From 33c89be3b72c1c3cae20a12b13da9ee6c723e31c Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Thu, 27 Aug 2020 18:36:42 -0400 Subject: [PATCH 0001/2500] [dev.fuzz] testing: add basic go command support for fuzzing This change adds support for a -fuzz flag in the go command, and sets up the groundwork for native fuzzing support. These functions are no-ops for now, but will be built out and tested in future PRs. Change-Id: I58e78eceada5799bcb73acc4ae5a20372badbf40 Reviewed-on: https://go-review.googlesource.com/c/go/+/251441 Run-TryBot: Katie Hockman TryBot-Result: Gobot Gobot Reviewed-by: Jay Conrod --- api/except.txt | 1 + api/next.txt | 33 +++++ src/cmd/go/internal/load/test.go | 15 +- src/cmd/go/internal/test/flagdefs.go | 1 + src/cmd/go/internal/test/test.go | 2 + src/cmd/go/internal/test/testflag.go | 1 + src/go/doc/example.go | 16 +-- src/go/doc/example_test.go | 6 + src/testing/fuzz.go | 196 +++++++++++++++++++++++++++ src/testing/testing.go | 47 +++++-- 10 files changed, 295 insertions(+), 23 deletions(-) create mode 100644 src/testing/fuzz.go diff --git a/api/except.txt b/api/except.txt index 962bb14271..662fa16f81 100644 --- a/api/except.txt +++ b/api/except.txt @@ -350,6 +350,7 @@ pkg syscall (openbsd-amd64-cgo), type Timespec struct, Pad_cgo_0 [4]uint8 pkg syscall (openbsd-amd64-cgo), type Timespec struct, Sec int32 pkg testing, func RegisterCover(Cover) pkg testing, func MainStart(func(string, string) (bool, error), []InternalTest, []InternalBenchmark, []InternalExample) *M +pkg testing, func MainStart(testDeps, []InternalTest, []InternalBenchmark, []InternalExample) *M pkg text/template/parse, type DotNode bool pkg text/template/parse, type Node interface { Copy, String, Type } pkg unicode, const Version = "6.2.0" diff --git a/api/next.txt b/api/next.txt index 076f39ec34..71fdaddc08 100644 --- a/api/next.txt +++ b/api/next.txt @@ -17,3 +17,36 @@ pkg text/template/parse, type CommentNode struct, embedded NodeType pkg text/template/parse, type CommentNode struct, embedded Pos pkg text/template/parse, type Mode uint pkg text/template/parse, type Tree struct, Mode Mode +pkg testing, func Fuzz(func(*F)) FuzzResult +pkg testing, func MainStart(testDeps, []InternalTest, []InternalBenchmark, []InternalFuzzTarget, []InternalExample) *M +pkg testing, func RunFuzzTargets(func(string, string) (bool, error), []InternalFuzzTarget) bool +pkg testing, func RunFuzzing(func(string, string) (bool, error), []InternalFuzzTarget) bool +pkg testing, method (*F) Add(...interface{}) +pkg testing, method (*F) Cleanup(func()) +pkg testing, method (*F) Error(...interface{}) +pkg testing, method (*F) Errorf(string, ...interface{}) +pkg testing, method (*F) Fail() +pkg testing, method (*F) FailNow() +pkg testing, method (*F) Failed() bool +pkg testing, method (*F) Fatal(...interface{}) +pkg testing, method (*F) Fatalf(string, ...interface{}) +pkg testing, method (*F) Fuzz(interface{}) +pkg testing, method (*F) Helper() +pkg testing, method (*F) Log(...interface{}) +pkg testing, method (*F) Logf(string, ...interface{}) +pkg testing, method (*F) Name() string +pkg testing, method (*F) Skip(...interface{}) +pkg testing, method (*F) SkipNow() +pkg testing, method (*F) Skipf(string, ...interface{}) +pkg testing, method (*F) Skipped() bool +pkg testing, method (*F) TempDir() string +pkg testing, method (FuzzResult) String() string +pkg testing, type F struct +pkg testing, type FuzzResult struct +pkg testing, type FuzzResult struct, Crasher entry +pkg testing, type FuzzResult struct, Error error +pkg testing, type FuzzResult struct, N int +pkg testing, type FuzzResult struct, T time.Duration +pkg testing, type InternalFuzzTarget struct +pkg testing, type InternalFuzzTarget struct, Fn func(*F) +pkg testing, type InternalFuzzTarget struct, Name string \ No newline at end of file diff --git a/src/cmd/go/internal/load/test.go b/src/cmd/go/internal/load/test.go index e0f13323df..93ec5facc5 100644 --- a/src/cmd/go/internal/load/test.go +++ b/src/cmd/go/internal/load/test.go @@ -496,6 +496,7 @@ func formatTestmain(t *testFuncs) ([]byte, error) { type testFuncs struct { Tests []testFunc Benchmarks []testFunc + FuzzTargets []testFunc Examples []testFunc TestMain *testFunc Package *Package @@ -588,6 +589,12 @@ func (t *testFuncs) load(filename, pkg string, doImport, seen *bool) error { } t.Benchmarks = append(t.Benchmarks, testFunc{pkg, name, "", false}) *doImport, *seen = true, true + case isTest(name, "Fuzz"): + err := checkTestFunc(n, "F") + if err != nil { + return err + } + t.FuzzTargets = append(t.FuzzTargets, testFunc{pkg, name, "", false}) } } ex := doc.Examples(f) @@ -651,6 +658,12 @@ var benchmarks = []testing.InternalBenchmark{ {{end}} } +var fuzzTargets = []testing.InternalFuzzTarget{ +{{range .FuzzTargets}} + {"{{.Name}}", {{.Package}}.{{.Name}}}, +{{end}} +} + var examples = []testing.InternalExample{ {{range .Examples}} {"{{.Name}}", {{.Package}}.{{.Name}}, {{.Output | printf "%q"}}, {{.Unordered}}}, @@ -709,7 +722,7 @@ func main() { CoveredPackages: {{printf "%q" .Covered}}, }) {{end}} - m := testing.MainStart(testdeps.TestDeps{}, tests, benchmarks, examples) + m := testing.MainStart(testdeps.TestDeps{}, tests, benchmarks, fuzzTargets, examples) {{with .TestMain}} {{.Package}}.{{.Name}}(m) os.Exit(int(reflect.ValueOf(m).Elem().FieldByName("exitCode").Int())) diff --git a/src/cmd/go/internal/test/flagdefs.go b/src/cmd/go/internal/test/flagdefs.go index 8a0a07683b..57e60e2c0c 100644 --- a/src/cmd/go/internal/test/flagdefs.go +++ b/src/cmd/go/internal/test/flagdefs.go @@ -19,6 +19,7 @@ var passFlagToTest = map[string]bool{ "cpu": true, "cpuprofile": true, "failfast": true, + "fuzz": true, "list": true, "memprofile": true, "memprofilerate": true, diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 1ea6d2881e..721236ca36 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -467,6 +467,7 @@ See the documentation of the testing package for more information. `, } +// TODO(katiehockman): complete the testing here var ( testBench string // -bench flag testC bool // -c flag @@ -475,6 +476,7 @@ var ( testCoverPaths []string // -coverpkg flag testCoverPkgs []*load.Package // -coverpkg flag testCoverProfile string // -coverprofile flag + testFuzz string // -fuzz flag testJSON bool // -json flag testList string // -list flag testO string // -o flag diff --git a/src/cmd/go/internal/test/testflag.go b/src/cmd/go/internal/test/testflag.go index 4f0a8924f1..620dea646b 100644 --- a/src/cmd/go/internal/test/testflag.go +++ b/src/cmd/go/internal/test/testflag.go @@ -56,6 +56,7 @@ func init() { cf.String("cpu", "", "") cf.StringVar(&testCPUProfile, "cpuprofile", "", "") cf.Bool("failfast", false, "") + cf.String("fuzz", "", "") cf.StringVar(&testList, "list", "", "") cf.StringVar(&testMemProfile, "memprofile", "", "") cf.String("memprofilerate", "", "") diff --git a/src/go/doc/example.go b/src/go/doc/example.go index 125fd530b1..094d7ba61b 100644 --- a/src/go/doc/example.go +++ b/src/go/doc/example.go @@ -44,13 +44,13 @@ type Example struct { // identifiers from other packages (or predeclared identifiers, such as // "int") and the test file does not include a dot import. // - The entire test file is the example: the file contains exactly one -// example function, zero test or benchmark functions, and at least one -// top-level function, type, variable, or constant declaration other -// than the example function. +// example function, zero test, fuzz target, or benchmark function, and at +// least one top-level function, type, variable, or constant declaration +// other than the example function. func Examples(testFiles ...*ast.File) []*Example { var list []*Example for _, file := range testFiles { - hasTests := false // file contains tests or benchmarks + hasTests := false // file contains tests, fuzz targets, or benchmarks numDecl := 0 // number of non-import declarations in the file var flist []*Example for _, decl := range file.Decls { @@ -64,7 +64,7 @@ func Examples(testFiles ...*ast.File) []*Example { } numDecl++ name := f.Name.Name - if isTest(name, "Test") || isTest(name, "Benchmark") { + if isTest(name, "Test") || isTest(name, "Benchmark") || isTest(name, "Fuzz") { hasTests = true continue } @@ -133,9 +133,9 @@ func exampleOutput(b *ast.BlockStmt, comments []*ast.CommentGroup) (output strin return "", false, false // no suitable comment found } -// isTest tells whether name looks like a test, example, or benchmark. -// It is a Test (say) if there is a character after Test that is not a -// lower-case letter. (We don't want Testiness.) +// isTest tells whether name looks like a test, example, fuzz target, or +// benchmark. It is a Test (say) if there is a character after Test that is not +// a lower-case letter. (We don't want Testiness.) func isTest(name, prefix string) bool { if !strings.HasPrefix(name, prefix) { return false diff --git a/src/go/doc/example_test.go b/src/go/doc/example_test.go index 7c96f0300a..2d9b95803b 100644 --- a/src/go/doc/example_test.go +++ b/src/go/doc/example_test.go @@ -307,6 +307,9 @@ func (X) TestBlah() { func (X) BenchmarkFoo() { } +func (X) FuzzFoo() { +} + func Example() { fmt.Println("Hello, world!") // Output: Hello, world! @@ -326,6 +329,9 @@ func (X) TestBlah() { func (X) BenchmarkFoo() { } +func (X) FuzzFoo() { +} + func main() { fmt.Println("Hello, world!") } diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go new file mode 100644 index 0000000000..aaa4ad1931 --- /dev/null +++ b/src/testing/fuzz.go @@ -0,0 +1,196 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testing + +import ( + "flag" + "fmt" + "os" + "time" +) + +func initFuzzFlags() { + matchFuzz = flag.String("test.fuzz", "", "run the fuzz target matching `regexp`") +} + +var matchFuzz *string + +// InternalFuzzTarget is an internal type but exported because it is cross-package; +// it is part of the implementation of the "go test" command. +type InternalFuzzTarget struct { + Name string + Fn func(f *F) +} + +// F is a type passed to fuzz targets for fuzz testing. +type F struct { + common + context *fuzzContext + corpus []corpusEntry // corpus is the in-memory corpus + result FuzzResult // result is the result of running the fuzz target + fuzzFunc func(f *F) // fuzzFunc is the function which makes up the fuzz target + fuzz bool // fuzz indicates whether or not the fuzzing engine should run +} + +// corpus corpusEntry +type corpusEntry struct { + b []byte +} + +// Add will add the arguments to the seed corpus for the fuzz target. This +// cannot be invoked after or within the Fuzz function. The args must match +// those in the Fuzz function. +func (f *F) Add(args ...interface{}) { + return +} + +// Fuzz runs the fuzz function, ff, for fuzz testing. It runs ff in a separate +// goroutine. Only one call to Fuzz is allowed per fuzz target, and any +// subsequent calls will panic. If ff fails for a set of arguments, those +// arguments will be added to the seed corpus. +func (f *F) Fuzz(ff interface{}) { + return +} + +// FuzzResult contains the results of a fuzz run. +type FuzzResult struct { + N int // The number of iterations. + T time.Duration // The total time taken. + Crasher corpusEntry // Crasher is the corpus entry that caused the crash + Error error // Error is the error from the crash +} + +func (r FuzzResult) String() string { + s := "" + if len(r.Error.Error()) != 0 { + s = fmt.Sprintf("error: %s\ncrasher: %b", r.Error.Error(), r.Crasher) + } + return s +} + +// fuzzContext holds all fields that are common to all fuzz targets. +type fuzzContext struct { + runMatch *matcher + fuzzMatch *matcher +} + +// RunFuzzTargets is an internal function but exported because it is cross-package; +// it is part of the implementation of the "go test" command. +func RunFuzzTargets(matchString func(pat, str string) (bool, error), fuzzTargets []InternalFuzzTarget) (ok bool) { + _, ok = runFuzzTargets(matchString, fuzzTargets) + return ok +} + +// runFuzzTargets runs the fuzz targets matching the pattern for -run. This will +// only run the f.Fuzz function for each seed corpus without using the fuzzing +// engine to generate or mutate inputs. If -fuzz matches a given fuzz target, +// then such test will be skipped and run later during fuzzing. +func runFuzzTargets(matchString func(pat, str string) (bool, error), fuzzTargets []InternalFuzzTarget) (ran, ok bool) { + ran, ok = true, true + if len(fuzzTargets) == 0 { + return false, ok + } + for _, ft := range fuzzTargets { + ctx := &fuzzContext{runMatch: newMatcher(matchString, *match, "-test.run")} + f := &F{ + common: common{ + signal: make(chan bool), + barrier: make(chan bool), + w: os.Stdout, + name: ft.Name, + }, + context: ctx, + } + testName, matched, _ := ctx.runMatch.fullName(&f.common, f.name) + if !matched { + continue + } + if *matchFuzz != "" { + ctx.fuzzMatch = newMatcher(matchString, *matchFuzz, "-test.fuzz") + if _, doFuzz, partial := ctx.fuzzMatch.fullName(&f.common, f.name); doFuzz && !partial { + continue // this will be run later when fuzzed + } + } + if Verbose() { + f.chatty = newChattyPrinter(f.w) + } + if f.chatty != nil { + f.chatty.Updatef(f.name, "=== RUN %s\n", testName) + } + } + return ran, ok +} + +// RunFuzzing is an internal function but exported because it is cross-package; +// it is part of the implementation of the "go test" command. +func RunFuzzing(matchString func(pat, str string) (bool, error), fuzzTargets []InternalFuzzTarget) (ok bool) { + _, ok = runFuzzing(matchString, fuzzTargets) + return ok +} + +// runFuzzing runs the fuzz target matching the pattern for -fuzz. Only one such +// fuzz target must match. This will run the f.Fuzz function for each seed +// corpus and will run the fuzzing engine to generate and mutate new inputs +// against f.Fuzz. +func runFuzzing(matchString func(pat, str string) (bool, error), fuzzTargets []InternalFuzzTarget) (ran, ok bool) { + ran, ok = true, true + if len(fuzzTargets) == 0 { + return false, ok + } + ctx := &fuzzContext{ + fuzzMatch: newMatcher(matchString, *matchFuzz, "-test.fuzz"), + } + if *matchFuzz == "" { + return false, true + } + f := &F{ + common: common{ + signal: make(chan bool), + barrier: make(chan bool), + w: os.Stdout, + }, + context: ctx, + fuzz: true, + } + var ( + ft InternalFuzzTarget + found int + ) + for _, ft = range fuzzTargets { + testName, matched, _ := ctx.fuzzMatch.fullName(&f.common, ft.Name) + if matched { + found++ + if found > 1 { + fmt.Fprintf(f.w, "testing: warning: -fuzz matched more than one target, won't run\n") + return false, ok + } + f.name = testName + } + } + if Verbose() { + f.chatty = newChattyPrinter(f.w) + } + if f.chatty != nil { + f.chatty.Updatef(f.name, "--- FUZZ %s\n", f.name) + } + return ran, ok +} + +// Fuzz runs a single fuzz target. It is useful for creating +// custom fuzz targets that do not use the "go test" command. +// +// If fn depends on testing flags, then Init must be used to register +// those flags before calling Fuzz and before calling flag.Parse. +func Fuzz(fn func(f *F)) FuzzResult { + f := &F{ + common: common{ + signal: make(chan bool), + w: discard{}, + }, + fuzzFunc: fn, + } + // TODO(katiehockman): run the test + return f.result +} diff --git a/src/testing/testing.go b/src/testing/testing.go index 66f296234a..3e0d2b689e 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -302,6 +302,7 @@ func Init() { testlog = flag.String("test.testlogfile", "", "write test action log to `file` (for use only by cmd/go)") initBenchmarkFlags() + initFuzzFlags() } var ( @@ -1294,15 +1295,16 @@ func (f matchStringOnly) SetPanicOnExit0(bool) {} // new functionality is added to the testing package. // Systems simulating "go test" should be updated to use MainStart. func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) { - os.Exit(MainStart(matchStringOnly(matchString), tests, benchmarks, examples).Run()) + os.Exit(MainStart(matchStringOnly(matchString), tests, benchmarks, nil, examples).Run()) } // M is a type passed to a TestMain function to run the actual tests. type M struct { - deps testDeps - tests []InternalTest - benchmarks []InternalBenchmark - examples []InternalExample + deps testDeps + tests []InternalTest + benchmarks []InternalBenchmark + fuzzTargets []InternalFuzzTarget + examples []InternalExample timer *time.Timer afterOnce sync.Once @@ -1332,13 +1334,14 @@ type testDeps interface { // MainStart is meant for use by tests generated by 'go test'. // It is not meant to be called directly and is not subject to the Go 1 compatibility document. // It may change signature from release to release. -func MainStart(deps testDeps, tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) *M { +func MainStart(deps testDeps, tests []InternalTest, benchmarks []InternalBenchmark, fuzzTargets []InternalFuzzTarget, examples []InternalExample) *M { Init() return &M{ - deps: deps, - tests: tests, - benchmarks: benchmarks, - examples: examples, + deps: deps, + tests: tests, + benchmarks: benchmarks, + fuzzTargets: fuzzTargets, + examples: examples, } } @@ -1367,7 +1370,7 @@ func (m *M) Run() (code int) { } if len(*matchList) != 0 { - listTests(m.deps.MatchString, m.tests, m.benchmarks, m.examples) + listTests(m.deps.MatchString, m.tests, m.benchmarks, m.fuzzTargets, m.examples) m.exitCode = 0 return } @@ -1379,12 +1382,23 @@ func (m *M) Run() (code int) { deadline := m.startAlarm() haveExamples = len(m.examples) > 0 testRan, testOk := runTests(m.deps.MatchString, m.tests, deadline) + fuzzTargetsRan, fuzzTargetsOk := runFuzzTargets(m.deps.MatchString, m.fuzzTargets) exampleRan, exampleOk := runExamples(m.deps.MatchString, m.examples) m.stopAlarm() - if !testRan && !exampleRan && *matchBenchmarks == "" { + if !testRan && !exampleRan && !fuzzTargetsRan && *matchBenchmarks == "" && *matchFuzz == "" { fmt.Fprintln(os.Stderr, "testing: warning: no tests to run") } - if !testOk || !exampleOk || !runBenchmarks(m.deps.ImportPath(), m.deps.MatchString, m.benchmarks) || race.Errors() > 0 { + if !testOk || !exampleOk || !fuzzTargetsOk || !runBenchmarks(m.deps.ImportPath(), m.deps.MatchString, m.benchmarks) || race.Errors() > 0 { + fmt.Println("FAIL") + m.exitCode = 1 + return + } + + fuzzingRan, fuzzingOk := runFuzzing(m.deps.MatchString, m.fuzzTargets) + if *matchFuzz != "" && !fuzzingRan { + fmt.Fprintln(os.Stderr, "testing: warning: no fuzz targets to run") + } + if !fuzzingOk { fmt.Println("FAIL") m.exitCode = 1 return @@ -1412,7 +1426,7 @@ func (t *T) report() { } } -func listTests(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) { +func listTests(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, fuzzTargets []InternalFuzzTarget, examples []InternalExample) { if _, err := matchString(*matchList, "non-empty"); err != nil { fmt.Fprintf(os.Stderr, "testing: invalid regexp in -test.list (%q): %s\n", *matchList, err) os.Exit(1) @@ -1428,6 +1442,11 @@ func listTests(matchString func(pat, str string) (bool, error), tests []Internal fmt.Println(bench.Name) } } + for _, fuzzTarget := range fuzzTargets { + if ok, _ := matchString(*matchList, fuzzTarget.Name); ok { + fmt.Println(fuzzTarget.Name) + } + } for _, example := range examples { if ok, _ := matchString(*matchList, example.Name); ok { fmt.Println(example.Name) -- GitLab From 2a9036fe7e3c8f62bf80c857534dc142a4248f37 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Fri, 11 Sep 2020 11:11:08 -0400 Subject: [PATCH 0002/2500] [dev.fuzz] testing: add script tests for fuzz targets Tests include: - matching fuzz targets - matching fuzz targets with -fuzz - chatty tests with -v - failing tests - skipped tests - passing tests - panic in tests Change-Id: I54e63c8891b45cfae7212924e067e790f25ab411 Reviewed-on: https://go-review.googlesource.com/c/go/+/254360 Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod Trust: Jay Conrod Trust: Katie Hockman --- src/cmd/go/internal/load/test.go | 1 + src/cmd/go/internal/test/test.go | 8 + src/cmd/go/testdata/script/test_fuzz.txt | 56 +++++++ .../go/testdata/script/test_fuzz_chatty.txt | 64 ++++++++ .../go/testdata/script/test_fuzz_match.txt | 54 +++++++ src/testing/fuzz.go | 146 ++++++++++++------ src/testing/testing.go | 2 +- 7 files changed, 283 insertions(+), 48 deletions(-) create mode 100644 src/cmd/go/testdata/script/test_fuzz.txt create mode 100644 src/cmd/go/testdata/script/test_fuzz_chatty.txt create mode 100644 src/cmd/go/testdata/script/test_fuzz_match.txt diff --git a/src/cmd/go/internal/load/test.go b/src/cmd/go/internal/load/test.go index 93ec5facc5..d4453846e6 100644 --- a/src/cmd/go/internal/load/test.go +++ b/src/cmd/go/internal/load/test.go @@ -595,6 +595,7 @@ func (t *testFuncs) load(filename, pkg string, doImport, seen *bool) error { return err } t.FuzzTargets = append(t.FuzzTargets, testFunc{pkg, name, "", false}) + *doImport, *seen = true, true } } ex := doc.Examples(f) diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 721236ca36..109acb53da 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -1064,6 +1064,8 @@ func declareCoverVars(p *load.Package, files ...string) map[string]*load.CoverVa } var noTestsToRun = []byte("\ntesting: warning: no tests to run\n") +var noTargetsToFuzz = []byte("\ntesting: warning: no targets to fuzz\n") +var tooManyTargetsToFuzz = []byte("\ntesting: warning: -fuzz matches more than one target, won't fuzz\n") type runCache struct { disableCache bool // cache should be disabled for this run @@ -1260,6 +1262,12 @@ func (c *runCache) builderRunTest(b *work.Builder, ctx context.Context, a *work. if bytes.HasPrefix(out, noTestsToRun[1:]) || bytes.Contains(out, noTestsToRun) { norun = " [no tests to run]" } + if bytes.HasPrefix(out, noTargetsToFuzz[1:]) || bytes.Contains(out, noTargetsToFuzz) { + norun = " [no targets to fuzz]" + } + if bytes.HasPrefix(out, tooManyTargetsToFuzz[1:]) || bytes.Contains(out, tooManyTargetsToFuzz) { + norun = " [will not fuzz, -fuzz matches more than one target]" + } fmt.Fprintf(cmd.Stdout, "ok \t%s\t%s%s%s\n", a.Package.ImportPath, t, coveragePercentage(out), norun) c.saveOutput(a) } else { diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt new file mode 100644 index 0000000000..68e5041822 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -0,0 +1,56 @@ +# Test that calling f.Fatal in a fuzz target causes a non-zero exit status. +! go test fail_fuzz_test.go +! stdout ^ok +stdout FAIL + +# Test that successful test exits cleanly. +go test success_fuzz_test.go +stdout ok +! stdout FAIL + +[short] stop + +# Test that calling panic(nil) in a fuzz target causes a non-zero exit status. +! go test panic_fuzz_test.go +! stdout ^ok +stdout FAIL + +# Test that skipped test exits cleanly. +go test skipped_fuzz_test.go +stdout ok +! stdout FAIL + +-- fail_fuzz_test.go -- +package fail_fuzz + +import "testing" + +func FuzzFail(f *testing.F) { + f.Fatal("fatal in target") +} + +-- panic_fuzz_test.go -- +package panic_fuzz + +import "testing" + +func FuzzPanic(f *testing.F) { + panic(nil) +} + +-- success_fuzz_test.go -- +package success_fuzz + +import "testing" + +func Fuzz(f *testing.F) { +} + +-- skipped_fuzz_test.go -- +package skipped_fuzz + +import "testing" + +func Fuzz(f *testing.F) { + f.Skip() +} diff --git a/src/cmd/go/testdata/script/test_fuzz_chatty.txt b/src/cmd/go/testdata/script/test_fuzz_chatty.txt new file mode 100644 index 0000000000..56b20bedad --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_chatty.txt @@ -0,0 +1,64 @@ +[short] skip + +# Run chatty fuzz targets with an error and fatal. +! go test -v chatty_fail_fuzz_test.go +! stdout '^ok' +stdout 'FAIL' +stdout 'error in target' +stdout 'fatal in target' + +# Run chatty fuzz target with a panic +! go test -v chatty_panic_fuzz_test.go +! stdout ^ok +stdout FAIL +stdout 'this is bad' + +# Run skipped chatty fuzz targets. +go test -v chatty_skipped_fuzz_test.go +stdout ok +stdout SKIP +! stdout FAIL + +# Run successful chatty fuzz targets. +go test -v chatty_fuzz_test.go +stdout ok +stdout PASS +stdout 'all good here' +! stdout FAIL + +-- chatty_fail_fuzz_test.go -- +package chatty_fail_fuzz + +import "testing" + +func Fuzz(f *testing.F) { + f.Error("error in target") + f.Fatal("fatal in target") +} + +-- chatty_panic_fuzz_test.go -- +package chatty_panic_fuzz + +import "testing" + +func Fuzz(f *testing.F) { + panic("this is bad") +} + +-- chatty_skipped_fuzz_test.go -- +package chatty_skipped_fuzz + +import "testing" + +func Fuzz(f *testing.F) { + f.Skip() +} + +-- chatty_fuzz_test.go -- +package chatty_fuzz + +import "testing" + +func Fuzz(f *testing.F) { + f.Log("all good here") +} diff --git a/src/cmd/go/testdata/script/test_fuzz_match.txt b/src/cmd/go/testdata/script/test_fuzz_match.txt new file mode 100644 index 0000000000..da7e7f13ab --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_match.txt @@ -0,0 +1,54 @@ +# Matches only fuzz targets to test. +go test standalone_fuzz_test.go +! stdout '^ok.*\[no tests to run\]' +stdout '^ok' + +# Matches only for fuzzing. +go test -fuzz Fuzz standalone_fuzz_test.go +! stdout '^ok.*\[no tests to run\]' +stdout '^ok' + +# Matches none for fuzzing but will run the fuzz target as a test. +go test -fuzz ThisWillNotMatch standalone_fuzz_test.go +! stdout '^ok.*\[no tests to run\]' +stdout ok +stdout '\[no targets to fuzz\]' + +[short] stop + +# Matches only fuzz targets to test with -run. +go test -run Fuzz standalone_fuzz_test.go +! stdout '^ok.*\[no tests to run\]' +stdout '^ok' + +# Matches no fuzz targets. +go test -run ThisWillNotMatch standalone_fuzz_test.go +stdout '^ok.*\[no tests to run\]' +! stdout '\[no targets to fuzz\]' + +# Matches more than one fuzz target for fuzzing. +go test -fuzz Fuzz multiple_fuzz_test.go +# The tests should run, but not be fuzzed +! stdout '\[no tests to run\]' +! stdout '\[no targets to fuzz\]' +stdout ok +stdout '\[will not fuzz, -fuzz matches more than one target\]' + +-- standalone_fuzz_test.go -- +package standalone_fuzz + +import "testing" + +func Fuzz(f *testing.F) { +} + +-- multiple_fuzz_test.go -- +package multiple_fuzz + +import "testing" + +func FuzzA(f *testing.F) { +} + +func FuzzB(f *testing.F) { +} \ No newline at end of file diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index aaa4ad1931..f5162115b4 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -54,18 +54,79 @@ func (f *F) Fuzz(ff interface{}) { return } +func (f *F) report(name string) { + if f.Failed() { + fmt.Fprintf(f.w, "--- FAIL: %s\n%s\n", name, f.result.String()) + } else if f.chatty != nil { + if f.Skipped() { + f.chatty.Updatef(name, "SKIP\n") + } else { + f.chatty.Updatef(name, "PASS\n") + } + } +} + +// run runs each fuzz target in its own goroutine with its own *F. +func (f *F) run(name string, fn func(f *F)) (ran, ok bool) { + innerF := &F{ + common: common{ + signal: make(chan bool), + name: name, + chatty: f.chatty, + w: f.w, + }, + context: f.context, + } + if innerF.chatty != nil { + if f.fuzz { + innerF.chatty.Updatef(name, "--- FUZZ: %s\n", name) + } else { + innerF.chatty.Updatef(name, "=== RUN %s\n", name) + } + } + go runTarget(innerF, fn) + <-innerF.signal + return innerF.ran, !innerF.failed +} + +// runTarget runs the given target, handling panics and exits +// within the test, and reporting errors. +func runTarget(f *F, fn func(f *F)) { + defer func() { + err := recover() + // If the function has recovered but the test hasn't finished, + // it is due to a nil panic or runtime.GoExit. + if !f.finished && err == nil { + err = errNilPanicOrGoexit + } + if err != nil { + f.Fail() + f.result = FuzzResult{Error: fmt.Errorf("%s", err)} + } + f.report(f.name) + f.setRan() + f.signal <- true // signal that the test has finished + }() + fn(f) + f.finished = true +} + // FuzzResult contains the results of a fuzz run. type FuzzResult struct { N int // The number of iterations. T time.Duration // The total time taken. - Crasher corpusEntry // Crasher is the corpus entry that caused the crash + Crasher *corpusEntry // Crasher is the corpus entry that caused the crash Error error // Error is the error from the crash } func (r FuzzResult) String() string { s := "" - if len(r.Error.Error()) != 0 { - s = fmt.Sprintf("error: %s\ncrasher: %b", r.Error.Error(), r.Crasher) + if r.Error == nil { + return s + } + s = fmt.Sprintf("error: %s", r.Error.Error()) + if r.Crasher != nil { + s += fmt.Sprintf("\ncrasher: %b", r.Crasher) } return s } @@ -85,41 +146,37 @@ func RunFuzzTargets(matchString func(pat, str string) (bool, error), fuzzTargets // runFuzzTargets runs the fuzz targets matching the pattern for -run. This will // only run the f.Fuzz function for each seed corpus without using the fuzzing -// engine to generate or mutate inputs. If -fuzz matches a given fuzz target, -// then such test will be skipped and run later during fuzzing. +// engine to generate or mutate inputs. func runFuzzTargets(matchString func(pat, str string) (bool, error), fuzzTargets []InternalFuzzTarget) (ran, ok bool) { - ran, ok = true, true + ok = true if len(fuzzTargets) == 0 { - return false, ok + return ran, ok } + ctx := &fuzzContext{runMatch: newMatcher(matchString, *match, "-test.run")} + var fts []InternalFuzzTarget for _, ft := range fuzzTargets { - ctx := &fuzzContext{runMatch: newMatcher(matchString, *match, "-test.run")} - f := &F{ - common: common{ - signal: make(chan bool), - barrier: make(chan bool), - w: os.Stdout, - name: ft.Name, - }, - context: ctx, - } - testName, matched, _ := ctx.runMatch.fullName(&f.common, f.name) - if !matched { - continue + if _, matched, _ := ctx.runMatch.fullName(nil, ft.Name); matched { + fts = append(fts, ft) } - if *matchFuzz != "" { - ctx.fuzzMatch = newMatcher(matchString, *matchFuzz, "-test.fuzz") - if _, doFuzz, partial := ctx.fuzzMatch.fullName(&f.common, f.name); doFuzz && !partial { - continue // this will be run later when fuzzed + } + f := &F{ + common: common{ + w: os.Stdout, + }, + fuzzFunc: func(f *F) { + for _, ft := range fts { + // Run each fuzz target in it's own goroutine. + ftRan, ftOk := f.run(ft.Name, ft.Fn) + ran = ran || ftRan + ok = ok && ftOk } - } - if Verbose() { - f.chatty = newChattyPrinter(f.w) - } - if f.chatty != nil { - f.chatty.Updatef(f.name, "=== RUN %s\n", testName) - } + }, + context: ctx, } + if Verbose() { + f.chatty = newChattyPrinter(f.w) + } + f.fuzzFunc(f) return ran, ok } @@ -131,13 +188,11 @@ func RunFuzzing(matchString func(pat, str string) (bool, error), fuzzTargets []I } // runFuzzing runs the fuzz target matching the pattern for -fuzz. Only one such -// fuzz target must match. This will run the f.Fuzz function for each seed -// corpus and will run the fuzzing engine to generate and mutate new inputs -// against f.Fuzz. +// fuzz target must match. This will run the fuzzing engine to generate and +// mutate new inputs against the f.Fuzz function. func runFuzzing(matchString func(pat, str string) (bool, error), fuzzTargets []InternalFuzzTarget) (ran, ok bool) { - ran, ok = true, true if len(fuzzTargets) == 0 { - return false, ok + return false, true } ctx := &fuzzContext{ fuzzMatch: newMatcher(matchString, *matchFuzz, "-test.fuzz"), @@ -147,9 +202,7 @@ func runFuzzing(matchString func(pat, str string) (bool, error), fuzzTargets []I } f := &F{ common: common{ - signal: make(chan bool), - barrier: make(chan bool), - w: os.Stdout, + w: os.Stdout, }, context: ctx, fuzz: true, @@ -163,19 +216,19 @@ func runFuzzing(matchString func(pat, str string) (bool, error), fuzzTargets []I if matched { found++ if found > 1 { - fmt.Fprintf(f.w, "testing: warning: -fuzz matched more than one target, won't run\n") - return false, ok + fmt.Fprintln(os.Stderr, "testing: warning: -fuzz matches more than one target, won't fuzz") + return false, true } f.name = testName } } + if found == 0 { + return false, true + } if Verbose() { f.chatty = newChattyPrinter(f.w) } - if f.chatty != nil { - f.chatty.Updatef(f.name, "--- FUZZ %s\n", f.name) - } - return ran, ok + return f.run(ft.Name, ft.Fn) } // Fuzz runs a single fuzz target. It is useful for creating @@ -186,8 +239,7 @@ func runFuzzing(matchString func(pat, str string) (bool, error), fuzzTargets []I func Fuzz(fn func(f *F)) FuzzResult { f := &F{ common: common{ - signal: make(chan bool), - w: discard{}, + w: discard{}, }, fuzzFunc: fn, } diff --git a/src/testing/testing.go b/src/testing/testing.go index 3e0d2b689e..4fd628c0ff 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1396,7 +1396,7 @@ func (m *M) Run() (code int) { fuzzingRan, fuzzingOk := runFuzzing(m.deps.MatchString, m.fuzzTargets) if *matchFuzz != "" && !fuzzingRan { - fmt.Fprintln(os.Stderr, "testing: warning: no fuzz targets to run") + fmt.Fprintln(os.Stderr, "testing: warning: no targets to fuzz") } if !fuzzingOk { fmt.Println("FAIL") -- GitLab From 5ce83d3bdaa97012150e7e20941d1a0ceb2cd7db Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Thu, 17 Sep 2020 10:28:18 -0400 Subject: [PATCH 0003/2500] [dev.fuzz] testing: small cleanup to running targets Change-Id: Idcf90c5acbf7dbba2ea01d21d893214a5c2028c2 Reviewed-on: https://go-review.googlesource.com/c/go/+/255517 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/testdata/script/test_fuzz.txt | 10 ++++++++++ src/testing/fuzz.go | 18 +++++++++--------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt index 68e5041822..24350ee450 100644 --- a/src/cmd/go/testdata/script/test_fuzz.txt +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -8,6 +8,16 @@ go test success_fuzz_test.go stdout ok ! stdout FAIL +# Test that calling f.Fatal while fuzzing causes a non-zero exit status. +! go test -fuzz Fuzz fail_fuzz_test.go +! stdout ^ok +stdout FAIL + +# Test that successful fuzzing exits cleanly. +go test -fuzz Fuzz success_fuzz_test.go +stdout ok +! stdout FAIL + [short] stop # Test that calling panic(nil) in a fuzz target causes a non-zero exit status. diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index f5162115b4..ee7f68e544 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -78,20 +78,16 @@ func (f *F) run(name string, fn func(f *F)) (ran, ok bool) { context: f.context, } if innerF.chatty != nil { - if f.fuzz { - innerF.chatty.Updatef(name, "--- FUZZ: %s\n", name) - } else { - innerF.chatty.Updatef(name, "=== RUN %s\n", name) - } + innerF.chatty.Updatef(name, "=== RUN %s\n", name) } - go runTarget(innerF, fn) + go innerF.runTarget(fn) <-innerF.signal return innerF.ran, !innerF.failed } // runTarget runs the given target, handling panics and exits // within the test, and reporting errors. -func runTarget(f *F, fn func(f *F)) { +func (f *F) runTarget(fn func(f *F)) { defer func() { err := recover() // If the function has recovered but the test hasn't finished, @@ -202,7 +198,8 @@ func runFuzzing(matchString func(pat, str string) (bool, error), fuzzTargets []I } f := &F{ common: common{ - w: os.Stdout, + signal: make(chan bool), + w: os.Stdout, }, context: ctx, fuzz: true, @@ -227,8 +224,11 @@ func runFuzzing(matchString func(pat, str string) (bool, error), fuzzTargets []I } if Verbose() { f.chatty = newChattyPrinter(f.w) + f.chatty.Updatef(f.name, "--- FUZZ: %s\n", f.name) } - return f.run(ft.Name, ft.Fn) + go f.runTarget(ft.Fn) + <-f.signal + return f.ran, !f.failed } // Fuzz runs a single fuzz target. It is useful for creating -- GitLab From dc8f16829a253dbbaffe278dcbf38534ced8403a Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Tue, 15 Sep 2020 15:13:31 -0400 Subject: [PATCH 0004/2500] [dev.fuzz] testing: add support for testing.F.Add of []byte Change-Id: I183693fec6a643b2f27cc379a422e2b42d8eca90 Reviewed-on: https://go-review.googlesource.com/c/go/+/255339 Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod Trust: Katie Hockman --- src/testing/fuzz.go | 19 +++++++++++++++--- src/testing/fuzz_test.go | 42 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 src/testing/fuzz_test.go diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index ee7f68e544..d159f2e425 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -39,11 +39,24 @@ type corpusEntry struct { b []byte } -// Add will add the arguments to the seed corpus for the fuzz target. This -// cannot be invoked after or within the Fuzz function. The args must match +// Add will add the arguments to the seed corpus for the fuzz target. This will +// be a no-op if called after or within the Fuzz function. The args must match // those in the Fuzz function. func (f *F) Add(args ...interface{}) { - return + if len(args) == 0 { + panic("testing: Add must have at least one argument") + } + if len(args) != 1 { + // TODO: support more than one argument + panic("testing: Add only supports one argument currently") + } + switch v := args[0].(type) { + case []byte: + f.corpus = append(f.corpus, corpusEntry{v}) + // TODO: support other types + default: + panic("testing: Add only supports []byte currently") + } } // Fuzz runs the fuzz function, ff, for fuzz testing. It runs ff in a separate diff --git a/src/testing/fuzz_test.go b/src/testing/fuzz_test.go new file mode 100644 index 0000000000..77a7d5ea4e --- /dev/null +++ b/src/testing/fuzz_test.go @@ -0,0 +1,42 @@ +package testing_test + +import ( + "testing" +) + +func TestFuzzAdd(t *testing.T) { + matchFunc := func(a, b string) (bool, error) { return true, nil } + tests := []struct { + name string + fn func(f *testing.F) + ok bool + }{ + { + "empty", + func(f *testing.F) { f.Add() }, + false, + }, + { + "multiple arguments", + func(f *testing.F) { f.Add([]byte("hello"), []byte("bye")) }, + false, + }, + { + "string", + func(f *testing.F) { f.Add("hello") }, + false, + }, + { + "bytes", + func(f *testing.F) { f.Add([]byte("hello")) }, + true, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + if got, want := testing.RunFuzzTargets(matchFunc, []testing.InternalFuzzTarget{{Fn: tc.fn}}), tc.ok; got != want { + t.Errorf("testing.Add: ok %t, want %t", got, want) + } + }) + } +} -- GitLab From aea29a9016cb5c3e160f94e6a95b197407de8c2c Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Fri, 18 Sep 2020 10:13:23 -0400 Subject: [PATCH 0005/2500] [dev.fuzz] testing: implement F.Fuzz to run seed corpus Change-Id: Ibd204a5d0596c4f8acf598289055c17a836d9023 Reviewed-on: https://go-review.googlesource.com/c/go/+/255957 Run-TryBot: Katie Hockman TryBot-Result: Go Bot Trust: Katie Hockman Trust: Jay Conrod Reviewed-by: Jay Conrod --- src/cmd/go/testdata/script/test_fuzz.txt | 122 +++++++++++++++++++++++ src/testing/fuzz.go | 86 +++++++++++++--- 2 files changed, 192 insertions(+), 16 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt index 24350ee450..ab93f5cc2e 100644 --- a/src/cmd/go/testdata/script/test_fuzz.txt +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -18,6 +18,12 @@ go test -fuzz Fuzz success_fuzz_test.go stdout ok ! stdout FAIL +# Test error with seed corpus in f.Fuzz +! go test -run FuzzError fuzz_add_test.go +! stdout ^ok +stdout FAIL +stdout 'error here' + [short] stop # Test that calling panic(nil) in a fuzz target causes a non-zero exit status. @@ -30,6 +36,39 @@ go test skipped_fuzz_test.go stdout ok ! stdout FAIL +# Test that multiple calls to f.Fuzz causes a non-zero exit status. +! go test multiple_fuzz_calls_fuzz_test.go +! stdout ^ok +stdout FAIL + +# Test that missing *T in f.Fuzz causes a non-zero exit status. +! go test incomplete_fuzz_call_fuzz_test.go +! stdout ^ok +stdout FAIL + +# Test success with seed corpus in f.Fuzz +go test -run FuzzPass fuzz_add_test.go +stdout ok +! stdout FAIL +! stdout 'off by one error' + +# Test fatal with seed corpus in f.Fuzz +! go test -run FuzzFatal fuzz_add_test.go +! stdout ^ok +stdout FAIL +stdout 'fatal here' + +# Test panic with seed corpus in f.Fuzz +! go test -run FuzzPanic fuzz_add_test.go +! stdout ^ok +stdout FAIL +stdout 'off by one error' + +# Test panic(nil) with seed corpus in f.Fuzz +! go test -run FuzzNilPanic fuzz_add_test.go +! stdout ^ok +stdout FAIL + -- fail_fuzz_test.go -- package fail_fuzz @@ -64,3 +103,86 @@ import "testing" func Fuzz(f *testing.F) { f.Skip() } + +-- multiple_fuzz_calls_fuzz_test.go -- +package multiple_fuzz_calls_fuzz + +import "testing" + +func Fuzz(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + // no-op + }) + + f.Fuzz(func(t *testing.T, b []byte) { + // this second call should panic + }) +} + +-- incomplete_fuzz_call_fuzz_test.go -- +package incomplete_fuzz_call_fuzz + +import "testing" + +func Fuzz(f *testing.F) { + f.Fuzz(func(b []byte) { + // this is missing *testing.T as the first param, so should panic + }) +} + +-- fuzz_add_test.go -- +package fuzz_add + +import "testing" + +func add(f *testing.F) { + f.Helper() + f.Add([]byte("123")) + f.Add([]byte("12345")) + f.Add([]byte("")) +} + +func FuzzPass(f *testing.F) { + add(f) + f.Fuzz(func(t *testing.T, b []byte) { + if len(b) == -1 { + t.Fatal("fatal here") // will not be executed + } + }) +} + +func FuzzError(f *testing.F) { + add(f) + f.Fuzz(func(t *testing.T, b []byte) { + if len(b) == 3 { + t.Error("error here") + } + }) +} + +func FuzzFatal(f *testing.F) { + add(f) + f.Fuzz(func(t *testing.T, b []byte) { + if len(b) == 0 { + t.Fatal("fatal here") + } + }) +} + +func FuzzPanic(f *testing.F) { + add(f) + f.Fuzz(func(t *testing.T, b []byte) { + if len(b) == 5 { + panic("off by one error") + } + }) +} + +func FuzzNilPanic(f *testing.F) { + add(f) + f.Fuzz(func(t *testing.T, b []byte) { + if len(b) == 3 { + panic(nil) + } + }) +} \ No newline at end of file diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index d159f2e425..6f985c7c38 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -5,6 +5,7 @@ package testing import ( + "errors" "flag" "fmt" "os" @@ -27,11 +28,12 @@ type InternalFuzzTarget struct { // F is a type passed to fuzz targets for fuzz testing. type F struct { common - context *fuzzContext - corpus []corpusEntry // corpus is the in-memory corpus - result FuzzResult // result is the result of running the fuzz target - fuzzFunc func(f *F) // fuzzFunc is the function which makes up the fuzz target - fuzz bool // fuzz indicates whether or not the fuzzing engine should run + context *fuzzContext + corpus []corpusEntry // corpus is the in-memory corpus + result FuzzResult // result is the result of running the fuzz target + fuzzFunc func(f *F) // fuzzFunc is the function which makes up the fuzz target + fuzz bool // fuzz indicates whether the fuzzing engine should run + fuzzCalled bool // fuzzCalled indicates whether f.Fuzz has been called for this target } // corpus corpusEntry @@ -60,21 +62,73 @@ func (f *F) Add(args ...interface{}) { } // Fuzz runs the fuzz function, ff, for fuzz testing. It runs ff in a separate -// goroutine. Only one call to Fuzz is allowed per fuzz target, and any -// subsequent calls will panic. If ff fails for a set of arguments, those -// arguments will be added to the seed corpus. +// goroutine. Only the first call to Fuzz will be executed, and any subsequent +// calls will panic. If ff fails for a set of arguments, those arguments will be +// added to the seed corpus. func (f *F) Fuzz(ff interface{}) { - return + if f.fuzzCalled { + panic("testing: found more than one call to Fuzz, will skip") + } + f.fuzzCalled = true + + fn, ok := ff.(func(*T, []byte)) + if !ok { + panic("testing: Fuzz function must have type func(*testing.T, []byte)") + } + + var errStr string + run := func(t *T, b []byte) { + defer func() { + err := recover() + // If the function has recovered but the test hasn't finished, + // it is due to a nil panic or runtime.GoExit. + if !t.finished && err == nil { + err = errNilPanicOrGoexit + } + if err != nil { + t.Fail() + t.output = []byte(fmt.Sprintf(" panic: %s\n", err)) + } + f.setRan() + t.signal <- true // signal that the test has finished + }() + fn(t, b) + t.finished = true + } + + // Run the seed corpus first + for _, c := range f.corpus { + t := &T{ + common: common{ + signal: make(chan bool), + w: f.w, + chatty: f.chatty, + }, + context: newTestContext(1, nil), + } + go run(t, c.b) + <-t.signal + if t.Failed() { + f.Fail() + errStr += string(t.output) + } + } + if f.Failed() { + f.result = FuzzResult{Error: errors.New(errStr)} + return + } + + // TODO: if f.fuzz is set, run fuzzing engine } -func (f *F) report(name string) { +func (f *F) report() { if f.Failed() { - fmt.Fprintf(f.w, "--- FAIL: %s\n%s\n", name, f.result.String()) + fmt.Fprintf(f.w, "--- FAIL: %s\n%s\n", f.name, f.result.String()) } else if f.chatty != nil { if f.Skipped() { - f.chatty.Updatef(name, "SKIP\n") + f.chatty.Updatef(f.name, "SKIP\n") } else { - f.chatty.Updatef(name, "PASS\n") + f.chatty.Updatef(f.name, "PASS\n") } } } @@ -100,7 +154,7 @@ func (f *F) run(name string, fn func(f *F)) (ran, ok bool) { // runTarget runs the given target, handling panics and exits // within the test, and reporting errors. -func (f *F) runTarget(fn func(f *F)) { +func (f *F) runTarget(fn func(*F)) { defer func() { err := recover() // If the function has recovered but the test hasn't finished, @@ -112,7 +166,7 @@ func (f *F) runTarget(fn func(f *F)) { f.Fail() f.result = FuzzResult{Error: fmt.Errorf("%s", err)} } - f.report(f.name) + f.report() f.setRan() f.signal <- true // signal that the test has finished }() @@ -133,7 +187,7 @@ func (r FuzzResult) String() string { if r.Error == nil { return s } - s = fmt.Sprintf("error: %s", r.Error.Error()) + s = fmt.Sprintf("%s", r.Error.Error()) if r.Crasher != nil { s += fmt.Sprintf("\ncrasher: %b", r.Crasher) } -- GitLab From 4fb2f3ca22de92e7ad6137fb988dcc1cd4449ceb Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Mon, 5 Oct 2020 14:24:21 -0400 Subject: [PATCH 0006/2500] [dev.fuzz] testing: panic if certain testing.F functions are called in Fuzz func Change-Id: I8ee513b2b157e6033d4bc9607d0e65f42bd6801f Reviewed-on: https://go-review.googlesource.com/c/go/+/259657 Trust: Katie Hockman Trust: Jay Conrod Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/testdata/script/test_fuzz.txt | 57 ++++++++++++++++++++++++ src/testing/fuzz.go | 7 ++- src/testing/testing.go | 37 +++++++++++++++ 3 files changed, 100 insertions(+), 1 deletion(-) diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt index ab93f5cc2e..d9aa718987 100644 --- a/src/cmd/go/testdata/script/test_fuzz.txt +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -36,6 +36,27 @@ go test skipped_fuzz_test.go stdout ok ! stdout FAIL +# Test that f.Fatal within f.Fuzz panics +! go test fatal_fuzz_fn_fuzz_test.go +! stdout ^ok +! stdout 'fatal here' +stdout FAIL +stdout illegal + +# Test that f.Error within f.Fuzz panics +! go test error_fuzz_fn_fuzz_test.go +! stdout ^ok +! stdout 'error here' +stdout FAIL +stdout illegal + +# Test that f.Skip within f.Fuzz panics +! go test skip_fuzz_fn_fuzz_test.go +! stdout ^ok +! stdout 'skip here' +stdout FAIL +stdout illegal + # Test that multiple calls to f.Fuzz causes a non-zero exit status. ! go test multiple_fuzz_calls_fuzz_test.go ! stdout ^ok @@ -104,6 +125,42 @@ func Fuzz(f *testing.F) { f.Skip() } +-- fatal_fuzz_fn_fuzz_test.go -- +package fatal_fuzz_fn_fuzz + +import "testing" + +func Fuzz(f *testing.F) { + f.Add([]byte("aa")) + f.Fuzz(func(t *testing.T, b []byte) { + f.Fatal("fatal here") + }) +} + +-- error_fuzz_fn_fuzz_test.go -- +package error_fuzz_fn_fuzz + +import "testing" + +func Fuzz(f *testing.F) { + f.Add([]byte("aa")) + f.Fuzz(func(t *testing.T, b []byte) { + f.Error("error here") + }) +} + +-- skip_fuzz_fn_fuzz_test.go -- +package skip_fuzz_fn_fuzz + +import "testing" + +func Fuzz(f *testing.F) { + f.Add([]byte("aa")) + f.Fuzz(func(t *testing.T, b []byte) { + f.Skip("skip here") + }) +} + -- multiple_fuzz_calls_fuzz_test.go -- package multiple_fuzz_calls_fuzz diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 6f985c7c38..01895e8d7d 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -87,11 +87,16 @@ func (f *F) Fuzz(ff interface{}) { } if err != nil { t.Fail() - t.output = []byte(fmt.Sprintf(" panic: %s\n", err)) + t.output = []byte(fmt.Sprintf(" %s", err)) } f.setRan() + f.inFuzzFn = false t.signal <- true // signal that the test has finished }() + // TODO(katiehockman, jayconrod): consider replacing inFuzzFn with + // general purpose flag that checks whether specific methods can be + // called. + f.inFuzzFn = true fn(t, b) t.finished = true } diff --git a/src/testing/testing.go b/src/testing/testing.go index 4fd628c0ff..7cf3323d51 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -399,6 +399,7 @@ type common struct { chatty *chattyPrinter // A copy of chattyPrinter, if the chatty flag is set. bench bool // Whether the current test is a benchmark. + inFuzzFn bool // Whether the test is executing a Fuzz function finished bool // Test function has completed. hasSub int32 // Written atomically. raceErrors int // Number of races detected during test. @@ -681,6 +682,9 @@ func (c *common) setRan() { // Fail marks the function as having failed but continues execution. func (c *common) Fail() { + if c.inFuzzFn { + panic("testing: f.Fail was called inside the f.Fuzz function") + } if c.parent != nil { c.parent.Fail() } @@ -710,6 +714,9 @@ func (c *common) Failed() bool { // created during the test. Calling FailNow does not stop // those other goroutines. func (c *common) FailNow() { + if c.inFuzzFn { + panic("testing: f.FailNow was called inside the f.Fuzz function") + } c.Fail() // Calling runtime.Goexit will exit the goroutine, which @@ -787,36 +794,54 @@ func (c *common) Logf(format string, args ...interface{}) { c.log(fmt.Sprintf(fo // Error is equivalent to Log followed by Fail. func (c *common) Error(args ...interface{}) { + if c.inFuzzFn { + panic("testing: f.Error was called inside the f.Fuzz function") + } c.log(fmt.Sprintln(args...)) c.Fail() } // Errorf is equivalent to Logf followed by Fail. func (c *common) Errorf(format string, args ...interface{}) { + if c.inFuzzFn { + panic("testing: f.Errorf was called inside the f.Fuzz function") + } c.log(fmt.Sprintf(format, args...)) c.Fail() } // Fatal is equivalent to Log followed by FailNow. func (c *common) Fatal(args ...interface{}) { + if c.inFuzzFn { + panic("testing: f.Fatal was called inside the f.Fuzz function") + } c.log(fmt.Sprintln(args...)) c.FailNow() } // Fatalf is equivalent to Logf followed by FailNow. func (c *common) Fatalf(format string, args ...interface{}) { + if c.inFuzzFn { + panic("testing: f.Fatalf was called inside the f.Fuzz function") + } c.log(fmt.Sprintf(format, args...)) c.FailNow() } // Skip is equivalent to Log followed by SkipNow. func (c *common) Skip(args ...interface{}) { + if c.inFuzzFn { + panic("testing: f.Skip was called inside the f.Fuzz function") + } c.log(fmt.Sprintln(args...)) c.SkipNow() } // Skipf is equivalent to Logf followed by SkipNow. func (c *common) Skipf(format string, args ...interface{}) { + if c.inFuzzFn { + panic("testing: f.Skipf was called inside the f.Fuzz function") + } c.log(fmt.Sprintf(format, args...)) c.SkipNow() } @@ -830,6 +855,9 @@ func (c *common) Skipf(format string, args ...interface{}) { // other goroutines created during the test. Calling SkipNow does not stop // those other goroutines. func (c *common) SkipNow() { + if c.inFuzzFn { + panic("testing: f.SkipNow was called inside the f.Fuzz function") + } c.skip() c.finished = true runtime.Goexit() @@ -852,6 +880,9 @@ func (c *common) Skipped() bool { // When printing file and line information, that function will be skipped. // Helper may be called simultaneously from multiple goroutines. func (c *common) Helper() { + if c.inFuzzFn { + panic("testing: f.Helper was called inside the f.Fuzz function") + } c.mu.Lock() defer c.mu.Unlock() if c.helpers == nil { @@ -864,6 +895,9 @@ func (c *common) Helper() { // subtests complete. Cleanup functions will be called in last added, // first called order. func (c *common) Cleanup(f func()) { + if c.inFuzzFn { + panic("testing: f.Cleanup was called inside the f.Fuzz function") + } var pc [maxStackLen]uintptr // Skip two extra frames to account for this function and runtime.Callers itself. n := runtime.Callers(2, pc[:]) @@ -902,6 +936,9 @@ var tempDirReplacer struct { // Each subsequent call to t.TempDir returns a unique directory; // if the directory creation fails, TempDir terminates the test by calling Fatal. func (c *common) TempDir() string { + if c.inFuzzFn { + panic("testing: f.TempDir was called inside the f.Fuzz function") + } // Use a single parent directory for all the temporary directories // created by a test, each numbered sequentially. c.tempDirMu.Lock() -- GitLab From 555797058ae41e3cc0825831520dee7fb77b3ce5 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Tue, 6 Oct 2020 17:13:26 -0400 Subject: [PATCH 0007/2500] [dev.fuzz] testing: fix error message checked in tests Change-Id: Ie40bcca896b95f575d7edd054fbe7a8029d2fc5a Reviewed-on: https://go-review.googlesource.com/c/go/+/259977 Run-TryBot: Katie Hockman TryBot-Result: Go Bot Trust: Katie Hockman Trust: Jay Conrod Reviewed-by: Jay Conrod --- src/cmd/go/testdata/script/test_fuzz.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt index d9aa718987..8f3242dc5e 100644 --- a/src/cmd/go/testdata/script/test_fuzz.txt +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -41,21 +41,21 @@ stdout ok ! stdout ^ok ! stdout 'fatal here' stdout FAIL -stdout illegal +stdout 'f.Fuzz function' # Test that f.Error within f.Fuzz panics ! go test error_fuzz_fn_fuzz_test.go ! stdout ^ok ! stdout 'error here' stdout FAIL -stdout illegal +stdout 'f.Fuzz function' # Test that f.Skip within f.Fuzz panics ! go test skip_fuzz_fn_fuzz_test.go ! stdout ^ok ! stdout 'skip here' stdout FAIL -stdout illegal +stdout 'f.Fuzz function' # Test that multiple calls to f.Fuzz causes a non-zero exit status. ! go test multiple_fuzz_calls_fuzz_test.go -- GitLab From 0a6f004cb1ed99bc225f4fe3cba5c2c5b901b442 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Wed, 7 Oct 2020 14:08:53 -0400 Subject: [PATCH 0008/2500] [dev.fuzz] testing: exit after f.Fuzz function This change causes f.Fuzz to call runtime.GoExit when it has finished running. This would mean that any code after an f.Fuzz function within a fuzz target would not be executed. In the future, vet should fail if someone tries to do this. This change also adds the missing code that would execute any cleanup functions added by f.Cleanup. Change-Id: Ib4d1e6bcafbe189986d0667a1e87dabae67ee621 Reviewed-on: https://go-review.googlesource.com/c/go/+/260338 Run-TryBot: Katie Hockman TryBot-Result: Go Bot Trust: Katie Hockman Trust: Jay Conrod Reviewed-by: Jay Conrod --- src/cmd/go/testdata/script/test_fuzz.txt | 37 +++++++++++++++++------- src/testing/fuzz.go | 33 +++++++++++---------- 2 files changed, 44 insertions(+), 26 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt index 8f3242dc5e..2a3e6e26c7 100644 --- a/src/cmd/go/testdata/script/test_fuzz.txt +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -57,16 +57,22 @@ stdout 'f.Fuzz function' stdout FAIL stdout 'f.Fuzz function' -# Test that multiple calls to f.Fuzz causes a non-zero exit status. -! go test multiple_fuzz_calls_fuzz_test.go -! stdout ^ok -stdout FAIL +# Test that a call to f.Fatal after the Fuzz func is never executed. +go test fatal_after_fuzz_func_fuzz_test.go +stdout ok +! stdout FAIL # Test that missing *T in f.Fuzz causes a non-zero exit status. ! go test incomplete_fuzz_call_fuzz_test.go ! stdout ^ok stdout FAIL +# Test that a panic in the Cleanup func is executed. +! go test cleanup_fuzz_test.go +! stdout ^ok +stdout FAIL +stdout 'failed some precondition' + # Test success with seed corpus in f.Fuzz go test -run FuzzPass fuzz_add_test.go stdout ok @@ -161,8 +167,8 @@ func Fuzz(f *testing.F) { }) } --- multiple_fuzz_calls_fuzz_test.go -- -package multiple_fuzz_calls_fuzz +-- fatal_after_fuzz_func_fuzz_test.go -- +package fatal_after_fuzz_func_fuzz import "testing" @@ -170,10 +176,7 @@ func Fuzz(f *testing.F) { f.Fuzz(func(t *testing.T, b []byte) { // no-op }) - - f.Fuzz(func(t *testing.T, b []byte) { - // this second call should panic - }) + f.Fatal("this shouldn't be called") } -- incomplete_fuzz_call_fuzz_test.go -- @@ -187,6 +190,20 @@ func Fuzz(f *testing.F) { }) } +-- cleanup_fuzz_test.go -- +package cleanup_fuzz_test + +import "testing" + +func Fuzz(f *testing.F) { + f.Cleanup(func() { + panic("failed some precondition") + }) + f.Fuzz(func(t *testing.T, b []byte) { + // no-op + }) +} + -- fuzz_add_test.go -- package fuzz_add diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 01895e8d7d..11bbd8fb16 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -9,6 +9,7 @@ import ( "flag" "fmt" "os" + "runtime" "time" ) @@ -28,12 +29,11 @@ type InternalFuzzTarget struct { // F is a type passed to fuzz targets for fuzz testing. type F struct { common - context *fuzzContext - corpus []corpusEntry // corpus is the in-memory corpus - result FuzzResult // result is the result of running the fuzz target - fuzzFunc func(f *F) // fuzzFunc is the function which makes up the fuzz target - fuzz bool // fuzz indicates whether the fuzzing engine should run - fuzzCalled bool // fuzzCalled indicates whether f.Fuzz has been called for this target + context *fuzzContext + corpus []corpusEntry // corpus is the in-memory corpus + result FuzzResult // result is the result of running the fuzz target + fuzzFunc func(f *F) // fuzzFunc is the function which makes up the fuzz target + fuzz bool // fuzz indicates whether the fuzzing engine should run } // corpus corpusEntry @@ -61,21 +61,20 @@ func (f *F) Add(args ...interface{}) { } } -// Fuzz runs the fuzz function, ff, for fuzz testing. It runs ff in a separate -// goroutine. Only the first call to Fuzz will be executed, and any subsequent -// calls will panic. If ff fails for a set of arguments, those arguments will be -// added to the seed corpus. +// Fuzz runs the fuzz function, ff, for fuzz testing. If ff fails for a set of +// arguments, those arguments will be added to the seed corpus. +// +// This is a terminal function which will terminate the currently running fuzz +// target by calling runtime.Goexit. To run any code after this function, use +// Cleanup. func (f *F) Fuzz(ff interface{}) { - if f.fuzzCalled { - panic("testing: found more than one call to Fuzz, will skip") - } - f.fuzzCalled = true - fn, ok := ff.(func(*T, []byte)) if !ok { panic("testing: Fuzz function must have type func(*testing.T, []byte)") } + defer runtime.Goexit() // exit after this function + var errStr string run := func(t *T, b []byte) { defer func() { @@ -118,6 +117,7 @@ func (f *F) Fuzz(ff interface{}) { errStr += string(t.output) } } + f.finished = true if f.Failed() { f.result = FuzzResult{Error: errors.New(errStr)} return @@ -169,12 +169,13 @@ func (f *F) runTarget(fn func(*F)) { } if err != nil { f.Fail() - f.result = FuzzResult{Error: fmt.Errorf("%s", err)} + f.result = FuzzResult{Error: fmt.Errorf(" %s", err)} } f.report() f.setRan() f.signal <- true // signal that the test has finished }() + defer f.runCleanup(normalPanic) fn(f) f.finished = true } -- GitLab From 8fabdcee8ff0537097ae68619ff515563bb2f986 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Fri, 2 Oct 2020 16:05:33 -0400 Subject: [PATCH 0009/2500] [dev.fuzz] internal/fuzz: coordinate fuzzing across workers Package fuzz provides common fuzzing functionality for tests built with "go test" and for programs that use fuzzing functionality in the testing package. Change-Id: I3901c6a993a9adb8a93733ae1838b86dd78c7036 Reviewed-on: https://go-review.googlesource.com/c/go/+/259259 Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman Trust: Katie Hockman Trust: Jay Conrod --- src/cmd/go/internal/test/flagdefs_test.go | 2 +- src/cmd/go/internal/test/test.go | 1 - src/go/build/deps_test.go | 5 +- src/internal/fuzz/fuzz.go | 143 ++++++++ src/internal/fuzz/sys_posix.go | 25 ++ src/internal/fuzz/sys_windows.go | 49 +++ src/internal/fuzz/worker.go | 381 ++++++++++++++++++++++ src/testing/fuzz.go | 129 +++++--- src/testing/internal/testdeps/deps.go | 9 + src/testing/testing.go | 6 +- 10 files changed, 704 insertions(+), 46 deletions(-) create mode 100644 src/internal/fuzz/fuzz.go create mode 100644 src/internal/fuzz/sys_posix.go create mode 100644 src/internal/fuzz/sys_windows.go create mode 100644 src/internal/fuzz/worker.go diff --git a/src/cmd/go/internal/test/flagdefs_test.go b/src/cmd/go/internal/test/flagdefs_test.go index ab5440b380..50711ecff9 100644 --- a/src/cmd/go/internal/test/flagdefs_test.go +++ b/src/cmd/go/internal/test/flagdefs_test.go @@ -17,7 +17,7 @@ func TestPassFlagToTestIncludesAllTestFlags(t *testing.T) { } name := strings.TrimPrefix(f.Name, "test.") switch name { - case "testlogfile", "paniconexit0": + case "testlogfile", "paniconexit0", "fuzzworker": // These are internal flags. default: if !passFlagToTest[name] { diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 109acb53da..5758910a5f 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -467,7 +467,6 @@ See the documentation of the testing package for more information. `, } -// TODO(katiehockman): complete the testing here var ( testBench string // -bench flag testC bool // -c flag diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index fa8ecf10f4..e5f38d4fbc 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -467,7 +467,10 @@ var depsRules = ` FMT, flag, runtime/debug, runtime/trace < testing; - internal/testlog, runtime/pprof, regexp + FMT, encoding/json + < internal/fuzz; + + internal/fuzz, internal/testlog, runtime/pprof, regexp < testing/internal/testdeps; OS, flag, testing, internal/cfg diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go new file mode 100644 index 0000000000..4f1d204834 --- /dev/null +++ b/src/internal/fuzz/fuzz.go @@ -0,0 +1,143 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package fuzz provides common fuzzing functionality for tests built with +// "go test" and for programs that use fuzzing functionality in the testing +// package. +package fuzz + +import ( + "os" + "runtime" + "sync" + "time" +) + +// CoordinateFuzzing creates several worker processes and communicates with +// them to test random inputs that could trigger crashes and expose bugs. +// The worker processes run the same binary in the same directory with the +// same environment variables as the coordinator process. Workers also run +// with the same arguments as the coordinator, except with the -test.fuzzworker +// flag prepended to the argument list. +// +// parallel is the number of worker processes to run in parallel. If parallel +// is 0, CoordinateFuzzing will run GOMAXPROCS workers. +// +// seed is a list of seed values added by the fuzz target with testing.F.Add. +// Seed values from testdata and GOFUZZCACHE should not be included in this +// list; this function loads them separately. +func CoordinateFuzzing(parallel int, seed [][]byte) error { + if parallel == 0 { + parallel = runtime.GOMAXPROCS(0) + } + // TODO(jayconrod): support fuzzing indefinitely or with a given duration. + // The value below is just a placeholder until we figure out how to handle + // interrupts. + duration := 5 * time.Second + + // TODO(jayconrod): do we want to support fuzzing different binaries? + dir := "" // same as self + binPath := os.Args[0] + args := append([]string{"-test.fuzzworker"}, os.Args[1:]...) + env := os.Environ() // same as self + + c := &coordinator{ + doneC: make(chan struct{}), + inputC: make(chan corpusEntry), + } + + newWorker := func() *worker { + return &worker{ + dir: dir, + binPath: binPath, + args: args, + env: env, + coordinator: c, + } + } + + corpus := corpus{entries: make([]corpusEntry, len(seed))} + for i, v := range seed { + corpus.entries[i].b = v + } + if len(corpus.entries) == 0 { + // TODO(jayconrod,katiehockman): pick a good starting corpus when one is + // missing or very small. + corpus.entries = append(corpus.entries, corpusEntry{b: []byte{0}}) + } + + // TODO(jayconrod,katiehockman): read corpus from testdata. + // TODO(jayconrod,katiehockman): read corpus from GOFUZZCACHE. + + // Start workers. + workers := make([]*worker, parallel) + runErrs := make([]error, parallel) + var wg sync.WaitGroup + wg.Add(parallel) + for i := 0; i < parallel; i++ { + go func(i int) { + defer wg.Done() + workers[i] = newWorker() + runErrs[i] = workers[i].runFuzzing() + }(i) + } + + // Main event loop. + stopC := time.After(duration) + i := 0 + for { + select { + // TODO(jayconrod): handle interruptions like SIGINT. + // TODO(jayconrod,katiehockman): receive crashers and new corpus values + // from workers. + + case <-stopC: + // Time's up. + close(c.doneC) + + case <-c.doneC: + // Wait for workers to stop and return. + wg.Wait() + for _, err := range runErrs { + if err != nil { + return err + } + } + return nil + + case c.inputC <- corpus.entries[i]: + // Sent the next input to any worker. + // TODO(jayconrod,katiehockman): need a scheduling algorithm that chooses + // which corpus value to send next (or generates something new). + i = (i + 1) % len(corpus.entries) + } + } + + // TODO(jayconrod,katiehockman): write crashers to testdata and other inputs + // to GOFUZZCACHE. If the testdata directory is outside the current module, + // always write to GOFUZZCACHE, since the testdata is likely read-only. +} + +type corpus struct { + entries []corpusEntry +} + +// TODO(jayconrod,katiehockman): decide whether and how to unify this type +// with the equivalent in testing. +type corpusEntry struct { + b []byte +} + +// coordinator holds channels that workers can use to communicate with +// the coordinator. +type coordinator struct { + // doneC is closed to indicate fuzzing is done and workers should stop. + // doneC may be closed due to a time limit expiring or a fatal error in + // a worker. + doneC chan struct{} + + // inputC is sent values to fuzz by the coordinator. Any worker may receive + // values from this channel. + inputC chan corpusEntry +} diff --git a/src/internal/fuzz/sys_posix.go b/src/internal/fuzz/sys_posix.go new file mode 100644 index 0000000000..259caa8a59 --- /dev/null +++ b/src/internal/fuzz/sys_posix.go @@ -0,0 +1,25 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !windows + +package fuzz + +import ( + "os" + "os/exec" +) + +// setWorkerComm configures communciation channels on the cmd that will +// run a worker process. +func setWorkerComm(cmd *exec.Cmd, fuzzIn, fuzzOut *os.File) { + cmd.ExtraFiles = []*os.File{fuzzIn, fuzzOut} +} + +// getWorkerComm returns communication channels in the worker process. +func getWorkerComm() (fuzzIn, fuzzOut *os.File, err error) { + fuzzIn = os.NewFile(3, "fuzz_in") + fuzzOut = os.NewFile(4, "fuzz_out") + return fuzzIn, fuzzOut, nil +} diff --git a/src/internal/fuzz/sys_windows.go b/src/internal/fuzz/sys_windows.go new file mode 100644 index 0000000000..a67548477b --- /dev/null +++ b/src/internal/fuzz/sys_windows.go @@ -0,0 +1,49 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build windows + +package fuzz + +import ( + "fmt" + "os" + "os/exec" + "strconv" + "strings" + "syscall" +) + +// setWorkerComm configures communciation channels on the cmd that will +// run a worker process. +func setWorkerComm(cmd *exec.Cmd, fuzzIn, fuzzOut *os.File) { + syscall.SetHandleInformation(syscall.Handle(fuzzIn.Fd()), syscall.HANDLE_FLAG_INHERIT, 1) + syscall.SetHandleInformation(syscall.Handle(fuzzOut.Fd()), syscall.HANDLE_FLAG_INHERIT, 1) + cmd.Env = append(cmd.Env, fmt.Sprintf("GO_TEST_FUZZ_WORKER_HANDLES=%x,%x", fuzzIn.Fd(), fuzzOut.Fd())) +} + +// getWorkerComm returns communication channels in the worker process. +func getWorkerComm() (fuzzIn *os.File, fuzzOut *os.File, err error) { + v := os.Getenv("GO_TEST_FUZZ_WORKER_HANDLES") + if v == "" { + return nil, nil, fmt.Errorf("GO_TEST_FUZZ_WORKER_HANDLES not set") + } + parts := strings.Split(v, ",") + if len(parts) != 2 { + return nil, nil, fmt.Errorf("GO_TEST_FUZZ_WORKER_HANDLES has invalid value") + } + base := 16 + bitSize := 64 + in, err := strconv.ParseInt(parts[0], base, bitSize) + if err != nil { + return nil, nil, fmt.Errorf("GO_TEST_FUZZ_WORKER_HANDLES has invalid value: %v", err) + } + out, err := strconv.ParseInt(parts[1], base, bitSize) + if err != nil { + return nil, nil, fmt.Errorf("GO_TEST_FUZZ_WORKER_HANDLES has invalid value: %v", err) + } + fuzzIn = os.NewFile(uintptr(in), "fuzz_in") + fuzzOut = os.NewFile(uintptr(out), "fuzz_out") + return fuzzIn, fuzzOut, nil +} diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go new file mode 100644 index 0000000000..543e352e7f --- /dev/null +++ b/src/internal/fuzz/worker.go @@ -0,0 +1,381 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fuzz + +import ( + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "os" + "os/exec" + "runtime" + "time" +) + +const ( + // workerFuzzDuration is the amount of time a worker can spend testing random + // variations of an input given by the coordinator. + workerFuzzDuration = 100 * time.Millisecond + + // workerTimeoutDuration is the amount of time a worker can go without + // responding to the coordinator before being stopped. + workerTimeoutDuration = 1 * time.Second +) + +// worker manages a worker process running a test binary. +type worker struct { + dir string // working directory, same as package directory + binPath string // path to test executable + args []string // arguments for test executable + env []string // environment for test executable + + coordinator *coordinator + + cmd *exec.Cmd // current worker process + client *workerClient // used to communicate with worker process + waitErr error // last error returned by wait, set before termC is closed. + termC chan struct{} // closed by wait when worker process terminates +} + +// runFuzzing runs the test binary to perform fuzzing. +// +// This function loops until w.coordinator.doneC is closed or some +// fatal error is encountered. It receives inputs from w.coordinator.inputC, +// then passes those on to the worker process. If the worker crashes, +// runFuzzing restarts it and continues. +func (w *worker) runFuzzing() error { + // Start the process. + if err := w.start(); err != nil { + // We couldn't start the worker process. We can't do anything, and it's + // likely that other workers can't either, so give up. + close(w.coordinator.doneC) + return err + } + + inputC := w.coordinator.inputC // set to nil when processing input + fuzzC := make(chan struct{}) // sent when we finish processing an input. + + // Main event loop. + for { + select { + case <-w.coordinator.doneC: + // All workers were told to stop. + return w.stop() + + case <-w.termC: + // Worker process terminated unexpectedly. + // TODO(jayconrod,katiehockman): handle crasher. + + // Restart the process. + if err := w.start(); err != nil { + close(w.coordinator.doneC) + return err + } + + case input := <-inputC: + // Received input from coordinator. + inputC = nil // block new inputs until we finish with this one. + go func() { + args := fuzzArgs{ + Value: input.b, + DurationSec: workerFuzzDuration.Seconds(), + } + _, err := w.client.fuzz(args) + if err != nil { + // TODO(jayconrod): if we get an error here, something failed between + // main and the call to testing.F.Fuzz. The error here won't + // be useful. Collect stderr, clean it up, and return that. + // TODO(jayconrod): what happens if testing.F.Fuzz is never called? + // TODO(jayconrod): time out if the test process hangs. + } + + fuzzC <- struct{}{} + }() + + case <-fuzzC: + // Worker finished fuzzing. + // TODO(jayconrod,katiehockman): gather statistics. Collect "interesting" + // inputs and add to corpus. + inputC = w.coordinator.inputC // unblock new inputs + } + } +} + +// start runs a new worker process. +// +// If the process couldn't be started, start returns an error. Start won't +// return later termination errors from the process if they occur. +// +// If the process starts successfully, start returns nil. stop must be called +// once later to clean up, even if the process terminates on its own. +// +// When the process terminates, w.waitErr is set to the error (if any), and +// w.termC is closed. +func (w *worker) start() (err error) { + if w.cmd != nil { + panic("worker already started") + } + w.waitErr = nil + w.termC = nil + + cmd := exec.Command(w.binPath, w.args...) + cmd.Dir = w.dir + cmd.Env = w.env + // TODO(jayconrod): set stdout and stderr to nil or buffer. A large number + // of workers may be very noisy, but for now, this output is useful for + // debugging. + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + // TODO(jayconrod): set up shared memory between the coordinator and worker to + // transfer values and coverage data. If the worker crashes, we need to be + // able to find the value that caused the crash. + + // Create the "fuzz_in" and "fuzz_out" pipes so we can communicate with + // the worker. We don't use stdin and stdout, since the test binary may + // do something else with those. + // + // Each pipe has a reader and a writer. The coordinator writes to fuzzInW + // and reads from fuzzOutR. The worker inherits fuzzInR and fuzzOutW. + // The coordinator closes fuzzInR and fuzzOutW after starting the worker, + // since we have no further need of them. + fuzzInR, fuzzInW, err := os.Pipe() + if err != nil { + return err + } + defer fuzzInR.Close() + fuzzOutR, fuzzOutW, err := os.Pipe() + if err != nil { + fuzzInW.Close() + return err + } + defer fuzzOutW.Close() + setWorkerComm(cmd, fuzzInR, fuzzOutW) + + // Start the worker process. + if err := cmd.Start(); err != nil { + fuzzInW.Close() + fuzzOutR.Close() + return err + } + + // Worker started successfully. + // After this, w.client owns fuzzInW and fuzzOutR, so w.client.Close must be + // called later by stop. + w.cmd = cmd + w.termC = make(chan struct{}) + w.client = newWorkerClient(fuzzInW, fuzzOutR) + + go func() { + w.waitErr = w.cmd.Wait() + close(w.termC) + }() + + return nil +} + +// stop tells the worker process to exit by closing w.client, then blocks until +// it terminates. If the worker doesn't terminate after a short time, stop +// signals it with os.Interrupt (where supported), then os.Kill. +// +// stop returns the error the process terminated with, if any (same as +// w.waitErr). +// +// stop must be called once after start returns successfully, even if the +// worker process terminates unexpectedly. +func (w *worker) stop() error { + if w.termC == nil { + panic("worker was not started successfully") + } + select { + case <-w.termC: + // Worker already terminated, perhaps unexpectedly. + if w.client == nil { + panic("worker already stopped") + } + w.client.Close() + w.cmd = nil + w.client = nil + return w.waitErr + default: + // Worker still running. + } + + // Tell the worker to stop by closing fuzz_in. It won't actually stop until it + // finishes with earlier calls. + closeC := make(chan struct{}) + go func() { + w.client.Close() + close(closeC) + }() + + sig := os.Interrupt + if runtime.GOOS == "windows" { + // Per https://golang.org/pkg/os/#Signal, “Interrupt is not implemented on + // Windows; using it with os.Process.Signal will return an error.” + // Fall back to Kill instead. + sig = os.Kill + } + + t := time.NewTimer(workerTimeoutDuration) + for { + select { + case <-w.termC: + // Worker terminated. + t.Stop() + <-closeC + w.cmd = nil + w.client = nil + return w.waitErr + + case <-t.C: + // Timer fired before worker terminated. + switch sig { + case os.Interrupt: + // Try to stop the worker with SIGINT and wait a little longer. + w.cmd.Process.Signal(sig) + sig = os.Kill + t.Reset(workerTimeoutDuration) + + case os.Kill: + // Try to stop the worker with SIGKILL and keep waiting. + w.cmd.Process.Signal(sig) + sig = nil + t.Reset(workerTimeoutDuration) + + case nil: + // Still waiting. Print a message to let the user know why. + fmt.Fprintf(os.Stderr, "go: waiting for fuzz worker to terminate...\n") + } + } + } +} + +// RunFuzzWorker is called in a worker process to communicate with the +// coordinator process in order to fuzz random inputs. RunFuzzWorker loops +// until the coordinator tells it to stop. +// +// fn is a wrapper on the fuzz function. It may return an error to indicate +// a given input "crashed". The coordinator will also record a crasher if +// the function times out or terminates the process. +// +// RunFuzzWorker returns an error if it could not communicate with the +// coordinator process. +func RunFuzzWorker(fn func([]byte) error) error { + fuzzIn, fuzzOut, err := getWorkerComm() + if err != nil { + return err + } + srv := &workerServer{fn: fn} + return srv.serve(fuzzIn, fuzzOut) +} + +// call is serialized and sent from the coordinator on fuzz_in. It acts as +// a minimalist RPC mechanism. Exactly one of its fields must be set to indicate +// which method to call. +type call struct { + Fuzz *fuzzArgs +} + +type fuzzArgs struct { + Value []byte + DurationSec float64 +} + +type fuzzResponse struct{} + +// workerServer is a minimalist RPC server, run in fuzz worker processes. +type workerServer struct { + fn func([]byte) error +} + +// serve deserializes and executes RPCs on a given pair of pipes. +// +// serve returns errors communicating over the pipes. It does not return +// errors from methods; those are passed through response values. +func (ws *workerServer) serve(fuzzIn io.ReadCloser, fuzzOut io.WriteCloser) error { + enc := json.NewEncoder(fuzzOut) + dec := json.NewDecoder(fuzzIn) + for { + var c call + if err := dec.Decode(&c); err == io.EOF { + return nil + } else if err != nil { + return err + } + + var resp interface{} + switch { + case c.Fuzz != nil: + resp = ws.fuzz(*c.Fuzz) + default: + return errors.New("no arguments provided for any call") + } + + if err := enc.Encode(resp); err != nil { + return err + } + } +} + +// fuzz runs the test function on random variations of a given input value for +// a given amount of time. fuzz returns early if it finds an input that crashes +// the fuzz function or an input that expands coverage. +func (ws *workerServer) fuzz(args fuzzArgs) fuzzResponse { + // TODO(jayconrod, katiehockman): implement + return fuzzResponse{} +} + +// workerClient is a minimalist RPC client, run in the fuzz coordinator. +type workerClient struct { + fuzzIn io.WriteCloser + fuzzOut io.ReadCloser + enc *json.Encoder + dec *json.Decoder +} + +func newWorkerClient(fuzzIn io.WriteCloser, fuzzOut io.ReadCloser) *workerClient { + return &workerClient{ + fuzzIn: fuzzIn, + fuzzOut: fuzzOut, + enc: json.NewEncoder(fuzzIn), + dec: json.NewDecoder(fuzzOut), + } +} + +// Close shuts down the connection to the RPC server (the worker process) by +// closing fuzz_in. Close drains fuzz_out (avoiding a SIGPIPE in the worker), +// and closes it after the worker process closes the other end. +func (wc *workerClient) Close() error { + // Close fuzzIn. This signals to the server that there are no more calls, + // and it should exit. + if err := wc.fuzzIn.Close(); err != nil { + wc.fuzzOut.Close() + return err + } + + // Drain fuzzOut and close it. When the server exits, the kernel will close + // its end of fuzzOut, and we'll get EOF. + if _, err := io.Copy(ioutil.Discard, wc.fuzzOut); err != nil { + wc.fuzzOut.Close() + return err + } + return wc.fuzzOut.Close() +} + +// fuzz tells the worker to call the fuzz method. See workerServer.fuzz. +func (wc *workerClient) fuzz(args fuzzArgs) (fuzzResponse, error) { + c := call{Fuzz: &args} + if err := wc.enc.Encode(c); err != nil { + return fuzzResponse{}, err + } + var resp fuzzResponse + if err := wc.dec.Decode(&resp); err != nil { + return fuzzResponse{}, err + } + return resp, nil +} diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 11bbd8fb16..6773b7161d 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -15,9 +15,13 @@ import ( func initFuzzFlags() { matchFuzz = flag.String("test.fuzz", "", "run the fuzz target matching `regexp`") + isFuzzWorker = flag.Bool("test.fuzzworker", false, "coordinate with the parent process to fuzz random values") } -var matchFuzz *string +var ( + matchFuzz *string + isFuzzWorker *bool +) // InternalFuzzTarget is an internal type but exported because it is cross-package; // it is part of the implementation of the "go test" command. @@ -33,7 +37,6 @@ type F struct { corpus []corpusEntry // corpus is the in-memory corpus result FuzzResult // result is the result of running the fuzz target fuzzFunc func(f *F) // fuzzFunc is the function which makes up the fuzz target - fuzz bool // fuzz indicates whether the fuzzing engine should run } // corpus corpusEntry @@ -88,7 +91,6 @@ func (f *F) Fuzz(ff interface{}) { t.Fail() t.output = []byte(fmt.Sprintf(" %s", err)) } - f.setRan() f.inFuzzFn = false t.signal <- true // signal that the test has finished }() @@ -100,30 +102,76 @@ func (f *F) Fuzz(ff interface{}) { t.finished = true } - // Run the seed corpus first - for _, c := range f.corpus { - t := &T{ - common: common{ - signal: make(chan bool), - w: f.w, - chatty: f.chatty, - }, - context: newTestContext(1, nil), + switch { + case f.context.coordinateFuzzing != nil: + // Fuzzing is enabled, and this is the test process started by 'go test'. + // Act as the coordinator process, and coordinate workers to perform the + // actual fuzzing. + seed := make([][]byte, len(f.corpus)) + for i, e := range f.corpus { + seed[i] = e.b } - go run(t, c.b) - <-t.signal - if t.Failed() { - f.Fail() - errStr += string(t.output) + err := f.context.coordinateFuzzing(*parallel, seed) + f.setRan() + f.finished = true + f.result = FuzzResult{Error: err} + // TODO(jayconrod,katiehockman): Aggregate statistics across workers + // and set FuzzResult properly. + + case f.context.runFuzzWorker != nil: + // Fuzzing is enabled, and this is a worker process. Follow instructions + // from the coordinator. + err := f.context.runFuzzWorker(func(input []byte) error { + t := &T{ + common: common{ + signal: make(chan bool), + w: f.w, + chatty: f.chatty, + }, + context: newTestContext(1, nil), + } + go run(t, input) + <-t.signal + if t.Failed() { + return errors.New(string(t.output)) + } + return nil + }) + if err != nil { + // TODO(jayconrod,katiehockman): how should we handle a failure to + // communicate with the coordinator? Might be caused by the coordinator + // terminating early. + fmt.Fprintf(os.Stderr, "testing: communicating with fuzz coordinator: %v\n", err) + os.Exit(1) } - } - f.finished = true - if f.Failed() { - f.result = FuzzResult{Error: errors.New(errStr)} - return - } + f.setRan() + f.finished = true - // TODO: if f.fuzz is set, run fuzzing engine + default: + // Fuzzing is not enabled. Only run the seed corpus. + for _, c := range f.corpus { + t := &T{ + common: common{ + signal: make(chan bool), + w: f.w, + chatty: f.chatty, + }, + context: newTestContext(1, nil), + } + go run(t, c.b) + <-t.signal + if t.Failed() { + f.Fail() + errStr += string(t.output) + } + f.setRan() + } + f.finished = true + if f.Failed() { + f.result = FuzzResult{Error: errors.New(errStr)} + return + } + } } func (f *F) report() { @@ -202,8 +250,10 @@ func (r FuzzResult) String() string { // fuzzContext holds all fields that are common to all fuzz targets. type fuzzContext struct { - runMatch *matcher - fuzzMatch *matcher + runMatch *matcher + fuzzMatch *matcher + coordinateFuzzing func(int, [][]byte) error + runFuzzWorker func(func([]byte) error) error } // RunFuzzTargets is an internal function but exported because it is cross-package; @@ -218,7 +268,7 @@ func RunFuzzTargets(matchString func(pat, str string) (bool, error), fuzzTargets // engine to generate or mutate inputs. func runFuzzTargets(matchString func(pat, str string) (bool, error), fuzzTargets []InternalFuzzTarget) (ran, ok bool) { ok = true - if len(fuzzTargets) == 0 { + if len(fuzzTargets) == 0 || *isFuzzWorker { return ran, ok } ctx := &fuzzContext{runMatch: newMatcher(matchString, *match, "-test.run")} @@ -249,25 +299,21 @@ func runFuzzTargets(matchString func(pat, str string) (bool, error), fuzzTargets return ran, ok } -// RunFuzzing is an internal function but exported because it is cross-package; -// it is part of the implementation of the "go test" command. -func RunFuzzing(matchString func(pat, str string) (bool, error), fuzzTargets []InternalFuzzTarget) (ok bool) { - _, ok = runFuzzing(matchString, fuzzTargets) - return ok -} - // runFuzzing runs the fuzz target matching the pattern for -fuzz. Only one such // fuzz target must match. This will run the fuzzing engine to generate and // mutate new inputs against the f.Fuzz function. -func runFuzzing(matchString func(pat, str string) (bool, error), fuzzTargets []InternalFuzzTarget) (ran, ok bool) { - if len(fuzzTargets) == 0 { +// +// If fuzzing is disabled (-test.fuzz is not set), runFuzzing +// returns immediately. +func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran, ok bool) { + if len(fuzzTargets) == 0 || *matchFuzz == "" { return false, true } - ctx := &fuzzContext{ - fuzzMatch: newMatcher(matchString, *matchFuzz, "-test.fuzz"), - } - if *matchFuzz == "" { - return false, true + ctx := &fuzzContext{fuzzMatch: newMatcher(deps.MatchString, *matchFuzz, "-test.fuzz")} + if *isFuzzWorker { + ctx.runFuzzWorker = deps.RunFuzzWorker + } else { + ctx.coordinateFuzzing = deps.CoordinateFuzzing } f := &F{ common: common{ @@ -275,7 +321,6 @@ func runFuzzing(matchString func(pat, str string) (bool, error), fuzzTargets []I w: os.Stdout, }, context: ctx, - fuzz: true, } var ( ft InternalFuzzTarget diff --git a/src/testing/internal/testdeps/deps.go b/src/testing/internal/testdeps/deps.go index 3608d33294..9665092f4c 100644 --- a/src/testing/internal/testdeps/deps.go +++ b/src/testing/internal/testdeps/deps.go @@ -12,6 +12,7 @@ package testdeps import ( "bufio" + "internal/fuzz" "internal/testlog" "io" "regexp" @@ -126,3 +127,11 @@ func (TestDeps) StopTestLog() error { func (TestDeps) SetPanicOnExit0(v bool) { testlog.SetPanicOnExit0(v) } + +func (TestDeps) CoordinateFuzzing(parallel int, seed [][]byte) error { + return fuzz.CoordinateFuzzing(parallel, seed) +} + +func (TestDeps) RunFuzzWorker(fn func([]byte) error) error { + return fuzz.RunFuzzWorker(fn) +} diff --git a/src/testing/testing.go b/src/testing/testing.go index 7cf3323d51..2c2e77dc4b 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1324,6 +1324,8 @@ func (f matchStringOnly) ImportPath() string { return " func (f matchStringOnly) StartTestLog(io.Writer) {} func (f matchStringOnly) StopTestLog() error { return errMain } func (f matchStringOnly) SetPanicOnExit0(bool) {} +func (f matchStringOnly) CoordinateFuzzing(int, [][]byte) error { return errMain } +func (f matchStringOnly) RunFuzzWorker(func([]byte) error) error { return errMain } // Main is an internal function, part of the implementation of the "go test" command. // It was exported because it is cross-package and predates "internal" packages. @@ -1366,6 +1368,8 @@ type testDeps interface { StartTestLog(io.Writer) StopTestLog() error WriteProfileTo(string, io.Writer, int) error + CoordinateFuzzing(int, [][]byte) error + RunFuzzWorker(func([]byte) error) error } // MainStart is meant for use by tests generated by 'go test'. @@ -1431,7 +1435,7 @@ func (m *M) Run() (code int) { return } - fuzzingRan, fuzzingOk := runFuzzing(m.deps.MatchString, m.fuzzTargets) + fuzzingRan, fuzzingOk := runFuzzing(m.deps, m.fuzzTargets) if *matchFuzz != "" && !fuzzingRan { fmt.Fprintln(os.Stderr, "testing: warning: no targets to fuzz") } -- GitLab From 24beae1df3e15c7d5b8d79ad2cfb4651c047e029 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Wed, 14 Oct 2020 12:05:13 -0400 Subject: [PATCH 0010/2500] [dev.fuzz] testing: remove testing.RunFuzzTargets It is a legacy practice to expose these exported testing functions, and is not needed for running fuzz targets. Change-Id: Ic300c9bfd15f4e71a1cea99f12c97d671a899f9b Reviewed-on: https://go-review.googlesource.com/c/go/+/262258 Trust: Katie Hockman Trust: Jay Conrod Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/testing/fuzz.go | 7 ------- src/testing/fuzz_test.go | 42 ---------------------------------------- 2 files changed, 49 deletions(-) delete mode 100644 src/testing/fuzz_test.go diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 6773b7161d..766242f75d 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -256,13 +256,6 @@ type fuzzContext struct { runFuzzWorker func(func([]byte) error) error } -// RunFuzzTargets is an internal function but exported because it is cross-package; -// it is part of the implementation of the "go test" command. -func RunFuzzTargets(matchString func(pat, str string) (bool, error), fuzzTargets []InternalFuzzTarget) (ok bool) { - _, ok = runFuzzTargets(matchString, fuzzTargets) - return ok -} - // runFuzzTargets runs the fuzz targets matching the pattern for -run. This will // only run the f.Fuzz function for each seed corpus without using the fuzzing // engine to generate or mutate inputs. diff --git a/src/testing/fuzz_test.go b/src/testing/fuzz_test.go deleted file mode 100644 index 77a7d5ea4e..0000000000 --- a/src/testing/fuzz_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package testing_test - -import ( - "testing" -) - -func TestFuzzAdd(t *testing.T) { - matchFunc := func(a, b string) (bool, error) { return true, nil } - tests := []struct { - name string - fn func(f *testing.F) - ok bool - }{ - { - "empty", - func(f *testing.F) { f.Add() }, - false, - }, - { - "multiple arguments", - func(f *testing.F) { f.Add([]byte("hello"), []byte("bye")) }, - false, - }, - { - "string", - func(f *testing.F) { f.Add("hello") }, - false, - }, - { - "bytes", - func(f *testing.F) { f.Add([]byte("hello")) }, - true, - }, - } - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - if got, want := testing.RunFuzzTargets(matchFunc, []testing.InternalFuzzTarget{{Fn: tc.fn}}), tc.ok; got != want { - t.Errorf("testing.Add: ok %t, want %t", got, want) - } - }) - } -} -- GitLab From 9f3aa113a9adfceb5ab13dc9abd0921f8d118e15 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Tue, 6 Oct 2020 17:54:50 -0400 Subject: [PATCH 0011/2500] [dev.fuzz] testing: read corpus from testdata/corpus for each target This change also includes a small cleanup of the run() function and additional tests for error conditions in fuzz targets. Change-Id: I2b7722b25a0d071182a84f1dc4b92e82a7ea34d9 Reviewed-on: https://go-review.googlesource.com/c/go/+/256978 Run-TryBot: Katie Hockman TryBot-Result: Go Bot Trust: Katie Hockman Trust: Jay Conrod Reviewed-by: Jay Conrod --- src/cmd/go/testdata/script/test_fuzz.txt | 77 +++++++++++++++++-- .../go/testdata/script/test_fuzz_chatty.txt | 21 ++++- src/internal/fuzz/fuzz.go | 35 ++++++++- src/testing/fuzz.go | 47 ++++++++--- src/testing/internal/testdeps/deps.go | 4 + src/testing/testing.go | 4 +- 6 files changed, 161 insertions(+), 27 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt index 2a3e6e26c7..5ab1c320d7 100644 --- a/src/cmd/go/testdata/script/test_fuzz.txt +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -1,5 +1,10 @@ +# Test that calling f.Error in a fuzz target causes a non-zero exit status. +! go test -fuzz Fuzz error_fuzz_test.go +! stdout ^ok +stdout FAIL + # Test that calling f.Fatal in a fuzz target causes a non-zero exit status. -! go test fail_fuzz_test.go +! go test fatal_fuzz_test.go ! stdout ^ok stdout FAIL @@ -9,7 +14,7 @@ stdout ok ! stdout FAIL # Test that calling f.Fatal while fuzzing causes a non-zero exit status. -! go test -fuzz Fuzz fail_fuzz_test.go +! go test -fuzz Fuzz fatal_fuzz_test.go ! stdout ^ok stdout FAIL @@ -96,12 +101,39 @@ stdout 'off by one error' ! stdout ^ok stdout FAIL --- fail_fuzz_test.go -- -package fail_fuzz +# Test fatal with testdata seed corpus +! go test -run FuzzFail corpustesting/fuzz_testdata_corpus_test.go +! stdout ^ok +stdout FAIL +stdout 'fatal here' + +# Test pass with testdata seed corpus +go test -run FuzzPass corpustesting/fuzz_testdata_corpus_test.go +stdout ok +! stdout FAIL +! stdout 'fatal here' + +# Test pass with file in other nested testdata directory +go test -run FuzzInNestedDir corpustesting/fuzz_testdata_corpus_test.go +stdout ok +! stdout FAIL +! stdout 'fatal here' + +-- error_fuzz_test.go -- +package error_fuzz import "testing" -func FuzzFail(f *testing.F) { +func Fuzz(f *testing.F) { + f.Error("error in target") +} + +-- fatal_fuzz_test.go -- +package fatal_fuzz + +import "testing" + +func Fuzz(f *testing.F) { f.Fatal("fatal in target") } @@ -259,4 +291,37 @@ func FuzzNilPanic(f *testing.F) { panic(nil) } }) -} \ No newline at end of file +} + +-- corpustesting/fuzz_testdata_corpus_test.go -- +package fuzz_testdata_corpus + +import "testing" + +func fuzzFn(f *testing.F) { + f.Helper() + f.Fuzz(func(t *testing.T, b []byte) { + if string(b) == "12345\n" { + t.Fatal("fatal here") + } + }) +} + +func FuzzFail(f *testing.F) { + fuzzFn(f) +} + +func FuzzPass(f *testing.F) { + fuzzFn(f) +} + +func FuzzInNestedDir(f *testing.F) { + fuzzFn(f) +} + +-- corpustesting/testdata/corpus/FuzzFail/1 -- +12345 +-- corpustesting/testdata/corpus/FuzzPass/1 -- +00000 +-- corpustesting/testdata/corpus/FuzzInNestedDir/anotherdir/1 -- +12345 \ No newline at end of file diff --git a/src/cmd/go/testdata/script/test_fuzz_chatty.txt b/src/cmd/go/testdata/script/test_fuzz_chatty.txt index 56b20bedad..a881d54bdc 100644 --- a/src/cmd/go/testdata/script/test_fuzz_chatty.txt +++ b/src/cmd/go/testdata/script/test_fuzz_chatty.txt @@ -1,10 +1,15 @@ [short] skip -# Run chatty fuzz targets with an error and fatal. -! go test -v chatty_fail_fuzz_test.go +# Run chatty fuzz targets with an error. +! go test -v chatty_error_fuzz_test.go ! stdout '^ok' stdout 'FAIL' stdout 'error in target' + +# Run chatty fuzz targets with a fatal. +! go test -v chatty_fatal_fuzz_test.go +! stdout '^ok' +stdout 'FAIL' stdout 'fatal in target' # Run chatty fuzz target with a panic @@ -26,13 +31,21 @@ stdout PASS stdout 'all good here' ! stdout FAIL --- chatty_fail_fuzz_test.go -- -package chatty_fail_fuzz +-- chatty_error_fuzz_test.go -- +package chatty_error_fuzz import "testing" func Fuzz(f *testing.F) { f.Error("error in target") +} + +-- chatty_fatal_fuzz_test.go -- +package chatty_fatal_fuzz + +import "testing" + +func Fuzz(f *testing.F) { f.Fatal("fatal in target") } diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 4f1d204834..d7187d043e 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -8,7 +8,10 @@ package fuzz import ( + "fmt" + "io/ioutil" "os" + "path/filepath" "runtime" "sync" "time" @@ -24,9 +27,10 @@ import ( // parallel is the number of worker processes to run in parallel. If parallel // is 0, CoordinateFuzzing will run GOMAXPROCS workers. // -// seed is a list of seed values added by the fuzz target with testing.F.Add. -// Seed values from testdata and GOFUZZCACHE should not be included in this -// list; this function loads them separately. +// seed is a list of seed values added by the fuzz target with testing.F.Add and +// in testdata. +// Seed values from GOFUZZCACHE should not be included in this list; this +// function loads them separately. func CoordinateFuzzing(parallel int, seed [][]byte) error { if parallel == 0 { parallel = runtime.GOMAXPROCS(0) @@ -67,7 +71,6 @@ func CoordinateFuzzing(parallel int, seed [][]byte) error { corpus.entries = append(corpus.entries, corpusEntry{b: []byte{0}}) } - // TODO(jayconrod,katiehockman): read corpus from testdata. // TODO(jayconrod,katiehockman): read corpus from GOFUZZCACHE. // Start workers. @@ -141,3 +144,27 @@ type coordinator struct { // values from this channel. inputC chan corpusEntry } + +// ReadCorpus reads the corpus from the testdata directory in this target's +// package. +func ReadCorpus(name string) ([][]byte, error) { + testdataDir := filepath.Join("testdata/corpus", name) + files, err := ioutil.ReadDir(testdataDir) + if os.IsNotExist(err) { + return nil, nil // No corpus to read + } else if err != nil { + return nil, fmt.Errorf("testing: reading seed corpus from testdata: %v", err) + } + var corpus [][]byte + for _, file := range files { + if file.IsDir() { + continue + } + bytes, err := ioutil.ReadFile(filepath.Join(testdataDir, file.Name())) + if err != nil { + return nil, fmt.Errorf("testing: failed to read corpus file: %v", err) + } + corpus = append(corpus, bytes) + } + return corpus, nil +} diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 766242f75d..ff13e0b4e0 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -44,6 +44,14 @@ type corpusEntry struct { b []byte } +func bytesToCorpus(bytes [][]byte) []corpusEntry { + c := make([]corpusEntry, len(bytes)) + for i, b := range bytes { + c[i].b = b + } + return c +} + // Add will add the arguments to the seed corpus for the fuzz target. This will // be a no-op if called after or within the Fuzz function. The args must match // those in the Fuzz function. @@ -76,6 +84,14 @@ func (f *F) Fuzz(ff interface{}) { panic("testing: Fuzz function must have type func(*testing.T, []byte)") } + // Load seed corpus + c, err := f.context.readCorpus(f.name) + if err != nil { + f.Fatal(err) + } + f.corpus = append(f.corpus, bytesToCorpus(c)...) + // TODO(jayconrod,katiehockman): dedupe testdata corpus with entries from f.Add + defer runtime.Goexit() // exit after this function var errStr string @@ -187,22 +203,22 @@ func (f *F) report() { } // run runs each fuzz target in its own goroutine with its own *F. -func (f *F) run(name string, fn func(f *F)) (ran, ok bool) { - innerF := &F{ +func (f *F) run(ft InternalFuzzTarget) (ran, ok bool) { + f = &F{ common: common{ signal: make(chan bool), - name: name, + name: ft.Name, chatty: f.chatty, w: f.w, }, context: f.context, } - if innerF.chatty != nil { - innerF.chatty.Updatef(name, "=== RUN %s\n", name) + if f.chatty != nil { + f.chatty.Updatef(ft.Name, "=== RUN %s\n", ft.Name) } - go innerF.runTarget(fn) - <-innerF.signal - return innerF.ran, !innerF.failed + go f.runTarget(ft.Fn) + <-f.signal + return f.ran, !f.failed } // runTarget runs the given target, handling panics and exits @@ -254,17 +270,21 @@ type fuzzContext struct { fuzzMatch *matcher coordinateFuzzing func(int, [][]byte) error runFuzzWorker func(func([]byte) error) error + readCorpus func(string) ([][]byte, error) } // runFuzzTargets runs the fuzz targets matching the pattern for -run. This will // only run the f.Fuzz function for each seed corpus without using the fuzzing // engine to generate or mutate inputs. -func runFuzzTargets(matchString func(pat, str string) (bool, error), fuzzTargets []InternalFuzzTarget) (ran, ok bool) { +func runFuzzTargets(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran, ok bool) { ok = true if len(fuzzTargets) == 0 || *isFuzzWorker { return ran, ok } - ctx := &fuzzContext{runMatch: newMatcher(matchString, *match, "-test.run")} + ctx := &fuzzContext{ + runMatch: newMatcher(deps.MatchString, *match, "-test.run"), + readCorpus: deps.ReadCorpus, + } var fts []InternalFuzzTarget for _, ft := range fuzzTargets { if _, matched, _ := ctx.runMatch.fullName(nil, ft.Name); matched { @@ -278,7 +298,7 @@ func runFuzzTargets(matchString func(pat, str string) (bool, error), fuzzTargets fuzzFunc: func(f *F) { for _, ft := range fts { // Run each fuzz target in it's own goroutine. - ftRan, ftOk := f.run(ft.Name, ft.Fn) + ftRan, ftOk := f.run(ft) ran = ran || ftRan ok = ok && ftOk } @@ -302,7 +322,10 @@ func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran, ok bool) if len(fuzzTargets) == 0 || *matchFuzz == "" { return false, true } - ctx := &fuzzContext{fuzzMatch: newMatcher(deps.MatchString, *matchFuzz, "-test.fuzz")} + ctx := &fuzzContext{ + fuzzMatch: newMatcher(deps.MatchString, *matchFuzz, "-test.fuzz"), + readCorpus: deps.ReadCorpus, + } if *isFuzzWorker { ctx.runFuzzWorker = deps.RunFuzzWorker } else { diff --git a/src/testing/internal/testdeps/deps.go b/src/testing/internal/testdeps/deps.go index 9665092f4c..acd38d78cb 100644 --- a/src/testing/internal/testdeps/deps.go +++ b/src/testing/internal/testdeps/deps.go @@ -135,3 +135,7 @@ func (TestDeps) CoordinateFuzzing(parallel int, seed [][]byte) error { func (TestDeps) RunFuzzWorker(fn func([]byte) error) error { return fuzz.RunFuzzWorker(fn) } + +func (TestDeps) ReadCorpus(name string) ([][]byte, error) { + return fuzz.ReadCorpus(name) +} diff --git a/src/testing/testing.go b/src/testing/testing.go index 2c2e77dc4b..f44b7ca7a5 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1326,6 +1326,7 @@ func (f matchStringOnly) StopTestLog() error { return e func (f matchStringOnly) SetPanicOnExit0(bool) {} func (f matchStringOnly) CoordinateFuzzing(int, [][]byte) error { return errMain } func (f matchStringOnly) RunFuzzWorker(func([]byte) error) error { return errMain } +func (f matchStringOnly) ReadCorpus(name string) ([][]byte, error) { return nil, errMain } // Main is an internal function, part of the implementation of the "go test" command. // It was exported because it is cross-package and predates "internal" packages. @@ -1370,6 +1371,7 @@ type testDeps interface { WriteProfileTo(string, io.Writer, int) error CoordinateFuzzing(int, [][]byte) error RunFuzzWorker(func([]byte) error) error + ReadCorpus(name string) ([][]byte, error) } // MainStart is meant for use by tests generated by 'go test'. @@ -1423,7 +1425,7 @@ func (m *M) Run() (code int) { deadline := m.startAlarm() haveExamples = len(m.examples) > 0 testRan, testOk := runTests(m.deps.MatchString, m.tests, deadline) - fuzzTargetsRan, fuzzTargetsOk := runFuzzTargets(m.deps.MatchString, m.fuzzTargets) + fuzzTargetsRan, fuzzTargetsOk := runFuzzTargets(m.deps, m.fuzzTargets) exampleRan, exampleOk := runExamples(m.deps.MatchString, m.examples) m.stopAlarm() if !testRan && !exampleRan && !fuzzTargetsRan && *matchBenchmarks == "" && *matchFuzz == "" { -- GitLab From f5d0fa82af1dbb752bb256f0761ec3f50f58db8f Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Mon, 19 Oct 2020 11:04:37 -0400 Subject: [PATCH 0012/2500] [dev.fuzz] testing: cleanup a few small things Deletes the exported testing.Fuzz function which would run a standalone fuzz target. Similar to RunFuzzing and RunFuzzTargets, which were previously removed, this will likely be too complex to support. Moves the deferred Exit in f.Fuzz higher up the function so it is always run. Change-Id: I9ea6210dc30dee8c2a943bfb8077225c369cfb95 Reviewed-on: https://go-review.googlesource.com/c/go/+/263642 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/testing/fuzz.go | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index ff13e0b4e0..ce66000a3a 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -79,6 +79,8 @@ func (f *F) Add(args ...interface{}) { // target by calling runtime.Goexit. To run any code after this function, use // Cleanup. func (f *F) Fuzz(ff interface{}) { + defer runtime.Goexit() // exit after this function + fn, ok := ff.(func(*T, []byte)) if !ok { panic("testing: Fuzz function must have type func(*testing.T, []byte)") @@ -92,8 +94,6 @@ func (f *F) Fuzz(ff interface{}) { f.corpus = append(f.corpus, bytesToCorpus(c)...) // TODO(jayconrod,katiehockman): dedupe testdata corpus with entries from f.Add - defer runtime.Goexit() // exit after this function - var errStr string run := func(t *T, b []byte) { defer func() { @@ -364,19 +364,3 @@ func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran, ok bool) <-f.signal return f.ran, !f.failed } - -// Fuzz runs a single fuzz target. It is useful for creating -// custom fuzz targets that do not use the "go test" command. -// -// If fn depends on testing flags, then Init must be used to register -// those flags before calling Fuzz and before calling flag.Parse. -func Fuzz(fn func(f *F)) FuzzResult { - f := &F{ - common: common{ - w: discard{}, - }, - fuzzFunc: fn, - } - // TODO(katiehockman): run the test - return f.result -} -- GitLab From c3a4e8dd8224d6ac46513fe4a7c909908a22395b Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Mon, 19 Oct 2020 13:48:28 -0400 Subject: [PATCH 0013/2500] [dev.fuzz] internal/fuzz: implement basic mutator and use in worker Note that this is an extremely basic mutator, and only meant to act as a placeholder for future development. Change-Id: I650691db44f30953345702aac93cbd1cadc21427 Reviewed-on: https://go-review.googlesource.com/c/go/+/263657 Trust: Katie Hockman Trust: Jay Conrod Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/go/build/deps_test.go | 2 +- src/internal/fuzz/mutator.go | 18 ++++++++++++++++++ src/internal/fuzz/worker.go | 28 +++++++++++++++++++++------- 3 files changed, 40 insertions(+), 8 deletions(-) create mode 100644 src/internal/fuzz/mutator.go diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index e5f38d4fbc..26f6ab2ec3 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -467,7 +467,7 @@ var depsRules = ` FMT, flag, runtime/debug, runtime/trace < testing; - FMT, encoding/json + FMT, encoding/json, math/rand < internal/fuzz; internal/fuzz, internal/testlog, runtime/pprof, regexp diff --git a/src/internal/fuzz/mutator.go b/src/internal/fuzz/mutator.go new file mode 100644 index 0000000000..229bb31a11 --- /dev/null +++ b/src/internal/fuzz/mutator.go @@ -0,0 +1,18 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fuzz + +import "math/rand" + +func mutate(b []byte) []byte { + mutated := make([]byte, len(b)) + copy(mutated, b) + + // Mutate a byte in a random position. + pos := rand.Intn(len(mutated)) + mutated[pos] = byte(rand.Intn(256)) + + return mutated +} diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 543e352e7f..0aa7015c66 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -81,8 +81,8 @@ func (w *worker) runFuzzing() error { inputC = nil // block new inputs until we finish with this one. go func() { args := fuzzArgs{ - Value: input.b, - DurationSec: workerFuzzDuration.Seconds(), + Value: input.b, + Duration: workerFuzzDuration, } _, err := w.client.fuzz(args) if err != nil { @@ -282,11 +282,14 @@ type call struct { } type fuzzArgs struct { - Value []byte - DurationSec float64 + Value []byte + Duration time.Duration } -type fuzzResponse struct{} +type fuzzResponse struct { + Crasher []byte + Err string +} // workerServer is a minimalist RPC server, run in fuzz worker processes. type workerServer struct { @@ -326,8 +329,19 @@ func (ws *workerServer) serve(fuzzIn io.ReadCloser, fuzzOut io.WriteCloser) erro // a given amount of time. fuzz returns early if it finds an input that crashes // the fuzz function or an input that expands coverage. func (ws *workerServer) fuzz(args fuzzArgs) fuzzResponse { - // TODO(jayconrod, katiehockman): implement - return fuzzResponse{} + t := time.NewTimer(args.Duration) + for { + select { + case <-t.C: + return fuzzResponse{} + default: + b := mutate(args.Value) + if err := ws.fn(b); err != nil { + return fuzzResponse{Crasher: b, Err: err.Error()} + } + // TODO(jayconrod,katiehockman): return early if coverage is expanded + } + } } // workerClient is a minimalist RPC client, run in the fuzz coordinator. -- GitLab From a01814975c18ff1a63847eb82e0a57f7c3c746e5 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Fri, 16 Oct 2020 17:42:39 -0400 Subject: [PATCH 0014/2500] [dev.fuzz] internal/fuzz: send inputs to workers with shared memory The coordinator process creates a temporary file for each worker. Both coordinator and worker map the file into memory and use it for input values. Access is synchronized with RPC over pipes. Change-Id: I43c10d7291a8760a616b472d11c017a3a7bb19cf Reviewed-on: https://go-review.googlesource.com/c/go/+/263153 Reviewed-by: Katie Hockman Trust: Jay Conrod --- .../go/testdata/script/test_fuzz_mutate.txt | 153 ++++++++++++++++++ src/internal/fuzz/fuzz.go | 59 ++++--- src/internal/fuzz/mem.go | 107 ++++++++++++ src/internal/fuzz/sys_posix.go | 64 +++++++- src/internal/fuzz/sys_unimplemented.go | 31 ++++ src/internal/fuzz/sys_windows.go | 118 ++++++++++++-- src/internal/fuzz/worker.go | 87 ++++++---- src/testing/fuzz.go | 27 ++-- 8 files changed, 555 insertions(+), 91 deletions(-) create mode 100644 src/cmd/go/testdata/script/test_fuzz_mutate.txt create mode 100644 src/internal/fuzz/mem.go create mode 100644 src/internal/fuzz/sys_unimplemented.go diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate.txt b/src/cmd/go/testdata/script/test_fuzz_mutate.txt new file mode 100644 index 0000000000..b881292dc8 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_mutate.txt @@ -0,0 +1,153 @@ +# Test basic fuzzing mutator behavior. +# +# fuzz_test.go has two fuzz targets (FuzzA, FuzzB) which both add a seed value. +# Each fuzz function writes the input to a log file. The coordinator and worker +# use separate log files. check_logs.go verifies that the coordinator only +# tests seed values and the worker tests mutated values on the fuzz target. + +[short] skip + +go test -fuzz=FuzzA -parallel=1 -log=fuzz +go run check_logs.go fuzz fuzz.worker + +-- go.mod -- +module m + +go 1.16 +-- fuzz_test.go -- +package fuzz_test + +import ( + "flag" + "fmt" + "os" + "testing" +) + +var ( + logPath = flag.String("log", "", "path to log file") + logFile *os.File +) + +func TestMain(m *testing.M) { + flag.Parse() + var err error + logFile, err = os.OpenFile(*logPath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666) + if os.IsExist(err) { + *logPath += ".worker" + logFile, err = os.OpenFile(*logPath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666) + } + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + os.Exit(m.Run()) +} + +func FuzzA(f *testing.F) { + f.Add([]byte("seed")) + f.Fuzz(func(t *testing.T, b []byte) { + fmt.Fprintf(logFile, "FuzzA %q\n", b) + }) +} + +func FuzzB(f *testing.F) { + f.Add([]byte("seed")) + f.Fuzz(func(t *testing.T, b []byte) { + fmt.Fprintf(logFile, "FuzzB %q\n", b) + }) +} + +-- check_logs.go -- +// +build ignore + +package main + +import ( + "bufio" + "fmt" + "io" + "os" + "strings" +) + +func main() { + coordPath, workerPath := os.Args[1], os.Args[2] + + coordLog, err := os.Open(coordPath) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + defer coordLog.Close() + if err := checkCoordLog(coordLog); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + + workerLog, err := os.Open(workerPath) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + defer workerLog.Close() + if err := checkWorkerLog(workerLog); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} + +func checkCoordLog(r io.Reader) error { + scan := bufio.NewScanner(r) + var sawASeed, sawBSeed bool + for scan.Scan() { + line := scan.Text() + switch { + case line == `FuzzA "seed"`: + if sawASeed { + return fmt.Errorf("coordinator: tested FuzzA seed multiple times") + } + sawASeed = true + + case line == `FuzzB "seed"`: + if sawBSeed { + return fmt.Errorf("coordinator: tested FuzzB seed multiple times") + } + sawBSeed = true + + default: + return fmt.Errorf("coordinator: tested something other than seeds: %s", line) + } + } + if err := scan.Err(); err != nil { + return err + } + if !sawASeed { + return fmt.Errorf("coordinator: did not test FuzzA seed") + } + if !sawBSeed { + return fmt.Errorf("coordinator: did not test FuzzB seed") + } + return nil +} + +func checkWorkerLog(r io.Reader) error { + scan := bufio.NewScanner(r) + var sawAMutant bool + for scan.Scan() { + line := scan.Text() + if !strings.HasPrefix(line, "FuzzA ") { + return fmt.Errorf("worker: tested something other than target: %s", line) + } + if strings.TrimPrefix(line, "FuzzA ") != `"seed"` { + sawAMutant = true + } + } + if err := scan.Err(); err != nil { + return err + } + if !sawAMutant { + return fmt.Errorf("worker: did not test any mutants") + } + return nil +} diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index d7187d043e..b72106b337 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -40,6 +40,22 @@ func CoordinateFuzzing(parallel int, seed [][]byte) error { // interrupts. duration := 5 * time.Second + var corpus corpus + var maxSeedLen int + if len(seed) == 0 { + corpus.entries = []corpusEntry{{b: []byte{}}} + maxSeedLen = 0 + } else { + corpus.entries = make([]corpusEntry, len(seed)) + for i, v := range seed { + corpus.entries[i].b = v + if len(v) > maxSeedLen { + maxSeedLen = len(v) + } + } + } + // TODO(jayconrod,katiehockman): read corpus from GOFUZZCACHE. + // TODO(jayconrod): do we want to support fuzzing different binaries? dir := "" // same as self binPath := os.Args[0] @@ -51,38 +67,41 @@ func CoordinateFuzzing(parallel int, seed [][]byte) error { inputC: make(chan corpusEntry), } - newWorker := func() *worker { + newWorker := func() (*worker, error) { + mem, err := sharedMemTempFile(maxSeedLen) + if err != nil { + return nil, err + } return &worker{ dir: dir, binPath: binPath, args: args, env: env, coordinator: c, - } - } - - corpus := corpus{entries: make([]corpusEntry, len(seed))} - for i, v := range seed { - corpus.entries[i].b = v - } - if len(corpus.entries) == 0 { - // TODO(jayconrod,katiehockman): pick a good starting corpus when one is - // missing or very small. - corpus.entries = append(corpus.entries, corpusEntry{b: []byte{0}}) + mem: mem, + }, nil } - // TODO(jayconrod,katiehockman): read corpus from GOFUZZCACHE. - // Start workers. workers := make([]*worker, parallel) - runErrs := make([]error, parallel) + for i := range workers { + var err error + workers[i], err = newWorker() + if err != nil { + return err + } + } + + workerErrs := make([]error, len(workers)) var wg sync.WaitGroup - wg.Add(parallel) - for i := 0; i < parallel; i++ { + wg.Add(len(workers)) + for i := range workers { go func(i int) { defer wg.Done() - workers[i] = newWorker() - runErrs[i] = workers[i].runFuzzing() + workerErrs[i] = workers[i].runFuzzing() + if cleanErr := workers[i].cleanup(); workerErrs[i] == nil { + workerErrs[i] = cleanErr + } }(i) } @@ -102,7 +121,7 @@ func CoordinateFuzzing(parallel int, seed [][]byte) error { case <-c.doneC: // Wait for workers to stop and return. wg.Wait() - for _, err := range runErrs { + for _, err := range workerErrs { if err != nil { return err } diff --git a/src/internal/fuzz/mem.go b/src/internal/fuzz/mem.go new file mode 100644 index 0000000000..2bb5736cf5 --- /dev/null +++ b/src/internal/fuzz/mem.go @@ -0,0 +1,107 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fuzz + +import ( + "fmt" + "io/ioutil" + "os" + "unsafe" +) + +// sharedMem manages access to a region of virtual memory mapped from a file, +// shared between multiple processes. The region includes space for a header and +// a value of variable length. +// +// When fuzzing, the coordinator creates a sharedMem from a temporary file for +// each worker. This buffer is used to pass values to fuzz between processes. +// +// Care must be taken to synchronize access to shared memory across processes. +// For example, workerClient and workerServer use an RPC protocol over pipes: +// workerServer may access shared memory when handling an RPC; workerClient may +// access shared memory at other times. +type sharedMem struct { + // f is the file mapped into memory. + f *os.File + + // region is the mapped region of virtual memory for f. The content of f may + // be read or written through this slice. + region []byte + + // removeOnClose is true if the file should be deleted by Close. + removeOnClose bool + + // sys contains OS-specific information. + sys sharedMemSys +} + +// sharedMemHeader stores metadata in shared memory. +type sharedMemHeader struct { + length int +} + +// sharedMemSize returns the size needed for a shared memory buffer that can +// contain values of the given size. +func sharedMemSize(valueSize int) int { + // TODO(jayconrod): set a reasonable maximum size per platform. + return int(unsafe.Sizeof(sharedMemHeader{})) + valueSize +} + +// sharedMemTempFile creates a new temporary file large enough to hold a value +// of the given size, then maps it into memory. The file will be removed when +// the Close method is called. +func sharedMemTempFile(valueSize int) (m *sharedMem, err error) { + // Create a temporary file. + f, err := ioutil.TempFile("", "fuzz-*") + if err != nil { + return nil, err + } + defer func() { + if err != nil { + f.Close() + os.Remove(f.Name()) + } + }() + + // Resize it to the correct size. + totalSize := sharedMemSize(valueSize) + if err := f.Truncate(int64(totalSize)); err != nil { + return nil, err + } + + // Map the file into memory. + removeOnClose := true + return sharedMemMapFile(f, totalSize, removeOnClose) +} + +// header returns a pointer to metadata within the shared memory region. +func (m *sharedMem) header() *sharedMemHeader { + return (*sharedMemHeader)(unsafe.Pointer(&m.region[0])) +} + +// value returns the value currently stored in shared memory. The returned slice +// points to shared memory; it is not a copy. +func (m *sharedMem) value() []byte { + length := m.header().length + valueOffset := int(unsafe.Sizeof(sharedMemHeader{})) + return m.region[valueOffset : valueOffset+length] +} + +// setValue copies the data in b into the shared memory buffer and sets +// the length. len(b) must be less than or equal to the capacity of the buffer +// (as returned by cap(m.value())). +func (m *sharedMem) setValue(b []byte) { + v := m.value() + if len(b) > cap(v) { + panic(fmt.Sprintf("value length %d larger than shared memory capacity %d", len(b), cap(v))) + } + m.header().length = len(b) + copy(v[:cap(v)], b) +} + +// TODO(jayconrod): add method to resize the buffer. We'll need that when the +// mutator can increase input length. Only the coordinator will be able to +// do it, since we'll need to send a message to the worker telling it to +// remap the file. diff --git a/src/internal/fuzz/sys_posix.go b/src/internal/fuzz/sys_posix.go index 259caa8a59..ec27b4bf00 100644 --- a/src/internal/fuzz/sys_posix.go +++ b/src/internal/fuzz/sys_posix.go @@ -2,24 +2,74 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !windows +// +build darwin linux package fuzz import ( + "fmt" "os" "os/exec" + "syscall" ) +type sharedMemSys struct{} + +func sharedMemMapFile(f *os.File, size int, removeOnClose bool) (*sharedMem, error) { + prot := syscall.PROT_READ | syscall.PROT_WRITE + flags := syscall.MAP_FILE | syscall.MAP_SHARED + region, err := syscall.Mmap(int(f.Fd()), 0, size, prot, flags) + if err != nil { + return nil, err + } + + return &sharedMem{f: f, region: region, removeOnClose: removeOnClose}, nil +} + +// Close unmaps the shared memory and closes the temporary file. If this +// sharedMem was created with sharedMemTempFile, Close also removes the file. +func (m *sharedMem) Close() error { + // Attempt all operations, even if we get an error for an earlier operation. + // os.File.Close may fail due to I/O errors, but we still want to delete + // the temporary file. + var errs []error + errs = append(errs, + syscall.Munmap(m.region), + m.f.Close()) + if m.removeOnClose { + errs = append(errs, os.Remove(m.f.Name())) + } + for _, err := range errs { + if err != nil { + return err + } + } + return nil +} + // setWorkerComm configures communciation channels on the cmd that will // run a worker process. -func setWorkerComm(cmd *exec.Cmd, fuzzIn, fuzzOut *os.File) { - cmd.ExtraFiles = []*os.File{fuzzIn, fuzzOut} +func setWorkerComm(cmd *exec.Cmd, comm workerComm) { + cmd.ExtraFiles = []*os.File{comm.fuzzIn, comm.fuzzOut, comm.mem.f} } // getWorkerComm returns communication channels in the worker process. -func getWorkerComm() (fuzzIn, fuzzOut *os.File, err error) { - fuzzIn = os.NewFile(3, "fuzz_in") - fuzzOut = os.NewFile(4, "fuzz_out") - return fuzzIn, fuzzOut, nil +func getWorkerComm() (comm workerComm, err error) { + fuzzIn := os.NewFile(3, "fuzz_in") + fuzzOut := os.NewFile(4, "fuzz_out") + memFile := os.NewFile(5, "fuzz_mem") + fi, err := memFile.Stat() + if err != nil { + return workerComm{}, err + } + size := int(fi.Size()) + if int64(size) != fi.Size() { + return workerComm{}, fmt.Errorf("fuzz temp file exceeds maximum size") + } + removeOnClose := false + mem, err := sharedMemMapFile(memFile, size, removeOnClose) + if err != nil { + return workerComm{}, err + } + return workerComm{fuzzIn: fuzzIn, fuzzOut: fuzzOut, mem: mem}, nil } diff --git a/src/internal/fuzz/sys_unimplemented.go b/src/internal/fuzz/sys_unimplemented.go new file mode 100644 index 0000000000..dbb380ef67 --- /dev/null +++ b/src/internal/fuzz/sys_unimplemented.go @@ -0,0 +1,31 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// TODO(jayconrod): support more platforms. +// +build !darwin,!linux,!windows + +package fuzz + +import ( + "os" + "os/exec" +) + +type sharedMemSys struct{} + +func sharedMemMapFile(f *os.File, size int, removeOnClose bool) (*sharedMem, error) { + panic("not implemented") +} + +func (m *sharedMem) Close() error { + panic("not implemented") +} + +func setWorkerComm(cmd *exec.Cmd, comm workerComm) { + panic("not implemented") +} + +func getWorkerComm() (comm workerComm, err error) { + panic("not implemented") +} diff --git a/src/internal/fuzz/sys_windows.go b/src/internal/fuzz/sys_windows.go index a67548477b..286634c692 100644 --- a/src/internal/fuzz/sys_windows.go +++ b/src/internal/fuzz/sys_windows.go @@ -2,48 +2,132 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build windows - package fuzz import ( "fmt" "os" "os/exec" + "reflect" "strconv" "strings" "syscall" + "unsafe" ) +type sharedMemSys struct { + mapObj syscall.Handle +} + +func sharedMemMapFile(f *os.File, size int, removeOnClose bool) (*sharedMem, error) { + // Create a file mapping object. The object itself is not shared. + mapObj, err := syscall.CreateFileMapping( + syscall.Handle(f.Fd()), // fhandle + nil, // sa + syscall.PAGE_READWRITE, // prot + 0, // maxSizeHigh + 0, // maxSizeLow + nil, // name + ) + if err != nil { + return nil, err + } + + // Create a view from the file mapping object. + access := uint32(syscall.FILE_MAP_READ | syscall.FILE_MAP_WRITE) + addr, err := syscall.MapViewOfFile( + mapObj, // handle + access, // access + 0, // offsetHigh + 0, // offsetLow + uintptr(size), // length + ) + if err != nil { + syscall.CloseHandle(mapObj) + return nil, err + } + + var region []byte + header := (*reflect.SliceHeader)(unsafe.Pointer(®ion)) + header.Data = addr + header.Len = size + header.Cap = size + return &sharedMem{ + f: f, + region: region, + removeOnClose: removeOnClose, + sys: sharedMemSys{mapObj: mapObj}, + }, nil +} + +// Close unmaps the shared memory and closes the temporary file. If this +// sharedMem was created with sharedMemTempFile, Close also removes the file. +func (m *sharedMem) Close() error { + // Attempt all operations, even if we get an error for an earlier operation. + // os.File.Close may fail due to I/O errors, but we still want to delete + // the temporary file. + var errs []error + errs = append(errs, + syscall.UnmapViewOfFile(uintptr(unsafe.Pointer(&m.region[0]))), + syscall.CloseHandle(m.sys.mapObj), + m.f.Close()) + if m.removeOnClose { + errs = append(errs, os.Remove(m.f.Name())) + } + for _, err := range errs { + if err != nil { + return err + } + } + return nil +} + // setWorkerComm configures communciation channels on the cmd that will // run a worker process. -func setWorkerComm(cmd *exec.Cmd, fuzzIn, fuzzOut *os.File) { - syscall.SetHandleInformation(syscall.Handle(fuzzIn.Fd()), syscall.HANDLE_FLAG_INHERIT, 1) - syscall.SetHandleInformation(syscall.Handle(fuzzOut.Fd()), syscall.HANDLE_FLAG_INHERIT, 1) - cmd.Env = append(cmd.Env, fmt.Sprintf("GO_TEST_FUZZ_WORKER_HANDLES=%x,%x", fuzzIn.Fd(), fuzzOut.Fd())) +func setWorkerComm(cmd *exec.Cmd, comm workerComm) { + syscall.SetHandleInformation(syscall.Handle(comm.fuzzIn.Fd()), syscall.HANDLE_FLAG_INHERIT, 1) + syscall.SetHandleInformation(syscall.Handle(comm.fuzzOut.Fd()), syscall.HANDLE_FLAG_INHERIT, 1) + syscall.SetHandleInformation(syscall.Handle(comm.mem.f.Fd()), syscall.HANDLE_FLAG_INHERIT, 1) + cmd.Env = append(cmd.Env, fmt.Sprintf("GO_TEST_FUZZ_WORKER_HANDLES=%x,%x,%x", comm.fuzzIn.Fd(), comm.fuzzOut.Fd(), comm.mem.f.Fd())) } // getWorkerComm returns communication channels in the worker process. -func getWorkerComm() (fuzzIn *os.File, fuzzOut *os.File, err error) { +func getWorkerComm() (comm workerComm, err error) { v := os.Getenv("GO_TEST_FUZZ_WORKER_HANDLES") if v == "" { - return nil, nil, fmt.Errorf("GO_TEST_FUZZ_WORKER_HANDLES not set") + return workerComm{}, fmt.Errorf("GO_TEST_FUZZ_WORKER_HANDLES not set") } parts := strings.Split(v, ",") - if len(parts) != 2 { - return nil, nil, fmt.Errorf("GO_TEST_FUZZ_WORKER_HANDLES has invalid value") + if len(parts) != 3 { + return workerComm{}, fmt.Errorf("GO_TEST_FUZZ_WORKER_HANDLES has invalid value") } base := 16 bitSize := 64 - in, err := strconv.ParseInt(parts[0], base, bitSize) + handles := make([]syscall.Handle, len(parts)) + for i, s := range parts { + h, err := strconv.ParseInt(s, base, bitSize) + if err != nil { + return workerComm{}, fmt.Errorf("GO_TEST_FUZZ_WORKER_HANDLES has invalid value: %v", err) + } + handles[i] = syscall.Handle(h) + } + + fuzzIn := os.NewFile(uintptr(handles[0]), "fuzz_in") + fuzzOut := os.NewFile(uintptr(handles[1]), "fuzz_out") + tmpFile := os.NewFile(uintptr(handles[2]), "fuzz_mem") + fi, err := tmpFile.Stat() if err != nil { - return nil, nil, fmt.Errorf("GO_TEST_FUZZ_WORKER_HANDLES has invalid value: %v", err) + return workerComm{}, err } - out, err := strconv.ParseInt(parts[1], base, bitSize) + size := int(fi.Size()) + if int64(size) != fi.Size() { + return workerComm{}, fmt.Errorf("fuzz temp file exceeds maximum size") + } + removeOnClose := false + mem, err := sharedMemMapFile(tmpFile, size, removeOnClose) if err != nil { - return nil, nil, fmt.Errorf("GO_TEST_FUZZ_WORKER_HANDLES has invalid value: %v", err) + return workerComm{}, err } - fuzzIn = os.NewFile(uintptr(in), "fuzz_in") - fuzzOut = os.NewFile(uintptr(out), "fuzz_out") - return fuzzIn, fuzzOut, nil + + return workerComm{fuzzIn: fuzzIn, fuzzOut: fuzzOut, mem: mem}, nil } diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 0aa7015c66..a194a5f9be 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -26,7 +26,10 @@ const ( workerTimeoutDuration = 1 * time.Second ) -// worker manages a worker process running a test binary. +// worker manages a worker process running a test binary. The worker object +// exists only in the coordinator (the process started by 'go test -fuzz'). +// workerClient is used by the coordinator to send RPCs to the worker process, +// which handles them with workerServer. type worker struct { dir string // working directory, same as package directory binPath string // path to test executable @@ -35,12 +38,24 @@ type worker struct { coordinator *coordinator + mem *sharedMem // shared memory with worker; persists across processes. + cmd *exec.Cmd // current worker process client *workerClient // used to communicate with worker process waitErr error // last error returned by wait, set before termC is closed. termC chan struct{} // closed by wait when worker process terminates } +// cleanup releases persistent resources associated with the worker. +func (w *worker) cleanup() error { + if w.mem == nil { + return nil + } + err := w.mem.Close() + w.mem = nil + return err +} + // runFuzzing runs the test binary to perform fuzzing. // // This function loops until w.coordinator.doneC is closed or some @@ -69,28 +84,27 @@ func (w *worker) runFuzzing() error { case <-w.termC: // Worker process terminated unexpectedly. // TODO(jayconrod,katiehockman): handle crasher. - - // Restart the process. - if err := w.start(); err != nil { - close(w.coordinator.doneC) - return err + // TODO(jayconrod,katiehockman): if -keepfuzzing, restart worker. + err := w.stop() + if err == nil { + err = fmt.Errorf("worker exited unexpectedly") } + close(w.coordinator.doneC) + return err case input := <-inputC: // Received input from coordinator. inputC = nil // block new inputs until we finish with this one. go func() { - args := fuzzArgs{ - Value: input.b, - Duration: workerFuzzDuration, - } - _, err := w.client.fuzz(args) + args := fuzzArgs{Duration: workerFuzzDuration} + _, err := w.client.fuzz(input.b, args) if err != nil { // TODO(jayconrod): if we get an error here, something failed between // main and the call to testing.F.Fuzz. The error here won't // be useful. Collect stderr, clean it up, and return that. // TODO(jayconrod): what happens if testing.F.Fuzz is never called? // TODO(jayconrod): time out if the test process hangs. + fmt.Fprintf(os.Stderr, "communicating with worker: %v\n", err) } fuzzC <- struct{}{} @@ -154,7 +168,7 @@ func (w *worker) start() (err error) { return err } defer fuzzOutW.Close() - setWorkerComm(cmd, fuzzInR, fuzzOutW) + setWorkerComm(cmd, workerComm{fuzzIn: fuzzInR, fuzzOut: fuzzOutW, mem: w.mem}) // Start the worker process. if err := cmd.Start(); err != nil { @@ -168,7 +182,7 @@ func (w *worker) start() (err error) { // called later by stop. w.cmd = cmd w.termC = make(chan struct{}) - w.client = newWorkerClient(fuzzInW, fuzzOutR) + w.client = newWorkerClient(workerComm{fuzzIn: fuzzInW, fuzzOut: fuzzOutR, mem: w.mem}) go func() { w.waitErr = w.cmd.Wait() @@ -266,12 +280,12 @@ func (w *worker) stop() error { // RunFuzzWorker returns an error if it could not communicate with the // coordinator process. func RunFuzzWorker(fn func([]byte) error) error { - fuzzIn, fuzzOut, err := getWorkerComm() + comm, err := getWorkerComm() if err != nil { return err } - srv := &workerServer{fn: fn} - return srv.serve(fuzzIn, fuzzOut) + srv := &workerServer{workerComm: comm, fn: fn} + return srv.serve() } // call is serialized and sent from the coordinator on fuzz_in. It acts as @@ -282,7 +296,6 @@ type call struct { } type fuzzArgs struct { - Value []byte Duration time.Duration } @@ -291,8 +304,16 @@ type fuzzResponse struct { Err string } +// workerComm holds objects needed for the worker client and server +// to communicate. +type workerComm struct { + fuzzIn, fuzzOut *os.File + mem *sharedMem +} + // workerServer is a minimalist RPC server, run in fuzz worker processes. type workerServer struct { + workerComm fn func([]byte) error } @@ -300,9 +321,9 @@ type workerServer struct { // // serve returns errors communicating over the pipes. It does not return // errors from methods; those are passed through response values. -func (ws *workerServer) serve(fuzzIn io.ReadCloser, fuzzOut io.WriteCloser) error { - enc := json.NewEncoder(fuzzOut) - dec := json.NewDecoder(fuzzIn) +func (ws *workerServer) serve() error { + enc := json.NewEncoder(ws.fuzzOut) + dec := json.NewDecoder(ws.fuzzIn) for { var c call if err := dec.Decode(&c); err == io.EOF { @@ -314,7 +335,8 @@ func (ws *workerServer) serve(fuzzIn io.ReadCloser, fuzzOut io.WriteCloser) erro var resp interface{} switch { case c.Fuzz != nil: - resp = ws.fuzz(*c.Fuzz) + value := ws.mem.value() + resp = ws.fuzz(value, *c.Fuzz) default: return errors.New("no arguments provided for any call") } @@ -328,14 +350,14 @@ func (ws *workerServer) serve(fuzzIn io.ReadCloser, fuzzOut io.WriteCloser) erro // fuzz runs the test function on random variations of a given input value for // a given amount of time. fuzz returns early if it finds an input that crashes // the fuzz function or an input that expands coverage. -func (ws *workerServer) fuzz(args fuzzArgs) fuzzResponse { +func (ws *workerServer) fuzz(value []byte, args fuzzArgs) fuzzResponse { t := time.NewTimer(args.Duration) for { select { case <-t.C: return fuzzResponse{} default: - b := mutate(args.Value) + b := mutate(value) if err := ws.fn(b); err != nil { return fuzzResponse{Crasher: b, Err: err.Error()} } @@ -346,18 +368,16 @@ func (ws *workerServer) fuzz(args fuzzArgs) fuzzResponse { // workerClient is a minimalist RPC client, run in the fuzz coordinator. type workerClient struct { - fuzzIn io.WriteCloser - fuzzOut io.ReadCloser - enc *json.Encoder - dec *json.Decoder + workerComm + enc *json.Encoder + dec *json.Decoder } -func newWorkerClient(fuzzIn io.WriteCloser, fuzzOut io.ReadCloser) *workerClient { +func newWorkerClient(comm workerComm) *workerClient { return &workerClient{ - fuzzIn: fuzzIn, - fuzzOut: fuzzOut, - enc: json.NewEncoder(fuzzIn), - dec: json.NewDecoder(fuzzOut), + workerComm: comm, + enc: json.NewEncoder(comm.fuzzIn), + dec: json.NewDecoder(comm.fuzzOut), } } @@ -382,7 +402,8 @@ func (wc *workerClient) Close() error { } // fuzz tells the worker to call the fuzz method. See workerServer.fuzz. -func (wc *workerClient) fuzz(args fuzzArgs) (fuzzResponse, error) { +func (wc *workerClient) fuzz(value []byte, args fuzzArgs) (fuzzResponse, error) { + wc.mem.setValue(value) c := call{Fuzz: &args} if err := wc.enc.Encode(c); err != nil { return fuzzResponse{}, err diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index ce66000a3a..100075ca2c 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -338,29 +338,28 @@ func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran, ok bool) }, context: ctx, } - var ( - ft InternalFuzzTarget - found int - ) - for _, ft = range fuzzTargets { + var target *InternalFuzzTarget + for i := range fuzzTargets { + ft := &fuzzTargets[i] testName, matched, _ := ctx.fuzzMatch.fullName(&f.common, ft.Name) - if matched { - found++ - if found > 1 { - fmt.Fprintln(os.Stderr, "testing: warning: -fuzz matches more than one target, won't fuzz") - return false, true - } - f.name = testName + if !matched { + continue + } + if target != nil { + fmt.Fprintln(os.Stderr, "testing: warning: -fuzz matches more than one target, won't fuzz") + return false, true } + target = ft + f.name = testName } - if found == 0 { + if target == nil { return false, true } if Verbose() { f.chatty = newChattyPrinter(f.w) f.chatty.Updatef(f.name, "--- FUZZ: %s\n", f.name) } - go f.runTarget(ft.Fn) + go f.runTarget(target.Fn) <-f.signal return f.ran, !f.failed } -- GitLab From db514c0caf5effb4396c9746e025c1ba2d717604 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Tue, 1 Dec 2020 17:37:07 -0500 Subject: [PATCH 0015/2500] [dev.fuzz] testing: fix duplicate logging when fuzzing The workers were printing PASS/FAIL logs and various others things, when that should be the sole responsibility of the coordinator process, which will have the aggregated data. Change-Id: I7ac9883db62f0fe79ba1799cb88773c542a2a948 Reviewed-on: https://go-review.googlesource.com/c/go/+/274652 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/testing/fuzz.go | 7 ++++++- src/testing/testing.go | 6 ++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 100075ca2c..5f65f8a395 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -191,6 +191,9 @@ func (f *F) Fuzz(ff interface{}) { } func (f *F) report() { + if *isFuzzWorker { + return + } if f.Failed() { fmt.Fprintf(f.w, "--- FAIL: %s\n%s\n", f.name, f.result.String()) } else if f.chatty != nil { @@ -357,7 +360,9 @@ func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran, ok bool) } if Verbose() { f.chatty = newChattyPrinter(f.w) - f.chatty.Updatef(f.name, "--- FUZZ: %s\n", f.name) + if !*isFuzzWorker { + f.chatty.Updatef(f.name, "--- FUZZ: %s\n", f.name) + } } go f.runTarget(target.Fn) <-f.signal diff --git a/src/testing/testing.go b/src/testing/testing.go index f44b7ca7a5..8b4f55215b 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1441,14 +1441,16 @@ func (m *M) Run() (code int) { if *matchFuzz != "" && !fuzzingRan { fmt.Fprintln(os.Stderr, "testing: warning: no targets to fuzz") } - if !fuzzingOk { + if !fuzzingOk && !*isFuzzWorker { fmt.Println("FAIL") m.exitCode = 1 return } - fmt.Println("PASS") m.exitCode = 0 + if !*isFuzzWorker { + fmt.Println("PASS") + } return } -- GitLab From 35f3b7053addf842690162d4d4937c0fbf438c50 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Thu, 3 Dec 2020 13:05:14 -0500 Subject: [PATCH 0016/2500] [dev.fuzz] internal/fuzz: add mutex to workerClient This prevents workerClient.Close from closing fuzzIn while workerClient.fuzz is writing to it concurrently. It also prevents multiple callers from writing to fuzzIn concurrently, though there's nothing that does that yet. This should prevent most "broken pipe" errors, though they may still be possible if worker.stop is called and it needs to kill the process due to a timeout. In the future, we should detect and ignore those errors, but for now, they're useful for debugging. Also, improve documentation on workerClient and workerServer. Change-Id: Ie2c870392d5e91674d3b1e32b2fa4f9de9ac3eb0 Reviewed-on: https://go-review.googlesource.com/c/go/+/275173 Run-TryBot: Jay Conrod TryBot-Result: Go Bot Trust: Jay Conrod Reviewed-by: Katie Hockman --- src/internal/fuzz/worker.go | 47 +++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index a194a5f9be..148cc6dae9 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -13,6 +13,7 @@ import ( "os" "os/exec" "runtime" + "sync" "time" ) @@ -102,6 +103,9 @@ func (w *worker) runFuzzing() error { // TODO(jayconrod): if we get an error here, something failed between // main and the call to testing.F.Fuzz. The error here won't // be useful. Collect stderr, clean it up, and return that. + // TODO(jayconrod): we can get EPIPE if w.stop is called concurrently + // and it kills the worker process. Suppress this message in + // that case. // TODO(jayconrod): what happens if testing.F.Fuzz is never called? // TODO(jayconrod): time out if the test process hangs. fmt.Fprintf(os.Stderr, "communicating with worker: %v\n", err) @@ -284,7 +288,7 @@ func RunFuzzWorker(fn func([]byte) error) error { if err != nil { return err } - srv := &workerServer{workerComm: comm, fn: fn} + srv := &workerServer{workerComm: comm, fuzzFn: fn} return srv.serve() } @@ -304,23 +308,36 @@ type fuzzResponse struct { Err string } -// workerComm holds objects needed for the worker client and server -// to communicate. +// workerComm holds pipes and shared memory used for communication +// between the coordinator process (client) and a worker process (server). type workerComm struct { fuzzIn, fuzzOut *os.File mem *sharedMem } -// workerServer is a minimalist RPC server, run in fuzz worker processes. +// workerServer is a minimalist RPC server, run by fuzz worker processes. +// It allows the coordinator process (using workerClient) to call methods in a +// worker process. This system allows the coordinator to run multiple worker +// processes in parallel and to collect inputs that caused crashes from shared +// memory after a worker process terminates unexpectedly. type workerServer struct { workerComm - fn func([]byte) error + + // fuzzFn runs the worker's fuzz function on the given input and returns + // an error if it finds a crasher (the process may also exit or crash). + fuzzFn func([]byte) error } -// serve deserializes and executes RPCs on a given pair of pipes. +// serve reads serialized RPC messages on fuzzIn. When serve receives a message, +// it calls the corresponding method, then sends the serialized result back +// on fuzzOut. +// +// serve handles RPC calls synchronously; it will not attempt to read a message +// until the previous call has finished. // -// serve returns errors communicating over the pipes. It does not return -// errors from methods; those are passed through response values. +// serve returns errors that occurred when communicating over pipes. serve +// does not return errors from method calls; those are passed through serialized +// responses. func (ws *workerServer) serve() error { enc := json.NewEncoder(ws.fuzzOut) dec := json.NewDecoder(ws.fuzzIn) @@ -358,7 +375,7 @@ func (ws *workerServer) fuzz(value []byte, args fuzzArgs) fuzzResponse { return fuzzResponse{} default: b := mutate(value) - if err := ws.fn(b); err != nil { + if err := ws.fuzzFn(b); err != nil { return fuzzResponse{Crasher: b, Err: err.Error()} } // TODO(jayconrod,katiehockman): return early if coverage is expanded @@ -366,9 +383,13 @@ func (ws *workerServer) fuzz(value []byte, args fuzzArgs) fuzzResponse { } } -// workerClient is a minimalist RPC client, run in the fuzz coordinator. +// workerClient is a minimalist RPC client. The coordinator process uses a +// workerClient to call methods in each worker process (handled by +// workerServer). type workerClient struct { workerComm + + mu sync.Mutex enc *json.Encoder dec *json.Decoder } @@ -385,6 +406,9 @@ func newWorkerClient(comm workerComm) *workerClient { // closing fuzz_in. Close drains fuzz_out (avoiding a SIGPIPE in the worker), // and closes it after the worker process closes the other end. func (wc *workerClient) Close() error { + wc.mu.Lock() + defer wc.mu.Unlock() + // Close fuzzIn. This signals to the server that there are no more calls, // and it should exit. if err := wc.fuzzIn.Close(); err != nil { @@ -403,6 +427,9 @@ func (wc *workerClient) Close() error { // fuzz tells the worker to call the fuzz method. See workerServer.fuzz. func (wc *workerClient) fuzz(value []byte, args fuzzArgs) (fuzzResponse, error) { + wc.mu.Lock() + defer wc.mu.Unlock() + wc.mem.setValue(value) c := call{Fuzz: &args} if err := wc.enc.Encode(c); err != nil { -- GitLab From 4651d6b267818b0e0d128a5443289717c4bb8cbc Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Wed, 2 Dec 2020 14:37:49 -0500 Subject: [PATCH 0017/2500] [dev.fuzz] internal/fuzzing: handle and report crashers Change-Id: Ie2a84c12f4991984974162e74f06cfd67e9bb4d7 Reviewed-on: https://go-review.googlesource.com/c/go/+/274855 Trust: Katie Hockman Run-TryBot: Katie Hockman Reviewed-by: Jay Conrod --- .../script/test_fuzz_mutate_crash.txt | 68 +++++++++++++++++ src/go/build/deps_test.go | 2 +- src/internal/fuzz/fuzz.go | 76 +++++++++++++++++-- src/internal/fuzz/worker.go | 47 ++++++++---- src/testing/fuzz.go | 28 ++++--- src/testing/internal/testdeps/deps.go | 8 +- src/testing/testing.go | 26 +++---- 7 files changed, 204 insertions(+), 51 deletions(-) create mode 100644 src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt new file mode 100644 index 0000000000..f28da90ac2 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt @@ -0,0 +1,68 @@ +# Tests that a crash caused by a mutator-discovered input writes the bad input +# to testdata, and fails+reports correctly. This tests the end-to-end behavior +# of the mutator finding a crash while fuzzing, adding it as a regression test +# to the seed corpus in testdata, and failing the next time the test is run. + +[short] skip + +# TODO: remove -parallel=1 once the races are fixed. + +# Running the seed corpus for all of the targets should pass the first +# time, since nothing in the seed corpus will cause a crash. +go test -parallel=1 + +# Running the fuzzer should find a crashing input quickly. +! go test -fuzz=FuzzWithBug -parallel=1 +stdout 'testdata/corpus/FuzzWithBug/fb8e20fc2e4c3f248c60c39bd652f3c1347298bb977b8b4d5903b85055620603' +stdout 'this input caused a crash!' +grep '\Aab\z' testdata/corpus/FuzzWithBug/fb8e20fc2e4c3f248c60c39bd652f3c1347298bb977b8b4d5903b85055620603 + +# Now, the failing bytes should have been added to the seed corpus for +# the target, and should fail when run without fuzzing. +! go test -parallel=1 + +! go test -run=FuzzWithNilPanic -fuzz=FuzzWithNilPanic -parallel=1 +stdout 'testdata/corpus/FuzzWithNilPanic/f45de51cdef30991551e41e882dd7b5404799648a0a00753f44fc966e6153fc1' +stdout 'runtime.Goexit' +grep '\Aac\z' testdata/corpus/FuzzWithNilPanic/f45de51cdef30991551e41e882dd7b5404799648a0a00753f44fc966e6153fc1 + +! go test -run=FuzzWithBadExit -fuzz=FuzzWithBadExit -parallel=1 +stdout 'testdata/corpus/FuzzWithBadExit/70ba33708cbfb103f1a8e34afef333ba7dc021022b2d9aaa583aabb8058d8d67' +stdout 'unexpectedly' +grep '\Aad\z' testdata/corpus/FuzzWithBadExit/70ba33708cbfb103f1a8e34afef333ba7dc021022b2d9aaa583aabb8058d8d67 + +-- fuzz_crash_test.go -- +package fuzz_crash + +import ( + "bytes" + "os" + "testing" +) + +func FuzzWithBug(f *testing.F) { + f.Add([]byte("aa")) + f.Fuzz(func(t *testing.T, b []byte) { + if bytes.Equal(b, []byte("ab")) { + panic("this input caused a crash!") + } + }) +} + +func FuzzWithNilPanic(f *testing.F) { + f.Add([]byte("aa")) + f.Fuzz(func(t *testing.T, b []byte) { + if bytes.Equal(b, []byte("ac")) { + panic(nil) + } + }) +} + +func FuzzWithBadExit(f *testing.F) { + f.Add([]byte("aa")) + f.Fuzz(func(t *testing.T, b []byte) { + if bytes.Equal(b, []byte("ad")) { + os.Exit(1) + } + }) +} \ No newline at end of file diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 26f6ab2ec3..7fb4feee82 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -467,7 +467,7 @@ var depsRules = ` FMT, flag, runtime/debug, runtime/trace < testing; - FMT, encoding/json, math/rand + FMT, crypto/sha256, encoding/json, math/rand < internal/fuzz; internal/fuzz, internal/testlog, runtime/pprof, regexp diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index b72106b337..930683000f 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -8,6 +8,7 @@ package fuzz import ( + "crypto/sha256" "fmt" "io/ioutil" "os" @@ -31,7 +32,10 @@ import ( // in testdata. // Seed values from GOFUZZCACHE should not be included in this list; this // function loads them separately. -func CoordinateFuzzing(parallel int, seed [][]byte) error { +// +// If a crash occurs, the function will return an error containing information +// about the crash, which can be reported to the user. +func CoordinateFuzzing(parallel int, seed [][]byte, crashDir string) error { if parallel == 0 { parallel = runtime.GOMAXPROCS(0) } @@ -63,8 +67,9 @@ func CoordinateFuzzing(parallel int, seed [][]byte) error { env := os.Environ() // same as self c := &coordinator{ - doneC: make(chan struct{}), - inputC: make(chan corpusEntry), + doneC: make(chan struct{}), + inputC: make(chan corpusEntry), + interestingC: make(chan fuzzResponse), } newWorker := func() (*worker, error) { @@ -128,6 +133,33 @@ func CoordinateFuzzing(parallel int, seed [][]byte) error { } return nil + case resp := <-c.interestingC: + // Some interesting input arrived from a worker. + if resp.Err != "" { + // This is a crasher, which should be written to testdata and + // reported to the user. + fileName, err := writeToCorpus(resp.Value, crashDir) + if err == nil { + err = fmt.Errorf(" Crash written to: %s\n%s", fileName, resp.Err) + } + // TODO(jayconrod,katiehockman): if -keepfuzzing, don't stop all + // of the workers, but still report to the user. + + // Stop the rest of the workers and wait until they have + // stopped before returning this error. + close(c.doneC) + wg.Wait() + return err + } else if len(resp.Value) > 0 { + // This is not a crasher, but something interesting that should + // be added to the on disk corpus and prioritized for future + // workers to fuzz. + + corpus.entries = append(corpus.entries, corpusEntry{b: resp.Value}) + // TODO(jayconrod, katiehockman): Add this to the on disk corpus + // TODO(jayconrod, katiehockman): Prioritize fuzzing these values which expanded coverage + } + case c.inputC <- corpus.entries[i]: // Sent the next input to any worker. // TODO(jayconrod,katiehockman): need a scheduling algorithm that chooses @@ -162,13 +194,17 @@ type coordinator struct { // inputC is sent values to fuzz by the coordinator. Any worker may receive // values from this channel. inputC chan corpusEntry + + // interestingC is sent interesting values by the worker, which is received + // by the coordinator. The interesting value could be a crash or some + // value that increased coverage. + interestingC chan fuzzResponse } // ReadCorpus reads the corpus from the testdata directory in this target's // package. -func ReadCorpus(name string) ([][]byte, error) { - testdataDir := filepath.Join("testdata/corpus", name) - files, err := ioutil.ReadDir(testdataDir) +func ReadCorpus(dir string) ([][]byte, error) { + files, err := ioutil.ReadDir(dir) if os.IsNotExist(err) { return nil, nil // No corpus to read } else if err != nil { @@ -179,7 +215,7 @@ func ReadCorpus(name string) ([][]byte, error) { if file.IsDir() { continue } - bytes, err := ioutil.ReadFile(filepath.Join(testdataDir, file.Name())) + bytes, err := ioutil.ReadFile(filepath.Join(dir, file.Name())) if err != nil { return nil, fmt.Errorf("testing: failed to read corpus file: %v", err) } @@ -187,3 +223,29 @@ func ReadCorpus(name string) ([][]byte, error) { } return corpus, nil } + +// writeToCorpus writes the given bytes to a new file in testdata. If the +// directory does not exist, it will create one. It returns the filename that +// was written, or an error if it failed. +func writeToCorpus(b []byte, crashDir string) (string, error) { + // TODO: Consider not writing a new file if one with those contents already + // exists. Perhaps the filename can be compared to those that already exist + // if all of the filenames are normalized, or by checking the contents of + // all other files. + if _, err := ioutil.ReadDir(crashDir); os.IsNotExist(err) { + // Make the seed corpus directory since it doesn't exist. + err = os.MkdirAll(crashDir, 0777) + if err != nil { + return "", err + } + } else if err != nil { + return "", err + } + sum := fmt.Sprintf("%x", sha256.Sum256(b)) + name := filepath.Join(crashDir, sum) + err := ioutil.WriteFile(name, b, 0666) + if err != nil { + return "", err + } + return name, nil +} diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 148cc6dae9..47d3009525 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -61,8 +61,7 @@ func (w *worker) cleanup() error { // // This function loops until w.coordinator.doneC is closed or some // fatal error is encountered. It receives inputs from w.coordinator.inputC, -// then passes those on to the worker process. If the worker crashes, -// runFuzzing restarts it and continues. +// then passes those on to the worker process. func (w *worker) runFuzzing() error { // Start the process. if err := w.start(); err != nil { @@ -83,14 +82,19 @@ func (w *worker) runFuzzing() error { return w.stop() case <-w.termC: - // Worker process terminated unexpectedly. - // TODO(jayconrod,katiehockman): handle crasher. + // Worker process terminated unexpectedly, so inform the coordinator + // that a crash occurred. + b := w.mem.value() // These are the bytes that caused the crash. + resB := make([]byte, len(b)) + copy(resB, b) + resp := fuzzResponse{Value: resB, Err: "fuzzing process crashed unexpectedly"} + w.coordinator.interestingC <- resp + // TODO(jayconrod,katiehockman): if -keepfuzzing, restart worker. err := w.stop() if err == nil { err = fmt.Errorf("worker exited unexpectedly") } - close(w.coordinator.doneC) return err case input := <-inputC: @@ -98,7 +102,7 @@ func (w *worker) runFuzzing() error { inputC = nil // block new inputs until we finish with this one. go func() { args := fuzzArgs{Duration: workerFuzzDuration} - _, err := w.client.fuzz(input.b, args) + resp, err := w.client.fuzz(input.b, args) if err != nil { // TODO(jayconrod): if we get an error here, something failed between // main and the call to testing.F.Fuzz. The error here won't @@ -109,15 +113,28 @@ func (w *worker) runFuzzing() error { // TODO(jayconrod): what happens if testing.F.Fuzz is never called? // TODO(jayconrod): time out if the test process hangs. fmt.Fprintf(os.Stderr, "communicating with worker: %v\n", err) + } else { + // TODO(jayconrod, katiehockman): Right now, this will just + // send an empty fuzzResponse{} if nothing interesting came + // up. Probably want to only pass to interestingC if fuzzing + // found something interesting. + + // Inform the coordinator that fuzzing found something + // interesting (ie. a crash or new coverage). + w.coordinator.interestingC <- resp + + if resp.Err == "" { + // Only unblock to allow more fuzzing to occur if + // everything was successful with the last fuzzing + // attempt. + fuzzC <- struct{}{} + } } - - fuzzC <- struct{}{} + // TODO(jayconrod,katiehockman): gather statistics. }() case <-fuzzC: - // Worker finished fuzzing. - // TODO(jayconrod,katiehockman): gather statistics. Collect "interesting" - // inputs and add to corpus. + // Worker finished fuzzing and nothing new happened. inputC = w.coordinator.inputC // unblock new inputs } } @@ -304,8 +321,8 @@ type fuzzArgs struct { } type fuzzResponse struct { - Crasher []byte - Err string + Value []byte // The bytes that yielded the response. + Err string // The error if the bytes resulted in a crash, nil otherwise. } // workerComm holds pipes and shared memory used for communication @@ -375,10 +392,12 @@ func (ws *workerServer) fuzz(value []byte, args fuzzArgs) fuzzResponse { return fuzzResponse{} default: b := mutate(value) + ws.mem.setValue(b) // Write the value to memory so it can be recovered it if the process dies if err := ws.fuzzFn(b); err != nil { - return fuzzResponse{Crasher: b, Err: err.Error()} + return fuzzResponse{Value: b, Err: err.Error()} } // TODO(jayconrod,katiehockman): return early if coverage is expanded + // by returning a fuzzResponse with the Value set but a nil Err. } } } diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 5f65f8a395..97d64f99be 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -9,6 +9,7 @@ import ( "flag" "fmt" "os" + "path/filepath" "runtime" "time" ) @@ -21,6 +22,10 @@ func initFuzzFlags() { var ( matchFuzz *string isFuzzWorker *bool + + // corpusDir is the parent directory of the target's seed corpus within + // the package. + corpusDir = "testdata/corpus" ) // InternalFuzzTarget is an internal type but exported because it is cross-package; @@ -87,7 +92,7 @@ func (f *F) Fuzz(ff interface{}) { } // Load seed corpus - c, err := f.context.readCorpus(f.name) + c, err := f.context.readCorpus(filepath.Join(corpusDir, f.name)) if err != nil { f.Fatal(err) } @@ -127,12 +132,15 @@ func (f *F) Fuzz(ff interface{}) { for i, e := range f.corpus { seed[i] = e.b } - err := f.context.coordinateFuzzing(*parallel, seed) + err := f.context.coordinateFuzzing(*parallel, seed, filepath.Join(corpusDir, f.name)) + if err != nil { + f.Fail() + f.result = FuzzResult{Error: err} + } f.setRan() f.finished = true - f.result = FuzzResult{Error: err} // TODO(jayconrod,katiehockman): Aggregate statistics across workers - // and set FuzzResult properly. + // and add to FuzzResult (ie. time taken, num iterations) case f.context.runFuzzWorker != nil: // Fuzzing is enabled, and this is a worker process. Follow instructions @@ -249,10 +257,9 @@ func (f *F) runTarget(fn func(*F)) { // FuzzResult contains the results of a fuzz run. type FuzzResult struct { - N int // The number of iterations. - T time.Duration // The total time taken. - Crasher *corpusEntry // Crasher is the corpus entry that caused the crash - Error error // Error is the error from the crash + N int // The number of iterations. + T time.Duration // The total time taken. + Error error // Error is the error from the crash } func (r FuzzResult) String() string { @@ -261,9 +268,6 @@ func (r FuzzResult) String() string { return s } s = fmt.Sprintf("%s", r.Error.Error()) - if r.Crasher != nil { - s += fmt.Sprintf("\ncrasher: %b", r.Crasher) - } return s } @@ -271,7 +275,7 @@ func (r FuzzResult) String() string { type fuzzContext struct { runMatch *matcher fuzzMatch *matcher - coordinateFuzzing func(int, [][]byte) error + coordinateFuzzing func(int, [][]byte, string) error runFuzzWorker func(func([]byte) error) error readCorpus func(string) ([][]byte, error) } diff --git a/src/testing/internal/testdeps/deps.go b/src/testing/internal/testdeps/deps.go index acd38d78cb..109d925016 100644 --- a/src/testing/internal/testdeps/deps.go +++ b/src/testing/internal/testdeps/deps.go @@ -128,14 +128,14 @@ func (TestDeps) SetPanicOnExit0(v bool) { testlog.SetPanicOnExit0(v) } -func (TestDeps) CoordinateFuzzing(parallel int, seed [][]byte) error { - return fuzz.CoordinateFuzzing(parallel, seed) +func (TestDeps) CoordinateFuzzing(parallel int, seed [][]byte, crashDir string) error { + return fuzz.CoordinateFuzzing(parallel, seed, crashDir) } func (TestDeps) RunFuzzWorker(fn func([]byte) error) error { return fuzz.RunFuzzWorker(fn) } -func (TestDeps) ReadCorpus(name string) ([][]byte, error) { - return fuzz.ReadCorpus(name) +func (TestDeps) ReadCorpus(dir string) ([][]byte, error) { + return fuzz.ReadCorpus(dir) } diff --git a/src/testing/testing.go b/src/testing/testing.go index 8b4f55215b..6267abfcdf 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1316,17 +1316,17 @@ var errMain = errors.New("testing: unexpected use of func Main") type matchStringOnly func(pat, str string) (bool, error) -func (f matchStringOnly) MatchString(pat, str string) (bool, error) { return f(pat, str) } -func (f matchStringOnly) StartCPUProfile(w io.Writer) error { return errMain } -func (f matchStringOnly) StopCPUProfile() {} -func (f matchStringOnly) WriteProfileTo(string, io.Writer, int) error { return errMain } -func (f matchStringOnly) ImportPath() string { return "" } -func (f matchStringOnly) StartTestLog(io.Writer) {} -func (f matchStringOnly) StopTestLog() error { return errMain } -func (f matchStringOnly) SetPanicOnExit0(bool) {} -func (f matchStringOnly) CoordinateFuzzing(int, [][]byte) error { return errMain } -func (f matchStringOnly) RunFuzzWorker(func([]byte) error) error { return errMain } -func (f matchStringOnly) ReadCorpus(name string) ([][]byte, error) { return nil, errMain } +func (f matchStringOnly) MatchString(pat, str string) (bool, error) { return f(pat, str) } +func (f matchStringOnly) StartCPUProfile(w io.Writer) error { return errMain } +func (f matchStringOnly) StopCPUProfile() {} +func (f matchStringOnly) WriteProfileTo(string, io.Writer, int) error { return errMain } +func (f matchStringOnly) ImportPath() string { return "" } +func (f matchStringOnly) StartTestLog(io.Writer) {} +func (f matchStringOnly) StopTestLog() error { return errMain } +func (f matchStringOnly) SetPanicOnExit0(bool) {} +func (f matchStringOnly) CoordinateFuzzing(int, [][]byte, string) error { return errMain } +func (f matchStringOnly) RunFuzzWorker(func([]byte) error) error { return errMain } +func (f matchStringOnly) ReadCorpus(string) ([][]byte, error) { return nil, errMain } // Main is an internal function, part of the implementation of the "go test" command. // It was exported because it is cross-package and predates "internal" packages. @@ -1369,9 +1369,9 @@ type testDeps interface { StartTestLog(io.Writer) StopTestLog() error WriteProfileTo(string, io.Writer, int) error - CoordinateFuzzing(int, [][]byte) error + CoordinateFuzzing(int, [][]byte, string) error RunFuzzWorker(func([]byte) error) error - ReadCorpus(name string) ([][]byte, error) + ReadCorpus(string) ([][]byte, error) } // MainStart is meant for use by tests generated by 'go test'. -- GitLab From c3dc22598829eec39b6b55e347ad4b974af24e12 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Mon, 14 Dec 2020 17:59:36 -0500 Subject: [PATCH 0018/2500] [dev.fuzz] cmd/go: fix test_fuzz_mutate_crash Add a go.mod file, which is needed now that GO111MODULE=on by default. Change-Id: I982f32afcf80ec190a2dd4603eb0aebc6fa22c67 Reviewed-on: https://go-review.googlesource.com/c/go/+/278052 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt index f28da90ac2..2effd44bf8 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt @@ -31,6 +31,10 @@ stdout 'testdata/corpus/FuzzWithBadExit/70ba33708cbfb103f1a8e34afef333ba7dc02102 stdout 'unexpectedly' grep '\Aad\z' testdata/corpus/FuzzWithBadExit/70ba33708cbfb103f1a8e34afef333ba7dc021022b2d9aaa583aabb8058d8d67 +-- go.mod -- +module m + +go 1.16 -- fuzz_crash_test.go -- package fuzz_crash -- GitLab From 97df3ba792bda80b99a8508cf36dfba3d1c37576 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Fri, 4 Dec 2020 18:07:20 -0500 Subject: [PATCH 0019/2500] [dev.fuzz] internal/fuzz: refactor in preparation for GOFUZZCACHE Several small changes, most related to GOFUZZCACHE. * Use separate channels to send crashers and interesting values to the coordinator. * Add a new type, crasherEntry, which is a corpusEntry with an error message. * Workers now send fatal errors to the coordinator via errC instead of returning or closing doneC. * In CoordinateFuzzing, defer code that closes doneC and waits for workers to stop. This is the only place where doneC is closed. * In workerServer and workerClient, always pass input values through shared memory instead of RPC messages or arguments to avoid confusion. * Rename sharedMem.value to valueRef and add valueCopy to make it clearer whether a reference or copy is needed. * mutate now operates on shared memory directly. * mutate will not panic on empty input. Change-Id: I6e57354875508f0ac4483ed2728f3ba18dc938c4 Reviewed-on: https://go-review.googlesource.com/c/go/+/275533 Run-TryBot: Jay Conrod TryBot-Result: Go Bot Trust: Jay Conrod Reviewed-by: Katie Hockman --- src/internal/fuzz/fuzz.go | 98 ++++++++++++++++++++---------------- src/internal/fuzz/mem.go | 24 +++++---- src/internal/fuzz/mutator.go | 13 +++-- src/internal/fuzz/worker.go | 91 +++++++++++++++++++-------------- 4 files changed, 129 insertions(+), 97 deletions(-) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 930683000f..88bfc5dddc 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -35,7 +35,7 @@ import ( // // If a crash occurs, the function will return an error containing information // about the crash, which can be reported to the user. -func CoordinateFuzzing(parallel int, seed [][]byte, crashDir string) error { +func CoordinateFuzzing(parallel int, seed [][]byte, crashDir string) (err error) { if parallel == 0 { parallel = runtime.GOMAXPROCS(0) } @@ -69,7 +69,9 @@ func CoordinateFuzzing(parallel int, seed [][]byte, crashDir string) error { c := &coordinator{ doneC: make(chan struct{}), inputC: make(chan corpusEntry), - interestingC: make(chan fuzzResponse), + interestingC: make(chan corpusEntry), + crasherC: make(chan crasherEntry), + errC: make(chan error), } newWorker := func() (*worker, error) { @@ -110,58 +112,56 @@ func CoordinateFuzzing(parallel int, seed [][]byte, crashDir string) error { }(i) } + // Before returning, signal workers to stop, wait for them to actually stop, + // and gather any errors they encountered. + defer func() { + close(c.doneC) + wg.Wait() + if err == nil { + for _, err = range workerErrs { + if err != nil { + // Return the first error found. + return + } + } + } + }() + // Main event loop. stopC := time.After(duration) i := 0 for { select { // TODO(jayconrod): handle interruptions like SIGINT. - // TODO(jayconrod,katiehockman): receive crashers and new corpus values - // from workers. case <-stopC: // Time's up. - close(c.doneC) + return nil - case <-c.doneC: - // Wait for workers to stop and return. - wg.Wait() - for _, err := range workerErrs { - if err != nil { - return err - } + case crasher := <-c.crasherC: + // A worker found a crasher. Write it to testdata and return it. + fileName, err := writeToCorpus(crasher.b, crashDir) + if err == nil { + err = fmt.Errorf(" Crash written to %s\n%s", fileName, crasher.errMsg) } - return nil + // TODO(jayconrod,katiehockman): if -keepfuzzing, report the error to + // the user and restart the crashed worker. + return err - case resp := <-c.interestingC: + case entry := <-c.interestingC: // Some interesting input arrived from a worker. - if resp.Err != "" { - // This is a crasher, which should be written to testdata and - // reported to the user. - fileName, err := writeToCorpus(resp.Value, crashDir) - if err == nil { - err = fmt.Errorf(" Crash written to: %s\n%s", fileName, resp.Err) - } - // TODO(jayconrod,katiehockman): if -keepfuzzing, don't stop all - // of the workers, but still report to the user. - - // Stop the rest of the workers and wait until they have - // stopped before returning this error. - close(c.doneC) - wg.Wait() - return err - } else if len(resp.Value) > 0 { - // This is not a crasher, but something interesting that should - // be added to the on disk corpus and prioritized for future - // workers to fuzz. - - corpus.entries = append(corpus.entries, corpusEntry{b: resp.Value}) - // TODO(jayconrod, katiehockman): Add this to the on disk corpus - // TODO(jayconrod, katiehockman): Prioritize fuzzing these values which expanded coverage - } + // This is not a crasher, but something interesting that should + // be added to the on disk corpus and prioritized for future + // workers to fuzz. + // TODO(jayconrod, katiehockman): Prioritize fuzzing these values which expanded coverage + corpus.entries = append(corpus.entries, entry) + + case err := <-c.errC: + // A worker encountered a fatal error. + return err case c.inputC <- corpus.entries[i]: - // Sent the next input to any worker. + // Send the next input to any worker. // TODO(jayconrod,katiehockman): need a scheduling algorithm that chooses // which corpus value to send next (or generates something new). i = (i + 1) % len(corpus.entries) @@ -183,6 +183,11 @@ type corpusEntry struct { b []byte } +type crasherEntry struct { + corpusEntry + errMsg string +} + // coordinator holds channels that workers can use to communicate with // the coordinator. type coordinator struct { @@ -196,9 +201,18 @@ type coordinator struct { inputC chan corpusEntry // interestingC is sent interesting values by the worker, which is received - // by the coordinator. The interesting value could be a crash or some - // value that increased coverage. - interestingC chan fuzzResponse + // by the coordinator. Values are usually interesting because they + // increase coverage. + interestingC chan corpusEntry + + // crasherC is sent values that crashed the code being fuzzed. These values + // should be saved in the corpus, and we may want to stop fuzzing after + // receiving one. + crasherC chan crasherEntry + + // errC is sent internal errors encountered by workers. When the coordinator + // receives an error, it closes doneC and returns. + errC chan error } // ReadCorpus reads the corpus from the testdata directory in this target's diff --git a/src/internal/fuzz/mem.go b/src/internal/fuzz/mem.go index 2bb5736cf5..54e3eb737c 100644 --- a/src/internal/fuzz/mem.go +++ b/src/internal/fuzz/mem.go @@ -17,11 +17,9 @@ import ( // // When fuzzing, the coordinator creates a sharedMem from a temporary file for // each worker. This buffer is used to pass values to fuzz between processes. -// -// Care must be taken to synchronize access to shared memory across processes. -// For example, workerClient and workerServer use an RPC protocol over pipes: -// workerServer may access shared memory when handling an RPC; workerClient may -// access shared memory at other times. +// Care must be taken to manage access to shared memory across processes; +// sharedMem provides no synchronization on its own. See workerComm for an +// explanation. type sharedMem struct { // f is the file mapped into memory. f *os.File @@ -81,19 +79,27 @@ func (m *sharedMem) header() *sharedMemHeader { return (*sharedMemHeader)(unsafe.Pointer(&m.region[0])) } -// value returns the value currently stored in shared memory. The returned slice -// points to shared memory; it is not a copy. -func (m *sharedMem) value() []byte { +// valueRef returns the value currently stored in shared memory. The returned +// slice points to shared memory; it is not a copy. +func (m *sharedMem) valueRef() []byte { length := m.header().length valueOffset := int(unsafe.Sizeof(sharedMemHeader{})) return m.region[valueOffset : valueOffset+length] } +// valueCopy returns a copy of the value stored in shared memory. +func (m *sharedMem) valueCopy() []byte { + ref := m.valueRef() + b := make([]byte, len(ref)) + copy(b, ref) + return b +} + // setValue copies the data in b into the shared memory buffer and sets // the length. len(b) must be less than or equal to the capacity of the buffer // (as returned by cap(m.value())). func (m *sharedMem) setValue(b []byte) { - v := m.value() + v := m.valueRef() if len(b) > cap(v) { panic(fmt.Sprintf("value length %d larger than shared memory capacity %d", len(b), cap(v))) } diff --git a/src/internal/fuzz/mutator.go b/src/internal/fuzz/mutator.go index 229bb31a11..6a52e46f6f 100644 --- a/src/internal/fuzz/mutator.go +++ b/src/internal/fuzz/mutator.go @@ -6,13 +6,12 @@ package fuzz import "math/rand" -func mutate(b []byte) []byte { - mutated := make([]byte, len(b)) - copy(mutated, b) +func mutate(b []byte) { + if len(b) == 0 { + return + } // Mutate a byte in a random position. - pos := rand.Intn(len(mutated)) - mutated[pos] = byte(rand.Intn(256)) - - return mutated + pos := rand.Intn(len(b)) + b[pos] = byte(rand.Intn(256)) } diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 47d3009525..4658687106 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -67,7 +67,7 @@ func (w *worker) runFuzzing() error { if err := w.start(); err != nil { // We couldn't start the worker process. We can't do anything, and it's // likely that other workers can't either, so give up. - close(w.coordinator.doneC) + w.coordinator.errC <- err return err } @@ -84,11 +84,12 @@ func (w *worker) runFuzzing() error { case <-w.termC: // Worker process terminated unexpectedly, so inform the coordinator // that a crash occurred. - b := w.mem.value() // These are the bytes that caused the crash. - resB := make([]byte, len(b)) - copy(resB, b) - resp := fuzzResponse{Value: resB, Err: "fuzzing process crashed unexpectedly"} - w.coordinator.interestingC <- resp + value := w.mem.valueCopy() + crasher := crasherEntry{ + corpusEntry: corpusEntry{b: value}, + errMsg: "fuzzing process crashed unexpectedly", + } + w.coordinator.crasherC <- crasher // TODO(jayconrod,katiehockman): if -keepfuzzing, restart worker. err := w.stop() @@ -102,7 +103,7 @@ func (w *worker) runFuzzing() error { inputC = nil // block new inputs until we finish with this one. go func() { args := fuzzArgs{Duration: workerFuzzDuration} - resp, err := w.client.fuzz(input.b, args) + value, resp, err := w.client.fuzz(input.b, args) if err != nil { // TODO(jayconrod): if we get an error here, something failed between // main and the call to testing.F.Fuzz. The error here won't @@ -113,22 +114,22 @@ func (w *worker) runFuzzing() error { // TODO(jayconrod): what happens if testing.F.Fuzz is never called? // TODO(jayconrod): time out if the test process hangs. fmt.Fprintf(os.Stderr, "communicating with worker: %v\n", err) + } else if resp.Err != "" { + // The worker found a crasher. Inform the coordinator. + crasher := crasherEntry{ + corpusEntry: corpusEntry{b: value}, + errMsg: resp.Err, + } + w.coordinator.crasherC <- crasher } else { - // TODO(jayconrod, katiehockman): Right now, this will just - // send an empty fuzzResponse{} if nothing interesting came - // up. Probably want to only pass to interestingC if fuzzing - // found something interesting. - // Inform the coordinator that fuzzing found something // interesting (ie. a crash or new coverage). - w.coordinator.interestingC <- resp - - if resp.Err == "" { - // Only unblock to allow more fuzzing to occur if - // everything was successful with the last fuzzing - // attempt. - fuzzC <- struct{}{} + if resp.Interesting { + w.coordinator.interestingC <- corpusEntry{b: value} } + + // Continue fuzzing. + fuzzC <- struct{}{} } // TODO(jayconrod,katiehockman): gather statistics. }() @@ -316,17 +317,31 @@ type call struct { Fuzz *fuzzArgs } +// fuzzArgs contains arguments to workerServer.fuzz. The value to fuzz is +// passed in shared memory. type fuzzArgs struct { Duration time.Duration } +// fuzzResponse contains results from workerServer.fuzz. type fuzzResponse struct { - Value []byte // The bytes that yielded the response. - Err string // The error if the bytes resulted in a crash, nil otherwise. + // Interesting indicates the value in shared memory may be interesting to + // the coordinator (for example, because it expanded coverage). + Interesting bool + + // Err is set if the value in shared memory caused a crash. + Err string } // workerComm holds pipes and shared memory used for communication // between the coordinator process (client) and a worker process (server). +// These values are unique to each worker; they are shared only with the +// coordinator, not with other workers. +// +// Access to shared memory is synchronized implicitly over the RPC protocol +// implemented in workerServer and workerClient. During a call, the client +// (worker) has exclusive access to shared memory; at other times, the server +// (coordinator) has exclusive access. type workerComm struct { fuzzIn, fuzzOut *os.File mem *sharedMem @@ -369,8 +384,7 @@ func (ws *workerServer) serve() error { var resp interface{} switch { case c.Fuzz != nil: - value := ws.mem.value() - resp = ws.fuzz(value, *c.Fuzz) + resp = ws.fuzz(*c.Fuzz) default: return errors.New("no arguments provided for any call") } @@ -384,20 +398,21 @@ func (ws *workerServer) serve() error { // fuzz runs the test function on random variations of a given input value for // a given amount of time. fuzz returns early if it finds an input that crashes // the fuzz function or an input that expands coverage. -func (ws *workerServer) fuzz(value []byte, args fuzzArgs) fuzzResponse { +func (ws *workerServer) fuzz(args fuzzArgs) fuzzResponse { t := time.NewTimer(args.Duration) for { select { case <-t.C: - return fuzzResponse{} + // TODO(jayconrod,katiehockman): this value is not interesting. Use a + // real heuristic once we have one. + return fuzzResponse{Interesting: true} default: - b := mutate(value) - ws.mem.setValue(b) // Write the value to memory so it can be recovered it if the process dies - if err := ws.fuzzFn(b); err != nil { - return fuzzResponse{Value: b, Err: err.Error()} + mutate(ws.mem.valueRef()) + if err := ws.fuzzFn(ws.mem.valueRef()); err != nil { + return fuzzResponse{Err: err.Error()} } - // TODO(jayconrod,katiehockman): return early if coverage is expanded - // by returning a fuzzResponse with the Value set but a nil Err. + // TODO(jayconrod,katiehockman): return early if we find an + // interesting value. } } } @@ -445,18 +460,16 @@ func (wc *workerClient) Close() error { } // fuzz tells the worker to call the fuzz method. See workerServer.fuzz. -func (wc *workerClient) fuzz(value []byte, args fuzzArgs) (fuzzResponse, error) { +func (wc *workerClient) fuzz(valueIn []byte, args fuzzArgs) (valueOut []byte, resp fuzzResponse, err error) { wc.mu.Lock() defer wc.mu.Unlock() - wc.mem.setValue(value) + wc.mem.setValue(valueIn) c := call{Fuzz: &args} if err := wc.enc.Encode(c); err != nil { - return fuzzResponse{}, err - } - var resp fuzzResponse - if err := wc.dec.Decode(&resp); err != nil { - return fuzzResponse{}, err + return nil, fuzzResponse{}, err } - return resp, nil + err = wc.dec.Decode(&resp) + valueOut = wc.mem.valueCopy() + return valueOut, resp, err } -- GitLab From 0e21d5be3790a55484f1dfcad6d8b1d2f253600e Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Fri, 4 Dec 2020 18:27:09 -0500 Subject: [PATCH 0020/2500] [dev.fuzz] internal/fuzz: read and write interesting values in fuzz cache 'go test -fuzz' may now read and write interesting fuzzing values to directories in $GOCACHE/fuzz. Files in this directory are named $pkg/$test/$hash where $pkg is the package path containing the fuzz target, $test is the target name, and $hash is the SHA-256 sum of the data in the file. Note that different versions of the same package or packages with the same path from different modules may share the same directory. Although files are written into a subdirectory of GOCACHE, they are not removed automatically, nor are they removed by 'go clean -cache'. Instead, they may be removed with 'go clean -fuzzcache'. We chose to nest the fuzzing directory inside GOCACHE to avoid introducing a new environment variable, since there's no real need for users to specify a separate directory. Change-Id: I2032cf8e6c92f715cf36a9fc6a550acf666d2382 Reviewed-on: https://go-review.googlesource.com/c/go/+/275534 Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman Trust: Katie Hockman Trust: Jay Conrod --- src/cmd/go/alldocs.go | 2 + src/cmd/go/internal/cache/cache.go | 10 ++ src/cmd/go/internal/clean/clean.go | 16 +++ src/cmd/go/internal/test/flagdefs_test.go | 2 +- src/cmd/go/internal/test/test.go | 7 +- src/cmd/go/internal/test/testflag.go | 2 +- .../go/testdata/script/test_fuzz_cache.txt | 62 ++++++++++ src/internal/fuzz/fuzz.go | 108 ++++++++++++------ src/testing/fuzz.go | 8 +- src/testing/internal/testdeps/deps.go | 4 +- src/testing/testing.go | 30 +++-- 11 files changed, 194 insertions(+), 57 deletions(-) create mode 100644 src/cmd/go/testdata/script/test_fuzz_cache.txt diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index c4913ce695..da5909a04b 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -279,6 +279,8 @@ // download cache, including unpacked source code of versioned // dependencies. // +// The -fuzzcache flag causes clean to remove values used for fuzz testing. +// // For more about build flags, see 'go help build'. // // For more about specifying packages, see 'go help packages'. diff --git a/src/cmd/go/internal/cache/cache.go b/src/cmd/go/internal/cache/cache.go index 41f921641d..1a9762bdfb 100644 --- a/src/cmd/go/internal/cache/cache.go +++ b/src/cmd/go/internal/cache/cache.go @@ -522,3 +522,13 @@ func (c *Cache) copyFile(file io.ReadSeeker, out OutputID, size int64) error { return nil } + +// FuzzDir returns a subdirectory within the cache for storing fuzzing data. +// The subdirectory may not exist. +// +// This directory is managed by the internal/fuzz package. Files in this +// directory aren't removed by the 'go clean -cache' command or by Trim. +// They may be removed with 'go clean -fuzzcache'. +func (c *Cache) FuzzDir() string { + return filepath.Join(c.dir, "fuzz") +} diff --git a/src/cmd/go/internal/clean/clean.go b/src/cmd/go/internal/clean/clean.go index b1d40feb27..788c4b1977 100644 --- a/src/cmd/go/internal/clean/clean.go +++ b/src/cmd/go/internal/clean/clean.go @@ -75,6 +75,8 @@ The -modcache flag causes clean to remove the entire module download cache, including unpacked source code of versioned dependencies. +The -fuzzcache flag causes clean to remove values used for fuzz testing. + For more about build flags, see 'go help build'. For more about specifying packages, see 'go help packages'. @@ -85,6 +87,7 @@ var ( cleanI bool // clean -i flag cleanR bool // clean -r flag cleanCache bool // clean -cache flag + cleanFuzzcache bool // clean -fuzzcache flag cleanModcache bool // clean -modcache flag cleanTestcache bool // clean -testcache flag ) @@ -96,6 +99,7 @@ func init() { CmdClean.Flag.BoolVar(&cleanI, "i", false, "") CmdClean.Flag.BoolVar(&cleanR, "r", false, "") CmdClean.Flag.BoolVar(&cleanCache, "cache", false, "") + CmdClean.Flag.BoolVar(&cleanFuzzcache, "fuzzcache", false, "") CmdClean.Flag.BoolVar(&cleanModcache, "modcache", false, "") CmdClean.Flag.BoolVar(&cleanTestcache, "testcache", false, "") @@ -206,6 +210,18 @@ func runClean(ctx context.Context, cmd *base.Command, args []string) { } } } + + if cleanFuzzcache { + fuzzDir := cache.Default().FuzzDir() + if cfg.BuildN || cfg.BuildX { + b.Showcmd("", "rm -rf %s", fuzzDir) + } + if !cfg.BuildN { + if err := os.RemoveAll(fuzzDir); err != nil { + base.Errorf("go clean -fuzzcache: %v", err) + } + } + } } var cleaned = map[*load.Package]bool{} diff --git a/src/cmd/go/internal/test/flagdefs_test.go b/src/cmd/go/internal/test/flagdefs_test.go index 50711ecff9..f238fc7d33 100644 --- a/src/cmd/go/internal/test/flagdefs_test.go +++ b/src/cmd/go/internal/test/flagdefs_test.go @@ -17,7 +17,7 @@ func TestPassFlagToTestIncludesAllTestFlags(t *testing.T) { } name := strings.TrimPrefix(f.Name, "test.") switch name { - case "testlogfile", "paniconexit0", "fuzzworker": + case "testlogfile", "paniconexit0", "fuzzcachedir", "fuzzworker": // These are internal flags. default: if !passFlagToTest[name] { diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 41e58cb7fe..28e49e44b5 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -1169,7 +1169,12 @@ func (c *runCache) builderRunTest(b *work.Builder, ctx context.Context, a *work. testlogArg = []string{"-test.testlogfile=" + a.Objdir + "testlog.txt"} } panicArg := "-test.paniconexit0" - args := str.StringList(execCmd, a.Deps[0].BuiltTarget(), testlogArg, panicArg, testArgs) + fuzzArg := []string{} + if testFuzz != "" { + fuzzCacheDir := filepath.Join(cache.Default().FuzzDir(), a.Package.ImportPath) + fuzzArg = []string{"-test.fuzzcachedir=" + fuzzCacheDir} + } + args := str.StringList(execCmd, a.Deps[0].BuiltTarget(), testlogArg, panicArg, fuzzArg, testArgs) if testCoverProfile != "" { // Write coverage to temporary profile, for merging later. diff --git a/src/cmd/go/internal/test/testflag.go b/src/cmd/go/internal/test/testflag.go index bba7ede2b2..cb25dc014a 100644 --- a/src/cmd/go/internal/test/testflag.go +++ b/src/cmd/go/internal/test/testflag.go @@ -56,7 +56,7 @@ func init() { cf.String("cpu", "", "") cf.StringVar(&testCPUProfile, "cpuprofile", "", "") cf.Bool("failfast", false, "") - cf.String("fuzz", "", "") + cf.StringVar(&testFuzz, "fuzz", "", "") cf.StringVar(&testList, "list", "", "") cf.StringVar(&testMemProfile, "memprofile", "", "") cf.String("memprofilerate", "", "") diff --git a/src/cmd/go/testdata/script/test_fuzz_cache.txt b/src/cmd/go/testdata/script/test_fuzz_cache.txt new file mode 100644 index 0000000000..6fb443e1fd --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_cache.txt @@ -0,0 +1,62 @@ +[short] skip +env GOCACHE=$WORK/cache + +# Fuzz cache should not exist after a regular test run. +go test . +exists $GOCACHE +! exists $GOCACHE/fuzz + +# Fuzzing should write interesting values to the cache. +go test -fuzz=FuzzY -parallel=1 . +go run ./contains_files $GOCACHE/fuzz/example.com/y/FuzzY + +# 'go clean -cache' should not delete the fuzz cache. +go clean -cache +exists $GOCACHE/fuzz + +# 'go clean -fuzzcache' should delete the fuzz cache but not the build cache. +go list -f {{.Stale}} ./empty +stdout true +go install ./empty +go list -f {{.Stale}} ./empty +stdout false +go clean -fuzzcache +! exists $GOCACHE/fuzz +go list -f {{.Stale}} ./empty +stdout false + +-- go.mod -- +module example.com/y + +go 1.16 +-- y_test.go -- +package y + +import "testing" + +func FuzzY(f *testing.F) { + f.Add([]byte("y")) + f.Fuzz(func(t *testing.T, b []byte) {}) +} +-- empty/empty.go -- +package empty +-- contains_files/contains_files.go -- +package main + +import ( + "fmt" + "path/filepath" + "io/ioutil" + "os" +) + +func main() { + infos, err := ioutil.ReadDir(filepath.Clean(os.Args[1])) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + if len(infos) == 0 { + os.Exit(1) + } +} diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 88bfc5dddc..2ab16b1189 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -30,12 +30,16 @@ import ( // // seed is a list of seed values added by the fuzz target with testing.F.Add and // in testdata. -// Seed values from GOFUZZCACHE should not be included in this list; this -// function loads them separately. +// +// corpusDir is a directory where files containing values that crash the +// code being tested may be written. +// +// cacheDir is a directory containing additional "interesting" values. +// The fuzzer may derive new values from these, and may write new values here. // // If a crash occurs, the function will return an error containing information // about the crash, which can be reported to the user. -func CoordinateFuzzing(parallel int, seed [][]byte, crashDir string) (err error) { +func CoordinateFuzzing(parallel int, seed [][]byte, corpusDir, cacheDir string) (err error) { if parallel == 0 { parallel = runtime.GOMAXPROCS(0) } @@ -44,21 +48,21 @@ func CoordinateFuzzing(parallel int, seed [][]byte, crashDir string) (err error) // interrupts. duration := 5 * time.Second - var corpus corpus - var maxSeedLen int - if len(seed) == 0 { + corpus, err := readCorpusAndCache(seed, corpusDir, cacheDir) + if err != nil { + return err + } + var maxEntryLen int + if len(corpus.entries) == 0 { corpus.entries = []corpusEntry{{b: []byte{}}} - maxSeedLen = 0 + maxEntryLen = 0 } else { - corpus.entries = make([]corpusEntry, len(seed)) - for i, v := range seed { - corpus.entries[i].b = v - if len(v) > maxSeedLen { - maxSeedLen = len(v) + for _, e := range corpus.entries { + if len(e.b) > maxEntryLen { + maxEntryLen = len(e.b) } } } - // TODO(jayconrod,katiehockman): read corpus from GOFUZZCACHE. // TODO(jayconrod): do we want to support fuzzing different binaries? dir := "" // same as self @@ -75,7 +79,7 @@ func CoordinateFuzzing(parallel int, seed [][]byte, crashDir string) (err error) } newWorker := func() (*worker, error) { - mem, err := sharedMemTempFile(maxSeedLen) + mem, err := sharedMemTempFile(maxEntryLen) if err != nil { return nil, err } @@ -140,7 +144,7 @@ func CoordinateFuzzing(parallel int, seed [][]byte, crashDir string) (err error) case crasher := <-c.crasherC: // A worker found a crasher. Write it to testdata and return it. - fileName, err := writeToCorpus(crasher.b, crashDir) + fileName, err := writeToCorpus(crasher.b, corpusDir) if err == nil { err = fmt.Errorf(" Crash written to %s\n%s", fileName, crasher.errMsg) } @@ -153,8 +157,16 @@ func CoordinateFuzzing(parallel int, seed [][]byte, crashDir string) (err error) // This is not a crasher, but something interesting that should // be added to the on disk corpus and prioritized for future // workers to fuzz. - // TODO(jayconrod, katiehockman): Prioritize fuzzing these values which expanded coverage + // TODO(jayconrod, katiehockman): Prioritize fuzzing these values which + // expanded coverage. + // TODO(jayconrod, katiehockman): Don't write a value that's already + // in the corpus. corpus.entries = append(corpus.entries, entry) + if cacheDir != "" { + if _, err := writeToCorpus(entry.b, cacheDir); err != nil { + return err + } + } case err := <-c.errC: // A worker encountered a fatal error. @@ -168,9 +180,8 @@ func CoordinateFuzzing(parallel int, seed [][]byte, crashDir string) (err error) } } - // TODO(jayconrod,katiehockman): write crashers to testdata and other inputs - // to GOFUZZCACHE. If the testdata directory is outside the current module, - // always write to GOFUZZCACHE, since the testdata is likely read-only. + // TODO(jayconrod,katiehockman): if a crasher can't be written to corpusDir, + // write to cacheDir instead. } type corpus struct { @@ -215,6 +226,31 @@ type coordinator struct { errC chan error } +// readCorpusAndCache creates a combined corpus from seed values, values in the +// corpus directory (in testdata), and values in the cache (in GOCACHE/fuzz). +// +// TODO(jayconrod,katiehockman): if a value in the cache has the wrong type, +// ignore it instead of reporting an error. Cached values may be used for +// the same package at a different version or in a different module. +// TODO(jayconrod,katiehockman): need a mechanism that can remove values that +// aren't useful anymore, for example, because they have the wrong type. +func readCorpusAndCache(seed [][]byte, corpusDir, cacheDir string) (corpus, error) { + var c corpus + for _, b := range seed { + c.entries = append(c.entries, corpusEntry{b: b}) + } + for _, dir := range []string{corpusDir, cacheDir} { + bs, err := ReadCorpus(dir) + if err != nil { + return corpus{}, err + } + for _, b := range bs { + c.entries = append(c.entries, corpusEntry{b: b}) + } + } + return c, nil +} + // ReadCorpus reads the corpus from the testdata directory in this target's // package. func ReadCorpus(dir string) ([][]byte, error) { @@ -226,6 +262,11 @@ func ReadCorpus(dir string) ([][]byte, error) { } var corpus [][]byte for _, file := range files { + // TODO(jayconrod,katiehockman): determine when a file is a fuzzing input + // based on its name. We should only read files created by writeToCorpus. + // If we read ALL files, we won't be able to change the file format by + // changing the extension. We also won't be able to add files like + // README.txt explaining why the directory exists. if file.IsDir() { continue } @@ -238,27 +279,18 @@ func ReadCorpus(dir string) ([][]byte, error) { return corpus, nil } -// writeToCorpus writes the given bytes to a new file in testdata. If the -// directory does not exist, it will create one. It returns the filename that -// was written, or an error if it failed. -func writeToCorpus(b []byte, crashDir string) (string, error) { - // TODO: Consider not writing a new file if one with those contents already - // exists. Perhaps the filename can be compared to those that already exist - // if all of the filenames are normalized, or by checking the contents of - // all other files. - if _, err := ioutil.ReadDir(crashDir); os.IsNotExist(err) { - // Make the seed corpus directory since it doesn't exist. - err = os.MkdirAll(crashDir, 0777) - if err != nil { - return "", err - } - } else if err != nil { +// writeToCorpus atomically writes the given bytes to a new file in testdata. +// If the directory does not exist, it will create one. If the file already +// exists, writeToCorpus will not rewrite it. writeToCorpus returns the +// file's name, or an error if it failed. +func writeToCorpus(b []byte, dir string) (name string, err error) { + sum := fmt.Sprintf("%x", sha256.Sum256(b)) + name = filepath.Join(dir, sum) + if err := os.MkdirAll(dir, 0777); err != nil { return "", err } - sum := fmt.Sprintf("%x", sha256.Sum256(b)) - name := filepath.Join(crashDir, sum) - err := ioutil.WriteFile(name, b, 0666) - if err != nil { + if err := ioutil.WriteFile(name, b, 0666); err != nil { + os.Remove(name) // remove partially written file return "", err } return name, nil diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 97d64f99be..996e361300 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -16,11 +16,13 @@ import ( func initFuzzFlags() { matchFuzz = flag.String("test.fuzz", "", "run the fuzz target matching `regexp`") + fuzzCacheDir = flag.String("test.fuzzcachedir", "", "directory where interesting fuzzing inputs are stored") isFuzzWorker = flag.Bool("test.fuzzworker", false, "coordinate with the parent process to fuzz random values") } var ( matchFuzz *string + fuzzCacheDir *string isFuzzWorker *bool // corpusDir is the parent directory of the target's seed corpus within @@ -132,7 +134,9 @@ func (f *F) Fuzz(ff interface{}) { for i, e := range f.corpus { seed[i] = e.b } - err := f.context.coordinateFuzzing(*parallel, seed, filepath.Join(corpusDir, f.name)) + corpusTargetDir := filepath.Join(corpusDir, f.name) + cacheTargetDir := filepath.Join(*fuzzCacheDir, f.name) + err := f.context.coordinateFuzzing(*parallel, seed, corpusTargetDir, cacheTargetDir) if err != nil { f.Fail() f.result = FuzzResult{Error: err} @@ -275,7 +279,7 @@ func (r FuzzResult) String() string { type fuzzContext struct { runMatch *matcher fuzzMatch *matcher - coordinateFuzzing func(int, [][]byte, string) error + coordinateFuzzing func(int, [][]byte, string, string) error runFuzzWorker func(func([]byte) error) error readCorpus func(string) ([][]byte, error) } diff --git a/src/testing/internal/testdeps/deps.go b/src/testing/internal/testdeps/deps.go index 109d925016..dcca6032d0 100644 --- a/src/testing/internal/testdeps/deps.go +++ b/src/testing/internal/testdeps/deps.go @@ -128,8 +128,8 @@ func (TestDeps) SetPanicOnExit0(v bool) { testlog.SetPanicOnExit0(v) } -func (TestDeps) CoordinateFuzzing(parallel int, seed [][]byte, crashDir string) error { - return fuzz.CoordinateFuzzing(parallel, seed, crashDir) +func (TestDeps) CoordinateFuzzing(parallel int, seed [][]byte, corpusDir, cacheDir string) error { + return fuzz.CoordinateFuzzing(parallel, seed, corpusDir, cacheDir) } func (TestDeps) RunFuzzWorker(fn func([]byte) error) error { diff --git a/src/testing/testing.go b/src/testing/testing.go index c87e0a5b9a..e3e35fa13a 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1353,17 +1353,17 @@ var errMain = errors.New("testing: unexpected use of func Main") type matchStringOnly func(pat, str string) (bool, error) -func (f matchStringOnly) MatchString(pat, str string) (bool, error) { return f(pat, str) } -func (f matchStringOnly) StartCPUProfile(w io.Writer) error { return errMain } -func (f matchStringOnly) StopCPUProfile() {} -func (f matchStringOnly) WriteProfileTo(string, io.Writer, int) error { return errMain } -func (f matchStringOnly) ImportPath() string { return "" } -func (f matchStringOnly) StartTestLog(io.Writer) {} -func (f matchStringOnly) StopTestLog() error { return errMain } -func (f matchStringOnly) SetPanicOnExit0(bool) {} -func (f matchStringOnly) CoordinateFuzzing(int, [][]byte, string) error { return errMain } -func (f matchStringOnly) RunFuzzWorker(func([]byte) error) error { return errMain } -func (f matchStringOnly) ReadCorpus(string) ([][]byte, error) { return nil, errMain } +func (f matchStringOnly) MatchString(pat, str string) (bool, error) { return f(pat, str) } +func (f matchStringOnly) StartCPUProfile(w io.Writer) error { return errMain } +func (f matchStringOnly) StopCPUProfile() {} +func (f matchStringOnly) WriteProfileTo(string, io.Writer, int) error { return errMain } +func (f matchStringOnly) ImportPath() string { return "" } +func (f matchStringOnly) StartTestLog(io.Writer) {} +func (f matchStringOnly) StopTestLog() error { return errMain } +func (f matchStringOnly) SetPanicOnExit0(bool) {} +func (f matchStringOnly) CoordinateFuzzing(int, [][]byte, string, string) error { return errMain } +func (f matchStringOnly) RunFuzzWorker(func([]byte) error) error { return errMain } +func (f matchStringOnly) ReadCorpus(string) ([][]byte, error) { return nil, errMain } // Main is an internal function, part of the implementation of the "go test" command. // It was exported because it is cross-package and predates "internal" packages. @@ -1406,7 +1406,7 @@ type testDeps interface { StartTestLog(io.Writer) StopTestLog() error WriteProfileTo(string, io.Writer, int) error - CoordinateFuzzing(int, [][]byte, string) error + CoordinateFuzzing(int, [][]byte, string, string) error RunFuzzWorker(func([]byte) error) error ReadCorpus(string) ([][]byte, error) } @@ -1448,6 +1448,12 @@ func (m *M) Run() (code int) { m.exitCode = 2 return } + if *matchFuzz != "" && *fuzzCacheDir == "" { + fmt.Fprintln(os.Stderr, "testing: internal error: -test.fuzzcachedir must be set if -test.fuzz is set") + flag.Usage() + m.exitCode = 2 + return + } if len(*matchList) != 0 { listTests(m.deps.MatchString, m.tests, m.benchmarks, m.fuzzTargets, m.examples) -- GitLab From 6dc2c16f95c7b9a7f33964d2946ba2f8a6e7de9b Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Tue, 22 Dec 2020 16:31:56 -0500 Subject: [PATCH 0021/2500] [dev.cmdgo] codereview.cfg: add config for dev.cmdgo Change-Id: I6a711402b06a75c5cba43a72950617fea27bd50b Reviewed-on: https://go-review.googlesource.com/c/go/+/279526 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Russ Cox --- codereview.cfg | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 codereview.cfg diff --git a/codereview.cfg b/codereview.cfg new file mode 100644 index 0000000000..c5bef5e62d --- /dev/null +++ b/codereview.cfg @@ -0,0 +1,2 @@ +branch: dev.cmdgo +parent-branch: master -- GitLab From 3ea342eb2e2f65a02bc84e206a4e7615747df49a Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Wed, 23 Dec 2020 09:52:30 -0500 Subject: [PATCH 0022/2500] [dev.fuzz] cmd/go: fix test_fuzz_mutate_crash test on windows Change-Id: I1efde6dd82bb22f8bba63fe837c0f6ad4b3f03bd Reviewed-on: https://go-review.googlesource.com/c/go/+/279992 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt index 2effd44bf8..3647bf1dbd 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt @@ -13,7 +13,7 @@ go test -parallel=1 # Running the fuzzer should find a crashing input quickly. ! go test -fuzz=FuzzWithBug -parallel=1 -stdout 'testdata/corpus/FuzzWithBug/fb8e20fc2e4c3f248c60c39bd652f3c1347298bb977b8b4d5903b85055620603' +stdout 'testdata[/\\]corpus[/\\]FuzzWithBug[/\\]fb8e20fc2e4c3f248c60c39bd652f3c1347298bb977b8b4d5903b85055620603' stdout 'this input caused a crash!' grep '\Aab\z' testdata/corpus/FuzzWithBug/fb8e20fc2e4c3f248c60c39bd652f3c1347298bb977b8b4d5903b85055620603 @@ -22,12 +22,12 @@ grep '\Aab\z' testdata/corpus/FuzzWithBug/fb8e20fc2e4c3f248c60c39bd652f3c1347298 ! go test -parallel=1 ! go test -run=FuzzWithNilPanic -fuzz=FuzzWithNilPanic -parallel=1 -stdout 'testdata/corpus/FuzzWithNilPanic/f45de51cdef30991551e41e882dd7b5404799648a0a00753f44fc966e6153fc1' +stdout 'testdata[/\\]corpus[/\\]FuzzWithNilPanic[/\\]f45de51cdef30991551e41e882dd7b5404799648a0a00753f44fc966e6153fc1' stdout 'runtime.Goexit' grep '\Aac\z' testdata/corpus/FuzzWithNilPanic/f45de51cdef30991551e41e882dd7b5404799648a0a00753f44fc966e6153fc1 ! go test -run=FuzzWithBadExit -fuzz=FuzzWithBadExit -parallel=1 -stdout 'testdata/corpus/FuzzWithBadExit/70ba33708cbfb103f1a8e34afef333ba7dc021022b2d9aaa583aabb8058d8d67' +stdout 'testdata[/\\]corpus[/\\]FuzzWithBadExit[/\\]70ba33708cbfb103f1a8e34afef333ba7dc021022b2d9aaa583aabb8058d8d67' stdout 'unexpectedly' grep '\Aad\z' testdata/corpus/FuzzWithBadExit/70ba33708cbfb103f1a8e34afef333ba7dc021022b2d9aaa583aabb8058d8d67 -- GitLab From a1646595e63cc0bf7f566bb9b657f826cbda22a1 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Thu, 17 Dec 2020 17:25:42 -0500 Subject: [PATCH 0023/2500] [dev.fuzz] cmd/go: implement -fuzztime flag and support cancellation fuzz.CoordinateFuzzing and RunFuzzWorker now accept a context.Context parameter. They should terminate gracefully when the context is cancelled. The worker should exit quickly without processing more inputs. The coordinator should save interesting inputs to the cache. The testing package can't import context directly, so it provides a timeout argument to testdeps.CoordinateFuzzing instead. The testdeps wrapper sets the timeout and installs an interrupt handler (for SIGINT on POSIX and the equivalent on Windows) that cancels the context when ^C is pressed. Note that on POSIX platforms, pressing ^C causes the shell to deliver SIGINT to all processes in the active group: so 'go test', the coordinator, and the workers should all react to that. On Windows, pressing ^C only interrupts 'go test'. We may want to look at that separately. Change-Id: I924d3be2905f9685dae82ff3c047ca3d6b5e2357 Reviewed-on: https://go-review.googlesource.com/c/go/+/279487 Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman Trust: Katie Hockman Trust: Jay Conrod --- src/cmd/go/internal/test/flagdefs.go | 1 + src/cmd/go/internal/test/genflags.go | 2 +- src/cmd/go/internal/test/testflag.go | 1 + src/cmd/go/testdata/script/test_fuzz.txt | 6 +- .../go/testdata/script/test_fuzz_cache.txt | 2 +- .../go/testdata/script/test_fuzz_fuzztime.txt | 27 +++++++ .../go/testdata/script/test_fuzz_match.txt | 6 +- .../go/testdata/script/test_fuzz_mutate.txt | 2 +- .../script/test_fuzz_mutate_crash.txt | 6 +- src/internal/fuzz/fuzz.go | 35 +++++----- src/internal/fuzz/worker.go | 70 ++++++++++++++----- src/testing/fuzz.go | 6 +- src/testing/internal/testdeps/deps.go | 49 ++++++++++++- src/testing/testing.go | 32 +++++---- 14 files changed, 181 insertions(+), 64 deletions(-) create mode 100644 src/cmd/go/testdata/script/test_fuzz_fuzztime.txt diff --git a/src/cmd/go/internal/test/flagdefs.go b/src/cmd/go/internal/test/flagdefs.go index 57e60e2c0c..c32b89430b 100644 --- a/src/cmd/go/internal/test/flagdefs.go +++ b/src/cmd/go/internal/test/flagdefs.go @@ -20,6 +20,7 @@ var passFlagToTest = map[string]bool{ "cpuprofile": true, "failfast": true, "fuzz": true, + "fuzztime": true, "list": true, "memprofile": true, "memprofilerate": true, diff --git a/src/cmd/go/internal/test/genflags.go b/src/cmd/go/internal/test/genflags.go index 5e83d53980..ca16113bb8 100644 --- a/src/cmd/go/internal/test/genflags.go +++ b/src/cmd/go/internal/test/genflags.go @@ -63,7 +63,7 @@ func testFlags() []string { name := strings.TrimPrefix(f.Name, "test.") switch name { - case "testlogfile", "paniconexit0": + case "testlogfile", "paniconexit0", "fuzzcachedir", "fuzzworker": // These flags are only for use by cmd/go. default: names = append(names, name) diff --git a/src/cmd/go/internal/test/testflag.go b/src/cmd/go/internal/test/testflag.go index cb25dc014a..2669aac831 100644 --- a/src/cmd/go/internal/test/testflag.go +++ b/src/cmd/go/internal/test/testflag.go @@ -67,6 +67,7 @@ func init() { cf.String("run", "", "") cf.Bool("short", false, "") cf.DurationVar(&testTimeout, "timeout", 10*time.Minute, "") + cf.Duration("fuzztime", 0, "") cf.StringVar(&testTrace, "trace", "", "") cf.BoolVar(&testV, "v", false, "") diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt index 5ab1c320d7..4a761d1fd9 100644 --- a/src/cmd/go/testdata/script/test_fuzz.txt +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -1,5 +1,5 @@ # Test that calling f.Error in a fuzz target causes a non-zero exit status. -! go test -fuzz Fuzz error_fuzz_test.go +! go test -fuzz=Fuzz -fuzztime=5s -parallel=1 error_fuzz_test.go ! stdout ^ok stdout FAIL @@ -14,12 +14,12 @@ stdout ok ! stdout FAIL # Test that calling f.Fatal while fuzzing causes a non-zero exit status. -! go test -fuzz Fuzz fatal_fuzz_test.go +! go test -fuzz=Fuzz -fuzztime=5s -parallel=1 fatal_fuzz_test.go ! stdout ^ok stdout FAIL # Test that successful fuzzing exits cleanly. -go test -fuzz Fuzz success_fuzz_test.go +go test -fuzz=Fuzz -fuzztime=5s -parallel=1 success_fuzz_test.go stdout ok ! stdout FAIL diff --git a/src/cmd/go/testdata/script/test_fuzz_cache.txt b/src/cmd/go/testdata/script/test_fuzz_cache.txt index 6fb443e1fd..ad8334ae7d 100644 --- a/src/cmd/go/testdata/script/test_fuzz_cache.txt +++ b/src/cmd/go/testdata/script/test_fuzz_cache.txt @@ -7,7 +7,7 @@ exists $GOCACHE ! exists $GOCACHE/fuzz # Fuzzing should write interesting values to the cache. -go test -fuzz=FuzzY -parallel=1 . +go test -fuzz=FuzzY -fuzztime=5s -parallel=1 . go run ./contains_files $GOCACHE/fuzz/example.com/y/FuzzY # 'go clean -cache' should not delete the fuzz cache. diff --git a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt new file mode 100644 index 0000000000..0fc2f74e31 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt @@ -0,0 +1,27 @@ +[short] skip + +# There are no seed values, so 'go test' should finish quickly. +go test + +# Fuzzing should exit 0 when after fuzztime, even if timeout is short. +go test -timeout=10ms -fuzz=FuzzFast -fuzztime=5s -parallel=1 + +# We should see the same behavior when invoking the test binary directly. +go test -c +exec ./fuzz.test$GOEXE -test.timeout=10ms -test.fuzz=FuzzFast -test.fuzztime=5s -test.parallel=1 -test.fuzzcachedir=$WORK/cache + +# Timeout should not cause inputs to be written as crashers. +! exists testdata/corpus + +-- go.mod -- +module fuzz + +go 1.16 +-- fuzz_test.go -- +package fuzz_test + +import "testing" + +func FuzzFast(f *testing.F) { + f.Fuzz(func (*testing.T, []byte) {}) +} diff --git a/src/cmd/go/testdata/script/test_fuzz_match.txt b/src/cmd/go/testdata/script/test_fuzz_match.txt index da7e7f13ab..6161438c2a 100644 --- a/src/cmd/go/testdata/script/test_fuzz_match.txt +++ b/src/cmd/go/testdata/script/test_fuzz_match.txt @@ -4,12 +4,12 @@ go test standalone_fuzz_test.go stdout '^ok' # Matches only for fuzzing. -go test -fuzz Fuzz standalone_fuzz_test.go +go test -fuzz Fuzz -fuzztime 5s -parallel 1 standalone_fuzz_test.go ! stdout '^ok.*\[no tests to run\]' stdout '^ok' # Matches none for fuzzing but will run the fuzz target as a test. -go test -fuzz ThisWillNotMatch standalone_fuzz_test.go +go test -fuzz ThisWillNotMatch -fuzztime 5s -parallel 1 standalone_fuzz_test.go ! stdout '^ok.*\[no tests to run\]' stdout ok stdout '\[no targets to fuzz\]' @@ -27,7 +27,7 @@ stdout '^ok.*\[no tests to run\]' ! stdout '\[no targets to fuzz\]' # Matches more than one fuzz target for fuzzing. -go test -fuzz Fuzz multiple_fuzz_test.go +go test -fuzz Fuzz -fuzztime 5s -parallel 1 multiple_fuzz_test.go # The tests should run, but not be fuzzed ! stdout '\[no tests to run\]' ! stdout '\[no targets to fuzz\]' diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate.txt b/src/cmd/go/testdata/script/test_fuzz_mutate.txt index b881292dc8..cbd0838e73 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutate.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutate.txt @@ -7,7 +7,7 @@ [short] skip -go test -fuzz=FuzzA -parallel=1 -log=fuzz +go test -fuzz=FuzzA -fuzztime=5s -parallel=1 -log=fuzz go run check_logs.go fuzz fuzz.worker -- go.mod -- diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt index 3647bf1dbd..6816950265 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt @@ -12,7 +12,7 @@ go test -parallel=1 # Running the fuzzer should find a crashing input quickly. -! go test -fuzz=FuzzWithBug -parallel=1 +! go test -fuzz=FuzzWithBug -fuzztime=5s -parallel=1 stdout 'testdata[/\\]corpus[/\\]FuzzWithBug[/\\]fb8e20fc2e4c3f248c60c39bd652f3c1347298bb977b8b4d5903b85055620603' stdout 'this input caused a crash!' grep '\Aab\z' testdata/corpus/FuzzWithBug/fb8e20fc2e4c3f248c60c39bd652f3c1347298bb977b8b4d5903b85055620603 @@ -21,12 +21,12 @@ grep '\Aab\z' testdata/corpus/FuzzWithBug/fb8e20fc2e4c3f248c60c39bd652f3c1347298 # the target, and should fail when run without fuzzing. ! go test -parallel=1 -! go test -run=FuzzWithNilPanic -fuzz=FuzzWithNilPanic -parallel=1 +! go test -run=FuzzWithNilPanic -fuzz=FuzzWithNilPanic -fuzztime=5s -parallel=1 stdout 'testdata[/\\]corpus[/\\]FuzzWithNilPanic[/\\]f45de51cdef30991551e41e882dd7b5404799648a0a00753f44fc966e6153fc1' stdout 'runtime.Goexit' grep '\Aac\z' testdata/corpus/FuzzWithNilPanic/f45de51cdef30991551e41e882dd7b5404799648a0a00753f44fc966e6153fc1 -! go test -run=FuzzWithBadExit -fuzz=FuzzWithBadExit -parallel=1 +! go test -run=FuzzWithBadExit -fuzz=FuzzWithBadExit -fuzztime=5s -parallel=1 stdout 'testdata[/\\]corpus[/\\]FuzzWithBadExit[/\\]70ba33708cbfb103f1a8e34afef333ba7dc021022b2d9aaa583aabb8058d8d67' stdout 'unexpectedly' grep '\Aad\z' testdata/corpus/FuzzWithBadExit/70ba33708cbfb103f1a8e34afef333ba7dc021022b2d9aaa583aabb8058d8d67 diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 2ab16b1189..aacc053682 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -8,6 +8,7 @@ package fuzz import ( + "context" "crypto/sha256" "fmt" "io/ioutil" @@ -15,7 +16,6 @@ import ( "path/filepath" "runtime" "sync" - "time" ) // CoordinateFuzzing creates several worker processes and communicates with @@ -39,14 +39,13 @@ import ( // // If a crash occurs, the function will return an error containing information // about the crash, which can be reported to the user. -func CoordinateFuzzing(parallel int, seed [][]byte, corpusDir, cacheDir string) (err error) { +func CoordinateFuzzing(ctx context.Context, parallel int, seed [][]byte, corpusDir, cacheDir string) (err error) { + if err := ctx.Err(); err != nil { + return err + } if parallel == 0 { parallel = runtime.GOMAXPROCS(0) } - // TODO(jayconrod): support fuzzing indefinitely or with a given duration. - // The value below is just a placeholder until we figure out how to handle - // interrupts. - duration := 5 * time.Second corpus, err := readCorpusAndCache(seed, corpusDir, cacheDir) if err != nil { @@ -121,26 +120,28 @@ func CoordinateFuzzing(parallel int, seed [][]byte, corpusDir, cacheDir string) defer func() { close(c.doneC) wg.Wait() - if err == nil { - for _, err = range workerErrs { - if err != nil { - // Return the first error found. - return + if err == nil || err == ctx.Err() { + for _, werr := range workerErrs { + if werr != nil { + // Return the first error found, replacing ctx.Err() if a more + // interesting error is found. + err = werr } } } }() // Main event loop. - stopC := time.After(duration) i := 0 for { select { - // TODO(jayconrod): handle interruptions like SIGINT. - - case <-stopC: - // Time's up. - return nil + case <-ctx.Done(): + // Interrupted, cancelled, or timed out. + // TODO(jayconrod,katiehockman): On Windows, ^C only interrupts 'go test', + // not the coordinator or worker processes. 'go test' will stop running + // actions, but it won't interrupt its child processes. This makes it + // difficult to stop fuzzing on Windows without a timeout. + return ctx.Err() case crasher := <-c.crasherC: // A worker found a crasher. Write it to testdata and return it. diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 4658687106..ef2a9303ef 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -5,6 +5,7 @@ package fuzz import ( + "context" "encoding/json" "errors" "fmt" @@ -105,15 +106,26 @@ func (w *worker) runFuzzing() error { args := fuzzArgs{Duration: workerFuzzDuration} value, resp, err := w.client.fuzz(input.b, args) if err != nil { - // TODO(jayconrod): if we get an error here, something failed between - // main and the call to testing.F.Fuzz. The error here won't - // be useful. Collect stderr, clean it up, and return that. - // TODO(jayconrod): we can get EPIPE if w.stop is called concurrently - // and it kills the worker process. Suppress this message in - // that case. + // Error communicating with worker. + select { + case <-w.termC: + // Worker terminated, perhaps unexpectedly. + // We expect I/O errors due to partially sent or received RPCs, + // so ignore this error. + case <-w.coordinator.doneC: + // Timeout or interruption. Worker may also be interrupted. + // Again, ignore I/O errors. + default: + // TODO(jayconrod): if we get an error here, something failed between + // main and the call to testing.F.Fuzz. The error here won't + // be useful. Collect stderr, clean it up, and return that. + // TODO(jayconrod): we can get EPIPE if w.stop is called concurrently + // and it kills the worker process. Suppress this message in + // that case. + fmt.Fprintf(os.Stderr, "communicating with worker: %v\n", err) + } // TODO(jayconrod): what happens if testing.F.Fuzz is never called? // TODO(jayconrod): time out if the test process hangs. - fmt.Fprintf(os.Stderr, "communicating with worker: %v\n", err) } else if resp.Err != "" { // The worker found a crasher. Inform the coordinator. crasher := crasherEntry{ @@ -301,13 +313,13 @@ func (w *worker) stop() error { // // RunFuzzWorker returns an error if it could not communicate with the // coordinator process. -func RunFuzzWorker(fn func([]byte) error) error { +func RunFuzzWorker(ctx context.Context, fn func([]byte) error) error { comm, err := getWorkerComm() if err != nil { return err } srv := &workerServer{workerComm: comm, fuzzFn: fn} - return srv.serve() + return srv.serve(ctx) } // call is serialized and sent from the coordinator on fuzz_in. It acts as @@ -370,21 +382,41 @@ type workerServer struct { // serve returns errors that occurred when communicating over pipes. serve // does not return errors from method calls; those are passed through serialized // responses. -func (ws *workerServer) serve() error { +func (ws *workerServer) serve(ctx context.Context) error { + // Stop handling messages when ctx.Done() is closed. This normally happens + // when the worker process receives a SIGINT signal, which on POSIX platforms + // is sent to the process group when ^C is pressed. + // + // Ordinarily, the coordinator process may stop a worker by closing fuzz_in. + // We simulate that and interrupt a blocked read here. + doneC := make(chan struct{}) + defer func() { close(doneC) }() + go func() { + select { + case <-ctx.Done(): + ws.fuzzIn.Close() + case <-doneC: + } + }() + enc := json.NewEncoder(ws.fuzzOut) dec := json.NewDecoder(ws.fuzzIn) for { var c call - if err := dec.Decode(&c); err == io.EOF { - return nil - } else if err != nil { - return err + if err := dec.Decode(&c); err != nil { + if ctx.Err() != nil { + return ctx.Err() + } else if err == io.EOF { + return nil + } else { + return err + } } var resp interface{} switch { case c.Fuzz != nil: - resp = ws.fuzz(*c.Fuzz) + resp = ws.fuzz(ctx, *c.Fuzz) default: return errors.New("no arguments provided for any call") } @@ -398,11 +430,13 @@ func (ws *workerServer) serve() error { // fuzz runs the test function on random variations of a given input value for // a given amount of time. fuzz returns early if it finds an input that crashes // the fuzz function or an input that expands coverage. -func (ws *workerServer) fuzz(args fuzzArgs) fuzzResponse { - t := time.NewTimer(args.Duration) +func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) fuzzResponse { + ctx, cancel := context.WithTimeout(ctx, args.Duration) + defer cancel() + for { select { - case <-t.C: + case <-ctx.Done(): // TODO(jayconrod,katiehockman): this value is not interesting. Use a // real heuristic once we have one. return fuzzResponse{Interesting: true} diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 996e361300..4351704b58 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -16,12 +16,14 @@ import ( func initFuzzFlags() { matchFuzz = flag.String("test.fuzz", "", "run the fuzz target matching `regexp`") + fuzzDuration = flag.Duration("test.fuzztime", 0, "time to spend fuzzing; default (0) is to run indefinitely") fuzzCacheDir = flag.String("test.fuzzcachedir", "", "directory where interesting fuzzing inputs are stored") isFuzzWorker = flag.Bool("test.fuzzworker", false, "coordinate with the parent process to fuzz random values") } var ( matchFuzz *string + fuzzDuration *time.Duration fuzzCacheDir *string isFuzzWorker *bool @@ -136,7 +138,7 @@ func (f *F) Fuzz(ff interface{}) { } corpusTargetDir := filepath.Join(corpusDir, f.name) cacheTargetDir := filepath.Join(*fuzzCacheDir, f.name) - err := f.context.coordinateFuzzing(*parallel, seed, corpusTargetDir, cacheTargetDir) + err := f.context.coordinateFuzzing(*fuzzDuration, *parallel, seed, corpusTargetDir, cacheTargetDir) if err != nil { f.Fail() f.result = FuzzResult{Error: err} @@ -279,7 +281,7 @@ func (r FuzzResult) String() string { type fuzzContext struct { runMatch *matcher fuzzMatch *matcher - coordinateFuzzing func(int, [][]byte, string, string) error + coordinateFuzzing func(time.Duration, int, [][]byte, string, string) error runFuzzWorker func(func([]byte) error) error readCorpus func(string) ([][]byte, error) } diff --git a/src/testing/internal/testdeps/deps.go b/src/testing/internal/testdeps/deps.go index dcca6032d0..12da4f3863 100644 --- a/src/testing/internal/testdeps/deps.go +++ b/src/testing/internal/testdeps/deps.go @@ -12,13 +12,17 @@ package testdeps import ( "bufio" + "context" "internal/fuzz" "internal/testlog" "io" + "os" + "os/signal" "regexp" "runtime/pprof" "strings" "sync" + "time" ) // TestDeps is an implementation of the testing.testDeps interface, @@ -128,12 +132,51 @@ func (TestDeps) SetPanicOnExit0(v bool) { testlog.SetPanicOnExit0(v) } -func (TestDeps) CoordinateFuzzing(parallel int, seed [][]byte, corpusDir, cacheDir string) error { - return fuzz.CoordinateFuzzing(parallel, seed, corpusDir, cacheDir) +func (TestDeps) CoordinateFuzzing(timeout time.Duration, parallel int, seed [][]byte, corpusDir, cacheDir string) error { + // Fuzzing may be interrupted with a timeout or if the user presses ^C. + // In either case, we'll stop worker processes gracefully and save + // crashers and interesting values. + ctx := context.Background() + cancel := func() {} + if timeout > 0 { + ctx, cancel = context.WithTimeout(ctx, timeout) + } + interruptC := make(chan os.Signal, 1) + signal.Notify(interruptC, os.Interrupt) + go func() { + <-interruptC + cancel() + }() + defer close(interruptC) + + err := fuzz.CoordinateFuzzing(ctx, parallel, seed, corpusDir, cacheDir) + if err == ctx.Err() { + return nil + } + return err } func (TestDeps) RunFuzzWorker(fn func([]byte) error) error { - return fuzz.RunFuzzWorker(fn) + // Worker processes may or may not receive a signal when the user presses ^C + // On POSIX operating systems, a signal sent to a process group is delivered + // to all processes in that group. This is not the case on Windows. + // If the worker is interrupted, return quickly and without error. + // If only the coordinator process is interrupted, it tells each worker + // process to stop by closing its "fuzz_in" pipe. + ctx, cancel := context.WithCancel(context.Background()) + interruptC := make(chan os.Signal, 1) + signal.Notify(interruptC, os.Interrupt) + go func() { + <-interruptC + cancel() + }() + defer close(interruptC) + + err := fuzz.RunFuzzWorker(ctx, fn) + if err == ctx.Err() { + return nil + } + return nil } func (TestDeps) ReadCorpus(dir string) ([][]byte, error) { diff --git a/src/testing/testing.go b/src/testing/testing.go index e3e35fa13a..39316122a6 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1353,17 +1353,19 @@ var errMain = errors.New("testing: unexpected use of func Main") type matchStringOnly func(pat, str string) (bool, error) -func (f matchStringOnly) MatchString(pat, str string) (bool, error) { return f(pat, str) } -func (f matchStringOnly) StartCPUProfile(w io.Writer) error { return errMain } -func (f matchStringOnly) StopCPUProfile() {} -func (f matchStringOnly) WriteProfileTo(string, io.Writer, int) error { return errMain } -func (f matchStringOnly) ImportPath() string { return "" } -func (f matchStringOnly) StartTestLog(io.Writer) {} -func (f matchStringOnly) StopTestLog() error { return errMain } -func (f matchStringOnly) SetPanicOnExit0(bool) {} -func (f matchStringOnly) CoordinateFuzzing(int, [][]byte, string, string) error { return errMain } -func (f matchStringOnly) RunFuzzWorker(func([]byte) error) error { return errMain } -func (f matchStringOnly) ReadCorpus(string) ([][]byte, error) { return nil, errMain } +func (f matchStringOnly) MatchString(pat, str string) (bool, error) { return f(pat, str) } +func (f matchStringOnly) StartCPUProfile(w io.Writer) error { return errMain } +func (f matchStringOnly) StopCPUProfile() {} +func (f matchStringOnly) WriteProfileTo(string, io.Writer, int) error { return errMain } +func (f matchStringOnly) ImportPath() string { return "" } +func (f matchStringOnly) StartTestLog(io.Writer) {} +func (f matchStringOnly) StopTestLog() error { return errMain } +func (f matchStringOnly) SetPanicOnExit0(bool) {} +func (f matchStringOnly) CoordinateFuzzing(time.Duration, int, [][]byte, string, string) error { + return errMain +} +func (f matchStringOnly) RunFuzzWorker(func([]byte) error) error { return errMain } +func (f matchStringOnly) ReadCorpus(string) ([][]byte, error) { return nil, errMain } // Main is an internal function, part of the implementation of the "go test" command. // It was exported because it is cross-package and predates "internal" packages. @@ -1406,7 +1408,7 @@ type testDeps interface { StartTestLog(io.Writer) StopTestLog() error WriteProfileTo(string, io.Writer, int) error - CoordinateFuzzing(int, [][]byte, string, string) error + CoordinateFuzzing(time.Duration, int, [][]byte, string, string) error RunFuzzWorker(func([]byte) error) error ReadCorpus(string) ([][]byte, error) } @@ -1448,6 +1450,12 @@ func (m *M) Run() (code int) { m.exitCode = 2 return } + if *fuzzDuration < 0 { + fmt.Fprintln(os.Stderr, "testing: -fuzztime can only be given a positive duration, or zero to run indefinitely") + flag.Usage() + m.exitCode = 2 + return + } if *matchFuzz != "" && *fuzzCacheDir == "" { fmt.Fprintln(os.Stderr, "testing: internal error: -test.fuzzcachedir must be set if -test.fuzz is set") flag.Usage() -- GitLab From 2f072cf8a975afb082b40cb29238ce536b5ae9b6 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Tue, 5 Jan 2021 16:01:49 -0500 Subject: [PATCH 0024/2500] [dev.fuzz] internal/fuzz: implement a more robust mutator This change also allocates a larger capacity (100 MB) for the shared memory at the start, rather than beginning as small as possible and immediately needing to grow while mutating. This means that 100 MB is the maximum size of a corpus entry currently, since growing the shared memory is not yet supported. The code in internal/fuzz/mutator.go and internal/fuzz/pcg.go are copied from, or heavily inspired by, code originally authored by Dmitry Vyukov and Josh Bleecher Snyder as part of the go-fuzz project. Thanks to them for their contributions. See https://github.com/dvyukov/go-fuzz. Change-Id: I0d51d53976e23933072e760ff78e6c4ad9dcd862 Reviewed-on: https://go-review.googlesource.com/c/go/+/281972 Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod Trust: Katie Hockman --- .../script/test_fuzz_mutate_crash.txt | 66 ++++- ..._fuzz_mutate.txt => test_fuzz_mutator.txt} | 45 +++- src/internal/fuzz/fuzz.go | 11 +- src/internal/fuzz/mem.go | 9 +- src/internal/fuzz/mutator.go | 244 +++++++++++++++++- src/internal/fuzz/pcg.go | 104 ++++++++ src/internal/fuzz/worker.go | 9 +- 7 files changed, 454 insertions(+), 34 deletions(-) rename src/cmd/go/testdata/script/{test_fuzz_mutate.txt => test_fuzz_mutator.txt} (73%) create mode 100644 src/internal/fuzz/pcg.go diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt index 6816950265..2d5e1e5fd7 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt @@ -13,23 +13,23 @@ go test -parallel=1 # Running the fuzzer should find a crashing input quickly. ! go test -fuzz=FuzzWithBug -fuzztime=5s -parallel=1 -stdout 'testdata[/\\]corpus[/\\]FuzzWithBug[/\\]fb8e20fc2e4c3f248c60c39bd652f3c1347298bb977b8b4d5903b85055620603' +stdout 'testdata[/\\]corpus[/\\]FuzzWithBug[/\\]' stdout 'this input caused a crash!' -grep '\Aab\z' testdata/corpus/FuzzWithBug/fb8e20fc2e4c3f248c60c39bd652f3c1347298bb977b8b4d5903b85055620603 +go run check_testdata.go FuzzWithBug # Now, the failing bytes should have been added to the seed corpus for # the target, and should fail when run without fuzzing. ! go test -parallel=1 ! go test -run=FuzzWithNilPanic -fuzz=FuzzWithNilPanic -fuzztime=5s -parallel=1 -stdout 'testdata[/\\]corpus[/\\]FuzzWithNilPanic[/\\]f45de51cdef30991551e41e882dd7b5404799648a0a00753f44fc966e6153fc1' +stdout 'testdata[/\\]corpus[/\\]FuzzWithNilPanic[/\\]' stdout 'runtime.Goexit' -grep '\Aac\z' testdata/corpus/FuzzWithNilPanic/f45de51cdef30991551e41e882dd7b5404799648a0a00753f44fc966e6153fc1 +go run check_testdata.go FuzzWithNilPanic ! go test -run=FuzzWithBadExit -fuzz=FuzzWithBadExit -fuzztime=5s -parallel=1 -stdout 'testdata[/\\]corpus[/\\]FuzzWithBadExit[/\\]70ba33708cbfb103f1a8e34afef333ba7dc021022b2d9aaa583aabb8058d8d67' +stdout 'testdata[/\\]corpus[/\\]FuzzWithBadExit[/\\]' stdout 'unexpectedly' -grep '\Aad\z' testdata/corpus/FuzzWithBadExit/70ba33708cbfb103f1a8e34afef333ba7dc021022b2d9aaa583aabb8058d8d67 +go run check_testdata.go FuzzWithBadExit -- go.mod -- module m @@ -39,7 +39,6 @@ go 1.16 package fuzz_crash import ( - "bytes" "os" "testing" ) @@ -47,7 +46,7 @@ import ( func FuzzWithBug(f *testing.F) { f.Add([]byte("aa")) f.Fuzz(func(t *testing.T, b []byte) { - if bytes.Equal(b, []byte("ab")) { + if string(b) != "aa" { panic("this input caused a crash!") } }) @@ -56,7 +55,7 @@ func FuzzWithBug(f *testing.F) { func FuzzWithNilPanic(f *testing.F) { f.Add([]byte("aa")) f.Fuzz(func(t *testing.T, b []byte) { - if bytes.Equal(b, []byte("ac")) { + if string(b) != "aa" { panic(nil) } }) @@ -65,8 +64,55 @@ func FuzzWithNilPanic(f *testing.F) { func FuzzWithBadExit(f *testing.F) { f.Add([]byte("aa")) f.Fuzz(func(t *testing.T, b []byte) { - if bytes.Equal(b, []byte("ad")) { + if string(b) != "aa" { os.Exit(1) } }) +} + +-- check_testdata.go -- +// +build ignore + +package main + +import ( + "bytes" + "crypto/sha256" + "fmt" + "io/ioutil" + "os" + "path/filepath" +) + +func main() { + target := os.Args[1] + dir := filepath.Join("testdata/corpus", target) + + files, err := ioutil.ReadDir(dir) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + + if len(files) != 1 { + fmt.Fprintln(os.Stderr, fmt.Errorf("expect only one new mutation to be written to testdata", len(files))) + os.Exit(1) + } + + fname := files[0].Name() + contents, err := ioutil.ReadFile(filepath.Join(dir, fname)) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + if bytes.Equal(contents, []byte("aa")) { + fmt.Fprintln(os.Stderr, fmt.Errorf("newly written testdata entry was not mutated")) + os.Exit(1) + } + // The hash of the bytes in the file should match the filename. + h := []byte(fmt.Sprintf("%x", sha256.Sum256(contents))) + if !bytes.Equal([]byte(fname), h) { + fmt.Fprintln(os.Stderr, fmt.Errorf("hash of bytes %q does not match filename %q", h, fname)) + os.Exit(1) + } } \ No newline at end of file diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate.txt b/src/cmd/go/testdata/script/test_fuzz_mutator.txt similarity index 73% rename from src/cmd/go/testdata/script/test_fuzz_mutate.txt rename to src/cmd/go/testdata/script/test_fuzz_mutator.txt index cbd0838e73..f858dcf354 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutate.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutator.txt @@ -10,6 +10,12 @@ go test -fuzz=FuzzA -fuzztime=5s -parallel=1 -log=fuzz go run check_logs.go fuzz fuzz.worker +# Test that the mutator is good enough to find several unique mutations. +! go test -v -fuzz=Fuzz -parallel=1 -fuzztime=30s mutator_test.go +! stdout ok +stdout FAIL +stdout 'mutator found enough edge cases' + -- go.mod -- module m @@ -143,7 +149,7 @@ func checkWorkerLog(r io.Reader) error { sawAMutant = true } } - if err := scan.Err(); err != nil { + if err := scan.Err(); err != nil && err != bufio.ErrTooLong { return err } if !sawAMutant { @@ -151,3 +157,40 @@ func checkWorkerLog(r io.Reader) error { } return nil } + +-- mutator_test.go -- +package fuzz_test + +import ( + "strings" + "testing" +) + +// TODO(katiehockman): re-work this test once we have a better fuzzing engine +// (ie. more mutations, and compiler instrumentation) +func Fuzz(f *testing.F) { + // TODO(katiehockman): simplify this once we can dedupe crashes (e.g. + // replace map with calls to panic, and simply count the number of crashes + // that were added to testdata) + crashes := make(map[string]bool) + // No seed corpus initiated + f.Fuzz(func(t *testing.T, b []byte) { + if len(crashes) >= 150 { + panic("mutator found enough edge cases") + } + + if len(b) < 5 { + return // continue + } + + for i := 0; i < 256; i++ { + s := string(byte(i)) + if strings.HasPrefix(string(b), s) { + crashes["pre-" + s] = true + } + if strings.HasSuffix(string(b), s) { + crashes["suffix-" + s] = true + } + } + }) +} \ No newline at end of file diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index aacc053682..2a60e73c7f 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -47,20 +47,13 @@ func CoordinateFuzzing(ctx context.Context, parallel int, seed [][]byte, corpusD parallel = runtime.GOMAXPROCS(0) } + sharedMemSize := 100 << 20 // 100 MB corpus, err := readCorpusAndCache(seed, corpusDir, cacheDir) if err != nil { return err } - var maxEntryLen int if len(corpus.entries) == 0 { corpus.entries = []corpusEntry{{b: []byte{}}} - maxEntryLen = 0 - } else { - for _, e := range corpus.entries { - if len(e.b) > maxEntryLen { - maxEntryLen = len(e.b) - } - } } // TODO(jayconrod): do we want to support fuzzing different binaries? @@ -78,7 +71,7 @@ func CoordinateFuzzing(ctx context.Context, parallel int, seed [][]byte, corpusD } newWorker := func() (*worker, error) { - mem, err := sharedMemTempFile(maxEntryLen) + mem, err := sharedMemTempFile(sharedMemSize) if err != nil { return nil, err } diff --git a/src/internal/fuzz/mem.go b/src/internal/fuzz/mem.go index 54e3eb737c..663598bb48 100644 --- a/src/internal/fuzz/mem.go +++ b/src/internal/fuzz/mem.go @@ -47,10 +47,9 @@ func sharedMemSize(valueSize int) int { return int(unsafe.Sizeof(sharedMemHeader{})) + valueSize } -// sharedMemTempFile creates a new temporary file large enough to hold a value -// of the given size, then maps it into memory. The file will be removed when -// the Close method is called. -func sharedMemTempFile(valueSize int) (m *sharedMem, err error) { +// sharedMemTempFile creates a new temporary file of the given size, then maps +// it into memory. The file will be removed when the Close method is called. +func sharedMemTempFile(size int) (m *sharedMem, err error) { // Create a temporary file. f, err := ioutil.TempFile("", "fuzz-*") if err != nil { @@ -64,7 +63,7 @@ func sharedMemTempFile(valueSize int) (m *sharedMem, err error) { }() // Resize it to the correct size. - totalSize := sharedMemSize(valueSize) + totalSize := sharedMemSize(size) if err := f.Truncate(int64(totalSize)); err != nil { return nil, err } diff --git a/src/internal/fuzz/mutator.go b/src/internal/fuzz/mutator.go index 6a52e46f6f..377491adcb 100644 --- a/src/internal/fuzz/mutator.go +++ b/src/internal/fuzz/mutator.go @@ -4,14 +4,244 @@ package fuzz -import "math/rand" +import ( + "encoding/binary" + "reflect" + "unsafe" +) -func mutate(b []byte) { - if len(b) == 0 { - return +type mutator struct { + r *pcgRand +} + +func newMutator() *mutator { + return &mutator{r: newPcgRand()} +} + +func (m *mutator) rand(n int) int { + return m.r.intn(n) +} + +func (m *mutator) randByteOrder() binary.ByteOrder { + if m.r.bool() { + return binary.LittleEndian + } + return binary.BigEndian +} + +// chooseLen chooses length of range mutation in range [0,n]. It gives +// preference to shorter ranges. +func (m *mutator) chooseLen(n int) int { + switch x := m.rand(100); { + case x < 90: + return m.rand(min(8, n)) + 1 + case x < 99: + return m.rand(min(32, n)) + 1 + default: + return m.rand(n) + 1 + } +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +// mutate performs several mutations directly onto the provided byte slice. +func (m *mutator) mutate(ptrB *[]byte) { + // TODO(jayconrod,katiehockman): make this use zero allocations + // TODO(katiehockman): pull some of these functions into helper methods + // and test that each case is working as expected. + // TODO(katiehockman): perform more types of mutations. + b := *ptrB + defer func() { + oldHdr := (*reflect.SliceHeader)(unsafe.Pointer(ptrB)) + newHdr := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + if oldHdr.Data != newHdr.Data { + panic("data moved to new address") + } + *ptrB = b + }() + + numIters := 1 + m.r.exp2() + for iter := 0; iter < numIters; iter++ { + switch m.rand(10) { + case 0: + // Remove a range of bytes. + if len(b) <= 1 { + iter-- + continue + } + pos0 := m.rand(len(b)) + pos1 := pos0 + m.chooseLen(len(b)-pos0) + copy(b[pos0:], b[pos1:]) + b = b[:len(b)-(pos1-pos0)] + case 1: + // Insert a range of random bytes. + pos := m.rand(len(b) + 1) + n := m.chooseLen(10) + if len(b)+n >= cap(b) { + iter-- + continue + } + b = b[:len(b)+n] + copy(b[pos+n:], b[pos:]) + for i := 0; i < n; i++ { + b[pos+i] = byte(m.rand(256)) + } + case 2: + // Duplicate a range of bytes. + if len(b) <= 1 { + iter-- + continue + } + src := m.rand(len(b)) + dst := m.rand(len(b)) + for dst == src { + dst = m.rand(len(b)) + } + n := m.chooseLen(len(b) - src) + tmp := make([]byte, n) + copy(tmp, b[src:]) + b = b[:len(b)+n] + copy(b[dst+n:], b[dst:]) + copy(b[dst:], tmp) + case 3: + // Copy a range of bytes. + if len(b) <= 1 { + iter-- + continue + } + src := m.rand(len(b)) + dst := m.rand(len(b)) + for dst == src { + dst = m.rand(len(b)) + } + n := m.chooseLen(len(b) - src) + copy(b[dst:], b[src:src+n]) + case 4: + // Bit flip. + if len(b) == 0 { + iter-- + continue + } + pos := m.rand(len(b)) + b[pos] ^= 1 << uint(m.rand(8)) + case 5: + // Set a byte to a random value. + if len(b) == 0 { + iter-- + continue + } + pos := m.rand(len(b)) + b[pos] = byte(m.rand(256)) + case 6: + // Swap 2 bytes. + if len(b) <= 1 { + iter-- + continue + } + src := m.rand(len(b)) + dst := m.rand(len(b)) + for dst == src { + dst = m.rand(len(b)) + } + b[src], b[dst] = b[dst], b[src] + case 7: + // Add/subtract from a byte. + if len(b) == 0 { + iter-- + continue + } + pos := m.rand(len(b)) + v := byte(m.rand(35) + 1) + if m.r.bool() { + b[pos] += v + } else { + b[pos] -= v + } + case 8: + // Add/subtract from a uint16. + if len(b) < 2 { + iter-- + continue + } + v := uint16(m.rand(35) + 1) + if m.r.bool() { + v = 0 - v + } + pos := m.rand(len(b) - 1) + enc := m.randByteOrder() + enc.PutUint16(b[pos:], enc.Uint16(b[pos:])+v) + case 9: + // Add/subtract from a uint32. + if len(b) < 4 { + iter-- + continue + } + v := uint32(m.rand(35) + 1) + if m.r.bool() { + v = 0 - v + } + pos := m.rand(len(b) - 3) + enc := m.randByteOrder() + enc.PutUint32(b[pos:], enc.Uint32(b[pos:])+v) + case 10: + // Add/subtract from a uint64. + if len(b) < 8 { + iter-- + continue + } + v := uint64(m.rand(35) + 1) + if m.r.bool() { + v = 0 - v + } + pos := m.rand(len(b) - 7) + enc := m.randByteOrder() + enc.PutUint64(b[pos:], enc.Uint64(b[pos:])+v) + case 11: + // Replace a byte with an interesting value. + if len(b) == 0 { + iter-- + continue + } + pos := m.rand(len(b)) + b[pos] = byte(interesting8[m.rand(len(interesting8))]) + case 12: + // Replace a uint16 with an interesting value. + if len(b) < 2 { + iter-- + continue + } + pos := m.rand(len(b) - 1) + v := uint16(interesting16[m.rand(len(interesting16))]) + m.randByteOrder().PutUint16(b[pos:], v) + case 13: + // Replace a uint32 with an interesting value. + if len(b) < 4 { + iter-- + continue + } + pos := m.rand(len(b) - 3) + v := uint32(interesting32[m.rand(len(interesting32))]) + m.randByteOrder().PutUint32(b[pos:], v) + } } +} + +var ( + interesting8 = []int8{-128, -1, 0, 1, 16, 32, 64, 100, 127} + interesting16 = []int16{-32768, -129, 128, 255, 256, 512, 1000, 1024, 4096, 32767} + interesting32 = []int32{-2147483648, -100663046, -32769, 32768, 65535, 65536, 100663045, 2147483647} +) - // Mutate a byte in a random position. - pos := rand.Intn(len(b)) - b[pos] = byte(rand.Intn(256)) +func init() { + for _, v := range interesting8 { + interesting16 = append(interesting16, int16(v)) + } + for _, v := range interesting16 { + interesting32 = append(interesting32, int32(v)) + } } diff --git a/src/internal/fuzz/pcg.go b/src/internal/fuzz/pcg.go new file mode 100644 index 0000000000..5f0c1c39f6 --- /dev/null +++ b/src/internal/fuzz/pcg.go @@ -0,0 +1,104 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fuzz + +import ( + "math/bits" + "sync/atomic" + "time" +) + +// The functions in pcg implement a 32 bit PRNG with a 64 bit period: pcg xsh rr +// 64 32. See https://www.pcg-random.org/ for more information. This +// implementation is geared specifically towards the needs of fuzzing: Simple +// creation and use, no reproducibility, no concurrency safety, just the +// necessary methods, optimized for speed. + +var globalInc uint64 // PCG stream + +const multiplier uint64 = 6364136223846793005 + +// pcgRand is a PRNG. It should not be copied or shared. No Rand methods are +// concurrency safe. +type pcgRand struct { + noCopy noCopy // help avoid mistakes: ask vet to ensure that we don't make a copy + state uint64 + inc uint64 +} + +// newPcgRand generates a new, seeded Rand, ready for use. +func newPcgRand() *pcgRand { + r := new(pcgRand) + now := uint64(time.Now().UnixNano()) + inc := atomic.AddUint64(&globalInc, 1) + r.state = now + r.inc = (inc << 1) | 1 + r.step() + r.state += now + r.step() + return r +} + +func (r *pcgRand) step() { + r.state *= multiplier + r.state += r.inc +} + +// uint32 returns a pseudo-random uint32. +func (r *pcgRand) uint32() uint32 { + x := r.state + r.step() + return bits.RotateLeft32(uint32(((x>>18)^x)>>27), -int(x>>59)) +} + +// intn returns a pseudo-random number in [0, n). +// n must fit in a uint32. +func (r *pcgRand) intn(n int) int { + if int(uint32(n)) != n { + panic("large Intn") + } + return int(r.uint32n(uint32(n))) +} + +// uint32n returns a pseudo-random number in [0, n). +// +// For implementation details, see: +// https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction +// https://lemire.me/blog/2016/06/30/fast-random-shuffling +func (r *pcgRand) uint32n(n uint32) uint32 { + v := r.uint32() + prod := uint64(v) * uint64(n) + low := uint32(prod) + if low < n { + thresh := uint32(-int32(n)) % n + for low < thresh { + v = r.uint32() + prod = uint64(v) * uint64(n) + low = uint32(prod) + } + } + return uint32(prod >> 32) +} + +// exp2 generates n with probability 1/2^(n+1). +func (r *pcgRand) exp2() int { + return bits.TrailingZeros32(r.uint32()) +} + +// bool generates a random bool. +func (r *pcgRand) bool() bool { + return r.uint32()&1 == 0 +} + +// noCopy may be embedded into structs which must not be copied +// after the first use. +// +// See https://golang.org/issues/8005#issuecomment-190753527 +// for details. +type noCopy struct{} + +// lock is a no-op used by -copylocks checker from `go vet`. +func (*noCopy) lock() {} +func (*noCopy) unlock() {} diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index ef2a9303ef..8947641996 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -318,7 +318,7 @@ func RunFuzzWorker(ctx context.Context, fn func([]byte) error) error { if err != nil { return err } - srv := &workerServer{workerComm: comm, fuzzFn: fn} + srv := &workerServer{workerComm: comm, fuzzFn: fn, m: newMutator()} return srv.serve(ctx) } @@ -366,6 +366,7 @@ type workerComm struct { // memory after a worker process terminates unexpectedly. type workerServer struct { workerComm + m *mutator // fuzzFn runs the worker's fuzz function on the given input and returns // an error if it finds a crasher (the process may also exit or crash). @@ -441,7 +442,11 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) fuzzResponse { // real heuristic once we have one. return fuzzResponse{Interesting: true} default: - mutate(ws.mem.valueRef()) + b := ws.mem.valueRef() + ws.m.mutate(&b) + // TODO(jayconrod): consider making ws.m.header() contain the whole + // slice header, so the length can be updated when the slice changes + ws.mem.header().length = len(b) if err := ws.fuzzFn(ws.mem.valueRef()); err != nil { return fuzzResponse{Err: err.Error()} } -- GitLab From 06074108fab489d6bd7358e736bcd0cb38830c7c Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Wed, 13 Jan 2021 14:43:30 -0500 Subject: [PATCH 0025/2500] [dev.fuzz] internal/fuzz: fix context cancellation for coordinator Previously, performing a SIGINT would cause the coordinator to write a crash to testdata, and would continue to run despite being interupted. Also includes a few small cleanups. Change-Id: Ia3cf7cd231c30ac9ad2a61f4935aa543e241f60d Reviewed-on: https://go-review.googlesource.com/c/go/+/283634 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/internal/fuzz/fuzz.go | 1 + src/internal/fuzz/worker.go | 2 +- src/testing/internal/testdeps/deps.go | 3 +-- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 2a60e73c7f..e05b5566ae 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -119,6 +119,7 @@ func CoordinateFuzzing(ctx context.Context, parallel int, seed [][]byte, corpusD // Return the first error found, replacing ctx.Err() if a more // interesting error is found. err = werr + break } } } diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 8947641996..ee31ff43c6 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -135,7 +135,7 @@ func (w *worker) runFuzzing() error { w.coordinator.crasherC <- crasher } else { // Inform the coordinator that fuzzing found something - // interesting (ie. a crash or new coverage). + // interesting (i.e. new coverage). if resp.Interesting { w.coordinator.interestingC <- corpusEntry{b: value} } diff --git a/src/testing/internal/testdeps/deps.go b/src/testing/internal/testdeps/deps.go index 12da4f3863..dbc30ddc0f 100644 --- a/src/testing/internal/testdeps/deps.go +++ b/src/testing/internal/testdeps/deps.go @@ -136,8 +136,7 @@ func (TestDeps) CoordinateFuzzing(timeout time.Duration, parallel int, seed [][] // Fuzzing may be interrupted with a timeout or if the user presses ^C. // In either case, we'll stop worker processes gracefully and save // crashers and interesting values. - ctx := context.Background() - cancel := func() {} + ctx, cancel := context.WithCancel(context.Background()) if timeout > 0 { ctx, cancel = context.WithTimeout(ctx, timeout) } -- GitLab From cc7f8c305501399c78d894b7ba7bd3ea428b250e Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Thu, 14 Jan 2021 18:22:41 -0500 Subject: [PATCH 0026/2500] [dev.fuzz] internal/fuzz: add sharedMem.setValueLen This method sets the len of the slice returned by valueRef. The worker now uses this instead of setting the length in the header directly. Unfortunately, we can't store the whole slice header in the shared memory header because the pointer won't be valid across processes. Change-Id: Icef24acfcd85e098cd8c23810568f04b13649a19 Reviewed-on: https://go-review.googlesource.com/c/go/+/284012 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/internal/fuzz/mem.go | 14 ++++++++++++++ src/internal/fuzz/worker.go | 6 ++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/internal/fuzz/mem.go b/src/internal/fuzz/mem.go index 663598bb48..bb30241a45 100644 --- a/src/internal/fuzz/mem.go +++ b/src/internal/fuzz/mem.go @@ -106,6 +106,20 @@ func (m *sharedMem) setValue(b []byte) { copy(v[:cap(v)], b) } +// setValueLen sets the length of the shared memory buffer returned by valueRef +// to n, which may be at most the cap of that slice. +// +// Note that we can only store the length in the shared memory header. The full +// slice header contains a pointer, which is likely only valid for one process, +// since each process can map shared memory at a different virtual address. +func (m *sharedMem) setValueLen(n int) { + v := m.valueRef() + if n > cap(v) { + panic(fmt.Sprintf("length %d larger than shared memory capacity %d", n, cap(v))) + } + m.header().length = n +} + // TODO(jayconrod): add method to resize the buffer. We'll need that when the // mutator can increase input length. Only the coordinator will be able to // do it, since we'll need to send a message to the worker telling it to diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index ee31ff43c6..583e8f25c1 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -444,10 +444,8 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) fuzzResponse { default: b := ws.mem.valueRef() ws.m.mutate(&b) - // TODO(jayconrod): consider making ws.m.header() contain the whole - // slice header, so the length can be updated when the slice changes - ws.mem.header().length = len(b) - if err := ws.fuzzFn(ws.mem.valueRef()); err != nil { + ws.mem.setValueLen(len(b)) + if err := ws.fuzzFn(b); err != nil { return fuzzResponse{Err: err.Error()} } // TODO(jayconrod,katiehockman): return early if we find an -- GitLab From d45df5de32e555a0386b7e473d30516d744df70a Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Fri, 15 Jan 2021 11:26:34 -0500 Subject: [PATCH 0027/2500] [dev.fuzz] cmd/go/testdata: fix flaky test Change-Id: I7702aa12a1ed9bb0645af774dd584e661d7c8fa5 Reviewed-on: https://go-review.googlesource.com/c/go/+/284193 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- .../go/testdata/script/test_fuzz_mutator.txt | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_mutator.txt b/src/cmd/go/testdata/script/test_fuzz_mutator.txt index f858dcf354..bc7edf3cc5 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutator.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutator.txt @@ -14,7 +14,7 @@ go run check_logs.go fuzz fuzz.worker ! go test -v -fuzz=Fuzz -parallel=1 -fuzztime=30s mutator_test.go ! stdout ok stdout FAIL -stdout 'mutator found enough edge cases' +stdout 'mutator found enough unique mutations' -- go.mod -- module m @@ -162,7 +162,6 @@ func checkWorkerLog(r io.Reader) error { package fuzz_test import ( - "strings" "testing" ) @@ -175,22 +174,9 @@ func Fuzz(f *testing.F) { crashes := make(map[string]bool) // No seed corpus initiated f.Fuzz(func(t *testing.T, b []byte) { - if len(crashes) >= 150 { - panic("mutator found enough edge cases") - } - - if len(b) < 5 { - return // continue - } - - for i := 0; i < 256; i++ { - s := string(byte(i)) - if strings.HasPrefix(string(b), s) { - crashes["pre-" + s] = true - } - if strings.HasSuffix(string(b), s) { - crashes["suffix-" + s] = true - } + crashes[string(b)] = true + if len(crashes) >= 1000 { + panic("mutator found enough unique mutations") } }) } \ No newline at end of file -- GitLab From 8e0584c327e429bd010edb28fb9fea6f68a4cccc Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Fri, 15 Jan 2021 14:43:25 -0500 Subject: [PATCH 0028/2500] [dev.fuzz] internal/fuzz: handle SIGINT races gracefully A worker process may be terminated by SIGINT if it doesn't install the signal handler before SIGINT is delivered. That's likely when TestMain or the fuzz target setup take a long time. The coordinator now ignores these errors. Also, when testdeps.TestDeps.CoordinateFuzzing and RunFuzzWorker return, they will send a value on the chan passed to signal.Notify instead of closing it. This should have been obvious in hindsight, but the signal handler could still send a value on that channel after those functions return but before the process exits. Change-Id: Iea2589115f1f9bb7415bb5e7911defee423e642e Reviewed-on: https://go-review.googlesource.com/c/go/+/284292 Trust: Jay Conrod Reviewed-by: Katie Hockman --- src/internal/fuzz/sys_posix.go | 11 +++++++++++ src/internal/fuzz/sys_unimplemented.go | 4 ++++ src/internal/fuzz/sys_windows.go | 5 +++++ src/internal/fuzz/worker.go | 25 +++++++++++++++++++------ src/testing/internal/testdeps/deps.go | 4 ++-- 5 files changed, 41 insertions(+), 8 deletions(-) diff --git a/src/internal/fuzz/sys_posix.go b/src/internal/fuzz/sys_posix.go index ec27b4bf00..ecffa72755 100644 --- a/src/internal/fuzz/sys_posix.go +++ b/src/internal/fuzz/sys_posix.go @@ -73,3 +73,14 @@ func getWorkerComm() (comm workerComm, err error) { } return workerComm{fuzzIn: fuzzIn, fuzzOut: fuzzOut, mem: mem}, nil } + +// isInterruptError returns whether an error was returned by a process that +// was terminated by an interrupt signal (SIGINT). +func isInterruptError(err error) bool { + exitErr, ok := err.(*exec.ExitError) + if !ok || exitErr.ExitCode() >= 0 { + return false + } + status := exitErr.Sys().(syscall.WaitStatus) + return status.Signal() == syscall.SIGINT +} diff --git a/src/internal/fuzz/sys_unimplemented.go b/src/internal/fuzz/sys_unimplemented.go index dbb380ef67..331b8761d0 100644 --- a/src/internal/fuzz/sys_unimplemented.go +++ b/src/internal/fuzz/sys_unimplemented.go @@ -29,3 +29,7 @@ func setWorkerComm(cmd *exec.Cmd, comm workerComm) { func getWorkerComm() (comm workerComm, err error) { panic("not implemented") } + +func isInterruptError(err error) bool { + panic("not implemented") +} diff --git a/src/internal/fuzz/sys_windows.go b/src/internal/fuzz/sys_windows.go index 286634c692..678ab0f0a3 100644 --- a/src/internal/fuzz/sys_windows.go +++ b/src/internal/fuzz/sys_windows.go @@ -131,3 +131,8 @@ func getWorkerComm() (comm workerComm, err error) { return workerComm{fuzzIn: fuzzIn, fuzzOut: fuzzOut, mem: mem}, nil } + +func isInterruptError(err error) bool { + // TODO(jayconrod): implement + return false +} diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 583e8f25c1..a10561a244 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -80,19 +80,32 @@ func (w *worker) runFuzzing() error { select { case <-w.coordinator.doneC: // All workers were told to stop. - return w.stop() + err := w.stop() + if isInterruptError(err) { + // Worker interrupted by SIGINT. This can happen if the worker receives + // SIGINT before installing the signal handler. That's likely if + // TestMain or the fuzz target setup takes a long time. + return nil + } + return err case <-w.termC: - // Worker process terminated unexpectedly, so inform the coordinator - // that a crash occurred. + // Worker process terminated unexpectedly. + if isInterruptError(w.waitErr) { + // Worker interrupted by SIGINT. See comment in doneC case. + w.stop() + return nil + } + + // Unexpected termination. Inform the coordinator about the crash. + // TODO(jayconrod,katiehockman): if -keepfuzzing, restart worker. value := w.mem.valueCopy() + message := fmt.Sprintf("fuzzing process terminated unexpectedly: %v", w.waitErr) crasher := crasherEntry{ corpusEntry: corpusEntry{b: value}, - errMsg: "fuzzing process crashed unexpectedly", + errMsg: message, } w.coordinator.crasherC <- crasher - - // TODO(jayconrod,katiehockman): if -keepfuzzing, restart worker. err := w.stop() if err == nil { err = fmt.Errorf("worker exited unexpectedly") diff --git a/src/testing/internal/testdeps/deps.go b/src/testing/internal/testdeps/deps.go index dbc30ddc0f..2d0d7bac38 100644 --- a/src/testing/internal/testdeps/deps.go +++ b/src/testing/internal/testdeps/deps.go @@ -146,7 +146,7 @@ func (TestDeps) CoordinateFuzzing(timeout time.Duration, parallel int, seed [][] <-interruptC cancel() }() - defer close(interruptC) + defer func() { interruptC <- os.Interrupt }() err := fuzz.CoordinateFuzzing(ctx, parallel, seed, corpusDir, cacheDir) if err == ctx.Err() { @@ -169,7 +169,7 @@ func (TestDeps) RunFuzzWorker(fn func([]byte) error) error { <-interruptC cancel() }() - defer close(interruptC) + defer func() { interruptC <- os.Interrupt }() err := fuzz.RunFuzzWorker(ctx, fn) if err == ctx.Err() { -- GitLab From 671dba6c89bc0183982553e0359e0a3b2c00963f Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Wed, 20 Jan 2021 17:09:59 -0500 Subject: [PATCH 0029/2500] [dev.fuzz] internal/fuzz: guard concurrent access to shared memory This change moves the worker's *sharedMem into a buffered chan that acts as a mutex. The mutex can be locked by receiving from the chan; it can be unlocked by sending *sharedMem back to the chan. Multiple objects (like worker, workerClient, workerServer) may have references to the chan and may hold the lock across several operations. This is intended to fix a segfault that occurred when workerClient.fuzz accessed shared memory after it was already closed and unmapped by the worker's goroutine. workerClient.fuzz is executed in a separate goroutine so the worker can still receive messages from the coordinator (like being told to stop and clean up). Change-Id: I4eb9079ba9e5bfcfacfecd0fc8ad9bed17b33bba Reviewed-on: https://go-review.googlesource.com/c/go/+/285054 Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman Trust: Jay Conrod --- src/internal/fuzz/fuzz.go | 4 ++- src/internal/fuzz/sys_posix.go | 9 ++++-- src/internal/fuzz/sys_windows.go | 11 +++++-- src/internal/fuzz/worker.go | 52 ++++++++++++++++++++++++-------- 4 files changed, 57 insertions(+), 19 deletions(-) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index e05b5566ae..f17bce35a2 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -75,13 +75,15 @@ func CoordinateFuzzing(ctx context.Context, parallel int, seed [][]byte, corpusD if err != nil { return nil, err } + memMu := make(chan *sharedMem, 1) + memMu <- mem return &worker{ dir: dir, binPath: binPath, args: args, env: env, coordinator: c, - mem: mem, + memMu: memMu, }, nil } diff --git a/src/internal/fuzz/sys_posix.go b/src/internal/fuzz/sys_posix.go index ecffa72755..d29ff40e8d 100644 --- a/src/internal/fuzz/sys_posix.go +++ b/src/internal/fuzz/sys_posix.go @@ -50,7 +50,10 @@ func (m *sharedMem) Close() error { // setWorkerComm configures communciation channels on the cmd that will // run a worker process. func setWorkerComm(cmd *exec.Cmd, comm workerComm) { - cmd.ExtraFiles = []*os.File{comm.fuzzIn, comm.fuzzOut, comm.mem.f} + mem := <-comm.memMu + memFile := mem.f + comm.memMu <- mem + cmd.ExtraFiles = []*os.File{comm.fuzzIn, comm.fuzzOut, memFile} } // getWorkerComm returns communication channels in the worker process. @@ -71,7 +74,9 @@ func getWorkerComm() (comm workerComm, err error) { if err != nil { return workerComm{}, err } - return workerComm{fuzzIn: fuzzIn, fuzzOut: fuzzOut, mem: mem}, nil + memMu := make(chan *sharedMem, 1) + memMu <- mem + return workerComm{fuzzIn: fuzzIn, fuzzOut: fuzzOut, memMu: memMu}, nil } // isInterruptError returns whether an error was returned by a process that diff --git a/src/internal/fuzz/sys_windows.go b/src/internal/fuzz/sys_windows.go index 678ab0f0a3..6d015c0195 100644 --- a/src/internal/fuzz/sys_windows.go +++ b/src/internal/fuzz/sys_windows.go @@ -85,10 +85,13 @@ func (m *sharedMem) Close() error { // setWorkerComm configures communciation channels on the cmd that will // run a worker process. func setWorkerComm(cmd *exec.Cmd, comm workerComm) { + mem := <-comm.memMu + memFD := mem.f.Fd() + comm.memMu <- mem syscall.SetHandleInformation(syscall.Handle(comm.fuzzIn.Fd()), syscall.HANDLE_FLAG_INHERIT, 1) syscall.SetHandleInformation(syscall.Handle(comm.fuzzOut.Fd()), syscall.HANDLE_FLAG_INHERIT, 1) - syscall.SetHandleInformation(syscall.Handle(comm.mem.f.Fd()), syscall.HANDLE_FLAG_INHERIT, 1) - cmd.Env = append(cmd.Env, fmt.Sprintf("GO_TEST_FUZZ_WORKER_HANDLES=%x,%x,%x", comm.fuzzIn.Fd(), comm.fuzzOut.Fd(), comm.mem.f.Fd())) + syscall.SetHandleInformation(syscall.Handle(memFD), syscall.HANDLE_FLAG_INHERIT, 1) + cmd.Env = append(cmd.Env, fmt.Sprintf("GO_TEST_FUZZ_WORKER_HANDLES=%x,%x,%x", comm.fuzzIn.Fd(), comm.fuzzOut.Fd(), memFD)) } // getWorkerComm returns communication channels in the worker process. @@ -128,8 +131,10 @@ func getWorkerComm() (comm workerComm, err error) { if err != nil { return workerComm{}, err } + memMu := make(chan *sharedMem, 1) + memMu <- mem - return workerComm{fuzzIn: fuzzIn, fuzzOut: fuzzOut, mem: mem}, nil + return workerComm{fuzzIn: fuzzIn, fuzzOut: fuzzOut, memMu: memMu}, nil } func isInterruptError(err error) bool { diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index a10561a244..6d8dd188e1 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -40,7 +40,7 @@ type worker struct { coordinator *coordinator - mem *sharedMem // shared memory with worker; persists across processes. + memMu chan *sharedMem // mutex guarding shared memory with worker; persists across processes. cmd *exec.Cmd // current worker process client *workerClient // used to communicate with worker process @@ -50,12 +50,12 @@ type worker struct { // cleanup releases persistent resources associated with the worker. func (w *worker) cleanup() error { - if w.mem == nil { + mem := <-w.memMu + if mem == nil { return nil } - err := w.mem.Close() - w.mem = nil - return err + close(w.memMu) + return mem.Close() } // runFuzzing runs the test binary to perform fuzzing. @@ -99,7 +99,9 @@ func (w *worker) runFuzzing() error { // Unexpected termination. Inform the coordinator about the crash. // TODO(jayconrod,katiehockman): if -keepfuzzing, restart worker. - value := w.mem.valueCopy() + mem := <-w.memMu + value := mem.valueCopy() + w.memMu <- mem message := fmt.Sprintf("fuzzing process terminated unexpectedly: %v", w.waitErr) crasher := crasherEntry{ corpusEntry: corpusEntry{b: value}, @@ -215,7 +217,7 @@ func (w *worker) start() (err error) { return err } defer fuzzOutW.Close() - setWorkerComm(cmd, workerComm{fuzzIn: fuzzInR, fuzzOut: fuzzOutW, mem: w.mem}) + setWorkerComm(cmd, workerComm{fuzzIn: fuzzInR, fuzzOut: fuzzOutW, memMu: w.memMu}) // Start the worker process. if err := cmd.Start(); err != nil { @@ -229,7 +231,7 @@ func (w *worker) start() (err error) { // called later by stop. w.cmd = cmd w.termC = make(chan struct{}) - w.client = newWorkerClient(workerComm{fuzzIn: fuzzInW, fuzzOut: fuzzOutR, mem: w.mem}) + w.client = newWorkerClient(workerComm{fuzzIn: fuzzInW, fuzzOut: fuzzOutR, memMu: w.memMu}) go func() { w.waitErr = w.cmd.Wait() @@ -369,7 +371,7 @@ type fuzzResponse struct { // (coordinator) has exclusive access. type workerComm struct { fuzzIn, fuzzOut *os.File - mem *sharedMem + memMu chan *sharedMem // mutex guarding shared memory } // workerServer is a minimalist RPC server, run by fuzz worker processes. @@ -447,6 +449,8 @@ func (ws *workerServer) serve(ctx context.Context) error { func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) fuzzResponse { ctx, cancel := context.WithTimeout(ctx, args.Duration) defer cancel() + mem := <-ws.memMu + defer func() { ws.memMu <- mem }() for { select { @@ -455,9 +459,9 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) fuzzResponse { // real heuristic once we have one. return fuzzResponse{Interesting: true} default: - b := ws.mem.valueRef() + b := mem.valueRef() ws.m.mutate(&b) - ws.mem.setValueLen(len(b)) + mem.setValueLen(len(b)) if err := ws.fuzzFn(b); err != nil { return fuzzResponse{Err: err.Error()} } @@ -509,17 +513,39 @@ func (wc *workerClient) Close() error { return wc.fuzzOut.Close() } +// errSharedMemClosed is returned by workerClient methods that cannot access +// shared memory because it was closed and unmapped by another goroutine. That +// can happen when worker.cleanup is called in the worker goroutine while a +// workerClient.fuzz call runs concurrently. +// +// This error should not be reported. It indicates the operation was +// interrupted. +var errSharedMemClosed = errors.New("internal error: shared memory was closed and unmapped") + // fuzz tells the worker to call the fuzz method. See workerServer.fuzz. func (wc *workerClient) fuzz(valueIn []byte, args fuzzArgs) (valueOut []byte, resp fuzzResponse, err error) { wc.mu.Lock() defer wc.mu.Unlock() - wc.mem.setValue(valueIn) + mem, ok := <-wc.memMu + if !ok { + return nil, fuzzResponse{}, errSharedMemClosed + } + mem.setValue(valueIn) + wc.memMu <- mem + c := call{Fuzz: &args} if err := wc.enc.Encode(c); err != nil { return nil, fuzzResponse{}, err } err = wc.dec.Decode(&resp) - valueOut = wc.mem.valueCopy() + + mem, ok = <-wc.memMu + if !ok { + return nil, fuzzResponse{}, errSharedMemClosed + } + valueOut = mem.valueCopy() + wc.memMu <- mem + return valueOut, resp, err } -- GitLab From 5ef7357b50015e91b096a4f14f554db78ba18b5f Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Mon, 1 Feb 2021 18:00:37 -0500 Subject: [PATCH 0030/2500] [dev.fuzz] internal/fuzz: refactor CorpusEntry type CorpusEntry is now a struct type with Name and Data fields. In the future, it may have more fields describing multiple values with different types added with f.Add. CorpusEntry must be the same type in testing and internal/fuzz. However, we don't want to export it from testing, and testing can't import internal/fuzz. We define it to be a type alias of a struct type instead of a defined type. We need to define it to the same thing in both places. We'll get a type error when building cmd/go if there's a difference. Change-Id: I9df6cd7aed67a6aa48b77ffb3a84bd302d2e5d94 Reviewed-on: https://go-review.googlesource.com/c/go/+/288534 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/internal/fuzz/fuzz.go | 61 ++++++++++++++++----------- src/internal/fuzz/worker.go | 8 ++-- src/testing/fuzz.go | 33 ++++++--------- src/testing/internal/testdeps/deps.go | 4 +- src/testing/testing.go | 10 ++--- 5 files changed, 59 insertions(+), 57 deletions(-) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index f17bce35a2..451731ba93 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -39,7 +39,7 @@ import ( // // If a crash occurs, the function will return an error containing information // about the crash, which can be reported to the user. -func CoordinateFuzzing(ctx context.Context, parallel int, seed [][]byte, corpusDir, cacheDir string) (err error) { +func CoordinateFuzzing(ctx context.Context, parallel int, seed []CorpusEntry, corpusDir, cacheDir string) (err error) { if err := ctx.Err(); err != nil { return err } @@ -53,7 +53,7 @@ func CoordinateFuzzing(ctx context.Context, parallel int, seed [][]byte, corpusD return err } if len(corpus.entries) == 0 { - corpus.entries = []corpusEntry{{b: []byte{}}} + corpus.entries = []CorpusEntry{{Data: []byte{}}} } // TODO(jayconrod): do we want to support fuzzing different binaries? @@ -64,8 +64,8 @@ func CoordinateFuzzing(ctx context.Context, parallel int, seed [][]byte, corpusD c := &coordinator{ doneC: make(chan struct{}), - inputC: make(chan corpusEntry), - interestingC: make(chan corpusEntry), + inputC: make(chan CorpusEntry), + interestingC: make(chan CorpusEntry), crasherC: make(chan crasherEntry), errC: make(chan error), } @@ -141,7 +141,7 @@ func CoordinateFuzzing(ctx context.Context, parallel int, seed [][]byte, corpusD case crasher := <-c.crasherC: // A worker found a crasher. Write it to testdata and return it. - fileName, err := writeToCorpus(crasher.b, corpusDir) + fileName, err := writeToCorpus(crasher.Data, corpusDir) if err == nil { err = fmt.Errorf(" Crash written to %s\n%s", fileName, crasher.errMsg) } @@ -160,7 +160,7 @@ func CoordinateFuzzing(ctx context.Context, parallel int, seed [][]byte, corpusD // in the corpus. corpus.entries = append(corpus.entries, entry) if cacheDir != "" { - if _, err := writeToCorpus(entry.b, cacheDir); err != nil { + if _, err := writeToCorpus(entry.Data, cacheDir); err != nil { return err } } @@ -182,17 +182,32 @@ func CoordinateFuzzing(ctx context.Context, parallel int, seed [][]byte, corpusD } type corpus struct { - entries []corpusEntry + entries []CorpusEntry } -// TODO(jayconrod,katiehockman): decide whether and how to unify this type -// with the equivalent in testing. -type corpusEntry struct { - b []byte +// CorpusEntry represents an individual input for fuzzing. +// +// We must use an equivalent type in the testing and testing/internal/testdeps +// packages, but testing can't import this package directly, and we don't want +// to export this type from testing. Instead, we use the same struct type and +// use a type alias (not a defined type) for convenience. +type CorpusEntry = struct { + // Name is the name of the corpus file, if the entry was loaded from the + // seed corpus. It can be used with -run. For entries added with f.Add and + // entries generated by the mutator, Name is empty. + Name string + + // Data is the raw data loaded from a corpus file. + Data []byte + + // TODO(jayconrod,katiehockman): support multiple values of different types + // added with f.Add with a Values []interface{} field. We'll need marhsalling + // and unmarshalling functions, and we'll need to figure out what to do + // in the mutator. } type crasherEntry struct { - corpusEntry + CorpusEntry errMsg string } @@ -206,12 +221,12 @@ type coordinator struct { // inputC is sent values to fuzz by the coordinator. Any worker may receive // values from this channel. - inputC chan corpusEntry + inputC chan CorpusEntry // interestingC is sent interesting values by the worker, which is received // by the coordinator. Values are usually interesting because they // increase coverage. - interestingC chan corpusEntry + interestingC chan CorpusEntry // crasherC is sent values that crashed the code being fuzzed. These values // should be saved in the corpus, and we may want to stop fuzzing after @@ -231,33 +246,29 @@ type coordinator struct { // the same package at a different version or in a different module. // TODO(jayconrod,katiehockman): need a mechanism that can remove values that // aren't useful anymore, for example, because they have the wrong type. -func readCorpusAndCache(seed [][]byte, corpusDir, cacheDir string) (corpus, error) { +func readCorpusAndCache(seed []CorpusEntry, corpusDir, cacheDir string) (corpus, error) { var c corpus - for _, b := range seed { - c.entries = append(c.entries, corpusEntry{b: b}) - } + c.entries = append(c.entries, seed...) for _, dir := range []string{corpusDir, cacheDir} { - bs, err := ReadCorpus(dir) + entries, err := ReadCorpus(dir) if err != nil { return corpus{}, err } - for _, b := range bs { - c.entries = append(c.entries, corpusEntry{b: b}) - } + c.entries = append(c.entries, entries...) } return c, nil } // ReadCorpus reads the corpus from the testdata directory in this target's // package. -func ReadCorpus(dir string) ([][]byte, error) { +func ReadCorpus(dir string) ([]CorpusEntry, error) { files, err := ioutil.ReadDir(dir) if os.IsNotExist(err) { return nil, nil // No corpus to read } else if err != nil { return nil, fmt.Errorf("testing: reading seed corpus from testdata: %v", err) } - var corpus [][]byte + var corpus []CorpusEntry for _, file := range files { // TODO(jayconrod,katiehockman): determine when a file is a fuzzing input // based on its name. We should only read files created by writeToCorpus. @@ -271,7 +282,7 @@ func ReadCorpus(dir string) ([][]byte, error) { if err != nil { return nil, fmt.Errorf("testing: failed to read corpus file: %v", err) } - corpus = append(corpus, bytes) + corpus = append(corpus, CorpusEntry{Name: file.Name(), Data: bytes}) } return corpus, nil } diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 6d8dd188e1..8ea95438ca 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -104,7 +104,7 @@ func (w *worker) runFuzzing() error { w.memMu <- mem message := fmt.Sprintf("fuzzing process terminated unexpectedly: %v", w.waitErr) crasher := crasherEntry{ - corpusEntry: corpusEntry{b: value}, + CorpusEntry: CorpusEntry{Data: value}, errMsg: message, } w.coordinator.crasherC <- crasher @@ -119,7 +119,7 @@ func (w *worker) runFuzzing() error { inputC = nil // block new inputs until we finish with this one. go func() { args := fuzzArgs{Duration: workerFuzzDuration} - value, resp, err := w.client.fuzz(input.b, args) + value, resp, err := w.client.fuzz(input.Data, args) if err != nil { // Error communicating with worker. select { @@ -144,7 +144,7 @@ func (w *worker) runFuzzing() error { } else if resp.Err != "" { // The worker found a crasher. Inform the coordinator. crasher := crasherEntry{ - corpusEntry: corpusEntry{b: value}, + CorpusEntry: CorpusEntry{Data: value}, errMsg: resp.Err, } w.coordinator.crasherC <- crasher @@ -152,7 +152,7 @@ func (w *worker) runFuzzing() error { // Inform the coordinator that fuzzing found something // interesting (i.e. new coverage). if resp.Interesting { - w.coordinator.interestingC <- corpusEntry{b: value} + w.coordinator.interestingC <- CorpusEntry{Data: value} } // Continue fuzzing. diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 4351704b58..7ef47872d0 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -48,17 +48,12 @@ type F struct { fuzzFunc func(f *F) // fuzzFunc is the function which makes up the fuzz target } -// corpus corpusEntry -type corpusEntry struct { - b []byte -} - -func bytesToCorpus(bytes [][]byte) []corpusEntry { - c := make([]corpusEntry, len(bytes)) - for i, b := range bytes { - c[i].b = b - } - return c +// corpusEntry is an alias to the same type as internal/fuzz.CorpusEntry. +// We use a type alias because we don't want to export this type, and we can't +// importing internal/fuzz from testing. +type corpusEntry = struct { + Name string + Data []byte } // Add will add the arguments to the seed corpus for the fuzz target. This will @@ -74,7 +69,7 @@ func (f *F) Add(args ...interface{}) { } switch v := args[0].(type) { case []byte: - f.corpus = append(f.corpus, corpusEntry{v}) + f.corpus = append(f.corpus, corpusEntry{Data: v}) // TODO: support other types default: panic("testing: Add only supports []byte currently") @@ -100,7 +95,7 @@ func (f *F) Fuzz(ff interface{}) { if err != nil { f.Fatal(err) } - f.corpus = append(f.corpus, bytesToCorpus(c)...) + f.corpus = append(f.corpus, c...) // TODO(jayconrod,katiehockman): dedupe testdata corpus with entries from f.Add var errStr string @@ -132,13 +127,9 @@ func (f *F) Fuzz(ff interface{}) { // Fuzzing is enabled, and this is the test process started by 'go test'. // Act as the coordinator process, and coordinate workers to perform the // actual fuzzing. - seed := make([][]byte, len(f.corpus)) - for i, e := range f.corpus { - seed[i] = e.b - } corpusTargetDir := filepath.Join(corpusDir, f.name) cacheTargetDir := filepath.Join(*fuzzCacheDir, f.name) - err := f.context.coordinateFuzzing(*fuzzDuration, *parallel, seed, corpusTargetDir, cacheTargetDir) + err := f.context.coordinateFuzzing(*fuzzDuration, *parallel, f.corpus, corpusTargetDir, cacheTargetDir) if err != nil { f.Fail() f.result = FuzzResult{Error: err} @@ -188,7 +179,7 @@ func (f *F) Fuzz(ff interface{}) { }, context: newTestContext(1, nil), } - go run(t, c.b) + go run(t, c.Data) <-t.signal if t.Failed() { f.Fail() @@ -281,9 +272,9 @@ func (r FuzzResult) String() string { type fuzzContext struct { runMatch *matcher fuzzMatch *matcher - coordinateFuzzing func(time.Duration, int, [][]byte, string, string) error + coordinateFuzzing func(time.Duration, int, []corpusEntry, string, string) error runFuzzWorker func(func([]byte) error) error - readCorpus func(string) ([][]byte, error) + readCorpus func(string) ([]corpusEntry, error) } // runFuzzTargets runs the fuzz targets matching the pattern for -run. This will diff --git a/src/testing/internal/testdeps/deps.go b/src/testing/internal/testdeps/deps.go index 2d0d7bac38..3d43170721 100644 --- a/src/testing/internal/testdeps/deps.go +++ b/src/testing/internal/testdeps/deps.go @@ -132,7 +132,7 @@ func (TestDeps) SetPanicOnExit0(v bool) { testlog.SetPanicOnExit0(v) } -func (TestDeps) CoordinateFuzzing(timeout time.Duration, parallel int, seed [][]byte, corpusDir, cacheDir string) error { +func (TestDeps) CoordinateFuzzing(timeout time.Duration, parallel int, seed []fuzz.CorpusEntry, corpusDir, cacheDir string) error { // Fuzzing may be interrupted with a timeout or if the user presses ^C. // In either case, we'll stop worker processes gracefully and save // crashers and interesting values. @@ -178,6 +178,6 @@ func (TestDeps) RunFuzzWorker(fn func([]byte) error) error { return nil } -func (TestDeps) ReadCorpus(dir string) ([][]byte, error) { +func (TestDeps) ReadCorpus(dir string) ([]fuzz.CorpusEntry, error) { return fuzz.ReadCorpus(dir) } diff --git a/src/testing/testing.go b/src/testing/testing.go index 39316122a6..e2abec2224 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1361,11 +1361,11 @@ func (f matchStringOnly) ImportPath() string { return " func (f matchStringOnly) StartTestLog(io.Writer) {} func (f matchStringOnly) StopTestLog() error { return errMain } func (f matchStringOnly) SetPanicOnExit0(bool) {} -func (f matchStringOnly) CoordinateFuzzing(time.Duration, int, [][]byte, string, string) error { +func (f matchStringOnly) CoordinateFuzzing(time.Duration, int, []corpusEntry, string, string) error { return errMain } -func (f matchStringOnly) RunFuzzWorker(func([]byte) error) error { return errMain } -func (f matchStringOnly) ReadCorpus(string) ([][]byte, error) { return nil, errMain } +func (f matchStringOnly) RunFuzzWorker(func([]byte) error) error { return errMain } +func (f matchStringOnly) ReadCorpus(string) ([]corpusEntry, error) { return nil, errMain } // Main is an internal function, part of the implementation of the "go test" command. // It was exported because it is cross-package and predates "internal" packages. @@ -1408,9 +1408,9 @@ type testDeps interface { StartTestLog(io.Writer) StopTestLog() error WriteProfileTo(string, io.Writer, int) error - CoordinateFuzzing(time.Duration, int, [][]byte, string, string) error + CoordinateFuzzing(time.Duration, int, []corpusEntry, string, string) error RunFuzzWorker(func([]byte) error) error - ReadCorpus(string) ([][]byte, error) + ReadCorpus(string) ([]corpusEntry, error) } // MainStart is meant for use by tests generated by 'go test'. -- GitLab From b60f79385018b41ccd1d0fb717b0bff99d2d3139 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 9 Feb 2021 16:09:30 -0500 Subject: [PATCH 0031/2500] [dev.fuzz] cmd/go: skip fuzz tests on unsupported platforms For now, fuzzing is only supported on Darwin, Linux, and Windows. We haven't testing shared memory communication between coordinator and worker processes on other platforms. Currently, fuzz.CoordinateFuzzing and RunFuzzWorker both panic with "unimplemented" messages. Unfortunately, these may be masked by runtime.Goexit calls that override panics, so some builders fail with test executed panic(nil) or runtime.Goexit Change-Id: Ic7bd692461958626dd5c5bb31198aec86387bbd6 Reviewed-on: https://go-review.googlesource.com/c/go/+/290810 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/cmd/go/testdata/script/test_fuzz.txt | 3 +++ src/cmd/go/testdata/script/test_fuzz_cache.txt | 3 +++ src/cmd/go/testdata/script/test_fuzz_chatty.txt | 3 +++ src/cmd/go/testdata/script/test_fuzz_fuzztime.txt | 3 +++ src/cmd/go/testdata/script/test_fuzz_match.txt | 3 +++ src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt | 3 +++ src/cmd/go/testdata/script/test_fuzz_mutator.txt | 3 +++ 7 files changed, 21 insertions(+) diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt index 4a761d1fd9..eb65e0db2a 100644 --- a/src/cmd/go/testdata/script/test_fuzz.txt +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -1,3 +1,6 @@ +# TODO(jayconrod): support shared memory on more platforms. +[!darwin] [!linux] [!windows] skip + # Test that calling f.Error in a fuzz target causes a non-zero exit status. ! go test -fuzz=Fuzz -fuzztime=5s -parallel=1 error_fuzz_test.go ! stdout ^ok diff --git a/src/cmd/go/testdata/script/test_fuzz_cache.txt b/src/cmd/go/testdata/script/test_fuzz_cache.txt index ad8334ae7d..b4f59271ea 100644 --- a/src/cmd/go/testdata/script/test_fuzz_cache.txt +++ b/src/cmd/go/testdata/script/test_fuzz_cache.txt @@ -1,3 +1,6 @@ +# TODO(jayconrod): support shared memory on more platforms. +[!darwin] [!linux] [!windows] skip + [short] skip env GOCACHE=$WORK/cache diff --git a/src/cmd/go/testdata/script/test_fuzz_chatty.txt b/src/cmd/go/testdata/script/test_fuzz_chatty.txt index a881d54bdc..b70bb9e49f 100644 --- a/src/cmd/go/testdata/script/test_fuzz_chatty.txt +++ b/src/cmd/go/testdata/script/test_fuzz_chatty.txt @@ -1,3 +1,6 @@ +# TODO(jayconrod): support shared memory on more platforms. +[!darwin] [!linux] [!windows] skip + [short] skip # Run chatty fuzz targets with an error. diff --git a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt index 0fc2f74e31..1da095f06c 100644 --- a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt +++ b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt @@ -1,3 +1,6 @@ +# TODO(jayconrod): support shared memory on more platforms. +[!darwin] [!linux] [!windows] skip + [short] skip # There are no seed values, so 'go test' should finish quickly. diff --git a/src/cmd/go/testdata/script/test_fuzz_match.txt b/src/cmd/go/testdata/script/test_fuzz_match.txt index 6161438c2a..44ebf0bf66 100644 --- a/src/cmd/go/testdata/script/test_fuzz_match.txt +++ b/src/cmd/go/testdata/script/test_fuzz_match.txt @@ -1,3 +1,6 @@ +# TODO(jayconrod): support shared memory on more platforms. +[!darwin] [!linux] [!windows] skip + # Matches only fuzz targets to test. go test standalone_fuzz_test.go ! stdout '^ok.*\[no tests to run\]' diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt index 2d5e1e5fd7..b45e7d77c7 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt @@ -1,3 +1,6 @@ +# TODO(jayconrod): support shared memory on more platforms. +[!darwin] [!linux] [!windows] skip + # Tests that a crash caused by a mutator-discovered input writes the bad input # to testdata, and fails+reports correctly. This tests the end-to-end behavior # of the mutator finding a crash while fuzzing, adding it as a regression test diff --git a/src/cmd/go/testdata/script/test_fuzz_mutator.txt b/src/cmd/go/testdata/script/test_fuzz_mutator.txt index bc7edf3cc5..a84fc35c5c 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutator.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutator.txt @@ -1,3 +1,6 @@ +# TODO(jayconrod): support shared memory on more platforms. +[!darwin] [!linux] [!windows] skip + # Test basic fuzzing mutator behavior. # # fuzz_test.go has two fuzz targets (FuzzA, FuzzB) which both add a seed value. -- GitLab From 6f401df36680526d7e6eabb70ce8c4dd986273ef Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 9 Feb 2021 10:15:02 -0500 Subject: [PATCH 0032/2500] [dev.fuzz] cmd/go: call F.Fuzz from all fuzz script tests Fuzz targets must call F.Skip, F.Fail, or F.Fuzz. F.Fuzz must not be called more than once. If a fuzz target panics, calls runtime.Goexit, or returns normally without calling one of those functions, the target should panic, and 'go test' should exit with a non-zero status. For now, this isn't checked. It will be fixed in a follow-up CL. Change-Id: Ibb905954462b64af15332c285124d78a998f7762 Reviewed-on: https://go-review.googlesource.com/c/go/+/290689 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/cmd/go/testdata/script/test_fuzz.txt | 32 ++++++++++++++++--- .../go/testdata/script/test_fuzz_chatty.txt | 1 + .../go/testdata/script/test_fuzz_match.txt | 5 ++- 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt index eb65e0db2a..ccdae830a5 100644 --- a/src/cmd/go/testdata/script/test_fuzz.txt +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -1,6 +1,20 @@ # TODO(jayconrod): support shared memory on more platforms. [!darwin] [!linux] [!windows] skip +# Test that running a fuzz target that returns without failing or calling +# f.Fuzz fails and causes a non-zero exit status. +# BUG(jayconrod): for now, it passes. +go test noop_fuzz_test.go +stdout ok +! stdout FAIL + +# Test that fuzzing a fuzz target that returns without failing or calling +# f.Fuzz fails and causes a non-zero exit status. +# BUG(jayconrod): for now, it passes. +go test -fuzz=Fuzz -fuzztime=5s -parallel=1 noop_fuzz_test.go +stdout ok +! stdout FAIL + # Test that calling f.Error in a fuzz target causes a non-zero exit status. ! go test -fuzz=Fuzz -fuzztime=5s -parallel=1 error_fuzz_test.go ! stdout ^ok @@ -13,6 +27,11 @@ stdout FAIL # Test that successful test exits cleanly. go test success_fuzz_test.go +stdout ^ok +! stdout FAIL + +# Test that successful fuzzing exits cleanly. +go test -fuzz=Fuzz -fuzztime=5s -parallel=1 success_fuzz_test.go stdout ok ! stdout FAIL @@ -21,11 +40,6 @@ stdout ok ! stdout ^ok stdout FAIL -# Test that successful fuzzing exits cleanly. -go test -fuzz=Fuzz -fuzztime=5s -parallel=1 success_fuzz_test.go -stdout ok -! stdout FAIL - # Test error with seed corpus in f.Fuzz ! go test -run FuzzError fuzz_add_test.go ! stdout ^ok @@ -122,6 +136,13 @@ stdout ok ! stdout FAIL ! stdout 'fatal here' +-- noop_fuzz_test.go -- +package noop_fuzz + +import "testing" + +func Fuzz(f *testing.F) {} + -- error_fuzz_test.go -- package error_fuzz @@ -155,6 +176,7 @@ package success_fuzz import "testing" func Fuzz(f *testing.F) { + f.Fuzz(func (*testing.T, []byte) {}) } -- skipped_fuzz_test.go -- diff --git a/src/cmd/go/testdata/script/test_fuzz_chatty.txt b/src/cmd/go/testdata/script/test_fuzz_chatty.txt index b70bb9e49f..aaf385f293 100644 --- a/src/cmd/go/testdata/script/test_fuzz_chatty.txt +++ b/src/cmd/go/testdata/script/test_fuzz_chatty.txt @@ -77,4 +77,5 @@ import "testing" func Fuzz(f *testing.F) { f.Log("all good here") + f.Fuzz(func(*testing.T, []byte) {}) } diff --git a/src/cmd/go/testdata/script/test_fuzz_match.txt b/src/cmd/go/testdata/script/test_fuzz_match.txt index 44ebf0bf66..5ead41411f 100644 --- a/src/cmd/go/testdata/script/test_fuzz_match.txt +++ b/src/cmd/go/testdata/script/test_fuzz_match.txt @@ -43,6 +43,7 @@ package standalone_fuzz import "testing" func Fuzz(f *testing.F) { + f.Fuzz(func (*testing.T, []byte) {}) } -- multiple_fuzz_test.go -- @@ -51,7 +52,9 @@ package multiple_fuzz import "testing" func FuzzA(f *testing.F) { + f.Fuzz(func (*testing.T, []byte) {}) } func FuzzB(f *testing.F) { -} \ No newline at end of file + f.Fuzz(func (*testing.T, []byte) {}) +} -- GitLab From 9b967d12a9f1a13c79104b834a17c4356585cc7a Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 9 Feb 2021 10:23:40 -0500 Subject: [PATCH 0033/2500] [dev.fuzz] internal/fuzz: worker exiting 0 should not be a crasher If a worker process exits with status 0, treat it as a communication error. Previously, we treated this as a crasher, but it seems more likely to be caused by a bug in the fuzz function rather than a bug in the code being tested. Change-Id: I0c4efeaef85537f8a0e9c6def6aac41d75b2b307 Reviewed-on: https://go-review.googlesource.com/c/go/+/290690 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/internal/fuzz/worker.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 8ea95438ca..9a92813f8c 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -96,6 +96,11 @@ func (w *worker) runFuzzing() error { w.stop() return nil } + if w.waitErr == nil { + // Worker exited 0. + w.stop() + return fmt.Errorf("worker exited unexpectedly with status 0") + } // Unexpected termination. Inform the coordinator about the crash. // TODO(jayconrod,katiehockman): if -keepfuzzing, restart worker. @@ -108,11 +113,7 @@ func (w *worker) runFuzzing() error { errMsg: message, } w.coordinator.crasherC <- crasher - err := w.stop() - if err == nil { - err = fmt.Errorf("worker exited unexpectedly") - } - return err + return w.stop() case input := <-inputC: // Received input from coordinator. -- GitLab From b9c88eaab915874bc004f579940b10fe48bba36b Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 9 Feb 2021 10:30:02 -0500 Subject: [PATCH 0034/2500] [dev.fuzz] testing/internal/testdeps: use signal.NotifyContext In RunFuzzWorker and CoordinateFuzzing, use signal.NotifyContext (new in 1.16) to cancel the context in response to SIGINT. This is shorter and more correct than what we were doing before. Change-Id: Id7e9a58e9dd992dffb86e4e0f2e3efd117d03c47 Reviewed-on: https://go-review.googlesource.com/c/go/+/290691 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/testing/internal/testdeps/deps.go | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/src/testing/internal/testdeps/deps.go b/src/testing/internal/testdeps/deps.go index 3d43170721..1333944d5e 100644 --- a/src/testing/internal/testdeps/deps.go +++ b/src/testing/internal/testdeps/deps.go @@ -140,14 +140,9 @@ func (TestDeps) CoordinateFuzzing(timeout time.Duration, parallel int, seed []fu if timeout > 0 { ctx, cancel = context.WithTimeout(ctx, timeout) } - interruptC := make(chan os.Signal, 1) - signal.Notify(interruptC, os.Interrupt) - go func() { - <-interruptC - cancel() - }() - defer func() { interruptC <- os.Interrupt }() - + ctx, stop := signal.NotifyContext(ctx, os.Interrupt) + defer stop() + defer cancel() err := fuzz.CoordinateFuzzing(ctx, parallel, seed, corpusDir, cacheDir) if err == ctx.Err() { return nil @@ -163,14 +158,9 @@ func (TestDeps) RunFuzzWorker(fn func([]byte) error) error { // If only the coordinator process is interrupted, it tells each worker // process to stop by closing its "fuzz_in" pipe. ctx, cancel := context.WithCancel(context.Background()) - interruptC := make(chan os.Signal, 1) - signal.Notify(interruptC, os.Interrupt) - go func() { - <-interruptC - cancel() - }() - defer func() { interruptC <- os.Interrupt }() - + ctx, stop := signal.NotifyContext(ctx, os.Interrupt) + defer stop() + defer cancel() err := fuzz.RunFuzzWorker(ctx, fn) if err == ctx.Err() { return nil -- GitLab From 1b5cf71ccf0dc95f121830cfdad8280c4f6c1f28 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 9 Feb 2021 10:36:27 -0500 Subject: [PATCH 0035/2500] [dev.fuzz] internal/fuzz: make RunFuzzWorker accept CorpusEntry RunFuzzWorker now accepts a fuzz.CorpusEntry instead of []byte. This may help us pass structured data in the future. Change-Id: Idf7754cb890b6a835d887032fd23ade4d0713bcf Reviewed-on: https://go-review.googlesource.com/c/go/+/290692 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/internal/fuzz/worker.go | 6 +++--- src/testing/fuzz.go | 6 +++--- src/testing/internal/testdeps/deps.go | 6 +++--- src/testing/testing.go | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 9a92813f8c..f9284db729 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -329,7 +329,7 @@ func (w *worker) stop() error { // // RunFuzzWorker returns an error if it could not communicate with the // coordinator process. -func RunFuzzWorker(ctx context.Context, fn func([]byte) error) error { +func RunFuzzWorker(ctx context.Context, fn func(CorpusEntry) error) error { comm, err := getWorkerComm() if err != nil { return err @@ -386,7 +386,7 @@ type workerServer struct { // fuzzFn runs the worker's fuzz function on the given input and returns // an error if it finds a crasher (the process may also exit or crash). - fuzzFn func([]byte) error + fuzzFn func(CorpusEntry) error } // serve reads serialized RPC messages on fuzzIn. When serve receives a message, @@ -463,7 +463,7 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) fuzzResponse { b := mem.valueRef() ws.m.mutate(&b) mem.setValueLen(len(b)) - if err := ws.fuzzFn(b); err != nil { + if err := ws.fuzzFn(CorpusEntry{Data: b}); err != nil { return fuzzResponse{Err: err.Error()} } // TODO(jayconrod,katiehockman): return early if we find an diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 7ef47872d0..196b4cf7ab 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -142,7 +142,7 @@ func (f *F) Fuzz(ff interface{}) { case f.context.runFuzzWorker != nil: // Fuzzing is enabled, and this is a worker process. Follow instructions // from the coordinator. - err := f.context.runFuzzWorker(func(input []byte) error { + err := f.context.runFuzzWorker(func(e corpusEntry) error { t := &T{ common: common{ signal: make(chan bool), @@ -151,7 +151,7 @@ func (f *F) Fuzz(ff interface{}) { }, context: newTestContext(1, nil), } - go run(t, input) + go run(t, e.Data) <-t.signal if t.Failed() { return errors.New(string(t.output)) @@ -273,7 +273,7 @@ type fuzzContext struct { runMatch *matcher fuzzMatch *matcher coordinateFuzzing func(time.Duration, int, []corpusEntry, string, string) error - runFuzzWorker func(func([]byte) error) error + runFuzzWorker func(func(corpusEntry) error) error readCorpus func(string) ([]corpusEntry, error) } diff --git a/src/testing/internal/testdeps/deps.go b/src/testing/internal/testdeps/deps.go index 1333944d5e..3160cae7a4 100644 --- a/src/testing/internal/testdeps/deps.go +++ b/src/testing/internal/testdeps/deps.go @@ -132,7 +132,7 @@ func (TestDeps) SetPanicOnExit0(v bool) { testlog.SetPanicOnExit0(v) } -func (TestDeps) CoordinateFuzzing(timeout time.Duration, parallel int, seed []fuzz.CorpusEntry, corpusDir, cacheDir string) error { +func (TestDeps) CoordinateFuzzing(timeout time.Duration, parallel int, seed []fuzz.CorpusEntry, corpusDir, cacheDir string) (err error) { // Fuzzing may be interrupted with a timeout or if the user presses ^C. // In either case, we'll stop worker processes gracefully and save // crashers and interesting values. @@ -143,14 +143,14 @@ func (TestDeps) CoordinateFuzzing(timeout time.Duration, parallel int, seed []fu ctx, stop := signal.NotifyContext(ctx, os.Interrupt) defer stop() defer cancel() - err := fuzz.CoordinateFuzzing(ctx, parallel, seed, corpusDir, cacheDir) + err = fuzz.CoordinateFuzzing(ctx, parallel, seed, corpusDir, cacheDir) if err == ctx.Err() { return nil } return err } -func (TestDeps) RunFuzzWorker(fn func([]byte) error) error { +func (TestDeps) RunFuzzWorker(fn func(fuzz.CorpusEntry) error) error { // Worker processes may or may not receive a signal when the user presses ^C // On POSIX operating systems, a signal sent to a process group is delivered // to all processes in that group. This is not the case on Windows. diff --git a/src/testing/testing.go b/src/testing/testing.go index e2abec2224..72529956c3 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1364,8 +1364,8 @@ func (f matchStringOnly) SetPanicOnExit0(bool) {} func (f matchStringOnly) CoordinateFuzzing(time.Duration, int, []corpusEntry, string, string) error { return errMain } -func (f matchStringOnly) RunFuzzWorker(func([]byte) error) error { return errMain } -func (f matchStringOnly) ReadCorpus(string) ([]corpusEntry, error) { return nil, errMain } +func (f matchStringOnly) RunFuzzWorker(func(corpusEntry) error) error { return errMain } +func (f matchStringOnly) ReadCorpus(string) ([]corpusEntry, error) { return nil, errMain } // Main is an internal function, part of the implementation of the "go test" command. // It was exported because it is cross-package and predates "internal" packages. @@ -1409,7 +1409,7 @@ type testDeps interface { StopTestLog() error WriteProfileTo(string, io.Writer, int) error CoordinateFuzzing(time.Duration, int, []corpusEntry, string, string) error - RunFuzzWorker(func([]byte) error) error + RunFuzzWorker(func(corpusEntry) error) error ReadCorpus(string) ([]corpusEntry, error) } -- GitLab From 25bd2e962e33d15922111464311c4a94ec910773 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 9 Feb 2021 17:32:08 -0500 Subject: [PATCH 0036/2500] [dev.fuzz] testing: move inFuzzFn checks from common to F inFuzzFn is set when the fuzz function is called. While it's set, F methods that have side effects like Skip and Fail may not be called. Previously, (CL 259657) inFuzzFn was in common, and we checked it in the common implementation of those methods. This causes problems in CL 290693 for recursive methods like common.Fail. If T.Fail is called by the fuzz function, it calls common.Fail on the parent F's common. That should not panic. Change-Id: I841b12f77d9c77f5021370d03313e71b4ef50102 Reviewed-on: https://go-review.googlesource.com/c/go/+/290811 Trust: Jay Conrod Trust: Katie Hockman Reviewed-by: Katie Hockman --- src/testing/fuzz.go | 121 +++++++++++++++++++++++++++++++++++++++++ src/testing/testing.go | 37 ------------- 2 files changed, 121 insertions(+), 37 deletions(-) diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 196b4cf7ab..f64629bcd4 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -43,11 +43,14 @@ type InternalFuzzTarget struct { type F struct { common context *fuzzContext + inFuzzFn bool // set to true when fuzz function is running corpus []corpusEntry // corpus is the in-memory corpus result FuzzResult // result is the result of running the fuzz target fuzzFunc func(f *F) // fuzzFunc is the function which makes up the fuzz target } +var _ TB = (*F)(nil) + // corpusEntry is an alias to the same type as internal/fuzz.CorpusEntry. // We use a type alias because we don't want to export this type, and we can't // importing internal/fuzz from testing. @@ -56,6 +59,124 @@ type corpusEntry = struct { Data []byte } +// Cleanup registers a function to be called when the test and all its +// subtests complete. Cleanup functions will be called in last added, +// first called order. +func (f *F) Cleanup(fn func()) { + if f.inFuzzFn { + panic("testing: f.Cleanup was called inside the f.Fuzz function") + } + f.common.Cleanup(fn) +} + +// Error is equivalent to Log followed by Fail. +func (f *F) Error(args ...interface{}) { + if f.inFuzzFn { + panic("testing: f.Error was called inside the f.Fuzz function") + } + f.common.Error(args...) +} + +// Errorf is equivalent to Logf followed by Fail. +func (f *F) Errorf(format string, args ...interface{}) { + if f.inFuzzFn { + panic("testing: f.Errorf was called inside the f.Fuzz function") + } + f.common.Errorf(format, args...) +} + +// Fail marks the function as having failed but continues execution. +func (f *F) Fail() { + if f.inFuzzFn { + panic("testing: f.Fail was called inside the f.Fuzz function") + } + f.common.Fail() +} + +// FailNow marks the function as having failed and stops its execution +// by calling runtime.Goexit (which then runs all deferred calls in the +// current goroutine). +// Execution will continue at the next test or benchmark. +// FailNow must be called from the goroutine running the +// test or benchmark function, not from other goroutines +// created during the test. Calling FailNow does not stop +// those other goroutines. +func (f *F) FailNow() { + if f.inFuzzFn { + panic("testing: f.FailNow was called inside the f.Fuzz function") + } + f.common.FailNow() +} + +// Fatal is equivalent to Log followed by FailNow. +func (f *F) Fatal(args ...interface{}) { + if f.inFuzzFn { + panic("testing: f.Fatal was called inside the f.Fuzz function") + } + f.common.Fatal(args...) +} + +// Fatalf is equivalent to Logf followed by FailNow. +func (f *F) Fatalf(format string, args ...interface{}) { + if f.inFuzzFn { + panic("testing: f.Fatalf was called inside the f.Fuzz function") + } + f.common.Fatalf(format, args...) +} + +// Helper marks the calling function as a test helper function. +// When printing file and line information, that function will be skipped. +// Helper may be called simultaneously from multiple goroutines. +func (f *F) Helper() { + if f.inFuzzFn { + panic("testing: f.Helper was called inside the f.Fuzz function") + } + f.common.Helper() +} + +// Skip is equivalent to Log followed by SkipNow. +func (f *F) Skip(args ...interface{}) { + if f.inFuzzFn { + panic("testing: f.Skip was called inside the f.Fuzz function") + } + f.common.Skip(args...) +} + +// SkipNow marks the test as having been skipped and stops its execution +// by calling runtime.Goexit. +// If a test fails (see Error, Errorf, Fail) and is then skipped, +// it is still considered to have failed. +// Execution will continue at the next test or benchmark. See also FailNow. +// SkipNow must be called from the goroutine running the test, not from +// other goroutines created during the test. Calling SkipNow does not stop +// those other goroutines. +func (f *F) SkipNow() { + if f.inFuzzFn { + panic("testing: f.SkipNow was called inside the f.Fuzz function") + } + f.common.SkipNow() +} + +// Skipf is equivalent to Logf followed by SkipNow. +func (f *F) Skipf(format string, args ...interface{}) { + if f.inFuzzFn { + panic("testing: f.Skipf was called inside the f.Fuzz function") + } + f.common.Skipf(format, args...) +} + +// TempDir returns a temporary directory for the test to use. +// The directory is automatically removed by Cleanup when the test and +// all its subtests complete. +// Each subsequent call to t.TempDir returns a unique directory; +// if the directory creation fails, TempDir terminates the test by calling Fatal. +func (f *F) TempDir() string { + if f.inFuzzFn { + panic("testing: f.TempDir was called inside the f.Fuzz function") + } + return f.common.TempDir() +} + // Add will add the arguments to the seed corpus for the fuzz target. This will // be a no-op if called after or within the Fuzz function. The args must match // those in the Fuzz function. diff --git a/src/testing/testing.go b/src/testing/testing.go index 72529956c3..2e38898c98 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -399,7 +399,6 @@ type common struct { chatty *chattyPrinter // A copy of chattyPrinter, if the chatty flag is set. bench bool // Whether the current test is a benchmark. - inFuzzFn bool // Whether the test is executing a Fuzz function finished bool // Test function has completed. hasSub int32 // Written atomically. raceErrors int // Number of races detected during test. @@ -690,9 +689,6 @@ func (c *common) setRan() { // Fail marks the function as having failed but continues execution. func (c *common) Fail() { - if c.inFuzzFn { - panic("testing: f.Fail was called inside the f.Fuzz function") - } if c.parent != nil { c.parent.Fail() } @@ -722,9 +718,6 @@ func (c *common) Failed() bool { // created during the test. Calling FailNow does not stop // those other goroutines. func (c *common) FailNow() { - if c.inFuzzFn { - panic("testing: f.FailNow was called inside the f.Fuzz function") - } c.Fail() // Calling runtime.Goexit will exit the goroutine, which @@ -802,54 +795,36 @@ func (c *common) Logf(format string, args ...interface{}) { c.log(fmt.Sprintf(fo // Error is equivalent to Log followed by Fail. func (c *common) Error(args ...interface{}) { - if c.inFuzzFn { - panic("testing: f.Error was called inside the f.Fuzz function") - } c.log(fmt.Sprintln(args...)) c.Fail() } // Errorf is equivalent to Logf followed by Fail. func (c *common) Errorf(format string, args ...interface{}) { - if c.inFuzzFn { - panic("testing: f.Errorf was called inside the f.Fuzz function") - } c.log(fmt.Sprintf(format, args...)) c.Fail() } // Fatal is equivalent to Log followed by FailNow. func (c *common) Fatal(args ...interface{}) { - if c.inFuzzFn { - panic("testing: f.Fatal was called inside the f.Fuzz function") - } c.log(fmt.Sprintln(args...)) c.FailNow() } // Fatalf is equivalent to Logf followed by FailNow. func (c *common) Fatalf(format string, args ...interface{}) { - if c.inFuzzFn { - panic("testing: f.Fatalf was called inside the f.Fuzz function") - } c.log(fmt.Sprintf(format, args...)) c.FailNow() } // Skip is equivalent to Log followed by SkipNow. func (c *common) Skip(args ...interface{}) { - if c.inFuzzFn { - panic("testing: f.Skip was called inside the f.Fuzz function") - } c.log(fmt.Sprintln(args...)) c.SkipNow() } // Skipf is equivalent to Logf followed by SkipNow. func (c *common) Skipf(format string, args ...interface{}) { - if c.inFuzzFn { - panic("testing: f.Skipf was called inside the f.Fuzz function") - } c.log(fmt.Sprintf(format, args...)) c.SkipNow() } @@ -863,9 +838,6 @@ func (c *common) Skipf(format string, args ...interface{}) { // other goroutines created during the test. Calling SkipNow does not stop // those other goroutines. func (c *common) SkipNow() { - if c.inFuzzFn { - panic("testing: f.SkipNow was called inside the f.Fuzz function") - } c.skip() c.finished = true runtime.Goexit() @@ -888,9 +860,6 @@ func (c *common) Skipped() bool { // When printing file and line information, that function will be skipped. // Helper may be called simultaneously from multiple goroutines. func (c *common) Helper() { - if c.inFuzzFn { - panic("testing: f.Helper was called inside the f.Fuzz function") - } c.mu.Lock() defer c.mu.Unlock() if c.helperPCs == nil { @@ -912,9 +881,6 @@ func (c *common) Helper() { // subtests complete. Cleanup functions will be called in last added, // first called order. func (c *common) Cleanup(f func()) { - if c.inFuzzFn { - panic("testing: f.Cleanup was called inside the f.Fuzz function") - } var pc [maxStackLen]uintptr // Skip two extra frames to account for this function and runtime.Callers itself. n := runtime.Callers(2, pc[:]) @@ -953,9 +919,6 @@ var tempDirReplacer struct { // Each subsequent call to t.TempDir returns a unique directory; // if the directory creation fails, TempDir terminates the test by calling Fatal. func (c *common) TempDir() string { - if c.inFuzzFn { - panic("testing: f.TempDir was called inside the f.Fuzz function") - } // Use a single parent directory for all the temporary directories // created by a test, each numbered sequentially. c.tempDirMu.Lock() -- GitLab From 7743f60b5a01b5892edda7311484a2c2bc207ea2 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 9 Feb 2021 10:08:48 -0500 Subject: [PATCH 0037/2500] [dev.fuzz] testing: make F.Fuzz more similar to T.Run This change rewrites much of the glue code in testing/fuzz.go to work more analogously to T.Run. This results in improved behavior: * If a fuzz target returns without calling F.Skip, F.Fail, or F.Fuzz, 'go test' will report an error and exit non-zero. * Functions registered with F.Cleanup are called. * The user can re-run individual inputs using -run=FuzzTarget/name where name is the base name of the seed corpus file. We now print the 'go test' command after a crash. This change doesn't correctly handle T.Parallel calls yet, but it should be easier to do that in the future. Highlighted parts of this change: * Instead of creating one F for all targets, create an F for each target. F (actually common) holds the status, output, and cleanup function list for each target, so it's important to keep them separate. * Run each target in its own goroutine via fRunner. fRunner is analogous to tRunner. It runs cleanups and catches inappropriate Goexits and panics. * Run each input in its own goroutine via T.Run. This enables subtest filtering with -test.run and ensures functions registered with T.Cleanup (not F.Cleanup) are run at the appropriate time. Change-Id: Iab1da14ead8bcb57746f8a76f4aebc625baa5792 Reviewed-on: https://go-review.googlesource.com/c/go/+/290693 Reviewed-by: Katie Hockman Trust: Jay Conrod Run-TryBot: Jay Conrod --- src/cmd/go/testdata/script/test_fuzz.txt | 14 +- .../go/testdata/script/test_fuzz_cleanup.txt | 67 +++ src/internal/fuzz/fuzz.go | 26 +- src/testing/fuzz.go | 393 ++++++++++-------- 4 files changed, 324 insertions(+), 176 deletions(-) create mode 100644 src/cmd/go/testdata/script/test_fuzz_cleanup.txt diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt index ccdae830a5..9870f719da 100644 --- a/src/cmd/go/testdata/script/test_fuzz.txt +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -3,17 +3,15 @@ # Test that running a fuzz target that returns without failing or calling # f.Fuzz fails and causes a non-zero exit status. -# BUG(jayconrod): for now, it passes. -go test noop_fuzz_test.go -stdout ok -! stdout FAIL +! go test noop_fuzz_test.go +! stdout ^ok +stdout FAIL # Test that fuzzing a fuzz target that returns without failing or calling # f.Fuzz fails and causes a non-zero exit status. -# BUG(jayconrod): for now, it passes. -go test -fuzz=Fuzz -fuzztime=5s -parallel=1 noop_fuzz_test.go -stdout ok -! stdout FAIL +! go test -fuzz=Fuzz -fuzztime=5s -parallel=1 noop_fuzz_test.go +! stdout ^ok +stdout FAIL # Test that calling f.Error in a fuzz target causes a non-zero exit status. ! go test -fuzz=Fuzz -fuzztime=5s -parallel=1 error_fuzz_test.go diff --git a/src/cmd/go/testdata/script/test_fuzz_cleanup.txt b/src/cmd/go/testdata/script/test_fuzz_cleanup.txt new file mode 100644 index 0000000000..88625916ba --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_cleanup.txt @@ -0,0 +1,67 @@ +# TODO(jayconrod): support shared memory on more platforms. +[!darwin] [!linux] [!windows] skip +[short] skip + +# Cleanup should run after F.Skip. +go test -run=FuzzTargetSkip +stdout cleanup + +# Cleanup should run after F.Fatal. +! go test -run=FuzzTargetFatal +stdout cleanup + +# Cleanup should run after an unexpected runtime.Goexit. +! go test -run=FuzzTargetGoexit +stdout cleanup + +# Cleanup should run after panic. +! go test -run=FuzzTargetPanic +stdout cleanup + +# Cleanup should run in fuzz function on seed corpus. +go test -v -run=FuzzFunction +stdout '(?s)inner.*outer' + +# TODO(jayconrod): test cleanup while fuzzing. For now, the worker process's +# stdout and stderr is connected to the coordinator's, but it should eventually +# be connected to os.DevNull, so we wouldn't see t.Log output. + +-- go.mod -- +module cleanup + +go 1.15 +-- cleanup_test.go -- +package cleanup + +import ( + "runtime" + "testing" +) + +func FuzzTargetSkip(f *testing.F) { + f.Cleanup(func() { f.Log("cleanup") }) + f.Skip() +} + +func FuzzTargetFatal(f *testing.F) { + f.Cleanup(func() { f.Log("cleanup") }) + f.Fatal() +} + +func FuzzTargetGoexit(f *testing.F) { + f.Cleanup(func() { f.Log("cleanup") }) + runtime.Goexit() +} + +func FuzzTargetPanic(f *testing.F) { + f.Cleanup(func() { f.Log("cleanup") }) + panic("oh no") +} + +func FuzzFunction(f *testing.F) { + f.Add([]byte{0}) + f.Cleanup(func() { f.Log("outer") }) + f.Fuzz(func(t *testing.T, b []byte) { + t.Cleanup(func() { t.Logf("inner") }) + }) +} diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 451731ba93..3b2baaf3a5 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -10,6 +10,7 @@ package fuzz import ( "context" "crypto/sha256" + "errors" "fmt" "io/ioutil" "os" @@ -143,7 +144,10 @@ func CoordinateFuzzing(ctx context.Context, parallel int, seed []CorpusEntry, co // A worker found a crasher. Write it to testdata and return it. fileName, err := writeToCorpus(crasher.Data, corpusDir) if err == nil { - err = fmt.Errorf(" Crash written to %s\n%s", fileName, crasher.errMsg) + err = &crashError{ + name: filepath.Base(fileName), + err: errors.New(crasher.errMsg), + } } // TODO(jayconrod,katiehockman): if -keepfuzzing, report the error to // the user and restart the crashed worker. @@ -181,6 +185,26 @@ func CoordinateFuzzing(ctx context.Context, parallel int, seed []CorpusEntry, co // write to cacheDir instead. } +// crashError wraps a crasher written to the seed corpus. It saves the name +// of the file where the input causing the crasher was saved. The testing +// framework uses this to report a command to re-run that specific input. +type crashError struct { + name string + err error +} + +func (e *crashError) Error() string { + return e.err.Error() +} + +func (e *crashError) Unwrap() error { + return e.err +} + +func (e *crashError) CrashName() string { + return e.name +} + type corpus struct { entries []CorpusEntry } diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index f64629bcd4..6b2d910af5 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -11,6 +11,7 @@ import ( "os" "path/filepath" "runtime" + "sync/atomic" "time" ) @@ -42,11 +43,12 @@ type InternalFuzzTarget struct { // F is a type passed to fuzz targets for fuzz testing. type F struct { common - context *fuzzContext - inFuzzFn bool // set to true when fuzz function is running - corpus []corpusEntry // corpus is the in-memory corpus - result FuzzResult // result is the result of running the fuzz target - fuzzFunc func(f *F) // fuzzFunc is the function which makes up the fuzz target + fuzzContext *fuzzContext + testContext *testContext + inFuzzFn bool // set to true when fuzz function is running + corpus []corpusEntry // corpus is the in-memory corpus + result FuzzResult // result is the result of running the fuzz target + fuzzCalled bool } var _ TB = (*F)(nil) @@ -204,175 +206,131 @@ func (f *F) Add(args ...interface{}) { // target by calling runtime.Goexit. To run any code after this function, use // Cleanup. func (f *F) Fuzz(ff interface{}) { - defer runtime.Goexit() // exit after this function + if f.fuzzCalled { + panic("testing: F.Fuzz called more than once") + } + f.fuzzCalled = true fn, ok := ff.(func(*T, []byte)) if !ok { panic("testing: Fuzz function must have type func(*testing.T, []byte)") } + f.Helper() // Load seed corpus - c, err := f.context.readCorpus(filepath.Join(corpusDir, f.name)) + c, err := f.fuzzContext.readCorpus(filepath.Join(corpusDir, f.name)) if err != nil { f.Fatal(err) } f.corpus = append(f.corpus, c...) - // TODO(jayconrod,katiehockman): dedupe testdata corpus with entries from f.Add - var errStr string - run := func(t *T, b []byte) { - defer func() { - err := recover() - // If the function has recovered but the test hasn't finished, - // it is due to a nil panic or runtime.GoExit. - if !t.finished && err == nil { - err = errNilPanicOrGoexit - } - if err != nil { - t.Fail() - t.output = []byte(fmt.Sprintf(" %s", err)) - } - f.inFuzzFn = false - t.signal <- true // signal that the test has finished - }() - // TODO(katiehockman, jayconrod): consider replacing inFuzzFn with - // general purpose flag that checks whether specific methods can be - // called. + // run calls fn on a given input, as a subtest with its own T. + // run is analogous to T.Run. The test filtering and cleanup works similarly. + // fn is called in its own goroutine. + // + // TODO(jayconrod,katiehockman): dedupe testdata corpus with entries from f.Add + // TODO(jayconrod,katiehockman): handle T.Parallel calls within fuzz function. + run := func(e corpusEntry) error { + testName, ok, _ := f.testContext.match.fullName(&f.common, e.Name) + if !ok || shouldFailFast() { + return nil + } + // Record the stack trace at the point of this call so that if the subtest + // function - which runs in a separate stack - is marked as a helper, we can + // continue walking the stack into the parent test. + var pc [maxStackLen]uintptr + n := runtime.Callers(2, pc[:]) + t := &T{ + common: common{ + barrier: make(chan bool), + signal: make(chan bool), + name: testName, + parent: &f.common, + level: f.level + 1, + creator: pc[:n], + chatty: f.chatty, + }, + context: f.testContext, + } + t.w = indenter{&t.common} + if t.chatty != nil { + t.chatty.Updatef(t.name, "=== RUN %s\n", t.name) + } f.inFuzzFn = true - fn(t, b) - t.finished = true + go tRunner(t, func(t *T) { fn(t, e.Data) }) + <-t.signal + f.inFuzzFn = false + if t.Failed() { + return errors.New(string(t.output)) + } + return nil } switch { - case f.context.coordinateFuzzing != nil: + case f.fuzzContext.coordinateFuzzing != nil: // Fuzzing is enabled, and this is the test process started by 'go test'. // Act as the coordinator process, and coordinate workers to perform the // actual fuzzing. corpusTargetDir := filepath.Join(corpusDir, f.name) cacheTargetDir := filepath.Join(*fuzzCacheDir, f.name) - err := f.context.coordinateFuzzing(*fuzzDuration, *parallel, f.corpus, corpusTargetDir, cacheTargetDir) + err := f.fuzzContext.coordinateFuzzing(*fuzzDuration, *parallel, f.corpus, corpusTargetDir, cacheTargetDir) if err != nil { - f.Fail() f.result = FuzzResult{Error: err} + f.Error(err) + if crashErr, ok := err.(fuzzCrashError); ok { + crashName := crashErr.CrashName() + f.Logf("Crash written to %s", filepath.Join("testdata/corpus", f.name, crashName)) + f.Logf("To re-run:\ngo test %s -run=%s/%s", f.fuzzContext.importPath(), f.name, crashName) + } } - f.setRan() - f.finished = true // TODO(jayconrod,katiehockman): Aggregate statistics across workers // and add to FuzzResult (ie. time taken, num iterations) - case f.context.runFuzzWorker != nil: + case f.fuzzContext.runFuzzWorker != nil: // Fuzzing is enabled, and this is a worker process. Follow instructions // from the coordinator. - err := f.context.runFuzzWorker(func(e corpusEntry) error { - t := &T{ - common: common{ - signal: make(chan bool), - w: f.w, - chatty: f.chatty, - }, - context: newTestContext(1, nil), - } - go run(t, e.Data) - <-t.signal - if t.Failed() { - return errors.New(string(t.output)) - } - return nil - }) - if err != nil { + if err := f.fuzzContext.runFuzzWorker(run); err != nil { // TODO(jayconrod,katiehockman): how should we handle a failure to // communicate with the coordinator? Might be caused by the coordinator // terminating early. - fmt.Fprintf(os.Stderr, "testing: communicating with fuzz coordinator: %v\n", err) - os.Exit(1) + f.Errorf("communicating with fuzzing coordinator: %v", err) } - f.setRan() - f.finished = true default: // Fuzzing is not enabled. Only run the seed corpus. - for _, c := range f.corpus { - t := &T{ - common: common{ - signal: make(chan bool), - w: f.w, - chatty: f.chatty, - }, - context: newTestContext(1, nil), - } - go run(t, c.Data) - <-t.signal - if t.Failed() { - f.Fail() - errStr += string(t.output) - } - f.setRan() - } - f.finished = true - if f.Failed() { - f.result = FuzzResult{Error: errors.New(errStr)} - return + for _, e := range f.corpus { + run(e) } } + + // Record that the fuzz function (or coordinateFuzzing or runFuzzWorker) + // returned normally. This is used to distinguish runtime.Goexit below + // from panic(nil). + f.finished = true + + // Terminate the goroutine. F.Fuzz should not return. + // We cannot call runtime.Goexit from a deferred function: if there is a + // panic, that would replace the panic value with nil. + runtime.Goexit() } func (f *F) report() { - if *isFuzzWorker { + if *isFuzzWorker || f.parent == nil { return } + dstr := fmtDuration(f.duration) + format := "--- %s: %s (%s)\n" if f.Failed() { - fmt.Fprintf(f.w, "--- FAIL: %s\n%s\n", f.name, f.result.String()) + f.flushToParent(f.name, format, "FAIL", f.name, dstr) } else if f.chatty != nil { if f.Skipped() { - f.chatty.Updatef(f.name, "SKIP\n") + f.flushToParent(f.name, format, "SKIP", f.name, dstr) } else { - f.chatty.Updatef(f.name, "PASS\n") + f.flushToParent(f.name, format, "PASS", f.name, dstr) } } } -// run runs each fuzz target in its own goroutine with its own *F. -func (f *F) run(ft InternalFuzzTarget) (ran, ok bool) { - f = &F{ - common: common{ - signal: make(chan bool), - name: ft.Name, - chatty: f.chatty, - w: f.w, - }, - context: f.context, - } - if f.chatty != nil { - f.chatty.Updatef(ft.Name, "=== RUN %s\n", ft.Name) - } - go f.runTarget(ft.Fn) - <-f.signal - return f.ran, !f.failed -} - -// runTarget runs the given target, handling panics and exits -// within the test, and reporting errors. -func (f *F) runTarget(fn func(*F)) { - defer func() { - err := recover() - // If the function has recovered but the test hasn't finished, - // it is due to a nil panic or runtime.GoExit. - if !f.finished && err == nil { - err = errNilPanicOrGoexit - } - if err != nil { - f.Fail() - f.result = FuzzResult{Error: fmt.Errorf(" %s", err)} - } - f.report() - f.setRan() - f.signal <- true // signal that the test has finished - }() - defer f.runCleanup(normalPanic) - fn(f) - f.finished = true -} - // FuzzResult contains the results of a fuzz run. type FuzzResult struct { N int // The number of iterations. @@ -389,10 +347,24 @@ func (r FuzzResult) String() string { return s } +// fuzzCrashError is satisfied by a crash detected within the fuzz function. +// These errors are written to the seed corpus and can be re-run with 'go test'. +// Errors within the fuzzing framework (like I/O errors between coordinator +// and worker processes) don't satisfy this interface. +type fuzzCrashError interface { + error + Unwrap() error + + // CrashName returns the name of the subtest that corresponds to the saved + // crash input file in the seed corpus. The test can be re-run with + // go test $pkg -run=$target/$name where $pkg is the package's import path, + // $target is the fuzz target name, and $name is the string returned here. + CrashName() string +} + // fuzzContext holds all fields that are common to all fuzz targets. type fuzzContext struct { - runMatch *matcher - fuzzMatch *matcher + importPath func() string coordinateFuzzing func(time.Duration, int, []corpusEntry, string, string) error runFuzzWorker func(func(corpusEntry) error) error readCorpus func(string) ([]corpusEntry, error) @@ -406,35 +378,44 @@ func runFuzzTargets(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran, ok bo if len(fuzzTargets) == 0 || *isFuzzWorker { return ran, ok } - ctx := &fuzzContext{ - runMatch: newMatcher(deps.MatchString, *match, "-test.run"), + m := newMatcher(deps.MatchString, *match, "-test.run") + tctx := newTestContext(*parallel, m) + fctx := &fuzzContext{ + importPath: deps.ImportPath, readCorpus: deps.ReadCorpus, } - var fts []InternalFuzzTarget + root := common{w: os.Stdout} // gather output in one place + if Verbose() { + root.chatty = newChattyPrinter(root.w) + } for _, ft := range fuzzTargets { - if _, matched, _ := ctx.runMatch.fullName(nil, ft.Name); matched { - fts = append(fts, ft) + if shouldFailFast() { + break } + testName, matched, _ := tctx.match.fullName(nil, ft.Name) + if !matched { + continue + } + f := &F{ + common: common{ + signal: make(chan bool), + name: testName, + parent: &root, + level: root.level + 1, + chatty: root.chatty, + }, + testContext: tctx, + fuzzContext: fctx, + } + f.w = indenter{&f.common} + if f.chatty != nil { + f.chatty.Updatef(f.name, "=== RUN %s\n", f.name) + } + + go fRunner(f, ft.Fn) + <-f.signal } - f := &F{ - common: common{ - w: os.Stdout, - }, - fuzzFunc: func(f *F) { - for _, ft := range fts { - // Run each fuzz target in it's own goroutine. - ftRan, ftOk := f.run(ft) - ran = ran || ftRan - ok = ok && ftOk - } - }, - context: ctx, - } - if Verbose() { - f.chatty = newChattyPrinter(f.w) - } - f.fuzzFunc(f) - return ran, ok + return root.ran, !root.Failed() } // runFuzzing runs the fuzz target matching the pattern for -fuzz. Only one such @@ -447,26 +428,26 @@ func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran, ok bool) if len(fuzzTargets) == 0 || *matchFuzz == "" { return false, true } - ctx := &fuzzContext{ - fuzzMatch: newMatcher(deps.MatchString, *matchFuzz, "-test.fuzz"), + m := newMatcher(deps.MatchString, *matchFuzz, "-test.fuzz") + tctx := newTestContext(1, m) + fctx := &fuzzContext{ + importPath: deps.ImportPath, readCorpus: deps.ReadCorpus, } if *isFuzzWorker { - ctx.runFuzzWorker = deps.RunFuzzWorker + fctx.runFuzzWorker = deps.RunFuzzWorker } else { - ctx.coordinateFuzzing = deps.CoordinateFuzzing + fctx.coordinateFuzzing = deps.CoordinateFuzzing } - f := &F{ - common: common{ - signal: make(chan bool), - w: os.Stdout, - }, - context: ctx, + root := common{w: os.Stdout} + if Verbose() && !*isFuzzWorker { + root.chatty = newChattyPrinter(root.w) } var target *InternalFuzzTarget + var f *F for i := range fuzzTargets { ft := &fuzzTargets[i] - testName, matched, _ := ctx.fuzzMatch.fullName(&f.common, ft.Name) + testName, matched, _ := tctx.match.fullName(nil, ft.Name) if !matched { continue } @@ -475,18 +456,96 @@ func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran, ok bool) return false, true } target = ft - f.name = testName + f = &F{ + common: common{ + signal: make(chan bool), + name: testName, + parent: &root, + level: root.level + 1, + chatty: root.chatty, + }, + fuzzContext: fctx, + testContext: tctx, + } + f.w = indenter{&f.common} } if target == nil { return false, true } - if Verbose() { - f.chatty = newChattyPrinter(f.w) - if !*isFuzzWorker { - f.chatty.Updatef(f.name, "--- FUZZ: %s\n", f.name) - } + if f.chatty != nil { + f.chatty.Updatef(f.name, "=== FUZZ %s\n", f.name) } - go f.runTarget(target.Fn) + go fRunner(f, target.Fn) <-f.signal return f.ran, !f.failed } + +// fRunner wraps a call to a fuzz target and ensures that cleanup functions are +// called and status flags are set. fRunner should be called in its own +// goroutine. To wait for its completion, receive f.signal. +// +// fRunner is analogous with tRunner, which wraps subtests started with T.Run. +// Tests and fuzz targets work a little differently, so for now, these functions +// aren't consoldiated. +func fRunner(f *F, fn func(*F)) { + // When this goroutine is done, either because runtime.Goexit was called, + // a panic started, or fn returned normally, record the duration and send + // t.signal, indicating the fuzz target is done. + defer func() { + // Detect whether the fuzz target panicked or called runtime.Goexit without + // calling F.Fuzz, F.Fail, or F.Skip. If it did, panic (possibly replacing + // a nil panic value). Nothing should recover after fRunner unwinds, + // so this should crash the process with a stack. Unfortunately, recovering + // here adds stack frames, but the location of the original panic should + // still be clear. + if f.Failed() { + atomic.AddUint32(&numFailed, 1) + } + err := recover() + f.mu.RLock() + ok := f.skipped || f.failed || (f.fuzzCalled && f.finished) + f.mu.RUnlock() + if err == nil && !ok { + err = errNilPanicOrGoexit + } + + // If we recovered a panic or inappropriate runtime.Goexit, fail the test, + // flush the output log up to the root, then panic. + if err != nil { + f.Fail() + for root := &f.common; root.parent != nil; root = root.parent { + root.mu.Lock() + root.duration += time.Since(root.start) + d := root.duration + root.mu.Unlock() + root.flushToParent(root.name, "--- FAIL: %s (%s)\n", root.name, fmtDuration(d)) + } + panic(err) + } + + // No panic or inappropriate Goexit. Record duration and report the result. + f.duration += time.Since(f.start) + f.report() + f.done = true + f.setRan() + + // Only report that the test is complete if it doesn't panic, + // as otherwise the test binary can exit before the panic is + // reported to the user. See issue 41479. + f.signal <- true + }() + defer func() { + f.runCleanup(normalPanic) + }() + + f.start = time.Now() + fn(f) + + // Code beyond this point is only executed if fn returned normally. + // That means fn did not call F.Fuzz or F.Skip. It should have called F.Fail. + f.mu.Lock() + defer f.mu.Unlock() + if !f.failed { + panic(f.name + " returned without calling F.Fuzz, F.Fail, or F.Skip") + } +} -- GitLab From 9cbf92c52bd7da4fb80c86dc0f17f00ca76fd038 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Wed, 10 Feb 2021 13:05:59 -0500 Subject: [PATCH 0038/2500] [dev.fuzz] internal/fuzz: support corpus file encoding/decoding Change-Id: Id245ce5f154557f1744210e7d7f061d08901c746 Reviewed-on: https://go-review.googlesource.com/c/go/+/290951 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/internal/fuzz/encoding.go | 240 +++++++++++++++++++++++++++++ src/internal/fuzz/encoding_test.go | 115 ++++++++++++++ 2 files changed, 355 insertions(+) create mode 100644 src/internal/fuzz/encoding.go create mode 100644 src/internal/fuzz/encoding_test.go diff --git a/src/internal/fuzz/encoding.go b/src/internal/fuzz/encoding.go new file mode 100644 index 0000000000..f9403b36bc --- /dev/null +++ b/src/internal/fuzz/encoding.go @@ -0,0 +1,240 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fuzz + +import ( + "bytes" + "fmt" + "go/ast" + "go/parser" + "go/token" + "strconv" +) + +// encVersion1 will be the first line of a file with version 1 encoding. +var encVersion1 = "version 1" + +// marshalCorpusFile encodes an arbitrary number of arguments into the file format for the +// corpus. +func marshalCorpusFile(vals ...interface{}) []byte { + if len(vals) == 0 { + panic("must have at least one value to encode") + } + b := bytes.NewBuffer([]byte(encVersion1)) + // TODO(katiehockman): keep uint8 and int32 encoding where applicable, + // instead of changing to byte and rune respectively. + for _, val := range vals { + switch t := val.(type) { + case int, int8, int16, int64, uint, uint16, uint32, uint64, uintptr, float32, float64, bool: + fmt.Fprintf(b, "\n%T(%v)", t, t) + case string: + fmt.Fprintf(b, "\nstring(%q)", t) + case rune: // int32 + fmt.Fprintf(b, "\nrune(%q)", t) + case byte: // uint8 + fmt.Fprintf(b, "\nbyte(%q)", t) + case []byte: // []uint8 + fmt.Fprintf(b, "\n[]byte(%q)", t) + default: + panic(fmt.Sprintf("unsupported type: %T", t)) + } + } + return b.Bytes() +} + +// unmarshalCorpusFile decodes corpus bytes into their respective values. +func unmarshalCorpusFile(b []byte) ([]interface{}, error) { + if len(b) == 0 { + return nil, fmt.Errorf("cannot decode empty string") + } + lines := bytes.Split(b, []byte("\n")) + if len(lines) < 2 { + return nil, fmt.Errorf("must include version and at least one value") + } + if string(lines[0]) != encVersion1 { + return nil, fmt.Errorf("unknown encoding version: %s", lines[0]) + } + var vals []interface{} + for _, line := range lines[1:] { + line = bytes.TrimSpace(line) + if len(line) == 0 { + continue + } + v, err := parseCorpusValue(line) + if err != nil { + return nil, fmt.Errorf("malformed line %q: %v", line, err) + } + vals = append(vals, v) + } + return vals, nil +} + +func parseCorpusValue(line []byte) (interface{}, error) { + fs := token.NewFileSet() + expr, err := parser.ParseExprFrom(fs, "(test)", line, 0) + if err != nil { + return nil, err + } + call, ok := expr.(*ast.CallExpr) + if !ok { + return nil, fmt.Errorf("expected call expression") + } + if len(call.Args) != 1 { + return nil, fmt.Errorf("expected call expression with 1 argument; got %d", len(call.Args)) + } + arg := call.Args[0] + + if arrayType, ok := call.Fun.(*ast.ArrayType); ok { + if arrayType.Len != nil { + return nil, fmt.Errorf("expected []byte or primitive type") + } + elt, ok := arrayType.Elt.(*ast.Ident) + if !ok || elt.Name != "byte" { + return nil, fmt.Errorf("expected []byte") + } + lit, ok := arg.(*ast.BasicLit) + if !ok || lit.Kind != token.STRING { + return nil, fmt.Errorf("string literal required for type []byte") + } + s, err := strconv.Unquote(lit.Value) + if err != nil { + return nil, err + } + return []byte(s), nil + } + + idType, ok := call.Fun.(*ast.Ident) + if !ok { + return nil, fmt.Errorf("expected []byte or primitive type") + } + if idType.Name == "bool" { + id, ok := arg.(*ast.Ident) + if !ok { + return nil, fmt.Errorf("malformed bool") + } + if id.Name == "true" { + return true, nil + } else if id.Name == "false" { + return false, nil + } else { + return nil, fmt.Errorf("true or false required for type bool") + } + } + var ( + val string + kind token.Token + ) + if op, ok := arg.(*ast.UnaryExpr); ok { + // Special case for negative numbers. + lit, ok := op.X.(*ast.BasicLit) + if !ok || (lit.Kind != token.INT && lit.Kind != token.FLOAT) { + return nil, fmt.Errorf("expected operation on int or float type") + } + if op.Op != token.SUB { + return nil, fmt.Errorf("unsupported operation on int: %v", op.Op) + } + val = op.Op.String() + lit.Value // e.g. "-" + "124" + kind = lit.Kind + } else { + lit, ok := arg.(*ast.BasicLit) + if !ok { + return nil, fmt.Errorf("literal value required for primitive type") + } + val, kind = lit.Value, lit.Kind + } + + switch typ := idType.Name; typ { + case "string": + if kind != token.STRING { + return nil, fmt.Errorf("string literal value required for type string") + } + return strconv.Unquote(val) + case "byte", "rune": + if kind != token.CHAR { + return nil, fmt.Errorf("character literal required for byte/rune types") + } + n := len(val) + if n < 2 { + return nil, fmt.Errorf("malformed character literal, missing single quotes") + } + code, _, _, err := strconv.UnquoteChar(val[1:n-1], '\'') + if err != nil { + return nil, err + } + if typ == "rune" { + return code, nil + } + if code >= 256 { + return nil, fmt.Errorf("can only encode single byte to a byte type") + } + return byte(code), nil + case "int", "int8", "int16", "int32", "int64": + if kind != token.INT { + return nil, fmt.Errorf("integer literal required for int types") + } + return parseInt(val, typ) + case "uint", "uint8", "uint16", "uint32", "uint64": + if kind != token.INT { + return nil, fmt.Errorf("integer literal required for uint types") + } + return parseUint(val, typ) + case "float32": + if kind != token.FLOAT { + return nil, fmt.Errorf("float literal required for float32 type") + } + v, err := strconv.ParseFloat(val, 32) + return float32(v), err + case "float64": + if kind != token.FLOAT { + return nil, fmt.Errorf("float literal required for float64 type") + } + return strconv.ParseFloat(val, 64) + default: + return nil, fmt.Errorf("expected []byte or primitive type") + } +} + +// parseInt returns an integer of value val and type typ. +func parseInt(val, typ string) (interface{}, error) { + switch typ { + case "int": + return strconv.Atoi(val) + case "int8": + i, err := strconv.ParseInt(val, 10, 8) + return int8(i), err + case "int16": + i, err := strconv.ParseInt(val, 10, 16) + return int16(i), err + case "int32": + i, err := strconv.ParseInt(val, 10, 32) + return int32(i), err + case "int64": + return strconv.ParseInt(val, 10, 64) + default: + panic("unreachable") + } +} + +// parseInt returns an unsigned integer of value val and type typ. +func parseUint(val, typ string) (interface{}, error) { + switch typ { + case "uint": + i, err := strconv.ParseUint(val, 10, 0) + return uint(i), err + case "uint8": + i, err := strconv.ParseUint(val, 10, 8) + return uint8(i), err + case "uint16": + i, err := strconv.ParseUint(val, 10, 16) + return uint16(i), err + case "uint32": + i, err := strconv.ParseUint(val, 10, 32) + return uint32(i), err + case "uint64": + return strconv.ParseUint(val, 10, 64) + default: + panic("unreachable") + } +} diff --git a/src/internal/fuzz/encoding_test.go b/src/internal/fuzz/encoding_test.go new file mode 100644 index 0000000000..98d3e21c1f --- /dev/null +++ b/src/internal/fuzz/encoding_test.go @@ -0,0 +1,115 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fuzz + +import ( + "strings" + "testing" +) + +func TestUnmarshalMarshal(t *testing.T) { + var tests = []struct { + in string + ok bool + }{ + { + in: "int(1234)", + ok: false, // missing version + }, + { + in: `version 1 +string("a"bcad")`, + ok: false, // malformed + }, + { + in: `version 1 +int()`, + ok: false, // empty value + }, + { + in: `version 1 +uint(-32)`, + ok: false, // invalid negative uint + }, + { + in: `version 1 +int8(1234456)`, + ok: false, // int8 too large + }, + { + in: `version 1 +int(20*5)`, + ok: false, // expression in int value + }, + { + in: `version 1 +int(--5)`, + ok: false, // expression in int value + }, + { + in: `version 1 +bool(0)`, + ok: false, // malformed bool + }, + { + in: `version 1 +byte('aa)`, + ok: false, // malformed byte + }, + { + in: `version 1 +byte('☃')`, + ok: false, // byte out of range + }, + { + in: `version 1 +string("extra") +[]byte("spacing") + `, + ok: true, + }, + { + in: `version 1 +int(-23) +int8(-2) +int64(2342425) +uint(1) +uint16(234) +uint32(352342) +uint64(123) +rune('œ') +byte('K') +byte('ÿ') +[]byte("hello¿") +[]byte("a") +bool(true) +string("hello\\xbd\\xb2=\\xbc ⌘") +float64(-12.5) +float32(2.5)`, + ok: true, + }, + } + for _, test := range tests { + t.Run(test.in, func(t *testing.T) { + vals, err := unmarshalCorpusFile([]byte(test.in)) + if test.ok && err != nil { + t.Fatalf("unmarshal unexpected error: %v", err) + } else if !test.ok && err == nil { + t.Fatalf("unmarshal unexpected success") + } + if !test.ok { + return // skip the rest of the test + } + newB := marshalCorpusFile(vals...) + if err != nil { + t.Fatalf("marshal unexpected error: %v", err) + } + want := strings.TrimSpace(test.in) + if want != string(newB) { + t.Errorf("values changed after unmarshal then marshal\nbefore: %q\nafter: %q", want, newB) + } + }) + } +} -- GitLab From 1c162b41c5a6233d20cf714cb46764c14c61db03 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Wed, 17 Feb 2021 14:56:47 -0500 Subject: [PATCH 0039/2500] [dev.fuzz] internal/fuzz: remove duplicate read from testdata We already read the seed corpus from testdata for the fuzz target, and pass that corpus to the coordinator. The coordinator doesn't need to read from testdata again. Change-Id: Ia7822e3e02b35d56f6918c7082a7b19901b36644 Reviewed-on: https://go-review.googlesource.com/c/go/+/293189 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/internal/fuzz/fuzz.go | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 3b2baaf3a5..ef009334f7 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -49,7 +49,7 @@ func CoordinateFuzzing(ctx context.Context, parallel int, seed []CorpusEntry, co } sharedMemSize := 100 << 20 // 100 MB - corpus, err := readCorpusAndCache(seed, corpusDir, cacheDir) + corpus, err := readCache(seed, cacheDir) if err != nil { return err } @@ -262,7 +262,7 @@ type coordinator struct { errC chan error } -// readCorpusAndCache creates a combined corpus from seed values, values in the +// readCache creates a combined corpus from seed values, values in the // corpus directory (in testdata), and values in the cache (in GOCACHE/fuzz). // // TODO(jayconrod,katiehockman): if a value in the cache has the wrong type, @@ -270,16 +270,14 @@ type coordinator struct { // the same package at a different version or in a different module. // TODO(jayconrod,katiehockman): need a mechanism that can remove values that // aren't useful anymore, for example, because they have the wrong type. -func readCorpusAndCache(seed []CorpusEntry, corpusDir, cacheDir string) (corpus, error) { +func readCache(seed []CorpusEntry, cacheDir string) (corpus, error) { var c corpus c.entries = append(c.entries, seed...) - for _, dir := range []string{corpusDir, cacheDir} { - entries, err := ReadCorpus(dir) - if err != nil { - return corpus{}, err - } - c.entries = append(c.entries, entries...) + entries, err := ReadCorpus(cacheDir) + if err != nil { + return corpus{}, err } + c.entries = append(c.entries, entries...) return c, nil } -- GitLab From 84953420fbf8d7ecb86c3521fc585c8c383ac100 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Thu, 18 Feb 2021 16:16:29 -0500 Subject: [PATCH 0040/2500] [dev.fuzz] all: add codereview.cfg This will enable the new "git-codereview sync-branch" command. Change-Id: Id2f933f6d13e181817c56d2548172a74b1d0b629 Reviewed-on: https://go-review.googlesource.com/c/go/+/293909 Trust: Katie Hockman Reviewed-by: Jay Conrod --- codereview.cfg | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 codereview.cfg diff --git a/codereview.cfg b/codereview.cfg new file mode 100644 index 0000000000..bed9bcf7ee --- /dev/null +++ b/codereview.cfg @@ -0,0 +1,2 @@ +branch: dev.fuzz +parent-branch: master \ No newline at end of file -- GitLab From 563a6cb17fdfbd20067cfe56cd38608ae3824df9 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Thu, 18 Feb 2021 17:53:07 -0500 Subject: [PATCH 0041/2500] [dev.fuzz] go/build: add missing dependencies The test was broken before, but was fixed in CL 279073, which will be pulled in during our merge. Change-Id: I782c49f223eec5f856e4735a6c883f1464be5a57 Reviewed-on: https://go-review.googlesource.com/c/go/+/293842 Reviewed-by: Jay Conrod Trust: Katie Hockman --- src/go/build/deps_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 8542e52049..16ca675f8c 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -484,7 +484,7 @@ var depsRules = ` FMT, flag, runtime/debug, runtime/trace, internal/sysinfo < testing; - FMT, crypto/sha256, encoding/json, math/rand + FMT, crypto/sha256, encoding/json, go/ast, go/parser, go/token, math/rand < internal/fuzz; internal/fuzz, internal/testlog, runtime/pprof, regexp -- GitLab From 5aacd47c002c39b481c4c7a0663e851758da372a Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Mon, 22 Feb 2021 13:25:07 -0500 Subject: [PATCH 0042/2500] [dev.fuzz] internal/fuzz: updating version incoding Based on feedback from rsc@, update the version encoding to more clearly indicate that this is about fuzzing with Go. Change-Id: Id95dec8283608779b157bf662e7147f9a9c8dba8 Reviewed-on: https://go-review.googlesource.com/c/go/+/295110 Trust: Katie Hockman Run-TryBot: Katie Hockman Reviewed-by: Jay Conrod --- src/internal/fuzz/encoding.go | 2 +- src/internal/fuzz/encoding_test.go | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/internal/fuzz/encoding.go b/src/internal/fuzz/encoding.go index f9403b36bc..31810fca61 100644 --- a/src/internal/fuzz/encoding.go +++ b/src/internal/fuzz/encoding.go @@ -14,7 +14,7 @@ import ( ) // encVersion1 will be the first line of a file with version 1 encoding. -var encVersion1 = "version 1" +var encVersion1 = "go test fuzz v1" // marshalCorpusFile encodes an arbitrary number of arguments into the file format for the // corpus. diff --git a/src/internal/fuzz/encoding_test.go b/src/internal/fuzz/encoding_test.go index 98d3e21c1f..cbf4999f8d 100644 --- a/src/internal/fuzz/encoding_test.go +++ b/src/internal/fuzz/encoding_test.go @@ -19,59 +19,59 @@ func TestUnmarshalMarshal(t *testing.T) { ok: false, // missing version }, { - in: `version 1 + in: `go test fuzz v1 string("a"bcad")`, ok: false, // malformed }, { - in: `version 1 + in: `go test fuzz v1 int()`, ok: false, // empty value }, { - in: `version 1 + in: `go test fuzz v1 uint(-32)`, ok: false, // invalid negative uint }, { - in: `version 1 + in: `go test fuzz v1 int8(1234456)`, ok: false, // int8 too large }, { - in: `version 1 + in: `go test fuzz v1 int(20*5)`, ok: false, // expression in int value }, { - in: `version 1 + in: `go test fuzz v1 int(--5)`, ok: false, // expression in int value }, { - in: `version 1 + in: `go test fuzz v1 bool(0)`, ok: false, // malformed bool }, { - in: `version 1 + in: `go test fuzz v1 byte('aa)`, ok: false, // malformed byte }, { - in: `version 1 + in: `go test fuzz v1 byte('☃')`, ok: false, // byte out of range }, { - in: `version 1 + in: `go test fuzz v1 string("extra") []byte("spacing") `, ok: true, }, { - in: `version 1 + in: `go test fuzz v1 int(-23) int8(-2) int64(2342425) -- GitLab From 621a81aba0fd5fc7ceb297ede3627819fc59728c Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Thu, 18 Feb 2021 15:42:05 -0500 Subject: [PATCH 0043/2500] [dev.fuzz] testing,internal/fuzz: support structured inputs This change makes several refactors to start supporting structured fuzzing. The mutator can still only mutate byte slices, and future changes will be made to support mutating other types. However, it does now support fuzzing more than one []byte. This change also makes it so that corpus entries are encoded in the new file format when being written to testdata or GOCACHE. Any existing GOCACHE data should be deleted from your local workstation to allow tests to pass locally. Change-Id: Iab8fe01a5dc870f0c53010b9d5b0b479bbdb310d Reviewed-on: https://go-review.googlesource.com/c/go/+/293810 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/testdata/script/test_fuzz.txt | 57 +++++++- .../script/test_fuzz_mutate_crash.txt | 14 ++ .../go/testdata/script/test_fuzz_mutator.txt | 2 +- src/internal/fuzz/encoding.go | 6 +- src/internal/fuzz/fuzz.go | 126 +++++++++++++++--- src/internal/fuzz/mutator.go | 41 +++++- src/internal/fuzz/worker.go | 11 +- src/testing/fuzz.go | 91 +++++++++---- src/testing/internal/testdeps/deps.go | 9 +- src/testing/testing.go | 11 +- 10 files changed, 297 insertions(+), 71 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt index 9870f719da..f9783504ee 100644 --- a/src/cmd/go/testdata/script/test_fuzz.txt +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -116,6 +116,21 @@ stdout 'off by one error' ! stdout ^ok stdout FAIL +# Test panic with unsupported seed corpus +! go test -run FuzzUnsupported fuzz_add_test.go +! stdout ^ok +stdout FAIL + +# Test panic with different number of args to f.Add +! go test -run FuzzAddDifferentNumber fuzz_add_test.go +! stdout ^ok +stdout FAIL + +# Test panic with different type of args to f.Add +! go test -run FuzzAddDifferentType fuzz_add_test.go +! stdout ^ok +stdout FAIL + # Test fatal with testdata seed corpus ! go test -run FuzzFail corpustesting/fuzz_testdata_corpus_test.go ! stdout ^ok @@ -128,6 +143,11 @@ stdout ok ! stdout FAIL ! stdout 'fatal here' +# Test panic with malformed seed corpus +! go test -run FuzzFail corpustesting/fuzz_testdata_corpus_test.go +! stdout ^ok +stdout FAIL + # Test pass with file in other nested testdata directory go test -run FuzzInNestedDir corpustesting/fuzz_testdata_corpus_test.go stdout ok @@ -316,6 +336,24 @@ func FuzzNilPanic(f *testing.F) { }) } +func FuzzUnsupported(f *testing.F) { + m := make(map[string]bool) + f.Add(m) + f.Fuzz(func(t *testing.T, b []byte) {}) +} + +func FuzzAddDifferentNumber(f *testing.F) { + f.Add([]byte("a")) + f.Add([]byte("a"), []byte("b")) + f.Fuzz(func(t *testing.T, b []byte) {}) +} + +func FuzzAddDifferentType(f *testing.F) { + f.Add(false) + f.Add(1234) + f.Fuzz(func(t *testing.T, b []byte) {}) +} + -- corpustesting/fuzz_testdata_corpus_test.go -- package fuzz_testdata_corpus @@ -324,7 +362,7 @@ import "testing" func fuzzFn(f *testing.F) { f.Helper() f.Fuzz(func(t *testing.T, b []byte) { - if string(b) == "12345\n" { + if string(b) == "12345" { t.Fatal("fatal here") } }) @@ -338,13 +376,22 @@ func FuzzPass(f *testing.F) { fuzzFn(f) } +func FuzzPanic(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) {}) +} + func FuzzInNestedDir(f *testing.F) { - fuzzFn(f) + f.Fuzz(func(t *testing.T, b []byte) {}) } -- corpustesting/testdata/corpus/FuzzFail/1 -- -12345 +go test fuzz v1 +[]byte("12345") -- corpustesting/testdata/corpus/FuzzPass/1 -- -00000 +go test fuzz v1 +[]byte("00000") +-- corpustesting/testdata/corpus/FuzzPanic/1 -- +malformed -- corpustesting/testdata/corpus/FuzzInNestedDir/anotherdir/1 -- -12345 \ No newline at end of file +go test fuzz v1 +[]byte("12345") \ No newline at end of file diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt index b45e7d77c7..2f5d069e69 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt @@ -24,6 +24,12 @@ go run check_testdata.go FuzzWithBug # the target, and should fail when run without fuzzing. ! go test -parallel=1 +# Running the fuzzer should find a crashing input quickly for fuzzing two types. +! go test -run=FuzzWithTwoTypes -fuzz=FuzzWithTwoTypes -fuzztime=5s -parallel=1 +stdout 'testdata[/\\]corpus[/\\]FuzzWithTwoTypes[/\\]' +stdout 'these inputs caused a crash!' +go run check_testdata.go FuzzWithTwoTypes + ! go test -run=FuzzWithNilPanic -fuzz=FuzzWithNilPanic -fuzztime=5s -parallel=1 stdout 'testdata[/\\]corpus[/\\]FuzzWithNilPanic[/\\]' stdout 'runtime.Goexit' @@ -64,6 +70,14 @@ func FuzzWithNilPanic(f *testing.F) { }) } +func FuzzWithTwoTypes(f *testing.F) { + f.Fuzz(func(t *testing.T, a, b []byte) { + if len(a) > 0 && len(b) > 0 { + panic("these inputs caused a crash!") + } + }) +} + func FuzzWithBadExit(f *testing.F) { f.Add([]byte("aa")) f.Fuzz(func(t *testing.T, b []byte) { diff --git a/src/cmd/go/testdata/script/test_fuzz_mutator.txt b/src/cmd/go/testdata/script/test_fuzz_mutator.txt index a84fc35c5c..b94fa90245 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutator.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutator.txt @@ -14,7 +14,7 @@ go test -fuzz=FuzzA -fuzztime=5s -parallel=1 -log=fuzz go run check_logs.go fuzz fuzz.worker # Test that the mutator is good enough to find several unique mutations. -! go test -v -fuzz=Fuzz -parallel=1 -fuzztime=30s mutator_test.go +! go test -fuzz=Fuzz -parallel=1 -fuzztime=30s mutator_test.go ! stdout ok stdout FAIL stdout 'mutator found enough unique mutations' diff --git a/src/internal/fuzz/encoding.go b/src/internal/fuzz/encoding.go index 31810fca61..c018ef5fe2 100644 --- a/src/internal/fuzz/encoding.go +++ b/src/internal/fuzz/encoding.go @@ -20,14 +20,14 @@ var encVersion1 = "go test fuzz v1" // corpus. func marshalCorpusFile(vals ...interface{}) []byte { if len(vals) == 0 { - panic("must have at least one value to encode") + panic("must have at least one value to marshal") } b := bytes.NewBuffer([]byte(encVersion1)) // TODO(katiehockman): keep uint8 and int32 encoding where applicable, // instead of changing to byte and rune respectively. for _, val := range vals { switch t := val.(type) { - case int, int8, int16, int64, uint, uint16, uint32, uint64, uintptr, float32, float64, bool: + case int, int8, int16, int64, uint, uint16, uint32, uint64, float32, float64, bool: fmt.Fprintf(b, "\n%T(%v)", t, t) case string: fmt.Fprintf(b, "\nstring(%q)", t) @@ -47,7 +47,7 @@ func marshalCorpusFile(vals ...interface{}) []byte { // unmarshalCorpusFile decodes corpus bytes into their respective values. func unmarshalCorpusFile(b []byte) ([]interface{}, error) { if len(b) == 0 { - return nil, fmt.Errorf("cannot decode empty string") + return nil, fmt.Errorf("cannot unmarshal empty string") } lines := bytes.Split(b, []byte("\n")) if len(lines) < 2 { diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index ef009334f7..aa121bf2a0 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -15,7 +15,9 @@ import ( "io/ioutil" "os" "path/filepath" + "reflect" "runtime" + "strings" "sync" ) @@ -32,6 +34,8 @@ import ( // seed is a list of seed values added by the fuzz target with testing.F.Add and // in testdata. // +// types is the list of types which make up a corpus entry. +// // corpusDir is a directory where files containing values that crash the // code being tested may be written. // @@ -40,7 +44,7 @@ import ( // // If a crash occurs, the function will return an error containing information // about the crash, which can be reported to the user. -func CoordinateFuzzing(ctx context.Context, parallel int, seed []CorpusEntry, corpusDir, cacheDir string) (err error) { +func CoordinateFuzzing(ctx context.Context, parallel int, seed []CorpusEntry, types []reflect.Type, corpusDir, cacheDir string) (err error) { if err := ctx.Err(); err != nil { return err } @@ -49,12 +53,22 @@ func CoordinateFuzzing(ctx context.Context, parallel int, seed []CorpusEntry, co } sharedMemSize := 100 << 20 // 100 MB - corpus, err := readCache(seed, cacheDir) + // Make sure all of the seed corpus has marshalled data. + for i := range seed { + if seed[i].Data == nil { + seed[i].Data = marshalCorpusFile(seed[i].Values...) + } + } + corpus, err := readCache(seed, types, cacheDir) if err != nil { return err } if len(corpus.entries) == 0 { - corpus.entries = []CorpusEntry{{Data: []byte{}}} + var vals []interface{} + for _, t := range types { + vals = append(vals, zeroValue(t)) + } + corpus.entries = append(corpus.entries, CorpusEntry{Data: marshalCorpusFile(vals...), Values: vals}) } // TODO(jayconrod): do we want to support fuzzing different binaries? @@ -224,10 +238,8 @@ type CorpusEntry = struct { // Data is the raw data loaded from a corpus file. Data []byte - // TODO(jayconrod,katiehockman): support multiple values of different types - // added with f.Add with a Values []interface{} field. We'll need marhsalling - // and unmarshalling functions, and we'll need to figure out what to do - // in the mutator. + // Values is the unmarshaled values from a corpus file. + Values []interface{} } type crasherEntry struct { @@ -262,35 +274,57 @@ type coordinator struct { errC chan error } -// readCache creates a combined corpus from seed values, values in the -// corpus directory (in testdata), and values in the cache (in GOCACHE/fuzz). +// readCache creates a combined corpus from seed values and values in the cache +// (in GOCACHE/fuzz). // -// TODO(jayconrod,katiehockman): if a value in the cache has the wrong type, -// ignore it instead of reporting an error. Cached values may be used for -// the same package at a different version or in a different module. // TODO(jayconrod,katiehockman): need a mechanism that can remove values that // aren't useful anymore, for example, because they have the wrong type. -func readCache(seed []CorpusEntry, cacheDir string) (corpus, error) { +func readCache(seed []CorpusEntry, types []reflect.Type, cacheDir string) (corpus, error) { var c corpus c.entries = append(c.entries, seed...) - entries, err := ReadCorpus(cacheDir) + entries, err := ReadCorpus(cacheDir, types) if err != nil { - return corpus{}, err + if _, ok := err.(*MalformedCorpusError); !ok { + // It's okay if some files in the cache directory are malformed and + // are not included in the corpus, but fail if it's an I/O error. + return corpus{}, err + } + // TODO(jayconrod,katiehockman): consider printing some kind of warning + // indicating the number of files which were skipped because they are + // malformed. } c.entries = append(c.entries, entries...) return c, nil } -// ReadCorpus reads the corpus from the testdata directory in this target's -// package. -func ReadCorpus(dir string) ([]CorpusEntry, error) { +// MalformedCorpusError is an error found while reading the corpus from the +// filesystem. All of the errors are stored in the errs list. The testing +// framework uses this to report malformed files in testdata. +type MalformedCorpusError struct { + errs []error +} + +func (e *MalformedCorpusError) Error() string { + var msgs []string + for _, s := range e.errs { + msgs = append(msgs, s.Error()) + } + return strings.Join(msgs, "\n") +} + +// ReadCorpus reads the corpus from the provided dir. The returned corpus +// entries are guaranteed to match the given types. Any malformed files will +// be saved in a MalformedCorpusError and returned, along with the most recent +// error. +func ReadCorpus(dir string, types []reflect.Type) ([]CorpusEntry, error) { files, err := ioutil.ReadDir(dir) if os.IsNotExist(err) { return nil, nil // No corpus to read } else if err != nil { - return nil, fmt.Errorf("testing: reading seed corpus from testdata: %v", err) + return nil, fmt.Errorf("reading seed corpus from testdata: %v", err) } var corpus []CorpusEntry + var errs []error for _, file := range files { // TODO(jayconrod,katiehockman): determine when a file is a fuzzing input // based on its name. We should only read files created by writeToCorpus. @@ -300,11 +334,30 @@ func ReadCorpus(dir string) ([]CorpusEntry, error) { if file.IsDir() { continue } - bytes, err := ioutil.ReadFile(filepath.Join(dir, file.Name())) + filename := filepath.Join(dir, file.Name()) + data, err := ioutil.ReadFile(filename) if err != nil { - return nil, fmt.Errorf("testing: failed to read corpus file: %v", err) + return nil, fmt.Errorf("failed to read corpus file: %v", err) } - corpus = append(corpus, CorpusEntry{Name: file.Name(), Data: bytes}) + vals, err := unmarshalCorpusFile(data) + if err != nil { + errs = append(errs, fmt.Errorf("failed to unmarshal %q: %v", filename, err)) + continue + } + if len(vals) != len(types) { + errs = append(errs, fmt.Errorf("wrong number of values in corpus file %q: %d, want %d", filename, len(vals), len(types))) + continue + } + for i := range types { + if reflect.TypeOf(vals[i]) != types[i] { + errs = append(errs, fmt.Errorf("mismatched types in corpus file %q: %v, want %v", filename, vals, types)) + continue + } + } + corpus = append(corpus, CorpusEntry{Name: file.Name(), Data: data, Values: vals}) + } + if len(errs) > 0 { + return corpus, &MalformedCorpusError{errs: errs} } return corpus, nil } @@ -325,3 +378,32 @@ func writeToCorpus(b []byte, dir string) (name string, err error) { } return name, nil } + +func zeroValue(t reflect.Type) interface{} { + for _, v := range zeroVals { + if reflect.TypeOf(v) == t { + return v + } + } + panic(fmt.Sprintf("unsupported type: %v", t)) +} + +var zeroVals []interface{} = []interface{}{ + []byte(""), + string(""), + false, + byte(0), + rune(0), + float32(0), + float64(0), + int(0), + int8(0), + int16(0), + int32(0), + int64(0), + uint(0), + uint8(0), + uint16(0), + uint32(0), + uint64(0), +} diff --git a/src/internal/fuzz/mutator.go b/src/internal/fuzz/mutator.go index 377491adcb..584c21e8ae 100644 --- a/src/internal/fuzz/mutator.go +++ b/src/internal/fuzz/mutator.go @@ -6,6 +6,7 @@ package fuzz import ( "encoding/binary" + "fmt" "reflect" "unsafe" ) @@ -49,12 +50,38 @@ func min(a, b int) int { return b } -// mutate performs several mutations directly onto the provided byte slice. -func (m *mutator) mutate(ptrB *[]byte) { - // TODO(jayconrod,katiehockman): make this use zero allocations - // TODO(katiehockman): pull some of these functions into helper methods - // and test that each case is working as expected. +// mutate performs several mutations on the provided values. +func (m *mutator) mutate(vals []interface{}, maxBytes int) []interface{} { + // TODO(jayconrod,katiehockman): use as few allocations as possible + // TODO(katiehockman): pull some of these functions into helper methods and + // test that each case is working as expected. // TODO(katiehockman): perform more types of mutations. + + // maxPerVal will represent the maximum number of bytes that each value be + // allowed after mutating, giving an equal amount of capacity to each line. + // Allow a little wiggle room for the encoding. + maxPerVal := maxBytes/len(vals) - 100 + + // Pick a random value to mutate. + // TODO: consider mutating more than one value at a time. + i := m.rand(len(vals)) + // TODO(katiehockman): support mutating other types + switch v := vals[i].(type) { + case []byte: + if len(v) > maxPerVal { + panic(fmt.Sprintf("cannot mutate bytes of length %d", len(v))) + } + b := make([]byte, 0, maxPerVal) + b = append(b, v...) + m.mutateBytes(&b) + vals[i] = b + return vals + default: + panic(fmt.Sprintf("type not supported for mutating: %T", vals[i])) + } +} + +func (m *mutator) mutateBytes(ptrB *[]byte) { b := *ptrB defer func() { oldHdr := (*reflect.SliceHeader)(unsafe.Pointer(ptrB)) @@ -103,6 +130,10 @@ func (m *mutator) mutate(ptrB *[]byte) { dst = m.rand(len(b)) } n := m.chooseLen(len(b) - src) + if len(b)+n >= cap(b) { + iter-- + continue + } tmp := make([]byte, n) copy(tmp, b[src:]) b = b[:len(b)+n] diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index f9284db729..e2b3c3d7a6 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -453,6 +453,10 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) fuzzResponse { mem := <-ws.memMu defer func() { ws.memMu <- mem }() + vals, err := unmarshalCorpusFile(mem.valueCopy()) + if err != nil { + panic(err) + } for { select { case <-ctx.Done(): @@ -460,10 +464,11 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) fuzzResponse { // real heuristic once we have one. return fuzzResponse{Interesting: true} default: - b := mem.valueRef() - ws.m.mutate(&b) + vals = ws.m.mutate(vals, cap(mem.valueRef())) + b := marshalCorpusFile(vals...) mem.setValueLen(len(b)) - if err := ws.fuzzFn(CorpusEntry{Data: b}); err != nil { + mem.setValue(b) + if err := ws.fuzzFn(CorpusEntry{Values: vals}); err != nil { return fuzzResponse{Err: err.Error()} } // TODO(jayconrod,katiehockman): return early if we find an diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 6b2d910af5..f670ef4546 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -10,6 +10,7 @@ import ( "fmt" "os" "path/filepath" + "reflect" "runtime" "sync/atomic" "time" @@ -57,8 +58,9 @@ var _ TB = (*F)(nil) // We use a type alias because we don't want to export this type, and we can't // importing internal/fuzz from testing. type corpusEntry = struct { - Name string - Data []byte + Name string + Data []byte + Values []interface{} } // Cleanup registers a function to be called when the test and all its @@ -183,20 +185,35 @@ func (f *F) TempDir() string { // be a no-op if called after or within the Fuzz function. The args must match // those in the Fuzz function. func (f *F) Add(args ...interface{}) { - if len(args) == 0 { - panic("testing: Add must have at least one argument") - } - if len(args) != 1 { - // TODO: support more than one argument - panic("testing: Add only supports one argument currently") - } - switch v := args[0].(type) { - case []byte: - f.corpus = append(f.corpus, corpusEntry{Data: v}) - // TODO: support other types - default: - panic("testing: Add only supports []byte currently") + var values []interface{} + for i := range args { + if t := reflect.TypeOf(args[i]); !supportedTypes[t] { + panic(fmt.Sprintf("testing: unsupported type to Add %v", t)) + } + values = append(values, args[i]) } + f.corpus = append(f.corpus, corpusEntry{Values: values}) +} + +// supportedTypes represents all of the supported types which can be fuzzed. +var supportedTypes = map[reflect.Type]bool{ + reflect.TypeOf(([]byte)("")): true, + reflect.TypeOf((string)("")): true, + reflect.TypeOf((bool)(false)): true, + reflect.TypeOf((byte)(0)): true, + reflect.TypeOf((rune)(0)): true, + reflect.TypeOf((float32)(0)): true, + reflect.TypeOf((float64)(0)): true, + reflect.TypeOf((int)(0)): true, + reflect.TypeOf((int8)(0)): true, + reflect.TypeOf((int16)(0)): true, + reflect.TypeOf((int32)(0)): true, + reflect.TypeOf((int64)(0)): true, + reflect.TypeOf((uint)(0)): true, + reflect.TypeOf((uint8)(0)): true, + reflect.TypeOf((uint16)(0)): true, + reflect.TypeOf((uint32)(0)): true, + reflect.TypeOf((uint64)(0)): true, } // Fuzz runs the fuzz function, ff, for fuzz testing. If ff fails for a set of @@ -210,15 +227,30 @@ func (f *F) Fuzz(ff interface{}) { panic("testing: F.Fuzz called more than once") } f.fuzzCalled = true + f.Helper() - fn, ok := ff.(func(*T, []byte)) - if !ok { - panic("testing: Fuzz function must have type func(*testing.T, []byte)") + // ff should be in the form func(*testing.T, ...interface{}) + fn := reflect.ValueOf(ff) + fnType := fn.Type() + if fnType.Kind() != reflect.Func { + panic("testing: F.Fuzz must receive a function") + } + if fnType.NumIn() < 2 || fnType.In(0) != reflect.TypeOf((*T)(nil)) { + panic("testing: F.Fuzz function must receive at least two arguments, where the first argument is a *T") + } + + // Save the types of the function to compare against the corpus. + var types []reflect.Type + for i := 1; i < fnType.NumIn(); i++ { + t := fnType.In(i) + if !supportedTypes[t] { + panic(fmt.Sprintf("testing: unsupported type for fuzzing %v", t)) + } + types = append(types, t) } - f.Helper() // Load seed corpus - c, err := f.fuzzContext.readCorpus(filepath.Join(corpusDir, f.name)) + c, err := f.fuzzContext.readCorpus(filepath.Join(corpusDir, f.name), types) if err != nil { f.Fatal(err) } @@ -231,6 +263,11 @@ func (f *F) Fuzz(ff interface{}) { // TODO(jayconrod,katiehockman): dedupe testdata corpus with entries from f.Add // TODO(jayconrod,katiehockman): handle T.Parallel calls within fuzz function. run := func(e corpusEntry) error { + if e.Values == nil { + // Every code path should have already unmarshaled Data into Values. + // It's our fault if it didn't. + panic(fmt.Sprintf("corpus file %q was not unmarshaled", e.Name)) + } testName, ok, _ := f.testContext.match.fullName(&f.common, e.Name) if !ok || shouldFailFast() { return nil @@ -257,7 +294,13 @@ func (f *F) Fuzz(ff interface{}) { t.chatty.Updatef(t.name, "=== RUN %s\n", t.name) } f.inFuzzFn = true - go tRunner(t, func(t *T) { fn(t, e.Data) }) + go tRunner(t, func(t *T) { + args := []reflect.Value{reflect.ValueOf(t)} + for _, v := range e.Values { + args = append(args, reflect.ValueOf(v)) + } + fn.Call(args) + }) <-t.signal f.inFuzzFn = false if t.Failed() { @@ -273,7 +316,7 @@ func (f *F) Fuzz(ff interface{}) { // actual fuzzing. corpusTargetDir := filepath.Join(corpusDir, f.name) cacheTargetDir := filepath.Join(*fuzzCacheDir, f.name) - err := f.fuzzContext.coordinateFuzzing(*fuzzDuration, *parallel, f.corpus, corpusTargetDir, cacheTargetDir) + err := f.fuzzContext.coordinateFuzzing(*fuzzDuration, *parallel, f.corpus, types, corpusTargetDir, cacheTargetDir) if err != nil { f.result = FuzzResult{Error: err} f.Error(err) @@ -365,9 +408,9 @@ type fuzzCrashError interface { // fuzzContext holds all fields that are common to all fuzz targets. type fuzzContext struct { importPath func() string - coordinateFuzzing func(time.Duration, int, []corpusEntry, string, string) error + coordinateFuzzing func(time.Duration, int, []corpusEntry, []reflect.Type, string, string) error runFuzzWorker func(func(corpusEntry) error) error - readCorpus func(string) ([]corpusEntry, error) + readCorpus func(string, []reflect.Type) ([]corpusEntry, error) } // runFuzzTargets runs the fuzz targets matching the pattern for -run. This will diff --git a/src/testing/internal/testdeps/deps.go b/src/testing/internal/testdeps/deps.go index 3160cae7a4..d5481d6608 100644 --- a/src/testing/internal/testdeps/deps.go +++ b/src/testing/internal/testdeps/deps.go @@ -18,6 +18,7 @@ import ( "io" "os" "os/signal" + "reflect" "regexp" "runtime/pprof" "strings" @@ -132,7 +133,7 @@ func (TestDeps) SetPanicOnExit0(v bool) { testlog.SetPanicOnExit0(v) } -func (TestDeps) CoordinateFuzzing(timeout time.Duration, parallel int, seed []fuzz.CorpusEntry, corpusDir, cacheDir string) (err error) { +func (TestDeps) CoordinateFuzzing(timeout time.Duration, parallel int, seed []fuzz.CorpusEntry, types []reflect.Type, corpusDir, cacheDir string) (err error) { // Fuzzing may be interrupted with a timeout or if the user presses ^C. // In either case, we'll stop worker processes gracefully and save // crashers and interesting values. @@ -143,7 +144,7 @@ func (TestDeps) CoordinateFuzzing(timeout time.Duration, parallel int, seed []fu ctx, stop := signal.NotifyContext(ctx, os.Interrupt) defer stop() defer cancel() - err = fuzz.CoordinateFuzzing(ctx, parallel, seed, corpusDir, cacheDir) + err = fuzz.CoordinateFuzzing(ctx, parallel, seed, types, corpusDir, cacheDir) if err == ctx.Err() { return nil } @@ -168,6 +169,6 @@ func (TestDeps) RunFuzzWorker(fn func(fuzz.CorpusEntry) error) error { return nil } -func (TestDeps) ReadCorpus(dir string) ([]fuzz.CorpusEntry, error) { - return fuzz.ReadCorpus(dir) +func (TestDeps) ReadCorpus(dir string, types []reflect.Type) ([]fuzz.CorpusEntry, error) { + return fuzz.ReadCorpus(dir, types) } diff --git a/src/testing/testing.go b/src/testing/testing.go index 2e38898c98..152483d8ff 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -243,6 +243,7 @@ import ( "internal/race" "io" "os" + "reflect" "runtime" "runtime/debug" "runtime/trace" @@ -1324,11 +1325,13 @@ func (f matchStringOnly) ImportPath() string { return " func (f matchStringOnly) StartTestLog(io.Writer) {} func (f matchStringOnly) StopTestLog() error { return errMain } func (f matchStringOnly) SetPanicOnExit0(bool) {} -func (f matchStringOnly) CoordinateFuzzing(time.Duration, int, []corpusEntry, string, string) error { +func (f matchStringOnly) CoordinateFuzzing(time.Duration, int, []corpusEntry, []reflect.Type, string, string) error { return errMain } func (f matchStringOnly) RunFuzzWorker(func(corpusEntry) error) error { return errMain } -func (f matchStringOnly) ReadCorpus(string) ([]corpusEntry, error) { return nil, errMain } +func (f matchStringOnly) ReadCorpus(string, []reflect.Type) ([]corpusEntry, error) { + return nil, errMain +} // Main is an internal function, part of the implementation of the "go test" command. // It was exported because it is cross-package and predates "internal" packages. @@ -1371,9 +1374,9 @@ type testDeps interface { StartTestLog(io.Writer) StopTestLog() error WriteProfileTo(string, io.Writer, int) error - CoordinateFuzzing(time.Duration, int, []corpusEntry, string, string) error + CoordinateFuzzing(time.Duration, int, []corpusEntry, []reflect.Type, string, string) error RunFuzzWorker(func(corpusEntry) error) error - ReadCorpus(string) ([]corpusEntry, error) + ReadCorpus(string, []reflect.Type) ([]corpusEntry, error) } // MainStart is meant for use by tests generated by 'go test'. -- GitLab From 354c77a108863a1ccae810c94453870f0678a828 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Wed, 3 Mar 2021 16:00:49 -0500 Subject: [PATCH 0044/2500] [dev.fuzz] internal/fuzz: crash if there is no error output Previously, the coordintor used the error string encoded by the worker to determine whether or not a crash occurred. However, failures caused by things like t.Fail() which have no output will have an empty error string, so we can't rely on the error string alone to determine if something is a crasher or not. Change-Id: Idcf7f6b1210aa1dc4e8dab222642c87919595693 Reviewed-on: https://go-review.googlesource.com/c/go/+/298351 Trust: Katie Hockman Run-TryBot: Katie Hockman Reviewed-by: Jay Conrod --- .../script/test_fuzz_mutate_crash.txt | 43 +++++++++++++++++++ src/internal/fuzz/worker.go | 11 +++-- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt index 2f5d069e69..66e1cd8b76 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt @@ -35,6 +35,22 @@ stdout 'testdata[/\\]corpus[/\\]FuzzWithNilPanic[/\\]' stdout 'runtime.Goexit' go run check_testdata.go FuzzWithNilPanic +! go test -run=FuzzWithFail -fuzz=FuzzWithFail -fuzztime=5s -parallel=1 +stdout 'testdata[/\\]corpus[/\\]FuzzWithFail[/\\]' +go run check_testdata.go FuzzWithFail + +! go test -run=FuzzWithErrorf -fuzz=FuzzWithErrorf -fuzztime=5s -parallel=1 +stdout 'testdata[/\\]corpus[/\\]FuzzWithErrorf[/\\]' +# TODO: Uncomment this part of the test once it's fixed +# stdout 'errorf was called here' +go run check_testdata.go FuzzWithErrorf + +! go test -run=FuzzWithFatalf -fuzz=FuzzWithFatalf -fuzztime=5s -parallel=1 +stdout 'testdata[/\\]corpus[/\\]FuzzWithFatalf[/\\]' +# TODO: Uncomment this part of the test once it's fixed +# stdout 'fatalf was called here' +go run check_testdata.go FuzzWithFatalf + ! go test -run=FuzzWithBadExit -fuzz=FuzzWithBadExit -fuzztime=5s -parallel=1 stdout 'testdata[/\\]corpus[/\\]FuzzWithBadExit[/\\]' stdout 'unexpectedly' @@ -70,6 +86,33 @@ func FuzzWithNilPanic(f *testing.F) { }) } +func FuzzWithFail(f *testing.F) { + f.Add([]byte("aa")) + f.Fuzz(func(t *testing.T, b []byte) { + if string(b) != "aa" { + t.Fail() + } + }) +} + +func FuzzWithErrorf(f *testing.F) { + f.Add([]byte("aa")) + f.Fuzz(func(t *testing.T, b []byte) { + if string(b) != "aa" { + t.Errorf("errorf was called here") + } + }) +} + +func FuzzWithFatalf(f *testing.F) { + f.Add([]byte("aa")) + f.Fuzz(func(t *testing.T, b []byte) { + if string(b) != "aa" { + t.Fatalf("fatalf was called here") + } + }) +} + func FuzzWithTwoTypes(f *testing.F) { f.Fuzz(func(t *testing.T, a, b []byte) { if len(a) > 0 && len(b) > 0 { diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index e2b3c3d7a6..b44c321aac 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -142,7 +142,7 @@ func (w *worker) runFuzzing() error { } // TODO(jayconrod): what happens if testing.F.Fuzz is never called? // TODO(jayconrod): time out if the test process hangs. - } else if resp.Err != "" { + } else if resp.Crashed { // The worker found a crasher. Inform the coordinator. crasher := crasherEntry{ CorpusEntry: CorpusEntry{Data: value}, @@ -357,7 +357,12 @@ type fuzzResponse struct { // the coordinator (for example, because it expanded coverage). Interesting bool - // Err is set if the value in shared memory caused a crash. + // Crashed indicates the value in shared memory caused a crash. + Crashed bool + + // Err is the error string caused by the value in shared memory. This alone + // cannot be used to determine whether this value caused a crash, since a + // crash can occur without any output (e.g. with t.Fail()). Err string } @@ -469,7 +474,7 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) fuzzResponse { mem.setValueLen(len(b)) mem.setValue(b) if err := ws.fuzzFn(CorpusEntry{Values: vals}); err != nil { - return fuzzResponse{Err: err.Error()} + return fuzzResponse{Crashed: true, Err: err.Error()} } // TODO(jayconrod,katiehockman): return early if we find an // interesting value. -- GitLab From b89483497a7349bb8dba9110e765f5ff1189f69d Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Thu, 4 Mar 2021 13:02:24 -0500 Subject: [PATCH 0045/2500] [dev.fuzz] testing: only let workers run fuzz targets Previously, ever worker would run all of the unit tests, benchmarks, and examples. Only the single coordinator needs to do this. Change-Id: I0dfa7f79b390b6c3220d8ea646e2d2312eee6bb1 Reviewed-on: https://go-review.googlesource.com/c/go/+/298809 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- .../go/testdata/script/test_fuzz_chatty.txt | 25 +++++++++++++++ src/testing/testing.go | 32 +++++++++++-------- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_chatty.txt b/src/cmd/go/testdata/script/test_fuzz_chatty.txt index aaf385f293..ea81bc331d 100644 --- a/src/cmd/go/testdata/script/test_fuzz_chatty.txt +++ b/src/cmd/go/testdata/script/test_fuzz_chatty.txt @@ -34,6 +34,17 @@ stdout PASS stdout 'all good here' ! stdout FAIL +# Fuzz successful chatty fuzz target that includes a separate unit test. +go test -v chatty_with_test_fuzz_test.go -fuzz=Fuzz -fuzztime=1s +stdout ok +stdout PASS +! stdout FAIL +# TODO: It's currently the case that it's logged twice. Fix that, and change +# this check to verify it. +stdout 'all good here' +# Verify that the unit test is only run once. +! stdout '(?s)logged foo.*logged foo' + -- chatty_error_fuzz_test.go -- package chatty_error_fuzz @@ -79,3 +90,17 @@ func Fuzz(f *testing.F) { f.Log("all good here") f.Fuzz(func(*testing.T, []byte) {}) } + +-- chatty_with_test_fuzz_test.go -- +package chatty_with_test_fuzz + +import "testing" + +func TestFoo(t *testing.T) { + t.Log("logged foo") +} + +func Fuzz(f *testing.F) { + f.Log("all good here") + f.Fuzz(func(*testing.T, []byte) {}) +} diff --git a/src/testing/testing.go b/src/testing/testing.go index 152483d8ff..7ce794c5a8 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1439,26 +1439,30 @@ func (m *M) Run() (code int) { m.before() defer m.after() - deadline := m.startAlarm() - haveExamples = len(m.examples) > 0 - testRan, testOk := runTests(m.deps.MatchString, m.tests, deadline) - fuzzTargetsRan, fuzzTargetsOk := runFuzzTargets(m.deps, m.fuzzTargets) - exampleRan, exampleOk := runExamples(m.deps.MatchString, m.examples) - m.stopAlarm() - if !testRan && !exampleRan && !fuzzTargetsRan && *matchBenchmarks == "" && *matchFuzz == "" { - fmt.Fprintln(os.Stderr, "testing: warning: no tests to run") - } - if !testOk || !exampleOk || !fuzzTargetsOk || !runBenchmarks(m.deps.ImportPath(), m.deps.MatchString, m.benchmarks) || race.Errors() > 0 { - fmt.Println("FAIL") - m.exitCode = 1 - return + if !*isFuzzWorker { + // The fuzzing coordinator will already run all tests, examples, + // and benchmarks. Don't make the workers do redundant work. + deadline := m.startAlarm() + haveExamples = len(m.examples) > 0 + testRan, testOk := runTests(m.deps.MatchString, m.tests, deadline) + fuzzTargetsRan, fuzzTargetsOk := runFuzzTargets(m.deps, m.fuzzTargets) + exampleRan, exampleOk := runExamples(m.deps.MatchString, m.examples) + m.stopAlarm() + if !testRan && !exampleRan && !fuzzTargetsRan && *matchBenchmarks == "" && *matchFuzz == "" { + fmt.Fprintln(os.Stderr, "testing: warning: no tests to run") + } + if !testOk || !exampleOk || !fuzzTargetsOk || !runBenchmarks(m.deps.ImportPath(), m.deps.MatchString, m.benchmarks) || race.Errors() > 0 { + fmt.Println("FAIL") + m.exitCode = 1 + return + } } fuzzingRan, fuzzingOk := runFuzzing(m.deps, m.fuzzTargets) if *matchFuzz != "" && !fuzzingRan { fmt.Fprintln(os.Stderr, "testing: warning: no targets to fuzz") } - if !fuzzingOk && !*isFuzzWorker { + if !*isFuzzWorker && !fuzzingOk { fmt.Println("FAIL") m.exitCode = 1 return -- GitLab From f251d1fbb69156627379df28a150343c08a29474 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Fri, 26 Feb 2021 10:54:11 -0500 Subject: [PATCH 0046/2500] [dev.fuzz] testing, internal/fuzz: multiple small fixes * Run gofmt with go1.17 build constraint changes. * Tighten regular expressions used in tests. "ok" got some false positives with verbose output, so make sure it appears at the start of a line. * Return err in deps.RunFuzzWorker instead of nil. * Call common.Helper from F methods. This prevents F methods from appearing in stack traces. Change-Id: I839c70ec8a9f313c1a4ea68e6bb34a4d801dd36f Reviewed-on: https://go-review.googlesource.com/c/go/+/297032 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/cmd/go/internal/test/genflags.go | 1 + .../go/testdata/script/test_fuzz_match.txt | 2 +- .../go/testdata/script/test_fuzz_mutator.txt | 2 +- src/internal/fuzz/sys_posix.go | 1 + src/internal/fuzz/sys_unimplemented.go | 1 + src/testing/fuzz.go | 31 ++++++++++++++++++- src/testing/internal/testdeps/deps.go | 2 +- 7 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/cmd/go/internal/test/genflags.go b/src/cmd/go/internal/test/genflags.go index 949d65ae80..645aae68b1 100644 --- a/src/cmd/go/internal/test/genflags.go +++ b/src/cmd/go/internal/test/genflags.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore package main diff --git a/src/cmd/go/testdata/script/test_fuzz_match.txt b/src/cmd/go/testdata/script/test_fuzz_match.txt index 5ead41411f..4ea2fe2540 100644 --- a/src/cmd/go/testdata/script/test_fuzz_match.txt +++ b/src/cmd/go/testdata/script/test_fuzz_match.txt @@ -14,7 +14,7 @@ stdout '^ok' # Matches none for fuzzing but will run the fuzz target as a test. go test -fuzz ThisWillNotMatch -fuzztime 5s -parallel 1 standalone_fuzz_test.go ! stdout '^ok.*\[no tests to run\]' -stdout ok +stdout '^ok' stdout '\[no targets to fuzz\]' [short] stop diff --git a/src/cmd/go/testdata/script/test_fuzz_mutator.txt b/src/cmd/go/testdata/script/test_fuzz_mutator.txt index b94fa90245..4a33eba339 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutator.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutator.txt @@ -15,7 +15,7 @@ go run check_logs.go fuzz fuzz.worker # Test that the mutator is good enough to find several unique mutations. ! go test -fuzz=Fuzz -parallel=1 -fuzztime=30s mutator_test.go -! stdout ok +! stdout '^ok' stdout FAIL stdout 'mutator found enough unique mutations' diff --git a/src/internal/fuzz/sys_posix.go b/src/internal/fuzz/sys_posix.go index d29ff40e8d..3fbbb47869 100644 --- a/src/internal/fuzz/sys_posix.go +++ b/src/internal/fuzz/sys_posix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || linux // +build darwin linux package fuzz diff --git a/src/internal/fuzz/sys_unimplemented.go b/src/internal/fuzz/sys_unimplemented.go index 331b8761d0..5f80379c22 100644 --- a/src/internal/fuzz/sys_unimplemented.go +++ b/src/internal/fuzz/sys_unimplemented.go @@ -3,6 +3,7 @@ // license that can be found in the LICENSE file. // TODO(jayconrod): support more platforms. +//go:build !darwin && !linux && !windows // +build !darwin,!linux,!windows package fuzz diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index f670ef4546..1a634dbe8b 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -70,6 +70,7 @@ func (f *F) Cleanup(fn func()) { if f.inFuzzFn { panic("testing: f.Cleanup was called inside the f.Fuzz function") } + f.common.Helper() f.common.Cleanup(fn) } @@ -78,6 +79,7 @@ func (f *F) Error(args ...interface{}) { if f.inFuzzFn { panic("testing: f.Error was called inside the f.Fuzz function") } + f.common.Helper() f.common.Error(args...) } @@ -86,6 +88,7 @@ func (f *F) Errorf(format string, args ...interface{}) { if f.inFuzzFn { panic("testing: f.Errorf was called inside the f.Fuzz function") } + f.common.Helper() f.common.Errorf(format, args...) } @@ -94,6 +97,7 @@ func (f *F) Fail() { if f.inFuzzFn { panic("testing: f.Fail was called inside the f.Fuzz function") } + f.common.Helper() f.common.Fail() } @@ -109,6 +113,7 @@ func (f *F) FailNow() { if f.inFuzzFn { panic("testing: f.FailNow was called inside the f.Fuzz function") } + f.common.Helper() f.common.FailNow() } @@ -117,6 +122,7 @@ func (f *F) Fatal(args ...interface{}) { if f.inFuzzFn { panic("testing: f.Fatal was called inside the f.Fuzz function") } + f.common.Helper() f.common.Fatal(args...) } @@ -125,6 +131,7 @@ func (f *F) Fatalf(format string, args ...interface{}) { if f.inFuzzFn { panic("testing: f.Fatalf was called inside the f.Fuzz function") } + f.common.Helper() f.common.Fatalf(format, args...) } @@ -135,7 +142,25 @@ func (f *F) Helper() { if f.inFuzzFn { panic("testing: f.Helper was called inside the f.Fuzz function") } - f.common.Helper() + + // common.Helper is inlined here. + // If we called it, it would mark F.Helper as the helper + // instead of the caller. + f.mu.Lock() + defer f.mu.Unlock() + if f.helperPCs == nil { + f.helperPCs = make(map[uintptr]struct{}) + } + // repeating code from callerName here to save walking a stack frame + var pc [1]uintptr + n := runtime.Callers(2, pc[:]) // skip runtime.Callers + Helper + if n == 0 { + panic("testing: zero callers found") + } + if _, found := f.helperPCs[pc[0]]; !found { + f.helperPCs[pc[0]] = struct{}{} + f.helperNames = nil // map will be recreated next time it is needed + } } // Skip is equivalent to Log followed by SkipNow. @@ -143,6 +168,7 @@ func (f *F) Skip(args ...interface{}) { if f.inFuzzFn { panic("testing: f.Skip was called inside the f.Fuzz function") } + f.common.Helper() f.common.Skip(args...) } @@ -158,6 +184,7 @@ func (f *F) SkipNow() { if f.inFuzzFn { panic("testing: f.SkipNow was called inside the f.Fuzz function") } + f.common.Helper() f.common.SkipNow() } @@ -166,6 +193,7 @@ func (f *F) Skipf(format string, args ...interface{}) { if f.inFuzzFn { panic("testing: f.Skipf was called inside the f.Fuzz function") } + f.common.Helper() f.common.Skipf(format, args...) } @@ -178,6 +206,7 @@ func (f *F) TempDir() string { if f.inFuzzFn { panic("testing: f.TempDir was called inside the f.Fuzz function") } + f.common.Helper() return f.common.TempDir() } diff --git a/src/testing/internal/testdeps/deps.go b/src/testing/internal/testdeps/deps.go index d5481d6608..8f587b2e1d 100644 --- a/src/testing/internal/testdeps/deps.go +++ b/src/testing/internal/testdeps/deps.go @@ -166,7 +166,7 @@ func (TestDeps) RunFuzzWorker(fn func(fuzz.CorpusEntry) error) error { if err == ctx.Err() { return nil } - return nil + return err } func (TestDeps) ReadCorpus(dir string, types []reflect.Type) ([]fuzz.CorpusEntry, error) { -- GitLab From ac58614190c9dd1ca0a1a47bf7a29a4a7c501e72 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Fri, 26 Feb 2021 12:50:48 -0500 Subject: [PATCH 0047/2500] [dev.fuzz] testing: use exit status 70 for worker errors (not crashes) If a worker process encounters an error communicating with the coordinator, or if the setup code reports an error with F.Fail before calling F.Fuzz, exit with status 70. The coordinator will report these errors and 'go test' will exit non-zero, but the coordinator won't record a crasher since the problem is not in the code being fuzzed. The coordinator also detects unexpected terminations before the worker calls F.Fuzz by sending a ping RPC. If the worker terminates before responding to the ping RPC, the coordinator won't record a crasher. Exit codes are chosen somewhat arbitrary, but in the Advanced Bash Scripting Guide, 70 is "internal software error" which is applicable here. 70 is also ASCII 'F'. Change-Id: I1e676e39a7b07c5664efaaa3221d055f55240fff Reviewed-on: https://go-review.googlesource.com/c/go/+/297033 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- .../testdata/script/test_fuzz_mutate_fail.txt | 103 ++++++++++++++++++ src/internal/fuzz/worker.go | 69 +++++++++++- src/testing/fuzz.go | 14 ++- src/testing/testing.go | 6 +- 4 files changed, 183 insertions(+), 9 deletions(-) create mode 100644 src/cmd/go/testdata/script/test_fuzz_mutate_fail.txt diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate_fail.txt b/src/cmd/go/testdata/script/test_fuzz_mutate_fail.txt new file mode 100644 index 0000000000..935c22a05e --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_mutate_fail.txt @@ -0,0 +1,103 @@ +# TODO(jayconrod): support shared memory on more platforms. +[!darwin] [!linux] [!windows] skip + +# Check that if a worker does not call F.Fuzz or calls F.Fail first, +# 'go test' exits non-zero and no crasher is recorded. + +[short] skip + +! go test -fuzz=FuzzReturn +! exists testdata + +! go test -fuzz=FuzzSkip +! exists testdata + +! go test -fuzz=FuzzFail +! exists testdata + +! go test -fuzz=FuzzPanic +! exists testdata + +! go test -fuzz=FuzzNilPanic +! exists testdata + +! go test -fuzz=FuzzGoexit +! exists testdata + +! go test -fuzz=FuzzExit +! exists testdata + +-- go.mod -- +module m + +go 1.17 +-- fuzz_fail_test.go -- +package fuzz_fail + +import ( + "flag" + "os" + "runtime" + "testing" +) + +func isWorker() bool { + f := flag.Lookup("test.fuzzworker") + if f == nil { + return false + } + get, ok := f.Value.(flag.Getter) + if !ok { + return false + } + return get.Get() == interface{}(true) +} + +func FuzzReturn(f *testing.F) { + if isWorker() { + return + } + f.Fuzz(func(*testing.T, []byte) {}) +} + +func FuzzSkip(f *testing.F) { + if isWorker() { + f.Skip() + } + f.Fuzz(func(*testing.T, []byte) {}) +} + +func FuzzFail(f *testing.F) { + if isWorker() { + f.Fail() + } + f.Fuzz(func(*testing.T, []byte) {}) +} + +func FuzzPanic(f *testing.F) { + if isWorker() { + panic("nope") + } + f.Fuzz(func(*testing.T, []byte) {}) +} + +func FuzzNilPanic(f *testing.F) { + if isWorker() { + panic(nil) + } + f.Fuzz(func(*testing.T, []byte) {}) +} + +func FuzzGoexit(f *testing.F) { + if isWorker() { + runtime.Goexit() + } + f.Fuzz(func(*testing.T, []byte) {}) +} + +func FuzzExit(f *testing.F) { + if isWorker() { + os.Exit(99) + } + f.Fuzz(func(*testing.T, []byte) {}) +} diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index b44c321aac..1a590fad42 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -26,6 +26,11 @@ const ( // workerTimeoutDuration is the amount of time a worker can go without // responding to the coordinator before being stopped. workerTimeoutDuration = 1 * time.Second + + // workerExitCode is used as an exit code by fuzz worker processes after an internal error. + // This distinguishes internal errors from uncontrolled panics and other crashes. + // Keep in sync with internal/fuzz.workerExitCode. + workerExitCode = 70 ) // worker manages a worker process running a test binary. The worker object @@ -72,8 +77,29 @@ func (w *worker) runFuzzing() error { return err } - inputC := w.coordinator.inputC // set to nil when processing input - fuzzC := make(chan struct{}) // sent when we finish processing an input. + // inputC is set to w.coordinator.inputC when the worker is able to process + // input. It's nil at other times, so its case won't be selected in the + // event loop below. + var inputC chan CorpusEntry + + // A value is sent to fuzzC to tell the worker to prepare to process an input + // by setting inputC. + fuzzC := make(chan struct{}, 1) + + // Send the worker a message to make sure it can respond. + // Errors that occur before we get a response likely indicate that + // the worker did not call F.Fuzz or called F.Fail first. + // We don't record crashers for these errors. + pinged := false + go func() { + err := w.client.ping() + if err != nil { + w.stop() // trigger termC case below + return + } + pinged = true + fuzzC <- struct{}{} + }() // Main event loop. for { @@ -91,15 +117,20 @@ func (w *worker) runFuzzing() error { case <-w.termC: // Worker process terminated unexpectedly. + if !pinged { + w.stop() + return fmt.Errorf("worker terminated without fuzzing") + // TODO(jayconrod,katiehockman): record and return stderr. + } if isInterruptError(w.waitErr) { // Worker interrupted by SIGINT. See comment in doneC case. w.stop() return nil } - if w.waitErr == nil { - // Worker exited 0. + if exitErr, ok := w.waitErr.(*exec.ExitError); ok && exitErr.ExitCode() == workerExitCode { w.stop() - return fmt.Errorf("worker exited unexpectedly with status 0") + return fmt.Errorf("worker exited unexpectedly due to an internal failure") + // TODO(jayconrod,katiehockman): record and return stderr. } // Unexpected termination. Inform the coordinator about the crash. @@ -342,6 +373,7 @@ func RunFuzzWorker(ctx context.Context, fn func(CorpusEntry) error) error { // a minimalist RPC mechanism. Exactly one of its fields must be set to indicate // which method to call. type call struct { + Ping *pingArgs Fuzz *fuzzArgs } @@ -366,6 +398,12 @@ type fuzzResponse struct { Err string } +// pingArgs contains arguments to workerServer.ping. +type pingArgs struct{} + +// pingResponse contains results from workerServer.ping. +type pingResponse struct{} + // workerComm holds pipes and shared memory used for communication // between the coordinator process (client) and a worker process (server). // These values are unique to each worker; they are shared only with the @@ -439,6 +477,8 @@ func (ws *workerServer) serve(ctx context.Context) error { switch { case c.Fuzz != nil: resp = ws.fuzz(ctx, *c.Fuzz) + case c.Ping != nil: + resp = ws.ping(ctx, *c.Ping) default: return errors.New("no arguments provided for any call") } @@ -482,6 +522,12 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) fuzzResponse { } } +// ping does nothing. The coordinator calls this method to ensure the worker +// has called F.Fuzz and can communicate. +func (ws *workerServer) ping(ctx context.Context, args pingArgs) pingResponse { + return pingResponse{} +} + // workerClient is a minimalist RPC client. The coordinator process uses a // workerClient to call methods in each worker process (handled by // workerServer). @@ -560,3 +606,16 @@ func (wc *workerClient) fuzz(valueIn []byte, args fuzzArgs) (valueOut []byte, re return valueOut, resp, err } + +// ping tells the worker to call the ping method. See workerServer.ping. +func (wc *workerClient) ping() error { + c := call{Ping: &pingArgs{}} + if err := wc.enc.Encode(c); err != nil { + return err + } + var resp pingResponse + if err := wc.dec.Decode(&resp); err != nil { + return err + } + return nil +} diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 1a634dbe8b..c855379566 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -34,6 +34,11 @@ var ( corpusDir = "testdata/corpus" ) +// fuzzWorkerExitCode is used as an exit code by fuzz worker processes after an internal error. +// This distinguishes internal errors from uncontrolled panics and other crashes. +// Keep in sync with internal/fuzz.workerExitCode. +const fuzzWorkerExitCode = 70 + // InternalFuzzTarget is an internal type but exported because it is cross-package; // it is part of the implementation of the "go test" command. type InternalFuzzTarget struct { @@ -256,6 +261,9 @@ func (f *F) Fuzz(ff interface{}) { panic("testing: F.Fuzz called more than once") } f.fuzzCalled = true + if f.failed { + return + } f.Helper() // ff should be in the form func(*testing.T, ...interface{}) @@ -362,9 +370,9 @@ func (f *F) Fuzz(ff interface{}) { // Fuzzing is enabled, and this is a worker process. Follow instructions // from the coordinator. if err := f.fuzzContext.runFuzzWorker(run); err != nil { - // TODO(jayconrod,katiehockman): how should we handle a failure to - // communicate with the coordinator? Might be caused by the coordinator - // terminating early. + // Internal errors are marked with f.Fail; user code may call this too, before F.Fuzz. + // The worker will exit with fuzzWorkerExitCode, indicating this is a failure + // (and 'go test' should exit non-zero) but a crasher should not be recorded. f.Errorf("communicating with fuzzing coordinator: %v", err) } diff --git a/src/testing/testing.go b/src/testing/testing.go index 7ce794c5a8..2ad39f7137 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1464,7 +1464,11 @@ func (m *M) Run() (code int) { } if !*isFuzzWorker && !fuzzingOk { fmt.Println("FAIL") - m.exitCode = 1 + if *isFuzzWorker { + m.exitCode = fuzzWorkerExitCode + } else { + m.exitCode = 1 + } return } -- GitLab From d4825819fe58e8531c7fcdf4ce27cec63824db25 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Fri, 26 Feb 2021 12:57:44 -0500 Subject: [PATCH 0048/2500] [dev.fuzz] internal/fuzz: fix two bugs affecting windows * Appending to the worker environment slice should reallocate it. On Windows, we pass handles through the environment, and concurrent workers were writing to the same memory, resulting in "The handle is invalid" errors. * Instead of passing a handle to the temporary file, we pass its path to each worker instead. The worker is responsible for opening and closing the handle. Previously, all inheritable handles were inherited by all workers, even though only one was used. This prevented temporary files from being deleted after a worker stopped, because other workers would still have open handles to it. Change-Id: If8b8bcfa5b03fbcadd10ef923b036bb0ee5dc3f5 Reviewed-on: https://go-review.googlesource.com/c/go/+/297034 Trust: Jay Conrod Trust: Katie Hockman Reviewed-by: Katie Hockman --- src/internal/fuzz/fuzz.go | 2 +- src/internal/fuzz/sys_windows.go | 43 +++++++++++++++----------------- src/internal/fuzz/worker.go | 2 +- 3 files changed, 22 insertions(+), 25 deletions(-) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index aa121bf2a0..b8405622df 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -96,7 +96,7 @@ func CoordinateFuzzing(ctx context.Context, parallel int, seed []CorpusEntry, ty dir: dir, binPath: binPath, args: args, - env: env, + env: env[:len(env):len(env)], // copy on append to ensure workers don't overwrite each other. coordinator: c, memMu: memMu, }, nil diff --git a/src/internal/fuzz/sys_windows.go b/src/internal/fuzz/sys_windows.go index 6d015c0195..e1734af53c 100644 --- a/src/internal/fuzz/sys_windows.go +++ b/src/internal/fuzz/sys_windows.go @@ -9,8 +9,6 @@ import ( "os" "os/exec" "reflect" - "strconv" - "strings" "syscall" "unsafe" ) @@ -19,7 +17,13 @@ type sharedMemSys struct { mapObj syscall.Handle } -func sharedMemMapFile(f *os.File, size int, removeOnClose bool) (*sharedMem, error) { +func sharedMemMapFile(f *os.File, size int, removeOnClose bool) (mem *sharedMem, err error) { + defer func() { + if err != nil { + err = fmt.Errorf("mapping temporary file %s: %w", f.Name(), err) + } + }() + // Create a file mapping object. The object itself is not shared. mapObj, err := syscall.CreateFileMapping( syscall.Handle(f.Fd()), // fhandle @@ -86,12 +90,11 @@ func (m *sharedMem) Close() error { // run a worker process. func setWorkerComm(cmd *exec.Cmd, comm workerComm) { mem := <-comm.memMu - memFD := mem.f.Fd() + memName := mem.f.Name() comm.memMu <- mem syscall.SetHandleInformation(syscall.Handle(comm.fuzzIn.Fd()), syscall.HANDLE_FLAG_INHERIT, 1) syscall.SetHandleInformation(syscall.Handle(comm.fuzzOut.Fd()), syscall.HANDLE_FLAG_INHERIT, 1) - syscall.SetHandleInformation(syscall.Handle(memFD), syscall.HANDLE_FLAG_INHERIT, 1) - cmd.Env = append(cmd.Env, fmt.Sprintf("GO_TEST_FUZZ_WORKER_HANDLES=%x,%x,%x", comm.fuzzIn.Fd(), comm.fuzzOut.Fd(), memFD)) + cmd.Env = append(cmd.Env, fmt.Sprintf("GO_TEST_FUZZ_WORKER_HANDLES=%x,%x,%q", comm.fuzzIn.Fd(), comm.fuzzOut.Fd(), memName)) } // getWorkerComm returns communication channels in the worker process. @@ -100,27 +103,21 @@ func getWorkerComm() (comm workerComm, err error) { if v == "" { return workerComm{}, fmt.Errorf("GO_TEST_FUZZ_WORKER_HANDLES not set") } - parts := strings.Split(v, ",") - if len(parts) != 3 { - return workerComm{}, fmt.Errorf("GO_TEST_FUZZ_WORKER_HANDLES has invalid value") - } - base := 16 - bitSize := 64 - handles := make([]syscall.Handle, len(parts)) - for i, s := range parts { - h, err := strconv.ParseInt(s, base, bitSize) - if err != nil { - return workerComm{}, fmt.Errorf("GO_TEST_FUZZ_WORKER_HANDLES has invalid value: %v", err) - } - handles[i] = syscall.Handle(h) + var fuzzInFD, fuzzOutFD uintptr + var memName string + if _, err := fmt.Sscanf(v, "%x,%x,%q", &fuzzInFD, &fuzzOutFD, &memName); err != nil { + return workerComm{}, fmt.Errorf("parsing GO_TEST_FUZZ_WORKER_HANDLES=%s: %v", v, err) } - fuzzIn := os.NewFile(uintptr(handles[0]), "fuzz_in") - fuzzOut := os.NewFile(uintptr(handles[1]), "fuzz_out") - tmpFile := os.NewFile(uintptr(handles[2]), "fuzz_mem") + fuzzIn := os.NewFile(fuzzInFD, "fuzz_in") + fuzzOut := os.NewFile(fuzzOutFD, "fuzz_out") + tmpFile, err := os.OpenFile(memName, os.O_RDWR, 0) + if err != nil { + return workerComm{}, fmt.Errorf("worker opening temp file: %w", err) + } fi, err := tmpFile.Stat() if err != nil { - return workerComm{}, err + return workerComm{}, fmt.Errorf("worker checking temp file size: %w", err) } size := int(fi.Size()) if int64(size) != fi.Size() { diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 1a590fad42..4ccf469d60 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -219,7 +219,7 @@ func (w *worker) start() (err error) { cmd := exec.Command(w.binPath, w.args...) cmd.Dir = w.dir - cmd.Env = w.env + cmd.Env = w.env[:len(w.env):len(w.env)] // copy on append to ensure workers don't overwrite each other. // TODO(jayconrod): set stdout and stderr to nil or buffer. A large number // of workers may be very noisy, but for now, this output is useful for // debugging. -- GitLab From 6ee1506769b24d99e27f9a6a9c99e9b7143112bf Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Wed, 17 Feb 2021 17:31:22 -0500 Subject: [PATCH 0049/2500] [dev.fuzz] internal/fuzz: fix deadlock with multiple workers CoordinateFuzzing now continues to run after discovering a crasher. It waits until all workers have terminated before returning. This fixes a deadlock that occurred when multiple workers discovered crashers concurrently. CoordinateFuzzing would receive one crasher, close doneC (telling workers to stop), then wait for workers to stop without receiving more crashers. Other workers would block sending crashers. Change-Id: I55a64aac0e6e43f5e36b9d03c15051c3d5debb20 Reviewed-on: https://go-review.googlesource.com/c/go/+/293369 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod Reviewed-by: Katie Hockman --- src/cmd/go/testdata/script/test_fuzz.txt | 8 +- .../go/testdata/script/test_fuzz_cache.txt | 2 +- .../go/testdata/script/test_fuzz_fuzztime.txt | 2 +- .../go/testdata/script/test_fuzz_match.txt | 6 +- .../script/test_fuzz_mutate_crash.txt | 30 ++++---- src/internal/fuzz/fuzz.go | 74 +++++++++---------- src/internal/fuzz/sys_posix.go | 2 +- src/internal/fuzz/worker.go | 3 +- 8 files changed, 60 insertions(+), 67 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt index f9783504ee..c8567b996f 100644 --- a/src/cmd/go/testdata/script/test_fuzz.txt +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -9,12 +9,12 @@ stdout FAIL # Test that fuzzing a fuzz target that returns without failing or calling # f.Fuzz fails and causes a non-zero exit status. -! go test -fuzz=Fuzz -fuzztime=5s -parallel=1 noop_fuzz_test.go +! go test -fuzz=Fuzz -fuzztime=5s noop_fuzz_test.go ! stdout ^ok stdout FAIL # Test that calling f.Error in a fuzz target causes a non-zero exit status. -! go test -fuzz=Fuzz -fuzztime=5s -parallel=1 error_fuzz_test.go +! go test -fuzz=Fuzz -fuzztime=5s error_fuzz_test.go ! stdout ^ok stdout FAIL @@ -29,12 +29,12 @@ stdout ^ok ! stdout FAIL # Test that successful fuzzing exits cleanly. -go test -fuzz=Fuzz -fuzztime=5s -parallel=1 success_fuzz_test.go +go test -fuzz=Fuzz -fuzztime=5s success_fuzz_test.go stdout ok ! stdout FAIL # Test that calling f.Fatal while fuzzing causes a non-zero exit status. -! go test -fuzz=Fuzz -fuzztime=5s -parallel=1 fatal_fuzz_test.go +! go test -fuzz=Fuzz -fuzztime=5s fatal_fuzz_test.go ! stdout ^ok stdout FAIL diff --git a/src/cmd/go/testdata/script/test_fuzz_cache.txt b/src/cmd/go/testdata/script/test_fuzz_cache.txt index b4f59271ea..21546a828b 100644 --- a/src/cmd/go/testdata/script/test_fuzz_cache.txt +++ b/src/cmd/go/testdata/script/test_fuzz_cache.txt @@ -10,7 +10,7 @@ exists $GOCACHE ! exists $GOCACHE/fuzz # Fuzzing should write interesting values to the cache. -go test -fuzz=FuzzY -fuzztime=5s -parallel=1 . +go test -fuzz=FuzzY -fuzztime=5s . go run ./contains_files $GOCACHE/fuzz/example.com/y/FuzzY # 'go clean -cache' should not delete the fuzz cache. diff --git a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt index 1da095f06c..15a0f86e93 100644 --- a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt +++ b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt @@ -7,7 +7,7 @@ go test # Fuzzing should exit 0 when after fuzztime, even if timeout is short. -go test -timeout=10ms -fuzz=FuzzFast -fuzztime=5s -parallel=1 +go test -timeout=10ms -fuzz=FuzzFast -fuzztime=5s # We should see the same behavior when invoking the test binary directly. go test -c diff --git a/src/cmd/go/testdata/script/test_fuzz_match.txt b/src/cmd/go/testdata/script/test_fuzz_match.txt index 4ea2fe2540..7b2216f3dd 100644 --- a/src/cmd/go/testdata/script/test_fuzz_match.txt +++ b/src/cmd/go/testdata/script/test_fuzz_match.txt @@ -7,12 +7,12 @@ go test standalone_fuzz_test.go stdout '^ok' # Matches only for fuzzing. -go test -fuzz Fuzz -fuzztime 5s -parallel 1 standalone_fuzz_test.go +go test -fuzz Fuzz -fuzztime 2s -parallel 4 standalone_fuzz_test.go ! stdout '^ok.*\[no tests to run\]' stdout '^ok' # Matches none for fuzzing but will run the fuzz target as a test. -go test -fuzz ThisWillNotMatch -fuzztime 5s -parallel 1 standalone_fuzz_test.go +go test -fuzz ThisWillNotMatch -fuzztime 2s -parallel 4 standalone_fuzz_test.go ! stdout '^ok.*\[no tests to run\]' stdout '^ok' stdout '\[no targets to fuzz\]' @@ -30,7 +30,7 @@ stdout '^ok.*\[no tests to run\]' ! stdout '\[no targets to fuzz\]' # Matches more than one fuzz target for fuzzing. -go test -fuzz Fuzz -fuzztime 5s -parallel 1 multiple_fuzz_test.go +go test -fuzz Fuzz -fuzztime 2s -parallel 4 multiple_fuzz_test.go # The tests should run, but not be fuzzed ! stdout '\[no tests to run\]' ! stdout '\[no targets to fuzz\]' diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt index 66e1cd8b76..bd9ce5c512 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt @@ -8,50 +8,48 @@ [short] skip -# TODO: remove -parallel=1 once the races are fixed. - # Running the seed corpus for all of the targets should pass the first # time, since nothing in the seed corpus will cause a crash. -go test -parallel=1 +go test # Running the fuzzer should find a crashing input quickly. -! go test -fuzz=FuzzWithBug -fuzztime=5s -parallel=1 +! go test -fuzz=FuzzWithBug -fuzztime=5s stdout 'testdata[/\\]corpus[/\\]FuzzWithBug[/\\]' stdout 'this input caused a crash!' go run check_testdata.go FuzzWithBug # Now, the failing bytes should have been added to the seed corpus for # the target, and should fail when run without fuzzing. -! go test -parallel=1 +! go test # Running the fuzzer should find a crashing input quickly for fuzzing two types. -! go test -run=FuzzWithTwoTypes -fuzz=FuzzWithTwoTypes -fuzztime=5s -parallel=1 +! go test -run=FuzzWithTwoTypes -fuzz=FuzzWithTwoTypes -fuzztime=5s stdout 'testdata[/\\]corpus[/\\]FuzzWithTwoTypes[/\\]' stdout 'these inputs caused a crash!' go run check_testdata.go FuzzWithTwoTypes -! go test -run=FuzzWithNilPanic -fuzz=FuzzWithNilPanic -fuzztime=5s -parallel=1 +! go test -run=FuzzWithNilPanic -fuzz=FuzzWithNilPanic -fuzztime=5s stdout 'testdata[/\\]corpus[/\\]FuzzWithNilPanic[/\\]' stdout 'runtime.Goexit' go run check_testdata.go FuzzWithNilPanic -! go test -run=FuzzWithFail -fuzz=FuzzWithFail -fuzztime=5s -parallel=1 +! go test -run=FuzzWithFail -fuzz=FuzzWithFail -fuzztime=5s stdout 'testdata[/\\]corpus[/\\]FuzzWithFail[/\\]' go run check_testdata.go FuzzWithFail -! go test -run=FuzzWithErrorf -fuzz=FuzzWithErrorf -fuzztime=5s -parallel=1 +! go test -run=FuzzWithErrorf -fuzz=FuzzWithErrorf -fuzztime=5s stdout 'testdata[/\\]corpus[/\\]FuzzWithErrorf[/\\]' # TODO: Uncomment this part of the test once it's fixed # stdout 'errorf was called here' go run check_testdata.go FuzzWithErrorf -! go test -run=FuzzWithFatalf -fuzz=FuzzWithFatalf -fuzztime=5s -parallel=1 +! go test -run=FuzzWithFatalf -fuzz=FuzzWithFatalf -fuzztime=5s stdout 'testdata[/\\]corpus[/\\]FuzzWithFatalf[/\\]' # TODO: Uncomment this part of the test once it's fixed # stdout 'fatalf was called here' go run check_testdata.go FuzzWithFatalf -! go test -run=FuzzWithBadExit -fuzz=FuzzWithBadExit -fuzztime=5s -parallel=1 +! go test -run=FuzzWithBadExit -fuzz=FuzzWithBadExit -fuzztime=5s stdout 'testdata[/\\]corpus[/\\]FuzzWithBadExit[/\\]' stdout 'unexpectedly' go run check_testdata.go FuzzWithBadExit @@ -154,8 +152,8 @@ func main() { os.Exit(1) } - if len(files) != 1 { - fmt.Fprintln(os.Stderr, fmt.Errorf("expect only one new mutation to be written to testdata", len(files))) + if len(files) == 0 { + fmt.Fprintf(os.Stderr, "expect at least one new mutation to be written to testdata\n") os.Exit(1) } @@ -166,13 +164,13 @@ func main() { os.Exit(1) } if bytes.Equal(contents, []byte("aa")) { - fmt.Fprintln(os.Stderr, fmt.Errorf("newly written testdata entry was not mutated")) + fmt.Fprintf(os.Stderr, "newly written testdata entry was not mutated\n") os.Exit(1) } // The hash of the bytes in the file should match the filename. h := []byte(fmt.Sprintf("%x", sha256.Sum256(contents))) if !bytes.Equal([]byte(fname), h) { - fmt.Fprintln(os.Stderr, fmt.Errorf("hash of bytes %q does not match filename %q", h, fname)) + fmt.Fprintf(os.Stderr, "hash of bytes %q does not match filename %q\n", h, fname) os.Exit(1) } -} \ No newline at end of file +} diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index b8405622df..9ae1eadaec 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -18,7 +18,6 @@ import ( "reflect" "runtime" "strings" - "sync" ) // CoordinateFuzzing creates several worker processes and communicates with @@ -82,8 +81,8 @@ func CoordinateFuzzing(ctx context.Context, parallel int, seed []CorpusEntry, ty inputC: make(chan CorpusEntry), interestingC: make(chan CorpusEntry), crasherC: make(chan crasherEntry), - errC: make(chan error), } + errC := make(chan error) newWorker := func() (*worker, error) { mem, err := sharedMemTempFile(sharedMemSize) @@ -102,6 +101,19 @@ func CoordinateFuzzing(ctx context.Context, parallel int, seed []CorpusEntry, ty }, nil } + var fuzzErr error + stopping := false + stop := func(err error) { + if fuzzErr == nil || fuzzErr == ctx.Err() { + fuzzErr = err + } + if stopping { + return + } + stopping = true + close(c.doneC) + } + // Start workers. workers := make([]*worker, parallel) for i := range workers { @@ -111,38 +123,22 @@ func CoordinateFuzzing(ctx context.Context, parallel int, seed []CorpusEntry, ty return err } } - - workerErrs := make([]error, len(workers)) - var wg sync.WaitGroup - wg.Add(len(workers)) for i := range workers { - go func(i int) { - defer wg.Done() - workerErrs[i] = workers[i].runFuzzing() - if cleanErr := workers[i].cleanup(); workerErrs[i] == nil { - workerErrs[i] = cleanErr + w := workers[i] + go func() { + err := w.runFuzzing() + cleanErr := w.cleanup() + if err == nil { + err = cleanErr } - }(i) + errC <- err + }() } - // Before returning, signal workers to stop, wait for them to actually stop, - // and gather any errors they encountered. - defer func() { - close(c.doneC) - wg.Wait() - if err == nil || err == ctx.Err() { - for _, werr := range workerErrs { - if werr != nil { - // Return the first error found, replacing ctx.Err() if a more - // interesting error is found. - err = werr - break - } - } - } - }() - // Main event loop. + // Do not return until all workers have terminated. We avoid a deadlock by + // receiving messages from workers even after closing c.doneC. + activeWorkers := len(workers) i := 0 for { select { @@ -152,7 +148,7 @@ func CoordinateFuzzing(ctx context.Context, parallel int, seed []CorpusEntry, ty // not the coordinator or worker processes. 'go test' will stop running // actions, but it won't interrupt its child processes. This makes it // difficult to stop fuzzing on Windows without a timeout. - return ctx.Err() + stop(ctx.Err()) case crasher := <-c.crasherC: // A worker found a crasher. Write it to testdata and return it. @@ -165,7 +161,7 @@ func CoordinateFuzzing(ctx context.Context, parallel int, seed []CorpusEntry, ty } // TODO(jayconrod,katiehockman): if -keepfuzzing, report the error to // the user and restart the crashed worker. - return err + stop(err) case entry := <-c.interestingC: // Some interesting input arrived from a worker. @@ -179,13 +175,17 @@ func CoordinateFuzzing(ctx context.Context, parallel int, seed []CorpusEntry, ty corpus.entries = append(corpus.entries, entry) if cacheDir != "" { if _, err := writeToCorpus(entry.Data, cacheDir); err != nil { - return err + stop(err) } } - case err := <-c.errC: - // A worker encountered a fatal error. - return err + case err := <-errC: + // A worker terminated, possibly after encountering a fatal error. + stop(err) + activeWorkers-- + if activeWorkers == 0 { + return fuzzErr + } case c.inputC <- corpus.entries[i]: // Send the next input to any worker. @@ -268,10 +268,6 @@ type coordinator struct { // should be saved in the corpus, and we may want to stop fuzzing after // receiving one. crasherC chan crasherEntry - - // errC is sent internal errors encountered by workers. When the coordinator - // receives an error, it closes doneC and returns. - errC chan error } // readCache creates a combined corpus from seed values and values in the cache diff --git a/src/internal/fuzz/sys_posix.go b/src/internal/fuzz/sys_posix.go index 3fbbb47869..8ea84d2025 100644 --- a/src/internal/fuzz/sys_posix.go +++ b/src/internal/fuzz/sys_posix.go @@ -88,5 +88,5 @@ func isInterruptError(err error) bool { return false } status := exitErr.Sys().(syscall.WaitStatus) - return status.Signal() == syscall.SIGINT + return status.Signal() == syscall.SIGINT || status.Signal() == syscall.SIGKILL } diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 4ccf469d60..d42044bb91 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -72,8 +72,7 @@ func (w *worker) runFuzzing() error { // Start the process. if err := w.start(); err != nil { // We couldn't start the worker process. We can't do anything, and it's - // likely that other workers can't either, so give up. - w.coordinator.errC <- err + // likely that other workers can't either, so don't try to restart. return err } -- GitLab From 32f45d13b2fa9ef8ae17e885c2d82d80a6d22caa Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Wed, 3 Mar 2021 14:16:07 -0500 Subject: [PATCH 0050/2500] [dev.fuzz] internal/fuzz: add minimization of []byte This works by minimizing for a maximum of one minute. We may consider making this customizable in the future. This only minimizes []byte inputs which caused a recoverable error. In the future, it should support minimizing other appopriate types, and minimizing types which caused non-recoverable errors (though this is much more expensive). The code in internal/fuzz/worker.go is copied from, or heavily inspired by, code originally authored by Dmitry Vyukov and Josh Bleecher Snyder as part of the go-fuzz project. Thanks to them for their contributions. See https://github.com/dvyukov/go-fuzz. Change-Id: I93dbac7ff874d6d0c1b9b9dda23930ae9921480c Reviewed-on: https://go-review.googlesource.com/c/go/+/298909 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- .../go/testdata/script/test_fuzz_mutator.txt | 39 +++++- src/internal/fuzz/worker.go | 117 +++++++++++++++++- 2 files changed, 149 insertions(+), 7 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_mutator.txt b/src/cmd/go/testdata/script/test_fuzz_mutator.txt index 4a33eba339..c5a7a86b84 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutator.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutator.txt @@ -14,11 +14,21 @@ go test -fuzz=FuzzA -fuzztime=5s -parallel=1 -log=fuzz go run check_logs.go fuzz fuzz.worker # Test that the mutator is good enough to find several unique mutations. -! go test -fuzz=Fuzz -parallel=1 -fuzztime=30s mutator_test.go +! go test -fuzz=FuzzMutator -parallel=1 -fuzztime=30s mutator_test.go ! stdout '^ok' stdout FAIL stdout 'mutator found enough unique mutations' +# Test that minimization is working. +! go test -fuzz=FuzzMinimizer -run=FuzzMinimizer -parallel=1 -fuzztime=5s minimizer_test.go +! stdout ok +# TODO(jayconrod,katiehockman): Once logging is fixed, add this test in. +# stdout 'got the minimum size!' +stdout FAIL + +# Test that re-running the minimized value causes a crash. +! go test -run=FuzzMinimizer minimizer_test.go + -- go.mod -- module m @@ -67,6 +77,31 @@ func FuzzB(f *testing.F) { }) } +-- minimizer_test.go -- +package fuzz_test + +import ( + "bytes" + "testing" +) + +func FuzzMinimizer(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + if len(b) < 100 { + // Make sure that b is large enough that it can be minimized + return + } + if len(b) == 100 { + t.Logf("got the minimum size!") + } + if bytes.ContainsAny(b, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") { + // Given the randomness of the mutations, this should allow the + // minimizer to trim down the value quite a bit. + t.Errorf("contains a letter") + } + }) +} + -- check_logs.go -- // +build ignore @@ -170,7 +205,7 @@ import ( // TODO(katiehockman): re-work this test once we have a better fuzzing engine // (ie. more mutations, and compiler instrumentation) -func Fuzz(f *testing.F) { +func FuzzMutator(f *testing.F) { // TODO(katiehockman): simplify this once we can dedupe crashes (e.g. // replace map with calls to panic, and simply count the number of crashes // that were added to testdata) diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index d42044bb91..70d76d6fc6 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -492,7 +492,7 @@ func (ws *workerServer) serve(ctx context.Context) error { // a given amount of time. fuzz returns early if it finds an input that crashes // the fuzz function or an input that expands coverage. func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) fuzzResponse { - ctx, cancel := context.WithTimeout(ctx, args.Duration) + fuzzCtx, cancel := context.WithTimeout(ctx, args.Duration) defer cancel() mem := <-ws.memMu defer func() { ws.memMu <- mem }() @@ -503,16 +503,19 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) fuzzResponse { } for { select { - case <-ctx.Done(): + case <-fuzzCtx.Done(): // TODO(jayconrod,katiehockman): this value is not interesting. Use a // real heuristic once we have one. return fuzzResponse{Interesting: true} default: vals = ws.m.mutate(vals, cap(mem.valueRef())) - b := marshalCorpusFile(vals...) - mem.setValueLen(len(b)) - mem.setValue(b) + writeToMem(vals, mem) if err := ws.fuzzFn(CorpusEntry{Values: vals}); err != nil { + if minErr := ws.minimize(ctx, vals, mem); minErr != nil { + // Minimization found a different error, so use that one. + writeToMem(vals, mem) + err = minErr + } return fuzzResponse{Crashed: true, Err: err.Error()} } // TODO(jayconrod,katiehockman): return early if we find an @@ -521,6 +524,110 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) fuzzResponse { } } +// minimizeInput applies a series of minimizing transformations on the provided +// vals, ensuring that each minimization still causes an error in fuzzFn. Before +// every call to fuzzFn, it marshals the new vals and writes it to the provided +// mem just in case an unrecoverable error occurs. It runs for a maximum of one +// minute, and returns the last error it found. +func (ws *workerServer) minimize(ctx context.Context, vals []interface{}, mem *sharedMem) error { + // TODO(jayconrod,katiehockman): consider making the maximum minimization + // time customizable with a go command flag. + ctx, cancel := context.WithTimeout(ctx, time.Minute) + defer cancel() + var retErr error + + // tryMinimized will run the fuzz function for the values in vals at the + // time the function is called. If err is nil, then the minimization was + // unsuccessful, since we expect an error to still occur. + tryMinimized := func(i int, prevVal interface{}) error { + err := ws.fuzzFn(CorpusEntry{Values: vals}) + if err == nil { + // The fuzz function succeeded, so return the value at index i back + // to the previously failing input. + vals[i] = prevVal + } else { + // The fuzz function failed, so save the most recent error. + retErr = err + } + return err + } + for valI := range vals { + switch v := vals[valI].(type) { + case bool, byte, rune: + continue // can't minimize + case string, int, int8, int16, int64, uint, uint16, uint32, uint64, float32, float64: + // TODO(jayconrod,katiehockman): support minimizing other types + case []byte: + // First, try to cut the tail. + for n := 1024; n != 0; n /= 2 { + for len(v) > n { + if ctx.Done() != nil { + return retErr + } + vals[valI] = v[:len(v)-n] + if tryMinimized(valI, v) != nil { + break + } + // Set v to the new value to continue iterating. + v = v[:len(v)-n] + } + } + + // Then, try to remove each individual byte. + tmp := make([]byte, len(v)) + for i := 0; i < len(v)-1; i++ { + if ctx.Done() != nil { + return retErr + } + candidate := tmp[:len(v)-1] + copy(candidate[:i], v[:i]) + copy(candidate[i:], v[i+1:]) + vals[valI] = candidate + if tryMinimized(valI, v) != nil { + continue + } + // Update v to delete the value at index i. + copy(v[i:], v[i+1:]) + v = v[:len(candidate)] + // v[i] is now different, so decrement i to redo this iteration + // of the loop with the new value. + i-- + } + + // Then, try to remove each possible subset of bytes. + for i := 0; i < len(v)-1; i++ { + copy(tmp, v[:i]) + for j := len(v); j > i+1; j-- { + if ctx.Done() != nil { + return retErr + } + candidate := tmp[:len(v)-j+i] + copy(candidate[i:], v[j:]) + vals[valI] = candidate + if tryMinimized(valI, v) != nil { + continue + } + // Update v and reset the loop with the new length. + copy(v[i:], v[j:]) + v = v[:len(candidate)] + j = len(v) + } + } + // TODO(jayconrod,katiehockman): consider adding canonicalization + // which replaces each individual byte with '0' + default: + panic("unreachable") + } + } + return retErr +} + +func writeToMem(vals []interface{}, mem *sharedMem) { + b := marshalCorpusFile(vals...) + mem.setValueLen(len(b)) + mem.setValue(b) +} + // ping does nothing. The coordinator calls this method to ensure the worker // has called F.Fuzz and can communicate. func (ws *workerServer) ping(ctx context.Context, args pingArgs) pingResponse { -- GitLab From 9d4d5ee66dc53f6640dd8f5333df69db4df3b044 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Thu, 4 Mar 2021 14:53:18 -0500 Subject: [PATCH 0051/2500] [dev.fuzz] testing: print logs and error messages when fuzzing Also improve the error messages for the use of testing.F functions inside the Fuzz function. Change-Id: I5fa48f8c7e0460a1da89a49a73e5af83c544e549 Reviewed-on: https://go-review.googlesource.com/c/go/+/298849 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- .../script/test_fuzz_mutate_crash.txt | 21 +++++++-- src/internal/fuzz/worker.go | 2 +- src/testing/fuzz.go | 44 ++++++++++++------- src/testing/testing.go | 1 + 4 files changed, 46 insertions(+), 22 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt index bd9ce5c512..a143edda08 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt @@ -37,16 +37,19 @@ go run check_testdata.go FuzzWithNilPanic stdout 'testdata[/\\]corpus[/\\]FuzzWithFail[/\\]' go run check_testdata.go FuzzWithFail +! go test -run=FuzzWithLogFail -fuzz=FuzzWithLogFail -fuzztime=5s +stdout 'testdata[/\\]corpus[/\\]FuzzWithLogFail[/\\]' +stdout 'logged something' +go run check_testdata.go FuzzWithLogFail + ! go test -run=FuzzWithErrorf -fuzz=FuzzWithErrorf -fuzztime=5s stdout 'testdata[/\\]corpus[/\\]FuzzWithErrorf[/\\]' -# TODO: Uncomment this part of the test once it's fixed -# stdout 'errorf was called here' +stdout 'errorf was called here' go run check_testdata.go FuzzWithErrorf ! go test -run=FuzzWithFatalf -fuzz=FuzzWithFatalf -fuzztime=5s stdout 'testdata[/\\]corpus[/\\]FuzzWithFatalf[/\\]' -# TODO: Uncomment this part of the test once it's fixed -# stdout 'fatalf was called here' +stdout 'fatalf was called here' go run check_testdata.go FuzzWithFatalf ! go test -run=FuzzWithBadExit -fuzz=FuzzWithBadExit -fuzztime=5s @@ -93,6 +96,16 @@ func FuzzWithFail(f *testing.F) { }) } +func FuzzWithLogFail(f *testing.F) { + f.Add([]byte("aa")) + f.Fuzz(func(t *testing.T, b []byte) { + if string(b) != "aa" { + t.Log("logged something") + t.Fail() + } + }) +} + func FuzzWithErrorf(f *testing.F) { f.Add([]byte("aa")) f.Fuzz(func(t *testing.T, b []byte) { diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 70d76d6fc6..3fe5aebbf4 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -137,7 +137,7 @@ func (w *worker) runFuzzing() error { mem := <-w.memMu value := mem.valueCopy() w.memMu <- mem - message := fmt.Sprintf("fuzzing process terminated unexpectedly: %v", w.waitErr) + message := fmt.Sprintf("fuzzing process terminated unexpectedly: %v\n", w.waitErr) crasher := crasherEntry{ CorpusEntry: CorpusEntry{Data: value}, errMsg: message, diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index c855379566..2a0754fdd7 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -73,7 +73,7 @@ type corpusEntry = struct { // first called order. func (f *F) Cleanup(fn func()) { if f.inFuzzFn { - panic("testing: f.Cleanup was called inside the f.Fuzz function") + panic("testing: f.Cleanup was called inside the f.Fuzz function, use t.Cleanup instead") } f.common.Helper() f.common.Cleanup(fn) @@ -82,7 +82,7 @@ func (f *F) Cleanup(fn func()) { // Error is equivalent to Log followed by Fail. func (f *F) Error(args ...interface{}) { if f.inFuzzFn { - panic("testing: f.Error was called inside the f.Fuzz function") + panic("testing: f.Error was called inside the f.Fuzz function, use t.Error instead") } f.common.Helper() f.common.Error(args...) @@ -91,7 +91,7 @@ func (f *F) Error(args ...interface{}) { // Errorf is equivalent to Logf followed by Fail. func (f *F) Errorf(format string, args ...interface{}) { if f.inFuzzFn { - panic("testing: f.Errorf was called inside the f.Fuzz function") + panic("testing: f.Errorf was called inside the f.Fuzz function, use t.Errorf instead") } f.common.Helper() f.common.Errorf(format, args...) @@ -100,7 +100,7 @@ func (f *F) Errorf(format string, args ...interface{}) { // Fail marks the function as having failed but continues execution. func (f *F) Fail() { if f.inFuzzFn { - panic("testing: f.Fail was called inside the f.Fuzz function") + panic("testing: f.Fail was called inside the f.Fuzz function, use t.Fail instead") } f.common.Helper() f.common.Fail() @@ -116,7 +116,7 @@ func (f *F) Fail() { // those other goroutines. func (f *F) FailNow() { if f.inFuzzFn { - panic("testing: f.FailNow was called inside the f.Fuzz function") + panic("testing: f.FailNow was called inside the f.Fuzz function, use t.FailNow instead") } f.common.Helper() f.common.FailNow() @@ -125,7 +125,7 @@ func (f *F) FailNow() { // Fatal is equivalent to Log followed by FailNow. func (f *F) Fatal(args ...interface{}) { if f.inFuzzFn { - panic("testing: f.Fatal was called inside the f.Fuzz function") + panic("testing: f.Fatal was called inside the f.Fuzz function, use t.Fatal instead") } f.common.Helper() f.common.Fatal(args...) @@ -134,7 +134,7 @@ func (f *F) Fatal(args ...interface{}) { // Fatalf is equivalent to Logf followed by FailNow. func (f *F) Fatalf(format string, args ...interface{}) { if f.inFuzzFn { - panic("testing: f.Fatalf was called inside the f.Fuzz function") + panic("testing: f.Fatalf was called inside the f.Fuzz function, use t.Fatalf instead") } f.common.Helper() f.common.Fatalf(format, args...) @@ -145,7 +145,7 @@ func (f *F) Fatalf(format string, args ...interface{}) { // Helper may be called simultaneously from multiple goroutines. func (f *F) Helper() { if f.inFuzzFn { - panic("testing: f.Helper was called inside the f.Fuzz function") + panic("testing: f.Helper was called inside the f.Fuzz function, use t.Helper instead") } // common.Helper is inlined here. @@ -171,7 +171,7 @@ func (f *F) Helper() { // Skip is equivalent to Log followed by SkipNow. func (f *F) Skip(args ...interface{}) { if f.inFuzzFn { - panic("testing: f.Skip was called inside the f.Fuzz function") + panic("testing: f.Skip was called inside the f.Fuzz function, use t.Skip instead") } f.common.Helper() f.common.Skip(args...) @@ -187,7 +187,7 @@ func (f *F) Skip(args ...interface{}) { // those other goroutines. func (f *F) SkipNow() { if f.inFuzzFn { - panic("testing: f.SkipNow was called inside the f.Fuzz function") + panic("testing: f.SkipNow was called inside the f.Fuzz function, use t.SkipNow instead") } f.common.Helper() f.common.SkipNow() @@ -196,7 +196,7 @@ func (f *F) SkipNow() { // Skipf is equivalent to Logf followed by SkipNow. func (f *F) Skipf(format string, args ...interface{}) { if f.inFuzzFn { - panic("testing: f.Skipf was called inside the f.Fuzz function") + panic("testing: f.Skipf was called inside the f.Fuzz function, use t.Skipf instead") } f.common.Helper() f.common.Skipf(format, args...) @@ -209,7 +209,7 @@ func (f *F) Skipf(format string, args ...interface{}) { // if the directory creation fails, TempDir terminates the test by calling Fatal. func (f *F) TempDir() string { if f.inFuzzFn { - panic("testing: f.TempDir was called inside the f.Fuzz function") + panic("testing: f.TempDir was called inside the f.Fuzz function, use t.TempDir instead") } f.common.Helper() return f.common.TempDir() @@ -299,6 +299,11 @@ func (f *F) Fuzz(ff interface{}) { // // TODO(jayconrod,katiehockman): dedupe testdata corpus with entries from f.Add // TODO(jayconrod,katiehockman): handle T.Parallel calls within fuzz function. + // TODO(jayconrod,katiehockman): improve output when running the subtest. + // e.g. instead of + // --- FAIL: FuzzSomethingError/#00 (0.00s) + // do + // --- FAIL: FuzzSomethingError/ (0.00s) run := func(e corpusEntry) error { if e.Values == nil { // Every code path should have already unmarshaled Data into Values. @@ -341,7 +346,7 @@ func (f *F) Fuzz(ff interface{}) { <-t.signal f.inFuzzFn = false if t.Failed() { - return errors.New(string(t.output)) + return errors.New(string(f.output)) } return nil } @@ -356,11 +361,12 @@ func (f *F) Fuzz(ff interface{}) { err := f.fuzzContext.coordinateFuzzing(*fuzzDuration, *parallel, f.corpus, types, corpusTargetDir, cacheTargetDir) if err != nil { f.result = FuzzResult{Error: err} - f.Error(err) + f.Fail() + fmt.Fprintf(f.w, "%v", err) if crashErr, ok := err.(fuzzCrashError); ok { crashName := crashErr.CrashName() - f.Logf("Crash written to %s", filepath.Join("testdata/corpus", f.name, crashName)) - f.Logf("To re-run:\ngo test %s -run=%s/%s", f.fuzzContext.importPath(), f.name, crashName) + fmt.Fprintf(f.w, "Crash written to %s\n", filepath.Join("testdata/corpus", f.name, crashName)) + fmt.Fprintf(f.w, "To re-run:\ngo test %s -run=%s/%s\n", f.fuzzContext.importPath(), f.name, crashName) } } // TODO(jayconrod,katiehockman): Aggregate statistics across workers @@ -377,7 +383,8 @@ func (f *F) Fuzz(ff interface{}) { } default: - // Fuzzing is not enabled. Only run the seed corpus. + // Fuzzing is not enabled, or will be done later. Only run the seed + // corpus now. for _, e := range f.corpus { run(e) } @@ -505,6 +512,9 @@ func runFuzzTargets(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran, ok bo // If fuzzing is disabled (-test.fuzz is not set), runFuzzing // returns immediately. func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran, ok bool) { + // TODO(katiehockman,jayconrod): Should we do something special to make sure + // we don't print f.Log statements again with runFuzzing, since we already + // would have printed them when we ran runFuzzTargets (ie. seed corpus run)? if len(fuzzTargets) == 0 || *matchFuzz == "" { return false, true } diff --git a/src/testing/testing.go b/src/testing/testing.go index 2ad39f7137..2ba93ad63d 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -523,6 +523,7 @@ func (c *common) frameSkip(skip int) runtime.Frame { // and inserts the final newline if needed and indentation spaces for formatting. // This function must be called with c.mu held. func (c *common) decorate(s string, skip int) string { + // TODO(jayconrod,katiehockman): Consider refactoring the logging logic. // If more helper PCs have been added since we last did the conversion if c.helperNames == nil { c.helperNames = make(map[string]struct{}) -- GitLab From b975d0baa0e0d4a733c4f5ff86ed81514deb53b2 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Thu, 1 Apr 2021 17:51:18 -0400 Subject: [PATCH 0052/2500] [dev.fuzz] internal/fuzz: reduce allocation in the mutator When mutating a byte slice, mutate in place, and only allocate once if the slice's capacity is less than the maximum size. mutateBytes already should not allocate; we check a post-condition that the slice's data pointer does not change. This speeds up the mutator from 4 ms per value to 200-600 ns. For example: goos: darwin goarch: amd64 pkg: internal/fuzz cpu: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz BenchmarkMutatorBytes/1-8 5908735 275.3 ns/op BenchmarkMutatorBytes/10-8 5198473 282.0 ns/op BenchmarkMutatorBytes/100-8 4304750 233.9 ns/op BenchmarkMutatorBytes/1000-8 4623988 295.2 ns/op BenchmarkMutatorBytes/10000-8 4252104 458.5 ns/op BenchmarkMutatorBytes/100000-8 1236751 950.8 ns/op PASS ok internal/fuzz 12.993s Change-Id: I4bf2a04be6c648ef440af2c62bf0ffa3d310172c Reviewed-on: https://go-review.googlesource.com/c/go/+/306675 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod Reviewed-by: Katie Hockman --- src/internal/fuzz/fuzz.go | 3 +-- src/internal/fuzz/mutator.go | 13 ++++++------- src/internal/fuzz/mutator_test.go | 30 ++++++++++++++++++++++++++++++ src/internal/fuzz/worker.go | 6 +++++- 4 files changed, 42 insertions(+), 10 deletions(-) create mode 100644 src/internal/fuzz/mutator_test.go diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 9ae1eadaec..8e0425c0c4 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -51,7 +51,6 @@ func CoordinateFuzzing(ctx context.Context, parallel int, seed []CorpusEntry, ty parallel = runtime.GOMAXPROCS(0) } - sharedMemSize := 100 << 20 // 100 MB // Make sure all of the seed corpus has marshalled data. for i := range seed { if seed[i].Data == nil { @@ -85,7 +84,7 @@ func CoordinateFuzzing(ctx context.Context, parallel int, seed []CorpusEntry, ty errC := make(chan error) newWorker := func() (*worker, error) { - mem, err := sharedMemTempFile(sharedMemSize) + mem, err := sharedMemTempFile(workerSharedMemSize) if err != nil { return nil, err } diff --git a/src/internal/fuzz/mutator.go b/src/internal/fuzz/mutator.go index 584c21e8ae..aa72972147 100644 --- a/src/internal/fuzz/mutator.go +++ b/src/internal/fuzz/mutator.go @@ -51,8 +51,7 @@ func min(a, b int) int { } // mutate performs several mutations on the provided values. -func (m *mutator) mutate(vals []interface{}, maxBytes int) []interface{} { - // TODO(jayconrod,katiehockman): use as few allocations as possible +func (m *mutator) mutate(vals []interface{}, maxBytes int) { // TODO(katiehockman): pull some of these functions into helper methods and // test that each case is working as expected. // TODO(katiehockman): perform more types of mutations. @@ -71,11 +70,11 @@ func (m *mutator) mutate(vals []interface{}, maxBytes int) []interface{} { if len(v) > maxPerVal { panic(fmt.Sprintf("cannot mutate bytes of length %d", len(v))) } - b := make([]byte, 0, maxPerVal) - b = append(b, v...) - m.mutateBytes(&b) - vals[i] = b - return vals + if cap(v) < maxPerVal { + v = append(make([]byte, 0, maxPerVal), v...) + } + m.mutateBytes(&v) + vals[i] = v default: panic(fmt.Sprintf("type not supported for mutating: %T", vals[i])) } diff --git a/src/internal/fuzz/mutator_test.go b/src/internal/fuzz/mutator_test.go new file mode 100644 index 0000000000..b1b5311639 --- /dev/null +++ b/src/internal/fuzz/mutator_test.go @@ -0,0 +1,30 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fuzz + +import ( + "strconv" + "testing" +) + +func BenchmarkMutatorBytes(b *testing.B) { + for _, size := range []int{ + 1, + 10, + 100, + 1000, + 10000, + 100000, + } { + size := size + b.Run(strconv.Itoa(size), func(b *testing.B) { + vals := []interface{}{make([]byte, size)} + m := newMutator() + for i := 0; i < b.N; i++ { + m.mutate(vals, workerSharedMemSize) + } + }) + } +} diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 3fe5aebbf4..243a12baef 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -31,6 +31,10 @@ const ( // This distinguishes internal errors from uncontrolled panics and other crashes. // Keep in sync with internal/fuzz.workerExitCode. workerExitCode = 70 + + // workerSharedMemSize is the maximum size of the shared memory file used to + // communicate with workers. This limits the size of fuzz inputs. + workerSharedMemSize = 100 << 20 // 100 MB ) // worker manages a worker process running a test binary. The worker object @@ -508,7 +512,7 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) fuzzResponse { // real heuristic once we have one. return fuzzResponse{Interesting: true} default: - vals = ws.m.mutate(vals, cap(mem.valueRef())) + ws.m.mutate(vals, cap(mem.valueRef())) writeToMem(vals, mem) if err := ws.fuzzFn(CorpusEntry{Values: vals}); err != nil { if minErr := ws.minimize(ctx, vals, mem); minErr != nil { -- GitLab From 161439fec01692d4111fd4bd0eb0d3416ec8d594 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Tue, 6 Apr 2021 15:33:55 -0400 Subject: [PATCH 0053/2500] [dev.fuzz] internal/fuzz: small bug fixes and refactors to minimization This fixes a few issues that were being masked since log statements weren't being printed to stdout. Now that they are, fix the bugs, and update the tests. Also includes a few small refactors which will make minimizing non-recoverable errors easier. Change-Id: Ie2fd2e5534b3980317e1e1f3fd8e04750988c17f Reviewed-on: https://go-review.googlesource.com/c/go/+/307810 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- .../go/testdata/script/test_fuzz_mutator.txt | 14 ++++----- src/internal/fuzz/worker.go | 31 ++++++++++--------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_mutator.txt b/src/cmd/go/testdata/script/test_fuzz_mutator.txt index c5a7a86b84..8ec73bf35e 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutator.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutator.txt @@ -19,15 +19,15 @@ go run check_logs.go fuzz fuzz.worker stdout FAIL stdout 'mutator found enough unique mutations' -# Test that minimization is working. -! go test -fuzz=FuzzMinimizer -run=FuzzMinimizer -parallel=1 -fuzztime=5s minimizer_test.go -! stdout ok -# TODO(jayconrod,katiehockman): Once logging is fixed, add this test in. -# stdout 'got the minimum size!' +# Test that minimization is working for recoverable errors. +! go test -v -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -parallel=1 -fuzztime=10s minimizer_test.go +! stdout '^ok' +stdout 'got the minimum size!' +stdout 'contains a letter' stdout FAIL # Test that re-running the minimized value causes a crash. -! go test -run=FuzzMinimizer minimizer_test.go +! go test -run=FuzzMinimizerRecoverable minimizer_test.go -- go.mod -- module m @@ -85,7 +85,7 @@ import ( "testing" ) -func FuzzMinimizer(f *testing.F) { +func FuzzMinimizerRecoverable(f *testing.F) { f.Fuzz(func(t *testing.T, b []byte) { if len(b) < 100 { // Make sure that b is large enough that it can be minimized diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 243a12baef..506a485f24 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -515,9 +515,12 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) fuzzResponse { ws.m.mutate(vals, cap(mem.valueRef())) writeToMem(vals, mem) if err := ws.fuzzFn(CorpusEntry{Values: vals}); err != nil { - if minErr := ws.minimize(ctx, vals, mem); minErr != nil { + // TODO(jayconrod,katiehockman): consider making the maximum minimization + // time customizable with a go command flag. + minCtx, minCancel := context.WithTimeout(ctx, time.Minute) + defer minCancel() + if minErr := ws.minimize(minCtx, vals, mem); minErr != nil { // Minimization found a different error, so use that one. - writeToMem(vals, mem) err = minErr } return fuzzResponse{Crashed: true, Err: err.Error()} @@ -528,22 +531,20 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) fuzzResponse { } } -// minimizeInput applies a series of minimizing transformations on the provided +// minimize applies a series of minimizing transformations on the provided // vals, ensuring that each minimization still causes an error in fuzzFn. Before // every call to fuzzFn, it marshals the new vals and writes it to the provided // mem just in case an unrecoverable error occurs. It runs for a maximum of one // minute, and returns the last error it found. -func (ws *workerServer) minimize(ctx context.Context, vals []interface{}, mem *sharedMem) error { - // TODO(jayconrod,katiehockman): consider making the maximum minimization - // time customizable with a go command flag. - ctx, cancel := context.WithTimeout(ctx, time.Minute) - defer cancel() - var retErr error +func (ws *workerServer) minimize(ctx context.Context, vals []interface{}, mem *sharedMem) (retErr error) { + // Make sure the last crashing value is written to mem. + defer writeToMem(vals, mem) // tryMinimized will run the fuzz function for the values in vals at the // time the function is called. If err is nil, then the minimization was // unsuccessful, since we expect an error to still occur. tryMinimized := func(i int, prevVal interface{}) error { + writeToMem(vals, mem) // write to mem in case a non-recoverable crash occurs err := ws.fuzzFn(CorpusEntry{Values: vals}) if err == nil { // The fuzz function succeeded, so return the value at index i back @@ -565,11 +566,11 @@ func (ws *workerServer) minimize(ctx context.Context, vals []interface{}, mem *s // First, try to cut the tail. for n := 1024; n != 0; n /= 2 { for len(v) > n { - if ctx.Done() != nil { + if ctx.Err() != nil { return retErr } vals[valI] = v[:len(v)-n] - if tryMinimized(valI, v) != nil { + if tryMinimized(valI, v) == nil { break } // Set v to the new value to continue iterating. @@ -580,14 +581,14 @@ func (ws *workerServer) minimize(ctx context.Context, vals []interface{}, mem *s // Then, try to remove each individual byte. tmp := make([]byte, len(v)) for i := 0; i < len(v)-1; i++ { - if ctx.Done() != nil { + if ctx.Err() != nil { return retErr } candidate := tmp[:len(v)-1] copy(candidate[:i], v[:i]) copy(candidate[i:], v[i+1:]) vals[valI] = candidate - if tryMinimized(valI, v) != nil { + if tryMinimized(valI, v) == nil { continue } // Update v to delete the value at index i. @@ -602,13 +603,13 @@ func (ws *workerServer) minimize(ctx context.Context, vals []interface{}, mem *s for i := 0; i < len(v)-1; i++ { copy(tmp, v[:i]) for j := len(v); j > i+1; j-- { - if ctx.Done() != nil { + if ctx.Err() != nil { return retErr } candidate := tmp[:len(v)-j+i] copy(candidate[i:], v[j:]) vals[valI] = candidate - if tryMinimized(valI, v) != nil { + if tryMinimized(valI, v) == nil { continue } // Update v and reset the loop with the new length. -- GitLab From 06a7c848d9e3c2804e6d84aeaf777e76df4e5bea Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Wed, 7 Apr 2021 17:40:39 -0400 Subject: [PATCH 0054/2500] [dev.fuzz] internal/fuzz: add stub for coverage This change only includes a stub for the function which will hook into the runtime to expose coverage instrumentation while we're fuzzing. Previously, we discussed an exported API named FuzzCoverage, but since this is within the internal/fuzz package, simply naming it coverage seems appropriate. Change-Id: Iba3240e53e0c4c434e937aa9bb1711a44fec9975 Reviewed-on: https://go-review.googlesource.com/c/go/+/308191 Trust: Katie Hockman Run-TryBot: Katie Hockman Reviewed-by: Matthew Dempsky Reviewed-by: Jay Conrod --- src/internal/fuzz/coverage.go | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/internal/fuzz/coverage.go diff --git a/src/internal/fuzz/coverage.go b/src/internal/fuzz/coverage.go new file mode 100644 index 0000000000..7624b56e0a --- /dev/null +++ b/src/internal/fuzz/coverage.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fuzz + +// coverage returns a []byte containing unique 8-bit counters for each edge of +// the instrumented source code. This coverage data will only be generated if +// `-d=libfuzzer` is set at build time. This can be used to understand the code +// coverage of a test execution. +func coverage() []byte { return nil } -- GitLab From 2f3bc725fe80e1ba3ef726e412c212d533a43684 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Wed, 7 Apr 2021 16:28:13 -0400 Subject: [PATCH 0055/2500] [dev.fuzz] internal/fuzz: add mutator for int types Assuming this works, will follow up with another CL that mutates other types. Change-Id: Id61acaacd56ca41e3be52e400f8f768672313bbb Reviewed-on: https://go-review.googlesource.com/c/go/+/308169 Trust: Katie Hockman Trust: Jay Conrod Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- .../script/test_fuzz_mutate_crash.txt | 14 ++++++ src/internal/fuzz/mutator.go | 48 +++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt index a143edda08..57db788436 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt @@ -28,6 +28,12 @@ stdout 'testdata[/\\]corpus[/\\]FuzzWithTwoTypes[/\\]' stdout 'these inputs caused a crash!' go run check_testdata.go FuzzWithTwoTypes +# Running the fuzzer should find a crashing input quickly for an integer +! go test -run=FuzzInt -fuzz=FuzzInt -fuzztime=5s +stdout 'testdata[/\\]corpus[/\\]FuzzInt[/\\]' +stdout 'this input caused a crash!' +go run check_testdata.go FuzzInt + ! go test -run=FuzzWithNilPanic -fuzz=FuzzWithNilPanic -fuzztime=5s stdout 'testdata[/\\]corpus[/\\]FuzzWithNilPanic[/\\]' stdout 'runtime.Goexit' @@ -132,6 +138,14 @@ func FuzzWithTwoTypes(f *testing.F) { }) } +func FuzzInt(f *testing.F) { + f.Fuzz(func(t *testing.T, a int) { + if 200 > a && a < 250 { + panic("this input caused a crash!") + } + }) +} + func FuzzWithBadExit(f *testing.F) { f.Add([]byte("aa")) f.Fuzz(func(t *testing.T, b []byte) { diff --git a/src/internal/fuzz/mutator.go b/src/internal/fuzz/mutator.go index aa72972147..e4ee2f44ea 100644 --- a/src/internal/fuzz/mutator.go +++ b/src/internal/fuzz/mutator.go @@ -7,6 +7,7 @@ package fuzz import ( "encoding/binary" "fmt" + "math" "reflect" "unsafe" ) @@ -75,11 +76,53 @@ func (m *mutator) mutate(vals []interface{}, maxBytes int) { } m.mutateBytes(&v) vals[i] = v + case int8: + vals[i] = int8(m.mutateInt(int64(v), math.MaxInt8)) + case int16: + vals[i] = int16(m.mutateInt(int64(v), math.MaxInt16)) + case int32: + vals[i] = int32(m.mutateInt(int64(v), math.MaxInt32)) + case int64: + vals[i] = m.mutateInt(v, int64(maxInt)) + case int: + vals[i] = int(m.mutateInt(int64(v), int64(maxInt))) default: panic(fmt.Sprintf("type not supported for mutating: %T", vals[i])) } } +func (m *mutator) mutateInt(v, maxValue int64) int64 { + numIters := 1 + m.r.exp2() + var max int64 + for iter := 0; iter < numIters; iter++ { + switch m.rand(2) { + case 0: + // Add a random number + if v >= maxValue { + continue + } + max = 100 + if v > 0 && maxValue-v < max { + // Don't let v exceed maxValue + max = maxValue - v + } + v += int64(m.rand(int(max))) + case 1: + // Subtract a random number + if v <= -maxValue { + continue + } + max = 100 + if v < 0 && maxValue+v < max { + // Don't let v drop below -maxValue + max = maxValue + v + } + v -= int64(m.rand(int(max))) + } + } + return v +} + func (m *mutator) mutateBytes(ptrB *[]byte) { b := *ptrB defer func() { @@ -267,6 +310,11 @@ var ( interesting32 = []int32{-2147483648, -100663046, -32769, 32768, 65535, 65536, 100663045, 2147483647} ) +const ( + maxUint = ^uint(0) + maxInt = maxUint >> 1 +) + func init() { for _, v := range interesting8 { interesting16 = append(interesting16, int16(v)) -- GitLab From 74f49f3366826f95a464cc15838a0668c92e3357 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 7 Apr 2021 17:11:48 -0700 Subject: [PATCH 0056/2500] [dev.fuzz] internal/fuzz: implement coverage and trace instrumentation This CL makes two main changes to allow internal/fuzz to support -d=libfuzzer instrumentation: 1. It extends cmd/link to define _counters and _ecounters symbols so internal/fuzz can find the coverage counters. 2. It adds "trace" stub functions that implement the ABI expected by cmd/compile for comparison instrumentation. N.B., that -tags=libfuzzer should *not* be set, so that internal/fuzz's trace routines will be used instead of runtime's libfuzzer trampolines. Also, the current implementation doesn't support multi-module builds (i.e., compiling a Go program that spans multiple .so/.dll files). Presumably this isn't an issue, since "go test -fuzz" will need to recompile the binary with instrumentation anyway so it can make sure to always use a single-module build. But we can revisit this if necessary. Change-Id: I9b1619119ab7477bebcfd5988b4b60499a7ab0d7 Reviewed-on: https://go-review.googlesource.com/c/go/+/308289 Trust: Matthew Dempsky Trust: Katie Hockman Reviewed-by: Katie Hockman Reviewed-by: Jay Conrod Reviewed-by: Cherry Zhang Run-TryBot: Katie Hockman TryBot-Result: Go Bot --- src/cmd/link/internal/ld/data.go | 24 ++++++++++++++++-------- src/internal/fuzz/coverage.go | 23 ++++++++++++++++++++++- src/internal/fuzz/trace.go | 29 +++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 src/internal/fuzz/trace.go diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 92d38bb63e..a089caa1a9 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -1746,7 +1746,9 @@ func (state *dodataState) allocateDataSections(ctxt *Link) { // Coverage instrumentation counters for libfuzzer. if len(state.data[sym.SLIBFUZZER_EXTRA_COUNTER]) > 0 { - state.allocateNamedSectionAndAssignSyms(&Segdata, "__libfuzzer_extra_counters", sym.SLIBFUZZER_EXTRA_COUNTER, sym.Sxxx, 06) + sect := state.allocateNamedSectionAndAssignSyms(&Segdata, "__libfuzzer_extra_counters", sym.SLIBFUZZER_EXTRA_COUNTER, sym.Sxxx, 06) + ldr.SetSymSect(ldr.LookupOrCreateSym("internal/fuzz._counters", 0), sect) + ldr.SetSymSect(ldr.LookupOrCreateSym("internal/fuzz._ecounters", 0), sect) } if len(state.data[sym.STLSBSS]) > 0 { @@ -2410,6 +2412,7 @@ func (ctxt *Link) address() []*sym.Segment { var noptr *sym.Section var bss *sym.Section var noptrbss *sym.Section + var fuzzCounters *sym.Section for i, s := range Segdata.Sections { if (ctxt.IsELF || ctxt.HeadType == objabi.Haix) && s.Name == ".tbss" { continue @@ -2421,17 +2424,17 @@ func (ctxt *Link) address() []*sym.Segment { s.Vaddr = va va += uint64(vlen) Segdata.Length = va - Segdata.Vaddr - if s.Name == ".data" { + switch s.Name { + case ".data": data = s - } - if s.Name == ".noptrdata" { + case ".noptrdata": noptr = s - } - if s.Name == ".bss" { + case ".bss": bss = s - } - if s.Name == ".noptrbss" { + case ".noptrbss": noptrbss = s + case "__libfuzzer_extra_counters": + fuzzCounters = s } } @@ -2548,6 +2551,11 @@ func (ctxt *Link) address() []*sym.Segment { ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, int64(noptrbss.Vaddr+noptrbss.Length)) ctxt.xdefine("runtime.end", sym.SBSS, int64(Segdata.Vaddr+Segdata.Length)) + if fuzzCounters != nil { + ctxt.xdefine("internal/fuzz._counters", sym.SLIBFUZZER_EXTRA_COUNTER, int64(fuzzCounters.Vaddr)) + ctxt.xdefine("internal/fuzz._ecounters", sym.SLIBFUZZER_EXTRA_COUNTER, int64(fuzzCounters.Vaddr+fuzzCounters.Length)) + } + if ctxt.IsSolaris() { // On Solaris, in the runtime it sets the external names of the // end symbols. Unset them and define separate symbols, so we diff --git a/src/internal/fuzz/coverage.go b/src/internal/fuzz/coverage.go index 7624b56e0a..74872541c9 100644 --- a/src/internal/fuzz/coverage.go +++ b/src/internal/fuzz/coverage.go @@ -4,8 +4,29 @@ package fuzz +import ( + "internal/unsafeheader" + "unsafe" +) + // coverage returns a []byte containing unique 8-bit counters for each edge of // the instrumented source code. This coverage data will only be generated if // `-d=libfuzzer` is set at build time. This can be used to understand the code // coverage of a test execution. -func coverage() []byte { return nil } +func coverage() []byte { + addr := unsafe.Pointer(&_counters) + size := uintptr(unsafe.Pointer(&_ecounters)) - uintptr(addr) + + var res []byte + *(*unsafeheader.Slice)(unsafe.Pointer(&res)) = unsafeheader.Slice{ + Data: addr, + Len: int(size), + Cap: int(size), + } + return res +} + +// _counters and _ecounters mark the start and end, respectively, of where +// the 8-bit coverage counters reside in memory. They're known to cmd/link, +// which specially assigns their addresses for this purpose. +var _counters, _ecounters [0]byte diff --git a/src/internal/fuzz/trace.go b/src/internal/fuzz/trace.go new file mode 100644 index 0000000000..f70b1a6f5b --- /dev/null +++ b/src/internal/fuzz/trace.go @@ -0,0 +1,29 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !libfuzzer + +package fuzz + +import _ "unsafe" // for go:linkname + +//go:linkname libfuzzerTraceCmp1 runtime.libfuzzerTraceCmp1 +//go:linkname libfuzzerTraceCmp2 runtime.libfuzzerTraceCmp2 +//go:linkname libfuzzerTraceCmp4 runtime.libfuzzerTraceCmp4 +//go:linkname libfuzzerTraceCmp8 runtime.libfuzzerTraceCmp8 + +//go:linkname libfuzzerTraceConstCmp1 runtime.libfuzzerTraceConstCmp1 +//go:linkname libfuzzerTraceConstCmp2 runtime.libfuzzerTraceConstCmp2 +//go:linkname libfuzzerTraceConstCmp4 runtime.libfuzzerTraceConstCmp4 +//go:linkname libfuzzerTraceConstCmp8 runtime.libfuzzerTraceConstCmp8 + +func libfuzzerTraceCmp1(arg0, arg1 uint8) {} +func libfuzzerTraceCmp2(arg0, arg1 uint16) {} +func libfuzzerTraceCmp4(arg0, arg1 uint32) {} +func libfuzzerTraceCmp8(arg0, arg1 uint64) {} + +func libfuzzerTraceConstCmp1(arg0, arg1 uint8) {} +func libfuzzerTraceConstCmp2(arg0, arg1 uint16) {} +func libfuzzerTraceConstCmp4(arg0, arg1 uint32) {} +func libfuzzerTraceConstCmp8(arg0, arg1 uint64) {} -- GitLab From b178a81e1f95eea38893e6da8daa3260d3e601de Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Mon, 5 Apr 2021 11:40:12 -0400 Subject: [PATCH 0057/2500] [dev.fuzz] internal/fuzz: don't count time spent loading corpus The -fuzztime flag tells us how much time to spend fuzzing, not counting time spent running the seed corpus. We shouldn't count time spent loading the cache either. If the cache is large, the time limit may be exceeded before the coordinator starts the workers. Change-Id: If00435faa5d24aabdb9003ebb9337fa2e47f22b6 Reviewed-on: https://go-review.googlesource.com/c/go/+/307310 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/internal/fuzz/fuzz.go | 12 +++++++++++- src/testing/internal/testdeps/deps.go | 13 +++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 8e0425c0c4..293cb48d4d 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -18,6 +18,7 @@ import ( "reflect" "runtime" "strings" + "time" ) // CoordinateFuzzing creates several worker processes and communicates with @@ -27,6 +28,9 @@ import ( // with the same arguments as the coordinator, except with the -test.fuzzworker // flag prepended to the argument list. // +// timeout is the amount of wall clock time to spend fuzzing after the corpus +// has loaded. +// // parallel is the number of worker processes to run in parallel. If parallel // is 0, CoordinateFuzzing will run GOMAXPROCS workers. // @@ -43,7 +47,7 @@ import ( // // If a crash occurs, the function will return an error containing information // about the crash, which can be reported to the user. -func CoordinateFuzzing(ctx context.Context, parallel int, seed []CorpusEntry, types []reflect.Type, corpusDir, cacheDir string) (err error) { +func CoordinateFuzzing(ctx context.Context, timeout time.Duration, parallel int, seed []CorpusEntry, types []reflect.Type, corpusDir, cacheDir string) (err error) { if err := ctx.Err(); err != nil { return err } @@ -69,6 +73,12 @@ func CoordinateFuzzing(ctx context.Context, parallel int, seed []CorpusEntry, ty corpus.entries = append(corpus.entries, CorpusEntry{Data: marshalCorpusFile(vals...), Values: vals}) } + if timeout > 0 { + var cancel func() + ctx, cancel = context.WithTimeout(ctx, timeout) + defer cancel() + } + // TODO(jayconrod): do we want to support fuzzing different binaries? dir := "" // same as self binPath := os.Args[0] diff --git a/src/testing/internal/testdeps/deps.go b/src/testing/internal/testdeps/deps.go index 8f587b2e1d..c77aca3da8 100644 --- a/src/testing/internal/testdeps/deps.go +++ b/src/testing/internal/testdeps/deps.go @@ -137,14 +137,9 @@ func (TestDeps) CoordinateFuzzing(timeout time.Duration, parallel int, seed []fu // Fuzzing may be interrupted with a timeout or if the user presses ^C. // In either case, we'll stop worker processes gracefully and save // crashers and interesting values. - ctx, cancel := context.WithCancel(context.Background()) - if timeout > 0 { - ctx, cancel = context.WithTimeout(ctx, timeout) - } - ctx, stop := signal.NotifyContext(ctx, os.Interrupt) - defer stop() + ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt) defer cancel() - err = fuzz.CoordinateFuzzing(ctx, parallel, seed, types, corpusDir, cacheDir) + err = fuzz.CoordinateFuzzing(ctx, timeout, parallel, seed, types, corpusDir, cacheDir) if err == ctx.Err() { return nil } @@ -158,9 +153,7 @@ func (TestDeps) RunFuzzWorker(fn func(fuzz.CorpusEntry) error) error { // If the worker is interrupted, return quickly and without error. // If only the coordinator process is interrupted, it tells each worker // process to stop by closing its "fuzz_in" pipe. - ctx, cancel := context.WithCancel(context.Background()) - ctx, stop := signal.NotifyContext(ctx, os.Interrupt) - defer stop() + ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt) defer cancel() err := fuzz.RunFuzzWorker(ctx, fn) if err == ctx.Err() { -- GitLab From 4cde035a720448b2bca07ecdc12beef3b1322939 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Fri, 19 Mar 2021 15:11:29 -0400 Subject: [PATCH 0058/2500] [dev.fuzz] internal/fuzz: improve cancellation in worker event loops worker.runFuzzing now accepts a Context, used for cancellation instead of doneC (which is removed). This is passed down through workerClient RPC methods (ping, fuzz). workerClient RPC methods now wrap the call method, which handles marshaling and cancellation. Both workerClient.call and workerServer.serve should return quickly when their contexts are cancelled. Turns out, closing the pipe won't actually unblock a read on all platforms. Instead, we were falling back to SIGKILL in worker.stop, which works but takes longer than necessary. Also fixed missing newline in log message. Change-Id: I7b5ae54d6eb9afd6361a07759f049f048952e0cc Reviewed-on: https://go-review.googlesource.com/c/go/+/303429 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod Reviewed-by: Katie Hockman --- .../go/testdata/script/test_fuzz_io_error.txt | 101 ++++++ src/internal/fuzz/fuzz.go | 35 +- src/internal/fuzz/sys_windows.go | 3 +- src/internal/fuzz/worker.go | 322 +++++++++--------- src/testing/fuzz.go | 2 +- 5 files changed, 290 insertions(+), 173 deletions(-) create mode 100644 src/cmd/go/testdata/script/test_fuzz_io_error.txt diff --git a/src/cmd/go/testdata/script/test_fuzz_io_error.txt b/src/cmd/go/testdata/script/test_fuzz_io_error.txt new file mode 100644 index 0000000000..4c7ab4c152 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_io_error.txt @@ -0,0 +1,101 @@ +# Test that when the coordinator experiences an I/O error communicating +# with a worker, the coordinator stops the worker and reports the error. +# The coordinator should not record a crasher. +# +# We simulate an I/O error in the test by writing garbage to fuzz_out. +# This is unlikely, but possible. It's difficult to simulate interruptions +# due to ^C and EOF errors which are more common. We don't report those. +[short] skip +[!darwin] [!linux] [!windows] skip + +# If the I/O error occurs before F.Fuzz is called, the coordinator should +# stop the worker and say that. +! go test -fuzz=FuzzClosePipeBefore -parallel=1 +stdout '\s*fuzzing process terminated without fuzzing:' +! stdout 'communicating with fuzzing process' +! exists testdata + +# If the I/O error occurs after F.Fuzz is called (unlikely), just exit. +# It's hard to distinguish this case from the worker being interrupted by ^C +# or exiting with status 0 (which it should do when interrupted by ^C). +! go test -fuzz=FuzzClosePipeAfter -parallel=1 +stdout '^\s*communicating with fuzzing process: invalid character ''!'' looking for beginning of value$' +! exists testdata + +-- go.mod -- +module test + +go 1.17 +-- io_error_test.go -- +package io_error + +import ( + "flag" + "testing" + "time" +) + +func isWorker() bool { + f := flag.Lookup("test.fuzzworker") + if f == nil { + return false + } + get, ok := f.Value.(flag.Getter) + if !ok { + return false + } + return get.Get() == interface{}(true) +} + +func FuzzClosePipeBefore(f *testing.F) { + if isWorker() { + sendGarbageToCoordinator(f) + time.Sleep(3600 * time.Second) // pause until coordinator terminates the process + } + f.Fuzz(func(*testing.T, []byte) {}) +} + +func FuzzClosePipeAfter(f *testing.F) { + f.Fuzz(func(t *testing.T, _ []byte) { + if isWorker() { + sendGarbageToCoordinator(t) + time.Sleep(3600 * time.Second) // pause until coordinator terminates the process + } + }) +} +-- io_error_windows_test.go -- +package io_error + +import ( + "fmt" + "os" + "testing" +) + +func sendGarbageToCoordinator(tb testing.TB) { + v := os.Getenv("GO_TEST_FUZZ_WORKER_HANDLES") + var fuzzInFD, fuzzOutFD uintptr + if _, err := fmt.Sscanf(v, "%x,%x", &fuzzInFD, &fuzzOutFD); err != nil { + tb.Fatalf("parsing GO_TEST_FUZZ_WORKER_HANDLES: %v", err) + } + f := os.NewFile(fuzzOutFD, "fuzz_out") + if _, err := f.Write([]byte("!!")); err != nil { + tb.Fatalf("writing fuzz_out: %v", err) + } +} +-- io_error_notwindows_test.go -- +// +build !windows + +package io_error + +import ( + "os" + "testing" +) + +func sendGarbageToCoordinator(tb testing.TB) { + f := os.NewFile(4, "fuzz_out") + if _, err := f.Write([]byte("!!")); err != nil { + tb.Fatalf("writing fuzz_out: %v", err) + } +} diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 293cb48d4d..5fa265f8c5 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -86,13 +86,13 @@ func CoordinateFuzzing(ctx context.Context, timeout time.Duration, parallel int, env := os.Environ() // same as self c := &coordinator{ - doneC: make(chan struct{}), inputC: make(chan CorpusEntry), interestingC: make(chan CorpusEntry), crasherC: make(chan crasherEntry), } errC := make(chan error) + // newWorker creates a worker but doesn't start it yet. newWorker := func() (*worker, error) { mem, err := sharedMemTempFile(workerSharedMemSize) if err != nil { @@ -110,17 +110,30 @@ func CoordinateFuzzing(ctx context.Context, timeout time.Duration, parallel int, }, nil } + // fuzzCtx is used to stop workers, for example, after finding a crasher. + fuzzCtx, cancelWorkers := context.WithCancel(ctx) + defer cancelWorkers() + doneC := ctx.Done() + + // stop is called when a worker encounters a fatal error. var fuzzErr error stopping := false stop := func(err error) { - if fuzzErr == nil || fuzzErr == ctx.Err() { + if err == fuzzCtx.Err() || isInterruptError(err) { + // Suppress cancellation errors and terminations due to SIGINT. + // The messages are not helpful since either the user triggered the error + // (with ^C) or another more helpful message will be printed (a crasher). + err = nil + } + if err != nil && (fuzzErr == nil || fuzzErr == ctx.Err()) { fuzzErr = err } if stopping { return } stopping = true - close(c.doneC) + cancelWorkers() + doneC = nil } // Start workers. @@ -135,7 +148,7 @@ func CoordinateFuzzing(ctx context.Context, timeout time.Duration, parallel int, for i := range workers { w := workers[i] go func() { - err := w.runFuzzing() + err := w.coordinate(fuzzCtx) cleanErr := w.cleanup() if err == nil { err = cleanErr @@ -146,17 +159,14 @@ func CoordinateFuzzing(ctx context.Context, timeout time.Duration, parallel int, // Main event loop. // Do not return until all workers have terminated. We avoid a deadlock by - // receiving messages from workers even after closing c.doneC. + // receiving messages from workers even after ctx is cancelled. activeWorkers := len(workers) i := 0 for { select { - case <-ctx.Done(): + case <-doneC: // Interrupted, cancelled, or timed out. - // TODO(jayconrod,katiehockman): On Windows, ^C only interrupts 'go test', - // not the coordinator or worker processes. 'go test' will stop running - // actions, but it won't interrupt its child processes. This makes it - // difficult to stop fuzzing on Windows without a timeout. + // stop sets doneC to nil so we don't busy wait here. stop(ctx.Err()) case crasher := <-c.crasherC: @@ -259,11 +269,6 @@ type crasherEntry struct { // coordinator holds channels that workers can use to communicate with // the coordinator. type coordinator struct { - // doneC is closed to indicate fuzzing is done and workers should stop. - // doneC may be closed due to a time limit expiring or a fatal error in - // a worker. - doneC chan struct{} - // inputC is sent values to fuzz by the coordinator. Any worker may receive // values from this channel. inputC chan CorpusEntry diff --git a/src/internal/fuzz/sys_windows.go b/src/internal/fuzz/sys_windows.go index e1734af53c..de6af81d94 100644 --- a/src/internal/fuzz/sys_windows.go +++ b/src/internal/fuzz/sys_windows.go @@ -135,6 +135,7 @@ func getWorkerComm() (comm workerComm, err error) { } func isInterruptError(err error) bool { - // TODO(jayconrod): implement + // On Windows, we can't tell whether the process was interrupted by the error + // returned by Wait. It looks like an ExitError with status 1. return false } diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 506a485f24..2c4cc1f82b 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -51,10 +51,11 @@ type worker struct { memMu chan *sharedMem // mutex guarding shared memory with worker; persists across processes. - cmd *exec.Cmd // current worker process - client *workerClient // used to communicate with worker process - waitErr error // last error returned by wait, set before termC is closed. - termC chan struct{} // closed by wait when worker process terminates + cmd *exec.Cmd // current worker process + client *workerClient // used to communicate with worker process + waitErr error // last error returned by wait, set before termC is closed. + interrupted bool // true after stop interrupts a running worker. + termC chan struct{} // closed by wait when worker process terminates } // cleanup releases persistent resources associated with the worker. @@ -67,12 +68,12 @@ func (w *worker) cleanup() error { return mem.Close() } -// runFuzzing runs the test binary to perform fuzzing. +// coordinate runs the test binary to perform fuzzing. // -// This function loops until w.coordinator.doneC is closed or some -// fatal error is encountered. It receives inputs from w.coordinator.inputC, -// then passes those on to the worker process. -func (w *worker) runFuzzing() error { +// coordinate loops until ctx is cancelled or a fatal error is encountered. While +// looping, coordinate receives inputs from w.coordinator.inputC, then passes +// those on to the worker process. +func (w *worker) coordinate(ctx context.Context) error { // Start the process. if err := w.start(); err != nil { // We couldn't start the worker process. We can't do anything, and it's @@ -80,125 +81,113 @@ func (w *worker) runFuzzing() error { return err } - // inputC is set to w.coordinator.inputC when the worker is able to process - // input. It's nil at other times, so its case won't be selected in the - // event loop below. - var inputC chan CorpusEntry - - // A value is sent to fuzzC to tell the worker to prepare to process an input - // by setting inputC. - fuzzC := make(chan struct{}, 1) - // Send the worker a message to make sure it can respond. // Errors that occur before we get a response likely indicate that // the worker did not call F.Fuzz or called F.Fail first. // We don't record crashers for these errors. - pinged := false - go func() { - err := w.client.ping() - if err != nil { - w.stop() // trigger termC case below - return + if err := w.client.ping(ctx); err != nil { + w.stop() + if ctx.Err() != nil { + return ctx.Err() } - pinged = true - fuzzC <- struct{}{} - }() + if isInterruptError(err) { + // User may have pressed ^C before worker responded. + return nil + } + return fmt.Errorf("fuzzing process terminated without fuzzing: %w", err) + // TODO(jayconrod,katiehockman): record and return stderr. + } // Main event loop. for { select { - case <-w.coordinator.doneC: - // All workers were told to stop. + case <-ctx.Done(): + // Worker was told to stop. err := w.stop() - if isInterruptError(err) { - // Worker interrupted by SIGINT. This can happen if the worker receives - // SIGINT before installing the signal handler. That's likely if - // TestMain or the fuzz target setup takes a long time. - return nil + if err != nil && !w.interrupted && !isInterruptError(err) { + return err } - return err + return ctx.Err() case <-w.termC: - // Worker process terminated unexpectedly. - if !pinged { - w.stop() - return fmt.Errorf("worker terminated without fuzzing") - // TODO(jayconrod,katiehockman): record and return stderr. + // Worker process terminated unexpectedly while waiting for input. + err := w.stop() + if w.interrupted { + panic("worker interrupted after unexpected termination") } - if isInterruptError(w.waitErr) { - // Worker interrupted by SIGINT. See comment in doneC case. - w.stop() + if err == nil || isInterruptError(err) { + // Worker stopped, either by exiting with status 0 or after being + // interrupted with a signal that was not sent by the coordinator. + // + // When the user presses ^C, on POSIX platforms, SIGINT is delivered to + // all processes in the group concurrently, and the worker may see it + // before the coordinator. The worker should exit 0 gracefully (in + // theory). + // + // This condition is probably intended by the user, so suppress + // the error. return nil } - if exitErr, ok := w.waitErr.(*exec.ExitError); ok && exitErr.ExitCode() == workerExitCode { - w.stop() - return fmt.Errorf("worker exited unexpectedly due to an internal failure") - // TODO(jayconrod,katiehockman): record and return stderr. - } - - // Unexpected termination. Inform the coordinator about the crash. - // TODO(jayconrod,katiehockman): if -keepfuzzing, restart worker. - mem := <-w.memMu - value := mem.valueCopy() - w.memMu <- mem - message := fmt.Sprintf("fuzzing process terminated unexpectedly: %v\n", w.waitErr) - crasher := crasherEntry{ - CorpusEntry: CorpusEntry{Data: value}, - errMsg: message, + if exitErr, ok := err.(*exec.ExitError); ok && exitErr.ExitCode() == workerExitCode { + // Worker exited with a code indicating F.Fuzz was not called correctly, + // for example, F.Fail was called first. + return fmt.Errorf("fuzzing process exited unexpectedly due to an internal failure: %w", err) } - w.coordinator.crasherC <- crasher - return w.stop() + // Worker exited non-zero or was terminated by a non-interrupt signal + // (for example, SIGSEGV). + return fmt.Errorf("fuzzing process terminated unexpectedly: %w", err) + // TODO(jayconrod,katiehockman): record and return stderr. - case input := <-inputC: + case input := <-w.coordinator.inputC: // Received input from coordinator. - inputC = nil // block new inputs until we finish with this one. - go func() { - args := fuzzArgs{Duration: workerFuzzDuration} - value, resp, err := w.client.fuzz(input.Data, args) - if err != nil { - // Error communicating with worker. - select { - case <-w.termC: - // Worker terminated, perhaps unexpectedly. - // We expect I/O errors due to partially sent or received RPCs, - // so ignore this error. - case <-w.coordinator.doneC: - // Timeout or interruption. Worker may also be interrupted. - // Again, ignore I/O errors. - default: - // TODO(jayconrod): if we get an error here, something failed between - // main and the call to testing.F.Fuzz. The error here won't - // be useful. Collect stderr, clean it up, and return that. - // TODO(jayconrod): we can get EPIPE if w.stop is called concurrently - // and it kills the worker process. Suppress this message in - // that case. - fmt.Fprintf(os.Stderr, "communicating with worker: %v\n", err) - } - // TODO(jayconrod): what happens if testing.F.Fuzz is never called? - // TODO(jayconrod): time out if the test process hangs. - } else if resp.Crashed { - // The worker found a crasher. Inform the coordinator. - crasher := crasherEntry{ - CorpusEntry: CorpusEntry{Data: value}, - errMsg: resp.Err, - } - w.coordinator.crasherC <- crasher - } else { - // Inform the coordinator that fuzzing found something - // interesting (i.e. new coverage). - if resp.Interesting { - w.coordinator.interestingC <- CorpusEntry{Data: value} - } - - // Continue fuzzing. - fuzzC <- struct{}{} + args := fuzzArgs{Duration: workerFuzzDuration} + value, resp, err := w.client.fuzz(ctx, input.Data, args) + if err != nil { + // Error communicating with worker. + w.stop() + if ctx.Err() != nil { + // Timeout or interruption. + return ctx.Err() + } + if w.interrupted { + // Communication error before we stopped the worker. + // Report an error, but don't record a crasher. + return fmt.Errorf("communicating with fuzzing process: %v", err) + } + if w.waitErr == nil || isInterruptError(w.waitErr) { + // Worker stopped, either by exiting with status 0 or after being + // interrupted with a signal (not sent by coordinator). See comment in + // termC case above. + // + // Since we expect I/O errors around interrupts, ignore this error. + return nil } - // TODO(jayconrod,katiehockman): gather statistics. - }() - case <-fuzzC: - // Worker finished fuzzing and nothing new happened. - inputC = w.coordinator.inputC // unblock new inputs + // Unexpected termination. Inform the coordinator about the crash. + // TODO(jayconrod,katiehockman): if -keepfuzzing, restart worker. + mem := <-w.memMu + value := mem.valueCopy() + w.memMu <- mem + message := fmt.Sprintf("fuzzing process terminated unexpectedly: %v", w.waitErr) + crasher := crasherEntry{ + CorpusEntry: CorpusEntry{Data: value}, + errMsg: message, + } + w.coordinator.crasherC <- crasher + return w.waitErr + } else if resp.Crashed { + // The worker found a crasher. Inform the coordinator. + crasher := crasherEntry{ + CorpusEntry: CorpusEntry{Data: value}, + errMsg: resp.Err, + } + w.coordinator.crasherC <- crasher + } else if resp.Interesting { + // Inform the coordinator that fuzzing found something + // interesting (i.e. new coverage). + w.coordinator.interestingC <- CorpusEntry{Data: value} + } + // TODO(jayconrod,katiehockman): gather statistics. } } } @@ -218,6 +207,7 @@ func (w *worker) start() (err error) { panic("worker already started") } w.waitErr = nil + w.interrupted = false w.termC = nil cmd := exec.Command(w.binPath, w.args...) @@ -332,6 +322,7 @@ func (w *worker) stop() error { case <-t.C: // Timer fired before worker terminated. + w.interrupted = true switch sig { case os.Interrupt: // Try to stop the worker with SIGINT and wait a little longer. @@ -347,7 +338,7 @@ func (w *worker) stop() error { case nil: // Still waiting. Print a message to let the user know why. - fmt.Fprintf(os.Stderr, "go: waiting for fuzz worker to terminate...\n") + fmt.Fprintf(os.Stderr, "go: waiting for fuzzing process to terminate...\n") } } } @@ -446,49 +437,55 @@ type workerServer struct { // does not return errors from method calls; those are passed through serialized // responses. func (ws *workerServer) serve(ctx context.Context) error { - // Stop handling messages when ctx.Done() is closed. This normally happens - // when the worker process receives a SIGINT signal, which on POSIX platforms - // is sent to the process group when ^C is pressed. - // - // Ordinarily, the coordinator process may stop a worker by closing fuzz_in. - // We simulate that and interrupt a blocked read here. - doneC := make(chan struct{}) - defer func() { close(doneC) }() + // This goroutine may stay blocked after serve returns because the underlying + // read blocks, even after the file descriptor in this process is closed. The + // pipe must be closed by the client, too. + errC := make(chan error, 1) go func() { - select { - case <-ctx.Done(): - ws.fuzzIn.Close() - case <-doneC: - } - }() + enc := json.NewEncoder(ws.fuzzOut) + dec := json.NewDecoder(ws.fuzzIn) + for { + if ctx.Err() != nil { + return + } - enc := json.NewEncoder(ws.fuzzOut) - dec := json.NewDecoder(ws.fuzzIn) - for { - var c call - if err := dec.Decode(&c); err != nil { + var c call + if err := dec.Decode(&c); err == io.EOF { + return + } else if err != nil { + errC <- err + return + } if ctx.Err() != nil { - return ctx.Err() - } else if err == io.EOF { - return nil - } else { - return err + return } - } - var resp interface{} - switch { - case c.Fuzz != nil: - resp = ws.fuzz(ctx, *c.Fuzz) - case c.Ping != nil: - resp = ws.ping(ctx, *c.Ping) - default: - return errors.New("no arguments provided for any call") - } + var resp interface{} + switch { + case c.Fuzz != nil: + resp = ws.fuzz(ctx, *c.Fuzz) + case c.Ping != nil: + resp = ws.ping(ctx, *c.Ping) + default: + errC <- errors.New("no arguments provided for any call") + return + } - if err := enc.Encode(resp); err != nil { - return err + if err := enc.Encode(resp); err != nil { + errC <- err + return + } } + }() + + select { + case <-ctx.Done(): + // Stop handling messages when ctx.Done() is closed. This normally happens + // when the worker process receives a SIGINT signal, which on POSIX platforms + // is sent to the process group when ^C is pressed. + return ctx.Err() + case err := <-errC: + return err } } @@ -691,7 +688,7 @@ func (wc *workerClient) Close() error { var errSharedMemClosed = errors.New("internal error: shared memory was closed and unmapped") // fuzz tells the worker to call the fuzz method. See workerServer.fuzz. -func (wc *workerClient) fuzz(valueIn []byte, args fuzzArgs) (valueOut []byte, resp fuzzResponse, err error) { +func (wc *workerClient) fuzz(ctx context.Context, valueIn []byte, args fuzzArgs) (valueOut []byte, resp fuzzResponse, err error) { wc.mu.Lock() defer wc.mu.Unlock() @@ -703,11 +700,7 @@ func (wc *workerClient) fuzz(valueIn []byte, args fuzzArgs) (valueOut []byte, re wc.memMu <- mem c := call{Fuzz: &args} - if err := wc.enc.Encode(c); err != nil { - return nil, fuzzResponse{}, err - } - err = wc.dec.Decode(&resp) - + err = wc.call(ctx, c, &resp) mem, ok = <-wc.memMu if !ok { return nil, fuzzResponse{}, errSharedMemClosed @@ -719,14 +712,31 @@ func (wc *workerClient) fuzz(valueIn []byte, args fuzzArgs) (valueOut []byte, re } // ping tells the worker to call the ping method. See workerServer.ping. -func (wc *workerClient) ping() error { +func (wc *workerClient) ping(ctx context.Context) error { c := call{Ping: &pingArgs{}} - if err := wc.enc.Encode(c); err != nil { - return err - } var resp pingResponse - if err := wc.dec.Decode(&resp); err != nil { + return wc.call(ctx, c, &resp) +} + +// call sends an RPC from the coordinator to the worker process and waits for +// the response. The call may be cancelled with ctx. +func (wc *workerClient) call(ctx context.Context, c call, resp interface{}) (err error) { + // This goroutine may stay blocked after call returns because the underlying + // read blocks, even after the file descriptor in this process is closed. The + // pipe must be closed by the server, too. + errC := make(chan error, 1) + go func() { + if err := wc.enc.Encode(c); err != nil { + errC <- err + return + } + errC <- wc.dec.Decode(resp) + }() + + select { + case <-ctx.Done(): + return ctx.Err() + case err := <-errC: return err } - return nil } diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 2a0754fdd7..73ac59cfb4 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -362,7 +362,7 @@ func (f *F) Fuzz(ff interface{}) { if err != nil { f.result = FuzzResult{Error: err} f.Fail() - fmt.Fprintf(f.w, "%v", err) + fmt.Fprintf(f.w, "%v\n", err) if crashErr, ok := err.(fuzzCrashError); ok { crashName := crashErr.CrashName() fmt.Fprintf(f.w, "Crash written to %s\n", filepath.Join("testdata/corpus", f.name, crashName)) -- GitLab From 4baa39ca22c34d4c224ac69da644c85dee196474 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Fri, 2 Apr 2021 14:36:08 -0400 Subject: [PATCH 0059/2500] [dev.fuzz] testing: let -fuzztime specify a number of executions -fuzztime now works similarly to -benchtime: if it's given a string with an "x" suffix (as opposed to "s" or some other unit of duration), the fuzzing system will generate and run a maximum number of values. This CL also implements tracking and printing counts, since most of the work was already done. Change-Id: I013007984b5adfc1a751c379dc98c8d46b4a97e9 Reviewed-on: https://go-review.googlesource.com/c/go/+/306909 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/cmd/go/internal/test/testflag.go | 2 +- src/cmd/go/testdata/script/test_fuzz.txt | 8 +- .../go/testdata/script/test_fuzz_cache.txt | 2 +- .../go/testdata/script/test_fuzz_chatty.txt | 2 +- .../go/testdata/script/test_fuzz_fuzztime.txt | 48 +++- .../go/testdata/script/test_fuzz_match.txt | 6 +- .../script/test_fuzz_mutate_crash.txt | 18 +- .../go/testdata/script/test_fuzz_mutator.txt | 6 +- src/internal/fuzz/fuzz.go | 269 ++++++++++++++---- src/internal/fuzz/worker.go | 73 +++-- src/testing/benchmark.go | 14 +- src/testing/fuzz.go | 8 +- src/testing/internal/testdeps/deps.go | 4 +- src/testing/sub_test.go | 2 +- src/testing/testing.go | 10 +- 15 files changed, 344 insertions(+), 128 deletions(-) diff --git a/src/cmd/go/internal/test/testflag.go b/src/cmd/go/internal/test/testflag.go index e11b41ba76..b3e77594db 100644 --- a/src/cmd/go/internal/test/testflag.go +++ b/src/cmd/go/internal/test/testflag.go @@ -67,7 +67,7 @@ func init() { cf.String("run", "", "") cf.Bool("short", false, "") cf.DurationVar(&testTimeout, "timeout", 10*time.Minute, "") - cf.Duration("fuzztime", 0, "") + cf.String("fuzztime", "", "") cf.StringVar(&testTrace, "trace", "", "") cf.BoolVar(&testV, "v", false, "") diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt index c8567b996f..bfa1b68c67 100644 --- a/src/cmd/go/testdata/script/test_fuzz.txt +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -9,12 +9,12 @@ stdout FAIL # Test that fuzzing a fuzz target that returns without failing or calling # f.Fuzz fails and causes a non-zero exit status. -! go test -fuzz=Fuzz -fuzztime=5s noop_fuzz_test.go +! go test -fuzz=Fuzz -fuzztime=1x noop_fuzz_test.go ! stdout ^ok stdout FAIL # Test that calling f.Error in a fuzz target causes a non-zero exit status. -! go test -fuzz=Fuzz -fuzztime=5s error_fuzz_test.go +! go test -fuzz=Fuzz -fuzztime=1x error_fuzz_test.go ! stdout ^ok stdout FAIL @@ -29,12 +29,12 @@ stdout ^ok ! stdout FAIL # Test that successful fuzzing exits cleanly. -go test -fuzz=Fuzz -fuzztime=5s success_fuzz_test.go +go test -fuzz=Fuzz -fuzztime=1x success_fuzz_test.go stdout ok ! stdout FAIL # Test that calling f.Fatal while fuzzing causes a non-zero exit status. -! go test -fuzz=Fuzz -fuzztime=5s fatal_fuzz_test.go +! go test -fuzz=Fuzz -fuzztime=1x fatal_fuzz_test.go ! stdout ^ok stdout FAIL diff --git a/src/cmd/go/testdata/script/test_fuzz_cache.txt b/src/cmd/go/testdata/script/test_fuzz_cache.txt index 21546a828b..cb344a7158 100644 --- a/src/cmd/go/testdata/script/test_fuzz_cache.txt +++ b/src/cmd/go/testdata/script/test_fuzz_cache.txt @@ -10,7 +10,7 @@ exists $GOCACHE ! exists $GOCACHE/fuzz # Fuzzing should write interesting values to the cache. -go test -fuzz=FuzzY -fuzztime=5s . +go test -fuzz=FuzzY -fuzztime=100x . go run ./contains_files $GOCACHE/fuzz/example.com/y/FuzzY # 'go clean -cache' should not delete the fuzz cache. diff --git a/src/cmd/go/testdata/script/test_fuzz_chatty.txt b/src/cmd/go/testdata/script/test_fuzz_chatty.txt index ea81bc331d..9ebd480c90 100644 --- a/src/cmd/go/testdata/script/test_fuzz_chatty.txt +++ b/src/cmd/go/testdata/script/test_fuzz_chatty.txt @@ -35,7 +35,7 @@ stdout 'all good here' ! stdout FAIL # Fuzz successful chatty fuzz target that includes a separate unit test. -go test -v chatty_with_test_fuzz_test.go -fuzz=Fuzz -fuzztime=1s +go test -v chatty_with_test_fuzz_test.go -fuzz=Fuzz -fuzztime=1x stdout ok stdout PASS ! stdout FAIL diff --git a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt index 15a0f86e93..2b2e38c504 100644 --- a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt +++ b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt @@ -16,11 +16,19 @@ exec ./fuzz.test$GOEXE -test.timeout=10ms -test.fuzz=FuzzFast -test.fuzztime=5s # Timeout should not cause inputs to be written as crashers. ! exists testdata/corpus +# When we use fuzztime with an "x" suffix, it runs a specific number of times. +# This fuzz function creates a file with a unique name ($pid.$count) on each run. +# We count the files to find the number of runs. +mkdir count +go test -fuzz=FuzzCount -fuzztime=1000x +go run count_files.go +stdout '^1000$' + -- go.mod -- module fuzz go 1.16 --- fuzz_test.go -- +-- fuzz_fast_test.go -- package fuzz_test import "testing" @@ -28,3 +36,41 @@ import "testing" func FuzzFast(f *testing.F) { f.Fuzz(func (*testing.T, []byte) {}) } +-- fuzz_count_test.go -- +package fuzz + +import ( + "fmt" + "os" + "testing" +) + +func FuzzCount(f *testing.F) { + pid := os.Getpid() + n := 0 + f.Fuzz(func(t *testing.T, _ []byte) { + name := fmt.Sprintf("count/%v.%d", pid, n) + if err := os.WriteFile(name, nil, 0666); err != nil { + t.Fatal(err) + } + n++ + }) +} +-- count_files.go -- +// +build ignore + +package main + +import ( + "fmt" + "os" +) + +func main() { + dir, err := os.ReadDir("count") + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + fmt.Println(len(dir)) +} diff --git a/src/cmd/go/testdata/script/test_fuzz_match.txt b/src/cmd/go/testdata/script/test_fuzz_match.txt index 7b2216f3dd..ab8bebf52c 100644 --- a/src/cmd/go/testdata/script/test_fuzz_match.txt +++ b/src/cmd/go/testdata/script/test_fuzz_match.txt @@ -7,12 +7,12 @@ go test standalone_fuzz_test.go stdout '^ok' # Matches only for fuzzing. -go test -fuzz Fuzz -fuzztime 2s -parallel 4 standalone_fuzz_test.go +go test -fuzz Fuzz -fuzztime 1x standalone_fuzz_test.go ! stdout '^ok.*\[no tests to run\]' stdout '^ok' # Matches none for fuzzing but will run the fuzz target as a test. -go test -fuzz ThisWillNotMatch -fuzztime 2s -parallel 4 standalone_fuzz_test.go +go test -fuzz ThisWillNotMatch -fuzztime 1x standalone_fuzz_test.go ! stdout '^ok.*\[no tests to run\]' stdout '^ok' stdout '\[no targets to fuzz\]' @@ -30,7 +30,7 @@ stdout '^ok.*\[no tests to run\]' ! stdout '\[no targets to fuzz\]' # Matches more than one fuzz target for fuzzing. -go test -fuzz Fuzz -fuzztime 2s -parallel 4 multiple_fuzz_test.go +go test -fuzz Fuzz -fuzztime 1x multiple_fuzz_test.go # The tests should run, but not be fuzzed ! stdout '\[no tests to run\]' ! stdout '\[no targets to fuzz\]' diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt index 57db788436..f8ee63b109 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt @@ -13,7 +13,7 @@ go test # Running the fuzzer should find a crashing input quickly. -! go test -fuzz=FuzzWithBug -fuzztime=5s +! go test -fuzz=FuzzWithBug -fuzztime=100x stdout 'testdata[/\\]corpus[/\\]FuzzWithBug[/\\]' stdout 'this input caused a crash!' go run check_testdata.go FuzzWithBug @@ -23,42 +23,42 @@ go run check_testdata.go FuzzWithBug ! go test # Running the fuzzer should find a crashing input quickly for fuzzing two types. -! go test -run=FuzzWithTwoTypes -fuzz=FuzzWithTwoTypes -fuzztime=5s +! go test -run=FuzzWithTwoTypes -fuzz=FuzzWithTwoTypes -fuzztime=100x stdout 'testdata[/\\]corpus[/\\]FuzzWithTwoTypes[/\\]' stdout 'these inputs caused a crash!' go run check_testdata.go FuzzWithTwoTypes # Running the fuzzer should find a crashing input quickly for an integer -! go test -run=FuzzInt -fuzz=FuzzInt -fuzztime=5s +! go test -run=FuzzInt -fuzz=FuzzInt -fuzztime=100x stdout 'testdata[/\\]corpus[/\\]FuzzInt[/\\]' stdout 'this input caused a crash!' go run check_testdata.go FuzzInt -! go test -run=FuzzWithNilPanic -fuzz=FuzzWithNilPanic -fuzztime=5s +! go test -run=FuzzWithNilPanic -fuzz=FuzzWithNilPanic -fuzztime=100x stdout 'testdata[/\\]corpus[/\\]FuzzWithNilPanic[/\\]' stdout 'runtime.Goexit' go run check_testdata.go FuzzWithNilPanic -! go test -run=FuzzWithFail -fuzz=FuzzWithFail -fuzztime=5s +! go test -run=FuzzWithFail -fuzz=FuzzWithFail -fuzztime=100x stdout 'testdata[/\\]corpus[/\\]FuzzWithFail[/\\]' go run check_testdata.go FuzzWithFail -! go test -run=FuzzWithLogFail -fuzz=FuzzWithLogFail -fuzztime=5s +! go test -run=FuzzWithLogFail -fuzz=FuzzWithLogFail -fuzztime=100x stdout 'testdata[/\\]corpus[/\\]FuzzWithLogFail[/\\]' stdout 'logged something' go run check_testdata.go FuzzWithLogFail -! go test -run=FuzzWithErrorf -fuzz=FuzzWithErrorf -fuzztime=5s +! go test -run=FuzzWithErrorf -fuzz=FuzzWithErrorf -fuzztime=100x stdout 'testdata[/\\]corpus[/\\]FuzzWithErrorf[/\\]' stdout 'errorf was called here' go run check_testdata.go FuzzWithErrorf -! go test -run=FuzzWithFatalf -fuzz=FuzzWithFatalf -fuzztime=5s +! go test -run=FuzzWithFatalf -fuzz=FuzzWithFatalf -fuzztime=100x stdout 'testdata[/\\]corpus[/\\]FuzzWithFatalf[/\\]' stdout 'fatalf was called here' go run check_testdata.go FuzzWithFatalf -! go test -run=FuzzWithBadExit -fuzz=FuzzWithBadExit -fuzztime=5s +! go test -run=FuzzWithBadExit -fuzz=FuzzWithBadExit -fuzztime=100x stdout 'testdata[/\\]corpus[/\\]FuzzWithBadExit[/\\]' stdout 'unexpectedly' go run check_testdata.go FuzzWithBadExit diff --git a/src/cmd/go/testdata/script/test_fuzz_mutator.txt b/src/cmd/go/testdata/script/test_fuzz_mutator.txt index 8ec73bf35e..aa2b8ff83f 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutator.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutator.txt @@ -10,11 +10,11 @@ [short] skip -go test -fuzz=FuzzA -fuzztime=5s -parallel=1 -log=fuzz +go test -fuzz=FuzzA -fuzztime=100x -parallel=1 -log=fuzz go run check_logs.go fuzz fuzz.worker # Test that the mutator is good enough to find several unique mutations. -! go test -fuzz=FuzzMutator -parallel=1 -fuzztime=30s mutator_test.go +! go test -fuzz=FuzzMutator -parallel=1 -fuzztime=100x mutator_test.go ! stdout '^ok' stdout FAIL stdout 'mutator found enough unique mutations' @@ -213,7 +213,7 @@ func FuzzMutator(f *testing.F) { // No seed corpus initiated f.Fuzz(func(t *testing.T, b []byte) { crashes[string(b)] = true - if len(crashes) >= 1000 { + if len(crashes) >= 10 { panic("mutator found enough unique mutations") } }) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 5fa265f8c5..5d4fcb9a66 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -12,6 +12,7 @@ import ( "crypto/sha256" "errors" "fmt" + "io" "io/ioutil" "os" "path/filepath" @@ -28,9 +29,14 @@ import ( // with the same arguments as the coordinator, except with the -test.fuzzworker // flag prepended to the argument list. // +// log is a writer for logging progress messages and warnings. +// // timeout is the amount of wall clock time to spend fuzzing after the corpus // has loaded. // +// count is the number of random values to generate and test. If 0, +// CoordinateFuzzing will run until ctx is canceled. +// // parallel is the number of worker processes to run in parallel. If parallel // is 0, CoordinateFuzzing will run GOMAXPROCS workers. // @@ -47,31 +53,22 @@ import ( // // If a crash occurs, the function will return an error containing information // about the crash, which can be reported to the user. -func CoordinateFuzzing(ctx context.Context, timeout time.Duration, parallel int, seed []CorpusEntry, types []reflect.Type, corpusDir, cacheDir string) (err error) { +func CoordinateFuzzing(ctx context.Context, log io.Writer, timeout time.Duration, count int64, parallel int, seed []CorpusEntry, types []reflect.Type, corpusDir, cacheDir string) (err error) { if err := ctx.Err(); err != nil { return err } if parallel == 0 { parallel = runtime.GOMAXPROCS(0) } - - // Make sure all of the seed corpus has marshalled data. - for i := range seed { - if seed[i].Data == nil { - seed[i].Data = marshalCorpusFile(seed[i].Values...) - } + if count > 0 && int64(parallel) > count { + // Don't start more workers than we need. + parallel = int(count) } - corpus, err := readCache(seed, types, cacheDir) + + c, err := newCoordinator(log, count, parallel, seed, types, cacheDir) if err != nil { return err } - if len(corpus.entries) == 0 { - var vals []interface{} - for _, t := range types { - vals = append(vals, zeroValue(t)) - } - corpus.entries = append(corpus.entries, CorpusEntry{Data: marshalCorpusFile(vals...), Values: vals}) - } if timeout > 0 { var cancel func() @@ -85,13 +82,6 @@ func CoordinateFuzzing(ctx context.Context, timeout time.Duration, parallel int, args := append([]string{"-test.fuzzworker"}, os.Args[1:]...) env := os.Environ() // same as self - c := &coordinator{ - inputC: make(chan CorpusEntry), - interestingC: make(chan CorpusEntry), - crasherC: make(chan crasherEntry), - } - errC := make(chan error) - // newWorker creates a worker but doesn't start it yet. newWorker := func() (*worker, error) { mem, err := sharedMemTempFile(workerSharedMemSize) @@ -114,6 +104,7 @@ func CoordinateFuzzing(ctx context.Context, timeout time.Duration, parallel int, fuzzCtx, cancelWorkers := context.WithCancel(ctx) defer cancelWorkers() doneC := ctx.Done() + inputC := c.inputC // stop is called when a worker encounters a fatal error. var fuzzErr error @@ -134,9 +125,11 @@ func CoordinateFuzzing(ctx context.Context, timeout time.Duration, parallel int, stopping = true cancelWorkers() doneC = nil + inputC = nil } // Start workers. + errC := make(chan error) workers := make([]*worker, parallel) for i := range workers { var err error @@ -161,7 +154,14 @@ func CoordinateFuzzing(ctx context.Context, timeout time.Duration, parallel int, // Do not return until all workers have terminated. We avoid a deadlock by // receiving messages from workers even after ctx is cancelled. activeWorkers := len(workers) - i := 0 + input, ok := c.nextInput() + if !ok { + panic("no input") + } + statTicker := time.NewTicker(3 * time.Second) + defer statTicker.Stop() + defer c.logStats() + for { select { case <-doneC: @@ -169,32 +169,48 @@ func CoordinateFuzzing(ctx context.Context, timeout time.Duration, parallel int, // stop sets doneC to nil so we don't busy wait here. stop(ctx.Err()) - case crasher := <-c.crasherC: - // A worker found a crasher. Write it to testdata and return it. - fileName, err := writeToCorpus(crasher.Data, corpusDir) - if err == nil { - err = &crashError{ - name: filepath.Base(fileName), - err: errors.New(crasher.errMsg), + case result := <-c.resultC: + // Received response from worker. + c.updateStats(result) + if c.countRequested > 0 && c.count >= c.countRequested { + stop(nil) + } + + if result.crasherMsg != "" { + // Found a crasher. Write it to testdata and return it. + fileName, err := writeToCorpus(result.entry.Data, corpusDir) + if err == nil { + err = &crashError{ + name: filepath.Base(fileName), + err: errors.New(result.crasherMsg), + } + } + // TODO(jayconrod,katiehockman): if -keepfuzzing, report the error to + // the user and restart the crashed worker. + stop(err) + } else if result.isInteresting { + // Found an interesting value that expanded coverage. + // This is not a crasher, but we should minimize it, add it to the + // on-disk corpus, and prioritize it for future fuzzing. + // TODO(jayconrod, katiehockman): Prioritize fuzzing these values which + // expanded coverage. + // TODO(jayconrod, katiehockman): Don't write a value that's already + // in the corpus. + c.corpus.entries = append(c.corpus.entries, result.entry) + if cacheDir != "" { + if _, err := writeToCorpus(result.entry.Data, cacheDir); err != nil { + stop(err) + } } } - // TODO(jayconrod,katiehockman): if -keepfuzzing, report the error to - // the user and restart the crashed worker. - stop(err) - case entry := <-c.interestingC: - // Some interesting input arrived from a worker. - // This is not a crasher, but something interesting that should - // be added to the on disk corpus and prioritized for future - // workers to fuzz. - // TODO(jayconrod, katiehockman): Prioritize fuzzing these values which - // expanded coverage. - // TODO(jayconrod, katiehockman): Don't write a value that's already - // in the corpus. - corpus.entries = append(corpus.entries, entry) - if cacheDir != "" { - if _, err := writeToCorpus(entry.Data, cacheDir); err != nil { - stop(err) + if inputC == nil && !stopping { + // inputC was disabled earlier because we hit the limit on the number + // of inputs to fuzz (nextInput returned false). + // Workers can do less work than requested though, so we might be + // below the limit now. Call nextInput again and re-enable inputC if so. + if input, ok = c.nextInput(); ok { + inputC = c.inputC } } @@ -206,11 +222,14 @@ func CoordinateFuzzing(ctx context.Context, timeout time.Duration, parallel int, return fuzzErr } - case c.inputC <- corpus.entries[i]: + case inputC <- input: // Send the next input to any worker. - // TODO(jayconrod,katiehockman): need a scheduling algorithm that chooses - // which corpus value to send next (or generates something new). - i = (i + 1) % len(corpus.entries) + if input, ok = c.nextInput(); !ok { + inputC = nil + } + + case <-statTicker.C: + c.logStats() } } @@ -261,27 +280,153 @@ type CorpusEntry = struct { Values []interface{} } -type crasherEntry struct { - CorpusEntry - errMsg string +type fuzzInput struct { + // entry is the value to test initially. The worker will randomly mutate + // values from this starting point. + entry CorpusEntry + + // countRequested is the number of values to test. If non-zero, the worker + // will stop after testing this many values, if it hasn't already stopped. + countRequested int64 +} + +type fuzzResult struct { + // entry is an interesting value or a crasher. + entry CorpusEntry + + // crasherMsg is an error message from a crash. It's "" if no crash was found. + crasherMsg string + + // isInteresting is true if the worker found new coverage. We should minimize + // the value, cache it, and prioritize it for further fuzzing. + isInteresting bool + + // countRequested is the number of values the coordinator asked the worker + // to test. 0 if there was no limit. + countRequested int64 + + // count is the number of values the worker actually tested. + count int64 + + // duration is the time the worker spent testing inputs. + duration time.Duration } // coordinator holds channels that workers can use to communicate with // the coordinator. type coordinator struct { + // log is a writer for logging progress messages and warnings. + log io.Writer + + // startTime is the time we started the workers after loading the corpus. + // Used for logging. + startTime time.Time + // inputC is sent values to fuzz by the coordinator. Any worker may receive // values from this channel. - inputC chan CorpusEntry + inputC chan fuzzInput + + // resultC is sent results of fuzzing by workers. The coordinator + // receives these. Multiple types of messages are allowed. + resultC chan fuzzResult + + // parallel is the number of worker processes. + parallel int64 + + // countRequested is the number of values the client asked to be tested. + // If countRequested is 0, there is no limit. + countRequested int64 + + // count is the number of values fuzzed so far. + count int64 + + // duration is the time spent fuzzing inside workers, not counting time + // starting up or tearing down. + duration time.Duration + + // countWaiting is the number of values the coordinator is currently waiting + // for workers to fuzz. + countWaiting int64 + + // corpus is a set of interesting values, including the seed corpus and + // generated values that workers reported as interesting. + corpus corpus + + // corpusIndex is the next value to send to workers. + // TODO(jayconrod,katiehockman): need a scheduling algorithm that chooses + // which corpus value to send next (or generates something new). + corpusIndex int +} + +func newCoordinator(w io.Writer, countRequested int64, parallel int, seed []CorpusEntry, types []reflect.Type, cacheDir string) (*coordinator, error) { + // Make sure all of the seed corpus has marshalled data. + for i := range seed { + if seed[i].Data == nil { + seed[i].Data = marshalCorpusFile(seed[i].Values...) + } + } + corpus, err := readCache(seed, types, cacheDir) + if err != nil { + return nil, err + } + if len(corpus.entries) == 0 { + var vals []interface{} + for _, t := range types { + vals = append(vals, zeroValue(t)) + } + corpus.entries = append(corpus.entries, CorpusEntry{Data: marshalCorpusFile(vals...), Values: vals}) + } + c := &coordinator{ + log: w, + startTime: time.Now(), + inputC: make(chan fuzzInput), + resultC: make(chan fuzzResult), + countRequested: countRequested, + parallel: int64(parallel), + corpus: corpus, + } + + return c, nil +} + +func (c *coordinator) updateStats(result fuzzResult) { + // Adjust total stats. + c.count += result.count + c.countWaiting -= result.countRequested + c.duration += result.duration +} + +func (c *coordinator) logStats() { + elapsed := time.Since(c.startTime) + rate := float64(c.count) / elapsed.Seconds() + fmt.Fprintf(c.log, "elapsed: %.1fs, execs: %d (%.0f/sec), workers: %d\n", elapsed.Seconds(), c.count, rate, c.parallel) +} - // interestingC is sent interesting values by the worker, which is received - // by the coordinator. Values are usually interesting because they - // increase coverage. - interestingC chan CorpusEntry +// nextInput returns the next value that should be sent to workers. +// If the number of executions is limited, the returned value includes +// a limit for one worker. If there are no executions left, nextInput returns +// a zero value and false. +func (c *coordinator) nextInput() (fuzzInput, bool) { + if c.countRequested > 0 && c.count+c.countWaiting >= c.countRequested { + // Workers already testing all requested inputs. + return fuzzInput{}, false + } - // crasherC is sent values that crashed the code being fuzzed. These values - // should be saved in the corpus, and we may want to stop fuzzing after - // receiving one. - crasherC chan crasherEntry + e := c.corpus.entries[c.corpusIndex] + c.corpusIndex = (c.corpusIndex + 1) % (len(c.corpus.entries)) + var n int64 + if c.countRequested > 0 { + n = c.countRequested / int64(c.parallel) + if c.countRequested%int64(c.parallel) > 0 { + n++ + } + remaining := c.countRequested - c.count - c.countWaiting + if n > remaining { + n = remaining + } + c.countWaiting += n + } + return fuzzInput{entry: e, countRequested: n}, true } // readCache creates a combined corpus from seed values and values in the cache diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 2c4cc1f82b..f784a04a39 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -140,8 +140,8 @@ func (w *worker) coordinate(ctx context.Context) error { case input := <-w.coordinator.inputC: // Received input from coordinator. - args := fuzzArgs{Duration: workerFuzzDuration} - value, resp, err := w.client.fuzz(ctx, input.Data, args) + args := fuzzArgs{Count: input.countRequested, Duration: workerFuzzDuration} + value, resp, err := w.client.fuzz(ctx, input.entry.Data, args) if err != nil { // Error communicating with worker. w.stop() @@ -169,25 +169,26 @@ func (w *worker) coordinate(ctx context.Context) error { value := mem.valueCopy() w.memMu <- mem message := fmt.Sprintf("fuzzing process terminated unexpectedly: %v", w.waitErr) - crasher := crasherEntry{ - CorpusEntry: CorpusEntry{Data: value}, - errMsg: message, + w.coordinator.resultC <- fuzzResult{ + entry: CorpusEntry{Data: value}, + crasherMsg: message, } - w.coordinator.crasherC <- crasher return w.waitErr - } else if resp.Crashed { - // The worker found a crasher. Inform the coordinator. - crasher := crasherEntry{ - CorpusEntry: CorpusEntry{Data: value}, - errMsg: resp.Err, - } - w.coordinator.crasherC <- crasher + } + + result := fuzzResult{ + countRequested: input.countRequested, + count: resp.Count, + duration: resp.Duration, + } + if resp.Crashed { + result.entry = CorpusEntry{Data: value} + result.crasherMsg = resp.Err } else if resp.Interesting { - // Inform the coordinator that fuzzing found something - // interesting (i.e. new coverage). - w.coordinator.interestingC <- CorpusEntry{Data: value} + result.entry = CorpusEntry{Data: value} + result.isInteresting = true } - // TODO(jayconrod,katiehockman): gather statistics. + w.coordinator.resultC <- result } } } @@ -338,7 +339,7 @@ func (w *worker) stop() error { case nil: // Still waiting. Print a message to let the user know why. - fmt.Fprintf(os.Stderr, "go: waiting for fuzzing process to terminate...\n") + fmt.Fprintf(w.coordinator.log, "waiting for fuzzing process to terminate...\n") } } } @@ -374,11 +375,23 @@ type call struct { // fuzzArgs contains arguments to workerServer.fuzz. The value to fuzz is // passed in shared memory. type fuzzArgs struct { + // Duration is the time to spend fuzzing, not including starting or + // cleaning up. Duration time.Duration + + // Count is the number of values to test, without spending more time + // than Duration. + Count int64 } // fuzzResponse contains results from workerServer.fuzz. type fuzzResponse struct { + // Duration is the time spent fuzzing, not including starting or cleaning up. + Duration time.Duration + + // Count is the number of values tested. + Count int64 + // Interesting indicates the value in shared memory may be interesting to // the coordinator (for example, because it expanded coverage). Interesting bool @@ -492,7 +505,10 @@ func (ws *workerServer) serve(ctx context.Context) error { // fuzz runs the test function on random variations of a given input value for // a given amount of time. fuzz returns early if it finds an input that crashes // the fuzz function or an input that expands coverage. -func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) fuzzResponse { +func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzResponse) { + start := time.Now() + defer func() { resp.Duration = time.Since(start) }() + fuzzCtx, cancel := context.WithTimeout(ctx, args.Duration) defer cancel() mem := <-ws.memMu @@ -502,13 +518,17 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) fuzzResponse { if err != nil { panic(err) } + for { select { case <-fuzzCtx.Done(): // TODO(jayconrod,katiehockman): this value is not interesting. Use a // real heuristic once we have one. - return fuzzResponse{Interesting: true} + resp.Interesting = true + return resp + default: + resp.Count++ ws.m.mutate(vals, cap(mem.valueRef())) writeToMem(vals, mem) if err := ws.fuzzFn(CorpusEntry{Values: vals}); err != nil { @@ -520,7 +540,18 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) fuzzResponse { // Minimization found a different error, so use that one. err = minErr } - return fuzzResponse{Crashed: true, Err: err.Error()} + resp.Crashed = true + resp.Err = err.Error() + if resp.Err == "" { + resp.Err = "fuzz function failed with no output" + } + return resp + } + if args.Count > 0 && resp.Count == args.Count { + // TODO(jayconrod,katiehockman): this value is not interesting. Use a + // real heuristic once we have one. + resp.Interesting = true + return resp } // TODO(jayconrod,katiehockman): return early if we find an // interesting value. diff --git a/src/testing/benchmark.go b/src/testing/benchmark.go index a8f75e9712..ac22ac5b26 100644 --- a/src/testing/benchmark.go +++ b/src/testing/benchmark.go @@ -32,35 +32,35 @@ var ( matchBenchmarks *string benchmarkMemory *bool - benchTime = benchTimeFlag{d: 1 * time.Second} // changed during test of testing package + benchTime = durationOrCountFlag{d: 1 * time.Second} // changed during test of testing package ) -type benchTimeFlag struct { +type durationOrCountFlag struct { d time.Duration n int } -func (f *benchTimeFlag) String() string { +func (f *durationOrCountFlag) String() string { if f.n > 0 { return fmt.Sprintf("%dx", f.n) } return time.Duration(f.d).String() } -func (f *benchTimeFlag) Set(s string) error { +func (f *durationOrCountFlag) Set(s string) error { if strings.HasSuffix(s, "x") { n, err := strconv.ParseInt(s[:len(s)-1], 10, 0) if err != nil || n <= 0 { return fmt.Errorf("invalid count") } - *f = benchTimeFlag{n: int(n)} + *f = durationOrCountFlag{n: int(n)} return nil } d, err := time.ParseDuration(s) if err != nil || d <= 0 { return fmt.Errorf("invalid duration") } - *f = benchTimeFlag{d: d} + *f = durationOrCountFlag{d: d} return nil } @@ -98,7 +98,7 @@ type B struct { previousN int // number of iterations in the previous run previousDuration time.Duration // total duration of the previous run benchFunc func(b *B) - benchTime benchTimeFlag + benchTime durationOrCountFlag bytes int64 missingBytes bool // one of the subbenchmarks does not have bytes set. timerOn bool diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 73ac59cfb4..0c1280c656 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -18,14 +18,14 @@ import ( func initFuzzFlags() { matchFuzz = flag.String("test.fuzz", "", "run the fuzz target matching `regexp`") - fuzzDuration = flag.Duration("test.fuzztime", 0, "time to spend fuzzing; default (0) is to run indefinitely") + flag.Var(&fuzzDuration, "test.fuzztime", "time to spend fuzzing default is to run indefinitely") fuzzCacheDir = flag.String("test.fuzzcachedir", "", "directory where interesting fuzzing inputs are stored") isFuzzWorker = flag.Bool("test.fuzzworker", false, "coordinate with the parent process to fuzz random values") } var ( matchFuzz *string - fuzzDuration *time.Duration + fuzzDuration durationOrCountFlag fuzzCacheDir *string isFuzzWorker *bool @@ -358,7 +358,7 @@ func (f *F) Fuzz(ff interface{}) { // actual fuzzing. corpusTargetDir := filepath.Join(corpusDir, f.name) cacheTargetDir := filepath.Join(*fuzzCacheDir, f.name) - err := f.fuzzContext.coordinateFuzzing(*fuzzDuration, *parallel, f.corpus, types, corpusTargetDir, cacheTargetDir) + err := f.fuzzContext.coordinateFuzzing(fuzzDuration.d, int64(fuzzDuration.n), *parallel, f.corpus, types, corpusTargetDir, cacheTargetDir) if err != nil { f.result = FuzzResult{Error: err} f.Fail() @@ -452,7 +452,7 @@ type fuzzCrashError interface { // fuzzContext holds all fields that are common to all fuzz targets. type fuzzContext struct { importPath func() string - coordinateFuzzing func(time.Duration, int, []corpusEntry, []reflect.Type, string, string) error + coordinateFuzzing func(time.Duration, int64, int, []corpusEntry, []reflect.Type, string, string) error runFuzzWorker func(func(corpusEntry) error) error readCorpus func(string, []reflect.Type) ([]corpusEntry, error) } diff --git a/src/testing/internal/testdeps/deps.go b/src/testing/internal/testdeps/deps.go index c77aca3da8..73c61fb54f 100644 --- a/src/testing/internal/testdeps/deps.go +++ b/src/testing/internal/testdeps/deps.go @@ -133,13 +133,13 @@ func (TestDeps) SetPanicOnExit0(v bool) { testlog.SetPanicOnExit0(v) } -func (TestDeps) CoordinateFuzzing(timeout time.Duration, parallel int, seed []fuzz.CorpusEntry, types []reflect.Type, corpusDir, cacheDir string) (err error) { +func (TestDeps) CoordinateFuzzing(timeout time.Duration, count int64, parallel int, seed []fuzz.CorpusEntry, types []reflect.Type, corpusDir, cacheDir string) (err error) { // Fuzzing may be interrupted with a timeout or if the user presses ^C. // In either case, we'll stop worker processes gracefully and save // crashers and interesting values. ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt) defer cancel() - err = fuzz.CoordinateFuzzing(ctx, timeout, parallel, seed, types, corpusDir, cacheDir) + err = fuzz.CoordinateFuzzing(ctx, os.Stderr, timeout, count, parallel, seed, types, corpusDir, cacheDir) if err == ctx.Err() { return nil } diff --git a/src/testing/sub_test.go b/src/testing/sub_test.go index 5b226f85ad..d2b966dcf9 100644 --- a/src/testing/sub_test.go +++ b/src/testing/sub_test.go @@ -669,7 +669,7 @@ func TestBRun(t *T) { w: buf, }, benchFunc: func(b *B) { ok = b.Run("test", tc.f) }, // Use Run to catch failure. - benchTime: benchTimeFlag{d: 1 * time.Microsecond}, + benchTime: durationOrCountFlag{d: 1 * time.Microsecond}, } if tc.chatty { root.chatty = newChattyPrinter(root.w) diff --git a/src/testing/testing.go b/src/testing/testing.go index 2ba93ad63d..48e9ee089f 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1326,7 +1326,7 @@ func (f matchStringOnly) ImportPath() string { return " func (f matchStringOnly) StartTestLog(io.Writer) {} func (f matchStringOnly) StopTestLog() error { return errMain } func (f matchStringOnly) SetPanicOnExit0(bool) {} -func (f matchStringOnly) CoordinateFuzzing(time.Duration, int, []corpusEntry, []reflect.Type, string, string) error { +func (f matchStringOnly) CoordinateFuzzing(time.Duration, int64, int, []corpusEntry, []reflect.Type, string, string) error { return errMain } func (f matchStringOnly) RunFuzzWorker(func(corpusEntry) error) error { return errMain } @@ -1375,7 +1375,7 @@ type testDeps interface { StartTestLog(io.Writer) StopTestLog() error WriteProfileTo(string, io.Writer, int) error - CoordinateFuzzing(time.Duration, int, []corpusEntry, []reflect.Type, string, string) error + CoordinateFuzzing(time.Duration, int64, int, []corpusEntry, []reflect.Type, string, string) error RunFuzzWorker(func(corpusEntry) error) error ReadCorpus(string, []reflect.Type) ([]corpusEntry, error) } @@ -1417,12 +1417,6 @@ func (m *M) Run() (code int) { m.exitCode = 2 return } - if *fuzzDuration < 0 { - fmt.Fprintln(os.Stderr, "testing: -fuzztime can only be given a positive duration, or zero to run indefinitely") - flag.Usage() - m.exitCode = 2 - return - } if *matchFuzz != "" && *fuzzCacheDir == "" { fmt.Fprintln(os.Stderr, "testing: internal error: -test.fuzzcachedir must be set if -test.fuzz is set") flag.Usage() -- GitLab From b2b6be71f27ef74510394dad822cfe8d5e56f4f4 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Wed, 10 Mar 2021 11:11:59 -0500 Subject: [PATCH 0060/2500] [dev.fuzz] testing: support T.Parallel in fuzz functions While running the seed corpus, T.Parallel acts like it does in subtests started with T.Run: it blocks until all other non-parallel subtests have finished, then unblocks when the barrier chan is closed. A semaphore (t.context.waitParallel) limits the number of tests that run concurrently (determined by -test.parallel). While fuzzing, T.Parallel has no effect, other than asserting that it can't be called multiple times. We already run different inputs in concurrent processes, but we can't run inputs concurrently in the same process if we want to attribute crashes to specific inputs. Change-Id: I2bac08e647e1d92ea410c83c3f3558a033fe3dd1 Reviewed-on: https://go-review.googlesource.com/c/go/+/300449 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- .../go/testdata/script/test_fuzz_parallel.txt | 61 ++++++++++++++ src/internal/fuzz/worker.go | 10 ++- src/testing/fuzz.go | 82 ++++++++++++++----- src/testing/sub_test.go | 7 +- src/testing/testing.go | 6 ++ 5 files changed, 139 insertions(+), 27 deletions(-) create mode 100644 src/cmd/go/testdata/script/test_fuzz_parallel.txt diff --git a/src/cmd/go/testdata/script/test_fuzz_parallel.txt b/src/cmd/go/testdata/script/test_fuzz_parallel.txt new file mode 100644 index 0000000000..d9f6cc720b --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_parallel.txt @@ -0,0 +1,61 @@ +# TODO(jayconrod): support shared memory on more platforms. +[!darwin] [!linux] [!windows] skip + +[short] skip + +# When running seed inputs, T.Parallel should let multiple inputs run in +# parallel. +go test -run=FuzzSeed + +# When fuzzing, T.Parallel should be safe to call, but it should have no effect. +# We just check that it doesn't hang, which would be the most obvious +# failure mode. +# TODO(jayconrod): check for the string "after T.Parallel". It's not printed +# by 'go test', so we can't distinguish that crasher from some other panic. +! go test -run=FuzzMutate -fuzz=FuzzMutate +exists testdata/corpus/FuzzMutate + +-- go.mod -- +module fuzz_parallel + +go 1.17 +-- fuzz_parallel_test.go -- +package fuzz_parallel + +import ( + "sort" + "sync" + "testing" +) + +func FuzzSeed(f *testing.F) { + for _, v := range [][]byte{{'a'}, {'b'}, {'c'}} { + f.Add(v) + } + + var mu sync.Mutex + var before, after []byte + f.Cleanup(func() { + sort.Slice(after, func(i, j int) bool { return after[i] < after[j] }) + got := string(before) + string(after) + want := "abcabc" + if got != want { + f.Fatalf("got %q; want %q", got, want) + } + }) + + f.Fuzz(func(t *testing.T, b []byte) { + before = append(before, b...) + t.Parallel() + mu.Lock() + after = append(after, b...) + mu.Unlock() + }) +} + +func FuzzMutate(f *testing.F) { + f.Fuzz(func(t *testing.T, _ []byte) { + t.Parallel() + t.Error("after T.Parallel") + }) +} diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index f784a04a39..22c85618be 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -274,18 +274,20 @@ func (w *worker) start() (err error) { // stop returns the error the process terminated with, if any (same as // w.waitErr). // -// stop must be called once after start returns successfully, even if the -// worker process terminates unexpectedly. +// stop must be called at least once after start returns successfully, even if +// the worker process terminates unexpectedly. func (w *worker) stop() error { if w.termC == nil { panic("worker was not started successfully") } select { case <-w.termC: - // Worker already terminated, perhaps unexpectedly. + // Worker already terminated. if w.client == nil { - panic("worker already stopped") + // stop already called. + return w.waitErr } + // Possible unexpected termination. w.client.Close() w.cmd = nil w.client = nil diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 0c1280c656..70e1b414a8 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -298,7 +298,6 @@ func (f *F) Fuzz(ff interface{}) { // fn is called in its own goroutine. // // TODO(jayconrod,katiehockman): dedupe testdata corpus with entries from f.Add - // TODO(jayconrod,katiehockman): handle T.Parallel calls within fuzz function. // TODO(jayconrod,katiehockman): improve output when running the subtest. // e.g. instead of // --- FAIL: FuzzSomethingError/#00 (0.00s) @@ -485,11 +484,12 @@ func runFuzzTargets(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran, ok bo } f := &F{ common: common{ - signal: make(chan bool), - name: testName, - parent: &root, - level: root.level + 1, - chatty: root.chatty, + signal: make(chan bool), + barrier: make(chan bool), + name: testName, + parent: &root, + level: root.level + 1, + chatty: root.chatty, }, testContext: tctx, fuzzContext: fctx, @@ -548,11 +548,12 @@ func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran, ok bool) target = ft f = &F{ common: common{ - signal: make(chan bool), - name: testName, - parent: &root, - level: root.level + 1, - chatty: root.chatty, + signal: make(chan bool), + barrier: nil, // T.Parallel has no effect when fuzzing. + name: testName, + parent: &root, + level: root.level + 1, + chatty: root.chatty, }, fuzzContext: fctx, testContext: tctx, @@ -576,7 +577,10 @@ func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran, ok bool) // // fRunner is analogous with tRunner, which wraps subtests started with T.Run. // Tests and fuzz targets work a little differently, so for now, these functions -// aren't consoldiated. +// aren't consolidated. In particular, because there are no F.Run and F.Parallel +// methods, i.e., no fuzz sub-targets or parallel fuzz targets, a few +// simplifications are made. We also require that F.Fuzz, F.Skip, or F.Fail is +// called. func fRunner(f *F, fn func(*F)) { // When this goroutine is done, either because runtime.Goexit was called, // a panic started, or fn returned normally, record the duration and send @@ -599,10 +603,29 @@ func fRunner(f *F, fn func(*F)) { err = errNilPanicOrGoexit } + // Use a deferred call to ensure that we report that the test is + // complete even if a cleanup function calls t.FailNow. See issue 41355. + didPanic := false + defer func() { + if didPanic { + return + } + if err != nil { + panic(err) + } + // Only report that the test is complete if it doesn't panic, + // as otherwise the test binary can exit before the panic is + // reported to the user. See issue 41479. + f.signal <- true + }() + // If we recovered a panic or inappropriate runtime.Goexit, fail the test, // flush the output log up to the root, then panic. - if err != nil { + doPanic := func(err interface{}) { f.Fail() + if r := f.runCleanup(recoverAndReturnPanic); r != nil { + f.Logf("cleanup panicked with %v", r) + } for root := &f.common; root.parent != nil; root = root.parent { root.mu.Lock() root.duration += time.Since(root.start) @@ -610,22 +633,41 @@ func fRunner(f *F, fn func(*F)) { root.mu.Unlock() root.flushToParent(root.name, "--- FAIL: %s (%s)\n", root.name, fmtDuration(d)) } + didPanic = true panic(err) } + if err != nil { + doPanic(err) + } - // No panic or inappropriate Goexit. Record duration and report the result. + // No panic or inappropriate Goexit. f.duration += time.Since(f.start) + + if len(f.sub) > 0 { + // Run parallel inputs. + // Release the parallel subtests. + close(f.barrier) + // Wait for the subtests to complete. + for _, sub := range f.sub { + <-sub.signal + } + cleanupStart := time.Now() + err := f.runCleanup(recoverAndReturnPanic) + f.duration += time.Since(cleanupStart) + if err != nil { + doPanic(err) + } + } + + // Report after all subtests have finished. f.report() f.done = true f.setRan() - - // Only report that the test is complete if it doesn't panic, - // as otherwise the test binary can exit before the panic is - // reported to the user. See issue 41479. - f.signal <- true }() defer func() { - f.runCleanup(normalPanic) + if len(f.sub) == 0 { + f.runCleanup(normalPanic) + } }() f.start = time.Now() diff --git a/src/testing/sub_test.go b/src/testing/sub_test.go index d2b966dcf9..2d9e145a73 100644 --- a/src/testing/sub_test.go +++ b/src/testing/sub_test.go @@ -480,9 +480,10 @@ func TestTRun(t *T) { buf := &bytes.Buffer{} root := &T{ common: common{ - signal: make(chan bool), - name: "Test", - w: buf, + signal: make(chan bool), + barrier: make(chan bool), + name: "Test", + w: buf, }, context: ctx, } diff --git a/src/testing/testing.go b/src/testing/testing.go index 48e9ee089f..da26dec6fb 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1039,6 +1039,12 @@ func (t *T) Parallel() { panic("testing: t.Parallel called multiple times") } t.isParallel = true + if t.parent.barrier == nil { + // T.Parallel has no effect when fuzzing. + // Multiple processes may run in parallel, but only one input can run at a + // time per process so we can attribute crashes to specific inputs. + return + } // We don't want to include the time we spend waiting for serial tests // in the test duration. Record the elapsed time thus far and reset the -- GitLab From 88c0c2d9ea9c57eb3c5915d9e90ec59ae5a35a35 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Wed, 7 Apr 2021 17:24:06 -0400 Subject: [PATCH 0061/2500] [dev.fuzz] internal/fuzz: move CoordinateFuzzing args into struct type This improves readability a bit, and it should help with compatibility for future clients when arguments are added or reordered. Unfortunately, testing still can't import internal/fuzz, so the interface there can't use this type. Change-Id: I4cda2347884defcbbfc2bd01ab5b4a901d91549c Reviewed-on: https://go-review.googlesource.com/c/go/+/308192 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod Reviewed-by: Katie Hockman --- src/internal/fuzz/fuzz.go | 137 ++++++++++++++------------ src/internal/fuzz/worker.go | 2 +- src/testing/internal/testdeps/deps.go | 11 ++- 3 files changed, 83 insertions(+), 67 deletions(-) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 5d4fcb9a66..f8c72dbff1 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -22,6 +22,42 @@ import ( "time" ) +// CoordinateFuzzingOpts is a set of arguments for CoordinateFuzzing. +// The zero value is valid for each field unless specified otherwise. +type CoordinateFuzzingOpts struct { + // Log is a writer for logging progress messages and warnings. + // If nil, io.Discard will be used instead. + Log io.Writer + + // Timeout is the amount of wall clock time to spend fuzzing after the corpus + // has loaded. If zero, there will be no time limit. + Timeout time.Duration + + // Count is the number of random values to generate and test. If zero, + // there will be no limit on the number of generated values. + Count int64 + + // parallel is the number of worker processes to run in parallel. If zero, + // CoordinateFuzzing will run GOMAXPROCS workers. + Parallel int + + // Seed is a list of seed values added by the fuzz target with testing.F.Add + // and in testdata. + Seed []CorpusEntry + + // Types is the list of types which make up a corpus entry. + // Types must be set and must match values in Seed. + Types []reflect.Type + + // CorpusDir is a directory where files containing values that crash the + // code being tested may be written. CorpusDir must be set. + CorpusDir string + + // CacheDir is a directory containing additional "interesting" values. + // The fuzzer may derive new values from these, and may write new values here. + CacheDir string +} + // CoordinateFuzzing creates several worker processes and communicates with // them to test random inputs that could trigger crashes and expose bugs. // The worker processes run the same binary in the same directory with the @@ -29,50 +65,31 @@ import ( // with the same arguments as the coordinator, except with the -test.fuzzworker // flag prepended to the argument list. // -// log is a writer for logging progress messages and warnings. -// -// timeout is the amount of wall clock time to spend fuzzing after the corpus -// has loaded. -// -// count is the number of random values to generate and test. If 0, -// CoordinateFuzzing will run until ctx is canceled. -// -// parallel is the number of worker processes to run in parallel. If parallel -// is 0, CoordinateFuzzing will run GOMAXPROCS workers. -// -// seed is a list of seed values added by the fuzz target with testing.F.Add and -// in testdata. -// -// types is the list of types which make up a corpus entry. -// -// corpusDir is a directory where files containing values that crash the -// code being tested may be written. -// -// cacheDir is a directory containing additional "interesting" values. -// The fuzzer may derive new values from these, and may write new values here. -// // If a crash occurs, the function will return an error containing information // about the crash, which can be reported to the user. -func CoordinateFuzzing(ctx context.Context, log io.Writer, timeout time.Duration, count int64, parallel int, seed []CorpusEntry, types []reflect.Type, corpusDir, cacheDir string) (err error) { +func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err error) { if err := ctx.Err(); err != nil { return err } - if parallel == 0 { - parallel = runtime.GOMAXPROCS(0) + if opts.Log == nil { + opts.Log = io.Discard + } + if opts.Parallel == 0 { + opts.Parallel = runtime.GOMAXPROCS(0) } - if count > 0 && int64(parallel) > count { + if opts.Count > 0 && int64(opts.Parallel) > opts.Count { // Don't start more workers than we need. - parallel = int(count) + opts.Parallel = int(opts.Count) } - c, err := newCoordinator(log, count, parallel, seed, types, cacheDir) + c, err := newCoordinator(opts) if err != nil { return err } - if timeout > 0 { + if opts.Timeout > 0 { var cancel func() - ctx, cancel = context.WithTimeout(ctx, timeout) + ctx, cancel = context.WithTimeout(ctx, opts.Timeout) defer cancel() } @@ -130,7 +147,7 @@ func CoordinateFuzzing(ctx context.Context, log io.Writer, timeout time.Duration // Start workers. errC := make(chan error) - workers := make([]*worker, parallel) + workers := make([]*worker, opts.Parallel) for i := range workers { var err error workers[i], err = newWorker() @@ -172,13 +189,13 @@ func CoordinateFuzzing(ctx context.Context, log io.Writer, timeout time.Duration case result := <-c.resultC: // Received response from worker. c.updateStats(result) - if c.countRequested > 0 && c.count >= c.countRequested { + if c.opts.Count > 0 && c.count >= c.opts.Count { stop(nil) } if result.crasherMsg != "" { // Found a crasher. Write it to testdata and return it. - fileName, err := writeToCorpus(result.entry.Data, corpusDir) + fileName, err := writeToCorpus(result.entry.Data, opts.CorpusDir) if err == nil { err = &crashError{ name: filepath.Base(fileName), @@ -197,8 +214,8 @@ func CoordinateFuzzing(ctx context.Context, log io.Writer, timeout time.Duration // TODO(jayconrod, katiehockman): Don't write a value that's already // in the corpus. c.corpus.entries = append(c.corpus.entries, result.entry) - if cacheDir != "" { - if _, err := writeToCorpus(result.entry.Data, cacheDir); err != nil { + if opts.CacheDir != "" { + if _, err := writeToCorpus(result.entry.Data, opts.CacheDir); err != nil { stop(err) } } @@ -233,8 +250,8 @@ func CoordinateFuzzing(ctx context.Context, log io.Writer, timeout time.Duration } } - // TODO(jayconrod,katiehockman): if a crasher can't be written to corpusDir, - // write to cacheDir instead. + // TODO(jayconrod,katiehockman): if a crasher can't be written to the corpus, + // write to the cache instead. } // crashError wraps a crasher written to the seed corpus. It saves the name @@ -315,8 +332,7 @@ type fuzzResult struct { // coordinator holds channels that workers can use to communicate with // the coordinator. type coordinator struct { - // log is a writer for logging progress messages and warnings. - log io.Writer + opts CoordinateFuzzingOpts // startTime is the time we started the workers after loading the corpus. // Used for logging. @@ -330,13 +346,6 @@ type coordinator struct { // receives these. Multiple types of messages are allowed. resultC chan fuzzResult - // parallel is the number of worker processes. - parallel int64 - - // countRequested is the number of values the client asked to be tested. - // If countRequested is 0, there is no limit. - countRequested int64 - // count is the number of values fuzzed so far. count int64 @@ -358,32 +367,30 @@ type coordinator struct { corpusIndex int } -func newCoordinator(w io.Writer, countRequested int64, parallel int, seed []CorpusEntry, types []reflect.Type, cacheDir string) (*coordinator, error) { +func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { // Make sure all of the seed corpus has marshalled data. - for i := range seed { - if seed[i].Data == nil { - seed[i].Data = marshalCorpusFile(seed[i].Values...) + for i := range opts.Seed { + if opts.Seed[i].Data == nil { + opts.Seed[i].Data = marshalCorpusFile(opts.Seed[i].Values...) } } - corpus, err := readCache(seed, types, cacheDir) + corpus, err := readCache(opts.Seed, opts.Types, opts.CacheDir) if err != nil { return nil, err } if len(corpus.entries) == 0 { var vals []interface{} - for _, t := range types { + for _, t := range opts.Types { vals = append(vals, zeroValue(t)) } corpus.entries = append(corpus.entries, CorpusEntry{Data: marshalCorpusFile(vals...), Values: vals}) } c := &coordinator{ - log: w, - startTime: time.Now(), - inputC: make(chan fuzzInput), - resultC: make(chan fuzzResult), - countRequested: countRequested, - parallel: int64(parallel), - corpus: corpus, + opts: opts, + startTime: time.Now(), + inputC: make(chan fuzzInput), + resultC: make(chan fuzzResult), + corpus: corpus, } return c, nil @@ -399,7 +406,7 @@ func (c *coordinator) updateStats(result fuzzResult) { func (c *coordinator) logStats() { elapsed := time.Since(c.startTime) rate := float64(c.count) / elapsed.Seconds() - fmt.Fprintf(c.log, "elapsed: %.1fs, execs: %d (%.0f/sec), workers: %d\n", elapsed.Seconds(), c.count, rate, c.parallel) + fmt.Fprintf(c.opts.Log, "elapsed: %.1fs, execs: %d (%.0f/sec), workers: %d\n", elapsed.Seconds(), c.count, rate, c.opts.Parallel) } // nextInput returns the next value that should be sent to workers. @@ -407,7 +414,7 @@ func (c *coordinator) logStats() { // a limit for one worker. If there are no executions left, nextInput returns // a zero value and false. func (c *coordinator) nextInput() (fuzzInput, bool) { - if c.countRequested > 0 && c.count+c.countWaiting >= c.countRequested { + if c.opts.Count > 0 && c.count+c.countWaiting >= c.opts.Count { // Workers already testing all requested inputs. return fuzzInput{}, false } @@ -415,12 +422,12 @@ func (c *coordinator) nextInput() (fuzzInput, bool) { e := c.corpus.entries[c.corpusIndex] c.corpusIndex = (c.corpusIndex + 1) % (len(c.corpus.entries)) var n int64 - if c.countRequested > 0 { - n = c.countRequested / int64(c.parallel) - if c.countRequested%int64(c.parallel) > 0 { + if c.opts.Count > 0 { + n = c.opts.Count / int64(c.opts.Parallel) + if c.opts.Count%int64(c.opts.Parallel) > 0 { n++ } - remaining := c.countRequested - c.count - c.countWaiting + remaining := c.opts.Count - c.count - c.countWaiting if n > remaining { n = remaining } diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 22c85618be..c130f691f4 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -341,7 +341,7 @@ func (w *worker) stop() error { case nil: // Still waiting. Print a message to let the user know why. - fmt.Fprintf(w.coordinator.log, "waiting for fuzzing process to terminate...\n") + fmt.Fprintf(w.coordinator.opts.Log, "waiting for fuzzing process to terminate...\n") } } } diff --git a/src/testing/internal/testdeps/deps.go b/src/testing/internal/testdeps/deps.go index 73c61fb54f..b9c110100f 100644 --- a/src/testing/internal/testdeps/deps.go +++ b/src/testing/internal/testdeps/deps.go @@ -139,7 +139,16 @@ func (TestDeps) CoordinateFuzzing(timeout time.Duration, count int64, parallel i // crashers and interesting values. ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt) defer cancel() - err = fuzz.CoordinateFuzzing(ctx, os.Stderr, timeout, count, parallel, seed, types, corpusDir, cacheDir) + err = fuzz.CoordinateFuzzing(ctx, fuzz.CoordinateFuzzingOpts{ + Log: os.Stderr, + Timeout: timeout, + Count: count, + Parallel: parallel, + Seed: seed, + Types: types, + CorpusDir: corpusDir, + CacheDir: cacheDir, + }) if err == ctx.Err() { return nil } -- GitLab From 8b96efd8a274a65504dc9051e0545379d26f8445 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Fri, 9 Apr 2021 15:50:40 -0400 Subject: [PATCH 0062/2500] [dev.fuzz] internal/fuzz: allow float types to be integer literals Previously, something like `float64(0)` would fail to decode since the 0 value is considered an integer literal, and the float64 parsing code required a float literal. Be more flexible here since an integer can always be converted to a float. Change-Id: Id1c53ef2e8a9748a4f71176b00b453a329af4ade Reviewed-on: https://go-review.googlesource.com/c/go/+/309032 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/internal/fuzz/encoding.go | 8 ++++---- src/internal/fuzz/encoding_test.go | 7 +++++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/internal/fuzz/encoding.go b/src/internal/fuzz/encoding.go index c018ef5fe2..c2f7d22b75 100644 --- a/src/internal/fuzz/encoding.go +++ b/src/internal/fuzz/encoding.go @@ -181,14 +181,14 @@ func parseCorpusValue(line []byte) (interface{}, error) { } return parseUint(val, typ) case "float32": - if kind != token.FLOAT { - return nil, fmt.Errorf("float literal required for float32 type") + if kind != token.FLOAT && kind != token.INT { + return nil, fmt.Errorf("float or integer literal required for float32 type") } v, err := strconv.ParseFloat(val, 32) return float32(v), err case "float64": - if kind != token.FLOAT { - return nil, fmt.Errorf("float literal required for float64 type") + if kind != token.FLOAT && kind != token.INT { + return nil, fmt.Errorf("float or integer literal required for float64 type") } return strconv.ParseFloat(val, 64) default: diff --git a/src/internal/fuzz/encoding_test.go b/src/internal/fuzz/encoding_test.go index cbf4999f8d..3cd8d0e2ab 100644 --- a/src/internal/fuzz/encoding_test.go +++ b/src/internal/fuzz/encoding_test.go @@ -72,6 +72,13 @@ string("extra") }, { in: `go test fuzz v1 +float64(0) +float32(0) +`, + ok: true, // will be an integer literal since there is no decimal + }, + { + in: `go test fuzz v1 int(-23) int8(-2) int64(2342425) -- GitLab From 529e5d0c7dc734f3fa6ae69ad6afdb3e185d2c1c Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Fri, 9 Apr 2021 16:01:26 -0400 Subject: [PATCH 0063/2500] [dev.fuzz] internal/fuzz: mutate other types Change-Id: I8042c17268aca0a9bb2f692317207bb864b18680 Reviewed-on: https://go-review.googlesource.com/c/go/+/309033 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- .../script/test_fuzz_mutate_crash.txt | 120 +++++++++++--- src/internal/fuzz/mutator.go | 151 ++++++++++++++++-- 2 files changed, 237 insertions(+), 34 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt index f8ee63b109..76e7907bf1 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt @@ -22,18 +22,6 @@ go run check_testdata.go FuzzWithBug # the target, and should fail when run without fuzzing. ! go test -# Running the fuzzer should find a crashing input quickly for fuzzing two types. -! go test -run=FuzzWithTwoTypes -fuzz=FuzzWithTwoTypes -fuzztime=100x -stdout 'testdata[/\\]corpus[/\\]FuzzWithTwoTypes[/\\]' -stdout 'these inputs caused a crash!' -go run check_testdata.go FuzzWithTwoTypes - -# Running the fuzzer should find a crashing input quickly for an integer -! go test -run=FuzzInt -fuzz=FuzzInt -fuzztime=100x -stdout 'testdata[/\\]corpus[/\\]FuzzInt[/\\]' -stdout 'this input caused a crash!' -go run check_testdata.go FuzzInt - ! go test -run=FuzzWithNilPanic -fuzz=FuzzWithNilPanic -fuzztime=100x stdout 'testdata[/\\]corpus[/\\]FuzzWithNilPanic[/\\]' stdout 'runtime.Goexit' @@ -63,6 +51,53 @@ stdout 'testdata[/\\]corpus[/\\]FuzzWithBadExit[/\\]' stdout 'unexpectedly' go run check_testdata.go FuzzWithBadExit +# Running the fuzzer should find a crashing input quickly for fuzzing two types. +! go test -run=FuzzWithTwoTypes -fuzz=FuzzWithTwoTypes -fuzztime=100x +stdout 'testdata[/\\]corpus[/\\]FuzzWithTwoTypes[/\\]' +stdout 'these inputs caused a crash!' +go run check_testdata.go FuzzWithTwoTypes + +# Running the fuzzer should find a crashing input quickly for an integer. +! go test -run=FuzzInt -fuzz=FuzzInt -fuzztime=100x +stdout 'testdata[/\\]corpus[/\\]FuzzInt[/\\]' +stdout 'this input caused a crash!' +go run check_testdata.go FuzzInt + +! go test -run=FuzzUint -fuzz=FuzzUint -fuzztime=100x +stdout 'testdata[/\\]corpus[/\\]FuzzUint[/\\]' +stdout 'this input caused a crash!' +go run check_testdata.go FuzzUint + +# Running the fuzzer should find a crashing input quickly for a bool. +! go test -run=FuzzBool -fuzz=FuzzBool -fuzztime=100x +stdout 'testdata[/\\]corpus[/\\]FuzzBool[/\\]' +stdout 'this input caused a crash!' +go run check_testdata.go FuzzBool + +# Running the fuzzer should find a crashing input quickly for a float. +! go test -run=FuzzFloat -fuzz=FuzzFloat -fuzztime=100x +stdout 'testdata[/\\]corpus[/\\]FuzzFloat[/\\]' +stdout 'this input caused a crash!' +go run check_testdata.go FuzzFloat + +# Running the fuzzer should find a crashing input quickly for a byte. +! go test -run=FuzzByte -fuzz=FuzzByte -fuzztime=100x +stdout 'testdata[/\\]corpus[/\\]FuzzByte[/\\]' +stdout 'this input caused a crash!' +go run check_testdata.go FuzzByte + +# Running the fuzzer should find a crashing input quickly for a rune. +! go test -run=FuzzRune -fuzz=FuzzRune -fuzztime=100x +stdout 'testdata[/\\]corpus[/\\]FuzzRune[/\\]' +stdout 'this input caused a crash!' +go run check_testdata.go FuzzRune + +# Running the fuzzer should find a crashing input quickly for a string. +! go test -run=FuzzString -fuzz=FuzzString -fuzztime=100x +stdout 'testdata[/\\]corpus[/\\]FuzzString[/\\]' +stdout 'this input caused a crash!' +go run check_testdata.go FuzzString + -- go.mod -- module m @@ -130,6 +165,15 @@ func FuzzWithFatalf(f *testing.F) { }) } +func FuzzWithBadExit(f *testing.F) { + f.Add([]byte("aa")) + f.Fuzz(func(t *testing.T, b []byte) { + if string(b) != "aa" { + os.Exit(1) + } + }) +} + func FuzzWithTwoTypes(f *testing.F) { f.Fuzz(func(t *testing.T, a, b []byte) { if len(a) > 0 && len(b) > 0 { @@ -140,17 +184,57 @@ func FuzzWithTwoTypes(f *testing.F) { func FuzzInt(f *testing.F) { f.Fuzz(func(t *testing.T, a int) { - if 200 > a && a < 250 { + if a > 200 && a < 250 { panic("this input caused a crash!") } }) } -func FuzzWithBadExit(f *testing.F) { - f.Add([]byte("aa")) - f.Fuzz(func(t *testing.T, b []byte) { - if string(b) != "aa" { - os.Exit(1) +func FuzzUint(f *testing.F) { + f.Fuzz(func(t *testing.T, a uint) { + if a > 200 && a < 250 { + panic("this input caused a crash!") + } + }) +} + +func FuzzBool(f *testing.F) { + f.Fuzz(func(t *testing.T, a bool) { + if a { + panic("this input caused a crash!") + } + }) +} + +func FuzzFloat(f *testing.F) { + f.Fuzz(func(t *testing.T, a float64) { + if a != float64(int64(a)) { + // It has a decimal, so it was mutated by division + panic("this input caused a crash!") + } + }) +} + +func FuzzByte(f *testing.F) { + f.Fuzz(func(t *testing.T, a byte) { + if a > 50 { + panic("this input caused a crash!") + } + }) +} + +func FuzzRune(f *testing.F) { + f.Fuzz(func(t *testing.T, a rune) { + if a > 50 { + panic("this input caused a crash!") + } + }) +} + +func FuzzString(f *testing.F) { + f.Fuzz(func(t *testing.T, a string) { + if a != "" { + panic("this input caused a crash!") } }) } diff --git a/src/internal/fuzz/mutator.go b/src/internal/fuzz/mutator.go index e4ee2f44ea..88cb7b4e03 100644 --- a/src/internal/fuzz/mutator.go +++ b/src/internal/fuzz/mutator.go @@ -55,7 +55,7 @@ func min(a, b int) int { func (m *mutator) mutate(vals []interface{}, maxBytes int) { // TODO(katiehockman): pull some of these functions into helper methods and // test that each case is working as expected. - // TODO(katiehockman): perform more types of mutations. + // TODO(katiehockman): perform more types of mutations for []byte. // maxPerVal will represent the maximum number of bytes that each value be // allowed after mutating, giving an equal amount of capacity to each line. @@ -65,8 +65,48 @@ func (m *mutator) mutate(vals []interface{}, maxBytes int) { // Pick a random value to mutate. // TODO: consider mutating more than one value at a time. i := m.rand(len(vals)) - // TODO(katiehockman): support mutating other types switch v := vals[i].(type) { + case int: + vals[i] = int(m.mutateInt(int64(v), maxInt)) + case int8: + vals[i] = int8(m.mutateInt(int64(v), math.MaxInt8)) + case int16: + vals[i] = int16(m.mutateInt(int64(v), math.MaxInt16)) + case int64: + vals[i] = m.mutateInt(v, maxInt) + case uint: + vals[i] = uint(m.mutateUInt(uint64(v), maxUint)) + case uint16: + vals[i] = uint16(m.mutateUInt(uint64(v), math.MaxUint16)) + case uint32: + vals[i] = uint32(m.mutateUInt(uint64(v), math.MaxUint32)) + case uint64: + vals[i] = m.mutateUInt(uint64(v), maxUint) + case float32: + vals[i] = float32(m.mutateFloat(float64(v), math.MaxFloat32)) + case float64: + vals[i] = m.mutateFloat(v, math.MaxFloat64) + case bool: + if m.rand(2) == 1 { + vals[i] = !v // 50% chance of flipping the bool + } + case rune: // int32 + vals[i] = rune(m.mutateInt(int64(v), math.MaxInt32)) + case byte: // uint8 + vals[i] = byte(m.mutateUInt(uint64(v), math.MaxUint8)) + case string: + // TODO(jayconrod,katiehockman): Keep a []byte somewhere (maybe in + // mutator) that we mutate repeatedly to avoid re-allocating the data + // every time. + if len(v) > maxPerVal { + panic(fmt.Sprintf("cannot mutate bytes of length %d", len(v))) + } + b := []byte(v) + if cap(b) < maxPerVal { + b = append(make([]byte, 0, maxPerVal), b...) + } + m.mutateBytes(&b) + vals[i] = string(b) case []byte: if len(v) > maxPerVal { panic(fmt.Sprintf("cannot mutate bytes of length %d", len(v))) @@ -76,16 +116,6 @@ func (m *mutator) mutate(vals []interface{}, maxBytes int) { } m.mutateBytes(&v) vals[i] = v - case int8: - vals[i] = int8(m.mutateInt(int64(v), math.MaxInt8)) - case int16: - vals[i] = int16(m.mutateInt(int64(v), math.MaxInt16)) - case int32: - vals[i] = int32(m.mutateInt(int64(v), math.MaxInt32)) - case int64: - vals[i] = m.mutateInt(v, int64(maxInt)) - case int: - vals[i] = int(m.mutateInt(int64(v), int64(maxInt))) default: panic(fmt.Sprintf("type not supported for mutating: %T", vals[i])) } @@ -95,10 +125,78 @@ func (m *mutator) mutateInt(v, maxValue int64) int64 { numIters := 1 + m.r.exp2() var max int64 for iter := 0; iter < numIters; iter++ { + max = 100 + switch m.rand(2) { + case 0: + // Add a random number + if v >= maxValue { + iter-- + continue + } + if v > 0 && maxValue-v < max { + // Don't let v exceed maxValue + max = maxValue - v + } + v += int64(1 + m.rand(int(max))) + case 1: + // Subtract a random number + if v <= -maxValue { + iter-- + continue + } + if v < 0 && maxValue+v < max { + // Don't let v drop below -maxValue + max = maxValue + v + } + v -= int64(1 + m.rand(int(max))) + } + } + return v +} + +func (m *mutator) mutateUInt(v, maxValue uint64) uint64 { + numIters := 1 + m.r.exp2() + var max uint64 + for iter := 0; iter < numIters; iter++ { + max = 100 switch m.rand(2) { case 0: // Add a random number if v >= maxValue { + iter-- + continue + } + if v > 0 && maxValue-v < max { + // Don't let v exceed maxValue + max = maxValue - v + } + + v += uint64(1 + m.rand(int(max))) + case 1: + // Subtract a random number + if v <= 0 { + iter-- + continue + } + if v < max { + // Don't let v drop below 0 + max = v + } + v -= uint64(1 + m.rand(int(max))) + } + } + return v +} + +func (m *mutator) mutateFloat(v, maxValue float64) float64 { + numIters := 1 + m.r.exp2() + var max float64 + for iter := 0; iter < numIters; iter++ { + switch m.rand(4) { + case 0: + // Add a random number + if v >= maxValue { + iter-- continue } max = 100 @@ -106,10 +204,11 @@ func (m *mutator) mutateInt(v, maxValue int64) int64 { // Don't let v exceed maxValue max = maxValue - v } - v += int64(m.rand(int(max))) + v += float64(1 + m.rand(int(max))) case 1: // Subtract a random number if v <= -maxValue { + iter-- continue } max = 100 @@ -117,7 +216,27 @@ func (m *mutator) mutateInt(v, maxValue int64) int64 { // Don't let v drop below -maxValue max = maxValue + v } - v -= int64(m.rand(int(max))) + v -= float64(1 + m.rand(int(max))) + case 2: + // Multiply by a random number + absV := math.Abs(v) + if v == 0 || absV >= maxValue { + iter-- + continue + } + max = 10 + if maxValue/absV < max { + // Don't let v go beyond the minimum or maximum value + max = maxValue / absV + } + v *= float64(1 + m.rand(int(max))) + case 3: + // Divide by a random number + if v == 0 { + iter-- + continue + } + v /= float64(1 + m.rand(10)) } } return v @@ -311,8 +430,8 @@ var ( ) const ( - maxUint = ^uint(0) - maxInt = maxUint >> 1 + maxUint = uint64(^uint(0)) + maxInt = int64(maxUint >> 1) ) func init() { -- GitLab From 7a7eee8ab72908b79ac10ba3f817447dd59e7642 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Fri, 26 Mar 2021 16:12:45 -0400 Subject: [PATCH 0064/2500] [dev.fuzz] internal/fuzz: minimize non-recoverable errors Assuming that this works for non-recoverable errors, there will likely be a follow-up CL which refactors the minimization for recoverable errors to use the same RPC flow (since that more easily allows the worker to tell the coordinator that it's minimizing and shouldn't send more inputs to other workers to fuzz). Change-Id: I32ac7cec4abe2d4c345c0ee77315233047efb1fb Reviewed-on: https://go-review.googlesource.com/c/go/+/309509 Trust: Katie Hockman Run-TryBot: Katie Hockman Reviewed-by: Jay Conrod --- .../go/testdata/script/test_fuzz_mutator.txt | 121 +++++++++++++++- src/internal/fuzz/fuzz.go | 5 + src/internal/fuzz/worker.go | 137 ++++++++++++++++-- 3 files changed, 241 insertions(+), 22 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_mutator.txt b/src/cmd/go/testdata/script/test_fuzz_mutator.txt index aa2b8ff83f..c29912b65a 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutator.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutator.txt @@ -20,15 +20,40 @@ stdout FAIL stdout 'mutator found enough unique mutations' # Test that minimization is working for recoverable errors. -! go test -v -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -parallel=1 -fuzztime=10s minimizer_test.go +! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10s minimizer_test.go ! stdout '^ok' stdout 'got the minimum size!' stdout 'contains a letter' stdout FAIL +# Check that the bytes written to testdata are of length 100 (the minimum size) +go run check_testdata.go FuzzMinimizerRecoverable 100 + # Test that re-running the minimized value causes a crash. ! go test -run=FuzzMinimizerRecoverable minimizer_test.go +# Test that minimization is working for non-recoverable errors. +! go test -fuzz=FuzzMinimizerNonrecoverable -run=FuzzMinimizerNonrecoverable -fuzztime=10s minimizer_test.go +! stdout '^ok' +stdout 'got the minimum size!' +stdout 'contains a letter' +stdout FAIL + +# Check that the bytes written to testdata are of length 100 (the minimum size) +go run check_testdata.go FuzzMinimizerNonrecoverable 100 + +# Test that minimization can be cancelled by fuzztime and the latest crash will +# still be logged and written to testdata. +! go test -fuzz=FuzzNonMinimizable -run=FuzzNonMinimizable -parallel=1 -fuzztime=5s minimizer_test.go +! stdout '^ok' +stdout 'testdata[/\\]corpus[/\\]FuzzNonMinimizable[/\\]' +! stdout 'got the minimum size!' # it shouldn't have had enough time to minimize it +stdout 'at least 100 bytes' +stdout FAIL + +# TODO(jayconrod,katiehockman): add a test which verifies that the right bytes +# are written to testdata in the case of an interrupt during minimization. + -- go.mod -- module m @@ -83,6 +108,7 @@ package fuzz_test import ( "bytes" "testing" + "time" ) func FuzzMinimizerRecoverable(f *testing.F) { @@ -91,17 +117,48 @@ func FuzzMinimizerRecoverable(f *testing.F) { // Make sure that b is large enough that it can be minimized return } - if len(b) == 100 { - t.Logf("got the minimum size!") - } + // Given the randomness of the mutations, this should allow the + // minimizer to trim down the value a bit. if bytes.ContainsAny(b, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") { - // Given the randomness of the mutations, this should allow the - // minimizer to trim down the value quite a bit. + if len(b) == 100 { + t.Logf("got the minimum size!") + } t.Errorf("contains a letter") } }) } +func FuzzMinimizerNonrecoverable(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + if len(b) < 100 { + // Make sure that b is large enough that it can be minimized + return + } + // Given the randomness of the mutations, this should allow the + // minimizer to trim down the value quite a bit. + if bytes.ContainsAny(b, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") { + if len(b) == 100 { + t.Logf("got the minimum size!") + } + panic("contains a letter") + } + }) +} + +func FuzzNonMinimizable(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + if len(b) < 10 { + // Make sure that b is large enough that minimization will try to run. + return + } + time.Sleep(3 * time.Second) + if len(b) == 10 { + t.Logf("got the minimum size!") + } + panic("at least 100 bytes") + }) +} + -- check_logs.go -- // +build ignore @@ -195,7 +252,59 @@ func checkWorkerLog(r io.Reader) error { } return nil } +-- check_testdata.go -- +// +build ignore + +package main + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strconv" +) +func main() { + target := os.Args[1] + numBytes, err := strconv.Atoi(os.Args[2]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + + // Open the file in testdata (there should only be one) + dir := fmt.Sprintf("testdata/corpus/%s", target) + files, err := ioutil.ReadDir(dir) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + if len(files) != 1 { + fmt.Fprintf(os.Stderr, "expected one file, got %d", len(files)) + os.Exit(1) + } + got, err := ioutil.ReadFile(filepath.Join(dir, files[0].Name())) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + + // Make sure that there were exactly 100 bytes written to the corpus entry + prefix := []byte("[]byte(") + i := bytes.Index(got, prefix) + gotBytes := got[i+len(prefix) : len(got)-1] + s, err := strconv.Unquote(string(gotBytes)) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + if want, got := numBytes, len(s); want != got { + fmt.Fprintf(os.Stderr, "want %d bytes, got %d", want, got) + os.Exit(1) + } +} -- mutator_test.go -- package fuzz_test diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index f8c72dbff1..586b51188c 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -178,6 +178,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err statTicker := time.NewTicker(3 * time.Second) defer statTicker.Stop() defer c.logStats() + crashWritten := false for { select { @@ -195,8 +196,12 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err if result.crasherMsg != "" { // Found a crasher. Write it to testdata and return it. + if crashWritten { + break + } fileName, err := writeToCorpus(result.entry.Data, opts.CorpusDir) if err == nil { + crashWritten = true err = &crashError{ name: filepath.Base(fileName), err: errors.New(result.crasherMsg), diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index c130f691f4..ca2808639a 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -163,19 +163,29 @@ func (w *worker) coordinate(ctx context.Context) error { return nil } - // Unexpected termination. Inform the coordinator about the crash. + // Unexpected termination. Attempt to minimize, then inform the + // coordinator about the crash. // TODO(jayconrod,katiehockman): if -keepfuzzing, restart worker. - mem := <-w.memMu - value := mem.valueCopy() - w.memMu <- mem + // TODO(jayconrod,katiehockman): consider informing the + // coordinator that this worker is minimizing, in order to block + // the other workers from receiving more inputs. message := fmt.Sprintf("fuzzing process terminated unexpectedly: %v", w.waitErr) - w.coordinator.resultC <- fuzzResult{ - entry: CorpusEntry{Data: value}, - crasherMsg: message, + err = w.waitErr + res, minimized, minErr := w.minimize(ctx) + if !minimized { + // Minimization did not find a smaller crashing value, so + // return the one we already found. + res = fuzzResult{ + entry: CorpusEntry{Data: value}, + crasherMsg: message, + } + } + if minErr != nil { + err = minErr } - return w.waitErr + w.coordinator.resultC <- res + return err } - result := fuzzResult{ countRequested: input.countRequested, count: resp.Count, @@ -193,6 +203,56 @@ func (w *worker) coordinate(ctx context.Context) error { } } +// minimize asks a workerServer to attempt to minimize what is currently in +// shared memory. It runs for a maxium of 1 minute. The worker must be stopped +// when minimize is called. +func (w *worker) minimize(ctx context.Context) (res fuzzResult, minimized bool, retErr error) { + fmt.Fprint(w.coordinator.opts.Log, "found a crash, currently minimizing for up to 1 minute\n") + defer func() { + w.stop() + if retErr == nil { + retErr = w.waitErr + } + }() + // In case we can't minimize it at all, save the last crash value that we + // found to send to the coordinator once the time is up. + minimizeDeadline := time.Now().Add(time.Minute) + for rem := time.Until(minimizeDeadline); rem > 0; { + // Restart the worker. + if err := w.start(); err != nil { + return res, minimized, err + } + args := minimizeArgs{Duration: rem} + value, err := w.client.minimize(ctx, args) + if err == nil { + // Minimization finished successfully, meaning that it + // couldn't find any smaller inputs that caused a crash, + // so stop trying. + return res, minimized, nil + } + // Minimization will return an error for a non-recoverable problem, so + // a non-nil error is expected. However, make sure it didn't fail for + // some other reason which should cause us to stop minimizing. + if ctx.Err() != nil || w.interrupted || isInterruptError(w.waitErr) { + return res, minimized, nil + } + + // The bytes in memory caused a legitimate crash, so stop the worker and + // save this value and error message. + w.stop() + message := fmt.Sprintf("fuzzing process terminated unexpectedly: %v", w.waitErr) + res = fuzzResult{ + entry: CorpusEntry{Data: value}, + crasherMsg: message, + } + minimized = true + } + return res, minimized, nil + // TODO(jayconrod,katiehockman): while minimizing, every panic message is + // logged to STDOUT. We should probably suppress all but the last one to + // lower the noise. +} + // start runs a new worker process. // // If the process couldn't be started, start returns an error. Start won't @@ -370,10 +430,20 @@ func RunFuzzWorker(ctx context.Context, fn func(CorpusEntry) error) error { // a minimalist RPC mechanism. Exactly one of its fields must be set to indicate // which method to call. type call struct { - Ping *pingArgs - Fuzz *fuzzArgs + Ping *pingArgs + Fuzz *fuzzArgs + Minimize *minimizeArgs } +// minimizeArgs contains arguments to workerServer.minimize. The value to +// minimize is already in shared memory. +type minimizeArgs struct { + Duration time.Duration +} + +// minimizeResponse contains results from workerServer.minimize. +type minimizeResponse struct{} + // fuzzArgs contains arguments to workerServer.fuzz. The value to fuzz is // passed in shared memory. type fuzzArgs struct { @@ -479,6 +549,8 @@ func (ws *workerServer) serve(ctx context.Context) error { switch { case c.Fuzz != nil: resp = ws.fuzz(ctx, *c.Fuzz) + case c.Minimize != nil: + resp = ws.minimize(ctx, *c.Minimize) case c.Ping != nil: resp = ws.ping(ctx, *c.Ping) default: @@ -538,7 +610,7 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo // time customizable with a go command flag. minCtx, minCancel := context.WithTimeout(ctx, time.Minute) defer minCancel() - if minErr := ws.minimize(minCtx, vals, mem); minErr != nil { + if minErr := ws.minimizeInput(minCtx, vals, mem); minErr != nil { // Minimization found a different error, so use that one. err = minErr } @@ -561,12 +633,26 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo } } -// minimize applies a series of minimizing transformations on the provided +func (ws *workerServer) minimize(ctx context.Context, args minimizeArgs) minimizeResponse { + mem := <-ws.memMu + defer func() { ws.memMu <- mem }() + vals, err := unmarshalCorpusFile(mem.valueCopy()) + if err != nil { + panic(err) + } + ctx, cancel := context.WithTimeout(ctx, args.Duration) + defer cancel() + ws.minimizeInput(ctx, vals, mem) + return minimizeResponse{} +} + +// minimizeInput applies a series of minimizing transformations on the provided // vals, ensuring that each minimization still causes an error in fuzzFn. Before // every call to fuzzFn, it marshals the new vals and writes it to the provided -// mem just in case an unrecoverable error occurs. It runs for a maximum of one -// minute, and returns the last error it found. -func (ws *workerServer) minimize(ctx context.Context, vals []interface{}, mem *sharedMem) (retErr error) { +// mem just in case an unrecoverable error occurs. It uses the context to +// determine how long to run, stopping once closed. It returns the last error it +// found. +func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, mem *sharedMem) (retErr error) { // Make sure the last crashing value is written to mem. defer writeToMem(vals, mem) @@ -720,6 +806,25 @@ func (wc *workerClient) Close() error { // interrupted. var errSharedMemClosed = errors.New("internal error: shared memory was closed and unmapped") +// minimize tells the worker to call the minimize method. See +// workerServer.minimize. +func (wc *workerClient) minimize(ctx context.Context, args minimizeArgs) (valueOut []byte, err error) { + wc.mu.Lock() + defer wc.mu.Unlock() + + var resp minimizeResponse + c := call{Minimize: &args} + err = wc.call(ctx, c, &resp) + mem, ok := <-wc.memMu + if !ok { + return nil, errSharedMemClosed + } + valueOut = mem.valueCopy() + wc.memMu <- mem + + return valueOut, err +} + // fuzz tells the worker to call the fuzz method. See workerServer.fuzz. func (wc *workerClient) fuzz(ctx context.Context, valueIn []byte, args fuzzArgs) (valueOut []byte, resp fuzzResponse, err error) { wc.mu.Lock() -- GitLab From 0b5470f31d8d8cdd49e5754fd1cb5ce391f77bd6 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Mon, 26 Apr 2021 13:00:15 -0700 Subject: [PATCH 0065/2500] [dev.fuzz] internal/fuzz: allow setting pcg seed via GODEBUG Format is "fuzzseed=123". Change-Id: Idb314270c8fd4307149c8503e13424b653ec4b0a Reviewed-on: https://go-review.googlesource.com/c/go/+/313651 Trust: Roland Shoemaker Trust: Katie Hockman Run-TryBot: Roland Shoemaker Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/internal/fuzz/pcg.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/internal/fuzz/pcg.go b/src/internal/fuzz/pcg.go index 5f0c1c39f6..18e553bc94 100644 --- a/src/internal/fuzz/pcg.go +++ b/src/internal/fuzz/pcg.go @@ -6,6 +6,9 @@ package fuzz import ( "math/bits" + "os" + "strconv" + "strings" "sync/atomic" "time" ) @@ -28,10 +31,27 @@ type pcgRand struct { inc uint64 } +func godebugSeed() *int { + debug := strings.Split(os.Getenv("GODEBUG"), ",") + for _, f := range debug { + if strings.HasPrefix(f, "fuzzseed=") { + seed, err := strconv.Atoi(strings.TrimPrefix(f, "fuzzseed=")) + if err != nil { + panic("malformed fuzzseed") + } + return &seed + } + } + return nil +} + // newPcgRand generates a new, seeded Rand, ready for use. func newPcgRand() *pcgRand { r := new(pcgRand) now := uint64(time.Now().UnixNano()) + if seed := godebugSeed(); seed != nil { + now = uint64(*seed) + } inc := atomic.AddUint64(&globalInc, 1) r.state = now r.inc = (inc << 1) | 1 -- GitLab From dd7529408412ec94a454d8455f7547327ee0d64d Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Sun, 25 Apr 2021 08:46:42 -0700 Subject: [PATCH 0066/2500] [dev.fuzz] internal/fuzz: add extra []byte mutators Adds four []byte mutators which: * insert a chunk of constant bytes * overwirtes a chunk with constant bytes * shuffle a range of bytes * swaps two chunks Also updates the 'set byte to random value' mutator to use XOR in order to avoid a no-op. Additionally updates the rng call which chooses the []byte mutators so all the available mutators are used. Change-Id: I0703518922952f4b1c81b19b196ee91c73b0d5f8 Reviewed-on: https://go-review.googlesource.com/c/go/+/313270 Trust: Roland Shoemaker Trust: Katie Hockman Run-TryBot: Roland Shoemaker TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/internal/fuzz/mutator.go | 89 ++++++++++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 4 deletions(-) diff --git a/src/internal/fuzz/mutator.go b/src/internal/fuzz/mutator.go index 88cb7b4e03..eda0128300 100644 --- a/src/internal/fuzz/mutator.go +++ b/src/internal/fuzz/mutator.go @@ -255,7 +255,7 @@ func (m *mutator) mutateBytes(ptrB *[]byte) { numIters := 1 + m.r.exp2() for iter := 0; iter < numIters; iter++ { - switch m.rand(10) { + switch m.rand(18) { case 0: // Remove a range of bytes. if len(b) <= 1 { @@ -280,7 +280,8 @@ func (m *mutator) mutateBytes(ptrB *[]byte) { b[pos+i] = byte(m.rand(256)) } case 2: - // Duplicate a range of bytes. + // Duplicate a range of bytes and insert it into + // a random position if len(b) <= 1 { iter-- continue @@ -301,7 +302,8 @@ func (m *mutator) mutateBytes(ptrB *[]byte) { copy(b[dst+n:], b[dst:]) copy(b[dst:], tmp) case 3: - // Copy a range of bytes. + // Overwrite a range of bytes with a randomly selected + // chunk if len(b) <= 1 { iter-- continue @@ -328,7 +330,10 @@ func (m *mutator) mutateBytes(ptrB *[]byte) { continue } pos := m.rand(len(b)) - b[pos] = byte(m.rand(256)) + // In order to avoid a no-op (where the random value matches + // the existing value), use XOR instead of just setting to + // the random value. + b[pos] ^= byte(1 + m.rand(255)) case 6: // Swap 2 bytes. if len(b) <= 1 { @@ -419,6 +424,82 @@ func (m *mutator) mutateBytes(ptrB *[]byte) { pos := m.rand(len(b) - 3) v := uint32(interesting32[m.rand(len(interesting32))]) m.randByteOrder().PutUint32(b[pos:], v) + case 14: + // Insert a range of constant bytes. + if len(b) <= 1 { + iter-- + continue + } + dst := m.rand(len(b)) + // TODO(rolandshoemaker,katiehockman): 4096 was mainly picked + // randomly. We may want to either pick a much larger value + // (AFL uses 32768, paired with a similar impl to chooseLen + // which biases towards smaller lengths that grow over time), + // or set the max based on characteristics of the corpus + // (libFuzzer sets a min/max based on the min/max size of + // entries in the corpus and then picks uniformly from + // that range). + n := m.chooseLen(4096) + if len(b)+n >= cap(b) { + iter-- + continue + } + b = b[:len(b)+n] + copy(b[dst+n:], b[dst:]) + rb := byte(m.rand(256)) + for i := dst; i < dst+n; i++ { + b[i] = rb + } + case 15: + // Overwrite a range of bytes with a chunk of + // constant bytes. + if len(b) <= 1 { + iter-- + continue + } + dst := m.rand(len(b)) + n := m.chooseLen(len(b) - dst) + rb := byte(m.rand(256)) + for i := dst; i < dst+n; i++ { + b[i] = rb + } + case 16: + // Shuffle a range of bytes + if len(b) <= 1 { + iter-- + continue + } + dst := m.rand(len(b)) + n := m.chooseLen(len(b) - dst) + if n <= 2 { + iter-- + continue + } + // Start at the end of the range, and iterate backwards + // to dst, swapping each element with another element in + // dst:dst+n (Fisher-Yates shuffle). + for i := n - 1; i > 0; i-- { + j := m.rand(i + 1) + b[dst+i], b[dst+j] = b[dst+j], b[dst+i] + } + case 17: + // Swap two chunks + if len(b) <= 1 { + iter-- + continue + } + src := m.rand(len(b)) + dst := m.rand(len(b)) + for dst == src { + dst = m.rand(len(b)) + } + n := m.chooseLen(len(b) - src) + tmp := make([]byte, n) + copy(tmp, b[dst:]) + copy(b[dst:], b[src:src+n]) + copy(b[src:], tmp) + default: + panic("unknown mutator") } } } -- GitLab From fe8c0e9467d8628138d54951ebb8e166c086c80b Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Fri, 23 Apr 2021 14:06:51 -0400 Subject: [PATCH 0067/2500] [dev.fuzz] cmd/go/internal/test: don't set default timeout when fuzzing The -timeout flag is not used when the fuzzing engine is running, but there was another backup alarm that would stop the test binary after 11 minutes by default. This change disables that backup alarm when the -fuzz flag is set. Note: unfortunately this means that if someone is running `go test -fuzz` and a test hangs before the fuzzing engine starts running, then the backup alarm won't trigger and the test will run ~forever. I don't think there's a way around this though, since the backup alarm has no way of knowing what stage of the test execution we're in (ie. are we running the unit tests, the seed corpus, or is it fuzzing). Fixes #44483 Change-Id: I4e212708a739c9cfc2e138440e27f257bb408c7f Reviewed-on: https://go-review.googlesource.com/c/go/+/313072 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/test/test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index c713394141..6c92c35360 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -618,7 +618,9 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { // to that timeout plus one minute. This is a backup alarm in case // the test wedges with a goroutine spinning and its background // timer does not get a chance to fire. - if testTimeout > 0 { + // Don't set this if fuzzing, since it should be able to run + // indefinitely. + if testTimeout > 0 && testFuzz == "" { testKillTimeout = testTimeout + 1*time.Minute } -- GitLab From af3237eaf9cf46e6a02a3b53447e49c55abd4f00 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Tue, 27 Apr 2021 14:34:17 -0400 Subject: [PATCH 0068/2500] [dev.fuzz] internal/fuzz: don't panic if types change There was a bug where if the types to fuzz were different from the types in a file in the on-disk corpus, then the code would panic. We thought this case was handled, but the final `continue` in the nested loop still allowed the invalid entry to be added to the corpus. Pulling the validation into a helper function makes this less brittle. Change-Id: I401346f890ea30ab7cff9640cb555da2e3ff8cc6 Reviewed-on: https://go-review.googlesource.com/c/go/+/313810 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/testdata/script/test_fuzz.txt | 14 ++++++++++- src/internal/fuzz/fuzz.go | 31 +++++++++++++++--------- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt index bfa1b68c67..0b1b85f397 100644 --- a/src/cmd/go/testdata/script/test_fuzz.txt +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -154,6 +154,11 @@ stdout ok ! stdout FAIL ! stdout 'fatal here' +# Test fails with file containing wrong type +! go test -run FuzzWrongType corpustesting/fuzz_testdata_corpus_test.go +! stdout ^ok +stdout FAIL + -- noop_fuzz_test.go -- package noop_fuzz @@ -384,6 +389,10 @@ func FuzzInNestedDir(f *testing.F) { f.Fuzz(func(t *testing.T, b []byte) {}) } +func FuzzWrongType(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) {}) +} + -- corpustesting/testdata/corpus/FuzzFail/1 -- go test fuzz v1 []byte("12345") @@ -394,4 +403,7 @@ go test fuzz v1 malformed -- corpustesting/testdata/corpus/FuzzInNestedDir/anotherdir/1 -- go test fuzz v1 -[]byte("12345") \ No newline at end of file +[]byte("12345") +-- corpustesting/testdata/corpus/FuzzWrongType/1 -- +go test fuzz v1 +int("00000") \ No newline at end of file diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 586b51188c..b9d2d4cd5f 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -506,21 +506,12 @@ func ReadCorpus(dir string, types []reflect.Type) ([]CorpusEntry, error) { if err != nil { return nil, fmt.Errorf("failed to read corpus file: %v", err) } - vals, err := unmarshalCorpusFile(data) + var vals []interface{} + vals, err = readCorpusData(data, types) if err != nil { - errs = append(errs, fmt.Errorf("failed to unmarshal %q: %v", filename, err)) - continue - } - if len(vals) != len(types) { - errs = append(errs, fmt.Errorf("wrong number of values in corpus file %q: %d, want %d", filename, len(vals), len(types))) + errs = append(errs, fmt.Errorf("%q: %v", filename, err)) continue } - for i := range types { - if reflect.TypeOf(vals[i]) != types[i] { - errs = append(errs, fmt.Errorf("mismatched types in corpus file %q: %v, want %v", filename, vals, types)) - continue - } - } corpus = append(corpus, CorpusEntry{Name: file.Name(), Data: data, Values: vals}) } if len(errs) > 0 { @@ -529,6 +520,22 @@ func ReadCorpus(dir string, types []reflect.Type) ([]CorpusEntry, error) { return corpus, nil } +func readCorpusData(data []byte, types []reflect.Type) ([]interface{}, error) { + vals, err := unmarshalCorpusFile(data) + if err != nil { + return nil, fmt.Errorf("unmarshal: %v", err) + } + if len(vals) != len(types) { + return nil, fmt.Errorf("wrong number of values in corpus file: %d, want %d", len(vals), len(types)) + } + for i := range types { + if reflect.TypeOf(vals[i]) != types[i] { + return nil, fmt.Errorf("mismatched types in corpus file: %v, want %v", vals, types) + } + } + return vals, nil +} + // writeToCorpus atomically writes the given bytes to a new file in testdata. // If the directory does not exist, it will create one. If the file already // exists, writeToCorpus will not rewrite it. writeToCorpus returns the -- GitLab From 510e711dd36999f1800678909bb7fdb448aa074f Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Sat, 1 May 2021 18:46:22 -0700 Subject: [PATCH 0069/2500] [dev.fuzz] testing,internal/fuzz: prevent unbounded memory growth Usage of f.testContext.match.fullName to generate the test name causes unbounded memory growth, eventually causing the fuzzer to slow down as memory pressure increases. Each time fuzzFn is invoked it generates a unique string and stores it in a map. With the fuzzer running at around 100k executions per second this consumed around ~30GB of memory in a handful of minutes. Instead just use the base name of the test for mutated inputs, a special name for seeded inputs, and the filename for inputs from the input corpus. Change-Id: I083f47df7e82f0c6b0bda244f158233784a13029 Reviewed-on: https://go-review.googlesource.com/c/go/+/316030 Trust: Roland Shoemaker Trust: Katie Hockman Run-TryBot: Roland Shoemaker TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- .../go/testdata/script/test_fuzz_mutate_crash.txt | 2 ++ src/go/build/deps_test.go | 2 +- src/internal/fuzz/fuzz.go | 2 +- src/testing/fuzz.go | 14 ++++++-------- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt index 76e7907bf1..ca2b389321 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt @@ -21,6 +21,8 @@ go run check_testdata.go FuzzWithBug # Now, the failing bytes should have been added to the seed corpus for # the target, and should fail when run without fuzzing. ! go test +stdout 'testdata[/\\]corpus[/\\]FuzzWithBug[/\\][a-f0-9]{64}' +stdout 'this input caused a crash!' ! go test -run=FuzzWithNilPanic -fuzz=FuzzWithNilPanic -fuzztime=100x stdout 'testdata[/\\]corpus[/\\]FuzzWithNilPanic[/\\]' diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 3511cf41a6..a370bc9ac9 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -501,7 +501,7 @@ var depsRules = ` FMT, flag, runtime/debug, runtime/trace, internal/sysinfo < testing; - FMT, crypto/sha256, encoding/json, go/ast, go/parser, go/token, math/rand + FMT, crypto/sha256, encoding/json, go/ast, go/parser, go/token, math/rand, encoding/hex, crypto/sha256 < internal/fuzz; internal/fuzz, internal/testlog, runtime/pprof, regexp diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index b9d2d4cd5f..d0545bd076 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -512,7 +512,7 @@ func ReadCorpus(dir string, types []reflect.Type) ([]CorpusEntry, error) { errs = append(errs, fmt.Errorf("%q: %v", filename, err)) continue } - corpus = append(corpus, CorpusEntry{Name: file.Name(), Data: data, Values: vals}) + corpus = append(corpus, CorpusEntry{Name: filename, Data: data, Values: vals}) } if len(errs) > 0 { return corpus, &MalformedCorpusError{errs: errs} diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 70e1b414a8..7afd24d258 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -226,7 +226,7 @@ func (f *F) Add(args ...interface{}) { } values = append(values, args[i]) } - f.corpus = append(f.corpus, corpusEntry{Values: values}) + f.corpus = append(f.corpus, corpusEntry{Values: values, Name: fmt.Sprintf("seed#%d", len(f.corpus))}) } // supportedTypes represents all of the supported types which can be fuzzed. @@ -298,21 +298,19 @@ func (f *F) Fuzz(ff interface{}) { // fn is called in its own goroutine. // // TODO(jayconrod,katiehockman): dedupe testdata corpus with entries from f.Add - // TODO(jayconrod,katiehockman): improve output when running the subtest. - // e.g. instead of - // --- FAIL: FuzzSomethingError/#00 (0.00s) - // do - // --- FAIL: FuzzSomethingError/ (0.00s) run := func(e corpusEntry) error { if e.Values == nil { // Every code path should have already unmarshaled Data into Values. // It's our fault if it didn't. panic(fmt.Sprintf("corpus file %q was not unmarshaled", e.Name)) } - testName, ok, _ := f.testContext.match.fullName(&f.common, e.Name) - if !ok || shouldFailFast() { + if shouldFailFast() { return nil } + testName := f.common.name + if e.Name != "" { + testName = fmt.Sprintf("%s/%s", testName, e.Name) + } // Record the stack trace at the point of this call so that if the subtest // function - which runs in a separate stack - is marked as a helper, we can // continue walking the stack into the parent test. -- GitLab From 6ffb027483a86d6081989a63bb2af6a69028b46a Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Tue, 20 Apr 2021 16:11:13 -0400 Subject: [PATCH 0070/2500] [dev.fuzz] internal/fuzz: use coverage instrumentation while fuzzing This change updates the go command behavior when fuzzing to instrument the binary for code coverage, and uses this coverage in the fuzzing engine to determine if an input is interesting. Unfortunately, we can't store and use the coverage data for a given run of `go test` and re-use it the next time we fuzz, since the edges could have changed between builds. Instead, every entry in the seed corpus and the on-disk corpus is run by the workers before fuzzing begins, so that the coordinator can get the baseline coverage for what the fuzzing engine has already found (or what the developers have already provided). Users should run `go clean -fuzzcache` before using this change, to clear out any existing "interesting" values that were in the cache. Previously, every single non-crashing input was written to the on-disk corpus. Now, only inputs that actually expand coverage are written. This change includes a small hack in cmd/go/internal/load/pkg.go which ensures that the Gcflags that were explicitly set in cmd/go/internal/test/test.go don't get cleared out. Tests will be added in a follow-up change, since they will be a bit more involved. Change-Id: Ie659222d44475c6d68fa4a35d37c37cab3619d71 Reviewed-on: https://go-review.googlesource.com/c/go/+/312009 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/load/pkg.go | 9 + src/cmd/go/internal/test/test.go | 9 + src/cmd/go/internal/work/init.go | 8 + .../go/testdata/script/test_fuzz_fuzztime.txt | 1 + .../go/testdata/script/test_fuzz_mutator.txt | 38 ++-- src/internal/fuzz/coverage.go | 19 ++ src/internal/fuzz/fuzz.go | 162 ++++++++++++++---- src/internal/fuzz/mutator.go | 2 +- src/internal/fuzz/worker.go | 86 +++++++--- 9 files changed, 254 insertions(+), 80 deletions(-) diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index 8b12faf4cd..acd34d59ea 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -206,6 +206,7 @@ type PackageInternal struct { BuildInfo string // add this info to package main TestmainGo *[]byte // content for _testmain.go Embed map[string][]string // //go:embed comment mapping + FlagsSet bool // whether the flags have been set Asmflags []string // -asmflags for this package Gcflags []string // -gcflags for this package @@ -2493,6 +2494,14 @@ func CheckPackageErrors(pkgs []*Package) { func setToolFlags(pkgs ...*Package) { for _, p := range PackageList(pkgs) { + // TODO(jayconrod,katiehockman): See if there's a better way to do this. + if p.Internal.FlagsSet { + // The flags have already been set, so don't re-run this and + // potentially clear existing flags. + continue + } else { + p.Internal.FlagsSet = true + } p.Internal.Asmflags = BuildAsmflags.For(p) p.Internal.Gcflags = BuildGcflags.For(p) p.Internal.Ldflags = BuildLdflags.For(p) diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 6c92c35360..076a7e0807 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -764,6 +764,15 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { } } + fuzzFlags := work.FuzzInstrumentFlags() + if testFuzz != "" && fuzzFlags != nil { + // Inform the compiler that it should instrument the binary at + // build-time when fuzzing is enabled. + for _, p := range load.PackageList(pkgs) { + p.Internal.Gcflags = append(p.Internal.Gcflags, fuzzFlags...) + } + } + // Prepare build + run + print actions for all packages being tested. for _, p := range pkgs { // sync/atomic import is inserted by the cover tool. See #18486 diff --git a/src/cmd/go/internal/work/init.go b/src/cmd/go/internal/work/init.go index ba7c7c2fbb..81ebb750ad 100644 --- a/src/cmd/go/internal/work/init.go +++ b/src/cmd/go/internal/work/init.go @@ -63,6 +63,14 @@ func BuildInit() { } } +func FuzzInstrumentFlags() []string { + if cfg.Goarch != "amd64" && cfg.Goarch != "arm64" { + // Instrumentation is only supported on 64-bit architectures. + return nil + } + return []string{"-d=libfuzzer"} +} + func instrumentInit() { if !cfg.BuildRace && !cfg.BuildMSan { return diff --git a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt index 2b2e38c504..617980e940 100644 --- a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt +++ b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt @@ -20,6 +20,7 @@ exec ./fuzz.test$GOEXE -test.timeout=10ms -test.fuzz=FuzzFast -test.fuzztime=5s # This fuzz function creates a file with a unique name ($pid.$count) on each run. # We count the files to find the number of runs. mkdir count +env GOCACHE=$WORK/tmp go test -fuzz=FuzzCount -fuzztime=1000x go run count_files.go stdout '^1000$' diff --git a/src/cmd/go/testdata/script/test_fuzz_mutator.txt b/src/cmd/go/testdata/script/test_fuzz_mutator.txt index c29912b65a..c92be50a8e 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutator.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutator.txt @@ -20,27 +20,27 @@ stdout FAIL stdout 'mutator found enough unique mutations' # Test that minimization is working for recoverable errors. -! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10s minimizer_test.go +! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=1000x minimizer_test.go ! stdout '^ok' stdout 'got the minimum size!' stdout 'contains a letter' stdout FAIL -# Check that the bytes written to testdata are of length 100 (the minimum size) -go run check_testdata.go FuzzMinimizerRecoverable 100 +# Check that the bytes written to testdata are of length 50 (the minimum size) +go run check_testdata.go FuzzMinimizerRecoverable 50 # Test that re-running the minimized value causes a crash. ! go test -run=FuzzMinimizerRecoverable minimizer_test.go # Test that minimization is working for non-recoverable errors. -! go test -fuzz=FuzzMinimizerNonrecoverable -run=FuzzMinimizerNonrecoverable -fuzztime=10s minimizer_test.go +! go test -fuzz=FuzzMinimizerNonrecoverable -run=FuzzMinimizerNonrecoverable -fuzztime=1000x minimizer_test.go ! stdout '^ok' stdout 'got the minimum size!' stdout 'contains a letter' stdout FAIL -# Check that the bytes written to testdata are of length 100 (the minimum size) -go run check_testdata.go FuzzMinimizerNonrecoverable 100 +# Check that the bytes written to testdata are of length 50 (the minimum size) +go run check_testdata.go FuzzMinimizerNonrecoverable 50 # Test that minimization can be cancelled by fuzztime and the latest crash will # still be logged and written to testdata. @@ -48,7 +48,7 @@ go run check_testdata.go FuzzMinimizerNonrecoverable 100 ! stdout '^ok' stdout 'testdata[/\\]corpus[/\\]FuzzNonMinimizable[/\\]' ! stdout 'got the minimum size!' # it shouldn't have had enough time to minimize it -stdout 'at least 100 bytes' +stdout 'at least 20 bytes' stdout FAIL # TODO(jayconrod,katiehockman): add a test which verifies that the right bytes @@ -113,32 +113,32 @@ import ( func FuzzMinimizerRecoverable(f *testing.F) { f.Fuzz(func(t *testing.T, b []byte) { - if len(b) < 100 { + if len(b) < 50 { // Make sure that b is large enough that it can be minimized return } // Given the randomness of the mutations, this should allow the // minimizer to trim down the value a bit. if bytes.ContainsAny(b, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") { - if len(b) == 100 { - t.Logf("got the minimum size!") + if len(b) == 50 { + t.Log("got the minimum size!") } - t.Errorf("contains a letter") + t.Error("contains a letter") } }) } func FuzzMinimizerNonrecoverable(f *testing.F) { f.Fuzz(func(t *testing.T, b []byte) { - if len(b) < 100 { + if len(b) < 50 { // Make sure that b is large enough that it can be minimized return } // Given the randomness of the mutations, this should allow the // minimizer to trim down the value quite a bit. if bytes.ContainsAny(b, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") { - if len(b) == 100 { - t.Logf("got the minimum size!") + if len(b) == 50 { + t.Log("got the minimum size!") } panic("contains a letter") } @@ -147,15 +147,15 @@ func FuzzMinimizerNonrecoverable(f *testing.F) { func FuzzNonMinimizable(f *testing.F) { f.Fuzz(func(t *testing.T, b []byte) { - if len(b) < 10 { + if len(b) < 20 { // Make sure that b is large enough that minimization will try to run. return } - time.Sleep(3 * time.Second) - if len(b) == 10 { - t.Logf("got the minimum size!") + panic("at least 20 bytes") + if len(b) == 20 { + t.Log("got the minimum size!") } - panic("at least 100 bytes") + time.Sleep(4 * time.Second) }) } diff --git a/src/internal/fuzz/coverage.go b/src/internal/fuzz/coverage.go index 74872541c9..e039d68d9a 100644 --- a/src/internal/fuzz/coverage.go +++ b/src/internal/fuzz/coverage.go @@ -26,6 +26,25 @@ func coverage() []byte { return res } +// coverageCopy returns a copy of the current bytes provided by coverage(). +// TODO(jayconrod,katiehockman): consider using a shared buffer instead, to +// make fewer costly allocations. +func coverageCopy() []byte { + cov := coverage() + ret := make([]byte, len(cov)) + copy(ret, cov) + return ret +} + +// resetCovereage sets all of the counters for each edge of the instrumented +// source code to 0. +func resetCoverage() { + cov := coverage() + for i := range cov { + cov[i] = 0 + } +} + // _counters and _ecounters mark the start and end, respectively, of where // the 8-bit coverage counters reside in memory. They're known to cmd/link, // which specially assigns their addresses for this purpose. diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index d0545bd076..c46220e3ec 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -210,23 +210,36 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err // TODO(jayconrod,katiehockman): if -keepfuzzing, report the error to // the user and restart the crashed worker. stop(err) - } else if result.isInteresting { - // Found an interesting value that expanded coverage. - // This is not a crasher, but we should minimize it, add it to the - // on-disk corpus, and prioritize it for future fuzzing. - // TODO(jayconrod, katiehockman): Prioritize fuzzing these values which - // expanded coverage. - // TODO(jayconrod, katiehockman): Don't write a value that's already - // in the corpus. - c.corpus.entries = append(c.corpus.entries, result.entry) - if opts.CacheDir != "" { - if _, err := writeToCorpus(result.entry.Data, opts.CacheDir); err != nil { - stop(err) + } else if result.coverageData != nil { + foundNew := c.updateCoverage(result.coverageData) + if foundNew && !c.coverageOnlyRun() { + // Found an interesting value that expanded coverage. + // This is not a crasher, but we should add it to the + // on-disk corpus, and prioritize it for future fuzzing. + // TODO(jayconrod, katiehockman): Prioritize fuzzing these + // values which expanded coverage, perhaps based on the + // number of new edges that this result expanded. + // TODO(jayconrod, katiehockman): Don't write a value that's already + // in the corpus. + c.interestingCount++ + c.corpus.entries = append(c.corpus.entries, result.entry) + if opts.CacheDir != "" { + if _, err := writeToCorpus(result.entry.Data, opts.CacheDir); err != nil { + stop(err) + } + } + } else if c.coverageOnlyRun() { + c.covOnlyInputs-- + if c.covOnlyInputs == 0 { + // The coordinator has finished getting a baseline for + // coverage. Tell all of the workers to inialize their + // baseline coverage data (by setting interestingCount + // to 0). + c.interestingCount = 0 } } } - - if inputC == nil && !stopping { + if inputC == nil && !stopping && !c.coverageOnlyRun() { // inputC was disabled earlier because we hit the limit on the number // of inputs to fuzz (nextInput returned false). // Workers can do less work than requested though, so we might be @@ -246,7 +259,13 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err case inputC <- input: // Send the next input to any worker. - if input, ok = c.nextInput(); !ok { + if c.corpusIndex == 0 && c.coverageOnlyRun() { + // The coordinator is currently trying to run all of the corpus + // entries to gather baseline coverage data, and all of the + // inputs have been passed to inputC. Block any more inputs from + // being passed to the workers for now. + inputC = nil + } else if input, ok = c.nextInput(); !ok { inputC = nil } @@ -310,6 +329,17 @@ type fuzzInput struct { // countRequested is the number of values to test. If non-zero, the worker // will stop after testing this many values, if it hasn't already stopped. countRequested int64 + + // coverageOnly indicates whether this input is for a coverage-only run. If + // true, the input should not be fuzzed. + coverageOnly bool + + // interestingCount reflects the coordinator's current interestingCount + // value. + interestingCount int64 + + // coverageData reflects the coordinator's current coverageData. + coverageData []byte } type fuzzResult struct { @@ -319,9 +349,8 @@ type fuzzResult struct { // crasherMsg is an error message from a crash. It's "" if no crash was found. crasherMsg string - // isInteresting is true if the worker found new coverage. We should minimize - // the value, cache it, and prioritize it for further fuzzing. - isInteresting bool + // coverageData is set if the worker found new coverage. + coverageData []byte // countRequested is the number of values the coordinator asked the worker // to test. 0 if there was no limit. @@ -354,6 +383,14 @@ type coordinator struct { // count is the number of values fuzzed so far. count int64 + // interestingCount is the number of unique interesting values which have + // been found this execution. + interestingCount int64 + + // covOnlyInputs is the number of entries in the corpus which still need to + // be sent to a worker to gather baseline coverage data. + covOnlyInputs int + // duration is the time spent fuzzing inside workers, not counting time // starting up or tearing down. duration time.Duration @@ -370,6 +407,8 @@ type coordinator struct { // TODO(jayconrod,katiehockman): need a scheduling algorithm that chooses // which corpus value to send next (or generates something new). corpusIndex int + + coverageData []byte } func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { @@ -383,6 +422,7 @@ func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { if err != nil { return nil, err } + covOnlyInputs := len(corpus.entries) if len(corpus.entries) == 0 { var vals []interface{} for _, t := range opts.Types { @@ -391,11 +431,27 @@ func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { corpus.entries = append(corpus.entries, CorpusEntry{Data: marshalCorpusFile(vals...), Values: vals}) } c := &coordinator{ - opts: opts, - startTime: time.Now(), - inputC: make(chan fuzzInput), - resultC: make(chan fuzzResult), - corpus: corpus, + opts: opts, + startTime: time.Now(), + inputC: make(chan fuzzInput), + resultC: make(chan fuzzResult), + corpus: corpus, + covOnlyInputs: covOnlyInputs, + } + + cov := coverageCopy() + if len(cov) == 0 { + fmt.Fprintf(c.opts.Log, "warning: coverage-guided fuzzing is not supported on this platform\n") + c.covOnlyInputs = 0 + } else { + // Set c.coverageData to a clean []byte full of zeros. + c.coverageData = make([]byte, len(cov)) + } + + if c.covOnlyInputs > 0 { + // Set c.interestingCount to -1 so the workers know when the coverage + // run is finished and can update their local coverage data. + c.interestingCount = -1 } return c, nil @@ -409,9 +465,15 @@ func (c *coordinator) updateStats(result fuzzResult) { } func (c *coordinator) logStats() { + // TODO(jayconrod,katiehockman): consider printing the amount of coverage + // that has been reached so far (perhaps a percentage of edges?) elapsed := time.Since(c.startTime) - rate := float64(c.count) / elapsed.Seconds() - fmt.Fprintf(c.opts.Log, "elapsed: %.1fs, execs: %d (%.0f/sec), workers: %d\n", elapsed.Seconds(), c.count, rate, c.opts.Parallel) + if c.coverageOnlyRun() { + fmt.Fprintf(c.opts.Log, "gathering baseline coverage, elapsed: %.1fs, workers: %d, left: %d\n", elapsed.Seconds(), c.opts.Parallel, c.covOnlyInputs) + } else { + rate := float64(c.count) / elapsed.Seconds() + fmt.Fprintf(c.opts.Log, "fuzzing, elapsed: %.1fs, execs: %d (%.0f/sec), workers: %d, interesting: %d\n", elapsed.Seconds(), c.count, rate, c.opts.Parallel, c.interestingCount) + } } // nextInput returns the next value that should be sent to workers. @@ -423,22 +485,54 @@ func (c *coordinator) nextInput() (fuzzInput, bool) { // Workers already testing all requested inputs. return fuzzInput{}, false } - - e := c.corpus.entries[c.corpusIndex] + input := fuzzInput{ + entry: c.corpus.entries[c.corpusIndex], + interestingCount: c.interestingCount, + coverageData: c.coverageData, + } c.corpusIndex = (c.corpusIndex + 1) % (len(c.corpus.entries)) - var n int64 + + if c.coverageOnlyRun() { + // This is a coverage-only run, so this input shouldn't be fuzzed, + // and shouldn't be included in the count of generated values. + input.coverageOnly = true + return input, true + } + if c.opts.Count > 0 { - n = c.opts.Count / int64(c.opts.Parallel) + input.countRequested = c.opts.Count / int64(c.opts.Parallel) if c.opts.Count%int64(c.opts.Parallel) > 0 { - n++ + input.countRequested++ } remaining := c.opts.Count - c.count - c.countWaiting - if n > remaining { - n = remaining + if input.countRequested > remaining { + input.countRequested = remaining + } + c.countWaiting += input.countRequested + } + return input, true +} + +func (c *coordinator) coverageOnlyRun() bool { + return c.covOnlyInputs > 0 +} + +// updateCoverage updates c.coverageData for all edges that have a higher +// counter value in newCoverage. It return true if a new edge was hit. +func (c *coordinator) updateCoverage(newCoverage []byte) bool { + if len(newCoverage) != len(c.coverageData) { + panic(fmt.Sprintf("num edges changed at runtime: %d, expected %d", len(newCoverage), len(c.coverageData))) + } + newEdge := false + for i := range newCoverage { + if newCoverage[i] > c.coverageData[i] { + if c.coverageData[i] == 0 { + newEdge = true + } + c.coverageData[i] = newCoverage[i] } - c.countWaiting += n } - return fuzzInput{entry: e, countRequested: n}, true + return newEdge } // readCache creates a combined corpus from seed values and values in the cache diff --git a/src/internal/fuzz/mutator.go b/src/internal/fuzz/mutator.go index eda0128300..d4ca31e6e5 100644 --- a/src/internal/fuzz/mutator.go +++ b/src/internal/fuzz/mutator.go @@ -269,7 +269,7 @@ func (m *mutator) mutateBytes(ptrB *[]byte) { case 1: // Insert a range of random bytes. pos := m.rand(len(b) + 1) - n := m.chooseLen(10) + n := m.chooseLen(1024) if len(b)+n >= cap(b) { iter-- continue diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index ca2808639a..61d3226b30 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -98,6 +98,10 @@ func (w *worker) coordinate(ctx context.Context) error { // TODO(jayconrod,katiehockman): record and return stderr. } + // interestingCount starts at -1, like the coordinator does, so that the + // worker client's coverage data is updated after a coverage-only run. + interestingCount := int64(-1) + // Main event loop. for { select { @@ -134,13 +138,19 @@ func (w *worker) coordinate(ctx context.Context) error { return fmt.Errorf("fuzzing process exited unexpectedly due to an internal failure: %w", err) } // Worker exited non-zero or was terminated by a non-interrupt signal - // (for example, SIGSEGV). + // (for example, SIGSEGV) while fuzzing. return fmt.Errorf("fuzzing process terminated unexpectedly: %w", err) + // TODO(jayconrod,katiehockman): if -keepfuzzing, restart worker. // TODO(jayconrod,katiehockman): record and return stderr. case input := <-w.coordinator.inputC: // Received input from coordinator. - args := fuzzArgs{Count: input.countRequested, Duration: workerFuzzDuration} + args := fuzzArgs{Count: input.countRequested, Duration: workerFuzzDuration, CoverageOnly: input.coverageOnly} + if interestingCount < input.interestingCount { + // The coordinator's coverage data has changed, so send the data + // to the client. + args.CoverageData = input.coverageData + } value, resp, err := w.client.fuzz(ctx, input.entry.Data, args) if err != nil { // Error communicating with worker. @@ -162,7 +172,6 @@ func (w *worker) coordinate(ctx context.Context) error { // Since we expect I/O errors around interrupts, ignore this error. return nil } - // Unexpected termination. Attempt to minimize, then inform the // coordinator about the crash. // TODO(jayconrod,katiehockman): if -keepfuzzing, restart worker. @@ -191,12 +200,12 @@ func (w *worker) coordinate(ctx context.Context) error { count: resp.Count, duration: resp.Duration, } - if resp.Crashed { + if resp.Err != "" { result.entry = CorpusEntry{Data: value} result.crasherMsg = resp.Err - } else if resp.Interesting { + } else if resp.CoverageData != nil { result.entry = CorpusEntry{Data: value} - result.isInteresting = true + result.coverageData = resp.CoverageData } w.coordinator.resultC <- result } @@ -454,6 +463,14 @@ type fuzzArgs struct { // Count is the number of values to test, without spending more time // than Duration. Count int64 + + // CoverageOnly indicates whether this is a coverage-only run (ie. fuzzing + // should not occur). + CoverageOnly bool + + // CoverageData is the coverage data. If set, the worker should update its + // local coverage data prior to fuzzing. + CoverageData []byte } // fuzzResponse contains results from workerServer.fuzz. @@ -464,16 +481,12 @@ type fuzzResponse struct { // Count is the number of values tested. Count int64 - // Interesting indicates the value in shared memory may be interesting to - // the coordinator (for example, because it expanded coverage). - Interesting bool - - // Crashed indicates the value in shared memory caused a crash. - Crashed bool + // CoverageData is set if the value in shared memory expands coverage + // and therefore may be interesting to the coordinator. + CoverageData []byte - // Err is the error string caused by the value in shared memory. This alone - // cannot be used to determine whether this value caused a crash, since a - // crash can occur without any output (e.g. with t.Fail()). + // Err is the error string caused by the value in shared memory, which is + // non-empty if the value in shared memory caused a crash. Err string } @@ -506,6 +519,11 @@ type workerServer struct { workerComm m *mutator + // coverageData is the local coverage data for the worker. It is + // periodically updated to reflect the data in the coordinator when new + // edges are hit. + coverageData []byte + // fuzzFn runs the worker's fuzz function on the given input and returns // an error if it finds a crasher (the process may also exit or crash). fuzzFn func(CorpusEntry) error @@ -580,6 +598,9 @@ func (ws *workerServer) serve(ctx context.Context) error { // a given amount of time. fuzz returns early if it finds an input that crashes // the fuzz function or an input that expands coverage. func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzResponse) { + if args.CoverageData != nil { + ws.coverageData = args.CoverageData + } start := time.Now() defer func() { resp.Duration = time.Since(start) }() @@ -593,42 +614,55 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo panic(err) } + if args.CoverageOnly { + // Reset the coverage each time before running the fuzzFn. + resetCoverage() + ws.fuzzFn(CorpusEntry{Values: vals}) + resp.CoverageData = coverageCopy() + return resp + } + + cov := coverage() + if len(cov) != len(ws.coverageData) { + panic(fmt.Sprintf("num edges changed at runtime: %d, expected %d", len(cov), len(ws.coverageData))) + } for { select { case <-fuzzCtx.Done(): - // TODO(jayconrod,katiehockman): this value is not interesting. Use a - // real heuristic once we have one. - resp.Interesting = true return resp default: resp.Count++ ws.m.mutate(vals, cap(mem.valueRef())) writeToMem(vals, mem) + resetCoverage() if err := ws.fuzzFn(CorpusEntry{Values: vals}); err != nil { - // TODO(jayconrod,katiehockman): consider making the maximum minimization - // time customizable with a go command flag. + // TODO(jayconrod,katiehockman): consider making the maximum + // minimization time customizable with a go command flag. minCtx, minCancel := context.WithTimeout(ctx, time.Minute) defer minCancel() if minErr := ws.minimizeInput(minCtx, vals, mem); minErr != nil { // Minimization found a different error, so use that one. err = minErr } - resp.Crashed = true resp.Err = err.Error() if resp.Err == "" { resp.Err = "fuzz function failed with no output" } return resp } + for i := range cov { + if ws.coverageData[i] == 0 && cov[i] > ws.coverageData[i] { + // TODO(jayconrod,katie): minimize this. + // This run hit a new edge. Only allocate a new slice as a + // copy of cov if we are returning, since it is expensive. + resp.CoverageData = coverageCopy() + return resp + } + } if args.Count > 0 && resp.Count == args.Count { - // TODO(jayconrod,katiehockman): this value is not interesting. Use a - // real heuristic once we have one. - resp.Interesting = true return resp } - // TODO(jayconrod,katiehockman): return early if we find an - // interesting value. } } } -- GitLab From 04f65d394c00cf706ba1e0949b057d94dace6b94 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Fri, 7 May 2021 13:20:34 -0700 Subject: [PATCH 0071/2500] [dev.typeparams] cmd/compile: fix use of method values with stenciled methods We were handling the case where an OFUNCINST node was used as a function value, but not the case when an OFUNCINST node was used as a method value. In the case of a method value, we need to create a new selector expression that references the newly stenciled method. To make this work, also needed small fix to noder2 code to properly set the Sel of a method SelectorExpr (should be just the base method name, not the full method name including the type string). This has to be correct, so that the function created by MethodValueWrapper() can be typechecked successfully. Fixes #45817 Change-Id: I7343e8a0d35fc46b44dfe4d45b77997ba6c8733e Reviewed-on: https://go-review.googlesource.com/c/go/+/319589 Reviewed-by: Keith Randall Trust: Dan Scales --- src/cmd/compile/internal/ir/expr.go | 9 ++++++-- src/cmd/compile/internal/noder/expr.go | 2 +- src/cmd/compile/internal/noder/stencil.go | 22 +++++++++++++++++--- test/typeparam/issue45817.go | 25 +++++++++++++++++++++++ 4 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 test/typeparam/issue45817.go diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index f70645f079..9ea8b61965 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -494,8 +494,13 @@ func NewNameOffsetExpr(pos src.XPos, name *Name, offset int64, typ *types.Type) // A SelectorExpr is a selector expression X.Sel. type SelectorExpr struct { miniExpr - X Node - Sel *types.Sym + X Node + // Sel is the name of the field or method being selected, without (in the + // case of methods) any preceding type specifier. If the field/method is + // exported, than the Sym uses the local package regardless of the package + // of the containing type. + Sel *types.Sym + // The actual selected field - may not be filled in until typechecking. Selection *types.Field Prealloc *Name // preallocated storage for OCALLPART, if any } diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index c7695ed920..b7f7a34953 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -266,7 +266,7 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto recvType2 = recvType2Base // method is the generic method associated with the gen type method := g.obj(types2.AsNamed(recvType2).Method(last)) - n = ir.NewSelectorExpr(pos, ir.OCALLPART, x, method.Sym()) + n = ir.NewSelectorExpr(pos, ir.OCALLPART, x, typecheck.Lookup(expr.Sel.Value)) n.(*ir.SelectorExpr).Selection = types.NewField(pos, method.Sym(), method.Type()) n.(*ir.SelectorExpr).Selection.Nname = method typed(method.Type(), n) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 3ebc8dff6d..751a628256 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -112,14 +112,30 @@ func (g *irgen) stencil() { // EditChildren rather than Visit), where we actually change the // OFUNCINST node to an ONAME for the instantiated function. // EditChildren is more expensive than Visit, so we only do this - // in the infrequent case of an OFUNCINSt without a corresponding + // in the infrequent case of an OFUNCINST without a corresponding // call. if foundFuncInst { var edit func(ir.Node) ir.Node edit = func(x ir.Node) ir.Node { if x.Op() == ir.OFUNCINST { - st := g.getInstantiationForNode(x.(*ir.InstExpr)) - return st.Nname + // inst.X is either a function name node + // or a selector expression for a method. + inst := x.(*ir.InstExpr) + st := g.getInstantiationForNode(inst) + modified = true + if inst.X.Op() == ir.ONAME { + return st.Nname + } + assert(inst.X.Op() == ir.OCALLPART) + + // Return a new selector expression referring + // to the newly stenciled function. + oldse := inst.X.(*ir.SelectorExpr) + newse := ir.NewSelectorExpr(oldse.Pos(), ir.OCALLPART, oldse.X, oldse.Sel) + newse.Selection = types.NewField(oldse.Pos(), st.Sym(), st.Type()) + newse.Selection.Nname = st + typed(inst.Type(), newse) + return newse } ir.EditChildren(x, edit) return x diff --git a/test/typeparam/issue45817.go b/test/typeparam/issue45817.go new file mode 100644 index 0000000000..744698f40b --- /dev/null +++ b/test/typeparam/issue45817.go @@ -0,0 +1,25 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" +) + +type s[T any] struct { + a T +} +func (x s[T]) f() T { + return x.a +} +func main() { + x := s[int]{a:7} + f := x.f + if got, want := f(), 7; got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } +} -- GitLab From 9daf3cca8245a156b02da7bafef42637f8196f88 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 12 May 2021 09:26:45 -0700 Subject: [PATCH 0072/2500] [dev.typeparams] cmd/compile: keep instantiated method as a method, rather than converting to function Previously, we were converting an instantitated method to a function, by moving the receiver arg to the regular args, etc. But that made the type of the method signature inconsistent with the signature on the method fields, which leads to some problems with more complex programs with instantiations. And things work fine if we leave the instantiated method as a method. So, make the change to keep instantiated methods as real methods (until they are transformed much later in the compiler). Change-Id: If34be9e88c1b0ff819d557cf8dfbb31196542e7c Reviewed-on: https://go-review.googlesource.com/c/go/+/319490 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 51 ++++++++++++++--------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 751a628256..adcea2c087 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -87,19 +87,20 @@ func (g *irgen) stencil() { call := n.(*ir.CallExpr) inst := call.X.(*ir.InstExpr) st := g.getInstantiationForNode(inst) - // Replace the OFUNCINST with a direct reference to the - // new stenciled function - call.X = st.Nname if inst.X.Op() == ir.OCALLPART { - // When we create an instantiation of a method - // call, we make it a function. So, move the - // receiver to be the first arg of the function - // call. - withRecv := make([]ir.Node, len(call.Args)+1) - dot := inst.X.(*ir.SelectorExpr) - withRecv[0] = dot.X - copy(withRecv[1:], call.Args) - call.Args = withRecv + // Replace the OFUNCINST with the selector + // expression, and update the selector expression + // to refer to the new stenciled function. + call.X = inst.X + se := call.X.(*ir.SelectorExpr) + se.Selection = types.NewField(se.Pos(), se.Sel, st.Type()) + se.Selection.Nname = st.Nname + se.SetOp(ir.ODOTMETH) + se.SetType(st.Type()) + } else { + // Replace the OFUNCINST with a direct reference to the + // new stenciled function + call.X = st.Nname } // Transform the Call now, which changes OCALL // to OCALLFUNC and does typecheckaste/assignconvfn. @@ -165,13 +166,13 @@ func (g *irgen) instantiateMethods() { baseSym := typ.Sym().Pkg.Lookup(genericTypeName(typ.Sym())) baseType := baseSym.Def.(*ir.Name).Type() for j, m := range typ.Methods().Slice() { - name := m.Nname.(*ir.Name) targs := make([]ir.Node, len(typ.RParams())) for k, targ := range typ.RParams() { targs[k] = ir.TypeNode(targ) } baseNname := baseType.Methods().Slice()[j].Nname.(*ir.Name) - name.Func = g.getInstantiation(baseNname, targs, true) + f := g.getInstantiation(baseNname, targs, true) + m.Nname = f.Nname } } g.instTypeList = nil @@ -315,15 +316,25 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []ir.No newf.Dcl[i] = subst.node(n).(*ir.Name) } - // Ugly: we have to insert the Name nodes of the parameters/results into + // Replace the types in the function signature. + // Ugly: also, we have to insert the Name nodes of the parameters/results into // the function type. The current function type has no Nname fields set, // because it came via conversion from the types2 type. oldt := nameNode.Type() - // We also transform a generic method type to the corresponding - // instantiated function type where the receiver is the first parameter. - newt := types.NewSignature(oldt.Pkg(), nil, nil, - subst.fields(ir.PPARAM, append(oldt.Recvs().FieldSlice(), oldt.Params().FieldSlice()...), newf.Dcl), - subst.fields(ir.PPARAMOUT, oldt.Results().FieldSlice(), newf.Dcl)) + dcl := newf.Dcl + var newrecv *types.Field + if oldt.Recv() != nil { + newrecv = subst.fields(ir.PPARAM, oldt.Recvs().FieldSlice(), dcl)[0] + if newrecv.Nname != nil { + // If we found the receiver in the dcl list, then skip it + // when we scan for the remaining params below. + assert(newrecv.Nname == dcl[0]) + dcl = dcl[1:] + } + } + newt := types.NewSignature(oldt.Pkg(), newrecv, nil, + subst.fields(ir.PPARAM, oldt.Params().FieldSlice(), dcl), + subst.fields(ir.PPARAMOUT, oldt.Results().FieldSlice(), dcl)) newf.Nname.SetType(newt) ir.MarkFunc(newf.Nname) -- GitLab From c3fa51c9a2288ae6441f54e3a59d82015f0b7728 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Thu, 6 May 2021 14:21:47 -0700 Subject: [PATCH 0073/2500] cmd/compile: changed representation of typeparam bound in types1 Especially with typesets, we should be able to fully represent a typeparam bound as just another type (actually an interface type). Change the representation of a typeparam in types1 to include a bound, which is just a type. Changed the signature for NewTypeParam() to take a sym, and not a package, since we always set the sym (name) of the typeparam when creating it. No need for an extra pkg field in Typeparam. Also added index field in the types1 representation of typeparam. This is especially needed to correctly export the typeparam, and re-import it as a types2 type (which requires the index to be set correctly). Change-Id: I50200e2489a97898c37d292b2bd025df790b0277 Reviewed-on: https://go-review.googlesource.com/c/go/+/319929 Reviewed-by: Robert Griesemer Trust: Robert Griesemer Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot --- src/cmd/compile/internal/noder/types.go | 7 ++--- src/cmd/compile/internal/types/type.go | 38 +++++++++++++++++++++---- src/cmd/compile/internal/types2/type.go | 5 ++++ 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index 8680559a41..8a2c023a1a 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -204,18 +204,15 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { return types.NewInterface(g.tpkg(typ), append(embeddeds, methods...)) case *types2.TypeParam: - tp := types.NewTypeParam(g.tpkg(typ)) // Save the name of the type parameter in the sym of the type. // Include the types2 subscript in the sym name sym := g.pkg(typ.Obj().Pkg()).Lookup(types2.TypeString(typ, func(*types2.Package) string { return "" })) - tp.SetSym(sym) + tp := types.NewTypeParam(sym, typ.Index()) // Set g.typs[typ] in case the bound methods reference typ. g.typs[typ] = tp - // TODO(danscales): we don't currently need to use the bounds - // anywhere, so eventually we can probably remove. bound := g.typ1(typ.Bound()) - *tp.Methods() = *bound.Methods() + tp.SetBound(bound) return tp case *types2.Tuple: diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 1a9aa6916a..d3c02fc56d 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -151,7 +151,7 @@ type Type struct { // TARRAY: *Array // TSLICE: Slice // TSSA: string - // TTYPEPARAM: *Interface (though we may not need to store/use the Interface info) + // TTYPEPARAM: *Typeparam Extra interface{} // Width is the width of this Type in bytes. @@ -377,6 +377,12 @@ type Interface struct { pkg *Pkg } +// Typeparam contains Type fields specific to typeparam types. +type Typeparam struct { + index int // type parameter index in source order, starting at 0 + bound *Type +} + // Ptr contains Type fields specific to pointer types. type Ptr struct { Elem *Type // element type @@ -558,7 +564,7 @@ func New(et Kind) *Type { case TRESULTS: t.Extra = new(Results) case TTYPEPARAM: - t.Extra = new(Interface) + t.Extra = new(Typeparam) } return t } @@ -825,6 +831,8 @@ func (t *Type) copy() *Type { case TARRAY: x := *t.Extra.(*Array) nt.Extra = &x + case TTYPEPARAM: + base.Fatalf("typeparam types cannot be copied") case TTUPLE, TSSA, TRESULTS: base.Fatalf("ssa types cannot be copied") } @@ -1766,14 +1774,34 @@ func NewInterface(pkg *Pkg, methods []*Field) *Type { return t } -// NewTypeParam returns a new type param. -func NewTypeParam(pkg *Pkg) *Type { +// NewTypeParam returns a new type param with the specified sym (package and name) +// and specified index within the typeparam list. +func NewTypeParam(sym *Sym, index int) *Type { t := New(TTYPEPARAM) - t.Extra.(*Interface).pkg = pkg + t.sym = sym + t.Extra.(*Typeparam).index = index t.SetHasTParam(true) return t } +// Index returns the index of the type param within its param list. +func (t *Type) Index() int { + t.wantEtype(TTYPEPARAM) + return t.Extra.(*Typeparam).index +} + +// SetBound sets the bound of a typeparam. +func (t *Type) SetBound(bound *Type) { + t.wantEtype(TTYPEPARAM) + t.Extra.(*Typeparam).bound = bound +} + +// Bound returns the bound of a typeparam. +func (t *Type) Bound() *Type { + t.wantEtype(TTYPEPARAM) + return t.Extra.(*Typeparam).bound +} + const BOGUS_FUNARG_OFFSET = -1000000000 func unzeroFieldOffsets(f []*Field) { diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index e6c260ff67..88dedbad45 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -760,6 +760,11 @@ func (check *Checker) NewTypeParam(obj *TypeName, index int, bound Type) *TypePa return typ } +// Index returns the index of the type param within its param list. +func (t *TypeParam) Index() int { + return t.index +} + func (t *TypeParam) Bound() *Interface { iface := asInterface(t.bound) // use the type bound position if we have one -- GitLab From 03ed590e517980afc9c48816aced517fce2996ca Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 6 May 2021 16:04:05 -0700 Subject: [PATCH 0074/2500] [dev.typeparams] cmd/compile/internal/types2: use Checker-provided type parameter IDs when possible This is a port of https://golang.org/cl/317472. For #46003. Change-Id: Ie7b8880d43d459527b981ed4f60ee4d80a3cd17a Reviewed-on: https://go-review.googlesource.com/c/go/+/320149 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/api_test.go | 1 - src/cmd/compile/internal/types2/check.go | 1 + src/cmd/compile/internal/types2/type.go | 14 ++++++++++---- src/cmd/compile/internal/types2/types_test.go | 8 -------- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index 873390c1e9..e1020a1219 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -349,7 +349,6 @@ func TestTypesInfo(t *testing.T) { } for _, test := range tests { - ResetId() // avoid renumbering of type parameter ids when adding tests info := Info{Types: make(map[syntax.Expr]TypeAndValue)} var name string if strings.HasPrefix(test.src, brokenPkg) { diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go index 8d6cd1edab..f80a918467 100644 --- a/src/cmd/compile/internal/types2/check.go +++ b/src/cmd/compile/internal/types2/check.go @@ -83,6 +83,7 @@ type Checker struct { pkg *Package *Info version version // accepted language version + nextID uint64 // unique Id for type parameters (first valid Id is 1) objMap map[Object]*declInfo // maps package-level objects and (non-interface) methods to declaration info impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package posMap map[*Interface][]syntax.Pos // maps interface types to lists of embedded interface positions diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 88dedbad45..cf119a1b23 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -732,11 +732,11 @@ func (t *Named) AddMethod(m *Func) { // Note: This is a uint32 rather than a uint64 because the // respective 64 bit atomic instructions are not available // on all platforms. -var lastId uint32 +var lastID uint32 -// nextId returns a value increasing monotonically by 1 with +// nextID returns a value increasing monotonically by 1 with // each call, starting with 1. It may be called concurrently. -func nextId() uint64 { return uint64(atomic.AddUint32(&lastId, 1)) } +func nextID() uint64 { return uint64(atomic.AddUint32(&lastID, 1)) } // A TypeParam represents a type parameter type. type TypeParam struct { @@ -753,7 +753,13 @@ func (t *TypeParam) Obj() *TypeName { return t.obj } // NewTypeParam returns a new TypeParam. func (check *Checker) NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam { assert(bound != nil) - typ := &TypeParam{check: check, id: nextId(), obj: obj, index: index, bound: bound} + // Always increment lastID, even if it is not used. + id := nextID() + if check != nil { + check.nextID++ + id = check.nextID + } + typ := &TypeParam{check: check, id: id, obj: obj, index: index, bound: bound} if obj.typ == nil { obj.typ = typ } diff --git a/src/cmd/compile/internal/types2/types_test.go b/src/cmd/compile/internal/types2/types_test.go index 096402148d..11dca0b53d 100644 --- a/src/cmd/compile/internal/types2/types_test.go +++ b/src/cmd/compile/internal/types2/types_test.go @@ -4,14 +4,6 @@ package types2 -import "sync/atomic" - func init() { acceptMethodTypeParams = true } - -// Upon calling ResetId, nextId starts with 1 again. -// It may be called concurrently. This is only needed -// for tests where we may want to have a consistent -// numbering for each individual test case. -func ResetId() { atomic.StoreUint32(&lastId, 0) } -- GitLab From 0d1e293b2329a013f03ea3f742f1716098ee282c Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 14 May 2021 10:05:16 -0700 Subject: [PATCH 0075/2500] [dev.typeparams] cmd/compile/internal/types2: print "incomplete" for interfaces in debug mode only The /* incomplete */ comment printed for interfaces that have not been "completed" yet is not useful for end-users; it's here for type-checker debugging. Rather than trying to pass through a debug flag through all print routines (which may require new exported API), simply don't print the comment unless we have the debug flag set inside the type-checker. For #46167. Change-Id: Ibd22edfe63001dfd2b814eeb94c2d54d35afd88c Reviewed-on: https://go-review.googlesource.com/c/go/+/320150 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/types_test.go | 3 +++ src/cmd/compile/internal/types2/typestring.go | 2 +- src/cmd/compile/internal/types2/typestring_test.go | 4 ++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/types2/types_test.go b/src/cmd/compile/internal/types2/types_test.go index 11dca0b53d..1525844f2d 100644 --- a/src/cmd/compile/internal/types2/types_test.go +++ b/src/cmd/compile/internal/types2/types_test.go @@ -7,3 +7,6 @@ package types2 func init() { acceptMethodTypeParams = true } + +// Debug is set if types2 is built with debug mode enabled. +const Debug = debug diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 40016697b7..e85cc8ed35 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -226,7 +226,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { empty = false } } - if t.allMethods == nil || len(t.methods) > len(t.allMethods) { + if debug && (t.allMethods == nil || len(t.methods) > len(t.allMethods)) { if !empty { buf.WriteByte(' ') } diff --git a/src/cmd/compile/internal/types2/typestring_test.go b/src/cmd/compile/internal/types2/typestring_test.go index d98e9a5ade..618fdc0757 100644 --- a/src/cmd/compile/internal/types2/typestring_test.go +++ b/src/cmd/compile/internal/types2/typestring_test.go @@ -138,6 +138,10 @@ func TestTypeString(t *testing.T) { var nopos syntax.Pos func TestIncompleteInterfaces(t *testing.T) { + if !Debug { + t.Skip("requires type checker to be compiled with debug = true") + } + sig := NewSignature(nil, nil, nil, false) m := NewFunc(nopos, nil, "m", sig) for _, test := range []struct { -- GitLab From f39200b037e022d0f79ed478a45492306aaf5629 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 17 May 2021 11:49:53 -0700 Subject: [PATCH 0076/2500] [dev.typeparams] go/constant: implement Kind.String Fixes #46211. Change-Id: I7e373be5ccf9c6b53d58ed942addd17d28c3efa1 Reviewed-on: https://go-review.googlesource.com/c/go/+/320491 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Matthew Dempsky TryBot-Result: Go Bot --- src/go/constant/kind_string.go | 28 ++++++++++++++++++++++++++++ src/go/constant/value.go | 2 ++ 2 files changed, 30 insertions(+) create mode 100644 src/go/constant/kind_string.go diff --git a/src/go/constant/kind_string.go b/src/go/constant/kind_string.go new file mode 100644 index 0000000000..700332511d --- /dev/null +++ b/src/go/constant/kind_string.go @@ -0,0 +1,28 @@ +// Code generated by "stringer -type Kind"; DO NOT EDIT. + +package constant + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[Unknown-0] + _ = x[Bool-1] + _ = x[String-2] + _ = x[Int-3] + _ = x[Float-4] + _ = x[Complex-5] +} + +const _Kind_name = "UnknownBoolStringIntFloatComplex" + +var _Kind_index = [...]uint8{0, 7, 11, 17, 20, 25, 32} + +func (i Kind) String() string { + if i < 0 || i >= Kind(len(_Kind_index)-1) { + return "Kind(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _Kind_name[_Kind_index[i]:_Kind_index[i+1]] +} diff --git a/src/go/constant/value.go b/src/go/constant/value.go index 78cb3f896f..014e873100 100644 --- a/src/go/constant/value.go +++ b/src/go/constant/value.go @@ -24,6 +24,8 @@ import ( "unicode/utf8" ) +//go:generate stringer -type Kind + // Kind specifies the kind of value represented by a Value. type Kind int -- GitLab From 077f03f4d878f3b62e4aa15cdbd7cabc9dd08a11 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 18 May 2021 12:47:30 -0400 Subject: [PATCH 0077/2500] [dev.typeparams] runtime: use internal/abi.FuncPCABI0 for sigtramp PC on FreeBSD Same as CL 313230, for FreeBSD. sigtramp is the only one we need. Change-Id: Iefc00c1cb7e70b08a07c3bc3604b2114fd86563d Reviewed-on: https://go-review.googlesource.com/c/go/+/320912 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/runtime/os_freebsd2.go | 4 +++- src/runtime/os_freebsd_amd64.go | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/runtime/os_freebsd2.go b/src/runtime/os_freebsd2.go index fde6fbf1b1..53ba23b64c 100644 --- a/src/runtime/os_freebsd2.go +++ b/src/runtime/os_freebsd2.go @@ -7,6 +7,8 @@ package runtime +import "internal/abi" + //go:nosplit //go:nowritebarrierrec func setsig(i uint32, fn uintptr) { @@ -14,7 +16,7 @@ func setsig(i uint32, fn uintptr) { sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART sa.sa_mask = sigset_all if fn == funcPC(sighandler) { - fn = funcPC(sigtramp) + fn = abi.FuncPCABI0(sigtramp) } sa.sa_handler = fn sigaction(i, &sa, nil) diff --git a/src/runtime/os_freebsd_amd64.go b/src/runtime/os_freebsd_amd64.go index dc0bb9ff96..7ae80c2506 100644 --- a/src/runtime/os_freebsd_amd64.go +++ b/src/runtime/os_freebsd_amd64.go @@ -4,6 +4,8 @@ package runtime +import "internal/abi" + func cgoSigtramp() //go:nosplit @@ -14,9 +16,9 @@ func setsig(i uint32, fn uintptr) { sa.sa_mask = sigset_all if fn == funcPC(sighandler) { if iscgo { - fn = funcPC(cgoSigtramp) + fn = abi.FuncPCABI0(cgoSigtramp) } else { - fn = funcPC(sigtramp) + fn = abi.FuncPCABI0(sigtramp) } } sa.sa_handler = fn -- GitLab From 54f067812dd870c305daabd22ca190b0f48e672e Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Wed, 12 May 2021 18:25:20 -0700 Subject: [PATCH 0078/2500] [dev.fuzz] internal/fuzz: include coverage in logged stats Change-Id: I51ec70b69e802fd0d962ba9544e96e29b1627fef Reviewed-on: https://go-review.googlesource.com/c/go/+/319590 Trust: Roland Shoemaker Trust: Katie Hockman Run-TryBot: Roland Shoemaker TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/internal/fuzz/fuzz.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index c46220e3ec..b4145f58dc 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -465,14 +465,18 @@ func (c *coordinator) updateStats(result fuzzResult) { } func (c *coordinator) logStats() { - // TODO(jayconrod,katiehockman): consider printing the amount of coverage - // that has been reached so far (perhaps a percentage of edges?) elapsed := time.Since(c.startTime) if c.coverageOnlyRun() { fmt.Fprintf(c.opts.Log, "gathering baseline coverage, elapsed: %.1fs, workers: %d, left: %d\n", elapsed.Seconds(), c.opts.Parallel, c.covOnlyInputs) } else { rate := float64(c.count) / elapsed.Seconds() - fmt.Fprintf(c.opts.Log, "fuzzing, elapsed: %.1fs, execs: %d (%.0f/sec), workers: %d, interesting: %d\n", elapsed.Seconds(), c.count, rate, c.opts.Parallel, c.interestingCount) + edges, hits := len(c.coverageData), 0 + for _, c := range c.coverageData { + if c > 0 { + hits++ + } + } + fmt.Fprintf(c.opts.Log, "fuzzing, elapsed: %.1fs, execs: %d (%.0f/sec), workers: %d, interesting: %d, coverage: %d/%d\n", elapsed.Seconds(), c.count, rate, c.opts.Parallel, c.interestingCount, hits, edges) } } -- GitLab From f208f1ac993b0b47ebf9bb247a4bc16bc53ad0fd Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 17 May 2021 11:40:21 -0700 Subject: [PATCH 0079/2500] [dev.typeparams] cmd/compile/internal/ir: more useful Fatalfs This CL just adds some additional details to existing Fatalf messages that make them more useful for identifying what went wrong. Change-Id: Icba0d943ccfb1b810a1ede0977cc8cf22b2afde5 Reviewed-on: https://go-review.googlesource.com/c/go/+/320612 Trust: Matthew Dempsky Trust: Dan Scales Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/ir/func.go | 2 +- src/cmd/compile/internal/ir/node.go | 2 +- src/cmd/compile/internal/ir/val.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go index 20fe965711..a4231a1bcb 100644 --- a/src/cmd/compile/internal/ir/func.go +++ b/src/cmd/compile/internal/ir/func.go @@ -279,7 +279,7 @@ func FuncSymName(s *types.Sym) string { // MarkFunc marks a node as a function. func MarkFunc(n *Name) { if n.Op() != ONAME || n.Class != Pxxx { - base.Fatalf("expected ONAME/Pxxx node, got %v", n) + base.FatalfAt(n.Pos(), "expected ONAME/Pxxx node, got %v (%v/%v)", n, n.Op(), n.Class) } n.Class = PFUNC diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index af559cc082..9191eeb1d6 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -563,7 +563,7 @@ func OuterValue(n Node) Node { for { switch nn := n; nn.Op() { case OXDOT: - base.Fatalf("OXDOT in walk") + base.FatalfAt(n.Pos(), "OXDOT in walk: %v", n) case ODOT: nn := nn.(*SelectorExpr) n = nn.X diff --git a/src/cmd/compile/internal/ir/val.go b/src/cmd/compile/internal/ir/val.go index 03c320e205..af9f95b29d 100644 --- a/src/cmd/compile/internal/ir/val.go +++ b/src/cmd/compile/internal/ir/val.go @@ -66,7 +66,7 @@ func Float64Val(v constant.Value) float64 { func AssertValidTypeForConst(t *types.Type, v constant.Value) { if !ValidTypeForConst(t, v) { - base.Fatalf("%v does not represent %v", t, v) + base.Fatalf("%v does not represent %v (%v)", t, v, v.Kind()) } } -- GitLab From bbc0059b037c22c27fe42ed0a97d1400ebd7785d Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 17 May 2021 13:59:25 -0700 Subject: [PATCH 0080/2500] [dev.typeparams] test: run more tests with -G=3 This CL expands the current logic for re-running "errorcheck" tests with -G=3 to run (almost) all regress tests that way. This exposes a handful of additional failures, so the excluded-files list is expanded accordingly. (The next CL addresses several of the easy test cases.) Change-Id: Ia5ce399f225d83e817a046a3bd1a41b9681be3af Reviewed-on: https://go-review.googlesource.com/c/go/+/320609 Run-TryBot: Matthew Dempsky Trust: Matthew Dempsky Trust: Dan Scales TryBot-Result: Go Bot Reviewed-by: Dan Scales --- test/run.go | 293 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 199 insertions(+), 94 deletions(-) diff --git a/test/run.go b/test/run.go index 5e60de7624..fc4e89fc64 100644 --- a/test/run.go +++ b/test/run.go @@ -42,6 +42,7 @@ var ( linkshared = flag.Bool("linkshared", false, "") updateErrors = flag.Bool("update_errors", false, "update error messages in test file based on compiler output") runoutputLimit = flag.Int("l", defaultRunOutputLimit(), "number of parallel runoutput tests to run") + generics = flag.String("G", "0,3", "a comma-separated list of -G compiler flags to test with") shard = flag.Int("shard", 0, "shard index to run. Only applicable if -shards is non-zero.") shards = flag.Int("shards", 0, "number of shards. If 0, all tests are run. This is used by the continuous build.") @@ -82,6 +83,15 @@ const maxTests = 5000 func main() { flag.Parse() + var glevels []int + for _, s := range strings.Split(*generics, ",") { + glevel, err := strconv.Atoi(s) + if err != nil { + log.Fatalf("invalid -G flag: %v", err) + } + glevels = append(glevels, glevel) + } + goos = getenv("GOOS", runtime.GOOS) goarch = getenv("GOARCH", runtime.GOARCH) cgoEnv, err := exec.Command(goTool(), "env", "CGO_ENABLED").Output() @@ -113,11 +123,11 @@ func main() { } if fi, err := os.Stat(arg); err == nil && fi.IsDir() { for _, baseGoFile := range goFiles(arg) { - tests = append(tests, startTest(arg, baseGoFile)) + tests = append(tests, startTests(arg, baseGoFile, glevels)...) } } else if strings.HasSuffix(arg, ".go") { dir, file := filepath.Split(arg) - tests = append(tests, startTest(dir, file)) + tests = append(tests, startTests(dir, file, glevels)...) } else { log.Fatalf("can't yet deal with non-directory and non-go file %q", arg) } @@ -125,7 +135,7 @@ func main() { } else { for _, dir := range dirs { for _, baseGoFile := range goFiles(dir) { - tests = append(tests, startTest(dir, baseGoFile)) + tests = append(tests, startTests(dir, baseGoFile, glevels)...) } } } @@ -151,7 +161,8 @@ func main() { resCount[status]++ dt := fmt.Sprintf("%.3fs", test.dt.Seconds()) if status == "FAIL" { - fmt.Printf("# go run run.go -- %s\n%s\nFAIL\t%s\t%s\n", + fmt.Printf("# go run run.go -G=%v %s\n%s\nFAIL\t%s\t%s\n", + test.glevel, path.Join(test.dir, test.gofile), errStr, test.goFileName(), dt) continue @@ -270,6 +281,7 @@ type test struct { dir, gofile string donec chan bool // closed when done dt time.Duration + glevel int // what -G level this test should use src string @@ -277,23 +289,27 @@ type test struct { err error } -// startTest -func startTest(dir, gofile string) *test { - t := &test{ - dir: dir, - gofile: gofile, - donec: make(chan bool, 1), - } - if toRun == nil { - toRun = make(chan *test, maxTests) - go runTests() - } - select { - case toRun <- t: - default: - panic("toRun buffer size (maxTests) is too small") +func startTests(dir, gofile string, glevels []int) []*test { + tests := make([]*test, len(glevels)) + for i, glevel := range glevels { + t := &test{ + dir: dir, + gofile: gofile, + glevel: glevel, + donec: make(chan bool, 1), + } + if toRun == nil { + toRun = make(chan *test, maxTests) + go runTests() + } + select { + case toRun <- t: + default: + panic("toRun buffer size (maxTests) is too small") + } + tests[i] = t } - return t + return tests } // runTests runs tests in parallel, but respecting the order they @@ -480,12 +496,16 @@ func init() { checkShouldTest() } // This must match the flags used for building the standard library, // or else the commands will rebuild any needed packages (like runtime) // over and over. -func goGcflags() string { - return "-gcflags=all=" + os.Getenv("GO_GCFLAGS") +func (t *test) goGcflags() string { + flags := os.Getenv("GO_GCFLAGS") + if t.glevel != 0 { + flags = fmt.Sprintf("%s -G=%v", flags, t.glevel) + } + return "-gcflags=all=" + flags } -func goGcflagsIsEmpty() bool { - return "" == os.Getenv("GO_GCFLAGS") +func (t *test) goGcflagsIsEmpty() bool { + return "" == os.Getenv("GO_GCFLAGS") && t.glevel == 0 } var errTimeout = errors.New("command exceeded time limit") @@ -498,6 +518,17 @@ func (t *test) run() { close(t.donec) }() + if t.glevel > 0 { + // Files excluded from generics testing. + filename := strings.Replace(t.goFileName(), "\\", "/", -1) // goFileName() uses \ on Windows + if excludedFiles[filename] { + if *verbose { + fmt.Printf("excl\t%s\n", filename) + } + return + } + } + srcBytes, err := ioutil.ReadFile(t.goFileName()) if err != nil { t.err = err @@ -616,6 +647,49 @@ func (t *test) run() { } } + type Tool int + + const ( + _ Tool = iota + AsmCheck + Build + Run + Compile + ) + + // checkFlags reports whether the current test configuration should + // be skipped because flags (which should be an arguments list for + // "go tool compile", not "go build") contains an excluded flag. + // It will also update flags as appropriate. + checkFlags := func(tool Tool) bool { + if t.glevel > 0 { + return true + } + + switch tool { + case Build, Run: + // ok; handled in goGcflags + + case Compile: + for _, flag := range flags { + for _, pattern := range excludedFlags { + if strings.Contains(flag, pattern) { + if *verbose { + fmt.Printf("excl\t%s\t%s\n", t.goFileName(), flags) + } + return true // cannot handle flag + } + } + } + flags = append(flags, fmt.Sprintf("-G=%v", t.glevel)) + + default: + return false + } + + return true + } + t.makeTempDir() if !*keep { defer os.RemoveAll(t.tempDir) @@ -692,6 +766,10 @@ func (t *test) run() { t.err = fmt.Errorf("unimplemented action %q", action) case "asmcheck": + if !checkFlags(AsmCheck) { + return + } + // Compile Go file and match the generated assembly // against a set of regexps in comments. ops := t.wantedAsmOpcodes(long) @@ -746,6 +824,10 @@ func (t *test) run() { return case "errorcheck": + if !checkFlags(Compile) { + return + } + // Compile Go file. // Fail if wantError is true and compilation was successful and vice versa. // Match errors produced by gc against errors in comments. @@ -774,72 +856,20 @@ func (t *test) run() { t.updateErrors(string(out), long) } t.err = t.errorCheck(string(out), wantAuto, long, t.gofile) - if t.err != nil { - return // don't hide error if run below succeeds - } - - // The following is temporary scaffolding to get types2 typechecker - // up and running against the existing test cases. The explicitly - // listed files don't pass yet, usually because the error messages - // are slightly different (this list is not complete). Any errorcheck - // tests that require output from analysis phases past initial type- - // checking are also excluded since these phases are not running yet. - // We can get rid of this code once types2 is fully plugged in. - - // For now we're done when we can't handle the file or some of the flags. - // The first goal is to eliminate the excluded list; the second goal is to - // eliminate the flag list. - // Excluded files. - filename := strings.Replace(t.goFileName(), "\\", "/", -1) // goFileName() uses \ on Windows - if excluded[filename] { - if *verbose { - fmt.Printf("excl\t%s\n", filename) - } - return // cannot handle file yet - } - - // Excluded flags. - for _, flag := range flags { - for _, pattern := range []string{ - "-m", - } { - if strings.Contains(flag, pattern) { - if *verbose { - fmt.Printf("excl\t%s\t%s\n", filename, flags) - } - return // cannot handle flag - } - } - } - - // Run errorcheck again with -G option (new typechecker). - cmdline = []string{goTool(), "tool", "compile", "-G=3", "-C", "-e", "-o", "a.o"} - // No need to add -dynlink even if linkshared if we're just checking for errors... - cmdline = append(cmdline, flags...) - cmdline = append(cmdline, long) - out, err = runcmd(cmdline...) - if wantError { - if err == nil { - t.err = fmt.Errorf("compilation succeeded unexpectedly\n%s", out) - return - } - } else { - if err != nil { - t.err = err - return - } - } - if *updateErrors { - t.updateErrors(string(out), long) + case "compile": + if !checkFlags(Compile) { + return } - t.err = t.errorCheck(string(out), wantAuto, long, t.gofile) - case "compile": // Compile Go file. _, t.err = compileFile(runcmd, long, flags) case "compiledir": + if !checkFlags(Compile) { + return + } + // Compile all files in the directory as packages in lexicographic order. longdir := filepath.Join(cwd, t.goDirName()) pkgs, err := goDirPackages(longdir, singlefilepkgs) @@ -855,6 +885,10 @@ func (t *test) run() { } case "errorcheckdir", "errorcheckandrundir": + if !checkFlags(Compile) { + return + } + flags = append(flags, "-d=panic") // Compile and errorCheck all files in the directory as packages in lexicographic order. // If errorcheckdir and wantError, compilation of the last package must fail. @@ -900,6 +934,10 @@ func (t *test) run() { fallthrough case "rundir": + if !checkFlags(Run) { + return + } + // Compile all files in the directory as packages in lexicographic order. // In case of errorcheckandrundir, ignore failed compilation of the package before the last. // Link as if the last file is the main package, run it. @@ -958,6 +996,10 @@ func (t *test) run() { } case "runindir": + if !checkFlags(Run) { + return + } + // Make a shallow copy of t.goDirName() in its own module and GOPATH, and // run "go run ." in it. The module path (and hence import path prefix) of // the copy is equal to the basename of the source directory. @@ -983,7 +1025,7 @@ func (t *test) run() { return } - cmd := []string{goTool(), "run", goGcflags()} + cmd := []string{goTool(), "run", t.goGcflags()} if *linkshared { cmd = append(cmd, "-linkshared") } @@ -997,13 +1039,21 @@ func (t *test) run() { t.checkExpectedOutput(out) case "build": + if !checkFlags(Build) { + return + } + // Build Go file. - _, err := runcmd(goTool(), "build", goGcflags(), "-o", "a.exe", long) + _, err := runcmd(goTool(), "build", t.goGcflags(), "-o", "a.exe", long) if err != nil { t.err = err } case "builddir", "buildrundir": + if !checkFlags(Build) { + return + } + // Build an executable from all the .go and .s files in a subdirectory. // Run it and verify its output in the buildrundir case. longdir := filepath.Join(cwd, t.goDirName()) @@ -1083,10 +1133,14 @@ func (t *test) run() { } case "buildrun": + if !checkFlags(Build) { + return + } + // Build an executable from Go file, then run it, verify its output. // Useful for timeout tests where failure mode is infinite loop. // TODO: not supported on NaCl - cmd := []string{goTool(), "build", goGcflags(), "-o", "a.exe"} + cmd := []string{goTool(), "build", t.goGcflags(), "-o", "a.exe"} if *linkshared { cmd = append(cmd, "-linkshared") } @@ -1108,13 +1162,17 @@ func (t *test) run() { t.checkExpectedOutput(out) case "run": + if !checkFlags(Run) { + return + } + // Run Go file if no special go command flags are provided; // otherwise build an executable and run it. // Verify the output. runInDir = "" var out []byte var err error - if len(flags)+len(args) == 0 && goGcflagsIsEmpty() && !*linkshared && goarch == runtime.GOARCH && goos == runtime.GOOS { + if len(flags)+len(args) == 0 && t.goGcflagsIsEmpty() && !*linkshared && goarch == runtime.GOARCH && goos == runtime.GOOS { // If we're not using special go command flags, // skip all the go command machinery. // This avoids any time the go command would @@ -1136,7 +1194,7 @@ func (t *test) run() { } out, err = runcmd(append([]string{exe}, args...)...) } else { - cmd := []string{goTool(), "run", goGcflags()} + cmd := []string{goTool(), "run", t.goGcflags()} if *linkshared { cmd = append(cmd, "-linkshared") } @@ -1151,6 +1209,10 @@ func (t *test) run() { t.checkExpectedOutput(out) case "runoutput": + if !checkFlags(Run) { + return + } + // Run Go file and write its output into temporary Go file. // Run generated Go file and verify its output. rungatec <- true @@ -1158,7 +1220,7 @@ func (t *test) run() { <-rungatec }() runInDir = "" - cmd := []string{goTool(), "run", goGcflags()} + cmd := []string{goTool(), "run", t.goGcflags()} if *linkshared { cmd = append(cmd, "-linkshared") } @@ -1173,7 +1235,7 @@ func (t *test) run() { t.err = fmt.Errorf("write tempfile:%s", err) return } - cmd = []string{goTool(), "run", goGcflags()} + cmd = []string{goTool(), "run", t.goGcflags()} if *linkshared { cmd = append(cmd, "-linkshared") } @@ -1186,10 +1248,14 @@ func (t *test) run() { t.checkExpectedOutput(out) case "errorcheckoutput": + if !checkFlags(Compile) { + return + } + // Run Go file and write its output into temporary Go file. // Compile and errorCheck generated Go file. runInDir = "" - cmd := []string{goTool(), "run", goGcflags()} + cmd := []string{goTool(), "run", t.goGcflags()} if *linkshared { cmd = append(cmd, "-linkshared") } @@ -1941,9 +2007,26 @@ func overlayDir(dstRoot, srcRoot string) error { }) } +// The following is temporary scaffolding to get types2 typechecker +// up and running against the existing test cases. The explicitly +// listed files don't pass yet, usually because the error messages +// are slightly different (this list is not complete). Any errorcheck +// tests that require output from analysis phases past initial type- +// checking are also excluded since these phases are not running yet. +// We can get rid of this code once types2 is fully plugged in. + +// For now we skip tests when we can't handle the file or some of the flags. +// The first goal is to eliminate the excluded list; the second goal is to +// eliminate the flag list. + +var excludedFlags = []string{ + "-G", // skip redundant testing + "-m", +} + // List of files that the compiler cannot errorcheck with the new typechecker (compiler -G option). // Temporary scaffolding until we pass all the tests at which point this map can be removed. -var excluded = map[string]bool{ +var excludedFiles = map[string]bool{ "complit1.go": true, // types2 reports extra errors "const2.go": true, // types2 not run after syntax errors "ddd1.go": true, // issue #42987 @@ -1955,51 +2038,73 @@ var excluded = map[string]bool{ "initializerr.go": true, // types2 reports extra errors "linkname2.go": true, // error reported by noder (not running for types2 errorcheck test) "notinheap.go": true, // types2 doesn't report errors about conversions that are invalid due to //go:notinheap + "printbig.go": true, // large untyped int passed to print (32-bit) "shift1.go": true, // issue #42989 + "shift2.go": true, // bad code generation; constant.Value of the wrong kind? "typecheck.go": true, // invalid function is not causing errors when called "writebarrier.go": true, // correct diagnostics, but different lines (probably irgen's fault) + "interface/private.go": true, // types2 phrases errors differently (doesn't use non-spec "private" term) + + "fixedbugs/bug114.go": true, // large untyped int passed to println (32-bit) "fixedbugs/bug176.go": true, // types2 reports all errors (pref: types2) "fixedbugs/bug195.go": true, // types2 reports slightly different (but correct) bugs - "fixedbugs/bug228.go": true, // types2 not run after syntax errors + "fixedbugs/bug228.go": true, // types2 doesn't run when there are syntax errors "fixedbugs/bug231.go": true, // types2 bug? (same error reported twice) + "fixedbugs/bug248.go": true, // types2 reports different (but ok) error message "fixedbugs/bug255.go": true, // types2 reports extra errors + "fixedbugs/bug345.go": true, // types2 reports different (but ok) error message "fixedbugs/bug351.go": true, // types2 reports extra errors "fixedbugs/bug374.go": true, // types2 reports extra errors "fixedbugs/bug385_32.go": true, // types2 doesn't produce missing error "type .* too large" (32-bit specific) "fixedbugs/bug388.go": true, // types2 not run due to syntax errors "fixedbugs/bug412.go": true, // types2 produces a follow-on error + "fixedbugs/bug420.go": true, // ICE in irgen + "fixedbugs/bug460.go": true, // types2 reports different (but probably ok) error message + "fixedbugs/issue10700.go": true, // types2 reports ok hint, but does not match regexp "fixedbugs/issue11590.go": true, // types2 doesn't report a follow-on error (pref: types2) "fixedbugs/issue11610.go": true, // types2 not run after syntax errors "fixedbugs/issue11614.go": true, // types2 reports an extra error "fixedbugs/issue13415.go": true, // declared but not used conflict "fixedbugs/issue14520.go": true, // missing import path error by types2 + "fixedbugs/issue16133.go": true, // types2 doesn't use package path for qualified identifiers when package name is ambiguous "fixedbugs/issue16428.go": true, // types2 reports two instead of one error "fixedbugs/issue17038.go": true, // types2 doesn't report a follow-on error (pref: types2) + "fixedbugs/issue17270.go": true, // ICE in irgen "fixedbugs/issue17645.go": true, // multiple errors on same line "fixedbugs/issue18331.go": true, // missing error about misuse of //go:noescape (irgen needs code from noder) "fixedbugs/issue18393.go": true, // types2 not run after syntax errors + "fixedbugs/issue18419.go": true, // types2 reports "fixedbugs/issue19012.go": true, // multiple errors on same line + "fixedbugs/issue20174.go": true, // ICE due to width not calculated (probably irgen's fault) "fixedbugs/issue20233.go": true, // types2 reports two instead of one error (pref: compiler) "fixedbugs/issue20245.go": true, // types2 reports two instead of one error (pref: compiler) "fixedbugs/issue20250.go": true, // correct diagnostics, but different lines (probably irgen's fault) "fixedbugs/issue21979.go": true, // types2 doesn't report a follow-on error (pref: types2) + "fixedbugs/issue23305.go": true, // large untyped int passed to println (32-bit) "fixedbugs/issue23732.go": true, // types2 reports different (but ok) line numbers "fixedbugs/issue25958.go": true, // types2 doesn't report a follow-on error (pref: types2) "fixedbugs/issue28079b.go": true, // types2 reports follow-on errors "fixedbugs/issue28268.go": true, // types2 reports follow-on errors + "fixedbugs/issue31053.go": true, // types2 reports "unknown field" instead of "cannot refer to unexported field" "fixedbugs/issue33460.go": true, // types2 reports alternative positions in separate error "fixedbugs/issue41575.go": true, // types2 reports alternative positions in separate error "fixedbugs/issue42058a.go": true, // types2 doesn't report "channel element type too large" "fixedbugs/issue42058b.go": true, // types2 doesn't report "channel element type too large" "fixedbugs/issue4232.go": true, // types2 reports (correct) extra errors + "fixedbugs/issue43479.go": true, // ICE in iexport due to Syms from the wrong package + "fixedbugs/issue43962.go": true, // types2 panics when importing package named "init" + "fixedbugs/issue44432.go": true, // types2 reports different (but ok) error message "fixedbugs/issue4452.go": true, // types2 reports (correct) extra errors + "fixedbugs/issue4510.go": true, // types2 reports different (but ok) line numbers + "fixedbugs/issue4909b.go": true, // types2 reports different (but ok) error message "fixedbugs/issue5609.go": true, // types2 needs a better error message "fixedbugs/issue6889.go": true, // types2 can handle this without constant overflow - "fixedbugs/issue7525.go": true, // types2 reports init cycle error on different line - ok otherwise "fixedbugs/issue7525b.go": true, // types2 reports init cycle error on different line - ok otherwise "fixedbugs/issue7525c.go": true, // types2 reports init cycle error on different line - ok otherwise "fixedbugs/issue7525d.go": true, // types2 reports init cycle error on different line - ok otherwise "fixedbugs/issue7525e.go": true, // types2 reports init cycle error on different line - ok otherwise + "fixedbugs/issue7525.go": true, // types2 reports init cycle error on different line - ok otherwise + "fixedbugs/issue9691.go": true, // "cannot assign to int(.autotmp_4)" (probably irgen's fault) } -- GitLab From 140cd7c1d3f1f37ae332d504897a98800a80e0e6 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 13 May 2021 18:07:57 -0400 Subject: [PATCH 0081/2500] [dev.typeparams] runtime: use internal/abi.FuncPCABI0 for syscall wrappers on OpenBSD Same as CL 313230, for OpenBSD. Change-Id: I56f4a8a368e1a17615a01db4e2b6c53e4ed263bd Reviewed-on: https://go-review.googlesource.com/c/go/+/320889 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh Reviewed-by: Michael Knyszek --- src/runtime/os_openbsd.go | 3 +- src/runtime/os_openbsd_libc.go | 3 +- src/runtime/sys_openbsd.go | 15 ++++++---- src/runtime/sys_openbsd1.go | 13 ++++---- src/runtime/sys_openbsd2.go | 53 +++++++++++++++++---------------- src/runtime/sys_openbsd3.go | 25 +++++++++------- src/runtime/sys_openbsd_amd64.s | 2 +- 7 files changed, 64 insertions(+), 50 deletions(-) diff --git a/src/runtime/os_openbsd.go b/src/runtime/os_openbsd.go index 6259b96c22..35995e7035 100644 --- a/src/runtime/os_openbsd.go +++ b/src/runtime/os_openbsd.go @@ -5,6 +5,7 @@ package runtime import ( + "internal/abi" "runtime/internal/atomic" "unsafe" ) @@ -192,7 +193,7 @@ func setsig(i uint32, fn uintptr) { sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART sa.sa_mask = uint32(sigset_all) if fn == funcPC(sighandler) { - fn = funcPC(sigtramp) + fn = abi.FuncPCABI0(sigtramp) } sa.sa_sigaction = fn sigaction(i, &sa, nil) diff --git a/src/runtime/os_openbsd_libc.go b/src/runtime/os_openbsd_libc.go index 0a342e5533..981e49827f 100644 --- a/src/runtime/os_openbsd_libc.go +++ b/src/runtime/os_openbsd_libc.go @@ -8,6 +8,7 @@ package runtime import ( + "internal/abi" "unsafe" ) @@ -48,7 +49,7 @@ func newosproc(mp *m) { // setup and then calls mstart. var oset sigset sigprocmask(_SIG_SETMASK, &sigset_all, &oset) - err := pthread_create(&attr, funcPC(mstart_stub), unsafe.Pointer(mp)) + err := pthread_create(&attr, abi.FuncPCABI0(mstart_stub), unsafe.Pointer(mp)) sigprocmask(_SIG_SETMASK, &oset, nil) if err != 0 { write(2, unsafe.Pointer(&failThreadCreate[0]), int32(len(failThreadCreate))) diff --git a/src/runtime/sys_openbsd.go b/src/runtime/sys_openbsd.go index ab3149558b..15888619b1 100644 --- a/src/runtime/sys_openbsd.go +++ b/src/runtime/sys_openbsd.go @@ -7,7 +7,10 @@ package runtime -import "unsafe" +import ( + "internal/abi" + "unsafe" +) // The *_trampoline functions convert from the Go calling convention to the C calling convention // and then call the underlying libc function. These are defined in sys_openbsd_$ARCH.s. @@ -15,35 +18,35 @@ import "unsafe" //go:nosplit //go:cgo_unsafe_args func pthread_attr_init(attr *pthreadattr) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_attr_init_trampoline)), unsafe.Pointer(&attr)) + return libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_attr_init_trampoline)), unsafe.Pointer(&attr)) } func pthread_attr_init_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_attr_destroy(attr *pthreadattr) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_attr_destroy_trampoline)), unsafe.Pointer(&attr)) + return libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_attr_destroy_trampoline)), unsafe.Pointer(&attr)) } func pthread_attr_destroy_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_attr_getstacksize(attr *pthreadattr, size *uintptr) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_attr_getstacksize_trampoline)), unsafe.Pointer(&attr)) + return libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_attr_getstacksize_trampoline)), unsafe.Pointer(&attr)) } func pthread_attr_getstacksize_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_attr_setdetachstate(attr *pthreadattr, state int) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_attr_setdetachstate_trampoline)), unsafe.Pointer(&attr)) + return libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_attr_setdetachstate_trampoline)), unsafe.Pointer(&attr)) } func pthread_attr_setdetachstate_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_create(attr *pthreadattr, start uintptr, arg unsafe.Pointer) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_create_trampoline)), unsafe.Pointer(&attr)) + return libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_create_trampoline)), unsafe.Pointer(&attr)) } func pthread_create_trampoline() diff --git a/src/runtime/sys_openbsd1.go b/src/runtime/sys_openbsd1.go index cb5d35879c..b4e9f54538 100644 --- a/src/runtime/sys_openbsd1.go +++ b/src/runtime/sys_openbsd1.go @@ -7,31 +7,34 @@ package runtime -import "unsafe" +import ( + "internal/abi" + "unsafe" +) //go:nosplit //go:cgo_unsafe_args func thrsleep(ident uintptr, clock_id int32, tsp *timespec, lock uintptr, abort *uint32) int32 { - return libcCall(unsafe.Pointer(funcPC(thrsleep_trampoline)), unsafe.Pointer(&ident)) + return libcCall(unsafe.Pointer(abi.FuncPCABI0(thrsleep_trampoline)), unsafe.Pointer(&ident)) } func thrsleep_trampoline() //go:nosplit //go:cgo_unsafe_args func thrwakeup(ident uintptr, n int32) int32 { - return libcCall(unsafe.Pointer(funcPC(thrwakeup_trampoline)), unsafe.Pointer(&ident)) + return libcCall(unsafe.Pointer(abi.FuncPCABI0(thrwakeup_trampoline)), unsafe.Pointer(&ident)) } func thrwakeup_trampoline() //go:nosplit func osyield() { - libcCall(unsafe.Pointer(funcPC(sched_yield_trampoline)), unsafe.Pointer(nil)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(sched_yield_trampoline)), unsafe.Pointer(nil)) } func sched_yield_trampoline() //go:nosplit func osyield_no_g() { - asmcgocall_no_g(unsafe.Pointer(funcPC(sched_yield_trampoline)), unsafe.Pointer(nil)) + asmcgocall_no_g(unsafe.Pointer(abi.FuncPCABI0(sched_yield_trampoline)), unsafe.Pointer(nil)) } //go:cgo_import_dynamic libc_thrsleep __thrsleep "libc.so" diff --git a/src/runtime/sys_openbsd2.go b/src/runtime/sys_openbsd2.go index cd1a4e879f..190ee4716a 100644 --- a/src/runtime/sys_openbsd2.go +++ b/src/runtime/sys_openbsd2.go @@ -7,21 +7,24 @@ package runtime -import "unsafe" +import ( + "internal/abi" + "unsafe" +) // This is exported via linkname to assembly in runtime/cgo. //go:linkname exit //go:nosplit //go:cgo_unsafe_args func exit(code int32) { - libcCall(unsafe.Pointer(funcPC(exit_trampoline)), unsafe.Pointer(&code)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(exit_trampoline)), unsafe.Pointer(&code)) } func exit_trampoline() //go:nosplit //go:cgo_unsafe_args func getthrid() (tid int32) { - libcCall(unsafe.Pointer(funcPC(getthrid_trampoline)), unsafe.Pointer(&tid)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(getthrid_trampoline)), unsafe.Pointer(&tid)) return } func getthrid_trampoline() @@ -29,14 +32,14 @@ func getthrid_trampoline() //go:nosplit //go:cgo_unsafe_args func raiseproc(sig uint32) { - libcCall(unsafe.Pointer(funcPC(raiseproc_trampoline)), unsafe.Pointer(&sig)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(raiseproc_trampoline)), unsafe.Pointer(&sig)) } func raiseproc_trampoline() //go:nosplit //go:cgo_unsafe_args func thrkill(tid int32, sig int) { - libcCall(unsafe.Pointer(funcPC(thrkill_trampoline)), unsafe.Pointer(&tid)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(thrkill_trampoline)), unsafe.Pointer(&tid)) } func thrkill_trampoline() @@ -53,7 +56,7 @@ func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) (un ret1 unsafe.Pointer ret2 int }{addr, n, prot, flags, fd, off, nil, 0} - libcCall(unsafe.Pointer(funcPC(mmap_trampoline)), unsafe.Pointer(&args)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(mmap_trampoline)), unsafe.Pointer(&args)) return args.ret1, args.ret2 } func mmap_trampoline() @@ -61,42 +64,42 @@ func mmap_trampoline() //go:nosplit //go:cgo_unsafe_args func munmap(addr unsafe.Pointer, n uintptr) { - libcCall(unsafe.Pointer(funcPC(munmap_trampoline)), unsafe.Pointer(&addr)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(munmap_trampoline)), unsafe.Pointer(&addr)) } func munmap_trampoline() //go:nosplit //go:cgo_unsafe_args func madvise(addr unsafe.Pointer, n uintptr, flags int32) { - libcCall(unsafe.Pointer(funcPC(madvise_trampoline)), unsafe.Pointer(&addr)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(madvise_trampoline)), unsafe.Pointer(&addr)) } func madvise_trampoline() //go:nosplit //go:cgo_unsafe_args func open(name *byte, mode, perm int32) (ret int32) { - return libcCall(unsafe.Pointer(funcPC(open_trampoline)), unsafe.Pointer(&name)) + return libcCall(unsafe.Pointer(abi.FuncPCABI0(open_trampoline)), unsafe.Pointer(&name)) } func open_trampoline() //go:nosplit //go:cgo_unsafe_args func closefd(fd int32) int32 { - return libcCall(unsafe.Pointer(funcPC(close_trampoline)), unsafe.Pointer(&fd)) + return libcCall(unsafe.Pointer(abi.FuncPCABI0(close_trampoline)), unsafe.Pointer(&fd)) } func close_trampoline() //go:nosplit //go:cgo_unsafe_args func read(fd int32, p unsafe.Pointer, n int32) int32 { - return libcCall(unsafe.Pointer(funcPC(read_trampoline)), unsafe.Pointer(&fd)) + return libcCall(unsafe.Pointer(abi.FuncPCABI0(read_trampoline)), unsafe.Pointer(&fd)) } func read_trampoline() //go:nosplit //go:cgo_unsafe_args func write1(fd uintptr, p unsafe.Pointer, n int32) int32 { - return libcCall(unsafe.Pointer(funcPC(write_trampoline)), unsafe.Pointer(&fd)) + return libcCall(unsafe.Pointer(abi.FuncPCABI0(write_trampoline)), unsafe.Pointer(&fd)) } func write_trampoline() @@ -110,7 +113,7 @@ func pipe2(flags int32) (r, w int32, errno int32) { p unsafe.Pointer flags int32 }{noescape(unsafe.Pointer(&p)), flags} - errno = libcCall(unsafe.Pointer(funcPC(pipe2_trampoline)), unsafe.Pointer(&args)) + errno = libcCall(unsafe.Pointer(abi.FuncPCABI0(pipe2_trampoline)), unsafe.Pointer(&args)) return p[0], p[1], errno } func pipe2_trampoline() @@ -118,34 +121,34 @@ func pipe2_trampoline() //go:nosplit //go:cgo_unsafe_args func setitimer(mode int32, new, old *itimerval) { - libcCall(unsafe.Pointer(funcPC(setitimer_trampoline)), unsafe.Pointer(&mode)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(setitimer_trampoline)), unsafe.Pointer(&mode)) } func setitimer_trampoline() //go:nosplit //go:cgo_unsafe_args func usleep(usec uint32) { - libcCall(unsafe.Pointer(funcPC(usleep_trampoline)), unsafe.Pointer(&usec)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(usleep_trampoline)), unsafe.Pointer(&usec)) } func usleep_trampoline() //go:nosplit //go:cgo_unsafe_args func usleep_no_g(usec uint32) { - asmcgocall_no_g(unsafe.Pointer(funcPC(usleep_trampoline)), unsafe.Pointer(&usec)) + asmcgocall_no_g(unsafe.Pointer(abi.FuncPCABI0(usleep_trampoline)), unsafe.Pointer(&usec)) } //go:nosplit //go:cgo_unsafe_args func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32 { - return libcCall(unsafe.Pointer(funcPC(sysctl_trampoline)), unsafe.Pointer(&mib)) + return libcCall(unsafe.Pointer(abi.FuncPCABI0(sysctl_trampoline)), unsafe.Pointer(&mib)) } func sysctl_trampoline() //go:nosplit //go:cgo_unsafe_args func fcntl(fd, cmd, arg int32) int32 { - return libcCall(unsafe.Pointer(funcPC(fcntl_trampoline)), unsafe.Pointer(&fd)) + return libcCall(unsafe.Pointer(abi.FuncPCABI0(fcntl_trampoline)), unsafe.Pointer(&fd)) } func fcntl_trampoline() @@ -156,7 +159,7 @@ func nanotime1() int64 { clock_id int32 tp unsafe.Pointer }{_CLOCK_MONOTONIC, unsafe.Pointer(&ts)} - libcCall(unsafe.Pointer(funcPC(clock_gettime_trampoline)), unsafe.Pointer(&args)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(clock_gettime_trampoline)), unsafe.Pointer(&args)) return ts.tv_sec*1e9 + int64(ts.tv_nsec) } func clock_gettime_trampoline() @@ -168,42 +171,42 @@ func walltime() (int64, int32) { clock_id int32 tp unsafe.Pointer }{_CLOCK_REALTIME, unsafe.Pointer(&ts)} - libcCall(unsafe.Pointer(funcPC(clock_gettime_trampoline)), unsafe.Pointer(&args)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(clock_gettime_trampoline)), unsafe.Pointer(&args)) return ts.tv_sec, int32(ts.tv_nsec) } //go:nosplit //go:cgo_unsafe_args func kqueue() int32 { - return libcCall(unsafe.Pointer(funcPC(kqueue_trampoline)), nil) + return libcCall(unsafe.Pointer(abi.FuncPCABI0(kqueue_trampoline)), nil) } func kqueue_trampoline() //go:nosplit //go:cgo_unsafe_args func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32 { - return libcCall(unsafe.Pointer(funcPC(kevent_trampoline)), unsafe.Pointer(&kq)) + return libcCall(unsafe.Pointer(abi.FuncPCABI0(kevent_trampoline)), unsafe.Pointer(&kq)) } func kevent_trampoline() //go:nosplit //go:cgo_unsafe_args func sigaction(sig uint32, new *sigactiont, old *sigactiont) { - libcCall(unsafe.Pointer(funcPC(sigaction_trampoline)), unsafe.Pointer(&sig)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(sigaction_trampoline)), unsafe.Pointer(&sig)) } func sigaction_trampoline() //go:nosplit //go:cgo_unsafe_args func sigprocmask(how uint32, new *sigset, old *sigset) { - libcCall(unsafe.Pointer(funcPC(sigprocmask_trampoline)), unsafe.Pointer(&how)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(sigprocmask_trampoline)), unsafe.Pointer(&how)) } func sigprocmask_trampoline() //go:nosplit //go:cgo_unsafe_args func sigaltstack(new *stackt, old *stackt) { - libcCall(unsafe.Pointer(funcPC(sigaltstack_trampoline)), unsafe.Pointer(&new)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(sigaltstack_trampoline)), unsafe.Pointer(&new)) } func sigaltstack_trampoline() diff --git a/src/runtime/sys_openbsd3.go b/src/runtime/sys_openbsd3.go index 8d77a4b216..a917ebde61 100644 --- a/src/runtime/sys_openbsd3.go +++ b/src/runtime/sys_openbsd3.go @@ -7,7 +7,10 @@ package runtime -import "unsafe" +import ( + "internal/abi" + "unsafe" +) // The X versions of syscall expect the libc call to return a 64-bit result. // Otherwise (the non-X version) expects a 32-bit result. @@ -20,7 +23,7 @@ import "unsafe" //go:cgo_unsafe_args func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) { entersyscall() - libcCall(unsafe.Pointer(funcPC(syscall)), unsafe.Pointer(&fn)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall)), unsafe.Pointer(&fn)) exitsyscall() return } @@ -31,7 +34,7 @@ func syscall() //go:cgo_unsafe_args func syscall_syscallX(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) { entersyscall() - libcCall(unsafe.Pointer(funcPC(syscallX)), unsafe.Pointer(&fn)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(syscallX)), unsafe.Pointer(&fn)) exitsyscall() return } @@ -42,7 +45,7 @@ func syscallX() //go:cgo_unsafe_args func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) { entersyscall() - libcCall(unsafe.Pointer(funcPC(syscall6)), unsafe.Pointer(&fn)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6)), unsafe.Pointer(&fn)) exitsyscall() return } @@ -53,7 +56,7 @@ func syscall6() //go:cgo_unsafe_args func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) { entersyscall() - libcCall(unsafe.Pointer(funcPC(syscall6X)), unsafe.Pointer(&fn)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6X)), unsafe.Pointer(&fn)) exitsyscall() return } @@ -64,7 +67,7 @@ func syscall6X() //go:cgo_unsafe_args func syscall_syscall10(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 uintptr) (r1, r2, err uintptr) { entersyscall() - libcCall(unsafe.Pointer(funcPC(syscall10)), unsafe.Pointer(&fn)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall10)), unsafe.Pointer(&fn)) exitsyscall() return } @@ -75,7 +78,7 @@ func syscall10() //go:cgo_unsafe_args func syscall_syscall10X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 uintptr) (r1, r2, err uintptr) { entersyscall() - libcCall(unsafe.Pointer(funcPC(syscall10X)), unsafe.Pointer(&fn)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall10X)), unsafe.Pointer(&fn)) exitsyscall() return } @@ -85,7 +88,7 @@ func syscall10X() //go:nosplit //go:cgo_unsafe_args func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) { - libcCall(unsafe.Pointer(funcPC(syscall)), unsafe.Pointer(&fn)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall)), unsafe.Pointer(&fn)) return } @@ -93,7 +96,7 @@ func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) { //go:nosplit //go:cgo_unsafe_args func syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) { - libcCall(unsafe.Pointer(funcPC(syscall6)), unsafe.Pointer(&fn)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6)), unsafe.Pointer(&fn)) return } @@ -101,7 +104,7 @@ func syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintpt //go:nosplit //go:cgo_unsafe_args func syscall_rawSyscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) { - libcCall(unsafe.Pointer(funcPC(syscall6X)), unsafe.Pointer(&fn)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6X)), unsafe.Pointer(&fn)) return } @@ -109,6 +112,6 @@ func syscall_rawSyscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintp //go:nosplit //go:cgo_unsafe_args func syscall_rawSyscall10X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 uintptr) (r1, r2, err uintptr) { - libcCall(unsafe.Pointer(funcPC(syscall10X)), unsafe.Pointer(&fn)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall10X)), unsafe.Pointer(&fn)) return } diff --git a/src/runtime/sys_openbsd_amd64.s b/src/runtime/sys_openbsd_amd64.s index 522e98cf4f..fc89ee6cbb 100644 --- a/src/runtime/sys_openbsd_amd64.s +++ b/src/runtime/sys_openbsd_amd64.s @@ -58,7 +58,7 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32 RET // Called using C ABI. -TEXT runtime·sigtramp(SB),NOSPLIT,$0 +TEXT runtime·sigtramp(SB),NOSPLIT,$0 // Transition from C ABI to Go ABI. PUSH_REGS_HOST_TO_ABI0() -- GitLab From f3fc8b5779314bae827b868deb916c7a8e748907 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 17 May 2021 11:40:02 -0700 Subject: [PATCH 0082/2500] [dev.typeparams] cmd/compile: simplify type alias handling for export Currently the exporter uses types.IsDotAlias(n.Sym()) to recognize that n is a type alias, but IsDotAlias is actually meant for recognizing aliases introduced by dot imports. Translated to go/types, the current logic amounts recognizing type aliases as if by: var n *types.TypeName typ, ok := n.Pkg().Scope().Lookup(n.Name()).Type().(*types.Named) isAlias := !ok || typ.Obj().Pkg() != n.Pkg() || typ.Obj().Name() != n.Name() But we can instead just check n.Alias() (eqv. n.IsAlias() in go/types). In addition to being much simpler, this is also actually correct for recognizing function-scoped type declarations (though we don't currently support those anyway, nor would they go through this exact code path). To avoid possible future misuse of IsDotAlias, this CL also inlines its trivial definition into its only call site. Passes toolstash -cmp, also w/ -gcflags=all=-G=3. Change-Id: I7c6283f4b58d5311aa683f8229bbf62f8bab2ff9 Reviewed-on: https://go-review.googlesource.com/c/go/+/320613 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Matthew Dempsky Trust: Dan Scales Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/decl.go | 8 +------- src/cmd/compile/internal/noder/import.go | 2 +- src/cmd/compile/internal/noder/object.go | 1 + src/cmd/compile/internal/typecheck/iexport.go | 2 +- src/cmd/compile/internal/typecheck/typecheck.go | 5 ----- src/cmd/compile/internal/types/pkg.go | 4 ---- 6 files changed, 4 insertions(+), 18 deletions(-) diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go index 4ca2eb4740..3e55437afa 100644 --- a/src/cmd/compile/internal/noder/decl.go +++ b/src/cmd/compile/internal/noder/decl.go @@ -104,13 +104,7 @@ func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) { if decl.Alias { name, _ := g.def(decl.Name) g.pragmaFlags(decl.Pragma, 0) - - // TODO(mdempsky): This matches how typecheckdef marks aliases for - // export, but this won't generalize to exporting function-scoped - // type aliases. We should maybe just use n.Alias() instead. - if ir.CurFunc == nil { - name.Sym().Def = ir.TypeNode(name.Type()) - } + assert(name.Alias()) // should be set by irgen.obj out.Append(ir.NewDecl(g.pos(decl), ir.ODCLTYPE, name)) return diff --git a/src/cmd/compile/internal/noder/import.go b/src/cmd/compile/internal/noder/import.go index 701e9001c8..c4a57806eb 100644 --- a/src/cmd/compile/internal/noder/import.go +++ b/src/cmd/compile/internal/noder/import.go @@ -431,7 +431,7 @@ func clearImports() { s.Def = nil continue } - if types.IsDotAlias(s) { + if s.Def != nil && s.Def.Sym() != s { // throw away top-level name left over // from previous import . "x" // We'll report errors after type checking in CheckDotImports. diff --git a/src/cmd/compile/internal/noder/object.go b/src/cmd/compile/internal/noder/object.go index 82cce1ace0..7af2fe6715 100644 --- a/src/cmd/compile/internal/noder/object.go +++ b/src/cmd/compile/internal/noder/object.go @@ -101,6 +101,7 @@ func (g *irgen) obj(obj types2.Object) *ir.Name { case *types2.TypeName: if obj.IsAlias() { name = g.objCommon(pos, ir.OTYPE, g.sym(obj), class, g.typ(obj.Type())) + name.SetAlias(true) } else { name = ir.NewDeclNameAt(pos, ir.OTYPE, g.sym(obj)) g.objFinish(name, class, types.NewNamed(name)) diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 64d68ef625..3538c4d5a6 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -479,7 +479,7 @@ func (p *iexporter) doDecl(n *ir.Name) { w.constExt(n) case ir.OTYPE: - if types.IsDotAlias(n.Sym()) { + if n.Alias() { // Alias. w.tag('A') w.pos(n.Pos()) diff --git a/src/cmd/compile/internal/typecheck/typecheck.go b/src/cmd/compile/internal/typecheck/typecheck.go index 95f7b50259..9868c2d9a9 100644 --- a/src/cmd/compile/internal/typecheck/typecheck.go +++ b/src/cmd/compile/internal/typecheck/typecheck.go @@ -1889,11 +1889,6 @@ func typecheckdef(n *ir.Name) { n.SetDiag(true) goto ret } - // For package-level type aliases, set n.Sym.Def so we can identify - // it as a type alias during export. See also #31959. - if n.Curfn == nil { - n.Sym().Def = n.Ntype - } } break } diff --git a/src/cmd/compile/internal/types/pkg.go b/src/cmd/compile/internal/types/pkg.go index a6d2e2007b..f63a357f0d 100644 --- a/src/cmd/compile/internal/types/pkg.go +++ b/src/cmd/compile/internal/types/pkg.go @@ -137,7 +137,3 @@ func CleanroomDo(f func()) { f() pkgMap = saved } - -func IsDotAlias(sym *Sym) bool { - return sym.Def != nil && sym.Def.Sym() != sym -} -- GitLab From b9417ffd2797753219aa404abcb848e7c7c8bfd8 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Sat, 15 May 2021 18:46:05 -0700 Subject: [PATCH 0083/2500] [dev.fuzz] internal/fuzz: move coverage capture closer to function When instrumented packages intersect with the packages used by the testing or internal/fuzz packages the coverage counters become noisier, as counters will be triggered by non-fuzzed harness code. Ideally counters would be deterministic, as there are many advanced fuzzing strategies that require mutating the input while maintaining static coverage. The simplest way to mitigate this noise is to capture the coverage counters as closely as possible to the invocation of the fuzz target in the testing package. In order to do this add a new function which captures the current values of the counters, SnapshotCoverage. This function copies the current counters into a static buffer, coverageSnapshot, which workerServer.fuzz can then inspect when it comes time to check if new coverage has been found. This method is not foolproof. As the fuzz target is called in a goroutine, harness code can still cause counters to be incremented while the target is being executed. Despite this we do see significant reduction in churn via this approach. For example, running a basic target that causes strconv to be instrumented for 500,000 iterations causes ~800 unique sets of coverage counters, whereas by capturing the counters closer to the target we get ~40 unique sets. It may be possible to make counters completely deterministic, but likely this would require rewriting testing/F.Fuzz to not use tRunner in a goroutine, and instead use it in a blocking manner (which I couldn't figure out an obvious way to do), or by doing something even more complex. Change-Id: I95c2f3b1d7089c3e6885fc7628a0d3a8ac1a99cf Reviewed-on: https://go-review.googlesource.com/c/go/+/320329 Trust: Roland Shoemaker Trust: Katie Hockman Reviewed-by: Jay Conrod Reviewed-by: Katie Hockman --- src/internal/fuzz/coverage.go | 26 ++++++++++++++------------ src/internal/fuzz/fuzz.go | 6 +++--- src/internal/fuzz/worker.go | 16 +++++----------- src/testing/fuzz.go | 16 ++++++++++++---- src/testing/internal/testdeps/deps.go | 8 ++++++++ src/testing/testing.go | 4 ++++ 6 files changed, 46 insertions(+), 30 deletions(-) diff --git a/src/internal/fuzz/coverage.go b/src/internal/fuzz/coverage.go index e039d68d9a..316aa14783 100644 --- a/src/internal/fuzz/coverage.go +++ b/src/internal/fuzz/coverage.go @@ -26,25 +26,27 @@ func coverage() []byte { return res } -// coverageCopy returns a copy of the current bytes provided by coverage(). -// TODO(jayconrod,katiehockman): consider using a shared buffer instead, to -// make fewer costly allocations. -func coverageCopy() []byte { - cov := coverage() - ret := make([]byte, len(cov)) - copy(ret, cov) - return ret -} - -// resetCovereage sets all of the counters for each edge of the instrumented +// ResetCovereage sets all of the counters for each edge of the instrumented // source code to 0. -func resetCoverage() { +func ResetCoverage() { cov := coverage() for i := range cov { cov[i] = 0 } } +// SnapshotCoverage copies the current counter values into coverageSnapshot, +// preserving them for later inspection. +func SnapshotCoverage() { + cov := coverage() + if coverageSnapshot == nil { + coverageSnapshot = make([]byte, len(cov)) + } + copy(coverageSnapshot, cov) +} + +var coverageSnapshot []byte + // _counters and _ecounters mark the start and end, respectively, of where // the 8-bit coverage counters reside in memory. They're known to cmd/link, // which specially assigns their addresses for this purpose. diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index b4145f58dc..3bb2da872c 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -439,13 +439,13 @@ func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { covOnlyInputs: covOnlyInputs, } - cov := coverageCopy() - if len(cov) == 0 { + covSize := len(coverage()) + if covSize == 0 { fmt.Fprintf(c.opts.Log, "warning: coverage-guided fuzzing is not supported on this platform\n") c.covOnlyInputs = 0 } else { // Set c.coverageData to a clean []byte full of zeros. - c.coverageData = make([]byte, len(cov)) + c.coverageData = make([]byte, covSize) } if c.covOnlyInputs > 0 { diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 61d3226b30..15b1f89daa 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -615,15 +615,12 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo } if args.CoverageOnly { - // Reset the coverage each time before running the fuzzFn. - resetCoverage() ws.fuzzFn(CorpusEntry{Values: vals}) - resp.CoverageData = coverageCopy() + resp.CoverageData = coverageSnapshot return resp } - cov := coverage() - if len(cov) != len(ws.coverageData) { + if cov := coverage(); len(cov) != len(ws.coverageData) { panic(fmt.Sprintf("num edges changed at runtime: %d, expected %d", len(cov), len(ws.coverageData))) } for { @@ -635,7 +632,6 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo resp.Count++ ws.m.mutate(vals, cap(mem.valueRef())) writeToMem(vals, mem) - resetCoverage() if err := ws.fuzzFn(CorpusEntry{Values: vals}); err != nil { // TODO(jayconrod,katiehockman): consider making the maximum // minimization time customizable with a go command flag. @@ -651,12 +647,10 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo } return resp } - for i := range cov { - if ws.coverageData[i] == 0 && cov[i] > ws.coverageData[i] { + for i := range coverageSnapshot { + if ws.coverageData[i] == 0 && coverageSnapshot[i] > ws.coverageData[i] { // TODO(jayconrod,katie): minimize this. - // This run hit a new edge. Only allocate a new slice as a - // copy of cov if we are returning, since it is expensive. - resp.CoverageData = coverageCopy() + resp.CoverageData = coverageSnapshot return resp } } diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 7afd24d258..d81796b4fc 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -338,7 +338,9 @@ func (f *F) Fuzz(ff interface{}) { for _, v := range e.Values { args = append(args, reflect.ValueOf(v)) } + f.fuzzContext.resetCoverage() fn.Call(args) + f.fuzzContext.snapshotCoverage() }) <-t.signal f.inFuzzFn = false @@ -452,6 +454,8 @@ type fuzzContext struct { coordinateFuzzing func(time.Duration, int64, int, []corpusEntry, []reflect.Type, string, string) error runFuzzWorker func(func(corpusEntry) error) error readCorpus func(string, []reflect.Type) ([]corpusEntry, error) + resetCoverage func() + snapshotCoverage func() } // runFuzzTargets runs the fuzz targets matching the pattern for -run. This will @@ -465,8 +469,10 @@ func runFuzzTargets(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran, ok bo m := newMatcher(deps.MatchString, *match, "-test.run") tctx := newTestContext(*parallel, m) fctx := &fuzzContext{ - importPath: deps.ImportPath, - readCorpus: deps.ReadCorpus, + importPath: deps.ImportPath, + readCorpus: deps.ReadCorpus, + resetCoverage: deps.ResetCoverage, + snapshotCoverage: deps.SnapshotCoverage, } root := common{w: os.Stdout} // gather output in one place if Verbose() { @@ -519,8 +525,10 @@ func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran, ok bool) m := newMatcher(deps.MatchString, *matchFuzz, "-test.fuzz") tctx := newTestContext(1, m) fctx := &fuzzContext{ - importPath: deps.ImportPath, - readCorpus: deps.ReadCorpus, + importPath: deps.ImportPath, + readCorpus: deps.ReadCorpus, + resetCoverage: deps.ResetCoverage, + snapshotCoverage: deps.SnapshotCoverage, } if *isFuzzWorker { fctx.runFuzzWorker = deps.RunFuzzWorker diff --git a/src/testing/internal/testdeps/deps.go b/src/testing/internal/testdeps/deps.go index b9c110100f..24ef7c4d62 100644 --- a/src/testing/internal/testdeps/deps.go +++ b/src/testing/internal/testdeps/deps.go @@ -174,3 +174,11 @@ func (TestDeps) RunFuzzWorker(fn func(fuzz.CorpusEntry) error) error { func (TestDeps) ReadCorpus(dir string, types []reflect.Type) ([]fuzz.CorpusEntry, error) { return fuzz.ReadCorpus(dir, types) } + +func (TestDeps) ResetCoverage() { + fuzz.ResetCoverage() +} + +func (TestDeps) SnapshotCoverage() { + fuzz.SnapshotCoverage() +} diff --git a/src/testing/testing.go b/src/testing/testing.go index 1877ce3ba4..63dcc62597 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1397,6 +1397,8 @@ func (f matchStringOnly) RunFuzzWorker(func(corpusEntry) error) error { return e func (f matchStringOnly) ReadCorpus(string, []reflect.Type) ([]corpusEntry, error) { return nil, errMain } +func (f matchStringOnly) ResetCoverage() {} +func (f matchStringOnly) SnapshotCoverage() {} // Main is an internal function, part of the implementation of the "go test" command. // It was exported because it is cross-package and predates "internal" packages. @@ -1442,6 +1444,8 @@ type testDeps interface { CoordinateFuzzing(time.Duration, int64, int, []corpusEntry, []reflect.Type, string, string) error RunFuzzWorker(func(corpusEntry) error) error ReadCorpus(string, []reflect.Type) ([]corpusEntry, error) + ResetCoverage() + SnapshotCoverage() } // MainStart is meant for use by tests generated by 'go test'. -- GitLab From 81b22480cfd66dc5d95f8cadfadc4ac2c16074e6 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 18 May 2021 17:37:54 -0700 Subject: [PATCH 0084/2500] [dev.typeparams] cmd/compile/internal/syntax: accept embedded type literals The parser accepted embedded elements but the first term of an element had to be a ~-term or a type name. This CL fixes that. Change-Id: I013b6cdc5963fb228867ca6597f9139db2be7ec5 Reviewed-on: https://go-review.googlesource.com/c/go/+/321109 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/syntax/parser.go | 12 +++++ .../internal/syntax/testdata/interface.go2 | 46 ++++++++++++++++++- 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index e7b8840b33..0e711a0113 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -1443,6 +1443,18 @@ func (p *parser) interfaceType() *InterfaceType { } return false } + + default: + if p.mode&AllowGenerics != 0 { + pos := p.pos() + if t := p.typeOrNil(); t != nil { + f := new(Field) + f.pos = pos + f.Type = t + typ.MethodList = append(typ.MethodList, p.embeddedElem(f)) + return false + } + } } if p.mode&AllowGenerics != 0 { diff --git a/src/cmd/compile/internal/syntax/testdata/interface.go2 b/src/cmd/compile/internal/syntax/testdata/interface.go2 index a817327a43..b399d75148 100644 --- a/src/cmd/compile/internal/syntax/testdata/interface.go2 +++ b/src/cmd/compile/internal/syntax/testdata/interface.go2 @@ -25,7 +25,6 @@ type _ interface { ~int | ~string } - type _ interface { m() ~int @@ -34,3 +33,48 @@ type _ interface { ~int | ~string type bool, int, float64 } + +type _ interface { + int + []byte + [10]int + struct{} + *int + func() + interface{} + map[string]int + chan T + chan<- T + <-chan T + T[int] +} + +type _ interface { + int | string + []byte | string + [10]int | string + struct{} | string + *int | string + func() | string + interface{} | string + map[string]int | string + chan T | string + chan<- T | string + <-chan T | string + T[int] | string +} + +type _ interface { + ~int | string + ~[]byte | string + ~[10]int | string + ~struct{} | string + ~*int | string + ~func() | string + ~interface{} | string + ~map[string]int | string + ~chan T | string + ~chan<- T | string + ~<-chan T | string + ~T[int] | string +} -- GitLab From c81562d99f8945a38da9a302731e6ac08f72825f Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 17 May 2021 11:41:20 -0700 Subject: [PATCH 0085/2500] [dev.typeparams] test: update regress tests for types2 Followup to previous commit that extended test/run.go to run more tests with -G=3. This CL updates a handful of easy test cases for types2 compatibility. Change-Id: I58a6f9ce6f9172d61dc25411536ee489ccb03ae0 Reviewed-on: https://go-review.googlesource.com/c/go/+/320610 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Matthew Dempsky Trust: Dan Scales Reviewed-by: Dan Scales Reviewed-by: Robert Griesemer --- test/fixedbugs/bug248.dir/bug2.go | 4 ++-- test/fixedbugs/bug345.dir/main.go | 4 ++-- test/fixedbugs/bug460.dir/b.go | 10 +++++----- test/fixedbugs/issue44432.go | 4 ++-- test/fixedbugs/issue4909b.go | 2 +- test/run.go | 5 ----- 6 files changed, 12 insertions(+), 17 deletions(-) diff --git a/test/fixedbugs/bug248.dir/bug2.go b/test/fixedbugs/bug248.dir/bug2.go index c0fdecfdb7..92a7974679 100644 --- a/test/fixedbugs/bug248.dir/bug2.go +++ b/test/fixedbugs/bug248.dir/bug2.go @@ -50,8 +50,8 @@ var p0i2 p1.I = t0(0) // ERROR "does not implement|incompatible" func foobar() { // check that cannot assign one to the other, // but can convert. - v0 = v1 // ERROR "assign" - v1 = v0 // ERROR "assign" + v0 = v1 // ERROR "assign|cannot use" + v1 = v0 // ERROR "assign|cannot use" v0 = p0.T(v1) v1 = p1.T(v0) diff --git a/test/fixedbugs/bug345.dir/main.go b/test/fixedbugs/bug345.dir/main.go index b77a2fad5f..a53d3e8586 100644 --- a/test/fixedbugs/bug345.dir/main.go +++ b/test/fixedbugs/bug345.dir/main.go @@ -23,7 +23,7 @@ func main() { // main.go:27: cannot use &x (type *"io".SectionReader) as type *"/Users/rsc/g/go/test/fixedbugs/bug345.dir/io".SectionReader in function argument var w io.Writer - bufio.NewWriter(w) // ERROR "[\w.]+[^.]/io|has incompatible type" + bufio.NewWriter(w) // ERROR "[\w.]+[^.]/io|has incompatible type|cannot use" var x goio.SectionReader - io.SR(&x) // ERROR "[\w.]+[^.]/io|has incompatible type" + io.SR(&x) // ERROR "[\w.]+[^.]/io|has incompatible type|cannot use" } diff --git a/test/fixedbugs/bug460.dir/b.go b/test/fixedbugs/bug460.dir/b.go index ef646946cf..5d388fc413 100644 --- a/test/fixedbugs/bug460.dir/b.go +++ b/test/fixedbugs/bug460.dir/b.go @@ -9,9 +9,9 @@ import "./a" var x a.Foo func main() { - x.int = 20 // ERROR "unexported field" - x.int8 = 20 // ERROR "unexported field" - x.error = nil // ERROR "unexported field" - x.rune = 'a' // ERROR "unexported field" - x.byte = 20 // ERROR "unexported field" + x.int = 20 // ERROR "unexported field|undefined" + x.int8 = 20 // ERROR "unexported field|undefined" + x.error = nil // ERROR "unexported field|undefined" + x.rune = 'a' // ERROR "unexported field|undefined" + x.byte = 20 // ERROR "unexported field|undefined" } diff --git a/test/fixedbugs/issue44432.go b/test/fixedbugs/issue44432.go index c5fb67e0d7..eec53f3000 100644 --- a/test/fixedbugs/issue44432.go +++ b/test/fixedbugs/issue44432.go @@ -8,6 +8,6 @@ package p var m = map[string]int{ "a": 1, - 1: 1, // ERROR "cannot use 1.*as type string in map key" - 2: 2, // ERROR "cannot use 2.*as type string in map key" + 1: 1, // ERROR "cannot use 1.*as.*string.*in map" + 2: 2, // ERROR "cannot use 2.*as.*string.*in map" } diff --git a/test/fixedbugs/issue4909b.go b/test/fixedbugs/issue4909b.go index 0f594e3db6..7d7922701a 100644 --- a/test/fixedbugs/issue4909b.go +++ b/test/fixedbugs/issue4909b.go @@ -73,7 +73,7 @@ func writeDot(ns ...int) { } fmt.Print(")") if isIndirect { - fmt.Print(` // ERROR "indirection"`) + fmt.Print(` // ERROR "indirection|embedded via a pointer"`) } fmt.Print("\n") } diff --git a/test/run.go b/test/run.go index fc4e89fc64..d64affb772 100644 --- a/test/run.go +++ b/test/run.go @@ -2051,16 +2051,13 @@ var excludedFiles = map[string]bool{ "fixedbugs/bug195.go": true, // types2 reports slightly different (but correct) bugs "fixedbugs/bug228.go": true, // types2 doesn't run when there are syntax errors "fixedbugs/bug231.go": true, // types2 bug? (same error reported twice) - "fixedbugs/bug248.go": true, // types2 reports different (but ok) error message "fixedbugs/bug255.go": true, // types2 reports extra errors - "fixedbugs/bug345.go": true, // types2 reports different (but ok) error message "fixedbugs/bug351.go": true, // types2 reports extra errors "fixedbugs/bug374.go": true, // types2 reports extra errors "fixedbugs/bug385_32.go": true, // types2 doesn't produce missing error "type .* too large" (32-bit specific) "fixedbugs/bug388.go": true, // types2 not run due to syntax errors "fixedbugs/bug412.go": true, // types2 produces a follow-on error "fixedbugs/bug420.go": true, // ICE in irgen - "fixedbugs/bug460.go": true, // types2 reports different (but probably ok) error message "fixedbugs/issue10700.go": true, // types2 reports ok hint, but does not match regexp "fixedbugs/issue11590.go": true, // types2 doesn't report a follow-on error (pref: types2) @@ -2095,10 +2092,8 @@ var excludedFiles = map[string]bool{ "fixedbugs/issue4232.go": true, // types2 reports (correct) extra errors "fixedbugs/issue43479.go": true, // ICE in iexport due to Syms from the wrong package "fixedbugs/issue43962.go": true, // types2 panics when importing package named "init" - "fixedbugs/issue44432.go": true, // types2 reports different (but ok) error message "fixedbugs/issue4452.go": true, // types2 reports (correct) extra errors "fixedbugs/issue4510.go": true, // types2 reports different (but ok) line numbers - "fixedbugs/issue4909b.go": true, // types2 reports different (but ok) error message "fixedbugs/issue5609.go": true, // types2 needs a better error message "fixedbugs/issue6889.go": true, // types2 can handle this without constant overflow "fixedbugs/issue7525b.go": true, // types2 reports init cycle error on different line - ok otherwise -- GitLab From fc9e64cc98edda355471f0390da4d1d1de4100a0 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 17 May 2021 10:50:41 -0700 Subject: [PATCH 0086/2500] [dev.typeparams] cmd/compile/internal/types2: fix types2 panic When reporting a "cannot import package as init" error, we can't rely on s.LocalPkgName being non-nil, as the original package's name may already be nil. Change-Id: Idec006780f12ee4398501d05a5b2ed13157f88ea Reviewed-on: https://go-review.googlesource.com/c/go/+/320490 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/resolver.go | 2 +- test/run.go | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/types2/resolver.go b/src/cmd/compile/internal/types2/resolver.go index fa30650bd4..ef49a8b48d 100644 --- a/src/cmd/compile/internal/types2/resolver.go +++ b/src/cmd/compile/internal/types2/resolver.go @@ -265,7 +265,7 @@ func (check *Checker) collectObjects() { } if name == "init" { - check.error(s.LocalPkgName, "cannot import package as init - init must be a func") + check.error(s, "cannot import package as init - init must be a func") continue } diff --git a/test/run.go b/test/run.go index d64affb772..506380a7a5 100644 --- a/test/run.go +++ b/test/run.go @@ -2091,7 +2091,6 @@ var excludedFiles = map[string]bool{ "fixedbugs/issue42058b.go": true, // types2 doesn't report "channel element type too large" "fixedbugs/issue4232.go": true, // types2 reports (correct) extra errors "fixedbugs/issue43479.go": true, // ICE in iexport due to Syms from the wrong package - "fixedbugs/issue43962.go": true, // types2 panics when importing package named "init" "fixedbugs/issue4452.go": true, // types2 reports (correct) extra errors "fixedbugs/issue4510.go": true, // types2 reports different (but ok) line numbers "fixedbugs/issue5609.go": true, // types2 needs a better error message -- GitLab From 90b6e7260553a742522830ddd38f5854657f2985 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 17 May 2021 14:25:49 -0700 Subject: [PATCH 0087/2500] [dev.typeparams] cmd/compile/internal/types2: tweak anonymous parameter position When declaring anonymous parameters, use the syntax.Field's Pos directly rather than its Type field's Pos. When the type expression is a qualified identifier (i.e., SelectorExpr), its Pos returns the position of the dot, whereas we typically declare the anonymous parameter at the starting position of the type. (We could equivalently use syntax.StartPos(field.Type), but we already have this as field.Pos().) Change-Id: If6ac9635b6e9c2b75a1989d5893a78e0b21cba88 Reviewed-on: https://go-review.googlesource.com/c/go/+/320611 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/typexpr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index e64d804c30..a1663d2aa0 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -778,7 +778,7 @@ func (check *Checker) collectParams(scope *Scope, list []*syntax.Field, type0 sy named = true } else { // anonymous parameter - par := NewParam(ftype.Pos(), check.pkg, "", typ) + par := NewParam(field.Pos(), check.pkg, "", typ) check.recordImplicit(field, par) params = append(params, par) anonymous = true -- GitLab From c92ae885d98d331ec489f6e705f2c5371e5f0e42 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 17 May 2021 10:47:04 -0700 Subject: [PATCH 0088/2500] [dev.typeparams] cmd/compile/internal/types2: better recv Var for method expressions When synthesizing the Signature to represent a method expression, keep as much of the original parameter as possible, substituting only the receiver type. Fixes #46209. Change-Id: Ic4531820ae7d203bb0ba25a985f72d219b4aa25f Reviewed-on: https://go-review.googlesource.com/c/go/+/320489 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/call.go | 10 ++++++++-- .../compile/internal/types2/testdata/check/decls0.src | 8 ++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 6d149340b2..f0f769ec70 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -576,17 +576,23 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) { check.recordSelection(e, MethodExpr, x.typ, m, index, indirect) + sig := m.typ.(*Signature) + if sig.recv == nil { + check.error(e, "illegal cycle in method declaration") + goto Error + } + // the receiver type becomes the type of the first function // argument of the method expression's function type var params []*Var - sig := m.typ.(*Signature) if sig.params != nil { params = sig.params.vars } + params = append([]*Var{NewVar(sig.recv.pos, sig.recv.pkg, sig.recv.name, x.typ)}, params...) x.mode = value x.typ = &Signature{ tparams: sig.tparams, - params: NewTuple(append([]*Var{NewVar(nopos, check.pkg, "_", x.typ)}, params...)...), + params: NewTuple(params...), results: sig.results, variadic: sig.variadic, } diff --git a/src/cmd/compile/internal/types2/testdata/check/decls0.src b/src/cmd/compile/internal/types2/testdata/check/decls0.src index e78d8867e0..80bf4ebb3d 100644 --- a/src/cmd/compile/internal/types2/testdata/check/decls0.src +++ b/src/cmd/compile/internal/types2/testdata/check/decls0.src @@ -185,10 +185,10 @@ func f2(x *f2 /* ERROR "not a type" */ ) {} func f3() (x f3 /* ERROR "not a type" */ ) { return } func f4() (x *f4 /* ERROR "not a type" */ ) { return } -func (S0) m1(x S0 /* ERROR value .* is not a type */ .m1) {} -func (S0) m2(x *S0 /* ERROR value .* is not a type */ .m2) {} -func (S0) m3() (x S0 /* ERROR value .* is not a type */ .m3) { return } -func (S0) m4() (x *S0 /* ERROR value .* is not a type */ .m4) { return } +func (S0) m1(x S0 /* ERROR illegal cycle in method declaration */ .m1) {} +func (S0) m2(x *S0 /* ERROR illegal cycle in method declaration */ .m2) {} +func (S0) m3() (x S0 /* ERROR illegal cycle in method declaration */ .m3) { return } +func (S0) m4() (x *S0 /* ERROR illegal cycle in method declaration */ .m4) { return } // interfaces may not have any blank methods type BlankI interface { -- GitLab From fb79f6955e8d13fd6c98f6bd036819d7cc6dfad6 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 17 May 2021 15:30:00 -0700 Subject: [PATCH 0089/2500] [dev.typeparams] cmd/compile/internal/importer: implement position reading This CL finishes importReader.pos's stub implementation to actually return syntax.Pos. New PosBase handling is analogous to typecheck/iimport.go, except for using syntax.PosBase instead of src.PosBase. Change-Id: I7629f9f5e69a38ffc2eec772504d6fb2169e1f12 Reviewed-on: https://go-review.googlesource.com/c/go/+/320614 Trust: Matthew Dempsky Trust: Dan Scales Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Dan Scales Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/importer/iimport.go | 52 ++++++++++++-------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index 8ab0b7b989..5c02f837ef 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -99,9 +99,10 @@ func iImportData(imports map[string]*types2.Package, data []byte, path string) ( ipath: path, version: int(version), - stringData: stringData, - stringCache: make(map[uint64]string), - pkgCache: make(map[uint64]*types2.Package), + stringData: stringData, + stringCache: make(map[uint64]string), + pkgCache: make(map[uint64]*types2.Package), + posBaseCache: make(map[uint64]*syntax.PosBase), declData: declData, pkgIndex: make(map[*types2.Package]map[string]uint64), @@ -173,9 +174,10 @@ type iimporter struct { ipath string version int - stringData []byte - stringCache map[uint64]string - pkgCache map[uint64]*types2.Package + stringData []byte + stringCache map[uint64]string + pkgCache map[uint64]*types2.Package + posBaseCache map[uint64]*syntax.PosBase declData []byte pkgIndex map[*types2.Package]map[string]uint64 @@ -228,6 +230,16 @@ func (p *iimporter) pkgAt(off uint64) *types2.Package { return nil } +func (p *iimporter) posBaseAt(off uint64) *syntax.PosBase { + if posBase, ok := p.posBaseCache[off]; ok { + return posBase + } + filename := p.stringAt(off) + posBase := syntax.NewFileBase(filename) + p.posBaseCache[off] = posBase + return posBase +} + func (p *iimporter) typAt(off uint64, base *types2.Named) types2.Type { if t, ok := p.typCache[off]; ok && (base == nil || !isInterface(t)) { return t @@ -251,12 +263,12 @@ func (p *iimporter) typAt(off uint64, base *types2.Named) types2.Type { } type importReader struct { - p *iimporter - declReader bytes.Reader - currPkg *types2.Package - prevFile string - prevLine int64 - prevColumn int64 + p *iimporter + declReader bytes.Reader + currPkg *types2.Package + prevPosBase *syntax.PosBase + prevLine int64 + prevColumn int64 } func (r *importReader) obj(name string) { @@ -439,12 +451,11 @@ func (r *importReader) pos() syntax.Pos { r.posv0() } - if r.prevFile == "" && r.prevLine == 0 && r.prevColumn == 0 { + if (r.prevPosBase == nil || r.prevPosBase.Filename() == "") && r.prevLine == 0 && r.prevColumn == 0 { return syntax.Pos{} } - // TODO(gri) fix this - // return r.p.fake.pos(r.prevFile, int(r.prevLine), int(r.prevColumn)) - return syntax.Pos{} + + return syntax.MakePos(r.prevPosBase, uint(r.prevLine), uint(r.prevColumn)) } func (r *importReader) posv0() { @@ -454,7 +465,7 @@ func (r *importReader) posv0() { } else if l := r.int64(); l == -1 { r.prevLine += deltaNewFile } else { - r.prevFile = r.string() + r.prevPosBase = r.posBase() r.prevLine = l } } @@ -466,7 +477,7 @@ func (r *importReader) posv1() { delta = r.int64() r.prevLine += delta >> 1 if delta&1 != 0 { - r.prevFile = r.string() + r.prevPosBase = r.posBase() } } } @@ -480,8 +491,9 @@ func isInterface(t types2.Type) bool { return ok } -func (r *importReader) pkg() *types2.Package { return r.p.pkgAt(r.uint64()) } -func (r *importReader) string() string { return r.p.stringAt(r.uint64()) } +func (r *importReader) pkg() *types2.Package { return r.p.pkgAt(r.uint64()) } +func (r *importReader) string() string { return r.p.stringAt(r.uint64()) } +func (r *importReader) posBase() *syntax.PosBase { return r.p.posBaseAt(r.uint64()) } func (r *importReader) doType(base *types2.Named) types2.Type { switch k := r.kind(); k { -- GitLab From c2966ae272b7ddd44ee6f93beb32da925e8336df Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 18 May 2021 16:34:44 -0700 Subject: [PATCH 0090/2500] [dev.typeparams] cmd/compile/internal/ir: more position details in dump When dumping node positions, include column position and the full inlining tree. These details are helpful for diagnosing "toolstash -cmp" failures due to subtly changing positions. Change-Id: I953292d6c01899fd98e2f315bafaa123c4d98ffd Reviewed-on: https://go-review.googlesource.com/c/go/+/321089 Trust: Matthew Dempsky Trust: Dan Scales Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/ir/fmt.go | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index f2ae0f7606..4ac5f3fea2 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -1114,16 +1114,21 @@ func dumpNodeHeader(w io.Writer, n Node) { } if n.Pos().IsKnown() { - pfx := "" + fmt.Fprint(w, " # ") switch n.Pos().IsStmt() { case src.PosNotStmt: - pfx = "_" // "-" would be confusing + fmt.Fprint(w, "_") // "-" would be confusing case src.PosIsStmt: - pfx = "+" + fmt.Fprint(w, "+") + } + for i, pos := range base.Ctxt.AllPos(n.Pos(), nil) { + if i > 0 { + fmt.Fprint(w, ",") + } + // TODO(mdempsky): Print line pragma details too. + file := filepath.Base(pos.Filename()) + fmt.Fprintf(w, "%s:%d:%d", file, pos.Line(), pos.Col()) } - pos := base.Ctxt.PosTable.Pos(n.Pos()) - file := filepath.Base(pos.Filename()) - fmt.Fprintf(w, " # %s%s:%d", pfx, file, pos.Line()) } } -- GitLab From 2212a1a339c7ac72ff2133855c97ae097444cb5c Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Fri, 7 May 2021 13:23:11 -0400 Subject: [PATCH 0091/2500] [dev.fuzz] cmd/go/internal/test,testing: add documentation about fuzzing Change-Id: Id43f7f75d6033a2c35bacd1cc0b8e3fbcaf69316 Reviewed-on: https://go-review.googlesource.com/c/go/+/317973 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/alldocs.go | 76 +++++++++++++++++++++++++------ src/cmd/go/internal/test/test.go | 78 ++++++++++++++++++++++++++------ src/cmd/go/main.go | 1 + src/testing/testing.go | 56 ++++++++++++++++++++--- 4 files changed, 175 insertions(+), 36 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 0e1119aa0c..2a439bd904 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -53,6 +53,7 @@ // private configuration for downloading non-public code // testflag testing flags // testfunc testing functions +// fuzz fuzzing // vcs controlling version control with GOVCS // // Use "go help " for more information about that topic. @@ -1377,8 +1378,8 @@ // // 'Go test' recompiles each package along with any files with names matching // the file pattern "*_test.go". -// These additional files can contain test functions, benchmark functions, and -// example functions. See 'go help testfunc' for more. +// These additional files can contain test functions, benchmark functions, fuzz +// targets and example functions. See 'go help testfunc' for more. // Each listed package causes the execution of a separate test binary. // Files whose names begin with "_" (including "_test.go") or "." are ignored. // @@ -1447,6 +1448,8 @@ // so a successful package test result will be cached and reused // regardless of -timeout setting. // +// Run 'go help fuzz' for details around how the go command handles fuzz targets. +// // In addition to the build flags, the flags handled by 'go test' itself are: // // -args @@ -2609,7 +2612,8 @@ // (for example, -benchtime 100x). // // -count n -// Run each test and benchmark n times (default 1). +// Run each test, benchmark, and fuzz targets' seed corpora n times +// (default 1). // If -cpu is set, run n times for each GOMAXPROCS value. // Examples are always run once. // @@ -2638,32 +2642,51 @@ // Sets -cover. // // -cpu 1,2,4 -// Specify a list of GOMAXPROCS values for which the tests or -// benchmarks should be executed. The default is the current value +// Specify a list of GOMAXPROCS values for which the tests, benchmarks or +// fuzz targets should be executed. The default is the current value // of GOMAXPROCS. // // -failfast // Do not start new tests after the first test failure. // +// -fuzz name +// Run the fuzz target with the given regexp. Must match exactly one fuzz +// target. This is an experimental feature. +// +// -fuzztime t +// Run enough iterations of the fuzz test to take t, specified as a +// time.Duration (for example, -fuzztime 1h30s). The default is to run +// forever. +// The special syntax Nx means to run the fuzz test N times +// (for example, -fuzztime 100x). +// +// -keepfuzzing +// Keep running the fuzz target if a crasher is found. +// // -list regexp -// List tests, benchmarks, or examples matching the regular expression. -// No tests, benchmarks or examples will be run. This will only -// list top-level tests. No subtest or subbenchmarks will be shown. +// List tests, benchmarks, fuzz targets, or examples matching the regular +// expression. No tests, benchmarks, fuzz targets, or examples will be run. +// This will only list top-level tests. No subtest or subbenchmarks will be +// shown. // // -parallel n -// Allow parallel execution of test functions that call t.Parallel. +// Allow parallel execution of test functions that call t.Parallel, and +// f.Fuzz functions that call t.Parallel when running the seed corpus. // The value of this flag is the maximum number of tests to run -// simultaneously; by default, it is set to the value of GOMAXPROCS. +// simultaneously. While fuzzing, the value of this flag is the +// maximum number of workers to run the fuzz function simultaneously, +// regardless of whether t.Parallel has been called; by default, it is set +// to the value of GOMAXPROCS. // Note that -parallel only applies within a single test binary. // The 'go test' command may run tests for different packages // in parallel as well, according to the setting of the -p flag // (see 'go help build'). // // -run regexp -// Run only those tests and examples matching the regular expression. -// For tests, the regular expression is split by unbracketed slash (/) -// characters into a sequence of regular expressions, and each part -// of a test's identifier must match the corresponding element in +// Run only those tests, examples, and fuzz targets matching the regular +// expression. For tests, the regular expression is split by unbracketed +// slash (/) characters into a sequence of regular expressions, and each +// part of a test's identifier must match the corresponding element in // the sequence, if any. Note that possible parents of matches are // run too, so that -run=X/Y matches and runs and reports the result // of all tests matching X, even those without sub-tests matching Y, @@ -2830,6 +2853,10 @@ // // func BenchmarkXxx(b *testing.B) { ... } // +// A fuzz target is one named FuzzXxx and should have the signature, +// +// func FuzzXxx(f *testing.F) { ... } +// // An example function is similar to a test function but, instead of using // *testing.T to report success or failure, prints output to os.Stdout. // If the last comment in the function starts with "Output:" then the output @@ -2869,11 +2896,30 @@ // // The entire test file is presented as the example when it contains a single // example function, at least one other function, type, variable, or constant -// declaration, and no test or benchmark functions. +// declaration, and no fuzz targets or test or benchmark functions. // // See the documentation of the testing package for more information. // // +// Fuzzing +// +// By default, go test will build and run the fuzz targets using the target's seed +// corpus only. Any generated corpora in $GOCACHE that were previously written by +// the fuzzing engine will not be run by default. +// +// When -fuzz is set, the binary will be instrumented for coverage. After all +// tests, examples, benchmark functions, and the seed corpora for all fuzz targets +// have been run, go test will begin to fuzz the specified fuzz target. +// Note that this feature is experimental. +// +// -run can be used for testing a single seed corpus entry for a fuzz target. The +// regular expression value of -run can be in the form $target/$name, where $target +// is the name of the fuzz target, and $name is the name of the file (ignoring file +// extensions) to run. For example, -run=FuzzFoo/497b6f87. +// +// See https://golang.org/s/draft-fuzzing-design for more details. +// +// // Controlling version control with GOVCS // // The 'go get' command can run version control commands like git diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 290f6fd348..d5afae782b 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -60,8 +60,8 @@ followed by detailed output for each failed package. 'Go test' recompiles each package along with any files with names matching the file pattern "*_test.go". -These additional files can contain test functions, benchmark functions, and -example functions. See 'go help testfunc' for more. +These additional files can contain test functions, benchmark functions, fuzz +targets and example functions. See 'go help testfunc' for more. Each listed package causes the execution of a separate test binary. Files whose names begin with "_" (including "_test.go") or "." are ignored. @@ -130,6 +130,8 @@ A cached test result is treated as executing in no time at all, so a successful package test result will be cached and reused regardless of -timeout setting. +Run 'go help fuzz' for details around how the go command handles fuzz targets. + In addition to the build flags, the flags handled by 'go test' itself are: -args @@ -206,7 +208,8 @@ control the execution of any test: (for example, -benchtime 100x). -count n - Run each test and benchmark n times (default 1). + Run each test, benchmark, and fuzz targets' seed corpora n times + (default 1). If -cpu is set, run n times for each GOMAXPROCS value. Examples are always run once. @@ -235,32 +238,51 @@ control the execution of any test: Sets -cover. -cpu 1,2,4 - Specify a list of GOMAXPROCS values for which the tests or - benchmarks should be executed. The default is the current value + Specify a list of GOMAXPROCS values for which the tests, benchmarks or + fuzz targets should be executed. The default is the current value of GOMAXPROCS. -failfast Do not start new tests after the first test failure. + -fuzz name + Run the fuzz target with the given regexp. Must match exactly one fuzz + target. This is an experimental feature. + + -fuzztime t + Run enough iterations of the fuzz test to take t, specified as a + time.Duration (for example, -fuzztime 1h30s). The default is to run + forever. + The special syntax Nx means to run the fuzz test N times + (for example, -fuzztime 100x). + + -keepfuzzing + Keep running the fuzz target if a crasher is found. + -list regexp - List tests, benchmarks, or examples matching the regular expression. - No tests, benchmarks or examples will be run. This will only - list top-level tests. No subtest or subbenchmarks will be shown. + List tests, benchmarks, fuzz targets, or examples matching the regular + expression. No tests, benchmarks, fuzz targets, or examples will be run. + This will only list top-level tests. No subtest or subbenchmarks will be + shown. -parallel n - Allow parallel execution of test functions that call t.Parallel. + Allow parallel execution of test functions that call t.Parallel, and + f.Fuzz functions that call t.Parallel when running the seed corpus. The value of this flag is the maximum number of tests to run - simultaneously; by default, it is set to the value of GOMAXPROCS. + simultaneously. While fuzzing, the value of this flag is the + maximum number of workers to run the fuzz function simultaneously, + regardless of whether t.Parallel has been called; by default, it is set + to the value of GOMAXPROCS. Note that -parallel only applies within a single test binary. The 'go test' command may run tests for different packages in parallel as well, according to the setting of the -p flag (see 'go help build'). -run regexp - Run only those tests and examples matching the regular expression. - For tests, the regular expression is split by unbracketed slash (/) - characters into a sequence of regular expressions, and each part - of a test's identifier must match the corresponding element in + Run only those tests, examples, and fuzz targets matching the regular + expression. For tests, the regular expression is split by unbracketed + slash (/) characters into a sequence of regular expressions, and each + part of a test's identifier must match the corresponding element in the sequence, if any. Note that possible parents of matches are run too, so that -run=X/Y matches and runs and reports the result of all tests matching X, even those without sub-tests matching Y, @@ -430,6 +452,10 @@ A benchmark function is one named BenchmarkXxx and should have the signature, func BenchmarkXxx(b *testing.B) { ... } +A fuzz target is one named FuzzXxx and should have the signature, + + func FuzzXxx(f *testing.F) { ... } + An example function is similar to a test function but, instead of using *testing.T to report success or failure, prints output to os.Stdout. If the last comment in the function starts with "Output:" then the output @@ -469,12 +495,34 @@ Here is another example where the ordering of the output is ignored: The entire test file is presented as the example when it contains a single example function, at least one other function, type, variable, or constant -declaration, and no test or benchmark functions. +declaration, and no fuzz targets or test or benchmark functions. See the documentation of the testing package for more information. `, } +var HelpFuzz = &base.Command{ + UsageLine: "fuzz", + Short: "fuzzing", + Long: ` +By default, go test will build and run the fuzz targets using the target's seed +corpus only. Any generated corpora in $GOCACHE that were previously written by +the fuzzing engine will not be run by default. + +When -fuzz is set, the binary will be instrumented for coverage. After all +tests, examples, benchmark functions, and the seed corpora for all fuzz targets +have been run, go test will begin to fuzz the specified fuzz target. +Note that this feature is experimental. + +-run can be used for testing a single seed corpus entry for a fuzz target. The +regular expression value of -run can be in the form $target/$name, where $target +is the name of the fuzz target, and $name is the name of the file (ignoring file +extensions) to run. For example, -run=FuzzFoo/497b6f87. + +See https://golang.org/s/draft-fuzzing-design for more details. +`, +} + var ( testBench string // -bench flag testC bool // -c flag diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go index 02174a56ff..452673dd34 100644 --- a/src/cmd/go/main.go +++ b/src/cmd/go/main.go @@ -80,6 +80,7 @@ func init() { modfetch.HelpPrivate, test.HelpTestflag, test.HelpTestfunc, + test.HelpFuzz, modget.HelpVCS, } } diff --git a/src/testing/testing.go b/src/testing/testing.go index 63dcc62597..6b710d26d5 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -34,7 +34,7 @@ // its -bench flag is provided. Benchmarks are run sequentially. // // For a description of the testing flags, see -// https://golang.org/cmd/go/#hdr-Testing_flags +// https://golang.org/cmd/go/#hdr-Testing_flags. // // A sample benchmark function looks like this: // func BenchmarkRandInt(b *testing.B) { @@ -132,6 +132,27 @@ // example function, at least one other function, type, variable, or constant // declaration, and no test or benchmark functions. // +// Fuzzing +// +// Functions of the form +// func FuzzXxx(*testing.F) +// are considered fuzz targets, and are executed by the "go test" command. When +// the -fuzz flag is provided, the functions will be fuzzed. +// +// For a description of the testing flags, see +// https://golang.org/cmd/go/#hdr-Testing_flags. +// +// For a description of fuzzing, see golang.org/s/draft-fuzzing-design. +// +// A sample fuzz target looks like this: +// func FuzzBytesCmp(f *testing.F) { +// f.Fuzz(func(t *testing.T, a, b []byte) { +// if bytes.HasPrefix(a, b) && !bytes.Contains(a, b) { +// t.Error("HasPrefix is true, but Contains is false") +// } +// }) +// } +// // Skipping // // Tests or benchmarks may be skipped at run time with a call to @@ -144,6 +165,21 @@ // ... // } // +// The Skip method of *T can be used in a fuzz target if the input is invalid, +// but should not be considered a crash. For example: +// +// func FuzzJSONMarshalling(f *testing.F) { +// f.Fuzz(func(t *testing.T, b []byte) { +// var v interface{} +// if err := json.Unmarshal(b, &v); err != nil { +// t.Skip() +// } +// if _, err := json.Marshal(v); err != nil { +// t.Error("Marshal: %v", err) +// } +// }) +// } +// // Subtests and Sub-benchmarks // // The Run methods of T and B allow defining subtests and sub-benchmarks, @@ -163,17 +199,25 @@ // of the top-level test and the sequence of names passed to Run, separated by // slashes, with an optional trailing sequence number for disambiguation. // -// The argument to the -run and -bench command-line flags is an unanchored regular +// The argument to the -run, -bench, and -fuzz command-line flags is an unanchored regular // expression that matches the test's name. For tests with multiple slash-separated // elements, such as subtests, the argument is itself slash-separated, with // expressions matching each name element in turn. Because it is unanchored, an // empty expression matches any string. // For example, using "matching" to mean "whose name contains": // -// go test -run '' # Run all tests. -// go test -run Foo # Run top-level tests matching "Foo", such as "TestFooBar". -// go test -run Foo/A= # For top-level tests matching "Foo", run subtests matching "A=". -// go test -run /A=1 # For all top-level tests, run subtests matching "A=1". +// go test -run '' # Run all tests. +// go test -run Foo # Run top-level tests matching "Foo", such as "TestFooBar". +// go test -run Foo/A= # For top-level tests matching "Foo", run subtests matching "A=". +// go test -run /A=1 # For all top-level tests, run subtests matching "A=1". +// go test -fuzz FuzzFoo # Fuzz the target matching "FuzzFoo" +// +// The -run argument can also be used to run a specific value in the seed +// corpus, for debugging. For example: +// go test -run=FuzzFoo/9ddb952d9814 +// +// The -fuzz and -run flags can both be set, in order to fuzz a target but +// skip the execution of all other tests. // // Subtests can also be used to control parallelism. A parent test will only // complete once all of its subtests complete. In this example, all tests are -- GitLab From ad24be022be1c3124887ff22fc742494ee12dfb8 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Fri, 14 May 2021 13:59:26 -0400 Subject: [PATCH 0092/2500] [dev.fuzz] internal/fuzz: make minimization tests more reliable * Introduced -fuzzminimizetime flag to control the number of time or the number of calls to spend minimizing. Defaults to 60s. Only works for unrecoverable crashes for now. * Moved the count (used by -fuzztime=1000x) into shared memory. Calling workerClient.fuzz resets it, but it will remain after the worker processes crashes. workerClient.minimize resets it once before restarting the worker the first time, but the total number of runs should still be limited during minimization, even after multiple terminations and restarts. * Renamed fuzzArgs.Count to Limit to avoid confusion. * Several other small fixes and refactorings. Change-Id: I03faa4c94405041f6dfe48568e5ead502f8dbbd2 Reviewed-on: https://go-review.googlesource.com/c/go/+/320171 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod Reviewed-by: Katie Hockman --- src/cmd/go/internal/test/flagdefs.go | 1 + src/cmd/go/internal/test/testflag.go | 1 + .../script/test_fuzz_mutate_crash.txt | 14 +- .../go/testdata/script/test_fuzz_mutator.txt | 17 ++- src/internal/fuzz/fuzz.go | 29 ++-- src/internal/fuzz/mem.go | 13 +- src/internal/fuzz/worker.go | 141 ++++++++++++------ src/testing/fuzz.go | 25 +++- src/testing/internal/testdeps/deps.go | 29 ++-- src/testing/testing.go | 4 +- 10 files changed, 187 insertions(+), 87 deletions(-) diff --git a/src/cmd/go/internal/test/flagdefs.go b/src/cmd/go/internal/test/flagdefs.go index 5a666aa1f9..3148074d57 100644 --- a/src/cmd/go/internal/test/flagdefs.go +++ b/src/cmd/go/internal/test/flagdefs.go @@ -20,6 +20,7 @@ var passFlagToTest = map[string]bool{ "cpuprofile": true, "failfast": true, "fuzz": true, + "fuzzminimizetime": true, "fuzztime": true, "list": true, "memprofile": true, diff --git a/src/cmd/go/internal/test/testflag.go b/src/cmd/go/internal/test/testflag.go index 6a7b2a608b..e3eca9249b 100644 --- a/src/cmd/go/internal/test/testflag.go +++ b/src/cmd/go/internal/test/testflag.go @@ -69,6 +69,7 @@ func init() { cf.Bool("short", false, "") cf.DurationVar(&testTimeout, "timeout", 10*time.Minute, "") cf.String("fuzztime", "", "") + cf.String("fuzzminimizetime", "", "") cf.StringVar(&testTrace, "trace", "", "") cf.BoolVar(&testV, "v", false, "") cf.Var(&testShuffle, "shuffle", "") diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt index ca2b389321..cba91a99cf 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt @@ -185,22 +185,25 @@ func FuzzWithTwoTypes(f *testing.F) { } func FuzzInt(f *testing.F) { + f.Add(0) f.Fuzz(func(t *testing.T, a int) { - if a > 200 && a < 250 { + if a != 0 { panic("this input caused a crash!") } }) } func FuzzUint(f *testing.F) { + f.Add(uint(0)) f.Fuzz(func(t *testing.T, a uint) { - if a > 200 && a < 250 { + if a != 0 { panic("this input caused a crash!") } }) } func FuzzBool(f *testing.F) { + f.Add(false) f.Fuzz(func(t *testing.T, a bool) { if a { panic("this input caused a crash!") @@ -218,22 +221,25 @@ func FuzzFloat(f *testing.F) { } func FuzzByte(f *testing.F) { + f.Add(byte(0)) f.Fuzz(func(t *testing.T, a byte) { - if a > 50 { + if a != 0 { panic("this input caused a crash!") } }) } func FuzzRune(f *testing.F) { + f.Add(rune(0)) f.Fuzz(func(t *testing.T, a rune) { - if a > 50 { + if a != 0 { panic("this input caused a crash!") } }) } func FuzzString(f *testing.F) { + f.Add("") f.Fuzz(func(t *testing.T, a string) { if a != "" { panic("this input caused a crash!") diff --git a/src/cmd/go/testdata/script/test_fuzz_mutator.txt b/src/cmd/go/testdata/script/test_fuzz_mutator.txt index c92be50a8e..9098d52f5b 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutator.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutator.txt @@ -10,6 +10,9 @@ [short] skip +# TODO(b/181800488): remove -parallel=1, here and below. For now, when a +# crash is found, all workers keep running, wasting resources and reducing +# the number of executions available to the minimizer, increasing flakiness. go test -fuzz=FuzzA -fuzztime=100x -parallel=1 -log=fuzz go run check_logs.go fuzz fuzz.worker @@ -20,7 +23,7 @@ stdout FAIL stdout 'mutator found enough unique mutations' # Test that minimization is working for recoverable errors. -! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=1000x minimizer_test.go +! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=100x -fuzzminimizetime=10000x -parallel=1 minimizer_test.go ! stdout '^ok' stdout 'got the minimum size!' stdout 'contains a letter' @@ -33,7 +36,7 @@ go run check_testdata.go FuzzMinimizerRecoverable 50 ! go test -run=FuzzMinimizerRecoverable minimizer_test.go # Test that minimization is working for non-recoverable errors. -! go test -fuzz=FuzzMinimizerNonrecoverable -run=FuzzMinimizerNonrecoverable -fuzztime=1000x minimizer_test.go +! go test -fuzz=FuzzMinimizerNonrecoverable -run=FuzzMinimizerNonrecoverable -fuzztime=100x -fuzzminimizetime=10000x -parallel=1 minimizer_test.go ! stdout '^ok' stdout 'got the minimum size!' stdout 'contains a letter' @@ -42,9 +45,9 @@ stdout FAIL # Check that the bytes written to testdata are of length 50 (the minimum size) go run check_testdata.go FuzzMinimizerNonrecoverable 50 -# Test that minimization can be cancelled by fuzztime and the latest crash will -# still be logged and written to testdata. -! go test -fuzz=FuzzNonMinimizable -run=FuzzNonMinimizable -parallel=1 -fuzztime=5s minimizer_test.go +# Test that minimization can be cancelled by fuzzminimizetime and the latest +# crash will still be logged and written to testdata. +! go test -fuzz=FuzzNonMinimizable -run=FuzzNonMinimizable -parallel=1 -fuzztime=100x -fuzzminimizetime=1x minimizer_test.go ! stdout '^ok' stdout 'testdata[/\\]corpus[/\\]FuzzNonMinimizable[/\\]' ! stdout 'got the minimum size!' # it shouldn't have had enough time to minimize it @@ -108,7 +111,6 @@ package fuzz_test import ( "bytes" "testing" - "time" ) func FuzzMinimizerRecoverable(f *testing.F) { @@ -155,7 +157,6 @@ func FuzzNonMinimizable(f *testing.F) { if len(b) == 20 { t.Log("got the minimum size!") } - time.Sleep(4 * time.Second) }) } @@ -301,7 +302,7 @@ func main() { os.Exit(1) } if want, got := numBytes, len(s); want != got { - fmt.Fprintf(os.Stderr, "want %d bytes, got %d", want, got) + fmt.Fprintf(os.Stderr, "want %d bytes, got %d\n", want, got) os.Exit(1) } } diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 3bb2da872c..28539b2604 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -33,9 +33,18 @@ type CoordinateFuzzingOpts struct { // has loaded. If zero, there will be no time limit. Timeout time.Duration - // Count is the number of random values to generate and test. If zero, + // Limit is the number of random values to generate and test. If zero, // there will be no limit on the number of generated values. - Count int64 + Limit int64 + + // MinimizeTimeout is the amount of wall clock time to spend minimizing + // after discovering a crasher. If zero, there will be no time limit. + MinimizeTimeout time.Duration + + // MinimizeLimit is the maximum number of calls to the fuzz function to be + // made while minimizing after finding a crash. If zero, there will be + // no limit. + MinimizeLimit int64 // parallel is the number of worker processes to run in parallel. If zero, // CoordinateFuzzing will run GOMAXPROCS workers. @@ -77,9 +86,9 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err if opts.Parallel == 0 { opts.Parallel = runtime.GOMAXPROCS(0) } - if opts.Count > 0 && int64(opts.Parallel) > opts.Count { + if opts.Limit > 0 && int64(opts.Parallel) > opts.Limit { // Don't start more workers than we need. - opts.Parallel = int(opts.Count) + opts.Parallel = int(opts.Limit) } c, err := newCoordinator(opts) @@ -190,7 +199,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err case result := <-c.resultC: // Received response from worker. c.updateStats(result) - if c.opts.Count > 0 && c.count >= c.opts.Count { + if c.opts.Limit > 0 && c.count >= c.opts.Limit { stop(nil) } @@ -485,7 +494,7 @@ func (c *coordinator) logStats() { // a limit for one worker. If there are no executions left, nextInput returns // a zero value and false. func (c *coordinator) nextInput() (fuzzInput, bool) { - if c.opts.Count > 0 && c.count+c.countWaiting >= c.opts.Count { + if c.opts.Limit > 0 && c.count+c.countWaiting >= c.opts.Limit { // Workers already testing all requested inputs. return fuzzInput{}, false } @@ -503,12 +512,12 @@ func (c *coordinator) nextInput() (fuzzInput, bool) { return input, true } - if c.opts.Count > 0 { - input.countRequested = c.opts.Count / int64(c.opts.Parallel) - if c.opts.Count%int64(c.opts.Parallel) > 0 { + if c.opts.Limit > 0 { + input.countRequested = c.opts.Limit / int64(c.opts.Parallel) + if c.opts.Limit%int64(c.opts.Parallel) > 0 { input.countRequested++ } - remaining := c.opts.Count - c.count - c.countWaiting + remaining := c.opts.Limit - c.count - c.countWaiting if input.countRequested > remaining { input.countRequested = remaining } diff --git a/src/internal/fuzz/mem.go b/src/internal/fuzz/mem.go index bb30241a45..a7792321ee 100644 --- a/src/internal/fuzz/mem.go +++ b/src/internal/fuzz/mem.go @@ -37,7 +37,12 @@ type sharedMem struct { // sharedMemHeader stores metadata in shared memory. type sharedMemHeader struct { - length int + // count is the number of times the worker has called the fuzz function. + // May be reset by coordinator. + count int64 + + // valueLen is the length of the value that was last fuzzed. + valueLen int } // sharedMemSize returns the size needed for a shared memory buffer that can @@ -81,7 +86,7 @@ func (m *sharedMem) header() *sharedMemHeader { // valueRef returns the value currently stored in shared memory. The returned // slice points to shared memory; it is not a copy. func (m *sharedMem) valueRef() []byte { - length := m.header().length + length := m.header().valueLen valueOffset := int(unsafe.Sizeof(sharedMemHeader{})) return m.region[valueOffset : valueOffset+length] } @@ -102,7 +107,7 @@ func (m *sharedMem) setValue(b []byte) { if len(b) > cap(v) { panic(fmt.Sprintf("value length %d larger than shared memory capacity %d", len(b), cap(v))) } - m.header().length = len(b) + m.header().valueLen = len(b) copy(v[:cap(v)], b) } @@ -117,7 +122,7 @@ func (m *sharedMem) setValueLen(n int) { if n > cap(v) { panic(fmt.Sprintf("length %d larger than shared memory capacity %d", n, cap(v))) } - m.header().length = n + m.header().valueLen = n } // TODO(jayconrod): add method to resize the buffer. We'll need that when the diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 15b1f89daa..91ae2de1b1 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -145,7 +145,7 @@ func (w *worker) coordinate(ctx context.Context) error { case input := <-w.coordinator.inputC: // Received input from coordinator. - args := fuzzArgs{Count: input.countRequested, Duration: workerFuzzDuration, CoverageOnly: input.coverageOnly} + args := fuzzArgs{Limit: input.countRequested, Timeout: workerFuzzDuration, CoverageOnly: input.coverageOnly} if interestingCount < input.interestingCount { // The coordinator's coverage data has changed, so send the data // to the client. @@ -180,21 +180,25 @@ func (w *worker) coordinate(ctx context.Context) error { // the other workers from receiving more inputs. message := fmt.Sprintf("fuzzing process terminated unexpectedly: %v", w.waitErr) err = w.waitErr - res, minimized, minErr := w.minimize(ctx) + var result fuzzResult + var minimized bool + if !input.coverageOnly { + var minErr error + result, minimized, minErr = w.minimize(ctx) + if minErr != nil { + err = minErr + } + } if !minimized { // Minimization did not find a smaller crashing value, so // return the one we already found. - res = fuzzResult{ - entry: CorpusEntry{Data: value}, - crasherMsg: message, - } - } - if minErr != nil { - err = minErr + result.entry = CorpusEntry{Data: value} + result.crasherMsg = message } - w.coordinator.resultC <- res + w.coordinator.resultC <- result return err } + result := fuzzResult{ countRequested: input.countRequested, count: resp.Count, @@ -212,26 +216,54 @@ func (w *worker) coordinate(ctx context.Context) error { } } -// minimize asks a workerServer to attempt to minimize what is currently in -// shared memory. It runs for a maxium of 1 minute. The worker must be stopped -// when minimize is called. +// minimize asks a workerServer to attempt to minimize a value that caused an +// unexpected termination of the worker process. The value must be in shared +// memory, and the worker must be stopped. The execution count in shared memory +// is reset once before restarting the worker. func (w *worker) minimize(ctx context.Context) (res fuzzResult, minimized bool, retErr error) { - fmt.Fprint(w.coordinator.opts.Log, "found a crash, currently minimizing for up to 1 minute\n") + if w.coordinator.opts.MinimizeTimeout != 0 { + fmt.Fprintf(w.coordinator.opts.Log, "found a crash, minimizing for up to %v\n", w.coordinator.opts.MinimizeTimeout) + } else if w.coordinator.opts.MinimizeLimit != 0 { + fmt.Fprintf(w.coordinator.opts.Log, "found a crash, minimizing for up to %d execs\n", w.coordinator.opts.MinimizeLimit) + } else { + fmt.Fprintf(w.coordinator.opts.Log, "found a crash, minimizing...\n") + } + start := time.Now() + if w.coordinator.opts.MinimizeTimeout != 0 { + var cancel func() + ctx, cancel = context.WithTimeout(ctx, w.coordinator.opts.MinimizeTimeout) + defer cancel() + } defer func() { w.stop() if retErr == nil { retErr = w.waitErr } }() - // In case we can't minimize it at all, save the last crash value that we - // found to send to the coordinator once the time is up. - minimizeDeadline := time.Now().Add(time.Minute) - for rem := time.Until(minimizeDeadline); rem > 0; { + + mem := <-w.memMu + mem.header().count = 0 + w.memMu <- mem + + for { + if ctx.Err() != nil { + return res, minimized, retErr + } // Restart the worker. if err := w.start(); err != nil { return res, minimized, err } - args := minimizeArgs{Duration: rem} + if err := w.client.ping(ctx); err != nil { + return res, minimized, err + } + args := minimizeArgs{Limit: w.coordinator.opts.MinimizeLimit} + if w.coordinator.opts.MinimizeTimeout != 0 { + elapsed := time.Now().Sub(start) + args.Timeout = w.coordinator.opts.MinimizeTimeout - elapsed + if args.Timeout < 0 { + return res, minimized, retErr + } + } value, err := w.client.minimize(ctx, args) if err == nil { // Minimization finished successfully, meaning that it @@ -239,6 +271,7 @@ func (w *worker) minimize(ctx context.Context) (res fuzzResult, minimized bool, // so stop trying. return res, minimized, nil } + w.stop() // Minimization will return an error for a non-recoverable problem, so // a non-nil error is expected. However, make sure it didn't fail for // some other reason which should cause us to stop minimizing. @@ -248,7 +281,6 @@ func (w *worker) minimize(ctx context.Context) (res fuzzResult, minimized bool, // The bytes in memory caused a legitimate crash, so stop the worker and // save this value and error message. - w.stop() message := fmt.Sprintf("fuzzing process terminated unexpectedly: %v", w.waitErr) res = fuzzResult{ entry: CorpusEntry{Data: value}, @@ -256,7 +288,6 @@ func (w *worker) minimize(ctx context.Context) (res fuzzResult, minimized bool, } minimized = true } - return res, minimized, nil // TODO(jayconrod,katiehockman): while minimizing, every panic message is // logged to STDOUT. We should probably suppress all but the last one to // lower the noise. @@ -447,7 +478,14 @@ type call struct { // minimizeArgs contains arguments to workerServer.minimize. The value to // minimize is already in shared memory. type minimizeArgs struct { - Duration time.Duration + // Timeout is the time to spend minimizing. This may include time to start up, + // especially if the input causes the worker process to terminated, requiring + // repeated restarts. + Timeout time.Duration + + // Limit is the maximum number of values to test, without spending more time + // than Duration. 0 indicates no limit. + Limit int64 } // minimizeResponse contains results from workerServer.minimize. @@ -456,13 +494,13 @@ type minimizeResponse struct{} // fuzzArgs contains arguments to workerServer.fuzz. The value to fuzz is // passed in shared memory. type fuzzArgs struct { - // Duration is the time to spend fuzzing, not including starting or + // Timeout is the time to spend fuzzing, not including starting or // cleaning up. - Duration time.Duration + Timeout time.Duration - // Count is the number of values to test, without spending more time - // than Duration. - Count int64 + // Limit is the maximum number of values to test, without spending more time + // than Duration. 0 indicates no limit. + Limit int64 // CoverageOnly indicates whether this is a coverage-only run (ie. fuzzing // should not occur). @@ -604,10 +642,13 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo start := time.Now() defer func() { resp.Duration = time.Since(start) }() - fuzzCtx, cancel := context.WithTimeout(ctx, args.Duration) + fuzzCtx, cancel := context.WithTimeout(ctx, args.Timeout) defer cancel() mem := <-ws.memMu - defer func() { ws.memMu <- mem }() + defer func() { + ws.memMu <- mem + resp.Count = mem.header().count + }() vals, err := unmarshalCorpusFile(mem.valueCopy()) if err != nil { @@ -629,15 +670,17 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo return resp default: - resp.Count++ + mem.header().count++ ws.m.mutate(vals, cap(mem.valueRef())) writeToMem(vals, mem) if err := ws.fuzzFn(CorpusEntry{Values: vals}); err != nil { - // TODO(jayconrod,katiehockman): consider making the maximum - // minimization time customizable with a go command flag. + // TODO(jayconrod,katiehockman): report unminimized input to coordinator + // immediately so it can stop other workers. + // TODO(jayconrod,katiehockman): use -fuzzminimizetime to limit time or + // iterations spent on minimization. minCtx, minCancel := context.WithTimeout(ctx, time.Minute) defer minCancel() - if minErr := ws.minimizeInput(minCtx, vals, mem); minErr != nil { + if minErr := ws.minimizeInput(minCtx, vals, mem, &mem.header().count, args.Limit); minErr != nil { // Minimization found a different error, so use that one. err = minErr } @@ -654,24 +697,27 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo return resp } } - if args.Count > 0 && resp.Count == args.Count { + if args.Limit > 0 && mem.header().count == args.Limit { return resp } } } } -func (ws *workerServer) minimize(ctx context.Context, args minimizeArgs) minimizeResponse { +func (ws *workerServer) minimize(ctx context.Context, args minimizeArgs) (resp minimizeResponse) { mem := <-ws.memMu defer func() { ws.memMu <- mem }() vals, err := unmarshalCorpusFile(mem.valueCopy()) if err != nil { panic(err) } - ctx, cancel := context.WithTimeout(ctx, args.Duration) - defer cancel() - ws.minimizeInput(ctx, vals, mem) - return minimizeResponse{} + if args.Timeout != 0 { + var cancel func() + ctx, cancel = context.WithTimeout(ctx, args.Timeout) + defer cancel() + } + ws.minimizeInput(ctx, vals, mem, &mem.header().count, args.Limit) + return resp } // minimizeInput applies a series of minimizing transformations on the provided @@ -680,10 +726,17 @@ func (ws *workerServer) minimize(ctx context.Context, args minimizeArgs) minimiz // mem just in case an unrecoverable error occurs. It uses the context to // determine how long to run, stopping once closed. It returns the last error it // found. -func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, mem *sharedMem) (retErr error) { +func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, mem *sharedMem, count *int64, limit int64) (retErr error) { // Make sure the last crashing value is written to mem. defer writeToMem(vals, mem) + shouldStop := func() bool { + return ctx.Err() != nil || (limit > 0 && *count >= limit) + } + if shouldStop() { + return nil + } + // tryMinimized will run the fuzz function for the values in vals at the // time the function is called. If err is nil, then the minimization was // unsuccessful, since we expect an error to still occur. @@ -698,6 +751,7 @@ func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, m // The fuzz function failed, so save the most recent error. retErr = err } + *count++ return err } for valI := range vals { @@ -710,7 +764,7 @@ func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, m // First, try to cut the tail. for n := 1024; n != 0; n /= 2 { for len(v) > n { - if ctx.Err() != nil { + if shouldStop() { return retErr } vals[valI] = v[:len(v)-n] @@ -725,7 +779,7 @@ func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, m // Then, try to remove each individual byte. tmp := make([]byte, len(v)) for i := 0; i < len(v)-1; i++ { - if ctx.Err() != nil { + if shouldStop() { return retErr } candidate := tmp[:len(v)-1] @@ -747,7 +801,7 @@ func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, m for i := 0; i < len(v)-1; i++ { copy(tmp, v[:i]) for j := len(v); j > i+1; j-- { - if ctx.Err() != nil { + if shouldStop() { return retErr } candidate := tmp[:len(v)-j+i] @@ -862,6 +916,7 @@ func (wc *workerClient) fuzz(ctx context.Context, valueIn []byte, args fuzzArgs) if !ok { return nil, fuzzResponse{}, errSharedMemClosed } + mem.header().count = 0 mem.setValue(valueIn) wc.memMu <- mem diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index d81796b4fc..9364b27eaf 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -18,16 +18,18 @@ import ( func initFuzzFlags() { matchFuzz = flag.String("test.fuzz", "", "run the fuzz target matching `regexp`") - flag.Var(&fuzzDuration, "test.fuzztime", "time to spend fuzzing default is to run indefinitely") + flag.Var(&fuzzDuration, "test.fuzztime", "time to spend fuzzing; default is to run indefinitely") + flag.Var(&minimizeDuration, "test.fuzzminimizetime", "time to spend minimizing a value after finding a crash; default is to minimize for 60s") fuzzCacheDir = flag.String("test.fuzzcachedir", "", "directory where interesting fuzzing inputs are stored") isFuzzWorker = flag.Bool("test.fuzzworker", false, "coordinate with the parent process to fuzz random values") } var ( - matchFuzz *string - fuzzDuration durationOrCountFlag - fuzzCacheDir *string - isFuzzWorker *bool + matchFuzz *string + fuzzDuration durationOrCountFlag + minimizeDuration = durationOrCountFlag{d: 60 * time.Second} + fuzzCacheDir *string + isFuzzWorker *bool // corpusDir is the parent directory of the target's seed corpus within // the package. @@ -357,7 +359,16 @@ func (f *F) Fuzz(ff interface{}) { // actual fuzzing. corpusTargetDir := filepath.Join(corpusDir, f.name) cacheTargetDir := filepath.Join(*fuzzCacheDir, f.name) - err := f.fuzzContext.coordinateFuzzing(fuzzDuration.d, int64(fuzzDuration.n), *parallel, f.corpus, types, corpusTargetDir, cacheTargetDir) + err := f.fuzzContext.coordinateFuzzing( + fuzzDuration.d, + int64(fuzzDuration.n), + minimizeDuration.d, + int64(minimizeDuration.n), + *parallel, + f.corpus, + types, + corpusTargetDir, + cacheTargetDir) if err != nil { f.result = FuzzResult{Error: err} f.Fail() @@ -451,7 +462,7 @@ type fuzzCrashError interface { // fuzzContext holds all fields that are common to all fuzz targets. type fuzzContext struct { importPath func() string - coordinateFuzzing func(time.Duration, int64, int, []corpusEntry, []reflect.Type, string, string) error + coordinateFuzzing func(time.Duration, int64, time.Duration, int64, int, []corpusEntry, []reflect.Type, string, string) error runFuzzWorker func(func(corpusEntry) error) error readCorpus func(string, []reflect.Type) ([]corpusEntry, error) resetCoverage func() diff --git a/src/testing/internal/testdeps/deps.go b/src/testing/internal/testdeps/deps.go index 24ef7c4d62..01390f51d3 100644 --- a/src/testing/internal/testdeps/deps.go +++ b/src/testing/internal/testdeps/deps.go @@ -133,21 +133,32 @@ func (TestDeps) SetPanicOnExit0(v bool) { testlog.SetPanicOnExit0(v) } -func (TestDeps) CoordinateFuzzing(timeout time.Duration, count int64, parallel int, seed []fuzz.CorpusEntry, types []reflect.Type, corpusDir, cacheDir string) (err error) { +func (TestDeps) CoordinateFuzzing( + timeout time.Duration, + limit int64, + minimizeTimeout time.Duration, + minimizeLimit int64, + parallel int, + seed []fuzz.CorpusEntry, + types []reflect.Type, + corpusDir, + cacheDir string) (err error) { // Fuzzing may be interrupted with a timeout or if the user presses ^C. // In either case, we'll stop worker processes gracefully and save // crashers and interesting values. ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt) defer cancel() err = fuzz.CoordinateFuzzing(ctx, fuzz.CoordinateFuzzingOpts{ - Log: os.Stderr, - Timeout: timeout, - Count: count, - Parallel: parallel, - Seed: seed, - Types: types, - CorpusDir: corpusDir, - CacheDir: cacheDir, + Log: os.Stderr, + Timeout: timeout, + Limit: limit, + MinimizeTimeout: minimizeTimeout, + MinimizeLimit: minimizeLimit, + Parallel: parallel, + Seed: seed, + Types: types, + CorpusDir: corpusDir, + CacheDir: cacheDir, }) if err == ctx.Err() { return nil diff --git a/src/testing/testing.go b/src/testing/testing.go index 6b710d26d5..07ef625538 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1434,7 +1434,7 @@ func (f matchStringOnly) ImportPath() string { return " func (f matchStringOnly) StartTestLog(io.Writer) {} func (f matchStringOnly) StopTestLog() error { return errMain } func (f matchStringOnly) SetPanicOnExit0(bool) {} -func (f matchStringOnly) CoordinateFuzzing(time.Duration, int64, int, []corpusEntry, []reflect.Type, string, string) error { +func (f matchStringOnly) CoordinateFuzzing(time.Duration, int64, time.Duration, int64, int, []corpusEntry, []reflect.Type, string, string) error { return errMain } func (f matchStringOnly) RunFuzzWorker(func(corpusEntry) error) error { return errMain } @@ -1485,7 +1485,7 @@ type testDeps interface { StartTestLog(io.Writer) StopTestLog() error WriteProfileTo(string, io.Writer, int) error - CoordinateFuzzing(time.Duration, int64, int, []corpusEntry, []reflect.Type, string, string) error + CoordinateFuzzing(time.Duration, int64, time.Duration, int64, int, []corpusEntry, []reflect.Type, string, string) error RunFuzzWorker(func(corpusEntry) error) error ReadCorpus(string, []reflect.Type) ([]corpusEntry, error) ResetCoverage() -- GitLab From bb53bd49571e08909ab6274255ddddd6c6ffe041 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Thu, 13 May 2021 13:13:26 -0400 Subject: [PATCH 0093/2500] [dev.fuzz] cmd/go: fix test_fuzz_cache This test started failing when coverage-based fuzzing was enabled. It expects at least one file to be written to the fuzz cache. Nothing was written because the fuzz function was trivial, and no interesting inputs could be discovered. This CL makes the fuzz function return different values for different inputs, which is enough to pass. Change-Id: I6ffd2667891cf5f3e4588133efb65f096a739c09 Reviewed-on: https://go-review.googlesource.com/c/go/+/319871 Trust: Jay Conrod Run-TryBot: Jay Conrod Reviewed-by: Katie Hockman --- src/cmd/go/testdata/script/test_fuzz_cache.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_cache.txt b/src/cmd/go/testdata/script/test_fuzz_cache.txt index cb344a7158..a6c9cafada 100644 --- a/src/cmd/go/testdata/script/test_fuzz_cache.txt +++ b/src/cmd/go/testdata/script/test_fuzz_cache.txt @@ -39,7 +39,15 @@ import "testing" func FuzzY(f *testing.F) { f.Add([]byte("y")) - f.Fuzz(func(t *testing.T, b []byte) {}) + f.Fuzz(func(t *testing.T, b []byte) { Y(b) }) +} +-- y.go -- +package y + +import "bytes" + +func Y(b []byte) bool { + return bytes.Equal(b, []byte("y")) } -- empty/empty.go -- package empty -- GitLab From 701bd6064655fb51d189c9f421f876a67f6619a3 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Wed, 19 May 2021 09:58:01 -0700 Subject: [PATCH 0094/2500] [dev.typeparams] cmd/compile: simplify targ's type Make the base type of targ a *types.Type instead of an ir.Node containing a type. Also move makeInstName to typecheck, so it can later be used by reflectdata for making wrappers. Change-Id: If148beaa972e5112ead2771d6e32d73f16ca30c1 Reviewed-on: https://go-review.googlesource.com/c/go/+/321209 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 63 ++++------------------ src/cmd/compile/internal/noder/types.go | 4 +- src/cmd/compile/internal/typecheck/subr.go | 58 ++++++++++++++++++++ 3 files changed, 70 insertions(+), 55 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index adcea2c087..87c61b2cf1 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -166,12 +166,8 @@ func (g *irgen) instantiateMethods() { baseSym := typ.Sym().Pkg.Lookup(genericTypeName(typ.Sym())) baseType := baseSym.Def.(*ir.Name).Type() for j, m := range typ.Methods().Slice() { - targs := make([]ir.Node, len(typ.RParams())) - for k, targ := range typ.RParams() { - targs[k] = ir.TypeNode(targ) - } baseNname := baseType.Methods().Slice()[j].Nname.(*ir.Name) - f := g.getInstantiation(baseNname, targs, true) + f := g.getInstantiation(baseNname, typ.RParams(), true) m.Nname = f.Nname } } @@ -190,17 +186,17 @@ func genericTypeName(sym *types.Sym) string { // InstExpr node inst. func (g *irgen) getInstantiationForNode(inst *ir.InstExpr) *ir.Func { if meth, ok := inst.X.(*ir.SelectorExpr); ok { - return g.getInstantiation(meth.Selection.Nname.(*ir.Name), inst.Targs, true) + return g.getInstantiation(meth.Selection.Nname.(*ir.Name), typecheck.TypesOf(inst.Targs), true) } else { - return g.getInstantiation(inst.X.(*ir.Name), inst.Targs, false) + return g.getInstantiation(inst.X.(*ir.Name), typecheck.TypesOf(inst.Targs), false) } } // getInstantiation gets the instantiantion of the function or method nameNode // with the type arguments targs. If the instantiated function is not already // cached, then it calls genericSubst to create the new instantiation. -func (g *irgen) getInstantiation(nameNode *ir.Name, targs []ir.Node, isMeth bool) *ir.Func { - sym := makeInstName(nameNode.Sym(), targs, isMeth) +func (g *irgen) getInstantiation(nameNode *ir.Name, targs []*types.Type, isMeth bool) *ir.Func { + sym := typecheck.MakeInstName(nameNode.Sym(), targs, isMeth) st := g.target.Stencils[sym] if st == nil { // If instantiation doesn't exist yet, create it and add @@ -215,45 +211,6 @@ func (g *irgen) getInstantiation(nameNode *ir.Name, targs []ir.Node, isMeth bool return st } -// makeInstName makes the unique name for a stenciled generic function or method, -// based on the name of the function fy=nsym and the targs. It replaces any -// existing bracket type list in the name. makeInstName asserts that fnsym has -// brackets in its name if and only if hasBrackets is true. -// TODO(danscales): remove the assertions and the hasBrackets argument later. -// -// Names of declared generic functions have no brackets originally, so hasBrackets -// should be false. Names of generic methods already have brackets, since the new -// type parameter is specified in the generic type of the receiver (e.g. func -// (func (v *value[T]).set(...) { ... } has the original name (*value[T]).set. -// -// The standard naming is something like: 'genFn[int,bool]' for functions and -// '(*genType[int,bool]).methodName' for methods -func makeInstName(fnsym *types.Sym, targs []ir.Node, hasBrackets bool) *types.Sym { - b := bytes.NewBufferString("") - name := fnsym.Name - i := strings.Index(name, "[") - assert(hasBrackets == (i >= 0)) - if i >= 0 { - b.WriteString(name[0:i]) - } else { - b.WriteString(name) - } - b.WriteString("[") - for i, targ := range targs { - if i > 0 { - b.WriteString(",") - } - b.WriteString(targ.Type().String()) - } - b.WriteString("]") - if i >= 0 { - i2 := strings.Index(name[i:], "]") - assert(i2 >= 0) - b.WriteString(name[i+i2+1:]) - } - return typecheck.Lookup(b.String()) -} - // Struct containing info needed for doing the substitution as we create the // instantiation of a generic function with specified type arguments. type subster struct { @@ -261,7 +218,7 @@ type subster struct { isMethod bool // If a method is being instantiated newf *ir.Func // Func node for the new stenciled function tparams []*types.Field - targs []ir.Node + targs []*types.Type // The substitution map from name nodes in the generic function to the // name nodes in the new stenciled function. vars map[*ir.Name]*ir.Name @@ -273,7 +230,7 @@ type subster struct { // function type where the receiver becomes the first parameter. Otherwise the // instantiated method would still need to be transformed by later compiler // phases. -func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []ir.Node, isMethod bool) *ir.Func { +func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []*types.Type, isMethod bool) *ir.Func { var tparams []*types.Field if isMethod { // Get the type params from the method receiver (after skipping @@ -545,7 +502,7 @@ func (subst *subster) node(n ir.Node) ir.Node { m.(*ir.ClosureExpr).Func = newfn // Closure name can already have brackets, if it derives // from a generic method - newsym := makeInstName(oldfn.Nname.Sym(), subst.targs, subst.isMethod) + newsym := typecheck.MakeInstName(oldfn.Nname.Sym(), subst.targs, subst.isMethod) newfn.Nname = ir.NewNameAt(oldfn.Nname.Pos(), newsym) newfn.Nname.Func = newfn newfn.Nname.Defn = newfn @@ -704,7 +661,7 @@ func (subst *subster) typ(t *types.Type) *types.Type { if t.Kind() == types.TTYPEPARAM { for i, tp := range subst.tparams { if tp.Type == t { - return subst.targs[i].Type() + return subst.targs[i] } } // If t is a simple typeparam T, then t has the name/symbol 'T' @@ -872,7 +829,7 @@ func (subst *subster) typ(t *types.Type) *types.Type { for i, f := range t.Methods().Slice() { t2 := subst.typ(f.Type) oldsym := f.Nname.Sym() - newsym := makeInstName(oldsym, subst.targs, true) + newsym := typecheck.MakeInstName(oldsym, subst.targs, true) var nname *ir.Name if newsym.Def != nil { nname = newsym.Def.(*ir.Name) diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index 8a2c023a1a..107488e650 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -240,9 +240,9 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { // and for actually generating the methods for instantiated types. func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) { if typ.NumMethods() != 0 { - targs := make([]ir.Node, len(typ.TArgs())) + targs := make([]*types.Type, len(typ.TArgs())) for i, targ := range typ.TArgs() { - targs[i] = ir.TypeNode(g.typ1(targ)) + targs[i] = g.typ1(targ) } methods := make([]*types.Field, typ.NumMethods()) diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 9ee7a94b1f..97fb145132 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -5,6 +5,7 @@ package typecheck import ( + "bytes" "fmt" "sort" "strconv" @@ -874,3 +875,60 @@ var slist []symlink type symlink struct { field *types.Field } + +// TypesOf converts a list of nodes to a list +// of types of those nodes. +func TypesOf(x []ir.Node) []*types.Type { + r := make([]*types.Type, len(x)) + for i, n := range x { + r[i] = n.Type() + } + return r +} + +// MakeInstName makes the unique name for a stenciled generic function or method, +// based on the name of the function fy=nsym and the targs. It replaces any +// existing bracket type list in the name. makeInstName asserts that fnsym has +// brackets in its name if and only if hasBrackets is true. +// TODO(danscales): remove the assertions and the hasBrackets argument later. +// +// Names of declared generic functions have no brackets originally, so hasBrackets +// should be false. Names of generic methods already have brackets, since the new +// type parameter is specified in the generic type of the receiver (e.g. func +// (func (v *value[T]).set(...) { ... } has the original name (*value[T]).set. +// +// The standard naming is something like: 'genFn[int,bool]' for functions and +// '(*genType[int,bool]).methodName' for methods +func MakeInstName(fnsym *types.Sym, targs []*types.Type, hasBrackets bool) *types.Sym { + b := bytes.NewBufferString("") + name := fnsym.Name + i := strings.Index(name, "[") + assert(hasBrackets == (i >= 0)) + if i >= 0 { + b.WriteString(name[0:i]) + } else { + b.WriteString(name) + } + b.WriteString("[") + for i, targ := range targs { + if i > 0 { + b.WriteString(",") + } + b.WriteString(targ.String()) + } + b.WriteString("]") + if i >= 0 { + i2 := strings.Index(name[i:], "]") + assert(i2 >= 0) + b.WriteString(name[i+i2+1:]) + } + return Lookup(b.String()) +} + +// For catching problems as we add more features +// TODO(danscales): remove assertions or replace with base.FatalfAt() +func assert(p bool) { + if !p { + panic("assertion failed") + } +} -- GitLab From b69347d24acbf4ab0cff815097dc3ebea1c9b6b0 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Wed, 19 May 2021 10:04:44 -0700 Subject: [PATCH 0095/2500] [dev.typeparams] cmd/compile: simplify tparam's type We just need the type of the param, no need for a full Field. Change-Id: I851ff2628e1323d971e58d0cabbdfd93c63e1d3c Reviewed-on: https://go-review.googlesource.com/c/go/+/321229 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 17 +++++++++-------- src/cmd/compile/internal/noder/types.go | 4 ++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 87c61b2cf1..e6498e5ef8 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -217,7 +217,7 @@ type subster struct { g *irgen isMethod bool // If a method is being instantiated newf *ir.Func // Func node for the new stenciled function - tparams []*types.Field + tparams []*types.Type targs []*types.Type // The substitution map from name nodes in the generic function to the // name nodes in the new stenciled function. @@ -231,18 +231,19 @@ type subster struct { // instantiated method would still need to be transformed by later compiler // phases. func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []*types.Type, isMethod bool) *ir.Func { - var tparams []*types.Field + var tparams []*types.Type if isMethod { // Get the type params from the method receiver (after skipping // over any pointer) recvType := nameNode.Type().Recv().Type recvType = deref(recvType) - tparams = make([]*types.Field, len(recvType.RParams())) - for i, rparam := range recvType.RParams() { - tparams[i] = types.NewField(src.NoXPos, nil, rparam) - } + tparams = recvType.RParams() } else { - tparams = nameNode.Type().TParams().Fields().Slice() + fields := nameNode.Type().TParams().Fields().Slice() + tparams = make([]*types.Type, len(fields)) + for i, f := range fields { + tparams[i] = f.Type + } } gf := nameNode.Func // Pos of the instantiated function is same as the generic function @@ -660,7 +661,7 @@ func (subst *subster) typ(t *types.Type) *types.Type { if t.Kind() == types.TTYPEPARAM { for i, tp := range subst.tparams { - if tp.Type == t { + if tp == t { return subst.targs[i] } } diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index 107488e650..35ba1cd238 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -273,9 +273,9 @@ func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) { } else { meth2 = ir.NewNameAt(meth.Pos(), newsym) rparams := types2.AsSignature(m.Type()).RParams() - tparams := make([]*types.Field, len(rparams)) + tparams := make([]*types.Type, len(rparams)) for i, rparam := range rparams { - tparams[i] = types.NewField(src.NoXPos, nil, g.typ1(rparam.Type())) + tparams[i] = g.typ1(rparam.Type()) } assert(len(tparams) == len(targs)) subst := &subster{ -- GitLab From 3b40183806a30e44076dd052f25bf0ed247c45f2 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 11 May 2021 18:05:43 -0400 Subject: [PATCH 0096/2500] [dev.fuzz] cmd/go/internal/cfg: enable "gofuzzbeta" tag by default This lets users check in fuzz targets for use with this branch without breaking the build for developers using a regular version of Go. Before we merge this branch to master, this CL should be reverted. At that point, users should change the tag to go1.18 (or whichever version we land on). Change-Id: I0e21a21e415e4fb7c599abe11e61de754c74a3d7 Reviewed-on: https://go-review.googlesource.com/c/go/+/319872 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/cmd/go/internal/cfg/cfg.go | 4 +++ src/cmd/go/testdata/script/test_fuzz_tag.txt | 31 ++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 src/cmd/go/testdata/script/test_fuzz_tag.txt diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go index b47eb812b5..21a56d6df6 100644 --- a/src/cmd/go/internal/cfg/cfg.go +++ b/src/cmd/go/internal/cfg/cfg.go @@ -58,6 +58,10 @@ var ( func defaultContext() build.Context { ctxt := build.Default + + // TODO(b/187972950): remove this tag before merging to master. + ctxt.BuildTags = []string{"gofuzzbeta"} + ctxt.JoinPath = filepath.Join // back door to say "do not use go command" ctxt.GOROOT = findGOROOT() diff --git a/src/cmd/go/testdata/script/test_fuzz_tag.txt b/src/cmd/go/testdata/script/test_fuzz_tag.txt new file mode 100644 index 0000000000..07ed5d6d61 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_tag.txt @@ -0,0 +1,31 @@ +# Check that the gofuzzbeta tag is enabled by default and can be disabled. +# TODO(jayconrod,katiehockman): before merging to master, restore the old +# default and delete this test. + +[short] skip + +go test -list=. +stdout Test +stdout Fuzz + +go test -tags= + +-- go.mod -- +module fuzz + +go 1.17 +-- fuzz_test.go -- +// +build gofuzzbeta + +package fuzz + +import "testing" + +func Fuzz(f *testing.F) { + f.Add([]byte(nil)) + f.Fuzz(func(*testing.T, []byte) {}) +} + +func Test(*testing.T) {} +-- empty_test.go -- +package fuzz -- GitLab From 3f6f12972b08d8559264971e8706efb3fbfd106a Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 18 May 2021 14:48:28 -0400 Subject: [PATCH 0097/2500] [dev.typeparams] runtime: use internal/abi.FuncPCABI0 for sigtramp PC on DragonflyBSD Same as CL 313230, for DragonflyBSD. sigtramp is the only one we need. Change-Id: Ic11d0aedc7422512b43b2e4505e8f95056f915bd Reviewed-on: https://go-review.googlesource.com/c/go/+/321312 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: Than McIntosh Reviewed-by: Michael Knyszek TryBot-Result: Go Bot --- src/runtime/os_dragonfly.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/runtime/os_dragonfly.go b/src/runtime/os_dragonfly.go index 5c688a3109..ab0ad4728f 100644 --- a/src/runtime/os_dragonfly.go +++ b/src/runtime/os_dragonfly.go @@ -5,6 +5,7 @@ package runtime import ( + "internal/abi" "runtime/internal/sys" "unsafe" ) @@ -227,7 +228,7 @@ func setsig(i uint32, fn uintptr) { sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART sa.sa_mask = sigset_all if fn == funcPC(sighandler) { - fn = funcPC(sigtramp) + fn = abi.FuncPCABI0(sigtramp) } sa.sa_sigaction = fn sigaction(i, &sa, nil) -- GitLab From eff66248ea242c2611a9a0e2be47a762073e81b2 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 18 May 2021 19:03:00 -0700 Subject: [PATCH 0098/2500] [dev.typeparams] cmd/compile/internal/types2: implement package height This CL extends types2 with package height information, styled after the way it works already in cmd/compile: - A new NewPackageHeight entry point for constructing packages with explicit height information, and a corresponding Height accessor method. - The types2 importer is updated to provide package height for imported packages. - The types2 type checker sets height based on imported packages. - Adds an assertion to irgen to verify that types1 and types2 calculated the same height for the source package. - Func.less's ordering incorporates package height to match types.Sym.less and is generalized to object.less. - sortTypes (used for sorting embedded types) now sorts defined types using object.less as well. Change-Id: Id4dbbb627aef405cc7438d611cbdd5a5bd97fc96 Reviewed-on: https://go-review.googlesource.com/c/go/+/321231 Run-TryBot: Matthew Dempsky Trust: Matthew Dempsky Trust: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/importer/iimport.go | 13 ++-- src/cmd/compile/internal/noder/irgen.go | 1 + src/cmd/compile/internal/types2/object.go | 69 +++++++++++--------- src/cmd/compile/internal/types2/package.go | 14 +++- src/cmd/compile/internal/types2/resolver.go | 10 +++ src/cmd/compile/internal/types2/typexpr.go | 10 +-- 6 files changed, 76 insertions(+), 41 deletions(-) diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index 5c02f837ef..b91b209d35 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -118,17 +118,22 @@ func iImportData(imports map[string]*types2.Package, data []byte, path string) ( pkgPathOff := r.uint64() pkgPath := p.stringAt(pkgPathOff) pkgName := p.stringAt(r.uint64()) - _ = r.uint64() // package height; unused by go/types + pkgHeight := int(r.uint64()) if pkgPath == "" { pkgPath = path } pkg := imports[pkgPath] if pkg == nil { - pkg = types2.NewPackage(pkgPath, pkgName) + pkg = types2.NewPackageHeight(pkgPath, pkgName, pkgHeight) imports[pkgPath] = pkg - } else if pkg.Name() != pkgName { - errorf("conflicting names %s and %s for package %q", pkg.Name(), pkgName, path) + } else { + if pkg.Name() != pkgName { + errorf("conflicting names %s and %s for package %q", pkg.Name(), pkgName, path) + } + if pkg.Height() != pkgHeight { + errorf("conflicting heights %v and %v for package %q", pkg.Height(), pkgHeight, path) + } } p.pkgCache[pkgPathOff] = pkg diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index 3e0d3285ab..2a9f0e99d8 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -132,6 +132,7 @@ Outer: } } } + assert(myheight == g.self.Height()) types.LocalPkg.Height = myheight // 2. Process all package-block type declarations. As with imports, diff --git a/src/cmd/compile/internal/types2/object.go b/src/cmd/compile/internal/types2/object.go index 844bc34b6a..8ed55f1dbf 100644 --- a/src/cmd/compile/internal/types2/object.go +++ b/src/cmd/compile/internal/types2/object.go @@ -186,6 +186,45 @@ func (obj *object) sameId(pkg *Package, name string) bool { return pkg.path == obj.pkg.path } +// less reports whether object a is ordered before object b. +// +// Objects are ordered nil before non-nil, exported before +// non-exported, then by name, and finally (for non-exported +// functions) by package height and path. +func (a *object) less(b *object) bool { + if a == b { + return false + } + + // Nil before non-nil. + if a == nil { + return true + } + if b == nil { + return false + } + + // Exported functions before non-exported. + ea := isExported(a.name) + eb := isExported(b.name) + if ea != eb { + return ea + } + + // Order by name and then (for non-exported names) by package. + if a.name != b.name { + return a.name < b.name + } + if !ea { + if a.pkg.height != b.pkg.height { + return a.pkg.height < b.pkg.height + } + return a.pkg.path < b.pkg.path + } + + return false +} + // A PkgName represents an imported Go package. // PkgNames don't have a type. type PkgName struct { @@ -329,36 +368,6 @@ func (obj *Func) FullName() string { // Scope returns the scope of the function's body block. func (obj *Func) Scope() *Scope { return obj.typ.(*Signature).scope } -// Less reports whether function a is ordered before function b. -// -// Functions are ordered exported before non-exported, then by name, -// and finally (for non-exported functions) by package path. -// -// TODO(gri) The compiler also sorts by package height before package -// path for non-exported names. -func (a *Func) less(b *Func) bool { - if a == b { - return false - } - - // Exported functions before non-exported. - ea := isExported(a.name) - eb := isExported(b.name) - if ea != eb { - return ea - } - - // Order by name and then (for non-exported names) by package. - if a.name != b.name { - return a.name < b.name - } - if !ea { - return a.pkg.path < b.pkg.path - } - - return false -} - func (*Func) isDependency() {} // a function may be a dependency of an initialization expression // A Label represents a declared label. diff --git a/src/cmd/compile/internal/types2/package.go b/src/cmd/compile/internal/types2/package.go index 31b1e71787..c5804a05ad 100644 --- a/src/cmd/compile/internal/types2/package.go +++ b/src/cmd/compile/internal/types2/package.go @@ -13,8 +13,9 @@ type Package struct { path string name string scope *Scope - complete bool imports []*Package + height int + complete bool fake bool // scope lookup errors are silently dropped if package is fake (internal use only) cgo bool // uses of this package will be rewritten into uses of declarations from _cgo_gotypes.go } @@ -22,8 +23,14 @@ type Package struct { // NewPackage returns a new Package for the given package path and name. // The package is not complete and contains no explicit imports. func NewPackage(path, name string) *Package { + return NewPackageHeight(path, name, 0) +} + +// NewPackageHeight is like NewPackage, but allows specifying the +// package's height. +func NewPackageHeight(path, name string, height int) *Package { scope := NewScope(Universe, nopos, nopos, fmt.Sprintf("package %q", path)) - return &Package{path: path, name: name, scope: scope} + return &Package{path: path, name: name, scope: scope, height: height} } // Path returns the package path. @@ -32,6 +39,9 @@ func (pkg *Package) Path() string { return pkg.path } // Name returns the package name. func (pkg *Package) Name() string { return pkg.name } +// Height returns the package height. +func (pkg *Package) Height() int { return pkg.height } + // SetName sets the package name. func (pkg *Package) SetName(name string) { pkg.name = name } diff --git a/src/cmd/compile/internal/types2/resolver.go b/src/cmd/compile/internal/types2/resolver.go index ef49a8b48d..9b1482b14e 100644 --- a/src/cmd/compile/internal/types2/resolver.go +++ b/src/cmd/compile/internal/types2/resolver.go @@ -196,6 +196,7 @@ func (check *Checker) importPackage(pos syntax.Pos, path, dir string) *Package { // methods with receiver base type names. func (check *Checker) collectObjects() { pkg := check.pkg + pkg.height = 0 // pkgImports is the set of packages already imported by any package file seen // so far. Used to avoid duplicate entries in pkg.imports. Allocate and populate @@ -253,6 +254,15 @@ func (check *Checker) collectObjects() { continue } + if imp == Unsafe { + // typecheck ignores imports of package unsafe for + // calculating height. + // TODO(mdempsky): Revisit this. This seems fine, but I + // don't remember explicitly considering this case. + } else if h := imp.height + 1; h > pkg.height { + pkg.height = h + } + // local name overrides imported package name name := imp.name if s.LocalPkgName != nil { diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index a1663d2aa0..7fb914cd7e 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -1055,14 +1055,14 @@ func sortTypes(list []Type) { type byUniqueTypeName []Type func (a byUniqueTypeName) Len() int { return len(a) } -func (a byUniqueTypeName) Less(i, j int) bool { return sortName(a[i]) < sortName(a[j]) } +func (a byUniqueTypeName) Less(i, j int) bool { return sortObj(a[i]).less(sortObj(a[j])) } func (a byUniqueTypeName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func sortName(t Type) string { +func sortObj(t Type) *object { if named := asNamed(t); named != nil { - return named.obj.Id() + return &named.obj.object } - return "" + return nil } func sortMethods(list []*Func) { @@ -1082,7 +1082,7 @@ func assertSortedMethods(list []*Func) { type byUniqueMethodName []*Func func (a byUniqueMethodName) Len() int { return len(a) } -func (a byUniqueMethodName) Less(i, j int) bool { return a[i].less(a[j]) } +func (a byUniqueMethodName) Less(i, j int) bool { return a[i].less(&a[j].object) } func (a byUniqueMethodName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (check *Checker) tag(t *syntax.BasicLit) string { -- GitLab From 6bdfff112f098b371bca718efffa47225cc1b608 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 19 May 2021 16:25:31 -0700 Subject: [PATCH 0099/2500] [dev.typeparams] cmd/compile/internal/types2: use correct type parameter list in missingMethod For #46275 Change-Id: Iaed9d8ba034ad793e5c57f2be174f01a535fee95 Reviewed-on: https://go-review.googlesource.com/c/go/+/321232 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/lookup.go | 21 ++++++++++++++- .../types2/testdata/fixedbugs/issue46275.go2 | 26 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue46275.go2 diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index 78299502e9..eb2b17dd4d 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -333,6 +333,9 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, if len(ftyp.tparams) != len(mtyp.tparams) { return m, f } + if !acceptMethodTypeParams && len(ftyp.tparams) > 0 { + panic("internal error: method with type parameters") + } // If the methods have type parameters we don't care whether they // are the same or not, as long as they match up. Use unification @@ -386,6 +389,9 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, if len(ftyp.tparams) != len(mtyp.tparams) { return m, f } + if !acceptMethodTypeParams && len(ftyp.tparams) > 0 { + panic("internal error: method with type parameters") + } // If V is a (instantiated) generic type, its methods are still // parameterized using the original (declaration) receiver type @@ -413,7 +419,20 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // TODO(gri) is this always correct? what about type bounds? // (Alternative is to rename/subst type parameters and compare.) u := newUnifier(check, true) - u.x.init(ftyp.tparams) + if len(ftyp.tparams) > 0 { + // We reach here only if we accept method type parameters. + // In this case, unification must consider any receiver + // and method type parameters as "free" type parameters. + assert(acceptMethodTypeParams) + // We don't have a test case for this at the moment since + // we can't parse method type parameters. Keeping the + // unimplemented call so that we test this code if we + // enable method type parameters. + unimplemented() + u.x.init(append(ftyp.rparams, ftyp.tparams...)) + } else { + u.x.init(ftyp.rparams) + } if !u.unify(ftyp, mtyp) { return m, f } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46275.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46275.go2 new file mode 100644 index 0000000000..f41ae26e4b --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46275.go2 @@ -0,0 +1,26 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package issue46275 + +type N[T any] struct { + *N[T] + t T +} + +func (n *N[T]) Elem() T { + return n.t +} + +type I interface { + Elem() string +} + +func _() { + var n1 *N[string] + var _ I = n1 + type NS N[string] + var n2 *NS + var _ I = n2 +} -- GitLab From a5cd89b8c36df906e9f0e2932b83d66a43b5e745 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 19 May 2021 17:20:45 -0400 Subject: [PATCH 0100/2500] [dev.typeparams] runtime: use internal/abi.FuncPCABI0 and cgo_unsafe_args for Solaris syscall wrappers Similar to CL 313230, for Solaris (and Illumos). Also mark functions that take address of one arg and pass to asmcgocall cgo_unsafe_args, as it effectively takes address of all args. Change-Id: I4281dd774719fb21ecba82e5ed94a609378a3df5 Reviewed-on: https://go-review.googlesource.com/c/go/+/321314 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/runtime/os3_solaris.go | 8 +++++--- src/runtime/os_solaris.go | 3 +++ src/runtime/syscall_solaris.go | 10 ++++++++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/runtime/os3_solaris.go b/src/runtime/os3_solaris.go index 39ef831acf..3b1a773ee2 100644 --- a/src/runtime/os3_solaris.go +++ b/src/runtime/os3_solaris.go @@ -5,6 +5,7 @@ package runtime import ( + "internal/abi" "runtime/internal/sys" "unsafe" ) @@ -172,7 +173,7 @@ func newosproc(mp *m) { // Disable signals during create, so that the new thread starts // with signals disabled. It will enable them in minit. sigprocmask(_SIG_SETMASK, &sigset_all, &oset) - ret = pthread_create(&tid, &attr, funcPC(tstart_sysvicall), unsafe.Pointer(mp)) + ret = pthread_create(&tid, &attr, abi.FuncPCABI0(tstart_sysvicall), unsafe.Pointer(mp)) sigprocmask(_SIG_SETMASK, &oset, nil) if ret != 0 { print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", ret, ")\n") @@ -215,7 +216,7 @@ func miniterrno() // Called to initialize a new m (including the bootstrap m). // Called on the new thread, cannot allocate memory. func minit() { - asmcgocall(unsafe.Pointer(funcPC(miniterrno)), unsafe.Pointer(&libc____errno)) + asmcgocall(unsafe.Pointer(abi.FuncPCABI0(miniterrno)), unsafe.Pointer(&libc____errno)) minitSignals() @@ -242,7 +243,7 @@ func setsig(i uint32, fn uintptr) { sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART sa.sa_mask = sigset_all if fn == funcPC(sighandler) { - fn = funcPC(sigtramp) + fn = abi.FuncPCABI0(sigtramp) } *((*uintptr)(unsafe.Pointer(&sa._funcptr))) = fn sigaction(i, &sa, nil) @@ -390,6 +391,7 @@ func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) (un } //go:nosplit +//go:cgo_unsafe_args func doMmap(addr, n, prot, flags, fd, off uintptr) (uintptr, uintptr) { var libcall libcall libcall.fn = uintptr(unsafe.Pointer(&libc_mmap)) diff --git a/src/runtime/os_solaris.go b/src/runtime/os_solaris.go index 89129e5f1a..8ac1b08f69 100644 --- a/src/runtime/os_solaris.go +++ b/src/runtime/os_solaris.go @@ -179,6 +179,7 @@ func sysvicall3Err(fn *libcFunc, a1, a2, a3 uintptr) (r1, err uintptr) { } //go:nosplit +//go:cgo_unsafe_args func sysvicall4(fn *libcFunc, a1, a2, a3, a4 uintptr) uintptr { // Leave caller's PC/SP around for traceback. gp := getg() @@ -208,6 +209,7 @@ func sysvicall4(fn *libcFunc, a1, a2, a3, a4 uintptr) uintptr { } //go:nosplit +//go:cgo_unsafe_args func sysvicall5(fn *libcFunc, a1, a2, a3, a4, a5 uintptr) uintptr { // Leave caller's PC/SP around for traceback. gp := getg() @@ -237,6 +239,7 @@ func sysvicall5(fn *libcFunc, a1, a2, a3, a4, a5 uintptr) uintptr { } //go:nosplit +//go:cgo_unsafe_args func sysvicall6(fn *libcFunc, a1, a2, a3, a4, a5, a6 uintptr) uintptr { // Leave caller's PC/SP around for traceback. gp := getg() diff --git a/src/runtime/syscall_solaris.go b/src/runtime/syscall_solaris.go index 094516927f..15be8e1c61 100644 --- a/src/runtime/syscall_solaris.go +++ b/src/runtime/syscall_solaris.go @@ -35,6 +35,7 @@ func pipe1() // declared for vet; do NOT call //go:nosplit //go:linkname syscall_sysvicall6 +//go:cgo_unsafe_args func syscall_sysvicall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) { call := libcall{ fn: fn, @@ -49,6 +50,7 @@ func syscall_sysvicall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err //go:nosplit //go:linkname syscall_rawsysvicall6 +//go:cgo_unsafe_args func syscall_rawsysvicall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) { call := libcall{ fn: fn, @@ -104,6 +106,7 @@ func syscall_dup2(oldfd, newfd uintptr) (val, err uintptr) { //go:nosplit //go:linkname syscall_execve +//go:cgo_unsafe_args func syscall_execve(path, argv, envp uintptr) (err uintptr) { call := libcall{ fn: uintptr(unsafe.Pointer(&libc_execve)), @@ -123,6 +126,7 @@ func syscall_exit(code uintptr) { //go:nosplit //go:linkname syscall_fcntl +//go:cgo_unsafe_args func syscall_fcntl(fd, cmd, arg uintptr) (val, err uintptr) { call := libcall{ fn: uintptr(unsafe.Pointer(&libc_fcntl)), @@ -181,6 +185,7 @@ func syscall_getpid() (pid, err uintptr) { //go:nosplit //go:linkname syscall_ioctl +//go:cgo_unsafe_args func syscall_ioctl(fd, req, arg uintptr) (err uintptr) { call := libcall{ fn: uintptr(unsafe.Pointer(&libc_ioctl)), @@ -234,6 +239,7 @@ func syscall_setgid(gid uintptr) (err uintptr) { //go:nosplit //go:linkname syscall_setgroups +//go:cgo_unsafe_args func syscall_setgroups(ngid, gid uintptr) (err uintptr) { call := libcall{ fn: uintptr(unsafe.Pointer(&libc_setgroups)), @@ -270,6 +276,7 @@ func syscall_setuid(uid uintptr) (err uintptr) { //go:nosplit //go:linkname syscall_setpgid +//go:cgo_unsafe_args func syscall_setpgid(pid, pgid uintptr) (err uintptr) { call := libcall{ fn: uintptr(unsafe.Pointer(&libc_setpgid)), @@ -281,6 +288,7 @@ func syscall_setpgid(pid, pgid uintptr) (err uintptr) { } //go:linkname syscall_syscall +//go:cgo_unsafe_args func syscall_syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) { call := libcall{ fn: uintptr(unsafe.Pointer(&libc_syscall)), @@ -294,6 +302,7 @@ func syscall_syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) { } //go:linkname syscall_wait4 +//go:cgo_unsafe_args func syscall_wait4(pid uintptr, wstatus *uint32, options uintptr, rusage unsafe.Pointer) (wpid int, err uintptr) { call := libcall{ fn: uintptr(unsafe.Pointer(&libc_wait4)), @@ -308,6 +317,7 @@ func syscall_wait4(pid uintptr, wstatus *uint32, options uintptr, rusage unsafe. //go:nosplit //go:linkname syscall_write +//go:cgo_unsafe_args func syscall_write(fd, buf, nbyte uintptr) (n, err uintptr) { call := libcall{ fn: uintptr(unsafe.Pointer(&libc_write)), -- GitLab From 02117775d1550653bd4f58fdaa12b1e906409052 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 19 May 2021 18:13:45 -0400 Subject: [PATCH 0101/2500] [dev.typeparams] cmd/compile, runtime: do not zero X15 on Plan 9 On Plan 9, we cannot use SSE registers in note handlers, so we don't use X15 for zeroing (MOVOstorezero and DUFFZERO). Do not zero X15 on Plan 9. Change-Id: I2b083b01b27965611cb83d19afd66b383dc77846 Reviewed-on: https://go-review.googlesource.com/c/go/+/321329 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/compile/internal/amd64/ssa.go | 12 +++++++++--- src/runtime/asm_amd64.s | 2 ++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/amd64/ssa.go b/src/cmd/compile/internal/amd64/ssa.go index ca5f36e775..7e2dc41928 100644 --- a/src/cmd/compile/internal/amd64/ssa.go +++ b/src/cmd/compile/internal/amd64/ssa.go @@ -1005,14 +1005,18 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { case ssa.OpAMD64CALLstatic: if buildcfg.Experiment.RegabiG && s.ABI == obj.ABI0 && v.Aux.(*ssa.AuxCall).Fn.ABI() == obj.ABIInternal { // zeroing X15 when entering ABIInternal from ABI0 - opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15) + if buildcfg.GOOS != "plan9" { // do not use SSE on Plan 9 + opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15) + } // set G register from TLS getgFromTLS(s, x86.REG_R14) } s.Call(v) if buildcfg.Experiment.RegabiG && s.ABI == obj.ABIInternal && v.Aux.(*ssa.AuxCall).Fn.ABI() == obj.ABI0 { // zeroing X15 when entering ABIInternal from ABI0 - opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15) + if buildcfg.GOOS != "plan9" { // do not use SSE on Plan 9 + opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15) + } // set G register from TLS getgFromTLS(s, x86.REG_R14) } @@ -1306,7 +1310,9 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) { case ssa.BlockRetJmp: if buildcfg.Experiment.RegabiG && s.ABI == obj.ABI0 && b.Aux.(*obj.LSym).ABI() == obj.ABIInternal { // zeroing X15 when entering ABIInternal from ABI0 - opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15) + if buildcfg.GOOS != "plan9" { // do not use SSE on Plan 9 + opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15) + } // set G register from TLS getgFromTLS(s, x86.REG_R14) } diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index 14f29e1964..5990ce54c8 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -1600,7 +1600,9 @@ TEXT ·sigpanic0(SB),NOSPLIT,$0-0 #ifdef GOEXPERIMENT_regabig get_tls(R14) MOVQ g(R14), R14 +#ifndef GOOS_plan9 XORPS X15, X15 +#endif #endif JMP ·sigpanic(SB) -- GitLab From ed2001232acd78319bd028a2e8775072c9339e1b Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 19 May 2021 17:33:32 -0400 Subject: [PATCH 0102/2500] [dev.typeparams] runtime: use internal/abi.FuncPCABI0 for sigtramp PC on Plan 9 Same as CL 313230, for Plan 9. Change-Id: I0e99c095856c4b21b89abdffa4c0699b24ea9428 Reviewed-on: https://go-review.googlesource.com/c/go/+/321330 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek Reviewed-by: Than McIntosh --- src/runtime/os_plan9.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/runtime/os_plan9.go b/src/runtime/os_plan9.go index 4d428346f0..975d460a7d 100644 --- a/src/runtime/os_plan9.go +++ b/src/runtime/os_plan9.go @@ -5,6 +5,7 @@ package runtime import ( + "internal/abi" "runtime/internal/atomic" "unsafe" ) @@ -346,7 +347,7 @@ func getRandomData(r []byte) { func initsig(preinit bool) { if !preinit { - notify(unsafe.Pointer(funcPC(sigtramp))) + notify(unsafe.Pointer(abi.FuncPCABI0(sigtramp))) } } -- GitLab From 240d6d00ca561b7d293976e758642addb467d6b9 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 19 May 2021 17:34:19 -0400 Subject: [PATCH 0103/2500] [dev.typeparams] cmd/link: mangle symbol ABI name on Plan 9 It is probably not strictly necessary (as we don't support external linking on Plan 9). Do it for consistency (and less confusion). Change-Id: I0b48562061273ccbd4be83db4a981b8e465b1c95 Reviewed-on: https://go-review.googlesource.com/c/go/+/321331 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/link/internal/ld/symtab.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index 00f557875a..1f5e333cfd 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -300,6 +300,7 @@ func putplan9sym(ctxt *Link, ldr *loader.Loader, s loader.Sym, char SymbolType) ctxt.Out.Write8(uint8(t + 0x80)) /* 0x80 is variable length */ name := ldr.SymName(s) + name = mangleABIName(ctxt, ldr, s, name) ctxt.Out.WriteString(name) ctxt.Out.Write8(0) -- GitLab From 382c5dd5f754392444fbe2c3489d09b2f36f3939 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 14 May 2021 15:04:51 -0400 Subject: [PATCH 0104/2500] [dev.typeparams] internal/buildcfg: turn on register ABI on all AMD64 platforms Register ABI is already enabled by default on AMD64 on Linux (including Android), macOS, and Windows. This CL enables it on the rest, specifically, on FreeBSD, OpenBSD, NetBSD, DragonflyBSD, Solaris (including Illumos), iOS (simulator), and Plan 9. Change-Id: I80fa20c8bbc8d67b16a19f71b65422e890210ab5 Reviewed-on: https://go-review.googlesource.com/c/go/+/321332 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: Than McIntosh Reviewed-by: David Chase Reviewed-by: Michael Knyszek --- src/internal/buildcfg/exp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go index 2435a79dce..417d87cf4a 100644 --- a/src/internal/buildcfg/exp.go +++ b/src/internal/buildcfg/exp.go @@ -20,7 +20,7 @@ import ( // was built with.) var Experiment goexperiment.Flags = parseExperiments() -var regabiSupported = GOARCH == "amd64" && (GOOS == "android" || GOOS == "linux" || GOOS == "darwin" || GOOS == "windows") +var regabiSupported = GOARCH == "amd64" // experimentBaseline specifies the experiment flags that are enabled by // default in the current toolchain. This is, in effect, the "control" -- GitLab From 468efd5e2fb05860430c0bdede4e1cd0f8c07f65 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Thu, 20 May 2021 15:35:55 -0700 Subject: [PATCH 0105/2500] [dev.typeparams] cmd/compile: change method instantiations back to being functions Change all instantiated methods to being functions again. We found that this is easier for adding the dictionary argument consistently. A method wrapper will usually be added around the instantiation call, so that eliminate the inconsistency in the type of the top-level method and the the associated function node type. Change-Id: I9034a0c5cc901e7a89e60756bff574c1346adbc7 Reviewed-on: https://go-review.googlesource.com/c/go/+/321609 Run-TryBot: Dan Scales Reviewed-by: Keith Randall TryBot-Result: Go Bot Trust: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 52 ++++++++++------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index e6498e5ef8..f9cf6d8a1a 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -86,21 +86,20 @@ func (g *irgen) stencil() { // instantiation. call := n.(*ir.CallExpr) inst := call.X.(*ir.InstExpr) + // Replace the OFUNCINST with a direct reference to the + // new stenciled function st := g.getInstantiationForNode(inst) + call.X = st.Nname if inst.X.Op() == ir.OCALLPART { - // Replace the OFUNCINST with the selector - // expression, and update the selector expression - // to refer to the new stenciled function. - call.X = inst.X - se := call.X.(*ir.SelectorExpr) - se.Selection = types.NewField(se.Pos(), se.Sel, st.Type()) - se.Selection.Nname = st.Nname - se.SetOp(ir.ODOTMETH) - se.SetType(st.Type()) - } else { - // Replace the OFUNCINST with a direct reference to the - // new stenciled function - call.X = st.Nname + // When we create an instantiation of a method + // call, we make it a function. So, move the + // receiver to be the first arg of the function + // call. + withRecv := make([]ir.Node, len(call.Args)+1) + dot := inst.X.(*ir.SelectorExpr) + withRecv[0] = dot.X + copy(withRecv[1:], call.Args) + call.Args = withRecv } // Transform the Call now, which changes OCALL // to OCALLFUNC and does typecheckaste/assignconvfn. @@ -166,9 +165,13 @@ func (g *irgen) instantiateMethods() { baseSym := typ.Sym().Pkg.Lookup(genericTypeName(typ.Sym())) baseType := baseSym.Def.(*ir.Name).Type() for j, m := range typ.Methods().Slice() { + name := m.Nname.(*ir.Name) baseNname := baseType.Methods().Slice()[j].Nname.(*ir.Name) - f := g.getInstantiation(baseNname, typ.RParams(), true) - m.Nname = f.Nname + // Note: we are breaking an invariant here: + // m.Nname is now not equal m.Nname.Func.Nname. + // m.Nname has the type of a method, whereas m.Nname.Func.Nname has + // the type of a function, since it is an function instantiation. + name.Func = g.getInstantiation(baseNname, typ.RParams(), true) } } g.instTypeList = nil @@ -279,20 +282,11 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []*type // the function type. The current function type has no Nname fields set, // because it came via conversion from the types2 type. oldt := nameNode.Type() - dcl := newf.Dcl - var newrecv *types.Field - if oldt.Recv() != nil { - newrecv = subst.fields(ir.PPARAM, oldt.Recvs().FieldSlice(), dcl)[0] - if newrecv.Nname != nil { - // If we found the receiver in the dcl list, then skip it - // when we scan for the remaining params below. - assert(newrecv.Nname == dcl[0]) - dcl = dcl[1:] - } - } - newt := types.NewSignature(oldt.Pkg(), newrecv, nil, - subst.fields(ir.PPARAM, oldt.Params().FieldSlice(), dcl), - subst.fields(ir.PPARAMOUT, oldt.Results().FieldSlice(), dcl)) + // We also transform a generic method type to the corresponding + // instantiated function type where the receiver is the first parameter. + newt := types.NewSignature(oldt.Pkg(), nil, nil, + subst.fields(ir.PPARAM, append(oldt.Recvs().FieldSlice(), oldt.Params().FieldSlice()...), newf.Dcl), + subst.fields(ir.PPARAMOUT, oldt.Results().FieldSlice(), newf.Dcl)) newf.Nname.SetType(newt) ir.MarkFunc(newf.Nname) -- GitLab From 15ad61aff5e6b7774101483a933b3d975ae9bae8 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 13 Apr 2021 15:37:36 -0700 Subject: [PATCH 0106/2500] [dev.typeparams] cmd/compile: get export/import of generic types & functions working The general idea is that we now export/import typeparams, typeparam lists for generic types and functions, and instantiated types (instantiations of generic types with either new typeparams or concrete types). This changes the export format -- the next CL in the stack adds the export versions and checks for it in the appropriate places. We always export/import generic function bodies, using the same code that we use for exporting/importing the bodies of inlineable functions. To avoid complicated scoping, we consider all type params as unique and give them unique names for types1. We therefore include the types2 ids (subscripts) in the export format and re-create on import. We always access the same unique types1 typeParam type for the same typeparam name. We create fully-instantiated generic types and functions in the original source package. We do an extra NeedRuntimeType() call to make sure that the correct DWARF information is written out. We call SetDupOK(true) for the functions/methods to have the linker automatically drop duplicate instantiations. Other miscellaneous details: - Export/import of typeparam bounds works for methods (but not typelists) for now, but will change with the typeset changes. - Added a new types.Instantiate function roughly analogous to the types2.Instantiate function recently added. - Always access methods info from the original/base generic type, since the methods of an instantiated type are not filled in (in types2 or types1). - New field OrigSym in types.Type to keep track of base generic type that instantiated type was based on. We use the generic type's symbol (OrigSym) as the link, rather than a Type pointer, since we haven't always created the base type yet when we want to set the link (during types2 to types1 conversion). - Added types2.AsTypeParam(), (*types2.TypeParam).SetId() - New test minimp.dir, which tests use of generic function Min across packages. Another test stringimp.dir, which also exports a generic function Stringify across packages, where the type param has a bound (Stringer) as well. New test pairimp.dir, which tests use of generic type Pair (with no methods) across packages. - New test valimp.dir, which tests use of generic type (with methods and related functions) across packages. - Modified several other tests (adder.go, settable.go, smallest.go, stringable.go, struct.go, sum.go) to export their generic functions/types to show that generic functions/types can be exported successfully (but this doesn't test import). Change-Id: Ie61ce9d54a46d368ddc7a76c41399378963bb57f Reviewed-on: https://go-review.googlesource.com/c/go/+/319930 Trust: Dan Scales Trust: Robert Griesemer Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/gc/export.go | 12 +- src/cmd/compile/internal/importer/iimport.go | 85 ++++++++ src/cmd/compile/internal/noder/decl.go | 14 +- src/cmd/compile/internal/noder/expr.go | 8 +- src/cmd/compile/internal/noder/irgen.go | 6 +- src/cmd/compile/internal/noder/object.go | 10 +- src/cmd/compile/internal/noder/stencil.go | 69 +++---- src/cmd/compile/internal/noder/types.go | 35 +++- .../compile/internal/reflectdata/reflect.go | 8 +- src/cmd/compile/internal/typecheck/iexport.go | 97 ++++++++- src/cmd/compile/internal/typecheck/iimport.go | 188 +++++++++++++++--- src/cmd/compile/internal/typecheck/subr.go | 10 +- src/cmd/compile/internal/types/sizeof_test.go | 2 +- src/cmd/compile/internal/types/type.go | 21 +- src/cmd/compile/internal/types2/api_test.go | 14 +- src/cmd/compile/internal/types2/type.go | 10 + src/cmd/compile/internal/types2/typestring.go | 7 + src/go/internal/gcimporter/gcimporter_test.go | 3 +- src/go/internal/gcimporter/iimport.go | 20 ++ test/typeparam/adder.go | 8 +- test/typeparam/min.go | 11 +- test/typeparam/minimp.dir/a.go | 16 ++ test/typeparam/minimp.dir/main.go | 38 ++++ test/typeparam/minimp.go | 7 + test/typeparam/pair.go | 1 + test/typeparam/pairimp.dir/a.go | 10 + test/typeparam/pairimp.dir/main.go | 27 +++ test/typeparam/pairimp.go | 7 + test/typeparam/settable.go | 10 +- test/typeparam/smallest.go | 6 +- test/typeparam/stringable.go | 8 +- test/typeparam/stringerimp.dir/a.go | 16 ++ test/typeparam/stringerimp.dir/main.go | 38 ++++ test/typeparam/stringerimp.go | 7 + test/typeparam/struct.go | 34 ++-- test/typeparam/sum.go | 16 +- test/typeparam/valimp.dir/a.go | 32 +++ test/typeparam/valimp.dir/main.go | 56 ++++++ test/typeparam/valimp.go | 7 + 39 files changed, 816 insertions(+), 158 deletions(-) create mode 100644 test/typeparam/minimp.dir/a.go create mode 100644 test/typeparam/minimp.dir/main.go create mode 100644 test/typeparam/minimp.go create mode 100644 test/typeparam/pairimp.dir/a.go create mode 100644 test/typeparam/pairimp.dir/main.go create mode 100644 test/typeparam/pairimp.go create mode 100644 test/typeparam/stringerimp.dir/a.go create mode 100644 test/typeparam/stringerimp.dir/main.go create mode 100644 test/typeparam/stringerimp.go create mode 100644 test/typeparam/valimp.dir/a.go create mode 100644 test/typeparam/valimp.dir/main.go create mode 100644 test/typeparam/valimp.go diff --git a/src/cmd/compile/internal/gc/export.go b/src/cmd/compile/internal/gc/export.go index 2137f1d196..e19d52fa95 100644 --- a/src/cmd/compile/internal/gc/export.go +++ b/src/cmd/compile/internal/gc/export.go @@ -25,11 +25,6 @@ func exportf(bout *bio.Writer, format string, args ...interface{}) { func dumpexport(bout *bio.Writer) { p := &exporter{marked: make(map[*types.Type]bool)} for _, n := range typecheck.Target.Exports { - // Must catch it here rather than Export(), because the type can be - // not fully set (still TFORW) when Export() is called. - if n.Type() != nil && n.Type().HasTParam() { - base.Fatalf("Cannot (yet) export a generic type: %v", n) - } p.markObject(n) } @@ -103,6 +98,11 @@ func (p *exporter) markType(t *types.Type) { return } p.marked[t] = true + if t.HasTParam() { + // Don't deal with any generic types or their methods, since we + // will only be inlining actual instantiations, not generic methods. + return + } // If this is a named type, mark all of its associated // methods. Skip interface types because t.Methods contains @@ -152,6 +152,8 @@ func (p *exporter) markType(t *types.Type) { } case types.TINTER: + // TODO(danscales) - will have to deal with the types in interface + // elements here when implemented in types2 and represented in types1. for _, f := range t.AllMethods().Slice() { if types.IsExported(f.Sym.Name) { p.markType(f.Type) diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index b91b209d35..a4637ec34f 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -57,6 +57,8 @@ const ( signatureType structType interfaceType + typeParamType + instType ) const io_SeekCurrent = 1 // io.SeekCurrent (not defined in Go 1.4) @@ -292,15 +294,20 @@ func (r *importReader) obj(name string) { r.declare(types2.NewConst(pos, r.currPkg, name, typ, val)) case 'F': + tparams := r.tparamList() sig := r.signature(nil) + sig.SetTParams(tparams) r.declare(types2.NewFunc(pos, r.currPkg, name, sig)) case 'T': + tparams := r.tparamList() + // Types can be recursive. We need to setup a stub // declaration before recursing. obj := types2.NewTypeName(pos, r.currPkg, name, nil) named := types2.NewNamed(obj, nil, nil) + named.SetTParams(tparams) r.declare(obj) underlying := r.p.typAt(r.uint64(), named).Underlying() @@ -313,6 +320,18 @@ func (r *importReader) obj(name string) { recv := r.param() msig := r.signature(recv) + // If the receiver has any targs, set those as the + // rparams of the method (since those are the + // typeparams being used in the method sig/body). + targs := baseType(msig.Recv().Type()).TArgs() + if len(targs) > 0 { + rparams := make([]*types2.TypeName, len(targs)) + for i, targ := range targs { + rparams[i] = types2.AsTypeParam(targ).Obj() + } + msig.SetRParams(rparams) + } + named.AddMethod(types2.NewFunc(mpos, r.currPkg, mname, msig)) } } @@ -571,6 +590,49 @@ func (r *importReader) doType(base *types2.Named) types2.Type { typ := types2.NewInterfaceType(methods, embeddeds) r.p.interfaceList = append(r.p.interfaceList, typ) return typ + + case typeParamType: + r.currPkg = r.pkg() + pos := r.pos() + name := r.string() + + // Extract the subscript value from the type param name. We export + // and import the subscript value, so that all type params have + // unique names. + sub := uint64(0) + startsub := -1 + for i, r := range name { + if '₀' <= r && r < '₀'+10 { + if startsub == -1 { + startsub = i + } + sub = sub*10 + uint64(r-'₀') + } + } + if startsub >= 0 { + name = name[:startsub] + } + index := int(r.int64()) + bound := r.typ() + tn := types2.NewTypeName(pos, r.currPkg, name, nil) + t := (*types2.Checker)(nil).NewTypeParam(tn, index, bound) + if sub >= 0 { + t.SetId(sub) + } + return t + + case instType: + pos := r.pos() + len := r.uint64() + targs := make([]types2.Type, len) + for i := range targs { + targs[i] = r.typ() + } + baseType := r.typ() + // The imported instantiated type doesn't include any methods, so + // we must always use the methods of the base (orig) type. + t := types2.Instantiate(pos, baseType, targs) + return t } } @@ -585,6 +647,19 @@ func (r *importReader) signature(recv *types2.Var) *types2.Signature { return types2.NewSignature(recv, params, results, variadic) } +func (r *importReader) tparamList() []*types2.TypeName { + n := r.uint64() + if n == 0 { + return nil + } + xs := make([]*types2.TypeName, n) + for i := range xs { + typ := r.typ() + xs[i] = types2.AsTypeParam(typ).Obj() + } + return xs +} + func (r *importReader) paramList() *types2.Tuple { xs := make([]*types2.Var, r.uint64()) for i := range xs { @@ -627,3 +702,13 @@ func (r *importReader) byte() byte { } return x } + +func baseType(typ types2.Type) *types2.Named { + // pointer receivers are never types2.Named types + if p, _ := typ.(*types2.Pointer); p != nil { + typ = p.Elem() + } + // receiver base types are always (possibly generic) types2.Named types + n, _ := typ.(*types2.Named) + return n +} diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go index 3e55437afa..40cbe50aff 100644 --- a/src/cmd/compile/internal/noder/decl.go +++ b/src/cmd/compile/internal/noder/decl.go @@ -148,11 +148,15 @@ func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) { // [mdempsky: Subtleties like these are why I always vehemently // object to new type pragmas.] ntyp.SetUnderlying(g.typeExpr(decl.Type)) - if len(decl.TParamList) > 0 { - // Set HasTParam if there are any tparams, even if no tparams are - // used in the type itself (e.g., if it is an empty struct, or no - // fields in the struct use the tparam). - ntyp.SetHasTParam(true) + + tparams := otyp.(*types2.Named).TParams() + if len(tparams) > 0 { + rparams := make([]*types.Type, len(tparams)) + for i := range rparams { + rparams[i] = g.typ(tparams[i].Type()) + } + // This will set hasTParam flag if any rparams are not concrete types. + ntyp.SetRParams(rparams) } types.ResumeCheckSize() diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index b7f7a34953..f96144f8d7 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -264,8 +264,12 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto // instantiated for this method call. // selinfo.Recv() is the instantiated type recvType2 = recvType2Base - // method is the generic method associated with the gen type - method := g.obj(types2.AsNamed(recvType2).Method(last)) + recvTypeSym := g.pkg(method2.Pkg()).Lookup(recvType2.(*types2.Named).Obj().Name()) + recvType := recvTypeSym.Def.(*ir.Name).Type() + // method is the generic method associated with + // the base generic type. The instantiated type may not + // have method bodies filled in, if it was imported. + method := recvType.Methods().Index(last).Nname.(*ir.Name) n = ir.NewSelectorExpr(pos, ir.OCALLPART, x, typecheck.Lookup(expr.Sel.Value)) n.(*ir.SelectorExpr).Selection = types.NewField(pos, method.Sym(), method.Type()) n.(*ir.SelectorExpr).Selection.Nname = method diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index 2a9f0e99d8..f02246111f 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -185,9 +185,9 @@ Outer: // Create any needed stencils of generic functions g.stencil() - // For now, remove all generic functions from g.target.Decl, since they - // have been used for stenciling, but don't compile. TODO: We will - // eventually export any exportable generic functions. + // Remove all generic functions from g.target.Decl, since they have been + // used for stenciling, but don't compile. Generic functions will already + // have been marked for export as appropriate. j := 0 for i, decl := range g.target.Decls { if decl.Op() != ir.ODCLFUNC || !decl.Type().HasTParam() { diff --git a/src/cmd/compile/internal/noder/object.go b/src/cmd/compile/internal/noder/object.go index 7af2fe6715..a1a10e4eaa 100644 --- a/src/cmd/compile/internal/noder/object.go +++ b/src/cmd/compile/internal/noder/object.go @@ -49,6 +49,11 @@ func (g *irgen) obj(obj types2.Object) *ir.Name { // For imported objects, we use iimport directly instead of mapping // the types2 representation. if obj.Pkg() != g.self { + if sig, ok := obj.Type().(*types2.Signature); ok && sig.Recv() != nil { + // We can't import a method by name - must import the type + // and access the method from it. + base.FatalfAt(g.pos(obj), "tried to import a method directly") + } sym := g.sym(obj) if sym.Def != nil { return sym.Def.(*ir.Name) @@ -165,9 +170,8 @@ func (g *irgen) objFinish(name *ir.Name, class ir.Class, typ *types.Type) { break // methods are exported with their receiver type } if types.IsExported(sym.Name) { - if name.Class == ir.PFUNC && name.Type().NumTParams() > 0 { - base.FatalfAt(name.Pos(), "Cannot export a generic function (yet): %v", name) - } + // Generic functions can be marked for export here, even + // though they will not be compiled until instantiated. typecheck.Export(name) } if base.Flag.AsmHdr != "" && !name.Sym().Asm() { diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index f9cf6d8a1a..7a7c05280d 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -8,12 +8,10 @@ package noder import ( - "bytes" "cmd/compile/internal/base" "cmd/compile/internal/ir" "cmd/compile/internal/typecheck" "cmd/compile/internal/types" - "cmd/internal/src" "fmt" "strings" ) @@ -160,9 +158,14 @@ func (g *irgen) stencil() { func (g *irgen) instantiateMethods() { for i := 0; i < len(g.instTypeList); i++ { typ := g.instTypeList[i] - // Get the base generic type by looking up the symbol of the - // generic (uninstantiated) name. - baseSym := typ.Sym().Pkg.Lookup(genericTypeName(typ.Sym())) + // Mark runtime type as needed, since this ensures that the + // compiler puts out the needed DWARF symbols, when this + // instantiated type has a different package from the local + // package. + typecheck.NeedRuntimeType(typ) + // Lookup the method on the base generic type, since methods may + // not be set on imported instantiated types. + baseSym := typ.OrigSym baseType := baseSym.Def.(*ir.Name).Type() for j, m := range typ.Methods().Slice() { name := m.Nname.(*ir.Name) @@ -199,12 +202,24 @@ func (g *irgen) getInstantiationForNode(inst *ir.InstExpr) *ir.Func { // with the type arguments targs. If the instantiated function is not already // cached, then it calls genericSubst to create the new instantiation. func (g *irgen) getInstantiation(nameNode *ir.Name, targs []*types.Type, isMeth bool) *ir.Func { + if nameNode.Func.Body == nil && nameNode.Func.Inl != nil { + // If there is no body yet but Func.Inl exists, then we can can + // import the whole generic body. + assert(nameNode.Func.Inl.Cost == 1 && nameNode.Sym().Pkg != types.LocalPkg) + typecheck.ImportBody(nameNode.Func) + assert(nameNode.Func.Inl.Body != nil) + nameNode.Func.Body = nameNode.Func.Inl.Body + nameNode.Func.Dcl = nameNode.Func.Inl.Dcl + } sym := typecheck.MakeInstName(nameNode.Sym(), targs, isMeth) st := g.target.Stencils[sym] if st == nil { // If instantiation doesn't exist yet, create it and add // to the list of decls. st = g.genericSubst(sym, nameNode, targs, isMeth) + // This ensures that the linker drops duplicates of this instantiation. + // All just works! + st.SetDupok(true) g.target.Stencils[sym] = st g.target.Decls = append(g.target.Decls, st) if base.Flag.W > 1 { @@ -626,21 +641,6 @@ func (subst *subster) tinter(t *types.Type) *types.Type { return t } -// instTypeName creates a name for an instantiated type, based on the name of the -// generic type and the type args -func instTypeName(name string, targs []*types.Type) string { - b := bytes.NewBufferString(name) - b.WriteByte('[') - for i, targ := range targs { - if i > 0 { - b.WriteByte(',') - } - b.WriteString(targ.String()) - } - b.WriteByte(']') - return b.String() -} - // typ computes the type obtained by substituting any type parameter in t with the // corresponding type argument in subst. If t contains no type parameters, the // result is t; otherwise the result is a new type. It deals with recursive types @@ -696,7 +696,7 @@ func (subst *subster) typ(t *types.Type) *types.Type { // already seen this type during this substitution or other // definitions/substitutions. genName := genericTypeName(t.Sym()) - newsym = t.Sym().Pkg.Lookup(instTypeName(genName, neededTargs)) + newsym = t.Sym().Pkg.Lookup(typecheck.InstTypeName(genName, neededTargs)) if newsym.Def != nil { // We've already created this instantiated defined type. return newsym.Def.Type() @@ -705,9 +705,13 @@ func (subst *subster) typ(t *types.Type) *types.Type { // In order to deal with recursive generic types, create a TFORW // type initially and set the Def field of its sym, so it can be // found if this type appears recursively within the type. - forw = newIncompleteNamedType(t.Pos(), newsym) + forw = typecheck.NewIncompleteNamedType(t.Pos(), newsym) //println("Creating new type by sub", newsym.Name, forw.HasTParam()) forw.SetRParams(neededTargs) + // Copy the OrigSym from the re-instantiated type (which is the sym of + // the base generic type). + assert(t.OrigSym != nil) + forw.OrigSym = t.OrigSym } var newt *types.Type @@ -865,11 +869,14 @@ func (subst *subster) fields(class ir.Class, oldfields []*types.Field, dcl []*ir for j := range oldfields { newfields[j] = oldfields[j].Copy() newfields[j].Type = subst.typ(oldfields[j].Type) - // A param field will be missing from dcl if its name is + // A PPARAM field will be missing from dcl if its name is // unspecified or specified as "_". So, we compare the dcl sym - // with the field sym. If they don't match, this dcl (if there is - // one left) must apply to a later field. - if i < len(dcl) && dcl[i].Sym() == oldfields[j].Sym { + // with the field sym (or sym of the field's Nname node). (Unnamed + // results still have a name like ~r2 in their Nname node.) If + // they don't match, this dcl (if there is one left) must apply to + // a later field. + if i < len(dcl) && (dcl[i].Sym() == oldfields[j].Sym || + (oldfields[j].Nname != nil && dcl[i].Sym() == oldfields[j].Nname.Sym())) { newfields[j].Nname = dcl[i] i++ } @@ -884,13 +891,3 @@ func deref(t *types.Type) *types.Type { } return t } - -// newIncompleteNamedType returns a TFORW type t with name specified by sym, such -// that t.nod and sym.Def are set correctly. -func newIncompleteNamedType(pos src.XPos, sym *types.Sym) *types.Type { - name := ir.NewDeclNameAt(pos, ir.OTYPE, sym) - forw := types.NewNamed(name) - name.SetType(forw) - sym.Def = name - return forw -} diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index 35ba1cd238..7fdad29e16 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -68,8 +68,10 @@ func instTypeName2(name string, targs []types2.Type) string { if i > 0 { b.WriteByte(',') } + // Include package names for all types, including typeparams, to + // make sure type arguments are uniquely specified. tname := types2.TypeString(targ, - func(*types2.Package) string { return "" }) + func(pkg *types2.Package) string { return pkg.Name() }) if strings.Index(tname, ", ") >= 0 { // types2.TypeString puts spaces after a comma in a type // list, but we don't want spaces in our actual type names @@ -120,7 +122,7 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { // which may set HasTParam) before translating the // underlying type itself, so we handle recursion // correctly, including via method signatures. - ntyp := newIncompleteNamedType(g.pos(typ.Obj().Pos()), s) + ntyp := typecheck.NewIncompleteNamedType(g.pos(typ.Obj().Pos()), s) g.typs[typ] = ntyp // If ntyp still has type params, then we must be @@ -143,6 +145,8 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { ntyp.SetUnderlying(g.typ1(typ.Underlying())) g.fillinMethods(typ, ntyp) + // Save the symbol for the base generic type. + ntyp.OrigSym = g.pkg(typ.Obj().Pkg()).Lookup(typ.Obj().Name()) return ntyp } obj := g.obj(typ.Obj()) @@ -206,8 +210,19 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { case *types2.TypeParam: // Save the name of the type parameter in the sym of the type. // Include the types2 subscript in the sym name - sym := g.pkg(typ.Obj().Pkg()).Lookup(types2.TypeString(typ, func(*types2.Package) string { return "" })) + pkg := g.tpkg(typ) + sym := pkg.Lookup(types2.TypeString(typ, func(*types2.Package) string { return "" })) + if sym.Def != nil { + // Make sure we use the same type param type for the same + // name, whether it is created during types1-import or + // this types2-to-types1 translation. + return sym.Def.Type() + } tp := types.NewTypeParam(sym, typ.Index()) + nname := ir.NewDeclNameAt(g.pos(typ.Obj().Pos()), ir.OTYPE, sym) + sym.Def = nname + nname.SetType(tp) + tp.SetNod(nname) // Set g.typs[typ] in case the bound methods reference typ. g.typs[typ] = tp @@ -248,12 +263,20 @@ func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) { methods := make([]*types.Field, typ.NumMethods()) for i := range methods { m := typ.Method(i) - meth := g.obj(m) recvType := types2.AsSignature(m.Type()).Recv().Type() ptr := types2.AsPointer(recvType) if ptr != nil { recvType = ptr.Elem() } + var meth *ir.Name + if m.Pkg() != g.self { + // Imported methods cannot be loaded by name (what + // g.obj() does) - they must be loaded via their + // type. + meth = g.obj(recvType.(*types2.Named).Obj()).Type().Methods().Index(i).Nname.(*ir.Name) + } else { + meth = g.obj(m) + } if recvType != types2.Type(typ) { // Unfortunately, meth is the type of the method of the // generic type, so we have to do a substitution to get @@ -343,7 +366,7 @@ func (g *irgen) selector(obj types2.Object) *types.Sym { return pkg.Lookup(name) } -// tpkg returns the package that a function, interface, or struct type +// tpkg returns the package that a function, interface, struct, or typeparam type // expression appeared in. // // Caveat: For the degenerate types "func()", "interface{}", and @@ -373,6 +396,8 @@ func (g *irgen) tpkg(typ types2.Type) *types.Pkg { if typ.NumExplicitMethods() > 0 { return typ.ExplicitMethod(0) } + case *types2.TypeParam: + return typ.Obj() } return nil } diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 8c0e33f6df..f65841b33c 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -951,8 +951,12 @@ func writeType(t *types.Type) *obj.LSym { } if base.Ctxt.Pkgpath != "runtime" || (tbase != types.Types[tbase.Kind()] && tbase != types.ByteType && tbase != types.RuneType && tbase != types.ErrorType) { // int, float, etc - // named types from other files are defined only by those files - if tbase.Sym() != nil && tbase.Sym().Pkg != types.LocalPkg { + // Named types from other files are defined only by those files. + // However, as an exception, we can write out instantiated types + // in the local package, even if they may be marked as part of + // another package (the package of their base generic type). + if tbase.Sym() != nil && tbase.Sym().Pkg != types.LocalPkg && + len(tbase.RParams()) == 0 { if i := typecheck.BaseTypeIndex(t); i >= 0 { lsym.Pkg = tbase.Sym().Pkg.Prefix lsym.SymIdx = int32(i) diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 3538c4d5a6..11b9755148 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -173,6 +173,8 @@ // } // // +// TODO(danscales): fill in doc for 'type TypeParamType' and 'type InstType' +// // type Signature struct { // Params []Param // Results []Param @@ -244,6 +246,8 @@ const ( signatureType structType interfaceType + typeParamType + instType ) const ( @@ -459,6 +463,13 @@ func (p *iexporter) doDecl(n *ir.Name) { // Function. w.tag('F') w.pos(n.Pos()) + // The tparam list of the function type is the + // declaration of the type params. So, write out the type + // params right now. Then those type params will be + // referenced via their type offset (via typOff) in all + // other places in the signature and function that they + // are used. + w.tparamList(n.Type().TParams().FieldSlice()) w.signature(n.Type()) w.funcExt(n) @@ -491,6 +502,8 @@ func (p *iexporter) doDecl(n *ir.Name) { w.tag('T') w.pos(n.Pos()) + // Export any new typeparams needed for this type + w.typeList(n.Type().RParams()) underlying := n.Type().Underlying() if underlying == types.ErrorType.Underlying() { // For "type T error", use error as the @@ -803,8 +816,49 @@ func (w *exportWriter) startType(k itag) { } func (w *exportWriter) doTyp(t *types.Type) { - if t.Sym() != nil { - if t.Sym().Pkg == types.BuiltinPkg || t.Sym().Pkg == ir.Pkgs.Unsafe { + if t.Kind() == types.TTYPEPARAM { + // A typeparam has a name, but doesn't have an underlying type. + // Just write out the details of the type param here. All other + // uses of this typeparam type will be written out as its unique + // type offset. + w.startType(typeParamType) + s := t.Sym() + w.setPkg(s.Pkg, true) + w.pos(t.Pos()) + + // We are writing out the name with the subscript, so that the + // typeparam name is unique. + w.string(s.Name) + w.int64(int64(t.Index())) + + w.typ(t.Bound()) + return + } + + s := t.Sym() + if s != nil && t.OrigSym != nil { + // This is an instantiated type - could be a re-instantiation like + // Value[T2] or a full instantiation like Value[int]. + if strings.Index(s.Name, "[") < 0 { + base.Fatalf("incorrect name for instantiated type") + } + w.startType(instType) + w.pos(t.Pos()) + // Export the type arguments for the instantiated type. The + // instantiated type could be in a method header (e.g. "func (v + // *Value[T2]) set (...) { ... }"), so the type args are "new" + // typeparams. Or the instantiated type could be in a + // function/method body, so the type args are either concrete + // types or existing typeparams from the function/method header. + w.typeList(t.RParams()) + // Export a reference to the base type. + baseType := t.OrigSym.Def.(*ir.Name).Type() + w.typ(baseType) + return + } + + if s != nil { + if s.Pkg == types.BuiltinPkg || s.Pkg == ir.Pkgs.Unsafe { base.Fatalf("builtin type missing from typIndex: %v", t) } @@ -906,6 +960,23 @@ func (w *exportWriter) signature(t *types.Type) { } } +func (w *exportWriter) typeList(ts []*types.Type) { + w.uint64(uint64(len(ts))) + for _, rparam := range ts { + w.typ(rparam) + } +} + +func (w *exportWriter) tparamList(fs []*types.Field) { + w.uint64(uint64(len(fs))) + for _, f := range fs { + if f.Type.Kind() != types.TTYPEPARAM { + base.Fatalf("unexpected non-typeparam") + } + w.typ(f.Type) + } +} + func (w *exportWriter) paramList(fs []*types.Field) { w.uint64(uint64(len(fs))) for _, f := range fs { @@ -1186,9 +1257,21 @@ func (w *exportWriter) funcExt(n *ir.Name) { } // Inline body. + if n.Type().HasTParam() { + if n.Func.Inl != nil { + base.FatalfAt(n.Pos(), "generic function is marked inlineable") + } + // Populate n.Func.Inl, so body of exported generic function will + // be written out. + n.Func.Inl = &ir.Inline{ + Cost: 1, + Dcl: n.Func.Dcl, + Body: n.Func.Body, + } + } if n.Func.Inl != nil { w.uint64(1 + uint64(n.Func.Inl.Cost)) - if n.Func.ExportInline() { + if n.Func.ExportInline() || n.Type().HasTParam() { w.p.doInline(n) } @@ -1588,9 +1671,8 @@ func (w *exportWriter) expr(n ir.Node) { case ir.OXDOT, ir.ODOT, ir.ODOTPTR, ir.ODOTINTER, ir.ODOTMETH, ir.OCALLPART, ir.OMETHEXPR: n := n.(*ir.SelectorExpr) if go117ExportTypes { - if n.Op() == ir.OXDOT { - base.Fatalf("shouldn't encounter XDOT in new exporter") - } + // For go117ExportTypes, we usually see all ops except + // OXDOT, but we can see OXDOT for generic functions. w.op(n.Op()) } else { w.op(ir.OXDOT) @@ -1604,7 +1686,8 @@ func (w *exportWriter) expr(n ir.Node) { w.exoticField(n.Selection) } // n.Selection is not required for OMETHEXPR, ODOTMETH, and OCALLPART. It will - // be reconstructed during import. + // be reconstructed during import. n.Selection is computed during + // transformDot() for OXDOT. } case ir.ODOTTYPE, ir.ODOTTYPE2: diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index a5ddbb5a74..b6f227bb00 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -8,6 +8,7 @@ package typecheck import ( + "bytes" "encoding/binary" "fmt" "go/constant" @@ -313,13 +314,16 @@ func (r *importReader) doDecl(sym *types.Sym) *ir.Name { return n case 'F': - typ := r.signature(nil) + tparams := r.tparamList() + typ := r.signature(nil, tparams) n := importfunc(r.p.ipkg, pos, sym, typ) r.funcExt(n) return n case 'T': + rparams := r.typeList() + // Types can be recursive. We need to setup a stub // declaration before recursing. n := importtype(r.p.ipkg, pos, sym) @@ -332,6 +336,10 @@ func (r *importReader) doDecl(sym *types.Sym) *ir.Name { t.SetUnderlying(underlying) types.ResumeCheckSize() + if rparams != nil { + t.SetRParams(rparams) + } + if underlying.IsInterface() { r.typeExt(t) return n @@ -342,7 +350,7 @@ func (r *importReader) doDecl(sym *types.Sym) *ir.Name { mpos := r.pos() msym := r.selector() recv := r.param() - mtyp := r.signature(recv) + mtyp := r.signature(recv, nil) // MethodSym already marked m.Sym as a function. m := ir.NewNameAt(mpos, ir.MethodSym(recv.Type, msym)) @@ -680,7 +688,7 @@ func (r *importReader) typ1() *types.Type { case signatureType: r.setPkg() - return r.signature(nil) + return r.signature(nil, nil) case structType: r.setPkg() @@ -718,7 +726,7 @@ func (r *importReader) typ1() *types.Type { for i := range methods { pos := r.pos() sym := r.selector() - typ := r.signature(fakeRecvField()) + typ := r.signature(fakeRecvField(), nil) methods[i] = types.NewField(pos, sym, typ) } @@ -728,6 +736,40 @@ func (r *importReader) typ1() *types.Type { // Ensure we expand the interface in the frontend (#25055). types.CheckSize(t) return t + + case typeParamType: + r.setPkg() + pos := r.pos() + name := r.string() + sym := r.currPkg.Lookup(name) + index := int(r.int64()) + bound := r.typ() + if sym.Def != nil { + // Make sure we use the same type param type for the same + // name, whether it is created during types1-import or + // this types2-to-types1 translation. + return sym.Def.Type() + } + t := types.NewTypeParam(sym, index) + // Nname needed to save the pos. + nname := ir.NewDeclNameAt(pos, ir.OTYPE, sym) + sym.Def = nname + nname.SetType(t) + t.SetNod(nname) + + t.SetBound(bound) + return t + + case instType: + pos := r.pos() + len := r.uint64() + targs := make([]*types.Type, len) + for i := range targs { + targs[i] = r.typ() + } + baseType := r.typ() + t := Instantiate(pos, baseType, targs) + return t } } @@ -735,13 +777,38 @@ func (r *importReader) kind() itag { return itag(r.uint64()) } -func (r *importReader) signature(recv *types.Field) *types.Type { +func (r *importReader) signature(recv *types.Field, tparams []*types.Field) *types.Type { params := r.paramList() results := r.paramList() if n := len(params); n > 0 { params[n-1].SetIsDDD(r.bool()) } - return types.NewSignature(r.currPkg, recv, nil, params, results) + return types.NewSignature(r.currPkg, recv, tparams, params, results) +} + +func (r *importReader) typeList() []*types.Type { + n := r.uint64() + if n == 0 { + return nil + } + ts := make([]*types.Type, n) + for i := range ts { + ts[i] = r.typ() + } + return ts +} + +func (r *importReader) tparamList() []*types.Field { + n := r.uint64() + if n == 0 { + return nil + } + fs := make([]*types.Field, n) + for i := range fs { + typ := r.typ() + fs[i] = types.NewField(typ.Pos(), typ.Sym(), typ) + } + return fs } func (r *importReader) paramList() []*types.Field { @@ -809,7 +876,9 @@ func (r *importReader) funcExt(n *ir.Name) { n.Func.ABI = obj.ABI(r.uint64()) - n.SetPragma(ir.PragmaFlag(r.uint64())) + // Make sure //go:noinline pragma is imported (so stenciled functions have + // same noinline status as the corresponding generic function.) + n.Func.Pragma = ir.PragmaFlag(r.uint64()) // Escape analysis. for _, fs := range &types.RecvsParams { @@ -1117,7 +1186,7 @@ func (r *importReader) node() ir.Node { case ir.OCLOSURE: //println("Importing CLOSURE") pos := r.pos() - typ := r.signature(nil) + typ := r.signature(nil, nil) // All the remaining code below is similar to (*noder).funcLit(), but // with Dcls and ClosureVars lists already set up @@ -1202,35 +1271,32 @@ func (r *importReader) node() ir.Node { // case OSTRUCTKEY: // unreachable - handled in case OSTRUCTLIT by elemList - case ir.OXDOT: - // see parser.new_dotname - if go117ExportTypes { - base.Fatalf("shouldn't encounter XDOT in new importer") - } - return ir.NewSelectorExpr(r.pos(), ir.OXDOT, r.expr(), r.exoticSelector()) - - case ir.ODOT, ir.ODOTPTR, ir.ODOTINTER, ir.ODOTMETH, ir.OCALLPART, ir.OMETHEXPR: - if !go117ExportTypes { - // unreachable - mapped to case OXDOT by exporter + case ir.OXDOT, ir.ODOT, ir.ODOTPTR, ir.ODOTINTER, ir.ODOTMETH, ir.OCALLPART, ir.OMETHEXPR: + // For !go117ExportTypes, we should only see OXDOT. + // For go117ExportTypes, we usually see all the other ops, but can see + // OXDOT for generic functions. + if op != ir.OXDOT && !go117ExportTypes { goto error } pos := r.pos() expr := r.expr() sel := r.exoticSelector() n := ir.NewSelectorExpr(pos, op, expr, sel) - n.SetType(r.exoticType()) - switch op { - case ir.ODOT, ir.ODOTPTR, ir.ODOTINTER: - n.Selection = r.exoticField() - case ir.ODOTMETH, ir.OCALLPART, ir.OMETHEXPR: - // These require a Lookup to link to the correct declaration. - rcvrType := expr.Type() - typ := n.Type() - n.Selection = Lookdot(n, rcvrType, 1) - if op == ir.OCALLPART || op == ir.OMETHEXPR { - // Lookdot clobbers the opcode and type, undo that. - n.SetOp(op) - n.SetType(typ) + if go117ExportTypes { + n.SetType(r.exoticType()) + switch op { + case ir.ODOT, ir.ODOTPTR, ir.ODOTINTER: + n.Selection = r.exoticField() + case ir.ODOTMETH, ir.OCALLPART, ir.OMETHEXPR: + // These require a Lookup to link to the correct declaration. + rcvrType := expr.Type() + typ := n.Type() + n.Selection = Lookdot(n, rcvrType, 1) + if op == ir.OCALLPART || op == ir.OMETHEXPR { + // Lookdot clobbers the opcode and type, undo that. + n.SetOp(op) + n.SetType(typ) + } } } return n @@ -1544,3 +1610,63 @@ func builtinCall(pos src.XPos, op ir.Op) *ir.CallExpr { } return ir.NewCallExpr(pos, ir.OCALL, ir.NewIdent(base.Pos, types.BuiltinPkg.Lookup(ir.OpNames[op])), nil) } + +// InstTypeName creates a name for an instantiated type, based on the name of the +// generic type and the type args. +func InstTypeName(name string, targs []*types.Type) string { + b := bytes.NewBufferString(name) + b.WriteByte('[') + for i, targ := range targs { + if i > 0 { + b.WriteByte(',') + } + // WriteString() does not include the package name for the local + // package, but we want it to make sure type arguments (including + // type params) are uniquely specified. + if targ.Sym() != nil && targ.Sym().Pkg == types.LocalPkg { + b.WriteString(targ.Sym().Pkg.Name) + b.WriteByte('.') + } + b.WriteString(targ.String()) + } + b.WriteByte(']') + return b.String() +} + +// NewIncompleteNamedType returns a TFORW type t with name specified by sym, such +// that t.nod and sym.Def are set correctly. +func NewIncompleteNamedType(pos src.XPos, sym *types.Sym) *types.Type { + name := ir.NewDeclNameAt(pos, ir.OTYPE, sym) + forw := types.NewNamed(name) + name.SetType(forw) + sym.Def = name + return forw +} + +// Instantiate creates a new named type which is the instantiation of the base +// named generic type, with the specified type args. +func Instantiate(pos src.XPos, baseType *types.Type, targs []*types.Type) *types.Type { + baseSym := baseType.Sym() + if strings.Index(baseSym.Name, "[") >= 0 { + base.Fatalf("arg to Instantiate is not a base generic type") + } + name := InstTypeName(baseSym.Name, targs) + instSym := baseSym.Pkg.Lookup(name) + if instSym.Def != nil { + return instSym.Def.Type() + } + + t := NewIncompleteNamedType(baseType.Pos(), instSym) + t.SetRParams(targs) + // baseType may not yet be complete (since we are in the middle of + // importing it), but its underlying type will be updated when baseType's + // underlying type is finished. + t.SetUnderlying(baseType.Underlying()) + + // As with types2, the methods are the generic method signatures (without + // substitution). + t.Methods().Set(baseType.Methods().Slice()) + t.OrigSym = baseSym + + return t +} diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 97fb145132..9eac802dab 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -887,7 +887,7 @@ func TypesOf(x []ir.Node) []*types.Type { } // MakeInstName makes the unique name for a stenciled generic function or method, -// based on the name of the function fy=nsym and the targs. It replaces any +// based on the name of the function fnsym and the targs. It replaces any // existing bracket type list in the name. makeInstName asserts that fnsym has // brackets in its name if and only if hasBrackets is true. // TODO(danscales): remove the assertions and the hasBrackets argument later. @@ -914,6 +914,12 @@ func MakeInstName(fnsym *types.Sym, targs []*types.Type, hasBrackets bool) *type if i > 0 { b.WriteString(",") } + // WriteString() does not include the package name for the local + // package, but we want it for uniqueness. + if targ.Sym() != nil && targ.Sym().Pkg == types.LocalPkg { + b.WriteString(targ.Sym().Pkg.Name) + b.WriteByte('.') + } b.WriteString(targ.String()) } b.WriteString("]") @@ -922,7 +928,7 @@ func MakeInstName(fnsym *types.Sym, targs []*types.Type, hasBrackets bool) *type assert(i2 >= 0) b.WriteString(name[i+i2+1:]) } - return Lookup(b.String()) + return fnsym.Pkg.Lookup(b.String()) } // For catching problems as we add more features diff --git a/src/cmd/compile/internal/types/sizeof_test.go b/src/cmd/compile/internal/types/sizeof_test.go index 7028938742..7349e52a73 100644 --- a/src/cmd/compile/internal/types/sizeof_test.go +++ b/src/cmd/compile/internal/types/sizeof_test.go @@ -21,7 +21,7 @@ func TestSizeof(t *testing.T) { _64bit uintptr // size on 64bit platforms }{ {Sym{}, 44, 72}, - {Type{}, 60, 104}, + {Type{}, 64, 112}, {Map{}, 20, 40}, {Forward{}, 20, 32}, {Func{}, 28, 48}, diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index d3c02fc56d..3b0a9706f6 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -182,12 +182,19 @@ type Type struct { flags bitset8 // For defined (named) generic types, a pointer to the list of type params - // (in order) of this type that need to be instantiated. For - // fully-instantiated generic types, this is the targs used to instantiate - // them (which are used when generating the corresponding instantiated - // methods). rparams is only set for named types that are generic or are - // fully-instantiated from a generic type, and is otherwise set to nil. + // (in order) of this type that need to be instantiated. For instantiated + // generic types, this is the targs used to instantiate them. These targs + // may be typeparams (for re-instantiated types such as Value[T2]) or + // concrete types (for fully instantiated types such as Value[int]). + // rparams is only set for named types that are generic or are fully + // instantiated from a generic type, and is otherwise set to nil. + // TODO(danscales): choose a better name. rparams *[]*Type + + // For an instantiated generic type, the symbol for the base generic type. + // This backpointer is useful, because the base type is the type that has + // the method bodies. + OrigSym *Sym } func (*Type) CanBeAnSSAAux() {} @@ -213,7 +220,9 @@ func (t *Type) SetBroke(b bool) { t.flags.set(typeBroke, b) } func (t *Type) SetNoalg(b bool) { t.flags.set(typeNoalg, b) } func (t *Type) SetDeferwidth(b bool) { t.flags.set(typeDeferwidth, b) } func (t *Type) SetRecur(b bool) { t.flags.set(typeRecur, b) } -func (t *Type) SetHasTParam(b bool) { t.flags.set(typeHasTParam, b) } + +// Generic types should never have alg functions. +func (t *Type) SetHasTParam(b bool) { t.flags.set(typeHasTParam, b); t.flags.set(typeNoalg, b) } // Kind returns the kind of type t. func (t *Type) Kind() Kind { return t.kind } diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index e1020a1219..d82d29cad8 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -329,23 +329,23 @@ func TestTypesInfo(t *testing.T) { {brokenPkg + `x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string]invalid type`}, // parameterized functions - {genericPkg + `p0; func f[T any](T); var _ = f[int]`, `f`, `func[T₁ interface{}](T₁)`}, + {genericPkg + `p0; func f[T any](T); var _ = f[int]`, `f`, `func[generic_p0.T₁ interface{}](generic_p0.T₁)`}, {genericPkg + `p1; func f[T any](T); var _ = f[int]`, `f[int]`, `func(int)`}, - {genericPkg + `p2; func f[T any](T); func _() { f(42) }`, `f`, `func[T₁ interface{}](T₁)`}, + {genericPkg + `p2; func f[T any](T); func _() { f(42) }`, `f`, `func[generic_p2.T₁ interface{}](generic_p2.T₁)`}, {genericPkg + `p3; func f[T any](T); func _() { f(42) }`, `f(42)`, `()`}, // type parameters {genericPkg + `t0; type t[] int; var _ t`, `t`, `generic_t0.t`}, // t[] is a syntax error that is ignored in this test in favor of t - {genericPkg + `t1; type t[P any] int; var _ t[int]`, `t`, `generic_t1.t[P₁ interface{}]`}, - {genericPkg + `t2; type t[P interface{}] int; var _ t[int]`, `t`, `generic_t2.t[P₁ interface{}]`}, - {genericPkg + `t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `generic_t3.t[P₁, Q₂ interface{}]`}, - {brokenPkg + `t4; type t[P, Q interface{ m() }] int; var _ t[int, int]`, `t`, `broken_t4.t[P₁, Q₂ interface{m()}]`}, + {genericPkg + `t1; type t[P any] int; var _ t[int]`, `t`, `generic_t1.t[generic_t1.P₁ interface{}]`}, + {genericPkg + `t2; type t[P interface{}] int; var _ t[int]`, `t`, `generic_t2.t[generic_t2.P₁ interface{}]`}, + {genericPkg + `t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `generic_t3.t[generic_t3.P₁, generic_t3.Q₂ interface{}]`}, + {brokenPkg + `t4; type t[P, Q interface{ m() }] int; var _ t[int, int]`, `t`, `broken_t4.t[broken_t4.P₁, broken_t4.Q₂ interface{m()}]`}, // instantiated types must be sanitized {genericPkg + `g0; type t[P any] int; var x struct{ f t[int] }; var _ = x.f`, `x.f`, `generic_g0.t[int]`}, // issue 45096 - {genericPkg + `issue45096; func _[T interface{ type int8, int16, int32 }](x T) { _ = x < 0 }`, `0`, `T₁`}, + {genericPkg + `issue45096; func _[T interface{ type int8, int16, int32 }](x T) { _ = x < 0 }`, `0`, `generic_issue45096.T₁`}, } for _, test := range tests { diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index cf119a1b23..55c2f336ce 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -250,6 +250,9 @@ func (s *Signature) RParams() []*TypeName { return s.rparams } // SetTParams sets the type parameters of signature s. func (s *Signature) SetTParams(tparams []*TypeName) { s.tparams = tparams } +// SetRParams sets the receiver type params of signature s. +func (s *Signature) SetRParams(rparams []*TypeName) { s.rparams = rparams } + // Params returns the parameters of signature s, or nil. func (s *Signature) Params() *Tuple { return s.params } @@ -771,6 +774,12 @@ func (t *TypeParam) Index() int { return t.index } +// SetId sets the unique id of a type param. Should only be used for type params +// in imported generic types. +func (t *TypeParam) SetId(id uint64) { + t.id = id +} + func (t *TypeParam) Bound() *Interface { iface := asInterface(t.bound) // use the type bound position if we have one @@ -1002,3 +1011,4 @@ func AsPointer(t Type) *Pointer { return asPointer(t) } func AsNamed(t Type) *Named { return asNamed(t) } func AsSignature(t Type) *Signature { return asSignature(t) } func AsInterface(t Type) *Interface { return asInterface(t) } +func AsTypeParam(t Type) *TypeParam { return asTypeParam(t) } diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index e85cc8ed35..c534b04130 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -281,6 +281,13 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { case *TypeParam: s := "?" if t.obj != nil { + // Optionally write out package for typeparams (like Named). + // TODO(danscales): this is required for import/export, so + // we maybe need a separate function that won't be changed + // for debugging purposes. + if t.obj.pkg != nil { + writePackage(buf, t.obj.pkg, qf) + } s = t.obj.name } buf.WriteString(s + subscript(t.id)) diff --git a/src/go/internal/gcimporter/gcimporter_test.go b/src/go/internal/gcimporter/gcimporter_test.go index 3c76aafde3..c010dc506e 100644 --- a/src/go/internal/gcimporter/gcimporter_test.go +++ b/src/go/internal/gcimporter/gcimporter_test.go @@ -138,7 +138,8 @@ func TestVersionHandling(t *testing.T) { skipSpecialPlatforms(t) // This package only handles gc export data. - if runtime.Compiler != "gc" { + // Disable test until we put in the new export version. + if true || runtime.Compiler != "gc" { t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) } diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go index a3184e7641..4416f5b2b9 100644 --- a/src/go/internal/gcimporter/iimport.go +++ b/src/go/internal/gcimporter/iimport.go @@ -55,6 +55,8 @@ const ( signatureType structType interfaceType + typeParamType + instType ) // iImportData imports a package from the serialized package data @@ -271,11 +273,21 @@ func (r *importReader) obj(name string) { r.declare(types.NewConst(pos, r.currPkg, name, typ, val)) case 'F': + numTparams := r.uint64() + if numTparams > 0 { + errorf("unexpected tparam") + return + } sig := r.signature(nil) r.declare(types.NewFunc(pos, r.currPkg, name, sig)) case 'T': + numTparams := r.uint64() + if numTparams > 0 { + errorf("unexpected tparam") + } + // Types can be recursive. We need to setup a stub // declaration before recursing. obj := types.NewTypeName(pos, r.currPkg, name, nil) @@ -548,6 +560,14 @@ func (r *importReader) doType(base *types.Named) types.Type { typ := types.NewInterfaceType(methods, embeddeds) r.p.interfaceList = append(r.p.interfaceList, typ) return typ + + case typeParamType: + errorf("do not handle tparams yet") + return nil + + case instType: + errorf("do not handle instantiated types yet") + return nil } } diff --git a/test/typeparam/adder.go b/test/typeparam/adder.go index 0c25ad4ef2..eb564b5bd5 100644 --- a/test/typeparam/adder.go +++ b/test/typeparam/adder.go @@ -14,16 +14,16 @@ type AddType interface { type int, int64, string } -// _Add can add numbers or strings -func _Add[T AddType](a, b T) T { +// Add can add numbers or strings +func Add[T AddType](a, b T) T { return a + b } func main() { - if got, want := _Add(5, 3), 8; got != want { + if got, want := Add(5, 3), 8; got != want { panic(fmt.Sprintf("got %d, want %d", got, want)) } - if got, want := _Add("ab", "cd"), "abcd"; got != want { + if got, want := Add("ab", "cd"), "abcd"; got != want { panic(fmt.Sprintf("got %d, want %d", got, want)) } } diff --git a/test/typeparam/min.go b/test/typeparam/min.go index a3e4464a30..6e28c062a8 100644 --- a/test/typeparam/min.go +++ b/test/typeparam/min.go @@ -11,7 +11,7 @@ import ( ) type Ordered interface { - type int, int64, float64 + type int, int64, float64, string } func min[T Ordered](x, y T) T { @@ -38,4 +38,13 @@ func main() { if got := min(3.5, 2.0); got != want { panic(fmt.Sprintf("got %d, want %d", got, want)) } + + const want2 = "ay" + if got := min[string]("bb", "ay"); got != want2 { + panic(fmt.Sprintf("got %d, want %d", got, want2)) + } + + if got := min("bb", "ay"); got != want2 { + panic(fmt.Sprintf("got %d, want %d", got, want2)) + } } diff --git a/test/typeparam/minimp.dir/a.go b/test/typeparam/minimp.dir/a.go new file mode 100644 index 0000000000..16c1b035f4 --- /dev/null +++ b/test/typeparam/minimp.dir/a.go @@ -0,0 +1,16 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type Ordered interface { + type int, int64, float64, string +} + +func Min[T Ordered](x, y T) T { + if x < y { + return x + } + return y +} diff --git a/test/typeparam/minimp.dir/main.go b/test/typeparam/minimp.dir/main.go new file mode 100644 index 0000000000..509f5aaed2 --- /dev/null +++ b/test/typeparam/minimp.dir/main.go @@ -0,0 +1,38 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "a" + "fmt" +) + +func main() { + const want = 2 + if got := a.Min[int](2, 3); got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } + + if got := a.Min(2, 3); got != want { + panic(fmt.Sprintf("want %d, got %d", want, got)) + } + + if got := a.Min[float64](3.5, 2.0); got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } + + if got := a.Min(3.5, 2.0); got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } + + const want2 = "ay" + if got := a.Min[string]("bb", "ay"); got != want2 { + panic(fmt.Sprintf("got %d, want %d", got, want2)) + } + + if got := a.Min("bb", "ay"); got != want2 { + panic(fmt.Sprintf("got %d, want %d", got, want2)) + } +} diff --git a/test/typeparam/minimp.go b/test/typeparam/minimp.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/minimp.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored diff --git a/test/typeparam/pair.go b/test/typeparam/pair.go index 7faf083c89..57742022b1 100644 --- a/test/typeparam/pair.go +++ b/test/typeparam/pair.go @@ -24,6 +24,7 @@ func main() { if got, want := unsafe.Sizeof(p.f2), uintptr(8); got != want { panic(fmt.Sprintf("unexpected f2 size == %d, want %d", got, want)) } + type mypair struct { f1 int32; f2 int64 } mp := mypair(p) if mp.f1 != 1 || mp.f2 != 2 { diff --git a/test/typeparam/pairimp.dir/a.go b/test/typeparam/pairimp.dir/a.go new file mode 100644 index 0000000000..27b2412961 --- /dev/null +++ b/test/typeparam/pairimp.dir/a.go @@ -0,0 +1,10 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type Pair[F1, F2 any] struct { + Field1 F1 + Field2 F2 +} diff --git a/test/typeparam/pairimp.dir/main.go b/test/typeparam/pairimp.dir/main.go new file mode 100644 index 0000000000..fc2face81d --- /dev/null +++ b/test/typeparam/pairimp.dir/main.go @@ -0,0 +1,27 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "a" + "fmt" + "unsafe" +) + +func main() { + p := a.Pair[int32, int64]{1, 2} + if got, want := unsafe.Sizeof(p.Field1), uintptr(4); got != want { + panic(fmt.Sprintf("unexpected f1 size == %d, want %d", got, want)) + } + if got, want := unsafe.Sizeof(p.Field2), uintptr(8); got != want { + panic(fmt.Sprintf("unexpected f2 size == %d, want %d", got, want)) + } + + type mypair struct { Field1 int32; Field2 int64 } + mp := mypair(p) + if mp.Field1 != 1 || mp.Field2 != 2 { + panic(fmt.Sprintf("mp == %#v, want %#v", mp, mypair{1, 2})) + } +} diff --git a/test/typeparam/pairimp.go b/test/typeparam/pairimp.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/pairimp.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored diff --git a/test/typeparam/settable.go b/test/typeparam/settable.go index 588166da85..d0b831b533 100644 --- a/test/typeparam/settable.go +++ b/test/typeparam/settable.go @@ -13,13 +13,13 @@ import ( // Various implementations of fromStrings(). -type _Setter[B any] interface { +type Setter[B any] interface { Set(string) type *B } // Takes two type parameters where PT = *T -func fromStrings1[T any, PT _Setter[T]](s []string) []T { +func fromStrings1[T any, PT Setter[T]](s []string) []T { result := make([]T, len(s)) for i, v := range s { // The type of &result[i] is *T which is in the type list @@ -31,7 +31,7 @@ func fromStrings1[T any, PT _Setter[T]](s []string) []T { return result } -func fromStrings1a[T any, PT _Setter[T]](s []string) []PT { +func fromStrings1a[T any, PT Setter[T]](s []string) []PT { result := make([]PT, len(s)) for i, v := range s { // The type new(T) is *T which is in the type list @@ -54,12 +54,12 @@ func fromStrings2[T any](s []string, set func(*T, string)) []T { return results } -type _Setter2 interface { +type Setter2 interface { Set(string) } // Takes only one type parameter, but causes a panic (see below) -func fromStrings3[T _Setter2](s []string) []T { +func fromStrings3[T Setter2](s []string) []T { results := make([]T, len(s)) for i, v := range s { // Panics if T is a pointer type because receiver is T(nil). diff --git a/test/typeparam/smallest.go b/test/typeparam/smallest.go index 63dd9ddb70..d851536049 100644 --- a/test/typeparam/smallest.go +++ b/test/typeparam/smallest.go @@ -17,7 +17,7 @@ type Ordered interface { string } -func smallest[T Ordered](s []T) T { +func Smallest[T Ordered](s []T) T { r := s[0] // panics if slice is empty for _, v := range s[1:] { if v < r { @@ -32,11 +32,11 @@ func main() { vec2 := []string{"abc", "def", "aaa"} want1 := 1.2 - if got := smallest(vec1); got != want1 { + if got := Smallest(vec1); got != want1 { panic(fmt.Sprintf("got %d, want %d", got, want1)) } want2 := "aaa" - if got := smallest(vec2); got != want2 { + if got := Smallest(vec2); got != want2 { panic(fmt.Sprintf("got %d, want %d", got, want2)) } } diff --git a/test/typeparam/stringable.go b/test/typeparam/stringable.go index 9340a3b10a..20da012cb8 100644 --- a/test/typeparam/stringable.go +++ b/test/typeparam/stringable.go @@ -16,11 +16,11 @@ type Stringer interface { String() string } -// stringableList is a slice of some type, where the type +// StringableList is a slice of some type, where the type // must have a String method. -type stringableList[T Stringer] []T +type StringableList[T Stringer] []T -func (s stringableList[T]) String() string { +func (s StringableList[T]) String() string { var sb strings.Builder for i, v := range s { if i > 0 { @@ -38,7 +38,7 @@ func (a myint) String() string { } func main() { - v := stringableList[myint]{ myint(1), myint(2) } + v := StringableList[myint]{ myint(1), myint(2) } if got, want := v.String(), "1, 2"; got != want { panic(fmt.Sprintf("got %s, want %s", got, want)) diff --git a/test/typeparam/stringerimp.dir/a.go b/test/typeparam/stringerimp.dir/a.go new file mode 100644 index 0000000000..3f70937ff5 --- /dev/null +++ b/test/typeparam/stringerimp.dir/a.go @@ -0,0 +1,16 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type Stringer interface { + String() string +} + +func Stringify[T Stringer](s []T) (ret []string) { + for _, v := range s { + ret = append(ret, v.String()) + } + return ret +} diff --git a/test/typeparam/stringerimp.dir/main.go b/test/typeparam/stringerimp.dir/main.go new file mode 100644 index 0000000000..e30bdf1abe --- /dev/null +++ b/test/typeparam/stringerimp.dir/main.go @@ -0,0 +1,38 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "a" + "fmt" + "reflect" + "strconv" +) + +type myint int + +func (i myint) String() string { + return strconv.Itoa(int(i)) +} + +func main() { + x := []myint{myint(1), myint(2), myint(3)} + + got := a.Stringify(x) + want := []string{"1", "2", "3"} + if !reflect.DeepEqual(got, want) { + panic(fmt.Sprintf("got %s, want %s", got, want)) + } + + m1 := myint(1) + m2 := myint(2) + m3 := myint(3) + y := []*myint{&m1, &m2, &m3} + got2 := a.Stringify(y) + want2 := []string{"1", "2", "3"} + if !reflect.DeepEqual(got2, want2) { + panic(fmt.Sprintf("got %s, want %s", got2, want2)) + } +} diff --git a/test/typeparam/stringerimp.go b/test/typeparam/stringerimp.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/stringerimp.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored diff --git a/test/typeparam/struct.go b/test/typeparam/struct.go index 98f0fcd888..093f6935e6 100644 --- a/test/typeparam/struct.go +++ b/test/typeparam/struct.go @@ -10,40 +10,40 @@ import ( "fmt" ) -type _E[T any] struct { +type E[T any] struct { v T } -type _S1 struct { - _E[int] +type S1 struct { + E[int] v string } -type _Eint = _E[int] -type _Ebool = _E[bool] +type Eint = E[int] +type Ebool = E[bool] -type _S2 struct { - _Eint - _Ebool +type S2 struct { + Eint + Ebool v string } -type _S3 struct { - *_E[int] +type S3 struct { + *E[int] } func main() { - s1 := _S1{_Eint{2}, "foo"} - if got, want := s1._E.v, 2; got != want { + s1 := S1{Eint{2}, "foo"} + if got, want := s1.E.v, 2; got != want { panic(fmt.Sprintf("got %d, want %d", got, want)) } - s2 := _S2{_Eint{3}, _Ebool{true}, "foo"} - if got, want := s2._Eint.v, 3; got != want { + s2 := S2{Eint{3}, Ebool{true}, "foo"} + if got, want := s2.Eint.v, 3; got != want { panic(fmt.Sprintf("got %d, want %d", got, want)) } - var s3 _S3 - s3._E = &_Eint{4} - if got, want := s3._E.v, 4; got != want { + var s3 S3 + s3.E = &Eint{4} + if got, want := s3.E.v, 4; got != want { panic(fmt.Sprintf("got %d, want %d", got, want)) } } diff --git a/test/typeparam/sum.go b/test/typeparam/sum.go index f0f5e6aa07..c82d8e4c61 100644 --- a/test/typeparam/sum.go +++ b/test/typeparam/sum.go @@ -10,7 +10,7 @@ import ( "fmt" ) -func sum[T interface{ type int, float64 }](vec []T) T { +func Sum[T interface{ type int, float64 }](vec []T) T { var sum T for _, elt := range vec { sum = sum + elt @@ -18,7 +18,7 @@ func sum[T interface{ type int, float64 }](vec []T) T { return sum } -func abs(f float64) float64 { +func Abs(f float64) float64 { if f < 0.0 { return -f } @@ -28,23 +28,23 @@ func abs(f float64) float64 { func main() { vec1 := []int{3, 4} vec2 := []float64{5.8, 9.6} - got := sum[int](vec1) + got := Sum[int](vec1) want := vec1[0] + vec1[1] if got != want { panic(fmt.Sprintf("got %d, want %d", got, want)) } - got = sum(vec1) + got = Sum(vec1) if want != got { panic(fmt.Sprintf("got %d, want %d", got, want)) } fwant := vec2[0] + vec2[1] - fgot := sum[float64](vec2) - if abs(fgot - fwant) > 1e-10 { + fgot := Sum[float64](vec2) + if Abs(fgot - fwant) > 1e-10 { panic(fmt.Sprintf("got %f, want %f", fgot, fwant)) } - fgot = sum(vec2) - if abs(fgot - fwant) > 1e-10 { + fgot = Sum(vec2) + if Abs(fgot - fwant) > 1e-10 { panic(fmt.Sprintf("got %f, want %f", fgot, fwant)) } } diff --git a/test/typeparam/valimp.dir/a.go b/test/typeparam/valimp.dir/a.go new file mode 100644 index 0000000000..5aa5ebfa97 --- /dev/null +++ b/test/typeparam/valimp.dir/a.go @@ -0,0 +1,32 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type Value[T any] struct { + val T +} + +// The noinline directive should survive across import, and prevent instantiations +// of these functions from being inlined. + +//go:noinline +func Get[T any](v *Value[T]) T { + return v.val +} + +//go:noinline +func Set[T any](v *Value[T], val T) { + v.val = val +} + +//go:noinline +func (v *Value[T]) Set(val T) { + v.val = val +} + +//go:noinline +func (v *Value[T]) Get() T { + return v.val +} diff --git a/test/typeparam/valimp.dir/main.go b/test/typeparam/valimp.dir/main.go new file mode 100644 index 0000000000..925fb1e699 --- /dev/null +++ b/test/typeparam/valimp.dir/main.go @@ -0,0 +1,56 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "a" + "fmt" +) + +func main() { + var v1 a.Value[int] + + a.Set(&v1, 1) + if got, want := a.Get(&v1), 1; got != want { + panic(fmt.Sprintf("Get() == %d, want %d", got, want)) + } + v1.Set(2) + if got, want := v1.Get(), 2; got != want { + panic(fmt.Sprintf("Get() == %d, want %d", got, want)) + } + v1p := new(a.Value[int]) + a.Set(v1p, 3) + if got, want := a.Get(v1p), 3; got != want { + panic(fmt.Sprintf("Get() == %d, want %d", got, want)) + } + + v1p.Set(4) + if got, want := v1p.Get(), 4; got != want { + panic(fmt.Sprintf("Get() == %d, want %d", got, want)) + } + + var v2 a.Value[string] + a.Set(&v2, "a") + if got, want := a.Get(&v2), "a"; got != want { + panic(fmt.Sprintf("Get() == %q, want %q", got, want)) + } + + v2.Set("b") + if got, want := a.Get(&v2), "b"; got != want { + panic(fmt.Sprintf("Get() == %q, want %q", got, want)) + } + + v2p := new(a.Value[string]) + a.Set(v2p, "c") + if got, want := a.Get(v2p), "c"; got != want { + panic(fmt.Sprintf("Get() == %d, want %d", got, want)) + } + + v2p.Set("d") + if got, want := v2p.Get(), "d"; got != want { + panic(fmt.Sprintf("Get() == %d, want %d", got, want)) + } +} + diff --git a/test/typeparam/valimp.go b/test/typeparam/valimp.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/valimp.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From 7b3ee6102d4690c768a7a4b303a89f3f8c811124 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 14 Apr 2021 09:34:17 -0700 Subject: [PATCH 0107/2500] [dev.typeparams] cmd/compile: move to new export version, keep reading previous version I added constants for the previous export versions, and for the final generics export version. I also added a const for the current export version. We can increment the current export version for unstable changes in dev.typeparams, and eventally set it back to the generics version (2) before release. Added the same constants in typecheck/iexport.go, importer/iimport.go, and gcimporter/iimport.go, must be kept in sync. Put in the needed conditionals to be able to read old versions. Added new export/import test listimp.dir. Change-Id: I166d17d943e07951aa752562e952b067704aeeca Reviewed-on: https://go-review.googlesource.com/c/go/+/319931 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/importer/iimport.go | 47 +++++++++++++---- src/cmd/compile/internal/typecheck/iexport.go | 14 ++++-- src/cmd/compile/internal/typecheck/iimport.go | 32 +++++++++--- src/go/internal/gcimporter/gcimporter_test.go | 2 +- src/go/internal/gcimporter/iimport.go | 49 ++++++++++++------ test/typeparam/listimp.dir/a.go | 50 +++++++++++++++++++ test/typeparam/listimp.dir/main.go | 48 ++++++++++++++++++ test/typeparam/listimp.go | 7 +++ 8 files changed, 214 insertions(+), 35 deletions(-) create mode 100644 test/typeparam/listimp.dir/a.go create mode 100644 test/typeparam/listimp.dir/main.go create mode 100644 test/typeparam/listimp.go diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index a4637ec34f..37e5113435 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -1,4 +1,3 @@ -// UNREVIEWED // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -42,6 +41,16 @@ func (r *intReader) uint64() uint64 { return i } +// Keep this in sync with constants in iexport.go. +const ( + iexportVersionGo1_11 = 0 + iexportVersionPosCol = 1 + iexportVersionGenerics = 2 + + // Start of the unstable series of versions, remove "+ n" before release. + iexportVersionCurrent = iexportVersionGenerics + 1 +) + const predeclReserved = 32 type itag uint64 @@ -68,7 +77,7 @@ const io_SeekCurrent = 1 // io.SeekCurrent (not defined in Go 1.4) // If the export data version is not recognized or the format is otherwise // compromised, an error is returned. func iImportData(imports map[string]*types2.Package, data []byte, path string) (_ int, pkg *types2.Package, err error) { - const currentVersion = 1 + const currentVersion = iexportVersionCurrent version := int64(-1) defer func() { if e := recover(); e != nil { @@ -84,9 +93,13 @@ func iImportData(imports map[string]*types2.Package, data []byte, path string) ( version = int64(r.uint64()) switch version { - case currentVersion, 0: + case currentVersion, iexportVersionPosCol, iexportVersionGo1_11: default: - errorf("unknown iexport format version %d", version) + if version > iexportVersionGenerics { + errorf("unstable iexport format version %d, just rebuild compiler and std library", version) + } else { + errorf("unknown iexport format version %d", version) + } } sLen := int64(r.uint64()) @@ -98,8 +111,9 @@ func iImportData(imports map[string]*types2.Package, data []byte, path string) ( r.Seek(sLen+dLen, io_SeekCurrent) p := iimporter{ - ipath: path, - version: int(version), + exportVersion: version, + ipath: path, + version: int(version), stringData: stringData, stringCache: make(map[uint64]string), @@ -178,8 +192,9 @@ func iImportData(imports map[string]*types2.Package, data []byte, path string) ( } type iimporter struct { - ipath string - version int + exportVersion int64 + ipath string + version int stringData []byte stringCache map[uint64]string @@ -294,14 +309,20 @@ func (r *importReader) obj(name string) { r.declare(types2.NewConst(pos, r.currPkg, name, typ, val)) case 'F': - tparams := r.tparamList() + var tparams []*types2.TypeName + if r.p.exportVersion >= iexportVersionGenerics { + tparams = r.tparamList() + } sig := r.signature(nil) sig.SetTParams(tparams) r.declare(types2.NewFunc(pos, r.currPkg, name, sig)) case 'T': - tparams := r.tparamList() + var tparams []*types2.TypeName + if r.p.exportVersion >= iexportVersionGenerics { + tparams = r.tparamList() + } // Types can be recursive. We need to setup a stub // declaration before recursing. @@ -592,6 +613,9 @@ func (r *importReader) doType(base *types2.Named) types2.Type { return typ case typeParamType: + if r.p.exportVersion < iexportVersionGenerics { + errorf("unexpected type param type") + } r.currPkg = r.pkg() pos := r.pos() name := r.string() @@ -622,6 +646,9 @@ func (r *importReader) doType(base *types2.Named) types2.Type { return t case instType: + if r.p.exportVersion < iexportVersionGenerics { + errorf("unexpected instantiation type") + } pos := r.pos() len := r.uint64() targs := make([]types2.Type, len) diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 11b9755148..e6813adbf9 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -223,9 +223,17 @@ import ( ) // Current indexed export format version. Increase with each format change. -// 1: added column details to Pos // 0: Go1.11 encoding -const iexportVersion = 1 +// 1: added column details to Pos +// 2: added information for generic function/types (currently unstable) +const ( + iexportVersionGo1_11 = 0 + iexportVersionPosCol = 1 + iexportVersionGenerics = 2 + + // Start of the unstable series of versions, remove "+ n" before release. + iexportVersionCurrent = iexportVersionGenerics + 1 +) // predeclReserved is the number of type offsets reserved for types // implicitly declared in the universe block. @@ -297,7 +305,7 @@ func WriteExports(out *bufio.Writer) { // Assemble header. var hdr intWriter hdr.WriteByte('i') - hdr.uint64(iexportVersion) + hdr.uint64(iexportVersionCurrent) hdr.uint64(uint64(p.strings.Len())) hdr.uint64(dataLen) diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index b6f227bb00..778ce4be12 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -121,8 +121,14 @@ func ReadImports(pkg *types.Pkg, in *bio.Reader) (fingerprint goobj.FingerprintT ird := &intReader{in, pkg} version := ird.uint64() - if version != iexportVersion { - base.Errorf("import %q: unknown export format version %d", pkg.Path, version) + switch version { + case iexportVersionCurrent, iexportVersionPosCol, iexportVersionGo1_11: + default: + if version > iexportVersionGenerics { + base.Errorf("import %q: unstable export format version %d, just recompile", pkg.Path, version) + } else { + base.Errorf("import %q: unknown export format version %d", pkg.Path, version) + } base.ErrorExit() } @@ -143,7 +149,8 @@ func ReadImports(pkg *types.Pkg, in *bio.Reader) (fingerprint goobj.FingerprintT in.MustSeek(int64(sLen+dLen), os.SEEK_CUR) p := &iimporter{ - ipkg: pkg, + exportVersion: version, + ipkg: pkg, pkgCache: map[uint64]*types.Pkg{}, posBaseCache: map[uint64]*src.PosBase{}, @@ -212,7 +219,8 @@ func ReadImports(pkg *types.Pkg, in *bio.Reader) (fingerprint goobj.FingerprintT } type iimporter struct { - ipkg *types.Pkg + exportVersion uint64 + ipkg *types.Pkg pkgCache map[uint64]*types.Pkg posBaseCache map[uint64]*src.PosBase @@ -314,7 +322,10 @@ func (r *importReader) doDecl(sym *types.Sym) *ir.Name { return n case 'F': - tparams := r.tparamList() + var tparams []*types.Field + if r.p.exportVersion >= iexportVersionGenerics { + tparams = r.tparamList() + } typ := r.signature(nil, tparams) n := importfunc(r.p.ipkg, pos, sym, typ) @@ -322,7 +333,10 @@ func (r *importReader) doDecl(sym *types.Sym) *ir.Name { return n case 'T': - rparams := r.typeList() + var rparams []*types.Type + if r.p.exportVersion >= iexportVersionGenerics { + rparams = r.typeList() + } // Types can be recursive. We need to setup a stub // declaration before recursing. @@ -738,6 +752,9 @@ func (r *importReader) typ1() *types.Type { return t case typeParamType: + if r.p.exportVersion < iexportVersionGenerics { + base.Fatalf("unexpected type param type") + } r.setPkg() pos := r.pos() name := r.string() @@ -761,6 +778,9 @@ func (r *importReader) typ1() *types.Type { return t case instType: + if r.p.exportVersion < iexportVersionGenerics { + base.Fatalf("unexpected instantiation type") + } pos := r.pos() len := r.uint64() targs := make([]*types.Type, len) diff --git a/src/go/internal/gcimporter/gcimporter_test.go b/src/go/internal/gcimporter/gcimporter_test.go index c010dc506e..286b8a6347 100644 --- a/src/go/internal/gcimporter/gcimporter_test.go +++ b/src/go/internal/gcimporter/gcimporter_test.go @@ -139,7 +139,7 @@ func TestVersionHandling(t *testing.T) { // This package only handles gc export data. // Disable test until we put in the new export version. - if true || runtime.Compiler != "gc" { + if runtime.Compiler != "gc" { t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) } diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go index 4416f5b2b9..e003dc9767 100644 --- a/src/go/internal/gcimporter/iimport.go +++ b/src/go/internal/gcimporter/iimport.go @@ -40,6 +40,16 @@ func (r *intReader) uint64() uint64 { return i } +// Keep this in sync with constants in iexport.go. +const ( + iexportVersionGo1_11 = 0 + iexportVersionPosCol = 1 + iexportVersionGenerics = 2 + + // Start of the unstable series of versions, remove "+ n" before release. + iexportVersionCurrent = iexportVersionGenerics + 1 +) + const predeclReserved = 32 type itag uint64 @@ -64,7 +74,7 @@ const ( // If the export data version is not recognized or the format is otherwise // compromised, an error is returned. func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) { - const currentVersion = 1 + const currentVersion = iexportVersionCurrent version := int64(-1) defer func() { if e := recover(); e != nil { @@ -80,9 +90,13 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, data [] version = int64(r.uint64()) switch version { - case currentVersion, 0: + case currentVersion, iexportVersionPosCol, iexportVersionGo1_11: default: - errorf("unknown iexport format version %d", version) + if version > iexportVersionGenerics { + errorf("unstable iexport format version %d, just rebuild compiler and std library", version) + } else { + errorf("unknown iexport format version %d", version) + } } sLen := int64(r.uint64()) @@ -94,8 +108,9 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, data [] r.Seek(sLen+dLen, io.SeekCurrent) p := iimporter{ - ipath: path, - version: int(version), + exportVersion: version, + ipath: path, + version: int(version), stringData: stringData, stringCache: make(map[uint64]string), @@ -173,8 +188,9 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, data [] } type iimporter struct { - ipath string - version int + exportVersion int64 + ipath string + version int stringData []byte stringCache map[uint64]string @@ -273,19 +289,22 @@ func (r *importReader) obj(name string) { r.declare(types.NewConst(pos, r.currPkg, name, typ, val)) case 'F': - numTparams := r.uint64() - if numTparams > 0 { - errorf("unexpected tparam") - return + if r.p.exportVersion >= iexportVersionGenerics { + numTparams := r.uint64() + if numTparams > 0 { + errorf("unexpected tparam") + } } sig := r.signature(nil) r.declare(types.NewFunc(pos, r.currPkg, name, sig)) case 'T': - numTparams := r.uint64() - if numTparams > 0 { - errorf("unexpected tparam") + if r.p.exportVersion >= iexportVersionGenerics { + numTparams := r.uint64() + if numTparams > 0 { + errorf("unexpected tparam") + } } // Types can be recursive. We need to setup a stub @@ -562,7 +581,7 @@ func (r *importReader) doType(base *types.Named) types.Type { return typ case typeParamType: - errorf("do not handle tparams yet") + errorf("do not handle type param types yet") return nil case instType: diff --git a/test/typeparam/listimp.dir/a.go b/test/typeparam/listimp.dir/a.go new file mode 100644 index 0000000000..ea569751a6 --- /dev/null +++ b/test/typeparam/listimp.dir/a.go @@ -0,0 +1,50 @@ +package a + +type Ordered interface { + type int, int8, int16, int32, int64, + uint, uint8, uint16, uint32, uint64, uintptr, + float32, float64, + string +} + +// List is a linked list of ordered values of type T. +type List[T Ordered] struct { + Next *List[T] + Val T +} + +func (l *List[T]) Largest() T { + var max T + for p := l; p != nil; p = p.Next { + if p.Val > max { + max = p.Val + } + } + return max +} + +type OrderedNum interface { + type int, int8, int16, int32, int64, + uint, uint8, uint16, uint32, uint64, uintptr, + float32, float64 +} + +// ListNum is a linked _List of ordered numeric values of type T. +type ListNum[T OrderedNum] struct { + Next *ListNum[T] + Val T +} + +const Clip = 5 + +// clippedLargest returns the largest in the list of OrderNums, but a max of 5. +// TODO(danscales): fix export/import of an untype constant with typeparam type +func (l *ListNum[T]) ClippedLargest() T { + var max T + for p := l; p != nil; p = p.Next { + if p.Val > max && p.Val < T(Clip) { + max = p.Val + } + } + return max +} diff --git a/test/typeparam/listimp.dir/main.go b/test/typeparam/listimp.dir/main.go new file mode 100644 index 0000000000..4c1aa3e493 --- /dev/null +++ b/test/typeparam/listimp.dir/main.go @@ -0,0 +1,48 @@ +package main + +import ( + "a" + "fmt" +) + +func main() { + i3 := &a.List[int]{nil, 1} + i2 := &a.List[int]{i3, 3} + i1 := &a.List[int]{i2, 2} + if got, want := i1.Largest(), 3; got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } + + b3 := &a.List[byte]{nil, byte(1)} + b2 := &a.List[byte]{b3, byte(3)} + b1 := &a.List[byte]{b2, byte(2)} + if got, want := b1.Largest(), byte(3); got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } + + f3 := &a.List[float64]{nil, 13.5} + f2 := &a.List[float64]{f3, 1.2} + f1 := &a.List[float64]{f2, 4.5} + if got, want := f1.Largest(), 13.5; got != want { + panic(fmt.Sprintf("got %f, want %f", got, want)) + } + + s3 := &a.List[string]{nil, "dd"} + s2 := &a.List[string]{s3, "aa"} + s1 := &a.List[string]{s2, "bb"} + if got, want := s1.Largest(), "dd"; got != want { + panic(fmt.Sprintf("got %s, want %s", got, want)) + } + j3 := &a.ListNum[int]{nil, 1} + j2 := &a.ListNum[int]{j3, 32} + j1 := &a.ListNum[int]{j2, 2} + if got, want := j1.ClippedLargest(), 2; got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } + g3 := &a.ListNum[float64]{nil, 13.5} + g2 := &a.ListNum[float64]{g3, 1.2} + g1 := &a.ListNum[float64]{g2, 4.5} + if got, want := g1.ClippedLargest(), 4.5; got != want { + panic(fmt.Sprintf("got %f, want %f", got, want)) + } +} diff --git a/test/typeparam/listimp.go b/test/typeparam/listimp.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/listimp.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From 60f16d7f19c2787e22bda198b7595035c1702f06 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Thu, 20 May 2021 17:42:06 -0400 Subject: [PATCH 0108/2500] [dev.fuzz] internal/fuzz: remove old TODO Change-Id: I997934ebcde0dee9017c85a0572597855d73cf64 Reviewed-on: https://go-review.googlesource.com/c/go/+/321569 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Roland Shoemaker Reviewed-by: Jay Conrod --- src/internal/fuzz/worker.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 91ae2de1b1..c2cacf986b 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -320,10 +320,6 @@ func (w *worker) start() (err error) { cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr - // TODO(jayconrod): set up shared memory between the coordinator and worker to - // transfer values and coverage data. If the worker crashes, we need to be - // able to find the value that caused the crash. - // Create the "fuzz_in" and "fuzz_out" pipes so we can communicate with // the worker. We don't use stdin and stdout, since the test binary may // do something else with those. -- GitLab From 211244e1720942af2f2b77b8c96ff7f3a019df31 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 20 May 2021 14:40:11 -0700 Subject: [PATCH 0109/2500] [dev.typeparams] cmd/compile/internal/types2: move interface checking into separate file This only moves functionality from one file into another. Except for import adjustments there are no changes to the code. Change-Id: Ia7d611d3a01c1ed3331dcc7cfe94a96f87b338e7 Reviewed-on: https://go-review.googlesource.com/c/go/+/321549 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/interface.go | 320 +++++++++++++++++++ src/cmd/compile/internal/types2/typexpr.go | 311 ------------------ 2 files changed, 320 insertions(+), 311 deletions(-) create mode 100644 src/cmd/compile/internal/types2/interface.go diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go new file mode 100644 index 0000000000..bbd25cbd09 --- /dev/null +++ b/src/cmd/compile/internal/types2/interface.go @@ -0,0 +1,320 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types2 + +import ( + "cmd/compile/internal/syntax" + "sort" +) + +func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType, def *Named) { + var tname *syntax.Name // most recent "type" name + var types []syntax.Expr + for _, f := range iface.MethodList { + if f.Name != nil { + // We have a method with name f.Name, or a type + // of a type list (f.Name.Value == "type"). + name := f.Name.Value + if name == "_" { + if check.conf.CompilerErrorMessages { + check.error(f.Name, "methods must have a unique non-blank name") + } else { + check.error(f.Name, "invalid method name _") + } + continue // ignore + } + + if name == "type" { + // Always collect all type list entries, even from + // different type lists, under the assumption that + // the author intended to include all types. + types = append(types, f.Type) + if tname != nil && tname != f.Name { + check.error(f.Name, "cannot have multiple type lists in an interface") + } + tname = f.Name + continue + } + + typ := check.typ(f.Type) + sig, _ := typ.(*Signature) + if sig == nil { + if typ != Typ[Invalid] { + check.errorf(f.Type, invalidAST+"%s is not a method signature", typ) + } + continue // ignore + } + + // Always type-check method type parameters but complain if they are not enabled. + // (This extra check is needed here because interface method signatures don't have + // a receiver specification.) + if sig.tparams != nil && !acceptMethodTypeParams { + check.error(f.Type, "methods cannot have type parameters") + } + + // use named receiver type if available (for better error messages) + var recvTyp Type = ityp + if def != nil { + recvTyp = def + } + sig.recv = NewVar(f.Name.Pos(), check.pkg, "", recvTyp) + + m := NewFunc(f.Name.Pos(), check.pkg, name, sig) + check.recordDef(f.Name, m) + ityp.methods = append(ityp.methods, m) + } else { + // We have an embedded type. completeInterface will + // eventually verify that we have an interface. + ityp.embeddeds = append(ityp.embeddeds, check.typ(f.Type)) + check.posMap[ityp] = append(check.posMap[ityp], f.Type.Pos()) + } + } + + // type constraints + ityp.types = NewSum(check.collectTypeConstraints(iface.Pos(), types)) + + if len(ityp.methods) == 0 && ityp.types == nil && len(ityp.embeddeds) == 0 { + // empty interface + ityp.allMethods = markComplete + return + } + + // sort for API stability + sortMethods(ityp.methods) + sortTypes(ityp.embeddeds) + + check.later(func() { check.completeInterface(iface.Pos(), ityp) }) +} + +func (check *Checker) collectTypeConstraints(pos syntax.Pos, types []syntax.Expr) []Type { + list := make([]Type, 0, len(types)) // assume all types are correct + for _, texpr := range types { + if texpr == nil { + check.error(pos, invalidAST+"missing type constraint") + continue + } + list = append(list, check.varType(texpr)) + } + + // Ensure that each type is only present once in the type list. Types may be + // interfaces, which may not be complete yet. It's ok to do this check at the + // end because it's not a requirement for correctness of the code. + // Note: This is a quadratic algorithm, but type lists tend to be short. + check.later(func() { + for i, t := range list { + if t := asInterface(t); t != nil { + check.completeInterface(types[i].Pos(), t) + } + if includes(list[:i], t) { + check.softErrorf(types[i], "duplicate type %s in type list", t) + } + } + }) + + return list +} + +// includes reports whether typ is in list +func includes(list []Type, typ Type) bool { + for _, e := range list { + if Identical(typ, e) { + return true + } + } + return false +} + +func (check *Checker) completeInterface(pos syntax.Pos, ityp *Interface) { + if ityp.allMethods != nil { + return + } + + // completeInterface may be called via the LookupFieldOrMethod, + // MissingMethod, Identical, or IdenticalIgnoreTags external API + // in which case check will be nil. In this case, type-checking + // must be finished and all interfaces should have been completed. + if check == nil { + panic("internal error: incomplete interface") + } + + if check.conf.Trace { + // Types don't generally have position information. + // If we don't have a valid pos provided, try to use + // one close enough. + if !pos.IsKnown() && len(ityp.methods) > 0 { + pos = ityp.methods[0].pos + } + + check.trace(pos, "complete %s", ityp) + check.indent++ + defer func() { + check.indent-- + check.trace(pos, "=> %s (methods = %v, types = %v)", ityp, ityp.allMethods, ityp.allTypes) + }() + } + + // An infinitely expanding interface (due to a cycle) is detected + // elsewhere (Checker.validType), so here we simply assume we only + // have valid interfaces. Mark the interface as complete to avoid + // infinite recursion if the validType check occurs later for some + // reason. + ityp.allMethods = markComplete + + // Methods of embedded interfaces are collected unchanged; i.e., the identity + // of a method I.m's Func Object of an interface I is the same as that of + // the method m in an interface that embeds interface I. On the other hand, + // if a method is embedded via multiple overlapping embedded interfaces, we + // don't provide a guarantee which "original m" got chosen for the embedding + // interface. See also issue #34421. + // + // If we don't care to provide this identity guarantee anymore, instead of + // reusing the original method in embeddings, we can clone the method's Func + // Object and give it the position of a corresponding embedded interface. Then + // we can get rid of the mpos map below and simply use the cloned method's + // position. + + var seen objset + var methods []*Func + mpos := make(map[*Func]syntax.Pos) // method specification or method embedding position, for good error messages + addMethod := func(pos syntax.Pos, m *Func, explicit bool) { + switch other := seen.insert(m); { + case other == nil: + methods = append(methods, m) + mpos[m] = pos + case explicit: + var err error_ + err.errorf(pos, "duplicate method %s", m.name) + err.errorf(mpos[other.(*Func)], "other declaration of %s", m.name) + check.report(&err) + default: + // We have a duplicate method name in an embedded (not explicitly declared) method. + // Check method signatures after all types are computed (issue #33656). + // If we're pre-go1.14 (overlapping embeddings are not permitted), report that + // error here as well (even though we could do it eagerly) because it's the same + // error message. + check.later(func() { + if !check.allowVersion(m.pkg, 1, 14) || !check.identical(m.typ, other.Type()) { + var err error_ + err.errorf(pos, "duplicate method %s", m.name) + err.errorf(mpos[other.(*Func)], "other declaration of %s", m.name) + check.report(&err) + } + }) + } + } + + for _, m := range ityp.methods { + addMethod(m.pos, m, true) + } + + // collect types + allTypes := ityp.types + + posList := check.posMap[ityp] + for i, typ := range ityp.embeddeds { + pos := posList[i] // embedding position + utyp := under(typ) + etyp := asInterface(utyp) + if etyp == nil { + if utyp != Typ[Invalid] { + var format string + if _, ok := utyp.(*TypeParam); ok { + format = "%s is a type parameter, not an interface" + } else { + format = "%s is not an interface" + } + check.errorf(pos, format, typ) + } + continue + } + check.completeInterface(pos, etyp) + for _, m := range etyp.allMethods { + addMethod(pos, m, false) // use embedding position pos rather than m.pos + } + allTypes = intersect(allTypes, etyp.allTypes) + } + + if methods != nil { + sortMethods(methods) + ityp.allMethods = methods + } + ityp.allTypes = allTypes +} + +// intersect computes the intersection of the types x and y. +// Note: A incomming nil type stands for the top type. A top +// type result is returned as nil. +func intersect(x, y Type) (r Type) { + defer func() { + if r == theTop { + r = nil + } + }() + + switch { + case x == theBottom || y == theBottom: + return theBottom + case x == nil || x == theTop: + return y + case y == nil || x == theTop: + return x + } + + xtypes := unpack(x) + ytypes := unpack(y) + // Compute the list rtypes which includes only + // types that are in both xtypes and ytypes. + // Quadratic algorithm, but good enough for now. + // TODO(gri) fix this + var rtypes []Type + for _, x := range xtypes { + if includes(ytypes, x) { + rtypes = append(rtypes, x) + } + } + + if rtypes == nil { + return theBottom + } + return NewSum(rtypes) +} + +func sortTypes(list []Type) { + sort.Stable(byUniqueTypeName(list)) +} + +// byUniqueTypeName named type lists can be sorted by their unique type names. +type byUniqueTypeName []Type + +func (a byUniqueTypeName) Len() int { return len(a) } +func (a byUniqueTypeName) Less(i, j int) bool { return sortObj(a[i]).less(sortObj(a[j])) } +func (a byUniqueTypeName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +func sortObj(t Type) *object { + if named := asNamed(t); named != nil { + return &named.obj.object + } + return nil +} + +func sortMethods(list []*Func) { + sort.Sort(byUniqueMethodName(list)) +} + +func assertSortedMethods(list []*Func) { + if !debug { + panic("internal error: assertSortedMethods called outside debug mode") + } + if !sort.IsSorted(byUniqueMethodName(list)) { + panic("internal error: methods not sorted") + } +} + +// byUniqueMethodName method lists can be sorted by their unique method names. +type byUniqueMethodName []*Func + +func (a byUniqueMethodName) Len() int { return len(a) } +func (a byUniqueMethodName) Less(i, j int) bool { return a[i].less(&a[j].object) } +func (a byUniqueMethodName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 7fb914cd7e..bae4d3e4b5 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -10,7 +10,6 @@ import ( "cmd/compile/internal/syntax" "fmt" "go/constant" - "sort" "strconv" "strings" ) @@ -813,278 +812,6 @@ func (check *Checker) declareInSet(oset *objset, pos syntax.Pos, obj Object) boo return true } -func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType, def *Named) { - var tname *syntax.Name // most recent "type" name - var types []syntax.Expr - for _, f := range iface.MethodList { - if f.Name != nil { - // We have a method with name f.Name, or a type - // of a type list (f.Name.Value == "type"). - name := f.Name.Value - if name == "_" { - if check.conf.CompilerErrorMessages { - check.error(f.Name, "methods must have a unique non-blank name") - } else { - check.error(f.Name, "invalid method name _") - } - continue // ignore - } - - if name == "type" { - // Always collect all type list entries, even from - // different type lists, under the assumption that - // the author intended to include all types. - types = append(types, f.Type) - if tname != nil && tname != f.Name { - check.error(f.Name, "cannot have multiple type lists in an interface") - } - tname = f.Name - continue - } - - typ := check.typ(f.Type) - sig, _ := typ.(*Signature) - if sig == nil { - if typ != Typ[Invalid] { - check.errorf(f.Type, invalidAST+"%s is not a method signature", typ) - } - continue // ignore - } - - // Always type-check method type parameters but complain if they are not enabled. - // (This extra check is needed here because interface method signatures don't have - // a receiver specification.) - if sig.tparams != nil && !acceptMethodTypeParams { - check.error(f.Type, "methods cannot have type parameters") - } - - // use named receiver type if available (for better error messages) - var recvTyp Type = ityp - if def != nil { - recvTyp = def - } - sig.recv = NewVar(f.Name.Pos(), check.pkg, "", recvTyp) - - m := NewFunc(f.Name.Pos(), check.pkg, name, sig) - check.recordDef(f.Name, m) - ityp.methods = append(ityp.methods, m) - } else { - // We have an embedded type. completeInterface will - // eventually verify that we have an interface. - ityp.embeddeds = append(ityp.embeddeds, check.typ(f.Type)) - check.posMap[ityp] = append(check.posMap[ityp], f.Type.Pos()) - } - } - - // type constraints - ityp.types = NewSum(check.collectTypeConstraints(iface.Pos(), types)) - - if len(ityp.methods) == 0 && ityp.types == nil && len(ityp.embeddeds) == 0 { - // empty interface - ityp.allMethods = markComplete - return - } - - // sort for API stability - sortMethods(ityp.methods) - sortTypes(ityp.embeddeds) - - check.later(func() { check.completeInterface(iface.Pos(), ityp) }) -} - -func (check *Checker) completeInterface(pos syntax.Pos, ityp *Interface) { - if ityp.allMethods != nil { - return - } - - // completeInterface may be called via the LookupFieldOrMethod, - // MissingMethod, Identical, or IdenticalIgnoreTags external API - // in which case check will be nil. In this case, type-checking - // must be finished and all interfaces should have been completed. - if check == nil { - panic("internal error: incomplete interface") - } - - if check.conf.Trace { - // Types don't generally have position information. - // If we don't have a valid pos provided, try to use - // one close enough. - if !pos.IsKnown() && len(ityp.methods) > 0 { - pos = ityp.methods[0].pos - } - - check.trace(pos, "complete %s", ityp) - check.indent++ - defer func() { - check.indent-- - check.trace(pos, "=> %s (methods = %v, types = %v)", ityp, ityp.allMethods, ityp.allTypes) - }() - } - - // An infinitely expanding interface (due to a cycle) is detected - // elsewhere (Checker.validType), so here we simply assume we only - // have valid interfaces. Mark the interface as complete to avoid - // infinite recursion if the validType check occurs later for some - // reason. - ityp.allMethods = markComplete - - // Methods of embedded interfaces are collected unchanged; i.e., the identity - // of a method I.m's Func Object of an interface I is the same as that of - // the method m in an interface that embeds interface I. On the other hand, - // if a method is embedded via multiple overlapping embedded interfaces, we - // don't provide a guarantee which "original m" got chosen for the embedding - // interface. See also issue #34421. - // - // If we don't care to provide this identity guarantee anymore, instead of - // reusing the original method in embeddings, we can clone the method's Func - // Object and give it the position of a corresponding embedded interface. Then - // we can get rid of the mpos map below and simply use the cloned method's - // position. - - var seen objset - var methods []*Func - mpos := make(map[*Func]syntax.Pos) // method specification or method embedding position, for good error messages - addMethod := func(pos syntax.Pos, m *Func, explicit bool) { - switch other := seen.insert(m); { - case other == nil: - methods = append(methods, m) - mpos[m] = pos - case explicit: - var err error_ - err.errorf(pos, "duplicate method %s", m.name) - err.errorf(mpos[other.(*Func)], "other declaration of %s", m.name) - check.report(&err) - default: - // We have a duplicate method name in an embedded (not explicitly declared) method. - // Check method signatures after all types are computed (issue #33656). - // If we're pre-go1.14 (overlapping embeddings are not permitted), report that - // error here as well (even though we could do it eagerly) because it's the same - // error message. - check.later(func() { - if !check.allowVersion(m.pkg, 1, 14) || !check.identical(m.typ, other.Type()) { - var err error_ - err.errorf(pos, "duplicate method %s", m.name) - err.errorf(mpos[other.(*Func)], "other declaration of %s", m.name) - check.report(&err) - } - }) - } - } - - for _, m := range ityp.methods { - addMethod(m.pos, m, true) - } - - // collect types - allTypes := ityp.types - - posList := check.posMap[ityp] - for i, typ := range ityp.embeddeds { - pos := posList[i] // embedding position - utyp := under(typ) - etyp := asInterface(utyp) - if etyp == nil { - if utyp != Typ[Invalid] { - var format string - if _, ok := utyp.(*TypeParam); ok { - format = "%s is a type parameter, not an interface" - } else { - format = "%s is not an interface" - } - check.errorf(pos, format, typ) - } - continue - } - check.completeInterface(pos, etyp) - for _, m := range etyp.allMethods { - addMethod(pos, m, false) // use embedding position pos rather than m.pos - } - allTypes = intersect(allTypes, etyp.allTypes) - } - - if methods != nil { - sortMethods(methods) - ityp.allMethods = methods - } - ityp.allTypes = allTypes -} - -// intersect computes the intersection of the types x and y. -// Note: A incomming nil type stands for the top type. A top -// type result is returned as nil. -func intersect(x, y Type) (r Type) { - defer func() { - if r == theTop { - r = nil - } - }() - - switch { - case x == theBottom || y == theBottom: - return theBottom - case x == nil || x == theTop: - return y - case y == nil || x == theTop: - return x - } - - xtypes := unpack(x) - ytypes := unpack(y) - // Compute the list rtypes which includes only - // types that are in both xtypes and ytypes. - // Quadratic algorithm, but good enough for now. - // TODO(gri) fix this - var rtypes []Type - for _, x := range xtypes { - if includes(ytypes, x) { - rtypes = append(rtypes, x) - } - } - - if rtypes == nil { - return theBottom - } - return NewSum(rtypes) -} - -func sortTypes(list []Type) { - sort.Stable(byUniqueTypeName(list)) -} - -// byUniqueTypeName named type lists can be sorted by their unique type names. -type byUniqueTypeName []Type - -func (a byUniqueTypeName) Len() int { return len(a) } -func (a byUniqueTypeName) Less(i, j int) bool { return sortObj(a[i]).less(sortObj(a[j])) } -func (a byUniqueTypeName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } - -func sortObj(t Type) *object { - if named := asNamed(t); named != nil { - return &named.obj.object - } - return nil -} - -func sortMethods(list []*Func) { - sort.Sort(byUniqueMethodName(list)) -} - -func assertSortedMethods(list []*Func) { - if !debug { - panic("internal error: assertSortedMethods called outside debug mode") - } - if !sort.IsSorted(byUniqueMethodName(list)) { - panic("internal error: methods not sorted") - } -} - -// byUniqueMethodName method lists can be sorted by their unique method names. -type byUniqueMethodName []*Func - -func (a byUniqueMethodName) Len() int { return len(a) } -func (a byUniqueMethodName) Less(i, j int) bool { return a[i].less(&a[j].object) } -func (a byUniqueMethodName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } - func (check *Checker) tag(t *syntax.BasicLit) string { // If t.Bad, an error was reported during parsing. if t != nil && !t.Bad { @@ -1222,44 +949,6 @@ func embeddedFieldIdent(e syntax.Expr) *syntax.Name { return nil // invalid embedded field } -func (check *Checker) collectTypeConstraints(pos syntax.Pos, types []syntax.Expr) []Type { - list := make([]Type, 0, len(types)) // assume all types are correct - for _, texpr := range types { - if texpr == nil { - check.error(pos, invalidAST+"missing type constraint") - continue - } - list = append(list, check.varType(texpr)) - } - - // Ensure that each type is only present once in the type list. Types may be - // interfaces, which may not be complete yet. It's ok to do this check at the - // end because it's not a requirement for correctness of the code. - // Note: This is a quadratic algorithm, but type lists tend to be short. - check.later(func() { - for i, t := range list { - if t := asInterface(t); t != nil { - check.completeInterface(types[i].Pos(), t) - } - if includes(list[:i], t) { - check.softErrorf(types[i], "duplicate type %s in type list", t) - } - } - }) - - return list -} - -// includes reports whether typ is in list -func includes(list []Type, typ Type) bool { - for _, e := range list { - if Identical(typ, e) { - return true - } - } - return false -} - func ptrBase(x *syntax.Operation) syntax.Expr { if x.Op == syntax.Mul && x.Y == nil { return x.X -- GitLab From cfe0250497aa2eaa7d3a9a56d815bfa1f4b9b8b5 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 20 May 2021 14:47:40 -0700 Subject: [PATCH 0110/2500] [dev.typeparams] cmd/compile/internal/types2: move struct checking into separate file This only moves functionality from one file into another. Except for import adjustments there are no changes to the code. Change-Id: I8dff41fe82693c96b09a152975c3fd1e3b439e8d Reviewed-on: https://go-review.googlesource.com/c/go/+/321589 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/struct.go | 165 +++++++++++++++++++++ src/cmd/compile/internal/types2/typexpr.go | 156 ------------------- 2 files changed, 165 insertions(+), 156 deletions(-) create mode 100644 src/cmd/compile/internal/types2/struct.go diff --git a/src/cmd/compile/internal/types2/struct.go b/src/cmd/compile/internal/types2/struct.go new file mode 100644 index 0000000000..302b9886f4 --- /dev/null +++ b/src/cmd/compile/internal/types2/struct.go @@ -0,0 +1,165 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types2 + +import ( + "cmd/compile/internal/syntax" + "strconv" +) + +func (check *Checker) structType(styp *Struct, e *syntax.StructType) { + if e.FieldList == nil { + return + } + + // struct fields and tags + var fields []*Var + var tags []string + + // for double-declaration checks + var fset objset + + // current field typ and tag + var typ Type + var tag string + add := func(ident *syntax.Name, embedded bool, pos syntax.Pos) { + if tag != "" && tags == nil { + tags = make([]string, len(fields)) + } + if tags != nil { + tags = append(tags, tag) + } + + name := ident.Value + fld := NewField(pos, check.pkg, name, typ, embedded) + // spec: "Within a struct, non-blank field names must be unique." + if name == "_" || check.declareInSet(&fset, pos, fld) { + fields = append(fields, fld) + check.recordDef(ident, fld) + } + } + + // addInvalid adds an embedded field of invalid type to the struct for + // fields with errors; this keeps the number of struct fields in sync + // with the source as long as the fields are _ or have different names + // (issue #25627). + addInvalid := func(ident *syntax.Name, pos syntax.Pos) { + typ = Typ[Invalid] + tag = "" + add(ident, true, pos) + } + + var prev syntax.Expr + for i, f := range e.FieldList { + // Fields declared syntactically with the same type (e.g.: a, b, c T) + // share the same type expression. Only check type if it's a new type. + if i == 0 || f.Type != prev { + typ = check.varType(f.Type) + prev = f.Type + } + tag = "" + if i < len(e.TagList) { + tag = check.tag(e.TagList[i]) + } + if f.Name != nil { + // named field + add(f.Name, false, f.Name.Pos()) + } else { + // embedded field + // spec: "An embedded type must be specified as a type name T or as a + // pointer to a non-interface type name *T, and T itself may not be a + // pointer type." + pos := syntax.StartPos(f.Type) + name := embeddedFieldIdent(f.Type) + if name == nil { + check.errorf(pos, "invalid embedded field type %s", f.Type) + name = &syntax.Name{Value: "_"} // TODO(gri) need to set position to pos + addInvalid(name, pos) + continue + } + add(name, true, pos) + + // Because we have a name, typ must be of the form T or *T, where T is the name + // of a (named or alias) type, and t (= deref(typ)) must be the type of T. + // We must delay this check to the end because we don't want to instantiate + // (via under(t)) a possibly incomplete type. + embeddedTyp := typ // for closure below + embeddedPos := pos + check.later(func() { + t, isPtr := deref(embeddedTyp) + switch t := optype(t).(type) { + case *Basic: + if t == Typ[Invalid] { + // error was reported before + return + } + // unsafe.Pointer is treated like a regular pointer + if t.kind == UnsafePointer { + check.error(embeddedPos, "embedded field type cannot be unsafe.Pointer") + } + case *Pointer: + check.error(embeddedPos, "embedded field type cannot be a pointer") + case *Interface: + if isPtr { + check.error(embeddedPos, "embedded field type cannot be a pointer to an interface") + } + } + }) + } + } + + styp.fields = fields + styp.tags = tags +} + +func embeddedFieldIdent(e syntax.Expr) *syntax.Name { + switch e := e.(type) { + case *syntax.Name: + return e + case *syntax.Operation: + if base := ptrBase(e); base != nil { + // *T is valid, but **T is not + if op, _ := base.(*syntax.Operation); op == nil || ptrBase(op) == nil { + return embeddedFieldIdent(e.X) + } + } + case *syntax.SelectorExpr: + return e.Sel + case *syntax.IndexExpr: + return embeddedFieldIdent(e.X) + } + return nil // invalid embedded field +} + +func (check *Checker) declareInSet(oset *objset, pos syntax.Pos, obj Object) bool { + if alt := oset.insert(obj); alt != nil { + var err error_ + err.errorf(pos, "%s redeclared", obj.Name()) + err.recordAltDecl(alt) + check.report(&err) + return false + } + return true +} + +func (check *Checker) tag(t *syntax.BasicLit) string { + // If t.Bad, an error was reported during parsing. + if t != nil && !t.Bad { + if t.Kind == syntax.StringLit { + if val, err := strconv.Unquote(t.Value); err == nil { + return val + } + } + check.errorf(t, invalidAST+"incorrect tag syntax: %q", t.Value) + } + return "" +} + +func ptrBase(x *syntax.Operation) syntax.Expr { + if x.Op == syntax.Mul && x.Y == nil { + return x.X + } + return nil +} diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index bae4d3e4b5..2352030b9b 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -10,7 +10,6 @@ import ( "cmd/compile/internal/syntax" "fmt" "go/constant" - "strconv" "strings" ) @@ -800,158 +799,3 @@ func (check *Checker) collectParams(scope *Scope, list []*syntax.Field, type0 sy return } - -func (check *Checker) declareInSet(oset *objset, pos syntax.Pos, obj Object) bool { - if alt := oset.insert(obj); alt != nil { - var err error_ - err.errorf(pos, "%s redeclared", obj.Name()) - err.recordAltDecl(alt) - check.report(&err) - return false - } - return true -} - -func (check *Checker) tag(t *syntax.BasicLit) string { - // If t.Bad, an error was reported during parsing. - if t != nil && !t.Bad { - if t.Kind == syntax.StringLit { - if val, err := strconv.Unquote(t.Value); err == nil { - return val - } - } - check.errorf(t, invalidAST+"incorrect tag syntax: %q", t.Value) - } - return "" -} - -func (check *Checker) structType(styp *Struct, e *syntax.StructType) { - if e.FieldList == nil { - return - } - - // struct fields and tags - var fields []*Var - var tags []string - - // for double-declaration checks - var fset objset - - // current field typ and tag - var typ Type - var tag string - add := func(ident *syntax.Name, embedded bool, pos syntax.Pos) { - if tag != "" && tags == nil { - tags = make([]string, len(fields)) - } - if tags != nil { - tags = append(tags, tag) - } - - name := ident.Value - fld := NewField(pos, check.pkg, name, typ, embedded) - // spec: "Within a struct, non-blank field names must be unique." - if name == "_" || check.declareInSet(&fset, pos, fld) { - fields = append(fields, fld) - check.recordDef(ident, fld) - } - } - - // addInvalid adds an embedded field of invalid type to the struct for - // fields with errors; this keeps the number of struct fields in sync - // with the source as long as the fields are _ or have different names - // (issue #25627). - addInvalid := func(ident *syntax.Name, pos syntax.Pos) { - typ = Typ[Invalid] - tag = "" - add(ident, true, pos) - } - - var prev syntax.Expr - for i, f := range e.FieldList { - // Fields declared syntactically with the same type (e.g.: a, b, c T) - // share the same type expression. Only check type if it's a new type. - if i == 0 || f.Type != prev { - typ = check.varType(f.Type) - prev = f.Type - } - tag = "" - if i < len(e.TagList) { - tag = check.tag(e.TagList[i]) - } - if f.Name != nil { - // named field - add(f.Name, false, f.Name.Pos()) - } else { - // embedded field - // spec: "An embedded type must be specified as a type name T or as a - // pointer to a non-interface type name *T, and T itself may not be a - // pointer type." - pos := syntax.StartPos(f.Type) - name := embeddedFieldIdent(f.Type) - if name == nil { - check.errorf(pos, "invalid embedded field type %s", f.Type) - name = &syntax.Name{Value: "_"} // TODO(gri) need to set position to pos - addInvalid(name, pos) - continue - } - add(name, true, pos) - - // Because we have a name, typ must be of the form T or *T, where T is the name - // of a (named or alias) type, and t (= deref(typ)) must be the type of T. - // We must delay this check to the end because we don't want to instantiate - // (via under(t)) a possibly incomplete type. - embeddedTyp := typ // for closure below - embeddedPos := pos - check.later(func() { - t, isPtr := deref(embeddedTyp) - switch t := optype(t).(type) { - case *Basic: - if t == Typ[Invalid] { - // error was reported before - return - } - // unsafe.Pointer is treated like a regular pointer - if t.kind == UnsafePointer { - check.error(embeddedPos, "embedded field type cannot be unsafe.Pointer") - } - case *Pointer: - check.error(embeddedPos, "embedded field type cannot be a pointer") - case *Interface: - if isPtr { - check.error(embeddedPos, "embedded field type cannot be a pointer to an interface") - } - } - }) - } - } - - styp.fields = fields - styp.tags = tags -} - -func embeddedFieldIdent(e syntax.Expr) *syntax.Name { - switch e := e.(type) { - case *syntax.Name: - return e - case *syntax.Operation: - if base := ptrBase(e); base != nil { - // *T is valid, but **T is not - if op, _ := base.(*syntax.Operation); op == nil || ptrBase(op) == nil { - return embeddedFieldIdent(e.X) - } - } - case *syntax.SelectorExpr: - return e.Sel - case *syntax.IndexExpr: - return embeddedFieldIdent(e.X) - } - return nil // invalid embedded field -} - -func ptrBase(x *syntax.Operation) syntax.Expr { - if x.Op == syntax.Mul && x.Y == nil { - return x.X - } - return nil -} -- GitLab From 243076da64d251853ed7a69ce770e9fa71b5bf0d Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 20 May 2021 14:53:21 -0700 Subject: [PATCH 0111/2500] [dev.typeparams] cmd/compile/internal/types2: move signature checking into separate file This only moves functionality from one file into another. Except for import adjustments there are no changes to the code. Change-Id: Id0d20a7537f20abe3a257ad3f550b0cb4499598c Reviewed-on: https://go-review.googlesource.com/c/go/+/321590 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/signature.go | 314 +++++++++++++++++++ src/cmd/compile/internal/types2/typexpr.go | 304 ------------------ 2 files changed, 314 insertions(+), 304 deletions(-) create mode 100644 src/cmd/compile/internal/types2/signature.go diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go new file mode 100644 index 0000000000..c8c4cca0a7 --- /dev/null +++ b/src/cmd/compile/internal/types2/signature.go @@ -0,0 +1,314 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types2 + +import ( + "cmd/compile/internal/syntax" + "fmt" +) + +// Disabled by default, but enabled when running tests (via types_test.go). +var acceptMethodTypeParams bool + +// funcType type-checks a function or method type. +func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []*syntax.Field, ftyp *syntax.FuncType) { + check.openScope(ftyp, "function") + check.scope.isFunc = true + check.recordScope(ftyp, check.scope) + sig.scope = check.scope + defer check.closeScope() + + var recvTyp syntax.Expr // rewritten receiver type; valid if != nil + if recvPar != nil { + // collect generic receiver type parameters, if any + // - a receiver type parameter is like any other type parameter, except that it is declared implicitly + // - the receiver specification acts as local declaration for its type parameters, which may be blank + _, rname, rparams := check.unpackRecv(recvPar.Type, true) + if len(rparams) > 0 { + // Blank identifiers don't get declared and regular type-checking of the instantiated + // parameterized receiver type expression fails in Checker.collectParams of receiver. + // Identify blank type parameters and substitute each with a unique new identifier named + // "n_" (where n is the parameter index) and which cannot conflict with any user-defined + // name. + var smap map[*syntax.Name]*syntax.Name // substitution map from "_" to "!n" identifiers + for i, p := range rparams { + if p.Value == "_" { + new := *p + new.Value = fmt.Sprintf("%d_", i) + rparams[i] = &new // use n_ identifier instead of _ so it can be looked up + if smap == nil { + smap = make(map[*syntax.Name]*syntax.Name) + } + smap[p] = &new + } + } + if smap != nil { + // blank identifiers were found => use rewritten receiver type + recvTyp = isubst(recvPar.Type, smap) + } + // TODO(gri) rework declareTypeParams + sig.rparams = nil + for _, rparam := range rparams { + sig.rparams = check.declareTypeParam(sig.rparams, rparam) + } + // determine receiver type to get its type parameters + // and the respective type parameter bounds + var recvTParams []*TypeName + if rname != nil { + // recv should be a Named type (otherwise an error is reported elsewhere) + // Also: Don't report an error via genericType since it will be reported + // again when we type-check the signature. + // TODO(gri) maybe the receiver should be marked as invalid instead? + if recv := asNamed(check.genericType(rname, false)); recv != nil { + recvTParams = recv.tparams + } + } + // provide type parameter bounds + // - only do this if we have the right number (otherwise an error is reported elsewhere) + if len(sig.rparams) == len(recvTParams) { + // We have a list of *TypeNames but we need a list of Types. + list := make([]Type, len(sig.rparams)) + for i, t := range sig.rparams { + list[i] = t.typ + } + smap := makeSubstMap(recvTParams, list) + for i, tname := range sig.rparams { + bound := recvTParams[i].typ.(*TypeParam).bound + // bound is (possibly) parameterized in the context of the + // receiver type declaration. Substitute parameters for the + // current context. + // TODO(gri) should we assume now that bounds always exist? + // (no bound == empty interface) + if bound != nil { + bound = check.subst(tname.pos, bound, smap) + tname.typ.(*TypeParam).bound = bound + } + } + } + } + } + + if tparams != nil { + sig.tparams = check.collectTypeParams(tparams) + // Always type-check method type parameters but complain if they are not enabled. + // (A separate check is needed when type-checking interface method signatures because + // they don't have a receiver specification.) + if recvPar != nil && !acceptMethodTypeParams { + check.error(ftyp, "methods cannot have type parameters") + } + } + + // Value (non-type) parameters' scope starts in the function body. Use a temporary scope for their + // declarations and then squash that scope into the parent scope (and report any redeclarations at + // that time). + scope := NewScope(check.scope, nopos, nopos, "function body (temp. scope)") + var recvList []*Var // TODO(gri) remove the need for making a list here + if recvPar != nil { + recvList, _ = check.collectParams(scope, []*syntax.Field{recvPar}, recvTyp, false) // use rewritten receiver type, if any + } + params, variadic := check.collectParams(scope, ftyp.ParamList, nil, true) + results, _ := check.collectParams(scope, ftyp.ResultList, nil, false) + scope.Squash(func(obj, alt Object) { + var err error_ + err.errorf(obj, "%s redeclared in this block", obj.Name()) + err.recordAltDecl(alt) + check.report(&err) + }) + + if recvPar != nil { + // recv parameter list present (may be empty) + // spec: "The receiver is specified via an extra parameter section preceding the + // method name. That parameter section must declare a single parameter, the receiver." + var recv *Var + switch len(recvList) { + case 0: + // error reported by resolver + recv = NewParam(nopos, nil, "", Typ[Invalid]) // ignore recv below + default: + // more than one receiver + check.error(recvList[len(recvList)-1].Pos(), "method must have exactly one receiver") + fallthrough // continue with first receiver + case 1: + recv = recvList[0] + } + + // TODO(gri) We should delay rtyp expansion to when we actually need the + // receiver; thus all checks here should be delayed to later. + rtyp, _ := deref(recv.typ) + rtyp = expand(rtyp) + + // spec: "The receiver type must be of the form T or *T where T is a type name." + // (ignore invalid types - error was reported before) + if t := rtyp; t != Typ[Invalid] { + var err string + if T := asNamed(t); T != nil { + // spec: "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." + if T.obj.pkg != check.pkg { + err = "type not defined in this package" + if check.conf.CompilerErrorMessages { + check.errorf(recv.pos, "cannot define new methods on non-local type %s", recv.typ) + err = "" + } + } else { + switch u := optype(T).(type) { + case *Basic: + // unsafe.Pointer is treated like a regular pointer + if u.kind == UnsafePointer { + err = "unsafe.Pointer" + } + case *Pointer, *Interface: + err = "pointer or interface type" + } + } + } else if T := asBasic(t); T != nil { + err = "basic or unnamed type" + if check.conf.CompilerErrorMessages { + check.errorf(recv.pos, "cannot define new methods on non-local type %s", recv.typ) + err = "" + } + } else { + check.errorf(recv.pos, "invalid receiver type %s", recv.typ) + } + if err != "" { + check.errorf(recv.pos, "invalid receiver type %s (%s)", recv.typ, err) + // ok to continue + } + } + sig.recv = recv + } + + sig.params = NewTuple(params...) + sig.results = NewTuple(results...) + sig.variadic = variadic +} + +// collectParams declares the parameters of list in scope and returns the corresponding +// variable list. If type0 != nil, it is used instead of the first type in list. +func (check *Checker) collectParams(scope *Scope, list []*syntax.Field, type0 syntax.Expr, variadicOk bool) (params []*Var, variadic bool) { + if list == nil { + return + } + + var named, anonymous bool + + var typ Type + var prev syntax.Expr + for i, field := range list { + ftype := field.Type + // type-check type of grouped fields only once + if ftype != prev { + prev = ftype + if i == 0 && type0 != nil { + ftype = type0 + } + if t, _ := ftype.(*syntax.DotsType); t != nil { + ftype = t.Elem + if variadicOk && i == len(list)-1 { + variadic = true + } else { + check.softErrorf(t, "can only use ... with final parameter in list") + // ignore ... and continue + } + } + typ = check.varType(ftype) + } + // The parser ensures that f.Tag is nil and we don't + // care if a constructed AST contains a non-nil tag. + if field.Name != nil { + // named parameter + name := field.Name.Value + if name == "" { + check.error(field.Name, invalidAST+"anonymous parameter") + // ok to continue + } + par := NewParam(field.Name.Pos(), check.pkg, name, typ) + check.declare(scope, field.Name, par, scope.pos) + params = append(params, par) + named = true + } else { + // anonymous parameter + par := NewParam(field.Pos(), check.pkg, "", typ) + check.recordImplicit(field, par) + params = append(params, par) + anonymous = true + } + } + + if named && anonymous { + check.error(list[0], invalidAST+"list contains both named and anonymous parameters") + // ok to continue + } + + // For a variadic function, change the last parameter's type from T to []T. + // Since we type-checked T rather than ...T, we also need to retro-actively + // record the type for ...T. + if variadic { + last := params[len(params)-1] + last.typ = &Slice{elem: last.typ} + check.recordTypeAndValue(list[len(list)-1].Type, typexpr, last.typ, nil) + } + + return +} + +// isubst returns an x with identifiers substituted per the substitution map smap. +// isubst only handles the case of (valid) method receiver type expressions correctly. +func isubst(x syntax.Expr, smap map[*syntax.Name]*syntax.Name) syntax.Expr { + switch n := x.(type) { + case *syntax.Name: + if alt := smap[n]; alt != nil { + return alt + } + // case *syntax.StarExpr: + // X := isubst(n.X, smap) + // if X != n.X { + // new := *n + // new.X = X + // return &new + // } + case *syntax.Operation: + if n.Op == syntax.Mul && n.Y == nil { + X := isubst(n.X, smap) + if X != n.X { + new := *n + new.X = X + return &new + } + } + case *syntax.IndexExpr: + Index := isubst(n.Index, smap) + if Index != n.Index { + new := *n + new.Index = Index + return &new + } + case *syntax.ListExpr: + var elems []syntax.Expr + for i, elem := range n.ElemList { + new := isubst(elem, smap) + if new != elem { + if elems == nil { + elems = make([]syntax.Expr, len(n.ElemList)) + copy(elems, n.ElemList) + } + elems[i] = new + } + } + if elems != nil { + new := *n + new.ElemList = elems + return &new + } + case *syntax.ParenExpr: + return isubst(n.X, smap) // no need to keep parentheses + default: + // Other receiver type expressions are invalid. + // It's fine to ignore those here as they will + // be checked elsewhere. + } + return x +} diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 2352030b9b..b27b2a00df 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -13,9 +13,6 @@ import ( "strings" ) -// Disabled by default, but enabled when running tests (via types_test.go). -var acceptMethodTypeParams bool - // ident type-checks identifier e and initializes x with the value or type of e. // If an error occurred, x.mode is set to invalid. // For the meaning of def, see Checker.definedType, below. @@ -196,238 +193,6 @@ func (check *Checker) genericType(e syntax.Expr, reportErr bool) Type { return typ } -// isubst returns an x with identifiers substituted per the substitution map smap. -// isubst only handles the case of (valid) method receiver type expressions correctly. -func isubst(x syntax.Expr, smap map[*syntax.Name]*syntax.Name) syntax.Expr { - switch n := x.(type) { - case *syntax.Name: - if alt := smap[n]; alt != nil { - return alt - } - // case *syntax.StarExpr: - // X := isubst(n.X, smap) - // if X != n.X { - // new := *n - // new.X = X - // return &new - // } - case *syntax.Operation: - if n.Op == syntax.Mul && n.Y == nil { - X := isubst(n.X, smap) - if X != n.X { - new := *n - new.X = X - return &new - } - } - case *syntax.IndexExpr: - Index := isubst(n.Index, smap) - if Index != n.Index { - new := *n - new.Index = Index - return &new - } - case *syntax.ListExpr: - var elems []syntax.Expr - for i, elem := range n.ElemList { - new := isubst(elem, smap) - if new != elem { - if elems == nil { - elems = make([]syntax.Expr, len(n.ElemList)) - copy(elems, n.ElemList) - } - elems[i] = new - } - } - if elems != nil { - new := *n - new.ElemList = elems - return &new - } - case *syntax.ParenExpr: - return isubst(n.X, smap) // no need to keep parentheses - default: - // Other receiver type expressions are invalid. - // It's fine to ignore those here as they will - // be checked elsewhere. - } - return x -} - -// funcType type-checks a function or method type. -func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []*syntax.Field, ftyp *syntax.FuncType) { - check.openScope(ftyp, "function") - check.scope.isFunc = true - check.recordScope(ftyp, check.scope) - sig.scope = check.scope - defer check.closeScope() - - var recvTyp syntax.Expr // rewritten receiver type; valid if != nil - if recvPar != nil { - // collect generic receiver type parameters, if any - // - a receiver type parameter is like any other type parameter, except that it is declared implicitly - // - the receiver specification acts as local declaration for its type parameters, which may be blank - _, rname, rparams := check.unpackRecv(recvPar.Type, true) - if len(rparams) > 0 { - // Blank identifiers don't get declared and regular type-checking of the instantiated - // parameterized receiver type expression fails in Checker.collectParams of receiver. - // Identify blank type parameters and substitute each with a unique new identifier named - // "n_" (where n is the parameter index) and which cannot conflict with any user-defined - // name. - var smap map[*syntax.Name]*syntax.Name // substitution map from "_" to "!n" identifiers - for i, p := range rparams { - if p.Value == "_" { - new := *p - new.Value = fmt.Sprintf("%d_", i) - rparams[i] = &new // use n_ identifier instead of _ so it can be looked up - if smap == nil { - smap = make(map[*syntax.Name]*syntax.Name) - } - smap[p] = &new - } - } - if smap != nil { - // blank identifiers were found => use rewritten receiver type - recvTyp = isubst(recvPar.Type, smap) - } - // TODO(gri) rework declareTypeParams - sig.rparams = nil - for _, rparam := range rparams { - sig.rparams = check.declareTypeParam(sig.rparams, rparam) - } - // determine receiver type to get its type parameters - // and the respective type parameter bounds - var recvTParams []*TypeName - if rname != nil { - // recv should be a Named type (otherwise an error is reported elsewhere) - // Also: Don't report an error via genericType since it will be reported - // again when we type-check the signature. - // TODO(gri) maybe the receiver should be marked as invalid instead? - if recv := asNamed(check.genericType(rname, false)); recv != nil { - recvTParams = recv.tparams - } - } - // provide type parameter bounds - // - only do this if we have the right number (otherwise an error is reported elsewhere) - if len(sig.rparams) == len(recvTParams) { - // We have a list of *TypeNames but we need a list of Types. - list := make([]Type, len(sig.rparams)) - for i, t := range sig.rparams { - list[i] = t.typ - } - smap := makeSubstMap(recvTParams, list) - for i, tname := range sig.rparams { - bound := recvTParams[i].typ.(*TypeParam).bound - // bound is (possibly) parameterized in the context of the - // receiver type declaration. Substitute parameters for the - // current context. - // TODO(gri) should we assume now that bounds always exist? - // (no bound == empty interface) - if bound != nil { - bound = check.subst(tname.pos, bound, smap) - tname.typ.(*TypeParam).bound = bound - } - } - } - } - } - - if tparams != nil { - sig.tparams = check.collectTypeParams(tparams) - // Always type-check method type parameters but complain if they are not enabled. - // (A separate check is needed when type-checking interface method signatures because - // they don't have a receiver specification.) - if recvPar != nil && !acceptMethodTypeParams { - check.error(ftyp, "methods cannot have type parameters") - } - } - - // Value (non-type) parameters' scope starts in the function body. Use a temporary scope for their - // declarations and then squash that scope into the parent scope (and report any redeclarations at - // that time). - scope := NewScope(check.scope, nopos, nopos, "function body (temp. scope)") - var recvList []*Var // TODO(gri) remove the need for making a list here - if recvPar != nil { - recvList, _ = check.collectParams(scope, []*syntax.Field{recvPar}, recvTyp, false) // use rewritten receiver type, if any - } - params, variadic := check.collectParams(scope, ftyp.ParamList, nil, true) - results, _ := check.collectParams(scope, ftyp.ResultList, nil, false) - scope.Squash(func(obj, alt Object) { - var err error_ - err.errorf(obj, "%s redeclared in this block", obj.Name()) - err.recordAltDecl(alt) - check.report(&err) - }) - - if recvPar != nil { - // recv parameter list present (may be empty) - // spec: "The receiver is specified via an extra parameter section preceding the - // method name. That parameter section must declare a single parameter, the receiver." - var recv *Var - switch len(recvList) { - case 0: - // error reported by resolver - recv = NewParam(nopos, nil, "", Typ[Invalid]) // ignore recv below - default: - // more than one receiver - check.error(recvList[len(recvList)-1].Pos(), "method must have exactly one receiver") - fallthrough // continue with first receiver - case 1: - recv = recvList[0] - } - - // TODO(gri) We should delay rtyp expansion to when we actually need the - // receiver; thus all checks here should be delayed to later. - rtyp, _ := deref(recv.typ) - rtyp = expand(rtyp) - - // spec: "The receiver type must be of the form T or *T where T is a type name." - // (ignore invalid types - error was reported before) - if t := rtyp; t != Typ[Invalid] { - var err string - if T := asNamed(t); T != nil { - // spec: "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." - if T.obj.pkg != check.pkg { - err = "type not defined in this package" - if check.conf.CompilerErrorMessages { - check.errorf(recv.pos, "cannot define new methods on non-local type %s", recv.typ) - err = "" - } - } else { - switch u := optype(T).(type) { - case *Basic: - // unsafe.Pointer is treated like a regular pointer - if u.kind == UnsafePointer { - err = "unsafe.Pointer" - } - case *Pointer, *Interface: - err = "pointer or interface type" - } - } - } else if T := asBasic(t); T != nil { - err = "basic or unnamed type" - if check.conf.CompilerErrorMessages { - check.errorf(recv.pos, "cannot define new methods on non-local type %s", recv.typ) - err = "" - } - } else { - check.errorf(recv.pos, "invalid receiver type %s", recv.typ) - } - if err != "" { - check.errorf(recv.pos, "invalid receiver type %s (%s)", recv.typ, err) - // ok to continue - } - } - sig.recv = recv - } - - sig.params = NewTuple(params...) - sig.results = NewTuple(results...) - sig.variadic = variadic -} - // goTypeName returns the Go type name for typ and // removes any occurrences of "types2." from that name. func goTypeName(typ Type) string { @@ -730,72 +495,3 @@ func (check *Checker) typeList(list []syntax.Expr) []Type { } return res } - -// collectParams declares the parameters of list in scope and returns the corresponding -// variable list. If type0 != nil, it is used instead of the first type in list. -func (check *Checker) collectParams(scope *Scope, list []*syntax.Field, type0 syntax.Expr, variadicOk bool) (params []*Var, variadic bool) { - if list == nil { - return - } - - var named, anonymous bool - - var typ Type - var prev syntax.Expr - for i, field := range list { - ftype := field.Type - // type-check type of grouped fields only once - if ftype != prev { - prev = ftype - if i == 0 && type0 != nil { - ftype = type0 - } - if t, _ := ftype.(*syntax.DotsType); t != nil { - ftype = t.Elem - if variadicOk && i == len(list)-1 { - variadic = true - } else { - check.softErrorf(t, "can only use ... with final parameter in list") - // ignore ... and continue - } - } - typ = check.varType(ftype) - } - // The parser ensures that f.Tag is nil and we don't - // care if a constructed AST contains a non-nil tag. - if field.Name != nil { - // named parameter - name := field.Name.Value - if name == "" { - check.error(field.Name, invalidAST+"anonymous parameter") - // ok to continue - } - par := NewParam(field.Name.Pos(), check.pkg, name, typ) - check.declare(scope, field.Name, par, scope.pos) - params = append(params, par) - named = true - } else { - // anonymous parameter - par := NewParam(field.Pos(), check.pkg, "", typ) - check.recordImplicit(field, par) - params = append(params, par) - anonymous = true - } - } - - if named && anonymous { - check.error(list[0], invalidAST+"list contains both named and anonymous parameters") - // ok to continue - } - - // For a variadic function, change the last parameter's type from T to []T. - // Since we type-checked T rather than ...T, we also need to retro-actively - // record the type for ...T. - if variadic { - last := params[len(params)-1] - last.typ = &Slice{elem: last.typ} - check.recordTypeAndValue(list[len(list)-1].Type, typexpr, last.typ, nil) - } - - return -} -- GitLab From ccbfbb1c3327fffe88dd6b6da550f4a0cd37db6e Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sun, 9 May 2021 11:38:34 -0700 Subject: [PATCH 0112/2500] [dev.typeparams] cmd/compile: export OFUNCINST and OSELRECV2 nodes (for generic functions) Added new test typeparam/factimp.go and changed a bunch of other tests to test exporting more generic functions and types. Change-Id: I573d75431cc92482f8f908695cfbc8e84dbb36d2 Reviewed-on: https://go-review.googlesource.com/c/go/+/321749 Trust: Dan Scales Reviewed-by: Keith Randall --- src/cmd/compile/internal/typecheck/iexport.go | 20 ++++++++ src/cmd/compile/internal/typecheck/iimport.go | 20 ++++++++ test/typeparam/combine.go | 28 +++++------ test/typeparam/cons.go | 46 +++++++++---------- test/typeparam/factimp.dir/a.go | 12 +++++ test/typeparam/factimp.dir/main.go | 26 +++++++++++ test/typeparam/factimp.go | 7 +++ test/typeparam/index.go | 8 ++-- test/typeparam/listimp.dir/a.go | 4 ++ test/typeparam/listimp.dir/main.go | 4 ++ test/typeparam/lockable.go | 16 +++---- 11 files changed, 142 insertions(+), 49 deletions(-) create mode 100644 test/typeparam/factimp.dir/a.go create mode 100644 test/typeparam/factimp.dir/main.go create mode 100644 test/typeparam/factimp.go diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index e6813adbf9..d125dadd88 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -1920,6 +1920,26 @@ func (w *exportWriter) expr(n ir.Node) { // if exporting, DCLCONST should just be removed as its usage // has already been replaced with literals + case ir.OFUNCINST: + n := n.(*ir.InstExpr) + w.op(ir.OFUNCINST) + w.pos(n.Pos()) + w.expr(n.X) + w.uint64(uint64(len(n.Targs))) + for _, targ := range n.Targs { + w.typ(targ.Type()) + } + if go117ExportTypes { + w.typ(n.Type()) + } + + case ir.OSELRECV2: + n := n.(*ir.AssignListStmt) + w.op(ir.OSELRECV2) + w.pos(n.Pos()) + w.exprList(n.Lhs) + w.exprList(n.Rhs) + default: base.Fatalf("cannot export %v (%d) node\n"+ "\t==> please file an issue and assign to gri@", n.Op(), int(n.Op())) diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 778ce4be12..3b725a226c 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1582,6 +1582,26 @@ func (r *importReader) node() ir.Node { case ir.OEND: return nil + case ir.OFUNCINST: + pos := r.pos() + x := r.expr() + ntargs := r.uint64() + var targs []ir.Node + if ntargs > 0 { + targs = make([]ir.Node, ntargs) + for i := range targs { + targs[i] = ir.TypeNode(r.typ()) + } + } + n := ir.NewInstExpr(pos, ir.OFUNCINST, x, targs) + if go117ExportTypes { + n.SetType(r.typ()) + } + return n + + case ir.OSELRECV2: + return ir.NewAssignListStmt(r.pos(), ir.OSELRECV2, r.exprList(), r.exprList()) + default: base.Fatalf("cannot import %v (%d) node\n"+ "\t==> please file an issue and assign to gri@", op, int(op)) diff --git a/test/typeparam/combine.go b/test/typeparam/combine.go index d4a2988a7b..0e120cf242 100644 --- a/test/typeparam/combine.go +++ b/test/typeparam/combine.go @@ -10,9 +10,9 @@ import ( "fmt" ) -type _Gen[A any] func() (A, bool) +type Gen[A any] func() (A, bool) -func combine[T1, T2, T any](g1 _Gen[T1], g2 _Gen[T2], join func(T1, T2) T) _Gen[T] { +func Combine[T1, T2, T any](g1 Gen[T1], g2 Gen[T2], join func(T1, T2) T) Gen[T] { return func() (T, bool) { var t T t1, ok := g1() @@ -27,38 +27,38 @@ func combine[T1, T2, T any](g1 _Gen[T1], g2 _Gen[T2], join func(T1, T2) T) _Gen[ } } -type _Pair[A, B any] struct { +type Pair[A, B any] struct { A A B B } -func _NewPair[A, B any](a A, b B) _Pair[A, B] { - return _Pair[A, B]{a, b} +func _NewPair[A, B any](a A, b B) Pair[A, B] { + return Pair[A, B]{a, b} } -func _Combine2[A, B any](ga _Gen[A], gb _Gen[B]) _Gen[_Pair[A, B]] { - return combine(ga, gb, _NewPair[A, B]) +func Combine2[A, B any](ga Gen[A], gb Gen[B]) Gen[Pair[A, B]] { + return Combine(ga, gb, _NewPair[A, B]) } func main() { - var g1 _Gen[int] = func() (int, bool) { return 3, true } - var g2 _Gen[string] = func() (string, bool) { return "x", false } - var g3 _Gen[string] = func() (string, bool) { return "y", true } + var g1 Gen[int] = func() (int, bool) { return 3, true } + var g2 Gen[string] = func() (string, bool) { return "x", false } + var g3 Gen[string] = func() (string, bool) { return "y", true } - gc := combine(g1, g2, _NewPair[int, string]) + gc := Combine(g1, g2, _NewPair[int, string]) if got, ok := gc(); ok { panic(fmt.Sprintf("got %v, %v, wanted -/false", got, ok)) } - gc2 := _Combine2(g1, g2) + gc2 := Combine2(g1, g2) if got, ok := gc2(); ok { panic(fmt.Sprintf("got %v, %v, wanted -/false", got, ok)) } - gc3 := combine(g1, g3, _NewPair[int, string]) + gc3 := Combine(g1, g3, _NewPair[int, string]) if got, ok := gc3(); !ok || got.A != 3 || got.B != "y" { panic(fmt.Sprintf("got %v, %v, wanted {3, y}, true", got, ok)) } - gc4 := _Combine2(g1, g3) + gc4 := Combine2(g1, g3) if got, ok := gc4(); !ok || got.A != 3 || got.B != "y" { panic (fmt.Sprintf("got %v, %v, wanted {3, y}, true", got, ok)) } diff --git a/test/typeparam/cons.go b/test/typeparam/cons.go index 8d255ebdb8..f20514fb66 100644 --- a/test/typeparam/cons.go +++ b/test/typeparam/cons.go @@ -12,7 +12,7 @@ import "fmt" // argument type any interface{} -type _Function[a, b any] interface { +type Function[a, b any] interface { Apply(x a) b } @@ -29,8 +29,8 @@ func (this pos) Apply(x int) bool { } type compose[a, b, c any] struct { - f _Function[a, b] - g _Function[b, c] + f Function[a, b] + g Function[b, c] } func (this compose[a, b, c]) Apply(x a) c { @@ -47,52 +47,52 @@ func (this Int) Equal(that int) bool { return int(this) == that } -type _List[a any] interface { - Match(casenil _Function[_Nil[a], any], casecons _Function[_Cons[a], any]) any +type List[a any] interface { + Match(casenil Function[Nil[a], any], casecons Function[Cons[a], any]) any } -type _Nil[a any] struct{ +type Nil[a any] struct{ } -func (xs _Nil[a]) Match(casenil _Function[_Nil[a], any], casecons _Function[_Cons[a], any]) any { +func (xs Nil[a]) Match(casenil Function[Nil[a], any], casecons Function[Cons[a], any]) any { return casenil.Apply(xs) } -type _Cons[a any] struct { +type Cons[a any] struct { Head a - Tail _List[a] + Tail List[a] } -func (xs _Cons[a]) Match(casenil _Function[_Nil[a], any], casecons _Function[_Cons[a], any]) any { +func (xs Cons[a]) Match(casenil Function[Nil[a], any], casecons Function[Cons[a], any]) any { return casecons.Apply(xs) } type mapNil[a, b any] struct{ } -func (m mapNil[a, b]) Apply(_ _Nil[a]) any { - return _Nil[b]{} +func (m mapNil[a, b]) Apply(_ Nil[a]) any { + return Nil[b]{} } type mapCons[a, b any] struct { - f _Function[a, b] + f Function[a, b] } -func (m mapCons[a, b]) Apply(xs _Cons[a]) any { - return _Cons[b]{m.f.Apply(xs.Head), _Map[a, b](m.f, xs.Tail)} +func (m mapCons[a, b]) Apply(xs Cons[a]) any { + return Cons[b]{m.f.Apply(xs.Head), Map[a, b](m.f, xs.Tail)} } -func _Map[a, b any](f _Function[a, b], xs _List[a]) _List[b] { - return xs.Match(mapNil[a, b]{}, mapCons[a, b]{f}).(_List[b]) +func Map[a, b any](f Function[a, b], xs List[a]) List[b] { + return xs.Match(mapNil[a, b]{}, mapCons[a, b]{f}).(List[b]) } func main() { - var xs _List[int] = _Cons[int]{3, _Cons[int]{6, _Nil[int]{}}} - var ys _List[int] = _Map[int, int](incr{-5}, xs) - var xz _List[bool] = _Map[int, bool](pos{}, ys) - cs1 := xz.(_Cons[bool]) - cs2 := cs1.Tail.(_Cons[bool]) - _, ok := cs2.Tail.(_Nil[bool]) + var xs List[int] = Cons[int]{3, Cons[int]{6, Nil[int]{}}} + var ys List[int] = Map[int, int](incr{-5}, xs) + var xz List[bool] = Map[int, bool](pos{}, ys) + cs1 := xz.(Cons[bool]) + cs2 := cs1.Tail.(Cons[bool]) + _, ok := cs2.Tail.(Nil[bool]) if cs1.Head != false || cs2.Head != true || !ok { panic(fmt.Sprintf("got %v, %v, %v, expected false, true, true", cs1.Head, cs2.Head, ok)) diff --git a/test/typeparam/factimp.dir/a.go b/test/typeparam/factimp.dir/a.go new file mode 100644 index 0000000000..e11575e66e --- /dev/null +++ b/test/typeparam/factimp.dir/a.go @@ -0,0 +1,12 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +func Fact[T interface { type int, int64, float64 }](n T) T { + if n == T(1) { + return T(1) + } + return n * Fact(n - T(1)) +} diff --git a/test/typeparam/factimp.dir/main.go b/test/typeparam/factimp.dir/main.go new file mode 100644 index 0000000000..c2238002ae --- /dev/null +++ b/test/typeparam/factimp.dir/main.go @@ -0,0 +1,26 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "a" + "fmt" +) + +func main() { + const want = 120 + + if got := a.Fact(5); got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } + + if got := a.Fact[int64](5); got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } + + if got := a.Fact(5.0); got != want { + panic(fmt.Sprintf("got %f, want %f", got, want)) + } +} diff --git a/test/typeparam/factimp.go b/test/typeparam/factimp.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/factimp.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored diff --git a/test/typeparam/index.go b/test/typeparam/index.go index 83e65acdd0..cb9b2613c3 100644 --- a/test/typeparam/index.go +++ b/test/typeparam/index.go @@ -11,7 +11,7 @@ import ( ) // Index returns the index of x in s, or -1 if not found. -func index[T comparable](s []T, x T) int { +func Index[T comparable](s []T, x T) int { for i, v := range s { // v and x are type T, which has the comparable // constraint, so we can use == here. @@ -30,17 +30,17 @@ func main() { want := 2 vec1 := []string{"ab", "cd", "ef"} - if got := index(vec1, "ef"); got != want { + if got := Index(vec1, "ef"); got != want { panic(fmt.Sprintf("got %d, want %d", got, want)) } vec2 := []byte{'c', '6', '@'} - if got := index(vec2, '@'); got != want { + if got := Index(vec2, '@'); got != want { panic(fmt.Sprintf("got %d, want %d", got, want)) } vec3 := []*obj{&obj{2}, &obj{42}, &obj{1}} - if got := index(vec3, vec3[2]); got != want { + if got := Index(vec3, vec3[2]); got != want { panic(fmt.Sprintf("got %d, want %d", got, want)) } } diff --git a/test/typeparam/listimp.dir/a.go b/test/typeparam/listimp.dir/a.go index ea569751a6..a4118a0e81 100644 --- a/test/typeparam/listimp.dir/a.go +++ b/test/typeparam/listimp.dir/a.go @@ -1,3 +1,7 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package a type Ordered interface { diff --git a/test/typeparam/listimp.dir/main.go b/test/typeparam/listimp.dir/main.go index 4c1aa3e493..d43ad508be 100644 --- a/test/typeparam/listimp.dir/main.go +++ b/test/typeparam/listimp.dir/main.go @@ -1,3 +1,7 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package main import ( diff --git a/test/typeparam/lockable.go b/test/typeparam/lockable.go index d53817521f..3a03652cd8 100644 --- a/test/typeparam/lockable.go +++ b/test/typeparam/lockable.go @@ -8,29 +8,29 @@ package main import "sync" -// A _Lockable is a value that may be safely simultaneously accessed +// A Lockable is a value that may be safely simultaneously accessed // from multiple goroutines via the Get and Set methods. -type _Lockable[T any] struct { +type Lockable[T any] struct { T mu sync.Mutex } -// Get returns the value stored in a _Lockable. -func (l *_Lockable[T]) get() T { +// Get returns the value stored in a Lockable. +func (l *Lockable[T]) get() T { l.mu.Lock() defer l.mu.Unlock() return l.T } -// set sets the value in a _Lockable. -func (l *_Lockable[T]) set(v T) { +// set sets the value in a Lockable. +func (l *Lockable[T]) set(v T) { l.mu.Lock() defer l.mu.Unlock() l.T = v } func main() { - sl := _Lockable[string]{T: "a"} + sl := Lockable[string]{T: "a"} if got := sl.get(); got != "a" { panic(got) } @@ -39,7 +39,7 @@ func main() { panic(got) } - il := _Lockable[int]{T: 1} + il := Lockable[int]{T: 1} if got := il.get(); got != 1 { panic(got) } -- GitLab From b1a398cf0f04ac911be204d3c0ee001a94621683 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 10 May 2021 10:17:51 -0700 Subject: [PATCH 0113/2500] [dev.typeparams] cmd/compile: add import/export of calls to builtin functions For generic functions, we have to leave the builtins in OCALL form, rather than transform to specific ops, since we don't know the exact types involved. Allow export/import of builtins in OCALL form. Added new export/import test mapimp.go. Change-Id: I571f8eeaa13b4f69389dbdb9afb6cc61924b9bf2 Reviewed-on: https://go-review.googlesource.com/c/go/+/321750 Trust: Dan Scales Reviewed-by: Keith Randall --- src/cmd/compile/internal/typecheck/iexport.go | 10 +++++++ src/cmd/compile/internal/typecheck/iimport.go | 4 +++ test/typeparam/mapimp.dir/a.go | 15 ++++++++++ test/typeparam/mapimp.dir/main.go | 28 +++++++++++++++++++ test/typeparam/mapimp.go | 7 +++++ 5 files changed, 64 insertions(+) create mode 100644 test/typeparam/mapimp.dir/a.go create mode 100644 test/typeparam/mapimp.dir/main.go create mode 100644 test/typeparam/mapimp.go diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index d125dadd88..802a8c3839 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -1579,6 +1579,16 @@ func (w *exportWriter) expr(n ir.Node) { // We don't need a type here, as the type will be provided at the // declaration of n. w.op(ir.ONAME) + + // This handles the case where we haven't yet transformed a call + // to a builtin, so we must write out the builtin as a name in the + // builtin package. + isBuiltin := n.BuiltinOp != ir.OXXX + w.bool(isBuiltin) + if isBuiltin { + w.string(n.Sym().Name) + break + } w.localName(n) // case OPACK, ONONAME: diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 3b725a226c..39b5ab09da 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1184,6 +1184,10 @@ func (r *importReader) node() ir.Node { return n case ir.ONAME: + isBuiltin := r.bool() + if isBuiltin { + return types.BuiltinPkg.Lookup(r.string()).Def.(*ir.Name) + } return r.localName() // case OPACK, ONONAME: diff --git a/test/typeparam/mapimp.dir/a.go b/test/typeparam/mapimp.dir/a.go new file mode 100644 index 0000000000..6835e214b8 --- /dev/null +++ b/test/typeparam/mapimp.dir/a.go @@ -0,0 +1,15 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +// Map calls the function f on every element of the slice s, +// returning a new slice of the results. +func Mapper[F, T any](s []F, f func(F) T) []T { + r := make([]T, len(s)) + for i, v := range s { + r[i] = f(v) + } + return r +} diff --git a/test/typeparam/mapimp.dir/main.go b/test/typeparam/mapimp.dir/main.go new file mode 100644 index 0000000000..4d4a4d9eb0 --- /dev/null +++ b/test/typeparam/mapimp.dir/main.go @@ -0,0 +1,28 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "a" + "fmt" + "reflect" + "strconv" +) + +func main() { + got := a.Mapper([]int{1, 2, 3}, strconv.Itoa) + want := []string{"1", "2", "3"} + if !reflect.DeepEqual(got, want) { + panic(fmt.Sprintf("got %s, want %s", got, want)) + } + + fgot := a.Mapper([]float64{2.5, 2.3, 3.5}, func(f float64) string { + return strconv.FormatFloat(f, 'f', -1, 64) + }) + fwant := []string{"2.5", "2.3", "3.5"} + if !reflect.DeepEqual(fgot, fwant) { + panic(fmt.Sprintf("got %s, want %s", fgot, fwant)) + } +} diff --git a/test/typeparam/mapimp.go b/test/typeparam/mapimp.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/mapimp.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From 21db1d193cc3d830e1a7d53a04271631ce1198cd Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 21 May 2021 17:00:08 -0400 Subject: [PATCH 0114/2500] [dev.typeparams] runtime: fix newproc arg size on ARM At runtime startup it calls newproc from assembly code to start the main goroutine. runtime.main has no arguments, so the arg size should be 0, instead of 8. While here, use clearer code sequence to open the frame. Change-Id: I2bbb26a83521ea867897530b86a85b22a3c8be9d Reviewed-on: https://go-review.googlesource.com/c/go/+/321957 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: Michael Knyszek TryBot-Result: Go Bot --- src/runtime/asm_arm.s | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/runtime/asm_arm.s b/src/runtime/asm_arm.s index 6d3573d68f..872e56aeb4 100644 --- a/src/runtime/asm_arm.s +++ b/src/runtime/asm_arm.s @@ -168,14 +168,14 @@ TEXT runtime·rt0_go(SB),NOSPLIT|NOFRAME|TOPFRAME,$0 BL runtime·schedinit(SB) // create a new goroutine to start program + SUB $12, R13 MOVW $runtime·mainPC(SB), R0 - MOVW.W R0, -4(R13) - MOVW $8, R0 - MOVW.W R0, -4(R13) + MOVW R0, 8(R13) // arg 2: fn MOVW $0, R0 - MOVW.W R0, -4(R13) // push $0 as guard + MOVW R0, 4(R13) // arg 1: siz + MOVW R0, 0(R13) // dummy LR BL runtime·newproc(SB) - MOVW $12(R13), R13 // pop args and LR + ADD $12, R13 // pop args and LR // start this M BL runtime·mstart(SB) -- GitLab From fb42fb705df4832a76165f9a36f3a8d5d7ca8f49 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 20 May 2021 18:55:47 -0400 Subject: [PATCH 0115/2500] [dev.typeparams] runtime: use internal/abi.FuncPCABI0 to take address of assembly functions There are a few assembly functions in the runtime that are marked as ABIInternal, solely because funcPC can get the right address. The functions themselves do not actually follow ABIInternal (or irrelevant). Now we have internal/abi.FuncPCABI0, use that, and un-mark the functions. Also un-mark assembly functions that are only called in assembly. For them, it only matters if the caller and callee are consistent. Change-Id: I240e126ac13cb362f61ff8482057ee9f53c24097 Reviewed-on: https://go-review.googlesource.com/c/go/+/321950 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/reflect/asm_amd64.s | 4 ++-- src/runtime/asm.s | 2 +- src/runtime/asm_amd64.s | 14 +++++++------- src/runtime/mkpreempt.go | 3 +-- src/runtime/os3_plan9.go | 3 ++- src/runtime/os_linux.go | 9 +++++---- src/runtime/os_windows.go | 7 ++++--- src/runtime/preempt.go | 3 ++- src/runtime/preempt_386.s | 3 +-- src/runtime/preempt_amd64.s | 3 +-- src/runtime/preempt_arm.s | 3 +-- src/runtime/preempt_arm64.s | 3 +-- src/runtime/preempt_mips64x.s | 3 +-- src/runtime/preempt_mipsx.s | 3 +-- src/runtime/preempt_ppc64x.s | 3 +-- src/runtime/preempt_riscv64.s | 3 +-- src/runtime/preempt_s390x.s | 3 +-- src/runtime/preempt_wasm.s | 3 +-- src/runtime/race.go | 3 ++- src/runtime/race_amd64.s | 4 +--- src/runtime/signal_amd64.go | 5 +++-- src/runtime/signal_unix.go | 3 ++- src/runtime/signal_windows.go | 13 +++++++------ src/runtime/sys_linux_amd64.s | 13 +++++-------- src/runtime/sys_windows_386.s | 14 +++++++------- src/runtime/sys_windows_amd64.s | 12 ++++++------ src/runtime/sys_windows_arm.s | 12 ++++++------ src/runtime/sys_windows_arm64.s | 10 +++++----- src/runtime/syscall_windows.go | 2 +- src/runtime/wincallback.go | 6 +++--- src/runtime/zcallback_windows.s | 2 +- src/runtime/zcallback_windows_arm.s | 2 +- src/runtime/zcallback_windows_arm64.s | 2 +- 33 files changed, 85 insertions(+), 93 deletions(-) diff --git a/src/reflect/asm_amd64.s b/src/reflect/asm_amd64.s index facf07516d..86d3f4e4bf 100644 --- a/src/reflect/asm_amd64.s +++ b/src/reflect/asm_amd64.s @@ -32,7 +32,7 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$312 // NO_LOCAL_POINTERS is a lie. The stack map for the two locals in this // frame is specially handled in the runtime. See the comment above LOCAL_RETVALID. LEAQ LOCAL_REGARGS(SP), R12 - CALL runtime·spillArgs(SB) + CALL runtime·spillArgs(SB) MOVQ DX, 24(SP) // outside of moveMakeFuncArgPtrs's arg area MOVQ DX, 0(SP) MOVQ R12, 8(SP) @@ -48,7 +48,7 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$312 MOVQ AX, 24(SP) CALL ·callReflect(SB) LEAQ LOCAL_REGARGS(SP), R12 - CALL runtime·unspillArgs(SB) + CALL runtime·unspillArgs(SB) RET // methodValueCall is the code half of the function returned by makeMethodValue. diff --git a/src/runtime/asm.s b/src/runtime/asm.s index 72c744925d..0e14fcd3e6 100644 --- a/src/runtime/asm.s +++ b/src/runtime/asm.s @@ -13,6 +13,6 @@ DATA runtime·no_pointers_stackmap+0x04(SB)/4, $0 GLOBL runtime·no_pointers_stackmap(SB),RODATA, $8 #ifndef GOARCH_amd64 -TEXT ·sigpanic0(SB),NOSPLIT,$0-0 +TEXT ·sigpanic0(SB),NOSPLIT,$0-0 JMP ·sigpanic(SB) #endif diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index 5990ce54c8..96f0d3fefc 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -469,7 +469,7 @@ TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0 #ifdef GOEXPERIMENT_regabireflect // spillArgs stores return values from registers to a *internal/abi.RegArgs in R12. -TEXT ·spillArgs(SB),NOSPLIT,$0-0 +TEXT ·spillArgs(SB),NOSPLIT,$0-0 MOVQ AX, 0(R12) MOVQ BX, 8(R12) MOVQ CX, 16(R12) @@ -497,7 +497,7 @@ TEXT ·spillArgs(SB),NOSPLIT,$0-0 RET // unspillArgs loads args into registers from a *internal/abi.RegArgs in R12. -TEXT ·unspillArgs(SB),NOSPLIT,$0-0 +TEXT ·unspillArgs(SB),NOSPLIT,$0-0 MOVQ 0(R12), AX MOVQ 8(R12), BX MOVQ 16(R12), CX @@ -525,11 +525,11 @@ TEXT ·unspillArgs(SB),NOSPLIT,$0-0 RET #else // spillArgs stores return values from registers to a pointer in R12. -TEXT ·spillArgs(SB),NOSPLIT,$0-0 +TEXT ·spillArgs(SB),NOSPLIT,$0-0 RET // unspillArgs loads args into registers from a pointer in R12. -TEXT ·unspillArgs(SB),NOSPLIT,$0-0 +TEXT ·unspillArgs(SB),NOSPLIT,$0-0 RET #endif @@ -588,7 +588,7 @@ TEXT NAME(SB), WRAPPER, $MAXSIZE-48; \ REP;MOVSB; \ /* set up argument registers */ \ MOVQ regArgs+40(FP), R12; \ - CALL ·unspillArgs(SB); \ + CALL ·unspillArgs(SB); \ /* call function */ \ MOVQ f+8(FP), DX; \ PCDATA $PCDATA_StackMapIndex, $0; \ @@ -596,7 +596,7 @@ TEXT NAME(SB), WRAPPER, $MAXSIZE-48; \ CALL R12; \ /* copy register return values back */ \ MOVQ regArgs+40(FP), R12; \ - CALL ·spillArgs(SB); \ + CALL ·spillArgs(SB); \ MOVLQZX stackArgsSize+24(FP), CX; \ MOVLQZX stackRetOffset+28(FP), BX; \ MOVQ stackArgs+16(FP), DI; \ @@ -1596,7 +1596,7 @@ TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0 // This function is injected from the signal handler for panicking // signals. It is quite painful to set X15 in the signal context, // so we do it here. -TEXT ·sigpanic0(SB),NOSPLIT,$0-0 +TEXT ·sigpanic0(SB),NOSPLIT,$0-0 #ifdef GOEXPERIMENT_regabig get_tls(R14) MOVQ g(R14), R14 diff --git a/src/runtime/mkpreempt.go b/src/runtime/mkpreempt.go index 6c980540f5..f2b90307ca 100644 --- a/src/runtime/mkpreempt.go +++ b/src/runtime/mkpreempt.go @@ -128,8 +128,7 @@ func header(arch string) { } fmt.Fprintf(out, "#include \"go_asm.h\"\n") fmt.Fprintf(out, "#include \"textflag.h\"\n\n") - fmt.Fprintf(out, "// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.\n") - fmt.Fprintf(out, "TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0\n") + fmt.Fprintf(out, "TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0\n") } func p(f string, args ...interface{}) { diff --git a/src/runtime/os3_plan9.go b/src/runtime/os3_plan9.go index c5dc23de8b..dacb5c23a0 100644 --- a/src/runtime/os3_plan9.go +++ b/src/runtime/os3_plan9.go @@ -5,6 +5,7 @@ package runtime import ( + "internal/abi" "runtime/internal/sys" "unsafe" ) @@ -100,7 +101,7 @@ func sighandler(_ureg *ureg, note *byte, gp *g) int { if usesLR { c.setpc(funcPC(sigpanictramp)) } else { - c.setpc(funcPC(sigpanic0)) + c.setpc(abi.FuncPCABI0(sigpanic0)) } return _NCONT } diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go index c8b29e396c..235c96e45a 100644 --- a/src/runtime/os_linux.go +++ b/src/runtime/os_linux.go @@ -5,6 +5,7 @@ package runtime import ( + "internal/abi" "runtime/internal/sys" "unsafe" ) @@ -149,7 +150,7 @@ func newosproc(mp *m) { // with signals disabled. It will enable them in minit. var oset sigset sigprocmask(_SIG_SETMASK, &sigset_all, &oset) - ret := clone(cloneFlags, stk, unsafe.Pointer(mp), unsafe.Pointer(mp.g0), unsafe.Pointer(funcPC(mstart))) + ret := clone(cloneFlags, stk, unsafe.Pointer(mp), unsafe.Pointer(mp.g0), unsafe.Pointer(abi.FuncPCABI0(mstart))) sigprocmask(_SIG_SETMASK, &oset, nil) if ret < 0 { @@ -429,13 +430,13 @@ func setsig(i uint32, fn uintptr) { // should not be used". x86_64 kernel requires it. Only use it on // x86. if GOARCH == "386" || GOARCH == "amd64" { - sa.sa_restorer = funcPC(sigreturn) + sa.sa_restorer = abi.FuncPCABI0(sigreturn) } if fn == funcPC(sighandler) { if iscgo { - fn = funcPC(cgoSigtramp) + fn = abi.FuncPCABI0(cgoSigtramp) } else { - fn = funcPC(sigtramp) + fn = abi.FuncPCABI0(sigtramp) } } sa.sa_handler = fn diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go index f0935264ac..d82173e738 100644 --- a/src/runtime/os_windows.go +++ b/src/runtime/os_windows.go @@ -5,6 +5,7 @@ package runtime import ( + "internal/abi" "runtime/internal/atomic" "runtime/internal/sys" "unsafe" @@ -543,7 +544,7 @@ func initLongPathSupport() { } func osinit() { - asmstdcallAddr = unsafe.Pointer(funcPC(asmstdcall)) + asmstdcallAddr = unsafe.Pointer(abi.FuncPCABI0(asmstdcall)) setBadSignalMsg() @@ -906,7 +907,7 @@ func semacreate(mp *m) { func newosproc(mp *m) { // We pass 0 for the stack size to use the default for this binary. thandle := stdcall6(_CreateThread, 0, 0, - funcPC(tstart_stdcall), uintptr(unsafe.Pointer(mp)), + abi.FuncPCABI0(tstart_stdcall), uintptr(unsafe.Pointer(mp)), 0, 0) if thandle == 0 { @@ -1385,7 +1386,7 @@ func preemptM(mp *m) { if gp != nil && wantAsyncPreempt(gp) { if ok, newpc := isAsyncSafePoint(gp, c.ip(), c.sp(), c.lr()); ok { // Inject call to asyncPreempt - targetPC := funcPC(asyncPreempt) + targetPC := abi.FuncPCABI0(asyncPreempt) switch GOARCH { default: throw("unsupported architecture") diff --git a/src/runtime/preempt.go b/src/runtime/preempt.go index 1d5aae1363..d1291c9c48 100644 --- a/src/runtime/preempt.go +++ b/src/runtime/preempt.go @@ -53,6 +53,7 @@ package runtime import ( + "internal/abi" "runtime/internal/atomic" "runtime/internal/sys" "unsafe" @@ -315,7 +316,7 @@ func asyncPreempt2() { var asyncPreemptStack = ^uintptr(0) func init() { - f := findfunc(funcPC(asyncPreempt)) + f := findfunc(abi.FuncPCABI0(asyncPreempt)) total := funcMaxSPDelta(f) f = findfunc(funcPC(asyncPreempt2)) total += funcMaxSPDelta(f) diff --git a/src/runtime/preempt_386.s b/src/runtime/preempt_386.s index a803b24dc6..c3a5fa1f36 100644 --- a/src/runtime/preempt_386.s +++ b/src/runtime/preempt_386.s @@ -3,8 +3,7 @@ #include "go_asm.h" #include "textflag.h" -// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally. -TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 +TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 PUSHFL ADJSP $156 NOP SP diff --git a/src/runtime/preempt_amd64.s b/src/runtime/preempt_amd64.s index dc7af806d3..31f7c8b66f 100644 --- a/src/runtime/preempt_amd64.s +++ b/src/runtime/preempt_amd64.s @@ -3,8 +3,7 @@ #include "go_asm.h" #include "textflag.h" -// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally. -TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 +TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 PUSHQ BP MOVQ SP, BP // Save flags before clobbering them diff --git a/src/runtime/preempt_arm.s b/src/runtime/preempt_arm.s index bbc9fbb1ea..8f243c0dcd 100644 --- a/src/runtime/preempt_arm.s +++ b/src/runtime/preempt_arm.s @@ -3,8 +3,7 @@ #include "go_asm.h" #include "textflag.h" -// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally. -TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 +TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 MOVW.W R14, -188(R13) MOVW R0, 4(R13) MOVW R1, 8(R13) diff --git a/src/runtime/preempt_arm64.s b/src/runtime/preempt_arm64.s index 2b70a28479..36ee13282c 100644 --- a/src/runtime/preempt_arm64.s +++ b/src/runtime/preempt_arm64.s @@ -3,8 +3,7 @@ #include "go_asm.h" #include "textflag.h" -// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally. -TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 +TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 MOVD R30, -496(RSP) SUB $496, RSP #ifdef GOOS_linux diff --git a/src/runtime/preempt_mips64x.s b/src/runtime/preempt_mips64x.s index b755425bc5..c1249e382e 100644 --- a/src/runtime/preempt_mips64x.s +++ b/src/runtime/preempt_mips64x.s @@ -6,8 +6,7 @@ #include "go_asm.h" #include "textflag.h" -// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally. -TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 +TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 MOVV R31, -488(R29) SUBV $488, R29 MOVV R1, 8(R29) diff --git a/src/runtime/preempt_mipsx.s b/src/runtime/preempt_mipsx.s index c1bff60859..70b79e05b9 100644 --- a/src/runtime/preempt_mipsx.s +++ b/src/runtime/preempt_mipsx.s @@ -6,8 +6,7 @@ #include "go_asm.h" #include "textflag.h" -// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally. -TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 +TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 MOVW R31, -244(R29) SUB $244, R29 MOVW R1, 4(R29) diff --git a/src/runtime/preempt_ppc64x.s b/src/runtime/preempt_ppc64x.s index 70bd91982b..7ed4021dde 100644 --- a/src/runtime/preempt_ppc64x.s +++ b/src/runtime/preempt_ppc64x.s @@ -6,8 +6,7 @@ #include "go_asm.h" #include "textflag.h" -// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally. -TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 +TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 MOVD R31, -488(R1) MOVD LR, R31 MOVDU R31, -520(R1) diff --git a/src/runtime/preempt_riscv64.s b/src/runtime/preempt_riscv64.s index d4f9cc277f..eb68dcba2b 100644 --- a/src/runtime/preempt_riscv64.s +++ b/src/runtime/preempt_riscv64.s @@ -3,8 +3,7 @@ #include "go_asm.h" #include "textflag.h" -// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally. -TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 +TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 MOV X1, -472(X2) ADD $-472, X2 MOV X3, 8(X2) diff --git a/src/runtime/preempt_s390x.s b/src/runtime/preempt_s390x.s index c6f11571df..ca9e47cde1 100644 --- a/src/runtime/preempt_s390x.s +++ b/src/runtime/preempt_s390x.s @@ -3,8 +3,7 @@ #include "go_asm.h" #include "textflag.h" -// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally. -TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 +TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 IPM R10 MOVD R14, -248(R15) ADD $-248, R15 diff --git a/src/runtime/preempt_wasm.s b/src/runtime/preempt_wasm.s index da90e8aa6d..0cf57d3d22 100644 --- a/src/runtime/preempt_wasm.s +++ b/src/runtime/preempt_wasm.s @@ -3,7 +3,6 @@ #include "go_asm.h" #include "textflag.h" -// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally. -TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 +TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 // No async preemption on wasm UNDEF diff --git a/src/runtime/race.go b/src/runtime/race.go index cc8c5db1bd..f1c3c3098d 100644 --- a/src/runtime/race.go +++ b/src/runtime/race.go @@ -8,6 +8,7 @@ package runtime import ( + "internal/abi" "unsafe" ) @@ -361,7 +362,7 @@ func raceinit() (gctx, pctx uintptr) { throw("raceinit: race build must use cgo") } - racecall(&__tsan_init, uintptr(unsafe.Pointer(&gctx)), uintptr(unsafe.Pointer(&pctx)), funcPC(racecallbackthunk), 0) + racecall(&__tsan_init, uintptr(unsafe.Pointer(&gctx)), uintptr(unsafe.Pointer(&pctx)), abi.FuncPCABI0(racecallbackthunk), 0) // Round data segment to page boundaries, because it's used in mmap(). start := ^uintptr(0) diff --git a/src/runtime/race_amd64.s b/src/runtime/race_amd64.s index 8d4813eadd..469623ff20 100644 --- a/src/runtime/race_amd64.s +++ b/src/runtime/race_amd64.s @@ -441,9 +441,7 @@ call: // The overall effect of Go->C->Go call chain is similar to that of mcall. // RARG0 contains command code. RARG1 contains command-specific context. // See racecallback for command codes. -// Defined as ABIInternal so as to avoid introducing a wrapper, -// because its address is passed to C via funcPC. -TEXT runtime·racecallbackthunk(SB), NOSPLIT, $0-0 +TEXT runtime·racecallbackthunk(SB), NOSPLIT, $0-0 // Handle command raceGetProcCmd (0) here. // First, code below assumes that we are on curg, while raceGetProcCmd // can be executed on g0. Second, it is called frequently, so will diff --git a/src/runtime/signal_amd64.go b/src/runtime/signal_amd64.go index e45fbb4a87..afcf4404fb 100644 --- a/src/runtime/signal_amd64.go +++ b/src/runtime/signal_amd64.go @@ -9,6 +9,7 @@ package runtime import ( + "internal/abi" "runtime/internal/sys" "unsafe" ) @@ -70,10 +71,10 @@ func (c *sigctxt) preparePanic(sig uint32, gp *g) { // Go special registers. We inject sigpanic0 (instead of sigpanic), // which takes care of that. if shouldPushSigpanic(gp, pc, *(*uintptr)(unsafe.Pointer(sp))) { - c.pushCall(funcPC(sigpanic0), pc) + c.pushCall(abi.FuncPCABI0(sigpanic0), pc) } else { // Not safe to push the call. Just clobber the frame. - c.set_rip(uint64(funcPC(sigpanic0))) + c.set_rip(uint64(abi.FuncPCABI0(sigpanic0))) } } diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go index f2e526973d..6396232dd7 100644 --- a/src/runtime/signal_unix.go +++ b/src/runtime/signal_unix.go @@ -8,6 +8,7 @@ package runtime import ( + "internal/abi" "runtime/internal/atomic" "unsafe" ) @@ -329,7 +330,7 @@ func doSigPreempt(gp *g, ctxt *sigctxt) { if wantAsyncPreempt(gp) { if ok, newpc := isAsyncSafePoint(gp, ctxt.sigpc(), ctxt.sigsp(), ctxt.siglr()); ok { // Adjust the PC and inject a call to asyncPreempt. - ctxt.pushCall(funcPC(asyncPreempt), newpc) + ctxt.pushCall(abi.FuncPCABI0(asyncPreempt), newpc) } } diff --git a/src/runtime/signal_windows.go b/src/runtime/signal_windows.go index f2ce24d735..af15709a4a 100644 --- a/src/runtime/signal_windows.go +++ b/src/runtime/signal_windows.go @@ -5,6 +5,7 @@ package runtime import ( + "internal/abi" "runtime/internal/sys" "unsafe" ) @@ -27,15 +28,15 @@ func firstcontinuetramp() func lastcontinuetramp() func initExceptionHandler() { - stdcall2(_AddVectoredExceptionHandler, 1, funcPC(exceptiontramp)) + stdcall2(_AddVectoredExceptionHandler, 1, abi.FuncPCABI0(exceptiontramp)) if _AddVectoredContinueHandler == nil || GOARCH == "386" { // use SetUnhandledExceptionFilter for windows-386 or // if VectoredContinueHandler is unavailable. // note: SetUnhandledExceptionFilter handler won't be called, if debugging. - stdcall1(_SetUnhandledExceptionFilter, funcPC(lastcontinuetramp)) + stdcall1(_SetUnhandledExceptionFilter, abi.FuncPCABI0(lastcontinuetramp)) } else { - stdcall2(_AddVectoredContinueHandler, 1, funcPC(firstcontinuetramp)) - stdcall2(_AddVectoredContinueHandler, 0, funcPC(lastcontinuetramp)) + stdcall2(_AddVectoredContinueHandler, 1, abi.FuncPCABI0(firstcontinuetramp)) + stdcall2(_AddVectoredContinueHandler, 0, abi.FuncPCABI0(lastcontinuetramp)) } } @@ -133,7 +134,7 @@ func exceptionhandler(info *exceptionrecord, r *context, gp *g) int32 { // The exception is not from asyncPreempt, so not to push a // sigpanic call to make it look like that. Instead, just // overwrite the PC. (See issue #35773) - if r.ip() != 0 && r.ip() != funcPC(asyncPreempt) { + if r.ip() != 0 && r.ip() != abi.FuncPCABI0(asyncPreempt) { sp := unsafe.Pointer(r.sp()) delta := uintptr(sys.StackAlign) sp = add(sp, -delta) @@ -145,7 +146,7 @@ func exceptionhandler(info *exceptionrecord, r *context, gp *g) int32 { *((*uintptr)(sp)) = r.ip() } } - r.set_ip(funcPC(sigpanic0)) + r.set_ip(abi.FuncPCABI0(sigpanic0)) return _EXCEPTION_CONTINUE_EXECUTION } diff --git a/src/runtime/sys_linux_amd64.s b/src/runtime/sys_linux_amd64.s index 33cc670b64..f22b7ad928 100644 --- a/src/runtime/sys_linux_amd64.s +++ b/src/runtime/sys_linux_amd64.s @@ -328,9 +328,8 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32 POPQ BP RET -// Defined as ABIInternal since it does not use the stack-based Go ABI. // Called using C ABI. -TEXT runtime·sigtramp(SB),NOSPLIT,$0 +TEXT runtime·sigtramp(SB),NOSPLIT,$0 // Transition from C ABI to Go ABI. PUSH_REGS_HOST_TO_ABI0() @@ -348,8 +347,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0 // Used instead of sigtramp in programs that use cgo. // Arguments from kernel are in DI, SI, DX. -// Defined as ABIInternal since it does not use the stack-based Go ABI. -TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0 +TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0 // If no traceback function, do usual sigtramp. MOVQ runtime·cgoTraceback(SB), AX TESTQ AX, AX @@ -392,12 +390,12 @@ TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0 // The first three arguments, and the fifth, are already in registers. // Set the two remaining arguments now. MOVQ runtime·cgoTraceback(SB), CX - MOVQ $runtime·sigtramp(SB), R9 + MOVQ $runtime·sigtramp(SB), R9 MOVQ _cgo_callers(SB), AX JMP AX sigtramp: - JMP runtime·sigtramp(SB) + JMP runtime·sigtramp(SB) sigtrampnog: // Signal arrived on a non-Go thread. If this is SIGPROF, get a @@ -428,8 +426,7 @@ sigtrampnog: // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/x86_64/sigaction.c // The code that cares about the precise instructions used is: // https://gcc.gnu.org/viewcvs/gcc/trunk/libgcc/config/i386/linux-unwind.h?revision=219188&view=markup -// Defined as ABIInternal since it does not use the stack-based Go ABI. -TEXT runtime·sigreturn(SB),NOSPLIT,$0 +TEXT runtime·sigreturn(SB),NOSPLIT,$0 MOVQ $SYS_rt_sigreturn, AX SYSCALL INT $3 // not reached diff --git a/src/runtime/sys_windows_386.s b/src/runtime/sys_windows_386.s index 0b3933502a..cf3a439523 100644 --- a/src/runtime/sys_windows_386.s +++ b/src/runtime/sys_windows_386.s @@ -8,7 +8,7 @@ #include "time_windows.h" // void runtime·asmstdcall(void *c); -TEXT runtime·asmstdcall(SB),NOSPLIT,$0 +TEXT runtime·asmstdcall(SB),NOSPLIT,$0 MOVL fn+0(FP), BX // SetLastError(0). @@ -147,21 +147,21 @@ done: BYTE $0xC2; WORD $4 RET // unreached; make assembler happy -TEXT runtime·exceptiontramp(SB),NOSPLIT,$0 +TEXT runtime·exceptiontramp(SB),NOSPLIT,$0 MOVL $runtime·exceptionhandler(SB), AX JMP sigtramp<>(SB) -TEXT runtime·firstcontinuetramp(SB),NOSPLIT,$0-0 +TEXT runtime·firstcontinuetramp(SB),NOSPLIT,$0-0 // is never called INT $3 -TEXT runtime·lastcontinuetramp(SB),NOSPLIT,$0-0 +TEXT runtime·lastcontinuetramp(SB),NOSPLIT,$0-0 MOVL $runtime·lastcontinuehandler(SB), AX JMP sigtramp<>(SB) GLOBL runtime·cbctxts(SB), NOPTR, $4 -TEXT runtime·callbackasm1(SB),NOSPLIT,$0 +TEXT runtime·callbackasm1(SB),NOSPLIT,$0 MOVL 0(SP), AX // will use to find our callback context // remove return address from stack, we are not returning to callbackasm, but to its caller. @@ -180,7 +180,7 @@ TEXT runtime·callbackasm1(SB),NOSPLIT,$0 CLD // determine index into runtime·cbs table - SUBL $runtime·callbackasm(SB), AX + SUBL $runtime·callbackasm(SB), AX MOVL $0, DX MOVL $5, BX // divide by 5 because each call instruction in runtime·callbacks is 5 bytes long DIVL BX @@ -250,7 +250,7 @@ TEXT tstart<>(SB),NOSPLIT,$0 RET // uint32 tstart_stdcall(M *newm); -TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0 +TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0 MOVL newm+0(FP), BX PUSHL BX diff --git a/src/runtime/sys_windows_amd64.s b/src/runtime/sys_windows_amd64.s index e7782846b2..6cc5bba2b7 100644 --- a/src/runtime/sys_windows_amd64.s +++ b/src/runtime/sys_windows_amd64.s @@ -13,7 +13,7 @@ #define maxargs 18 // void runtime·asmstdcall(void *c); -TEXT runtime·asmstdcall(SB),NOSPLIT|NOFRAME,$0 +TEXT runtime·asmstdcall(SB),NOSPLIT|NOFRAME,$0 // asmcgocall will put first argument into CX. PUSHQ CX // save for later MOVQ libcall_fn(CX), AX @@ -179,15 +179,15 @@ done: RET -TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0 +TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0 MOVQ $runtime·exceptionhandler(SB), AX JMP sigtramp<>(SB) -TEXT runtime·firstcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0 +TEXT runtime·firstcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0 MOVQ $runtime·firstcontinuehandler(SB), AX JMP sigtramp<>(SB) -TEXT runtime·lastcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0 +TEXT runtime·lastcontinuetramp(SB),NOSPLIT|NOFRAME,$0-0 MOVQ $runtime·lastcontinuehandler(SB), AX JMP sigtramp<>(SB) @@ -212,7 +212,7 @@ TEXT runtime·callbackasm1(SB),NOSPLIT,$0 ADDQ $8, SP // determine index into runtime·cbs table - MOVQ $runtime·callbackasm(SB), DX + MOVQ $runtime·callbackasm(SB), DX SUBQ DX, AX MOVQ $0, DX MOVQ $5, CX // divide by 5 because each call instruction in runtime·callbacks is 5 bytes long @@ -245,7 +245,7 @@ TEXT runtime·callbackasm1(SB),NOSPLIT,$0 RET // uint32 tstart_stdcall(M *newm); -TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0 +TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0 // Switch from the host ABI to the Go ABI. PUSH_REGS_HOST_TO_ABI0() diff --git a/src/runtime/sys_windows_arm.s b/src/runtime/sys_windows_arm.s index 48f8c7dedf..c9e96cb652 100644 --- a/src/runtime/sys_windows_arm.s +++ b/src/runtime/sys_windows_arm.s @@ -10,7 +10,7 @@ // Note: For system ABI, R0-R3 are args, R4-R11 are callee-save. // void runtime·asmstdcall(void *c); -TEXT runtime·asmstdcall(SB),NOSPLIT|NOFRAME,$0 +TEXT runtime·asmstdcall(SB),NOSPLIT|NOFRAME,$0 MOVM.DB.W [R4, R5, R14], (R13) // push {r4, r5, lr} MOVW R0, R4 // put libcall * in r4 MOVW R13, R5 // save stack pointer in r5 @@ -222,21 +222,21 @@ TEXT sigresume<>(SB),NOSPLIT|NOFRAME,$0 MOVW R0, R13 B (R1) -TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0 +TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0 MOVW $runtime·exceptionhandler(SB), R1 B sigtramp<>(SB) -TEXT runtime·firstcontinuetramp(SB),NOSPLIT|NOFRAME,$0 +TEXT runtime·firstcontinuetramp(SB),NOSPLIT|NOFRAME,$0 MOVW $runtime·firstcontinuehandler(SB), R1 B sigtramp<>(SB) -TEXT runtime·lastcontinuetramp(SB),NOSPLIT|NOFRAME,$0 +TEXT runtime·lastcontinuetramp(SB),NOSPLIT|NOFRAME,$0 MOVW $runtime·lastcontinuehandler(SB), R1 B sigtramp<>(SB) GLOBL runtime·cbctxts(SB), NOPTR, $4 -TEXT runtime·callbackasm1(SB),NOSPLIT|NOFRAME,$0 +TEXT runtime·callbackasm1(SB),NOSPLIT|NOFRAME,$0 // On entry, the trampoline in zcallback_windows_arm.s left // the callback index in R12 (which is volatile in the C ABI). @@ -275,7 +275,7 @@ TEXT runtime·callbackasm1(SB),NOSPLIT|NOFRAME,$0 B (R12) // return // uint32 tstart_stdcall(M *newm); -TEXT runtime·tstart_stdcall(SB),NOSPLIT|NOFRAME,$0 +TEXT runtime·tstart_stdcall(SB),NOSPLIT|NOFRAME,$0 MOVM.DB.W [R4-R11, R14], (R13) // push {r4-r11, lr} MOVW m_g0(R0), g diff --git a/src/runtime/sys_windows_arm64.s b/src/runtime/sys_windows_arm64.s index 7a2e11f5ae..1cf877dce9 100644 --- a/src/runtime/sys_windows_arm64.s +++ b/src/runtime/sys_windows_arm64.s @@ -18,7 +18,7 @@ // load_g and save_g (in tls_arm64.s) clobber R27 (REGTMP) and R0. // void runtime·asmstdcall(void *c); -TEXT runtime·asmstdcall(SB),NOSPLIT|NOFRAME,$0 +TEXT runtime·asmstdcall(SB),NOSPLIT|NOFRAME,$0 STP.W (R29, R30), -32(RSP) // allocate C ABI stack frame STP (R19, R20), 16(RSP) // save old R19, R20 MOVD R0, R19 // save libcall pointer @@ -290,11 +290,11 @@ TEXT sigresume<>(SB),NOSPLIT|NOFRAME,$0 MOVD R0, RSP B (R1) -TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0 +TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0 MOVD $runtime·exceptionhandler(SB), R1 B sigtramp<>(SB) -TEXT runtime·firstcontinuetramp(SB),NOSPLIT|NOFRAME,$0 +TEXT runtime·firstcontinuetramp(SB),NOSPLIT|NOFRAME,$0 MOVD $runtime·firstcontinuehandler(SB), R1 B sigtramp<>(SB) @@ -304,7 +304,7 @@ TEXT runtime·lastcontinuetramp(SB),NOSPLIT|NOFRAME,$0 GLOBL runtime·cbctxts(SB), NOPTR, $4 -TEXT runtime·callbackasm1(SB),NOSPLIT,$208-0 +TEXT runtime·callbackasm1(SB),NOSPLIT,$208-0 NO_LOCAL_POINTERS // On entry, the trampoline in zcallback_windows_arm64.s left @@ -356,7 +356,7 @@ TEXT runtime·callbackasm1(SB),NOSPLIT,$208-0 RET // uint32 tstart_stdcall(M *newm); -TEXT runtime·tstart_stdcall(SB),NOSPLIT,$96-0 +TEXT runtime·tstart_stdcall(SB),NOSPLIT,$96-0 SAVE_R19_TO_R28(-10*8) MOVD m_g0(R0), g diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go index 6b9195bcd5..e045e5f4bf 100644 --- a/src/runtime/syscall_windows.go +++ b/src/runtime/syscall_windows.go @@ -224,7 +224,7 @@ func callbackasmAddr(i int) uintptr { // followed by a branch instruction entrySize = 8 } - return funcPC(callbackasm) + uintptr(i*entrySize) + return abi.FuncPCABI0(callbackasm) + uintptr(i*entrySize) } const callbackMaxFrame = 64 * sys.PtrSize diff --git a/src/runtime/wincallback.go b/src/runtime/wincallback.go index a7a787d8f6..73f1e567ce 100644 --- a/src/runtime/wincallback.go +++ b/src/runtime/wincallback.go @@ -33,7 +33,7 @@ func genasm386Amd64() { // CALL instruction in runtime·callbackasm. This determines // which Go callback function is executed later on. -TEXT runtime·callbackasm(SB),7,$0 +TEXT runtime·callbackasm(SB),7,$0 `) for i := 0; i < maxCallback; i++ { buf.WriteString("\tCALL\truntime·callbackasm1(SB)\n") @@ -61,7 +61,7 @@ func genasmArm() { // It then calls the Go implementation for that callback. #include "textflag.h" -TEXT runtime·callbackasm(SB),NOSPLIT|NOFRAME,$0 +TEXT runtime·callbackasm(SB),NOSPLIT|NOFRAME,$0 `) for i := 0; i < maxCallback; i++ { buf.WriteString(fmt.Sprintf("\tMOVW\t$%d, R12\n", i)) @@ -89,7 +89,7 @@ func genasmArm64() { // It then calls the Go implementation for that callback. #include "textflag.h" -TEXT runtime·callbackasm(SB),NOSPLIT|NOFRAME,$0 +TEXT runtime·callbackasm(SB),NOSPLIT|NOFRAME,$0 `) for i := 0; i < maxCallback; i++ { buf.WriteString(fmt.Sprintf("\tMOVD\t$%d, R12\n", i)) diff --git a/src/runtime/zcallback_windows.s b/src/runtime/zcallback_windows.s index e451c2b9d0..561527c90d 100644 --- a/src/runtime/zcallback_windows.s +++ b/src/runtime/zcallback_windows.s @@ -11,7 +11,7 @@ // CALL instruction in runtime·callbackasm. This determines // which Go callback function is executed later on. -TEXT runtime·callbackasm(SB),7,$0 +TEXT runtime·callbackasm(SB),7,$0 CALL runtime·callbackasm1(SB) CALL runtime·callbackasm1(SB) CALL runtime·callbackasm1(SB) diff --git a/src/runtime/zcallback_windows_arm.s b/src/runtime/zcallback_windows_arm.s index a73a813acb..f943d84cbf 100644 --- a/src/runtime/zcallback_windows_arm.s +++ b/src/runtime/zcallback_windows_arm.s @@ -9,7 +9,7 @@ // It then calls the Go implementation for that callback. #include "textflag.h" -TEXT runtime·callbackasm(SB),NOSPLIT|NOFRAME,$0 +TEXT runtime·callbackasm(SB),NOSPLIT|NOFRAME,$0 MOVW $0, R12 B runtime·callbackasm1(SB) MOVW $1, R12 diff --git a/src/runtime/zcallback_windows_arm64.s b/src/runtime/zcallback_windows_arm64.s index 2a6bda0990..69fb05788c 100644 --- a/src/runtime/zcallback_windows_arm64.s +++ b/src/runtime/zcallback_windows_arm64.s @@ -9,7 +9,7 @@ // It then calls the Go implementation for that callback. #include "textflag.h" -TEXT runtime·callbackasm(SB),NOSPLIT|NOFRAME,$0 +TEXT runtime·callbackasm(SB),NOSPLIT|NOFRAME,$0 MOVD $0, R12 B runtime·callbackasm1(SB) MOVD $1, R12 -- GitLab From 0e0a1f94f3bd6c34b630818ecee2bf1a395e4242 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 20 May 2021 19:04:33 -0400 Subject: [PATCH 0116/2500] [dev.typeparams] runtime: use ABI0 handler addresses on Windows/ARM64 The handler address is passed to sigtramp, which calls it using ABI0 calling convention. Use ABI0 symbols. Change-Id: I5c16abef5e74a992d972fa5e100fed0ffb9f090a Reviewed-on: https://go-review.googlesource.com/c/go/+/321951 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/runtime/sys_windows_arm64.s | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/runtime/sys_windows_arm64.s b/src/runtime/sys_windows_arm64.s index 1cf877dce9..e859371508 100644 --- a/src/runtime/sys_windows_arm64.s +++ b/src/runtime/sys_windows_arm64.s @@ -291,15 +291,15 @@ TEXT sigresume<>(SB),NOSPLIT|NOFRAME,$0 B (R1) TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0 - MOVD $runtime·exceptionhandler(SB), R1 + MOVD $runtime·exceptionhandler(SB), R1 B sigtramp<>(SB) TEXT runtime·firstcontinuetramp(SB),NOSPLIT|NOFRAME,$0 - MOVD $runtime·firstcontinuehandler(SB), R1 + MOVD $runtime·firstcontinuehandler(SB), R1 B sigtramp<>(SB) TEXT runtime·lastcontinuetramp(SB),NOSPLIT|NOFRAME,$0 - MOVD $runtime·lastcontinuehandler(SB), R1 + MOVD $runtime·lastcontinuehandler(SB), R1 B sigtramp<>(SB) GLOBL runtime·cbctxts(SB), NOPTR, $4 -- GitLab From 7d928460a183f4efeed97638aa29f5f1fe74e397 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 20 May 2021 21:33:01 -0400 Subject: [PATCH 0117/2500] [dev.typeparams] runtime: use internal/abi.FuncPCABI0 to reference ABI0 assembly symbols Use FuncPCABI0 to reference ABI0 assembly symbols. Currently, they are referenced using funcPC, which will get the ABI wrapper's address. They don't seem to affect correctness (either the wrapper is harmless, or, on non-AMD64 architectures, not enabled). They should have been converted. This CL does not yet completely eliminate funcPC. But at this point we should be able to replace all remaining uses of funcPC to internal/abi.FuncPCABIInternal. Change-Id: I383a686e11d570f757f185fe46769a42c856ab77 Reviewed-on: https://go-review.googlesource.com/c/go/+/321952 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/runtime/defs_plan9_386.go | 2 +- src/runtime/defs_plan9_amd64.go | 2 +- src/runtime/os3_plan9.go | 2 +- src/runtime/os_dragonfly.go | 4 ++-- src/runtime/os_freebsd.go | 5 +++-- src/runtime/os_linux.go | 2 +- src/runtime/os_netbsd.go | 5 +++-- src/runtime/os_netbsd_386.go | 7 +++++-- src/runtime/os_netbsd_amd64.go | 7 +++++-- src/runtime/os_netbsd_arm.go | 7 +++++-- src/runtime/os_netbsd_arm64.go | 7 +++++-- src/runtime/os_openbsd_syscall.go | 3 ++- src/runtime/proc.go | 2 +- src/runtime/sys_darwin_arm64.go | 5 +++-- src/runtime/sys_plan9_386.s | 4 ++++ src/runtime/sys_plan9_amd64.s | 4 ++++ 16 files changed, 46 insertions(+), 22 deletions(-) diff --git a/src/runtime/defs_plan9_386.go b/src/runtime/defs_plan9_386.go index 49129b3c3f..428044df68 100644 --- a/src/runtime/defs_plan9_386.go +++ b/src/runtime/defs_plan9_386.go @@ -61,4 +61,4 @@ func dumpregs(u *ureg) { print("gs ", hex(u.gs), "\n") } -func sigpanictramp() {} +func sigpanictramp() diff --git a/src/runtime/defs_plan9_amd64.go b/src/runtime/defs_plan9_amd64.go index 0099563034..15a27fc7db 100644 --- a/src/runtime/defs_plan9_amd64.go +++ b/src/runtime/defs_plan9_amd64.go @@ -78,4 +78,4 @@ func dumpregs(u *ureg) { print("gs ", hex(u.gs), "\n") } -func sigpanictramp() {} +func sigpanictramp() diff --git a/src/runtime/os3_plan9.go b/src/runtime/os3_plan9.go index dacb5c23a0..ce8bc7f103 100644 --- a/src/runtime/os3_plan9.go +++ b/src/runtime/os3_plan9.go @@ -99,7 +99,7 @@ func sighandler(_ureg *ureg, note *byte, gp *g) int { } } if usesLR { - c.setpc(funcPC(sigpanictramp)) + c.setpc(abi.FuncPCABI0(sigpanictramp)) } else { c.setpc(abi.FuncPCABI0(sigpanic0)) } diff --git a/src/runtime/os_dragonfly.go b/src/runtime/os_dragonfly.go index ab0ad4728f..45aeaecd89 100644 --- a/src/runtime/os_dragonfly.go +++ b/src/runtime/os_dragonfly.go @@ -148,14 +148,14 @@ func lwp_start(uintptr) func newosproc(mp *m) { stk := unsafe.Pointer(mp.g0.stack.hi) if false { - print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " lwp_start=", funcPC(lwp_start), " id=", mp.id, " ostk=", &mp, "\n") + print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " lwp_start=", abi.FuncPCABI0(lwp_start), " id=", mp.id, " ostk=", &mp, "\n") } var oset sigset sigprocmask(_SIG_SETMASK, &sigset_all, &oset) params := lwpparams{ - start_func: funcPC(lwp_start), + start_func: abi.FuncPCABI0(lwp_start), arg: unsafe.Pointer(mp), stack: uintptr(stk), tid1: nil, // minit will record tid diff --git a/src/runtime/os_freebsd.go b/src/runtime/os_freebsd.go index 09dd50ce59..41feaecf6b 100644 --- a/src/runtime/os_freebsd.go +++ b/src/runtime/os_freebsd.go @@ -5,6 +5,7 @@ package runtime import ( + "internal/abi" "runtime/internal/sys" "unsafe" ) @@ -197,11 +198,11 @@ func thr_start() func newosproc(mp *m) { stk := unsafe.Pointer(mp.g0.stack.hi) if false { - print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " thr_start=", funcPC(thr_start), " id=", mp.id, " ostk=", &mp, "\n") + print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " thr_start=", abi.FuncPCABI0(thr_start), " id=", mp.id, " ostk=", &mp, "\n") } param := thrparam{ - start_func: funcPC(thr_start), + start_func: abi.FuncPCABI0(thr_start), arg: unsafe.Pointer(mp), stack_base: mp.g0.stack.lo, stack_size: uintptr(stk) - mp.g0.stack.lo, diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go index 235c96e45a..9203f28351 100644 --- a/src/runtime/os_linux.go +++ b/src/runtime/os_linux.go @@ -143,7 +143,7 @@ func newosproc(mp *m) { * note: strace gets confused if we use CLONE_PTRACE here. */ if false { - print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " clone=", funcPC(clone), " id=", mp.id, " ostk=", &mp, "\n") + print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " clone=", abi.FuncPCABI0(clone), " id=", mp.id, " ostk=", &mp, "\n") } // Disable signals during clone, so that the new thread starts diff --git a/src/runtime/os_netbsd.go b/src/runtime/os_netbsd.go index 6fbb3aa694..0920d5293e 100644 --- a/src/runtime/os_netbsd.go +++ b/src/runtime/os_netbsd.go @@ -5,6 +5,7 @@ package runtime import ( + "internal/abi" "runtime/internal/atomic" "runtime/internal/sys" "unsafe" @@ -215,7 +216,7 @@ func newosproc(mp *m) { var oset sigset sigprocmask(_SIG_SETMASK, &sigset_all, &oset) - lwp_mcontext_init(&uc.uc_mcontext, stk, mp, mp.g0, funcPC(netbsdMstart)) + lwp_mcontext_init(&uc.uc_mcontext, stk, mp, mp.g0, abi.FuncPCABI0(netbsdMstart)) ret := lwp_create(unsafe.Pointer(&uc), _LWP_DETACHED, unsafe.Pointer(&mp.procid)) sigprocmask(_SIG_SETMASK, &oset, nil) @@ -319,7 +320,7 @@ func setsig(i uint32, fn uintptr) { sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART sa.sa_mask = sigset_all if fn == funcPC(sighandler) { - fn = funcPC(sigtramp) + fn = abi.FuncPCABI0(sigtramp) } sa.sa_sigaction = fn sigaction(i, &sa, nil) diff --git a/src/runtime/os_netbsd_386.go b/src/runtime/os_netbsd_386.go index 037f7e36dc..ac89b9852c 100644 --- a/src/runtime/os_netbsd_386.go +++ b/src/runtime/os_netbsd_386.go @@ -4,11 +4,14 @@ package runtime -import "unsafe" +import ( + "internal/abi" + "unsafe" +) func lwp_mcontext_init(mc *mcontextt, stk unsafe.Pointer, mp *m, gp *g, fn uintptr) { // Machine dependent mcontext initialisation for LWP. - mc.__gregs[_REG_EIP] = uint32(funcPC(lwp_tramp)) + mc.__gregs[_REG_EIP] = uint32(abi.FuncPCABI0(lwp_tramp)) mc.__gregs[_REG_UESP] = uint32(uintptr(stk)) mc.__gregs[_REG_EBX] = uint32(uintptr(unsafe.Pointer(mp))) mc.__gregs[_REG_EDX] = uint32(uintptr(unsafe.Pointer(gp))) diff --git a/src/runtime/os_netbsd_amd64.go b/src/runtime/os_netbsd_amd64.go index 5118b0c4ff..74eea0ceab 100644 --- a/src/runtime/os_netbsd_amd64.go +++ b/src/runtime/os_netbsd_amd64.go @@ -4,11 +4,14 @@ package runtime -import "unsafe" +import ( + "internal/abi" + "unsafe" +) func lwp_mcontext_init(mc *mcontextt, stk unsafe.Pointer, mp *m, gp *g, fn uintptr) { // Machine dependent mcontext initialisation for LWP. - mc.__gregs[_REG_RIP] = uint64(funcPC(lwp_tramp)) + mc.__gregs[_REG_RIP] = uint64(abi.FuncPCABI0(lwp_tramp)) mc.__gregs[_REG_RSP] = uint64(uintptr(stk)) mc.__gregs[_REG_R8] = uint64(uintptr(unsafe.Pointer(mp))) mc.__gregs[_REG_R9] = uint64(uintptr(unsafe.Pointer(gp))) diff --git a/src/runtime/os_netbsd_arm.go b/src/runtime/os_netbsd_arm.go index b5ec23e45b..5fb4e08d66 100644 --- a/src/runtime/os_netbsd_arm.go +++ b/src/runtime/os_netbsd_arm.go @@ -4,11 +4,14 @@ package runtime -import "unsafe" +import ( + "internal/abi" + "unsafe" +) func lwp_mcontext_init(mc *mcontextt, stk unsafe.Pointer, mp *m, gp *g, fn uintptr) { // Machine dependent mcontext initialisation for LWP. - mc.__gregs[_REG_R15] = uint32(funcPC(lwp_tramp)) + mc.__gregs[_REG_R15] = uint32(abi.FuncPCABI0(lwp_tramp)) mc.__gregs[_REG_R13] = uint32(uintptr(stk)) mc.__gregs[_REG_R0] = uint32(uintptr(unsafe.Pointer(mp))) mc.__gregs[_REG_R1] = uint32(uintptr(unsafe.Pointer(gp))) diff --git a/src/runtime/os_netbsd_arm64.go b/src/runtime/os_netbsd_arm64.go index 8d21b0a430..2dda9c9274 100644 --- a/src/runtime/os_netbsd_arm64.go +++ b/src/runtime/os_netbsd_arm64.go @@ -4,11 +4,14 @@ package runtime -import "unsafe" +import ( + "internal/abi" + "unsafe" +) func lwp_mcontext_init(mc *mcontextt, stk unsafe.Pointer, mp *m, gp *g, fn uintptr) { // Machine dependent mcontext initialisation for LWP. - mc.__gregs[_REG_ELR] = uint64(funcPC(lwp_tramp)) + mc.__gregs[_REG_ELR] = uint64(abi.FuncPCABI0(lwp_tramp)) mc.__gregs[_REG_X31] = uint64(uintptr(stk)) mc.__gregs[_REG_X0] = uint64(uintptr(unsafe.Pointer(mp))) mc.__gregs[_REG_X1] = uint64(uintptr(unsafe.Pointer(mp.g0))) diff --git a/src/runtime/os_openbsd_syscall.go b/src/runtime/os_openbsd_syscall.go index 3cdcb6c707..a04eb4fc4d 100644 --- a/src/runtime/os_openbsd_syscall.go +++ b/src/runtime/os_openbsd_syscall.go @@ -8,6 +8,7 @@ package runtime import ( + "internal/abi" "runtime/internal/sys" "unsafe" ) @@ -33,7 +34,7 @@ func newosproc(mp *m) { var oset sigset sigprocmask(_SIG_SETMASK, &sigset_all, &oset) - ret := tfork(¶m, unsafe.Sizeof(param), mp, mp.g0, funcPC(mstart)) + ret := tfork(¶m, unsafe.Sizeof(param), mp, mp.g0, abi.FuncPCABI0(mstart)) sigprocmask(_SIG_SETMASK, &oset, nil) if ret < 0 { diff --git a/src/runtime/proc.go b/src/runtime/proc.go index ded406cc28..694f456ac5 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -2236,7 +2236,7 @@ func newm1(mp *m) { } ts.g.set(mp.g0) ts.tls = (*uint64)(unsafe.Pointer(&mp.tls[0])) - ts.fn = unsafe.Pointer(funcPC(mstart)) + ts.fn = unsafe.Pointer(abi.FuncPCABI0(mstart)) if msanenabled { msanwrite(unsafe.Pointer(&ts), unsafe.Sizeof(ts)) } diff --git a/src/runtime/sys_darwin_arm64.go b/src/runtime/sys_darwin_arm64.go index 9c14f33a1c..7dabaca08d 100644 --- a/src/runtime/sys_darwin_arm64.go +++ b/src/runtime/sys_darwin_arm64.go @@ -5,6 +5,7 @@ package runtime import ( + "internal/abi" "runtime/internal/sys" "unsafe" ) @@ -14,14 +15,14 @@ import ( //go:nosplit //go:cgo_unsafe_args func g0_pthread_key_create(k *pthreadkey, destructor uintptr) int32 { - return asmcgocall(unsafe.Pointer(funcPC(pthread_key_create_trampoline)), unsafe.Pointer(&k)) + return asmcgocall(unsafe.Pointer(abi.FuncPCABI0(pthread_key_create_trampoline)), unsafe.Pointer(&k)) } func pthread_key_create_trampoline() //go:nosplit //go:cgo_unsafe_args func g0_pthread_setspecific(k pthreadkey, value uintptr) int32 { - return asmcgocall(unsafe.Pointer(funcPC(pthread_setspecific_trampoline)), unsafe.Pointer(&k)) + return asmcgocall(unsafe.Pointer(abi.FuncPCABI0(pthread_setspecific_trampoline)), unsafe.Pointer(&k)) } func pthread_setspecific_trampoline() diff --git a/src/runtime/sys_plan9_386.s b/src/runtime/sys_plan9_386.s index b3d2f1376d..bdcb98e19e 100644 --- a/src/runtime/sys_plan9_386.s +++ b/src/runtime/sys_plan9_386.s @@ -250,3 +250,7 @@ TEXT runtime·errstr(SB),NOSPLIT,$8-8 MOVL 0(SP), AX MOVL AX, ret_base+0(FP) RET + +// never called on this platform +TEXT ·sigpanictramp(SB),NOSPLIT,$0-0 + UNDEF diff --git a/src/runtime/sys_plan9_amd64.s b/src/runtime/sys_plan9_amd64.s index 731306ab44..39fc4c68e4 100644 --- a/src/runtime/sys_plan9_amd64.s +++ b/src/runtime/sys_plan9_amd64.s @@ -251,3 +251,7 @@ TEXT runtime·errstr(SB),NOSPLIT,$16-16 MOVQ 0(SP), AX MOVQ AX, ret_base+0(FP) RET + +// never called on this platform +TEXT ·sigpanictramp(SB),NOSPLIT,$0-0 + UNDEF -- GitLab From 6a81e063dd0bf28d21b7085cc1d9e76eaeb78460 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 20 May 2021 21:40:32 -0400 Subject: [PATCH 0118/2500] [dev.typeparams] runtime: fix misuse of funcPC funcPC expects a func value. There are places where we pass an unsafe.Pointer, which is technically undefined. In proc.go it is actually representing a func value, so the expression does the right thing. Cast to a func value so it is clearer. In os_freebsd.go it is a raw function pointer. Using funcPC on a raw function pointer is incorrect. Just use it directly instead. Change-Id: I3c5d61cea08f0abf5737834b520f9f1b583c1d34 Reviewed-on: https://go-review.googlesource.com/c/go/+/321953 Trust: Cherry Mui Reviewed-by: Michael Knyszek --- src/runtime/os_freebsd.go | 2 +- src/runtime/proc.go | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/runtime/os_freebsd.go b/src/runtime/os_freebsd.go index 41feaecf6b..151a5fd91a 100644 --- a/src/runtime/os_freebsd.go +++ b/src/runtime/os_freebsd.go @@ -237,7 +237,7 @@ func newosproc0(stacksize uintptr, fn unsafe.Pointer) { // However, newosproc0 is currently unreachable because builds // utilizing c-shared/c-archive force external linking. param := thrparam{ - start_func: funcPC(fn), + start_func: uintptr(fn), arg: nil, stack_base: uintptr(stack), //+stacksize? stack_size: stacksize, diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 694f456ac5..6c896cb993 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -6487,7 +6487,8 @@ func doInit(t *initTask) { // Load stats non-atomically since tracinit is updated only by this init goroutine. after := inittrace - pkg := funcpkgpath(findfunc(funcPC(firstFunc))) + f := *(*func())(unsafe.Pointer(&firstFunc)) + pkg := funcpkgpath(findfunc(funcPC(f))) var sbuf [24]byte print("init ", pkg, " @") -- GitLab From 626e89c261297d13ef892bb569640cd72c35b98a Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 21 May 2021 13:37:19 -0400 Subject: [PATCH 0119/2500] [dev.typeparams] runtime: replace funcPC with internal/abi.FuncPCABIInternal At this point all funcPC references are ABIInternal functions. Replace with the intrinsics. Change-Id: I3ba7e485c83017408749b53f92877d3727a75e27 Reviewed-on: https://go-review.googlesource.com/c/go/+/321954 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/cmd/compile/internal/test/inl_test.go | 1 - src/runtime/chan.go | 5 +++-- src/runtime/cpuprof.go | 9 ++++---- src/runtime/export_debug_test.go | 2 +- src/runtime/export_test.go | 2 -- src/runtime/iface.go | 9 ++++---- src/runtime/map.go | 19 +++++++++-------- src/runtime/map_fast32.go | 11 +++++----- src/runtime/map_fast64.go | 11 +++++----- src/runtime/map_faststr.go | 9 ++++---- src/runtime/mbarrier.go | 6 +++--- src/runtime/mprof.go | 5 +++-- src/runtime/norace_linux_test.go | 3 ++- src/runtime/os3_solaris.go | 2 +- src/runtime/os_aix.go | 3 ++- src/runtime/os_darwin.go | 2 +- src/runtime/os_dragonfly.go | 2 +- src/runtime/os_freebsd2.go | 2 +- src/runtime/os_freebsd_amd64.go | 2 +- src/runtime/os_linux.go | 2 +- src/runtime/os_netbsd.go | 2 +- src/runtime/os_openbsd.go | 2 +- src/runtime/preempt.go | 2 +- src/runtime/proc.go | 26 ++++++----------------- src/runtime/select.go | 5 +++-- src/runtime/signal_386.go | 5 +++-- src/runtime/signal_arm.go | 7 ++++-- src/runtime/signal_arm64.go | 3 ++- src/runtime/signal_linux_s390x.go | 3 ++- src/runtime/signal_mips64x.go | 3 ++- src/runtime/signal_mipsx.go | 3 ++- src/runtime/signal_ppc64x.go | 5 +++-- src/runtime/signal_riscv64.go | 3 ++- src/runtime/signal_unix.go | 8 +++---- src/runtime/slice.go | 7 +++--- src/runtime/stack.go | 2 +- src/runtime/string.go | 7 +++--- src/runtime/time.go | 3 ++- src/runtime/type.go | 7 ++++-- 39 files changed, 111 insertions(+), 99 deletions(-) diff --git a/src/cmd/compile/internal/test/inl_test.go b/src/cmd/compile/internal/test/inl_test.go index 6f100033cf..ad4e4fee97 100644 --- a/src/cmd/compile/internal/test/inl_test.go +++ b/src/cmd/compile/internal/test/inl_test.go @@ -48,7 +48,6 @@ func TestIntendedInlining(t *testing.T) { "fastlog2", "fastrand", "float64bits", - "funcPC", "getArgInfoFast", "getm", "getMCache", diff --git a/src/runtime/chan.go b/src/runtime/chan.go index f2a75b30f4..3cdb5dce11 100644 --- a/src/runtime/chan.go +++ b/src/runtime/chan.go @@ -18,6 +18,7 @@ package runtime // c.qcount < c.dataqsiz implies that c.sendq is empty. import ( + "internal/abi" "runtime/internal/atomic" "runtime/internal/math" "unsafe" @@ -169,7 +170,7 @@ func chansend(c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool { } if raceenabled { - racereadpc(c.raceaddr(), callerpc, funcPC(chansend)) + racereadpc(c.raceaddr(), callerpc, abi.FuncPCABIInternal(chansend)) } // Fast path: check for failed non-blocking operation without acquiring the lock. @@ -365,7 +366,7 @@ func closechan(c *hchan) { if raceenabled { callerpc := getcallerpc() - racewritepc(c.raceaddr(), callerpc, funcPC(closechan)) + racewritepc(c.raceaddr(), callerpc, abi.FuncPCABIInternal(closechan)) racerelease(c.raceaddr()) } diff --git a/src/runtime/cpuprof.go b/src/runtime/cpuprof.go index e5d0193b9c..c81ab710c2 100644 --- a/src/runtime/cpuprof.go +++ b/src/runtime/cpuprof.go @@ -13,6 +13,7 @@ package runtime import ( + "internal/abi" "runtime/internal/atomic" "runtime/internal/sys" "unsafe" @@ -166,8 +167,8 @@ func (p *cpuProfile) addExtra() { if p.lostExtra > 0 { hdr := [1]uint64{p.lostExtra} lostStk := [2]uintptr{ - funcPC(_LostExternalCode) + sys.PCQuantum, - funcPC(_ExternalCode) + sys.PCQuantum, + abi.FuncPCABIInternal(_LostExternalCode) + sys.PCQuantum, + abi.FuncPCABIInternal(_ExternalCode) + sys.PCQuantum, } p.log.write(nil, 0, hdr[:], lostStk[:]) p.lostExtra = 0 @@ -176,8 +177,8 @@ func (p *cpuProfile) addExtra() { if p.lostAtomic > 0 { hdr := [1]uint64{p.lostAtomic} lostStk := [2]uintptr{ - funcPC(_LostSIGPROFDuringAtomic64) + sys.PCQuantum, - funcPC(_System) + sys.PCQuantum, + abi.FuncPCABIInternal(_LostSIGPROFDuringAtomic64) + sys.PCQuantum, + abi.FuncPCABIInternal(_System) + sys.PCQuantum, } p.log.write(nil, 0, hdr[:], lostStk[:]) p.lostAtomic = 0 diff --git a/src/runtime/export_debug_test.go b/src/runtime/export_debug_test.go index fe4c9045c1..9808fd5299 100644 --- a/src/runtime/export_debug_test.go +++ b/src/runtime/export_debug_test.go @@ -125,7 +125,7 @@ func (h *debugCallHandler) inject(info *siginfo, ctxt *sigctxt, gp2 *g) bool { h.savedFP = *h.savedRegs.fpstate h.savedRegs.fpstate = nil // Set PC to debugCallV2. - ctxt.set_rip(uint64(funcPC(debugCallV2))) + ctxt.set_rip(uint64(abi.FuncPCABIInternal(debugCallV2))) // Call injected. Switch to the debugCall protocol. testSigtrap = h.handleF case _Grunnable: diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index a6fc1e4785..b4de497aca 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -27,8 +27,6 @@ var Exitsyscall = exitsyscall var LockedOSThread = lockedOSThread var Xadduintptr = atomic.Xadduintptr -var FuncPC = funcPC - var Fastlog2 = fastlog2 var Atoi = atoi diff --git a/src/runtime/iface.go b/src/runtime/iface.go index cd5fead999..b397d1ff8d 100644 --- a/src/runtime/iface.go +++ b/src/runtime/iface.go @@ -5,6 +5,7 @@ package runtime import ( + "internal/abi" "runtime/internal/atomic" "runtime/internal/sys" "unsafe" @@ -317,7 +318,7 @@ var ( func convT2E(t *_type, elem unsafe.Pointer) (e eface) { if raceenabled { - raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2E)) + raceReadObjectPC(t, elem, getcallerpc(), abi.FuncPCABIInternal(convT2E)) } if msanenabled { msanread(elem, t.size) @@ -390,7 +391,7 @@ func convTslice(val []byte) (x unsafe.Pointer) { func convT2Enoptr(t *_type, elem unsafe.Pointer) (e eface) { if raceenabled { - raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2Enoptr)) + raceReadObjectPC(t, elem, getcallerpc(), abi.FuncPCABIInternal(convT2Enoptr)) } if msanenabled { msanread(elem, t.size) @@ -405,7 +406,7 @@ func convT2Enoptr(t *_type, elem unsafe.Pointer) (e eface) { func convT2I(tab *itab, elem unsafe.Pointer) (i iface) { t := tab._type if raceenabled { - raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2I)) + raceReadObjectPC(t, elem, getcallerpc(), abi.FuncPCABIInternal(convT2I)) } if msanenabled { msanread(elem, t.size) @@ -420,7 +421,7 @@ func convT2I(tab *itab, elem unsafe.Pointer) (i iface) { func convT2Inoptr(tab *itab, elem unsafe.Pointer) (i iface) { t := tab._type if raceenabled { - raceReadObjectPC(t, elem, getcallerpc(), funcPC(convT2Inoptr)) + raceReadObjectPC(t, elem, getcallerpc(), abi.FuncPCABIInternal(convT2Inoptr)) } if msanenabled { msanread(elem, t.size) diff --git a/src/runtime/map.go b/src/runtime/map.go index 111db56b01..5575040f2a 100644 --- a/src/runtime/map.go +++ b/src/runtime/map.go @@ -54,6 +54,7 @@ package runtime // before the table grows. Typical tables will be somewhat less loaded. import ( + "internal/abi" "runtime/internal/atomic" "runtime/internal/math" "runtime/internal/sys" @@ -394,7 +395,7 @@ func makeBucketArray(t *maptype, b uint8, dirtyalloc unsafe.Pointer) (buckets un func mapaccess1(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer { if raceenabled && h != nil { callerpc := getcallerpc() - pc := funcPC(mapaccess1) + pc := abi.FuncPCABIInternal(mapaccess1) racereadpc(unsafe.Pointer(h), callerpc, pc) raceReadObjectPC(t.key, key, callerpc, pc) } @@ -452,7 +453,7 @@ bucketloop: func mapaccess2(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, bool) { if raceenabled && h != nil { callerpc := getcallerpc() - pc := funcPC(mapaccess2) + pc := abi.FuncPCABIInternal(mapaccess2) racereadpc(unsafe.Pointer(h), callerpc, pc) raceReadObjectPC(t.key, key, callerpc, pc) } @@ -574,7 +575,7 @@ func mapassign(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer { } if raceenabled { callerpc := getcallerpc() - pc := funcPC(mapassign) + pc := abi.FuncPCABIInternal(mapassign) racewritepc(unsafe.Pointer(h), callerpc, pc) raceReadObjectPC(t.key, key, callerpc, pc) } @@ -685,7 +686,7 @@ done: func mapdelete(t *maptype, h *hmap, key unsafe.Pointer) { if raceenabled && h != nil { callerpc := getcallerpc() - pc := funcPC(mapdelete) + pc := abi.FuncPCABIInternal(mapdelete) racewritepc(unsafe.Pointer(h), callerpc, pc) raceReadObjectPC(t.key, key, callerpc, pc) } @@ -802,7 +803,7 @@ search: func mapiterinit(t *maptype, h *hmap, it *hiter) { if raceenabled && h != nil { callerpc := getcallerpc() - racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapiterinit)) + racereadpc(unsafe.Pointer(h), callerpc, abi.FuncPCABIInternal(mapiterinit)) } if h == nil || h.count == 0 { @@ -852,7 +853,7 @@ func mapiternext(it *hiter) { h := it.h if raceenabled { callerpc := getcallerpc() - racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapiternext)) + racereadpc(unsafe.Pointer(h), callerpc, abi.FuncPCABIInternal(mapiternext)) } if h.flags&hashWriting != 0 { throw("concurrent map iteration and map write") @@ -978,7 +979,7 @@ next: func mapclear(t *maptype, h *hmap) { if raceenabled && h != nil { callerpc := getcallerpc() - pc := funcPC(mapclear) + pc := abi.FuncPCABIInternal(mapclear) racewritepc(unsafe.Pointer(h), callerpc, pc) } @@ -1363,7 +1364,7 @@ func reflect_maplen(h *hmap) int { } if raceenabled { callerpc := getcallerpc() - racereadpc(unsafe.Pointer(h), callerpc, funcPC(reflect_maplen)) + racereadpc(unsafe.Pointer(h), callerpc, abi.FuncPCABIInternal(reflect_maplen)) } return h.count } @@ -1375,7 +1376,7 @@ func reflectlite_maplen(h *hmap) int { } if raceenabled { callerpc := getcallerpc() - racereadpc(unsafe.Pointer(h), callerpc, funcPC(reflect_maplen)) + racereadpc(unsafe.Pointer(h), callerpc, abi.FuncPCABIInternal(reflect_maplen)) } return h.count } diff --git a/src/runtime/map_fast32.go b/src/runtime/map_fast32.go index 8d52dad217..420a01daec 100644 --- a/src/runtime/map_fast32.go +++ b/src/runtime/map_fast32.go @@ -5,6 +5,7 @@ package runtime import ( + "internal/abi" "runtime/internal/sys" "unsafe" ) @@ -12,7 +13,7 @@ import ( func mapaccess1_fast32(t *maptype, h *hmap, key uint32) unsafe.Pointer { if raceenabled && h != nil { callerpc := getcallerpc() - racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess1_fast32)) + racereadpc(unsafe.Pointer(h), callerpc, abi.FuncPCABIInternal(mapaccess1_fast32)) } if h == nil || h.count == 0 { return unsafe.Pointer(&zeroVal[0]) @@ -52,7 +53,7 @@ func mapaccess1_fast32(t *maptype, h *hmap, key uint32) unsafe.Pointer { func mapaccess2_fast32(t *maptype, h *hmap, key uint32) (unsafe.Pointer, bool) { if raceenabled && h != nil { callerpc := getcallerpc() - racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess2_fast32)) + racereadpc(unsafe.Pointer(h), callerpc, abi.FuncPCABIInternal(mapaccess2_fast32)) } if h == nil || h.count == 0 { return unsafe.Pointer(&zeroVal[0]), false @@ -95,7 +96,7 @@ func mapassign_fast32(t *maptype, h *hmap, key uint32) unsafe.Pointer { } if raceenabled { callerpc := getcallerpc() - racewritepc(unsafe.Pointer(h), callerpc, funcPC(mapassign_fast32)) + racewritepc(unsafe.Pointer(h), callerpc, abi.FuncPCABIInternal(mapassign_fast32)) } if h.flags&hashWriting != 0 { throw("concurrent map writes") @@ -185,7 +186,7 @@ func mapassign_fast32ptr(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer } if raceenabled { callerpc := getcallerpc() - racewritepc(unsafe.Pointer(h), callerpc, funcPC(mapassign_fast32)) + racewritepc(unsafe.Pointer(h), callerpc, abi.FuncPCABIInternal(mapassign_fast32)) } if h.flags&hashWriting != 0 { throw("concurrent map writes") @@ -272,7 +273,7 @@ done: func mapdelete_fast32(t *maptype, h *hmap, key uint32) { if raceenabled && h != nil { callerpc := getcallerpc() - racewritepc(unsafe.Pointer(h), callerpc, funcPC(mapdelete_fast32)) + racewritepc(unsafe.Pointer(h), callerpc, abi.FuncPCABIInternal(mapdelete_fast32)) } if h == nil || h.count == 0 { return diff --git a/src/runtime/map_fast64.go b/src/runtime/map_fast64.go index f1368dc774..cb202113ac 100644 --- a/src/runtime/map_fast64.go +++ b/src/runtime/map_fast64.go @@ -5,6 +5,7 @@ package runtime import ( + "internal/abi" "runtime/internal/sys" "unsafe" ) @@ -12,7 +13,7 @@ import ( func mapaccess1_fast64(t *maptype, h *hmap, key uint64) unsafe.Pointer { if raceenabled && h != nil { callerpc := getcallerpc() - racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess1_fast64)) + racereadpc(unsafe.Pointer(h), callerpc, abi.FuncPCABIInternal(mapaccess1_fast64)) } if h == nil || h.count == 0 { return unsafe.Pointer(&zeroVal[0]) @@ -52,7 +53,7 @@ func mapaccess1_fast64(t *maptype, h *hmap, key uint64) unsafe.Pointer { func mapaccess2_fast64(t *maptype, h *hmap, key uint64) (unsafe.Pointer, bool) { if raceenabled && h != nil { callerpc := getcallerpc() - racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess2_fast64)) + racereadpc(unsafe.Pointer(h), callerpc, abi.FuncPCABIInternal(mapaccess2_fast64)) } if h == nil || h.count == 0 { return unsafe.Pointer(&zeroVal[0]), false @@ -95,7 +96,7 @@ func mapassign_fast64(t *maptype, h *hmap, key uint64) unsafe.Pointer { } if raceenabled { callerpc := getcallerpc() - racewritepc(unsafe.Pointer(h), callerpc, funcPC(mapassign_fast64)) + racewritepc(unsafe.Pointer(h), callerpc, abi.FuncPCABIInternal(mapassign_fast64)) } if h.flags&hashWriting != 0 { throw("concurrent map writes") @@ -185,7 +186,7 @@ func mapassign_fast64ptr(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer } if raceenabled { callerpc := getcallerpc() - racewritepc(unsafe.Pointer(h), callerpc, funcPC(mapassign_fast64)) + racewritepc(unsafe.Pointer(h), callerpc, abi.FuncPCABIInternal(mapassign_fast64)) } if h.flags&hashWriting != 0 { throw("concurrent map writes") @@ -272,7 +273,7 @@ done: func mapdelete_fast64(t *maptype, h *hmap, key uint64) { if raceenabled && h != nil { callerpc := getcallerpc() - racewritepc(unsafe.Pointer(h), callerpc, funcPC(mapdelete_fast64)) + racewritepc(unsafe.Pointer(h), callerpc, abi.FuncPCABIInternal(mapdelete_fast64)) } if h == nil || h.count == 0 { return diff --git a/src/runtime/map_faststr.go b/src/runtime/map_faststr.go index 0673dd39c8..ed7e46b5f6 100644 --- a/src/runtime/map_faststr.go +++ b/src/runtime/map_faststr.go @@ -5,6 +5,7 @@ package runtime import ( + "internal/abi" "runtime/internal/sys" "unsafe" ) @@ -12,7 +13,7 @@ import ( func mapaccess1_faststr(t *maptype, h *hmap, ky string) unsafe.Pointer { if raceenabled && h != nil { callerpc := getcallerpc() - racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess1_faststr)) + racereadpc(unsafe.Pointer(h), callerpc, abi.FuncPCABIInternal(mapaccess1_faststr)) } if h == nil || h.count == 0 { return unsafe.Pointer(&zeroVal[0]) @@ -107,7 +108,7 @@ dohash: func mapaccess2_faststr(t *maptype, h *hmap, ky string) (unsafe.Pointer, bool) { if raceenabled && h != nil { callerpc := getcallerpc() - racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess2_faststr)) + racereadpc(unsafe.Pointer(h), callerpc, abi.FuncPCABIInternal(mapaccess2_faststr)) } if h == nil || h.count == 0 { return unsafe.Pointer(&zeroVal[0]), false @@ -205,7 +206,7 @@ func mapassign_faststr(t *maptype, h *hmap, s string) unsafe.Pointer { } if raceenabled { callerpc := getcallerpc() - racewritepc(unsafe.Pointer(h), callerpc, funcPC(mapassign_faststr)) + racewritepc(unsafe.Pointer(h), callerpc, abi.FuncPCABIInternal(mapassign_faststr)) } if h.flags&hashWriting != 0 { throw("concurrent map writes") @@ -300,7 +301,7 @@ done: func mapdelete_faststr(t *maptype, h *hmap, ky string) { if raceenabled && h != nil { callerpc := getcallerpc() - racewritepc(unsafe.Pointer(h), callerpc, funcPC(mapdelete_faststr)) + racewritepc(unsafe.Pointer(h), callerpc, abi.FuncPCABIInternal(mapdelete_faststr)) } if h == nil || h.count == 0 { return diff --git a/src/runtime/mbarrier.go b/src/runtime/mbarrier.go index 4994347bde..b06ee725dd 100644 --- a/src/runtime/mbarrier.go +++ b/src/runtime/mbarrier.go @@ -177,8 +177,8 @@ func typedmemmove(typ *_type, dst, src unsafe.Pointer) { //go:linkname reflect_typedmemmove reflect.typedmemmove func reflect_typedmemmove(typ *_type, dst, src unsafe.Pointer) { if raceenabled { - raceWriteObjectPC(typ, dst, getcallerpc(), funcPC(reflect_typedmemmove)) - raceReadObjectPC(typ, src, getcallerpc(), funcPC(reflect_typedmemmove)) + raceWriteObjectPC(typ, dst, getcallerpc(), abi.FuncPCABIInternal(reflect_typedmemmove)) + raceReadObjectPC(typ, src, getcallerpc(), abi.FuncPCABIInternal(reflect_typedmemmove)) } if msanenabled { msanwrite(dst, typ.size) @@ -254,7 +254,7 @@ func typedslicecopy(typ *_type, dstPtr unsafe.Pointer, dstLen int, srcPtr unsafe // code and needs its own instrumentation. if raceenabled { callerpc := getcallerpc() - pc := funcPC(slicecopy) + pc := abi.FuncPCABIInternal(slicecopy) racewriterangepc(dstPtr, uintptr(n)*typ.size, callerpc, pc) racereadrangepc(srcPtr, uintptr(n)*typ.size, callerpc, pc) } diff --git a/src/runtime/mprof.go b/src/runtime/mprof.go index 5235b898e4..0ba415ba5a 100644 --- a/src/runtime/mprof.go +++ b/src/runtime/mprof.go @@ -8,6 +8,7 @@ package runtime import ( + "internal/abi" "runtime/internal/atomic" "unsafe" ) @@ -621,7 +622,7 @@ func record(r *MemProfileRecord, b *bucket) { r.AllocObjects = int64(mp.active.allocs) r.FreeObjects = int64(mp.active.frees) if raceenabled { - racewriterangepc(unsafe.Pointer(&r.Stack0[0]), unsafe.Sizeof(r.Stack0), getcallerpc(), funcPC(MemProfile)) + racewriterangepc(unsafe.Pointer(&r.Stack0[0]), unsafe.Sizeof(r.Stack0), getcallerpc(), abi.FuncPCABIInternal(MemProfile)) } if msanenabled { msanwrite(unsafe.Pointer(&r.Stack0[0]), unsafe.Sizeof(r.Stack0)) @@ -674,7 +675,7 @@ func BlockProfile(p []BlockProfileRecord) (n int, ok bool) { } r.Cycles = bp.cycles if raceenabled { - racewriterangepc(unsafe.Pointer(&r.Stack0[0]), unsafe.Sizeof(r.Stack0), getcallerpc(), funcPC(BlockProfile)) + racewriterangepc(unsafe.Pointer(&r.Stack0[0]), unsafe.Sizeof(r.Stack0), getcallerpc(), abi.FuncPCABIInternal(BlockProfile)) } if msanenabled { msanwrite(unsafe.Pointer(&r.Stack0[0]), unsafe.Sizeof(r.Stack0)) diff --git a/src/runtime/norace_linux_test.go b/src/runtime/norace_linux_test.go index 94b7c7a467..b199aa633c 100644 --- a/src/runtime/norace_linux_test.go +++ b/src/runtime/norace_linux_test.go @@ -9,6 +9,7 @@ package runtime_test import ( + "internal/abi" "runtime" "testing" "time" @@ -25,7 +26,7 @@ func newOSProcCreated() { // Can't be run with -race because it inserts calls into newOSProcCreated() // that require a valid G/M. func TestNewOSProc0(t *testing.T) { - runtime.NewOSProc0(0x800000, unsafe.Pointer(runtime.FuncPC(newOSProcCreated))) + runtime.NewOSProc0(0x800000, unsafe.Pointer(abi.FuncPCABIInternal(newOSProcCreated))) check := time.NewTicker(100 * time.Millisecond) defer check.Stop() end := time.After(5 * time.Second) diff --git a/src/runtime/os3_solaris.go b/src/runtime/os3_solaris.go index 3b1a773ee2..bfd7c7eb64 100644 --- a/src/runtime/os3_solaris.go +++ b/src/runtime/os3_solaris.go @@ -242,7 +242,7 @@ func setsig(i uint32, fn uintptr) { sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART sa.sa_mask = sigset_all - if fn == funcPC(sighandler) { + if fn == abi.FuncPCABIInternal(sighandler) { // abi.FuncPCABIInternal(sighandler) matches the callers in signal_unix.go fn = abi.FuncPCABI0(sigtramp) } *((*uintptr)(unsafe.Pointer(&sa._funcptr))) = fn diff --git a/src/runtime/os_aix.go b/src/runtime/os_aix.go index 4fb1c8e845..478dde2fc3 100644 --- a/src/runtime/os_aix.go +++ b/src/runtime/os_aix.go @@ -8,6 +8,7 @@ package runtime import ( + "internal/abi" "unsafe" ) @@ -267,7 +268,7 @@ func setsig(i uint32, fn uintptr) { var sa sigactiont sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART sa.sa_mask = sigset_all - if fn == funcPC(sighandler) { + if fn == abi.FuncPCABIInternal(sighandler) { // abi.FuncPCABIInternal(sighandler) matches the callers in signal_unix.go fn = uintptr(unsafe.Pointer(&sigtramp)) } sa.sa_handler = fn diff --git a/src/runtime/os_darwin.go b/src/runtime/os_darwin.go index 00139351ab..df2c0ff4a5 100644 --- a/src/runtime/os_darwin.go +++ b/src/runtime/os_darwin.go @@ -364,7 +364,7 @@ func setsig(i uint32, fn uintptr) { var sa usigactiont sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART sa.sa_mask = ^uint32(0) - if fn == funcPC(sighandler) { // funcPC(sighandler) matches the callers in signal_unix.go + if fn == abi.FuncPCABIInternal(sighandler) { // abi.FuncPCABIInternal(sighandler) matches the callers in signal_unix.go if iscgo { fn = abi.FuncPCABI0(cgoSigtramp) } else { diff --git a/src/runtime/os_dragonfly.go b/src/runtime/os_dragonfly.go index 45aeaecd89..0c81ed4d7c 100644 --- a/src/runtime/os_dragonfly.go +++ b/src/runtime/os_dragonfly.go @@ -227,7 +227,7 @@ func setsig(i uint32, fn uintptr) { var sa sigactiont sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART sa.sa_mask = sigset_all - if fn == funcPC(sighandler) { + if fn == abi.FuncPCABIInternal(sighandler) { // abi.FuncPCABIInternal(sighandler) matches the callers in signal_unix.go fn = abi.FuncPCABI0(sigtramp) } sa.sa_sigaction = fn diff --git a/src/runtime/os_freebsd2.go b/src/runtime/os_freebsd2.go index 53ba23b64c..7e266dc27e 100644 --- a/src/runtime/os_freebsd2.go +++ b/src/runtime/os_freebsd2.go @@ -15,7 +15,7 @@ func setsig(i uint32, fn uintptr) { var sa sigactiont sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART sa.sa_mask = sigset_all - if fn == funcPC(sighandler) { + if fn == abi.FuncPCABIInternal(sighandler) { // abi.FuncPCABIInternal(sighandler) matches the callers in signal_unix.go fn = abi.FuncPCABI0(sigtramp) } sa.sa_handler = fn diff --git a/src/runtime/os_freebsd_amd64.go b/src/runtime/os_freebsd_amd64.go index 7ae80c2506..b179383eac 100644 --- a/src/runtime/os_freebsd_amd64.go +++ b/src/runtime/os_freebsd_amd64.go @@ -14,7 +14,7 @@ func setsig(i uint32, fn uintptr) { var sa sigactiont sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART sa.sa_mask = sigset_all - if fn == funcPC(sighandler) { + if fn == abi.FuncPCABIInternal(sighandler) { // abi.FuncPCABIInternal(sighandler) matches the callers in signal_unix.go if iscgo { fn = abi.FuncPCABI0(cgoSigtramp) } else { diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go index 9203f28351..1984bf6844 100644 --- a/src/runtime/os_linux.go +++ b/src/runtime/os_linux.go @@ -432,7 +432,7 @@ func setsig(i uint32, fn uintptr) { if GOARCH == "386" || GOARCH == "amd64" { sa.sa_restorer = abi.FuncPCABI0(sigreturn) } - if fn == funcPC(sighandler) { + if fn == abi.FuncPCABIInternal(sighandler) { // abi.FuncPCABIInternal(sighandler) matches the callers in signal_unix.go if iscgo { fn = abi.FuncPCABI0(cgoSigtramp) } else { diff --git a/src/runtime/os_netbsd.go b/src/runtime/os_netbsd.go index 0920d5293e..151cd17bbe 100644 --- a/src/runtime/os_netbsd.go +++ b/src/runtime/os_netbsd.go @@ -319,7 +319,7 @@ func setsig(i uint32, fn uintptr) { var sa sigactiont sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART sa.sa_mask = sigset_all - if fn == funcPC(sighandler) { + if fn == abi.FuncPCABIInternal(sighandler) { // abi.FuncPCABIInternal(sighandler) matches the callers in signal_unix.go fn = abi.FuncPCABI0(sigtramp) } sa.sa_sigaction = fn diff --git a/src/runtime/os_openbsd.go b/src/runtime/os_openbsd.go index 35995e7035..54f36c6ebf 100644 --- a/src/runtime/os_openbsd.go +++ b/src/runtime/os_openbsd.go @@ -192,7 +192,7 @@ func setsig(i uint32, fn uintptr) { var sa sigactiont sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART sa.sa_mask = uint32(sigset_all) - if fn == funcPC(sighandler) { + if fn == abi.FuncPCABIInternal(sighandler) { // abi.FuncPCABIInternal(sighandler) matches the callers in signal_unix.go fn = abi.FuncPCABI0(sigtramp) } sa.sa_sigaction = fn diff --git a/src/runtime/preempt.go b/src/runtime/preempt.go index d1291c9c48..d6cdf1b8f8 100644 --- a/src/runtime/preempt.go +++ b/src/runtime/preempt.go @@ -318,7 +318,7 @@ var asyncPreemptStack = ^uintptr(0) func init() { f := findfunc(abi.FuncPCABI0(asyncPreempt)) total := funcMaxSPDelta(f) - f = findfunc(funcPC(asyncPreempt2)) + f = findfunc(abi.FuncPCABIInternal(asyncPreempt2)) total += funcMaxSPDelta(f) // Add some overhead for return PCs, etc. asyncPreemptStack = uintptr(total) + 8*sys.PtrSize diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 6c896cb993..63eeb6c9c7 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -466,18 +466,6 @@ func releaseSudog(s *sudog) { releasem(mp) } -// funcPC returns the entry PC of the function f. -// It assumes that f is a func value. Otherwise the behavior is undefined. -// CAREFUL: In programs with plugins, funcPC can return different values -// for the same function (because there are actually multiple copies of -// the same function in the address space). To be safe, don't use the -// results of this function in any == expression. It is only safe to -// use the result as an address at which to start executing code. -//go:nosplit -func funcPC(f interface{}) uintptr { - return *(*uintptr)(efaceOf(&f).data) -} - // called from assembly func badmcall(fn func(*g)) { throw("runtime: mcall called on m->g0 stack") @@ -2043,7 +2031,7 @@ func oneNewExtraM() { gp.lockedm.set(mp) gp.goid = int64(atomic.Xadd64(&sched.goidgen, 1)) if raceenabled { - gp.racectx = racegostart(funcPC(newextram) + sys.PCQuantum) + gp.racectx = racegostart(abi.FuncPCABIInternal(newextram) + sys.PCQuantum) } // put on allg for garbage collector allgadd(gp) @@ -4741,16 +4729,16 @@ func sigprof(pc, sp, lr uintptr, gp *g, mp *m) { // If all of the above has failed, account it against abstract "System" or "GC". n = 2 if inVDSOPage(pc) { - pc = funcPC(_VDSO) + sys.PCQuantum + pc = abi.FuncPCABIInternal(_VDSO) + sys.PCQuantum } else if pc > firstmoduledata.etext { // "ExternalCode" is better than "etext". - pc = funcPC(_ExternalCode) + sys.PCQuantum + pc = abi.FuncPCABIInternal(_ExternalCode) + sys.PCQuantum } stk[0] = pc if mp.preemptoff != "" { - stk[1] = funcPC(_GC) + sys.PCQuantum + stk[1] = abi.FuncPCABIInternal(_GC) + sys.PCQuantum } else { - stk[1] = funcPC(_System) + sys.PCQuantum + stk[1] = abi.FuncPCABIInternal(_System) + sys.PCQuantum } } } @@ -4794,7 +4782,7 @@ func sigprofNonGoPC(pc uintptr) { if prof.hz != 0 { stk := []uintptr{ pc, - funcPC(_ExternalCode) + sys.PCQuantum, + abi.FuncPCABIInternal(_ExternalCode) + sys.PCQuantum, } cpuprof.addNonGo(stk) } @@ -6488,7 +6476,7 @@ func doInit(t *initTask) { after := inittrace f := *(*func())(unsafe.Pointer(&firstFunc)) - pkg := funcpkgpath(findfunc(funcPC(f))) + pkg := funcpkgpath(findfunc(abi.FuncPCABIInternal(f))) var sbuf [24]byte print("init ", pkg, " @") diff --git a/src/runtime/select.go b/src/runtime/select.go index e72761bfa9..74f0c29194 100644 --- a/src/runtime/select.go +++ b/src/runtime/select.go @@ -7,6 +7,7 @@ package runtime // This file contains the implementation of Go select statements. import ( + "internal/abi" "runtime/internal/atomic" "unsafe" ) @@ -22,8 +23,8 @@ type scase struct { } var ( - chansendpc = funcPC(chansend) - chanrecvpc = funcPC(chanrecv) + chansendpc = abi.FuncPCABIInternal(chansend) + chanrecvpc = abi.FuncPCABIInternal(chanrecv) ) func selectsetpc(pc *uintptr) { diff --git a/src/runtime/signal_386.go b/src/runtime/signal_386.go index 5824eaddb5..c77a9cc522 100644 --- a/src/runtime/signal_386.go +++ b/src/runtime/signal_386.go @@ -8,6 +8,7 @@ package runtime import ( + "internal/abi" "runtime/internal/sys" "unsafe" ) @@ -42,10 +43,10 @@ func (c *sigctxt) preparePanic(sig uint32, gp *g) { sp := uintptr(c.esp()) if shouldPushSigpanic(gp, pc, *(*uintptr)(unsafe.Pointer(sp))) { - c.pushCall(funcPC(sigpanic), pc) + c.pushCall(abi.FuncPCABIInternal(sigpanic), pc) } else { // Not safe to push the call. Just clobber the frame. - c.set_eip(uint32(funcPC(sigpanic))) + c.set_eip(uint32(abi.FuncPCABIInternal(sigpanic))) } } diff --git a/src/runtime/signal_arm.go b/src/runtime/signal_arm.go index 4d9c6224a2..a0780788f8 100644 --- a/src/runtime/signal_arm.go +++ b/src/runtime/signal_arm.go @@ -7,7 +7,10 @@ package runtime -import "unsafe" +import ( + "internal/abi" + "unsafe" +) func dumpregs(c *sigctxt) { print("trap ", hex(c.trap()), "\n") @@ -61,7 +64,7 @@ func (c *sigctxt) preparePanic(sig uint32, gp *g) { // In case we are panicking from external C code c.set_r10(uint32(uintptr(unsafe.Pointer(gp)))) - c.set_pc(uint32(funcPC(sigpanic))) + c.set_pc(uint32(abi.FuncPCABIInternal(sigpanic))) } func (c *sigctxt) pushCall(targetPC, resumePC uintptr) { diff --git a/src/runtime/signal_arm64.go b/src/runtime/signal_arm64.go index f04750084f..9d4a8b8a99 100644 --- a/src/runtime/signal_arm64.go +++ b/src/runtime/signal_arm64.go @@ -8,6 +8,7 @@ package runtime import ( + "internal/abi" "runtime/internal/sys" "unsafe" ) @@ -77,7 +78,7 @@ func (c *sigctxt) preparePanic(sig uint32, gp *g) { // In case we are panicking from external C code c.set_r28(uint64(uintptr(unsafe.Pointer(gp)))) - c.set_pc(uint64(funcPC(sigpanic))) + c.set_pc(uint64(abi.FuncPCABIInternal(sigpanic))) } func (c *sigctxt) pushCall(targetPC, resumePC uintptr) { diff --git a/src/runtime/signal_linux_s390x.go b/src/runtime/signal_linux_s390x.go index 12d5c31593..03c58cbbb6 100644 --- a/src/runtime/signal_linux_s390x.go +++ b/src/runtime/signal_linux_s390x.go @@ -5,6 +5,7 @@ package runtime import ( + "internal/abi" "runtime/internal/sys" "unsafe" ) @@ -107,7 +108,7 @@ func (c *sigctxt) preparePanic(sig uint32, gp *g) { // In case we are panicking from external C code c.set_r0(0) c.set_r13(uint64(uintptr(unsafe.Pointer(gp)))) - c.set_pc(uint64(funcPC(sigpanic))) + c.set_pc(uint64(abi.FuncPCABIInternal(sigpanic))) } func (c *sigctxt) pushCall(targetPC, resumePC uintptr) { diff --git a/src/runtime/signal_mips64x.go b/src/runtime/signal_mips64x.go index 1616b57027..eebcc74886 100644 --- a/src/runtime/signal_mips64x.go +++ b/src/runtime/signal_mips64x.go @@ -9,6 +9,7 @@ package runtime import ( + "internal/abi" "runtime/internal/sys" "unsafe" ) @@ -80,7 +81,7 @@ func (c *sigctxt) preparePanic(sig uint32, gp *g) { } // In case we are panicking from external C code - sigpanicPC := uint64(funcPC(sigpanic)) + sigpanicPC := uint64(abi.FuncPCABIInternal(sigpanic)) c.set_r28(sigpanicPC >> 32 << 32) // RSB register c.set_r30(uint64(uintptr(unsafe.Pointer(gp)))) c.set_pc(sigpanicPC) diff --git a/src/runtime/signal_mipsx.go b/src/runtime/signal_mipsx.go index dcc7f1e9dd..5067799bd6 100644 --- a/src/runtime/signal_mipsx.go +++ b/src/runtime/signal_mipsx.go @@ -9,6 +9,7 @@ package runtime import ( + "internal/abi" "runtime/internal/sys" "unsafe" ) @@ -78,7 +79,7 @@ func (c *sigctxt) preparePanic(sig uint32, gp *g) { // In case we are panicking from external C code c.set_r30(uint32(uintptr(unsafe.Pointer(gp)))) - c.set_pc(uint32(funcPC(sigpanic))) + c.set_pc(uint32(abi.FuncPCABIInternal(sigpanic))) } func (c *sigctxt) pushCall(targetPC, resumePC uintptr) { diff --git a/src/runtime/signal_ppc64x.go b/src/runtime/signal_ppc64x.go index f2225da9a1..8a39d59957 100644 --- a/src/runtime/signal_ppc64x.go +++ b/src/runtime/signal_ppc64x.go @@ -9,6 +9,7 @@ package runtime import ( + "internal/abi" "runtime/internal/sys" "unsafe" ) @@ -83,8 +84,8 @@ func (c *sigctxt) preparePanic(sig uint32, gp *g) { // In case we are panicking from external C code c.set_r0(0) c.set_r30(uint64(uintptr(unsafe.Pointer(gp)))) - c.set_r12(uint64(funcPC(sigpanic))) - c.set_pc(uint64(funcPC(sigpanic))) + c.set_r12(uint64(abi.FuncPCABIInternal(sigpanic))) + c.set_pc(uint64(abi.FuncPCABIInternal(sigpanic))) } func (c *sigctxt) pushCall(targetPC, resumePC uintptr) { diff --git a/src/runtime/signal_riscv64.go b/src/runtime/signal_riscv64.go index e6b1b14130..aaaa217051 100644 --- a/src/runtime/signal_riscv64.go +++ b/src/runtime/signal_riscv64.go @@ -8,6 +8,7 @@ package runtime import ( + "internal/abi" "runtime/internal/sys" "unsafe" ) @@ -76,7 +77,7 @@ func (c *sigctxt) preparePanic(sig uint32, gp *g) { // In case we are panicking from external C code c.set_gp(uint64(uintptr(unsafe.Pointer(gp)))) - c.set_pc(uint64(funcPC(sigpanic))) + c.set_pc(uint64(abi.FuncPCABIInternal(sigpanic))) } func (c *sigctxt) pushCall(targetPC, resumePC uintptr) { diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go index 6396232dd7..0b3414d457 100644 --- a/src/runtime/signal_unix.go +++ b/src/runtime/signal_unix.go @@ -144,7 +144,7 @@ func initsig(preinit bool) { } handlingSig[i] = 1 - setsig(i, funcPC(sighandler)) + setsig(i, abi.FuncPCABIInternal(sighandler)) } } @@ -195,7 +195,7 @@ func sigenable(sig uint32) { <-maskUpdatedChan if atomic.Cas(&handlingSig[sig], 0, 1) { atomic.Storeuintptr(&fwdSig[sig], getsig(sig)) - setsig(sig, funcPC(sighandler)) + setsig(sig, abi.FuncPCABIInternal(sighandler)) } } } @@ -272,7 +272,7 @@ func setProcessCPUProfiler(hz int32) { // Enable the Go signal handler if not enabled. if atomic.Cas(&handlingSig[_SIGPROF], 0, 1) { atomic.Storeuintptr(&fwdSig[_SIGPROF], getsig(_SIGPROF)) - setsig(_SIGPROF, funcPC(sighandler)) + setsig(_SIGPROF, abi.FuncPCABIInternal(sighandler)) } var it itimerval @@ -844,7 +844,7 @@ func raisebadsignal(sig uint32, c *sigctxt) { // We may receive another instance of the signal before we // restore the Go handler, but that is not so bad: we know // that the Go program has been ignoring the signal. - setsig(sig, funcPC(sighandler)) + setsig(sig, abi.FuncPCABIInternal(sighandler)) } //go:nosplit diff --git a/src/runtime/slice.go b/src/runtime/slice.go index f9d4154acf..7a470f09b6 100644 --- a/src/runtime/slice.go +++ b/src/runtime/slice.go @@ -5,6 +5,7 @@ package runtime import ( + "internal/abi" "runtime/internal/math" "runtime/internal/sys" "unsafe" @@ -68,7 +69,7 @@ func makeslicecopy(et *_type, tolen int, fromlen int, from unsafe.Pointer) unsaf if raceenabled { callerpc := getcallerpc() - pc := funcPC(makeslicecopy) + pc := abi.FuncPCABIInternal(makeslicecopy) racereadrangepc(from, copymem, callerpc, pc) } if msanenabled { @@ -144,7 +145,7 @@ func panicunsafeslicelen() { func growslice(et *_type, old slice, cap int) slice { if raceenabled { callerpc := getcallerpc() - racereadrangepc(old.array, uintptr(old.len*int(et.size)), callerpc, funcPC(growslice)) + racereadrangepc(old.array, uintptr(old.len*int(et.size)), callerpc, abi.FuncPCABIInternal(growslice)) } if msanenabled { msanread(old.array, uintptr(old.len*int(et.size))) @@ -280,7 +281,7 @@ func slicecopy(toPtr unsafe.Pointer, toLen int, fromPtr unsafe.Pointer, fromLen size := uintptr(n) * width if raceenabled { callerpc := getcallerpc() - pc := funcPC(slicecopy) + pc := abi.FuncPCABIInternal(slicecopy) racereadrangepc(fromPtr, size, callerpc, pc) racewriterangepc(toPtr, size, callerpc, pc) } diff --git a/src/runtime/stack.go b/src/runtime/stack.go index b21c9c9518..622de45f25 100644 --- a/src/runtime/stack.go +++ b/src/runtime/stack.go @@ -1112,7 +1112,7 @@ func gostartcallfn(gobuf *gobuf, fv *funcval) { if fv != nil { fn = unsafe.Pointer(fv.fn) } else { - fn = unsafe.Pointer(funcPC(nilfunc)) + fn = unsafe.Pointer(abi.FuncPCABIInternal(nilfunc)) } gostartcall(gobuf, fn, unsafe.Pointer(fv)) } diff --git a/src/runtime/string.go b/src/runtime/string.go index d6030a1dca..3c215d3754 100644 --- a/src/runtime/string.go +++ b/src/runtime/string.go @@ -5,6 +5,7 @@ package runtime import ( + "internal/abi" "internal/bytealg" "runtime/internal/sys" "unsafe" @@ -88,7 +89,7 @@ func slicebytetostring(buf *tmpBuf, ptr *byte, n int) (str string) { racereadrangepc(unsafe.Pointer(ptr), uintptr(n), getcallerpc(), - funcPC(slicebytetostring)) + abi.FuncPCABIInternal(slicebytetostring)) } if msanenabled { msanread(unsafe.Pointer(ptr), uintptr(n)) @@ -152,7 +153,7 @@ func slicebytetostringtmp(ptr *byte, n int) (str string) { racereadrangepc(unsafe.Pointer(ptr), uintptr(n), getcallerpc(), - funcPC(slicebytetostringtmp)) + abi.FuncPCABIInternal(slicebytetostringtmp)) } if msanenabled && n > 0 { msanread(unsafe.Pointer(ptr), uintptr(n)) @@ -203,7 +204,7 @@ func slicerunetostring(buf *tmpBuf, a []rune) string { racereadrangepc(unsafe.Pointer(&a[0]), uintptr(len(a))*unsafe.Sizeof(a[0]), getcallerpc(), - funcPC(slicerunetostring)) + abi.FuncPCABIInternal(slicerunetostring)) } if msanenabled && len(a) > 0 { msanread(unsafe.Pointer(&a[0]), uintptr(len(a))*unsafe.Sizeof(a[0])) diff --git a/src/runtime/time.go b/src/runtime/time.go index dee6a674e4..90e9b1139f 100644 --- a/src/runtime/time.go +++ b/src/runtime/time.go @@ -7,6 +7,7 @@ package runtime import ( + "internal/abi" "runtime/internal/atomic" "runtime/internal/sys" "unsafe" @@ -856,7 +857,7 @@ func runOneTimer(pp *p, t *timer, now int64) { if raceenabled { ppcur := getg().m.p.ptr() if ppcur.timerRaceCtx == 0 { - ppcur.timerRaceCtx = racegostart(funcPC(runtimer) + sys.PCQuantum) + ppcur.timerRaceCtx = racegostart(abi.FuncPCABIInternal(runtimer) + sys.PCQuantum) } raceacquirectx(ppcur.timerRaceCtx, unsafe.Pointer(t)) } diff --git a/src/runtime/type.go b/src/runtime/type.go index 335fc57f4b..52e65a3bd2 100644 --- a/src/runtime/type.go +++ b/src/runtime/type.go @@ -6,7 +6,10 @@ package runtime -import "unsafe" +import ( + "internal/abi" + "unsafe" +) // tflag is documented in reflect/type.go. // @@ -262,7 +265,7 @@ func (t *_type) textOff(off textOff) unsafe.Pointer { if off == -1 { // -1 is the sentinel value for unreachable code. // See cmd/link/internal/ld/data.go:relocsym. - return unsafe.Pointer(funcPC(unreachableMethod)) + return unsafe.Pointer(abi.FuncPCABIInternal(unreachableMethod)) } base := uintptr(unsafe.Pointer(t)) var md *moduledata -- GitLab From 8d2b4cb6cc3100f337e08cc7342f42823fa1dc9a Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 10 May 2021 16:23:35 -0700 Subject: [PATCH 0120/2500] [dev.typeparams] cmd/compile: fixing import of comm clauses/closures in generic functions Improvements: - Fix export/import of the default case of a select statement (was not dealing with nil Comm case) - Set properly the name of closure functions in imported generic functions Added new test exporting/importing a reasonably large channel package, chansimp.go. Change-Id: If2ee12bd749e5df415f48ec4b629a2fa68a79dcb Reviewed-on: https://go-review.googlesource.com/c/go/+/321734 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Dan Scales --- src/cmd/compile/internal/typecheck/iexport.go | 7 +- src/cmd/compile/internal/typecheck/iimport.go | 14 +- test/typeparam/chansimp.dir/a.go | 232 ++++++++++++++++++ test/typeparam/chansimp.dir/main.go | 189 ++++++++++++++ test/typeparam/chansimp.go | 7 + 5 files changed, 447 insertions(+), 2 deletions(-) create mode 100644 test/typeparam/chansimp.dir/a.go create mode 100644 test/typeparam/chansimp.dir/main.go create mode 100644 test/typeparam/chansimp.go diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 802a8c3839..d956ada3c5 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -1523,7 +1523,12 @@ func (w *exportWriter) commList(cases []*ir.CommClause) { w.uint64(uint64(len(cases))) for _, cas := range cases { w.pos(cas.Pos()) - w.node(cas.Comm) + defaultCase := cas.Comm == nil + w.bool(defaultCase) + if !defaultCase { + // Only call w.node for non-default cause (cas.Comm is non-nil) + w.node(cas.Comm) + } w.stmtList(cas.Body) } } diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 39b5ab09da..966e865630 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1121,7 +1121,13 @@ func (r *importReader) caseList(switchExpr ir.Node) []*ir.CaseClause { func (r *importReader) commList() []*ir.CommClause { cases := make([]*ir.CommClause, r.uint64()) for i := range cases { - cases[i] = ir.NewCommStmt(r.pos(), r.node(), r.stmtList()) + pos := r.pos() + defaultCase := r.bool() + var comm ir.Node + if !defaultCase { + comm = r.node() + } + cases[i] = ir.NewCommStmt(pos, comm, r.stmtList()) } return cases } @@ -1257,6 +1263,12 @@ func (r *importReader) node() ir.Node { if go117ExportTypes { clo.SetType(typ) } + if r.curfn.Type().HasTParam() { + // Generic functions aren't inlined, so give the closure a + // function name now, which is then available for use + // (after appending the type args) for each stenciling. + fn.Nname.SetSym(ClosureName(r.curfn)) + } return clo diff --git a/test/typeparam/chansimp.dir/a.go b/test/typeparam/chansimp.dir/a.go new file mode 100644 index 0000000000..a3f73b2199 --- /dev/null +++ b/test/typeparam/chansimp.dir/a.go @@ -0,0 +1,232 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +import ( + "context" + "runtime" +) + +// Equal reports whether two slices are equal: the same length and all +// elements equal. All floating point NaNs are considered equal. +func SliceEqual[Elem comparable](s1, s2 []Elem) bool { + if len(s1) != len(s2) { + return false + } + for i, v1 := range s1 { + v2 := s2[i] + if v1 != v2 { + isNaN := func(f Elem) bool { return f != f } + if !isNaN(v1) || !isNaN(v2) { + return false + } + } + } + return true +} + +// ReadAll reads from c until the channel is closed or the context is +// canceled, returning all the values read. +func ReadAll[Elem any](ctx context.Context, c <-chan Elem) []Elem { + var r []Elem + for { + select { + case <-ctx.Done(): + return r + case v, ok := <-c: + if !ok { + return r + } + r = append(r, v) + } + } +} + +// Merge merges two channels into a single channel. +// This will leave a goroutine running until either both channels are closed +// or the context is canceled, at which point the returned channel is closed. +func Merge[Elem any](ctx context.Context, c1, c2 <-chan Elem) <-chan Elem { + r := make(chan Elem) + go func(ctx context.Context, c1, c2 <-chan Elem, r chan<- Elem) { + defer close(r) + for c1 != nil || c2 != nil { + select { + case <-ctx.Done(): + return + case v1, ok := <-c1: + if ok { + r <- v1 + } else { + c1 = nil + } + case v2, ok := <-c2: + if ok { + r <- v2 + } else { + c2 = nil + } + } + } + }(ctx, c1, c2, r) + return r +} + +// Filter calls f on each value read from c. If f returns true the value +// is sent on the returned channel. This will leave a goroutine running +// until c is closed or the context is canceled, at which point the +// returned channel is closed. +func Filter[Elem any](ctx context.Context, c <-chan Elem, f func(Elem) bool) <-chan Elem { + r := make(chan Elem) + go func(ctx context.Context, c <-chan Elem, f func(Elem) bool, r chan<- Elem) { + defer close(r) + for { + select { + case <-ctx.Done(): + return + case v, ok := <-c: + if !ok { + return + } + if f(v) { + r <- v + } + } + } + }(ctx, c, f, r) + return r +} + +// Sink returns a channel that discards all values sent to it. +// This will leave a goroutine running until the context is canceled +// or the returned channel is closed. +func Sink[Elem any](ctx context.Context) chan<- Elem { + r := make(chan Elem) + go func(ctx context.Context, r <-chan Elem) { + for { + select { + case <-ctx.Done(): + return + case _, ok := <-r: + if !ok { + return + } + } + } + }(ctx, r) + return r +} + +// An Exclusive is a value that may only be used by a single goroutine +// at a time. This is implemented using channels rather than a mutex. +type Exclusive[Val any] struct { + c chan Val +} + +// MakeExclusive makes an initialized exclusive value. +func MakeExclusive[Val any](initial Val) *Exclusive[Val] { + r := &Exclusive[Val]{ + c: make(chan Val, 1), + } + r.c <- initial + return r +} + +// Acquire acquires the exclusive value for private use. +// It must be released using the Release method. +func (e *Exclusive[Val]) Acquire() Val { + return <-e.c +} + +// TryAcquire attempts to acquire the value. The ok result reports whether +// the value was acquired. If the value is acquired, it must be released +// using the Release method. +func (e *Exclusive[Val]) TryAcquire() (v Val, ok bool) { + select { + case r := <-e.c: + return r, true + default: + return v, false + } +} + +// Release updates and releases the value. +// This method panics if the value has not been acquired. +func (e *Exclusive[Val]) Release(v Val) { + select { + case e.c <- v: + default: + panic("Exclusive Release without Acquire") + } +} + +// Ranger returns a Sender and a Receiver. The Receiver provides a +// Next method to retrieve values. The Sender provides a Send method +// to send values and a Close method to stop sending values. The Next +// method indicates when the Sender has been closed, and the Send +// method indicates when the Receiver has been freed. +// +// This is a convenient way to exit a goroutine sending values when +// the receiver stops reading them. +func Ranger[Elem any]() (*Sender[Elem], *Receiver[Elem]) { + c := make(chan Elem) + d := make(chan struct{}) + s := &Sender[Elem]{ + values: c, + done: d, + } + r := &Receiver[Elem] { + values: c, + done: d, + } + runtime.SetFinalizer(r, (*Receiver[Elem]).finalize) + return s, r +} + +// A Sender is used to send values to a Receiver. +type Sender[Elem any] struct { + values chan<- Elem + done <-chan struct{} +} + +// Send sends a value to the receiver. It reports whether the value was sent. +// The value will not be sent if the context is closed or the receiver +// is freed. +func (s *Sender[Elem]) Send(ctx context.Context, v Elem) bool { + select { + case <-ctx.Done(): + return false + case s.values <- v: + return true + case <-s.done: + return false + } +} + +// Close tells the receiver that no more values will arrive. +// After Close is called, the Sender may no longer be used. +func (s *Sender[Elem]) Close() { + close(s.values) +} + +// A Receiver receives values from a Sender. +type Receiver[Elem any] struct { + values <-chan Elem + done chan<- struct{} +} + +// Next returns the next value from the channel. The bool result indicates +// whether the value is valid. +func (r *Receiver[Elem]) Next(ctx context.Context) (v Elem, ok bool) { + select { + case <-ctx.Done(): + case v, ok = <-r.values: + } + return v, ok +} + +// finalize is a finalizer for the receiver. +func (r *Receiver[Elem]) finalize() { + close(r.done) +} diff --git a/test/typeparam/chansimp.dir/main.go b/test/typeparam/chansimp.dir/main.go new file mode 100644 index 0000000000..ca27167598 --- /dev/null +++ b/test/typeparam/chansimp.dir/main.go @@ -0,0 +1,189 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "a" + "context" + "fmt" + "runtime" + "sort" + "sync" + "time" +) + +func TestReadAll() { + c := make(chan int) + go func() { + c <- 4 + c <- 2 + c <- 5 + close(c) + }() + got := a.ReadAll(context.Background(), c) + want := []int{4, 2, 5} + if !a.SliceEqual(got, want) { + panic(fmt.Sprintf("ReadAll returned %v, want %v", got, want)) + } +} + +func TestMerge() { + c1 := make(chan int) + c2 := make(chan int) + go func() { + c1 <- 1 + c1 <- 3 + c1 <- 5 + close(c1) + }() + go func() { + c2 <- 2 + c2 <- 4 + c2 <- 6 + close(c2) + }() + ctx := context.Background() + got := a.ReadAll(ctx, a.Merge(ctx, c1, c2)) + sort.Ints(got) + want := []int{1, 2, 3, 4, 5, 6} + if !a.SliceEqual(got, want) { + panic(fmt.Sprintf("Merge returned %v, want %v", got, want)) + } +} + +func TestFilter() { + c := make(chan int) + go func() { + c <- 1 + c <- 2 + c <- 3 + close(c) + }() + even := func(i int) bool { return i%2 == 0 } + ctx := context.Background() + got := a.ReadAll(ctx, a.Filter(ctx, c, even)) + want := []int{2} + if !a.SliceEqual(got, want) { + panic(fmt.Sprintf("Filter returned %v, want %v", got, want)) + } +} + +func TestSink() { + c := a.Sink[int](context.Background()) + after := time.NewTimer(time.Minute) + defer after.Stop() + send := func(v int) { + select { + case c <- v: + case <-after.C: + panic("timed out sending to Sink") + } + } + send(1) + send(2) + send(3) + close(c) +} + +func TestExclusive() { + val := 0 + ex := a.MakeExclusive(&val) + + var wg sync.WaitGroup + f := func() { + defer wg.Done() + for i := 0; i < 10; i++ { + p := ex.Acquire() + (*p)++ + ex.Release(p) + } + } + + wg.Add(2) + go f() + go f() + + wg.Wait() + if val != 20 { + panic(fmt.Sprintf("after Acquire/Release loop got %d, want 20", val)) + } +} + +func TestExclusiveTry() { + s := "" + ex := a.MakeExclusive(&s) + p, ok := ex.TryAcquire() + if !ok { + panic("TryAcquire failed") + } + *p = "a" + + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + _, ok := ex.TryAcquire() + if ok { + panic(fmt.Sprintf("TryAcquire succeeded unexpectedly")) + } + }() + wg.Wait() + + ex.Release(p) + + p, ok = ex.TryAcquire() + if !ok { + panic(fmt.Sprintf("TryAcquire failed")) + } +} + +func TestRanger() { + s, r := a.Ranger[int]() + + ctx := context.Background() + go func() { + // Receive one value then exit. + v, ok := r.Next(ctx) + if !ok { + panic(fmt.Sprintf("did not receive any values")) + } else if v != 1 { + panic(fmt.Sprintf("received %d, want 1", v)) + } + }() + + c1 := make(chan bool) + c2 := make(chan bool) + go func() { + defer close(c2) + if !s.Send(ctx, 1) { + panic(fmt.Sprintf("Send failed unexpectedly")) + } + close(c1) + if s.Send(ctx, 2) { + panic(fmt.Sprintf("Send succeeded unexpectedly")) + } + }() + + <-c1 + + // Force a garbage collection to try to get the finalizers to run. + runtime.GC() + + select { + case <-c2: + case <-time.After(time.Minute): + panic("Ranger Send should have failed, but timed out") + } +} + +func main() { + TestReadAll() + TestMerge() + TestFilter() + TestSink() + TestExclusive() + TestExclusiveTry() + TestRanger() +} diff --git a/test/typeparam/chansimp.go b/test/typeparam/chansimp.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/chansimp.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From 5b1120fac7e234af44c09ec0db1982aa2c7b7357 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 11 May 2021 14:14:30 -0700 Subject: [PATCH 0121/2500] [dev.typeparams] cmd/compile: fix handling of Nname field in (*subster).tstruct. We want to keep the Nname references for external function references in tstruct (not remove them, as is currently happening). We only change the Nname reference (translate it) when it appears in subst.vars[]. New export/import test sliceimp.go which includes some of these external function references. Change-Id: Ie3d73bd989a16082f0cebfb566e0a7faeda55e60 Reviewed-on: https://go-review.googlesource.com/c/go/+/321735 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 26 ++-- test/typeparam/sliceimp.dir/a.go | 141 +++++++++++++++++ test/typeparam/sliceimp.dir/main.go | 179 ++++++++++++++++++++++ test/typeparam/sliceimp.go | 7 + 4 files changed, 343 insertions(+), 10 deletions(-) create mode 100644 test/typeparam/sliceimp.dir/a.go create mode 100644 test/typeparam/sliceimp.dir/main.go create mode 100644 test/typeparam/sliceimp.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 7a7c05280d..1626ab9dd3 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -565,10 +565,10 @@ func (subst *subster) list(l []ir.Node) []ir.Node { } // tstruct substitutes type params in types of the fields of a structure type. For -// each field, if Nname is set, tstruct also translates the Nname using -// subst.vars, if Nname is in subst.vars. To always force the creation of a new -// (top-level) struct, regardless of whether anything changed with the types or -// names of the struct's fields, set force to true. +// each field, tstruct copies the Nname, and translates it if Nname is in +// subst.vars. To always force the creation of a new (top-level) struct, +// regardless of whether anything changed with the types or names of the struct's +// fields, set force to true. func (subst *subster) tstruct(t *types.Type, force bool) *types.Type { if t.NumFields() == 0 { if t.HasTParam() { @@ -597,15 +597,21 @@ func (subst *subster) tstruct(t *types.Type, force bool) *types.Type { // the type param, not the instantiated type). newfields[i] = types.NewField(f.Pos, f.Sym, t2) if f.Nname != nil { - // f.Nname may not be in subst.vars[] if this is - // a function name or a function instantiation type - // that we are translating v := subst.vars[f.Nname.(*ir.Name)] - // Be careful not to put a nil var into Nname, - // since Nname is an interface, so it would be a - // non-nil interface. if v != nil { + // This is the case where we are + // translating the type of the function we + // are substituting, so its dcls are in + // the subst.vars table, and we want to + // change to reference the new dcl. newfields[i].Nname = v + } else { + // This is the case where we are + // translating the type of a function + // reference inside the function we are + // substituting, so we leave the Nname + // value as is. + newfields[i].Nname = f.Nname } } } diff --git a/test/typeparam/sliceimp.dir/a.go b/test/typeparam/sliceimp.dir/a.go new file mode 100644 index 0000000000..2b58d1c29e --- /dev/null +++ b/test/typeparam/sliceimp.dir/a.go @@ -0,0 +1,141 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type Ordered interface { + type int, int8, int16, int32, int64, + uint, uint8, uint16, uint32, uint64, uintptr, + float32, float64, + string +} + +// Max returns the maximum of two values of some ordered type. +func Max[T Ordered](a, b T) T { + if a > b { + return a + } + return b +} + +// Min returns the minimum of two values of some ordered type. +func Min[T Ordered](a, b T) T { + if a < b { + return a + } + return b +} + +// Equal reports whether two slices are equal: the same length and all +// elements equal. All floating point NaNs are considered equal. +func Equal[Elem comparable](s1, s2 []Elem) bool { + if len(s1) != len(s2) { + return false + } + for i, v1 := range s1 { + v2 := s2[i] + if v1 != v2 { + isNaN := func(f Elem) bool { return f != f } + if !isNaN(v1) || !isNaN(v2) { + return false + } + } + } + return true +} + +// EqualFn reports whether two slices are equal using a comparision +// function on each element. +func EqualFn[Elem any](s1, s2 []Elem, eq func(Elem, Elem) bool) bool { + if len(s1) != len(s2) { + return false + } + for i, v1 := range s1 { + v2 := s2[i] + if !eq(v1, v2) { + return false + } + } + return true +} + +// Map turns a []Elem1 to a []Elem2 using a mapping function. +func Map[Elem1, Elem2 any](s []Elem1, f func(Elem1) Elem2) []Elem2 { + r := make([]Elem2, len(s)) + for i, v := range s { + r[i] = f(v) + } + return r +} + +// Reduce reduces a []Elem1 to a single value of type Elem2 using +// a reduction function. +func Reduce[Elem1, Elem2 any](s []Elem1, initializer Elem2, f func(Elem2, Elem1) Elem2) Elem2 { + r := initializer + for _, v := range s { + r = f(r, v) + } + return r +} + +// Filter filters values from a slice using a filter function. +func Filter[Elem any](s []Elem, f func(Elem) bool) []Elem { + var r []Elem + for _, v := range s { + if f(v) { + r = append(r, v) + } + } + return r +} + +// Max returns the maximum element in a slice of some ordered type. +// If the slice is empty it returns the zero value of the element type. +func SliceMax[Elem Ordered](s []Elem) Elem { + if len(s) == 0 { + var zero Elem + return zero + } + return Reduce(s[1:], s[0], Max[Elem]) +} + +// Min returns the minimum element in a slice of some ordered type. +// If the slice is empty it returns the zero value of the element type. +func SliceMin[Elem Ordered](s []Elem) Elem { + if len(s) == 0 { + var zero Elem + return zero + } + return Reduce(s[1:], s[0], Min[Elem]) +} + +// Append adds values to the end of a slice, returning a new slice. +// This is like the predeclared append function; it's an example +// of how to write it using generics. We used to write code like +// this before append was added to the language, but we had to write +// a separate copy for each type. +func Append[T any](s []T, t ...T) []T { + lens := len(s) + tot := lens + len(t) + if tot <= cap(s) { + s = s[:tot] + } else { + news := make([]T, tot, tot + tot/2) + Copy(news, s) + s = news + } + Copy(s[lens:tot], t) + return s +} + +// Copy copies values from t to s, stopping when either slice is full, +// returning the number of values copied. This is like the predeclared +// copy function; it's an example of how to write it using generics. +func Copy[T any](s, t []T) int { + i := 0 + for ; i < len(s) && i < len(t); i++ { + s[i] = t[i] + } + return i +} diff --git a/test/typeparam/sliceimp.dir/main.go b/test/typeparam/sliceimp.dir/main.go new file mode 100644 index 0000000000..0a8e756b26 --- /dev/null +++ b/test/typeparam/sliceimp.dir/main.go @@ -0,0 +1,179 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "a" + "fmt" + "math" + "strings" +) + +type Integer interface { + type int, int8, int16, int32, int64, + uint, uint8, uint16, uint32, uint64, uintptr +} + +func TestEqual() { + s1 := []int{1, 2, 3} + if !a.Equal(s1, s1) { + panic(fmt.Sprintf("a.Equal(%v, %v) = false, want true", s1, s1)) + } + s2 := []int{1, 2, 3} + if !a.Equal(s1, s2) { + panic(fmt.Sprintf("a.Equal(%v, %v) = false, want true", s1, s2)) + } + s2 = append(s2, 4) + if a.Equal(s1, s2) { + panic(fmt.Sprintf("a.Equal(%v, %v) = true, want false", s1, s2)) + } + + s3 := []float64{1, 2, math.NaN()} + if !a.Equal(s3, s3) { + panic(fmt.Sprintf("a.Equal(%v, %v) = false, want true", s3, s3)) + } + + if a.Equal(s1, nil) { + panic(fmt.Sprintf("a.Equal(%v, nil) = true, want false", s1)) + } + if a.Equal(nil, s1) { + panic(fmt.Sprintf("a.Equal(nil, %v) = true, want false", s1)) + } + if !a.Equal(s1[:0], nil) { + panic(fmt.Sprintf("a.Equal(%v, nil = false, want true", s1[:0])) + } +} + +func offByOne[Elem Integer](a, b Elem) bool { + return a == b + 1 || a == b - 1 +} + +func TestEqualFn() { + s1 := []int{1, 2, 3} + s2 := []int{2, 3, 4} + if a.EqualFn(s1, s1, offByOne[int]) { + panic(fmt.Sprintf("a.EqualFn(%v, %v, offByOne) = true, want false", s1, s1)) + } + if !a.EqualFn(s1, s2, offByOne[int]) { + panic(fmt.Sprintf("a.EqualFn(%v, %v, offByOne) = false, want true", s1, s2)) + } + + if !a.EqualFn(s1[:0], nil, offByOne[int]) { + panic(fmt.Sprintf("a.EqualFn(%v, nil, offByOne) = false, want true", s1[:0])) + } + + s3 := []string{"a", "b", "c"} + s4 := []string{"A", "B", "C"} + if !a.EqualFn(s3, s4, strings.EqualFold) { + panic(fmt.Sprintf("a.EqualFn(%v, %v, strings.EqualFold) = false, want true", s3, s4)) + } +} + +func TestMap() { + s1 := []int{1, 2, 3} + s2 := a.Map(s1, func(i int) float64 { return float64(i) * 2.5 }) + if want := []float64{2.5, 5, 7.5}; !a.Equal(s2, want) { + panic(fmt.Sprintf("a.Map(%v, ...) = %v, want %v", s1, s2, want)) + } + + s3 := []string{"Hello", "World"} + s4 := a.Map(s3, strings.ToLower) + if want := []string{"hello", "world"}; !a.Equal(s4, want) { + panic(fmt.Sprintf("a.Map(%v, strings.ToLower) = %v, want %v", s3, s4, want)) + } + + s5 := a.Map(nil, func(i int) int { return i }) + if len(s5) != 0 { + panic(fmt.Sprintf("a.Map(nil, identity) = %v, want empty slice", s5)) + } +} + +func TestReduce() { + s1 := []int{1, 2, 3} + r := a.Reduce(s1, 0, func(f float64, i int) float64 { return float64(i) * 2.5 + f }) + if want := 15.0; r != want { + panic(fmt.Sprintf("a.Reduce(%v, 0, ...) = %v, want %v", s1, r, want)) + } + + if got := a.Reduce(nil, 0, func(i, j int) int { return i + j}); got != 0 { + panic(fmt.Sprintf("a.Reduce(nil, 0, add) = %v, want 0", got)) + } +} + +func TestFilter() { + s1 := []int{1, 2, 3} + s2 := a.Filter(s1, func(i int) bool { return i%2 == 0 }) + if want := []int{2}; !a.Equal(s2, want) { + panic(fmt.Sprintf("a.Filter(%v, even) = %v, want %v", s1, s2, want)) + } + + if s3 := a.Filter(s1[:0], func(i int) bool { return true }); len(s3) > 0 { + panic(fmt.Sprintf("a.Filter(%v, identity) = %v, want empty slice", s1[:0], s3)) + } +} + +func TestMax() { + s1 := []int{1, 2, 3, -5} + if got, want := a.SliceMax(s1), 3; got != want { + panic(fmt.Sprintf("a.Max(%v) = %d, want %d", s1, got, want)) + } + + s2 := []string{"aaa", "a", "aa", "aaaa"} + if got, want := a.SliceMax(s2), "aaaa"; got != want { + panic(fmt.Sprintf("a.Max(%v) = %q, want %q", s2, got, want)) + } + + if got, want := a.SliceMax(s2[:0]), ""; got != want { + panic(fmt.Sprintf("a.Max(%v) = %q, want %q", s2[:0], got, want)) + } +} + +func TestMin() { + s1 := []int{1, 2, 3, -5} + if got, want := a.SliceMin(s1), -5; got != want { + panic(fmt.Sprintf("a.Min(%v) = %d, want %d", s1, got, want)) + } + + s2 := []string{"aaa", "a", "aa", "aaaa"} + if got, want := a.SliceMin(s2), "a"; got != want { + panic(fmt.Sprintf("a.Min(%v) = %q, want %q", s2, got, want)) + } + + if got, want := a.SliceMin(s2[:0]), ""; got != want { + panic(fmt.Sprintf("a.Min(%v) = %q, want %q", s2[:0], got, want)) + } +} + +func TestAppend() { + s := []int{1, 2, 3} + s = a.Append(s, 4, 5, 6) + want := []int{1, 2, 3, 4, 5, 6} + if !a.Equal(s, want) { + panic(fmt.Sprintf("after a.Append got %v, want %v", s, want)) + } +} + +func TestCopy() { + s1 := []int{1, 2, 3} + s2 := []int{4, 5} + if got := a.Copy(s1, s2); got != 2 { + panic(fmt.Sprintf("a.Copy returned %d, want 2", got)) + } + want := []int{4, 5, 3} + if !a.Equal(s1, want) { + panic(fmt.Sprintf("after a.Copy got %v, want %v", s1, want)) + } +} +func main() { + TestEqual() + TestEqualFn() + TestMap() + TestReduce() + TestFilter() + TestMax() + TestMin() + TestAppend() + TestCopy() +} diff --git a/test/typeparam/sliceimp.go b/test/typeparam/sliceimp.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/sliceimp.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From b18b2d372e263dda8862c1eafef739403ba4521d Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Fri, 21 May 2021 20:09:55 -0700 Subject: [PATCH 0122/2500] [dev.typeparams] cmd/compile: fix case where we were copying a raw Node Replace the raw Node copy with the creation of a new node, and the copying of the needed flags and fields. Change-Id: I636bf228ba28c0d5dc25f8366d82379d86ecd731 Reviewed-on: https://go-review.googlesource.com/c/go/+/322189 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky Trust: Dan Scales --- src/cmd/compile/internal/inline/inl.go | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index a6829e9835..bd453e40a5 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -1153,17 +1153,21 @@ func (subst *inlsubst) fields(oldt *types.Type) []*types.Field { // clovar creates a new ONAME node for a local variable or param of a closure // inside a function being inlined. func (subst *inlsubst) clovar(n *ir.Name) *ir.Name { - // TODO(danscales): want to get rid of this shallow copy, with code like the - // following, but it is hard to copy all the necessary flags in a maintainable way. - // m := ir.NewNameAt(n.Pos(), n.Sym()) - // m.Class = n.Class - // m.SetType(n.Type()) - // m.SetTypecheck(1) - //if n.IsClosureVar() { - // m.SetIsClosureVar(true) - //} - m := &ir.Name{} - *m = *n + m := ir.NewNameAt(n.Pos(), n.Sym()) + m.Class = n.Class + m.SetType(n.Type()) + m.SetTypecheck(1) + if n.IsClosureVar() { + m.SetIsClosureVar(true) + } + if n.Addrtaken() { + m.SetAddrtaken(true) + } + if n.Used() { + m.SetUsed(true) + } + m.Defn = n.Defn + m.Curfn = subst.newclofn switch defn := n.Defn.(type) { -- GitLab From ae26b451136a20cb29ac171b1b0dee6ccd06e6eb Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 13 May 2021 12:40:21 -0400 Subject: [PATCH 0123/2500] [dev.typeparams] cmd/compile/abi-internal.md: specify ARM64 register-based ABI The ABI is similar to the AMD64 ABI, just uses different registers and stack layout. The stack layout is compatible with the current stack-based ABI0. To be implemented in Go 1.18. Change-Id: If9c5e664574947f959d3427e3bed769e05d2d673 Reviewed-on: https://go-review.googlesource.com/c/go/+/319829 Trust: Cherry Mui Reviewed-by: Than McIntosh --- src/cmd/compile/abi-internal.md | 122 ++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/src/cmd/compile/abi-internal.md b/src/cmd/compile/abi-internal.md index 1ae3c2538f..7aed7efe97 100644 --- a/src/cmd/compile/abi-internal.md +++ b/src/cmd/compile/abi-internal.md @@ -505,6 +505,128 @@ control bits specified by the ELF AMD64 ABI. The x87 floating-point control word is not used by Go on amd64. +### arm64 architecture + +The arm64 architecture uses R0 – R15 for integer arguments and results. + +It uses F0 – F15 for floating-point arguments and results. + +*Rationale*: 16 integer registers and 16 floating-point registers are +more than enough for passing arguments and results for practically all +functions (see Appendix). While there are more registers available, +using more registers provides little benefit. Additionally, it will add +overhead on code paths where the number of arguments are not statically +known (e.g. reflect call), and will consume more stack space when there +is only limited stack space available to fit in the nosplit limit. + +Registers R16 and R17 are permanent scratch registers. They are also +used as scratch registers by the linker (Go linker and external +linker) in trampolines. + +Register R18 is reserved and never used. It is reserved for the OS +on some platforms (e.g. macOS). + +Registers R19 – R25 are permanent scratch registers. In addition, +R27 is a permanent scratch register used by the assembler when +expanding instructions. + +Floating-point registers F16 – F31 are also permanent scratch +registers. + +Special-purpose registers are as follows: + +| Register | Call meaning | Return meaning | Body meaning | +| --- | --- | --- | --- | +| RSP | Stack pointer | Same | Same | +| R30 | Link register | Same | Scratch (non-leaf functions) | +| R29 | Frame pointer | Same | Same | +| R28 | Current goroutine | Same | Same | +| R27 | Scratch | Scratch | Scratch | +| R26 | Closure context pointer | Scratch | Scratch | +| R18 | Reserved (not used) | Same | Same | +| ZR | Zero value | Same | Same | + +*Rationale*: These register meanings are compatible with Go’s +stack-based calling convention. + +*Rationale*: The link register, R30, holds the function return +address at the function entry. For functions that have frames +(including most non-leaf functions), R30 is saved to stack in the +function prologue and restored in the epilogue. Within the function +body, R30 can be used as a scratch register. + +*Implementation note*: Registers with fixed meaning at calls but not +in function bodies must be initialized by "injected" calls such as +signal-based panics. + +#### Stack layout + +The stack pointer, RSP, grows down and is always aligned to 16 bytes. + +*Rationale*: The arm64 architecture requires the stack pointer to be +16-byte aligned. + +A function's stack frame, after the frame is created, is laid out as +follows: + + +------------------------------+ + | ... locals ... | + | ... outgoing arguments ... | + | return PC | ← RSP points to + | frame pointer on entry | + +------------------------------+ ↓ lower addresses + +The "return PC" is loaded to the link register, R30, as part of the +arm64 `CALL` operation. + +On entry, a function subtracts from RSP to open its stack frame, and +saves the values of R30 and R29 at the bottom of the frame. +Specifically, R30 is saved at 0(RSP) and R29 is saved at -8(RSP), +after RSP is updated. + +A leaf function that does not require any stack space may omit the +saved R30 and R29. + +The Go ABI's use of R29 as a frame pointer register is compatible with +arm64 architecture requirement so that Go can inter-operate with platform +debuggers and profilers. + +This stack layout is used by both register-based (ABIInternal) and +stack-based (ABI0) calling conventions. + +#### Flags + +The arithmetic status flags (NZCV) are treated like scratch registers +and not preserved across calls. +All other bits in PSTATE are system flags and are not modified by Go. + +The floating-point status register (FPSR) is treated like scratch +registers and not preserved across calls. + +At calls, the floating-point control register (FPCR) bits are always +set as follows: + +| Flag | Bit | Value | Meaning | +| --- | --- | --- | --- | +| DN | 25 | 0 | Propagate NaN operands | +| FZ | 24 | 0 | Do not flush to zero | +| RC | 23/22 | 0 (RN) | Round to nearest, choose even if tied | +| IDE | 15 | 0 | Denormal operations trap disabled | +| IXE | 12 | 0 | Inexact trap disabled | +| UFE | 11 | 0 | Underflow trap disabled | +| OFE | 10 | 0 | Overflow trap disabled | +| DZE | 9 | 0 | Divide-by-zero trap disabled | +| IOE | 8 | 0 | Invalid operations trap disabled | +| NEP | 2 | 0 | Scalar operations do not affect higher elements in vector registers | +| AH | 1 | 0 | No alternate handling of de-normal inputs | +| FIZ | 0 | 0 | Do not zero de-normals | + +*Rationale*: Having a fixed FPCR control configuration allows Go +functions to use floating-point and vector (SIMD) operations without +modifying or saving the FPCR. +Functions are allowed to modify it between calls (as long as they +restore it), but as of this writing Go code never does. + ## Future directions ### Spill path improvements -- GitLab From e0844acfc8baa57541a8efef723937c2733e0c99 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 21 May 2021 18:13:04 -0400 Subject: [PATCH 0124/2500] [dev.typeparams] runtime/pprof: replace funcPC with internal/abi.FuncPCABIInternal All funcPC references are ABIInternal functions. Replace with the intrinsics. Change-Id: I2266bb6d2b713eb63b6a09846e9f9c423cab6e9b Reviewed-on: https://go-review.googlesource.com/c/go/+/322349 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/runtime/pprof/pprof.go | 3 ++- src/runtime/pprof/pprof_test.go | 3 ++- src/runtime/pprof/proto.go | 8 ++------ src/runtime/pprof/proto_test.go | 9 +++++---- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/runtime/pprof/pprof.go b/src/runtime/pprof/pprof.go index 99eda10f1c..000abf935c 100644 --- a/src/runtime/pprof/pprof.go +++ b/src/runtime/pprof/pprof.go @@ -76,6 +76,7 @@ import ( "bufio" "bytes" "fmt" + "internal/abi" "io" "runtime" "sort" @@ -289,7 +290,7 @@ func (p *Profile) Add(value interface{}, skip int) { stk = stk[:n] if len(stk) == 0 { // The value for skip is too large, and there's no stack trace to record. - stk = []uintptr{funcPC(lostProfileEvent)} + stk = []uintptr{abi.FuncPCABIInternal(lostProfileEvent)} } p.mu.Lock() diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go index 7cbb4fc7ae..cfcf379d1f 100644 --- a/src/runtime/pprof/pprof_test.go +++ b/src/runtime/pprof/pprof_test.go @@ -11,6 +11,7 @@ import ( "bytes" "context" "fmt" + "internal/abi" "internal/profile" "internal/testenv" "io" @@ -116,7 +117,7 @@ func containsInlinedCall(f interface{}, maxBytes int) bool { // findInlinedCall returns the PC of an inlined function call within // the function body for the function f if any. func findInlinedCall(f interface{}, maxBytes int) (pc uint64, found bool) { - fFunc := runtime.FuncForPC(uintptr(funcPC(f))) + fFunc := runtime.FuncForPC(uintptr(abi.FuncPCABIInternal(f))) if fFunc == nil || fFunc.Entry() == 0 { panic("failed to locate function entry") } diff --git a/src/runtime/pprof/proto.go b/src/runtime/pprof/proto.go index bdb4454b6e..6862513956 100644 --- a/src/runtime/pprof/proto.go +++ b/src/runtime/pprof/proto.go @@ -8,6 +8,7 @@ import ( "bytes" "compress/gzip" "fmt" + "internal/abi" "io" "os" "runtime" @@ -21,11 +22,6 @@ import ( // (The name shows up in the pprof graphs.) func lostProfileEvent() { lostProfileEvent() } -// funcPC returns the PC for the func value f. -func funcPC(f interface{}) uintptr { - return *(*[2]*uintptr)(unsafe.Pointer(&f))[1] -} - // A profileBuilder writes a profile incrementally from a // stream of profile samples delivered by the runtime. type profileBuilder struct { @@ -325,7 +321,7 @@ func (b *profileBuilder) addCPUData(data []uint64, tags []unsafe.Pointer) error // gentraceback guarantees that PCs in the // stack can be unconditionally decremented and // still be valid, so we must do the same. - uint64(funcPC(lostProfileEvent) + 1), + uint64(abi.FuncPCABIInternal(lostProfileEvent) + 1), } } b.m.lookup(stk, tag).count += int64(count) diff --git a/src/runtime/pprof/proto_test.go b/src/runtime/pprof/proto_test.go index 5eb1aab140..d052b9fa42 100644 --- a/src/runtime/pprof/proto_test.go +++ b/src/runtime/pprof/proto_test.go @@ -8,6 +8,7 @@ import ( "bytes" "encoding/json" "fmt" + "internal/abi" "internal/profile" "internal/testenv" "os" @@ -97,11 +98,11 @@ func testPCs(t *testing.T) (addr1, addr2 uint64, map1, map2 *profile.Mapping) { map2 = mprof.Mapping[1] map2.BuildID, _ = elfBuildID(map2.File) case "js": - addr1 = uint64(funcPC(f1)) - addr2 = uint64(funcPC(f2)) + addr1 = uint64(abi.FuncPCABIInternal(f1)) + addr2 = uint64(abi.FuncPCABIInternal(f2)) default: - addr1 = uint64(funcPC(f1)) - addr2 = uint64(funcPC(f2)) + addr1 = uint64(abi.FuncPCABIInternal(f1)) + addr2 = uint64(abi.FuncPCABIInternal(f2)) // Fake mapping - HasFunctions will be true because two PCs from Go // will be fully symbolized. fake := &profile.Mapping{ID: 1, HasFunctions: true} -- GitLab From f6427426787b292ec28cfd826615e3ae9a66b54a Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 21 May 2021 18:28:25 -0400 Subject: [PATCH 0125/2500] [dev.typeparams] reflect: use internal/abi.FuncPCABI0 to take address of assembly functions makeFuncStub and methodValueCall on AMD64 are marked as ABIInternal, so Go code can get their (unwrapped) addresses (using open-coded funcPC). Ues internal/abi.FuncPCABI0 instead, and un-mark the functions. Change-Id: Id28b6101ec7e55bc5a357d4236482cec70cd7e5d Reviewed-on: https://go-review.googlesource.com/c/go/+/322350 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/reflect/asm_amd64.s | 8 ++------ src/reflect/makefunc.go | 12 ++---------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/src/reflect/asm_amd64.s b/src/reflect/asm_amd64.s index 86d3f4e4bf..7491c772ac 100644 --- a/src/reflect/asm_amd64.s +++ b/src/reflect/asm_amd64.s @@ -24,10 +24,8 @@ // See the comment on the declaration of makeFuncStub in makefunc.go // for more details. // No arg size here; runtime pulls arg map out of the func value. -// makeFuncStub must be ABIInternal because it is placed directly -// in function values. // This frame contains two locals. See the comment above LOCAL_RETVALID. -TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$312 +TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$312 NO_LOCAL_POINTERS // NO_LOCAL_POINTERS is a lie. The stack map for the two locals in this // frame is specially handled in the runtime. See the comment above LOCAL_RETVALID. @@ -55,10 +53,8 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$312 // See the comment on the declaration of methodValueCall in makefunc.go // for more details. // No arg size here; runtime pulls arg map out of the func value. -// methodValueCall must be ABIInternal because it is placed directly -// in function values. // This frame contains two locals. See the comment above LOCAL_RETVALID. -TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$312 +TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$312 NO_LOCAL_POINTERS // NO_LOCAL_POINTERS is a lie. The stack map for the two locals in this // frame is specially handled in the runtime. See the comment above LOCAL_RETVALID. diff --git a/src/reflect/makefunc.go b/src/reflect/makefunc.go index d53e68a359..588be8bcc1 100644 --- a/src/reflect/makefunc.go +++ b/src/reflect/makefunc.go @@ -52,11 +52,7 @@ func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value { t := typ.common() ftyp := (*funcType)(unsafe.Pointer(t)) - // Indirect Go func value (dummy) to obtain - // actual code address. (A Go func value is a pointer - // to a C function pointer. https://golang.org/s/go11func.) - dummy := makeFuncStub - code := **(**uintptr)(unsafe.Pointer(&dummy)) + code := abi.FuncPCABI0(makeFuncStub) // makeFuncImpl contains a stack map for use by the runtime _, _, abi := funcLayout(ftyp, nil) @@ -111,11 +107,7 @@ func makeMethodValue(op string, v Value) Value { // v.Type returns the actual type of the method value. ftyp := (*funcType)(unsafe.Pointer(v.Type().(*rtype))) - // Indirect Go func value (dummy) to obtain - // actual code address. (A Go func value is a pointer - // to a C function pointer. https://golang.org/s/go11func.) - dummy := methodValueCall - code := **(**uintptr)(unsafe.Pointer(&dummy)) + code := abi.FuncPCABI0(methodValueCall) // methodValue contains a stack map for use by the runtime _, _, abi := funcLayout(ftyp, nil) -- GitLab From dcaf785add683fdda9bd0e53395c17c55779a8ac Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 20 May 2021 18:03:49 -0400 Subject: [PATCH 0126/2500] [dev.typeparams] internal/buildcfg: enable defer/go wrapping everywhere For register ABI, we wrap deferred/go'd function with arguments or results in an argumentless closure, so the runtime can call the function without knowing how to marshal the arguments, or reserving frame for arguments and results. The wrapping mechanism works everywhere, regardless of whether the register ABI is used. And wrapping will simplify the compiler and runtime's implementation for defer and go calls. For example, the compiler will not need to marshal arguments for defer/go calls, the opendefer metadata will not need to contain argument information, and _defer record will be fixed-sized. Enable wrapping everywhere. Change-Id: I2032ba87249ceb686310dc640fb00696669ae912 Reviewed-on: https://go-review.googlesource.com/c/go/+/321958 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: Michael Knyszek TryBot-Result: Go Bot --- src/internal/buildcfg/exp.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go index 417d87cf4a..11cd05f2ed 100644 --- a/src/internal/buildcfg/exp.go +++ b/src/internal/buildcfg/exp.go @@ -29,7 +29,7 @@ var experimentBaseline = goexperiment.Flags{ RegabiWrappers: regabiSupported, RegabiG: regabiSupported, RegabiReflect: regabiSupported, - RegabiDefer: regabiSupported, + RegabiDefer: true, RegabiArgs: regabiSupported, } @@ -103,7 +103,6 @@ func parseExperiments() goexperiment.Flags { flags.RegabiWrappers = false flags.RegabiG = false flags.RegabiReflect = false - flags.RegabiDefer = false flags.RegabiArgs = false } // Check regabi dependencies. -- GitLab From 4c50721cda74abbf7732638f39a23dfbf6271a48 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 11 May 2021 19:29:10 -0700 Subject: [PATCH 0127/2500] [dev.typeparams] cmd/compile: Fix handling of Name nodes during stenciling The name substitution for stenciling was incorrectly handling non-local names. Made changes to explicitly built the vars[] name substitution map based on the local variables (similar to what inlining substitution does). Then, we we are stenciling a name node, we do NOT make a copy of the name node if it is not in vars[], since it is then a reference to an external name. Added new function localvar() to create the new nodes for the local variables and put them in the vars[] map. New test listimp2.go, added missing test calls in list2.go Change-Id: I8946478250c7bf2bd31c3247089bd50cfeeda0fd Reviewed-on: https://go-review.googlesource.com/c/go/+/322190 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 51 ++-- test/typeparam/list2.go | 9 + test/typeparam/listimp2.dir/a.go | 298 ++++++++++++++++++++ test/typeparam/listimp2.dir/main.go | 316 ++++++++++++++++++++++ test/typeparam/listimp2.go | 7 + 5 files changed, 656 insertions(+), 25 deletions(-) create mode 100644 test/typeparam/listimp2.dir/a.go create mode 100644 test/typeparam/listimp2.dir/main.go create mode 100644 test/typeparam/listimp2.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 1626ab9dd3..67580add73 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -289,7 +289,7 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []*type newf.Dcl = make([]*ir.Name, len(gf.Dcl)) for i, n := range gf.Dcl { - newf.Dcl[i] = subst.node(n).(*ir.Name) + newf.Dcl[i] = subst.localvar(n) } // Replace the types in the function signature. @@ -315,9 +315,28 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []*type return newf } -// node is like DeepCopy(), but creates distinct ONAME nodes, and also descends -// into closures. It substitutes type arguments for type parameters in all the new -// nodes. +// localvar creates a new name node for the specified local variable and enters it +// in subst.vars. It substitutes type arguments for type parameters in the type of +// name as needed. +func (subst *subster) localvar(name *ir.Name) *ir.Name { + m := ir.NewNameAt(name.Pos(), name.Sym()) + if name.IsClosureVar() { + m.SetIsClosureVar(true) + } + m.SetType(subst.typ(name.Type())) + m.BuiltinOp = name.BuiltinOp + m.Curfn = subst.newf + m.Class = name.Class + assert(name.Class != ir.PEXTERN && name.Class != ir.PFUNC) + m.Func = name.Func + subst.vars[name] = m + m.SetTypecheck(1) + return m +} + +// node is like DeepCopy(), but substitutes ONAME nodes based on subst.vars, and +// also descends into closures. It substitutes type arguments for type parameters +// in all the new nodes. func (subst *subster) node(n ir.Node) ir.Node { // Use closure to capture all state needed by the ir.EditChildren argument. var edit func(ir.Node) ir.Node @@ -327,28 +346,10 @@ func (subst *subster) node(n ir.Node) ir.Node { return ir.TypeNode(subst.typ(x.Type())) case ir.ONAME: - name := x.(*ir.Name) - if v := subst.vars[name]; v != nil { + if v := subst.vars[x.(*ir.Name)]; v != nil { return v } - m := ir.NewNameAt(name.Pos(), name.Sym()) - if name.IsClosureVar() { - m.SetIsClosureVar(true) - } - t := x.Type() - if t == nil { - assert(name.BuiltinOp != 0) - } else { - newt := subst.typ(t) - m.SetType(newt) - } - m.BuiltinOp = name.BuiltinOp - m.Curfn = subst.newf - m.Class = name.Class - m.Func = name.Func - subst.vars[name] = m - m.SetTypecheck(1) - return m + return x case ir.OLITERAL, ir.ONIL: if x.Sym() != nil { return x @@ -545,7 +546,7 @@ func (subst *subster) node(n ir.Node) ir.Node { func (subst *subster) namelist(l []*ir.Name) []*ir.Name { s := make([]*ir.Name, len(l)) for i, n := range l { - s[i] = subst.node(n).(*ir.Name) + s[i] = subst.localvar(n) if n.Defn != nil { s[i].Defn = subst.node(n.Defn) } diff --git a/test/typeparam/list2.go b/test/typeparam/list2.go index 385193d876..32023cf319 100644 --- a/test/typeparam/list2.go +++ b/test/typeparam/list2.go @@ -597,5 +597,14 @@ func TestTransform() { func main() { TestList() + TestExtending() + TestRemove() + TestIssue4103() + TestIssue6349() + TestMove() + TestZeroList() + TestInsertBeforeUnknownMark() + TestInsertAfterUnknownMark() + TestTransform() } diff --git a/test/typeparam/listimp2.dir/a.go b/test/typeparam/listimp2.dir/a.go new file mode 100644 index 0000000000..76ad669767 --- /dev/null +++ b/test/typeparam/listimp2.dir/a.go @@ -0,0 +1,298 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +import ( + "fmt" +) + +// Element is an element of a linked list. +type Element[T any] struct { + // Next and previous pointers in the doubly-linked list of elements. + // To simplify the implementation, internally a list l is implemented + // as a ring, such that &l.root is both the next element of the last + // list element (l.Back()) and the previous element of the first list + // element (l.Front()). + next, prev *Element[T] + + // The list to which this element belongs. + list *List[T] + + // The value stored with this element. + Value T +} + +// Next returns the next list element or nil. +func (e *Element[T]) Next() *Element[T] { + if p := e.next; e.list != nil && p != &e.list.root { + return p + } + return nil +} + +// Prev returns the previous list element or nil. +func (e *Element[T]) Prev() *Element[T] { + if p := e.prev; e.list != nil && p != &e.list.root { + return p + } + return nil +} + +// List represents a doubly linked list. +// The zero value for List is an empty list ready to use. +type List[T any] struct { + root Element[T] // sentinel list element, only &root, root.prev, and root.next are used + len int // current list length excluding (this) sentinel element +} + +// Init initializes or clears list l. +func (l *List[T]) Init() *List[T] { + l.root.next = &l.root + l.root.prev = &l.root + l.len = 0 + return l +} + +// New returns an initialized list. +func New[T any]() *List[T] { return new(List[T]).Init() } + +// Len returns the number of elements of list l. +// The complexity is O(1). +func (l *List[_]) Len() int { return l.len } + +// Front returns the first element of list l or nil if the list is empty. +func (l *List[T]) Front() *Element[T] { + if l.len == 0 { + return nil + } + return l.root.next +} + +// Back returns the last element of list l or nil if the list is empty. +func (l *List[T]) Back() *Element[T] { + if l.len == 0 { + return nil + } + return l.root.prev +} + +// lazyInit lazily initializes a zero List value. +func (l *List[_]) lazyInit() { + if l.root.next == nil { + l.Init() + } +} + +// insert inserts e after at, increments l.len, and returns e. +func (l *List[T]) insert(e, at *Element[T]) *Element[T] { + e.prev = at + e.next = at.next + e.prev.next = e + e.next.prev = e + e.list = l + l.len++ + return e +} + +// insertValue is a convenience wrapper for insert(&Element[T]{Value: v}, at). +func (l *List[T]) insertValue(v T, at *Element[T]) *Element[T] { + return l.insert(&Element[T]{Value: v}, at) +} + +// remove removes e from its list, decrements l.len, and returns e. +func (l *List[T]) remove(e *Element[T]) *Element[T] { + e.prev.next = e.next + e.next.prev = e.prev + e.next = nil // avoid memory leaks + e.prev = nil // avoid memory leaks + e.list = nil + l.len-- + return e +} + +// move moves e to next to at and returns e. +func (l *List[T]) move(e, at *Element[T]) *Element[T] { + if e == at { + return e + } + e.prev.next = e.next + e.next.prev = e.prev + + e.prev = at + e.next = at.next + e.prev.next = e + e.next.prev = e + + return e +} + +// Remove removes e from l if e is an element of list l. +// It returns the element value e.Value. +// The element must not be nil. +func (l *List[T]) Remove(e *Element[T]) T { + if e.list == l { + // if e.list == l, l must have been initialized when e was inserted + // in l or l == nil (e is a zero Element) and l.remove will crash + l.remove(e) + } + return e.Value +} + +// PushFront inserts a new element e with value v at the front of list l and returns e. +func (l *List[T]) PushFront(v T) *Element[T] { + l.lazyInit() + return l.insertValue(v, &l.root) +} + +// PushBack inserts a new element e with value v at the back of list l and returns e. +func (l *List[T]) PushBack(v T) *Element[T] { + l.lazyInit() + return l.insertValue(v, l.root.prev) +} + +// InsertBefore inserts a new element e with value v immediately before mark and returns e. +// If mark is not an element of l, the list is not modified. +// The mark must not be nil. +func (l *List[T]) InsertBefore(v T, mark *Element[T]) *Element[T] { + if mark.list != l { + return nil + } + // see comment in List.Remove about initialization of l + return l.insertValue(v, mark.prev) +} + +// InsertAfter inserts a new element e with value v immediately after mark and returns e. +// If mark is not an element of l, the list is not modified. +// The mark must not be nil. +func (l *List[T]) InsertAfter(v T, mark *Element[T]) *Element[T] { + if mark.list != l { + return nil + } + // see comment in List.Remove about initialization of l + return l.insertValue(v, mark) +} + +// MoveToFront moves element e to the front of list l. +// If e is not an element of l, the list is not modified. +// The element must not be nil. +func (l *List[T]) MoveToFront(e *Element[T]) { + if e.list != l || l.root.next == e { + return + } + // see comment in List.Remove about initialization of l + l.move(e, &l.root) +} + +// MoveToBack moves element e to the back of list l. +// If e is not an element of l, the list is not modified. +// The element must not be nil. +func (l *List[T]) MoveToBack(e *Element[T]) { + if e.list != l || l.root.prev == e { + return + } + // see comment in List.Remove about initialization of l + l.move(e, l.root.prev) +} + +// MoveBefore moves element e to its new position before mark. +// If e or mark is not an element of l, or e == mark, the list is not modified. +// The element and mark must not be nil. +func (l *List[T]) MoveBefore(e, mark *Element[T]) { + if e.list != l || e == mark || mark.list != l { + return + } + l.move(e, mark.prev) +} + +// MoveAfter moves element e to its new position after mark. +// If e or mark is not an element of l, or e == mark, the list is not modified. +// The element and mark must not be nil. +func (l *List[T]) MoveAfter(e, mark *Element[T]) { + if e.list != l || e == mark || mark.list != l { + return + } + l.move(e, mark) +} + +// PushBackList inserts a copy of an other list at the back of list l. +// The lists l and other may be the same. They must not be nil. +func (l *List[T]) PushBackList(other *List[T]) { + l.lazyInit() + for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() { + l.insertValue(e.Value, l.root.prev) + } +} + +// PushFrontList inserts a copy of an other list at the front of list l. +// The lists l and other may be the same. They must not be nil. +func (l *List[T]) PushFrontList(other *List[T]) { + l.lazyInit() + for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() { + l.insertValue(e.Value, &l.root) + } +} + +// Transform runs a transform function on a list returning a new list. +func Transform[TElem1, TElem2 any](lst *List[TElem1], f func(TElem1) TElem2) *List[TElem2] { + ret := New[TElem2]() + for p := lst.Front(); p != nil; p = p.Next() { + ret.PushBack(f(p.Value)) + } + return ret +} + +func CheckListLen[T any](l *List[T], len int) bool { + if n := l.Len(); n != len { + panic(fmt.Sprintf("l.Len() = %d, want %d", n, len)) + return false + } + return true +} + +func CheckListPointers[T any](l *List[T], es []*Element[T]) { + root := &l.root + + if !CheckListLen(l, len(es)) { + return + } + + // zero length lists must be the zero value or properly initialized (sentinel circle) + if len(es) == 0 { + if l.root.next != nil && l.root.next != root || l.root.prev != nil && l.root.prev != root { + panic(fmt.Sprintf("l.root.next = %p, l.root.prev = %p; both should both be nil or %p", l.root.next, l.root.prev, root)) + } + return + } + // len(es) > 0 + + // check internal and external prev/next connections + for i, e := range es { + prev := root + Prev := (*Element[T])(nil) + if i > 0 { + prev = es[i-1] + Prev = prev + } + if p := e.prev; p != prev { + panic(fmt.Sprintf("elt[%d](%p).prev = %p, want %p", i, e, p, prev)) + } + if p := e.Prev(); p != Prev { + panic(fmt.Sprintf("elt[%d](%p).Prev() = %p, want %p", i, e, p, Prev)) + } + + next := root + Next := (*Element[T])(nil) + if i < len(es)-1 { + next = es[i+1] + Next = next + } + if n := e.next; n != next { + panic(fmt.Sprintf("elt[%d](%p).next = %p, want %p", i, e, n, next)) + } + if n := e.Next(); n != Next { + panic(fmt.Sprintf("elt[%d](%p).Next() = %p, want %p", i, e, n, Next)) + } + } +} diff --git a/test/typeparam/listimp2.dir/main.go b/test/typeparam/listimp2.dir/main.go new file mode 100644 index 0000000000..0c2c38e399 --- /dev/null +++ b/test/typeparam/listimp2.dir/main.go @@ -0,0 +1,316 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "a" + "fmt" + "strconv" +) + +func TestList() { + l := a.New[string]() + a.CheckListPointers(l, []*(a.Element[string]){}) + + // Single element list + e := l.PushFront("a") + a.CheckListPointers(l, []*(a.Element[string]){e}) + l.MoveToFront(e) + a.CheckListPointers(l, []*(a.Element[string]){e}) + l.MoveToBack(e) + a.CheckListPointers(l, []*(a.Element[string]){e}) + l.Remove(e) + a.CheckListPointers(l, []*(a.Element[string]){}) + + // Bigger list + l2 := a.New[int]() + e2 := l2.PushFront(2) + e1 := l2.PushFront(1) + e3 := l2.PushBack(3) + e4 := l2.PushBack(600) + a.CheckListPointers(l2, []*(a.Element[int]){e1, e2, e3, e4}) + + l2.Remove(e2) + a.CheckListPointers(l2, []*(a.Element[int]){e1, e3, e4}) + + l2.MoveToFront(e3) // move from middle + a.CheckListPointers(l2, []*(a.Element[int]){e3, e1, e4}) + + l2.MoveToFront(e1) + l2.MoveToBack(e3) // move from middle + a.CheckListPointers(l2, []*(a.Element[int]){e1, e4, e3}) + + l2.MoveToFront(e3) // move from back + a.CheckListPointers(l2, []*(a.Element[int]){e3, e1, e4}) + l2.MoveToFront(e3) // should be no-op + a.CheckListPointers(l2, []*(a.Element[int]){e3, e1, e4}) + + l2.MoveToBack(e3) // move from front + a.CheckListPointers(l2, []*(a.Element[int]){e1, e4, e3}) + l2.MoveToBack(e3) // should be no-op + a.CheckListPointers(l2, []*(a.Element[int]){e1, e4, e3}) + + e2 = l2.InsertBefore(2, e1) // insert before front + a.CheckListPointers(l2, []*(a.Element[int]){e2, e1, e4, e3}) + l2.Remove(e2) + e2 = l2.InsertBefore(2, e4) // insert before middle + a.CheckListPointers(l2, []*(a.Element[int]){e1, e2, e4, e3}) + l2.Remove(e2) + e2 = l2.InsertBefore(2, e3) // insert before back + a.CheckListPointers(l2, []*(a.Element[int]){e1, e4, e2, e3}) + l2.Remove(e2) + + e2 = l2.InsertAfter(2, e1) // insert after front + a.CheckListPointers(l2, []*(a.Element[int]){e1, e2, e4, e3}) + l2.Remove(e2) + e2 = l2.InsertAfter(2, e4) // insert after middle + a.CheckListPointers(l2, []*(a.Element[int]){e1, e4, e2, e3}) + l2.Remove(e2) + e2 = l2.InsertAfter(2, e3) // insert after back + a.CheckListPointers(l2, []*(a.Element[int]){e1, e4, e3, e2}) + l2.Remove(e2) + + // Check standard iteration. + sum := 0 + for e := l2.Front(); e != nil; e = e.Next() { + sum += e.Value + } + if sum != 604 { + panic(fmt.Sprintf("sum over l = %d, want 604", sum)) + } + + // Clear all elements by iterating + var next *a.Element[int] + for e := l2.Front(); e != nil; e = next { + next = e.Next() + l2.Remove(e) + } + a.CheckListPointers(l2, []*(a.Element[int]){}) +} + +func checkList[T comparable](l *a.List[T], es []interface{}) { + if !a.CheckListLen(l, len(es)) { + return + } + + i := 0 + for e := l.Front(); e != nil; e = e.Next() { + le := e.Value + // Comparison between a generically-typed variable le and an interface. + if le != es[i] { + panic(fmt.Sprintf("elt[%d].Value = %v, want %v", i, le, es[i])) + } + i++ + } +} + +func TestExtending() { + l1 := a.New[int]() + l2 := a.New[int]() + + l1.PushBack(1) + l1.PushBack(2) + l1.PushBack(3) + + l2.PushBack(4) + l2.PushBack(5) + + l3 := a.New[int]() + l3.PushBackList(l1) + checkList(l3, []interface{}{1, 2, 3}) + l3.PushBackList(l2) + checkList(l3, []interface{}{1, 2, 3, 4, 5}) + + l3 = a.New[int]() + l3.PushFrontList(l2) + checkList(l3, []interface{}{4, 5}) + l3.PushFrontList(l1) + checkList(l3, []interface{}{1, 2, 3, 4, 5}) + + checkList(l1, []interface{}{1, 2, 3}) + checkList(l2, []interface{}{4, 5}) + + l3 = a.New[int]() + l3.PushBackList(l1) + checkList(l3, []interface{}{1, 2, 3}) + l3.PushBackList(l3) + checkList(l3, []interface{}{1, 2, 3, 1, 2, 3}) + + l3 = a.New[int]() + l3.PushFrontList(l1) + checkList(l3, []interface{}{1, 2, 3}) + l3.PushFrontList(l3) + checkList(l3, []interface{}{1, 2, 3, 1, 2, 3}) + + l3 = a.New[int]() + l1.PushBackList(l3) + checkList(l1, []interface{}{1, 2, 3}) + l1.PushFrontList(l3) + checkList(l1, []interface{}{1, 2, 3}) +} + +func TestRemove() { + l := a.New[int]() + e1 := l.PushBack(1) + e2 := l.PushBack(2) + a.CheckListPointers(l, []*(a.Element[int]){e1, e2}) + e := l.Front() + l.Remove(e) + a.CheckListPointers(l, []*(a.Element[int]){e2}) + l.Remove(e) + a.CheckListPointers(l, []*(a.Element[int]){e2}) +} + +func TestIssue4103() { + l1 := a.New[int]() + l1.PushBack(1) + l1.PushBack(2) + + l2 := a.New[int]() + l2.PushBack(3) + l2.PushBack(4) + + e := l1.Front() + l2.Remove(e) // l2 should not change because e is not an element of l2 + if n := l2.Len(); n != 2 { + panic(fmt.Sprintf("l2.Len() = %d, want 2", n)) + } + + l1.InsertBefore(8, e) + if n := l1.Len(); n != 3 { + panic(fmt.Sprintf("l1.Len() = %d, want 3", n)) + } +} + +func TestIssue6349() { + l := a.New[int]() + l.PushBack(1) + l.PushBack(2) + + e := l.Front() + l.Remove(e) + if e.Value != 1 { + panic(fmt.Sprintf("e.value = %d, want 1", e.Value)) + } + if e.Next() != nil { + panic(fmt.Sprintf("e.Next() != nil")) + } + if e.Prev() != nil { + panic(fmt.Sprintf("e.Prev() != nil")) + } +} + +func TestMove() { + l := a.New[int]() + e1 := l.PushBack(1) + e2 := l.PushBack(2) + e3 := l.PushBack(3) + e4 := l.PushBack(4) + + l.MoveAfter(e3, e3) + a.CheckListPointers(l, []*(a.Element[int]){e1, e2, e3, e4}) + l.MoveBefore(e2, e2) + a.CheckListPointers(l, []*(a.Element[int]){e1, e2, e3, e4}) + + l.MoveAfter(e3, e2) + a.CheckListPointers(l, []*(a.Element[int]){e1, e2, e3, e4}) + l.MoveBefore(e2, e3) + a.CheckListPointers(l, []*(a.Element[int]){e1, e2, e3, e4}) + + l.MoveBefore(e2, e4) + a.CheckListPointers(l, []*(a.Element[int]){e1, e3, e2, e4}) + e2, e3 = e3, e2 + + l.MoveBefore(e4, e1) + a.CheckListPointers(l, []*(a.Element[int]){e4, e1, e2, e3}) + e1, e2, e3, e4 = e4, e1, e2, e3 + + l.MoveAfter(e4, e1) + a.CheckListPointers(l, []*(a.Element[int]){e1, e4, e2, e3}) + e2, e3, e4 = e4, e2, e3 + + l.MoveAfter(e2, e3) + a.CheckListPointers(l, []*(a.Element[int]){e1, e3, e2, e4}) + e2, e3 = e3, e2 +} + +// Test PushFront, PushBack, PushFrontList, PushBackList with uninitialized a.List +func TestZeroList() { + var l1 = new(a.List[int]) + l1.PushFront(1) + checkList(l1, []interface{}{1}) + + var l2 = new(a.List[int]) + l2.PushBack(1) + checkList(l2, []interface{}{1}) + + var l3 = new(a.List[int]) + l3.PushFrontList(l1) + checkList(l3, []interface{}{1}) + + var l4 = new(a.List[int]) + l4.PushBackList(l2) + checkList(l4, []interface{}{1}) +} + +// Test that a list l is not modified when calling InsertBefore with a mark that is not an element of l. +func TestInsertBeforeUnknownMark() { + var l a.List[int] + l.PushBack(1) + l.PushBack(2) + l.PushBack(3) + l.InsertBefore(1, new(a.Element[int])) + checkList(&l, []interface{}{1, 2, 3}) +} + +// Test that a list l is not modified when calling InsertAfter with a mark that is not an element of l. +func TestInsertAfterUnknownMark() { + var l a.List[int] + l.PushBack(1) + l.PushBack(2) + l.PushBack(3) + l.InsertAfter(1, new(a.Element[int])) + checkList(&l, []interface{}{1, 2, 3}) +} + +// Test that a list l is not modified when calling MoveAfter or MoveBefore with a mark that is not an element of l. +func TestMoveUnknownMark() { + var l1 a.List[int] + e1 := l1.PushBack(1) + + var l2 a.List[int] + e2 := l2.PushBack(2) + + l1.MoveAfter(e1, e2) + checkList(&l1, []interface{}{1}) + checkList(&l2, []interface{}{2}) + + l1.MoveBefore(e1, e2) + checkList(&l1, []interface{}{1}) + checkList(&l2, []interface{}{2}) +} + +// Test the Transform function. +func TestTransform() { + l1 := a.New[int]() + l1.PushBack(1) + l1.PushBack(2) + l2 := a.Transform(l1, strconv.Itoa) + checkList(l2, []interface{}{"1", "2"}) +} + + +func main() { + TestList() + TestExtending() + TestRemove() + TestIssue4103() + TestIssue6349() + TestMove() + TestZeroList() + TestInsertBeforeUnknownMark() + TestInsertAfterUnknownMark() + TestTransform() +} diff --git a/test/typeparam/listimp2.go b/test/typeparam/listimp2.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/listimp2.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From d48f6d9f6f1ee7099ad129552507903e191ad589 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Fri, 14 May 2021 16:35:04 -0700 Subject: [PATCH 0128/2500] [dev.typeparams] Don't check typecheck(3) on transform, so no need to export/import it We have a value typecheck(3) that indicates that a node in a generic function still needs transformation (via the functions in transform.go). But it is not very desirable to export/import the value of typecheck(3). So, I changed the stenciling code to just try to transform all relevant node types during node copy. Almost all tranform functions were already idempotent. I only had to add an extra if check before calling transformAssign() in the OAS case. We still use the typecheck(3) in noder to determine when higher-nodes have to delay transformation because one or more of their args are delaying transformation. Added new test mapsimp.go that required these tranformations after import. As an additional change, export/import of OINDEX requires exporting the type using w.exoticType() rather than w.typ(), in order to handle generic functions. Since generic functions can have pre-transform operations, the index operation can have a tuple type (multiple return from a map lookup). Added printing of imported function bodies in -W=3 debug mode. Change-Id: I220e2428dc5f2741e91db146f075eb5b6045f451 Reviewed-on: https://go-review.googlesource.com/c/go/+/322191 Trust: Dan Scales Run-TryBot: Dan Scales Reviewed-by: Keith Randall TryBot-Result: Go Bot --- src/cmd/compile/internal/noder/stencil.go | 64 ++++--- src/cmd/compile/internal/typecheck/iexport.go | 2 +- src/cmd/compile/internal/typecheck/iimport.go | 6 +- test/typeparam/mapsimp.dir/a.go | 108 ++++++++++++ test/typeparam/mapsimp.dir/main.go | 156 ++++++++++++++++++ test/typeparam/mapsimp.go | 7 + 6 files changed, 308 insertions(+), 35 deletions(-) create mode 100644 test/typeparam/mapsimp.dir/a.go create mode 100644 test/typeparam/mapsimp.dir/main.go create mode 100644 test/typeparam/mapsimp.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 67580add73..e273a80b20 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -374,45 +374,43 @@ func (subst *subster) node(n ir.Node) ir.Node { } ir.EditChildren(m, edit) - if x.Typecheck() == 3 { - // These are nodes whose transforms were delayed until - // their instantiated type was known. - m.SetTypecheck(1) - if typecheck.IsCmp(x.Op()) { - transformCompare(m.(*ir.BinaryExpr)) - } else { - switch x.Op() { - case ir.OSLICE, ir.OSLICE3: - transformSlice(m.(*ir.SliceExpr)) - - case ir.OADD: - m = transformAdd(m.(*ir.BinaryExpr)) - - case ir.OINDEX: - transformIndex(m.(*ir.IndexExpr)) - - case ir.OAS2: - as2 := m.(*ir.AssignListStmt) - transformAssign(as2, as2.Lhs, as2.Rhs) - - case ir.OAS: - as := m.(*ir.AssignStmt) + m.SetTypecheck(1) + if typecheck.IsCmp(x.Op()) { + transformCompare(m.(*ir.BinaryExpr)) + } else { + switch x.Op() { + case ir.OSLICE, ir.OSLICE3: + transformSlice(m.(*ir.SliceExpr)) + + case ir.OADD: + m = transformAdd(m.(*ir.BinaryExpr)) + + case ir.OINDEX: + transformIndex(m.(*ir.IndexExpr)) + + case ir.OAS2: + as2 := m.(*ir.AssignListStmt) + transformAssign(as2, as2.Lhs, as2.Rhs) + + case ir.OAS: + as := m.(*ir.AssignStmt) + if as.Y != nil { + // transformAssign doesn't handle the case + // of zeroing assignment of a dcl (rhs[0] is nil). lhs, rhs := []ir.Node{as.X}, []ir.Node{as.Y} transformAssign(as, lhs, rhs) + } - case ir.OASOP: - as := m.(*ir.AssignOpStmt) - transformCheckAssign(as, as.X) + case ir.OASOP: + as := m.(*ir.AssignOpStmt) + transformCheckAssign(as, as.X) - case ir.ORETURN: - transformReturn(m.(*ir.ReturnStmt)) + case ir.ORETURN: + transformReturn(m.(*ir.ReturnStmt)) - case ir.OSEND: - transformSend(m.(*ir.SendStmt)) + case ir.OSEND: + transformSend(m.(*ir.SendStmt)) - default: - base.Fatalf("Unexpected node with Typecheck() == 3") - } } } diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index d956ada3c5..292bb2c409 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -1735,7 +1735,7 @@ func (w *exportWriter) expr(n ir.Node) { w.expr(n.X) w.expr(n.Index) if go117ExportTypes { - w.typ(n.Type()) + w.exoticType(n.Type()) if n.Op() == ir.OINDEXMAP { w.bool(n.Assigned) } diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 966e865630..d5b549483d 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1025,6 +1025,10 @@ func (r *importReader) funcBody(fn *ir.Func) { fn.Inl.Body = body r.curfn = outerfn + if base.Flag.W >= 3 { + fmt.Printf("Imported for %v", fn) + ir.DumpList("", fn.Inl.Body) + } } func (r *importReader) readNames(fn *ir.Func) []*ir.Name { @@ -1349,7 +1353,7 @@ func (r *importReader) node() ir.Node { n := ir.NewIndexExpr(r.pos(), r.expr(), r.expr()) if go117ExportTypes { n.SetOp(op) - n.SetType(r.typ()) + n.SetType(r.exoticType()) if op == ir.OINDEXMAP { n.Assigned = r.bool() } diff --git a/test/typeparam/mapsimp.dir/a.go b/test/typeparam/mapsimp.dir/a.go new file mode 100644 index 0000000000..696e2a5680 --- /dev/null +++ b/test/typeparam/mapsimp.dir/a.go @@ -0,0 +1,108 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +// SliceEqual reports whether two slices are equal: the same length and all +// elements equal. All floating point NaNs are considered equal. +func SliceEqual[Elem comparable](s1, s2 []Elem) bool { + if len(s1) != len(s2) { + return false + } + for i, v1 := range s1 { + v2 := s2[i] + if v1 != v2 { + isNaN := func(f Elem) bool { return f != f } + if !isNaN(v1) || !isNaN(v2) { + return false + } + } + } + return true +} + +// Keys returns the keys of the map m. +// The keys will be an indeterminate order. +func Keys[K comparable, V any](m map[K]V) []K { + r := make([]K, 0, len(m)) + for k := range m { + r = append(r, k) + } + return r +} + +// Values returns the values of the map m. +// The values will be in an indeterminate order. +func Values[K comparable, V any](m map[K]V) []V { + r := make([]V, 0, len(m)) + for _, v := range m { + r = append(r, v) + } + return r +} + +// Equal reports whether two maps contain the same key/value pairs. +// Values are compared using ==. +func Equal[K, V comparable](m1, m2 map[K]V) bool { + if len(m1) != len(m2) { + return false + } + for k, v1 := range m1 { + if v2, ok := m2[k]; !ok || v1 != v2 { + return false + } + } + return true +} + +// Copy returns a copy of m. +func Copy[K comparable, V any](m map[K]V) map[K]V { + r := make(map[K]V, len(m)) + for k, v := range m { + r[k] = v + } + return r +} + +// Add adds all key/value pairs in m2 to m1. Keys in m2 that are already +// present in m1 will be overwritten with the value in m2. +func Add[K comparable, V any](m1, m2 map[K]V) { + for k, v := range m2 { + m1[k] = v + } +} + +// Sub removes all keys in m2 from m1. Keys in m2 that are not present +// in m1 are ignored. The values in m2 are ignored. +func Sub[K comparable, V any](m1, m2 map[K]V) { + for k := range m2 { + delete(m1, k) + } +} + +// Intersect removes all keys from m1 that are not present in m2. +// Keys in m2 that are not in m1 are ignored. The values in m2 are ignored. +func Intersect[K comparable, V any](m1, m2 map[K]V) { + for k := range m1 { + if _, ok := m2[k]; !ok { + delete(m1, k) + } + } +} + +// Filter deletes any key/value pairs from m for which f returns false. +func Filter[K comparable, V any](m map[K]V, f func(K, V) bool) { + for k, v := range m { + if !f(k, v) { + delete(m, k) + } + } +} + +// TransformValues applies f to each value in m. The keys remain unchanged. +func TransformValues[K comparable, V any](m map[K]V, f func(V) V) { + for k, v := range m { + m[k] = f(v) + } +} diff --git a/test/typeparam/mapsimp.dir/main.go b/test/typeparam/mapsimp.dir/main.go new file mode 100644 index 0000000000..873660e4cd --- /dev/null +++ b/test/typeparam/mapsimp.dir/main.go @@ -0,0 +1,156 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "a" + "fmt" + "math" + "sort" +) + +var m1 = map[int]int{1: 2, 2: 4, 4: 8, 8: 16} +var m2 = map[int]string{1: "2", 2: "4", 4: "8", 8: "16"} + +func TestKeys() { + want := []int{1, 2, 4, 8} + + got1 := a.Keys(m1) + sort.Ints(got1) + if !a.SliceEqual(got1, want) { + panic(fmt.Sprintf("a.Keys(%v) = %v, want %v", m1, got1, want)) + } + + got2 := a.Keys(m2) + sort.Ints(got2) + if !a.SliceEqual(got2, want) { + panic(fmt.Sprintf("a.Keys(%v) = %v, want %v", m2, got2, want)) + } +} + +func TestValues() { + got1 := a.Values(m1) + want1 := []int{2, 4, 8, 16} + sort.Ints(got1) + if !a.SliceEqual(got1, want1) { + panic(fmt.Sprintf("a.Values(%v) = %v, want %v", m1, got1, want1)) + } + + got2 := a.Values(m2) + want2 := []string{"16", "2", "4", "8"} + sort.Strings(got2) + if !a.SliceEqual(got2, want2) { + panic(fmt.Sprintf("a.Values(%v) = %v, want %v", m2, got2, want2)) + } +} + +func TestEqual() { + if !a.Equal(m1, m1) { + panic(fmt.Sprintf("a.Equal(%v, %v) = false, want true", m1, m1)) + } + if a.Equal(m1, nil) { + panic(fmt.Sprintf("a.Equal(%v, nil) = true, want false", m1)) + } + if a.Equal(nil, m1) { + panic(fmt.Sprintf("a.Equal(nil, %v) = true, want false", m1)) + } + if !a.Equal[int, int](nil, nil) { + panic("a.Equal(nil, nil) = false, want true") + } + if ms := map[int]int{1: 2}; a.Equal(m1, ms) { + panic(fmt.Sprintf("a.Equal(%v, %v) = true, want false", m1, ms)) + } + + // Comparing NaN for equality is expected to fail. + mf := map[int]float64{1: 0, 2: math.NaN()} + if a.Equal(mf, mf) { + panic(fmt.Sprintf("a.Equal(%v, %v) = true, want false", mf, mf)) + } +} + +func TestCopy() { + m2 := a.Copy(m1) + if !a.Equal(m1, m2) { + panic(fmt.Sprintf("a.Copy(%v) = %v, want %v", m1, m2, m1)) + } + m2[16] = 32 + if a.Equal(m1, m2) { + panic(fmt.Sprintf("a.Equal(%v, %v) = true, want false", m1, m2)) + } +} + +func TestAdd() { + mc := a.Copy(m1) + a.Add(mc, mc) + if !a.Equal(mc, m1) { + panic(fmt.Sprintf("a.Add(%v, %v) = %v, want %v", m1, m1, mc, m1)) + } + a.Add(mc, map[int]int{16: 32}) + want := map[int]int{1: 2, 2: 4, 4: 8, 8: 16, 16: 32} + if !a.Equal(mc, want) { + panic(fmt.Sprintf("a.Add result = %v, want %v", mc, want)) + } +} + +func TestSub() { + mc := a.Copy(m1) + a.Sub(mc, mc) + if len(mc) > 0 { + panic(fmt.Sprintf("a.Sub(%v, %v) = %v, want empty map", m1, m1, mc)) + } + mc = a.Copy(m1) + a.Sub(mc, map[int]int{1: 0}) + want := map[int]int{2: 4, 4: 8, 8: 16} + if !a.Equal(mc, want) { + panic(fmt.Sprintf("a.Sub result = %v, want %v", mc, want)) + } +} + +func TestIntersect() { + mc := a.Copy(m1) + a.Intersect(mc, mc) + if !a.Equal(mc, m1) { + panic(fmt.Sprintf("a.Intersect(%v, %v) = %v, want %v", m1, m1, mc, m1)) + } + a.Intersect(mc, map[int]int{1: 0, 2: 0}) + want := map[int]int{1: 2, 2: 4} + if !a.Equal(mc, want) { + panic(fmt.Sprintf("a.Intersect result = %v, want %v", mc, want)) + } +} + +func TestFilter() { + mc := a.Copy(m1) + a.Filter(mc, func(int, int) bool { return true }) + if !a.Equal(mc, m1) { + panic(fmt.Sprintf("a.Filter(%v, true) = %v, want %v", m1, mc, m1)) + } + a.Filter(mc, func(k, v int) bool { return k < 3 }) + want := map[int]int{1: 2, 2: 4} + if !a.Equal(mc, want) { + panic(fmt.Sprintf("a.Filter result = %v, want %v", mc, want)) + } +} + +func TestTransformValues() { + mc := a.Copy(m1) + a.TransformValues(mc, func(i int) int { return i / 2 }) + want := map[int]int{1: 1, 2: 2, 4: 4, 8: 8} + if !a.Equal(mc, want) { + panic(fmt.Sprintf("a.TransformValues result = %v, want %v", mc, want)) + } +} + +func main() { + TestKeys() + TestValues() + TestEqual() + TestCopy() + TestAdd() + TestSub() + TestIntersect() + TestFilter() + TestTransformValues() +} diff --git a/test/typeparam/mapsimp.go b/test/typeparam/mapsimp.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/mapsimp.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From 1608577e0503be1739631d60576a07bdf1bbb49e Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 20 May 2021 21:24:36 -0700 Subject: [PATCH 0129/2500] [dev.typeparams] cmd/compile/internal/types2: re-use existing code for Interface.Complete Change-Id: I0fa07e49651aa086c2edbd1162332608c400250f Reviewed-on: https://go-review.googlesource.com/c/go/+/321751 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/interface.go | 47 +++++++++++++-- src/cmd/compile/internal/types2/type.go | 60 +------------------- 2 files changed, 44 insertions(+), 63 deletions(-) diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index bbd25cbd09..21968b34aa 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -6,6 +6,7 @@ package types2 import ( "cmd/compile/internal/syntax" + "fmt" "sort" ) @@ -139,7 +140,13 @@ func (check *Checker) completeInterface(pos syntax.Pos, ityp *Interface) { panic("internal error: incomplete interface") } - if check.conf.Trace { + completeInterface(check, pos, ityp) +} + +func completeInterface(check *Checker, pos syntax.Pos, ityp *Interface) { + assert(ityp.allMethods == nil) + + if check != nil && check.conf.Trace { // Types don't generally have position information. // If we don't have a valid pos provided, try to use // one close enough. @@ -175,6 +182,7 @@ func (check *Checker) completeInterface(pos syntax.Pos, ityp *Interface) { // we can get rid of the mpos map below and simply use the cloned method's // position. + var todo []*Func var seen objset var methods []*Func mpos := make(map[*Func]syntax.Pos) // method specification or method embedding position, for good error messages @@ -184,6 +192,9 @@ func (check *Checker) completeInterface(pos syntax.Pos, ityp *Interface) { methods = append(methods, m) mpos[m] = pos case explicit: + if check == nil { + panic(fmt.Sprintf("%s: duplicate method %s", m.pos, m.name)) + } var err error_ err.errorf(pos, "duplicate method %s", m.name) err.errorf(mpos[other.(*Func)], "other declaration of %s", m.name) @@ -194,6 +205,11 @@ func (check *Checker) completeInterface(pos syntax.Pos, ityp *Interface) { // If we're pre-go1.14 (overlapping embeddings are not permitted), report that // error here as well (even though we could do it eagerly) because it's the same // error message. + if check == nil { + // check method signatures after all locally embedded interfaces are computed + todo = append(todo, m, other.(*Func)) + break + } check.later(func() { if !check.allowVersion(m.pkg, 1, 14) || !check.identical(m.typ, other.Type()) { var err error_ @@ -212,9 +228,15 @@ func (check *Checker) completeInterface(pos syntax.Pos, ityp *Interface) { // collect types allTypes := ityp.types - posList := check.posMap[ityp] + var posList []syntax.Pos + if check != nil { + posList = check.posMap[ityp] + } for i, typ := range ityp.embeddeds { - pos := posList[i] // embedding position + var pos syntax.Pos // embedding position + if posList != nil { + pos = posList[i] + } utyp := under(typ) etyp := asInterface(utyp) if etyp == nil { @@ -225,17 +247,32 @@ func (check *Checker) completeInterface(pos syntax.Pos, ityp *Interface) { } else { format = "%s is not an interface" } - check.errorf(pos, format, typ) + if check != nil { + check.errorf(pos, format, typ) + } else { + panic(fmt.Sprintf("%s: "+format, pos, typ)) + } } continue } - check.completeInterface(pos, etyp) + if etyp.allMethods == nil { + completeInterface(check, pos, etyp) + } for _, m := range etyp.allMethods { addMethod(pos, m, false) // use embedding position pos rather than m.pos } allTypes = intersect(allTypes, etyp.allTypes) } + // process todo's (this only happens if check == nil) + for i := 0; i < len(todo); i += 2 { + m := todo[i] + other := todo[i+1] + if !Identical(m.typ, other.typ) { + panic(fmt.Sprintf("%s: duplicate method %s", m.pos, m.name)) + } + } + if methods != nil { sortMethods(methods) ityp.allMethods = methods diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 55c2f336ce..db955a8509 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -6,7 +6,6 @@ package types2 import ( "cmd/compile/internal/syntax" - "fmt" "sync/atomic" ) @@ -544,64 +543,9 @@ func (t *Interface) isSatisfiedBy(typ Type) bool { // form other types. The interface must not contain duplicate methods or a // panic occurs. Complete returns the receiver. func (t *Interface) Complete() *Interface { - // TODO(gri) consolidate this method with Checker.completeInterface - if t.allMethods != nil { - return t - } - - t.allMethods = markComplete // avoid infinite recursion - - var todo []*Func - var methods []*Func - var seen objset - addMethod := func(m *Func, explicit bool) { - switch other := seen.insert(m); { - case other == nil: - methods = append(methods, m) - case explicit: - panic("duplicate method " + m.name) - default: - // check method signatures after all locally embedded interfaces are computed - todo = append(todo, m, other.(*Func)) - } - } - - for _, m := range t.methods { - addMethod(m, true) - } - - allTypes := t.types - - for _, typ := range t.embeddeds { - utyp := under(typ) - etyp := asInterface(utyp) - if etyp == nil { - if utyp != Typ[Invalid] { - panic(fmt.Sprintf("%s is not an interface", typ)) - } - continue - } - etyp.Complete() - for _, m := range etyp.allMethods { - addMethod(m, false) - } - allTypes = intersect(allTypes, etyp.allTypes) - } - - for i := 0; i < len(todo); i += 2 { - m := todo[i] - other := todo[i+1] - if !Identical(m.typ, other.typ) { - panic("duplicate method " + m.name) - } - } - - if methods != nil { - sortMethods(methods) - t.allMethods = methods + if t.allMethods == nil { + completeInterface(nil, nopos, t) } - t.allTypes = allTypes - return t } -- GitLab From cc7ceea5859beb5569d1a278e389ae7dd7d13f8b Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 21 May 2021 09:46:40 -0700 Subject: [PATCH 0130/2500] [dev.typeparams] cmd/compile/internal/types2: simplify Interface accessors Change-Id: Ia97cf88d94de044d61ce2bd364a858bd608c050a Reviewed-on: https://go-review.googlesource.com/c/go/+/321850 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/type.go | 62 +++++-------------------- 1 file changed, 12 insertions(+), 50 deletions(-) diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index db955a8509..e54f7601be 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -427,79 +427,41 @@ func (t *Interface) EmbeddedType(i int) Type { return t.embeddeds[i] } // NumMethods returns the total number of methods of interface t. // The interface must have been completed. -func (t *Interface) NumMethods() int { t.assertCompleteness(); return len(t.allMethods) } - -func (t *Interface) assertCompleteness() { - if t.allMethods == nil { - panic("interface is incomplete") - } -} +func (t *Interface) NumMethods() int { t.Complete(); return len(t.allMethods) } // Method returns the i'th method of interface t for 0 <= i < t.NumMethods(). // The methods are ordered by their unique Id. // The interface must have been completed. -func (t *Interface) Method(i int) *Func { t.assertCompleteness(); return t.allMethods[i] } +func (t *Interface) Method(i int) *Func { t.Complete(); return t.allMethods[i] } // Empty reports whether t is the empty interface. func (t *Interface) Empty() bool { - if t.allMethods != nil { - // interface is complete - quick test - // A non-nil allTypes may still be empty and represents the bottom type. - return len(t.allMethods) == 0 && t.allTypes == nil - } - return !t.iterate(func(t *Interface) bool { - return len(t.methods) > 0 || t.types != nil - }, nil) + t.Complete() + // A non-nil allTypes may still have length 0 but represents the bottom type. + return len(t.allMethods) == 0 && t.allTypes == nil } // HasTypeList reports whether interface t has a type list, possibly from an embedded type. func (t *Interface) HasTypeList() bool { - if t.allMethods != nil { - // interface is complete - quick test - return t.allTypes != nil - } - - return t.iterate(func(t *Interface) bool { - return t.types != nil - }, nil) + t.Complete() + return t.allTypes != nil } // IsComparable reports whether interface t is or embeds the predeclared interface "comparable". func (t *Interface) IsComparable() bool { - if t.allMethods != nil { - // interface is complete - quick test - _, m := lookupMethod(t.allMethods, nil, "==") - return m != nil - } - - return t.iterate(func(t *Interface) bool { - _, m := lookupMethod(t.methods, nil, "==") - return m != nil - }, nil) + t.Complete() + _, m := lookupMethod(t.allMethods, nil, "==") + return m != nil } // IsConstraint reports t.HasTypeList() || t.IsComparable(). func (t *Interface) IsConstraint() bool { - if t.allMethods != nil { - // interface is complete - quick test - if t.allTypes != nil { - return true - } - _, m := lookupMethod(t.allMethods, nil, "==") - return m != nil - } - - return t.iterate(func(t *Interface) bool { - if t.types != nil { - return true - } - _, m := lookupMethod(t.methods, nil, "==") - return m != nil - }, nil) + return t.HasTypeList() || t.IsComparable() } // iterate calls f with t and then with any embedded interface of t, recursively, until f returns true. // iterate reports whether any call to f returned true. +// TODO(gri) This is now only used by infer.go - see if we can eliminate it. func (t *Interface) iterate(f func(*Interface) bool, seen map[*Interface]bool) bool { if f(t) { return true -- GitLab From 5770d7a63743ddfd0e78877f162cbbf18ffb9c1d Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 20 May 2021 15:13:04 -0700 Subject: [PATCH 0131/2500] [dev.typeparams] cmd/compile/internal/types2: accept embedded interface elements Accept embedded interface elements of the form ~T or A|B and treat them like type lists: for now the elements of a union cannot be interfaces. Also, translate existing style "type"- lists in interfaces into interface elements: "type a, b, c" becomes a union element "~a|~b|~c" which in turn is handled internally like a type list. For now, "~" is still ignored and type lists are mapped to Sum types as before, thus ensuring that all existing tests work as before (with some minor adjustments). Introduced a new Union type to represent union elements. For now they don't make it past interface completion where they are represented as a Sum type. Thus, except for printing (and the respective tests) and substitution for interfaces, the various type switches ignore Union types. In a next step, we'll replace Sum types with union types and then consider the ~ functionality as well. Because union elements are no different from embedded interfaces we don't need a separate Interface.types field anymore. Removed. For #45346. Change-Id: I98ac3286aea9d706e98aee80241d4712ed99af08 Reviewed-on: https://go-review.googlesource.com/c/go/+/321689 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/noder/types.go | 18 +- src/cmd/compile/internal/types2/builtins.go | 2 +- src/cmd/compile/internal/types2/index.go | 2 +- src/cmd/compile/internal/types2/infer.go | 5 +- src/cmd/compile/internal/types2/interface.go | 211 +++++++++--------- src/cmd/compile/internal/types2/predicates.go | 3 + src/cmd/compile/internal/types2/sanitize.go | 8 +- .../compile/internal/types2/sizeof_test.go | 3 +- src/cmd/compile/internal/types2/sizes.go | 2 + src/cmd/compile/internal/types2/subst.go | 16 +- .../internal/types2/testdata/check/decls0.src | 2 +- .../internal/types2/testdata/check/issues.src | 2 +- .../types2/testdata/check/typeinst2.go2 | 6 +- .../types2/testdata/examples/constraints.go2 | 25 +++ .../types2/testdata/fixedbugs/issue39634.go2 | 2 +- .../types2/testdata/fixedbugs/issue39693.go2 | 17 +- .../types2/testdata/fixedbugs/issue39711.go2 | 4 +- .../types2/testdata/fixedbugs/issue39723.go2 | 2 +- .../types2/testdata/fixedbugs/issue39948.go2 | 8 +- src/cmd/compile/internal/types2/type.go | 1 - src/cmd/compile/internal/types2/typestring.go | 21 +- .../internal/types2/typestring_test.go | 4 +- src/cmd/compile/internal/types2/unify.go | 3 + src/cmd/compile/internal/types2/union.go | 105 +++++++++ 24 files changed, 319 insertions(+), 153 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/examples/constraints.go2 create mode 100644 src/cmd/compile/internal/types2/union.go diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index 7fdad29e16..16d664f538 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -187,14 +187,18 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { for i := range embeddeds { // TODO(mdempsky): Get embedding position. e := typ.EmbeddedType(i) - if t := types2.AsInterface(e); t != nil && t.IsComparable() { - // Ignore predefined type 'comparable', since it - // doesn't resolve and it doesn't have any - // relevant methods. - continue + if t := types2.AsInterface(e); t != nil { + if t.IsComparable() { + // Ignore predefined type 'comparable', since it + // doesn't resolve and it doesn't have any + // relevant methods. + continue + } + embeddeds[j] = types.NewField(src.NoXPos, nil, g.typ1(e)) + j++ } - embeddeds[j] = types.NewField(src.NoXPos, nil, g.typ1(e)) - j++ + // Ignore embedded non-interface types - they correspond + // to type lists which we currently don't handle here. } embeddeds = embeddeds[:j] diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index b9e178dd57..94fb506d80 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -769,7 +769,7 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { tpar := NewTypeName(nopos, nil /* = Universe pkg */, "", nil) ptyp := check.NewTypeParam(tpar, 0, &emptyInterface) // assigns type to tpar as a side-effect tsum := NewSum(rtypes) - ptyp.bound = &Interface{types: tsum, allMethods: markComplete, allTypes: tsum} + ptyp.bound = &Interface{allMethods: markComplete, allTypes: tsum} return ptyp } diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index c94017a8fb..33e79aac3e 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -126,7 +126,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo case *TypeParam: check.errorf(x, "type of %s contains a type parameter - cannot index (implementation restriction)", x) case *instance: - panic("unimplemented") + unimplemented() } if e == nil || telem != nil && !Identical(e, telem) { return false diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index f37d7f6477..d8865784a5 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -320,6 +320,9 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { // Thus, we only need to look at the input and result parameters. return w.isParameterized(t.params) || w.isParameterized(t.results) + case *Union: + unimplemented() + case *Interface: if t.allMethods != nil { // interface is complete - quick test @@ -337,7 +340,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { return true } } - return w.isParameterizedList(unpack(t.types)) + return w.isParameterizedList(t.embeddeds) }, nil) case *Map: diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index 21968b34aa..d590066ad6 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -11,72 +11,84 @@ import ( ) func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType, def *Named) { - var tname *syntax.Name // most recent "type" name - var types []syntax.Expr + var tlist []syntax.Expr // types collected from all type lists + var tname *syntax.Name // most recent "type" name + for _, f := range iface.MethodList { - if f.Name != nil { - // We have a method with name f.Name, or a type - // of a type list (f.Name.Value == "type"). - name := f.Name.Value - if name == "_" { - if check.conf.CompilerErrorMessages { - check.error(f.Name, "methods must have a unique non-blank name") - } else { - check.error(f.Name, "invalid method name _") - } - continue // ignore + if f.Name == nil { + // We have an embedded type; possibly a union of types. + ityp.embeddeds = append(ityp.embeddeds, parseUnion(check, flattenUnion(nil, f.Type))) + check.posMap[ityp] = append(check.posMap[ityp], f.Type.Pos()) + continue + } + // f.Name != nil + + // We have a method with name f.Name, or a type of a type list (f.Name.Value == "type"). + name := f.Name.Value + if name == "_" { + if check.conf.CompilerErrorMessages { + check.error(f.Name, "methods must have a unique non-blank name") + } else { + check.error(f.Name, "invalid method name _") } + continue // ignore + } - if name == "type" { - // Always collect all type list entries, even from - // different type lists, under the assumption that - // the author intended to include all types. - types = append(types, f.Type) - if tname != nil && tname != f.Name { - check.error(f.Name, "cannot have multiple type lists in an interface") - } - tname = f.Name - continue + if name == "type" { + // For now, collect all type list entries as if it + // were a single union, where each union element is + // of the form ~T. + // TODO(gri) remove once we disallow type lists + op := new(syntax.Operation) + // We should also set the position (but there is no setter); + // we don't care because this code will eventually go away. + op.Op = syntax.Tilde + op.X = f.Type + tlist = append(tlist, op) + if tname != nil && tname != f.Name { + check.error(f.Name, "cannot have multiple type lists in an interface") } + tname = f.Name + continue + } - typ := check.typ(f.Type) - sig, _ := typ.(*Signature) - if sig == nil { - if typ != Typ[Invalid] { - check.errorf(f.Type, invalidAST+"%s is not a method signature", typ) - } - continue // ignore + typ := check.typ(f.Type) + sig, _ := typ.(*Signature) + if sig == nil { + if typ != Typ[Invalid] { + check.errorf(f.Type, invalidAST+"%s is not a method signature", typ) } + continue // ignore + } - // Always type-check method type parameters but complain if they are not enabled. - // (This extra check is needed here because interface method signatures don't have - // a receiver specification.) - if sig.tparams != nil && !acceptMethodTypeParams { - check.error(f.Type, "methods cannot have type parameters") - } + // Always type-check method type parameters but complain if they are not enabled. + // (This extra check is needed here because interface method signatures don't have + // a receiver specification.) + if sig.tparams != nil && !acceptMethodTypeParams { + check.error(f.Type, "methods cannot have type parameters") + } - // use named receiver type if available (for better error messages) - var recvTyp Type = ityp - if def != nil { - recvTyp = def - } - sig.recv = NewVar(f.Name.Pos(), check.pkg, "", recvTyp) - - m := NewFunc(f.Name.Pos(), check.pkg, name, sig) - check.recordDef(f.Name, m) - ityp.methods = append(ityp.methods, m) - } else { - // We have an embedded type. completeInterface will - // eventually verify that we have an interface. - ityp.embeddeds = append(ityp.embeddeds, check.typ(f.Type)) - check.posMap[ityp] = append(check.posMap[ityp], f.Type.Pos()) + // use named receiver type if available (for better error messages) + var recvTyp Type = ityp + if def != nil { + recvTyp = def } + sig.recv = NewVar(f.Name.Pos(), check.pkg, "", recvTyp) + + m := NewFunc(f.Name.Pos(), check.pkg, name, sig) + check.recordDef(f.Name, m) + ityp.methods = append(ityp.methods, m) } - // type constraints - ityp.types = NewSum(check.collectTypeConstraints(iface.Pos(), types)) + // If we saw a type list, add it like an embedded union. + if tlist != nil { + ityp.embeddeds = append(ityp.embeddeds, parseUnion(check, tlist)) + // Types T in a type list are added as ~T expressions but we don't + // have the position of the '~'. Use the first type position instead. + check.posMap[ityp] = append(check.posMap[ityp], tlist[0].(*syntax.Operation).X.Pos()) + } - if len(ityp.methods) == 0 && ityp.types == nil && len(ityp.embeddeds) == 0 { + if len(ityp.methods) == 0 && len(ityp.embeddeds) == 0 { // empty interface ityp.allMethods = markComplete return @@ -89,32 +101,12 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType check.later(func() { check.completeInterface(iface.Pos(), ityp) }) } -func (check *Checker) collectTypeConstraints(pos syntax.Pos, types []syntax.Expr) []Type { - list := make([]Type, 0, len(types)) // assume all types are correct - for _, texpr := range types { - if texpr == nil { - check.error(pos, invalidAST+"missing type constraint") - continue - } - list = append(list, check.varType(texpr)) +func flattenUnion(list []syntax.Expr, x syntax.Expr) []syntax.Expr { + if o, _ := x.(*syntax.Operation); o != nil && o.Op == syntax.Or { + list = flattenUnion(list, o.X) + x = o.Y } - - // Ensure that each type is only present once in the type list. Types may be - // interfaces, which may not be complete yet. It's ok to do this check at the - // end because it's not a requirement for correctness of the code. - // Note: This is a quadratic algorithm, but type lists tend to be short. - check.later(func() { - for i, t := range list { - if t := asInterface(t); t != nil { - check.completeInterface(types[i].Pos(), t) - } - if includes(list[:i], t) { - check.softErrorf(types[i], "duplicate type %s in type list", t) - } - } - }) - - return list + return append(list, x) } // includes reports whether typ is in list @@ -143,6 +135,7 @@ func (check *Checker) completeInterface(pos syntax.Pos, ityp *Interface) { completeInterface(check, pos, ityp) } +// completeInterface may be called with check == nil. func completeInterface(check *Checker, pos syntax.Pos, ityp *Interface) { assert(ityp.allMethods == nil) @@ -195,6 +188,7 @@ func completeInterface(check *Checker, pos syntax.Pos, ityp *Interface) { if check == nil { panic(fmt.Sprintf("%s: duplicate method %s", m.pos, m.name)) } + // check != nil var err error_ err.errorf(pos, "duplicate method %s", m.name) err.errorf(mpos[other.(*Func)], "other declaration of %s", m.name) @@ -210,6 +204,7 @@ func completeInterface(check *Checker, pos syntax.Pos, ityp *Interface) { todo = append(todo, m, other.(*Func)) break } + // check != nil check.later(func() { if !check.allowVersion(m.pkg, 1, 14) || !check.identical(m.typ, other.Type()) { var err error_ @@ -225,9 +220,8 @@ func completeInterface(check *Checker, pos syntax.Pos, ityp *Interface) { addMethod(m.pos, m, true) } - // collect types - allTypes := ityp.types - + // collect embedded elements + var allTypes Type var posList []syntax.Pos if check != nil { posList = check.posMap[ityp] @@ -237,31 +231,36 @@ func completeInterface(check *Checker, pos syntax.Pos, ityp *Interface) { if posList != nil { pos = posList[i] } - utyp := under(typ) - etyp := asInterface(utyp) - if etyp == nil { - if utyp != Typ[Invalid] { - var format string - if _, ok := utyp.(*TypeParam); ok { - format = "%s is a type parameter, not an interface" - } else { - format = "%s is not an interface" - } - if check != nil { - check.errorf(pos, format, typ) - } else { - panic(fmt.Sprintf("%s: "+format, pos, typ)) - } + var types Type + switch t := under(typ).(type) { + case *Interface: + if t.allMethods == nil { + completeInterface(check, pos, t) } - continue - } - if etyp.allMethods == nil { - completeInterface(check, pos, etyp) - } - for _, m := range etyp.allMethods { - addMethod(pos, m, false) // use embedding position pos rather than m.pos + for _, m := range t.allMethods { + addMethod(pos, m, false) // use embedding position pos rather than m.pos + } + types = t.allTypes + case *Union: + types = NewSum(t.terms) + // TODO(gri) don't ignore tilde information + case *TypeParam: + if check != nil && !check.allowVersion(check.pkg, 1, 18) { + check.errorf(pos, "%s is a type parameter, not an interface", typ) + continue + } + types = t + default: + if t == Typ[Invalid] { + continue + } + if check != nil && !check.allowVersion(check.pkg, 1, 18) { + check.errorf(pos, "%s is not an interface", typ) + continue + } + types = t } - allTypes = intersect(allTypes, etyp.allTypes) + allTypes = intersect(allTypes, types) } // process todo's (this only happens if check == nil) @@ -281,7 +280,7 @@ func completeInterface(check *Checker, pos syntax.Pos, ityp *Interface) { } // intersect computes the intersection of the types x and y. -// Note: A incomming nil type stands for the top type. A top +// Note: An incomming nil type stands for the top type. A top // type result is returned as nil. func intersect(x, y Type) (r Type) { defer func() { diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index ae186a0b5d..ab0a457276 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -284,6 +284,9 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { return true } + case *Union: + unimplemented() + case *Interface: // Two interface types are identical if they have the same set of methods with // the same names and identical function types. Lower-case method names from diff --git a/src/cmd/compile/internal/types2/sanitize.go b/src/cmd/compile/internal/types2/sanitize.go index 64a2dedc7d..9fad52e224 100644 --- a/src/cmd/compile/internal/types2/sanitize.go +++ b/src/cmd/compile/internal/types2/sanitize.go @@ -109,11 +109,11 @@ func (s sanitizer) typ(typ Type) Type { case *Sum: s.typeList(t.types) + case *Union: + s.typeList(t.terms) + case *Interface: s.funcList(t.methods) - if types := s.typ(t.types); types != t.types { - t.types = types - } s.typeList(t.embeddeds) s.funcList(t.allMethods) if allTypes := s.typ(t.allTypes); allTypes != t.allTypes { @@ -153,7 +153,7 @@ func (s sanitizer) typ(typ Type) Type { s[t] = typ default: - panic("unimplemented") + unimplemented() } return typ diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go index 236feb0404..552f3488cd 100644 --- a/src/cmd/compile/internal/types2/sizeof_test.go +++ b/src/cmd/compile/internal/types2/sizeof_test.go @@ -28,7 +28,8 @@ func TestSizeof(t *testing.T) { {Tuple{}, 12, 24}, {Signature{}, 44, 88}, {Sum{}, 12, 24}, - {Interface{}, 60, 120}, + {Union{}, 24, 48}, + {Interface{}, 52, 104}, {Map{}, 16, 32}, {Chan{}, 12, 24}, {Named{}, 68, 136}, diff --git a/src/cmd/compile/internal/types2/sizes.go b/src/cmd/compile/internal/types2/sizes.go index aa0fbf40fc..c6b807cd06 100644 --- a/src/cmd/compile/internal/types2/sizes.go +++ b/src/cmd/compile/internal/types2/sizes.go @@ -150,6 +150,8 @@ func (s *StdSizes) Sizeof(T Type) int64 { return offsets[n-1] + s.Sizeof(t.fields[n-1].typ) case *Sum: panic("Sizeof unimplemented for type sum") + case *Union: + unimplemented() case *Interface: return s.WordSize * 2 } diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index c8e428c183..04a3527d6d 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -299,15 +299,19 @@ func (subst *subster) typ(typ Type) Type { return NewSum(types) } + case *Union: + terms, copied := subst.typeList(t.terms) + if copied { + // TODO(gri) Do we need to remove duplicates that may have + // crept in after substitution? It may not matter. + return newUnion(terms, t.tilde) + } + case *Interface: methods, mcopied := subst.funcList(t.methods) - types := t.types - if t.types != nil { - types = subst.typ(t.types) - } embeddeds, ecopied := subst.typeList(t.embeddeds) - if mcopied || types != t.types || ecopied { - iface := &Interface{methods: methods, types: types, embeddeds: embeddeds} + if mcopied || ecopied { + iface := &Interface{methods: methods, embeddeds: embeddeds} if subst.check == nil { panic("internal error: cannot instantiate interfaces yet") } diff --git a/src/cmd/compile/internal/types2/testdata/check/decls0.src b/src/cmd/compile/internal/types2/testdata/check/decls0.src index 80bf4ebb3d..f051a4f2ac 100644 --- a/src/cmd/compile/internal/types2/testdata/check/decls0.src +++ b/src/cmd/compile/internal/types2/testdata/check/decls0.src @@ -4,7 +4,7 @@ // type declarations -package decls0 +package go1_17 // don't permit non-interface elements in interfaces import "unsafe" diff --git a/src/cmd/compile/internal/types2/testdata/check/issues.src b/src/cmd/compile/internal/types2/testdata/check/issues.src index 21aa208cc7..60d23b3c3b 100644 --- a/src/cmd/compile/internal/types2/testdata/check/issues.src +++ b/src/cmd/compile/internal/types2/testdata/check/issues.src @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package issues +package go1_17 // don't permit non-interface elements in interfaces import ( "fmt" diff --git a/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 b/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 index 6e2104a515..1096bb42eb 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 @@ -164,12 +164,12 @@ type _ interface { // for them to be all in a single list, and we report the error // as well.) type _ interface { - type int, int /* ERROR duplicate type int */ - type /* ERROR multiple type lists */ int /* ERROR duplicate type int */ + type int, int /* ERROR duplicate term int */ + type /* ERROR multiple type lists */ int /* ERROR duplicate term int */ } type _ interface { - type struct{f int}, struct{g int}, struct /* ERROR duplicate type */ {f int} + type struct{f int}, struct{g int}, struct /* ERROR duplicate term */ {f int} } // Interface type lists can contain any type, incl. *Named types. diff --git a/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 b/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 new file mode 100644 index 0000000000..e8b3912884 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 @@ -0,0 +1,25 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file shows some examples of generic constraint interfaces. + +package p + +type ( + // Arbitrary types may be embedded like interfaces. + _ interface{int} + _ interface{~int} + + // Types may be combined into a union. + _ interface{int|~string} + + // Union terms must be unique independent of whether they are ~ or not. + _ interface{int|int /* ERROR duplicate term int */ } + _ interface{int|~ /* ERROR duplicate term int */ int } + _ interface{~int|~ /* ERROR duplicate term int */ int } + + // For now we do not permit interfaces with ~ or in unions. + _ interface{~ /* ERROR cannot use interface */ interface{}} + _ interface{int|interface /* ERROR cannot use interface */ {}} +) diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 index 2c1299feb0..92ea305479 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 @@ -36,7 +36,7 @@ func bar8[A foo8[A]](a A) {} func main8() {} // crash 9 -type foo9[A any] interface { type foo9 /* ERROR interface contains type constraints */ [A] } +type foo9[A any] interface { type foo9 /* ERROR cannot use interface */ [A] } func _() { var _ = new(foo9 /* ERROR interface contains type constraints */ [int]) } // crash 12 diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39693.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39693.go2 index 316ab1982e..301c13be41 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39693.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39693.go2 @@ -4,11 +4,20 @@ package p -type Number interface { - int /* ERROR int is not an interface */ - float64 /* ERROR float64 is not an interface */ +type Number1 interface { + // embedding non-interface types is permitted + int + float64 } -func Add[T Number](a, b T) T { +func Add1[T Number1](a, b T) T { return a /* ERROR not defined */ + b } + +type Number2 interface { + int|float64 +} + +func Add2[T Number2](a, b T) T { + return a + b +} diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39711.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39711.go2 index df621a4c17..85eb0a78fe 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39711.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39711.go2 @@ -7,5 +7,7 @@ package p // Do not report a duplicate type error for this type list. // (Check types after interfaces have been completed.) type _ interface { - type interface{ Error() string }, interface{ String() string } + // TODO(gri) Once we have full type sets we can enable this again. + // Fow now we don't permit interfaces in type lists. + // type interface{ Error() string }, interface{ String() string } } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39723.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39723.go2 index 55464e6b77..61bc606789 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39723.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39723.go2 @@ -6,4 +6,4 @@ package p // A constraint must be an interface; it cannot // be a type parameter, for instance. -func _[A interface{ type interface{} }, B A /* ERROR not an interface */ ]() +func _[A interface{ type int }, B A /* ERROR not an interface */ ]() diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39948.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39948.go2 index c2b460902c..6372397ed9 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39948.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39948.go2 @@ -2,7 +2,13 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package p +// TODO(gri) Eventually, once we disallow type lists, we need to +// adjust this code: for 1.17 we don't accept type parameters, +// and for 1.18 this code is valid. +// Leaving for now so we can see that existing errors +// are being reported. + +package go1_17 // don't permit non-interface elements in interfaces type T[P any] interface{ P // ERROR P is a type parameter, not an interface diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index e54f7601be..79a8f3cd7f 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -311,7 +311,6 @@ func (s *Sum) is(pred func(Type) bool) bool { // An Interface represents an interface type. type Interface struct { methods []*Func // ordered list of explicitly declared methods - types Type // (possibly a Sum) type declared with a type list (TODO(gri) need better field name) embeddeds []Type // ordered list of explicitly embedded types allMethods []*Func // ordered list of methods declared with or embedded in this interface (TODO(gri): replace with mset) diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index c534b04130..55858b7b42 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -158,11 +158,17 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { writeSignature(buf, t, qf, visited) case *Sum: - for i, t := range t.types { + writeTypeList(buf, t.types, qf, visited) + + case *Union: + for i, e := range t.terms { if i > 0 { - buf.WriteString(", ") + buf.WriteString("|") } - writeType(buf, t, qf, visited) + if t.tilde[i] { + buf.WriteByte('~') + } + writeType(buf, e, qf, visited) } case *Interface: @@ -207,14 +213,6 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { writeSignature(buf, m.typ.(*Signature), qf, visited) empty = false } - if !empty && t.types != nil { - buf.WriteString("; ") - } - if t.types != nil { - buf.WriteString("type ") - writeType(buf, t.types, qf, visited) - empty = false - } if !empty && len(t.embeddeds) > 0 { buf.WriteString("; ") } @@ -307,6 +305,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { default: // For externally defined implementations of Type. + // Note: In this case cycles won't be caught. buf.WriteString(t.String()) } } diff --git a/src/cmd/compile/internal/types2/typestring_test.go b/src/cmd/compile/internal/types2/typestring_test.go index 618fdc0757..8d0ca760bf 100644 --- a/src/cmd/compile/internal/types2/typestring_test.go +++ b/src/cmd/compile/internal/types2/typestring_test.go @@ -91,7 +91,9 @@ var independentTestTypes = []testEntry{ dup("interface{}"), dup("interface{m()}"), dup(`interface{String() string; m(int) float32}`), - dup(`interface{type int, float32, complex128}`), + {"interface{type int, float32, complex128}", "interface{~int|~float32|~complex128}"}, + dup("interface{int|float32|complex128}"), + dup("interface{int|~float32|~complex128}"), // maps dup("map[string]int"), diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index e1832bbb2a..f1630b75d0 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -356,6 +356,9 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { // This should not happen with the current internal use of sum types. panic("type inference across sum types not implemented") + case *Union: + unimplemented() + case *Interface: // Two interface types are identical if they have the same set of methods with // the same names and identical function types. Lower-case method names from diff --git a/src/cmd/compile/internal/types2/union.go b/src/cmd/compile/internal/types2/union.go new file mode 100644 index 0000000000..70dc3bc360 --- /dev/null +++ b/src/cmd/compile/internal/types2/union.go @@ -0,0 +1,105 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types2 + +import "cmd/compile/internal/syntax" + +// ---------------------------------------------------------------------------- +// API + +// A Union represents a union of terms. +// A term is a type, possibly with a ~ (tilde) indication. +type Union struct { + terms []Type // terms are unique + tilde []bool // if tilde[i] is set, terms[i] is of the form ~T +} + +func NewUnion(terms []Type, tilde []bool) Type { return newUnion(terms, tilde) } + +func (u *Union) NumTerms() int { return len(u.terms) } +func (u *Union) Term(i int) (Type, bool) { return u.terms[i], u.tilde[i] } + +func (u *Union) Underlying() Type { return u } +func (u *Union) String() string { return TypeString(u, nil) } + +// ---------------------------------------------------------------------------- +// Implementation + +func newUnion(terms []Type, tilde []bool) Type { + assert(len(terms) == len(tilde)) + if terms == nil { + return nil + } + t := new(Union) + t.terms = terms + t.tilde = tilde + return t +} + +func parseUnion(check *Checker, tlist []syntax.Expr) Type { + var terms []Type + var tilde []bool + for _, x := range tlist { + t, d := parseTilde(check, x) + if len(tlist) == 1 && !d { + return t // single type + } + terms = append(terms, t) + tilde = append(tilde, d) + } + + // Ensure that each type is only present once in the type list. + // It's ok to do this check at the end because it's not a requirement + // for correctness of the code. + // Note: This is a quadratic algorithm, but unions tend to be short. + check.later(func() { + for i, t := range terms { + t := expand(t) + if t == Typ[Invalid] { + continue + } + + x := tlist[i] + pos := syntax.StartPos(x) + // We may not know the position of x if it was a typechecker- + // introduced ~T type of a type list entry T. Use the position + // of T instead. + // TODO(gri) remove this test once we don't support type lists anymore + if !pos.IsKnown() { + if op, _ := x.(*syntax.Operation); op != nil { + pos = syntax.StartPos(op.X) + } + } + + u := under(t) + if tilde[i] { + // TODO(gri) enable this check once we have converted tests + // if !Identical(u, t) { + // check.errorf(x, "invalid use of ~ (underlying type of %s is %s)", t, u) + // } + } + if _, ok := u.(*Interface); ok { + check.errorf(pos, "cannot use interface %s with ~ or inside a union (implementation restriction)", t) + } + + // Complain about duplicate entries a|a, but also a|~a, and ~a|~a. + if includes(terms[:i], t) { + // TODO(gri) this currently doesn't print the ~ if present + check.softErrorf(pos, "duplicate term %s in union element", t) + } + } + }) + + return newUnion(terms, tilde) +} + +func parseTilde(check *Checker, x syntax.Expr) (Type, bool) { + tilde := false + if op, _ := x.(*syntax.Operation); op != nil && op.Op == syntax.Tilde { + x = op.X + tilde = true + } + return check.anyType(x), tilde +} -- GitLab From 155dc0e541368bbd208bfcf12985f58fb375dd5c Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 21 May 2021 19:46:45 -0700 Subject: [PATCH 0132/2500] [dev.typeparams] cmd/compile/internal/types2: factor out constraint satisfaction check This is a simple move of a block of inlined code into a function to make instantiation more manageable and easier to understand. There is no change in functionality or behavior. Change-Id: I46e7a9ea03527731e1f0219b3402eb03949627c5 Reviewed-on: https://go-review.googlesource.com/c/go/+/322070 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/subst.go | 146 ++++++++++++----------- 1 file changed, 77 insertions(+), 69 deletions(-) diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 04a3527d6d..a2b81ba0cc 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -119,90 +119,98 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, poslis // check bounds for i, tname := range tparams { - tpar := tname.typ.(*TypeParam) - iface := tpar.Bound() - if iface.Empty() { - continue // no type bound - } - - targ := targs[i] - // best position for error reporting pos := pos if i < len(poslist) { pos = poslist[i] } + // stop checking bounds after the first failure + if !check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap) { + break + } + } - // The type parameter bound is parameterized with the same type parameters - // as the instantiated type; before we can use it for bounds checking we - // need to instantiate it with the type arguments with which we instantiate - // the parameterized type. - iface = check.subst(pos, iface, smap).(*Interface) - - // targ must implement iface (methods) - // - check only if we have methods - check.completeInterface(nopos, iface) - if len(iface.allMethods) > 0 { - // If the type argument is a pointer to a type parameter, the type argument's - // method set is empty. - // TODO(gri) is this what we want? (spec question) - if base, isPtr := deref(targ); isPtr && asTypeParam(base) != nil { - check.errorf(pos, "%s has no methods", targ) - break - } - if m, wrong := check.missingMethod(targ, iface, true); m != nil { - // TODO(gri) needs to print updated name to avoid major confusion in error message! - // (print warning for now) - // Old warning: - // check.softErrorf(pos, "%s does not satisfy %s (warning: name not updated) = %s (missing method %s)", targ, tpar.bound, iface, m) - if m.name == "==" { - // We don't want to report "missing method ==". - check.softErrorf(pos, "%s does not satisfy comparable", targ) - } else if wrong != nil { - // TODO(gri) This can still report uninstantiated types which makes the error message - // more difficult to read then necessary. - check.softErrorf(pos, - "%s does not satisfy %s: wrong method signature\n\tgot %s\n\twant %s", - targ, tpar.bound, wrong, m, - ) - } else { - check.softErrorf(pos, "%s does not satisfy %s (missing method %s)", targ, tpar.bound, m.name) - } - break + return check.subst(pos, typ, smap) +} + +// satisfies reports whether the type argument targ satisfies the constraint of type parameter +// parameter tpar (after any of its type parameters have been substituted through smap). +// A suitable error is reported if the result is false. +func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap *substMap) bool { + iface := tpar.Bound() + if iface.Empty() { + return true // no type bound + } + + // The type parameter bound is parameterized with the same type parameters + // as the instantiated type; before we can use it for bounds checking we + // need to instantiate it with the type arguments with which we instantiate + // the parameterized type. + iface = check.subst(pos, iface, smap).(*Interface) + + // targ must implement iface (methods) + // - check only if we have methods + check.completeInterface(nopos, iface) + if len(iface.allMethods) > 0 { + // If the type argument is a pointer to a type parameter, the type argument's + // method set is empty. + // TODO(gri) is this what we want? (spec question) + if base, isPtr := deref(targ); isPtr && asTypeParam(base) != nil { + check.errorf(pos, "%s has no methods", targ) + return false + } + if m, wrong := check.missingMethod(targ, iface, true); m != nil { + // TODO(gri) needs to print updated name to avoid major confusion in error message! + // (print warning for now) + // Old warning: + // check.softErrorf(pos, "%s does not satisfy %s (warning: name not updated) = %s (missing method %s)", targ, tpar.bound, iface, m) + if m.name == "==" { + // We don't want to report "missing method ==". + check.softErrorf(pos, "%s does not satisfy comparable", targ) + } else if wrong != nil { + // TODO(gri) This can still report uninstantiated types which makes the error message + // more difficult to read then necessary. + check.softErrorf(pos, + "%s does not satisfy %s: wrong method signature\n\tgot %s\n\twant %s", + targ, tpar.bound, wrong, m, + ) + } else { + check.softErrorf(pos, "%s does not satisfy %s (missing method %s)", targ, tpar.bound, m.name) } + return false } + } - // targ's underlying type must also be one of the interface types listed, if any - if iface.allTypes == nil { - continue // nothing to do - } + // targ's underlying type must also be one of the interface types listed, if any + if iface.allTypes == nil { + return true // nothing to do + } - // If targ is itself a type parameter, each of its possible types, but at least one, must be in the - // list of iface types (i.e., the targ type list must be a non-empty subset of the iface types). - if targ := asTypeParam(targ); targ != nil { - targBound := targ.Bound() - if targBound.allTypes == nil { - check.softErrorf(pos, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ) - break - } - for _, t := range unpack(targBound.allTypes) { - if !iface.isSatisfiedBy(t) { - // TODO(gri) match this error message with the one below (or vice versa) - check.softErrorf(pos, "%s does not satisfy %s (%s type constraint %s not found in %s)", targ, tpar.bound, targ, t, iface.allTypes) - break - } + // If targ is itself a type parameter, each of its possible types, but at least one, must be in the + // list of iface types (i.e., the targ type list must be a non-empty subset of the iface types). + if targ := asTypeParam(targ); targ != nil { + targBound := targ.Bound() + if targBound.allTypes == nil { + check.softErrorf(pos, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ) + return false + } + for _, t := range unpack(targBound.allTypes) { + if !iface.isSatisfiedBy(t) { + // TODO(gri) match this error message with the one below (or vice versa) + check.softErrorf(pos, "%s does not satisfy %s (%s type constraint %s not found in %s)", targ, tpar.bound, targ, t, iface.allTypes) + return false } - break } + return false + } - // Otherwise, targ's type or underlying type must also be one of the interface types listed, if any. - if !iface.isSatisfiedBy(targ) { - check.softErrorf(pos, "%s does not satisfy %s (%s not found in %s)", targ, tpar.bound, under(targ), iface.allTypes) - break - } + // Otherwise, targ's type or underlying type must also be one of the interface types listed, if any. + if !iface.isSatisfiedBy(targ) { + check.softErrorf(pos, "%s does not satisfy %s (%s not found in %s)", targ, tpar.bound, under(targ), iface.allTypes) + return false } - return check.subst(pos, typ, smap) + return true } // subst returns the type typ with its type parameters tpars replaced by -- GitLab From 6c9e1c58bc7661638ee084e40a3b6fc907825496 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 25 May 2021 14:06:56 -0700 Subject: [PATCH 0133/2500] [dev.typeparams] test: fix and update run.go's generics testing In a late change to golang.org/cl/320609, while going back and forth on the meaning of the boolean result value for "checkFlags", I got one of the cases wrong. As a result, rather than testing both default flags and -G=3, we were (redundanly) testing default flags and -G=0. I ran into this because in my local dev tree, I'm using types2 even for -G=0, and evidently one of the recent types2 CLs changed the error message in fixedbugs/issue10975.go. Fortunately, there haven't been any other regressions despite lacking test coverage. So this CL cleans things up a bit: 1. Fixes that test to use -lang=go1.17, so types2 reports the old error message again. 2. Renames "checkFlags" to "validForGLevel" so the boolean result is harder to get wrong. 3. Removes the blanket deny list of all -m tests, and instead adds the specific tests that are still failing. This effectively extends -G=3 coverage to another 27 tests that were using -m but already passing, so we can make sure they don't regress again. 4. Adds a -f flag to force running tests even if they're in the deny list, to make it easier to test whether they're still failing without having to edit run.go. Change-Id: I058d9d90d81a92189e54c6f591d95fb617fede53 Reviewed-on: https://go-review.googlesource.com/c/go/+/322612 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: Robert Griesemer --- test/fixedbugs/issue10975.go | 2 +- test/run.go | 109 ++++++++++++++++++++++------------- 2 files changed, 71 insertions(+), 40 deletions(-) diff --git a/test/fixedbugs/issue10975.go b/test/fixedbugs/issue10975.go index 89ef23c1a8..876ea58ef9 100644 --- a/test/fixedbugs/issue10975.go +++ b/test/fixedbugs/issue10975.go @@ -1,4 +1,4 @@ -// errorcheck +// errorcheck -lang=go1.17 // Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/test/run.go b/test/run.go index 506380a7a5..ef24396809 100644 --- a/test/run.go +++ b/test/run.go @@ -43,6 +43,7 @@ var ( updateErrors = flag.Bool("update_errors", false, "update error messages in test file based on compiler output") runoutputLimit = flag.Int("l", defaultRunOutputLimit(), "number of parallel runoutput tests to run") generics = flag.String("G", "0,3", "a comma-separated list of -G compiler flags to test with") + force = flag.Bool("f", false, "run expected-failure generics tests rather than skipping them") shard = flag.Int("shard", 0, "shard index to run. Only applicable if -shards is non-zero.") shards = flag.Int("shards", 0, "number of shards. If 0, all tests are run. This is used by the continuous build.") @@ -518,7 +519,7 @@ func (t *test) run() { close(t.donec) }() - if t.glevel > 0 { + if t.glevel > 0 && !*force { // Files excluded from generics testing. filename := strings.Replace(t.goFileName(), "\\", "/", -1) // goFileName() uses \ on Windows if excludedFiles[filename] { @@ -657,33 +658,37 @@ func (t *test) run() { Compile ) - // checkFlags reports whether the current test configuration should - // be skipped because flags (which should be an arguments list for - // "go tool compile", not "go build") contains an excluded flag. - // It will also update flags as appropriate. - checkFlags := func(tool Tool) bool { - if t.glevel > 0 { + // validForGLevel reports whether the current test is valid to run + // at the specified -G level. If so, it may update flags as + // necessary to test with -G. + validForGLevel := func(tool Tool) bool { + if t.glevel == 0 { + // default -G level; always valid return true } + for _, flag := range flags { + if strings.Contains(flag, "-G") { + // test provides explicit -G flag already + if *verbose { + fmt.Printf("excl\t%s\n", t.goFileName()) + } + return false + } + } + switch tool { case Build, Run: // ok; handled in goGcflags case Compile: - for _, flag := range flags { - for _, pattern := range excludedFlags { - if strings.Contains(flag, pattern) { - if *verbose { - fmt.Printf("excl\t%s\t%s\n", t.goFileName(), flags) - } - return true // cannot handle flag - } - } - } flags = append(flags, fmt.Sprintf("-G=%v", t.glevel)) default: + // we don't know how to add -G for this test yet + if *verbose { + fmt.Printf("excl\t%s\n", t.goFileName()) + } return false } @@ -766,7 +771,7 @@ func (t *test) run() { t.err = fmt.Errorf("unimplemented action %q", action) case "asmcheck": - if !checkFlags(AsmCheck) { + if !validForGLevel(AsmCheck) { return } @@ -824,7 +829,7 @@ func (t *test) run() { return case "errorcheck": - if !checkFlags(Compile) { + if !validForGLevel(Compile) { return } @@ -858,7 +863,7 @@ func (t *test) run() { t.err = t.errorCheck(string(out), wantAuto, long, t.gofile) case "compile": - if !checkFlags(Compile) { + if !validForGLevel(Compile) { return } @@ -866,7 +871,7 @@ func (t *test) run() { _, t.err = compileFile(runcmd, long, flags) case "compiledir": - if !checkFlags(Compile) { + if !validForGLevel(Compile) { return } @@ -885,7 +890,7 @@ func (t *test) run() { } case "errorcheckdir", "errorcheckandrundir": - if !checkFlags(Compile) { + if !validForGLevel(Compile) { return } @@ -934,7 +939,7 @@ func (t *test) run() { fallthrough case "rundir": - if !checkFlags(Run) { + if !validForGLevel(Run) { return } @@ -996,7 +1001,7 @@ func (t *test) run() { } case "runindir": - if !checkFlags(Run) { + if !validForGLevel(Run) { return } @@ -1039,7 +1044,7 @@ func (t *test) run() { t.checkExpectedOutput(out) case "build": - if !checkFlags(Build) { + if !validForGLevel(Build) { return } @@ -1050,7 +1055,7 @@ func (t *test) run() { } case "builddir", "buildrundir": - if !checkFlags(Build) { + if !validForGLevel(Build) { return } @@ -1133,7 +1138,7 @@ func (t *test) run() { } case "buildrun": - if !checkFlags(Build) { + if !validForGLevel(Build) { return } @@ -1162,7 +1167,7 @@ func (t *test) run() { t.checkExpectedOutput(out) case "run": - if !checkFlags(Run) { + if !validForGLevel(Run) { return } @@ -1209,7 +1214,7 @@ func (t *test) run() { t.checkExpectedOutput(out) case "runoutput": - if !checkFlags(Run) { + if !validForGLevel(Run) { return } @@ -1248,7 +1253,7 @@ func (t *test) run() { t.checkExpectedOutput(out) case "errorcheckoutput": - if !checkFlags(Compile) { + if !validForGLevel(Compile) { return } @@ -2015,15 +2020,6 @@ func overlayDir(dstRoot, srcRoot string) error { // checking are also excluded since these phases are not running yet. // We can get rid of this code once types2 is fully plugged in. -// For now we skip tests when we can't handle the file or some of the flags. -// The first goal is to eliminate the excluded list; the second goal is to -// eliminate the flag list. - -var excludedFlags = []string{ - "-G", // skip redundant testing - "-m", -} - // List of files that the compiler cannot errorcheck with the new typechecker (compiler -G option). // Temporary scaffolding until we pass all the tests at which point this map can be removed. var excludedFiles = map[string]bool{ @@ -2101,4 +2097,39 @@ var excludedFiles = map[string]bool{ "fixedbugs/issue7525e.go": true, // types2 reports init cycle error on different line - ok otherwise "fixedbugs/issue7525.go": true, // types2 reports init cycle error on different line - ok otherwise "fixedbugs/issue9691.go": true, // "cannot assign to int(.autotmp_4)" (probably irgen's fault) + + // tests that rely on -m diagnostics, which currently differ with -G=3 + // + // TODO(mdempsky): Triage, though most of the issues seem to fall into: + // - Anonymous result parameters given different names (e.g., ~r0 vs ~r1) + // - Some escape analysis diagnostics being printed without position information + // - Some expressions printed differently (e.g., "int(100)" instead + // of "100" or "&composite literal" instead of "&[4]int{...}"). + "closure3.go": true, + "escape2.go": true, + "escape2n.go": true, + "escape4.go": true, + "escape5.go": true, + "escape_array.go": true, + "escape_calls.go": true, + "escape_field.go": true, + "escape_iface.go": true, + "escape_indir.go": true, + "escape_level.go": true, + "escape_map.go": true, + "escape_param.go": true, + "escape_slice.go": true, + "escape_struct_param1.go": true, + "escape_struct_param2.go": true, + "fixedbugs/issue12006.go": true, + "fixedbugs/issue13799.go": true, + "fixedbugs/issue21709.go": true, + "fixedbugs/issue24651a.go": true, + "fixedbugs/issue24651b.go": true, + "fixedbugs/issue27557.go": true, + "fixedbugs/issue31573.go": true, + "fixedbugs/issue37837.go": true, + "fixedbugs/issue39292.go": true, + "fixedbugs/issue7921.go": true, + "inline.go": true, } -- GitLab From ff0164cf736b12740bf5837111e93130da6d612c Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Tue, 25 May 2021 21:21:16 +0000 Subject: [PATCH 0134/2500] Revert "[dev.fuzz] internal/fuzz: include coverage in logged stats" This reverts commit 54f067812dd870c305daabd22ca190b0f48e672e. Reason for revert: While this is helpful for the engineering team when we're debugging, it might lead to users feeling like the fuzzer is stuck and that there are a lot of edges that are still yet to be reached. In reality, it's very likely that the compiler will instrument more lines of code than are actually reachable by the fuzz target, so showing the ratio between number of edges hit vs. all edges can be misleading. In the future, we may want to consider making this information viewable by a debug flag or something similar. Change-Id: Ied696f8bf644445bad22c872b64daa7add605ac6 Reviewed-on: https://go-review.googlesource.com/c/go/+/322632 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/internal/fuzz/fuzz.go | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 28539b2604..553086b20a 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -474,18 +474,14 @@ func (c *coordinator) updateStats(result fuzzResult) { } func (c *coordinator) logStats() { + // TODO(jayconrod,katiehockman): consider printing the amount of coverage + // that has been reached so far (perhaps a percentage of edges?) elapsed := time.Since(c.startTime) if c.coverageOnlyRun() { fmt.Fprintf(c.opts.Log, "gathering baseline coverage, elapsed: %.1fs, workers: %d, left: %d\n", elapsed.Seconds(), c.opts.Parallel, c.covOnlyInputs) } else { rate := float64(c.count) / elapsed.Seconds() - edges, hits := len(c.coverageData), 0 - for _, c := range c.coverageData { - if c > 0 { - hits++ - } - } - fmt.Fprintf(c.opts.Log, "fuzzing, elapsed: %.1fs, execs: %d (%.0f/sec), workers: %d, interesting: %d, coverage: %d/%d\n", elapsed.Seconds(), c.count, rate, c.opts.Parallel, c.interestingCount, hits, edges) + fmt.Fprintf(c.opts.Log, "fuzzing, elapsed: %.1fs, execs: %d (%.0f/sec), workers: %d, interesting: %d\n", elapsed.Seconds(), c.count, rate, c.opts.Parallel, c.interestingCount) } } -- GitLab From fd54ae8b0c7ed3ef9869112586069f7cac82cf1e Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 24 May 2021 20:36:42 -0700 Subject: [PATCH 0135/2500] [dev.typeparams] cmd/compile: adding union support in types1 Add union support in types1, and allow exporting of unions, and importing unions back into types1 and types2. Added new test mincheck.go/mincheck.dir that tests that type lists (type sets) are correctly exported/imported, so that types2 gives correct errors that an instantiation doesn't fit the type list in the type param constraint. Change-Id: I8041c6c79289c870a95ed5a1b10e4c1c16985b12 Reviewed-on: https://go-review.googlesource.com/c/go/+/322609 Trust: Dan Scales Trust: Robert Griesemer Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/importer/iimport.go | 14 +++++++ src/cmd/compile/internal/noder/types.go | 19 +++++++-- src/cmd/compile/internal/typecheck/iexport.go | 13 +++++++ src/cmd/compile/internal/typecheck/iimport.go | 13 +++++++ src/cmd/compile/internal/types/kind_string.go | 23 +++++------ src/cmd/compile/internal/types/size.go | 14 ++++++- src/cmd/compile/internal/types/type.go | 39 +++++++++++++++++++ src/cmd/compile/internal/types2/type.go | 13 ------- test/fixedbugs/bug195.go | 2 +- test/fixedbugs/issue11614.go | 2 +- test/typeparam/mincheck.dir/a.go | 16 ++++++++ test/typeparam/mincheck.dir/main.go | 38 ++++++++++++++++++ test/typeparam/mincheck.go | 7 ++++ 13 files changed, 182 insertions(+), 31 deletions(-) create mode 100644 test/typeparam/mincheck.dir/a.go create mode 100644 test/typeparam/mincheck.dir/main.go create mode 100644 test/typeparam/mincheck.go diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index 37e5113435..fd48bfc179 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -68,6 +68,7 @@ const ( interfaceType typeParamType instType + unionType ) const io_SeekCurrent = 1 // io.SeekCurrent (not defined in Go 1.4) @@ -660,6 +661,19 @@ func (r *importReader) doType(base *types2.Named) types2.Type { // we must always use the methods of the base (orig) type. t := types2.Instantiate(pos, baseType, targs) return t + + case unionType: + if r.p.exportVersion < iexportVersionGenerics { + errorf("unexpected instantiation type") + } + nt := int(r.uint64()) + terms := make([]types2.Type, nt) + tildes := make([]bool, nt) + for i := range terms { + terms[i] = r.typ() + tildes[i] = r.bool() + } + return types2.NewUnion(terms, tildes) } } diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index 16d664f538..c6e97d4206 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -187,6 +187,9 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { for i := range embeddeds { // TODO(mdempsky): Get embedding position. e := typ.EmbeddedType(i) + + // With Go 1.18, an embedded element can be any type, not + // just an interface. if t := types2.AsInterface(e); t != nil { if t.IsComparable() { // Ignore predefined type 'comparable', since it @@ -194,11 +197,9 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { // relevant methods. continue } - embeddeds[j] = types.NewField(src.NoXPos, nil, g.typ1(e)) - j++ } - // Ignore embedded non-interface types - they correspond - // to type lists which we currently don't handle here. + embeddeds[j] = types.NewField(src.NoXPos, nil, g.typ1(e)) + j++ } embeddeds = embeddeds[:j] @@ -234,6 +235,16 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { tp.SetBound(bound) return tp + case *types2.Union: + nt := typ.NumTerms() + tlist := make([]*types.Type, nt) + tildes := make([]bool, nt) + for i := range tlist { + term, _ := typ.Term(i) + tlist[i] = g.typ1(term) + } + return types.NewUnion(tlist, tildes) + case *types2.Tuple: // Tuples are used for the type of a function call (i.e. the // return value of the function). diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 292bb2c409..ea8e751852 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -256,6 +256,7 @@ const ( interfaceType typeParamType instType + unionType ) const ( @@ -943,6 +944,18 @@ func (w *exportWriter) doTyp(t *types.Type) { w.signature(f.Type) } + case types.TUNION: + // TODO(danscales): possibly put out the tilde bools in more + // compact form. + w.startType(unionType) + nt := t.NumTerms() + w.uint64(uint64(nt)) + for i := 0; i < nt; i++ { + t, b := t.Term(i) + w.typ(t) + w.bool(b) + } + default: base.Fatalf("unexpected type: %v", t) } diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index d5b549483d..3fb675f824 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -790,6 +790,19 @@ func (r *importReader) typ1() *types.Type { baseType := r.typ() t := Instantiate(pos, baseType, targs) return t + + case unionType: + if r.p.exportVersion < iexportVersionGenerics { + base.Fatalf("unexpected instantiation type") + } + nt := int(r.uint64()) + terms := make([]*types.Type, nt) + tildes := make([]bool, nt) + for i := range terms { + terms[i] = r.typ() + tildes[i] = r.bool() + } + return types.NewUnion(terms, tildes) } } diff --git a/src/cmd/compile/internal/types/kind_string.go b/src/cmd/compile/internal/types/kind_string.go index ae24a58b92..3e6a8bc064 100644 --- a/src/cmd/compile/internal/types/kind_string.go +++ b/src/cmd/compile/internal/types/kind_string.go @@ -38,20 +38,21 @@ func _() { _ = x[TSTRING-27] _ = x[TUNSAFEPTR-28] _ = x[TTYPEPARAM-29] - _ = x[TIDEAL-30] - _ = x[TNIL-31] - _ = x[TBLANK-32] - _ = x[TFUNCARGS-33] - _ = x[TCHANARGS-34] - _ = x[TSSA-35] - _ = x[TTUPLE-36] - _ = x[TRESULTS-37] - _ = x[NTYPE-38] + _ = x[TUNION-30] + _ = x[TIDEAL-31] + _ = x[TNIL-32] + _ = x[TBLANK-33] + _ = x[TFUNCARGS-34] + _ = x[TCHANARGS-35] + _ = x[TSSA-36] + _ = x[TTUPLE-37] + _ = x[TRESULTS-38] + _ = x[NTYPE-39] } -const _Kind_name = "xxxINT8UINT8INT16UINT16INT32UINT32INT64UINT64INTUINTUINTPTRCOMPLEX64COMPLEX128FLOAT32FLOAT64BOOLPTRFUNCSLICEARRAYSTRUCTCHANMAPINTERFORWANYSTRINGUNSAFEPTRTYPEPARAMIDEALNILBLANKFUNCARGSCHANARGSSSATUPLERESULTSNTYPE" +const _Kind_name = "xxxINT8UINT8INT16UINT16INT32UINT32INT64UINT64INTUINTUINTPTRCOMPLEX64COMPLEX128FLOAT32FLOAT64BOOLPTRFUNCSLICEARRAYSTRUCTCHANMAPINTERFORWANYSTRINGUNSAFEPTRTYPEPARAMUNIONIDEALNILBLANKFUNCARGSCHANARGSSSATUPLERESULTSNTYPE" -var _Kind_index = [...]uint8{0, 3, 7, 12, 17, 23, 28, 34, 39, 45, 48, 52, 59, 68, 78, 85, 92, 96, 99, 103, 108, 113, 119, 123, 126, 131, 135, 138, 144, 153, 162, 167, 170, 175, 183, 191, 194, 199, 206, 211} +var _Kind_index = [...]uint8{0, 3, 7, 12, 17, 23, 28, 34, 39, 45, 48, 52, 59, 68, 78, 85, 92, 96, 99, 103, 108, 113, 119, 123, 126, 131, 135, 138, 144, 153, 162, 167, 172, 175, 180, 188, 196, 199, 204, 211, 216} func (i Kind) String() string { if i >= Kind(len(_Kind_index)-1) { diff --git a/src/cmd/compile/internal/types/size.go b/src/cmd/compile/internal/types/size.go index f0e695ab96..7059eff398 100644 --- a/src/cmd/compile/internal/types/size.go +++ b/src/cmd/compile/internal/types/size.go @@ -104,8 +104,14 @@ func expandiface(t *Type) { continue } + if m.Type.IsUnion() { + continue + } + + // Once we go to 1.18, then embedded types can be anything, but + // for now, just interfaces and unions. if !m.Type.IsInterface() { - base.ErrorfAt(m.Pos, "interface contains embedded non-interface %v", m.Type) + base.ErrorfAt(m.Pos, "interface contains embedded non-interface, non-union %v", m.Type) m.SetBroke(true) t.SetBroke(true) // Add to fields so that error messages @@ -405,6 +411,12 @@ func CalcSize(t *Type) { t.Align = uint8(PtrSize) expandiface(t) + case TUNION: + // Always part of an interface for now, so size/align don't matter. + // Pretend a union is represented like an interface. + w = 2 * int64(PtrSize) + t.Align = uint8(PtrSize) + case TCHAN: // implemented as pointer w = int64(PtrSize) diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 3b0a9706f6..e7831121bf 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -73,6 +73,7 @@ const ( TSTRING TUNSAFEPTR TTYPEPARAM + TUNION // pseudo-types for literals TIDEAL // untyped numeric constants @@ -392,6 +393,12 @@ type Typeparam struct { bound *Type } +// Union contains Type fields specific to union types. +type Union struct { + terms []*Type + tildes []bool // whether terms[i] is of form ~T +} + // Ptr contains Type fields specific to pointer types. type Ptr struct { Elem *Type // element type @@ -574,6 +581,8 @@ func New(et Kind) *Type { t.Extra = new(Results) case TTYPEPARAM: t.Extra = new(Typeparam) + case TUNION: + t.Extra = new(Union) } return t } @@ -1453,6 +1462,10 @@ func (t *Type) IsInterface() bool { return t.kind == TINTER } +func (t *Type) IsUnion() bool { + return t.kind == TUNION +} + // IsEmptyInterface reports whether t is an empty interface type. func (t *Type) IsEmptyInterface() bool { return t.IsInterface() && t.AllMethods().Len() == 0 @@ -1811,6 +1824,32 @@ func (t *Type) Bound() *Type { return t.Extra.(*Typeparam).bound } +// NewUnion returns a new union with the specified set of terms (types). If +// tildes[i] is true, then terms[i] represents ~T, rather than just T. +func NewUnion(terms []*Type, tildes []bool) *Type { + t := New(TUNION) + if len(terms) != len(tildes) { + base.Fatalf("Mismatched terms and tildes for NewUnion") + } + t.Extra.(*Union).terms = terms + t.Extra.(*Union).tildes = tildes + return t +} + +// NumTerms returns the number of terms in a union type. +func (t *Type) NumTerms() int { + t.wantEtype(TUNION) + return len(t.Extra.(*Union).terms) +} + +// Term returns ith term of a union type as (term, tilde). If tilde is true, term +// represents ~T, rather than just T. +func (t *Type) Term(i int) (*Type, bool) { + t.wantEtype(TUNION) + u := t.Extra.(*Union) + return u.terms[i], u.tildes[i] +} + const BOGUS_FUNARG_OFFSET = -1000000000 func unzeroFieldOffsets(f []*Field) { diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 79a8f3cd7f..2a93ca0388 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -368,9 +368,6 @@ func NewInterface(methods []*Func, embeddeds []*Named) *Interface { } // NewInterfaceType returns a new (incomplete) interface for the given methods and embedded types. -// Each embedded type must have an underlying type of interface type (this property is not -// verified for defined types, which may be in the process of being set up and which don't -// have a valid underlying type yet). // NewInterfaceType takes ownership of the provided methods and may modify their types by setting // missing receivers. To compute the method set of the interface, Complete must be called. func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface { @@ -386,16 +383,6 @@ func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface { } } - // All embedded types should be interfaces; however, defined types - // may not yet be fully resolved. Only verify that non-defined types - // are interfaces. This matches the behavior of the code before the - // fix for #25301 (issue #25596). - for _, t := range embeddeds { - if _, ok := t.(*Named); !ok && !IsInterface(t) { - panic("embedded type is not an interface") - } - } - // sort for API stability sortMethods(methods) sortTypes(embeddeds) diff --git a/test/fixedbugs/bug195.go b/test/fixedbugs/bug195.go index 94f61fff7f..6d8578d6cb 100644 --- a/test/fixedbugs/bug195.go +++ b/test/fixedbugs/bug195.go @@ -1,4 +1,4 @@ -// errorcheck +// errorcheck -lang=go1.17 // Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/test/fixedbugs/issue11614.go b/test/fixedbugs/issue11614.go index de15f9827f..6ea463b7fe 100644 --- a/test/fixedbugs/issue11614.go +++ b/test/fixedbugs/issue11614.go @@ -1,4 +1,4 @@ -// errorcheck +// errorcheck -lang=go1.17 // Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/test/typeparam/mincheck.dir/a.go b/test/typeparam/mincheck.dir/a.go new file mode 100644 index 0000000000..f1844bba9d --- /dev/null +++ b/test/typeparam/mincheck.dir/a.go @@ -0,0 +1,16 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type Ordered interface { + type int, int64, float64 +} + +func Min[T Ordered](x, y T) T { + if x < y { + return x + } + return y +} diff --git a/test/typeparam/mincheck.dir/main.go b/test/typeparam/mincheck.dir/main.go new file mode 100644 index 0000000000..72d8effcc5 --- /dev/null +++ b/test/typeparam/mincheck.dir/main.go @@ -0,0 +1,38 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "a" + "fmt" +) + +func main() { + const want = 2 + if got := a.Min[int](2, 3); got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } + + if got := a.Min(2, 3); got != want { + panic(fmt.Sprintf("want %d, got %d", want, got)) + } + + if got := a.Min[float64](3.5, 2.0); got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } + + if got := a.Min(3.5, 2.0); got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } + + const want2 = "ay" + if got := a.Min[string]("bb", "ay"); got != want2 { // ERROR "string does not satisfy interface{int|int64|float64}" + panic(fmt.Sprintf("got %d, want %d", got, want2)) + } + + if got := a.Min("bb", "ay"); got != want2 { // ERROR "string does not satisfy interface{int|int64|float64}" + panic(fmt.Sprintf("got %d, want %d", got, want2)) + } +} diff --git a/test/typeparam/mincheck.go b/test/typeparam/mincheck.go new file mode 100644 index 0000000000..32cf4b830d --- /dev/null +++ b/test/typeparam/mincheck.go @@ -0,0 +1,7 @@ +// errorcheckdir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From 95748d1b741d2c612cf90d9b6f4f8bdb81800e23 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 18 May 2021 01:20:13 -0700 Subject: [PATCH 0136/2500] [dev.typeparams] cmd/compile: avoid some redundant type construction This CL updates noder and typecheck to avoid a couple of instances of redundant evaluation of type expressions: 1. When noding struct fields or parameter tuples, check for syntax.Type reuse between adjacent fields and then reuse the corresponding ir.Node type expression. It would perhaps be even better to avoid re-noding the type expression too, but noder's days are numbered anyway, so I'd rather be minimally invasive here. 2. When importing an empty interface, reuse the same cached empty interface instance that is used for empty interfaces that appear in source. This matches types2's behavior, which uses a single types2.Interface instance for all empty interfaces. These changes are motivated by making it possible to migrate from typecheck to types2 while passing toolstash -cmp. Updates #46208. Change-Id: Ia6458894494464d863181db356f3284630c90ffe Reviewed-on: https://go-review.googlesource.com/c/go/+/320789 Run-TryBot: Matthew Dempsky Trust: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/noder/noder.go | 6 ++++++ src/cmd/compile/internal/typecheck/iimport.go | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index 4c7c9fc322..06c3b00601 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -625,6 +625,9 @@ func (p *noder) params(params []*syntax.Field, dddOk bool) []*ir.Field { for i, param := range params { p.setlineno(param) nodes = append(nodes, p.param(param, dddOk, i+1 == len(params))) + if i > 0 && params[i].Type == params[i-1].Type { + nodes[i].Ntype = nodes[i-1].Ntype + } } return nodes } @@ -917,6 +920,9 @@ func (p *noder) structType(expr *syntax.StructType) ir.Node { } else { n = ir.NewField(p.pos(field), p.name(field.Name), p.typeExpr(field.Type), nil) } + if i > 0 && expr.FieldList[i].Type == expr.FieldList[i-1].Type { + n.Ntype = l[i-1].Ntype + } if i < len(expr.TagList) && expr.TagList[i] != nil { n.Note = constant.StringVal(p.basicLit(expr.TagList[i])) } diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 3fb675f824..16b3e7ceba 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -745,6 +745,10 @@ func (r *importReader) typ1() *types.Type { methods[i] = types.NewField(pos, sym, typ) } + if len(embeddeds)+len(methods) == 0 { + return types.Types[types.TINTER] + } + t := types.NewInterface(r.currPkg, append(embeddeds, methods...)) // Ensure we expand the interface in the frontend (#25055). -- GitLab From b7f7d1cd7b3d965ec25d365b3e5057ef3278c729 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 24 May 2021 14:15:48 -0700 Subject: [PATCH 0137/2500] [dev.typeparams] cmd/compile: get type aliases working with generic types Generic types can the source type of a type alias, so modify g.typ0() to be able to deal with base generic types. Added test aliasimp.go that tests aliasing of local generic types and imported generic types. Change-Id: I1c398193819d47a36b014cc1f9bb55107e9a565b Reviewed-on: https://go-review.googlesource.com/c/go/+/322194 Trust: Dan Scales Trust: Robert Griesemer Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/noder/types.go | 45 ++++++++++++------------- test/typeparam/aliasimp.dir/a.go | 9 +++++ test/typeparam/aliasimp.dir/main.go | 38 +++++++++++++++++++++ test/typeparam/aliasimp.go | 7 ++++ 4 files changed, 76 insertions(+), 23 deletions(-) create mode 100644 test/typeparam/aliasimp.dir/a.go create mode 100644 test/typeparam/aliasimp.dir/main.go create mode 100644 test/typeparam/aliasimp.go diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index c6e97d4206..ae10e03a24 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -91,50 +91,49 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { case *types2.Basic: return g.basic(typ) case *types2.Named: - if typ.TParams() != nil { + // If tparams is set, but targs is not, typ is a base generic + // type. typ is appearing as part of the source type of an alias, + // since that is the only use of a generic type that doesn't + // involve instantiation. We just translate the named type in the + // normal way below using g.obj(). + if typ.TParams() != nil && typ.TArgs() != nil { // typ is an instantiation of a defined (named) generic type. // This instantiation should also be a defined (named) type. // types2 gives us the substituted type in t.Underlying() // The substituted type may or may not still have type // params. We might, for example, be substituting one type // param for another type param. - - if typ.TArgs() == nil { - base.Fatalf("In typ0, Targs should be set if TParams is set") - } - - // When converted to types.Type, typ must have a name, - // based on the names of the type arguments. We need a - // name to deal with recursive generic types (and it also - // looks better when printing types). + // + // When converted to types.Type, typ has a unique name, + // based on the names of the type arguments. instName := instTypeName2(typ.Obj().Name(), typ.TArgs()) s := g.pkg(typ.Obj().Pkg()).Lookup(instName) if s.Def != nil { - // We have already encountered this instantiation, - // so use the type we previously created, since there + // We have already encountered this instantiation. + // Use the type we previously created, since there // must be exactly one instance of a defined type. return s.Def.Type() } // Create a forwarding type first and put it in the g.typs - // map, in order to deal with recursive generic types. - // Fully set up the extra ntyp information (Def, RParams, - // which may set HasTParam) before translating the - // underlying type itself, so we handle recursion - // correctly, including via method signatures. + // map, in order to deal with recursive generic types + // (including via method signatures).. Set up the extra + // ntyp information (Def, RParams, which may set + // HasTParam) before translating the underlying type + // itself, so we handle recursion correctly. ntyp := typecheck.NewIncompleteNamedType(g.pos(typ.Obj().Pos()), s) g.typs[typ] = ntyp // If ntyp still has type params, then we must be // referencing something like 'value[T2]', as when - // specifying the generic receiver of a method, - // where value was defined as "type value[T any] - // ...". Save the type args, which will now be the - // new type of the current type. + // specifying the generic receiver of a method, where + // value was defined as "type value[T any] ...". Save the + // type args, which will now be the new typeparams of the + // current type. // // If ntyp does not have type params, we are saving the - // concrete types used to instantiate this type. We'll use - // these when instantiating the methods of the + // non-generic types used to instantiate this type. We'll + // use these when instantiating the methods of the // instantiated type. rparams := make([]*types.Type, len(typ.TArgs())) for i, targ := range typ.TArgs() { diff --git a/test/typeparam/aliasimp.dir/a.go b/test/typeparam/aliasimp.dir/a.go new file mode 100644 index 0000000000..3fac4aac98 --- /dev/null +++ b/test/typeparam/aliasimp.dir/a.go @@ -0,0 +1,9 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type Rimp[T any] struct { + F T +} diff --git a/test/typeparam/aliasimp.dir/main.go b/test/typeparam/aliasimp.dir/main.go new file mode 100644 index 0000000000..6638fa9454 --- /dev/null +++ b/test/typeparam/aliasimp.dir/main.go @@ -0,0 +1,38 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "a" + +type R[T any] struct { + F T +} + +type S = R + +type Sint = R[int] + +type Simp = a.Rimp + +type SimpString Simp[string] + +func main() { + var s S[int] + if s.F != 0 { + panic(s.F) + } + var s2 Sint + if s2.F != 0 { + panic(s2.F) + } + var s3 Simp[string] + if s3.F != "" { + panic(s3.F) + } + var s4 SimpString + if s4.F != "" { + panic(s4.F) + } +} diff --git a/test/typeparam/aliasimp.go b/test/typeparam/aliasimp.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/aliasimp.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From 4ed6317e735af24093b96077d1e813cc8b7dee6a Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sun, 16 May 2021 14:48:05 -0700 Subject: [PATCH 0138/2500] [dev.typeparams] cmd/compile: always generate (*T).M wrappers for instantiated methods Always generate (*T).M wrappers for instantiated methods, even when the instantiated method is being generated for another package (its source package) Added new function t.IsInstantiated() to check for fully-instantiated types (generic type instantiated with concrete types, hence concrete themselves). This function helps hide the representation of instantiated types outside of the types package. Added new export/import test setsimp.go that needs this change. Change-Id: Ifb700db8c9494e1684c93735edb20f4709be5f7f Reviewed-on: https://go-review.googlesource.com/c/go/+/322193 Trust: Dan Scales Trust: Robert Griesemer Reviewed-by: Robert Griesemer --- .../compile/internal/reflectdata/reflect.go | 8 +- src/cmd/compile/internal/types/type.go | 7 + test/typeparam/setsimp.dir/a.go | 128 ++++++++++++++ test/typeparam/setsimp.dir/main.go | 156 ++++++++++++++++++ test/typeparam/setsimp.go | 7 + 5 files changed, 303 insertions(+), 3 deletions(-) create mode 100644 test/typeparam/setsimp.dir/a.go create mode 100644 test/typeparam/setsimp.dir/main.go create mode 100644 test/typeparam/setsimp.go diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 3576a23db9..d452d4f194 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -956,7 +956,7 @@ func writeType(t *types.Type) *obj.LSym { // in the local package, even if they may be marked as part of // another package (the package of their base generic type). if tbase.Sym() != nil && tbase.Sym().Pkg != types.LocalPkg && - len(tbase.RParams()) == 0 { + !tbase.IsInstantiated() { if i := typecheck.BaseTypeIndex(t); i >= 0 { lsym.Pkg = tbase.Sym().Pkg.Prefix lsym.SymIdx = int32(i) @@ -1777,9 +1777,11 @@ func methodWrapper(rcvr *types.Type, method *types.Field) *obj.LSym { return lsym } - // Only generate (*T).M wrappers for T.M in T's own package. + // Only generate (*T).M wrappers for T.M in T's own package, except for + // instantiated methods. if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type && - rcvr.Elem().Sym() != nil && rcvr.Elem().Sym().Pkg != types.LocalPkg { + rcvr.Elem().Sym() != nil && rcvr.Elem().Sym().Pkg != types.LocalPkg && + !rcvr.Elem().IsInstantiated() { return lsym } diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index e7831121bf..08855f518c 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -279,6 +279,13 @@ func (t *Type) SetRParams(rparams []*Type) { } } +// IsInstantiated reports whether t is a fully instantiated generic type; i.e. an +// instantiated generic type where all type arguments are non-generic or fully +// instantiated generic types. +func (t *Type) IsInstantiated() bool { + return len(t.RParams()) > 0 && !t.HasTParam() +} + // NoPkg is a nil *Pkg value for clarity. // It's intended for use when constructing types that aren't exported // and thus don't need to be associated with any package. diff --git a/test/typeparam/setsimp.dir/a.go b/test/typeparam/setsimp.dir/a.go new file mode 100644 index 0000000000..92449ce956 --- /dev/null +++ b/test/typeparam/setsimp.dir/a.go @@ -0,0 +1,128 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +// SliceEqual reports whether two slices are equal: the same length and all +// elements equal. All floating point NaNs are considered equal. +func SliceEqual[Elem comparable](s1, s2 []Elem) bool { + if len(s1) != len(s2) { + return false + } + for i, v1 := range s1 { + v2 := s2[i] + if v1 != v2 { + isNaN := func(f Elem) bool { return f != f } + if !isNaN(v1) || !isNaN(v2) { + return false + } + } + } + return true +} + +// A Set is a set of elements of some type. +type Set[Elem comparable] struct { + m map[Elem]struct{} +} + +// Make makes a new set. +func Make[Elem comparable]() Set[Elem] { + return Set[Elem]{m: make(map[Elem]struct{})} +} + +// Add adds an element to a set. +func (s Set[Elem]) Add(v Elem) { + s.m[v] = struct{}{} +} + +// Delete removes an element from a set. If the element is not present +// in the set, this does nothing. +func (s Set[Elem]) Delete(v Elem) { + delete(s.m, v) +} + +// Contains reports whether v is in the set. +func (s Set[Elem]) Contains(v Elem) bool { + _, ok := s.m[v] + return ok +} + +// Len returns the number of elements in the set. +func (s Set[Elem]) Len() int { + return len(s.m) +} + +// Values returns the values in the set. +// The values will be in an indeterminate order. +func (s Set[Elem]) Values() []Elem { + r := make([]Elem, 0, len(s.m)) + for v := range s.m { + r = append(r, v) + } + return r +} + +// Equal reports whether two sets contain the same elements. +func Equal[Elem comparable](s1, s2 Set[Elem]) bool { + if len(s1.m) != len(s2.m) { + return false + } + for v1 := range s1.m { + if !s2.Contains(v1) { + return false + } + } + return true +} + +// Copy returns a copy of s. +func (s Set[Elem]) Copy() Set[Elem] { + r := Set[Elem]{m: make(map[Elem]struct{}, len(s.m))} + for v := range s.m { + r.m[v] = struct{}{} + } + return r +} + +// AddSet adds all the elements of s2 to s. +func (s Set[Elem]) AddSet(s2 Set[Elem]) { + for v := range s2.m { + s.m[v] = struct{}{} + } +} + +// SubSet removes all elements in s2 from s. +// Values in s2 that are not in s are ignored. +func (s Set[Elem]) SubSet(s2 Set[Elem]) { + for v := range s2.m { + delete(s.m, v) + } +} + +// Intersect removes all elements from s that are not present in s2. +// Values in s2 that are not in s are ignored. +func (s Set[Elem]) Intersect(s2 Set[Elem]) { + for v := range s.m { + if !s2.Contains(v) { + delete(s.m, v) + } + } +} + +// Iterate calls f on every element in the set. +func (s Set[Elem]) Iterate(f func(Elem)) { + for v := range s.m { + f(v) + } +} + +// Filter deletes any elements from s for which f returns false. +func (s Set[Elem]) Filter(f func(Elem) bool) { + for v := range s.m { + if !f(v) { + delete(s.m, v) + } + } +} diff --git a/test/typeparam/setsimp.dir/main.go b/test/typeparam/setsimp.dir/main.go new file mode 100644 index 0000000000..8fd1657143 --- /dev/null +++ b/test/typeparam/setsimp.dir/main.go @@ -0,0 +1,156 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "a" + "fmt" + "sort" +) + +func TestSet() { + s1 := a.Make[int]() + if got := s1.Len(); got != 0 { + panic(fmt.Sprintf("Len of empty set = %d, want 0", got)) + } + s1.Add(1) + s1.Add(1) + s1.Add(1) + if got := s1.Len(); got != 1 { + panic(fmt.Sprintf("(%v).Len() == %d, want 1", s1, got)) + } + s1.Add(2) + s1.Add(3) + s1.Add(4) + if got := s1.Len(); got != 4 { + panic(fmt.Sprintf("(%v).Len() == %d, want 4", s1, got)) + } + if !s1.Contains(1) { + panic(fmt.Sprintf("(%v).Contains(1) == false, want true", s1)) + } + if s1.Contains(5) { + panic(fmt.Sprintf("(%v).Contains(5) == true, want false", s1)) + } + vals := s1.Values() + sort.Ints(vals) + w1 := []int{1, 2, 3, 4} + if !a.SliceEqual(vals, w1) { + panic(fmt.Sprintf("(%v).Values() == %v, want %v", s1, vals, w1)) + } +} + +func TestEqual() { + s1 := a.Make[string]() + s2 := a.Make[string]() + if !a.Equal(s1, s2) { + panic(fmt.Sprintf("a.Equal(%v, %v) = false, want true", s1, s2)) + } + s1.Add("hello") + s1.Add("world") + if got := s1.Len(); got != 2 { + panic(fmt.Sprintf("(%v).Len() == %d, want 2", s1, got)) + } + if a.Equal(s1, s2) { + panic(fmt.Sprintf("a.Equal(%v, %v) = true, want false", s1, s2)) + } +} + +func TestCopy() { + s1 := a.Make[float64]() + s1.Add(0) + s2 := s1.Copy() + if !a.Equal(s1, s2) { + panic(fmt.Sprintf("a.Equal(%v, %v) = false, want true", s1, s2)) + } + s1.Add(1) + if a.Equal(s1, s2) { + panic(fmt.Sprintf("a.Equal(%v, %v) = true, want false", s1, s2)) + } +} + +func TestAddSet() { + s1 := a.Make[int]() + s1.Add(1) + s1.Add(2) + s2 := a.Make[int]() + s2.Add(2) + s2.Add(3) + s1.AddSet(s2) + if got := s1.Len(); got != 3 { + panic(fmt.Sprintf("(%v).Len() == %d, want 3", s1, got)) + } + s2.Add(1) + if !a.Equal(s1, s2) { + panic(fmt.Sprintf("a.Equal(%v, %v) = false, want true", s1, s2)) + } +} + +func TestSubSet() { + s1 := a.Make[int]() + s1.Add(1) + s1.Add(2) + s2 := a.Make[int]() + s2.Add(2) + s2.Add(3) + s1.SubSet(s2) + if got := s1.Len(); got != 1 { + panic(fmt.Sprintf("(%v).Len() == %d, want 1", s1, got)) + } + if vals, want := s1.Values(), []int{1}; !a.SliceEqual(vals, want) { + panic(fmt.Sprintf("after SubSet got %v, want %v", vals, want)) + } +} + +func TestIntersect() { + s1 := a.Make[int]() + s1.Add(1) + s1.Add(2) + s2 := a.Make[int]() + s2.Add(2) + s2.Add(3) + s1.Intersect(s2) + if got := s1.Len(); got != 1 { + panic(fmt.Sprintf("(%v).Len() == %d, want 1", s1, got)) + } + if vals, want := s1.Values(), []int{2}; !a.SliceEqual(vals, want) { + panic(fmt.Sprintf("after Intersect got %v, want %v", vals, want)) + } +} + +func TestIterate() { + s1 := a.Make[int]() + s1.Add(1) + s1.Add(2) + s1.Add(3) + s1.Add(4) + tot := 0 + s1.Iterate(func(i int) { tot += i }) + if tot != 10 { + panic(fmt.Sprintf("total of %v == %d, want 10", s1, tot)) + } +} + +func TestFilter() { + s1 := a.Make[int]() + s1.Add(1) + s1.Add(2) + s1.Add(3) + s1.Filter(func(v int) bool { return v%2 == 0 }) + if vals, want := s1.Values(), []int{2}; !a.SliceEqual(vals, want) { + panic(fmt.Sprintf("after Filter got %v, want %v", vals, want)) + } + +} + +func main() { + TestSet() + TestEqual() + TestCopy() + TestAddSet() + TestSubSet() + TestIntersect() + TestIterate() + TestFilter() +} diff --git a/test/typeparam/setsimp.go b/test/typeparam/setsimp.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/setsimp.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From cf23daeda3792eb2ba07c30823d5a0c8667f5083 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 25 May 2021 19:49:08 -0400 Subject: [PATCH 0139/2500] [dev.typeparams] cmd/compile: do not schedule in-register args late, even for block control In the scheduler we have the logic that if a Value is used as the block's control, we schedule it at the end, except for Phis and Args. Even the comment says so, the code doesn't exclude in-register Args (OpArgXXXReg). Change to check for score instead, which includes OpArgXXXRegs. It also includes GetClosurePtr, which must be scheduled early. We just happen to never use it as block control. Found when working on ARM64 register ABI. In theory this could apply to AMD64 as well. But on AMD64 we never use in-register Value as block control, as conditional branch is always based on FLAGS, never based on registers, so it doesn't actually cause any problem. Change-Id: I167a550309772639574f7468caf91bd805eb74c6 Reviewed-on: https://go-review.googlesource.com/c/go/+/322849 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh Reviewed-by: David Chase --- src/cmd/compile/internal/ssa/schedule.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/ssa/schedule.go b/src/cmd/compile/internal/ssa/schedule.go index 4e3e5e75e3..c5130b2ee5 100644 --- a/src/cmd/compile/internal/ssa/schedule.go +++ b/src/cmd/compile/internal/ssa/schedule.go @@ -220,7 +220,7 @@ func schedule(f *Func) { // unless they are phi values (which must be first). // OpArg also goes first -- if it is stack it register allocates // to a LoadReg, if it is register it is from the beginning anyway. - if c.Op == OpPhi || c.Op == OpArg { + if score[c.ID] == ScorePhi || score[c.ID] == ScoreArg { continue } score[c.ID] = ScoreControl -- GitLab From 4bb927f82e7d4661d287ec5e975ba6cbdee2ae90 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 25 May 2021 11:53:04 -0400 Subject: [PATCH 0140/2500] [dev.typeparams] cmd/compile: define ARM64 parameter registers Define the registers. They are not really enabled for now. Otherwise the compiler will start using them for go:registerparams functions and it is not fully working. Some test will fail. Now we can compile a simple Add function with registerparams (with registers enabled). Change-Id: Ifdfac931052c0196096a1dd8b0687b5fdedb14d5 Reviewed-on: https://go-review.googlesource.com/c/go/+/322850 Trust: Cherry Mui Reviewed-by: David Chase Reviewed-by: Than McIntosh --- src/cmd/compile/internal/arm64/ssa.go | 3 +++ src/cmd/compile/internal/ssa/config.go | 4 ++++ src/cmd/compile/internal/ssa/gen/ARM64Ops.go | 2 ++ src/cmd/compile/internal/ssa/opGen.go | 4 ++-- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/arm64/ssa.go b/src/cmd/compile/internal/arm64/ssa.go index 0c997bc4b3..ca76b18497 100644 --- a/src/cmd/compile/internal/arm64/ssa.go +++ b/src/cmd/compile/internal/arm64/ssa.go @@ -161,6 +161,9 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.From.Type = obj.TYPE_REG p.From.Reg = v.Args[0].Reg() ssagen.AddrAuto(&p.To, v) + case ssa.OpArgIntReg, ssa.OpArgFloatReg: + // TODO: generate morestack spill code + ssagen.CheckArgReg(v) case ssa.OpARM64ADD, ssa.OpARM64SUB, ssa.OpARM64AND, diff --git a/src/cmd/compile/internal/ssa/config.go b/src/cmd/compile/internal/ssa/config.go index a8393a1999..07d8b6e532 100644 --- a/src/cmd/compile/internal/ssa/config.go +++ b/src/cmd/compile/internal/ssa/config.go @@ -228,6 +228,10 @@ func NewConfig(arch string, types Types, ctxt *obj.Link, optimize bool) *Config c.registers = registersARM64[:] c.gpRegMask = gpRegMaskARM64 c.fpRegMask = fpRegMaskARM64 + // XXX commented out for now. Uncomment it will enable register args for + // go:registerparams functions, which isn't fully working, so tests fail. + //c.intParamRegs = paramIntRegARM64 + //c.floatParamRegs = paramFloatRegARM64 c.FPReg = framepointerRegARM64 c.LinkReg = linkRegARM64 c.hasGReg = true diff --git a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go index 18a5666b40..a91ece1c9f 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go @@ -765,6 +765,8 @@ func init() { ops: ops, blocks: blocks, regnames: regNamesARM64, + ParamIntRegNames: "R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15", + ParamFloatRegNames: "F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15", gpregmask: gp, fpregmask: fp, framepointerreg: -1, // not used diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 1c37fbe0db..cf31dfacf6 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -36400,8 +36400,8 @@ var registersARM64 = [...]Register{ {62, arm64.REG_F31, -1, "F31"}, {63, 0, -1, "SB"}, } -var paramIntRegARM64 = []int8(nil) -var paramFloatRegARM64 = []int8(nil) +var paramIntRegARM64 = []int8{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} +var paramFloatRegARM64 = []int8{31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46} var gpRegMaskARM64 = regMask(670826495) var fpRegMaskARM64 = regMask(9223372034707292160) var specialRegMaskARM64 = regMask(0) -- GitLab From a4b2a04bc50d568579f437f324d56471bf31ec6c Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 25 May 2021 18:08:36 -0400 Subject: [PATCH 0141/2500] [dev.typeparams] cmd/internal/obj/arm64: use ABI-compatible registers in function prologue Avoid using R1, R2, etc. in function prologue, which may carry live argument values. Change-Id: I80322b3f7e8fda7aaff622aaa99bc76d02e09727 Reviewed-on: https://go-review.googlesource.com/c/go/+/322852 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh Reviewed-by: David Chase --- src/cmd/internal/obj/arm64/obj7.go | 80 +++++++++++++++--------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/src/cmd/internal/obj/arm64/obj7.go b/src/cmd/internal/obj/arm64/obj7.go index e41fb3bb75..13966f7b86 100644 --- a/src/cmd/internal/obj/arm64/obj7.go +++ b/src/cmd/internal/obj/arm64/obj7.go @@ -52,7 +52,7 @@ var complements = []obj.As{ } func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { - // MOV g_stackguard(g), R1 + // MOV g_stackguard(g), RT1 p = obj.Appendp(p, c.newprog) p.As = AMOVD @@ -63,7 +63,7 @@ func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { p.From.Offset = 3 * int64(c.ctxt.Arch.PtrSize) // G.stackguard1 } p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R1 + p.To.Reg = REGRT1 // Mark the stack bound check and morestack call async nonpreemptible. // If we get preempted here, when resumed the preemption request is @@ -74,25 +74,25 @@ func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { q := (*obj.Prog)(nil) if framesize <= objabi.StackSmall { // small stack: SP < stackguard - // MOV SP, R2 - // CMP stackguard, R2 + // MOV SP, RT2 + // CMP stackguard, RT2 p = obj.Appendp(p, c.newprog) p.As = AMOVD p.From.Type = obj.TYPE_REG p.From.Reg = REGSP p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R2 + p.To.Reg = REGRT2 p = obj.Appendp(p, c.newprog) p.As = ACMP p.From.Type = obj.TYPE_REG - p.From.Reg = REG_R1 - p.Reg = REG_R2 + p.From.Reg = REGRT1 + p.Reg = REGRT2 } else if framesize <= objabi.StackBig { // large stack: SP-framesize < stackguard-StackSmall - // SUB $(framesize-StackSmall), SP, R2 - // CMP stackguard, R2 + // SUB $(framesize-StackSmall), SP, RT2 + // CMP stackguard, RT2 p = obj.Appendp(p, c.newprog) p.As = ASUB @@ -100,13 +100,13 @@ func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { p.From.Offset = int64(framesize) - objabi.StackSmall p.Reg = REGSP p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R2 + p.To.Reg = REGRT2 p = obj.Appendp(p, c.newprog) p.As = ACMP p.From.Type = obj.TYPE_REG - p.From.Reg = REG_R1 - p.Reg = REG_R2 + p.From.Reg = REGRT1 + p.Reg = REGRT2 } else { // Such a large stack we need to protect against underflow. // The runtime guarantees SP > objabi.StackBig, but @@ -115,10 +115,10 @@ func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { // stack guard to incorrectly succeed. We explicitly // guard against underflow. // - // SUBS $(framesize-StackSmall), SP, R2 + // SUBS $(framesize-StackSmall), SP, RT2 // // On underflow, jump to morestack // BLO label_of_call_to_morestack - // CMP stackguard, R2 + // CMP stackguard, RT2 p = obj.Appendp(p, c.newprog) p.As = ASUBS @@ -126,7 +126,7 @@ func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { p.From.Offset = int64(framesize) - objabi.StackSmall p.Reg = REGSP p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R2 + p.To.Reg = REGRT2 p = obj.Appendp(p, c.newprog) q = p @@ -136,8 +136,8 @@ func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { p = obj.Appendp(p, c.newprog) p.As = ACMP p.From.Type = obj.TYPE_REG - p.From.Reg = REG_R1 - p.Reg = REG_R2 + p.From.Reg = REGRT1 + p.Reg = REGRT2 } // BLS do-morestack @@ -631,38 +631,38 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { if c.cursym.Func().Text.From.Sym.Wrapper() { // if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame // - // MOV g_panic(g), R1 + // MOV g_panic(g), RT1 // CBNZ checkargp // end: // NOP // ... function body ... // checkargp: - // MOV panic_argp(R1), R2 - // ADD $(autosize+8), RSP, R3 - // CMP R2, R3 + // MOV panic_argp(RT1), RT2 + // ADD $(autosize+8), RSP, R20 + // CMP RT2, R20 // BNE end - // ADD $8, RSP, R4 - // MOVD R4, panic_argp(R1) + // ADD $8, RSP, R20 + // MOVD R20, panic_argp(RT1) // B end // // The NOP is needed to give the jumps somewhere to land. // It is a liblink NOP, not an ARM64 NOP: it encodes to 0 instruction bytes. q = q1 - // MOV g_panic(g), R1 + // MOV g_panic(g), RT1 q = obj.Appendp(q, c.newprog) q.As = AMOVD q.From.Type = obj.TYPE_MEM q.From.Reg = REGG q.From.Offset = 4 * int64(c.ctxt.Arch.PtrSize) // G.panic q.To.Type = obj.TYPE_REG - q.To.Reg = REG_R1 + q.To.Reg = REGRT1 - // CBNZ R1, checkargp + // CBNZ RT1, checkargp cbnz := obj.Appendp(q, c.newprog) cbnz.As = ACBNZ cbnz.From.Type = obj.TYPE_REG - cbnz.From.Reg = REG_R1 + cbnz.From.Reg = REGRT1 cbnz.To.Type = obj.TYPE_BRANCH // Empty branch target at the top of the function body @@ -674,33 +674,33 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { for last = end; last.Link != nil; last = last.Link { } - // MOV panic_argp(R1), R2 + // MOV panic_argp(RT1), RT2 mov := obj.Appendp(last, c.newprog) mov.As = AMOVD mov.From.Type = obj.TYPE_MEM - mov.From.Reg = REG_R1 + mov.From.Reg = REGRT1 mov.From.Offset = 0 // Panic.argp mov.To.Type = obj.TYPE_REG - mov.To.Reg = REG_R2 + mov.To.Reg = REGRT2 // CBNZ branches to the MOV above cbnz.To.SetTarget(mov) - // ADD $(autosize+8), SP, R3 + // ADD $(autosize+8), SP, R20 q = obj.Appendp(mov, c.newprog) q.As = AADD q.From.Type = obj.TYPE_CONST q.From.Offset = int64(c.autosize) + 8 q.Reg = REGSP q.To.Type = obj.TYPE_REG - q.To.Reg = REG_R3 + q.To.Reg = REG_R20 - // CMP R2, R3 + // CMP RT2, R20 q = obj.Appendp(q, c.newprog) q.As = ACMP q.From.Type = obj.TYPE_REG - q.From.Reg = REG_R2 - q.Reg = REG_R3 + q.From.Reg = REGRT2 + q.Reg = REG_R20 // BNE end q = obj.Appendp(q, c.newprog) @@ -708,22 +708,22 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { q.To.Type = obj.TYPE_BRANCH q.To.SetTarget(end) - // ADD $8, SP, R4 + // ADD $8, SP, R20 q = obj.Appendp(q, c.newprog) q.As = AADD q.From.Type = obj.TYPE_CONST q.From.Offset = 8 q.Reg = REGSP q.To.Type = obj.TYPE_REG - q.To.Reg = REG_R4 + q.To.Reg = REG_R20 - // MOV R4, panic_argp(R1) + // MOV R20, panic_argp(RT1) q = obj.Appendp(q, c.newprog) q.As = AMOVD q.From.Type = obj.TYPE_REG - q.From.Reg = REG_R4 + q.From.Reg = REG_R20 q.To.Type = obj.TYPE_MEM - q.To.Reg = REG_R1 + q.To.Reg = REGRT1 q.To.Offset = 0 // Panic.argp // B end -- GitLab From 4c68edd1feaad43e098dd7375d6c1cfc43243211 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 25 May 2021 18:40:28 -0400 Subject: [PATCH 0142/2500] [dev.typeparams] cmd/compile: add morestack arg spilling code on ARM64 Spill arg registers before calling morestack, and reload after. Change-Id: I09404def321b8f935d5e8836a46ccae8256d0d55 Reviewed-on: https://go-review.googlesource.com/c/go/+/322853 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: David Chase --- src/cmd/compile/internal/arm64/ssa.go | 11 ++++++++++- src/cmd/compile/internal/ssagen/ssa.go | 1 - src/cmd/internal/obj/arm64/obj7.go | 16 ++++++++++------ 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/internal/arm64/ssa.go b/src/cmd/compile/internal/arm64/ssa.go index ca76b18497..d82788218d 100644 --- a/src/cmd/compile/internal/arm64/ssa.go +++ b/src/cmd/compile/internal/arm64/ssa.go @@ -162,7 +162,16 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.From.Reg = v.Args[0].Reg() ssagen.AddrAuto(&p.To, v) case ssa.OpArgIntReg, ssa.OpArgFloatReg: - // TODO: generate morestack spill code + // The assembler needs to wrap the entry safepoint/stack growth code with spill/unspill + // The loop only runs once. + for _, a := range v.Block.Func.RegArgs { + // Pass the spill/unspill information along to the assembler, offset by size of + // the saved LR slot. + addr := ssagen.SpillSlotAddr(a, arm64.REGSP, base.Ctxt.FixedFrameSize()) + s.FuncInfo().AddSpill( + obj.RegSpill{Reg: a.Reg, Addr: addr, Unspill: loadByType(a.Type), Spill: storeByType(a.Type)}) + } + v.Block.Func.RegArgs = nil ssagen.CheckArgReg(v) case ssa.OpARM64ADD, ssa.OpARM64SUB, diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 004e084f72..91b0c79cd3 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -650,7 +650,6 @@ func buildssa(fn *ir.Func, worker int) *ssa.Func { // it mimics the behavior of the former ABI (everything stored) and because it's not 100% // clear if naming conventions are respected in autogenerated code. // TODO figure out exactly what's unused, don't spill it. Make liveness fine-grained, also. - // TODO non-amd64 architectures have link registers etc that may require adjustment here. for _, p := range params.InParams() { typs, offs := p.RegisterTypesAndOffsets() for i, t := range typs { diff --git a/src/cmd/internal/obj/arm64/obj7.go b/src/cmd/internal/obj/arm64/obj7.go index 13966f7b86..c94a0b67ee 100644 --- a/src/cmd/internal/obj/arm64/obj7.go +++ b/src/cmd/internal/obj/arm64/obj7.go @@ -161,17 +161,20 @@ func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { pcdata := c.ctxt.EmitEntryStackMap(c.cursym, spfix, c.newprog) pcdata = c.ctxt.StartUnsafePoint(pcdata, c.newprog) + if q != nil { + q.To.SetTarget(pcdata) + } + bls.To.SetTarget(pcdata) + + spill := c.cursym.Func().SpillRegisterArgs(pcdata, c.newprog) + // MOV LR, R3 - movlr := obj.Appendp(pcdata, c.newprog) + movlr := obj.Appendp(spill, c.newprog) movlr.As = AMOVD movlr.From.Type = obj.TYPE_REG movlr.From.Reg = REGLINK movlr.To.Type = obj.TYPE_REG movlr.To.Reg = REG_R3 - if q != nil { - q.To.SetTarget(movlr) - } - bls.To.SetTarget(movlr) debug := movlr if false { @@ -196,7 +199,8 @@ func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { } call.To.Sym = c.ctxt.Lookup(morestack) - pcdata = c.ctxt.EndUnsafePoint(call, c.newprog, -1) + unspill := c.cursym.Func().UnspillRegisterArgs(call, c.newprog) + pcdata = c.ctxt.EndUnsafePoint(unspill, c.newprog, -1) // B start jmp := obj.Appendp(pcdata, c.newprog) -- GitLab From e99e9a6e0147592b12175a19a2a9dafe96a984f9 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 26 May 2021 13:54:31 -0700 Subject: [PATCH 0143/2500] [dev.typeparams] cmd/compile: simplify ~r/~b naming The compiler renames anonymous and blank result parameters to ~rN or ~bN, but the current semantics for computing N are rather annoying and difficult to reproduce cleanly. They also lead to difficult to read escape analysis results in tests. This CL changes N to always be calculated as the parameter's index within the function's result parameter tuple. E.g., if a function has a single result, it will now always be named "~r0". The normative change to this CL is fairly simple, but it requires updating a lot of test expectations. Change-Id: I58a3c94de00cb822cb94efe52d115531193c993c Reviewed-on: https://go-review.googlesource.com/c/go/+/323010 Trust: Matthew Dempsky Trust: Dan Scales Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Dan Scales --- .../compile/internal/logopt/logopt_test.go | 4 +- src/cmd/compile/internal/noder/object.go | 22 +++++----- src/cmd/compile/internal/typecheck/dcl.go | 9 ++-- test/escape2.go | 44 +++++++++---------- test/escape2n.go | 44 +++++++++---------- test/escape5.go | 8 ++-- test/escape_array.go | 16 +++---- test/escape_calls.go | 2 +- test/escape_closure.go | 8 ++-- test/escape_param.go | 10 ++--- test/escape_runtime_atomic.go | 4 +- test/escape_slice.go | 4 +- test/escape_struct_return.go | 4 +- test/escape_unsafe.go | 10 ++--- test/fixedbugs/issue12006.go | 6 +-- test/fixedbugs/issue12588.go | 6 +-- test/fixedbugs/issue42284.dir/a.go | 2 +- 17 files changed, 101 insertions(+), 102 deletions(-) diff --git a/src/cmd/compile/internal/logopt/logopt_test.go b/src/cmd/compile/internal/logopt/logopt_test.go index 71976174b0..41a11b0c70 100644 --- a/src/cmd/compile/internal/logopt/logopt_test.go +++ b/src/cmd/compile/internal/logopt/logopt_test.go @@ -209,7 +209,7 @@ func s15a8(x *[15]int64) [15]int64 { want(t, slogged, `{"range":{"start":{"line":11,"character":6},"end":{"line":11,"character":6}},"severity":3,"code":"isInBounds","source":"go compiler","message":""}`) want(t, slogged, `{"range":{"start":{"line":7,"character":6},"end":{"line":7,"character":6}},"severity":3,"code":"canInlineFunction","source":"go compiler","message":"cost: 35"}`) // escape analysis explanation - want(t, slogged, `{"range":{"start":{"line":7,"character":13},"end":{"line":7,"character":13}},"severity":3,"code":"leak","source":"go compiler","message":"parameter z leaks to ~r2 with derefs=0",`+ + want(t, slogged, `{"range":{"start":{"line":7,"character":13},"end":{"line":7,"character":13}},"severity":3,"code":"leak","source":"go compiler","message":"parameter z leaks to ~r0 with derefs=0",`+ `"relatedInformation":[`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: flow: y = z:"},`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from y := z (assign-pair)"},`+ @@ -220,7 +220,7 @@ func s15a8(x *[15]int64) [15]int64 { `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from \u0026y.b (address-of)"},`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":4,"character":9},"end":{"line":4,"character":9}}},"message":"inlineLoc"},`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from ~R0 = \u0026y.b (assign-pair)"},`+ - `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":3},"end":{"line":9,"character":3}}},"message":"escflow: flow: ~r2 = ~R0:"},`+ + `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":3},"end":{"line":9,"character":3}}},"message":"escflow: flow: ~r0 = ~R0:"},`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":3},"end":{"line":9,"character":3}}},"message":"escflow: from return (*int)(~R0) (return)"}]}`) }) } diff --git a/src/cmd/compile/internal/noder/object.go b/src/cmd/compile/internal/noder/object.go index a1a10e4eaa..581a3652ec 100644 --- a/src/cmd/compile/internal/noder/object.go +++ b/src/cmd/compile/internal/noder/object.go @@ -113,19 +113,21 @@ func (g *irgen) obj(obj types2.Object) *ir.Name { } case *types2.Var: - var sym *types.Sym - if class == ir.PPARAMOUT { + sym := g.sym(obj) + if class == ir.PPARAMOUT && (sym == nil || sym.IsBlank()) { // Backend needs names for result parameters, // even if they're anonymous or blank. - switch obj.Name() { - case "": - sym = typecheck.LookupNum("~r", len(ir.CurFunc.Dcl)) // 'r' for "result" - case "_": - sym = typecheck.LookupNum("~b", len(ir.CurFunc.Dcl)) // 'b' for "blank" + nresults := 0 + for _, n := range ir.CurFunc.Dcl { + if n.Class == ir.PPARAMOUT { + nresults++ + } + } + if sym == nil { + sym = typecheck.LookupNum("~r", nresults) // 'r' for "result" + } else { + sym = typecheck.LookupNum("~b", nresults) // 'b' for "blank" } - } - if sym == nil { - sym = g.sym(obj) } name = g.objCommon(pos, ir.ONAME, sym, class, g.typ(obj.Type())) diff --git a/src/cmd/compile/internal/typecheck/dcl.go b/src/cmd/compile/internal/typecheck/dcl.go index f3058d8811..5f8b8b3d41 100644 --- a/src/cmd/compile/internal/typecheck/dcl.go +++ b/src/cmd/compile/internal/typecheck/dcl.go @@ -353,12 +353,10 @@ func funcargs(nt *ir.FuncType) { } // declare the out arguments. - gen := len(nt.Params) - for _, n := range nt.Results { + for i, n := range nt.Results { if n.Sym == nil { // Name so that escape analysis can track it. ~r stands for 'result'. - n.Sym = LookupNum("~r", gen) - gen++ + n.Sym = LookupNum("~r", i) } if n.Sym.IsBlank() { // Give it a name so we can assign to it during return. ~b stands for 'blank'. @@ -367,8 +365,7 @@ func funcargs(nt *ir.FuncType) { // func g() int // f is allowed to use a plain 'return' with no arguments, while g is not. // So the two cases must be distinguished. - n.Sym = LookupNum("~b", gen) - gen++ + n.Sym = LookupNum("~b", i) } funcarg(n, ir.PPARAMOUT) diff --git a/test/escape2.go b/test/escape2.go index b9b723d866..04ab635aa5 100644 --- a/test/escape2.go +++ b/test/escape2.go @@ -59,7 +59,7 @@ func foo8(xx, yy *int) int { // ERROR "xx does not escape$" "yy does not escape$ return *xx } -func foo9(xx, yy *int) *int { // ERROR "leaking param: xx to result ~r2 level=0$" "leaking param: yy to result ~r2 level=0$" +func foo9(xx, yy *int) *int { // ERROR "leaking param: xx to result ~r0 level=0$" "leaking param: yy to result ~r0 level=0$" xx = yy return xx } @@ -343,11 +343,11 @@ func indaddr1(x int) *int { // ERROR "moved to heap: x$" return &x } -func indaddr2(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$" +func indaddr2(x *int) *int { // ERROR "leaking param: x to result ~r0 level=0$" return *&x } -func indaddr3(x *int32) *int { // ERROR "leaking param: x to result ~r1 level=0$" +func indaddr3(x *int32) *int { // ERROR "leaking param: x to result ~r0 level=0$" return *(**int)(unsafe.Pointer(&x)) } @@ -374,11 +374,11 @@ func float64bitsptr(f float64) *uint64 { // ERROR "moved to heap: f$" return (*uint64)(unsafe.Pointer(&f)) } -func float64ptrbitsptr(f *float64) *uint64 { // ERROR "leaking param: f to result ~r1 level=0$" +func float64ptrbitsptr(f *float64) *uint64 { // ERROR "leaking param: f to result ~r0 level=0$" return (*uint64)(unsafe.Pointer(f)) } -func typesw(i interface{}) *int { // ERROR "leaking param: i to result ~r1 level=0$" +func typesw(i interface{}) *int { // ERROR "leaking param: i to result ~r0 level=0$" switch val := i.(type) { case *int: return val @@ -389,7 +389,7 @@ func typesw(i interface{}) *int { // ERROR "leaking param: i to result ~r1 level return nil } -func exprsw(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$" +func exprsw(i *int) *int { // ERROR "leaking param: i to result ~r0 level=0$" switch j := i; *j + 110 { case 12: return j @@ -401,7 +401,7 @@ func exprsw(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$" } // assigning to an array element is like assigning to the array -func foo60(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$" +func foo60(i *int) *int { // ERROR "leaking param: i to result ~r0 level=0$" var a [12]*int a[0] = i return a[1] @@ -414,7 +414,7 @@ func foo60a(i *int) *int { // ERROR "i does not escape$" } // assigning to a struct field is like assigning to the struct -func foo61(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$" +func foo61(i *int) *int { // ERROR "leaking param: i to result ~r0 level=0$" type S struct { a, b *int } @@ -611,11 +611,11 @@ func foo74c() { } } -func myprint(y *int, x ...interface{}) *int { // ERROR "leaking param: y to result ~r2 level=0$" "x does not escape$" +func myprint(y *int, x ...interface{}) *int { // ERROR "leaking param: y to result ~r0 level=0$" "x does not escape$" return y } -func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "leaking param: x to result ~r2 level=0$" "y does not escape$" +func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "leaking param: x to result ~r0 level=0$" "y does not escape$" return &x[0] } @@ -770,7 +770,7 @@ func foo91(x *int) map[*int]*int { // ERROR "leaking param: x$" return map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int{...} escapes to heap$" } -func foo92(x *int) [2]*int { // ERROR "leaking param: x to result ~r1 level=0$" +func foo92(x *int) [2]*int { // ERROR "leaking param: x to result ~r0 level=0$" return [2]*int{x, nil} } @@ -783,7 +783,7 @@ func foo93(c chan *int) *int { // ERROR "c does not escape$" } // does not leak m -func foo94(m map[*int]*int, b bool) *int { // ERROR "leaking param: m to result ~r2 level=1" +func foo94(m map[*int]*int, b bool) *int { // ERROR "leaking param: m to result ~r0 level=1" for k, v := range m { if b { return k @@ -799,12 +799,12 @@ func foo95(m map[*int]*int, x *int) { // ERROR "m does not escape$" "leaking par } // does not leak m but does leak content -func foo96(m []*int) *int { // ERROR "leaking param: m to result ~r1 level=1" +func foo96(m []*int) *int { // ERROR "leaking param: m to result ~r0 level=1" return m[0] } // does leak m -func foo97(m [1]*int) *int { // ERROR "leaking param: m to result ~r1 level=0$" +func foo97(m [1]*int) *int { // ERROR "leaking param: m to result ~r0 level=0$" return m[0] } @@ -814,12 +814,12 @@ func foo98(m map[int]*int) *int { // ERROR "m does not escape$" } // does leak m -func foo99(m *[1]*int) []*int { // ERROR "leaking param: m to result ~r1 level=0$" +func foo99(m *[1]*int) []*int { // ERROR "leaking param: m to result ~r0 level=0$" return m[:] } // does not leak m -func foo100(m []*int) *int { // ERROR "leaking param: m to result ~r1 level=1" +func foo100(m []*int) *int { // ERROR "leaking param: m to result ~r0 level=1" for _, v := range m { return v } @@ -827,7 +827,7 @@ func foo100(m []*int) *int { // ERROR "leaking param: m to result ~r1 level=1" } // does leak m -func foo101(m [1]*int) *int { // ERROR "leaking param: m to result ~r1 level=0$" +func foo101(m [1]*int) *int { // ERROR "leaking param: m to result ~r0 level=0$" for _, v := range m { return v } @@ -890,27 +890,27 @@ func foo110(x *int) *int { // ERROR "leaking param: x$" return m[nil] } -func foo111(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0" +func foo111(x *int) *int { // ERROR "leaking param: x to result ~r0 level=0" m := []*int{x} // ERROR "\[\]\*int{...} does not escape$" return m[0] } -func foo112(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$" +func foo112(x *int) *int { // ERROR "leaking param: x to result ~r0 level=0$" m := [1]*int{x} return m[0] } -func foo113(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$" +func foo113(x *int) *int { // ERROR "leaking param: x to result ~r0 level=0$" m := Bar{ii: x} return m.ii } -func foo114(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$" +func foo114(x *int) *int { // ERROR "leaking param: x to result ~r0 level=0$" m := &Bar{ii: x} // ERROR "&Bar{...} does not escape$" return m.ii } -func foo115(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$" +func foo115(x *int) *int { // ERROR "leaking param: x to result ~r0 level=0$" return (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(x)) + 1)) } diff --git a/test/escape2n.go b/test/escape2n.go index 7c8208aa73..01a25795f4 100644 --- a/test/escape2n.go +++ b/test/escape2n.go @@ -59,7 +59,7 @@ func foo8(xx, yy *int) int { // ERROR "xx does not escape$" "yy does not escape$ return *xx } -func foo9(xx, yy *int) *int { // ERROR "leaking param: xx to result ~r2 level=0$" "leaking param: yy to result ~r2 level=0$" +func foo9(xx, yy *int) *int { // ERROR "leaking param: xx to result ~r0 level=0$" "leaking param: yy to result ~r0 level=0$" xx = yy return xx } @@ -343,11 +343,11 @@ func indaddr1(x int) *int { // ERROR "moved to heap: x$" return &x } -func indaddr2(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$" +func indaddr2(x *int) *int { // ERROR "leaking param: x to result ~r0 level=0$" return *&x } -func indaddr3(x *int32) *int { // ERROR "leaking param: x to result ~r1 level=0$" +func indaddr3(x *int32) *int { // ERROR "leaking param: x to result ~r0 level=0$" return *(**int)(unsafe.Pointer(&x)) } @@ -374,11 +374,11 @@ func float64bitsptr(f float64) *uint64 { // ERROR "moved to heap: f$" return (*uint64)(unsafe.Pointer(&f)) } -func float64ptrbitsptr(f *float64) *uint64 { // ERROR "leaking param: f to result ~r1 level=0$" +func float64ptrbitsptr(f *float64) *uint64 { // ERROR "leaking param: f to result ~r0 level=0$" return (*uint64)(unsafe.Pointer(f)) } -func typesw(i interface{}) *int { // ERROR "leaking param: i to result ~r1 level=0$" +func typesw(i interface{}) *int { // ERROR "leaking param: i to result ~r0 level=0$" switch val := i.(type) { case *int: return val @@ -389,7 +389,7 @@ func typesw(i interface{}) *int { // ERROR "leaking param: i to result ~r1 level return nil } -func exprsw(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$" +func exprsw(i *int) *int { // ERROR "leaking param: i to result ~r0 level=0$" switch j := i; *j + 110 { case 12: return j @@ -401,7 +401,7 @@ func exprsw(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$" } // assigning to an array element is like assigning to the array -func foo60(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$" +func foo60(i *int) *int { // ERROR "leaking param: i to result ~r0 level=0$" var a [12]*int a[0] = i return a[1] @@ -414,7 +414,7 @@ func foo60a(i *int) *int { // ERROR "i does not escape$" } // assigning to a struct field is like assigning to the struct -func foo61(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$" +func foo61(i *int) *int { // ERROR "leaking param: i to result ~r0 level=0$" type S struct { a, b *int } @@ -611,11 +611,11 @@ func foo74c() { } } -func myprint(y *int, x ...interface{}) *int { // ERROR "leaking param: y to result ~r2 level=0$" "x does not escape$" +func myprint(y *int, x ...interface{}) *int { // ERROR "leaking param: y to result ~r0 level=0$" "x does not escape$" return y } -func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "leaking param: x to result ~r2 level=0$" "y does not escape$" +func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "leaking param: x to result ~r0 level=0$" "y does not escape$" return &x[0] } @@ -770,7 +770,7 @@ func foo91(x *int) map[*int]*int { // ERROR "leaking param: x$" return map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int{...} escapes to heap$" } -func foo92(x *int) [2]*int { // ERROR "leaking param: x to result ~r1 level=0$" +func foo92(x *int) [2]*int { // ERROR "leaking param: x to result ~r0 level=0$" return [2]*int{x, nil} } @@ -783,7 +783,7 @@ func foo93(c chan *int) *int { // ERROR "c does not escape$" } // does not leak m -func foo94(m map[*int]*int, b bool) *int { // ERROR "leaking param: m to result ~r2 level=1" +func foo94(m map[*int]*int, b bool) *int { // ERROR "leaking param: m to result ~r0 level=1" for k, v := range m { if b { return k @@ -799,12 +799,12 @@ func foo95(m map[*int]*int, x *int) { // ERROR "m does not escape$" "leaking par } // does not leak m but does leak content -func foo96(m []*int) *int { // ERROR "leaking param: m to result ~r1 level=1" +func foo96(m []*int) *int { // ERROR "leaking param: m to result ~r0 level=1" return m[0] } // does leak m -func foo97(m [1]*int) *int { // ERROR "leaking param: m to result ~r1 level=0$" +func foo97(m [1]*int) *int { // ERROR "leaking param: m to result ~r0 level=0$" return m[0] } @@ -814,12 +814,12 @@ func foo98(m map[int]*int) *int { // ERROR "m does not escape$" } // does leak m -func foo99(m *[1]*int) []*int { // ERROR "leaking param: m to result ~r1 level=0$" +func foo99(m *[1]*int) []*int { // ERROR "leaking param: m to result ~r0 level=0$" return m[:] } // does not leak m -func foo100(m []*int) *int { // ERROR "leaking param: m to result ~r1 level=1" +func foo100(m []*int) *int { // ERROR "leaking param: m to result ~r0 level=1" for _, v := range m { return v } @@ -827,7 +827,7 @@ func foo100(m []*int) *int { // ERROR "leaking param: m to result ~r1 level=1" } // does leak m -func foo101(m [1]*int) *int { // ERROR "leaking param: m to result ~r1 level=0$" +func foo101(m [1]*int) *int { // ERROR "leaking param: m to result ~r0 level=0$" for _, v := range m { return v } @@ -890,27 +890,27 @@ func foo110(x *int) *int { // ERROR "leaking param: x$" return m[nil] } -func foo111(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0" +func foo111(x *int) *int { // ERROR "leaking param: x to result ~r0 level=0" m := []*int{x} // ERROR "\[\]\*int{...} does not escape$" return m[0] } -func foo112(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$" +func foo112(x *int) *int { // ERROR "leaking param: x to result ~r0 level=0$" m := [1]*int{x} return m[0] } -func foo113(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$" +func foo113(x *int) *int { // ERROR "leaking param: x to result ~r0 level=0$" m := Bar{ii: x} return m.ii } -func foo114(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$" +func foo114(x *int) *int { // ERROR "leaking param: x to result ~r0 level=0$" m := &Bar{ii: x} // ERROR "&Bar{...} does not escape$" return m.ii } -func foo115(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$" +func foo115(x *int) *int { // ERROR "leaking param: x to result ~r0 level=0$" return (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(x)) + 1)) } diff --git a/test/escape5.go b/test/escape5.go index 82be2c38e7..73acfb46a9 100644 --- a/test/escape5.go +++ b/test/escape5.go @@ -22,19 +22,19 @@ func leaktoret(p *int) *int { // ERROR "leaking param: p to result" return p } -func leaktoret2(p *int) (*int, *int) { // ERROR "leaking param: p to result ~r1" "leaking param: p to result ~r2" +func leaktoret2(p *int) (*int, *int) { // ERROR "leaking param: p to result ~r0" "leaking param: p to result ~r1" return p, p } -func leaktoret22(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r2" "leaking param: q to result ~r3" +func leaktoret22(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r0" "leaking param: q to result ~r1" return p, q } -func leaktoret22b(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r3" "leaking param: q to result ~r2" +func leaktoret22b(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r1" "leaking param: q to result ~r0" return leaktoret22(q, p) } -func leaktoret22c(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r3" "leaking param: q to result ~r2" +func leaktoret22c(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r1" "leaking param: q to result ~r0" r, s := leaktoret22(q, p) return r, s } diff --git a/test/escape_array.go b/test/escape_array.go index 0d07fd861f..83062c9436 100644 --- a/test/escape_array.go +++ b/test/escape_array.go @@ -12,15 +12,15 @@ var Ssink *string type U [2]*string -func bar(a, b *string) U { // ERROR "leaking param: a to result ~r2 level=0$" "leaking param: b to result ~r2 level=0$" +func bar(a, b *string) U { // ERROR "leaking param: a to result ~r0 level=0$" "leaking param: b to result ~r0 level=0$" return U{a, b} } -func foo(x U) U { // ERROR "leaking param: x to result ~r1 level=0$" +func foo(x U) U { // ERROR "leaking param: x to result ~r0 level=0$" return U{x[1], x[0]} } -func bff(a, b *string) U { // ERROR "leaking param: a to result ~r2 level=0$" "leaking param: b to result ~r2 level=0$" +func bff(a, b *string) U { // ERROR "leaking param: a to result ~r0 level=0$" "leaking param: b to result ~r0 level=0$" return foo(foo(bar(a, b))) } @@ -41,27 +41,27 @@ func tbff2() *string { return u[1] } -func car(x U) *string { // ERROR "leaking param: x to result ~r1 level=0$" +func car(x U) *string { // ERROR "leaking param: x to result ~r0 level=0$" return x[0] } // BAD: need fine-grained analysis to track x[0] and x[1] differently. -func fun(x U, y *string) *string { // ERROR "leaking param: x to result ~r2 level=0$" "leaking param: y to result ~r2 level=0$" +func fun(x U, y *string) *string { // ERROR "leaking param: x to result ~r0 level=0$" "leaking param: y to result ~r0 level=0$" x[0] = y return x[1] } -func fup(x *U, y *string) *string { // ERROR "leaking param: x to result ~r2 level=1$" "leaking param: y$" +func fup(x *U, y *string) *string { // ERROR "leaking param: x to result ~r0 level=1$" "leaking param: y$" x[0] = y // leaking y to heap is intended return x[1] } -func fum(x *U, y **string) *string { // ERROR "leaking param: x to result ~r2 level=1$" "leaking param content: y$" +func fum(x *U, y **string) *string { // ERROR "leaking param: x to result ~r0 level=1$" "leaking param content: y$" x[0] = *y return x[1] } -func fuo(x *U, y *U) *string { // ERROR "leaking param: x to result ~r2 level=1$" "leaking param content: y$" +func fuo(x *U, y *U) *string { // ERROR "leaking param: x to result ~r0 level=1$" "leaking param content: y$" x[0] = y[0] return x[1] } diff --git a/test/escape_calls.go b/test/escape_calls.go index 9e1db5426e..aa7c7f516c 100644 --- a/test/escape_calls.go +++ b/test/escape_calls.go @@ -11,7 +11,7 @@ package foo -func f(buf []byte) []byte { // ERROR "leaking param: buf to result ~r1 level=0$" +func f(buf []byte) []byte { // ERROR "leaking param: buf to result ~r0 level=0$" return buf } diff --git a/test/escape_closure.go b/test/escape_closure.go index 9152319fe0..bd6c025476 100644 --- a/test/escape_closure.go +++ b/test/escape_closure.go @@ -44,7 +44,7 @@ func ClosureCallArgs3() { func ClosureCallArgs4() { x := 0 - _ = func(p *int) *int { // ERROR "leaking param: p to result ~r1" "func literal does not escape" + _ = func(p *int) *int { // ERROR "leaking param: p to result ~r0" "func literal does not escape" return p }(&x) } @@ -111,7 +111,7 @@ func ClosureCallArgs11() { func ClosureCallArgs12() { x := 0 - defer func(p *int) *int { // ERROR "leaking param: p to result ~r1" "func literal does not escape" + defer func(p *int) *int { // ERROR "leaking param: p to result ~r0" "func literal does not escape" return p }(&x) } @@ -126,7 +126,7 @@ func ClosureCallArgs13() { func ClosureCallArgs14() { x := 0 p := &x - _ = func(p **int) *int { // ERROR "leaking param: p to result ~r1 level=1" "func literal does not escape" + _ = func(p **int) *int { // ERROR "leaking param: p to result ~r0 level=1" "func literal does not escape" return *p }(&p) } @@ -145,7 +145,7 @@ func ClosureLeak1(s string) string { // ERROR "s does not escape" } // See #14409 -- returning part of captured var leaks it. -func ClosureLeak1a(a ...string) string { // ERROR "leaking param: a to result ~r1 level=1$" +func ClosureLeak1a(a ...string) string { // ERROR "leaking param: a to result ~r0 level=1$" return func() string { // ERROR "func literal does not escape" return a[0] }() diff --git a/test/escape_param.go b/test/escape_param.go index dc93f689cf..b630bae88f 100644 --- a/test/escape_param.go +++ b/test/escape_param.go @@ -16,7 +16,7 @@ func zero() int { return 0 } var sink interface{} // in -> out -func param0(p *int) *int { // ERROR "leaking param: p to result ~r1" +func param0(p *int) *int { // ERROR "leaking param: p to result ~r0" return p } @@ -31,7 +31,7 @@ func caller0b() { } // in, in -> out, out -func param1(p1, p2 *int) (*int, *int) { // ERROR "leaking param: p1 to result ~r2" "leaking param: p2 to result ~r3" +func param1(p1, p2 *int) (*int, *int) { // ERROR "leaking param: p1 to result ~r0" "leaking param: p2 to result ~r1" return p1, p2 } @@ -222,7 +222,7 @@ func caller8() { } // *in -> out -func param9(p ***int) **int { // ERROR "leaking param: p to result ~r1 level=1" +func param9(p ***int) **int { // ERROR "leaking param: p to result ~r0 level=1" return *p } @@ -241,7 +241,7 @@ func caller9b() { } // **in -> out -func param10(p ***int) *int { // ERROR "leaking param: p to result ~r1 level=2" +func param10(p ***int) *int { // ERROR "leaking param: p to result ~r0 level=2" return **p } @@ -436,6 +436,6 @@ func param14a(x [4]*int) interface{} { // ERROR "leaking param: x$" // Convert to a direct interface, does not need an allocation. // So x only leaks to result. -func param14b(x *int) interface{} { // ERROR "leaking param: x to result ~r1 level=0" +func param14b(x *int) interface{} { // ERROR "leaking param: x to result ~r0 level=0" return x } diff --git a/test/escape_runtime_atomic.go b/test/escape_runtime_atomic.go index 62e8fede27..30d1d0c0c1 100644 --- a/test/escape_runtime_atomic.go +++ b/test/escape_runtime_atomic.go @@ -13,8 +13,8 @@ import ( "unsafe" ) -// BAD: should always be "leaking param: addr to result ~r1 level=1$". -func Loadp(addr unsafe.Pointer) unsafe.Pointer { // ERROR "leaking param: addr( to result ~r1 level=1)?$" +// BAD: should always be "leaking param: addr to result ~r0 level=1$". +func Loadp(addr unsafe.Pointer) unsafe.Pointer { // ERROR "leaking param: addr( to result ~r0 level=1)?$" return atomic.Loadp(addr) } diff --git a/test/escape_slice.go b/test/escape_slice.go index d60414736c..055b60be41 100644 --- a/test/escape_slice.go +++ b/test/escape_slice.go @@ -101,7 +101,7 @@ func slice11() { _ = s } -func slice12(x []int) *[1]int { // ERROR "leaking param: x to result ~r1 level=0$" +func slice12(x []int) *[1]int { // ERROR "leaking param: x to result ~r0 level=0$" return (*[1]int)(x) } @@ -110,7 +110,7 @@ func envForDir(dir string) []string { // ERROR "dir does not escape" return mergeEnvLists([]string{"PWD=" + dir}, env) // ERROR ".PWD=. \+ dir escapes to heap" "\[\]string{...} does not escape" } -func mergeEnvLists(in, out []string) []string { // ERROR "leaking param content: in" "leaking param content: out" "leaking param: out to result ~r2 level=0" +func mergeEnvLists(in, out []string) []string { // ERROR "leaking param content: in" "leaking param content: out" "leaking param: out to result ~r0 level=0" NextVar: for _, inkv := range in { k := strings.SplitAfterN(inkv, "=", 2)[0] diff --git a/test/escape_struct_return.go b/test/escape_struct_return.go index 222ef8bc22..a42ae1e8c9 100644 --- a/test/escape_struct_return.go +++ b/test/escape_struct_return.go @@ -15,11 +15,11 @@ type U struct { _spp **string } -func A(sp *string, spp **string) U { // ERROR "leaking param: sp to result ~r2 level=0$" "leaking param: spp to result ~r2 level=0$" +func A(sp *string, spp **string) U { // ERROR "leaking param: sp to result ~r0 level=0$" "leaking param: spp to result ~r0 level=0$" return U{sp, spp} } -func B(spp **string) U { // ERROR "leaking param: spp to result ~r1 level=0$" +func B(spp **string) U { // ERROR "leaking param: spp to result ~r0 level=0$" return U{*spp, spp} } diff --git a/test/escape_unsafe.go b/test/escape_unsafe.go index b34beacccb..cec6674a14 100644 --- a/test/escape_unsafe.go +++ b/test/escape_unsafe.go @@ -15,7 +15,7 @@ import ( // (1) Conversion of a *T1 to Pointer to *T2. -func convert(p *float64) *uint64 { // ERROR "leaking param: p to result ~r1 level=0$" +func convert(p *float64) *uint64 { // ERROR "leaking param: p to result ~r0 level=0$" return (*uint64)(unsafe.Pointer(p)) } @@ -39,12 +39,12 @@ func arithMask() unsafe.Pointer { // (5) Conversion of the result of reflect.Value.Pointer or // reflect.Value.UnsafeAddr from uintptr to Pointer. -// BAD: should be "leaking param: p to result ~r1 level=0$" +// BAD: should be "leaking param: p to result ~r0 level=0$" func valuePointer(p *int) unsafe.Pointer { // ERROR "leaking param: p$" return unsafe.Pointer(reflect.ValueOf(p).Pointer()) } -// BAD: should be "leaking param: p to result ~r1 level=0$" +// BAD: should be "leaking param: p to result ~r0 level=0$" func valueUnsafeAddr(p *int) unsafe.Pointer { // ERROR "leaking param: p$" return unsafe.Pointer(reflect.ValueOf(p).Elem().UnsafeAddr()) } @@ -52,11 +52,11 @@ func valueUnsafeAddr(p *int) unsafe.Pointer { // ERROR "leaking param: p$" // (6) Conversion of a reflect.SliceHeader or reflect.StringHeader // Data field to or from Pointer. -func fromSliceData(s []int) unsafe.Pointer { // ERROR "leaking param: s to result ~r1 level=0$" +func fromSliceData(s []int) unsafe.Pointer { // ERROR "leaking param: s to result ~r0 level=0$" return unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&s)).Data) } -func fromStringData(s string) unsafe.Pointer { // ERROR "leaking param: s to result ~r1 level=0$" +func fromStringData(s string) unsafe.Pointer { // ERROR "leaking param: s to result ~r0 level=0$" return unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&s)).Data) } diff --git a/test/fixedbugs/issue12006.go b/test/fixedbugs/issue12006.go index 0a2ef8dad0..e878bc48e2 100644 --- a/test/fixedbugs/issue12006.go +++ b/test/fixedbugs/issue12006.go @@ -87,7 +87,7 @@ func TFooI() { FooI(a, b, c) // ERROR "a escapes to heap" "b escapes to heap" "... argument does not escape" } -func FooJ(args ...interface{}) *int32 { // ERROR "leaking param: args to result ~r1 level=1" +func FooJ(args ...interface{}) *int32 { // ERROR "leaking param: args to result ~r0 level=1" for i := 0; i < len(args); i++ { switch x := args[i].(type) { case nil: @@ -123,7 +123,7 @@ type fakeSlice struct { a *[4]interface{} } -func FooK(args fakeSlice) *int32 { // ERROR "leaking param: args to result ~r1 level=1" +func FooK(args fakeSlice) *int32 { // ERROR "leaking param: args to result ~r0 level=1" for i := 0; i < args.l; i++ { switch x := (*args.a)[i].(type) { case nil: @@ -148,7 +148,7 @@ func TFooK2() { isink = FooK(fs) } -func FooL(args []interface{}) *int32 { // ERROR "leaking param: args to result ~r1 level=1" +func FooL(args []interface{}) *int32 { // ERROR "leaking param: args to result ~r0 level=1" for i := 0; i < len(args); i++ { switch x := args[i].(type) { case nil: diff --git a/test/fixedbugs/issue12588.go b/test/fixedbugs/issue12588.go index 950ef36e20..dc8111198c 100644 --- a/test/fixedbugs/issue12588.go +++ b/test/fixedbugs/issue12588.go @@ -35,7 +35,7 @@ func g(a *A) int { // ERROR "a does not escape" return 0 } -func h(a *B) *uint64 { // ERROR "leaking param: a to result ~r1 level=1" +func h(a *B) *uint64 { // ERROR "leaking param: a to result ~r0 level=1" for i, x := range &a.b { if i == 0 { return x @@ -44,7 +44,7 @@ func h(a *B) *uint64 { // ERROR "leaking param: a to result ~r1 level=1" return nil } -func h2(a *B) *uint64 { // ERROR "leaking param: a to result ~r1 level=1" +func h2(a *B) *uint64 { // ERROR "leaking param: a to result ~r0 level=1" p := &a.b for i, x := range p { if i == 0 { @@ -55,7 +55,7 @@ func h2(a *B) *uint64 { // ERROR "leaking param: a to result ~r1 level=1" } // Seems like below should be level=1, not 0. -func k(a B) *uint64 { // ERROR "leaking param: a to result ~r1 level=0" +func k(a B) *uint64 { // ERROR "leaking param: a to result ~r0 level=0" for i, x := range &a.b { if i == 0 { return x diff --git a/test/fixedbugs/issue42284.dir/a.go b/test/fixedbugs/issue42284.dir/a.go index ffe9310be3..f7fd80bd20 100644 --- a/test/fixedbugs/issue42284.dir/a.go +++ b/test/fixedbugs/issue42284.dir/a.go @@ -13,7 +13,7 @@ func E() I { // ERROR "can inline E" return T(0) // ERROR "T\(0\) escapes to heap" } -func F(i I) I { // ERROR "can inline F" "leaking param: i to result ~r1 level=0" +func F(i I) I { // ERROR "can inline F" "leaking param: i to result ~r0 level=0" i = nil return i } -- GitLab From 6da1661371410c46af84c578d644052894226314 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 25 May 2021 20:14:33 -0700 Subject: [PATCH 0144/2500] [dev.typeparams] cmd/compile: simplify inlining variadic calls We already have and use FixVariadicCall to normalize non-dotted calls to variadic functions elsewhere in the compiler to simplify rewriting of function calls. This CL updates inl.go to use it too. A couple tests need to be updated to (correctly) expect diagnostics about "... argument" instead of a slice literal. This is because inl.go previously failed to set Implicit on the slice literal node. Change-Id: I76bd79b95ae1f16e3b26ff7e9e1c468f538fd1f0 Reviewed-on: https://go-review.googlesource.com/c/go/+/323009 Trust: Matthew Dempsky Trust: Dan Scales Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/inline/inl.go | 51 ++-------------------- src/cmd/compile/internal/typecheck/func.go | 13 +++--- src/cmd/compile/internal/walk/convert.go | 2 +- test/fixedbugs/issue30898.go | 2 +- test/inline_variadic.go | 2 +- 5 files changed, 14 insertions(+), 56 deletions(-) diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index 263e0b310b..00f8447f05 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -793,6 +793,9 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b defer func() { inlMap[fn] = false }() + + typecheck.FixVariadicCall(n) + if base.Debug.TypecheckInl == 0 { typecheck.ImportedBody(fn) } @@ -914,51 +917,17 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b } as.Rhs.Append(n.Args...) - // For non-dotted calls to variadic functions, we assign the - // variadic parameter's temp name separately. - var vas *ir.AssignStmt - if recv := fn.Type().Recv(); recv != nil { as.Lhs.Append(inlParam(recv, as, inlvars)) } for _, param := range fn.Type().Params().Fields().Slice() { - // For ordinary parameters or variadic parameters in - // dotted calls, just add the variable to the - // assignment list, and we're done. - if !param.IsDDD() || n.IsDDD { - as.Lhs.Append(inlParam(param, as, inlvars)) - continue - } - - // Otherwise, we need to collect the remaining values - // to pass as a slice. - - x := len(as.Lhs) - for len(as.Lhs) < len(as.Rhs) { - as.Lhs.Append(argvar(param.Type, len(as.Lhs))) - } - varargs := as.Lhs[x:] - - vas = ir.NewAssignStmt(base.Pos, nil, nil) - vas.X = inlParam(param, vas, inlvars) - if len(varargs) == 0 { - vas.Y = typecheck.NodNil() - vas.Y.SetType(param.Type) - } else { - lit := ir.NewCompLitExpr(base.Pos, ir.OCOMPLIT, ir.TypeNode(param.Type), nil) - lit.List = varargs - vas.Y = lit - } + as.Lhs.Append(inlParam(param, as, inlvars)) } if len(as.Rhs) != 0 { ninit.Append(typecheck.Stmt(as)) } - if vas != nil { - ninit.Append(typecheck.Stmt(vas)) - } - if !delayretvars { // Zero the return parameters. for _, n := range retvars { @@ -1078,18 +1047,6 @@ func retvar(t *types.Field, i int) *ir.Name { return n } -// Synthesize a variable to store the inlined function's arguments -// when they come from a multiple return call. -func argvar(t *types.Type, i int) ir.Node { - n := typecheck.NewName(typecheck.LookupNum("~arg", i)) - n.SetType(t.Elem()) - n.Class = ir.PAUTO - n.SetUsed(true) - n.Curfn = ir.CurFunc // the calling function, not the called one - ir.CurFunc.Dcl = append(ir.CurFunc.Dcl, n) - return n -} - // The inlsubst type implements the actual inlining of a single // function call. type inlsubst struct { diff --git a/src/cmd/compile/internal/typecheck/func.go b/src/cmd/compile/internal/typecheck/func.go index f381e1dbdc..760b8868ab 100644 --- a/src/cmd/compile/internal/typecheck/func.go +++ b/src/cmd/compile/internal/typecheck/func.go @@ -8,6 +8,7 @@ import ( "cmd/compile/internal/base" "cmd/compile/internal/ir" "cmd/compile/internal/types" + "cmd/internal/src" "fmt" "go/constant" @@ -15,21 +16,21 @@ import ( ) // package all the arguments that match a ... T parameter into a []T. -func MakeDotArgs(typ *types.Type, args []ir.Node) ir.Node { +func MakeDotArgs(pos src.XPos, typ *types.Type, args []ir.Node) ir.Node { var n ir.Node if len(args) == 0 { - n = NodNil() + n = ir.NewNilExpr(pos) n.SetType(typ) } else { - lit := ir.NewCompLitExpr(base.Pos, ir.OCOMPLIT, ir.TypeNode(typ), nil) - lit.List.Append(args...) + args = append([]ir.Node(nil), args...) + lit := ir.NewCompLitExpr(pos, ir.OCOMPLIT, ir.TypeNode(typ), args) lit.SetImplicit(true) n = lit } n = Expr(n) if n.Type() == nil { - base.Fatalf("mkdotargslice: typecheck failed") + base.FatalfAt(pos, "mkdotargslice: typecheck failed") } return n } @@ -47,7 +48,7 @@ func FixVariadicCall(call *ir.CallExpr) { args := call.Args extra := args[vi:] - slice := MakeDotArgs(vt, extra) + slice := MakeDotArgs(call.Pos(), vt, extra) for i := range extra { extra[i] = nil // allow GC } diff --git a/src/cmd/compile/internal/walk/convert.go b/src/cmd/compile/internal/walk/convert.go index 26e17a126f..5297332f6b 100644 --- a/src/cmd/compile/internal/walk/convert.go +++ b/src/cmd/compile/internal/walk/convert.go @@ -499,7 +499,7 @@ func walkCheckPtrArithmetic(n *ir.ConvExpr, init *ir.Nodes) ir.Node { cheap := cheapExpr(n, init) - slice := typecheck.MakeDotArgs(types.NewSlice(types.Types[types.TUNSAFEPTR]), originals) + slice := typecheck.MakeDotArgs(base.Pos, types.NewSlice(types.Types[types.TUNSAFEPTR]), originals) slice.SetEsc(ir.EscNone) init.Append(mkcall("checkptrArithmetic", nil, init, typecheck.ConvNop(cheap, types.Types[types.TUNSAFEPTR]), slice)) diff --git a/test/fixedbugs/issue30898.go b/test/fixedbugs/issue30898.go index b6376d3f9e..c7f6f2d371 100644 --- a/test/fixedbugs/issue30898.go +++ b/test/fixedbugs/issue30898.go @@ -15,5 +15,5 @@ func debugf(format string, args ...interface{}) { // ERROR "can inline debugf" " func bar() { // ERROR "can inline bar" value := 10 - debugf("value is %d", value) // ERROR "inlining call to debugf" "value does not escape" "\[\]interface {}{...} does not escape" + debugf("value is %d", value) // ERROR "inlining call to debugf" "value does not escape" "\.\.\. argument does not escape" } diff --git a/test/inline_variadic.go b/test/inline_variadic.go index 687048a192..49483d77f7 100644 --- a/test/inline_variadic.go +++ b/test/inline_variadic.go @@ -14,6 +14,6 @@ func head(xs ...string) string { // ERROR "can inline head" "leaking param: xs t } func f() string { // ERROR "can inline f" - x := head("hello", "world") // ERROR "inlining call to head" "\[\]string{...} does not escape" + x := head("hello", "world") // ERROR "inlining call to head" "\.\.\. argument does not escape" return x } -- GitLab From 1ec056244e1a058ea3a21f0abd1165d710398416 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 24 May 2021 04:41:58 -0700 Subject: [PATCH 0145/2500] [dev.typeparams] cmd/compile: inlining tweaks for toolstash This CL makes to minor changes motivated by making it easier to make large-scale changes to the inliner while satisfying toolstash -cmp: 1. When creating inlining variables, make sure to preserve the AutoTemp flag. This is necessary so that temporary variables introduced by rewriting f(g()) calls during typecheck stay autotemp after inlining and are (correctly) omitted from DWARF debugging information. 2. When sorting variables for stack frame layout, use a stable sort. This ensures that layout is insensitive to whether deadcode elimination happens before or after inlining. Change-Id: I672e752a873c7e16749b9873fd6573607e074309 Reviewed-on: https://go-review.googlesource.com/c/go/+/323011 Trust: Matthew Dempsky Trust: Dan Scales Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/inline/inl.go | 1 + src/cmd/compile/internal/ssagen/pgen.go | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index 00f8447f05..042e3f2332 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -1029,6 +1029,7 @@ func inlvar(var_ *ir.Name) *ir.Name { n.SetType(var_.Type()) n.Class = ir.PAUTO n.SetUsed(true) + n.SetAutoTemp(var_.AutoTemp()) n.Curfn = ir.CurFunc // the calling function, not the called one n.SetAddrtaken(var_.Addrtaken()) diff --git a/src/cmd/compile/internal/ssagen/pgen.go b/src/cmd/compile/internal/ssagen/pgen.go index 62567535d7..93157bfa11 100644 --- a/src/cmd/compile/internal/ssagen/pgen.go +++ b/src/cmd/compile/internal/ssagen/pgen.go @@ -114,7 +114,10 @@ func (s *ssafn) AllocFrame(f *ssa.Func) { } } - sort.Sort(byStackVar(fn.Dcl)) + // Use sort.Stable instead of sort.Sort so stack layout (and thus + // compiler output) is less sensitive to frontend changes that + // introduce or remove unused variables. + sort.Stable(byStackVar(fn.Dcl)) // Reassign stack offsets of the locals that are used. lastHasPtr := false -- GitLab From 5fcd18bc9bd89bad5270434f99d40e820affbd82 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Wed, 19 May 2021 11:43:58 -0700 Subject: [PATCH 0146/2500] [dev.fuzz] internal/fuzz,testing: treat panics as recoverable And only log the last panic, not all of them, during minimization. This change makes the worker processes quiet, so now the only process that logs anything is the coordinator. This hides all of the panics caused during minimization of an input which causes a panic. This change also alters the usage of tRunner such that we now recover from recoverable panics instead of terminating the process. This results in larger stack traces, since we include a bit more of the trace within testing. There is a TODO to see if it's possible to slice the stack up so that it is somewhat more informative. Change-Id: Ic85eabd2e70b078412fbb88adf424a8da25af876 Reviewed-on: https://go-review.googlesource.com/c/go/+/321230 Trust: Roland Shoemaker Trust: Katie Hockman Run-TryBot: Roland Shoemaker TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- .../go/testdata/script/test_fuzz_mutator.txt | 10 ++++--- src/internal/fuzz/worker.go | 8 ------ src/testing/fuzz.go | 6 ++++- src/testing/testing.go | 26 +++++++++++++++++-- 4 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_mutator.txt b/src/cmd/go/testdata/script/test_fuzz_mutator.txt index 9098d52f5b..1d0c399a6c 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutator.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutator.txt @@ -110,6 +110,8 @@ package fuzz_test import ( "bytes" + "fmt" + "os" "testing" ) @@ -123,7 +125,7 @@ func FuzzMinimizerRecoverable(f *testing.F) { // minimizer to trim down the value a bit. if bytes.ContainsAny(b, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") { if len(b) == 50 { - t.Log("got the minimum size!") + fmt.Fprint(os.Stderr, "got the minimum size!\n") } t.Error("contains a letter") } @@ -140,7 +142,7 @@ func FuzzMinimizerNonrecoverable(f *testing.F) { // minimizer to trim down the value quite a bit. if bytes.ContainsAny(b, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") { if len(b) == 50 { - t.Log("got the minimum size!") + fmt.Fprint(os.Stderr, "got the minimum size!\n") } panic("contains a letter") } @@ -155,7 +157,7 @@ func FuzzNonMinimizable(f *testing.F) { } panic("at least 20 bytes") if len(b) == 20 { - t.Log("got the minimum size!") + fmt.Fprint(os.Stderr, "got the minimum size!\n") } }) } @@ -327,4 +329,4 @@ func FuzzMutator(f *testing.F) { panic("mutator found enough unique mutations") } }) -} \ No newline at end of file +} diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index c2cacf986b..875f3ac5ba 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -95,7 +95,6 @@ func (w *worker) coordinate(ctx context.Context) error { return nil } return fmt.Errorf("fuzzing process terminated without fuzzing: %w", err) - // TODO(jayconrod,katiehockman): record and return stderr. } // interestingCount starts at -1, like the coordinator does, so that the @@ -141,7 +140,6 @@ func (w *worker) coordinate(ctx context.Context) error { // (for example, SIGSEGV) while fuzzing. return fmt.Errorf("fuzzing process terminated unexpectedly: %w", err) // TODO(jayconrod,katiehockman): if -keepfuzzing, restart worker. - // TODO(jayconrod,katiehockman): record and return stderr. case input := <-w.coordinator.inputC: // Received input from coordinator. @@ -288,9 +286,6 @@ func (w *worker) minimize(ctx context.Context) (res fuzzResult, minimized bool, } minimized = true } - // TODO(jayconrod,katiehockman): while minimizing, every panic message is - // logged to STDOUT. We should probably suppress all but the last one to - // lower the noise. } // start runs a new worker process. @@ -314,9 +309,6 @@ func (w *worker) start() (err error) { cmd := exec.Command(w.binPath, w.args...) cmd.Dir = w.dir cmd.Env = w.env[:len(w.env):len(w.env)] // copy on append to ensure workers don't overwrite each other. - // TODO(jayconrod): set stdout and stderr to nil or buffer. A large number - // of workers may be very noisy, but for now, this output is useful for - // debugging. cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 9364b27eaf..78a0a600fa 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -8,6 +8,7 @@ import ( "errors" "flag" "fmt" + "io" "os" "path/filepath" "reflect" @@ -313,6 +314,7 @@ func (f *F) Fuzz(ff interface{}) { if e.Name != "" { testName = fmt.Sprintf("%s/%s", testName, e.Name) } + // Record the stack trace at the point of this call so that if the subtest // function - which runs in a separate stack - is marked as a helper, we can // continue walking the stack into the parent test. @@ -327,6 +329,7 @@ func (f *F) Fuzz(ff interface{}) { level: f.level + 1, creator: pc[:n], chatty: f.chatty, + fuzzing: true, }, context: f.testContext, } @@ -541,12 +544,13 @@ func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran, ok bool) resetCoverage: deps.ResetCoverage, snapshotCoverage: deps.SnapshotCoverage, } + root := common{w: os.Stdout} if *isFuzzWorker { + root.w = io.Discard fctx.runFuzzWorker = deps.RunFuzzWorker } else { fctx.coordinateFuzzing = deps.CoordinateFuzzing } - root := common{w: os.Stdout} if Verbose() && !*isFuzzWorker { root.chatty = newChattyPrinter(root.w) } diff --git a/src/testing/testing.go b/src/testing/testing.go index 07ef625538..82b422a414 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -448,6 +448,7 @@ type common struct { chatty *chattyPrinter // A copy of chattyPrinter, if the chatty flag is set. bench bool // Whether the current test is a benchmark. + fuzzing bool // Whether the current test is a fuzzing target. hasSub int32 // Written atomically. raceErrors int // Number of races detected during test. runner string // Function name of tRunner running the test. @@ -655,6 +656,20 @@ func (c *common) flushToParent(testName, format string, args ...interface{}) { } } +// isFuzzing returns whether the current context, or any of the parent contexts, +// are a fuzzing target +func (c *common) isFuzzing() bool { + if c.fuzzing { + return true + } + for parent := c.parent; parent != nil; parent = parent.parent { + if parent.fuzzing { + return true + } + } + return false +} + type indenter struct { c *common } @@ -1221,10 +1236,11 @@ func tRunner(t *T, fn func(t *T)) { // complete even if a cleanup function calls t.FailNow. See issue 41355. didPanic := false defer func() { - if didPanic { + isFuzzing := t.common.isFuzzing() + if didPanic && !isFuzzing { return } - if err != nil { + if err != nil && !isFuzzing { panic(err) } // Only report that the test is complete if it doesn't panic, @@ -1250,6 +1266,12 @@ func tRunner(t *T, fn func(t *T)) { } } didPanic = true + if t.common.fuzzing { + for root := &t.common; root.parent != nil; root = root.parent { + fmt.Fprintf(root.parent.w, "panic: %s\n%s\n", err, string(debug.Stack())) + } + return + } panic(err) } if err != nil { -- GitLab From a573cbfa6c84c108d79330d062c345dc8d38dbfd Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Mon, 17 May 2021 20:14:15 -0700 Subject: [PATCH 0147/2500] [dev.fuzz] internal/fuzz: support minimization of strings, integers, and floats Adds support for minimizing strings using the same logic as byte slices as well as minimizing both signed and unsigned integers and floats using extremely basic logic. A more complex approach is probably warranted in the future, but for now this should be _good enough_. Change-Id: Ibc6c3d6ae82685998f571aa2c1ecea2f85c2708b Reviewed-on: https://go-review.googlesource.com/c/go/+/320669 Trust: Roland Shoemaker Trust: Katie Hockman Run-TryBot: Roland Shoemaker TryBot-Result: Go Bot Reviewed-by: Katie Hockman Reviewed-by: Jay Conrod --- src/internal/fuzz/minimize.go | 104 ++++++++++++++ src/internal/fuzz/minimize_test.go | 219 +++++++++++++++++++++++++++++ src/internal/fuzz/worker.go | 175 +++++++++++++---------- 3 files changed, 425 insertions(+), 73 deletions(-) create mode 100644 src/internal/fuzz/minimize.go create mode 100644 src/internal/fuzz/minimize_test.go diff --git a/src/internal/fuzz/minimize.go b/src/internal/fuzz/minimize.go new file mode 100644 index 0000000000..c5533bd917 --- /dev/null +++ b/src/internal/fuzz/minimize.go @@ -0,0 +1,104 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fuzz + +import ( + "context" + "math" +) + +func minimizeBytes(ctx context.Context, v []byte, stillCrashes func(interface{}) bool, shouldStop func() bool) { + // First, try to cut the tail. + for n := 1024; n != 0; n /= 2 { + for len(v) > n { + if shouldStop() { + return + } + candidate := v[:len(v)-n] + if !stillCrashes(candidate) { + break + } + // Set v to the new value to continue iterating. + v = candidate + } + } + + // Then, try to remove each individual byte. + tmp := make([]byte, len(v)) + for i := 0; i < len(v)-1; i++ { + if shouldStop() { + return + } + candidate := tmp[:len(v)-1] + copy(candidate[:i], v[:i]) + copy(candidate[i:], v[i+1:]) + if !stillCrashes(candidate) { + continue + } + // Update v to delete the value at index i. + copy(v[i:], v[i+1:]) + v = v[:len(candidate)] + // v[i] is now different, so decrement i to redo this iteration + // of the loop with the new value. + i-- + } + + // Then, try to remove each possible subset of bytes. + for i := 0; i < len(v)-1; i++ { + copy(tmp, v[:i]) + for j := len(v); j > i+1; j-- { + if shouldStop() { + return + } + candidate := tmp[:len(v)-j+i] + copy(candidate[i:], v[j:]) + if !stillCrashes(candidate) { + continue + } + // Update v and reset the loop with the new length. + copy(v[i:], v[j:]) + v = v[:len(candidate)] + j = len(v) + } + } + + return +} + +func minimizeInteger(ctx context.Context, v uint, stillCrashes func(interface{}) bool, shouldStop func() bool) { + // TODO(rolandshoemaker): another approach could be either unsetting/setting all bits + // (depending on signed-ness), or rotating bits? When operating on cast signed integers + // this would probably be more complex though. + for ; v != 0; v /= 10 { + if shouldStop() { + return + } + // We ignore the return value here because there is no point + // advancing the loop, since there is nothing after this check, + // and we don't return early because a smaller value could + // re-trigger the crash. + stillCrashes(v) + } + return +} + +func minimizeFloat(ctx context.Context, v float64, stillCrashes func(interface{}) bool, shouldStop func() bool) { + if math.IsNaN(v) { + return + } + minimized := float64(0) + for div := 10.0; minimized < v; div *= 10 { + if shouldStop() { + return + } + minimized = float64(int(v*div)) / div + if !stillCrashes(minimized) { + // Since we are searching from least precision -> highest precision we + // can return early since we've already found the smallest value + return + } + } + return +} diff --git a/src/internal/fuzz/minimize_test.go b/src/internal/fuzz/minimize_test.go new file mode 100644 index 0000000000..500ff431b4 --- /dev/null +++ b/src/internal/fuzz/minimize_test.go @@ -0,0 +1,219 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin || linux || windows +// +build darwin linux windows + +package fuzz + +import ( + "context" + "fmt" + "reflect" + "testing" +) + +func TestMinimizeInput(t *testing.T) { + type testcase struct { + fn func(CorpusEntry) error + input []interface{} + expected []interface{} + } + cases := []testcase{ + { + fn: func(e CorpusEntry) error { + b := e.Values[0].([]byte) + ones := 0 + for _, v := range b { + if v == 1 { + ones++ + } + } + if ones == 3 { + return fmt.Errorf("bad %v", e.Values[0]) + } + return nil + }, + input: []interface{}{[]byte{0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + expected: []interface{}{[]byte{1, 1, 1}}, + }, + { + fn: func(e CorpusEntry) error { + b := e.Values[0].(string) + ones := 0 + for _, v := range b { + if v == '1' { + ones++ + } + } + if ones == 3 { + return fmt.Errorf("bad %v", e.Values[0]) + } + return nil + }, + input: []interface{}{"001010001000000000000000000"}, + expected: []interface{}{"111"}, + }, + { + fn: func(e CorpusEntry) error { + i := e.Values[0].(int) + if i > 100 { + return fmt.Errorf("bad %v", e.Values[0]) + } + return nil + }, + input: []interface{}{123456}, + expected: []interface{}{123}, + }, + { + fn: func(e CorpusEntry) error { + i := e.Values[0].(int8) + if i > 10 { + return fmt.Errorf("bad %v", e.Values[0]) + } + return nil + }, + input: []interface{}{int8(1<<7 - 1)}, + expected: []interface{}{int8(12)}, + }, + { + fn: func(e CorpusEntry) error { + i := e.Values[0].(int16) + if i > 10 { + return fmt.Errorf("bad %v", e.Values[0]) + } + return nil + }, + input: []interface{}{int16(1<<15 - 1)}, + expected: []interface{}{int16(32)}, + }, + { + fn: func(e CorpusEntry) error { + i := e.Values[0].(int32) + if i > 10 { + return fmt.Errorf("bad %v", e.Values[0]) + } + return nil + }, + input: []interface{}{int32(1<<31 - 1)}, + expected: []interface{}{int32(21)}, + }, + { + fn: func(e CorpusEntry) error { + i := e.Values[0].(uint) + if i > 10 { + return fmt.Errorf("bad %v", e.Values[0]) + } + return nil + }, + input: []interface{}{uint(123456)}, + expected: []interface{}{uint(12)}, + }, + { + fn: func(e CorpusEntry) error { + i := e.Values[0].(uint8) + if i > 10 { + return fmt.Errorf("bad %v", e.Values[0]) + } + return nil + }, + input: []interface{}{uint8(1<<8 - 1)}, + expected: []interface{}{uint8(25)}, + }, + { + fn: func(e CorpusEntry) error { + i := e.Values[0].(uint16) + if i > 10 { + return fmt.Errorf("bad %v", e.Values[0]) + } + return nil + }, + input: []interface{}{uint16(1<<16 - 1)}, + expected: []interface{}{uint16(65)}, + }, + { + fn: func(e CorpusEntry) error { + i := e.Values[0].(uint32) + if i > 10 { + return fmt.Errorf("bad %v", e.Values[0]) + } + return nil + }, + input: []interface{}{uint32(1<<32 - 1)}, + expected: []interface{}{uint32(42)}, + }, + { + fn: func(e CorpusEntry) error { + if i := e.Values[0].(float32); i == 1.23 { + return nil + } + return fmt.Errorf("bad %v", e.Values[0]) + }, + input: []interface{}{float32(1.23456789)}, + expected: []interface{}{float32(1.2)}, + }, + { + fn: func(e CorpusEntry) error { + if i := e.Values[0].(float64); i == 1.23 { + return nil + } + return fmt.Errorf("bad %v", e.Values[0]) + }, + input: []interface{}{float64(1.23456789)}, + expected: []interface{}{float64(1.2)}, + }, + } + + // If we are on a 64 bit platform add int64 and uint64 tests + if v := int64(1<<63 - 1); int64(int(v)) == v { + cases = append(cases, testcase{ + fn: func(e CorpusEntry) error { + i := e.Values[0].(int64) + if i > 10 { + return fmt.Errorf("bad %v", e.Values[0]) + } + return nil + }, + input: []interface{}{int64(1<<63 - 1)}, + expected: []interface{}{int64(92)}, + }, testcase{ + fn: func(e CorpusEntry) error { + i := e.Values[0].(uint64) + if i > 10 { + return fmt.Errorf("bad %v", e.Values[0]) + } + return nil + }, + input: []interface{}{uint64(1<<64 - 1)}, + expected: []interface{}{uint64(18)}, + }) + } + + sm, err := sharedMemTempFile(workerSharedMemSize) + if err != nil { + t.Fatalf("failed to create temporary shared memory file: %s", err) + } + defer sm.Close() + + for _, tc := range cases { + ws := &workerServer{ + fuzzFn: tc.fn, + } + count := int64(0) + err = ws.minimizeInput(context.Background(), tc.input, sm, &count, 0) + if err == nil { + t.Error("minimizeInput didn't fail") + } + if expected := fmt.Sprintf("bad %v", tc.input[0]); err.Error() != expected { + t.Errorf("unexpected error: got %s, want %s", err, expected) + } + vals, err := unmarshalCorpusFile(sm.valueCopy()) + if err != nil { + t.Fatalf("failed to unmarshal values from shared memory file: %s", err) + } + if !reflect.DeepEqual(vals, tc.expected) { + t.Errorf("unexpected results: got %v, want %v", vals, tc.expected) + } + } +} diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 875f3ac5ba..33727a5438 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -714,7 +714,7 @@ func (ws *workerServer) minimize(ctx context.Context, args minimizeArgs) (resp m // mem just in case an unrecoverable error occurs. It uses the context to // determine how long to run, stopping once closed. It returns the last error it // found. -func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, mem *sharedMem, count *int64, limit int64) (retErr error) { +func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, mem *sharedMem, count *int64, limit int64) error { // Make sure the last crashing value is written to mem. defer writeToMem(vals, mem) @@ -725,87 +725,116 @@ func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, m return nil } - // tryMinimized will run the fuzz function for the values in vals at the - // time the function is called. If err is nil, then the minimization was - // unsuccessful, since we expect an error to still occur. - tryMinimized := func(i int, prevVal interface{}) error { - writeToMem(vals, mem) // write to mem in case a non-recoverable crash occurs + var valI int + var retErr error + tryMinimized := func(candidate interface{}) bool { + prev := vals[valI] + // Set vals[valI] to the candidate after it has been + // properly cast. We know that candidate must be of + // the same type as prev, so use that as a reference. + switch c := candidate.(type) { + case float64: + switch prev.(type) { + case float32: + vals[valI] = float32(c) + case float64: + vals[valI] = c + default: + panic("impossible") + } + case uint: + switch prev.(type) { + case uint: + vals[valI] = c + case uint8: + vals[valI] = uint8(c) + case uint16: + vals[valI] = uint16(c) + case uint32: + vals[valI] = uint32(c) + case uint64: + vals[valI] = uint64(c) + case int: + vals[valI] = int(c) + case int8: + vals[valI] = int8(c) + case int16: + vals[valI] = int16(c) + case int32: + vals[valI] = int32(c) + case int64: + vals[valI] = int64(c) + default: + panic("impossible") + } + case []byte: + switch prev.(type) { + case []byte: + vals[valI] = c + case string: + vals[valI] = string(c) + default: + panic("impossible") + } + default: + panic("impossible") + } + writeToMem(vals, mem) err := ws.fuzzFn(CorpusEntry{Values: vals}) - if err == nil { - // The fuzz function succeeded, so return the value at index i back - // to the previously failing input. - vals[i] = prevVal - } else { - // The fuzz function failed, so save the most recent error. + if err != nil { retErr = err + return true } *count++ - return err + vals[valI] = prev + return false } - for valI := range vals { + + for valI = range vals { + if shouldStop() { + return retErr + } switch v := vals[valI].(type) { - case bool, byte, rune: + case bool: continue // can't minimize - case string, int, int8, int16, int64, uint, uint16, uint32, uint64, float32, float64: - // TODO(jayconrod,katiehockman): support minimizing other types - case []byte: - // First, try to cut the tail. - for n := 1024; n != 0; n /= 2 { - for len(v) > n { - if shouldStop() { - return retErr - } - vals[valI] = v[:len(v)-n] - if tryMinimized(valI, v) == nil { - break - } - // Set v to the new value to continue iterating. - v = v[:len(v)-n] - } + case float32: + minimizeFloat(ctx, float64(v), tryMinimized, shouldStop) + case float64: + minimizeFloat(ctx, v, tryMinimized, shouldStop) + case uint: + minimizeInteger(ctx, v, tryMinimized, shouldStop) + case uint8: + minimizeInteger(ctx, uint(v), tryMinimized, shouldStop) + case uint16: + minimizeInteger(ctx, uint(v), tryMinimized, shouldStop) + case uint32: + minimizeInteger(ctx, uint(v), tryMinimized, shouldStop) + case uint64: + if uint64(uint(v)) != v { + // Skip minimizing a uint64 on 32 bit platforms, since we'll truncate the + // value when casting + continue } - - // Then, try to remove each individual byte. - tmp := make([]byte, len(v)) - for i := 0; i < len(v)-1; i++ { - if shouldStop() { - return retErr - } - candidate := tmp[:len(v)-1] - copy(candidate[:i], v[:i]) - copy(candidate[i:], v[i+1:]) - vals[valI] = candidate - if tryMinimized(valI, v) == nil { - continue - } - // Update v to delete the value at index i. - copy(v[i:], v[i+1:]) - v = v[:len(candidate)] - // v[i] is now different, so decrement i to redo this iteration - // of the loop with the new value. - i-- + minimizeInteger(ctx, uint(v), tryMinimized, shouldStop) + case int: + minimizeInteger(ctx, uint(v), tryMinimized, shouldStop) + case int8: + minimizeInteger(ctx, uint(v), tryMinimized, shouldStop) + case int16: + minimizeInteger(ctx, uint(v), tryMinimized, shouldStop) + case int32: + minimizeInteger(ctx, uint(v), tryMinimized, shouldStop) + case int64: + if int64(int(v)) != v { + // Skip minimizing a int64 on 32 bit platforms, since we'll truncate the + // value when casting + continue } - - // Then, try to remove each possible subset of bytes. - for i := 0; i < len(v)-1; i++ { - copy(tmp, v[:i]) - for j := len(v); j > i+1; j-- { - if shouldStop() { - return retErr - } - candidate := tmp[:len(v)-j+i] - copy(candidate[i:], v[j:]) - vals[valI] = candidate - if tryMinimized(valI, v) == nil { - continue - } - // Update v and reset the loop with the new length. - copy(v[i:], v[j:]) - v = v[:len(candidate)] - j = len(v) - } - } - // TODO(jayconrod,katiehockman): consider adding canonicalization - // which replaces each individual byte with '0' + minimizeInteger(ctx, uint(v), tryMinimized, shouldStop) + case string: + minimizeBytes(ctx, []byte(v), tryMinimized, shouldStop) + case []byte: + minimizeBytes(ctx, v, tryMinimized, shouldStop) default: panic("unreachable") } -- GitLab From 06df0ee7fa8b6d7d095de77274f53fb81a43d622 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 25 May 2021 18:05:02 -0400 Subject: [PATCH 0148/2500] [dev.typeparams] cmd/compile: add arg/result register load/spill code on ARM64 Add code that loads results into registers (used in defer return code path) and spills argument registers (used for partially lived in-register args). Move some code from the amd64 package to a common place. Change-Id: I8d59b68693048fdba86e10769c4ac58de5fcfb64 Reviewed-on: https://go-review.googlesource.com/c/go/+/322851 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: David Chase Reviewed-by: Than McIntosh --- src/cmd/compile/internal/amd64/galign.go | 2 +- src/cmd/compile/internal/amd64/ssa.go | 23 +++++++++-------------- src/cmd/compile/internal/arm64/galign.go | 2 ++ src/cmd/compile/internal/arm64/ssa.go | 20 ++++++++++++++++++++ src/cmd/compile/internal/ssagen/arch.go | 8 ++++---- src/cmd/compile/internal/ssagen/ssa.go | 8 ++++++-- 6 files changed, 42 insertions(+), 21 deletions(-) diff --git a/src/cmd/compile/internal/amd64/galign.go b/src/cmd/compile/internal/amd64/galign.go index 2785aa0336..3b13e123a7 100644 --- a/src/cmd/compile/internal/amd64/galign.go +++ b/src/cmd/compile/internal/amd64/galign.go @@ -23,6 +23,6 @@ func Init(arch *ssagen.ArchInfo) { arch.SSAMarkMoves = ssaMarkMoves arch.SSAGenValue = ssaGenValue arch.SSAGenBlock = ssaGenBlock - arch.LoadRegResults = loadRegResults + arch.LoadRegResult = loadRegResult arch.SpillArgReg = spillArgReg } diff --git a/src/cmd/compile/internal/amd64/ssa.go b/src/cmd/compile/internal/amd64/ssa.go index 7e2dc41928..c27a5fe5b5 100644 --- a/src/cmd/compile/internal/amd64/ssa.go +++ b/src/cmd/compile/internal/amd64/ssa.go @@ -1354,20 +1354,15 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) { } } -func loadRegResults(s *ssagen.State, f *ssa.Func) { - for _, o := range f.OwnAux.ABIInfo().OutParams() { - n := o.Name.(*ir.Name) - rts, offs := o.RegisterTypesAndOffsets() - for i := range o.Registers { - p := s.Prog(loadByType(rts[i])) - p.From.Type = obj.TYPE_MEM - p.From.Name = obj.NAME_AUTO - p.From.Sym = n.Linksym() - p.From.Offset = n.FrameOffset() + offs[i] - p.To.Type = obj.TYPE_REG - p.To.Reg = ssa.ObjRegForAbiReg(o.Registers[i], f.Config) - } - } +func loadRegResult(s *ssagen.State, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog { + p := s.Prog(loadByType(t)) + p.From.Type = obj.TYPE_MEM + p.From.Name = obj.NAME_AUTO + p.From.Sym = n.Linksym() + p.From.Offset = n.FrameOffset() + off + p.To.Type = obj.TYPE_REG + p.To.Reg = reg + return p } func spillArgReg(pp *objw.Progs, p *obj.Prog, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog { diff --git a/src/cmd/compile/internal/arm64/galign.go b/src/cmd/compile/internal/arm64/galign.go index d3db37e16f..2a61b9dd99 100644 --- a/src/cmd/compile/internal/arm64/galign.go +++ b/src/cmd/compile/internal/arm64/galign.go @@ -23,4 +23,6 @@ func Init(arch *ssagen.ArchInfo) { arch.SSAMarkMoves = func(s *ssagen.State, b *ssa.Block) {} arch.SSAGenValue = ssaGenValue arch.SSAGenBlock = ssaGenBlock + arch.LoadRegResult = loadRegResult + arch.SpillArgReg = spillArgReg } diff --git a/src/cmd/compile/internal/arm64/ssa.go b/src/cmd/compile/internal/arm64/ssa.go index d82788218d..74308a18f6 100644 --- a/src/cmd/compile/internal/arm64/ssa.go +++ b/src/cmd/compile/internal/arm64/ssa.go @@ -10,6 +10,7 @@ import ( "cmd/compile/internal/base" "cmd/compile/internal/ir" "cmd/compile/internal/logopt" + "cmd/compile/internal/objw" "cmd/compile/internal/ssa" "cmd/compile/internal/ssagen" "cmd/compile/internal/types" @@ -1278,3 +1279,22 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) { b.Fatalf("branch not implemented: %s", b.LongString()) } } + +func loadRegResult(s *ssagen.State, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog { + p := s.Prog(loadByType(t)) + p.From.Type = obj.TYPE_MEM + p.From.Name = obj.NAME_AUTO + p.From.Sym = n.Linksym() + p.From.Offset = n.FrameOffset() + off + p.To.Type = obj.TYPE_REG + p.To.Reg = reg + return p +} + +func spillArgReg(pp *objw.Progs, p *obj.Prog, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog { + p = pp.Append(p, storeByType(t), obj.TYPE_REG, reg, 0, obj.TYPE_MEM, 0, n.FrameOffset()+off) + p.To.Name = obj.NAME_PARAM + p.To.Sym = n.Linksym() + p.Pos = p.Pos.WithNotStmt() + return p +} diff --git a/src/cmd/compile/internal/ssagen/arch.go b/src/cmd/compile/internal/ssagen/arch.go index 7215f42c05..957fb3e84a 100644 --- a/src/cmd/compile/internal/ssagen/arch.go +++ b/src/cmd/compile/internal/ssagen/arch.go @@ -42,10 +42,10 @@ type ArchInfo struct { // for all values in the block before SSAGenBlock. SSAGenBlock func(s *State, b, next *ssa.Block) - // LoadRegResults emits instructions that loads register-assigned results - // into registers. They are already in memory (PPARAMOUT nodes). - // Used in open-coded defer return path. - LoadRegResults func(s *State, f *ssa.Func) + // LoadRegResult emits instructions that loads register-assigned result + // at n+off (n is PPARAMOUT) to register reg. The result is already in + // memory. Used in open-coded defer return path. + LoadRegResult func(s *State, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog // SpillArgReg emits instructions that spill reg to n+off. SpillArgReg func(pp *objw.Progs, p *obj.Prog, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 91b0c79cd3..f59220ab8e 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -6930,8 +6930,12 @@ func genssa(f *ssa.Func, pp *objw.Progs) { // recovers a panic, it will return to caller with right results. // The results are already in memory, because they are not SSA'd // when the function has defers (see canSSAName). - if f.OwnAux.ABIInfo().OutRegistersUsed() != 0 { - Arch.LoadRegResults(&s, f) + for _, o := range f.OwnAux.ABIInfo().OutParams() { + n := o.Name.(*ir.Name) + rts, offs := o.RegisterTypesAndOffsets() + for i := range o.Registers { + Arch.LoadRegResult(&s, f, rts[i], ssa.ObjRegForAbiReg(o.Registers[i], f.Config), n, offs[i]) + } } pp.Prog(obj.ARET) -- GitLab From 963f33b03b88e2c010d6a9876c3f0cc8d1f36f2d Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 25 May 2021 19:19:08 -0400 Subject: [PATCH 0149/2500] [dev.typeparams] cmd/compile: enable register args on ARM64 Now it will be used for functions marked go:registerparams. test/abi tests are passing with it. Change-Id: I5af37ae6b79a1064832a42c7ef5f2cc0b5b6a342 Reviewed-on: https://go-review.googlesource.com/c/go/+/322854 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: David Chase Reviewed-by: Than McIntosh --- src/cmd/compile/internal/ssa/config.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/ssa/config.go b/src/cmd/compile/internal/ssa/config.go index 07d8b6e532..7d680304c9 100644 --- a/src/cmd/compile/internal/ssa/config.go +++ b/src/cmd/compile/internal/ssa/config.go @@ -228,10 +228,8 @@ func NewConfig(arch string, types Types, ctxt *obj.Link, optimize bool) *Config c.registers = registersARM64[:] c.gpRegMask = gpRegMaskARM64 c.fpRegMask = fpRegMaskARM64 - // XXX commented out for now. Uncomment it will enable register args for - // go:registerparams functions, which isn't fully working, so tests fail. - //c.intParamRegs = paramIntRegARM64 - //c.floatParamRegs = paramFloatRegARM64 + c.intParamRegs = paramIntRegARM64 + c.floatParamRegs = paramFloatRegARM64 c.FPReg = framepointerRegARM64 c.LinkReg = linkRegARM64 c.hasGReg = true -- GitLab From 8c99e5db431c28ef563fc4980b05b26f82172864 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 26 May 2021 21:42:09 -0700 Subject: [PATCH 0150/2500] [dev.typeparams] cmd/compile/internal/types2: ensure that Named.check is nilled out once it is expanded This is a port of - https://golang.org/cl/318849 - https://golang.org/cl/322974 For #45580. Change-Id: Ie0700ed6c8d472305d5ba7ff97da1ae063152aa3 Reviewed-on: https://go-review.googlesource.com/c/go/+/323030 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/decl.go | 51 ++++++++++++++++----- src/cmd/compile/internal/types2/sanitize.go | 3 ++ src/cmd/compile/internal/types2/type.go | 19 +++++++- 3 files changed, 60 insertions(+), 13 deletions(-) diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 1333e4c0ec..aa70f3880b 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -523,15 +523,37 @@ func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init syntax.Expr) { // n0.check != nil, the cycle is reported. func (n0 *Named) under() Type { u := n0.underlying - if u == nil { - return Typ[Invalid] + + if u == Typ[Invalid] { + return u } // If the underlying type of a defined type is not a defined - // type, then that is the desired underlying type. + // (incl. instance) type, then that is the desired underlying + // type. + switch u.(type) { + case nil: + return Typ[Invalid] + default: + // common case + return u + case *Named, *instance: + // handled below + } + + if n0.check == nil { + panic("internal error: Named.check == nil but type is incomplete") + } + + // Invariant: after this point n0 as well as any named types in its + // underlying chain should be set up when this function exits. + check := n0.check + + // If we can't expand u at this point, it is invalid. n := asNamed(u) if n == nil { - return u // common case + n0.underlying = Typ[Invalid] + return n0.underlying } // Otherwise, follow the forward chain. @@ -543,7 +565,16 @@ func (n0 *Named) under() Type { u = Typ[Invalid] break } - n1 := asNamed(u) + var n1 *Named + switch u1 := u.(type) { + case *Named: + n1 = u1 + case *instance: + n1, _ = u1.expand().(*Named) + if n1 == nil { + u = Typ[Invalid] + } + } if n1 == nil { break // end of chain } @@ -554,11 +585,7 @@ func (n0 *Named) under() Type { if i, ok := seen[n]; ok { // cycle - // TODO(gri) revert this to a method on Checker. Having a possibly - // nil Checker on Named and TypeParam is too subtle. - if n0.check != nil { - n0.check.cycleError(path[i:]) - } + check.cycleError(path[i:]) u = Typ[Invalid] break } @@ -568,8 +595,8 @@ func (n0 *Named) under() Type { // We should never have to update the underlying type of an imported type; // those underlying types should have been resolved during the import. // Also, doing so would lead to a race condition (was issue #31749). - // Do this check always, not just in debug more (it's cheap). - if n0.check != nil && n.obj.pkg != n0.check.pkg { + // Do this check always, not just in debug mode (it's cheap). + if n.obj.pkg != check.pkg { panic("internal error: imported type with unresolved underlying type") } n.underlying = u diff --git a/src/cmd/compile/internal/types2/sanitize.go b/src/cmd/compile/internal/types2/sanitize.go index 9fad52e224..c30febfda8 100644 --- a/src/cmd/compile/internal/types2/sanitize.go +++ b/src/cmd/compile/internal/types2/sanitize.go @@ -134,6 +134,9 @@ func (s sanitizer) typ(typ Type) Type { } case *Named: + if debug && t.check != nil { + panic("internal error: Named.check != nil") + } if orig := s.typ(t.fromRHS); orig != t.fromRHS { t.fromRHS = orig } diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 2a93ca0388..3b2a5960e8 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -544,7 +544,7 @@ func (c *Chan) Elem() Type { return c.elem } // A Named represents a named (defined) type. type Named struct { - check *Checker // for Named.under implementation + check *Checker // for Named.under implementation; nilled once under has been called info typeInfo // for cycle detection obj *TypeName // corresponding declared object orig *Named // original, uninstantiated type @@ -574,6 +574,23 @@ func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tpar if obj.typ == nil { obj.typ = typ } + // Ensure that typ is always expanded, at which point the check field can be + // nilled out. + // + // Note that currently we cannot nil out check inside typ.under(), because + // it's possible that typ is expanded multiple times. + // + // TODO(gri): clean this up so that under is the only function mutating + // named types. + if check != nil { + check.later(func() { + switch typ.under().(type) { + case *Named, *instance: + panic("internal error: unexpanded underlying type") + } + typ.check = nil + }) + } return typ } -- GitLab From 2fed6926a152d67b5d001d68899edc5e97d599f1 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Tue, 25 May 2021 11:10:25 -0400 Subject: [PATCH 0151/2500] [dev.fuzz] cmd/go/internal: instrument imports of the test Previously, the packages that were imported by the test were not instrumented for coverage. This meant that a fuzz target in a stand-alone test file would not be able to perform coverage-guided fuzzing. The fix uses all of the imports, including those from the test files, when determining which packages to instrument. However, certain package should be ignored when walking the import graph. Otherwise, packages like internal/fuzz, and its imports, may be instrumented, which could lead to false positives for "interesting" corpus values. There was an additional bug which needed to be fixed in order for this to work. The bug was in the fact that the GcFlags which held `-d=libfuzzer` were being overwritten in some cases. The fix updates the way these flags are set in order to prevent this behavior. Change-Id: I21d336c29a33db1181bbae0fd23678d127fe52a0 Reviewed-on: https://go-review.googlesource.com/c/go/+/321960 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/load/flag.go | 5 +++-- src/cmd/go/internal/load/pkg.go | 25 +++++++++++++------------ src/cmd/go/internal/test/test.go | 16 +++++++++++++--- 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/cmd/go/internal/load/flag.go b/src/cmd/go/internal/load/flag.go index 440cb86134..274c0f23e2 100644 --- a/src/cmd/go/internal/load/flag.go +++ b/src/cmd/go/internal/load/flag.go @@ -22,8 +22,9 @@ var ( // that allows specifying different effective flags for different packages. // See 'go help build' for more details about per-package flags. type PerPackageFlag struct { - present bool - values []ppfValue + present bool + values []ppfValue + seenPackages map[*Package]bool // the packages for which the flags have already been set } // A ppfValue is a single = per-package flag value. diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index 193a27a713..9d7d32b5d1 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -210,7 +210,6 @@ type PackageInternal struct { BuildInfo string // add this info to package main TestmainGo *[]byte // content for _testmain.go Embed map[string][]string // //go:embed comment mapping - FlagsSet bool // whether the flags have been set OrigImportPath string // original import path before adding '_test' suffix Asmflags []string // -asmflags for this package @@ -2628,18 +2627,20 @@ func (e *mainPackageError) ImportPath() string { func setToolFlags(pkgs ...*Package) { for _, p := range PackageList(pkgs) { - // TODO(jayconrod,katiehockman): See if there's a better way to do this. - if p.Internal.FlagsSet { - // The flags have already been set, so don't re-run this and - // potentially clear existing flags. - continue - } else { - p.Internal.FlagsSet = true + appendFlags(p, &p.Internal.Asmflags, &BuildAsmflags) + appendFlags(p, &p.Internal.Gcflags, &BuildGcflags) + appendFlags(p, &p.Internal.Ldflags, &BuildLdflags) + appendFlags(p, &p.Internal.Gccgoflags, &BuildGccgoflags) + } +} + +func appendFlags(p *Package, flags *[]string, packageFlag *PerPackageFlag) { + if !packageFlag.seenPackages[p] { + if packageFlag.seenPackages == nil { + packageFlag.seenPackages = make(map[*Package]bool) } - p.Internal.Asmflags = BuildAsmflags.For(p) - p.Internal.Gcflags = BuildGcflags.For(p) - p.Internal.Ldflags = BuildLdflags.For(p) - p.Internal.Gccgoflags = BuildGccgoflags.For(p) + packageFlag.seenPackages[p] = true + *flags = append(*flags, packageFlag.For(p)...) } } diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index d5afae782b..012a75123b 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -826,11 +826,21 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { } } + // Inform the compiler that it should instrument the binary at + // build-time when fuzzing is enabled. fuzzFlags := work.FuzzInstrumentFlags() if testFuzz != "" && fuzzFlags != nil { - // Inform the compiler that it should instrument the binary at - // build-time when fuzzing is enabled. - for _, p := range load.PackageList(pkgs) { + // Don't instrument packages which may affect coverage guidance but are + // unlikely to be useful. + var fuzzNoInstrument = map[string]bool{ + "testing": true, + "internal/fuzz": true, + "runtime": true, + } + for _, p := range load.TestPackageList(ctx, pkgOpts, pkgs) { + if fuzzNoInstrument[p.ImportPath] { + continue + } p.Internal.Gcflags = append(p.Internal.Gcflags, fuzzFlags...) } } -- GitLab From c2c1b53b39fd54b915b2a4bbae36d1c9793fac8a Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Thu, 27 May 2021 11:18:13 -0700 Subject: [PATCH 0152/2500] [dev.typeparams] cmd/compile: use old export format if not compiling with generics Write out export data with the old export format (iexportVersionPosCol) if not compiling with generics (-G=0, the default value). This helps ensure we don't break tests involving x/tools/go/gcexportdata (since we can't modify that tool yet to use the new format). Change-Id: I5f9bce44ed1e0696fc65fead6bab9e30de88461d Reviewed-on: https://go-review.googlesource.com/c/go/+/323189 Reviewed-by: Robert Griesemer Reviewed-by: Matthew Dempsky Trust: Robert Griesemer --- src/cmd/compile/internal/typecheck/iexport.go | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index ea8e751852..9c24213176 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -306,7 +306,12 @@ func WriteExports(out *bufio.Writer) { // Assemble header. var hdr intWriter hdr.WriteByte('i') - hdr.uint64(iexportVersionCurrent) + if base.Flag.G > 0 { + hdr.uint64(iexportVersionCurrent) + } else { + // Use old export format if doing -G=0 (no generics) + hdr.uint64(iexportVersionPosCol) + } hdr.uint64(uint64(p.strings.Len())) hdr.uint64(dataLen) @@ -478,7 +483,9 @@ func (p *iexporter) doDecl(n *ir.Name) { // referenced via their type offset (via typOff) in all // other places in the signature and function that they // are used. - w.tparamList(n.Type().TParams().FieldSlice()) + if base.Flag.G > 0 { + w.tparamList(n.Type().TParams().FieldSlice()) + } w.signature(n.Type()) w.funcExt(n) @@ -511,8 +518,10 @@ func (p *iexporter) doDecl(n *ir.Name) { w.tag('T') w.pos(n.Pos()) - // Export any new typeparams needed for this type - w.typeList(n.Type().RParams()) + if base.Flag.G > 0 { + // Export any new typeparams needed for this type + w.typeList(n.Type().RParams()) + } underlying := n.Type().Underlying() if underlying == types.ErrorType.Underlying() { // For "type T error", use error as the @@ -826,6 +835,7 @@ func (w *exportWriter) startType(k itag) { func (w *exportWriter) doTyp(t *types.Type) { if t.Kind() == types.TTYPEPARAM { + assert(base.Flag.G > 0) // A typeparam has a name, but doesn't have an underlying type. // Just write out the details of the type param here. All other // uses of this typeparam type will be written out as its unique @@ -846,6 +856,7 @@ func (w *exportWriter) doTyp(t *types.Type) { s := t.Sym() if s != nil && t.OrigSym != nil { + assert(base.Flag.G > 0) // This is an instantiated type - could be a re-instantiation like // Value[T2] or a full instantiation like Value[int]. if strings.Index(s.Name, "[") < 0 { @@ -945,6 +956,7 @@ func (w *exportWriter) doTyp(t *types.Type) { } case types.TUNION: + assert(base.Flag.G > 0) // TODO(danscales): possibly put out the tilde bools in more // compact form. w.startType(unionType) -- GitLab From de5d1aca5e61e49e0704213961c68bcf14e288b8 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 26 May 2021 19:52:31 -0700 Subject: [PATCH 0153/2500] [dev.typeparams] cmd/compile: tweaks to match types2 This CL makes a handful of changes to either bring existing compiler output consistent with what types2 produces or to make it easier to reproduce with types2: 1. The position for embedded fields is corrected to the position of the syntax.Field, rather than the syntax.Type. 2. Methods and embedded types are sorted in export data the same way that types2 sorts them. 3. Don't write out position information for OLITERALs that don't have their own position (i.e., references to named constants). Change-Id: Ic3979215ae9ef280cfbba7b44c236e03fc12a2ef Reviewed-on: https://go-review.googlesource.com/c/go/+/323209 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer Reviewed-by: Dan Scales Trust: Matthew Dempsky --- src/cmd/compile/internal/noder/noder.go | 6 +++-- src/cmd/compile/internal/typecheck/iexport.go | 23 +++++++++++++++---- src/cmd/compile/internal/types/size.go | 7 +++++- src/cmd/compile/internal/types/sort.go | 13 +++++++---- 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index 06c3b00601..44385f34fd 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -986,6 +986,8 @@ func (p *noder) packname(expr syntax.Expr) *types.Sym { } func (p *noder) embedded(typ syntax.Expr) *ir.Field { + pos := p.pos(syntax.StartPos(typ)) + op, isStar := typ.(*syntax.Operation) if isStar { if op.Op != syntax.Mul || op.Y != nil { @@ -995,11 +997,11 @@ func (p *noder) embedded(typ syntax.Expr) *ir.Field { } sym := p.packname(typ) - n := ir.NewField(p.pos(typ), typecheck.Lookup(sym.Name), importName(sym).(ir.Ntype), nil) + n := ir.NewField(pos, typecheck.Lookup(sym.Name), importName(sym).(ir.Ntype), nil) n.Embedded = true if isStar { - n.Ntype = ir.NewStarExpr(p.pos(op), n.Ntype) + n.Ntype = ir.NewStarExpr(pos, n.Ntype) } return n } diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 9c24213176..e798ce5143 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -540,9 +540,12 @@ func (p *iexporter) doDecl(n *ir.Name) { break } - ms := t.Methods() - w.uint64(uint64(ms.Len())) - for _, m := range ms.Slice() { + // Sort methods, for consistency with types2. + methods := append([]*types.Field(nil), t.Methods().Slice()...) + sort.Sort(types.MethodsByName(methods)) + + w.uint64(uint64(len(methods))) + for _, m := range methods { w.pos(m.Pos) w.selector(m.Sym) w.param(m.Type.Recv()) @@ -550,7 +553,7 @@ func (p *iexporter) doDecl(n *ir.Name) { } w.typeExt(t) - for _, m := range ms.Slice() { + for _, m := range methods { w.methExt(m) } @@ -939,6 +942,12 @@ func (w *exportWriter) doTyp(t *types.Type) { } } + // Sort methods and embedded types, for consistency with types2. + // Note: embedded types may be anonymous, and types2 sorts them + // with sort.Stable too. + sort.Sort(types.MethodsByName(methods)) + sort.Stable(types.EmbeddedsByName(embeddeds)) + w.startType(interfaceType) w.setPkg(t.Pkg(), true) @@ -1590,7 +1599,11 @@ func (w *exportWriter) expr(n ir.Node) { case ir.OLITERAL: w.op(ir.OLITERAL) - w.pos(n.Pos()) + if ir.HasUniquePos(n) { + w.pos(n.Pos()) + } else { + w.pos(src.NoXPos) + } w.value(n.Type(), n.Val()) case ir.ONAME: diff --git a/src/cmd/compile/internal/types/size.go b/src/cmd/compile/internal/types/size.go index 7059eff398..e6ca4556b9 100644 --- a/src/cmd/compile/internal/types/size.go +++ b/src/cmd/compile/internal/types/size.go @@ -126,10 +126,15 @@ func expandiface(t *Type) { // (including broken ones, if any) and add to t's // method set. for _, t1 := range m.Type.AllMethods().Slice() { - // Use m.Pos rather than t1.Pos to preserve embedding position. f := NewField(m.Pos, t1.Sym, t1.Type) addMethod(f, false) + + // Clear position after typechecking, for consistency with types2. + f.Pos = src.NoXPos } + + // Clear position after typechecking, for consistency with types2. + m.Pos = src.NoXPos } sort.Sort(MethodsByName(methods)) diff --git a/src/cmd/compile/internal/types/sort.go b/src/cmd/compile/internal/types/sort.go index dc59b06415..765c070cd9 100644 --- a/src/cmd/compile/internal/types/sort.go +++ b/src/cmd/compile/internal/types/sort.go @@ -4,11 +4,16 @@ package types -// MethodsByName sorts methods by symbol. +// MethodsByName sorts methods by name. type MethodsByName []*Field -func (x MethodsByName) Len() int { return len(x) } +func (x MethodsByName) Len() int { return len(x) } +func (x MethodsByName) Swap(i, j int) { x[i], x[j] = x[j], x[i] } +func (x MethodsByName) Less(i, j int) bool { return x[i].Sym.Less(x[j].Sym) } -func (x MethodsByName) Swap(i, j int) { x[i], x[j] = x[j], x[i] } +// EmbeddedsByName sorts embedded types by name. +type EmbeddedsByName []*Field -func (x MethodsByName) Less(i, j int) bool { return x[i].Sym.Less(x[j].Sym) } +func (x EmbeddedsByName) Len() int { return len(x) } +func (x EmbeddedsByName) Swap(i, j int) { x[i], x[j] = x[j], x[i] } +func (x EmbeddedsByName) Less(i, j int) bool { return x[i].Type.Sym().Less(x[j].Type.Sym()) } -- GitLab From ea522bc546bb9f66285ea00744de8b258368b3ed Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 27 May 2021 02:50:17 -0700 Subject: [PATCH 0154/2500] [dev.typeparams] cmd/compile: add and use ir.RawOrigExpr This CL adds ir.RawOrigExpr, which can be used to represent arbitrary constant expressions without needing to build and carry around an entire IR representation of the original expression. It also allows distinguishing how the constant was originally written by the user (e.g., "0xff" vs "255"). This CL then also updates irgen to make use of this functionality for expressions that were constant folded by types2. Change-Id: I41e04e228e715ae2735c357b75633a2d08ee7021 Reviewed-on: https://go-review.googlesource.com/c/go/+/323210 Trust: Matthew Dempsky Trust: Robert Griesemer Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer Reviewed-by: Dan Scales --- src/cmd/compile/internal/ir/expr.go | 14 +++++++ src/cmd/compile/internal/ir/fmt.go | 5 +++ src/cmd/compile/internal/ir/node_gen.go | 16 +++++++ src/cmd/compile/internal/ir/val.go | 2 +- src/cmd/compile/internal/noder/expr.go | 51 ++++++++++++++++++++--- src/cmd/compile/internal/noder/helpers.go | 26 ++++++++++++ 6 files changed, 107 insertions(+), 7 deletions(-) diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 9ea8b61965..519120ed6b 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -448,6 +448,20 @@ func (n *ParenExpr) SetOTYPE(t *types.Type) { t.SetNod(n) } +// A RawOrigExpr represents an arbitrary Go expression as a string value. +// When printed in diagnostics, the string value is written out exactly as-is. +type RawOrigExpr struct { + miniExpr + Raw string +} + +func NewRawOrigExpr(pos src.XPos, op Op, raw string) *RawOrigExpr { + n := &RawOrigExpr{Raw: raw} + n.pos = pos + n.op = op + return n +} + // A ResultExpr represents a direct access to a result. type ResultExpr struct { miniExpr diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index 4ac5f3fea2..d9cc5f109f 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -567,6 +567,11 @@ func exprFmt(n Node, s fmt.State, prec int) { return } + if n, ok := n.(*RawOrigExpr); ok { + fmt.Fprint(s, n.Raw) + return + } + switch n.Op() { case OPAREN: n := n.(*ParenExpr) diff --git a/src/cmd/compile/internal/ir/node_gen.go b/src/cmd/compile/internal/ir/node_gen.go index 22855d7163..9a4858d037 100644 --- a/src/cmd/compile/internal/ir/node_gen.go +++ b/src/cmd/compile/internal/ir/node_gen.go @@ -947,6 +947,22 @@ func (n *RangeStmt) editChildren(edit func(Node) Node) { } } +func (n *RawOrigExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) } +func (n *RawOrigExpr) copy() Node { + c := *n + c.init = copyNodes(c.init) + return &c +} +func (n *RawOrigExpr) doChildren(do func(Node) bool) bool { + if doNodes(n.init, do) { + return true + } + return false +} +func (n *RawOrigExpr) editChildren(edit func(Node) Node) { + editNodes(n.init, edit) +} + func (n *ResultExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) } func (n *ResultExpr) copy() Node { c := *n diff --git a/src/cmd/compile/internal/ir/val.go b/src/cmd/compile/internal/ir/val.go index af9f95b29d..bfe7d2bb43 100644 --- a/src/cmd/compile/internal/ir/val.go +++ b/src/cmd/compile/internal/ir/val.go @@ -66,7 +66,7 @@ func Float64Val(v constant.Value) float64 { func AssertValidTypeForConst(t *types.Type, v constant.Value) { if !ValidTypeForConst(t, v) { - base.Fatalf("%v does not represent %v (%v)", t, v, v.Kind()) + base.Fatalf("%v (%v) does not represent %v (%v)", t, t.Kind(), v, v.Kind()) } } diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index f96144f8d7..c901dc5534 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -5,6 +5,8 @@ package noder import ( + "fmt" + "cmd/compile/internal/base" "cmd/compile/internal/ir" "cmd/compile/internal/syntax" @@ -15,6 +17,8 @@ import ( ) func (g *irgen) expr(expr syntax.Expr) ir.Node { + expr = unparen(expr) // skip parens; unneeded after parse+typecheck + if expr == nil { return nil } @@ -67,7 +71,9 @@ func (g *irgen) expr(expr syntax.Expr) ir.Node { // Constant expression. if tv.Value != nil { - return Const(g.pos(expr), g.typ(typ), tv.Value) + typ := g.typ(typ) + value := FixValue(typ, tv.Value) + return OrigConst(g.pos(expr), typ, value, constExprOp(expr), syntax.String(expr)) } n := g.expr0(typ, expr) @@ -161,9 +167,6 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { typed(g.typ(typ), n) return n - case *syntax.ParenExpr: - return g.expr(expr.X) // skip parens; unneeded after parse+typecheck - case *syntax.SelectorExpr: // Qualified identifier. if name, ok := expr.X.(*syntax.Name); ok { @@ -317,13 +320,17 @@ func getTargs(selinfo *types2.Selection) []types2.Type { } func (g *irgen) exprList(expr syntax.Expr) []ir.Node { + return g.exprs(unpackListExpr(expr)) +} + +func unpackListExpr(expr syntax.Expr) []syntax.Expr { switch expr := expr.(type) { case nil: return nil case *syntax.ListExpr: - return g.exprs(expr.ElemList) + return expr.ElemList default: - return []ir.Node{g.expr(expr)} + return []syntax.Expr{expr} } } @@ -402,3 +409,35 @@ func (g *irgen) typeExpr(typ syntax.Expr) *types.Type { } return n.Type() } + +// constExprOp returns an ir.Op that represents the outermost +// operation of the given constant expression. It's intended for use +// with ir.RawOrigExpr. +func constExprOp(expr syntax.Expr) ir.Op { + switch expr := expr.(type) { + default: + panic(fmt.Sprintf("%s: unexpected expression: %T", expr.Pos(), expr)) + + case *syntax.BasicLit: + return ir.OLITERAL + case *syntax.Name, *syntax.SelectorExpr: + return ir.ONAME + case *syntax.CallExpr: + return ir.OCALL + case *syntax.Operation: + if expr.Y == nil { + return unOps[expr.Op] + } + return binOps[expr.Op] + } +} + +func unparen(expr syntax.Expr) syntax.Expr { + for { + paren, ok := expr.(*syntax.ParenExpr) + if !ok { + return expr + } + expr = paren.X + } +} diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index 9da0e49300..ea30a3bfa9 100644 --- a/src/cmd/compile/internal/noder/helpers.go +++ b/src/cmd/compile/internal/noder/helpers.go @@ -43,6 +43,32 @@ func Const(pos src.XPos, typ *types.Type, val constant.Value) ir.Node { return typed(typ, ir.NewBasicLit(pos, val)) } +func OrigConst(pos src.XPos, typ *types.Type, val constant.Value, op ir.Op, raw string) ir.Node { + orig := ir.NewRawOrigExpr(pos, op, raw) + return ir.NewConstExpr(val, typed(typ, orig)) +} + +// FixValue returns val after converting and truncating it as +// appropriate for typ. +func FixValue(typ *types.Type, val constant.Value) constant.Value { + assert(typ.Kind() != types.TFORW) + switch { + case typ.IsInteger(): + val = constant.ToInt(val) + case typ.IsFloat(): + val = constant.ToFloat(val) + case typ.IsComplex(): + val = constant.ToComplex(val) + } + if !typ.IsUntyped() { + val = typecheck.DefaultLit(ir.NewBasicLit(src.NoXPos, val), typ).Val() + } + if typ.Kind() != types.TTYPEPARAM { + ir.AssertValidTypeForConst(typ, val) + } + return val +} + func Nil(pos src.XPos, typ *types.Type) ir.Node { return typed(typ, ir.NewNilExpr(pos)) } -- GitLab From 88583a2a6639c72f2cb0143b0135f50fa6b379c0 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 27 May 2021 02:42:15 -0700 Subject: [PATCH 0155/2500] [dev.typeparams] test: trim list of expected -G=3 failures 15 more tests are passing from recent changes. 83 still to go. Change-Id: I155b3e3db966d604ccec8bf3a7c182421f3d26c4 Reviewed-on: https://go-review.googlesource.com/c/go/+/323211 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- test/run.go | 59 ++++++++++++++++++++--------------------------------- 1 file changed, 22 insertions(+), 37 deletions(-) diff --git a/test/run.go b/test/run.go index ef24396809..cf1d301598 100644 --- a/test/run.go +++ b/test/run.go @@ -2024,19 +2024,16 @@ func overlayDir(dstRoot, srcRoot string) error { // Temporary scaffolding until we pass all the tests at which point this map can be removed. var excludedFiles = map[string]bool{ "complit1.go": true, // types2 reports extra errors - "const2.go": true, // types2 not run after syntax errors "ddd1.go": true, // issue #42987 "directive.go": true, // misplaced compiler directive checks "float_lit3.go": true, // types2 reports extra errors "import1.go": true, // types2 reports extra errors - "import5.go": true, // issue #42988 "import6.go": true, // issue #43109 "initializerr.go": true, // types2 reports extra errors "linkname2.go": true, // error reported by noder (not running for types2 errorcheck test) "notinheap.go": true, // types2 doesn't report errors about conversions that are invalid due to //go:notinheap "printbig.go": true, // large untyped int passed to print (32-bit) "shift1.go": true, // issue #42989 - "shift2.go": true, // bad code generation; constant.Value of the wrong kind? "typecheck.go": true, // invalid function is not causing errors when called "writebarrier.go": true, // correct diagnostics, but different lines (probably irgen's fault) @@ -2048,18 +2045,15 @@ var excludedFiles = map[string]bool{ "fixedbugs/bug228.go": true, // types2 doesn't run when there are syntax errors "fixedbugs/bug231.go": true, // types2 bug? (same error reported twice) "fixedbugs/bug255.go": true, // types2 reports extra errors - "fixedbugs/bug351.go": true, // types2 reports extra errors "fixedbugs/bug374.go": true, // types2 reports extra errors "fixedbugs/bug385_32.go": true, // types2 doesn't produce missing error "type .* too large" (32-bit specific) "fixedbugs/bug388.go": true, // types2 not run due to syntax errors "fixedbugs/bug412.go": true, // types2 produces a follow-on error - "fixedbugs/bug420.go": true, // ICE in irgen "fixedbugs/issue10700.go": true, // types2 reports ok hint, but does not match regexp "fixedbugs/issue11590.go": true, // types2 doesn't report a follow-on error (pref: types2) "fixedbugs/issue11610.go": true, // types2 not run after syntax errors "fixedbugs/issue11614.go": true, // types2 reports an extra error - "fixedbugs/issue13415.go": true, // declared but not used conflict "fixedbugs/issue14520.go": true, // missing import path error by types2 "fixedbugs/issue16133.go": true, // types2 doesn't use package path for qualified identifiers when package name is ambiguous "fixedbugs/issue16428.go": true, // types2 reports two instead of one error @@ -2067,7 +2061,6 @@ var excludedFiles = map[string]bool{ "fixedbugs/issue17270.go": true, // ICE in irgen "fixedbugs/issue17645.go": true, // multiple errors on same line "fixedbugs/issue18331.go": true, // missing error about misuse of //go:noescape (irgen needs code from noder) - "fixedbugs/issue18393.go": true, // types2 not run after syntax errors "fixedbugs/issue18419.go": true, // types2 reports "fixedbugs/issue19012.go": true, // multiple errors on same line "fixedbugs/issue20174.go": true, // ICE due to width not calculated (probably irgen's fault) @@ -2082,15 +2075,12 @@ var excludedFiles = map[string]bool{ "fixedbugs/issue28268.go": true, // types2 reports follow-on errors "fixedbugs/issue31053.go": true, // types2 reports "unknown field" instead of "cannot refer to unexported field" "fixedbugs/issue33460.go": true, // types2 reports alternative positions in separate error - "fixedbugs/issue41575.go": true, // types2 reports alternative positions in separate error "fixedbugs/issue42058a.go": true, // types2 doesn't report "channel element type too large" "fixedbugs/issue42058b.go": true, // types2 doesn't report "channel element type too large" "fixedbugs/issue4232.go": true, // types2 reports (correct) extra errors - "fixedbugs/issue43479.go": true, // ICE in iexport due to Syms from the wrong package "fixedbugs/issue4452.go": true, // types2 reports (correct) extra errors "fixedbugs/issue4510.go": true, // types2 reports different (but ok) line numbers "fixedbugs/issue5609.go": true, // types2 needs a better error message - "fixedbugs/issue6889.go": true, // types2 can handle this without constant overflow "fixedbugs/issue7525b.go": true, // types2 reports init cycle error on different line - ok otherwise "fixedbugs/issue7525c.go": true, // types2 reports init cycle error on different line - ok otherwise "fixedbugs/issue7525d.go": true, // types2 reports init cycle error on different line - ok otherwise @@ -2105,31 +2095,26 @@ var excludedFiles = map[string]bool{ // - Some escape analysis diagnostics being printed without position information // - Some expressions printed differently (e.g., "int(100)" instead // of "100" or "&composite literal" instead of "&[4]int{...}"). - "closure3.go": true, - "escape2.go": true, - "escape2n.go": true, - "escape4.go": true, - "escape5.go": true, - "escape_array.go": true, - "escape_calls.go": true, - "escape_field.go": true, - "escape_iface.go": true, - "escape_indir.go": true, - "escape_level.go": true, - "escape_map.go": true, - "escape_param.go": true, - "escape_slice.go": true, - "escape_struct_param1.go": true, - "escape_struct_param2.go": true, - "fixedbugs/issue12006.go": true, - "fixedbugs/issue13799.go": true, - "fixedbugs/issue21709.go": true, - "fixedbugs/issue24651a.go": true, - "fixedbugs/issue24651b.go": true, - "fixedbugs/issue27557.go": true, - "fixedbugs/issue31573.go": true, - "fixedbugs/issue37837.go": true, - "fixedbugs/issue39292.go": true, - "fixedbugs/issue7921.go": true, - "inline.go": true, + "closure3.go": true, + "escape2.go": true, + "escape2n.go": true, + "escape4.go": true, + "escape_calls.go": true, + "escape_field.go": true, + "escape_iface.go": true, + "escape_indir.go": true, + "escape_level.go": true, + "escape_map.go": true, + "escape_param.go": true, + "escape_slice.go": true, + "escape_struct_param1.go": true, + "escape_struct_param2.go": true, + "fixedbugs/issue12006.go": true, + "fixedbugs/issue13799.go": true, + "fixedbugs/issue21709.go": true, + "fixedbugs/issue31573.go": true, + "fixedbugs/issue37837.go": true, + "fixedbugs/issue39292.go": true, + "fixedbugs/issue7921.go": true, + "inline.go": true, } -- GitLab From 417955d151359629ca11be968e3056e6636b828e Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 27 May 2021 02:47:04 -0700 Subject: [PATCH 0156/2500] [dev.typeparams] cmd/compile/internal/inline: refactor mkinlcall This CL refactors mkinlcall by extracting the core InlinedCallExpr construction code into a new "oldInline" function, and adds a new "NewInline" hook point that can be overriden with a new inliner implementation that only needs to worry about the details of constructing the InlinedCallExpr. It also moves the delayretvars optimization check into CanInline, so it's performed just once per inlinable function rather than once for each inlined call. Finally, it skips printing the function body about to be inlined (and updates the couple of regress tests that expected this output). We already report the inline body as it was saved, and this diagnostic is only applicable to the current inliner, which clones existing function body instances. In the unified IR inliner, we'll directly construct inline bodies from the serialized representation. Change-Id: Ibdbe617da83c07665dcbda402cc8d4d4431dde2f Reviewed-on: https://go-review.googlesource.com/c/go/+/323290 Trust: Matthew Dempsky Trust: Dan Scales Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/inline/inl.go | 187 ++++++++++-------- src/cmd/compile/internal/ir/func.go | 5 + src/cmd/compile/internal/typecheck/iexport.go | 1 + src/cmd/compile/internal/typecheck/iimport.go | 3 +- test/fixedbugs/issue24651a.go | 2 +- test/fixedbugs/issue24651b.go | 4 +- test/inline_big.go | 2 +- 7 files changed, 113 insertions(+), 91 deletions(-) diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index 042e3f2332..594f280f03 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -179,6 +179,8 @@ func CanInline(fn *ir.Func) { Cost: inlineMaxBudget - visitor.budget, Dcl: pruneUnusedAutos(n.Defn.(*ir.Func).Dcl, &visitor), Body: inlcopylist(fn.Body), + + CanDelayResults: canDelayResults(fn), } if base.Flag.LowerM > 1 { @@ -191,6 +193,38 @@ func CanInline(fn *ir.Func) { } } +// canDelayResults reports whether inlined calls to fn can delay +// declaring the result parameter until the "return" statement. +func canDelayResults(fn *ir.Func) bool { + // We can delay declaring+initializing result parameters if: + // (1) there's exactly one "return" statement in the inlined function; + // (2) it's not an empty return statement (#44355); and + // (3) the result parameters aren't named. + + nreturns := 0 + ir.VisitList(fn.Body, func(n ir.Node) { + if n, ok := n.(*ir.ReturnStmt); ok { + nreturns++ + if len(n.Results) == 0 { + nreturns++ // empty return statement (case 2) + } + } + }) + + if nreturns != 1 { + return false // not exactly one return statement (case 1) + } + + // temporaries for return values. + for _, param := range fn.Type().Results().FieldSlice() { + if sym := types.OrigSym(param.Sym); sym != nil && !sym.IsBlank() { + return false // found a named result parameter (case 3) + } + } + + return true +} + // Inline_Flood marks n's inline body for export and recursively ensures // all called functions are marked too. func Inline_Flood(n *ir.Name, exportsym func(*ir.Name)) { @@ -740,6 +774,11 @@ var inlgen int // when producing output for debugging the compiler itself. var SSADumpInline = func(*ir.Func) {} +// NewInline allows the inliner implementation to be overridden. +// If it returns nil, the legacy inliner will handle this call +// instead. +var NewInline = func(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExpr { return nil } + // If n is a call node (OCALLFUNC or OCALLMETH), and fn is an ONAME node for a // function with an inlinable body, return an OINLCALL node that can replace n. // The returned node's Ninit has the parameter assignments, the Nbody is the @@ -796,30 +835,64 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b typecheck.FixVariadicCall(n) - if base.Debug.TypecheckInl == 0 { - typecheck.ImportedBody(fn) + parent := base.Ctxt.PosTable.Pos(n.Pos()).Base().InliningIndex() + + sym := fn.Linksym() + inlIndex := base.Ctxt.InlTree.Add(parent, n.Pos(), sym) + + if base.Flag.GenDwarfInl > 0 { + if !sym.WasInlined() { + base.Ctxt.DwFixups.SetPrecursorFunc(sym, fn) + sym.Set(obj.AttrWasInlined, true) + } } - // We have a function node, and it has an inlineable body. - if base.Flag.LowerM > 1 { - fmt.Printf("%v: inlining call to %v %v { %v }\n", ir.Line(n), fn.Sym(), fn.Type(), ir.Nodes(fn.Inl.Body)) - } else if base.Flag.LowerM != 0 { + if base.Flag.LowerM != 0 { fmt.Printf("%v: inlining call to %v\n", ir.Line(n), fn) } if base.Flag.LowerM > 2 { fmt.Printf("%v: Before inlining: %+v\n", ir.Line(n), n) } + res := NewInline(n, fn, inlIndex) + if res == nil { + res = oldInline(n, fn, inlIndex) + } + + // transitive inlining + // might be nice to do this before exporting the body, + // but can't emit the body with inlining expanded. + // instead we emit the things that the body needs + // and each use must redo the inlining. + // luckily these are small. + ir.EditChildren(res, edit) + + if base.Flag.LowerM > 2 { + fmt.Printf("%v: After inlining %+v\n\n", ir.Line(res), res) + } + + return res +} + +// oldInline creates an InlinedCallExpr to replace the given call +// expression. fn is the callee function to be inlined. inlIndex is +// the inlining tree position index, for use with src.NewInliningBase +// when rewriting positions. +func oldInline(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExpr { + if base.Debug.TypecheckInl == 0 { + typecheck.ImportedBody(fn) + } + SSADumpInline(fn) - ninit := n.Init() + ninit := call.Init() // For normal function calls, the function callee expression // may contain side effects (e.g., added by addinit during // inlconv2expr or inlconv2list). Make sure to preserve these, // if necessary (#42703). - if n.Op() == ir.OCALLFUNC { - callee := n.X + if call.Op() == ir.OCALLFUNC { + callee := call.X for callee.Op() == ir.OCONVNOP { conv := callee.(*ir.ConvExpr) ninit.Append(ir.TakeInit(conv)...) @@ -857,25 +930,6 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b } // We can delay declaring+initializing result parameters if: - // (1) there's exactly one "return" statement in the inlined function; - // (2) it's not an empty return statement (#44355); and - // (3) the result parameters aren't named. - delayretvars := true - - nreturns := 0 - ir.VisitList(ir.Nodes(fn.Inl.Body), func(n ir.Node) { - if n, ok := n.(*ir.ReturnStmt); ok { - nreturns++ - if len(n.Results) == 0 { - delayretvars = false // empty return statement (case 2) - } - } - }) - - if nreturns != 1 { - delayretvars = false // not exactly one return statement (case 1) - } - // temporaries for return values. var retvars []ir.Node for i, t := range fn.Type().Results().Fields().Slice() { @@ -885,7 +939,6 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b m = inlvar(n) m = typecheck.Expr(m).(*ir.Name) inlvars[n] = m - delayretvars = false // found a named result parameter (case 3) } else { // anonymous return values, synthesize names for use in assignment that replaces return m = retvar(t, i) @@ -908,14 +961,14 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b // Assign arguments to the parameters' temp names. as := ir.NewAssignListStmt(base.Pos, ir.OAS2, nil, nil) as.Def = true - if n.Op() == ir.OCALLMETH { - sel := n.X.(*ir.SelectorExpr) + if call.Op() == ir.OCALLMETH { + sel := call.X.(*ir.SelectorExpr) if sel.X == nil { - base.Fatalf("method call without receiver: %+v", n) + base.Fatalf("method call without receiver: %+v", call) } as.Rhs.Append(sel.X) } - as.Rhs.Append(n.Args...) + as.Rhs.Append(call.Args...) if recv := fn.Type().Recv(); recv != nil { as.Lhs.Append(inlParam(recv, as, inlvars)) @@ -928,7 +981,7 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b ninit.Append(typecheck.Stmt(as)) } - if !delayretvars { + if !fn.Inl.CanDelayResults { // Zero the return parameters. for _, n := range retvars { ninit.Append(ir.NewDecl(base.Pos, ir.ODCL, n.(*ir.Name))) @@ -941,40 +994,21 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b inlgen++ - parent := -1 - if b := base.Ctxt.PosTable.Pos(n.Pos()).Base(); b != nil { - parent = b.InliningIndex() - } - - sym := fn.Linksym() - newIndex := base.Ctxt.InlTree.Add(parent, n.Pos(), sym) - // Add an inline mark just before the inlined body. // This mark is inline in the code so that it's a reasonable spot // to put a breakpoint. Not sure if that's really necessary or not // (in which case it could go at the end of the function instead). // Note issue 28603. - inlMark := ir.NewInlineMarkStmt(base.Pos, types.BADWIDTH) - inlMark.SetPos(n.Pos().WithIsStmt()) - inlMark.Index = int64(newIndex) - ninit.Append(inlMark) - - if base.Flag.GenDwarfInl > 0 { - if !sym.WasInlined() { - base.Ctxt.DwFixups.SetPrecursorFunc(sym, fn) - sym.Set(obj.AttrWasInlined, true) - } - } + ninit.Append(ir.NewInlineMarkStmt(call.Pos().WithIsStmt(), int64(inlIndex))) subst := inlsubst{ - retlabel: retlabel, - retvars: retvars, - delayretvars: delayretvars, - inlvars: inlvars, - defnMarker: ir.NilExpr{}, - bases: make(map[*src.PosBase]*src.PosBase), - newInlIndex: newIndex, - fn: fn, + retlabel: retlabel, + retvars: retvars, + inlvars: inlvars, + defnMarker: ir.NilExpr{}, + bases: make(map[*src.PosBase]*src.PosBase), + newInlIndex: inlIndex, + fn: fn, } subst.edit = subst.node @@ -995,26 +1029,11 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b //dumplist("ninit post", ninit); - call := ir.NewInlinedCallExpr(base.Pos, nil, nil) - *call.PtrInit() = ninit - call.Body = body - call.ReturnVars = retvars - call.SetType(n.Type()) - call.SetTypecheck(1) - - // transitive inlining - // might be nice to do this before exporting the body, - // but can't emit the body with inlining expanded. - // instead we emit the things that the body needs - // and each use must redo the inlining. - // luckily these are small. - ir.EditChildren(call, edit) - - if base.Flag.LowerM > 2 { - fmt.Printf("%v: After inlining %+v\n\n", ir.Line(call), call) - } - - return call + res := ir.NewInlinedCallExpr(base.Pos, body, retvars) + res.SetInit(ninit) + res.SetType(call.Type()) + res.SetTypecheck(1) + return res } // Every time we expand a function we generate a new set of tmpnames, @@ -1057,10 +1076,6 @@ type inlsubst struct { // Temporary result variables. retvars []ir.Node - // Whether result variables should be initialized at the - // "return" statement. - delayretvars bool - inlvars map[*ir.Name]*ir.Name // defnMarker is used to mark a Node for reassignment. // inlsubst.clovar set this during creating new ONAME. @@ -1353,7 +1368,7 @@ func (subst *inlsubst) node(n ir.Node) ir.Node { } as.Rhs = subst.list(n.Results) - if subst.delayretvars { + if subst.fn.Inl.CanDelayResults { for _, n := range as.Lhs { as.PtrInit().Append(ir.NewDecl(base.Pos, ir.ODCL, n.(*ir.Name))) n.Name().Defn = as diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go index a4231a1bcb..ca6c8eca8b 100644 --- a/src/cmd/compile/internal/ir/func.go +++ b/src/cmd/compile/internal/ir/func.go @@ -166,6 +166,11 @@ type Inline struct { // another package is imported. Dcl []*Name Body []Node + + // CanDelayResults reports whether it's safe for the inliner to delay + // initializing the result parameters until immediately before the + // "return" statement. + CanDelayResults bool } // A Mark represents a scope boundary. diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index e798ce5143..f49718d442 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -1313,6 +1313,7 @@ func (w *exportWriter) funcExt(n *ir.Name) { } if n.Func.Inl != nil { w.uint64(1 + uint64(n.Func.Inl.Cost)) + w.bool(n.Func.Inl.CanDelayResults) if n.Func.ExportInline() || n.Type().HasTParam() { w.p.doInline(n) } diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 16b3e7ceba..cca14a0d91 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -927,7 +927,8 @@ func (r *importReader) funcExt(n *ir.Name) { // Inline body. if u := r.uint64(); u > 0 { n.Func.Inl = &ir.Inline{ - Cost: int32(u - 1), + Cost: int32(u - 1), + CanDelayResults: r.bool(), } n.Func.Endlineno = r.pos() } diff --git a/test/fixedbugs/issue24651a.go b/test/fixedbugs/issue24651a.go index 6c7bf30908..1bfe8ac1ce 100644 --- a/test/fixedbugs/issue24651a.go +++ b/test/fixedbugs/issue24651a.go @@ -21,5 +21,5 @@ var x = 5 //go:noinline Provide a clean, constant reason for not inlining main func main() { // ERROR "cannot inline main: marked go:noinline$" println("Foo(", x, ")=", Foo(x)) - println("Bar(", x, ")=", Bar(x)) // ERROR "inlining call to Bar func\(int\) int { return x \* \(x \+ 1\) \* \(x \+ 2\) }$" + println("Bar(", x, ")=", Bar(x)) // ERROR "inlining call to Bar" } diff --git a/test/fixedbugs/issue24651b.go b/test/fixedbugs/issue24651b.go index aa88a6787b..2af54fc4b5 100644 --- a/test/fixedbugs/issue24651b.go +++ b/test/fixedbugs/issue24651b.go @@ -19,6 +19,6 @@ var x = 5 //go:noinline Provide a clean, constant reason for not inlining main func main() { // ERROR "cannot inline main: marked go:noinline$" - println("Foo(", x, ")=", Foo(x)) // ERROR "inlining call to Foo func\(int\) int { return x \* \(x \+ 1\) \* \(x \+ 2\) }$" - println("Bar(", x, ")=", Bar(x)) // ERROR "inlining call to Bar func\(int\) int { return x \* \(x \+ 1\) \* \(x \+ 2\) }$" + println("Foo(", x, ")=", Foo(x)) // ERROR "inlining call to Foo" + println("Bar(", x, ")=", Bar(x)) // ERROR "inlining call to Bar" } diff --git a/test/inline_big.go b/test/inline_big.go index 68e1101d3b..83672753f7 100644 --- a/test/inline_big.go +++ b/test/inline_big.go @@ -1023,7 +1023,7 @@ func f(a []int) int { // ERROR "cannot inline f:.*" "a does not escape" a[997] = 0 a[998] = 0 a[999] = 0 - x := small(a) // ERROR "inlining call to small .*" + x := small(a) // ERROR "inlining call to small" y := medium(a) // The crux of this test: medium is not inlined. return x + y } -- GitLab From 22f5ece3b13b7e5f6dece399c96d1d665b3a05bc Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 27 May 2021 02:48:33 -0700 Subject: [PATCH 0157/2500] [dev.typeparams] cmd/compile/internal/noder: refactor irgen import handling Rather than re-parsing and re-resolving the import path string, use the PkgName object provided by types2 to determine what package path it refers to. Also, decompose importfile into smaller functions, so that we can directly pass the already-resolved package path to the importer. Finally, switch to simply using height as calculated by types2 rather than redoing the calculations. Change-Id: I3338f4e68387b2835b2e58d6df65d740d6a648cb Reviewed-on: https://go-review.googlesource.com/c/go/+/323309 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Dan Scales Trust: Dan Scales Trust: Matthew Dempsky --- src/cmd/compile/internal/noder/decl.go | 15 ++++++++- src/cmd/compile/internal/noder/import.go | 40 +++++++++++++----------- src/cmd/compile/internal/noder/irgen.go | 3 +- 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go index 40cbe50aff..375eb41898 100644 --- a/src/cmd/compile/internal/noder/decl.go +++ b/src/cmd/compile/internal/noder/decl.go @@ -46,7 +46,12 @@ func (g *irgen) importDecl(p *noder, decl *syntax.ImportDecl) { g.pragmaFlags(decl.Pragma, 0) - ipkg := importfile(decl) + // Get the imported package's path, as resolved already by types2 + // and gcimporter. This is the same path as would be computed by + // parseImportPath. + path := pkgNameOf(g.info, decl).Imported().Path() + + ipkg := readImportFile(g.target, path) if ipkg == ir.Pkgs.Unsafe { p.importedUnsafe = true } @@ -55,6 +60,14 @@ func (g *irgen) importDecl(p *noder, decl *syntax.ImportDecl) { } } +// pkgNameOf returns the PkgName associated with the given ImportDecl. +func pkgNameOf(info *types2.Info, decl *syntax.ImportDecl) *types2.PkgName { + if name := decl.LocalPkgName; name != nil { + return info.Defs[name].(*types2.PkgName) + } + return info.Implicits[decl].(*types2.PkgName) +} + func (g *irgen) constDecl(out *ir.Nodes, decl *syntax.ConstDecl) { g.pragmaFlags(decl.Pragma, 0) diff --git a/src/cmd/compile/internal/noder/import.go b/src/cmd/compile/internal/noder/import.go index c4a57806eb..24d911ba38 100644 --- a/src/cmd/compile/internal/noder/import.go +++ b/src/cmd/compile/internal/noder/import.go @@ -175,36 +175,44 @@ func resolveImportPath(path string) (string, error) { return path, nil } -// TODO(mdempsky): Return an error instead. func importfile(decl *syntax.ImportDecl) *types.Pkg { - if decl.Path.Kind != syntax.StringLit { - base.Errorf("import path must be a string") + path, err := parseImportPath(decl.Path) + if err != nil { + base.Errorf("%s", err) return nil } - path, err := strconv.Unquote(decl.Path.Value) - if err != nil { - base.Errorf("import path must be a string") - return nil + pkg := readImportFile(typecheck.Target, path) + if pkg != ir.Pkgs.Unsafe && pkg.Height >= myheight { + myheight = pkg.Height + 1 } + return pkg +} - if err := checkImportPath(path, false); err != nil { - base.Errorf("%s", err.Error()) - return nil +func parseImportPath(pathLit *syntax.BasicLit) (string, error) { + if pathLit.Kind != syntax.StringLit { + return "", errors.New("import path must be a string") } - path, err = resolveImportPath(path) + path, err := strconv.Unquote(pathLit.Value) if err != nil { - base.Errorf("%s", err) - return nil + return "", errors.New("import path must be a string") + } + + if err := checkImportPath(path, false); err != nil { + return "", err } + return resolveImportPath(path) +} + +func readImportFile(target *ir.Package, path string) *types.Pkg { importpkg := types.NewPkg(path, "") if importpkg.Direct { return importpkg // already fully loaded } importpkg.Direct = true - typecheck.Target.Imports = append(typecheck.Target.Imports, importpkg) + target.Imports = append(target.Imports, importpkg) if path == "unsafe" { return importpkg // initialized with universe @@ -324,10 +332,6 @@ func importfile(decl *syntax.ImportDecl) *types.Pkg { base.Ctxt.AddImport(file[len(file)-len(path)-len(".a"):], fingerprint) } - if importpkg.Height >= myheight { - myheight = importpkg.Height + 1 - } - return importpkg } diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index f02246111f..abaaa8cbb0 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -98,6 +98,7 @@ type irgen struct { func (g *irgen) generate(noders []*noder) { types.LocalPkg.Name = g.self.Name() + types.LocalPkg.Height = g.self.Height() typecheck.TypecheckAllowed = true // Prevent size calculations until we set the underlying type @@ -132,8 +133,6 @@ Outer: } } } - assert(myheight == g.self.Height()) - types.LocalPkg.Height = myheight // 2. Process all package-block type declarations. As with imports, // we need to make sure all types are properly instantiated before -- GitLab From f32f4f58d9cd9d15371ee6198c1b222bcf2b56d9 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Sun, 30 May 2021 18:13:36 -0700 Subject: [PATCH 0158/2500] [dev.typeparams] cmd/compile: simplify formatting of defined types The existing code for deciding how to format defined type names is incredibly convoluted and difficult to follow. In particular, I'm looking at changing how Vargen works, and I couldn't tell from the existing code whether my idea was viable. This CL overhauls the logic to be much simpler with fewer special cases, while overall behaving the same. A few notable intentional differences from how the current code works: 1. The old code replaced the 'S' verb for fmtTypeGo and fmtTypeDebug to 'v', whereas the new code leaves it alone. There's currently no code that actually uses 'S' with these modes anyway, so it doesn't seem important to maintain this special case. If future code wants 'v' formatting, it should just use 'v' instead of 'S'. 2. The old code included Vargen for fmtTypeIDName mode with the 'S' verb; but again, this functionality isn't actually used. I think it would make sense for fmtTypeIDName to include Vargen like fmtTypeID does (Vargen is logically part of the type's identity after all), but that breaks tests and toolstash -cmp. So for now, this is left as a TODO to investigate in the future. 3. The old code only added Vargen for fmtTypeID in 'v' mode when printing types from the local package. But because we don't currently support exporting function-scoped defined types anyway, this is again irrelevant. In fact, once we *do* support exporting function-scoped defined types, we'll need to include Vargen to generate the linker symbols correctly. Passes toolstash -cmp. Change-Id: I4e481276bc4dc8d5b17eebf597b612737f26be5b Reviewed-on: https://go-review.googlesource.com/c/go/+/323709 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/types/fmt.go | 33 +++++++++------------------ 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/src/cmd/compile/internal/types/fmt.go b/src/cmd/compile/internal/types/fmt.go index b538ea8054..cecd1b3cc1 100644 --- a/src/cmd/compile/internal/types/fmt.go +++ b/src/cmd/compile/internal/types/fmt.go @@ -319,31 +319,20 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type // Unless the 'L' flag was specified, if the type has a name, just print that name. if verb != 'L' && t.Sym() != nil && t != Types[t.Kind()] { - switch mode { - case fmtTypeID, fmtTypeIDName: - if verb == 'S' { - if t.Vargen != 0 { - sconv2(b, t.Sym(), 'S', mode) - fmt.Fprintf(b, "·%d", t.Vargen) - return - } - sconv2(b, t.Sym(), 'S', mode) - return - } + // Default to 'v' if verb is invalid. + if verb != 'S' { + verb = 'v' + } - if mode == fmtTypeIDName { - sconv2(b, t.Sym(), 'v', fmtTypeIDName) - return - } + sconv2(b, t.Sym(), verb, mode) - if t.Sym().Pkg == LocalPkg && t.Vargen != 0 { - sconv2(b, t.Sym(), 'v', mode) - fmt.Fprintf(b, "·%d", t.Vargen) - return - } + // TODO(mdempsky): Investigate including Vargen in fmtTypeIDName + // output too. It seems like it should, but that mode is currently + // used in string representation used by reflection, which is + // user-visible and doesn't expect this. + if mode == fmtTypeID && t.Vargen != 0 { + fmt.Fprintf(b, "·%d", t.Vargen) } - - sconv2(b, t.Sym(), 'v', mode) return } -- GitLab From 4b10e4c5473560539c6a6470e45391e8b9a9e786 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Tue, 1 Jun 2021 00:56:14 +0700 Subject: [PATCH 0159/2500] [dev.typeparams] cmd/compile: handle ONONAME in subster.node Fixes #46472 Change-Id: I27802978fa0c3bb32a29e452165a6fcac93473bb Reviewed-on: https://go-review.googlesource.com/c/go/+/323731 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 3 +++ test/typeparam/issue46472.go | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 test/typeparam/issue46472.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index e273a80b20..36a6f2e6d0 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -350,6 +350,9 @@ func (subst *subster) node(n ir.Node) ir.Node { return v } return x + case ir.ONONAME: + // This handles the identifier in a type switch guard + fallthrough case ir.OLITERAL, ir.ONIL: if x.Sym() != nil { return x diff --git a/test/typeparam/issue46472.go b/test/typeparam/issue46472.go new file mode 100644 index 0000000000..bab48e7d2f --- /dev/null +++ b/test/typeparam/issue46472.go @@ -0,0 +1,20 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func foo[T any](d T) { + switch v := interface{}(d).(type) { + case string: + if v != "x" { + panic("unexpected v: "+v) + } + } + +} +func main() { + foo("x") +} -- GitLab From 2580e9a16049c12fbd0b058c4dc08cb7b0fdd08f Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 27 May 2021 02:47:25 -0700 Subject: [PATCH 0160/2500] [dev.typeparams] cmd/compile: refactor noder/irgen helpers This CL refactors the code for invoking the types2 checker and for validating //go:embed directives to be easier to reuse separately. No functional change. Change-Id: I706f4ea4a26b1f1d2f4064befcc0777a1067383d Reviewed-on: https://go-review.googlesource.com/c/go/+/323310 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Dan Scales Trust: Matthew Dempsky --- src/cmd/compile/internal/noder/irgen.go | 33 ++++++++++----- src/cmd/compile/internal/noder/noder.go | 47 ++++++++++----------- src/cmd/compile/internal/noder/types.go | 55 +++++++++++++------------ 3 files changed, 74 insertions(+), 61 deletions(-) diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index abaaa8cbb0..d5ef0c0ef4 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -18,9 +18,9 @@ import ( "cmd/internal/src" ) -// check2 type checks a Go package using types2, and then generates IR -// using the results. -func check2(noders []*noder) { +// checkFiles configures and runs the types2 checker on the given +// parsed source files and then returns the result. +func checkFiles(noders []*noder, importer types2.Importer) (posMap, *types2.Package, *types2.Info) { if base.SyntaxErrors() != 0 { base.ErrorExit() } @@ -42,12 +42,10 @@ func check2(noders []*noder) { terr := err.(types2.Error) base.ErrorfAt(m.makeXPos(terr.Pos), "%s", terr.Msg) }, - Importer: &gcimports{ - packages: make(map[string]*types2.Package), - }, - Sizes: &gcSizes{}, + Importer: importer, + Sizes: &gcSizes{}, } - info := types2.Info{ + info := &types2.Info{ Types: make(map[syntax.Expr]types2.TypeAndValue), Defs: make(map[*syntax.Name]types2.Object), Uses: make(map[*syntax.Name]types2.Object), @@ -57,12 +55,25 @@ func check2(noders []*noder) { Inferred: make(map[syntax.Expr]types2.Inferred), // expand as needed } - pkg, err := conf.Check(base.Ctxt.Pkgpath, files, &info) - files = nil + + pkg, err := conf.Check(base.Ctxt.Pkgpath, files, info) base.ExitIfErrors() if err != nil { base.FatalfAt(src.NoXPos, "conf.Check error: %v", err) } + + return m, pkg, info +} + +// check2 type checks a Go package using types2, and then generates IR +// using the results. +func check2(noders []*noder) { + importer := &gcimports{ + packages: make(map[string]*types2.Package), + } + + m, pkg, info := checkFiles(noders, importer) + if base.Flag.G < 2 { os.Exit(0) } @@ -70,7 +81,7 @@ func check2(noders []*noder) { g := irgen{ target: typecheck.Target, self: pkg, - info: &info, + info: info, posMap: m, objs: make(map[types2.Object]*ir.Name), typs: make(map[types2.Type]*types.Type), diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index 44385f34fd..2fb852b184 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -5,6 +5,7 @@ package noder import ( + "errors" "fmt" "go/constant" "go/token" @@ -1852,33 +1853,14 @@ func oldname(s *types.Sym) ir.Node { } func varEmbed(makeXPos func(syntax.Pos) src.XPos, name *ir.Name, decl *syntax.VarDecl, pragma *pragmas, haveEmbed bool) { - if pragma.Embeds == nil { - return - } - pragmaEmbeds := pragma.Embeds pragma.Embeds = nil - pos := makeXPos(pragmaEmbeds[0].Pos) - - if !haveEmbed { - base.ErrorfAt(pos, "go:embed only allowed in Go files that import \"embed\"") - return - } - if len(decl.NameList) > 1 { - base.ErrorfAt(pos, "go:embed cannot apply to multiple vars") + if len(pragmaEmbeds) == 0 { return } - if decl.Values != nil { - base.ErrorfAt(pos, "go:embed cannot apply to var with initializer") - return - } - if decl.Type == nil { - // Should not happen, since Values == nil now. - base.ErrorfAt(pos, "go:embed cannot apply to var without type") - return - } - if typecheck.DeclContext != ir.PEXTERN { - base.ErrorfAt(pos, "go:embed cannot apply to var inside func") + + if err := checkEmbed(decl, haveEmbed, typecheck.DeclContext != ir.PEXTERN); err != nil { + base.ErrorfAt(makeXPos(pragmaEmbeds[0].Pos), "%s", err) return } @@ -1889,3 +1871,22 @@ func varEmbed(makeXPos func(syntax.Pos) src.XPos, name *ir.Name, decl *syntax.Va typecheck.Target.Embeds = append(typecheck.Target.Embeds, name) name.Embed = &embeds } + +func checkEmbed(decl *syntax.VarDecl, haveEmbed, withinFunc bool) error { + switch { + case !haveEmbed: + return errors.New("go:embed only allowed in Go files that import \"embed\"") + case len(decl.NameList) > 1: + return errors.New("go:embed cannot apply to multiple vars") + case decl.Values != nil: + return errors.New("go:embed cannot apply to var with initializer") + case decl.Type == nil: + // Should not happen, since Values == nil now. + return errors.New("go:embed cannot apply to var without type") + case withinFunc: + return errors.New("go:embed cannot apply to var inside func") + + default: + return nil + } +} diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index ae10e03a24..f34cf146bb 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -390,38 +390,39 @@ func (g *irgen) selector(obj types2.Object) *types.Sym { // particular types is because go/types does *not* report it for // them. So in practice this limitation is probably moot. func (g *irgen) tpkg(typ types2.Type) *types.Pkg { - anyObj := func() types2.Object { - switch typ := typ.(type) { - case *types2.Signature: - if recv := typ.Recv(); recv != nil { - return recv - } - if params := typ.Params(); params.Len() > 0 { - return params.At(0) - } - if results := typ.Results(); results.Len() > 0 { - return results.At(0) - } - case *types2.Struct: - if typ.NumFields() > 0 { - return typ.Field(0) - } - case *types2.Interface: - if typ.NumExplicitMethods() > 0 { - return typ.ExplicitMethod(0) - } - case *types2.TypeParam: - return typ.Obj() - } - return nil - } - - if obj := anyObj(); obj != nil { + if obj := anyObj(typ); obj != nil { return g.pkg(obj.Pkg()) } return types.LocalPkg } +// anyObj returns some object accessible from typ, if any. +func anyObj(typ types2.Type) types2.Object { + switch typ := typ.(type) { + case *types2.Signature: + if recv := typ.Recv(); recv != nil { + return recv + } + if params := typ.Params(); params.Len() > 0 { + return params.At(0) + } + if results := typ.Results(); results.Len() > 0 { + return results.At(0) + } + case *types2.Struct: + if typ.NumFields() > 0 { + return typ.Field(0) + } + case *types2.Interface: + if typ.NumExplicitMethods() > 0 { + return typ.ExplicitMethod(0) + } + case *types2.TypeParam: + return typ.Obj() + } + return nil +} + func (g *irgen) basic(typ *types2.Basic) *types.Type { switch typ.Name() { case "byte": -- GitLab From 8e7abefdaaa3c00c35cfe04b787225926f70affe Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 28 May 2021 22:23:00 -0400 Subject: [PATCH 0161/2500] [dev.typeparams] cmd/compile: update ARM64 CALL* ops for register ABI Now they take variable number of args. Change-Id: I49c8bce9c3a403947eac03e397ae264a8f4fdd2c Reviewed-on: https://go-review.googlesource.com/c/go/+/323929 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: David Chase --- src/cmd/compile/internal/ssa/gen/ARM64Ops.go | 6 +++--- src/cmd/compile/internal/ssa/opGen.go | 6 +++--- src/cmd/compile/internal/ssa/rewriteARM64.go | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go index a91ece1c9f..414c429db6 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go @@ -482,9 +482,9 @@ func init() { {name: "CSETM", argLength: 1, reg: readflags, asm: "CSETM", aux: "CCop"}, // auxint(flags) ? -1 : 0 // function calls - {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem - {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R26"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem - {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem + {name: "CALLstatic", argLength: -1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). last arg=mem, auxint=argsize, returns mem + {name: "CALLclosure", argLength: -1, reg: regInfo{inputs: []regMask{gpsp, buildReg("R26"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, last arg=mem, auxint=argsize, returns mem + {name: "CALLinter", argLength: -1, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, last arg=mem, auxint=argsize, returns mem // pseudo-ops {name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpg}}, nilCheck: true, faultOnNilArg0: true}, // panic if arg0 is nil. arg1=mem. diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index cf31dfacf6..df15c2edda 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -20664,7 +20664,7 @@ var opcodeTable = [...]opInfo{ { name: "CALLstatic", auxType: auxCallOff, - argLen: 1, + argLen: -1, clobberFlags: true, call: true, reg: regInfo{ @@ -20674,7 +20674,7 @@ var opcodeTable = [...]opInfo{ { name: "CALLclosure", auxType: auxCallOff, - argLen: 3, + argLen: -1, clobberFlags: true, call: true, reg: regInfo{ @@ -20688,7 +20688,7 @@ var opcodeTable = [...]opInfo{ { name: "CALLinter", auxType: auxCallOff, - argLen: 2, + argLen: -1, clobberFlags: true, call: true, reg: regInfo{ diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index 3cdc4d36cb..debe5f2c2a 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -25997,7 +25997,7 @@ func rewriteValueARM64_OpSelectN(v *Value) bool { break } call := v_0 - if call.Op != OpARM64CALLstatic { + if call.Op != OpARM64CALLstatic || len(call.Args) != 1 { break } sym := auxToCall(call.Aux) -- GitLab From e4003463fff6a90d331c0a2da92774941693a4f7 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 28 May 2021 22:32:41 -0400 Subject: [PATCH 0162/2500] [dev.typeparams] cmd/compile: match register-ABI version of memmove call on ARM64 Update the rule to match register-ABI version of the call for inlining memmove. Change-Id: Ic6da810e4d7ac391ffb766fcdc943985f0739624 Reviewed-on: https://go-review.googlesource.com/c/go/+/323930 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: David Chase --- src/cmd/compile/internal/ssa/gen/ARM64.rules | 9 +++++++ src/cmd/compile/internal/ssa/rewriteARM64.go | 28 ++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index 62699f290c..530e48bcb2 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -2868,3 +2868,12 @@ && isInlinableMemmove(dst, src, sz, config) && clobber(s1, s2, s3, call) => (Move [sz] dst src mem) + +// Match post-lowering calls, register version. +(SelectN [0] call:(CALLstatic {sym} dst src (MOVDconst [sz]) mem)) + && sz >= 0 + && isSameCall(sym, "runtime.memmove") + && call.Uses == 1 + && isInlinableMemmove(dst, src, sz, config) + && clobber(call) + => (Move [sz] dst src mem) diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index debe5f2c2a..f7840c5503 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -26031,6 +26031,34 @@ func rewriteValueARM64_OpSelectN(v *Value) bool { v.AddArg3(dst, src, mem) return true } + // match: (SelectN [0] call:(CALLstatic {sym} dst src (MOVDconst [sz]) mem)) + // cond: sz >= 0 && isSameCall(sym, "runtime.memmove") && call.Uses == 1 && isInlinableMemmove(dst, src, sz, config) && clobber(call) + // result: (Move [sz] dst src mem) + for { + if auxIntToInt64(v.AuxInt) != 0 { + break + } + call := v_0 + if call.Op != OpARM64CALLstatic || len(call.Args) != 4 { + break + } + sym := auxToCall(call.Aux) + mem := call.Args[3] + dst := call.Args[0] + src := call.Args[1] + call_2 := call.Args[2] + if call_2.Op != OpARM64MOVDconst { + break + } + sz := auxIntToInt64(call_2.AuxInt) + if !(sz >= 0 && isSameCall(sym, "runtime.memmove") && call.Uses == 1 && isInlinableMemmove(dst, src, sz, config) && clobber(call)) { + break + } + v.reset(OpMove) + v.AuxInt = int64ToAuxInt(sz) + v.AddArg3(dst, src, mem) + return true + } return false } func rewriteValueARM64_OpSlicemask(v *Value) bool { -- GitLab From 6633dc8b0982173064c587f0b5e98f0b16f2132a Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 27 May 2021 18:41:12 -0400 Subject: [PATCH 0163/2500] [dev.typeparams] reflect: call ABI0 spill/unspill functions on AMD64 CL 321950 changed runtime.spillArgs and unspillArgs to ABI0. References to those functions should have been updated to ABI0, but this one was missed. Change-Id: I99238e4a96c945a47bec0981a415037578c73de4 Reviewed-on: https://go-review.googlesource.com/c/go/+/323931 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek Reviewed-by: David Chase --- src/reflect/asm_amd64.s | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/reflect/asm_amd64.s b/src/reflect/asm_amd64.s index 7491c772ac..d21d498063 100644 --- a/src/reflect/asm_amd64.s +++ b/src/reflect/asm_amd64.s @@ -59,7 +59,7 @@ TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$312 // NO_LOCAL_POINTERS is a lie. The stack map for the two locals in this // frame is specially handled in the runtime. See the comment above LOCAL_RETVALID. LEAQ LOCAL_REGARGS(SP), R12 - CALL runtime·spillArgs(SB) + CALL runtime·spillArgs(SB) MOVQ DX, 24(SP) // outside of moveMakeFuncArgPtrs's arg area MOVQ DX, 0(SP) MOVQ R12, 8(SP) @@ -75,5 +75,5 @@ TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$312 MOVQ AX, 24(SP) CALL ·callMethod(SB) LEAQ LOCAL_REGARGS(SP), R12 - CALL runtime·unspillArgs(SB) + CALL runtime·unspillArgs(SB) RET -- GitLab From c3639918d1c319e34bbb67b506394e8ee4d2fc6c Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 27 May 2021 18:22:49 -0400 Subject: [PATCH 0164/2500] [dev.typeparams] internal/abi: define ARM64 register ABI constants Change-Id: I9cdf0f2b6c1739f13a859a8e37351f8ecd77804a Reviewed-on: https://go-review.googlesource.com/c/go/+/323932 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/internal/abi/abi_arm64.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/internal/abi/abi_arm64.go diff --git a/src/internal/abi/abi_arm64.go b/src/internal/abi/abi_arm64.go new file mode 100644 index 0000000000..7544d7506e --- /dev/null +++ b/src/internal/abi/abi_arm64.go @@ -0,0 +1,20 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build goexperiment.regabireflect +// +build goexperiment.regabireflect + +package abi + +const ( + // See abi_generic.go. + + // R0 - R15. + IntArgRegs = 16 + + // F0 - F15. + FloatArgRegs = 16 + + EffectiveFloatRegSize = 8 +) -- GitLab From 58ad36b3592d3267ab9d9e0a91adecac08445028 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 27 May 2021 16:56:02 -0400 Subject: [PATCH 0165/2500] [dev.typeparams] internal/buildcfg: allow regabi GOEXPERIMENTs on ARM64 It is not working yet, but allow enabling the experiments so we can develop. Change-Id: I957eb05acb4d80b2858ff1f8c16bbfb24e0f6e56 Reviewed-on: https://go-review.googlesource.com/c/go/+/323933 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: David Chase --- src/internal/buildcfg/exp.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go index 11cd05f2ed..196d6af4a6 100644 --- a/src/internal/buildcfg/exp.go +++ b/src/internal/buildcfg/exp.go @@ -98,8 +98,8 @@ func parseExperiments() goexperiment.Flags { } } - // regabi is only supported on amd64. - if GOARCH != "amd64" { + // regabi is only supported on amd64 and arm64. + if GOARCH != "amd64" && GOARCH != "arm64" { flags.RegabiWrappers = false flags.RegabiG = false flags.RegabiReflect = false -- GitLab From b1f48e8addb640b6cbfad56d790b7702ff9fd30d Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 1 Jun 2021 16:57:59 -0700 Subject: [PATCH 0166/2500] [dev.typeparams] cmd/compile: fix formatting Looks like CL 322850 didn't have the change to ARM64Ops.go properly gofmt'ed. Change-Id: I1a080bc13ea27b897fbb91f18ded754ce440994b Reviewed-on: https://go-review.googlesource.com/c/go/+/324109 Trust: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/compile/internal/ssa/gen/ARM64Ops.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go index 414c429db6..5de0b5f020 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go @@ -759,17 +759,17 @@ func init() { } archs = append(archs, arch{ - name: "ARM64", - pkg: "cmd/internal/obj/arm64", - genfile: "../../arm64/ssa.go", - ops: ops, - blocks: blocks, - regnames: regNamesARM64, + name: "ARM64", + pkg: "cmd/internal/obj/arm64", + genfile: "../../arm64/ssa.go", + ops: ops, + blocks: blocks, + regnames: regNamesARM64, ParamIntRegNames: "R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15", ParamFloatRegNames: "F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15", - gpregmask: gp, - fpregmask: fp, - framepointerreg: -1, // not used - linkreg: int8(num["R30"]), + gpregmask: gp, + fpregmask: fp, + framepointerreg: -1, // not used + linkreg: int8(num["R30"]), }) } -- GitLab From d2b435117d3a1db612ad894125b8ab673a5a46ee Mon Sep 17 00:00:00 2001 From: Zachary Burkett Date: Sat, 29 May 2021 19:54:10 +0000 Subject: [PATCH 0167/2500] test: fix error check messages for 2 types2 tests Many compiler tests fail with -G=3 due to changes in error message format. This commit fixes two of these tests, to ensure I am on the right track in review. Updates #46447 Change-Id: I138956d536a1d48ca9198e6ddbfde13865bb5dd5 GitHub-Last-Rev: 0ed904b9fad5e6739fee02ab48c7bc66508d736b GitHub-Pull-Request: golang/go#46445 Reviewed-on: https://go-review.googlesource.com/c/go/+/323314 Reviewed-by: Matthew Dempsky Reviewed-by: Robert Griesemer Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot --- test/complit1.go | 14 +++++++------- test/ddd1.go | 10 +++++----- test/run.go | 2 -- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/test/complit1.go b/test/complit1.go index 7c2a4e2996..8cbcd63ee0 100644 --- a/test/complit1.go +++ b/test/complit1.go @@ -46,20 +46,20 @@ var ( _ = &T{0, 0, "", nil} // ok _ = &T{i: 0, f: 0, s: "", next: {}} // ERROR "missing type in composite literal|omit types within composite literal" _ = &T{0, 0, "", {}} // ERROR "missing type in composite literal|omit types within composite literal" - _ = TP{i: 0, f: 0, s: "", next: {}} // ERROR "invalid composite literal type TP|omit types within composite literal" + _ = TP{i: 0, f: 0, s: ""} // ERROR "invalid composite literal type TP" _ = &Ti{} // ERROR "invalid composite literal type Ti|expected.*type for composite literal" ) type M map[T]T var ( - _ = M{{i:1}: {i:2}} - _ = M{T{i:1}: {i:2}} - _ = M{{i:1}: T{i:2}} - _ = M{T{i:1}: T{i:2}} + _ = M{{i: 1}: {i: 2}} + _ = M{T{i: 1}: {i: 2}} + _ = M{{i: 1}: T{i: 2}} + _ = M{T{i: 1}: T{i: 2}} ) -type S struct { s [1]*M1 } +type S struct{ s [1]*M1 } type M1 map[S]int -var _ = M1{{s:[1]*M1{&M1{{}:1}}}:2} +var _ = M1{{s: [1]*M1{&M1{{}: 1}}}: 2} diff --git a/test/ddd1.go b/test/ddd1.go index ad49b347f4..f7381b7c94 100644 --- a/test/ddd1.go +++ b/test/ddd1.go @@ -17,8 +17,8 @@ var ( _ = sum(1, 2, 3) _ = sum() _ = sum(1.0, 2.0) - _ = sum(1.5) // ERROR "integer" - _ = sum("hello") // ERROR ".hello. .type untyped string. as type int|incompatible" + _ = sum(1.5) // ERROR "1\.5 .untyped float constant. as int|integer" + _ = sum("hello") // ERROR ".hello. (.untyped string constant. as int|.type untyped string. as type int)|incompatible" _ = sum([]int{1}) // ERROR "\[\]int{...}.*as type int|incompatible" ) @@ -27,9 +27,9 @@ func tuple() (int, int, int) { return 1, 2, 3 } var ( _ = sum(tuple()) - _ = sum(tuple()...) // ERROR "multiple-value" + _ = sum(tuple()...) // ERROR "\.{3} with 3-valued|multiple-value" _ = sum3(tuple()) - _ = sum3(tuple()...) // ERROR "multiple-value" ERROR "invalid use of .*[.][.][.]" + _ = sum3(tuple()...) // ERROR "\.{3} in call to non-variadic|multiple-value|invalid use of .*[.][.][.]" ) type T []T @@ -60,5 +60,5 @@ func bad(args ...int) { _ = [...]byte("foo") // ERROR "[.][.][.]" _ = [...][...]int{{1,2,3},{4,5,6}} // ERROR "[.][.][.]" - Foo(x...) // ERROR "invalid use of .*[.][.][.]" + Foo(x...) // ERROR "\.{3} in call to non-variadic|invalid use of .*[.][.][.]" } diff --git a/test/run.go b/test/run.go index cf1d301598..ef1e9de150 100644 --- a/test/run.go +++ b/test/run.go @@ -2023,8 +2023,6 @@ func overlayDir(dstRoot, srcRoot string) error { // List of files that the compiler cannot errorcheck with the new typechecker (compiler -G option). // Temporary scaffolding until we pass all the tests at which point this map can be removed. var excludedFiles = map[string]bool{ - "complit1.go": true, // types2 reports extra errors - "ddd1.go": true, // issue #42987 "directive.go": true, // misplaced compiler directive checks "float_lit3.go": true, // types2 reports extra errors "import1.go": true, // types2 reports extra errors -- GitLab From dc2cb529a8c9e4b771163be1974ef39d76c3f548 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 27 May 2021 18:07:36 -0400 Subject: [PATCH 0168/2500] [dev.typeparams] runtime: mark assembly functions called directly from compiler ABIInternal For functions such as gcWriteBarrier and panicIndexXXX, the compiler generates ABIInternal calls directly. And they must not use wrappers because it follows a special calling convention or the caller's PC is used. Mark them as ABIInternal. Note that even though they are marked as ABIInternal, they don't actually use the internal ABI, i.e. regabiargs is not honored for now. Now all.bash passes with GOEXPERIMENT=regabiwrappers (at least on macOS). Change-Id: I87e41964e6dc4efae03e8eb636ae9fa1d99285bb Reviewed-on: https://go-review.googlesource.com/c/go/+/323934 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/cmd/internal/obj/arm64/obj7.go | 4 +- src/runtime/asm_arm64.s | 78 ++++++++++++++++-------------- src/runtime/duff_arm64.s | 4 +- src/runtime/mkduff.go | 4 +- src/runtime/race_arm64.s | 16 ++++-- 5 files changed, 60 insertions(+), 46 deletions(-) diff --git a/src/cmd/internal/obj/arm64/obj7.go b/src/cmd/internal/obj/arm64/obj7.go index c94a0b67ee..31b7c43245 100644 --- a/src/cmd/internal/obj/arm64/obj7.go +++ b/src/cmd/internal/obj/arm64/obj7.go @@ -325,9 +325,9 @@ func (c *ctxt7) rewriteToUseGot(p *obj.Prog) { // CALL REGTMP var sym *obj.LSym if p.As == obj.ADUFFZERO { - sym = c.ctxt.Lookup("runtime.duffzero") + sym = c.ctxt.LookupABI("runtime.duffzero", obj.ABIInternal) } else { - sym = c.ctxt.Lookup("runtime.duffcopy") + sym = c.ctxt.LookupABI("runtime.duffcopy", obj.ABIInternal) } offset := p.To.Offset p.As = AMOVD diff --git a/src/runtime/asm_arm64.s b/src/runtime/asm_arm64.s index 2d495397a8..ca04dddd5b 100644 --- a/src/runtime/asm_arm64.s +++ b/src/runtime/asm_arm64.s @@ -103,7 +103,7 @@ nocgo: MOVD R0, (R0) // boom UNDEF -DATA runtime·mainPC+0(SB)/8,$runtime·main(SB) +DATA runtime·mainPC+0(SB)/8,$runtime·main(SB) GLOBL runtime·mainPC(SB),RODATA,$8 TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0 @@ -1158,7 +1158,10 @@ TEXT ·checkASM(SB),NOSPLIT,$0-1 // It does not clobber any general-purpose registers, // but may clobber others (e.g., floating point registers) // The act of CALLing gcWriteBarrier will clobber R30 (LR). -TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$200 +// +// Defined as ABIInternal since the compiler generates ABIInternal +// calls to it directly and it does not use the stack-based Go ABI. +TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$200 // Save the registers clobbered by the fast path. MOVD R0, 184(RSP) MOVD R1, 192(RSP) @@ -1250,71 +1253,74 @@ flush: // in the caller's stack frame. These stubs write the args into that stack space and // then tail call to the corresponding runtime handler. // The tail call makes these stubs disappear in backtraces. -TEXT runtime·panicIndex(SB),NOSPLIT,$0-16 +// +// Defined as ABIInternal since the compiler generates ABIInternal +// calls to it directly and it does not use the stack-based Go ABI. +TEXT runtime·panicIndex(SB),NOSPLIT,$0-16 MOVD R0, x+0(FP) MOVD R1, y+8(FP) - JMP runtime·goPanicIndex(SB) -TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16 + JMP runtime·goPanicIndex(SB) +TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16 MOVD R0, x+0(FP) MOVD R1, y+8(FP) - JMP runtime·goPanicIndexU(SB) -TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16 + JMP runtime·goPanicIndexU(SB) +TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16 MOVD R1, x+0(FP) MOVD R2, y+8(FP) - JMP runtime·goPanicSliceAlen(SB) -TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-16 + JMP runtime·goPanicSliceAlen(SB) +TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-16 MOVD R1, x+0(FP) MOVD R2, y+8(FP) - JMP runtime·goPanicSliceAlenU(SB) -TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-16 + JMP runtime·goPanicSliceAlenU(SB) +TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-16 MOVD R1, x+0(FP) MOVD R2, y+8(FP) - JMP runtime·goPanicSliceAcap(SB) -TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16 + JMP runtime·goPanicSliceAcap(SB) +TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16 MOVD R1, x+0(FP) MOVD R2, y+8(FP) - JMP runtime·goPanicSliceAcapU(SB) -TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16 + JMP runtime·goPanicSliceAcapU(SB) +TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16 MOVD R0, x+0(FP) MOVD R1, y+8(FP) - JMP runtime·goPanicSliceB(SB) -TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16 + JMP runtime·goPanicSliceB(SB) +TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16 MOVD R0, x+0(FP) MOVD R1, y+8(FP) - JMP runtime·goPanicSliceBU(SB) -TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16 + JMP runtime·goPanicSliceBU(SB) +TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16 MOVD R2, x+0(FP) MOVD R3, y+8(FP) - JMP runtime·goPanicSlice3Alen(SB) -TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-16 + JMP runtime·goPanicSlice3Alen(SB) +TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-16 MOVD R2, x+0(FP) MOVD R3, y+8(FP) - JMP runtime·goPanicSlice3AlenU(SB) -TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-16 + JMP runtime·goPanicSlice3AlenU(SB) +TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-16 MOVD R2, x+0(FP) MOVD R3, y+8(FP) - JMP runtime·goPanicSlice3Acap(SB) -TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-16 + JMP runtime·goPanicSlice3Acap(SB) +TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-16 MOVD R2, x+0(FP) MOVD R3, y+8(FP) - JMP runtime·goPanicSlice3AcapU(SB) -TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-16 + JMP runtime·goPanicSlice3AcapU(SB) +TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-16 MOVD R1, x+0(FP) MOVD R2, y+8(FP) - JMP runtime·goPanicSlice3B(SB) -TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16 + JMP runtime·goPanicSlice3B(SB) +TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16 MOVD R1, x+0(FP) MOVD R2, y+8(FP) - JMP runtime·goPanicSlice3BU(SB) -TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16 + JMP runtime·goPanicSlice3BU(SB) +TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16 MOVD R0, x+0(FP) MOVD R1, y+8(FP) - JMP runtime·goPanicSlice3C(SB) -TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16 + JMP runtime·goPanicSlice3C(SB) +TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16 MOVD R0, x+0(FP) MOVD R1, y+8(FP) - JMP runtime·goPanicSlice3CU(SB) -TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-16 + JMP runtime·goPanicSlice3CU(SB) +TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-16 MOVD R2, x+0(FP) MOVD R3, y+8(FP) - JMP runtime·goPanicSliceConvert(SB) + JMP runtime·goPanicSliceConvert(SB) diff --git a/src/runtime/duff_arm64.s b/src/runtime/duff_arm64.s index 128b076af9..33c4905078 100644 --- a/src/runtime/duff_arm64.s +++ b/src/runtime/duff_arm64.s @@ -4,7 +4,7 @@ #include "textflag.h" -TEXT runtime·duffzero(SB), NOSPLIT|NOFRAME, $0-0 +TEXT runtime·duffzero(SB), NOSPLIT|NOFRAME, $0-0 STP.P (ZR, ZR), 16(R20) STP.P (ZR, ZR), 16(R20) STP.P (ZR, ZR), 16(R20) @@ -71,7 +71,7 @@ TEXT runtime·duffzero(SB), NOSPLIT|NOFRAME, $0-0 STP (ZR, ZR), (R20) RET -TEXT runtime·duffcopy(SB), NOSPLIT|NOFRAME, $0-0 +TEXT runtime·duffcopy(SB), NOSPLIT|NOFRAME, $0-0 LDP.P 16(R20), (R26, R27) STP.P (R26, R27), 16(R21) diff --git a/src/runtime/mkduff.go b/src/runtime/mkduff.go index da191cc594..f036745092 100644 --- a/src/runtime/mkduff.go +++ b/src/runtime/mkduff.go @@ -154,7 +154,7 @@ func zeroARM64(w io.Writer) { // ZR: always zero // R20: ptr to memory to be zeroed // On return, R20 points to the last zeroed dword. - fmt.Fprintln(w, "TEXT runtime·duffzero(SB), NOSPLIT|NOFRAME, $0-0") + fmt.Fprintln(w, "TEXT runtime·duffzero(SB), NOSPLIT|NOFRAME, $0-0") for i := 0; i < 63; i++ { fmt.Fprintln(w, "\tSTP.P\t(ZR, ZR), 16(R20)") } @@ -167,7 +167,7 @@ func copyARM64(w io.Writer) { // R21: ptr to destination memory // R26, R27 (aka REGTMP): scratch space // R20 and R21 are updated as a side effect - fmt.Fprintln(w, "TEXT runtime·duffcopy(SB), NOSPLIT|NOFRAME, $0-0") + fmt.Fprintln(w, "TEXT runtime·duffcopy(SB), NOSPLIT|NOFRAME, $0-0") for i := 0; i < 64; i++ { fmt.Fprintln(w, "\tLDP.P\t16(R20), (R26, R27)") diff --git a/src/runtime/race_arm64.s b/src/runtime/race_arm64.s index c6d5b91edc..bfad08b9fb 100644 --- a/src/runtime/race_arm64.s +++ b/src/runtime/race_arm64.s @@ -43,7 +43,9 @@ // func runtime·raceread(addr uintptr) // Called from instrumented code. -TEXT runtime·raceread(SB), NOSPLIT, $0-8 +// Defined as ABIInternal so as to avoid introducing a wrapper, +// which would make caller's PC ineffective. +TEXT runtime·raceread(SB), NOSPLIT, $0-8 MOVD addr+0(FP), R1 MOVD LR, R2 // void __tsan_read(ThreadState *thr, void *addr, void *pc); @@ -66,7 +68,9 @@ TEXT runtime·racereadpc(SB), NOSPLIT, $0-24 // func runtime·racewrite(addr uintptr) // Called from instrumented code. -TEXT runtime·racewrite(SB), NOSPLIT, $0-8 +// Defined as ABIInternal so as to avoid introducing a wrapper, +// which would make caller's PC ineffective. +TEXT runtime·racewrite(SB), NOSPLIT, $0-8 MOVD addr+0(FP), R1 MOVD LR, R2 // void __tsan_write(ThreadState *thr, void *addr, void *pc); @@ -89,7 +93,9 @@ TEXT runtime·racewritepc(SB), NOSPLIT, $0-24 // func runtime·racereadrange(addr, size uintptr) // Called from instrumented code. -TEXT runtime·racereadrange(SB), NOSPLIT, $0-16 +// Defined as ABIInternal so as to avoid introducing a wrapper, +// which would make caller's PC ineffective. +TEXT runtime·racereadrange(SB), NOSPLIT, $0-16 MOVD addr+0(FP), R1 MOVD size+8(FP), R2 MOVD LR, R3 @@ -114,7 +120,9 @@ TEXT runtime·racereadrangepc1(SB), NOSPLIT, $0-24 // func runtime·racewriterange(addr, size uintptr) // Called from instrumented code. -TEXT runtime·racewriterange(SB), NOSPLIT, $0-16 +// Defined as ABIInternal so as to avoid introducing a wrapper, +// which would make caller's PC ineffective. +TEXT runtime·racewriterange(SB), NOSPLIT, $0-16 MOVD addr+0(FP), R1 MOVD size+8(FP), R2 MOVD LR, R3 -- GitLab From 2e4b79949fbb6e0c7e68a1f0258c42ea791069e6 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 27 May 2021 19:02:27 -0400 Subject: [PATCH 0169/2500] [dev.typeparams] runtime: implement register ABI for reflectcall on ARM64 Implement register ABI version of reflectcall. Now runtime tests pass with GOEXPERIMENT=regabiwrappers,regabireflect on ARM64 (at least on macOS). Change-Id: I2812cd96bdc13f8dc91c867e3f571921c0cdfc8a Reviewed-on: https://go-review.googlesource.com/c/go/+/323935 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/runtime/asm_arm64.s | 94 ++++++++++++++++++++++++++++++++++++-- src/runtime/stubs_arm64.go | 7 +++ 2 files changed, 97 insertions(+), 4 deletions(-) diff --git a/src/runtime/asm_arm64.s b/src/runtime/asm_arm64.s index ca04dddd5b..3da2b8d315 100644 --- a/src/runtime/asm_arm64.s +++ b/src/runtime/asm_arm64.s @@ -310,6 +310,86 @@ TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0 MOVW $0, R26 B runtime·morestack(SB) +#ifdef GOEXPERIMENT_regabireflect +// spillArgs stores return values from registers to a *internal/abi.RegArgs in R20. +TEXT ·spillArgs(SB),NOSPLIT,$0-0 + MOVD R0, (0*8)(R20) + MOVD R1, (1*8)(R20) + MOVD R2, (2*8)(R20) + MOVD R3, (3*8)(R20) + MOVD R4, (4*8)(R20) + MOVD R5, (5*8)(R20) + MOVD R6, (6*8)(R20) + MOVD R7, (7*8)(R20) + MOVD R8, (8*8)(R20) + MOVD R9, (9*8)(R20) + MOVD R10, (10*8)(R20) + MOVD R11, (11*8)(R20) + MOVD R12, (12*8)(R20) + MOVD R13, (13*8)(R20) + MOVD R14, (14*8)(R20) + MOVD R15, (15*8)(R20) + FMOVD F0, (16*8)(R20) + FMOVD F1, (17*8)(R20) + FMOVD F2, (18*8)(R20) + FMOVD F3, (19*8)(R20) + FMOVD F4, (20*8)(R20) + FMOVD F5, (21*8)(R20) + FMOVD F6, (22*8)(R20) + FMOVD F7, (23*8)(R20) + FMOVD F8, (24*8)(R20) + FMOVD F9, (25*8)(R20) + FMOVD F10, (26*8)(R20) + FMOVD F11, (27*8)(R20) + FMOVD F12, (28*8)(R20) + FMOVD F13, (29*8)(R20) + FMOVD F14, (30*8)(R20) + FMOVD F15, (31*8)(R20) + RET + +// unspillArgs loads args into registers from a *internal/abi.RegArgs in R20. +TEXT ·unspillArgs(SB),NOSPLIT,$0-0 + MOVD (0*8)(R20), R0 + MOVD (1*8)(R20), R1 + MOVD (2*8)(R20), R2 + MOVD (3*8)(R20), R3 + MOVD (4*8)(R20), R4 + MOVD (5*8)(R20), R5 + MOVD (6*8)(R20), R6 + MOVD (7*8)(R20), R7 + MOVD (8*8)(R20), R8 + MOVD (9*8)(R20), R9 + MOVD (10*8)(R20), R10 + MOVD (11*8)(R20), R11 + MOVD (12*8)(R20), R12 + MOVD (13*8)(R20), R13 + MOVD (14*8)(R20), R14 + MOVD (15*8)(R20), R15 + FMOVD (16*8)(R20), F0 + FMOVD (17*8)(R20), F1 + FMOVD (18*8)(R20), F2 + FMOVD (19*8)(R20), F3 + FMOVD (20*8)(R20), F4 + FMOVD (21*8)(R20), F5 + FMOVD (22*8)(R20), F6 + FMOVD (23*8)(R20), F7 + FMOVD (24*8)(R20), F8 + FMOVD (25*8)(R20), F9 + FMOVD (26*8)(R20), F10 + FMOVD (27*8)(R20), F11 + FMOVD (28*8)(R20), F12 + FMOVD (29*8)(R20), F13 + FMOVD (30*8)(R20), F14 + FMOVD (31*8)(R20), F15 + RET +#else +TEXT ·spillArgs(SB),NOSPLIT,$0-0 + RET + +TEXT ·unspillArgs(SB),NOSPLIT,$0-0 + RET +#endif + // reflectcall: call a function with the given argument list // func call(stackArgsType *_type, f *FuncVal, stackArgs *byte, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs). // we don't have variable-sized frames, so we use a small number @@ -381,12 +461,17 @@ TEXT NAME(SB), WRAPPER, $MAXSIZE-48; \ MOVBU.P R7, 1(R5); \ CMP R5, R6; \ BNE -3(PC); \ + /* set up argument registers */ \ + MOVD regArgs+40(FP), R20; \ + CALL ·unspillArgs(SB); \ /* call function */ \ MOVD f+8(FP), R26; \ - MOVD (R26), R0; \ - PCDATA $PCDATA_StackMapIndex, $0; \ - BL (R0); \ + MOVD (R26), R20; \ + PCDATA $PCDATA_StackMapIndex, $0; \ + BL (R20); \ /* copy return values back */ \ + MOVD regArgs+40(FP), R20; \ + CALL ·spillArgs(SB); \ MOVD stackArgsType+0(FP), R7; \ MOVD stackArgs+16(FP), R3; \ MOVWU stackArgsSize+24(FP), R4; \ @@ -403,11 +488,12 @@ TEXT NAME(SB), WRAPPER, $MAXSIZE-48; \ // to reflectcallmove. It does not follow the Go ABI; it expects its // arguments in registers. TEXT callRet<>(SB), NOSPLIT, $48-0 + NO_LOCAL_POINTERS MOVD R7, 8(RSP) MOVD R3, 16(RSP) MOVD R5, 24(RSP) MOVD R4, 32(RSP) - MOVD $0, 40(RSP) + MOVD R20, 40(RSP) BL runtime·reflectcallmove(SB) RET diff --git a/src/runtime/stubs_arm64.go b/src/runtime/stubs_arm64.go index f5e3bb4854..bd0533d158 100644 --- a/src/runtime/stubs_arm64.go +++ b/src/runtime/stubs_arm64.go @@ -14,3 +14,10 @@ func save_g() func asmcgocall_no_g(fn, arg unsafe.Pointer) func emptyfunc() + +// Used by reflectcall and the reflect package. +// +// Spills/loads arguments in registers to/from an internal/abi.RegArgs +// respectively. Does not follow the Go ABI. +func spillArgs() +func unspillArgs() -- GitLab From 0c123cdf8ba88991e51fdb3523fdc7df03cf3118 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 27 May 2021 20:20:16 -0400 Subject: [PATCH 0170/2500] [dev.typeparams] reflect: implement register ABI for MakeFunc etc. on ARM64 Implement register ABI for reflect.MakeFunc and method Value Call on ARM64. Change-Id: I5487febb9ea764af5ccf5d7c94858ab0acec7cac Reviewed-on: https://go-review.googlesource.com/c/go/+/323936 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/reflect/asm_arm64.s | 61 ++++++++++++++++++++++++++++++++++------- src/runtime/stack.go | 6 ++-- 2 files changed, 54 insertions(+), 13 deletions(-) diff --git a/src/reflect/asm_arm64.s b/src/reflect/asm_arm64.s index 5fe88e27e4..5b9b3573fa 100644 --- a/src/reflect/asm_arm64.s +++ b/src/reflect/asm_arm64.s @@ -5,34 +5,75 @@ #include "textflag.h" #include "funcdata.h" +// The frames of each of the two functions below contain two locals, at offsets +// that are known to the runtime. +// +// The first local is a bool called retValid with a whole pointer-word reserved +// for it on the stack. The purpose of this word is so that the runtime knows +// whether the stack-allocated return space contains valid values for stack +// scanning. +// +// The second local is an abi.RegArgs value whose offset is also known to the +// runtime, so that a stack map for it can be constructed, since it contains +// pointers visible to the GC. +#define LOCAL_RETVALID 40 +#define LOCAL_REGARGS 48 + +// The frame size of the functions below is +// 32 (args of callReflect) + 8 (bool + padding) + 392 (abi.RegArgs) = 432. + // makeFuncStub is the code half of the function returned by MakeFunc. // See the comment on the declaration of makeFuncStub in makefunc.go // for more details. // No arg size here, runtime pulls arg map out of the func value. -TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$40 +TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$432 NO_LOCAL_POINTERS + // NO_LOCAL_POINTERS is a lie. The stack map for the two locals in this + // frame is specially handled in the runtime. See the comment above LOCAL_RETVALID. + ADD $LOCAL_REGARGS, RSP, R20 + CALL runtime·spillArgs(SB) + MOVD R26, 32(RSP) // outside of moveMakeFuncArgPtrs's arg area + MOVD R26, 8(RSP) + MOVD R20, 16(RSP) + CALL ·moveMakeFuncArgPtrs(SB) + MOVD 32(RSP), R26 MOVD R26, 8(RSP) MOVD $argframe+0(FP), R3 MOVD R3, 16(RSP) - MOVB $0, 40(RSP) - ADD $40, RSP, R3 + MOVB $0, LOCAL_RETVALID(RSP) + ADD $LOCAL_RETVALID, RSP, R3 MOVD R3, 24(RSP) - MOVD $0, 32(RSP) - BL ·callReflect(SB) + ADD $LOCAL_REGARGS, RSP, R3 + MOVD R3, 32(RSP) + CALL ·callReflect(SB) + ADD $LOCAL_REGARGS, RSP, R20 + CALL runtime·unspillArgs(SB) RET // methodValueCall is the code half of the function returned by makeMethodValue. // See the comment on the declaration of methodValueCall in makefunc.go // for more details. // No arg size here; runtime pulls arg map out of the func value. -TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$40 +TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$432 NO_LOCAL_POINTERS + // NO_LOCAL_POINTERS is a lie. The stack map for the two locals in this + // frame is specially handled in the runtime. See the comment above LOCAL_RETVALID. + ADD $LOCAL_REGARGS, RSP, R20 + CALL runtime·spillArgs(SB) + MOVD R26, 32(RSP) // outside of moveMakeFuncArgPtrs's arg area + MOVD R26, 8(RSP) + MOVD R20, 16(RSP) + CALL ·moveMakeFuncArgPtrs(SB) + MOVD 32(RSP), R26 MOVD R26, 8(RSP) MOVD $argframe+0(FP), R3 MOVD R3, 16(RSP) - MOVB $0, 40(RSP) - ADD $40, RSP, R3 + MOVB $0, LOCAL_RETVALID(RSP) + ADD $LOCAL_RETVALID, RSP, R3 MOVD R3, 24(RSP) - MOVD $0, 32(RSP) - BL ·callMethod(SB) + ADD $LOCAL_REGARGS, RSP, R3 + MOVD R3, 32(RSP) + CALL ·callMethod(SB) + ADD $LOCAL_REGARGS, RSP, R20 + CALL runtime·unspillArgs(SB) RET diff --git a/src/runtime/stack.go b/src/runtime/stack.go index 622de45f25..a1182b00bd 100644 --- a/src/runtime/stack.go +++ b/src/runtime/stack.go @@ -1318,11 +1318,11 @@ func getStackMap(frame *stkframe, cache *pcvalueCache, debug bool) (locals, args } // stack objects. - if GOARCH == "amd64" && unsafe.Sizeof(abi.RegArgs{}) > 0 && frame.argmap != nil { + if (GOARCH == "amd64" || GOARCH == "arm64") && unsafe.Sizeof(abi.RegArgs{}) > 0 && frame.argmap != nil { // argmap is set when the function is reflect.makeFuncStub or reflect.methodValueCall. // We don't actually use argmap in this case, but we need to fake the stack object - // record for these frames which contain an internal/abi.RegArgs at a hard-coded offset - // on amd64. + // record for these frames which contain an internal/abi.RegArgs at a hard-coded offset. + // This offset matches the assembly code on amd64 and arm64. objs = methodValueCallFrameObjs } else { p := funcdata(f, _FUNCDATA_StackObjects) -- GitLab From aa9cfdf775692a9fa6cc4ea9768415d73323c0cc Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 28 May 2021 21:56:50 -0400 Subject: [PATCH 0171/2500] [dev.typeparams] runtime: update ABIInternal assembly with register ABI on ARM64 mcall calls a closure (using ABIInternal) with an argument. Update it to pass the argument in register. Panic functions tail-call Go panic functions using ABIInternal. Update them to pass the arguments in registers. Race functions are called using ABIInternal from compiler- instrumented code. Update them to receive the arguments in registers. Now all.bash passes with GOEXPERIMENT=regabi on ARM64 (at least on macOS). Change-Id: I648f6502c7eeb1422330c6c829181f12e08c7d0e Reviewed-on: https://go-review.googlesource.com/c/go/+/323937 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/runtime/asm_arm64.s | 75 +++++++++++++++++++++++++++++++++++++--- src/runtime/race_arm64.s | 18 ++++++++++ 2 files changed, 88 insertions(+), 5 deletions(-) diff --git a/src/runtime/asm_arm64.s b/src/runtime/asm_arm64.s index 3da2b8d315..170e4406fc 100644 --- a/src/runtime/asm_arm64.s +++ b/src/runtime/asm_arm64.s @@ -152,7 +152,13 @@ TEXT gogo<>(SB), NOSPLIT|NOFRAME, $0 // Switch to m->g0's stack, call fn(g). // Fn must never return. It should gogo(&g->sched) // to keep running g. -TEXT runtime·mcall(SB), NOSPLIT|NOFRAME, $0-8 +TEXT runtime·mcall(SB), NOSPLIT|NOFRAME, $0-8 +#ifdef GOEXPERIMENT_regabiargs + MOVD R0, R26 // context +#else + MOVD fn+0(FP), R26 // context +#endif + // Save caller state in g->sched MOVD RSP, R0 MOVD R0, (g_sched+gobuf_sp)(g) @@ -168,14 +174,18 @@ TEXT runtime·mcall(SB), NOSPLIT|NOFRAME, $0-8 CMP g, R3 BNE 2(PC) B runtime·badmcall(SB) - MOVD fn+0(FP), R26 // context - MOVD 0(R26), R4 // code pointer + MOVD (g_sched+gobuf_sp)(g), R0 MOVD R0, RSP // sp = m->g0->sched.sp MOVD (g_sched+gobuf_bp)(g), R29 - MOVD R3, -8(RSP) - MOVD $0, -16(RSP) +#ifdef GOEXPERIMENT_regabiargs + MOVD R3, R0 // arg = g +#else + MOVD R3, -8(RSP) // arg = g +#endif + MOVD $0, -16(RSP) // dummy LR SUB $16, RSP + MOVD 0(R26), R4 // code pointer BL (R4) B runtime·badmcall2(SB) @@ -1351,20 +1361,40 @@ TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16 MOVD R1, y+8(FP) JMP runtime·goPanicIndexU(SB) TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16 +#ifdef GOEXPERIMENT_regabiargs + MOVD R1, R0 + MOVD R2, R1 +#else MOVD R1, x+0(FP) MOVD R2, y+8(FP) +#endif JMP runtime·goPanicSliceAlen(SB) TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-16 +#ifdef GOEXPERIMENT_regabiargs + MOVD R1, R0 + MOVD R2, R1 +#else MOVD R1, x+0(FP) MOVD R2, y+8(FP) +#endif JMP runtime·goPanicSliceAlenU(SB) TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-16 +#ifdef GOEXPERIMENT_regabiargs + MOVD R1, R0 + MOVD R2, R1 +#else MOVD R1, x+0(FP) MOVD R2, y+8(FP) +#endif JMP runtime·goPanicSliceAcap(SB) TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16 +#ifdef GOEXPERIMENT_regabiargs + MOVD R1, R0 + MOVD R2, R1 +#else MOVD R1, x+0(FP) MOVD R2, y+8(FP) +#endif JMP runtime·goPanicSliceAcapU(SB) TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16 MOVD R0, x+0(FP) @@ -1375,28 +1405,58 @@ TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16 MOVD R1, y+8(FP) JMP runtime·goPanicSliceBU(SB) TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16 +#ifdef GOEXPERIMENT_regabiargs + MOVD R2, R0 + MOVD R3, R1 +#else MOVD R2, x+0(FP) MOVD R3, y+8(FP) +#endif JMP runtime·goPanicSlice3Alen(SB) TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-16 +#ifdef GOEXPERIMENT_regabiargs + MOVD R2, R0 + MOVD R3, R1 +#else MOVD R2, x+0(FP) MOVD R3, y+8(FP) +#endif JMP runtime·goPanicSlice3AlenU(SB) TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-16 +#ifdef GOEXPERIMENT_regabiargs + MOVD R2, R0 + MOVD R3, R1 +#else MOVD R2, x+0(FP) MOVD R3, y+8(FP) +#endif JMP runtime·goPanicSlice3Acap(SB) TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-16 +#ifdef GOEXPERIMENT_regabiargs + MOVD R2, R0 + MOVD R3, R1 +#else MOVD R2, x+0(FP) MOVD R3, y+8(FP) +#endif JMP runtime·goPanicSlice3AcapU(SB) TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-16 +#ifdef GOEXPERIMENT_regabiargs + MOVD R1, R0 + MOVD R2, R1 +#else MOVD R1, x+0(FP) MOVD R2, y+8(FP) +#endif JMP runtime·goPanicSlice3B(SB) TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16 +#ifdef GOEXPERIMENT_regabiargs + MOVD R1, R0 + MOVD R2, R1 +#else MOVD R1, x+0(FP) MOVD R2, y+8(FP) +#endif JMP runtime·goPanicSlice3BU(SB) TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16 MOVD R0, x+0(FP) @@ -1407,6 +1467,11 @@ TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16 MOVD R1, y+8(FP) JMP runtime·goPanicSlice3CU(SB) TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-16 +#ifdef GOEXPERIMENT_regabiargs + MOVD R2, R0 + MOVD R3, R1 +#else MOVD R2, x+0(FP) MOVD R3, y+8(FP) +#endif JMP runtime·goPanicSliceConvert(SB) diff --git a/src/runtime/race_arm64.s b/src/runtime/race_arm64.s index bfad08b9fb..2b2413b6b7 100644 --- a/src/runtime/race_arm64.s +++ b/src/runtime/race_arm64.s @@ -46,7 +46,11 @@ // Defined as ABIInternal so as to avoid introducing a wrapper, // which would make caller's PC ineffective. TEXT runtime·raceread(SB), NOSPLIT, $0-8 +#ifdef GOEXPERIMENT_regabiargs + MOVD R0, R1 // addr +#else MOVD addr+0(FP), R1 +#endif MOVD LR, R2 // void __tsan_read(ThreadState *thr, void *addr, void *pc); MOVD $__tsan_read(SB), R9 @@ -71,7 +75,11 @@ TEXT runtime·racereadpc(SB), NOSPLIT, $0-24 // Defined as ABIInternal so as to avoid introducing a wrapper, // which would make caller's PC ineffective. TEXT runtime·racewrite(SB), NOSPLIT, $0-8 +#ifdef GOEXPERIMENT_regabiargs + MOVD R0, R1 // addr +#else MOVD addr+0(FP), R1 +#endif MOVD LR, R2 // void __tsan_write(ThreadState *thr, void *addr, void *pc); MOVD $__tsan_write(SB), R9 @@ -96,8 +104,13 @@ TEXT runtime·racewritepc(SB), NOSPLIT, $0-24 // Defined as ABIInternal so as to avoid introducing a wrapper, // which would make caller's PC ineffective. TEXT runtime·racereadrange(SB), NOSPLIT, $0-16 +#ifdef GOEXPERIMENT_regabiargs + MOVD R1, R2 // size + MOVD R0, R1 // addr +#else MOVD addr+0(FP), R1 MOVD size+8(FP), R2 +#endif MOVD LR, R3 // void __tsan_read_range(ThreadState *thr, void *addr, uintptr size, void *pc); MOVD $__tsan_read_range(SB), R9 @@ -123,8 +136,13 @@ TEXT runtime·racereadrangepc1(SB), NOSPLIT, $0-24 // Defined as ABIInternal so as to avoid introducing a wrapper, // which would make caller's PC ineffective. TEXT runtime·racewriterange(SB), NOSPLIT, $0-16 +#ifdef GOEXPERIMENT_regabiargs + MOVD R1, R2 // size + MOVD R0, R1 // addr +#else MOVD addr+0(FP), R1 MOVD size+8(FP), R2 +#endif MOVD LR, R3 // void __tsan_write_range(ThreadState *thr, void *addr, uintptr size, void *pc); MOVD $__tsan_write_range(SB), R9 -- GitLab From 7b876def6c4936cfae774d3007f8265876a9fbf7 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 16 Apr 2021 14:06:50 -0700 Subject: [PATCH 0172/2500] [dev.typeparams] cmd/compile: add dictionary argument to generic functions When converting from a generic function to a concrete implementation, add a dictionary argument to the generic function (both an actual argument at each callsite, and a formal argument of each implementation). The dictionary argument comes before all other arguments (including any receiver). The dictionary argument is checked for validity, but is otherwise unused. Subsequent CLs will start using the dictionary for, e.g., converting a value of generic type to interface{}. Import/export required adding support for LINKSYMOFFSET, which is used by the dictionary checking code. Change-Id: I16a7a8d23c7bd6a897e0da87c69f273be9103bd7 Reviewed-on: https://go-review.googlesource.com/c/go/+/323272 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/irgen.go | 2 + src/cmd/compile/internal/noder/stencil.go | 440 +++++++++++++++--- src/cmd/compile/internal/noder/transform.go | 72 ++- .../compile/internal/reflectdata/reflect.go | 151 +++++- src/cmd/compile/internal/typecheck/iexport.go | 10 +- src/cmd/compile/internal/typecheck/iimport.go | 7 + src/cmd/compile/internal/typecheck/subr.go | 13 +- src/cmd/compile/internal/types/type.go | 2 +- src/runtime/internal/atomic/atomic_arm64.go | 2 +- test/typeparam/dictionaryCapture.go | 100 ++++ 10 files changed, 687 insertions(+), 112 deletions(-) create mode 100644 test/typeparam/dictionaryCapture.go diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index d5ef0c0ef4..3f362e9d2b 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -105,6 +105,8 @@ type irgen struct { // Fully-instantiated generic types whose methods should be instantiated instTypeList []*types.Type + + dnum int // for generating unique dictionary variables } func (g *irgen) generate(noders []*noder) { diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 36a6f2e6d0..08c09c6fb1 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -10,9 +10,11 @@ package noder import ( "cmd/compile/internal/base" "cmd/compile/internal/ir" + "cmd/compile/internal/reflectdata" "cmd/compile/internal/typecheck" "cmd/compile/internal/types" "fmt" + "go/constant" "strings" ) @@ -70,72 +72,89 @@ func (g *irgen) stencil() { // instantiated function if it hasn't been created yet, and change // to calling that function directly. modified := false - foundFuncInst := false + closureRequired := false ir.Visit(decl, func(n ir.Node) { if n.Op() == ir.OFUNCINST { - // We found a function instantiation that is not - // immediately called. - foundFuncInst = true + // generic F, not immediately called + closureRequired = true } - if n.Op() != ir.OCALL || n.(*ir.CallExpr).X.Op() != ir.OFUNCINST { - return + if n.Op() == ir.OMETHEXPR && len(n.(*ir.SelectorExpr).X.Type().RParams()) > 0 { + // T.M, T a type which is generic, not immediately called + closureRequired = true } - // We have found a function call using a generic function - // instantiation. - call := n.(*ir.CallExpr) - inst := call.X.(*ir.InstExpr) - // Replace the OFUNCINST with a direct reference to the - // new stenciled function - st := g.getInstantiationForNode(inst) - call.X = st.Nname - if inst.X.Op() == ir.OCALLPART { - // When we create an instantiation of a method - // call, we make it a function. So, move the - // receiver to be the first arg of the function - // call. - withRecv := make([]ir.Node, len(call.Args)+1) - dot := inst.X.(*ir.SelectorExpr) - withRecv[0] = dot.X - copy(withRecv[1:], call.Args) - call.Args = withRecv + if n.Op() == ir.OCALL && n.(*ir.CallExpr).X.Op() == ir.OFUNCINST { + // We have found a function call using a generic function + // instantiation. + call := n.(*ir.CallExpr) + inst := call.X.(*ir.InstExpr) + st := g.getInstantiationForNode(inst) + // Replace the OFUNCINST with a direct reference to the + // new stenciled function + call.X = st.Nname + if inst.X.Op() == ir.OCALLPART { + // When we create an instantiation of a method + // call, we make it a function. So, move the + // receiver to be the first arg of the function + // call. + call.Args.Prepend(inst.X.(*ir.SelectorExpr).X) + } + // Add dictionary to argument list. + dict := reflectdata.GetDictionaryForInstantiation(inst) + call.Args.Prepend(dict) + // Transform the Call now, which changes OCALL + // to OCALLFUNC and does typecheckaste/assignconvfn. + transformCall(call) + modified = true + } + if n.Op() == ir.OCALLMETH && n.(*ir.CallExpr).X.Op() == ir.ODOTMETH && len(deref(n.(*ir.CallExpr).X.Type().Recv().Type).RParams()) > 0 { + // Method call on a generic type, which was instantiated by stenciling. + // Method calls on explicitly instantiated types will have an OFUNCINST + // and are handled above. + call := n.(*ir.CallExpr) + meth := call.X.(*ir.SelectorExpr) + targs := deref(meth.Type().Recv().Type).RParams() + + t := meth.X.Type() + baseSym := deref(t).OrigSym + baseType := baseSym.Def.(*ir.Name).Type() + var gf *ir.Name + for _, m := range baseType.Methods().Slice() { + if meth.Sel == m.Sym { + gf = m.Nname.(*ir.Name) + break + } + } + + st := g.getInstantiation(gf, targs, true) + call.SetOp(ir.OCALL) + call.X = st.Nname + dict := reflectdata.GetDictionaryForMethod(gf, targs) + call.Args.Prepend(dict, meth.X) + // Transform the Call now, which changes OCALL + // to OCALLFUNC and does typecheckaste/assignconvfn. + transformCall(call) + modified = true } - // Transform the Call now, which changes OCALL - // to OCALLFUNC and does typecheckaste/assignconvfn. - transformCall(call) - modified = true }) - // If we found an OFUNCINST without a corresponding call in the - // above decl, then traverse the nodes of decl again (with + // If we found a reference to a generic instantiation that wasn't an + // immediate call, then traverse the nodes of decl again (with // EditChildren rather than Visit), where we actually change the - // OFUNCINST node to an ONAME for the instantiated function. + // reference to the instantiation to a closure that captures the + // dictionary, then does a direct call. // EditChildren is more expensive than Visit, so we only do this // in the infrequent case of an OFUNCINST without a corresponding // call. - if foundFuncInst { + if closureRequired { var edit func(ir.Node) ir.Node edit = func(x ir.Node) ir.Node { - if x.Op() == ir.OFUNCINST { - // inst.X is either a function name node - // or a selector expression for a method. - inst := x.(*ir.InstExpr) - st := g.getInstantiationForNode(inst) - modified = true - if inst.X.Op() == ir.ONAME { - return st.Nname - } - assert(inst.X.Op() == ir.OCALLPART) - - // Return a new selector expression referring - // to the newly stenciled function. - oldse := inst.X.(*ir.SelectorExpr) - newse := ir.NewSelectorExpr(oldse.Pos(), ir.OCALLPART, oldse.X, oldse.Sel) - newse.Selection = types.NewField(oldse.Pos(), st.Sym(), st.Type()) - newse.Selection.Nname = st - typed(inst.Type(), newse) - return newse - } ir.EditChildren(x, edit) + switch { + case x.Op() == ir.OFUNCINST: + return g.buildClosure(decl.(*ir.Func), x) + case x.Op() == ir.OMETHEXPR && len(deref(x.(*ir.SelectorExpr).X.Type()).RParams()) > 0: // TODO: test for ptr-to-method case + return g.buildClosure(decl.(*ir.Func), x) + } return x } edit(decl) @@ -153,6 +172,228 @@ func (g *irgen) stencil() { } +// buildClosure makes a closure to implement x, a OFUNCINST or OMETHEXPR +// of generic type. outer is the containing function. +func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { + pos := x.Pos() + var target *ir.Func // target instantiated function/method + var dictValue ir.Node // dictionary to use + var rcvrValue ir.Node // receiver, if a method value + typ := x.Type() // type of the closure + if x.Op() == ir.OFUNCINST { + inst := x.(*ir.InstExpr) + + // Type arguments we're instantiating with. + targs := typecheck.TypesOf(inst.Targs) + + // Find the generic function/method. + var gf *ir.Name + if inst.X.Op() == ir.ONAME { + // Instantiating a generic function call. + gf = inst.X.(*ir.Name) + } else if inst.X.Op() == ir.OCALLPART { + // Instantiating a method value x.M. + se := inst.X.(*ir.SelectorExpr) + rcvrValue = se.X + gf = se.Selection.Nname.(*ir.Name) + } else { + panic("unhandled") + } + + // target is the instantiated function we're trying to call. + // For functions, the target expects a dictionary as its first argument. + // For method values, the target expects a dictionary and the receiver + // as its first two arguments. + target = g.getInstantiation(gf, targs, rcvrValue != nil) + + // The value to use for the dictionary argument. + if rcvrValue == nil { + dictValue = reflectdata.GetDictionaryForFunc(gf, targs) + } else { + dictValue = reflectdata.GetDictionaryForMethod(gf, targs) + } + } else { // ir.OMETHEXPR + // Method expression T.M where T is a generic type. + // TODO: Is (*T).M right? + se := x.(*ir.SelectorExpr) + targs := se.X.Type().RParams() + if len(targs) == 0 { + if se.X.Type().IsPtr() { + targs = se.X.Type().Elem().RParams() + if len(targs) == 0 { + panic("bad") + } + } + } + t := se.X.Type() + baseSym := t.OrigSym + baseType := baseSym.Def.(*ir.Name).Type() + var gf *ir.Name + for _, m := range baseType.Methods().Slice() { + if se.Sel == m.Sym { + gf = m.Nname.(*ir.Name) + break + } + } + target = g.getInstantiation(gf, targs, true) + dictValue = reflectdata.GetDictionaryForMethod(gf, targs) + } + + // Build a closure to implement a function instantiation. + // + // func f[T any] (int, int) (int, int) { ...whatever... } + // + // Then any reference to f[int] not directly called gets rewritten to + // + // .dictN := ... dictionary to use ... + // func(a0, a1 int) (r0, r1 int) { + // return .inst.f[int](.dictN, a0, a1) + // } + // + // Similarly for method expressions, + // + // type g[T any] .... + // func (rcvr g[T]) f(a0, a1 int) (r0, r1 int) { ... } + // + // Any reference to g[int].f not directly called gets rewritten to + // + // .dictN := ... dictionary to use ... + // func(rcvr g[int], a0, a1 int) (r0, r1 int) { + // return .inst.g[int].f(.dictN, rcvr, a0, a1) + // } + // + // Also method values + // + // var x g[int] + // + // Any reference to x.f not directly called gets rewritten to + // + // .dictN := ... dictionary to use ... + // x2 := x + // func(a0, a1 int) (r0, r1 int) { + // return .inst.g[int].f(.dictN, x2, a0, a1) + // } + + // Make a new internal function. + fn := ir.NewFunc(pos) + fn.SetIsHiddenClosure(true) + + // This is the dictionary we want to use. + // Note: for now this is a compile-time constant, so we don't really need a closure + // to capture it (a wrapper function would work just as well). But eventually it + // will be a read of a subdictionary from the parent dictionary. + dictVar := ir.NewNameAt(pos, typecheck.LookupNum(".dict", g.dnum)) + g.dnum++ + dictVar.Class = ir.PAUTO + typed(types.Types[types.TUINTPTR], dictVar) + dictVar.Curfn = outer + dictAssign := ir.NewAssignStmt(pos, dictVar, dictValue) + dictAssign.SetTypecheck(1) + dictVar.Defn = dictAssign + outer.Dcl = append(outer.Dcl, dictVar) + + // assign the receiver to a temporary. + var rcvrVar *ir.Name + var rcvrAssign ir.Node + if rcvrValue != nil { + rcvrVar = ir.NewNameAt(pos, typecheck.LookupNum(".rcvr", g.dnum)) + g.dnum++ + rcvrVar.Class = ir.PAUTO + typed(rcvrValue.Type(), rcvrVar) + rcvrVar.Curfn = outer + rcvrAssign = ir.NewAssignStmt(pos, rcvrVar, rcvrValue) + rcvrAssign.SetTypecheck(1) + rcvrVar.Defn = rcvrAssign + outer.Dcl = append(outer.Dcl, rcvrVar) + } + + // Build formal argument and return lists. + var formalParams []*types.Field // arguments of closure + var formalResults []*types.Field // returns of closure + for i := 0; i < typ.NumParams(); i++ { + t := typ.Params().Field(i).Type + arg := ir.NewNameAt(pos, typecheck.LookupNum("a", i)) + arg.Class = ir.PPARAM + typed(t, arg) + arg.Curfn = fn + fn.Dcl = append(fn.Dcl, arg) + f := types.NewField(pos, arg.Sym(), t) + f.Nname = arg + formalParams = append(formalParams, f) + } + for i := 0; i < typ.NumResults(); i++ { + t := typ.Results().Field(i).Type + result := ir.NewNameAt(pos, typecheck.LookupNum("r", i)) // TODO: names not needed? + result.Class = ir.PPARAMOUT + typed(t, result) + result.Curfn = fn + fn.Dcl = append(fn.Dcl, result) + f := types.NewField(pos, result.Sym(), t) + f.Nname = result + formalResults = append(formalResults, f) + } + + // Build an internal function with the right signature. + closureType := types.NewSignature(x.Type().Pkg(), nil, nil, formalParams, formalResults) + sym := typecheck.ClosureName(outer) + sym.SetFunc(true) + fn.Nname = ir.NewNameAt(pos, sym) + fn.Nname.Func = fn + fn.Nname.Defn = fn + typed(closureType, fn.Nname) + fn.SetTypecheck(1) + + // Build body of closure. This involves just calling the wrapped function directly + // with the additional dictionary argument. + + // First, capture the dictionary variable for use in the closure. + dict2Var := ir.CaptureName(pos, fn, dictVar) + // Also capture the receiver variable. + var rcvr2Var *ir.Name + if rcvrValue != nil { + rcvr2Var = ir.CaptureName(pos, fn, rcvrVar) + } + + // Build arguments to call inside the closure. + var args []ir.Node + + // First the dictionary argument. + args = append(args, dict2Var) + // Then the receiver. + if rcvrValue != nil { + args = append(args, rcvr2Var) + } + // Then all the other arguments (including receiver for method expressions). + for i := 0; i < typ.NumParams(); i++ { + args = append(args, formalParams[i].Nname.(*ir.Name)) + } + + // Build call itself. + var innerCall ir.Node = ir.NewCallExpr(pos, ir.OCALL, target.Nname, args) + if len(formalResults) > 0 { + innerCall = ir.NewReturnStmt(pos, []ir.Node{innerCall}) + } + // Finish building body of closure. + ir.CurFunc = fn + // TODO: set types directly here instead of using typecheck.Stmt + typecheck.Stmt(innerCall) + ir.CurFunc = nil + fn.Body = []ir.Node{innerCall} + + // We're all done with the captured dictionary (and receiver, for method values). + ir.FinishCaptureNames(pos, outer, fn) + + // Make a closure referencing our new internal function. + c := ir.NewClosureExpr(pos, fn) + init := []ir.Node{dictAssign} + if rcvrValue != nil { + init = append(init, rcvrAssign) + } + c.SetInit(init) + typed(x.Type(), c) + return c +} + // instantiateMethods instantiates all the methods of all fully-instantiated // generic types that have been added to g.instTypeList. func (g *irgen) instantiateMethods() { @@ -167,14 +408,17 @@ func (g *irgen) instantiateMethods() { // not be set on imported instantiated types. baseSym := typ.OrigSym baseType := baseSym.Def.(*ir.Name).Type() - for j, m := range typ.Methods().Slice() { - name := m.Nname.(*ir.Name) + for j, _ := range typ.Methods().Slice() { baseNname := baseType.Methods().Slice()[j].Nname.(*ir.Name) - // Note: we are breaking an invariant here: - // m.Nname is now not equal m.Nname.Func.Nname. - // m.Nname has the type of a method, whereas m.Nname.Func.Nname has - // the type of a function, since it is an function instantiation. - name.Func = g.getInstantiation(baseNname, typ.RParams(), true) + // Eagerly generate the instantiations that implement these methods. + // We don't use the instantiations here, just generate them (and any + // further instantiations those generate, etc.). + // Note that we don't set the Func for any methods on instantiated + // types. Their signatures don't match so that would be confusing. + // Direct method calls go directly to the instantiations, implemented above. + // Indirect method calls use wrappers generated in reflectcall. Those wrappers + // will use these instantiations if they are needed (for interface tables or reflection). + _ = g.getInstantiation(baseNname, typ.RParams(), true) } } g.instTypeList = nil @@ -287,10 +531,7 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []*type vars: make(map[*ir.Name]*ir.Name), } - newf.Dcl = make([]*ir.Name, len(gf.Dcl)) - for i, n := range gf.Dcl { - newf.Dcl[i] = subst.localvar(n) - } + newf.Dcl = make([]*ir.Name, 0, len(gf.Dcl)+1) // Replace the types in the function signature. // Ugly: also, we have to insert the Name nodes of the parameters/results into @@ -298,18 +539,40 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []*type // because it came via conversion from the types2 type. oldt := nameNode.Type() // We also transform a generic method type to the corresponding - // instantiated function type where the receiver is the first parameter. + // instantiated function type where the dictionary is the first parameter. + dictionarySym := types.LocalPkg.Lookup(".dict") + dictionaryType := types.Types[types.TUINTPTR] + dictionaryName := ir.NewNameAt(gf.Pos(), dictionarySym) + typed(dictionaryType, dictionaryName) + dictionaryName.Class = ir.PPARAM + dictionaryName.Curfn = newf + newf.Dcl = append(newf.Dcl, dictionaryName) + for _, n := range gf.Dcl { + if n.Sym().Name == ".dict" { + panic("already has dictionary") + } + newf.Dcl = append(newf.Dcl, subst.localvar(n)) + } + dictionaryArg := types.NewField(gf.Pos(), dictionarySym, dictionaryType) + dictionaryArg.Nname = dictionaryName + var args []*types.Field + args = append(args, dictionaryArg) + args = append(args, oldt.Recvs().FieldSlice()...) + args = append(args, oldt.Params().FieldSlice()...) newt := types.NewSignature(oldt.Pkg(), nil, nil, - subst.fields(ir.PPARAM, append(oldt.Recvs().FieldSlice(), oldt.Params().FieldSlice()...), newf.Dcl), + subst.fields(ir.PPARAM, args, newf.Dcl), subst.fields(ir.PPARAMOUT, oldt.Results().FieldSlice(), newf.Dcl)) - newf.Nname.SetType(newt) + typed(newt, newf.Nname) ir.MarkFunc(newf.Nname) newf.SetTypecheck(1) - newf.Nname.SetTypecheck(1) // Make sure name/type of newf is set before substituting the body. newf.Body = subst.list(gf.Body) + + // Add code to check that the dictionary is correct. + newf.Body.Prepend(g.checkDictionary(dictionaryName, targs)...) + ir.CurFunc = savef return newf @@ -334,6 +597,44 @@ func (subst *subster) localvar(name *ir.Name) *ir.Name { return m } +// checkDictionary returns code that does runtime consistency checks +// between the dictionary and the types it should contain. +func (g *irgen) checkDictionary(name *ir.Name, targs []*types.Type) (code []ir.Node) { + if false { + return // checking turned off + } + // TODO: when moving to GCshape, this test will become harder. Call into + // runtime to check the expected shape is correct? + pos := name.Pos() + // Convert dictionary to *[N]uintptr + d := ir.NewConvExpr(pos, ir.OCONVNOP, types.Types[types.TUNSAFEPTR], name) + d.SetTypecheck(1) + d = ir.NewConvExpr(pos, ir.OCONVNOP, types.NewArray(types.Types[types.TUINTPTR], int64(len(targs))).PtrTo(), d) + d.SetTypecheck(1) + + // Check that each type entry in the dictionary is correct. + for i, t := range targs { + want := reflectdata.TypePtr(t) + typed(types.Types[types.TUINTPTR], want) + deref := ir.NewStarExpr(pos, d) + typed(d.Type().Elem(), deref) + idx := ir.NewConstExpr(constant.MakeUint64(uint64(i)), name) // TODO: what to set orig to? + typed(types.Types[types.TUINTPTR], idx) + got := ir.NewIndexExpr(pos, deref, idx) + typed(types.Types[types.TUINTPTR], got) + cond := ir.NewBinaryExpr(pos, ir.ONE, want, got) + typed(types.Types[types.TBOOL], cond) + panicArg := ir.NewNilExpr(pos) + typed(types.NewInterface(types.LocalPkg, nil), panicArg) + then := ir.NewUnaryExpr(pos, ir.OPANIC, panicArg) + then.SetTypecheck(1) + x := ir.NewIfStmt(pos, cond, []ir.Node{then}, nil) + x.SetTypecheck(1) + code = append(code, x) + } + return +} + // node is like DeepCopy(), but substitutes ONAME nodes based on subst.vars, and // also descends into closures. It substitutes type arguments for type parameters // in all the new nodes. @@ -837,13 +1138,14 @@ func (subst *subster) typ(t *types.Type) *types.Type { t2 := subst.typ(f.Type) oldsym := f.Nname.Sym() newsym := typecheck.MakeInstName(oldsym, subst.targs, true) + // TODO: use newsym? var nname *ir.Name if newsym.Def != nil { nname = newsym.Def.(*ir.Name) } else { - nname = ir.NewNameAt(f.Pos, newsym) + nname = ir.NewNameAt(f.Pos, oldsym) nname.SetType(t2) - newsym.Def = nname + oldsym.Def = nname } newfields[i] = types.NewField(f.Pos, f.Sym, t2) newfields[i].Nname = nname diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index 2859089e69..90d38fe514 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -340,12 +340,12 @@ assignOK: } } -// Corresponds to typecheck.typecheckargs. +// Corresponds to, but slightly more general than, typecheck.typecheckargs. func transformArgs(n ir.InitNode) { var list []ir.Node switch n := n.(type) { default: - base.Fatalf("typecheckargs %+v", n.Op()) + base.Fatalf("transformArgs %+v", n.Op()) case *ir.CallExpr: list = n.Args if n.IsDDD { @@ -354,25 +354,31 @@ func transformArgs(n ir.InitNode) { case *ir.ReturnStmt: list = n.Results } - if len(list) != 1 { - return - } - t := list[0].Type() - if t == nil || !t.IsFuncArgStruct() { + // Look to see if we have any multi-return functions as arguments. + extra := 0 + for _, arg := range list { + t := arg.Type() + if t.IsFuncArgStruct() { + num := t.Fields().Len() + if num <= 1 { + base.Fatalf("multi-return type with only %d parts", num) + } + extra += num - 1 + } + } + // If not, nothing to do. + if extra == 0 { return } - // Rewrite f(g()) into t1, t2, ... = g(); f(t1, t2, ...). + // Rewrite f(..., g(), ...) into t1, ..., tN = g(); f(..., t1, ..., tN, ...). // Save n as n.Orig for fmt.go. if ir.Orig(n) == n { n.(ir.OrigNode).SetOrig(ir.SepCopy(n)) } - as := ir.NewAssignListStmt(base.Pos, ir.OAS2, nil, nil) - as.Rhs.Append(list...) - // If we're outside of function context, then this call will // be executed during the generated init function. However, // init.go hasn't yet created it. Instead, associate the @@ -382,27 +388,42 @@ func transformArgs(n ir.InitNode) { if static { ir.CurFunc = typecheck.InitTodoFunc } - list = nil - for _, f := range t.FieldSlice() { - t := typecheck.Temp(f.Type) - as.PtrInit().Append(ir.NewDecl(base.Pos, ir.ODCL, t)) - as.Lhs.Append(t) - list = append(list, t) + + // Expand multi-return function calls. + // The spec only allows a multi-return function as an argument + // if it is the only argument. This code must handle calls to + // stenciled generic functions which have extra arguments + // (like the dictionary) so it must handle a slightly more general + // cases, like f(n, g()) where g is multi-return. + newList := make([]ir.Node, 0, len(list)+extra) + for _, arg := range list { + t := arg.Type() + if t.IsFuncArgStruct() { + as := ir.NewAssignListStmt(base.Pos, ir.OAS2, nil, []ir.Node{arg}) + for _, f := range t.FieldSlice() { + t := typecheck.Temp(f.Type) + as.PtrInit().Append(ir.NewDecl(base.Pos, ir.ODCL, t)) + as.Lhs.Append(t) + newList = append(newList, t) + } + transformAssign(as, as.Lhs, as.Rhs) + as.SetTypecheck(1) + n.PtrInit().Append(as) + } else { + newList = append(newList, arg) + } } + if static { ir.CurFunc = nil } switch n := n.(type) { case *ir.CallExpr: - n.Args = list + n.Args = newList case *ir.ReturnStmt: - n.Results = list + n.Results = newList } - - transformAssign(as, as.Lhs, as.Rhs) - as.SetTypecheck(1) - n.PtrInit().Append(as) } // assignconvfn converts node n for assignment to type t. Corresponds to @@ -562,6 +583,11 @@ func transformDot(n *ir.SelectorExpr, isCall bool) ir.Node { if (n.Op() == ir.ODOTINTER || n.Op() == ir.ODOTMETH) && !isCall { n.SetOp(ir.OCALLPART) + if len(n.X.Type().RParams()) > 0 || n.X.Type().IsPtr() && len(n.X.Type().Elem().RParams()) > 0 { + // TODO: MethodValueWrapper needed for generics? + // Or did we successfully desugar all that at stencil time? + return n + } n.SetType(typecheck.MethodValueWrapper(n).Type()) } return n diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index d452d4f194..604cec6096 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -321,13 +321,6 @@ func methods(t *types.Type) []*typeSig { } typecheck.CalcMethods(mt) - // type stored in interface word - it := t - - if !types.IsDirectIface(it) { - it = types.NewPtr(t) - } - // make list of methods for t, // generating code if necessary. var ms []*typeSig @@ -355,8 +348,8 @@ func methods(t *types.Type) []*typeSig { sig := &typeSig{ name: f.Sym, - isym: methodWrapper(it, f), - tsym: methodWrapper(t, f), + isym: methodWrapper(t, f, true), + tsym: methodWrapper(t, f, false), type_: typecheck.NewMethodType(f.Type, t), mtype: typecheck.NewMethodType(f.Type, nil), } @@ -394,7 +387,7 @@ func imethods(t *types.Type) []*typeSig { // IfaceType.Method is not in the reflect data. // Generate the method body, so that compiled // code can refer to it. - methodWrapper(t, f) + methodWrapper(t, f, false) } return methods @@ -1765,7 +1758,28 @@ func CollectPTabs() { // // rcvr - U // method - M func (t T)(), a TFIELD type struct -func methodWrapper(rcvr *types.Type, method *types.Field) *obj.LSym { +// +// Also wraps methods on instantiated generic types for use in itab entries. +// For an instantiated generic type G[int], we generate wrappers like: +// G[int] pointer shaped: +// func (x G[int]) f(arg) { +// .inst.G[int].f(dictionary, x, arg) +// } +// G[int] not pointer shaped: +// func (x *G[int]) f(arg) { +// .inst.G[int].f(dictionary, *x, arg) +// } +// These wrappers are always fully stenciled. +func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSym { + orig := rcvr + if forItab && !types.IsDirectIface(rcvr) { + rcvr = rcvr.PtrTo() + } + generic := false + if !rcvr.IsInterface() && len(rcvr.RParams()) > 0 || rcvr.IsPtr() && len(rcvr.Elem().RParams()) > 0 { // TODO: right detection? + // TODO: check that we do the right thing when rcvr.IsInterface(). + generic = true + } newnam := ir.MethodSym(rcvr, method.Sym) lsym := newnam.Linksym() if newnam.Siggen() { @@ -1773,7 +1787,7 @@ func methodWrapper(rcvr *types.Type, method *types.Field) *obj.LSym { } newnam.SetSiggen(true) - if types.Identical(rcvr, method.Type.Recv().Type) { + if !generic && types.Identical(rcvr, method.Type.Recv().Type) { return lsym } @@ -1808,9 +1822,10 @@ func methodWrapper(rcvr *types.Type, method *types.Field) *obj.LSym { nthis := ir.AsNode(tfn.Type().Recv().Nname) methodrcvr := method.Type.Recv().Type + indirect := rcvr.IsPtr() && rcvr.Elem() == methodrcvr // generate nil pointer check for better error - if rcvr.IsPtr() && rcvr.Elem() == methodrcvr { + if indirect { // generating wrapper from *T to T. n := ir.NewIfStmt(base.Pos, nil, nil, nil) n.Cond = ir.NewBinaryExpr(base.Pos, ir.OEQ, nthis, typecheck.NodNil()) @@ -1832,7 +1847,7 @@ func methodWrapper(rcvr *types.Type, method *types.Field) *obj.LSym { // Disable tailcall for RegabiArgs for now. The IR does not connect the // arguments with the OTAILCALL node, and the arguments are not marshaled // correctly. - if !base.Flag.Cfg.Instrumenting && rcvr.IsPtr() && methodrcvr.IsPtr() && method.Embedded != 0 && !types.IsInterfaceMethod(method.Type) && !(base.Ctxt.Arch.Name == "ppc64le" && base.Ctxt.Flag_dynlink) && !buildcfg.Experiment.RegabiArgs { + if !base.Flag.Cfg.Instrumenting && rcvr.IsPtr() && methodrcvr.IsPtr() && method.Embedded != 0 && !types.IsInterfaceMethod(method.Type) && !(base.Ctxt.Arch.Name == "ppc64le" && base.Ctxt.Flag_dynlink) && !buildcfg.Experiment.RegabiArgs && !generic { // generate tail call: adjust pointer receiver and jump to embedded method. left := dot.X // skip final .M if !left.Type().IsPtr() { @@ -1843,8 +1858,44 @@ func methodWrapper(rcvr *types.Type, method *types.Field) *obj.LSym { fn.Body.Append(ir.NewTailCallStmt(base.Pos, method.Nname.(*ir.Name))) } else { fn.SetWrapper(true) // ignore frame for panic+recover matching - call := ir.NewCallExpr(base.Pos, ir.OCALL, dot, nil) - call.Args = ir.ParamNames(tfn.Type()) + var call *ir.CallExpr + if generic { + var args []ir.Node + var targs []*types.Type + if rcvr.IsPtr() { // TODO: correct condition? + targs = rcvr.Elem().RParams() + } else { + targs = rcvr.RParams() + } + if strings.HasPrefix(ir.MethodSym(orig, method.Sym).Name, ".inst.") { + fmt.Printf("%s\n", ir.MethodSym(orig, method.Sym).Name) + panic("multiple .inst.") + } + args = append(args, getDictionary(".inst."+ir.MethodSym(orig, method.Sym).Name, targs)) // TODO: remove .inst. + if indirect { + args = append(args, ir.NewStarExpr(base.Pos, nthis)) + } else { + args = append(args, nthis) + } + args = append(args, ir.ParamNames(tfn.Type())...) + + // TODO: Once we enter the gcshape world, we'll need a way to look up + // the stenciled implementation to use for this concrete type. Essentially, + // erase the concrete types and replace them with gc shape representatives. + sym := typecheck.MakeInstName(ir.MethodSym(methodrcvr, method.Sym), targs, true) + if sym.Def == nil { + // Currently we make sure that we have all the instantiations + // we need by generating them all in ../noder/stencil.go:instantiateMethods + // TODO: maybe there's a better, more incremental way to generate + // only the instantiations we need? + base.Fatalf("instantiation %s not found", sym.Name) + } + target := ir.AsNode(sym.Def) + call = ir.NewCallExpr(base.Pos, ir.OCALL, target, args) + } else { + call = ir.NewCallExpr(base.Pos, ir.OCALL, dot, nil) + call.Args = ir.ParamNames(tfn.Type()) + } call.IsDDD = tfn.Type().IsVariadic() if method.Type.NumResults() > 0 { ret := ir.NewReturnStmt(base.Pos, nil) @@ -1909,3 +1960,71 @@ func MarkUsedIfaceMethod(n *ir.CallExpr) { r.Add = InterfaceMethodOffset(ityp, midx) r.Type = objabi.R_USEIFACEMETHOD } + +// getDictionaryForInstantiation returns the dictionary that should be used for invoking +// the concrete instantiation described by inst. +func GetDictionaryForInstantiation(inst *ir.InstExpr) ir.Node { + targs := typecheck.TypesOf(inst.Targs) + if meth, ok := inst.X.(*ir.SelectorExpr); ok { + return GetDictionaryForMethod(meth.Selection.Nname.(*ir.Name), targs) + } + return GetDictionaryForFunc(inst.X.(*ir.Name), targs) +} + +func GetDictionaryForFunc(fn *ir.Name, targs []*types.Type) ir.Node { + return getDictionary(typecheck.MakeInstName(fn.Sym(), targs, false).Name, targs) +} +func GetDictionaryForMethod(meth *ir.Name, targs []*types.Type) ir.Node { + return getDictionary(typecheck.MakeInstName(meth.Sym(), targs, true).Name, targs) +} + +// getDictionary returns the dictionary for the given named generic function +// or method, with the given type arguments. +// TODO: pass a reference to the generic function instead? We might need +// that to look up protodictionaries. +func getDictionary(name string, targs []*types.Type) ir.Node { + if len(targs) == 0 { + base.Fatalf("%s should have type arguments", name) + } + + // The dictionary for this instantiation is named after the function + // and concrete types it is instantiated with. + // TODO: decouple this naming from the instantiation naming. The instantiation + // naming will be based on GC shapes, this naming must be fully stenciled. + if !strings.HasPrefix(name, ".inst.") { + base.Fatalf("%s should start in .inst.", name) + } + name = ".dict." + name[6:] + + // Get a symbol representing the dictionary. + sym := typecheck.Lookup(name) + + // Initialize the dictionary, if we haven't yet already. + if lsym := sym.Linksym(); len(lsym.P) == 0 { + off := 0 + // Emit an entry for each concrete type. + for _, t := range targs { + s := TypeLinksym(t) + off = objw.SymPtr(lsym, off, s, 0) + } + // TODO: subdictionaries + objw.Global(lsym, int32(off), obj.DUPOK|obj.RODATA) + } + + // Make a node referencing the dictionary symbol. + n := typecheck.NewName(sym) + n.SetType(types.Types[types.TUINTPTR]) // should probably be [...]uintptr, but doesn't really matter + n.SetTypecheck(1) + n.Class = ir.PEXTERN + sym.Def = n + + // Return the address of the dictionary. + np := typecheck.NodAddr(n) + // Note: treat dictionary pointers as uintptrs, so they aren't pointers + // with respect to GC. That saves on stack scanning work, write barriers, etc. + // We can get away with it because dictionaries are global variables. + // TODO: use a cast, or is typing directly ok? + np.SetType(types.Types[types.TUINTPTR]) + np.SetTypecheck(1) + return np +} diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index f49718d442..d83f385fcb 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -1904,6 +1904,14 @@ func (w *exportWriter) expr(n ir.Node) { w.op(ir.OEND) } + case ir.OLINKSYMOFFSET: + n := n.(*ir.LinksymOffsetExpr) + w.op(ir.OLINKSYMOFFSET) + w.pos(n.Pos()) + w.string(n.Linksym.Name) + w.uint64(uint64(n.Offset_)) + w.typ(n.Type()) + // unary expressions case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT, ir.ORECV: n := n.(*ir.UnaryExpr) @@ -2068,7 +2076,7 @@ func (w *exportWriter) localIdent(s *types.Sym) { } // TODO(mdempsky): Fix autotmp hack. - if i := strings.LastIndex(name, "."); i >= 0 && !strings.HasPrefix(name, ".autotmp_") { + if i := strings.LastIndex(name, "."); i >= 0 && !strings.HasPrefix(name, ".autotmp_") && !strings.HasPrefix(name, ".dict") { // TODO: just use autotmp names for dictionaries? base.Fatalf("unexpected dot in identifier: %v", name) } diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index cca14a0d91..4c31e47378 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1467,6 +1467,13 @@ func (r *importReader) node() ir.Node { n.Args.Append(r.exprList()...) return n + case ir.OLINKSYMOFFSET: + pos := r.pos() + name := r.string() + off := r.uint64() + typ := r.typ() + return ir.NewLinksymOffsetExpr(pos, Lookup(name).Linksym(), int64(off), typ) + // unary expressions case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT, ir.ORECV: n := ir.NewUnaryExpr(r.pos(), op, r.expr()) diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 9eac802dab..3e7799b35b 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -901,6 +901,14 @@ func TypesOf(x []ir.Node) []*types.Type { // '(*genType[int,bool]).methodName' for methods func MakeInstName(fnsym *types.Sym, targs []*types.Type, hasBrackets bool) *types.Sym { b := bytes.NewBufferString("") + + // marker to distinguish generic instantiations from fully stenciled wrapper functions. + // Once we move to GC shape implementations, this prefix will not be necessary as the + // GC shape naming will distinguish them. + // e.g. f[8bytenonpointer] vs. f[int]. + // For now, we use .inst.f[int] vs. f[int]. + b.WriteString(".inst.") + name := fnsym.Name i := strings.Index(name, "[") assert(hasBrackets == (i >= 0)) @@ -924,10 +932,13 @@ func MakeInstName(fnsym *types.Sym, targs []*types.Type, hasBrackets bool) *type } b.WriteString("]") if i >= 0 { - i2 := strings.Index(name[i:], "]") + i2 := strings.LastIndex(name[i:], "]") assert(i2 >= 0) b.WriteString(name[i+i2+1:]) } + if strings.HasPrefix(b.String(), ".inst..inst.") { + panic(fmt.Sprintf("multiple .inst. prefix in %s", b.String())) + } return fnsym.Pkg.Lookup(b.String()) } diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 08855f518c..7a05230a78 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -958,7 +958,7 @@ func (t *Type) FuncArgs() *Type { return t.Extra.(FuncArgs).T } -// IsFuncArgStruct reports whether t is a struct representing function parameters. +// IsFuncArgStruct reports whether t is a struct representing function parameters or results. func (t *Type) IsFuncArgStruct() bool { return t.kind == TSTRUCT && t.Extra.(*Struct).Funarg != FunargNone } diff --git a/src/runtime/internal/atomic/atomic_arm64.go b/src/runtime/internal/atomic/atomic_arm64.go index 3c8736997f..dbb1796ec0 100644 --- a/src/runtime/internal/atomic/atomic_arm64.go +++ b/src/runtime/internal/atomic/atomic_arm64.go @@ -8,8 +8,8 @@ package atomic import ( - "unsafe" "internal/cpu" + "unsafe" ) const ( diff --git a/test/typeparam/dictionaryCapture.go b/test/typeparam/dictionaryCapture.go new file mode 100644 index 0000000000..9ce7c540ca --- /dev/null +++ b/test/typeparam/dictionaryCapture.go @@ -0,0 +1,100 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test situations where functions/methods are not +// immediately called and we need to capture the dictionary +// required for later invocation. + +// TODO: copy this test file, add -l to gcflags. + +package main + +func main() { + functions() + methodExpressions() + methodValues() + interfaceMethods() +} + +func g0[T any](x T) { +} +func g1[T any](x T) T { + return x +} +func g2[T any](x T) (T, T) { + return x, x +} + +func functions() { + f0 := g0[int] + f0(7) + f1 := g1[int] + is7(f1(7)) + f2 := g2[int] + is77(f2(7)) +} + +func is7(x int) { + if x != 7 { + println(x) + panic("assertion failed") + } +} +func is77(x, y int) { + if x != 7 || y != 7 { + println(x,y) + panic("assertion failed") + } +} + +type s[T any] struct { + a T +} + +func (x s[T]) g0() { +} +func (x s[T]) g1() T { + return x.a +} +func (x s[T]) g2() (T, T) { + return x.a, x.a +} + +func methodExpressions() { + x := s[int]{a:7} + f0 := s[int].g0 + f0(x) + f1 := s[int].g1 + is7(f1(x)) + f2 := s[int].g2 + is77(f2(x)) +} + +func methodValues() { + x := s[int]{a:7} + f0 := x.g0 + f0() + f1 := x.g1 + is7(f1()) + f2 := x.g2 + is77(f2()) +} + +var x interface{ + g0() + g1()int + g2()(int,int) +} = s[int]{a:7} +var y interface{} = s[int]{a:7} + +func interfaceMethods() { + x.g0() + is7(x.g1()) + is77(x.g2()) + y.(interface{g0()}).g0() + is7(y.(interface{g1()int}).g1()) + is77(y.(interface{g2()(int,int)}).g2()) +} -- GitLab From 589e32dbdf89484d620c635a966c736085cae5c4 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 25 May 2021 17:49:32 -0700 Subject: [PATCH 0173/2500] [dev.typeparams] cmd/compile/internal/types2: replace Sum type with Union type - We still mostly ignore the tilde information. - More consistent naming: A Union term is the pair (type, tilde). Rename Union.terms to Union.types; the Union.types and Union.tilde slices make up the Union terms. - Replace Sum.is with Union.underIs: underIs iterates through all union terms and calls its argument function with the underlying type of the term (and thus can ignore the tilde information). This also eliminates the need to call under in the argument function. - Added Union.is for situations where we need to consider the tilde information for each Union term. Change-Id: I70fcf1813e072651dc0f61d52d5555642ee762fd Reviewed-on: https://go-review.googlesource.com/c/go/+/323274 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/builtins.go | 16 ++- src/cmd/compile/internal/types2/expr.go | 4 +- src/cmd/compile/internal/types2/index.go | 18 +-- src/cmd/compile/internal/types2/infer.go | 5 +- src/cmd/compile/internal/types2/interface.go | 51 ++------ src/cmd/compile/internal/types2/operand.go | 19 ++- src/cmd/compile/internal/types2/predicates.go | 35 +++--- src/cmd/compile/internal/types2/sanitize.go | 5 +- .../compile/internal/types2/sizeof_test.go | 1 - src/cmd/compile/internal/types2/sizes.go | 4 +- src/cmd/compile/internal/types2/stmt.go | 6 +- src/cmd/compile/internal/types2/subst.go | 18 +-- src/cmd/compile/internal/types2/type.go | 72 +++--------- src/cmd/compile/internal/types2/typestring.go | 5 +- src/cmd/compile/internal/types2/unify.go | 7 +- src/cmd/compile/internal/types2/union.go | 111 +++++++++++++++--- 16 files changed, 187 insertions(+), 190 deletions(-) diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 94fb506d80..1779e32c5c 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -178,9 +178,9 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( mode = value } - case *Sum: - if t.is(func(t Type) bool { - switch t := under(t).(type) { + case *Union: + if t.underIs(func(t Type) bool { + switch t := t.(type) { case *Basic: if isString(t) && id == _Len { return true @@ -460,8 +460,8 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( m = 2 case *Map, *Chan: m = 1 - case *Sum: - return t.is(valid) + case *Union: + return t.underIs(valid) default: return false } @@ -749,10 +749,14 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { if tp := asTypeParam(x); tp != nil { // Test if t satisfies the requirements for the argument // type and collect possible result types at the same time. + // TODO(gri) This needs to consider the ~ information if we + // have a union type. var rtypes []Type + var tilde []bool if !tp.Bound().is(func(x Type) bool { if r := f(x); r != nil { rtypes = append(rtypes, r) + tilde = append(tilde, true) // for now - see TODO above return true } return false @@ -768,7 +772,7 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { // construct a suitable new type parameter tpar := NewTypeName(nopos, nil /* = Universe pkg */, "", nil) ptyp := check.NewTypeParam(tpar, 0, &emptyInterface) // assigns type to tpar as a side-effect - tsum := NewSum(rtypes) + tsum := newUnion(rtypes, tilde) ptyp.bound = &Interface{allMethods: markComplete, allTypes: tsum} return ptyp diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 23b79656bb..b223387f18 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -723,8 +723,8 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const default: return nil, nil, _InvalidUntypedConversion } - case *Sum: - ok := t.is(func(t Type) bool { + case *Union: + ok := t.underIs(func(t Type) bool { target, _, _ := check.implicitTypeAndValue(x, t) return target != nil }) diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index 33e79aac3e..47e0853a3b 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -91,15 +91,15 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo x.expr = e return - case *Sum: - // A sum type can be indexed if all of the sum's types + case *Union: + // A union type can be indexed if all of the union's terms // support indexing and have the same index and element - // type. Special rules apply for maps in the sum type. + // type. Special rules apply for maps in the union type. var tkey, telem Type // key is for map types only - nmaps := 0 // number of map types in sum type - if typ.is(func(t Type) bool { + nmaps := 0 // number of map types in union type + if typ.underIs(func(t Type) bool { var e Type - switch t := under(t).(type) { + switch t := t.(type) { case *Basic: if isString(t) { e = universeByte @@ -113,7 +113,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo case *Slice: e = t.elem case *Map: - // If there are multiple maps in the sum type, + // If there are multiple maps in the union type, // they must have identical key types. // TODO(gri) We may be able to relax this rule // but it becomes complicated very quickly. @@ -148,7 +148,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo // ok to continue even if indexing failed - map element type is known // If there are only maps, we are done. - if nmaps == len(typ.types) { + if nmaps == typ.NumTerms() { x.mode = mapindex x.typ = telem x.expr = e @@ -246,7 +246,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { valid = true // x.typ doesn't change - case *Sum, *TypeParam: + case *Union, *TypeParam: check.error(x, "generic slice expressions not yet implemented") x.mode = invalid return diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index d8865784a5..73ea8330d4 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -307,7 +307,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { } } - case *Sum: + case *Union: return w.isParameterizedList(t.types) case *Signature: @@ -320,9 +320,6 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { // Thus, we only need to look at the input and result parameters. return w.isParameterized(t.params) || w.isParameterized(t.results) - case *Union: - unimplemented() - case *Interface: if t.allMethods != nil { // interface is complete - quick test diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index d590066ad6..db34d0705f 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -242,23 +242,26 @@ func completeInterface(check *Checker, pos syntax.Pos, ityp *Interface) { } types = t.allTypes case *Union: - types = NewSum(t.terms) - // TODO(gri) don't ignore tilde information + // TODO(gri) combine with default case once we have + // converted all tests to new notation and we + // can report an error when we don't have an + // interface before go1.18. + types = typ case *TypeParam: if check != nil && !check.allowVersion(check.pkg, 1, 18) { check.errorf(pos, "%s is a type parameter, not an interface", typ) continue } - types = t + types = typ default: - if t == Typ[Invalid] { + if typ == Typ[Invalid] { continue } if check != nil && !check.allowVersion(check.pkg, 1, 18) { check.errorf(pos, "%s is not an interface", typ) continue } - types = t + types = typ } allTypes = intersect(allTypes, types) } @@ -279,44 +282,6 @@ func completeInterface(check *Checker, pos syntax.Pos, ityp *Interface) { ityp.allTypes = allTypes } -// intersect computes the intersection of the types x and y. -// Note: An incomming nil type stands for the top type. A top -// type result is returned as nil. -func intersect(x, y Type) (r Type) { - defer func() { - if r == theTop { - r = nil - } - }() - - switch { - case x == theBottom || y == theBottom: - return theBottom - case x == nil || x == theTop: - return y - case y == nil || x == theTop: - return x - } - - xtypes := unpack(x) - ytypes := unpack(y) - // Compute the list rtypes which includes only - // types that are in both xtypes and ytypes. - // Quadratic algorithm, but good enough for now. - // TODO(gri) fix this - var rtypes []Type - for _, x := range xtypes { - if includes(ytypes, x) { - rtypes = append(rtypes, x) - } - } - - if rtypes == nil { - return theBottom - } - return NewSum(rtypes) -} - func sortTypes(list []Type) { sort.Stable(byUniqueTypeName(list)) } diff --git a/src/cmd/compile/internal/types2/operand.go b/src/cmd/compile/internal/types2/operand.go index 455d8b5dd1..fdc6ec52aa 100644 --- a/src/cmd/compile/internal/types2/operand.go +++ b/src/cmd/compile/internal/types2/operand.go @@ -248,6 +248,12 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er V := x.typ + const debugAssignableTo = false + if debugAssignableTo && check != nil { + check.dump("V = %s", V) + check.dump("T = %s", T) + } + // x's type is identical to T if check.identical(V, T) { return true, 0 @@ -256,11 +262,20 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er Vu := optype(V) Tu := optype(T) + if debugAssignableTo && check != nil { + check.dump("Vu = %s", Vu) + check.dump("Tu = %s", Tu) + } + // x is an untyped value representable by a value of type T. if isUntyped(Vu) { - if t, ok := Tu.(*Sum); ok { - return t.is(func(t Type) bool { + if t, ok := Tu.(*Union); ok { + return t.is(func(t Type, tilde bool) bool { // TODO(gri) this could probably be more efficient + if tilde { + // TODO(gri) We need to check assignability + // for the underlying type of x. + } ok, _ := x.assignableTo(check, t, reason) return ok }), _IncompatibleAssign diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index ab0a457276..bcb3e221d0 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -28,8 +28,8 @@ func is(typ Type, what BasicInfo) bool { switch t := optype(typ).(type) { case *Basic: return t.info&what != 0 - case *Sum: - return t.is(func(typ Type) bool { return is(typ, what) }) + case *Union: + return t.underIs(func(t Type) bool { return is(t, what) }) } return false } @@ -124,11 +124,10 @@ func comparable(T Type, seen map[Type]bool) bool { return true case *Array: return comparable(t.elem, seen) - case *Sum: - pred := func(t Type) bool { + case *Union: + return t.underIs(func(t Type) bool { return comparable(t, seen) - } - return t.is(pred) + }) case *TypeParam: return t.Bound().IsComparable() } @@ -142,8 +141,8 @@ func hasNil(typ Type) bool { return t.kind == UnsafePointer case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan: return true - case *Sum: - return t.is(hasNil) + case *Union: + return t.underIs(hasNil) } return false } @@ -261,21 +260,20 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { check.identical0(x.results, y.results, cmpTags, p) } - case *Sum: - // Two sum types are identical if they contain the same types. - // (Sum types always consist of at least two types. Also, the - // the set (list) of types in a sum type consists of unique - // types - each type appears exactly once. Thus, two sum types + case *Union: + // Two union types are identical if they contain the same terms. + // The set (list) of types in a union type consists of unique + // types - each type appears exactly once. Thus, two union types // must contain the same number of types to have chance of // being equal. - if y, ok := y.(*Sum); ok && len(x.types) == len(y.types) { + if y, ok := y.(*Union); ok && x.NumTerms() == y.NumTerms() { // Every type in x.types must be in y.types. // Quadratic algorithm, but probably good enough for now. // TODO(gri) we need a fast quick type ID/hash for all types. L: - for _, x := range x.types { - for _, y := range y.types { - if Identical(x, y) { + for i, xt := range x.types { + for j, yt := range y.types { + if Identical(xt, yt) && x.tilde[i] == y.tilde[j] { continue L // x is in y.types } } @@ -284,9 +282,6 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { return true } - case *Union: - unimplemented() - case *Interface: // Two interface types are identical if they have the same set of methods with // the same names and identical function types. Lower-case method names from diff --git a/src/cmd/compile/internal/types2/sanitize.go b/src/cmd/compile/internal/types2/sanitize.go index c30febfda8..ce26bab186 100644 --- a/src/cmd/compile/internal/types2/sanitize.go +++ b/src/cmd/compile/internal/types2/sanitize.go @@ -106,11 +106,8 @@ func (s sanitizer) typ(typ Type) Type { s.tuple(t.params) s.tuple(t.results) - case *Sum: - s.typeList(t.types) - case *Union: - s.typeList(t.terms) + s.typeList(t.types) case *Interface: s.funcList(t.methods) diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go index 552f3488cd..d3c391161e 100644 --- a/src/cmd/compile/internal/types2/sizeof_test.go +++ b/src/cmd/compile/internal/types2/sizeof_test.go @@ -27,7 +27,6 @@ func TestSizeof(t *testing.T) { {Pointer{}, 8, 16}, {Tuple{}, 12, 24}, {Signature{}, 44, 88}, - {Sum{}, 12, 24}, {Union{}, 24, 48}, {Interface{}, 52, 104}, {Map{}, 16, 32}, diff --git a/src/cmd/compile/internal/types2/sizes.go b/src/cmd/compile/internal/types2/sizes.go index c6b807cd06..cb789598e5 100644 --- a/src/cmd/compile/internal/types2/sizes.go +++ b/src/cmd/compile/internal/types2/sizes.go @@ -148,10 +148,8 @@ func (s *StdSizes) Sizeof(T Type) int64 { } offsets := s.Offsetsof(t.fields) return offsets[n-1] + s.Sizeof(t.fields[n-1].typ) - case *Sum: - panic("Sizeof unimplemented for type sum") case *Union: - unimplemented() + panic("Sizeof unimplemented for union") case *Interface: return s.WordSize * 2 } diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index c3e646c80c..e9ffd4f5ca 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -912,12 +912,12 @@ func rangeKeyVal(typ Type, wantKey, wantVal bool) (Type, Type, string) { msg = "receive from send-only channel" } return typ.elem, Typ[Invalid], msg - case *Sum: + case *Union: first := true var key, val Type var msg string - typ.is(func(t Type) bool { - k, v, m := rangeKeyVal(under(t), wantKey, wantVal) + typ.underIs(func(t Type) bool { + k, v, m := rangeKeyVal(t, wantKey, wantVal) if k == nil || m != "" { key, val, msg = k, v, m return false diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index a2b81ba0cc..bfec61a065 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -298,21 +298,13 @@ func (subst *subster) typ(typ Type) Type { } } - case *Sum: - types, copied := subst.typeList(t.types) - if copied { - // Don't do it manually, with a Sum literal: the new - // types list may not be unique and NewSum may remove - // duplicates. - return NewSum(types) - } - case *Union: - terms, copied := subst.typeList(t.terms) + types, copied := subst.typeList(t.types) if copied { - // TODO(gri) Do we need to remove duplicates that may have - // crept in after substitution? It may not matter. - return newUnion(terms, t.tilde) + // TODO(gri) Remove duplicates that may have crept in after substitution + // (unlikely but possible). This matters for the Identical + // predicate on unions. + return newUnion(types, t.tilde) } case *Interface: diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 3b2a5960e8..aab75811b8 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -261,53 +261,6 @@ func (s *Signature) Results() *Tuple { return s.results } // Variadic reports whether the signature s is variadic. func (s *Signature) Variadic() bool { return s.variadic } -// A Sum represents a set of possible types. -// Sums are currently used to represent type lists of interfaces -// and thus the underlying types of type parameters; they are not -// first class types of Go. -type Sum struct { - types []Type // types are unique -} - -// NewSum returns a new Sum type consisting of the provided -// types if there are more than one. If there is exactly one -// type, it returns that type. If the list of types is empty -// the result is nil. -func NewSum(types []Type) Type { - if len(types) == 0 { - return nil - } - - // What should happen if types contains a sum type? - // Do we flatten the types list? For now we check - // and panic. This should not be possible for the - // current use case of type lists. - // TODO(gri) Come up with the rules for sum types. - for _, t := range types { - if _, ok := t.(*Sum); ok { - panic("sum type contains sum type - unimplemented") - } - } - - if len(types) == 1 { - return types[0] - } - return &Sum{types: types} -} - -// is reports whether all types in t satisfy pred. -func (s *Sum) is(pred func(Type) bool) bool { - if s == nil { - return false - } - for _, t := range s.types { - if !pred(t) { - return false - } - } - return true -} - // An Interface represents an interface type. type Interface struct { methods []*Func // ordered list of explicitly declared methods @@ -325,8 +278,8 @@ func unpack(typ Type) []Type { if typ == nil { return nil } - if sum := asSum(typ); sum != nil { - return sum.types + if u := asUnion(typ); u != nil { + return u.types } return []Type{typ} } @@ -716,9 +669,16 @@ func optype(typ Type) Type { // for a type parameter list of the form: // (type T interface { type T }). // See also issue #39680. - if u := t.Bound().allTypes; u != nil && u != typ { - // u != typ and u is a type parameter => under(u) != typ, so this is ok - return under(u) + if a := t.Bound().allTypes; a != nil { + // If we have a union with a single entry, ignore + // any tilde because under(~t) == under(t). + if u, _ := a.(*Union); u != nil && u.NumTerms() == 1 { + a = u.types[0] + } + if a != typ { + // a != typ and a is a type parameter => under(a) != typ, so this is ok + return under(a) + } } return theTop } @@ -800,7 +760,6 @@ func (t *Struct) Underlying() Type { return t } func (t *Pointer) Underlying() Type { return t } func (t *Tuple) Underlying() Type { return t } func (t *Signature) Underlying() Type { return t } -func (t *Sum) Underlying() Type { return t } func (t *Interface) Underlying() Type { return t } func (t *Map) Underlying() Type { return t } func (t *Chan) Underlying() Type { return t } @@ -818,7 +777,6 @@ func (t *Struct) String() string { return TypeString(t, nil) } func (t *Pointer) String() string { return TypeString(t, nil) } func (t *Tuple) String() string { return TypeString(t, nil) } func (t *Signature) String() string { return TypeString(t, nil) } -func (t *Sum) String() string { return TypeString(t, nil) } func (t *Interface) String() string { return TypeString(t, nil) } func (t *Map) String() string { return TypeString(t, nil) } func (t *Chan) String() string { return TypeString(t, nil) } @@ -833,7 +791,7 @@ func (t *top) String() string { return TypeString(t, nil) } // under must only be called when a type is known // to be fully set up. func under(t Type) Type { - // TODO(gri) is this correct for *Sum? + // TODO(gri) is this correct for *Union? if n := asNamed(t); n != nil { return n.under() } @@ -880,8 +838,8 @@ func asSignature(t Type) *Signature { return op } -func asSum(t Type) *Sum { - op, _ := optype(t).(*Sum) +func asUnion(t Type) *Union { + op, _ := optype(t).(*Union) return op } diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 55858b7b42..466beb2398 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -157,11 +157,8 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { buf.WriteString("func") writeSignature(buf, t, qf, visited) - case *Sum: - writeTypeList(buf, t.types, qf, visited) - case *Union: - for i, e := range t.terms { + for i, e := range t.types { if i > 0 { buf.WriteString("|") } diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index f1630b75d0..e5983dd40c 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -352,12 +352,9 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { u.nify(x.results, y.results, p) } - case *Sum: - // This should not happen with the current internal use of sum types. - panic("type inference across sum types not implemented") - case *Union: - unimplemented() + // This should not happen with the current internal use of union types. + panic("type inference across union types not implemented") case *Interface: // Two interface types are identical if they have the same set of methods with diff --git a/src/cmd/compile/internal/types2/union.go b/src/cmd/compile/internal/types2/union.go index 70dc3bc360..a5ef721ee6 100644 --- a/src/cmd/compile/internal/types2/union.go +++ b/src/cmd/compile/internal/types2/union.go @@ -10,16 +10,16 @@ import "cmd/compile/internal/syntax" // API // A Union represents a union of terms. -// A term is a type, possibly with a ~ (tilde) indication. +// A term is a type with a ~ (tilde) flag. type Union struct { - terms []Type // terms are unique + types []Type // types are unique tilde []bool // if tilde[i] is set, terms[i] is of the form ~T } -func NewUnion(terms []Type, tilde []bool) Type { return newUnion(terms, tilde) } +func NewUnion(types []Type, tilde []bool) Type { return newUnion(types, tilde) } -func (u *Union) NumTerms() int { return len(u.terms) } -func (u *Union) Term(i int) (Type, bool) { return u.terms[i], u.tilde[i] } +func (u *Union) NumTerms() int { return len(u.types) } +func (u *Union) Term(i int) (Type, bool) { return u.types[i], u.tilde[i] } func (u *Union) Underlying() Type { return u } func (u *Union) String() string { return TypeString(u, nil) } @@ -27,26 +27,52 @@ func (u *Union) String() string { return TypeString(u, nil) } // ---------------------------------------------------------------------------- // Implementation -func newUnion(terms []Type, tilde []bool) Type { - assert(len(terms) == len(tilde)) - if terms == nil { +func newUnion(types []Type, tilde []bool) Type { + assert(len(types) == len(tilde)) + if types == nil { return nil } t := new(Union) - t.terms = terms + t.types = types t.tilde = tilde return t } +// is reports whether f returned true for all terms (type, tilde) of u. +func (u *Union) is(f func(Type, bool) bool) bool { + if u == nil { + return false + } + for i, t := range u.types { + if !f(t, u.tilde[i]) { + return false + } + } + return true +} + +// is reports whether f returned true for the underlying types of all terms of u. +func (u *Union) underIs(f func(Type) bool) bool { + if u == nil { + return false + } + for _, t := range u.types { + if !f(under(t)) { + return false + } + } + return true +} + func parseUnion(check *Checker, tlist []syntax.Expr) Type { - var terms []Type + var types []Type var tilde []bool for _, x := range tlist { t, d := parseTilde(check, x) if len(tlist) == 1 && !d { return t // single type } - terms = append(terms, t) + types = append(types, t) tilde = append(tilde, d) } @@ -55,7 +81,7 @@ func parseUnion(check *Checker, tlist []syntax.Expr) Type { // for correctness of the code. // Note: This is a quadratic algorithm, but unions tend to be short. check.later(func() { - for i, t := range terms { + for i, t := range types { t := expand(t) if t == Typ[Invalid] { continue @@ -85,14 +111,14 @@ func parseUnion(check *Checker, tlist []syntax.Expr) Type { } // Complain about duplicate entries a|a, but also a|~a, and ~a|~a. - if includes(terms[:i], t) { + if includes(types[:i], t) { // TODO(gri) this currently doesn't print the ~ if present check.softErrorf(pos, "duplicate term %s in union element", t) } } }) - return newUnion(terms, tilde) + return newUnion(types, tilde) } func parseTilde(check *Checker, x syntax.Expr) (Type, bool) { @@ -103,3 +129,60 @@ func parseTilde(check *Checker, x syntax.Expr) (Type, bool) { } return check.anyType(x), tilde } + +// intersect computes the intersection of the types x and y. +// Note: An incomming nil type stands for the top type. A top +// type result is returned as nil. +func intersect(x, y Type) (r Type) { + defer func() { + if r == theTop { + r = nil + } + }() + + switch { + case x == theBottom || y == theBottom: + return theBottom + case x == nil || x == theTop: + return y + case y == nil || x == theTop: + return x + } + + // Compute the terms which are in both x and y. + xu, _ := x.(*Union) + yu, _ := y.(*Union) + switch { + case xu != nil && yu != nil: + // Quadratic algorithm, but good enough for now. + // TODO(gri) fix asymptotic performance + var types []Type + var tilde []bool + for _, y := range yu.types { + if includes(xu.types, y) { + types = append(types, y) + tilde = append(tilde, true) // TODO(gri) fix this + } + } + if types != nil { + return newUnion(types, tilde) + } + + case xu != nil: + if includes(xu.types, y) { + return y + } + + case yu != nil: + if includes(yu.types, x) { + return x + } + + default: // xu == nil && yu == nil + if Identical(x, y) { + return x + } + } + + return theBottom +} -- GitLab From 8c5c5a9e6983c00d63f3216976f102d79065a180 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 1 Jun 2021 22:48:20 -0700 Subject: [PATCH 0174/2500] [dev.typeparams] cmd/compile/internal/importer: review of support.go This CL removes the // UNREVIEWED disclaimer at the top of the file. This file is essentially a copy of its reviewed version at src/go/internal/gcimporter/support.go with adjustments to make it work for the compiler and types2. To see the changes made with respect to the original, compare patchset 1 against patchset 2. Change-Id: Icb8e7e7cac02751265c1020431018293826bad18 Reviewed-on: https://go-review.googlesource.com/c/go/+/324130 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/importer/support.go | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cmd/compile/internal/importer/support.go b/src/cmd/compile/internal/importer/support.go index 40b9c7c958..3d1f77afcd 100644 --- a/src/cmd/compile/internal/importer/support.go +++ b/src/cmd/compile/internal/importer/support.go @@ -1,4 +1,3 @@ -// UNREVIEWED // Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -- GitLab From cc52fdd1f3ec9ee24c0a0d6223ac934672c9569c Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 1 Jun 2021 23:05:25 -0700 Subject: [PATCH 0175/2500] [dev.typeparams] cmd/compile/internal/importer: review of exportdata.go This CL removes the // UNREVIEWED disclaimer at the top of the file. This file is essentially a copy of its reviewed version at src/go/internal/gcimporter/exportdata.go with adjustments to make it work for the compiler and types2. To see the changes made with respect to the original, compare patchset 1 against patchset 2. Change-Id: I276d898ef238afa37ec6b9605496407df36cf7d0 Reviewed-on: https://go-review.googlesource.com/c/go/+/324133 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/importer/exportdata.go | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cmd/compile/internal/importer/exportdata.go b/src/cmd/compile/internal/importer/exportdata.go index 3925a64314..6a672be9c1 100644 --- a/src/cmd/compile/internal/importer/exportdata.go +++ b/src/cmd/compile/internal/importer/exportdata.go @@ -1,4 +1,3 @@ -// UNREVIEWED // Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -- GitLab From a3b5084204a69e441fa1cc4162a14d93c3507d54 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 1 Jun 2021 12:49:50 -0400 Subject: [PATCH 0176/2500] [dev.fuzz] cmd/go: split test_fuzz_minimize from test_fuzz_mutator This CL moves test cases for minimization into a new script. The tests are changed to be more deterministic. Any non-zero byte now triggers a failure. Change-Id: Id45a721071dbfc3aec46be369966b0a67a745c55 Reviewed-on: https://go-review.googlesource.com/c/go/+/323851 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod Reviewed-by: Katie Hockman TryBot-Result: Go Bot --- .../go/testdata/script/test_fuzz_minimize.txt | 159 ++++++++++++++++++ .../go/testdata/script/test_fuzz_mutator.txt | 150 +---------------- 2 files changed, 162 insertions(+), 147 deletions(-) create mode 100644 src/cmd/go/testdata/script/test_fuzz_minimize.txt diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize.txt b/src/cmd/go/testdata/script/test_fuzz_minimize.txt new file mode 100644 index 0000000000..7652759668 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_minimize.txt @@ -0,0 +1,159 @@ +# TODO(jayconrod): support shared memory on more platforms. +[!darwin] [!linux] [!windows] skip + +[short] skip + +# We clean the fuzz cache during this test. Don't clean the user's cache. +env GOCACHE=$WORK/gocache + +# TODO(b/181800488): remove -parallel=1, here and below. For now, when a +# crash is found, all workers keep running, wasting resources and reducing +# the number of executions available to the minimizer, increasing flakiness. + +# Test that minimization is working for recoverable errors. +! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=100x -fuzzminimizetime=10000x -parallel=1 minimizer_test.go +! stdout '^ok' +stdout 'got the minimum size!' +stdout 'contains a non-zero byte' +stdout FAIL + +# Check that the bytes written to testdata are of length 50 (the minimum size) +go run check_testdata.go FuzzMinimizerRecoverable 50 + +# Test that re-running the minimized value causes a crash. +! go test -run=FuzzMinimizerRecoverable minimizer_test.go +rm testdata + +# Test that minimization is working for non-recoverable errors. +! go test -fuzz=FuzzMinimizerNonrecoverable -run=FuzzMinimizerNonrecoverable -fuzztime=100x -fuzzminimizetime=10000x -parallel=1 minimizer_test.go +! stdout '^ok' +# TODO(jayconrod): fix in CL 321835. +stdout 'found a crash, minimizing' +# stdout 'fuzzing process terminated unexpectedly while minimizing: exit status 99' +stdout FAIL + +# Check that re-running the value causes a crash. +! go test -run=FuzzMinimizerNonrecoverable minimizer_test.go +rm testdata + +# Clear the fuzzing cache. There may already be minimized inputs that would +# interfere with the next stage of the test. +go clean -fuzzcache + +# Test that minimization can be cancelled by fuzzminimizetime and the latest +# crash will still be logged and written to testdata. +! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -parallel=1 -fuzztime=100x -fuzzminimizetime=1x minimizer_test.go +! stdout '^ok' +stdout 'testdata[/\\]corpus[/\\]FuzzMinimizerRecoverable[/\\]' +# TODO(jayconrod): implement -fuzzminimizetime in 321835. +# ! stdout 'got the minimum size!' # it shouldn't have had enough time to minimize it +stdout FAIL + +# Test that re-running the unminimized value causes a crash. +! go test -run=FuzzMinimizerRecoverable minimizer_test.go + +# TODO(jayconrod,katiehockman): add a test which verifies that the right bytes +# are written to testdata in the case of an interrupt during minimization. + +-- go.mod -- +module m + +go 1.16 +-- minimizer_test.go -- +package fuzz_test + +import ( + "os" + "testing" +) + +func FuzzMinimizerRecoverable(f *testing.F) { + f.Add(make([]byte, 100)) + f.Fuzz(func(t *testing.T, b []byte) { + if len(b) < 50 { + // Make sure that b is large enough that it can be minimized + return + } + // Given the randomness of the mutations, this should allow the + // minimizer to trim down the value a bit. + for _, n := range b { + if n != 0 { + if len(b) == 50 { + t.Log("got the minimum size!") + } + t.Fatal("contains a non-zero byte") + } + } + }) +} + +func FuzzMinimizerNonrecoverable(f *testing.F) { + f.Add(make([]byte, 100)) + f.Fuzz(func(t *testing.T, b []byte) { + if len(b) < 50 { + // Make sure that b is large enough that it can be minimized + return + } + // Given the randomness of the mutations, this should allow the + // minimizer to trim down the value a bit. + for _, n := range b { + if n != 0 { + t.Log("contains a non-zero byte") + os.Exit(99) + } + } + }) +} +-- check_testdata.go -- +// +build ignore + +package main + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strconv" +) + +func main() { + target := os.Args[1] + numBytes, err := strconv.Atoi(os.Args[2]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + + // Open the file in testdata (there should only be one) + dir := fmt.Sprintf("testdata/corpus/%s", target) + files, err := ioutil.ReadDir(dir) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + if len(files) != 1 { + fmt.Fprintf(os.Stderr, "expected one file, got %d", len(files)) + os.Exit(1) + } + got, err := ioutil.ReadFile(filepath.Join(dir, files[0].Name())) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + + // Make sure that there were exactly 100 bytes written to the corpus entry + prefix := []byte("[]byte(") + i := bytes.Index(got, prefix) + gotBytes := got[i+len(prefix) : len(got)-1] + s, err := strconv.Unquote(string(gotBytes)) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + if want, got := numBytes, len(s); want != got { + fmt.Fprintf(os.Stderr, "want %d bytes, got %d\n", want, got) + os.Exit(1) + } +} diff --git a/src/cmd/go/testdata/script/test_fuzz_mutator.txt b/src/cmd/go/testdata/script/test_fuzz_mutator.txt index 1d0c399a6c..fb7984c662 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutator.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutator.txt @@ -10,11 +10,12 @@ [short] skip +go test -fuzz=FuzzA -fuzztime=100x -parallel=1 -log=fuzz +go run check_logs.go fuzz fuzz.worker + # TODO(b/181800488): remove -parallel=1, here and below. For now, when a # crash is found, all workers keep running, wasting resources and reducing # the number of executions available to the minimizer, increasing flakiness. -go test -fuzz=FuzzA -fuzztime=100x -parallel=1 -log=fuzz -go run check_logs.go fuzz fuzz.worker # Test that the mutator is good enough to find several unique mutations. ! go test -fuzz=FuzzMutator -parallel=1 -fuzztime=100x mutator_test.go @@ -22,41 +23,6 @@ go run check_logs.go fuzz fuzz.worker stdout FAIL stdout 'mutator found enough unique mutations' -# Test that minimization is working for recoverable errors. -! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=100x -fuzzminimizetime=10000x -parallel=1 minimizer_test.go -! stdout '^ok' -stdout 'got the minimum size!' -stdout 'contains a letter' -stdout FAIL - -# Check that the bytes written to testdata are of length 50 (the minimum size) -go run check_testdata.go FuzzMinimizerRecoverable 50 - -# Test that re-running the minimized value causes a crash. -! go test -run=FuzzMinimizerRecoverable minimizer_test.go - -# Test that minimization is working for non-recoverable errors. -! go test -fuzz=FuzzMinimizerNonrecoverable -run=FuzzMinimizerNonrecoverable -fuzztime=100x -fuzzminimizetime=10000x -parallel=1 minimizer_test.go -! stdout '^ok' -stdout 'got the minimum size!' -stdout 'contains a letter' -stdout FAIL - -# Check that the bytes written to testdata are of length 50 (the minimum size) -go run check_testdata.go FuzzMinimizerNonrecoverable 50 - -# Test that minimization can be cancelled by fuzzminimizetime and the latest -# crash will still be logged and written to testdata. -! go test -fuzz=FuzzNonMinimizable -run=FuzzNonMinimizable -parallel=1 -fuzztime=100x -fuzzminimizetime=1x minimizer_test.go -! stdout '^ok' -stdout 'testdata[/\\]corpus[/\\]FuzzNonMinimizable[/\\]' -! stdout 'got the minimum size!' # it shouldn't have had enough time to minimize it -stdout 'at least 20 bytes' -stdout FAIL - -# TODO(jayconrod,katiehockman): add a test which verifies that the right bytes -# are written to testdata in the case of an interrupt during minimization. - -- go.mod -- module m @@ -105,63 +71,6 @@ func FuzzB(f *testing.F) { }) } --- minimizer_test.go -- -package fuzz_test - -import ( - "bytes" - "fmt" - "os" - "testing" -) - -func FuzzMinimizerRecoverable(f *testing.F) { - f.Fuzz(func(t *testing.T, b []byte) { - if len(b) < 50 { - // Make sure that b is large enough that it can be minimized - return - } - // Given the randomness of the mutations, this should allow the - // minimizer to trim down the value a bit. - if bytes.ContainsAny(b, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") { - if len(b) == 50 { - fmt.Fprint(os.Stderr, "got the minimum size!\n") - } - t.Error("contains a letter") - } - }) -} - -func FuzzMinimizerNonrecoverable(f *testing.F) { - f.Fuzz(func(t *testing.T, b []byte) { - if len(b) < 50 { - // Make sure that b is large enough that it can be minimized - return - } - // Given the randomness of the mutations, this should allow the - // minimizer to trim down the value quite a bit. - if bytes.ContainsAny(b, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") { - if len(b) == 50 { - fmt.Fprint(os.Stderr, "got the minimum size!\n") - } - panic("contains a letter") - } - }) -} - -func FuzzNonMinimizable(f *testing.F) { - f.Fuzz(func(t *testing.T, b []byte) { - if len(b) < 20 { - // Make sure that b is large enough that minimization will try to run. - return - } - panic("at least 20 bytes") - if len(b) == 20 { - fmt.Fprint(os.Stderr, "got the minimum size!\n") - } - }) -} - -- check_logs.go -- // +build ignore @@ -255,59 +164,6 @@ func checkWorkerLog(r io.Reader) error { } return nil } --- check_testdata.go -- -// +build ignore - -package main - -import ( - "bytes" - "fmt" - "io/ioutil" - "os" - "path/filepath" - "strconv" -) - -func main() { - target := os.Args[1] - numBytes, err := strconv.Atoi(os.Args[2]) - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - - // Open the file in testdata (there should only be one) - dir := fmt.Sprintf("testdata/corpus/%s", target) - files, err := ioutil.ReadDir(dir) - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - if len(files) != 1 { - fmt.Fprintf(os.Stderr, "expected one file, got %d", len(files)) - os.Exit(1) - } - got, err := ioutil.ReadFile(filepath.Join(dir, files[0].Name())) - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - - // Make sure that there were exactly 100 bytes written to the corpus entry - prefix := []byte("[]byte(") - i := bytes.Index(got, prefix) - gotBytes := got[i+len(prefix) : len(got)-1] - s, err := strconv.Unquote(string(gotBytes)) - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - if want, got := numBytes, len(s); want != got { - fmt.Fprintf(os.Stderr, "want %d bytes, got %d\n", want, got) - os.Exit(1) - } -} -- mutator_test.go -- package fuzz_test -- GitLab From bc1fbe204443cc2e32391b79effe9c18f295d0c2 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Fri, 21 May 2021 12:44:26 -0400 Subject: [PATCH 0177/2500] [dev.fuzz] internal/fuzz: notify coordinator for minimization When a worker process finds a crasher, it now sends that result directly to the coordinator without attempting to minimize it first. The coordinator stops sending new inputs and sends the unminimized crasher back to a worker (any worker) for minimization. This prevents wasted work during minimization and will help us implement -keepfuzzing later on. We may also be able to minimize interesting inputs with this approach later. Since panics are recoverable errors (they don't terminate worker processes), we no longer attempt to minimize non-recoverable errors. This didn't work too well before: we lost too much state. Change-Id: Id142c7e91a33f64584170b0d42d22cb1f22a92d7 Reviewed-on: https://go-review.googlesource.com/c/go/+/321835 Trust: Jay Conrod Trust: Katie Hockman Reviewed-by: Katie Hockman --- .../go/testdata/script/test_fuzz_minimize.txt | 16 +- src/internal/fuzz/fuzz.go | 70 ++-- src/internal/fuzz/minimize.go | 17 +- src/internal/fuzz/minimize_test.go | 13 +- src/internal/fuzz/worker.go | 298 +++++++++--------- 5 files changed, 219 insertions(+), 195 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize.txt b/src/cmd/go/testdata/script/test_fuzz_minimize.txt index 7652759668..215ce04dbc 100644 --- a/src/cmd/go/testdata/script/test_fuzz_minimize.txt +++ b/src/cmd/go/testdata/script/test_fuzz_minimize.txt @@ -6,12 +6,8 @@ # We clean the fuzz cache during this test. Don't clean the user's cache. env GOCACHE=$WORK/gocache -# TODO(b/181800488): remove -parallel=1, here and below. For now, when a -# crash is found, all workers keep running, wasting resources and reducing -# the number of executions available to the minimizer, increasing flakiness. - # Test that minimization is working for recoverable errors. -! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=100x -fuzzminimizetime=10000x -parallel=1 minimizer_test.go +! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=100x -fuzzminimizetime=10000x minimizer_test.go ! stdout '^ok' stdout 'got the minimum size!' stdout 'contains a non-zero byte' @@ -25,11 +21,10 @@ go run check_testdata.go FuzzMinimizerRecoverable 50 rm testdata # Test that minimization is working for non-recoverable errors. -! go test -fuzz=FuzzMinimizerNonrecoverable -run=FuzzMinimizerNonrecoverable -fuzztime=100x -fuzzminimizetime=10000x -parallel=1 minimizer_test.go +! go test -fuzz=FuzzMinimizerNonrecoverable -run=FuzzMinimizerNonrecoverable -fuzztime=100x -fuzzminimizetime=10000x minimizer_test.go ! stdout '^ok' -# TODO(jayconrod): fix in CL 321835. stdout 'found a crash, minimizing' -# stdout 'fuzzing process terminated unexpectedly while minimizing: exit status 99' +stdout 'fuzzing process terminated unexpectedly while minimizing: exit status 99' stdout FAIL # Check that re-running the value causes a crash. @@ -42,11 +37,10 @@ go clean -fuzzcache # Test that minimization can be cancelled by fuzzminimizetime and the latest # crash will still be logged and written to testdata. -! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -parallel=1 -fuzztime=100x -fuzzminimizetime=1x minimizer_test.go +! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=100x -fuzzminimizetime=1x minimizer_test.go ! stdout '^ok' stdout 'testdata[/\\]corpus[/\\]FuzzMinimizerRecoverable[/\\]' -# TODO(jayconrod): implement -fuzzminimizetime in 321835. -# ! stdout 'got the minimum size!' # it shouldn't have had enough time to minimize it +! stdout 'got the minimum size!' # it shouldn't have had enough time to minimize it stdout FAIL # Test that re-running the unminimized value causes a crash. diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 553086b20a..4bcfbeec33 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -90,6 +90,13 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err // Don't start more workers than we need. opts.Parallel = int(opts.Limit) } + canMinimize := false + for _, t := range opts.Types { + if isMinimizable(t) { + canMinimize = true + break + } + } c, err := newCoordinator(opts) if err != nil { @@ -168,6 +175,9 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err w := workers[i] go func() { err := w.coordinate(fuzzCtx) + if fuzzCtx.Err() != nil || isInterruptError(err) { + err = nil + } cleanErr := w.cleanup() if err == nil { err = cleanErr @@ -187,6 +197,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err statTicker := time.NewTicker(3 * time.Second) defer statTicker.Stop() defer c.logStats() + crashMinimizing := false crashWritten := false for { @@ -204,21 +215,30 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err } if result.crasherMsg != "" { - // Found a crasher. Write it to testdata and return it. - if crashWritten { - break - } - fileName, err := writeToCorpus(result.entry.Data, opts.CorpusDir) - if err == nil { - crashWritten = true - err = &crashError{ - name: filepath.Base(fileName), - err: errors.New(result.crasherMsg), + if canMinimize && !result.minimized { + // Found a crasher but haven't yet attempted to minimize it. + // Send it back to a worker for minimization. Disable inputC so + // other workers don't continue fuzzing. + if crashMinimizing { + break } + crashMinimizing = true + inputC = nil + fmt.Fprintf(c.opts.Log, "found a crash, minimizing...\n") + c.minimizeC <- result + } else if !crashWritten { + // Found a crasher that's either minimized or not minimizable. + // Write to corpus and stop. + fileName, err := writeToCorpus(result.entry.Data, opts.CorpusDir) + if err == nil { + crashWritten = true + err = &crashError{ + name: filepath.Base(fileName), + err: errors.New(result.crasherMsg), + } + } + stop(err) } - // TODO(jayconrod,katiehockman): if -keepfuzzing, report the error to - // the user and restart the crashed worker. - stop(err) } else if result.coverageData != nil { foundNew := c.updateCoverage(result.coverageData) if foundNew && !c.coverageOnlyRun() { @@ -248,11 +268,11 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err } } } - if inputC == nil && !stopping && !c.coverageOnlyRun() { - // inputC was disabled earlier because we hit the limit on the number - // of inputs to fuzz (nextInput returned false). - // Workers can do less work than requested though, so we might be - // below the limit now. Call nextInput again and re-enable inputC if so. + if inputC == nil && !crashMinimizing && !stopping && !c.coverageOnlyRun() { + // Re-enable inputC if it was disabled earlier because we hit the limit + // on the number of inputs to fuzz (nextInput returned false). Workers + // can do less work than requested, so after receiving a result above, + // we might be below the limit now. if input, ok = c.nextInput(); ok { inputC = c.inputC } @@ -317,6 +337,9 @@ type corpus struct { // packages, but testing can't import this package directly, and we don't want // to export this type from testing. Instead, we use the same struct type and // use a type alias (not a defined type) for convenience. +// +// TODO: split marshalled and unmarshalled types. In most places, we only need +// one or the other. type CorpusEntry = struct { // Name is the name of the corpus file, if the entry was loaded from the // seed corpus. It can be used with -run. For entries added with f.Add and @@ -358,6 +381,10 @@ type fuzzResult struct { // crasherMsg is an error message from a crash. It's "" if no crash was found. crasherMsg string + // minimized is true if a worker attempted to minimize entry. + // Minimization may not have actually been completed. + minimized bool + // coverageData is set if the worker found new coverage. coverageData []byte @@ -382,9 +409,13 @@ type coordinator struct { startTime time.Time // inputC is sent values to fuzz by the coordinator. Any worker may receive - // values from this channel. + // values from this channel. Workers send results to resultC. inputC chan fuzzInput + // minimizeC is sent values to minimize by the coordinator. Any worker may + // receive values from this channel. Workers send results to resultC. + minimizeC chan fuzzResult + // resultC is sent results of fuzzing by workers. The coordinator // receives these. Multiple types of messages are allowed. resultC chan fuzzResult @@ -443,6 +474,7 @@ func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { opts: opts, startTime: time.Now(), inputC: make(chan fuzzInput), + minimizeC: make(chan fuzzResult), resultC: make(chan fuzzResult), corpus: corpus, covOnlyInputs: covOnlyInputs, diff --git a/src/internal/fuzz/minimize.go b/src/internal/fuzz/minimize.go index c5533bd917..5164c34845 100644 --- a/src/internal/fuzz/minimize.go +++ b/src/internal/fuzz/minimize.go @@ -5,11 +5,20 @@ package fuzz import ( - "context" "math" + "reflect" ) -func minimizeBytes(ctx context.Context, v []byte, stillCrashes func(interface{}) bool, shouldStop func() bool) { +func isMinimizable(t reflect.Type) bool { + for _, v := range zeroVals { + if t == reflect.TypeOf(v) { + return true + } + } + return false +} + +func minimizeBytes(v []byte, stillCrashes func(interface{}) bool, shouldStop func() bool) { // First, try to cut the tail. for n := 1024; n != 0; n /= 2 { for len(v) > n { @@ -67,7 +76,7 @@ func minimizeBytes(ctx context.Context, v []byte, stillCrashes func(interface{}) return } -func minimizeInteger(ctx context.Context, v uint, stillCrashes func(interface{}) bool, shouldStop func() bool) { +func minimizeInteger(v uint, stillCrashes func(interface{}) bool, shouldStop func() bool) { // TODO(rolandshoemaker): another approach could be either unsetting/setting all bits // (depending on signed-ness), or rotating bits? When operating on cast signed integers // this would probably be more complex though. @@ -84,7 +93,7 @@ func minimizeInteger(ctx context.Context, v uint, stillCrashes func(interface{}) return } -func minimizeFloat(ctx context.Context, v float64, stillCrashes func(interface{}) bool, shouldStop func() bool) { +func minimizeFloat(v float64, stillCrashes func(interface{}) bool, shouldStop func() bool) { if math.IsNaN(v) { return } diff --git a/src/internal/fuzz/minimize_test.go b/src/internal/fuzz/minimize_test.go index 500ff431b4..d786cf809e 100644 --- a/src/internal/fuzz/minimize_test.go +++ b/src/internal/fuzz/minimize_test.go @@ -190,28 +190,19 @@ func TestMinimizeInput(t *testing.T) { }) } - sm, err := sharedMemTempFile(workerSharedMemSize) - if err != nil { - t.Fatalf("failed to create temporary shared memory file: %s", err) - } - defer sm.Close() - for _, tc := range cases { ws := &workerServer{ fuzzFn: tc.fn, } count := int64(0) - err = ws.minimizeInput(context.Background(), tc.input, sm, &count, 0) + vals := tc.input + err := ws.minimizeInput(context.Background(), vals, &count, 0) if err == nil { t.Error("minimizeInput didn't fail") } if expected := fmt.Sprintf("bad %v", tc.input[0]); err.Error() != expected { t.Errorf("unexpected error: got %s, want %s", err, expected) } - vals, err := unmarshalCorpusFile(sm.valueCopy()) - if err != nil { - t.Fatalf("failed to unmarshal values from shared memory file: %s", err) - } if !reflect.DeepEqual(vals, tc.expected) { t.Errorf("unexpected results: got %v, want %v", vals, tc.expected) } diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 33727a5438..2bfd9fce77 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -70,39 +70,28 @@ func (w *worker) cleanup() error { // coordinate runs the test binary to perform fuzzing. // -// coordinate loops until ctx is cancelled or a fatal error is encountered. While -// looping, coordinate receives inputs from w.coordinator.inputC, then passes -// those on to the worker process. +// coordinate loops until ctx is cancelled or a fatal error is encountered. +// If a test process terminates unexpectedly while fuzzing, coordinate will +// attempt to restart and continue unless the termination can be attributed +// to an interruption (from a timer or the user). +// +// While looping, coordinate receives inputs from the coordinator, passes +// those inputs to the worker process, then passes the results back to +// the coordinator. func (w *worker) coordinate(ctx context.Context) error { - // Start the process. - if err := w.start(); err != nil { - // We couldn't start the worker process. We can't do anything, and it's - // likely that other workers can't either, so don't try to restart. - return err - } - - // Send the worker a message to make sure it can respond. - // Errors that occur before we get a response likely indicate that - // the worker did not call F.Fuzz or called F.Fail first. - // We don't record crashers for these errors. - if err := w.client.ping(ctx); err != nil { - w.stop() - if ctx.Err() != nil { - return ctx.Err() - } - if isInterruptError(err) { - // User may have pressed ^C before worker responded. - return nil - } - return fmt.Errorf("fuzzing process terminated without fuzzing: %w", err) - } - // interestingCount starts at -1, like the coordinator does, so that the // worker client's coverage data is updated after a coverage-only run. interestingCount := int64(-1) // Main event loop. for { + // Start or restart the worker if it's not running. + if !w.isRunning() { + if err := w.startAndPing(ctx); err != nil { + return err + } + } + select { case <-ctx.Done(): // Worker was told to stop. @@ -170,33 +159,10 @@ func (w *worker) coordinate(ctx context.Context) error { // Since we expect I/O errors around interrupts, ignore this error. return nil } - // Unexpected termination. Attempt to minimize, then inform the - // coordinator about the crash. - // TODO(jayconrod,katiehockman): if -keepfuzzing, restart worker. - // TODO(jayconrod,katiehockman): consider informing the - // coordinator that this worker is minimizing, in order to block - // the other workers from receiving more inputs. - message := fmt.Sprintf("fuzzing process terminated unexpectedly: %v", w.waitErr) - err = w.waitErr - var result fuzzResult - var minimized bool - if !input.coverageOnly { - var minErr error - result, minimized, minErr = w.minimize(ctx) - if minErr != nil { - err = minErr - } - } - if !minimized { - // Minimization did not find a smaller crashing value, so - // return the one we already found. - result.entry = CorpusEntry{Data: value} - result.crasherMsg = message - } - w.coordinator.resultC <- result - return err + // Unexpected termination. Set error message and fall through. + // We'll restart the worker on the next iteration. + resp.Err = fmt.Sprintf("fuzzing process terminated unexpectedly: %v", w.waitErr) } - result := fuzzResult{ countRequested: input.countRequested, count: resp.Count, @@ -210,82 +176,99 @@ func (w *worker) coordinate(ctx context.Context) error { result.coverageData = resp.CoverageData } w.coordinator.resultC <- result + + case crasher := <-w.coordinator.minimizeC: + // Received input to minimize from coordinator. + minRes, err := w.minimize(ctx, crasher) + if err != nil { + // Failed to minimize. Send back the original crash. + fmt.Fprintln(w.coordinator.opts.Log, err) + minRes = crasher + minRes.minimized = true + } + w.coordinator.resultC <- minRes } } } -// minimize asks a workerServer to attempt to minimize a value that caused an -// unexpected termination of the worker process. The value must be in shared -// memory, and the worker must be stopped. The execution count in shared memory -// is reset once before restarting the worker. -func (w *worker) minimize(ctx context.Context) (res fuzzResult, minimized bool, retErr error) { - if w.coordinator.opts.MinimizeTimeout != 0 { - fmt.Fprintf(w.coordinator.opts.Log, "found a crash, minimizing for up to %v\n", w.coordinator.opts.MinimizeTimeout) - } else if w.coordinator.opts.MinimizeLimit != 0 { - fmt.Fprintf(w.coordinator.opts.Log, "found a crash, minimizing for up to %d execs\n", w.coordinator.opts.MinimizeLimit) - } else { - fmt.Fprintf(w.coordinator.opts.Log, "found a crash, minimizing...\n") - } - start := time.Now() +// minimize tells a worker process to attempt to find a smaller value that +// causes an error. minimize may restart the worker repeatedly if the error +// causes (or already caused) the worker process to terminate. +// +// TODO: support minimizing inputs that expand coverage in a specific way, +// for example, by ensuring that an input activates a specific set of counters. +func (w *worker) minimize(ctx context.Context, input fuzzResult) (min fuzzResult, err error) { if w.coordinator.opts.MinimizeTimeout != 0 { var cancel func() ctx, cancel = context.WithTimeout(ctx, w.coordinator.opts.MinimizeTimeout) defer cancel() } - defer func() { - w.stop() - if retErr == nil { - retErr = w.waitErr - } - }() - mem := <-w.memMu - mem.header().count = 0 - w.memMu <- mem + min = input + min.minimized = true - for { - if ctx.Err() != nil { - return res, minimized, retErr - } - // Restart the worker. - if err := w.start(); err != nil { - return res, minimized, err - } - if err := w.client.ping(ctx); err != nil { - return res, minimized, err - } - args := minimizeArgs{Limit: w.coordinator.opts.MinimizeLimit} - if w.coordinator.opts.MinimizeTimeout != 0 { - elapsed := time.Now().Sub(start) - args.Timeout = w.coordinator.opts.MinimizeTimeout - elapsed - if args.Timeout < 0 { - return res, minimized, retErr - } - } - value, err := w.client.minimize(ctx, args) - if err == nil { - // Minimization finished successfully, meaning that it - // couldn't find any smaller inputs that caused a crash, - // so stop trying. - return res, minimized, nil - } + args := minimizeArgs{ + Limit: w.coordinator.opts.MinimizeLimit, + Timeout: w.coordinator.opts.MinimizeTimeout, + } + value, resp, err := w.client.minimize(ctx, input.entry.Data, args) + if err != nil { + // Error communicating with worker. w.stop() - // Minimization will return an error for a non-recoverable problem, so - // a non-nil error is expected. However, make sure it didn't fail for - // some other reason which should cause us to stop minimizing. if ctx.Err() != nil || w.interrupted || isInterruptError(w.waitErr) { - return res, minimized, nil + // Worker was interrupted, possibly by the user pressing ^C. + // Normally, workers can handle interrupts and timeouts gracefully and + // will return without error. An error here indicates the worker + // may not have been in a good state, but the error won't be meaningful + // to the user. Just return the original crasher without logging anything. + return min, nil } + return fuzzResult{}, fmt.Errorf("fuzzing process terminated unexpectedly while minimizing: %w", w.waitErr) + } + + if resp.Err == "" { + // Minimization did not find a smaller input that caused a crash. + return min, nil + } + min.crasherMsg = resp.Err + min.count = resp.Count + min.duration = resp.Duration + min.entry.Data = value + return min, nil +} + +func (w *worker) isRunning() bool { + return w.cmd != nil +} - // The bytes in memory caused a legitimate crash, so stop the worker and - // save this value and error message. - message := fmt.Sprintf("fuzzing process terminated unexpectedly: %v", w.waitErr) - res = fuzzResult{ - entry: CorpusEntry{Data: value}, - crasherMsg: message, +// startAndPing starts the worker process and sends it a message to make sure it +// can communicate. +// +// startAndPing returns an error if any part of this didn't work, including if +// the context is expired or the worker process was interrupted before it +// responded. Errors that happen after start but before the ping response +// likely indicate that the worker did not call F.Fuzz or called F.Fail first. +// We don't record crashers for these errors. +func (w *worker) startAndPing(ctx context.Context) error { + if ctx.Err() != nil { + return ctx.Err() + } + if err := w.start(); err != nil { + return err + } + if err := w.client.ping(ctx); err != nil { + w.stop() + if ctx.Err() != nil { + return ctx.Err() } - minimized = true + if isInterruptError(err) { + // User may have pressed ^C before worker responded. + return err + } + // TODO: record and return stderr. + return fmt.Errorf("fuzzing process terminated without fuzzing: %w", err) } + return nil } // start runs a new worker process. @@ -299,7 +282,7 @@ func (w *worker) minimize(ctx context.Context) (res fuzzResult, minimized bool, // When the process terminates, w.waitErr is set to the error (if any), and // w.termC is closed. func (w *worker) start() (err error) { - if w.cmd != nil { + if w.isRunning() { panic("worker already started") } w.waitErr = nil @@ -477,7 +460,18 @@ type minimizeArgs struct { } // minimizeResponse contains results from workerServer.minimize. -type minimizeResponse struct{} +type minimizeResponse struct { + // Err is the error string caused by the value in shared memory. + // If Err is empty, minimize was unable to find any shorter values that + // caused errors, and the value in shared memory is the original value. + Err string + + // Duration is the time spent minimizing, not including starting or cleaning up. + Duration time.Duration + + // Count is the number of values tested. + Count int64 +} // fuzzArgs contains arguments to workerServer.fuzz. The value to fuzz is // passed in shared memory. @@ -634,8 +628,8 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo defer cancel() mem := <-ws.memMu defer func() { - ws.memMu <- mem resp.Count = mem.header().count + ws.memMu <- mem }() vals, err := unmarshalCorpusFile(mem.valueCopy()) @@ -662,16 +656,6 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo ws.m.mutate(vals, cap(mem.valueRef())) writeToMem(vals, mem) if err := ws.fuzzFn(CorpusEntry{Values: vals}); err != nil { - // TODO(jayconrod,katiehockman): report unminimized input to coordinator - // immediately so it can stop other workers. - // TODO(jayconrod,katiehockman): use -fuzzminimizetime to limit time or - // iterations spent on minimization. - minCtx, minCancel := context.WithTimeout(ctx, time.Minute) - defer minCancel() - if minErr := ws.minimizeInput(minCtx, vals, mem, &mem.header().count, args.Limit); minErr != nil { - // Minimization found a different error, so use that one. - err = minErr - } resp.Err = err.Error() if resp.Err == "" { resp.Err = "fuzz function failed with no output" @@ -693,6 +677,8 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo } func (ws *workerServer) minimize(ctx context.Context, args minimizeArgs) (resp minimizeResponse) { + start := time.Now() + defer func() { resp.Duration = time.Now().Sub(start) }() mem := <-ws.memMu defer func() { ws.memMu <- mem }() vals, err := unmarshalCorpusFile(mem.valueCopy()) @@ -704,7 +690,15 @@ func (ws *workerServer) minimize(ctx context.Context, args minimizeArgs) (resp m ctx, cancel = context.WithTimeout(ctx, args.Timeout) defer cancel() } - ws.minimizeInput(ctx, vals, mem, &mem.header().count, args.Limit) + + // Minimize the values in vals, then write to shared memory. We only write + // to shared memory after completing minimization. If the worker terminates + // unexpectedly before then, the coordinator will use the original input. + err = ws.minimizeInput(ctx, vals, &mem.header().count, args.Limit) + writeToMem(vals, mem) + if err != nil { + resp.Err = err.Error() + } return resp } @@ -714,10 +708,7 @@ func (ws *workerServer) minimize(ctx context.Context, args minimizeArgs) (resp m // mem just in case an unrecoverable error occurs. It uses the context to // determine how long to run, stopping once closed. It returns the last error it // found. -func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, mem *sharedMem, count *int64, limit int64) error { - // Make sure the last crashing value is written to mem. - defer writeToMem(vals, mem) - +func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, count *int64, limit int64) error { shouldStop := func() bool { return ctx.Err() != nil || (limit > 0 && *count >= limit) } @@ -779,7 +770,6 @@ func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, m default: panic("impossible") } - writeToMem(vals, mem) err := ws.fuzzFn(CorpusEntry{Values: vals}) if err != nil { retErr = err @@ -798,43 +788,43 @@ func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, m case bool: continue // can't minimize case float32: - minimizeFloat(ctx, float64(v), tryMinimized, shouldStop) + minimizeFloat(float64(v), tryMinimized, shouldStop) case float64: - minimizeFloat(ctx, v, tryMinimized, shouldStop) + minimizeFloat(v, tryMinimized, shouldStop) case uint: - minimizeInteger(ctx, v, tryMinimized, shouldStop) + minimizeInteger(v, tryMinimized, shouldStop) case uint8: - minimizeInteger(ctx, uint(v), tryMinimized, shouldStop) + minimizeInteger(uint(v), tryMinimized, shouldStop) case uint16: - minimizeInteger(ctx, uint(v), tryMinimized, shouldStop) + minimizeInteger(uint(v), tryMinimized, shouldStop) case uint32: - minimizeInteger(ctx, uint(v), tryMinimized, shouldStop) + minimizeInteger(uint(v), tryMinimized, shouldStop) case uint64: if uint64(uint(v)) != v { // Skip minimizing a uint64 on 32 bit platforms, since we'll truncate the // value when casting continue } - minimizeInteger(ctx, uint(v), tryMinimized, shouldStop) + minimizeInteger(uint(v), tryMinimized, shouldStop) case int: - minimizeInteger(ctx, uint(v), tryMinimized, shouldStop) + minimizeInteger(uint(v), tryMinimized, shouldStop) case int8: - minimizeInteger(ctx, uint(v), tryMinimized, shouldStop) + minimizeInteger(uint(v), tryMinimized, shouldStop) case int16: - minimizeInteger(ctx, uint(v), tryMinimized, shouldStop) + minimizeInteger(uint(v), tryMinimized, shouldStop) case int32: - minimizeInteger(ctx, uint(v), tryMinimized, shouldStop) + minimizeInteger(uint(v), tryMinimized, shouldStop) case int64: if int64(int(v)) != v { // Skip minimizing a int64 on 32 bit platforms, since we'll truncate the // value when casting continue } - minimizeInteger(ctx, uint(v), tryMinimized, shouldStop) + minimizeInteger(uint(v), tryMinimized, shouldStop) case string: - minimizeBytes(ctx, []byte(v), tryMinimized, shouldStop) + minimizeBytes([]byte(v), tryMinimized, shouldStop) case []byte: - minimizeBytes(ctx, v, tryMinimized, shouldStop) + minimizeBytes(v, tryMinimized, shouldStop) default: panic("unreachable") } @@ -844,7 +834,6 @@ func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, m func writeToMem(vals []interface{}, mem *sharedMem) { b := marshalCorpusFile(vals...) - mem.setValueLen(len(b)) mem.setValue(b) } @@ -907,21 +896,29 @@ var errSharedMemClosed = errors.New("internal error: shared memory was closed an // minimize tells the worker to call the minimize method. See // workerServer.minimize. -func (wc *workerClient) minimize(ctx context.Context, args minimizeArgs) (valueOut []byte, err error) { +func (wc *workerClient) minimize(ctx context.Context, valueIn []byte, args minimizeArgs) (valueOut []byte, resp minimizeResponse, err error) { wc.mu.Lock() defer wc.mu.Unlock() - var resp minimizeResponse + mem, ok := <-wc.memMu + if !ok { + return nil, minimizeResponse{}, errSharedMemClosed + } + mem.header().count = 0 + mem.setValue(valueIn) + wc.memMu <- mem + c := call{Minimize: &args} err = wc.call(ctx, c, &resp) - mem, ok := <-wc.memMu + mem, ok = <-wc.memMu if !ok { - return nil, errSharedMemClosed + return nil, minimizeResponse{}, errSharedMemClosed } valueOut = mem.valueCopy() + resp.Count = mem.header().count wc.memMu <- mem - return valueOut, err + return valueOut, resp, err } // fuzz tells the worker to call the fuzz method. See workerServer.fuzz. @@ -944,6 +941,7 @@ func (wc *workerClient) fuzz(ctx context.Context, valueIn []byte, args fuzzArgs) return nil, fuzzResponse{}, errSharedMemClosed } valueOut = mem.valueCopy() + resp.Count = mem.header().count wc.memMu <- mem return valueOut, resp, err -- GitLab From 498a48327fae3b57e2696322f1ce2b681ccca668 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 1 Jun 2021 18:45:40 -0700 Subject: [PATCH 0178/2500] [dev.typeparams] cmd/compile: sort iface fields before expansion For toolstash -cmp compatibility with types2, we also need to sort fields (or at least the embedded types) *before* expanding them. This is relevant to what position information and parameter names are used for methods when embedded interfaces have overlapping methods. This came up in archive/zip, which has: type fileInfoDirEntry interface { fs.FileInfo fs.DirEntry } and both of these embedded interfaces in turn have an "IsDir() bool" method. Traditionally, cmd/compile would keep the method from fs.FileInfo.IsDir, but with types2 it will now keep fs.DirEntry.IsDir instead. This doesn't affect correctness at all, but it does end up in DWARF sometimes. Change-Id: Iac8d6321894be335466a76b5bf8a0c1b15a3581b Reviewed-on: https://go-review.googlesource.com/c/go/+/324330 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types/size.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/cmd/compile/internal/types/size.go b/src/cmd/compile/internal/types/size.go index e6ca4556b9..f5a74f83b3 100644 --- a/src/cmd/compile/internal/types/size.go +++ b/src/cmd/compile/internal/types/size.go @@ -90,6 +90,26 @@ func expandiface(t *Type) { methods = append(methods, m) } + { + methods := t.Methods().Slice() + sort.SliceStable(methods, func(i, j int) bool { + mi, mj := methods[i], methods[j] + + // Sort embedded types by type name (if any). + if mi.Sym == nil && mj.Sym == nil { + return mi.Type.Sym().Less(mj.Type.Sym()) + } + + // Sort methods before embedded types. + if mi.Sym == nil || mj.Sym == nil { + return mi.Sym != nil + } + + // Sort methods by symbol name. + return mi.Sym.Less(mj.Sym) + }) + } + for _, m := range t.Methods().Slice() { if m.Sym == nil { continue -- GitLab From c7b98115815a04d9efa664c163d39f5fea38b32c Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 1 Jun 2021 23:01:41 -0700 Subject: [PATCH 0179/2500] [dev.typeparams] cmd/compile/internal/importer: review of gcimporter.go This CL removes the // UNREVIEWED disclaimer at the top of the file. This file is essentially a copy of its reviewed version at src/go/internal/gcimporter/gcimporter.go with adjustments to make it work for the compiler and types2. To see the changes made with respect to the original, compare patchset 1 against patchset 2. Change-Id: I0fd635730fb6bdee8cef1b89154f4049a6581751 Reviewed-on: https://go-review.googlesource.com/c/go/+/324132 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/importer/gcimporter.go | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cmd/compile/internal/importer/gcimporter.go b/src/cmd/compile/internal/importer/gcimporter.go index feb18cf2c9..6c5458fad1 100644 --- a/src/cmd/compile/internal/importer/gcimporter.go +++ b/src/cmd/compile/internal/importer/gcimporter.go @@ -1,4 +1,3 @@ -// UNREVIEWED // Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -- GitLab From 6b1cdeaef3099b32d244cef7bb5adc4d7b7628fc Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 1 Jun 2021 17:00:26 -0700 Subject: [PATCH 0180/2500] [dev.typeparams] cmd/link: include "go build" output in test logs If running "go build" outputs anything, write it to the test log even if the test succeeds. This makes it easier to diagnose errors within the compiler by adding print statements and finding them in the test log, even if the compiler exits successfully. Change-Id: Id04716c4e1dcd9220c35ea0040ea516c1dd5237c Reviewed-on: https://go-review.googlesource.com/c/go/+/324329 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/link/internal/ld/dwarf_test.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/cmd/link/internal/ld/dwarf_test.go b/src/cmd/link/internal/ld/dwarf_test.go index 2f59c2fe0a..543dd5caac 100644 --- a/src/cmd/link/internal/ld/dwarf_test.go +++ b/src/cmd/link/internal/ld/dwarf_test.go @@ -101,8 +101,11 @@ func gobuild(t *testing.T, dir string, testfile string, gcflags string) *builtFi } cmd := exec.Command(testenv.GoToolPath(t), "build", gcflags, "-o", dst, src) - if b, err := cmd.CombinedOutput(); err != nil { - t.Logf("build: %s\n", b) + b, err := cmd.CombinedOutput() + if len(b) != 0 { + t.Logf("## build output:\n%s", b) + } + if err != nil { t.Fatalf("build error: %v", err) } -- GitLab From 97cb0113a358a24931bc91c956da0cb023f2776c Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 2 Jun 2021 00:03:25 -0700 Subject: [PATCH 0181/2500] [dev.typeparams] cmd/compile: fix export/import of constants with typeparam type A constant will have a TYPEPARAM type if it appears in a place where it must match that typeparam type (e.g. in a binary operation with a variable of that typeparam type). If so, then we must write out its actual constant kind as well, so its constant val can be read in properly during import. Fixed some export/import tests which were casting some untyped constants to avoid this problem. Change-Id: I285ad8f1c8febbe526769c96e6b27acbd23050f0 Reviewed-on: https://go-review.googlesource.com/c/go/+/324189 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/typecheck/iexport.go | 44 ++++++++++++++----- src/cmd/compile/internal/typecheck/iimport.go | 28 ++++++++++-- test/typeparam/fact.go | 6 +-- test/typeparam/factimp.dir/a.go | 6 +-- test/typeparam/listimp.dir/a.go | 3 +- 5 files changed, 65 insertions(+), 22 deletions(-) diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index d83f385fcb..66c356ee7c 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -1061,26 +1061,50 @@ func constTypeOf(typ *types.Type) constant.Kind { } func (w *exportWriter) value(typ *types.Type, v constant.Value) { - ir.AssertValidTypeForConst(typ, v) w.typ(typ) + var kind constant.Kind + var valType *types.Type + + if typ.Kind() == types.TTYPEPARAM { + // A constant will have a TYPEPARAM type if it appears in a place + // where it must match that typeparam type (e.g. in a binary + // operation with a variable of that typeparam type). If so, then + // we must write out its actual constant kind as well, so its + // constant val can be read in properly during import. + kind = v.Kind() + w.int64(int64(kind)) + + switch kind { + case constant.Int: + valType = types.Types[types.TINT64] + case constant.Float: + valType = types.Types[types.TFLOAT64] + case constant.Complex: + valType = types.Types[types.TCOMPLEX128] + } + } else { + ir.AssertValidTypeForConst(typ, v) + kind = constTypeOf(typ) + valType = typ + } - // Each type has only one admissible constant representation, - // so we could type switch directly on v.U here. However, - // switching on the type increases symmetry with import logic - // and provides a useful consistency check. + // Each type has only one admissible constant representation, so we could + // type switch directly on v.Kind() here. However, switching on the type + // (in the non-typeparam case) increases symmetry with import logic and + // provides a useful consistency check. - switch constTypeOf(typ) { + switch kind { case constant.Bool: w.bool(constant.BoolVal(v)) case constant.String: w.string(constant.StringVal(v)) case constant.Int: - w.mpint(v, typ) + w.mpint(v, valType) case constant.Float: - w.mpfloat(v, typ) + w.mpfloat(v, valType) case constant.Complex: - w.mpfloat(constant.Real(v), typ) - w.mpfloat(constant.Imag(v), typ) + w.mpfloat(constant.Real(v), valType) + w.mpfloat(constant.Imag(v), valType) } } diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 4c31e47378..96107b657b 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -400,19 +400,39 @@ func (r *importReader) doDecl(sym *types.Sym) *ir.Name { } func (p *importReader) value(typ *types.Type) constant.Value { - switch constTypeOf(typ) { + var kind constant.Kind + var valType *types.Type + + if typ.Kind() == types.TTYPEPARAM { + // If a constant had a typeparam type, then we wrote out its + // actual constant kind as well. + kind = constant.Kind(p.int64()) + switch kind { + case constant.Int: + valType = types.Types[types.TINT64] + case constant.Float: + valType = types.Types[types.TFLOAT64] + case constant.Complex: + valType = types.Types[types.TCOMPLEX128] + } + } else { + kind = constTypeOf(typ) + valType = typ + } + + switch kind { case constant.Bool: return constant.MakeBool(p.bool()) case constant.String: return constant.MakeString(p.string()) case constant.Int: var i big.Int - p.mpint(&i, typ) + p.mpint(&i, valType) return constant.Make(&i) case constant.Float: - return p.float(typ) + return p.float(valType) case constant.Complex: - return makeComplex(p.float(typ), p.float(typ)) + return makeComplex(p.float(valType), p.float(valType)) } base.Fatalf("unexpected value type: %v", typ) diff --git a/test/typeparam/fact.go b/test/typeparam/fact.go index 16b2adf6fb..ea86ae3e02 100644 --- a/test/typeparam/fact.go +++ b/test/typeparam/fact.go @@ -9,10 +9,10 @@ package main import "fmt" func fact[T interface { type int, int64, float64 }](n T) T { - if n == T(1) { - return T(1) + if n == 1 { + return 1 } - return n * fact(n - T(1)) + return n * fact(n - 1) } func main() { diff --git a/test/typeparam/factimp.dir/a.go b/test/typeparam/factimp.dir/a.go index e11575e66e..3552474382 100644 --- a/test/typeparam/factimp.dir/a.go +++ b/test/typeparam/factimp.dir/a.go @@ -5,8 +5,8 @@ package a func Fact[T interface { type int, int64, float64 }](n T) T { - if n == T(1) { - return T(1) + if n == 1 { + return 1 } - return n * Fact(n - T(1)) + return n * Fact(n - 1) } diff --git a/test/typeparam/listimp.dir/a.go b/test/typeparam/listimp.dir/a.go index a4118a0e81..0a4634b7be 100644 --- a/test/typeparam/listimp.dir/a.go +++ b/test/typeparam/listimp.dir/a.go @@ -42,11 +42,10 @@ type ListNum[T OrderedNum] struct { const Clip = 5 // clippedLargest returns the largest in the list of OrderNums, but a max of 5. -// TODO(danscales): fix export/import of an untype constant with typeparam type func (l *ListNum[T]) ClippedLargest() T { var max T for p := l; p != nil; p = p.Next { - if p.Val > max && p.Val < T(Clip) { + if p.Val > max && p.Val < Clip { max = p.Val } } -- GitLab From 848b58e47357965dc5a61fb0ae5535da717e2633 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 27 May 2021 19:03:16 -0700 Subject: [PATCH 0182/2500] [dev.typeparams] cmd/compile/internal/types2: clean up type set/union intersection - Eliminate the need for bottom type: This is now represented by an empty union (denoting the set of no types). - Clean up type set intersection and incorporate tilde information in intersection operation and satisfaction tests. - Minor cleanups along the way. - Note: The intersection algorithm does not always compute the largest possible intersection. To be addressed in a follow-up CL. Change-Id: I7fa19df5996da36a4d8f29300d30a0aa4d8a3e5c Reviewed-on: https://go-review.googlesource.com/c/go/+/323354 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley TryBot-Result: Go Bot --- src/cmd/compile/internal/types2/interface.go | 10 -- src/cmd/compile/internal/types2/predicates.go | 11 +- src/cmd/compile/internal/types2/sanitize.go | 2 +- .../compile/internal/types2/sizeof_test.go | 1 - src/cmd/compile/internal/types2/subst.go | 4 +- .../internal/types2/testdata/check/issues.go2 | 2 +- .../types2/testdata/examples/constraints.go2 | 14 +++ src/cmd/compile/internal/types2/type.go | 40 +++---- src/cmd/compile/internal/types2/typestring.go | 7 +- src/cmd/compile/internal/types2/union.go | 105 +++++++++++++----- 10 files changed, 118 insertions(+), 78 deletions(-) diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index db34d0705f..770b8ba5cc 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -109,16 +109,6 @@ func flattenUnion(list []syntax.Expr, x syntax.Expr) []syntax.Expr { return append(list, x) } -// includes reports whether typ is in list -func includes(list []Type, typ Type) bool { - for _, e := range list { - if Identical(typ, e) { - return true - } - } - return false -} - func (check *Checker) completeInterface(pos syntax.Pos, ityp *Interface) { if ityp.allMethods != nil { return diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index bcb3e221d0..74436836cd 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -97,9 +97,9 @@ func comparable(T Type, seen map[Type]bool) bool { seen[T] = true // If T is a type parameter not constrained by any type - // list (i.e., it's underlying type is the top type), + // list (i.e., it's operational type is the top type), // T is comparable if it has the == method. Otherwise, - // the underlying type "wins". For instance + // the operational type "wins". For instance // // interface{ comparable; type []byte } // @@ -370,10 +370,9 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { // case *instance: // unreachable since types are expanded - case *bottom, *top: - // Either both types are theBottom, or both are theTop in which - // case the initial x == y check will have caught them. Otherwise - // they are not identical. + case *top: + // Either both types are theTop in which case the initial x == y check + // will have caught them. Otherwise they are not identical. case nil: // avoid a crash in case of nil type diff --git a/src/cmd/compile/internal/types2/sanitize.go b/src/cmd/compile/internal/types2/sanitize.go index ce26bab186..03aef90fe1 100644 --- a/src/cmd/compile/internal/types2/sanitize.go +++ b/src/cmd/compile/internal/types2/sanitize.go @@ -77,7 +77,7 @@ func (s sanitizer) typ(typ Type) Type { s[typ] = typ switch t := typ.(type) { - case *Basic, *bottom, *top: + case *Basic, *top: // nothing to do case *Array: diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go index d3c391161e..daa039bf92 100644 --- a/src/cmd/compile/internal/types2/sizeof_test.go +++ b/src/cmd/compile/internal/types2/sizeof_test.go @@ -34,7 +34,6 @@ func TestSizeof(t *testing.T) { {Named{}, 68, 136}, {TypeParam{}, 28, 48}, {instance{}, 52, 96}, - {bottom{}, 0, 0}, {top{}, 0, 0}, // Objects diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index bfec61a065..617a03ddbc 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -206,7 +206,7 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap // Otherwise, targ's type or underlying type must also be one of the interface types listed, if any. if !iface.isSatisfiedBy(targ) { - check.softErrorf(pos, "%s does not satisfy %s (%s not found in %s)", targ, tpar.bound, under(targ), iface.allTypes) + check.softErrorf(pos, "%s does not satisfy %s (%s not found in %s)", targ, tpar.bound, targ, iface.allTypes) return false } @@ -249,7 +249,7 @@ func (subst *subster) typ(typ Type) Type { // Call typOrNil if it's possible that typ is nil. panic("nil typ") - case *Basic, *bottom, *top: + case *Basic, *top: // nothing to do case *Array: diff --git a/src/cmd/compile/internal/types2/testdata/check/issues.go2 b/src/cmd/compile/internal/types2/testdata/check/issues.go2 index 1c73b5da92..f0a7b24748 100644 --- a/src/cmd/compile/internal/types2/testdata/check/issues.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/issues.go2 @@ -234,7 +234,7 @@ func _[T interface{ type func() }](f T) { type sliceOf[E any] interface{ type []E } -func append[T interface{}, S sliceOf[T], T2 interface{ type T }](s S, t ...T2) S +func append[T interface{}, S sliceOf[T], T2 interface{ T }](s S, t ...T2) S var f func() var cancelSlice []context.CancelFunc diff --git a/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 b/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 index e8b3912884..f6291ccf7d 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 @@ -23,3 +23,17 @@ type ( _ interface{~ /* ERROR cannot use interface */ interface{}} _ interface{int|interface /* ERROR cannot use interface */ {}} ) + +// Multiple embedded union elements are intersected. The order in which they +// appear in the interface doesn't matter since intersection is a symmetric +// operation. + +type myInt1 int +type myInt2 int + +func _[T interface{ myInt1|myInt2; ~int }]() T { return T(0) } +func _[T interface{ ~int; myInt1|myInt2 }]() T { return T(0) } + +// Here the intersections are empty - there's no type that's in the type set of T. +func _[T interface{ myInt1|myInt2; int }]() T { return T(0 /* ERROR cannot convert */ ) } +func _[T interface{ int; myInt1|myInt2 }]() T { return T(0 /* ERROR cannot convert */ ) } diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index aab75811b8..990b9d374c 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -376,7 +376,6 @@ func (t *Interface) Method(i int) *Func { t.Complete(); return t.allMethods[i] } // Empty reports whether t is the empty interface. func (t *Interface) Empty() bool { t.Complete() - // A non-nil allTypes may still have length 0 but represents the bottom type. return len(t.allMethods) == 0 && t.allTypes == nil } @@ -431,11 +430,15 @@ func (t *Interface) iterate(f func(*Interface) bool, seen map[*Interface]bool) b // "implements" predicate. func (t *Interface) isSatisfiedBy(typ Type) bool { t.Complete() - if t.allTypes == nil { - return true + switch t := t.allTypes.(type) { + case nil: + return true // no type restrictions + case *Union: + r, _ := t.intersect(typ, false) + return r != nil + default: + return Identical(t, typ) } - types := unpack(t.allTypes) - return includes(types, typ) || includes(types, under(typ)) } // Complete computes the interface's method set. It must be called by users of @@ -654,13 +657,11 @@ func (t *TypeParam) Bound() *Interface { return iface } -// optype returns a type's operational type. Except for -// type parameters, the operational type is the same -// as the underlying type (as returned by under). For -// Type parameters, the operational type is determined -// by the corresponding type bound's type list. The -// result may be the bottom or top type, but it is never -// the incoming type parameter. +// optype returns a type's operational type. Except for type parameters, +// the operational type is the same as the underlying type (as returned +// by under). For Type parameters, the operational type is determined +// by the corresponding type constraint. The result may be the top type, +// but it is never the incoming type parameter. func optype(typ Type) Type { if t := asTypeParam(typ); t != nil { // If the optype is typ, return the top type as we have @@ -733,20 +734,11 @@ var expandf func(Type) Type func init() { expandf = expand } -// bottom represents the bottom of the type lattice. -// It is the underlying type of a type parameter that -// cannot be satisfied by any type, usually because -// the intersection of type constraints left nothing). -type bottom struct{} - -// theBottom is the singleton bottom type. -var theBottom = &bottom{} - // top represents the top of the type lattice. // It is the underlying type of a type parameter that // can be satisfied by any type (ignoring methods), -// usually because the type constraint has no type -// list. +// because its type constraint contains no restrictions +// besides methods. type top struct{} // theTop is the singleton top type. @@ -766,7 +758,6 @@ func (t *Chan) Underlying() Type { return t } func (t *Named) Underlying() Type { return t.underlying } func (t *TypeParam) Underlying() Type { return t } func (t *instance) Underlying() Type { return t } -func (t *bottom) Underlying() Type { return t } func (t *top) Underlying() Type { return t } // Type-specific implementations of String. @@ -783,7 +774,6 @@ func (t *Chan) String() string { return TypeString(t, nil) } func (t *Named) String() string { return TypeString(t, nil) } func (t *TypeParam) String() string { return TypeString(t, nil) } func (t *instance) String() string { return TypeString(t, nil) } -func (t *bottom) String() string { return TypeString(t, nil) } func (t *top) String() string { return TypeString(t, nil) } // under returns the true expanded underlying type. diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 466beb2398..28583b62d9 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -158,6 +158,10 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { writeSignature(buf, t, qf, visited) case *Union: + if t.IsEmpty() { + buf.WriteString("⊥") + break + } for i, e := range t.types { if i > 0 { buf.WriteString("|") @@ -294,9 +298,6 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { writeTypeList(buf, t.targs, qf, visited) buf.WriteByte(']') - case *bottom: - buf.WriteString("⊥") - case *top: buf.WriteString("⊤") diff --git a/src/cmd/compile/internal/types2/union.go b/src/cmd/compile/internal/types2/union.go index a5ef721ee6..671e36111b 100644 --- a/src/cmd/compile/internal/types2/union.go +++ b/src/cmd/compile/internal/types2/union.go @@ -16,8 +16,12 @@ type Union struct { tilde []bool // if tilde[i] is set, terms[i] is of the form ~T } -func NewUnion(types []Type, tilde []bool) Type { return newUnion(types, tilde) } +// NewUnion returns a new Union type with the given terms (types[i], tilde[i]). +// The lengths of both arguments must match. An empty union represents the set +// of no types. +func NewUnion(types []Type, tilde []bool) *Union { return newUnion(types, tilde) } +func (u *Union) IsEmpty() bool { return len(u.types) == 0 } func (u *Union) NumTerms() int { return len(u.types) } func (u *Union) Term(i int) (Type, bool) { return u.types[i], u.tilde[i] } @@ -27,10 +31,12 @@ func (u *Union) String() string { return TypeString(u, nil) } // ---------------------------------------------------------------------------- // Implementation -func newUnion(types []Type, tilde []bool) Type { +var emptyUnion = new(Union) + +func newUnion(types []Type, tilde []bool) *Union { assert(len(types) == len(tilde)) - if types == nil { - return nil + if len(types) == 0 { + return emptyUnion } t := new(Union) t.types = types @@ -40,7 +46,7 @@ func newUnion(types []Type, tilde []bool) Type { // is reports whether f returned true for all terms (type, tilde) of u. func (u *Union) is(f func(Type, bool) bool) bool { - if u == nil { + if u.IsEmpty() { return false } for i, t := range u.types { @@ -53,7 +59,7 @@ func (u *Union) is(f func(Type, bool) bool) bool { // is reports whether f returned true for the underlying types of all terms of u. func (u *Union) underIs(f func(Type) bool) bool { - if u == nil { + if u.IsEmpty() { return false } for _, t := range u.types { @@ -130,26 +136,24 @@ func parseTilde(check *Checker, x syntax.Expr) (Type, bool) { return check.anyType(x), tilde } -// intersect computes the intersection of the types x and y. -// Note: An incomming nil type stands for the top type. A top -// type result is returned as nil. +// intersect computes the intersection of the types x and y, +// A nil type stands for the set of all types; an empty union +// stands for the set of no types. func intersect(x, y Type) (r Type) { - defer func() { - if r == theTop { - r = nil - } - }() - + // If one of the types is nil (no restrictions) + // the result is the other type. switch { - case x == theBottom || y == theBottom: - return theBottom - case x == nil || x == theTop: + case x == nil: return y - case y == nil || x == theTop: + case y == nil: return x } // Compute the terms which are in both x and y. + // TODO(gri) This is not correct as it may not always compute + // the "largest" intersection. For instance, for + // x = myInt|~int, y = ~int + // we get the result myInt but we should get ~int. xu, _ := x.(*Union) yu, _ := y.(*Union) switch { @@ -158,23 +162,29 @@ func intersect(x, y Type) (r Type) { // TODO(gri) fix asymptotic performance var types []Type var tilde []bool - for _, y := range yu.types { - if includes(xu.types, y) { - types = append(types, y) - tilde = append(tilde, true) // TODO(gri) fix this + for j, y := range yu.types { + yt := yu.tilde[j] + if r, rt := xu.intersect(y, yt); r != nil { + // Terms x[i] and y[j] match: Select the one that + // is not a ~t because that is the intersection + // type. If both are ~t, they are identical: + // T ∩ T = T + // T ∩ ~t = T + // ~t ∩ T = T + // ~t ∩ ~t = ~t + types = append(types, r) + tilde = append(tilde, rt) } } - if types != nil { - return newUnion(types, tilde) - } + return newUnion(types, tilde) case xu != nil: - if includes(xu.types, y) { + if r, _ := xu.intersect(y, false); r != nil { return y } case yu != nil: - if includes(yu.types, x) { + if r, _ := yu.intersect(x, false); r != nil { return x } @@ -184,5 +194,42 @@ func intersect(x, y Type) (r Type) { } } - return theBottom + return emptyUnion +} + +// includes reports whether typ is in list. +func includes(list []Type, typ Type) bool { + for _, e := range list { + if Identical(typ, e) { + return true + } + } + return false +} + +// intersect computes the intersection of the union u and term (y, yt) +// and returns the intersection term, if any. Otherwise the result is +// (nil, false). +func (u *Union) intersect(y Type, yt bool) (Type, bool) { + under_y := under(y) + for i, x := range u.types { + xt := u.tilde[i] + // determine which types xx, yy to compare + xx := x + if yt { + xx = under(x) + } + yy := y + if xt { + yy = under_y + } + if Identical(xx, yy) { + // T ∩ T = T + // T ∩ ~t = T + // ~t ∩ T = T + // ~t ∩ ~t = ~t + return xx, xt && yt + } + } + return nil, false } -- GitLab From 3c1d502a19dcdaaf0f7ddf58ccad9953fe5d92d1 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 27 May 2021 22:09:58 -0700 Subject: [PATCH 0183/2500] [dev.typeparams] cmd/compile/internal/types2: eliminate need for unpack and asUnion functions Change-Id: Iaa75b091d52f44939330e5945305aea323ba58f4 Reviewed-on: https://go-review.googlesource.com/c/go/+/323355 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/builtins.go | 12 +++---- src/cmd/compile/internal/types2/infer.go | 15 +++++---- src/cmd/compile/internal/types2/subst.go | 11 ++++--- src/cmd/compile/internal/types2/type.go | 35 ++++++--------------- 4 files changed, 29 insertions(+), 44 deletions(-) diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 1779e32c5c..20c4ff62a1 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -749,14 +749,12 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { if tp := asTypeParam(x); tp != nil { // Test if t satisfies the requirements for the argument // type and collect possible result types at the same time. - // TODO(gri) This needs to consider the ~ information if we - // have a union type. var rtypes []Type - var tilde []bool - if !tp.Bound().is(func(x Type) bool { - if r := f(x); r != nil { + var tildes []bool + if !tp.Bound().is(func(typ Type, tilde bool) bool { + if r := f(typ); r != nil { rtypes = append(rtypes, r) - tilde = append(tilde, true) // for now - see TODO above + tildes = append(tildes, tilde) return true } return false @@ -772,7 +770,7 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { // construct a suitable new type parameter tpar := NewTypeName(nopos, nil /* = Universe pkg */, "", nil) ptyp := check.NewTypeParam(tpar, 0, &emptyInterface) // assigns type to tpar as a side-effect - tsum := newUnion(rtypes, tilde) + tsum := newUnion(rtypes, tildes) ptyp.bound = &Interface{allMethods: markComplete, allTypes: tsum} return ptyp diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index 73ea8330d4..63cd63aacc 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -328,7 +328,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { return true } } - return w.isParameterizedList(unpack(t.allTypes)) + return w.isParameterized(t.allTypes) } return t.iterate(func(t *Interface) bool { @@ -477,11 +477,14 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty func (check *Checker) structuralType(constraint Type) Type { if iface, _ := under(constraint).(*Interface); iface != nil { check.completeInterface(nopos, iface) - types := unpack(iface.allTypes) - if len(types) == 1 { - return types[0] + if u, _ := iface.allTypes.(*Union); u != nil { + if u.NumTerms() == 1 { + // TODO(gri) do we need to respect tilde? + return u.types[0] + } + return nil } - return nil + return iface.allTypes } - return constraint + return nil } diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 617a03ddbc..35ca197d64 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -194,14 +194,15 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap check.softErrorf(pos, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ) return false } - for _, t := range unpack(targBound.allTypes) { - if !iface.isSatisfiedBy(t) { + return iface.is(func(typ Type, tilde bool) bool { + // TODO(gri) incorporate tilde information! + if !iface.isSatisfiedBy(typ) { // TODO(gri) match this error message with the one below (or vice versa) - check.softErrorf(pos, "%s does not satisfy %s (%s type constraint %s not found in %s)", targ, tpar.bound, targ, t, iface.allTypes) + check.softErrorf(pos, "%s does not satisfy %s (%s type constraint %s not found in %s)", targ, tpar.bound, targ, typ, iface.allTypes) return false } - } - return false + return true + }) } // Otherwise, targ's type or underlying type must also be one of the interface types listed, if any. diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 990b9d374c..92f35f1279 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -272,29 +272,17 @@ type Interface struct { obj Object // type declaration defining this interface; or nil (for better error messages) } -// unpack unpacks a type into a list of types. -// TODO(gri) Try to eliminate the need for this function. -func unpack(typ Type) []Type { - if typ == nil { - return nil - } - if u := asUnion(typ); u != nil { - return u.types - } - return []Type{typ} -} - -// is reports whether interface t represents types that all satisfy pred. -func (t *Interface) is(pred func(Type) bool) bool { - if t.allTypes == nil { +// is reports whether interface t represents types that all satisfy f. +func (t *Interface) is(f func(Type, bool) bool) bool { + switch t := t.allTypes.(type) { + case nil, *top: + // TODO(gri) should settle on top or nil to represent this case return false // we must have at least one type! (was bug) + case *Union: + return t.is(func(typ Type, tilde bool) bool { return f(typ, tilde) }) + default: + return f(t, false) } - for _, t := range unpack(t.allTypes) { - if !pred(t) { - return false - } - } - return true } // emptyInterface represents the empty (completed) interface @@ -828,11 +816,6 @@ func asSignature(t Type) *Signature { return op } -func asUnion(t Type) *Union { - op, _ := optype(t).(*Union) - return op -} - func asInterface(t Type) *Interface { op, _ := optype(t).(*Interface) return op -- GitLab From d36b7d7bdd130dacfc6166d16dd879e2231baf62 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 1 Jun 2021 22:56:01 -0700 Subject: [PATCH 0184/2500] [dev.typeparams] cmd/compile/internal/importer: review of gcimporter_test.go This CL removes the // UNREVIEWED disclaimer at the top of the file. This file is essentially a copy of its reviewed version at src/go/internal/gcimporter/gcimporter_test.go with adjustments to make it work for the compiler and types2. To see the changes made with respect to the original, compare patchset 2 against patchset 3. Change-Id: Iaeb9a56a6a56f4c1d93e7bfedc5b1f1968fa6792 Reviewed-on: https://go-review.googlesource.com/c/go/+/324131 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley TryBot-Result: Go Bot --- .../internal/importer/gcimporter_test.go | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/cmd/compile/internal/importer/gcimporter_test.go b/src/cmd/compile/internal/importer/gcimporter_test.go index 7fb8fed59c..44c5e06cd6 100644 --- a/src/cmd/compile/internal/importer/gcimporter_test.go +++ b/src/cmd/compile/internal/importer/gcimporter_test.go @@ -1,4 +1,3 @@ -// UNREVIEWED // Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -10,7 +9,6 @@ import ( "cmd/compile/internal/types2" "fmt" "internal/testenv" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -64,7 +62,7 @@ const maxTime = 30 * time.Second func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) { dirname := filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_"+runtime.GOARCH, dir) - list, err := ioutil.ReadDir(dirname) + list, err := os.ReadDir(dirname) if err != nil { t.Fatalf("testDir(%s): %s", dirname, err) } @@ -92,7 +90,7 @@ func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) { } func mktmpdir(t *testing.T) string { - tmpdir, err := ioutil.TempDir("", "gcimporter_test") + tmpdir, err := os.MkdirTemp("", "gcimporter_test") if err != nil { t.Fatal("mktmpdir:", err) } @@ -142,7 +140,7 @@ func TestVersionHandling(t *testing.T) { } const dir = "./testdata/versions" - list, err := ioutil.ReadDir(dir) + list, err := os.ReadDir(dir) if err != nil { t.Fatal(err) } @@ -195,7 +193,7 @@ func TestVersionHandling(t *testing.T) { // create file with corrupted export data // 1) read file - data, err := ioutil.ReadFile(filepath.Join(dir, name)) + data, err := os.ReadFile(filepath.Join(dir, name)) if err != nil { t.Fatal(err) } @@ -212,7 +210,7 @@ func TestVersionHandling(t *testing.T) { // 4) write the file pkgpath += "_corrupted" filename := filepath.Join(corruptdir, pkgpath) + ".a" - ioutil.WriteFile(filename, data, 0666) + os.WriteFile(filename, data, 0666) // test that importing the corrupted file results in an error _, err = Import(make(map[string]*types2.Package), pkgpath, corruptdir, nil) @@ -261,8 +259,7 @@ var importedObjectTests = []struct { {"io.Reader", "type Reader interface{Read(p []byte) (n int, err error)}"}, {"io.ReadWriter", "type ReadWriter interface{Reader; Writer}"}, {"go/ast.Node", "type Node interface{End() go/token.Pos; Pos() go/token.Pos}"}, - // go/types.Type has grown much larger - excluded for now - // {"go/types.Type", "type Type interface{String() string; Underlying() Type}"}, + {"go/types.Type", "type Type interface{String() string; Underlying() Type}"}, } func TestImportedTypes(t *testing.T) { @@ -457,17 +454,17 @@ func TestIssue13898(t *testing.T) { t.Fatal("go/types not found") } - // look for go/types2.Object type + // look for go/types.Object type obj := lookupObj(t, goTypesPkg.Scope(), "Object") typ, ok := obj.Type().(*types2.Named) if !ok { - t.Fatalf("go/types2.Object type is %v; wanted named type", typ) + t.Fatalf("go/types.Object type is %v; wanted named type", typ) } - // lookup go/types2.Object.Pkg method + // lookup go/types.Object.Pkg method m, index, indirect := types2.LookupFieldOrMethod(typ, false, nil, "Pkg") if m == nil { - t.Fatalf("go/types2.Object.Pkg not found (index = %v, indirect = %v)", index, indirect) + t.Fatalf("go/types.Object.Pkg not found (index = %v, indirect = %v)", index, indirect) } // the method must belong to go/types -- GitLab From 9a99e728fecccb992a175f9d39c5c64d78d429fc Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 2 Jun 2021 15:36:11 -0700 Subject: [PATCH 0185/2500] [dev.typeparams] cmd/compile/internal/types2: convert testdata/examples tests to type set sytax Change-Id: Ida3837c9cbb970a2b49cd1598c6e6e9de8aa9690 Reviewed-on: https://go-review.googlesource.com/c/go/+/324529 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley TryBot-Result: Go Bot --- .../internal/types2/testdata/examples/functions.go2 | 2 +- .../internal/types2/testdata/examples/inference.go2 | 6 +++--- .../compile/internal/types2/testdata/examples/types.go2 | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/internal/types2/testdata/examples/functions.go2 b/src/cmd/compile/internal/types2/testdata/examples/functions.go2 index 0c2a408f02..154d09f528 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/functions.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/functions.go2 @@ -98,7 +98,7 @@ func g2b[P, Q any](x P, y Q) { // Here's an example of a recursive function call with variadic // arguments and type inference inferring the type parameter of // the caller (i.e., itself). -func max[T interface{ type int }](x ...T) T { +func max[T interface{ ~int }](x ...T) T { var x0 T if len(x) > 0 { x0 = x[0] diff --git a/src/cmd/compile/internal/types2/testdata/examples/inference.go2 b/src/cmd/compile/internal/types2/testdata/examples/inference.go2 index b47ce75805..75d47d2c9b 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/inference.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/inference.go2 @@ -7,7 +7,7 @@ package p type Ordered interface { - type int, float64, string + ~int|~float64|~string } func min[T Ordered](x, y T) T @@ -54,7 +54,7 @@ func _() { mixed[int, string](1.1 /* ERROR cannot use 1.1 */ , "", false) } -func related1[Slice interface{type []Elem}, Elem any](s Slice, e Elem) +func related1[Slice interface{~[]Elem}, Elem any](s Slice, e Elem) func _() { // related1 can be called with explicit instantiation. @@ -78,7 +78,7 @@ func _() { related1(si, "foo" /* ERROR cannot use "foo" */ ) } -func related2[Elem any, Slice interface{type []Elem}](e Elem, s Slice) +func related2[Elem any, Slice interface{~[]Elem}](e Elem, s Slice) func _() { // related2 can be called with explicit instantiation. diff --git a/src/cmd/compile/internal/types2/testdata/examples/types.go2 b/src/cmd/compile/internal/types2/testdata/examples/types.go2 index a7825ed2d9..66e7a7b90e 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/types.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/types.go2 @@ -159,7 +159,7 @@ type _ struct { // are type parameters. As with ordinary type definitions, the // types underlying properties are "inherited" but the methods // are not. -func _[T interface{ m(); type int }]() { +func _[T interface{ m(); ~int }]() { type L T var x L @@ -232,11 +232,11 @@ func _[A Adder[A], B Adder[B], C Adder[A]]() { // The type of variables (incl. parameters and return values) cannot // be an interface with type constraints or be/embed comparable. type I interface { - type int + ~int } var ( - _ interface /* ERROR contains type constraints */ {type int} + _ interface /* ERROR contains type constraints */ {~int} _ I /* ERROR contains type constraints */ ) @@ -267,7 +267,7 @@ func _() { // (If a type list contains just a single const type, we could // allow it, but such type lists don't make much sense in the // first place.) -func _[T interface { type int, float64 }]() { +func _[T interface{~int|~float64}]() { // not valid const _ = T /* ERROR not constant */ (0) const _ T /* ERROR invalid constant type T */ = 1 -- GitLab From c790964ae457f244e634184a810b226b27bf7e0b Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 2 Jun 2021 15:45:43 -0700 Subject: [PATCH 0186/2500] [dev.typeparams] cmd/compile/internal/types2: convert testdata/fixedbugs tests to type set sytax Change-Id: I2ad94c71bebb93e0e3f4eba9d5199a3b3e9fa63d Reviewed-on: https://go-review.googlesource.com/c/go/+/324530 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley --- .../compile/internal/types2/testdata/fixedbugs/issue39634.go2 | 4 ++-- .../compile/internal/types2/testdata/fixedbugs/issue39680.go2 | 4 ++-- .../compile/internal/types2/testdata/fixedbugs/issue39699.go2 | 2 +- .../compile/internal/types2/testdata/fixedbugs/issue39723.go2 | 2 +- .../compile/internal/types2/testdata/fixedbugs/issue39755.go2 | 4 ++-- .../compile/internal/types2/testdata/fixedbugs/issue41124.go2 | 4 ++-- .../compile/internal/types2/testdata/fixedbugs/issue42758.go2 | 2 +- .../compile/internal/types2/testdata/fixedbugs/issue45548.go2 | 2 +- .../compile/internal/types2/testdata/fixedbugs/issue45635.go2 | 2 +- .../compile/internal/types2/testdata/fixedbugs/issue45985.go2 | 2 +- 10 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 index 92ea305479..39ec5d7b30 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 @@ -31,12 +31,12 @@ type x7[A any] struct{ foo7 } func main7() { var _ foo7 = x7[int]{} } // crash 8 -type foo8[A any] interface { type A } +type foo8[A any] interface { ~A } func bar8[A foo8[A]](a A) {} func main8() {} // crash 9 -type foo9[A any] interface { type foo9 /* ERROR cannot use interface */ [A] } +type foo9[A any] interface { ~/* ERROR cannot use interface */ foo9[A] } func _() { var _ = new(foo9 /* ERROR interface contains type constraints */ [int]) } // crash 12 diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39680.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39680.go2 index 9bc26f3546..01eadd2dbf 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39680.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39680.go2 @@ -7,13 +7,13 @@ package p import "fmt" // Minimal test case. -func _[T interface{type T}](x T) T{ +func _[T interface{~T}](x T) T{ return x } // Test case from issue. type constr[T any] interface { - type T + ~T } func Print[T constr[T]](s []T) { diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39699.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39699.go2 index 75491e7e26..72f83997c2 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39699.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39699.go2 @@ -8,7 +8,7 @@ type T0 interface{ } type T1 interface{ - type int + ~int } type T2 interface{ diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39723.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39723.go2 index 61bc606789..367b3f1360 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39723.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39723.go2 @@ -6,4 +6,4 @@ package p // A constraint must be an interface; it cannot // be a type parameter, for instance. -func _[A interface{ type int }, B A /* ERROR not an interface */ ]() +func _[A interface{ ~int }, B A /* ERROR not an interface */ ]() diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39755.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39755.go2 index b7ab68818e..257b73a2fb 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39755.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39755.go2 @@ -4,14 +4,14 @@ package p -func _[T interface{type map[string]int}](x T) { +func _[T interface{~map[string]int}](x T) { _ = x == nil } // simplified test case from issue type PathParamsConstraint interface { - type map[string]string, []struct{key, value string} + ~map[string]string | ~[]struct{key, value string} } type PathParams[T PathParamsConstraint] struct { diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2 index 61f766bcbd..ab535049dd 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2 @@ -7,7 +7,7 @@ package p // Test case from issue. type Nat interface { - type Zero, Succ + Zero|Succ } type Zero struct{} @@ -22,7 +22,7 @@ type I1 interface { } type I2 interface { - type int + ~int } type I3 interface { diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue42758.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue42758.go2 index 698cb8a16b..bf0031f5d2 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue42758.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue42758.go2 @@ -17,7 +17,7 @@ func _[T any](x interface{}){ } type constraint interface { - type int + ~int } func _[T constraint](x interface{}){ diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45548.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45548.go2 index b1e42497e8..b8ba0ad4a7 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45548.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45548.go2 @@ -4,7 +4,7 @@ package p -func f[F interface{type *Q}, G interface{type *R}, Q, R any](q Q, r R) {} +func f[F interface{~*Q}, G interface{~*R}, Q, R any](q Q, r R) {} func _() { f[*float64, *int](1, 2) diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45635.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45635.go2 index 65662cdc76..e9b57ae8f1 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45635.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45635.go2 @@ -13,7 +13,7 @@ type N[T any] struct{} var _ N[] /* ERROR expecting type */ type I interface { - type map[int]int, []int + ~map[int]int | ~[]int } func _[T I](i, j int) { diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45985.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45985.go2 index 7678e348ef..f25b9d2b26 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45985.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45985.go2 @@ -5,7 +5,7 @@ package issue45985 // TODO(gri): this error should be on app[int] below. -func app[S /* ERROR "type S = S does not match" */ interface{ type []T }, T any](s S, e T) S { +func app[S /* ERROR "type S = S does not match" */ interface{ ~[]T }, T any](s S, e T) S { return append(s, e) } -- GitLab From 8cdce85bdf80f6aa9bd3979d3ecab6565512b736 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 2 Jun 2021 16:12:25 -0700 Subject: [PATCH 0187/2500] [dev.typeparams] cmd/compile/internal/types2: convert testdata/check tests to type set sytax Change-Id: I0c2dda10ba7cb40330545fd10fbacb8c84f66a2d Reviewed-on: https://go-review.googlesource.com/c/go/+/324569 Trust: Robert Griesemer Reviewed-by: Robert Findley --- .../types2/testdata/check/builtins.go2 | 8 +- .../internal/types2/testdata/check/issues.go2 | 26 +++--- .../internal/types2/testdata/check/linalg.go2 | 16 ++-- .../types2/testdata/check/tinference.go2 | 20 ++--- .../types2/testdata/check/typeinst2.go2 | 29 +++---- .../types2/testdata/check/typeparams.go2 | 80 +++++++++---------- 6 files changed, 90 insertions(+), 89 deletions(-) diff --git a/src/cmd/compile/internal/types2/testdata/check/builtins.go2 b/src/cmd/compile/internal/types2/testdata/check/builtins.go2 index 3918d836b5..5bb67efec9 100644 --- a/src/cmd/compile/internal/types2/testdata/check/builtins.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/builtins.go2 @@ -7,19 +7,19 @@ package builtins type Bmc interface { - type map[rune]string, chan int + ~map[rune]string | ~chan int } type Bms interface { - type map[string]int, []int + ~map[string]int | ~[]int } type Bcs interface { - type chan bool, []float64 + ~chan bool | ~[]float64 } type Bss interface { - type []int, []string + ~[]int | ~[]string } func _[T any] () { diff --git a/src/cmd/compile/internal/types2/testdata/check/issues.go2 b/src/cmd/compile/internal/types2/testdata/check/issues.go2 index f0a7b24748..59dd4ae465 100644 --- a/src/cmd/compile/internal/types2/testdata/check/issues.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/issues.go2 @@ -57,7 +57,7 @@ func _() { // type with a type list constraint, all of the type argument's types in its // bound, but at least one (!), must be in the type list of the bound of the // corresponding parameterized type's type parameter. -type T1[P interface{type uint}] struct{} +type T1[P interface{~uint}] struct{} func _[P any]() { _ = T1[P /* ERROR P has no type constraints */ ]{} @@ -65,7 +65,7 @@ func _[P any]() { // This is the original (simplified) program causing the same issue. type Unsigned interface { - type uint + ~uint } type T2[U Unsigned] struct { @@ -156,7 +156,7 @@ type inf2[T any] struct{ inf2 /* ERROR illegal cycle */ [T] } // predicate disjunction in the implementation was wrong because if a type list // contains both an integer and a floating-point type, the type parameter is // neither an integer or a floating-point number. -func convert[T1, T2 interface{type int, uint, float32}](v T1) T2 { +func convert[T1, T2 interface{~int | ~uint | ~float32}](v T1) T2 { return T2(v) } @@ -168,12 +168,12 @@ func _() { // both numeric, or both strings. The implementation had the same problem // with this check as the conversion issue above (issue #39623). -func issue39623[T interface{type int, string}](x, y T) T { +func issue39623[T interface{~int | ~string}](x, y T) T { return x + y } // Simplified, from https://go2goplay.golang.org/p/efS6x6s-9NI: -func Sum[T interface{type int, string}](s []T) (sum T) { +func Sum[T interface{~int | ~string}](s []T) (sum T) { for _, v := range s { sum += v } @@ -182,19 +182,19 @@ func Sum[T interface{type int, string}](s []T) (sum T) { // Assignability of an unnamed pointer type to a type parameter that // has a matching underlying type. -func _[T interface{}, PT interface{type *T}] (x T) PT { +func _[T interface{}, PT interface{~*T}] (x T) PT { return &x } // Indexing of generic types containing type parameters in their type list: -func at[T interface{ type []E }, E interface{}](x T, i int) E { +func at[T interface{ ~[]E }, E interface{}](x T, i int) E { return x[i] } // A generic type inside a function acts like a named type. Its underlying // type is itself, its "operational type" is defined by the type list in // the tybe bound, if any. -func _[T interface{type int}](x T) { +func _[T interface{~int}](x T) { type myint int var _ int = int(x) var _ T = 42 @@ -203,24 +203,24 @@ func _[T interface{type int}](x T) { // Indexing a generic type with an array type bound checks length. // (Example by mdempsky@.) -func _[T interface { type [10]int }](x T) { +func _[T interface { ~[10]int }](x T) { _ = x[9] // ok _ = x[20 /* ERROR out of bounds */ ] } // Pointer indirection of a generic type. -func _[T interface{ type *int }](p T) int { +func _[T interface{ ~*int }](p T) int { return *p } // Channel sends and receives on generic types. -func _[T interface{ type chan int }](ch T) int { +func _[T interface{ ~chan int }](ch T) int { ch <- 0 return <- ch } // Calling of a generic variable. -func _[T interface{ type func() }](f T) { +func _[T interface{ ~func() }](f T) { f() go f() } @@ -232,7 +232,7 @@ func _[T interface{ type func() }](f T) { // type parameter that was substituted with a defined type. // Test case from an (originally) failing example. -type sliceOf[E any] interface{ type []E } +type sliceOf[E any] interface{ ~[]E } func append[T interface{}, S sliceOf[T], T2 interface{ T }](s S, t ...T2) S diff --git a/src/cmd/compile/internal/types2/testdata/check/linalg.go2 b/src/cmd/compile/internal/types2/testdata/check/linalg.go2 index 0d27603a58..efc090a1d1 100644 --- a/src/cmd/compile/internal/types2/testdata/check/linalg.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/linalg.go2 @@ -9,10 +9,10 @@ import "math" // Numeric is type bound that matches any numeric type. // It would likely be in a constraints package in the standard library. type Numeric interface { - type int, int8, int16, int32, int64, - uint, uint8, uint16, uint32, uint64, uintptr, - float32, float64, - complex64, complex128 + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 | + ~complex64 | ~complex128 } func DotProduct[T Numeric](s1, s2 []T) T { @@ -42,14 +42,14 @@ func AbsDifference[T NumericAbs[T]](a, b T) T { // OrderedNumeric is a type bound that matches numeric types that support the < operator. type OrderedNumeric interface { - type int, int8, int16, int32, int64, - uint, uint8, uint16, uint32, uint64, uintptr, - float32, float64 + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 } // Complex is a type bound that matches the two complex types, which do not have a < operator. type Complex interface { - type complex64, complex128 + ~complex64 | ~complex128 } // OrderedAbs is a helper type that defines an Abs method for diff --git a/src/cmd/compile/internal/types2/testdata/check/tinference.go2 b/src/cmd/compile/internal/types2/testdata/check/tinference.go2 index a53fde0a2a..2fdb39ca7a 100644 --- a/src/cmd/compile/internal/types2/testdata/check/tinference.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/tinference.go2 @@ -8,28 +8,28 @@ import "strconv" type any interface{} -func f0[A any, B interface{type C}, C interface{type D}, D interface{type A}](A, B, C, D) +func f0[A any, B interface{~C}, C interface{~D}, D interface{~A}](A, B, C, D) func _() { f := f0[string] f("a", "b", "c", "d") f0("a", "b", "c", "d") } -func f1[A any, B interface{type A}](A, B) +func f1[A any, B interface{~A}](A, B) func _() { f := f1[int] f(int(0), int(0)) f1(int(0), int(0)) } -func f2[A any, B interface{type []A}](A, B) +func f2[A any, B interface{~[]A}](A, B) func _() { f := f2[byte] f(byte(0), []byte{}) f2(byte(0), []byte{}) } -func f3[A any, B interface{type C}, C interface{type *A}](A, B, C) +func f3[A any, B interface{~C}, C interface{~*A}](A, B, C) func _() { f := f3[int] var x int @@ -37,7 +37,7 @@ func _() { f3(x, &x, &x) } -func f4[A any, B interface{type []C}, C interface{type *A}](A, B, C) +func f4[A any, B interface{~[]C}, C interface{~*A}](A, B, C) func _() { f := f4[int] var x int @@ -45,14 +45,14 @@ func _() { f4(x, []*int{}, &x) } -func f5[A interface{type struct{b B; c C}}, B any, C interface{type *B}](x B) A +func f5[A interface{~struct{b B; c C}}, B any, C interface{~*B}](x B) A func _() { x := f5(1.2) var _ float64 = x.b var _ float64 = *x.c } -func f6[A any, B interface{type struct{f []A}}](B) A +func f6[A any, B interface{~struct{f []A}}](B) A func _() { x := f6(struct{f []string}{}) var _ string = x @@ -60,11 +60,11 @@ func _() { // TODO(gri) Need to flag invalid recursive constraints. At the // moment these cause infinite recursions and stack overflow. -// func f7[A interface{type B}, B interface{type A}]() +// func f7[A interface{type B}, B interface{~A}]() // More realistic examples -func Double[S interface{ type []E }, E interface{ type int, int8, int16, int32, int64 }](s S) S { +func Double[S interface{ ~[]E }, E interface{ ~int | ~int8 | ~int16 | ~int32 | ~int64 }](s S) S { r := make(S, len(s)) for i, v := range s { r[i] = v + v @@ -80,7 +80,7 @@ var _ = Double(MySlice{1}) type Setter[B any] interface { Set(string) - type *B + ~*B } func FromStrings[T interface{}, PT Setter[T]](s []string) []T { diff --git a/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 b/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 index 1096bb42eb..37745dfcba 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 @@ -148,15 +148,15 @@ func _[T any](r R2[T, int], p *R2[string, T]) { p.pm() } -// An interface can (explicitly) declare at most one type list. +// It is ok to have multiple embedded unions. type _ interface { m0() - type int, string, bool - type /* ERROR multiple type lists */ float32, float64 + ~int | ~string | ~bool + ~float32 | ~float64 m1() m2() - type /* ERROR multiple type lists */ complex64, complex128 - type /* ERROR multiple type lists */ rune + ~complex64 | ~complex128 + ~rune } // Interface type lists may contain each type at most once. @@ -164,23 +164,24 @@ type _ interface { // for them to be all in a single list, and we report the error // as well.) type _ interface { - type int, int /* ERROR duplicate term int */ - type /* ERROR multiple type lists */ int /* ERROR duplicate term int */ + ~int|~int /* ERROR duplicate term int */ + ~int|int /* ERROR duplicate term int */ + int|int /* ERROR duplicate term int */ } type _ interface { - type struct{f int}, struct{g int}, struct /* ERROR duplicate term */ {f int} + ~struct{f int} | ~struct{g int} | ~struct /* ERROR duplicate term */ {f int} } // Interface type lists can contain any type, incl. *Named types. // Verify that we use the underlying type to compute the operational type. type MyInt int -func add1[T interface{type MyInt}](x T) T { +func add1[T interface{~MyInt}](x T) T { return x + 1 } type MyString string -func double[T interface{type MyInt, MyString}](x T) T { +func double[T interface{~MyInt | ~MyString}](x T) T { return x + x } @@ -189,15 +190,15 @@ func double[T interface{type MyInt, MyString}](x T) T { // type lists. type E0 interface { - type int, bool, string + ~int | ~bool | ~string } type E1 interface { - type int, float64, string + ~int | ~float64 | ~string } type E2 interface { - type float64 + ~float64 } type I0 interface { @@ -246,7 +247,7 @@ var _ = f12[float64] type I0_ interface { E0 - type int + ~int } func f0_[T I0_]() diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 index badda01105..4074ef17ea 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 @@ -52,22 +52,22 @@ func swapswap[A, B any](a A, b B) (A, B) { type F[A, B any] func(A, B) (B, A) -func min[T interface{ type int }](x, y T) T { +func min[T interface{ ~int }](x, y T) T { if x < y { return x } return y } -func _[T interface{type int, float32}](x, y T) bool { return x < y } +func _[T interface{~int | ~float32}](x, y T) bool { return x < y } func _[T any](x, y T) bool { return x /* ERROR cannot compare */ < y } -func _[T interface{type int, float32, bool}](x, y T) bool { return x /* ERROR cannot compare */ < y } +func _[T interface{~int | ~float32 | ~bool}](x, y T) bool { return x /* ERROR cannot compare */ < y } func _[T C1[T]](x, y T) bool { return x /* ERROR cannot compare */ < y } func _[T C2[T]](x, y T) bool { return x < y } type C1[T any] interface{} -type C2[T any] interface{ type int, float32 } +type C2[T any] interface{ ~int | ~float32 } func new[T any]() *T { var x T @@ -95,48 +95,48 @@ var _ = f3[int, rune, bool](1, struct{x rune}{}, nil) // indexing func _[T any] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } -func _[T interface{ type int }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } -func _[T interface{ type string }] (x T, i int) { _ = x[i] } -func _[T interface{ type []int }] (x T, i int) { _ = x[i] } -func _[T interface{ type [10]int, *[20]int, map[int]int }] (x T, i int) { _ = x[i] } -func _[T interface{ type string, []byte }] (x T, i int) { _ = x[i] } -func _[T interface{ type []int, [1]rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } -func _[T interface{ type string, []rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } +func _[T interface{ ~int }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } +func _[T interface{ ~string }] (x T, i int) { _ = x[i] } +func _[T interface{ ~[]int }] (x T, i int) { _ = x[i] } +func _[T interface{ ~[10]int | ~*[20]int | ~map[int]int }] (x T, i int) { _ = x[i] } +func _[T interface{ ~string | ~[]byte }] (x T, i int) { _ = x[i] } +func _[T interface{ ~[]int | ~[1]rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } +func _[T interface{ ~string | ~[]rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } // indexing with various combinations of map types in type lists (see issue #42616) -func _[T interface{ type []E, map[int]E }, E any](x T, i int) { _ = x[i] } -func _[T interface{ type []E }, E any](x T, i int) { _ = &x[i] } -func _[T interface{ type map[int]E }, E any](x T, i int) { _, _ = x[i] } // comma-ok permitted -func _[T interface{ type []E, map[int]E }, E any](x T, i int) { _ = &x /* ERROR cannot take address */ [i] } -func _[T interface{ type []E, map[int]E, map[uint]E }, E any](x T, i int) { _ = x /* ERROR cannot index */ [i] } // different map element types -func _[T interface{ type []E, map[string]E }, E any](x T, i int) { _ = x[i /* ERROR cannot use i */ ] } +func _[T interface{ ~[]E | ~map[int]E }, E any](x T, i int) { _ = x[i] } +func _[T interface{ ~[]E }, E any](x T, i int) { _ = &x[i] } +func _[T interface{ ~map[int]E }, E any](x T, i int) { _, _ = x[i] } // comma-ok permitted +func _[T interface{ ~[]E | ~map[int]E }, E any](x T, i int) { _ = &x /* ERROR cannot take address */ [i] } +func _[T interface{ ~[]E | ~map[int]E | ~map[uint]E }, E any](x T, i int) { _ = x /* ERROR cannot index */ [i] } // different map element types +func _[T interface{ ~[]E | ~map[string]E }, E any](x T, i int) { _ = x[i /* ERROR cannot use i */ ] } // slicing // TODO(gri) implement this -func _[T interface{ type string }] (x T, i, j, k int) { _ = x /* ERROR invalid operation */ [i:j:k] } +func _[T interface{ ~string }] (x T, i, j, k int) { _ = x /* ERROR invalid operation */ [i:j:k] } // len/cap built-ins func _[T any](x T) { _ = len(x /* ERROR invalid argument */ ) } -func _[T interface{ type int }](x T) { _ = len(x /* ERROR invalid argument */ ) } -func _[T interface{ type string, []byte, int }](x T) { _ = len(x /* ERROR invalid argument */ ) } -func _[T interface{ type string }](x T) { _ = len(x) } -func _[T interface{ type [10]int }](x T) { _ = len(x) } -func _[T interface{ type []byte }](x T) { _ = len(x) } -func _[T interface{ type map[int]int }](x T) { _ = len(x) } -func _[T interface{ type chan int }](x T) { _ = len(x) } -func _[T interface{ type string, []byte, chan int }](x T) { _ = len(x) } +func _[T interface{ ~int }](x T) { _ = len(x /* ERROR invalid argument */ ) } +func _[T interface{ ~string | ~[]byte | ~int }](x T) { _ = len(x /* ERROR invalid argument */ ) } +func _[T interface{ ~string }](x T) { _ = len(x) } +func _[T interface{ ~[10]int }](x T) { _ = len(x) } +func _[T interface{ ~[]byte }](x T) { _ = len(x) } +func _[T interface{ ~map[int]int }](x T) { _ = len(x) } +func _[T interface{ ~chan int }](x T) { _ = len(x) } +func _[T interface{ ~string | ~[]byte | ~chan int }](x T) { _ = len(x) } func _[T any](x T) { _ = cap(x /* ERROR invalid argument */ ) } -func _[T interface{ type int }](x T) { _ = cap(x /* ERROR invalid argument */ ) } -func _[T interface{ type string, []byte, int }](x T) { _ = cap(x /* ERROR invalid argument */ ) } -func _[T interface{ type string }](x T) { _ = cap(x /* ERROR invalid argument */ ) } -func _[T interface{ type [10]int }](x T) { _ = cap(x) } -func _[T interface{ type []byte }](x T) { _ = cap(x) } -func _[T interface{ type map[int]int }](x T) { _ = cap(x /* ERROR invalid argument */ ) } -func _[T interface{ type chan int }](x T) { _ = cap(x) } -func _[T interface{ type []byte, chan int }](x T) { _ = cap(x) } +func _[T interface{ ~int }](x T) { _ = cap(x /* ERROR invalid argument */ ) } +func _[T interface{ ~string | ~[]byte | ~int }](x T) { _ = cap(x /* ERROR invalid argument */ ) } +func _[T interface{ ~string }](x T) { _ = cap(x /* ERROR invalid argument */ ) } +func _[T interface{ ~[10]int }](x T) { _ = cap(x) } +func _[T interface{ ~[]byte }](x T) { _ = cap(x) } +func _[T interface{ ~map[int]int }](x T) { _ = cap(x /* ERROR invalid argument */ ) } +func _[T interface{ ~chan int }](x T) { _ = cap(x) } +func _[T interface{ ~[]byte | ~chan int }](x T) { _ = cap(x) } // range iteration @@ -144,7 +144,7 @@ func _[T interface{}](x T) { for range x /* ERROR cannot range */ {} } -func _[T interface{ type string, []string }](x T) { +func _[T interface{ ~string | ~[]string }](x T) { for range x {} for i := range x { _ = i } for i, _ := range x { _ = i } @@ -156,23 +156,23 @@ func _[T interface{ type string, []string }](x T) { } -func _[T interface{ type string, []rune, map[int]rune }](x T) { +func _[T interface{ ~string | ~[]rune | ~map[int]rune }](x T) { for _, e := range x { _ = e } for i, e := range x { _ = i; _ = e } } -func _[T interface{ type string, []rune, map[string]rune }](x T) { +func _[T interface{ ~string | ~[]rune | ~map[string]rune }](x T) { for _, e := range x { _ = e } for i, e := range x /* ERROR must have the same key type */ { _ = e } } -func _[T interface{ type string, chan int }](x T) { +func _[T interface{ ~string | ~chan int }](x T) { for range x {} for i := range x { _ = i } for i, _ := range x { _ = i } // TODO(gri) should get an error here: channels only return one value } -func _[T interface{ type string, chan<-int }](x T) { +func _[T interface{ ~string | ~chan<-int }](x T) { for i := range x /* ERROR send-only channel */ { _ = i } } @@ -400,7 +400,7 @@ func _[T any](x T) { } } -func _[T interface{type int}](x T) { +func _[T interface{~int}](x T) { _ = x /* ERROR not an interface */ .(int) switch x /* ERROR not an interface */ .(type) { } -- GitLab From 10d6b36ca3f8d48a667742eee791dacbcfc888cd Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 2 Jun 2021 17:05:37 -0700 Subject: [PATCH 0188/2500] [dev.typeparams] cmd/compile/internal/types2: disallow ~T where T is a defined type or an interface Change-Id: I35f6f43db00d56847da48320308f2fcfff924738 Reviewed-on: https://go-review.googlesource.com/c/go/+/324570 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- .../internal/types2/testdata/check/typeinst2.go2 | 4 ++-- .../internal/types2/testdata/examples/constraints.go2 | 9 +++++++++ .../internal/types2/testdata/fixedbugs/issue39634.go2 | 4 ++-- src/cmd/compile/internal/types2/union.go | 11 ++++++----- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 b/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 index 37745dfcba..14d8f0ea8c 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 @@ -176,12 +176,12 @@ type _ interface { // Interface type lists can contain any type, incl. *Named types. // Verify that we use the underlying type to compute the operational type. type MyInt int -func add1[T interface{~MyInt}](x T) T { +func add1[T interface{MyInt}](x T) T { return x + 1 } type MyString string -func double[T interface{~MyInt | ~MyString}](x T) T { +func double[T interface{MyInt|MyString}](x T) T { return x + x } diff --git a/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 b/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 index f6291ccf7d..efefaa2a25 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 @@ -24,6 +24,15 @@ type ( _ interface{int|interface /* ERROR cannot use interface */ {}} ) +type ( + // Tilde is not permitted on defined types or interfaces. + foo int + bar interface{} + _ interface{foo} + _ interface{~ /* ERROR invalid use of ~ */ foo } + _ interface{~ /* ERROR invalid use of ~ */ bar } +) + // Multiple embedded union elements are intersected. The order in which they // appear in the interface doesn't matter since intersection is a symmetric // operation. diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 index 39ec5d7b30..6d002f5d2f 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 @@ -36,8 +36,8 @@ func bar8[A foo8[A]](a A) {} func main8() {} // crash 9 -type foo9[A any] interface { ~/* ERROR cannot use interface */ foo9[A] } -func _() { var _ = new(foo9 /* ERROR interface contains type constraints */ [int]) } +type foo9[A any] interface { foo9 /* ERROR illegal cycle */ [A] } +func _() { var _ = new(foo9 /* ERROR illegal cycle */ [int]) } // crash 12 var u /* ERROR cycle */ , i [func /* ERROR used as value */ /* ERROR used as value */ (u, c /* ERROR undeclared */ /* ERROR undeclared */ ) {}(0, len /* ERROR must be called */ /* ERROR must be called */ )]c /* ERROR undeclared */ /* ERROR undeclared */ diff --git a/src/cmd/compile/internal/types2/union.go b/src/cmd/compile/internal/types2/union.go index 671e36111b..30570b5e80 100644 --- a/src/cmd/compile/internal/types2/union.go +++ b/src/cmd/compile/internal/types2/union.go @@ -106,17 +106,18 @@ func parseUnion(check *Checker, tlist []syntax.Expr) Type { } u := under(t) - if tilde[i] { - // TODO(gri) enable this check once we have converted tests - // if !Identical(u, t) { - // check.errorf(x, "invalid use of ~ (underlying type of %s is %s)", t, u) - // } + if tilde[i] && !Identical(u, t) { + check.errorf(x, "invalid use of ~ (underlying type of %s is %s)", t, u) + continue // don't report another error for t } if _, ok := u.(*Interface); ok { + // A single type with a ~ is a single-term union. check.errorf(pos, "cannot use interface %s with ~ or inside a union (implementation restriction)", t) + continue // don't report another error for t } // Complain about duplicate entries a|a, but also a|~a, and ~a|~a. + // TODO(gri) We should also exclude myint|~int since myint is included in ~int. if includes(types[:i], t) { // TODO(gri) this currently doesn't print the ~ if present check.softErrorf(pos, "duplicate term %s in union element", t) -- GitLab From 95c618e99a3f733543fd36ef19e833d04acc8710 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 2 Jun 2021 17:50:47 -0700 Subject: [PATCH 0189/2500] [dev.typeparams] cmd/compile/internal/types2: add Config.AllowTypeLists to control type list handling Eventually the flag should not be set anymore, but we set it in the compiler until all tests have been converted. Also, convert some more types2 tests to use the type set notation. Change-Id: I616599a3473451ab75d67272016b2bd3de6835af Reviewed-on: https://go-review.googlesource.com/c/go/+/324571 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/noder/irgen.go | 1 + src/cmd/compile/internal/types2/api.go | 6 ++++++ src/cmd/compile/internal/types2/api_test.go | 16 ++++++++-------- src/cmd/compile/internal/types2/interface.go | 11 +++++++++-- .../types2/testdata/examples/constraints.go2 | 12 ++++++++++++ .../compile/internal/types2/typestring_test.go | 1 - 6 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index 3f362e9d2b..b70d82d7e6 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -38,6 +38,7 @@ func checkFiles(noders []*noder, importer types2.Importer) (posMap, *types2.Pack GoVersion: base.Flag.Lang, IgnoreLabels: true, // parser already checked via syntax.CheckBranches mode CompilerErrorMessages: true, // use error strings matching existing compiler errors + AllowTypeLists: true, // remove this line once all tests use type set syntax Error: func(err error) { terr := err.(types2.Error) base.ErrorfAt(m.makeXPos(terr.Pos), "%s", terr.Msg) diff --git a/src/cmd/compile/internal/types2/api.go b/src/cmd/compile/internal/types2/api.go index 2939dcc0bd..433250f02c 100644 --- a/src/cmd/compile/internal/types2/api.go +++ b/src/cmd/compile/internal/types2/api.go @@ -125,6 +125,12 @@ type Config struct { // TODO(gri) Consolidate error messages and remove this flag. CompilerErrorMessages bool + // If AllowTypeLists is set, the type list syntax is permitted + // in an interface in addition to the type set syntax. + // TODO(gri) Remove once type lists are no longer supported by + // the parser. + AllowTypeLists bool + // If go115UsesCgo is set, the type checker expects the // _cgo_gotypes.go file generated by running cmd/cgo to be // provided as a package source file. Qualified identifiers diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index d82d29cad8..49d710067a 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -345,7 +345,7 @@ func TestTypesInfo(t *testing.T) { {genericPkg + `g0; type t[P any] int; var x struct{ f t[int] }; var _ = x.f`, `x.f`, `generic_g0.t[int]`}, // issue 45096 - {genericPkg + `issue45096; func _[T interface{ type int8, int16, int32 }](x T) { _ = x < 0 }`, `0`, `generic_issue45096.T₁`}, + {genericPkg + `issue45096; func _[T interface{ ~int8 | ~int16 | ~int32 }](x T) { _ = x < 0 }`, `0`, `generic_issue45096.T₁`}, } for _, test := range tests { @@ -454,38 +454,38 @@ func TestInferredInfo(t *testing.T) { // `func(float64)`, // }, - {genericPkg + `s1; func f[T any, P interface{type *T}](x T); func _(x string) { f(x) }`, + {genericPkg + `s1; func f[T any, P interface{~*T}](x T); func _(x string) { f(x) }`, `f`, []string{`string`, `*string`}, `func(x string)`, }, - {genericPkg + `s2; func f[T any, P interface{type *T}](x []T); func _(x []int) { f(x) }`, + {genericPkg + `s2; func f[T any, P interface{~*T}](x []T); func _(x []int) { f(x) }`, `f`, []string{`int`, `*int`}, `func(x []int)`, }, - {genericPkg + `s3; type C[T any] interface{type chan<- T}; func f[T any, P C[T]](x []T); func _(x []int) { f(x) }`, + {genericPkg + `s3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]](x []T); func _(x []int) { f(x) }`, `f`, []string{`int`, `chan<- int`}, `func(x []int)`, }, - {genericPkg + `s4; type C[T any] interface{type chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T); func _(x []int) { f(x) }`, + {genericPkg + `s4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T); func _(x []int) { f(x) }`, `f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func(x []int)`, }, - {genericPkg + `t1; func f[T any, P interface{type *T}]() T; func _() { _ = f[string] }`, + {genericPkg + `t1; func f[T any, P interface{~*T}]() T; func _() { _ = f[string] }`, `f`, []string{`string`, `*string`}, `func() string`, }, - {genericPkg + `t2; type C[T any] interface{type chan<- T}; func f[T any, P C[T]]() []T; func _() { _ = f[int] }`, + {genericPkg + `t2; type C[T any] interface{~chan<- T}; func f[T any, P C[T]]() []T; func _() { _ = f[int] }`, `f`, []string{`int`, `chan<- int`}, `func() []int`, }, - {genericPkg + `t3; type C[T any] interface{type chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T; func _() { _ = f[int] }`, + {genericPkg + `t3; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T; func _() { _ = f[int] }`, `f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func() []int`, diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index 770b8ba5cc..c79026f00d 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -34,18 +34,25 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType continue // ignore } + // TODO(gri) Remove type list handling once the parser doesn't accept type lists anymore. if name == "type" { + // Report an error for the first type list per interface + // if we don't allow type lists, but continue. + if !check.conf.AllowTypeLists && tlist == nil { + check.softErrorf(f.Name, "use generalized embedding syntax instead of a type list") + } // For now, collect all type list entries as if it // were a single union, where each union element is // of the form ~T. - // TODO(gri) remove once we disallow type lists op := new(syntax.Operation) // We should also set the position (but there is no setter); // we don't care because this code will eventually go away. op.Op = syntax.Tilde op.X = f.Type tlist = append(tlist, op) - if tname != nil && tname != f.Name { + // Report an error if we have multiple type lists in an + // interface, but only if they are permitted in the first place. + if check.conf.AllowTypeLists && tname != nil && tname != f.Name { check.error(f.Name, "cannot have multiple type lists in an interface") } tname = f.Name diff --git a/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 b/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 index efefaa2a25..d9805fe694 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 @@ -6,6 +6,18 @@ package p +type ( + // Type lists are processed as unions but an error is reported. + // TODO(gri) remove this once the parser doesn't accept type lists anymore. + _ interface{ + type /* ERROR use generalized embedding syntax instead of a type list */ int + } + _ interface{ + type /* ERROR use generalized embedding syntax instead of a type list */ int + type float32 + } +) + type ( // Arbitrary types may be embedded like interfaces. _ interface{int} diff --git a/src/cmd/compile/internal/types2/typestring_test.go b/src/cmd/compile/internal/types2/typestring_test.go index 8d0ca760bf..88103b81b1 100644 --- a/src/cmd/compile/internal/types2/typestring_test.go +++ b/src/cmd/compile/internal/types2/typestring_test.go @@ -91,7 +91,6 @@ var independentTestTypes = []testEntry{ dup("interface{}"), dup("interface{m()}"), dup(`interface{String() string; m(int) float32}`), - {"interface{type int, float32, complex128}", "interface{~int|~float32|~complex128}"}, dup("interface{int|float32|complex128}"), dup("interface{int|~float32|~complex128}"), -- GitLab From 9c054f413751fdec62aa33df19ec1249426767ee Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 1 Jun 2021 19:16:33 -0400 Subject: [PATCH 0190/2500] [dev.typeparams] cmd/link: take function address in assembly in TestFuncAlign In TestFuncAlign we want to get the address of an assembly function. Take the address in assembly, so we get the actual function's address, not the wrapper's. Change-Id: Idc1fe2c8426562c70f8f7d6e489584ef059bc556 Reviewed-on: https://go-review.googlesource.com/c/go/+/324249 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/link/link_test.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go index 4d6bc76aca..4a580991ef 100644 --- a/src/cmd/link/link_test.go +++ b/src/cmd/link/link_test.go @@ -524,14 +524,13 @@ const testFuncAlignSrc = ` package main import ( "fmt" - "reflect" ) func alignPc() +var alignPcFnAddr uintptr func main() { - addr := reflect.ValueOf(alignPc).Pointer() - if (addr % 512) != 0 { - fmt.Printf("expected 512 bytes alignment, got %v\n", addr) + if alignPcFnAddr % 512 != 0 { + fmt.Printf("expected 512 bytes alignment, got %v\n", alignPcFnAddr) } else { fmt.Printf("PASS") } @@ -546,6 +545,9 @@ TEXT ·alignPc(SB),NOSPLIT, $0-0 PCALIGN $512 MOVD $3, R1 RET + +GLOBL ·alignPcFnAddr(SB),RODATA,$8 +DATA ·alignPcFnAddr(SB)/8,$·alignPc(SB) ` // TestFuncAlign verifies that the address of a function can be aligned -- GitLab From b5f37faf3b0fa4c8ae24461bf99cdc0f1f583fa3 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 1 Jun 2021 19:18:25 -0400 Subject: [PATCH 0191/2500] [dev.typeparams] cmd/internal/goobj: add duffzero/duffcopy to builtin list duffzero and duffcopy are commonly referenced functions. Add them to builtin list, so they are referenced by index, not by name. Also change gcWriteBarrier to ABIInternal, which is changed in CL 266638. Regenerate the file. Change-Id: If8550d9ed300ac2be930a7c58657a9cf1933ac1d Reviewed-on: https://go-review.googlesource.com/c/go/+/324250 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/internal/goobj/builtinlist.go | 7 ++++++- src/cmd/internal/goobj/mkbuiltin.go | 4 +++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/cmd/internal/goobj/builtinlist.go b/src/cmd/internal/goobj/builtinlist.go index 9f248137da..608c0d7222 100644 --- a/src/cmd/internal/goobj/builtinlist.go +++ b/src/cmd/internal/goobj/builtinlist.go @@ -33,6 +33,7 @@ var builtins = [...]struct { {"runtime.goPanicSlice3BU", 1}, {"runtime.goPanicSlice3C", 1}, {"runtime.goPanicSlice3CU", 1}, + {"runtime.goPanicSliceConvert", 1}, {"runtime.printbool", 1}, {"runtime.printfloat", 1}, {"runtime.printint", 1}, @@ -129,6 +130,8 @@ var builtins = [...]struct { {"runtime.makeslice64", 1}, {"runtime.makeslicecopy", 1}, {"runtime.growslice", 1}, + {"runtime.unsafeslice", 1}, + {"runtime.unsafeslice64", 1}, {"runtime.memmove", 1}, {"runtime.memclrNoHeapPointers", 1}, {"runtime.memclrHasPointers", 1}, @@ -203,7 +206,9 @@ var builtins = [...]struct { {"runtime.newproc", 1}, {"runtime.panicoverflow", 1}, {"runtime.sigpanic", 1}, - {"runtime.gcWriteBarrier", 0}, + {"runtime.gcWriteBarrier", 1}, + {"runtime.duffzero", 1}, + {"runtime.duffcopy", 1}, {"runtime.morestack", 0}, {"runtime.morestackc", 0}, {"runtime.morestack_noctxt", 0}, diff --git a/src/cmd/internal/goobj/mkbuiltin.go b/src/cmd/internal/goobj/mkbuiltin.go index 18b969586c..c9995fcede 100644 --- a/src/cmd/internal/goobj/mkbuiltin.go +++ b/src/cmd/internal/goobj/mkbuiltin.go @@ -151,7 +151,9 @@ var fextras = [...]extra{ {"sigpanic", 1}, // compiler backend inserted calls - {"gcWriteBarrier", 0}, // asm function, ABI0 + {"gcWriteBarrier", 1}, + {"duffzero", 1}, + {"duffcopy", 1}, // assembler backend inserted calls {"morestack", 0}, // asm function, ABI0 -- GitLab From 165d39a1d460880f2d28619a4609f272448b0d60 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 1 Jun 2021 19:29:24 -0400 Subject: [PATCH 0192/2500] [dev.typeparams] test: adjust codegen test for register ABI on ARM64 In codegen/arithmetic.go, previously there are MOVD's that match for loads of arguments. With register ABI there are no more such loads. Remove the MOVD matches. Change-Id: I920ee2629c8c04d454f13a0c08e283d3528d9a64 Reviewed-on: https://go-review.googlesource.com/c/go/+/324251 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- test/codegen/arithmetic.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/codegen/arithmetic.go b/test/codegen/arithmetic.go index a27a17f6e1..eb0f338036 100644 --- a/test/codegen/arithmetic.go +++ b/test/codegen/arithmetic.go @@ -202,7 +202,7 @@ func ConstDivs(n1 uint, n2 int) (uint, int) { // amd64:"MOVQ\t[$]-1085102592571150095","IMULQ",-"IDIVQ" // 386:"MOVL\t[$]-252645135","IMULL",-"IDIVL" - // arm64:`MOVD`,`SMULH`,-`DIV` + // arm64:`SMULH`,-`DIV` // arm:`MOVW`,`MUL`,-`.*udiv` b := n2 / 17 // signed @@ -266,7 +266,7 @@ func ConstMods(n1 uint, n2 int) (uint, int) { // amd64:"MOVQ\t[$]-1085102592571150095","IMULQ",-"IDIVQ" // 386:"MOVL\t[$]-252645135","IMULL",-"IDIVL" - // arm64:`MOVD`,`SMULH`,-`DIV` + // arm64:`SMULH`,-`DIV` // arm:`MOVW`,`MUL`,-`.*udiv` b := n2 % 17 // signed -- GitLab From 5a008a92e84f05e79fbe9fd8ab283bcee95d54ee Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 2 Jun 2021 18:00:12 -0400 Subject: [PATCH 0193/2500] [dev.typeparams] internal/bytealg: call memeqbody directly in memequal_varlen on ARM64 Currently, memequal_varlen opens up a frame and call memequal, which then tail-calls memeqbody. This CL changes memequal_varlen tail-calls memeqbody directly. This makes it simpler to switch to the register ABI in the next CL. Change-Id: Ia1367c0abb7f4755fe736c404411793fb9e5c04f Reviewed-on: https://go-review.googlesource.com/c/go/+/324399 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/internal/bytealg/equal_arm64.s | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/internal/bytealg/equal_arm64.s b/src/internal/bytealg/equal_arm64.s index 01aa7b7b7a..944edd8768 100644 --- a/src/internal/bytealg/equal_arm64.s +++ b/src/internal/bytealg/equal_arm64.s @@ -20,20 +20,15 @@ equal: RET // memequal_varlen(a, b unsafe.Pointer) bool -TEXT runtime·memequal_varlen(SB),NOSPLIT,$40-17 - MOVD a+0(FP), R3 - MOVD b+8(FP), R4 - CMP R3, R4 +TEXT runtime·memequal_varlen(SB),NOSPLIT,$0-17 + MOVD a+0(FP), R0 + MOVD b+8(FP), R2 + CMP R0, R2 BEQ eq - MOVD 8(R26), R5 // compiler stores size at offset 8 in the closure - CBZ R5, eq - MOVD R3, 8(RSP) - MOVD R4, 16(RSP) - MOVD R5, 24(RSP) - BL runtime·memequal(SB) - MOVBU 32(RSP), R3 - MOVB R3, ret+16(FP) - RET + MOVD 8(R26), R1 // compiler stores size at offset 8 in the closure + CBZ R1, eq + MOVD $ret+16(FP), R8 + B memeqbody<>(SB) eq: MOVD $1, R3 MOVB R3, ret+16(FP) -- GitLab From 370ff5ff96cf02dfbbc33b70934219367fa700bb Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 2 Jun 2021 18:12:14 -0700 Subject: [PATCH 0194/2500] [dev.typeparams] test: update all the typeparam tests to use the new union/tilde syntax Did a mix of tilde and non-tilde usage. Tilde notation is not quite fully functional, so no tests are currently trying to distinguish (fail/not fail) based on tilde usage. Change-Id: Ib50cec2fc0684f9d9f3561c889fd44c7a7af458c Reviewed-on: https://go-review.googlesource.com/c/go/+/324572 Trust: Dan Scales Trust: Robert Griesemer Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- test/typeparam/absdiff.go | 16 ++++++++-------- test/typeparam/adder.go | 2 +- test/typeparam/double.go | 2 +- test/typeparam/fact.go | 2 +- test/typeparam/factimp.dir/a.go | 2 +- test/typeparam/list.go | 14 +++++++------- test/typeparam/listimp.dir/a.go | 14 +++++++------- test/typeparam/min.go | 2 +- test/typeparam/mincheck.dir/a.go | 2 +- test/typeparam/minimp.dir/a.go | 2 +- test/typeparam/ordered.go | 8 ++++---- test/typeparam/orderedmap.go | 8 ++++---- test/typeparam/sliceimp.dir/a.go | 8 ++++---- test/typeparam/sliceimp.dir/main.go | 4 ++-- test/typeparam/slices.go | 12 ++++++------ test/typeparam/smallest.go | 8 ++++---- test/typeparam/smoketest.go | 2 +- test/typeparam/sum.go | 2 +- 18 files changed, 55 insertions(+), 55 deletions(-) diff --git a/test/typeparam/absdiff.go b/test/typeparam/absdiff.go index 1381d7c92c..ecaa907795 100644 --- a/test/typeparam/absdiff.go +++ b/test/typeparam/absdiff.go @@ -12,10 +12,10 @@ import ( ) type Numeric interface { - type int, int8, int16, int32, int64, - uint, uint8, uint16, uint32, uint64, uintptr, - float32, float64, - complex64, complex128 + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 | + ~complex64 | ~complex128 } // numericAbs matches numeric types with an Abs method. @@ -33,14 +33,14 @@ func absDifference[T numericAbs[T]](a, b T) T { // orderedNumeric matches numeric types that support the < operator. type orderedNumeric interface { - type int, int8, int16, int32, int64, - uint, uint8, uint16, uint32, uint64, uintptr, - float32, float64 + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 } // Complex matches the two complex types, which do not have a < operator. type Complex interface { - type complex64, complex128 + ~complex64 | ~complex128 } // orderedAbs is a helper type that defines an Abs method for diff --git a/test/typeparam/adder.go b/test/typeparam/adder.go index eb564b5bd5..79319bd236 100644 --- a/test/typeparam/adder.go +++ b/test/typeparam/adder.go @@ -11,7 +11,7 @@ import ( ) type AddType interface { - type int, int64, string + int | int64 | string } // Add can add numbers or strings diff --git a/test/typeparam/double.go b/test/typeparam/double.go index ce78ec9748..6652613814 100644 --- a/test/typeparam/double.go +++ b/test/typeparam/double.go @@ -12,7 +12,7 @@ import ( ) type Number interface { - type int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, float32, float64 + ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | ~float32 | ~float64 } type MySlice []int diff --git a/test/typeparam/fact.go b/test/typeparam/fact.go index ea86ae3e02..baa7fbc68e 100644 --- a/test/typeparam/fact.go +++ b/test/typeparam/fact.go @@ -8,7 +8,7 @@ package main import "fmt" -func fact[T interface { type int, int64, float64 }](n T) T { +func fact[T interface { ~int | ~int64 | ~float64 }](n T) T { if n == 1 { return 1 } diff --git a/test/typeparam/factimp.dir/a.go b/test/typeparam/factimp.dir/a.go index 3552474382..cb1ff2615b 100644 --- a/test/typeparam/factimp.dir/a.go +++ b/test/typeparam/factimp.dir/a.go @@ -4,7 +4,7 @@ package a -func Fact[T interface { type int, int64, float64 }](n T) T { +func Fact[T interface { int | int64 | float64 }](n T) T { if n == 1 { return 1 } diff --git a/test/typeparam/list.go b/test/typeparam/list.go index 579078f02f..c63c9bff79 100644 --- a/test/typeparam/list.go +++ b/test/typeparam/list.go @@ -11,10 +11,10 @@ import ( ) type Ordered interface { - type int, int8, int16, int32, int64, - uint, uint8, uint16, uint32, uint64, uintptr, - float32, float64, - string + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 | + ~string } // _List is a linked list of ordered values of type T. @@ -34,9 +34,9 @@ func (l *_List[T]) Largest() T { } type OrderedNum interface { - type int, int8, int16, int32, int64, - uint, uint8, uint16, uint32, uint64, uintptr, - float32, float64 + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 } // _ListNum is a linked _List of ordered numeric values of type T. diff --git a/test/typeparam/listimp.dir/a.go b/test/typeparam/listimp.dir/a.go index 0a4634b7be..2b5b23cde3 100644 --- a/test/typeparam/listimp.dir/a.go +++ b/test/typeparam/listimp.dir/a.go @@ -5,10 +5,10 @@ package a type Ordered interface { - type int, int8, int16, int32, int64, - uint, uint8, uint16, uint32, uint64, uintptr, - float32, float64, - string + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 | + ~string } // List is a linked list of ordered values of type T. @@ -28,9 +28,9 @@ func (l *List[T]) Largest() T { } type OrderedNum interface { - type int, int8, int16, int32, int64, - uint, uint8, uint16, uint32, uint64, uintptr, - float32, float64 + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 } // ListNum is a linked _List of ordered numeric values of type T. diff --git a/test/typeparam/min.go b/test/typeparam/min.go index 6e28c062a8..d6c65d68b7 100644 --- a/test/typeparam/min.go +++ b/test/typeparam/min.go @@ -11,7 +11,7 @@ import ( ) type Ordered interface { - type int, int64, float64, string + ~int | ~int64 | ~float64 | ~string } func min[T Ordered](x, y T) T { diff --git a/test/typeparam/mincheck.dir/a.go b/test/typeparam/mincheck.dir/a.go index f1844bba9d..7d42492b74 100644 --- a/test/typeparam/mincheck.dir/a.go +++ b/test/typeparam/mincheck.dir/a.go @@ -5,7 +5,7 @@ package a type Ordered interface { - type int, int64, float64 + int | int64 | float64 } func Min[T Ordered](x, y T) T { diff --git a/test/typeparam/minimp.dir/a.go b/test/typeparam/minimp.dir/a.go index 16c1b035f4..6c3e0eba36 100644 --- a/test/typeparam/minimp.dir/a.go +++ b/test/typeparam/minimp.dir/a.go @@ -5,7 +5,7 @@ package a type Ordered interface { - type int, int64, float64, string + ~int | ~int64 | ~float64 | ~string } func Min[T Ordered](x, y T) T { diff --git a/test/typeparam/ordered.go b/test/typeparam/ordered.go index 448db68bb5..699505ec75 100644 --- a/test/typeparam/ordered.go +++ b/test/typeparam/ordered.go @@ -13,10 +13,10 @@ import ( ) type Ordered interface { - type int, int8, int16, int32, int64, - uint, uint8, uint16, uint32, uint64, uintptr, - float32, float64, - string + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 | + ~string } type orderedSlice[Elem Ordered] []Elem diff --git a/test/typeparam/orderedmap.go b/test/typeparam/orderedmap.go index db1b374267..6a895bd396 100644 --- a/test/typeparam/orderedmap.go +++ b/test/typeparam/orderedmap.go @@ -15,10 +15,10 @@ import ( ) type Ordered interface { - type int, int8, int16, int32, int64, - uint, uint8, uint16, uint32, uint64, uintptr, - float32, float64, - string + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 | + ~string } // _Map is an ordered map. diff --git a/test/typeparam/sliceimp.dir/a.go b/test/typeparam/sliceimp.dir/a.go index 2b58d1c29e..61b1b17a98 100644 --- a/test/typeparam/sliceimp.dir/a.go +++ b/test/typeparam/sliceimp.dir/a.go @@ -5,10 +5,10 @@ package a type Ordered interface { - type int, int8, int16, int32, int64, - uint, uint8, uint16, uint32, uint64, uintptr, - float32, float64, - string + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 | + ~string } // Max returns the maximum of two values of some ordered type. diff --git a/test/typeparam/sliceimp.dir/main.go b/test/typeparam/sliceimp.dir/main.go index 0a8e756b26..2d4d3b2831 100644 --- a/test/typeparam/sliceimp.dir/main.go +++ b/test/typeparam/sliceimp.dir/main.go @@ -12,8 +12,8 @@ import ( ) type Integer interface { - type int, int8, int16, int32, int64, - uint, uint8, uint16, uint32, uint64, uintptr + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr } func TestEqual() { diff --git a/test/typeparam/slices.go b/test/typeparam/slices.go index 149199eb64..50783a5439 100644 --- a/test/typeparam/slices.go +++ b/test/typeparam/slices.go @@ -15,15 +15,15 @@ import ( ) type Ordered interface { - type int, int8, int16, int32, int64, - uint, uint8, uint16, uint32, uint64, uintptr, - float32, float64, - string + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 | + ~string } type Integer interface { - type int, int8, int16, int32, int64, - uint, uint8, uint16, uint32, uint64, uintptr + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr } // Max returns the maximum of two values of some ordered type. diff --git a/test/typeparam/smallest.go b/test/typeparam/smallest.go index d851536049..3fead6a067 100644 --- a/test/typeparam/smallest.go +++ b/test/typeparam/smallest.go @@ -11,10 +11,10 @@ import ( ) type Ordered interface { - type int, int8, int16, int32, int64, - uint, uint8, uint16, uint32, uint64, uintptr, - float32, float64, - string + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 | + ~string } func Smallest[T Ordered](s []T) T { diff --git a/test/typeparam/smoketest.go b/test/typeparam/smoketest.go index b7d6201b2c..d92e02713d 100644 --- a/test/typeparam/smoketest.go +++ b/test/typeparam/smoketest.go @@ -37,7 +37,7 @@ func (x T2[P1, P2, P3]) m() {} type _ interface { m1() m2() - type int, float32, string + int | float32 | string m3() } diff --git a/test/typeparam/sum.go b/test/typeparam/sum.go index c82d8e4c61..53e6face11 100644 --- a/test/typeparam/sum.go +++ b/test/typeparam/sum.go @@ -10,7 +10,7 @@ import ( "fmt" ) -func Sum[T interface{ type int, float64 }](vec []T) T { +func Sum[T interface{ int | float64 }](vec []T) T { var sum T for _, elt := range vec { sum = sum + elt -- GitLab From 5a40fab19fd615aa879e8f499a63e31d98257886 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 2 Jun 2021 17:30:58 -0400 Subject: [PATCH 0195/2500] [dev.typeparams] runtime, internal/bytealg: port performance-critical functions to register ABI on ARM64 This CL ports a few performance-critical assembly functions to use register arguments directly. This is similar to CL 308931 and CL 310184. Change-Id: I6e30dfff17f76b8578ce8cfd51de21b66610fdb0 Reviewed-on: https://go-review.googlesource.com/c/go/+/324400 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: Than McIntosh Reviewed-by: Michael Knyszek TryBot-Result: Go Bot --- src/internal/bytealg/compare_arm64.s | 113 ++++++++++++-------- src/internal/bytealg/equal_arm64.s | 93 ++++++++++------- src/runtime/asm_arm64.s | 150 ++++++++++++++++++--------- src/runtime/memclr_arm64.s | 4 +- src/runtime/memmove_arm64.s | 4 +- 5 files changed, 233 insertions(+), 131 deletions(-) diff --git a/src/internal/bytealg/compare_arm64.s b/src/internal/bytealg/compare_arm64.s index 56d56f241e..5a80207258 100644 --- a/src/internal/bytealg/compare_arm64.s +++ b/src/internal/bytealg/compare_arm64.s @@ -5,65 +5,88 @@ #include "go_asm.h" #include "textflag.h" -TEXT ·Compare(SB),NOSPLIT|NOFRAME,$0-56 - MOVD a_base+0(FP), R2 - MOVD a_len+8(FP), R0 - MOVD b_base+24(FP), R3 - MOVD b_len+32(FP), R1 +TEXT ·Compare(SB),NOSPLIT|NOFRAME,$0-56 +#ifdef GOEXPERIMENT_regabiargs + // R0 = a_base (want in R0) + // R1 = a_len (want in R1) + // R2 = a_cap (unused) + // R3 = b_base (want in R2) + // R4 = b_len (want in R3) + // R5 = b_cap (unused) + MOVD R3, R2 + MOVD R4, R3 +#else + MOVD a_base+0(FP), R0 + MOVD a_len+8(FP), R1 + MOVD b_base+24(FP), R2 + MOVD b_len+32(FP), R3 MOVD $ret+48(FP), R7 +#endif B cmpbody<>(SB) -TEXT runtime·cmpstring(SB),NOSPLIT|NOFRAME,$0-40 - MOVD a_base+0(FP), R2 - MOVD a_len+8(FP), R0 - MOVD b_base+16(FP), R3 - MOVD b_len+24(FP), R1 +TEXT runtime·cmpstring(SB),NOSPLIT|NOFRAME,$0-40 +#ifdef GOEXPERIMENT_regabiargs + // R0 = a_base + // R1 = a_len + // R2 = b_base + // R3 = b_len +#else + MOVD a_base+0(FP), R0 + MOVD a_len+8(FP), R1 + MOVD b_base+16(FP), R2 + MOVD b_len+24(FP), R3 MOVD $ret+32(FP), R7 +#endif B cmpbody<>(SB) // On entry: -// R0 is the length of a -// R1 is the length of b -// R2 points to the start of a -// R3 points to the start of b +// R0 points to the start of a +// R1 is the length of a +// R2 points to the start of b +// R3 is the length of b +#ifndef GOEXPERIMENT_regabiargs // R7 points to return value (-1/0/1 will be written here) +#endif // // On exit: +#ifdef GOEXPERIMENT_regabiargs +// R0 is the result +#endif // R4, R5, R6, R8, R9 and R10 are clobbered TEXT cmpbody<>(SB),NOSPLIT|NOFRAME,$0-0 - CMP R2, R3 + CMP R0, R2 BEQ samebytes // same starting pointers; compare lengths - CMP R0, R1 - CSEL LT, R1, R0, R6 // R6 is min(R0, R1) + CMP R1, R3 + CSEL LT, R3, R1, R6 // R6 is min(R1, R3) CBZ R6, samebytes BIC $0xf, R6, R10 CBZ R10, small // length < 16 - ADD R2, R10 // end of chunk16 + ADD R0, R10 // end of chunk16 // length >= 16 chunk16_loop: - LDP.P 16(R2), (R4, R8) - LDP.P 16(R3), (R5, R9) + LDP.P 16(R0), (R4, R8) + LDP.P 16(R2), (R5, R9) CMP R4, R5 BNE cmp CMP R8, R9 BNE cmpnext - CMP R10, R2 + CMP R10, R0 BNE chunk16_loop AND $0xf, R6, R6 CBZ R6, samebytes SUBS $8, R6 BLT tail // the length of tail > 8 bytes - MOVD.P 8(R2), R4 - MOVD.P 8(R3), R5 + MOVD.P 8(R0), R4 + MOVD.P 8(R2), R5 CMP R4, R5 BNE cmp SUB $8, R6 // compare last 8 bytes tail: - MOVD (R2)(R6), R4 - MOVD (R3)(R6), R5 + MOVD (R0)(R6), R4 + MOVD (R2)(R6), R5 CMP R4, R5 BEQ samebytes cmp: @@ -71,52 +94,56 @@ cmp: REV R5, R5 CMP R4, R5 ret: - MOVD $1, R4 - CNEG HI, R4, R4 - MOVD R4, (R7) + MOVD $1, R0 + CNEG HI, R0, R0 +#ifndef GOEXPERIMENT_regabiargs + MOVD R0, (R7) +#endif RET small: TBZ $3, R6, lt_8 - MOVD (R2), R4 - MOVD (R3), R5 + MOVD (R0), R4 + MOVD (R2), R5 CMP R4, R5 BNE cmp SUBS $8, R6 BEQ samebytes + ADD $8, R0 ADD $8, R2 - ADD $8, R3 SUB $8, R6 B tail lt_8: TBZ $2, R6, lt_4 - MOVWU (R2), R4 - MOVWU (R3), R5 + MOVWU (R0), R4 + MOVWU (R2), R5 CMPW R4, R5 BNE cmp SUBS $4, R6 BEQ samebytes + ADD $4, R0 ADD $4, R2 - ADD $4, R3 lt_4: TBZ $1, R6, lt_2 - MOVHU (R2), R4 - MOVHU (R3), R5 + MOVHU (R0), R4 + MOVHU (R2), R5 CMPW R4, R5 BNE cmp + ADD $2, R0 ADD $2, R2 - ADD $2, R3 lt_2: TBZ $0, R6, samebytes one: - MOVBU (R2), R4 - MOVBU (R3), R5 + MOVBU (R0), R4 + MOVBU (R2), R5 CMPW R4, R5 BNE ret samebytes: - CMP R1, R0 - CSET NE, R4 - CNEG LO, R4, R4 - MOVD R4, (R7) + CMP R3, R1 + CSET NE, R0 + CNEG LO, R0, R0 +#ifndef GOEXPERIMENT_regabiargs + MOVD R0, (R7) +#endif RET cmpnext: REV R8, R4 diff --git a/src/internal/bytealg/equal_arm64.s b/src/internal/bytealg/equal_arm64.s index 944edd8768..cf5cf54e59 100644 --- a/src/internal/bytealg/equal_arm64.s +++ b/src/internal/bytealg/equal_arm64.s @@ -6,53 +6,70 @@ #include "textflag.h" // memequal(a, b unsafe.Pointer, size uintptr) bool -TEXT runtime·memequal(SB),NOSPLIT|NOFRAME,$0-25 - MOVD size+16(FP), R1 +TEXT runtime·memequal(SB),NOSPLIT|NOFRAME,$0-25 +#ifndef GOEXPERIMENT_regabiargs + MOVD size+16(FP), R2 +#endif // short path to handle 0-byte case - CBZ R1, equal + CBZ R2, equal +#ifndef GOEXPERIMENT_regabiargs MOVD a+0(FP), R0 - MOVD b+8(FP), R2 + MOVD b+8(FP), R1 MOVD $ret+24(FP), R8 +#endif B memeqbody<>(SB) equal: MOVD $1, R0 +#ifndef GOEXPERIMENT_regabiargs MOVB R0, ret+24(FP) +#endif RET // memequal_varlen(a, b unsafe.Pointer) bool -TEXT runtime·memequal_varlen(SB),NOSPLIT,$0-17 +TEXT runtime·memequal_varlen(SB),NOSPLIT,$0-17 +#ifndef GOEXPERIMENT_regabiargs MOVD a+0(FP), R0 - MOVD b+8(FP), R2 - CMP R0, R2 + MOVD b+8(FP), R1 +#endif + CMP R0, R1 BEQ eq - MOVD 8(R26), R1 // compiler stores size at offset 8 in the closure - CBZ R1, eq + MOVD 8(R26), R2 // compiler stores size at offset 8 in the closure + CBZ R2, eq +#ifndef GOEXPERIMENT_regabiargs MOVD $ret+16(FP), R8 +#endif B memeqbody<>(SB) eq: - MOVD $1, R3 - MOVB R3, ret+16(FP) + MOVD $1, R0 +#ifndef GOEXPERIMENT_regabiargs + MOVB R0, ret+16(FP) +#endif RET // input: // R0: pointer a -// R1: data len -// R2: pointer b +// R1: pointer b +// R2: data len +#ifdef GOEXPERIMENT_regabiargs +// at return: result in R0 +#else // R8: address to put result +#endif + TEXT memeqbody<>(SB),NOSPLIT,$0 - CMP $1, R1 + CMP $1, R2 // handle 1-byte special case for better performance BEQ one - CMP $16, R1 + CMP $16, R2 // handle specially if length < 16 BLO tail - BIC $0x3f, R1, R3 + BIC $0x3f, R2, R3 CBZ R3, chunk16 // work with 64-byte chunks ADD R3, R0, R6 // end of chunks chunk64_loop: VLD1.P (R0), [V0.D2, V1.D2, V2.D2, V3.D2] - VLD1.P (R2), [V4.D2, V5.D2, V6.D2, V7.D2] + VLD1.P (R1), [V4.D2, V5.D2, V6.D2, V7.D2] VCMEQ V0.D2, V4.D2, V8.D2 VCMEQ V1.D2, V5.D2, V9.D2 VCMEQ V2.D2, V6.D2, V10.D2 @@ -66,66 +83,72 @@ chunk64_loop: CBZ R4, not_equal CBZ R5, not_equal BNE chunk64_loop - AND $0x3f, R1, R1 - CBZ R1, equal + AND $0x3f, R2, R2 + CBZ R2, equal chunk16: // work with 16-byte chunks - BIC $0xf, R1, R3 + BIC $0xf, R2, R3 CBZ R3, tail ADD R3, R0, R6 // end of chunks chunk16_loop: LDP.P 16(R0), (R4, R5) - LDP.P 16(R2), (R7, R9) + LDP.P 16(R1), (R7, R9) EOR R4, R7 CBNZ R7, not_equal EOR R5, R9 CBNZ R9, not_equal CMP R0, R6 BNE chunk16_loop - AND $0xf, R1, R1 - CBZ R1, equal + AND $0xf, R2, R2 + CBZ R2, equal tail: // special compare of tail with length < 16 - TBZ $3, R1, lt_8 + TBZ $3, R2, lt_8 MOVD (R0), R4 - MOVD (R2), R5 + MOVD (R1), R5 EOR R4, R5 CBNZ R5, not_equal - SUB $8, R1, R6 // offset of the last 8 bytes + SUB $8, R2, R6 // offset of the last 8 bytes MOVD (R0)(R6), R4 - MOVD (R2)(R6), R5 + MOVD (R1)(R6), R5 EOR R4, R5 CBNZ R5, not_equal B equal lt_8: - TBZ $2, R1, lt_4 + TBZ $2, R2, lt_4 MOVWU (R0), R4 - MOVWU (R2), R5 + MOVWU (R1), R5 EOR R4, R5 CBNZ R5, not_equal - SUB $4, R1, R6 // offset of the last 4 bytes + SUB $4, R2, R6 // offset of the last 4 bytes MOVWU (R0)(R6), R4 - MOVWU (R2)(R6), R5 + MOVWU (R1)(R6), R5 EOR R4, R5 CBNZ R5, not_equal B equal lt_4: - TBZ $1, R1, lt_2 + TBZ $1, R2, lt_2 MOVHU.P 2(R0), R4 - MOVHU.P 2(R2), R5 + MOVHU.P 2(R1), R5 CMP R4, R5 BNE not_equal lt_2: - TBZ $0, R1, equal + TBZ $0, R2, equal one: MOVBU (R0), R4 - MOVBU (R2), R5 + MOVBU (R1), R5 CMP R4, R5 BNE not_equal equal: MOVD $1, R0 +#ifndef GOEXPERIMENT_regabiargs MOVB R0, (R8) +#endif RET not_equal: +#ifdef GOEXPERIMENT_regabiargs + MOVB ZR, R0 +#else MOVB ZR, (R8) +#endif RET diff --git a/src/runtime/asm_arm64.s b/src/runtime/asm_arm64.s index 170e4406fc..4babcc7fcb 100644 --- a/src/runtime/asm_arm64.s +++ b/src/runtime/asm_arm64.s @@ -536,12 +536,14 @@ CALLFN(·call536870912, 536870912) CALLFN(·call1073741824, 1073741824) // func memhash32(p unsafe.Pointer, h uintptr) uintptr -TEXT runtime·memhash32(SB),NOSPLIT|NOFRAME,$0-24 - MOVB runtime·useAeshash(SB), R0 - CBZ R0, noaes +TEXT runtime·memhash32(SB),NOSPLIT|NOFRAME,$0-24 + MOVB runtime·useAeshash(SB), R10 + CBZ R10, noaes +#ifndef GOEXPERIMENT_regabiargs MOVD p+0(FP), R0 MOVD h+8(FP), R1 MOVD $ret+16(FP), R2 +#endif MOVD $runtime·aeskeysched+0(SB), R3 VEOR V0.B16, V0.B16, V0.B16 @@ -555,18 +557,24 @@ TEXT runtime·memhash32(SB),NOSPLIT|NOFRAME,$0-24 AESMC V0.B16, V0.B16 AESE V2.B16, V0.B16 +#ifdef GOEXPERIMENT_regabiargs + VMOV V0.D[0], R0 +#else VST1 [V0.D1], (R2) +#endif RET noaes: - B runtime·memhash32Fallback(SB) + B runtime·memhash32Fallback(SB) // func memhash64(p unsafe.Pointer, h uintptr) uintptr -TEXT runtime·memhash64(SB),NOSPLIT|NOFRAME,$0-24 - MOVB runtime·useAeshash(SB), R0 - CBZ R0, noaes +TEXT runtime·memhash64(SB),NOSPLIT|NOFRAME,$0-24 + MOVB runtime·useAeshash(SB), R10 + CBZ R10, noaes +#ifndef GOEXPERIMENT_regabiargs MOVD p+0(FP), R0 MOVD h+8(FP), R1 MOVD $ret+16(FP), R2 +#endif MOVD $runtime·aeskeysched+0(SB), R3 VEOR V0.B16, V0.B16, V0.B16 @@ -580,75 +588,89 @@ TEXT runtime·memhash64(SB),NOSPLIT|NOFRAME,$0-24 AESMC V0.B16, V0.B16 AESE V2.B16, V0.B16 +#ifdef GOEXPERIMENT_regabiargs + VMOV V0.D[0], R0 +#else VST1 [V0.D1], (R2) +#endif RET noaes: - B runtime·memhash64Fallback(SB) + B runtime·memhash64Fallback(SB) // func memhash(p unsafe.Pointer, h, size uintptr) uintptr -TEXT runtime·memhash(SB),NOSPLIT|NOFRAME,$0-32 - MOVB runtime·useAeshash(SB), R0 - CBZ R0, noaes +TEXT runtime·memhash(SB),NOSPLIT|NOFRAME,$0-32 + MOVB runtime·useAeshash(SB), R10 + CBZ R10, noaes +#ifndef GOEXPERIMENT_regabiargs MOVD p+0(FP), R0 - MOVD s+16(FP), R1 - MOVD h+8(FP), R3 - MOVD $ret+24(FP), R2 + MOVD h+8(FP), R1 + MOVD s+16(FP), R2 + MOVD $ret+24(FP), R8 +#endif B aeshashbody<>(SB) noaes: - B runtime·memhashFallback(SB) + B runtime·memhashFallback(SB) // func strhash(p unsafe.Pointer, h uintptr) uintptr -TEXT runtime·strhash(SB),NOSPLIT|NOFRAME,$0-24 - MOVB runtime·useAeshash(SB), R0 - CBZ R0, noaes - MOVD p+0(FP), R10 // string pointer - LDP (R10), (R0, R1) //string data/ length - MOVD h+8(FP), R3 - MOVD $ret+16(FP), R2 // return adddress +TEXT runtime·strhash(SB),NOSPLIT|NOFRAME,$0-24 + MOVB runtime·useAeshash(SB), R10 + CBZ R10, noaes +#ifdef GOEXPERIMENT_regabiargs + LDP (R0), (R0, R2) // string data / length +#else + MOVD p+0(FP), R10 // string pointer + LDP (R10), (R0, R2) // string data / length + MOVD h+8(FP), R1 + MOVD $ret+16(FP), R8 // return adddress +#endif B aeshashbody<>(SB) noaes: - B runtime·strhashFallback(SB) + B runtime·strhashFallback(SB) // R0: data -// R1: length -// R2: address to put return value -// R3: seed data +// R1: seed data +// R2: length +#ifdef GOEXPERIMENT_regabiargs +// At return, R0 = return value +#else +// R8: address to put return value +#endif TEXT aeshashbody<>(SB),NOSPLIT|NOFRAME,$0 VEOR V30.B16, V30.B16, V30.B16 - VMOV R3, V30.D[0] - VMOV R1, V30.D[1] // load length into seed + VMOV R1, V30.D[0] + VMOV R2, V30.D[1] // load length into seed MOVD $runtime·aeskeysched+0(SB), R4 VLD1.P 16(R4), [V0.B16] AESE V30.B16, V0.B16 AESMC V0.B16, V0.B16 - CMP $16, R1 + CMP $16, R2 BLO aes0to15 BEQ aes16 - CMP $32, R1 + CMP $32, R2 BLS aes17to32 - CMP $64, R1 + CMP $64, R2 BLS aes33to64 - CMP $128, R1 + CMP $128, R2 BLS aes65to128 B aes129plus aes0to15: - CBZ R1, aes0 + CBZ R2, aes0 VEOR V2.B16, V2.B16, V2.B16 - TBZ $3, R1, less_than_8 + TBZ $3, R2, less_than_8 VLD1.P 8(R0), V2.D[0] less_than_8: - TBZ $2, R1, less_than_4 + TBZ $2, R2, less_than_4 VLD1.P 4(R0), V2.S[2] less_than_4: - TBZ $1, R1, less_than_2 + TBZ $1, R2, less_than_2 VLD1.P 2(R0), V2.H[6] less_than_2: - TBZ $0, R1, done + TBZ $0, R2, done VLD1 (R0), V2.B[14] done: AESE V0.B16, V2.B16 @@ -657,11 +679,21 @@ done: AESMC V2.B16, V2.B16 AESE V0.B16, V2.B16 - VST1 [V2.D1], (R2) +#ifdef GOEXPERIMENT_regabiargs + VMOV V2.D[0], R0 +#else + VST1 [V2.D1], (R8) +#endif RET + aes0: - VST1 [V0.D1], (R2) +#ifdef GOEXPERIMENT_regabiargs + VMOV V0.D[0], R0 +#else + VST1 [V0.D1], (R8) +#endif RET + aes16: VLD1 (R0), [V2.B16] B done @@ -671,7 +703,7 @@ aes17to32: VLD1 (R4), [V1.B16] AESE V30.B16, V1.B16 AESMC V1.B16, V1.B16 - SUB $16, R1, R10 + SUB $16, R2, R10 VLD1.P (R0)(R10), [V2.B16] VLD1 (R0), [V3.B16] @@ -689,7 +721,11 @@ aes17to32: AESE V1.B16, V3.B16 VEOR V3.B16, V2.B16, V2.B16 - VST1 [V2.D1], (R2) +#ifdef GOEXPERIMENT_regabiargs + VMOV V2.D[0], R0 +#else + VST1 [V2.D1], (R8) +#endif RET aes33to64: @@ -700,7 +736,7 @@ aes33to64: AESMC V2.B16, V2.B16 AESE V30.B16, V3.B16 AESMC V3.B16, V3.B16 - SUB $32, R1, R10 + SUB $32, R2, R10 VLD1.P (R0)(R10), [V4.B16, V5.B16] VLD1 (R0), [V6.B16, V7.B16] @@ -732,7 +768,11 @@ aes33to64: VEOR V7.B16, V5.B16, V5.B16 VEOR V5.B16, V4.B16, V4.B16 - VST1 [V4.D1], (R2) +#ifdef GOEXPERIMENT_regabiargs + VMOV V4.D[0], R0 +#else + VST1 [V4.D1], (R8) +#endif RET aes65to128: @@ -753,7 +793,7 @@ aes65to128: AESE V30.B16, V7.B16 AESMC V7.B16, V7.B16 - SUB $64, R1, R10 + SUB $64, R2, R10 VLD1.P (R0)(R10), [V8.B16, V9.B16, V10.B16, V11.B16] VLD1 (R0), [V12.B16, V13.B16, V14.B16, V15.B16] AESE V0.B16, V8.B16 @@ -807,7 +847,11 @@ aes65to128: VEOR V11.B16, V9.B16, V9.B16 VEOR V9.B16, V8.B16, V8.B16 - VST1 [V8.D1], (R2) +#ifdef GOEXPERIMENT_regabiargs + VMOV V8.D[0], R0 +#else + VST1 [V8.D1], (R8) +#endif RET aes129plus: @@ -828,12 +872,12 @@ aes129plus: AESMC V6.B16, V6.B16 AESE V30.B16, V7.B16 AESMC V7.B16, V7.B16 - ADD R0, R1, R10 + ADD R0, R2, R10 SUB $128, R10, R10 VLD1.P 64(R10), [V8.B16, V9.B16, V10.B16, V11.B16] VLD1 (R10), [V12.B16, V13.B16, V14.B16, V15.B16] - SUB $1, R1, R1 - LSR $7, R1, R1 + SUB $1, R2, R2 + LSR $7, R2, R2 aesloop: AESE V8.B16, V0.B16 @@ -872,8 +916,8 @@ aesloop: AESMC V6.B16, V6.B16 AESE V15.B16, V7.B16 AESMC V7.B16, V7.B16 - SUB $1, R1, R1 - CBNZ R1, aesloop + SUB $1, R2, R2 + CBNZ R2, aesloop AESE V8.B16, V0.B16 AESMC V0.B16, V0.B16 @@ -926,7 +970,11 @@ aesloop: VEOR V4.B16, V6.B16, V4.B16 VEOR V4.B16, V0.B16, V0.B16 - VST1 [V0.D1], (R2) +#ifdef GOEXPERIMENT_regabiargs + VMOV V0.D[0], R0 +#else + VST1 [V0.D1], (R8) +#endif RET TEXT runtime·procyield(SB),NOSPLIT,$0-0 diff --git a/src/runtime/memclr_arm64.s b/src/runtime/memclr_arm64.s index c1a0dcef58..b80cca6a1c 100644 --- a/src/runtime/memclr_arm64.s +++ b/src/runtime/memclr_arm64.s @@ -8,9 +8,11 @@ // func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr) // Also called from assembly in sys_windows_arm64.s without g (but using Go stack convention). -TEXT runtime·memclrNoHeapPointers(SB),NOSPLIT,$0-16 +TEXT runtime·memclrNoHeapPointers(SB),NOSPLIT,$0-16 +#ifndef GOEXPERIMENT_regabiargs MOVD ptr+0(FP), R0 MOVD n+8(FP), R1 +#endif CMP $16, R1 // If n is equal to 16 bytes, use zero_exact_16 to zero diff --git a/src/runtime/memmove_arm64.s b/src/runtime/memmove_arm64.s index 43d27629e5..bee3b00c47 100644 --- a/src/runtime/memmove_arm64.s +++ b/src/runtime/memmove_arm64.s @@ -26,10 +26,12 @@ // The loop tail is handled by always copying 64 bytes from the end. // func memmove(to, from unsafe.Pointer, n uintptr) -TEXT runtime·memmove(SB), NOSPLIT|NOFRAME, $0-24 +TEXT runtime·memmove(SB), NOSPLIT|NOFRAME, $0-24 +#ifndef GOEXPERIMENT_regabiargs MOVD to+0(FP), R0 MOVD from+8(FP), R1 MOVD n+16(FP), R2 +#endif CBZ R2, copy0 // Small copies: 1..16 bytes -- GitLab From 3de49868526d5bfae2f9bda8be1a60c022cf3363 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 2 Jun 2021 19:43:28 -0400 Subject: [PATCH 0196/2500] [dev.typeparams] runtime: call cgocallbackg indirectly on ARM64 This is CL 312669, for ARM64. cgocallback calls cgocallbackg after switching the stack. Call it indirectly to bypass the linker's nosplit check. In particular, this avoids a nosplit stack overflow on Windows when register ABI is enabled. Change-Id: I7054a750fb0ec2579d46004f94b46b6f7b9e3a21 Reviewed-on: https://go-review.googlesource.com/c/go/+/324734 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/runtime/asm_arm64.s | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/runtime/asm_arm64.s b/src/runtime/asm_arm64.s index 4babcc7fcb..be4313d35d 100644 --- a/src/runtime/asm_arm64.s +++ b/src/runtime/asm_arm64.s @@ -1196,7 +1196,8 @@ havem: MOVD R1, 8(RSP) MOVD R2, 16(RSP) MOVD R3, 24(RSP) - BL runtime·cgocallbackg(SB) + MOVD $runtime·cgocallbackg(SB), R0 + CALL (R0) // indirect call to bypass nosplit check. We're on a different stack now. // Restore g->sched (== m->curg->sched) from saved values. MOVD 0(RSP), R5 -- GitLab From 28bd325e418a0ca1c70a024764aa74e25aacab12 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 2 Jun 2021 19:52:39 -0400 Subject: [PATCH 0197/2500] [dev.typeparams] runtime: use ABIInternal callbackWrap in callbackasm1 on ARM64 On Windows/ARM64, callbackasm1 calls callbackWrap via cgocallback. cgocallback uses ABIInternal calling convention to call the function. Pass the ABIInternal entry point to cgocallback. Change-Id: I79d21b77525f6ac8dd50d34f4f304749419b2ad4 Reviewed-on: https://go-review.googlesource.com/c/go/+/324735 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/runtime/sys_windows_arm64.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/sys_windows_arm64.s b/src/runtime/sys_windows_arm64.s index e859371508..44145c53fb 100644 --- a/src/runtime/sys_windows_arm64.s +++ b/src/runtime/sys_windows_arm64.s @@ -339,7 +339,7 @@ TEXT runtime·callbackasm1(SB),NOSPLIT,$208-0 MOVD R0, callbackArgs_result(R13) // result // Call cgocallback, which will call callbackWrap(frame). - MOVD $·callbackWrap(SB), R0 // PC of function to call + MOVD $·callbackWrap(SB), R0 // PC of function to call, cgocallback takes an ABIInternal entry-point MOVD R13, R1 // frame (&callbackArgs{...}) MOVD $0, R2 // context MOVD R0, (1*8)(RSP) -- GitLab From e9ba0750b63652514bc527690b39fe8b3651ad31 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 3 Jun 2021 15:23:22 -0400 Subject: [PATCH 0198/2500] [dev.typeparams] reflect: guard abi_test.go with regabiargs build tag The test in abi_test.go relies on the compiler to generate register-ABI calls using a magic name. As of CL 300150 the name loses its magic. Guard it with regabiargs for the use of register-ABI calls. Change-Id: Ib8b3c24f71ea5161d607c9becfb3027ceee40ac1 Reviewed-on: https://go-review.googlesource.com/c/go/+/324767 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: Michael Knyszek TryBot-Result: Go Bot --- src/reflect/abi_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/reflect/abi_test.go b/src/reflect/abi_test.go index 1a2a48b5ed..26e77f14dd 100644 --- a/src/reflect/abi_test.go +++ b/src/reflect/abi_test.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build goexperiment.regabireflect -// +build goexperiment.regabireflect +//go:build goexperiment.regabireflect && goexperiment.regabiargs +// +build goexperiment.regabireflect,goexperiment.regabiargs package reflect_test -- GitLab From 1c947e4f31331ffbc0397a7781c443903f1da473 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Thu, 3 Jun 2021 10:59:35 -0700 Subject: [PATCH 0199/2500] [dev.typeparams] cmd/compile: properly copy tilde value for unions in types2-to-types1 conversion Change-Id: I2211020141886b348cddf9e33ab31b71c8478987 Reviewed-on: https://go-review.googlesource.com/c/go/+/324811 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Robert Griesemer Trust: Dan Scales --- src/cmd/compile/internal/noder/types.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index f34cf146bb..f0061e79d7 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -239,8 +239,9 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { tlist := make([]*types.Type, nt) tildes := make([]bool, nt) for i := range tlist { - term, _ := typ.Term(i) + term, tilde := typ.Term(i) tlist[i] = g.typ1(term) + tildes[i] = tilde } return types.NewUnion(tlist, tildes) -- GitLab From 6b1e4430bb79674ff523240608f106a1aeb7302e Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 3 Jun 2021 12:23:14 -0400 Subject: [PATCH 0200/2500] [dev.typeparams] cmd/compile: implement clobberdead mode on ARM64 For debugging. Change-Id: I5875ccd2413b8ffd2ec97a0ace66b5cae7893b24 Reviewed-on: https://go-review.googlesource.com/c/go/+/324765 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: Than McIntosh TryBot-Result: Go Bot --- src/cmd/compile/internal/arm64/ssa.go | 30 +++++++++++++++++++++++++-- test/codegen/clobberdead.go | 7 +++++-- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/arm64/ssa.go b/src/cmd/compile/internal/arm64/ssa.go index 74308a18f6..c3319f9491 100644 --- a/src/cmd/compile/internal/arm64/ssa.go +++ b/src/cmd/compile/internal/arm64/ssa.go @@ -1114,8 +1114,34 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { v.Fatalf("FlagConstant op should never make it to codegen %v", v.LongString()) case ssa.OpARM64InvertFlags: v.Fatalf("InvertFlags should never make it to codegen %v", v.LongString()) - case ssa.OpClobber, ssa.OpClobberReg: - // TODO: implement for clobberdead experiment. Nop is ok for now. + case ssa.OpClobber: + // MOVW $0xdeaddead, REGTMP + // MOVW REGTMP, (slot) + // MOVW REGTMP, 4(slot) + p := s.Prog(arm64.AMOVW) + p.From.Type = obj.TYPE_CONST + p.From.Offset = 0xdeaddead + p.To.Type = obj.TYPE_REG + p.To.Reg = arm64.REGTMP + p = s.Prog(arm64.AMOVW) + p.From.Type = obj.TYPE_REG + p.From.Reg = arm64.REGTMP + p.To.Type = obj.TYPE_MEM + p.To.Reg = arm64.REGSP + ssagen.AddAux(&p.To, v) + p = s.Prog(arm64.AMOVW) + p.From.Type = obj.TYPE_REG + p.From.Reg = arm64.REGTMP + p.To.Type = obj.TYPE_MEM + p.To.Reg = arm64.REGSP + ssagen.AddAux2(&p.To, v, v.AuxInt+4) + case ssa.OpClobberReg: + x := uint64(0xdeaddeaddeaddead) + p := s.Prog(arm64.AMOVD) + p.From.Type = obj.TYPE_CONST + p.From.Offset = int64(x) + p.To.Type = obj.TYPE_REG + p.To.Reg = v.Reg() default: v.Fatalf("genValue not implemented: %s", v.LongString()) } diff --git a/test/codegen/clobberdead.go b/test/codegen/clobberdead.go index f8d964cba6..c490790bb6 100644 --- a/test/codegen/clobberdead.go +++ b/test/codegen/clobberdead.go @@ -1,6 +1,6 @@ // asmcheck -gcflags=-clobberdead -// +build amd64 +// +build amd64 arm64 // Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style @@ -13,15 +13,18 @@ type T [2]*int // contain pointer, not SSA-able (so locals are not registerized) var p1, p2, p3 T func F() { - // 3735936685 is 0xdeaddead + // 3735936685 is 0xdeaddead. On ARM64 R27 is REGTMP. // clobber x, y at entry. not clobber z (stack object). // amd64:`MOVL\t\$3735936685, ""\.x`, `MOVL\t\$3735936685, ""\.y`, -`MOVL\t\$3735936685, ""\.z` + // arm64:`MOVW\tR27, ""\.x`, `MOVW\tR27, ""\.y`, -`MOVW\tR27, ""\.z` x, y, z := p1, p2, p3 addrTaken(&z) // x is dead at the call (the value of x is loaded before the CALL), y is not // amd64:`MOVL\t\$3735936685, ""\.x`, -`MOVL\t\$3735936685, ""\.y` + // arm64:`MOVW\tR27, ""\.x`, -`MOVW\tR27, ""\.y` use(x) // amd64:`MOVL\t\$3735936685, ""\.x`, `MOVL\t\$3735936685, ""\.y` + // arm64:`MOVW\tR27, ""\.x`, `MOVW\tR27, ""\.y` use(y) } -- GitLab From 55b4310acdbd7bc7253936c44a845a98d82eaae7 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 3 Jun 2021 12:26:18 -0400 Subject: [PATCH 0201/2500] [dev.typeparams] runtime: crash the GC at clobberdead pointer on ARM64 Extend CL 310330 to ARM64, which now has clobberdead mode implemented in the compiler. Change-Id: I07f6951d81a0797ef7a74e48b79db5cea2bf876b Reviewed-on: https://go-review.googlesource.com/c/go/+/324766 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: Michael Knyszek TryBot-Result: Go Bot --- src/runtime/mbitmap.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/runtime/mbitmap.go b/src/runtime/mbitmap.go index 32b8db7a50..819acf40bd 100644 --- a/src/runtime/mbitmap.go +++ b/src/runtime/mbitmap.go @@ -386,10 +386,10 @@ func findObject(p, refBase, refOff uintptr) (base uintptr, s *mspan, objIndex ui // If s is nil, the virtual address has never been part of the heap. // This pointer may be to some mmap'd region, so we allow it. if s == nil { - if GOARCH == "amd64" && p == clobberdeadPtr && debug.invalidptr != 0 { - // Crash if clobberdeadPtr is seen. Only on AMD64 for now, as - // it is the only platform where compiler's clobberdead mode is - // implemented. On AMD64 clobberdeadPtr cannot be a valid address. + if (GOARCH == "amd64" || GOARCH == "arm64") && p == clobberdeadPtr && debug.invalidptr != 0 { + // Crash if clobberdeadPtr is seen. Only on AMD64 and ARM64 for now, + // as they are the only platform where compiler's clobberdead mode is + // implemented. On these platforms clobberdeadPtr cannot be a valid address. badPointer(s, p, refBase, refOff) } return -- GitLab From a2d6a2caebec473de95e29c48f076b01b7ab5af0 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 3 Jun 2021 15:17:51 -0400 Subject: [PATCH 0202/2500] [dev.typeparams] internal/buildcfg: turn on regabiwrappers by default on ARM64 Change-Id: I8db0a797a745630ec35af3e56406fcb250ea59fe Reviewed-on: https://go-review.googlesource.com/c/go/+/324768 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek Reviewed-by: Than McIntosh --- src/internal/buildcfg/exp.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go index 196d6af4a6..1fc53324c1 100644 --- a/src/internal/buildcfg/exp.go +++ b/src/internal/buildcfg/exp.go @@ -21,12 +21,13 @@ import ( var Experiment goexperiment.Flags = parseExperiments() var regabiSupported = GOARCH == "amd64" +var regabiDeveloping = GOARCH == "arm64" // experimentBaseline specifies the experiment flags that are enabled by // default in the current toolchain. This is, in effect, the "control" // configuration and any variation from this is an experiment. var experimentBaseline = goexperiment.Flags{ - RegabiWrappers: regabiSupported, + RegabiWrappers: regabiSupported || regabiDeveloping, RegabiG: regabiSupported, RegabiReflect: regabiSupported, RegabiDefer: true, -- GitLab From 026480d06bd0b72e147953281b328c0283128e52 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 3 Jun 2021 13:05:22 -0700 Subject: [PATCH 0203/2500] [dev.typeparams] cmd/compile: allow nil Syms in Sym.Less Allows sorting interfaces that contain embedded anonymous types. Fixes #46556. Change-Id: If19afa1d62432323b2e98957087867afbf3f9097 Reviewed-on: https://go-review.googlesource.com/c/go/+/324812 Trust: Matthew Dempsky Trust: Dan Scales Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/types/sym.go | 8 ++++++++ test/fixedbugs/issue46556.go | 16 ++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 test/fixedbugs/issue46556.go diff --git a/src/cmd/compile/internal/types/sym.go b/src/cmd/compile/internal/types/sym.go index 534cf7e237..fb642f52f8 100644 --- a/src/cmd/compile/internal/types/sym.go +++ b/src/cmd/compile/internal/types/sym.go @@ -110,6 +110,14 @@ func (a *Sym) Less(b *Sym) bool { return false } + // Nil before non-nil. + if a == nil { + return true + } + if b == nil { + return false + } + // Exported symbols before non-exported. ea := IsExported(a.Name) eb := IsExported(b.Name) diff --git a/test/fixedbugs/issue46556.go b/test/fixedbugs/issue46556.go new file mode 100644 index 0000000000..b159f61b0c --- /dev/null +++ b/test/fixedbugs/issue46556.go @@ -0,0 +1,16 @@ +// compile + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type A = interface{} +type B interface{} + +// Test that embedding both anonymous and defined types is supported. +type C interface { + A + B +} -- GitLab From 5f034f9b46f32010434d64aa376bb118e899253a Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 3 Jun 2021 15:18:36 -0400 Subject: [PATCH 0204/2500] [dev.typeparams] internal/buildcfg: turn on regabireflect by default on ARM64 Change-Id: I4a0a093b07a287cc3a3e0ee939e7ee82d8e9b1aa Reviewed-on: https://go-review.googlesource.com/c/go/+/324889 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: Michael Knyszek Reviewed-by: Than McIntosh TryBot-Result: Go Bot --- src/internal/buildcfg/exp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go index 1fc53324c1..352aebd227 100644 --- a/src/internal/buildcfg/exp.go +++ b/src/internal/buildcfg/exp.go @@ -29,7 +29,7 @@ var regabiDeveloping = GOARCH == "arm64" var experimentBaseline = goexperiment.Flags{ RegabiWrappers: regabiSupported || regabiDeveloping, RegabiG: regabiSupported, - RegabiReflect: regabiSupported, + RegabiReflect: regabiSupported || regabiDeveloping, RegabiDefer: true, RegabiArgs: regabiSupported, } -- GitLab From 4d2b528795fe2534398d1b1a978e1037d4a9d2f0 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 3 Jun 2021 10:30:47 -0400 Subject: [PATCH 0205/2500] [dev.typeparams] internal/buildcfg: turn on register ABI by default on ARM64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This CL enables all regabi experiments on ARM64 by default. regabiwrappers and regabireflect are enabled in the previous CLs. regabidefer is already enabled everywhere. regabig is no-op on ARM64 as it already has a G register. regabiargs is enabled in this CL. Go1 benchmarks results (GOEXPERIMENT=regabi vs. none, on macOS/ARM64): name old time/op new time/op delta BinaryTree17-8 1.20s ± 1% 1.02s ± 0% -15.08% (p=0.000 n=9+9) Fannkuch11-8 1.55s ± 0% 1.57s ± 0% +1.53% (p=0.000 n=9+8) FmtFprintfEmpty-8 22.5ns ± 3% 14.7ns ± 1% -34.47% (p=0.000 n=10+8) FmtFprintfString-8 38.4ns ± 0% 28.8ns ± 0% -24.99% (p=0.000 n=9+9) FmtFprintfInt-8 38.7ns ± 2% 34.5ns ± 0% -10.79% (p=0.000 n=10+7) FmtFprintfIntInt-8 61.1ns ± 1% 57.9ns ± 0% -5.23% (p=0.000 n=10+8) FmtFprintfPrefixedInt-8 69.9ns ± 0% 64.4ns ± 0% -7.78% (p=0.000 n=8+8) FmtFprintfFloat-8 106ns ± 0% 76ns ± 0% -28.12% (p=0.000 n=7+10) FmtManyArgs-8 273ns ± 0% 236ns ± 1% -13.57% (p=0.000 n=9+10) GobDecode-8 3.09ms ± 1% 2.02ms ± 0% -34.70% (p=0.000 n=9+10) GobEncode-8 2.45ms ± 1% 1.44ms ± 1% -41.26% (p=0.000 n=10+10) Gzip-8 128ms ± 0% 124ms ± 0% -2.89% (p=0.000 n=7+8) Gunzip-8 23.6ms ± 1% 19.8ms ± 0% -16.15% (p=0.000 n=10+9) HTTPClientServer-8 27.4µs ± 1% 26.3µs ± 0% -4.05% (p=0.000 n=10+10) JSONEncode-8 4.47ms ± 1% 3.45ms ± 1% -22.73% (p=0.000 n=10+9) JSONDecode-8 21.5ms ± 0% 17.2ms ± 0% -19.78% (p=0.000 n=9+9) Mandelbrot200-8 2.33ms ± 1% 2.33ms ± 1% ~ (p=0.842 n=9+10) GoParse-8 1.62ms ± 1% 1.32ms ± 1% -18.67% (p=0.000 n=10+10) RegexpMatchEasy0_32-8 33.1ns ± 0% 26.3ns ± 0% -20.50% (p=0.000 n=8+10) RegexpMatchEasy0_1K-8 121ns ± 6% 121ns ± 8% ~ (p=0.926 n=10+10) RegexpMatchEasy1_32-8 31.4ns ± 0% 24.7ns ± 0% -21.50% (p=0.000 n=9+10) RegexpMatchEasy1_1K-8 177ns ± 0% 140ns ± 0% -20.70% (p=0.000 n=10+9) RegexpMatchMedium_32-8 3.02ns ± 3% 2.12ns ± 0% -29.73% (p=0.000 n=10+10) RegexpMatchMedium_1K-8 19.8µs ± 2% 17.1µs ± 0% -13.50% (p=0.000 n=9+9) RegexpMatchHard_32-8 940ns ± 0% 872ns ± 0% -7.20% (p=0.000 n=9+8) RegexpMatchHard_1K-8 28.5µs ± 1% 26.5µs ± 0% -7.06% (p=0.000 n=10+10) Revcomp-8 186ms ± 1% 179ms ± 1% -3.66% (p=0.000 n=10+10) Template-8 30.3ms ± 0% 22.3ms ± 0% -26.58% (p=0.000 n=8+9) TimeParse-8 133ns ± 0% 117ns ± 0% -12.40% (p=0.000 n=10+10) TimeFormat-8 176ns ± 0% 141ns ± 0% -19.92% (p=0.000 n=8+9) [Geo mean] 21.4µs 17.8µs -16.81% name old speed new speed delta GobDecode-8 249MB/s ± 1% 381MB/s ± 0% +53.13% (p=0.000 n=9+10) GobEncode-8 314MB/s ± 1% 534MB/s ± 1% +70.25% (p=0.000 n=10+10) Gzip-8 152MB/s ± 0% 156MB/s ± 0% +2.97% (p=0.000 n=7+8) Gunzip-8 822MB/s ± 1% 981MB/s ± 0% +19.26% (p=0.000 n=10+9) JSONEncode-8 434MB/s ± 1% 562MB/s ± 1% +29.41% (p=0.000 n=10+9) JSONDecode-8 90.3MB/s ± 0% 112.5MB/s ± 0% +24.66% (p=0.000 n=9+9) GoParse-8 35.7MB/s ± 1% 43.9MB/s ± 1% +22.96% (p=0.000 n=10+10) RegexpMatchEasy0_32-8 967MB/s ± 0% 1216MB/s ± 0% +25.78% (p=0.000 n=8+10) RegexpMatchEasy0_1K-8 8.46GB/s ± 6% 8.45GB/s ± 7% ~ (p=0.912 n=10+10) RegexpMatchEasy1_32-8 1.02GB/s ± 0% 1.30GB/s ± 0% +27.40% (p=0.000 n=9+10) RegexpMatchEasy1_1K-8 5.78GB/s ± 0% 7.29GB/s ± 0% +26.10% (p=0.000 n=10+9) RegexpMatchMedium_32-8 331MB/s ± 2% 471MB/s ± 0% +42.29% (p=0.000 n=10+10) RegexpMatchMedium_1K-8 51.7MB/s ± 2% 59.8MB/s ± 0% +15.60% (p=0.000 n=9+9) RegexpMatchHard_32-8 34.0MB/s ± 0% 36.7MB/s ± 0% +7.75% (p=0.000 n=9+8) RegexpMatchHard_1K-8 35.9MB/s ± 1% 38.6MB/s ± 0% +7.59% (p=0.000 n=10+10) Revcomp-8 1.37GB/s ± 1% 1.42GB/s ± 1% +3.79% (p=0.000 n=10+10) Template-8 64.0MB/s ± 0% 87.1MB/s ± 0% +36.20% (p=0.000 n=8+9) [Geo mean] 299MB/s 368MB/s +23.16% Binary sizes: old new hello 1180994 1162626 -1.6% cmd/compile 23455858 22833970 -2.7% cmd/link 6425010 6332978 -1.4% Text sizes: old new hello 458752 425984 -7.1% cmd/compile 10190848 9355264 -8.2% cmd/link 2621440 2441216 -6.9% Change-Id: I52c10c11bb8fe5952b7043f9dbf09573ef71d2b0 Reviewed-on: https://go-review.googlesource.com/c/go/+/324890 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek Reviewed-by: Than McIntosh Reviewed-by: Jeremy Faller --- src/internal/buildcfg/exp.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go index 352aebd227..38a2045639 100644 --- a/src/internal/buildcfg/exp.go +++ b/src/internal/buildcfg/exp.go @@ -20,16 +20,16 @@ import ( // was built with.) var Experiment goexperiment.Flags = parseExperiments() -var regabiSupported = GOARCH == "amd64" -var regabiDeveloping = GOARCH == "arm64" +var regabiSupported = GOARCH == "amd64" || GOARCH == "arm64" +var regabiDeveloping = false // experimentBaseline specifies the experiment flags that are enabled by // default in the current toolchain. This is, in effect, the "control" // configuration and any variation from this is an experiment. var experimentBaseline = goexperiment.Flags{ - RegabiWrappers: regabiSupported || regabiDeveloping, + RegabiWrappers: regabiSupported, RegabiG: regabiSupported, - RegabiReflect: regabiSupported || regabiDeveloping, + RegabiReflect: regabiSupported, RegabiDefer: true, RegabiArgs: regabiSupported, } -- GitLab From 5542c10fbf19cb199d1659c18963f9ed83570746 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Tue, 27 Apr 2021 12:16:03 -0700 Subject: [PATCH 0206/2500] [dev.fuzz] internal/fuzz: don't use temporary buffers We're already allocating a huge amount of space at the end of each byte slice, so just use that for scratch space instead of allocating a new temporary buffer. Change-Id: Ie075a199d4ac5dd5789949af2a19815c3025b809 Reviewed-on: https://go-review.googlesource.com/c/go/+/314272 Trust: Roland Shoemaker Trust: Katie Hockman Run-TryBot: Roland Shoemaker TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/internal/fuzz/mutator.go | 40 +++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/internal/fuzz/mutator.go b/src/internal/fuzz/mutator.go index d4ca31e6e5..bd8651f806 100644 --- a/src/internal/fuzz/mutator.go +++ b/src/internal/fuzz/mutator.go @@ -31,7 +31,7 @@ func (m *mutator) randByteOrder() binary.ByteOrder { return binary.BigEndian } -// chooseLen chooses length of range mutation in range [0,n]. It gives +// chooseLen chooses length of range mutation in range [1,n]. It gives // preference to shorter ranges. func (m *mutator) chooseLen(n int) int { switch x := m.rand(100); { @@ -292,15 +292,26 @@ func (m *mutator) mutateBytes(ptrB *[]byte) { dst = m.rand(len(b)) } n := m.chooseLen(len(b) - src) - if len(b)+n >= cap(b) { + // Use the end of the slice as scratch space to avoid doing an + // allocation. If the slice is too small abort and try something + // else. + if len(b)+(n*2) >= cap(b) { iter-- continue } - tmp := make([]byte, n) - copy(tmp, b[src:]) - b = b[:len(b)+n] - copy(b[dst+n:], b[dst:]) - copy(b[dst:], tmp) + end := len(b) + // Increase the size of b to fit the duplicated block as well as + // some extra working space + b = b[:end+(n*2)] + // Copy the block of bytes we want to duplicate to the end of the + // slice + copy(b[end+n:], b[src:src+n]) + // Shift the bytes after the splice point n positions to the right + // to make room for the new block + copy(b[dst+n:end+n], b[dst:end]) + // Insert the duplicate block into the splice point + copy(b[dst:], b[end+n:]) + b = b[:end+n] case 3: // Overwrite a range of bytes with a randomly selected // chunk @@ -494,10 +505,19 @@ func (m *mutator) mutateBytes(ptrB *[]byte) { dst = m.rand(len(b)) } n := m.chooseLen(len(b) - src) - tmp := make([]byte, n) - copy(tmp, b[dst:]) + // Use the end of the slice as scratch space to avoid doing an + // allocation. If the slice is too small abort and try something + // else. + if len(b)+n >= cap(b) { + iter-- + continue + } + end := len(b) + b = b[:end+n] + copy(b[end:], b[dst:dst+n]) copy(b[dst:], b[src:src+n]) - copy(b[src:], tmp) + copy(b[src:], b[end:]) + b = b[:end] default: panic("unknown mutator") } -- GitLab From 2175e2f57331cbcd32bccc47fa7fe7a6874a69a3 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Sat, 29 May 2021 15:35:18 -0700 Subject: [PATCH 0207/2500] [dev.typeparams] cmd/compile: lazy import resolution for types2 This CL adds three new functions to the types2 API to support lazy import resolution: 1. A new Scope.InsertLazy method to allow recording that Objects exist in a particular Scope (in particular, package scopes) without having to yet fully construct those objects. Instead, types2 will call the provided `resolve` function if/when the object is actually needed. 2. Similarly, a new NewTypeNameLazy function to create TypeName objects without yet instantiating their underlying Named instance. 3. Finally, an InstantiateLazy method, that allows creating type instances without requiring any of the types to be expanded right away. Importantly, this requires providing a types2.Checker argument to handle recursive types correctly. The APIs as-is are a bit clumsy (esp. NewTypeNameLazy), but seem to work well for cmd/compile's needs. In particular, they simplify some of the complexities of handling recursive type definitions within the importer. Also, the current prototype is a bit fragile. It uses sync.Once to manage concurrent lazy resolution, which is frustrating to debug in the presence of reentrancy issues. It also means the importer needs to deal with concurrency as well. These aren't issues for types2 though as cmd/compile only walks the type-checked AST sequentially. Finally, it looks like some of the details of lazy type names are similar to the lazy "instance" stuff used for generics, so maybe there's opportunity for unifying them under a more general (but still internal) lazy type mechanism. I had originally intended for this CL to also update the types2 importer, but (1) it doesn't have access to the types2.Checker instance needed to call InstantiateLazy, and (2) it creates a new TypeName/TypeParam at each use rather than reusing them, which evidently works with types2.Instantiate but not types2.(*Checker).instantiate (i.e., InstantiateLazy). I spent a while trying to fix these issues, but kept running into more subtle issues. Instead, I've included my WIP "unified IR" CL as a followup CL that demonstrates these Lazy methods (see noder/reader2.go). Updates #46449. Change-Id: I4d1e8e649f6325a11790d25fd90c39fa07c8d41d Reviewed-on: https://go-review.googlesource.com/c/go/+/323569 Run-TryBot: Matthew Dempsky Trust: Matthew Dempsky Trust: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/check.go | 2 +- src/cmd/compile/internal/types2/decl.go | 7 +- .../compile/internal/types2/instantiate.go | 18 +++- src/cmd/compile/internal/types2/labels.go | 3 +- src/cmd/compile/internal/types2/lookup.go | 5 +- src/cmd/compile/internal/types2/object.go | 8 ++ src/cmd/compile/internal/types2/predicates.go | 2 +- src/cmd/compile/internal/types2/resolver.go | 19 ++-- src/cmd/compile/internal/types2/sanitize.go | 1 + src/cmd/compile/internal/types2/scope.go | 93 +++++++++++++++++-- src/cmd/compile/internal/types2/signature.go | 2 +- .../compile/internal/types2/sizeof_test.go | 2 +- src/cmd/compile/internal/types2/stmt.go | 3 +- src/cmd/compile/internal/types2/subst.go | 12 +-- src/cmd/compile/internal/types2/type.go | 46 +++++++-- src/cmd/compile/internal/types2/typestring.go | 4 +- src/cmd/compile/internal/types2/typexpr.go | 2 +- 17 files changed, 186 insertions(+), 43 deletions(-) diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go index f80a918467..5d3c2c8ad2 100644 --- a/src/cmd/compile/internal/types2/check.go +++ b/src/cmd/compile/internal/types2/check.go @@ -71,7 +71,7 @@ type importKey struct { // A dotImportKey describes a dot-imported object in the given scope. type dotImportKey struct { scope *Scope - obj Object + name string } // A Checker maintains the state of the type checker. diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index aa70f3880b..00b4ef7010 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -522,7 +522,7 @@ func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init syntax.Expr) { // is detected, the result is Typ[Invalid]. If a cycle is detected and // n0.check != nil, the cycle is reported. func (n0 *Named) under() Type { - u := n0.underlying + u := n0.Underlying() if u == Typ[Invalid] { return u @@ -560,7 +560,7 @@ func (n0 *Named) under() Type { seen := map[*Named]int{n0: 0} path := []Object{n0.obj} for { - u = n.underlying + u = n.Underlying() if u == nil { u = Typ[Invalid] break @@ -764,7 +764,7 @@ func (check *Checker) collectMethods(obj *TypeName) { // and field names must be distinct." base := asNamed(obj.typ) // shouldn't fail but be conservative if base != nil { - if t, _ := base.underlying.(*Struct); t != nil { + if t, _ := base.Underlying().(*Struct); t != nil { for _, fld := range t.fields { if fld.name != "_" { assert(mset.insert(fld) == nil) @@ -806,6 +806,7 @@ func (check *Checker) collectMethods(obj *TypeName) { } if base != nil { + base.expand() // TODO(mdempsky): Probably unnecessary. base.methods = append(base.methods, m) } } diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 0df52e851c..85c897a909 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -23,7 +23,7 @@ func Instantiate(pos syntax.Pos, typ Type, targs []Type) (res Type) { var tparams []*TypeName switch t := typ.(type) { case *Named: - tparams = t.tparams + tparams = t.TParams() case *Signature: tparams = t.tparams defer func() { @@ -61,3 +61,19 @@ func Instantiate(pos syntax.Pos, typ Type, targs []Type) (res Type) { smap := makeSubstMap(tparams, targs) return (*Checker)(nil).subst(pos, typ, smap) } + +// InstantiateLazy is like Instantiate, but avoids actually +// instantiating the type until needed. +func (check *Checker) InstantiateLazy(pos syntax.Pos, typ Type, targs []Type) (res Type) { + base := asNamed(typ) + if base == nil { + panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) + } + + return &instance{ + check: check, + pos: pos, + base: base, + targs: targs, + } +} diff --git a/src/cmd/compile/internal/types2/labels.go b/src/cmd/compile/internal/types2/labels.go index d3206988b5..6f02e2fc96 100644 --- a/src/cmd/compile/internal/types2/labels.go +++ b/src/cmd/compile/internal/types2/labels.go @@ -32,7 +32,8 @@ func (check *Checker) labels(body *syntax.BlockStmt) { } // spec: "It is illegal to define a label that is never used." - for _, obj := range all.elems { + for name, obj := range all.elems { + obj = resolve(name, obj) if lbl := obj.(*Label); !lbl.used { check.softErrorf(lbl.pos, "label %s declared but not used", lbl.name) } diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index eb2b17dd4d..93ed620449 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -54,7 +54,7 @@ func (check *Checker) lookupFieldOrMethod(T Type, addressable bool, pkg *Package // pointer type but discard the result if it is a method since we would // not have found it for T (see also issue 8590). if t := asNamed(T); t != nil { - if p, _ := t.underlying.(*Pointer); p != nil { + if p, _ := t.Underlying().(*Pointer); p != nil { obj, index, indirect = check.rawLookupFieldOrMethod(p, false, pkg, name) if _, ok := obj.(*Func); ok { return nil, nil, false @@ -126,6 +126,7 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack seen[named] = true // look for a matching attached method + named.expand() if i, m := lookupMethod(named.methods, pkg, name); m != nil { // potential match // caution: method may not have a proper signature yet @@ -400,7 +401,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // In order to compare the signatures, substitute the receiver // type parameters of ftyp with V's instantiation type arguments. // This lazily instantiates the signature of method f. - if Vn != nil && len(Vn.tparams) > 0 { + if Vn != nil && len(Vn.TParams()) > 0 { // Be careful: The number of type arguments may not match // the number of receiver parameters. If so, an error was // reported earlier but the length discrepancy is still diff --git a/src/cmd/compile/internal/types2/object.go b/src/cmd/compile/internal/types2/object.go index 8ed55f1dbf..82297ff17f 100644 --- a/src/cmd/compile/internal/types2/object.go +++ b/src/cmd/compile/internal/types2/object.go @@ -276,6 +276,14 @@ func NewTypeName(pos syntax.Pos, pkg *Package, name string, typ Type) *TypeName return &TypeName{object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}} } +// NewTypeNameLazy returns a new defined type like NewTypeName, but it +// lazily calls resolve to finish constructing the Named object. +func NewTypeNameLazy(pos syntax.Pos, pkg *Package, name string, resolve func(named *Named) (tparams []*TypeName, underlying Type, methods []*Func)) *TypeName { + obj := NewTypeName(pos, pkg, name, nil) + NewNamed(obj, nil, nil).resolve = resolve + return obj +} + // IsAlias reports whether obj is an alias name for a type. func (obj *TypeName) IsAlias() bool { switch t := obj.typ.(type) { diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 74436836cd..66de249044 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -21,7 +21,7 @@ func isNamed(typ Type) bool { func isGeneric(typ Type) bool { // A parameterized type is only instantiated if it doesn't have an instantiation already. named, _ := typ.(*Named) - return named != nil && named.obj != nil && named.tparams != nil && named.targs == nil + return named != nil && named.obj != nil && named.TParams() != nil && named.targs == nil } func is(typ Type, what BasicInfo) bool { diff --git a/src/cmd/compile/internal/types2/resolver.go b/src/cmd/compile/internal/types2/resolver.go index 9b1482b14e..018a20cfb2 100644 --- a/src/cmd/compile/internal/types2/resolver.go +++ b/src/cmd/compile/internal/types2/resolver.go @@ -308,22 +308,26 @@ func (check *Checker) collectObjects() { check.dotImportMap = make(map[dotImportKey]*PkgName) } // merge imported scope with file scope - for _, obj := range imp.scope.elems { + for name, obj := range imp.scope.elems { + // Note: Avoid eager resolve(name, obj) here, so we only + // resolve dot-imported objects as needed. + // A package scope may contain non-exported objects, // do not import them! - if obj.Exported() { + if isExported(name) { // declare dot-imported object // (Do not use check.declare because it modifies the object // via Object.setScopePos, which leads to a race condition; // the object may be imported into more than one file scope // concurrently. See issue #32154.) - if alt := fileScope.Insert(obj); alt != nil { + if alt := fileScope.Lookup(name); alt != nil { var err error_ - err.errorf(s.LocalPkgName, "%s redeclared in this block", obj.Name()) + err.errorf(s.LocalPkgName, "%s redeclared in this block", alt.Name()) err.recordAltDecl(alt) check.report(&err) } else { - check.dotImportMap[dotImportKey{fileScope, obj}] = pkgName + fileScope.insert(name, obj) + check.dotImportMap[dotImportKey{fileScope, name}] = pkgName } } } @@ -469,8 +473,9 @@ func (check *Checker) collectObjects() { // verify that objects in package and file scopes have different names for _, scope := range fileScopes { - for _, obj := range scope.elems { - if alt := pkg.scope.Lookup(obj.Name()); alt != nil { + for name, obj := range scope.elems { + if alt := pkg.scope.Lookup(name); alt != nil { + obj = resolve(name, obj) var err error_ if pkg, ok := obj.(*PkgName); ok { err.errorf(alt, "%s already declared through import of %s", alt.Name(), pkg.Imported()) diff --git a/src/cmd/compile/internal/types2/sanitize.go b/src/cmd/compile/internal/types2/sanitize.go index 03aef90fe1..4e654e074f 100644 --- a/src/cmd/compile/internal/types2/sanitize.go +++ b/src/cmd/compile/internal/types2/sanitize.go @@ -134,6 +134,7 @@ func (s sanitizer) typ(typ Type) Type { if debug && t.check != nil { panic("internal error: Named.check != nil") } + t.expand() if orig := s.typ(t.fromRHS); orig != t.fromRHS { t.fromRHS = orig } diff --git a/src/cmd/compile/internal/types2/scope.go b/src/cmd/compile/internal/types2/scope.go index ade0a79b31..2f1814a631 100644 --- a/src/cmd/compile/internal/types2/scope.go +++ b/src/cmd/compile/internal/types2/scope.go @@ -13,6 +13,7 @@ import ( "io" "sort" "strings" + "sync" ) // A Scope maintains a set of objects and links to its containing @@ -66,7 +67,7 @@ func (s *Scope) Child(i int) *Scope { return s.children[i] } // Lookup returns the object in scope s with the given name if such an // object exists; otherwise the result is nil. func (s *Scope) Lookup(name string) Object { - return s.elems[name] + return resolve(name, s.elems[name]) } // LookupParent follows the parent chain of scopes starting with s until @@ -81,7 +82,7 @@ func (s *Scope) Lookup(name string) Object { // whose scope is the scope of the package that exported them. func (s *Scope) LookupParent(name string, pos syntax.Pos) (*Scope, Object) { for ; s != nil; s = s.parent { - if obj := s.elems[name]; obj != nil && (!pos.IsKnown() || obj.scopePos().Cmp(pos) <= 0) { + if obj := s.Lookup(name); obj != nil && (!pos.IsKnown() || obj.scopePos().Cmp(pos) <= 0) { return s, obj } } @@ -95,19 +96,38 @@ func (s *Scope) LookupParent(name string, pos syntax.Pos) (*Scope, Object) { // if not already set, and returns nil. func (s *Scope) Insert(obj Object) Object { name := obj.Name() - if alt := s.elems[name]; alt != nil { + if alt := s.Lookup(name); alt != nil { return alt } - if s.elems == nil { - s.elems = make(map[string]Object) - } - s.elems[name] = obj + s.insert(name, obj) if obj.Parent() == nil { obj.setParent(s) } return nil } +// InsertLazy is like Insert, but allows deferring construction of the +// inserted object until it's accessed with Lookup. The Object +// returned by resolve must have the same name as given to InsertLazy. +// If s already contains an alternative object with the same name, +// InsertLazy leaves s unchanged and returns false. Otherwise it +// records the binding and returns true. The object's parent scope +// will be set to s after resolve is called. +func (s *Scope) InsertLazy(name string, resolve func() Object) bool { + if s.elems[name] != nil { + return false + } + s.insert(name, &lazyObject{parent: s, resolve: resolve}) + return true +} + +func (s *Scope) insert(name string, obj Object) { + if s.elems == nil { + s.elems = make(map[string]Object) + } + s.elems[name] = obj +} + // Squash merges s with its parent scope p by adding all // objects of s to p, adding all children of s to the // children of p, and removing s from p's children. @@ -117,7 +137,8 @@ func (s *Scope) Insert(obj Object) Object { func (s *Scope) Squash(err func(obj, alt Object)) { p := s.parent assert(p != nil) - for _, obj := range s.elems { + for name, obj := range s.elems { + obj = resolve(name, obj) obj.setParent(nil) if alt := p.Insert(obj); alt != nil { err(obj, alt) @@ -196,7 +217,7 @@ func (s *Scope) WriteTo(w io.Writer, n int, recurse bool) { indn1 := indn + ind for _, name := range s.Names() { - fmt.Fprintf(w, "%s%s\n", indn1, s.elems[name]) + fmt.Fprintf(w, "%s%s\n", indn1, s.Lookup(name)) } if recurse { @@ -214,3 +235,57 @@ func (s *Scope) String() string { s.WriteTo(&buf, 0, false) return buf.String() } + +// A lazyObject represents an imported Object that has not been fully +// resolved yet by its importer. +type lazyObject struct { + parent *Scope + resolve func() Object + obj Object + once sync.Once +} + +// resolve returns the Object represented by obj, resolving lazy +// objects as appropriate. +func resolve(name string, obj Object) Object { + if lazy, ok := obj.(*lazyObject); ok { + lazy.once.Do(func() { + obj := lazy.resolve() + + if _, ok := obj.(*lazyObject); ok { + panic("recursive lazy object") + } + if obj.Name() != name { + panic("lazy object has unexpected name") + } + + if obj.Parent() == nil { + obj.setParent(lazy.parent) + } + lazy.obj = obj + }) + + obj = lazy.obj + } + return obj +} + +// stub implementations so *lazyObject implements Object and we can +// store them directly into Scope.elems. +func (*lazyObject) Parent() *Scope { panic("unreachable") } +func (*lazyObject) Pos() syntax.Pos { panic("unreachable") } +func (*lazyObject) Pkg() *Package { panic("unreachable") } +func (*lazyObject) Name() string { panic("unreachable") } +func (*lazyObject) Type() Type { panic("unreachable") } +func (*lazyObject) Exported() bool { panic("unreachable") } +func (*lazyObject) Id() string { panic("unreachable") } +func (*lazyObject) String() string { panic("unreachable") } +func (*lazyObject) order() uint32 { panic("unreachable") } +func (*lazyObject) color() color { panic("unreachable") } +func (*lazyObject) setType(Type) { panic("unreachable") } +func (*lazyObject) setOrder(uint32) { panic("unreachable") } +func (*lazyObject) setColor(color color) { panic("unreachable") } +func (*lazyObject) setParent(*Scope) { panic("unreachable") } +func (*lazyObject) sameId(pkg *Package, name string) bool { panic("unreachable") } +func (*lazyObject) scopePos() syntax.Pos { panic("unreachable") } +func (*lazyObject) setScopePos(pos syntax.Pos) { panic("unreachable") } diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index c8c4cca0a7..a7edc5ac03 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -62,7 +62,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] // again when we type-check the signature. // TODO(gri) maybe the receiver should be marked as invalid instead? if recv := asNamed(check.genericType(rname, false)); recv != nil { - recvTParams = recv.tparams + recvTParams = recv.TParams() } } // provide type parameter bounds diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go index daa039bf92..3cb162764c 100644 --- a/src/cmd/compile/internal/types2/sizeof_test.go +++ b/src/cmd/compile/internal/types2/sizeof_test.go @@ -31,7 +31,7 @@ func TestSizeof(t *testing.T) { {Interface{}, 52, 104}, {Map{}, 16, 32}, {Chan{}, 12, 24}, - {Named{}, 68, 136}, + {Named{}, 84, 160}, {TypeParam{}, 28, 48}, {instance{}, 52, 96}, {top{}, 0, 0}, diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index e9ffd4f5ca..ab66432126 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -64,7 +64,8 @@ func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body func (check *Checker) usage(scope *Scope) { var unused []*Var - for _, elem := range scope.elems { + for name, elem := range scope.elems { + elem = resolve(name, elem) if v, _ := elem.(*Var); v != nil && !v.used { unused = append(unused, v) } diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 35ca197d64..dd8dd74161 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -76,7 +76,7 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, poslis var tparams []*TypeName switch t := typ.(type) { case *Named: - tparams = t.tparams + tparams = t.TParams() case *Signature: tparams = t.tparams defer func() { @@ -347,7 +347,7 @@ func (subst *subster) typ(typ Type) Type { } } - if t.tparams == nil { + if t.TParams() == nil { dump(">>> %s is not parameterized", t) return t // type is not parameterized } @@ -357,7 +357,7 @@ func (subst *subster) typ(typ Type) Type { if len(t.targs) > 0 { // already instantiated dump(">>> %s already instantiated", t) - assert(len(t.targs) == len(t.tparams)) + assert(len(t.targs) == len(t.TParams())) // For each (existing) type argument targ, determine if it needs // to be substituted; i.e., if it is or contains a type parameter // that has a type argument for it. @@ -367,7 +367,7 @@ func (subst *subster) typ(typ Type) Type { if new_targ != targ { dump(">>> substituted %d targ %s => %s", i, targ, new_targ) if new_targs == nil { - new_targs = make([]Type, len(t.tparams)) + new_targs = make([]Type, len(t.TParams())) copy(new_targs, t.targs) } new_targs[i] = new_targ @@ -397,7 +397,7 @@ func (subst *subster) typ(typ Type) Type { // create a new named type and populate caches to avoid endless recursion tname := NewTypeName(subst.pos, t.obj.pkg, t.obj.name, nil) - named := subst.check.newNamed(tname, t, t.underlying, t.tparams, t.methods) // method signatures are updated lazily + named := subst.check.newNamed(tname, t, t.Underlying(), t.TParams(), t.methods) // method signatures are updated lazily named.targs = new_targs if subst.check != nil { subst.check.typMap[h] = named @@ -406,7 +406,7 @@ func (subst *subster) typ(typ Type) Type { // do the substitution dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, new_targs) - named.underlying = subst.typOrNil(t.underlying) + named.underlying = subst.typOrNil(t.Underlying()) named.fromRHS = named.underlying // for cycle detection (Checker.validType) return named diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 92f35f1279..604520d27f 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -6,6 +6,7 @@ package types2 import ( "cmd/compile/internal/syntax" + "sync" "sync/atomic" ) @@ -497,6 +498,9 @@ type Named struct { tparams []*TypeName // type parameters, or nil targs []Type // type arguments (after instantiation), or nil methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily + + resolve func(*Named) ([]*TypeName, Type, []*Func) + once sync.Once } // NewNamed returns a new named type for the given type name, underlying type, and associated methods. @@ -509,6 +513,35 @@ func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named { return (*Checker)(nil).newNamed(obj, nil, underlying, nil, methods) } +func (t *Named) expand() *Named { + if t.resolve == nil { + return t + } + + t.once.Do(func() { + // TODO(mdempsky): Since we're passing t to resolve anyway + // (necessary because types2 expects the receiver type for methods + // on defined interface types to be the Named rather than the + // underlying Interface), maybe it should just handle calling + // SetTParams, SetUnderlying, and AddMethod instead? Those + // methods would need to support reentrant calls though. It would + // also make the API more future-proof towards further extensions + // (like SetTParams). + + tparams, underlying, methods := t.resolve(t) + + switch underlying.(type) { + case nil, *Named: + panic("invalid underlying type") + } + + t.tparams = tparams + t.underlying = underlying + t.methods = methods + }) + return t +} + // newNamed is like NewNamed but with a *Checker receiver and additional orig argument. func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams []*TypeName, methods []*Func) *Named { typ := &Named{check: check, obj: obj, orig: orig, fromRHS: underlying, underlying: underlying, tparams: tparams, methods: methods} @@ -550,10 +583,10 @@ func (t *Named) Orig() *Named { return t.orig } // TParams returns the type parameters of the named type t, or nil. // The result is non-nil for an (originally) parameterized type even if it is instantiated. -func (t *Named) TParams() []*TypeName { return t.tparams } +func (t *Named) TParams() []*TypeName { return t.expand().tparams } // SetTParams sets the type parameters of the named type t. -func (t *Named) SetTParams(tparams []*TypeName) { t.tparams = tparams } +func (t *Named) SetTParams(tparams []*TypeName) { t.expand().tparams = tparams } // TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated. func (t *Named) TArgs() []Type { return t.targs } @@ -562,10 +595,10 @@ func (t *Named) TArgs() []Type { return t.targs } func (t *Named) SetTArgs(args []Type) { t.targs = args } // NumMethods returns the number of explicit methods whose receiver is named type t. -func (t *Named) NumMethods() int { return len(t.methods) } +func (t *Named) NumMethods() int { return len(t.expand().methods) } // Method returns the i'th method of named type t for 0 <= i < t.NumMethods(). -func (t *Named) Method(i int) *Func { return t.methods[i] } +func (t *Named) Method(i int) *Func { return t.expand().methods[i] } // SetUnderlying sets the underlying type and marks t as complete. func (t *Named) SetUnderlying(underlying Type) { @@ -575,11 +608,12 @@ func (t *Named) SetUnderlying(underlying Type) { if _, ok := underlying.(*Named); ok { panic("types2.Named.SetUnderlying: underlying type must not be *Named") } - t.underlying = underlying + t.expand().underlying = underlying } // AddMethod adds method m unless it is already in the method list. func (t *Named) AddMethod(m *Func) { + t.expand() if i, _ := lookupMethod(t.methods, m.pkg, m.name); i < 0 { t.methods = append(t.methods, m) } @@ -743,7 +777,7 @@ func (t *Signature) Underlying() Type { return t } func (t *Interface) Underlying() Type { return t } func (t *Map) Underlying() Type { return t } func (t *Chan) Underlying() Type { return t } -func (t *Named) Underlying() Type { return t.underlying } +func (t *Named) Underlying() Type { return t.expand().underlying } func (t *TypeParam) Underlying() Type { return t } func (t *instance) Underlying() Type { return t } func (t *top) Underlying() Type { return t } diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 28583b62d9..07ed510d11 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -272,9 +272,9 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { buf.WriteByte('[') writeTypeList(buf, t.targs, qf, visited) buf.WriteByte(']') - } else if t.tparams != nil { + } else if t.TParams() != nil { // parameterized type - writeTParamList(buf, t.tparams, qf, visited) + writeTParamList(buf, t.TParams(), qf, visited) } case *TypeParam: diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index b27b2a00df..583bb464b2 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -58,7 +58,7 @@ func (check *Checker) ident(x *operand, e *syntax.Name, def *Named, wantType boo // If so, mark the respective package as used. // (This code is only needed for dot-imports. Without them, // we only have to mark variables, see *Var case below). - if pkgName := check.dotImportMap[dotImportKey{scope, obj}]; pkgName != nil { + if pkgName := check.dotImportMap[dotImportKey{scope, obj.Name()}]; pkgName != nil { pkgName.used = true } -- GitLab From 298149a915dd9b2ce74593f5f75584f8ed6d6414 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Thu, 6 May 2021 09:08:32 -0400 Subject: [PATCH 0208/2500] [dev.typeparams] go/types: use Checker-provided type parameter IDs when possible Incrementing type parameter subscripts for each type checking pass is distracting for an interactive program where packages are type-checked on each keystroke. We should perhaps hide the type parameter ID altogether, but for now at least add a layer of indirection so that type parameters for a single type-checked package can be stabilized. This change should have no effect on non-generic type checking. For #46003 Change-Id: I60d747e0a2bfb68e7d64e897eac23f609a2a4429 Reviewed-on: https://go-review.googlesource.com/c/go/+/321269 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/api_test.go | 1 - src/go/types/api_typeparams.go | 5 +++++ src/go/types/check.go | 1 + src/go/types/type.go | 17 ++++++++++++----- src/go/types/types_test.go | 8 -------- 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index f37b91d5a4..5a2d4a4ca3 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -353,7 +353,6 @@ func TestTypesInfo(t *testing.T) { } for _, test := range tests { - ResetId() // avoid renumbering of type parameter ids when adding tests if strings.HasPrefix(test.src, genericPkg) && !typeparams.Enabled { continue } diff --git a/src/go/types/api_typeparams.go b/src/go/types/api_typeparams.go index ed744c4dba..ae2c5a7fd0 100644 --- a/src/go/types/api_typeparams.go +++ b/src/go/types/api_typeparams.go @@ -19,6 +19,11 @@ type ( func NewSum(types []Type) Type { return _NewSum(types) } +// NewTypeParam returns a new TypeParam. +func NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam { + return (*Checker)(nil).newTypeParam(obj, index, bound) +} + func (s *Signature) TParams() []*TypeName { return s._TParams() } func (s *Signature) SetTParams(tparams []*TypeName) { s._SetTParams(tparams) } diff --git a/src/go/types/check.go b/src/go/types/check.go index a923c3c612..e82056e722 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -86,6 +86,7 @@ type Checker struct { pkg *Package *Info version version // accepted language version + nextID uint64 // unique Id for type parameters (first valid Id is 1) objMap map[Object]*declInfo // maps package-level objects and (non-interface) methods to declaration info impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package posMap map[*Interface][]token.Pos // maps interface types to lists of embedded interface positions diff --git a/src/go/types/type.go b/src/go/types/type.go index 2660ce4408..2ea4d76d8b 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -732,11 +732,11 @@ func (t *Named) AddMethod(m *Func) { // Note: This is a uint32 rather than a uint64 because the // respective 64 bit atomic instructions are not available // on all platforms. -var lastId uint32 +var lastID uint32 -// nextId returns a value increasing monotonically by 1 with +// nextID returns a value increasing monotonically by 1 with // each call, starting with 1. It may be called concurrently. -func nextId() uint64 { return uint64(atomic.AddUint32(&lastId, 1)) } +func nextID() uint64 { return uint64(atomic.AddUint32(&lastID, 1)) } // A _TypeParam represents a type parameter type. type _TypeParam struct { @@ -747,10 +747,17 @@ type _TypeParam struct { bound Type // *Named or *Interface; underlying type is always *Interface } -// newTypeParam returns a new TypeParam. func (check *Checker) newTypeParam(obj *TypeName, index int, bound Type) *_TypeParam { assert(bound != nil) - typ := &_TypeParam{check: check, id: nextId(), obj: obj, index: index, bound: bound} + + // Always increment lastID, even if it is not used. + id := nextID() + if check != nil { + check.nextID++ + id = check.nextID + } + + typ := &_TypeParam{check: check, id: id, obj: obj, index: index, bound: bound} if obj.typ == nil { obj.typ = typ } diff --git a/src/go/types/types_test.go b/src/go/types/types_test.go index 25cd996628..e1a40f1f6e 100644 --- a/src/go/types/types_test.go +++ b/src/go/types/types_test.go @@ -4,14 +4,6 @@ package types -import "sync/atomic" - -// Upon calling ResetId, nextId starts with 1 again. -// It may be called concurrently. This is only needed -// for tests where we may want to have a consistent -// numbering for each individual test case. -func ResetId() { atomic.StoreUint32(&lastId, 0) } - // SetGoVersion sets the unexported goVersion field on config, so that tests // which assert on behavior for older Go versions can set it. func SetGoVersion(config *Config, goVersion string) { -- GitLab From 410fa4c75b7487cc92f48e4b4ca037830348b963 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Wed, 19 May 2021 15:51:45 -0400 Subject: [PATCH 0209/2500] [dev.typeparams] go/types: rename Inferred.Targs to TArgs This is consistent with Named.TArgs. Change-Id: Ib25f7ac5b7242e169c8c1701dfa407f763f26125 Reviewed-on: https://go-review.googlesource.com/c/go/+/321289 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/api.go | 2 +- src/go/types/api_typeparams_test.go | 2 +- src/go/types/sanitize.go | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/go/types/api.go b/src/go/types/api.go index 8c0d9d22bf..30f8ded744 100644 --- a/src/go/types/api.go +++ b/src/go/types/api.go @@ -255,7 +255,7 @@ func (tv TypeAndValue) HasOk() bool { // _Inferred reports the _Inferred type arguments and signature // for a parameterized function call that uses type inference. type _Inferred struct { - Targs []Type + TArgs []Type Sig *Signature } diff --git a/src/go/types/api_typeparams_test.go b/src/go/types/api_typeparams_test.go index 15c9bf09f9..517c58505b 100644 --- a/src/go/types/api_typeparams_test.go +++ b/src/go/types/api_typeparams_test.go @@ -109,7 +109,7 @@ func TestInferredInfo(t *testing.T) { panic(fmt.Sprintf("unexpected call expression type %T", call)) } if ExprString(fun) == test.fun { - targs = inf.Targs + targs = inf.TArgs sig = inf.Sig break } diff --git a/src/go/types/sanitize.go b/src/go/types/sanitize.go index 727ec173ea..f167cdd8b6 100644 --- a/src/go/types/sanitize.go +++ b/src/go/types/sanitize.go @@ -27,9 +27,9 @@ func sanitizeInfo(info *Info) { inferred := getInferred(info) for e, inf := range inferred { changed := false - for i, targ := range inf.Targs { + for i, targ := range inf.TArgs { if typ := s.typ(targ); typ != targ { - inf.Targs[i] = typ + inf.TArgs[i] = typ changed = true } } -- GitLab From d7592ab4242484110ac8af636f9152faeb3197d6 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Thu, 3 Jun 2021 09:29:35 -0400 Subject: [PATCH 0210/2500] [dev.typeparams] go/types: implement types.Instantiate This is a straightforward port of CL 314773 to go/types. Change-Id: If9e2d6d99790d694615389acbe6ccb3c8c0bd1da Reviewed-on: https://go-review.googlesource.com/c/go/+/324729 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/instantiate.go | 63 +++++++++++++++++++++++++++++++++++++ src/go/types/subst.go | 31 +++++++++++------- 2 files changed, 83 insertions(+), 11 deletions(-) create mode 100644 src/go/types/instantiate.go diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go new file mode 100644 index 0000000000..6f8c4983f4 --- /dev/null +++ b/src/go/types/instantiate.go @@ -0,0 +1,63 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +import ( + "fmt" + "go/token" +) + +// Instantiate instantiates the type typ with the given type arguments. +// typ must be a *Named or a *Signature type, it must be generic, and +// its number of type parameters must match the number of provided type +// arguments. The result is a new, instantiated (not generic) type of +// the same kind (either a *Named or a *Signature). The type arguments +// are not checked against the constraints of the type parameters. +// Any methods attached to a *Named are simply copied; they are not +// instantiated. +func Instantiate(pos token.Pos, typ Type, targs []Type) (res Type) { + // TODO(gri) This code is basically identical to the prolog + // in Checker.instantiate. Factor. + var tparams []*TypeName + switch t := typ.(type) { + case *Named: + tparams = t.tparams + case *Signature: + tparams = t.tparams + defer func() { + // If we had an unexpected failure somewhere don't panic below when + // asserting res.(*Signature). Check for *Signature in case Typ[Invalid] + // is returned. + if _, ok := res.(*Signature); !ok { + return + } + // If the signature doesn't use its type parameters, subst + // will not make a copy. In that case, make a copy now (so + // we can set tparams to nil w/o causing side-effects). + if t == res { + copy := *t + res = © + } + // After instantiating a generic signature, it is not generic + // anymore; we need to set tparams to nil. + res.(*Signature).tparams = nil + }() + + default: + panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) + } + + // the number of supplied types must match the number of type parameters + if len(targs) != len(tparams) { + panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, len(targs), len(tparams))) + } + + if len(tparams) == 0 { + return typ // nothing to do (minor optimization) + } + + smap := makeSubstMap(tparams, targs) + return (*Checker)(nil).subst(pos, typ, smap) +} diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 931375f1f2..d27f3645cc 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -311,6 +311,9 @@ func (subst *subster) typ(typ Type) Type { embeddeds, ecopied := subst.typeList(t.embeddeds) if mcopied || types != t.types || ecopied { iface := &Interface{methods: methods, types: types, embeddeds: embeddeds} + if subst.check == nil { + panic("internal error: cannot instantiate interfaces yet") + } subst.check.posMap[iface] = subst.check.posMap[t] // satisfy completeInterface requirement subst.check.completeInterface(token.NoPos, iface) return iface @@ -330,12 +333,14 @@ func (subst *subster) typ(typ Type) Type { } case *Named: - subst.check.indent++ - defer func() { - subst.check.indent-- - }() - dump := func(format string, args ...interface{}) { - if trace { + // dump is for debugging + dump := func(string, ...interface{}) {} + if subst.check != nil && trace { + subst.check.indent++ + defer func() { + subst.check.indent-- + }() + dump = func(format string, args ...interface{}) { subst.check.trace(subst.pos, format, args...) } } @@ -381,10 +386,12 @@ func (subst *subster) typ(typ Type) Type { // before creating a new named type, check if we have this one already h := instantiatedHash(t, newTargs) dump(">>> new type hash: %s", h) - if named, found := subst.check.typMap[h]; found { - dump(">>> found %s", named) - subst.cache[t] = named - return named + if subst.check != nil { + if named, found := subst.check.typMap[h]; found { + dump(">>> found %s", named) + subst.cache[t] = named + return named + } } // create a new named type and populate caches to avoid endless recursion @@ -392,7 +399,9 @@ func (subst *subster) typ(typ Type) Type { named := subst.check.newNamed(tname, t.underlying, t.methods) // method signatures are updated lazily named.tparams = t.tparams // new type is still parameterized named.targs = newTargs - subst.check.typMap[h] = named + if subst.check != nil { + subst.check.typMap[h] = named + } subst.cache[t] = named // do the substitution -- GitLab From 655246f99a22950985a9ab9fc1e0bb4a8cb2ea7e Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Thu, 3 Jun 2021 09:45:01 -0400 Subject: [PATCH 0211/2500] [dev.typeparams] go/types: make TestManual work for directories This is a port of CL 315769 to go/types, adjusted for the additional testPkg indirection in go/types on top of testFiles, and to remove the colDelta argument. Change-Id: Ieb722d77866313a01645aeec49912c16cb475462 Reviewed-on: https://go-review.googlesource.com/c/go/+/324730 Trust: Robert Findley Trust: Robert Griesemer Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/check_test.go | 98 +++++++++++++++++++---------- src/go/types/testdata/check/tmp.go2 | 17 ----- src/go/types/testdata/manual.go2 | 9 +++ 3 files changed, 73 insertions(+), 51 deletions(-) delete mode 100644 src/go/types/testdata/check/tmp.go2 create mode 100644 src/go/types/testdata/manual.go2 diff --git a/src/go/types/check_test.go b/src/go/types/check_test.go index 6c3b630a1b..0926ac7431 100644 --- a/src/go/types/check_test.go +++ b/src/go/types/check_test.go @@ -202,7 +202,7 @@ func asGoVersion(s string) string { return "" } -func checkFiles(t *testing.T, sizes Sizes, goVersion string, filenames []string, srcs [][]byte, manual bool) { +func testFiles(t *testing.T, sizes Sizes, filenames []string, srcs [][]byte, manual bool) { if len(filenames) == 0 { t.Fatal("no source files") } @@ -225,6 +225,7 @@ func checkFiles(t *testing.T, sizes Sizes, goVersion string, filenames []string, } // if no Go version is given, consider the package name + goVersion := *goVersion if goVersion == "" { goVersion = asGoVersion(pkgName) } @@ -297,29 +298,48 @@ func checkFiles(t *testing.T, sizes Sizes, goVersion string, filenames []string, } } -// TestManual is for manual testing of input files, provided as a list -// of arguments after the test arguments (and a separating "--"). For -// instance, to check the files foo.go and bar.go, use: +// TestManual is for manual testing of a package - either provided +// as a list of filenames belonging to the package, or a directory +// name containing the package files - after the test arguments +// (and a separating "--"). For instance, to test the package made +// of the files foo.go and bar.go, use: // // go test -run Manual -- foo.go bar.go // -// Provide the -verify flag to verify errors against ERROR comments in -// the input files rather than having a list of errors reported. -// The accepted Go language version can be controlled with the -lang flag. +// If no source arguments are provided, the file testdata/manual.go2 +// is used instead. +// Provide the -verify flag to verify errors against ERROR comments +// in the input files rather than having a list of errors reported. +// The accepted Go language version can be controlled with the -lang +// flag. func TestManual(t *testing.T) { + testenv.MustHaveGoBuild(t) + filenames := flag.Args() if len(filenames) == 0 { - return + filenames = []string{filepath.FromSlash("testdata/manual.go2")} } - testenv.MustHaveGoBuild(t) + + info, err := os.Stat(filenames[0]) + if err != nil { + t.Fatalf("TestManual: %v", err) + } + DefPredeclaredTestFuncs() - testPkg(t, filenames, *goVersion, true) + if info.IsDir() { + if len(filenames) > 1 { + t.Fatal("TestManual: must have only one directory argument") + } + testDir(t, filenames[0], true) + } else { + testPkg(t, filenames, true) + } } func TestLongConstants(t *testing.T) { format := "package longconst\n\nconst _ = %s\nconst _ = %s // ERROR excessively long constant" src := fmt.Sprintf(format, strings.Repeat("1", 9999), strings.Repeat("1", 10001)) - checkFiles(t, nil, "", []string{"longconst.go"}, [][]byte{[]byte(src)}, false) + testFiles(t, nil, []string{"longconst.go"}, [][]byte{[]byte(src)}, false) } // TestIndexRepresentability tests that constant index operands must @@ -327,7 +347,7 @@ func TestLongConstants(t *testing.T) { // represent larger values. func TestIndexRepresentability(t *testing.T) { const src = "package index\n\nvar s []byte\nvar _ = s[int64 /* ERROR \"int64\\(1\\) << 40 \\(.*\\) overflows int\" */ (1) << 40]" - checkFiles(t, &StdSizes{4, 4}, "", []string{"index.go"}, [][]byte{[]byte(src)}, false) + testFiles(t, &StdSizes{4, 4}, []string{"index.go"}, [][]byte{[]byte(src)}, false) } func TestIssue46453(t *testing.T) { @@ -335,17 +355,17 @@ func TestIssue46453(t *testing.T) { t.Skip("type params are enabled") } const src = "package p\ntype _ comparable // ERROR \"undeclared name: comparable\"" - checkFiles(t, nil, "", []string{"issue46453.go"}, [][]byte{[]byte(src)}, false) + testFiles(t, nil, []string{"issue46453.go"}, [][]byte{[]byte(src)}, false) } -func TestCheck(t *testing.T) { DefPredeclaredTestFuncs(); testDir(t, "check") } -func TestExamples(t *testing.T) { testDir(t, "examples") } -func TestFixedbugs(t *testing.T) { testDir(t, "fixedbugs") } +func TestCheck(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/check", false) } +func TestExamples(t *testing.T) { testDirFiles(t, "testdata/examples", false) } +func TestFixedbugs(t *testing.T) { testDirFiles(t, "testdata/fixedbugs", false) } -func testDir(t *testing.T, dir string) { +func testDirFiles(t *testing.T, dir string, manual bool) { testenv.MustHaveGoBuild(t) + dir = filepath.FromSlash(dir) - dir = filepath.Join("testdata", dir) fis, err := os.ReadDir(dir) if err != nil { t.Error(err) @@ -355,28 +375,38 @@ func testDir(t *testing.T, dir string) { for _, fi := range fis { path := filepath.Join(dir, fi.Name()) - // if fi is a directory, its files make up a single package - var filenames []string + // If fi is a directory, its files make up a single package. if fi.IsDir() { - fis, err := os.ReadDir(path) - if err != nil { - t.Error(err) - continue - } - for _, fi := range fis { - filenames = append(filenames, filepath.Join(path, fi.Name())) - } + testDir(t, path, manual) } else { - filenames = []string{path} + t.Run(filepath.Base(path), func(t *testing.T) { + testPkg(t, []string{path}, manual) + }) } - t.Run(filepath.Base(path), func(t *testing.T) { - testPkg(t, filenames, "", false) - }) } } +func testDir(t *testing.T, dir string, manual bool) { + testenv.MustHaveGoBuild(t) + + fis, err := os.ReadDir(dir) + if err != nil { + t.Error(err) + return + } + + var filenames []string + for _, fi := range fis { + filenames = append(filenames, filepath.Join(dir, fi.Name())) + } + + t.Run(filepath.Base(dir), func(t *testing.T) { + testPkg(t, filenames, manual) + }) +} + // TODO(rFindley) reconcile the different test setup in go/types with types2. -func testPkg(t *testing.T, filenames []string, goVersion string, manual bool) { +func testPkg(t *testing.T, filenames []string, manual bool) { srcs := make([][]byte, len(filenames)) for i, filename := range filenames { src, err := os.ReadFile(filename) @@ -385,5 +415,5 @@ func testPkg(t *testing.T, filenames []string, goVersion string, manual bool) { } srcs[i] = src } - checkFiles(t, nil, goVersion, filenames, srcs, manual) + testFiles(t, nil, filenames, srcs, manual) } diff --git a/src/go/types/testdata/check/tmp.go2 b/src/go/types/testdata/check/tmp.go2 deleted file mode 100644 index dae78caff8..0000000000 --- a/src/go/types/testdata/check/tmp.go2 +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This file is meant as "dumping ground" for debugging code. - -package p - -// fun test case -type C[P interface{m()}] P - -func (r C[P]) m() { r.m() } - -func f[T interface{m(); n()}](x T) { - y := C[T](x) - y.m() -} diff --git a/src/go/types/testdata/manual.go2 b/src/go/types/testdata/manual.go2 new file mode 100644 index 0000000000..25e6f22f94 --- /dev/null +++ b/src/go/types/testdata/manual.go2 @@ -0,0 +1,9 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file is tested when running "go test -run Manual" +// without source arguments. Use for one-off debugging. + +package p + -- GitLab From cd6e9df446680d591c28c08d2cc768ec014cf29d Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Thu, 3 Jun 2021 09:49:21 -0400 Subject: [PATCH 0212/2500] [dev.typeparams] go/types: print "incomplete" for interfaces in debug mode only This is a straightforward port of CL 320150 to go/types. Fixes #46167 Change-Id: Id1845046f598ac4fefd68cda6a5a03b7a5fc5a4a Reviewed-on: https://go-review.googlesource.com/c/go/+/324731 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/types_test.go | 3 +++ src/go/types/typestring.go | 2 +- src/go/types/typestring_test.go | 4 ++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/go/types/types_test.go b/src/go/types/types_test.go index e1a40f1f6e..7990414f42 100644 --- a/src/go/types/types_test.go +++ b/src/go/types/types_test.go @@ -9,3 +9,6 @@ package types func SetGoVersion(config *Config, goVersion string) { config.goVersion = goVersion } + +// Debug is set if go/types is built with debug mode enabled. +const Debug = debug diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index fe27f0f276..ff93f3b3c3 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -227,7 +227,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { empty = false } } - if t.allMethods == nil || len(t.methods) > len(t.allMethods) { + if debug && (t.allMethods == nil || len(t.methods) > len(t.allMethods)) { if !empty { buf.WriteByte(' ') } diff --git a/src/go/types/typestring_test.go b/src/go/types/typestring_test.go index b16529dc64..55ee4b987f 100644 --- a/src/go/types/typestring_test.go +++ b/src/go/types/typestring_test.go @@ -143,6 +143,10 @@ func TestTypeString(t *testing.T) { } func TestIncompleteInterfaces(t *testing.T) { + if !Debug { + t.Skip("requires type checker to be compiled with debug = true") + } + sig := NewSignature(nil, nil, nil, false) m := NewFunc(token.NoPos, nil, "m", sig) for _, test := range []struct { -- GitLab From e32fab145b488cf8bd1fb4a2466cb9be33ac3770 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Thu, 3 Jun 2021 09:52:05 -0400 Subject: [PATCH 0213/2500] [dev.typeparams] go/types: fix panic with nil package name This is a straightforward port of CL 320490 to go/types. Change-Id: I763c806c777f926a563d8f9384764e5b3f7f083c Reviewed-on: https://go-review.googlesource.com/c/go/+/324732 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/resolver.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/go/types/resolver.go b/src/go/types/resolver.go index 114647a2ff..4892218b75 100644 --- a/src/go/types/resolver.go +++ b/src/go/types/resolver.go @@ -276,7 +276,7 @@ func (check *Checker) collectObjects() { } if name == "init" { - check.errorf(d.spec.Name, _InvalidInitDecl, "cannot import package as init - init must be a func") + check.errorf(d.spec, _InvalidInitDecl, "cannot import package as init - init must be a func") return } -- GitLab From 62c40878e47c71b1e291e9c3064d76c16a6f9d69 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Thu, 3 Jun 2021 10:12:37 -0400 Subject: [PATCH 0214/2500] [dev.typeparams] go/types: better recv Var for method expressions This is a port of CL 320489 to go/types, adjusted to be consistent about named/unnamed parameters. TestEvalPos was failing without this addition. For #46209 Change-Id: Icdf86e84ebce8ccdb7846a63b5605e360e2b8781 Reviewed-on: https://go-review.googlesource.com/c/go/+/324733 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/call.go | 25 +++++++++++++++++++++++-- src/go/types/testdata/check/decls0.src | 8 ++++---- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/go/types/call.go b/src/go/types/call.go index 631ea426c6..3a04121e98 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -575,17 +575,38 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { check.recordSelection(e, MethodExpr, x.typ, m, index, indirect) + sig := m.typ.(*Signature) + if sig.recv == nil { + check.error(e, _InvalidDeclCycle, "illegal cycle in method declaration") + goto Error + } + // the receiver type becomes the type of the first function // argument of the method expression's function type var params []*Var - sig := m.typ.(*Signature) if sig.params != nil { params = sig.params.vars } + // Be consistent about named/unnamed parameters. + needName := true + for _, param := range params { + if param.Name() == "" { + needName = false + break + } + } + name := "" + if needName { + name = sig.recv.name + if name == "" { + name = "_" + } + } + params = append([]*Var{NewVar(sig.recv.pos, sig.recv.pkg, name, x.typ)}, params...) x.mode = value x.typ = &Signature{ tparams: sig.tparams, - params: NewTuple(append([]*Var{NewVar(token.NoPos, check.pkg, "_", x.typ)}, params...)...), + params: NewTuple(params...), results: sig.results, variadic: sig.variadic, } diff --git a/src/go/types/testdata/check/decls0.src b/src/go/types/testdata/check/decls0.src index 5ad8f53f65..09904bb303 100644 --- a/src/go/types/testdata/check/decls0.src +++ b/src/go/types/testdata/check/decls0.src @@ -187,10 +187,10 @@ func f4() (x *f4 /* ERROR "not a type" */ ) { return } // TODO(#43215) this should be detected as a cycle error func f5([unsafe.Sizeof(f5)]int) {} -func (S0) m1 (x S0 /* ERROR value .* is not a type */ .m1) {} -func (S0) m2 (x *S0 /* ERROR value .* is not a type */ .m2) {} -func (S0) m3 () (x S0 /* ERROR value .* is not a type */ .m3) { return } -func (S0) m4 () (x *S0 /* ERROR value .* is not a type */ .m4) { return } +func (S0) m1 (x S0 /* ERROR illegal cycle in method declaration */ .m1) {} +func (S0) m2 (x *S0 /* ERROR illegal cycle in method declaration */ .m2) {} +func (S0) m3 () (x S0 /* ERROR illegal cycle in method declaration */ .m3) { return } +func (S0) m4 () (x *S0 /* ERROR illegal cycle in method declaration */ .m4) { return } // interfaces may not have any blank methods type BlankI interface { -- GitLab From 090a17c99847166ac25ce33397e6adf83cc40a1d Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Thu, 3 Jun 2021 10:57:09 -0400 Subject: [PATCH 0215/2500] [dev.typeparams] go/types: use correct type parameter list in missingMethod This is a port of CL 321232 to go/types, adjusted to add a missing comment and to remove optional support for method type params. Fixes #46275 Change-Id: I63fcbb669e7607876a888fca89b9064568805448 Reviewed-on: https://go-review.googlesource.com/c/go/+/324751 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/lookup.go | 9 ++++++- .../types/testdata/fixedbugs/issue46275.go2 | 27 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 src/go/types/testdata/fixedbugs/issue46275.go2 diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index 9c7bfd4bb9..3e89b6cc2b 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -327,11 +327,15 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, return m, f } + // both methods must have the same number of type parameters ftyp := f.typ.(*Signature) mtyp := m.typ.(*Signature) if len(ftyp.tparams) != len(mtyp.tparams) { return m, f } + if len(ftyp.tparams) > 0 { + panic("internal error: method with type parameters") + } // If the methods have type parameters we don't care whether they // are the same or not, as long as they match up. Use unification @@ -385,6 +389,9 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, if len(ftyp.tparams) != len(mtyp.tparams) { return m, f } + if len(ftyp.tparams) > 0 { + panic("internal error: method with type parameters") + } // If V is a (instantiated) generic type, its methods are still // parameterized using the original (declaration) receiver type @@ -412,7 +419,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // TODO(gri) is this always correct? what about type bounds? // (Alternative is to rename/subst type parameters and compare.) u := newUnifier(check, true) - u.x.init(ftyp.tparams) + u.x.init(ftyp.rparams) if !u.unify(ftyp, mtyp) { return m, f } diff --git a/src/go/types/testdata/fixedbugs/issue46275.go2 b/src/go/types/testdata/fixedbugs/issue46275.go2 new file mode 100644 index 0000000000..0ebde31c8e --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue46275.go2 @@ -0,0 +1,27 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package issue46275 + +type N[T any] struct { + *N[T] + t T +} + +func (n *N[T]) Elem() T { + return n.t +} + +type I interface { + Elem() string +} + +func _() { + var n1 *N[string] + var _ I = n1 + type NS N[string] + var n2 *NS + var _ I = n2 +} + -- GitLab From ffc74ad5d3241f3fed48816e25802967cfd6fb07 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Thu, 3 Jun 2021 11:04:50 -0400 Subject: [PATCH 0216/2500] [dev.typeparams] go/types: move interface checking into separate file This is a port of CL 321549 to go/types. Specifically, the same checker methods were moved. Change-Id: I491a8c5a985d71ebb23e4b34541a557da0af0cfc Reviewed-on: https://go-review.googlesource.com/c/go/+/324752 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/interface.go | 321 ++++++++++++++++++++++++++++++++++++++ src/go/types/typexpr.go | 310 ------------------------------------ 2 files changed, 321 insertions(+), 310 deletions(-) create mode 100644 src/go/types/interface.go diff --git a/src/go/types/interface.go b/src/go/types/interface.go new file mode 100644 index 0000000000..288e421cae --- /dev/null +++ b/src/go/types/interface.go @@ -0,0 +1,321 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +import ( + "go/ast" + "go/internal/typeparams" + "go/token" + "sort" +) + +func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, def *Named) { + var tlist *ast.Ident // "type" name of first entry in a type list declaration + var types []ast.Expr + for _, f := range iface.Methods.List { + if len(f.Names) > 0 { + // We have a method with name f.Names[0], or a type + // of a type list (name.Name == "type"). + // (The parser ensures that there's only one method + // and we don't care if a constructed AST has more.) + name := f.Names[0] + if name.Name == "_" { + check.errorf(name, _BlankIfaceMethod, "invalid method name _") + continue // ignore + } + + if name.Name == "type" { + // Always collect all type list entries, even from + // different type lists, under the assumption that + // the author intended to include all types. + types = append(types, f.Type) + if tlist != nil && tlist != name { + check.errorf(name, _Todo, "cannot have multiple type lists in an interface") + } + tlist = name + continue + } + + typ := check.typ(f.Type) + sig, _ := typ.(*Signature) + if sig == nil { + if typ != Typ[Invalid] { + check.invalidAST(f.Type, "%s is not a method signature", typ) + } + continue // ignore + } + + // Always type-check method type parameters but complain if they are not enabled. + // (This extra check is needed here because interface method signatures don't have + // a receiver specification.) + if sig.tparams != nil { + var at positioner = f.Type + if tparams := typeparams.Get(f.Type); tparams != nil { + at = tparams + } + check.errorf(at, _Todo, "methods cannot have type parameters") + } + + // use named receiver type if available (for better error messages) + var recvTyp Type = ityp + if def != nil { + recvTyp = def + } + sig.recv = NewVar(name.Pos(), check.pkg, "", recvTyp) + + m := NewFunc(name.Pos(), check.pkg, name.Name, sig) + check.recordDef(name, m) + ityp.methods = append(ityp.methods, m) + } else { + // We have an embedded type. completeInterface will + // eventually verify that we have an interface. + ityp.embeddeds = append(ityp.embeddeds, check.typ(f.Type)) + check.posMap[ityp] = append(check.posMap[ityp], f.Type.Pos()) + } + } + + // type constraints + ityp.types = _NewSum(check.collectTypeConstraints(iface.Pos(), types)) + + if len(ityp.methods) == 0 && ityp.types == nil && len(ityp.embeddeds) == 0 { + // empty interface + ityp.allMethods = markComplete + return + } + + // sort for API stability + sortMethods(ityp.methods) + sortTypes(ityp.embeddeds) + + check.later(func() { check.completeInterface(iface.Pos(), ityp) }) +} + +func (check *Checker) collectTypeConstraints(pos token.Pos, types []ast.Expr) []Type { + list := make([]Type, 0, len(types)) // assume all types are correct + for _, texpr := range types { + if texpr == nil { + check.invalidAST(atPos(pos), "missing type constraint") + continue + } + list = append(list, check.varType(texpr)) + } + + // Ensure that each type is only present once in the type list. Types may be + // interfaces, which may not be complete yet. It's ok to do this check at the + // end because it's not a requirement for correctness of the code. + // Note: This is a quadratic algorithm, but type lists tend to be short. + check.later(func() { + for i, t := range list { + if t := asInterface(t); t != nil { + check.completeInterface(types[i].Pos(), t) + } + if includes(list[:i], t) { + check.softErrorf(types[i], _Todo, "duplicate type %s in type list", t) + } + } + }) + + return list +} + +// includes reports whether typ is in list. +func includes(list []Type, typ Type) bool { + for _, e := range list { + if Identical(typ, e) { + return true + } + } + return false +} + +func (check *Checker) completeInterface(pos token.Pos, ityp *Interface) { + if ityp.allMethods != nil { + return + } + + // completeInterface may be called via the LookupFieldOrMethod, + // MissingMethod, Identical, or IdenticalIgnoreTags external API + // in which case check will be nil. In this case, type-checking + // must be finished and all interfaces should have been completed. + if check == nil { + panic("internal error: incomplete interface") + } + + if trace { + // Types don't generally have position information. + // If we don't have a valid pos provided, try to use + // one close enough. + if !pos.IsValid() && len(ityp.methods) > 0 { + pos = ityp.methods[0].pos + } + + check.trace(pos, "complete %s", ityp) + check.indent++ + defer func() { + check.indent-- + check.trace(pos, "=> %s (methods = %v, types = %v)", ityp, ityp.allMethods, ityp.allTypes) + }() + } + + // An infinitely expanding interface (due to a cycle) is detected + // elsewhere (Checker.validType), so here we simply assume we only + // have valid interfaces. Mark the interface as complete to avoid + // infinite recursion if the validType check occurs later for some + // reason. + ityp.allMethods = markComplete + + // Methods of embedded interfaces are collected unchanged; i.e., the identity + // of a method I.m's Func Object of an interface I is the same as that of + // the method m in an interface that embeds interface I. On the other hand, + // if a method is embedded via multiple overlapping embedded interfaces, we + // don't provide a guarantee which "original m" got chosen for the embedding + // interface. See also issue #34421. + // + // If we don't care to provide this identity guarantee anymore, instead of + // reusing the original method in embeddings, we can clone the method's Func + // Object and give it the position of a corresponding embedded interface. Then + // we can get rid of the mpos map below and simply use the cloned method's + // position. + + var seen objset + var methods []*Func + mpos := make(map[*Func]token.Pos) // method specification or method embedding position, for good error messages + addMethod := func(pos token.Pos, m *Func, explicit bool) { + switch other := seen.insert(m); { + case other == nil: + methods = append(methods, m) + mpos[m] = pos + case explicit: + check.errorf(atPos(pos), _DuplicateDecl, "duplicate method %s", m.name) + check.errorf(atPos(mpos[other.(*Func)]), _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented + default: + // We have a duplicate method name in an embedded (not explicitly declared) method. + // Check method signatures after all types are computed (issue #33656). + // If we're pre-go1.14 (overlapping embeddings are not permitted), report that + // error here as well (even though we could do it eagerly) because it's the same + // error message. + check.later(func() { + if !check.allowVersion(m.pkg, 1, 14) || !check.identical(m.typ, other.Type()) { + check.errorf(atPos(pos), _DuplicateDecl, "duplicate method %s", m.name) + check.errorf(atPos(mpos[other.(*Func)]), _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented + } + }) + } + } + + for _, m := range ityp.methods { + addMethod(m.pos, m, true) + } + + // collect types + allTypes := ityp.types + + posList := check.posMap[ityp] + for i, typ := range ityp.embeddeds { + pos := posList[i] // embedding position + utyp := under(typ) + etyp := asInterface(utyp) + if etyp == nil { + if utyp != Typ[Invalid] { + var format string + if _, ok := utyp.(*_TypeParam); ok { + format = "%s is a type parameter, not an interface" + } else { + format = "%s is not an interface" + } + // TODO: correct error code. + check.errorf(atPos(pos), _InvalidIfaceEmbed, format, typ) + } + continue + } + check.completeInterface(pos, etyp) + for _, m := range etyp.allMethods { + addMethod(pos, m, false) // use embedding position pos rather than m.pos + } + allTypes = intersect(allTypes, etyp.allTypes) + } + + if methods != nil { + sort.Sort(byUniqueMethodName(methods)) + ityp.allMethods = methods + } + ityp.allTypes = allTypes +} + +// intersect computes the intersection of the types x and y. +// Note: A incomming nil type stands for the top type. A top +// type result is returned as nil. +func intersect(x, y Type) (r Type) { + defer func() { + if r == theTop { + r = nil + } + }() + + switch { + case x == theBottom || y == theBottom: + return theBottom + case x == nil || x == theTop: + return y + case y == nil || x == theTop: + return x + } + + xtypes := unpackType(x) + ytypes := unpackType(y) + // Compute the list rtypes which includes only + // types that are in both xtypes and ytypes. + // Quadratic algorithm, but good enough for now. + // TODO(gri) fix this + var rtypes []Type + for _, x := range xtypes { + if includes(ytypes, x) { + rtypes = append(rtypes, x) + } + } + + if rtypes == nil { + return theBottom + } + return _NewSum(rtypes) +} + +func sortTypes(list []Type) { + sort.Stable(byUniqueTypeName(list)) +} + +// byUniqueTypeName named type lists can be sorted by their unique type names. +type byUniqueTypeName []Type + +func (a byUniqueTypeName) Len() int { return len(a) } +func (a byUniqueTypeName) Less(i, j int) bool { return sortName(a[i]) < sortName(a[j]) } +func (a byUniqueTypeName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +func sortName(t Type) string { + if named := asNamed(t); named != nil { + return named.obj.Id() + } + return "" +} + +func sortMethods(list []*Func) { + sort.Sort(byUniqueMethodName(list)) +} + +func assertSortedMethods(list []*Func) { + if !debug { + panic("internal error: assertSortedMethods called outside debug mode") + } + if !sort.IsSorted(byUniqueMethodName(list)) { + panic("internal error: methods not sorted") + } +} + +// byUniqueMethodName method lists can be sorted by their unique method names. +type byUniqueMethodName []*Func + +func (a byUniqueMethodName) Len() int { return len(a) } +func (a byUniqueMethodName) Less(i, j int) bool { return a[i].Id() < a[j].Id() } +func (a byUniqueMethodName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 5185c33fcb..b1b4ff9a77 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -12,7 +12,6 @@ import ( "go/constant" "go/internal/typeparams" "go/token" - "sort" "strconv" "strings" ) @@ -758,277 +757,6 @@ func (check *Checker) declareInSet(oset *objset, pos token.Pos, obj Object) bool return true } -func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, def *Named) { - var tlist *ast.Ident // "type" name of first entry in a type list declaration - var types []ast.Expr - for _, f := range iface.Methods.List { - if len(f.Names) > 0 { - // We have a method with name f.Names[0], or a type - // of a type list (name.Name == "type"). - // (The parser ensures that there's only one method - // and we don't care if a constructed AST has more.) - name := f.Names[0] - if name.Name == "_" { - check.errorf(name, _BlankIfaceMethod, "invalid method name _") - continue // ignore - } - - if name.Name == "type" { - // Always collect all type list entries, even from - // different type lists, under the assumption that - // the author intended to include all types. - types = append(types, f.Type) - if tlist != nil && tlist != name { - check.errorf(name, _Todo, "cannot have multiple type lists in an interface") - } - tlist = name - continue - } - - typ := check.typ(f.Type) - sig, _ := typ.(*Signature) - if sig == nil { - if typ != Typ[Invalid] { - check.invalidAST(f.Type, "%s is not a method signature", typ) - } - continue // ignore - } - - // Always type-check method type parameters but complain if they are not enabled. - // (This extra check is needed here because interface method signatures don't have - // a receiver specification.) - if sig.tparams != nil { - var at positioner = f.Type - if tparams := typeparams.Get(f.Type); tparams != nil { - at = tparams - } - check.errorf(at, _Todo, "methods cannot have type parameters") - } - - // use named receiver type if available (for better error messages) - var recvTyp Type = ityp - if def != nil { - recvTyp = def - } - sig.recv = NewVar(name.Pos(), check.pkg, "", recvTyp) - - m := NewFunc(name.Pos(), check.pkg, name.Name, sig) - check.recordDef(name, m) - ityp.methods = append(ityp.methods, m) - } else { - // We have an embedded type. completeInterface will - // eventually verify that we have an interface. - ityp.embeddeds = append(ityp.embeddeds, check.typ(f.Type)) - check.posMap[ityp] = append(check.posMap[ityp], f.Type.Pos()) - } - } - - // type constraints - ityp.types = _NewSum(check.collectTypeConstraints(iface.Pos(), types)) - - if len(ityp.methods) == 0 && ityp.types == nil && len(ityp.embeddeds) == 0 { - // empty interface - ityp.allMethods = markComplete - return - } - - // sort for API stability - sortMethods(ityp.methods) - sortTypes(ityp.embeddeds) - - check.later(func() { check.completeInterface(iface.Pos(), ityp) }) -} - -func (check *Checker) completeInterface(pos token.Pos, ityp *Interface) { - if ityp.allMethods != nil { - return - } - - // completeInterface may be called via the LookupFieldOrMethod, - // MissingMethod, Identical, or IdenticalIgnoreTags external API - // in which case check will be nil. In this case, type-checking - // must be finished and all interfaces should have been completed. - if check == nil { - panic("internal error: incomplete interface") - } - - if trace { - // Types don't generally have position information. - // If we don't have a valid pos provided, try to use - // one close enough. - if !pos.IsValid() && len(ityp.methods) > 0 { - pos = ityp.methods[0].pos - } - - check.trace(pos, "complete %s", ityp) - check.indent++ - defer func() { - check.indent-- - check.trace(pos, "=> %s (methods = %v, types = %v)", ityp, ityp.allMethods, ityp.allTypes) - }() - } - - // An infinitely expanding interface (due to a cycle) is detected - // elsewhere (Checker.validType), so here we simply assume we only - // have valid interfaces. Mark the interface as complete to avoid - // infinite recursion if the validType check occurs later for some - // reason. - ityp.allMethods = markComplete - - // Methods of embedded interfaces are collected unchanged; i.e., the identity - // of a method I.m's Func Object of an interface I is the same as that of - // the method m in an interface that embeds interface I. On the other hand, - // if a method is embedded via multiple overlapping embedded interfaces, we - // don't provide a guarantee which "original m" got chosen for the embedding - // interface. See also issue #34421. - // - // If we don't care to provide this identity guarantee anymore, instead of - // reusing the original method in embeddings, we can clone the method's Func - // Object and give it the position of a corresponding embedded interface. Then - // we can get rid of the mpos map below and simply use the cloned method's - // position. - - var seen objset - var methods []*Func - mpos := make(map[*Func]token.Pos) // method specification or method embedding position, for good error messages - addMethod := func(pos token.Pos, m *Func, explicit bool) { - switch other := seen.insert(m); { - case other == nil: - methods = append(methods, m) - mpos[m] = pos - case explicit: - check.errorf(atPos(pos), _DuplicateDecl, "duplicate method %s", m.name) - check.errorf(atPos(mpos[other.(*Func)]), _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented - default: - // We have a duplicate method name in an embedded (not explicitly declared) method. - // Check method signatures after all types are computed (issue #33656). - // If we're pre-go1.14 (overlapping embeddings are not permitted), report that - // error here as well (even though we could do it eagerly) because it's the same - // error message. - check.later(func() { - if !check.allowVersion(m.pkg, 1, 14) || !check.identical(m.typ, other.Type()) { - check.errorf(atPos(pos), _DuplicateDecl, "duplicate method %s", m.name) - check.errorf(atPos(mpos[other.(*Func)]), _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented - } - }) - } - } - - for _, m := range ityp.methods { - addMethod(m.pos, m, true) - } - - // collect types - allTypes := ityp.types - - posList := check.posMap[ityp] - for i, typ := range ityp.embeddeds { - pos := posList[i] // embedding position - utyp := under(typ) - etyp := asInterface(utyp) - if etyp == nil { - if utyp != Typ[Invalid] { - var format string - if _, ok := utyp.(*_TypeParam); ok { - format = "%s is a type parameter, not an interface" - } else { - format = "%s is not an interface" - } - // TODO: correct error code. - check.errorf(atPos(pos), _InvalidIfaceEmbed, format, typ) - } - continue - } - check.completeInterface(pos, etyp) - for _, m := range etyp.allMethods { - addMethod(pos, m, false) // use embedding position pos rather than m.pos - } - allTypes = intersect(allTypes, etyp.allTypes) - } - - if methods != nil { - sort.Sort(byUniqueMethodName(methods)) - ityp.allMethods = methods - } - ityp.allTypes = allTypes -} - -// intersect computes the intersection of the types x and y. -// Note: A incomming nil type stands for the top type. A top -// type result is returned as nil. -func intersect(x, y Type) (r Type) { - defer func() { - if r == theTop { - r = nil - } - }() - - switch { - case x == theBottom || y == theBottom: - return theBottom - case x == nil || x == theTop: - return y - case y == nil || x == theTop: - return x - } - - xtypes := unpackType(x) - ytypes := unpackType(y) - // Compute the list rtypes which includes only - // types that are in both xtypes and ytypes. - // Quadratic algorithm, but good enough for now. - // TODO(gri) fix this - var rtypes []Type - for _, x := range xtypes { - if includes(ytypes, x) { - rtypes = append(rtypes, x) - } - } - - if rtypes == nil { - return theBottom - } - return _NewSum(rtypes) -} - -func sortTypes(list []Type) { - sort.Stable(byUniqueTypeName(list)) -} - -// byUniqueTypeName named type lists can be sorted by their unique type names. -type byUniqueTypeName []Type - -func (a byUniqueTypeName) Len() int { return len(a) } -func (a byUniqueTypeName) Less(i, j int) bool { return sortName(a[i]) < sortName(a[j]) } -func (a byUniqueTypeName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } - -func sortName(t Type) string { - if named := asNamed(t); named != nil { - return named.obj.Id() - } - return "" -} - -func sortMethods(list []*Func) { - sort.Sort(byUniqueMethodName(list)) -} - -func assertSortedMethods(list []*Func) { - if !debug { - panic("internal error: assertSortedMethods called outside debug mode") - } - if !sort.IsSorted(byUniqueMethodName(list)) { - panic("internal error: methods not sorted") - } -} - -// byUniqueMethodName method lists can be sorted by their unique method names. -type byUniqueMethodName []*Func - -func (a byUniqueMethodName) Len() int { return len(a) } -func (a byUniqueMethodName) Less(i, j int) bool { return a[i].Id() < a[j].Id() } -func (a byUniqueMethodName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } - func (check *Checker) tag(t *ast.BasicLit) string { if t != nil { if t.Kind == token.STRING { @@ -1162,41 +890,3 @@ func embeddedFieldIdent(e ast.Expr) *ast.Ident { } return nil // invalid embedded field } - -func (check *Checker) collectTypeConstraints(pos token.Pos, types []ast.Expr) []Type { - list := make([]Type, 0, len(types)) // assume all types are correct - for _, texpr := range types { - if texpr == nil { - check.invalidAST(atPos(pos), "missing type constraint") - continue - } - list = append(list, check.varType(texpr)) - } - - // Ensure that each type is only present once in the type list. Types may be - // interfaces, which may not be complete yet. It's ok to do this check at the - // end because it's not a requirement for correctness of the code. - // Note: This is a quadratic algorithm, but type lists tend to be short. - check.later(func() { - for i, t := range list { - if t := asInterface(t); t != nil { - check.completeInterface(types[i].Pos(), t) - } - if includes(list[:i], t) { - check.softErrorf(types[i], _Todo, "duplicate type %s in type list", t) - } - } - }) - - return list -} - -// includes reports whether typ is in list. -func includes(list []Type, typ Type) bool { - for _, e := range list { - if Identical(typ, e) { - return true - } - } - return false -} -- GitLab From 93a886a165ed39bcfb842f88f17fc2cd7d005ab9 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Thu, 3 Jun 2021 11:10:08 -0400 Subject: [PATCH 0217/2500] [dev.typeparams] go/types: move struct checking into separate file This is a port of CL 321589 to go/types. Specifically, the same checker methods were moved. Change-Id: If07d96faa77d2f9409d8895f970149c42cbfe440 Reviewed-on: https://go-review.googlesource.com/c/go/+/324753 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/struct.go | 154 ++++++++++++++++++++++++++++++++++++++++ src/go/types/typexpr.go | 144 ------------------------------------- 2 files changed, 154 insertions(+), 144 deletions(-) create mode 100644 src/go/types/struct.go diff --git a/src/go/types/struct.go b/src/go/types/struct.go new file mode 100644 index 0000000000..1fec9ea527 --- /dev/null +++ b/src/go/types/struct.go @@ -0,0 +1,154 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +import ( + "go/ast" + "go/token" + "strconv" +) + +func (check *Checker) structType(styp *Struct, e *ast.StructType) { + list := e.Fields + if list == nil { + return + } + + // struct fields and tags + var fields []*Var + var tags []string + + // for double-declaration checks + var fset objset + + // current field typ and tag + var typ Type + var tag string + add := func(ident *ast.Ident, embedded bool, pos token.Pos) { + if tag != "" && tags == nil { + tags = make([]string, len(fields)) + } + if tags != nil { + tags = append(tags, tag) + } + + name := ident.Name + fld := NewField(pos, check.pkg, name, typ, embedded) + // spec: "Within a struct, non-blank field names must be unique." + if name == "_" || check.declareInSet(&fset, pos, fld) { + fields = append(fields, fld) + check.recordDef(ident, fld) + } + } + + // addInvalid adds an embedded field of invalid type to the struct for + // fields with errors; this keeps the number of struct fields in sync + // with the source as long as the fields are _ or have different names + // (issue #25627). + addInvalid := func(ident *ast.Ident, pos token.Pos) { + typ = Typ[Invalid] + tag = "" + add(ident, true, pos) + } + + for _, f := range list.List { + typ = check.varType(f.Type) + tag = check.tag(f.Tag) + if len(f.Names) > 0 { + // named fields + for _, name := range f.Names { + add(name, false, name.Pos()) + } + } else { + // embedded field + // spec: "An embedded type must be specified as a type name T or as a + // pointer to a non-interface type name *T, and T itself may not be a + // pointer type." + pos := f.Type.Pos() + name := embeddedFieldIdent(f.Type) + if name == nil { + // TODO(rFindley): using invalidAST here causes test failures (all + // errors should have codes). Clean this up. + check.errorf(f.Type, _Todo, "invalid AST: embedded field type %s has no name", f.Type) + name = ast.NewIdent("_") + name.NamePos = pos + addInvalid(name, pos) + continue + } + add(name, true, pos) + + // Because we have a name, typ must be of the form T or *T, where T is the name + // of a (named or alias) type, and t (= deref(typ)) must be the type of T. + // We must delay this check to the end because we don't want to instantiate + // (via under(t)) a possibly incomplete type. + + // for use in the closure below + embeddedTyp := typ + embeddedPos := f.Type + + check.later(func() { + t, isPtr := deref(embeddedTyp) + switch t := optype(t).(type) { + case *Basic: + if t == Typ[Invalid] { + // error was reported before + return + } + // unsafe.Pointer is treated like a regular pointer + if t.kind == UnsafePointer { + check.errorf(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be unsafe.Pointer") + } + case *Pointer: + check.errorf(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a pointer") + case *Interface: + if isPtr { + check.errorf(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a pointer to an interface") + } + } + }) + } + } + + styp.fields = fields + styp.tags = tags +} + +func embeddedFieldIdent(e ast.Expr) *ast.Ident { + switch e := e.(type) { + case *ast.Ident: + return e + case *ast.StarExpr: + // *T is valid, but **T is not + if _, ok := e.X.(*ast.StarExpr); !ok { + return embeddedFieldIdent(e.X) + } + case *ast.SelectorExpr: + return e.Sel + case *ast.IndexExpr: + return embeddedFieldIdent(e.X) + } + return nil // invalid embedded field +} + +func (check *Checker) declareInSet(oset *objset, pos token.Pos, obj Object) bool { + if alt := oset.insert(obj); alt != nil { + check.errorf(atPos(pos), _DuplicateDecl, "%s redeclared", obj.Name()) + check.reportAltDecl(alt) + return false + } + return true +} + +func (check *Checker) tag(t *ast.BasicLit) string { + if t != nil { + if t.Kind == token.STRING { + if val, err := strconv.Unquote(t.Value); err == nil { + return val + } + } + check.invalidAST(t, "incorrect tag syntax: %q", t.Value) + } + return "" +} diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index b1b4ff9a77..c6c3dc049a 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -12,7 +12,6 @@ import ( "go/constant" "go/internal/typeparams" "go/token" - "strconv" "strings" ) @@ -747,146 +746,3 @@ func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, type0 ast return } - -func (check *Checker) declareInSet(oset *objset, pos token.Pos, obj Object) bool { - if alt := oset.insert(obj); alt != nil { - check.errorf(atPos(pos), _DuplicateDecl, "%s redeclared", obj.Name()) - check.reportAltDecl(alt) - return false - } - return true -} - -func (check *Checker) tag(t *ast.BasicLit) string { - if t != nil { - if t.Kind == token.STRING { - if val, err := strconv.Unquote(t.Value); err == nil { - return val - } - } - check.invalidAST(t, "incorrect tag syntax: %q", t.Value) - } - return "" -} - -func (check *Checker) structType(styp *Struct, e *ast.StructType) { - list := e.Fields - if list == nil { - return - } - - // struct fields and tags - var fields []*Var - var tags []string - - // for double-declaration checks - var fset objset - - // current field typ and tag - var typ Type - var tag string - add := func(ident *ast.Ident, embedded bool, pos token.Pos) { - if tag != "" && tags == nil { - tags = make([]string, len(fields)) - } - if tags != nil { - tags = append(tags, tag) - } - - name := ident.Name - fld := NewField(pos, check.pkg, name, typ, embedded) - // spec: "Within a struct, non-blank field names must be unique." - if name == "_" || check.declareInSet(&fset, pos, fld) { - fields = append(fields, fld) - check.recordDef(ident, fld) - } - } - - // addInvalid adds an embedded field of invalid type to the struct for - // fields with errors; this keeps the number of struct fields in sync - // with the source as long as the fields are _ or have different names - // (issue #25627). - addInvalid := func(ident *ast.Ident, pos token.Pos) { - typ = Typ[Invalid] - tag = "" - add(ident, true, pos) - } - - for _, f := range list.List { - typ = check.varType(f.Type) - tag = check.tag(f.Tag) - if len(f.Names) > 0 { - // named fields - for _, name := range f.Names { - add(name, false, name.Pos()) - } - } else { - // embedded field - // spec: "An embedded type must be specified as a type name T or as a - // pointer to a non-interface type name *T, and T itself may not be a - // pointer type." - pos := f.Type.Pos() - name := embeddedFieldIdent(f.Type) - if name == nil { - // TODO(rFindley): using invalidAST here causes test failures (all - // errors should have codes). Clean this up. - check.errorf(f.Type, _Todo, "invalid AST: embedded field type %s has no name", f.Type) - name = ast.NewIdent("_") - name.NamePos = pos - addInvalid(name, pos) - continue - } - add(name, true, pos) - - // Because we have a name, typ must be of the form T or *T, where T is the name - // of a (named or alias) type, and t (= deref(typ)) must be the type of T. - // We must delay this check to the end because we don't want to instantiate - // (via under(t)) a possibly incomplete type. - - // for use in the closure below - embeddedTyp := typ - embeddedPos := f.Type - - check.later(func() { - t, isPtr := deref(embeddedTyp) - switch t := optype(t).(type) { - case *Basic: - if t == Typ[Invalid] { - // error was reported before - return - } - // unsafe.Pointer is treated like a regular pointer - if t.kind == UnsafePointer { - check.errorf(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be unsafe.Pointer") - } - case *Pointer: - check.errorf(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a pointer") - case *Interface: - if isPtr { - check.errorf(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a pointer to an interface") - } - } - }) - } - } - - styp.fields = fields - styp.tags = tags -} - -func embeddedFieldIdent(e ast.Expr) *ast.Ident { - switch e := e.(type) { - case *ast.Ident: - return e - case *ast.StarExpr: - // *T is valid, but **T is not - if _, ok := e.X.(*ast.StarExpr); !ok { - return embeddedFieldIdent(e.X) - } - case *ast.SelectorExpr: - return e.Sel - case *ast.IndexExpr: - return embeddedFieldIdent(e.X) - } - return nil // invalid embedded field -} -- GitLab From 542e8c74e7051690539889a1dd0197517603e473 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Thu, 3 Jun 2021 18:04:53 -0700 Subject: [PATCH 0218/2500] [dev.fuzz] internal/fuzz: stablize mutator benchmark and add additional benchmarks Adds a few new benchmarks, and attempts to reduce the variability of the existing BenchmarkMutatorBytes benchmark. These should help provide some insight when we're working on performance issues. Change-Id: I45b68ae36da99ec2eb4a610b7a3fc6fbf3d9494a Reviewed-on: https://go-review.googlesource.com/c/go/+/324969 Trust: Roland Shoemaker Trust: Katie Hockman Run-TryBot: Roland Shoemaker Reviewed-by: Katie Hockman TryBot-Result: Go Bot --- src/internal/fuzz/mutator_test.go | 76 +++++++++++++++++++++++++++++-- src/internal/fuzz/worker_test.go | 42 +++++++++++++++++ 2 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 src/internal/fuzz/worker_test.go diff --git a/src/internal/fuzz/mutator_test.go b/src/internal/fuzz/mutator_test.go index b1b5311639..5fcfb27c16 100644 --- a/src/internal/fuzz/mutator_test.go +++ b/src/internal/fuzz/mutator_test.go @@ -5,11 +5,17 @@ package fuzz import ( + "fmt" + "os" "strconv" "testing" ) func BenchmarkMutatorBytes(b *testing.B) { + origEnv := os.Getenv("GODEBUG") + defer func() { os.Setenv("GODEBUG", origEnv) }() + os.Setenv("GODEBUG", fmt.Sprintf("%s,fuzzseed=123", origEnv)) + for _, size := range []int{ 1, 10, @@ -20,10 +26,74 @@ func BenchmarkMutatorBytes(b *testing.B) { } { size := size b.Run(strconv.Itoa(size), func(b *testing.B) { - vals := []interface{}{make([]byte, size)} - m := newMutator() + buf := make([]byte, size) + b.ResetTimer() + + for i := 0; i < b.N; i++ { + // resize buffer to the correct shape and reset the PCG + buf = buf[0:size] + m := newMutator() + m.mutate([]interface{}{buf}, workerSharedMemSize) + } + }) + } +} + +func BenchmarkMutatorString(b *testing.B) { + origEnv := os.Getenv("GODEBUG") + defer func() { os.Setenv("GODEBUG", origEnv) }() + os.Setenv("GODEBUG", fmt.Sprintf("%s,fuzzseed=123", origEnv)) + + for _, size := range []int{ + 1, + 10, + 100, + 1000, + 10000, + 100000, + } { + size := size + b.Run(strconv.Itoa(size), func(b *testing.B) { + buf := make([]byte, size) + b.ResetTimer() + + for i := 0; i < b.N; i++ { + // resize buffer to the correct shape and reset the PCG + buf = buf[0:size] + m := newMutator() + m.mutate([]interface{}{string(buf)}, workerSharedMemSize) + } + }) + } +} + +func BenchmarkMutatorAllBasicTypes(b *testing.B) { + origEnv := os.Getenv("GODEBUG") + defer func() { os.Setenv("GODEBUG", origEnv) }() + os.Setenv("GODEBUG", fmt.Sprintf("%s,fuzzseed=123", origEnv)) + + types := []interface{}{ + []byte(""), + string(""), + false, + float32(0), + float64(0), + int(0), + int8(0), + int16(0), + int32(0), + int64(0), + uint8(0), + uint16(0), + uint32(0), + uint64(0), + } + + for _, t := range types { + b.Run(fmt.Sprintf("%T", t), func(b *testing.B) { for i := 0; i < b.N; i++ { - m.mutate(vals, workerSharedMemSize) + m := newMutator() + m.mutate([]interface{}{t}, workerSharedMemSize) } }) } diff --git a/src/internal/fuzz/worker_test.go b/src/internal/fuzz/worker_test.go new file mode 100644 index 0000000000..10d61b19db --- /dev/null +++ b/src/internal/fuzz/worker_test.go @@ -0,0 +1,42 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fuzz + +import ( + "context" + "fmt" + "os" + "testing" +) + +func BenchmarkWorkerFuzzOverhead(b *testing.B) { + origEnv := os.Getenv("GODEBUG") + defer func() { os.Setenv("GODEBUG", origEnv) }() + os.Setenv("GODEBUG", fmt.Sprintf("%s,fuzzseed=123", origEnv)) + + ws := &workerServer{ + fuzzFn: func(_ CorpusEntry) error { return nil }, + workerComm: workerComm{memMu: make(chan *sharedMem, 1)}, + } + + mem, err := sharedMemTempFile(workerSharedMemSize) + if err != nil { + b.Fatalf("failed to create temporary shared memory file: %s", err) + } + + initialVal := []interface{}{make([]byte, 32)} + encodedVals := marshalCorpusFile(initialVal...) + mem.setValue(encodedVals) + + ws.memMu <- mem + + b.ResetTimer() + for i := 0; i < b.N; i++ { + ws.m = newMutator() + mem.setValue(encodedVals) + + ws.fuzz(context.Background(), fuzzArgs{Limit: 1}) + } +} -- GitLab From 8e6dfe1b315ca0ef6497b28e16523c2dc4019503 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 17 May 2021 15:00:39 -0700 Subject: [PATCH 0219/2500] [dev.typeparams] cmd/compile: export/import of recursive generic types. Deal with export/import of recursive generic types. This includes typeparams which have bounds that reference the typeparam. There are three main changes: - Change export/import of typeparams to have an implicit "declaration" (doDecl). We need to do a declaration of typeparams (via the typeparam's package and unique name), because it may be referenced within its bound during its own definition. - We delay most of the processing of the Instantiate call until we finish the creation of the top-most type (similar to the way we delay CheckSize). This is because we can't do the full instantiation properly until the base type is fully defined (with methods). The functions delayDoInst() and resumeDoInst() delay and resume the processing of the instantiations. - To do the full needed type substitutions for type instantiations during import, I had to separate out the type subster in stencil.go and move it to subr.go in the typecheck package. The subster in stencil.go now does node substitution and makes use of the type subster to do type substitutions. Notable other changes: - In types/builtins.go, put the newly defined typeparam for a union type (related to use of real/imag, etc.) in the current package, rather than the builtin package, so exports/imports work properly. - In types2, allowed NewTypeParam() to be called with a nil bound, and allow setting the bound later. (Needed to import a typeparam whose bound refers to the typeparam itself.) - During import of typeparams in types2 (importer/import.go), we need to keep an index of the typeparams by their package and unique name (with id). Use a new map typParamIndex[] for that. Again, this is needed to deal with typeparams whose bounds refer to the typeparam itself. - Added several new tests absdiffimp.go and orderedmapsimp.go. Some of the orderemapsimp tests are commented out for now, because there are some issues with closures inside instantiations (relating to unexported names of closure structs). - Renamed some typeparams in test value.go to make them all T (to make typeparam uniqueness is working fine). Change-Id: Ib47ed9471c19ee8e9fbb34e8506907dad3021e5a Reviewed-on: https://go-review.googlesource.com/c/go/+/323029 Trust: Dan Scales Trust: Robert Griesemer Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/importer/iimport.go | 92 +++-- src/cmd/compile/internal/noder/stencil.go | 335 +---------------- src/cmd/compile/internal/noder/types.go | 13 +- src/cmd/compile/internal/typecheck/iexport.go | 74 ++-- src/cmd/compile/internal/typecheck/iimport.go | 172 +++++++-- src/cmd/compile/internal/typecheck/subr.go | 336 +++++++++++++++++- src/cmd/compile/internal/types2/builtins.go | 6 +- src/cmd/compile/internal/types2/type.go | 22 +- test/typeparam/absdiff.go | 3 +- test/typeparam/absdiffimp.dir/a.go | 75 ++++ test/typeparam/absdiffimp.dir/main.go | 29 ++ test/typeparam/absdiffimp.go | 7 + test/typeparam/orderedmapsimp.dir/a.go | 226 ++++++++++++ test/typeparam/orderedmapsimp.dir/main.go | 67 ++++ test/typeparam/orderedmapsimp.go | 7 + test/typeparam/value.go | 6 +- 16 files changed, 1035 insertions(+), 435 deletions(-) create mode 100644 test/typeparam/absdiffimp.dir/a.go create mode 100644 test/typeparam/absdiffimp.dir/main.go create mode 100644 test/typeparam/absdiffimp.go create mode 100644 test/typeparam/orderedmapsimp.dir/a.go create mode 100644 test/typeparam/orderedmapsimp.dir/main.go create mode 100644 test/typeparam/orderedmapsimp.go diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index fd48bfc179..fb39e93073 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -51,6 +51,11 @@ const ( iexportVersionCurrent = iexportVersionGenerics + 1 ) +type ident struct { + pkg string + name string +} + const predeclReserved = 32 type itag uint64 @@ -124,6 +129,9 @@ func iImportData(imports map[string]*types2.Package, data []byte, path string) ( declData: declData, pkgIndex: make(map[*types2.Package]map[string]uint64), typCache: make(map[uint64]types2.Type), + // Separate map for typeparams, keyed by their package and unique + // name (name with subscript). + tparamIndex: make(map[ident]types2.Type), } for i, pt := range predeclared { @@ -202,9 +210,10 @@ type iimporter struct { pkgCache map[uint64]*types2.Package posBaseCache map[uint64]*syntax.PosBase - declData []byte - pkgIndex map[*types2.Package]map[string]uint64 - typCache map[uint64]types2.Type + declData []byte + pkgIndex map[*types2.Package]map[string]uint64 + typCache map[uint64]types2.Type + tparamIndex map[ident]types2.Type interfaceList []*types2.Interface } @@ -358,6 +367,28 @@ func (r *importReader) obj(name string) { } } + case 'P': + // We need to "declare" a typeparam in order to have a name that + // can be referenced recursively (if needed) in the type param's + // bound. + if r.p.exportVersion < iexportVersionGenerics { + errorf("unexpected type param type") + } + index := int(r.int64()) + name0, sub := parseSubscript(name) + tn := types2.NewTypeName(pos, r.currPkg, name0, nil) + t := (*types2.Checker)(nil).NewTypeParam(tn, index, nil) + if sub == 0 { + errorf("missing subscript") + } + t.SetId(sub) + // To handle recursive references to the typeparam within its + // bound, save the partial type in tparamIndex before reading the bounds. + id := ident{r.currPkg.Name(), name} + r.p.tparamIndex[id] = t + + t.SetBound(r.typ()) + case 'V': typ := r.typ() @@ -617,34 +648,15 @@ func (r *importReader) doType(base *types2.Named) types2.Type { if r.p.exportVersion < iexportVersionGenerics { errorf("unexpected type param type") } - r.currPkg = r.pkg() - pos := r.pos() - name := r.string() - - // Extract the subscript value from the type param name. We export - // and import the subscript value, so that all type params have - // unique names. - sub := uint64(0) - startsub := -1 - for i, r := range name { - if '₀' <= r && r < '₀'+10 { - if startsub == -1 { - startsub = i - } - sub = sub*10 + uint64(r-'₀') - } - } - if startsub >= 0 { - name = name[:startsub] - } - index := int(r.int64()) - bound := r.typ() - tn := types2.NewTypeName(pos, r.currPkg, name, nil) - t := (*types2.Checker)(nil).NewTypeParam(tn, index, bound) - if sub >= 0 { - t.SetId(sub) + pkg, name := r.qualifiedIdent() + id := ident{pkg.Name(), name} + if t, ok := r.p.tparamIndex[id]; ok { + // We're already in the process of importing this typeparam. + return t } - return t + // Otherwise, import the definition of the typeparam now. + r.p.doDecl(pkg, name) + return r.p.tparamIndex[id] case instType: if r.p.exportVersion < iexportVersionGenerics { @@ -753,3 +765,23 @@ func baseType(typ types2.Type) *types2.Named { n, _ := typ.(*types2.Named) return n } + +func parseSubscript(name string) (string, uint64) { + // Extract the subscript value from the type param name. We export + // and import the subscript value, so that all type params have + // unique names. + sub := uint64(0) + startsub := -1 + for i, r := range name { + if '₀' <= r && r < '₀'+10 { + if startsub == -1 { + startsub = i + } + sub = sub*10 + uint64(r-'₀') + } + } + if startsub >= 0 { + name = name[:startsub] + } + return name, sub +} diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 08c09c6fb1..3ba364f67c 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -15,7 +15,6 @@ import ( "cmd/compile/internal/types" "fmt" "go/constant" - "strings" ) // For catching problems as we add more features @@ -425,13 +424,6 @@ func (g *irgen) instantiateMethods() { } -// genericSym returns the name of the base generic type for the type named by -// sym. It simply returns the name obtained by removing everything after the -// first bracket ("["). -func genericTypeName(sym *types.Sym) string { - return sym.Name[0:strings.Index(sym.Name, "[")] -} - // getInstantiationForNode returns the function/method instantiation for a // InstExpr node inst. func (g *irgen) getInstantiationForNode(inst *ir.InstExpr) *ir.Func { @@ -479,11 +471,7 @@ type subster struct { g *irgen isMethod bool // If a method is being instantiated newf *ir.Func // Func node for the new stenciled function - tparams []*types.Type - targs []*types.Type - // The substitution map from name nodes in the generic function to the - // name nodes in the new stenciled function. - vars map[*ir.Name]*ir.Name + ts typecheck.Tsubster } // genericSubst returns a new function with name newsym. The function is an @@ -526,9 +514,11 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []*type g: g, isMethod: isMethod, newf: newf, - tparams: tparams, - targs: targs, - vars: make(map[*ir.Name]*ir.Name), + ts: typecheck.Tsubster{ + Tparams: tparams, + Targs: targs, + Vars: make(map[*ir.Name]*ir.Name), + }, } newf.Dcl = make([]*ir.Name, 0, len(gf.Dcl)+1) @@ -574,6 +564,9 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []*type newf.Body.Prepend(g.checkDictionary(dictionaryName, targs)...) ir.CurFunc = savef + // Add any new, fully instantiated types seen during the substitution to + // g.instTypeList. + g.instTypeList = append(g.instTypeList, subst.ts.InstTypeList...) return newf } @@ -586,13 +579,13 @@ func (subst *subster) localvar(name *ir.Name) *ir.Name { if name.IsClosureVar() { m.SetIsClosureVar(true) } - m.SetType(subst.typ(name.Type())) + m.SetType(subst.ts.Typ(name.Type())) m.BuiltinOp = name.BuiltinOp m.Curfn = subst.newf m.Class = name.Class assert(name.Class != ir.PEXTERN && name.Class != ir.PFUNC) m.Func = name.Func - subst.vars[name] = m + subst.ts.Vars[name] = m m.SetTypecheck(1) return m } @@ -635,7 +628,7 @@ func (g *irgen) checkDictionary(name *ir.Name, targs []*types.Type) (code []ir.N return } -// node is like DeepCopy(), but substitutes ONAME nodes based on subst.vars, and +// node is like DeepCopy(), but substitutes ONAME nodes based on subst.ts.vars, and // also descends into closures. It substitutes type arguments for type parameters // in all the new nodes. func (subst *subster) node(n ir.Node) ir.Node { @@ -644,10 +637,10 @@ func (subst *subster) node(n ir.Node) ir.Node { edit = func(x ir.Node) ir.Node { switch x.Op() { case ir.OTYPE: - return ir.TypeNode(subst.typ(x.Type())) + return ir.TypeNode(subst.ts.Typ(x.Type())) case ir.ONAME: - if v := subst.vars[x.(*ir.Name)]; v != nil { + if v := subst.ts.Vars[x.(*ir.Name)]; v != nil { return v } return x @@ -673,7 +666,7 @@ func (subst *subster) node(n ir.Node) ir.Node { base.Fatalf(fmt.Sprintf("Nil type for %v", x)) } } else if x.Op() != ir.OCLOSURE { - m.SetType(subst.typ(x.Type())) + m.SetType(subst.ts.Typ(x.Type())) } } ir.EditChildren(m, edit) @@ -815,7 +808,7 @@ func (subst *subster) node(n ir.Node) ir.Node { m.(*ir.ClosureExpr).Func = newfn // Closure name can already have brackets, if it derives // from a generic method - newsym := typecheck.MakeInstName(oldfn.Nname.Sym(), subst.targs, subst.isMethod) + newsym := typecheck.MakeInstName(oldfn.Nname.Sym(), subst.ts.Targs, subst.isMethod) newfn.Nname = ir.NewNameAt(oldfn.Nname.Pos(), newsym) newfn.Nname.Func = newfn newfn.Nname.Defn = newfn @@ -828,7 +821,7 @@ func (subst *subster) node(n ir.Node) ir.Node { newfn.Dcl = subst.namelist(oldfn.Dcl) newfn.ClosureVars = subst.namelist(oldfn.ClosureVars) - typed(subst.typ(oldfn.Nname.Type()), newfn.Nname) + typed(subst.ts.Typ(oldfn.Nname.Type()), newfn.Nname) typed(newfn.Nname.Type(), m) newfn.SetTypecheck(1) @@ -867,298 +860,6 @@ func (subst *subster) list(l []ir.Node) []ir.Node { return s } -// tstruct substitutes type params in types of the fields of a structure type. For -// each field, tstruct copies the Nname, and translates it if Nname is in -// subst.vars. To always force the creation of a new (top-level) struct, -// regardless of whether anything changed with the types or names of the struct's -// fields, set force to true. -func (subst *subster) tstruct(t *types.Type, force bool) *types.Type { - if t.NumFields() == 0 { - if t.HasTParam() { - // For an empty struct, we need to return a new type, - // since it may now be fully instantiated (HasTParam - // becomes false). - return types.NewStruct(t.Pkg(), nil) - } - return t - } - var newfields []*types.Field - if force { - newfields = make([]*types.Field, t.NumFields()) - } - for i, f := range t.Fields().Slice() { - t2 := subst.typ(f.Type) - if (t2 != f.Type || f.Nname != nil) && newfields == nil { - newfields = make([]*types.Field, t.NumFields()) - for j := 0; j < i; j++ { - newfields[j] = t.Field(j) - } - } - if newfields != nil { - // TODO(danscales): make sure this works for the field - // names of embedded types (which should keep the name of - // the type param, not the instantiated type). - newfields[i] = types.NewField(f.Pos, f.Sym, t2) - if f.Nname != nil { - v := subst.vars[f.Nname.(*ir.Name)] - if v != nil { - // This is the case where we are - // translating the type of the function we - // are substituting, so its dcls are in - // the subst.vars table, and we want to - // change to reference the new dcl. - newfields[i].Nname = v - } else { - // This is the case where we are - // translating the type of a function - // reference inside the function we are - // substituting, so we leave the Nname - // value as is. - newfields[i].Nname = f.Nname - } - } - } - } - if newfields != nil { - return types.NewStruct(t.Pkg(), newfields) - } - return t - -} - -// tinter substitutes type params in types of the methods of an interface type. -func (subst *subster) tinter(t *types.Type) *types.Type { - if t.Methods().Len() == 0 { - return t - } - var newfields []*types.Field - for i, f := range t.Methods().Slice() { - t2 := subst.typ(f.Type) - if (t2 != f.Type || f.Nname != nil) && newfields == nil { - newfields = make([]*types.Field, t.Methods().Len()) - for j := 0; j < i; j++ { - newfields[j] = t.Methods().Index(j) - } - } - if newfields != nil { - newfields[i] = types.NewField(f.Pos, f.Sym, t2) - } - } - if newfields != nil { - return types.NewInterface(t.Pkg(), newfields) - } - return t -} - -// typ computes the type obtained by substituting any type parameter in t with the -// corresponding type argument in subst. If t contains no type parameters, the -// result is t; otherwise the result is a new type. It deals with recursive types -// by using TFORW types and finding partially or fully created types via sym.Def. -func (subst *subster) typ(t *types.Type) *types.Type { - if !t.HasTParam() && t.Kind() != types.TFUNC { - // Note: function types need to be copied regardless, as the - // types of closures may contain declarations that need - // to be copied. See #45738. - return t - } - - if t.Kind() == types.TTYPEPARAM { - for i, tp := range subst.tparams { - if tp == t { - return subst.targs[i] - } - } - // If t is a simple typeparam T, then t has the name/symbol 'T' - // and t.Underlying() == t. - // - // However, consider the type definition: 'type P[T any] T'. We - // might use this definition so we can have a variant of type T - // that we can add new methods to. Suppose t is a reference to - // P[T]. t has the name 'P[T]', but its kind is TTYPEPARAM, - // because P[T] is defined as T. If we look at t.Underlying(), it - // is different, because the name of t.Underlying() is 'T' rather - // than 'P[T]'. But the kind of t.Underlying() is also TTYPEPARAM. - // In this case, we do the needed recursive substitution in the - // case statement below. - if t.Underlying() == t { - // t is a simple typeparam that didn't match anything in tparam - return t - } - // t is a more complex typeparam (e.g. P[T], as above, whose - // definition is just T). - assert(t.Sym() != nil) - } - - var newsym *types.Sym - var neededTargs []*types.Type - var forw *types.Type - - if t.Sym() != nil { - // Translate the type params for this type according to - // the tparam/targs mapping from subst. - neededTargs = make([]*types.Type, len(t.RParams())) - for i, rparam := range t.RParams() { - neededTargs[i] = subst.typ(rparam) - } - // For a named (defined) type, we have to change the name of the - // type as well. We do this first, so we can look up if we've - // already seen this type during this substitution or other - // definitions/substitutions. - genName := genericTypeName(t.Sym()) - newsym = t.Sym().Pkg.Lookup(typecheck.InstTypeName(genName, neededTargs)) - if newsym.Def != nil { - // We've already created this instantiated defined type. - return newsym.Def.Type() - } - - // In order to deal with recursive generic types, create a TFORW - // type initially and set the Def field of its sym, so it can be - // found if this type appears recursively within the type. - forw = typecheck.NewIncompleteNamedType(t.Pos(), newsym) - //println("Creating new type by sub", newsym.Name, forw.HasTParam()) - forw.SetRParams(neededTargs) - // Copy the OrigSym from the re-instantiated type (which is the sym of - // the base generic type). - assert(t.OrigSym != nil) - forw.OrigSym = t.OrigSym - } - - var newt *types.Type - - switch t.Kind() { - case types.TTYPEPARAM: - if t.Sym() == newsym { - // The substitution did not change the type. - return t - } - // Substitute the underlying typeparam (e.g. T in P[T], see - // the example describing type P[T] above). - newt = subst.typ(t.Underlying()) - assert(newt != t) - - case types.TARRAY: - elem := t.Elem() - newelem := subst.typ(elem) - if newelem != elem { - newt = types.NewArray(newelem, t.NumElem()) - } - - case types.TPTR: - elem := t.Elem() - newelem := subst.typ(elem) - if newelem != elem { - newt = types.NewPtr(newelem) - } - - case types.TSLICE: - elem := t.Elem() - newelem := subst.typ(elem) - if newelem != elem { - newt = types.NewSlice(newelem) - } - - case types.TSTRUCT: - newt = subst.tstruct(t, false) - if newt == t { - newt = nil - } - - case types.TFUNC: - newrecvs := subst.tstruct(t.Recvs(), false) - newparams := subst.tstruct(t.Params(), false) - newresults := subst.tstruct(t.Results(), false) - if newrecvs != t.Recvs() || newparams != t.Params() || newresults != t.Results() { - // If any types have changed, then the all the fields of - // of recv, params, and results must be copied, because they have - // offset fields that are dependent, and so must have an - // independent copy for each new signature. - var newrecv *types.Field - if newrecvs.NumFields() > 0 { - if newrecvs == t.Recvs() { - newrecvs = subst.tstruct(t.Recvs(), true) - } - newrecv = newrecvs.Field(0) - } - if newparams == t.Params() { - newparams = subst.tstruct(t.Params(), true) - } - if newresults == t.Results() { - newresults = subst.tstruct(t.Results(), true) - } - newt = types.NewSignature(t.Pkg(), newrecv, t.TParams().FieldSlice(), newparams.FieldSlice(), newresults.FieldSlice()) - } - - case types.TINTER: - newt = subst.tinter(t) - if newt == t { - newt = nil - } - - case types.TMAP: - newkey := subst.typ(t.Key()) - newval := subst.typ(t.Elem()) - if newkey != t.Key() || newval != t.Elem() { - newt = types.NewMap(newkey, newval) - } - - case types.TCHAN: - elem := t.Elem() - newelem := subst.typ(elem) - if newelem != elem { - newt = types.NewChan(newelem, t.ChanDir()) - if !newt.HasTParam() { - // TODO(danscales): not sure why I have to do this - // only for channels..... - types.CheckSize(newt) - } - } - } - if newt == nil { - // Even though there were typeparams in the type, there may be no - // change if this is a function type for a function call (which will - // have its own tparams/targs in the function instantiation). - return t - } - - if t.Sym() == nil { - // Not a named type, so there was no forwarding type and there are - // no methods to substitute. - assert(t.Methods().Len() == 0) - return newt - } - - forw.SetUnderlying(newt) - newt = forw - - if t.Kind() != types.TINTER && t.Methods().Len() > 0 { - // Fill in the method info for the new type. - var newfields []*types.Field - newfields = make([]*types.Field, t.Methods().Len()) - for i, f := range t.Methods().Slice() { - t2 := subst.typ(f.Type) - oldsym := f.Nname.Sym() - newsym := typecheck.MakeInstName(oldsym, subst.targs, true) - // TODO: use newsym? - var nname *ir.Name - if newsym.Def != nil { - nname = newsym.Def.(*ir.Name) - } else { - nname = ir.NewNameAt(f.Pos, oldsym) - nname.SetType(t2) - oldsym.Def = nname - } - newfields[i] = types.NewField(f.Pos, f.Sym, t2) - newfields[i].Nname = nname - } - newt.Methods().Set(newfields) - if !newt.HasTParam() { - // Generate all the methods for a new fully-instantiated type. - subst.g.instTypeList = append(subst.g.instTypeList, newt) - } - } - return newt -} - // fields sets the Nname field for the Field nodes inside a type signature, based // on the corresponding in/out parameters in dcl. It depends on the in and out // parameters being in order in dcl. @@ -1178,7 +879,7 @@ func (subst *subster) fields(class ir.Class, oldfields []*types.Field, dcl []*ir newfields := make([]*types.Field, len(oldfields)) for j := range oldfields { newfields[j] = oldfields[j].Copy() - newfields[j].Type = subst.typ(oldfields[j].Type) + newfields[j].Type = subst.ts.Typ(oldfields[j].Type) // A PPARAM field will be missing from dcl if its name is // unspecified or specified as "_". So, we compare the dcl sym // with the field sym (or sym of the field's Nname node). (Unnamed diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index f0061e79d7..b37793b2d0 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -316,13 +316,16 @@ func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) { tparams[i] = g.typ1(rparam.Type()) } assert(len(tparams) == len(targs)) - subst := &subster{ - g: g, - tparams: tparams, - targs: targs, + ts := typecheck.Tsubster{ + Tparams: tparams, + Targs: targs, } // Do the substitution of the type - meth2.SetType(subst.typ(meth.Type())) + meth2.SetType(ts.Typ(meth.Type())) + // Add any new fully instantiated types + // seen during the substitution to + // g.instTypeList. + g.instTypeList = append(g.instTypeList, ts.InstTypeList...) newsym.Def = meth2 } meth = meth2 diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 66c356ee7c..f635b79ada 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -506,6 +506,20 @@ func (p *iexporter) doDecl(n *ir.Name) { w.constExt(n) case ir.OTYPE: + if n.Type().Kind() == types.TTYPEPARAM && n.Type().Underlying() == n.Type() { + // Even though it has local scope, a typeparam requires a + // declaration via its package and unique name, because it + // may be referenced within its type bound during its own + // definition. + w.tag('P') + // A typeparam has a name, and has a type bound rather + // than an underlying type. + w.pos(n.Pos()) + w.int64(int64(n.Type().Index())) + w.typ(n.Type().Bound()) + break + } + if n.Alias() { // Alias. w.tag('A') @@ -519,9 +533,10 @@ func (p *iexporter) doDecl(n *ir.Name) { w.pos(n.Pos()) if base.Flag.G > 0 { - // Export any new typeparams needed for this type + // Export type parameters, if any, needed for this type w.typeList(n.Type().RParams()) } + underlying := n.Type().Underlying() if underlying == types.ErrorType.Underlying() { // For "type T error", use error as the @@ -837,26 +852,6 @@ func (w *exportWriter) startType(k itag) { } func (w *exportWriter) doTyp(t *types.Type) { - if t.Kind() == types.TTYPEPARAM { - assert(base.Flag.G > 0) - // A typeparam has a name, but doesn't have an underlying type. - // Just write out the details of the type param here. All other - // uses of this typeparam type will be written out as its unique - // type offset. - w.startType(typeParamType) - s := t.Sym() - w.setPkg(s.Pkg, true) - w.pos(t.Pos()) - - // We are writing out the name with the subscript, so that the - // typeparam name is unique. - w.string(s.Name) - w.int64(int64(t.Index())) - - w.typ(t.Bound()) - return - } - s := t.Sym() if s != nil && t.OrigSym != nil { assert(base.Flag.G > 0) @@ -880,6 +875,21 @@ func (w *exportWriter) doTyp(t *types.Type) { return } + // The 't.Underlying() == t' check is to confirm this is a base typeparam + // type, rather than a defined type with typeparam underlying type, like: + // type orderedAbs[T any] T + if t.Kind() == types.TTYPEPARAM && t.Underlying() == t { + assert(base.Flag.G > 0) + if s.Pkg == types.BuiltinPkg || s.Pkg == ir.Pkgs.Unsafe { + base.Fatalf("builtin type missing from typIndex: %v", t) + } + // Write out the first use of a type param as a qualified ident. + // This will force a "declaration" of the type param. + w.startType(typeParamType) + w.qualifiedIdent(t.Obj().(*ir.Name)) + return + } + if s != nil { if s.Pkg == types.BuiltinPkg || s.Pkg == ir.Pkgs.Unsafe { base.Fatalf("builtin type missing from typIndex: %v", t) @@ -1325,14 +1335,20 @@ func (w *exportWriter) funcExt(n *ir.Name) { // Inline body. if n.Type().HasTParam() { if n.Func.Inl != nil { - base.FatalfAt(n.Pos(), "generic function is marked inlineable") - } - // Populate n.Func.Inl, so body of exported generic function will - // be written out. - n.Func.Inl = &ir.Inline{ - Cost: 1, - Dcl: n.Func.Dcl, - Body: n.Func.Body, + // n.Func.Inl may already be set on a generic function if + // we imported it from another package, but shouldn't be + // set for a generic function in the local package. + if n.Sym().Pkg == types.LocalPkg { + base.FatalfAt(n.Pos(), "generic function is marked inlineable") + } + } else { + // Populate n.Func.Inl, so body of exported generic function will + // be written out. + n.Func.Inl = &ir.Inline{ + Cost: 1, + Dcl: n.Func.Dcl, + Body: n.Func.Body, + } } } if n.Func.Inl != nil { diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 96107b657b..9e6115cbf7 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -342,19 +342,22 @@ func (r *importReader) doDecl(sym *types.Sym) *ir.Name { // declaration before recursing. n := importtype(r.p.ipkg, pos, sym) t := n.Type() + if rparams != nil { + t.SetRParams(rparams) + } // We also need to defer width calculations until // after the underlying type has been assigned. types.DeferCheckSize() + deferDoInst() underlying := r.typ() t.SetUnderlying(underlying) - types.ResumeCheckSize() - - if rparams != nil { - t.SetRParams(rparams) - } if underlying.IsInterface() { + // Finish up all type instantiations and CheckSize calls + // now that a top-level type is fully constructed. + resumeDoInst() + types.ResumeCheckSize() r.typeExt(t) return n } @@ -380,12 +383,38 @@ func (r *importReader) doDecl(sym *types.Sym) *ir.Name { } t.Methods().Set(ms) + // Finish up all instantiations and CheckSize calls now + // that a top-level type is fully constructed. + resumeDoInst() + types.ResumeCheckSize() + r.typeExt(t) for _, m := range ms { r.methExt(m) } return n + case 'P': + if r.p.exportVersion < iexportVersionGenerics { + base.Fatalf("unexpected type param type") + } + if sym.Def != nil { + // Make sure we use the same type param type for the same + // name, whether it is created during types1-import or + // this types2-to-types1 translation. + return sym.Def.(*ir.Name) + } + index := int(r.int64()) + t := types.NewTypeParam(sym, index) + // Nname needed to save the pos. + nname := ir.NewDeclNameAt(pos, ir.OTYPE, sym) + sym.Def = nname + nname.SetType(t) + t.SetNod(nname) + + t.SetBound(r.typ()) + return nname + case 'V': typ := r.typ() @@ -545,7 +574,12 @@ func (r *importReader) pos() src.XPos { } func (r *importReader) typ() *types.Type { - return r.p.typAt(r.uint64()) + // If this is a top-level type call, defer type instantiations until the + // type is fully constructed. + deferDoInst() + t := r.p.typAt(r.uint64()) + resumeDoInst() + return t } func (r *importReader) exoticType() *types.Type { @@ -683,7 +717,13 @@ func (p *iimporter) typAt(off uint64) *types.Type { // are pushed to compile queue, then draining from the queue for compiling. // During this process, the size calculation is disabled, so it is not safe for // calculating size during SSA generation anymore. See issue #44732. - types.CheckSize(t) + // + // No need to calc sizes for re-instantiated generic types, and + // they are not necessarily resolved until the top-level type is + // defined (because of recursive types). + if t.OrigSym == nil || !t.HasTParam() { + types.CheckSize(t) + } p.typCache[off] = t } return t @@ -779,27 +819,18 @@ func (r *importReader) typ1() *types.Type { if r.p.exportVersion < iexportVersionGenerics { base.Fatalf("unexpected type param type") } - r.setPkg() - pos := r.pos() - name := r.string() - sym := r.currPkg.Lookup(name) - index := int(r.int64()) - bound := r.typ() - if sym.Def != nil { - // Make sure we use the same type param type for the same - // name, whether it is created during types1-import or - // this types2-to-types1 translation. - return sym.Def.Type() + // Similar to code for defined types, since we "declared" + // typeparams to deal with recursion (typeparam is used within its + // own type bound). + ident := r.qualifiedIdent() + if ident.Sym().Def != nil { + return ident.Sym().Def.(*ir.Name).Type() } - t := types.NewTypeParam(sym, index) - // Nname needed to save the pos. - nname := ir.NewDeclNameAt(pos, ir.OTYPE, sym) - sym.Def = nname - nname.SetType(t) - t.SetNod(nname) - - t.SetBound(bound) - return t + n := expandDecl(ident) + if n.Op() != ir.OTYPE { + base.Fatalf("expected OTYPE, got %v: %v, %v", n.Op(), n.Sym(), n) + } + return n.Type() case instType: if r.p.exportVersion < iexportVersionGenerics { @@ -1758,20 +1789,91 @@ func Instantiate(pos src.XPos, baseType *types.Type, targs []*types.Type) *types name := InstTypeName(baseSym.Name, targs) instSym := baseSym.Pkg.Lookup(name) if instSym.Def != nil { + // May match existing type from previous import or + // types2-to-types1 conversion, or from in-progress instantiation + // in the current type import stack. return instSym.Def.Type() } t := NewIncompleteNamedType(baseType.Pos(), instSym) t.SetRParams(targs) - // baseType may not yet be complete (since we are in the middle of - // importing it), but its underlying type will be updated when baseType's - // underlying type is finished. - t.SetUnderlying(baseType.Underlying()) - - // As with types2, the methods are the generic method signatures (without - // substitution). - t.Methods().Set(baseType.Methods().Slice()) t.OrigSym = baseSym + // baseType may still be TFORW or its methods may not be fully filled in + // (since we are in the middle of importing it). So, delay call to + // substInstType until we get back up to the top of the current top-most + // type import. + deferredInstStack = append(deferredInstStack, t) + return t } + +var deferredInstStack []*types.Type +var deferInst int + +// deferDoInst defers substitution on instantiated types until we are at the +// top-most defined type, so the base types are fully defined. +func deferDoInst() { + deferInst++ +} + +func resumeDoInst() { + if deferInst == 1 { + for len(deferredInstStack) > 0 { + t := deferredInstStack[0] + deferredInstStack = deferredInstStack[1:] + substInstType(t, t.OrigSym.Def.(*ir.Name).Type(), t.RParams()) + } + } + deferInst-- +} + +// doInst creates a new instantiation type (which will be added to +// deferredInstStack for completion later) for an incomplete type encountered +// during a type substitution for an instantiation. This is needed for +// instantiations of mutually recursive types. +func doInst(t *types.Type) *types.Type { + return Instantiate(t.Pos(), t.OrigSym.Def.(*ir.Name).Type(), t.RParams()) +} + +// substInstType completes the instantiation of a generic type by doing a +// substitution on the underlying type itself and any methods. t is the +// instantiation being created, baseType is the base generic type, and targs are +// the type arguments that baseType is being instantiated with. +func substInstType(t *types.Type, baseType *types.Type, targs []*types.Type) { + subst := Tsubster{ + Tparams: baseType.RParams(), + Targs: targs, + SubstForwFunc: doInst, + } + t.SetUnderlying(subst.Typ(baseType.Underlying())) + + newfields := make([]*types.Field, baseType.Methods().Len()) + for i, f := range baseType.Methods().Slice() { + recvType := f.Type.Recv().Type + if recvType.IsPtr() { + recvType = recvType.Elem() + } + // Substitute in the method using the type params used in the + // method (not the type params in the definition of the generic type). + subst := Tsubster{ + Tparams: recvType.RParams(), + Targs: targs, + SubstForwFunc: doInst, + } + t2 := subst.Typ(f.Type) + oldsym := f.Nname.Sym() + newsym := MakeInstName(oldsym, targs, true) + var nname *ir.Name + if newsym.Def != nil { + nname = newsym.Def.(*ir.Name) + } else { + nname = ir.NewNameAt(f.Pos, newsym) + nname.SetType(t2) + newsym.Def = nname + } + newfields[i] = types.NewField(f.Pos, f.Sym, t2) + newfields[i].Nname = nname + } + t.Methods().Set(newfields) +} diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 3e7799b35b..8ef49f91c8 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -890,7 +890,6 @@ func TypesOf(x []ir.Node) []*types.Type { // based on the name of the function fnsym and the targs. It replaces any // existing bracket type list in the name. makeInstName asserts that fnsym has // brackets in its name if and only if hasBrackets is true. -// TODO(danscales): remove the assertions and the hasBrackets argument later. // // Names of declared generic functions have no brackets originally, so hasBrackets // should be false. Names of generic methods already have brackets, since the new @@ -902,12 +901,24 @@ func TypesOf(x []ir.Node) []*types.Type { func MakeInstName(fnsym *types.Sym, targs []*types.Type, hasBrackets bool) *types.Sym { b := bytes.NewBufferString("") - // marker to distinguish generic instantiations from fully stenciled wrapper functions. + // Determine if the type args are concrete types or new typeparams. + hasTParam := false + for _, targ := range targs { + if hasTParam { + assert(targ.HasTParam()) + } else if targ.HasTParam() { + hasTParam = true + } + } + + // Marker to distinguish generic instantiations from fully stenciled wrapper functions. // Once we move to GC shape implementations, this prefix will not be necessary as the // GC shape naming will distinguish them. // e.g. f[8bytenonpointer] vs. f[int]. // For now, we use .inst.f[int] vs. f[int]. - b.WriteString(".inst.") + if !hasTParam { + b.WriteString(".inst.") + } name := fnsym.Name i := strings.Index(name, "[") @@ -942,10 +953,325 @@ func MakeInstName(fnsym *types.Sym, targs []*types.Type, hasBrackets bool) *type return fnsym.Pkg.Lookup(b.String()) } -// For catching problems as we add more features -// TODO(danscales): remove assertions or replace with base.FatalfAt() func assert(p bool) { if !p { panic("assertion failed") } } + +// General type substituter, for replacing typeparams with type args. +type Tsubster struct { + Tparams []*types.Type + Targs []*types.Type + // If non-nil, the substitution map from name nodes in the generic function to the + // name nodes in the new stenciled function. + Vars map[*ir.Name]*ir.Name + // New fully-instantiated generic types whose methods should be instantiated. + InstTypeList []*types.Type + // If non-nil, function to substitute an incomplete (TFORW) type. + SubstForwFunc func(*types.Type) *types.Type +} + +// Typ computes the type obtained by substituting any type parameter in t with the +// corresponding type argument in subst. If t contains no type parameters, the +// result is t; otherwise the result is a new type. It deals with recursive types +// by using TFORW types and finding partially or fully created types via sym.Def. +func (ts *Tsubster) Typ(t *types.Type) *types.Type { + if !t.HasTParam() && t.Kind() != types.TFUNC { + // Note: function types need to be copied regardless, as the + // types of closures may contain declarations that need + // to be copied. See #45738. + return t + } + + if t.Kind() == types.TTYPEPARAM { + for i, tp := range ts.Tparams { + if tp == t { + return ts.Targs[i] + } + } + // If t is a simple typeparam T, then t has the name/symbol 'T' + // and t.Underlying() == t. + // + // However, consider the type definition: 'type P[T any] T'. We + // might use this definition so we can have a variant of type T + // that we can add new methods to. Suppose t is a reference to + // P[T]. t has the name 'P[T]', but its kind is TTYPEPARAM, + // because P[T] is defined as T. If we look at t.Underlying(), it + // is different, because the name of t.Underlying() is 'T' rather + // than 'P[T]'. But the kind of t.Underlying() is also TTYPEPARAM. + // In this case, we do the needed recursive substitution in the + // case statement below. + if t.Underlying() == t { + // t is a simple typeparam that didn't match anything in tparam + return t + } + // t is a more complex typeparam (e.g. P[T], as above, whose + // definition is just T). + assert(t.Sym() != nil) + } + + var newsym *types.Sym + var neededTargs []*types.Type + var forw *types.Type + + if t.Sym() != nil { + // Translate the type params for this type according to + // the tparam/targs mapping from subst. + neededTargs = make([]*types.Type, len(t.RParams())) + for i, rparam := range t.RParams() { + neededTargs[i] = ts.Typ(rparam) + } + // For a named (defined) type, we have to change the name of the + // type as well. We do this first, so we can look up if we've + // already seen this type during this substitution or other + // definitions/substitutions. + genName := genericTypeName(t.Sym()) + newsym = t.Sym().Pkg.Lookup(InstTypeName(genName, neededTargs)) + if newsym.Def != nil { + // We've already created this instantiated defined type. + return newsym.Def.Type() + } + + // In order to deal with recursive generic types, create a TFORW + // type initially and set the Def field of its sym, so it can be + // found if this type appears recursively within the type. + forw = NewIncompleteNamedType(t.Pos(), newsym) + //println("Creating new type by sub", newsym.Name, forw.HasTParam()) + forw.SetRParams(neededTargs) + // Copy the OrigSym from the re-instantiated type (which is the sym of + // the base generic type). + assert(t.OrigSym != nil) + forw.OrigSym = t.OrigSym + } + + var newt *types.Type + + switch t.Kind() { + case types.TTYPEPARAM: + if t.Sym() == newsym { + // The substitution did not change the type. + return t + } + // Substitute the underlying typeparam (e.g. T in P[T], see + // the example describing type P[T] above). + newt = ts.Typ(t.Underlying()) + assert(newt != t) + + case types.TARRAY: + elem := t.Elem() + newelem := ts.Typ(elem) + if newelem != elem { + newt = types.NewArray(newelem, t.NumElem()) + } + + case types.TPTR: + elem := t.Elem() + newelem := ts.Typ(elem) + if newelem != elem { + newt = types.NewPtr(newelem) + } + + case types.TSLICE: + elem := t.Elem() + newelem := ts.Typ(elem) + if newelem != elem { + newt = types.NewSlice(newelem) + } + + case types.TSTRUCT: + newt = ts.tstruct(t, false) + if newt == t { + newt = nil + } + + case types.TFUNC: + newrecvs := ts.tstruct(t.Recvs(), false) + newparams := ts.tstruct(t.Params(), false) + newresults := ts.tstruct(t.Results(), false) + if newrecvs != t.Recvs() || newparams != t.Params() || newresults != t.Results() { + // If any types have changed, then the all the fields of + // of recv, params, and results must be copied, because they have + // offset fields that are dependent, and so must have an + // independent copy for each new signature. + var newrecv *types.Field + if newrecvs.NumFields() > 0 { + if newrecvs == t.Recvs() { + newrecvs = ts.tstruct(t.Recvs(), true) + } + newrecv = newrecvs.Field(0) + } + if newparams == t.Params() { + newparams = ts.tstruct(t.Params(), true) + } + if newresults == t.Results() { + newresults = ts.tstruct(t.Results(), true) + } + newt = types.NewSignature(t.Pkg(), newrecv, t.TParams().FieldSlice(), newparams.FieldSlice(), newresults.FieldSlice()) + } + + case types.TINTER: + newt = ts.tinter(t) + if newt == t { + newt = nil + } + + case types.TMAP: + newkey := ts.Typ(t.Key()) + newval := ts.Typ(t.Elem()) + if newkey != t.Key() || newval != t.Elem() { + newt = types.NewMap(newkey, newval) + } + + case types.TCHAN: + elem := t.Elem() + newelem := ts.Typ(elem) + if newelem != elem { + newt = types.NewChan(newelem, t.ChanDir()) + if !newt.HasTParam() { + // TODO(danscales): not sure why I have to do this + // only for channels..... + types.CheckSize(newt) + } + } + case types.TFORW: + if ts.SubstForwFunc != nil { + newt = ts.SubstForwFunc(t) + } else { + assert(false) + } + } + if newt == nil { + // Even though there were typeparams in the type, there may be no + // change if this is a function type for a function call (which will + // have its own tparams/targs in the function instantiation). + return t + } + + if t.Sym() == nil { + // Not a named type, so there was no forwarding type and there are + // no methods to substitute. + assert(t.Methods().Len() == 0) + return newt + } + + forw.SetUnderlying(newt) + newt = forw + + if t.Kind() != types.TINTER && t.Methods().Len() > 0 { + // Fill in the method info for the new type. + var newfields []*types.Field + newfields = make([]*types.Field, t.Methods().Len()) + for i, f := range t.Methods().Slice() { + t2 := ts.Typ(f.Type) + oldsym := f.Nname.Sym() + newsym := MakeInstName(oldsym, ts.Targs, true) + var nname *ir.Name + if newsym.Def != nil { + nname = newsym.Def.(*ir.Name) + } else { + nname = ir.NewNameAt(f.Pos, newsym) + nname.SetType(t2) + newsym.Def = nname + } + newfields[i] = types.NewField(f.Pos, f.Sym, t2) + newfields[i].Nname = nname + } + newt.Methods().Set(newfields) + if !newt.HasTParam() { + // Generate all the methods for a new fully-instantiated type. + ts.InstTypeList = append(ts.InstTypeList, newt) + } + } + return newt +} + +// tstruct substitutes type params in types of the fields of a structure type. For +// each field, tstruct copies the Nname, and translates it if Nname is in +// ts.vars. To always force the creation of a new (top-level) struct, +// regardless of whether anything changed with the types or names of the struct's +// fields, set force to true. +func (ts *Tsubster) tstruct(t *types.Type, force bool) *types.Type { + if t.NumFields() == 0 { + if t.HasTParam() { + // For an empty struct, we need to return a new type, + // since it may now be fully instantiated (HasTParam + // becomes false). + return types.NewStruct(t.Pkg(), nil) + } + return t + } + var newfields []*types.Field + if force { + newfields = make([]*types.Field, t.NumFields()) + } + for i, f := range t.Fields().Slice() { + t2 := ts.Typ(f.Type) + if (t2 != f.Type || f.Nname != nil) && newfields == nil { + newfields = make([]*types.Field, t.NumFields()) + for j := 0; j < i; j++ { + newfields[j] = t.Field(j) + } + } + if newfields != nil { + // TODO(danscales): make sure this works for the field + // names of embedded types (which should keep the name of + // the type param, not the instantiated type). + newfields[i] = types.NewField(f.Pos, f.Sym, t2) + if f.Nname != nil && ts.Vars != nil { + v := ts.Vars[f.Nname.(*ir.Name)] + if v != nil { + // This is the case where we are + // translating the type of the function we + // are substituting, so its dcls are in + // the subst.ts.vars table, and we want to + // change to reference the new dcl. + newfields[i].Nname = v + } else { + // This is the case where we are + // translating the type of a function + // reference inside the function we are + // substituting, so we leave the Nname + // value as is. + newfields[i].Nname = f.Nname + } + } + } + } + if newfields != nil { + return types.NewStruct(t.Pkg(), newfields) + } + return t + +} + +// tinter substitutes type params in types of the methods of an interface type. +func (ts *Tsubster) tinter(t *types.Type) *types.Type { + if t.Methods().Len() == 0 { + return t + } + var newfields []*types.Field + for i, f := range t.Methods().Slice() { + t2 := ts.Typ(f.Type) + if (t2 != f.Type || f.Nname != nil) && newfields == nil { + newfields = make([]*types.Field, t.Methods().Len()) + for j := 0; j < i; j++ { + newfields[j] = t.Methods().Index(j) + } + } + if newfields != nil { + newfields[i] = types.NewField(f.Pos, f.Sym, t2) + } + } + if newfields != nil { + return types.NewInterface(t.Pkg(), newfields) + } + return t +} + +// genericSym returns the name of the base generic type for the type named by +// sym. It simply returns the name obtained by removing everything after the +// first bracket ("["). +func genericTypeName(sym *types.Sym) string { + return sym.Name[0:strings.Index(sym.Name, "[")] +} diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 20c4ff62a1..8e13b0ff18 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -767,8 +767,10 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { // uses of real() where the result is used to // define type and initialize a variable? - // construct a suitable new type parameter - tpar := NewTypeName(nopos, nil /* = Universe pkg */, "", nil) + // Construct a suitable new type parameter for the sum type. The + // type param is placed in the current package so export/import + // works as expected. + tpar := NewTypeName(nopos, check.pkg, "", nil) ptyp := check.NewTypeParam(tpar, 0, &emptyInterface) // assigns type to tpar as a side-effect tsum := newUnion(rtypes, tildes) ptyp.bound = &Interface{allMethods: markComplete, allTypes: tsum} diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 604520d27f..10cb651d0c 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -640,9 +640,8 @@ type TypeParam struct { // Obj returns the type name for the type parameter t. func (t *TypeParam) Obj() *TypeName { return t.obj } -// NewTypeParam returns a new TypeParam. +// NewTypeParam returns a new TypeParam. bound can be nil (and set later). func (check *Checker) NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam { - assert(bound != nil) // Always increment lastID, even if it is not used. id := nextID() if check != nil { @@ -679,11 +678,20 @@ func (t *TypeParam) Bound() *Interface { return iface } -// optype returns a type's operational type. Except for type parameters, -// the operational type is the same as the underlying type (as returned -// by under). For Type parameters, the operational type is determined -// by the corresponding type constraint. The result may be the top type, -// but it is never the incoming type parameter. +func (t *TypeParam) SetBound(bound Type) { + if bound == nil { + panic("types2.TypeParam.SetBound: bound must not be nil") + } + t.bound = bound +} + +// optype returns a type's operational type. Except for +// type parameters, the operational type is the same +// as the underlying type (as returned by under). For +// Type parameters, the operational type is determined +// by the corresponding type bound's type list. The +// result may be the bottom or top type, but it is never +// the incoming type parameter. func optype(typ Type) Type { if t := asTypeParam(typ); t != nil { // If the optype is typ, return the top type as we have diff --git a/test/typeparam/absdiff.go b/test/typeparam/absdiff.go index ecaa907795..e76a998b4d 100644 --- a/test/typeparam/absdiff.go +++ b/test/typeparam/absdiff.go @@ -48,8 +48,7 @@ type Complex interface { type orderedAbs[T orderedNumeric] T func (a orderedAbs[T]) Abs() orderedAbs[T] { - // TODO(danscales): orderedAbs[T] conversion shouldn't be needed - if a < orderedAbs[T](0) { + if a < 0 { return -a } return a diff --git a/test/typeparam/absdiffimp.dir/a.go b/test/typeparam/absdiffimp.dir/a.go new file mode 100644 index 0000000000..df81dcf538 --- /dev/null +++ b/test/typeparam/absdiffimp.dir/a.go @@ -0,0 +1,75 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +import ( + "math" +) + +type Numeric interface { + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 | + ~complex64 | ~complex128 +} + +// numericAbs matches numeric types with an Abs method. +type numericAbs[T any] interface { + Numeric + Abs() T +} + +// AbsDifference computes the absolute value of the difference of +// a and b, where the absolute value is determined by the Abs method. +func absDifference[T numericAbs[T]](a, b T) T { + d := a - b + return d.Abs() +} + +// orderedNumeric matches numeric types that support the < operator. +type orderedNumeric interface { + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 +} + +// Complex matches the two complex types, which do not have a < operator. +type Complex interface { + ~complex64 | ~complex128 +} + +// orderedAbs is a helper type that defines an Abs method for +// ordered numeric types. +type orderedAbs[T orderedNumeric] T + +func (a orderedAbs[T]) Abs() orderedAbs[T] { + if a < 0 { + return -a + } + return a +} + +// complexAbs is a helper type that defines an Abs method for +// complex types. +type complexAbs[T Complex] T + +func (a complexAbs[T]) Abs() complexAbs[T] { + r := float64(real(a)) + i := float64(imag(a)) + d := math.Sqrt(r * r + i * i) + return complexAbs[T](complex(d, 0)) +} + +// OrderedAbsDifference returns the absolute value of the difference +// between a and b, where a and b are of an ordered type. +func OrderedAbsDifference[T orderedNumeric](a, b T) T { + return T(absDifference(orderedAbs[T](a), orderedAbs[T](b))) +} + +// ComplexAbsDifference returns the absolute value of the difference +// between a and b, where a and b are of a complex type. +func ComplexAbsDifference[T Complex](a, b T) T { + return T(absDifference(complexAbs[T](a), complexAbs[T](b))) +} diff --git a/test/typeparam/absdiffimp.dir/main.go b/test/typeparam/absdiffimp.dir/main.go new file mode 100644 index 0000000000..8eefdbdf38 --- /dev/null +++ b/test/typeparam/absdiffimp.dir/main.go @@ -0,0 +1,29 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "a" + "fmt" +) + +func main() { + if got, want := a.OrderedAbsDifference(1.0, -2.0), 3.0; got != want { + panic(fmt.Sprintf("got = %v, want = %v", got, want)) + } + if got, want := a.OrderedAbsDifference(-1.0, 2.0), 3.0; got != want { + panic(fmt.Sprintf("got = %v, want = %v", got, want)) + } + if got, want := a.OrderedAbsDifference(-20, 15), 35; got != want { + panic(fmt.Sprintf("got = %v, want = %v", got, want)) + } + + if got, want := a.ComplexAbsDifference(5.0+2.0i, 2.0-2.0i), 5+0i; got != want { + panic(fmt.Sprintf("got = %v, want = %v", got, want)) + } + if got, want := a.ComplexAbsDifference(2.0-2.0i, 5.0+2.0i), 5+0i; got != want { + panic(fmt.Sprintf("got = %v, want = %v", got, want)) + } +} diff --git a/test/typeparam/absdiffimp.go b/test/typeparam/absdiffimp.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/absdiffimp.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored diff --git a/test/typeparam/orderedmapsimp.dir/a.go b/test/typeparam/orderedmapsimp.dir/a.go new file mode 100644 index 0000000000..1b5827b4bb --- /dev/null +++ b/test/typeparam/orderedmapsimp.dir/a.go @@ -0,0 +1,226 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +import ( + "context" + "runtime" +) + +type Ordered interface { + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 | + ~string +} + +// Map is an ordered map. +type Map[K, V any] struct { + root *node[K, V] + compare func(K, K) int +} + +// node is the type of a node in the binary tree. +type node[K, V any] struct { + key K + val V + left, right *node[K, V] +} + +// New returns a new map. It takes a comparison function that compares two +// keys and returns < 0 if the first is less, == 0 if they are equal, +// > 0 if the first is greater. +func New[K, V any](compare func(K, K) int) *Map[K, V] { + return &Map[K, V]{compare: compare} +} + +// NewOrdered returns a new map whose key is an ordered type. +// This is like New, but does not require providing a compare function. +// The map compare function uses the obvious key ordering. +func NewOrdered[K Ordered, V any]() *Map[K, V] { + return New[K, V](func(k1, k2 K) int { + switch { + case k1 < k2: + return -1 + case k1 > k2: + return 1 + default: + return 0 + } + }) +} + +// find looks up key in the map, returning either a pointer to the slot of the +// node holding key, or a pointer to the slot where a node would go. +func (m *Map[K, V]) find(key K) **node[K, V] { + pn := &m.root + for *pn != nil { + switch cmp := m.compare(key, (*pn).key); { + case cmp < 0: + pn = &(*pn).left + case cmp > 0: + pn = &(*pn).right + default: + return pn + } + } + return pn +} + +// Insert inserts a new key/value into the map. +// If the key is already present, the value is replaced. +// Reports whether this is a new key. +func (m *Map[K, V]) Insert(key K, val V) bool { + pn := m.find(key) + if *pn != nil { + (*pn).val = val + return false + } + *pn = &node[K, V]{key: key, val: val} + return true +} + +// Find returns the value associated with a key, or the zero value +// if not present. The second result reports whether the key was found. +func (m *Map[K, V]) Find(key K) (V, bool) { + pn := m.find(key) + if *pn == nil { + var zero V + return zero, false + } + return (*pn).val, true +} + +// keyValue is a pair of key and value used while iterating. +type keyValue[K, V any] struct { + key K + val V +} + +// iterate returns an iterator that traverses the map. +// func (m *Map[K, V]) Iterate() *Iterator[K, V] { +// sender, receiver := Ranger[keyValue[K, V]]() +// var f func(*node[K, V]) bool +// f = func(n *node[K, V]) bool { +// if n == nil { +// return true +// } +// // Stop the traversal if Send fails, which means that +// // nothing is listening to the receiver. +// return f(n.left) && +// sender.Send(context.Background(), keyValue[K, V]{n.key, n.val}) && +// f(n.right) +// } +// go func() { +// f(m.root) +// sender.Close() +// }() +// return &Iterator[K, V]{receiver} +// } + +// Iterator is used to iterate over the map. +type Iterator[K, V any] struct { + r *Receiver[keyValue[K, V]] +} + +// Next returns the next key and value pair, and a boolean that reports +// whether they are valid. If not valid, we have reached the end of the map. +func (it *Iterator[K, V]) Next() (K, V, bool) { + keyval, ok := it.r.Next(context.Background()) + if !ok { + var zerok K + var zerov V + return zerok, zerov, false + } + return keyval.key, keyval.val, true +} + +// Equal reports whether two slices are equal: the same length and all +// elements equal. All floating point NaNs are considered equal. +func SliceEqual[Elem comparable](s1, s2 []Elem) bool { + if len(s1) != len(s2) { + return false + } + for i, v1 := range s1 { + v2 := s2[i] + if v1 != v2 { + isNaN := func(f Elem) bool { return f != f } + if !isNaN(v1) || !isNaN(v2) { + return false + } + } + } + return true +} + +// Ranger returns a Sender and a Receiver. The Receiver provides a +// Next method to retrieve values. The Sender provides a Send method +// to send values and a Close method to stop sending values. The Next +// method indicates when the Sender has been closed, and the Send +// method indicates when the Receiver has been freed. +// +// This is a convenient way to exit a goroutine sending values when +// the receiver stops reading them. +func Ranger[Elem any]() (*Sender[Elem], *Receiver[Elem]) { + c := make(chan Elem) + d := make(chan struct{}) + s := &Sender[Elem]{ + values: c, + done: d, + } + r := &Receiver[Elem] { + values: c, + done: d, + } + runtime.SetFinalizer(r, (*Receiver[Elem]).finalize) + return s, r +} + +// A Sender is used to send values to a Receiver. +type Sender[Elem any] struct { + values chan<- Elem + done <-chan struct{} +} + +// Send sends a value to the receiver. It reports whether the value was sent. +// The value will not be sent if the context is closed or the receiver +// is freed. +func (s *Sender[Elem]) Send(ctx context.Context, v Elem) bool { + select { + case <-ctx.Done(): + return false + case s.values <- v: + return true + case <-s.done: + return false + } +} + +// Close tells the receiver that no more values will arrive. +// After Close is called, the Sender may no longer be used. +func (s *Sender[Elem]) Close() { + close(s.values) +} + +// A Receiver receives values from a Sender. +type Receiver[Elem any] struct { + values <-chan Elem + done chan<- struct{} +} + +// Next returns the next value from the channel. The bool result indicates +// whether the value is valid. +func (r *Receiver[Elem]) Next(ctx context.Context) (v Elem, ok bool) { + select { + case <-ctx.Done(): + case v, ok = <-r.values: + } + return v, ok +} + +// finalize is a finalizer for the receiver. +func (r *Receiver[Elem]) finalize() { + close(r.done) +} diff --git a/test/typeparam/orderedmapsimp.dir/main.go b/test/typeparam/orderedmapsimp.dir/main.go new file mode 100644 index 0000000000..77869ad9fc --- /dev/null +++ b/test/typeparam/orderedmapsimp.dir/main.go @@ -0,0 +1,67 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "a" + "bytes" + "fmt" +) + +func TestMap() { + m := a.New[[]byte, int](bytes.Compare) + + if _, found := m.Find([]byte("a")); found { + panic(fmt.Sprintf("unexpectedly found %q in empty map", []byte("a"))) + } + + for _, c := range []int{ 'a', 'c', 'b' } { + if !m.Insert([]byte(string(c)), c) { + panic(fmt.Sprintf("key %q unexpectedly already present", []byte(string(c)))) + } + } + if m.Insert([]byte("c"), 'x') { + panic(fmt.Sprintf("key %q unexpectedly not present", []byte("c"))) + } + + if v, found := m.Find([]byte("a")); !found { + panic(fmt.Sprintf("did not find %q", []byte("a"))) + } else if v != 'a' { + panic(fmt.Sprintf("key %q returned wrong value %c, expected %c", []byte("a"), v, 'a')) + } + if v, found := m.Find([]byte("c")); !found { + panic(fmt.Sprintf("did not find %q", []byte("c"))) + } else if v != 'x' { + panic(fmt.Sprintf("key %q returned wrong value %c, expected %c", []byte("c"), v, 'x')) + } + + if _, found := m.Find([]byte("d")); found { + panic(fmt.Sprintf("unexpectedly found %q", []byte("d"))) + } + + // TODO(danscales): Iterate() has some things to be fixed with inlining in + // stenciled functions and using closures across packages. + + // gather := func(it *a.Iterator[[]byte, int]) []int { + // var r []int + // for { + // _, v, ok := it.Next() + // if !ok { + // return r + // } + // r = append(r, v) + // } + // } + // got := gather(m.Iterate()) + // want := []int{'a', 'b', 'x'} + // if !a.SliceEqual(got, want) { + // panic(fmt.Sprintf("Iterate returned %v, want %v", got, want)) + // } + +} + +func main() { + TestMap() +} diff --git a/test/typeparam/orderedmapsimp.go b/test/typeparam/orderedmapsimp.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/orderedmapsimp.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored diff --git a/test/typeparam/value.go b/test/typeparam/value.go index 5dd7449d9c..6c6dabcf7c 100644 --- a/test/typeparam/value.go +++ b/test/typeparam/value.go @@ -12,7 +12,7 @@ type value[T any] struct { val T } -func get[T2 any](v *value[T2]) T2 { +func get[T any](v *value[T]) T { return v.val } @@ -20,11 +20,11 @@ func set[T any](v *value[T], val T) { v.val = val } -func (v *value[T2]) set(val T2) { +func (v *value[T]) set(val T) { v.val = val } -func (v *value[T2]) get() T2 { +func (v *value[T]) get() T { return v.val } -- GitLab From 46beeed0ac4cd409554167c315861eaf8ae68c4a Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 3 Jun 2021 18:25:47 -0400 Subject: [PATCH 0220/2500] [dev.typeparams] cmd/compile: allow go'd closure to escape when compiling runtime When compiling runtime, we don't allow closures to escape, because we don't want (implicit) allocations to occur when it is not okay to allocate (e.g. in the allocator itself). However, for go statement, it already allocates a new goroutine anyway. It is okay to allocate the closure. Allow it. Also include the closure's name when reporting error. Updates #40724. Change-Id: Id7574ed17cc27709609a059c4eaa67ba1c4436dc Reviewed-on: https://go-review.googlesource.com/c/go/+/325109 Trust: Cherry Mui Reviewed-by: Than McIntosh --- src/cmd/compile/internal/ir/expr.go | 1 + src/cmd/compile/internal/ir/func.go | 4 ++-- src/cmd/compile/internal/walk/order.go | 14 ++++++-------- test/fixedbugs/issue14999.go | 4 ++-- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 519120ed6b..856b255657 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -192,6 +192,7 @@ type ClosureExpr struct { miniExpr Func *Func `mknode:"-"` Prealloc *Name + IsGoWrap bool // whether this is wrapper closure of a go statement } func NewClosureExpr(pos src.XPos, fn *Func) *ClosureExpr { diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go index ca6c8eca8b..1d76813a4c 100644 --- a/src/cmd/compile/internal/ir/func.go +++ b/src/cmd/compile/internal/ir/func.go @@ -301,8 +301,8 @@ func ClosureDebugRuntimeCheck(clo *ClosureExpr) { base.WarnfAt(clo.Pos(), "stack closure, captured vars = %v", clo.Func.ClosureVars) } } - if base.Flag.CompilingRuntime && clo.Esc() == EscHeap { - base.ErrorfAt(clo.Pos(), "heap-allocated closure, not allowed in runtime") + if base.Flag.CompilingRuntime && clo.Esc() == EscHeap && !clo.IsGoWrap { + base.ErrorfAt(clo.Pos(), "heap-allocated closure %s, not allowed in runtime", FuncName(clo.Func)) } } diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go index b733d3a29f..19d9551566 100644 --- a/src/cmd/compile/internal/walk/order.go +++ b/src/cmd/compile/internal/walk/order.go @@ -1570,8 +1570,9 @@ func (o *orderState) wrapGoDefer(n *ir.GoDeferStmt) { // only in-register results? if len(callArgs) == 0 && call.Op() == ir.OCALLFUNC && callX.Type().NumResults() == 0 { if c, ok := call.(*ir.CallExpr); ok && callX != nil && callX.Op() == ir.OCLOSURE { - cloFunc := callX.(*ir.ClosureExpr).Func - cloFunc.SetClosureCalled(false) + clo := callX.(*ir.ClosureExpr) + clo.Func.SetClosureCalled(false) + clo.IsGoWrap = true c.PreserveClosure = true } return @@ -1777,12 +1778,9 @@ func (o *orderState) wrapGoDefer(n *ir.GoDeferStmt) { // Set escape properties for closure. if n.Op() == ir.OGO { - // For "go", assume that the closure is going to escape - // (with an exception for the runtime, which doesn't - // permit heap-allocated closures). - if base.Ctxt.Pkgpath != "runtime" { - clo.SetEsc(ir.EscHeap) - } + // For "go", assume that the closure is going to escape. + clo.SetEsc(ir.EscHeap) + clo.IsGoWrap = true } else { // For defer, just use whatever result escape analysis // has determined for the defer. diff --git a/test/fixedbugs/issue14999.go b/test/fixedbugs/issue14999.go index b648441fc2..a25a50e519 100644 --- a/test/fixedbugs/issue14999.go +++ b/test/fixedbugs/issue14999.go @@ -7,11 +7,11 @@ package p func f(x int) func(int) int { - return func(y int) int { return x + y } // ERROR "heap-allocated closure, not allowed in runtime" + return func(y int) int { return x + y } // ERROR "heap-allocated closure f\.func1, not allowed in runtime" } func g(x int) func(int) int { // ERROR "x escapes to heap, not allowed in runtime" - return func(y int) int { // ERROR "heap-allocated closure, not allowed in runtime" + return func(y int) int { // ERROR "heap-allocated closure g\.func1, not allowed in runtime" x += y return x + y } -- GitLab From 3298c749acc32eca0460f52866d169441eb0e076 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 3 Jun 2021 18:29:05 -0400 Subject: [PATCH 0221/2500] [dev.typeparams] runtime: undo go'd closure argument workaround In CL 298669 we added defer/go wrapping, and, as it is not allowed for closures to escape when compiling runtime, we worked around it by rewriting go'd closures to argumentless non-capturing closures, so it is not a real closure and so not needed to escape. Previous CL removes the restriction. Now we can undo the workaround. Updates #40724. Change-Id: Ic7bf129da4aee7b7fdb7157414eca943a6a27264 Reviewed-on: https://go-review.googlesource.com/c/go/+/325110 Trust: Cherry Mui Reviewed-by: Than McIntosh --- src/runtime/export_test.go | 20 ++++---------------- src/runtime/mgc.go | 15 +++++---------- src/runtime/mgcscavenge.go | 4 ++-- src/runtime/mgcsweep.go | 4 ++-- 4 files changed, 13 insertions(+), 30 deletions(-) diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index fa878c4946..60c06c3f10 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -145,40 +145,28 @@ func RunSchedLocalQueueStealTest() { } } -// Temporary to enable register ABI bringup. -// TODO(register args): convert back to local variables in RunSchedLocalQueueEmptyTest that -// get passed to the "go" stmts there. -var RunSchedLocalQueueEmptyState struct { - done chan bool - ready *uint32 - p *p -} - func RunSchedLocalQueueEmptyTest(iters int) { // Test that runq is not spuriously reported as empty. // Runq emptiness affects scheduling decisions and spurious emptiness // can lead to underutilization (both runnable Gs and idle Ps coexist // for arbitrary long time). done := make(chan bool, 1) - RunSchedLocalQueueEmptyState.done = done p := new(p) - RunSchedLocalQueueEmptyState.p = p gs := make([]g, 2) ready := new(uint32) - RunSchedLocalQueueEmptyState.ready = ready for i := 0; i < iters; i++ { *ready = 0 next0 := (i & 1) == 0 next1 := (i & 2) == 0 runqput(p, &gs[0], next0) go func() { - for atomic.Xadd(RunSchedLocalQueueEmptyState.ready, 1); atomic.Load(RunSchedLocalQueueEmptyState.ready) != 2; { + for atomic.Xadd(ready, 1); atomic.Load(ready) != 2; { } - if runqempty(RunSchedLocalQueueEmptyState.p) { - //println("next:", next0, next1) + if runqempty(p) { + println("next:", next0, next1) throw("queue is empty") } - RunSchedLocalQueueEmptyState.done <- true + done <- true }() for atomic.Xadd(ready, 1); atomic.Load(ready) != 2; { } diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go index 4585663535..c239fa0f63 100644 --- a/src/runtime/mgc.go +++ b/src/runtime/mgc.go @@ -167,22 +167,17 @@ func gcinit() { lockInit(&work.wbufSpans.lock, lockRankWbufSpans) } -// Temporary in order to enable register ABI work. -// TODO(register args): convert back to local chan in gcenabled, passed to "go" stmts. -var gcenable_setup chan int - // gcenable is called after the bulk of the runtime initialization, // just before we're about to start letting user code run. // It kicks off the background sweeper goroutine, the background // scavenger goroutine, and enables GC. func gcenable() { // Kick off sweeping and scavenging. - gcenable_setup = make(chan int, 2) - go bgsweep() - go bgscavenge() - <-gcenable_setup - <-gcenable_setup - gcenable_setup = nil + c := make(chan int, 2) + go bgsweep(c) + go bgscavenge(c) + <-c + <-c memstats.enablegc = true // now that runtime is initialized, GC is okay } diff --git a/src/runtime/mgcscavenge.go b/src/runtime/mgcscavenge.go index 7578129f9d..9cb61ed0a6 100644 --- a/src/runtime/mgcscavenge.go +++ b/src/runtime/mgcscavenge.go @@ -249,7 +249,7 @@ func scavengeSleep(ns int64) int64 { // The background scavenger maintains the RSS of the application below // the line described by the proportional scavenging statistics in // the mheap struct. -func bgscavenge() { +func bgscavenge(c chan int) { scavenge.g = getg() lockInit(&scavenge.lock, lockRankScavenge) @@ -261,7 +261,7 @@ func bgscavenge() { wakeScavenger() } - gcenable_setup <- 1 + c <- 1 goparkunlock(&scavenge.lock, waitReasonGCScavengeWait, traceEvGoBlock, 1) // Exponentially-weighted moving average of the fraction of time this diff --git a/src/runtime/mgcsweep.go b/src/runtime/mgcsweep.go index 8fe3a65340..1812644623 100644 --- a/src/runtime/mgcsweep.go +++ b/src/runtime/mgcsweep.go @@ -153,13 +153,13 @@ func finishsweep_m() { nextMarkBitArenaEpoch() } -func bgsweep() { +func bgsweep(c chan int) { sweep.g = getg() lockInit(&sweep.lock, lockRankSweep) lock(&sweep.lock) sweep.parked = true - gcenable_setup <- 1 + c <- 1 goparkunlock(&sweep.lock, waitReasonGCSweepWait, traceEvGoBlock, 1) for { -- GitLab From 4cf7f5f6947c1e3200d669ae7b8016f7431d718c Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 4 Jun 2021 11:09:25 -0400 Subject: [PATCH 0222/2500] [dev.typeparams] test: test regabidefers in live.go Previously, live.go is conditioned on not using regabidefers. Now we have regabidefers enabled by default everywhere, and we may remove the fallback path in the near future, test that configuration instead. Change-Id: Idf910aee323bdd6478bc7a2062b2052d82ce003f Reviewed-on: https://go-review.googlesource.com/c/go/+/325111 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- test/live.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/live.go b/test/live.go index bc7b3849cf..ee51134371 100644 --- a/test/live.go +++ b/test/live.go @@ -1,5 +1,5 @@ // errorcheckwithauto -0 -l -live -wb=0 -d=ssa/insert_resched_checks/off -// +build !ppc64,!ppc64le,!goexperiment.regabi,!goexperiment.regabidefer +// +build !ppc64,!ppc64le,goexperiment.regabidefer,!goexperiment.regabiargs // ppc64 needs a better tighten pass to make f18 pass // rescheduling checks need to be turned off because there are some live variables across the inserted check call @@ -424,7 +424,7 @@ func f27defer(b bool) { } defer call27(func() { x++ }) // ERROR "stack object .autotmp_[0-9]+ struct \{" printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+ .autotmp_[0-9]+" - return // ERROR "live at call to call27: .autotmp_[0-9]+" + return // ERROR "live at indirect call: .autotmp_[0-9]+" } // and newproc (go) escapes to the heap @@ -432,9 +432,9 @@ func f27defer(b bool) { func f27go(b bool) { x := 0 if b { - go call27(func() { x++ }) // ERROR "live at call to newobject: &x$" "live at call to newproc: &x$" + go call27(func() { x++ }) // ERROR "live at call to newobject: &x$" "live at call to newobject: &x .autotmp_[0-9]+$" "live at call to newproc: &x$" // allocate two closures, the func literal, and the wrapper for go } - go call27(func() { x++ }) // ERROR "live at call to newobject: &x$" + go call27(func() { x++ }) // ERROR "live at call to newobject: &x$" "live at call to newobject: .autotmp_[0-9]+$" // allocate two closures, the func literal, and the wrapper for go printnl() } -- GitLab From de614651561c6d5bfe1e68bddaf0dedab9a0ecb0 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 1 Jun 2021 10:49:14 -0700 Subject: [PATCH 0223/2500] [dev.typeparams] cmd/compile: allow inlining in instantiated functions Change markType to scan generic types and methods, so that inlineable functions inside generic functions/methods will be properly marked for export, which means inlining inside instantiated functions will work correctly. Also, fix handling of closures for instantiated functions. Some code needs to be adjusted, since instantiated functions/methods are compiled as if in the package of the source generic function/type, rather than in the local package. When we create the closure struct, we want to make sure that the .F field has the same package as the other fields for the closure variables. Also, we need to disable a check in tcCompLit() when being done for an instantiated function, since fields of the closure struct will be from the source package, not the local package. Re-enabled part of the orderedmapsimp test that was disabled because of these issues. Change-Id: Ic4dba8917da0a36b17c0bdb69d6d6edfdf14104a Reviewed-on: https://go-review.googlesource.com/c/go/+/324331 Trust: Dan Scales Run-TryBot: Dan Scales Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/export.go | 12 +++--- src/cmd/compile/internal/noder/decl.go | 10 +++++ src/cmd/compile/internal/noder/stencil.go | 2 - .../compile/internal/reflectdata/reflect.go | 4 +- src/cmd/compile/internal/typecheck/expr.go | 15 +++++++- src/cmd/compile/internal/typecheck/func.go | 19 +++++++++- src/cmd/compile/internal/typecheck/iexport.go | 21 ++-------- src/cmd/compile/internal/types/type.go | 18 ++++++++- test/typeparam/orderedmapsimp.dir/a.go | 38 +++++++++---------- test/typeparam/orderedmapsimp.dir/main.go | 33 ++++++++-------- 10 files changed, 103 insertions(+), 69 deletions(-) diff --git a/src/cmd/compile/internal/gc/export.go b/src/cmd/compile/internal/gc/export.go index e19d52fa95..a11e5fdd30 100644 --- a/src/cmd/compile/internal/gc/export.go +++ b/src/cmd/compile/internal/gc/export.go @@ -94,15 +94,14 @@ func (p *exporter) markObject(n ir.Node) { // markType recursively visits types reachable from t to identify // functions whose inline bodies may be needed. func (p *exporter) markType(t *types.Type) { - if p.marked[t] { + if t.IsInstantiatedGeneric() { + // Re-instantiated types don't add anything new, so don't follow them. return } - p.marked[t] = true - if t.HasTParam() { - // Don't deal with any generic types or their methods, since we - // will only be inlining actual instantiations, not generic methods. + if p.marked[t] { return } + p.marked[t] = true // If this is a named type, mark all of its associated // methods. Skip interface types because t.Methods contains @@ -159,5 +158,8 @@ func (p *exporter) markType(t *types.Type) { p.markType(f.Type) } } + + case types.TTYPEPARAM: + // No other type that needs to be followed. } } diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go index 375eb41898..5c80b20671 100644 --- a/src/cmd/compile/internal/noder/decl.go +++ b/src/cmd/compile/internal/noder/decl.go @@ -109,6 +109,16 @@ func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) { } g.funcBody(fn, decl.Recv, decl.Type, decl.Body) + if fn.Type().HasTParam() && fn.Body != nil { + // Set pointers to the dcls/body of a generic function/method in + // the Inl struct, so it is marked for export, is available for + // stenciling, and works with Inline_Flood(). + fn.Inl = &ir.Inline{ + Cost: 1, + Dcl: fn.Dcl, + Body: fn.Body, + } + } out.Append(fn) } diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 3ba364f67c..8145f9e8f9 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -17,8 +17,6 @@ import ( "go/constant" ) -// For catching problems as we add more features -// TODO(danscales): remove assertions or replace with base.FatalfAt() func assert(p bool) { if !p { panic("assertion failed") diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 604cec6096..0fcb7e3d6d 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -949,7 +949,7 @@ func writeType(t *types.Type) *obj.LSym { // in the local package, even if they may be marked as part of // another package (the package of their base generic type). if tbase.Sym() != nil && tbase.Sym().Pkg != types.LocalPkg && - !tbase.IsInstantiated() { + !tbase.IsFullyInstantiated() { if i := typecheck.BaseTypeIndex(t); i >= 0 { lsym.Pkg = tbase.Sym().Pkg.Prefix lsym.SymIdx = int32(i) @@ -1795,7 +1795,7 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy // instantiated methods. if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type && rcvr.Elem().Sym() != nil && rcvr.Elem().Sym().Pkg != types.LocalPkg && - !rcvr.Elem().IsInstantiated() { + !rcvr.Elem().IsFullyInstantiated() { return lsym } diff --git a/src/cmd/compile/internal/typecheck/expr.go b/src/cmd/compile/internal/typecheck/expr.go index 24d141e8a2..30d864320f 100644 --- a/src/cmd/compile/internal/typecheck/expr.go +++ b/src/cmd/compile/internal/typecheck/expr.go @@ -311,8 +311,19 @@ func tcCompLit(n *ir.CompLitExpr) (res ir.Node) { f := t.Field(i) s := f.Sym - if s != nil && !types.IsExported(s.Name) && s.Pkg != types.LocalPkg { - base.Errorf("implicit assignment of unexported field '%s' in %v literal", s.Name, t) + + // Do the test for assigning to unexported fields. + // But if this is an instantiated function, then + // the function has already been typechecked. In + // that case, don't do the test, since it can fail + // for the closure structs created in + // walkClosure(), because the instantiated + // function is compiled as if in the source + // package of the generic function. + if !(ir.CurFunc != nil && strings.Index(ir.CurFunc.Nname.Sym().Name, "[") >= 0) { + if s != nil && !types.IsExported(s.Name) && s.Pkg != types.LocalPkg { + base.Errorf("implicit assignment of unexported field '%s' in %v literal", s.Name, t) + } } // No pushtype allowed here. Must name fields for that. n1 = AssignConv(n1, f.Type, "field value") diff --git a/src/cmd/compile/internal/typecheck/func.go b/src/cmd/compile/internal/typecheck/func.go index 760b8868ab..f9ee686f9e 100644 --- a/src/cmd/compile/internal/typecheck/func.go +++ b/src/cmd/compile/internal/typecheck/func.go @@ -74,8 +74,25 @@ func ClosureType(clo *ir.ClosureExpr) *types.Type { // The information appears in the binary in the form of type descriptors; // the struct is unnamed so that closures in multiple packages with the // same struct type can share the descriptor. + + // Make sure the .F field is in the same package as the rest of the + // fields. This deals with closures in instantiated functions, which are + // compiled as if from the source package of the generic function. + var pkg *types.Pkg + if len(clo.Func.ClosureVars) == 0 { + pkg = types.LocalPkg + } else { + for _, v := range clo.Func.ClosureVars { + if pkg == nil { + pkg = v.Sym().Pkg + } else if pkg != v.Sym().Pkg { + base.Fatalf("Closure variables from multiple packages") + } + } + } + fields := []*types.Field{ - types.NewField(base.Pos, Lookup(".F"), types.Types[types.TUINTPTR]), + types.NewField(base.Pos, pkg.Lookup(".F"), types.Types[types.TUINTPTR]), } for _, v := range clo.Func.ClosureVars { typ := v.Type() diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index f635b79ada..236f6ed789 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -1332,24 +1332,9 @@ func (w *exportWriter) funcExt(n *ir.Name) { } } - // Inline body. - if n.Type().HasTParam() { - if n.Func.Inl != nil { - // n.Func.Inl may already be set on a generic function if - // we imported it from another package, but shouldn't be - // set for a generic function in the local package. - if n.Sym().Pkg == types.LocalPkg { - base.FatalfAt(n.Pos(), "generic function is marked inlineable") - } - } else { - // Populate n.Func.Inl, so body of exported generic function will - // be written out. - n.Func.Inl = &ir.Inline{ - Cost: 1, - Dcl: n.Func.Dcl, - Body: n.Func.Body, - } - } + // Write out inline body or body of a generic function/method. + if n.Type().HasTParam() && n.Func.Body != nil && n.Func.Inl == nil { + base.FatalfAt(n.Pos(), "generic function is not marked inlineable") } if n.Func.Inl != nil { w.uint64(1 + uint64(n.Func.Inl.Cost)) diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 7a05230a78..a3a6050c52 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -8,6 +8,7 @@ import ( "cmd/compile/internal/base" "cmd/internal/src" "fmt" + "strings" "sync" ) @@ -279,10 +280,23 @@ func (t *Type) SetRParams(rparams []*Type) { } } -// IsInstantiated reports whether t is a fully instantiated generic type; i.e. an +// IsBaseGeneric returns true if t is a generic type (not reinstantiated with +// another type params or fully instantiated. +func (t *Type) IsBaseGeneric() bool { + return len(t.RParams()) > 0 && strings.Index(t.Sym().Name, "[") < 0 +} + +// IsInstantiatedGeneric returns t if t ia generic type that has been +// reinstantiated with new typeparams (i.e. is not fully instantiated). +func (t *Type) IsInstantiatedGeneric() bool { + return len(t.RParams()) > 0 && strings.Index(t.Sym().Name, "[") >= 0 && + t.HasTParam() +} + +// IsFullyInstantiated reports whether t is a fully instantiated generic type; i.e. an // instantiated generic type where all type arguments are non-generic or fully // instantiated generic types. -func (t *Type) IsInstantiated() bool { +func (t *Type) IsFullyInstantiated() bool { return len(t.RParams()) > 0 && !t.HasTParam() } diff --git a/test/typeparam/orderedmapsimp.dir/a.go b/test/typeparam/orderedmapsimp.dir/a.go index 1b5827b4bb..37fc3e79b9 100644 --- a/test/typeparam/orderedmapsimp.dir/a.go +++ b/test/typeparam/orderedmapsimp.dir/a.go @@ -100,25 +100,25 @@ type keyValue[K, V any] struct { } // iterate returns an iterator that traverses the map. -// func (m *Map[K, V]) Iterate() *Iterator[K, V] { -// sender, receiver := Ranger[keyValue[K, V]]() -// var f func(*node[K, V]) bool -// f = func(n *node[K, V]) bool { -// if n == nil { -// return true -// } -// // Stop the traversal if Send fails, which means that -// // nothing is listening to the receiver. -// return f(n.left) && -// sender.Send(context.Background(), keyValue[K, V]{n.key, n.val}) && -// f(n.right) -// } -// go func() { -// f(m.root) -// sender.Close() -// }() -// return &Iterator[K, V]{receiver} -// } +func (m *Map[K, V]) Iterate() *Iterator[K, V] { + sender, receiver := Ranger[keyValue[K, V]]() + var f func(*node[K, V]) bool + f = func(n *node[K, V]) bool { + if n == nil { + return true + } + // Stop the traversal if Send fails, which means that + // nothing is listening to the receiver. + return f(n.left) && + sender.Send(context.Background(), keyValue[K, V]{n.key, n.val}) && + f(n.right) + } + go func() { + f(m.root) + sender.Close() + }() + return &Iterator[K, V]{receiver} +} // Iterator is used to iterate over the map. type Iterator[K, V any] struct { diff --git a/test/typeparam/orderedmapsimp.dir/main.go b/test/typeparam/orderedmapsimp.dir/main.go index 77869ad9fc..ac4cee6a78 100644 --- a/test/typeparam/orderedmapsimp.dir/main.go +++ b/test/typeparam/orderedmapsimp.dir/main.go @@ -41,24 +41,21 @@ func TestMap() { panic(fmt.Sprintf("unexpectedly found %q", []byte("d"))) } - // TODO(danscales): Iterate() has some things to be fixed with inlining in - // stenciled functions and using closures across packages. - - // gather := func(it *a.Iterator[[]byte, int]) []int { - // var r []int - // for { - // _, v, ok := it.Next() - // if !ok { - // return r - // } - // r = append(r, v) - // } - // } - // got := gather(m.Iterate()) - // want := []int{'a', 'b', 'x'} - // if !a.SliceEqual(got, want) { - // panic(fmt.Sprintf("Iterate returned %v, want %v", got, want)) - // } + gather := func(it *a.Iterator[[]byte, int]) []int { + var r []int + for { + _, v, ok := it.Next() + if !ok { + return r + } + r = append(r, v) + } + } + got := gather(m.Iterate()) + want := []int{'a', 'b', 'x'} + if !a.SliceEqual(got, want) { + panic(fmt.Sprintf("Iterate returned %v, want %v", got, want)) + } } -- GitLab From bad388744b57cb49f364971e21d6a2300545f0fb Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 3 Jun 2021 15:39:23 -0700 Subject: [PATCH 0224/2500] [dev.typeparams] cmd/compile: handle dictionaries for top-level instantiations There's no outer function in these cases, so we won't be reading the dictionary as a subdictionary from the outer scope's dictionary. It will always be a compile-time constant. Change-Id: I754b126652a6ffb62255734d53fcec29d77cfa9e Reviewed-on: https://go-review.googlesource.com/c/go/+/324949 Trust: Keith Randall Trust: Dan Scales Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 68 ++++++++++++++++------- test/typeparam/dictionaryCapture.go | 28 ++++++++++ 2 files changed, 77 insertions(+), 19 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 8145f9e8f9..25a4bf775f 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -144,13 +144,19 @@ func (g *irgen) stencil() { // call. if closureRequired { var edit func(ir.Node) ir.Node + var outer *ir.Func + if f, ok := decl.(*ir.Func); ok { + outer = f + } edit = func(x ir.Node) ir.Node { ir.EditChildren(x, edit) switch { case x.Op() == ir.OFUNCINST: - return g.buildClosure(decl.(*ir.Func), x) + // TODO: only set outer!=nil if this instantiation uses + // a type parameter from outer. See comment in buildClosure. + return g.buildClosure(outer, x) case x.Op() == ir.OMETHEXPR && len(deref(x.(*ir.SelectorExpr).X.Type()).RParams()) > 0: // TODO: test for ptr-to-method case - return g.buildClosure(decl.(*ir.Func), x) + return g.buildClosure(outer, x) } return x } @@ -170,7 +176,8 @@ func (g *irgen) stencil() { } // buildClosure makes a closure to implement x, a OFUNCINST or OMETHEXPR -// of generic type. outer is the containing function. +// of generic type. outer is the containing function (or nil if closure is +// in a global assignment instead of a function). func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { pos := x.Pos() var target *ir.Func // target instantiated function/method @@ -276,19 +283,25 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { fn.SetIsHiddenClosure(true) // This is the dictionary we want to use. - // Note: for now this is a compile-time constant, so we don't really need a closure - // to capture it (a wrapper function would work just as well). But eventually it - // will be a read of a subdictionary from the parent dictionary. - dictVar := ir.NewNameAt(pos, typecheck.LookupNum(".dict", g.dnum)) - g.dnum++ - dictVar.Class = ir.PAUTO - typed(types.Types[types.TUINTPTR], dictVar) - dictVar.Curfn = outer - dictAssign := ir.NewAssignStmt(pos, dictVar, dictValue) - dictAssign.SetTypecheck(1) - dictVar.Defn = dictAssign - outer.Dcl = append(outer.Dcl, dictVar) - + // It may be a constant, or it may be a dictionary acquired from the outer function's dictionary. + // For the latter, dictVar is a variable in the outer function's scope, set to the subdictionary + // read from the outer function's dictionary. + var dictVar *ir.Name + var dictAssign *ir.AssignStmt + if outer != nil { + // Note: for now this is a compile-time constant, so we don't really need a closure + // to capture it (a wrapper function would work just as well). But eventually it + // will be a read of a subdictionary from the parent dictionary. + dictVar = ir.NewNameAt(pos, typecheck.LookupNum(".dict", g.dnum)) + g.dnum++ + dictVar.Class = ir.PAUTO + typed(types.Types[types.TUINTPTR], dictVar) + dictVar.Curfn = outer + dictAssign = ir.NewAssignStmt(pos, dictVar, dictValue) + dictAssign.SetTypecheck(1) + dictVar.Defn = dictAssign + outer.Dcl = append(outer.Dcl, dictVar) + } // assign the receiver to a temporary. var rcvrVar *ir.Name var rcvrAssign ir.Node @@ -335,6 +348,7 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { sym := typecheck.ClosureName(outer) sym.SetFunc(true) fn.Nname = ir.NewNameAt(pos, sym) + fn.Nname.Class = ir.PFUNC fn.Nname.Func = fn fn.Nname.Defn = fn typed(closureType, fn.Nname) @@ -343,8 +357,18 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { // Build body of closure. This involves just calling the wrapped function directly // with the additional dictionary argument. - // First, capture the dictionary variable for use in the closure. - dict2Var := ir.CaptureName(pos, fn, dictVar) + // First, figure out the dictionary argument. + var dict2Var ir.Node + if outer != nil { + // If there's an outer function, the dictionary value will be read from + // the dictionary of the outer function. + // TODO: only use a subdictionary if any of the instantiating types + // depend on the type params of the outer function. + dict2Var = ir.CaptureName(pos, fn, dictVar) + } else { + // No outer function, instantiating types are known concrete types. + dict2Var = dictValue + } // Also capture the receiver variable. var rcvr2Var *ir.Name if rcvrValue != nil { @@ -376,13 +400,19 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { typecheck.Stmt(innerCall) ir.CurFunc = nil fn.Body = []ir.Node{innerCall} + if outer == nil { + g.target.Decls = append(g.target.Decls, fn) + } // We're all done with the captured dictionary (and receiver, for method values). ir.FinishCaptureNames(pos, outer, fn) // Make a closure referencing our new internal function. c := ir.NewClosureExpr(pos, fn) - init := []ir.Node{dictAssign} + var init []ir.Node + if outer != nil { + init = append(init, dictAssign) + } if rcvrValue != nil { init = append(init, rcvrAssign) } diff --git a/test/typeparam/dictionaryCapture.go b/test/typeparam/dictionaryCapture.go index 9ce7c540ca..bb35df5309 100644 --- a/test/typeparam/dictionaryCapture.go +++ b/test/typeparam/dictionaryCapture.go @@ -17,6 +17,7 @@ func main() { methodExpressions() methodValues() interfaceMethods() + globals() } func g0[T any](x T) { @@ -98,3 +99,30 @@ func interfaceMethods() { is7(y.(interface{g1()int}).g1()) is77(y.(interface{g2()(int,int)}).g2()) } + +// Also check for instantiations outside functions. +var gg0 = g0[int] +var gg1 = g1[int] +var gg2 = g2[int] + +var hh0 = s[int].g0 +var hh1 = s[int].g1 +var hh2 = s[int].g2 + +var xtop = s[int]{a:7} +var ii0 = x.g0 +var ii1 = x.g1 +var ii2 = x.g2 + +func globals() { + gg0(7) + is7(gg1(7)) + is77(gg2(7)) + x := s[int]{a:7} + hh0(x) + is7(hh1(x)) + is77(hh2(x)) + ii0() + is7(ii1()) + is77(ii2()) +} -- GitLab From a94e4f5a8590e7c8d3aa058fb592561d870285a9 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 4 Jun 2021 00:01:22 -0700 Subject: [PATCH 0225/2500] [dev.typeparams] cmd/compile: point StructKeyExpr at the types.Field When constructing struct literals, importers need a way to specify precisely which field to initialize without worrying about visibility or those fields being blank. (A blank field doesn't actually need to be initialized, but the expression needs to be evaluated still, and with the right order-of-operations.) This CL changes StructKeyExpr's Field field to point directly to the corresponding types.Field, rather than merely holding a copy of its Sym and Offset. This is akin to past changes to add SelectorExpr.Selection. Change-Id: I95b72b1788f73206fcebc22b456cf6b1186db6a7 Reviewed-on: https://go-review.googlesource.com/c/go/+/325031 Trust: Matthew Dempsky Reviewed-by: Cuong Manh Le Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot --- src/cmd/compile/internal/ir/expr.go | 10 +- src/cmd/compile/internal/noder/expr.go | 6 +- src/cmd/compile/internal/noder/transform.go | 43 +++--- src/cmd/compile/internal/staticinit/sched.go | 4 +- src/cmd/compile/internal/typecheck/expr.go | 140 +++++++++--------- src/cmd/compile/internal/typecheck/iexport.go | 5 +- src/cmd/compile/internal/typecheck/iimport.go | 6 +- src/cmd/compile/internal/walk/closure.go | 3 + src/cmd/compile/internal/walk/complit.go | 4 +- 9 files changed, 108 insertions(+), 113 deletions(-) diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 856b255657..bcc0e412d5 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -324,20 +324,18 @@ func NewKeyExpr(pos src.XPos, key, value Node) *KeyExpr { // A StructKeyExpr is an Field: Value composite literal key. type StructKeyExpr struct { miniExpr - Field *types.Sym - Value Node - Offset int64 + Field *types.Field + Value Node } -func NewStructKeyExpr(pos src.XPos, field *types.Sym, value Node) *StructKeyExpr { +func NewStructKeyExpr(pos src.XPos, field *types.Field, value Node) *StructKeyExpr { n := &StructKeyExpr{Field: field, Value: value} n.pos = pos n.op = OSTRUCTKEY - n.Offset = types.BADWIDTH return n } -func (n *StructKeyExpr) Sym() *types.Sym { return n.Field } +func (n *StructKeyExpr) Sym() *types.Sym { return n.Field.Sym } // An InlinedCallExpr is an inlined function call. type InlinedCallExpr struct { diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index c901dc5534..d6c75845ce 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -355,11 +355,13 @@ func (g *irgen) compLit(typ types2.Type, lit *syntax.CompositeLit) ir.Node { for i, elem := range lit.ElemList { switch elem := elem.(type) { case *syntax.KeyValueExpr: + var key ir.Node if isStruct { - exprs[i] = ir.NewStructKeyExpr(g.pos(elem), g.name(elem.Key.(*syntax.Name)), g.expr(elem.Value)) + key = ir.NewIdent(g.pos(elem.Key), g.name(elem.Key.(*syntax.Name))) } else { - exprs[i] = ir.NewKeyExpr(g.pos(elem), g.expr(elem.Key), g.expr(elem.Value)) + key = g.expr(elem.Key) } + exprs[i] = ir.NewKeyExpr(g.pos(elem), key, g.expr(elem.Value)) default: exprs[i] = g.expr(elem) } diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index 90d38fe514..a084f0b7be 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -937,9 +937,7 @@ func transformCompLit(n *ir.CompLitExpr) (res ir.Node) { f := t.Field(i) n1 = assignconvfn(n1, f.Type) - sk := ir.NewStructKeyExpr(base.Pos, f.Sym, n1) - sk.Offset = f.Offset - ls[i] = sk + ls[i] = ir.NewStructKeyExpr(base.Pos, f, n1) } assert(len(ls) >= t.NumFields()) } else { @@ -948,33 +946,26 @@ func transformCompLit(n *ir.CompLitExpr) (res ir.Node) { for i, l := range ls { ir.SetPos(l) - if l.Op() == ir.OKEY { - kv := l.(*ir.KeyExpr) - key := kv.Key + kv := l.(*ir.KeyExpr) + key := kv.Key - // Sym might have resolved to name in other top-level - // package, because of import dot. Redirect to correct sym - // before we do the lookup. - s := key.Sym() - if id, ok := key.(*ir.Ident); ok && typecheck.DotImportRefs[id] != nil { - s = typecheck.Lookup(s.Name) - } - - // An OXDOT uses the Sym field to hold - // the field to the right of the dot, - // so s will be non-nil, but an OXDOT - // is never a valid struct literal key. - assert(!(s == nil || s.Pkg != types.LocalPkg || key.Op() == ir.OXDOT || s.IsBlank())) - - l = ir.NewStructKeyExpr(l.Pos(), s, kv.Value) - ls[i] = l + // Sym might have resolved to name in other top-level + // package, because of import dot. Redirect to correct sym + // before we do the lookup. + s := key.Sym() + if id, ok := key.(*ir.Ident); ok && typecheck.DotImportRefs[id] != nil { + s = typecheck.Lookup(s.Name) } - assert(l.Op() == ir.OSTRUCTKEY) - l := l.(*ir.StructKeyExpr) + // An OXDOT uses the Sym field to hold + // the field to the right of the dot, + // so s will be non-nil, but an OXDOT + // is never a valid struct literal key. + assert(!(s == nil || s.Pkg != types.LocalPkg || key.Op() == ir.OXDOT || s.IsBlank())) - f := typecheck.Lookdot1(nil, l.Field, t, t.Fields(), 0) - l.Offset = f.Offset + f := typecheck.Lookdot1(nil, s, t, t.Fields(), 0) + l := ir.NewStructKeyExpr(l.Pos(), f, kv.Value) + ls[i] = l l.Value = assignconvfn(l.Value, f.Type) } diff --git a/src/cmd/compile/internal/staticinit/sched.go b/src/cmd/compile/internal/staticinit/sched.go index 0c97b6de74..9329a46989 100644 --- a/src/cmd/compile/internal/staticinit/sched.go +++ b/src/cmd/compile/internal/staticinit/sched.go @@ -403,10 +403,10 @@ func (s *Schedule) initplan(n ir.Node) { base.Fatalf("initplan structlit") } a := a.(*ir.StructKeyExpr) - if a.Field.IsBlank() { + if a.Sym().IsBlank() { continue } - s.addvalue(p, a.Offset, a.Value) + s.addvalue(p, a.Field.Offset, a.Value) } case ir.OMAPLIT: diff --git a/src/cmd/compile/internal/typecheck/expr.go b/src/cmd/compile/internal/typecheck/expr.go index 30d864320f..d52f011072 100644 --- a/src/cmd/compile/internal/typecheck/expr.go +++ b/src/cmd/compile/internal/typecheck/expr.go @@ -327,9 +327,7 @@ func tcCompLit(n *ir.CompLitExpr) (res ir.Node) { } // No pushtype allowed here. Must name fields for that. n1 = AssignConv(n1, f.Type, "field value") - sk := ir.NewStructKeyExpr(base.Pos, f.Sym, n1) - sk.Offset = f.Offset - ls[i] = sk + ls[i] = ir.NewStructKeyExpr(base.Pos, f, n1) } if len(ls) < t.NumFields() { base.Errorf("too few values in %v", n) @@ -339,77 +337,33 @@ func tcCompLit(n *ir.CompLitExpr) (res ir.Node) { // keyed list ls := n.List - for i, l := range ls { - ir.SetPos(l) - - if l.Op() == ir.OKEY { - kv := l.(*ir.KeyExpr) - key := kv.Key - - // Sym might have resolved to name in other top-level - // package, because of import dot. Redirect to correct sym - // before we do the lookup. - s := key.Sym() - if id, ok := key.(*ir.Ident); ok && DotImportRefs[id] != nil { - s = Lookup(s.Name) - } - - // An OXDOT uses the Sym field to hold - // the field to the right of the dot, - // so s will be non-nil, but an OXDOT - // is never a valid struct literal key. - if s == nil || s.Pkg != types.LocalPkg || key.Op() == ir.OXDOT || s.IsBlank() { - base.Errorf("invalid field name %v in struct initializer", key) - continue - } - - l = ir.NewStructKeyExpr(l.Pos(), s, kv.Value) - ls[i] = l - } - - if l.Op() != ir.OSTRUCTKEY { - if !errored { - base.Errorf("mixture of field:value and value initializers") - errored = true - } - ls[i] = Expr(ls[i]) - continue - } - l := l.(*ir.StructKeyExpr) - - f := Lookdot1(nil, l.Field, t, t.Fields(), 0) - if f == nil { - if ci := Lookdot1(nil, l.Field, t, t.Fields(), 2); ci != nil { // Case-insensitive lookup. - if visible(ci.Sym) { - base.Errorf("unknown field '%v' in struct literal of type %v (but does have %v)", l.Field, t, ci.Sym) - } else if nonexported(l.Field) && l.Field.Name == ci.Sym.Name { // Ensure exactness before the suggestion. - base.Errorf("cannot refer to unexported field '%v' in struct literal of type %v", l.Field, t) - } else { - base.Errorf("unknown field '%v' in struct literal of type %v", l.Field, t) + for i, n := range ls { + ir.SetPos(n) + + sk, ok := n.(*ir.StructKeyExpr) + if !ok { + kv, ok := n.(*ir.KeyExpr) + if !ok { + if !errored { + base.Errorf("mixture of field:value and value initializers") + errored = true } + ls[i] = Expr(n) continue } - var f *types.Field - p, _ := dotpath(l.Field, t, &f, true) - if p == nil || f.IsMethod() { - base.Errorf("unknown field '%v' in struct literal of type %v", l.Field, t) + + sk = tcStructLitKey(t, kv) + if sk == nil { continue } - // dotpath returns the parent embedded types in reverse order. - var ep []string - for ei := len(p) - 1; ei >= 0; ei-- { - ep = append(ep, p[ei].field.Sym.Name) - } - ep = append(ep, l.Field.Name) - base.Errorf("cannot use promoted field %v in struct literal of type %v", strings.Join(ep, "."), t) - continue + + fielddup(sk.Sym().Name, hash) } - fielddup(f.Sym.Name, hash) - l.Offset = f.Offset // No pushtype allowed here. Tried and rejected. - l.Value = Expr(l.Value) - l.Value = AssignConv(l.Value, f.Type, "field value") + sk.Value = Expr(sk.Value) + sk.Value = AssignConv(sk.Value, sk.Field.Type, "field value") + ls[i] = sk } } @@ -420,6 +374,60 @@ func tcCompLit(n *ir.CompLitExpr) (res ir.Node) { return n } +// tcStructLitKey typechecks an OKEY node that appeared within a +// struct literal. +func tcStructLitKey(typ *types.Type, kv *ir.KeyExpr) *ir.StructKeyExpr { + key := kv.Key + + // Sym might have resolved to name in other top-level + // package, because of import dot. Redirect to correct sym + // before we do the lookup. + sym := key.Sym() + if id, ok := key.(*ir.Ident); ok && DotImportRefs[id] != nil { + sym = Lookup(sym.Name) + } + + // An OXDOT uses the Sym field to hold + // the field to the right of the dot, + // so s will be non-nil, but an OXDOT + // is never a valid struct literal key. + if sym == nil || sym.Pkg != types.LocalPkg || key.Op() == ir.OXDOT || sym.IsBlank() { + base.Errorf("invalid field name %v in struct initializer", key) + return nil + } + + if f := Lookdot1(nil, sym, typ, typ.Fields(), 0); f != nil { + return ir.NewStructKeyExpr(kv.Pos(), f, kv.Value) + } + + if ci := Lookdot1(nil, sym, typ, typ.Fields(), 2); ci != nil { // Case-insensitive lookup. + if visible(ci.Sym) { + base.Errorf("unknown field '%v' in struct literal of type %v (but does have %v)", sym, typ, ci.Sym) + } else if nonexported(sym) && sym.Name == ci.Sym.Name { // Ensure exactness before the suggestion. + base.Errorf("cannot refer to unexported field '%v' in struct literal of type %v", sym, typ) + } else { + base.Errorf("unknown field '%v' in struct literal of type %v", sym, typ) + } + return nil + } + + var f *types.Field + p, _ := dotpath(sym, typ, &f, true) + if p == nil || f.IsMethod() { + base.Errorf("unknown field '%v' in struct literal of type %v", sym, typ) + return nil + } + + // dotpath returns the parent embedded types in reverse order. + var ep []string + for ei := len(p) - 1; ei >= 0; ei-- { + ep = append(ep, p[ei].field.Sym.Name) + } + ep = append(ep, sym.Name) + base.Errorf("cannot use promoted field %v in struct literal of type %v", strings.Join(ep, "."), typ) + return nil +} + // tcConv typechecks an OCONV node. func tcConv(n *ir.ConvExpr) ir.Node { types.CheckSize(n.Type()) // ensure width is calculated for backend diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 236f6ed789..3bfbea11c0 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -2062,11 +2062,8 @@ func (w *exportWriter) fieldList(list ir.Nodes) { for _, n := range list { n := n.(*ir.StructKeyExpr) w.pos(n.Pos()) - w.selector(n.Field) + w.exoticField(n.Field) w.expr(n.Value) - if go117ExportTypes { - w.uint64(uint64(n.Offset)) - } } } diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 9e6115cbf7..45a177951e 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1719,11 +1719,7 @@ func (r *importReader) op() ir.Op { func (r *importReader) fieldList() []ir.Node { list := make([]ir.Node, r.uint64()) for i := range list { - x := ir.NewStructKeyExpr(r.pos(), r.selector(), r.expr()) - if go117ExportTypes { - x.Offset = int64(r.uint64()) - } - list[i] = x + list[i] = ir.NewStructKeyExpr(r.pos(), r.exoticField(), r.expr()) } return list } diff --git a/src/cmd/compile/internal/walk/closure.go b/src/cmd/compile/internal/walk/closure.go index 2194e1c5b0..feda3c3b4f 100644 --- a/src/cmd/compile/internal/walk/closure.go +++ b/src/cmd/compile/internal/walk/closure.go @@ -122,6 +122,9 @@ func walkClosure(clo *ir.ClosureExpr, init *ir.Nodes) ir.Node { clos := ir.NewCompLitExpr(base.Pos, ir.OCOMPLIT, ir.TypeNode(typ), nil) clos.SetEsc(clo.Esc()) clos.List = append([]ir.Node{ir.NewUnaryExpr(base.Pos, ir.OCFUNC, clofn.Nname)}, closureArgs(clo)...) + for i, value := range clos.List { + clos.List[i] = ir.NewStructKeyExpr(base.Pos, typ.Field(i), value) + } addr := typecheck.NodAddr(clos) addr.SetEsc(clo.Esc()) diff --git a/src/cmd/compile/internal/walk/complit.go b/src/cmd/compile/internal/walk/complit.go index abd920d646..6c6b4982a0 100644 --- a/src/cmd/compile/internal/walk/complit.go +++ b/src/cmd/compile/internal/walk/complit.go @@ -218,11 +218,11 @@ func fixedlit(ctxt initContext, kind initKind, n *ir.CompLitExpr, var_ ir.Node, case ir.OSTRUCTLIT: splitnode = func(rn ir.Node) (ir.Node, ir.Node) { r := rn.(*ir.StructKeyExpr) - if r.Field.IsBlank() || isBlank { + if r.Sym().IsBlank() || isBlank { return ir.BlankNode, r.Value } ir.SetPos(r) - return ir.NewSelectorExpr(base.Pos, ir.ODOT, var_, r.Field), r.Value + return ir.NewSelectorExpr(base.Pos, ir.ODOT, var_, r.Sym()), r.Value } default: base.Fatalf("fixedlit bad op: %v", n.Op()) -- GitLab From 692399fbaa09578314f8583e49505c6784e8d335 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 3 Jun 2021 20:53:08 -0700 Subject: [PATCH 0226/2500] [dev.typeparams] cmd/compile/internal/syntax: not all index expressions can be instantiated types An index expression followed by an opening "{" may indicate a composite literal but only if the index expression can be a type. Exclude cases where the index expression cannot be a type (e.g. s[0], a[i+j], etc.). This leads to a better error message in code that is erroneous. Fixes #46558. Change-Id: Ida9291ca30683c211812dfb95abe4969f44c474f Reviewed-on: https://go-review.googlesource.com/c/go/+/325009 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/syntax/parser.go | 17 ++++++++++++++++- .../internal/syntax/testdata/issue46558.src | 14 ++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 src/cmd/compile/internal/syntax/testdata/issue46558.src diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index 0e711a0113..503dea7fae 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -1100,7 +1100,7 @@ loop: complit_ok = true } case *IndexExpr: - if p.xnest >= 0 { + if p.xnest >= 0 && !isValue(t) { // x is possibly a composite literal type complit_ok = true } @@ -1127,6 +1127,21 @@ loop: return x } +// isValue reports whether x syntactically must be a value (and not a type) expression. +func isValue(x Expr) bool { + switch x := x.(type) { + case *BasicLit, *CompositeLit, *FuncLit, *SliceExpr, *AssertExpr, *TypeSwitchGuard, *CallExpr: + return true + case *Operation: + return x.Op != Mul || x.Y != nil // *T may be a type + case *ParenExpr: + return isValue(x.X) + case *IndexExpr: + return isValue(x.X) || isValue(x.Index) + } + return false +} + // Element = Expression | LiteralValue . func (p *parser) bare_complitexpr() Expr { if trace { diff --git a/src/cmd/compile/internal/syntax/testdata/issue46558.src b/src/cmd/compile/internal/syntax/testdata/issue46558.src new file mode 100644 index 0000000000..a22b600825 --- /dev/null +++ b/src/cmd/compile/internal/syntax/testdata/issue46558.src @@ -0,0 +1,14 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func F(s string) { + switch s[0] { + case 'a': + case s[2] { // ERROR unexpected { + case 'b': + } + } +} // ERROR non-declaration statement -- GitLab From 246a5570bea7b60fa2c1f0e8d4bdca527dd7c224 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 3 Jun 2021 21:58:32 -0700 Subject: [PATCH 0227/2500] [dev.typeparams] cmd/compile: rename (types2.Inferred.)Targs to TArgs This is consistent with Named.TArgs. This is a straight-forward port of https://golang.org/cl/321289 plus the necessary compiler noder changes. Change-Id: I50791e5abe0d7f294293bed65cebc8dde8bf8c06 Reviewed-on: https://go-review.googlesource.com/c/go/+/325010 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/noder/expr.go | 12 ++++++------ src/cmd/compile/internal/types2/api.go | 2 +- src/cmd/compile/internal/types2/api_test.go | 2 +- src/cmd/compile/internal/types2/sanitize.go | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index d6c75845ce..7034a19b81 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -111,11 +111,11 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { // The key for the Inferred map is the CallExpr (if inferring // types required the function arguments) or the IndexExpr below // (if types could be inferred without the function arguments). - if inferred, ok := g.info.Inferred[expr]; ok && len(inferred.Targs) > 0 { + if inferred, ok := g.info.Inferred[expr]; ok && len(inferred.TArgs) > 0 { // This is the case where inferring types required the // types of the function arguments. - targs := make([]ir.Node, len(inferred.Targs)) - for i, targ := range inferred.Targs { + targs := make([]ir.Node, len(inferred.TArgs)) + for i, targ := range inferred.TArgs { targs[i] = ir.TypeNode(g.typ(targ)) } if fun.Op() == ir.OFUNCINST { @@ -137,12 +137,12 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { case *syntax.IndexExpr: var targs []ir.Node - if inferred, ok := g.info.Inferred[expr]; ok && len(inferred.Targs) > 0 { + if inferred, ok := g.info.Inferred[expr]; ok && len(inferred.TArgs) > 0 { // This is the partial type inference case where the types // can be inferred from other type arguments without using // the types of the function arguments. - targs = make([]ir.Node, len(inferred.Targs)) - for i, targ := range inferred.Targs { + targs = make([]ir.Node, len(inferred.TArgs)) + for i, targ := range inferred.TArgs { targs[i] = ir.TypeNode(g.typ(targ)) } } else if _, ok := expr.Index.(*syntax.ListExpr); ok { diff --git a/src/cmd/compile/internal/types2/api.go b/src/cmd/compile/internal/types2/api.go index 433250f02c..4f7f35e61b 100644 --- a/src/cmd/compile/internal/types2/api.go +++ b/src/cmd/compile/internal/types2/api.go @@ -361,7 +361,7 @@ func (tv TypeAndValue) HasOk() bool { // Inferred reports the inferred type arguments and signature // for a parameterized function call that uses type inference. type Inferred struct { - Targs []Type + TArgs []Type Sig *Signature } diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index 49d710067a..c7f3e490aa 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -514,7 +514,7 @@ func TestInferredInfo(t *testing.T) { panic(fmt.Sprintf("unexpected call expression type %T", call)) } if syntax.String(fun) == test.fun { - targs = inf.Targs + targs = inf.TArgs sig = inf.Sig break } diff --git a/src/cmd/compile/internal/types2/sanitize.go b/src/cmd/compile/internal/types2/sanitize.go index 4e654e074f..406b46e574 100644 --- a/src/cmd/compile/internal/types2/sanitize.go +++ b/src/cmd/compile/internal/types2/sanitize.go @@ -26,9 +26,9 @@ func sanitizeInfo(info *Info) { for e, inf := range info.Inferred { changed := false - for i, targ := range inf.Targs { + for i, targ := range inf.TArgs { if typ := s.typ(targ); typ != targ { - inf.Targs[i] = typ + inf.TArgs[i] = typ changed = true } } -- GitLab From 4e001a8d9eec1ec165b45a37e804c2cf42351bc5 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 3 Jun 2021 23:52:34 -0700 Subject: [PATCH 0228/2500] [dev.typeparams] runtime/race: make test compatible with types2 types2 correctly distinguishes variable assignment from use even within function literals. Whatever the outcome of #3059, the test cases in runtime/race need to be fixed to accomodate that. Change-Id: Ibe3547f07b681ff41225caabaf050872a48c98d1 Reviewed-on: https://go-review.googlesource.com/c/go/+/325030 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/runtime/race/output_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/runtime/race/output_test.go b/src/runtime/race/output_test.go index 99052071d0..63fcd847dc 100644 --- a/src/runtime/race/output_test.go +++ b/src/runtime/race/output_test.go @@ -148,7 +148,7 @@ exit status 66 package main func main() { done := make(chan bool) - x := 0 + x := 0; _ = x go func() { x = 42 done <- true @@ -162,7 +162,7 @@ func main() { package main func main() { done := make(chan bool) - x := 0 + x := 0; _ = x go func() { x = 42 done <- true @@ -178,7 +178,7 @@ func main() { package main func main() { done := make(chan bool) - x := 0 + x := 0; _ = x go func() { x = 42 done <- true -- GitLab From 4c072c94dc2ffedd29d51d04aba2e1a6f2afd93f Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 4 Jun 2021 10:26:40 -0700 Subject: [PATCH 0229/2500] [dev.typeparams] cmd/compile: refactor import reading This CL restructures the gcimports importer to mmap the export data into memory as a string, and then pass that same string to both the typecheck and types2 importers. This is primarily motivated by preparation for unified IR; but it should also improve performance (fewer string copies) and reduces divergance between the two importers. Passes toolstash -cmp. Change-Id: I397f720693e9e6360bfcb5acb12609ab339d251f Reviewed-on: https://go-review.googlesource.com/c/go/+/325210 Run-TryBot: Matthew Dempsky Trust: Matthew Dempsky Trust: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- .../{typecheck => base}/mapfile_mmap.go | 4 +- .../{typecheck => base}/mapfile_read.go | 4 +- .../compile/internal/importer/gcimporter.go | 2 +- src/cmd/compile/internal/importer/iimport.go | 34 ++- src/cmd/compile/internal/noder/decl.go | 12 +- src/cmd/compile/internal/noder/import.go | 231 +++++++++++------- src/cmd/compile/internal/typecheck/iimport.go | 39 +-- 7 files changed, 172 insertions(+), 154 deletions(-) rename src/cmd/compile/internal/{typecheck => base}/mapfile_mmap.go (93%) rename src/cmd/compile/internal/{typecheck => base}/mapfile_read.go (85%) diff --git a/src/cmd/compile/internal/typecheck/mapfile_mmap.go b/src/cmd/compile/internal/base/mapfile_mmap.go similarity index 93% rename from src/cmd/compile/internal/typecheck/mapfile_mmap.go rename to src/cmd/compile/internal/base/mapfile_mmap.go index 298b385bcb..c1616db8e9 100644 --- a/src/cmd/compile/internal/typecheck/mapfile_mmap.go +++ b/src/cmd/compile/internal/base/mapfile_mmap.go @@ -5,7 +5,7 @@ //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd // +build darwin dragonfly freebsd linux netbsd openbsd -package typecheck +package base import ( "os" @@ -19,7 +19,7 @@ import ( // mapFile returns length bytes from the file starting at the // specified offset as a string. -func mapFile(f *os.File, offset, length int64) (string, error) { +func MapFile(f *os.File, offset, length int64) (string, error) { // POSIX mmap: "The implementation may require that off is a // multiple of the page size." x := offset & int64(os.Getpagesize()-1) diff --git a/src/cmd/compile/internal/typecheck/mapfile_read.go b/src/cmd/compile/internal/base/mapfile_read.go similarity index 85% rename from src/cmd/compile/internal/typecheck/mapfile_read.go rename to src/cmd/compile/internal/base/mapfile_read.go index 9637ab97ab..01796a9bab 100644 --- a/src/cmd/compile/internal/typecheck/mapfile_read.go +++ b/src/cmd/compile/internal/base/mapfile_read.go @@ -5,14 +5,14 @@ //go:build !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd // +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd -package typecheck +package base import ( "io" "os" ) -func mapFile(f *os.File, offset, length int64) (string, error) { +func MapFile(f *os.File, offset, length int64) (string, error) { buf := make([]byte, length) _, err := io.ReadFull(io.NewSectionReader(f, offset, length), buf) if err != nil { diff --git a/src/cmd/compile/internal/importer/gcimporter.go b/src/cmd/compile/internal/importer/gcimporter.go index 6c5458fad1..ff40be65bb 100644 --- a/src/cmd/compile/internal/importer/gcimporter.go +++ b/src/cmd/compile/internal/importer/gcimporter.go @@ -155,7 +155,7 @@ func Import(packages map[string]*types2.Package, path, srcDir string, lookup fun // binary export format starts with a 'c', 'd', or 'v' // (from "version"). Select appropriate importer. if len(data) > 0 && data[0] == 'i' { - _, pkg, err = iImportData(packages, data[1:], id) + pkg, err = ImportData(packages, string(data[1:]), id) } else { err = fmt.Errorf("import %q: old binary export format no longer supported (recompile library)", path) } diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index fb39e93073..14e64891b8 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -8,7 +8,6 @@ package importer import ( - "bytes" "cmd/compile/internal/syntax" "cmd/compile/internal/types2" "encoding/binary" @@ -18,10 +17,11 @@ import ( "io" "math/big" "sort" + "strings" ) type intReader struct { - *bytes.Reader + *strings.Reader path string } @@ -82,7 +82,7 @@ const io_SeekCurrent = 1 // io.SeekCurrent (not defined in Go 1.4) // and returns the number of bytes consumed and a reference to the package. // If the export data version is not recognized or the format is otherwise // compromised, an error is returned. -func iImportData(imports map[string]*types2.Package, data []byte, path string) (_ int, pkg *types2.Package, err error) { +func ImportData(imports map[string]*types2.Package, data, path string) (pkg *types2.Package, err error) { const currentVersion = iexportVersionCurrent version := int64(-1) defer func() { @@ -95,7 +95,7 @@ func iImportData(imports map[string]*types2.Package, data []byte, path string) ( } }() - r := &intReader{bytes.NewReader(data), path} + r := &intReader{strings.NewReader(data), path} version = int64(r.uint64()) switch version { @@ -122,7 +122,6 @@ func iImportData(imports map[string]*types2.Package, data []byte, path string) ( version: int(version), stringData: stringData, - stringCache: make(map[uint64]string), pkgCache: make(map[uint64]*types2.Package), posBaseCache: make(map[uint64]*syntax.PosBase), @@ -196,8 +195,7 @@ func iImportData(imports map[string]*types2.Package, data []byte, path string) ( // package was imported completely and without errors localpkg.MarkComplete() - consumed, _ := r.Seek(0, io_SeekCurrent) - return int(consumed), localpkg, nil + return localpkg, nil } type iimporter struct { @@ -205,12 +203,11 @@ type iimporter struct { ipath string version int - stringData []byte - stringCache map[uint64]string + stringData string pkgCache map[uint64]*types2.Package posBaseCache map[uint64]*syntax.PosBase - declData []byte + declData string pkgIndex map[*types2.Package]map[string]uint64 typCache map[uint64]types2.Type tparamIndex map[ident]types2.Type @@ -233,24 +230,21 @@ func (p *iimporter) doDecl(pkg *types2.Package, name string) { // Reader.Reset is not available in Go 1.4. // Use bytes.NewReader for now. // r.declReader.Reset(p.declData[off:]) - r.declReader = *bytes.NewReader(p.declData[off:]) + r.declReader = *strings.NewReader(p.declData[off:]) r.obj(name) } func (p *iimporter) stringAt(off uint64) string { - if s, ok := p.stringCache[off]; ok { - return s - } + var x [binary.MaxVarintLen64]byte + n := copy(x[:], p.stringData[off:]) - slen, n := binary.Uvarint(p.stringData[off:]) + slen, n := binary.Uvarint(x[:n]) if n <= 0 { errorf("varint failed") } spos := off + uint64(n) - s := string(p.stringData[spos : spos+slen]) - p.stringCache[off] = s - return s + return p.stringData[spos : spos+slen] } func (p *iimporter) pkgAt(off uint64) *types2.Package { @@ -285,7 +279,7 @@ func (p *iimporter) typAt(off uint64, base *types2.Named) types2.Type { // Reader.Reset is not available in Go 1.4. // Use bytes.NewReader for now. // r.declReader.Reset(p.declData[off-predeclReserved:]) - r.declReader = *bytes.NewReader(p.declData[off-predeclReserved:]) + r.declReader = *strings.NewReader(p.declData[off-predeclReserved:]) t := r.doType(base) if base == nil || !isInterface(t) { @@ -296,7 +290,7 @@ func (p *iimporter) typAt(off uint64, base *types2.Named) types2.Type { type importReader struct { p *iimporter - declReader bytes.Reader + declReader strings.Reader currPkg *types2.Package prevPosBase *syntax.PosBase prevLine int64 diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go index 5c80b20671..96abbe66ae 100644 --- a/src/cmd/compile/internal/noder/decl.go +++ b/src/cmd/compile/internal/noder/decl.go @@ -41,21 +41,15 @@ func (g *irgen) decls(decls []syntax.Decl) []ir.Node { } func (g *irgen) importDecl(p *noder, decl *syntax.ImportDecl) { - // TODO(mdempsky): Merge with gcimports so we don't have to import - // packages twice. - g.pragmaFlags(decl.Pragma, 0) // Get the imported package's path, as resolved already by types2 // and gcimporter. This is the same path as would be computed by // parseImportPath. - path := pkgNameOf(g.info, decl).Imported().Path() - - ipkg := readImportFile(g.target, path) - if ipkg == ir.Pkgs.Unsafe { + switch pkgNameOf(g.info, decl).Imported().Path() { + case "unsafe": p.importedUnsafe = true - } - if ipkg.Path == "embed" { + case "embed": p.importedEmbed = true } } diff --git a/src/cmd/compile/internal/noder/import.go b/src/cmd/compile/internal/noder/import.go index 24d911ba38..8076b74650 100644 --- a/src/cmd/compile/internal/noder/import.go +++ b/src/cmd/compile/internal/noder/import.go @@ -8,7 +8,6 @@ import ( "errors" "fmt" "internal/buildcfg" - "io" "os" pathpkg "path" "runtime" @@ -46,13 +45,8 @@ func (m *gcimports) ImportFrom(path, srcDir string, mode types2.ImportMode) (*ty panic("mode must be 0") } - path, err := resolveImportPath(path) - if err != nil { - return nil, err - } - - lookup := func(path string) (io.ReadCloser, error) { return openPackage(path) } - return importer.Import(m.packages, path, srcDir, lookup) + _, pkg, err := readImportFile(path, typecheck.Target, m.packages) + return pkg, err } func isDriveLetter(b byte) bool { @@ -182,7 +176,12 @@ func importfile(decl *syntax.ImportDecl) *types.Pkg { return nil } - pkg := readImportFile(typecheck.Target, path) + pkg, _, err := readImportFile(path, typecheck.Target, nil) + if err != nil { + base.Errorf("%s", err) + return nil + } + if pkg != ir.Pkgs.Unsafe && pkg.Height >= myheight { myheight = pkg.Height + 1 } @@ -203,136 +202,184 @@ func parseImportPath(pathLit *syntax.BasicLit) (string, error) { return "", err } - return resolveImportPath(path) + return path, err } -func readImportFile(target *ir.Package, path string) *types.Pkg { - importpkg := types.NewPkg(path, "") - if importpkg.Direct { - return importpkg // already fully loaded +// readImportFile reads the import file for the given package path and +// returns its types.Pkg representation. If packages is non-nil, the +// types2.Package representation is also returned. +func readImportFile(path string, target *ir.Package, packages map[string]*types2.Package) (pkg1 *types.Pkg, pkg2 *types2.Package, err error) { + path, err = resolveImportPath(path) + if err != nil { + return } - importpkg.Direct = true - target.Imports = append(target.Imports, importpkg) if path == "unsafe" { - return importpkg // initialized with universe + pkg1, pkg2 = ir.Pkgs.Unsafe, types2.Unsafe + + // TODO(mdempsky): Investigate if this actually matters. Why would + // the linker or runtime care whether a package imported unsafe? + if !pkg1.Direct { + pkg1.Direct = true + target.Imports = append(target.Imports, pkg1) + } + + return + } + + pkg1 = types.NewPkg(path, "") + if packages != nil { + pkg2 = packages[path] + assert(pkg1.Direct == (pkg2 != nil && pkg2.Complete())) + } + + if pkg1.Direct { + return } + pkg1.Direct = true + target.Imports = append(target.Imports, pkg1) f, err := openPackage(path) if err != nil { - base.Errorf("could not import %q: %v", path, err) - base.ErrorExit() + return } - imp := bio.NewReader(f) - defer imp.Close() - file := f.Name() + defer f.Close() + + r, end, err := findExportData(f) + if err != nil { + return + } + + if base.Debug.Export != 0 { + fmt.Printf("importing %s (%s)\n", path, f.Name()) + } + + var c byte + switch c, err = r.ReadByte(); { + case err != nil: + return + + case c != 'i': + // Indexed format is distinguished by an 'i' byte, + // whereas previous export formats started with 'c', 'd', or 'v'. + err = fmt.Errorf("unexpected package format byte: %v", c) + return + } + + // Map string (and data) section into memory as a single large + // string. This reduces heap fragmentation and allows + // returning individual substrings very efficiently. + pos := r.Offset() + data, err := base.MapFile(r.File(), pos, end-pos) + if err != nil { + return + } + + typecheck.ReadImports(pkg1, data) + + if packages != nil { + pkg2, err = importer.ImportData(packages, data, path) + if err != nil { + return + } + } + + err = addFingerprint(path, f, end) + return +} + +// findExportData returns a *bio.Reader positioned at the start of the +// binary export data section, and a file offset for where to stop +// reading. +func findExportData(f *os.File) (r *bio.Reader, end int64, err error) { + r = bio.NewReader(f) // check object header - p, err := imp.ReadString('\n') + line, err := r.ReadString('\n') if err != nil { - base.Errorf("import %s: reading input: %v", file, err) - base.ErrorExit() + return } - if p == "!\n" { // package archive + if line == "!\n" { // package archive // package export block should be first - sz := archive.ReadHeader(imp.Reader, "__.PKGDEF") + sz := int64(archive.ReadHeader(r.Reader, "__.PKGDEF")) if sz <= 0 { - base.Errorf("import %s: not a package file", file) - base.ErrorExit() + err = errors.New("not a package file") + return + } + end = r.Offset() + sz + line, err = r.ReadString('\n') + if err != nil { + return } - p, err = imp.ReadString('\n') + } else { + // Not an archive; provide end of file instead. + // TODO(mdempsky): I don't think this happens anymore. + var fi os.FileInfo + fi, err = f.Stat() if err != nil { - base.Errorf("import %s: reading input: %v", file, err) - base.ErrorExit() + return } + end = fi.Size() } - if !strings.HasPrefix(p, "go object ") { - base.Errorf("import %s: not a go object file: %s", file, p) - base.ErrorExit() + if !strings.HasPrefix(line, "go object ") { + err = fmt.Errorf("not a go object file: %s", line) + return } - q := objabi.HeaderString() - if p != q { - base.Errorf("import %s: object is [%s] expected [%s]", file, p, q) - base.ErrorExit() + if expect := objabi.HeaderString(); line != expect { + err = fmt.Errorf("object is [%s] expected [%s]", line, expect) + return } // process header lines - for { - p, err = imp.ReadString('\n') + for !strings.HasPrefix(line, "$$") { + line, err = r.ReadString('\n') if err != nil { - base.Errorf("import %s: reading input: %v", file, err) - base.ErrorExit() - } - if p == "\n" { - break // header ends with blank line + return } } // Expect $$B\n to signal binary import format. - - // look for $$ - var c byte - for { - c, err = imp.ReadByte() - if err != nil { - break - } - if c == '$' { - c, err = imp.ReadByte() - if c == '$' || err != nil { - break - } - } + if line != "$$B\n" { + err = errors.New("old export format no longer supported (recompile library)") + return } - // get character after $$ - if err == nil { - c, _ = imp.ReadByte() - } + return +} +// addFingerprint reads the linker fingerprint included at the end of +// the exportdata. +func addFingerprint(path string, f *os.File, end int64) error { + const eom = "\n$$\n" var fingerprint goobj.FingerprintType - switch c { - case '\n': - base.Errorf("cannot import %s: old export format no longer supported (recompile library)", path) - return nil - - case 'B': - if base.Debug.Export != 0 { - fmt.Printf("importing %s (%s)\n", path, file) - } - imp.ReadByte() // skip \n after $$B - - c, err = imp.ReadByte() - if err != nil { - base.Errorf("import %s: reading input: %v", file, err) - base.ErrorExit() - } - // Indexed format is distinguished by an 'i' byte, - // whereas previous export formats started with 'c', 'd', or 'v'. - if c != 'i' { - base.Errorf("import %s: unexpected package format byte: %v", file, c) - base.ErrorExit() - } - fingerprint = typecheck.ReadImports(importpkg, imp) + var buf [len(fingerprint) + len(eom)]byte + if _, err := f.ReadAt(buf[:], end-int64(len(buf))); err != nil { + return err + } - default: - base.Errorf("no import in %q", path) - base.ErrorExit() + // Caller should have given us the end position of the export data, + // which should end with the "\n$$\n" marker. As a consistency check + // to make sure we're reading at the right offset, make sure we + // found the marker. + if s := string(buf[len(fingerprint):]); s != eom { + return fmt.Errorf("expected $$ marker, but found %q", s) } + copy(fingerprint[:], buf[:]) + // assume files move (get installed) so don't record the full path if base.Flag.Cfg.PackageFile != nil { // If using a packageFile map, assume path_ can be recorded directly. base.Ctxt.AddImport(path, fingerprint) } else { // For file "/Users/foo/go/pkg/darwin_amd64/math.a" record "math.a". + file := f.Name() base.Ctxt.AddImport(file[len(file)-len(path)-len(".a"):], fingerprint) } - - return importpkg + return nil } // The linker uses the magic symbol prefixes "go." and "type." diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 45a177951e..cafb18d7a8 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -12,7 +12,6 @@ import ( "encoding/binary" "fmt" "go/constant" - "io" "math/big" "os" "strings" @@ -20,8 +19,6 @@ import ( "cmd/compile/internal/base" "cmd/compile/internal/ir" "cmd/compile/internal/types" - "cmd/internal/bio" - "cmd/internal/goobj" "cmd/internal/obj" "cmd/internal/src" ) @@ -95,7 +92,7 @@ func importReaderFor(sym *types.Sym, importers map[*types.Sym]iimporterAndOffset } type intReader struct { - *bio.Reader + *strings.Reader pkg *types.Pkg } @@ -117,8 +114,8 @@ func (r *intReader) uint64() uint64 { return i } -func ReadImports(pkg *types.Pkg, in *bio.Reader) (fingerprint goobj.FingerprintType) { - ird := &intReader{in, pkg} +func ReadImports(pkg *types.Pkg, data string) { + ird := &intReader{strings.NewReader(data), pkg} version := ird.uint64() switch version { @@ -132,21 +129,15 @@ func ReadImports(pkg *types.Pkg, in *bio.Reader) (fingerprint goobj.FingerprintT base.ErrorExit() } - sLen := ird.uint64() - dLen := ird.uint64() + sLen := int64(ird.uint64()) + dLen := int64(ird.uint64()) - // Map string (and data) section into memory as a single large - // string. This reduces heap fragmentation and allows - // returning individual substrings very efficiently. - data, err := mapFile(in.File(), in.Offset(), int64(sLen+dLen)) - if err != nil { - base.Errorf("import %q: mapping input: %v", pkg.Path, err) - base.ErrorExit() - } - stringData := data[:sLen] - declData := data[sLen:] - - in.MustSeek(int64(sLen+dLen), os.SEEK_CUR) + // TODO(mdempsky): Replace os.SEEK_CUR with io.SeekCurrent after + // #44505 is fixed. + whence, _ := ird.Seek(0, os.SEEK_CUR) + stringData := data[whence : whence+sLen] + declData := data[whence+sLen : whence+sLen+dLen] + ird.Seek(sLen+dLen, os.SEEK_CUR) p := &iimporter{ exportVersion: version, @@ -208,14 +199,6 @@ func ReadImports(pkg *types.Pkg, in *bio.Reader) (fingerprint goobj.FingerprintT } } } - - // Fingerprint. - _, err = io.ReadFull(in, fingerprint[:]) - if err != nil { - base.Errorf("import %s: error reading fingerprint", pkg.Path) - base.ErrorExit() - } - return fingerprint } type iimporter struct { -- GitLab From a5be3eaee2cc0b8e5da216bdf545b9ca44789892 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 4 Jun 2021 13:14:32 -0700 Subject: [PATCH 0230/2500] [dev.typeparams] cmd/compile: refactor export writing This CL reorganizes export writing in preparation for unified IR: 1. It moves dumpexport into noder as noder.WriteExports so that it can be extended to include unified IR's export data. 2. Adds an "extensions" flag to typecheck.WriteExports to control whether the compiler-only extension data (e.g., function bodies and linker symbol info) is included in the exports. 3. It moves the gc.exporter type into typecheck and renames it to "crawler". The type originated as the implementation of the (pre-iexport) binary exporter, but since the removal of bexport it's been relegated to simply crawling the exported functions/bodies graph to identify which inline bodies need to be included. 4. It changes inline.Inline_Flood into the method crawler.markInlBody. Inline_Flood doesn't actually have anything to do with the rest of inlining; its current name and location are just historical quirks. Passes toolstash -cmp. Change-Id: I6445e2de9d3ce500a3aded5a8e20b09f46d23dbc Reviewed-on: https://go-review.googlesource.com/c/go/+/325212 Run-TryBot: Matthew Dempsky Trust: Matthew Dempsky Trust: Robert Griesemer Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/gc/export.go | 120 +------------ src/cmd/compile/internal/gc/obj.go | 3 +- src/cmd/compile/internal/inline/inl.go | 56 ------ src/cmd/compile/internal/noder/export.go | 26 +++ src/cmd/compile/internal/typecheck/crawler.go | 164 ++++++++++++++++++ src/cmd/compile/internal/typecheck/iexport.go | 38 +++- 6 files changed, 224 insertions(+), 183 deletions(-) create mode 100644 src/cmd/compile/internal/noder/export.go create mode 100644 src/cmd/compile/internal/typecheck/crawler.go diff --git a/src/cmd/compile/internal/gc/export.go b/src/cmd/compile/internal/gc/export.go index a11e5fdd30..9bf3c7240a 100644 --- a/src/cmd/compile/internal/gc/export.go +++ b/src/cmd/compile/internal/gc/export.go @@ -5,41 +5,16 @@ package gc import ( + "fmt" + "go/constant" + "cmd/compile/internal/base" - "cmd/compile/internal/inline" "cmd/compile/internal/ir" "cmd/compile/internal/typecheck" "cmd/compile/internal/types" "cmd/internal/bio" - "fmt" - "go/constant" ) -func exportf(bout *bio.Writer, format string, args ...interface{}) { - fmt.Fprintf(bout, format, args...) - if base.Debug.Export != 0 { - fmt.Printf(format, args...) - } -} - -func dumpexport(bout *bio.Writer) { - p := &exporter{marked: make(map[*types.Type]bool)} - for _, n := range typecheck.Target.Exports { - p.markObject(n) - } - - // The linker also looks for the $$ marker - use char after $$ to distinguish format. - exportf(bout, "\n$$B\n") // indicate binary export format - off := bout.Offset() - typecheck.WriteExports(bout.Writer) - size := bout.Offset() - off - exportf(bout, "\n$$\n") - - if base.Debug.Export != 0 { - fmt.Printf("BenchmarkExportSize:%s 1 %d bytes\n", base.Ctxt.Pkgpath, size) - } -} - func dumpasmhdr() { b, err := bio.Create(base.Flag.AsmHdr) if err != nil { @@ -74,92 +49,3 @@ func dumpasmhdr() { b.Close() } - -type exporter struct { - marked map[*types.Type]bool // types already seen by markType -} - -// markObject visits a reachable object. -func (p *exporter) markObject(n ir.Node) { - if n.Op() == ir.ONAME { - n := n.(*ir.Name) - if n.Class == ir.PFUNC { - inline.Inline_Flood(n, typecheck.Export) - } - } - - p.markType(n.Type()) -} - -// markType recursively visits types reachable from t to identify -// functions whose inline bodies may be needed. -func (p *exporter) markType(t *types.Type) { - if t.IsInstantiatedGeneric() { - // Re-instantiated types don't add anything new, so don't follow them. - return - } - if p.marked[t] { - return - } - p.marked[t] = true - - // If this is a named type, mark all of its associated - // methods. Skip interface types because t.Methods contains - // only their unexpanded method set (i.e., exclusive of - // interface embeddings), and the switch statement below - // handles their full method set. - if t.Sym() != nil && t.Kind() != types.TINTER { - for _, m := range t.Methods().Slice() { - if types.IsExported(m.Sym.Name) { - p.markObject(ir.AsNode(m.Nname)) - } - } - } - - // Recursively mark any types that can be produced given a - // value of type t: dereferencing a pointer; indexing or - // iterating over an array, slice, or map; receiving from a - // channel; accessing a struct field or interface method; or - // calling a function. - // - // Notably, we don't mark function parameter types, because - // the user already needs some way to construct values of - // those types. - switch t.Kind() { - case types.TPTR, types.TARRAY, types.TSLICE: - p.markType(t.Elem()) - - case types.TCHAN: - if t.ChanDir().CanRecv() { - p.markType(t.Elem()) - } - - case types.TMAP: - p.markType(t.Key()) - p.markType(t.Elem()) - - case types.TSTRUCT: - for _, f := range t.FieldSlice() { - if types.IsExported(f.Sym.Name) || f.Embedded != 0 { - p.markType(f.Type) - } - } - - case types.TFUNC: - for _, f := range t.Results().FieldSlice() { - p.markType(f.Type) - } - - case types.TINTER: - // TODO(danscales) - will have to deal with the types in interface - // elements here when implemented in types2 and represented in types1. - for _, f := range t.AllMethods().Slice() { - if types.IsExported(f.Sym.Name) { - p.markType(f.Type) - } - } - - case types.TTYPEPARAM: - // No other type that needs to be followed. - } -} diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go index 0b10cb8a9e..a52696fbb6 100644 --- a/src/cmd/compile/internal/gc/obj.go +++ b/src/cmd/compile/internal/gc/obj.go @@ -7,6 +7,7 @@ package gc import ( "cmd/compile/internal/base" "cmd/compile/internal/ir" + "cmd/compile/internal/noder" "cmd/compile/internal/objw" "cmd/compile/internal/reflectdata" "cmd/compile/internal/staticdata" @@ -103,7 +104,7 @@ func finishArchiveEntry(bout *bio.Writer, start int64, name string) { func dumpCompilerObj(bout *bio.Writer) { printObjHeader(bout) - dumpexport(bout) + noder.WriteExports(bout) } func dumpdata() { diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index 594f280f03..e12a30f936 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -225,62 +225,6 @@ func canDelayResults(fn *ir.Func) bool { return true } -// Inline_Flood marks n's inline body for export and recursively ensures -// all called functions are marked too. -func Inline_Flood(n *ir.Name, exportsym func(*ir.Name)) { - if n == nil { - return - } - if n.Op() != ir.ONAME || n.Class != ir.PFUNC { - base.Fatalf("Inline_Flood: unexpected %v, %v, %v", n, n.Op(), n.Class) - } - fn := n.Func - if fn == nil { - base.Fatalf("Inline_Flood: missing Func on %v", n) - } - if fn.Inl == nil { - return - } - - if fn.ExportInline() { - return - } - fn.SetExportInline(true) - - typecheck.ImportedBody(fn) - - var doFlood func(n ir.Node) - doFlood = func(n ir.Node) { - switch n.Op() { - case ir.OMETHEXPR, ir.ODOTMETH: - Inline_Flood(ir.MethodExprName(n), exportsym) - - case ir.ONAME: - n := n.(*ir.Name) - switch n.Class { - case ir.PFUNC: - Inline_Flood(n, exportsym) - exportsym(n) - case ir.PEXTERN: - exportsym(n) - } - - case ir.OCALLPART: - // Okay, because we don't yet inline indirect - // calls to method values. - case ir.OCLOSURE: - // VisitList doesn't visit closure bodies, so force a - // recursive call to VisitList on the body of the closure. - ir.VisitList(n.(*ir.ClosureExpr).Func.Body, doFlood) - } - } - - // Recursively identify all referenced functions for - // reexport. We want to include even non-called functions, - // because after inlining they might be callable. - ir.VisitList(ir.Nodes(fn.Inl.Body), doFlood) -} - // hairyVisitor visits a function body to determine its inlining // hairiness and whether or not it can be inlined. type hairyVisitor struct { diff --git a/src/cmd/compile/internal/noder/export.go b/src/cmd/compile/internal/noder/export.go new file mode 100644 index 0000000000..9fb3b4da10 --- /dev/null +++ b/src/cmd/compile/internal/noder/export.go @@ -0,0 +1,26 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package noder + +import ( + "fmt" + + "cmd/compile/internal/base" + "cmd/compile/internal/typecheck" + "cmd/internal/bio" +) + +func WriteExports(out *bio.Writer) { + // The linker also looks for the $$ marker - use char after $$ to distinguish format. + out.WriteString("\n$$B\n") // indicate binary export format + off := out.Offset() + typecheck.WriteExports(out, true) + size := out.Offset() - off + out.WriteString("\n$$\n") + + if base.Debug.Export != 0 { + fmt.Printf("BenchmarkExportSize:%s 1 %d bytes\n", base.Ctxt.Pkgpath, size) + } +} diff --git a/src/cmd/compile/internal/typecheck/crawler.go b/src/cmd/compile/internal/typecheck/crawler.go new file mode 100644 index 0000000000..48fc61dbfd --- /dev/null +++ b/src/cmd/compile/internal/typecheck/crawler.go @@ -0,0 +1,164 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package typecheck + +import ( + "cmd/compile/internal/base" + "cmd/compile/internal/ir" + "cmd/compile/internal/types" +) + +// crawlExports crawls the type/object graph rooted at the given list +// of exported objects. Any functions that are found to be potentially +// callable by importers are marked with ExportInline so that +// iexport.go knows to re-export their inline body. +func crawlExports(exports []*ir.Name) { + p := crawler{marked: make(map[*types.Type]bool)} + for _, n := range exports { + p.markObject(n) + } +} + +type crawler struct { + marked map[*types.Type]bool // types already seen by markType +} + +// markObject visits a reachable object. +func (p *crawler) markObject(n *ir.Name) { + if n.Op() == ir.ONAME && n.Class == ir.PFUNC { + p.markInlBody(n) + } + + p.markType(n.Type()) +} + +// markType recursively visits types reachable from t to identify +// functions whose inline bodies may be needed. +func (p *crawler) markType(t *types.Type) { + if t.IsInstantiatedGeneric() { + // Re-instantiated types don't add anything new, so don't follow them. + return + } + if p.marked[t] { + return + } + p.marked[t] = true + + // If this is a named type, mark all of its associated + // methods. Skip interface types because t.Methods contains + // only their unexpanded method set (i.e., exclusive of + // interface embeddings), and the switch statement below + // handles their full method set. + if t.Sym() != nil && t.Kind() != types.TINTER { + for _, m := range t.Methods().Slice() { + if types.IsExported(m.Sym.Name) { + p.markObject(m.Nname.(*ir.Name)) + } + } + } + + // Recursively mark any types that can be produced given a + // value of type t: dereferencing a pointer; indexing or + // iterating over an array, slice, or map; receiving from a + // channel; accessing a struct field or interface method; or + // calling a function. + // + // Notably, we don't mark function parameter types, because + // the user already needs some way to construct values of + // those types. + switch t.Kind() { + case types.TPTR, types.TARRAY, types.TSLICE: + p.markType(t.Elem()) + + case types.TCHAN: + if t.ChanDir().CanRecv() { + p.markType(t.Elem()) + } + + case types.TMAP: + p.markType(t.Key()) + p.markType(t.Elem()) + + case types.TSTRUCT: + for _, f := range t.FieldSlice() { + if types.IsExported(f.Sym.Name) || f.Embedded != 0 { + p.markType(f.Type) + } + } + + case types.TFUNC: + for _, f := range t.Results().FieldSlice() { + p.markType(f.Type) + } + + case types.TINTER: + // TODO(danscales) - will have to deal with the types in interface + // elements here when implemented in types2 and represented in types1. + for _, f := range t.AllMethods().Slice() { + if types.IsExported(f.Sym.Name) { + p.markType(f.Type) + } + } + + case types.TTYPEPARAM: + // No other type that needs to be followed. + } +} + +// markInlBody marks n's inline body for export and recursively +// ensures all called functions are marked too. +func (p *crawler) markInlBody(n *ir.Name) { + if n == nil { + return + } + if n.Op() != ir.ONAME || n.Class != ir.PFUNC { + base.Fatalf("markInlBody: unexpected %v, %v, %v", n, n.Op(), n.Class) + } + fn := n.Func + if fn == nil { + base.Fatalf("markInlBody: missing Func on %v", n) + } + if fn.Inl == nil { + return + } + + if fn.ExportInline() { + return + } + fn.SetExportInline(true) + + ImportedBody(fn) + + var doFlood func(n ir.Node) + doFlood = func(n ir.Node) { + switch n.Op() { + case ir.OMETHEXPR, ir.ODOTMETH: + p.markInlBody(ir.MethodExprName(n)) + + case ir.ONAME: + n := n.(*ir.Name) + switch n.Class { + case ir.PFUNC: + p.markInlBody(n) + Export(n) + case ir.PEXTERN: + Export(n) + } + + case ir.OCALLPART: + // Okay, because we don't yet inline indirect + // calls to method values. + case ir.OCLOSURE: + // VisitList doesn't visit closure bodies, so force a + // recursive call to VisitList on the body of the closure. + ir.VisitList(n.(*ir.ClosureExpr).Func.Body, doFlood) + } + } + + // Recursively identify all referenced functions for + // reexport. We want to include even non-called functions, + // because after inlining they might be callable. + ir.VisitList(fn.Inl.Body, doFlood) +} diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 3bfbea11c0..6987bc9918 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -204,7 +204,6 @@ package typecheck import ( - "bufio" "bytes" "crypto/md5" "encoding/binary" @@ -264,13 +263,22 @@ const ( magic = 0x6742937dc293105 ) -func WriteExports(out *bufio.Writer) { +// WriteExports writes the indexed export format to out. If extensions +// is true, then the compiler-only extensions are included. +func WriteExports(out io.Writer, extensions bool) { + if extensions { + // If we're exporting inline bodies, invoke the crawler to mark + // which bodies to include. + crawlExports(Target.Exports) + } + p := iexporter{ allPkgs: map[*types.Pkg]bool{}, stringIndex: map[string]uint64{}, declIndex: map[*types.Sym]uint64{}, inlineIndex: map[*types.Sym]uint64{}, typIndex: map[*types.Type]uint64{}, + extensions: extensions, } for i, pt := range predeclared() { @@ -397,6 +405,8 @@ type iexporter struct { declIndex map[*types.Sym]uint64 inlineIndex map[*types.Sym]uint64 typIndex map[*types.Type]uint64 + + extensions bool } // stringOff returns the offset of s within the string section. @@ -467,7 +477,9 @@ func (p *iexporter) doDecl(n *ir.Name) { w.tag('V') w.pos(n.Pos()) w.typ(n.Type()) - w.varExt(n) + if w.p.extensions { + w.varExt(n) + } case ir.PFUNC: if ir.IsMethod(n) { @@ -487,7 +499,9 @@ func (p *iexporter) doDecl(n *ir.Name) { w.tparamList(n.Type().TParams().FieldSlice()) } w.signature(n.Type()) - w.funcExt(n) + if w.p.extensions { + w.funcExt(n) + } default: base.Fatalf("unexpected class: %v, %v", n, n.Class) @@ -503,7 +517,9 @@ func (p *iexporter) doDecl(n *ir.Name) { w.tag('C') w.pos(n.Pos()) w.value(n.Type(), n.Val()) - w.constExt(n) + if w.p.extensions { + w.constExt(n) + } case ir.OTYPE: if n.Type().Kind() == types.TTYPEPARAM && n.Type().Underlying() == n.Type() { @@ -551,7 +567,9 @@ func (p *iexporter) doDecl(n *ir.Name) { t := n.Type() if t.IsInterface() { - w.typeExt(t) + if w.p.extensions { + w.typeExt(t) + } break } @@ -567,9 +585,11 @@ func (p *iexporter) doDecl(n *ir.Name) { w.signature(m.Type) } - w.typeExt(t) - for _, m := range methods { - w.methExt(m) + if w.p.extensions { + w.typeExt(t) + for _, m := range methods { + w.methExt(m) + } } default: -- GitLab From c23294d6b356590d5ebcaf153048111ee9b30465 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sat, 5 Jun 2021 21:23:48 -0700 Subject: [PATCH 0231/2500] [dev.typeparams] cmd/compile/internal/types2: return Universe for ((*Package)(nil)).Scope() For #46594. Change-Id: I53776cbdc1b8f6da511abe2c6659a7313d7a163a Reviewed-on: https://go-review.googlesource.com/c/go/+/325469 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/types2/package.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/types2/package.go b/src/cmd/compile/internal/types2/package.go index c5804a05ad..8044e7e6a7 100644 --- a/src/cmd/compile/internal/types2/package.go +++ b/src/cmd/compile/internal/types2/package.go @@ -48,7 +48,13 @@ func (pkg *Package) SetName(name string) { pkg.name = name } // Scope returns the (complete or incomplete) package scope // holding the objects declared at package level (TypeNames, // Consts, Vars, and Funcs). -func (pkg *Package) Scope() *Scope { return pkg.scope } +// For a nil pkg receiver, Scope returns the Universe scope. +func (pkg *Package) Scope() *Scope { + if pkg != nil { + return pkg.scope + } + return Universe +} // A package is complete if its scope contains (at least) all // exported objects; otherwise it is incomplete. -- GitLab From 991dca0112c9c81c384b32d413a693ff4751c3ab Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Thu, 3 Jun 2021 11:13:38 -0400 Subject: [PATCH 0232/2500] [dev.typeparams] go/types: move signature checking into separate file This is a port of CL 321590 to go/types. Specifically, the same checker methods were moved. Change-Id: If4522d316f29c6b6f887580aa037e6b6dedbb6ac Reviewed-on: https://go-review.googlesource.com/c/go/+/324754 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/signature.go | 274 ++++++++++++++++++++++++++++++++++++++ src/go/types/typexpr.go | 262 ------------------------------------ 2 files changed, 274 insertions(+), 262 deletions(-) create mode 100644 src/go/types/signature.go diff --git a/src/go/types/signature.go b/src/go/types/signature.go new file mode 100644 index 0000000000..5489b493ba --- /dev/null +++ b/src/go/types/signature.go @@ -0,0 +1,274 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +import ( + "fmt" + "go/ast" + "go/internal/typeparams" + "go/token" +) + +// funcType type-checks a function or method type. +func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast.FuncType) { + check.openScope(ftyp, "function") + check.scope.isFunc = true + check.recordScope(ftyp, check.scope) + sig.scope = check.scope + defer check.closeScope() + + var recvTyp ast.Expr // rewritten receiver type; valid if != nil + if recvPar != nil && len(recvPar.List) > 0 { + // collect generic receiver type parameters, if any + // - a receiver type parameter is like any other type parameter, except that it is declared implicitly + // - the receiver specification acts as local declaration for its type parameters, which may be blank + _, rname, rparams := check.unpackRecv(recvPar.List[0].Type, true) + if len(rparams) > 0 { + // Blank identifiers don't get declared and regular type-checking of the instantiated + // parameterized receiver type expression fails in Checker.collectParams of receiver. + // Identify blank type parameters and substitute each with a unique new identifier named + // "n_" (where n is the parameter index) and which cannot conflict with any user-defined + // name. + var smap map[*ast.Ident]*ast.Ident // substitution map from "_" to "n_" identifiers + for i, p := range rparams { + if p.Name == "_" { + new := *p + new.Name = fmt.Sprintf("%d_", i) + rparams[i] = &new // use n_ identifier instead of _ so it can be looked up + if smap == nil { + smap = make(map[*ast.Ident]*ast.Ident) + } + smap[p] = &new + } + } + if smap != nil { + // blank identifiers were found => use rewritten receiver type + recvTyp = isubst(recvPar.List[0].Type, smap) + } + sig.rparams = check.declareTypeParams(nil, rparams) + // determine receiver type to get its type parameters + // and the respective type parameter bounds + var recvTParams []*TypeName + if rname != nil { + // recv should be a Named type (otherwise an error is reported elsewhere) + // Also: Don't report an error via genericType since it will be reported + // again when we type-check the signature. + // TODO(gri) maybe the receiver should be marked as invalid instead? + if recv := asNamed(check.genericType(rname, false)); recv != nil { + recvTParams = recv.tparams + } + } + // provide type parameter bounds + // - only do this if we have the right number (otherwise an error is reported elsewhere) + if len(sig.rparams) == len(recvTParams) { + // We have a list of *TypeNames but we need a list of Types. + list := make([]Type, len(sig.rparams)) + for i, t := range sig.rparams { + list[i] = t.typ + } + smap := makeSubstMap(recvTParams, list) + for i, tname := range sig.rparams { + bound := recvTParams[i].typ.(*_TypeParam).bound + // bound is (possibly) parameterized in the context of the + // receiver type declaration. Substitute parameters for the + // current context. + // TODO(gri) should we assume now that bounds always exist? + // (no bound == empty interface) + if bound != nil { + bound = check.subst(tname.pos, bound, smap) + tname.typ.(*_TypeParam).bound = bound + } + } + } + } + } + + if tparams := typeparams.Get(ftyp); tparams != nil { + sig.tparams = check.collectTypeParams(tparams) + // Always type-check method type parameters but complain that they are not allowed. + // (A separate check is needed when type-checking interface method signatures because + // they don't have a receiver specification.) + if recvPar != nil { + check.errorf(tparams, _Todo, "methods cannot have type parameters") + } + } + + // Value (non-type) parameters' scope starts in the function body. Use a temporary scope for their + // declarations and then squash that scope into the parent scope (and report any redeclarations at + // that time). + scope := NewScope(check.scope, token.NoPos, token.NoPos, "function body (temp. scope)") + recvList, _ := check.collectParams(scope, recvPar, recvTyp, false) // use rewritten receiver type, if any + params, variadic := check.collectParams(scope, ftyp.Params, nil, true) + results, _ := check.collectParams(scope, ftyp.Results, nil, false) + scope.squash(func(obj, alt Object) { + check.errorf(obj, _DuplicateDecl, "%s redeclared in this block", obj.Name()) + check.reportAltDecl(alt) + }) + + if recvPar != nil { + // recv parameter list present (may be empty) + // spec: "The receiver is specified via an extra parameter section preceding the + // method name. That parameter section must declare a single parameter, the receiver." + var recv *Var + switch len(recvList) { + case 0: + // error reported by resolver + recv = NewParam(0, nil, "", Typ[Invalid]) // ignore recv below + default: + // more than one receiver + check.error(recvList[len(recvList)-1], _BadRecv, "method must have exactly one receiver") + fallthrough // continue with first receiver + case 1: + recv = recvList[0] + } + + // TODO(gri) We should delay rtyp expansion to when we actually need the + // receiver; thus all checks here should be delayed to later. + rtyp, _ := deref(recv.typ) + rtyp = expand(rtyp) + + // spec: "The receiver type must be of the form T or *T where T is a type name." + // (ignore invalid types - error was reported before) + if t := rtyp; t != Typ[Invalid] { + var err string + if T := asNamed(t); T != nil { + // spec: "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." + if T.obj.pkg != check.pkg { + err = "type not defined in this package" + } else { + switch u := optype(T).(type) { + case *Basic: + // unsafe.Pointer is treated like a regular pointer + if u.kind == UnsafePointer { + err = "unsafe.Pointer" + } + case *Pointer, *Interface: + err = "pointer or interface type" + } + } + } else { + err = "basic or unnamed type" + } + if err != "" { + check.errorf(recv, _InvalidRecv, "invalid receiver %s (%s)", recv.typ, err) + // ok to continue + } + } + sig.recv = recv + } + + sig.params = NewTuple(params...) + sig.results = NewTuple(results...) + sig.variadic = variadic +} + +// collectParams declares the parameters of list in scope and returns the corresponding +// variable list. If type0 != nil, it is used instead of the first type in list. +func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, type0 ast.Expr, variadicOk bool) (params []*Var, variadic bool) { + if list == nil { + return + } + + var named, anonymous bool + for i, field := range list.List { + ftype := field.Type + if i == 0 && type0 != nil { + ftype = type0 + } + if t, _ := ftype.(*ast.Ellipsis); t != nil { + ftype = t.Elt + if variadicOk && i == len(list.List)-1 && len(field.Names) <= 1 { + variadic = true + } else { + check.softErrorf(t, _MisplacedDotDotDot, "can only use ... with final parameter in list") + // ignore ... and continue + } + } + typ := check.varType(ftype) + // The parser ensures that f.Tag is nil and we don't + // care if a constructed AST contains a non-nil tag. + if len(field.Names) > 0 { + // named parameter + for _, name := range field.Names { + if name.Name == "" { + check.invalidAST(name, "anonymous parameter") + // ok to continue + } + par := NewParam(name.Pos(), check.pkg, name.Name, typ) + check.declare(scope, name, par, scope.pos) + params = append(params, par) + } + named = true + } else { + // anonymous parameter + par := NewParam(ftype.Pos(), check.pkg, "", typ) + check.recordImplicit(field, par) + params = append(params, par) + anonymous = true + } + } + + if named && anonymous { + check.invalidAST(list, "list contains both named and anonymous parameters") + // ok to continue + } + + // For a variadic function, change the last parameter's type from T to []T. + // Since we type-checked T rather than ...T, we also need to retro-actively + // record the type for ...T. + if variadic { + last := params[len(params)-1] + last.typ = &Slice{elem: last.typ} + check.recordTypeAndValue(list.List[len(list.List)-1].Type, typexpr, last.typ, nil) + } + + return +} + +// isubst returns an x with identifiers substituted per the substitution map smap. +// isubst only handles the case of (valid) method receiver type expressions correctly. +func isubst(x ast.Expr, smap map[*ast.Ident]*ast.Ident) ast.Expr { + switch n := x.(type) { + case *ast.Ident: + if alt := smap[n]; alt != nil { + return alt + } + case *ast.StarExpr: + X := isubst(n.X, smap) + if X != n.X { + new := *n + new.X = X + return &new + } + case *ast.IndexExpr: + elems := typeparams.UnpackExpr(n.Index) + var newElems []ast.Expr + for i, elem := range elems { + new := isubst(elem, smap) + if new != elem { + if newElems == nil { + newElems = make([]ast.Expr, len(elems)) + copy(newElems, elems) + } + newElems[i] = new + } + } + if newElems != nil { + index := typeparams.PackExpr(newElems) + new := *n + new.Index = index + return &new + } + case *ast.ParenExpr: + return isubst(n.X, smap) // no need to keep parentheses + default: + // Other receiver type expressions are invalid. + // It's fine to ignore those here as they will + // be checked elsewhere. + } + return x +} diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index c6c3dc049a..97df908ae9 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -192,205 +192,6 @@ func (check *Checker) genericType(e ast.Expr, reportErr bool) Type { return typ } -// isubst returns an x with identifiers substituted per the substitution map smap. -// isubst only handles the case of (valid) method receiver type expressions correctly. -func isubst(x ast.Expr, smap map[*ast.Ident]*ast.Ident) ast.Expr { - switch n := x.(type) { - case *ast.Ident: - if alt := smap[n]; alt != nil { - return alt - } - case *ast.StarExpr: - X := isubst(n.X, smap) - if X != n.X { - new := *n - new.X = X - return &new - } - case *ast.IndexExpr: - elems := typeparams.UnpackExpr(n.Index) - var newElems []ast.Expr - for i, elem := range elems { - new := isubst(elem, smap) - if new != elem { - if newElems == nil { - newElems = make([]ast.Expr, len(elems)) - copy(newElems, elems) - } - newElems[i] = new - } - } - if newElems != nil { - index := typeparams.PackExpr(newElems) - new := *n - new.Index = index - return &new - } - case *ast.ParenExpr: - return isubst(n.X, smap) // no need to keep parentheses - default: - // Other receiver type expressions are invalid. - // It's fine to ignore those here as they will - // be checked elsewhere. - } - return x -} - -// funcType type-checks a function or method type. -func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast.FuncType) { - check.openScope(ftyp, "function") - check.scope.isFunc = true - check.recordScope(ftyp, check.scope) - sig.scope = check.scope - defer check.closeScope() - - var recvTyp ast.Expr // rewritten receiver type; valid if != nil - if recvPar != nil && len(recvPar.List) > 0 { - // collect generic receiver type parameters, if any - // - a receiver type parameter is like any other type parameter, except that it is declared implicitly - // - the receiver specification acts as local declaration for its type parameters, which may be blank - _, rname, rparams := check.unpackRecv(recvPar.List[0].Type, true) - if len(rparams) > 0 { - // Blank identifiers don't get declared and regular type-checking of the instantiated - // parameterized receiver type expression fails in Checker.collectParams of receiver. - // Identify blank type parameters and substitute each with a unique new identifier named - // "n_" (where n is the parameter index) and which cannot conflict with any user-defined - // name. - var smap map[*ast.Ident]*ast.Ident // substitution map from "_" to "n_" identifiers - for i, p := range rparams { - if p.Name == "_" { - new := *p - new.Name = fmt.Sprintf("%d_", i) - rparams[i] = &new // use n_ identifier instead of _ so it can be looked up - if smap == nil { - smap = make(map[*ast.Ident]*ast.Ident) - } - smap[p] = &new - } - } - if smap != nil { - // blank identifiers were found => use rewritten receiver type - recvTyp = isubst(recvPar.List[0].Type, smap) - } - sig.rparams = check.declareTypeParams(nil, rparams) - // determine receiver type to get its type parameters - // and the respective type parameter bounds - var recvTParams []*TypeName - if rname != nil { - // recv should be a Named type (otherwise an error is reported elsewhere) - // Also: Don't report an error via genericType since it will be reported - // again when we type-check the signature. - // TODO(gri) maybe the receiver should be marked as invalid instead? - if recv := asNamed(check.genericType(rname, false)); recv != nil { - recvTParams = recv.tparams - } - } - // provide type parameter bounds - // - only do this if we have the right number (otherwise an error is reported elsewhere) - if len(sig.rparams) == len(recvTParams) { - // We have a list of *TypeNames but we need a list of Types. - list := make([]Type, len(sig.rparams)) - for i, t := range sig.rparams { - list[i] = t.typ - } - smap := makeSubstMap(recvTParams, list) - for i, tname := range sig.rparams { - bound := recvTParams[i].typ.(*_TypeParam).bound - // bound is (possibly) parameterized in the context of the - // receiver type declaration. Substitute parameters for the - // current context. - // TODO(gri) should we assume now that bounds always exist? - // (no bound == empty interface) - if bound != nil { - bound = check.subst(tname.pos, bound, smap) - tname.typ.(*_TypeParam).bound = bound - } - } - } - } - } - - if tparams := typeparams.Get(ftyp); tparams != nil { - sig.tparams = check.collectTypeParams(tparams) - // Always type-check method type parameters but complain that they are not allowed. - // (A separate check is needed when type-checking interface method signatures because - // they don't have a receiver specification.) - if recvPar != nil { - check.errorf(tparams, _Todo, "methods cannot have type parameters") - } - } - - // Value (non-type) parameters' scope starts in the function body. Use a temporary scope for their - // declarations and then squash that scope into the parent scope (and report any redeclarations at - // that time). - scope := NewScope(check.scope, token.NoPos, token.NoPos, "function body (temp. scope)") - recvList, _ := check.collectParams(scope, recvPar, recvTyp, false) // use rewritten receiver type, if any - params, variadic := check.collectParams(scope, ftyp.Params, nil, true) - results, _ := check.collectParams(scope, ftyp.Results, nil, false) - scope.squash(func(obj, alt Object) { - check.errorf(obj, _DuplicateDecl, "%s redeclared in this block", obj.Name()) - check.reportAltDecl(alt) - }) - - if recvPar != nil { - // recv parameter list present (may be empty) - // spec: "The receiver is specified via an extra parameter section preceding the - // method name. That parameter section must declare a single parameter, the receiver." - var recv *Var - switch len(recvList) { - case 0: - // error reported by resolver - recv = NewParam(0, nil, "", Typ[Invalid]) // ignore recv below - default: - // more than one receiver - check.error(recvList[len(recvList)-1], _BadRecv, "method must have exactly one receiver") - fallthrough // continue with first receiver - case 1: - recv = recvList[0] - } - - // TODO(gri) We should delay rtyp expansion to when we actually need the - // receiver; thus all checks here should be delayed to later. - rtyp, _ := deref(recv.typ) - rtyp = expand(rtyp) - - // spec: "The receiver type must be of the form T or *T where T is a type name." - // (ignore invalid types - error was reported before) - if t := rtyp; t != Typ[Invalid] { - var err string - if T := asNamed(t); T != nil { - // spec: "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." - if T.obj.pkg != check.pkg { - err = "type not defined in this package" - } else { - switch u := optype(T).(type) { - case *Basic: - // unsafe.Pointer is treated like a regular pointer - if u.kind == UnsafePointer { - err = "unsafe.Pointer" - } - case *Pointer, *Interface: - err = "pointer or interface type" - } - } - } else { - err = "basic or unnamed type" - } - if err != "" { - check.errorf(recv, _InvalidRecv, "invalid receiver %s (%s)", recv.typ, err) - // ok to continue - } - } - sig.recv = recv - } - - sig.params = NewTuple(params...) - sig.results = NewTuple(results...) - sig.variadic = variadic -} - // goTypeName returns the Go type name for typ and // removes any occurrences of "types." from that name. func goTypeName(typ Type) string { @@ -683,66 +484,3 @@ func (check *Checker) typeList(list []ast.Expr) []Type { } return res } - -// collectParams declares the parameters of list in scope and returns the corresponding -// variable list. If type0 != nil, it is used instead of the first type in list. -func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, type0 ast.Expr, variadicOk bool) (params []*Var, variadic bool) { - if list == nil { - return - } - - var named, anonymous bool - for i, field := range list.List { - ftype := field.Type - if i == 0 && type0 != nil { - ftype = type0 - } - if t, _ := ftype.(*ast.Ellipsis); t != nil { - ftype = t.Elt - if variadicOk && i == len(list.List)-1 && len(field.Names) <= 1 { - variadic = true - } else { - check.softErrorf(t, _MisplacedDotDotDot, "can only use ... with final parameter in list") - // ignore ... and continue - } - } - typ := check.varType(ftype) - // The parser ensures that f.Tag is nil and we don't - // care if a constructed AST contains a non-nil tag. - if len(field.Names) > 0 { - // named parameter - for _, name := range field.Names { - if name.Name == "" { - check.invalidAST(name, "anonymous parameter") - // ok to continue - } - par := NewParam(name.Pos(), check.pkg, name.Name, typ) - check.declare(scope, name, par, scope.pos) - params = append(params, par) - } - named = true - } else { - // anonymous parameter - par := NewParam(ftype.Pos(), check.pkg, "", typ) - check.recordImplicit(field, par) - params = append(params, par) - anonymous = true - } - } - - if named && anonymous { - check.invalidAST(list, "list contains both named and anonymous parameters") - // ok to continue - } - - // For a variadic function, change the last parameter's type from T to []T. - // Since we type-checked T rather than ...T, we also need to retro-actively - // record the type for ...T. - if variadic { - last := params[len(params)-1] - last.typ = &Slice{elem: last.typ} - check.recordTypeAndValue(list.List[len(list.List)-1].Type, typexpr, last.typ, nil) - } - - return -} -- GitLab From 139595207570ae380e3947fa39e43205477b7bba Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Thu, 3 Jun 2021 11:37:26 -0400 Subject: [PATCH 0233/2500] [dev.typeparams] go/types: add Named.SetTParams and Named.Orig methods This is a port of CL 309832 to go/types, adjusted to not export the new API and to amend TestSizeof. Change-Id: I67efd3ba9b921c8431528eba1cd88ec1f41898bb Reviewed-on: https://go-review.googlesource.com/c/go/+/324755 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/decl.go | 9 ++++----- src/go/types/sanitize.go | 4 ++-- src/go/types/sizeof_test.go | 2 +- src/go/types/subst.go | 5 ++--- src/go/types/type.go | 27 ++++++++++++++++++++------- 5 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 9211febc6d..12ee51b920 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -333,7 +333,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { switch t.info { case unknown: t.info = marked - t.info = check.validType(t.orig, append(path, t.obj)) // only types of current package added to path + t.info = check.validType(t.fromRHS, append(path, t.obj)) // only types of current package added to path case marked: // cycle detected for i, tn := range path { @@ -692,9 +692,8 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { } else { // defined type declaration - named := check.newNamed(obj, nil, nil) + named := check.newNamed(obj, nil, nil, nil, nil) def.setUnderlying(named) - obj.typ = named // make sure recursive type declarations terminate if tparams := typeparams.Get(tdecl); tparams != nil { check.openScope(tdecl, "type parameters") @@ -703,7 +702,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { } // determine underlying type of named - named.orig = check.definedType(tdecl.Type, named) + named.fromRHS = check.definedType(tdecl.Type, named) // The underlying type of named may be itself a named type that is // incomplete: @@ -718,7 +717,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { // and which has as its underlying type the named type B. // Determine the (final, unnamed) underlying type by resolving // any forward chain. - // TODO(gri) Investigate if we can just use named.origin here + // TODO(gri) Investigate if we can just use named.fromRHS here // and rely on lazy computation of the underlying type. named.underlying = under(named) } diff --git a/src/go/types/sanitize.go b/src/go/types/sanitize.go index f167cdd8b6..88fc3f8377 100644 --- a/src/go/types/sanitize.go +++ b/src/go/types/sanitize.go @@ -138,8 +138,8 @@ func (s sanitizer) typ(typ Type) Type { if debug && t.check != nil { panic("internal error: Named.check != nil") } - if orig := s.typ(t.orig); orig != t.orig { - t.orig = orig + if orig := s.typ(t.fromRHS); orig != t.fromRHS { + t.fromRHS = orig } if under := s.typ(t.underlying); under != t.underlying { t.underlying = under diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index 5a9d07ca41..3af9079a85 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -30,7 +30,7 @@ func TestSizeof(t *testing.T) { {Interface{}, 60, 120}, {Map{}, 16, 32}, {Chan{}, 12, 24}, - {Named{}, 64, 128}, + {Named{}, 68, 136}, {_TypeParam{}, 28, 48}, {instance{}, 44, 88}, {bottom{}, 0, 0}, diff --git a/src/go/types/subst.go b/src/go/types/subst.go index d27f3645cc..43a64d04bb 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -396,8 +396,7 @@ func (subst *subster) typ(typ Type) Type { // create a new named type and populate caches to avoid endless recursion tname := NewTypeName(subst.pos, t.obj.pkg, t.obj.name, nil) - named := subst.check.newNamed(tname, t.underlying, t.methods) // method signatures are updated lazily - named.tparams = t.tparams // new type is still parameterized + named := subst.check.newNamed(tname, t, t.underlying, t.tparams, t.methods) // method signatures are updated lazily named.targs = newTargs if subst.check != nil { subst.check.typMap[h] = named @@ -407,7 +406,7 @@ func (subst *subster) typ(typ Type) Type { // do the substitution dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, newTargs) named.underlying = subst.typOrNil(t.underlying) - named.orig = named.underlying // for cycle detection (Checker.validType) + named.fromRHS = named.underlying // for cycle detection (Checker.validType) return named diff --git a/src/go/types/type.go b/src/go/types/type.go index 2ea4d76d8b..55b5c81540 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -642,12 +642,15 @@ func (c *Chan) Dir() ChanDir { return c.dir } // Elem returns the element type of channel c. func (c *Chan) Elem() Type { return c.elem } +// TODO(rfindley) Clean up Named struct below; specifically the fromRHS field (can we use underlying?). + // A Named represents a named (defined) type. type Named struct { check *Checker // for Named.under implementation; nilled once under has been called info typeInfo // for cycle detection obj *TypeName // corresponding declared object - orig Type // type (on RHS of declaration) this *Named type is derived of (for cycle reporting) + orig *Named // original, uninstantiated type + fromRHS Type // type (on RHS of declaration) this *Named type is derived of (for cycle reporting) underlying Type // possibly a *Named during setup; never a *Named once set up completely tparams []*TypeName // type parameters, or nil targs []Type // type arguments (after instantiation), or nil @@ -661,11 +664,14 @@ func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named { if _, ok := underlying.(*Named); ok { panic("types.NewNamed: underlying type must not be *Named") } - return (*Checker)(nil).newNamed(obj, underlying, methods) + return (*Checker)(nil).newNamed(obj, nil, underlying, nil, methods) } -func (check *Checker) newNamed(obj *TypeName, underlying Type, methods []*Func) *Named { - typ := &Named{check: check, obj: obj, orig: underlying, underlying: underlying, methods: methods} +func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams []*TypeName, methods []*Func) *Named { + typ := &Named{check: check, obj: obj, orig: orig, fromRHS: underlying, underlying: underlying, tparams: tparams, methods: methods} + if typ.orig == nil { + typ.orig = typ + } if obj.typ == nil { obj.typ = typ } @@ -692,6 +698,10 @@ func (check *Checker) newNamed(obj *TypeName, underlying Type, methods []*Func) // Obj returns the type name for the named type t. func (t *Named) Obj() *TypeName { return t.obj } +// _Orig returns the original generic type an instantiated type is derived from. +// If t is not an instantiated type, the result is t. +func (t *Named) _Orig() *Named { return t.orig } + // TODO(gri) Come up with a better representation and API to distinguish // between parameterized instantiated and non-instantiated types. @@ -699,10 +709,13 @@ func (t *Named) Obj() *TypeName { return t.obj } // The result is non-nil for an (originally) parameterized type even if it is instantiated. func (t *Named) _TParams() []*TypeName { return t.tparams } +// _SetTParams sets the type parameters of the named type t. +func (t *Named) _SetTParams(tparams []*TypeName) { t.tparams = tparams } + // _TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated. func (t *Named) _TArgs() []Type { return t.targs } -// _SetTArgs sets the type arguments of Named. +// SetTArgs sets the type arguments of the named type t. func (t *Named) _SetTArgs(args []Type) { t.targs = args } // NumMethods returns the number of explicit methods whose receiver is named type t. @@ -741,9 +754,9 @@ func nextID() uint64 { return uint64(atomic.AddUint32(&lastID, 1)) } // A _TypeParam represents a type parameter type. type _TypeParam struct { check *Checker // for lazy type bound completion - id uint64 // unique id + id uint64 // unique id, for debugging only obj *TypeName // corresponding type name - index int // parameter index + index int // type parameter index in source order, starting at 0 bound Type // *Named or *Interface; underlying type is always *Interface } -- GitLab From 2f26adc232988938cff003e15dae75757f76710a Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Thu, 3 Jun 2021 11:49:52 -0400 Subject: [PATCH 0234/2500] [dev.typeparams] go/types: re-use existing code for Interface.Complete This is a port of CL 321751 to go/types, adjusted to use token.Pos, and to exclude a missing position from a panic message (an unresolved comment on the original CL). Change-Id: I5814067aecb67aca9d73f2093fb6004b769924f3 Reviewed-on: https://go-review.googlesource.com/c/go/+/324756 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/interface.go | 48 +++++++++++++++++++++++++++---- src/go/types/type.go | 60 ++------------------------------------- 2 files changed, 44 insertions(+), 64 deletions(-) diff --git a/src/go/types/interface.go b/src/go/types/interface.go index 288e421cae..fd3fe0ef91 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -5,6 +5,7 @@ package types import ( + "fmt" "go/ast" "go/internal/typeparams" "go/token" @@ -142,8 +143,13 @@ func (check *Checker) completeInterface(pos token.Pos, ityp *Interface) { if check == nil { panic("internal error: incomplete interface") } + completeInterface(check, pos, ityp) +} + +func completeInterface(check *Checker, pos token.Pos, ityp *Interface) { + assert(ityp.allMethods == nil) - if trace { + if check != nil && trace { // Types don't generally have position information. // If we don't have a valid pos provided, try to use // one close enough. @@ -179,6 +185,7 @@ func (check *Checker) completeInterface(pos token.Pos, ityp *Interface) { // we can get rid of the mpos map below and simply use the cloned method's // position. + var todo []*Func var seen objset var methods []*Func mpos := make(map[*Func]token.Pos) // method specification or method embedding position, for good error messages @@ -188,6 +195,9 @@ func (check *Checker) completeInterface(pos token.Pos, ityp *Interface) { methods = append(methods, m) mpos[m] = pos case explicit: + if check == nil { + panic(fmt.Sprintf("%v: duplicate method %s", m.pos, m.name)) + } check.errorf(atPos(pos), _DuplicateDecl, "duplicate method %s", m.name) check.errorf(atPos(mpos[other.(*Func)]), _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented default: @@ -196,6 +206,11 @@ func (check *Checker) completeInterface(pos token.Pos, ityp *Interface) { // If we're pre-go1.14 (overlapping embeddings are not permitted), report that // error here as well (even though we could do it eagerly) because it's the same // error message. + if check == nil { + // check method signatures after all locally embedded interfaces are computed + todo = append(todo, m, other.(*Func)) + break + } check.later(func() { if !check.allowVersion(m.pkg, 1, 14) || !check.identical(m.typ, other.Type()) { check.errorf(atPos(pos), _DuplicateDecl, "duplicate method %s", m.name) @@ -212,9 +227,15 @@ func (check *Checker) completeInterface(pos token.Pos, ityp *Interface) { // collect types allTypes := ityp.types - posList := check.posMap[ityp] + var posList []token.Pos + if check != nil { + posList = check.posMap[ityp] + } for i, typ := range ityp.embeddeds { - pos := posList[i] // embedding position + var pos token.Pos // embedding position + if posList != nil { + pos = posList[i] + } utyp := under(typ) etyp := asInterface(utyp) if etyp == nil { @@ -225,18 +246,33 @@ func (check *Checker) completeInterface(pos token.Pos, ityp *Interface) { } else { format = "%s is not an interface" } - // TODO: correct error code. - check.errorf(atPos(pos), _InvalidIfaceEmbed, format, typ) + if check != nil { + // TODO: correct error code. + check.errorf(atPos(pos), _InvalidIfaceEmbed, format, typ) + } else { + panic(fmt.Sprintf(format, typ)) + } } continue } - check.completeInterface(pos, etyp) + if etyp.allMethods == nil { + completeInterface(check, pos, etyp) + } for _, m := range etyp.allMethods { addMethod(pos, m, false) // use embedding position pos rather than m.pos } allTypes = intersect(allTypes, etyp.allTypes) } + // process todo's (this only happens if check == nil) + for i := 0; i < len(todo); i += 2 { + m := todo[i] + other := todo[i+1] + if !Identical(m.typ, other.typ) { + panic(fmt.Sprintf("%v: duplicate method %s", m.pos, m.name)) + } + } + if methods != nil { sort.Sort(byUniqueMethodName(methods)) ityp.allMethods = methods diff --git a/src/go/types/type.go b/src/go/types/type.go index 55b5c81540..fff8541c42 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -5,7 +5,6 @@ package types import ( - "fmt" "go/token" "sync/atomic" ) @@ -538,64 +537,9 @@ func (t *Interface) isSatisfiedBy(typ Type) bool { // form other types. The interface must not contain duplicate methods or a // panic occurs. Complete returns the receiver. func (t *Interface) Complete() *Interface { - // TODO(gri) consolidate this method with Checker.completeInterface - if t.allMethods != nil { - return t - } - - t.allMethods = markComplete // avoid infinite recursion - - var todo []*Func - var methods []*Func - var seen objset - addMethod := func(m *Func, explicit bool) { - switch other := seen.insert(m); { - case other == nil: - methods = append(methods, m) - case explicit: - panic("duplicate method " + m.name) - default: - // check method signatures after all locally embedded interfaces are computed - todo = append(todo, m, other.(*Func)) - } - } - - for _, m := range t.methods { - addMethod(m, true) - } - - allTypes := t.types - - for _, typ := range t.embeddeds { - utyp := under(typ) - etyp := asInterface(utyp) - if etyp == nil { - if utyp != Typ[Invalid] { - panic(fmt.Sprintf("%s is not an interface", typ)) - } - continue - } - etyp.Complete() - for _, m := range etyp.allMethods { - addMethod(m, false) - } - allTypes = intersect(allTypes, etyp.allTypes) - } - - for i := 0; i < len(todo); i += 2 { - m := todo[i] - other := todo[i+1] - if !Identical(m.typ, other.typ) { - panic("duplicate method " + m.name) - } - } - - if methods != nil { - sortMethods(methods) - t.allMethods = methods + if t.allMethods == nil { + completeInterface(nil, token.NoPos, t) } - t.allTypes = allTypes - return t } -- GitLab From 7497e57a39b38894ee19b32a00fe5d057c05f842 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Thu, 3 Jun 2021 11:55:11 -0400 Subject: [PATCH 0235/2500] [dev.typeparams] go/types: simplify Interface accessors This is a straightforward port of CL 321850 to go/types. Change-Id: I719c19b8839390fdfa961255c6f1e79561cda6e6 Reviewed-on: https://go-review.googlesource.com/c/go/+/324757 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/type.go | 62 +++++++++----------------------------------- 1 file changed, 12 insertions(+), 50 deletions(-) diff --git a/src/go/types/type.go b/src/go/types/type.go index fff8541c42..4a39499905 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -421,79 +421,41 @@ func (t *Interface) EmbeddedType(i int) Type { return t.embeddeds[i] } // NumMethods returns the total number of methods of interface t. // The interface must have been completed. -func (t *Interface) NumMethods() int { t.assertCompleteness(); return len(t.allMethods) } - -func (t *Interface) assertCompleteness() { - if t.allMethods == nil { - panic("interface is incomplete") - } -} +func (t *Interface) NumMethods() int { t.Complete(); return len(t.allMethods) } // Method returns the i'th method of interface t for 0 <= i < t.NumMethods(). // The methods are ordered by their unique Id. // The interface must have been completed. -func (t *Interface) Method(i int) *Func { t.assertCompleteness(); return t.allMethods[i] } +func (t *Interface) Method(i int) *Func { t.Complete(); return t.allMethods[i] } // Empty reports whether t is the empty interface. func (t *Interface) Empty() bool { - if t.allMethods != nil { - // interface is complete - quick test - // A non-nil allTypes may still be empty and represents the bottom type. - return len(t.allMethods) == 0 && t.allTypes == nil - } - return !t.iterate(func(t *Interface) bool { - return len(t.methods) > 0 || t.types != nil - }, nil) + t.Complete() + // A non-nil allTypes may still have length 0 but represents the bottom type. + return len(t.allMethods) == 0 && t.allTypes == nil } // _HasTypeList reports whether interface t has a type list, possibly from an embedded type. func (t *Interface) _HasTypeList() bool { - if t.allMethods != nil { - // interface is complete - quick test - return t.allTypes != nil - } - - return t.iterate(func(t *Interface) bool { - return t.types != nil - }, nil) + t.Complete() + return t.allTypes != nil } // _IsComparable reports whether interface t is or embeds the predeclared interface "comparable". func (t *Interface) _IsComparable() bool { - if t.allMethods != nil { - // interface is complete - quick test - _, m := lookupMethod(t.allMethods, nil, "==") - return m != nil - } - - return t.iterate(func(t *Interface) bool { - _, m := lookupMethod(t.methods, nil, "==") - return m != nil - }, nil) + t.Complete() + _, m := lookupMethod(t.allMethods, nil, "==") + return m != nil } // _IsConstraint reports t.HasTypeList() || t.IsComparable(). func (t *Interface) _IsConstraint() bool { - if t.allMethods != nil { - // interface is complete - quick test - if t.allTypes != nil { - return true - } - _, m := lookupMethod(t.allMethods, nil, "==") - return m != nil - } - - return t.iterate(func(t *Interface) bool { - if t.types != nil { - return true - } - _, m := lookupMethod(t.methods, nil, "==") - return m != nil - }, nil) + return t._HasTypeList() || t._IsComparable() } // iterate calls f with t and then with any embedded interface of t, recursively, until f returns true. // iterate reports whether any call to f returned true. +// TODO(rfindley) This is now only used by infer.go - see if we can eliminate it. func (t *Interface) iterate(f func(*Interface) bool, seen map[*Interface]bool) bool { if f(t) { return true -- GitLab From 7c8a5be2d6f26caed84c6bae2a115872af5b1021 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Thu, 3 Jun 2021 12:14:16 -0400 Subject: [PATCH 0236/2500] [dev.typeparams] go/types: factor out constraint satisfaction check This is a port of CL 322070 to go/types, adjusted for the different error reporting API. Change-Id: I75eafe015b5b00554116527ea021e7a5f9e0343b Reviewed-on: https://go-review.googlesource.com/c/go/+/324759 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/subst.go | 149 ++++++++++++++++++++++-------------------- 1 file changed, 79 insertions(+), 70 deletions(-) diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 43a64d04bb..47b0c279db 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -121,91 +121,100 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, poslist // check bounds for i, tname := range tparams { - tpar := tname.typ.(*_TypeParam) - iface := tpar.Bound() - if iface.Empty() { - continue // no type bound - } - - targ := targs[i] - // best position for error reporting pos := pos if i < len(poslist) { pos = poslist[i] } - // The type parameter bound is parameterized with the same type parameters - // as the instantiated type; before we can use it for bounds checking we - // need to instantiate it with the type arguments with which we instantiate - // the parameterized type. - iface = check.subst(pos, iface, smap).(*Interface) - - // targ must implement iface (methods) - // - check only if we have methods - check.completeInterface(token.NoPos, iface) - if len(iface.allMethods) > 0 { - // If the type argument is a pointer to a type parameter, the type argument's - // method set is empty. - // TODO(gri) is this what we want? (spec question) - if base, isPtr := deref(targ); isPtr && asTypeParam(base) != nil { - check.errorf(atPos(pos), 0, "%s has no methods", targ) - break - } - if m, wrong := check.missingMethod(targ, iface, true); m != nil { - // TODO(gri) needs to print updated name to avoid major confusion in error message! - // (print warning for now) - // Old warning: - // check.softErrorf(pos, "%s does not satisfy %s (warning: name not updated) = %s (missing method %s)", targ, tpar.bound, iface, m) - if m.name == "==" { - // We don't want to report "missing method ==". - check.softErrorf(atPos(pos), 0, "%s does not satisfy comparable", targ) - } else if wrong != nil { - // TODO(gri) This can still report uninstantiated types which makes the error message - // more difficult to read then necessary. - // TODO(rFindley) should this use parentheses rather than ':' for qualification? - check.softErrorf(atPos(pos), _Todo, - "%s does not satisfy %s: wrong method signature\n\tgot %s\n\twant %s", - targ, tpar.bound, wrong, m, - ) - } else { - check.softErrorf(atPos(pos), 0, "%s does not satisfy %s (missing method %s)", targ, tpar.bound, m.name) - } - break - } + // stop checking bounds after the first failure + if !check.satisfies(pos, targs[i], tname.typ.(*_TypeParam), smap) { + break } + } - // targ's underlying type must also be one of the interface types listed, if any - if iface.allTypes == nil { - continue // nothing to do - } + return check.subst(pos, typ, smap) +} - // If targ is itself a type parameter, each of its possible types, but at least one, must be in the - // list of iface types (i.e., the targ type list must be a non-empty subset of the iface types). - if targ := asTypeParam(targ); targ != nil { - targBound := targ.Bound() - if targBound.allTypes == nil { - check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ) - break - } - for _, t := range unpackType(targBound.allTypes) { - if !iface.isSatisfiedBy(t) { - // TODO(gri) match this error message with the one below (or vice versa) - check.softErrorf(atPos(pos), 0, "%s does not satisfy %s (%s type constraint %s not found in %s)", targ, tpar.bound, targ, t, iface.allTypes) - break - } +// satisfies reports whether the type argument targ satisfies the constraint of type parameter +// parameter tpar (after any of its type parameters have been substituted through smap). +// A suitable error is reported if the result is false. +func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *_TypeParam, smap *substMap) bool { + iface := tpar.Bound() + if iface.Empty() { + return true // no type bound + } + + // The type parameter bound is parameterized with the same type parameters + // as the instantiated type; before we can use it for bounds checking we + // need to instantiate it with the type arguments with which we instantiate + // the parameterized type. + iface = check.subst(pos, iface, smap).(*Interface) + + // targ must implement iface (methods) + // - check only if we have methods + check.completeInterface(token.NoPos, iface) + if len(iface.allMethods) > 0 { + // If the type argument is a pointer to a type parameter, the type argument's + // method set is empty. + // TODO(gri) is this what we want? (spec question) + if base, isPtr := deref(targ); isPtr && asTypeParam(base) != nil { + check.errorf(atPos(pos), 0, "%s has no methods", targ) + return false + } + if m, wrong := check.missingMethod(targ, iface, true); m != nil { + // TODO(gri) needs to print updated name to avoid major confusion in error message! + // (print warning for now) + // Old warning: + // check.softErrorf(pos, "%s does not satisfy %s (warning: name not updated) = %s (missing method %s)", targ, tpar.bound, iface, m) + if m.name == "==" { + // We don't want to report "missing method ==". + check.softErrorf(atPos(pos), 0, "%s does not satisfy comparable", targ) + } else if wrong != nil { + // TODO(gri) This can still report uninstantiated types which makes the error message + // more difficult to read then necessary. + // TODO(rFindley) should this use parentheses rather than ':' for qualification? + check.softErrorf(atPos(pos), _Todo, + "%s does not satisfy %s: wrong method signature\n\tgot %s\n\twant %s", + targ, tpar.bound, wrong, m, + ) + } else { + check.softErrorf(atPos(pos), 0, "%s does not satisfy %s (missing method %s)", targ, tpar.bound, m.name) } - break + return false } + } - // Otherwise, targ's type or underlying type must also be one of the interface types listed, if any. - if !iface.isSatisfiedBy(targ) { - check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s or %s not found in %s)", targ, tpar.bound, targ, under(targ), iface.allTypes) - break + // targ's underlying type must also be one of the interface types listed, if any + if iface.allTypes == nil { + return true // nothing to do + } + + // If targ is itself a type parameter, each of its possible types, but at least one, must be in the + // list of iface types (i.e., the targ type list must be a non-empty subset of the iface types). + if targ := asTypeParam(targ); targ != nil { + targBound := targ.Bound() + if targBound.allTypes == nil { + check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ) + return false + } + for _, t := range unpackType(targBound.allTypes) { + if !iface.isSatisfiedBy(t) { + // TODO(gri) match this error message with the one below (or vice versa) + check.softErrorf(atPos(pos), 0, "%s does not satisfy %s (%s type constraint %s not found in %s)", targ, tpar.bound, targ, t, iface.allTypes) + return false + } } + return false } - return check.subst(pos, typ, smap) + // Otherwise, targ's type or underlying type must also be one of the interface types listed, if any. + if !iface.isSatisfiedBy(targ) { + check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s not found in %s)", targ, tpar.bound, under(targ), iface.allTypes) + return false + } + + return true } // subst returns the type typ with its type parameters tpars replaced by -- GitLab From 2c98915ac7d304590590fc33a10a8922c466958b Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Sat, 22 May 2021 17:24:17 -0700 Subject: [PATCH 0237/2500] [dev.fuzz] internal/fuzz: add additional debug logging When GODEBUG=fuzzdebug=1, log additional debug level information about what the fuzzer is doing. This provides useful information for investigating the operation and performance of the fuzzing engine, and is necessary for profiling new fuzzing strategies. Change-Id: Ic3e24e7a128781377e62785767a218811c3c2030 Reviewed-on: https://go-review.googlesource.com/c/go/+/324972 Trust: Roland Shoemaker Trust: Katie Hockman Run-TryBot: Roland Shoemaker TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/go/build/deps_test.go | 2 +- src/internal/fuzz/coverage.go | 10 ++++++ src/internal/fuzz/fuzz.go | 66 +++++++++++++++++++++++++++++------ src/internal/fuzz/worker.go | 37 ++++++++++++++++---- src/testing/fuzz.go | 8 +++-- 5 files changed, 102 insertions(+), 21 deletions(-) diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 67989d2e38..2dc2939eec 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -509,7 +509,7 @@ var depsRules = ` FMT, flag, runtime/debug, runtime/trace, internal/sysinfo, math/rand < testing; - FMT, crypto/sha256, encoding/json, go/ast, go/parser, go/token, math/rand, encoding/hex, crypto/sha256 + FMT, crypto/sha256, encoding/json, go/ast, go/parser, go/token, math/rand, encoding/hex, crypto/sha256, log < internal/fuzz; internal/fuzz, internal/testlog, runtime/pprof, regexp diff --git a/src/internal/fuzz/coverage.go b/src/internal/fuzz/coverage.go index 316aa14783..bd1ff8690d 100644 --- a/src/internal/fuzz/coverage.go +++ b/src/internal/fuzz/coverage.go @@ -45,6 +45,16 @@ func SnapshotCoverage() { copy(coverageSnapshot, cov) } +func countEdges(cov []byte) int { + n := 0 + for _, c := range cov { + if c > 0 { + n++ + } + } + return n +} + var coverageSnapshot []byte // _counters and _ecounters mark the start and end, respectively, of where diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 4bcfbeec33..572a0f04d2 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -14,11 +14,13 @@ import ( "fmt" "io" "io/ioutil" + "log" "os" "path/filepath" "reflect" "runtime" "strings" + "sync" "time" ) @@ -237,11 +239,14 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err err: errors.New(result.crasherMsg), } } + if printDebugInfo() { + log.Printf("DEBUG new crasher, id: %s, parent: %s, gen: %d, size: %d, exec time: %s\n", result.entry.Name, result.entry.Parent, result.entry.Generation, len(result.entry.Data), result.entryDuration) + } stop(err) } } else if result.coverageData != nil { - foundNew := c.updateCoverage(result.coverageData) - if foundNew && !c.coverageOnlyRun() { + newEdges := c.updateCoverage(result.coverageData) + if newEdges > 0 && !c.coverageOnlyRun() { // Found an interesting value that expanded coverage. // This is not a crasher, but we should add it to the // on-disk corpus, and prioritize it for future fuzzing. @@ -257,14 +262,27 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err stop(err) } } + if printDebugInfo() { + log.Printf("DEBUG new interesting input, id: %s, parent: %s, gen: %d, new edges: %d, total edges: %d, size: %d, exec time: %s\n", result.entry.Name, result.entry.Parent, result.entry.Generation, newEdges, countEdges(c.coverageData), len(result.entry.Data), result.entryDuration) + } } else if c.coverageOnlyRun() { c.covOnlyInputs-- + if printDebugInfo() { + log.Printf("DEBUG processed an initial input, id: %s, new edges: %d, size: %d, exec time: %s\n", result.entry.Parent, newEdges, len(result.entry.Data), result.entryDuration) + } if c.covOnlyInputs == 0 { // The coordinator has finished getting a baseline for // coverage. Tell all of the workers to inialize their // baseline coverage data (by setting interestingCount // to 0). c.interestingCount = 0 + if printDebugInfo() { + log.Printf("DEBUG finished processing input corpus, entries: %d, initial coverage edges: %d\n", len(c.corpus.entries), countEdges(c.coverageData)) + } + } + } else { + if printDebugInfo() { + log.Printf("DEBUG worker reported interesting input that doesn't expand coverage, id: %s, parent: %s\n", result.entry.Name, result.entry.Parent) } } } @@ -341,6 +359,8 @@ type corpus struct { // TODO: split marshalled and unmarshalled types. In most places, we only need // one or the other. type CorpusEntry = struct { + Parent string + // Name is the name of the corpus file, if the entry was loaded from the // seed corpus. It can be used with -run. For entries added with f.Add and // entries generated by the mutator, Name is empty. @@ -351,6 +371,8 @@ type CorpusEntry = struct { // Values is the unmarshaled values from a corpus file. Values []interface{} + + Generation int } type fuzzInput struct { @@ -395,8 +417,11 @@ type fuzzResult struct { // count is the number of values the worker actually tested. count int64 - // duration is the time the worker spent testing inputs. - duration time.Duration + // totalDuration is the time the worker spent testing inputs. + totalDuration time.Duration + + // entryDuration is the time the worker spent execution an interesting result + entryDuration time.Duration } // coordinator holds channels that workers can use to communicate with @@ -468,7 +493,10 @@ func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { for _, t := range opts.Types { vals = append(vals, zeroValue(t)) } - corpus.entries = append(corpus.entries, CorpusEntry{Data: marshalCorpusFile(vals...), Values: vals}) + data := marshalCorpusFile(vals...) + h := sha256.Sum256(data) + name := fmt.Sprintf("%x", h[:4]) + corpus.entries = append(corpus.entries, CorpusEntry{Name: name, Data: data, Values: vals}) } c := &coordinator{ opts: opts, @@ -502,7 +530,7 @@ func (c *coordinator) updateStats(result fuzzResult) { // Adjust total stats. c.count += result.count c.countWaiting -= result.countRequested - c.duration += result.duration + c.duration += result.totalDuration } func (c *coordinator) logStats() { @@ -560,20 +588,20 @@ func (c *coordinator) coverageOnlyRun() bool { // updateCoverage updates c.coverageData for all edges that have a higher // counter value in newCoverage. It return true if a new edge was hit. -func (c *coordinator) updateCoverage(newCoverage []byte) bool { +func (c *coordinator) updateCoverage(newCoverage []byte) int { if len(newCoverage) != len(c.coverageData) { panic(fmt.Sprintf("num edges changed at runtime: %d, expected %d", len(newCoverage), len(c.coverageData))) } - newEdge := false + newEdges := 0 for i := range newCoverage { if newCoverage[i] > c.coverageData[i] { if c.coverageData[i] == 0 { - newEdge = true + newEdges++ } c.coverageData[i] = newCoverage[i] } } - return newEdge + return newEdges } // readCache creates a combined corpus from seed values and values in the cache @@ -716,3 +744,21 @@ var zeroVals []interface{} = []interface{}{ uint32(0), uint64(0), } + +var ( + debugInfo bool + debugInfoOnce sync.Once +) + +func printDebugInfo() bool { + debugInfoOnce.Do(func() { + debug := strings.Split(os.Getenv("GODEBUG"), ",") + for _, f := range debug { + if f == "fuzzdebug=1" { + debugInfo = true + break + } + } + }) + return debugInfo +} diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 2bfd9fce77..34871024c3 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -6,6 +6,7 @@ package fuzz import ( "context" + "crypto/sha256" "encoding/json" "errors" "fmt" @@ -166,13 +167,28 @@ func (w *worker) coordinate(ctx context.Context) error { result := fuzzResult{ countRequested: input.countRequested, count: resp.Count, - duration: resp.Duration, + totalDuration: resp.TotalDuration, + entryDuration: resp.InterestingDuration, } if resp.Err != "" { - result.entry = CorpusEntry{Data: value} + h := sha256.Sum256(value) + name := fmt.Sprintf("%x", h[:4]) + result.entry = CorpusEntry{ + Name: name, + Parent: input.entry.Name, + Data: value, + Generation: input.entry.Generation + 1, + } result.crasherMsg = resp.Err } else if resp.CoverageData != nil { - result.entry = CorpusEntry{Data: value} + h := sha256.Sum256(value) + name := fmt.Sprintf("%x", h[:4]) + result.entry = CorpusEntry{ + Name: name, + Parent: input.entry.Name, + Data: value, + Generation: input.entry.Generation + 1, + } result.coverageData = resp.CoverageData } w.coordinator.resultC <- result @@ -232,7 +248,7 @@ func (w *worker) minimize(ctx context.Context, input fuzzResult) (min fuzzResult } min.crasherMsg = resp.Err min.count = resp.Count - min.duration = resp.Duration + min.totalDuration = resp.Duration min.entry.Data = value return min, nil } @@ -496,7 +512,8 @@ type fuzzArgs struct { // fuzzResponse contains results from workerServer.fuzz. type fuzzResponse struct { // Duration is the time spent fuzzing, not including starting or cleaning up. - Duration time.Duration + TotalDuration time.Duration + InterestingDuration time.Duration // Count is the number of values tested. Count int64 @@ -622,7 +639,7 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo ws.coverageData = args.CoverageData } start := time.Now() - defer func() { resp.Duration = time.Since(start) }() + defer func() { resp.TotalDuration = time.Since(start) }() fuzzCtx, cancel := context.WithTimeout(ctx, args.Timeout) defer cancel() @@ -638,7 +655,9 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo } if args.CoverageOnly { + fStart := time.Now() ws.fuzzFn(CorpusEntry{Values: vals}) + resp.InterestingDuration = time.Since(fStart) resp.CoverageData = coverageSnapshot return resp } @@ -655,7 +674,10 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo mem.header().count++ ws.m.mutate(vals, cap(mem.valueRef())) writeToMem(vals, mem) - if err := ws.fuzzFn(CorpusEntry{Values: vals}); err != nil { + fStart := time.Now() + err := ws.fuzzFn(CorpusEntry{Values: vals}) + fDur := time.Since(fStart) + if err != nil { resp.Err = err.Error() if resp.Err == "" { resp.Err = "fuzz function failed with no output" @@ -666,6 +688,7 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo if ws.coverageData[i] == 0 && coverageSnapshot[i] > ws.coverageData[i] { // TODO(jayconrod,katie): minimize this. resp.CoverageData = coverageSnapshot + resp.InterestingDuration = fDur return resp } } diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 78a0a600fa..06f755b1ea 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -66,9 +66,11 @@ var _ TB = (*F)(nil) // We use a type alias because we don't want to export this type, and we can't // importing internal/fuzz from testing. type corpusEntry = struct { - Name string - Data []byte - Values []interface{} + Parent string + Name string + Data []byte + Values []interface{} + Generation int } // Cleanup registers a function to be called when the test and all its -- GitLab From 201d55e6376365dc5e8c2392e34fdf7ee8a4b63e Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Fri, 4 Jun 2021 18:17:49 -0700 Subject: [PATCH 0238/2500] [dev.typeparams] cmd/compile: create .dict Param in the package of the instantiated function The instantiated functions are created in the source package of the generic function, so all lookups of symbols should be relative to that package, so all symbols are consistently in the source package. Fixes #46575 Change-Id: Iba67b2ba8014a630c5d4e032c0f2f2fbaaedce65 Reviewed-on: https://go-review.googlesource.com/c/go/+/325529 Reviewed-by: Keith Randall Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/noder/stencil.go | 2 +- test/typeparam/mutualimp.dir/a.go | 11 +++++++++++ test/typeparam/mutualimp.dir/b.go | 12 ++++++++++++ test/typeparam/mutualimp.go | 7 +++++++ 4 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 test/typeparam/mutualimp.dir/a.go create mode 100644 test/typeparam/mutualimp.dir/b.go create mode 100644 test/typeparam/mutualimp.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 25a4bf775f..8b5a91f6d1 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -558,7 +558,7 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []*type oldt := nameNode.Type() // We also transform a generic method type to the corresponding // instantiated function type where the dictionary is the first parameter. - dictionarySym := types.LocalPkg.Lookup(".dict") + dictionarySym := newsym.Pkg.Lookup(".dict") dictionaryType := types.Types[types.TUINTPTR] dictionaryName := ir.NewNameAt(gf.Pos(), dictionarySym) typed(dictionaryType, dictionaryName) diff --git a/test/typeparam/mutualimp.dir/a.go b/test/typeparam/mutualimp.dir/a.go new file mode 100644 index 0000000000..56ca57cea5 --- /dev/null +++ b/test/typeparam/mutualimp.dir/a.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type X int +func (x X) M() X { return x } + +func F[T interface{ M() U }, U interface{ M() T }]() {} +func G() { F[X, X]() } diff --git a/test/typeparam/mutualimp.dir/b.go b/test/typeparam/mutualimp.dir/b.go new file mode 100644 index 0000000000..83cc3af283 --- /dev/null +++ b/test/typeparam/mutualimp.dir/b.go @@ -0,0 +1,12 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package b + +import "./a" + +func H() { + a.F[a.X, a.X]() + a.G() +} diff --git a/test/typeparam/mutualimp.go b/test/typeparam/mutualimp.go new file mode 100644 index 0000000000..87b4ff46c1 --- /dev/null +++ b/test/typeparam/mutualimp.go @@ -0,0 +1,7 @@ +// compiledir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From bcb3927cb51af39f44d810aab809dff27c950697 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 4 Jun 2021 23:01:13 -0700 Subject: [PATCH 0239/2500] [dev.typeparams] cmd/compile: introduce IsTypeParam() helper better than Kind() == types.TTYPEPARAM Change-Id: I4f35a177cd0cda3be615a92b7b2af1b5a60a3bbc Reviewed-on: https://go-review.googlesource.com/c/go/+/325410 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/helpers.go | 2 +- src/cmd/compile/internal/typecheck/iexport.go | 8 ++++---- src/cmd/compile/internal/typecheck/iimport.go | 2 +- src/cmd/compile/internal/typecheck/subr.go | 2 +- src/cmd/compile/internal/types/type.go | 4 ++++ 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index ea30a3bfa9..456df312a6 100644 --- a/src/cmd/compile/internal/noder/helpers.go +++ b/src/cmd/compile/internal/noder/helpers.go @@ -63,7 +63,7 @@ func FixValue(typ *types.Type, val constant.Value) constant.Value { if !typ.IsUntyped() { val = typecheck.DefaultLit(ir.NewBasicLit(src.NoXPos, val), typ).Val() } - if typ.Kind() != types.TTYPEPARAM { + if !typ.IsTypeParam() { ir.AssertValidTypeForConst(typ, val) } return val diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 6987bc9918..10d4bd6e7e 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -522,7 +522,7 @@ func (p *iexporter) doDecl(n *ir.Name) { } case ir.OTYPE: - if n.Type().Kind() == types.TTYPEPARAM && n.Type().Underlying() == n.Type() { + if n.Type().IsTypeParam() && n.Type().Underlying() == n.Type() { // Even though it has local scope, a typeparam requires a // declaration via its package and unique name, because it // may be referenced within its type bound during its own @@ -898,7 +898,7 @@ func (w *exportWriter) doTyp(t *types.Type) { // The 't.Underlying() == t' check is to confirm this is a base typeparam // type, rather than a defined type with typeparam underlying type, like: // type orderedAbs[T any] T - if t.Kind() == types.TTYPEPARAM && t.Underlying() == t { + if t.IsTypeParam() && t.Underlying() == t { assert(base.Flag.G > 0) if s.Pkg == types.BuiltinPkg || s.Pkg == ir.Pkgs.Unsafe { base.Fatalf("builtin type missing from typIndex: %v", t) @@ -1042,7 +1042,7 @@ func (w *exportWriter) typeList(ts []*types.Type) { func (w *exportWriter) tparamList(fs []*types.Field) { w.uint64(uint64(len(fs))) for _, f := range fs { - if f.Type.Kind() != types.TTYPEPARAM { + if !f.Type.IsTypeParam() { base.Fatalf("unexpected non-typeparam") } w.typ(f.Type) @@ -1095,7 +1095,7 @@ func (w *exportWriter) value(typ *types.Type, v constant.Value) { var kind constant.Kind var valType *types.Type - if typ.Kind() == types.TTYPEPARAM { + if typ.IsTypeParam() { // A constant will have a TYPEPARAM type if it appears in a place // where it must match that typeparam type (e.g. in a binary // operation with a variable of that typeparam type). If so, then diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index cafb18d7a8..6d42875f49 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -415,7 +415,7 @@ func (p *importReader) value(typ *types.Type) constant.Value { var kind constant.Kind var valType *types.Type - if typ.Kind() == types.TTYPEPARAM { + if typ.IsTypeParam() { // If a constant had a typeparam type, then we wrote out its // actual constant kind as well. kind = constant.Kind(p.int64()) diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 8ef49f91c8..e9a9a57126 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -984,7 +984,7 @@ func (ts *Tsubster) Typ(t *types.Type) *types.Type { return t } - if t.Kind() == types.TTYPEPARAM { + if t.IsTypeParam() { for i, tp := range ts.Tparams { if tp == t { return ts.Targs[i] diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index a3a6050c52..075009d6a3 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -1487,6 +1487,10 @@ func (t *Type) IsUnion() bool { return t.kind == TUNION } +func (t *Type) IsTypeParam() bool { + return t.kind == TTYPEPARAM +} + // IsEmptyInterface reports whether t is an empty interface type. func (t *Type) IsEmptyInterface() bool { return t.IsInterface() && t.AllMethods().Len() == 0 -- GitLab From cf4b6dc48eba807e7d85fb6ab30cbbbdb143c552 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 4 Jun 2021 22:54:08 -0700 Subject: [PATCH 0240/2500] [dev.typeparams] cmd/compile: allow conversions from type parameter to interface When converting from a type param to an interface, allow it if the type bound implements that interface. Query: some conversions go through this path, some use another path? The test does var i interface{foo()int} = x but i := (interface{foo()int})(x) works at tip. Change-Id: I84d497e5228c0e1d1c9d76ffebaedce09dc45e8e Reviewed-on: https://go-review.googlesource.com/c/go/+/325409 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/transform.go | 5 +- src/cmd/compile/internal/typecheck/subr.go | 12 ++++- test/typeparam/ifaceconv.go | 58 +++++++++++++++++++++ 3 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 test/typeparam/ifaceconv.go diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index a084f0b7be..946d335f07 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -437,7 +437,10 @@ func assignconvfn(n ir.Node, t *types.Type) ir.Node { return n } - op, _ := typecheck.Assignop(n.Type(), t) + op, why := typecheck.Assignop(n.Type(), t) + if op == ir.OXXX { + base.Fatalf("found illegal assignment %+v -> %+v; %s", n.Type(), t, why) + } r := ir.NewConvExpr(base.Pos, op, t, n) r.SetTypecheck(1) diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index e9a9a57126..0e306eaea8 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -723,13 +723,23 @@ func ifacelookdot(s *types.Sym, t *types.Type, ignorecase bool) (m *types.Field, return m, followptr } +// implements reports whether t implements the interface iface. t can be +// an interface, a type parameter, or a concrete type. If implements returns +// false, it stores a method of iface that is not implemented in *m. If the +// method name matches but the type is wrong, it additionally stores the type +// of the method (on t) in *samename. func implements(t, iface *types.Type, m, samename **types.Field, ptr *int) bool { t0 := t if t == nil { return false } - if t.IsInterface() { + if t.IsInterface() || t.IsTypeParam() { + if t.IsTypeParam() { + // A typeparam satisfies an interface if its type bound + // has all the methods of that interface. + t = t.Bound() + } i := 0 tms := t.AllMethods().Slice() for _, im := range iface.AllMethods().Slice() { diff --git a/test/typeparam/ifaceconv.go b/test/typeparam/ifaceconv.go new file mode 100644 index 0000000000..0b0776815c --- /dev/null +++ b/test/typeparam/ifaceconv.go @@ -0,0 +1,58 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test that we can convert type parameters to both empty +// and nonempty interfaces, and named and nonnamed versions +// thereof. + +package main + +import "fmt" + +type E interface{} + +func f[T any](x T) interface{} { + var i interface{} = x + return i +} +func g[T any](x T) E { + var i E = x + return i +} + +type C interface { + foo() int +} + +type myInt int + +func (x myInt) foo() int { + return int(x+1) +} + +func h[T C](x T) interface{foo() int} { + var i interface{foo()int} = x + return i +} +func i[T C](x T) C { + var i C = x + return i +} + +func main() { + if got, want := f[int](7), 7; got != want { + panic(fmt.Sprintf("got %d want %d", got, want)) + } + if got, want := g[int](7), 7; got != want { + panic(fmt.Sprintf("got %d want %d", got, want)) + } + if got, want := h[myInt](7).foo(), 8; got != want { + panic(fmt.Sprintf("got %d want %d", got, want)) + } + if got, want := i[myInt](7).foo(), 8; got != want { + panic(fmt.Sprintf("got %d want %d", got, want)) + } +} -- GitLab From b2ff3e82ba04f86c724b179d0c0d383da9767243 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Fri, 4 Jun 2021 15:18:35 -0400 Subject: [PATCH 0241/2500] [dev.fuzz] testing: fix documentation for fuzzminimizetime This removes redundancy for the default value. Fixes #46555 Change-Id: Ib62bd2d584ef82bef806d0fe2ce59957488e469e Reviewed-on: https://go-review.googlesource.com/c/go/+/325070 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Roland Shoemaker --- src/testing/fuzz.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 06f755b1ea..9f0bb1ec50 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -20,7 +20,7 @@ import ( func initFuzzFlags() { matchFuzz = flag.String("test.fuzz", "", "run the fuzz target matching `regexp`") flag.Var(&fuzzDuration, "test.fuzztime", "time to spend fuzzing; default is to run indefinitely") - flag.Var(&minimizeDuration, "test.fuzzminimizetime", "time to spend minimizing a value after finding a crash; default is to minimize for 60s") + flag.Var(&minimizeDuration, "test.fuzzminimizetime", "time to spend minimizing a value after finding a crash") fuzzCacheDir = flag.String("test.fuzzcachedir", "", "directory where interesting fuzzing inputs are stored") isFuzzWorker = flag.Bool("test.fuzzworker", false, "coordinate with the parent process to fuzz random values") } -- GitLab From ccfb0ce8df980599750db4fa56a8ab16202f1ba6 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 4 Jun 2021 17:19:09 -0700 Subject: [PATCH 0242/2500] [dev.typeparams] cmd/compile: convert generic values to interface type using dictionary When converting a variable of generic type to an interface, use the entry in the dictionary for the type field instead of using the compile-time type (which we only have when fully stenciling). Note: this isn't all the conversions. Conversions often get processed in the ir.OCALL case. Those aren't handled yet. Change-Id: I9a6a4c572e3c54a8e8efad98365184dbb94c4487 Reviewed-on: https://go-review.googlesource.com/c/go/+/325330 Trust: Keith Randall Trust: Dan Scales Reviewed-by: Dan Scales --- src/cmd/compile/internal/escape/escape.go | 7 +++ src/cmd/compile/internal/noder/stencil.go | 71 +++++++++++++++++++++-- 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/escape/escape.go b/src/cmd/compile/internal/escape/escape.go index 3ac7ff1ebe..842b0f4a7e 100644 --- a/src/cmd/compile/internal/escape/escape.go +++ b/src/cmd/compile/internal/escape/escape.go @@ -669,6 +669,13 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) { k = e.spill(k, n) } e.expr(k.note(n, "interface-converted"), n.X) + case ir.OEFACE: + n := n.(*ir.BinaryExpr) + // Note: n.X is not needed because it can never point to memory that might escape. + e.expr(k, n.Y) + case ir.OIDATA: + n := n.(*ir.UnaryExpr) + e.expr(k, n.X) case ir.OSLICE2ARRPTR: // the slice pointer flows directly to the result n := n.(*ir.ConvExpr) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 8b5a91f6d1..3e3de1908e 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -13,6 +13,7 @@ import ( "cmd/compile/internal/reflectdata" "cmd/compile/internal/typecheck" "cmd/compile/internal/types" + "cmd/internal/src" "fmt" "go/constant" ) @@ -496,10 +497,11 @@ func (g *irgen) getInstantiation(nameNode *ir.Name, targs []*types.Type, isMeth // Struct containing info needed for doing the substitution as we create the // instantiation of a generic function with specified type arguments. type subster struct { - g *irgen - isMethod bool // If a method is being instantiated - newf *ir.Func // Func node for the new stenciled function - ts typecheck.Tsubster + g *irgen + isMethod bool // If a method is being instantiated + newf *ir.Func // Func node for the new stenciled function + ts typecheck.Tsubster + dictionary *ir.Name // Name of dictionary variable } // genericSubst returns a new function with name newsym. The function is an @@ -573,6 +575,7 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []*type } dictionaryArg := types.NewField(gf.Pos(), dictionarySym, dictionaryType) dictionaryArg.Nname = dictionaryName + subst.dictionary = dictionaryName var args []*types.Field args = append(args, dictionaryArg) args = append(args, oldt.Recvs().FieldSlice()...) @@ -656,6 +659,38 @@ func (g *irgen) checkDictionary(name *ir.Name, targs []*types.Type) (code []ir.N return } +// getDictionaryType returns a *runtime._type from the dictionary corresponding to the input type. +// The input type must be a type parameter (TODO: or a local derived type). +func (subst *subster) getDictionaryType(pos src.XPos, t *types.Type) ir.Node { + tparams := subst.ts.Tparams + var i = 0 + for i = range tparams { + if t == tparams[i] { + break + } + } + if i == len(tparams) { + base.Fatalf(fmt.Sprintf("couldn't find type param %+v", t)) + } + + // Convert dictionary to *[N]uintptr + // All entries in the dictionary are pointers. They all point to static data, though, so we + // treat them as uintptrs so the GC doesn't need to keep track of them. + d := ir.NewConvExpr(pos, ir.OCONVNOP, types.Types[types.TUNSAFEPTR], subst.dictionary) + d.SetTypecheck(1) + d = ir.NewConvExpr(pos, ir.OCONVNOP, types.NewArray(types.Types[types.TUINTPTR], int64(len(tparams))).PtrTo(), d) + d.SetTypecheck(1) + + // Load entry i out of the dictionary. + deref := ir.NewStarExpr(pos, d) + typed(d.Type().Elem(), deref) + idx := ir.NewConstExpr(constant.MakeUint64(uint64(i)), subst.dictionary) // TODO: what to set orig to? + typed(types.Types[types.TUINTPTR], idx) + r := ir.NewIndexExpr(pos, deref, idx) + typed(types.Types[types.TUINT8].PtrTo(), r) // standard typing of a *runtime._type in the compiler is *byte + return r +} + // node is like DeepCopy(), but substitutes ONAME nodes based on subst.ts.vars, and // also descends into closures. It substitutes type arguments for type parameters // in all the new nodes. @@ -859,6 +894,34 @@ func (subst *subster) node(n ir.Node) ir.Node { ir.CurFunc = saveNewf subst.g.target.Decls = append(subst.g.target.Decls, newfn) + + case ir.OCONVIFACE: + x := x.(*ir.ConvExpr) + // TODO: handle converting from derived types. For now, just from naked + // type parameters. + if x.X.Type().IsTypeParam() { + // Load the actual runtime._type of the type parameter from the dictionary. + rt := subst.getDictionaryType(m.Pos(), x.X.Type()) + + // At this point, m is an interface type with a data word we want. + // But the type word represents a gcshape type, which we don't want. + // Replace with the instantiated type loaded from the dictionary. + m = ir.NewUnaryExpr(m.Pos(), ir.OIDATA, m) + typed(types.Types[types.TUNSAFEPTR], m) + m = ir.NewBinaryExpr(m.Pos(), ir.OEFACE, rt, m) + if !x.Type().IsEmptyInterface() { + // We just built an empty interface{}. Type it as such, + // then assert it to the required non-empty interface. + typed(types.NewInterface(types.LocalPkg, nil), m) + m = ir.NewTypeAssertExpr(m.Pos(), m, nil) + } + typed(x.Type(), m) + // TODO: we're throwing away the type word of the original version + // of m here (it would be OITAB(m)), which probably took some + // work to generate. Can we avoid generating it at all? + // (The linker will throw them away if not needed, so it would just + // save toolchain work, not binary size.) + } } return m } -- GitLab From 74d46381b2003f7d77bbe6eb4a8a31cb6f753a09 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Fri, 4 Jun 2021 15:22:55 -0700 Subject: [PATCH 0243/2500] [dev.typeparams] cmd/compile: do extra markObjects during iexport to deal with generics markInlBody/markObject/markType don't fully work as they stand for generic functions/methods, since markInlBody can't understand method calls on generic types. Those method calls will be resolved to concrete methods in a full instantiation, but markInlBody on a generic function/method can't understand those method calls. So, we won't necessarily cause export of the appropriate extra method/function bodies needed for inlining in an instantiated function. One way to do this is just to make sure that we call markType on all generic types that are exported (whether explicitly exported via a capitalized name or unexported types that are referenced by a generic function body). That way, we will call markInlBody on all possible generic methods that might be called. Fixes the current problem for i386-softfloat builds on dev.typeparams. Change-Id: I2d3625d26042296731bd3c44ba1938aa194d527e Reviewed-on: https://go-review.googlesource.com/c/go/+/325329 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky Trust: Dan Scales --- src/cmd/compile/internal/typecheck/crawler.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/typecheck/crawler.go b/src/cmd/compile/internal/typecheck/crawler.go index 48fc61dbfd..c78a604a8d 100644 --- a/src/cmd/compile/internal/typecheck/crawler.go +++ b/src/cmd/compile/internal/typecheck/crawler.go @@ -146,7 +146,9 @@ func (p *crawler) markInlBody(n *ir.Name) { case ir.PEXTERN: Export(n) } - + p.checkGenericType(n.Type()) + case ir.OTYPE: + p.checkGenericType(n.Type()) case ir.OCALLPART: // Okay, because we don't yet inline indirect // calls to method values. @@ -162,3 +164,16 @@ func (p *crawler) markInlBody(n *ir.Name) { // because after inlining they might be callable. ir.VisitList(fn.Inl.Body, doFlood) } + +// checkGenerictype ensures that we call markType() on any base generic type that +// is written to the export file (even if not explicitly marked +// for export), so its methods will be available for inlining if needed. +func (p *crawler) checkGenericType(t *types.Type) { + if t != nil && t.HasTParam() { + if t.OrigSym != nil { + // Convert to the base generic type. + t = t.OrigSym.Def.Type() + } + p.markType(t) + } +} -- GitLab From 0c40cb4a0736df4514c5e5f35fdbb87c0543fe6f Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 4 Jun 2021 21:38:40 -0700 Subject: [PATCH 0244/2500] [dev.typeparams] cmd/compile/internal/types2: provide valid signature in errors involving method expressions This is an adjusted port of a similar fix in https://golang.org/cl/324733. Fixes #46583. Change-Id: Ica1410e4de561e64e58b753e3da04b32156cbaf6 Reviewed-on: https://go-review.googlesource.com/c/go/+/325369 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/call.go | 20 +++++++++++-- .../types2/testdata/fixedbugs/issue46583.src | 28 +++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue46583.src diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index f0f769ec70..8c717cd1e5 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -582,13 +582,27 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) { goto Error } - // the receiver type becomes the type of the first function - // argument of the method expression's function type + // The receiver type becomes the type of the first function + // argument of the method expression's function type. var params []*Var if sig.params != nil { params = sig.params.vars } - params = append([]*Var{NewVar(sig.recv.pos, sig.recv.pkg, sig.recv.name, x.typ)}, params...) + // Be consistent about named/unnamed parameters. This is not needed + // for type-checking, but the newly constructed signature may appear + // in an error message and then have mixed named/unnamed parameters. + // (An alternative would be to not print parameter names in errors, + // but it's useful to see them; this is cheap and method expressions + // are rare.) + name := "" + if len(params) > 0 && params[0].name != "" { + // name needed + name = sig.recv.name + if name == "" { + name = "_" + } + } + params = append([]*Var{NewVar(sig.recv.pos, sig.recv.pkg, name, x.typ)}, params...) x.mode = value x.typ = &Signature{ tparams: sig.tparams, diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46583.src b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46583.src new file mode 100644 index 0000000000..da1f1ffbba --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46583.src @@ -0,0 +1,28 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T1 struct{} +func (t T1) m(int) {} +var f1 func(T1) + +type T2 struct{} +func (t T2) m(x int) {} +var f2 func(T2) + +type T3 struct{} +func (T3) m(int) {} +var f3 func(T3) + +type T4 struct{} +func (T4) m(x int) {} +var f4 func(T4) + +func _() { + f1 = T1 /* ERROR func\(T1, int\) */ .m + f2 = T2 /* ERROR func\(t T2, x int\) */ .m + f3 = T3 /* ERROR func\(T3, int\) */ .m + f4 = T4 /* ERROR func\(_ T4, x int\) */ .m +} -- GitLab From e58bddde706c8814f82ec4ef404fc7ff36d88469 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Mon, 7 Jun 2021 18:22:14 -0400 Subject: [PATCH 0245/2500] [dev.typeparams] internal/goexperiment: regenerate generated files Rerun the generator. exp_regabi_{on,off}.go are gone, as "regabi" itself is not a goexperiment that we test at run time (the sub-experiments are). Change-Id: Ic1f31b4ef2769a143f768e1b3dc7221041aafca9 Reviewed-on: https://go-review.googlesource.com/c/go/+/325912 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/internal/goexperiment/exp_regabi_off.go | 9 --------- src/internal/goexperiment/exp_regabi_on.go | 9 --------- 2 files changed, 18 deletions(-) delete mode 100644 src/internal/goexperiment/exp_regabi_off.go delete mode 100644 src/internal/goexperiment/exp_regabi_on.go diff --git a/src/internal/goexperiment/exp_regabi_off.go b/src/internal/goexperiment/exp_regabi_off.go deleted file mode 100644 index 5d8823843d..0000000000 --- a/src/internal/goexperiment/exp_regabi_off.go +++ /dev/null @@ -1,9 +0,0 @@ -// Code generated by mkconsts.go. DO NOT EDIT. - -//go:build !goexperiment.regabi -// +build !goexperiment.regabi - -package goexperiment - -const Regabi = false -const RegabiInt = 0 diff --git a/src/internal/goexperiment/exp_regabi_on.go b/src/internal/goexperiment/exp_regabi_on.go deleted file mode 100644 index c08d58e9b2..0000000000 --- a/src/internal/goexperiment/exp_regabi_on.go +++ /dev/null @@ -1,9 +0,0 @@ -// Code generated by mkconsts.go. DO NOT EDIT. - -//go:build goexperiment.regabi -// +build goexperiment.regabi - -package goexperiment - -const Regabi = true -const RegabiInt = 1 -- GitLab From a9de78ac88ff668bbe8c0dc5fdc9dc864ae60447 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 4 Jun 2021 13:53:18 -0400 Subject: [PATCH 0246/2500] [dev.typeparams] cmd/compile, runtime: always enable defer/go wrapping Hardwire regabidefers to true. Remove it from GOEXPERIMENTs. Fallback paths are not cleaned up in this CL. That will be done in later CLs. Change-Id: Iec1112a1e55d5f6ef70232a5ff6e702f649071c4 Reviewed-on: https://go-review.googlesource.com/c/go/+/325913 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek Reviewed-by: Than McIntosh --- src/cmd/compile/internal/ssagen/ssa.go | 4 ++-- src/cmd/compile/internal/walk/order.go | 5 +---- src/internal/buildcfg/exp.go | 6 ++---- .../goexperiment/exp_regabidefer_off.go | 9 --------- .../goexperiment/exp_regabidefer_on.go | 9 --------- src/internal/goexperiment/flags.go | 3 --- src/runtime/panic.go | 19 +++++++++---------- src/runtime/proc.go | 3 +-- test/live.go | 2 +- test/live_regabi.go | 2 +- 10 files changed, 17 insertions(+), 45 deletions(-) delete mode 100644 src/internal/goexperiment/exp_regabidefer_off.go delete mode 100644 src/internal/goexperiment/exp_regabidefer_on.go diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index f59220ab8e..106ce8d6c5 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -4696,7 +4696,7 @@ func (s *state) openDeferRecord(n *ir.CallExpr) { var args []*ssa.Value var argNodes []*ir.Name - if buildcfg.Experiment.RegabiDefer && (len(n.Args) != 0 || n.Op() == ir.OCALLINTER || n.X.Type().NumResults() != 0) { + if len(n.Args) != 0 || n.Op() == ir.OCALLINTER || n.X.Type().NumResults() != 0 { s.Fatalf("defer call with arguments or results: %v", n) } @@ -4951,7 +4951,7 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val } } - if buildcfg.Experiment.RegabiDefer && k != callNormal && (len(n.Args) != 0 || n.Op() == ir.OCALLINTER || n.X.Type().NumResults() != 0) { + if k != callNormal && (len(n.Args) != 0 || n.Op() == ir.OCALLINTER || n.X.Type().NumResults() != 0) { s.Fatalf("go/defer call with arguments: %v", n) } diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go index 19d9551566..d1fd3a9b73 100644 --- a/src/cmd/compile/internal/walk/order.go +++ b/src/cmd/compile/internal/walk/order.go @@ -7,7 +7,6 @@ package walk import ( "fmt" "go/constant" - "internal/buildcfg" "cmd/compile/internal/base" "cmd/compile/internal/escape" @@ -790,9 +789,7 @@ func (o *orderState) stmt(n ir.Node) { n.Call = walkRecover(n.Call.(*ir.CallExpr), &init) o.stmtList(init) } - if buildcfg.Experiment.RegabiDefer { - o.wrapGoDefer(n) - } + o.wrapGoDefer(n) o.out = append(o.out, n) o.cleanTemp(t) diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go index 38a2045639..9402da2ebf 100644 --- a/src/internal/buildcfg/exp.go +++ b/src/internal/buildcfg/exp.go @@ -30,7 +30,6 @@ var experimentBaseline = goexperiment.Flags{ RegabiWrappers: regabiSupported, RegabiG: regabiSupported, RegabiReflect: regabiSupported, - RegabiDefer: true, RegabiArgs: regabiSupported, } @@ -70,7 +69,6 @@ func parseExperiments() goexperiment.Flags { flags.RegabiWrappers = v flags.RegabiG = v flags.RegabiReflect = v - flags.RegabiDefer = v flags.RegabiArgs = v } @@ -110,8 +108,8 @@ func parseExperiments() goexperiment.Flags { if flags.RegabiG && !flags.RegabiWrappers { Error = fmt.Errorf("GOEXPERIMENT regabig requires regabiwrappers") } - if flags.RegabiArgs && !(flags.RegabiWrappers && flags.RegabiG && flags.RegabiReflect && flags.RegabiDefer) { - Error = fmt.Errorf("GOEXPERIMENT regabiargs requires regabiwrappers,regabig,regabireflect,regabidefer") + if flags.RegabiArgs && !(flags.RegabiWrappers && flags.RegabiG && flags.RegabiReflect) { + Error = fmt.Errorf("GOEXPERIMENT regabiargs requires regabiwrappers,regabig,regabireflect") } return flags } diff --git a/src/internal/goexperiment/exp_regabidefer_off.go b/src/internal/goexperiment/exp_regabidefer_off.go deleted file mode 100644 index b47c0c2cf5..0000000000 --- a/src/internal/goexperiment/exp_regabidefer_off.go +++ /dev/null @@ -1,9 +0,0 @@ -// Code generated by mkconsts.go. DO NOT EDIT. - -//go:build !goexperiment.regabidefer -// +build !goexperiment.regabidefer - -package goexperiment - -const RegabiDefer = false -const RegabiDeferInt = 0 diff --git a/src/internal/goexperiment/exp_regabidefer_on.go b/src/internal/goexperiment/exp_regabidefer_on.go deleted file mode 100644 index bbf2f6c69b..0000000000 --- a/src/internal/goexperiment/exp_regabidefer_on.go +++ /dev/null @@ -1,9 +0,0 @@ -// Code generated by mkconsts.go. DO NOT EDIT. - -//go:build goexperiment.regabidefer -// +build goexperiment.regabidefer - -package goexperiment - -const RegabiDefer = true -const RegabiDeferInt = 1 diff --git a/src/internal/goexperiment/flags.go b/src/internal/goexperiment/flags.go index cd4c178818..c20dbcd9f5 100644 --- a/src/internal/goexperiment/flags.go +++ b/src/internal/goexperiment/flags.go @@ -78,9 +78,6 @@ type Flags struct { // reflect and runtime (which are disabled by default) so it // can be used in targeted tests. RegabiReflect bool - // RegabiDefer enables desugaring defer and go calls - // into argument-less closures. - RegabiDefer bool // RegabiArgs enables register arguments/results in all // compiled Go functions. // diff --git a/src/runtime/panic.go b/src/runtime/panic.go index f6c38aafcc..e73d59c136 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -6,7 +6,6 @@ package runtime import ( "internal/abi" - "internal/goexperiment" "runtime/internal/atomic" "runtime/internal/sys" "unsafe" @@ -236,7 +235,7 @@ func deferproc(siz int32, fn *funcval) { // arguments of fn follow fn throw("defer on system stack") } - if goexperiment.RegabiDefer && siz != 0 { + if true && siz != 0 { // TODO: Make deferproc just take a func(). throw("defer with non-empty frame") } @@ -293,7 +292,7 @@ func deferprocStack(d *_defer) { // go code on the system stack can't defer throw("defer on system stack") } - if goexperiment.RegabiDefer && d.siz != 0 { + if true && d.siz != 0 { throw("defer with non-empty frame") } // siz and fn are already set. @@ -395,7 +394,7 @@ func deferArgs(d *_defer) unsafe.Pointer { // that experiment, we should change the type of d.fn. //go:nosplit func deferFunc(d *_defer) func() { - if !goexperiment.RegabiDefer { + if false { throw("requires GOEXPERIMENT=regabidefer") } var fn func() @@ -655,7 +654,7 @@ func Goexit() { addOneOpenDeferFrame(gp, 0, nil) } } else { - if goexperiment.RegabiDefer { + if true { // Save the pc/sp in deferCallSave(), so we can "recover" back to this // loop if necessary. deferCallSave(&p, deferFunc(d)) @@ -857,7 +856,7 @@ func runOpenDeferFrame(gp *g, d *_defer) bool { argWidth, fd = readvarintUnsafe(fd) closureOffset, fd = readvarintUnsafe(fd) nArgs, fd = readvarintUnsafe(fd) - if goexperiment.RegabiDefer && argWidth != 0 { + if true && argWidth != 0 { throw("defer with non-empty frame") } if deferBits&(1< Date: Fri, 4 Jun 2021 16:32:03 -0400 Subject: [PATCH 0247/2500] [dev.typeparams] cmd/compile: remove variadic defer calls Now that defer wrapping is used, deferred function is always argumentless. Remove the code handling arguments. This CL is mostly removing the fallback code path. There are more cleanups to be done, in later CLs. Change-Id: If6c729d3055c7a507cb1f1a000f5bbd3ad7ff235 Reviewed-on: https://go-review.googlesource.com/c/go/+/325914 Trust: Cherry Mui Reviewed-by: Than McIntosh --- src/cmd/compile/internal/ssagen/ssa.go | 178 ++++--------------------- 1 file changed, 29 insertions(+), 149 deletions(-) diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 106ce8d6c5..6479346845 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -359,31 +359,8 @@ func (s *state) emitOpenDeferInfo() { r := s.openDefers[i] off = dvarint(x, off, r.n.X.Type().ArgWidth()) off = dvarint(x, off, -r.closureNode.FrameOffset()) - numArgs := len(r.argNodes) - if r.rcvrNode != nil { - // If there's an interface receiver, treat/place it as the first - // arg. (If there is a method receiver, it's already included as - // first arg in r.argNodes.) - numArgs++ - } + numArgs := 0 off = dvarint(x, off, int64(numArgs)) - argAdjust := 0 // presence of receiver offsets the parameter count. - if r.rcvrNode != nil { - off = dvarint(x, off, -okOffset(r.rcvrNode.FrameOffset())) - off = dvarint(x, off, s.config.PtrSize) - off = dvarint(x, off, 0) // This is okay because defer records use ABI0 (for now) - argAdjust++ - } - - // TODO(register args) assume abi0 for this? - ab := s.f.ABI0 - pri := ab.ABIAnalyzeFuncType(r.n.X.Type().FuncType()) - for j, arg := range r.argNodes { - f := getParam(r.n, j) - off = dvarint(x, off, -okOffset(arg.FrameOffset())) - off = dvarint(x, off, f.Type.Size()) - off = dvarint(x, off, okOffset(pri.InParam(j+argAdjust).FrameOffset(pri))) - } } } @@ -864,16 +841,6 @@ type openDeferInfo struct { // function, method, or interface call, to store a closure that panic // processing can use for this defer. closureNode *ir.Name - // If defer call is interface call, the address of the argtmp where the - // receiver is stored - rcvr *ssa.Value - // The node representing the argtmp where the receiver is stored - rcvrNode *ir.Name - // The addresses of the argtmps where the evaluated arguments of the defer - // function call are stored. - argVals []*ssa.Value - // The nodes representing the argtmps where the args of the defer are stored - argNodes []*ir.Name } type state struct { @@ -4686,17 +4653,14 @@ func (s *state) intrinsicArgs(n *ir.CallExpr) []*ssa.Value { return args } -// openDeferRecord adds code to evaluate and store the args for an open-code defer +// openDeferRecord adds code to evaluate and store the function for an open-code defer // call, and records info about the defer, so we can generate proper code on the // exit paths. n is the sub-node of the defer node that is the actual function -// call. We will also record funcdata information on where the args are stored +// call. We will also record funcdata information on where the function is stored // (as well as the deferBits variable), and this will enable us to run the proper // defer calls during panics. func (s *state) openDeferRecord(n *ir.CallExpr) { - var args []*ssa.Value - var argNodes []*ir.Name - - if len(n.Args) != 0 || n.Op() == ir.OCALLINTER || n.X.Type().NumResults() != 0 { + if len(n.Args) != 0 || n.Op() != ir.OCALLFUNC || n.X.Type().NumResults() != 0 { s.Fatalf("defer call with arguments or results: %v", n) } @@ -4704,48 +4668,20 @@ func (s *state) openDeferRecord(n *ir.CallExpr) { n: n, } fn := n.X - if n.Op() == ir.OCALLFUNC { - // We must always store the function value in a stack slot for the - // runtime panic code to use. But in the defer exit code, we will - // call the function directly if it is a static function. - closureVal := s.expr(fn) - closure := s.openDeferSave(nil, fn.Type(), closureVal) - opendefer.closureNode = closure.Aux.(*ir.Name) - if !(fn.Op() == ir.ONAME && fn.(*ir.Name).Class == ir.PFUNC) { - opendefer.closure = closure - } - } else if n.Op() == ir.OCALLMETH { - base.Fatalf("OCALLMETH missed by walkCall") - } else { - if fn.Op() != ir.ODOTINTER { - base.Fatalf("OCALLINTER: n.Left not an ODOTINTER: %v", fn.Op()) - } - fn := fn.(*ir.SelectorExpr) - closure, rcvr := s.getClosureAndRcvr(fn) - opendefer.closure = s.openDeferSave(nil, closure.Type, closure) - // Important to get the receiver type correct, so it is recognized - // as a pointer for GC purposes. - opendefer.rcvr = s.openDeferSave(nil, fn.Type().Recv().Type, rcvr) - opendefer.closureNode = opendefer.closure.Aux.(*ir.Name) - opendefer.rcvrNode = opendefer.rcvr.Aux.(*ir.Name) - } - for _, argn := range n.Args { - var v *ssa.Value - if TypeOK(argn.Type()) { - v = s.openDeferSave(nil, argn.Type(), s.expr(argn)) - } else { - v = s.openDeferSave(argn, argn.Type(), nil) - } - args = append(args, v) - argNodes = append(argNodes, v.Aux.(*ir.Name)) + // We must always store the function value in a stack slot for the + // runtime panic code to use. But in the defer exit code, we will + // call the function directly if it is a static function. + closureVal := s.expr(fn) + closure := s.openDeferSave(nil, fn.Type(), closureVal) + opendefer.closureNode = closure.Aux.(*ir.Name) + if !(fn.Op() == ir.ONAME && fn.(*ir.Name).Class == ir.PFUNC) { + opendefer.closure = closure } - opendefer.argVals = args - opendefer.argNodes = argNodes index := len(s.openDefers) s.openDefers = append(s.openDefers, opendefer) // Update deferBits only after evaluation and storage to stack of - // args/receiver/interface is successful. + // the function is successful. bitvalue := s.constInt8(types.Types[types.TUINT8], 1< Date: Fri, 4 Jun 2021 17:04:46 -0400 Subject: [PATCH 0248/2500] [dev.typeparams] runtime: remove variadic defer/go calls Now that defer/go wrapping is used, deferred/go'd functions are always argumentless. Remove the code handling arguments. This CL is mostly removing the fallback code path. There are more cleanups to be done, in later CLs. Change-Id: I87bfd3fb2d759fbeb6487b8125c0f6992863d6e5 Reviewed-on: https://go-review.googlesource.com/c/go/+/325915 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/cmd/compile/internal/test/inl_test.go | 1 - src/cmd/internal/objabi/funcid.go | 1 - src/runtime/panic.go | 113 ++-------------------- src/runtime/proc.go | 34 +------ src/runtime/traceback.go | 9 +- 5 files changed, 16 insertions(+), 142 deletions(-) diff --git a/src/cmd/compile/internal/test/inl_test.go b/src/cmd/compile/internal/test/inl_test.go index ad4e4fee97..5b0db83301 100644 --- a/src/cmd/compile/internal/test/inl_test.go +++ b/src/cmd/compile/internal/test/inl_test.go @@ -42,7 +42,6 @@ func TestIntendedInlining(t *testing.T) { "bucketMask", "bucketShift", "chanbuf", - "deferArgs", "deferclass", "evacuated", "fastlog2", diff --git a/src/cmd/internal/objabi/funcid.go b/src/cmd/internal/objabi/funcid.go index 93ebd7be94..d881cdd061 100644 --- a/src/cmd/internal/objabi/funcid.go +++ b/src/cmd/internal/objabi/funcid.go @@ -74,7 +74,6 @@ var funcIDs = map[string]FuncID{ // Don't show in call stack but otherwise not special. "deferreturn": FuncID_wrapper, "runOpenDeferFrame": FuncID_wrapper, - "reflectcallSave": FuncID_wrapper, "deferCallSave": FuncID_wrapper, } diff --git a/src/runtime/panic.go b/src/runtime/panic.go index e73d59c136..8a296a3c17 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -5,7 +5,6 @@ package runtime import ( - "internal/abi" "runtime/internal/atomic" "runtime/internal/sys" "unsafe" @@ -235,7 +234,7 @@ func deferproc(siz int32, fn *funcval) { // arguments of fn follow fn throw("defer on system stack") } - if true && siz != 0 { + if siz != 0 { // TODO: Make deferproc just take a func(). throw("defer with non-empty frame") } @@ -246,10 +245,9 @@ func deferproc(siz int32, fn *funcval) { // arguments of fn follow fn // to somewhere safe. The memmove below does that. // Until the copy completes, we can only call nosplit routines. sp := getcallersp() - argp := uintptr(unsafe.Pointer(&fn)) + unsafe.Sizeof(fn) callerpc := getcallerpc() - d := newdefer(siz) + d := newdefer(0) if d._panic != nil { throw("deferproc: d.panic != nil after newdefer") } @@ -258,14 +256,6 @@ func deferproc(siz int32, fn *funcval) { // arguments of fn follow fn d.fn = fn d.pc = callerpc d.sp = sp - switch siz { - case 0: - // Do nothing. - case sys.PtrSize: - *(*uintptr)(deferArgs(d)) = *(*uintptr)(unsafe.Pointer(argp)) - default: - memmove(deferArgs(d), unsafe.Pointer(argp), uintptr(siz)) - } // deferproc returns 0 normally. // a deferred func that stops a panic @@ -292,7 +282,7 @@ func deferprocStack(d *_defer) { // go code on the system stack can't defer throw("defer on system stack") } - if true && d.siz != 0 { + if d.siz != 0 { throw("defer with non-empty frame") } // siz and fn are already set. @@ -378,25 +368,11 @@ func testdefersizes() { } } -// The arguments associated with a deferred call are stored -// immediately after the _defer header in memory. -//go:nosplit -func deferArgs(d *_defer) unsafe.Pointer { - if d.siz == 0 { - // Avoid pointer past the defer allocation. - return nil - } - return add(unsafe.Pointer(d), unsafe.Sizeof(*d)) -} - // deferFunc returns d's deferred function. This is temporary while we // support both modes of GOEXPERIMENT=regabidefer. Once we commit to // that experiment, we should change the type of d.fn. //go:nosplit func deferFunc(d *_defer) func() { - if false { - throw("requires GOEXPERIMENT=regabidefer") - } var fn func() *(**funcval)(unsafe.Pointer(&fn)) = d.fn return fn @@ -575,14 +551,6 @@ func deferreturn() { // of the arguments until the jmpdefer can flip the PC over to // fn. argp := getcallersp() + sys.MinFrameSize - switch d.siz { - case 0: - // Do nothing. - case sys.PtrSize: - *(*uintptr)(unsafe.Pointer(argp)) = *(*uintptr)(deferArgs(d)) - default: - memmove(unsafe.Pointer(argp), deferArgs(d), uintptr(d.siz)) - } fn := d.fn d.fn = nil gp._defer = d.link @@ -654,15 +622,9 @@ func Goexit() { addOneOpenDeferFrame(gp, 0, nil) } } else { - if true { - // Save the pc/sp in deferCallSave(), so we can "recover" back to this - // loop if necessary. - deferCallSave(&p, deferFunc(d)) - } else { - // Save the pc/sp in reflectcallSave(), so we can "recover" back to this - // loop if necessary. - reflectcallSave(&p, unsafe.Pointer(d.fn), deferArgs(d), uint32(d.siz)) - } + // Save the pc/sp in deferCallSave(), so we can "recover" back to this + // loop if necessary. + deferCallSave(&p, deferFunc(d)) } if p.aborted { // We had a recursive panic in the defer d we started, and @@ -856,7 +818,7 @@ func runOpenDeferFrame(gp *g, d *_defer) bool { argWidth, fd = readvarintUnsafe(fd) closureOffset, fd = readvarintUnsafe(fd) nArgs, fd = readvarintUnsafe(fd) - if true && argWidth != 0 { + if argWidth != 0 || nArgs != 0 { throw("defer with non-empty frame") } if deferBits&(1<= _StackMin-4*sys.PtrSize-sys.PtrSize { - throw("newproc: function arguments too large for new goroutine") - } _p_ := _g_.m.p.ptr() newg := gfget(_p_) @@ -4299,8 +4289,8 @@ func newproc1(fn *funcval, argp unsafe.Pointer, narg int32, callergp *g, callerp throw("newproc1: new g is not Gdead") } - totalSize := 4*sys.PtrSize + uintptr(siz) + sys.MinFrameSize // extra space in case of reads slightly beyond frame - totalSize += -totalSize & (sys.StackAlign - 1) // align to StackAlign + totalSize := uintptr(4*sys.PtrSize + sys.MinFrameSize) // extra space in case of reads slightly beyond frame + totalSize = alignUp(totalSize, sys.StackAlign) sp := newg.stack.hi - totalSize spArg := sp if usesLR { @@ -4309,24 +4299,6 @@ func newproc1(fn *funcval, argp unsafe.Pointer, narg int32, callergp *g, callerp prepGoExitFrame(sp) spArg += sys.MinFrameSize } - if narg > 0 { - memmove(unsafe.Pointer(spArg), argp, uintptr(narg)) - // This is a stack-to-stack copy. If write barriers - // are enabled and the source stack is grey (the - // destination is always black), then perform a - // barrier copy. We do this *after* the memmove - // because the destination stack may have garbage on - // it. - if writeBarrier.needed && !_g_.m.curg.gcscandone { - f := findfunc(fn.fn) - stkmap := (*stackmap)(funcdata(f, _FUNCDATA_ArgsPointerMaps)) - if stkmap.nbit > 0 { - // We're in the prologue, so it's always stack map index 0. - bv := stackmapdata(stkmap, 0) - bulkBarrierBitmap(spArg, spArg, uintptr(bv.n)*sys.PtrSize, 0, bv.bytedata) - } - } - } memclrNoHeapPointers(unsafe.Pointer(&newg.sched), unsafe.Sizeof(newg.sched)) newg.sched.sp = sp diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go index 89780edc1f..2564273a53 100644 --- a/src/runtime/traceback.go +++ b/src/runtime/traceback.go @@ -42,12 +42,9 @@ func tracebackdefers(gp *g, callback func(*stkframe, unsafe.Pointer) bool, v uns throw("unknown pc") } frame.fn = f - frame.argp = uintptr(deferArgs(d)) - var ok bool - frame.arglen, frame.argmap, ok = getArgInfoFast(f, true) - if !ok { - frame.arglen, frame.argmap = getArgInfo(&frame, f, true, fn) - } + frame.argp = 0 + frame.arglen = 0 + frame.argmap = nil } frame.continpc = frame.pc if !callback((*stkframe)(noescape(unsafe.Pointer(&frame))), v) { -- GitLab From 00d01b57866d4b052c3b75706bbc8601167ead7c Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 4 Jun 2021 17:18:09 -0400 Subject: [PATCH 0249/2500] [dev.typeparams] runtime: remove tracebackdefers tracebackdefers is used for scanning/copying deferred functions' arguments. Now that deferred functions are always argumentless, it does nothing. Remove. Change-Id: I55bedabe5584ea41a12cdb03d55ec9692a5aacd9 Reviewed-on: https://go-review.googlesource.com/c/go/+/325916 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/runtime/mgcmark.go | 7 ++----- src/runtime/stack.go | 5 ----- src/runtime/traceback.go | 32 -------------------------------- 3 files changed, 2 insertions(+), 42 deletions(-) diff --git a/src/runtime/mgcmark.go b/src/runtime/mgcmark.go index 1fd0732d62..eb70ae9f49 100644 --- a/src/runtime/mgcmark.go +++ b/src/runtime/mgcmark.go @@ -750,14 +750,11 @@ func scanstack(gp *g, gcw *gcWork) { // Find additional pointers that point into the stack from the heap. // Currently this includes defers and panics. See also function copystack. - // Find and trace all defer arguments. - tracebackdefers(gp, scanframe, nil) - // Find and trace other pointers in defer records. for d := gp._defer; d != nil; d = d.link { if d.fn != nil { - // tracebackdefers above does not scan the func value, which could - // be a stack allocated closure. See issue 30453. + // Scan the func value, which could be a stack allocated closure. + // See issue 30453. scanblock(uintptr(unsafe.Pointer(&d.fn)), sys.PtrSize, &oneptrmask[0], gcw, &state) } if d.link != nil { diff --git a/src/runtime/stack.go b/src/runtime/stack.go index a1182b00bd..b5545ac796 100644 --- a/src/runtime/stack.go +++ b/src/runtime/stack.go @@ -753,11 +753,6 @@ func adjustdefers(gp *g, adjinfo *adjustinfo) { adjustpointer(adjinfo, unsafe.Pointer(&d.varp)) adjustpointer(adjinfo, unsafe.Pointer(&d.fd)) } - - // Adjust defer argument blocks the same way we adjust active stack frames. - // Note: this code is after the loop above, so that if a defer record is - // stack allocated, we work on the copy in the new stack. - tracebackdefers(gp, adjustframe, noescape(unsafe.Pointer(adjinfo))) } func adjustpanics(gp *g, adjinfo *adjustinfo) { diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go index 2564273a53..3fc9d07fc5 100644 --- a/src/runtime/traceback.go +++ b/src/runtime/traceback.go @@ -21,38 +21,6 @@ import ( const usesLR = sys.MinFrameSize > 0 -// Traceback over the deferred function calls. -// Report them like calls that have been invoked but not started executing yet. -func tracebackdefers(gp *g, callback func(*stkframe, unsafe.Pointer) bool, v unsafe.Pointer) { - var frame stkframe - for d := gp._defer; d != nil; d = d.link { - fn := d.fn - if fn == nil { - // Defer of nil function. Args don't matter. - frame.pc = 0 - frame.fn = funcInfo{} - frame.argp = 0 - frame.arglen = 0 - frame.argmap = nil - } else { - frame.pc = fn.fn - f := findfunc(frame.pc) - if !f.valid() { - print("runtime: unknown pc in defer ", hex(frame.pc), "\n") - throw("unknown pc") - } - frame.fn = f - frame.argp = 0 - frame.arglen = 0 - frame.argmap = nil - } - frame.continpc = frame.pc - if !callback((*stkframe)(noescape(unsafe.Pointer(&frame))), v) { - return - } - } -} - const sizeofSkipFunction = 256 // Generic traceback. Handles runtime stack prints (pcbuf == nil), -- GitLab From 965b1147549ef28a407bd4e8f5efe5e7b7616f80 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Mon, 7 Jun 2021 17:25:21 -0700 Subject: [PATCH 0250/2500] internal/fuzz: use consistent log format Match the existing "fuzzing, ..." logging style for debug logs, so that processing everything is considerably simpler. Change-Id: I4da4071700b3d9f8fb1ebf0c2de91ac693fd492f Reviewed-on: https://go-review.googlesource.com/c/go/+/325876 Reviewed-by: Katie Hockman Trust: Katie Hockman Trust: Roland Shoemaker Run-TryBot: Katie Hockman TryBot-Result: Go Bot --- src/go/build/deps_test.go | 2 +- src/internal/fuzz/fuzz.go | 51 ++++++++++++++++++++++++++++++++++----- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 2dc2939eec..67989d2e38 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -509,7 +509,7 @@ var depsRules = ` FMT, flag, runtime/debug, runtime/trace, internal/sysinfo, math/rand < testing; - FMT, crypto/sha256, encoding/json, go/ast, go/parser, go/token, math/rand, encoding/hex, crypto/sha256, log + FMT, crypto/sha256, encoding/json, go/ast, go/parser, go/token, math/rand, encoding/hex, crypto/sha256 < internal/fuzz; internal/fuzz, internal/testlog, runtime/pprof, regexp diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 572a0f04d2..929f78bb17 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -14,7 +14,6 @@ import ( "fmt" "io" "io/ioutil" - "log" "os" "path/filepath" "reflect" @@ -240,7 +239,16 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err } } if printDebugInfo() { - log.Printf("DEBUG new crasher, id: %s, parent: %s, gen: %d, size: %d, exec time: %s\n", result.entry.Name, result.entry.Parent, result.entry.Generation, len(result.entry.Data), result.entryDuration) + fmt.Fprintf( + c.opts.Log, + "DEBUG new crasher, elapsed: %s, id: %s, parent: %s, gen: %d, size: %d, exec time: %s\n", + time.Since(c.startTime), + result.entry.Name, + result.entry.Parent, + result.entry.Generation, + len(result.entry.Data), + result.entryDuration, + ) } stop(err) } @@ -263,12 +271,31 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err } } if printDebugInfo() { - log.Printf("DEBUG new interesting input, id: %s, parent: %s, gen: %d, new edges: %d, total edges: %d, size: %d, exec time: %s\n", result.entry.Name, result.entry.Parent, result.entry.Generation, newEdges, countEdges(c.coverageData), len(result.entry.Data), result.entryDuration) + fmt.Fprintf( + c.opts.Log, + "DEBUG new interesting input, elapsed: %s, id: %s, parent: %s, gen: %d, new edges: %d, total edges: %d, size: %d, exec time: %s\n", + time.Since(c.startTime), + result.entry.Name, + result.entry.Parent, + result.entry.Generation, + newEdges, + countEdges(c.coverageData), + len(result.entry.Data), + result.entryDuration, + ) } } else if c.coverageOnlyRun() { c.covOnlyInputs-- if printDebugInfo() { - log.Printf("DEBUG processed an initial input, id: %s, new edges: %d, size: %d, exec time: %s\n", result.entry.Parent, newEdges, len(result.entry.Data), result.entryDuration) + fmt.Fprintf( + c.opts.Log, + "DEBUG processed an initial input, elapsed: %s, id: %s, new edges: %d, size: %d, exec time: %s\n", + time.Since(c.startTime), + result.entry.Parent, + newEdges, + len(result.entry.Data), + result.entryDuration, + ) } if c.covOnlyInputs == 0 { // The coordinator has finished getting a baseline for @@ -277,12 +304,24 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err // to 0). c.interestingCount = 0 if printDebugInfo() { - log.Printf("DEBUG finished processing input corpus, entries: %d, initial coverage edges: %d\n", len(c.corpus.entries), countEdges(c.coverageData)) + fmt.Fprintf( + c.opts.Log, + "DEBUG finished processing input corpus, elapsed: %s, entries: %d, initial coverage edges: %d\n", + time.Since(c.startTime), + len(c.corpus.entries), + countEdges(c.coverageData), + ) } } } else { if printDebugInfo() { - log.Printf("DEBUG worker reported interesting input that doesn't expand coverage, id: %s, parent: %s\n", result.entry.Name, result.entry.Parent) + fmt.Fprintf( + c.opts.Log, + "DEBUG worker reported interesting input that doesn't expand coverage, elapsed: %s, id: %s, parent: %s\n", + time.Since(c.startTime), + result.entry.Name, + result.entry.Parent, + ) } } } -- GitLab From 8e5304f7298a0eef48e4796017c51b4d9aeb52b5 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 4 Jun 2021 18:11:59 -0400 Subject: [PATCH 0251/2500] [dev.typeparams] cmd/compile, runtime: remove the siz argument of newproc/deferproc newproc/deferproc takes a siz argument for the go'd/deferred function's argument size. Now it is always zero. Remove the argument. Change-Id: If1bb8d427e34015ccec0ba10dbccaae96757fa8c Reviewed-on: https://go-review.googlesource.com/c/go/+/325917 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/cmd/compile/internal/ssagen/ssa.go | 11 ++++------- src/runtime/asm_386.s | 2 -- src/runtime/asm_amd64.s | 2 -- src/runtime/asm_arm.s | 7 +++---- src/runtime/asm_arm64.s | 11 ++++------- src/runtime/asm_mips64x.s | 7 +++---- src/runtime/asm_mipsx.s | 7 +++---- src/runtime/asm_ppc64x.s | 3 +-- src/runtime/asm_riscv64.s | 7 +++---- src/runtime/asm_s390x.s | 7 +++---- src/runtime/asm_wasm.s | 3 +-- src/runtime/debugcall.go | 2 +- src/runtime/panic.go | 9 ++------- src/runtime/proc.go | 27 +++++++++++--------------- 14 files changed, 39 insertions(+), 66 deletions(-) diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 6479346845..27f0ee685b 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -4972,14 +4972,11 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val argStart := base.Ctxt.FixedFrameSize() // Defer/go args. if k != callNormal { - // Write argsize and closure (args to newproc/deferproc). - argsize := s.constInt32(types.Types[types.TUINT32], int32(stksize)) - ACArgs = append(ACArgs, types.Types[types.TUINT32]) // not argExtra - callArgs = append(callArgs, argsize) - ACArgs = append(ACArgs, types.Types[types.TUINTPTR]) + // Write closure (arg to newproc/deferproc). + ACArgs = append(ACArgs, types.Types[types.TUINTPTR]) // not argExtra callArgs = append(callArgs, closure) - stksize += 2 * int64(types.PtrSize) - argStart += 2 * int64(types.PtrSize) + stksize += int64(types.PtrSize) + argStart += int64(types.PtrSize) } // Set receiver (for interface calls). diff --git a/src/runtime/asm_386.s b/src/runtime/asm_386.s index ec5ea58028..dd2ea458cc 100644 --- a/src/runtime/asm_386.s +++ b/src/runtime/asm_386.s @@ -244,10 +244,8 @@ ok: // create a new goroutine to start program PUSHL $runtime·mainPC(SB) // entry - PUSHL $0 // arg size CALL runtime·newproc(SB) POPL AX - POPL AX // start this M CALL runtime·mstart(SB) diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index 96f0d3fefc..f8f5fc62e6 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -214,10 +214,8 @@ ok: // create a new goroutine to start program MOVQ $runtime·mainPC(SB), AX // entry PUSHQ AX - PUSHQ $0 // arg size CALL runtime·newproc(SB) POPQ AX - POPQ AX // start this M CALL runtime·mstart(SB) diff --git a/src/runtime/asm_arm.s b/src/runtime/asm_arm.s index 872e56aeb4..5c2bc00fe8 100644 --- a/src/runtime/asm_arm.s +++ b/src/runtime/asm_arm.s @@ -168,14 +168,13 @@ TEXT runtime·rt0_go(SB),NOSPLIT|NOFRAME|TOPFRAME,$0 BL runtime·schedinit(SB) // create a new goroutine to start program - SUB $12, R13 + SUB $8, R13 MOVW $runtime·mainPC(SB), R0 - MOVW R0, 8(R13) // arg 2: fn + MOVW R0, 4(R13) // arg 1: fn MOVW $0, R0 - MOVW R0, 4(R13) // arg 1: siz MOVW R0, 0(R13) // dummy LR BL runtime·newproc(SB) - ADD $12, R13 // pop args and LR + ADD $8, R13 // pop args and LR // start this M BL runtime·mstart(SB) diff --git a/src/runtime/asm_arm64.s b/src/runtime/asm_arm64.s index be4313d35d..e7c5fa3225 100644 --- a/src/runtime/asm_arm64.s +++ b/src/runtime/asm_arm64.s @@ -87,14 +87,11 @@ nocgo: // create a new goroutine to start program MOVD $runtime·mainPC(SB), R0 // entry - MOVD RSP, R7 - MOVD.W $0, -8(R7) - MOVD.W R0, -8(R7) - MOVD.W $0, -8(R7) - MOVD.W $0, -8(R7) - MOVD R7, RSP + SUB $16, RSP + MOVD R0, 8(RSP) // arg + MOVD $0, 0(RSP) // dummy LR BL runtime·newproc(SB) - ADD $32, RSP + ADD $16, RSP // start this M BL runtime·mstart(SB) diff --git a/src/runtime/asm_mips64x.s b/src/runtime/asm_mips64x.s index d4d2280105..f3ac453d99 100644 --- a/src/runtime/asm_mips64x.s +++ b/src/runtime/asm_mips64x.s @@ -63,12 +63,11 @@ nocgo: // create a new goroutine to start program MOVV $runtime·mainPC(SB), R1 // entry - ADDV $-24, R29 - MOVV R1, 16(R29) - MOVV R0, 8(R29) + ADDV $-16, R29 + MOVV R1, 8(R29) MOVV R0, 0(R29) JAL runtime·newproc(SB) - ADDV $24, R29 + ADDV $16, R29 // start this M JAL runtime·mstart(SB) diff --git a/src/runtime/asm_mipsx.s b/src/runtime/asm_mipsx.s index ea7edf20cf..4dc165849e 100644 --- a/src/runtime/asm_mipsx.s +++ b/src/runtime/asm_mipsx.s @@ -64,12 +64,11 @@ nocgo: // create a new goroutine to start program MOVW $runtime·mainPC(SB), R1 // entry - ADDU $-12, R29 - MOVW R1, 8(R29) - MOVW R0, 4(R29) + ADDU $-8, R29 + MOVW R1, 4(R29) MOVW R0, 0(R29) JAL runtime·newproc(SB) - ADDU $12, R29 + ADDU $8, R29 // start this M JAL runtime·mstart(SB) diff --git a/src/runtime/asm_ppc64x.s b/src/runtime/asm_ppc64x.s index 942cc14f17..a789d041e4 100644 --- a/src/runtime/asm_ppc64x.s +++ b/src/runtime/asm_ppc64x.s @@ -94,9 +94,8 @@ nocgo: MOVDU R0, -8(R1) MOVDU R0, -8(R1) MOVDU R0, -8(R1) - MOVDU R0, -8(R1) BL runtime·newproc(SB) - ADD $(16+FIXED_FRAME), R1 + ADD $(8+FIXED_FRAME), R1 // start this M BL runtime·mstart(SB) diff --git a/src/runtime/asm_riscv64.s b/src/runtime/asm_riscv64.s index ef7af4e10d..69ab88f1d2 100644 --- a/src/runtime/asm_riscv64.s +++ b/src/runtime/asm_riscv64.s @@ -57,12 +57,11 @@ nocgo: // create a new goroutine to start program MOV $runtime·mainPC(SB), T0 // entry - ADD $-24, X2 - MOV T0, 16(X2) - MOV ZERO, 8(X2) + ADD $-16, X2 + MOV T0, 8(X2) MOV ZERO, 0(X2) CALL runtime·newproc(SB) - ADD $24, X2 + ADD $16, X2 // start this M CALL runtime·mstart(SB) diff --git a/src/runtime/asm_s390x.s b/src/runtime/asm_s390x.s index fb38271630..534cb6112c 100644 --- a/src/runtime/asm_s390x.s +++ b/src/runtime/asm_s390x.s @@ -147,12 +147,11 @@ nocgo: // create a new goroutine to start program MOVD $runtime·mainPC(SB), R2 // entry - SUB $24, R15 - MOVD R2, 16(R15) - MOVD $0, 8(R15) + SUB $16, R15 + MOVD R2, 8(R15) MOVD $0, 0(R15) BL runtime·newproc(SB) - ADD $24, R15 + ADD $16, R15 // start this M BL runtime·mstart(SB) diff --git a/src/runtime/asm_wasm.s b/src/runtime/asm_wasm.s index 33c335ba5a..53c271aa70 100644 --- a/src/runtime/asm_wasm.s +++ b/src/runtime/asm_wasm.s @@ -18,8 +18,7 @@ TEXT runtime·rt0_go(SB), NOSPLIT|NOFRAME|TOPFRAME, $0 CALLNORESUME runtime·args(SB) CALLNORESUME runtime·osinit(SB) CALLNORESUME runtime·schedinit(SB) - MOVD $0, 0(SP) - MOVD $runtime·mainPC(SB), 8(SP) + MOVD $runtime·mainPC(SB), 0(SP) CALLNORESUME runtime·newproc(SB) CALL runtime·mstart(SB) // WebAssembly stack will unwind when switching to another goroutine UNDEF diff --git a/src/runtime/debugcall.go b/src/runtime/debugcall.go index faddf59eed..ad66a18c26 100644 --- a/src/runtime/debugcall.go +++ b/src/runtime/debugcall.go @@ -112,7 +112,7 @@ func debugCallWrap(dispatch uintptr) { // closure and start the goroutine with that closure, but the compiler disallows // implicit closure allocation in the runtime. fn := debugCallWrap1 - newg := newproc1(*(**funcval)(unsafe.Pointer(&fn)), nil, 0, gp, callerpc) + newg := newproc1(*(**funcval)(unsafe.Pointer(&fn)), gp, callerpc) args := &debugCallWrapArgs{ dispatch: dispatch, callingG: gp, diff --git a/src/runtime/panic.go b/src/runtime/panic.go index 8a296a3c17..46e43382cd 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -224,21 +224,16 @@ func panicmemAddr(addr uintptr) { panic(errorAddressString{msg: "invalid memory address or nil pointer dereference", addr: addr}) } -// Create a new deferred function fn with siz bytes of arguments. +// Create a new deferred function fn, which has no arguments and results. // The compiler turns a defer statement into a call to this. //go:nosplit -func deferproc(siz int32, fn *funcval) { // arguments of fn follow fn +func deferproc(fn *funcval) { // TODO: Make deferproc just take a func(). gp := getg() if gp.m.curg != gp { // go code on the system stack can't defer throw("defer on system stack") } - if siz != 0 { - // TODO: Make deferproc just take a func(). - throw("defer with non-empty frame") - } - // the arguments of fn are in a perilous state. The stack map // for deferproc does not describe them. So we can't let garbage // collection or stack copying trigger until we've copied them out diff --git a/src/runtime/proc.go b/src/runtime/proc.go index be18bbc090..5d2511b83c 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -4217,7 +4217,7 @@ func malg(stacksize int32) *g { return newg } -// Create a new g running fn with siz bytes of arguments. +// Create a new g running fn. // Put it on the queue of g's waiting to run. // The compiler turns a go statement into a call to this. // @@ -4232,12 +4232,11 @@ func malg(stacksize int32) *g { // be able to adjust them and stack splits won't be able to copy them. // //go:nosplit -func newproc(siz int32, fn *funcval) { - argp := add(unsafe.Pointer(&fn), sys.PtrSize) +func newproc(fn *funcval) { gp := getg() pc := getcallerpc() systemstack(func() { - newg := newproc1(fn, argp, siz, gp, pc) + newg := newproc1(fn, gp, pc) _p_ := getg().m.p.ptr() runqput(_p_, newg, true) @@ -4248,23 +4247,19 @@ func newproc(siz int32, fn *funcval) { }) } -// Create a new g in state _Grunnable, starting at fn, with narg bytes -// of arguments starting at argp. callerpc is the address of the go -// statement that created this. The caller is responsible for adding -// the new g to the scheduler. +// Create a new g in state _Grunnable, starting at fn. callerpc is the +// address of the go statement that created this. The caller is responsible +// for adding the new g to the scheduler. // // This must run on the system stack because it's the continuation of // newproc, which cannot split the stack. // //go:systemstack -func newproc1(fn *funcval, argp unsafe.Pointer, narg int32, callergp *g, callerpc uintptr) *g { - if narg != 0 { - // TODO: When we commit to GOEXPERIMENT=regabidefer, - // rewrite the comments for newproc and newproc1. - // newproc will no longer have a funny stack layout or - // need to be nosplit. - throw("go with non-empty frame") - } +func newproc1(fn *funcval, callergp *g, callerpc uintptr) *g { + // TODO: When we commit to GOEXPERIMENT=regabidefer, + // rewrite the comments for newproc and newproc1. + // newproc will no longer have a funny stack layout or + // need to be nosplit. _g_ := getg() -- GitLab From 83da32749ce86d7ecbe9078d524788fbecb4f39c Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 4 Jun 2021 18:30:51 -0400 Subject: [PATCH 0252/2500] [dev.typeparams] runtime: make deferproc take a func() argument Previously it takes a *funcval, as it can be any function types. Now it must be func(). Make it so. Change-Id: I04273047b024386f55dbbd5fbda4767cbee7ac93 Reviewed-on: https://go-review.googlesource.com/c/go/+/325918 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/runtime/heapdump.go | 7 ++++--- src/runtime/panic.go | 25 ++++++++----------------- src/runtime/runtime2.go | 8 ++++---- src/runtime/stubs.go | 2 +- 4 files changed, 17 insertions(+), 25 deletions(-) diff --git a/src/runtime/heapdump.go b/src/runtime/heapdump.go index 934e55f495..47e4b6b0d1 100644 --- a/src/runtime/heapdump.go +++ b/src/runtime/heapdump.go @@ -381,12 +381,13 @@ func dumpgoroutine(gp *g) { dumpint(uint64(uintptr(unsafe.Pointer(gp)))) dumpint(uint64(d.sp)) dumpint(uint64(d.pc)) - dumpint(uint64(uintptr(unsafe.Pointer(d.fn)))) - if d.fn == nil { + fn := *(**funcval)(unsafe.Pointer(&d.fn)) + dumpint(uint64(uintptr(unsafe.Pointer(fn)))) + if fn == nil { // d.fn can be nil for open-coded defers dumpint(uint64(0)) } else { - dumpint(uint64(uintptr(unsafe.Pointer(d.fn.fn)))) + dumpint(uint64(uintptr(unsafe.Pointer(fn.fn)))) } dumpint(uint64(uintptr(unsafe.Pointer(d.link)))) } diff --git a/src/runtime/panic.go b/src/runtime/panic.go index 46e43382cd..dc3f6956eb 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -227,7 +227,7 @@ func panicmemAddr(addr uintptr) { // Create a new deferred function fn, which has no arguments and results. // The compiler turns a defer statement into a call to this. //go:nosplit -func deferproc(fn *funcval) { // TODO: Make deferproc just take a func(). +func deferproc(fn func()) { gp := getg() if gp.m.curg != gp { // go code on the system stack can't defer @@ -363,16 +363,6 @@ func testdefersizes() { } } -// deferFunc returns d's deferred function. This is temporary while we -// support both modes of GOEXPERIMENT=regabidefer. Once we commit to -// that experiment, we should change the type of d.fn. -//go:nosplit -func deferFunc(d *_defer) func() { - var fn func() - *(**funcval)(unsafe.Pointer(&fn)) = d.fn - return fn -} - var deferType *_type // type of _defer struct func init() { @@ -555,7 +545,9 @@ func deferreturn() { // called with a callback on an LR architecture and jmpdefer is on the // stack, because the stack trace can be incorrect in that case - see // issue #8153). - _ = fn.fn + if fn == nil { + fn() + } jmpdefer(fn, argp) } @@ -619,7 +611,7 @@ func Goexit() { } else { // Save the pc/sp in deferCallSave(), so we can "recover" back to this // loop if necessary. - deferCallSave(&p, deferFunc(d)) + deferCallSave(&p, d.fn) } if p.aborted { // We had a recursive panic in the defer d we started, and @@ -824,12 +816,12 @@ func runOpenDeferFrame(gp *g, d *_defer) bool { } continue } - closure := *(**funcval)(unsafe.Pointer(d.varp - uintptr(closureOffset))) + closure := *(*func())(unsafe.Pointer(d.varp - uintptr(closureOffset))) d.fn = closure deferBits = deferBits &^ (1 << i) *(*uint8)(unsafe.Pointer(d.varp - uintptr(deferBitsOffset))) = deferBits p := d._panic - deferCallSave(p, deferFunc(d)) + deferCallSave(p, d.fn) if p != nil && p.aborted { break } @@ -950,8 +942,7 @@ func gopanic(e interface{}) { } } else { p.argp = unsafe.Pointer(getargp()) - fn := deferFunc(d) - fn() + d.fn() } p.argp = nil diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index 0e0eb0b728..8b2998f29a 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -954,10 +954,10 @@ type _defer struct { // defers. We have only one defer record for the entire frame (which may // currently have 0, 1, or more defers active). openDefer bool - sp uintptr // sp at time of defer - pc uintptr // pc at time of defer - fn *funcval // can be nil for open-coded defers - _panic *_panic // panic that is running defer + sp uintptr // sp at time of defer + pc uintptr // pc at time of defer + fn func() // can be nil for open-coded defers + _panic *_panic // panic that is running defer link *_defer // If openDefer is true, the fields below record values about the stack diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go index 16d7583202..b94acdea1f 100644 --- a/src/runtime/stubs.go +++ b/src/runtime/stubs.go @@ -177,7 +177,7 @@ func cgocallback(fn, frame, ctxt uintptr) func gogo(buf *gobuf) //go:noescape -func jmpdefer(fv *funcval, argp uintptr) +func jmpdefer(fv func(), argp uintptr) func asminit() func setg(gg *g) func breakpoint() -- GitLab From b80a4c56f015ed51a94da6bd7bcf5bf4b0b08a27 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 4 Jun 2021 20:07:50 -0400 Subject: [PATCH 0253/2500] [dev.typeparams] runtime: allow deferproc split stack deferproc was not allowed to split stack because it had a special stack layout, where the go'd function's arguments were passed on stack but not included in the signature (therefore the stack map). Now it no longer has argument, so it does not need to be nosplit. Change-Id: I6d4b5302bd6fea6642bb4202984d86e3ebbc9054 Reviewed-on: https://go-review.googlesource.com/c/go/+/325920 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/runtime/panic.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/runtime/panic.go b/src/runtime/panic.go index dc3f6956eb..5f35abc43b 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -226,7 +226,6 @@ func panicmemAddr(addr uintptr) { // Create a new deferred function fn, which has no arguments and results. // The compiler turns a defer statement into a call to this. -//go:nosplit func deferproc(fn func()) { gp := getg() if gp.m.curg != gp { @@ -234,11 +233,6 @@ func deferproc(fn func()) { throw("defer on system stack") } - // the arguments of fn are in a perilous state. The stack map - // for deferproc does not describe them. So we can't let garbage - // collection or stack copying trigger until we've copied them out - // to somewhere safe. The memmove below does that. - // Until the copy completes, we can only call nosplit routines. sp := getcallersp() callerpc := getcallerpc() -- GitLab From 74b0b2772ab361884c0e00caf16aa158a7b51e36 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Mon, 7 Jun 2021 18:18:00 -0400 Subject: [PATCH 0254/2500] [dev.typeparams] cmd/compile, runtime: remove _defer.siz field As deferred function now always has zero arguments, _defer.siz is always 0 and can be removed. Change-Id: Ibb89f65b2f9d2ba4aeabe50438cc3d4b6a88320b Reviewed-on: https://go-review.googlesource.com/c/go/+/325921 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/cmd/compile/internal/ssagen/ssa.go | 33 +++++++++++--------------- src/runtime/panic.go | 11 +++------ src/runtime/runtime2.go | 5 ++-- 3 files changed, 19 insertions(+), 30 deletions(-) diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 27f0ee685b..613a5b6211 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -4940,24 +4940,20 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val addr := s.addr(d) // Must match deferstruct() below and src/runtime/runtime2.go:_defer. - // 0: siz - s.store(types.Types[types.TUINT32], - s.newValue1I(ssa.OpOffPtr, types.Types[types.TUINT32].PtrTo(), t.FieldOff(0), addr), - s.constInt32(types.Types[types.TUINT32], 0)) - // 1: started, set in deferprocStack - // 2: heap, set in deferprocStack - // 3: openDefer - // 4: sp, set in deferprocStack - // 5: pc, set in deferprocStack - // 6: fn + // 0: started, set in deferprocStack + // 1: heap, set in deferprocStack + // 2: openDefer + // 3: sp, set in deferprocStack + // 4: pc, set in deferprocStack + // 5: fn s.store(closure.Type, - s.newValue1I(ssa.OpOffPtr, closure.Type.PtrTo(), t.FieldOff(6), addr), + s.newValue1I(ssa.OpOffPtr, closure.Type.PtrTo(), t.FieldOff(5), addr), closure) - // 7: panic, set in deferprocStack - // 8: link, set in deferprocStack - // 9: framepc - // 10: varp - // 11: fd + // 6: panic, set in deferprocStack + // 7: link, set in deferprocStack + // 8: fd + // 9: varp + // 10: framepc // Call runtime.deferprocStack with pointer to _defer record. ACArgs = append(ACArgs, types.Types[types.TUINTPTR]) @@ -7583,7 +7579,6 @@ func deferstruct() *types.Type { // These fields must match the ones in runtime/runtime2.go:_defer and // (*state).call above. fields := []*types.Field{ - makefield("siz", types.Types[types.TUINT32]), makefield("started", types.Types[types.TBOOL]), makefield("heap", types.Types[types.TBOOL]), makefield("openDefer", types.Types[types.TBOOL]), @@ -7595,9 +7590,9 @@ func deferstruct() *types.Type { makefield("fn", types.Types[types.TUINTPTR]), makefield("_panic", types.Types[types.TUINTPTR]), makefield("link", types.Types[types.TUINTPTR]), - makefield("framepc", types.Types[types.TUINTPTR]), - makefield("varp", types.Types[types.TUINTPTR]), makefield("fd", types.Types[types.TUINTPTR]), + makefield("varp", types.Types[types.TUINTPTR]), + makefield("framepc", types.Types[types.TUINTPTR]), } // build struct holding the above fields diff --git a/src/runtime/panic.go b/src/runtime/panic.go index 5f35abc43b..f6d72995b3 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -258,7 +258,7 @@ func deferproc(fn func()) { } // deferprocStack queues a new deferred function with a defer record on the stack. -// The defer record must have its siz and fn fields initialized. +// The defer record must have its fn field initialized. // All other fields can contain junk. // The defer record must be immediately followed in memory by // the arguments of the defer. @@ -271,10 +271,7 @@ func deferprocStack(d *_defer) { // go code on the system stack can't defer throw("defer on system stack") } - if d.siz != 0 { - throw("defer with non-empty frame") - } - // siz and fn are already set. + // fn is already set. // The other fields are junk on entry to deferprocStack and // are initialized here. d.started = false @@ -406,7 +403,6 @@ func newdefer(siz int32) *_defer { d = (*_defer)(mallocgc(total, deferType, true)) }) } - d.siz = siz d.heap = true return d } @@ -428,7 +424,7 @@ func freedefer(d *_defer) { if !d.heap { return } - sc := deferclass(uintptr(d.siz)) + sc := deferclass(0) if sc >= uintptr(len(p{}.deferpool)) { return } @@ -461,7 +457,6 @@ func freedefer(d *_defer) { // These lines used to be simply `*d = _defer{}` but that // started causing a nosplit stack overflow via typedmemmove. - d.siz = 0 d.started = false d.openDefer = false d.sp = 0 diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index 8b2998f29a..cf4b0bff43 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -940,14 +940,13 @@ func extendRandom(r []byte, n int) { // A _defer holds an entry on the list of deferred calls. // If you add a field here, add code to clear it in freedefer and deferProcStack -// This struct must match the code in cmd/compile/internal/gc/reflect.go:deferstruct -// and cmd/compile/internal/gc/ssa.go:(*state).call. +// This struct must match the code in cmd/compile/internal/ssagen/ssa.go:deferstruct +// and cmd/compile/internal/ssagen/ssa.go:(*state).call. // Some defers will be allocated on the stack and some on the heap. // All defers are logically part of the stack, so write barriers to // initialize them are not required. All defers must be manually scanned, // and for heap defers, marked. type _defer struct { - siz int32 // includes both arguments and results started bool heap bool // openDefer indicates that this _defer is for a frame with open-coded -- GitLab From c0a86c10f174dd1679974b48a085273d02803121 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 8 Jun 2021 16:55:36 -0400 Subject: [PATCH 0255/2500] [dev.typeparams] cmd/compile: simplify openDeferSave Now it is only used to save the deferred the function (closure), which must be a function type. Simplify the code. Change-Id: Id4b8f2760fbf39a95883df2327f97378e7edab88 Reviewed-on: https://go-review.googlesource.com/c/go/+/326060 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/compile/internal/ssagen/ssa.go | 78 +++++++++++--------------- 1 file changed, 34 insertions(+), 44 deletions(-) diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 613a5b6211..68a06ab4f5 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -4672,7 +4672,7 @@ func (s *state) openDeferRecord(n *ir.CallExpr) { // runtime panic code to use. But in the defer exit code, we will // call the function directly if it is a static function. closureVal := s.expr(fn) - closure := s.openDeferSave(nil, fn.Type(), closureVal) + closure := s.openDeferSave(fn.Type(), closureVal) opendefer.closureNode = closure.Aux.(*ir.Name) if !(fn.Op() == ir.ONAME && fn.(*ir.Name).Class == ir.PFUNC) { opendefer.closure = closure @@ -4690,57 +4690,47 @@ func (s *state) openDeferRecord(n *ir.CallExpr) { // openDeferSave generates SSA nodes to store a value (with type t) for an // open-coded defer at an explicit autotmp location on the stack, so it can be -// reloaded and used for the appropriate call on exit. If type t is SSAable, then -// val must be non-nil (and n should be nil) and val is the value to be stored. If -// type t is non-SSAable, then n must be non-nil (and val should be nil) and n is -// evaluated (via s.addr() below) to get the value that is to be stored. The -// function returns an SSA value representing a pointer to the autotmp location. -func (s *state) openDeferSave(n ir.Node, t *types.Type, val *ssa.Value) *ssa.Value { - canSSA := TypeOK(t) - var pos src.XPos - if canSSA { - pos = val.Pos - } else { - pos = n.Pos() +// reloaded and used for the appropriate call on exit. Type t must be a function type +// (therefore SSAable). val is the value to be stored. The function returns an SSA +// value representing a pointer to the autotmp location. +func (s *state) openDeferSave(t *types.Type, val *ssa.Value) *ssa.Value { + if !TypeOK(t) { + s.Fatalf("openDeferSave of non-SSA-able type %v val=%v", t, val) + } + if !t.HasPointers() { + s.Fatalf("openDeferSave of pointerless type %v val=%v", t, val) } - argTemp := typecheck.TempAt(pos.WithNotStmt(), s.curfn, t) - argTemp.SetOpenDeferSlot(true) - var addrArgTemp *ssa.Value - // Use OpVarLive to make sure stack slots for the args, etc. are not - // removed by dead-store elimination + pos := val.Pos + temp := typecheck.TempAt(pos.WithNotStmt(), s.curfn, t) + temp.SetOpenDeferSlot(true) + var addrTemp *ssa.Value + // Use OpVarLive to make sure stack slot for the closure is not removed by + // dead-store elimination if s.curBlock.ID != s.f.Entry.ID { - // Force the argtmp storing this defer function/receiver/arg to be - // declared in the entry block, so that it will be live for the - // defer exit code (which will actually access it only if the - // associated defer call has been activated). - s.defvars[s.f.Entry.ID][memVar] = s.f.Entry.NewValue1A(src.NoXPos, ssa.OpVarDef, types.TypeMem, argTemp, s.defvars[s.f.Entry.ID][memVar]) - s.defvars[s.f.Entry.ID][memVar] = s.f.Entry.NewValue1A(src.NoXPos, ssa.OpVarLive, types.TypeMem, argTemp, s.defvars[s.f.Entry.ID][memVar]) - addrArgTemp = s.f.Entry.NewValue2A(src.NoXPos, ssa.OpLocalAddr, types.NewPtr(argTemp.Type()), argTemp, s.sp, s.defvars[s.f.Entry.ID][memVar]) + // Force the tmp storing this defer function to be declared in the entry + // block, so that it will be live for the defer exit code (which will + // actually access it only if the associated defer call has been activated). + s.defvars[s.f.Entry.ID][memVar] = s.f.Entry.NewValue1A(src.NoXPos, ssa.OpVarDef, types.TypeMem, temp, s.defvars[s.f.Entry.ID][memVar]) + s.defvars[s.f.Entry.ID][memVar] = s.f.Entry.NewValue1A(src.NoXPos, ssa.OpVarLive, types.TypeMem, temp, s.defvars[s.f.Entry.ID][memVar]) + addrTemp = s.f.Entry.NewValue2A(src.NoXPos, ssa.OpLocalAddr, types.NewPtr(temp.Type()), temp, s.sp, s.defvars[s.f.Entry.ID][memVar]) } else { // Special case if we're still in the entry block. We can't use // the above code, since s.defvars[s.f.Entry.ID] isn't defined // until we end the entry block with s.endBlock(). - s.vars[memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, argTemp, s.mem(), false) - s.vars[memVar] = s.newValue1Apos(ssa.OpVarLive, types.TypeMem, argTemp, s.mem(), false) - addrArgTemp = s.newValue2Apos(ssa.OpLocalAddr, types.NewPtr(argTemp.Type()), argTemp, s.sp, s.mem(), false) - } - if t.HasPointers() { - // Since we may use this argTemp during exit depending on the - // deferBits, we must define it unconditionally on entry. - // Therefore, we must make sure it is zeroed out in the entry - // block if it contains pointers, else GC may wrongly follow an - // uninitialized pointer value. - argTemp.SetNeedzero(true) - } - if !canSSA { - a := s.addr(n) - s.move(t, addrArgTemp, a) - return addrArgTemp - } + s.vars[memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, temp, s.mem(), false) + s.vars[memVar] = s.newValue1Apos(ssa.OpVarLive, types.TypeMem, temp, s.mem(), false) + addrTemp = s.newValue2Apos(ssa.OpLocalAddr, types.NewPtr(temp.Type()), temp, s.sp, s.mem(), false) + } + // Since we may use this temp during exit depending on the + // deferBits, we must define it unconditionally on entry. + // Therefore, we must make sure it is zeroed out in the entry + // block if it contains pointers, else GC may wrongly follow an + // uninitialized pointer value. + temp.SetNeedzero(true) // We are storing to the stack, hence we can avoid the full checks in // storeType() (no write barrier) and do a simple store(). - s.store(t, addrArgTemp, val) - return addrArgTemp + s.store(t, addrTemp, val) + return addrTemp } // openDeferExit generates SSA for processing all the open coded defers at exit. -- GitLab From b20747334a4a3dee51759369a098ef2a0c9dbcff Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 8 Jun 2021 18:07:16 -0400 Subject: [PATCH 0256/2500] [dev.typeparams] cmd/compile, runtime: simplify opendefer metadata Now that deferred functions are always argumentless, we don't need the metadata for the frame size, number of arguments, and the information about each argument. Change-Id: I99e75248a22bda6efbdf2012a2f35beca4c18fd7 Reviewed-on: https://go-review.googlesource.com/c/go/+/326061 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/compile/internal/ssagen/ssa.go | 22 ---------------------- src/runtime/panic.go | 17 ++--------------- 2 files changed, 2 insertions(+), 37 deletions(-) diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 68a06ab4f5..0fbb39cfbb 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -324,43 +324,21 @@ func dvarint(x *obj.LSym, off int, v int64) int { // for stack variables are specified as the number of bytes below varp (pointer to the // top of the local variables) for their starting address. The format is: // -// - Max total argument size among all the defers // - Offset of the deferBits variable // - Number of defers in the function // - Information about each defer call, in reverse order of appearance in the function: -// - Total argument size of the call // - Offset of the closure value to call -// - Number of arguments (including interface receiver or method receiver as first arg) -// - Information about each argument -// - Offset of the stored defer argument in this function's frame -// - Size of the argument -// - Offset of where argument should be placed in the args frame when making call func (s *state) emitOpenDeferInfo() { x := base.Ctxt.Lookup(s.curfn.LSym.Name + ".opendefer") s.curfn.LSym.Func().OpenCodedDeferInfo = x off := 0 - - // Compute maxargsize (max size of arguments for all defers) - // first, so we can output it first to the funcdata - var maxargsize int64 - for i := len(s.openDefers) - 1; i >= 0; i-- { - r := s.openDefers[i] - argsize := r.n.X.Type().ArgWidth() // TODO register args: but maybe use of abi0 will make this easy - if argsize > maxargsize { - maxargsize = argsize - } - } - off = dvarint(x, off, maxargsize) off = dvarint(x, off, -s.deferBitsTemp.FrameOffset()) off = dvarint(x, off, int64(len(s.openDefers))) // Write in reverse-order, for ease of running in that order at runtime for i := len(s.openDefers) - 1; i >= 0; i-- { r := s.openDefers[i] - off = dvarint(x, off, r.n.X.Type().ArgWidth()) off = dvarint(x, off, -r.closureNode.FrameOffset()) - numArgs := 0 - off = dvarint(x, off, int64(numArgs)) } } diff --git a/src/runtime/panic.go b/src/runtime/panic.go index f6d72995b3..39013163b6 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -720,8 +720,7 @@ func addOneOpenDeferFrame(gp *g, pc uintptr, sp unsafe.Pointer) { throw("missing deferreturn") } - maxargsize, _ := readvarintUnsafe(fd) - d1 := newdefer(int32(maxargsize)) + d1 := newdefer(0) d1.openDefer = true d1._panic = nil // These are the pc/sp to set after we've @@ -782,27 +781,15 @@ func runOpenDeferFrame(gp *g, d *_defer) bool { done := true fd := d.fd - // Skip the maxargsize - _, fd = readvarintUnsafe(fd) deferBitsOffset, fd := readvarintUnsafe(fd) nDefers, fd := readvarintUnsafe(fd) deferBits := *(*uint8)(unsafe.Pointer(d.varp - uintptr(deferBitsOffset))) for i := int(nDefers) - 1; i >= 0; i-- { // read the funcdata info for this defer - var argWidth, closureOffset, nArgs uint32 - argWidth, fd = readvarintUnsafe(fd) + var closureOffset uint32 closureOffset, fd = readvarintUnsafe(fd) - nArgs, fd = readvarintUnsafe(fd) - if argWidth != 0 || nArgs != 0 { - throw("defer with non-empty frame") - } if deferBits&(1< Date: Fri, 11 Jun 2021 01:10:10 -0700 Subject: [PATCH 0257/2500] [dev.typeparams] cmd/compile: add ir.TypeNodeAt This CL adds a variant of ir.TypeNode that allows specifying position information. This shouldn't normally be needed/used, but it's occasionally helpful for writing code that passes toolstash -cmp. Change-Id: I2be5da0339fd1ec2bee01d6c5310bd2ef58c46b4 Reviewed-on: https://go-review.googlesource.com/c/go/+/327049 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/ir/type.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/ir/type.go b/src/cmd/compile/internal/ir/type.go index a903ea8cd4..431468375a 100644 --- a/src/cmd/compile/internal/ir/type.go +++ b/src/cmd/compile/internal/ir/type.go @@ -300,11 +300,22 @@ func (n *typeNode) CanBeNtype() {} // TypeNode returns the Node representing the type t. func TypeNode(t *types.Type) Ntype { + return TypeNodeAt(src.NoXPos, t) +} + +// TypeNodeAt is like TypeNode, but allows specifying the position +// information if a new OTYPE needs to be constructed. +// +// Deprecated: Use TypeNode instead. For typical use, the position for +// an anonymous OTYPE node should not matter. However, TypeNodeAt is +// available for use with toolstash -cmp to refactor existing code +// that is sensitive to OTYPE position. +func TypeNodeAt(pos src.XPos, t *types.Type) Ntype { if n := t.Obj(); n != nil { if n.Type() != t { base.Fatalf("type skew: %v has type %v, but expected %v", n, n.Type(), t) } return n.(Ntype) } - return newTypeNode(src.NoXPos, t) + return newTypeNode(pos, t) } -- GitLab From 62e32dd386103b5ee8dfe921eb791b14277843b5 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 11 Jun 2021 01:10:56 -0700 Subject: [PATCH 0258/2500] [dev.typeparams] cmd/compile: extract SetBaseTypeIndex function The unified IR importer requires a way to set symbol indices for imported types, so provide an exported API for this. Change-Id: I2f088628f56d5b9f1097196dc1aa23f0a8b8d496 Reviewed-on: https://go-review.googlesource.com/c/go/+/327050 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/typecheck/iimport.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 6d42875f49..9054a83e6e 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -993,7 +993,13 @@ func (r *importReader) symIdx(s *types.Sym) { func (r *importReader) typeExt(t *types.Type) { t.SetNotInHeap(r.bool()) - i, pi := r.int64(), r.int64() + SetBaseTypeIndex(t, r.int64(), r.int64()) +} + +func SetBaseTypeIndex(t *types.Type, i, pi int64) { + if t.Obj() == nil { + base.Fatalf("SetBaseTypeIndex on non-defined type %v", t) + } if i != -1 && pi != -1 { typeSymIdx[t] = [2]int64{i, pi} } @@ -1001,6 +1007,7 @@ func (r *importReader) typeExt(t *types.Type) { // Map imported type T to the index of type descriptor symbols of T and *T, // so we can use index to reference the symbol. +// TODO(mdempsky): Store this information directly in the Type's Name. var typeSymIdx = make(map[*types.Type][2]int64) func BaseTypeIndex(t *types.Type) int64 { -- GitLab From 61888d47c4c49afc2e4ac3aeea42e83cda84d37b Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 11 Jun 2021 03:47:07 -0700 Subject: [PATCH 0259/2500] [dev.typeparams] cmd/compile: allow embedding Type.Vargen into Sym.Name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unified IR currently works by hoisting local type definitions to package scope, which requires giving them a unique name. Its current solution is to directly embed the ·N suffix in Sym.Name, rather than set Type.Vargen. This CL extends types/fmt.go to support trimming this suffix again when appropriate. Longer term, I want to revisit this hack, but this seemed like the least invasive solution while also handling generics and local types. Change-Id: If99fcdcc1e19e37d5887de3b021c256a3fe46b98 Reviewed-on: https://go-review.googlesource.com/c/go/+/327052 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/types/fmt.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/types/fmt.go b/src/cmd/compile/internal/types/fmt.go index cecd1b3cc1..b4d1f6c8bb 100644 --- a/src/cmd/compile/internal/types/fmt.go +++ b/src/cmd/compile/internal/types/fmt.go @@ -324,7 +324,21 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type verb = 'v' } - sconv2(b, t.Sym(), verb, mode) + // In unified IR, function-scope defined types will have a ·N + // suffix embedded directly in their Name. Trim this off for + // non-fmtTypeID modes. + sym := t.Sym() + if mode != fmtTypeID { + i := len(sym.Name) + for i > 0 && sym.Name[i-1] >= '0' && sym.Name[i-1] <= '9' { + i-- + } + const dot = "·" + if i >= len(dot) && sym.Name[i-len(dot):i] == dot { + sym = &Sym{Pkg: sym.Pkg, Name: sym.Name[:i-len(dot)]} + } + } + sconv2(b, sym, verb, mode) // TODO(mdempsky): Investigate including Vargen in fmtTypeIDName // output too. It seems like it should, but that mode is currently -- GitLab From 4a735ce0680e5ea6088da8072ba4c2b0076e51cb Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 11 Jun 2021 01:45:24 -0700 Subject: [PATCH 0260/2500] [dev.typeparams] cmd/compile: add "check" field to noder.gcimports The unified IR importer needs access to the *types2.Checker instance to lazily construct objects and types. Eventually, maybe the types2.Importer API can be extended to add the Checker as another parameter (or more likely something like an ImportConfig struct), but right now we can handle this ourselves as long as we forgo the types2.(*Config).Check convenience wrapper. Updates #46449. Change-Id: I89c41d5d47c224a58841247cd236cd9f701a23a1 Reviewed-on: https://go-review.googlesource.com/c/go/+/327053 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/noder/import.go | 8 ++++---- src/cmd/compile/internal/noder/irgen.go | 18 ++++++++++-------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/cmd/compile/internal/noder/import.go b/src/cmd/compile/internal/noder/import.go index 8076b74650..08e3f77b66 100644 --- a/src/cmd/compile/internal/noder/import.go +++ b/src/cmd/compile/internal/noder/import.go @@ -31,8 +31,8 @@ import ( "cmd/internal/src" ) -// Temporary import helper to get type2-based type-checking going. type gcimports struct { + check *types2.Checker packages map[string]*types2.Package } @@ -45,7 +45,7 @@ func (m *gcimports) ImportFrom(path, srcDir string, mode types2.ImportMode) (*ty panic("mode must be 0") } - _, pkg, err := readImportFile(path, typecheck.Target, m.packages) + _, pkg, err := readImportFile(path, typecheck.Target, m.check, m.packages) return pkg, err } @@ -176,7 +176,7 @@ func importfile(decl *syntax.ImportDecl) *types.Pkg { return nil } - pkg, _, err := readImportFile(path, typecheck.Target, nil) + pkg, _, err := readImportFile(path, typecheck.Target, nil, nil) if err != nil { base.Errorf("%s", err) return nil @@ -208,7 +208,7 @@ func parseImportPath(pathLit *syntax.BasicLit) (string, error) { // readImportFile reads the import file for the given package path and // returns its types.Pkg representation. If packages is non-nil, the // types2.Package representation is also returned. -func readImportFile(path string, target *ir.Package, packages map[string]*types2.Package) (pkg1 *types.Pkg, pkg2 *types2.Package, err error) { +func readImportFile(path string, target *ir.Package, check *types2.Checker, packages map[string]*types2.Package) (pkg1 *types.Pkg, pkg2 *types2.Package, err error) { path, err = resolveImportPath(path) if err != nil { return diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index b70d82d7e6..aac8b5e641 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -20,7 +20,7 @@ import ( // checkFiles configures and runs the types2 checker on the given // parsed source files and then returns the result. -func checkFiles(noders []*noder, importer types2.Importer) (posMap, *types2.Package, *types2.Info) { +func checkFiles(noders []*noder) (posMap, *types2.Package, *types2.Info) { if base.SyntaxErrors() != 0 { base.ErrorExit() } @@ -34,6 +34,9 @@ func checkFiles(noders []*noder, importer types2.Importer) (posMap, *types2.Pack } // typechecking + importer := gcimports{ + packages: make(map[string]*types2.Package), + } conf := types2.Config{ GoVersion: base.Flag.Lang, IgnoreLabels: true, // parser already checked via syntax.CheckBranches mode @@ -43,7 +46,7 @@ func checkFiles(noders []*noder, importer types2.Importer) (posMap, *types2.Pack terr := err.(types2.Error) base.ErrorfAt(m.makeXPos(terr.Pos), "%s", terr.Msg) }, - Importer: importer, + Importer: &importer, Sizes: &gcSizes{}, } info := &types2.Info{ @@ -57,7 +60,10 @@ func checkFiles(noders []*noder, importer types2.Importer) (posMap, *types2.Pack // expand as needed } - pkg, err := conf.Check(base.Ctxt.Pkgpath, files, info) + pkg := types2.NewPackage(base.Ctxt.Pkgpath, "") + importer.check = types2.NewChecker(&conf, pkg, info) + err := importer.check.Files(files) + base.ExitIfErrors() if err != nil { base.FatalfAt(src.NoXPos, "conf.Check error: %v", err) @@ -69,11 +75,7 @@ func checkFiles(noders []*noder, importer types2.Importer) (posMap, *types2.Pack // check2 type checks a Go package using types2, and then generates IR // using the results. func check2(noders []*noder) { - importer := &gcimports{ - packages: make(map[string]*types2.Package), - } - - m, pkg, info := checkFiles(noders, importer) + m, pkg, info := checkFiles(noders) if base.Flag.G < 2 { os.Exit(0) -- GitLab From ef6c5be16025a1868fc27267b7abfb1c28329fe2 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 11 Jun 2021 02:44:16 -0700 Subject: [PATCH 0261/2500] [dev.typeparams] cmd/compile: fix wrapper generation for imported generics This CL fixes reflectdata.methodWrapper to compile wrapper functions for method expressions involving imported, instantiated interface types. CL 322193 fixed a similar issue for generating wrappers for imported, instantiated concrete types, but missed this case. This is necessary to fix CL 326169's test case 10. However, that test case is not included currently, because -G=3 mode crashes on method expressions involving *any* instantiated interface type. Adding a test will have to wait until either this issue is fixed in -G=3 mode, or unified IR is merged. Updates #46704. Change-Id: Ib02d3c20e7c69d16288f1286cd1c98e7cbbba114 Reviewed-on: https://go-review.googlesource.com/c/go/+/327055 Run-TryBot: Matthew Dempsky Reviewed-by: Dan Scales Trust: Dan Scales Trust: Matthew Dempsky TryBot-Result: Go Bot --- src/cmd/compile/internal/reflectdata/reflect.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 0fcb7e3d6d..bdc3527011 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -1800,8 +1800,11 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy } // Only generate I.M wrappers for I in I's own package - // but keep doing it for error.Error (was issue #29304). - if rcvr.IsInterface() && rcvr.Sym() != nil && rcvr.Sym().Pkg != types.LocalPkg && rcvr != types.ErrorType { + // but keep doing it for error.Error (was issue #29304) + // and methods of instantiated interfaces. + if rcvr.IsInterface() && rcvr != types.ErrorType && + rcvr.Sym() != nil && rcvr.Sym().Pkg != types.LocalPkg && + !rcvr.IsFullyInstantiated() { return lsym } -- GitLab From 4468e1cfb94ed07fea5514dce740180fd3a6d20f Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 4 Jun 2021 20:04:57 -0400 Subject: [PATCH 0262/2500] [dev.typeparams] runtime: allow newproc split stack newproc was not allowed to split stack because it had a special stack layout, where the go'd function's arguments were passed on stack but not included in the signature (therefore the stack map). Now it no longer has argument, so it does not need to be nosplit. Change-Id: I6f39730fb1595c4b0438c74118fef418fe1c082b Reviewed-on: https://go-review.googlesource.com/c/go/+/325919 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: Michael Knyszek TryBot-Result: Go Bot --- src/runtime/proc.go | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 5d2511b83c..d6f3af690b 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -4220,18 +4220,6 @@ func malg(stacksize int32) *g { // Create a new g running fn. // Put it on the queue of g's waiting to run. // The compiler turns a go statement into a call to this. -// -// The stack layout of this call is unusual: it assumes that the -// arguments to pass to fn are on the stack sequentially immediately -// after &fn. Hence, they are logically part of newproc's argument -// frame, even though they don't appear in its signature (and can't -// because their types differ between call sites). -// -// This must be nosplit because this stack layout means there are -// untyped arguments in newproc's argument frame. Stack copies won't -// be able to adjust them and stack splits won't be able to copy them. -// -//go:nosplit func newproc(fn *funcval) { gp := getg() pc := getcallerpc() @@ -4250,17 +4238,7 @@ func newproc(fn *funcval) { // Create a new g in state _Grunnable, starting at fn. callerpc is the // address of the go statement that created this. The caller is responsible // for adding the new g to the scheduler. -// -// This must run on the system stack because it's the continuation of -// newproc, which cannot split the stack. -// -//go:systemstack func newproc1(fn *funcval, callergp *g, callerpc uintptr) *g { - // TODO: When we commit to GOEXPERIMENT=regabidefer, - // rewrite the comments for newproc and newproc1. - // newproc will no longer have a funny stack layout or - // need to be nosplit. - _g_ := getg() if fn == nil { -- GitLab From e0e9fb8affbe37c2ff73b9afb60f726e747f428d Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 8 Jun 2021 18:45:18 -0400 Subject: [PATCH 0263/2500] [dev.typeparams] runtime: simplify defer record allocation Now that deferred functions are always argumentless and defer records are no longer with arguments, defer record can be fixed size (just the _defer struct). This allows us to simplify the allocation of defer records, specifically, remove the defer classes and the pools of different sized defers. Change-Id: Icc4b16afc23b38262ca9dd1f7369ad40874cf701 Reviewed-on: https://go-review.googlesource.com/c/go/+/326062 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: Michael Knyszek TryBot-Result: Go Bot --- src/cmd/compile/internal/test/inl_test.go | 2 - src/runtime/malloc.go | 11 -- src/runtime/mgc.go | 18 ++- src/runtime/panic.go | 141 ++++++---------------- src/runtime/proc.go | 12 +- src/runtime/runtime2.go | 8 +- 6 files changed, 50 insertions(+), 142 deletions(-) diff --git a/src/cmd/compile/internal/test/inl_test.go b/src/cmd/compile/internal/test/inl_test.go index 5b0db83301..bbdbe0c37c 100644 --- a/src/cmd/compile/internal/test/inl_test.go +++ b/src/cmd/compile/internal/test/inl_test.go @@ -42,7 +42,6 @@ func TestIntendedInlining(t *testing.T) { "bucketMask", "bucketShift", "chanbuf", - "deferclass", "evacuated", "fastlog2", "fastrand", @@ -63,7 +62,6 @@ func TestIntendedInlining(t *testing.T) { "subtract1", "subtractb", "tophash", - "totaldefersize", "(*bmap).keys", "(*bmap).overflow", "(*waitq).enqueue", diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index 2759bbdaf9..c5f62483ff 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -420,8 +420,6 @@ func mallocinit() { throw("bad TinySizeClass") } - testdefersizes() - if heapArenaBitmapBytes&(heapArenaBitmapBytes-1) != 0 { // heapBits expects modular arithmetic on bitmap // addresses to work. @@ -1088,15 +1086,6 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { var scanSize uintptr if !noscan { - // If allocating a defer+arg block, now that we've picked a malloc size - // large enough to hold everything, cut the "asked for" size down to - // just the defer header, so that the GC bitmap will record the arg block - // as containing nothing at all (as if it were unused space at the end of - // a malloc block caused by size rounding). - // The defer arg areas are scanned as part of scanstack. - if typ == deferType { - dataSize = unsafe.Sizeof(_defer{}) - } heapBitsSetType(uintptr(x), size, dataSize, typ) if dataSize > typ.size { // Array allocation. If there are any diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go index c239fa0f63..34b5b482a3 100644 --- a/src/runtime/mgc.go +++ b/src/runtime/mgc.go @@ -1558,19 +1558,17 @@ func clearpools() { sched.sudogcache = nil unlock(&sched.sudoglock) - // Clear central defer pools. + // Clear central defer pool. // Leave per-P pools alone, they have strictly bounded size. lock(&sched.deferlock) - for i := range sched.deferpool { - // disconnect cached list before dropping it on the floor, - // so that a dangling ref to one entry does not pin all of them. - var d, dlink *_defer - for d = sched.deferpool[i]; d != nil; d = dlink { - dlink = d.link - d.link = nil - } - sched.deferpool[i] = nil + // disconnect cached list before dropping it on the floor, + // so that a dangling ref to one entry does not pin all of them. + var d, dlink *_defer + for d = sched.deferpool; d != nil; d = dlink { + dlink = d.link + d.link = nil } + sched.deferpool = nil unlock(&sched.deferlock) } diff --git a/src/runtime/panic.go b/src/runtime/panic.go index 39013163b6..86d41c4e1c 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -236,7 +236,7 @@ func deferproc(fn func()) { sp := getcallersp() callerpc := getcallerpc() - d := newdefer(0) + d := newdefer() if d._panic != nil { throw("deferproc: d.panic != nil after newdefer") } @@ -302,107 +302,38 @@ func deferprocStack(d *_defer) { // been set and must not be clobbered. } -// Small malloc size classes >= 16 are the multiples of 16: 16, 32, 48, 64, 80, 96, 112, 128, 144, ... -// Each P holds a pool for defers with small arg sizes. -// Assign defer allocations to pools by rounding to 16, to match malloc size classes. - -const ( - deferHeaderSize = unsafe.Sizeof(_defer{}) - minDeferAlloc = (deferHeaderSize + 15) &^ 15 - minDeferArgs = minDeferAlloc - deferHeaderSize -) - -// defer size class for arg size sz -//go:nosplit -func deferclass(siz uintptr) uintptr { - if siz <= minDeferArgs { - return 0 - } - return (siz - minDeferArgs + 15) / 16 -} - -// total size of memory block for defer with arg size sz -func totaldefersize(siz uintptr) uintptr { - if siz <= minDeferArgs { - return minDeferAlloc - } - return deferHeaderSize + siz -} - -// Ensure that defer arg sizes that map to the same defer size class -// also map to the same malloc size class. -func testdefersizes() { - var m [len(p{}.deferpool)]int32 - - for i := range m { - m[i] = -1 - } - for i := uintptr(0); ; i++ { - defersc := deferclass(i) - if defersc >= uintptr(len(m)) { - break - } - siz := roundupsize(totaldefersize(i)) - if m[defersc] < 0 { - m[defersc] = int32(siz) - continue - } - if m[defersc] != int32(siz) { - print("bad defer size class: i=", i, " siz=", siz, " defersc=", defersc, "\n") - throw("bad defer size class") - } - } -} - -var deferType *_type // type of _defer struct - -func init() { - var x interface{} - x = (*_defer)(nil) - deferType = (*(**ptrtype)(unsafe.Pointer(&x))).elem -} +// Each P holds a pool for defers. // Allocate a Defer, usually using per-P pool. // Each defer must be released with freedefer. The defer is not // added to any defer chain yet. -// -// This must not grow the stack because there may be a frame without -// stack map information when this is called. -// -//go:nosplit -func newdefer(siz int32) *_defer { +func newdefer() *_defer { var d *_defer - sc := deferclass(uintptr(siz)) gp := getg() - if sc < uintptr(len(p{}.deferpool)) { - pp := gp.m.p.ptr() - if len(pp.deferpool[sc]) == 0 && sched.deferpool[sc] != nil { - // Take the slow path on the system stack so - // we don't grow newdefer's stack. - systemstack(func() { - lock(&sched.deferlock) - for len(pp.deferpool[sc]) < cap(pp.deferpool[sc])/2 && sched.deferpool[sc] != nil { - d := sched.deferpool[sc] - sched.deferpool[sc] = d.link - d.link = nil - pp.deferpool[sc] = append(pp.deferpool[sc], d) - } - unlock(&sched.deferlock) - }) - } - if n := len(pp.deferpool[sc]); n > 0 { - d = pp.deferpool[sc][n-1] - pp.deferpool[sc][n-1] = nil - pp.deferpool[sc] = pp.deferpool[sc][:n-1] - } - } - if d == nil { - // Allocate new defer+args. + pp := gp.m.p.ptr() + if len(pp.deferpool) == 0 && sched.deferpool != nil { + // Take the slow path on the system stack so + // we don't grow newdefer's stack. systemstack(func() { - total := roundupsize(totaldefersize(uintptr(siz))) - d = (*_defer)(mallocgc(total, deferType, true)) + lock(&sched.deferlock) + for len(pp.deferpool) < cap(pp.deferpool)/2 && sched.deferpool != nil { + d := sched.deferpool + sched.deferpool = d.link + d.link = nil + pp.deferpool = append(pp.deferpool, d) + } + unlock(&sched.deferlock) }) } + if n := len(pp.deferpool); n > 0 { + d = pp.deferpool[n-1] + pp.deferpool[n-1] = nil + pp.deferpool = pp.deferpool[:n-1] + } + if d == nil { + // Allocate new defer. + d = new(_defer) + } d.heap = true return d } @@ -424,23 +355,19 @@ func freedefer(d *_defer) { if !d.heap { return } - sc := deferclass(0) - if sc >= uintptr(len(p{}.deferpool)) { - return - } pp := getg().m.p.ptr() - if len(pp.deferpool[sc]) == cap(pp.deferpool[sc]) { + if len(pp.deferpool) == cap(pp.deferpool) { // Transfer half of local cache to the central cache. // // Take this slow path on the system stack so // we don't grow freedefer's stack. systemstack(func() { var first, last *_defer - for len(pp.deferpool[sc]) > cap(pp.deferpool[sc])/2 { - n := len(pp.deferpool[sc]) - d := pp.deferpool[sc][n-1] - pp.deferpool[sc][n-1] = nil - pp.deferpool[sc] = pp.deferpool[sc][:n-1] + for len(pp.deferpool) > cap(pp.deferpool)/2 { + n := len(pp.deferpool) + d := pp.deferpool[n-1] + pp.deferpool[n-1] = nil + pp.deferpool = pp.deferpool[:n-1] if first == nil { first = d } else { @@ -449,8 +376,8 @@ func freedefer(d *_defer) { last = d } lock(&sched.deferlock) - last.link = sched.deferpool[sc] - sched.deferpool[sc] = first + last.link = sched.deferpool + sched.deferpool = first unlock(&sched.deferlock) }) } @@ -469,7 +396,7 @@ func freedefer(d *_defer) { // both of which throw. d.link = nil - pp.deferpool[sc] = append(pp.deferpool[sc], d) + pp.deferpool = append(pp.deferpool, d) } // Separate function so that it can split stack. @@ -720,7 +647,7 @@ func addOneOpenDeferFrame(gp *g, pc uintptr, sp unsafe.Pointer) { throw("missing deferreturn") } - d1 := newdefer(0) + d1 := newdefer() d1.openDefer = true d1._panic = nil // These are the pc/sp to set after we've diff --git a/src/runtime/proc.go b/src/runtime/proc.go index d6f3af690b..4a116130a5 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -4784,9 +4784,7 @@ func (pp *p) init(id int32) { pp.id = id pp.status = _Pgcstop pp.sudogcache = pp.sudogbuf[:0] - for i := range pp.deferpool { - pp.deferpool[i] = pp.deferpoolbuf[i][:0] - } + pp.deferpool = pp.deferpoolbuf[:0] pp.wbBuf.reset() if pp.mcache == nil { if id == 0 { @@ -4864,12 +4862,10 @@ func (pp *p) destroy() { pp.sudogbuf[i] = nil } pp.sudogcache = pp.sudogbuf[:0] - for i := range pp.deferpool { - for j := range pp.deferpoolbuf[i] { - pp.deferpoolbuf[i][j] = nil - } - pp.deferpool[i] = pp.deferpoolbuf[i][:0] + for j := range pp.deferpoolbuf { + pp.deferpoolbuf[j] = nil } + pp.deferpool = pp.deferpoolbuf[:0] systemstack(func() { for i := 0; i < pp.mspancache.len; i++ { // Safe to call since the world is stopped. diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index cf4b0bff43..75c4818599 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -613,8 +613,8 @@ type p struct { pcache pageCache raceprocctx uintptr - deferpool [5][]*_defer // pool of available defer structs of different sizes (see panic.go) - deferpoolbuf [5][32]*_defer + deferpool []*_defer // pool of available defer structs (see panic.go) + deferpoolbuf [32]*_defer // Cache of goroutine ids, amortizes accesses to runtime·sched.goidgen. goidcache uint64 @@ -801,9 +801,9 @@ type schedt struct { sudoglock mutex sudogcache *sudog - // Central pool of available defer structs of different sizes. + // Central pool of available defer structs. deferlock mutex - deferpool [5]*_defer + deferpool *_defer // freem is the list of m's waiting to be freed when their // m.exited is set. Linked through m.freelink. -- GitLab From 2fe324858b31a672070f8529191d0769013b8488 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 9 Jun 2021 13:51:59 -0400 Subject: [PATCH 0264/2500] [dev.typeparams] internal/buildcfg: always enable regabiwrappers on AMD64 Always enable regabiwrappers on AMD64. GOEXPERIMENT=none will not turn it off. Change-Id: I0aa208c02157661ac3676b753bcfbfa050b99e41 Reviewed-on: https://go-review.googlesource.com/c/go/+/327271 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: David Chase Reviewed-by: Than McIntosh TryBot-Result: Go Bot --- src/internal/buildcfg/exp.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go index 9402da2ebf..b3f3de62a8 100644 --- a/src/internal/buildcfg/exp.go +++ b/src/internal/buildcfg/exp.go @@ -97,6 +97,10 @@ func parseExperiments() goexperiment.Flags { } } + // regabiwrappers is always enabled on amd64. + if GOARCH == "amd64" { + flags.RegabiWrappers = true + } // regabi is only supported on amd64 and arm64. if GOARCH != "amd64" && GOARCH != "arm64" { flags.RegabiWrappers = false -- GitLab From c93d5d1a5245d4baa6824a2c88a6b79e3d895e4d Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 9 Jun 2021 14:29:20 -0400 Subject: [PATCH 0265/2500] [dev.typeparams] all: always enable regabig on AMD64 Always enable regabig on AMD64, which enables the G register and the X15 zero register. Remove the fallback path. Also remove the regabig GOEXPERIMENT. On AMD64 it is always enabled (this CL). Other architectures already have a G register, except for 386, where there are too few registers and it is unlikely that we will reserve one. (If we really do, we can just add a new experiment). Change-Id: I229cac0060f48fe58c9fdaabd38d6fa16b8a0855 Reviewed-on: https://go-review.googlesource.com/c/go/+/327272 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: Than McIntosh Reviewed-by: David Chase TryBot-Result: Go Bot --- src/cmd/compile/internal/amd64/ggen.go | 10 -------- src/cmd/compile/internal/amd64/ssa.go | 12 +++++----- src/cmd/compile/internal/ssa/config.go | 2 +- src/cmd/compile/internal/ssa/gen/AMD64.rules | 2 +- src/cmd/compile/internal/ssa/rewriteAMD64.go | 5 ++-- src/cmd/internal/obj/x86/obj6.go | 4 +--- src/internal/buildcfg/exp.go | 10 ++------ src/internal/goexperiment/exp_regabig_off.go | 9 -------- src/internal/goexperiment/exp_regabig_on.go | 9 -------- src/internal/goexperiment/flags.go | 5 ---- src/runtime/asm_amd64.s | 16 ------------- src/runtime/memclr_amd64.s | 3 --- src/runtime/memmove_amd64.s | 4 ---- src/runtime/race_amd64.s | 24 -------------------- src/runtime/sys_linux_amd64.s | 10 -------- src/runtime/time_linux_amd64.s | 10 -------- 16 files changed, 13 insertions(+), 122 deletions(-) delete mode 100644 src/internal/goexperiment/exp_regabig_off.go delete mode 100644 src/internal/goexperiment/exp_regabig_on.go diff --git a/src/cmd/compile/internal/amd64/ggen.go b/src/cmd/compile/internal/amd64/ggen.go index 1484ad5404..b8dce81a92 100644 --- a/src/cmd/compile/internal/amd64/ggen.go +++ b/src/cmd/compile/internal/amd64/ggen.go @@ -57,7 +57,6 @@ func dzDI(b int64) int64 { func zerorange(pp *objw.Progs, p *obj.Prog, off, cnt int64, state *uint32) *obj.Prog { const ( r13 = 1 << iota // if R13 is already zeroed. - x15 // if X15 is already zeroed. Note: in new ABI, X15 is always zero. ) if cnt == 0 { @@ -85,11 +84,6 @@ func zerorange(pp *objw.Progs, p *obj.Prog, off, cnt int64, state *uint32) *obj. } p = pp.Append(p, x86.AMOVQ, obj.TYPE_REG, x86.REG_R13, 0, obj.TYPE_MEM, x86.REG_SP, off) } else if !isPlan9 && cnt <= int64(8*types.RegSize) { - if !buildcfg.Experiment.RegabiG && *state&x15 == 0 { - p = pp.Append(p, x86.AXORPS, obj.TYPE_REG, x86.REG_X15, 0, obj.TYPE_REG, x86.REG_X15, 0) - *state |= x15 - } - for i := int64(0); i < cnt/16; i++ { p = pp.Append(p, x86.AMOVUPS, obj.TYPE_REG, x86.REG_X15, 0, obj.TYPE_MEM, x86.REG_SP, off+i*16) } @@ -98,10 +92,6 @@ func zerorange(pp *objw.Progs, p *obj.Prog, off, cnt int64, state *uint32) *obj. p = pp.Append(p, x86.AMOVUPS, obj.TYPE_REG, x86.REG_X15, 0, obj.TYPE_MEM, x86.REG_SP, off+cnt-int64(16)) } } else if !isPlan9 && (cnt <= int64(128*types.RegSize)) { - if !buildcfg.Experiment.RegabiG && *state&x15 == 0 { - p = pp.Append(p, x86.AXORPS, obj.TYPE_REG, x86.REG_X15, 0, obj.TYPE_REG, x86.REG_X15, 0) - *state |= x15 - } // Save DI to r12. With the amd64 Go register abi, DI can contain // an incoming parameter, whereas R12 is always scratch. p = pp.Append(p, x86.AMOVQ, obj.TYPE_REG, x86.REG_DI, 0, obj.TYPE_REG, x86.REG_R12, 0) diff --git a/src/cmd/compile/internal/amd64/ssa.go b/src/cmd/compile/internal/amd64/ssa.go index c27a5fe5b5..30dba057d0 100644 --- a/src/cmd/compile/internal/amd64/ssa.go +++ b/src/cmd/compile/internal/amd64/ssa.go @@ -823,7 +823,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.To.Reg = v.Args[0].Reg() ssagen.AddAux2(&p.To, v, sc.Off64()) case ssa.OpAMD64MOVOstorezero: - if !buildcfg.Experiment.RegabiG || s.ABI != obj.ABIInternal { + if s.ABI != obj.ABIInternal { // zero X15 manually opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15) } @@ -914,7 +914,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.To.Type = obj.TYPE_REG p.To.Reg = v.Reg() case ssa.OpAMD64DUFFZERO: - if !buildcfg.Experiment.RegabiG || s.ABI != obj.ABIInternal { + if s.ABI != obj.ABIInternal { // zero X15 manually opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15) } @@ -997,13 +997,13 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { // Closure pointer is DX. ssagen.CheckLoweredGetClosurePtr(v) case ssa.OpAMD64LoweredGetG: - if buildcfg.Experiment.RegabiG && s.ABI == obj.ABIInternal { + if s.ABI == obj.ABIInternal { v.Fatalf("LoweredGetG should not appear in ABIInternal") } r := v.Reg() getgFromTLS(s, r) case ssa.OpAMD64CALLstatic: - if buildcfg.Experiment.RegabiG && s.ABI == obj.ABI0 && v.Aux.(*ssa.AuxCall).Fn.ABI() == obj.ABIInternal { + if s.ABI == obj.ABI0 && v.Aux.(*ssa.AuxCall).Fn.ABI() == obj.ABIInternal { // zeroing X15 when entering ABIInternal from ABI0 if buildcfg.GOOS != "plan9" { // do not use SSE on Plan 9 opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15) @@ -1012,7 +1012,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { getgFromTLS(s, x86.REG_R14) } s.Call(v) - if buildcfg.Experiment.RegabiG && s.ABI == obj.ABIInternal && v.Aux.(*ssa.AuxCall).Fn.ABI() == obj.ABI0 { + if s.ABI == obj.ABIInternal && v.Aux.(*ssa.AuxCall).Fn.ABI() == obj.ABI0 { // zeroing X15 when entering ABIInternal from ABI0 if buildcfg.GOOS != "plan9" { // do not use SSE on Plan 9 opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15) @@ -1308,7 +1308,7 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) { case ssa.BlockRet: s.Prog(obj.ARET) case ssa.BlockRetJmp: - if buildcfg.Experiment.RegabiG && s.ABI == obj.ABI0 && b.Aux.(*obj.LSym).ABI() == obj.ABIInternal { + if s.ABI == obj.ABI0 && b.Aux.(*obj.LSym).ABI() == obj.ABIInternal { // zeroing X15 when entering ABIInternal from ABI0 if buildcfg.GOOS != "plan9" { // do not use SSE on Plan 9 opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15) diff --git a/src/cmd/compile/internal/ssa/config.go b/src/cmd/compile/internal/ssa/config.go index 7d680304c9..61c65f9e54 100644 --- a/src/cmd/compile/internal/ssa/config.go +++ b/src/cmd/compile/internal/ssa/config.go @@ -196,7 +196,7 @@ func NewConfig(arch string, types Types, ctxt *obj.Link, optimize bool) *Config c.floatParamRegs = paramFloatRegAMD64 c.FPReg = framepointerRegAMD64 c.LinkReg = linkRegAMD64 - c.hasGReg = buildcfg.Experiment.RegabiG + c.hasGReg = true case "386": c.PtrSize = 4 c.RegSize = 4 diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 4cd00732fc..45c0238317 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -460,7 +460,7 @@ (IsInBounds idx len) => (SETB (CMPQ idx len)) (IsSliceInBounds idx len) => (SETBE (CMPQ idx len)) (NilCheck ...) => (LoweredNilCheck ...) -(GetG mem) && !(buildcfg.Experiment.RegabiG && v.Block.Func.OwnAux.Fn.ABI() == obj.ABIInternal) => (LoweredGetG mem) // only lower in old ABI. in new ABI we have a G register. +(GetG mem) && v.Block.Func.OwnAux.Fn.ABI() != obj.ABIInternal => (LoweredGetG mem) // only lower in old ABI. in new ABI we have a G register. (GetClosurePtr ...) => (LoweredGetClosurePtr ...) (GetCallerPC ...) => (LoweredGetCallerPC ...) (GetCallerSP ...) => (LoweredGetCallerSP ...) diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 5045ba7351..89d32c0657 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -3,7 +3,6 @@ package ssa -import "internal/buildcfg" import "math" import "cmd/internal/obj" import "cmd/compile/internal/types" @@ -29339,11 +29338,11 @@ func rewriteValueAMD64_OpFloor(v *Value) bool { func rewriteValueAMD64_OpGetG(v *Value) bool { v_0 := v.Args[0] // match: (GetG mem) - // cond: !(buildcfg.Experiment.RegabiG && v.Block.Func.OwnAux.Fn.ABI() == obj.ABIInternal) + // cond: v.Block.Func.OwnAux.Fn.ABI() != obj.ABIInternal // result: (LoweredGetG mem) for { mem := v_0 - if !(!(buildcfg.Experiment.RegabiG && v.Block.Func.OwnAux.Fn.ABI() == obj.ABIInternal)) { + if !(v.Block.Func.OwnAux.Fn.ABI() != obj.ABIInternal) { break } v.reset(OpAMD64LoweredGetG) diff --git a/src/cmd/internal/obj/x86/obj6.go b/src/cmd/internal/obj/x86/obj6.go index e2732d53e3..183ca2ebe9 100644 --- a/src/cmd/internal/obj/x86/obj6.go +++ b/src/cmd/internal/obj/x86/obj6.go @@ -35,7 +35,6 @@ import ( "cmd/internal/objabi" "cmd/internal/src" "cmd/internal/sys" - "internal/buildcfg" "log" "math" "path" @@ -647,13 +646,12 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { var regg int16 if !p.From.Sym.NoSplit() || p.From.Sym.Wrapper() { - if ctxt.Arch.Family == sys.AMD64 && buildcfg.Experiment.RegabiG && cursym.ABI() == obj.ABIInternal { + if ctxt.Arch.Family == sys.AMD64 && cursym.ABI() == obj.ABIInternal { regg = REGG // use the g register directly in ABIInternal } else { p = obj.Appendp(p, newprog) regg = REG_CX if ctxt.Arch.Family == sys.AMD64 { - // Using this register means that stacksplit works w/ //go:registerparams even when !buildcfg.Experiment.RegabiG regg = REGG // == REG_R14 } p = load_g(ctxt, p, newprog, regg) // load g into regg diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go index b3f3de62a8..e78f987999 100644 --- a/src/internal/buildcfg/exp.go +++ b/src/internal/buildcfg/exp.go @@ -28,7 +28,6 @@ var regabiDeveloping = false // configuration and any variation from this is an experiment. var experimentBaseline = goexperiment.Flags{ RegabiWrappers: regabiSupported, - RegabiG: regabiSupported, RegabiReflect: regabiSupported, RegabiArgs: regabiSupported, } @@ -67,7 +66,6 @@ func parseExperiments() goexperiment.Flags { // do the right thing. names["regabi"] = func(v bool) { flags.RegabiWrappers = v - flags.RegabiG = v flags.RegabiReflect = v flags.RegabiArgs = v } @@ -104,16 +102,12 @@ func parseExperiments() goexperiment.Flags { // regabi is only supported on amd64 and arm64. if GOARCH != "amd64" && GOARCH != "arm64" { flags.RegabiWrappers = false - flags.RegabiG = false flags.RegabiReflect = false flags.RegabiArgs = false } // Check regabi dependencies. - if flags.RegabiG && !flags.RegabiWrappers { - Error = fmt.Errorf("GOEXPERIMENT regabig requires regabiwrappers") - } - if flags.RegabiArgs && !(flags.RegabiWrappers && flags.RegabiG && flags.RegabiReflect) { - Error = fmt.Errorf("GOEXPERIMENT regabiargs requires regabiwrappers,regabig,regabireflect") + if flags.RegabiArgs && !(flags.RegabiWrappers && flags.RegabiReflect) { + Error = fmt.Errorf("GOEXPERIMENT regabiargs requires regabiwrappers,regabireflect") } return flags } diff --git a/src/internal/goexperiment/exp_regabig_off.go b/src/internal/goexperiment/exp_regabig_off.go deleted file mode 100644 index 1b37d45186..0000000000 --- a/src/internal/goexperiment/exp_regabig_off.go +++ /dev/null @@ -1,9 +0,0 @@ -// Code generated by mkconsts.go. DO NOT EDIT. - -//go:build !goexperiment.regabig -// +build !goexperiment.regabig - -package goexperiment - -const RegabiG = false -const RegabiGInt = 0 diff --git a/src/internal/goexperiment/exp_regabig_on.go b/src/internal/goexperiment/exp_regabig_on.go deleted file mode 100644 index 7e5b162e0b..0000000000 --- a/src/internal/goexperiment/exp_regabig_on.go +++ /dev/null @@ -1,9 +0,0 @@ -// Code generated by mkconsts.go. DO NOT EDIT. - -//go:build goexperiment.regabig -// +build goexperiment.regabig - -package goexperiment - -const RegabiG = true -const RegabiGInt = 1 diff --git a/src/internal/goexperiment/flags.go b/src/internal/goexperiment/flags.go index c20dbcd9f5..71e38cd047 100644 --- a/src/internal/goexperiment/flags.go +++ b/src/internal/goexperiment/flags.go @@ -68,11 +68,6 @@ type Flags struct { // ABI0 and ABIInternal functions. Without this, the ABIs are // assumed to be identical so cross-ABI calls are direct. RegabiWrappers bool - // RegabiG enables dedicated G and zero registers in - // ABIInternal. - // - // Requires wrappers because it makes the ABIs incompatible. - RegabiG bool // RegabiReflect enables the register-passing paths in // reflection calls. This is also gated by intArgRegs in // reflect and runtime (which are disabled by default) so it diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index f8f5fc62e6..50ffa30ac5 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -683,10 +683,6 @@ TEXT runtime·jmpdefer(SB), NOSPLIT, $0-16 // or else unwinding from systemstack_switch is incorrect. // Smashes R9. TEXT gosave_systemstack_switch<>(SB),NOSPLIT,$0 -#ifndef GOEXPERIMENT_regabig - get_tls(R14) - MOVQ g(R14), R14 -#endif MOVQ $runtime·systemstack_switch(SB), R9 MOVQ R9, (g_sched+gobuf_pc)(R14) LEAQ 8(SP), R9 @@ -1284,10 +1280,8 @@ aes65to128: PXOR X10, X8 PXOR X11, X9 PXOR X9, X8 -#ifdef GOEXPERIMENT_regabig // X15 must be zero on return PXOR X15, X15 -#endif #ifdef GOEXPERIMENT_regabiargs MOVQ X8, AX // return X8 #else @@ -1408,10 +1402,8 @@ aesloop: PXOR X10, X8 PXOR X11, X9 PXOR X9, X8 -#ifdef GOEXPERIMENT_regabig // X15 must be zero on return PXOR X15, X15 -#endif #ifdef GOEXPERIMENT_regabiargs MOVQ X8, AX // return X8 #else @@ -1595,12 +1587,10 @@ TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0 // signals. It is quite painful to set X15 in the signal context, // so we do it here. TEXT ·sigpanic0(SB),NOSPLIT,$0-0 -#ifdef GOEXPERIMENT_regabig get_tls(R14) MOVQ g(R14), R14 #ifndef GOOS_plan9 XORPS X15, X15 -#endif #endif JMP ·sigpanic(SB) @@ -1619,13 +1609,7 @@ TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$112 MOVQ R13, 104(SP) // TODO: Consider passing g.m.p in as an argument so they can be shared // across a sequence of write barriers. -#ifdef GOEXPERIMENT_regabig MOVQ g_m(R14), R13 -#else - get_tls(R13) - MOVQ g(R13), R13 - MOVQ g_m(R13), R13 -#endif MOVQ m_p(R13), R13 MOVQ (p_wbBuf+wbBuf_next)(R13), R12 // Increment wbBuf.next position. diff --git a/src/runtime/memclr_amd64.s b/src/runtime/memclr_amd64.s index a10f57bd8c..6c78869f4c 100644 --- a/src/runtime/memclr_amd64.s +++ b/src/runtime/memclr_amd64.s @@ -37,9 +37,6 @@ tail: JE _8 CMPQ BX, $16 JBE _9through16 -#ifndef GOEXPERIMENT_regabig - PXOR X15, X15 -#endif CMPQ BX, $32 JBE _17through32 CMPQ BX, $64 diff --git a/src/runtime/memmove_amd64.s b/src/runtime/memmove_amd64.s index 24c6529f58..af538d4bce 100644 --- a/src/runtime/memmove_amd64.s +++ b/src/runtime/memmove_amd64.s @@ -254,10 +254,8 @@ move_129through256: MOVOU X13, -48(DI)(BX*1) MOVOU X14, -32(DI)(BX*1) MOVOU X15, -16(DI)(BX*1) -#ifdef GOEXPERIMENT_regabig // X15 must be zero on return PXOR X15, X15 -#endif RET move_256through2048: SUBQ $256, BX @@ -297,10 +295,8 @@ move_256through2048: LEAQ 256(SI), SI LEAQ 256(DI), DI JGE move_256through2048 -#ifdef GOEXPERIMENT_regabig // X15 must be zero on return PXOR X15, X15 -#endif JMP tail avxUnaligned: diff --git a/src/runtime/race_amd64.s b/src/runtime/race_amd64.s index 469623ff20..8a17113232 100644 --- a/src/runtime/race_amd64.s +++ b/src/runtime/race_amd64.s @@ -161,10 +161,6 @@ TEXT runtime·racewriterangepc1(SB), NOSPLIT, $0-24 // If addr (RARG1) is out of range, do nothing. // Otherwise, setup goroutine context and invoke racecall. Other arguments already set. TEXT racecalladdr<>(SB), NOSPLIT, $0-0 -#ifndef GOEXPERIMENT_regabig - get_tls(R12) - MOVQ g(R12), R14 -#endif MOVQ g_racectx(R14), RARG0 // goroutine context // Check that addr is within [arenastart, arenaend) or within [racedatastart, racedataend). CMPQ RARG1, runtime·racearenastart(SB) @@ -192,10 +188,6 @@ TEXT runtime·racefuncenter(SB), NOSPLIT, $0-8 // R11 = caller's return address TEXT racefuncenter<>(SB), NOSPLIT, $0-0 MOVQ DX, BX // save function entry context (for closures) -#ifndef GOEXPERIMENT_regabig - get_tls(R12) - MOVQ g(R12), R14 -#endif MOVQ g_racectx(R14), RARG0 // goroutine context MOVQ R11, RARG1 // void __tsan_func_enter(ThreadState *thr, void *pc); @@ -208,10 +200,6 @@ TEXT racefuncenter<>(SB), NOSPLIT, $0-0 // func runtime·racefuncexit() // Called from instrumented code. TEXT runtime·racefuncexit(SB), NOSPLIT, $0-0 -#ifndef GOEXPERIMENT_regabig - get_tls(R12) - MOVQ g(R12), R14 -#endif MOVQ g_racectx(R14), RARG0 // goroutine context // void __tsan_func_exit(ThreadState *thr); MOVQ $__tsan_func_exit(SB), AX @@ -370,10 +358,6 @@ racecallatomic_data: JAE racecallatomic_ignore racecallatomic_ok: // Addr is within the good range, call the atomic function. -#ifndef GOEXPERIMENT_regabig - get_tls(R12) - MOVQ g(R12), R14 -#endif MOVQ g_racectx(R14), RARG0 // goroutine context MOVQ 8(SP), RARG1 // caller pc MOVQ (SP), RARG2 // pc @@ -385,10 +369,6 @@ racecallatomic_ignore: // An attempt to synchronize on the address would cause crash. MOVQ AX, BX // remember the original function MOVQ $__tsan_go_ignore_sync_begin(SB), AX -#ifndef GOEXPERIMENT_regabig - get_tls(R12) - MOVQ g(R12), R14 -#endif MOVQ g_racectx(R14), RARG0 // goroutine context CALL racecall<>(SB) MOVQ BX, AX // restore the original function @@ -416,10 +396,6 @@ TEXT runtime·racecall(SB), NOSPLIT, $0-0 // Switches SP to g0 stack and calls (AX). Arguments already set. TEXT racecall<>(SB), NOSPLIT, $0-0 -#ifndef GOEXPERIMENT_regabig - get_tls(R12) - MOVQ g(R12), R14 -#endif MOVQ g_m(R14), R13 // Switch to g0 stack. MOVQ SP, R12 // callee-saved, preserved across the CALL diff --git a/src/runtime/sys_linux_amd64.s b/src/runtime/sys_linux_amd64.s index f22b7ad928..64ddc2354e 100644 --- a/src/runtime/sys_linux_amd64.s +++ b/src/runtime/sys_linux_amd64.s @@ -215,13 +215,7 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$16-8 MOVQ SP, R12 // Save old SP; R12 unchanged by C code. -#ifdef GOEXPERIMENT_regabig MOVQ g_m(R14), BX // BX unchanged by C code. -#else - get_tls(CX) - MOVQ g(CX), AX - MOVQ g_m(AX), BX // BX unchanged by C code. -#endif // Set vdsoPC and vdsoSP for SIGPROF traceback. // Save the old values on stack and restore them on exit, @@ -236,11 +230,7 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$16-8 MOVQ CX, m_vdsoPC(BX) MOVQ DX, m_vdsoSP(BX) -#ifdef GOEXPERIMENT_regabig CMPQ R14, m_curg(BX) // Only switch if on curg. -#else - CMPQ AX, m_curg(BX) // Only switch if on curg. -#endif JNE noswitch MOVQ m_g0(BX), DX diff --git a/src/runtime/time_linux_amd64.s b/src/runtime/time_linux_amd64.s index 0dd7919896..c88e92bd0c 100644 --- a/src/runtime/time_linux_amd64.s +++ b/src/runtime/time_linux_amd64.s @@ -15,13 +15,7 @@ TEXT time·now(SB),NOSPLIT,$16-24 MOVQ SP, R12 // Save old SP; R12 unchanged by C code. -#ifdef GOEXPERIMENT_regabig MOVQ g_m(R14), BX // BX unchanged by C code. -#else - get_tls(CX) - MOVQ g(CX), AX - MOVQ g_m(AX), BX // BX unchanged by C code. -#endif // Store CLOCK_REALTIME results directly to return space. LEAQ sec+0(FP), SI @@ -38,11 +32,7 @@ TEXT time·now(SB),NOSPLIT,$16-24 MOVQ CX, m_vdsoPC(BX) MOVQ SI, m_vdsoSP(BX) -#ifdef GOEXPERIMENT_regabig CMPQ R14, m_curg(BX) // Only switch if on curg. -#else - CMPQ AX, m_curg(BX) // Only switch if on curg. -#endif JNE noswitch MOVQ m_g0(BX), DX -- GitLab From 2954f11eadf344786d0ec6e3e1d34f6a5c385246 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 11 Jun 2021 06:33:30 -0700 Subject: [PATCH 0266/2500] [dev.typeparams] cmd/compile: scaffolding for export data experiments This CL adds a simple framework for augmenting the current export data format by writing out additional data *after* the existing data, with an extra header before it that current readers ignore. In particular, this is used by unified IR to be able to experiment and iterate on export data designs without having to keep the go/internal/gcimporter and x/tools/go/gcexportdata importers in sync. Instead, they simply continue reading the existing data written out by typecheck/iexport.go. Change-Id: I883211c2892e2c7dec758b85ff6bc31b244440a0 Reviewed-on: https://go-review.googlesource.com/c/go/+/327169 Run-TryBot: Matthew Dempsky Trust: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/noder/export.go | 47 +++++++++++-- src/cmd/compile/internal/noder/import.go | 87 +++++++++++++++++------- 2 files changed, 107 insertions(+), 27 deletions(-) diff --git a/src/cmd/compile/internal/noder/export.go b/src/cmd/compile/internal/noder/export.go index 9fb3b4da10..1a296e22c8 100644 --- a/src/cmd/compile/internal/noder/export.go +++ b/src/cmd/compile/internal/noder/export.go @@ -5,22 +5,61 @@ package noder import ( + "bytes" "fmt" + "io" "cmd/compile/internal/base" "cmd/compile/internal/typecheck" "cmd/internal/bio" ) +// writeNewExportFunc is a hook that can be added to append extra +// export data after the normal export data section. It allows +// experimenting with new export data format designs without requiring +// immediate support in the go/internal or x/tools importers. +var writeNewExportFunc func(out io.Writer) + func WriteExports(out *bio.Writer) { + // When unified IR exports are enable, we simply append it to the + // end of the normal export data (with compiler extensions + // disabled), and write an extra header giving its size. + // + // If the compiler sees this header, it knows to read the new data + // instead; meanwhile the go/types importers will silently ignore it + // and continue processing the old export instead. + // + // This allows us to experiment with changes to the new export data + // format without needing to update the go/internal/gcimporter or + // (worse) x/tools/go/gcexportdata. + + useNewExport := writeNewExportFunc != nil + + var old, new bytes.Buffer + + typecheck.WriteExports(&old, !useNewExport) + + if useNewExport { + writeNewExportFunc(&new) + } + + oldLen := old.Len() + newLen := new.Len() + + if useNewExport { + fmt.Fprintf(out, "\nnewexportsize %v\n", newLen) + } + // The linker also looks for the $$ marker - use char after $$ to distinguish format. out.WriteString("\n$$B\n") // indicate binary export format - off := out.Offset() - typecheck.WriteExports(out, true) - size := out.Offset() - off + io.Copy(out, &old) out.WriteString("\n$$\n") + io.Copy(out, &new) if base.Debug.Export != 0 { - fmt.Printf("BenchmarkExportSize:%s 1 %d bytes\n", base.Ctxt.Pkgpath, size) + fmt.Printf("BenchmarkExportSize:%s 1 %d bytes\n", base.Ctxt.Pkgpath, oldLen) + if useNewExport { + fmt.Printf("BenchmarkNewExportSize:%s 1 %d bytes\n", base.Ctxt.Pkgpath, newLen) + } } } diff --git a/src/cmd/compile/internal/noder/import.go b/src/cmd/compile/internal/noder/import.go index 08e3f77b66..48f0e48028 100644 --- a/src/cmd/compile/internal/noder/import.go +++ b/src/cmd/compile/internal/noder/import.go @@ -31,6 +31,22 @@ import ( "cmd/internal/src" ) +// haveLegacyImports records whether we've imported any packages +// without a new export data section. This is useful for experimenting +// with new export data format designs, when you need to support +// existing tests that manually compile files with inconsistent +// compiler flags. +var haveLegacyImports = false + +// newReadImportFunc is an extension hook for experimenting with new +// export data formats. If a new export data payload was written out +// for an imported package by overloading writeNewExportFunc, then +// that payload will be mapped into memory and passed to +// newReadImportFunc. +var newReadImportFunc = func(data string, pkg1 *types.Pkg, check *types2.Checker, packages map[string]*types2.Package) (pkg2 *types2.Package, err error) { + panic("unexpected new export data payload") +} + type gcimports struct { check *types2.Checker packages map[string]*types2.Package @@ -245,7 +261,7 @@ func readImportFile(path string, target *ir.Package, check *types2.Checker, pack } defer f.Close() - r, end, err := findExportData(f) + r, end, newsize, err := findExportData(f) if err != nil { return } @@ -254,34 +270,51 @@ func readImportFile(path string, target *ir.Package, check *types2.Checker, pack fmt.Printf("importing %s (%s)\n", path, f.Name()) } - var c byte - switch c, err = r.ReadByte(); { - case err != nil: - return + if newsize != 0 { + // We have unified IR data. Map it, and feed to the importers. + end -= newsize + var data string + data, err = base.MapFile(r.File(), end, newsize) + if err != nil { + return + } - case c != 'i': - // Indexed format is distinguished by an 'i' byte, - // whereas previous export formats started with 'c', 'd', or 'v'. - err = fmt.Errorf("unexpected package format byte: %v", c) - return - } + pkg2, err = newReadImportFunc(data, pkg1, check, packages) + } else { + // We only have old data. Oh well, fall back to the legacy importers. + haveLegacyImports = true - // Map string (and data) section into memory as a single large - // string. This reduces heap fragmentation and allows - // returning individual substrings very efficiently. - pos := r.Offset() - data, err := base.MapFile(r.File(), pos, end-pos) - if err != nil { - return - } + var c byte + switch c, err = r.ReadByte(); { + case err != nil: + return + + case c != 'i': + // Indexed format is distinguished by an 'i' byte, + // whereas previous export formats started with 'c', 'd', or 'v'. + err = fmt.Errorf("unexpected package format byte: %v", c) + return + } - typecheck.ReadImports(pkg1, data) + pos := r.Offset() - if packages != nil { - pkg2, err = importer.ImportData(packages, data, path) + // Map string (and data) section into memory as a single large + // string. This reduces heap fragmentation and allows + // returning individual substrings very efficiently. + var data string + data, err = base.MapFile(r.File(), pos, end-pos) if err != nil { return } + + typecheck.ReadImports(pkg1, data) + + if packages != nil { + pkg2, err = importer.ImportData(packages, data, path) + if err != nil { + return + } + } } err = addFingerprint(path, f, end) @@ -291,7 +324,7 @@ func readImportFile(path string, target *ir.Package, check *types2.Checker, pack // findExportData returns a *bio.Reader positioned at the start of the // binary export data section, and a file offset for where to stop // reading. -func findExportData(f *os.File) (r *bio.Reader, end int64, err error) { +func findExportData(f *os.File) (r *bio.Reader, end, newsize int64, err error) { r = bio.NewReader(f) // check object header @@ -334,6 +367,14 @@ func findExportData(f *os.File) (r *bio.Reader, end int64, err error) { // process header lines for !strings.HasPrefix(line, "$$") { + if strings.HasPrefix(line, "newexportsize ") { + fields := strings.Fields(line) + newsize, err = strconv.ParseInt(fields[1], 10, 64) + if err != nil { + return + } + } + line, err = r.ReadString('\n') if err != nil { return -- GitLab From 8f00eb009978e2e1bb681e698a0b51e20333eb05 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 11 Jun 2021 18:51:56 -0700 Subject: [PATCH 0267/2500] [dev.typeparams] cmd/compile: avoid ir.DeepCopy in noder.constDecl Instead of using ir.DeepCopy to copy the IR from the previous constant declaration, just call exprList again and then fix up the position information. This is equivalent in practice, but has cleaner semantics for tricky corner cases like constant declarations that contain function literals. In particular, this refactoring is necessary for the next CL that cleans up function literal construction, because it adds extra consistency checks that weren't satisfied by DeepCopy'd OCLOSUREs. Change-Id: I0372bde5d6613695ee572cc8bf8fb4ff9aef4cb4 Reviewed-on: https://go-review.googlesource.com/c/go/+/327449 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/noder/noder.go | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index 08c05a69be..9dc05182d1 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -450,7 +450,7 @@ func (p *noder) varDecl(decl *syntax.VarDecl) []ir.Node { type constState struct { group *syntax.Group typ ir.Ntype - values []ir.Node + values syntax.Expr iota int64 } @@ -468,16 +468,15 @@ func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []ir.Node { names := p.declNames(ir.OLITERAL, decl.NameList) typ := p.typeExprOrNil(decl.Type) - var values []ir.Node if decl.Values != nil { - values = p.exprList(decl.Values) - cs.typ, cs.values = typ, values + cs.typ, cs.values = typ, decl.Values } else { if typ != nil { base.Errorf("const declaration cannot have type without expression") } - typ, values = cs.typ, cs.values + typ = cs.typ } + values := p.exprList(cs.values) nn := make([]ir.Node, 0, len(names)) for i, n := range names { @@ -485,10 +484,16 @@ func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []ir.Node { base.Errorf("missing value in const declaration") break } + v := values[i] if decl.Values == nil { - v = ir.DeepCopy(n.Pos(), v) + ir.Visit(v, func(v ir.Node) { + if ir.HasUniquePos(v) { + v.SetPos(n.Pos()) + } + }) } + typecheck.Declare(n, typecheck.DeclContext) n.Ntype = typ -- GitLab From 0132b91127c3cf6e19e0e1db014a04219427171e Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 11 Jun 2021 03:09:26 -0700 Subject: [PATCH 0268/2500] [dev.typeparams] cmd/compile: refactor closure construction typecheck.tcClosure is complicated with many code flows because all of its callers setup the closure funcs in slightly different ways. E.g., it's non-obvious who's responsible for setting the underlying func's Sym or adding it to target.Decls, or how to write new code that constructs a closure without interfering with existing code. This CL refactors everything to use three common functions in package ir: NewClosureFunc (which handle creating the Func, Name, and ClosureExpr and wiring them together), NameClosure (which generates and assigns its unique Sym), and UseClosure (which handles adding the Func to target.Decls). Most IR builders can actually name the closure right away, but the legacy noder+typecheck path may not yet know the name of the enclosing function. In particular, for methods declared with aliased receiver parameters, we need to wait until after typechecking top-level declarations to know the method's true name. So they're left anonymous until typecheck. UseClosure does relatively little work today, but it serves as a useful spot to check that the code setting up closures got it right. It may also eventually serve as an optimization point for early lifting of trivial closures, which may or may not ultimately be beneficial. Change-Id: I7da1e93c70d268f575b12d6aaeb2336eb910a6f1 Reviewed-on: https://go-review.googlesource.com/c/go/+/327051 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/inline/inl.go | 32 ++---- src/cmd/compile/internal/ir/expr.go | 1 + src/cmd/compile/internal/ir/func.go | 100 ++++++++++++++++++ src/cmd/compile/internal/noder/expr.go | 16 +-- src/cmd/compile/internal/noder/noder.go | 69 ++++++------ src/cmd/compile/internal/noder/stencil.go | 47 +++----- src/cmd/compile/internal/typecheck/func.go | 80 +++++--------- src/cmd/compile/internal/typecheck/iimport.go | 17 +-- .../compile/internal/typecheck/typecheck.go | 6 +- src/cmd/compile/internal/walk/order.go | 28 ++--- 10 files changed, 200 insertions(+), 196 deletions(-) diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index e12a30f936..76a15dab8b 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -1143,8 +1143,6 @@ func (subst *inlsubst) clovar(n *ir.Name) *ir.Name { // closure does the necessary substitions for a ClosureExpr n and returns the new // closure node. func (subst *inlsubst) closure(n *ir.ClosureExpr) ir.Node { - m := ir.Copy(n) - // Prior to the subst edit, set a flag in the inlsubst to // indicated that we don't want to update the source positions in // the new closure. If we do this, it will appear that the closure @@ -1152,29 +1150,21 @@ func (subst *inlsubst) closure(n *ir.ClosureExpr) ir.Node { // issue #46234 for more details. defer func(prev bool) { subst.noPosUpdate = prev }(subst.noPosUpdate) subst.noPosUpdate = true - ir.EditChildren(m, subst.edit) //fmt.Printf("Inlining func %v with closure into %v\n", subst.fn, ir.FuncName(ir.CurFunc)) - // The following is similar to funcLit + outerfunc := subst.newclofn + if outerfunc == nil { + outerfunc = ir.CurFunc + } + oldfn := n.Func - newfn := ir.NewFunc(oldfn.Pos()) - // These three lines are not strictly necessary, but just to be clear - // that new function needs to redo typechecking and inlinability. - newfn.SetTypecheck(0) - newfn.SetInlinabilityChecked(false) - newfn.Inl = nil - newfn.SetIsHiddenClosure(true) - newfn.Nname = ir.NewNameAt(n.Pos(), ir.BlankNode.Sym()) - newfn.Nname.Func = newfn + newfn := ir.NewClosureFunc(oldfn.Pos(), outerfunc) + // Ntype can be nil for -G=3 mode. if oldfn.Nname.Ntype != nil { newfn.Nname.Ntype = subst.node(oldfn.Nname.Ntype).(ir.Ntype) } - newfn.Nname.Defn = newfn - - m.(*ir.ClosureExpr).Func = newfn - newfn.OClosure = m.(*ir.ClosureExpr) if subst.newclofn != nil { //fmt.Printf("Inlining a closure with a nested closure\n") @@ -1224,13 +1214,13 @@ func (subst *inlsubst) closure(n *ir.ClosureExpr) ir.Node { // Actually create the named function for the closure, now that // the closure is inlined in a specific function. - m.SetTypecheck(0) + newclo := newfn.OClosure + newclo.SetInit(subst.list(n.Init())) if oldfn.ClosureCalled() { - typecheck.Callee(m) + return typecheck.Callee(newclo) } else { - typecheck.Expr(m) + return typecheck.Expr(newclo) } - return m } // node recursively copies a node from the saved pristine body of the diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index bcc0e412d5..779793b2f2 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -195,6 +195,7 @@ type ClosureExpr struct { IsGoWrap bool // whether this is wrapper closure of a go statement } +// Deprecated: Use NewClosureFunc instead. func NewClosureExpr(pos src.XPos, fn *Func) *ClosureExpr { n := &ClosureExpr{Func: fn} n.op = OCLOSURE diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go index 1d76813a4c..3d4f8c4486 100644 --- a/src/cmd/compile/internal/ir/func.go +++ b/src/cmd/compile/internal/ir/func.go @@ -9,6 +9,7 @@ import ( "cmd/compile/internal/types" "cmd/internal/obj" "cmd/internal/src" + "fmt" ) // A Func corresponds to a single function in a Go program @@ -311,3 +312,102 @@ func ClosureDebugRuntimeCheck(clo *ClosureExpr) { func IsTrivialClosure(clo *ClosureExpr) bool { return len(clo.Func.ClosureVars) == 0 } + +// globClosgen is like Func.Closgen, but for the global scope. +var globClosgen int32 + +// closureName generates a new unique name for a closure within outerfn. +func closureName(outerfn *Func) *types.Sym { + pkg := types.LocalPkg + outer := "glob." + prefix := "func" + gen := &globClosgen + + if outerfn != nil { + if outerfn.OClosure != nil { + prefix = "" + } + + pkg = outerfn.Sym().Pkg + outer = FuncName(outerfn) + + // There may be multiple functions named "_". In those + // cases, we can't use their individual Closgens as it + // would lead to name clashes. + if !IsBlank(outerfn.Nname) { + gen = &outerfn.Closgen + } + } + + *gen++ + return pkg.Lookup(fmt.Sprintf("%s.%s%d", outer, prefix, *gen)) +} + +// NewClosureFunc creates a new Func to represent a function literal +// within outerfn. +func NewClosureFunc(pos src.XPos, outerfn *Func) *Func { + fn := NewFunc(pos) + fn.SetIsHiddenClosure(outerfn != nil) + + fn.Nname = NewNameAt(pos, BlankNode.Sym()) + fn.Nname.Func = fn + fn.Nname.Defn = fn + + fn.OClosure = NewClosureExpr(pos, fn) + + return fn +} + +// NameClosure generates a unique for the given function literal, +// which must have appeared within outerfn. +func NameClosure(clo *ClosureExpr, outerfn *Func) { + name := clo.Func.Nname + if !IsBlank(name) { + base.FatalfAt(clo.Pos(), "closure already named: %v", name) + } + + name.SetSym(closureName(outerfn)) + MarkFunc(name) +} + +// UseClosure checks that the ginen function literal has been setup +// correctly, and then returns it as an expression. +// It must be called after clo.Func.ClosureVars has been set. +func UseClosure(clo *ClosureExpr, pkg *Package) Node { + fn := clo.Func + name := fn.Nname + + if IsBlank(name) { + base.FatalfAt(fn.Pos(), "unnamed closure func: %v", fn) + } + // Caution: clo.Typecheck() is still 0 when UseClosure is called by + // tcClosure. + if fn.Typecheck() != 1 || name.Typecheck() != 1 { + base.FatalfAt(fn.Pos(), "missed typecheck: %v", fn) + } + if clo.Type() == nil || name.Type() == nil { + base.FatalfAt(fn.Pos(), "missing types: %v", fn) + } + if !types.Identical(clo.Type(), name.Type()) { + base.FatalfAt(fn.Pos(), "mismatched types: %v", fn) + } + + if base.Flag.W > 1 { + s := fmt.Sprintf("new closure func: %v", fn) + Dump(s, fn) + } + + if pkg != nil { + pkg.Decls = append(pkg.Decls, fn) + } + + if false && IsTrivialClosure(clo) { + // TODO(mdempsky): Investigate if we can/should optimize this + // case. walkClosure already handles it later, but it could be + // useful to recognize earlier (e.g., it might allow multiple + // inlined calls to a function to share a common trivial closure + // func, rather than cloning it for each inlined call). + } + + return clo +} diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 7034a19b81..86a61bc759 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -373,19 +373,13 @@ func (g *irgen) compLit(typ types2.Type, lit *syntax.CompositeLit) ir.Node { } func (g *irgen) funcLit(typ2 types2.Type, expr *syntax.FuncLit) ir.Node { - fn := ir.NewFunc(g.pos(expr)) - fn.SetIsHiddenClosure(ir.CurFunc != nil) + fn := ir.NewClosureFunc(g.pos(expr), ir.CurFunc) + ir.NameClosure(fn.OClosure, ir.CurFunc) - fn.Nname = ir.NewNameAt(g.pos(expr), typecheck.ClosureName(ir.CurFunc)) - ir.MarkFunc(fn.Nname) typ := g.typ(typ2) - fn.Nname.Func = fn - fn.Nname.Defn = fn typed(typ, fn.Nname) - fn.SetTypecheck(1) - - fn.OClosure = ir.NewClosureExpr(g.pos(expr), fn) typed(typ, fn.OClosure) + fn.SetTypecheck(1) g.funcBody(fn, nil, expr.Type, expr.Body) @@ -399,9 +393,7 @@ func (g *irgen) funcLit(typ2 types2.Type, expr *syntax.FuncLit) ir.Node { cv.SetWalkdef(1) } - g.target.Decls = append(g.target.Decls, fn) - - return fn.OClosure + return ir.UseClosure(fn.OClosure, g.target) } func (g *irgen) typeExpr(typ syntax.Expr) *types.Type { diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index 9dc05182d1..ced3f32a53 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -110,25 +110,35 @@ func LoadPackage(filenames []string) { // We also defer type alias declarations until phase 2 // to avoid cycles like #18640. // TODO(gri) Remove this again once we have a fix for #25838. - - // Don't use range--typecheck can add closures to Target.Decls. - base.Timer.Start("fe", "typecheck", "top1") - for i := 0; i < len(typecheck.Target.Decls); i++ { - n := typecheck.Target.Decls[i] - if op := n.Op(); op != ir.ODCL && op != ir.OAS && op != ir.OAS2 && (op != ir.ODCLTYPE || !n.(*ir.Decl).X.Alias()) { - typecheck.Target.Decls[i] = typecheck.Stmt(n) - } - } - + // // Phase 2: Variable assignments. // To check interface assignments, depends on phase 1. // Don't use range--typecheck can add closures to Target.Decls. - base.Timer.Start("fe", "typecheck", "top2") - for i := 0; i < len(typecheck.Target.Decls); i++ { - n := typecheck.Target.Decls[i] - if op := n.Op(); op == ir.ODCL || op == ir.OAS || op == ir.OAS2 || op == ir.ODCLTYPE && n.(*ir.Decl).X.Alias() { - typecheck.Target.Decls[i] = typecheck.Stmt(n) + for phase, name := range []string{"top1", "top2"} { + base.Timer.Start("fe", "typecheck", name) + for i := 0; i < len(typecheck.Target.Decls); i++ { + n := typecheck.Target.Decls[i] + op := n.Op() + + // Closure function declarations are typechecked as part of the + // closure expression. + if fn, ok := n.(*ir.Func); ok && fn.OClosure != nil { + continue + } + + // We don't actually add ir.ODCL nodes to Target.Decls. Make sure of that. + if op == ir.ODCL { + base.FatalfAt(n.Pos(), "unexpected top declaration: %v", op) + } + + // Identify declarations that should be deferred to the second + // iteration. + late := op == ir.OAS || op == ir.OAS2 || op == ir.ODCLTYPE && n.(*ir.Decl).X.Alias() + + if late == (phase == 1) { + typecheck.Target.Decls[i] = typecheck.Stmt(n) + } } } @@ -137,16 +147,15 @@ func LoadPackage(filenames []string) { base.Timer.Start("fe", "typecheck", "func") var fcount int64 for i := 0; i < len(typecheck.Target.Decls); i++ { - n := typecheck.Target.Decls[i] - if n.Op() == ir.ODCLFUNC { + if fn, ok := typecheck.Target.Decls[i].(*ir.Func); ok { if base.Flag.W > 1 { - s := fmt.Sprintf("\nbefore typecheck %v", n) - ir.Dump(s, n) + s := fmt.Sprintf("\nbefore typecheck %v", fn) + ir.Dump(s, fn) } - typecheck.FuncBody(n.(*ir.Func)) + typecheck.FuncBody(fn) if base.Flag.W > 1 { - s := fmt.Sprintf("\nafter typecheck %v", n) - ir.Dump(s, n) + s := fmt.Sprintf("\nafter typecheck %v", fn) + ir.Dump(s, fn) } fcount++ } @@ -1794,24 +1803,14 @@ func fakeRecv() *ir.Field { } func (p *noder) funcLit(expr *syntax.FuncLit) ir.Node { - xtype := p.typeExpr(expr.Type) - - fn := ir.NewFunc(p.pos(expr)) - fn.SetIsHiddenClosure(ir.CurFunc != nil) - - fn.Nname = ir.NewNameAt(p.pos(expr), ir.BlankNode.Sym()) // filled in by tcClosure - fn.Nname.Func = fn - fn.Nname.Ntype = xtype - fn.Nname.Defn = fn - - clo := ir.NewClosureExpr(p.pos(expr), fn) - fn.OClosure = clo + fn := ir.NewClosureFunc(p.pos(expr), ir.CurFunc) + fn.Nname.Ntype = p.typeExpr(expr.Type) p.funcBody(fn, expr.Body) ir.FinishCaptureNames(base.Pos, ir.CurFunc, fn) - return clo + return fn.OClosure } // A function named init is a special case. diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 3e3de1908e..a82274a240 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -280,8 +280,8 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { // } // Make a new internal function. - fn := ir.NewFunc(pos) - fn.SetIsHiddenClosure(true) + fn := ir.NewClosureFunc(pos, outer) + ir.NameClosure(fn.OClosure, outer) // This is the dictionary we want to use. // It may be a constant, or it may be a dictionary acquired from the outer function's dictionary. @@ -346,13 +346,8 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { // Build an internal function with the right signature. closureType := types.NewSignature(x.Type().Pkg(), nil, nil, formalParams, formalResults) - sym := typecheck.ClosureName(outer) - sym.SetFunc(true) - fn.Nname = ir.NewNameAt(pos, sym) - fn.Nname.Class = ir.PFUNC - fn.Nname.Func = fn - fn.Nname.Defn = fn typed(closureType, fn.Nname) + typed(x.Type(), fn.OClosure) fn.SetTypecheck(1) // Build body of closure. This involves just calling the wrapped function directly @@ -401,15 +396,12 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { typecheck.Stmt(innerCall) ir.CurFunc = nil fn.Body = []ir.Node{innerCall} - if outer == nil { - g.target.Decls = append(g.target.Decls, fn) - } // We're all done with the captured dictionary (and receiver, for method values). ir.FinishCaptureNames(pos, outer, fn) // Make a closure referencing our new internal function. - c := ir.NewClosureExpr(pos, fn) + c := ir.UseClosure(fn.OClosure, g.target) var init []ir.Node if outer != nil { init = append(init, dictAssign) @@ -417,9 +409,7 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { if rcvrValue != nil { init = append(init, rcvrAssign) } - c.SetInit(init) - typed(x.Type(), c) - return c + return ir.InitExpr(init, c) } // instantiateMethods instantiates all the methods of all fully-instantiated @@ -859,24 +849,18 @@ func (subst *subster) node(n ir.Node) ir.Node { } case ir.OCLOSURE: + // We're going to create a new closure from scratch, so clear m + // to avoid using the ir.Copy by accident until we reassign it. + m = nil + x := x.(*ir.ClosureExpr) // Need to duplicate x.Func.Nname, x.Func.Dcl, x.Func.ClosureVars, and // x.Func.Body. oldfn := x.Func - newfn := ir.NewFunc(oldfn.Pos()) - if oldfn.ClosureCalled() { - newfn.SetClosureCalled(true) - } - newfn.SetIsHiddenClosure(true) - m.(*ir.ClosureExpr).Func = newfn - // Closure name can already have brackets, if it derives - // from a generic method - newsym := typecheck.MakeInstName(oldfn.Nname.Sym(), subst.ts.Targs, subst.isMethod) - newfn.Nname = ir.NewNameAt(oldfn.Nname.Pos(), newsym) - newfn.Nname.Func = newfn - newfn.Nname.Defn = newfn - ir.MarkFunc(newfn.Nname) - newfn.OClosure = m.(*ir.ClosureExpr) + newfn := ir.NewClosureFunc(oldfn.Pos(), subst.newf) + ir.NameClosure(newfn.OClosure, subst.newf) + + newfn.SetClosureCalled(oldfn.ClosureCalled()) saveNewf := subst.newf ir.CurFunc = newfn @@ -885,7 +869,7 @@ func (subst *subster) node(n ir.Node) ir.Node { newfn.ClosureVars = subst.namelist(oldfn.ClosureVars) typed(subst.ts.Typ(oldfn.Nname.Type()), newfn.Nname) - typed(newfn.Nname.Type(), m) + typed(newfn.Nname.Type(), newfn.OClosure) newfn.SetTypecheck(1) // Make sure type of closure function is set before doing body. @@ -893,7 +877,8 @@ func (subst *subster) node(n ir.Node) ir.Node { subst.newf = saveNewf ir.CurFunc = saveNewf - subst.g.target.Decls = append(subst.g.target.Decls, newfn) + m = ir.UseClosure(newfn.OClosure, subst.g.target) + m.(*ir.ClosureExpr).SetInit(subst.list(x.Init())) case ir.OCONVIFACE: x := x.(*ir.ConvExpr) diff --git a/src/cmd/compile/internal/typecheck/func.go b/src/cmd/compile/internal/typecheck/func.go index 15756a47e4..bd21977f26 100644 --- a/src/cmd/compile/internal/typecheck/func.go +++ b/src/cmd/compile/internal/typecheck/func.go @@ -199,35 +199,6 @@ func fnpkg(fn *ir.Name) *types.Pkg { return fn.Sym().Pkg } -// ClosureName generates a new unique name for a closure within -// outerfunc. -func ClosureName(outerfunc *ir.Func) *types.Sym { - outer := "glob." - prefix := "func" - gen := &globClosgen - - if outerfunc != nil { - if outerfunc.OClosure != nil { - prefix = "" - } - - outer = ir.FuncName(outerfunc) - - // There may be multiple functions named "_". In those - // cases, we can't use their individual Closgens as it - // would lead to name clashes. - if !ir.IsBlank(outerfunc.Nname) { - gen = &outerfunc.Closgen - } - } - - *gen++ - return Lookup(fmt.Sprintf("%s.%s%d", outer, prefix, *gen)) -} - -// globClosgen is like Func.Closgen, but for the global scope. -var globClosgen int32 - // MethodValueWrapper returns the DCLFUNC node representing the // wrapper function (*-fm) needed for the given method value. If the // wrapper function hasn't already been created yet, it's created and @@ -312,8 +283,20 @@ func MethodValueWrapper(dot *ir.SelectorExpr) *ir.Func { // function associated with the closure. // TODO: This creation of the named function should probably really be done in a // separate pass from type-checking. -func tcClosure(clo *ir.ClosureExpr, top int) { +func tcClosure(clo *ir.ClosureExpr, top int) ir.Node { fn := clo.Func + + // We used to allow IR builders to typecheck the underlying Func + // themselves, but that led to too much variety and inconsistency + // around who's responsible for naming the function, typechecking + // it, or adding it to Target.Decls. + // + // It's now all or nothing. Callers are still allowed to do these + // themselves, but then they assume responsibility for all of them. + if fn.Typecheck() == 1 { + base.FatalfAt(fn.Pos(), "underlying closure func already typechecked: %v", fn) + } + // Set current associated iota value, so iota can be used inside // function in ConstSpec, see issue #22344 if x := getIotaValue(); x >= 0 { @@ -322,30 +305,14 @@ func tcClosure(clo *ir.ClosureExpr, top int) { fn.SetClosureCalled(top&ctxCallee != 0) - // Do not typecheck fn twice, otherwise, we will end up pushing - // fn to Target.Decls multiple times, causing InitLSym called twice. - // See #30709 - if fn.Typecheck() == 1 { - clo.SetType(fn.Type()) - return - } - - // Don't give a name and add to Target.Decls if we are typechecking an inlined - // body in ImportedBody(), since we only want to create the named function - // when the closure is actually inlined (and then we force a typecheck - // explicitly in (*inlsubst).node()). - if !inTypeCheckInl { - fn.Nname.SetSym(ClosureName(ir.CurFunc)) - ir.MarkFunc(fn.Nname) - } + ir.NameClosure(clo, ir.CurFunc) Func(fn) - clo.SetType(fn.Type()) // Type check the body now, but only if we're inside a function. // At top level (in a variable initialization: curfn==nil) we're not // ready to type check code yet; we'll check it later, because the // underlying closure function we create is added to Target.Decls. - if ir.CurFunc != nil && clo.Type() != nil { + if ir.CurFunc != nil { oldfn := ir.CurFunc ir.CurFunc = fn Stmts(fn.Body) @@ -371,14 +338,17 @@ func tcClosure(clo *ir.ClosureExpr, top int) { } fn.ClosureVars = fn.ClosureVars[:out] - if base.Flag.W > 1 { - s := fmt.Sprintf("New closure func: %s", ir.FuncName(fn)) - ir.Dump(s, fn) - } - if !inTypeCheckInl { - // Add function to Target.Decls once only when we give it a name - Target.Decls = append(Target.Decls, fn) + clo.SetType(fn.Type()) + + target := Target + if inTypeCheckInl { + // We're typechecking an imported function, so it's not actually + // part of Target. Skip adding it to Target.Decls so we don't + // compile it again. + target = nil } + + return ir.UseClosure(clo, target) } // type check function definition diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 9054a83e6e..b1b3c27898 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1283,12 +1283,7 @@ func (r *importReader) node() ir.Node { // All the remaining code below is similar to (*noder).funcLit(), but // with Dcls and ClosureVars lists already set up - fn := ir.NewFunc(pos) - fn.SetIsHiddenClosure(true) - fn.Nname = ir.NewNameAt(pos, ir.BlankNode.Sym()) - fn.Nname.Func = fn - fn.Nname.Ntype = ir.TypeNode(typ) - fn.Nname.Defn = fn + fn := ir.NewClosureFunc(pos, r.curfn) fn.Nname.SetType(typ) cvars := make([]*ir.Name, r.int64()) @@ -1321,18 +1316,10 @@ func (r *importReader) node() ir.Node { ir.FinishCaptureNames(pos, r.curfn, fn) - clo := ir.NewClosureExpr(pos, fn) - fn.OClosure = clo + clo := fn.OClosure if go117ExportTypes { clo.SetType(typ) } - if r.curfn.Type().HasTParam() { - // Generic functions aren't inlined, so give the closure a - // function name now, which is then available for use - // (after appending the type args) for each stenciling. - fn.Nname.SetSym(ClosureName(r.curfn)) - } - return clo case ir.OSTRUCTLIT: diff --git a/src/cmd/compile/internal/typecheck/typecheck.go b/src/cmd/compile/internal/typecheck/typecheck.go index 9868c2d9a9..a6b21f948a 100644 --- a/src/cmd/compile/internal/typecheck/typecheck.go +++ b/src/cmd/compile/internal/typecheck/typecheck.go @@ -787,11 +787,7 @@ func typecheck1(n ir.Node, top int) ir.Node { case ir.OCLOSURE: n := n.(*ir.ClosureExpr) - tcClosure(n, top) - if n.Type() == nil { - return n - } - return n + return tcClosure(n, top) case ir.OITAB: n := n.(*ir.UnaryExpr) diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go index d1fd3a9b73..750cb6bfc5 100644 --- a/src/cmd/compile/internal/walk/order.go +++ b/src/cmd/compile/internal/walk/order.go @@ -1704,14 +1704,10 @@ func (o *orderState) wrapGoDefer(n *ir.GoDeferStmt) { } // Create a new no-argument function that we'll hand off to defer. - var noFuncArgs []*ir.Field - noargst := ir.NewFuncType(base.Pos, nil, noFuncArgs, nil) - wrapGoDefer_prgen++ outerfn := ir.CurFunc - wrapname := fmt.Sprintf("%v·dwrap·%d", outerfn, wrapGoDefer_prgen) - sym := types.LocalPkg.Lookup(wrapname) - fn := typecheck.DeclFunc(sym, noargst) - fn.SetIsHiddenClosure(true) + + fn := ir.NewClosureFunc(base.Pos, outerfn) + fn.Nname.SetType(types.NewSignature(types.LocalPkg, nil, nil, nil, nil)) fn.SetWrapper(true) // helper for capturing reference to a var declared in an outer scope. @@ -1741,7 +1737,6 @@ func (o *orderState) wrapGoDefer(n *ir.GoDeferStmt) { if methSelectorExpr != nil { methSelectorExpr.X = capName(callX.Pos(), fn, methSelectorExpr.X.(*ir.Name)) } - ir.FinishCaptureNames(n.Pos(), outerfn, fn) // This flags a builtin as opposed to a regular call. irregular := (call.Op() != ir.OCALLFUNC && @@ -1755,23 +1750,12 @@ func (o *orderState) wrapGoDefer(n *ir.GoDeferStmt) { } newcall := mkNewCall(call.Pos(), op, callX, newCallArgs) - // Type-check the result. - if !irregular { - typecheck.Call(newcall.(*ir.CallExpr)) - } else { - typecheck.Stmt(newcall) - } - // Finalize body, register function on the main decls list. fn.Body = []ir.Node{newcall} - typecheck.FinishFuncBody() - typecheck.Func(fn) - typecheck.Target.Decls = append(typecheck.Target.Decls, fn) + ir.FinishCaptureNames(n.Pos(), outerfn, fn) // Create closure expr - clo := ir.NewClosureExpr(n.Pos(), fn) - fn.OClosure = clo - clo.SetType(fn.Type()) + clo := typecheck.Expr(fn.OClosure).(*ir.ClosureExpr) // Set escape properties for closure. if n.Op() == ir.OGO { @@ -1788,7 +1772,7 @@ func (o *orderState) wrapGoDefer(n *ir.GoDeferStmt) { } // Create new top level call to closure over argless function. - topcall := ir.NewCallExpr(n.Pos(), ir.OCALL, clo, []ir.Node{}) + topcall := ir.NewCallExpr(n.Pos(), ir.OCALL, clo, nil) typecheck.Call(topcall) // Tag the call to insure that directClosureCall doesn't undo our work. -- GitLab From db7c868307c87c5e9338e1cb0b5738eb96a929ad Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 11 Jun 2021 09:54:40 -0700 Subject: [PATCH 0269/2500] [dev.typeparams] test: add string quoting support to test/run.go This CL copies go/build's splitQuoted function (used for parsing #cgo directives within `import "C"` preambles) to parse test recipe commands. In particular, this now allows writing "build" and "run" tests that use -gcflags to pass multiple compiler flags. Change-Id: I0d18a9c13a4ce24bbdfa1da8662c0498c93a6762 Reviewed-on: https://go-review.googlesource.com/c/go/+/327275 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- test/run.go | 68 +++++++++- test/typeparam/dictionaryCapture-noinline.go | 126 +++++++++++++++++++ test/typeparam/dictionaryCapture.go | 2 - 3 files changed, 193 insertions(+), 3 deletions(-) create mode 100644 test/typeparam/dictionaryCapture-noinline.go diff --git a/test/run.go b/test/run.go index ef1e9de150..ca6a0f5c29 100644 --- a/test/run.go +++ b/test/run.go @@ -573,7 +573,11 @@ func (t *test) run() { singlefilepkgs := false setpkgpaths := false localImports := true - f := strings.Fields(action) + f, err := splitQuoted(action) + if err != nil { + t.err = fmt.Errorf("invalid test recipe: %v", err) + return + } if len(f) > 0 { action = f[0] args = f[1:] @@ -2116,3 +2120,65 @@ var excludedFiles = map[string]bool{ "fixedbugs/issue7921.go": true, "inline.go": true, } + +// splitQuoted splits the string s around each instance of one or more consecutive +// white space characters while taking into account quotes and escaping, and +// returns an array of substrings of s or an empty list if s contains only white space. +// Single quotes and double quotes are recognized to prevent splitting within the +// quoted region, and are removed from the resulting substrings. If a quote in s +// isn't closed err will be set and r will have the unclosed argument as the +// last element. The backslash is used for escaping. +// +// For example, the following string: +// +// a b:"c d" 'e''f' "g\"" +// +// Would be parsed as: +// +// []string{"a", "b:c d", "ef", `g"`} +// +// [copied from src/go/build/build.go] +func splitQuoted(s string) (r []string, err error) { + var args []string + arg := make([]rune, len(s)) + escaped := false + quoted := false + quote := '\x00' + i := 0 + for _, rune := range s { + switch { + case escaped: + escaped = false + case rune == '\\': + escaped = true + continue + case quote != '\x00': + if rune == quote { + quote = '\x00' + continue + } + case rune == '"' || rune == '\'': + quoted = true + quote = rune + continue + case unicode.IsSpace(rune): + if quoted || i > 0 { + quoted = false + args = append(args, string(arg[:i])) + i = 0 + } + continue + } + arg[i] = rune + i++ + } + if quoted || i > 0 { + args = append(args, string(arg[:i])) + } + if quote != 0 { + err = errors.New("unclosed quote") + } else if escaped { + err = errors.New("unfinished escaping") + } + return args, err +} diff --git a/test/typeparam/dictionaryCapture-noinline.go b/test/typeparam/dictionaryCapture-noinline.go new file mode 100644 index 0000000000..4b46d5f57f --- /dev/null +++ b/test/typeparam/dictionaryCapture-noinline.go @@ -0,0 +1,126 @@ +// run -gcflags="-G=3 -l" + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test situations where functions/methods are not +// immediately called and we need to capture the dictionary +// required for later invocation. + +package main + +func main() { + functions() + methodExpressions() + methodValues() + interfaceMethods() + globals() +} + +func g0[T any](x T) { +} +func g1[T any](x T) T { + return x +} +func g2[T any](x T) (T, T) { + return x, x +} + +func functions() { + f0 := g0[int] + f0(7) + f1 := g1[int] + is7(f1(7)) + f2 := g2[int] + is77(f2(7)) +} + +func is7(x int) { + if x != 7 { + println(x) + panic("assertion failed") + } +} +func is77(x, y int) { + if x != 7 || y != 7 { + println(x,y) + panic("assertion failed") + } +} + +type s[T any] struct { + a T +} + +func (x s[T]) g0() { +} +func (x s[T]) g1() T { + return x.a +} +func (x s[T]) g2() (T, T) { + return x.a, x.a +} + +func methodExpressions() { + x := s[int]{a:7} + f0 := s[int].g0 + f0(x) + f1 := s[int].g1 + is7(f1(x)) + f2 := s[int].g2 + is77(f2(x)) +} + +func methodValues() { + x := s[int]{a:7} + f0 := x.g0 + f0() + f1 := x.g1 + is7(f1()) + f2 := x.g2 + is77(f2()) +} + +var x interface{ + g0() + g1()int + g2()(int,int) +} = s[int]{a:7} +var y interface{} = s[int]{a:7} + +func interfaceMethods() { + x.g0() + is7(x.g1()) + is77(x.g2()) + y.(interface{g0()}).g0() + is7(y.(interface{g1()int}).g1()) + is77(y.(interface{g2()(int,int)}).g2()) +} + +// Also check for instantiations outside functions. +var gg0 = g0[int] +var gg1 = g1[int] +var gg2 = g2[int] + +var hh0 = s[int].g0 +var hh1 = s[int].g1 +var hh2 = s[int].g2 + +var xtop = s[int]{a:7} +var ii0 = x.g0 +var ii1 = x.g1 +var ii2 = x.g2 + +func globals() { + gg0(7) + is7(gg1(7)) + is77(gg2(7)) + x := s[int]{a:7} + hh0(x) + is7(hh1(x)) + is77(hh2(x)) + ii0() + is7(ii1()) + is77(ii2()) +} diff --git a/test/typeparam/dictionaryCapture.go b/test/typeparam/dictionaryCapture.go index bb35df5309..1b2ee1de91 100644 --- a/test/typeparam/dictionaryCapture.go +++ b/test/typeparam/dictionaryCapture.go @@ -8,8 +8,6 @@ // immediately called and we need to capture the dictionary // required for later invocation. -// TODO: copy this test file, add -l to gcflags. - package main func main() { -- GitLab From f1b1c2f67fae0598db5c20f324334c23d4cd3038 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Sat, 12 Jun 2021 07:33:18 -0700 Subject: [PATCH 0270/2500] [dev.typeparams] cmd/compile: simplify NewClosureFunc I initially made NewClosureFunc take an "outerfn *Func" parameter because I was planning on having it handle closure naming, until remembering that naming needs to wait until typecheck for noder. We don't actually need the *Func yet, just to know whether it's non-nil. So change the parameter to a bool, which simplifies callers a little. Change-Id: Ie83ee4a1ed0571ac6d3879ffd8474c6c3c1a9ff9 Reviewed-on: https://go-review.googlesource.com/c/go/+/327450 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: Cuong Manh Le TryBot-Result: Go Bot --- src/cmd/compile/internal/inline/inl.go | 7 +------ src/cmd/compile/internal/ir/func.go | 17 ++++++++++++----- src/cmd/compile/internal/noder/expr.go | 2 +- src/cmd/compile/internal/noder/noder.go | 2 +- src/cmd/compile/internal/noder/stencil.go | 4 ++-- src/cmd/compile/internal/typecheck/iimport.go | 2 +- src/cmd/compile/internal/walk/order.go | 6 ++---- 7 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index 76a15dab8b..0620191bbf 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -1153,13 +1153,8 @@ func (subst *inlsubst) closure(n *ir.ClosureExpr) ir.Node { //fmt.Printf("Inlining func %v with closure into %v\n", subst.fn, ir.FuncName(ir.CurFunc)) - outerfunc := subst.newclofn - if outerfunc == nil { - outerfunc = ir.CurFunc - } - oldfn := n.Func - newfn := ir.NewClosureFunc(oldfn.Pos(), outerfunc) + newfn := ir.NewClosureFunc(oldfn.Pos(), true) // Ntype can be nil for -G=3 mode. if oldfn.Nname.Ntype != nil { diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go index 3d4f8c4486..6480becc93 100644 --- a/src/cmd/compile/internal/ir/func.go +++ b/src/cmd/compile/internal/ir/func.go @@ -343,11 +343,13 @@ func closureName(outerfn *Func) *types.Sym { return pkg.Lookup(fmt.Sprintf("%s.%s%d", outer, prefix, *gen)) } -// NewClosureFunc creates a new Func to represent a function literal -// within outerfn. -func NewClosureFunc(pos src.XPos, outerfn *Func) *Func { +// NewClosureFunc creates a new Func to represent a function literal. +// If hidden is true, then the closure is marked hidden (i.e., as a +// function literal contained within another function, rather than a +// package-scope variable initialization expression). +func NewClosureFunc(pos src.XPos, hidden bool) *Func { fn := NewFunc(pos) - fn.SetIsHiddenClosure(outerfn != nil) + fn.SetIsHiddenClosure(hidden) fn.Nname = NewNameAt(pos, BlankNode.Sym()) fn.Nname.Func = fn @@ -361,7 +363,12 @@ func NewClosureFunc(pos src.XPos, outerfn *Func) *Func { // NameClosure generates a unique for the given function literal, // which must have appeared within outerfn. func NameClosure(clo *ClosureExpr, outerfn *Func) { - name := clo.Func.Nname + fn := clo.Func + if fn.IsHiddenClosure() != (outerfn != nil) { + base.FatalfAt(clo.Pos(), "closure naming inconsistency: hidden %v, but outer %v", fn.IsHiddenClosure(), outerfn) + } + + name := fn.Nname if !IsBlank(name) { base.FatalfAt(clo.Pos(), "closure already named: %v", name) } diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 86a61bc759..98dc504ee9 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -373,7 +373,7 @@ func (g *irgen) compLit(typ types2.Type, lit *syntax.CompositeLit) ir.Node { } func (g *irgen) funcLit(typ2 types2.Type, expr *syntax.FuncLit) ir.Node { - fn := ir.NewClosureFunc(g.pos(expr), ir.CurFunc) + fn := ir.NewClosureFunc(g.pos(expr), ir.CurFunc != nil) ir.NameClosure(fn.OClosure, ir.CurFunc) typ := g.typ(typ2) diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index ced3f32a53..63822d3089 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -1803,7 +1803,7 @@ func fakeRecv() *ir.Field { } func (p *noder) funcLit(expr *syntax.FuncLit) ir.Node { - fn := ir.NewClosureFunc(p.pos(expr), ir.CurFunc) + fn := ir.NewClosureFunc(p.pos(expr), ir.CurFunc != nil) fn.Nname.Ntype = p.typeExpr(expr.Type) p.funcBody(fn, expr.Body) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index a82274a240..8b53671dbe 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -280,7 +280,7 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { // } // Make a new internal function. - fn := ir.NewClosureFunc(pos, outer) + fn := ir.NewClosureFunc(pos, outer != nil) ir.NameClosure(fn.OClosure, outer) // This is the dictionary we want to use. @@ -857,7 +857,7 @@ func (subst *subster) node(n ir.Node) ir.Node { // Need to duplicate x.Func.Nname, x.Func.Dcl, x.Func.ClosureVars, and // x.Func.Body. oldfn := x.Func - newfn := ir.NewClosureFunc(oldfn.Pos(), subst.newf) + newfn := ir.NewClosureFunc(oldfn.Pos(), subst.newf != nil) ir.NameClosure(newfn.OClosure, subst.newf) newfn.SetClosureCalled(oldfn.ClosureCalled()) diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index b1b3c27898..81f8ea05d9 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1283,7 +1283,7 @@ func (r *importReader) node() ir.Node { // All the remaining code below is similar to (*noder).funcLit(), but // with Dcls and ClosureVars lists already set up - fn := ir.NewClosureFunc(pos, r.curfn) + fn := ir.NewClosureFunc(pos, true) fn.Nname.SetType(typ) cvars := make([]*ir.Name, r.int64()) diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go index 750cb6bfc5..845bf03657 100644 --- a/src/cmd/compile/internal/walk/order.go +++ b/src/cmd/compile/internal/walk/order.go @@ -1704,9 +1704,7 @@ func (o *orderState) wrapGoDefer(n *ir.GoDeferStmt) { } // Create a new no-argument function that we'll hand off to defer. - outerfn := ir.CurFunc - - fn := ir.NewClosureFunc(base.Pos, outerfn) + fn := ir.NewClosureFunc(base.Pos, true) fn.Nname.SetType(types.NewSignature(types.LocalPkg, nil, nil, nil, nil)) fn.SetWrapper(true) @@ -1752,7 +1750,7 @@ func (o *orderState) wrapGoDefer(n *ir.GoDeferStmt) { // Finalize body, register function on the main decls list. fn.Body = []ir.Node{newcall} - ir.FinishCaptureNames(n.Pos(), outerfn, fn) + ir.FinishCaptureNames(n.Pos(), ir.CurFunc, fn) // Create closure expr clo := typecheck.Expr(fn.OClosure).(*ir.ClosureExpr) -- GitLab From 8eeaf961c50973b0aa2065d2c31dfa5d9949bf93 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Sat, 12 Jun 2021 18:44:51 -0700 Subject: [PATCH 0271/2500] [dev.typeparams] cmd/compile: move //go:embed -lang check to noder User errors should be reported in noder and/or typecheck, we already know the -lang flag's value during noding, and checking it then works better for unified IR. The "multiple files for type" and "cannot apply to var of type" errors should also be moved to typecheck, but then they'd have to be duplicated for -G=3 mode (because it avoids typecheck). So those are left behind for now. Change-Id: I7caf16163c9faf975784acacdb8147514d2e698e Reviewed-on: https://go-review.googlesource.com/c/go/+/327609 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/noder/noder.go | 2 ++ src/cmd/compile/internal/staticdata/embed.go | 7 ------- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index 63822d3089..d417edcbd5 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -1886,6 +1886,8 @@ func checkEmbed(decl *syntax.VarDecl, haveEmbed, withinFunc bool) error { return errors.New("go:embed cannot apply to var without type") case withinFunc: return errors.New("go:embed cannot apply to var inside func") + case !types.AllowsGoVersion(types.LocalPkg, 1, 16): + return fmt.Errorf("go:embed requires go1.16 or later (-lang was set to %s; check go.mod)", base.Flag.Lang) default: return nil diff --git a/src/cmd/compile/internal/staticdata/embed.go b/src/cmd/compile/internal/staticdata/embed.go index 8936c4f5b4..0730d346b2 100644 --- a/src/cmd/compile/internal/staticdata/embed.go +++ b/src/cmd/compile/internal/staticdata/embed.go @@ -108,13 +108,6 @@ func WriteEmbed(v *ir.Name) { // TODO(mdempsky): User errors should be reported by the frontend. commentPos := (*v.Embed)[0].Pos - if !types.AllowsGoVersion(types.LocalPkg, 1, 16) { - prevPos := base.Pos - base.Pos = commentPos - base.ErrorfVers("go1.16", "go:embed") - base.Pos = prevPos - return - } if base.Flag.Cfg.Embed.Patterns == nil { base.ErrorfAt(commentPos, "invalid go:embed: build system did not supply embed configuration") return -- GitLab From 413c125da38990720744c0d98ab65c0d5b1602da Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Mon, 7 Jun 2021 17:51:51 -0400 Subject: [PATCH 0272/2500] [dev.fuzz] testing: convert seed corpus values where possible The types provided in f.Fuzz will be viewed as the canonical types for fuzzing. If the type is different for a seed corpus entry, then the testing package will attempt to convert it. If it can't convert it, f.Fuzz will fail. Currently, this allows converting types that may result in precision loss or a semantically different value. For example, an int(-1) can be converted to uint even though the value could be math.MaxUint64. There is a TODO to consider improving this in the future. Updates golang/go#45593 Change-Id: I2e752119662f46b68445d42b1ffa46dd30e9faea Reviewed-on: https://go-review.googlesource.com/c/go/+/325702 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Roland Shoemaker --- src/cmd/go/testdata/script/test_fuzz.txt | 38 ++++++++++++++++++-- src/internal/fuzz/fuzz.go | 45 +++++++++++++++++++++--- src/testing/fuzz.go | 14 +++++++- src/testing/internal/testdeps/deps.go | 4 +++ src/testing/testing.go | 6 ++-- 5 files changed, 97 insertions(+), 10 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt index 0b1b85f397..d3c7b4d55f 100644 --- a/src/cmd/go/testdata/script/test_fuzz.txt +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -131,6 +131,23 @@ stdout FAIL ! stdout ^ok stdout FAIL +# Test that converting compatible value from f.Add successful runs cleanly. +go test -run FuzzConvertType fuzz_add_test.go +stdout ^ok +! stdout FAIL + +# Test that converting incompatible value from f.Add fails. +! go test -run FuzzConvertIncompatibleType fuzz_add_test.go +! stdout ^ok +stdout FAIL + +# Test that converts value which would lose precision from f.Add. +# Consider making a test like this fail, as it may have unexpected +# consequences for the developer. +go test -v -run FuzzConvertLosePrecision fuzz_add_test.go +stdout ok +! stdout FAIL + # Test fatal with testdata seed corpus ! go test -run FuzzFail corpustesting/fuzz_testdata_corpus_test.go ! stdout ^ok @@ -344,19 +361,34 @@ func FuzzNilPanic(f *testing.F) { func FuzzUnsupported(f *testing.F) { m := make(map[string]bool) f.Add(m) - f.Fuzz(func(t *testing.T, b []byte) {}) + f.Fuzz(func(*testing.T, []byte) {}) } func FuzzAddDifferentNumber(f *testing.F) { f.Add([]byte("a")) f.Add([]byte("a"), []byte("b")) - f.Fuzz(func(t *testing.T, b []byte) {}) + f.Fuzz(func(*testing.T, []byte) {}) } func FuzzAddDifferentType(f *testing.F) { f.Add(false) f.Add(1234) - f.Fuzz(func(t *testing.T, b []byte) {}) + f.Fuzz(func(*testing.T, []byte) {}) +} + +func FuzzConvertIncompatibleType(f *testing.F) { + f.Add("abcde") + f.Fuzz(func(*testing.T, int64) {}) +} + +func FuzzConvertLosePrecision(f *testing.F) { + f.Add(-1) + f.Fuzz(func(*testing.T, uint) {}) +} + +func FuzzConvertType(f *testing.F) { + f.Add(1, "hello") + f.Fuzz(func(*testing.T, uint, []byte) {}) } -- corpustesting/fuzz_testdata_corpus_test.go -- diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 929f78bb17..9ffa8beb16 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -727,15 +727,52 @@ func readCorpusData(data []byte, types []reflect.Type) ([]interface{}, error) { if err != nil { return nil, fmt.Errorf("unmarshal: %v", err) } + if err = CheckCorpus(vals, types); err != nil { + return nil, err + } + return vals, nil +} + +// CheckCorpus verifies that the types in vals match the expected types +// provided. If not, attempt to convert them. If that's not possible, return an +// error. +func CheckCorpus(vals []interface{}, types []reflect.Type) error { if len(vals) != len(types) { - return nil, fmt.Errorf("wrong number of values in corpus file: %d, want %d", len(vals), len(types)) + return fmt.Errorf("wrong number of values in corpus file: %d, want %d", len(vals), len(types)) } for i := range types { - if reflect.TypeOf(vals[i]) != types[i] { - return nil, fmt.Errorf("mismatched types in corpus file: %v, want %v", vals, types) + orig := reflect.ValueOf(vals[i]) + origType := orig.Type() + wantType := types[i] + if origType == wantType { + continue // already the same type + } + // Attempt to convert the corpus value to the expected type + if !origType.ConvertibleTo(wantType) { + return fmt.Errorf("cannot convert %v to %v", origType, wantType) } + convertedVal, ok := convertToType(orig, wantType) + if !ok { + return fmt.Errorf("error converting %v to %v", origType, wantType) + } + // TODO: Check that the value didn't change. + // e.g. val went from int64(-1) -> uint(0) -> int64(0) which should fail + + // Updates vals to use the newly converted value of the expected type. + vals[i] = convertedVal.Interface() } - return vals, nil + return nil +} + +func convertToType(orig reflect.Value, t reflect.Type) (converted reflect.Value, ok bool) { + // Convert might panic even if ConvertibleTo returns true, so catch + // that panic and return false. + defer func() { + if r := recover(); r != nil { + ok = false + } + }() + return orig.Convert(t), true } // writeToCorpus atomically writes the given bytes to a new file in testdata. diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 9f0bb1ec50..b4c1ffcdd5 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -222,7 +222,7 @@ func (f *F) TempDir() string { // Add will add the arguments to the seed corpus for the fuzz target. This will // be a no-op if called after or within the Fuzz function. The args must match -// those in the Fuzz function. +// or be convertible to those in the Fuzz function. func (f *F) Add(args ...interface{}) { var values []interface{} for i := range args { @@ -291,6 +291,15 @@ func (f *F) Fuzz(ff interface{}) { types = append(types, t) } + // Check the corpus provided by f.Add + for _, c := range f.corpus { + if err := f.fuzzContext.checkCorpus(c.Values, types); err != nil { + // TODO: Is there a way to save which line number is associated + // with the f.Add call that failed? + f.Fatal(err) + } + } + // Load seed corpus c, err := f.fuzzContext.readCorpus(filepath.Join(corpusDir, f.name), types) if err != nil { @@ -470,6 +479,7 @@ type fuzzContext struct { coordinateFuzzing func(time.Duration, int64, time.Duration, int64, int, []corpusEntry, []reflect.Type, string, string) error runFuzzWorker func(func(corpusEntry) error) error readCorpus func(string, []reflect.Type) ([]corpusEntry, error) + checkCorpus func(vals []interface{}, types []reflect.Type) error resetCoverage func() snapshotCoverage func() } @@ -487,6 +497,7 @@ func runFuzzTargets(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran, ok bo fctx := &fuzzContext{ importPath: deps.ImportPath, readCorpus: deps.ReadCorpus, + checkCorpus: deps.CheckCorpus, resetCoverage: deps.ResetCoverage, snapshotCoverage: deps.SnapshotCoverage, } @@ -543,6 +554,7 @@ func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran, ok bool) fctx := &fuzzContext{ importPath: deps.ImportPath, readCorpus: deps.ReadCorpus, + checkCorpus: deps.CheckCorpus, resetCoverage: deps.ResetCoverage, snapshotCoverage: deps.SnapshotCoverage, } diff --git a/src/testing/internal/testdeps/deps.go b/src/testing/internal/testdeps/deps.go index 01390f51d3..c612355a00 100644 --- a/src/testing/internal/testdeps/deps.go +++ b/src/testing/internal/testdeps/deps.go @@ -186,6 +186,10 @@ func (TestDeps) ReadCorpus(dir string, types []reflect.Type) ([]fuzz.CorpusEntry return fuzz.ReadCorpus(dir, types) } +func (TestDeps) CheckCorpus(vals []interface{}, types []reflect.Type) error { + return fuzz.CheckCorpus(vals, types) +} + func (TestDeps) ResetCoverage() { fuzz.ResetCoverage() } diff --git a/src/testing/testing.go b/src/testing/testing.go index 82b422a414..fa92dbb005 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1463,8 +1463,9 @@ func (f matchStringOnly) RunFuzzWorker(func(corpusEntry) error) error { return e func (f matchStringOnly) ReadCorpus(string, []reflect.Type) ([]corpusEntry, error) { return nil, errMain } -func (f matchStringOnly) ResetCoverage() {} -func (f matchStringOnly) SnapshotCoverage() {} +func (f matchStringOnly) CheckCorpus([]interface{}, []reflect.Type) error { return nil } +func (f matchStringOnly) ResetCoverage() {} +func (f matchStringOnly) SnapshotCoverage() {} // Main is an internal function, part of the implementation of the "go test" command. // It was exported because it is cross-package and predates "internal" packages. @@ -1510,6 +1511,7 @@ type testDeps interface { CoordinateFuzzing(time.Duration, int64, time.Duration, int64, int, []corpusEntry, []reflect.Type, string, string) error RunFuzzWorker(func(corpusEntry) error) error ReadCorpus(string, []reflect.Type) ([]corpusEntry, error) + CheckCorpus([]interface{}, []reflect.Type) error ResetCoverage() SnapshotCoverage() } -- GitLab From 79cd1687e6abf8c565281d310b4c2b44a8d4bb84 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 13 May 2021 20:23:13 -0700 Subject: [PATCH 0273/2500] [dev.typeparams] cmd/compile: unified IR construction This CL adds a new unified IR construction mode to the frontend. It's purely additive, and all files include "UNREVIEWED" at the top, like how types2 was initially imported. The next CL adds a -d=unified flag to actually enable unified IR mode. See below for more details, but some highlights: 1. It adds ~6kloc (excluding enum listings and stringer output), but I estimate it will allow removing ~14kloc (see CL 324670, including its commit message); 2. When enabled by default, it passes more tests than -G=3 does (see CL 325213 and CL 324673); 3. Without requiring any new code, it supports inlining of more code than the current inliner (see CL 324574; contrast CL 283112 and CL 266203, which added support for inlining function literals and type switches, respectively); 4. Aside from dictionaries (which I intend to add still), its support for generics is more complete (e.g., it fully supports local types, including local generic types within generic functions and instantiating generic types with local types; see test/typeparam/nested.go); 5. It supports lazy loading of types and objects for types2 type checking; 6. It supports re-exporting of types, objects, and inline bodies without needing to parse them into IR; 7. The new export data format has extensive support for debugging with "sync" markers, so mistakes during development are easier to catch; 8. When compiling with -d=inlfuncswithclosures=0, it enables "quirks mode" where it generates output that passes toolstash -cmp. -- The new unified IR pipeline combines noding, stenciling, inlining, and import/export into a single, shared code path. Previously, IR trees went through multiple phases of copying during compilation: 1. "Noding": the syntax AST is copied into the initial IR form. To support generics, there's now also "irgen", which implements the same idea, but takes advantage of types2 type-checking results to more directly construct IR. 2. "Stenciling": generic IR forms are copied into instantiated IR forms, substituting type parameters as appropriate. 3. "Inlining": the inliner made backup copies of inlinable functions, and then copied them again when inlining into a call site, with some modifications (e.g., updating position information, rewriting variable references, changing "return" statements into "goto"). 4. "Importing/exporting": the exporter wrote out the IR as saved by the inliner, and then the importer read it back as to be used by the inliner again. Normal functions are imported/exported "desugared", while generic functions are imported/exported in source form. These passes are all conceptually the same thing: make a copy of a function body, maybe with some minor changes/substitutions. However, they're all completely separate implementations that frequently run into the same issues because IR has many nuanced corner cases. For example, inlining currently doesn't support local defined types, "range" loops, or labeled "for"/"switch" statements, because these require special handling around Sym references. We've recently extended the inliner to support new features like inlining type switches and function literals, and they've had issues. The exporter only knows how to export from IR form, so when re-exporting inlinable functions (e.g., methods on imported types that are exposed via exported APIs), these functions may need to be imported as IR for the sole purpose of being immediately exported back out again. By unifying all of these modes of copying into a single code path that cleanly separates concerns, we eliminate many of these possible issues. Some recent examples: 1. Issues #45743 and #46472 were issues where type switches were mishandled by inlining and stenciling, respectively; but neither of these affected unified IR, because it constructs type switches using the exact same code as for normal functions. 2. CL 325409 fixes an issue in stenciling with implicit conversion of values of type-parameter type to variables of interface type, but this issue did not affect unified IR. Change-Id: I5a05991fe16d68bb0f712503e034cb9f2d19e296 Reviewed-on: https://go-review.googlesource.com/c/go/+/324573 Trust: Matthew Dempsky Trust: Robert Griesemer Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/noder/codes.go | 126 ++ src/cmd/compile/internal/noder/decoder.go | 243 ++ src/cmd/compile/internal/noder/encoder.go | 245 ++ src/cmd/compile/internal/noder/linker.go | 296 +++ src/cmd/compile/internal/noder/quirks.go | 453 ++++ src/cmd/compile/internal/noder/reader.go | 1970 +++++++++++++++++ src/cmd/compile/internal/noder/reader2.go | 463 ++++ src/cmd/compile/internal/noder/reloc.go | 40 + src/cmd/compile/internal/noder/sync.go | 154 ++ .../internal/noder/syncmarker_string.go | 152 ++ src/cmd/compile/internal/noder/unified.go | 276 +++ src/cmd/compile/internal/noder/writer.go | 1746 +++++++++++++++ 12 files changed, 6164 insertions(+) create mode 100644 src/cmd/compile/internal/noder/codes.go create mode 100644 src/cmd/compile/internal/noder/decoder.go create mode 100644 src/cmd/compile/internal/noder/encoder.go create mode 100644 src/cmd/compile/internal/noder/linker.go create mode 100644 src/cmd/compile/internal/noder/quirks.go create mode 100644 src/cmd/compile/internal/noder/reader.go create mode 100644 src/cmd/compile/internal/noder/reader2.go create mode 100644 src/cmd/compile/internal/noder/reloc.go create mode 100644 src/cmd/compile/internal/noder/sync.go create mode 100644 src/cmd/compile/internal/noder/syncmarker_string.go create mode 100644 src/cmd/compile/internal/noder/unified.go create mode 100644 src/cmd/compile/internal/noder/writer.go diff --git a/src/cmd/compile/internal/noder/codes.go b/src/cmd/compile/internal/noder/codes.go new file mode 100644 index 0000000000..4a6a4e8307 --- /dev/null +++ b/src/cmd/compile/internal/noder/codes.go @@ -0,0 +1,126 @@ +// UNREVIEWED + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package noder + +type code interface { + marker() syncMarker + value() int +} + +type codeVal int + +func (c codeVal) marker() syncMarker { return syncVal } +func (c codeVal) value() int { return int(c) } + +const ( + valBool codeVal = iota + valString + valInt64 + valBigInt + valBigRat + valBigFloat +) + +type codeType int + +func (c codeType) marker() syncMarker { return syncType } +func (c codeType) value() int { return int(c) } + +const ( + typeBasic codeType = iota + typeNamed + typePointer + typeSlice + typeArray + typeChan + typeMap + typeSignature + typeStruct + typeInterface + typeUnion + typeTypeParam +) + +type codeObj int + +func (c codeObj) marker() syncMarker { return syncCodeObj } +func (c codeObj) value() int { return int(c) } + +const ( + objAlias codeObj = iota + objConst + objType + objFunc + objVar + objStub +) + +type codeStmt int + +func (c codeStmt) marker() syncMarker { return syncStmt1 } +func (c codeStmt) value() int { return int(c) } + +const ( + stmtEnd codeStmt = iota + stmtLabel + stmtBlock + stmtExpr + stmtSend + stmtAssign + stmtAssignOp + stmtIncDec + stmtBranch + stmtCall + stmtReturn + stmtIf + stmtFor + stmtSwitch + stmtSelect + + // TODO(mdempsky): Remove after we don't care about toolstash -cmp. + stmtTypeDeclHack +) + +type codeExpr int + +func (c codeExpr) marker() syncMarker { return syncExpr } +func (c codeExpr) value() int { return int(c) } + +// TODO(mdempsky): Split expr into addr, for lvalues. +const ( + exprNone codeExpr = iota + exprConst + exprType // type expression + exprLocal // local variable + exprName // global variable or function + exprBlank + exprCompLit + exprFuncLit + exprSelector + exprIndex + exprSlice + exprAssert + exprUnaryOp + exprBinaryOp + exprCall + + // TODO(mdempsky): Handle in switchStmt directly instead. + exprTypeSwitchGuard +) + +type codeDecl int + +func (c codeDecl) marker() syncMarker { return syncDecl } +func (c codeDecl) value() int { return int(c) } + +const ( + declEnd codeDecl = iota + declFunc + declMethod + declVar + declOther +) diff --git a/src/cmd/compile/internal/noder/decoder.go b/src/cmd/compile/internal/noder/decoder.go new file mode 100644 index 0000000000..023388875c --- /dev/null +++ b/src/cmd/compile/internal/noder/decoder.go @@ -0,0 +1,243 @@ +// UNREVIEWED + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package noder + +import ( + "encoding/binary" + "fmt" + "go/constant" + "go/token" + "math/big" + "os" + "strings" + + "cmd/compile/internal/base" +) + +type pkgDecoder struct { + pkgPath string + + elemEndsEnds [numRelocs]uint32 + elemEnds []uint32 + elemData string +} + +func newPkgDecoder(pkgPath, input string) pkgDecoder { + pr := pkgDecoder{ + pkgPath: pkgPath, + } + + // TODO(mdempsky): Implement direct indexing of input string to + // avoid copying the position information. + + r := strings.NewReader(input) + + assert(binary.Read(r, binary.LittleEndian, pr.elemEndsEnds[:]) == nil) + + pr.elemEnds = make([]uint32, pr.elemEndsEnds[len(pr.elemEndsEnds)-1]) + assert(binary.Read(r, binary.LittleEndian, pr.elemEnds[:]) == nil) + + pos, err := r.Seek(0, os.SEEK_CUR) + assert(err == nil) + + pr.elemData = input[pos:] + assert(len(pr.elemData) == int(pr.elemEnds[len(pr.elemEnds)-1])) + + return pr +} + +func (pr *pkgDecoder) numElems(k reloc) int { + count := int(pr.elemEndsEnds[k]) + if k > 0 { + count -= int(pr.elemEndsEnds[k-1]) + } + return count +} + +func (pr *pkgDecoder) totalElems() int { + return len(pr.elemEnds) +} + +func (pr *pkgDecoder) absIdx(k reloc, idx int) int { + absIdx := idx + if k > 0 { + absIdx += int(pr.elemEndsEnds[k-1]) + } + if absIdx >= int(pr.elemEndsEnds[k]) { + base.Fatalf("%v:%v is out of bounds; %v", k, idx, pr.elemEndsEnds) + } + return absIdx +} + +func (pr *pkgDecoder) dataIdx(k reloc, idx int) string { + absIdx := pr.absIdx(k, idx) + + var start uint32 + if absIdx > 0 { + start = pr.elemEnds[absIdx-1] + } + end := pr.elemEnds[absIdx] + + return pr.elemData[start:end] +} + +func (pr *pkgDecoder) stringIdx(idx int) string { + return pr.dataIdx(relocString, idx) +} + +func (pr *pkgDecoder) newDecoder(k reloc, idx int, marker syncMarker) decoder { + r := pr.newDecoderRaw(k, idx) + r.sync(marker) + return r +} + +func (pr *pkgDecoder) newDecoderRaw(k reloc, idx int) decoder { + r := decoder{ + common: pr, + k: k, + idx: idx, + } + + // TODO(mdempsky) r.data.Reset(...) after #44505 is resolved. + r.data = *strings.NewReader(pr.dataIdx(k, idx)) + + r.sync(syncRelocs) + r.relocs = make([]relocEnt, r.len()) + for i := range r.relocs { + r.sync(syncReloc) + r.relocs[i] = relocEnt{reloc(r.len()), r.len()} + } + + return r +} + +type decoder struct { + common *pkgDecoder + + relocs []relocEnt + data strings.Reader + + k reloc + idx int +} + +func (r *decoder) checkErr(err error) { + if err != nil { + base.Fatalf("unexpected error: %v", err) + } +} + +func (r *decoder) sync(m syncMarker) { + if debug { + pos, err0 := r.data.Seek(0, os.SEEK_CUR) + x, err := r.data.ReadByte() + r.checkErr(err) + if x != byte(m) { + // TODO(mdempsky): Revisit this error message, and make it more + // useful (e.g., include r.p.pkgPath). + base.Fatalf("data sync error: found %v at %v (%v) in (%v:%v), but expected %v", syncMarker(x), pos, err0, r.k, r.idx, m) + } + } +} + +func (r *decoder) bool() bool { + r.sync(syncBool) + x, err := r.data.ReadByte() + r.checkErr(err) + assert(x < 2) + return x != 0 +} + +func (r *decoder) int64() int64 { + r.sync(syncInt64) + x, err := binary.ReadVarint(&r.data) + r.checkErr(err) + return x +} + +func (r *decoder) uint64() uint64 { + r.sync(syncUint64) + x, err := binary.ReadUvarint(&r.data) + r.checkErr(err) + return x +} + +func (r *decoder) len() int { x := r.uint64(); v := int(x); assert(uint64(v) == x); return v } +func (r *decoder) int() int { x := r.int64(); v := int(x); assert(int64(v) == x); return v } +func (r *decoder) uint() uint { x := r.uint64(); v := uint(x); assert(uint64(v) == x); return v } + +func (r *decoder) code(mark syncMarker) int { + r.sync(mark) + return r.len() +} + +func (r *decoder) reloc(k reloc) int { + r.sync(syncUseReloc) + idx := r.len() + + e := r.relocs[idx] + assert(e.kind == k) + return e.idx +} + +func (r *decoder) string() string { + r.sync(syncString) + return r.common.stringIdx(r.reloc(relocString)) +} + +func (r *decoder) strings() []string { + res := make([]string, r.len()) + for i := range res { + res[i] = r.string() + } + return res +} + +func (r *decoder) rawValue() constant.Value { + isComplex := r.bool() + val := r.scalar() + if isComplex { + val = constant.BinaryOp(val, token.ADD, constant.MakeImag(r.scalar())) + } + return val +} + +func (r *decoder) scalar() constant.Value { + switch tag := codeVal(r.code(syncVal)); tag { + default: + panic(fmt.Sprintf("unexpected scalar tag: %v", tag)) + + case valBool: + return constant.MakeBool(r.bool()) + case valString: + return constant.MakeString(r.string()) + case valInt64: + return constant.MakeInt64(r.int64()) + case valBigInt: + return constant.Make(r.bigInt()) + case valBigRat: + num := r.bigInt() + denom := r.bigInt() + return constant.Make(new(big.Rat).SetFrac(num, denom)) + case valBigFloat: + return constant.Make(r.bigFloat()) + } +} + +func (r *decoder) bigInt() *big.Int { + v := new(big.Int).SetBytes([]byte(r.string())) + if r.bool() { + v.Neg(v) + } + return v +} + +func (r *decoder) bigFloat() *big.Float { + v := new(big.Float).SetPrec(512) + assert(v.UnmarshalText([]byte(r.string())) == nil) + return v +} diff --git a/src/cmd/compile/internal/noder/encoder.go b/src/cmd/compile/internal/noder/encoder.go new file mode 100644 index 0000000000..dc288dc29f --- /dev/null +++ b/src/cmd/compile/internal/noder/encoder.go @@ -0,0 +1,245 @@ +// UNREVIEWED + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package noder + +import ( + "bytes" + "encoding/binary" + "fmt" + "go/constant" + "io" + "math/big" + + "cmd/compile/internal/base" +) + +type pkgEncoder struct { + elems [numRelocs][]string + + stringsIdx map[string]int +} + +func newPkgEncoder() pkgEncoder { + return pkgEncoder{ + stringsIdx: make(map[string]int), + } +} + +func (pw *pkgEncoder) dump(out io.Writer) { + writeUint32 := func(x uint32) { + assert(binary.Write(out, binary.LittleEndian, x) == nil) + } + + var sum uint32 + for _, elems := range &pw.elems { + sum += uint32(len(elems)) + writeUint32(sum) + } + + sum = 0 + for _, elems := range &pw.elems { + for _, elem := range elems { + sum += uint32(len(elem)) + writeUint32(sum) + } + } + + for _, elems := range &pw.elems { + for _, elem := range elems { + _, err := io.WriteString(out, elem) + assert(err == nil) + } + } +} + +func (pw *pkgEncoder) stringIdx(s string) int { + if idx, ok := pw.stringsIdx[s]; ok { + assert(pw.elems[relocString][idx] == s) + return idx + } + + idx := len(pw.elems[relocString]) + pw.elems[relocString] = append(pw.elems[relocString], s) + pw.stringsIdx[s] = idx + return idx +} + +func (pw *pkgEncoder) newEncoder(k reloc, marker syncMarker) encoder { + e := pw.newEncoderRaw(k) + e.sync(marker) + return e +} + +func (pw *pkgEncoder) newEncoderRaw(k reloc) encoder { + idx := len(pw.elems[k]) + pw.elems[k] = append(pw.elems[k], "") // placeholder + + return encoder{ + p: pw, + k: k, + idx: idx, + } +} + +// Encoders + +type encoder struct { + p *pkgEncoder + + relocs []relocEnt + data bytes.Buffer + + k reloc + idx int +} + +func (w *encoder) flush() int { + var sb bytes.Buffer // TODO(mdempsky): strings.Builder after #44505 is resolved + + // Backup the data so we write the relocations at the front. + var tmp bytes.Buffer + io.Copy(&tmp, &w.data) + + // TODO(mdempsky): Consider writing these out separately so they're + // easier to strip, along with function bodies, so that we can prune + // down to just the data that's relevant to go/types. + w.sync(syncRelocs) + w.len(len(w.relocs)) + for _, rent := range w.relocs { + w.sync(syncReloc) + w.len(int(rent.kind)) + w.len(rent.idx) + } + + io.Copy(&sb, &w.data) + io.Copy(&sb, &tmp) + w.p.elems[w.k][w.idx] = sb.String() + + return w.idx +} + +func (w *encoder) checkErr(err error) { + if err != nil { + base.Fatalf("unexpected error: %v", err) + } +} + +func (w *encoder) sync(m syncMarker) { + if debug { + err := w.data.WriteByte(byte(m)) + w.checkErr(err) + } +} + +func (w *encoder) bool(b bool) bool { + w.sync(syncBool) + var x byte + if b { + x = 1 + } + err := w.data.WriteByte(x) + w.checkErr(err) + return b +} + +func (w *encoder) int64(x int64) { + w.sync(syncInt64) + var buf [binary.MaxVarintLen64]byte + n := binary.PutVarint(buf[:], x) + _, err := w.data.Write(buf[:n]) + w.checkErr(err) +} + +func (w *encoder) uint64(x uint64) { + w.sync(syncUint64) + var buf [binary.MaxVarintLen64]byte + n := binary.PutUvarint(buf[:], x) + _, err := w.data.Write(buf[:n]) + w.checkErr(err) +} + +func (w *encoder) len(x int) { assert(x >= 0); w.uint64(uint64(x)) } +func (w *encoder) int(x int) { w.int64(int64(x)) } +func (w *encoder) uint(x uint) { w.uint64(uint64(x)) } + +func (w *encoder) reloc(r reloc, idx int) { + w.sync(syncUseReloc) + + // TODO(mdempsky): Use map for lookup. + for i, rent := range w.relocs { + if rent.kind == r && rent.idx == idx { + w.len(i) + return + } + } + + w.len(len(w.relocs)) + w.relocs = append(w.relocs, relocEnt{r, idx}) +} + +func (w *encoder) code(c code) { + w.sync(c.marker()) + w.len(c.value()) +} + +func (w *encoder) string(s string) { + w.sync(syncString) + w.reloc(relocString, w.p.stringIdx(s)) +} + +func (w *encoder) strings(ss []string) { + w.len(len(ss)) + for _, s := range ss { + w.string(s) + } +} + +func (w *encoder) rawValue(val constant.Value) { + if w.bool(val.Kind() == constant.Complex) { + w.scalar(constant.Real(val)) + w.scalar(constant.Imag(val)) + } else { + w.scalar(val) + } +} + +func (w *encoder) scalar(val constant.Value) { + switch v := constant.Val(val).(type) { + default: + panic(fmt.Sprintf("unhandled %v (%v)", val, val.Kind())) + case bool: + w.code(valBool) + w.bool(v) + case string: + w.code(valString) + w.string(v) + case int64: + w.code(valInt64) + w.int64(v) + case *big.Int: + w.code(valBigInt) + w.bigInt(v) + case *big.Rat: + w.code(valBigRat) + w.bigInt(v.Num()) + w.bigInt(v.Denom()) + case *big.Float: + w.code(valBigFloat) + w.bigFloat(v) + } +} + +func (w *encoder) bigInt(v *big.Int) { + b := v.Bytes() + w.string(string(b)) // TODO: More efficient encoding. + w.bool(v.Sign() < 0) +} + +func (w *encoder) bigFloat(v *big.Float) { + b := v.Append(nil, 'p', -1) + w.string(string(b)) // TODO: More efficient encoding. +} diff --git a/src/cmd/compile/internal/noder/linker.go b/src/cmd/compile/internal/noder/linker.go new file mode 100644 index 0000000000..324902d246 --- /dev/null +++ b/src/cmd/compile/internal/noder/linker.go @@ -0,0 +1,296 @@ +// UNREVIEWED + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package noder + +import ( + "io" + + "cmd/compile/internal/base" + "cmd/compile/internal/ir" + "cmd/compile/internal/reflectdata" + "cmd/compile/internal/types" + "cmd/internal/goobj" + "cmd/internal/obj" +) + +// This file implements the unified IR linker, which combines the +// local package's stub data with imported package data to produce a +// complete export data file. It also rewrites the compiler's +// extension data sections based on the results of compilation (e.g., +// the function inlining cost and linker symbol index assignments). +// +// TODO(mdempsky): Using the name "linker" here is confusing, because +// readers are likely to mistake references to it for cmd/link. But +// there's a shortage of good names for "something that combines +// multiple parts into a cohesive whole"... e.g., "assembler" and +// "compiler" are also already taken. + +type linker struct { + pw pkgEncoder + + pkgs map[string]int + decls map[*types.Sym]int +} + +func (l *linker) relocAll(pr *pkgReader, relocs []relocEnt) []relocEnt { + res := make([]relocEnt, len(relocs)) + for i, rent := range relocs { + rent.idx = l.relocIdx(pr, rent.kind, rent.idx) + res[i] = rent + } + return res +} + +func (l *linker) relocIdx(pr *pkgReader, k reloc, idx int) int { + assert(pr != nil) + + absIdx := pr.absIdx(k, idx) + + if newidx := pr.newindex[absIdx]; newidx != 0 { + return ^newidx + } + + var newidx int + switch k { + case relocString: + newidx = l.relocString(pr, idx) + case relocPkg: + newidx = l.relocPkg(pr, idx) + case relocObj: + newidx = l.relocObj(pr, idx) + + default: + // Generic relocations. + // + // TODO(mdempsky): Deduplicate more sections? In fact, I think + // every section could be deduplicated. This would also be easier + // if we do external relocations. + + w := l.pw.newEncoderRaw(k) + l.relocCommon(pr, &w, k, idx) + newidx = w.idx + } + + pr.newindex[absIdx] = ^newidx + + return newidx +} + +func (l *linker) relocString(pr *pkgReader, idx int) int { + return l.pw.stringIdx(pr.stringIdx(idx)) +} + +func (l *linker) relocPkg(pr *pkgReader, idx int) int { + path := pr.peekPkgPath(idx) + + if newidx, ok := l.pkgs[path]; ok { + return newidx + } + + r := pr.newDecoder(relocPkg, idx, syncPkgDef) + w := l.pw.newEncoder(relocPkg, syncPkgDef) + l.pkgs[path] = w.idx + + // TODO(mdempsky): We end up leaving an empty string reference here + // from when the package was originally written as "". Probably not + // a big deal, but a little annoying. Maybe relocating + // cross-references in place is the way to go after all. + w.relocs = l.relocAll(pr, r.relocs) + + _ = r.string() // original path + w.string(path) + + io.Copy(&w.data, &r.data) + + return w.flush() +} + +func (l *linker) relocObj(pr *pkgReader, idx int) int { + path, name, tag, _ := pr.peekObj(idx) + sym := types.NewPkg(path, "").Lookup(name) + + if newidx, ok := l.decls[sym]; ok { + return newidx + } + + if tag == objStub && path != "builtin" && path != "unsafe" { + pri, ok := objReader[sym] + if !ok { + base.Fatalf("missing reader for %q.%v", path, name) + } + assert(ok) + + pr = pri.pr + idx = pri.idx + + path2, name2, tag2, _ := pr.peekObj(idx) + sym2 := types.NewPkg(path2, "").Lookup(name2) + assert(sym == sym2) + assert(tag2 != objStub) + } + + w := l.pw.newEncoderRaw(relocObj) + bside := l.pw.newEncoderRaw(relocObjExt) + assert(bside.idx == w.idx) + l.decls[sym] = w.idx + + l.relocCommon(pr, &w, relocObj, idx) + + var obj *ir.Name + if path == "" { + var ok bool + obj, ok = sym.Def.(*ir.Name) + + // Generic types and functions won't have definitions. + // For now, just generically copy their extension data. + if !ok && base.Flag.G == 0 { + base.Fatalf("missing definition for %v", sym) + } + } + + if obj != nil { + bside.sync(syncObject1) + switch tag { + case objFunc: + l.relocFuncExt(&bside, obj) + case objType: + l.relocTypeExt(&bside, obj) + case objVar: + l.relocVarExt(&bside, obj) + } + bside.flush() + } else { + l.relocCommon(pr, &bside, relocObjExt, idx) + } + + return w.idx +} + +func (l *linker) relocCommon(pr *pkgReader, w *encoder, k reloc, idx int) { + r := pr.newDecoderRaw(k, idx) + w.relocs = l.relocAll(pr, r.relocs) + io.Copy(&w.data, &r.data) + w.flush() +} + +func (l *linker) pragmaFlag(w *encoder, pragma ir.PragmaFlag) { + w.sync(syncPragma) + w.int(int(pragma)) +} + +func (l *linker) relocFuncExt(w *encoder, name *ir.Name) { + w.sync(syncFuncExt) + + l.pragmaFlag(w, name.Func.Pragma) + l.linkname(w, name) + + // Relocated extension data. + w.bool(true) + + // Record definition ABI so cross-ABI calls can be direct. + // This is important for the performance of calling some + // common functions implemented in assembly (e.g., bytealg). + w.uint64(uint64(name.Func.ABI)) + + // Escape analysis. + for _, fs := range &types.RecvsParams { + for _, f := range fs(name.Type()).FieldSlice() { + w.string(f.Note) + } + } + + if inl := name.Func.Inl; w.bool(inl != nil) { + w.len(int(inl.Cost)) + w.bool(inl.CanDelayResults) + + pri, ok := bodyReader[name.Func] + assert(ok) + w.sync(syncAddBody) + w.reloc(relocBody, l.relocIdx(pri.pr, relocBody, pri.idx)) + } + + w.sync(syncEOF) +} + +func (l *linker) relocTypeExt(w *encoder, name *ir.Name) { + w.sync(syncTypeExt) + + typ := name.Type() + + l.pragmaFlag(w, name.Pragma()) + + // For type T, export the index of type descriptor symbols of T and *T. + l.lsymIdx(w, "", reflectdata.TypeLinksym(typ)) + l.lsymIdx(w, "", reflectdata.TypeLinksym(typ.PtrTo())) + + if typ.Kind() != types.TINTER { + for _, method := range typ.Methods().Slice() { + l.relocFuncExt(w, method.Nname.(*ir.Name)) + } + } +} + +func (l *linker) relocVarExt(w *encoder, name *ir.Name) { + w.sync(syncVarExt) + l.linkname(w, name) +} + +func (l *linker) linkname(w *encoder, name *ir.Name) { + w.sync(syncLinkname) + + linkname := name.Sym().Linkname + if !l.lsymIdx(w, linkname, name.Linksym()) { + w.string(linkname) + } +} + +func (l *linker) lsymIdx(w *encoder, linkname string, lsym *obj.LSym) bool { + if lsym.PkgIdx > goobj.PkgIdxSelf || (lsym.PkgIdx == goobj.PkgIdxInvalid && !lsym.Indexed()) || linkname != "" { + w.int64(-1) + return false + } + + // For a defined symbol, export its index. + // For re-exporting an imported symbol, pass its index through. + w.int64(int64(lsym.SymIdx)) + return true +} + +// @@@ Helpers + +// TODO(mdempsky): These should probably be removed. I think they're a +// smell that the export data format is not yet quite right. + +func (pr *pkgDecoder) peekPkgPath(idx int) string { + r := pr.newDecoder(relocPkg, idx, syncPkgDef) + path := r.string() + if path == "" { + path = pr.pkgPath + } + return path +} + +func (pr *pkgDecoder) peekObj(idx int) (string, string, codeObj, []int) { + r := pr.newDecoder(relocObj, idx, syncObject1) + r.sync(syncSym) + r.sync(syncPkg) + path := pr.peekPkgPath(r.reloc(relocPkg)) + name := r.string() + assert(name != "") + + r.sync(syncTypeParamBounds) + r.len() // implicits + bounds := make([]int, r.len()) + for i := range bounds { + r.sync(syncType) + bounds[i] = r.reloc(relocType) + } + + tag := codeObj(r.code(syncCodeObj)) + + return path, name, tag, bounds +} diff --git a/src/cmd/compile/internal/noder/quirks.go b/src/cmd/compile/internal/noder/quirks.go new file mode 100644 index 0000000000..9f33fc576d --- /dev/null +++ b/src/cmd/compile/internal/noder/quirks.go @@ -0,0 +1,453 @@ +// UNREVIEWED + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package noder + +import ( + "fmt" + + "cmd/compile/internal/base" + "cmd/compile/internal/ir" + "cmd/compile/internal/syntax" + "cmd/compile/internal/types2" + "cmd/internal/src" +) + +// This file defines helper functions useful for satisfying toolstash +// -cmp when compared against the legacy frontend behavior, but can be +// removed after that's no longer a concern. + +// quirksMode controls whether behavior specific to satsifying +// toolstash -cmp is used. +func quirksMode() bool { + // Currently, unified IR doesn't try to be compatible with + // -d=inlfuncswithclosures=1, so we overload this as a flag for + // enabling quirks mode. + return base.Debug.InlFuncsWithClosures == 0 +} + +// posBasesOf returns all of the position bases in the source files, +// as seen in a straightforward traversal. +// +// This is necessary to ensure position bases (and thus file names) +// get registered in the same order as noder would visit them. +func posBasesOf(noders []*noder) []*syntax.PosBase { + seen := make(map[*syntax.PosBase]bool) + var bases []*syntax.PosBase + + for _, p := range noders { + syntax.Walk(p.file, func(n syntax.Node) bool { + if b := n.Pos().Base(); !seen[b] { + bases = append(bases, b) + seen[b] = true + } + return false + }) + } + + return bases +} + +// importedObjsOf returns the imported objects (i.e., referenced +// objects not declared by curpkg) from the parsed source files, in +// the order that typecheck used to load their definitions. +// +// This is needed because loading the definitions for imported objects +// can also add file names. +func importedObjsOf(curpkg *types2.Package, info *types2.Info, noders []*noder) []types2.Object { + // This code is complex because it matches the precise order that + // typecheck recursively and repeatedly traverses the IR. It's meant + // to be thrown away eventually anyway. + + seen := make(map[types2.Object]bool) + var objs []types2.Object + + var phase int + + decls := make(map[types2.Object]syntax.Decl) + assoc := func(decl syntax.Decl, names ...*syntax.Name) { + for _, name := range names { + obj, ok := info.Defs[name] + assert(ok) + decls[obj] = decl + } + } + + for _, p := range noders { + syntax.Walk(p.file, func(n syntax.Node) bool { + switch n := n.(type) { + case *syntax.ConstDecl: + assoc(n, n.NameList...) + case *syntax.FuncDecl: + assoc(n, n.Name) + case *syntax.TypeDecl: + assoc(n, n.Name) + case *syntax.VarDecl: + assoc(n, n.NameList...) + case *syntax.BlockStmt: + return true + } + return false + }) + } + + var visited map[syntax.Decl]bool + + var resolveDecl func(n syntax.Decl) + var resolveNode func(n syntax.Node, top bool) + + resolveDecl = func(n syntax.Decl) { + if visited[n] { + return + } + visited[n] = true + + switch n := n.(type) { + case *syntax.ConstDecl: + resolveNode(n.Type, true) + resolveNode(n.Values, true) + + case *syntax.FuncDecl: + if n.Recv != nil { + resolveNode(n.Recv, true) + } + resolveNode(n.Type, true) + + case *syntax.TypeDecl: + resolveNode(n.Type, true) + + case *syntax.VarDecl: + if n.Type != nil { + resolveNode(n.Type, true) + } else { + resolveNode(n.Values, true) + } + } + } + + resolveObj := func(pos syntax.Pos, obj types2.Object) { + switch obj.Pkg() { + case nil: + // builtin; nothing to do + + case curpkg: + if decl, ok := decls[obj]; ok { + resolveDecl(decl) + } + + default: + if obj.Parent() == obj.Pkg().Scope() && !seen[obj] { + seen[obj] = true + objs = append(objs, obj) + } + } + } + + checkdefat := func(pos syntax.Pos, n *syntax.Name) { + if n.Value == "_" { + return + } + obj, ok := info.Uses[n] + if !ok { + obj, ok = info.Defs[n] + if !ok { + return + } + } + if obj == nil { + return + } + resolveObj(pos, obj) + } + checkdef := func(n *syntax.Name) { checkdefat(n.Pos(), n) } + + var later []syntax.Node + + resolveNode = func(n syntax.Node, top bool) { + if n == nil { + return + } + syntax.Walk(n, func(n syntax.Node) bool { + switch n := n.(type) { + case *syntax.Name: + checkdef(n) + + case *syntax.SelectorExpr: + if name, ok := n.X.(*syntax.Name); ok { + if _, isPkg := info.Uses[name].(*types2.PkgName); isPkg { + checkdefat(n.X.Pos(), n.Sel) + return true + } + } + + case *syntax.AssignStmt: + resolveNode(n.Rhs, top) + resolveNode(n.Lhs, top) + return true + + case *syntax.VarDecl: + resolveNode(n.Values, top) + + case *syntax.FuncLit: + if top { + resolveNode(n.Type, top) + later = append(later, n.Body) + return true + } + + case *syntax.BlockStmt: + if phase >= 3 { + for _, stmt := range n.List { + resolveNode(stmt, false) + } + } + return true + } + + return false + }) + } + + for phase = 1; phase <= 5; phase++ { + visited = map[syntax.Decl]bool{} + + for _, p := range noders { + for _, decl := range p.file.DeclList { + switch decl := decl.(type) { + case *syntax.ConstDecl: + resolveDecl(decl) + + case *syntax.FuncDecl: + resolveDecl(decl) + if phase >= 3 && decl.Body != nil { + resolveNode(decl.Body, true) + } + + case *syntax.TypeDecl: + if !decl.Alias || phase >= 2 { + resolveDecl(decl) + } + + case *syntax.VarDecl: + if phase >= 2 { + resolveNode(decl.Values, true) + resolveDecl(decl) + } + } + } + + if phase >= 5 { + syntax.Walk(p.file, func(n syntax.Node) bool { + if name, ok := n.(*syntax.Name); ok { + if obj, ok := info.Uses[name]; ok { + resolveObj(name.Pos(), obj) + } + } + return false + }) + } + } + + for i := 0; i < len(later); i++ { + resolveNode(later[i], true) + } + later = nil + } + + return objs +} + +// typeExprEndPos returns the position that noder would leave base.Pos +// after parsing the given type expression. +func typeExprEndPos(expr0 syntax.Expr) syntax.Pos { + for { + switch expr := expr0.(type) { + case *syntax.Name: + return expr.Pos() + case *syntax.SelectorExpr: + return expr.X.Pos() + + case *syntax.ParenExpr: + expr0 = expr.X + + case *syntax.Operation: + assert(expr.Op == syntax.Mul) + assert(expr.Y == nil) + expr0 = expr.X + + case *syntax.ArrayType: + expr0 = expr.Elem + case *syntax.ChanType: + expr0 = expr.Elem + case *syntax.DotsType: + expr0 = expr.Elem + case *syntax.MapType: + expr0 = expr.Value + case *syntax.SliceType: + expr0 = expr.Elem + + case *syntax.StructType: + return expr.Pos() + + case *syntax.InterfaceType: + expr0 = lastFieldType(expr.MethodList) + if expr0 == nil { + return expr.Pos() + } + + case *syntax.FuncType: + expr0 = lastFieldType(expr.ResultList) + if expr0 == nil { + expr0 = lastFieldType(expr.ParamList) + if expr0 == nil { + return expr.Pos() + } + } + + case *syntax.IndexExpr: // explicit type instantiation + targs := unpackListExpr(expr.Index) + expr0 = targs[len(targs)-1] + + default: + panic(fmt.Sprintf("%s: unexpected type expression %v", expr.Pos(), syntax.String(expr))) + } + } +} + +func lastFieldType(fields []*syntax.Field) syntax.Expr { + if len(fields) == 0 { + return nil + } + return fields[len(fields)-1].Type +} + +// sumPos returns the position that noder.sum would produce for +// constant expression x. +func sumPos(x syntax.Expr) syntax.Pos { + orig := x + for { + switch x1 := x.(type) { + case *syntax.BasicLit: + assert(x1.Kind == syntax.StringLit) + return x1.Pos() + case *syntax.Operation: + assert(x1.Op == syntax.Add && x1.Y != nil) + if r, ok := x1.Y.(*syntax.BasicLit); ok { + assert(r.Kind == syntax.StringLit) + x = x1.X + continue + } + } + return orig.Pos() + } +} + +// funcParamsEndPos returns the value of base.Pos left by noder after +// processing a function signature. +func funcParamsEndPos(fn *ir.Func) src.XPos { + sig := fn.Nname.Type() + + fields := sig.Results().FieldSlice() + if len(fields) == 0 { + fields = sig.Params().FieldSlice() + if len(fields) == 0 { + fields = sig.Recvs().FieldSlice() + if len(fields) == 0 { + if fn.OClosure != nil { + return fn.Nname.Ntype.Pos() + } + return fn.Pos() + } + } + } + + return fields[len(fields)-1].Pos +} + +type dupTypes struct { + origs map[types2.Type]types2.Type +} + +func (d *dupTypes) orig(t types2.Type) types2.Type { + if orig, ok := d.origs[t]; ok { + return orig + } + return t +} + +func (d *dupTypes) add(t, orig types2.Type) { + if t == orig { + return + } + + if d.origs == nil { + d.origs = make(map[types2.Type]types2.Type) + } + assert(d.origs[t] == nil) + d.origs[t] = orig + + switch t := t.(type) { + case *types2.Pointer: + orig := orig.(*types2.Pointer) + d.add(t.Elem(), orig.Elem()) + + case *types2.Slice: + orig := orig.(*types2.Slice) + d.add(t.Elem(), orig.Elem()) + + case *types2.Map: + orig := orig.(*types2.Map) + d.add(t.Key(), orig.Key()) + d.add(t.Elem(), orig.Elem()) + + case *types2.Array: + orig := orig.(*types2.Array) + assert(t.Len() == orig.Len()) + d.add(t.Elem(), orig.Elem()) + + case *types2.Chan: + orig := orig.(*types2.Chan) + assert(t.Dir() == orig.Dir()) + d.add(t.Elem(), orig.Elem()) + + case *types2.Struct: + orig := orig.(*types2.Struct) + assert(t.NumFields() == orig.NumFields()) + for i := 0; i < t.NumFields(); i++ { + d.add(t.Field(i).Type(), orig.Field(i).Type()) + } + + case *types2.Interface: + orig := orig.(*types2.Interface) + assert(t.NumExplicitMethods() == orig.NumExplicitMethods()) + assert(t.NumEmbeddeds() == orig.NumEmbeddeds()) + for i := 0; i < t.NumExplicitMethods(); i++ { + d.add(t.ExplicitMethod(i).Type(), orig.ExplicitMethod(i).Type()) + } + for i := 0; i < t.NumEmbeddeds(); i++ { + d.add(t.EmbeddedType(i), orig.EmbeddedType(i)) + } + + case *types2.Signature: + orig := orig.(*types2.Signature) + assert((t.Recv() == nil) == (orig.Recv() == nil)) + if t.Recv() != nil { + d.add(t.Recv().Type(), orig.Recv().Type()) + } + d.add(t.Params(), orig.Params()) + d.add(t.Results(), orig.Results()) + + case *types2.Tuple: + orig := orig.(*types2.Tuple) + assert(t.Len() == orig.Len()) + for i := 0; i < t.Len(); i++ { + d.add(t.At(i).Type(), orig.At(i).Type()) + } + + default: + assert(types2.Identical(t, orig)) + } +} diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go new file mode 100644 index 0000000000..18ecbff3cc --- /dev/null +++ b/src/cmd/compile/internal/noder/reader.go @@ -0,0 +1,1970 @@ +// UNREVIEWED + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package noder + +import ( + "bytes" + "fmt" + "go/constant" + "strings" + + "cmd/compile/internal/base" + "cmd/compile/internal/deadcode" + "cmd/compile/internal/dwarfgen" + "cmd/compile/internal/ir" + "cmd/compile/internal/typecheck" + "cmd/compile/internal/types" + "cmd/internal/obj" + "cmd/internal/src" +) + +// TODO(mdempsky): Suppress duplicate type/const errors that can arise +// during typecheck due to naive type substitution (e.g., see #42758). +// I anticipate these will be handled as a consequence of adding +// dictionaries support, so it's probably not important to focus on +// this until after that's done. + +type pkgReader struct { + pkgDecoder + + posBases []*src.PosBase + pkgs []*types.Pkg + typs []*types.Type + + // offset for rewriting the given index into the output, + // but bitwise inverted so we can detect if we're missing the entry or not. + newindex []int +} + +func newPkgReader(pr pkgDecoder) *pkgReader { + return &pkgReader{ + pkgDecoder: pr, + + posBases: make([]*src.PosBase, pr.numElems(relocPosBase)), + pkgs: make([]*types.Pkg, pr.numElems(relocPkg)), + typs: make([]*types.Type, pr.numElems(relocType)), + + newindex: make([]int, pr.totalElems()), + } +} + +type pkgReaderIndex struct { + pr *pkgReader + idx int + implicits []*types.Type +} + +func (pri pkgReaderIndex) asReader(k reloc, marker syncMarker) *reader { + r := pri.pr.newReader(k, pri.idx, marker) + r.implicits = pri.implicits + return r +} + +func (pr *pkgReader) newReader(k reloc, idx int, marker syncMarker) *reader { + return &reader{ + decoder: pr.newDecoder(k, idx, marker), + p: pr, + } +} + +type reader struct { + decoder + + p *pkgReader + + // Implicit and explicit type arguments in use for reading the + // current object. For example: + // + // func F[T any]() { + // type X[U any] struct { t T; u U } + // var _ X[string] + // } + // + // var _ = F[int] + // + // While instantiating F[int], we need to in turn instantiate + // X[string]. [int] and [string] are explicit type arguments for F + // and X, respectively; but [int] is also the implicit type + // arguments for X. + // + // (As an analogy to function literals, explicits are the function + // literal's formal parameters, while implicits are variables + // captured by the function literal.) + implicits []*types.Type + explicits []*types.Type + + ext *reader + + // TODO(mdempsky): The state below is all specific to reading + // function bodies. It probably makes sense to split it out + // separately so that it doesn't take up space in every reader + // instance. + + curfn *ir.Func + locals []*ir.Name + + funarghack bool + + // scopeVars is a stack tracking the number of variables declared in + // the current function at the moment each open scope was opened. + scopeVars []int + marker dwarfgen.ScopeMarker + lastCloseScopePos src.XPos + + // === details for handling inline body expansion === + + // If we're reading in a function body because of inlining, this is + // the call that we're inlining for. + inlCaller *ir.Func + inlCall *ir.CallExpr + inlFunc *ir.Func + inlTreeIndex int + inlPosBases map[*src.PosBase]*src.PosBase + + delayResults bool + + // Label to return to. + retlabel *types.Sym + + inlvars, retvars ir.Nodes +} + +func (r *reader) setType(n ir.Node, typ *types.Type) { + n.SetType(typ) + n.SetTypecheck(1) + + if name, ok := n.(*ir.Name); ok { + name.SetWalkdef(1) + name.Ntype = ir.TypeNode(name.Type()) + } +} + +func (r *reader) setValue(name *ir.Name, val constant.Value) { + name.SetVal(val) + name.Defn = nil +} + +// @@@ Positions + +func (r *reader) pos() src.XPos { + return base.Ctxt.PosTable.XPos(r.pos0()) +} + +func (r *reader) pos0() src.Pos { + r.sync(syncPos) + if !r.bool() { + return src.NoPos + } + + posBase := r.posBase() + line := r.uint() + col := r.uint() + return src.MakePos(posBase, line, col) +} + +func (r *reader) posBase() *src.PosBase { + return r.inlPosBase(r.p.posBaseIdx(r.reloc(relocPosBase))) +} + +func (pr *pkgReader) posBaseIdx(idx int) *src.PosBase { + if b := pr.posBases[idx]; b != nil { + return b + } + + r := pr.newReader(relocPosBase, idx, syncPosBase) + var b *src.PosBase + + fn := r.string() + absfn := r.string() + + if r.bool() { + b = src.NewFileBase(fn, absfn) + } else { + pos := r.pos0() + line := r.uint() + col := r.uint() + b = src.NewLinePragmaBase(pos, fn, absfn, line, col) + } + + pr.posBases[idx] = b + return b +} + +func (r *reader) inlPosBase(oldBase *src.PosBase) *src.PosBase { + if r.inlCall == nil { + return oldBase + } + + if newBase, ok := r.inlPosBases[oldBase]; ok { + return newBase + } + + newBase := src.NewInliningBase(oldBase, r.inlTreeIndex) + r.inlPosBases[oldBase] = newBase + return newBase +} + +func (r *reader) updatePos(xpos src.XPos) src.XPos { + pos := base.Ctxt.PosTable.Pos(xpos) + pos.SetBase(r.inlPosBase(pos.Base())) + return base.Ctxt.PosTable.XPos(pos) +} + +func (r *reader) origPos(xpos src.XPos) src.XPos { + if r.inlCall == nil { + return xpos + } + + pos := base.Ctxt.PosTable.Pos(xpos) + for old, new := range r.inlPosBases { + if pos.Base() == new { + pos.SetBase(old) + return base.Ctxt.PosTable.XPos(pos) + } + } + + base.FatalfAt(xpos, "pos base missing from inlPosBases") + panic("unreachable") +} + +// @@@ Packages + +func (r *reader) pkg() *types.Pkg { + r.sync(syncPkg) + return r.p.pkgIdx(r.reloc(relocPkg)) +} + +func (pr *pkgReader) pkgIdx(idx int) *types.Pkg { + if pkg := pr.pkgs[idx]; pkg != nil { + return pkg + } + + pkg := pr.newReader(relocPkg, idx, syncPkgDef).doPkg() + pr.pkgs[idx] = pkg + return pkg +} + +func (r *reader) doPkg() *types.Pkg { + path := r.string() + if path == "builtin" { + return types.BuiltinPkg + } + if path == "" { + path = r.p.pkgPath + } + + name := r.string() + height := r.len() + + pkg := types.NewPkg(path, "") + + if pkg.Name == "" { + pkg.Name = name + } else { + assert(pkg.Name == name) + } + + if pkg.Height == 0 { + pkg.Height = height + } else { + assert(pkg.Height == height) + } + + return pkg +} + +// @@@ Types + +func (r *reader) typ() *types.Type { + r.sync(syncType) + return r.p.typIdx(r.reloc(relocType), r.implicits, r.explicits) +} + +func (pr *pkgReader) typIdx(idx int, implicits, explicits []*types.Type) *types.Type { + if typ := pr.typs[idx]; typ != nil { + return typ + } + + r := pr.newReader(relocType, idx, syncTypeIdx) + r.implicits = implicits + r.explicits = explicits + typ := r.doTyp() + assert(typ != nil) + + if typ := pr.typs[idx]; typ != nil { + // This happens in fixedbugs/issue27232.go. + // TODO(mdempsky): Explain why/how this happens. + return typ + } + + // If we have type parameters, the type might refer to them, and it + // wouldn't be safe to reuse those in other contexts. So we + // conservatively avoid caching them in that case. + // + // TODO(mdempsky): If we're clever, we should be able to still cache + // types by tracking which type parameters are used. However, in my + // attempts so far, I haven't yet succeeded in being clever enough. + if len(implicits)+len(explicits) == 0 { + pr.typs[idx] = typ + } + + if !typ.IsUntyped() { + types.CheckSize(typ) + } + + return typ +} + +func (r *reader) doTyp() *types.Type { + switch tag := codeType(r.code(syncType)); tag { + default: + panic(fmt.Sprintf("unexpected type: %v", tag)) + + case typeBasic: + return *basics[r.len()] + + case typeNamed: + obj := r.obj() + assert(obj.Op() == ir.OTYPE) + return obj.Type() + + case typeTypeParam: + idx := r.len() + if idx < len(r.implicits) { + return r.implicits[idx] + } + return r.explicits[idx-len(r.implicits)] + + case typeArray: + len := int64(r.uint64()) + return types.NewArray(r.typ(), len) + case typeChan: + dir := dirs[r.len()] + return types.NewChan(r.typ(), dir) + case typeMap: + return types.NewMap(r.typ(), r.typ()) + case typePointer: + return types.NewPtr(r.typ()) + case typeSignature: + return r.signature(types.LocalPkg, nil) + case typeSlice: + return types.NewSlice(r.typ()) + case typeStruct: + return r.structType() + case typeInterface: + return r.interfaceType() + } +} + +func (r *reader) interfaceType() *types.Type { + tpkg := types.LocalPkg // TODO(mdempsky): Remove after iexport is gone. + + nmethods, nembeddeds := r.len(), r.len() + + fields := make([]*types.Field, nmethods+nembeddeds) + methods, embeddeds := fields[:nmethods], fields[nmethods:] + + for i := range methods { + pos := r.pos() + pkg, sym := r.selector() + tpkg = pkg + mtyp := r.signature(pkg, typecheck.FakeRecv()) + methods[i] = types.NewField(pos, sym, mtyp) + } + for i := range embeddeds { + embeddeds[i] = types.NewField(src.NoXPos, nil, r.typ()) + } + + if len(fields) == 0 { + return types.Types[types.TINTER] // empty interface + } + return types.NewInterface(tpkg, fields) +} + +func (r *reader) structType() *types.Type { + tpkg := types.LocalPkg // TODO(mdempsky): Remove after iexport is gone. + fields := make([]*types.Field, r.len()) + for i := range fields { + pos := r.pos() + pkg, sym := r.selector() + tpkg = pkg + ftyp := r.typ() + tag := r.string() + embedded := r.bool() + + f := types.NewField(pos, sym, ftyp) + f.Note = tag + if embedded { + f.Embedded = 1 + } + fields[i] = f + } + return types.NewStruct(tpkg, fields) +} + +func (r *reader) signature(tpkg *types.Pkg, recv *types.Field) *types.Type { + r.sync(syncSignature) + + params := r.params(&tpkg) + results := r.params(&tpkg) + if r.bool() { // variadic + params[len(params)-1].SetIsDDD(true) + } + + return types.NewSignature(tpkg, recv, nil, params, results) +} + +func (r *reader) params(tpkg **types.Pkg) []*types.Field { + r.sync(syncParams) + fields := make([]*types.Field, r.len()) + for i := range fields { + *tpkg, fields[i] = r.param() + } + return fields +} + +func (r *reader) param() (*types.Pkg, *types.Field) { + r.sync(syncParam) + + pos := r.pos() + pkg, sym := r.localIdent() + typ := r.typ() + + return pkg, types.NewField(pos, sym, typ) +} + +// @@@ Objects + +var objReader = map[*types.Sym]pkgReaderIndex{} + +func (r *reader) obj() ir.Node { + r.sync(syncObject) + + idx := r.reloc(relocObj) + + explicits := make([]*types.Type, r.len()) + for i := range explicits { + explicits[i] = r.typ() + } + + return r.p.objIdx(idx, r.implicits, explicits) +} + +func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node { + r := pr.newReader(relocObj, idx, syncObject1) + r.ext = pr.newReader(relocObjExt, idx, syncObject1) + + _, sym := r.qualifiedIdent() + + // Middle dot indicates local defined type; see writer.sym. + // TODO(mdempsky): Come up with a better way to handle this. + if strings.Contains(sym.Name, "·") { + r.implicits = implicits + r.ext.implicits = implicits + } + r.explicits = explicits + r.ext.explicits = explicits + + origSym := sym + + sym = r.mangle(sym) + if !sym.IsBlank() && sym.Def != nil { + return sym.Def.(ir.Node) + } + + r.typeParamBounds(origSym) + tag := codeObj(r.code(syncCodeObj)) + + do := func(op ir.Op, hasTParams bool) *ir.Name { + pos := r.pos() + if hasTParams { + r.typeParamNames() + } + + name := ir.NewDeclNameAt(pos, op, sym) + name.Class = ir.PEXTERN // may be overridden later + if !sym.IsBlank() { + if sym.Def != nil { + base.FatalfAt(name.Pos(), "already have a definition for %v", name) + } + assert(sym.Def == nil) + sym.Def = name + } + return name + } + + switch tag { + default: + panic("unexpected object") + + case objStub: + if pri, ok := objReader[origSym]; ok { + return pri.pr.objIdx(pri.idx, pri.implicits, r.explicits) + } + if haveLegacyImports { + assert(len(r.implicits)+len(r.explicits) == 0) + return typecheck.Resolve(ir.NewIdent(src.NoXPos, origSym)) + } + base.Fatalf("unresolved stub: %v", origSym) + panic("unreachable") + + case objAlias: + name := do(ir.OTYPE, false) + r.setType(name, r.typ()) + name.SetAlias(true) + return name + + case objConst: + name := do(ir.OLITERAL, false) + typ, val := r.value() + r.setType(name, typ) + r.setValue(name, val) + return name + + case objFunc: + if sym.Name == "init" { + sym = renameinit() + } + name := do(ir.ONAME, true) + r.setType(name, r.signature(sym.Pkg, nil)) + + name.Func = ir.NewFunc(r.pos()) + name.Func.Nname = name + + r.ext.funcExt(name) + return name + + case objType: + name := do(ir.OTYPE, true) + typ := types.NewNamed(name) + r.setType(name, typ) + + // Important: We need to do this before SetUnderlying. + r.ext.typeExt(name) + + // We need to defer CheckSize until we've called SetUnderlying to + // handle recursive types. + types.DeferCheckSize() + typ.SetUnderlying(r.typ()) + types.ResumeCheckSize() + + methods := make([]*types.Field, r.len()) + for i := range methods { + methods[i] = r.method() + } + if len(methods) != 0 { + typ.Methods().Set(methods) + } + + return name + + case objVar: + name := do(ir.ONAME, false) + r.setType(name, r.typ()) + r.ext.varExt(name) + return name + } +} + +func (r *reader) mangle(sym *types.Sym) *types.Sym { + if len(r.implicits)+len(r.explicits) == 0 { + return sym + } + + var buf bytes.Buffer + buf.WriteString(sym.Name) + buf.WriteByte('[') + for i, targs := range [2][]*types.Type{r.implicits, r.explicits} { + if i > 0 && len(r.implicits) != 0 && len(r.explicits) != 0 { + buf.WriteByte(';') + } + for j, targ := range targs { + if j > 0 { + buf.WriteByte(',') + } + // TODO(mdempsky): We need the linker to replace "" in the symbol + // names here. + buf.WriteString(targ.ShortString()) + } + } + buf.WriteByte(']') + return sym.Pkg.Lookup(buf.String()) +} + +func (r *reader) typeParamBounds(sym *types.Sym) { + r.sync(syncTypeParamBounds) + + nimplicits := r.len() + nexplicits := r.len() + + if len(r.implicits) != nimplicits || len(r.explicits) != nexplicits { + base.Fatalf("%v has %v+%v params, but instantiated with %v+%v args", sym, nimplicits, nexplicits, len(r.implicits), len(r.explicits)) + } + + // For stenciling, we can just skip over the type parameters. + + for range r.explicits { + // Skip past bounds without actually evaluating them. + r.sync(syncType) + r.reloc(relocType) + } +} + +func (r *reader) typeParamNames() { + r.sync(syncTypeParamNames) + + for range r.explicits { + r.pos() + r.localIdent() + } +} + +func (r *reader) value() (*types.Type, constant.Value) { + r.sync(syncValue) + typ := r.typ() + return typ, FixValue(typ, r.rawValue()) +} + +func (r *reader) method() *types.Field { + r.sync(syncMethod) + pos := r.pos() + pkg, sym := r.selector() + r.typeParamNames() + _, recv := r.param() + typ := r.signature(pkg, recv) + + fnsym := sym + fnsym = ir.MethodSym(recv.Type, fnsym) + name := ir.NewNameAt(pos, fnsym) + r.setType(name, typ) + + name.Func = ir.NewFunc(r.pos()) + name.Func.Nname = name + + // TODO(mdempsky): Make sure we're handling //go:nointerface + // correctly. I don't think this is exercised within the Go repo. + + r.ext.funcExt(name) + + meth := types.NewField(name.Func.Pos(), sym, typ) + meth.Nname = name + return meth +} + +func (r *reader) qualifiedIdent() (pkg *types.Pkg, sym *types.Sym) { + r.sync(syncSym) + pkg = r.pkg() + if name := r.string(); name != "" { + sym = pkg.Lookup(name) + } + return +} + +func (r *reader) localIdent() (pkg *types.Pkg, sym *types.Sym) { + r.sync(syncLocalIdent) + pkg = r.pkg() + if name := r.string(); name != "" { + sym = pkg.Lookup(name) + } + return +} + +func (r *reader) selector() (origPkg *types.Pkg, sym *types.Sym) { + r.sync(syncSelector) + origPkg = r.pkg() + name := r.string() + pkg := origPkg + if types.IsExported(name) { + pkg = types.LocalPkg + } + sym = pkg.Lookup(name) + return +} + +// @@@ Compiler extensions + +func (r *reader) funcExt(name *ir.Name) { + r.sync(syncFuncExt) + + name.Class = 0 // so MarkFunc doesn't complain + ir.MarkFunc(name) + + fn := name.Func + + // XXX: Workaround because linker doesn't know how to copy Pos. + if !fn.Pos().IsKnown() { + fn.SetPos(name.Pos()) + } + + // TODO(mdempsky): Remember why I wrote this code. I think it has to + // do with how ir.VisitFuncsBottomUp works? + if name.Sym().Pkg == types.LocalPkg || len(r.implicits)+len(r.explicits) != 0 { + name.Defn = fn + } + + fn.Pragma = r.pragmaFlag() + r.linkname(name) + + if r.bool() { + fn.ABI = obj.ABI(r.uint64()) + + // Escape analysis. + for _, fs := range &types.RecvsParams { + for _, f := range fs(name.Type()).FieldSlice() { + f.Note = r.string() + } + } + + if r.bool() { + fn.Inl = &ir.Inline{ + Cost: int32(r.len()), + CanDelayResults: r.bool(), + } + r.addBody(name.Func) + } + } else { + r.addBody(name.Func) + } + r.sync(syncEOF) +} + +func (r *reader) typeExt(name *ir.Name) { + r.sync(syncTypeExt) + + typ := name.Type() + + if len(r.implicits)+len(r.explicits) != 0 { + // Set "RParams" (really type arguments here, not parameters) so + // this type is treated as "fully instantiated". This ensures the + // type descriptor is written out as DUPOK and method wrappers are + // generated even for imported types. + var targs []*types.Type + targs = append(targs, r.implicits...) + targs = append(targs, r.explicits...) + typ.SetRParams(targs) + } + + name.SetPragma(r.pragmaFlag()) + if name.Pragma()&ir.NotInHeap != 0 { + typ.SetNotInHeap(true) + } + + typecheck.SetBaseTypeIndex(typ, r.int64(), r.int64()) +} + +func (r *reader) varExt(name *ir.Name) { + r.sync(syncVarExt) + r.linkname(name) +} + +func (r *reader) linkname(name *ir.Name) { + assert(name.Op() == ir.ONAME) + r.sync(syncLinkname) + + if idx := r.int64(); idx >= 0 { + lsym := name.Linksym() + lsym.SymIdx = int32(idx) + lsym.Set(obj.AttrIndexed, true) + } else { + name.Sym().Linkname = r.string() + } +} + +func (r *reader) pragmaFlag() ir.PragmaFlag { + r.sync(syncPragma) + return ir.PragmaFlag(r.int()) +} + +// @@@ Function bodies + +// bodyReader tracks where the serialized IR for a function's body can +// be found. +var bodyReader = map[*ir.Func]pkgReaderIndex{} + +// todoBodies holds the list of function bodies that still need to be +// constructed. +var todoBodies []*ir.Func + +func (r *reader) addBody(fn *ir.Func) { + r.sync(syncAddBody) + + // See commont in writer.addBody for why r.implicits and r.explicits + // should never both be non-empty. + implicits := r.implicits + if len(implicits) == 0 { + implicits = r.explicits + } else { + assert(len(r.explicits) == 0) + } + + pri := pkgReaderIndex{r.p, r.reloc(relocBody), implicits} + bodyReader[fn] = pri + + if r.curfn == nil { + todoBodies = append(todoBodies, fn) + return + } + + pri.funcBody(fn) +} + +func (pri pkgReaderIndex) funcBody(fn *ir.Func) { + r := pri.asReader(relocBody, syncFuncBody) + r.funcBody(fn) +} + +func (r *reader) funcBody(fn *ir.Func) { + r.curfn = fn + r.locals = fn.ClosureVars + + // TODO(mdempsky): Get rid of uses of typecheck.NodAddrAt so we + // don't have to set ir.CurFunc. + outerCurFunc := ir.CurFunc + ir.CurFunc = fn + + r.funcargs(fn) + + if r.bool() { + body := r.stmts() + if body == nil { + pos := src.NoXPos + if quirksMode() { + pos = funcParamsEndPos(fn) + } + body = []ir.Node{ir.NewBlockStmt(pos, nil)} + } + fn.Body = body + fn.Endlineno = r.pos() + } + + ir.CurFunc = outerCurFunc + r.marker.WriteTo(fn) +} + +func (r *reader) funcargs(fn *ir.Func) { + sig := fn.Nname.Type() + + if recv := sig.Recv(); recv != nil { + r.funcarg(recv, recv.Sym, ir.PPARAM) + } + for _, param := range sig.Params().FieldSlice() { + r.funcarg(param, param.Sym, ir.PPARAM) + } + + for i, param := range sig.Results().FieldSlice() { + sym := types.OrigSym(param.Sym) + + if sym == nil || sym.IsBlank() { + prefix := "~r" + if r.inlCall != nil { + prefix = "~R" + } else if sym != nil { + prefix = "~b" + } + sym = typecheck.LookupNum(prefix, i) + } + + r.funcarg(param, sym, ir.PPARAMOUT) + } +} + +func (r *reader) funcarg(param *types.Field, sym *types.Sym, ctxt ir.Class) { + if sym == nil { + assert(ctxt == ir.PPARAM) + if r.inlCall != nil { + r.inlvars.Append(ir.BlankNode) + } + return + } + + name := ir.NewNameAt(r.updatePos(param.Pos), sym) + r.setType(name, param.Type) + r.addLocal(name, ctxt) + + if r.inlCall == nil { + if !r.funarghack { + param.Sym = sym + param.Nname = name + } + } else { + if ctxt == ir.PPARAMOUT { + r.retvars.Append(name) + } else { + r.inlvars.Append(name) + } + } +} + +func (r *reader) addLocal(name *ir.Name, ctxt ir.Class) { + assert(ctxt == ir.PAUTO || ctxt == ir.PPARAM || ctxt == ir.PPARAMOUT) + + r.sync(syncAddLocal) + if debug { + want := r.int() + if have := len(r.locals); have != want { + base.FatalfAt(name.Pos(), "locals table has desynced") + } + } + + name.SetUsed(true) + r.locals = append(r.locals, name) + + // TODO(mdempsky): Move earlier. + if ir.IsBlank(name) { + return + } + + if r.inlCall != nil { + if ctxt == ir.PAUTO { + name.SetInlLocal(true) + } else { + name.SetInlFormal(true) + ctxt = ir.PAUTO + } + + // TODO(mdempsky): Rethink this hack. + if strings.HasPrefix(name.Sym().Name, "~") || base.Flag.GenDwarfInl == 0 { + name.SetPos(r.inlCall.Pos()) + name.SetInlFormal(false) + name.SetInlLocal(false) + } + } + + name.Class = ctxt + name.Curfn = r.curfn + + r.curfn.Dcl = append(r.curfn.Dcl, name) + + if ctxt == ir.PAUTO { + name.SetFrameOffset(0) + } +} + +func (r *reader) useLocal() *ir.Name { + r.sync(syncUseObjLocal) + return r.locals[r.len()] +} + +func (r *reader) openScope() { + r.sync(syncOpenScope) + pos := r.pos() + + if base.Flag.Dwarf { + r.scopeVars = append(r.scopeVars, len(r.curfn.Dcl)) + r.marker.Push(pos) + } +} + +func (r *reader) closeScope() { + r.sync(syncCloseScope) + r.lastCloseScopePos = r.pos() + + r.closeAnotherScope() +} + +// closeAnotherScope is like closeScope, but it reuses the same mark +// position as the last closeScope call. This is useful for "for" and +// "if" statements, as their implicit blocks always end at the same +// position as an explicit block. +func (r *reader) closeAnotherScope() { + r.sync(syncCloseAnotherScope) + + if base.Flag.Dwarf { + scopeVars := r.scopeVars[len(r.scopeVars)-1] + r.scopeVars = r.scopeVars[:len(r.scopeVars)-1] + + if scopeVars == len(r.curfn.Dcl) { + // no variables were declared in this scope, so we can retract it. + r.marker.Unpush() + } else { + r.marker.Pop(r.lastCloseScopePos) + } + } +} + +// @@@ Statements + +func (r *reader) stmt() ir.Node { + switch stmts := r.stmts(); len(stmts) { + case 0: + return nil + case 1: + return stmts[0] + default: + return ir.NewBlockStmt(stmts[0].Pos(), stmts) + } +} + +func (r *reader) stmts() []ir.Node { + var res ir.Nodes + + r.sync(syncStmts) + for { + tag := codeStmt(r.code(syncStmt1)) + if tag == stmtEnd { + r.sync(syncStmtsEnd) + return res + } + + if n := r.stmt1(tag, &res); n != nil { + res.Append(n) + } + } +} + +func (r *reader) stmt1(tag codeStmt, out *ir.Nodes) ir.Node { + var label *types.Sym + if n := len(*out); n > 0 { + if ls, ok := (*out)[n-1].(*ir.LabelStmt); ok { + label = ls.Label + } + } + + switch tag { + default: + panic("unexpected statement") + + case stmtAssign: + pos := r.pos() + names, lhs := r.assignList() + rhs := r.exprList() + + if len(rhs) == 0 { + for _, name := range names { + as := ir.NewAssignStmt(pos, name, nil) + as.PtrInit().Append(ir.NewDecl(pos, ir.ODCL, name)) + out.Append(as) + } + return nil + } + + if len(lhs) == 1 && len(rhs) == 1 { + n := ir.NewAssignStmt(pos, lhs[0], rhs[0]) + n.Def = r.initDefn(n, names) + return n + } + + n := ir.NewAssignListStmt(pos, ir.OAS2, lhs, rhs) + n.Def = r.initDefn(n, names) + return n + + case stmtAssignOp: + op := r.op() + lhs := r.expr() + pos := r.pos() + rhs := r.expr() + return ir.NewAssignOpStmt(pos, op, lhs, rhs) + + case stmtIncDec: + op := r.op() + lhs := r.expr() + pos := r.pos() + n := ir.NewAssignOpStmt(pos, op, lhs, ir.NewBasicLit(pos, one)) + n.IncDec = true + return n + + case stmtBlock: + out.Append(r.blockStmt()...) + return nil + + case stmtBranch: + pos := r.pos() + op := r.op() + sym := r.optLabel() + return ir.NewBranchStmt(pos, op, sym) + + case stmtCall: + pos := r.pos() + op := r.op() + call := r.expr() + return ir.NewGoDeferStmt(pos, op, call) + + case stmtExpr: + return r.expr() + + case stmtFor: + return r.forStmt(label) + + case stmtIf: + return r.ifStmt() + + case stmtLabel: + pos := r.pos() + sym := r.label() + return ir.NewLabelStmt(pos, sym) + + case stmtReturn: + pos := r.pos() + results := r.exprList() + return ir.NewReturnStmt(pos, results) + + case stmtSelect: + return r.selectStmt(label) + + case stmtSend: + pos := r.pos() + ch := r.expr() + value := r.expr() + return ir.NewSendStmt(pos, ch, value) + + case stmtSwitch: + return r.switchStmt(label) + + case stmtTypeDeclHack: + // fake "type _ = int" declaration to prevent inlining in quirks mode. + assert(quirksMode()) + + name := ir.NewDeclNameAt(src.NoXPos, ir.OTYPE, ir.BlankNode.Sym()) + name.SetAlias(true) + r.setType(name, types.Types[types.TINT]) + + n := ir.NewDecl(src.NoXPos, ir.ODCLTYPE, name) + n.SetTypecheck(1) + return n + } +} + +func (r *reader) assignList() ([]*ir.Name, []ir.Node) { + lhs := make([]ir.Node, r.len()) + var names []*ir.Name + + for i := range lhs { + if r.bool() { + pos := r.pos() + _, sym := r.localIdent() + typ := r.typ() + + name := ir.NewNameAt(pos, sym) + lhs[i] = name + names = append(names, name) + r.setType(name, typ) + r.addLocal(name, ir.PAUTO) + continue + } + + lhs[i] = r.expr() + } + + return names, lhs +} + +func (r *reader) blockStmt() []ir.Node { + r.sync(syncBlockStmt) + r.openScope() + stmts := r.stmts() + r.closeScope() + return stmts +} + +func (r *reader) forStmt(label *types.Sym) ir.Node { + r.sync(syncForStmt) + + r.openScope() + + if r.bool() { + pos := r.pos() + names, lhs := r.assignList() + x := r.expr() + body := r.blockStmt() + r.closeAnotherScope() + + rang := ir.NewRangeStmt(pos, nil, nil, x, body) + if len(lhs) >= 1 { + rang.Key = lhs[0] + if len(lhs) >= 2 { + rang.Value = lhs[1] + } + } + rang.Def = r.initDefn(rang, names) + rang.Label = label + return rang + } + + pos := r.pos() + init := r.stmt() + cond := r.expr() + post := r.stmt() + body := r.blockStmt() + r.closeAnotherScope() + + stmt := ir.NewForStmt(pos, init, cond, post, body) + stmt.Label = label + return stmt +} + +func (r *reader) ifStmt() ir.Node { + r.sync(syncIfStmt) + r.openScope() + pos := r.pos() + init := r.stmts() + cond := r.expr() + then := r.blockStmt() + els := r.stmts() + n := ir.NewIfStmt(pos, cond, then, els) + n.SetInit(init) + r.closeAnotherScope() + return n +} + +func (r *reader) selectStmt(label *types.Sym) ir.Node { + r.sync(syncSelectStmt) + + pos := r.pos() + clauses := make([]*ir.CommClause, r.len()) + for i := range clauses { + if i > 0 { + r.closeScope() + } + r.openScope() + + pos := r.pos() + comm := r.stmt() + body := r.stmts() + + clauses[i] = ir.NewCommStmt(pos, comm, body) + } + if len(clauses) > 0 { + r.closeScope() + } + n := ir.NewSelectStmt(pos, clauses) + n.Label = label + return n +} + +func (r *reader) switchStmt(label *types.Sym) ir.Node { + r.sync(syncSwitchStmt) + + r.openScope() + pos := r.pos() + init := r.stmt() + tag := r.expr() + + tswitch, ok := tag.(*ir.TypeSwitchGuard) + if ok && tswitch.Tag == nil { + tswitch = nil + } + + clauses := make([]*ir.CaseClause, r.len()) + for i := range clauses { + if i > 0 { + r.closeScope() + } + r.openScope() + + pos := r.pos() + cases := r.exprList() + + clause := ir.NewCaseStmt(pos, cases, nil) + if tswitch != nil { + pos := r.pos() + typ := r.typ() + + name := ir.NewNameAt(pos, tswitch.Tag.Sym()) + r.setType(name, typ) + r.addLocal(name, ir.PAUTO) + clause.Var = name + name.Defn = tswitch + } + + clause.Body = r.stmts() + clauses[i] = clause + } + if len(clauses) > 0 { + r.closeScope() + } + r.closeScope() + + n := ir.NewSwitchStmt(pos, tag, clauses) + n.Label = label + if init != nil { + n.SetInit([]ir.Node{init}) + } + return n +} + +func (r *reader) label() *types.Sym { + r.sync(syncLabel) + name := r.string() + if r.inlCall != nil { + name = fmt.Sprintf("~%s·%d", name, inlgen) + } + return typecheck.Lookup(name) +} + +func (r *reader) optLabel() *types.Sym { + r.sync(syncOptLabel) + if r.bool() { + return r.label() + } + return nil +} + +// initDefn marks the given names as declared by defn and populates +// its Init field with ODCL nodes. It then reports whether any names +// were so declared, which can be used to initialize defn.Def. +func (r *reader) initDefn(defn ir.InitNode, names []*ir.Name) bool { + if len(names) == 0 { + return false + } + + init := make([]ir.Node, len(names)) + for i, name := range names { + name.Defn = defn + init[i] = ir.NewDecl(name.Pos(), ir.ODCL, name) + } + defn.SetInit(init) + return true +} + +// @@@ Expressions + +func (r *reader) expr() ir.Node { + switch tag := codeExpr(r.code(syncExpr)); tag { + default: + panic("unhandled expression") + + case exprNone: + return nil + + case exprBlank: + return ir.BlankNode + + case exprLocal: + return r.useLocal() + + case exprName: + return r.obj() + + case exprType: + return ir.TypeNode(r.typ()) + + case exprConst: + pos := r.pos() + typ, val := r.value() + op := r.op() + orig := r.string() + return OrigConst(pos, typ, val, op, orig) + + case exprCompLit: + return r.compLit() + + case exprFuncLit: + return r.funcLit() + + case exprSelector: + x := r.expr() + pos := r.pos() + _, sym := r.selector() + return ir.NewSelectorExpr(pos, ir.OXDOT, x, sym) + + case exprIndex: + x := r.expr() + pos := r.pos() + index := r.expr() + return ir.NewIndexExpr(pos, x, index) + + case exprSlice: + x := r.expr() + pos := r.pos() + var index [3]ir.Node + for i := range index { + index[i] = r.expr() + } + op := ir.OSLICE + if index[2] != nil { + op = ir.OSLICE3 + } + return ir.NewSliceExpr(pos, op, x, index[0], index[1], index[2]) + + case exprAssert: + x := r.expr() + pos := r.pos() + typ := r.expr().(ir.Ntype) + return ir.NewTypeAssertExpr(pos, x, typ) + + case exprUnaryOp: + op := r.op() + pos := r.pos() + x := r.expr() + + switch op { + case ir.OADDR: + return typecheck.NodAddrAt(pos, x) + case ir.ODEREF: + return ir.NewStarExpr(pos, x) + } + return ir.NewUnaryExpr(pos, op, x) + + case exprBinaryOp: + op := r.op() + x := r.expr() + pos := r.pos() + y := r.expr() + + switch op { + case ir.OANDAND, ir.OOROR: + return ir.NewLogicalExpr(pos, op, x, y) + } + return ir.NewBinaryExpr(pos, op, x, y) + + case exprCall: + fun := r.expr() + pos := r.pos() + args := r.exprs() + dots := r.bool() + n := ir.NewCallExpr(pos, ir.OCALL, fun, args) + n.IsDDD = dots + return n + + case exprTypeSwitchGuard: + pos := r.pos() + var tag *ir.Ident + if r.bool() { + pos := r.pos() + sym := typecheck.Lookup(r.string()) + tag = ir.NewIdent(pos, sym) + } + x := r.expr() + return ir.NewTypeSwitchGuard(pos, tag, x) + } +} + +func (r *reader) compLit() ir.Node { + r.sync(syncCompLit) + pos := r.pos() + typ := r.typ() + + isPtrLit := typ.IsPtr() + if isPtrLit { + typ = typ.Elem() + } + if typ.Kind() == types.TFORW { + base.FatalfAt(pos, "unresolved composite literal type: %v", typ) + } + isStruct := typ.Kind() == types.TSTRUCT + + elems := make([]ir.Node, r.len()) + for i := range elems { + elemp := &elems[i] + + if isStruct { + sk := ir.NewStructKeyExpr(r.pos(), typ.Field(r.len()), nil) + *elemp, elemp = sk, &sk.Value + } else if r.bool() { + kv := ir.NewKeyExpr(r.pos(), r.expr(), nil) + *elemp, elemp = kv, &kv.Value + } + + *elemp = wrapName(r.pos(), r.expr()) + } + + lit := ir.NewCompLitExpr(pos, ir.OCOMPLIT, ir.TypeNode(typ), elems) + if isPtrLit { + return typecheck.NodAddrAt(pos, lit) + } + return lit +} + +func wrapName(pos src.XPos, x ir.Node) ir.Node { + // These nodes do not carry line numbers. + // Introduce a wrapper node to give them the correct line. + switch ir.Orig(x).Op() { + case ir.OTYPE, ir.OLITERAL: + if x.Sym() == nil { + break + } + fallthrough + case ir.ONAME, ir.ONONAME, ir.OPACK, ir.ONIL: + p := ir.NewParenExpr(pos, x) + p.SetImplicit(true) + return p + } + return x +} + +func (r *reader) funcLit() ir.Node { + r.sync(syncFuncLit) + + pos := r.pos() + typPos := r.pos() + xtype2 := r.signature(types.LocalPkg, nil) + + opos := pos + if quirksMode() { + opos = r.origPos(pos) + } + + fn := ir.NewClosureFunc(opos, r.curfn != nil) + + r.setType(fn.Nname, xtype2) + if quirksMode() { + fn.Nname.Ntype = ir.TypeNodeAt(typPos, xtype2) + } + + fn.ClosureVars = make([]*ir.Name, r.len()) + for i := range fn.ClosureVars { + pos := r.pos() + outer := r.useLocal() + + cv := ir.NewNameAt(pos, outer.Sym()) + r.setType(cv, outer.Type()) + cv.Curfn = fn + cv.Class = ir.PAUTOHEAP + cv.SetIsClosureVar(true) + cv.Defn = outer.Canonical() + cv.Outer = outer + + fn.ClosureVars[i] = cv + } + + r.addBody(fn) + + return fn.OClosure +} + +func (r *reader) exprList() []ir.Node { + r.sync(syncExprList) + return r.exprs() +} + +func (r *reader) exprs() []ir.Node { + r.sync(syncExprs) + nodes := make([]ir.Node, r.len()) + if len(nodes) == 0 { + return nil // TODO(mdempsky): Unclear if this matters. + } + for i := range nodes { + nodes[i] = r.expr() + } + return nodes +} + +func (r *reader) op() ir.Op { + r.sync(syncOp) + return ir.Op(r.len()) +} + +// @@@ Package initialization + +func (r *reader) pkgInit(self *types.Pkg, target *ir.Package) { + if quirksMode() { + for i, n := 0, r.len(); i < n; i++ { + // Eagerly register position bases, so their filenames are + // assigned stable indices. + posBase := r.posBase() + _ = base.Ctxt.PosTable.XPos(src.MakePos(posBase, 0, 0)) + } + + for i, n := 0, r.len(); i < n; i++ { + // Eagerly resolve imported objects, so any filenames registered + // in the process are assigned stable indices too. + _, sym := r.qualifiedIdent() + typecheck.Resolve(ir.NewIdent(src.NoXPos, sym)) + assert(sym.Def != nil) + } + } + + cgoPragmas := make([][]string, r.len()) + for i := range cgoPragmas { + cgoPragmas[i] = r.strings() + } + target.CgoPragmas = cgoPragmas + + r.pkgDecls(target) + + r.sync(syncEOF) +} + +func (r *reader) pkgDecls(target *ir.Package) { + r.sync(syncDecls) + for { + switch code := codeDecl(r.code(syncDecl)); code { + default: + panic(fmt.Sprintf("unhandled decl: %v", code)) + + case declEnd: + return + + case declFunc: + names := r.pkgObjs(target) + assert(len(names) == 1) + target.Decls = append(target.Decls, names[0].Func) + + case declMethod: + typ := r.typ() + _, sym := r.selector() + + method := typecheck.Lookdot1(nil, sym, typ, typ.Methods(), 0) + target.Decls = append(target.Decls, method.Nname.(*ir.Name).Func) + + case declVar: + pos := r.pos() + names := r.pkgObjs(target) + values := r.exprList() + + if len(names) > 1 && len(values) == 1 { + as := ir.NewAssignListStmt(pos, ir.OAS2, nil, values) + for _, name := range names { + as.Lhs.Append(name) + name.Defn = as + } + target.Decls = append(target.Decls, as) + } else { + for i, name := range names { + as := ir.NewAssignStmt(pos, name, nil) + if i < len(values) { + as.Y = values[i] + } + name.Defn = as + target.Decls = append(target.Decls, as) + } + } + + if n := r.len(); n > 0 { + assert(len(names) == 1) + embeds := make([]ir.Embed, n) + for i := range embeds { + embeds[i] = ir.Embed{Pos: r.pos(), Patterns: r.strings()} + } + names[0].Embed = &embeds + target.Embeds = append(target.Embeds, names[0]) + } + + case declOther: + r.pkgObjs(target) + } + } +} + +func (r *reader) pkgObjs(target *ir.Package) []*ir.Name { + r.sync(syncDeclNames) + nodes := make([]*ir.Name, r.len()) + for i := range nodes { + r.sync(syncDeclName) + + name := r.obj().(*ir.Name) + nodes[i] = name + + sym := name.Sym() + if sym.IsBlank() { + continue + } + + switch name.Class { + default: + base.FatalfAt(name.Pos(), "unexpected class: %v", name.Class) + + case ir.PEXTERN: + target.Externs = append(target.Externs, name) + + case ir.PFUNC: + assert(name.Type().Recv() == nil) + + // TODO(mdempsky): Cleaner way to recognize init? + if strings.HasPrefix(sym.Name, "init.") { + target.Inits = append(target.Inits, name.Func) + } + } + + if types.IsExported(sym.Name) { + assert(!sym.OnExportList()) + target.Exports = append(target.Exports, name) + sym.SetOnExportList(true) + } + + if base.Flag.AsmHdr != "" { + assert(!sym.Asm()) + target.Asms = append(target.Asms, name) + sym.SetAsm(true) + } + } + + return nodes +} + +// @@@ Inlining + +var inlgen = 0 + +func InlineCall(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExpr { + // TODO(mdempsky): Turn callerfn into an explicit parameter. + callerfn := ir.CurFunc + + pri, ok := bodyReader[fn] + if !ok { + // Assume it's an imported function or something that we don't + // have access to in quirks mode. + if haveLegacyImports { + return nil + } + + base.FatalfAt(call.Pos(), "missing function body for call to %v", fn) + } + + if fn.Inl.Body == nil { + expandInline(fn, pri) + } + + r := pri.asReader(relocBody, syncFuncBody) + + // TODO(mdempsky): This still feels clumsy. Can we do better? + tmpfn := ir.NewFunc(fn.Pos()) + tmpfn.Nname = ir.NewNameAt(fn.Nname.Pos(), callerfn.Sym()) + tmpfn.Closgen = callerfn.Closgen + defer func() { callerfn.Closgen = tmpfn.Closgen }() + + r.setType(tmpfn.Nname, fn.Type()) + r.curfn = tmpfn + + r.inlCaller = ir.CurFunc + r.inlCall = call + r.inlFunc = fn + r.inlTreeIndex = inlIndex + r.inlPosBases = make(map[*src.PosBase]*src.PosBase) + + for _, cv := range r.inlFunc.ClosureVars { + r.locals = append(r.locals, cv.Outer) + } + + r.funcargs(fn) + + assert(r.bool()) // have body + r.delayResults = fn.Inl.CanDelayResults + + r.retlabel = typecheck.AutoLabel(".i") + inlgen++ + + init := ir.TakeInit(call) + + // For normal function calls, the function callee expression + // may contain side effects (e.g., added by addinit during + // inlconv2expr or inlconv2list). Make sure to preserve these, + // if necessary (#42703). + if call.Op() == ir.OCALLFUNC { + callee := call.X + for callee.Op() == ir.OCONVNOP { + conv := callee.(*ir.ConvExpr) + init.Append(ir.TakeInit(conv)...) + callee = conv.X + } + + switch callee.Op() { + case ir.ONAME, ir.OCLOSURE, ir.OMETHEXPR: + // ok + default: + base.Fatalf("unexpected callee expression: %v", callee) + } + } + + var args ir.Nodes + if call.Op() == ir.OCALLMETH { + assert(call.X.Op() == ir.ODOTMETH) + args.Append(call.X.(*ir.SelectorExpr).X) + } + args.Append(call.Args...) + + // Create assignment to declare and initialize inlvars. + as2 := ir.NewAssignListStmt(call.Pos(), ir.OAS2, r.inlvars, args) + as2.Def = true + var as2init ir.Nodes + for _, name := range r.inlvars { + if ir.IsBlank(name) { + continue + } + // TODO(mdempsky): Use inlined position of name.Pos() instead? + name := name.(*ir.Name) + as2init.Append(ir.NewDecl(call.Pos(), ir.ODCL, name)) + name.Defn = as2 + } + as2.SetInit(as2init) + init.Append(typecheck.Stmt(as2)) + + if !r.delayResults { + // If not delaying retvars, declare and zero initialize the + // result variables now. + for _, name := range r.retvars { + // TODO(mdempsky): Use inlined position of name.Pos() instead? + name := name.(*ir.Name) + init.Append(ir.NewDecl(call.Pos(), ir.ODCL, name)) + ras := ir.NewAssignStmt(call.Pos(), name, nil) + init.Append(typecheck.Stmt(ras)) + } + } + + // Add an inline mark just before the inlined body. + // This mark is inline in the code so that it's a reasonable spot + // to put a breakpoint. Not sure if that's really necessary or not + // (in which case it could go at the end of the function instead). + // Note issue 28603. + init.Append(ir.NewInlineMarkStmt(call.Pos().WithIsStmt(), int64(r.inlTreeIndex))) + + nparams := len(r.curfn.Dcl) + + oldcurfn := ir.CurFunc + ir.CurFunc = r.curfn + + r.curfn.Body = r.stmts() + r.curfn.Endlineno = r.pos() + + typecheck.Stmts(r.curfn.Body) + deadcode.Func(r.curfn) + + // Replace any "return" statements within the function body. + { + var edit func(ir.Node) ir.Node + edit = func(n ir.Node) ir.Node { + if ret, ok := n.(*ir.ReturnStmt); ok { + n = typecheck.Stmt(r.inlReturn(ret)) + } + ir.EditChildren(n, edit) + return n + } + edit(r.curfn) + } + + ir.CurFunc = oldcurfn + + body := ir.Nodes(r.curfn.Body) + + // Quirk: If deadcode elimination turned a non-empty function into + // an empty one, we need to set the position for the empty block + // left behind to the the inlined position for src.NoXPos, so that + // an empty string gets added into the DWARF file name listing at + // the appropriate index. + if quirksMode() && len(body) == 1 { + if block, ok := body[0].(*ir.BlockStmt); ok && len(block.List) == 0 { + block.SetPos(r.updatePos(src.NoXPos)) + } + } + + // Quirkish: We need to eagerly prune variables added during + // inlining, but removed by deadcode.FuncBody above. Unused + // variables will get removed during stack frame layout anyway, but + // len(fn.Dcl) ends up influencing things like autotmp naming. + + used := usedLocals(body) + + for i, name := range r.curfn.Dcl { + if i < nparams || used.Has(name) { + name.Curfn = callerfn + callerfn.Dcl = append(callerfn.Dcl, name) + + // Quirkish. TODO(mdempsky): Document why. + if name.AutoTemp() { + name.SetEsc(ir.EscUnknown) + + if base.Flag.GenDwarfInl != 0 { + name.SetInlLocal(true) + } else { + name.SetPos(r.inlCall.Pos()) + } + } + } + } + + body.Append(ir.NewLabelStmt(call.Pos(), r.retlabel)) + + res := ir.NewInlinedCallExpr(call.Pos(), body, append([]ir.Node(nil), r.retvars...)) + res.SetInit(init) + res.SetType(call.Type()) + res.SetTypecheck(1) + + // Inlining shouldn't add any functions to todoBodies. + assert(len(todoBodies) == 0) + + return res +} + +// inlReturn returns a statement that can substitute for the given +// return statement when inlining. +func (r *reader) inlReturn(ret *ir.ReturnStmt) *ir.BlockStmt { + pos := r.inlCall.Pos() + + block := ir.TakeInit(ret) + + if results := ret.Results; len(results) != 0 { + assert(len(r.retvars) == len(results)) + + as2 := ir.NewAssignListStmt(pos, ir.OAS2, append([]ir.Node(nil), r.retvars...), ret.Results) + + if r.delayResults { + for _, name := range r.retvars { + // TODO(mdempsky): Use inlined position of name.Pos() instead? + name := name.(*ir.Name) + block.Append(ir.NewDecl(pos, ir.ODCL, name)) + name.Defn = as2 + } + } + + block.Append(as2) + } + + block.Append(ir.NewBranchStmt(pos, ir.OGOTO, r.retlabel)) + return ir.NewBlockStmt(pos, block) +} + +// expandInline reads in an extra copy of IR to populate +// fn.Inl.{Dcl,Body}. +func expandInline(fn *ir.Func, pri pkgReaderIndex) { + // TODO(mdempsky): Remove this function. It's currently needed for + // dwarfgen for some reason, but we should be able to provide it + // with the same information some other way. + + fndcls := len(fn.Dcl) + topdcls := len(typecheck.Target.Decls) + + tmpfn := ir.NewFunc(fn.Pos()) + tmpfn.Nname = ir.NewNameAt(fn.Nname.Pos(), fn.Sym()) + tmpfn.ClosureVars = fn.ClosureVars + + { + r := pri.asReader(relocBody, syncFuncBody) + r.setType(tmpfn.Nname, fn.Type()) + + // Don't change parameter's Sym/Nname fields. + r.funarghack = true + + r.funcBody(tmpfn) + } + + oldcurfn := ir.CurFunc + ir.CurFunc = tmpfn + + typecheck.Stmts(tmpfn.Body) + deadcode.Func(tmpfn) + + ir.CurFunc = oldcurfn + + used := usedLocals(tmpfn.Body) + + for _, name := range tmpfn.Dcl { + if name.Class != ir.PAUTO || used.Has(name) { + name.Curfn = fn + fn.Inl.Dcl = append(fn.Inl.Dcl, name) + } + } + fn.Inl.Body = tmpfn.Body + + // Double check that we didn't change fn.Dcl by accident. + assert(fndcls == len(fn.Dcl)) + + // typecheck.Stmts may have added function literals to + // typecheck.Target.Decls. Remove them again so we don't risk trying + // to compile them multiple times. + typecheck.Target.Decls = typecheck.Target.Decls[:topdcls] +} + +// usedLocals returns a set of local variables that are used within body. +func usedLocals(body []ir.Node) ir.NameSet { + var used ir.NameSet + ir.VisitList(body, func(n ir.Node) { + if n, ok := n.(*ir.Name); ok && n.Op() == ir.ONAME && n.Class == ir.PAUTO { + used.Add(n) + } + }) + return used +} diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go new file mode 100644 index 0000000000..174bd3f5bd --- /dev/null +++ b/src/cmd/compile/internal/noder/reader2.go @@ -0,0 +1,463 @@ +// UNREVIEWED + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package noder + +import ( + "go/constant" + + "cmd/compile/internal/base" + "cmd/compile/internal/syntax" + "cmd/compile/internal/types2" + "cmd/internal/src" +) + +type pkgReader2 struct { + pkgDecoder + + check *types2.Checker + imports map[string]*types2.Package + + posBases []*syntax.PosBase + pkgs []*types2.Package + typs []types2.Type +} + +func readPackage2(check *types2.Checker, imports map[string]*types2.Package, input pkgDecoder) *types2.Package { + pr := pkgReader2{ + pkgDecoder: input, + + check: check, + imports: imports, + + posBases: make([]*syntax.PosBase, input.numElems(relocPosBase)), + pkgs: make([]*types2.Package, input.numElems(relocPkg)), + typs: make([]types2.Type, input.numElems(relocType)), + } + + r := pr.newReader(relocMeta, publicRootIdx, syncPublic) + pkg := r.pkg() + r.bool() // has init + + for i, n := 0, r.len(); i < n; i++ { + r.obj() + } + + r.sync(syncEOF) + + pkg.MarkComplete() + return pkg +} + +type reader2 struct { + decoder + + p *pkgReader2 + + tparams []*types2.TypeName +} + +func (pr *pkgReader2) newReader(k reloc, idx int, marker syncMarker) *reader2 { + return &reader2{ + decoder: pr.newDecoder(k, idx, marker), + p: pr, + } +} + +// @@@ Positions + +func (r *reader2) pos() syntax.Pos { + r.sync(syncPos) + if !r.bool() { + return syntax.Pos{} + } + + // TODO(mdempsky): Delta encoding. + posBase := r.posBase() + line := r.uint() + col := r.uint() + return syntax.MakePos(posBase, line, col) +} + +func (r *reader2) posBase() *syntax.PosBase { + return r.p.posBaseIdx(r.reloc(relocPosBase)) +} + +func (pr *pkgReader2) posBaseIdx(idx int) *syntax.PosBase { + if b := pr.posBases[idx]; b != nil { + return b + } + + r := pr.newReader(relocPosBase, idx, syncPosBase) + var b *syntax.PosBase + + filename := r.string() + _ = r.string() // absolute file name + + if r.bool() { + b = syntax.NewFileBase(filename) + } else { + pos := r.pos() + line := r.uint() + col := r.uint() + b = syntax.NewLineBase(pos, filename, line, col) + } + + pr.posBases[idx] = b + return b +} + +// @@@ Packages + +func (r *reader2) pkg() *types2.Package { + r.sync(syncPkg) + return r.p.pkgIdx(r.reloc(relocPkg)) +} + +func (pr *pkgReader2) pkgIdx(idx int) *types2.Package { + // TODO(mdempsky): Consider using some non-nil pointer to indicate + // the universe scope, so we don't need to keep re-reading it. + if pkg := pr.pkgs[idx]; pkg != nil { + return pkg + } + + pkg := pr.newReader(relocPkg, idx, syncPkgDef).doPkg() + pr.pkgs[idx] = pkg + return pkg +} + +func (r *reader2) doPkg() *types2.Package { + path := r.string() + if path == "builtin" { + return nil // universe + } + if path == "" { + path = r.p.pkgPath + } + + if pkg := r.p.imports[path]; pkg != nil { + return pkg + } + + name := r.string() + height := r.len() + + pkg := types2.NewPackageHeight(path, name, height) + r.p.imports[path] = pkg + + // TODO(mdempsky): The list of imported packages is important for + // go/types, but we could probably skip populating it for types2. + imports := make([]*types2.Package, r.len()) + for i := range imports { + imports[i] = r.pkg() + } + pkg.SetImports(imports) + + return pkg +} + +// @@@ Types + +func (r *reader2) typ() types2.Type { + r.sync(syncType) + return r.p.typIdx(r.reloc(relocType), r.tparams) +} + +func (pr *pkgReader2) typIdx(idx int, tparams []*types2.TypeName) types2.Type { + if typ := pr.typs[idx]; typ != nil { + return typ + } + + r := pr.newReader(relocType, idx, syncTypeIdx) + r.tparams = tparams + typ := r.doTyp() + assert(typ != nil) + + if pr.typs[idx] != nil { + // See comment in pkgReader.typIdx. + return pr.typs[idx] + } + + if len(tparams) == 0 { + pr.typs[idx] = typ + } + + return typ +} + +func (r *reader2) doTyp() (res types2.Type) { + switch tag := codeType(r.code(syncType)); tag { + default: + base.FatalfAt(src.NoXPos, "unhandled type tag: %v", tag) + panic("unreachable") + + case typeBasic: + return types2.Typ[r.len()] + + case typeNamed: + obj, targs := r.obj() + name := obj.(*types2.TypeName) + if len(targs) != 0 { + return r.p.check.InstantiateLazy(syntax.Pos{}, name.Type(), targs) + } + return name.Type() + + case typeTypeParam: + idx := r.len() + return r.tparams[idx].Type().(*types2.TypeParam) + + case typeArray: + len := int64(r.uint64()) + return types2.NewArray(r.typ(), len) + case typeChan: + dir := types2.ChanDir(r.len()) + return types2.NewChan(dir, r.typ()) + case typeMap: + return types2.NewMap(r.typ(), r.typ()) + case typePointer: + return types2.NewPointer(r.typ()) + case typeSignature: + return r.signature(nil) + case typeSlice: + return types2.NewSlice(r.typ()) + case typeStruct: + return r.structType() + case typeInterface: + return r.interfaceType() + case typeUnion: + return r.unionType() + } +} + +func (r *reader2) structType() *types2.Struct { + fields := make([]*types2.Var, r.len()) + var tags []string + for i := range fields { + pos := r.pos() + pkg, name := r.selector() + ftyp := r.typ() + tag := r.string() + embedded := r.bool() + + fields[i] = types2.NewField(pos, pkg, name, ftyp, embedded) + if tag != "" { + for len(tags) < i { + tags = append(tags, "") + } + tags = append(tags, tag) + } + } + return types2.NewStruct(fields, tags) +} + +func (r *reader2) unionType() *types2.Union { + terms := make([]types2.Type, r.len()) + tildes := make([]bool, len(terms)) + for i := range terms { + terms[i] = r.typ() + tildes[i] = r.bool() + } + return types2.NewUnion(terms, tildes) +} + +func (r *reader2) interfaceType() *types2.Interface { + methods := make([]*types2.Func, r.len()) + embeddeds := make([]types2.Type, r.len()) + + for i := range methods { + pos := r.pos() + pkg, name := r.selector() + mtyp := r.signature(nil) + methods[i] = types2.NewFunc(pos, pkg, name, mtyp) + } + + for i := range embeddeds { + embeddeds[i] = r.typ() + } + + typ := types2.NewInterfaceType(methods, embeddeds) + typ.Complete() + return typ +} + +func (r *reader2) signature(recv *types2.Var) *types2.Signature { + r.sync(syncSignature) + + params := r.params() + results := r.params() + variadic := r.bool() + + return types2.NewSignature(recv, params, results, variadic) +} + +func (r *reader2) params() *types2.Tuple { + r.sync(syncParams) + params := make([]*types2.Var, r.len()) + for i := range params { + params[i] = r.param() + } + return types2.NewTuple(params...) +} + +func (r *reader2) param() *types2.Var { + r.sync(syncParam) + + pos := r.pos() + pkg, name := r.localIdent() + typ := r.typ() + + return types2.NewParam(pos, pkg, name, typ) +} + +// @@@ Objects + +func (r *reader2) obj() (types2.Object, []types2.Type) { + r.sync(syncObject) + + pkg, name := r.p.objIdx(r.reloc(relocObj)) + obj := pkg.Scope().Lookup(name) + + targs := make([]types2.Type, r.len()) + for i := range targs { + targs[i] = r.typ() + } + + return obj, targs +} + +func (pr *pkgReader2) objIdx(idx int) (*types2.Package, string) { + r := pr.newReader(relocObj, idx, syncObject1) + objPkg, objName := r.qualifiedIdent() + assert(objName != "") + + bounds := r.typeParamBounds() + tag := codeObj(r.code(syncCodeObj)) + + if tag == objStub { + assert(objPkg == nil) + return objPkg, objName + } + + objPkg.Scope().InsertLazy(objName, func() types2.Object { + switch tag { + default: + panic("weird") + + case objAlias: + pos := r.pos() + typ := r.typ() + return types2.NewTypeName(pos, objPkg, objName, typ) + + case objConst: + pos := r.pos() + typ, val := r.value() + return types2.NewConst(pos, objPkg, objName, typ, val) + + case objFunc: + pos := r.pos() + r.typeParamNames(bounds) + sig := r.signature(nil) + if len(r.tparams) != 0 { + sig.SetTParams(r.tparams) + } + return types2.NewFunc(pos, objPkg, objName, sig) + + case objType: + pos := r.pos() + + return types2.NewTypeNameLazy(pos, objPkg, objName, func(named *types2.Named) (tparams []*types2.TypeName, underlying types2.Type, methods []*types2.Func) { + r.typeParamNames(bounds) + if len(r.tparams) != 0 { + tparams = r.tparams + } + + // TODO(mdempsky): Rewrite receiver types to underlying is an + // Interface? The go/types importer does this (I think because + // unit tests expected that), but cmd/compile doesn't care + // about it, so maybe we can avoid worrying about that here. + underlying = r.typ().Underlying() + + methods = make([]*types2.Func, r.len()) + for i := range methods { + methods[i] = r.method(bounds) + } + + return + }) + + case objVar: + pos := r.pos() + typ := r.typ() + return types2.NewVar(pos, objPkg, objName, typ) + } + }) + + return objPkg, objName +} + +func (r *reader2) value() (types2.Type, constant.Value) { + r.sync(syncValue) + return r.typ(), r.rawValue() +} + +func (r *reader2) typeParamBounds() []int { + r.sync(syncTypeParamBounds) + + // exported types never have implicit type parameters + // TODO(mdempsky): Hide this from public importer. + assert(r.len() == 0) + + bounds := make([]int, r.len()) + for i := range bounds { + r.sync(syncType) + bounds[i] = r.reloc(relocType) + } + return bounds +} + +func (r *reader2) typeParamNames(bounds []int) { + r.sync(syncTypeParamNames) + + r.tparams = make([]*types2.TypeName, len(bounds)) + + for i := range r.tparams { + pos := r.pos() + pkg, name := r.localIdent() + + obj := types2.NewTypeName(pos, pkg, name, nil) + r.p.check.NewTypeParam(obj, i, nil) + r.tparams[i] = obj + } + + for i, tparam := range r.tparams { + bound := r.p.typIdx(bounds[i], r.tparams) + tparam.Type().(*types2.TypeParam).SetBound(bound) + } +} + +func (r *reader2) method(bounds []int) *types2.Func { + r.sync(syncMethod) + pos := r.pos() + pkg, name := r.selector() + + r.typeParamNames(bounds) + sig := r.signature(r.param()) + if len(r.tparams) != 0 { + sig.SetRParams(r.tparams) + } + + _ = r.pos() // TODO(mdempsky): Remove; this is a hacker for linker.go. + return types2.NewFunc(pos, pkg, name, sig) +} + +func (r *reader2) qualifiedIdent() (*types2.Package, string) { return r.ident(syncSym) } +func (r *reader2) localIdent() (*types2.Package, string) { return r.ident(syncLocalIdent) } +func (r *reader2) selector() (*types2.Package, string) { return r.ident(syncSelector) } + +func (r *reader2) ident(marker syncMarker) (*types2.Package, string) { + r.sync(marker) + return r.pkg(), r.string() +} diff --git a/src/cmd/compile/internal/noder/reloc.go b/src/cmd/compile/internal/noder/reloc.go new file mode 100644 index 0000000000..961de49419 --- /dev/null +++ b/src/cmd/compile/internal/noder/reloc.go @@ -0,0 +1,40 @@ +// UNREVIEWED + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package noder + +// A reloc indicates a particular section within a unified IR export. +// +// TODO(mdempsky): Rename to "section" or something similar? +type reloc int + +// A relocEnt (relocation entry) is an entry in an atom's local +// reference table. +// +// TODO(mdempsky): Rename this too. +type relocEnt struct { + kind reloc + idx int +} + +// Reserved indices within the meta relocation section. +const ( + publicRootIdx = 0 + privateRootIdx = 1 +) + +const ( + relocString reloc = iota + relocMeta + relocPosBase + relocPkg + relocType + relocObj + relocObjExt + relocBody + + numRelocs = iota +) diff --git a/src/cmd/compile/internal/noder/sync.go b/src/cmd/compile/internal/noder/sync.go new file mode 100644 index 0000000000..d77a784479 --- /dev/null +++ b/src/cmd/compile/internal/noder/sync.go @@ -0,0 +1,154 @@ +// UNREVIEWED + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package noder + +const debug = true + +type syncMarker int + +//go:generate stringer -type=syncMarker -trimprefix=sync + +// TODO(mdempsky): Cleanup unneeded sync markers. + +// TODO(mdempsky): Split these markers into public/stable markers, and +// private ones. Also, trim unused ones. +const ( + _ syncMarker = iota + syncNode + syncBool + syncInt64 + syncUint64 + syncString + syncPos + syncPkg + syncSym + syncSelector + syncKind + syncType + syncTypePkg + syncSignature + syncParam + syncOp + syncObject + syncExpr + syncStmt + syncDecl + syncConstDecl + syncFuncDecl + syncTypeDecl + syncVarDecl + syncPragma + syncValue + syncEOF + syncMethod + syncFuncBody + syncUse + syncUseObj + syncObjectIdx + syncTypeIdx + syncBOF + syncEntry + syncOpenScope + syncCloseScope + syncGlobal + syncLocal + syncDefine + syncDefLocal + syncUseLocal + syncDefGlobal + syncUseGlobal + syncTypeParams + syncUseLabel + syncDefLabel + syncFuncLit + syncCommonFunc + syncBodyRef + syncLinksymExt + syncHack + syncSetlineno + syncName + syncImportDecl + syncDeclNames + syncDeclName + syncExprList + syncExprs + syncWrapname + syncTypeExpr + syncTypeExprOrNil + syncChanDir + syncParams + syncCloseAnotherScope + syncSum + syncUnOp + syncBinOp + syncStructType + syncInterfaceType + syncPackname + syncEmbedded + syncStmts + syncStmtsFall + syncStmtFall + syncBlockStmt + syncIfStmt + syncForStmt + syncSwitchStmt + syncRangeStmt + syncCaseClause + syncCommClause + syncSelectStmt + syncDecls + syncLabeledStmt + syncCompLit + + sync1 + sync2 + sync3 + sync4 + + syncN + syncDefImplicit + syncUseName + syncUseObjLocal + syncAddLocal + syncBothSignature + syncSetUnderlying + syncLinkname + syncStmt1 + syncStmtsEnd + syncDeclare + syncTopDecls + syncTopConstDecl + syncTopFuncDecl + syncTopTypeDecl + syncTopVarDecl + syncObject1 + syncAddBody + syncLabel + syncFuncExt + syncMethExt + syncOptLabel + syncScalar + syncStmtDecls + syncDeclLocal + syncObjLocal + syncObjLocal1 + syncDeclareLocal + syncPublic + syncPrivate + syncRelocs + syncReloc + syncUseReloc + syncVarExt + syncPkgDef + syncTypeExt + syncVal + syncCodeObj + syncPosBase + syncLocalIdent + syncTypeParamNames + syncTypeParamBounds +) diff --git a/src/cmd/compile/internal/noder/syncmarker_string.go b/src/cmd/compile/internal/noder/syncmarker_string.go new file mode 100644 index 0000000000..3eb88fb911 --- /dev/null +++ b/src/cmd/compile/internal/noder/syncmarker_string.go @@ -0,0 +1,152 @@ +// Code generated by "stringer -type=syncMarker -trimprefix=sync"; DO NOT EDIT. + +package noder + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[syncNode-1] + _ = x[syncBool-2] + _ = x[syncInt64-3] + _ = x[syncUint64-4] + _ = x[syncString-5] + _ = x[syncPos-6] + _ = x[syncPkg-7] + _ = x[syncSym-8] + _ = x[syncSelector-9] + _ = x[syncKind-10] + _ = x[syncType-11] + _ = x[syncTypePkg-12] + _ = x[syncSignature-13] + _ = x[syncParam-14] + _ = x[syncOp-15] + _ = x[syncObject-16] + _ = x[syncExpr-17] + _ = x[syncStmt-18] + _ = x[syncDecl-19] + _ = x[syncConstDecl-20] + _ = x[syncFuncDecl-21] + _ = x[syncTypeDecl-22] + _ = x[syncVarDecl-23] + _ = x[syncPragma-24] + _ = x[syncValue-25] + _ = x[syncEOF-26] + _ = x[syncMethod-27] + _ = x[syncFuncBody-28] + _ = x[syncUse-29] + _ = x[syncUseObj-30] + _ = x[syncObjectIdx-31] + _ = x[syncTypeIdx-32] + _ = x[syncBOF-33] + _ = x[syncEntry-34] + _ = x[syncOpenScope-35] + _ = x[syncCloseScope-36] + _ = x[syncGlobal-37] + _ = x[syncLocal-38] + _ = x[syncDefine-39] + _ = x[syncDefLocal-40] + _ = x[syncUseLocal-41] + _ = x[syncDefGlobal-42] + _ = x[syncUseGlobal-43] + _ = x[syncTypeParams-44] + _ = x[syncUseLabel-45] + _ = x[syncDefLabel-46] + _ = x[syncFuncLit-47] + _ = x[syncCommonFunc-48] + _ = x[syncBodyRef-49] + _ = x[syncLinksymExt-50] + _ = x[syncHack-51] + _ = x[syncSetlineno-52] + _ = x[syncName-53] + _ = x[syncImportDecl-54] + _ = x[syncDeclNames-55] + _ = x[syncDeclName-56] + _ = x[syncExprList-57] + _ = x[syncExprs-58] + _ = x[syncWrapname-59] + _ = x[syncTypeExpr-60] + _ = x[syncTypeExprOrNil-61] + _ = x[syncChanDir-62] + _ = x[syncParams-63] + _ = x[syncCloseAnotherScope-64] + _ = x[syncSum-65] + _ = x[syncUnOp-66] + _ = x[syncBinOp-67] + _ = x[syncStructType-68] + _ = x[syncInterfaceType-69] + _ = x[syncPackname-70] + _ = x[syncEmbedded-71] + _ = x[syncStmts-72] + _ = x[syncStmtsFall-73] + _ = x[syncStmtFall-74] + _ = x[syncBlockStmt-75] + _ = x[syncIfStmt-76] + _ = x[syncForStmt-77] + _ = x[syncSwitchStmt-78] + _ = x[syncRangeStmt-79] + _ = x[syncCaseClause-80] + _ = x[syncCommClause-81] + _ = x[syncSelectStmt-82] + _ = x[syncDecls-83] + _ = x[syncLabeledStmt-84] + _ = x[syncCompLit-85] + _ = x[sync1-86] + _ = x[sync2-87] + _ = x[sync3-88] + _ = x[sync4-89] + _ = x[syncN-90] + _ = x[syncDefImplicit-91] + _ = x[syncUseName-92] + _ = x[syncUseObjLocal-93] + _ = x[syncAddLocal-94] + _ = x[syncBothSignature-95] + _ = x[syncSetUnderlying-96] + _ = x[syncLinkname-97] + _ = x[syncStmt1-98] + _ = x[syncStmtsEnd-99] + _ = x[syncDeclare-100] + _ = x[syncTopDecls-101] + _ = x[syncTopConstDecl-102] + _ = x[syncTopFuncDecl-103] + _ = x[syncTopTypeDecl-104] + _ = x[syncTopVarDecl-105] + _ = x[syncObject1-106] + _ = x[syncAddBody-107] + _ = x[syncLabel-108] + _ = x[syncFuncExt-109] + _ = x[syncMethExt-110] + _ = x[syncOptLabel-111] + _ = x[syncScalar-112] + _ = x[syncStmtDecls-113] + _ = x[syncDeclLocal-114] + _ = x[syncObjLocal-115] + _ = x[syncObjLocal1-116] + _ = x[syncDeclareLocal-117] + _ = x[syncPublic-118] + _ = x[syncPrivate-119] + _ = x[syncRelocs-120] + _ = x[syncReloc-121] + _ = x[syncUseReloc-122] + _ = x[syncVarExt-123] + _ = x[syncPkgDef-124] + _ = x[syncTypeExt-125] + _ = x[syncVal-126] + _ = x[syncCodeObj-127] + _ = x[syncPosBase-128] + _ = x[syncLocalIdent-129] +} + +const _syncMarker_name = "NodeBoolInt64Uint64StringPosPkgSymSelectorKindTypeTypePkgSignatureParamOpObjectExprStmtDeclConstDeclFuncDeclTypeDeclVarDeclPragmaValueEOFMethodFuncBodyUseUseObjObjectIdxTypeIdxBOFEntryOpenScopeCloseScopeGlobalLocalDefineDefLocalUseLocalDefGlobalUseGlobalTypeParamsUseLabelDefLabelFuncLitCommonFuncBodyRefLinksymExtHackSetlinenoNameImportDeclDeclNamesDeclNameExprListExprsWrapnameTypeExprTypeExprOrNilChanDirParamsCloseAnotherScopeSumUnOpBinOpStructTypeInterfaceTypePacknameEmbeddedStmtsStmtsFallStmtFallBlockStmtIfStmtForStmtSwitchStmtRangeStmtCaseClauseCommClauseSelectStmtDeclsLabeledStmtCompLit1234NDefImplicitUseNameUseObjLocalAddLocalBothSignatureSetUnderlyingLinknameStmt1StmtsEndDeclareTopDeclsTopConstDeclTopFuncDeclTopTypeDeclTopVarDeclObject1AddBodyLabelFuncExtMethExtOptLabelScalarStmtDeclsDeclLocalObjLocalObjLocal1DeclareLocalPublicPrivateRelocsRelocUseRelocVarExtPkgDefTypeExtValCodeObjPosBaseLocalIdent" + +var _syncMarker_index = [...]uint16{0, 4, 8, 13, 19, 25, 28, 31, 34, 42, 46, 50, 57, 66, 71, 73, 79, 83, 87, 91, 100, 108, 116, 123, 129, 134, 137, 143, 151, 154, 160, 169, 176, 179, 184, 193, 203, 209, 214, 220, 228, 236, 245, 254, 264, 272, 280, 287, 297, 304, 314, 318, 327, 331, 341, 350, 358, 366, 371, 379, 387, 400, 407, 413, 430, 433, 437, 442, 452, 465, 473, 481, 486, 495, 503, 512, 518, 525, 535, 544, 554, 564, 574, 579, 590, 597, 598, 599, 600, 601, 602, 613, 620, 631, 639, 652, 665, 673, 678, 686, 693, 701, 713, 724, 735, 745, 752, 759, 764, 771, 778, 786, 792, 801, 810, 818, 827, 839, 845, 852, 858, 863, 871, 877, 883, 890, 893, 900, 907, 917} + +func (i syncMarker) String() string { + i -= 1 + if i < 0 || i >= syncMarker(len(_syncMarker_index)-1) { + return "syncMarker(" + strconv.FormatInt(int64(i+1), 10) + ")" + } + return _syncMarker_name[_syncMarker_index[i]:_syncMarker_index[i+1]] +} diff --git a/src/cmd/compile/internal/noder/unified.go b/src/cmd/compile/internal/noder/unified.go new file mode 100644 index 0000000000..9a41ea9dfe --- /dev/null +++ b/src/cmd/compile/internal/noder/unified.go @@ -0,0 +1,276 @@ +// UNREVIEWED + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package noder + +import ( + "bytes" + "fmt" + "internal/goversion" + "io" + "runtime" + "sort" + + "cmd/compile/internal/base" + "cmd/compile/internal/inline" + "cmd/compile/internal/ir" + "cmd/compile/internal/typecheck" + "cmd/compile/internal/types" + "cmd/compile/internal/types2" + "cmd/internal/src" +) + +// localPkgReader holds the package reader used for reading the local +// package. It exists so the unified IR linker can refer back to it +// later. +var localPkgReader *pkgReader + +// useUnifiedIR reports whether the unified IR frontend should be +// used; and if so, uses it to construct the local package's IR. +func useUnifiedIR(noders []*noder) { + inline.NewInline = InlineCall + + if !quirksMode() { + writeNewExportFunc = writeNewExport + } + + newReadImportFunc = func(data string, pkg1 *types.Pkg, check *types2.Checker, packages map[string]*types2.Package) (pkg2 *types2.Package, err error) { + pr := newPkgDecoder(pkg1.Path, data) + + // Read package descriptors for both types2 and compiler backend. + readPackage(newPkgReader(pr), pkg1) + pkg2 = readPackage2(check, packages, pr) + return + } + + data := writePkgStub(noders) + + // We already passed base.Flag.Lang to types2 to handle validating + // the user's source code. Bump it up now to the current version and + // re-parse, so typecheck doesn't complain if we construct IR that + // utilizes newer Go features. + base.Flag.Lang = fmt.Sprintf("go1.%d", goversion.Version) + types.ParseLangFlag() + + assert(types.LocalPkg.Path == "") + types.LocalPkg.Height = 0 // reset so pkgReader.pkgIdx doesn't complain + target := typecheck.Target + + typecheck.TypecheckAllowed = true + + localPkgReader = newPkgReader(newPkgDecoder(types.LocalPkg.Path, data)) + readPackage(localPkgReader, types.LocalPkg) + + r := localPkgReader.newReader(relocMeta, privateRootIdx, syncPrivate) + r.ext = r + r.pkgInit(types.LocalPkg, target) + + // Don't use range--bodyIdx can add closures to todoBodies. + for len(todoBodies) > 0 { + // The order we expand bodies doesn't matter, so pop from the end + // to reduce todoBodies reallocations if it grows further. + fn := todoBodies[len(todoBodies)-1] + todoBodies = todoBodies[:len(todoBodies)-1] + + pri, ok := bodyReader[fn] + assert(ok) + pri.funcBody(fn) + + // Instantiated generic function: add to Decls for typechecking + // and compilation. + if len(pri.implicits) != 0 && fn.OClosure == nil { + target.Decls = append(target.Decls, fn) + } + } + todoBodies = nil + + // Don't use range--typecheck can add closures to Target.Decls. + for i := 0; i < len(target.Decls); i++ { + target.Decls[i] = typecheck.Stmt(target.Decls[i]) + } + + // Don't use range--typecheck can add closures to Target.Decls. + for i := 0; i < len(target.Decls); i++ { + if fn, ok := target.Decls[i].(*ir.Func); ok { + if base.Flag.W > 1 { + s := fmt.Sprintf("\nbefore typecheck %v", fn) + ir.Dump(s, fn) + } + ir.CurFunc = fn + typecheck.Stmts(fn.Body) + if base.Flag.W > 1 { + s := fmt.Sprintf("\nafter typecheck %v", fn) + ir.Dump(s, fn) + } + } + } + + base.ExitIfErrors() // just in case +} + +// writePkgStub type checks the given parsed source files and then +// returns +func writePkgStub(noders []*noder) string { + m, pkg, info := checkFiles(noders) + + pw := newPkgWriter(m, pkg, info) + + pw.collectDecls(noders) + + publicRootWriter := pw.newWriter(relocMeta, syncPublic) + privateRootWriter := pw.newWriter(relocMeta, syncPrivate) + + assert(publicRootWriter.idx == publicRootIdx) + assert(privateRootWriter.idx == privateRootIdx) + + { + w := publicRootWriter + w.pkg(pkg) + w.bool(false) // has init; XXX + + scope := pkg.Scope() + names := scope.Names() + w.len(len(names)) + for _, name := range scope.Names() { + w.obj(scope.Lookup(name), nil) + } + + w.sync(syncEOF) + w.flush() + } + + { + w := privateRootWriter + w.ext = w + w.pkgInit(noders) + w.flush() + } + + var sb bytes.Buffer // TODO(mdempsky): strings.Builder after #44505 is resolved + pw.dump(&sb) + + // At this point, we're done with types2. Make sure the package is + // garbage collected. + freePackage(pkg) + + return sb.String() +} + +// freePackage ensures the given package is garbage collected. +func freePackage(pkg *types2.Package) { + // Set a finalizer on pkg so we can detect if/when it's collected. + done := make(chan struct{}) + runtime.SetFinalizer(pkg, func(*types2.Package) { close(done) }) + + // Important: objects involved in cycles are not finalized, so zero + // out pkg to break its cycles and allow the finalizer to run. + *pkg = types2.Package{} + + // It typically takes just 1 or 2 cycles to release pkg, but it + // doesn't hurt to try a few more times. + for i := 0; i < 10; i++ { + select { + case <-done: + return + default: + runtime.GC() + } + } + + base.Fatalf("package never finalized") +} + +func readPackage(pr *pkgReader, importpkg *types.Pkg) { + r := pr.newReader(relocMeta, publicRootIdx, syncPublic) + + pkg := r.pkg() + assert(pkg == importpkg) + + if r.bool() { + sym := pkg.Lookup(".inittask") + task := ir.NewNameAt(src.NoXPos, sym) + task.Class = ir.PEXTERN + sym.Def = task + } + + for i, n := 0, r.len(); i < n; i++ { + r.sync(syncObject) + idx := r.reloc(relocObj) + assert(r.len() == 0) + + path, name, code, _ := r.p.peekObj(idx) + if code != objStub { + objReader[types.NewPkg(path, "").Lookup(name)] = pkgReaderIndex{pr, idx, nil} + } + } +} + +func writeNewExport(out io.Writer) { + l := linker{ + pw: newPkgEncoder(), + + pkgs: make(map[string]int), + decls: make(map[*types.Sym]int), + } + + publicRootWriter := l.pw.newEncoder(relocMeta, syncPublic) + assert(publicRootWriter.idx == publicRootIdx) + + var selfPkgIdx int + + { + pr := localPkgReader + r := pr.newDecoder(relocMeta, publicRootIdx, syncPublic) + + r.sync(syncPkg) + selfPkgIdx = l.relocIdx(pr, relocPkg, r.reloc(relocPkg)) + + r.bool() // has init + + for i, n := 0, r.len(); i < n; i++ { + r.sync(syncObject) + idx := r.reloc(relocObj) + assert(r.len() == 0) + + xpath, xname, xtag, _ := pr.peekObj(idx) + assert(xpath == pr.pkgPath) + assert(xtag != objStub) + + if types.IsExported(xname) { + l.relocIdx(pr, relocObj, idx) + } + } + + r.sync(syncEOF) + } + + { + var idxs []int + for _, idx := range l.decls { + idxs = append(idxs, idx) + } + sort.Ints(idxs) + + w := publicRootWriter + + w.sync(syncPkg) + w.reloc(relocPkg, selfPkgIdx) + + w.bool(typecheck.Lookup(".inittask").Def != nil) + + w.len(len(idxs)) + for _, idx := range idxs { + w.sync(syncObject) + w.reloc(relocObj, idx) + w.len(0) + } + + w.sync(syncEOF) + w.flush() + } + + l.pw.dump(out) +} diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go new file mode 100644 index 0000000000..b39dd8651b --- /dev/null +++ b/src/cmd/compile/internal/noder/writer.go @@ -0,0 +1,1746 @@ +// UNREVIEWED + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package noder + +import ( + "fmt" + "go/constant" + + "cmd/compile/internal/base" + "cmd/compile/internal/ir" + "cmd/compile/internal/syntax" + "cmd/compile/internal/types2" +) + +type pkgWriter struct { + pkgEncoder + + m posMap + curpkg *types2.Package + info *types2.Info + + posBasesIdx map[*syntax.PosBase]int + pkgsIdx map[*types2.Package]int + typsIdx map[types2.Type]int + globalsIdx map[types2.Object]int + + funDecls map[*types2.Func]*syntax.FuncDecl + typDecls map[*types2.TypeName]typeDeclGen + + linknames map[types2.Object]string + cgoPragmas [][]string + + dups dupTypes +} + +func newPkgWriter(m posMap, pkg *types2.Package, info *types2.Info) *pkgWriter { + return &pkgWriter{ + pkgEncoder: newPkgEncoder(), + + m: m, + curpkg: pkg, + info: info, + + pkgsIdx: make(map[*types2.Package]int), + globalsIdx: make(map[types2.Object]int), + typsIdx: make(map[types2.Type]int), + + posBasesIdx: make(map[*syntax.PosBase]int), + + funDecls: make(map[*types2.Func]*syntax.FuncDecl), + typDecls: make(map[*types2.TypeName]typeDeclGen), + + linknames: make(map[types2.Object]string), + } +} + +func (pw *pkgWriter) errorf(p poser, msg string, args ...interface{}) { + base.ErrorfAt(pw.m.pos(p), msg, args...) +} + +func (pw *pkgWriter) fatalf(p poser, msg string, args ...interface{}) { + base.FatalfAt(pw.m.pos(p), msg, args...) +} + +func (pw *pkgWriter) unexpected(what string, p poser) { + pw.fatalf(p, "unexpected %s: %v (%T)", what, p, p) +} + +type writer struct { + p *pkgWriter + + encoder + + // For writing out object descriptions, ext points to the extension + // writer for where we can write the compiler's private extension + // details for the object. + // + // TODO(mdempsky): This is a little hacky, but works easiest with + // the way things are currently. + ext *writer + + // TODO(mdempsky): We should be able to prune localsIdx whenever a + // scope closes, and then maybe we can just use the same map for + // storing the TypeParams too (as their TypeName instead). + + // type parameters. explicitIdx has the type parameters declared on + // the current object, while implicitIdx has the type parameters + // declared on the enclosing object (if any). + // + // TODO(mdempsky): Merge these back together, now that I've got them + // working. + implicitIdx map[*types2.TypeParam]int + explicitIdx map[*types2.TypeParam]int + + // variables declared within this function + localsIdx map[types2.Object]int +} + +func (pw *pkgWriter) newWriter(k reloc, marker syncMarker) *writer { + return &writer{ + encoder: pw.newEncoder(k, marker), + p: pw, + } +} + +// @@@ Positions + +func (w *writer) pos(p poser) { + w.sync(syncPos) + pos := p.Pos() + + // TODO(mdempsky): Track down the remaining cases here and fix them. + if !w.bool(pos.IsKnown()) { + return + } + + // TODO(mdempsky): Delta encoding. Also, if there's a b-side, update + // its position base too (but not vice versa!). + w.posBase(pos.Base()) + w.uint(pos.Line()) + w.uint(pos.Col()) +} + +func (w *writer) posBase(b *syntax.PosBase) { + w.reloc(relocPosBase, w.p.posBaseIdx(b)) +} + +func (pw *pkgWriter) posBaseIdx(b *syntax.PosBase) int { + if idx, ok := pw.posBasesIdx[b]; ok { + return idx + } + + w := pw.newWriter(relocPosBase, syncPosBase) + w.p.posBasesIdx[b] = w.idx + + // TODO(mdempsky): What exactly does "fileh" do anyway? Is writing + // out both of these strings really the right thing to do here? + fn := b.Filename() + w.string(fn) + w.string(fileh(fn)) + + if !w.bool(b.IsFileBase()) { + w.pos(b) + w.uint(b.Line()) + w.uint(b.Col()) + } + + return w.flush() +} + +// @@@ Packages + +func (w *writer) pkg(pkg *types2.Package) { + w.sync(syncPkg) + w.reloc(relocPkg, w.p.pkgIdx(pkg)) +} + +func (pw *pkgWriter) pkgIdx(pkg *types2.Package) int { + if idx, ok := pw.pkgsIdx[pkg]; ok { + return idx + } + + w := pw.newWriter(relocPkg, syncPkgDef) + pw.pkgsIdx[pkg] = w.idx + + if pkg == nil { + w.string("builtin") + } else { + var path string + if pkg != w.p.curpkg { + path = pkg.Path() + } + w.string(path) + w.string(pkg.Name()) + w.len(pkg.Height()) + + w.len(len(pkg.Imports())) + for _, imp := range pkg.Imports() { + w.pkg(imp) + } + } + + return w.flush() +} + +// @@@ Types + +func (w *writer) typ(typ types2.Type) { + w.sync(syncType) + + if quirksMode() { + typ = w.p.dups.orig(typ) + } + + w.reloc(relocType, w.p.typIdx(typ, w.implicitIdx, w.explicitIdx)) +} + +func (pw *pkgWriter) typIdx(typ types2.Type, implicitIdx, explicitIdx map[*types2.TypeParam]int) int { + if idx, ok := pw.typsIdx[typ]; ok { + return idx + } + + w := pw.newWriter(relocType, syncTypeIdx) + w.implicitIdx = implicitIdx + w.explicitIdx = explicitIdx + + pw.typsIdx[typ] = w.idx // handle cycles + w.doTyp(typ) + return w.flush() +} + +func (w *writer) doTyp(typ types2.Type) { + switch typ := typ.(type) { + default: + base.Fatalf("unexpected type: %v (%T)", typ, typ) + + case *types2.Basic: + if kind := typ.Kind(); types2.Typ[kind] == typ { + w.code(typeBasic) + w.len(int(kind)) + break + } + + // Handle "byte" and "rune" as references to their TypeName. + obj := types2.Universe.Lookup(typ.Name()) + assert(obj.Type() == typ) + + w.code(typeNamed) + w.obj(obj, nil) + + case *types2.Named: + // Type aliases can refer to uninstantiated generic types, so we + // might see len(TParams) != 0 && len(TArgs) == 0 here. + // TODO(mdempsky): Revisit after #46477 is resolved. + assert(len(typ.TParams()) == len(typ.TArgs()) || len(typ.TArgs()) == 0) + + // TODO(mdempsky): Why do we need to loop here? + orig := typ + for orig.TArgs() != nil { + orig = orig.Orig() + } + + w.code(typeNamed) + w.obj(orig.Obj(), typ.TArgs()) + + case *types2.TypeParam: + w.code(typeTypeParam) + if idx, ok := w.implicitIdx[typ]; ok { + w.len(idx) + } else if idx, ok := w.explicitIdx[typ]; ok { + w.len(len(w.implicitIdx) + idx) + } else { + w.p.fatalf(typ.Obj(), "%v not in %v or %v", typ, w.implicitIdx, w.explicitIdx) + } + + case *types2.Array: + w.code(typeArray) + w.uint64(uint64(typ.Len())) + w.typ(typ.Elem()) + + case *types2.Chan: + w.code(typeChan) + w.len(int(typ.Dir())) + w.typ(typ.Elem()) + + case *types2.Map: + w.code(typeMap) + w.typ(typ.Key()) + w.typ(typ.Elem()) + + case *types2.Pointer: + w.code(typePointer) + w.typ(typ.Elem()) + + case *types2.Signature: + assert(typ.TParams() == nil) + w.code(typeSignature) + w.signature(typ) + + case *types2.Slice: + w.code(typeSlice) + w.typ(typ.Elem()) + + case *types2.Struct: + w.code(typeStruct) + w.structType(typ) + + case *types2.Interface: + w.code(typeInterface) + w.interfaceType(typ) + + case *types2.Union: + w.code(typeUnion) + w.unionType(typ) + } +} + +func (w *writer) structType(typ *types2.Struct) { + w.len(typ.NumFields()) + for i := 0; i < typ.NumFields(); i++ { + f := typ.Field(i) + w.pos(f) + w.selector(f) + w.typ(f.Type()) + w.string(typ.Tag(i)) + w.bool(f.Embedded()) + } +} + +func (w *writer) unionType(typ *types2.Union) { + w.len(typ.NumTerms()) + for i := 0; i < typ.NumTerms(); i++ { + term, tilde := typ.Term(i) + w.typ(term) + w.bool(tilde) + } +} + +func (w *writer) interfaceType(typ *types2.Interface) { + w.len(typ.NumExplicitMethods()) + w.len(typ.NumEmbeddeds()) + + for i := 0; i < typ.NumExplicitMethods(); i++ { + m := typ.ExplicitMethod(i) + sig := m.Type().(*types2.Signature) + assert(sig.TParams() == nil) + + w.pos(m) + w.selector(m) + w.signature(sig) + } + + for i := 0; i < typ.NumEmbeddeds(); i++ { + w.typ(typ.EmbeddedType(i)) + } +} + +func (w *writer) signature(sig *types2.Signature) { + w.sync(syncSignature) + w.params(sig.Params()) + w.params(sig.Results()) + w.bool(sig.Variadic()) +} + +func (w *writer) params(typ *types2.Tuple) { + w.sync(syncParams) + w.len(typ.Len()) + for i := 0; i < typ.Len(); i++ { + w.param(typ.At(i)) + } +} + +func (w *writer) param(param *types2.Var) { + w.sync(syncParam) + w.pos(param) + w.localIdent(param) + w.typ(param.Type()) +} + +// @@@ Objects + +func (w *writer) obj(obj types2.Object, explicits []types2.Type) { + w.sync(syncObject) + + var implicitIdx map[*types2.TypeParam]int + if isDefinedType(obj) && !isGlobal(obj) { + implicitIdx = w.implicitIdx + } + w.reloc(relocObj, w.p.objIdx(obj, implicitIdx)) + + w.len(len(explicits)) + for _, explicit := range explicits { + w.typ(explicit) + } +} + +func (pw *pkgWriter) objIdx(obj types2.Object, implicitIdx map[*types2.TypeParam]int) int { + if idx, ok := pw.globalsIdx[obj]; ok { + return idx + } + + w := pw.newWriter(relocObj, syncObject1) + w.ext = pw.newWriter(relocObjExt, syncObject1) + assert(w.ext.idx == w.idx) + + pw.globalsIdx[obj] = w.idx + + w.implicitIdx = implicitIdx + w.ext.implicitIdx = implicitIdx + + w.doObj(obj) + + w.flush() + w.ext.flush() + + return w.idx +} + +func (w *writer) doObj(obj types2.Object) { + // Ident goes first so importer can avoid unnecessary work if + // they've already resolved this object. + w.qualifiedIdent(obj) + + tparams := objTypeParams(obj) + w.setTypeParams(tparams) + w.typeParamBounds(tparams) + + if obj.Pkg() != w.p.curpkg { + w.code(objStub) + return + } + + switch obj := obj.(type) { + default: + w.p.unexpected("object", obj) + + case *types2.Const: + w.code(objConst) + w.pos(obj) + w.value(obj.Type(), obj.Val()) + + case *types2.Func: + decl, ok := w.p.funDecls[obj] + assert(ok) + sig := obj.Type().(*types2.Signature) + + // Rewrite blank methods into blank functions. + // They aren't included in the receiver type's method set, + // and we still want to write them out to be compiled + // for regression tests. + // TODO(mdempsky): Change regress tests to avoid relying + // on blank functions/methods, so we can just ignore them + // altogether. + if recv := sig.Recv(); recv != nil { + assert(obj.Name() == "_") + assert(sig.TParams() == nil) + + params := make([]*types2.Var, 1+sig.Params().Len()) + params[0] = recv + for i := 0; i < sig.Params().Len(); i++ { + params[1+i] = sig.Params().At(i) + } + sig = types2.NewSignature(nil, types2.NewTuple(params...), sig.Results(), sig.Variadic()) + } + + w.code(objFunc) + w.pos(obj) + w.typeParamNames(sig.TParams()) + w.signature(sig) + w.pos(decl) + w.ext.funcExt(obj) + + case *types2.TypeName: + decl, ok := w.p.typDecls[obj] + assert(ok) + + if obj.IsAlias() { + w.code(objAlias) + w.pos(obj) + w.typ(obj.Type()) + break + } + + named := obj.Type().(*types2.Named) + assert(named.TArgs() == nil) + + w.code(objType) + w.pos(obj) + w.typeParamNames(named.TParams()) + w.ext.typeExt(obj) + w.typExpr(decl.Type) + + w.len(named.NumMethods()) + for i := 0; i < named.NumMethods(); i++ { + w.method(named.Method(i)) + } + + case *types2.Var: + w.code(objVar) + w.pos(obj) + w.typ(obj.Type()) + w.ext.varExt(obj) + } +} + +// typExpr writes the type represented by the given expression. +func (w *writer) typExpr(expr syntax.Expr) { + tv, ok := w.p.info.Types[expr] + assert(ok) + assert(tv.IsType()) + w.typ(tv.Type) +} + +func (w *writer) value(typ types2.Type, val constant.Value) { + w.sync(syncValue) + w.typ(typ) + w.rawValue(val) +} + +func (w *writer) setTypeParams(tparams []*types2.TypeName) { + if len(tparams) == 0 { + return + } + + explicitIdx := make(map[*types2.TypeParam]int) + for _, tparam := range tparams { + explicitIdx[tparam.Type().(*types2.TypeParam)] = len(explicitIdx) + } + + w.explicitIdx = explicitIdx + w.ext.explicitIdx = explicitIdx +} + +func (w *writer) typeParamBounds(tparams []*types2.TypeName) { + w.sync(syncTypeParamBounds) + + // TODO(mdempsky): Remove. It's useful for debugging at the moment, + // but it doesn't belong here. + w.len(len(w.implicitIdx)) + w.len(len(w.explicitIdx)) + assert(len(w.explicitIdx) == len(tparams)) + + for _, tparam := range tparams { + w.typ(tparam.Type().(*types2.TypeParam).Bound()) + } +} + +func (w *writer) typeParamNames(tparams []*types2.TypeName) { + w.sync(syncTypeParamNames) + + for _, tparam := range tparams { + w.pos(tparam) + w.localIdent(tparam) + } +} + +func (w *writer) method(meth *types2.Func) { + decl, ok := w.p.funDecls[meth] + assert(ok) + sig := meth.Type().(*types2.Signature) + + assert(len(w.explicitIdx) == len(sig.RParams())) + w.setTypeParams(sig.RParams()) + + w.sync(syncMethod) + w.pos(meth) + w.selector(meth) + w.typeParamNames(sig.RParams()) + w.param(sig.Recv()) + w.signature(sig) + + w.pos(decl) // XXX: Hack to workaround linker limitations. + w.ext.funcExt(meth) +} + +// qualifiedIdent writes out the name of an object declared at package +// scope. (For now, it's also used to refer to local defined types.) +func (w *writer) qualifiedIdent(obj types2.Object) { + w.sync(syncSym) + + name := obj.Name() + if isDefinedType(obj) && !isGlobal(obj) { + // TODO(mdempsky): Find a better solution, this is terrible. + decl, ok := w.p.typDecls[obj.(*types2.TypeName)] + assert(ok) + name = fmt.Sprintf("%s·%v", name, decl.gen) + } + + w.pkg(obj.Pkg()) + w.string(name) +} + +// TODO(mdempsky): We should be able to omit pkg from both localIdent +// and selector, because they should always be known from context. +// However, past frustrations with this optimization in iexport make +// me a little nervous to try it again. + +// localIdent writes the name of a locally declared object (i.e., +// objects that can only be accessed by name, within the context of a +// particular function). +func (w *writer) localIdent(obj types2.Object) { + assert(!isGlobal(obj)) + w.sync(syncLocalIdent) + w.pkg(obj.Pkg()) + w.string(obj.Name()) +} + +// selector writes the name of a field or method (i.e., objects that +// can only be accessed using selector expressions). +func (w *writer) selector(obj types2.Object) { + w.sync(syncSelector) + w.pkg(obj.Pkg()) + w.string(obj.Name()) +} + +// @@@ Compiler extensions + +func (w *writer) funcExt(obj *types2.Func) { + decl, ok := w.p.funDecls[obj] + assert(ok) + + // TODO(mdempsky): Extend these pragma validation flags to account + // for generics. E.g., linkname probably doesn't make sense at + // least. + + pragma := asPragmaFlag(decl.Pragma) + if pragma&ir.Systemstack != 0 && pragma&ir.Nosplit != 0 { + w.p.errorf(decl, "go:nosplit and go:systemstack cannot be combined") + } + + if decl.Body != nil { + if pragma&ir.Noescape != 0 { + w.p.errorf(decl, "can only use //go:noescape with external func implementations") + } + } else { + if base.Flag.Complete || decl.Name.Value == "init" { + // Linknamed functions are allowed to have no body. Hopefully + // the linkname target has a body. See issue 23311. + if _, ok := w.p.linknames[obj]; !ok { + w.p.errorf(decl, "missing function body") + } + } + } + + w.sync(syncFuncExt) + w.pragmaFlag(pragma) + w.linkname(obj) + w.bool(false) // stub extension + w.addBody(obj.Type().(*types2.Signature), decl.Body, make(map[types2.Object]int)) + w.sync(syncEOF) +} + +func (w *writer) typeExt(obj *types2.TypeName) { + decl, ok := w.p.typDecls[obj] + assert(ok) + + w.sync(syncTypeExt) + + w.pragmaFlag(asPragmaFlag(decl.Pragma)) + + // No LSym.SymIdx info yet. + w.int64(-1) + w.int64(-1) +} + +func (w *writer) varExt(obj *types2.Var) { + w.sync(syncVarExt) + w.linkname(obj) +} + +func (w *writer) linkname(obj types2.Object) { + w.sync(syncLinkname) + w.int64(-1) + w.string(w.p.linknames[obj]) +} + +func (w *writer) pragmaFlag(p ir.PragmaFlag) { + w.sync(syncPragma) + w.int(int(p)) +} + +// @@@ Function bodies + +func (w *writer) addBody(sig *types2.Signature, block *syntax.BlockStmt, localsIdx map[types2.Object]int) { + // TODO(mdempsky): Theoretically, I think at this point we want to + // extend the implicit type parameters list with any new explicit + // type parameters. + // + // However, I believe that's moot: declared functions and methods + // have explicit type parameters, but are always declared at package + // scope (which has no implicit type parameters); and function + // literals can appear within a type-parameterized function (i.e., + // implicit type parameters), but cannot have explicit type + // parameters of their own. + // + // So I think it's safe to just use whichever is non-empty. + implicitIdx := w.implicitIdx + if len(implicitIdx) == 0 { + implicitIdx = w.explicitIdx + } else { + assert(len(w.explicitIdx) == 0) + } + + w.sync(syncAddBody) + w.reloc(relocBody, w.p.bodyIdx(w.p.curpkg, sig, block, implicitIdx, localsIdx)) +} + +func (pw *pkgWriter) bodyIdx(pkg *types2.Package, sig *types2.Signature, block *syntax.BlockStmt, implicitIdx map[*types2.TypeParam]int, localsIdx map[types2.Object]int) int { + w := pw.newWriter(relocBody, syncFuncBody) + w.implicitIdx = implicitIdx + w.localsIdx = localsIdx + + w.funcargs(sig) + if w.bool(block != nil) { + w.stmts(block.List) + w.pos(block.Rbrace) + } + + return w.flush() +} + +func (w *writer) funcargs(sig *types2.Signature) { + do := func(params *types2.Tuple, result bool) { + for i := 0; i < params.Len(); i++ { + w.funcarg(params.At(i), result) + } + } + + if recv := sig.Recv(); recv != nil { + w.funcarg(recv, false) + } + do(sig.Params(), false) + do(sig.Results(), true) +} + +func (w *writer) funcarg(param *types2.Var, result bool) { + if param.Name() != "" || result { + w.addLocal(param) + } +} + +func (w *writer) addLocal(obj types2.Object) { + w.sync(syncAddLocal) + idx := len(w.localsIdx) + if debug { + w.int(idx) + } + w.localsIdx[obj] = idx +} + +func (w *writer) useLocal(obj types2.Object) { + w.sync(syncUseObjLocal) + idx, ok := w.localsIdx[obj] + assert(ok) + w.len(idx) +} + +func (w *writer) openScope(pos syntax.Pos) { + w.sync(syncOpenScope) + w.pos(pos) +} + +func (w *writer) closeScope(pos syntax.Pos) { + w.sync(syncCloseScope) + w.pos(pos) + w.closeAnotherScope() +} + +func (w *writer) closeAnotherScope() { + w.sync(syncCloseAnotherScope) +} + +// @@@ Statements + +func (w *writer) stmt(stmt syntax.Stmt) { + var stmts []syntax.Stmt + if stmt != nil { + stmts = []syntax.Stmt{stmt} + } + w.stmts(stmts) +} + +func (w *writer) stmts(stmts []syntax.Stmt) { + w.sync(syncStmts) + for _, stmt := range stmts { + w.stmt1(stmt) + } + w.code(stmtEnd) + w.sync(syncStmtsEnd) +} + +func (w *writer) stmt1(stmt syntax.Stmt) { + switch stmt := stmt.(type) { + default: + w.p.unexpected("statement", stmt) + + case nil, *syntax.EmptyStmt: + return + + case *syntax.AssignStmt: + switch { + case stmt.Rhs == nil: + w.code(stmtIncDec) + w.op(binOps[stmt.Op]) + w.expr(stmt.Lhs) + w.pos(stmt) + + case stmt.Op != 0 && stmt.Op != syntax.Def: + w.code(stmtAssignOp) + w.op(binOps[stmt.Op]) + w.expr(stmt.Lhs) + w.pos(stmt) + w.expr(stmt.Rhs) + + default: + w.code(stmtAssign) + w.pos(stmt) + w.assignList(stmt.Lhs) + w.exprList(stmt.Rhs) + } + + case *syntax.BlockStmt: + w.code(stmtBlock) + w.blockStmt(stmt) + + case *syntax.BranchStmt: + w.code(stmtBranch) + w.pos(stmt) + w.op(branchOps[stmt.Tok]) + w.optLabel(stmt.Label) + + case *syntax.CallStmt: + w.code(stmtCall) + w.pos(stmt) + w.op(callOps[stmt.Tok]) + w.expr(stmt.Call) + + case *syntax.DeclStmt: + for _, decl := range stmt.DeclList { + w.declStmt(decl) + } + + case *syntax.ExprStmt: + w.code(stmtExpr) + w.expr(stmt.X) + + case *syntax.ForStmt: + w.code(stmtFor) + w.forStmt(stmt) + + case *syntax.IfStmt: + w.code(stmtIf) + w.ifStmt(stmt) + + case *syntax.LabeledStmt: + w.code(stmtLabel) + w.pos(stmt) + w.label(stmt.Label) + w.stmt1(stmt.Stmt) + + case *syntax.ReturnStmt: + w.code(stmtReturn) + w.pos(stmt) + w.exprList(stmt.Results) + + case *syntax.SelectStmt: + w.code(stmtSelect) + w.selectStmt(stmt) + + case *syntax.SendStmt: + w.code(stmtSend) + w.pos(stmt) + w.expr(stmt.Chan) + w.expr(stmt.Value) + + case *syntax.SwitchStmt: + w.code(stmtSwitch) + w.switchStmt(stmt) + } +} + +func (w *writer) assignList(expr syntax.Expr) { + exprs := unpackListExpr(expr) + w.len(len(exprs)) + + for _, expr := range exprs { + if name, ok := expr.(*syntax.Name); ok && name.Value != "_" { + if obj, ok := w.p.info.Defs[name]; ok { + w.bool(true) + w.pos(obj) + w.localIdent(obj) + w.typ(obj.Type()) + + // TODO(mdempsky): Minimize locals index size by deferring + // this until the variables actually come into scope. + w.addLocal(obj) + continue + } + } + + w.bool(false) + w.expr(expr) + } +} + +func (w *writer) declStmt(decl syntax.Decl) { + switch decl := decl.(type) { + default: + w.p.unexpected("declaration", decl) + + case *syntax.ConstDecl: + + case *syntax.TypeDecl: + // Quirk: The legacy inliner doesn't support inlining functions + // with type declarations. Unified IR doesn't have any need to + // write out type declarations explicitly (they're always looked + // up via global index tables instead), so we just write out a + // marker so the reader knows to synthesize a fake declaration to + // prevent inlining. + if quirksMode() { + w.code(stmtTypeDeclHack) + } + + case *syntax.VarDecl: + values := unpackListExpr(decl.Values) + + // Quirk: When N variables are declared with N initialization + // values, we need to decompose that into N interleaved + // declarations+initializations, because it leads to different + // (albeit semantically equivalent) code generation. + if quirksMode() && len(decl.NameList) == len(values) { + for i, name := range decl.NameList { + w.code(stmtAssign) + w.pos(decl) + w.assignList(name) + w.exprList(values[i]) + } + break + } + + w.code(stmtAssign) + w.pos(decl) + w.assignList(namesAsExpr(decl.NameList)) + w.exprList(decl.Values) + } +} + +func (w *writer) blockStmt(stmt *syntax.BlockStmt) { + w.sync(syncBlockStmt) + w.openScope(stmt.Pos()) + w.stmts(stmt.List) + w.closeScope(stmt.Rbrace) +} + +func (w *writer) forStmt(stmt *syntax.ForStmt) { + w.sync(syncForStmt) + w.openScope(stmt.Pos()) + + if rang, ok := stmt.Init.(*syntax.RangeClause); w.bool(ok) { + w.pos(rang) + w.assignList(rang.Lhs) + w.expr(rang.X) + } else { + w.pos(stmt) + w.stmt(stmt.Init) + w.expr(stmt.Cond) + w.stmt(stmt.Post) + } + + w.blockStmt(stmt.Body) + w.closeAnotherScope() +} + +func (w *writer) ifStmt(stmt *syntax.IfStmt) { + w.sync(syncIfStmt) + w.openScope(stmt.Pos()) + w.pos(stmt) + w.stmt(stmt.Init) + w.expr(stmt.Cond) + w.blockStmt(stmt.Then) + w.stmt(stmt.Else) + w.closeAnotherScope() +} + +func (w *writer) selectStmt(stmt *syntax.SelectStmt) { + w.sync(syncSelectStmt) + + w.pos(stmt) + w.len(len(stmt.Body)) + for i, clause := range stmt.Body { + if i > 0 { + w.closeScope(clause.Pos()) + } + w.openScope(clause.Pos()) + + w.pos(clause) + w.stmt(clause.Comm) + w.stmts(clause.Body) + } + if len(stmt.Body) > 0 { + w.closeScope(stmt.Rbrace) + } +} + +func (w *writer) switchStmt(stmt *syntax.SwitchStmt) { + w.sync(syncSwitchStmt) + + w.openScope(stmt.Pos()) + w.pos(stmt) + w.stmt(stmt.Init) + w.expr(stmt.Tag) + + w.len(len(stmt.Body)) + for i, clause := range stmt.Body { + if i > 0 { + w.closeScope(clause.Pos()) + } + w.openScope(clause.Pos()) + + w.pos(clause) + w.exprList(clause.Cases) + + if obj, ok := w.p.info.Implicits[clause]; ok { + // TODO(mdempsky): These pos details are quirkish, but also + // necessary so the variable's position is correct for DWARF + // scope assignment later. It would probably be better for us to + // instead just set the variable's DWARF scoping info earlier so + // we can give it the correct position information. + pos := clause.Pos() + if typs := unpackListExpr(clause.Cases); len(typs) != 0 { + pos = typeExprEndPos(typs[len(typs)-1]) + } + w.pos(pos) + + obj := obj.(*types2.Var) + w.typ(obj.Type()) + w.addLocal(obj) + } + + w.stmts(clause.Body) + } + if len(stmt.Body) > 0 { + w.closeScope(stmt.Rbrace) + } + + w.closeScope(stmt.Rbrace) +} + +func (w *writer) label(label *syntax.Name) { + w.sync(syncLabel) + + // TODO(mdempsky): Replace label strings with dense indices. + w.string(label.Value) +} + +func (w *writer) optLabel(label *syntax.Name) { + w.sync(syncOptLabel) + if w.bool(label != nil) { + w.label(label) + } +} + +// @@@ Expressions + +func (w *writer) expr(expr syntax.Expr) { + expr = unparen(expr) // skip parens; unneeded after typecheck + + obj, targs := lookupObj(w.p.info, expr) + + if tv, ok := w.p.info.Types[expr]; ok { + if tv.IsType() { + w.code(exprType) + w.typ(tv.Type) + return + } + + if tv.Value != nil { + pos := expr.Pos() + if quirksMode() { + if obj != nil { + // Quirk: IR (and thus iexport) doesn't track position + // information for uses of declared objects. + pos = syntax.Pos{} + } else if tv.Value.Kind() == constant.String { + // Quirk: noder.sum picks a particular position for certain + // string concatenations. + pos = sumPos(expr) + } + } + + w.code(exprConst) + w.pos(pos) + w.value(tv.Type, tv.Value) + + // TODO(mdempsky): These details are only important for backend + // diagnostics. Explore writing them out separately. + w.op(constExprOp(expr)) + w.string(syntax.String(expr)) + return + } + } + + if obj != nil { + if _, ok := w.localsIdx[obj]; ok { + assert(len(targs) == 0) + w.code(exprLocal) + w.useLocal(obj) + return + } + + w.code(exprName) + w.obj(obj, targs) + return + } + + switch expr := expr.(type) { + default: + w.p.unexpected("expression", expr) + + case nil: // absent slice index, for condition, or switch tag + w.code(exprNone) + + case *syntax.Name: + assert(expr.Value == "_") + w.code(exprBlank) + + case *syntax.CompositeLit: + w.code(exprCompLit) + w.compLit(expr) + + case *syntax.FuncLit: + w.code(exprFuncLit) + w.funcLit(expr) + + case *syntax.SelectorExpr: + sel, ok := w.p.info.Selections[expr] + assert(ok) + + w.code(exprSelector) + w.expr(expr.X) + w.pos(expr) + w.selector(sel.Obj()) + + case *syntax.IndexExpr: + tv, ok := w.p.info.Types[expr.Index] + assert(ok && tv.IsValue()) + + w.code(exprIndex) + w.expr(expr.X) + w.pos(expr) + w.expr(expr.Index) + + case *syntax.SliceExpr: + w.code(exprSlice) + w.expr(expr.X) + w.pos(expr) + for _, n := range &expr.Index { + w.expr(n) + } + + case *syntax.AssertExpr: + w.code(exprAssert) + w.expr(expr.X) + w.pos(expr) + w.expr(expr.Type) + + case *syntax.Operation: + if expr.Y == nil { + w.code(exprUnaryOp) + w.op(unOps[expr.Op]) + w.pos(expr) + w.expr(expr.X) + break + } + + w.code(exprBinaryOp) + w.op(binOps[expr.Op]) + w.expr(expr.X) + w.pos(expr) + w.expr(expr.Y) + + case *syntax.CallExpr: + w.code(exprCall) + + if inf, ok := w.p.info.Inferred[expr]; ok { + obj, _ := lookupObj(w.p.info, expr.Fun) + assert(obj != nil) + + // As if w.expr(expr.Fun), but using inf.TArgs instead. + w.code(exprName) + w.obj(obj, inf.TArgs) + } else { + w.expr(expr.Fun) + } + + w.pos(expr) + w.exprs(expr.ArgList) + w.bool(expr.HasDots) + + case *syntax.TypeSwitchGuard: + w.code(exprTypeSwitchGuard) + w.pos(expr) + if tag := expr.Lhs; w.bool(tag != nil) { + w.pos(tag) + w.string(tag.Value) + } + w.expr(expr.X) + } +} + +func (w *writer) compLit(lit *syntax.CompositeLit) { + tv, ok := w.p.info.Types[lit] + assert(ok) + + w.sync(syncCompLit) + w.pos(lit) + w.typ(tv.Type) + + typ := tv.Type + if ptr, ok := typ.Underlying().(*types2.Pointer); ok { + typ = ptr.Elem() + } + str, isStruct := typ.Underlying().(*types2.Struct) + + w.len(len(lit.ElemList)) + for i, elem := range lit.ElemList { + if isStruct { + if kv, ok := elem.(*syntax.KeyValueExpr); ok { + // use position of expr.Key rather than of elem (which has position of ':') + w.pos(kv.Key) + w.len(fieldIndex(w.p.info, str, kv.Key.(*syntax.Name))) + elem = kv.Value + } else { + w.pos(elem) + w.len(i) + } + } else { + if kv, ok := elem.(*syntax.KeyValueExpr); w.bool(ok) { + // use position of expr.Key rather than of elem (which has position of ':') + w.pos(kv.Key) + w.expr(kv.Key) + elem = kv.Value + } + } + w.pos(elem) + w.expr(elem) + } +} + +func (w *writer) funcLit(expr *syntax.FuncLit) { + tv, ok := w.p.info.Types[expr] + assert(ok) + sig := tv.Type.(*types2.Signature) + + w.sync(syncFuncLit) + w.pos(expr) + w.pos(expr.Type) // for QuirksMode + w.signature(sig) + + closureVars, localsIdx := w.captureVars(expr) + w.len(len(closureVars)) + for _, closureVar := range closureVars { + w.pos(closureVar.pos) + w.useLocal(closureVar.obj) + } + + w.addBody(sig, expr.Body, localsIdx) +} + +type posObj struct { + pos syntax.Pos + obj types2.Object +} + +// captureVars returns the free variables used by the given function +// literal. +func (w *writer) captureVars(expr *syntax.FuncLit) (closureVars []posObj, localsIdx map[types2.Object]int) { + scope, ok := w.p.info.Scopes[expr.Type] + assert(ok) + + localsIdx = make(map[types2.Object]int) + + // TODO(mdempsky): This code needs to be cleaned up (e.g., to avoid + // traversing nested function literals multiple times). This will be + // easier after we drop quirks mode. + + var rbracePos syntax.Pos + + var visitor func(n syntax.Node) bool + visitor = func(n syntax.Node) bool { + + // Constant expressions don't count towards capturing. + if n, ok := n.(syntax.Expr); ok { + if tv, ok := w.p.info.Types[n]; ok && tv.Value != nil { + return true + } + } + + switch n := n.(type) { + case *syntax.Name: + if obj, ok := w.p.info.Uses[n].(*types2.Var); ok && !obj.IsField() && obj.Pkg() == w.p.curpkg && obj.Parent() != obj.Pkg().Scope() { + // Found a local variable. See if it chains up to scope. + parent := obj.Parent() + for { + if parent == scope { + break + } + if parent == obj.Pkg().Scope() { + if _, present := localsIdx[obj]; !present { + pos := rbracePos + if pos == (syntax.Pos{}) { + pos = n.Pos() + } + + idx := len(closureVars) + closureVars = append(closureVars, posObj{pos, obj}) + localsIdx[obj] = idx + } + break + } + parent = parent.Parent() + } + } + + case *syntax.FuncLit: + // Quirk: typecheck uses the rbrace position position of the + // function literal as the position of the intermediary capture. + if quirksMode() && rbracePos == (syntax.Pos{}) { + rbracePos = n.Body.Rbrace + syntax.Walk(n.Body, visitor) + rbracePos = syntax.Pos{} + return true + } + + case *syntax.AssignStmt: + // Quirk: typecheck visits (and thus captures) the RHS of + // assignment statements before the LHS. + if quirksMode() && (n.Op == 0 || n.Op == syntax.Def) { + syntax.Walk(n.Rhs, visitor) + syntax.Walk(n.Lhs, visitor) + return true + } + case *syntax.RangeClause: + // Quirk: Similarly, it visits the expression to be iterated + // over before the iteration variables. + if quirksMode() { + syntax.Walk(n.X, visitor) + if n.Lhs != nil { + syntax.Walk(n.Lhs, visitor) + } + return true + } + } + + return false + } + syntax.Walk(expr.Body, visitor) + + return +} + +func (w *writer) exprList(expr syntax.Expr) { + w.sync(syncExprList) + w.exprs(unpackListExpr(expr)) +} + +func (w *writer) exprs(exprs []syntax.Expr) { + if len(exprs) == 0 { + assert(exprs == nil) + } + + w.sync(syncExprs) + w.len(len(exprs)) + for _, expr := range exprs { + w.expr(expr) + } +} + +func (w *writer) op(op ir.Op) { + // TODO(mdempsky): Remove in favor of explicit codes? Would make + // export data more stable against internal refactorings, but low + // priority at the moment. + assert(op != 0) + w.sync(syncOp) + w.len(int(op)) +} + +// @@@ Package initialization + +// Caution: This code is still clumsy, because toolstash -cmp is +// particularly sensitive to it. + +type typeDeclGen struct { + *syntax.TypeDecl + gen int +} + +func (pw *pkgWriter) collectDecls(noders []*noder) { + var typegen int + + for _, p := range noders { + var importedEmbed, importedUnsafe bool + + syntax.Walk(p.file, func(n syntax.Node) bool { + switch n := n.(type) { + case *syntax.File: + pw.checkPragmas(n.Pragma, ir.GoBuildPragma, false) + + case *syntax.ImportDecl: + pw.checkPragmas(n.Pragma, 0, false) + + switch pkgNameOf(pw.info, n).Imported().Path() { + case "embed": + importedEmbed = true + case "unsafe": + importedUnsafe = true + } + + case *syntax.ConstDecl: + pw.checkPragmas(n.Pragma, 0, false) + + case *syntax.FuncDecl: + pw.checkPragmas(n.Pragma, funcPragmas, false) + + obj := pw.info.Defs[n.Name].(*types2.Func) + pw.funDecls[obj] = n + + case *syntax.TypeDecl: + obj := pw.info.Defs[n.Name].(*types2.TypeName) + d := typeDeclGen{TypeDecl: n} + + if n.Alias { + pw.checkPragmas(n.Pragma, 0, false) + } else { + pw.checkPragmas(n.Pragma, typePragmas, false) + + // Assign a unique ID to function-scoped defined types. + if !isGlobal(obj) { + typegen++ + d.gen = typegen + } + } + + pw.typDecls[obj] = d + + case *syntax.VarDecl: + pw.checkPragmas(n.Pragma, 0, true) + + if p, ok := n.Pragma.(*pragmas); ok && len(p.Embeds) > 0 { + obj := pw.info.Defs[n.NameList[0]].(*types2.Var) + // TODO(mdempsky): isGlobal(obj) gives false positive errors + // for //go:embed directives on package-scope blank + // variables. + if err := checkEmbed(n, importedEmbed, !isGlobal(obj)); err != nil { + pw.errorf(p.Embeds[0].Pos, "%s", err) + } + } + + // Workaround for #46208. For variable declarations that + // declare multiple variables and have an explicit type + // expression, the type expression is evaluated multiple + // times. This affects toolstash -cmp, because iexport is + // sensitive to *types.Type pointer identity. + if quirksMode() && n.Type != nil { + tv, ok := pw.info.Types[n.Type] + assert(ok) + assert(tv.IsType()) + for _, name := range n.NameList { + obj := pw.info.Defs[name].(*types2.Var) + pw.dups.add(obj.Type(), tv.Type) + } + } + } + return false + }) + + pw.cgoPragmas = append(pw.cgoPragmas, p.pragcgobuf...) + + for _, l := range p.linknames { + if !importedUnsafe { + pw.errorf(l.pos, "//go:linkname only allowed in Go files that import \"unsafe\"") + continue + } + + switch obj := pw.curpkg.Scope().Lookup(l.local).(type) { + case *types2.Func, *types2.Var: + if _, ok := pw.linknames[obj]; !ok { + pw.linknames[obj] = l.remote + } else { + pw.errorf(l.pos, "duplicate //go:linkname for %s", l.local) + } + + default: + // TODO(mdempsky): Enable after #42938 is fixed. + if false { + pw.errorf(l.pos, "//go:linkname must refer to declared function or variable") + } + } + } + } +} + +func (pw *pkgWriter) checkPragmas(p syntax.Pragma, allowed ir.PragmaFlag, embedOK bool) { + if p == nil { + return + } + pragma := p.(*pragmas) + + for _, pos := range pragma.Pos { + if pos.Flag&^allowed != 0 { + pw.errorf(pos.Pos, "misplaced compiler directive") + } + } + + if !embedOK { + for _, e := range pragma.Embeds { + pw.errorf(e.Pos, "misplaced go:embed directive") + } + } +} + +func (w *writer) pkgInit(noders []*noder) { + if quirksMode() { + posBases := posBasesOf(noders) + w.len(len(posBases)) + for _, posBase := range posBases { + w.posBase(posBase) + } + + objs := importedObjsOf(w.p.curpkg, w.p.info, noders) + w.len(len(objs)) + for _, obj := range objs { + w.qualifiedIdent(obj) + } + } + + w.len(len(w.p.cgoPragmas)) + for _, cgoPragma := range w.p.cgoPragmas { + w.strings(cgoPragma) + } + + w.sync(syncDecls) + for _, p := range noders { + for _, decl := range p.file.DeclList { + w.pkgDecl(decl) + } + } + w.code(declEnd) + + w.sync(syncEOF) +} + +func (w *writer) pkgDecl(decl syntax.Decl) { + switch decl := decl.(type) { + default: + w.p.unexpected("declaration", decl) + + case *syntax.ImportDecl: + + case *syntax.ConstDecl: + w.code(declOther) + w.pkgObjs(decl.NameList...) + + case *syntax.FuncDecl: + obj := w.p.info.Defs[decl.Name].(*types2.Func) + sig := obj.Type().(*types2.Signature) + + if sig.RParams() != nil || sig.TParams() != nil { + break // skip generic functions + } + + if recv := sig.Recv(); recv != nil && obj.Name() != "_" { + w.code(declMethod) + w.typ(recvBase(recv)) + w.selector(obj) + break + } + + w.code(declFunc) + w.pkgObjs(decl.Name) + + case *syntax.TypeDecl: + if len(decl.TParamList) != 0 { + break // skip generic type decls + } + + name := w.p.info.Defs[decl.Name].(*types2.TypeName) + + // Skip type declarations for interfaces that are only usable as + // type parameter bounds. + if iface, ok := name.Type().Underlying().(*types2.Interface); ok && iface.IsConstraint() { + break + } + + // Skip aliases to uninstantiated generic types. + // TODO(mdempsky): Revisit after #46477 is resolved. + if name.IsAlias() { + named, ok := name.Type().(*types2.Named) + if ok && len(named.TParams()) != 0 && len(named.TArgs()) == 0 { + break + } + } + + w.code(declOther) + w.pkgObjs(decl.Name) + + case *syntax.VarDecl: + w.code(declVar) + w.pos(decl) + w.pkgObjs(decl.NameList...) + w.exprList(decl.Values) + + var embeds []pragmaEmbed + if p, ok := decl.Pragma.(*pragmas); ok { + embeds = p.Embeds + } + w.len(len(embeds)) + for _, embed := range embeds { + w.pos(embed.Pos) + w.strings(embed.Patterns) + } + } +} + +func (w *writer) pkgObjs(names ...*syntax.Name) { + w.sync(syncDeclNames) + w.len(len(names)) + + for _, name := range names { + obj, ok := w.p.info.Defs[name] + assert(ok) + + w.sync(syncDeclName) + w.obj(obj, nil) + } +} + +// @@@ Helpers + +// isDefinedType reports whether obj is a defined type. +func isDefinedType(obj types2.Object) bool { + if obj, ok := obj.(*types2.TypeName); ok { + return !obj.IsAlias() + } + return false +} + +// isGlobal reports whether obj was declared at package scope. +// +// Caveat: blank objects are not declared. +func isGlobal(obj types2.Object) bool { + return obj.Parent() == obj.Pkg().Scope() +} + +// lookupObj returns the object that expr refers to, if any. If expr +// is an explicit instantiation of a generic object, then the type +// arguments are returned as well. +func lookupObj(info *types2.Info, expr syntax.Expr) (obj types2.Object, targs []types2.Type) { + if index, ok := expr.(*syntax.IndexExpr); ok { + if inf, ok := info.Inferred[index]; ok { + targs = inf.TArgs + } else { + args := unpackListExpr(index.Index) + + if len(args) == 1 { + tv, ok := info.Types[args[0]] + assert(ok) + if tv.IsValue() { + return // normal index expression + } + } + + targs = make([]types2.Type, len(args)) + for i, arg := range args { + tv, ok := info.Types[arg] + assert(ok) + assert(tv.IsType()) + targs[i] = tv.Type + } + } + + expr = index.X + } + + // Strip package qualifier, if present. + if sel, ok := expr.(*syntax.SelectorExpr); ok { + if !isPkgQual(info, sel) { + return // normal selector expression + } + expr = sel.Sel + } + + if name, ok := expr.(*syntax.Name); ok { + obj, _ = info.Uses[name] + } + return +} + +// isPkgQual reports whether the given selector expression is a +// package-qualified identifier. +func isPkgQual(info *types2.Info, sel *syntax.SelectorExpr) bool { + if name, ok := sel.X.(*syntax.Name); ok { + _, isPkgName := info.Uses[name].(*types2.PkgName) + return isPkgName + } + return false +} + +// recvBase returns the base type for the given receiver parameter. +func recvBase(recv *types2.Var) *types2.Named { + typ := recv.Type() + if ptr, ok := typ.(*types2.Pointer); ok { + typ = ptr.Elem() + } + return typ.(*types2.Named) +} + +// namesAsExpr returns a list of names as a syntax.Expr. +func namesAsExpr(names []*syntax.Name) syntax.Expr { + if len(names) == 1 { + return names[0] + } + + exprs := make([]syntax.Expr, len(names)) + for i, name := range names { + exprs[i] = name + } + return &syntax.ListExpr{ElemList: exprs} +} + +// fieldIndex returns the index of the struct field named by key. +func fieldIndex(info *types2.Info, str *types2.Struct, key *syntax.Name) int { + field := info.Uses[key].(*types2.Var) + + for i := 0; i < str.NumFields(); i++ { + if str.Field(i) == field { + return i + } + } + + panic(fmt.Sprintf("%s: %v is not a field of %v", key.Pos(), field, str)) +} + +// objTypeParams returns the type parameters on the given object. +func objTypeParams(obj types2.Object) []*types2.TypeName { + switch obj := obj.(type) { + case *types2.Func: + return obj.Type().(*types2.Signature).TParams() + case *types2.TypeName: + if !obj.IsAlias() { + return obj.Type().(*types2.Named).TParams() + } + } + return nil +} + +func asPragmaFlag(p syntax.Pragma) ir.PragmaFlag { + if p == nil { + return 0 + } + return p.(*pragmas).Flag +} -- GitLab From cf1ae5fc364eb7f2ee5203e4c5e30411c3cfe01f Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 11 Jun 2021 03:54:25 -0700 Subject: [PATCH 0274/2500] [dev.typeparams] cmd/compile: add -d=unified flag to enable unified IR This CL adds a new -d=unified debug flag, which controls whether unified IR mode is used. Change-Id: Iaa5f3cc0a24b9881aeec5317cd6b462b4a7b6fc9 Reviewed-on: https://go-review.googlesource.com/c/go/+/327054 Trust: Matthew Dempsky Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/base/debug.go | 1 + src/cmd/compile/internal/noder/noder.go | 5 +++++ src/cmd/compile/internal/reflectdata/reflect.go | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/src/cmd/compile/internal/base/debug.go b/src/cmd/compile/internal/base/debug.go index 71712ab1a5..824a8baa83 100644 --- a/src/cmd/compile/internal/base/debug.go +++ b/src/cmd/compile/internal/base/debug.go @@ -46,6 +46,7 @@ type DebugFlags struct { SoftFloat int `help:"force compiler to emit soft-float code"` TypeAssert int `help:"print information about type assertion inlining"` TypecheckInl int `help:"eager typechecking of inline function bodies"` + Unified int `help:"enable unified IR construction"` WB int `help:"print information about write barriers"` ABIWrap int `help:"print information about ABI wrapper generation"` diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index d417edcbd5..c7970396f8 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -76,6 +76,11 @@ func LoadPackage(filenames []string) { } base.Timer.AddEvent(int64(lines), "lines") + if base.Debug.Unified != 0 { + useUnifiedIR(noders) + return + } + if base.Flag.G != 0 { // Use types2 to type-check and possibly generate IR. check2(noders) diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index f16034ea70..5516f707fa 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -1780,6 +1780,10 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy // TODO: check that we do the right thing when rcvr.IsInterface(). generic = true } + if base.Debug.Unified != 0 { + // TODO(mdempsky): Support dictionaries for unified IR. + generic = false + } newnam := ir.MethodSym(rcvr, method.Sym) lsym := newnam.Linksym() if newnam.Siggen() { -- GitLab From ee0420d3b56982cb1600dc141dfd4be155adddfe Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 16 Jun 2021 10:29:21 +0700 Subject: [PATCH 0275/2500] [dev.typeparams] cmd/compile: factor out implicit/explicit handling The logic for handling them must keep in sync between reader/writer, so factoring them out from addBody make it's easier to refer later. Change-Id: I26447065867d79f4f47cc678a398b9e7bf5d2403 Reviewed-on: https://go-review.googlesource.com/c/go/+/328051 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/noder/reader.go | 15 +++++++++++---- src/cmd/compile/internal/noder/sync.go | 1 + src/cmd/compile/internal/noder/writer.go | 11 +++++++++-- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 18ecbff3cc..803acaa88d 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -789,18 +789,25 @@ var bodyReader = map[*ir.Func]pkgReaderIndex{} // constructed. var todoBodies []*ir.Func -func (r *reader) addBody(fn *ir.Func) { - r.sync(syncAddBody) +// Keep in sync with writer.implicitTypes +// Also see comment there for why r.implicits and r.explicits should +// never both be non-empty. +func (r *reader) implicitTypes() []*types.Type { + r.sync(syncImplicitTypes) - // See commont in writer.addBody for why r.implicits and r.explicits - // should never both be non-empty. implicits := r.implicits if len(implicits) == 0 { implicits = r.explicits } else { assert(len(r.explicits) == 0) } + return implicits +} + +func (r *reader) addBody(fn *ir.Func) { + r.sync(syncAddBody) + implicits := r.implicitTypes() pri := pkgReaderIndex{r.p, r.reloc(relocBody), implicits} bodyReader[fn] = pri diff --git a/src/cmd/compile/internal/noder/sync.go b/src/cmd/compile/internal/noder/sync.go index d77a784479..7326a6edbe 100644 --- a/src/cmd/compile/internal/noder/sync.go +++ b/src/cmd/compile/internal/noder/sync.go @@ -151,4 +151,5 @@ const ( syncLocalIdent syncTypeParamNames syncTypeParamBounds + syncImplicitTypes ) diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index b39dd8651b..1475540d84 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -665,7 +665,9 @@ func (w *writer) pragmaFlag(p ir.PragmaFlag) { // @@@ Function bodies -func (w *writer) addBody(sig *types2.Signature, block *syntax.BlockStmt, localsIdx map[types2.Object]int) { +func (w *writer) implicitTypes() map[*types2.TypeParam]int { + w.sync(syncImplicitTypes) + // TODO(mdempsky): Theoretically, I think at this point we want to // extend the implicit type parameters list with any new explicit // type parameters. @@ -684,9 +686,14 @@ func (w *writer) addBody(sig *types2.Signature, block *syntax.BlockStmt, localsI } else { assert(len(w.explicitIdx) == 0) } + return implicitIdx +} +func (w *writer) addBody(sig *types2.Signature, block *syntax.BlockStmt, localsIdx map[types2.Object]int) { w.sync(syncAddBody) - w.reloc(relocBody, w.p.bodyIdx(w.p.curpkg, sig, block, implicitIdx, localsIdx)) + + implicits := w.implicitTypes() + w.reloc(relocBody, w.p.bodyIdx(w.p.curpkg, sig, block, implicits, localsIdx)) } func (pw *pkgWriter) bodyIdx(pkg *types2.Package, sig *types2.Signature, block *syntax.BlockStmt, implicitIdx map[*types2.TypeParam]int, localsIdx map[types2.Object]int) int { -- GitLab From a4121d7dd66b0bca91cc1619721f69e9027af041 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Mon, 14 Jun 2021 12:39:14 -0400 Subject: [PATCH 0276/2500] [dev.typeparams] Revert "[dev.typeparams] runtime: make deferproc take a func() argument" Temprary revert CL 325918. Delve relies on the _defer.fn.fn field to get defer frames. CL 325918 changes the type of _defer.fn to func(), which no longer has an fn field. Change-Id: If6c71b15a27bac579593f5273c9a49715e6e35b2 Reviewed-on: https://go-review.googlesource.com/c/go/+/327775 Trust: Cherry Mui Trust: Dan Scales Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/runtime/heapdump.go | 7 +++---- src/runtime/panic.go | 25 +++++++++++++++++-------- src/runtime/runtime2.go | 8 ++++---- src/runtime/stubs.go | 2 +- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/runtime/heapdump.go b/src/runtime/heapdump.go index 47e4b6b0d1..934e55f495 100644 --- a/src/runtime/heapdump.go +++ b/src/runtime/heapdump.go @@ -381,13 +381,12 @@ func dumpgoroutine(gp *g) { dumpint(uint64(uintptr(unsafe.Pointer(gp)))) dumpint(uint64(d.sp)) dumpint(uint64(d.pc)) - fn := *(**funcval)(unsafe.Pointer(&d.fn)) - dumpint(uint64(uintptr(unsafe.Pointer(fn)))) - if fn == nil { + dumpint(uint64(uintptr(unsafe.Pointer(d.fn)))) + if d.fn == nil { // d.fn can be nil for open-coded defers dumpint(uint64(0)) } else { - dumpint(uint64(uintptr(unsafe.Pointer(fn.fn)))) + dumpint(uint64(uintptr(unsafe.Pointer(d.fn.fn)))) } dumpint(uint64(uintptr(unsafe.Pointer(d.link)))) } diff --git a/src/runtime/panic.go b/src/runtime/panic.go index 86d41c4e1c..04b95e51e5 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -226,7 +226,7 @@ func panicmemAddr(addr uintptr) { // Create a new deferred function fn, which has no arguments and results. // The compiler turns a defer statement into a call to this. -func deferproc(fn func()) { +func deferproc(fn *funcval) { // TODO: Make deferproc just take a func(). gp := getg() if gp.m.curg != gp { // go code on the system stack can't defer @@ -302,6 +302,16 @@ func deferprocStack(d *_defer) { // been set and must not be clobbered. } +// deferFunc returns d's deferred function. This is temporary while we +// support both modes of GOEXPERIMENT=regabidefer. Once we commit to +// that experiment, we should change the type of d.fn. +//go:nosplit +func deferFunc(d *_defer) func() { + var fn func() + *(**funcval)(unsafe.Pointer(&fn)) = d.fn + return fn +} + // Each P holds a pool for defers. // Allocate a Defer, usually using per-P pool. @@ -461,9 +471,7 @@ func deferreturn() { // called with a callback on an LR architecture and jmpdefer is on the // stack, because the stack trace can be incorrect in that case - see // issue #8153). - if fn == nil { - fn() - } + _ = fn.fn jmpdefer(fn, argp) } @@ -527,7 +535,7 @@ func Goexit() { } else { // Save the pc/sp in deferCallSave(), so we can "recover" back to this // loop if necessary. - deferCallSave(&p, d.fn) + deferCallSave(&p, deferFunc(d)) } if p.aborted { // We had a recursive panic in the defer d we started, and @@ -719,12 +727,12 @@ func runOpenDeferFrame(gp *g, d *_defer) bool { if deferBits&(1< Date: Wed, 16 Jun 2021 23:00:23 +0700 Subject: [PATCH 0277/2500] [dev.typeparams] cmd/compile: fix missing sync implicit types CL 328051 introduced new syncImplicitTypes, but forgot to add a sync after syncAddBody in linker.relocFuncExt, cause the compiler crashes when reading in package data. Adding missing w.sync(syncImplicitTypes) call fixes this. While at it, also run go generate to update code generated for syncImplicitTypes, which is also missed in CL 328051. Change-Id: Ic65092f69f8d8e63de15989c7f15b6e5633d8f9e Reviewed-on: https://go-review.googlesource.com/c/go/+/328054 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le Reviewed-by: Matthew Dempsky TryBot-Result: Go Bot --- src/cmd/compile/internal/noder/linker.go | 1 + src/cmd/compile/internal/noder/syncmarker_string.go | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/noder/linker.go b/src/cmd/compile/internal/noder/linker.go index 324902d246..7291138160 100644 --- a/src/cmd/compile/internal/noder/linker.go +++ b/src/cmd/compile/internal/noder/linker.go @@ -210,6 +210,7 @@ func (l *linker) relocFuncExt(w *encoder, name *ir.Name) { pri, ok := bodyReader[name.Func] assert(ok) w.sync(syncAddBody) + w.sync(syncImplicitTypes) w.reloc(relocBody, l.relocIdx(pri.pr, relocBody, pri.idx)) } diff --git a/src/cmd/compile/internal/noder/syncmarker_string.go b/src/cmd/compile/internal/noder/syncmarker_string.go index 3eb88fb911..14747b7c10 100644 --- a/src/cmd/compile/internal/noder/syncmarker_string.go +++ b/src/cmd/compile/internal/noder/syncmarker_string.go @@ -137,11 +137,14 @@ func _() { _ = x[syncCodeObj-127] _ = x[syncPosBase-128] _ = x[syncLocalIdent-129] + _ = x[syncTypeParamNames-130] + _ = x[syncTypeParamBounds-131] + _ = x[syncImplicitTypes-132] } -const _syncMarker_name = "NodeBoolInt64Uint64StringPosPkgSymSelectorKindTypeTypePkgSignatureParamOpObjectExprStmtDeclConstDeclFuncDeclTypeDeclVarDeclPragmaValueEOFMethodFuncBodyUseUseObjObjectIdxTypeIdxBOFEntryOpenScopeCloseScopeGlobalLocalDefineDefLocalUseLocalDefGlobalUseGlobalTypeParamsUseLabelDefLabelFuncLitCommonFuncBodyRefLinksymExtHackSetlinenoNameImportDeclDeclNamesDeclNameExprListExprsWrapnameTypeExprTypeExprOrNilChanDirParamsCloseAnotherScopeSumUnOpBinOpStructTypeInterfaceTypePacknameEmbeddedStmtsStmtsFallStmtFallBlockStmtIfStmtForStmtSwitchStmtRangeStmtCaseClauseCommClauseSelectStmtDeclsLabeledStmtCompLit1234NDefImplicitUseNameUseObjLocalAddLocalBothSignatureSetUnderlyingLinknameStmt1StmtsEndDeclareTopDeclsTopConstDeclTopFuncDeclTopTypeDeclTopVarDeclObject1AddBodyLabelFuncExtMethExtOptLabelScalarStmtDeclsDeclLocalObjLocalObjLocal1DeclareLocalPublicPrivateRelocsRelocUseRelocVarExtPkgDefTypeExtValCodeObjPosBaseLocalIdent" +const _syncMarker_name = "NodeBoolInt64Uint64StringPosPkgSymSelectorKindTypeTypePkgSignatureParamOpObjectExprStmtDeclConstDeclFuncDeclTypeDeclVarDeclPragmaValueEOFMethodFuncBodyUseUseObjObjectIdxTypeIdxBOFEntryOpenScopeCloseScopeGlobalLocalDefineDefLocalUseLocalDefGlobalUseGlobalTypeParamsUseLabelDefLabelFuncLitCommonFuncBodyRefLinksymExtHackSetlinenoNameImportDeclDeclNamesDeclNameExprListExprsWrapnameTypeExprTypeExprOrNilChanDirParamsCloseAnotherScopeSumUnOpBinOpStructTypeInterfaceTypePacknameEmbeddedStmtsStmtsFallStmtFallBlockStmtIfStmtForStmtSwitchStmtRangeStmtCaseClauseCommClauseSelectStmtDeclsLabeledStmtCompLit1234NDefImplicitUseNameUseObjLocalAddLocalBothSignatureSetUnderlyingLinknameStmt1StmtsEndDeclareTopDeclsTopConstDeclTopFuncDeclTopTypeDeclTopVarDeclObject1AddBodyLabelFuncExtMethExtOptLabelScalarStmtDeclsDeclLocalObjLocalObjLocal1DeclareLocalPublicPrivateRelocsRelocUseRelocVarExtPkgDefTypeExtValCodeObjPosBaseLocalIdentTypeParamNamesTypeParamBoundsImplicitTypes" -var _syncMarker_index = [...]uint16{0, 4, 8, 13, 19, 25, 28, 31, 34, 42, 46, 50, 57, 66, 71, 73, 79, 83, 87, 91, 100, 108, 116, 123, 129, 134, 137, 143, 151, 154, 160, 169, 176, 179, 184, 193, 203, 209, 214, 220, 228, 236, 245, 254, 264, 272, 280, 287, 297, 304, 314, 318, 327, 331, 341, 350, 358, 366, 371, 379, 387, 400, 407, 413, 430, 433, 437, 442, 452, 465, 473, 481, 486, 495, 503, 512, 518, 525, 535, 544, 554, 564, 574, 579, 590, 597, 598, 599, 600, 601, 602, 613, 620, 631, 639, 652, 665, 673, 678, 686, 693, 701, 713, 724, 735, 745, 752, 759, 764, 771, 778, 786, 792, 801, 810, 818, 827, 839, 845, 852, 858, 863, 871, 877, 883, 890, 893, 900, 907, 917} +var _syncMarker_index = [...]uint16{0, 4, 8, 13, 19, 25, 28, 31, 34, 42, 46, 50, 57, 66, 71, 73, 79, 83, 87, 91, 100, 108, 116, 123, 129, 134, 137, 143, 151, 154, 160, 169, 176, 179, 184, 193, 203, 209, 214, 220, 228, 236, 245, 254, 264, 272, 280, 287, 297, 304, 314, 318, 327, 331, 341, 350, 358, 366, 371, 379, 387, 400, 407, 413, 430, 433, 437, 442, 452, 465, 473, 481, 486, 495, 503, 512, 518, 525, 535, 544, 554, 564, 574, 579, 590, 597, 598, 599, 600, 601, 602, 613, 620, 631, 639, 652, 665, 673, 678, 686, 693, 701, 713, 724, 735, 745, 752, 759, 764, 771, 778, 786, 792, 801, 810, 818, 827, 839, 845, 852, 858, 863, 871, 877, 883, 890, 893, 900, 907, 917, 931, 946, 959} func (i syncMarker) String() string { i -= 1 -- GitLab From 132ea56d292eac0226eef4bc32d784b0300c3bce Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 14 Jun 2021 19:21:14 -0700 Subject: [PATCH 0278/2500] [dev.typeparams] cmd/compile: fix crawling of embeddable types In reflectdata, we have a hack to only apply inlining for (*T).M wrappers generated around T.M. This was a hack because I didn't understand at the time why other cases were failing. But I understand now: during export, we generally skip exporting the inline bodies for unexported methods (unless they're reachable through some other exported method). But it doesn't take into account that embedding a type requires generating wrappers for promoted methods, including imported, unexported methods. For example: package a type T struct{} func (T) m() {} // previously omitted by exported package b import "./a" type U struct { a.T } // needs U.m -> T.m wrapper This CL adds extra logic to the crawler to recognize that T is an exported type directly reachable by the user, so *all* of its methods need to be re-exported. This finally allows simplifying reflectdata.methodWrapper to always call inline.InlineCalls. Change-Id: I25031d41fd6b6cd69d31c6a864b5329cdb5780e2 Reviewed-on: https://go-review.googlesource.com/c/go/+/327872 Trust: Matthew Dempsky Reviewed-by: Cuong Manh Le --- .../compile/internal/reflectdata/reflect.go | 41 ++++++++----- src/cmd/compile/internal/typecheck/crawler.go | 58 ++++++++++++++++++- 2 files changed, 81 insertions(+), 18 deletions(-) diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 5516f707fa..f4a0619935 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -1795,20 +1795,24 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy return lsym } - // Only generate (*T).M wrappers for T.M in T's own package, except for - // instantiated methods. - if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type && - rcvr.Elem().Sym() != nil && rcvr.Elem().Sym().Pkg != types.LocalPkg && - !rcvr.Elem().IsFullyInstantiated() { - return lsym + // imported reports whether typ is a defined type that was declared + // in an imported package, and therefore must have been compiled in + // that package. + importedType := func(typ *types.Type) bool { + return typ.Sym() != nil && typ.Sym().Pkg != types.LocalPkg && + + // Exception: need wrapper for error.Error (#29304). + // TODO(mdempsky): Put this in package runtime, like we do for + // the type descriptors for predeclared types. + typ != types.ErrorType && + + // Exception: parameterized types may have been instantiated + // with new type arguments, so we don't assume they've been + // compiled before. + !typ.IsFullyInstantiated() } - // Only generate I.M wrappers for I in I's own package - // but keep doing it for error.Error (was issue #29304) - // and methods of instantiated interfaces. - if rcvr.IsInterface() && rcvr != types.ErrorType && - rcvr.Sym() != nil && rcvr.Sym().Pkg != types.LocalPkg && - !rcvr.IsFullyInstantiated() { + if importedType(rcvr) || rcvr.IsPtr() && importedType(rcvr.Elem()) { return lsym } @@ -1922,9 +1926,16 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy ir.CurFunc = fn typecheck.Stmts(fn.Body) - // Inline calls within (*T).M wrappers. This is safe because we only - // generate those wrappers within the same compilation unit as (T).M. - // TODO(mdempsky): Investigate why we can't enable this more generally. + // TODO(mdempsky): Make this unconditional. The exporter now + // includes all of the inline bodies we need, and the "importedType" + // logic above now correctly suppresses compiling out-of-package + // types that we might not have inline bodies for. The only problem + // now is that the extra inlining can now introduce further new + // itabs, and gc.dumpdata's ad hoc compile loop doesn't handle this. + // + // CL 327871 will address this by writing itabs and generating + // wrappers as part of the loop, so we won't have to worry about + // "itabs changed after compile functions loop" errors anymore. if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type && rcvr.Elem().Sym() != nil { inline.InlineCalls(fn) } diff --git a/src/cmd/compile/internal/typecheck/crawler.go b/src/cmd/compile/internal/typecheck/crawler.go index c78a604a8d..655ac6e465 100644 --- a/src/cmd/compile/internal/typecheck/crawler.go +++ b/src/cmd/compile/internal/typecheck/crawler.go @@ -15,14 +15,18 @@ import ( // callable by importers are marked with ExportInline so that // iexport.go knows to re-export their inline body. func crawlExports(exports []*ir.Name) { - p := crawler{marked: make(map[*types.Type]bool)} + p := crawler{ + marked: make(map[*types.Type]bool), + embedded: make(map[*types.Type]bool), + } for _, n := range exports { p.markObject(n) } } type crawler struct { - marked map[*types.Type]bool // types already seen by markType + marked map[*types.Type]bool // types already seen by markType + embedded map[*types.Type]bool // types already seen by markEmbed } // markObject visits a reachable object. @@ -31,6 +35,12 @@ func (p *crawler) markObject(n *ir.Name) { p.markInlBody(n) } + // If a declared type name is reachable, users can embed it in their + // own types, which makes even its unexported methods reachable. + if n.Op() == ir.OTYPE { + p.markEmbed(n.Type()) + } + p.markType(n.Type()) } @@ -46,7 +56,7 @@ func (p *crawler) markType(t *types.Type) { } p.marked[t] = true - // If this is a named type, mark all of its associated + // If this is a defined type, mark all of its associated // methods. Skip interface types because t.Methods contains // only their unexpanded method set (i.e., exclusive of // interface embeddings), and the switch statement below @@ -107,6 +117,48 @@ func (p *crawler) markType(t *types.Type) { } } +// markEmbed is similar to markType, but handles finding methods that +// need to be re-exported because t can be embedded in user code +// (possibly transitively). +func (p *crawler) markEmbed(t *types.Type) { + if t.IsPtr() { + // Defined pointer type; not allowed to embed anyway. + if t.Sym() != nil { + return + } + t = t.Elem() + } + + if t.IsInstantiatedGeneric() { + // Re-instantiated types don't add anything new, so don't follow them. + return + } + + if p.embedded[t] { + return + } + p.embedded[t] = true + + // If t is a defined type, then re-export all of its methods. Unlike + // in markType, we include even unexported methods here, because we + // still need to generate wrappers for them, even if the user can't + // refer to them directly. + if t.Sym() != nil && t.Kind() != types.TINTER { + for _, m := range t.Methods().Slice() { + p.markObject(m.Nname.(*ir.Name)) + } + } + + // If t is a struct, recursively visit its embedded fields. + if t.IsStruct() { + for _, f := range t.FieldSlice() { + if f.Embedded != 0 { + p.markEmbed(f.Type) + } + } + } +} + // markInlBody marks n's inline body for export and recursively // ensures all called functions are marked too. func (p *crawler) markInlBody(n *ir.Name) { -- GitLab From dd95a4e3dbe1e060b59840efd7311e8d5e82c08c Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 14 Jun 2021 16:26:26 -0700 Subject: [PATCH 0279/2500] [dev.typeparams] cmd/compile: simplify SSA devirtualization This CL implements a few improvements to SSA devirtualization to make it simpler and more general: 1. Change reflectdata.ITabAddr to now immediately generate the wrapper functions and write out the itab symbol data. Previously, these were each handled by separate phases later on. 2. Removes the hack in typecheck where we marked itabs that we expected to need later. Instead, the calls to ITabAddr in walk now handle generating the wrappers. 3. Changes the SSA interface call devirtualization algorithm to just use the itab symbol data (namely, its relocations) to figure out what pointer is available in memory at the given offset. This decouples it somewhat from reflectdata. Change-Id: I8fe06922af8f8a1e7c93f5aff2b60ff59b8e7114 Reviewed-on: https://go-review.googlesource.com/c/go/+/327871 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Matthew Dempsky Reviewed-by: Cherry Mui --- src/cmd/compile/internal/escape/escape.go | 2 +- src/cmd/compile/internal/gc/main.go | 21 +- src/cmd/compile/internal/gc/obj.go | 7 +- .../compile/internal/reflectdata/reflect.go | 196 ++++++------------ src/cmd/compile/internal/ssa/config.go | 6 - src/cmd/compile/internal/ssa/rewrite.go | 36 ++-- src/cmd/compile/internal/ssagen/ssa.go | 4 - src/cmd/compile/internal/typecheck/subr.go | 8 - .../compile/internal/typecheck/typecheck.go | 1 - 9 files changed, 92 insertions(+), 189 deletions(-) diff --git a/src/cmd/compile/internal/escape/escape.go b/src/cmd/compile/internal/escape/escape.go index 842b0f4a7e..e3727bca27 100644 --- a/src/cmd/compile/internal/escape/escape.go +++ b/src/cmd/compile/internal/escape/escape.go @@ -673,7 +673,7 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) { n := n.(*ir.BinaryExpr) // Note: n.X is not needed because it can never point to memory that might escape. e.expr(k, n.Y) - case ir.OIDATA: + case ir.OIDATA, ir.OSPTR: n := n.(*ir.UnaryExpr) e.expr(k, n.X) case ir.OSLICE2ARRPTR: diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index ce50cbb4c2..c0346c0206 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -181,7 +181,6 @@ func Main(archInit func(*ssagen.ArchInfo)) { typecheck.Target = new(ir.Package) - typecheck.NeedITab = func(t, iface *types.Type) { reflectdata.ITabAddr(t, iface) } typecheck.NeedRuntimeType = reflectdata.NeedRuntimeType // TODO(rsc): TypeSym for lock? base.AutogeneratedPos = makePos(src.NewFileBase("", ""), 1, 0) @@ -193,6 +192,11 @@ func Main(archInit func(*ssagen.ArchInfo)) { dwarfgen.RecordPackageName() + // Prepare for backend processing. This must happen before pkginit, + // because it generates itabs for initializing global variables. + typecheck.InitRuntime() + ssagen.InitConfig() + // Build init task. if initTask := pkginit.Task(); initTask != nil { typecheck.Export(initTask) @@ -252,6 +256,11 @@ func Main(archInit func(*ssagen.ArchInfo)) { base.Timer.Start("fe", "escapes") escape.Funcs(typecheck.Target.Decls) + // TODO(mdempsky): This is a hack. We need a proper, global work + // queue for scheduling function compilation so components don't + // need to adjust their behavior depending on when they're called. + reflectdata.AfterGlobalEscapeAnalysis = true + // Collect information for go:nowritebarrierrec // checking. This must happen before transforming closures during Walk // We'll do the final check after write barriers are @@ -260,17 +269,7 @@ func Main(archInit func(*ssagen.ArchInfo)) { ssagen.EnableNoWriteBarrierRecCheck() } - // Prepare for SSA compilation. - // This must be before CompileITabs, because CompileITabs - // can trigger function compilation. - typecheck.InitRuntime() - ssagen.InitConfig() - - // Just before compilation, compile itabs found on - // the right side of OCONVIFACE so that methods - // can be de-virtualized during compilation. ir.CurFunc = nil - reflectdata.CompileITabs() // Compile top level functions. // Don't use range--walk can add functions to Target.Decls. diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go index 8a2ff75583..440f898211 100644 --- a/src/cmd/compile/internal/gc/obj.go +++ b/src/cmd/compile/internal/gc/obj.go @@ -117,7 +117,7 @@ func dumpdata() { addsignats(typecheck.Target.Externs) reflectdata.WriteRuntimeTypes() reflectdata.WriteTabs() - numPTabs, numITabs := reflectdata.CountTabs() + numPTabs := reflectdata.CountPTabs() reflectdata.WriteImportStrings() reflectdata.WriteBasicTypes() dumpembeds() @@ -158,13 +158,10 @@ func dumpdata() { if numExports != len(typecheck.Target.Exports) { base.Fatalf("Target.Exports changed after compile functions loop") } - newNumPTabs, newNumITabs := reflectdata.CountTabs() + newNumPTabs := reflectdata.CountPTabs() if newNumPTabs != numPTabs { base.Fatalf("ptabs changed after compile functions loop") } - if newNumITabs != numITabs { - base.Fatalf("itabs changed after compile functions loop") - } } func dumpLinkerObj(bout *bio.Writer) { diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index f4a0619935..9e070895a0 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -28,23 +28,13 @@ import ( "cmd/internal/src" ) -type itabEntry struct { - t, itype *types.Type - lsym *obj.LSym // symbol of the itab itself - - // symbols of each method in - // the itab, sorted by byte offset; - // filled in by CompileITabs - entries []*obj.LSym -} - type ptabEntry struct { s *types.Sym t *types.Type } -func CountTabs() (numPTabs, numITabs int) { - return len(ptabs), len(itabs) +func CountPTabs() int { + return len(ptabs) } // runtime interface and reflection data structures @@ -56,7 +46,6 @@ var ( gcsymmu sync.Mutex // protects gcsymset and gcsymslice gcsymset = make(map[*types.Type]struct{}) - itabs []itabEntry ptabs []*ir.Name ) @@ -841,16 +830,16 @@ func TypePtr(t *types.Type) *ir.AddrExpr { return typecheck.Expr(typecheck.NodAddr(n)).(*ir.AddrExpr) } -func ITabAddr(t, itype *types.Type) *ir.AddrExpr { - if t == nil || (t.IsPtr() && t.Elem() == nil) || t.IsUntyped() || !itype.IsInterface() || itype.IsEmptyInterface() { - base.Fatalf("ITabAddr(%v, %v)", t, itype) - } - s, existed := ir.Pkgs.Itab.LookupOK(t.ShortString() + "," + itype.ShortString()) +// ITabAddr returns an expression representing a pointer to the itab +// for concrete type typ implementing interface iface. +func ITabAddr(typ, iface *types.Type) *ir.AddrExpr { + s, existed := ir.Pkgs.Itab.LookupOK(typ.ShortString() + "," + iface.ShortString()) + lsym := s.Linksym() + if !existed { - itabs = append(itabs, itabEntry{t: t, itype: itype, lsym: s.Linksym()}) + writeITab(lsym, typ, iface) } - lsym := s.Linksym() n := ir.NewLinksymExpr(base.Pos, lsym, types.Types[types.TUINT8]) return typecheck.Expr(typecheck.NodAddr(n)).(*ir.AddrExpr) } @@ -1223,83 +1212,6 @@ func InterfaceMethodOffset(ityp *types.Type, i int64) int64 { return int64(commonSize()+4*types.PtrSize+uncommonSize(ityp)) + i*8 } -// for each itabEntry, gather the methods on -// the concrete type that implement the interface -func CompileITabs() { - for i := range itabs { - tab := &itabs[i] - methods := genfun(tab.t, tab.itype) - if len(methods) == 0 { - continue - } - tab.entries = methods - } -} - -// for the given concrete type and interface -// type, return the (sorted) set of methods -// on the concrete type that implement the interface -func genfun(t, it *types.Type) []*obj.LSym { - if t == nil || it == nil { - return nil - } - sigs := imethods(it) - methods := methods(t) - out := make([]*obj.LSym, 0, len(sigs)) - // TODO(mdempsky): Short circuit before calling methods(t)? - // See discussion on CL 105039. - if len(sigs) == 0 { - return nil - } - - // both sigs and methods are sorted by name, - // so we can find the intersect in a single pass - for _, m := range methods { - if m.name == sigs[0].name { - out = append(out, m.isym) - sigs = sigs[1:] - if len(sigs) == 0 { - break - } - } - } - - if len(sigs) != 0 { - base.Fatalf("incomplete itab") - } - - return out -} - -// ITabSym uses the information gathered in -// CompileITabs to de-virtualize interface methods. -// Since this is called by the SSA backend, it shouldn't -// generate additional Nodes, Syms, etc. -func ITabSym(it *obj.LSym, offset int64) *obj.LSym { - var syms []*obj.LSym - if it == nil { - return nil - } - - for i := range itabs { - e := &itabs[i] - if e.lsym == it { - syms = e.entries - break - } - } - if syms == nil { - return nil - } - - // keep this arithmetic in sync with *itab layout - methodnum := int((offset - 2*int64(types.PtrSize) - 8) / int64(types.PtrSize)) - if methodnum >= len(syms) { - return nil - } - return syms[methodnum] -} - // NeedRuntimeType ensures that a runtime type descriptor is emitted for t. func NeedRuntimeType(t *types.Type) { if t.HasTParam() { @@ -1346,29 +1258,57 @@ func WriteRuntimeTypes() { } } -func WriteTabs() { - // process itabs - for _, i := range itabs { - // dump empty itab symbol into i.sym - // type itab struct { - // inter *interfacetype - // _type *_type - // hash uint32 - // _ [4]byte - // fun [1]uintptr // variable sized - // } - o := objw.SymPtr(i.lsym, 0, writeType(i.itype), 0) - o = objw.SymPtr(i.lsym, o, writeType(i.t), 0) - o = objw.Uint32(i.lsym, o, types.TypeHash(i.t)) // copy of type hash - o += 4 // skip unused field - for _, fn := range genfun(i.t, i.itype) { - o = objw.SymPtrWeak(i.lsym, o, fn, 0) // method pointer for each method - } - // Nothing writes static itabs, so they are read only. - objw.Global(i.lsym, int32(o), int16(obj.DUPOK|obj.RODATA)) - i.lsym.Set(obj.AttrContentAddressable, true) +// writeITab writes the itab for concrete type typ implementing +// interface iface. +func writeITab(lsym *obj.LSym, typ, iface *types.Type) { + // TODO(mdempsky): Fix methodWrapper, geneq, and genhash (and maybe + // others) to stop clobbering these. + oldpos, oldfn := base.Pos, ir.CurFunc + defer func() { base.Pos, ir.CurFunc = oldpos, oldfn }() + + if typ == nil || (typ.IsPtr() && typ.Elem() == nil) || typ.IsUntyped() || iface == nil || !iface.IsInterface() || iface.IsEmptyInterface() { + base.Fatalf("writeITab(%v, %v)", typ, iface) + } + + sigs := iface.AllMethods().Slice() + entries := make([]*obj.LSym, 0, len(sigs)) + + // both sigs and methods are sorted by name, + // so we can find the intersection in a single pass + for _, m := range methods(typ) { + if m.name == sigs[0].Sym { + entries = append(entries, m.isym) + sigs = sigs[1:] + if len(sigs) == 0 { + break + } + } + } + if len(sigs) != 0 { + base.Fatalf("incomplete itab") + } + + // dump empty itab symbol into i.sym + // type itab struct { + // inter *interfacetype + // _type *_type + // hash uint32 + // _ [4]byte + // fun [1]uintptr // variable sized + // } + o := objw.SymPtr(lsym, 0, writeType(iface), 0) + o = objw.SymPtr(lsym, o, writeType(typ), 0) + o = objw.Uint32(lsym, o, types.TypeHash(typ)) // copy of type hash + o += 4 // skip unused field + for _, fn := range entries { + o = objw.SymPtrWeak(lsym, o, fn, 0) // method pointer for each method } + // Nothing writes static itabs, so they are read only. + objw.Global(lsym, int32(o), int16(obj.DUPOK|obj.RODATA)) + lsym.Set(obj.AttrContentAddressable, true) +} +func WriteTabs() { // process ptabs if types.LocalPkg.Name == "main" && len(ptabs) > 0 { ot := 0 @@ -1926,20 +1866,10 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy ir.CurFunc = fn typecheck.Stmts(fn.Body) - // TODO(mdempsky): Make this unconditional. The exporter now - // includes all of the inline bodies we need, and the "importedType" - // logic above now correctly suppresses compiling out-of-package - // types that we might not have inline bodies for. The only problem - // now is that the extra inlining can now introduce further new - // itabs, and gc.dumpdata's ad hoc compile loop doesn't handle this. - // - // CL 327871 will address this by writing itabs and generating - // wrappers as part of the loop, so we won't have to worry about - // "itabs changed after compile functions loop" errors anymore. - if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type && rcvr.Elem().Sym() != nil { + if AfterGlobalEscapeAnalysis { inline.InlineCalls(fn) + escape.Batch([]*ir.Func{fn}, false) } - escape.Batch([]*ir.Func{fn}, false) ir.CurFunc = nil typecheck.Target.Decls = append(typecheck.Target.Decls, fn) @@ -1947,6 +1877,12 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy return lsym } +// AfterGlobalEscapeAnalysis tracks whether package gc has already +// performed the main, global escape analysis pass. If so, +// methodWrapper takes responsibility for escape analyzing any +// generated wrappers. +var AfterGlobalEscapeAnalysis bool + var ZeroSize int64 // MarkTypeUsedInInterface marks that type t is converted to an interface. diff --git a/src/cmd/compile/internal/ssa/config.go b/src/cmd/compile/internal/ssa/config.go index 61c65f9e54..b08a394368 100644 --- a/src/cmd/compile/internal/ssa/config.go +++ b/src/cmd/compile/internal/ssa/config.go @@ -149,12 +149,6 @@ type Frontend interface { // for the parts of that compound type. SplitSlot(parent *LocalSlot, suffix string, offset int64, t *types.Type) LocalSlot - // DerefItab dereferences an itab function - // entry, given the symbol of the itab and - // the byte offset of the function pointer. - // It may return nil. - DerefItab(sym *obj.LSym, offset int64) *obj.LSym - // Line returns a string describing the given position. Line(src.XPos) string diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index 375c4d5a56..115d563933 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -745,27 +745,21 @@ func uaddOvf(a, b int64) bool { return uint64(a)+uint64(b) < uint64(a) } -// de-virtualize an InterCall -// 'sym' is the symbol for the itab -func devirt(v *Value, aux Aux, sym Sym, offset int64) *AuxCall { - f := v.Block.Func - n, ok := sym.(*obj.LSym) - if !ok { +// loadLSymOffset simulates reading a word at an offset into a +// read-only symbol's runtime memory. If it would read a pointer to +// another symbol, that symbol is returned. Otherwise, it returns nil. +func loadLSymOffset(lsym *obj.LSym, offset int64) *obj.LSym { + if lsym.Type != objabi.SRODATA { return nil } - lsym := f.fe.DerefItab(n, offset) - if f.pass.debug > 0 { - if lsym != nil { - f.Warnl(v.Pos, "de-virtualizing call") - } else { - f.Warnl(v.Pos, "couldn't de-virtualize call") + + for _, r := range lsym.R { + if int64(r.Off) == offset && r.Type&^objabi.R_WEAK == objabi.R_ADDR && r.Add == 0 { + return r.Sym } } - if lsym == nil { - return nil - } - va := aux.(*AuxCall) - return StaticAuxCall(lsym, va.abiInfo) + + return nil } // de-virtualize an InterLECall @@ -776,18 +770,14 @@ func devirtLESym(v *Value, aux Aux, sym Sym, offset int64) *obj.LSym { return nil } - f := v.Block.Func - lsym := f.fe.DerefItab(n, offset) - if f.pass.debug > 0 { + lsym := loadLSymOffset(n, offset) + if f := v.Block.Func; f.pass.debug > 0 { if lsym != nil { f.Warnl(v.Pos, "de-virtualizing call") } else { f.Warnl(v.Pos, "couldn't de-virtualize call") } } - if lsym == nil { - return nil - } return lsym } diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 0fbb39cfbb..7a6bf878e1 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -7401,10 +7401,6 @@ func (e *ssafn) Auto(pos src.XPos, t *types.Type) *ir.Name { return typecheck.TempAt(pos, e.curfn, t) // Note: adds new auto to e.curfn.Func.Dcl list } -func (e *ssafn) DerefItab(it *obj.LSym, offset int64) *obj.LSym { - return reflectdata.ITabSym(it, offset) -} - // SplitSlot returns a slot representing the data of parent starting at offset. func (e *ssafn) SplitSlot(parent *ssa.LocalSlot, suffix string, offset int64, t *types.Type) ssa.LocalSlot { node := parent.N diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 0e306eaea8..79b2402fe7 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -379,14 +379,6 @@ func Assignop(src, dst *types.Type) (ir.Op, string) { var missing, have *types.Field var ptr int if implements(src, dst, &missing, &have, &ptr) { - // Call NeedITab/ITabAddr so that (src, dst) - // gets added to itabs early, which allows - // us to de-virtualize calls through this - // type/interface pair later. See CompileITabs in reflect.go - if types.IsDirectIface(src) && !dst.IsEmptyInterface() { - NeedITab(src, dst) - } - return ir.OCONVIFACE, "" } diff --git a/src/cmd/compile/internal/typecheck/typecheck.go b/src/cmd/compile/internal/typecheck/typecheck.go index 8454b8d5b3..b1a4e193d6 100644 --- a/src/cmd/compile/internal/typecheck/typecheck.go +++ b/src/cmd/compile/internal/typecheck/typecheck.go @@ -24,7 +24,6 @@ var inimport bool // set during import var TypecheckAllowed bool var ( - NeedITab = func(t, itype *types.Type) {} NeedRuntimeType = func(*types.Type) {} ) -- GitLab From 1ba2074440a9b82b6e39c42f40b9d04858aa6c75 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 11 Jun 2021 01:09:47 -0700 Subject: [PATCH 0280/2500] [dev.typeparams] cmd/compile/internal/types2: support local defined types This CL changes types2's instance hashing logic to include position information for function-scope defined types as disambiguation. This isn't ideal, but it worked for getting nested.go passing. Updates #46592. Change-Id: Id83ba0001f44af69b81260306cc8b05e44fc4f09 Reviewed-on: https://go-review.googlesource.com/c/go/+/327170 Run-TryBot: Matthew Dempsky Trust: Matthew Dempsky Trust: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/subst.go | 5 + src/cmd/compile/internal/types2/typestring.go | 34 +++-- test/typeparam/nested.go | 134 ++++++++++++++++++ test/typeparam/nested.out | 4 + 4 files changed, 168 insertions(+), 9 deletions(-) create mode 100644 test/typeparam/nested.go create mode 100644 test/typeparam/nested.out diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index dd8dd74161..3ef65c2e92 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -425,14 +425,19 @@ func (subst *subster) typ(typ Type) Type { return typ } +var instanceHashing = 0 + // TODO(gri) Eventually, this should be more sophisticated. // It won't work correctly for locally declared types. func instantiatedHash(typ *Named, targs []Type) string { + assert(instanceHashing == 0) + instanceHashing++ var buf bytes.Buffer writeTypeName(&buf, typ.obj, nil) buf.WriteByte('[') writeTypeList(&buf, targs, nil, nil) buf.WriteByte(']') + instanceHashing-- // With respect to the represented type, whether a // type is fully expanded or stored as instance diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 07ed510d11..f08c41c2a3 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -350,17 +350,33 @@ func writeTParamList(buf *bytes.Buffer, list []*TypeName, qf Qualifier, visited } func writeTypeName(buf *bytes.Buffer, obj *TypeName, qf Qualifier) { - s := "" - if obj != nil { - if obj.pkg != nil { - writePackage(buf, obj.pkg, qf) + if obj == nil { + buf.WriteString("") + return + } + if obj.pkg != nil { + writePackage(buf, obj.pkg, qf) + } + buf.WriteString(obj.name) + + if instanceHashing != 0 { + // For local defined types, use the (original!) TypeName's position + // to disambiguate. This is overkill, and could probably instead + // just be the pointer value (if we assume a non-moving GC) or + // a unique ID (like cmd/compile uses). But this works for now, + // and is convenient for debugging. + + // TODO(mdempsky): I still don't fully understand why typ.orig.orig + // can differ from typ.orig, or whether looping more than twice is + // ever necessary. + typ := obj.typ.(*Named) + for typ.orig != typ { + typ = typ.orig + } + if orig := typ.obj; orig.pkg != nil && orig.parent != orig.pkg.scope { + fmt.Fprintf(buf, "@%q", orig.pos) } - // TODO(gri): function-local named types should be displayed - // differently from named types at package level to avoid - // ambiguity. - s = obj.name } - buf.WriteString(s) } func writeTuple(buf *bytes.Buffer, tup *Tuple, variadic bool, qf Qualifier, visited []Type) { diff --git a/test/typeparam/nested.go b/test/typeparam/nested.go new file mode 100644 index 0000000000..6512b3fc8f --- /dev/null +++ b/test/typeparam/nested.go @@ -0,0 +1,134 @@ +// run -gcflags=all="-d=unified -G" + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This test case stress tests a number of subtle cases involving +// nested type-parameterized declarations. At a high-level, it +// declares a generic function that contains a generic type +// declaration: +// +// func F[A intish]() { +// type T[B intish] struct{} +// +// // store reflect.Type tuple (A, B, F[A].T[B]) in tests +// } +// +// It then instantiates this function with a variety of type arguments +// for A and B. Particularly tricky things like shadowed types. +// +// From this data it tests two things: +// +// 1. Given tuples (A, B, F[A].T[B]) and (A', B', F[A'].T[B']), +// F[A].T[B] should be identical to F[A'].T[B'] iff (A, B) is +// identical to (A', B'). +// +// 2. A few of the instantiations are constructed to be identical, and +// it tests that exactly these pairs are duplicated (by golden +// output comparison to nested.out). +// +// In both cases, we're effectively using the compiler's existing +// runtime.Type handling (which is well tested) of type identity of A +// and B as a way to help bootstrap testing and validate its new +// runtime.Type handling of F[A].T[B]. +// +// This isn't perfect, but it smoked out a handful of issues in +// gotypes2 and unified IR. + +package main + +import ( + "fmt" + "reflect" +) + +type test struct { + TArgs [2]reflect.Type + Instance reflect.Type +} + +var tests []test + +type intish interface{ ~int } + +type Int int +type GlobalInt = Int // allow access to global Int, even when shadowed + +func F[A intish]() { + add := func(B, T interface{}) { + tests = append(tests, test{ + TArgs: [2]reflect.Type{ + reflect.TypeOf(A(0)), + reflect.TypeOf(B), + }, + Instance: reflect.TypeOf(T), + }) + } + + type Int int + + type T[B intish] struct{} + + add(int(0), T[int]{}) + add(Int(0), T[Int]{}) + add(GlobalInt(0), T[GlobalInt]{}) + add(A(0), T[A]{}) // NOTE: intentionally dups with int and GlobalInt + + type U[_ any] int + type V U[int] + type W V + + add(U[int](0), T[U[int]]{}) + add(U[Int](0), T[U[Int]]{}) + add(U[GlobalInt](0), T[U[GlobalInt]]{}) + add(U[A](0), T[U[A]]{}) // NOTE: intentionally dups with U[int] and U[GlobalInt] + add(V(0), T[V]{}) + add(W(0), T[W]{}) +} + +func main() { + type Int int + + F[int]() + F[Int]() + F[GlobalInt]() + + type U[_ any] int + type V U[int] + type W V + + F[U[int]]() + F[U[Int]]() + F[U[GlobalInt]]() + F[V]() + F[W]() + + type X[A any] U[X[A]] + + F[X[int]]() + F[X[Int]]() + F[X[GlobalInt]]() + + for j, tj := range tests { + for i, ti := range tests[:j+1] { + if (ti.TArgs == tj.TArgs) != (ti.Instance == tj.Instance) { + fmt.Printf("FAIL: %d,%d: %s, but %s\n", i, j, eq(ti.TArgs, tj.TArgs), eq(ti.Instance, tj.Instance)) + } + + // The test is constructed so we should see a few identical types. + // See "NOTE" comments above. + if i != j && ti.Instance == tj.Instance { + fmt.Printf("%d,%d: %v\n", i, j, ti.Instance) + } + } + } +} + +func eq(a, b interface{}) string { + op := "==" + if a != b { + op = "!=" + } + return fmt.Sprintf("%v %s %v", a, op, b) +} diff --git a/test/typeparam/nested.out b/test/typeparam/nested.out new file mode 100644 index 0000000000..9110518248 --- /dev/null +++ b/test/typeparam/nested.out @@ -0,0 +1,4 @@ +0,3: main.T·2[int;int] +4,7: main.T·2[int;"".U·3[int;int]] +22,23: main.T·2["".Int;"".Int] +26,27: main.T·2["".Int;"".U·3["".Int;"".Int]] -- GitLab From ad59efb02705a9f33a1eb9a9c04740da721a8cc4 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Mon, 7 Jun 2021 10:29:44 -0400 Subject: [PATCH 0281/2500] [dev.typeparams] go/ast: remove the typeparams build constraint This CL removes the typeparams build constraint guarding changes to the go/ast and go/types APIs. Notably it does not remove all indirection added to hide the type parameter API: the go/internal/typeparams package is not yet deleted, nor have go/parser or go/types been updated to access type parameter data directly. This will be done in a follow-up CL; the intent of this CL is to make it easier to support the new type set syntax, and to experiment with different AST APIs. Change-Id: I13ea0285752991b87b3aead1d1371e1f3f817b1a Reviewed-on: https://go-review.googlesource.com/c/go/+/325689 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/ast/ast.go | 62 +++++++++--- src/go/ast/ast_notypeparams.go | 28 ------ src/go/ast/ast_typeparams.go | 51 ---------- src/go/ast/walk.go | 17 +++- src/go/ast/walk_notypeparams.go | 17 ---- src/go/ast/walk_typeparams.go | 36 ------- src/go/internal/typeparams/notypeparams.go | 40 -------- src/go/internal/typeparams/typeparams.go | 3 - src/go/types/api_notypeparams.go | 104 --------------------- src/go/types/api_typeparams.go | 3 - src/go/types/api_typeparams_test.go | 3 - 11 files changed, 64 insertions(+), 300 deletions(-) delete mode 100644 src/go/ast/ast_notypeparams.go delete mode 100644 src/go/ast/ast_typeparams.go delete mode 100644 src/go/ast/walk_notypeparams.go delete mode 100644 src/go/ast/walk_typeparams.go delete mode 100644 src/go/internal/typeparams/notypeparams.go delete mode 100644 src/go/types/api_notypeparams.go diff --git a/src/go/ast/ast.go b/src/go/ast/ast.go index 337c87fd79..a34cafcb4e 100644 --- a/src/go/ast/ast.go +++ b/src/go/ast/ast.go @@ -374,6 +374,13 @@ type ( Rparen token.Pos // position of ")" } + // A ListExpr node represents a list of expressions separated by commas. + // ListExpr nodes are used as index in IndexExpr nodes representing type + // or function instantiations with more than one type argument. + ListExpr struct { + ElemList []Expr + } + // A StarExpr node represents an expression of the form "*" Expression. // Semantically it could be a unary "*" expression, or a pointer type. // @@ -440,6 +447,14 @@ type ( // Pointer types are represented via StarExpr nodes. + // A FuncType node represents a function type. + FuncType struct { + Func token.Pos // position of "func" keyword (token.NoPos if there is no "func") + TParams *FieldList // type parameters; or nil + Params *FieldList // (incoming) parameters; non-nil + Results *FieldList // (outgoing) results; or nil + } + // An InterfaceType node represents an interface type. InterfaceType struct { Interface token.Pos // position of "interface" keyword @@ -482,12 +497,18 @@ func (x *IndexExpr) Pos() token.Pos { return x.X.Pos() } func (x *SliceExpr) Pos() token.Pos { return x.X.Pos() } func (x *TypeAssertExpr) Pos() token.Pos { return x.X.Pos() } func (x *CallExpr) Pos() token.Pos { return x.Fun.Pos() } -func (x *StarExpr) Pos() token.Pos { return x.Star } -func (x *UnaryExpr) Pos() token.Pos { return x.OpPos } -func (x *BinaryExpr) Pos() token.Pos { return x.X.Pos() } -func (x *KeyValueExpr) Pos() token.Pos { return x.Key.Pos() } -func (x *ArrayType) Pos() token.Pos { return x.Lbrack } -func (x *StructType) Pos() token.Pos { return x.Struct } +func (x *ListExpr) Pos() token.Pos { + if len(x.ElemList) > 0 { + return x.ElemList[0].Pos() + } + return token.NoPos +} +func (x *StarExpr) Pos() token.Pos { return x.Star } +func (x *UnaryExpr) Pos() token.Pos { return x.OpPos } +func (x *BinaryExpr) Pos() token.Pos { return x.X.Pos() } +func (x *KeyValueExpr) Pos() token.Pos { return x.Key.Pos() } +func (x *ArrayType) Pos() token.Pos { return x.Lbrack } +func (x *StructType) Pos() token.Pos { return x.Struct } func (x *FuncType) Pos() token.Pos { if x.Func.IsValid() || x.Params == nil { // see issue 3870 return x.Func @@ -515,12 +536,18 @@ func (x *IndexExpr) End() token.Pos { return x.Rbrack + 1 } func (x *SliceExpr) End() token.Pos { return x.Rbrack + 1 } func (x *TypeAssertExpr) End() token.Pos { return x.Rparen + 1 } func (x *CallExpr) End() token.Pos { return x.Rparen + 1 } -func (x *StarExpr) End() token.Pos { return x.X.End() } -func (x *UnaryExpr) End() token.Pos { return x.X.End() } -func (x *BinaryExpr) End() token.Pos { return x.Y.End() } -func (x *KeyValueExpr) End() token.Pos { return x.Value.End() } -func (x *ArrayType) End() token.Pos { return x.Elt.End() } -func (x *StructType) End() token.Pos { return x.Fields.End() } +func (x *ListExpr) End() token.Pos { + if len(x.ElemList) > 0 { + return x.ElemList[len(x.ElemList)-1].End() + } + return token.NoPos +} +func (x *StarExpr) End() token.Pos { return x.X.End() } +func (x *UnaryExpr) End() token.Pos { return x.X.End() } +func (x *BinaryExpr) End() token.Pos { return x.Y.End() } +func (x *KeyValueExpr) End() token.Pos { return x.Value.End() } +func (x *ArrayType) End() token.Pos { return x.Elt.End() } +func (x *StructType) End() token.Pos { return x.Fields.End() } func (x *FuncType) End() token.Pos { if x.Results != nil { return x.Results.End() @@ -546,6 +573,7 @@ func (*IndexExpr) exprNode() {} func (*SliceExpr) exprNode() {} func (*TypeAssertExpr) exprNode() {} func (*CallExpr) exprNode() {} +func (*ListExpr) exprNode() {} func (*StarExpr) exprNode() {} func (*UnaryExpr) exprNode() {} func (*BinaryExpr) exprNode() {} @@ -892,6 +920,16 @@ type ( Values []Expr // initial values; or nil Comment *CommentGroup // line comments; or nil } + + // A TypeSpec node represents a type declaration (TypeSpec production). + TypeSpec struct { + Doc *CommentGroup // associated documentation; or nil + Name *Ident // type name + TParams *FieldList // type parameters; or nil + Assign token.Pos // position of '=', if any + Type Expr // *Ident, *ParenExpr, *SelectorExpr, *StarExpr, or any of the *XxxTypes + Comment *CommentGroup // line comments; or nil + } ) // Pos and End implementations for spec nodes. diff --git a/src/go/ast/ast_notypeparams.go b/src/go/ast/ast_notypeparams.go deleted file mode 100644 index fa132fba85..0000000000 --- a/src/go/ast/ast_notypeparams.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !typeparams -// +build !typeparams - -package ast - -import "go/token" - -type ( - // A FuncType node represents a function type. - FuncType struct { - Func token.Pos // position of "func" keyword (token.NoPos if there is no "func") - Params *FieldList // (incoming) parameters; non-nil - Results *FieldList // (outgoing) results; or nil - } - - // A TypeSpec node represents a type declaration (TypeSpec production). - TypeSpec struct { - Doc *CommentGroup // associated documentation; or nil - Name *Ident // type name - Assign token.Pos // position of '=', if any - Type Expr // *Ident, *ParenExpr, *SelectorExpr, *StarExpr, or any of the *XxxTypes - Comment *CommentGroup // line comments; or nil - } -) diff --git a/src/go/ast/ast_typeparams.go b/src/go/ast/ast_typeparams.go deleted file mode 100644 index 24fdc5f131..0000000000 --- a/src/go/ast/ast_typeparams.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build typeparams -// +build typeparams - -package ast - -import "go/token" - -type ( - // A FuncType node represents a function type. - FuncType struct { - Func token.Pos // position of "func" keyword (token.NoPos if there is no "func") - TParams *FieldList // type parameters; or nil - Params *FieldList // (incoming) parameters; non-nil - Results *FieldList // (outgoing) results; or nil - } - - // A TypeSpec node represents a type declaration (TypeSpec production). - TypeSpec struct { - Doc *CommentGroup // associated documentation; or nil - Name *Ident // type name - TParams *FieldList // type parameters; or nil - Assign token.Pos // position of '=', if any - Type Expr // *Ident, *ParenExpr, *SelectorExpr, *StarExpr, or any of the *XxxTypes - Comment *CommentGroup // line comments; or nil - } - - // A ListExpr node represents a list of expressions separated by commas. - // ListExpr nodes are used as index in IndexExpr nodes representing type - // or function instantiations with more than one type argument. - ListExpr struct { - ElemList []Expr - } -) - -func (*ListExpr) exprNode() {} -func (x *ListExpr) Pos() token.Pos { - if len(x.ElemList) > 0 { - return x.ElemList[0].Pos() - } - return token.NoPos -} -func (x *ListExpr) End() token.Pos { - if len(x.ElemList) > 0 { - return x.ElemList[len(x.ElemList)-1].End() - } - return token.NoPos -} diff --git a/src/go/ast/walk.go b/src/go/ast/walk.go index 9224264e29..02fef5901d 100644 --- a/src/go/ast/walk.go +++ b/src/go/ast/walk.go @@ -4,6 +4,8 @@ package ast +import "fmt" + // A Visitor's Visit method is invoked for each node encountered by Walk. // If the result visitor w is not nil, Walk visits each of the children // of node with the visitor w, followed by a call of w.Visit(nil). @@ -136,6 +138,11 @@ func Walk(v Visitor, node Node) { Walk(v, n.Fun) walkExprList(v, n.Args) + case *ListExpr: + for _, elem := range n.ElemList { + Walk(v, elem) + } + case *StarExpr: Walk(v, n.X) @@ -161,7 +168,9 @@ func Walk(v Visitor, node Node) { Walk(v, n.Fields) case *FuncType: - walkFuncTypeParams(v, n) + if n.TParams != nil { + Walk(v, n.TParams) + } if n.Params != nil { Walk(v, n.Params) } @@ -316,7 +325,9 @@ func Walk(v Visitor, node Node) { Walk(v, n.Doc) } Walk(v, n.Name) - walkTypeSpecParams(v, n) + if n.TParams != nil { + Walk(v, n.TParams) + } Walk(v, n.Type) if n.Comment != nil { Walk(v, n.Comment) @@ -363,7 +374,7 @@ func Walk(v Visitor, node Node) { } default: - walkOtherNodes(v, n) + panic(fmt.Sprintf("ast.Walk: unexpected node type %T", n)) } v.Visit(nil) diff --git a/src/go/ast/walk_notypeparams.go b/src/go/ast/walk_notypeparams.go deleted file mode 100644 index d43e13dd11..0000000000 --- a/src/go/ast/walk_notypeparams.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !typeparams -// +build !typeparams - -package ast - -import "fmt" - -func walkFuncTypeParams(v Visitor, n *FuncType) {} -func walkTypeSpecParams(v Visitor, n *TypeSpec) {} - -func walkOtherNodes(v Visitor, n Node) { - panic(fmt.Sprintf("ast.Walk: unexpected node type %T", n)) -} diff --git a/src/go/ast/walk_typeparams.go b/src/go/ast/walk_typeparams.go deleted file mode 100644 index b6621335b8..0000000000 --- a/src/go/ast/walk_typeparams.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build typeparams -// +build typeparams - -package ast - -import ( - "fmt" -) - -func walkFuncTypeParams(v Visitor, n *FuncType) { - if n.TParams != nil { - Walk(v, n.TParams) - } -} - -func walkTypeSpecParams(v Visitor, n *TypeSpec) { - if n.TParams != nil { - Walk(v, n.TParams) - } -} - -func walkOtherNodes(v Visitor, n Node) { - if e, ok := n.(*ListExpr); ok { - if e != nil { - for _, elem := range e.ElemList { - Walk(v, elem) - } - } - } else { - panic(fmt.Sprintf("ast.Walk: unexpected node type %T", n)) - } -} diff --git a/src/go/internal/typeparams/notypeparams.go b/src/go/internal/typeparams/notypeparams.go deleted file mode 100644 index 2ceafaac1c..0000000000 --- a/src/go/internal/typeparams/notypeparams.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !typeparams -// +build !typeparams - -package typeparams - -import ( - "go/ast" -) - -const Enabled = false - -func PackExpr(list []ast.Expr) ast.Expr { - switch len(list) { - case 1: - return list[0] - default: - // The parser should not attempt to pack multiple expressions into an - // IndexExpr if type params are disabled. - panic("multiple index expressions are unsupported without type params") - } -} - -func UnpackExpr(expr ast.Expr) []ast.Expr { - return []ast.Expr{expr} -} - -func IsListExpr(n ast.Node) bool { - return false -} - -func Get(ast.Node) *ast.FieldList { - return nil -} - -func Set(node ast.Node, params *ast.FieldList) { -} diff --git a/src/go/internal/typeparams/typeparams.go b/src/go/internal/typeparams/typeparams.go index 871e95d998..b4251bda7e 100644 --- a/src/go/internal/typeparams/typeparams.go +++ b/src/go/internal/typeparams/typeparams.go @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build typeparams -// +build typeparams - package typeparams import ( diff --git a/src/go/types/api_notypeparams.go b/src/go/types/api_notypeparams.go deleted file mode 100644 index 9f7cb7eccf..0000000000 --- a/src/go/types/api_notypeparams.go +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !typeparams -// +build !typeparams - -package types - -import "go/ast" - -// Info holds result type information for a type-checked package. -// Only the information for which a map is provided is collected. -// If the package has type errors, the collected information may -// be incomplete. -type Info struct { - // Types maps expressions to their types, and for constant - // expressions, also their values. Invalid expressions are - // omitted. - // - // For (possibly parenthesized) identifiers denoting built-in - // functions, the recorded signatures are call-site specific: - // if the call result is not a constant, the recorded type is - // an argument-specific signature. Otherwise, the recorded type - // is invalid. - // - // The Types map does not record the type of every identifier, - // only those that appear where an arbitrary expression is - // permitted. For instance, the identifier f in a selector - // expression x.f is found only in the Selections map, the - // identifier z in a variable declaration 'var z int' is found - // only in the Defs map, and identifiers denoting packages in - // qualified identifiers are collected in the Uses map. - Types map[ast.Expr]TypeAndValue - - // Defs maps identifiers to the objects they define (including - // package names, dots "." of dot-imports, and blank "_" identifiers). - // For identifiers that do not denote objects (e.g., the package name - // in package clauses, or symbolic variables t in t := x.(type) of - // type switch headers), the corresponding objects are nil. - // - // For an embedded field, Defs returns the field *Var it defines. - // - // Invariant: Defs[id] == nil || Defs[id].Pos() == id.Pos() - Defs map[*ast.Ident]Object - - // Uses maps identifiers to the objects they denote. - // - // For an embedded field, Uses returns the *TypeName it denotes. - // - // Invariant: Uses[id].Pos() != id.Pos() - Uses map[*ast.Ident]Object - - // Implicits maps nodes to their implicitly declared objects, if any. - // The following node and object types may appear: - // - // node declared object - // - // *ast.ImportSpec *PkgName for imports without renames - // *ast.CaseClause type-specific *Var for each type switch case clause (incl. default) - // *ast.Field anonymous parameter *Var (incl. unnamed results) - // - Implicits map[ast.Node]Object - - // Selections maps selector expressions (excluding qualified identifiers) - // to their corresponding selections. - Selections map[*ast.SelectorExpr]*Selection - - // Scopes maps ast.Nodes to the scopes they define. Package scopes are not - // associated with a specific node but with all files belonging to a package. - // Thus, the package scope can be found in the type-checked Package object. - // Scopes nest, with the Universe scope being the outermost scope, enclosing - // the package scope, which contains (one or more) files scopes, which enclose - // function scopes which in turn enclose statement and function literal scopes. - // Note that even though package-level functions are declared in the package - // scope, the function scopes are embedded in the file scope of the file - // containing the function declaration. - // - // The following node types may appear in Scopes: - // - // *ast.File - // *ast.FuncType - // *ast.BlockStmt - // *ast.IfStmt - // *ast.SwitchStmt - // *ast.TypeSwitchStmt - // *ast.CaseClause - // *ast.CommClause - // *ast.ForStmt - // *ast.RangeStmt - // - Scopes map[ast.Node]*Scope - - // InitOrder is the list of package-level initializers in the order in which - // they must be executed. Initializers referring to variables related by an - // initialization dependency appear in topological order, the others appear - // in source order. Variables without an initialization expression do not - // appear in this list. - InitOrder []*Initializer -} - -func getInferred(info *Info) map[ast.Expr]_Inferred { - return nil -} diff --git a/src/go/types/api_typeparams.go b/src/go/types/api_typeparams.go index ae2c5a7fd0..25fb3fa781 100644 --- a/src/go/types/api_typeparams.go +++ b/src/go/types/api_typeparams.go @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build typeparams -// +build typeparams - package types import ( diff --git a/src/go/types/api_typeparams_test.go b/src/go/types/api_typeparams_test.go index 517c58505b..4a2adce9a2 100644 --- a/src/go/types/api_typeparams_test.go +++ b/src/go/types/api_typeparams_test.go @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build typeparams -// +build typeparams - package types_test import ( -- GitLab From 7c5d7a4caffdb72ce252fb465ff4f7fd62a46c8a Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Thu, 3 Jun 2021 22:07:36 -0400 Subject: [PATCH 0282/2500] [dev.typeparams] go/token, go/scanner: add the "~" operator This is an approximate port of CL 307370 to go/token and go/scanner. Change-Id: I5b789408f825f7e39f569322cb67802117b9d734 Reviewed-on: https://go-review.googlesource.com/c/go/+/324992 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/scanner/scanner.go | 2 ++ src/go/scanner/scanner_test.go | 3 ++- src/go/token/token.go | 11 ++++++++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/go/scanner/scanner.go b/src/go/scanner/scanner.go index 29cbf39721..f8bcf4d864 100644 --- a/src/go/scanner/scanner.go +++ b/src/go/scanner/scanner.go @@ -969,6 +969,8 @@ scanAgain: } case '|': tok = s.switch3(token.OR, token.OR_ASSIGN, '|', token.LOR) + case '~': + tok = token.TILDE default: // next reports unexpected BOMs - don't repeat if ch != bom { diff --git a/src/go/scanner/scanner_test.go b/src/go/scanner/scanner_test.go index ac8d257716..dd3c7cf838 100644 --- a/src/go/scanner/scanner_test.go +++ b/src/go/scanner/scanner_test.go @@ -40,7 +40,7 @@ type elt struct { class int } -var tokens = [...]elt{ +var tokens = []elt{ // Special tokens {token.COMMENT, "/* a comment */", special}, {token.COMMENT, "// a comment \n", special}, @@ -149,6 +149,7 @@ var tokens = [...]elt{ {token.RBRACE, "}", operator}, {token.SEMICOLON, ";", operator}, {token.COLON, ":", operator}, + {token.TILDE, "~", operator}, // Keywords {token.BREAK, "break", keyword}, diff --git a/src/go/token/token.go b/src/go/token/token.go index 96a1079ec3..d22e575661 100644 --- a/src/go/token/token.go +++ b/src/go/token/token.go @@ -125,6 +125,11 @@ const ( TYPE VAR keyword_end + + additional_beg + // additional tokens, handled in an ad-hoc manner + TILDE + additional_end ) var tokens = [...]string{ @@ -225,6 +230,8 @@ var tokens = [...]string{ SWITCH: "switch", TYPE: "type", VAR: "var", + + TILDE: "~", } // String returns the string corresponding to the token tok. @@ -304,7 +311,9 @@ func (tok Token) IsLiteral() bool { return literal_beg < tok && tok < literal_en // IsOperator returns true for tokens corresponding to operators and // delimiters; it returns false otherwise. // -func (tok Token) IsOperator() bool { return operator_beg < tok && tok < operator_end } +func (tok Token) IsOperator() bool { + return (operator_beg < tok && tok < operator_end) || tok == TILDE +} // IsKeyword returns true for tokens corresponding to keywords; // it returns false otherwise. -- GitLab From ab4b3c4b15838e3eb5888b96c7965e31973b25cd Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Mon, 7 Jun 2021 10:04:12 -0400 Subject: [PATCH 0283/2500] [dev.typeparams] go/parser: accept "~" and "|" interface elements This is a port of CL 307371 to go/parser, adding support for the new embedded type expressions. As in that CL, type lists continue to be accepted. This CL also revealed a pre-existing bug related to embedded instances: the parser was failing to parse embedded instances with multiple type arguments, due to not consuming the initial ','. This is fixed, and along the way TestErrors is modified to use subtests. Several missing tests cases were added to exprstring_test.go. These must have been missed in an earlier CL. Change-Id: I452769536998cddb1618bebdba675fc09d48a12f Reviewed-on: https://go-review.googlesource.com/c/go/+/325690 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/parser/error_test.go | 20 ++++---- src/go/parser/parser.go | 74 +++++++++++++++++++++++++--- src/go/parser/testdata/interface.go2 | 37 ++++++++++++++ src/go/types/exprstring_test.go | 34 +++++++++++++ 4 files changed, 149 insertions(+), 16 deletions(-) create mode 100644 src/go/parser/testdata/interface.go2 diff --git a/src/go/parser/error_test.go b/src/go/parser/error_test.go index f4f0a5240a..e22ab12451 100644 --- a/src/go/parser/error_test.go +++ b/src/go/parser/error_test.go @@ -186,16 +186,18 @@ func TestErrors(t *testing.T) { } for _, d := range list { name := d.Name() - if !d.IsDir() && !strings.HasPrefix(name, ".") && (strings.HasSuffix(name, ".src") || strings.HasSuffix(name, ".go2")) { - mode := DeclarationErrors | AllErrors - if strings.HasSuffix(name, ".go2") { - if !typeparams.Enabled { - continue + t.Run(name, func(t *testing.T) { + if !d.IsDir() && !strings.HasPrefix(name, ".") && (strings.HasSuffix(name, ".src") || strings.HasSuffix(name, ".go2")) { + mode := DeclarationErrors | AllErrors + if strings.HasSuffix(name, ".go2") { + if !typeparams.Enabled { + return + } + } else { + mode |= typeparams.DisallowParsing } - } else { - mode |= typeparams.DisallowParsing + checkErrors(t, filepath.Join(testdata, name), nil, mode, true) } - checkErrors(t, filepath.Join(testdata, name), nil, mode, true) - } + }) } } diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go index 3965641713..5ccba02e5c 100644 --- a/src/go/parser/parser.go +++ b/src/go/parser/parser.go @@ -980,6 +980,7 @@ func (p *parser) parseMethodSpec() *ast.Field { list := []ast.Expr{x} if p.atComma("type argument list", token.RBRACK) { p.exprLev++ + p.next() for p.tok != token.RBRACK && p.tok != token.EOF { list = append(list, p.parseType()) if !p.atComma("type argument list", token.RBRACK) { @@ -1011,11 +1012,56 @@ func (p *parser) parseMethodSpec() *ast.Field { typ = p.parseTypeInstance(typ) } } - p.expectSemi() // call before accessing p.linecomment - spec := &ast.Field{Doc: doc, Names: idents, Type: typ, Comment: p.lineComment} + // Comment is added at the callsite: the field below may joined with + // additional type specs using '|'. + // TODO(rfindley) this should be refactored. + // TODO(rfindley) add more tests for comment handling. + return &ast.Field{Doc: doc, Names: idents, Type: typ} +} - return spec +func (p *parser) embeddedElem(f *ast.Field) *ast.Field { + if p.trace { + defer un(trace(p, "EmbeddedElem")) + } + if f == nil { + f = new(ast.Field) + f.Type = p.embeddedTerm() + } + for p.tok == token.OR { + t := new(ast.BinaryExpr) + t.OpPos = p.pos + t.Op = token.OR + p.next() + t.X = f.Type + t.Y = p.embeddedTerm() + f.Type = t + } + return f +} + +func (p *parser) embeddedTerm() ast.Expr { + if p.trace { + defer un(trace(p, "EmbeddedTerm")) + } + if p.tok == token.TILDE { + t := new(ast.UnaryExpr) + t.OpPos = p.pos + t.Op = token.TILDE + p.next() + t.X = p.parseType() + return t + } + + t := p.tryIdentOrType() + if t == nil { + pos := p.pos + p.errorExpected(pos, "~ term or type") + p.advance(exprEnd) + return &ast.BadExpr{From: pos, To: p.pos} + } + + return t } func (p *parser) parseInterfaceType() *ast.InterfaceType { @@ -1026,10 +1072,24 @@ func (p *parser) parseInterfaceType() *ast.InterfaceType { pos := p.expect(token.INTERFACE) lbrace := p.expect(token.LBRACE) var list []*ast.Field - for p.tok == token.IDENT || p.parseTypeParams() && p.tok == token.TYPE { - if p.tok == token.IDENT { - list = append(list, p.parseMethodSpec()) - } else { + for p.tok == token.IDENT || p.parseTypeParams() && (p.tok == token.TYPE || p.tok == token.TILDE) { + switch p.tok { + case token.IDENT: + f := p.parseMethodSpec() + if f.Names == nil && p.parseTypeParams() { + f = p.embeddedElem(f) + } + p.expectSemi() + f.Comment = p.lineComment + list = append(list, f) + case token.TILDE: + f := p.embeddedElem(nil) + p.expectSemi() + f.Comment = p.lineComment + list = append(list, f) + case token.TYPE: + // TODO(rfindley): remove TypeList syntax and refactor the clauses above. + // all types in a type list share the same field name "type" // (since type is a keyword, a Go program cannot have that field name) name := []*ast.Ident{{NamePos: p.pos, Name: "type"}} diff --git a/src/go/parser/testdata/interface.go2 b/src/go/parser/testdata/interface.go2 new file mode 100644 index 0000000000..c631055202 --- /dev/null +++ b/src/go/parser/testdata/interface.go2 @@ -0,0 +1,37 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file contains test cases for interfaces containing +// constraint elements. +// +// For now, we accept both ordinary type lists and the +// more complex constraint elements. + +package p + +type _ interface { + m() + type int + type int, string + E +} + +type _ interface { + m() + ~int + int | string + int | ~string + ~int | ~string +} + + +type _ interface { + m() + ~int + T[int, string] | string + int | ~T[string, struct{}] + ~int | ~string + type bool, int, float64 +} + diff --git a/src/go/types/exprstring_test.go b/src/go/types/exprstring_test.go index 51102881c9..a67f6a978a 100644 --- a/src/go/types/exprstring_test.go +++ b/src/go/types/exprstring_test.go @@ -27,6 +27,40 @@ var testExprs = []testEntry{ {"func(x int) complex128 {}", "(func(x int) complex128 literal)"}, {"[]int{1, 2, 3}", "([]int literal)"}, + // type expressions + dup("[1 << 10]byte"), + dup("[]int"), + dup("*int"), + dup("struct{x int}"), + dup("func()"), + dup("func(int, float32) string"), + dup("interface{m()}"), + dup("interface{m() string; n(x int)}"), + dup("interface{type int}"), + + // The following exprs do not get formatted correctly: each element in the + // type list is printed on a separate line. This is left as a placeholder + // until type lists are removed. + // TODO(rfindley): remove this once type lists are gone. + // dup("interface{type int, float64, string}"), + // dup("interface{type int; m()}"), + // dup("interface{type int, float64, string; m() string; n(x int)}"), + dup("map[string]int"), + dup("chan E"), + dup("<-chan E"), + dup("chan<- E"), + + // new interfaces + dup("interface{int}"), + dup("interface{~int}"), + dup("interface{~int}"), + dup("interface{int | string}"), + dup("interface{~int | ~string; float64; m()}"), + + // See above. + // dup("interface{type a, b, c; ~int | ~string; float64; m()}"), + dup("interface{~T[int, string] | string}"), + // non-type expressions dup("(x)"), dup("x.f"), -- GitLab From 54f854fb4150dfe5bc156abf57c46e9931d55ee5 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Mon, 7 Jun 2021 19:50:15 -0400 Subject: [PATCH 0284/2500] [dev.typeparams] go/parser: accept embedded type literals This is an approximate port of CL 321109 to go/parser, though go/parser does not have the same internal APIs as cmd/compile/internal/syntax, so this CL required some refactoring. Change-Id: I146ef530c969d61bab99f98f4de94b862e103ddc Reviewed-on: https://go-review.googlesource.com/c/go/+/325703 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/parser/parser.go | 27 +++++++++++++---- src/go/parser/short_test.go | 8 +++-- src/go/parser/testdata/interface.go2 | 45 +++++++++++++++++++++++++++- 3 files changed, 71 insertions(+), 9 deletions(-) diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go index 5ccba02e5c..869d14c2c1 100644 --- a/src/go/parser/parser.go +++ b/src/go/parser/parser.go @@ -1071,10 +1071,13 @@ func (p *parser) parseInterfaceType() *ast.InterfaceType { pos := p.expect(token.INTERFACE) lbrace := p.expect(token.LBRACE) + var list []*ast.Field - for p.tok == token.IDENT || p.parseTypeParams() && (p.tok == token.TYPE || p.tok == token.TILDE) { - switch p.tok { - case token.IDENT: + +parseElements: + for { + switch { + case p.tok == token.IDENT: f := p.parseMethodSpec() if f.Names == nil && p.parseTypeParams() { f = p.embeddedElem(f) @@ -1082,12 +1085,12 @@ func (p *parser) parseInterfaceType() *ast.InterfaceType { p.expectSemi() f.Comment = p.lineComment list = append(list, f) - case token.TILDE: + case p.tok == token.TILDE && p.parseTypeParams(): f := p.embeddedElem(nil) p.expectSemi() f.Comment = p.lineComment list = append(list, f) - case token.TYPE: + case p.tok == token.TYPE && p.parseTypeParams(): // TODO(rfindley): remove TypeList syntax and refactor the clauses above. // all types in a type list share the same field name "type" @@ -1099,8 +1102,22 @@ func (p *parser) parseInterfaceType() *ast.InterfaceType { list = append(list, &ast.Field{Names: name, Type: typ}) } p.expectSemi() + case p.parseTypeParams(): + if t := p.tryIdentOrType(); t != nil { + f := new(ast.Field) + f.Type = t + f = p.embeddedElem(f) + p.expectSemi() + f.Comment = p.lineComment + list = append(list, f) + } else { + break parseElements + } + default: + break parseElements } } + // TODO(rfindley): the error produced here could be improved, since we could // accept a identifier, 'type', or a '}' at this point. rbrace := p.expect(token.RBRACE) diff --git a/src/go/parser/short_test.go b/src/go/parser/short_test.go index 67fef15665..2467ccb4a7 100644 --- a/src/go/parser/short_test.go +++ b/src/go/parser/short_test.go @@ -200,10 +200,12 @@ var invalids = []string{ `package p; func (type /* ERROR "found 'type'" */ T)(T) _()`, `package p; type _[A+B, /* ERROR "expected ']'" */ ] int`, - // TODO: this error should be positioned on the ':' + // TODO(rfindley): this error should be positioned on the ':' `package p; var a = a[[]int:[ /* ERROR "expected expression" */ ]int];`, - // TODO: the compiler error is better here: "cannot parenthesize embedded type" - `package p; type I1 interface{}; type I2 interface{ (/* ERROR "expected '}', found '\('" */ I1) }`, + + // TODO(rfindley): the compiler error is better here: "cannot parenthesize embedded type" + // TODO(rfindley): confirm that parenthesized types should now be accepted. + // `package p; type I1 interface{}; type I2 interface{ (/* ERROR "expected '}', found '\('" */ I1) }`, // issue 8656 `package p; func f() (a b string /* ERROR "missing ','" */ , ok bool)`, diff --git a/src/go/parser/testdata/interface.go2 b/src/go/parser/testdata/interface.go2 index c631055202..b399d75148 100644 --- a/src/go/parser/testdata/interface.go2 +++ b/src/go/parser/testdata/interface.go2 @@ -25,7 +25,6 @@ type _ interface { ~int | ~string } - type _ interface { m() ~int @@ -35,3 +34,47 @@ type _ interface { type bool, int, float64 } +type _ interface { + int + []byte + [10]int + struct{} + *int + func() + interface{} + map[string]int + chan T + chan<- T + <-chan T + T[int] +} + +type _ interface { + int | string + []byte | string + [10]int | string + struct{} | string + *int | string + func() | string + interface{} | string + map[string]int | string + chan T | string + chan<- T | string + <-chan T | string + T[int] | string +} + +type _ interface { + ~int | string + ~[]byte | string + ~[10]int | string + ~struct{} | string + ~*int | string + ~func() | string + ~interface{} | string + ~map[string]int | string + ~chan T | string + ~chan<- T | string + ~<-chan T | string + ~T[int] | string +} -- GitLab From e7451f661665e406889094b9d1471c7991dfefaa Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Tue, 8 Jun 2021 10:21:51 -0400 Subject: [PATCH 0285/2500] [dev.typeparams] go/types: accept embedded interface elements This is a port of CL 321689 to go/types. It differs from that CL in the uses of the position, AST and error APIs, and in not factoring out an unimplemented() helper (this helper didn't already exist in go/types, so it seemed cleaner to defer adding it). Change-Id: I577a57297caf35eb7a23f63f3f52037a7bb528ea Reviewed-on: https://go-review.googlesource.com/c/go/+/326069 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer --- src/go/types/builtins.go | 2 +- src/go/types/errorcodes.go | 11 +- src/go/types/infer.go | 5 +- src/go/types/interface.go | 212 +++++++++--------- src/go/types/predicates.go | 3 + src/go/types/sanitize.go | 6 +- src/go/types/sizeof_test.go | 3 +- src/go/types/sizes.go | 2 + src/go/types/subst.go | 16 +- src/go/types/testdata/check/decls0.src | 2 +- src/go/types/testdata/check/issues.src | 2 +- src/go/types/testdata/check/typeinst2.go2 | 6 +- .../types/testdata/examples/constraints.go2 | 25 +++ .../types/testdata/fixedbugs/issue39634.go2 | 2 +- .../types/testdata/fixedbugs/issue39693.go2 | 17 +- .../types/testdata/fixedbugs/issue39711.go2 | 4 +- .../types/testdata/fixedbugs/issue39723.go2 | 2 +- .../types/testdata/fixedbugs/issue39948.go2 | 8 +- src/go/types/type.go | 1 - src/go/types/typestring.go | 21 +- src/go/types/typestring_test.go | 3 + src/go/types/unify.go | 4 + src/go/types/union.go | 108 +++++++++ 23 files changed, 310 insertions(+), 155 deletions(-) create mode 100644 src/go/types/testdata/examples/constraints.go2 create mode 100644 src/go/types/union.go diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 2a2d54da88..99122dfe7c 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -783,7 +783,7 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { tpar := NewTypeName(token.NoPos, nil /* = Universe pkg */, "", nil) ptyp := check.newTypeParam(tpar, 0, &emptyInterface) // assigns type to tpar as a side-effect tsum := _NewSum(rtypes) - ptyp.bound = &Interface{types: tsum, allMethods: markComplete, allTypes: tsum} + ptyp.bound = &Interface{allMethods: markComplete, allTypes: tsum} return ptyp } diff --git a/src/go/types/errorcodes.go b/src/go/types/errorcodes.go index 3d24da7b53..2afb6a383c 100644 --- a/src/go/types/errorcodes.go +++ b/src/go/types/errorcodes.go @@ -281,16 +281,7 @@ const ( _IncomparableMapKey // _InvalidIfaceEmbed occurs when a non-interface type is embedded in an - // interface. - // - // Example: - // type T struct {} - // - // func (T) m() - // - // type I interface { - // T - // } + // interface (for go 1.17 or earlier). _InvalidIfaceEmbed // _InvalidPtrEmbed occurs when an embedded field is of the pointer form *T, diff --git a/src/go/types/infer.go b/src/go/types/infer.go index 5d49351e1f..951c6b8cbd 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -315,6 +315,9 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { // Thus, we only need to look at the input and result parameters. return w.isParameterized(t.params) || w.isParameterized(t.results) + case *Union: + panic("unimplemented") + case *Interface: if t.allMethods != nil { // TODO(rFindley) at some point we should enforce completeness here @@ -332,7 +335,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { return true } } - return w.isParameterizedList(unpackType(t.types)) + return w.isParameterizedList(t.embeddeds) }, nil) case *Map: diff --git a/src/go/types/interface.go b/src/go/types/interface.go index fd3fe0ef91..611f387046 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -13,74 +13,84 @@ import ( ) func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, def *Named) { - var tlist *ast.Ident // "type" name of first entry in a type list declaration - var types []ast.Expr + var tlist []ast.Expr + var tname *ast.Ident // "type" name of first entry in a type list declaration + for _, f := range iface.Methods.List { - if len(f.Names) > 0 { - // We have a method with name f.Names[0], or a type - // of a type list (name.Name == "type"). - // (The parser ensures that there's only one method - // and we don't care if a constructed AST has more.) - name := f.Names[0] - if name.Name == "_" { - check.errorf(name, _BlankIfaceMethod, "invalid method name _") - continue // ignore - } + if len(f.Names) == 0 { + // We have an embedded type; possibly a union of types. + ityp.embeddeds = append(ityp.embeddeds, parseUnion(check, flattenUnion(nil, f.Type))) + check.posMap[ityp] = append(check.posMap[ityp], f.Type.Pos()) + continue + } - if name.Name == "type" { - // Always collect all type list entries, even from - // different type lists, under the assumption that - // the author intended to include all types. - types = append(types, f.Type) - if tlist != nil && tlist != name { - check.errorf(name, _Todo, "cannot have multiple type lists in an interface") - } - tlist = name - continue - } + // We have a method with name f.Names[0], or a type + // of a type list (name.Name == "type"). + // (The parser ensures that there's only one method + // and we don't care if a constructed AST has more.) + name := f.Names[0] + if name.Name == "_" { + check.errorf(name, _BlankIfaceMethod, "invalid method name _") + continue // ignore + } - typ := check.typ(f.Type) - sig, _ := typ.(*Signature) - if sig == nil { - if typ != Typ[Invalid] { - check.invalidAST(f.Type, "%s is not a method signature", typ) - } - continue // ignore + if name.Name == "type" { + // For now, collect all type list entries as if it + // were a single union, where each union element is + // of the form ~T. + // TODO(rfindley) remove once we disallow type lists + op := new(ast.UnaryExpr) + op.Op = token.TILDE + op.X = f.Type + tlist = append(tlist, op) + if tname != nil && tname != name { + check.errorf(name, _Todo, "cannot have multiple type lists in an interface") } + tname = name + continue + } - // Always type-check method type parameters but complain if they are not enabled. - // (This extra check is needed here because interface method signatures don't have - // a receiver specification.) - if sig.tparams != nil { - var at positioner = f.Type - if tparams := typeparams.Get(f.Type); tparams != nil { - at = tparams - } - check.errorf(at, _Todo, "methods cannot have type parameters") + typ := check.typ(f.Type) + sig, _ := typ.(*Signature) + if sig == nil { + if typ != Typ[Invalid] { + check.invalidAST(f.Type, "%s is not a method signature", typ) } + continue // ignore + } - // use named receiver type if available (for better error messages) - var recvTyp Type = ityp - if def != nil { - recvTyp = def + // Always type-check method type parameters but complain if they are not enabled. + // (This extra check is needed here because interface method signatures don't have + // a receiver specification.) + if sig.tparams != nil { + var at positioner = f.Type + if tparams := typeparams.Get(f.Type); tparams != nil { + at = tparams } - sig.recv = NewVar(name.Pos(), check.pkg, "", recvTyp) - - m := NewFunc(name.Pos(), check.pkg, name.Name, sig) - check.recordDef(name, m) - ityp.methods = append(ityp.methods, m) - } else { - // We have an embedded type. completeInterface will - // eventually verify that we have an interface. - ityp.embeddeds = append(ityp.embeddeds, check.typ(f.Type)) - check.posMap[ityp] = append(check.posMap[ityp], f.Type.Pos()) + check.errorf(at, _Todo, "methods cannot have type parameters") + } + + // use named receiver type if available (for better error messages) + var recvTyp Type = ityp + if def != nil { + recvTyp = def } + sig.recv = NewVar(name.Pos(), check.pkg, "", recvTyp) + + m := NewFunc(name.Pos(), check.pkg, name.Name, sig) + check.recordDef(name, m) + ityp.methods = append(ityp.methods, m) } // type constraints - ityp.types = _NewSum(check.collectTypeConstraints(iface.Pos(), types)) + if tlist != nil { + ityp.embeddeds = append(ityp.embeddeds, parseUnion(check, tlist)) + // Types T in a type list are added as ~T expressions but we don't + // have the position of the '~'. Use the first type position instead. + check.posMap[ityp] = append(check.posMap[ityp], tlist[0].(*ast.UnaryExpr).X.Pos()) + } - if len(ityp.methods) == 0 && ityp.types == nil && len(ityp.embeddeds) == 0 { + if len(ityp.methods) == 0 && len(ityp.embeddeds) == 0 { // empty interface ityp.allMethods = markComplete return @@ -93,32 +103,12 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d check.later(func() { check.completeInterface(iface.Pos(), ityp) }) } -func (check *Checker) collectTypeConstraints(pos token.Pos, types []ast.Expr) []Type { - list := make([]Type, 0, len(types)) // assume all types are correct - for _, texpr := range types { - if texpr == nil { - check.invalidAST(atPos(pos), "missing type constraint") - continue - } - list = append(list, check.varType(texpr)) +func flattenUnion(list []ast.Expr, x ast.Expr) []ast.Expr { + if o, _ := x.(*ast.BinaryExpr); o != nil && o.Op == token.OR { + list = flattenUnion(list, o.X) + x = o.Y } - - // Ensure that each type is only present once in the type list. Types may be - // interfaces, which may not be complete yet. It's ok to do this check at the - // end because it's not a requirement for correctness of the code. - // Note: This is a quadratic algorithm, but type lists tend to be short. - check.later(func() { - for i, t := range list { - if t := asInterface(t); t != nil { - check.completeInterface(types[i].Pos(), t) - } - if includes(list[:i], t) { - check.softErrorf(types[i], _Todo, "duplicate type %s in type list", t) - } - } - }) - - return list + return append(list, x) } // includes reports whether typ is in list. @@ -146,6 +136,7 @@ func (check *Checker) completeInterface(pos token.Pos, ityp *Interface) { completeInterface(check, pos, ityp) } +// completeInterface may be called with check == nil. func completeInterface(check *Checker, pos token.Pos, ityp *Interface) { assert(ityp.allMethods == nil) @@ -198,6 +189,7 @@ func completeInterface(check *Checker, pos token.Pos, ityp *Interface) { if check == nil { panic(fmt.Sprintf("%v: duplicate method %s", m.pos, m.name)) } + // check != nil check.errorf(atPos(pos), _DuplicateDecl, "duplicate method %s", m.name) check.errorf(atPos(mpos[other.(*Func)]), _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented default: @@ -211,6 +203,7 @@ func completeInterface(check *Checker, pos token.Pos, ityp *Interface) { todo = append(todo, m, other.(*Func)) break } + // check != nil check.later(func() { if !check.allowVersion(m.pkg, 1, 14) || !check.identical(m.typ, other.Type()) { check.errorf(atPos(pos), _DuplicateDecl, "duplicate method %s", m.name) @@ -224,9 +217,8 @@ func completeInterface(check *Checker, pos token.Pos, ityp *Interface) { addMethod(m.pos, m, true) } - // collect types - allTypes := ityp.types - + // collect embedded elements + var allTypes Type var posList []token.Pos if check != nil { posList = check.posMap[ityp] @@ -236,32 +228,36 @@ func completeInterface(check *Checker, pos token.Pos, ityp *Interface) { if posList != nil { pos = posList[i] } - utyp := under(typ) - etyp := asInterface(utyp) - if etyp == nil { - if utyp != Typ[Invalid] { - var format string - if _, ok := utyp.(*_TypeParam); ok { - format = "%s is a type parameter, not an interface" - } else { - format = "%s is not an interface" - } - if check != nil { - // TODO: correct error code. - check.errorf(atPos(pos), _InvalidIfaceEmbed, format, typ) - } else { - panic(fmt.Sprintf(format, typ)) - } + var types Type + switch t := under(typ).(type) { + case *Interface: + if t.allMethods == nil { + completeInterface(check, pos, t) } - continue - } - if etyp.allMethods == nil { - completeInterface(check, pos, etyp) - } - for _, m := range etyp.allMethods { - addMethod(pos, m, false) // use embedding position pos rather than m.pos + for _, m := range t.allMethods { + addMethod(pos, m, false) // use embedding position pos rather than m.pos + + } + types = t.allTypes + case *Union: + types = NewSum(t.terms) + case *TypeParam: + if check != nil && !check.allowVersion(check.pkg, 1, 18) { + check.errorf(atPos(pos), _InvalidIfaceEmbed, "%s is a type parameter, not an interface", typ) + continue + } + types = t + default: + if t == Typ[Invalid] { + continue + } + if check != nil && !check.allowVersion(check.pkg, 1, 18) { + check.errorf(atPos(pos), _InvalidIfaceEmbed, "%s is not an interface", typ) + continue + } + types = t } - allTypes = intersect(allTypes, etyp.allTypes) + allTypes = intersect(allTypes, types) } // process todo's (this only happens if check == nil) @@ -281,7 +277,7 @@ func completeInterface(check *Checker, pos token.Pos, ityp *Interface) { } // intersect computes the intersection of the types x and y. -// Note: A incomming nil type stands for the top type. A top +// Note: An incomming nil type stands for the top type. A top // type result is returned as nil. func intersect(x, y Type) (r Type) { defer func() { diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 7bb026414f..a72c0dc1fd 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -288,6 +288,9 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { return true } + case *Union: + panic("identical0 not implemented for union types") + case *Interface: // Two interface types are identical if they have the same set of methods with // the same names and identical function types. Lower-case method names from diff --git a/src/go/types/sanitize.go b/src/go/types/sanitize.go index 88fc3f8377..b9fd56001d 100644 --- a/src/go/types/sanitize.go +++ b/src/go/types/sanitize.go @@ -110,11 +110,11 @@ func (s sanitizer) typ(typ Type) Type { case *_Sum: s.typeList(t.types) + case *Union: + s.typeList(t.terms) + case *Interface: s.funcList(t.methods) - if types := s.typ(t.types); types != t.types { - t.types = types - } s.typeList(t.embeddeds) s.funcList(t.allMethods) if allTypes := s.typ(t.allTypes); allTypes != t.allTypes { diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index 3af9079a85..7454831843 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -27,7 +27,8 @@ func TestSizeof(t *testing.T) { {Tuple{}, 12, 24}, {Signature{}, 44, 88}, {_Sum{}, 12, 24}, - {Interface{}, 60, 120}, + {Union{}, 24, 48}, + {Interface{}, 52, 104}, {Map{}, 16, 32}, {Chan{}, 12, 24}, {Named{}, 68, 136}, diff --git a/src/go/types/sizes.go b/src/go/types/sizes.go index 67052bb816..ae5d765a89 100644 --- a/src/go/types/sizes.go +++ b/src/go/types/sizes.go @@ -150,6 +150,8 @@ func (s *StdSizes) Sizeof(T Type) int64 { return offsets[n-1] + s.Sizeof(t.fields[n-1].typ) case *_Sum: panic("Sizeof unimplemented for type sum") + case *Union: + panic("Sizeof unimplemented for type union") case *Interface: return s.WordSize * 2 } diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 47b0c279db..d79c07a2fc 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -311,15 +311,19 @@ func (subst *subster) typ(typ Type) Type { return _NewSum(types) } + case *Union: + terms, copied := subst.typeList(t.terms) + if copied { + // TODO(gri) Do we need to remove duplicates that may have + // crept in after substitution? It may not matter. + return newUnion(terms, t.tilde) + } + case *Interface: methods, mcopied := subst.funcList(t.methods) - types := t.types - if t.types != nil { - types = subst.typ(t.types) - } embeddeds, ecopied := subst.typeList(t.embeddeds) - if mcopied || types != t.types || ecopied { - iface := &Interface{methods: methods, types: types, embeddeds: embeddeds} + if mcopied || ecopied { + iface := &Interface{methods: methods, embeddeds: embeddeds} if subst.check == nil { panic("internal error: cannot instantiate interfaces yet") } diff --git a/src/go/types/testdata/check/decls0.src b/src/go/types/testdata/check/decls0.src index 09904bb303..1224e46377 100644 --- a/src/go/types/testdata/check/decls0.src +++ b/src/go/types/testdata/check/decls0.src @@ -4,7 +4,7 @@ // type declarations -package decls0 +package go1_17 // don't permit non-interface elements in interfaces import "unsafe" diff --git a/src/go/types/testdata/check/issues.src b/src/go/types/testdata/check/issues.src index e2ac06759b..9d9fc7862f 100644 --- a/src/go/types/testdata/check/issues.src +++ b/src/go/types/testdata/check/issues.src @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package issues +package go1_17 // don't permit non-interface elements in interfaces import ( "fmt" diff --git a/src/go/types/testdata/check/typeinst2.go2 b/src/go/types/testdata/check/typeinst2.go2 index 6e2104a515..1096bb42eb 100644 --- a/src/go/types/testdata/check/typeinst2.go2 +++ b/src/go/types/testdata/check/typeinst2.go2 @@ -164,12 +164,12 @@ type _ interface { // for them to be all in a single list, and we report the error // as well.) type _ interface { - type int, int /* ERROR duplicate type int */ - type /* ERROR multiple type lists */ int /* ERROR duplicate type int */ + type int, int /* ERROR duplicate term int */ + type /* ERROR multiple type lists */ int /* ERROR duplicate term int */ } type _ interface { - type struct{f int}, struct{g int}, struct /* ERROR duplicate type */ {f int} + type struct{f int}, struct{g int}, struct /* ERROR duplicate term */ {f int} } // Interface type lists can contain any type, incl. *Named types. diff --git a/src/go/types/testdata/examples/constraints.go2 b/src/go/types/testdata/examples/constraints.go2 new file mode 100644 index 0000000000..e8b3912884 --- /dev/null +++ b/src/go/types/testdata/examples/constraints.go2 @@ -0,0 +1,25 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file shows some examples of generic constraint interfaces. + +package p + +type ( + // Arbitrary types may be embedded like interfaces. + _ interface{int} + _ interface{~int} + + // Types may be combined into a union. + _ interface{int|~string} + + // Union terms must be unique independent of whether they are ~ or not. + _ interface{int|int /* ERROR duplicate term int */ } + _ interface{int|~ /* ERROR duplicate term int */ int } + _ interface{~int|~ /* ERROR duplicate term int */ int } + + // For now we do not permit interfaces with ~ or in unions. + _ interface{~ /* ERROR cannot use interface */ interface{}} + _ interface{int|interface /* ERROR cannot use interface */ {}} +) diff --git a/src/go/types/testdata/fixedbugs/issue39634.go2 b/src/go/types/testdata/fixedbugs/issue39634.go2 index a13ed13ce5..c759be0d93 100644 --- a/src/go/types/testdata/fixedbugs/issue39634.go2 +++ b/src/go/types/testdata/fixedbugs/issue39634.go2 @@ -36,7 +36,7 @@ func bar8[A foo8[A]](a A) {} func main8() {} // crash 9 -type foo9[A any] interface { type foo9 /* ERROR interface contains type constraints */ [A] } +type foo9[A any] interface { type foo9 /* ERROR cannot use interface */ [A] } func _() { var _ = new(foo9 /* ERROR interface contains type constraints */ [int]) } // crash 12 diff --git a/src/go/types/testdata/fixedbugs/issue39693.go2 b/src/go/types/testdata/fixedbugs/issue39693.go2 index 316ab1982e..ec7641902a 100644 --- a/src/go/types/testdata/fixedbugs/issue39693.go2 +++ b/src/go/types/testdata/fixedbugs/issue39693.go2 @@ -4,11 +4,20 @@ package p -type Number interface { - int /* ERROR int is not an interface */ - float64 /* ERROR float64 is not an interface */ +type Number1 interface { + // embedding non-interface types is permitted + int + float64 } -func Add[T Number](a, b T) T { +func Add[T Number1](a, b T) T { return a /* ERROR not defined */ + b } + +type Number2 interface { + int|float64 +} + +func Add2[T Number2](a, b T) T { + return a + b +} diff --git a/src/go/types/testdata/fixedbugs/issue39711.go2 b/src/go/types/testdata/fixedbugs/issue39711.go2 index df621a4c17..cf1f90545f 100644 --- a/src/go/types/testdata/fixedbugs/issue39711.go2 +++ b/src/go/types/testdata/fixedbugs/issue39711.go2 @@ -7,5 +7,7 @@ package p // Do not report a duplicate type error for this type list. // (Check types after interfaces have been completed.) type _ interface { - type interface{ Error() string }, interface{ String() string } + // TODO(rfindley) Once we have full type sets we can enable this again. + // Fow now we don't permit interfaces in type lists. + // type interface{ Error() string }, interface{ String() string } } diff --git a/src/go/types/testdata/fixedbugs/issue39723.go2 b/src/go/types/testdata/fixedbugs/issue39723.go2 index 55464e6b77..61bc606789 100644 --- a/src/go/types/testdata/fixedbugs/issue39723.go2 +++ b/src/go/types/testdata/fixedbugs/issue39723.go2 @@ -6,4 +6,4 @@ package p // A constraint must be an interface; it cannot // be a type parameter, for instance. -func _[A interface{ type interface{} }, B A /* ERROR not an interface */ ]() +func _[A interface{ type int }, B A /* ERROR not an interface */ ]() diff --git a/src/go/types/testdata/fixedbugs/issue39948.go2 b/src/go/types/testdata/fixedbugs/issue39948.go2 index c2b460902c..d83084b52a 100644 --- a/src/go/types/testdata/fixedbugs/issue39948.go2 +++ b/src/go/types/testdata/fixedbugs/issue39948.go2 @@ -2,7 +2,13 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package p +// TODO(rfindley) Eventually, once we disallow type lists, we need to +// adjust this code: for 1.17 we don't accept type parameters, +// and for 1.18 this code is valid. +// Leaving for now so we can see that existing errors +// are being reported. + +package go1_17 // don't permit non-interface elements in interfaces type T[P any] interface{ P // ERROR P is a type parameter, not an interface diff --git a/src/go/types/type.go b/src/go/types/type.go index 4a39499905..d487bf66f9 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -305,7 +305,6 @@ func (s *_Sum) is(pred func(Type) bool) bool { // An Interface represents an interface type. type Interface struct { methods []*Func // ordered list of explicitly declared methods - types Type // (possibly a Sum) type declared with a type list (TODO(gri) need better field name) embeddeds []Type // ordered list of explicitly embedded types allMethods []*Func // ordered list of methods declared with or embedded in this interface (TODO(gri): replace with mset) diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index ff93f3b3c3..9e860dda22 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -159,11 +159,17 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { writeSignature(buf, t, qf, visited) case *_Sum: - for i, t := range t.types { + writeTypeList(buf, t.types, qf, visited) + + case *Union: + for i, e := range t.terms { if i > 0 { - buf.WriteString(", ") + buf.WriteString("|") } - writeType(buf, t, qf, visited) + if t.tilde[i] { + buf.WriteByte('~') + } + writeType(buf, e, qf, visited) } case *Interface: @@ -208,14 +214,6 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { writeSignature(buf, m.typ.(*Signature), qf, visited) empty = false } - if !empty && t.types != nil { - buf.WriteString("; ") - } - if t.types != nil { - buf.WriteString("type ") - writeType(buf, t.types, qf, visited) - empty = false - } if !empty && len(t.embeddeds) > 0 { buf.WriteString("; ") } @@ -301,6 +299,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { default: // For externally defined implementations of Type. + // Note: In this case cycles won't be caught. buf.WriteString(t.String()) } } diff --git a/src/go/types/typestring_test.go b/src/go/types/typestring_test.go index 55ee4b987f..0e35a3dbf1 100644 --- a/src/go/types/typestring_test.go +++ b/src/go/types/typestring_test.go @@ -95,6 +95,9 @@ var independentTestTypes = []testEntry{ dup("interface{}"), dup("interface{m()}"), dup(`interface{String() string; m(int) float32}`), + {"interface{type int, float32, complex128}", "interface{~int|~float32|~complex128}"}, + dup("interface{int|float32|complex128}"), + dup("interface{int|~float32|~complex128}"), // TODO(rFindley) uncomment this once this AST is accepted, and add more test // cases. diff --git a/src/go/types/unify.go b/src/go/types/unify.go index db06e21cf7..4b541df4cd 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -356,6 +356,10 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { // This should not happen with the current internal use of sum types. panic("type inference across sum types not implemented") + case *Union: + // This should not happen with the current internal use of union types. + panic("type inference across union types not implemented") + case *Interface: // Two interface types are identical if they have the same set of methods with // the same names and identical function types. Lower-case method names from diff --git a/src/go/types/union.go b/src/go/types/union.go new file mode 100644 index 0000000000..0df200c67b --- /dev/null +++ b/src/go/types/union.go @@ -0,0 +1,108 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +import ( + "go/ast" + "go/token" +) + +// ---------------------------------------------------------------------------- +// API + +// A Union represents a union of terms. +// A term is a type, possibly with a ~ (tilde) indication. +type Union struct { + terms []Type // terms are unique + tilde []bool // if tilde[i] is set, terms[i] is of the form ~T +} + +func NewUnion(terms []Type, tilde []bool) Type { return newUnion(terms, tilde) } + +func (u *Union) NumTerms() int { return len(u.terms) } +func (u *Union) Term(i int) (Type, bool) { return u.terms[i], u.tilde[i] } + +func (u *Union) Underlying() Type { return u } +func (u *Union) String() string { return TypeString(u, nil) } + +// ---------------------------------------------------------------------------- +// Implementation + +func newUnion(terms []Type, tilde []bool) Type { + assert(len(terms) == len(tilde)) + if terms == nil { + return nil + } + t := new(Union) + t.terms = terms + t.tilde = tilde + return t +} + +func parseUnion(check *Checker, tlist []ast.Expr) Type { + var terms []Type + var tilde []bool + for _, x := range tlist { + t, d := parseTilde(check, x) + if len(tlist) == 1 && !d { + return t // single type + } + terms = append(terms, t) + tilde = append(tilde, d) + } + + // Ensure that each type is only present once in the type list. + // It's ok to do this check at the end because it's not a requirement + // for correctness of the code. + // Note: This is a quadratic algorithm, but unions tend to be short. + check.later(func() { + for i, t := range terms { + t := expand(t) + if t == Typ[Invalid] { + continue + } + + x := tlist[i] + pos := x.Pos() + // We may not know the position of x if it was a typechecker- + // introduced ~T type of a type list entry T. Use the position + // of T instead. + // TODO(rfindley) remove this test once we don't support type lists anymore + if !pos.IsValid() { + if op, _ := x.(*ast.UnaryExpr); op != nil { + pos = op.X.Pos() + } + } + + u := under(t) + if tilde[i] { + // TODO(rfindley) enable this check once we have converted tests + // if !Identical(u, t) { + // check.errorf(x, "invalid use of ~ (underlying type of %s is %s)", t, u) + // } + } + if _, ok := u.(*Interface); ok { + check.errorf(atPos(pos), _Todo, "cannot use interface %s with ~ or inside a union (implementation restriction)", t) + } + + // Complain about duplicate entries a|a, but also a|~a, and ~a|~a. + if includes(terms[:i], t) { + // TODO(rfindley) this currently doesn't print the ~ if present + check.softErrorf(atPos(pos), _Todo, "duplicate term %s in union element", t) + } + } + }) + + return newUnion(terms, tilde) +} + +func parseTilde(check *Checker, x ast.Expr) (Type, bool) { + tilde := false + if op, _ := x.(*ast.UnaryExpr); op != nil && op.Op == token.TILDE { + x = op.X + tilde = true + } + return check.anyType(x), tilde +} -- GitLab From c7a460526eb20752d92fef0456852a3e64bc47a0 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Wed, 9 Jun 2021 18:15:10 -0400 Subject: [PATCH 0286/2500] [dev.typeparams] go/types: replace Sum type with Union type This is a straightforward port of CL 323274 to go/types. Change-Id: Ica769d90fd482703f260f105199d2f2229498e95 Reviewed-on: https://go-review.googlesource.com/c/go/+/326677 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/api_typeparams.go | 3 - src/go/types/builtins.go | 16 +++-- src/go/types/expr.go | 4 +- src/go/types/index.go | 18 +++--- src/go/types/infer.go | 5 +- src/go/types/interface.go | 50 +++------------ src/go/types/operand.go | 19 +++++- src/go/types/predicates.go | 35 +++++------ src/go/types/sanitize.go | 5 +- src/go/types/sizeof_test.go | 1 - src/go/types/sizes.go | 4 +- src/go/types/stmt.go | 6 +- src/go/types/subst.go | 18 ++---- src/go/types/type.go | 72 +++++---------------- src/go/types/typestring.go | 5 +- src/go/types/unify.go | 4 -- src/go/types/union.go | 111 ++++++++++++++++++++++++++++----- 17 files changed, 185 insertions(+), 191 deletions(-) diff --git a/src/go/types/api_typeparams.go b/src/go/types/api_typeparams.go index 25fb3fa781..6aaefbb6b2 100644 --- a/src/go/types/api_typeparams.go +++ b/src/go/types/api_typeparams.go @@ -10,12 +10,9 @@ import ( type ( Inferred = _Inferred - Sum = _Sum TypeParam = _TypeParam ) -func NewSum(types []Type) Type { return _NewSum(types) } - // NewTypeParam returns a new TypeParam. func NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam { return (*Checker)(nil).newTypeParam(obj, index, bound) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 99122dfe7c..92807ed44a 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -179,9 +179,9 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b mode = value } - case *_Sum: - if t.is(func(t Type) bool { - switch t := under(t).(type) { + case *Union: + if t.underIs(func(t Type) bool { + switch t := t.(type) { case *Basic: if isString(t) && id == _Len { return true @@ -469,8 +469,8 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b m = 2 case *Map, *Chan: m = 1 - case *_Sum: - return t.is(valid) + case *Union: + return t.underIs(valid) default: return false } @@ -768,10 +768,14 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { if tp := asTypeParam(x); tp != nil { // Test if t satisfies the requirements for the argument // type and collect possible result types at the same time. + // TODO(gri) This needs to consider the ~ information if we + // have a union type. var rtypes []Type + var tilde []bool if !tp.Bound().is(func(x Type) bool { if r := f(x); r != nil { rtypes = append(rtypes, r) + tilde = append(tilde, true) return true } return false @@ -782,7 +786,7 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { // construct a suitable new type parameter tpar := NewTypeName(token.NoPos, nil /* = Universe pkg */, "", nil) ptyp := check.newTypeParam(tpar, 0, &emptyInterface) // assigns type to tpar as a side-effect - tsum := _NewSum(rtypes) + tsum := newUnion(rtypes, tilde) ptyp.bound = &Interface{allMethods: markComplete, allTypes: tsum} return ptyp diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 5c65fad447..b7cc6e8ae7 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -661,8 +661,8 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const default: return nil, nil, _InvalidUntypedConversion } - case *_Sum: - ok := t.is(func(t Type) bool { + case *Union: + ok := t.underIs(func(t Type) bool { target, _, _ := check.implicitTypeAndValue(x, t) return target != nil }) diff --git a/src/go/types/index.go b/src/go/types/index.go index 2ba3475f89..5bc1d0af8d 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -91,15 +91,15 @@ func (check *Checker) indexExpr(x *operand, e *ast.IndexExpr) (isFuncInst bool) x.expr = e return - case *_Sum: - // A sum type can be indexed if all of the sum's types + case *Union: + // A union type can be indexed if all of the union's terms // support indexing and have the same index and element - // type. Special rules apply for maps in the sum type. + // type. Special rules apply for maps in the union type. var tkey, telem Type // key is for map types only - nmaps := 0 // number of map types in sum type - if typ.is(func(t Type) bool { + nmaps := 0 // number of map types in union type + if typ.underIs(func(t Type) bool { var e Type - switch t := under(t).(type) { + switch t := t.(type) { case *Basic: if isString(t) { e = universeByte @@ -113,7 +113,7 @@ func (check *Checker) indexExpr(x *operand, e *ast.IndexExpr) (isFuncInst bool) case *Slice: e = t.elem case *Map: - // If there are multiple maps in the sum type, + // If there are multiple maps in the union type, // they must have identical key types. // TODO(gri) We may be able to relax this rule // but it becomes complicated very quickly. @@ -148,7 +148,7 @@ func (check *Checker) indexExpr(x *operand, e *ast.IndexExpr) (isFuncInst bool) // ok to continue even if indexing failed - map element type is known // If there are only maps, we are done. - if nmaps == len(typ.types) { + if nmaps == typ.NumTerms() { x.mode = mapindex x.typ = telem x.expr = e @@ -246,7 +246,7 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { valid = true // x.typ doesn't change - case *_Sum, *_TypeParam: + case *Union, *_TypeParam: check.errorf(x, 0, "generic slice expressions not yet implemented") x.mode = invalid return diff --git a/src/go/types/infer.go b/src/go/types/infer.go index 951c6b8cbd..ddf02a3942 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -302,7 +302,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { } } - case *_Sum: + case *Union: return w.isParameterizedList(t.types) case *Signature: @@ -315,9 +315,6 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { // Thus, we only need to look at the input and result parameters. return w.isParameterized(t.params) || w.isParameterized(t.results) - case *Union: - panic("unimplemented") - case *Interface: if t.allMethods != nil { // TODO(rFindley) at some point we should enforce completeness here diff --git a/src/go/types/interface.go b/src/go/types/interface.go index 611f387046..2bbd2f135d 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -240,22 +240,26 @@ func completeInterface(check *Checker, pos token.Pos, ityp *Interface) { } types = t.allTypes case *Union: - types = NewSum(t.terms) + // TODO(gri) combine with default case once we have + // converted all tests to new notation and we + // can report an error when we don't have an + // interface before go1.18. + types = typ case *TypeParam: if check != nil && !check.allowVersion(check.pkg, 1, 18) { check.errorf(atPos(pos), _InvalidIfaceEmbed, "%s is a type parameter, not an interface", typ) continue } - types = t + types = typ default: - if t == Typ[Invalid] { + if typ == Typ[Invalid] { continue } if check != nil && !check.allowVersion(check.pkg, 1, 18) { check.errorf(atPos(pos), _InvalidIfaceEmbed, "%s is not an interface", typ) continue } - types = t + types = typ } allTypes = intersect(allTypes, types) } @@ -276,44 +280,6 @@ func completeInterface(check *Checker, pos token.Pos, ityp *Interface) { ityp.allTypes = allTypes } -// intersect computes the intersection of the types x and y. -// Note: An incomming nil type stands for the top type. A top -// type result is returned as nil. -func intersect(x, y Type) (r Type) { - defer func() { - if r == theTop { - r = nil - } - }() - - switch { - case x == theBottom || y == theBottom: - return theBottom - case x == nil || x == theTop: - return y - case y == nil || x == theTop: - return x - } - - xtypes := unpackType(x) - ytypes := unpackType(y) - // Compute the list rtypes which includes only - // types that are in both xtypes and ytypes. - // Quadratic algorithm, but good enough for now. - // TODO(gri) fix this - var rtypes []Type - for _, x := range xtypes { - if includes(ytypes, x) { - rtypes = append(rtypes, x) - } - } - - if rtypes == nil { - return theBottom - } - return _NewSum(rtypes) -} - func sortTypes(list []Type) { sort.Stable(byUniqueTypeName(list)) } diff --git a/src/go/types/operand.go b/src/go/types/operand.go index 6463728cec..81dc66e800 100644 --- a/src/go/types/operand.go +++ b/src/go/types/operand.go @@ -233,6 +233,12 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er V := x.typ + const debugAssignableTo = false + if debugAssignableTo && check != nil { + check.dump("V = %s", V) + check.dump("T = %s", T) + } + // x's type is identical to T if check.identical(V, T) { return true, 0 @@ -241,11 +247,20 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er Vu := optype(V) Tu := optype(T) + if debugAssignableTo && check != nil { + check.dump("Vu = %s", Vu) + check.dump("Tu = %s", Tu) + } + // x is an untyped value representable by a value of type T. if isUntyped(Vu) { - if t, ok := Tu.(*_Sum); ok { - return t.is(func(t Type) bool { + if t, ok := Tu.(*Union); ok { + return t.is(func(t Type, tilde bool) bool { // TODO(gri) this could probably be more efficient + if tilde { + // TODO(gri) We need to check assignability + // for the underlying type of x. + } ok, _ := x.assignableTo(check, t, reason) return ok }), _IncompatibleAssign diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index a72c0dc1fd..78dba6d3e0 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -32,8 +32,8 @@ func is(typ Type, what BasicInfo) bool { switch t := optype(typ).(type) { case *Basic: return t.info&what != 0 - case *_Sum: - return t.is(func(typ Type) bool { return is(typ, what) }) + case *Union: + return t.underIs(func(typ Type) bool { return is(typ, what) }) } return false } @@ -128,11 +128,10 @@ func comparable(T Type, seen map[Type]bool) bool { return true case *Array: return comparable(t.elem, seen) - case *_Sum: - pred := func(t Type) bool { + case *Union: + return t.underIs(func(t Type) bool { return comparable(t, seen) - } - return t.is(pred) + }) case *_TypeParam: return t.Bound()._IsComparable() } @@ -146,8 +145,8 @@ func hasNil(typ Type) bool { return t.kind == UnsafePointer case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan: return true - case *_Sum: - return t.is(hasNil) + case *Union: + return t.underIs(hasNil) } return false } @@ -265,21 +264,20 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { check.identical0(x.results, y.results, cmpTags, p) } - case *_Sum: - // Two sum types are identical if they contain the same types. - // (Sum types always consist of at least two types. Also, the - // the set (list) of types in a sum type consists of unique - // types - each type appears exactly once. Thus, two sum types + case *Union: + // Two union types are identical if they contain the same terms. + // The set (list) of types in a union type consists of unique + // types - each type appears exactly once. Thus, two union types // must contain the same number of types to have chance of // being equal. - if y, ok := y.(*_Sum); ok && len(x.types) == len(y.types) { + if y, ok := y.(*Union); ok && x.NumTerms() == y.NumTerms() { // Every type in x.types must be in y.types. // Quadratic algorithm, but probably good enough for now. // TODO(gri) we need a fast quick type ID/hash for all types. L: - for _, x := range x.types { - for _, y := range y.types { - if Identical(x, y) { + for i, xt := range x.types { + for j, yt := range y.types { + if Identical(xt, yt) && x.tilde[i] == y.tilde[j] { continue L // x is in y.types } } @@ -288,9 +286,6 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { return true } - case *Union: - panic("identical0 not implemented for union types") - case *Interface: // Two interface types are identical if they have the same set of methods with // the same names and identical function types. Lower-case method names from diff --git a/src/go/types/sanitize.go b/src/go/types/sanitize.go index b9fd56001d..2d70060899 100644 --- a/src/go/types/sanitize.go +++ b/src/go/types/sanitize.go @@ -107,11 +107,8 @@ func (s sanitizer) typ(typ Type) Type { s.tuple(t.params) s.tuple(t.results) - case *_Sum: - s.typeList(t.types) - case *Union: - s.typeList(t.terms) + s.typeList(t.types) case *Interface: s.funcList(t.methods) diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index 7454831843..3e79499ea5 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -26,7 +26,6 @@ func TestSizeof(t *testing.T) { {Pointer{}, 8, 16}, {Tuple{}, 12, 24}, {Signature{}, 44, 88}, - {_Sum{}, 12, 24}, {Union{}, 24, 48}, {Interface{}, 52, 104}, {Map{}, 16, 32}, diff --git a/src/go/types/sizes.go b/src/go/types/sizes.go index ae5d765a89..35219836ec 100644 --- a/src/go/types/sizes.go +++ b/src/go/types/sizes.go @@ -148,10 +148,8 @@ func (s *StdSizes) Sizeof(T Type) int64 { } offsets := s.Offsetsof(t.fields) return offsets[n-1] + s.Sizeof(t.fields[n-1].typ) - case *_Sum: - panic("Sizeof unimplemented for type sum") case *Union: - panic("Sizeof unimplemented for type union") + panic("Sizeof unimplemented for union") case *Interface: return s.WordSize * 2 } diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index 47f6dcfbd1..9dcaceaca7 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -911,12 +911,12 @@ func rangeKeyVal(typ Type, wantKey, wantVal bool) (Type, Type, string) { msg = "send-only channel" } return typ.elem, Typ[Invalid], msg - case *_Sum: + case *Union: first := true var key, val Type var msg string - typ.is(func(t Type) bool { - k, v, m := rangeKeyVal(under(t), wantKey, wantVal) + typ.underIs(func(t Type) bool { + k, v, m := rangeKeyVal(t, wantKey, wantVal) if k == nil || m != "" { key, val, msg = k, v, m return false diff --git a/src/go/types/subst.go b/src/go/types/subst.go index d79c07a2fc..8cd8d0719b 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -302,21 +302,13 @@ func (subst *subster) typ(typ Type) Type { } } - case *_Sum: - types, copied := subst.typeList(t.types) - if copied { - // Don't do it manually, with a Sum literal: the new - // types list may not be unique and NewSum may remove - // duplicates. - return _NewSum(types) - } - case *Union: - terms, copied := subst.typeList(t.terms) + types, copied := subst.typeList(t.types) if copied { - // TODO(gri) Do we need to remove duplicates that may have - // crept in after substitution? It may not matter. - return newUnion(terms, t.tilde) + // TODO(gri) Remove duplicates that may have crept in after substitution + // (unlikely but possible). This matters for the Identical + // predicate on unions. + return newUnion(types, t.tilde) } case *Interface: diff --git a/src/go/types/type.go b/src/go/types/type.go index d487bf66f9..3b10fabbf8 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -255,53 +255,6 @@ func (s *Signature) Results() *Tuple { return s.results } // Variadic reports whether the signature s is variadic. func (s *Signature) Variadic() bool { return s.variadic } -// A _Sum represents a set of possible types. -// Sums are currently used to represent type lists of interfaces -// and thus the underlying types of type parameters; they are not -// first class types of Go. -type _Sum struct { - types []Type // types are unique -} - -// _NewSum returns a new Sum type consisting of the provided -// types if there are more than one. If there is exactly one -// type, it returns that type. If the list of types is empty -// the result is nil. -func _NewSum(types []Type) Type { - if len(types) == 0 { - return nil - } - - // What should happen if types contains a sum type? - // Do we flatten the types list? For now we check - // and panic. This should not be possible for the - // current use case of type lists. - // TODO(gri) Come up with the rules for sum types. - for _, t := range types { - if _, ok := t.(*_Sum); ok { - panic("sum type contains sum type - unimplemented") - } - } - - if len(types) == 1 { - return types[0] - } - return &_Sum{types: types} -} - -// is reports whether all types in t satisfy pred. -func (s *_Sum) is(pred func(Type) bool) bool { - if s == nil { - return false - } - for _, t := range s.types { - if !pred(t) { - return false - } - } - return true -} - // An Interface represents an interface type. type Interface struct { methods []*Func // ordered list of explicitly declared methods @@ -319,8 +272,8 @@ func unpackType(typ Type) []Type { if typ == nil { return nil } - if sum := asSum(typ); sum != nil { - return sum.types + if u := asUnion(typ); u != nil { + return u.types } return []Type{typ} } @@ -709,9 +662,16 @@ func optype(typ Type) Type { // for a type parameter list of the form: // (type T interface { type T }). // See also issue #39680. - if u := t.Bound().allTypes; u != nil && u != typ { - // u != typ and u is a type parameter => under(u) != typ, so this is ok - return under(u) + if a := t.Bound().allTypes; a != nil && a != typ { + // If we have a union with a single entry, ignore + // any tilde because under(~t) == under(t). + if u, _ := a.(*Union); u != nil && u.NumTerms() == 1 { + a = u.types[0] + } + if a != typ { + // a != typ and a is a type parameter => under(a) != typ, so this is ok + return under(a) + } } return theTop } @@ -793,7 +753,6 @@ func (t *Struct) Underlying() Type { return t } func (t *Pointer) Underlying() Type { return t } func (t *Tuple) Underlying() Type { return t } func (t *Signature) Underlying() Type { return t } -func (t *_Sum) Underlying() Type { return t } func (t *Interface) Underlying() Type { return t } func (t *Map) Underlying() Type { return t } func (t *Chan) Underlying() Type { return t } @@ -811,7 +770,6 @@ func (t *Struct) String() string { return TypeString(t, nil) } func (t *Pointer) String() string { return TypeString(t, nil) } func (t *Tuple) String() string { return TypeString(t, nil) } func (t *Signature) String() string { return TypeString(t, nil) } -func (t *_Sum) String() string { return TypeString(t, nil) } func (t *Interface) String() string { return TypeString(t, nil) } func (t *Map) String() string { return TypeString(t, nil) } func (t *Chan) String() string { return TypeString(t, nil) } @@ -826,7 +784,7 @@ func (t *top) String() string { return TypeString(t, nil) } // under must only be called when a type is known // to be fully set up. func under(t Type) Type { - // TODO(gri) is this correct for *Sum? + // TODO(gri) is this correct for *Union? if n := asNamed(t); n != nil { return n.under() } @@ -876,8 +834,8 @@ func asSignature(t Type) *Signature { return op } -func asSum(t Type) *_Sum { - op, _ := optype(t).(*_Sum) +func asUnion(t Type) *Union { + op, _ := optype(t).(*Union) return op } diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 9e860dda22..52c22f25d8 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -158,11 +158,8 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { buf.WriteString("func") writeSignature(buf, t, qf, visited) - case *_Sum: - writeTypeList(buf, t.types, qf, visited) - case *Union: - for i, e := range t.terms { + for i, e := range t.types { if i > 0 { buf.WriteString("|") } diff --git a/src/go/types/unify.go b/src/go/types/unify.go index 4b541df4cd..7c58c6c512 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -352,10 +352,6 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { u.nify(x.results, y.results, p) } - case *_Sum: - // This should not happen with the current internal use of sum types. - panic("type inference across sum types not implemented") - case *Union: // This should not happen with the current internal use of union types. panic("type inference across union types not implemented") diff --git a/src/go/types/union.go b/src/go/types/union.go index 0df200c67b..aa46b8ab9c 100644 --- a/src/go/types/union.go +++ b/src/go/types/union.go @@ -13,16 +13,16 @@ import ( // API // A Union represents a union of terms. -// A term is a type, possibly with a ~ (tilde) indication. +// A term is a type, possibly with a ~ (tilde) flag. type Union struct { - terms []Type // terms are unique + types []Type // types are unique tilde []bool // if tilde[i] is set, terms[i] is of the form ~T } -func NewUnion(terms []Type, tilde []bool) Type { return newUnion(terms, tilde) } +func NewUnion(types []Type, tilde []bool) Type { return newUnion(types, tilde) } -func (u *Union) NumTerms() int { return len(u.terms) } -func (u *Union) Term(i int) (Type, bool) { return u.terms[i], u.tilde[i] } +func (u *Union) NumTerms() int { return len(u.types) } +func (u *Union) Term(i int) (Type, bool) { return u.types[i], u.tilde[i] } func (u *Union) Underlying() Type { return u } func (u *Union) String() string { return TypeString(u, nil) } @@ -30,26 +30,52 @@ func (u *Union) String() string { return TypeString(u, nil) } // ---------------------------------------------------------------------------- // Implementation -func newUnion(terms []Type, tilde []bool) Type { - assert(len(terms) == len(tilde)) - if terms == nil { +func newUnion(types []Type, tilde []bool) Type { + assert(len(types) == len(tilde)) + if types == nil { return nil } t := new(Union) - t.terms = terms + t.types = types t.tilde = tilde return t } +// is reports whether f returned true for all terms (type, tilde) of u. +func (u *Union) is(f func(Type, bool) bool) bool { + if u == nil { + return false + } + for i, t := range u.types { + if !f(t, u.tilde[i]) { + return false + } + } + return true +} + +// is reports whether f returned true for the underlying types of all terms of u. +func (u *Union) underIs(f func(Type) bool) bool { + if u == nil { + return false + } + for _, t := range u.types { + if !f(under(t)) { + return false + } + } + return true +} + func parseUnion(check *Checker, tlist []ast.Expr) Type { - var terms []Type + var types []Type var tilde []bool for _, x := range tlist { t, d := parseTilde(check, x) if len(tlist) == 1 && !d { return t // single type } - terms = append(terms, t) + types = append(types, t) tilde = append(tilde, d) } @@ -58,7 +84,7 @@ func parseUnion(check *Checker, tlist []ast.Expr) Type { // for correctness of the code. // Note: This is a quadratic algorithm, but unions tend to be short. check.later(func() { - for i, t := range terms { + for i, t := range types { t := expand(t) if t == Typ[Invalid] { continue @@ -88,14 +114,14 @@ func parseUnion(check *Checker, tlist []ast.Expr) Type { } // Complain about duplicate entries a|a, but also a|~a, and ~a|~a. - if includes(terms[:i], t) { + if includes(types[:i], t) { // TODO(rfindley) this currently doesn't print the ~ if present check.softErrorf(atPos(pos), _Todo, "duplicate term %s in union element", t) } } }) - return newUnion(terms, tilde) + return newUnion(types, tilde) } func parseTilde(check *Checker, x ast.Expr) (Type, bool) { @@ -106,3 +132,60 @@ func parseTilde(check *Checker, x ast.Expr) (Type, bool) { } return check.anyType(x), tilde } + +// intersect computes the intersection of the types x and y. +// Note: An incomming nil type stands for the top type. A top +// type result is returned as nil. +func intersect(x, y Type) (r Type) { + defer func() { + if r == theTop { + r = nil + } + }() + + switch { + case x == theBottom || y == theBottom: + return theBottom + case x == nil || x == theTop: + return y + case y == nil || x == theTop: + return x + } + + // Compute the terms which are in both x and y. + xu, _ := x.(*Union) + yu, _ := y.(*Union) + switch { + case xu != nil && yu != nil: + // Quadratic algorithm, but good enough for now. + // TODO(gri) fix asymptotic performance + var types []Type + var tilde []bool + for _, y := range yu.types { + if includes(xu.types, y) { + types = append(types, y) + tilde = append(tilde, true) // TODO(gri) fix this + } + } + if types != nil { + return newUnion(types, tilde) + } + + case xu != nil: + if includes(xu.types, y) { + return y + } + + case yu != nil: + if includes(yu.types, x) { + return x + } + + default: // xu == nil && yu == nil + if Identical(x, y) { + return x + } + } + + return theBottom +} -- GitLab From aecfd5c29e3d8cb168c180f4e14e981c58eb599c Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Wed, 9 Jun 2021 18:31:55 -0400 Subject: [PATCH 0287/2500] [dev.typeparams] go/types: clean up type set/union intersection This is a straightforward port of CL 323354 to go/types. Change-Id: I53512540cc35df6e88b2b66e144e1be7ccc9a6f0 Reviewed-on: https://go-review.googlesource.com/c/go/+/326678 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/interface.go | 10 -- src/go/types/predicates.go | 11 +- src/go/types/sanitize.go | 2 +- src/go/types/sizeof_test.go | 1 - src/go/types/subst.go | 4 +- src/go/types/testdata/check/issues.go2 | 2 +- .../types/testdata/examples/constraints.go2 | 14 +++ src/go/types/type.go | 40 +++---- src/go/types/typestring.go | 7 +- src/go/types/union.go | 107 +++++++++++++----- 10 files changed, 119 insertions(+), 79 deletions(-) diff --git a/src/go/types/interface.go b/src/go/types/interface.go index 2bbd2f135d..9b4d080c81 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -111,16 +111,6 @@ func flattenUnion(list []ast.Expr, x ast.Expr) []ast.Expr { return append(list, x) } -// includes reports whether typ is in list. -func includes(list []Type, typ Type) bool { - for _, e := range list { - if Identical(typ, e) { - return true - } - } - return false -} - func (check *Checker) completeInterface(pos token.Pos, ityp *Interface) { if ityp.allMethods != nil { return diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 78dba6d3e0..6aa5825943 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -101,9 +101,9 @@ func comparable(T Type, seen map[Type]bool) bool { seen[T] = true // If T is a type parameter not constrained by any type - // list (i.e., it's underlying type is the top type), + // list (i.e., it's operational type is the top type), // T is comparable if it has the == method. Otherwise, - // the underlying type "wins". For instance + // the operational type "wins". For instance // // interface{ comparable; type []byte } // @@ -374,10 +374,9 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { // case *instance: // unreachable since types are expanded - case *bottom, *top: - // Either both types are theBottom, or both are theTop in which - // case the initial x == y check will have caught them. Otherwise - // they are not identical. + case *top: + // Either both types are theTop in which case the initial x == y check + // will have caught them. Otherwise they are not identical. case nil: // avoid a crash in case of nil type diff --git a/src/go/types/sanitize.go b/src/go/types/sanitize.go index 2d70060899..05e7d8b4bf 100644 --- a/src/go/types/sanitize.go +++ b/src/go/types/sanitize.go @@ -78,7 +78,7 @@ func (s sanitizer) typ(typ Type) Type { s[typ] = typ switch t := typ.(type) { - case *Basic, *bottom, *top: + case *Basic, *top: // nothing to do case *Array: diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index 3e79499ea5..9459f67769 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -33,7 +33,6 @@ func TestSizeof(t *testing.T) { {Named{}, 68, 136}, {_TypeParam{}, 28, 48}, {instance{}, 44, 88}, - {bottom{}, 0, 0}, {top{}, 0, 0}, // Objects diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 8cd8d0719b..24108993ef 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -210,7 +210,7 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *_TypeParam, smap // Otherwise, targ's type or underlying type must also be one of the interface types listed, if any. if !iface.isSatisfiedBy(targ) { - check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s not found in %s)", targ, tpar.bound, under(targ), iface.allTypes) + check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s not found in %s)", targ, tpar.bound, targ, iface.allTypes) return false } @@ -253,7 +253,7 @@ func (subst *subster) typ(typ Type) Type { // Call typOrNil if it's possible that typ is nil. panic("nil typ") - case *Basic, *bottom, *top: + case *Basic, *top: // nothing to do case *Array: diff --git a/src/go/types/testdata/check/issues.go2 b/src/go/types/testdata/check/issues.go2 index 8994164eac..0a7648cba1 100644 --- a/src/go/types/testdata/check/issues.go2 +++ b/src/go/types/testdata/check/issues.go2 @@ -241,7 +241,7 @@ func _[T interface{ type func() }](f T) { type sliceOf[E any] interface{ type []E } -func append[T interface{}, S sliceOf[T], T2 interface{ type T }](s S, t ...T2) S +func append[T interface{}, S sliceOf[T], T2 interface{ T }](s S, t ...T2) S var f func() var cancelSlice []context.CancelFunc diff --git a/src/go/types/testdata/examples/constraints.go2 b/src/go/types/testdata/examples/constraints.go2 index e8b3912884..f6291ccf7d 100644 --- a/src/go/types/testdata/examples/constraints.go2 +++ b/src/go/types/testdata/examples/constraints.go2 @@ -23,3 +23,17 @@ type ( _ interface{~ /* ERROR cannot use interface */ interface{}} _ interface{int|interface /* ERROR cannot use interface */ {}} ) + +// Multiple embedded union elements are intersected. The order in which they +// appear in the interface doesn't matter since intersection is a symmetric +// operation. + +type myInt1 int +type myInt2 int + +func _[T interface{ myInt1|myInt2; ~int }]() T { return T(0) } +func _[T interface{ ~int; myInt1|myInt2 }]() T { return T(0) } + +// Here the intersections are empty - there's no type that's in the type set of T. +func _[T interface{ myInt1|myInt2; int }]() T { return T(0 /* ERROR cannot convert */ ) } +func _[T interface{ int; myInt1|myInt2 }]() T { return T(0 /* ERROR cannot convert */ ) } diff --git a/src/go/types/type.go b/src/go/types/type.go index 3b10fabbf8..8a4544e497 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -383,7 +383,6 @@ func (t *Interface) Method(i int) *Func { t.Complete(); return t.allMethods[i] } // Empty reports whether t is the empty interface. func (t *Interface) Empty() bool { t.Complete() - // A non-nil allTypes may still have length 0 but represents the bottom type. return len(t.allMethods) == 0 && t.allTypes == nil } @@ -438,11 +437,15 @@ func (t *Interface) iterate(f func(*Interface) bool, seen map[*Interface]bool) b // "implements" predicate. func (t *Interface) isSatisfiedBy(typ Type) bool { t.Complete() - if t.allTypes == nil { - return true + switch t := t.allTypes.(type) { + case nil: + return true // no type restrictions + case *Union: + r, _ := t.intersect(typ, false) + return r != nil + default: + return Identical(t, typ) } - types := unpackType(t.allTypes) - return includes(types, typ) || includes(types, under(typ)) } // Complete computes the interface's method set. It must be called by users of @@ -647,13 +650,11 @@ func (t *_TypeParam) Bound() *Interface { return iface } -// optype returns a type's operational type. Except for -// type parameters, the operational type is the same -// as the underlying type (as returned by under). For -// Type parameters, the operational type is determined -// by the corresponding type bound's type list. The -// result may be the bottom or top type, but it is never -// the incoming type parameter. +// optype returns a type's operational type. Except for type parameters, +// the operational type is the same as the underlying type (as returned +// by under). For Type parameters, the operational type is determined +// by the corresponding type constraint. The result may be the top type, +// but it is never the incoming type parameter. func optype(typ Type) Type { if t := asTypeParam(typ); t != nil { // If the optype is typ, return the top type as we have @@ -726,20 +727,11 @@ var expandf func(Type) Type func init() { expandf = expand } -// bottom represents the bottom of the type lattice. -// It is the underlying type of a type parameter that -// cannot be satisfied by any type, usually because -// the intersection of type constraints left nothing). -type bottom struct{} - -// theBottom is the singleton bottom type. -var theBottom = &bottom{} - // top represents the top of the type lattice. // It is the underlying type of a type parameter that // can be satisfied by any type (ignoring methods), -// usually because the type constraint has no type -// list. +// because its type constraint contains no restrictions +// besides methods. type top struct{} // theTop is the singleton top type. @@ -759,7 +751,6 @@ func (t *Chan) Underlying() Type { return t } func (t *Named) Underlying() Type { return t.underlying } func (t *_TypeParam) Underlying() Type { return t } func (t *instance) Underlying() Type { return t } -func (t *bottom) Underlying() Type { return t } func (t *top) Underlying() Type { return t } // Type-specific implementations of String. @@ -776,7 +767,6 @@ func (t *Chan) String() string { return TypeString(t, nil) } func (t *Named) String() string { return TypeString(t, nil) } func (t *_TypeParam) String() string { return TypeString(t, nil) } func (t *instance) String() string { return TypeString(t, nil) } -func (t *bottom) String() string { return TypeString(t, nil) } func (t *top) String() string { return TypeString(t, nil) } // under returns the true expanded underlying type. diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 52c22f25d8..73465a35b7 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -159,6 +159,10 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { writeSignature(buf, t, qf, visited) case *Union: + if t.IsEmpty() { + buf.WriteString("⊥") + break + } for i, e := range t.types { if i > 0 { buf.WriteString("|") @@ -288,9 +292,6 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { writeTypeList(buf, t.targs, qf, visited) buf.WriteByte(']') - case *bottom: - buf.WriteString("⊥") - case *top: buf.WriteString("⊤") diff --git a/src/go/types/union.go b/src/go/types/union.go index aa46b8ab9c..4eda874eb8 100644 --- a/src/go/types/union.go +++ b/src/go/types/union.go @@ -13,14 +13,18 @@ import ( // API // A Union represents a union of terms. -// A term is a type, possibly with a ~ (tilde) flag. +// A term is a type with a ~ (tilde) flag. type Union struct { types []Type // types are unique tilde []bool // if tilde[i] is set, terms[i] is of the form ~T } -func NewUnion(types []Type, tilde []bool) Type { return newUnion(types, tilde) } +// NewUnion returns a new Union type with the given terms (types[i], tilde[i]). +// The lengths of both arguments must match. An empty union represents the set +// of no types. +func NewUnion(types []Type, tilde []bool) *Union { return newUnion(types, tilde) } +func (u *Union) IsEmpty() bool { return len(u.types) == 0 } func (u *Union) NumTerms() int { return len(u.types) } func (u *Union) Term(i int) (Type, bool) { return u.types[i], u.tilde[i] } @@ -30,10 +34,12 @@ func (u *Union) String() string { return TypeString(u, nil) } // ---------------------------------------------------------------------------- // Implementation -func newUnion(types []Type, tilde []bool) Type { +var emptyUnion = new(Union) + +func newUnion(types []Type, tilde []bool) *Union { assert(len(types) == len(tilde)) - if types == nil { - return nil + if len(types) == 0 { + return emptyUnion } t := new(Union) t.types = types @@ -43,7 +49,7 @@ func newUnion(types []Type, tilde []bool) Type { // is reports whether f returned true for all terms (type, tilde) of u. func (u *Union) is(f func(Type, bool) bool) bool { - if u == nil { + if u.IsEmpty() { return false } for i, t := range u.types { @@ -56,7 +62,7 @@ func (u *Union) is(f func(Type, bool) bool) bool { // is reports whether f returned true for the underlying types of all terms of u. func (u *Union) underIs(f func(Type) bool) bool { - if u == nil { + if u.IsEmpty() { return false } for _, t := range u.types { @@ -133,26 +139,24 @@ func parseTilde(check *Checker, x ast.Expr) (Type, bool) { return check.anyType(x), tilde } -// intersect computes the intersection of the types x and y. -// Note: An incomming nil type stands for the top type. A top -// type result is returned as nil. +// intersect computes the intersection of the types x and y, +// A nil type stands for the set of all types; an empty union +// stands for the set of no types. func intersect(x, y Type) (r Type) { - defer func() { - if r == theTop { - r = nil - } - }() - + // If one of the types is nil (no restrictions) + // the result is the other type. switch { - case x == theBottom || y == theBottom: - return theBottom - case x == nil || x == theTop: + case x == nil: return y - case y == nil || x == theTop: + case y == nil: return x } // Compute the terms which are in both x and y. + // TODO(gri) This is not correct as it may not always compute + // the "largest" intersection. For instance, for + // x = myInt|~int, y = ~int + // we get the result myInt but we should get ~int. xu, _ := x.(*Union) yu, _ := y.(*Union) switch { @@ -161,23 +165,29 @@ func intersect(x, y Type) (r Type) { // TODO(gri) fix asymptotic performance var types []Type var tilde []bool - for _, y := range yu.types { - if includes(xu.types, y) { - types = append(types, y) - tilde = append(tilde, true) // TODO(gri) fix this + for j, y := range yu.types { + yt := yu.tilde[j] + if r, rt := xu.intersect(y, yt); r != nil { + // Terms x[i] and y[j] match: Select the one that + // is not a ~t because that is the intersection + // type. If both are ~t, they are identical: + // T ∩ T = T + // T ∩ ~t = T + // ~t ∩ T = T + // ~t ∩ ~t = ~t + types = append(types, r) + tilde = append(tilde, rt) } } - if types != nil { - return newUnion(types, tilde) - } + return newUnion(types, tilde) case xu != nil: - if includes(xu.types, y) { + if r, _ := xu.intersect(y, false); r != nil { return y } case yu != nil: - if includes(yu.types, x) { + if r, _ := yu.intersect(x, false); r != nil { return x } @@ -187,5 +197,42 @@ func intersect(x, y Type) (r Type) { } } - return theBottom + return emptyUnion +} + +// includes reports whether typ is in list. +func includes(list []Type, typ Type) bool { + for _, e := range list { + if Identical(typ, e) { + return true + } + } + return false +} + +// intersect computes the intersection of the union u and term (y, yt) +// and returns the intersection term, if any. Otherwise the result is +// (nil, false). +func (u *Union) intersect(y Type, yt bool) (Type, bool) { + under_y := under(y) + for i, x := range u.types { + xt := u.tilde[i] + // determine which types xx, yy to compare + xx := x + if yt { + xx = under(x) + } + yy := y + if xt { + yy = under_y + } + if Identical(xx, yy) { + // T ∩ T = T + // T ∩ ~t = T + // ~t ∩ T = T + // ~t ∩ ~t = ~t + return xx, xt && yt + } + } + return nil, false } -- GitLab From 8e14a9cf04fd2a215871f7f68abaa926d8435173 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Wed, 9 Jun 2021 18:41:19 -0400 Subject: [PATCH 0288/2500] [dev.typeparams] go/types: eliminate need for unpack and asUnion functions This is a straightforward port of CL 323355 to go/types, adjusted for the different error reporting API in go/types. Change-Id: I0f9d7ca0e0959e1e214ecd61eb85cc311e6409a2 Reviewed-on: https://go-review.googlesource.com/c/go/+/326679 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/builtins.go | 12 +++++------- src/go/types/infer.go | 15 +++++++++------ src/go/types/subst.go | 11 ++++++----- src/go/types/type.go | 35 +++++++++-------------------------- 4 files changed, 29 insertions(+), 44 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 92807ed44a..cfaeab611b 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -768,14 +768,12 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { if tp := asTypeParam(x); tp != nil { // Test if t satisfies the requirements for the argument // type and collect possible result types at the same time. - // TODO(gri) This needs to consider the ~ information if we - // have a union type. var rtypes []Type - var tilde []bool - if !tp.Bound().is(func(x Type) bool { - if r := f(x); r != nil { + var tildes []bool + if !tp.Bound().is(func(typ Type, tilde bool) bool { + if r := f(typ); r != nil { rtypes = append(rtypes, r) - tilde = append(tilde, true) + tildes = append(tildes, tilde) return true } return false @@ -786,7 +784,7 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { // construct a suitable new type parameter tpar := NewTypeName(token.NoPos, nil /* = Universe pkg */, "", nil) ptyp := check.newTypeParam(tpar, 0, &emptyInterface) // assigns type to tpar as a side-effect - tsum := newUnion(rtypes, tilde) + tsum := newUnion(rtypes, tildes) ptyp.bound = &Interface{allMethods: markComplete, allTypes: tsum} return ptyp diff --git a/src/go/types/infer.go b/src/go/types/infer.go index ddf02a3942..5a4f939bb1 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -323,7 +323,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { return true } } - return w.isParameterizedList(unpackType(t.allTypes)) + return w.isParameterized(t.allTypes) } return t.iterate(func(t *Interface) bool { @@ -472,11 +472,14 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty func (check *Checker) structuralType(constraint Type) Type { if iface, _ := under(constraint).(*Interface); iface != nil { check.completeInterface(token.NoPos, iface) - types := unpackType(iface.allTypes) - if len(types) == 1 { - return types[0] + if u, _ := iface.allTypes.(*Union); u != nil { + if u.NumTerms() == 1 { + // TODO(gri) do we need to respect tilde? + return u.types[0] + } + return nil } - return nil + return iface.allTypes } - return constraint + return nil } diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 24108993ef..025eba0f8c 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -198,14 +198,15 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *_TypeParam, smap check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ) return false } - for _, t := range unpackType(targBound.allTypes) { - if !iface.isSatisfiedBy(t) { + return iface.is(func(typ Type, tilde bool) bool { + // TODO(gri) incorporate tilde information! + if !iface.isSatisfiedBy(typ) { // TODO(gri) match this error message with the one below (or vice versa) - check.softErrorf(atPos(pos), 0, "%s does not satisfy %s (%s type constraint %s not found in %s)", targ, tpar.bound, targ, t, iface.allTypes) + check.softErrorf(atPos(pos), 0, "%s does not satisfy %s (%s type constraint %s not found in %s)", targ, tpar.bound, targ, typ, iface.allTypes) return false } - } - return false + return true + }) } // Otherwise, targ's type or underlying type must also be one of the interface types listed, if any. diff --git a/src/go/types/type.go b/src/go/types/type.go index 8a4544e497..7429056865 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -266,29 +266,17 @@ type Interface struct { obj Object // type declaration defining this interface; or nil (for better error messages) } -// unpack unpacks a type into a list of types. -// TODO(gri) Try to eliminate the need for this function. -func unpackType(typ Type) []Type { - if typ == nil { - return nil - } - if u := asUnion(typ); u != nil { - return u.types - } - return []Type{typ} -} - -// is reports whether interface t represents types that all satisfy pred. -func (t *Interface) is(pred func(Type) bool) bool { - if t.allTypes == nil { +// is reports whether interface t represents types that all satisfy f. +func (t *Interface) is(f func(Type, bool) bool) bool { + switch t := t.allTypes.(type) { + case nil, *top: + // TODO(gri) should settle on top or nil to represent this case return false // we must have at least one type! (was bug) + case *Union: + return t.is(func(typ Type, tilde bool) bool { return f(typ, tilde) }) + default: + return f(t, false) } - for _, t := range unpackType(t.allTypes) { - if !pred(t) { - return false - } - } - return true } // emptyInterface represents the empty (completed) interface @@ -824,11 +812,6 @@ func asSignature(t Type) *Signature { return op } -func asUnion(t Type) *Union { - op, _ := optype(t).(*Union) - return op -} - func asInterface(t Type) *Interface { op, _ := optype(t).(*Interface) return op -- GitLab From 795f4475e58ff7adaeaf949f8e79470a7c43f501 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Wed, 9 Jun 2021 18:46:30 -0400 Subject: [PATCH 0289/2500] [dev.typeparams] go/types: convert testdata/examples tests to type set sytax This is a straightforward port of CL 324529 to go/types. Change-Id: I788b1ac3d4e40060038a134c525c81624add8e81 Reviewed-on: https://go-review.googlesource.com/c/go/+/326680 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/testdata/examples/functions.go2 | 2 +- src/go/types/testdata/examples/inference.go2 | 6 +++--- src/go/types/testdata/examples/types.go2 | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/go/types/testdata/examples/functions.go2 b/src/go/types/testdata/examples/functions.go2 index fb74ae7ae2..f15c709ce4 100644 --- a/src/go/types/testdata/examples/functions.go2 +++ b/src/go/types/testdata/examples/functions.go2 @@ -98,7 +98,7 @@ func g2b[P, Q any](x P, y Q) { // Here's an example of a recursive function call with variadic // arguments and type inference inferring the type parameter of // the caller (i.e., itself). -func max[T interface{ type int }](x ...T) T { +func max[T interface{ ~int }](x ...T) T { var x0 T if len(x) > 0 { x0 = x[0] diff --git a/src/go/types/testdata/examples/inference.go2 b/src/go/types/testdata/examples/inference.go2 index b4f3369aa0..1142e569b4 100644 --- a/src/go/types/testdata/examples/inference.go2 +++ b/src/go/types/testdata/examples/inference.go2 @@ -7,7 +7,7 @@ package p type Ordered interface { - type int, float64, string + ~int|~float64|~string } func min[T Ordered](x, y T) T @@ -54,7 +54,7 @@ func _() { mixed[int, string](1.1 /* ERROR cannot use 1.1 */ , "", false) } -func related1[Slice interface{type []Elem}, Elem any](s Slice, e Elem) +func related1[Slice interface{~[]Elem}, Elem any](s Slice, e Elem) func _() { // related1 can be called with explicit instantiation. @@ -78,7 +78,7 @@ func _() { related1(si, "foo" /* ERROR cannot use "foo" */ ) } -func related2[Elem any, Slice interface{type []Elem}](e Elem, s Slice) +func related2[Elem any, Slice interface{~[]Elem}](e Elem, s Slice) func _() { // related2 can be called with explicit instantiation. diff --git a/src/go/types/testdata/examples/types.go2 b/src/go/types/testdata/examples/types.go2 index 59c8804ad2..8cdd7f2fd2 100644 --- a/src/go/types/testdata/examples/types.go2 +++ b/src/go/types/testdata/examples/types.go2 @@ -165,7 +165,7 @@ type _ struct { // are type parameters. As with ordinary type definitions, the // types underlying properties are "inherited" but the methods // are not. -func _[T interface{ m(); type int }]() { +func _[T interface{ m(); ~int }]() { type L T var x L @@ -238,11 +238,11 @@ func _[A Adder[A], B Adder[B], C Adder[A]]() { // The type of variables (incl. parameters and return values) cannot // be an interface with type constraints or be/embed comparable. type I interface { - type int + ~int } var ( - _ interface /* ERROR contains type constraints */ {type int} + _ interface /* ERROR contains type constraints */ {~int} _ I /* ERROR contains type constraints */ ) @@ -273,7 +273,7 @@ func _() { // (If a type list contains just a single const type, we could // allow it, but such type lists don't make much sense in the // first place.) -func _[T interface { type int, float64 }]() { +func _[T interface {~int|~float64}]() { // not valid const _ = T /* ERROR not constant */ (0) const _ T /* ERROR invalid constant type T */ = 1 -- GitLab From b6fc4d01a8d9cefe180fde97ace36588d1d31417 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Wed, 9 Jun 2021 18:51:24 -0400 Subject: [PATCH 0290/2500] [dev.typeparams] go/types: convert testdata/fixedbugs tests to type set sytax This is a port of CL 324530 to go/types. One error position in issue39634.go2 was adjusted by a character, to account for go/types' positioning. Change-Id: Ie06974ea9ee81d3ae66ef58dba522936ab4ce2d1 Reviewed-on: https://go-review.googlesource.com/c/go/+/326681 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/testdata/fixedbugs/issue39634.go2 | 4 ++-- src/go/types/testdata/fixedbugs/issue39680.go2 | 4 ++-- src/go/types/testdata/fixedbugs/issue39699.go2 | 2 +- src/go/types/testdata/fixedbugs/issue39723.go2 | 2 +- src/go/types/testdata/fixedbugs/issue39755.go2 | 4 ++-- src/go/types/testdata/fixedbugs/issue41124.go2 | 4 ++-- src/go/types/testdata/fixedbugs/issue42758.go2 | 2 +- src/go/types/testdata/fixedbugs/issue45548.go2 | 2 +- src/go/types/testdata/fixedbugs/issue45635.go2 | 2 +- src/go/types/testdata/fixedbugs/issue45985.go2 | 2 +- 10 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/go/types/testdata/fixedbugs/issue39634.go2 b/src/go/types/testdata/fixedbugs/issue39634.go2 index c759be0d93..8decff5291 100644 --- a/src/go/types/testdata/fixedbugs/issue39634.go2 +++ b/src/go/types/testdata/fixedbugs/issue39634.go2 @@ -31,12 +31,12 @@ type x7[A any] struct{ foo7 } func main7() { var _ foo7 = x7[int]{} } // crash 8 -type foo8[A any] interface { type A } +type foo8[A any] interface { ~A } func bar8[A foo8[A]](a A) {} func main8() {} // crash 9 -type foo9[A any] interface { type foo9 /* ERROR cannot use interface */ [A] } +type foo9[A any] interface { ~ /* ERROR cannot use interface */ foo9 [A] } func _() { var _ = new(foo9 /* ERROR interface contains type constraints */ [int]) } // crash 12 diff --git a/src/go/types/testdata/fixedbugs/issue39680.go2 b/src/go/types/testdata/fixedbugs/issue39680.go2 index 9bc26f3546..01eadd2dbf 100644 --- a/src/go/types/testdata/fixedbugs/issue39680.go2 +++ b/src/go/types/testdata/fixedbugs/issue39680.go2 @@ -7,13 +7,13 @@ package p import "fmt" // Minimal test case. -func _[T interface{type T}](x T) T{ +func _[T interface{~T}](x T) T{ return x } // Test case from issue. type constr[T any] interface { - type T + ~T } func Print[T constr[T]](s []T) { diff --git a/src/go/types/testdata/fixedbugs/issue39699.go2 b/src/go/types/testdata/fixedbugs/issue39699.go2 index 75491e7e26..72f83997c2 100644 --- a/src/go/types/testdata/fixedbugs/issue39699.go2 +++ b/src/go/types/testdata/fixedbugs/issue39699.go2 @@ -8,7 +8,7 @@ type T0 interface{ } type T1 interface{ - type int + ~int } type T2 interface{ diff --git a/src/go/types/testdata/fixedbugs/issue39723.go2 b/src/go/types/testdata/fixedbugs/issue39723.go2 index 61bc606789..367b3f1360 100644 --- a/src/go/types/testdata/fixedbugs/issue39723.go2 +++ b/src/go/types/testdata/fixedbugs/issue39723.go2 @@ -6,4 +6,4 @@ package p // A constraint must be an interface; it cannot // be a type parameter, for instance. -func _[A interface{ type int }, B A /* ERROR not an interface */ ]() +func _[A interface{ ~int }, B A /* ERROR not an interface */ ]() diff --git a/src/go/types/testdata/fixedbugs/issue39755.go2 b/src/go/types/testdata/fixedbugs/issue39755.go2 index b7ab68818e..257b73a2fb 100644 --- a/src/go/types/testdata/fixedbugs/issue39755.go2 +++ b/src/go/types/testdata/fixedbugs/issue39755.go2 @@ -4,14 +4,14 @@ package p -func _[T interface{type map[string]int}](x T) { +func _[T interface{~map[string]int}](x T) { _ = x == nil } // simplified test case from issue type PathParamsConstraint interface { - type map[string]string, []struct{key, value string} + ~map[string]string | ~[]struct{key, value string} } type PathParams[T PathParamsConstraint] struct { diff --git a/src/go/types/testdata/fixedbugs/issue41124.go2 b/src/go/types/testdata/fixedbugs/issue41124.go2 index 61f766bcbd..ab535049dd 100644 --- a/src/go/types/testdata/fixedbugs/issue41124.go2 +++ b/src/go/types/testdata/fixedbugs/issue41124.go2 @@ -7,7 +7,7 @@ package p // Test case from issue. type Nat interface { - type Zero, Succ + Zero|Succ } type Zero struct{} @@ -22,7 +22,7 @@ type I1 interface { } type I2 interface { - type int + ~int } type I3 interface { diff --git a/src/go/types/testdata/fixedbugs/issue42758.go2 b/src/go/types/testdata/fixedbugs/issue42758.go2 index 698cb8a16b..bf0031f5d2 100644 --- a/src/go/types/testdata/fixedbugs/issue42758.go2 +++ b/src/go/types/testdata/fixedbugs/issue42758.go2 @@ -17,7 +17,7 @@ func _[T any](x interface{}){ } type constraint interface { - type int + ~int } func _[T constraint](x interface{}){ diff --git a/src/go/types/testdata/fixedbugs/issue45548.go2 b/src/go/types/testdata/fixedbugs/issue45548.go2 index b1e42497e8..b8ba0ad4a7 100644 --- a/src/go/types/testdata/fixedbugs/issue45548.go2 +++ b/src/go/types/testdata/fixedbugs/issue45548.go2 @@ -4,7 +4,7 @@ package p -func f[F interface{type *Q}, G interface{type *R}, Q, R any](q Q, r R) {} +func f[F interface{~*Q}, G interface{~*R}, Q, R any](q Q, r R) {} func _() { f[*float64, *int](1, 2) diff --git a/src/go/types/testdata/fixedbugs/issue45635.go2 b/src/go/types/testdata/fixedbugs/issue45635.go2 index 3e2cceca2d..0f62980343 100644 --- a/src/go/types/testdata/fixedbugs/issue45635.go2 +++ b/src/go/types/testdata/fixedbugs/issue45635.go2 @@ -13,7 +13,7 @@ type N[T any] struct{} var _ N /* ERROR "0 arguments but 1 type parameters" */ [] type I interface { - type map[int]int, []int + ~map[int]int | ~[]int } func _[T I](i, j int) { diff --git a/src/go/types/testdata/fixedbugs/issue45985.go2 b/src/go/types/testdata/fixedbugs/issue45985.go2 index 550b9c6712..6e42dbb633 100644 --- a/src/go/types/testdata/fixedbugs/issue45985.go2 +++ b/src/go/types/testdata/fixedbugs/issue45985.go2 @@ -5,7 +5,7 @@ package issue45985 // TODO(rFindley): this error should be on app[int] below. -func app[S /* ERROR "type S = S does not match" */ interface{ type []T }, T any](s S, e T) S { +func app[S /* ERROR "type S = S does not match" */ interface{ ~[]T }, T any](s S, e T) S { return append(s, e) } -- GitLab From 6e50f4f11166d5bfa2fba2f28bf4d43e3a713930 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Thu, 10 Jun 2021 09:27:44 -0400 Subject: [PATCH 0291/2500] [dev.typeparams] go/types: convert testdata/check tests to type set syntax This is a port of CL 324569 to go/types, with some error positions adjusted: go/types puts errors related to terms on the '~', not type name. Change-Id: I92e8443ce27a5ecae0e3e0dac4811eaf3eee07ff Reviewed-on: https://go-review.googlesource.com/c/go/+/326682 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer --- src/go/types/testdata/check/builtins.go2 | 8 +-- src/go/types/testdata/check/issues.go2 | 26 +++---- src/go/types/testdata/check/linalg.go2 | 16 ++--- src/go/types/testdata/check/tinference.go2 | 20 +++--- src/go/types/testdata/check/typeinst2.go2 | 29 ++++---- src/go/types/testdata/check/typeparams.go2 | 80 +++++++++++----------- 6 files changed, 90 insertions(+), 89 deletions(-) diff --git a/src/go/types/testdata/check/builtins.go2 b/src/go/types/testdata/check/builtins.go2 index 3918d836b5..5bb67efec9 100644 --- a/src/go/types/testdata/check/builtins.go2 +++ b/src/go/types/testdata/check/builtins.go2 @@ -7,19 +7,19 @@ package builtins type Bmc interface { - type map[rune]string, chan int + ~map[rune]string | ~chan int } type Bms interface { - type map[string]int, []int + ~map[string]int | ~[]int } type Bcs interface { - type chan bool, []float64 + ~chan bool | ~[]float64 } type Bss interface { - type []int, []string + ~[]int | ~[]string } func _[T any] () { diff --git a/src/go/types/testdata/check/issues.go2 b/src/go/types/testdata/check/issues.go2 index 0a7648cba1..c655fb99a4 100644 --- a/src/go/types/testdata/check/issues.go2 +++ b/src/go/types/testdata/check/issues.go2 @@ -64,7 +64,7 @@ func _() { // type with a type list constraint, all of the type argument's types in its // bound, but at least one (!), must be in the type list of the bound of the // corresponding parameterized type's type parameter. -type T1[P interface{type uint}] struct{} +type T1[P interface{~uint}] struct{} func _[P any]() { _ = T1[P /* ERROR P has no type constraints */ ]{} @@ -72,7 +72,7 @@ func _[P any]() { // This is the original (simplified) program causing the same issue. type Unsigned interface { - type uint + ~uint } type T2[U Unsigned] struct { @@ -163,7 +163,7 @@ type inf2[T any] struct{ inf2 /* ERROR illegal cycle */ [T] } // predicate disjunction in the implementation was wrong because if a type list // contains both an integer and a floating-point type, the type parameter is // neither an integer or a floating-point number. -func convert[T1, T2 interface{type int, uint, float32}](v T1) T2 { +func convert[T1, T2 interface{~int | ~uint | ~float32}](v T1) T2 { return T2(v) } @@ -175,12 +175,12 @@ func _() { // both numeric, or both strings. The implementation had the same problem // with this check as the conversion issue above (issue #39623). -func issue39623[T interface{type int, string}](x, y T) T { +func issue39623[T interface{~int | ~string}](x, y T) T { return x + y } // Simplified, from https://go2goplay.golang.org/p/efS6x6s-9NI: -func Sum[T interface{type int, string}](s []T) (sum T) { +func Sum[T interface{~int | ~string}](s []T) (sum T) { for _, v := range s { sum += v } @@ -189,19 +189,19 @@ func Sum[T interface{type int, string}](s []T) (sum T) { // Assignability of an unnamed pointer type to a type parameter that // has a matching underlying type. -func _[T interface{}, PT interface{type *T}] (x T) PT { +func _[T interface{}, PT interface{~*T}] (x T) PT { return &x } // Indexing of generic types containing type parameters in their type list: -func at[T interface{ type []E }, E interface{}](x T, i int) E { +func at[T interface{ ~[]E }, E interface{}](x T, i int) E { return x[i] } // A generic type inside a function acts like a named type. Its underlying // type is itself, its "operational type" is defined by the type list in // the tybe bound, if any. -func _[T interface{type int}](x T) { +func _[T interface{~int}](x T) { type myint int var _ int = int(x) var _ T = 42 @@ -210,24 +210,24 @@ func _[T interface{type int}](x T) { // Indexing a generic type with an array type bound checks length. // (Example by mdempsky@.) -func _[T interface { type [10]int }](x T) { +func _[T interface { ~[10]int }](x T) { _ = x[9] // ok _ = x[20 /* ERROR out of bounds */ ] } // Pointer indirection of a generic type. -func _[T interface{ type *int }](p T) int { +func _[T interface{ ~*int }](p T) int { return *p } // Channel sends and receives on generic types. -func _[T interface{ type chan int }](ch T) int { +func _[T interface{ ~chan int }](ch T) int { ch <- 0 return <- ch } // Calling of a generic variable. -func _[T interface{ type func() }](f T) { +func _[T interface{ ~func() }](f T) { f() go f() } @@ -239,7 +239,7 @@ func _[T interface{ type func() }](f T) { // type parameter that was substituted with a defined type. // Test case from an (originally) failing example. -type sliceOf[E any] interface{ type []E } +type sliceOf[E any] interface{ ~[]E } func append[T interface{}, S sliceOf[T], T2 interface{ T }](s S, t ...T2) S diff --git a/src/go/types/testdata/check/linalg.go2 b/src/go/types/testdata/check/linalg.go2 index 0d27603a58..efc090a1d1 100644 --- a/src/go/types/testdata/check/linalg.go2 +++ b/src/go/types/testdata/check/linalg.go2 @@ -9,10 +9,10 @@ import "math" // Numeric is type bound that matches any numeric type. // It would likely be in a constraints package in the standard library. type Numeric interface { - type int, int8, int16, int32, int64, - uint, uint8, uint16, uint32, uint64, uintptr, - float32, float64, - complex64, complex128 + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 | + ~complex64 | ~complex128 } func DotProduct[T Numeric](s1, s2 []T) T { @@ -42,14 +42,14 @@ func AbsDifference[T NumericAbs[T]](a, b T) T { // OrderedNumeric is a type bound that matches numeric types that support the < operator. type OrderedNumeric interface { - type int, int8, int16, int32, int64, - uint, uint8, uint16, uint32, uint64, uintptr, - float32, float64 + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 } // Complex is a type bound that matches the two complex types, which do not have a < operator. type Complex interface { - type complex64, complex128 + ~complex64 | ~complex128 } // OrderedAbs is a helper type that defines an Abs method for diff --git a/src/go/types/testdata/check/tinference.go2 b/src/go/types/testdata/check/tinference.go2 index 31338b33ad..7ed358e078 100644 --- a/src/go/types/testdata/check/tinference.go2 +++ b/src/go/types/testdata/check/tinference.go2 @@ -11,28 +11,28 @@ type any interface{} // TODO(rFindley) the below partially applied function types should probably // not be permitted (spec question). -func f0[A any, B interface{type C}, C interface{type D}, D interface{type A}](A, B, C, D) +func f0[A any, B interface{~C}, C interface{~D}, D interface{~A}](A, B, C, D) func _() { f := f0[string] f("a", "b", "c", "d") f0("a", "b", "c", "d") } -func f1[A any, B interface{type A}](A, B) +func f1[A any, B interface{~A}](A, B) func _() { f := f1[int] f(int(0), int(0)) f1(int(0), int(0)) } -func f2[A any, B interface{type []A}](A, B) +func f2[A any, B interface{~[]A}](A, B) func _() { f := f2[byte] f(byte(0), []byte{}) f2(byte(0), []byte{}) } -func f3[A any, B interface{type C}, C interface{type *A}](A, B, C) +func f3[A any, B interface{~C}, C interface{~*A}](A, B, C) func _() { f := f3[int] var x int @@ -40,7 +40,7 @@ func _() { f3(x, &x, &x) } -func f4[A any, B interface{type []C}, C interface{type *A}](A, B, C) +func f4[A any, B interface{~[]C}, C interface{~*A}](A, B, C) func _() { f := f4[int] var x int @@ -48,14 +48,14 @@ func _() { f4(x, []*int{}, &x) } -func f5[A interface{type struct{b B; c C}}, B any, C interface{type *B}](x B) A +func f5[A interface{~struct{b B; c C}}, B any, C interface{~*B}](x B) A func _() { x := f5(1.2) var _ float64 = x.b var _ float64 = *x.c } -func f6[A any, B interface{type struct{f []A}}](B) A +func f6[A any, B interface{~struct{f []A}}](B) A func _() { x := f6(struct{f []string}{}) var _ string = x @@ -63,11 +63,11 @@ func _() { // TODO(gri) Need to flag invalid recursive constraints. At the // moment these cause infinite recursions and stack overflow. -// func f7[A interface{type B}, B interface{type A}]() +// func f7[A interface{type B}, B interface{~A}]() // More realistic examples -func Double[S interface{ type []E }, E interface{ type int, int8, int16, int32, int64 }](s S) S { +func Double[S interface{ ~[]E }, E interface{ ~int | ~int8 | ~int16 | ~int32 | ~int64 }](s S) S { r := make(S, len(s)) for i, v := range s { r[i] = v + v @@ -83,7 +83,7 @@ var _ = Double(MySlice{1}) type Setter[B any] interface { Set(string) - type *B + ~*B } func FromStrings[T interface{}, PT Setter[T]](s []string) []T { diff --git a/src/go/types/testdata/check/typeinst2.go2 b/src/go/types/testdata/check/typeinst2.go2 index 1096bb42eb..a4c9f58c09 100644 --- a/src/go/types/testdata/check/typeinst2.go2 +++ b/src/go/types/testdata/check/typeinst2.go2 @@ -148,15 +148,15 @@ func _[T any](r R2[T, int], p *R2[string, T]) { p.pm() } -// An interface can (explicitly) declare at most one type list. +// It is ok to have multiple embedded unions. type _ interface { m0() - type int, string, bool - type /* ERROR multiple type lists */ float32, float64 + ~int | ~string | ~bool + ~float32 | ~float64 m1() m2() - type /* ERROR multiple type lists */ complex64, complex128 - type /* ERROR multiple type lists */ rune + ~complex64 | ~complex128 + ~rune } // Interface type lists may contain each type at most once. @@ -164,23 +164,24 @@ type _ interface { // for them to be all in a single list, and we report the error // as well.) type _ interface { - type int, int /* ERROR duplicate term int */ - type /* ERROR multiple type lists */ int /* ERROR duplicate term int */ + ~int|~ /* ERROR duplicate term int */ int + ~int|int /* ERROR duplicate term int */ + int|int /* ERROR duplicate term int */ } type _ interface { - type struct{f int}, struct{g int}, struct /* ERROR duplicate term */ {f int} + ~struct{f int} | ~struct{g int} | ~ /* ERROR duplicate term */ struct{f int} } // Interface type lists can contain any type, incl. *Named types. // Verify that we use the underlying type to compute the operational type. type MyInt int -func add1[T interface{type MyInt}](x T) T { +func add1[T interface{~MyInt}](x T) T { return x + 1 } type MyString string -func double[T interface{type MyInt, MyString}](x T) T { +func double[T interface{~MyInt | ~MyString}](x T) T { return x + x } @@ -189,15 +190,15 @@ func double[T interface{type MyInt, MyString}](x T) T { // type lists. type E0 interface { - type int, bool, string + ~int | ~bool | ~string } type E1 interface { - type int, float64, string + ~int | ~float64 | ~string } type E2 interface { - type float64 + ~float64 } type I0 interface { @@ -246,7 +247,7 @@ var _ = f12[float64] type I0_ interface { E0 - type int + ~int } func f0_[T I0_]() diff --git a/src/go/types/testdata/check/typeparams.go2 b/src/go/types/testdata/check/typeparams.go2 index d95e02e443..5b4361d279 100644 --- a/src/go/types/testdata/check/typeparams.go2 +++ b/src/go/types/testdata/check/typeparams.go2 @@ -52,22 +52,22 @@ func swapswap[A, B any](a A, b B) (A, B) { type F[A, B any] func(A, B) (B, A) -func min[T interface{ type int }](x, y T) T { +func min[T interface{ ~int }](x, y T) T { if x < y { return x } return y } -func _[T interface{type int, float32}](x, y T) bool { return x < y } +func _[T interface{~int | ~float32}](x, y T) bool { return x < y } func _[T any](x, y T) bool { return x /* ERROR cannot compare */ < y } -func _[T interface{type int, float32, bool}](x, y T) bool { return x /* ERROR cannot compare */ < y } +func _[T interface{~int | ~float32 | ~bool}](x, y T) bool { return x /* ERROR cannot compare */ < y } func _[T C1[T]](x, y T) bool { return x /* ERROR cannot compare */ < y } func _[T C2[T]](x, y T) bool { return x < y } type C1[T any] interface{} -type C2[T any] interface{ type int, float32 } +type C2[T any] interface{ ~int | ~float32 } func new[T any]() *T { var x T @@ -95,48 +95,48 @@ var _ = f3[int, rune, bool](1, struct{x rune}{}, nil) // indexing func _[T any] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } -func _[T interface{ type int }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } -func _[T interface{ type string }] (x T, i int) { _ = x[i] } -func _[T interface{ type []int }] (x T, i int) { _ = x[i] } -func _[T interface{ type [10]int, *[20]int, map[int]int }] (x T, i int) { _ = x[i] } -func _[T interface{ type string, []byte }] (x T, i int) { _ = x[i] } -func _[T interface{ type []int, [1]rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } -func _[T interface{ type string, []rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } +func _[T interface{ ~int }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } +func _[T interface{ ~string }] (x T, i int) { _ = x[i] } +func _[T interface{ ~[]int }] (x T, i int) { _ = x[i] } +func _[T interface{ ~[10]int | ~*[20]int | ~map[int]int }] (x T, i int) { _ = x[i] } +func _[T interface{ ~string | ~[]byte }] (x T, i int) { _ = x[i] } +func _[T interface{ ~[]int | ~[1]rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } +func _[T interface{ ~string | ~[]rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } // indexing with various combinations of map types in type lists (see issue #42616) -func _[T interface{ type []E, map[int]E }, E any](x T, i int) { _ = x[i] } -func _[T interface{ type []E }, E any](x T, i int) { _ = &x[i] } -func _[T interface{ type map[int]E }, E any](x T, i int) { _, _ = x[i] } // comma-ok permitted -func _[T interface{ type []E, map[int]E }, E any](x T, i int) { _ = &x /* ERROR cannot take address */ [i] } -func _[T interface{ type []E, map[int]E, map[uint]E }, E any](x T, i int) { _ = x /* ERROR cannot index */ [i] } // different map element types -func _[T interface{ type []E, map[string]E }, E any](x T, i int) { _ = x[i /* ERROR cannot use i */ ] } +func _[T interface{ ~[]E | ~map[int]E }, E any](x T, i int) { _ = x[i] } +func _[T interface{ ~[]E }, E any](x T, i int) { _ = &x[i] } +func _[T interface{ ~map[int]E }, E any](x T, i int) { _, _ = x[i] } // comma-ok permitted +func _[T interface{ ~[]E | ~map[int]E }, E any](x T, i int) { _ = &x /* ERROR cannot take address */ [i] } +func _[T interface{ ~[]E | ~map[int]E | ~map[uint]E }, E any](x T, i int) { _ = x /* ERROR cannot index */ [i] } // different map element types +func _[T interface{ ~[]E | ~map[string]E }, E any](x T, i int) { _ = x[i /* ERROR cannot use i */ ] } // slicing // TODO(gri) implement this -func _[T interface{ type string }] (x T, i, j, k int) { _ = x /* ERROR invalid operation */ [i:j:k] } +func _[T interface{ ~string }] (x T, i, j, k int) { _ = x /* ERROR invalid operation */ [i:j:k] } // len/cap built-ins func _[T any](x T) { _ = len(x /* ERROR invalid argument */ ) } -func _[T interface{ type int }](x T) { _ = len(x /* ERROR invalid argument */ ) } -func _[T interface{ type string, []byte, int }](x T) { _ = len(x /* ERROR invalid argument */ ) } -func _[T interface{ type string }](x T) { _ = len(x) } -func _[T interface{ type [10]int }](x T) { _ = len(x) } -func _[T interface{ type []byte }](x T) { _ = len(x) } -func _[T interface{ type map[int]int }](x T) { _ = len(x) } -func _[T interface{ type chan int }](x T) { _ = len(x) } -func _[T interface{ type string, []byte, chan int }](x T) { _ = len(x) } +func _[T interface{ ~int }](x T) { _ = len(x /* ERROR invalid argument */ ) } +func _[T interface{ ~string | ~[]byte | ~int }](x T) { _ = len(x /* ERROR invalid argument */ ) } +func _[T interface{ ~string }](x T) { _ = len(x) } +func _[T interface{ ~[10]int }](x T) { _ = len(x) } +func _[T interface{ ~[]byte }](x T) { _ = len(x) } +func _[T interface{ ~map[int]int }](x T) { _ = len(x) } +func _[T interface{ ~chan int }](x T) { _ = len(x) } +func _[T interface{ ~string | ~[]byte | ~chan int }](x T) { _ = len(x) } func _[T any](x T) { _ = cap(x /* ERROR invalid argument */ ) } -func _[T interface{ type int }](x T) { _ = cap(x /* ERROR invalid argument */ ) } -func _[T interface{ type string, []byte, int }](x T) { _ = cap(x /* ERROR invalid argument */ ) } -func _[T interface{ type string }](x T) { _ = cap(x /* ERROR invalid argument */ ) } -func _[T interface{ type [10]int }](x T) { _ = cap(x) } -func _[T interface{ type []byte }](x T) { _ = cap(x) } -func _[T interface{ type map[int]int }](x T) { _ = cap(x /* ERROR invalid argument */ ) } -func _[T interface{ type chan int }](x T) { _ = cap(x) } -func _[T interface{ type []byte, chan int }](x T) { _ = cap(x) } +func _[T interface{ ~int }](x T) { _ = cap(x /* ERROR invalid argument */ ) } +func _[T interface{ ~string | ~[]byte | ~int }](x T) { _ = cap(x /* ERROR invalid argument */ ) } +func _[T interface{ ~string }](x T) { _ = cap(x /* ERROR invalid argument */ ) } +func _[T interface{ ~[10]int }](x T) { _ = cap(x) } +func _[T interface{ ~[]byte }](x T) { _ = cap(x) } +func _[T interface{ ~map[int]int }](x T) { _ = cap(x /* ERROR invalid argument */ ) } +func _[T interface{ ~chan int }](x T) { _ = cap(x) } +func _[T interface{ ~[]byte | ~chan int }](x T) { _ = cap(x) } // range iteration @@ -144,7 +144,7 @@ func _[T interface{}](x T) { for range x /* ERROR cannot range */ {} } -func _[T interface{ type string, []string }](x T) { +func _[T interface{ ~string | ~[]string }](x T) { for range x {} for i := range x { _ = i } for i, _ := range x { _ = i } @@ -156,23 +156,23 @@ func _[T interface{ type string, []string }](x T) { } -func _[T interface{ type string, []rune, map[int]rune }](x T) { +func _[T interface{ ~string | ~[]rune | ~map[int]rune }](x T) { for _, e := range x { _ = e } for i, e := range x { _ = i; _ = e } } -func _[T interface{ type string, []rune, map[string]rune }](x T) { +func _[T interface{ ~string | ~[]rune | ~map[string]rune }](x T) { for _, e := range x { _ = e } for i, e := range x /* ERROR must have the same key type */ { _ = e } } -func _[T interface{ type string, chan int }](x T) { +func _[T interface{ ~string | ~chan int }](x T) { for range x {} for i := range x { _ = i } for i, _ := range x { _ = i } // TODO(gri) should get an error here: channels only return one value } -func _[T interface{ type string, chan<-int }](x T) { +func _[T interface{ ~string | ~chan<-int }](x T) { for i := range x /* ERROR send-only channel */ { _ = i } } @@ -399,7 +399,7 @@ func _[T any](x T) { } } -func _[T interface{type int}](x T) { +func _[T interface{~int}](x T) { _ = x /* ERROR not an interface */ .(int) switch x /* ERROR not an interface */ .(type) { } -- GitLab From 6237e441bca7f3429abde413bf71c7840fec9bf2 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Thu, 10 Jun 2021 11:26:08 -0400 Subject: [PATCH 0292/2500] [dev.typeparams] go/types: disallow type list handling This is a port of CL 324571 to go/types, though type list handling is guarded by a const rather than a config option. Change-Id: I91c940fead048980603e0bb56fcc896dbef4f94c Reviewed-on: https://go-review.googlesource.com/c/go/+/326683 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/api.go | 2 ++ src/go/types/api_test.go | 2 +- src/go/types/api_typeparams_test.go | 14 +++++++------- src/go/types/interface.go | 10 +++++++++- src/go/types/testdata/examples/constraints.go2 | 12 ++++++++++++ src/go/types/typestring_test.go | 1 - 6 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/go/types/api.go b/src/go/types/api.go index 30f8ded744..d3a95bc991 100644 --- a/src/go/types/api.go +++ b/src/go/types/api.go @@ -34,6 +34,8 @@ import ( "go/token" ) +const allowTypeLists = false + // An Error describes a type-checking error; it implements the error interface. // A "soft" error is an error that still permits a valid interpretation of a // package (such as "unused variable"); "hard" errors may lead to unpredictable diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index 5a2d4a4ca3..6a7218d90f 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -349,7 +349,7 @@ func TestTypesInfo(t *testing.T) { {genericPkg + `g0; type t[P any] int; var x struct{ f t[int] }; var _ = x.f`, `x.f`, `generic_g0.t[int]`}, // issue 45096 - {genericPkg + `issue45096; func _[T interface{ type int8, int16, int32 }](x T) { _ = x < 0 }`, `0`, `T₁`}, + {genericPkg + `issue45096; func _[T interface{ ~int8 | ~int16 | ~int32 }](x T) { _ = x < 0 }`, `0`, `T₁`}, } for _, test := range tests { diff --git a/src/go/types/api_typeparams_test.go b/src/go/types/api_typeparams_test.go index 4a2adce9a2..d9117b8412 100644 --- a/src/go/types/api_typeparams_test.go +++ b/src/go/types/api_typeparams_test.go @@ -45,38 +45,38 @@ func TestInferredInfo(t *testing.T) { `func(float64, *byte, ...[]byte)`, }, - {genericPkg + `s1; func f[T any, P interface{type *T}](x T); func _(x string) { f(x) }`, + {genericPkg + `s1; func f[T any, P interface{~*T}](x T); func _(x string) { f(x) }`, `f`, []string{`string`, `*string`}, `func(x string)`, }, - {genericPkg + `s2; func f[T any, P interface{type *T}](x []T); func _(x []int) { f(x) }`, + {genericPkg + `s2; func f[T any, P interface{~*T}](x []T); func _(x []int) { f(x) }`, `f`, []string{`int`, `*int`}, `func(x []int)`, }, - {genericPkg + `s3; type C[T any] interface{type chan<- T}; func f[T any, P C[T]](x []T); func _(x []int) { f(x) }`, + {genericPkg + `s3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]](x []T); func _(x []int) { f(x) }`, `f`, []string{`int`, `chan<- int`}, `func(x []int)`, }, - {genericPkg + `s4; type C[T any] interface{type chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T); func _(x []int) { f(x) }`, + {genericPkg + `s4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T); func _(x []int) { f(x) }`, `f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func(x []int)`, }, - {genericPkg + `t1; func f[T any, P interface{type *T}]() T; func _() { _ = f[string] }`, + {genericPkg + `t1; func f[T any, P interface{~*T}]() T; func _() { _ = f[string] }`, `f`, []string{`string`, `*string`}, `func() string`, }, - {genericPkg + `t2; type C[T any] interface{type chan<- T}; func f[T any, P C[T]]() []T; func _() { _ = f[int] }`, + {genericPkg + `t2; type C[T any] interface{~chan<- T}; func f[T any, P C[T]]() []T; func _() { _ = f[int] }`, `f`, []string{`int`, `chan<- int`}, `func() []int`, }, - {genericPkg + `t3; type C[T any] interface{type chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T; func _() { _ = f[int] }`, + {genericPkg + `t3; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T; func _() { _ = f[int] }`, `f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func() []int`, diff --git a/src/go/types/interface.go b/src/go/types/interface.go index 9b4d080c81..947e76dc17 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -34,7 +34,13 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d continue // ignore } + // TODO(rfindley) Remove type list handling once the parser doesn't accept type lists anymore. if name.Name == "type" { + // Report an error for the first type list per interface + // if we don't allow type lists, but continue. + if !allowTypeLists && tlist == nil { + check.softErrorf(name, _Todo, "use generalized embedding syntax instead of a type list") + } // For now, collect all type list entries as if it // were a single union, where each union element is // of the form ~T. @@ -43,7 +49,9 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d op.Op = token.TILDE op.X = f.Type tlist = append(tlist, op) - if tname != nil && tname != name { + // Report an error if we have multiple type lists in an + // interface, but only if they are permitted in the first place. + if allowTypeLists && tname != nil && tname != name { check.errorf(name, _Todo, "cannot have multiple type lists in an interface") } tname = name diff --git a/src/go/types/testdata/examples/constraints.go2 b/src/go/types/testdata/examples/constraints.go2 index f6291ccf7d..61992e4c2a 100644 --- a/src/go/types/testdata/examples/constraints.go2 +++ b/src/go/types/testdata/examples/constraints.go2 @@ -6,6 +6,18 @@ package p +type ( + // Type lists are processed as unions but an error is reported. + // TODO(gri) remove this once the parser doesn't accept type lists anymore. + _ interface{ + type /* ERROR use generalized embedding syntax instead of a type list */ int + } + _ interface{ + type /* ERROR use generalized embedding syntax instead of a type list */ int + type float32 + } +) + type ( // Arbitrary types may be embedded like interfaces. _ interface{int} diff --git a/src/go/types/typestring_test.go b/src/go/types/typestring_test.go index 0e35a3dbf1..f02c0d9c18 100644 --- a/src/go/types/typestring_test.go +++ b/src/go/types/typestring_test.go @@ -95,7 +95,6 @@ var independentTestTypes = []testEntry{ dup("interface{}"), dup("interface{m()}"), dup(`interface{String() string; m(int) float32}`), - {"interface{type int, float32, complex128}", "interface{~int|~float32|~complex128}"}, dup("interface{int|float32|complex128}"), dup("interface{int|~float32|~complex128}"), -- GitLab From 8115ae198d192f778a3586596c8550665f409823 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Thu, 10 Jun 2021 12:23:40 -0400 Subject: [PATCH 0293/2500] [dev.typeparams] go/types: disallow ~T where T is a defined type or an interface This is a straightforward port of CL 324570 to go/types. Change-Id: I1395775a1d21a903a57e0cefc4e240cfa2bb8e97 Reviewed-on: https://go-review.googlesource.com/c/go/+/326684 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/testdata/check/typeinst2.go2 | 4 ++-- src/go/types/testdata/examples/constraints.go2 | 9 +++++++++ src/go/types/testdata/fixedbugs/issue39634.go2 | 4 ++-- src/go/types/union.go | 11 ++++++----- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/go/types/testdata/check/typeinst2.go2 b/src/go/types/testdata/check/typeinst2.go2 index a4c9f58c09..ab56ccafc9 100644 --- a/src/go/types/testdata/check/typeinst2.go2 +++ b/src/go/types/testdata/check/typeinst2.go2 @@ -176,12 +176,12 @@ type _ interface { // Interface type lists can contain any type, incl. *Named types. // Verify that we use the underlying type to compute the operational type. type MyInt int -func add1[T interface{~MyInt}](x T) T { +func add1[T interface{MyInt}](x T) T { return x + 1 } type MyString string -func double[T interface{~MyInt | ~MyString}](x T) T { +func double[T interface{MyInt|MyString}](x T) T { return x + x } diff --git a/src/go/types/testdata/examples/constraints.go2 b/src/go/types/testdata/examples/constraints.go2 index 61992e4c2a..d9805fe694 100644 --- a/src/go/types/testdata/examples/constraints.go2 +++ b/src/go/types/testdata/examples/constraints.go2 @@ -36,6 +36,15 @@ type ( _ interface{int|interface /* ERROR cannot use interface */ {}} ) +type ( + // Tilde is not permitted on defined types or interfaces. + foo int + bar interface{} + _ interface{foo} + _ interface{~ /* ERROR invalid use of ~ */ foo } + _ interface{~ /* ERROR invalid use of ~ */ bar } +) + // Multiple embedded union elements are intersected. The order in which they // appear in the interface doesn't matter since intersection is a symmetric // operation. diff --git a/src/go/types/testdata/fixedbugs/issue39634.go2 b/src/go/types/testdata/fixedbugs/issue39634.go2 index 8decff5291..2a1367373f 100644 --- a/src/go/types/testdata/fixedbugs/issue39634.go2 +++ b/src/go/types/testdata/fixedbugs/issue39634.go2 @@ -36,8 +36,8 @@ func bar8[A foo8[A]](a A) {} func main8() {} // crash 9 -type foo9[A any] interface { ~ /* ERROR cannot use interface */ foo9 [A] } -func _() { var _ = new(foo9 /* ERROR interface contains type constraints */ [int]) } +type foo9[A any] interface { foo9 /* ERROR illegal cycle */ [A] } +func _() { var _ = new(foo9 /* ERROR illegal cycle */ [int]) } // crash 12 var u /* ERROR cycle */ , i [func /* ERROR used as value */ /* ERROR used as value */ (u, c /* ERROR undeclared */ /* ERROR undeclared */ ) {}(0, len /* ERROR must be called */ /* ERROR must be called */ )]c /* ERROR undeclared */ /* ERROR undeclared */ diff --git a/src/go/types/union.go b/src/go/types/union.go index 4eda874eb8..690b734d76 100644 --- a/src/go/types/union.go +++ b/src/go/types/union.go @@ -109,17 +109,18 @@ func parseUnion(check *Checker, tlist []ast.Expr) Type { } u := under(t) - if tilde[i] { - // TODO(rfindley) enable this check once we have converted tests - // if !Identical(u, t) { - // check.errorf(x, "invalid use of ~ (underlying type of %s is %s)", t, u) - // } + if tilde[i] && !Identical(u, t) { + check.errorf(x, _Todo, "invalid use of ~ (underlying type of %s is %s)", t, u) + continue // don't report another error for t } if _, ok := u.(*Interface); ok { + // A single type with a ~ is a single-term union. check.errorf(atPos(pos), _Todo, "cannot use interface %s with ~ or inside a union (implementation restriction)", t) + continue // don't report another error for t } // Complain about duplicate entries a|a, but also a|~a, and ~a|~a. + // TODO(gri) We should also exclude myint|~int since myint is included in ~int. if includes(types[:i], t) { // TODO(rfindley) this currently doesn't print the ~ if present check.softErrorf(atPos(pos), _Todo, "duplicate term %s in union element", t) -- GitLab From b14fd720a8c3822161ed85447774e38fab835f6f Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 16 Jun 2021 16:23:44 +0700 Subject: [PATCH 0294/2500] [dev.typeparams] cmd/compile: make types2 report better error for invalid untyped operation This ports the fix in CL 328050 for typecheck to types2. The fix is not identical, due to code structure differences between typecheck and types2, but the idea is the same. We only do the untyped conversion when both operands can be mixed. Updates #46749 Change-Id: Ib2c63ba0d5dd8bf02318b1bfdfe51dcaeeeb7f82 Reviewed-on: https://go-review.googlesource.com/c/go/+/328053 Trust: Cuong Manh Le Trust: Robert Griesemer Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/expr.go | 28 ++++++++++++++----- .../internal/types2/testdata/check/const0.src | 2 +- .../internal/types2/testdata/check/decls1.src | 2 +- .../internal/types2/testdata/check/expr1.src | 4 +-- .../internal/types2/testdata/check/expr2.src | 2 +- .../internal/types2/testdata/check/expr3.src | 2 +- .../internal/types2/testdata/check/stmt0.src | 12 ++++---- test/fixedbugs/issue41500.go | 8 +++--- test/fixedbugs/issue43762.go | 6 ++-- test/fixedbugs/issue46749.go | 10 +++---- test/run.go | 1 - 11 files changed, 45 insertions(+), 32 deletions(-) diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index b223387f18..d1cb27de16 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -972,14 +972,28 @@ func (check *Checker) binary(x *operand, e syntax.Expr, lhs, rhs syntax.Expr, op return } - check.convertUntyped(x, y.typ) - if x.mode == invalid { - return + canMix := func(x, y *operand) bool { + if IsInterface(x.typ) || IsInterface(y.typ) { + return true + } + if isBoolean(x.typ) != isBoolean(y.typ) { + return false + } + if isString(x.typ) != isString(y.typ) { + return false + } + return true } - check.convertUntyped(&y, x.typ) - if y.mode == invalid { - x.mode = invalid - return + if canMix(x, &y) { + check.convertUntyped(x, y.typ) + if x.mode == invalid { + return + } + check.convertUntyped(&y, x.typ) + if y.mode == invalid { + x.mode = invalid + return + } } if isComparison(op) { diff --git a/src/cmd/compile/internal/types2/testdata/check/const0.src b/src/cmd/compile/internal/types2/testdata/check/const0.src index 5608b1549b..3cffdf904c 100644 --- a/src/cmd/compile/internal/types2/testdata/check/const0.src +++ b/src/cmd/compile/internal/types2/testdata/check/const0.src @@ -27,7 +27,7 @@ const ( ub1 = true ub2 = 2 < 1 ub3 = ui1 == uf1 - ub4 = true /* ERROR "cannot convert" */ == 0 + ub4 = true /* ERROR "mismatched types untyped bool and untyped int" */ == 0 // integer values ui0 = 0 diff --git a/src/cmd/compile/internal/types2/testdata/check/decls1.src b/src/cmd/compile/internal/types2/testdata/check/decls1.src index e6beb78358..1167ced366 100644 --- a/src/cmd/compile/internal/types2/testdata/check/decls1.src +++ b/src/cmd/compile/internal/types2/testdata/check/decls1.src @@ -83,7 +83,7 @@ var ( // Constant expression initializations var ( - v1 = 1 /* ERROR "cannot convert" */ + "foo" + v1 = 1 /* ERROR "mismatched types untyped int and untyped string" */ + "foo" v2 = c + 255 v3 = c + 256 /* ERROR "overflows" */ v4 = r + 2147483647 diff --git a/src/cmd/compile/internal/types2/testdata/check/expr1.src b/src/cmd/compile/internal/types2/testdata/check/expr1.src index 4ead815158..85ad234bbb 100644 --- a/src/cmd/compile/internal/types2/testdata/check/expr1.src +++ b/src/cmd/compile/internal/types2/testdata/check/expr1.src @@ -111,10 +111,10 @@ type mystring string func _(x, y string, z mystring) { x = x + "foo" x = x /* ERROR not defined */ - "foo" - x = x + 1 // ERROR cannot convert + x = x + 1 // ERROR mismatched types string and untyped int x = x + y x = x /* ERROR not defined */ - y - x = x * 10 // ERROR cannot convert + x = x * 10 // ERROR mismatched types string and untyped int } func f() (a, b int) { return } diff --git a/src/cmd/compile/internal/types2/testdata/check/expr2.src b/src/cmd/compile/internal/types2/testdata/check/expr2.src index 0c959e8011..f9726b5de5 100644 --- a/src/cmd/compile/internal/types2/testdata/check/expr2.src +++ b/src/cmd/compile/internal/types2/testdata/check/expr2.src @@ -10,7 +10,7 @@ func _bool() { const t = true == true const f = true == false _ = t /* ERROR "cannot compare" */ < f - _ = 0 /* ERROR "cannot convert" */ == t + _ = 0 /* ERROR "mismatched types untyped int and untyped bool" */ == t var b bool var x, y float32 b = x < y diff --git a/src/cmd/compile/internal/types2/testdata/check/expr3.src b/src/cmd/compile/internal/types2/testdata/check/expr3.src index eab3f72c4d..fd28421dc8 100644 --- a/src/cmd/compile/internal/types2/testdata/check/expr3.src +++ b/src/cmd/compile/internal/types2/testdata/check/expr3.src @@ -104,7 +104,7 @@ func indexes() { var ok mybool _, ok = m["bar"] _ = ok - _ = m[0 /* ERROR "cannot use 0" */ ] + "foo" // ERROR "cannot convert" + _ = m[0 /* ERROR "cannot use 0" */ ] + "foo" // ERROR "mismatched types int and untyped string" var t string _ = t[- /* ERROR "negative" */ 1] diff --git a/src/cmd/compile/internal/types2/testdata/check/stmt0.src b/src/cmd/compile/internal/types2/testdata/check/stmt0.src index bedcbe5fce..d744f2ba81 100644 --- a/src/cmd/compile/internal/types2/testdata/check/stmt0.src +++ b/src/cmd/compile/internal/types2/testdata/check/stmt0.src @@ -49,18 +49,18 @@ func assignments1() { b = true i += 1 - i += "foo" /* ERROR "cannot convert.*int" */ + i += "foo" /* ERROR "mismatched types int and untyped string" */ f -= 1 f /= 0 f = float32(0)/0 /* ERROR "division by zero" */ - f -= "foo" /* ERROR "cannot convert.*float64" */ + f -= "foo" /* ERROR "mismatched types float64 and untyped string" */ c *= 1 c /= 0 s += "bar" - s += 1 /* ERROR "cannot convert.*string" */ + s += 1 /* ERROR "mismatched types string and untyped int" */ var u64 uint64 u64 += 1< Date: Wed, 16 Jun 2021 21:41:28 -0700 Subject: [PATCH 0295/2500] [dev.typeparams] all: add GOEXPERIMENT=unified knob Setting `-gcflags=all=-d=unified` works for normal builds/tests, but seems to have trouble with the test/run.go regress tests. So add a GOEXPERIMENT knob to allow another way to turn on unified IR construction, which plays better with all.bash. While here, update two existing test expectations that currently fail during GOEXPERIMENT=unified ./all.bash: 1. misc/cgo/errors/testdata/err2.go is testing column positions, and types2 gets one case slightly better, and another case slightly worse. For now, the test case is updated to accept both. 2. fixedbugs/issue42284.go is added to the list of known failures, because it fails for unified IR. (It's an escape analysis test, and escape analysis is working as expected; but unified is formatting an imported constant value differently than the test's regexp expects.) Updates #46786. Change-Id: I40a4a70fa1b85ac87fcc85a43687f5d81e011ec0 Reviewed-on: https://go-review.googlesource.com/c/go/+/328215 Run-TryBot: Matthew Dempsky Trust: Matthew Dempsky Trust: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- misc/cgo/errors/testdata/err2.go | 12 +++- src/cmd/compile/internal/base/flag.go | 4 ++ src/internal/goexperiment/exp_unified_off.go | 9 +++ src/internal/goexperiment/exp_unified_on.go | 9 +++ src/internal/goexperiment/flags.go | 4 ++ test/run.go | 66 +++++++++++++++----- 6 files changed, 86 insertions(+), 18 deletions(-) create mode 100644 src/internal/goexperiment/exp_unified_off.go create mode 100644 src/internal/goexperiment/exp_unified_on.go diff --git a/misc/cgo/errors/testdata/err2.go b/misc/cgo/errors/testdata/err2.go index a90598fe35..aa941584c3 100644 --- a/misc/cgo/errors/testdata/err2.go +++ b/misc/cgo/errors/testdata/err2.go @@ -91,10 +91,18 @@ func main() { // issue 26745 _ = func(i int) int { - return C.i + 1 // ERROR HERE: 14 + // typecheck reports at column 14 ('+'), but types2 reports at + // column 10 ('C'). + // TODO(mdempsky): Investigate why, and see if types2 can be + // updated to match typecheck behavior. + return C.i + 1 // ERROR HERE: \b(10|14)\b } _ = func(i int) { - C.fi(i) // ERROR HERE: 7 + // typecheck reports at column 7 ('('), but types2 reports at + // column 8 ('i'). The types2 position is more correct, but + // updating typecheck here is fundamentally challenging because of + // IR limitations. + C.fi(i) // ERROR HERE: \b(7|8)\b } C.fi = C.fi // ERROR HERE diff --git a/src/cmd/compile/internal/base/flag.go b/src/cmd/compile/internal/base/flag.go index 42c0c1b94b..b8b205f412 100644 --- a/src/cmd/compile/internal/base/flag.go +++ b/src/cmd/compile/internal/base/flag.go @@ -159,7 +159,11 @@ func ParseFlags() { Flag.LinkShared = &Ctxt.Flag_linkshared Flag.Shared = &Ctxt.Flag_shared Flag.WB = true + Debug.InlFuncsWithClosures = 1 + if buildcfg.Experiment.Unified { + Debug.Unified = 1 + } Debug.Checkptr = -1 // so we can tell whether it is set explicitly diff --git a/src/internal/goexperiment/exp_unified_off.go b/src/internal/goexperiment/exp_unified_off.go new file mode 100644 index 0000000000..4c16fd8562 --- /dev/null +++ b/src/internal/goexperiment/exp_unified_off.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.unified +// +build !goexperiment.unified + +package goexperiment + +const Unified = false +const UnifiedInt = 0 diff --git a/src/internal/goexperiment/exp_unified_on.go b/src/internal/goexperiment/exp_unified_on.go new file mode 100644 index 0000000000..2b17ba3e79 --- /dev/null +++ b/src/internal/goexperiment/exp_unified_on.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.unified +// +build goexperiment.unified + +package goexperiment + +const Unified = true +const UnifiedInt = 1 diff --git a/src/internal/goexperiment/flags.go b/src/internal/goexperiment/flags.go index 71e38cd047..b7a62b3e26 100644 --- a/src/internal/goexperiment/flags.go +++ b/src/internal/goexperiment/flags.go @@ -59,6 +59,10 @@ type Flags struct { PreemptibleLoops bool StaticLockRanking bool + // Unified enables the compiler's unified IR construction + // experiment. + Unified bool + // Regabi is split into several sub-experiments that can be // enabled individually. Not all combinations work. // The "regabi" GOEXPERIMENT is an alias for all "working" diff --git a/test/run.go b/test/run.go index 656519e301..f8bb8c081c 100644 --- a/test/run.go +++ b/test/run.go @@ -58,8 +58,9 @@ func defaultAllCodeGen() bool { } var ( - goos, goarch string - cgoEnabled bool + goos, goarch string + cgoEnabled bool + unifiedEnabled bool // dirs are the directories to look for *.go files in. // TODO(bradfitz): just use all directories? @@ -95,10 +96,27 @@ func main() { goos = getenv("GOOS", runtime.GOOS) goarch = getenv("GOARCH", runtime.GOARCH) - cgoEnv, err := exec.Command(goTool(), "env", "CGO_ENABLED").Output() - if err == nil { - cgoEnabled, _ = strconv.ParseBool(strings.TrimSpace(string(cgoEnv))) + + cgoCmd := exec.Command(goTool(), "env", "CGO_ENABLED") + cgoEnv, err := cgoCmd.Output() + if err != nil { + log.Fatalf("running %v: %v", cgoCmd, err) } + cgoEnabled, _ = strconv.ParseBool(strings.TrimSpace(string(cgoEnv))) + + // TODO(mdempsky): Change this to just "go env GOEXPERIMENT" after + // CL 328751 is merged back to dev.typeparams. In the mean time, we + // infer whether the "unified" experiment is defult enabled by + // inspecting the output from `go tool compile -V`. + compileCmd := exec.Command(goTool(), "tool", "compile", "-V") + compileOutput, err := compileCmd.Output() + if err != nil { + log.Fatalf("running %v: %v", compileCmd, err) + } + // TODO(mdempsky): This will give false negatives if the unified + // experiment is enabled by default, but presumably at that point we + // won't need to disable tests for it anymore anyway. + unifiedEnabled = strings.Contains(string(compileOutput), "unified") findExecCmd() @@ -290,6 +308,10 @@ type test struct { err error } +// usesTypes2 reports whether the compiler uses types2 for this test +// configuration (irrespective of flags specified by the test itself). +func (t *test) usesTypes2() bool { return unifiedEnabled || t.glevel != 0 } + func startTests(dir, gofile string, glevels []int) []*test { tests := make([]*test, len(glevels)) for i, glevel := range glevels { @@ -519,8 +541,8 @@ func (t *test) run() { close(t.donec) }() - if t.glevel > 0 && !*force { - // Files excluded from generics testing. + if t.usesTypes2() && !*force { + // Files excluded from types2 testing. filename := strings.Replace(t.goFileName(), "\\", "/", -1) // goFileName() uses \ on Windows if excludedFiles[filename] { if *verbose { @@ -666,19 +688,25 @@ func (t *test) run() { // at the specified -G level. If so, it may update flags as // necessary to test with -G. validForGLevel := func(tool Tool) bool { - if t.glevel == 0 { - // default -G level; always valid + if !t.usesTypes2() { + // tests should always pass when run w/o types2 (i.e., using the + // legacy typechecker). return true } + hasGFlag := false for _, flag := range flags { if strings.Contains(flag, "-G") { - // test provides explicit -G flag already - if *verbose { - fmt.Printf("excl\t%s\n", t.goFileName()) - } - return false + hasGFlag = true + } + } + + if hasGFlag && t.glevel != 0 { + // test provides explicit -G flag already; don't run again + if *verbose { + fmt.Printf("excl\t%s\n", t.goFileName()) } + return false } switch tool { @@ -686,7 +714,9 @@ func (t *test) run() { // ok; handled in goGcflags case Compile: - flags = append(flags, fmt.Sprintf("-G=%v", t.glevel)) + if !hasGFlag { + flags = append(flags, fmt.Sprintf("-G=%v", t.glevel)) + } default: // we don't know how to add -G for this test yet @@ -2026,6 +2056,9 @@ func overlayDir(dstRoot, srcRoot string) error { // List of files that the compiler cannot errorcheck with the new typechecker (compiler -G option). // Temporary scaffolding until we pass all the tests at which point this map can be removed. +// +// TODO(mdempsky): Split exclude list to disambiguate whether the +// failure is within types2, -G=3, or unified. var excludedFiles = map[string]bool{ "directive.go": true, // misplaced compiler directive checks "float_lit3.go": true, // types2 reports extra errors @@ -2079,10 +2112,11 @@ var excludedFiles = map[string]bool{ "fixedbugs/issue33460.go": true, // types2 reports alternative positions in separate error "fixedbugs/issue42058a.go": true, // types2 doesn't report "channel element type too large" "fixedbugs/issue42058b.go": true, // types2 doesn't report "channel element type too large" - "fixedbugs/issue46725.go": true, // fix applied to typecheck needs to be ported to irgen/transform + "fixedbugs/issue42284.go": true, // unified formats important constant expression differently in diagnostics "fixedbugs/issue4232.go": true, // types2 reports (correct) extra errors "fixedbugs/issue4452.go": true, // types2 reports (correct) extra errors "fixedbugs/issue4510.go": true, // types2 reports different (but ok) line numbers + "fixedbugs/issue46725.go": true, // fix applied to typecheck needs to be ported to irgen/transform "fixedbugs/issue5609.go": true, // types2 needs a better error message "fixedbugs/issue7525b.go": true, // types2 reports init cycle error on different line - ok otherwise "fixedbugs/issue7525c.go": true, // types2 reports init cycle error on different line - ok otherwise -- GitLab From 122f5e16d690bd14ae46e9cc7e37c0c84fdc2be8 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Wed, 16 Jun 2021 20:14:22 +0000 Subject: [PATCH 0296/2500] [dev.typeparams] internal/goarch,internal/goos: explode runtime/internal/sys into pieces This change extracts the GOOS and GOARCH specific constants from runtime/internal/sys into packages that are available to the entire standard library. This change does not yet update the runtime and associated packages to use them, and instead adds constants to runtime/internal/sys to forward the constants defined by these new packages. Change-Id: I14d574b8d7bfe599ad25da29dc1b39716e35a734 Reviewed-on: https://go-review.googlesource.com/c/go/+/328336 Trust: Michael Knyszek Run-TryBot: Michael Knyszek Reviewed-by: Matthew Dempsky TryBot-Result: Go Bot --- src/cmd/go/internal/work/gc.go | 19 ++- src/go/build/deps_test.go | 6 +- src/internal/goarch/gengoarch.go | 59 ++++++++++ .../sys/arch.go => internal/goarch/goarch.go} | 14 ++- .../goarch/goarch_386.go} | 2 +- .../goarch/goarch_amd64.go} | 2 +- .../goarch/goarch_arm.go} | 2 +- .../goarch/goarch_arm64.go} | 2 +- .../goarch/goarch_mips.go} | 2 +- .../goarch/goarch_mips64.go} | 2 +- .../goarch/goarch_mips64le.go} | 2 +- .../goarch/goarch_mipsle.go} | 2 +- .../goarch/goarch_ppc64.go} | 2 +- .../goarch/goarch_ppc64le.go} | 2 +- .../goarch/goarch_riscv64.go} | 2 +- .../goarch/goarch_s390x.go} | 2 +- .../goarch/goarch_wasm.go} | 2 +- .../sys => internal/goarch}/zgoarch_386.go | 4 +- .../sys => internal/goarch}/zgoarch_amd64.go | 4 +- .../sys => internal/goarch}/zgoarch_arm.go | 4 +- .../sys => internal/goarch}/zgoarch_arm64.go | 4 +- .../goarch}/zgoarch_arm64be.go | 4 +- .../sys => internal/goarch}/zgoarch_armbe.go | 4 +- .../sys => internal/goarch}/zgoarch_mips.go | 4 +- .../sys => internal/goarch}/zgoarch_mips64.go | 4 +- .../goarch}/zgoarch_mips64le.go | 4 +- .../goarch}/zgoarch_mips64p32.go | 4 +- .../goarch}/zgoarch_mips64p32le.go | 4 +- .../sys => internal/goarch}/zgoarch_mipsle.go | 4 +- .../sys => internal/goarch}/zgoarch_ppc.go | 4 +- .../sys => internal/goarch}/zgoarch_ppc64.go | 4 +- .../goarch}/zgoarch_ppc64le.go | 4 +- .../sys => internal/goarch}/zgoarch_riscv.go | 4 +- .../goarch}/zgoarch_riscv64.go | 4 +- .../sys => internal/goarch}/zgoarch_s390.go | 4 +- .../sys => internal/goarch}/zgoarch_s390x.go | 4 +- .../sys => internal/goarch}/zgoarch_sparc.go | 4 +- .../goarch}/zgoarch_sparc64.go | 4 +- .../sys => internal/goarch}/zgoarch_wasm.go | 4 +- .../internal/sys => internal/goos}/gengoos.go | 41 +------ src/internal/goos/goos.go | 12 ++ .../sys => internal/goos}/zgoos_aix.go | 2 +- .../sys => internal/goos}/zgoos_android.go | 2 +- .../sys => internal/goos}/zgoos_darwin.go | 2 +- .../sys => internal/goos}/zgoos_dragonfly.go | 2 +- .../sys => internal/goos}/zgoos_freebsd.go | 2 +- .../sys => internal/goos}/zgoos_hurd.go | 2 +- .../sys => internal/goos}/zgoos_illumos.go | 2 +- .../sys => internal/goos}/zgoos_ios.go | 2 +- .../sys => internal/goos}/zgoos_js.go | 2 +- .../sys => internal/goos}/zgoos_linux.go | 2 +- .../sys => internal/goos}/zgoos_netbsd.go | 2 +- .../sys => internal/goos}/zgoos_openbsd.go | 2 +- .../sys => internal/goos}/zgoos_plan9.go | 2 +- .../sys => internal/goos}/zgoos_solaris.go | 2 +- .../sys => internal/goos}/zgoos_windows.go | 2 +- .../sys => internal/goos}/zgoos_zos.go | 2 +- src/runtime/internal/sys/consts.go | 109 ++++++++++++++++++ src/runtime/internal/sys/sys.go | 8 -- 59 files changed, 284 insertions(+), 130 deletions(-) create mode 100644 src/internal/goarch/gengoarch.go rename src/{runtime/internal/sys/arch.go => internal/goarch/goarch.go} (79%) rename src/{runtime/internal/sys/arch_386.go => internal/goarch/goarch_386.go} (95%) rename src/{runtime/internal/sys/arch_amd64.go => internal/goarch/goarch_amd64.go} (95%) rename src/{runtime/internal/sys/arch_arm.go => internal/goarch/goarch_arm.go} (95%) rename src/{runtime/internal/sys/arch_arm64.go => internal/goarch/goarch_arm64.go} (95%) rename src/{runtime/internal/sys/arch_mips.go => internal/goarch/goarch_mips.go} (95%) rename src/{runtime/internal/sys/arch_mips64le.go => internal/goarch/goarch_mips64.go} (95%) rename src/{runtime/internal/sys/arch_mips64.go => internal/goarch/goarch_mips64le.go} (95%) rename src/{runtime/internal/sys/arch_mipsle.go => internal/goarch/goarch_mipsle.go} (95%) rename src/{runtime/internal/sys/arch_ppc64.go => internal/goarch/goarch_ppc64.go} (95%) rename src/{runtime/internal/sys/arch_ppc64le.go => internal/goarch/goarch_ppc64le.go} (95%) rename src/{runtime/internal/sys/arch_riscv64.go => internal/goarch/goarch_riscv64.go} (95%) rename src/{runtime/internal/sys/arch_s390x.go => internal/goarch/goarch_s390x.go} (95%) rename src/{runtime/internal/sys/arch_wasm.go => internal/goarch/goarch_wasm.go} (95%) rename src/{runtime/internal/sys => internal/goarch}/zgoarch_386.go (87%) rename src/{runtime/internal/sys => internal/goarch}/zgoarch_amd64.go (87%) rename src/{runtime/internal/sys => internal/goarch}/zgoarch_arm.go (87%) rename src/{runtime/internal/sys => internal/goarch}/zgoarch_arm64.go (87%) rename src/{runtime/internal/sys => internal/goarch}/zgoarch_arm64be.go (87%) rename src/{runtime/internal/sys => internal/goarch}/zgoarch_armbe.go (87%) rename src/{runtime/internal/sys => internal/goarch}/zgoarch_mips.go (87%) rename src/{runtime/internal/sys => internal/goarch}/zgoarch_mips64.go (87%) rename src/{runtime/internal/sys => internal/goarch}/zgoarch_mips64le.go (87%) rename src/{runtime/internal/sys => internal/goarch}/zgoarch_mips64p32.go (87%) rename src/{runtime/internal/sys => internal/goarch}/zgoarch_mips64p32le.go (87%) rename src/{runtime/internal/sys => internal/goarch}/zgoarch_mipsle.go (87%) rename src/{runtime/internal/sys => internal/goarch}/zgoarch_ppc.go (87%) rename src/{runtime/internal/sys => internal/goarch}/zgoarch_ppc64.go (87%) rename src/{runtime/internal/sys => internal/goarch}/zgoarch_ppc64le.go (87%) rename src/{runtime/internal/sys => internal/goarch}/zgoarch_riscv.go (87%) rename src/{runtime/internal/sys => internal/goarch}/zgoarch_riscv64.go (87%) rename src/{runtime/internal/sys => internal/goarch}/zgoarch_s390.go (87%) rename src/{runtime/internal/sys => internal/goarch}/zgoarch_s390x.go (87%) rename src/{runtime/internal/sys => internal/goarch}/zgoarch_sparc.go (87%) rename src/{runtime/internal/sys => internal/goarch}/zgoarch_sparc64.go (87%) rename src/{runtime/internal/sys => internal/goarch}/zgoarch_wasm.go (87%) rename src/{runtime/internal/sys => internal/goos}/gengoos.go (59%) create mode 100644 src/internal/goos/goos.go rename src/{runtime/internal/sys => internal/goos}/zgoos_aix.go (97%) rename src/{runtime/internal/sys => internal/goos}/zgoos_android.go (97%) rename src/{runtime/internal/sys => internal/goos}/zgoos_darwin.go (97%) rename src/{runtime/internal/sys => internal/goos}/zgoos_dragonfly.go (97%) rename src/{runtime/internal/sys => internal/goos}/zgoos_freebsd.go (97%) rename src/{runtime/internal/sys => internal/goos}/zgoos_hurd.go (97%) rename src/{runtime/internal/sys => internal/goos}/zgoos_illumos.go (97%) rename src/{runtime/internal/sys => internal/goos}/zgoos_ios.go (97%) rename src/{runtime/internal/sys => internal/goos}/zgoos_js.go (97%) rename src/{runtime/internal/sys => internal/goos}/zgoos_linux.go (97%) rename src/{runtime/internal/sys => internal/goos}/zgoos_netbsd.go (97%) rename src/{runtime/internal/sys => internal/goos}/zgoos_openbsd.go (97%) rename src/{runtime/internal/sys => internal/goos}/zgoos_plan9.go (97%) rename src/{runtime/internal/sys => internal/goos}/zgoos_solaris.go (97%) rename src/{runtime/internal/sys => internal/goos}/zgoos_windows.go (97%) rename src/{runtime/internal/sys => internal/goos}/zgoos_zos.go (97%) create mode 100644 src/runtime/internal/sys/consts.go diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go index 85da4f89f9..2ae908bc8f 100644 --- a/src/cmd/go/internal/work/gc.go +++ b/src/cmd/go/internal/work/gc.go @@ -29,6 +29,18 @@ import ( // The 'path' used for GOROOT_FINAL when -trimpath is specified const trimPathGoRootFinal = "go" +var runtimePackages = map[string]struct{}{ + "internal/abi": struct{}{}, + "internal/bytealg": struct{}{}, + "internal/cpu": struct{}{}, + "internal/goarch": struct{}{}, + "internal/goos": struct{}{}, + "runtime": struct{}{}, + "runtime/internal/atomic": struct{}{}, + "runtime/internal/math": struct{}{}, + "runtime/internal/sys": struct{}{}, +} + // The Go toolchain. type gcToolchain struct{} @@ -88,11 +100,8 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg if p.Standard { gcargs = append(gcargs, "-std") } - compilingRuntime := p.Standard && (p.ImportPath == "runtime" || strings.HasPrefix(p.ImportPath, "runtime/internal")) - // The runtime package imports a couple of general internal packages. - if p.Standard && (p.ImportPath == "internal/cpu" || p.ImportPath == "internal/bytealg" || p.ImportPath == "internal/abi") { - compilingRuntime = true - } + _, compilingRuntime := runtimePackages[p.ImportPath] + compilingRuntime = compilingRuntime && p.Standard if compilingRuntime { // runtime compiles with a special gc flag to check for // memory allocations that are invalid in the runtime package, diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 45e2f25df7..b440f7d235 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -71,7 +71,8 @@ var depsRules = ` # No dependencies allowed for any of these packages. NONE < container/list, container/ring, - internal/cfg, internal/cpu, internal/goexperiment, + internal/cfg, internal/cpu, internal/goarch, + internal/goexperiment, internal/goos, internal/goversion, internal/nettrace, unicode/utf8, unicode/utf16, unicode, unsafe; @@ -81,7 +82,8 @@ var depsRules = ` < internal/abi; # RUNTIME is the core runtime group of packages, all of them very light-weight. - internal/abi, internal/cpu, internal/goexperiment, unsafe + internal/abi, internal/cpu, internal/goarch, + internal/goexperiment, internal/goos, unsafe < internal/bytealg < internal/itoa < internal/unsafeheader diff --git a/src/internal/goarch/gengoarch.go b/src/internal/goarch/gengoarch.go new file mode 100644 index 0000000000..58c3b1104c --- /dev/null +++ b/src/internal/goarch/gengoarch.go @@ -0,0 +1,59 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ignore +// +build ignore + +package main + +import ( + "bytes" + "fmt" + "log" + "os" + "strconv" + "strings" +) + +var goarches []string + +func main() { + data, err := os.ReadFile("../../go/build/syslist.go") + if err != nil { + log.Fatal(err) + } + const goarchPrefix = `const goarchList = ` + for _, line := range strings.Split(string(data), "\n") { + if strings.HasPrefix(line, goarchPrefix) { + text, err := strconv.Unquote(strings.TrimPrefix(line, goarchPrefix)) + if err != nil { + log.Fatalf("parsing goarchList: %v", err) + } + goarches = strings.Fields(text) + } + } + + for _, target := range goarches { + if target == "amd64p32" { + continue + } + var buf bytes.Buffer + fmt.Fprintf(&buf, "// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.\n\n") + fmt.Fprintf(&buf, "//go:build %s\n", target) + fmt.Fprintf(&buf, "// +build %s\n\n", target) // must explicitly include target for bootstrapping purposes + fmt.Fprintf(&buf, "package goarch\n\n") + fmt.Fprintf(&buf, "const GOARCH = `%s`\n\n", target) + for _, goarch := range goarches { + value := 0 + if goarch == target { + value = 1 + } + fmt.Fprintf(&buf, "const Goarch%s = %d\n", strings.Title(goarch), value) + } + err := os.WriteFile("zgoarch_"+target+".go", buf.Bytes(), 0666) + if err != nil { + log.Fatal(err) + } + } +} diff --git a/src/runtime/internal/sys/arch.go b/src/internal/goarch/goarch.go similarity index 79% rename from src/runtime/internal/sys/arch.go rename to src/internal/goarch/goarch.go index 3c99a2f7da..8e240295b3 100644 --- a/src/runtime/internal/sys/arch.go +++ b/src/internal/goarch/goarch.go @@ -1,8 +1,15 @@ -// Copyright 2014 The Go Authors. All rights reserved. +// Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package sys +// package goarch contains GOARCH-specific constants. +package goarch + +// The next line makes 'go generate' write the zgoarch*.go files with +// per-arch information, including constants named Goarch$GOARCH for every +// GOARCH. The constant is 1 on the current system, 0 otherwise; multiplying +// by them is useful for defining GOARCH-specific constants. +//go:generate go run gengoarch.go type ArchFamilyType int @@ -23,9 +30,6 @@ const ( // It is also the size of the machine's native word size (that is, 4 on 32-bit systems, 8 on 64-bit). const PtrSize = 4 << (^uintptr(0) >> 63) -// AIX requires a larger stack for syscalls. -const StackGuardMultiplier = StackGuardMultiplierDefault*(1-GoosAix) + 2*GoosAix - // ArchFamily is the architecture family (AMD64, ARM, ...) const ArchFamily ArchFamilyType = _ArchFamily diff --git a/src/runtime/internal/sys/arch_386.go b/src/internal/goarch/goarch_386.go similarity index 95% rename from src/runtime/internal/sys/arch_386.go rename to src/internal/goarch/goarch_386.go index 1ebce3435e..c6214217fc 100644 --- a/src/runtime/internal/sys/arch_386.go +++ b/src/internal/goarch/goarch_386.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package sys +package goarch const ( _ArchFamily = I386 diff --git a/src/runtime/internal/sys/arch_amd64.go b/src/internal/goarch/goarch_amd64.go similarity index 95% rename from src/runtime/internal/sys/arch_amd64.go rename to src/internal/goarch/goarch_amd64.go index 7f003d0f1d..911e3e7242 100644 --- a/src/runtime/internal/sys/arch_amd64.go +++ b/src/internal/goarch/goarch_amd64.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package sys +package goarch const ( _ArchFamily = AMD64 diff --git a/src/runtime/internal/sys/arch_arm.go b/src/internal/goarch/goarch_arm.go similarity index 95% rename from src/runtime/internal/sys/arch_arm.go rename to src/internal/goarch/goarch_arm.go index ef2048bb71..a6591713c8 100644 --- a/src/runtime/internal/sys/arch_arm.go +++ b/src/internal/goarch/goarch_arm.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package sys +package goarch const ( _ArchFamily = ARM diff --git a/src/runtime/internal/sys/arch_arm64.go b/src/internal/goarch/goarch_arm64.go similarity index 95% rename from src/runtime/internal/sys/arch_arm64.go rename to src/internal/goarch/goarch_arm64.go index b9f2f7b1fe..85d0b47639 100644 --- a/src/runtime/internal/sys/arch_arm64.go +++ b/src/internal/goarch/goarch_arm64.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package sys +package goarch const ( _ArchFamily = ARM64 diff --git a/src/runtime/internal/sys/arch_mips.go b/src/internal/goarch/goarch_mips.go similarity index 95% rename from src/runtime/internal/sys/arch_mips.go rename to src/internal/goarch/goarch_mips.go index 4cb0eebea7..59f3995e2a 100644 --- a/src/runtime/internal/sys/arch_mips.go +++ b/src/internal/goarch/goarch_mips.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package sys +package goarch const ( _ArchFamily = MIPS diff --git a/src/runtime/internal/sys/arch_mips64le.go b/src/internal/goarch/goarch_mips64.go similarity index 95% rename from src/runtime/internal/sys/arch_mips64le.go rename to src/internal/goarch/goarch_mips64.go index 57636ac4a4..9e4f82797d 100644 --- a/src/runtime/internal/sys/arch_mips64le.go +++ b/src/internal/goarch/goarch_mips64.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package sys +package goarch const ( _ArchFamily = MIPS64 diff --git a/src/runtime/internal/sys/arch_mips64.go b/src/internal/goarch/goarch_mips64le.go similarity index 95% rename from src/runtime/internal/sys/arch_mips64.go rename to src/internal/goarch/goarch_mips64le.go index 57636ac4a4..9e4f82797d 100644 --- a/src/runtime/internal/sys/arch_mips64.go +++ b/src/internal/goarch/goarch_mips64le.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package sys +package goarch const ( _ArchFamily = MIPS64 diff --git a/src/runtime/internal/sys/arch_mipsle.go b/src/internal/goarch/goarch_mipsle.go similarity index 95% rename from src/runtime/internal/sys/arch_mipsle.go rename to src/internal/goarch/goarch_mipsle.go index 4240f5ce47..3e6642bb86 100644 --- a/src/runtime/internal/sys/arch_mipsle.go +++ b/src/internal/goarch/goarch_mipsle.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package sys +package goarch const ( _ArchFamily = MIPS diff --git a/src/runtime/internal/sys/arch_ppc64.go b/src/internal/goarch/goarch_ppc64.go similarity index 95% rename from src/runtime/internal/sys/arch_ppc64.go rename to src/internal/goarch/goarch_ppc64.go index 1869213ce2..60cc846e6a 100644 --- a/src/runtime/internal/sys/arch_ppc64.go +++ b/src/internal/goarch/goarch_ppc64.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package sys +package goarch const ( _ArchFamily = PPC64 diff --git a/src/runtime/internal/sys/arch_ppc64le.go b/src/internal/goarch/goarch_ppc64le.go similarity index 95% rename from src/runtime/internal/sys/arch_ppc64le.go rename to src/internal/goarch/goarch_ppc64le.go index 1869213ce2..60cc846e6a 100644 --- a/src/runtime/internal/sys/arch_ppc64le.go +++ b/src/internal/goarch/goarch_ppc64le.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package sys +package goarch const ( _ArchFamily = PPC64 diff --git a/src/runtime/internal/sys/arch_riscv64.go b/src/internal/goarch/goarch_riscv64.go similarity index 95% rename from src/runtime/internal/sys/arch_riscv64.go rename to src/internal/goarch/goarch_riscv64.go index 360d236e32..3b6da1e02f 100644 --- a/src/runtime/internal/sys/arch_riscv64.go +++ b/src/internal/goarch/goarch_riscv64.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package sys +package goarch const ( _ArchFamily = RISCV64 diff --git a/src/runtime/internal/sys/arch_s390x.go b/src/internal/goarch/goarch_s390x.go similarity index 95% rename from src/runtime/internal/sys/arch_s390x.go rename to src/internal/goarch/goarch_s390x.go index e33e0b7f2b..20c5705581 100644 --- a/src/runtime/internal/sys/arch_s390x.go +++ b/src/internal/goarch/goarch_s390x.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package sys +package goarch const ( _ArchFamily = S390X diff --git a/src/runtime/internal/sys/arch_wasm.go b/src/internal/goarch/goarch_wasm.go similarity index 95% rename from src/runtime/internal/sys/arch_wasm.go rename to src/internal/goarch/goarch_wasm.go index ee919ff9e6..98618d6980 100644 --- a/src/runtime/internal/sys/arch_wasm.go +++ b/src/internal/goarch/goarch_wasm.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package sys +package goarch const ( _ArchFamily = WASM diff --git a/src/runtime/internal/sys/zgoarch_386.go b/src/internal/goarch/zgoarch_386.go similarity index 87% rename from src/runtime/internal/sys/zgoarch_386.go rename to src/internal/goarch/zgoarch_386.go index 98a2401bfe..f424b5a6b9 100644 --- a/src/runtime/internal/sys/zgoarch_386.go +++ b/src/internal/goarch/zgoarch_386.go @@ -1,9 +1,9 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build 386 // +build 386 -package sys +package goarch const GOARCH = `386` diff --git a/src/runtime/internal/sys/zgoarch_amd64.go b/src/internal/goarch/zgoarch_amd64.go similarity index 87% rename from src/runtime/internal/sys/zgoarch_amd64.go rename to src/internal/goarch/zgoarch_amd64.go index d8faa5c786..728896c367 100644 --- a/src/runtime/internal/sys/zgoarch_amd64.go +++ b/src/internal/goarch/zgoarch_amd64.go @@ -1,9 +1,9 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build amd64 // +build amd64 -package sys +package goarch const GOARCH = `amd64` diff --git a/src/runtime/internal/sys/zgoarch_arm.go b/src/internal/goarch/zgoarch_arm.go similarity index 87% rename from src/runtime/internal/sys/zgoarch_arm.go rename to src/internal/goarch/zgoarch_arm.go index b64a69c9b4..9d388b0554 100644 --- a/src/runtime/internal/sys/zgoarch_arm.go +++ b/src/internal/goarch/zgoarch_arm.go @@ -1,9 +1,9 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build arm // +build arm -package sys +package goarch const GOARCH = `arm` diff --git a/src/runtime/internal/sys/zgoarch_arm64.go b/src/internal/goarch/zgoarch_arm64.go similarity index 87% rename from src/runtime/internal/sys/zgoarch_arm64.go rename to src/internal/goarch/zgoarch_arm64.go index de6f85347b..a375ac8076 100644 --- a/src/runtime/internal/sys/zgoarch_arm64.go +++ b/src/internal/goarch/zgoarch_arm64.go @@ -1,9 +1,9 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build arm64 // +build arm64 -package sys +package goarch const GOARCH = `arm64` diff --git a/src/runtime/internal/sys/zgoarch_arm64be.go b/src/internal/goarch/zgoarch_arm64be.go similarity index 87% rename from src/runtime/internal/sys/zgoarch_arm64be.go rename to src/internal/goarch/zgoarch_arm64be.go index b762bb069f..6fcc4f6bfa 100644 --- a/src/runtime/internal/sys/zgoarch_arm64be.go +++ b/src/internal/goarch/zgoarch_arm64be.go @@ -1,9 +1,9 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build arm64be // +build arm64be -package sys +package goarch const GOARCH = `arm64be` diff --git a/src/runtime/internal/sys/zgoarch_armbe.go b/src/internal/goarch/zgoarch_armbe.go similarity index 87% rename from src/runtime/internal/sys/zgoarch_armbe.go rename to src/internal/goarch/zgoarch_armbe.go index e5297e4b16..a3ac487d80 100644 --- a/src/runtime/internal/sys/zgoarch_armbe.go +++ b/src/internal/goarch/zgoarch_armbe.go @@ -1,9 +1,9 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build armbe // +build armbe -package sys +package goarch const GOARCH = `armbe` diff --git a/src/runtime/internal/sys/zgoarch_mips.go b/src/internal/goarch/zgoarch_mips.go similarity index 87% rename from src/runtime/internal/sys/zgoarch_mips.go rename to src/internal/goarch/zgoarch_mips.go index b5f4ed390c..00cfd90c3b 100644 --- a/src/runtime/internal/sys/zgoarch_mips.go +++ b/src/internal/goarch/zgoarch_mips.go @@ -1,9 +1,9 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build mips // +build mips -package sys +package goarch const GOARCH = `mips` diff --git a/src/runtime/internal/sys/zgoarch_mips64.go b/src/internal/goarch/zgoarch_mips64.go similarity index 87% rename from src/runtime/internal/sys/zgoarch_mips64.go rename to src/internal/goarch/zgoarch_mips64.go index 73777cceb2..947db612eb 100644 --- a/src/runtime/internal/sys/zgoarch_mips64.go +++ b/src/internal/goarch/zgoarch_mips64.go @@ -1,9 +1,9 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build mips64 // +build mips64 -package sys +package goarch const GOARCH = `mips64` diff --git a/src/runtime/internal/sys/zgoarch_mips64le.go b/src/internal/goarch/zgoarch_mips64le.go similarity index 87% rename from src/runtime/internal/sys/zgoarch_mips64le.go rename to src/internal/goarch/zgoarch_mips64le.go index 0c81c36c09..35ffbe2d3f 100644 --- a/src/runtime/internal/sys/zgoarch_mips64le.go +++ b/src/internal/goarch/zgoarch_mips64le.go @@ -1,9 +1,9 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build mips64le // +build mips64le -package sys +package goarch const GOARCH = `mips64le` diff --git a/src/runtime/internal/sys/zgoarch_mips64p32.go b/src/internal/goarch/zgoarch_mips64p32.go similarity index 87% rename from src/runtime/internal/sys/zgoarch_mips64p32.go rename to src/internal/goarch/zgoarch_mips64p32.go index d63ce27d24..c7c712032b 100644 --- a/src/runtime/internal/sys/zgoarch_mips64p32.go +++ b/src/internal/goarch/zgoarch_mips64p32.go @@ -1,9 +1,9 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build mips64p32 // +build mips64p32 -package sys +package goarch const GOARCH = `mips64p32` diff --git a/src/runtime/internal/sys/zgoarch_mips64p32le.go b/src/internal/goarch/zgoarch_mips64p32le.go similarity index 87% rename from src/runtime/internal/sys/zgoarch_mips64p32le.go rename to src/internal/goarch/zgoarch_mips64p32le.go index 2d577890b2..f605a6ff78 100644 --- a/src/runtime/internal/sys/zgoarch_mips64p32le.go +++ b/src/internal/goarch/zgoarch_mips64p32le.go @@ -1,9 +1,9 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build mips64p32le // +build mips64p32le -package sys +package goarch const GOARCH = `mips64p32le` diff --git a/src/runtime/internal/sys/zgoarch_mipsle.go b/src/internal/goarch/zgoarch_mipsle.go similarity index 87% rename from src/runtime/internal/sys/zgoarch_mipsle.go rename to src/internal/goarch/zgoarch_mipsle.go index 8af919d03a..56e24dc7b3 100644 --- a/src/runtime/internal/sys/zgoarch_mipsle.go +++ b/src/internal/goarch/zgoarch_mipsle.go @@ -1,9 +1,9 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build mipsle // +build mipsle -package sys +package goarch const GOARCH = `mipsle` diff --git a/src/runtime/internal/sys/zgoarch_ppc.go b/src/internal/goarch/zgoarch_ppc.go similarity index 87% rename from src/runtime/internal/sys/zgoarch_ppc.go rename to src/internal/goarch/zgoarch_ppc.go index f6f12a5ddc..4617d12792 100644 --- a/src/runtime/internal/sys/zgoarch_ppc.go +++ b/src/internal/goarch/zgoarch_ppc.go @@ -1,9 +1,9 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build ppc // +build ppc -package sys +package goarch const GOARCH = `ppc` diff --git a/src/runtime/internal/sys/zgoarch_ppc64.go b/src/internal/goarch/zgoarch_ppc64.go similarity index 87% rename from src/runtime/internal/sys/zgoarch_ppc64.go rename to src/internal/goarch/zgoarch_ppc64.go index a8379601f4..f3cb16e9b6 100644 --- a/src/runtime/internal/sys/zgoarch_ppc64.go +++ b/src/internal/goarch/zgoarch_ppc64.go @@ -1,9 +1,9 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build ppc64 // +build ppc64 -package sys +package goarch const GOARCH = `ppc64` diff --git a/src/runtime/internal/sys/zgoarch_ppc64le.go b/src/internal/goarch/zgoarch_ppc64le.go similarity index 87% rename from src/runtime/internal/sys/zgoarch_ppc64le.go rename to src/internal/goarch/zgoarch_ppc64le.go index f2ec5dcba7..b70abfb953 100644 --- a/src/runtime/internal/sys/zgoarch_ppc64le.go +++ b/src/internal/goarch/zgoarch_ppc64le.go @@ -1,9 +1,9 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build ppc64le // +build ppc64le -package sys +package goarch const GOARCH = `ppc64le` diff --git a/src/runtime/internal/sys/zgoarch_riscv.go b/src/internal/goarch/zgoarch_riscv.go similarity index 87% rename from src/runtime/internal/sys/zgoarch_riscv.go rename to src/internal/goarch/zgoarch_riscv.go index 83a3312f5f..f72973fbc5 100644 --- a/src/runtime/internal/sys/zgoarch_riscv.go +++ b/src/internal/goarch/zgoarch_riscv.go @@ -1,9 +1,9 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build riscv // +build riscv -package sys +package goarch const GOARCH = `riscv` diff --git a/src/runtime/internal/sys/zgoarch_riscv64.go b/src/internal/goarch/zgoarch_riscv64.go similarity index 87% rename from src/runtime/internal/sys/zgoarch_riscv64.go rename to src/internal/goarch/zgoarch_riscv64.go index 1dfcc84997..5d09b63a03 100644 --- a/src/runtime/internal/sys/zgoarch_riscv64.go +++ b/src/internal/goarch/zgoarch_riscv64.go @@ -1,9 +1,9 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build riscv64 // +build riscv64 -package sys +package goarch const GOARCH = `riscv64` diff --git a/src/runtime/internal/sys/zgoarch_s390.go b/src/internal/goarch/zgoarch_s390.go similarity index 87% rename from src/runtime/internal/sys/zgoarch_s390.go rename to src/internal/goarch/zgoarch_s390.go index 91aba5a0f6..0ceffe6c2e 100644 --- a/src/runtime/internal/sys/zgoarch_s390.go +++ b/src/internal/goarch/zgoarch_s390.go @@ -1,9 +1,9 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build s390 // +build s390 -package sys +package goarch const GOARCH = `s390` diff --git a/src/runtime/internal/sys/zgoarch_s390x.go b/src/internal/goarch/zgoarch_s390x.go similarity index 87% rename from src/runtime/internal/sys/zgoarch_s390x.go rename to src/internal/goarch/zgoarch_s390x.go index edce50234e..142bc0f1e3 100644 --- a/src/runtime/internal/sys/zgoarch_s390x.go +++ b/src/internal/goarch/zgoarch_s390x.go @@ -1,9 +1,9 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build s390x // +build s390x -package sys +package goarch const GOARCH = `s390x` diff --git a/src/runtime/internal/sys/zgoarch_sparc.go b/src/internal/goarch/zgoarch_sparc.go similarity index 87% rename from src/runtime/internal/sys/zgoarch_sparc.go rename to src/internal/goarch/zgoarch_sparc.go index 5ae9560ab0..62452b9d38 100644 --- a/src/runtime/internal/sys/zgoarch_sparc.go +++ b/src/internal/goarch/zgoarch_sparc.go @@ -1,9 +1,9 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build sparc // +build sparc -package sys +package goarch const GOARCH = `sparc` diff --git a/src/runtime/internal/sys/zgoarch_sparc64.go b/src/internal/goarch/zgoarch_sparc64.go similarity index 87% rename from src/runtime/internal/sys/zgoarch_sparc64.go rename to src/internal/goarch/zgoarch_sparc64.go index e2a0134aff..5149507917 100644 --- a/src/runtime/internal/sys/zgoarch_sparc64.go +++ b/src/internal/goarch/zgoarch_sparc64.go @@ -1,9 +1,9 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build sparc64 // +build sparc64 -package sys +package goarch const GOARCH = `sparc64` diff --git a/src/runtime/internal/sys/zgoarch_wasm.go b/src/internal/goarch/zgoarch_wasm.go similarity index 87% rename from src/runtime/internal/sys/zgoarch_wasm.go rename to src/internal/goarch/zgoarch_wasm.go index 52e85dea37..fd25e93e74 100644 --- a/src/runtime/internal/sys/zgoarch_wasm.go +++ b/src/internal/goarch/zgoarch_wasm.go @@ -1,9 +1,9 @@ -// Code generated by gengoos.go using 'go generate'. DO NOT EDIT. +// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build wasm // +build wasm -package sys +package goarch const GOARCH = `wasm` diff --git a/src/runtime/internal/sys/gengoos.go b/src/internal/goos/gengoos.go similarity index 59% rename from src/runtime/internal/sys/gengoos.go rename to src/internal/goos/gengoos.go index ffe962f71d..ebcdfec3ba 100644 --- a/src/runtime/internal/sys/gengoos.go +++ b/src/internal/goos/gengoos.go @@ -16,17 +16,14 @@ import ( "strings" ) -var gooses, goarches []string +var gooses []string func main() { - data, err := os.ReadFile("../../../go/build/syslist.go") + data, err := os.ReadFile("../../go/build/syslist.go") if err != nil { log.Fatal(err) } - const ( - goosPrefix = `const goosList = ` - goarchPrefix = `const goarchList = ` - ) + const goosPrefix = `const goosList = ` for _, line := range strings.Split(string(data), "\n") { if strings.HasPrefix(line, goosPrefix) { text, err := strconv.Unquote(strings.TrimPrefix(line, goosPrefix)) @@ -35,13 +32,6 @@ func main() { } gooses = strings.Fields(text) } - if strings.HasPrefix(line, goarchPrefix) { - text, err := strconv.Unquote(strings.TrimPrefix(line, goarchPrefix)) - if err != nil { - log.Fatalf("parsing goarchList: %v", err) - } - goarches = strings.Fields(text) - } } for _, target := range gooses { @@ -63,7 +53,7 @@ func main() { fmt.Fprintf(&buf, "// Code generated by gengoos.go using 'go generate'. DO NOT EDIT.\n\n") fmt.Fprintf(&buf, "//go:build %s\n", strings.Join(tags, " && ")) fmt.Fprintf(&buf, "// +build %s\n\n", strings.Join(tags, ",")) - fmt.Fprintf(&buf, "package sys\n\n") + fmt.Fprintf(&buf, "package goos\n\n") fmt.Fprintf(&buf, "const GOOS = `%s`\n\n", target) for _, goos := range gooses { value := 0 @@ -77,27 +67,4 @@ func main() { log.Fatal(err) } } - - for _, target := range goarches { - if target == "amd64p32" { - continue - } - var buf bytes.Buffer - fmt.Fprintf(&buf, "// Code generated by gengoos.go using 'go generate'. DO NOT EDIT.\n\n") - fmt.Fprintf(&buf, "//go:build %s\n", target) - fmt.Fprintf(&buf, "// +build %s\n\n", target) // must explicitly include target for bootstrapping purposes - fmt.Fprintf(&buf, "package sys\n\n") - fmt.Fprintf(&buf, "const GOARCH = `%s`\n\n", target) - for _, goarch := range goarches { - value := 0 - if goarch == target { - value = 1 - } - fmt.Fprintf(&buf, "const Goarch%s = %d\n", strings.Title(goarch), value) - } - err := os.WriteFile("zgoarch_"+target+".go", buf.Bytes(), 0666) - if err != nil { - log.Fatal(err) - } - } } diff --git a/src/internal/goos/goos.go b/src/internal/goos/goos.go new file mode 100644 index 0000000000..332cf51e5d --- /dev/null +++ b/src/internal/goos/goos.go @@ -0,0 +1,12 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// package goos contains GOOS-specific constants. +package goos + +// The next line makes 'go generate' write the zgoos*.go files with +// per-OS information, including constants named Goos$GOOS for every +// known GOOS. The constant is 1 on the current system, 0 otherwise; +// multiplying by them is useful for defining GOOS-specific constants. +//go:generate go run gengoos.go diff --git a/src/runtime/internal/sys/zgoos_aix.go b/src/internal/goos/zgoos_aix.go similarity index 97% rename from src/runtime/internal/sys/zgoos_aix.go rename to src/internal/goos/zgoos_aix.go index f3b907471f..f453a8a0a8 100644 --- a/src/runtime/internal/sys/zgoos_aix.go +++ b/src/internal/goos/zgoos_aix.go @@ -3,7 +3,7 @@ //go:build aix // +build aix -package sys +package goos const GOOS = `aix` diff --git a/src/runtime/internal/sys/zgoos_android.go b/src/internal/goos/zgoos_android.go similarity index 97% rename from src/runtime/internal/sys/zgoos_android.go rename to src/internal/goos/zgoos_android.go index e28baf7c48..d90c04f758 100644 --- a/src/runtime/internal/sys/zgoos_android.go +++ b/src/internal/goos/zgoos_android.go @@ -3,7 +3,7 @@ //go:build android // +build android -package sys +package goos const GOOS = `android` diff --git a/src/runtime/internal/sys/zgoos_darwin.go b/src/internal/goos/zgoos_darwin.go similarity index 97% rename from src/runtime/internal/sys/zgoos_darwin.go rename to src/internal/goos/zgoos_darwin.go index 3c7f7b543e..18f6c28b12 100644 --- a/src/runtime/internal/sys/zgoos_darwin.go +++ b/src/internal/goos/zgoos_darwin.go @@ -3,7 +3,7 @@ //go:build !ios && darwin // +build !ios,darwin -package sys +package goos const GOOS = `darwin` diff --git a/src/runtime/internal/sys/zgoos_dragonfly.go b/src/internal/goos/zgoos_dragonfly.go similarity index 97% rename from src/runtime/internal/sys/zgoos_dragonfly.go rename to src/internal/goos/zgoos_dragonfly.go index f844d29e2a..a658d1d07f 100644 --- a/src/runtime/internal/sys/zgoos_dragonfly.go +++ b/src/internal/goos/zgoos_dragonfly.go @@ -3,7 +3,7 @@ //go:build dragonfly // +build dragonfly -package sys +package goos const GOOS = `dragonfly` diff --git a/src/runtime/internal/sys/zgoos_freebsd.go b/src/internal/goos/zgoos_freebsd.go similarity index 97% rename from src/runtime/internal/sys/zgoos_freebsd.go rename to src/internal/goos/zgoos_freebsd.go index 8999a2797a..2534eb8c6f 100644 --- a/src/runtime/internal/sys/zgoos_freebsd.go +++ b/src/internal/goos/zgoos_freebsd.go @@ -3,7 +3,7 @@ //go:build freebsd // +build freebsd -package sys +package goos const GOOS = `freebsd` diff --git a/src/runtime/internal/sys/zgoos_hurd.go b/src/internal/goos/zgoos_hurd.go similarity index 97% rename from src/runtime/internal/sys/zgoos_hurd.go rename to src/internal/goos/zgoos_hurd.go index a546488bf8..3fefb1fbb1 100644 --- a/src/runtime/internal/sys/zgoos_hurd.go +++ b/src/internal/goos/zgoos_hurd.go @@ -3,7 +3,7 @@ //go:build hurd // +build hurd -package sys +package goos const GOOS = `hurd` diff --git a/src/runtime/internal/sys/zgoos_illumos.go b/src/internal/goos/zgoos_illumos.go similarity index 97% rename from src/runtime/internal/sys/zgoos_illumos.go rename to src/internal/goos/zgoos_illumos.go index 02a4ca06e8..77495a3369 100644 --- a/src/runtime/internal/sys/zgoos_illumos.go +++ b/src/internal/goos/zgoos_illumos.go @@ -3,7 +3,7 @@ //go:build illumos // +build illumos -package sys +package goos const GOOS = `illumos` diff --git a/src/runtime/internal/sys/zgoos_ios.go b/src/internal/goos/zgoos_ios.go similarity index 97% rename from src/runtime/internal/sys/zgoos_ios.go rename to src/internal/goos/zgoos_ios.go index 033eec623d..92820fe77e 100644 --- a/src/runtime/internal/sys/zgoos_ios.go +++ b/src/internal/goos/zgoos_ios.go @@ -3,7 +3,7 @@ //go:build ios // +build ios -package sys +package goos const GOOS = `ios` diff --git a/src/runtime/internal/sys/zgoos_js.go b/src/internal/goos/zgoos_js.go similarity index 97% rename from src/runtime/internal/sys/zgoos_js.go rename to src/internal/goos/zgoos_js.go index 28226ad60a..6331a5c3f1 100644 --- a/src/runtime/internal/sys/zgoos_js.go +++ b/src/internal/goos/zgoos_js.go @@ -3,7 +3,7 @@ //go:build js // +build js -package sys +package goos const GOOS = `js` diff --git a/src/runtime/internal/sys/zgoos_linux.go b/src/internal/goos/zgoos_linux.go similarity index 97% rename from src/runtime/internal/sys/zgoos_linux.go rename to src/internal/goos/zgoos_linux.go index 01546e4b9f..aa4e2d3145 100644 --- a/src/runtime/internal/sys/zgoos_linux.go +++ b/src/internal/goos/zgoos_linux.go @@ -3,7 +3,7 @@ //go:build !android && linux // +build !android,linux -package sys +package goos const GOOS = `linux` diff --git a/src/runtime/internal/sys/zgoos_netbsd.go b/src/internal/goos/zgoos_netbsd.go similarity index 97% rename from src/runtime/internal/sys/zgoos_netbsd.go rename to src/internal/goos/zgoos_netbsd.go index 9d658b20ee..39635104c0 100644 --- a/src/runtime/internal/sys/zgoos_netbsd.go +++ b/src/internal/goos/zgoos_netbsd.go @@ -3,7 +3,7 @@ //go:build netbsd // +build netbsd -package sys +package goos const GOOS = `netbsd` diff --git a/src/runtime/internal/sys/zgoos_openbsd.go b/src/internal/goos/zgoos_openbsd.go similarity index 97% rename from src/runtime/internal/sys/zgoos_openbsd.go rename to src/internal/goos/zgoos_openbsd.go index 0f55454a95..61d4ac8bb0 100644 --- a/src/runtime/internal/sys/zgoos_openbsd.go +++ b/src/internal/goos/zgoos_openbsd.go @@ -3,7 +3,7 @@ //go:build openbsd // +build openbsd -package sys +package goos const GOOS = `openbsd` diff --git a/src/runtime/internal/sys/zgoos_plan9.go b/src/internal/goos/zgoos_plan9.go similarity index 97% rename from src/runtime/internal/sys/zgoos_plan9.go rename to src/internal/goos/zgoos_plan9.go index d0347464d6..7f0dc2fa04 100644 --- a/src/runtime/internal/sys/zgoos_plan9.go +++ b/src/internal/goos/zgoos_plan9.go @@ -3,7 +3,7 @@ //go:build plan9 // +build plan9 -package sys +package goos const GOOS = `plan9` diff --git a/src/runtime/internal/sys/zgoos_solaris.go b/src/internal/goos/zgoos_solaris.go similarity index 97% rename from src/runtime/internal/sys/zgoos_solaris.go rename to src/internal/goos/zgoos_solaris.go index 05c3007e2c..7497324a4f 100644 --- a/src/runtime/internal/sys/zgoos_solaris.go +++ b/src/internal/goos/zgoos_solaris.go @@ -3,7 +3,7 @@ //go:build !illumos && solaris // +build !illumos,solaris -package sys +package goos const GOOS = `solaris` diff --git a/src/runtime/internal/sys/zgoos_windows.go b/src/internal/goos/zgoos_windows.go similarity index 97% rename from src/runtime/internal/sys/zgoos_windows.go rename to src/internal/goos/zgoos_windows.go index 7d07fa3a45..e316b80c82 100644 --- a/src/runtime/internal/sys/zgoos_windows.go +++ b/src/internal/goos/zgoos_windows.go @@ -3,7 +3,7 @@ //go:build windows // +build windows -package sys +package goos const GOOS = `windows` diff --git a/src/runtime/internal/sys/zgoos_zos.go b/src/internal/goos/zgoos_zos.go similarity index 97% rename from src/runtime/internal/sys/zgoos_zos.go rename to src/internal/goos/zgoos_zos.go index d6e5b9b0cb..26471f4f36 100644 --- a/src/runtime/internal/sys/zgoos_zos.go +++ b/src/internal/goos/zgoos_zos.go @@ -3,7 +3,7 @@ //go:build zos // +build zos -package sys +package goos const GOOS = `zos` diff --git a/src/runtime/internal/sys/consts.go b/src/runtime/internal/sys/consts.go new file mode 100644 index 0000000000..815f789380 --- /dev/null +++ b/src/runtime/internal/sys/consts.go @@ -0,0 +1,109 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sys + +import ( + "internal/goarch" + "internal/goos" +) + +type ArchFamilyType = goarch.ArchFamilyType + +const ( + AMD64 = goarch.AMD64 + ARM = goarch.ARM + ARM64 = goarch.ARM64 + I386 = goarch.I386 + MIPS = goarch.MIPS + MIPS64 = goarch.MIPS64 + PPC64 = goarch.PPC64 + RISCV64 = goarch.RISCV64 + S390X = goarch.S390X + WASM = goarch.WASM +) + +// PtrSize is the size of a pointer in bytes - unsafe.Sizeof(uintptr(0)) but as an ideal constant. +// It is also the size of the machine's native word size (that is, 4 on 32-bit systems, 8 on 64-bit). +const PtrSize = goarch.PtrSize + +// ArchFamily is the architecture family (AMD64, ARM, ...) +const ArchFamily ArchFamilyType = goarch.ArchFamily + +// AIX requires a larger stack for syscalls. +const StackGuardMultiplier = StackGuardMultiplierDefault*(1-goos.GoosAix) + 2*goos.GoosAix + +// BigEndian reports whether the architecture is big-endian. +const BigEndian = goarch.BigEndian + +// DefaultPhysPageSize is the default physical page size. +const DefaultPhysPageSize = goarch.DefaultPhysPageSize + +// PCQuantum is the minimal unit for a program counter (1 on x86, 4 on most other systems). +// The various PC tables record PC deltas pre-divided by PCQuantum. +const PCQuantum = goarch.PCQuantum + +// Int64Align is the required alignment for a 64-bit integer (4 on 32-bit systems, 8 on 64-bit). +const Int64Align = goarch.PtrSize + +// MinFrameSize is the size of the system-reserved words at the bottom +// of a frame (just above the architectural stack pointer). +// It is zero on x86 and PtrSize on most non-x86 (LR-based) systems. +// On PowerPC it is larger, to cover three more reserved words: +// the compiler word, the link editor word, and the TOC save word. +const MinFrameSize = goarch.MinFrameSize + +// StackAlign is the required alignment of the SP register. +// The stack must be at least word aligned, but some architectures require more. +const StackAlign = goarch.StackAlign + +const GOARCH = goarch.GOARCH + +const ( + Goarch386 = goarch.Goarch386 + GoarchAmd64 = goarch.GoarchAmd64 + GoarchAmd64p32 = goarch.GoarchAmd64p32 + GoarchArm = goarch.GoarchArm + GoarchArmbe = goarch.GoarchArmbe + GoarchArm64 = goarch.GoarchArm64 + GoarchArm64be = goarch.GoarchArm64be + GoarchPpc64 = goarch.GoarchPpc64 + GoarchPpc64le = goarch.GoarchPpc64le + GoarchMips = goarch.GoarchMips + GoarchMipsle = goarch.GoarchMipsle + GoarchMips64 = goarch.GoarchMips64 + GoarchMips64le = goarch.GoarchMips64le + GoarchMips64p32 = goarch.GoarchMips64p32 + GoarchMips64p32le = goarch.GoarchMips64p32le + GoarchPpc = goarch.GoarchPpc + GoarchRiscv = goarch.GoarchRiscv + GoarchRiscv64 = goarch.GoarchRiscv64 + GoarchS390 = goarch.GoarchS390 + GoarchS390x = goarch.GoarchS390x + GoarchSparc = goarch.GoarchSparc + GoarchSparc64 = goarch.GoarchSparc64 + GoarchWasm = goarch.GoarchWasm +) + +const GOOS = goos.GOOS + +const ( + GoosAix = goos.GoosAix + GoosAndroid = goos.GoosAndroid + GoosDarwin = goos.GoosDarwin + GoosDragonfly = goos.GoosDragonfly + GoosFreebsd = goos.GoosFreebsd + GoosHurd = goos.GoosHurd + GoosIllumos = goos.GoosIllumos + GoosIos = goos.GoosIos + GoosJs = goos.GoosJs + GoosLinux = goos.GoosLinux + GoosNacl = goos.GoosNacl + GoosNetbsd = goos.GoosNetbsd + GoosOpenbsd = goos.GoosOpenbsd + GoosPlan9 = goos.GoosPlan9 + GoosSolaris = goos.GoosSolaris + GoosWindows = goos.GoosWindows + GoosZos = goos.GoosZos +) diff --git a/src/runtime/internal/sys/sys.go b/src/runtime/internal/sys/sys.go index 9d9ac4507f..694101d36f 100644 --- a/src/runtime/internal/sys/sys.go +++ b/src/runtime/internal/sys/sys.go @@ -5,11 +5,3 @@ // package sys contains system- and configuration- and architecture-specific // constants used by the runtime. package sys - -// The next line makes 'go generate' write the zgo*.go files with -// per-OS and per-arch information, including constants -// named Goos$GOOS and Goarch$GOARCH for every -// known GOOS and GOARCH. The constant is 1 on the -// current system, 0 otherwise; multiplying by them is -// useful for defining GOOS- or GOARCH-specific constants. -//go:generate go run gengoos.go -- GitLab From 6d85891b291db01532375a7f69c24cb68b76bf11 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Wed, 16 Jun 2021 23:05:44 +0000 Subject: [PATCH 0297/2500] [dev.typeparams] runtime: replace uses of runtime/internal/sys.PtrSize with internal/goarch.PtrSize [generated] [git-generate] cd src/runtime/internal/math gofmt -w -r "sys.PtrSize -> goarch.PtrSize" . goimports -w *.go cd ../.. gofmt -w -r "sys.PtrSize -> goarch.PtrSize" . goimports -w *.go Change-Id: I43491cdd54d2e06d4d04152b3d213851b7d6d423 Reviewed-on: https://go-review.googlesource.com/c/go/+/328337 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/runtime/alg.go | 9 +- src/runtime/cgocall.go | 5 +- src/runtime/cgocheck.go | 14 +- .../export_debug_regabiargs_off_test.go | 3 +- .../export_debug_regabiargs_on_test.go | 3 +- src/runtime/export_debug_test.go | 8 +- src/runtime/export_test.go | 3 +- src/runtime/heapdump.go | 15 +- src/runtime/iface.go | 11 +- src/runtime/internal/math/math.go | 4 +- src/runtime/malloc.go | 23 +-- src/runtime/map.go | 18 +-- src/runtime/map_fast32.go | 6 +- src/runtime/map_fast64.go | 6 +- src/runtime/map_faststr.go | 56 +++---- src/runtime/map_test.go | 4 +- src/runtime/mbarrier.go | 10 +- src/runtime/mbitmap.go | 139 +++++++++--------- src/runtime/mcheckmark.go | 4 +- src/runtime/mfinal.go | 18 +-- src/runtime/mgcmark.go | 46 +++--- src/runtime/mgcstack.go | 4 +- src/runtime/mgcwork.go | 4 +- src/runtime/mheap.go | 8 +- src/runtime/mranges.go | 8 +- src/runtime/mspanset.go | 14 +- src/runtime/mstats.go | 4 +- src/runtime/mwbbuf.go | 4 +- src/runtime/os3_plan9.go | 4 +- src/runtime/os3_solaris.go | 4 +- src/runtime/os_dragonfly.go | 4 +- src/runtime/os_freebsd.go | 8 +- src/runtime/os_linux.go | 4 +- src/runtime/os_netbsd.go | 4 +- src/runtime/os_openbsd_syscall.go | 4 +- src/runtime/os_windows.go | 4 +- src/runtime/preempt.go | 4 +- src/runtime/print.go | 4 +- src/runtime/proc.go | 15 +- src/runtime/runtime1.go | 8 +- src/runtime/runtime2.go | 6 +- src/runtime/signal_386.go | 4 +- src/runtime/signal_aix_ppc64.go | 4 +- src/runtime/signal_amd64.go | 4 +- src/runtime/signal_linux_386.go | 4 +- src/runtime/signal_linux_amd64.go | 4 +- src/runtime/signal_linux_arm.go | 4 +- src/runtime/signal_linux_arm64.go | 4 +- src/runtime/signal_linux_mips64x.go | 4 +- src/runtime/signal_linux_ppc64x.go | 4 +- src/runtime/signal_linux_riscv64.go | 4 +- src/runtime/signal_linux_s390x.go | 3 +- src/runtime/signal_mips64x.go | 4 +- src/runtime/signal_riscv64.go | 6 +- src/runtime/slice.go | 15 +- src/runtime/stack.go | 23 +-- src/runtime/symtab.go | 11 +- src/runtime/sys_darwin_arm64.go | 4 +- src/runtime/sys_wasm.go | 3 +- src/runtime/sys_x86.go | 4 +- src/runtime/syscall_windows.go | 20 +-- src/runtime/trace.go | 7 +- src/runtime/traceback.go | 21 +-- 63 files changed, 349 insertions(+), 336 deletions(-) diff --git a/src/runtime/alg.go b/src/runtime/alg.go index 39c7426842..493499f2c5 100644 --- a/src/runtime/alg.go +++ b/src/runtime/alg.go @@ -7,12 +7,13 @@ package runtime import ( "internal/cpu" "runtime/internal/sys" + "internal/goarch" "unsafe" ) const ( - c0 = uintptr((8-sys.PtrSize)/4*2860486313 + (sys.PtrSize-4)/4*33054211828000289) - c1 = uintptr((8-sys.PtrSize)/4*3267000013 + (sys.PtrSize-4)/4*23344194077549503) + c0 = uintptr((8-goarch.PtrSize)/4*2860486313 + (goarch.PtrSize-4)/4*33054211828000289) + c1 = uintptr((8-goarch.PtrSize)/4*3267000013 + (goarch.PtrSize-4)/4*23344194077549503) ) func memhash0(p unsafe.Pointer, h uintptr) uintptr { @@ -300,7 +301,7 @@ func ifaceHash(i interface { return interhash(noescape(unsafe.Pointer(&i)), seed) } -const hashRandomBytes = sys.PtrSize / 4 * 64 +const hashRandomBytes = goarch.PtrSize / 4 * 64 // used in asm_{386,amd64,arm64}.s to seed the hash function var aeskeysched [hashRandomBytes]byte @@ -321,7 +322,7 @@ func alginit() { initAlgAES() return } - getRandomData((*[len(hashkey) * sys.PtrSize]byte)(unsafe.Pointer(&hashkey))[:]) + getRandomData((*[len(hashkey) * goarch.PtrSize]byte)(unsafe.Pointer(&hashkey))[:]) hashkey[0] |= 1 // make sure these numbers are odd hashkey[1] |= 1 hashkey[2] |= 1 diff --git a/src/runtime/cgocall.go b/src/runtime/cgocall.go index 0e287d0b8e..2dafda6ca4 100644 --- a/src/runtime/cgocall.go +++ b/src/runtime/cgocall.go @@ -87,6 +87,7 @@ package runtime import ( "runtime/internal/atomic" "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -470,7 +471,7 @@ func cgoCheckArg(t *_type, p unsafe.Pointer, indir, top bool, msg string) { if inheap(uintptr(unsafe.Pointer(it))) { panic(errorString(msg)) } - p = *(*unsafe.Pointer)(add(p, sys.PtrSize)) + p = *(*unsafe.Pointer)(add(p, goarch.PtrSize)) if !cgoIsGoPointer(p) { return } @@ -550,7 +551,7 @@ func cgoCheckUnknownPointer(p unsafe.Pointer, msg string) (base, i uintptr) { } hbits := heapBitsForAddr(base) n := span.elemsize - for i = uintptr(0); i < n; i += sys.PtrSize { + for i = uintptr(0); i < n; i += goarch.PtrSize { if !hbits.morePointers() { // No more possible pointers. break diff --git a/src/runtime/cgocheck.go b/src/runtime/cgocheck.go index 516045c163..3acbadf803 100644 --- a/src/runtime/cgocheck.go +++ b/src/runtime/cgocheck.go @@ -8,7 +8,7 @@ package runtime import ( - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -151,7 +151,7 @@ func cgoCheckTypedBlock(typ *_type, src unsafe.Pointer, off, size uintptr) { // src must be in the regular heap. hbits := heapBitsForAddr(uintptr(src)) - for i := uintptr(0); i < off+size; i += sys.PtrSize { + for i := uintptr(0); i < off+size; i += goarch.PtrSize { bits := hbits.bits() if i >= off && bits&bitPointer != 0 { v := *(*unsafe.Pointer)(add(src, i)) @@ -169,22 +169,22 @@ func cgoCheckTypedBlock(typ *_type, src unsafe.Pointer, off, size uintptr) { //go:nosplit //go:nowritebarrier func cgoCheckBits(src unsafe.Pointer, gcbits *byte, off, size uintptr) { - skipMask := off / sys.PtrSize / 8 - skipBytes := skipMask * sys.PtrSize * 8 + skipMask := off / goarch.PtrSize / 8 + skipBytes := skipMask * goarch.PtrSize * 8 ptrmask := addb(gcbits, skipMask) src = add(src, skipBytes) off -= skipBytes size += off var bits uint32 - for i := uintptr(0); i < size; i += sys.PtrSize { - if i&(sys.PtrSize*8-1) == 0 { + for i := uintptr(0); i < size; i += goarch.PtrSize { + if i&(goarch.PtrSize*8-1) == 0 { bits = uint32(*ptrmask) ptrmask = addb(ptrmask, 1) } else { bits >>= 1 } if off > 0 { - off -= sys.PtrSize + off -= goarch.PtrSize } else { if bits&1 != 0 { v := *(*unsafe.Pointer)(add(src, i)) diff --git a/src/runtime/export_debug_regabiargs_off_test.go b/src/runtime/export_debug_regabiargs_off_test.go index fce37ab4d1..5009003d27 100644 --- a/src/runtime/export_debug_regabiargs_off_test.go +++ b/src/runtime/export_debug_regabiargs_off_test.go @@ -3,8 +3,7 @@ // license that can be found in the LICENSE file. //go:build amd64 && linux && !goexperiment.regabiargs -// +build amd64,linux -// +build !goexperiment.regabiargs +// +build amd64,linux,!goexperiment.regabiargs package runtime diff --git a/src/runtime/export_debug_regabiargs_on_test.go b/src/runtime/export_debug_regabiargs_on_test.go index 3c65127e56..e1b72efd0f 100644 --- a/src/runtime/export_debug_regabiargs_on_test.go +++ b/src/runtime/export_debug_regabiargs_on_test.go @@ -3,8 +3,7 @@ // license that can be found in the LICENSE file. //go:build amd64 && linux && goexperiment.regabiargs -// +build amd64,linux -// +build goexperiment.regabiargs +// +build amd64,linux,goexperiment.regabiargs package runtime diff --git a/src/runtime/export_debug_test.go b/src/runtime/export_debug_test.go index 9808fd5299..a2cef02cf8 100644 --- a/src/runtime/export_debug_test.go +++ b/src/runtime/export_debug_test.go @@ -9,7 +9,7 @@ package runtime import ( "internal/abi" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -115,7 +115,7 @@ func (h *debugCallHandler) inject(info *siginfo, ctxt *sigctxt, gp2 *g) bool { return false } // Push current PC on the stack. - rsp := ctxt.rsp() - sys.PtrSize + rsp := ctxt.rsp() - goarch.PtrSize *(*uint64)(unsafe.Pointer(uintptr(rsp))) = ctxt.rip() ctxt.set_rsp(rsp) // Write the argument frame size. @@ -166,7 +166,7 @@ func (h *debugCallHandler) handle(info *siginfo, ctxt *sigctxt, gp2 *g) bool { storeRegArgs(ctxt.regs(), h.regArgs) } // Push return PC. - sp -= sys.PtrSize + sp -= goarch.PtrSize ctxt.set_rsp(sp) *(*uint64)(unsafe.Pointer(uintptr(sp))) = ctxt.rip() // Set PC to call and context register. @@ -182,7 +182,7 @@ func (h *debugCallHandler) handle(info *siginfo, ctxt *sigctxt, gp2 *g) bool { case 2: // Function panicked. Copy panic out. sp := ctxt.rsp() - memmove(unsafe.Pointer(&h.panic), unsafe.Pointer(uintptr(sp)), 2*sys.PtrSize) + memmove(unsafe.Pointer(&h.panic), unsafe.Pointer(uintptr(sp)), 2*goarch.PtrSize) case 8: // Call isn't safe. Get the reason. sp := ctxt.rsp() diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index 60c06c3f10..ae329746fe 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -9,6 +9,7 @@ package runtime import ( "runtime/internal/atomic" "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -245,7 +246,7 @@ func BenchSetType(n int, x interface{}) { }) } -const PtrSize = sys.PtrSize +const PtrSize = goarch.PtrSize var ForceGCPeriod = &forcegcperiod diff --git a/src/runtime/heapdump.go b/src/runtime/heapdump.go index 934e55f495..050628e33e 100644 --- a/src/runtime/heapdump.go +++ b/src/runtime/heapdump.go @@ -13,6 +13,7 @@ package runtime import ( "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -247,7 +248,7 @@ func dumpbv(cbv *bitvector, offset uintptr) { for i := uintptr(0); i < uintptr(cbv.n); i++ { if cbv.ptrbit(i) == 1 { dumpint(fieldKindPtr) - dumpint(uint64(offset + i*sys.PtrSize)) + dumpint(uint64(offset + i*goarch.PtrSize)) } } } @@ -298,7 +299,7 @@ func dumpframe(s *stkframe, arg unsafe.Pointer) bool { dumpbv(&child.args, child.argoff) } else { // conservative - everything might be a pointer - for off := child.argoff; off < child.argoff+child.arglen; off += sys.PtrSize { + for off := child.argoff; off < child.argoff+child.arglen; off += goarch.PtrSize { dumpint(fieldKindPtr) dumpint(uint64(off)) } @@ -307,21 +308,21 @@ func dumpframe(s *stkframe, arg unsafe.Pointer) bool { // Dump fields in the local vars section if stkmap == nil { // No locals information, dump everything. - for off := child.arglen; off < s.varp-s.sp; off += sys.PtrSize { + for off := child.arglen; off < s.varp-s.sp; off += goarch.PtrSize { dumpint(fieldKindPtr) dumpint(uint64(off)) } } else if stkmap.n < 0 { // Locals size information, dump just the locals. size := uintptr(-stkmap.n) - for off := s.varp - size - s.sp; off < s.varp-s.sp; off += sys.PtrSize { + for off := s.varp - size - s.sp; off < s.varp-s.sp; off += goarch.PtrSize { dumpint(fieldKindPtr) dumpint(uint64(off)) } } else if stkmap.n > 0 { // Locals bitmap information, scan just the pointers in // locals. - dumpbv(&bv, s.varp-uintptr(bv.n)*sys.PtrSize-s.sp) + dumpbv(&bv, s.varp-uintptr(bv.n)*goarch.PtrSize-s.sp) } dumpint(fieldKindEol) @@ -510,7 +511,7 @@ func dumpparams() { } else { dumpbool(true) // big-endian ptrs } - dumpint(sys.PtrSize) + dumpint(goarch.PtrSize) var arenaStart, arenaEnd uintptr for i1 := range mheap_.arenas { if mheap_.arenas[i1] == nil { @@ -725,7 +726,7 @@ func dumpfields(bv bitvector) { func makeheapobjbv(p uintptr, size uintptr) bitvector { // Extend the temp buffer if necessary. - nptr := size / sys.PtrSize + nptr := size / goarch.PtrSize if uintptr(len(tmpbuf)) < nptr/8+1 { if tmpbuf != nil { sysFree(unsafe.Pointer(&tmpbuf[0]), uintptr(len(tmpbuf)), &memstats.other_sys) diff --git a/src/runtime/iface.go b/src/runtime/iface.go index b397d1ff8d..67c0582363 100644 --- a/src/runtime/iface.go +++ b/src/runtime/iface.go @@ -8,6 +8,7 @@ import ( "internal/abi" "runtime/internal/atomic" "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -64,7 +65,7 @@ func getitab(inter *interfacetype, typ *_type, canfail bool) *itab { } // Entry doesn't exist yet. Make a new entry & add it. - m = (*itab)(persistentalloc(unsafe.Sizeof(itab{})+uintptr(len(inter.mhdr)-1)*sys.PtrSize, 0, &memstats.other_sys)) + m = (*itab)(persistentalloc(unsafe.Sizeof(itab{})+uintptr(len(inter.mhdr)-1)*goarch.PtrSize, 0, &memstats.other_sys)) m.inter = inter m._type = typ // The hash is used in type switches. However, compiler statically generates itab's @@ -101,7 +102,7 @@ func (t *itabTableType) find(inter *interfacetype, typ *_type) *itab { mask := t.size - 1 h := itabHashFunc(inter, typ) & mask for i := uintptr(1); ; i++ { - p := (**itab)(add(unsafe.Pointer(&t.entries), h*sys.PtrSize)) + p := (**itab)(add(unsafe.Pointer(&t.entries), h*goarch.PtrSize)) // Use atomic read here so if we see m != nil, we also see // the initializations of the fields of m. // m := *p @@ -134,7 +135,7 @@ func itabAdd(m *itab) { // t2 = new(itabTableType) + some additional entries // We lie and tell malloc we want pointer-free memory because // all the pointed-to values are not in the heap. - t2 := (*itabTableType)(mallocgc((2+2*t.size)*sys.PtrSize, nil, true)) + t2 := (*itabTableType)(mallocgc((2+2*t.size)*goarch.PtrSize, nil, true)) t2.size = t.size * 2 // Copy over entries. @@ -162,7 +163,7 @@ func (t *itabTableType) add(m *itab) { mask := t.size - 1 h := itabHashFunc(m.inter, m._type) & mask for i := uintptr(1); ; i++ { - p := (**itab)(add(unsafe.Pointer(&t.entries), h*sys.PtrSize)) + p := (**itab)(add(unsafe.Pointer(&t.entries), h*goarch.PtrSize)) m2 := *p if m2 == m { // A given itab may be used in more than one module @@ -512,7 +513,7 @@ func iterate_itabs(fn func(*itab)) { // so no other locks/atomics needed. t := itabTable for i := uintptr(0); i < t.size; i++ { - m := *(**itab)(add(unsafe.Pointer(&t.entries), i*sys.PtrSize)) + m := *(**itab)(add(unsafe.Pointer(&t.entries), i*goarch.PtrSize)) if m != nil { fn(m) } diff --git a/src/runtime/internal/math/math.go b/src/runtime/internal/math/math.go index b6bd12d3e8..c3fac366be 100644 --- a/src/runtime/internal/math/math.go +++ b/src/runtime/internal/math/math.go @@ -4,14 +4,14 @@ package math -import "runtime/internal/sys" +import "internal/goarch" const MaxUintptr = ^uintptr(0) // MulUintptr returns a * b and whether the multiplication overflowed. // On supported platforms this is an intrinsic lowered by the compiler. func MulUintptr(a, b uintptr) (uintptr, bool) { - if a|b < 1<<(4*sys.PtrSize) || a == 0 { + if a|b < 1<<(4*goarch.PtrSize) || a == 0 { return a * b, false } overflow := b > MaxUintptr/a diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index c5f62483ff..9f8e04d760 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -104,6 +104,7 @@ import ( "runtime/internal/atomic" "runtime/internal/math" "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -150,7 +151,7 @@ const ( // windows/32 | 4KB | 3 // windows/64 | 8KB | 2 // plan9 | 4KB | 3 - _NumStackOrders = 4 - sys.PtrSize/4*sys.GoosWindows - 1*sys.GoosPlan9 + _NumStackOrders = 4 - goarch.PtrSize/4*sys.GoosWindows - 1*sys.GoosPlan9 // heapAddrBits is the number of bits in a heap address. On // amd64, addresses are sign-extended beyond heapAddrBits. On @@ -251,7 +252,7 @@ const ( logHeapArenaBytes = (6+20)*(_64bit*(1-sys.GoosWindows)*(1-sys.GoarchWasm)*(1-sys.GoosIos*sys.GoarchArm64)) + (2+20)*(_64bit*sys.GoosWindows) + (2+20)*(1-_64bit) + (2+20)*sys.GoarchWasm + (2+20)*sys.GoosIos*sys.GoarchArm64 // heapArenaBitmapBytes is the size of each heap arena's bitmap. - heapArenaBitmapBytes = heapArenaBytes / (sys.PtrSize * 8 / 2) + heapArenaBitmapBytes = heapArenaBytes / (goarch.PtrSize * 8 / 2) pagesPerArena = heapArenaBytes / pageSize @@ -483,7 +484,7 @@ func mallocinit() { lockInit(&globalAlloc.mutex, lockRankGlobalAlloc) // Create initial arena growth hints. - if sys.PtrSize == 8 { + if goarch.PtrSize == 8 { // On a 64-bit machine, we pick the following hints // because: // @@ -730,7 +731,7 @@ mapped: l2 := h.arenas[ri.l1()] if l2 == nil { // Allocate an L2 arena map. - l2 = (*[1 << arenaL2Bits]*heapArena)(persistentalloc(unsafe.Sizeof(*l2), sys.PtrSize, nil)) + l2 = (*[1 << arenaL2Bits]*heapArena)(persistentalloc(unsafe.Sizeof(*l2), goarch.PtrSize, nil)) if l2 == nil { throw("out of memory allocating heap arena map") } @@ -741,9 +742,9 @@ mapped: throw("arena already initialized") } var r *heapArena - r = (*heapArena)(h.heapArenaAlloc.alloc(unsafe.Sizeof(*r), sys.PtrSize, &memstats.gcMiscSys)) + r = (*heapArena)(h.heapArenaAlloc.alloc(unsafe.Sizeof(*r), goarch.PtrSize, &memstats.gcMiscSys)) if r == nil { - r = (*heapArena)(persistentalloc(unsafe.Sizeof(*r), sys.PtrSize, &memstats.gcMiscSys)) + r = (*heapArena)(persistentalloc(unsafe.Sizeof(*r), goarch.PtrSize, &memstats.gcMiscSys)) if r == nil { throw("out of memory allocating heap arena metadata") } @@ -751,16 +752,16 @@ mapped: // Add the arena to the arenas list. if len(h.allArenas) == cap(h.allArenas) { - size := 2 * uintptr(cap(h.allArenas)) * sys.PtrSize + size := 2 * uintptr(cap(h.allArenas)) * goarch.PtrSize if size == 0 { size = physPageSize } - newArray := (*notInHeap)(persistentalloc(size, sys.PtrSize, &memstats.gcMiscSys)) + newArray := (*notInHeap)(persistentalloc(size, goarch.PtrSize, &memstats.gcMiscSys)) if newArray == nil { throw("out of memory allocating allArenas") } oldSlice := h.allArenas - *(*notInHeapSlice)(unsafe.Pointer(&h.allArenas)) = notInHeapSlice{newArray, len(h.allArenas), int(size / sys.PtrSize)} + *(*notInHeapSlice)(unsafe.Pointer(&h.allArenas)) = notInHeapSlice{newArray, len(h.allArenas), int(size / goarch.PtrSize)} copy(h.allArenas, oldSlice) // Do not free the old backing array because // there may be concurrent readers. Since we @@ -1015,7 +1016,7 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { // Align tiny pointer for required (conservative) alignment. if size&7 == 0 { off = alignUp(off, 8) - } else if sys.PtrSize == 4 && size == 12 { + } else if goarch.PtrSize == 4 && size == 12 { // Conservatively align 12-byte objects to 8 bytes on 32-bit // systems so that objects whose first field is a 64-bit // value is aligned to 8 bytes and does not cause a fault on @@ -1410,7 +1411,7 @@ func persistentalloc1(size, align uintptr, sysStat *sysMemStat) *notInHeap { break } } - persistent.off = alignUp(sys.PtrSize, align) + persistent.off = alignUp(goarch.PtrSize, align) } p := persistent.base.add(persistent.off) persistent.off += size diff --git a/src/runtime/map.go b/src/runtime/map.go index 5575040f2a..ca65d3e77f 100644 --- a/src/runtime/map.go +++ b/src/runtime/map.go @@ -57,7 +57,7 @@ import ( "internal/abi" "runtime/internal/atomic" "runtime/internal/math" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -104,7 +104,7 @@ const ( sameSizeGrow = 8 // the current map growth is to a new map of the same size // sentinel bucket ID for iterator checks - noCheck = 1<<(8*sys.PtrSize) - 1 + noCheck = 1<<(8*goarch.PtrSize) - 1 ) // isEmpty reports whether the given tophash array entry represents an empty bucket entry. @@ -183,7 +183,7 @@ type hiter struct { // bucketShift returns 1<> (sys.PtrSize*8 - 8)) + top := uint8(hash >> (goarch.PtrSize*8 - 8)) if top < minTopHash { top += minTopHash } @@ -206,11 +206,11 @@ func evacuated(b *bmap) bool { } func (b *bmap) overflow(t *maptype) *bmap { - return *(**bmap)(add(unsafe.Pointer(b), uintptr(t.bucketsize)-sys.PtrSize)) + return *(**bmap)(add(unsafe.Pointer(b), uintptr(t.bucketsize)-goarch.PtrSize)) } func (b *bmap) setoverflow(t *maptype, ovf *bmap) { - *(**bmap)(add(unsafe.Pointer(b), uintptr(t.bucketsize)-sys.PtrSize)) = ovf + *(**bmap)(add(unsafe.Pointer(b), uintptr(t.bucketsize)-goarch.PtrSize)) = ovf } func (b *bmap) keys() unsafe.Pointer { @@ -810,7 +810,7 @@ func mapiterinit(t *maptype, h *hmap, it *hiter) { return } - if unsafe.Sizeof(hiter{})/sys.PtrSize != 12 { + if unsafe.Sizeof(hiter{})/goarch.PtrSize != 12 { throw("hash_iter size incorrect") // see cmd/compile/internal/reflectdata/reflect.go } it.t = t @@ -1281,11 +1281,11 @@ func reflect_makemap(t *maptype, cap int) *hmap { if t.key.equal == nil { throw("runtime.reflect_makemap: unsupported map key type") } - if t.key.size > maxKeySize && (!t.indirectkey() || t.keysize != uint8(sys.PtrSize)) || + if t.key.size > maxKeySize && (!t.indirectkey() || t.keysize != uint8(goarch.PtrSize)) || t.key.size <= maxKeySize && (t.indirectkey() || t.keysize != uint8(t.key.size)) { throw("key size wrong") } - if t.elem.size > maxElemSize && (!t.indirectelem() || t.elemsize != uint8(sys.PtrSize)) || + if t.elem.size > maxElemSize && (!t.indirectelem() || t.elemsize != uint8(goarch.PtrSize)) || t.elem.size <= maxElemSize && (t.indirectelem() || t.elemsize != uint8(t.elem.size)) { throw("elem size wrong") } diff --git a/src/runtime/map_fast32.go b/src/runtime/map_fast32.go index 420a01daec..e80caeef55 100644 --- a/src/runtime/map_fast32.go +++ b/src/runtime/map_fast32.go @@ -6,7 +6,7 @@ package runtime import ( "internal/abi" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -302,7 +302,7 @@ search: // Only clear key if there are pointers in it. // This can only happen if pointers are 32 bit // wide as 64 bit pointers do not fit into a 32 bit key. - if sys.PtrSize == 4 && t.key.ptrdata != 0 { + if goarch.PtrSize == 4 && t.key.ptrdata != 0 { // The key must be a pointer as we checked pointers are // 32 bits wide and the key is 32 bits wide also. *(*unsafe.Pointer)(k) = nil @@ -428,7 +428,7 @@ func evacuate_fast32(t *maptype, h *hmap, oldbucket uintptr) { dst.b.tophash[dst.i&(bucketCnt-1)] = top // mask dst.i as an optimization, to avoid a bounds check // Copy key. - if sys.PtrSize == 4 && t.key.ptrdata != 0 && writeBarrier.enabled { + if goarch.PtrSize == 4 && t.key.ptrdata != 0 && writeBarrier.enabled { // Write with a write barrier. *(*unsafe.Pointer)(dst.k) = *(*unsafe.Pointer)(k) } else { diff --git a/src/runtime/map_fast64.go b/src/runtime/map_fast64.go index cb202113ac..69d8872885 100644 --- a/src/runtime/map_fast64.go +++ b/src/runtime/map_fast64.go @@ -6,7 +6,7 @@ package runtime import ( "internal/abi" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -301,7 +301,7 @@ search: } // Only clear key if there are pointers in it. if t.key.ptrdata != 0 { - if sys.PtrSize == 8 { + if goarch.PtrSize == 8 { *(*unsafe.Pointer)(k) = nil } else { // There are three ways to squeeze at one ore more 32 bit pointers into 64 bits. @@ -431,7 +431,7 @@ func evacuate_fast64(t *maptype, h *hmap, oldbucket uintptr) { // Copy key. if t.key.ptrdata != 0 && writeBarrier.enabled { - if sys.PtrSize == 8 { + if goarch.PtrSize == 8 { // Write with a write barrier. *(*unsafe.Pointer)(dst.k) = *(*unsafe.Pointer)(k) } else { diff --git a/src/runtime/map_faststr.go b/src/runtime/map_faststr.go index ed7e46b5f6..4dca882c63 100644 --- a/src/runtime/map_faststr.go +++ b/src/runtime/map_faststr.go @@ -6,7 +6,7 @@ package runtime import ( "internal/abi" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -27,7 +27,7 @@ func mapaccess1_faststr(t *maptype, h *hmap, ky string) unsafe.Pointer { b := (*bmap)(h.buckets) if key.len < 32 { // short key, doing lots of comparisons is ok - for i, kptr := uintptr(0), b.keys(); i < bucketCnt; i, kptr = i+1, add(kptr, 2*sys.PtrSize) { + for i, kptr := uintptr(0), b.keys(); i < bucketCnt; i, kptr = i+1, add(kptr, 2*goarch.PtrSize) { k := (*stringStruct)(kptr) if k.len != key.len || isEmpty(b.tophash[i]) { if b.tophash[i] == emptyRest { @@ -36,14 +36,14 @@ func mapaccess1_faststr(t *maptype, h *hmap, ky string) unsafe.Pointer { continue } if k.str == key.str || memequal(k.str, key.str, uintptr(key.len)) { - return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+i*uintptr(t.elemsize)) + return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*goarch.PtrSize+i*uintptr(t.elemsize)) } } return unsafe.Pointer(&zeroVal[0]) } // long key, try not to do more comparisons than necessary keymaybe := uintptr(bucketCnt) - for i, kptr := uintptr(0), b.keys(); i < bucketCnt; i, kptr = i+1, add(kptr, 2*sys.PtrSize) { + for i, kptr := uintptr(0), b.keys(); i < bucketCnt; i, kptr = i+1, add(kptr, 2*goarch.PtrSize) { k := (*stringStruct)(kptr) if k.len != key.len || isEmpty(b.tophash[i]) { if b.tophash[i] == emptyRest { @@ -52,7 +52,7 @@ func mapaccess1_faststr(t *maptype, h *hmap, ky string) unsafe.Pointer { continue } if k.str == key.str { - return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+i*uintptr(t.elemsize)) + return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*goarch.PtrSize+i*uintptr(t.elemsize)) } // check first 4 bytes if *((*[4]byte)(key.str)) != *((*[4]byte)(k.str)) { @@ -69,9 +69,9 @@ func mapaccess1_faststr(t *maptype, h *hmap, ky string) unsafe.Pointer { keymaybe = i } if keymaybe != bucketCnt { - k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+keymaybe*2*sys.PtrSize)) + k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+keymaybe*2*goarch.PtrSize)) if memequal(k.str, key.str, uintptr(key.len)) { - return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+keymaybe*uintptr(t.elemsize)) + return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*goarch.PtrSize+keymaybe*uintptr(t.elemsize)) } } return unsafe.Pointer(&zeroVal[0]) @@ -92,13 +92,13 @@ dohash: } top := tophash(hash) for ; b != nil; b = b.overflow(t) { - for i, kptr := uintptr(0), b.keys(); i < bucketCnt; i, kptr = i+1, add(kptr, 2*sys.PtrSize) { + for i, kptr := uintptr(0), b.keys(); i < bucketCnt; i, kptr = i+1, add(kptr, 2*goarch.PtrSize) { k := (*stringStruct)(kptr) if k.len != key.len || b.tophash[i] != top { continue } if k.str == key.str || memequal(k.str, key.str, uintptr(key.len)) { - return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+i*uintptr(t.elemsize)) + return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*goarch.PtrSize+i*uintptr(t.elemsize)) } } } @@ -122,7 +122,7 @@ func mapaccess2_faststr(t *maptype, h *hmap, ky string) (unsafe.Pointer, bool) { b := (*bmap)(h.buckets) if key.len < 32 { // short key, doing lots of comparisons is ok - for i, kptr := uintptr(0), b.keys(); i < bucketCnt; i, kptr = i+1, add(kptr, 2*sys.PtrSize) { + for i, kptr := uintptr(0), b.keys(); i < bucketCnt; i, kptr = i+1, add(kptr, 2*goarch.PtrSize) { k := (*stringStruct)(kptr) if k.len != key.len || isEmpty(b.tophash[i]) { if b.tophash[i] == emptyRest { @@ -131,14 +131,14 @@ func mapaccess2_faststr(t *maptype, h *hmap, ky string) (unsafe.Pointer, bool) { continue } if k.str == key.str || memequal(k.str, key.str, uintptr(key.len)) { - return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+i*uintptr(t.elemsize)), true + return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*goarch.PtrSize+i*uintptr(t.elemsize)), true } } return unsafe.Pointer(&zeroVal[0]), false } // long key, try not to do more comparisons than necessary keymaybe := uintptr(bucketCnt) - for i, kptr := uintptr(0), b.keys(); i < bucketCnt; i, kptr = i+1, add(kptr, 2*sys.PtrSize) { + for i, kptr := uintptr(0), b.keys(); i < bucketCnt; i, kptr = i+1, add(kptr, 2*goarch.PtrSize) { k := (*stringStruct)(kptr) if k.len != key.len || isEmpty(b.tophash[i]) { if b.tophash[i] == emptyRest { @@ -147,7 +147,7 @@ func mapaccess2_faststr(t *maptype, h *hmap, ky string) (unsafe.Pointer, bool) { continue } if k.str == key.str { - return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+i*uintptr(t.elemsize)), true + return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*goarch.PtrSize+i*uintptr(t.elemsize)), true } // check first 4 bytes if *((*[4]byte)(key.str)) != *((*[4]byte)(k.str)) { @@ -164,9 +164,9 @@ func mapaccess2_faststr(t *maptype, h *hmap, ky string) (unsafe.Pointer, bool) { keymaybe = i } if keymaybe != bucketCnt { - k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+keymaybe*2*sys.PtrSize)) + k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+keymaybe*2*goarch.PtrSize)) if memequal(k.str, key.str, uintptr(key.len)) { - return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+keymaybe*uintptr(t.elemsize)), true + return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*goarch.PtrSize+keymaybe*uintptr(t.elemsize)), true } } return unsafe.Pointer(&zeroVal[0]), false @@ -187,13 +187,13 @@ dohash: } top := tophash(hash) for ; b != nil; b = b.overflow(t) { - for i, kptr := uintptr(0), b.keys(); i < bucketCnt; i, kptr = i+1, add(kptr, 2*sys.PtrSize) { + for i, kptr := uintptr(0), b.keys(); i < bucketCnt; i, kptr = i+1, add(kptr, 2*goarch.PtrSize) { k := (*stringStruct)(kptr) if k.len != key.len || b.tophash[i] != top { continue } if k.str == key.str || memequal(k.str, key.str, uintptr(key.len)) { - return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+i*uintptr(t.elemsize)), true + return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*goarch.PtrSize+i*uintptr(t.elemsize)), true } } } @@ -246,7 +246,7 @@ bucketloop: } continue } - k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*sys.PtrSize)) + k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*goarch.PtrSize)) if k.len != key.len { continue } @@ -284,13 +284,13 @@ bucketloop: } insertb.tophash[inserti&(bucketCnt-1)] = top // mask inserti to avoid bounds checks - insertk = add(unsafe.Pointer(insertb), dataOffset+inserti*2*sys.PtrSize) + insertk = add(unsafe.Pointer(insertb), dataOffset+inserti*2*goarch.PtrSize) // store new key at insert position *((*stringStruct)(insertk)) = *key h.count++ done: - elem := add(unsafe.Pointer(insertb), dataOffset+bucketCnt*2*sys.PtrSize+inserti*uintptr(t.elemsize)) + elem := add(unsafe.Pointer(insertb), dataOffset+bucketCnt*2*goarch.PtrSize+inserti*uintptr(t.elemsize)) if h.flags&hashWriting == 0 { throw("concurrent map writes") } @@ -325,7 +325,7 @@ func mapdelete_faststr(t *maptype, h *hmap, ky string) { top := tophash(hash) search: for ; b != nil; b = b.overflow(t) { - for i, kptr := uintptr(0), b.keys(); i < bucketCnt; i, kptr = i+1, add(kptr, 2*sys.PtrSize) { + for i, kptr := uintptr(0), b.keys(); i < bucketCnt; i, kptr = i+1, add(kptr, 2*goarch.PtrSize) { k := (*stringStruct)(kptr) if k.len != key.len || b.tophash[i] != top { continue @@ -335,7 +335,7 @@ search: } // Clear key's pointer. k.str = nil - e := add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+i*uintptr(t.elemsize)) + e := add(unsafe.Pointer(b), dataOffset+bucketCnt*2*goarch.PtrSize+i*uintptr(t.elemsize)) if t.elem.ptrdata != 0 { memclrHasPointers(e, t.elem.size) } else { @@ -411,7 +411,7 @@ func evacuate_faststr(t *maptype, h *hmap, oldbucket uintptr) { x := &xy[0] x.b = (*bmap)(add(h.buckets, oldbucket*uintptr(t.bucketsize))) x.k = add(unsafe.Pointer(x.b), dataOffset) - x.e = add(x.k, bucketCnt*2*sys.PtrSize) + x.e = add(x.k, bucketCnt*2*goarch.PtrSize) if !h.sameSizeGrow() { // Only calculate y pointers if we're growing bigger. @@ -419,13 +419,13 @@ func evacuate_faststr(t *maptype, h *hmap, oldbucket uintptr) { y := &xy[1] y.b = (*bmap)(add(h.buckets, (oldbucket+newbit)*uintptr(t.bucketsize))) y.k = add(unsafe.Pointer(y.b), dataOffset) - y.e = add(y.k, bucketCnt*2*sys.PtrSize) + y.e = add(y.k, bucketCnt*2*goarch.PtrSize) } for ; b != nil; b = b.overflow(t) { k := add(unsafe.Pointer(b), dataOffset) - e := add(k, bucketCnt*2*sys.PtrSize) - for i := 0; i < bucketCnt; i, k, e = i+1, add(k, 2*sys.PtrSize), add(e, uintptr(t.elemsize)) { + e := add(k, bucketCnt*2*goarch.PtrSize) + for i := 0; i < bucketCnt; i, k, e = i+1, add(k, 2*goarch.PtrSize), add(e, uintptr(t.elemsize)) { top := b.tophash[i] if isEmpty(top) { b.tophash[i] = evacuatedEmpty @@ -451,7 +451,7 @@ func evacuate_faststr(t *maptype, h *hmap, oldbucket uintptr) { dst.b = h.newoverflow(t, dst.b) dst.i = 0 dst.k = add(unsafe.Pointer(dst.b), dataOffset) - dst.e = add(dst.k, bucketCnt*2*sys.PtrSize) + dst.e = add(dst.k, bucketCnt*2*goarch.PtrSize) } dst.b.tophash[dst.i&(bucketCnt-1)] = top // mask dst.i as an optimization, to avoid a bounds check @@ -464,7 +464,7 @@ func evacuate_faststr(t *maptype, h *hmap, oldbucket uintptr) { // key or elem arrays. That's ok, as we have the overflow pointer // at the end of the bucket to protect against pointing past the // end of the bucket. - dst.k = add(dst.k, 2*sys.PtrSize) + dst.k = add(dst.k, 2*goarch.PtrSize) dst.e = add(dst.e, uintptr(t.elemsize)) } } diff --git a/src/runtime/map_test.go b/src/runtime/map_test.go index 302b3c23c1..583be21eb3 100644 --- a/src/runtime/map_test.go +++ b/src/runtime/map_test.go @@ -9,8 +9,8 @@ import ( "math" "reflect" "runtime" - "runtime/internal/sys" "sort" + "internal/goarch" "strconv" "strings" "sync" @@ -21,7 +21,7 @@ func TestHmapSize(t *testing.T) { // The structure of hmap is defined in runtime/map.go // and in cmd/compile/internal/gc/reflect.go and must be in sync. // The size of hmap should be 48 bytes on 64 bit and 28 bytes on 32 bit platforms. - var hmapSize = uintptr(8 + 5*sys.PtrSize) + var hmapSize = uintptr(8 + 5*goarch.PtrSize) if runtime.RuntimeHmapSize != hmapSize { t.Errorf("sizeof(runtime.hmap{})==%d, want %d", runtime.RuntimeHmapSize, hmapSize) } diff --git a/src/runtime/mbarrier.go b/src/runtime/mbarrier.go index b06ee725dd..3fd1cca42c 100644 --- a/src/runtime/mbarrier.go +++ b/src/runtime/mbarrier.go @@ -15,7 +15,7 @@ package runtime import ( "internal/abi" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -197,11 +197,11 @@ func reflectlite_typedmemmove(typ *_type, dst, src unsafe.Pointer) { // off must be a multiple of sys.PtrSize. //go:linkname reflect_typedmemmovepartial reflect.typedmemmovepartial func reflect_typedmemmovepartial(typ *_type, dst, src unsafe.Pointer, off, size uintptr) { - if writeBarrier.needed && typ.ptrdata > off && size >= sys.PtrSize { - if off&(sys.PtrSize-1) != 0 { + if writeBarrier.needed && typ.ptrdata > off && size >= goarch.PtrSize { + if off&(goarch.PtrSize-1) != 0 { panic("reflect: internal error: misaligned offset") } - pwsize := alignDown(size, sys.PtrSize) + pwsize := alignDown(size, goarch.PtrSize) if poff := typ.ptrdata - off; pwsize > poff { pwsize = poff } @@ -225,7 +225,7 @@ func reflect_typedmemmovepartial(typ *_type, dst, src unsafe.Pointer, off, size // //go:nosplit func reflectcallmove(typ *_type, dst, src unsafe.Pointer, size uintptr, regs *abi.RegArgs) { - if writeBarrier.needed && typ != nil && typ.ptrdata != 0 && size >= sys.PtrSize { + if writeBarrier.needed && typ != nil && typ.ptrdata != 0 && size >= goarch.PtrSize { bulkBarrierPreWrite(uintptr(dst), uintptr(src), size) } memmove(dst, src, size) diff --git a/src/runtime/mbitmap.go b/src/runtime/mbitmap.go index 819acf40bd..124ac8f050 100644 --- a/src/runtime/mbitmap.go +++ b/src/runtime/mbitmap.go @@ -48,6 +48,7 @@ package runtime import ( "runtime/internal/atomic" "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -326,8 +327,8 @@ func heapBitsForAddr(addr uintptr) (h heapBits) { // we expect to crash in the caller. return } - h.bitp = &ha.bitmap[(addr/(sys.PtrSize*4))%heapArenaBitmapBytes] - h.shift = uint32((addr / sys.PtrSize) & 3) + h.bitp = &ha.bitmap[(addr/(goarch.PtrSize*4))%heapArenaBitmapBytes] + h.shift = uint32((addr / goarch.PtrSize) & 3) h.arena = uint32(arena) h.last = &ha.bitmap[len(ha.bitmap)-1] return @@ -557,7 +558,7 @@ func (h heapBits) isPointer() bool { // //go:nosplit func bulkBarrierPreWrite(dst, src, size uintptr) { - if (dst|src|size)&(sys.PtrSize-1) != 0 { + if (dst|src|size)&(goarch.PtrSize-1) != 0 { throw("bulkBarrierPreWrite: unaligned arguments") } if !writeBarrier.needed { @@ -592,7 +593,7 @@ func bulkBarrierPreWrite(dst, src, size uintptr) { buf := &getg().m.p.ptr().wbBuf h := heapBitsForAddr(dst) if src == 0 { - for i := uintptr(0); i < size; i += sys.PtrSize { + for i := uintptr(0); i < size; i += goarch.PtrSize { if h.isPointer() { dstx := (*uintptr)(unsafe.Pointer(dst + i)) if !buf.putFast(*dstx, 0) { @@ -602,7 +603,7 @@ func bulkBarrierPreWrite(dst, src, size uintptr) { h = h.next() } } else { - for i := uintptr(0); i < size; i += sys.PtrSize { + for i := uintptr(0); i < size; i += goarch.PtrSize { if h.isPointer() { dstx := (*uintptr)(unsafe.Pointer(dst + i)) srcx := (*uintptr)(unsafe.Pointer(src + i)) @@ -625,7 +626,7 @@ func bulkBarrierPreWrite(dst, src, size uintptr) { // created and zeroed with malloc. //go:nosplit func bulkBarrierPreWriteSrcOnly(dst, src, size uintptr) { - if (dst|src|size)&(sys.PtrSize-1) != 0 { + if (dst|src|size)&(goarch.PtrSize-1) != 0 { throw("bulkBarrierPreWrite: unaligned arguments") } if !writeBarrier.needed { @@ -633,7 +634,7 @@ func bulkBarrierPreWriteSrcOnly(dst, src, size uintptr) { } buf := &getg().m.p.ptr().wbBuf h := heapBitsForAddr(dst) - for i := uintptr(0); i < size; i += sys.PtrSize { + for i := uintptr(0); i < size; i += goarch.PtrSize { if h.isPointer() { srcx := (*uintptr)(unsafe.Pointer(src + i)) if !buf.putFast(0, *srcx) { @@ -653,17 +654,17 @@ func bulkBarrierPreWriteSrcOnly(dst, src, size uintptr) { // //go:nosplit func bulkBarrierBitmap(dst, src, size, maskOffset uintptr, bits *uint8) { - word := maskOffset / sys.PtrSize + word := maskOffset / goarch.PtrSize bits = addb(bits, word/8) mask := uint8(1) << (word % 8) buf := &getg().m.p.ptr().wbBuf - for i := uintptr(0); i < size; i += sys.PtrSize { + for i := uintptr(0); i < size; i += goarch.PtrSize { if mask == 0 { bits = addb(bits, 1) if *bits == 0 { // Skip 8 words. - i += 7 * sys.PtrSize + i += 7 * goarch.PtrSize continue } mask = 1 @@ -720,8 +721,8 @@ func typeBitsBulkBarrier(typ *_type, dst, src, size uintptr) { ptrmask := typ.gcdata buf := &getg().m.p.ptr().wbBuf var bits uint32 - for i := uintptr(0); i < typ.ptrdata; i += sys.PtrSize { - if i&(sys.PtrSize*8-1) == 0 { + for i := uintptr(0); i < typ.ptrdata; i += goarch.PtrSize { + if i&(goarch.PtrSize*8-1) == 0 { bits = uint32(*ptrmask) ptrmask = addb(ptrmask, 1) } else { @@ -751,14 +752,14 @@ func typeBitsBulkBarrier(typ *_type, dst, src, size uintptr) { // Otherwise, it initializes all words to scalar/dead. func (h heapBits) initSpan(s *mspan) { // Clear bits corresponding to objects. - nw := (s.npages << _PageShift) / sys.PtrSize + nw := (s.npages << _PageShift) / goarch.PtrSize if nw%wordsPerBitmapByte != 0 { throw("initSpan: unaligned length") } if h.shift != 0 { throw("initSpan: unaligned base") } - isPtrs := sys.PtrSize == 8 && s.elemsize == sys.PtrSize + isPtrs := goarch.PtrSize == 8 && s.elemsize == goarch.PtrSize for nw > 0 { hNext, anw := h.forwardOrBoundary(nw) nbyte := anw / wordsPerBitmapByte @@ -836,7 +837,7 @@ func heapBitsSetType(x, size, dataSize uintptr, typ *_type) { // The checks for size == sys.PtrSize and size == 2*sys.PtrSize can therefore // assume that dataSize == size without checking it explicitly. - if sys.PtrSize == 8 && size == sys.PtrSize { + if goarch.PtrSize == 8 && size == goarch.PtrSize { // It's one word and it has pointers, it must be a pointer. // Since all allocated one-word objects are pointers // (non-pointers are aggregated into tinySize allocations), @@ -862,8 +863,8 @@ func heapBitsSetType(x, size, dataSize uintptr, typ *_type) { // objects are at least 4 words long and that their bitmaps start either at the beginning // of a bitmap byte, or half-way in (h.shift of 0 and 2 respectively). - if size == 2*sys.PtrSize { - if typ.size == sys.PtrSize { + if size == 2*goarch.PtrSize { + if typ.size == goarch.PtrSize { // We're allocating a block big enough to hold two pointers. // On 64-bit, that means the actual object must be two pointers, // or else we'd have used the one-pointer-sized block. @@ -872,7 +873,7 @@ func heapBitsSetType(x, size, dataSize uintptr, typ *_type) { // just the smallest block available. Distinguish by checking dataSize. // (In general the number of instances of typ being allocated is // dataSize/typ.size.) - if sys.PtrSize == 4 && dataSize == sys.PtrSize { + if goarch.PtrSize == 4 && dataSize == goarch.PtrSize { // 1 pointer object. On 32-bit machines clear the bit for the // unused second word. *h.bitp &^= (bitPointer | bitScan | (bitPointer|bitScan)<> h.shift) & (bitPointer | bitScan) @@ -1446,7 +1447,7 @@ Phase4: print("initial bits h0.bitp=", h0.bitp, " h0.shift=", h0.shift, "\n") print("current bits h.bitp=", h.bitp, " h.shift=", h.shift, " *h.bitp=", hex(*h.bitp), "\n") print("ptrmask=", ptrmask, " p=", p, " endp=", endp, " endnb=", endnb, " pbits=", hex(pbits), " b=", hex(b), " nb=", nb, "\n") - println("at word", i, "offset", i*sys.PtrSize, "have", hex(have), "want", hex(want)) + println("at word", i, "offset", i*goarch.PtrSize, "have", hex(have), "want", hex(want)) if typ.kind&kindGCProg != 0 { println("GC program:") dumpGCProg(addb(typ.gcdata, 4)) @@ -1477,14 +1478,14 @@ var debugPtrmask struct { // so that the relevant bitmap bytes are not shared with surrounding // objects. func heapBitsSetTypeGCProg(h heapBits, progSize, elemSize, dataSize, allocSize uintptr, prog *byte) { - if sys.PtrSize == 8 && allocSize%(4*sys.PtrSize) != 0 { + if goarch.PtrSize == 8 && allocSize%(4*goarch.PtrSize) != 0 { // Alignment will be wrong. throw("heapBitsSetTypeGCProg: small allocation") } var totalBits uintptr if elemSize == dataSize { totalBits = runGCProg(prog, nil, h.bitp, 2) - if totalBits*sys.PtrSize != progSize { + if totalBits*goarch.PtrSize != progSize { println("runtime: heapBitsSetTypeGCProg: total bits", totalBits, "but progSize", progSize) throw("heapBitsSetTypeGCProg: unexpected bit count") } @@ -1499,7 +1500,7 @@ func heapBitsSetTypeGCProg(h heapBits, progSize, elemSize, dataSize, allocSize u // repeats that first element to fill the array. var trailer [40]byte // 3 varints (max 10 each) + some bytes i := 0 - if n := elemSize/sys.PtrSize - progSize/sys.PtrSize; n > 0 { + if n := elemSize/goarch.PtrSize - progSize/goarch.PtrSize; n > 0 { // literal(0) trailer[i] = 0x01 i++ @@ -1521,7 +1522,7 @@ func heapBitsSetTypeGCProg(h heapBits, progSize, elemSize, dataSize, allocSize u // repeat(elemSize/ptrSize, count-1) trailer[i] = 0x80 i++ - n := elemSize / sys.PtrSize + n := elemSize / goarch.PtrSize for ; n >= 0x80; n >>= 7 { trailer[i] = byte(n | 0x80) i++ @@ -1545,10 +1546,10 @@ func heapBitsSetTypeGCProg(h heapBits, progSize, elemSize, dataSize, allocSize u // last element. This will cause the code below to // memclr the dead section of the final array element, // so that scanobject can stop early in the final element. - totalBits = (elemSize*(count-1) + progSize) / sys.PtrSize + totalBits = (elemSize*(count-1) + progSize) / goarch.PtrSize } endProg := unsafe.Pointer(addb(h.bitp, (totalBits+3)/4)) - endAlloc := unsafe.Pointer(addb(h.bitp, allocSize/sys.PtrSize/wordsPerBitmapByte)) + endAlloc := unsafe.Pointer(addb(h.bitp, allocSize/goarch.PtrSize/wordsPerBitmapByte)) memclrNoHeapPointers(endProg, uintptr(endAlloc)-uintptr(endProg)) } @@ -1556,7 +1557,7 @@ func heapBitsSetTypeGCProg(h heapBits, progSize, elemSize, dataSize, allocSize u // size the size of the region described by prog, in bytes. // The resulting bitvector will have no more than size/sys.PtrSize bits. func progToPointerMask(prog *byte, size uintptr) bitvector { - n := (size/sys.PtrSize + 7) / 8 + n := (size/goarch.PtrSize + 7) / 8 x := (*[1 << 30]byte)(persistentalloc(n+1, 1, &memstats.buckhash_sys))[:n+1] x[len(x)-1] = 0xa1 // overflow check sentinel n = runGCProg(prog, nil, &x[0], 1) @@ -1691,7 +1692,7 @@ Run: // the pattern to a bit buffer holding at most 7 bits (a partial byte) // it will not overflow. src := dst - const maxBits = sys.PtrSize*8 - 7 + const maxBits = goarch.PtrSize*8 - 7 if n <= maxBits { // Start with bits in output buffer. pattern := bits @@ -1744,7 +1745,7 @@ Run: nb := npattern if nb+nb <= maxBits { // Double pattern until the whole uintptr is filled. - for nb <= sys.PtrSize*8 { + for nb <= goarch.PtrSize*8 { b |= b << nb nb += nb } @@ -1872,7 +1873,7 @@ Run: // The result must be deallocated with dematerializeGCProg. func materializeGCProg(ptrdata uintptr, prog *byte) *mspan { // Each word of ptrdata needs one bit in the bitmap. - bitmapBytes := divRoundUp(ptrdata, 8*sys.PtrSize) + bitmapBytes := divRoundUp(ptrdata, 8*goarch.PtrSize) // Compute the number of pages needed for bitmapBytes. pages := divRoundUp(bitmapBytes, pageSize) s := mheap_.allocManual(pages, spanAllocPtrScalarBits) @@ -1945,7 +1946,7 @@ func getgcmaskcb(frame *stkframe, ctxt unsafe.Pointer) bool { func reflect_gcbits(x interface{}) []byte { ret := getgcmask(x) typ := (*ptrtype)(unsafe.Pointer(efaceOf(&x)._type)).elem - nptr := typ.ptrdata / sys.PtrSize + nptr := typ.ptrdata / goarch.PtrSize for uintptr(len(ret)) > nptr && ret[len(ret)-1] == 0 { ret = ret[:len(ret)-1] } @@ -1965,10 +1966,10 @@ func getgcmask(ep interface{}) (mask []byte) { if datap.data <= uintptr(p) && uintptr(p) < datap.edata { bitmap := datap.gcdatamask.bytedata n := (*ptrtype)(unsafe.Pointer(t)).elem.size - mask = make([]byte, n/sys.PtrSize) - for i := uintptr(0); i < n; i += sys.PtrSize { - off := (uintptr(p) + i - datap.data) / sys.PtrSize - mask[i/sys.PtrSize] = (*addb(bitmap, off/8) >> (off % 8)) & 1 + mask = make([]byte, n/goarch.PtrSize) + for i := uintptr(0); i < n; i += goarch.PtrSize { + off := (uintptr(p) + i - datap.data) / goarch.PtrSize + mask[i/goarch.PtrSize] = (*addb(bitmap, off/8) >> (off % 8)) & 1 } return } @@ -1977,10 +1978,10 @@ func getgcmask(ep interface{}) (mask []byte) { if datap.bss <= uintptr(p) && uintptr(p) < datap.ebss { bitmap := datap.gcbssmask.bytedata n := (*ptrtype)(unsafe.Pointer(t)).elem.size - mask = make([]byte, n/sys.PtrSize) - for i := uintptr(0); i < n; i += sys.PtrSize { - off := (uintptr(p) + i - datap.bss) / sys.PtrSize - mask[i/sys.PtrSize] = (*addb(bitmap, off/8) >> (off % 8)) & 1 + mask = make([]byte, n/goarch.PtrSize) + for i := uintptr(0); i < n; i += goarch.PtrSize { + off := (uintptr(p) + i - datap.bss) / goarch.PtrSize + mask[i/goarch.PtrSize] = (*addb(bitmap, off/8) >> (off % 8)) & 1 } return } @@ -1990,13 +1991,13 @@ func getgcmask(ep interface{}) (mask []byte) { if base, s, _ := findObject(uintptr(p), 0, 0); base != 0 { hbits := heapBitsForAddr(base) n := s.elemsize - mask = make([]byte, n/sys.PtrSize) - for i := uintptr(0); i < n; i += sys.PtrSize { + mask = make([]byte, n/goarch.PtrSize) + for i := uintptr(0); i < n; i += goarch.PtrSize { if hbits.isPointer() { - mask[i/sys.PtrSize] = 1 + mask[i/goarch.PtrSize] = 1 } if !hbits.morePointers() { - mask = mask[:i/sys.PtrSize] + mask = mask[:i/goarch.PtrSize] break } hbits = hbits.next() @@ -2015,12 +2016,12 @@ func getgcmask(ep interface{}) (mask []byte) { if locals.n == 0 { return } - size := uintptr(locals.n) * sys.PtrSize + size := uintptr(locals.n) * goarch.PtrSize n := (*ptrtype)(unsafe.Pointer(t)).elem.size - mask = make([]byte, n/sys.PtrSize) - for i := uintptr(0); i < n; i += sys.PtrSize { - off := (uintptr(p) + i - frame.varp + size) / sys.PtrSize - mask[i/sys.PtrSize] = locals.ptrbit(off) + mask = make([]byte, n/goarch.PtrSize) + for i := uintptr(0); i < n; i += goarch.PtrSize { + off := (uintptr(p) + i - frame.varp + size) / goarch.PtrSize + mask[i/goarch.PtrSize] = locals.ptrbit(off) } } return diff --git a/src/runtime/mcheckmark.go b/src/runtime/mcheckmark.go index ba80ac1bdf..6a43142508 100644 --- a/src/runtime/mcheckmark.go +++ b/src/runtime/mcheckmark.go @@ -14,7 +14,7 @@ package runtime import ( "runtime/internal/atomic" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -24,7 +24,7 @@ import ( // allocation. // //go:notinheap -type checkmarksMap [heapArenaBytes / sys.PtrSize / 8]uint8 +type checkmarksMap [heapArenaBytes / goarch.PtrSize / 8]uint8 // If useCheckmark is true, marking of an object uses the checkmark // bits instead of the standard mark bits. diff --git a/src/runtime/mfinal.go b/src/runtime/mfinal.go index fd318d49a8..98f7cf793f 100644 --- a/src/runtime/mfinal.go +++ b/src/runtime/mfinal.go @@ -9,7 +9,7 @@ package runtime import ( "internal/abi" "runtime/internal/atomic" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -26,14 +26,14 @@ type finblock struct { next *finblock cnt uint32 _ int32 - fin [(_FinBlockSize - 2*sys.PtrSize - 2*4) / unsafe.Sizeof(finalizer{})]finalizer + fin [(_FinBlockSize - 2*goarch.PtrSize - 2*4) / unsafe.Sizeof(finalizer{})]finalizer } var finlock mutex // protects the following variables var fing *g // goroutine that runs finalizers var finq *finblock // list of finalizers that are to be executed var finc *finblock // cache of free blocks -var finptrmask [_FinBlockSize / sys.PtrSize / 8]byte +var finptrmask [_FinBlockSize / goarch.PtrSize / 8]byte var fingwait bool var fingwake bool var allfin *finblock // list of all blocks @@ -95,12 +95,12 @@ func queuefinalizer(p unsafe.Pointer, fn *funcval, nret uintptr, fint *_type, ot if finptrmask[0] == 0 { // Build pointer mask for Finalizer array in block. // Check assumptions made in finalizer1 array above. - if (unsafe.Sizeof(finalizer{}) != 5*sys.PtrSize || + if (unsafe.Sizeof(finalizer{}) != 5*goarch.PtrSize || unsafe.Offsetof(finalizer{}.fn) != 0 || - unsafe.Offsetof(finalizer{}.arg) != sys.PtrSize || - unsafe.Offsetof(finalizer{}.nret) != 2*sys.PtrSize || - unsafe.Offsetof(finalizer{}.fint) != 3*sys.PtrSize || - unsafe.Offsetof(finalizer{}.ot) != 4*sys.PtrSize) { + unsafe.Offsetof(finalizer{}.arg) != goarch.PtrSize || + unsafe.Offsetof(finalizer{}.nret) != 2*goarch.PtrSize || + unsafe.Offsetof(finalizer{}.fint) != 3*goarch.PtrSize || + unsafe.Offsetof(finalizer{}.ot) != 4*goarch.PtrSize) { throw("finalizer out of sync") } for i := range finptrmask { @@ -432,7 +432,7 @@ okarg: for _, t := range ft.out() { nret = alignUp(nret, uintptr(t.align)) + uintptr(t.size) } - nret = alignUp(nret, sys.PtrSize) + nret = alignUp(nret, goarch.PtrSize) // make sure we have a finalizer goroutine createfing() diff --git a/src/runtime/mgcmark.go b/src/runtime/mgcmark.go index eb70ae9f49..85c78f05a7 100644 --- a/src/runtime/mgcmark.go +++ b/src/runtime/mgcmark.go @@ -8,7 +8,7 @@ package runtime import ( "runtime/internal/atomic" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -245,7 +245,7 @@ func markroot(gcw *gcWork, i uint32) { // //go:nowritebarrier func markrootBlock(b0, n0 uintptr, ptrmask0 *uint8, gcw *gcWork, shard int) { - if rootBlockBytes%(8*sys.PtrSize) != 0 { + if rootBlockBytes%(8*goarch.PtrSize) != 0 { // This is necessary to pick byte offsets in ptrmask0. throw("rootBlockBytes must be a multiple of 8*ptrSize") } @@ -258,7 +258,7 @@ func markrootBlock(b0, n0 uintptr, ptrmask0 *uint8, gcw *gcWork, shard int) { return } b := b0 + off - ptrmask := (*uint8)(add(unsafe.Pointer(ptrmask0), uintptr(shard)*(rootBlockBytes/(8*sys.PtrSize)))) + ptrmask := (*uint8)(add(unsafe.Pointer(ptrmask0), uintptr(shard)*(rootBlockBytes/(8*goarch.PtrSize)))) n := uintptr(rootBlockBytes) if off+n > n0 { n = n0 - off @@ -372,7 +372,7 @@ func markrootSpans(gcw *gcWork, shard int) { scanobject(p, gcw) // The special itself is a root. - scanblock(uintptr(unsafe.Pointer(&spf.fn)), sys.PtrSize, &oneptrmask[0], gcw, nil) + scanblock(uintptr(unsafe.Pointer(&spf.fn)), goarch.PtrSize, &oneptrmask[0], gcw, nil) } unlock(&s.speciallock) } @@ -737,7 +737,7 @@ func scanstack(gp *g, gcw *gcWork) { // register that gets moved back and forth between the // register and sched.ctxt without a write barrier. if gp.sched.ctxt != nil { - scanblock(uintptr(unsafe.Pointer(&gp.sched.ctxt)), sys.PtrSize, &oneptrmask[0], gcw, &state) + scanblock(uintptr(unsafe.Pointer(&gp.sched.ctxt)), goarch.PtrSize, &oneptrmask[0], gcw, &state) } // Scan the stack. Accumulate a list of stack objects. @@ -755,18 +755,18 @@ func scanstack(gp *g, gcw *gcWork) { if d.fn != nil { // Scan the func value, which could be a stack allocated closure. // See issue 30453. - scanblock(uintptr(unsafe.Pointer(&d.fn)), sys.PtrSize, &oneptrmask[0], gcw, &state) + scanblock(uintptr(unsafe.Pointer(&d.fn)), goarch.PtrSize, &oneptrmask[0], gcw, &state) } if d.link != nil { // The link field of a stack-allocated defer record might point // to a heap-allocated defer record. Keep that heap record live. - scanblock(uintptr(unsafe.Pointer(&d.link)), sys.PtrSize, &oneptrmask[0], gcw, &state) + scanblock(uintptr(unsafe.Pointer(&d.link)), goarch.PtrSize, &oneptrmask[0], gcw, &state) } // Retain defers records themselves. // Defer records might not be reachable from the G through regular heap // tracing because the defer linked list might weave between the stack and the heap. if d.heap { - scanblock(uintptr(unsafe.Pointer(&d)), sys.PtrSize, &oneptrmask[0], gcw, &state) + scanblock(uintptr(unsafe.Pointer(&d)), goarch.PtrSize, &oneptrmask[0], gcw, &state) } } if gp._panic != nil { @@ -910,13 +910,13 @@ func scanframeworker(frame *stkframe, state *stackScanState, gcw *gcWork) { // Scan local variables if stack frame has been allocated. if locals.n > 0 { - size := uintptr(locals.n) * sys.PtrSize + size := uintptr(locals.n) * goarch.PtrSize scanblock(frame.varp-size, size, locals.bytedata, gcw, state) } // Scan arguments. if args.n > 0 { - scanblock(frame.argp, uintptr(args.n)*sys.PtrSize, args.bytedata, gcw, state) + scanblock(frame.argp, uintptr(args.n)*goarch.PtrSize, args.bytedata, gcw, state) } // Add all stack objects to the stack object list. @@ -1169,9 +1169,9 @@ func scanblock(b0, n0 uintptr, ptrmask *uint8, gcw *gcWork, stk *stackScanState) for i := uintptr(0); i < n; { // Find bits for the next word. - bits := uint32(*addb(ptrmask, i/(sys.PtrSize*8))) + bits := uint32(*addb(ptrmask, i/(goarch.PtrSize*8))) if bits == 0 { - i += sys.PtrSize * 8 + i += goarch.PtrSize * 8 continue } for j := 0; j < 8 && i < n; j++ { @@ -1187,7 +1187,7 @@ func scanblock(b0, n0 uintptr, ptrmask *uint8, gcw *gcWork, stk *stackScanState) } } bits >>= 1 - i += sys.PtrSize + i += goarch.PtrSize } } } @@ -1248,7 +1248,7 @@ func scanobject(b uintptr, gcw *gcWork) { } var i uintptr - for i = 0; i < n; i, hbits = i+sys.PtrSize, hbits.next() { + for i = 0; i < n; i, hbits = i+goarch.PtrSize, hbits.next() { // Load bits once. See CL 22712 and issue 16973 for discussion. bits := hbits.bits() if bits&bitScan == 0 { @@ -1297,7 +1297,7 @@ func scanConservative(b, n uintptr, ptrmask *uint8, gcw *gcWork, state *stackSca print("conservatively scanning [", hex(b), ",", hex(b+n), ")\n") hexdumpWords(b, b+n, func(p uintptr) byte { if ptrmask != nil { - word := (p - b) / sys.PtrSize + word := (p - b) / goarch.PtrSize bits := *addb(ptrmask, word/8) if (bits>>(word%8))&1 == 0 { return '$' @@ -1322,9 +1322,9 @@ func scanConservative(b, n uintptr, ptrmask *uint8, gcw *gcWork, state *stackSca printunlock() } - for i := uintptr(0); i < n; i += sys.PtrSize { + for i := uintptr(0); i < n; i += goarch.PtrSize { if ptrmask != nil { - word := i / sys.PtrSize + word := i / goarch.PtrSize bits := *addb(ptrmask, word/8) if bits == 0 { // Skip 8 words (the loop increment will do the 8th) @@ -1333,10 +1333,10 @@ func scanConservative(b, n uintptr, ptrmask *uint8, gcw *gcWork, state *stackSca // seen this word of ptrmask, so i // must be 8-word-aligned, but check // our reasoning just in case. - if i%(sys.PtrSize*8) != 0 { + if i%(goarch.PtrSize*8) != 0 { throw("misaligned mask") } - i += sys.PtrSize*8 - sys.PtrSize + i += goarch.PtrSize*8 - goarch.PtrSize continue } if (bits>>(word%8))&1 == 0 { @@ -1398,7 +1398,7 @@ func shade(b uintptr) { //go:nowritebarrierrec func greyobject(obj, base, off uintptr, span *mspan, gcw *gcWork, objIndex uintptr) { // obj should be start of allocation, and so must be at least pointer-aligned. - if obj&(sys.PtrSize-1) != 0 { + if obj&(goarch.PtrSize-1) != 0 { throw("greyobject: obj not pointer-aligned") } mbits := span.markBitsForIndex(objIndex) @@ -1470,13 +1470,13 @@ func gcDumpObject(label string, obj, off uintptr) { // We're printing something from a stack frame. We // don't know how big it is, so just show up to an // including off. - size = off + sys.PtrSize + size = off + goarch.PtrSize } - for i := uintptr(0); i < size; i += sys.PtrSize { + for i := uintptr(0); i < size; i += goarch.PtrSize { // For big objects, just print the beginning (because // that usually hints at the object's type) and the // fields around off. - if !(i < 128*sys.PtrSize || off-16*sys.PtrSize < i && i < off+16*sys.PtrSize) { + if !(i < 128*goarch.PtrSize || off-16*goarch.PtrSize < i && i < off+16*goarch.PtrSize) { skipped = true continue } diff --git a/src/runtime/mgcstack.go b/src/runtime/mgcstack.go index 92d58485f6..49dc54e165 100644 --- a/src/runtime/mgcstack.go +++ b/src/runtime/mgcstack.go @@ -95,7 +95,7 @@ package runtime import ( - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -107,7 +107,7 @@ const stackTraceDebug = false //go:notinheap type stackWorkBuf struct { stackWorkBufHdr - obj [(_WorkbufSize - unsafe.Sizeof(stackWorkBufHdr{})) / sys.PtrSize]uintptr + obj [(_WorkbufSize - unsafe.Sizeof(stackWorkBufHdr{})) / goarch.PtrSize]uintptr } // Header declaration must come after the buf declaration above, because of issue #14620. diff --git a/src/runtime/mgcwork.go b/src/runtime/mgcwork.go index 667c7afa97..9454ac46f3 100644 --- a/src/runtime/mgcwork.go +++ b/src/runtime/mgcwork.go @@ -6,7 +6,7 @@ package runtime import ( "runtime/internal/atomic" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -322,7 +322,7 @@ type workbufhdr struct { type workbuf struct { workbufhdr // account for the above fields - obj [(_WorkbufSize - unsafe.Sizeof(workbufhdr{})) / sys.PtrSize]uintptr + obj [(_WorkbufSize - unsafe.Sizeof(workbufhdr{})) / goarch.PtrSize]uintptr } // workbuf factory routines. These funcs are used to manage the diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go index 84c00ce8f8..87716a4b53 100644 --- a/src/runtime/mheap.go +++ b/src/runtime/mheap.go @@ -11,7 +11,7 @@ package runtime import ( "internal/cpu" "runtime/internal/atomic" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -497,13 +497,13 @@ func recordspan(vh unsafe.Pointer, p unsafe.Pointer) { assertLockHeld(&h.lock) if len(h.allspans) >= cap(h.allspans) { - n := 64 * 1024 / sys.PtrSize + n := 64 * 1024 / goarch.PtrSize if n < cap(h.allspans)*3/2 { n = cap(h.allspans) * 3 / 2 } var new []*mspan sp := (*slice)(unsafe.Pointer(&new)) - sp.array = sysAlloc(uintptr(n)*sys.PtrSize, &memstats.other_sys) + sp.array = sysAlloc(uintptr(n)*goarch.PtrSize, &memstats.other_sys) if sp.array == nil { throw("runtime: cannot allocate memory") } @@ -1822,7 +1822,7 @@ func addfinalizer(p unsafe.Pointer, f *funcval, nret uintptr, fint *_type, ot *p scanobject(base, gcw) // Mark the finalizer itself, since the // special isn't part of the GC'd heap. - scanblock(uintptr(unsafe.Pointer(&s.fn)), sys.PtrSize, &oneptrmask[0], gcw, nil) + scanblock(uintptr(unsafe.Pointer(&s.fn)), goarch.PtrSize, &oneptrmask[0], gcw, nil) releasem(mp) } return true diff --git a/src/runtime/mranges.go b/src/runtime/mranges.go index 84a2c06dbb..e0be1e134e 100644 --- a/src/runtime/mranges.go +++ b/src/runtime/mranges.go @@ -10,7 +10,7 @@ package runtime import ( - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -167,7 +167,7 @@ func (a *addrRanges) init(sysStat *sysMemStat) { ranges := (*notInHeapSlice)(unsafe.Pointer(&a.ranges)) ranges.len = 0 ranges.cap = 16 - ranges.array = (*notInHeap)(persistentalloc(unsafe.Sizeof(addrRange{})*uintptr(ranges.cap), sys.PtrSize, sysStat)) + ranges.array = (*notInHeap)(persistentalloc(unsafe.Sizeof(addrRange{})*uintptr(ranges.cap), goarch.PtrSize, sysStat)) a.sysStat = sysStat a.totalBytes = 0 } @@ -294,7 +294,7 @@ func (a *addrRanges) add(r addrRange) { ranges := (*notInHeapSlice)(unsafe.Pointer(&a.ranges)) ranges.len = len(oldRanges) + 1 ranges.cap = cap(oldRanges) * 2 - ranges.array = (*notInHeap)(persistentalloc(unsafe.Sizeof(addrRange{})*uintptr(ranges.cap), sys.PtrSize, a.sysStat)) + ranges.array = (*notInHeap)(persistentalloc(unsafe.Sizeof(addrRange{})*uintptr(ranges.cap), goarch.PtrSize, a.sysStat)) // Copy in the old array, but make space for the new range. copy(a.ranges[:i], oldRanges[:i]) @@ -364,7 +364,7 @@ func (a *addrRanges) cloneInto(b *addrRanges) { ranges := (*notInHeapSlice)(unsafe.Pointer(&b.ranges)) ranges.len = 0 ranges.cap = cap(a.ranges) - ranges.array = (*notInHeap)(persistentalloc(unsafe.Sizeof(addrRange{})*uintptr(ranges.cap), sys.PtrSize, b.sysStat)) + ranges.array = (*notInHeap)(persistentalloc(unsafe.Sizeof(addrRange{})*uintptr(ranges.cap), goarch.PtrSize, b.sysStat)) } b.ranges = b.ranges[:len(a.ranges)] b.totalBytes = a.totalBytes diff --git a/src/runtime/mspanset.go b/src/runtime/mspanset.go index 10d2596c38..9b0fb99c4c 100644 --- a/src/runtime/mspanset.go +++ b/src/runtime/mspanset.go @@ -7,7 +7,7 @@ package runtime import ( "internal/cpu" "runtime/internal/atomic" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -82,7 +82,7 @@ func (b *spanSet) push(s *mspan) { retry: if top < spineLen { spine := atomic.Loadp(unsafe.Pointer(&b.spine)) - blockp := add(spine, sys.PtrSize*top) + blockp := add(spine, goarch.PtrSize*top) block = (*spanSetBlock)(atomic.Loadp(blockp)) } else { // Add a new block to the spine, potentially growing @@ -102,11 +102,11 @@ retry: if newCap == 0 { newCap = spanSetInitSpineCap } - newSpine := persistentalloc(newCap*sys.PtrSize, cpu.CacheLineSize, &memstats.gcMiscSys) + newSpine := persistentalloc(newCap*goarch.PtrSize, cpu.CacheLineSize, &memstats.gcMiscSys) if b.spineCap != 0 { // Blocks are allocated off-heap, so // no write barriers. - memmove(newSpine, b.spine, b.spineCap*sys.PtrSize) + memmove(newSpine, b.spine, b.spineCap*goarch.PtrSize) } // Spine is allocated off-heap, so no write barrier. atomic.StorepNoWB(unsafe.Pointer(&b.spine), newSpine) @@ -124,7 +124,7 @@ retry: block = spanSetBlockPool.alloc() // Add it to the spine. - blockp := add(b.spine, sys.PtrSize*top) + blockp := add(b.spine, goarch.PtrSize*top) // Blocks are allocated off-heap, so no write barrier. atomic.StorepNoWB(blockp, unsafe.Pointer(block)) atomic.Storeuintptr(&b.spineLen, spineLen+1) @@ -181,7 +181,7 @@ claimLoop: // grows monotonically and we've already verified it, we'll definitely // be reading from a valid block. spine := atomic.Loadp(unsafe.Pointer(&b.spine)) - blockp := add(spine, sys.PtrSize*uintptr(top)) + blockp := add(spine, goarch.PtrSize*uintptr(top)) // Given that the spine length is correct, we know we will never // see a nil block here, since the length is always updated after @@ -241,7 +241,7 @@ func (b *spanSet) reset() { // since it may be pushed into again. In order to avoid leaking // memory since we're going to reset the head and tail, clean // up such a block now, if it exists. - blockp := (**spanSetBlock)(add(b.spine, sys.PtrSize*uintptr(top))) + blockp := (**spanSetBlock)(add(b.spine, goarch.PtrSize*uintptr(top))) block := *blockp if block != nil { // Sanity check the popped value. diff --git a/src/runtime/mstats.go b/src/runtime/mstats.go index eeb2a7b4bc..3ac88438bc 100644 --- a/src/runtime/mstats.go +++ b/src/runtime/mstats.go @@ -8,7 +8,7 @@ package runtime import ( "runtime/internal/atomic" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -713,7 +713,7 @@ type heapStatsDelta struct { // Add a uint32 to ensure this struct is a multiple of 8 bytes in size. // Only necessary on 32-bit platforms. - _ [(sys.PtrSize / 4) % 2]uint32 + _ [(goarch.PtrSize / 4) % 2]uint32 } // merge adds in the deltas from b into a. diff --git a/src/runtime/mwbbuf.go b/src/runtime/mwbbuf.go index 6efc00007d..7862dfbd9e 100644 --- a/src/runtime/mwbbuf.go +++ b/src/runtime/mwbbuf.go @@ -24,7 +24,7 @@ package runtime import ( "runtime/internal/atomic" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -145,7 +145,7 @@ func (b *wbBuf) putFast(old, new uintptr) bool { p := (*[2]uintptr)(unsafe.Pointer(b.next)) p[0] = old p[1] = new - b.next += 2 * sys.PtrSize + b.next += 2 * goarch.PtrSize return b.next != b.end } diff --git a/src/runtime/os3_plan9.go b/src/runtime/os3_plan9.go index ce8bc7f103..a06d74e279 100644 --- a/src/runtime/os3_plan9.go +++ b/src/runtime/os3_plan9.go @@ -6,7 +6,7 @@ package runtime import ( "internal/abi" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -93,7 +93,7 @@ func sighandler(_ureg *ureg, note *byte, gp *g) int { if usesLR { c.setlr(pc) } else { - sp -= sys.PtrSize + sp -= goarch.PtrSize *(*uintptr)(unsafe.Pointer(sp)) = pc c.setsp(sp) } diff --git a/src/runtime/os3_solaris.go b/src/runtime/os3_solaris.go index bfd7c7eb64..84194a3050 100644 --- a/src/runtime/os3_solaris.go +++ b/src/runtime/os3_solaris.go @@ -6,7 +6,7 @@ package runtime import ( "internal/abi" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -600,7 +600,7 @@ func sysargs(argc int32, argv **byte) { n++ // now argv+n is auxv - auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize)) + auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*goarch.PtrSize)) sysauxv(auxv[:]) } diff --git a/src/runtime/os_dragonfly.go b/src/runtime/os_dragonfly.go index 0c81ed4d7c..191a560667 100644 --- a/src/runtime/os_dragonfly.go +++ b/src/runtime/os_dragonfly.go @@ -6,7 +6,7 @@ package runtime import ( "internal/abi" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -279,7 +279,7 @@ func sysargs(argc int32, argv **byte) { // skip NULL separator n++ - auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize)) + auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*goarch.PtrSize)) sysauxv(auxv[:]) } diff --git a/src/runtime/os_freebsd.go b/src/runtime/os_freebsd.go index 151a5fd91a..5a8121a420 100644 --- a/src/runtime/os_freebsd.go +++ b/src/runtime/os_freebsd.go @@ -6,7 +6,7 @@ package runtime import ( "internal/abi" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -117,8 +117,8 @@ func getncpu() int32 { } maskSize := int(maxcpus+7) / 8 - if maskSize < sys.PtrSize { - maskSize = sys.PtrSize + if maskSize < goarch.PtrSize { + maskSize = goarch.PtrSize } if maskSize > len(mask) { maskSize = len(mask) @@ -392,7 +392,7 @@ func sysargs(argc int32, argv **byte) { n++ // now argv+n is auxv - auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize)) + auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*goarch.PtrSize)) sysauxv(auxv[:]) } diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go index 1984bf6844..88c16f7163 100644 --- a/src/runtime/os_linux.go +++ b/src/runtime/os_linux.go @@ -6,7 +6,7 @@ package runtime import ( "internal/abi" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -206,7 +206,7 @@ func sysargs(argc int32, argv **byte) { n++ // now argv+n is auxv - auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize)) + auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*goarch.PtrSize)) if sysauxv(auxv[:]) != 0 { return } diff --git a/src/runtime/os_netbsd.go b/src/runtime/os_netbsd.go index 151cd17bbe..bd936d3735 100644 --- a/src/runtime/os_netbsd.go +++ b/src/runtime/os_netbsd.go @@ -7,7 +7,7 @@ package runtime import ( "internal/abi" "runtime/internal/atomic" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -372,7 +372,7 @@ func sysargs(argc int32, argv **byte) { n++ // now argv+n is auxv - auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize)) + auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*goarch.PtrSize)) sysauxv(auxv[:]) } diff --git a/src/runtime/os_openbsd_syscall.go b/src/runtime/os_openbsd_syscall.go index a04eb4fc4d..1ddee1864e 100644 --- a/src/runtime/os_openbsd_syscall.go +++ b/src/runtime/os_openbsd_syscall.go @@ -9,7 +9,7 @@ package runtime import ( "internal/abi" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -29,7 +29,7 @@ func newosproc(mp *m) { param := tforkt{ tf_tcb: unsafe.Pointer(&mp.tls[0]), tf_tid: nil, // minit will record tid - tf_stack: uintptr(stk) - sys.PtrSize, + tf_stack: uintptr(stk) - goarch.PtrSize, } var oset sigset diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go index d82173e738..1cca0876a9 100644 --- a/src/runtime/os_windows.go +++ b/src/runtime/os_windows.go @@ -7,7 +7,7 @@ package runtime import ( "internal/abi" "runtime/internal/atomic" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -1393,7 +1393,7 @@ func preemptM(mp *m) { case "386", "amd64": // Make it look like the thread called targetPC. sp := c.sp() - sp -= sys.PtrSize + sp -= goarch.PtrSize *(*uintptr)(unsafe.Pointer(sp)) = newpc c.set_sp(sp) c.set_ip(targetPC) diff --git a/src/runtime/preempt.go b/src/runtime/preempt.go index d6cdf1b8f8..cfec196a09 100644 --- a/src/runtime/preempt.go +++ b/src/runtime/preempt.go @@ -55,7 +55,7 @@ package runtime import ( "internal/abi" "runtime/internal/atomic" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -321,7 +321,7 @@ func init() { f = findfunc(abi.FuncPCABIInternal(asyncPreempt2)) total += funcMaxSPDelta(f) // Add some overhead for return PCs, etc. - asyncPreemptStack = uintptr(total) + 8*sys.PtrSize + asyncPreemptStack = uintptr(total) + 8*goarch.PtrSize if asyncPreemptStack > _StackLimit { // We need more than the nosplit limit. This isn't // unsafe, but it may limit asynchronous preemption. diff --git a/src/runtime/print.go b/src/runtime/print.go index f15296cf02..fe32fbb08e 100644 --- a/src/runtime/print.go +++ b/src/runtime/print.go @@ -6,7 +6,7 @@ package runtime import ( "runtime/internal/atomic" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -271,7 +271,7 @@ func hexdumpWords(p, end uintptr, mark func(uintptr) byte) { var markbuf [1]byte markbuf[0] = ' ' minhexdigits = int(unsafe.Sizeof(uintptr(0)) * 2) - for i := uintptr(0); p+i < end; i += sys.PtrSize { + for i := uintptr(0); p+i < end; i += goarch.PtrSize { if i%16 == 0 { if i != 0 { println() diff --git a/src/runtime/proc.go b/src/runtime/proc.go index e4268b7109..3b1e067371 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -9,6 +9,7 @@ import ( "internal/cpu" "runtime/internal/atomic" "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -151,7 +152,7 @@ func main() { // Max stack size is 1 GB on 64-bit, 250 MB on 32-bit. // Using decimal instead of binary GB and MB because // they look nicer in the stack overflow failure message. - if sys.PtrSize == 8 { + if goarch.PtrSize == 8 { maxstacksize = 1000000000 } else { maxstacksize = 250000000 @@ -555,7 +556,7 @@ func atomicAllG() (**g, uintptr) { // atomicAllGIndex returns ptr[i] with the allgptr returned from atomicAllG. func atomicAllGIndex(ptr **g, i uintptr) *g { - return *(**g)(add(unsafe.Pointer(ptr), i*sys.PtrSize)) + return *(**g)(add(unsafe.Pointer(ptr), i*goarch.PtrSize)) } // forEachG calls fn on every G from allgs. @@ -2012,7 +2013,7 @@ func oneNewExtraM() { gp := malg(4096) gp.sched.pc = abi.FuncPCABI0(goexit) + sys.PCQuantum gp.sched.sp = gp.stack.hi - gp.sched.sp -= 4 * sys.PtrSize // extra space in case of reads slightly beyond frame + gp.sched.sp -= 4 * goarch.PtrSize // extra space in case of reads slightly beyond frame gp.sched.lr = 0 gp.sched.g = guintptr(unsafe.Pointer(gp)) gp.syscallpc = gp.sched.pc @@ -4262,7 +4263,7 @@ func newproc1(fn *funcval, callergp *g, callerpc uintptr) *g { throw("newproc1: new g is not Gdead") } - totalSize := uintptr(4*sys.PtrSize + sys.MinFrameSize) // extra space in case of reads slightly beyond frame + totalSize := uintptr(4*goarch.PtrSize + sys.MinFrameSize) // extra space in case of reads slightly beyond frame totalSize = alignUp(totalSize, sys.StackAlign) sp := newg.stack.hi - totalSize spArg := sp @@ -6390,7 +6391,7 @@ func doInit(t *initTask) { t.state = 1 // initialization in progress for i := uintptr(0); i < t.ndeps; i++ { - p := add(unsafe.Pointer(t), (3+i)*sys.PtrSize) + p := add(unsafe.Pointer(t), (3+i)*goarch.PtrSize) t2 := *(**initTask)(p) doInit(t2) } @@ -6411,9 +6412,9 @@ func doInit(t *initTask) { before = inittrace } - firstFunc := add(unsafe.Pointer(t), (3+t.ndeps)*sys.PtrSize) + firstFunc := add(unsafe.Pointer(t), (3+t.ndeps)*goarch.PtrSize) for i := uintptr(0); i < t.nfns; i++ { - p := add(firstFunc, i*sys.PtrSize) + p := add(firstFunc, i*goarch.PtrSize) f := *(*func())(unsafe.Pointer(&p)) f() } diff --git a/src/runtime/runtime1.go b/src/runtime/runtime1.go index b238da8f51..eda6aaa401 100644 --- a/src/runtime/runtime1.go +++ b/src/runtime/runtime1.go @@ -7,7 +7,7 @@ package runtime import ( "internal/bytealg" "runtime/internal/atomic" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -55,7 +55,7 @@ var ( // nosplit for use in linux startup sysargs //go:nosplit func argv_index(argv **byte, i int32) *byte { - return *(**byte)(add(unsafe.Pointer(argv), uintptr(i)*sys.PtrSize)) + return *(**byte)(add(unsafe.Pointer(argv), uintptr(i)*goarch.PtrSize)) } func args(c int32, v **byte) { @@ -190,10 +190,10 @@ func check() { if unsafe.Sizeof(j) != 8 { throw("bad j") } - if unsafe.Sizeof(k) != sys.PtrSize { + if unsafe.Sizeof(k) != goarch.PtrSize { throw("bad k") } - if unsafe.Sizeof(l) != sys.PtrSize { + if unsafe.Sizeof(l) != goarch.PtrSize { throw("bad l") } if unsafe.Sizeof(x1) != 1 { diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index f13c649a09..e2f0d5910f 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -6,7 +6,7 @@ package runtime import ( "runtime/internal/atomic" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -505,7 +505,7 @@ const ( // tlsSlots is the number of pointer-sized slots reserved for TLS on some platforms, // like Windows. tlsSlots = 6 - tlsSize = tlsSlots * sys.PtrSize + tlsSize = tlsSlots * goarch.PtrSize ) type m struct { @@ -930,7 +930,7 @@ func extendRandom(r []byte, n int) { w = 16 } h := memhash(unsafe.Pointer(&r[n-w]), uintptr(nanotime()), uintptr(w)) - for i := 0; i < sys.PtrSize && n < len(r); i++ { + for i := 0; i < goarch.PtrSize && n < len(r); i++ { r[n] = byte(h) n++ h >>= 8 diff --git a/src/runtime/signal_386.go b/src/runtime/signal_386.go index c77a9cc522..69a59e6dcf 100644 --- a/src/runtime/signal_386.go +++ b/src/runtime/signal_386.go @@ -9,7 +9,7 @@ package runtime import ( "internal/abi" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -53,7 +53,7 @@ func (c *sigctxt) preparePanic(sig uint32, gp *g) { func (c *sigctxt) pushCall(targetPC, resumePC uintptr) { // Make it look like we called target at resumePC. sp := uintptr(c.esp()) - sp -= sys.PtrSize + sp -= goarch.PtrSize *(*uintptr)(unsafe.Pointer(sp)) = resumePC c.set_esp(uint32(sp)) c.set_eip(uint32(targetPC)) diff --git a/src/runtime/signal_aix_ppc64.go b/src/runtime/signal_aix_ppc64.go index a0becd431e..5999d9dc3d 100644 --- a/src/runtime/signal_aix_ppc64.go +++ b/src/runtime/signal_aix_ppc64.go @@ -8,7 +8,7 @@ package runtime import ( - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -82,5 +82,5 @@ func (c *sigctxt) set_link(x uint64) { c.regs().lr = x } func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) } func (c *sigctxt) set_sigaddr(x uint64) { - *(*uintptr)(add(unsafe.Pointer(c.info), 2*sys.PtrSize)) = uintptr(x) + *(*uintptr)(add(unsafe.Pointer(c.info), 2*goarch.PtrSize)) = uintptr(x) } diff --git a/src/runtime/signal_amd64.go b/src/runtime/signal_amd64.go index afcf4404fb..20490cffbf 100644 --- a/src/runtime/signal_amd64.go +++ b/src/runtime/signal_amd64.go @@ -10,7 +10,7 @@ package runtime import ( "internal/abi" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -81,7 +81,7 @@ func (c *sigctxt) preparePanic(sig uint32, gp *g) { func (c *sigctxt) pushCall(targetPC, resumePC uintptr) { // Make it look like we called target at resumePC. sp := uintptr(c.rsp()) - sp -= sys.PtrSize + sp -= goarch.PtrSize *(*uintptr)(unsafe.Pointer(sp)) = resumePC c.set_rsp(uint64(sp)) c.set_rip(uint64(targetPC)) diff --git a/src/runtime/signal_linux_386.go b/src/runtime/signal_linux_386.go index 13d9df4071..321518c18e 100644 --- a/src/runtime/signal_linux_386.go +++ b/src/runtime/signal_linux_386.go @@ -5,7 +5,7 @@ package runtime import ( - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -42,5 +42,5 @@ func (c *sigctxt) set_eip(x uint32) { c.regs().eip = x } func (c *sigctxt) set_esp(x uint32) { c.regs().esp = x } func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) } func (c *sigctxt) set_sigaddr(x uint32) { - *(*uintptr)(add(unsafe.Pointer(c.info), 2*sys.PtrSize)) = uintptr(x) + *(*uintptr)(add(unsafe.Pointer(c.info), 2*goarch.PtrSize)) = uintptr(x) } diff --git a/src/runtime/signal_linux_amd64.go b/src/runtime/signal_linux_amd64.go index 210e8967e5..573b118397 100644 --- a/src/runtime/signal_linux_amd64.go +++ b/src/runtime/signal_linux_amd64.go @@ -5,7 +5,7 @@ package runtime import ( - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -52,5 +52,5 @@ func (c *sigctxt) set_rip(x uint64) { c.regs().rip = x } func (c *sigctxt) set_rsp(x uint64) { c.regs().rsp = x } func (c *sigctxt) set_sigcode(x uint64) { c.info.si_code = int32(x) } func (c *sigctxt) set_sigaddr(x uint64) { - *(*uintptr)(add(unsafe.Pointer(c.info), 2*sys.PtrSize)) = uintptr(x) + *(*uintptr)(add(unsafe.Pointer(c.info), 2*goarch.PtrSize)) = uintptr(x) } diff --git a/src/runtime/signal_linux_arm.go b/src/runtime/signal_linux_arm.go index 876b505917..eb107d68d1 100644 --- a/src/runtime/signal_linux_arm.go +++ b/src/runtime/signal_linux_arm.go @@ -5,7 +5,7 @@ package runtime import ( - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -54,5 +54,5 @@ func (c *sigctxt) set_r10(x uint32) { c.regs().r10 = x } func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) } func (c *sigctxt) set_sigaddr(x uint32) { - *(*uintptr)(add(unsafe.Pointer(c.info), 2*sys.PtrSize)) = uintptr(x) + *(*uintptr)(add(unsafe.Pointer(c.info), 2*goarch.PtrSize)) = uintptr(x) } diff --git a/src/runtime/signal_linux_arm64.go b/src/runtime/signal_linux_arm64.go index 2075f253d7..4ccc030792 100644 --- a/src/runtime/signal_linux_arm64.go +++ b/src/runtime/signal_linux_arm64.go @@ -5,7 +5,7 @@ package runtime import ( - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -67,5 +67,5 @@ func (c *sigctxt) set_lr(x uint64) { c.regs().regs[30] = x } func (c *sigctxt) set_r28(x uint64) { c.regs().regs[28] = x } func (c *sigctxt) set_sigaddr(x uint64) { - *(*uintptr)(add(unsafe.Pointer(c.info), 2*sys.PtrSize)) = uintptr(x) + *(*uintptr)(add(unsafe.Pointer(c.info), 2*goarch.PtrSize)) = uintptr(x) } diff --git a/src/runtime/signal_linux_mips64x.go b/src/runtime/signal_linux_mips64x.go index f0a75ac3ea..e62d6a93fd 100644 --- a/src/runtime/signal_linux_mips64x.go +++ b/src/runtime/signal_linux_mips64x.go @@ -9,7 +9,7 @@ package runtime import ( - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -75,5 +75,5 @@ func (c *sigctxt) set_link(x uint64) { c.regs().sc_regs[31] = x } func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) } func (c *sigctxt) set_sigaddr(x uint64) { - *(*uintptr)(add(unsafe.Pointer(c.info), 2*sys.PtrSize)) = uintptr(x) + *(*uintptr)(add(unsafe.Pointer(c.info), 2*goarch.PtrSize)) = uintptr(x) } diff --git a/src/runtime/signal_linux_ppc64x.go b/src/runtime/signal_linux_ppc64x.go index d9d3e55ec2..d2eeb39ead 100644 --- a/src/runtime/signal_linux_ppc64x.go +++ b/src/runtime/signal_linux_ppc64x.go @@ -9,7 +9,7 @@ package runtime import ( - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -79,5 +79,5 @@ func (c *sigctxt) set_link(x uint64) { c.regs().link = x } func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) } func (c *sigctxt) set_sigaddr(x uint64) { - *(*uintptr)(add(unsafe.Pointer(c.info), 2*sys.PtrSize)) = uintptr(x) + *(*uintptr)(add(unsafe.Pointer(c.info), 2*goarch.PtrSize)) = uintptr(x) } diff --git a/src/runtime/signal_linux_riscv64.go b/src/runtime/signal_linux_riscv64.go index 9f68e5c548..b26450dbfa 100644 --- a/src/runtime/signal_linux_riscv64.go +++ b/src/runtime/signal_linux_riscv64.go @@ -5,7 +5,7 @@ package runtime import ( - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -64,5 +64,5 @@ func (c *sigctxt) set_gp(x uint64) { c.regs().sc_regs.gp = x } func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) } func (c *sigctxt) set_sigaddr(x uint64) { - *(*uintptr)(add(unsafe.Pointer(c.info), 2*sys.PtrSize)) = uintptr(x) + *(*uintptr)(add(unsafe.Pointer(c.info), 2*goarch.PtrSize)) = uintptr(x) } diff --git a/src/runtime/signal_linux_s390x.go b/src/runtime/signal_linux_s390x.go index 03c58cbbb6..bba8169ded 100644 --- a/src/runtime/signal_linux_s390x.go +++ b/src/runtime/signal_linux_s390x.go @@ -7,6 +7,7 @@ package runtime import ( "internal/abi" "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -54,7 +55,7 @@ func (c *sigctxt) set_sp(x uint64) { c.regs().gregs[15] = x } func (c *sigctxt) set_pc(x uint64) { c.regs().psw_addr = x } func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) } func (c *sigctxt) set_sigaddr(x uint64) { - *(*uintptr)(add(unsafe.Pointer(c.info), 2*sys.PtrSize)) = uintptr(x) + *(*uintptr)(add(unsafe.Pointer(c.info), 2*goarch.PtrSize)) = uintptr(x) } func dumpregs(c *sigctxt) { diff --git a/src/runtime/signal_mips64x.go b/src/runtime/signal_mips64x.go index eebcc74886..87dfa724c4 100644 --- a/src/runtime/signal_mips64x.go +++ b/src/runtime/signal_mips64x.go @@ -10,7 +10,7 @@ package runtime import ( "internal/abi" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -69,7 +69,7 @@ func (c *sigctxt) preparePanic(sig uint32, gp *g) { // functions are correctly handled. This smashes // the stack frame but we're not going back there // anyway. - sp := c.sp() - sys.PtrSize + sp := c.sp() - goarch.PtrSize c.set_sp(sp) *(*uint64)(unsafe.Pointer(uintptr(sp))) = c.link() diff --git a/src/runtime/signal_riscv64.go b/src/runtime/signal_riscv64.go index aaaa217051..8a24e4e36a 100644 --- a/src/runtime/signal_riscv64.go +++ b/src/runtime/signal_riscv64.go @@ -9,7 +9,7 @@ package runtime import ( "internal/abi" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -64,7 +64,7 @@ func (c *sigctxt) preparePanic(sig uint32, gp *g) { // functions are correctly handled. This smashes // the stack frame but we're not going back there // anyway. - sp := c.sp() - sys.PtrSize + sp := c.sp() - goarch.PtrSize c.set_sp(sp) *(*uint64)(unsafe.Pointer(uintptr(sp))) = c.ra() @@ -85,7 +85,7 @@ func (c *sigctxt) pushCall(targetPC, resumePC uintptr) { // push the call. The function being pushed is responsible // for restoring the LR and setting the SP back. // This extra slot is known to gentraceback. - sp := c.sp() - sys.PtrSize + sp := c.sp() - goarch.PtrSize c.set_sp(sp) *(*uint64)(unsafe.Pointer(uintptr(sp))) = c.ra() // Set up PC and LR to pretend the function being signaled diff --git a/src/runtime/slice.go b/src/runtime/slice.go index 7a470f09b6..ff59fa6278 100644 --- a/src/runtime/slice.go +++ b/src/runtime/slice.go @@ -8,6 +8,7 @@ import ( "internal/abi" "runtime/internal/math" "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -195,15 +196,15 @@ func growslice(et *_type, old slice, cap int) slice { capmem = roundupsize(uintptr(newcap)) overflow = uintptr(newcap) > maxAlloc newcap = int(capmem) - case et.size == sys.PtrSize: - lenmem = uintptr(old.len) * sys.PtrSize - newlenmem = uintptr(cap) * sys.PtrSize - capmem = roundupsize(uintptr(newcap) * sys.PtrSize) - overflow = uintptr(newcap) > maxAlloc/sys.PtrSize - newcap = int(capmem / sys.PtrSize) + case et.size == goarch.PtrSize: + lenmem = uintptr(old.len) * goarch.PtrSize + newlenmem = uintptr(cap) * goarch.PtrSize + capmem = roundupsize(uintptr(newcap) * goarch.PtrSize) + overflow = uintptr(newcap) > maxAlloc/goarch.PtrSize + newcap = int(capmem / goarch.PtrSize) case isPowerOfTwo(et.size): var shift uintptr - if sys.PtrSize == 8 { + if goarch.PtrSize == 8 { // Mask shift for better code generation. shift = uintptr(sys.Ctz64(uint64(et.size))) & 63 } else { diff --git a/src/runtime/stack.go b/src/runtime/stack.go index b5545ac796..c37e8e76eb 100644 --- a/src/runtime/stack.go +++ b/src/runtime/stack.go @@ -9,6 +9,7 @@ import ( "internal/cpu" "runtime/internal/atomic" "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -67,7 +68,7 @@ const ( // to each stack below the usual guard area for OS-specific // purposes like signal handling. Used on Windows, Plan 9, // and iOS because they do not use a separate stack. - _StackSystem = sys.GoosWindows*512*sys.PtrSize + sys.GoosPlan9*512 + sys.GoosIos*sys.GoarchArm64*1024 + _StackSystem = sys.GoosWindows*512*goarch.PtrSize + sys.GoosPlan9*512 + sys.GoosIos*sys.GoarchArm64*1024 // The minimum size of stack used by Go code _StackMin = 2048 @@ -125,7 +126,7 @@ const ( ) const ( - uintptrMask = 1<<(8*sys.PtrSize) - 1 + uintptrMask = 1<<(8*goarch.PtrSize) - 1 // The values below can be stored to g.stackguard0 to force // the next stack check to fail. @@ -599,14 +600,14 @@ func adjustpointers(scanp unsafe.Pointer, bv *bitvector, adjinfo *adjustinfo, f for i := uintptr(0); i < num; i += 8 { if stackDebug >= 4 { for j := uintptr(0); j < 8; j++ { - print(" ", add(scanp, (i+j)*sys.PtrSize), ":", ptrnames[bv.ptrbit(i+j)], ":", hex(*(*uintptr)(add(scanp, (i+j)*sys.PtrSize))), " # ", i, " ", *addb(bv.bytedata, i/8), "\n") + print(" ", add(scanp, (i+j)*goarch.PtrSize), ":", ptrnames[bv.ptrbit(i+j)], ":", hex(*(*uintptr)(add(scanp, (i+j)*goarch.PtrSize))), " # ", i, " ", *addb(bv.bytedata, i/8), "\n") } } b := *(addb(bv.bytedata, i/8)) for b != 0 { j := uintptr(sys.Ctz8(b)) b &= b - 1 - pp := (*uintptr)(add(scanp, (i+j)*sys.PtrSize)) + pp := (*uintptr)(add(scanp, (i+j)*goarch.PtrSize)) retry: p := *pp if f.valid() && 0 < p && p < minLegalPointer && debug.invalidptr != 0 { @@ -655,13 +656,13 @@ func adjustframe(frame *stkframe, arg unsafe.Pointer) bool { // Adjust local variables if stack frame has been allocated. if locals.n > 0 { - size := uintptr(locals.n) * sys.PtrSize + size := uintptr(locals.n) * goarch.PtrSize adjustpointers(unsafe.Pointer(frame.varp-size), &locals, adjinfo, f) } // Adjust saved base pointer if there is one. // TODO what about arm64 frame pointer adjustment? - if sys.ArchFamily == sys.AMD64 && frame.argp-frame.varp == 2*sys.PtrSize { + if sys.ArchFamily == sys.AMD64 && frame.argp-frame.varp == 2*goarch.PtrSize { if stackDebug >= 3 { print(" saved bp\n") } @@ -710,8 +711,8 @@ func adjustframe(frame *stkframe, arg unsafe.Pointer) bool { s = materializeGCProg(ptrdata, gcdata) gcdata = (*byte)(unsafe.Pointer(s.startAddr)) } - for i := uintptr(0); i < ptrdata; i += sys.PtrSize { - if *addb(gcdata, i/(8*sys.PtrSize))>>(i/sys.PtrSize&7)&1 != 0 { + for i := uintptr(0); i < ptrdata; i += goarch.PtrSize { + if *addb(gcdata, i/(8*goarch.PtrSize))>>(i/goarch.PtrSize&7)&1 != 0 { adjustpointer(adjinfo, unsafe.Pointer(p+i)) } } @@ -1014,7 +1015,7 @@ func newstack() { sp := gp.sched.sp if sys.ArchFamily == sys.AMD64 || sys.ArchFamily == sys.I386 || sys.ArchFamily == sys.WASM { // The call to morestack cost a word. - sp -= sys.PtrSize + sp -= goarch.PtrSize } if stackDebug >= 1 || sp < gp.stack.lo { print("runtime: newstack sp=", hex(sp), " stack=[", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n", @@ -1291,7 +1292,7 @@ func getStackMap(frame *stkframe, cache *pcvalueCache, debug bool) (locals, args // In this case, arglen specifies how much of the args section is actually live. // (It could be either all the args + results, or just the args.) args = *frame.argmap - n := int32(frame.arglen / sys.PtrSize) + n := int32(frame.arglen / goarch.PtrSize) if n < args.n { args.n = n // Don't use more of the arguments than arglen. } @@ -1323,7 +1324,7 @@ func getStackMap(frame *stkframe, cache *pcvalueCache, debug bool) (locals, args p := funcdata(f, _FUNCDATA_StackObjects) if p != nil { n := *(*uintptr)(p) - p = add(p, sys.PtrSize) + p = add(p, goarch.PtrSize) *(*slice)(unsafe.Pointer(&objs)) = slice{array: noescape(p), len: int(n), cap: int(n)} // Note: the noescape above is needed to keep // getStackMap from "leaking param content: diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 6b535dfcbf..36e0bfa9c4 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -7,6 +7,7 @@ package runtime import ( "runtime/internal/atomic" "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -561,7 +562,7 @@ const debugPcln = false func moduledataverify1(datap *moduledata) { // Check that the pclntab's format is valid. hdr := datap.pcHeader - if hdr.magic != 0xfffffffa || hdr.pad1 != 0 || hdr.pad2 != 0 || hdr.minLC != sys.PCQuantum || hdr.ptrSize != sys.PtrSize { + if hdr.magic != 0xfffffffa || hdr.pad1 != 0 || hdr.pad2 != 0 || hdr.minLC != sys.PCQuantum || hdr.ptrSize != goarch.PtrSize { print("runtime: function symbol table header:", hex(hdr.magic), hex(hdr.pad1), hex(hdr.pad2), hex(hdr.minLC), hex(hdr.ptrSize)) if datap.pluginpath != "" { print(", plugin:", datap.pluginpath) @@ -779,7 +780,7 @@ type pcvalueCacheEnt struct { // For now, align to sys.PtrSize and reduce mod the number of entries. // In practice, this appears to be fairly randomly and evenly distributed. func pcvalueCacheKey(targetpc uintptr) uintptr { - return (targetpc / sys.PtrSize) % uintptr(len(pcvalueCache{}.entries)) + return (targetpc / goarch.PtrSize) % uintptr(len(pcvalueCache{}.entries)) } // Returns the PCData value, and the PC where this value starts. @@ -948,7 +949,7 @@ func funcline(f funcInfo, targetpc uintptr) (file string, line int32) { func funcspdelta(f funcInfo, targetpc uintptr, cache *pcvalueCache) int32 { x, _ := pcvalue(f, f.pcsp, targetpc, cache, true) - if x&(sys.PtrSize-1) != 0 { + if x&(goarch.PtrSize-1) != 0 { print("invalid spdelta ", funcname(f), " ", hex(f.entry), " ", hex(targetpc), " ", hex(f.pcsp), " ", x, "\n") } return x @@ -1007,13 +1008,13 @@ func funcdata(f funcInfo, i uint8) unsafe.Pointer { return nil } p := add(unsafe.Pointer(&f.nfuncdata), unsafe.Sizeof(f.nfuncdata)+uintptr(f.npcdata)*4) - if sys.PtrSize == 8 && uintptr(p)&4 != 0 { + if goarch.PtrSize == 8 && uintptr(p)&4 != 0 { if uintptr(unsafe.Pointer(f._func))&4 != 0 { println("runtime: misaligned func", f._func) } p = add(p, 4) } - return *(*unsafe.Pointer)(add(p, uintptr(i)*sys.PtrSize)) + return *(*unsafe.Pointer)(add(p, uintptr(i)*goarch.PtrSize)) } // step advances to the next pc, value pair in the encoded table. diff --git a/src/runtime/sys_darwin_arm64.go b/src/runtime/sys_darwin_arm64.go index 7dabaca08d..e6d4c1be48 100644 --- a/src/runtime/sys_darwin_arm64.go +++ b/src/runtime/sys_darwin_arm64.go @@ -6,7 +6,7 @@ package runtime import ( "internal/abi" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -54,7 +54,7 @@ func tlsinit(tlsg *uintptr, tlsbase *[_PTHREAD_KEYS_MAX]uintptr) { for i, x := range tlsbase { if x == magic { - *tlsg = uintptr(i * sys.PtrSize) + *tlsg = uintptr(i * goarch.PtrSize) g0_pthread_setspecific(k, 0) return } diff --git a/src/runtime/sys_wasm.go b/src/runtime/sys_wasm.go index 057ed4ccd9..1bf80289f2 100644 --- a/src/runtime/sys_wasm.go +++ b/src/runtime/sys_wasm.go @@ -6,6 +6,7 @@ package runtime import ( "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -30,7 +31,7 @@ func wasmExit(code int32) // and then stopped before the first instruction in fn. func gostartcall(buf *gobuf, fn, ctxt unsafe.Pointer) { sp := buf.sp - sp -= sys.PtrSize + sp -= goarch.PtrSize *(*uintptr)(unsafe.Pointer(sp)) = buf.pc buf.sp = sp buf.pc = uintptr(fn) diff --git a/src/runtime/sys_x86.go b/src/runtime/sys_x86.go index 0866e3140e..856c73a2f6 100644 --- a/src/runtime/sys_x86.go +++ b/src/runtime/sys_x86.go @@ -8,7 +8,7 @@ package runtime import ( - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -16,7 +16,7 @@ import ( // and then stopped before the first instruction in fn. func gostartcall(buf *gobuf, fn, ctxt unsafe.Pointer) { sp := buf.sp - sp -= sys.PtrSize + sp -= goarch.PtrSize *(*uintptr)(unsafe.Pointer(sp)) = buf.pc buf.sp = sp buf.pc = uintptr(fn) diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go index 4215d62cc1..e872d74e97 100644 --- a/src/runtime/syscall_windows.go +++ b/src/runtime/syscall_windows.go @@ -6,7 +6,7 @@ package runtime import ( "internal/abi" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -73,7 +73,7 @@ type abiDesc struct { } func (p *abiDesc) assignArg(t *_type) { - if t.size > sys.PtrSize { + if t.size > goarch.PtrSize { // We don't support this right now. In // stdcall/cdecl, 64-bit ints and doubles are // passed as two words (little endian); and @@ -146,7 +146,7 @@ func (p *abiDesc) assignArg(t *_type) { // cdecl, stdcall, fastcall, and arm pad arguments to word size. // TODO(rsc): On arm and arm64 do we need to skip the caller's saved LR? - p.srcStackSize += sys.PtrSize + p.srcStackSize += goarch.PtrSize } // tryRegAssignArg tries to register-assign a value of type t. @@ -162,7 +162,7 @@ func (p *abiDesc) tryRegAssignArg(t *_type, offset uintptr) bool { return p.assignReg(t.size, offset) case kindInt64, kindUint64: // Only register-assign if the registers are big enough. - if sys.PtrSize == 8 { + if goarch.PtrSize == 8 { return p.assignReg(t.size, offset) } case kindArray: @@ -235,7 +235,7 @@ func callbackasmAddr(i int) uintptr { return abi.FuncPCABI0(callbackasm) + uintptr(i*entrySize) } -const callbackMaxFrame = 64 * sys.PtrSize +const callbackMaxFrame = 64 * goarch.PtrSize // compileCallback converts a Go function fn into a C function pointer // that can be passed to Windows APIs. @@ -263,13 +263,13 @@ func compileCallback(fn eface, cdecl bool) (code uintptr) { } // The Go ABI aligns the result to the word size. src is // already aligned. - abiMap.dstStackSize = alignUp(abiMap.dstStackSize, sys.PtrSize) + abiMap.dstStackSize = alignUp(abiMap.dstStackSize, goarch.PtrSize) abiMap.retOffset = abiMap.dstStackSize if len(ft.out()) != 1 { panic("compileCallback: expected function with one uintptr-sized result") } - if ft.out()[0].size != sys.PtrSize { + if ft.out()[0].size != goarch.PtrSize { panic("compileCallback: expected function with one uintptr-sized result") } if k := ft.out()[0].kind & kindMask; k == kindFloat32 || k == kindFloat64 { @@ -282,12 +282,12 @@ func compileCallback(fn eface, cdecl bool) (code uintptr) { // Make room for the uintptr-sized result. // If there are argument registers, the return value will // be passed in the first register. - abiMap.dstStackSize += sys.PtrSize + abiMap.dstStackSize += goarch.PtrSize } // TODO(mknyszek): Remove dstSpill from this calculation when we no longer have // caller reserved spill space. - frameSize := alignUp(abiMap.dstStackSize, sys.PtrSize) + frameSize := alignUp(abiMap.dstStackSize, goarch.PtrSize) frameSize += abiMap.dstSpill if frameSize > callbackMaxFrame { panic("compileCallback: function argument frame too large") @@ -370,7 +370,7 @@ func callbackWrap(a *callbackArgs) { // TODO(mknyszek): Remove this when we no longer have // caller reserved spill space. - frameSize := alignUp(c.abiMap.dstStackSize, sys.PtrSize) + frameSize := alignUp(c.abiMap.dstStackSize, goarch.PtrSize) frameSize += c.abiMap.dstSpill // Even though this is copying back results, we can pass a nil diff --git a/src/runtime/trace.go b/src/runtime/trace.go index 1530178c85..1864e81a42 100644 --- a/src/runtime/trace.go +++ b/src/runtime/trace.go @@ -15,6 +15,7 @@ package runtime import ( "runtime/internal/atomic" "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -829,7 +830,7 @@ Search: // newStack allocates a new stack of size n. func (tab *traceStackTable) newStack(n int) *traceStack { - return (*traceStack)(tab.mem.alloc(unsafe.Sizeof(traceStack{}) + uintptr(n)*sys.PtrSize)) + return (*traceStack)(tab.mem.alloc(unsafe.Sizeof(traceStack{}) + uintptr(n)*goarch.PtrSize)) } // allFrames returns all of the Frames corresponding to pcs. @@ -929,7 +930,7 @@ type traceAlloc struct { //go:notinheap type traceAllocBlock struct { next traceAllocBlockPtr - data [64<<10 - sys.PtrSize]byte + data [64<<10 - goarch.PtrSize]byte } // TODO: Since traceAllocBlock is now go:notinheap, this isn't necessary. @@ -940,7 +941,7 @@ func (p *traceAllocBlockPtr) set(x *traceAllocBlock) { *p = traceAllocBlockPtr(u // alloc allocates n-byte block. func (a *traceAlloc) alloc(n uintptr) unsafe.Pointer { - n = alignUp(n, sys.PtrSize) + n = alignUp(n, goarch.PtrSize) if a.head == 0 || a.off+n > uintptr(len(a.head.ptr().data)) { if n > uintptr(len(a.head.ptr().data)) { throw("trace: alloc too large") diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go index fa41fdfe2d..27e187f4ed 100644 --- a/src/runtime/traceback.go +++ b/src/runtime/traceback.go @@ -8,6 +8,7 @@ import ( "internal/bytealg" "runtime/internal/atomic" "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -91,7 +92,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in frame.lr = 0 } else { frame.pc = uintptr(*(*uintptr)(unsafe.Pointer(frame.sp))) - frame.sp += sys.PtrSize + frame.sp += goarch.PtrSize } } @@ -172,7 +173,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in frame.fp = frame.sp + uintptr(funcspdelta(f, frame.pc, &cache)) if !usesLR { // On x86, call instruction pushes return PC before entering new function. - frame.fp += sys.PtrSize + frame.fp += goarch.PtrSize } } var flr funcInfo @@ -213,7 +214,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in } } else { if frame.lr == 0 { - lrPtr = frame.fp - sys.PtrSize + lrPtr = frame.fp - goarch.PtrSize frame.lr = uintptr(*(*uintptr)(unsafe.Pointer(lrPtr))) } } @@ -244,7 +245,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in frame.varp = frame.fp if !usesLR { // On x86, call instruction pushes return PC before entering new function. - frame.varp -= sys.PtrSize + frame.varp -= goarch.PtrSize } // For architectures with frame pointers, if there's @@ -265,7 +266,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in // And it happens to end up mimicking the x86 layout. // Other architectures may make different decisions. if frame.varp > frame.sp && framepointer_enabled { - frame.varp -= sys.PtrSize + frame.varp -= goarch.PtrSize } // Derive size of arguments. @@ -665,16 +666,16 @@ func getArgInfo(frame *stkframe, f funcInfo, needArgMap bool, ctxt *funcval) (ar // Figure out whether the return values are valid. // Reflect will update this value after it copies // in the return values. - retValid = *(*bool)(unsafe.Pointer(arg0 + 4*sys.PtrSize)) + retValid = *(*bool)(unsafe.Pointer(arg0 + 4*goarch.PtrSize)) } if mv.fn != f.entry { print("runtime: confused by ", funcname(f), "\n") throw("reflect mismatch") } bv := mv.stack - arglen = uintptr(bv.n * sys.PtrSize) + arglen = uintptr(bv.n * goarch.PtrSize) if !retValid { - arglen = uintptr(mv.argLen) &^ (sys.PtrSize - 1) + arglen = uintptr(mv.argLen) &^ (goarch.PtrSize - 1) } argmap = bv } @@ -1010,8 +1011,8 @@ func tracebackothers(me *g) { // for debugging purposes. If the address bad is included in the // hexdumped range, it will mark it as well. func tracebackHexdump(stk stack, frame *stkframe, bad uintptr) { - const expand = 32 * sys.PtrSize - const maxExpand = 256 * sys.PtrSize + const expand = 32 * goarch.PtrSize + const maxExpand = 256 * goarch.PtrSize // Start around frame.sp. lo, hi := frame.sp, frame.sp // Expand to include frame.fp. -- GitLab From 6d89c90fb166bf5c58fff33716ba632b67e9c182 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Wed, 16 Jun 2021 23:16:05 +0000 Subject: [PATCH 0298/2500] [dev.typeparams] runtime/internal/sys: remove unused PtrSize Change-Id: I01e079b95f71b01edaf049d49a0993a7ed39c7bf Reviewed-on: https://go-review.googlesource.com/c/go/+/328810 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/runtime/internal/sys/consts.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/runtime/internal/sys/consts.go b/src/runtime/internal/sys/consts.go index 815f789380..349d2ed4d6 100644 --- a/src/runtime/internal/sys/consts.go +++ b/src/runtime/internal/sys/consts.go @@ -24,10 +24,6 @@ const ( WASM = goarch.WASM ) -// PtrSize is the size of a pointer in bytes - unsafe.Sizeof(uintptr(0)) but as an ideal constant. -// It is also the size of the machine's native word size (that is, 4 on 32-bit systems, 8 on 64-bit). -const PtrSize = goarch.PtrSize - // ArchFamily is the architecture family (AMD64, ARM, ...) const ArchFamily ArchFamilyType = goarch.ArchFamily -- GitLab From 5c028751bde57d069bd0fe4c6769cba11c975d31 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Wed, 16 Jun 2021 21:11:32 +0000 Subject: [PATCH 0299/2500] [dev.typeparams] runtime/internal/sys: replace uses of GOARCH with goarch.GOARCH Refactoring performed by the rf tool: rf 'ex . { import "internal/goarch" import "runtime/internal/sys" sys.GOARCH -> goarch.GOARCH }' Change-Id: I4b0246bf4e734f08313c6fff7b547db362057714 Reviewed-on: https://go-review.googlesource.com/c/go/+/328338 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/runtime/extern.go | 7 +++++-- src/runtime/heapdump.go | 3 +-- src/runtime/internal/sys/consts.go | 2 -- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/runtime/extern.go b/src/runtime/extern.go index 48e1e6603b..1c70e8a361 100644 --- a/src/runtime/extern.go +++ b/src/runtime/extern.go @@ -186,7 +186,10 @@ of the run-time system. */ package runtime -import "runtime/internal/sys" +import ( + "internal/goarch" + "runtime/internal/sys" +) // Caller reports file and line number information about function invocations on // the calling goroutine's stack. The argument skip is the number of stack frames @@ -264,4 +267,4 @@ const GOOS string = sys.GOOS // GOARCH is the running program's architecture target: // one of 386, amd64, arm, s390x, and so on. -const GOARCH string = sys.GOARCH +const GOARCH string = goarch.GOARCH diff --git a/src/runtime/heapdump.go b/src/runtime/heapdump.go index 050628e33e..18e4666fa4 100644 --- a/src/runtime/heapdump.go +++ b/src/runtime/heapdump.go @@ -12,7 +12,6 @@ package runtime import ( - "runtime/internal/sys" "internal/goarch" "unsafe" ) @@ -532,7 +531,7 @@ func dumpparams() { } dumpint(uint64(arenaStart)) dumpint(uint64(arenaEnd)) - dumpstr(sys.GOARCH) + dumpstr(goarch.GOARCH) dumpstr(buildVersion) dumpint(uint64(ncpu)) } diff --git a/src/runtime/internal/sys/consts.go b/src/runtime/internal/sys/consts.go index 349d2ed4d6..07fbaf4d73 100644 --- a/src/runtime/internal/sys/consts.go +++ b/src/runtime/internal/sys/consts.go @@ -54,8 +54,6 @@ const MinFrameSize = goarch.MinFrameSize // The stack must be at least word aligned, but some architectures require more. const StackAlign = goarch.StackAlign -const GOARCH = goarch.GOARCH - const ( Goarch386 = goarch.Goarch386 GoarchAmd64 = goarch.GoarchAmd64 -- GitLab From 671954e72e8e3e569e659d29e22c6b2a23cea206 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Wed, 16 Jun 2021 21:15:19 +0000 Subject: [PATCH 0300/2500] [dev.typeparams] runtime/internal/sys: replace GOOS with goos.GOOS Refactoring done by rf tool: rf 'ex . { import "internal/goos" import "runtime/internal/sys" sys.GOOS -> goos.GOOS }' Change-Id: I4b4aadff8640731ce4cb9bdad9954c267eb484c8 Reviewed-on: https://go-review.googlesource.com/c/go/+/328339 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/runtime/extern.go | 4 ++-- src/runtime/internal/sys/consts.go | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/runtime/extern.go b/src/runtime/extern.go index 1c70e8a361..eca4062e68 100644 --- a/src/runtime/extern.go +++ b/src/runtime/extern.go @@ -188,7 +188,7 @@ package runtime import ( "internal/goarch" - "runtime/internal/sys" + "internal/goos" ) // Caller reports file and line number information about function invocations on @@ -263,7 +263,7 @@ func Version() string { // GOOS is the running program's operating system target: // one of darwin, freebsd, linux, and so on. // To view possible combinations of GOOS and GOARCH, run "go tool dist list". -const GOOS string = sys.GOOS +const GOOS string = goos.GOOS // GOARCH is the running program's architecture target: // one of 386, amd64, arm, s390x, and so on. diff --git a/src/runtime/internal/sys/consts.go b/src/runtime/internal/sys/consts.go index 07fbaf4d73..4d45f9d0d0 100644 --- a/src/runtime/internal/sys/consts.go +++ b/src/runtime/internal/sys/consts.go @@ -80,8 +80,6 @@ const ( GoarchWasm = goarch.GoarchWasm ) -const GOOS = goos.GOOS - const ( GoosAix = goos.GoosAix GoosAndroid = goos.GoosAndroid -- GitLab From 9c58e399a40d2cc4102245f072438caaf635d495 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Thu, 17 Jun 2021 19:10:18 +0000 Subject: [PATCH 0301/2500] [dev.typeparams] runtime: fix import sort order [generated] [git-generate] cd src/runtime goimports -w *.go Change-Id: I1387af0f2fd1a213dc2f4c122e83a8db0fcb15f0 Reviewed-on: https://go-review.googlesource.com/c/go/+/329189 Trust: Michael Knyszek Run-TryBot: Michael Knyszek Reviewed-by: Matthew Dempsky TryBot-Result: Go Bot --- src/runtime/alg.go | 2 +- src/runtime/cgocall.go | 2 +- src/runtime/export_test.go | 2 +- src/runtime/iface.go | 2 +- src/runtime/malloc.go | 2 +- src/runtime/map.go | 2 +- src/runtime/map_test.go | 2 +- src/runtime/mbitmap.go | 2 +- src/runtime/mcheckmark.go | 2 +- src/runtime/mfinal.go | 2 +- src/runtime/mgcmark.go | 2 +- src/runtime/mgcwork.go | 2 +- src/runtime/mheap.go | 2 +- src/runtime/mspanset.go | 2 +- src/runtime/mstats.go | 2 +- src/runtime/mwbbuf.go | 2 +- src/runtime/os_netbsd.go | 2 +- src/runtime/os_windows.go | 2 +- src/runtime/preempt.go | 2 +- src/runtime/print.go | 2 +- src/runtime/proc.go | 2 +- src/runtime/runtime1.go | 2 +- src/runtime/runtime2.go | 2 +- src/runtime/signal_linux_s390x.go | 2 +- src/runtime/slice.go | 2 +- src/runtime/stack.go | 2 +- src/runtime/symtab.go | 2 +- src/runtime/sys_wasm.go | 2 +- src/runtime/trace.go | 2 +- src/runtime/traceback.go | 2 +- 30 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/runtime/alg.go b/src/runtime/alg.go index 493499f2c5..fe6258cadd 100644 --- a/src/runtime/alg.go +++ b/src/runtime/alg.go @@ -6,8 +6,8 @@ package runtime import ( "internal/cpu" - "runtime/internal/sys" "internal/goarch" + "runtime/internal/sys" "unsafe" ) diff --git a/src/runtime/cgocall.go b/src/runtime/cgocall.go index 2dafda6ca4..34eec02d07 100644 --- a/src/runtime/cgocall.go +++ b/src/runtime/cgocall.go @@ -85,9 +85,9 @@ package runtime import ( + "internal/goarch" "runtime/internal/atomic" "runtime/internal/sys" - "internal/goarch" "unsafe" ) diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index ae329746fe..9a471bd9d6 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -7,9 +7,9 @@ package runtime import ( + "internal/goarch" "runtime/internal/atomic" "runtime/internal/sys" - "internal/goarch" "unsafe" ) diff --git a/src/runtime/iface.go b/src/runtime/iface.go index 67c0582363..9d10deee9c 100644 --- a/src/runtime/iface.go +++ b/src/runtime/iface.go @@ -6,9 +6,9 @@ package runtime import ( "internal/abi" + "internal/goarch" "runtime/internal/atomic" "runtime/internal/sys" - "internal/goarch" "unsafe" ) diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index 9f8e04d760..205e25ed88 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -101,10 +101,10 @@ package runtime import ( + "internal/goarch" "runtime/internal/atomic" "runtime/internal/math" "runtime/internal/sys" - "internal/goarch" "unsafe" ) diff --git a/src/runtime/map.go b/src/runtime/map.go index ca65d3e77f..0cad1a354d 100644 --- a/src/runtime/map.go +++ b/src/runtime/map.go @@ -55,9 +55,9 @@ package runtime import ( "internal/abi" + "internal/goarch" "runtime/internal/atomic" "runtime/internal/math" - "internal/goarch" "unsafe" ) diff --git a/src/runtime/map_test.go b/src/runtime/map_test.go index 583be21eb3..24556b4093 100644 --- a/src/runtime/map_test.go +++ b/src/runtime/map_test.go @@ -6,11 +6,11 @@ package runtime_test import ( "fmt" + "internal/goarch" "math" "reflect" "runtime" "sort" - "internal/goarch" "strconv" "strings" "sync" diff --git a/src/runtime/mbitmap.go b/src/runtime/mbitmap.go index 124ac8f050..9363409e36 100644 --- a/src/runtime/mbitmap.go +++ b/src/runtime/mbitmap.go @@ -46,9 +46,9 @@ package runtime import ( + "internal/goarch" "runtime/internal/atomic" "runtime/internal/sys" - "internal/goarch" "unsafe" ) diff --git a/src/runtime/mcheckmark.go b/src/runtime/mcheckmark.go index 6a43142508..1dd28585f1 100644 --- a/src/runtime/mcheckmark.go +++ b/src/runtime/mcheckmark.go @@ -13,8 +13,8 @@ package runtime import ( - "runtime/internal/atomic" "internal/goarch" + "runtime/internal/atomic" "unsafe" ) diff --git a/src/runtime/mfinal.go b/src/runtime/mfinal.go index 98f7cf793f..c07ea5e375 100644 --- a/src/runtime/mfinal.go +++ b/src/runtime/mfinal.go @@ -8,8 +8,8 @@ package runtime import ( "internal/abi" - "runtime/internal/atomic" "internal/goarch" + "runtime/internal/atomic" "unsafe" ) diff --git a/src/runtime/mgcmark.go b/src/runtime/mgcmark.go index 85c78f05a7..874d910720 100644 --- a/src/runtime/mgcmark.go +++ b/src/runtime/mgcmark.go @@ -7,8 +7,8 @@ package runtime import ( - "runtime/internal/atomic" "internal/goarch" + "runtime/internal/atomic" "unsafe" ) diff --git a/src/runtime/mgcwork.go b/src/runtime/mgcwork.go index 9454ac46f3..8787d93d87 100644 --- a/src/runtime/mgcwork.go +++ b/src/runtime/mgcwork.go @@ -5,8 +5,8 @@ package runtime import ( - "runtime/internal/atomic" "internal/goarch" + "runtime/internal/atomic" "unsafe" ) diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go index 87716a4b53..b78f752ded 100644 --- a/src/runtime/mheap.go +++ b/src/runtime/mheap.go @@ -10,8 +10,8 @@ package runtime import ( "internal/cpu" - "runtime/internal/atomic" "internal/goarch" + "runtime/internal/atomic" "unsafe" ) diff --git a/src/runtime/mspanset.go b/src/runtime/mspanset.go index 9b0fb99c4c..29f14910cc 100644 --- a/src/runtime/mspanset.go +++ b/src/runtime/mspanset.go @@ -6,8 +6,8 @@ package runtime import ( "internal/cpu" - "runtime/internal/atomic" "internal/goarch" + "runtime/internal/atomic" "unsafe" ) diff --git a/src/runtime/mstats.go b/src/runtime/mstats.go index 3ac88438bc..341ba9a936 100644 --- a/src/runtime/mstats.go +++ b/src/runtime/mstats.go @@ -7,8 +7,8 @@ package runtime import ( - "runtime/internal/atomic" "internal/goarch" + "runtime/internal/atomic" "unsafe" ) diff --git a/src/runtime/mwbbuf.go b/src/runtime/mwbbuf.go index 7862dfbd9e..78d9382620 100644 --- a/src/runtime/mwbbuf.go +++ b/src/runtime/mwbbuf.go @@ -23,8 +23,8 @@ package runtime import ( - "runtime/internal/atomic" "internal/goarch" + "runtime/internal/atomic" "unsafe" ) diff --git a/src/runtime/os_netbsd.go b/src/runtime/os_netbsd.go index bd936d3735..2c20ee2173 100644 --- a/src/runtime/os_netbsd.go +++ b/src/runtime/os_netbsd.go @@ -6,8 +6,8 @@ package runtime import ( "internal/abi" - "runtime/internal/atomic" "internal/goarch" + "runtime/internal/atomic" "unsafe" ) diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go index 1cca0876a9..648239fb36 100644 --- a/src/runtime/os_windows.go +++ b/src/runtime/os_windows.go @@ -6,8 +6,8 @@ package runtime import ( "internal/abi" - "runtime/internal/atomic" "internal/goarch" + "runtime/internal/atomic" "unsafe" ) diff --git a/src/runtime/preempt.go b/src/runtime/preempt.go index cfec196a09..a38ab79398 100644 --- a/src/runtime/preempt.go +++ b/src/runtime/preempt.go @@ -54,8 +54,8 @@ package runtime import ( "internal/abi" - "runtime/internal/atomic" "internal/goarch" + "runtime/internal/atomic" "unsafe" ) diff --git a/src/runtime/print.go b/src/runtime/print.go index fe32fbb08e..59a91203b9 100644 --- a/src/runtime/print.go +++ b/src/runtime/print.go @@ -5,8 +5,8 @@ package runtime import ( - "runtime/internal/atomic" "internal/goarch" + "runtime/internal/atomic" "unsafe" ) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 3b1e067371..f13f7d20a3 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -7,9 +7,9 @@ package runtime import ( "internal/abi" "internal/cpu" + "internal/goarch" "runtime/internal/atomic" "runtime/internal/sys" - "internal/goarch" "unsafe" ) diff --git a/src/runtime/runtime1.go b/src/runtime/runtime1.go index eda6aaa401..b6c3cbfff4 100644 --- a/src/runtime/runtime1.go +++ b/src/runtime/runtime1.go @@ -6,8 +6,8 @@ package runtime import ( "internal/bytealg" - "runtime/internal/atomic" "internal/goarch" + "runtime/internal/atomic" "unsafe" ) diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index e2f0d5910f..5795929301 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -5,8 +5,8 @@ package runtime import ( - "runtime/internal/atomic" "internal/goarch" + "runtime/internal/atomic" "unsafe" ) diff --git a/src/runtime/signal_linux_s390x.go b/src/runtime/signal_linux_s390x.go index bba8169ded..18c3b115ef 100644 --- a/src/runtime/signal_linux_s390x.go +++ b/src/runtime/signal_linux_s390x.go @@ -6,8 +6,8 @@ package runtime import ( "internal/abi" - "runtime/internal/sys" "internal/goarch" + "runtime/internal/sys" "unsafe" ) diff --git a/src/runtime/slice.go b/src/runtime/slice.go index ff59fa6278..66e3aff1a4 100644 --- a/src/runtime/slice.go +++ b/src/runtime/slice.go @@ -6,9 +6,9 @@ package runtime import ( "internal/abi" + "internal/goarch" "runtime/internal/math" "runtime/internal/sys" - "internal/goarch" "unsafe" ) diff --git a/src/runtime/stack.go b/src/runtime/stack.go index c37e8e76eb..0c862e5d08 100644 --- a/src/runtime/stack.go +++ b/src/runtime/stack.go @@ -7,9 +7,9 @@ package runtime import ( "internal/abi" "internal/cpu" + "internal/goarch" "runtime/internal/atomic" "runtime/internal/sys" - "internal/goarch" "unsafe" ) diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 36e0bfa9c4..0167d51d60 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -5,9 +5,9 @@ package runtime import ( + "internal/goarch" "runtime/internal/atomic" "runtime/internal/sys" - "internal/goarch" "unsafe" ) diff --git a/src/runtime/sys_wasm.go b/src/runtime/sys_wasm.go index 1bf80289f2..e6e7f471ee 100644 --- a/src/runtime/sys_wasm.go +++ b/src/runtime/sys_wasm.go @@ -5,8 +5,8 @@ package runtime import ( - "runtime/internal/sys" "internal/goarch" + "runtime/internal/sys" "unsafe" ) diff --git a/src/runtime/trace.go b/src/runtime/trace.go index 1864e81a42..72e95947db 100644 --- a/src/runtime/trace.go +++ b/src/runtime/trace.go @@ -13,9 +13,9 @@ package runtime import ( + "internal/goarch" "runtime/internal/atomic" "runtime/internal/sys" - "internal/goarch" "unsafe" ) diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go index 27e187f4ed..0bea20bf4d 100644 --- a/src/runtime/traceback.go +++ b/src/runtime/traceback.go @@ -6,9 +6,9 @@ package runtime import ( "internal/bytealg" + "internal/goarch" "runtime/internal/atomic" "runtime/internal/sys" - "internal/goarch" "unsafe" ) -- GitLab From 9a93072a0709c7940f765774dbde0989425ac499 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Thu, 17 Jun 2021 19:01:08 +0000 Subject: [PATCH 0302/2500] [dev.typeparams] runtime/internal/sys: replace BigEndian with goarch.BigEndian [generated] [git-generate] cd src/runtime/internal/atomic gofmt -w -r "sys.BigEndian -> goarch.BigEndian" . goimports -w *.go cd ../.. gofmt -w -r "sys.BigEndian -> goarch.BigEndian" . goimports -w *.go Change-Id: Iad35d2b367d8defb081a77ca837e7a7c805c2b7b Reviewed-on: https://go-review.googlesource.com/c/go/+/329190 Trust: Michael Knyszek Run-TryBot: Michael Knyszek Reviewed-by: Matthew Dempsky TryBot-Result: Go Bot --- src/runtime/alg.go | 5 ++--- src/runtime/export_test.go | 2 +- src/runtime/iface.go | 5 ++--- src/runtime/internal/atomic/atomic_test.go | 4 ++-- src/runtime/string.go | 4 ++-- src/runtime/traceback.go | 2 +- 6 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/runtime/alg.go b/src/runtime/alg.go index fe6258cadd..978a3b85dc 100644 --- a/src/runtime/alg.go +++ b/src/runtime/alg.go @@ -7,7 +7,6 @@ package runtime import ( "internal/cpu" "internal/goarch" - "runtime/internal/sys" "unsafe" ) @@ -338,7 +337,7 @@ func initAlgAES() { // Note: These routines perform the read with a native endianness. func readUnaligned32(p unsafe.Pointer) uint32 { q := (*[4]byte)(p) - if sys.BigEndian { + if goarch.BigEndian { return uint32(q[3]) | uint32(q[2])<<8 | uint32(q[1])<<16 | uint32(q[0])<<24 } return uint32(q[0]) | uint32(q[1])<<8 | uint32(q[2])<<16 | uint32(q[3])<<24 @@ -346,7 +345,7 @@ func readUnaligned32(p unsafe.Pointer) uint32 { func readUnaligned64(p unsafe.Pointer) uint64 { q := (*[8]byte)(p) - if sys.BigEndian { + if goarch.BigEndian { return uint64(q[7]) | uint64(q[6])<<8 | uint64(q[5])<<16 | uint64(q[4])<<24 | uint64(q[3])<<32 | uint64(q[2])<<40 | uint64(q[1])<<48 | uint64(q[0])<<56 } diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index 9a471bd9d6..de3d5b709d 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -215,7 +215,7 @@ var Write = write func Envs() []string { return envs } func SetEnvs(e []string) { envs = e } -var BigEndian = sys.BigEndian +var BigEndian = goarch.BigEndian // For benchmarking. diff --git a/src/runtime/iface.go b/src/runtime/iface.go index 9d10deee9c..79a49c0dff 100644 --- a/src/runtime/iface.go +++ b/src/runtime/iface.go @@ -8,7 +8,6 @@ import ( "internal/abi" "internal/goarch" "runtime/internal/atomic" - "runtime/internal/sys" "unsafe" ) @@ -336,7 +335,7 @@ func convT2E(t *_type, elem unsafe.Pointer) (e eface) { func convT16(val uint16) (x unsafe.Pointer) { if val < uint16(len(staticuint64s)) { x = unsafe.Pointer(&staticuint64s[val]) - if sys.BigEndian { + if goarch.BigEndian { x = add(x, 6) } } else { @@ -349,7 +348,7 @@ func convT16(val uint16) (x unsafe.Pointer) { func convT32(val uint32) (x unsafe.Pointer) { if val < uint32(len(staticuint64s)) { x = unsafe.Pointer(&staticuint64s[val]) - if sys.BigEndian { + if goarch.BigEndian { x = add(x, 4) } } else { diff --git a/src/runtime/internal/atomic/atomic_test.go b/src/runtime/internal/atomic/atomic_test.go index c9c2eba248..2ae60b8507 100644 --- a/src/runtime/internal/atomic/atomic_test.go +++ b/src/runtime/internal/atomic/atomic_test.go @@ -5,9 +5,9 @@ package atomic_test import ( + "internal/goarch" "runtime" "runtime/internal/atomic" - "runtime/internal/sys" "testing" "unsafe" ) @@ -56,7 +56,7 @@ func TestXadduintptr(t *testing.T) { // Tests that xadduintptr correctly updates 64-bit values. The place where // we actually do so is mstats.go, functions mSysStat{Inc,Dec}. func TestXadduintptrOnUint64(t *testing.T) { - if sys.BigEndian { + if goarch.BigEndian { // On big endian architectures, we never use xadduintptr to update // 64-bit values and hence we skip the test. (Note that functions // mSysStat{Inc,Dec} in mstats.go have explicit checks for diff --git a/src/runtime/string.go b/src/runtime/string.go index 3c215d3754..d6990dab9a 100644 --- a/src/runtime/string.go +++ b/src/runtime/string.go @@ -7,7 +7,7 @@ package runtime import ( "internal/abi" "internal/bytealg" - "runtime/internal/sys" + "internal/goarch" "unsafe" ) @@ -96,7 +96,7 @@ func slicebytetostring(buf *tmpBuf, ptr *byte, n int) (str string) { } if n == 1 { p := unsafe.Pointer(&staticuint64s[*ptr]) - if sys.BigEndian { + if goarch.BigEndian { p = add(p, 7) } stringStructOf(&str).str = p diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go index 0bea20bf4d..addfa6faac 100644 --- a/src/runtime/traceback.go +++ b/src/runtime/traceback.go @@ -569,7 +569,7 @@ func printArgs(f funcInfo, argp unsafe.Pointer) { // mask out irrelavant bits if sz < 8 { shift := 64 - sz*8 - if sys.BigEndian { + if goarch.BigEndian { x = x >> shift } else { x = x << shift >> shift -- GitLab From 85b12a856313f4410376df8d02a11cc902acefa3 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Thu, 17 Jun 2021 19:13:55 +0000 Subject: [PATCH 0303/2500] [dev.typeparams] runtime,runtime/internal/sys: remove unused BigEndian Change-Id: I1209904326b1563e12d9c7d19a12a10c72d1dbcb Reviewed-on: https://go-review.googlesource.com/c/go/+/329191 Trust: Michael Knyszek Run-TryBot: Michael Knyszek Reviewed-by: Matthew Dempsky TryBot-Result: Go Bot --- src/runtime/export_test.go | 2 -- src/runtime/internal/sys/consts.go | 3 --- 2 files changed, 5 deletions(-) diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index de3d5b709d..f3118472fd 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -215,8 +215,6 @@ var Write = write func Envs() []string { return envs } func SetEnvs(e []string) { envs = e } -var BigEndian = goarch.BigEndian - // For benchmarking. func BenchSetType(n int, x interface{}) { diff --git a/src/runtime/internal/sys/consts.go b/src/runtime/internal/sys/consts.go index 4d45f9d0d0..dcba7a6e0d 100644 --- a/src/runtime/internal/sys/consts.go +++ b/src/runtime/internal/sys/consts.go @@ -30,9 +30,6 @@ const ArchFamily ArchFamilyType = goarch.ArchFamily // AIX requires a larger stack for syscalls. const StackGuardMultiplier = StackGuardMultiplierDefault*(1-goos.GoosAix) + 2*goos.GoosAix -// BigEndian reports whether the architecture is big-endian. -const BigEndian = goarch.BigEndian - // DefaultPhysPageSize is the default physical page size. const DefaultPhysPageSize = goarch.DefaultPhysPageSize -- GitLab From 33d1b82d16a199b1f8c61cba40b4d883088ca278 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Wed, 16 Jun 2021 21:25:19 +0000 Subject: [PATCH 0304/2500] [dev.typeparams] runtime/internal/sys: replace ArchFamily and constants with goarch Refactoring with rf rf 'ex . { import "internal/goarch" import "runtime/internal/sys" sys.ArchFamily -> goarch.ArchFamily sys.AMD64 -> goarch.AMD64 sys.ARM -> goarch.ARM sys.ARM64 -> goarch.ARM64 sys.I386 -> goarch.I386 sys.MIPS -> goarch.MIPS sys.MIPS64 -> goarch.MIPS64 sys.PPC64 -> goarch.PPC64 sys.RISCV64 -> goarch.RISCV64 sys.S390X -> goarch.S390X sys.WASM -> goarch.WASM }' Change-Id: I0cc29ed3fdcf9ff39aa901d8bc92270996f0821c Reviewed-on: https://go-review.googlesource.com/c/go/+/328341 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/runtime/internal/sys/consts.go | 18 ------------------ src/runtime/stack.go | 8 ++++---- 2 files changed, 4 insertions(+), 22 deletions(-) diff --git a/src/runtime/internal/sys/consts.go b/src/runtime/internal/sys/consts.go index dcba7a6e0d..6400c10748 100644 --- a/src/runtime/internal/sys/consts.go +++ b/src/runtime/internal/sys/consts.go @@ -9,24 +9,6 @@ import ( "internal/goos" ) -type ArchFamilyType = goarch.ArchFamilyType - -const ( - AMD64 = goarch.AMD64 - ARM = goarch.ARM - ARM64 = goarch.ARM64 - I386 = goarch.I386 - MIPS = goarch.MIPS - MIPS64 = goarch.MIPS64 - PPC64 = goarch.PPC64 - RISCV64 = goarch.RISCV64 - S390X = goarch.S390X - WASM = goarch.WASM -) - -// ArchFamily is the architecture family (AMD64, ARM, ...) -const ArchFamily ArchFamilyType = goarch.ArchFamily - // AIX requires a larger stack for syscalls. const StackGuardMultiplier = StackGuardMultiplierDefault*(1-goos.GoosAix) + 2*goos.GoosAix diff --git a/src/runtime/stack.go b/src/runtime/stack.go index 0c862e5d08..d63b86ddc1 100644 --- a/src/runtime/stack.go +++ b/src/runtime/stack.go @@ -662,7 +662,7 @@ func adjustframe(frame *stkframe, arg unsafe.Pointer) bool { // Adjust saved base pointer if there is one. // TODO what about arm64 frame pointer adjustment? - if sys.ArchFamily == sys.AMD64 && frame.argp-frame.varp == 2*goarch.PtrSize { + if goarch.ArchFamily == goarch.AMD64 && frame.argp-frame.varp == 2*goarch.PtrSize { if stackDebug >= 3 { print(" saved bp\n") } @@ -1013,7 +1013,7 @@ func newstack() { throw("missing stack in newstack") } sp := gp.sched.sp - if sys.ArchFamily == sys.AMD64 || sys.ArchFamily == sys.I386 || sys.ArchFamily == sys.WASM { + if goarch.ArchFamily == goarch.AMD64 || goarch.ArchFamily == goarch.I386 || goarch.ArchFamily == goarch.WASM { // The call to morestack cost a word. sp -= goarch.PtrSize } @@ -1256,8 +1256,8 @@ func getStackMap(frame *stkframe, cache *pcvalueCache, debug bool) (locals, args // Local variables. size := frame.varp - frame.sp var minsize uintptr - switch sys.ArchFamily { - case sys.ARM64: + switch goarch.ArchFamily { + case goarch.ARM64: minsize = sys.StackAlign default: minsize = sys.MinFrameSize -- GitLab From 81a6a4354b8f64b9f3a3d870e366cd8af48afbdd Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Wed, 16 Jun 2021 21:47:33 +0000 Subject: [PATCH 0305/2500] [dev.typeparams] internal/goarch,internal/goos: rename Goos and Goarch constants Lots of constants in these packages start with Goarch and Goos, which is redundant. Instead, add the "Is" prefix to make the constant clearer, and to differentiate from the arch family constants. Change-Id: Id92c1d3e911296a72949f8c9d649f142e7dc9d17 Reviewed-on: https://go-review.googlesource.com/c/go/+/328343 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/internal/goarch/gengoarch.go | 2 +- src/internal/goarch/goarch.go | 4 +- src/internal/goarch/zgoarch_386.go | 46 ++++++------ src/internal/goarch/zgoarch_amd64.go | 46 ++++++------ src/internal/goarch/zgoarch_arm.go | 46 ++++++------ src/internal/goarch/zgoarch_arm64.go | 46 ++++++------ src/internal/goarch/zgoarch_arm64be.go | 46 ++++++------ src/internal/goarch/zgoarch_armbe.go | 46 ++++++------ src/internal/goarch/zgoarch_mips.go | 46 ++++++------ src/internal/goarch/zgoarch_mips64.go | 46 ++++++------ src/internal/goarch/zgoarch_mips64le.go | 46 ++++++------ src/internal/goarch/zgoarch_mips64p32.go | 46 ++++++------ src/internal/goarch/zgoarch_mips64p32le.go | 46 ++++++------ src/internal/goarch/zgoarch_mipsle.go | 46 ++++++------ src/internal/goarch/zgoarch_ppc.go | 46 ++++++------ src/internal/goarch/zgoarch_ppc64.go | 46 ++++++------ src/internal/goarch/zgoarch_ppc64le.go | 46 ++++++------ src/internal/goarch/zgoarch_riscv.go | 46 ++++++------ src/internal/goarch/zgoarch_riscv64.go | 46 ++++++------ src/internal/goarch/zgoarch_s390.go | 46 ++++++------ src/internal/goarch/zgoarch_s390x.go | 46 ++++++------ src/internal/goarch/zgoarch_sparc.go | 46 ++++++------ src/internal/goarch/zgoarch_sparc64.go | 46 ++++++------ src/internal/goarch/zgoarch_wasm.go | 46 ++++++------ src/internal/goos/gengoos.go | 2 +- src/internal/goos/goos.go | 2 +- src/internal/goos/zgoos_aix.go | 34 ++++----- src/internal/goos/zgoos_android.go | 34 ++++----- src/internal/goos/zgoos_darwin.go | 34 ++++----- src/internal/goos/zgoos_dragonfly.go | 34 ++++----- src/internal/goos/zgoos_freebsd.go | 34 ++++----- src/internal/goos/zgoos_hurd.go | 34 ++++----- src/internal/goos/zgoos_illumos.go | 34 ++++----- src/internal/goos/zgoos_ios.go | 34 ++++----- src/internal/goos/zgoos_js.go | 34 ++++----- src/internal/goos/zgoos_linux.go | 34 ++++----- src/internal/goos/zgoos_netbsd.go | 34 ++++----- src/internal/goos/zgoos_openbsd.go | 34 ++++----- src/internal/goos/zgoos_plan9.go | 34 ++++----- src/internal/goos/zgoos_solaris.go | 34 ++++----- src/internal/goos/zgoos_windows.go | 34 ++++----- src/internal/goos/zgoos_zos.go | 34 ++++----- src/runtime/internal/sys/consts.go | 82 +++++++++++----------- 43 files changed, 824 insertions(+), 824 deletions(-) diff --git a/src/internal/goarch/gengoarch.go b/src/internal/goarch/gengoarch.go index 58c3b1104c..af15518ad8 100644 --- a/src/internal/goarch/gengoarch.go +++ b/src/internal/goarch/gengoarch.go @@ -49,7 +49,7 @@ func main() { if goarch == target { value = 1 } - fmt.Fprintf(&buf, "const Goarch%s = %d\n", strings.Title(goarch), value) + fmt.Fprintf(&buf, "const Is%s = %d\n", strings.Title(goarch), value) } err := os.WriteFile("zgoarch_"+target+".go", buf.Bytes(), 0666) if err != nil { diff --git a/src/internal/goarch/goarch.go b/src/internal/goarch/goarch.go index 8e240295b3..921f5a208f 100644 --- a/src/internal/goarch/goarch.go +++ b/src/internal/goarch/goarch.go @@ -6,7 +6,7 @@ package goarch // The next line makes 'go generate' write the zgoarch*.go files with -// per-arch information, including constants named Goarch$GOARCH for every +// per-arch information, including constants named $GOARCH for every // GOARCH. The constant is 1 on the current system, 0 otherwise; multiplying // by them is useful for defining GOARCH-specific constants. //go:generate go run gengoarch.go @@ -34,7 +34,7 @@ const PtrSize = 4 << (^uintptr(0) >> 63) const ArchFamily ArchFamilyType = _ArchFamily // BigEndian reports whether the architecture is big-endian. -const BigEndian = GoarchArmbe|GoarchArm64be|GoarchMips|GoarchMips64|GoarchPpc|GoarchPpc64|GoarchS390|GoarchS390x|GoarchSparc|GoarchSparc64 == 1 +const BigEndian = IsArmbe|IsArm64be|IsMips|IsMips64|IsPpc|IsPpc64|IsS390|IsS390x|IsSparc|IsSparc64 == 1 // DefaultPhysPageSize is the default physical page size. const DefaultPhysPageSize = _DefaultPhysPageSize diff --git a/src/internal/goarch/zgoarch_386.go b/src/internal/goarch/zgoarch_386.go index f424b5a6b9..7fa23b07ef 100644 --- a/src/internal/goarch/zgoarch_386.go +++ b/src/internal/goarch/zgoarch_386.go @@ -7,26 +7,26 @@ package goarch const GOARCH = `386` -const Goarch386 = 1 -const GoarchAmd64 = 0 -const GoarchAmd64p32 = 0 -const GoarchArm = 0 -const GoarchArmbe = 0 -const GoarchArm64 = 0 -const GoarchArm64be = 0 -const GoarchPpc64 = 0 -const GoarchPpc64le = 0 -const GoarchMips = 0 -const GoarchMipsle = 0 -const GoarchMips64 = 0 -const GoarchMips64le = 0 -const GoarchMips64p32 = 0 -const GoarchMips64p32le = 0 -const GoarchPpc = 0 -const GoarchRiscv = 0 -const GoarchRiscv64 = 0 -const GoarchS390 = 0 -const GoarchS390x = 0 -const GoarchSparc = 0 -const GoarchSparc64 = 0 -const GoarchWasm = 0 +const Is386 = 1 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +const IsMips64le = 0 +const IsMips64p32 = 0 +const IsMips64p32le = 0 +const IsPpc = 0 +const IsRiscv = 0 +const IsRiscv64 = 0 +const IsS390 = 0 +const IsS390x = 0 +const IsSparc = 0 +const IsSparc64 = 0 +const IsWasm = 0 diff --git a/src/internal/goarch/zgoarch_amd64.go b/src/internal/goarch/zgoarch_amd64.go index 728896c367..a6bf1cc6f4 100644 --- a/src/internal/goarch/zgoarch_amd64.go +++ b/src/internal/goarch/zgoarch_amd64.go @@ -7,26 +7,26 @@ package goarch const GOARCH = `amd64` -const Goarch386 = 0 -const GoarchAmd64 = 1 -const GoarchAmd64p32 = 0 -const GoarchArm = 0 -const GoarchArmbe = 0 -const GoarchArm64 = 0 -const GoarchArm64be = 0 -const GoarchPpc64 = 0 -const GoarchPpc64le = 0 -const GoarchMips = 0 -const GoarchMipsle = 0 -const GoarchMips64 = 0 -const GoarchMips64le = 0 -const GoarchMips64p32 = 0 -const GoarchMips64p32le = 0 -const GoarchPpc = 0 -const GoarchRiscv = 0 -const GoarchRiscv64 = 0 -const GoarchS390 = 0 -const GoarchS390x = 0 -const GoarchSparc = 0 -const GoarchSparc64 = 0 -const GoarchWasm = 0 +const Is386 = 0 +const IsAmd64 = 1 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +const IsMips64le = 0 +const IsMips64p32 = 0 +const IsMips64p32le = 0 +const IsPpc = 0 +const IsRiscv = 0 +const IsRiscv64 = 0 +const IsS390 = 0 +const IsS390x = 0 +const IsSparc = 0 +const IsSparc64 = 0 +const IsWasm = 0 diff --git a/src/internal/goarch/zgoarch_arm.go b/src/internal/goarch/zgoarch_arm.go index 9d388b0554..dcdaa1f44d 100644 --- a/src/internal/goarch/zgoarch_arm.go +++ b/src/internal/goarch/zgoarch_arm.go @@ -7,26 +7,26 @@ package goarch const GOARCH = `arm` -const Goarch386 = 0 -const GoarchAmd64 = 0 -const GoarchAmd64p32 = 0 -const GoarchArm = 1 -const GoarchArmbe = 0 -const GoarchArm64 = 0 -const GoarchArm64be = 0 -const GoarchPpc64 = 0 -const GoarchPpc64le = 0 -const GoarchMips = 0 -const GoarchMipsle = 0 -const GoarchMips64 = 0 -const GoarchMips64le = 0 -const GoarchMips64p32 = 0 -const GoarchMips64p32le = 0 -const GoarchPpc = 0 -const GoarchRiscv = 0 -const GoarchRiscv64 = 0 -const GoarchS390 = 0 -const GoarchS390x = 0 -const GoarchSparc = 0 -const GoarchSparc64 = 0 -const GoarchWasm = 0 +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 1 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +const IsMips64le = 0 +const IsMips64p32 = 0 +const IsMips64p32le = 0 +const IsPpc = 0 +const IsRiscv = 0 +const IsRiscv64 = 0 +const IsS390 = 0 +const IsS390x = 0 +const IsSparc = 0 +const IsSparc64 = 0 +const IsWasm = 0 diff --git a/src/internal/goarch/zgoarch_arm64.go b/src/internal/goarch/zgoarch_arm64.go index a375ac8076..dd8d9806ab 100644 --- a/src/internal/goarch/zgoarch_arm64.go +++ b/src/internal/goarch/zgoarch_arm64.go @@ -7,26 +7,26 @@ package goarch const GOARCH = `arm64` -const Goarch386 = 0 -const GoarchAmd64 = 0 -const GoarchAmd64p32 = 0 -const GoarchArm = 0 -const GoarchArmbe = 0 -const GoarchArm64 = 1 -const GoarchArm64be = 0 -const GoarchPpc64 = 0 -const GoarchPpc64le = 0 -const GoarchMips = 0 -const GoarchMipsle = 0 -const GoarchMips64 = 0 -const GoarchMips64le = 0 -const GoarchMips64p32 = 0 -const GoarchMips64p32le = 0 -const GoarchPpc = 0 -const GoarchRiscv = 0 -const GoarchRiscv64 = 0 -const GoarchS390 = 0 -const GoarchS390x = 0 -const GoarchSparc = 0 -const GoarchSparc64 = 0 -const GoarchWasm = 0 +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 1 +const IsArm64be = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +const IsMips64le = 0 +const IsMips64p32 = 0 +const IsMips64p32le = 0 +const IsPpc = 0 +const IsRiscv = 0 +const IsRiscv64 = 0 +const IsS390 = 0 +const IsS390x = 0 +const IsSparc = 0 +const IsSparc64 = 0 +const IsWasm = 0 diff --git a/src/internal/goarch/zgoarch_arm64be.go b/src/internal/goarch/zgoarch_arm64be.go index 6fcc4f6bfa..a37df97031 100644 --- a/src/internal/goarch/zgoarch_arm64be.go +++ b/src/internal/goarch/zgoarch_arm64be.go @@ -7,26 +7,26 @@ package goarch const GOARCH = `arm64be` -const Goarch386 = 0 -const GoarchAmd64 = 0 -const GoarchAmd64p32 = 0 -const GoarchArm = 0 -const GoarchArmbe = 0 -const GoarchArm64 = 0 -const GoarchArm64be = 1 -const GoarchPpc64 = 0 -const GoarchPpc64le = 0 -const GoarchMips = 0 -const GoarchMipsle = 0 -const GoarchMips64 = 0 -const GoarchMips64le = 0 -const GoarchMips64p32 = 0 -const GoarchMips64p32le = 0 -const GoarchPpc = 0 -const GoarchRiscv = 0 -const GoarchRiscv64 = 0 -const GoarchS390 = 0 -const GoarchS390x = 0 -const GoarchSparc = 0 -const GoarchSparc64 = 0 -const GoarchWasm = 0 +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 1 +const IsPpc64 = 0 +const IsPpc64le = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +const IsMips64le = 0 +const IsMips64p32 = 0 +const IsMips64p32le = 0 +const IsPpc = 0 +const IsRiscv = 0 +const IsRiscv64 = 0 +const IsS390 = 0 +const IsS390x = 0 +const IsSparc = 0 +const IsSparc64 = 0 +const IsWasm = 0 diff --git a/src/internal/goarch/zgoarch_armbe.go b/src/internal/goarch/zgoarch_armbe.go index a3ac487d80..909b114330 100644 --- a/src/internal/goarch/zgoarch_armbe.go +++ b/src/internal/goarch/zgoarch_armbe.go @@ -7,26 +7,26 @@ package goarch const GOARCH = `armbe` -const Goarch386 = 0 -const GoarchAmd64 = 0 -const GoarchAmd64p32 = 0 -const GoarchArm = 0 -const GoarchArmbe = 1 -const GoarchArm64 = 0 -const GoarchArm64be = 0 -const GoarchPpc64 = 0 -const GoarchPpc64le = 0 -const GoarchMips = 0 -const GoarchMipsle = 0 -const GoarchMips64 = 0 -const GoarchMips64le = 0 -const GoarchMips64p32 = 0 -const GoarchMips64p32le = 0 -const GoarchPpc = 0 -const GoarchRiscv = 0 -const GoarchRiscv64 = 0 -const GoarchS390 = 0 -const GoarchS390x = 0 -const GoarchSparc = 0 -const GoarchSparc64 = 0 -const GoarchWasm = 0 +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 1 +const IsArm64 = 0 +const IsArm64be = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +const IsMips64le = 0 +const IsMips64p32 = 0 +const IsMips64p32le = 0 +const IsPpc = 0 +const IsRiscv = 0 +const IsRiscv64 = 0 +const IsS390 = 0 +const IsS390x = 0 +const IsSparc = 0 +const IsSparc64 = 0 +const IsWasm = 0 diff --git a/src/internal/goarch/zgoarch_mips.go b/src/internal/goarch/zgoarch_mips.go index 00cfd90c3b..0ff91f201a 100644 --- a/src/internal/goarch/zgoarch_mips.go +++ b/src/internal/goarch/zgoarch_mips.go @@ -7,26 +7,26 @@ package goarch const GOARCH = `mips` -const Goarch386 = 0 -const GoarchAmd64 = 0 -const GoarchAmd64p32 = 0 -const GoarchArm = 0 -const GoarchArmbe = 0 -const GoarchArm64 = 0 -const GoarchArm64be = 0 -const GoarchPpc64 = 0 -const GoarchPpc64le = 0 -const GoarchMips = 1 -const GoarchMipsle = 0 -const GoarchMips64 = 0 -const GoarchMips64le = 0 -const GoarchMips64p32 = 0 -const GoarchMips64p32le = 0 -const GoarchPpc = 0 -const GoarchRiscv = 0 -const GoarchRiscv64 = 0 -const GoarchS390 = 0 -const GoarchS390x = 0 -const GoarchSparc = 0 -const GoarchSparc64 = 0 -const GoarchWasm = 0 +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 +const IsMips = 1 +const IsMipsle = 0 +const IsMips64 = 0 +const IsMips64le = 0 +const IsMips64p32 = 0 +const IsMips64p32le = 0 +const IsPpc = 0 +const IsRiscv = 0 +const IsRiscv64 = 0 +const IsS390 = 0 +const IsS390x = 0 +const IsSparc = 0 +const IsSparc64 = 0 +const IsWasm = 0 diff --git a/src/internal/goarch/zgoarch_mips64.go b/src/internal/goarch/zgoarch_mips64.go index 947db612eb..3b61356b18 100644 --- a/src/internal/goarch/zgoarch_mips64.go +++ b/src/internal/goarch/zgoarch_mips64.go @@ -7,26 +7,26 @@ package goarch const GOARCH = `mips64` -const Goarch386 = 0 -const GoarchAmd64 = 0 -const GoarchAmd64p32 = 0 -const GoarchArm = 0 -const GoarchArmbe = 0 -const GoarchArm64 = 0 -const GoarchArm64be = 0 -const GoarchPpc64 = 0 -const GoarchPpc64le = 0 -const GoarchMips = 0 -const GoarchMipsle = 0 -const GoarchMips64 = 1 -const GoarchMips64le = 0 -const GoarchMips64p32 = 0 -const GoarchMips64p32le = 0 -const GoarchPpc = 0 -const GoarchRiscv = 0 -const GoarchRiscv64 = 0 -const GoarchS390 = 0 -const GoarchS390x = 0 -const GoarchSparc = 0 -const GoarchSparc64 = 0 -const GoarchWasm = 0 +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 1 +const IsMips64le = 0 +const IsMips64p32 = 0 +const IsMips64p32le = 0 +const IsPpc = 0 +const IsRiscv = 0 +const IsRiscv64 = 0 +const IsS390 = 0 +const IsS390x = 0 +const IsSparc = 0 +const IsSparc64 = 0 +const IsWasm = 0 diff --git a/src/internal/goarch/zgoarch_mips64le.go b/src/internal/goarch/zgoarch_mips64le.go index 35ffbe2d3f..14c9330cad 100644 --- a/src/internal/goarch/zgoarch_mips64le.go +++ b/src/internal/goarch/zgoarch_mips64le.go @@ -7,26 +7,26 @@ package goarch const GOARCH = `mips64le` -const Goarch386 = 0 -const GoarchAmd64 = 0 -const GoarchAmd64p32 = 0 -const GoarchArm = 0 -const GoarchArmbe = 0 -const GoarchArm64 = 0 -const GoarchArm64be = 0 -const GoarchPpc64 = 0 -const GoarchPpc64le = 0 -const GoarchMips = 0 -const GoarchMipsle = 0 -const GoarchMips64 = 0 -const GoarchMips64le = 1 -const GoarchMips64p32 = 0 -const GoarchMips64p32le = 0 -const GoarchPpc = 0 -const GoarchRiscv = 0 -const GoarchRiscv64 = 0 -const GoarchS390 = 0 -const GoarchS390x = 0 -const GoarchSparc = 0 -const GoarchSparc64 = 0 -const GoarchWasm = 0 +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +const IsMips64le = 1 +const IsMips64p32 = 0 +const IsMips64p32le = 0 +const IsPpc = 0 +const IsRiscv = 0 +const IsRiscv64 = 0 +const IsS390 = 0 +const IsS390x = 0 +const IsSparc = 0 +const IsSparc64 = 0 +const IsWasm = 0 diff --git a/src/internal/goarch/zgoarch_mips64p32.go b/src/internal/goarch/zgoarch_mips64p32.go index c7c712032b..b7429f2bf3 100644 --- a/src/internal/goarch/zgoarch_mips64p32.go +++ b/src/internal/goarch/zgoarch_mips64p32.go @@ -7,26 +7,26 @@ package goarch const GOARCH = `mips64p32` -const Goarch386 = 0 -const GoarchAmd64 = 0 -const GoarchAmd64p32 = 0 -const GoarchArm = 0 -const GoarchArmbe = 0 -const GoarchArm64 = 0 -const GoarchArm64be = 0 -const GoarchPpc64 = 0 -const GoarchPpc64le = 0 -const GoarchMips = 0 -const GoarchMipsle = 0 -const GoarchMips64 = 0 -const GoarchMips64le = 0 -const GoarchMips64p32 = 1 -const GoarchMips64p32le = 0 -const GoarchPpc = 0 -const GoarchRiscv = 0 -const GoarchRiscv64 = 0 -const GoarchS390 = 0 -const GoarchS390x = 0 -const GoarchSparc = 0 -const GoarchSparc64 = 0 -const GoarchWasm = 0 +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +const IsMips64le = 0 +const IsMips64p32 = 1 +const IsMips64p32le = 0 +const IsPpc = 0 +const IsRiscv = 0 +const IsRiscv64 = 0 +const IsS390 = 0 +const IsS390x = 0 +const IsSparc = 0 +const IsSparc64 = 0 +const IsWasm = 0 diff --git a/src/internal/goarch/zgoarch_mips64p32le.go b/src/internal/goarch/zgoarch_mips64p32le.go index f605a6ff78..35c21c1675 100644 --- a/src/internal/goarch/zgoarch_mips64p32le.go +++ b/src/internal/goarch/zgoarch_mips64p32le.go @@ -7,26 +7,26 @@ package goarch const GOARCH = `mips64p32le` -const Goarch386 = 0 -const GoarchAmd64 = 0 -const GoarchAmd64p32 = 0 -const GoarchArm = 0 -const GoarchArmbe = 0 -const GoarchArm64 = 0 -const GoarchArm64be = 0 -const GoarchPpc64 = 0 -const GoarchPpc64le = 0 -const GoarchMips = 0 -const GoarchMipsle = 0 -const GoarchMips64 = 0 -const GoarchMips64le = 0 -const GoarchMips64p32 = 0 -const GoarchMips64p32le = 1 -const GoarchPpc = 0 -const GoarchRiscv = 0 -const GoarchRiscv64 = 0 -const GoarchS390 = 0 -const GoarchS390x = 0 -const GoarchSparc = 0 -const GoarchSparc64 = 0 -const GoarchWasm = 0 +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +const IsMips64le = 0 +const IsMips64p32 = 0 +const IsMips64p32le = 1 +const IsPpc = 0 +const IsRiscv = 0 +const IsRiscv64 = 0 +const IsS390 = 0 +const IsS390x = 0 +const IsSparc = 0 +const IsSparc64 = 0 +const IsWasm = 0 diff --git a/src/internal/goarch/zgoarch_mipsle.go b/src/internal/goarch/zgoarch_mipsle.go index 56e24dc7b3..ba7be189bc 100644 --- a/src/internal/goarch/zgoarch_mipsle.go +++ b/src/internal/goarch/zgoarch_mipsle.go @@ -7,26 +7,26 @@ package goarch const GOARCH = `mipsle` -const Goarch386 = 0 -const GoarchAmd64 = 0 -const GoarchAmd64p32 = 0 -const GoarchArm = 0 -const GoarchArmbe = 0 -const GoarchArm64 = 0 -const GoarchArm64be = 0 -const GoarchPpc64 = 0 -const GoarchPpc64le = 0 -const GoarchMips = 0 -const GoarchMipsle = 1 -const GoarchMips64 = 0 -const GoarchMips64le = 0 -const GoarchMips64p32 = 0 -const GoarchMips64p32le = 0 -const GoarchPpc = 0 -const GoarchRiscv = 0 -const GoarchRiscv64 = 0 -const GoarchS390 = 0 -const GoarchS390x = 0 -const GoarchSparc = 0 -const GoarchSparc64 = 0 -const GoarchWasm = 0 +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 +const IsMips = 0 +const IsMipsle = 1 +const IsMips64 = 0 +const IsMips64le = 0 +const IsMips64p32 = 0 +const IsMips64p32le = 0 +const IsPpc = 0 +const IsRiscv = 0 +const IsRiscv64 = 0 +const IsS390 = 0 +const IsS390x = 0 +const IsSparc = 0 +const IsSparc64 = 0 +const IsWasm = 0 diff --git a/src/internal/goarch/zgoarch_ppc.go b/src/internal/goarch/zgoarch_ppc.go index 4617d12792..ab19982a12 100644 --- a/src/internal/goarch/zgoarch_ppc.go +++ b/src/internal/goarch/zgoarch_ppc.go @@ -7,26 +7,26 @@ package goarch const GOARCH = `ppc` -const Goarch386 = 0 -const GoarchAmd64 = 0 -const GoarchAmd64p32 = 0 -const GoarchArm = 0 -const GoarchArmbe = 0 -const GoarchArm64 = 0 -const GoarchArm64be = 0 -const GoarchPpc64 = 0 -const GoarchPpc64le = 0 -const GoarchMips = 0 -const GoarchMipsle = 0 -const GoarchMips64 = 0 -const GoarchMips64le = 0 -const GoarchMips64p32 = 0 -const GoarchMips64p32le = 0 -const GoarchPpc = 1 -const GoarchRiscv = 0 -const GoarchRiscv64 = 0 -const GoarchS390 = 0 -const GoarchS390x = 0 -const GoarchSparc = 0 -const GoarchSparc64 = 0 -const GoarchWasm = 0 +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +const IsMips64le = 0 +const IsMips64p32 = 0 +const IsMips64p32le = 0 +const IsPpc = 1 +const IsRiscv = 0 +const IsRiscv64 = 0 +const IsS390 = 0 +const IsS390x = 0 +const IsSparc = 0 +const IsSparc64 = 0 +const IsWasm = 0 diff --git a/src/internal/goarch/zgoarch_ppc64.go b/src/internal/goarch/zgoarch_ppc64.go index f3cb16e9b6..d3e35ca877 100644 --- a/src/internal/goarch/zgoarch_ppc64.go +++ b/src/internal/goarch/zgoarch_ppc64.go @@ -7,26 +7,26 @@ package goarch const GOARCH = `ppc64` -const Goarch386 = 0 -const GoarchAmd64 = 0 -const GoarchAmd64p32 = 0 -const GoarchArm = 0 -const GoarchArmbe = 0 -const GoarchArm64 = 0 -const GoarchArm64be = 0 -const GoarchPpc64 = 1 -const GoarchPpc64le = 0 -const GoarchMips = 0 -const GoarchMipsle = 0 -const GoarchMips64 = 0 -const GoarchMips64le = 0 -const GoarchMips64p32 = 0 -const GoarchMips64p32le = 0 -const GoarchPpc = 0 -const GoarchRiscv = 0 -const GoarchRiscv64 = 0 -const GoarchS390 = 0 -const GoarchS390x = 0 -const GoarchSparc = 0 -const GoarchSparc64 = 0 -const GoarchWasm = 0 +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsPpc64 = 1 +const IsPpc64le = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +const IsMips64le = 0 +const IsMips64p32 = 0 +const IsMips64p32le = 0 +const IsPpc = 0 +const IsRiscv = 0 +const IsRiscv64 = 0 +const IsS390 = 0 +const IsS390x = 0 +const IsSparc = 0 +const IsSparc64 = 0 +const IsWasm = 0 diff --git a/src/internal/goarch/zgoarch_ppc64le.go b/src/internal/goarch/zgoarch_ppc64le.go index b70abfb953..ef24e95c4d 100644 --- a/src/internal/goarch/zgoarch_ppc64le.go +++ b/src/internal/goarch/zgoarch_ppc64le.go @@ -7,26 +7,26 @@ package goarch const GOARCH = `ppc64le` -const Goarch386 = 0 -const GoarchAmd64 = 0 -const GoarchAmd64p32 = 0 -const GoarchArm = 0 -const GoarchArmbe = 0 -const GoarchArm64 = 0 -const GoarchArm64be = 0 -const GoarchPpc64 = 0 -const GoarchPpc64le = 1 -const GoarchMips = 0 -const GoarchMipsle = 0 -const GoarchMips64 = 0 -const GoarchMips64le = 0 -const GoarchMips64p32 = 0 -const GoarchMips64p32le = 0 -const GoarchPpc = 0 -const GoarchRiscv = 0 -const GoarchRiscv64 = 0 -const GoarchS390 = 0 -const GoarchS390x = 0 -const GoarchSparc = 0 -const GoarchSparc64 = 0 -const GoarchWasm = 0 +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsPpc64 = 0 +const IsPpc64le = 1 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +const IsMips64le = 0 +const IsMips64p32 = 0 +const IsMips64p32le = 0 +const IsPpc = 0 +const IsRiscv = 0 +const IsRiscv64 = 0 +const IsS390 = 0 +const IsS390x = 0 +const IsSparc = 0 +const IsSparc64 = 0 +const IsWasm = 0 diff --git a/src/internal/goarch/zgoarch_riscv.go b/src/internal/goarch/zgoarch_riscv.go index f72973fbc5..fe6b385c50 100644 --- a/src/internal/goarch/zgoarch_riscv.go +++ b/src/internal/goarch/zgoarch_riscv.go @@ -7,26 +7,26 @@ package goarch const GOARCH = `riscv` -const Goarch386 = 0 -const GoarchAmd64 = 0 -const GoarchAmd64p32 = 0 -const GoarchArm = 0 -const GoarchArmbe = 0 -const GoarchArm64 = 0 -const GoarchArm64be = 0 -const GoarchPpc64 = 0 -const GoarchPpc64le = 0 -const GoarchMips = 0 -const GoarchMipsle = 0 -const GoarchMips64 = 0 -const GoarchMips64le = 0 -const GoarchMips64p32 = 0 -const GoarchMips64p32le = 0 -const GoarchPpc = 0 -const GoarchRiscv = 1 -const GoarchRiscv64 = 0 -const GoarchS390 = 0 -const GoarchS390x = 0 -const GoarchSparc = 0 -const GoarchSparc64 = 0 -const GoarchWasm = 0 +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +const IsMips64le = 0 +const IsMips64p32 = 0 +const IsMips64p32le = 0 +const IsPpc = 0 +const IsRiscv = 1 +const IsRiscv64 = 0 +const IsS390 = 0 +const IsS390x = 0 +const IsSparc = 0 +const IsSparc64 = 0 +const IsWasm = 0 diff --git a/src/internal/goarch/zgoarch_riscv64.go b/src/internal/goarch/zgoarch_riscv64.go index 5d09b63a03..85299a6b4b 100644 --- a/src/internal/goarch/zgoarch_riscv64.go +++ b/src/internal/goarch/zgoarch_riscv64.go @@ -7,26 +7,26 @@ package goarch const GOARCH = `riscv64` -const Goarch386 = 0 -const GoarchAmd64 = 0 -const GoarchAmd64p32 = 0 -const GoarchArm = 0 -const GoarchArmbe = 0 -const GoarchArm64 = 0 -const GoarchArm64be = 0 -const GoarchPpc64 = 0 -const GoarchPpc64le = 0 -const GoarchMips = 0 -const GoarchMipsle = 0 -const GoarchMips64 = 0 -const GoarchMips64le = 0 -const GoarchMips64p32 = 0 -const GoarchMips64p32le = 0 -const GoarchPpc = 0 -const GoarchRiscv = 0 -const GoarchRiscv64 = 1 -const GoarchS390 = 0 -const GoarchS390x = 0 -const GoarchSparc = 0 -const GoarchSparc64 = 0 -const GoarchWasm = 0 +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +const IsMips64le = 0 +const IsMips64p32 = 0 +const IsMips64p32le = 0 +const IsPpc = 0 +const IsRiscv = 0 +const IsRiscv64 = 1 +const IsS390 = 0 +const IsS390x = 0 +const IsSparc = 0 +const IsSparc64 = 0 +const IsWasm = 0 diff --git a/src/internal/goarch/zgoarch_s390.go b/src/internal/goarch/zgoarch_s390.go index 0ceffe6c2e..39325c473e 100644 --- a/src/internal/goarch/zgoarch_s390.go +++ b/src/internal/goarch/zgoarch_s390.go @@ -7,26 +7,26 @@ package goarch const GOARCH = `s390` -const Goarch386 = 0 -const GoarchAmd64 = 0 -const GoarchAmd64p32 = 0 -const GoarchArm = 0 -const GoarchArmbe = 0 -const GoarchArm64 = 0 -const GoarchArm64be = 0 -const GoarchPpc64 = 0 -const GoarchPpc64le = 0 -const GoarchMips = 0 -const GoarchMipsle = 0 -const GoarchMips64 = 0 -const GoarchMips64le = 0 -const GoarchMips64p32 = 0 -const GoarchMips64p32le = 0 -const GoarchPpc = 0 -const GoarchRiscv = 0 -const GoarchRiscv64 = 0 -const GoarchS390 = 1 -const GoarchS390x = 0 -const GoarchSparc = 0 -const GoarchSparc64 = 0 -const GoarchWasm = 0 +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +const IsMips64le = 0 +const IsMips64p32 = 0 +const IsMips64p32le = 0 +const IsPpc = 0 +const IsRiscv = 0 +const IsRiscv64 = 0 +const IsS390 = 1 +const IsS390x = 0 +const IsSparc = 0 +const IsSparc64 = 0 +const IsWasm = 0 diff --git a/src/internal/goarch/zgoarch_s390x.go b/src/internal/goarch/zgoarch_s390x.go index 142bc0f1e3..64d714ace2 100644 --- a/src/internal/goarch/zgoarch_s390x.go +++ b/src/internal/goarch/zgoarch_s390x.go @@ -7,26 +7,26 @@ package goarch const GOARCH = `s390x` -const Goarch386 = 0 -const GoarchAmd64 = 0 -const GoarchAmd64p32 = 0 -const GoarchArm = 0 -const GoarchArmbe = 0 -const GoarchArm64 = 0 -const GoarchArm64be = 0 -const GoarchPpc64 = 0 -const GoarchPpc64le = 0 -const GoarchMips = 0 -const GoarchMipsle = 0 -const GoarchMips64 = 0 -const GoarchMips64le = 0 -const GoarchMips64p32 = 0 -const GoarchMips64p32le = 0 -const GoarchPpc = 0 -const GoarchRiscv = 0 -const GoarchRiscv64 = 0 -const GoarchS390 = 0 -const GoarchS390x = 1 -const GoarchSparc = 0 -const GoarchSparc64 = 0 -const GoarchWasm = 0 +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +const IsMips64le = 0 +const IsMips64p32 = 0 +const IsMips64p32le = 0 +const IsPpc = 0 +const IsRiscv = 0 +const IsRiscv64 = 0 +const IsS390 = 0 +const IsS390x = 1 +const IsSparc = 0 +const IsSparc64 = 0 +const IsWasm = 0 diff --git a/src/internal/goarch/zgoarch_sparc.go b/src/internal/goarch/zgoarch_sparc.go index 62452b9d38..9ccd362414 100644 --- a/src/internal/goarch/zgoarch_sparc.go +++ b/src/internal/goarch/zgoarch_sparc.go @@ -7,26 +7,26 @@ package goarch const GOARCH = `sparc` -const Goarch386 = 0 -const GoarchAmd64 = 0 -const GoarchAmd64p32 = 0 -const GoarchArm = 0 -const GoarchArmbe = 0 -const GoarchArm64 = 0 -const GoarchArm64be = 0 -const GoarchPpc64 = 0 -const GoarchPpc64le = 0 -const GoarchMips = 0 -const GoarchMipsle = 0 -const GoarchMips64 = 0 -const GoarchMips64le = 0 -const GoarchMips64p32 = 0 -const GoarchMips64p32le = 0 -const GoarchPpc = 0 -const GoarchRiscv = 0 -const GoarchRiscv64 = 0 -const GoarchS390 = 0 -const GoarchS390x = 0 -const GoarchSparc = 1 -const GoarchSparc64 = 0 -const GoarchWasm = 0 +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +const IsMips64le = 0 +const IsMips64p32 = 0 +const IsMips64p32le = 0 +const IsPpc = 0 +const IsRiscv = 0 +const IsRiscv64 = 0 +const IsS390 = 0 +const IsS390x = 0 +const IsSparc = 1 +const IsSparc64 = 0 +const IsWasm = 0 diff --git a/src/internal/goarch/zgoarch_sparc64.go b/src/internal/goarch/zgoarch_sparc64.go index 5149507917..490a714eb6 100644 --- a/src/internal/goarch/zgoarch_sparc64.go +++ b/src/internal/goarch/zgoarch_sparc64.go @@ -7,26 +7,26 @@ package goarch const GOARCH = `sparc64` -const Goarch386 = 0 -const GoarchAmd64 = 0 -const GoarchAmd64p32 = 0 -const GoarchArm = 0 -const GoarchArmbe = 0 -const GoarchArm64 = 0 -const GoarchArm64be = 0 -const GoarchPpc64 = 0 -const GoarchPpc64le = 0 -const GoarchMips = 0 -const GoarchMipsle = 0 -const GoarchMips64 = 0 -const GoarchMips64le = 0 -const GoarchMips64p32 = 0 -const GoarchMips64p32le = 0 -const GoarchPpc = 0 -const GoarchRiscv = 0 -const GoarchRiscv64 = 0 -const GoarchS390 = 0 -const GoarchS390x = 0 -const GoarchSparc = 0 -const GoarchSparc64 = 1 -const GoarchWasm = 0 +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +const IsMips64le = 0 +const IsMips64p32 = 0 +const IsMips64p32le = 0 +const IsPpc = 0 +const IsRiscv = 0 +const IsRiscv64 = 0 +const IsS390 = 0 +const IsS390x = 0 +const IsSparc = 0 +const IsSparc64 = 1 +const IsWasm = 0 diff --git a/src/internal/goarch/zgoarch_wasm.go b/src/internal/goarch/zgoarch_wasm.go index fd25e93e74..a4b4a38401 100644 --- a/src/internal/goarch/zgoarch_wasm.go +++ b/src/internal/goarch/zgoarch_wasm.go @@ -7,26 +7,26 @@ package goarch const GOARCH = `wasm` -const Goarch386 = 0 -const GoarchAmd64 = 0 -const GoarchAmd64p32 = 0 -const GoarchArm = 0 -const GoarchArmbe = 0 -const GoarchArm64 = 0 -const GoarchArm64be = 0 -const GoarchPpc64 = 0 -const GoarchPpc64le = 0 -const GoarchMips = 0 -const GoarchMipsle = 0 -const GoarchMips64 = 0 -const GoarchMips64le = 0 -const GoarchMips64p32 = 0 -const GoarchMips64p32le = 0 -const GoarchPpc = 0 -const GoarchRiscv = 0 -const GoarchRiscv64 = 0 -const GoarchS390 = 0 -const GoarchS390x = 0 -const GoarchSparc = 0 -const GoarchSparc64 = 0 -const GoarchWasm = 1 +const Is386 = 0 +const IsAmd64 = 0 +const IsAmd64p32 = 0 +const IsArm = 0 +const IsArmbe = 0 +const IsArm64 = 0 +const IsArm64be = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 +const IsMips = 0 +const IsMipsle = 0 +const IsMips64 = 0 +const IsMips64le = 0 +const IsMips64p32 = 0 +const IsMips64p32le = 0 +const IsPpc = 0 +const IsRiscv = 0 +const IsRiscv64 = 0 +const IsS390 = 0 +const IsS390x = 0 +const IsSparc = 0 +const IsSparc64 = 0 +const IsWasm = 1 diff --git a/src/internal/goos/gengoos.go b/src/internal/goos/gengoos.go index ebcdfec3ba..1860cd700d 100644 --- a/src/internal/goos/gengoos.go +++ b/src/internal/goos/gengoos.go @@ -60,7 +60,7 @@ func main() { if goos == target { value = 1 } - fmt.Fprintf(&buf, "const Goos%s = %d\n", strings.Title(goos), value) + fmt.Fprintf(&buf, "const Is%s = %d\n", strings.Title(goos), value) } err := os.WriteFile("zgoos_"+target+".go", buf.Bytes(), 0666) if err != nil { diff --git a/src/internal/goos/goos.go b/src/internal/goos/goos.go index 332cf51e5d..ebb521fec6 100644 --- a/src/internal/goos/goos.go +++ b/src/internal/goos/goos.go @@ -6,7 +6,7 @@ package goos // The next line makes 'go generate' write the zgoos*.go files with -// per-OS information, including constants named Goos$GOOS for every +// per-OS information, including constants named Is$GOOS for every // known GOOS. The constant is 1 on the current system, 0 otherwise; // multiplying by them is useful for defining GOOS-specific constants. //go:generate go run gengoos.go diff --git a/src/internal/goos/zgoos_aix.go b/src/internal/goos/zgoos_aix.go index f453a8a0a8..063e698b82 100644 --- a/src/internal/goos/zgoos_aix.go +++ b/src/internal/goos/zgoos_aix.go @@ -7,20 +7,20 @@ package goos const GOOS = `aix` -const GoosAix = 1 -const GoosAndroid = 0 -const GoosDarwin = 0 -const GoosDragonfly = 0 -const GoosFreebsd = 0 -const GoosHurd = 0 -const GoosIllumos = 0 -const GoosIos = 0 -const GoosJs = 0 -const GoosLinux = 0 -const GoosNacl = 0 -const GoosNetbsd = 0 -const GoosOpenbsd = 0 -const GoosPlan9 = 0 -const GoosSolaris = 0 -const GoosWindows = 0 -const GoosZos = 0 +const IsAix = 1 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/src/internal/goos/zgoos_android.go b/src/internal/goos/zgoos_android.go index d90c04f758..e9e4864978 100644 --- a/src/internal/goos/zgoos_android.go +++ b/src/internal/goos/zgoos_android.go @@ -7,20 +7,20 @@ package goos const GOOS = `android` -const GoosAix = 0 -const GoosAndroid = 1 -const GoosDarwin = 0 -const GoosDragonfly = 0 -const GoosFreebsd = 0 -const GoosHurd = 0 -const GoosIllumos = 0 -const GoosIos = 0 -const GoosJs = 0 -const GoosLinux = 0 -const GoosNacl = 0 -const GoosNetbsd = 0 -const GoosOpenbsd = 0 -const GoosPlan9 = 0 -const GoosSolaris = 0 -const GoosWindows = 0 -const GoosZos = 0 +const IsAix = 0 +const IsAndroid = 1 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/src/internal/goos/zgoos_darwin.go b/src/internal/goos/zgoos_darwin.go index 18f6c28b12..309d6a2717 100644 --- a/src/internal/goos/zgoos_darwin.go +++ b/src/internal/goos/zgoos_darwin.go @@ -7,20 +7,20 @@ package goos const GOOS = `darwin` -const GoosAix = 0 -const GoosAndroid = 0 -const GoosDarwin = 1 -const GoosDragonfly = 0 -const GoosFreebsd = 0 -const GoosHurd = 0 -const GoosIllumos = 0 -const GoosIos = 0 -const GoosJs = 0 -const GoosLinux = 0 -const GoosNacl = 0 -const GoosNetbsd = 0 -const GoosOpenbsd = 0 -const GoosPlan9 = 0 -const GoosSolaris = 0 -const GoosWindows = 0 -const GoosZos = 0 +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 1 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/src/internal/goos/zgoos_dragonfly.go b/src/internal/goos/zgoos_dragonfly.go index a658d1d07f..4e8711b94c 100644 --- a/src/internal/goos/zgoos_dragonfly.go +++ b/src/internal/goos/zgoos_dragonfly.go @@ -7,20 +7,20 @@ package goos const GOOS = `dragonfly` -const GoosAix = 0 -const GoosAndroid = 0 -const GoosDarwin = 0 -const GoosDragonfly = 1 -const GoosFreebsd = 0 -const GoosHurd = 0 -const GoosIllumos = 0 -const GoosIos = 0 -const GoosJs = 0 -const GoosLinux = 0 -const GoosNacl = 0 -const GoosNetbsd = 0 -const GoosOpenbsd = 0 -const GoosPlan9 = 0 -const GoosSolaris = 0 -const GoosWindows = 0 -const GoosZos = 0 +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 1 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/src/internal/goos/zgoos_freebsd.go b/src/internal/goos/zgoos_freebsd.go index 2534eb8c6f..f312bd1608 100644 --- a/src/internal/goos/zgoos_freebsd.go +++ b/src/internal/goos/zgoos_freebsd.go @@ -7,20 +7,20 @@ package goos const GOOS = `freebsd` -const GoosAix = 0 -const GoosAndroid = 0 -const GoosDarwin = 0 -const GoosDragonfly = 0 -const GoosFreebsd = 1 -const GoosHurd = 0 -const GoosIllumos = 0 -const GoosIos = 0 -const GoosJs = 0 -const GoosLinux = 0 -const GoosNacl = 0 -const GoosNetbsd = 0 -const GoosOpenbsd = 0 -const GoosPlan9 = 0 -const GoosSolaris = 0 -const GoosWindows = 0 -const GoosZos = 0 +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 1 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/src/internal/goos/zgoos_hurd.go b/src/internal/goos/zgoos_hurd.go index 3fefb1fbb1..0f0dd28b81 100644 --- a/src/internal/goos/zgoos_hurd.go +++ b/src/internal/goos/zgoos_hurd.go @@ -7,20 +7,20 @@ package goos const GOOS = `hurd` -const GoosAix = 0 -const GoosAndroid = 0 -const GoosDarwin = 0 -const GoosDragonfly = 0 -const GoosFreebsd = 0 -const GoosHurd = 1 -const GoosIllumos = 0 -const GoosIos = 0 -const GoosJs = 0 -const GoosLinux = 0 -const GoosNacl = 0 -const GoosNetbsd = 0 -const GoosOpenbsd = 0 -const GoosPlan9 = 0 -const GoosSolaris = 0 -const GoosWindows = 0 -const GoosZos = 0 +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 1 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/src/internal/goos/zgoos_illumos.go b/src/internal/goos/zgoos_illumos.go index 77495a3369..17e7c53a40 100644 --- a/src/internal/goos/zgoos_illumos.go +++ b/src/internal/goos/zgoos_illumos.go @@ -7,20 +7,20 @@ package goos const GOOS = `illumos` -const GoosAix = 0 -const GoosAndroid = 0 -const GoosDarwin = 0 -const GoosDragonfly = 0 -const GoosFreebsd = 0 -const GoosHurd = 0 -const GoosIllumos = 1 -const GoosIos = 0 -const GoosJs = 0 -const GoosLinux = 0 -const GoosNacl = 0 -const GoosNetbsd = 0 -const GoosOpenbsd = 0 -const GoosPlan9 = 0 -const GoosSolaris = 0 -const GoosWindows = 0 -const GoosZos = 0 +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 1 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/src/internal/goos/zgoos_ios.go b/src/internal/goos/zgoos_ios.go index 92820fe77e..e4745ca413 100644 --- a/src/internal/goos/zgoos_ios.go +++ b/src/internal/goos/zgoos_ios.go @@ -7,20 +7,20 @@ package goos const GOOS = `ios` -const GoosAix = 0 -const GoosAndroid = 0 -const GoosDarwin = 0 -const GoosDragonfly = 0 -const GoosFreebsd = 0 -const GoosHurd = 0 -const GoosIllumos = 0 -const GoosIos = 1 -const GoosJs = 0 -const GoosLinux = 0 -const GoosNacl = 0 -const GoosNetbsd = 0 -const GoosOpenbsd = 0 -const GoosPlan9 = 0 -const GoosSolaris = 0 -const GoosWindows = 0 -const GoosZos = 0 +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 1 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/src/internal/goos/zgoos_js.go b/src/internal/goos/zgoos_js.go index 6331a5c3f1..bd2417e9ce 100644 --- a/src/internal/goos/zgoos_js.go +++ b/src/internal/goos/zgoos_js.go @@ -7,20 +7,20 @@ package goos const GOOS = `js` -const GoosAix = 0 -const GoosAndroid = 0 -const GoosDarwin = 0 -const GoosDragonfly = 0 -const GoosFreebsd = 0 -const GoosHurd = 0 -const GoosIllumos = 0 -const GoosIos = 0 -const GoosJs = 1 -const GoosLinux = 0 -const GoosNacl = 0 -const GoosNetbsd = 0 -const GoosOpenbsd = 0 -const GoosPlan9 = 0 -const GoosSolaris = 0 -const GoosWindows = 0 -const GoosZos = 0 +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 1 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/src/internal/goos/zgoos_linux.go b/src/internal/goos/zgoos_linux.go index aa4e2d3145..476702f442 100644 --- a/src/internal/goos/zgoos_linux.go +++ b/src/internal/goos/zgoos_linux.go @@ -7,20 +7,20 @@ package goos const GOOS = `linux` -const GoosAix = 0 -const GoosAndroid = 0 -const GoosDarwin = 0 -const GoosDragonfly = 0 -const GoosFreebsd = 0 -const GoosHurd = 0 -const GoosIllumos = 0 -const GoosIos = 0 -const GoosJs = 0 -const GoosLinux = 1 -const GoosNacl = 0 -const GoosNetbsd = 0 -const GoosOpenbsd = 0 -const GoosPlan9 = 0 -const GoosSolaris = 0 -const GoosWindows = 0 -const GoosZos = 0 +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 1 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/src/internal/goos/zgoos_netbsd.go b/src/internal/goos/zgoos_netbsd.go index 39635104c0..97b7564bab 100644 --- a/src/internal/goos/zgoos_netbsd.go +++ b/src/internal/goos/zgoos_netbsd.go @@ -7,20 +7,20 @@ package goos const GOOS = `netbsd` -const GoosAix = 0 -const GoosAndroid = 0 -const GoosDarwin = 0 -const GoosDragonfly = 0 -const GoosFreebsd = 0 -const GoosHurd = 0 -const GoosIllumos = 0 -const GoosIos = 0 -const GoosJs = 0 -const GoosLinux = 0 -const GoosNacl = 0 -const GoosNetbsd = 1 -const GoosOpenbsd = 0 -const GoosPlan9 = 0 -const GoosSolaris = 0 -const GoosWindows = 0 -const GoosZos = 0 +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 1 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/src/internal/goos/zgoos_openbsd.go b/src/internal/goos/zgoos_openbsd.go index 61d4ac8bb0..384a96480d 100644 --- a/src/internal/goos/zgoos_openbsd.go +++ b/src/internal/goos/zgoos_openbsd.go @@ -7,20 +7,20 @@ package goos const GOOS = `openbsd` -const GoosAix = 0 -const GoosAndroid = 0 -const GoosDarwin = 0 -const GoosDragonfly = 0 -const GoosFreebsd = 0 -const GoosHurd = 0 -const GoosIllumos = 0 -const GoosIos = 0 -const GoosJs = 0 -const GoosLinux = 0 -const GoosNacl = 0 -const GoosNetbsd = 0 -const GoosOpenbsd = 1 -const GoosPlan9 = 0 -const GoosSolaris = 0 -const GoosWindows = 0 -const GoosZos = 0 +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 1 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/src/internal/goos/zgoos_plan9.go b/src/internal/goos/zgoos_plan9.go index 7f0dc2fa04..fcc279a79e 100644 --- a/src/internal/goos/zgoos_plan9.go +++ b/src/internal/goos/zgoos_plan9.go @@ -7,20 +7,20 @@ package goos const GOOS = `plan9` -const GoosAix = 0 -const GoosAndroid = 0 -const GoosDarwin = 0 -const GoosDragonfly = 0 -const GoosFreebsd = 0 -const GoosHurd = 0 -const GoosIllumos = 0 -const GoosIos = 0 -const GoosJs = 0 -const GoosLinux = 0 -const GoosNacl = 0 -const GoosNetbsd = 0 -const GoosOpenbsd = 0 -const GoosPlan9 = 1 -const GoosSolaris = 0 -const GoosWindows = 0 -const GoosZos = 0 +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 1 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 0 diff --git a/src/internal/goos/zgoos_solaris.go b/src/internal/goos/zgoos_solaris.go index 7497324a4f..3f366cf710 100644 --- a/src/internal/goos/zgoos_solaris.go +++ b/src/internal/goos/zgoos_solaris.go @@ -7,20 +7,20 @@ package goos const GOOS = `solaris` -const GoosAix = 0 -const GoosAndroid = 0 -const GoosDarwin = 0 -const GoosDragonfly = 0 -const GoosFreebsd = 0 -const GoosHurd = 0 -const GoosIllumos = 0 -const GoosIos = 0 -const GoosJs = 0 -const GoosLinux = 0 -const GoosNacl = 0 -const GoosNetbsd = 0 -const GoosOpenbsd = 0 -const GoosPlan9 = 0 -const GoosSolaris = 1 -const GoosWindows = 0 -const GoosZos = 0 +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 1 +const IsWindows = 0 +const IsZos = 0 diff --git a/src/internal/goos/zgoos_windows.go b/src/internal/goos/zgoos_windows.go index e316b80c82..dfa55339d3 100644 --- a/src/internal/goos/zgoos_windows.go +++ b/src/internal/goos/zgoos_windows.go @@ -7,20 +7,20 @@ package goos const GOOS = `windows` -const GoosAix = 0 -const GoosAndroid = 0 -const GoosDarwin = 0 -const GoosDragonfly = 0 -const GoosFreebsd = 0 -const GoosHurd = 0 -const GoosIllumos = 0 -const GoosIos = 0 -const GoosJs = 0 -const GoosLinux = 0 -const GoosNacl = 0 -const GoosNetbsd = 0 -const GoosOpenbsd = 0 -const GoosPlan9 = 0 -const GoosSolaris = 0 -const GoosWindows = 1 -const GoosZos = 0 +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 1 +const IsZos = 0 diff --git a/src/internal/goos/zgoos_zos.go b/src/internal/goos/zgoos_zos.go index 26471f4f36..714f24963a 100644 --- a/src/internal/goos/zgoos_zos.go +++ b/src/internal/goos/zgoos_zos.go @@ -7,20 +7,20 @@ package goos const GOOS = `zos` -const GoosAix = 0 -const GoosAndroid = 0 -const GoosDarwin = 0 -const GoosDragonfly = 0 -const GoosFreebsd = 0 -const GoosHurd = 0 -const GoosIllumos = 0 -const GoosIos = 0 -const GoosJs = 0 -const GoosLinux = 0 -const GoosNacl = 0 -const GoosNetbsd = 0 -const GoosOpenbsd = 0 -const GoosPlan9 = 0 -const GoosSolaris = 0 -const GoosWindows = 0 -const GoosZos = 1 +const IsAix = 0 +const IsAndroid = 0 +const IsDarwin = 0 +const IsDragonfly = 0 +const IsFreebsd = 0 +const IsHurd = 0 +const IsIllumos = 0 +const IsIos = 0 +const IsJs = 0 +const IsLinux = 0 +const IsNacl = 0 +const IsNetbsd = 0 +const IsOpenbsd = 0 +const IsPlan9 = 0 +const IsSolaris = 0 +const IsWindows = 0 +const IsZos = 1 diff --git a/src/runtime/internal/sys/consts.go b/src/runtime/internal/sys/consts.go index 6400c10748..ab0a02671a 100644 --- a/src/runtime/internal/sys/consts.go +++ b/src/runtime/internal/sys/consts.go @@ -10,7 +10,7 @@ import ( ) // AIX requires a larger stack for syscalls. -const StackGuardMultiplier = StackGuardMultiplierDefault*(1-goos.GoosAix) + 2*goos.GoosAix +const StackGuardMultiplier = StackGuardMultiplierDefault*(1-goos.IsAix) + 2*goos.IsAix // DefaultPhysPageSize is the default physical page size. const DefaultPhysPageSize = goarch.DefaultPhysPageSize @@ -34,47 +34,47 @@ const MinFrameSize = goarch.MinFrameSize const StackAlign = goarch.StackAlign const ( - Goarch386 = goarch.Goarch386 - GoarchAmd64 = goarch.GoarchAmd64 - GoarchAmd64p32 = goarch.GoarchAmd64p32 - GoarchArm = goarch.GoarchArm - GoarchArmbe = goarch.GoarchArmbe - GoarchArm64 = goarch.GoarchArm64 - GoarchArm64be = goarch.GoarchArm64be - GoarchPpc64 = goarch.GoarchPpc64 - GoarchPpc64le = goarch.GoarchPpc64le - GoarchMips = goarch.GoarchMips - GoarchMipsle = goarch.GoarchMipsle - GoarchMips64 = goarch.GoarchMips64 - GoarchMips64le = goarch.GoarchMips64le - GoarchMips64p32 = goarch.GoarchMips64p32 - GoarchMips64p32le = goarch.GoarchMips64p32le - GoarchPpc = goarch.GoarchPpc - GoarchRiscv = goarch.GoarchRiscv - GoarchRiscv64 = goarch.GoarchRiscv64 - GoarchS390 = goarch.GoarchS390 - GoarchS390x = goarch.GoarchS390x - GoarchSparc = goarch.GoarchSparc - GoarchSparc64 = goarch.GoarchSparc64 - GoarchWasm = goarch.GoarchWasm + Goarch386 = goarch.Is386 + GoarchAmd64 = goarch.IsAmd64 + GoarchAmd64p32 = goarch.IsAmd64p32 + GoarchArm = goarch.IsArm + GoarchArmbe = goarch.IsArmbe + GoarchArm64 = goarch.IsArm64 + GoarchArm64be = goarch.IsArm64be + GoarchPpc64 = goarch.IsPpc64 + GoarchPpc64le = goarch.IsPpc64le + GoarchMips = goarch.IsMips + GoarchMipsle = goarch.IsMipsle + GoarchMips64 = goarch.IsMips64 + GoarchMips64le = goarch.IsMips64le + GoarchMips64p32 = goarch.IsMips64p32 + GoarchMips64p32le = goarch.IsMips64p32le + GoarchPpc = goarch.IsPpc + GoarchRiscv = goarch.IsRiscv + GoarchRiscv64 = goarch.IsRiscv64 + GoarchS390 = goarch.IsS390 + GoarchS390x = goarch.IsS390x + GoarchSparc = goarch.IsSparc + GoarchSparc64 = goarch.IsSparc64 + GoarchWasm = goarch.IsWasm ) const ( - GoosAix = goos.GoosAix - GoosAndroid = goos.GoosAndroid - GoosDarwin = goos.GoosDarwin - GoosDragonfly = goos.GoosDragonfly - GoosFreebsd = goos.GoosFreebsd - GoosHurd = goos.GoosHurd - GoosIllumos = goos.GoosIllumos - GoosIos = goos.GoosIos - GoosJs = goos.GoosJs - GoosLinux = goos.GoosLinux - GoosNacl = goos.GoosNacl - GoosNetbsd = goos.GoosNetbsd - GoosOpenbsd = goos.GoosOpenbsd - GoosPlan9 = goos.GoosPlan9 - GoosSolaris = goos.GoosSolaris - GoosWindows = goos.GoosWindows - GoosZos = goos.GoosZos + GoosAix = goos.IsAix + GoosAndroid = goos.IsAndroid + GoosDarwin = goos.IsDarwin + GoosDragonfly = goos.IsDragonfly + GoosFreebsd = goos.IsFreebsd + GoosHurd = goos.IsHurd + GoosIllumos = goos.IsIllumos + GoosIos = goos.IsIos + GoosJs = goos.IsJs + GoosLinux = goos.IsLinux + GoosNacl = goos.IsNacl + GoosNetbsd = goos.IsNetbsd + GoosOpenbsd = goos.IsOpenbsd + GoosPlan9 = goos.IsPlan9 + GoosSolaris = goos.IsSolaris + GoosWindows = goos.IsWindows + GoosZos = goos.IsZos ) -- GitLab From 7b0e9cae66fc706bb390ba08fb4801015359f17b Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Wed, 16 Jun 2021 21:52:24 +0000 Subject: [PATCH 0306/2500] [dev.typeparams] runtime: replace Goos* constants with internal/goos versions [generated] [git-generate] cd src/runtime gofmt -w -r "sys.GoosAix -> goos.IsAix" . gofmt -w -r "sys.GoosAndroid -> goos.IsAndroid" . gofmt -w -r "sys.GoosDarwin -> goos.IsDarwin" . gofmt -w -r "sys.GoosDragonfly -> goos.IsDragonfly" . gofmt -w -r "sys.GoosFreebsd -> goos.IsFreebsd" . gofmt -w -r "sys.GoosHurd -> goos.IsHurd" . gofmt -w -r "sys.GoosIllumos -> goos.IsIllumos" . gofmt -w -r "sys.GoosIos -> goos.IsIos" . gofmt -w -r "sys.GoosJs -> goos.IsJs" . gofmt -w -r "sys.GoosLinux -> goos.IsLinux" . gofmt -w -r "sys.GoosNacl -> goos.IsNacl" . gofmt -w -r "sys.GoosNetbsd -> goos.IsNetbsd" . gofmt -w -r "sys.GoosOpenbsd -> goos.IsOpenbsd" . gofmt -w -r "sys.GoosPlan9 -> goos.IsPlan9" . gofmt -w -r "sys.GoosSolaris -> goos.IsSolaris" . gofmt -w -r "sys.GoosWindows -> goos.IsWindows" . gofmt -w -r "sys.GoosZos -> goos.IsZos" . goimports -w *.go Change-Id: I42bed2907317ed409812e5a3e2897c88a5d36f24 Reviewed-on: https://go-review.googlesource.com/c/go/+/328344 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/runtime/export_test.go | 3 ++- src/runtime/malloc.go | 11 ++++++----- src/runtime/mgcscavenge.go | 3 ++- src/runtime/stack.go | 3 ++- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index f3118472fd..e7279564e3 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -8,6 +8,7 @@ package runtime import ( "internal/goarch" + "internal/goos" "runtime/internal/atomic" "runtime/internal/sys" "unsafe" @@ -1051,7 +1052,7 @@ func FreePageAlloc(pp *PageAlloc) { // // This should not be higher than 0x100*pallocChunkBytes to support // mips and mipsle, which only have 31-bit address spaces. -var BaseChunkIdx = ChunkIdx(chunkIndex(((0xc000*pageAlloc64Bit + 0x100*pageAlloc32Bit) * pallocChunkBytes) + arenaBaseOffset*sys.GoosAix)) +var BaseChunkIdx = ChunkIdx(chunkIndex(((0xc000*pageAlloc64Bit + 0x100*pageAlloc32Bit) * pallocChunkBytes) + arenaBaseOffset*goos.IsAix)) // PageBase returns an address given a chunk index and a page index // relative to that chunk. diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index 205e25ed88..715019671d 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -102,6 +102,7 @@ package runtime import ( "internal/goarch" + "internal/goos" "runtime/internal/atomic" "runtime/internal/math" "runtime/internal/sys" @@ -151,7 +152,7 @@ const ( // windows/32 | 4KB | 3 // windows/64 | 8KB | 2 // plan9 | 4KB | 3 - _NumStackOrders = 4 - goarch.PtrSize/4*sys.GoosWindows - 1*sys.GoosPlan9 + _NumStackOrders = 4 - goarch.PtrSize/4*goos.IsWindows - 1*goos.IsPlan9 // heapAddrBits is the number of bits in a heap address. On // amd64, addresses are sign-extended beyond heapAddrBits. On @@ -208,7 +209,7 @@ const ( // arenaBaseOffset to offset into the top 4 GiB. // // WebAssembly currently has a limit of 4GB linear memory. - heapAddrBits = (_64bit*(1-sys.GoarchWasm)*(1-sys.GoosIos*sys.GoarchArm64))*48 + (1-_64bit+sys.GoarchWasm)*(32-(sys.GoarchMips+sys.GoarchMipsle)) + 33*sys.GoosIos*sys.GoarchArm64 + heapAddrBits = (_64bit*(1-sys.GoarchWasm)*(1-goos.IsIos*sys.GoarchArm64))*48 + (1-_64bit+sys.GoarchWasm)*(32-(sys.GoarchMips+sys.GoarchMipsle)) + 33*goos.IsIos*sys.GoarchArm64 // maxAlloc is the maximum size of an allocation. On 64-bit, // it's theoretically possible to allocate 1< Date: Wed, 16 Jun 2021 21:57:58 +0000 Subject: [PATCH 0307/2500] [dev.typeparams] runtime: replace Goarch* constants with internal/goarch versions [generated] [git-generate] cd src/runtime gofmt -w -r "sys.Goarch386 -> goarch.Is386" . gofmt -w -r "sys.GoarchAmd64 -> goarch.IsAmd64" . gofmt -w -r "sys.GoarchAmd64p32 -> goarch.IsAmd64p32" . gofmt -w -r "sys.GoarchArm -> goarch.IsArm" . gofmt -w -r "sys.GoarchArmbe -> goarch.IsArmbe" . gofmt -w -r "sys.GoarchArm64 -> goarch.IsArm64" . gofmt -w -r "sys.GoarchArm64be -> goarch.IsArm64be" . gofmt -w -r "sys.GoarchPpc64 -> goarch.IsPpc64" . gofmt -w -r "sys.GoarchPpc64le -> goarch.IsPpc64le" . gofmt -w -r "sys.GoarchMips -> goarch.IsMips" . gofmt -w -r "sys.GoarchMipsle -> goarch.IsMipsle" . gofmt -w -r "sys.GoarchMips64 -> goarch.IsMips64" . gofmt -w -r "sys.GoarchMips64le -> goarch.IsMips64le" . gofmt -w -r "sys.GoarchMips64p32 -> goarch.IsMips64p32" . gofmt -w -r "sys.GoarchMips64p32le -> goarch.IsMips64p32le" . gofmt -w -r "sys.GoarchPpc -> goarch.IsPpc" . gofmt -w -r "sys.GoarchRiscv -> goarch.IsRiscv" . gofmt -w -r "sys.GoarchRiscv64 -> goarch.IsRiscv64" . gofmt -w -r "sys.GoarchS390 -> goarch.IsS390" . gofmt -w -r "sys.GoarchS390x -> goarch.IsS390x" . gofmt -w -r "sys.GoarchSparc -> goarch.IsSparc" . gofmt -w -r "sys.GoarchSparc64 -> goarch.IsSparc64" . gofmt -w -r "sys.GoarchWasm -> goarch.IsWasm" . goimports -w *.go Change-Id: I9d88e1284efabaeb0ee3733cba6286247d078c85 Reviewed-on: https://go-review.googlesource.com/c/go/+/328345 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/runtime/malloc.go | 6 +++--- src/runtime/panic.go | 3 ++- src/runtime/stack.go | 2 +- src/runtime/trace.go | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index 715019671d..8483ec99d8 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -209,7 +209,7 @@ const ( // arenaBaseOffset to offset into the top 4 GiB. // // WebAssembly currently has a limit of 4GB linear memory. - heapAddrBits = (_64bit*(1-sys.GoarchWasm)*(1-goos.IsIos*sys.GoarchArm64))*48 + (1-_64bit+sys.GoarchWasm)*(32-(sys.GoarchMips+sys.GoarchMipsle)) + 33*goos.IsIos*sys.GoarchArm64 + heapAddrBits = (_64bit*(1-goarch.IsWasm)*(1-goos.IsIos*goarch.IsArm64))*48 + (1-_64bit+goarch.IsWasm)*(32-(goarch.IsMips+goarch.IsMipsle)) + 33*goos.IsIos*goarch.IsArm64 // maxAlloc is the maximum size of an allocation. On 64-bit, // it's theoretically possible to allocate 1< Date: Thu, 17 Jun 2021 19:49:42 +0000 Subject: [PATCH 0308/2500] [dev.typeparams] runtime/internal/sys: remove unused Goarch* and Goos* constants Change-Id: Ibc8381662242c6754f34edce9c0ad81681f55940 Reviewed-on: https://go-review.googlesource.com/c/go/+/329192 Trust: Michael Knyszek Run-TryBot: Michael Knyszek Reviewed-by: Matthew Dempsky TryBot-Result: Go Bot --- src/runtime/internal/sys/consts.go | 46 ------------------------------ 1 file changed, 46 deletions(-) diff --git a/src/runtime/internal/sys/consts.go b/src/runtime/internal/sys/consts.go index ab0a02671a..fffcf81d1f 100644 --- a/src/runtime/internal/sys/consts.go +++ b/src/runtime/internal/sys/consts.go @@ -32,49 +32,3 @@ const MinFrameSize = goarch.MinFrameSize // StackAlign is the required alignment of the SP register. // The stack must be at least word aligned, but some architectures require more. const StackAlign = goarch.StackAlign - -const ( - Goarch386 = goarch.Is386 - GoarchAmd64 = goarch.IsAmd64 - GoarchAmd64p32 = goarch.IsAmd64p32 - GoarchArm = goarch.IsArm - GoarchArmbe = goarch.IsArmbe - GoarchArm64 = goarch.IsArm64 - GoarchArm64be = goarch.IsArm64be - GoarchPpc64 = goarch.IsPpc64 - GoarchPpc64le = goarch.IsPpc64le - GoarchMips = goarch.IsMips - GoarchMipsle = goarch.IsMipsle - GoarchMips64 = goarch.IsMips64 - GoarchMips64le = goarch.IsMips64le - GoarchMips64p32 = goarch.IsMips64p32 - GoarchMips64p32le = goarch.IsMips64p32le - GoarchPpc = goarch.IsPpc - GoarchRiscv = goarch.IsRiscv - GoarchRiscv64 = goarch.IsRiscv64 - GoarchS390 = goarch.IsS390 - GoarchS390x = goarch.IsS390x - GoarchSparc = goarch.IsSparc - GoarchSparc64 = goarch.IsSparc64 - GoarchWasm = goarch.IsWasm -) - -const ( - GoosAix = goos.IsAix - GoosAndroid = goos.IsAndroid - GoosDarwin = goos.IsDarwin - GoosDragonfly = goos.IsDragonfly - GoosFreebsd = goos.IsFreebsd - GoosHurd = goos.IsHurd - GoosIllumos = goos.IsIllumos - GoosIos = goos.IsIos - GoosJs = goos.IsJs - GoosLinux = goos.IsLinux - GoosNacl = goos.IsNacl - GoosNetbsd = goos.IsNetbsd - GoosOpenbsd = goos.IsOpenbsd - GoosPlan9 = goos.IsPlan9 - GoosSolaris = goos.IsSolaris - GoosWindows = goos.IsWindows - GoosZos = goos.IsZos -) -- GitLab From 95c104ee61c88f77f43131b02a9ff3926e128669 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Wed, 16 Jun 2021 22:05:36 +0000 Subject: [PATCH 0309/2500] [dev.typeparams] reflect: use goarch.PtrSize instead of the duplicated ptrSize [generated] [git-generate] cd src/reflect gofmt -w -r "PtrSize -> goarch.PtrSize" . gofmt -w -r "ptrSize -> goarch.PtrSize" . goimports -w *.go Change-Id: Ib534bb0ecde10d93f45365ab4f8efd620d6d2ef3 Reviewed-on: https://go-review.googlesource.com/c/go/+/328346 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/reflect/abi.go | 23 ++++++------ src/reflect/all_test.go | 75 +++++++++++++++++++------------------- src/reflect/export_test.go | 5 ++- src/reflect/swapper.go | 3 +- src/reflect/type.go | 47 ++++++++++++------------ src/reflect/value.go | 7 ++-- 6 files changed, 83 insertions(+), 77 deletions(-) diff --git a/src/reflect/abi.go b/src/reflect/abi.go index 17b79a8394..9ddde3ae57 100644 --- a/src/reflect/abi.go +++ b/src/reflect/abi.go @@ -6,6 +6,7 @@ package reflect import ( "internal/abi" + "internal/goarch" "internal/goexperiment" "unsafe" ) @@ -167,7 +168,7 @@ func (a *abiSeq) addRcvr(rcvr *rtype) (*abiStep, bool) { a.valueStart = append(a.valueStart, len(a.steps)) var ok, ptr bool if ifaceIndir(rcvr) || rcvr.pointers() { - ok = a.assignIntN(0, ptrSize, 1, 0b1) + ok = a.assignIntN(0, goarch.PtrSize, 1, 0b1) ptr = true } else { // TODO(mknyszek): Is this case even possible? @@ -176,11 +177,11 @@ func (a *abiSeq) addRcvr(rcvr *rtype) (*abiStep, bool) { // in the reflect package which only conditionally added // a pointer bit to the reflect.(Value).Call stack frame's // GC bitmap. - ok = a.assignIntN(0, ptrSize, 1, 0b0) + ok = a.assignIntN(0, goarch.PtrSize, 1, 0b0) ptr = false } if !ok { - a.stackAssign(ptrSize, ptrSize) + a.stackAssign(goarch.PtrSize, goarch.PtrSize) return &a.steps[len(a.steps)-1], ptr } return nil, ptr @@ -202,7 +203,7 @@ func (a *abiSeq) regAssign(t *rtype, offset uintptr) bool { case Bool, Int, Uint, Int8, Uint8, Int16, Uint16, Int32, Uint32, Uintptr: return a.assignIntN(offset, t.size, 1, 0b0) case Int64, Uint64: - switch ptrSize { + switch goarch.PtrSize { case 4: return a.assignIntN(offset, 4, 2, 0b0) case 8: @@ -215,11 +216,11 @@ func (a *abiSeq) regAssign(t *rtype, offset uintptr) bool { case Complex128: return a.assignFloatN(offset, 8, 2) case String: - return a.assignIntN(offset, ptrSize, 2, 0b01) + return a.assignIntN(offset, goarch.PtrSize, 2, 0b01) case Interface: - return a.assignIntN(offset, ptrSize, 2, 0b10) + return a.assignIntN(offset, goarch.PtrSize, 2, 0b10) case Slice: - return a.assignIntN(offset, ptrSize, 3, 0b001) + return a.assignIntN(offset, goarch.PtrSize, 3, 0b001) case Array: tt := (*arrayType)(unsafe.Pointer(t)) switch tt.len { @@ -262,7 +263,7 @@ func (a *abiSeq) assignIntN(offset, size uintptr, n int, ptrMap uint8) bool { if n > 8 || n < 0 { panic("invalid n") } - if ptrMap != 0 && size != ptrSize { + if ptrMap != 0 && size != goarch.PtrSize { panic("non-empty pointer map passed for non-pointer-size values") } if a.iregs+n > intArgRegs { @@ -413,7 +414,7 @@ func newAbiDesc(t *funcType, rcvr *rtype) abiDesc { stackPtrs.append(0) } } else { - spill += ptrSize + spill += goarch.PtrSize } } for i, arg := range t.in() { @@ -430,12 +431,12 @@ func newAbiDesc(t *funcType, rcvr *rtype) abiDesc { } } } - spill = align(spill, ptrSize) + spill = align(spill, goarch.PtrSize) // From the input parameters alone, we now know // the stackCallArgsSize and retOffset. stackCallArgsSize := in.stackBytes - retOffset := align(in.stackBytes, ptrSize) + retOffset := align(in.stackBytes, goarch.PtrSize) // Compute the stack frame pointer bitmap and register // pointer bitmap for return values. diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index 0db5e13217..e3faa31c1f 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -10,6 +10,7 @@ import ( "flag" "fmt" "go/token" + "internal/goarch" "io" "math" "math/rand" @@ -6457,10 +6458,10 @@ func clobber() { func TestFuncLayout(t *testing.T) { align := func(x uintptr) uintptr { - return (x + PtrSize - 1) &^ (PtrSize - 1) + return (x + goarch.PtrSize - 1) &^ (goarch.PtrSize - 1) } var r []byte - if PtrSize == 4 { + if goarch.PtrSize == 4 { r = []byte{0, 0, 0, 1} } else { r = []byte{0, 0, 1} @@ -6481,56 +6482,56 @@ func TestFuncLayout(t *testing.T) { tests := []test{ { typ: ValueOf(func(a, b string) string { return "" }).Type(), - size: 6 * PtrSize, - argsize: 4 * PtrSize, - retOffset: 4 * PtrSize, + size: 6 * goarch.PtrSize, + argsize: 4 * goarch.PtrSize, + retOffset: 4 * goarch.PtrSize, stack: []byte{1, 0, 1, 0, 1}, gc: []byte{1, 0, 1, 0, 1}, }, { typ: ValueOf(func(a, b, c uint32, p *byte, d uint16) {}).Type(), - size: align(align(3*4) + PtrSize + 2), - argsize: align(3*4) + PtrSize + 2, - retOffset: align(align(3*4) + PtrSize + 2), + size: align(align(3*4) + goarch.PtrSize + 2), + argsize: align(3*4) + goarch.PtrSize + 2, + retOffset: align(align(3*4) + goarch.PtrSize + 2), stack: r, gc: r, }, { typ: ValueOf(func(a map[int]int, b uintptr, c interface{}) {}).Type(), - size: 4 * PtrSize, - argsize: 4 * PtrSize, - retOffset: 4 * PtrSize, + size: 4 * goarch.PtrSize, + argsize: 4 * goarch.PtrSize, + retOffset: 4 * goarch.PtrSize, stack: []byte{1, 0, 1, 1}, gc: []byte{1, 0, 1, 1}, }, { typ: ValueOf(func(a S) {}).Type(), - size: 4 * PtrSize, - argsize: 4 * PtrSize, - retOffset: 4 * PtrSize, + size: 4 * goarch.PtrSize, + argsize: 4 * goarch.PtrSize, + retOffset: 4 * goarch.PtrSize, stack: []byte{0, 0, 1, 1}, gc: []byte{0, 0, 1, 1}, }, { rcvr: ValueOf((*byte)(nil)).Type(), typ: ValueOf(func(a uintptr, b *int) {}).Type(), - size: 3 * PtrSize, - argsize: 3 * PtrSize, - retOffset: 3 * PtrSize, + size: 3 * goarch.PtrSize, + argsize: 3 * goarch.PtrSize, + retOffset: 3 * goarch.PtrSize, stack: []byte{1, 0, 1}, gc: []byte{1, 0, 1}, }, { typ: ValueOf(func(a uintptr) {}).Type(), - size: PtrSize, - argsize: PtrSize, - retOffset: PtrSize, + size: goarch.PtrSize, + argsize: goarch.PtrSize, + retOffset: goarch.PtrSize, stack: []byte{}, gc: []byte{}, }, { typ: ValueOf(func() uintptr { return 0 }).Type(), - size: PtrSize, + size: goarch.PtrSize, argsize: 0, retOffset: 0, stack: []byte{}, @@ -6539,9 +6540,9 @@ func TestFuncLayout(t *testing.T) { { rcvr: ValueOf(uintptr(0)).Type(), typ: ValueOf(func(a uintptr) {}).Type(), - size: 2 * PtrSize, - argsize: 2 * PtrSize, - retOffset: 2 * PtrSize, + size: 2 * goarch.PtrSize, + argsize: 2 * goarch.PtrSize, + retOffset: 2 * goarch.PtrSize, stack: []byte{1}, gc: []byte{1}, // Note: this one is tricky, as the receiver is not a pointer. But we @@ -6747,7 +6748,7 @@ func TestGCBits(t *testing.T) { verifyGCBits(t, TypeOf(([][10000]Xscalar)(nil)), lit(1)) verifyGCBits(t, SliceOf(ArrayOf(10000, Tscalar)), lit(1)) - hdr := make([]byte, 8/PtrSize) + hdr := make([]byte, 8/goarch.PtrSize) verifyMapBucket := func(t *testing.T, k, e Type, m interface{}, want []byte) { verifyGCBits(t, MapBucketOf(k, e), want) @@ -6763,7 +6764,7 @@ func TestGCBits(t *testing.T) { join(hdr, rep(8, lit(0, 1)), rep(8, lit(1)), lit(1))) verifyMapBucket(t, Tint64, Tptr, map[int64]Xptr(nil), - join(hdr, rep(8, rep(8/PtrSize, lit(0))), rep(8, lit(1)), lit(1))) + join(hdr, rep(8, rep(8/goarch.PtrSize, lit(0))), rep(8, lit(1)), lit(1))) verifyMapBucket(t, Tscalar, Tscalar, map[Xscalar]Xscalar(nil), @@ -6773,20 +6774,20 @@ func TestGCBits(t *testing.T) { map[[2]Xscalarptr][3]Xptrscalar(nil), join(hdr, rep(8*2, lit(0, 1)), rep(8*3, lit(1, 0)), lit(1))) verifyMapBucket(t, - ArrayOf(64/PtrSize, Tscalarptr), ArrayOf(64/PtrSize, Tptrscalar), - map[[64 / PtrSize]Xscalarptr][64 / PtrSize]Xptrscalar(nil), - join(hdr, rep(8*64/PtrSize, lit(0, 1)), rep(8*64/PtrSize, lit(1, 0)), lit(1))) + ArrayOf(64/goarch.PtrSize, Tscalarptr), ArrayOf(64/goarch.PtrSize, Tptrscalar), + map[[64 / goarch.PtrSize]Xscalarptr][64 / goarch.PtrSize]Xptrscalar(nil), + join(hdr, rep(8*64/goarch.PtrSize, lit(0, 1)), rep(8*64/goarch.PtrSize, lit(1, 0)), lit(1))) verifyMapBucket(t, - ArrayOf(64/PtrSize+1, Tscalarptr), ArrayOf(64/PtrSize, Tptrscalar), - map[[64/PtrSize + 1]Xscalarptr][64 / PtrSize]Xptrscalar(nil), - join(hdr, rep(8, lit(1)), rep(8*64/PtrSize, lit(1, 0)), lit(1))) + ArrayOf(64/goarch.PtrSize+1, Tscalarptr), ArrayOf(64/goarch.PtrSize, Tptrscalar), + map[[64/goarch.PtrSize + 1]Xscalarptr][64 / goarch.PtrSize]Xptrscalar(nil), + join(hdr, rep(8, lit(1)), rep(8*64/goarch.PtrSize, lit(1, 0)), lit(1))) verifyMapBucket(t, - ArrayOf(64/PtrSize, Tscalarptr), ArrayOf(64/PtrSize+1, Tptrscalar), - map[[64 / PtrSize]Xscalarptr][64/PtrSize + 1]Xptrscalar(nil), - join(hdr, rep(8*64/PtrSize, lit(0, 1)), rep(8, lit(1)), lit(1))) + ArrayOf(64/goarch.PtrSize, Tscalarptr), ArrayOf(64/goarch.PtrSize+1, Tptrscalar), + map[[64 / goarch.PtrSize]Xscalarptr][64/goarch.PtrSize + 1]Xptrscalar(nil), + join(hdr, rep(8*64/goarch.PtrSize, lit(0, 1)), rep(8, lit(1)), lit(1))) verifyMapBucket(t, - ArrayOf(64/PtrSize+1, Tscalarptr), ArrayOf(64/PtrSize+1, Tptrscalar), - map[[64/PtrSize + 1]Xscalarptr][64/PtrSize + 1]Xptrscalar(nil), + ArrayOf(64/goarch.PtrSize+1, Tscalarptr), ArrayOf(64/goarch.PtrSize+1, Tptrscalar), + map[[64/goarch.PtrSize + 1]Xscalarptr][64/goarch.PtrSize + 1]Xptrscalar(nil), join(hdr, rep(8, lit(1)), rep(8, lit(1)), lit(1))) } diff --git a/src/reflect/export_test.go b/src/reflect/export_test.go index b6830a9802..e775eaf135 100644 --- a/src/reflect/export_test.go +++ b/src/reflect/export_test.go @@ -5,6 +5,7 @@ package reflect import ( + "internal/goarch" "sync" "unsafe" ) @@ -22,7 +23,7 @@ func IsRO(v Value) bool { var CallGC = &callGC -const PtrSize = ptrSize +const PtrSize = goarch.PtrSize // FuncLayout calls funcLayout and returns a subset of the results for testing. // @@ -65,7 +66,7 @@ func FuncLayout(t Type, rcvr Type) (frametype Type, argSize, retOffset uintptr, // Expand frame type's GC bitmap into byte-map. ptrs = ft.ptrdata != 0 if ptrs { - nptrs := ft.ptrdata / ptrSize + nptrs := ft.ptrdata / goarch.PtrSize gcdata := ft.gcSlice(0, (nptrs+7)/8) for i := uintptr(0); i < nptrs; i++ { gc = append(gc, gcdata[i/8]>>(i%8)&1) diff --git a/src/reflect/swapper.go b/src/reflect/swapper.go index 0cf40666b1..67b7fbe59b 100644 --- a/src/reflect/swapper.go +++ b/src/reflect/swapper.go @@ -5,6 +5,7 @@ package reflect import ( + "internal/goarch" "internal/unsafeheader" "unsafe" ) @@ -36,7 +37,7 @@ func Swapper(slice interface{}) func(i, j int) { // Some common & small cases, without using memmove: if hasPtr { - if size == ptrSize { + if size == goarch.PtrSize { ps := *(*[]unsafe.Pointer)(v.ptr) return func(i, j int) { ps[i], ps[j] = ps[j], ps[i] } } diff --git a/src/reflect/type.go b/src/reflect/type.go index df863ae106..e119354af4 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -16,6 +16,7 @@ package reflect import ( + "internal/goarch" "internal/unsafeheader" "strconv" "sync" @@ -1924,13 +1925,13 @@ func MapOf(key, elem Type) Type { } mt.flags = 0 if ktyp.size > maxKeySize { - mt.keysize = uint8(ptrSize) + mt.keysize = uint8(goarch.PtrSize) mt.flags |= 1 // indirect key } else { mt.keysize = uint8(ktyp.size) } if etyp.size > maxValSize { - mt.valuesize = uint8(ptrSize) + mt.valuesize = uint8(goarch.PtrSize) mt.flags |= 2 // indirect value } else { mt.valuesize = uint8(etyp.size) @@ -2231,31 +2232,31 @@ func bucketOf(ktyp, etyp *rtype) *rtype { var ptrdata uintptr var overflowPad uintptr - size := bucketSize*(1+ktyp.size+etyp.size) + overflowPad + ptrSize + size := bucketSize*(1+ktyp.size+etyp.size) + overflowPad + goarch.PtrSize if size&uintptr(ktyp.align-1) != 0 || size&uintptr(etyp.align-1) != 0 { panic("reflect: bad size computation in MapOf") } if ktyp.ptrdata != 0 || etyp.ptrdata != 0 { - nptr := (bucketSize*(1+ktyp.size+etyp.size) + ptrSize) / ptrSize + nptr := (bucketSize*(1+ktyp.size+etyp.size) + goarch.PtrSize) / goarch.PtrSize mask := make([]byte, (nptr+7)/8) - base := bucketSize / ptrSize + base := bucketSize / goarch.PtrSize if ktyp.ptrdata != 0 { emitGCMask(mask, base, ktyp, bucketSize) } - base += bucketSize * ktyp.size / ptrSize + base += bucketSize * ktyp.size / goarch.PtrSize if etyp.ptrdata != 0 { emitGCMask(mask, base, etyp, bucketSize) } - base += bucketSize * etyp.size / ptrSize - base += overflowPad / ptrSize + base += bucketSize * etyp.size / goarch.PtrSize + base += overflowPad / goarch.PtrSize word := base mask[word/8] |= 1 << (word % 8) gcdata = &mask[0] - ptrdata = (word + 1) * ptrSize + ptrdata = (word + 1) * goarch.PtrSize // overflow word must be last if ptrdata != size { @@ -2264,7 +2265,7 @@ func bucketOf(ktyp, etyp *rtype) *rtype { } b := &rtype{ - align: ptrSize, + align: goarch.PtrSize, size: size, kind: uint8(Struct), ptrdata: ptrdata, @@ -2288,8 +2289,8 @@ func emitGCMask(out []byte, base uintptr, typ *rtype, n uintptr) { if typ.kind&kindGCProg != 0 { panic("reflect: unexpected GC program") } - ptrs := typ.ptrdata / ptrSize - words := typ.size / ptrSize + ptrs := typ.ptrdata / goarch.PtrSize + words := typ.size / goarch.PtrSize mask := typ.gcSlice(0, (ptrs+7)/8) for j := uintptr(0); j < ptrs; j++ { if (mask[j/8]>>(j%8))&1 != 0 { @@ -2312,7 +2313,7 @@ func appendGCProg(dst []byte, typ *rtype) []byte { } // Element is small with pointer mask; use as literal bits. - ptrs := typ.ptrdata / ptrSize + ptrs := typ.ptrdata / goarch.PtrSize mask := typ.gcSlice(0, (ptrs+7)/8) // Emit 120-bit chunks of full bytes (max is 127 but we avoid using partial bytes). @@ -2759,7 +2760,7 @@ func StructOf(fields []StructField) Type { } // Pad to start of this field with zeros. if ft.offset() > off { - n := (ft.offset() - off) / ptrSize + n := (ft.offset() - off) / goarch.PtrSize prog = append(prog, 0x01, 0x00) // emit a 0 bit if n > 1 { prog = append(prog, 0x81) // repeat previous bit @@ -2936,11 +2937,11 @@ func ArrayOf(length int, elem Type) Type { array.gcdata = typ.gcdata array.ptrdata = typ.ptrdata - case typ.kind&kindGCProg == 0 && array.size <= maxPtrmaskBytes*8*ptrSize: + case typ.kind&kindGCProg == 0 && array.size <= maxPtrmaskBytes*8*goarch.PtrSize: // Element is small with pointer mask; array is still small. // Create direct pointer mask by turning each 1 bit in elem // into length 1 bits in larger mask. - mask := make([]byte, (array.ptrdata/ptrSize+7)/8) + mask := make([]byte, (array.ptrdata/goarch.PtrSize+7)/8) emitGCMask(mask, 0, typ, array.len) array.gcdata = &mask[0] @@ -2950,8 +2951,8 @@ func ArrayOf(length int, elem Type) Type { prog := []byte{0, 0, 0, 0} // will be length of prog prog = appendGCProg(prog, typ) // Pad from ptrdata to size. - elemPtrs := typ.ptrdata / ptrSize - elemWords := typ.size / ptrSize + elemPtrs := typ.ptrdata / goarch.PtrSize + elemWords := typ.size / goarch.PtrSize if elemPtrs < elemWords { // Emit literal 0 bit, then repeat as needed. prog = append(prog, 0x01, 0x00) @@ -3063,13 +3064,13 @@ func funcLayout(t *funcType, rcvr *rtype) (frametype *rtype, framePool *sync.Poo // build dummy rtype holding gc program x := &rtype{ - align: ptrSize, + align: goarch.PtrSize, // Don't add spill space here; it's only necessary in // reflectcall's frame, not in the allocated frame. // TODO(mknyszek): Remove this comment when register // spill space in the frame is no longer required. - size: align(abi.retOffset+abi.ret.stackBytes, ptrSize), - ptrdata: uintptr(abi.stackPtrs.n) * ptrSize, + size: align(abi.retOffset+abi.ret.stackBytes, goarch.PtrSize), + ptrdata: uintptr(abi.stackPtrs.n) * goarch.PtrSize, } if abi.stackPtrs.n > 0 { x.gcdata = &abi.stackPtrs.data[0] @@ -3124,14 +3125,14 @@ func addTypeBits(bv *bitVector, offset uintptr, t *rtype) { switch Kind(t.kind & kindMask) { case Chan, Func, Map, Ptr, Slice, String, UnsafePointer: // 1 pointer at start of representation - for bv.n < uint32(offset/uintptr(ptrSize)) { + for bv.n < uint32(offset/uintptr(goarch.PtrSize)) { bv.append(0) } bv.append(1) case Interface: // 2 pointers - for bv.n < uint32(offset/uintptr(ptrSize)) { + for bv.n < uint32(offset/uintptr(goarch.PtrSize)) { bv.append(0) } bv.append(1) diff --git a/src/reflect/value.go b/src/reflect/value.go index 6ba6202a1a..e5ad4d5cd5 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -6,6 +6,7 @@ package reflect import ( "internal/abi" + "internal/goarch" "internal/itoa" "internal/unsafeheader" "math" @@ -94,7 +95,7 @@ func (f flag) ro() flag { // v.Kind() must be Ptr, Map, Chan, Func, or UnsafePointer // if v.Kind() == Ptr, the base type must not be go:notinheap. func (v Value) pointer() unsafe.Pointer { - if v.typ.size != ptrSize || !v.typ.pointers() { + if v.typ.size != goarch.PtrSize || !v.typ.pointers() { panic("can't call pointer on a non-pointer Value") } if v.flag&flagIndir != 0 { @@ -533,7 +534,7 @@ func (v Value) call(op string, in []Value) []Value { } // TODO(mknyszek): Remove this when we no longer have // caller reserved spill space. - frameSize = align(frameSize, ptrSize) + frameSize = align(frameSize, goarch.PtrSize) frameSize += abi.spill // Mark pointers in registers for the return path. @@ -1043,7 +1044,7 @@ func callMethod(ctxt *methodValue, frame unsafe.Pointer, retValid *bool, regs *a methodFrameSize := methodFrameType.size // TODO(mknyszek): Remove this when we no longer have // caller reserved spill space. - methodFrameSize = align(methodFrameSize, ptrSize) + methodFrameSize = align(methodFrameSize, goarch.PtrSize) methodFrameSize += methodABI.spill // Mark pointers in registers for the return path. -- GitLab From bfd9b63f125aebfbe2de3b6fa0b329cae2120b20 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Wed, 16 Jun 2021 23:26:39 +0000 Subject: [PATCH 0310/2500] [dev.typeparams] reflect: delete unused ptrSize and PtrSize Change-Id: I522263eb5112b78639340b83d92e80a13f738bd4 Reviewed-on: https://go-review.googlesource.com/c/go/+/328811 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/reflect/export_test.go | 2 -- src/reflect/value.go | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/reflect/export_test.go b/src/reflect/export_test.go index e775eaf135..01749e30d8 100644 --- a/src/reflect/export_test.go +++ b/src/reflect/export_test.go @@ -23,8 +23,6 @@ func IsRO(v Value) bool { var CallGC = &callGC -const PtrSize = goarch.PtrSize - // FuncLayout calls funcLayout and returns a subset of the results for testing. // // Bitmaps like stack, gc, inReg, and outReg are expanded such that each bit diff --git a/src/reflect/value.go b/src/reflect/value.go index e5ad4d5cd5..d8a0b5245e 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -14,8 +14,6 @@ import ( "unsafe" ) -const ptrSize = 4 << (^uintptr(0) >> 63) // unsafe.Sizeof(uintptr(0)) but an ideal const - // Value is the reflection interface to a Go value. // // Not all methods apply to all kinds of values. Restrictions, -- GitLab From 890a8407a9c30c0a1d08ff80100e4f53da7df17a Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Wed, 16 Jun 2021 22:07:16 +0000 Subject: [PATCH 0311/2500] [dev.typeparams] internal/reflectlite: use goarch.PtrSize instead of the duplicated ptrSize [generated] [git-generate] cd src/internal/reflectlite gofmt -w -r "ptrSize -> goarch.PtrSize" . goimports -w *.go Change-Id: I6a55f2aa035ed863785856ddd4fcc519dec15ac9 Reviewed-on: https://go-review.googlesource.com/c/go/+/328347 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/internal/reflectlite/swapper.go | 3 ++- src/internal/reflectlite/value.go | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/internal/reflectlite/swapper.go b/src/internal/reflectlite/swapper.go index 6330ab2d34..ac081d49bb 100644 --- a/src/internal/reflectlite/swapper.go +++ b/src/internal/reflectlite/swapper.go @@ -5,6 +5,7 @@ package reflectlite import ( + "internal/goarch" "internal/unsafeheader" "unsafe" ) @@ -36,7 +37,7 @@ func Swapper(slice interface{}) func(i, j int) { // Some common & small cases, without using memmove: if hasPtr { - if size == ptrSize { + if size == goarch.PtrSize { ps := *(*[]unsafe.Pointer)(v.ptr) return func(i, j int) { ps[i], ps[j] = ps[j], ps[i] } } diff --git a/src/internal/reflectlite/value.go b/src/internal/reflectlite/value.go index 0365eeeabf..86dfcb5c36 100644 --- a/src/internal/reflectlite/value.go +++ b/src/internal/reflectlite/value.go @@ -5,6 +5,7 @@ package reflectlite import ( + "internal/goarch" "internal/unsafeheader" "runtime" "unsafe" @@ -90,7 +91,7 @@ func (f flag) ro() flag { // pointer returns the underlying pointer represented by v. // v.Kind() must be Ptr, Map, Chan, Func, or UnsafePointer func (v Value) pointer() unsafe.Pointer { - if v.typ.size != ptrSize || !v.typ.pointers() { + if v.typ.size != goarch.PtrSize || !v.typ.pointers() { panic("can't call pointer on a non-pointer Value") } if v.flag&flagIndir != 0 { -- GitLab From 9f50d9a0b41bc0618272535f84c3e518e74f2fea Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Wed, 16 Jun 2021 23:29:40 +0000 Subject: [PATCH 0312/2500] [dev.typeparams] internal/reflectlite: remove unused ptrSize Change-Id: Ia0da5e5d1e8d20327690cb53c9df067401f3428c Reviewed-on: https://go-review.googlesource.com/c/go/+/328812 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/internal/reflectlite/value.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/internal/reflectlite/value.go b/src/internal/reflectlite/value.go index 86dfcb5c36..136273842c 100644 --- a/src/internal/reflectlite/value.go +++ b/src/internal/reflectlite/value.go @@ -11,8 +11,6 @@ import ( "unsafe" ) -const ptrSize = 4 << (^uintptr(0) >> 63) // unsafe.Sizeof(uintptr(0)) but an ideal const - // Value is the reflection interface to a Go value. // // Not all methods apply to all kinds of values. Restrictions, -- GitLab From fb84d213a8551526913647b7dea6103233f550db Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Wed, 16 Jun 2021 19:08:52 +0000 Subject: [PATCH 0313/2500] [dev.typeparams] reflect: support big endian architectures in callMethod Currently, callMethod has some ABI translation code that is not agnostic of endianness. This change rectifies that by adding a method to internal/abi.RegArgs for safely returning an offset into a register slot that's endianness-dependent. No tests for this because it's just best-effort. There's no actual way to test this because we don't support a register ABI on any big endian architectures yet. Change-Id: Ic68d9ee1bfdea0fc2992d467d749e2b083e92de3 Reviewed-on: https://go-review.googlesource.com/c/go/+/328348 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/go/build/deps_test.go | 4 ++-- src/internal/abi/abi.go | 45 ++++++++++++++++++++++++++++++++++++++- src/reflect/value.go | 11 ++++------ 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index b440f7d235..80f8e1a00d 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -77,8 +77,8 @@ var depsRules = ` unicode/utf8, unicode/utf16, unicode, unsafe; - # These packages depend only on unsafe. - unsafe + # These packages depend only on internal/goarch and unsafe. + internal/goarch, unsafe < internal/abi; # RUNTIME is the core runtime group of packages, all of them very light-weight. diff --git a/src/internal/abi/abi.go b/src/internal/abi/abi.go index aaff9cece3..eadff248d9 100644 --- a/src/internal/abi/abi.go +++ b/src/internal/abi/abi.go @@ -4,7 +4,10 @@ package abi -import "unsafe" +import ( + "internal/goarch" + "unsafe" +) // RegArgs is a struct that has space for each argument // and return value register on the current architecture. @@ -33,6 +36,46 @@ type RegArgs struct { ReturnIsPtr IntArgRegBitmap } +// IntRegArgAddr returns a pointer inside of r.Ints[reg] that is appropriately +// offset for an argument of size argSize. +// +// argSize must be non-zero, fit in a register, and a power-of-two. +// +// This method is a helper for dealing with the endianness of different CPU +// architectures, since sub-word-sized arguments in big endian architectures +// need to be "aligned" to the upper edge of the register to be interpreted +// by the CPU correctly. +func (r *RegArgs) IntRegArgAddr(reg int, argSize uintptr) unsafe.Pointer { + if argSize > goarch.PtrSize || argSize == 0 || argSize&(argSize-1) != 0 { + panic("invalid argSize") + } + offset := uintptr(0) + if goarch.BigEndian { + offset = goarch.PtrSize - argSize + } + return unsafe.Pointer(uintptr(unsafe.Pointer(&r.Ints[reg])) + offset) +} + +// FloatRegArgAddr returns a pointer inside of r.Floats[reg] that is appropriately +// offset for an argument of size argSize. +// +// argSize must be non-zero, fit in a register, and a power-of-two. +// +// This method is a helper for dealing with the endianness of different CPU +// architectures, since sub-word-sized arguments in big endian architectures +// need to be "aligned" to the upper edge of the register to be interpreted +// by the CPU correctly. +func (r *RegArgs) FloatRegArgAddr(reg int, argSize uintptr) unsafe.Pointer { + if argSize > EffectiveFloatRegSize || argSize == 0 || argSize&(argSize-1) != 0 { + panic("invalid argSize") + } + offset := uintptr(0) + if goarch.BigEndian { + offset = EffectiveFloatRegSize - argSize + } + return unsafe.Pointer(uintptr(unsafe.Pointer(&r.Floats[reg])) + offset) +} + // IntArgRegBitmap is a bitmap large enough to hold one bit per // integer argument/return register. type IntArgRegBitmap [(IntArgRegs + 7) / 8]uint8 diff --git a/src/reflect/value.go b/src/reflect/value.go index d8a0b5245e..4341fd3f90 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -957,9 +957,6 @@ func callMethod(ctxt *methodValue, frame unsafe.Pointer, retValid *bool, regs *a // 2. Stack -> registers translation. // 3. Registers -> stack translation. // 4. Registers -> registers translation. - // TODO(mknyszek): Cases 2 and 3 below only work on little endian - // architectures. This is OK for now, but this needs to be fixed - // before supporting the register ABI on big endian architectures. // If the value ABI passes the value on the stack, // then the method ABI does too, because it has strictly @@ -985,9 +982,9 @@ func callMethod(ctxt *methodValue, frame unsafe.Pointer, retValid *bool, regs *a methodRegs.Ptrs[mStep.ireg] = *(*unsafe.Pointer)(from) fallthrough // We need to make sure this ends up in Ints, too. case abiStepIntReg: - memmove(unsafe.Pointer(&methodRegs.Ints[mStep.ireg]), from, mStep.size) + memmove(methodRegs.IntRegArgAddr(mStep.ireg, mStep.size), from, mStep.size) case abiStepFloatReg: - memmove(unsafe.Pointer(&methodRegs.Floats[mStep.freg]), from, mStep.size) + memmove(methodRegs.FloatRegArgAddr(mStep.freg, mStep.size), from, mStep.size) default: panic("unexpected method step") } @@ -1003,9 +1000,9 @@ func callMethod(ctxt *methodValue, frame unsafe.Pointer, retValid *bool, regs *a // Do the pointer copy directly so we get a write barrier. *(*unsafe.Pointer)(to) = valueRegs.Ptrs[vStep.ireg] case abiStepIntReg: - memmove(to, unsafe.Pointer(&valueRegs.Ints[vStep.ireg]), vStep.size) + memmove(to, valueRegs.IntRegArgAddr(vStep.ireg, vStep.size), vStep.size) case abiStepFloatReg: - memmove(to, unsafe.Pointer(&valueRegs.Floats[vStep.freg]), vStep.size) + memmove(to, valueRegs.FloatRegArgAddr(vStep.freg, vStep.size), vStep.size) default: panic("unexpected value step") } -- GitLab From feec53c4e5641f6a9f89ba9dcd8d89d84ea2717c Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 17 Jun 2021 15:36:23 -0700 Subject: [PATCH 0314/2500] [dev.typeparams] cmd/compile: skip types2 GC test during bootstrapping Unified includes a check to make sure that types2 memory has been garbage collected, but it relies on precise finalization, which we provide (for dynamically allocated objects, at least) but isn't guaranteed by the Go spec. In particular, Go 1.4 doesn't provide this. The check is strictly unnecessary and only exists to make sure we don't regress and start holding onto types2 memory accidentally. So just disable the check during bootstrap builds. Change-Id: Ie54fe53b2edba02c0b0b1e5ae39d81be8a0ace8d Reviewed-on: https://go-review.googlesource.com/c/go/+/329269 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/base/bootstrap_false.go | 11 +++++++++++ src/cmd/compile/internal/base/bootstrap_true.go | 11 +++++++++++ src/cmd/compile/internal/noder/unified.go | 10 ++++++++++ 3 files changed, 32 insertions(+) create mode 100644 src/cmd/compile/internal/base/bootstrap_false.go create mode 100644 src/cmd/compile/internal/base/bootstrap_true.go diff --git a/src/cmd/compile/internal/base/bootstrap_false.go b/src/cmd/compile/internal/base/bootstrap_false.go new file mode 100644 index 0000000000..de86644527 --- /dev/null +++ b/src/cmd/compile/internal/base/bootstrap_false.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !compiler_bootstrap + +package base + +// CompilerBootstrap reports whether the current compiler binary was +// built with -tags=compiler_bootstrap. +const CompilerBootstrap = false diff --git a/src/cmd/compile/internal/base/bootstrap_true.go b/src/cmd/compile/internal/base/bootstrap_true.go new file mode 100644 index 0000000000..81a17e1f6e --- /dev/null +++ b/src/cmd/compile/internal/base/bootstrap_true.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build compiler_bootstrap + +package base + +// CompilerBootstrap reports whether the current compiler binary was +// built with -tags=compiler_bootstrap. +const CompilerBootstrap = true diff --git a/src/cmd/compile/internal/noder/unified.go b/src/cmd/compile/internal/noder/unified.go index 9a41ea9dfe..96c0916493 100644 --- a/src/cmd/compile/internal/noder/unified.go +++ b/src/cmd/compile/internal/noder/unified.go @@ -161,6 +161,16 @@ func writePkgStub(noders []*noder) string { // freePackage ensures the given package is garbage collected. func freePackage(pkg *types2.Package) { + // The GC test below relies on a precise GC that runs finalizers as + // soon as objects are unreachable. Our implementation provides + // this, but other/older implementations may not (e.g., Go 1.4 does + // not because of #22350). To avoid imposing unnecessary + // restrictions on the GOROOT_BOOTSTRAP toolchain, we skip the test + // during bootstrapping. + if base.CompilerBootstrap { + return + } + // Set a finalizer on pkg so we can detect if/when it's collected. done := make(chan struct{}) runtime.SetFinalizer(pkg, func(*types2.Package) { close(done) }) -- GitLab From 90096f445eaf78b954b9d37c47d137d4fcbd272c Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 15 Jun 2021 17:48:31 -0700 Subject: [PATCH 0315/2500] [dev.typeparams] cmd/compile/internal/syntax: convert (most) parser tests to new type set syntax Left a couple of tests with old notation so that we keep testing it while the notation is still supported. Change-Id: Ia6a3e7911af87eaccc7b06189c10f79789575a98 Reviewed-on: https://go-review.googlesource.com/c/go/+/328256 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley --- .../internal/syntax/testdata/go2/linalg.go2 | 16 ++--- .../syntax/testdata/go2/smoketest.go2 | 6 +- .../syntax/testdata/go2/typeinst2.go2 | 10 +-- .../syntax/testdata/go2/typeparams.go2 | 68 +++++++++---------- 4 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/cmd/compile/internal/syntax/testdata/go2/linalg.go2 b/src/cmd/compile/internal/syntax/testdata/go2/linalg.go2 index 0d27603a58..822d0287e7 100644 --- a/src/cmd/compile/internal/syntax/testdata/go2/linalg.go2 +++ b/src/cmd/compile/internal/syntax/testdata/go2/linalg.go2 @@ -9,10 +9,10 @@ import "math" // Numeric is type bound that matches any numeric type. // It would likely be in a constraints package in the standard library. type Numeric interface { - type int, int8, int16, int32, int64, - uint, uint8, uint16, uint32, uint64, uintptr, - float32, float64, - complex64, complex128 + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + float32 | ~float64 | + complex64 | ~complex128 } func DotProduct[T Numeric](s1, s2 []T) T { @@ -42,14 +42,14 @@ func AbsDifference[T NumericAbs[T]](a, b T) T { // OrderedNumeric is a type bound that matches numeric types that support the < operator. type OrderedNumeric interface { - type int, int8, int16, int32, int64, - uint, uint8, uint16, uint32, uint64, uintptr, - float32, float64 + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + float32 | ~float64 } // Complex is a type bound that matches the two complex types, which do not have a < operator. type Complex interface { - type complex64, complex128 + ~complex64 | ~complex128 } // OrderedAbs is a helper type that defines an Abs method for diff --git a/src/cmd/compile/internal/syntax/testdata/go2/smoketest.go2 b/src/cmd/compile/internal/syntax/testdata/go2/smoketest.go2 index e5cfba0612..42efb42527 100644 --- a/src/cmd/compile/internal/syntax/testdata/go2/smoketest.go2 +++ b/src/cmd/compile/internal/syntax/testdata/go2/smoketest.go2 @@ -46,12 +46,12 @@ type _ struct{ T[int] } // interfaces type _ interface{ m() - type int + ~int } type _ interface{ - type int, float, string - type complex128 + ~int | ~float | ~string + ~complex128 underlying(underlying underlying) underlying } diff --git a/src/cmd/compile/internal/syntax/testdata/go2/typeinst2.go2 b/src/cmd/compile/internal/syntax/testdata/go2/typeinst2.go2 index 6e2104a515..f3deb703b6 100644 --- a/src/cmd/compile/internal/syntax/testdata/go2/typeinst2.go2 +++ b/src/cmd/compile/internal/syntax/testdata/go2/typeinst2.go2 @@ -175,12 +175,12 @@ type _ interface { // Interface type lists can contain any type, incl. *Named types. // Verify that we use the underlying type to compute the operational type. type MyInt int -func add1[T interface{type MyInt}](x T) T { +func add1[T interface{ ~MyInt }](x T) T { return x + 1 } type MyString string -func double[T interface{type MyInt, MyString}](x T) T { +func double[T interface{ ~MyInt | ~MyString }](x T) T { return x + x } @@ -189,15 +189,15 @@ func double[T interface{type MyInt, MyString}](x T) T { // type lists. type E0 interface { - type int, bool, string + ~int | ~bool | ~string } type E1 interface { - type int, float64, string + ~int | ~float64 | ~string } type E2 interface { - type float64 + ~float64 } type I0 interface { diff --git a/src/cmd/compile/internal/syntax/testdata/go2/typeparams.go2 b/src/cmd/compile/internal/syntax/testdata/go2/typeparams.go2 index f78037f0f5..111f7c1004 100644 --- a/src/cmd/compile/internal/syntax/testdata/go2/typeparams.go2 +++ b/src/cmd/compile/internal/syntax/testdata/go2/typeparams.go2 @@ -48,22 +48,22 @@ func swapswap[A, B any](a A, b B) (A, B) { type F[A, B any] func(A, B) (B, A) -func min[T interface{ type int }](x, y T) T { +func min[T interface{ ~int }](x, y T) T { if x < y { return x } return y } -func _[T interface{type int, float32}](x, y T) bool { return x < y } +func _[T interface{ ~int | ~float32 }](x, y T) bool { return x < y } func _[T any](x, y T) bool { return x /* ERROR cannot compare */ < y } -func _[T interface{type int, float32, bool}](x, y T) bool { return x /* ERROR cannot compare */ < y } +func _[T interface{ ~int | ~float32 | ~bool }](x, y T) bool { return x /* ERROR cannot compare */ < y } func _[T C1[T]](x, y T) bool { return x /* ERROR cannot compare */ < y } func _[T C2[T]](x, y T) bool { return x < y } type C1[T any] interface{} -type C2[T any] interface{ type int, float32 } +type C2[T any] interface{ ~int | ~float32 } func new[T any]() *T { var x T @@ -91,40 +91,40 @@ var _ = f3[int, rune, bool](1, struct{x rune}{}, nil) // indexing func _[T any] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } -func _[T interface{ type int }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } -func _[T interface{ type string }] (x T, i int) { _ = x[i] } -func _[T interface{ type []int }] (x T, i int) { _ = x[i] } -func _[T interface{ type [10]int, *[20]int, map[string]int }] (x T, i int) { _ = x[i] } -func _[T interface{ type string, []byte }] (x T, i int) { _ = x[i] } -func _[T interface{ type []int, [1]rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } -func _[T interface{ type string, []rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } +func _[T interface{ ~int }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } +func _[T interface{ ~string }] (x T, i int) { _ = x[i] } +func _[T interface{ ~[]int }] (x T, i int) { _ = x[i] } +func _[T interface{ ~[10]int | ~*[20]int | ~map[string]int }] (x T, i int) { _ = x[i] } +func _[T interface{ ~string | ~[]byte }] (x T, i int) { _ = x[i] } +func _[T interface{ ~[]int | ~[1]rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } +func _[T interface{ ~string | ~[]rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } // slicing // TODO(gri) implement this -func _[T interface{ type string }] (x T, i, j, k int) { _ = x /* ERROR invalid operation */ [i:j:k] } +func _[T interface{ ~string }] (x T, i, j, k int) { _ = x /* ERROR invalid operation */ [i:j:k] } // len/cap built-ins func _[T any](x T) { _ = len(x /* ERROR invalid argument */ ) } -func _[T interface{ type int }](x T) { _ = len(x /* ERROR invalid argument */ ) } -func _[T interface{ type string, []byte, int }](x T) { _ = len(x /* ERROR invalid argument */ ) } -func _[T interface{ type string }](x T) { _ = len(x) } -func _[T interface{ type [10]int }](x T) { _ = len(x) } -func _[T interface{ type []byte }](x T) { _ = len(x) } -func _[T interface{ type map[int]int }](x T) { _ = len(x) } -func _[T interface{ type chan int }](x T) { _ = len(x) } -func _[T interface{ type string, []byte, chan int }](x T) { _ = len(x) } +func _[T interface{ ~int }](x T) { _ = len(x /* ERROR invalid argument */ ) } +func _[T interface{ ~string | ~[]byte | ~int }](x T) { _ = len(x /* ERROR invalid argument */ ) } +func _[T interface{ ~string }](x T) { _ = len(x) } +func _[T interface{ ~[10]int }](x T) { _ = len(x) } +func _[T interface{ ~[]byte }](x T) { _ = len(x) } +func _[T interface{ ~map[int]int }](x T) { _ = len(x) } +func _[T interface{ ~chan int }](x T) { _ = len(x) } +func _[T interface{ ~string | ~[]byte | ~chan int }](x T) { _ = len(x) } func _[T any](x T) { _ = cap(x /* ERROR invalid argument */ ) } -func _[T interface{ type int }](x T) { _ = cap(x /* ERROR invalid argument */ ) } -func _[T interface{ type string, []byte, int }](x T) { _ = cap(x /* ERROR invalid argument */ ) } -func _[T interface{ type string }](x T) { _ = cap(x /* ERROR invalid argument */ ) } -func _[T interface{ type [10]int }](x T) { _ = cap(x) } -func _[T interface{ type []byte }](x T) { _ = cap(x) } -func _[T interface{ type map[int]int }](x T) { _ = cap(x /* ERROR invalid argument */ ) } -func _[T interface{ type chan int }](x T) { _ = cap(x) } -func _[T interface{ type []byte, chan int }](x T) { _ = cap(x) } +func _[T interface{ ~int }](x T) { _ = cap(x /* ERROR invalid argument */ ) } +func _[T interface{ ~string | ~[]byte | ~int }](x T) { _ = cap(x /* ERROR invalid argument */ ) } +func _[T interface{ ~string }](x T) { _ = cap(x /* ERROR invalid argument */ ) } +func _[T interface{ ~[10]int }](x T) { _ = cap(x) } +func _[T interface{ ~[]byte }](x T) { _ = cap(x) } +func _[T interface{ ~map[int]int }](x T) { _ = cap(x /* ERROR invalid argument */ ) } +func _[T interface{ ~chan int }](x T) { _ = cap(x) } +func _[T interface{ ~[]byte | ~chan int }](x T) { _ = cap(x) } // range iteration @@ -132,7 +132,7 @@ func _[T interface{}](x T) { for range x /* ERROR cannot range */ {} } -func _[T interface{ type string, []string }](x T) { +func _[T interface{ ~string | ~[]string }](x T) { for range x {} for i := range x { _ = i } for i, _ := range x { _ = i } @@ -144,23 +144,23 @@ func _[T interface{ type string, []string }](x T) { } -func _[T interface{ type string, []rune, map[int]rune }](x T) { +func _[T interface{ ~string | ~[]rune | ~map[int]rune }](x T) { for _, e := range x { _ = e } for i, e := range x { _ = i; _ = e } } -func _[T interface{ type string, []rune, map[string]rune }](x T) { +func _[T interface{ ~string | ~[]rune | ~map[string]rune }](x T) { for _, e := range x { _ = e } for i, e := range x /* ERROR must have the same key type */ { _ = e } } -func _[T interface{ type string, chan int }](x T) { +func _[T interface{ ~string | ~chan int }](x T) { for range x {} for i := range x { _ = i } for i, _ := range x { _ = i } // TODO(gri) should get an error here: channels only return one value } -func _[T interface{ type string, chan<-int }](x T) { +func _[T interface{ ~string | ~chan<-int }](x T) { for i := range x /* ERROR send-only channel */ { _ = i } } @@ -388,7 +388,7 @@ func _[T any](x T) { } } -func _[T interface{type int}](x T) { +func _[T interface{ ~int }](x T) { _ = x /* ERROR not an interface */ .(int) switch x /* ERROR not an interface */ .(type) { } -- GitLab From 2a7900762c24a4b04d0d51c833e22bc319d0234e Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 17 Jun 2021 10:14:07 +0700 Subject: [PATCH 0316/2500] [dev.typeparams] go/types: report better error for invalid untyped operation This is port of CL 328053 for types2 to go/type. The change is identical, but for some tweaks to the error positions in tests. Updates #46749 Change-Id: I8d34c5b1669e59e4ec7d91f81dcf655b2bfd89a5 Reviewed-on: https://go-review.googlesource.com/c/go/+/328869 Trust: Cuong Manh Le Trust: Robert Griesemer Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Robert Findley Reviewed-by: Robert Griesemer --- src/go/types/errorcodes.go | 2 +- src/go/types/expr.go | 28 +++++++++++++++++++------- src/go/types/testdata/check/const0.src | 2 +- src/go/types/testdata/check/decls1.src | 2 +- src/go/types/testdata/check/expr1.src | 4 ++-- src/go/types/testdata/check/expr2.src | 2 +- src/go/types/testdata/check/expr3.src | 2 +- src/go/types/testdata/check/stmt0.src | 12 +++++------ 8 files changed, 34 insertions(+), 20 deletions(-) diff --git a/src/go/types/errorcodes.go b/src/go/types/errorcodes.go index 2afb6a383c..bcc850f753 100644 --- a/src/go/types/errorcodes.go +++ b/src/go/types/errorcodes.go @@ -875,7 +875,7 @@ const ( // context in which it is used. // // Example: - // var _ = 1 + "" + // var _ = 1 + nil _InvalidUntypedConversion // _BadOffsetofSyntax occurs when unsafe.Offsetof is called with an argument diff --git a/src/go/types/expr.go b/src/go/types/expr.go index b7cc6e8ae7..402d96f66a 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -927,14 +927,28 @@ func (check *Checker) binary(x *operand, e ast.Expr, lhs, rhs ast.Expr, op token return } - check.convertUntyped(x, y.typ) - if x.mode == invalid { - return + canMix := func(x, y *operand) bool { + if IsInterface(x.typ) || IsInterface(y.typ) { + return true + } + if isBoolean(x.typ) != isBoolean(y.typ) { + return false + } + if isString(x.typ) != isString(y.typ) { + return false + } + return true } - check.convertUntyped(&y, x.typ) - if y.mode == invalid { - x.mode = invalid - return + if canMix(x, &y) { + check.convertUntyped(x, y.typ) + if x.mode == invalid { + return + } + check.convertUntyped(&y, x.typ) + if y.mode == invalid { + x.mode = invalid + return + } } if isComparison(op) { diff --git a/src/go/types/testdata/check/const0.src b/src/go/types/testdata/check/const0.src index 5608b1549b..3cffdf904c 100644 --- a/src/go/types/testdata/check/const0.src +++ b/src/go/types/testdata/check/const0.src @@ -27,7 +27,7 @@ const ( ub1 = true ub2 = 2 < 1 ub3 = ui1 == uf1 - ub4 = true /* ERROR "cannot convert" */ == 0 + ub4 = true /* ERROR "mismatched types untyped bool and untyped int" */ == 0 // integer values ui0 = 0 diff --git a/src/go/types/testdata/check/decls1.src b/src/go/types/testdata/check/decls1.src index f4d2eaba91..6fe349b0b2 100644 --- a/src/go/types/testdata/check/decls1.src +++ b/src/go/types/testdata/check/decls1.src @@ -83,7 +83,7 @@ var ( // Constant expression initializations var ( - v1 = 1 /* ERROR "cannot convert" */ + "foo" + v1 = 1 /* ERROR "mismatched types untyped int and untyped string" */ + "foo" v2 = c + 255 v3 = c + 256 /* ERROR "overflows" */ v4 = r + 2147483647 diff --git a/src/go/types/testdata/check/expr1.src b/src/go/types/testdata/check/expr1.src index 4ead815158..42b95fbb37 100644 --- a/src/go/types/testdata/check/expr1.src +++ b/src/go/types/testdata/check/expr1.src @@ -111,10 +111,10 @@ type mystring string func _(x, y string, z mystring) { x = x + "foo" x = x /* ERROR not defined */ - "foo" - x = x + 1 // ERROR cannot convert + x = x /* ERROR mismatched types string and untyped int */ + 1 x = x + y x = x /* ERROR not defined */ - y - x = x * 10 // ERROR cannot convert + x = x /* ERROR mismatched types string and untyped int */* 10 } func f() (a, b int) { return } diff --git a/src/go/types/testdata/check/expr2.src b/src/go/types/testdata/check/expr2.src index 0c959e8011..f9726b5de5 100644 --- a/src/go/types/testdata/check/expr2.src +++ b/src/go/types/testdata/check/expr2.src @@ -10,7 +10,7 @@ func _bool() { const t = true == true const f = true == false _ = t /* ERROR "cannot compare" */ < f - _ = 0 /* ERROR "cannot convert" */ == t + _ = 0 /* ERROR "mismatched types untyped int and untyped bool" */ == t var b bool var x, y float32 b = x < y diff --git a/src/go/types/testdata/check/expr3.src b/src/go/types/testdata/check/expr3.src index 0525a5a33a..3ab367810f 100644 --- a/src/go/types/testdata/check/expr3.src +++ b/src/go/types/testdata/check/expr3.src @@ -103,7 +103,7 @@ func indexes() { var ok mybool _, ok = m["bar"] _ = ok - _ = m[0 /* ERROR "cannot use 0" */ ] + "foo" // ERROR "cannot convert" + _ = m/* ERROR "mismatched types int and untyped string" */[0 /* ERROR "cannot use 0" */ ] + "foo" var t string _ = t[- /* ERROR "negative" */ 1] diff --git a/src/go/types/testdata/check/stmt0.src b/src/go/types/testdata/check/stmt0.src index 76b6e70d63..15df37703c 100644 --- a/src/go/types/testdata/check/stmt0.src +++ b/src/go/types/testdata/check/stmt0.src @@ -49,18 +49,18 @@ func assignments1() { b = true i += 1 - i += "foo" /* ERROR "cannot convert.*int" */ + i /* ERROR "mismatched types int and untyped string" */+= "foo" f -= 1 f /= 0 f = float32(0)/0 /* ERROR "division by zero" */ - f -= "foo" /* ERROR "cannot convert.*float64" */ + f /* ERROR "mismatched types float64 and untyped string" */-= "foo" c *= 1 c /= 0 s += "bar" - s += 1 /* ERROR "cannot convert.*string" */ + s /* ERROR "mismatched types string and untyped int" */+= 1 var u64 uint64 u64 += 1< Date: Fri, 18 Jun 2021 03:14:09 +0000 Subject: [PATCH 0317/2500] [dev.typeparams] cmd/go: include new internal packages in TestNewReleaseRebuildsStalePackagesInGOPATH CL 328336 introduced two new packages that the runtime and other low-level packages depend on. Include them as targets to copy in this test with other such packages. Fixes the dev.typeparams longtest builders. Change-Id: Ia886f0264962a68acd06ebca002eef8515f06487 Reviewed-on: https://go-review.googlesource.com/c/go/+/329251 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/go/go_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index c0c86ab9f5..eaafe79235 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -806,7 +806,9 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) { "src/internal/abi", "src/internal/bytealg", "src/internal/cpu", + "src/internal/goarch", "src/internal/goexperiment", + "src/internal/goos", "src/math/bits", "src/unsafe", filepath.Join("pkg", runtime.GOOS+"_"+runtime.GOARCH), -- GitLab From 54fe57bc22f7890810bbddae2499eda8d4acfaef Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 17 Jun 2021 01:12:23 -0700 Subject: [PATCH 0318/2500] [dev.typeparams] cmd/compile: record writer's stack at export data sync points This CL extends the unified export data format's existing sync mechanism to save writer stacks, controlled by the -d=syncframes debug flag. This allows readers to provide more details when reporting desync errors, which should simplify development of the data format and the various reader/writer implementations. For example, CL 328051 updated reader and writer, but missed making a similar change to the linker (fix in CL 328054). Re-reviewing the CL in isolation after the failure, it was not immediately obvious what was going wrong. But the pair of stack traces below identifies exactly what happened: it should have updated linker.relocFuncExt to write out the new sync marker too. ``` data sync error: package "internal/abi", section 6, index 4, offset 536 found UseReloc, written at: /home/mdempsky/wd/go/src/cmd/compile/internal/noder/encoder.go:221: (*encoder).reloc +0x44 /home/mdempsky/wd/go/src/cmd/compile/internal/noder/linker.go:214: (*linker).relocFuncExt +0x580 /home/mdempsky/wd/go/src/cmd/compile/internal/noder/linker.go:233: (*linker).relocTypeExt +0x234 /home/mdempsky/wd/go/src/cmd/compile/internal/noder/linker.go:161: (*linker).relocObj +0x2198 /home/mdempsky/wd/go/src/cmd/compile/internal/noder/linker.go:64: (*linker).relocIdx +0x196 expected ImplicitTypes, reading at: /home/mdempsky/wd/go/src/cmd/compile/internal/noder/reader.go:796: (*reader).implicitTypes +0x36 /home/mdempsky/wd/go/src/cmd/compile/internal/noder/reader.go:810: (*reader).addBody +0x81 /home/mdempsky/wd/go/src/cmd/compile/internal/noder/reader.go:727: (*reader).funcExt +0x542 /home/mdempsky/wd/go/src/cmd/compile/internal/noder/reader.go:651: (*reader).method +0x324 /home/mdempsky/wd/go/src/cmd/compile/internal/noder/reader.go:557: (*pkgReader).objIdx +0x2704 ``` Change-Id: I911193edd2a965f81b7459f15fb613a773584685 Reviewed-on: https://go-review.googlesource.com/c/go/+/328909 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Matthew Dempsky Reviewed-by: Cuong Manh Le Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/base/debug.go | 1 + src/cmd/compile/internal/noder/decoder.go | 100 ++++++++++++++---- src/cmd/compile/internal/noder/encoder.go | 83 +++++++++++---- src/cmd/compile/internal/noder/frames_go1.go | 20 ++++ src/cmd/compile/internal/noder/frames_go17.go | 24 +++++ src/cmd/compile/internal/noder/reader.go | 2 +- src/cmd/compile/internal/noder/sync.go | 33 +++++- src/cmd/compile/internal/noder/writer.go | 2 +- 8 files changed, 219 insertions(+), 46 deletions(-) create mode 100644 src/cmd/compile/internal/noder/frames_go1.go create mode 100644 src/cmd/compile/internal/noder/frames_go17.go diff --git a/src/cmd/compile/internal/base/debug.go b/src/cmd/compile/internal/base/debug.go index 824a8baa83..fd42021946 100644 --- a/src/cmd/compile/internal/base/debug.go +++ b/src/cmd/compile/internal/base/debug.go @@ -44,6 +44,7 @@ type DebugFlags struct { Panic int `help:"show all compiler panics"` Slice int `help:"print information about slice compilation"` SoftFloat int `help:"force compiler to emit soft-float code"` + SyncFrames int `help:"how many writer stack frames to include at sync points in unified export data"` TypeAssert int `help:"print information about type assertion inlining"` TypecheckInl int `help:"eager typechecking of inline function bodies"` Unified int `help:"enable unified IR construction"` diff --git a/src/cmd/compile/internal/noder/decoder.go b/src/cmd/compile/internal/noder/decoder.go index 023388875c..3dc61c6a69 100644 --- a/src/cmd/compile/internal/noder/decoder.go +++ b/src/cmd/compile/internal/noder/decoder.go @@ -13,6 +13,7 @@ import ( "go/token" "math/big" "os" + "runtime" "strings" "cmd/compile/internal/base" @@ -131,17 +132,82 @@ func (r *decoder) checkErr(err error) { } } -func (r *decoder) sync(m syncMarker) { - if debug { - pos, err0 := r.data.Seek(0, os.SEEK_CUR) - x, err := r.data.ReadByte() - r.checkErr(err) - if x != byte(m) { - // TODO(mdempsky): Revisit this error message, and make it more - // useful (e.g., include r.p.pkgPath). - base.Fatalf("data sync error: found %v at %v (%v) in (%v:%v), but expected %v", syncMarker(x), pos, err0, r.k, r.idx, m) - } +func (r *decoder) rawUvarint() uint64 { + x, err := binary.ReadUvarint(&r.data) + r.checkErr(err) + return x +} + +func (r *decoder) rawVarint() int64 { + ux := r.rawUvarint() + + // Zig-zag decode. + x := int64(ux >> 1) + if ux&1 != 0 { + x = ^x + } + return x +} + +func (r *decoder) rawReloc(k reloc, idx int) int { + e := r.relocs[idx] + assert(e.kind == k) + return e.idx +} + +func (r *decoder) sync(mWant syncMarker) { + if !enableSync { + return + } + + pos, _ := r.data.Seek(0, os.SEEK_CUR) // TODO(mdempsky): io.SeekCurrent after #44505 is resolved + mHave := syncMarker(r.rawUvarint()) + writerPCs := make([]int, r.rawUvarint()) + for i := range writerPCs { + writerPCs[i] = int(r.rawUvarint()) } + + if mHave == mWant { + return + } + + // There's some tension here between printing: + // + // (1) full file paths that tools can recognize (e.g., so emacs + // hyperlinks the "file:line" text for easy navigation), or + // + // (2) short file paths that are easier for humans to read (e.g., by + // omitting redundant or irrelevant details, so it's easier to + // focus on the useful bits that remain). + // + // The current formatting favors the former, as it seems more + // helpful in practice. But perhaps the formatting could be improved + // to better address both concerns. For example, use relative file + // paths if they would be shorter, or rewrite file paths to contain + // "$GOROOT" (like objabi.AbsFile does) if tools can be taught how + // to reliably expand that again. + + fmt.Printf("export data desync: package %q, section %v, index %v, offset %v\n", r.common.pkgPath, r.k, r.idx, pos) + + fmt.Printf("\nfound %v, written at:\n", mHave) + if len(writerPCs) == 0 { + fmt.Printf("\t[stack trace unavailable; recompile package %q with -d=syncframes]\n", r.common.pkgPath) + } + for _, pc := range writerPCs { + fmt.Printf("\t%s\n", r.common.stringIdx(r.rawReloc(relocString, pc))) + } + + fmt.Printf("\nexpected %v, reading at:\n", mWant) + var readerPCs [32]uintptr // TODO(mdempsky): Dynamically size? + n := runtime.Callers(2, readerPCs[:]) + for _, pc := range fmtFrames(readerPCs[:n]...) { + fmt.Printf("\t%s\n", pc) + } + + // We already printed a stack trace for the reader, so now we can + // simply exit. Printing a second one with panic or base.Fatalf + // would just be noise. + os.Exit(1) } func (r *decoder) bool() bool { @@ -154,16 +220,12 @@ func (r *decoder) bool() bool { func (r *decoder) int64() int64 { r.sync(syncInt64) - x, err := binary.ReadVarint(&r.data) - r.checkErr(err) - return x + return r.rawVarint() } func (r *decoder) uint64() uint64 { r.sync(syncUint64) - x, err := binary.ReadUvarint(&r.data) - r.checkErr(err) - return x + return r.rawUvarint() } func (r *decoder) len() int { x := r.uint64(); v := int(x); assert(uint64(v) == x); return v } @@ -177,11 +239,7 @@ func (r *decoder) code(mark syncMarker) int { func (r *decoder) reloc(k reloc) int { r.sync(syncUseReloc) - idx := r.len() - - e := r.relocs[idx] - assert(e.kind == k) - return e.idx + return r.rawReloc(k, r.len()) } func (r *decoder) string() string { diff --git a/src/cmd/compile/internal/noder/encoder.go b/src/cmd/compile/internal/noder/encoder.go index dc288dc29f..d8ab0f6255 100644 --- a/src/cmd/compile/internal/noder/encoder.go +++ b/src/cmd/compile/internal/noder/encoder.go @@ -13,6 +13,7 @@ import ( "go/constant" "io" "math/big" + "runtime" "cmd/compile/internal/base" ) @@ -93,6 +94,8 @@ type encoder struct { relocs []relocEnt data bytes.Buffer + encodingRelocHeader bool + k reloc idx int } @@ -107,6 +110,10 @@ func (w *encoder) flush() int { // TODO(mdempsky): Consider writing these out separately so they're // easier to strip, along with function bodies, so that we can prune // down to just the data that's relevant to go/types. + if w.encodingRelocHeader { + base.Fatalf("encodingRelocHeader already true; recursive flush?") + } + w.encodingRelocHeader = true w.sync(syncRelocs) w.len(len(w.relocs)) for _, rent := range w.relocs { @@ -128,10 +135,58 @@ func (w *encoder) checkErr(err error) { } } +func (w *encoder) rawUvarint(x uint64) { + var buf [binary.MaxVarintLen64]byte + n := binary.PutUvarint(buf[:], x) + _, err := w.data.Write(buf[:n]) + w.checkErr(err) +} + +func (w *encoder) rawVarint(x int64) { + // Zig-zag encode. + ux := uint64(x) << 1 + if x < 0 { + ux = ^ux + } + + w.rawUvarint(ux) +} + +func (w *encoder) rawReloc(r reloc, idx int) int { + // TODO(mdempsky): Use map for lookup. + for i, rent := range w.relocs { + if rent.kind == r && rent.idx == idx { + return i + } + } + + i := len(w.relocs) + w.relocs = append(w.relocs, relocEnt{r, idx}) + return i +} + func (w *encoder) sync(m syncMarker) { - if debug { - err := w.data.WriteByte(byte(m)) - w.checkErr(err) + if !enableSync { + return + } + + // Writing out stack frame string references requires working + // relocations, but writing out the relocations themselves involves + // sync markers. To prevent infinite recursion, we simply trim the + // stack frame for sync markers within the relocation header. + var frames []string + if !w.encodingRelocHeader && base.Debug.SyncFrames > 0 { + pcs := make([]uintptr, base.Debug.SyncFrames) + n := runtime.Callers(2, pcs) + frames = fmtFrames(pcs[:n]...) + } + + // TODO(mdempsky): Save space by writing out stack frames as a + // linked list so we can share common stack frames. + w.rawUvarint(uint64(m)) + w.rawUvarint(uint64(len(frames))) + for _, frame := range frames { + w.rawUvarint(uint64(w.rawReloc(relocString, w.p.stringIdx(frame)))) } } @@ -148,18 +203,12 @@ func (w *encoder) bool(b bool) bool { func (w *encoder) int64(x int64) { w.sync(syncInt64) - var buf [binary.MaxVarintLen64]byte - n := binary.PutVarint(buf[:], x) - _, err := w.data.Write(buf[:n]) - w.checkErr(err) + w.rawVarint(x) } func (w *encoder) uint64(x uint64) { w.sync(syncUint64) - var buf [binary.MaxVarintLen64]byte - n := binary.PutUvarint(buf[:], x) - _, err := w.data.Write(buf[:n]) - w.checkErr(err) + w.rawUvarint(x) } func (w *encoder) len(x int) { assert(x >= 0); w.uint64(uint64(x)) } @@ -168,17 +217,7 @@ func (w *encoder) uint(x uint) { w.uint64(uint64(x)) } func (w *encoder) reloc(r reloc, idx int) { w.sync(syncUseReloc) - - // TODO(mdempsky): Use map for lookup. - for i, rent := range w.relocs { - if rent.kind == r && rent.idx == idx { - w.len(i) - return - } - } - - w.len(len(w.relocs)) - w.relocs = append(w.relocs, relocEnt{r, idx}) + w.len(w.rawReloc(r, idx)) } func (w *encoder) code(c code) { diff --git a/src/cmd/compile/internal/noder/frames_go1.go b/src/cmd/compile/internal/noder/frames_go1.go new file mode 100644 index 0000000000..2958efd622 --- /dev/null +++ b/src/cmd/compile/internal/noder/frames_go1.go @@ -0,0 +1,20 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !go1.7 + +// TODO(mdempsky): Remove after #44505 is resolved + +package noder + +import "runtime" + +func walkFrames(pcs []uintptr, visit frameVisitor) { + for _, pc := range pcs { + fn := runtime.FuncForPC(pc) + file, line := fn.FileLine(pc) + + visit(file, line, fn.Name(), pc-fn.Entry()) + } +} diff --git a/src/cmd/compile/internal/noder/frames_go17.go b/src/cmd/compile/internal/noder/frames_go17.go new file mode 100644 index 0000000000..273217e39a --- /dev/null +++ b/src/cmd/compile/internal/noder/frames_go17.go @@ -0,0 +1,24 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.7 + +package noder + +import "runtime" + +func walkFrames(pcs []uintptr, visit frameVisitor) { + if len(pcs) == 0 { + return + } + + frames := runtime.CallersFrames(pcs) + for { + frame, more := frames.Next() + visit(frame.File, frame.Line, frame.Function, frame.PC-frame.Entry) + if !more { + return + } + } +} diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 803acaa88d..efa607e13b 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -910,7 +910,7 @@ func (r *reader) addLocal(name *ir.Name, ctxt ir.Class) { assert(ctxt == ir.PAUTO || ctxt == ir.PPARAM || ctxt == ir.PPARAMOUT) r.sync(syncAddLocal) - if debug { + if enableSync { want := r.int() if have := len(r.locals); have != want { base.FatalfAt(name.Pos(), "locals table has desynced") diff --git a/src/cmd/compile/internal/noder/sync.go b/src/cmd/compile/internal/noder/sync.go index 7326a6edbe..aef98dbd78 100644 --- a/src/cmd/compile/internal/noder/sync.go +++ b/src/cmd/compile/internal/noder/sync.go @@ -6,8 +6,39 @@ package noder -const debug = true +import ( + "fmt" + "strings" +) + +// enableSync controls whether sync markers are written into unified +// IR's export data format and also whether they're expected when +// reading them back in. They're inessential to the correct +// functioning of unified IR, but are helpful during development to +// detect mistakes. +// +// When sync is enabled, writer stack frames will also be included in +// the export data. Currently, a fixed number of frames are included, +// controlled by -d=syncframes (default 0). +const enableSync = true + +// fmtFrames formats a backtrace for reporting reader/writer desyncs. +func fmtFrames(pcs ...uintptr) []string { + res := make([]string, 0, len(pcs)) + walkFrames(pcs, func(file string, line int, name string, offset uintptr) { + // Trim package from function name. It's just redundant noise. + name = strings.TrimPrefix(name, "cmd/compile/internal/noder.") + + res = append(res, fmt.Sprintf("%s:%v: %s +0x%v", file, line, name, offset)) + }) + return res +} + +type frameVisitor func(file string, line int, name string, offset uintptr) +// syncMarker is an enum type that represents markers that may be +// written to export data to ensure the reader and writer stay +// synchronized. type syncMarker int //go:generate stringer -type=syncMarker -trimprefix=sync diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 1475540d84..cc749b0d1e 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -733,7 +733,7 @@ func (w *writer) funcarg(param *types2.Var, result bool) { func (w *writer) addLocal(obj types2.Object) { w.sync(syncAddLocal) idx := len(w.localsIdx) - if debug { + if enableSync { w.int(idx) } w.localsIdx[obj] = idx -- GitLab From 6fa043795870305d96a1e4c0f276ac431f688524 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 17 Jun 2021 22:51:45 +0700 Subject: [PATCH 0319/2500] [dev.typeparams] cmd/compile: add documentation for unified IR pipeline While at it, also rename "useUnifiedIR" to "unified", to be consistent with "-d=unified" and "GOEXPERIMENT=unified". Change-Id: I48ffdb4b36368343893b74f174608f5f59278249 Reviewed-on: https://go-review.googlesource.com/c/go/+/328989 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/noder/noder.go | 2 +- src/cmd/compile/internal/noder/quirks.go | 2 +- src/cmd/compile/internal/noder/unified.go | 50 ++++++++++++++++++++--- 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index c7970396f8..3d83129aea 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -77,7 +77,7 @@ func LoadPackage(filenames []string) { base.Timer.AddEvent(int64(lines), "lines") if base.Debug.Unified != 0 { - useUnifiedIR(noders) + unified(noders) return } diff --git a/src/cmd/compile/internal/noder/quirks.go b/src/cmd/compile/internal/noder/quirks.go index 9f33fc576d..28a729f276 100644 --- a/src/cmd/compile/internal/noder/quirks.go +++ b/src/cmd/compile/internal/noder/quirks.go @@ -20,7 +20,7 @@ import ( // -cmp when compared against the legacy frontend behavior, but can be // removed after that's no longer a concern. -// quirksMode controls whether behavior specific to satsifying +// quirksMode controls whether behavior specific to satisfying // toolstash -cmp is used. func quirksMode() bool { // Currently, unified IR doesn't try to be compatible with diff --git a/src/cmd/compile/internal/noder/unified.go b/src/cmd/compile/internal/noder/unified.go index 96c0916493..7a1bb88537 100644 --- a/src/cmd/compile/internal/noder/unified.go +++ b/src/cmd/compile/internal/noder/unified.go @@ -28,9 +28,48 @@ import ( // later. var localPkgReader *pkgReader -// useUnifiedIR reports whether the unified IR frontend should be -// used; and if so, uses it to construct the local package's IR. -func useUnifiedIR(noders []*noder) { +// unified construct the local package's IR from syntax's AST. +// +// The pipeline contains 2 steps: +// +// (1) Generate package export data "stub". +// +// (2) Generate package IR from package export data. +// +// The package data "stub" at step (1) contains everything from the local package, +// but nothing that have been imported. When we're actually writing out export data +// to the output files (see writeNewExport function), we run the "linker", which does +// a few things: +// +// + Updates compiler extensions data (e.g., inlining cost, escape analysis results). +// +// + Handles re-exporting any transitive dependencies. +// +// + Prunes out any unnecessary details (e.g., non-inlineable functions, because any +// downstream importers only care about inlinable functions). +// +// The source files are typechecked twice, once before writing export data +// using types2 checker, once after read export data using gc/typecheck. +// This duplication of work will go away once we always use types2 checker, +// we can remove the gc/typecheck pass. The reason it is still here: +// +// + It reduces engineering costs in maintaining a fork of typecheck +// (e.g., no need to backport fixes like CL 327651). +// +// + It makes it easier to pass toolstash -cmp. +// +// + Historically, we would always re-run the typechecker after import, even though +// we know the imported data is valid. It's not ideal, but also not causing any +// problem either. +// +// + There's still transformation that being done during gc/typecheck, like rewriting +// multi-valued function call, or transform ir.OINDEX -> ir.OINDEXMAP. +// +// Using syntax+types2 tree, which already has a complete representation of generics, +// the unified IR has the full typed AST for doing introspection during step (1). +// In other words, we have all necessary information to build the generic IR form +// (see writer.captureVars for an example). +func unified(noders []*noder) { inline.NewInline = InlineCall if !quirksMode() { @@ -111,8 +150,9 @@ func useUnifiedIR(noders []*noder) { base.ExitIfErrors() // just in case } -// writePkgStub type checks the given parsed source files and then -// returns +// writePkgStub type checks the given parsed source files, +// writes an export data package stub representing them, +// and returns the result. func writePkgStub(noders []*noder) string { m, pkg, info := checkFiles(noders) -- GitLab From e9c01f980403ef88340ded62d78b4cd3a4b592f8 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sun, 13 Jun 2021 11:05:45 -0700 Subject: [PATCH 0320/2500] [dev.typeparams] cmd/compile: add missing copy of Field.Embedded in type substituter. Change-Id: I876933370a6bcb6586eda9d8fc28a081bf31b1cf Reviewed-on: https://go-review.googlesource.com/c/go/+/328511 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Robert Griesemer Trust: Dan Scales --- src/cmd/compile/internal/typecheck/subr.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 79b2402fe7..fb6d660db5 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1220,6 +1220,7 @@ func (ts *Tsubster) tstruct(t *types.Type, force bool) *types.Type { // names of embedded types (which should keep the name of // the type param, not the instantiated type). newfields[i] = types.NewField(f.Pos, f.Sym, t2) + newfields[i].Embedded = f.Embedded if f.Nname != nil && ts.Vars != nil { v := ts.Vars[f.Nname.(*ir.Name)] if v != nil { -- GitLab From 3f7a3133da4e13635c9012b451963cca76914270 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 18 Jun 2021 03:21:43 -0700 Subject: [PATCH 0321/2500] [dev.typeparams] cmd/compile: add "toolstash -cmp"-like test of -d=unified This CL adds a longtest test to make sure -d=unified=1 produces output identical to -d=unified=0. Change-Id: I2c5d38f67dbc8fecd8332a91ba7cae22225b090c Reviewed-on: https://go-review.googlesource.com/c/go/+/329429 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- .../compile/internal/noder/unified_test.go | 151 ++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 src/cmd/compile/internal/noder/unified_test.go diff --git a/src/cmd/compile/internal/noder/unified_test.go b/src/cmd/compile/internal/noder/unified_test.go new file mode 100644 index 0000000000..242fa1282f --- /dev/null +++ b/src/cmd/compile/internal/noder/unified_test.go @@ -0,0 +1,151 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package noder_test + +import ( + "encoding/json" + "flag" + exec "internal/execabs" + "os" + "reflect" + "runtime" + "strings" + "testing" +) + +var ( + flagPkgs = flag.String("pkgs", "std", "list of packages to compare") + flagAll = flag.Bool("all", false, "enable testing of all GOOS/GOARCH targets") + flagParallel = flag.Bool("parallel", false, "test GOOS/GOARCH targets in parallel") +) + +// TestUnifiedCompare implements a test similar to running: +// +// $ go build -toolexec="toolstash -cmp" std +// +// The -pkgs flag controls the list of packages tested. +// +// By default, only the native GOOS/GOARCH target is enabled. The -all +// flag enables testing of non-native targets. The -parallel flag +// additionally enables testing of targets in parallel. +// +// Caution: Testing all targets is very resource intensive! On an IBM +// P920 (dual Intel Xeon Gold 6154 CPUs; 36 cores, 192GB RAM), testing +// all targets in parallel takes about 5 minutes. Using the 'go test' +// command's -run flag for subtest matching is recommended for less +// powerful machines. +func TestUnifiedCompare(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode") + } + + targets, err := exec.Command("go", "tool", "dist", "list").Output() + if err != nil { + t.Fatal(err) + } + + for _, target := range strings.Fields(string(targets)) { + t.Run(target, func(t *testing.T) { + parts := strings.Split(target, "/") + goos, goarch := parts[0], parts[1] + + if !(*flagAll || goos == runtime.GOOS && goarch == runtime.GOARCH) { + t.Skip("skipping non-native target (use -all to enable)") + } + if *flagParallel { + t.Parallel() + } + + pkgs1 := loadPackages(t, goos, goarch, "-d=unified=0 -d=inlfuncswithclosures=0") + pkgs2 := loadPackages(t, goos, goarch, "-d=unified=1 -d=inlfuncswithclosures=0") + + if len(pkgs1) != len(pkgs2) { + t.Fatalf("length mismatch: %v != %v", len(pkgs1), len(pkgs2)) + } + + for i := range pkgs1 { + pkg1 := pkgs1[i] + pkg2 := pkgs2[i] + + path := pkg1.ImportPath + if path != pkg2.ImportPath { + t.Fatalf("mismatched paths: %q != %q", path, pkg2.ImportPath) + } + + // Packages that don't have any source files (e.g., packages + // unsafe, embed/internal/embedtest, and cmd/internal/moddeps). + if pkg1.Export == "" && pkg2.Export == "" { + continue + } + + if pkg1.BuildID == pkg2.BuildID { + t.Errorf("package %q: build IDs unexpectedly matched", path) + } + + // Unlike toolstash -cmp, we're comparing the same compiler + // binary against itself, just with different flags. So we + // don't need to worry about skipping over mismatched version + // strings, but we do need to account for differing build IDs. + // + // Fortunately, build IDs are cryptographic 256-bit hashes, + // and cmd/go provides us with them up front. So we can just + // use them as delimeters to split the files, and then check + // that the substrings are all equal. + file1 := strings.Split(readFile(t, pkg1.Export), pkg1.BuildID) + file2 := strings.Split(readFile(t, pkg2.Export), pkg2.BuildID) + if !reflect.DeepEqual(file1, file2) { + t.Errorf("package %q: compile output differs", path) + } + } + }) + } +} + +type pkg struct { + ImportPath string + Export string + BuildID string + Incomplete bool +} + +func loadPackages(t *testing.T, goos, goarch, gcflags string) []pkg { + args := []string{"list", "-e", "-export", "-json", "-gcflags=all=" + gcflags, "--"} + args = append(args, strings.Fields(*flagPkgs)...) + + cmd := exec.Command("go", args...) + cmd.Env = append(os.Environ(), "GOOS="+goos, "GOARCH="+goarch) + cmd.Stderr = os.Stderr + stdout, err := cmd.StdoutPipe() + if err != nil { + t.Fatal(err) + } + if err := cmd.Start(); err != nil { + t.Fatal(err) + } + + var res []pkg + for dec := json.NewDecoder(stdout); dec.More(); { + var pkg pkg + if err := dec.Decode(&pkg); err != nil { + t.Fatal(err) + } + if pkg.Incomplete { + t.Fatalf("incomplete package: %q", pkg.ImportPath) + } + res = append(res, pkg) + } + if err := cmd.Wait(); err != nil { + t.Fatal(err) + } + return res +} + +func readFile(t *testing.T, name string) string { + buf, err := os.ReadFile(name) + if err != nil { + t.Fatal(err) + } + return string(buf) +} -- GitLab From d24c90a1534a1399cc667696e05a0dcf2d15aa6d Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sun, 20 Jun 2021 02:06:45 +0700 Subject: [PATCH 0322/2500] [dev.typeparams] cmd/compile: explain how pkgReader.typIdx handles alias cyclic Change-Id: Ib9357c21bb010abf0d5fd17c3bee3197854c3a8a Reviewed-on: https://go-review.googlesource.com/c/go/+/329570 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/noder/reader.go | 41 ++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index efa607e13b..004f9cc271 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -295,9 +295,46 @@ func (pr *pkgReader) typIdx(idx int, implicits, explicits []*types.Type) *types. typ := r.doTyp() assert(typ != nil) + // For recursive type declarations involving interfaces and aliases, + // above r.doTyp() call may have already set pr.typs[idx], so just + // double check and return the type. + // + // Example: + // + // type F = func(I) + // + // type I interface { + // m(F) + // } + // + // The writer writes data types in following index order: + // + // 0: func(I) + // 1: I + // 2: interface{m(func(I))} + // + // The reader resolves it in following index order: + // + // 0 -> 1 -> 2 -> 0 -> 1 + // + // and can divide in logically 2 steps: + // + // - 0 -> 1 : first time the reader reach type I, + // it creates new named type with symbol I. + // + // - 2 -> 0 -> 1: the reader ends up reaching symbol I again, + // now the symbol I was setup in above step, so + // the reader just return the named type. + // + // Now, the functions called return, the pr.typs looks like below: + // + // - 0 -> 1 -> 2 -> 0 : [ I ] + // - 0 -> 1 -> 2 : [func(I) I ] + // - 0 -> 1 : [func(I) I interface { "".m(func("".I)) }] + // + // The idx 1, corresponding with type I was resolved successfully + // after r.doTyp() call. if typ := pr.typs[idx]; typ != nil { - // This happens in fixedbugs/issue27232.go. - // TODO(mdempsky): Explain why/how this happens. return typ } -- GitLab From 3f7f72a258394e19610c14772b07ba6f13e8bae6 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sun, 20 Jun 2021 14:33:51 +0700 Subject: [PATCH 0323/2500] [dev.typeparams] cmd/compile: fold reader checking type params logic to separate method So making it less verbose and clearer to the reader what that check means. Change-Id: I41587aab399e63600356c5cecec64978048bed36 Reviewed-on: https://go-review.googlesource.com/c/go/+/329571 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/noder/reader.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 004f9cc271..ad3cc25fd0 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -543,7 +543,7 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node return pri.pr.objIdx(pri.idx, pri.implicits, r.explicits) } if haveLegacyImports { - assert(len(r.implicits)+len(r.explicits) == 0) + assert(!r.hasTypeParams()) return typecheck.Resolve(ir.NewIdent(src.NoXPos, origSym)) } base.Fatalf("unresolved stub: %v", origSym) @@ -608,7 +608,7 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node } func (r *reader) mangle(sym *types.Sym) *types.Sym { - if len(r.implicits)+len(r.explicits) == 0 { + if !r.hasTypeParams() { return sym } @@ -722,6 +722,10 @@ func (r *reader) selector() (origPkg *types.Pkg, sym *types.Sym) { return } +func (r *reader) hasTypeParams() bool { + return len(r.implicits)+len(r.explicits) != 0 +} + // @@@ Compiler extensions func (r *reader) funcExt(name *ir.Name) { @@ -739,7 +743,7 @@ func (r *reader) funcExt(name *ir.Name) { // TODO(mdempsky): Remember why I wrote this code. I think it has to // do with how ir.VisitFuncsBottomUp works? - if name.Sym().Pkg == types.LocalPkg || len(r.implicits)+len(r.explicits) != 0 { + if name.Sym().Pkg == types.LocalPkg || r.hasTypeParams() { name.Defn = fn } @@ -774,7 +778,7 @@ func (r *reader) typeExt(name *ir.Name) { typ := name.Type() - if len(r.implicits)+len(r.explicits) != 0 { + if r.hasTypeParams() { // Set "RParams" (really type arguments here, not parameters) so // this type is treated as "fully instantiated". This ensures the // type descriptor is written out as DUPOK and method wrappers are -- GitLab From e57da8e53cadd2f456c6a9457beabd1b4659fc1f Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sun, 20 Jun 2021 22:17:19 +0700 Subject: [PATCH 0324/2500] [dev.typeparams] cmd/compile: explain why reader.funcExt need to set n.Defn Change-Id: I1a7d669879af57a1c1f48ce63ff0d214b694e680 Reviewed-on: https://go-review.googlesource.com/c/go/+/329572 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/noder/reader.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index ad3cc25fd0..4fc9e7a777 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -741,8 +741,13 @@ func (r *reader) funcExt(name *ir.Name) { fn.SetPos(name.Pos()) } - // TODO(mdempsky): Remember why I wrote this code. I think it has to - // do with how ir.VisitFuncsBottomUp works? + // Normally, we only compile local functions, which saves redundant compilation work. + // n.Defn is not nil for local functions, and is nil for imported function. But for + // generic functions, we might have an instantiation that no other package has seen before. + // So we need to be conservative and compile it again. + // + // That's why name.Defn is set here, so ir.VisitFuncsBottomUp can analyze function. + // TODO(mdempsky,cuonglm): find a cleaner way to handle this. if name.Sym().Pkg == types.LocalPkg || r.hasTypeParams() { name.Defn = fn } -- GitLab From 844c0763591e6c01ae2a30a743150be71b6d356f Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sun, 20 Jun 2021 21:33:54 +0700 Subject: [PATCH 0325/2500] [dev.typeparams] cmd/compile: simplify import* functions CL 280634 remove Sym.Importdef, so ipkg in importsym is not used anymore. So we can remove it from importsym and all other import* functions, which just call importsym internally. Change-Id: I15b9d11c4445dbe40982f7ff2a33a2116705e790 Reviewed-on: https://go-review.googlesource.com/c/go/+/329573 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/typecheck/export.go | 26 +++++++++---------- src/cmd/compile/internal/typecheck/iimport.go | 10 +++---- src/cmd/compile/internal/typecheck/syms.go | 4 +-- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/cmd/compile/internal/typecheck/export.go b/src/cmd/compile/internal/typecheck/export.go index 63d0a1ec6c..30726d4327 100644 --- a/src/cmd/compile/internal/typecheck/export.go +++ b/src/cmd/compile/internal/typecheck/export.go @@ -15,22 +15,22 @@ import ( // importalias declares symbol s as an imported type alias with type t. // ipkg is the package being imported -func importalias(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) *ir.Name { - return importobj(ipkg, pos, s, ir.OTYPE, ir.PEXTERN, t) +func importalias(pos src.XPos, s *types.Sym, t *types.Type) *ir.Name { + return importobj(pos, s, ir.OTYPE, ir.PEXTERN, t) } // importconst declares symbol s as an imported constant with type t and value val. // ipkg is the package being imported -func importconst(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type, val constant.Value) *ir.Name { - n := importobj(ipkg, pos, s, ir.OLITERAL, ir.PEXTERN, t) +func importconst(pos src.XPos, s *types.Sym, t *types.Type, val constant.Value) *ir.Name { + n := importobj(pos, s, ir.OLITERAL, ir.PEXTERN, t) n.SetVal(val) return n } // importfunc declares symbol s as an imported function with type t. // ipkg is the package being imported -func importfunc(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) *ir.Name { - n := importobj(ipkg, pos, s, ir.ONAME, ir.PFUNC, t) +func importfunc(pos src.XPos, s *types.Sym, t *types.Type) *ir.Name { + n := importobj(pos, s, ir.ONAME, ir.PFUNC, t) n.Func = ir.NewFunc(pos) n.Func.Nname = n return n @@ -38,8 +38,8 @@ func importfunc(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) *ir. // importobj declares symbol s as an imported object representable by op. // ipkg is the package being imported -func importobj(ipkg *types.Pkg, pos src.XPos, s *types.Sym, op ir.Op, ctxt ir.Class, t *types.Type) *ir.Name { - n := importsym(ipkg, pos, s, op, ctxt) +func importobj(pos src.XPos, s *types.Sym, op ir.Op, ctxt ir.Class, t *types.Type) *ir.Name { + n := importsym(pos, s, op, ctxt) n.SetType(t) if ctxt == ir.PFUNC { n.Sym().SetFunc(true) @@ -47,7 +47,7 @@ func importobj(ipkg *types.Pkg, pos src.XPos, s *types.Sym, op ir.Op, ctxt ir.Cl return n } -func importsym(ipkg *types.Pkg, pos src.XPos, s *types.Sym, op ir.Op, ctxt ir.Class) *ir.Name { +func importsym(pos src.XPos, s *types.Sym, op ir.Op, ctxt ir.Class) *ir.Name { if n := s.PkgDef(); n != nil { base.Fatalf("importsym of symbol that already exists: %v", n) } @@ -61,14 +61,14 @@ func importsym(ipkg *types.Pkg, pos src.XPos, s *types.Sym, op ir.Op, ctxt ir.Cl // importtype returns the named type declared by symbol s. // If no such type has been declared yet, a forward declaration is returned. // ipkg is the package being imported -func importtype(ipkg *types.Pkg, pos src.XPos, s *types.Sym) *ir.Name { - n := importsym(ipkg, pos, s, ir.OTYPE, ir.PEXTERN) +func importtype(pos src.XPos, s *types.Sym) *ir.Name { + n := importsym(pos, s, ir.OTYPE, ir.PEXTERN) n.SetType(types.NewNamed(n)) return n } // importvar declares symbol s as an imported variable with type t. // ipkg is the package being imported -func importvar(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) *ir.Name { - return importobj(ipkg, pos, s, ir.ONAME, ir.PEXTERN, t) +func importvar(pos src.XPos, s *types.Sym, t *types.Type) *ir.Name { + return importobj(pos, s, ir.ONAME, ir.PEXTERN, t) } diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 81f8ea05d9..d94f649a45 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -294,13 +294,13 @@ func (r *importReader) doDecl(sym *types.Sym) *ir.Name { case 'A': typ := r.typ() - return importalias(r.p.ipkg, pos, sym, typ) + return importalias(pos, sym, typ) case 'C': typ := r.typ() val := r.value(typ) - n := importconst(r.p.ipkg, pos, sym, typ, val) + n := importconst(pos, sym, typ, val) r.constExt(n) return n @@ -311,7 +311,7 @@ func (r *importReader) doDecl(sym *types.Sym) *ir.Name { } typ := r.signature(nil, tparams) - n := importfunc(r.p.ipkg, pos, sym, typ) + n := importfunc(pos, sym, typ) r.funcExt(n) return n @@ -323,7 +323,7 @@ func (r *importReader) doDecl(sym *types.Sym) *ir.Name { // Types can be recursive. We need to setup a stub // declaration before recursing. - n := importtype(r.p.ipkg, pos, sym) + n := importtype(pos, sym) t := n.Type() if rparams != nil { t.SetRParams(rparams) @@ -401,7 +401,7 @@ func (r *importReader) doDecl(sym *types.Sym) *ir.Name { case 'V': typ := r.typ() - n := importvar(r.p.ipkg, pos, sym, typ) + n := importvar(pos, sym, typ) r.varExt(n) return n diff --git a/src/cmd/compile/internal/typecheck/syms.go b/src/cmd/compile/internal/typecheck/syms.go index f29af82db2..ed3aaecc5a 100644 --- a/src/cmd/compile/internal/typecheck/syms.go +++ b/src/cmd/compile/internal/typecheck/syms.go @@ -75,9 +75,9 @@ func InitRuntime() { typ := typs[d.typ] switch d.tag { case funcTag: - importfunc(ir.Pkgs.Runtime, src.NoXPos, sym, typ) + importfunc(src.NoXPos, sym, typ) case varTag: - importvar(ir.Pkgs.Runtime, src.NoXPos, sym, typ) + importvar(src.NoXPos, sym, typ) default: base.Fatalf("unhandled declaration tag %v", d.tag) } -- GitLab From ff6f2051d9151a03d012c3020c62f3574e1b2d1b Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Thu, 17 Jun 2021 11:54:10 -0700 Subject: [PATCH 0326/2500] [dev.fuzz] internal/fuzz: refactor byte slice mutators Move all byte slice mutators into their own functions and randomly pick from a slice, rather than using a large switch statement. Additionally tests are added for each mutator which, lightly, test that they are working as intended. Other type mutators are left as-is for a similar refactor in the future. Change-Id: Ifd4447b885885b3cc068748f33cc5d1ea25af62f Reviewed-on: https://go-review.googlesource.com/c/go/+/329089 Trust: Roland Shoemaker Trust: Katie Hockman Run-TryBot: Roland Shoemaker TryBot-Result: Go Bot Reviewed-by: Katie Hockman Reviewed-by: Jay Conrod --- src/internal/fuzz/mutator.go | 296 ++---------------- src/internal/fuzz/mutators_byteslice.go | 301 +++++++++++++++++++ src/internal/fuzz/mutators_byteslice_test.go | 171 +++++++++++ src/internal/fuzz/pcg.go | 8 + 4 files changed, 510 insertions(+), 266 deletions(-) create mode 100644 src/internal/fuzz/mutators_byteslice.go create mode 100644 src/internal/fuzz/mutators_byteslice_test.go diff --git a/src/internal/fuzz/mutator.go b/src/internal/fuzz/mutator.go index bd8651f806..2d7dbe6ed8 100644 --- a/src/internal/fuzz/mutator.go +++ b/src/internal/fuzz/mutator.go @@ -13,7 +13,7 @@ import ( ) type mutator struct { - r *pcgRand + r mutatorRand } func newMutator() *mutator { @@ -242,6 +242,29 @@ func (m *mutator) mutateFloat(v, maxValue float64) float64 { return v } +type byteSliceMutator func(*mutator, []byte) []byte + +var byteSliceMutators = []byteSliceMutator{ + byteSliceRemoveBytes, + byteSliceInsertRandomBytes, + byteSliceDuplicateBytes, + byteSliceOverwriteBytes, + byteSliceBitFlip, + byteSliceXORByte, + byteSliceSwapByte, + byteSliceArithmeticUint8, + byteSliceArithmeticUint16, + byteSliceArithmeticUint32, + byteSliceArithmeticUint64, + byteSliceOverwriteInterestingUint8, + byteSliceOverwriteInterestingUint16, + byteSliceOverwriteInterestingUint32, + byteSliceInsertConstantBytes, + byteSliceOverwriteConstantBytes, + byteSliceShuffleBytes, + byteSliceSwapBytes, +} + func (m *mutator) mutateBytes(ptrB *[]byte) { b := *ptrB defer func() { @@ -255,272 +278,13 @@ func (m *mutator) mutateBytes(ptrB *[]byte) { numIters := 1 + m.r.exp2() for iter := 0; iter < numIters; iter++ { - switch m.rand(18) { - case 0: - // Remove a range of bytes. - if len(b) <= 1 { - iter-- - continue - } - pos0 := m.rand(len(b)) - pos1 := pos0 + m.chooseLen(len(b)-pos0) - copy(b[pos0:], b[pos1:]) - b = b[:len(b)-(pos1-pos0)] - case 1: - // Insert a range of random bytes. - pos := m.rand(len(b) + 1) - n := m.chooseLen(1024) - if len(b)+n >= cap(b) { - iter-- - continue - } - b = b[:len(b)+n] - copy(b[pos+n:], b[pos:]) - for i := 0; i < n; i++ { - b[pos+i] = byte(m.rand(256)) - } - case 2: - // Duplicate a range of bytes and insert it into - // a random position - if len(b) <= 1 { - iter-- - continue - } - src := m.rand(len(b)) - dst := m.rand(len(b)) - for dst == src { - dst = m.rand(len(b)) - } - n := m.chooseLen(len(b) - src) - // Use the end of the slice as scratch space to avoid doing an - // allocation. If the slice is too small abort and try something - // else. - if len(b)+(n*2) >= cap(b) { - iter-- - continue - } - end := len(b) - // Increase the size of b to fit the duplicated block as well as - // some extra working space - b = b[:end+(n*2)] - // Copy the block of bytes we want to duplicate to the end of the - // slice - copy(b[end+n:], b[src:src+n]) - // Shift the bytes after the splice point n positions to the right - // to make room for the new block - copy(b[dst+n:end+n], b[dst:end]) - // Insert the duplicate block into the splice point - copy(b[dst:], b[end+n:]) - b = b[:end+n] - case 3: - // Overwrite a range of bytes with a randomly selected - // chunk - if len(b) <= 1 { - iter-- - continue - } - src := m.rand(len(b)) - dst := m.rand(len(b)) - for dst == src { - dst = m.rand(len(b)) - } - n := m.chooseLen(len(b) - src) - copy(b[dst:], b[src:src+n]) - case 4: - // Bit flip. - if len(b) == 0 { - iter-- - continue - } - pos := m.rand(len(b)) - b[pos] ^= 1 << uint(m.rand(8)) - case 5: - // Set a byte to a random value. - if len(b) == 0 { - iter-- - continue - } - pos := m.rand(len(b)) - // In order to avoid a no-op (where the random value matches - // the existing value), use XOR instead of just setting to - // the random value. - b[pos] ^= byte(1 + m.rand(255)) - case 6: - // Swap 2 bytes. - if len(b) <= 1 { - iter-- - continue - } - src := m.rand(len(b)) - dst := m.rand(len(b)) - for dst == src { - dst = m.rand(len(b)) - } - b[src], b[dst] = b[dst], b[src] - case 7: - // Add/subtract from a byte. - if len(b) == 0 { - iter-- - continue - } - pos := m.rand(len(b)) - v := byte(m.rand(35) + 1) - if m.r.bool() { - b[pos] += v - } else { - b[pos] -= v - } - case 8: - // Add/subtract from a uint16. - if len(b) < 2 { - iter-- - continue - } - v := uint16(m.rand(35) + 1) - if m.r.bool() { - v = 0 - v - } - pos := m.rand(len(b) - 1) - enc := m.randByteOrder() - enc.PutUint16(b[pos:], enc.Uint16(b[pos:])+v) - case 9: - // Add/subtract from a uint32. - if len(b) < 4 { - iter-- - continue - } - v := uint32(m.rand(35) + 1) - if m.r.bool() { - v = 0 - v - } - pos := m.rand(len(b) - 3) - enc := m.randByteOrder() - enc.PutUint32(b[pos:], enc.Uint32(b[pos:])+v) - case 10: - // Add/subtract from a uint64. - if len(b) < 8 { - iter-- - continue - } - v := uint64(m.rand(35) + 1) - if m.r.bool() { - v = 0 - v - } - pos := m.rand(len(b) - 7) - enc := m.randByteOrder() - enc.PutUint64(b[pos:], enc.Uint64(b[pos:])+v) - case 11: - // Replace a byte with an interesting value. - if len(b) == 0 { - iter-- - continue - } - pos := m.rand(len(b)) - b[pos] = byte(interesting8[m.rand(len(interesting8))]) - case 12: - // Replace a uint16 with an interesting value. - if len(b) < 2 { - iter-- - continue - } - pos := m.rand(len(b) - 1) - v := uint16(interesting16[m.rand(len(interesting16))]) - m.randByteOrder().PutUint16(b[pos:], v) - case 13: - // Replace a uint32 with an interesting value. - if len(b) < 4 { - iter-- - continue - } - pos := m.rand(len(b) - 3) - v := uint32(interesting32[m.rand(len(interesting32))]) - m.randByteOrder().PutUint32(b[pos:], v) - case 14: - // Insert a range of constant bytes. - if len(b) <= 1 { - iter-- - continue - } - dst := m.rand(len(b)) - // TODO(rolandshoemaker,katiehockman): 4096 was mainly picked - // randomly. We may want to either pick a much larger value - // (AFL uses 32768, paired with a similar impl to chooseLen - // which biases towards smaller lengths that grow over time), - // or set the max based on characteristics of the corpus - // (libFuzzer sets a min/max based on the min/max size of - // entries in the corpus and then picks uniformly from - // that range). - n := m.chooseLen(4096) - if len(b)+n >= cap(b) { - iter-- - continue - } - b = b[:len(b)+n] - copy(b[dst+n:], b[dst:]) - rb := byte(m.rand(256)) - for i := dst; i < dst+n; i++ { - b[i] = rb - } - case 15: - // Overwrite a range of bytes with a chunk of - // constant bytes. - if len(b) <= 1 { - iter-- - continue - } - dst := m.rand(len(b)) - n := m.chooseLen(len(b) - dst) - rb := byte(m.rand(256)) - for i := dst; i < dst+n; i++ { - b[i] = rb - } - case 16: - // Shuffle a range of bytes - if len(b) <= 1 { - iter-- - continue - } - dst := m.rand(len(b)) - n := m.chooseLen(len(b) - dst) - if n <= 2 { - iter-- - continue - } - // Start at the end of the range, and iterate backwards - // to dst, swapping each element with another element in - // dst:dst+n (Fisher-Yates shuffle). - for i := n - 1; i > 0; i-- { - j := m.rand(i + 1) - b[dst+i], b[dst+j] = b[dst+j], b[dst+i] - } - case 17: - // Swap two chunks - if len(b) <= 1 { - iter-- - continue - } - src := m.rand(len(b)) - dst := m.rand(len(b)) - for dst == src { - dst = m.rand(len(b)) - } - n := m.chooseLen(len(b) - src) - // Use the end of the slice as scratch space to avoid doing an - // allocation. If the slice is too small abort and try something - // else. - if len(b)+n >= cap(b) { - iter-- - continue - } - end := len(b) - b = b[:end+n] - copy(b[end:], b[dst:dst+n]) - copy(b[dst:], b[src:src+n]) - copy(b[src:], b[end:]) - b = b[:end] - default: - panic("unknown mutator") + mut := byteSliceMutators[m.rand(len(byteSliceMutators))] + mutated := mut(m, b) + if mutated == nil { + iter-- + continue } + b = mutated } } diff --git a/src/internal/fuzz/mutators_byteslice.go b/src/internal/fuzz/mutators_byteslice.go new file mode 100644 index 0000000000..7c96b5920e --- /dev/null +++ b/src/internal/fuzz/mutators_byteslice.go @@ -0,0 +1,301 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fuzz + +// byteSliceRemoveBytes removes a random chunk of bytes from b. +func byteSliceRemoveBytes(m *mutator, b []byte) []byte { + if len(b) <= 1 { + return nil + } + pos0 := m.rand(len(b)) + pos1 := pos0 + m.chooseLen(len(b)-pos0) + copy(b[pos0:], b[pos1:]) + b = b[:len(b)-(pos1-pos0)] + return b +} + +// byteSliceInsertRandomBytes inserts a chunk of random bytes into b at a random +// position. +func byteSliceInsertRandomBytes(m *mutator, b []byte) []byte { + pos := m.rand(len(b) + 1) + n := m.chooseLen(1024) + if len(b)+n >= cap(b) { + return nil + } + b = b[:len(b)+n] + copy(b[pos+n:], b[pos:]) + for i := 0; i < n; i++ { + b[pos+i] = byte(m.rand(256)) + } + return b +} + +// byteSliceDuplicateBytes duplicates a chunk of bytes in b and inserts it into +// a random position. +func byteSliceDuplicateBytes(m *mutator, b []byte) []byte { + if len(b) <= 1 { + return nil + } + src := m.rand(len(b)) + dst := m.rand(len(b)) + for dst == src { + dst = m.rand(len(b)) + } + n := m.chooseLen(len(b) - src) + // Use the end of the slice as scratch space to avoid doing an + // allocation. If the slice is too small abort and try something + // else. + if len(b)+(n*2) >= cap(b) { + return nil + } + end := len(b) + // Increase the size of b to fit the duplicated block as well as + // some extra working space + b = b[:end+(n*2)] + // Copy the block of bytes we want to duplicate to the end of the + // slice + copy(b[end+n:], b[src:src+n]) + // Shift the bytes after the splice point n positions to the right + // to make room for the new block + copy(b[dst+n:end+n], b[dst:end]) + // Insert the duplicate block into the splice point + copy(b[dst:], b[end+n:]) + b = b[:end+n] + return b +} + +// byteSliceOverwriteBytes overwrites a chunk of b with another chunk of b. +func byteSliceOverwriteBytes(m *mutator, b []byte) []byte { + if len(b) <= 1 { + return nil + } + src := m.rand(len(b)) + dst := m.rand(len(b)) + for dst == src { + dst = m.rand(len(b)) + } + n := m.chooseLen(len(b) - src - 1) + copy(b[dst:], b[src:src+n]) + return b +} + +// byteSliceBitFlip flips a random bit in a random byte in b. +func byteSliceBitFlip(m *mutator, b []byte) []byte { + if len(b) == 0 { + return nil + } + pos := m.rand(len(b)) + b[pos] ^= 1 << uint(m.rand(8)) + return b +} + +// byteSliceXORByte XORs a random byte in b with a random value. +func byteSliceXORByte(m *mutator, b []byte) []byte { + if len(b) == 0 { + return nil + } + pos := m.rand(len(b)) + // In order to avoid a no-op (where the random value matches + // the existing value), use XOR instead of just setting to + // the random value. + b[pos] ^= byte(1 + m.rand(255)) + return b +} + +// byteSliceSwapByte swaps two random bytes in b. +func byteSliceSwapByte(m *mutator, b []byte) []byte { + if len(b) <= 1 { + return nil + } + src := m.rand(len(b)) + dst := m.rand(len(b)) + for dst == src { + dst = m.rand(len(b)) + } + b[src], b[dst] = b[dst], b[src] + return b +} + +// byteSliceArithmeticUint8 adds/subtracts from a random byte in b. +func byteSliceArithmeticUint8(m *mutator, b []byte) []byte { + if len(b) == 0 { + return nil + } + pos := m.rand(len(b)) + v := byte(m.rand(35) + 1) + if m.r.bool() { + b[pos] += v + } else { + b[pos] -= v + } + return b +} + +// byteSliceArithmeticUint16 adds/subtracts from a random uint16 in b. +func byteSliceArithmeticUint16(m *mutator, b []byte) []byte { + if len(b) < 2 { + return nil + } + v := uint16(m.rand(35) + 1) + if m.r.bool() { + v = 0 - v + } + pos := m.rand(len(b) - 1) + enc := m.randByteOrder() + enc.PutUint16(b[pos:], enc.Uint16(b[pos:])+v) + return b +} + +// byteSliceArithmeticUint32 adds/subtracts from a random uint32 in b. +func byteSliceArithmeticUint32(m *mutator, b []byte) []byte { + if len(b) < 4 { + return nil + } + v := uint32(m.rand(35) + 1) + if m.r.bool() { + v = 0 - v + } + pos := m.rand(len(b) - 3) + enc := m.randByteOrder() + enc.PutUint32(b[pos:], enc.Uint32(b[pos:])+v) + return b +} + +// byteSliceArithmeticUint64 adds/subtracts from a random uint64 in b. +func byteSliceArithmeticUint64(m *mutator, b []byte) []byte { + if len(b) < 8 { + return nil + } + v := uint64(m.rand(35) + 1) + if m.r.bool() { + v = 0 - v + } + pos := m.rand(len(b) - 7) + enc := m.randByteOrder() + enc.PutUint64(b[pos:], enc.Uint64(b[pos:])+v) + return b +} + +// byteSliceOverwriteInterestingUint8 overwrites a random byte in b with an interesting +// value. +func byteSliceOverwriteInterestingUint8(m *mutator, b []byte) []byte { + if len(b) == 0 { + return nil + } + pos := m.rand(len(b)) + b[pos] = byte(interesting8[m.rand(len(interesting8))]) + return b +} + +// byteSliceOverwriteInterestingUint16 overwrites a random uint16 in b with an interesting +// value. +func byteSliceOverwriteInterestingUint16(m *mutator, b []byte) []byte { + if len(b) < 2 { + return nil + } + pos := m.rand(len(b) - 1) + v := uint16(interesting16[m.rand(len(interesting16))]) + m.randByteOrder().PutUint16(b[pos:], v) + return b +} + +// byteSliceOverwriteInterestingUint32 overwrites a random uint16 in b with an interesting +// value. +func byteSliceOverwriteInterestingUint32(m *mutator, b []byte) []byte { + if len(b) < 4 { + return nil + } + pos := m.rand(len(b) - 3) + v := uint32(interesting32[m.rand(len(interesting32))]) + m.randByteOrder().PutUint32(b[pos:], v) + return b +} + +// byteSliceInsertConstantBytes inserts a chunk of constant bytes into a random position in b. +func byteSliceInsertConstantBytes(m *mutator, b []byte) []byte { + if len(b) <= 1 { + return nil + } + dst := m.rand(len(b)) + // TODO(rolandshoemaker,katiehockman): 4096 was mainly picked + // randomly. We may want to either pick a much larger value + // (AFL uses 32768, paired with a similar impl to chooseLen + // which biases towards smaller lengths that grow over time), + // or set the max based on characteristics of the corpus + // (libFuzzer sets a min/max based on the min/max size of + // entries in the corpus and then picks uniformly from + // that range). + n := m.chooseLen(4096) + if len(b)+n >= cap(b) { + return nil + } + b = b[:len(b)+n] + copy(b[dst+n:], b[dst:]) + rb := byte(m.rand(256)) + for i := dst; i < dst+n; i++ { + b[i] = rb + } + return b +} + +// byteSliceOverwriteConstantBytes overwrites a chunk of b with constant bytes. +func byteSliceOverwriteConstantBytes(m *mutator, b []byte) []byte { + if len(b) <= 1 { + return nil + } + dst := m.rand(len(b)) + n := m.chooseLen(len(b) - dst) + rb := byte(m.rand(256)) + for i := dst; i < dst+n; i++ { + b[i] = rb + } + return b +} + +// byteSliceShuffleBytes shuffles a chunk of bytes in b. +func byteSliceShuffleBytes(m *mutator, b []byte) []byte { + if len(b) <= 1 { + return nil + } + dst := m.rand(len(b)) + n := m.chooseLen(len(b) - dst) + if n <= 2 { + return nil + } + // Start at the end of the range, and iterate backwards + // to dst, swapping each element with another element in + // dst:dst+n (Fisher-Yates shuffle). + for i := n - 1; i > 0; i-- { + j := m.rand(i + 1) + b[dst+i], b[dst+j] = b[dst+j], b[dst+i] + } + return b +} + +// byteSliceSwapBytes swaps two chunks of bytes in b. +func byteSliceSwapBytes(m *mutator, b []byte) []byte { + if len(b) <= 1 { + return nil + } + src := m.rand(len(b)) + dst := m.rand(len(b)) + for dst == src { + dst = m.rand(len(b)) + } + n := m.chooseLen(len(b) - src - 1) + // Use the end of the slice as scratch space to avoid doing an + // allocation. If the slice is too small abort and try something + // else. + if len(b)+n >= cap(b) { + return nil + } + end := len(b) + b = b[:end+n] + copy(b[end:], b[dst:dst+n]) + copy(b[dst:], b[src:src+n]) + copy(b[src:], b[end:]) + b = b[:end] + return b +} diff --git a/src/internal/fuzz/mutators_byteslice_test.go b/src/internal/fuzz/mutators_byteslice_test.go new file mode 100644 index 0000000000..4b8652cf03 --- /dev/null +++ b/src/internal/fuzz/mutators_byteslice_test.go @@ -0,0 +1,171 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fuzz + +import ( + "bytes" + "testing" +) + +type mockRand struct { + counter int + b bool +} + +func (mr *mockRand) uint32() uint32 { + c := mr.counter + mr.counter++ + return uint32(c) +} + +func (mr *mockRand) intn(n int) int { + c := mr.counter + mr.counter++ + return c % n +} + +func (mr *mockRand) uint32n(n uint32) uint32 { + c := mr.counter + mr.counter++ + return uint32(c) % n +} + +func (mr *mockRand) exp2() int { + c := mr.counter + mr.counter++ + return c +} + +func (mr *mockRand) bool() bool { + b := mr.b + mr.b = !mr.b + return b +} + +func TestByteSliceMutators(t *testing.T) { + for _, tc := range []struct { + name string + mutator func(*mutator, []byte) []byte + input []byte + expected []byte + }{ + { + name: "byteSliceRemoveBytes", + mutator: byteSliceRemoveBytes, + input: []byte{1, 2, 3, 4}, + expected: []byte{4}, + }, + { + name: "byteSliceInsertRandomBytes", + mutator: byteSliceInsertRandomBytes, + input: make([]byte, 4, 8), + expected: []byte{3, 4, 5, 0, 0, 0, 0}, + }, + { + name: "byteSliceDuplicateBytes", + mutator: byteSliceDuplicateBytes, + input: append(make([]byte, 0, 13), []byte{1, 2, 3, 4}...), + expected: []byte{1, 1, 2, 3, 4, 2, 3, 4}, + }, + { + name: "byteSliceOverwriteBytes", + mutator: byteSliceOverwriteBytes, + input: []byte{1, 2, 3, 4}, + expected: []byte{1, 1, 3, 4}, + }, + { + name: "byteSliceBitFlip", + mutator: byteSliceBitFlip, + input: []byte{1, 2, 3, 4}, + expected: []byte{3, 2, 3, 4}, + }, + { + name: "byteSliceXORByte", + mutator: byteSliceXORByte, + input: []byte{1, 2, 3, 4}, + expected: []byte{3, 2, 3, 4}, + }, + { + name: "byteSliceSwapByte", + mutator: byteSliceSwapByte, + input: []byte{1, 2, 3, 4}, + expected: []byte{2, 1, 3, 4}, + }, + { + name: "byteSliceArithmeticUint8", + mutator: byteSliceArithmeticUint8, + input: []byte{1, 2, 3, 4}, + expected: []byte{255, 2, 3, 4}, + }, + { + name: "byteSliceArithmeticUint16", + mutator: byteSliceArithmeticUint16, + input: []byte{1, 2, 3, 4}, + expected: []byte{1, 3, 3, 4}, + }, + { + name: "byteSliceArithmeticUint32", + mutator: byteSliceArithmeticUint32, + input: []byte{1, 2, 3, 4}, + expected: []byte{2, 2, 3, 4}, + }, + { + name: "byteSliceArithmeticUint64", + mutator: byteSliceArithmeticUint64, + input: []byte{1, 2, 3, 4, 5, 6, 7, 8}, + expected: []byte{2, 2, 3, 4, 5, 6, 7, 8}, + }, + { + name: "byteSliceOverwriteInterestingUint8", + mutator: byteSliceOverwriteInterestingUint8, + input: []byte{1, 2, 3, 4}, + expected: []byte{255, 2, 3, 4}, + }, + { + name: "byteSliceOverwriteInterestingUint16", + mutator: byteSliceOverwriteInterestingUint16, + input: []byte{1, 2, 3, 4}, + expected: []byte{255, 127, 3, 4}, + }, + { + name: "byteSliceOverwriteInterestingUint32", + mutator: byteSliceOverwriteInterestingUint32, + input: []byte{1, 2, 3, 4}, + expected: []byte{250, 0, 0, 250}, + }, + { + name: "byteSliceInsertConstantBytes", + mutator: byteSliceInsertConstantBytes, + input: append(make([]byte, 0, 8), []byte{1, 2, 3, 4}...), + expected: []byte{3, 3, 3, 1, 2, 3, 4}, + }, + { + name: "byteSliceOverwriteConstantBytes", + mutator: byteSliceOverwriteConstantBytes, + input: []byte{1, 2, 3, 4}, + expected: []byte{3, 3, 3, 4}, + }, + { + name: "byteSliceShuffleBytes", + mutator: byteSliceShuffleBytes, + input: []byte{1, 2, 3, 4}, + expected: []byte{2, 3, 1, 4}, + }, + { + name: "byteSliceSwapBytes", + mutator: byteSliceSwapBytes, + input: append(make([]byte, 0, 9), []byte{1, 2, 3, 4}...), + expected: []byte{2, 1, 3, 4}, + }, + } { + t.Run(tc.name, func(t *testing.T) { + m := &mutator{r: &mockRand{}} + b := tc.mutator(m, tc.input) + if !bytes.Equal(b, tc.expected) { + t.Errorf("got %x, want %x", b, tc.expected) + } + }) + } +} diff --git a/src/internal/fuzz/pcg.go b/src/internal/fuzz/pcg.go index 18e553bc94..0b799aab02 100644 --- a/src/internal/fuzz/pcg.go +++ b/src/internal/fuzz/pcg.go @@ -13,6 +13,14 @@ import ( "time" ) +type mutatorRand interface { + uint32() uint32 + intn(int) int + uint32n(uint32) uint32 + exp2() int + bool() bool +} + // The functions in pcg implement a 32 bit PRNG with a 64 bit period: pcg xsh rr // 64 32. See https://www.pcg-random.org/ for more information. This // implementation is geared specifically towards the needs of fuzzing: Simple -- GitLab From 859d903b06af669edbbc74be371186f732b60bfa Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 21 Jun 2021 20:03:58 -0700 Subject: [PATCH 0327/2500] [dev.typeparams] cmd/compile: add -d=unifiedquirks for quirks mode Originally, overloading -d=inlfuncswithclosures=0 to enable quirks mode was convenient because toolstash -cmp doesn't provide a way to pass different gcflags to the installed vs stashed toolchains. Prior to unified IR being merged, the stashed toolchain wouldn't know about or accept any unified-specific flags. However, this concern is no longer applicable since unified IR has been merged, and the TestUnifiedCompare test can easily specify different flag sets for the baseline and experiment build configs. This CL adds a new -d=unifiedquirks flag to enable quirks mode, so that it's possible to test unified IR with -d=inlfuncswithclosures=0 without also affecting a bunch of other compilation details. Change-Id: Id1932f332822622aa8617278e82ec6d1a53b1b46 Reviewed-on: https://go-review.googlesource.com/c/go/+/329733 Trust: Matthew Dempsky Reviewed-by: Cuong Manh Le Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot --- src/cmd/compile/internal/base/debug.go | 1 + src/cmd/compile/internal/noder/quirks.go | 5 +---- src/cmd/compile/internal/noder/unified_test.go | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/cmd/compile/internal/base/debug.go b/src/cmd/compile/internal/base/debug.go index fd42021946..e2245e1c26 100644 --- a/src/cmd/compile/internal/base/debug.go +++ b/src/cmd/compile/internal/base/debug.go @@ -48,6 +48,7 @@ type DebugFlags struct { TypeAssert int `help:"print information about type assertion inlining"` TypecheckInl int `help:"eager typechecking of inline function bodies"` Unified int `help:"enable unified IR construction"` + UnifiedQuirks int `help:"enable unified IR construction's quirks mode"` WB int `help:"print information about write barriers"` ABIWrap int `help:"print information about ABI wrapper generation"` diff --git a/src/cmd/compile/internal/noder/quirks.go b/src/cmd/compile/internal/noder/quirks.go index 28a729f276..91b4c22025 100644 --- a/src/cmd/compile/internal/noder/quirks.go +++ b/src/cmd/compile/internal/noder/quirks.go @@ -23,10 +23,7 @@ import ( // quirksMode controls whether behavior specific to satisfying // toolstash -cmp is used. func quirksMode() bool { - // Currently, unified IR doesn't try to be compatible with - // -d=inlfuncswithclosures=1, so we overload this as a flag for - // enabling quirks mode. - return base.Debug.InlFuncsWithClosures == 0 + return base.Debug.UnifiedQuirks != 0 } // posBasesOf returns all of the position bases in the source files, diff --git a/src/cmd/compile/internal/noder/unified_test.go b/src/cmd/compile/internal/noder/unified_test.go index 242fa1282f..4732892f6c 100644 --- a/src/cmd/compile/internal/noder/unified_test.go +++ b/src/cmd/compile/internal/noder/unified_test.go @@ -59,7 +59,7 @@ func TestUnifiedCompare(t *testing.T) { } pkgs1 := loadPackages(t, goos, goarch, "-d=unified=0 -d=inlfuncswithclosures=0") - pkgs2 := loadPackages(t, goos, goarch, "-d=unified=1 -d=inlfuncswithclosures=0") + pkgs2 := loadPackages(t, goos, goarch, "-d=unified=1 -d=inlfuncswithclosures=0 -d=unifiedquirks=1") if len(pkgs1) != len(pkgs2) { t.Fatalf("length mismatch: %v != %v", len(pkgs1), len(pkgs2)) -- GitLab From 077100dfcd11b2aba4bd3099d5d28b4ce7de1126 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 21 Jun 2021 22:03:02 -0700 Subject: [PATCH 0328/2500] [dev.typeparams] cmd/compile: remove special escape analysis tags This CL removes the special escape analysis tags added to support //go:uintptrescapes and calls to external functions. Instead, these are kept as function pragmas. This CL by itself isn't very interesting, but I expect will help with subsequent cleanups I have planned here. Change-Id: Ifb960289a27e0a6295ce2d2f5ec233cac590522b Reviewed-on: https://go-review.googlesource.com/c/go/+/329969 Run-TryBot: Matthew Dempsky Reviewed-by: Cuong Manh Le Trust: Cuong Manh Le Trust: Matthew Dempsky --- src/cmd/compile/internal/escape/escape.go | 21 ++++----- src/cmd/compile/internal/ir/node.go | 19 +++++---- src/cmd/compile/internal/walk/order.go | 52 +++++++++++++---------- 3 files changed, 48 insertions(+), 44 deletions(-) diff --git a/src/cmd/compile/internal/escape/escape.go b/src/cmd/compile/internal/escape/escape.go index e3727bca27..3a937518ec 100644 --- a/src/cmd/compile/internal/escape/escape.go +++ b/src/cmd/compile/internal/escape/escape.go @@ -1132,7 +1132,7 @@ func (e *escape) tagHole(ks []hole, fn *ir.Name, param *types.Field) hole { // Call to previously tagged function. - if param.Note == UintptrEscapesNote { + if fn.Func != nil && fn.Func.Pragma&ir.UintptrEscapes != 0 && (param.Type.IsUintptr() || param.IsDDD() && param.Type.Elem().IsUintptr()) { k := e.heapHole() k.uintptrEscapesHack = true return k @@ -2048,15 +2048,6 @@ func HeapAllocReason(n ir.Node) string { return "" } -// This special tag is applied to uintptr variables -// that we believe may hold unsafe.Pointers for -// calls into assembly functions. -const UnsafeUintptrNote = "unsafe-uintptr" - -// This special tag is applied to uintptr parameters of functions -// marked go:uintptrescapes. -const UintptrEscapesNote = "uintptr-escapes" - func (b *batch) paramTag(fn *ir.Func, narg int, f *types.Field) string { name := func() string { if f.Sym != nil { @@ -2072,11 +2063,13 @@ func (b *batch) paramTag(fn *ir.Func, narg int, f *types.Field) string { // This really doesn't have much to do with escape analysis per se, // but we are reusing the ability to annotate an individual function // argument and pass those annotations along to importing code. + fn.Pragma |= ir.UintptrKeepAlive + if f.Type.IsUintptr() { if base.Flag.LowerM != 0 { base.WarnfAt(f.Pos, "assuming %v is unsafe uintptr", name()) } - return UnsafeUintptrNote + return "" } if !f.Type.HasPointers() { // don't bother tagging for scalars @@ -2102,18 +2095,20 @@ func (b *batch) paramTag(fn *ir.Func, narg int, f *types.Field) string { } if fn.Pragma&ir.UintptrEscapes != 0 { + fn.Pragma |= ir.UintptrKeepAlive + if f.Type.IsUintptr() { if base.Flag.LowerM != 0 { base.WarnfAt(f.Pos, "marking %v as escaping uintptr", name()) } - return UintptrEscapesNote + return "" } if f.IsDDD() && f.Type.Elem().IsUintptr() { // final argument is ...uintptr. if base.Flag.LowerM != 0 { base.WarnfAt(f.Pos, "marking %v as escaping ...uintptr", name()) } - return UintptrEscapesNote + return "" } } diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 9191eeb1d6..7c3dc10e46 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -436,18 +436,19 @@ func (s NameSet) Sorted(less func(*Name, *Name) bool) []*Name { return res } -type PragmaFlag int16 +type PragmaFlag uint16 const ( // Func pragmas. - Nointerface PragmaFlag = 1 << iota - Noescape // func parameters don't escape - Norace // func must not have race detector annotations - Nosplit // func should not execute on separate stack - Noinline // func should not be inlined - NoCheckPtr // func should not be instrumented by checkptr - CgoUnsafeArgs // treat a pointer to one arg as a pointer to them all - UintptrEscapes // pointers converted to uintptr escape + Nointerface PragmaFlag = 1 << iota + Noescape // func parameters don't escape + Norace // func must not have race detector annotations + Nosplit // func should not execute on separate stack + Noinline // func should not be inlined + NoCheckPtr // func should not be instrumented by checkptr + CgoUnsafeArgs // treat a pointer to one arg as a pointer to them all + UintptrKeepAlive // pointers converted to uintptr must be kept alive (compiler internal only) + UintptrEscapes // pointers converted to uintptr escape // Runtime-only func pragmas. // See ../../../../runtime/README.md for detailed descriptions. diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go index 845bf03657..b9aff03240 100644 --- a/src/cmd/compile/internal/walk/order.go +++ b/src/cmd/compile/internal/walk/order.go @@ -9,7 +9,6 @@ import ( "go/constant" "cmd/compile/internal/base" - "cmd/compile/internal/escape" "cmd/compile/internal/ir" "cmd/compile/internal/reflectdata" "cmd/compile/internal/staticinit" @@ -554,37 +553,46 @@ func (o *orderState) call(nn ir.Node) { n.X = o.expr(n.X, nil) o.exprList(n.Args) - if n.Op() == ir.OCALLINTER { + // Pick out the function callee, if statically known. + // TODO(mdempsky): De-duplicate with similar code in escape analysis. + var callee *ir.Func + switch n.Op() { + case ir.OCALLFUNC: + if fn, ok := n.X.(*ir.Name); ok && fn.Op() == ir.ONAME && fn.Class == ir.PFUNC { + callee = fn.Func + } + case ir.OCALLMETH: + callee = ir.MethodExprName(n.X).Func + } + + if callee == nil || callee.Pragma&ir.UintptrKeepAlive == 0 { return } - keepAlive := func(arg ir.Node) { + + keepAlive := func(args []ir.Node) { // If the argument is really a pointer being converted to uintptr, // arrange for the pointer to be kept alive until the call returns, // by copying it into a temp and marking that temp // still alive when we pop the temp stack. - if arg.Op() == ir.OCONVNOP { - arg := arg.(*ir.ConvExpr) - if arg.X.Type().IsUnsafePtr() { - x := o.copyExpr(arg.X) - arg.X = x - x.SetAddrtaken(true) // ensure SSA keeps the x variable - n.KeepAlive = append(n.KeepAlive, x) + for _, arg := range args { + if arg.Op() == ir.OCONVNOP && arg.Type().IsUintptr() { + arg := arg.(*ir.ConvExpr) + if arg.X.Type().IsUnsafePtr() { + x := o.copyExpr(arg.X) + arg.X = x + x.SetAddrtaken(true) // ensure SSA keeps the x variable + n.KeepAlive = append(n.KeepAlive, x) + } } } } - // Check for "unsafe-uintptr" tag provided by escape analysis. - for i, param := range n.X.Type().Params().FieldSlice() { - if param.Note == escape.UnsafeUintptrNote || param.Note == escape.UintptrEscapesNote { - if arg := n.Args[i]; arg.Op() == ir.OSLICELIT { - arg := arg.(*ir.CompLitExpr) - for _, elt := range arg.List { - keepAlive(elt) - } - } else { - keepAlive(arg) - } - } + last := len(n.Args) - 1 + if n.IsDDD && n.Args[last].Op() == ir.OSLICELIT { + keepAlive(n.Args[:last]) + keepAlive(n.Args[last].(*ir.CompLitExpr).List) + } else { + keepAlive(n.Args) } } -- GitLab From 3e6219c6a9472e266d504d443b065e5a3e265a64 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 22 Jun 2021 01:26:34 -0700 Subject: [PATCH 0329/2500] [dev.typeparams] cmd/compile: split package escape into multiple files This CL reorganizes the code from package escape into multiple files, so the relationships between bits of code are hopefully easier to follow. Besides moving code around and adding necessary copyright/import declarations, no code is touched at all. Change-Id: Iddd396c3a140f4eb1a7a6266d92a4098118b575b Reviewed-on: https://go-review.googlesource.com/c/go/+/329989 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Matthew Dempsky Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/escape/assign.go | 120 ++ src/cmd/compile/internal/escape/call.go | 182 +++ src/cmd/compile/internal/escape/escape.go | 1722 +-------------------- src/cmd/compile/internal/escape/expr.go | 340 ++++ src/cmd/compile/internal/escape/graph.go | 324 ++++ src/cmd/compile/internal/escape/leaks.go | 106 ++ src/cmd/compile/internal/escape/solve.go | 289 ++++ src/cmd/compile/internal/escape/stmt.go | 208 +++ src/cmd/compile/internal/escape/utils.go | 215 +++ 9 files changed, 1797 insertions(+), 1709 deletions(-) create mode 100644 src/cmd/compile/internal/escape/assign.go create mode 100644 src/cmd/compile/internal/escape/call.go create mode 100644 src/cmd/compile/internal/escape/expr.go create mode 100644 src/cmd/compile/internal/escape/graph.go create mode 100644 src/cmd/compile/internal/escape/leaks.go create mode 100644 src/cmd/compile/internal/escape/solve.go create mode 100644 src/cmd/compile/internal/escape/stmt.go create mode 100644 src/cmd/compile/internal/escape/utils.go diff --git a/src/cmd/compile/internal/escape/assign.go b/src/cmd/compile/internal/escape/assign.go new file mode 100644 index 0000000000..80697bf37b --- /dev/null +++ b/src/cmd/compile/internal/escape/assign.go @@ -0,0 +1,120 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package escape + +import ( + "cmd/compile/internal/base" + "cmd/compile/internal/ir" +) + +// addr evaluates an addressable expression n and returns a hole +// that represents storing into the represented location. +func (e *escape) addr(n ir.Node) hole { + if n == nil || ir.IsBlank(n) { + // Can happen in select case, range, maybe others. + return e.discardHole() + } + + k := e.heapHole() + + switch n.Op() { + default: + base.Fatalf("unexpected addr: %v", n) + case ir.ONAME: + n := n.(*ir.Name) + if n.Class == ir.PEXTERN { + break + } + k = e.oldLoc(n).asHole() + case ir.OLINKSYMOFFSET: + break + case ir.ODOT: + n := n.(*ir.SelectorExpr) + k = e.addr(n.X) + case ir.OINDEX: + n := n.(*ir.IndexExpr) + e.discard(n.Index) + if n.X.Type().IsArray() { + k = e.addr(n.X) + } else { + e.discard(n.X) + } + case ir.ODEREF, ir.ODOTPTR: + e.discard(n) + case ir.OINDEXMAP: + n := n.(*ir.IndexExpr) + e.discard(n.X) + e.assignHeap(n.Index, "key of map put", n) + } + + return k +} + +func (e *escape) addrs(l ir.Nodes) []hole { + var ks []hole + for _, n := range l { + ks = append(ks, e.addr(n)) + } + return ks +} + +func (e *escape) assignHeap(src ir.Node, why string, where ir.Node) { + e.expr(e.heapHole().note(where, why), src) +} + +// assignList evaluates the assignment dsts... = srcs.... +func (e *escape) assignList(dsts, srcs []ir.Node, why string, where ir.Node) { + ks := e.addrs(dsts) + for i, k := range ks { + var src ir.Node + if i < len(srcs) { + src = srcs[i] + } + + if dst := dsts[i]; dst != nil { + // Detect implicit conversion of uintptr to unsafe.Pointer when + // storing into reflect.{Slice,String}Header. + if dst.Op() == ir.ODOTPTR && ir.IsReflectHeaderDataField(dst) { + e.unsafeValue(e.heapHole().note(where, why), src) + continue + } + + // Filter out some no-op assignments for escape analysis. + if src != nil && isSelfAssign(dst, src) { + if base.Flag.LowerM != 0 { + base.WarnfAt(where.Pos(), "%v ignoring self-assignment in %v", e.curfn, where) + } + k = e.discardHole() + } + } + + e.expr(k.note(where, why), src) + } + + e.reassigned(ks, where) +} + +// reassigned marks the locations associated with the given holes as +// reassigned, unless the location represents a variable declared and +// assigned exactly once by where. +func (e *escape) reassigned(ks []hole, where ir.Node) { + if as, ok := where.(*ir.AssignStmt); ok && as.Op() == ir.OAS && as.Y == nil { + if dst, ok := as.X.(*ir.Name); ok && dst.Op() == ir.ONAME && dst.Defn == nil { + // Zero-value assignment for variable declared without an + // explicit initial value. Assume this is its initialization + // statement. + return + } + } + + for _, k := range ks { + loc := k.dst + // Variables declared by range statements are assigned on every iteration. + if n, ok := loc.n.(*ir.Name); ok && n.Defn == where && where.Op() != ir.ORANGE { + continue + } + loc.reassigned = true + } +} diff --git a/src/cmd/compile/internal/escape/call.go b/src/cmd/compile/internal/escape/call.go new file mode 100644 index 0000000000..28a3b679a5 --- /dev/null +++ b/src/cmd/compile/internal/escape/call.go @@ -0,0 +1,182 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package escape + +import ( + "cmd/compile/internal/base" + "cmd/compile/internal/ir" + "cmd/compile/internal/typecheck" + "cmd/compile/internal/types" +) + +// call evaluates a call expressions, including builtin calls. ks +// should contain the holes representing where the function callee's +// results flows; where is the OGO/ODEFER context of the call, if any. +func (e *escape) call(ks []hole, call, where ir.Node) { + topLevelDefer := where != nil && where.Op() == ir.ODEFER && e.loopDepth == 1 + if topLevelDefer { + // force stack allocation of defer record, unless + // open-coded defers are used (see ssa.go) + where.SetEsc(ir.EscNever) + } + + argument := func(k hole, arg ir.Node) { + if topLevelDefer { + // Top level defers arguments don't escape to + // heap, but they do need to last until end of + // function. + k = e.later(k) + } else if where != nil { + k = e.heapHole() + } + + e.expr(k.note(call, "call parameter"), arg) + } + + switch call.Op() { + default: + ir.Dump("esc", call) + base.Fatalf("unexpected call op: %v", call.Op()) + + case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER: + call := call.(*ir.CallExpr) + typecheck.FixVariadicCall(call) + + // Pick out the function callee, if statically known. + var fn *ir.Name + switch call.Op() { + case ir.OCALLFUNC: + switch v := ir.StaticValue(call.X); { + case v.Op() == ir.ONAME && v.(*ir.Name).Class == ir.PFUNC: + fn = v.(*ir.Name) + case v.Op() == ir.OCLOSURE: + fn = v.(*ir.ClosureExpr).Func.Nname + } + case ir.OCALLMETH: + fn = ir.MethodExprName(call.X) + } + + fntype := call.X.Type() + if fn != nil { + fntype = fn.Type() + } + + if ks != nil && fn != nil && e.inMutualBatch(fn) { + for i, result := range fn.Type().Results().FieldSlice() { + e.expr(ks[i], ir.AsNode(result.Nname)) + } + } + + if r := fntype.Recv(); r != nil { + argument(e.tagHole(ks, fn, r), call.X.(*ir.SelectorExpr).X) + } else { + // Evaluate callee function expression. + argument(e.discardHole(), call.X) + } + + args := call.Args + for i, param := range fntype.Params().FieldSlice() { + argument(e.tagHole(ks, fn, param), args[i]) + } + + case ir.OAPPEND: + call := call.(*ir.CallExpr) + args := call.Args + + // Appendee slice may flow directly to the result, if + // it has enough capacity. Alternatively, a new heap + // slice might be allocated, and all slice elements + // might flow to heap. + appendeeK := ks[0] + if args[0].Type().Elem().HasPointers() { + appendeeK = e.teeHole(appendeeK, e.heapHole().deref(call, "appendee slice")) + } + argument(appendeeK, args[0]) + + if call.IsDDD { + appendedK := e.discardHole() + if args[1].Type().IsSlice() && args[1].Type().Elem().HasPointers() { + appendedK = e.heapHole().deref(call, "appended slice...") + } + argument(appendedK, args[1]) + } else { + for _, arg := range args[1:] { + argument(e.heapHole(), arg) + } + } + + case ir.OCOPY: + call := call.(*ir.BinaryExpr) + argument(e.discardHole(), call.X) + + copiedK := e.discardHole() + if call.Y.Type().IsSlice() && call.Y.Type().Elem().HasPointers() { + copiedK = e.heapHole().deref(call, "copied slice") + } + argument(copiedK, call.Y) + + case ir.OPANIC: + call := call.(*ir.UnaryExpr) + argument(e.heapHole(), call.X) + + case ir.OCOMPLEX: + call := call.(*ir.BinaryExpr) + argument(e.discardHole(), call.X) + argument(e.discardHole(), call.Y) + case ir.ODELETE, ir.OPRINT, ir.OPRINTN, ir.ORECOVER: + call := call.(*ir.CallExpr) + for _, arg := range call.Args { + argument(e.discardHole(), arg) + } + case ir.OLEN, ir.OCAP, ir.OREAL, ir.OIMAG, ir.OCLOSE: + call := call.(*ir.UnaryExpr) + argument(e.discardHole(), call.X) + + case ir.OUNSAFEADD, ir.OUNSAFESLICE: + call := call.(*ir.BinaryExpr) + argument(ks[0], call.X) + argument(e.discardHole(), call.Y) + } +} + +// tagHole returns a hole for evaluating an argument passed to param. +// ks should contain the holes representing where the function +// callee's results flows. fn is the statically-known callee function, +// if any. +func (e *escape) tagHole(ks []hole, fn *ir.Name, param *types.Field) hole { + // If this is a dynamic call, we can't rely on param.Note. + if fn == nil { + return e.heapHole() + } + + if e.inMutualBatch(fn) { + return e.addr(ir.AsNode(param.Nname)) + } + + // Call to previously tagged function. + + if fn.Func != nil && fn.Func.Pragma&ir.UintptrEscapes != 0 && (param.Type.IsUintptr() || param.IsDDD() && param.Type.Elem().IsUintptr()) { + k := e.heapHole() + k.uintptrEscapesHack = true + return k + } + + var tagKs []hole + + esc := parseLeaks(param.Note) + if x := esc.Heap(); x >= 0 { + tagKs = append(tagKs, e.heapHole().shift(x)) + } + + if ks != nil { + for i := 0; i < numEscResults; i++ { + if x := esc.Result(i); x >= 0 { + tagKs = append(tagKs, ks[i].shift(x)) + } + } + } + + return e.teeHole(tagKs...) +} diff --git a/src/cmd/compile/internal/escape/escape.go b/src/cmd/compile/internal/escape/escape.go index 3a937518ec..8f75ae8b42 100644 --- a/src/cmd/compile/internal/escape/escape.go +++ b/src/cmd/compile/internal/escape/escape.go @@ -6,15 +6,11 @@ package escape import ( "fmt" - "math" - "strings" "cmd/compile/internal/base" "cmd/compile/internal/ir" "cmd/compile/internal/logopt" - "cmd/compile/internal/typecheck" "cmd/compile/internal/types" - "cmd/internal/src" ) // Escape analysis. @@ -118,90 +114,8 @@ type escape struct { loopDepth int } -// An location represents an abstract location that stores a Go -// variable. -type location struct { - n ir.Node // represented variable or expression, if any - curfn *ir.Func // enclosing function - edges []edge // incoming edges - loopDepth int // loopDepth at declaration - - // resultIndex records the tuple index (starting at 1) for - // PPARAMOUT variables within their function's result type. - // For non-PPARAMOUT variables it's 0. - resultIndex int - - // derefs and walkgen are used during walkOne to track the - // minimal dereferences from the walk root. - derefs int // >= -1 - walkgen uint32 - - // dst and dstEdgeindex track the next immediate assignment - // destination location during walkone, along with the index - // of the edge pointing back to this location. - dst *location - dstEdgeIdx int - - // queued is used by walkAll to track whether this location is - // in the walk queue. - queued bool - - // escapes reports whether the represented variable's address - // escapes; that is, whether the variable must be heap - // allocated. - escapes bool - - // transient reports whether the represented expression's - // address does not outlive the statement; that is, whether - // its storage can be immediately reused. - transient bool - - // paramEsc records the represented parameter's leak set. - paramEsc leaks - - captured bool // has a closure captured this variable? - reassigned bool // has this variable been reassigned? - addrtaken bool // has this variable's address been taken? -} - -// An edge represents an assignment edge between two Go variables. -type edge struct { - src *location - derefs int // >= -1 - notes *note -} - -// Fmt is called from node printing to print information about escape analysis results. -func Fmt(n ir.Node) string { - text := "" - switch n.Esc() { - case ir.EscUnknown: - break - - case ir.EscHeap: - text = "esc(h)" - - case ir.EscNone: - text = "esc(no)" - - case ir.EscNever: - text = "esc(N)" - - default: - text = fmt.Sprintf("esc(%d)", n.Esc()) - } - - if n.Op() == ir.ONAME { - n := n.(*ir.Name) - if loc, ok := n.Opt.(*location); ok && loc.loopDepth != 0 { - if text != "" { - text += " " - } - text += fmt.Sprintf("ld(%d)", loc.loopDepth) - } - } - - return text +func Funcs(all []ir.Node) { + ir.VisitFuncsBottomUp(all, Batch) } // Batch performs escape analysis on a minimal batch of @@ -342,1323 +256,6 @@ func (b *batch) flowClosure(k hole, clo *ir.ClosureExpr) { } } -// Below we implement the methods for walking the AST and recording -// data flow edges. Note that because a sub-expression might have -// side-effects, it's important to always visit the entire AST. -// -// For example, write either: -// -// if x { -// e.discard(n.Left) -// } else { -// e.value(k, n.Left) -// } -// -// or -// -// if x { -// k = e.discardHole() -// } -// e.value(k, n.Left) -// -// Do NOT write: -// -// // BAD: possibly loses side-effects within n.Left -// if !x { -// e.value(k, n.Left) -// } - -// stmt evaluates a single Go statement. -func (e *escape) stmt(n ir.Node) { - if n == nil { - return - } - - lno := ir.SetPos(n) - defer func() { - base.Pos = lno - }() - - if base.Flag.LowerM > 2 { - fmt.Printf("%v:[%d] %v stmt: %v\n", base.FmtPos(base.Pos), e.loopDepth, e.curfn, n) - } - - e.stmts(n.Init()) - - switch n.Op() { - default: - base.Fatalf("unexpected stmt: %v", n) - - case ir.ODCLCONST, ir.ODCLTYPE, ir.OFALL, ir.OINLMARK: - // nop - - case ir.OBREAK, ir.OCONTINUE, ir.OGOTO: - // TODO(mdempsky): Handle dead code? - - case ir.OBLOCK: - n := n.(*ir.BlockStmt) - e.stmts(n.List) - - case ir.ODCL: - // Record loop depth at declaration. - n := n.(*ir.Decl) - if !ir.IsBlank(n.X) { - e.dcl(n.X) - } - - case ir.OLABEL: - n := n.(*ir.LabelStmt) - switch e.labels[n.Label] { - case nonlooping: - if base.Flag.LowerM > 2 { - fmt.Printf("%v:%v non-looping label\n", base.FmtPos(base.Pos), n) - } - case looping: - if base.Flag.LowerM > 2 { - fmt.Printf("%v: %v looping label\n", base.FmtPos(base.Pos), n) - } - e.loopDepth++ - default: - base.Fatalf("label missing tag") - } - delete(e.labels, n.Label) - - case ir.OIF: - n := n.(*ir.IfStmt) - e.discard(n.Cond) - e.block(n.Body) - e.block(n.Else) - - case ir.OFOR, ir.OFORUNTIL: - n := n.(*ir.ForStmt) - e.loopDepth++ - e.discard(n.Cond) - e.stmt(n.Post) - e.block(n.Body) - e.loopDepth-- - - case ir.ORANGE: - // for Key, Value = range X { Body } - n := n.(*ir.RangeStmt) - - // X is evaluated outside the loop. - tmp := e.newLoc(nil, false) - e.expr(tmp.asHole(), n.X) - - e.loopDepth++ - ks := e.addrs([]ir.Node{n.Key, n.Value}) - if n.X.Type().IsArray() { - e.flow(ks[1].note(n, "range"), tmp) - } else { - e.flow(ks[1].deref(n, "range-deref"), tmp) - } - e.reassigned(ks, n) - - e.block(n.Body) - e.loopDepth-- - - case ir.OSWITCH: - n := n.(*ir.SwitchStmt) - - if guard, ok := n.Tag.(*ir.TypeSwitchGuard); ok { - var ks []hole - if guard.Tag != nil { - for _, cas := range n.Cases { - cv := cas.Var - k := e.dcl(cv) // type switch variables have no ODCL. - if cv.Type().HasPointers() { - ks = append(ks, k.dotType(cv.Type(), cas, "switch case")) - } - } - } - e.expr(e.teeHole(ks...), n.Tag.(*ir.TypeSwitchGuard).X) - } else { - e.discard(n.Tag) - } - - for _, cas := range n.Cases { - e.discards(cas.List) - e.block(cas.Body) - } - - case ir.OSELECT: - n := n.(*ir.SelectStmt) - for _, cas := range n.Cases { - e.stmt(cas.Comm) - e.block(cas.Body) - } - case ir.ORECV: - // TODO(mdempsky): Consider e.discard(n.Left). - n := n.(*ir.UnaryExpr) - e.exprSkipInit(e.discardHole(), n) // already visited n.Ninit - case ir.OSEND: - n := n.(*ir.SendStmt) - e.discard(n.Chan) - e.assignHeap(n.Value, "send", n) - - case ir.OAS: - n := n.(*ir.AssignStmt) - e.assignList([]ir.Node{n.X}, []ir.Node{n.Y}, "assign", n) - case ir.OASOP: - n := n.(*ir.AssignOpStmt) - // TODO(mdempsky): Worry about OLSH/ORSH? - e.assignList([]ir.Node{n.X}, []ir.Node{n.Y}, "assign", n) - case ir.OAS2: - n := n.(*ir.AssignListStmt) - e.assignList(n.Lhs, n.Rhs, "assign-pair", n) - - case ir.OAS2DOTTYPE: // v, ok = x.(type) - n := n.(*ir.AssignListStmt) - e.assignList(n.Lhs, n.Rhs, "assign-pair-dot-type", n) - case ir.OAS2MAPR: // v, ok = m[k] - n := n.(*ir.AssignListStmt) - e.assignList(n.Lhs, n.Rhs, "assign-pair-mapr", n) - case ir.OAS2RECV, ir.OSELRECV2: // v, ok = <-ch - n := n.(*ir.AssignListStmt) - e.assignList(n.Lhs, n.Rhs, "assign-pair-receive", n) - - case ir.OAS2FUNC: - n := n.(*ir.AssignListStmt) - e.stmts(n.Rhs[0].Init()) - ks := e.addrs(n.Lhs) - e.call(ks, n.Rhs[0], nil) - e.reassigned(ks, n) - case ir.ORETURN: - n := n.(*ir.ReturnStmt) - results := e.curfn.Type().Results().FieldSlice() - dsts := make([]ir.Node, len(results)) - for i, res := range results { - dsts[i] = res.Nname.(*ir.Name) - } - e.assignList(dsts, n.Results, "return", n) - case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER, ir.OCLOSE, ir.OCOPY, ir.ODELETE, ir.OPANIC, ir.OPRINT, ir.OPRINTN, ir.ORECOVER: - e.call(nil, n, nil) - case ir.OGO, ir.ODEFER: - n := n.(*ir.GoDeferStmt) - e.stmts(n.Call.Init()) - e.call(nil, n.Call, n) - - case ir.OTAILCALL: - // TODO(mdempsky): Treat like a normal call? esc.go used to just ignore it. - } -} - -func (e *escape) stmts(l ir.Nodes) { - for _, n := range l { - e.stmt(n) - } -} - -// block is like stmts, but preserves loopDepth. -func (e *escape) block(l ir.Nodes) { - old := e.loopDepth - e.stmts(l) - e.loopDepth = old -} - -// expr models evaluating an expression n and flowing the result into -// hole k. -func (e *escape) expr(k hole, n ir.Node) { - if n == nil { - return - } - e.stmts(n.Init()) - e.exprSkipInit(k, n) -} - -func (e *escape) exprSkipInit(k hole, n ir.Node) { - if n == nil { - return - } - - lno := ir.SetPos(n) - defer func() { - base.Pos = lno - }() - - uintptrEscapesHack := k.uintptrEscapesHack - k.uintptrEscapesHack = false - - if uintptrEscapesHack && n.Op() == ir.OCONVNOP && n.(*ir.ConvExpr).X.Type().IsUnsafePtr() { - // nop - } else if k.derefs >= 0 && !n.Type().HasPointers() { - k.dst = &e.blankLoc - } - - switch n.Op() { - default: - base.Fatalf("unexpected expr: %s %v", n.Op().String(), n) - - case ir.OLITERAL, ir.ONIL, ir.OGETG, ir.OTYPE, ir.OMETHEXPR, ir.OLINKSYMOFFSET: - // nop - - case ir.ONAME: - n := n.(*ir.Name) - if n.Class == ir.PFUNC || n.Class == ir.PEXTERN { - return - } - if n.IsClosureVar() && n.Defn == nil { - return // ".this" from method value wrapper - } - e.flow(k, e.oldLoc(n)) - - case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT: - n := n.(*ir.UnaryExpr) - e.discard(n.X) - case ir.OADD, ir.OSUB, ir.OOR, ir.OXOR, ir.OMUL, ir.ODIV, ir.OMOD, ir.OLSH, ir.ORSH, ir.OAND, ir.OANDNOT, ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE: - n := n.(*ir.BinaryExpr) - e.discard(n.X) - e.discard(n.Y) - case ir.OANDAND, ir.OOROR: - n := n.(*ir.LogicalExpr) - e.discard(n.X) - e.discard(n.Y) - case ir.OADDR: - n := n.(*ir.AddrExpr) - e.expr(k.addr(n, "address-of"), n.X) // "address-of" - case ir.ODEREF: - n := n.(*ir.StarExpr) - e.expr(k.deref(n, "indirection"), n.X) // "indirection" - case ir.ODOT, ir.ODOTMETH, ir.ODOTINTER: - n := n.(*ir.SelectorExpr) - e.expr(k.note(n, "dot"), n.X) - case ir.ODOTPTR: - n := n.(*ir.SelectorExpr) - e.expr(k.deref(n, "dot of pointer"), n.X) // "dot of pointer" - case ir.ODOTTYPE, ir.ODOTTYPE2: - n := n.(*ir.TypeAssertExpr) - e.expr(k.dotType(n.Type(), n, "dot"), n.X) - case ir.OINDEX: - n := n.(*ir.IndexExpr) - if n.X.Type().IsArray() { - e.expr(k.note(n, "fixed-array-index-of"), n.X) - } else { - // TODO(mdempsky): Fix why reason text. - e.expr(k.deref(n, "dot of pointer"), n.X) - } - e.discard(n.Index) - case ir.OINDEXMAP: - n := n.(*ir.IndexExpr) - e.discard(n.X) - e.discard(n.Index) - case ir.OSLICE, ir.OSLICEARR, ir.OSLICE3, ir.OSLICE3ARR, ir.OSLICESTR: - n := n.(*ir.SliceExpr) - e.expr(k.note(n, "slice"), n.X) - e.discard(n.Low) - e.discard(n.High) - e.discard(n.Max) - - case ir.OCONV, ir.OCONVNOP: - n := n.(*ir.ConvExpr) - if ir.ShouldCheckPtr(e.curfn, 2) && n.Type().IsUnsafePtr() && n.X.Type().IsPtr() { - // When -d=checkptr=2 is enabled, treat - // conversions to unsafe.Pointer as an - // escaping operation. This allows better - // runtime instrumentation, since we can more - // easily detect object boundaries on the heap - // than the stack. - e.assignHeap(n.X, "conversion to unsafe.Pointer", n) - } else if n.Type().IsUnsafePtr() && n.X.Type().IsUintptr() { - e.unsafeValue(k, n.X) - } else { - e.expr(k, n.X) - } - case ir.OCONVIFACE: - n := n.(*ir.ConvExpr) - if !n.X.Type().IsInterface() && !types.IsDirectIface(n.X.Type()) { - k = e.spill(k, n) - } - e.expr(k.note(n, "interface-converted"), n.X) - case ir.OEFACE: - n := n.(*ir.BinaryExpr) - // Note: n.X is not needed because it can never point to memory that might escape. - e.expr(k, n.Y) - case ir.OIDATA, ir.OSPTR: - n := n.(*ir.UnaryExpr) - e.expr(k, n.X) - case ir.OSLICE2ARRPTR: - // the slice pointer flows directly to the result - n := n.(*ir.ConvExpr) - e.expr(k, n.X) - case ir.ORECV: - n := n.(*ir.UnaryExpr) - e.discard(n.X) - - case ir.OCALLMETH, ir.OCALLFUNC, ir.OCALLINTER, ir.OLEN, ir.OCAP, ir.OCOMPLEX, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.OCOPY, ir.OUNSAFEADD, ir.OUNSAFESLICE: - e.call([]hole{k}, n, nil) - - case ir.ONEW: - n := n.(*ir.UnaryExpr) - e.spill(k, n) - - case ir.OMAKESLICE: - n := n.(*ir.MakeExpr) - e.spill(k, n) - e.discard(n.Len) - e.discard(n.Cap) - case ir.OMAKECHAN: - n := n.(*ir.MakeExpr) - e.discard(n.Len) - case ir.OMAKEMAP: - n := n.(*ir.MakeExpr) - e.spill(k, n) - e.discard(n.Len) - - case ir.ORECOVER: - // nop - - case ir.OCALLPART: - // Flow the receiver argument to both the closure and - // to the receiver parameter. - - n := n.(*ir.SelectorExpr) - closureK := e.spill(k, n) - - m := n.Selection - - // We don't know how the method value will be called - // later, so conservatively assume the result - // parameters all flow to the heap. - // - // TODO(mdempsky): Change ks into a callback, so that - // we don't have to create this slice? - var ks []hole - for i := m.Type.NumResults(); i > 0; i-- { - ks = append(ks, e.heapHole()) - } - name, _ := m.Nname.(*ir.Name) - paramK := e.tagHole(ks, name, m.Type.Recv()) - - e.expr(e.teeHole(paramK, closureK), n.X) - - case ir.OPTRLIT: - n := n.(*ir.AddrExpr) - e.expr(e.spill(k, n), n.X) - - case ir.OARRAYLIT: - n := n.(*ir.CompLitExpr) - for _, elt := range n.List { - if elt.Op() == ir.OKEY { - elt = elt.(*ir.KeyExpr).Value - } - e.expr(k.note(n, "array literal element"), elt) - } - - case ir.OSLICELIT: - n := n.(*ir.CompLitExpr) - k = e.spill(k, n) - k.uintptrEscapesHack = uintptrEscapesHack // for ...uintptr parameters - - for _, elt := range n.List { - if elt.Op() == ir.OKEY { - elt = elt.(*ir.KeyExpr).Value - } - e.expr(k.note(n, "slice-literal-element"), elt) - } - - case ir.OSTRUCTLIT: - n := n.(*ir.CompLitExpr) - for _, elt := range n.List { - e.expr(k.note(n, "struct literal element"), elt.(*ir.StructKeyExpr).Value) - } - - case ir.OMAPLIT: - n := n.(*ir.CompLitExpr) - e.spill(k, n) - - // Map keys and values are always stored in the heap. - for _, elt := range n.List { - elt := elt.(*ir.KeyExpr) - e.assignHeap(elt.Key, "map literal key", n) - e.assignHeap(elt.Value, "map literal value", n) - } - - case ir.OCLOSURE: - n := n.(*ir.ClosureExpr) - k = e.spill(k, n) - e.closures = append(e.closures, closure{k, n}) - - if fn := n.Func; fn.IsHiddenClosure() { - for _, cv := range fn.ClosureVars { - if loc := e.oldLoc(cv); !loc.captured { - loc.captured = true - - // Ignore reassignments to the variable in straightline code - // preceding the first capture by a closure. - if loc.loopDepth == e.loopDepth { - loc.reassigned = false - } - } - } - - for _, n := range fn.Dcl { - // Add locations for local variables of the - // closure, if needed, in case we're not including - // the closure func in the batch for escape - // analysis (happens for escape analysis called - // from reflectdata.methodWrapper) - if n.Op() == ir.ONAME && n.Opt == nil { - e.with(fn).newLoc(n, false) - } - } - e.walkFunc(fn) - } - - case ir.ORUNES2STR, ir.OBYTES2STR, ir.OSTR2RUNES, ir.OSTR2BYTES, ir.ORUNESTR: - n := n.(*ir.ConvExpr) - e.spill(k, n) - e.discard(n.X) - - case ir.OADDSTR: - n := n.(*ir.AddStringExpr) - e.spill(k, n) - - // Arguments of OADDSTR never escape; - // runtime.concatstrings makes sure of that. - e.discards(n.List) - } -} - -// unsafeValue evaluates a uintptr-typed arithmetic expression looking -// for conversions from an unsafe.Pointer. -func (e *escape) unsafeValue(k hole, n ir.Node) { - if n.Type().Kind() != types.TUINTPTR { - base.Fatalf("unexpected type %v for %v", n.Type(), n) - } - if k.addrtaken { - base.Fatalf("unexpected addrtaken") - } - - e.stmts(n.Init()) - - switch n.Op() { - case ir.OCONV, ir.OCONVNOP: - n := n.(*ir.ConvExpr) - if n.X.Type().IsUnsafePtr() { - e.expr(k, n.X) - } else { - e.discard(n.X) - } - case ir.ODOTPTR: - n := n.(*ir.SelectorExpr) - if ir.IsReflectHeaderDataField(n) { - e.expr(k.deref(n, "reflect.Header.Data"), n.X) - } else { - e.discard(n.X) - } - case ir.OPLUS, ir.ONEG, ir.OBITNOT: - n := n.(*ir.UnaryExpr) - e.unsafeValue(k, n.X) - case ir.OADD, ir.OSUB, ir.OOR, ir.OXOR, ir.OMUL, ir.ODIV, ir.OMOD, ir.OAND, ir.OANDNOT: - n := n.(*ir.BinaryExpr) - e.unsafeValue(k, n.X) - e.unsafeValue(k, n.Y) - case ir.OLSH, ir.ORSH: - n := n.(*ir.BinaryExpr) - e.unsafeValue(k, n.X) - // RHS need not be uintptr-typed (#32959) and can't meaningfully - // flow pointers anyway. - e.discard(n.Y) - default: - e.exprSkipInit(e.discardHole(), n) - } -} - -// discard evaluates an expression n for side-effects, but discards -// its value. -func (e *escape) discard(n ir.Node) { - e.expr(e.discardHole(), n) -} - -func (e *escape) discards(l ir.Nodes) { - for _, n := range l { - e.discard(n) - } -} - -// addr evaluates an addressable expression n and returns a hole -// that represents storing into the represented location. -func (e *escape) addr(n ir.Node) hole { - if n == nil || ir.IsBlank(n) { - // Can happen in select case, range, maybe others. - return e.discardHole() - } - - k := e.heapHole() - - switch n.Op() { - default: - base.Fatalf("unexpected addr: %v", n) - case ir.ONAME: - n := n.(*ir.Name) - if n.Class == ir.PEXTERN { - break - } - k = e.oldLoc(n).asHole() - case ir.OLINKSYMOFFSET: - break - case ir.ODOT: - n := n.(*ir.SelectorExpr) - k = e.addr(n.X) - case ir.OINDEX: - n := n.(*ir.IndexExpr) - e.discard(n.Index) - if n.X.Type().IsArray() { - k = e.addr(n.X) - } else { - e.discard(n.X) - } - case ir.ODEREF, ir.ODOTPTR: - e.discard(n) - case ir.OINDEXMAP: - n := n.(*ir.IndexExpr) - e.discard(n.X) - e.assignHeap(n.Index, "key of map put", n) - } - - return k -} - -func (e *escape) addrs(l ir.Nodes) []hole { - var ks []hole - for _, n := range l { - ks = append(ks, e.addr(n)) - } - return ks -} - -// reassigned marks the locations associated with the given holes as -// reassigned, unless the location represents a variable declared and -// assigned exactly once by where. -func (e *escape) reassigned(ks []hole, where ir.Node) { - if as, ok := where.(*ir.AssignStmt); ok && as.Op() == ir.OAS && as.Y == nil { - if dst, ok := as.X.(*ir.Name); ok && dst.Op() == ir.ONAME && dst.Defn == nil { - // Zero-value assignment for variable declared without an - // explicit initial value. Assume this is its initialization - // statement. - return - } - } - - for _, k := range ks { - loc := k.dst - // Variables declared by range statements are assigned on every iteration. - if n, ok := loc.n.(*ir.Name); ok && n.Defn == where && where.Op() != ir.ORANGE { - continue - } - loc.reassigned = true - } -} - -// assignList evaluates the assignment dsts... = srcs.... -func (e *escape) assignList(dsts, srcs []ir.Node, why string, where ir.Node) { - ks := e.addrs(dsts) - for i, k := range ks { - var src ir.Node - if i < len(srcs) { - src = srcs[i] - } - - if dst := dsts[i]; dst != nil { - // Detect implicit conversion of uintptr to unsafe.Pointer when - // storing into reflect.{Slice,String}Header. - if dst.Op() == ir.ODOTPTR && ir.IsReflectHeaderDataField(dst) { - e.unsafeValue(e.heapHole().note(where, why), src) - continue - } - - // Filter out some no-op assignments for escape analysis. - if src != nil && isSelfAssign(dst, src) { - if base.Flag.LowerM != 0 { - base.WarnfAt(where.Pos(), "%v ignoring self-assignment in %v", e.curfn, where) - } - k = e.discardHole() - } - } - - e.expr(k.note(where, why), src) - } - - e.reassigned(ks, where) -} - -func (e *escape) assignHeap(src ir.Node, why string, where ir.Node) { - e.expr(e.heapHole().note(where, why), src) -} - -// call evaluates a call expressions, including builtin calls. ks -// should contain the holes representing where the function callee's -// results flows; where is the OGO/ODEFER context of the call, if any. -func (e *escape) call(ks []hole, call, where ir.Node) { - topLevelDefer := where != nil && where.Op() == ir.ODEFER && e.loopDepth == 1 - if topLevelDefer { - // force stack allocation of defer record, unless - // open-coded defers are used (see ssa.go) - where.SetEsc(ir.EscNever) - } - - argument := func(k hole, arg ir.Node) { - if topLevelDefer { - // Top level defers arguments don't escape to - // heap, but they do need to last until end of - // function. - k = e.later(k) - } else if where != nil { - k = e.heapHole() - } - - e.expr(k.note(call, "call parameter"), arg) - } - - switch call.Op() { - default: - ir.Dump("esc", call) - base.Fatalf("unexpected call op: %v", call.Op()) - - case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER: - call := call.(*ir.CallExpr) - typecheck.FixVariadicCall(call) - - // Pick out the function callee, if statically known. - var fn *ir.Name - switch call.Op() { - case ir.OCALLFUNC: - switch v := ir.StaticValue(call.X); { - case v.Op() == ir.ONAME && v.(*ir.Name).Class == ir.PFUNC: - fn = v.(*ir.Name) - case v.Op() == ir.OCLOSURE: - fn = v.(*ir.ClosureExpr).Func.Nname - } - case ir.OCALLMETH: - fn = ir.MethodExprName(call.X) - } - - fntype := call.X.Type() - if fn != nil { - fntype = fn.Type() - } - - if ks != nil && fn != nil && e.inMutualBatch(fn) { - for i, result := range fn.Type().Results().FieldSlice() { - e.expr(ks[i], ir.AsNode(result.Nname)) - } - } - - if r := fntype.Recv(); r != nil { - argument(e.tagHole(ks, fn, r), call.X.(*ir.SelectorExpr).X) - } else { - // Evaluate callee function expression. - argument(e.discardHole(), call.X) - } - - args := call.Args - for i, param := range fntype.Params().FieldSlice() { - argument(e.tagHole(ks, fn, param), args[i]) - } - - case ir.OAPPEND: - call := call.(*ir.CallExpr) - args := call.Args - - // Appendee slice may flow directly to the result, if - // it has enough capacity. Alternatively, a new heap - // slice might be allocated, and all slice elements - // might flow to heap. - appendeeK := ks[0] - if args[0].Type().Elem().HasPointers() { - appendeeK = e.teeHole(appendeeK, e.heapHole().deref(call, "appendee slice")) - } - argument(appendeeK, args[0]) - - if call.IsDDD { - appendedK := e.discardHole() - if args[1].Type().IsSlice() && args[1].Type().Elem().HasPointers() { - appendedK = e.heapHole().deref(call, "appended slice...") - } - argument(appendedK, args[1]) - } else { - for _, arg := range args[1:] { - argument(e.heapHole(), arg) - } - } - - case ir.OCOPY: - call := call.(*ir.BinaryExpr) - argument(e.discardHole(), call.X) - - copiedK := e.discardHole() - if call.Y.Type().IsSlice() && call.Y.Type().Elem().HasPointers() { - copiedK = e.heapHole().deref(call, "copied slice") - } - argument(copiedK, call.Y) - - case ir.OPANIC: - call := call.(*ir.UnaryExpr) - argument(e.heapHole(), call.X) - - case ir.OCOMPLEX: - call := call.(*ir.BinaryExpr) - argument(e.discardHole(), call.X) - argument(e.discardHole(), call.Y) - case ir.ODELETE, ir.OPRINT, ir.OPRINTN, ir.ORECOVER: - call := call.(*ir.CallExpr) - for _, arg := range call.Args { - argument(e.discardHole(), arg) - } - case ir.OLEN, ir.OCAP, ir.OREAL, ir.OIMAG, ir.OCLOSE: - call := call.(*ir.UnaryExpr) - argument(e.discardHole(), call.X) - - case ir.OUNSAFEADD, ir.OUNSAFESLICE: - call := call.(*ir.BinaryExpr) - argument(ks[0], call.X) - argument(e.discardHole(), call.Y) - } -} - -// tagHole returns a hole for evaluating an argument passed to param. -// ks should contain the holes representing where the function -// callee's results flows. fn is the statically-known callee function, -// if any. -func (e *escape) tagHole(ks []hole, fn *ir.Name, param *types.Field) hole { - // If this is a dynamic call, we can't rely on param.Note. - if fn == nil { - return e.heapHole() - } - - if e.inMutualBatch(fn) { - return e.addr(ir.AsNode(param.Nname)) - } - - // Call to previously tagged function. - - if fn.Func != nil && fn.Func.Pragma&ir.UintptrEscapes != 0 && (param.Type.IsUintptr() || param.IsDDD() && param.Type.Elem().IsUintptr()) { - k := e.heapHole() - k.uintptrEscapesHack = true - return k - } - - var tagKs []hole - - esc := parseLeaks(param.Note) - if x := esc.Heap(); x >= 0 { - tagKs = append(tagKs, e.heapHole().shift(x)) - } - - if ks != nil { - for i := 0; i < numEscResults; i++ { - if x := esc.Result(i); x >= 0 { - tagKs = append(tagKs, ks[i].shift(x)) - } - } - } - - return e.teeHole(tagKs...) -} - -// inMutualBatch reports whether function fn is in the batch of -// mutually recursive functions being analyzed. When this is true, -// fn has not yet been analyzed, so its parameters and results -// should be incorporated directly into the flow graph instead of -// relying on its escape analysis tagging. -func (e *escape) inMutualBatch(fn *ir.Name) bool { - if fn.Defn != nil && fn.Defn.Esc() < escFuncTagged { - if fn.Defn.Esc() == escFuncUnknown { - base.Fatalf("graph inconsistency: %v", fn) - } - return true - } - return false -} - -// An hole represents a context for evaluation a Go -// expression. E.g., when evaluating p in "x = **p", we'd have a hole -// with dst==x and derefs==2. -type hole struct { - dst *location - derefs int // >= -1 - notes *note - - // addrtaken indicates whether this context is taking the address of - // the expression, independent of whether the address will actually - // be stored into a variable. - addrtaken bool - - // uintptrEscapesHack indicates this context is evaluating an - // argument for a //go:uintptrescapes function. - uintptrEscapesHack bool -} - -type note struct { - next *note - where ir.Node - why string -} - -func (k hole) note(where ir.Node, why string) hole { - if where == nil || why == "" { - base.Fatalf("note: missing where/why") - } - if base.Flag.LowerM >= 2 || logopt.Enabled() { - k.notes = ¬e{ - next: k.notes, - where: where, - why: why, - } - } - return k -} - -func (k hole) shift(delta int) hole { - k.derefs += delta - if k.derefs < -1 { - base.Fatalf("derefs underflow: %v", k.derefs) - } - k.addrtaken = delta < 0 - return k -} - -func (k hole) deref(where ir.Node, why string) hole { return k.shift(1).note(where, why) } -func (k hole) addr(where ir.Node, why string) hole { return k.shift(-1).note(where, why) } - -func (k hole) dotType(t *types.Type, where ir.Node, why string) hole { - if !t.IsInterface() && !types.IsDirectIface(t) { - k = k.shift(1) - } - return k.note(where, why) -} - -// teeHole returns a new hole that flows into each hole of ks, -// similar to the Unix tee(1) command. -func (e *escape) teeHole(ks ...hole) hole { - if len(ks) == 0 { - return e.discardHole() - } - if len(ks) == 1 { - return ks[0] - } - // TODO(mdempsky): Optimize if there's only one non-discard hole? - - // Given holes "l1 = _", "l2 = **_", "l3 = *_", ..., create a - // new temporary location ltmp, wire it into place, and return - // a hole for "ltmp = _". - loc := e.newLoc(nil, true) - for _, k := range ks { - // N.B., "p = &q" and "p = &tmp; tmp = q" are not - // semantically equivalent. To combine holes like "l1 - // = _" and "l2 = &_", we'd need to wire them as "l1 = - // *ltmp" and "l2 = ltmp" and return "ltmp = &_" - // instead. - if k.derefs < 0 { - base.Fatalf("teeHole: negative derefs") - } - - e.flow(k, loc) - } - return loc.asHole() -} - -func (e *escape) dcl(n *ir.Name) hole { - if n.Curfn != e.curfn || n.IsClosureVar() { - base.Fatalf("bad declaration of %v", n) - } - loc := e.oldLoc(n) - loc.loopDepth = e.loopDepth - return loc.asHole() -} - -// spill allocates a new location associated with expression n, flows -// its address to k, and returns a hole that flows values to it. It's -// intended for use with most expressions that allocate storage. -func (e *escape) spill(k hole, n ir.Node) hole { - loc := e.newLoc(n, true) - e.flow(k.addr(n, "spill"), loc) - return loc.asHole() -} - -// later returns a new hole that flows into k, but some time later. -// Its main effect is to prevent immediate reuse of temporary -// variables introduced during Order. -func (e *escape) later(k hole) hole { - loc := e.newLoc(nil, false) - e.flow(k, loc) - return loc.asHole() -} - -func (e *escape) newLoc(n ir.Node, transient bool) *location { - if e.curfn == nil { - base.Fatalf("e.curfn isn't set") - } - if n != nil && n.Type() != nil && n.Type().NotInHeap() { - base.ErrorfAt(n.Pos(), "%v is incomplete (or unallocatable); stack allocation disallowed", n.Type()) - } - - if n != nil && n.Op() == ir.ONAME { - n = n.(*ir.Name).Canonical() - } - loc := &location{ - n: n, - curfn: e.curfn, - loopDepth: e.loopDepth, - transient: transient, - } - e.allLocs = append(e.allLocs, loc) - if n != nil { - if n.Op() == ir.ONAME { - n := n.(*ir.Name) - if n.Curfn != e.curfn { - base.Fatalf("curfn mismatch: %v != %v for %v", n.Curfn, e.curfn, n) - } - - if n.Opt != nil { - base.Fatalf("%v already has a location", n) - } - n.Opt = loc - } - } - return loc -} - -func (b *batch) oldLoc(n *ir.Name) *location { - if n.Canonical().Opt == nil { - base.Fatalf("%v has no location", n) - } - return n.Canonical().Opt.(*location) -} - -func (l *location) asHole() hole { - return hole{dst: l} -} - -func (b *batch) flow(k hole, src *location) { - if k.addrtaken { - src.addrtaken = true - } - - dst := k.dst - if dst == &b.blankLoc { - return - } - if dst == src && k.derefs >= 0 { // dst = dst, dst = *dst, ... - return - } - if dst.escapes && k.derefs < 0 { // dst = &src - if base.Flag.LowerM >= 2 || logopt.Enabled() { - pos := base.FmtPos(src.n.Pos()) - if base.Flag.LowerM >= 2 { - fmt.Printf("%s: %v escapes to heap:\n", pos, src.n) - } - explanation := b.explainFlow(pos, dst, src, k.derefs, k.notes, []*logopt.LoggedOpt{}) - if logopt.Enabled() { - var e_curfn *ir.Func // TODO(mdempsky): Fix. - logopt.LogOpt(src.n.Pos(), "escapes", "escape", ir.FuncName(e_curfn), fmt.Sprintf("%v escapes to heap", src.n), explanation) - } - - } - src.escapes = true - return - } - - // TODO(mdempsky): Deduplicate edges? - dst.edges = append(dst.edges, edge{src: src, derefs: k.derefs, notes: k.notes}) -} - -func (b *batch) heapHole() hole { return b.heapLoc.asHole() } -func (b *batch) discardHole() hole { return b.blankLoc.asHole() } - -// walkAll computes the minimal dereferences between all pairs of -// locations. -func (b *batch) walkAll() { - // We use a work queue to keep track of locations that we need - // to visit, and repeatedly walk until we reach a fixed point. - // - // We walk once from each location (including the heap), and - // then re-enqueue each location on its transition from - // transient->!transient and !escapes->escapes, which can each - // happen at most once. So we take Θ(len(e.allLocs)) walks. - - // LIFO queue, has enough room for e.allLocs and e.heapLoc. - todo := make([]*location, 0, len(b.allLocs)+1) - enqueue := func(loc *location) { - if !loc.queued { - todo = append(todo, loc) - loc.queued = true - } - } - - for _, loc := range b.allLocs { - enqueue(loc) - } - enqueue(&b.heapLoc) - - var walkgen uint32 - for len(todo) > 0 { - root := todo[len(todo)-1] - todo = todo[:len(todo)-1] - root.queued = false - - walkgen++ - b.walkOne(root, walkgen, enqueue) - } -} - -// walkOne computes the minimal number of dereferences from root to -// all other locations. -func (b *batch) walkOne(root *location, walkgen uint32, enqueue func(*location)) { - // The data flow graph has negative edges (from addressing - // operations), so we use the Bellman-Ford algorithm. However, - // we don't have to worry about infinite negative cycles since - // we bound intermediate dereference counts to 0. - - root.walkgen = walkgen - root.derefs = 0 - root.dst = nil - - todo := []*location{root} // LIFO queue - for len(todo) > 0 { - l := todo[len(todo)-1] - todo = todo[:len(todo)-1] - - derefs := l.derefs - - // If l.derefs < 0, then l's address flows to root. - addressOf := derefs < 0 - if addressOf { - // For a flow path like "root = &l; l = x", - // l's address flows to root, but x's does - // not. We recognize this by lower bounding - // derefs at 0. - derefs = 0 - - // If l's address flows to a non-transient - // location, then l can't be transiently - // allocated. - if !root.transient && l.transient { - l.transient = false - enqueue(l) - } - } - - if b.outlives(root, l) { - // l's value flows to root. If l is a function - // parameter and root is the heap or a - // corresponding result parameter, then record - // that value flow for tagging the function - // later. - if l.isName(ir.PPARAM) { - if (logopt.Enabled() || base.Flag.LowerM >= 2) && !l.escapes { - if base.Flag.LowerM >= 2 { - fmt.Printf("%s: parameter %v leaks to %s with derefs=%d:\n", base.FmtPos(l.n.Pos()), l.n, b.explainLoc(root), derefs) - } - explanation := b.explainPath(root, l) - if logopt.Enabled() { - var e_curfn *ir.Func // TODO(mdempsky): Fix. - logopt.LogOpt(l.n.Pos(), "leak", "escape", ir.FuncName(e_curfn), - fmt.Sprintf("parameter %v leaks to %s with derefs=%d", l.n, b.explainLoc(root), derefs), explanation) - } - } - l.leakTo(root, derefs) - } - - // If l's address flows somewhere that - // outlives it, then l needs to be heap - // allocated. - if addressOf && !l.escapes { - if logopt.Enabled() || base.Flag.LowerM >= 2 { - if base.Flag.LowerM >= 2 { - fmt.Printf("%s: %v escapes to heap:\n", base.FmtPos(l.n.Pos()), l.n) - } - explanation := b.explainPath(root, l) - if logopt.Enabled() { - var e_curfn *ir.Func // TODO(mdempsky): Fix. - logopt.LogOpt(l.n.Pos(), "escape", "escape", ir.FuncName(e_curfn), fmt.Sprintf("%v escapes to heap", l.n), explanation) - } - } - l.escapes = true - enqueue(l) - continue - } - } - - for i, edge := range l.edges { - if edge.src.escapes { - continue - } - d := derefs + edge.derefs - if edge.src.walkgen != walkgen || edge.src.derefs > d { - edge.src.walkgen = walkgen - edge.src.derefs = d - edge.src.dst = l - edge.src.dstEdgeIdx = i - todo = append(todo, edge.src) - } - } - } -} - -// explainPath prints an explanation of how src flows to the walk root. -func (b *batch) explainPath(root, src *location) []*logopt.LoggedOpt { - visited := make(map[*location]bool) - pos := base.FmtPos(src.n.Pos()) - var explanation []*logopt.LoggedOpt - for { - // Prevent infinite loop. - if visited[src] { - if base.Flag.LowerM >= 2 { - fmt.Printf("%s: warning: truncated explanation due to assignment cycle; see golang.org/issue/35518\n", pos) - } - break - } - visited[src] = true - dst := src.dst - edge := &dst.edges[src.dstEdgeIdx] - if edge.src != src { - base.Fatalf("path inconsistency: %v != %v", edge.src, src) - } - - explanation = b.explainFlow(pos, dst, src, edge.derefs, edge.notes, explanation) - - if dst == root { - break - } - src = dst - } - - return explanation -} - -func (b *batch) explainFlow(pos string, dst, srcloc *location, derefs int, notes *note, explanation []*logopt.LoggedOpt) []*logopt.LoggedOpt { - ops := "&" - if derefs >= 0 { - ops = strings.Repeat("*", derefs) - } - print := base.Flag.LowerM >= 2 - - flow := fmt.Sprintf(" flow: %s = %s%v:", b.explainLoc(dst), ops, b.explainLoc(srcloc)) - if print { - fmt.Printf("%s:%s\n", pos, flow) - } - if logopt.Enabled() { - var epos src.XPos - if notes != nil { - epos = notes.where.Pos() - } else if srcloc != nil && srcloc.n != nil { - epos = srcloc.n.Pos() - } - var e_curfn *ir.Func // TODO(mdempsky): Fix. - explanation = append(explanation, logopt.NewLoggedOpt(epos, "escflow", "escape", ir.FuncName(e_curfn), flow)) - } - - for note := notes; note != nil; note = note.next { - if print { - fmt.Printf("%s: from %v (%v) at %s\n", pos, note.where, note.why, base.FmtPos(note.where.Pos())) - } - if logopt.Enabled() { - var e_curfn *ir.Func // TODO(mdempsky): Fix. - explanation = append(explanation, logopt.NewLoggedOpt(note.where.Pos(), "escflow", "escape", ir.FuncName(e_curfn), - fmt.Sprintf(" from %v (%v)", note.where, note.why))) - } - } - return explanation -} - -func (b *batch) explainLoc(l *location) string { - if l == &b.heapLoc { - return "{heap}" - } - if l.n == nil { - // TODO(mdempsky): Omit entirely. - return "{temp}" - } - if l.n.Op() == ir.ONAME { - return fmt.Sprintf("%v", l.n) - } - return fmt.Sprintf("{storage for %v}", l.n) -} - -// outlives reports whether values stored in l may survive beyond -// other's lifetime if stack allocated. -func (b *batch) outlives(l, other *location) bool { - // The heap outlives everything. - if l.escapes { - return true - } - - // We don't know what callers do with returned values, so - // pessimistically we need to assume they flow to the heap and - // outlive everything too. - if l.isName(ir.PPARAMOUT) { - // Exception: Directly called closures can return - // locations allocated outside of them without forcing - // them to the heap. For example: - // - // var u int // okay to stack allocate - // *(func() *int { return &u }()) = 42 - if containsClosure(other.curfn, l.curfn) && l.curfn.ClosureCalled() { - return false - } - - return true - } - - // If l and other are within the same function, then l - // outlives other if it was declared outside other's loop - // scope. For example: - // - // var l *int - // for { - // l = new(int) - // } - if l.curfn == other.curfn && l.loopDepth < other.loopDepth { - return true - } - - // If other is declared within a child closure of where l is - // declared, then l outlives it. For example: - // - // var l *int - // func() { - // l = new(int) - // } - if containsClosure(l.curfn, other.curfn) { - return true - } - - return false -} - -// containsClosure reports whether c is a closure contained within f. -func containsClosure(f, c *ir.Func) bool { - // Common case. - if f == c { - return false - } - - // Closures within function Foo are named like "Foo.funcN..." - // TODO(mdempsky): Better way to recognize this. - fn := f.Sym().Name - cn := c.Sym().Name - return len(cn) > len(fn) && cn[:len(fn)] == fn && cn[len(fn)] == '.' -} - -// leak records that parameter l leaks to sink. -func (l *location) leakTo(sink *location, derefs int) { - // If sink is a result parameter that doesn't escape (#44614) - // and we can fit return bits into the escape analysis tag, - // then record as a result leak. - if !sink.escapes && sink.isName(ir.PPARAMOUT) && sink.curfn == l.curfn { - ri := sink.resultIndex - 1 - if ri < numEscResults { - // Leak to result parameter. - l.paramEsc.AddResult(ri, derefs) - return - } - } - - // Otherwise, record as heap leak. - l.paramEsc.AddHeap(derefs) -} - func (b *batch) finish(fns []*ir.Func) { // Record parameter tags for package export data. for _, fn := range fns { @@ -1725,107 +322,19 @@ func (b *batch) finish(fns []*ir.Func) { } } -func (l *location) isName(c ir.Class) bool { - return l.n != nil && l.n.Op() == ir.ONAME && l.n.(*ir.Name).Class == c -} - -const numEscResults = 7 - -// An leaks represents a set of assignment flows from a parameter -// to the heap or to any of its function's (first numEscResults) -// result parameters. -type leaks [1 + numEscResults]uint8 - -// Empty reports whether l is an empty set (i.e., no assignment flows). -func (l leaks) Empty() bool { return l == leaks{} } - -// Heap returns the minimum deref count of any assignment flow from l -// to the heap. If no such flows exist, Heap returns -1. -func (l leaks) Heap() int { return l.get(0) } - -// Result returns the minimum deref count of any assignment flow from -// l to its function's i'th result parameter. If no such flows exist, -// Result returns -1. -func (l leaks) Result(i int) int { return l.get(1 + i) } - -// AddHeap adds an assignment flow from l to the heap. -func (l *leaks) AddHeap(derefs int) { l.add(0, derefs) } - -// AddResult adds an assignment flow from l to its function's i'th -// result parameter. -func (l *leaks) AddResult(i, derefs int) { l.add(1+i, derefs) } - -func (l *leaks) setResult(i, derefs int) { l.set(1+i, derefs) } - -func (l leaks) get(i int) int { return int(l[i]) - 1 } - -func (l *leaks) add(i, derefs int) { - if old := l.get(i); old < 0 || derefs < old { - l.set(i, derefs) - } -} - -func (l *leaks) set(i, derefs int) { - v := derefs + 1 - if v < 0 { - base.Fatalf("invalid derefs count: %v", derefs) - } - if v > math.MaxUint8 { - v = math.MaxUint8 - } - - l[i] = uint8(v) -} - -// Optimize removes result flow paths that are equal in length or -// longer than the shortest heap flow path. -func (l *leaks) Optimize() { - // If we have a path to the heap, then there's no use in - // keeping equal or longer paths elsewhere. - if x := l.Heap(); x >= 0 { - for i := 0; i < numEscResults; i++ { - if l.Result(i) >= x { - l.setResult(i, -1) - } +// inMutualBatch reports whether function fn is in the batch of +// mutually recursive functions being analyzed. When this is true, +// fn has not yet been analyzed, so its parameters and results +// should be incorporated directly into the flow graph instead of +// relying on its escape analysis tagging. +func (e *escape) inMutualBatch(fn *ir.Name) bool { + if fn.Defn != nil && fn.Defn.Esc() < escFuncTagged { + if fn.Defn.Esc() == escFuncUnknown { + base.Fatalf("graph inconsistency: %v", fn) } + return true } -} - -var leakTagCache = map[leaks]string{} - -// Encode converts l into a binary string for export data. -func (l leaks) Encode() string { - if l.Heap() == 0 { - // Space optimization: empty string encodes more - // efficiently in export data. - return "" - } - if s, ok := leakTagCache[l]; ok { - return s - } - - n := len(l) - for n > 0 && l[n-1] == 0 { - n-- - } - s := "esc:" + string(l[:n]) - leakTagCache[l] = s - return s -} - -// parseLeaks parses a binary string representing a leaks -func parseLeaks(s string) leaks { - var l leaks - if !strings.HasPrefix(s, "esc:") { - l.AddHeap(0) - return l - } - copy(l[:], s[4:]) - return l -} - -func Funcs(all []ir.Node) { - ir.VisitFuncsBottomUp(all, Batch) + return false } const ( @@ -1843,211 +352,6 @@ const ( nonlooping ) -func isSliceSelfAssign(dst, src ir.Node) bool { - // Detect the following special case. - // - // func (b *Buffer) Foo() { - // n, m := ... - // b.buf = b.buf[n:m] - // } - // - // This assignment is a no-op for escape analysis, - // it does not store any new pointers into b that were not already there. - // However, without this special case b will escape, because we assign to OIND/ODOTPTR. - // Here we assume that the statement will not contain calls, - // that is, that order will move any calls to init. - // Otherwise base ONAME value could change between the moments - // when we evaluate it for dst and for src. - - // dst is ONAME dereference. - var dstX ir.Node - switch dst.Op() { - default: - return false - case ir.ODEREF: - dst := dst.(*ir.StarExpr) - dstX = dst.X - case ir.ODOTPTR: - dst := dst.(*ir.SelectorExpr) - dstX = dst.X - } - if dstX.Op() != ir.ONAME { - return false - } - // src is a slice operation. - switch src.Op() { - case ir.OSLICE, ir.OSLICE3, ir.OSLICESTR: - // OK. - case ir.OSLICEARR, ir.OSLICE3ARR: - // Since arrays are embedded into containing object, - // slice of non-pointer array will introduce a new pointer into b that was not already there - // (pointer to b itself). After such assignment, if b contents escape, - // b escapes as well. If we ignore such OSLICEARR, we will conclude - // that b does not escape when b contents do. - // - // Pointer to an array is OK since it's not stored inside b directly. - // For slicing an array (not pointer to array), there is an implicit OADDR. - // We check that to determine non-pointer array slicing. - src := src.(*ir.SliceExpr) - if src.X.Op() == ir.OADDR { - return false - } - default: - return false - } - // slice is applied to ONAME dereference. - var baseX ir.Node - switch base := src.(*ir.SliceExpr).X; base.Op() { - default: - return false - case ir.ODEREF: - base := base.(*ir.StarExpr) - baseX = base.X - case ir.ODOTPTR: - base := base.(*ir.SelectorExpr) - baseX = base.X - } - if baseX.Op() != ir.ONAME { - return false - } - // dst and src reference the same base ONAME. - return dstX.(*ir.Name) == baseX.(*ir.Name) -} - -// isSelfAssign reports whether assignment from src to dst can -// be ignored by the escape analysis as it's effectively a self-assignment. -func isSelfAssign(dst, src ir.Node) bool { - if isSliceSelfAssign(dst, src) { - return true - } - - // Detect trivial assignments that assign back to the same object. - // - // It covers these cases: - // val.x = val.y - // val.x[i] = val.y[j] - // val.x1.x2 = val.x1.y2 - // ... etc - // - // These assignments do not change assigned object lifetime. - - if dst == nil || src == nil || dst.Op() != src.Op() { - return false - } - - // The expression prefix must be both "safe" and identical. - switch dst.Op() { - case ir.ODOT, ir.ODOTPTR: - // Safe trailing accessors that are permitted to differ. - dst := dst.(*ir.SelectorExpr) - src := src.(*ir.SelectorExpr) - return ir.SameSafeExpr(dst.X, src.X) - case ir.OINDEX: - dst := dst.(*ir.IndexExpr) - src := src.(*ir.IndexExpr) - if mayAffectMemory(dst.Index) || mayAffectMemory(src.Index) { - return false - } - return ir.SameSafeExpr(dst.X, src.X) - default: - return false - } -} - -// mayAffectMemory reports whether evaluation of n may affect the program's -// memory state. If the expression can't affect memory state, then it can be -// safely ignored by the escape analysis. -func mayAffectMemory(n ir.Node) bool { - // We may want to use a list of "memory safe" ops instead of generally - // "side-effect free", which would include all calls and other ops that can - // allocate or change global state. For now, it's safer to start with the latter. - // - // We're ignoring things like division by zero, index out of range, - // and nil pointer dereference here. - - // TODO(rsc): It seems like it should be possible to replace this with - // an ir.Any looking for any op that's not the ones in the case statement. - // But that produces changes in the compiled output detected by buildall. - switch n.Op() { - case ir.ONAME, ir.OLITERAL, ir.ONIL: - return false - - case ir.OADD, ir.OSUB, ir.OOR, ir.OXOR, ir.OMUL, ir.OLSH, ir.ORSH, ir.OAND, ir.OANDNOT, ir.ODIV, ir.OMOD: - n := n.(*ir.BinaryExpr) - return mayAffectMemory(n.X) || mayAffectMemory(n.Y) - - case ir.OINDEX: - n := n.(*ir.IndexExpr) - return mayAffectMemory(n.X) || mayAffectMemory(n.Index) - - case ir.OCONVNOP, ir.OCONV: - n := n.(*ir.ConvExpr) - return mayAffectMemory(n.X) - - case ir.OLEN, ir.OCAP, ir.ONOT, ir.OBITNOT, ir.OPLUS, ir.ONEG, ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF: - n := n.(*ir.UnaryExpr) - return mayAffectMemory(n.X) - - case ir.ODOT, ir.ODOTPTR: - n := n.(*ir.SelectorExpr) - return mayAffectMemory(n.X) - - case ir.ODEREF: - n := n.(*ir.StarExpr) - return mayAffectMemory(n.X) - - default: - return true - } -} - -// HeapAllocReason returns the reason the given Node must be heap -// allocated, or the empty string if it doesn't. -func HeapAllocReason(n ir.Node) string { - if n == nil || n.Type() == nil { - return "" - } - - // Parameters are always passed via the stack. - if n.Op() == ir.ONAME { - n := n.(*ir.Name) - if n.Class == ir.PPARAM || n.Class == ir.PPARAMOUT { - return "" - } - } - - if n.Type().Width > ir.MaxStackVarSize { - return "too large for stack" - } - - if (n.Op() == ir.ONEW || n.Op() == ir.OPTRLIT) && n.Type().Elem().Width >= ir.MaxImplicitStackVarSize { - return "too large for stack" - } - - if n.Op() == ir.OCLOSURE && typecheck.ClosureType(n.(*ir.ClosureExpr)).Size() >= ir.MaxImplicitStackVarSize { - return "too large for stack" - } - if n.Op() == ir.OCALLPART && typecheck.PartialCallType(n.(*ir.SelectorExpr)).Size() >= ir.MaxImplicitStackVarSize { - return "too large for stack" - } - - if n.Op() == ir.OMAKESLICE { - n := n.(*ir.MakeExpr) - r := n.Cap - if r == nil { - r = n.Len - } - if !ir.IsSmallIntConst(r) { - return "non-constant size" - } - if t := n.Type(); t.Elem().Width != 0 && ir.Int64Val(r) >= ir.MaxImplicitStackVarSize/t.Elem().Width { - return "too large for stack" - } - } - - return "" -} - func (b *batch) paramTag(fn *ir.Func, narg int, f *types.Field) string { name := func() string { if f.Sym != nil { diff --git a/src/cmd/compile/internal/escape/expr.go b/src/cmd/compile/internal/escape/expr.go new file mode 100644 index 0000000000..5b280c76f1 --- /dev/null +++ b/src/cmd/compile/internal/escape/expr.go @@ -0,0 +1,340 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package escape + +import ( + "cmd/compile/internal/base" + "cmd/compile/internal/ir" + "cmd/compile/internal/types" +) + +// expr models evaluating an expression n and flowing the result into +// hole k. +func (e *escape) expr(k hole, n ir.Node) { + if n == nil { + return + } + e.stmts(n.Init()) + e.exprSkipInit(k, n) +} + +func (e *escape) exprSkipInit(k hole, n ir.Node) { + if n == nil { + return + } + + lno := ir.SetPos(n) + defer func() { + base.Pos = lno + }() + + uintptrEscapesHack := k.uintptrEscapesHack + k.uintptrEscapesHack = false + + if uintptrEscapesHack && n.Op() == ir.OCONVNOP && n.(*ir.ConvExpr).X.Type().IsUnsafePtr() { + // nop + } else if k.derefs >= 0 && !n.Type().HasPointers() { + k.dst = &e.blankLoc + } + + switch n.Op() { + default: + base.Fatalf("unexpected expr: %s %v", n.Op().String(), n) + + case ir.OLITERAL, ir.ONIL, ir.OGETG, ir.OTYPE, ir.OMETHEXPR, ir.OLINKSYMOFFSET: + // nop + + case ir.ONAME: + n := n.(*ir.Name) + if n.Class == ir.PFUNC || n.Class == ir.PEXTERN { + return + } + if n.IsClosureVar() && n.Defn == nil { + return // ".this" from method value wrapper + } + e.flow(k, e.oldLoc(n)) + + case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT: + n := n.(*ir.UnaryExpr) + e.discard(n.X) + case ir.OADD, ir.OSUB, ir.OOR, ir.OXOR, ir.OMUL, ir.ODIV, ir.OMOD, ir.OLSH, ir.ORSH, ir.OAND, ir.OANDNOT, ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE: + n := n.(*ir.BinaryExpr) + e.discard(n.X) + e.discard(n.Y) + case ir.OANDAND, ir.OOROR: + n := n.(*ir.LogicalExpr) + e.discard(n.X) + e.discard(n.Y) + case ir.OADDR: + n := n.(*ir.AddrExpr) + e.expr(k.addr(n, "address-of"), n.X) // "address-of" + case ir.ODEREF: + n := n.(*ir.StarExpr) + e.expr(k.deref(n, "indirection"), n.X) // "indirection" + case ir.ODOT, ir.ODOTMETH, ir.ODOTINTER: + n := n.(*ir.SelectorExpr) + e.expr(k.note(n, "dot"), n.X) + case ir.ODOTPTR: + n := n.(*ir.SelectorExpr) + e.expr(k.deref(n, "dot of pointer"), n.X) // "dot of pointer" + case ir.ODOTTYPE, ir.ODOTTYPE2: + n := n.(*ir.TypeAssertExpr) + e.expr(k.dotType(n.Type(), n, "dot"), n.X) + case ir.OINDEX: + n := n.(*ir.IndexExpr) + if n.X.Type().IsArray() { + e.expr(k.note(n, "fixed-array-index-of"), n.X) + } else { + // TODO(mdempsky): Fix why reason text. + e.expr(k.deref(n, "dot of pointer"), n.X) + } + e.discard(n.Index) + case ir.OINDEXMAP: + n := n.(*ir.IndexExpr) + e.discard(n.X) + e.discard(n.Index) + case ir.OSLICE, ir.OSLICEARR, ir.OSLICE3, ir.OSLICE3ARR, ir.OSLICESTR: + n := n.(*ir.SliceExpr) + e.expr(k.note(n, "slice"), n.X) + e.discard(n.Low) + e.discard(n.High) + e.discard(n.Max) + + case ir.OCONV, ir.OCONVNOP: + n := n.(*ir.ConvExpr) + if ir.ShouldCheckPtr(e.curfn, 2) && n.Type().IsUnsafePtr() && n.X.Type().IsPtr() { + // When -d=checkptr=2 is enabled, treat + // conversions to unsafe.Pointer as an + // escaping operation. This allows better + // runtime instrumentation, since we can more + // easily detect object boundaries on the heap + // than the stack. + e.assignHeap(n.X, "conversion to unsafe.Pointer", n) + } else if n.Type().IsUnsafePtr() && n.X.Type().IsUintptr() { + e.unsafeValue(k, n.X) + } else { + e.expr(k, n.X) + } + case ir.OCONVIFACE: + n := n.(*ir.ConvExpr) + if !n.X.Type().IsInterface() && !types.IsDirectIface(n.X.Type()) { + k = e.spill(k, n) + } + e.expr(k.note(n, "interface-converted"), n.X) + case ir.OEFACE: + n := n.(*ir.BinaryExpr) + // Note: n.X is not needed because it can never point to memory that might escape. + e.expr(k, n.Y) + case ir.OIDATA, ir.OSPTR: + n := n.(*ir.UnaryExpr) + e.expr(k, n.X) + case ir.OSLICE2ARRPTR: + // the slice pointer flows directly to the result + n := n.(*ir.ConvExpr) + e.expr(k, n.X) + case ir.ORECV: + n := n.(*ir.UnaryExpr) + e.discard(n.X) + + case ir.OCALLMETH, ir.OCALLFUNC, ir.OCALLINTER, ir.OLEN, ir.OCAP, ir.OCOMPLEX, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.OCOPY, ir.OUNSAFEADD, ir.OUNSAFESLICE: + e.call([]hole{k}, n, nil) + + case ir.ONEW: + n := n.(*ir.UnaryExpr) + e.spill(k, n) + + case ir.OMAKESLICE: + n := n.(*ir.MakeExpr) + e.spill(k, n) + e.discard(n.Len) + e.discard(n.Cap) + case ir.OMAKECHAN: + n := n.(*ir.MakeExpr) + e.discard(n.Len) + case ir.OMAKEMAP: + n := n.(*ir.MakeExpr) + e.spill(k, n) + e.discard(n.Len) + + case ir.ORECOVER: + // nop + + case ir.OCALLPART: + // Flow the receiver argument to both the closure and + // to the receiver parameter. + + n := n.(*ir.SelectorExpr) + closureK := e.spill(k, n) + + m := n.Selection + + // We don't know how the method value will be called + // later, so conservatively assume the result + // parameters all flow to the heap. + // + // TODO(mdempsky): Change ks into a callback, so that + // we don't have to create this slice? + var ks []hole + for i := m.Type.NumResults(); i > 0; i-- { + ks = append(ks, e.heapHole()) + } + name, _ := m.Nname.(*ir.Name) + paramK := e.tagHole(ks, name, m.Type.Recv()) + + e.expr(e.teeHole(paramK, closureK), n.X) + + case ir.OPTRLIT: + n := n.(*ir.AddrExpr) + e.expr(e.spill(k, n), n.X) + + case ir.OARRAYLIT: + n := n.(*ir.CompLitExpr) + for _, elt := range n.List { + if elt.Op() == ir.OKEY { + elt = elt.(*ir.KeyExpr).Value + } + e.expr(k.note(n, "array literal element"), elt) + } + + case ir.OSLICELIT: + n := n.(*ir.CompLitExpr) + k = e.spill(k, n) + k.uintptrEscapesHack = uintptrEscapesHack // for ...uintptr parameters + + for _, elt := range n.List { + if elt.Op() == ir.OKEY { + elt = elt.(*ir.KeyExpr).Value + } + e.expr(k.note(n, "slice-literal-element"), elt) + } + + case ir.OSTRUCTLIT: + n := n.(*ir.CompLitExpr) + for _, elt := range n.List { + e.expr(k.note(n, "struct literal element"), elt.(*ir.StructKeyExpr).Value) + } + + case ir.OMAPLIT: + n := n.(*ir.CompLitExpr) + e.spill(k, n) + + // Map keys and values are always stored in the heap. + for _, elt := range n.List { + elt := elt.(*ir.KeyExpr) + e.assignHeap(elt.Key, "map literal key", n) + e.assignHeap(elt.Value, "map literal value", n) + } + + case ir.OCLOSURE: + n := n.(*ir.ClosureExpr) + k = e.spill(k, n) + e.closures = append(e.closures, closure{k, n}) + + if fn := n.Func; fn.IsHiddenClosure() { + for _, cv := range fn.ClosureVars { + if loc := e.oldLoc(cv); !loc.captured { + loc.captured = true + + // Ignore reassignments to the variable in straightline code + // preceding the first capture by a closure. + if loc.loopDepth == e.loopDepth { + loc.reassigned = false + } + } + } + + for _, n := range fn.Dcl { + // Add locations for local variables of the + // closure, if needed, in case we're not including + // the closure func in the batch for escape + // analysis (happens for escape analysis called + // from reflectdata.methodWrapper) + if n.Op() == ir.ONAME && n.Opt == nil { + e.with(fn).newLoc(n, false) + } + } + e.walkFunc(fn) + } + + case ir.ORUNES2STR, ir.OBYTES2STR, ir.OSTR2RUNES, ir.OSTR2BYTES, ir.ORUNESTR: + n := n.(*ir.ConvExpr) + e.spill(k, n) + e.discard(n.X) + + case ir.OADDSTR: + n := n.(*ir.AddStringExpr) + e.spill(k, n) + + // Arguments of OADDSTR never escape; + // runtime.concatstrings makes sure of that. + e.discards(n.List) + } +} + +// unsafeValue evaluates a uintptr-typed arithmetic expression looking +// for conversions from an unsafe.Pointer. +func (e *escape) unsafeValue(k hole, n ir.Node) { + if n.Type().Kind() != types.TUINTPTR { + base.Fatalf("unexpected type %v for %v", n.Type(), n) + } + if k.addrtaken { + base.Fatalf("unexpected addrtaken") + } + + e.stmts(n.Init()) + + switch n.Op() { + case ir.OCONV, ir.OCONVNOP: + n := n.(*ir.ConvExpr) + if n.X.Type().IsUnsafePtr() { + e.expr(k, n.X) + } else { + e.discard(n.X) + } + case ir.ODOTPTR: + n := n.(*ir.SelectorExpr) + if ir.IsReflectHeaderDataField(n) { + e.expr(k.deref(n, "reflect.Header.Data"), n.X) + } else { + e.discard(n.X) + } + case ir.OPLUS, ir.ONEG, ir.OBITNOT: + n := n.(*ir.UnaryExpr) + e.unsafeValue(k, n.X) + case ir.OADD, ir.OSUB, ir.OOR, ir.OXOR, ir.OMUL, ir.ODIV, ir.OMOD, ir.OAND, ir.OANDNOT: + n := n.(*ir.BinaryExpr) + e.unsafeValue(k, n.X) + e.unsafeValue(k, n.Y) + case ir.OLSH, ir.ORSH: + n := n.(*ir.BinaryExpr) + e.unsafeValue(k, n.X) + // RHS need not be uintptr-typed (#32959) and can't meaningfully + // flow pointers anyway. + e.discard(n.Y) + default: + e.exprSkipInit(e.discardHole(), n) + } +} + +// discard evaluates an expression n for side-effects, but discards +// its value. +func (e *escape) discard(n ir.Node) { + e.expr(e.discardHole(), n) +} + +func (e *escape) discards(l ir.Nodes) { + for _, n := range l { + e.discard(n) + } +} + +// spill allocates a new location associated with expression n, flows +// its address to k, and returns a hole that flows values to it. It's +// intended for use with most expressions that allocate storage. +func (e *escape) spill(k hole, n ir.Node) hole { + loc := e.newLoc(n, true) + e.flow(k.addr(n, "spill"), loc) + return loc.asHole() +} diff --git a/src/cmd/compile/internal/escape/graph.go b/src/cmd/compile/internal/escape/graph.go new file mode 100644 index 0000000000..3581fce30d --- /dev/null +++ b/src/cmd/compile/internal/escape/graph.go @@ -0,0 +1,324 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package escape + +import ( + "cmd/compile/internal/base" + "cmd/compile/internal/ir" + "cmd/compile/internal/logopt" + "cmd/compile/internal/types" + "fmt" +) + +// Below we implement the methods for walking the AST and recording +// data flow edges. Note that because a sub-expression might have +// side-effects, it's important to always visit the entire AST. +// +// For example, write either: +// +// if x { +// e.discard(n.Left) +// } else { +// e.value(k, n.Left) +// } +// +// or +// +// if x { +// k = e.discardHole() +// } +// e.value(k, n.Left) +// +// Do NOT write: +// +// // BAD: possibly loses side-effects within n.Left +// if !x { +// e.value(k, n.Left) +// } + +// An location represents an abstract location that stores a Go +// variable. +type location struct { + n ir.Node // represented variable or expression, if any + curfn *ir.Func // enclosing function + edges []edge // incoming edges + loopDepth int // loopDepth at declaration + + // resultIndex records the tuple index (starting at 1) for + // PPARAMOUT variables within their function's result type. + // For non-PPARAMOUT variables it's 0. + resultIndex int + + // derefs and walkgen are used during walkOne to track the + // minimal dereferences from the walk root. + derefs int // >= -1 + walkgen uint32 + + // dst and dstEdgeindex track the next immediate assignment + // destination location during walkone, along with the index + // of the edge pointing back to this location. + dst *location + dstEdgeIdx int + + // queued is used by walkAll to track whether this location is + // in the walk queue. + queued bool + + // escapes reports whether the represented variable's address + // escapes; that is, whether the variable must be heap + // allocated. + escapes bool + + // transient reports whether the represented expression's + // address does not outlive the statement; that is, whether + // its storage can be immediately reused. + transient bool + + // paramEsc records the represented parameter's leak set. + paramEsc leaks + + captured bool // has a closure captured this variable? + reassigned bool // has this variable been reassigned? + addrtaken bool // has this variable's address been taken? +} + +// An edge represents an assignment edge between two Go variables. +type edge struct { + src *location + derefs int // >= -1 + notes *note +} + +func (l *location) asHole() hole { + return hole{dst: l} +} + +// leak records that parameter l leaks to sink. +func (l *location) leakTo(sink *location, derefs int) { + // If sink is a result parameter that doesn't escape (#44614) + // and we can fit return bits into the escape analysis tag, + // then record as a result leak. + if !sink.escapes && sink.isName(ir.PPARAMOUT) && sink.curfn == l.curfn { + ri := sink.resultIndex - 1 + if ri < numEscResults { + // Leak to result parameter. + l.paramEsc.AddResult(ri, derefs) + return + } + } + + // Otherwise, record as heap leak. + l.paramEsc.AddHeap(derefs) +} + +func (l *location) isName(c ir.Class) bool { + return l.n != nil && l.n.Op() == ir.ONAME && l.n.(*ir.Name).Class == c +} + +// An hole represents a context for evaluation a Go +// expression. E.g., when evaluating p in "x = **p", we'd have a hole +// with dst==x and derefs==2. +type hole struct { + dst *location + derefs int // >= -1 + notes *note + + // addrtaken indicates whether this context is taking the address of + // the expression, independent of whether the address will actually + // be stored into a variable. + addrtaken bool + + // uintptrEscapesHack indicates this context is evaluating an + // argument for a //go:uintptrescapes function. + uintptrEscapesHack bool +} + +type note struct { + next *note + where ir.Node + why string +} + +func (k hole) note(where ir.Node, why string) hole { + if where == nil || why == "" { + base.Fatalf("note: missing where/why") + } + if base.Flag.LowerM >= 2 || logopt.Enabled() { + k.notes = ¬e{ + next: k.notes, + where: where, + why: why, + } + } + return k +} + +func (k hole) shift(delta int) hole { + k.derefs += delta + if k.derefs < -1 { + base.Fatalf("derefs underflow: %v", k.derefs) + } + k.addrtaken = delta < 0 + return k +} + +func (k hole) deref(where ir.Node, why string) hole { return k.shift(1).note(where, why) } +func (k hole) addr(where ir.Node, why string) hole { return k.shift(-1).note(where, why) } + +func (k hole) dotType(t *types.Type, where ir.Node, why string) hole { + if !t.IsInterface() && !types.IsDirectIface(t) { + k = k.shift(1) + } + return k.note(where, why) +} + +func (b *batch) flow(k hole, src *location) { + if k.addrtaken { + src.addrtaken = true + } + + dst := k.dst + if dst == &b.blankLoc { + return + } + if dst == src && k.derefs >= 0 { // dst = dst, dst = *dst, ... + return + } + if dst.escapes && k.derefs < 0 { // dst = &src + if base.Flag.LowerM >= 2 || logopt.Enabled() { + pos := base.FmtPos(src.n.Pos()) + if base.Flag.LowerM >= 2 { + fmt.Printf("%s: %v escapes to heap:\n", pos, src.n) + } + explanation := b.explainFlow(pos, dst, src, k.derefs, k.notes, []*logopt.LoggedOpt{}) + if logopt.Enabled() { + var e_curfn *ir.Func // TODO(mdempsky): Fix. + logopt.LogOpt(src.n.Pos(), "escapes", "escape", ir.FuncName(e_curfn), fmt.Sprintf("%v escapes to heap", src.n), explanation) + } + + } + src.escapes = true + return + } + + // TODO(mdempsky): Deduplicate edges? + dst.edges = append(dst.edges, edge{src: src, derefs: k.derefs, notes: k.notes}) +} + +func (b *batch) heapHole() hole { return b.heapLoc.asHole() } +func (b *batch) discardHole() hole { return b.blankLoc.asHole() } + +func (b *batch) oldLoc(n *ir.Name) *location { + if n.Canonical().Opt == nil { + base.Fatalf("%v has no location", n) + } + return n.Canonical().Opt.(*location) +} + +func (e *escape) newLoc(n ir.Node, transient bool) *location { + if e.curfn == nil { + base.Fatalf("e.curfn isn't set") + } + if n != nil && n.Type() != nil && n.Type().NotInHeap() { + base.ErrorfAt(n.Pos(), "%v is incomplete (or unallocatable); stack allocation disallowed", n.Type()) + } + + if n != nil && n.Op() == ir.ONAME { + n = n.(*ir.Name).Canonical() + } + loc := &location{ + n: n, + curfn: e.curfn, + loopDepth: e.loopDepth, + transient: transient, + } + e.allLocs = append(e.allLocs, loc) + if n != nil { + if n.Op() == ir.ONAME { + n := n.(*ir.Name) + if n.Curfn != e.curfn { + base.Fatalf("curfn mismatch: %v != %v for %v", n.Curfn, e.curfn, n) + } + + if n.Opt != nil { + base.Fatalf("%v already has a location", n) + } + n.Opt = loc + } + } + return loc +} + +// teeHole returns a new hole that flows into each hole of ks, +// similar to the Unix tee(1) command. +func (e *escape) teeHole(ks ...hole) hole { + if len(ks) == 0 { + return e.discardHole() + } + if len(ks) == 1 { + return ks[0] + } + // TODO(mdempsky): Optimize if there's only one non-discard hole? + + // Given holes "l1 = _", "l2 = **_", "l3 = *_", ..., create a + // new temporary location ltmp, wire it into place, and return + // a hole for "ltmp = _". + loc := e.newLoc(nil, true) + for _, k := range ks { + // N.B., "p = &q" and "p = &tmp; tmp = q" are not + // semantically equivalent. To combine holes like "l1 + // = _" and "l2 = &_", we'd need to wire them as "l1 = + // *ltmp" and "l2 = ltmp" and return "ltmp = &_" + // instead. + if k.derefs < 0 { + base.Fatalf("teeHole: negative derefs") + } + + e.flow(k, loc) + } + return loc.asHole() +} + +// later returns a new hole that flows into k, but some time later. +// Its main effect is to prevent immediate reuse of temporary +// variables introduced during Order. +func (e *escape) later(k hole) hole { + loc := e.newLoc(nil, false) + e.flow(k, loc) + return loc.asHole() +} + +// Fmt is called from node printing to print information about escape analysis results. +func Fmt(n ir.Node) string { + text := "" + switch n.Esc() { + case ir.EscUnknown: + break + + case ir.EscHeap: + text = "esc(h)" + + case ir.EscNone: + text = "esc(no)" + + case ir.EscNever: + text = "esc(N)" + + default: + text = fmt.Sprintf("esc(%d)", n.Esc()) + } + + if n.Op() == ir.ONAME { + n := n.(*ir.Name) + if loc, ok := n.Opt.(*location); ok && loc.loopDepth != 0 { + if text != "" { + text += " " + } + text += fmt.Sprintf("ld(%d)", loc.loopDepth) + } + } + + return text +} diff --git a/src/cmd/compile/internal/escape/leaks.go b/src/cmd/compile/internal/escape/leaks.go new file mode 100644 index 0000000000..4c848a5ee7 --- /dev/null +++ b/src/cmd/compile/internal/escape/leaks.go @@ -0,0 +1,106 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package escape + +import ( + "cmd/compile/internal/base" + "math" + "strings" +) + +const numEscResults = 7 + +// An leaks represents a set of assignment flows from a parameter +// to the heap or to any of its function's (first numEscResults) +// result parameters. +type leaks [1 + numEscResults]uint8 + +// Empty reports whether l is an empty set (i.e., no assignment flows). +func (l leaks) Empty() bool { return l == leaks{} } + +// Heap returns the minimum deref count of any assignment flow from l +// to the heap. If no such flows exist, Heap returns -1. +func (l leaks) Heap() int { return l.get(0) } + +// Result returns the minimum deref count of any assignment flow from +// l to its function's i'th result parameter. If no such flows exist, +// Result returns -1. +func (l leaks) Result(i int) int { return l.get(1 + i) } + +// AddHeap adds an assignment flow from l to the heap. +func (l *leaks) AddHeap(derefs int) { l.add(0, derefs) } + +// AddResult adds an assignment flow from l to its function's i'th +// result parameter. +func (l *leaks) AddResult(i, derefs int) { l.add(1+i, derefs) } + +func (l *leaks) setResult(i, derefs int) { l.set(1+i, derefs) } + +func (l leaks) get(i int) int { return int(l[i]) - 1 } + +func (l *leaks) add(i, derefs int) { + if old := l.get(i); old < 0 || derefs < old { + l.set(i, derefs) + } +} + +func (l *leaks) set(i, derefs int) { + v := derefs + 1 + if v < 0 { + base.Fatalf("invalid derefs count: %v", derefs) + } + if v > math.MaxUint8 { + v = math.MaxUint8 + } + + l[i] = uint8(v) +} + +// Optimize removes result flow paths that are equal in length or +// longer than the shortest heap flow path. +func (l *leaks) Optimize() { + // If we have a path to the heap, then there's no use in + // keeping equal or longer paths elsewhere. + if x := l.Heap(); x >= 0 { + for i := 0; i < numEscResults; i++ { + if l.Result(i) >= x { + l.setResult(i, -1) + } + } + } +} + +var leakTagCache = map[leaks]string{} + +// Encode converts l into a binary string for export data. +func (l leaks) Encode() string { + if l.Heap() == 0 { + // Space optimization: empty string encodes more + // efficiently in export data. + return "" + } + if s, ok := leakTagCache[l]; ok { + return s + } + + n := len(l) + for n > 0 && l[n-1] == 0 { + n-- + } + s := "esc:" + string(l[:n]) + leakTagCache[l] = s + return s +} + +// parseLeaks parses a binary string representing a leaks +func parseLeaks(s string) leaks { + var l leaks + if !strings.HasPrefix(s, "esc:") { + l.AddHeap(0) + return l + } + copy(l[:], s[4:]) + return l +} diff --git a/src/cmd/compile/internal/escape/solve.go b/src/cmd/compile/internal/escape/solve.go new file mode 100644 index 0000000000..77d6b27dd7 --- /dev/null +++ b/src/cmd/compile/internal/escape/solve.go @@ -0,0 +1,289 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package escape + +import ( + "cmd/compile/internal/base" + "cmd/compile/internal/ir" + "cmd/compile/internal/logopt" + "cmd/internal/src" + "fmt" + "strings" +) + +// walkAll computes the minimal dereferences between all pairs of +// locations. +func (b *batch) walkAll() { + // We use a work queue to keep track of locations that we need + // to visit, and repeatedly walk until we reach a fixed point. + // + // We walk once from each location (including the heap), and + // then re-enqueue each location on its transition from + // transient->!transient and !escapes->escapes, which can each + // happen at most once. So we take Θ(len(e.allLocs)) walks. + + // LIFO queue, has enough room for e.allLocs and e.heapLoc. + todo := make([]*location, 0, len(b.allLocs)+1) + enqueue := func(loc *location) { + if !loc.queued { + todo = append(todo, loc) + loc.queued = true + } + } + + for _, loc := range b.allLocs { + enqueue(loc) + } + enqueue(&b.heapLoc) + + var walkgen uint32 + for len(todo) > 0 { + root := todo[len(todo)-1] + todo = todo[:len(todo)-1] + root.queued = false + + walkgen++ + b.walkOne(root, walkgen, enqueue) + } +} + +// walkOne computes the minimal number of dereferences from root to +// all other locations. +func (b *batch) walkOne(root *location, walkgen uint32, enqueue func(*location)) { + // The data flow graph has negative edges (from addressing + // operations), so we use the Bellman-Ford algorithm. However, + // we don't have to worry about infinite negative cycles since + // we bound intermediate dereference counts to 0. + + root.walkgen = walkgen + root.derefs = 0 + root.dst = nil + + todo := []*location{root} // LIFO queue + for len(todo) > 0 { + l := todo[len(todo)-1] + todo = todo[:len(todo)-1] + + derefs := l.derefs + + // If l.derefs < 0, then l's address flows to root. + addressOf := derefs < 0 + if addressOf { + // For a flow path like "root = &l; l = x", + // l's address flows to root, but x's does + // not. We recognize this by lower bounding + // derefs at 0. + derefs = 0 + + // If l's address flows to a non-transient + // location, then l can't be transiently + // allocated. + if !root.transient && l.transient { + l.transient = false + enqueue(l) + } + } + + if b.outlives(root, l) { + // l's value flows to root. If l is a function + // parameter and root is the heap or a + // corresponding result parameter, then record + // that value flow for tagging the function + // later. + if l.isName(ir.PPARAM) { + if (logopt.Enabled() || base.Flag.LowerM >= 2) && !l.escapes { + if base.Flag.LowerM >= 2 { + fmt.Printf("%s: parameter %v leaks to %s with derefs=%d:\n", base.FmtPos(l.n.Pos()), l.n, b.explainLoc(root), derefs) + } + explanation := b.explainPath(root, l) + if logopt.Enabled() { + var e_curfn *ir.Func // TODO(mdempsky): Fix. + logopt.LogOpt(l.n.Pos(), "leak", "escape", ir.FuncName(e_curfn), + fmt.Sprintf("parameter %v leaks to %s with derefs=%d", l.n, b.explainLoc(root), derefs), explanation) + } + } + l.leakTo(root, derefs) + } + + // If l's address flows somewhere that + // outlives it, then l needs to be heap + // allocated. + if addressOf && !l.escapes { + if logopt.Enabled() || base.Flag.LowerM >= 2 { + if base.Flag.LowerM >= 2 { + fmt.Printf("%s: %v escapes to heap:\n", base.FmtPos(l.n.Pos()), l.n) + } + explanation := b.explainPath(root, l) + if logopt.Enabled() { + var e_curfn *ir.Func // TODO(mdempsky): Fix. + logopt.LogOpt(l.n.Pos(), "escape", "escape", ir.FuncName(e_curfn), fmt.Sprintf("%v escapes to heap", l.n), explanation) + } + } + l.escapes = true + enqueue(l) + continue + } + } + + for i, edge := range l.edges { + if edge.src.escapes { + continue + } + d := derefs + edge.derefs + if edge.src.walkgen != walkgen || edge.src.derefs > d { + edge.src.walkgen = walkgen + edge.src.derefs = d + edge.src.dst = l + edge.src.dstEdgeIdx = i + todo = append(todo, edge.src) + } + } + } +} + +// explainPath prints an explanation of how src flows to the walk root. +func (b *batch) explainPath(root, src *location) []*logopt.LoggedOpt { + visited := make(map[*location]bool) + pos := base.FmtPos(src.n.Pos()) + var explanation []*logopt.LoggedOpt + for { + // Prevent infinite loop. + if visited[src] { + if base.Flag.LowerM >= 2 { + fmt.Printf("%s: warning: truncated explanation due to assignment cycle; see golang.org/issue/35518\n", pos) + } + break + } + visited[src] = true + dst := src.dst + edge := &dst.edges[src.dstEdgeIdx] + if edge.src != src { + base.Fatalf("path inconsistency: %v != %v", edge.src, src) + } + + explanation = b.explainFlow(pos, dst, src, edge.derefs, edge.notes, explanation) + + if dst == root { + break + } + src = dst + } + + return explanation +} + +func (b *batch) explainFlow(pos string, dst, srcloc *location, derefs int, notes *note, explanation []*logopt.LoggedOpt) []*logopt.LoggedOpt { + ops := "&" + if derefs >= 0 { + ops = strings.Repeat("*", derefs) + } + print := base.Flag.LowerM >= 2 + + flow := fmt.Sprintf(" flow: %s = %s%v:", b.explainLoc(dst), ops, b.explainLoc(srcloc)) + if print { + fmt.Printf("%s:%s\n", pos, flow) + } + if logopt.Enabled() { + var epos src.XPos + if notes != nil { + epos = notes.where.Pos() + } else if srcloc != nil && srcloc.n != nil { + epos = srcloc.n.Pos() + } + var e_curfn *ir.Func // TODO(mdempsky): Fix. + explanation = append(explanation, logopt.NewLoggedOpt(epos, "escflow", "escape", ir.FuncName(e_curfn), flow)) + } + + for note := notes; note != nil; note = note.next { + if print { + fmt.Printf("%s: from %v (%v) at %s\n", pos, note.where, note.why, base.FmtPos(note.where.Pos())) + } + if logopt.Enabled() { + var e_curfn *ir.Func // TODO(mdempsky): Fix. + explanation = append(explanation, logopt.NewLoggedOpt(note.where.Pos(), "escflow", "escape", ir.FuncName(e_curfn), + fmt.Sprintf(" from %v (%v)", note.where, note.why))) + } + } + return explanation +} + +func (b *batch) explainLoc(l *location) string { + if l == &b.heapLoc { + return "{heap}" + } + if l.n == nil { + // TODO(mdempsky): Omit entirely. + return "{temp}" + } + if l.n.Op() == ir.ONAME { + return fmt.Sprintf("%v", l.n) + } + return fmt.Sprintf("{storage for %v}", l.n) +} + +// outlives reports whether values stored in l may survive beyond +// other's lifetime if stack allocated. +func (b *batch) outlives(l, other *location) bool { + // The heap outlives everything. + if l.escapes { + return true + } + + // We don't know what callers do with returned values, so + // pessimistically we need to assume they flow to the heap and + // outlive everything too. + if l.isName(ir.PPARAMOUT) { + // Exception: Directly called closures can return + // locations allocated outside of them without forcing + // them to the heap. For example: + // + // var u int // okay to stack allocate + // *(func() *int { return &u }()) = 42 + if containsClosure(other.curfn, l.curfn) && l.curfn.ClosureCalled() { + return false + } + + return true + } + + // If l and other are within the same function, then l + // outlives other if it was declared outside other's loop + // scope. For example: + // + // var l *int + // for { + // l = new(int) + // } + if l.curfn == other.curfn && l.loopDepth < other.loopDepth { + return true + } + + // If other is declared within a child closure of where l is + // declared, then l outlives it. For example: + // + // var l *int + // func() { + // l = new(int) + // } + if containsClosure(l.curfn, other.curfn) { + return true + } + + return false +} + +// containsClosure reports whether c is a closure contained within f. +func containsClosure(f, c *ir.Func) bool { + // Common case. + if f == c { + return false + } + + // Closures within function Foo are named like "Foo.funcN..." + // TODO(mdempsky): Better way to recognize this. + fn := f.Sym().Name + cn := c.Sym().Name + return len(cn) > len(fn) && cn[:len(fn)] == fn && cn[len(fn)] == '.' +} diff --git a/src/cmd/compile/internal/escape/stmt.go b/src/cmd/compile/internal/escape/stmt.go new file mode 100644 index 0000000000..d3e47290d3 --- /dev/null +++ b/src/cmd/compile/internal/escape/stmt.go @@ -0,0 +1,208 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package escape + +import ( + "cmd/compile/internal/base" + "cmd/compile/internal/ir" + "fmt" +) + +// stmt evaluates a single Go statement. +func (e *escape) stmt(n ir.Node) { + if n == nil { + return + } + + lno := ir.SetPos(n) + defer func() { + base.Pos = lno + }() + + if base.Flag.LowerM > 2 { + fmt.Printf("%v:[%d] %v stmt: %v\n", base.FmtPos(base.Pos), e.loopDepth, e.curfn, n) + } + + e.stmts(n.Init()) + + switch n.Op() { + default: + base.Fatalf("unexpected stmt: %v", n) + + case ir.ODCLCONST, ir.ODCLTYPE, ir.OFALL, ir.OINLMARK: + // nop + + case ir.OBREAK, ir.OCONTINUE, ir.OGOTO: + // TODO(mdempsky): Handle dead code? + + case ir.OBLOCK: + n := n.(*ir.BlockStmt) + e.stmts(n.List) + + case ir.ODCL: + // Record loop depth at declaration. + n := n.(*ir.Decl) + if !ir.IsBlank(n.X) { + e.dcl(n.X) + } + + case ir.OLABEL: + n := n.(*ir.LabelStmt) + switch e.labels[n.Label] { + case nonlooping: + if base.Flag.LowerM > 2 { + fmt.Printf("%v:%v non-looping label\n", base.FmtPos(base.Pos), n) + } + case looping: + if base.Flag.LowerM > 2 { + fmt.Printf("%v: %v looping label\n", base.FmtPos(base.Pos), n) + } + e.loopDepth++ + default: + base.Fatalf("label missing tag") + } + delete(e.labels, n.Label) + + case ir.OIF: + n := n.(*ir.IfStmt) + e.discard(n.Cond) + e.block(n.Body) + e.block(n.Else) + + case ir.OFOR, ir.OFORUNTIL: + n := n.(*ir.ForStmt) + e.loopDepth++ + e.discard(n.Cond) + e.stmt(n.Post) + e.block(n.Body) + e.loopDepth-- + + case ir.ORANGE: + // for Key, Value = range X { Body } + n := n.(*ir.RangeStmt) + + // X is evaluated outside the loop. + tmp := e.newLoc(nil, false) + e.expr(tmp.asHole(), n.X) + + e.loopDepth++ + ks := e.addrs([]ir.Node{n.Key, n.Value}) + if n.X.Type().IsArray() { + e.flow(ks[1].note(n, "range"), tmp) + } else { + e.flow(ks[1].deref(n, "range-deref"), tmp) + } + e.reassigned(ks, n) + + e.block(n.Body) + e.loopDepth-- + + case ir.OSWITCH: + n := n.(*ir.SwitchStmt) + + if guard, ok := n.Tag.(*ir.TypeSwitchGuard); ok { + var ks []hole + if guard.Tag != nil { + for _, cas := range n.Cases { + cv := cas.Var + k := e.dcl(cv) // type switch variables have no ODCL. + if cv.Type().HasPointers() { + ks = append(ks, k.dotType(cv.Type(), cas, "switch case")) + } + } + } + e.expr(e.teeHole(ks...), n.Tag.(*ir.TypeSwitchGuard).X) + } else { + e.discard(n.Tag) + } + + for _, cas := range n.Cases { + e.discards(cas.List) + e.block(cas.Body) + } + + case ir.OSELECT: + n := n.(*ir.SelectStmt) + for _, cas := range n.Cases { + e.stmt(cas.Comm) + e.block(cas.Body) + } + case ir.ORECV: + // TODO(mdempsky): Consider e.discard(n.Left). + n := n.(*ir.UnaryExpr) + e.exprSkipInit(e.discardHole(), n) // already visited n.Ninit + case ir.OSEND: + n := n.(*ir.SendStmt) + e.discard(n.Chan) + e.assignHeap(n.Value, "send", n) + + case ir.OAS: + n := n.(*ir.AssignStmt) + e.assignList([]ir.Node{n.X}, []ir.Node{n.Y}, "assign", n) + case ir.OASOP: + n := n.(*ir.AssignOpStmt) + // TODO(mdempsky): Worry about OLSH/ORSH? + e.assignList([]ir.Node{n.X}, []ir.Node{n.Y}, "assign", n) + case ir.OAS2: + n := n.(*ir.AssignListStmt) + e.assignList(n.Lhs, n.Rhs, "assign-pair", n) + + case ir.OAS2DOTTYPE: // v, ok = x.(type) + n := n.(*ir.AssignListStmt) + e.assignList(n.Lhs, n.Rhs, "assign-pair-dot-type", n) + case ir.OAS2MAPR: // v, ok = m[k] + n := n.(*ir.AssignListStmt) + e.assignList(n.Lhs, n.Rhs, "assign-pair-mapr", n) + case ir.OAS2RECV, ir.OSELRECV2: // v, ok = <-ch + n := n.(*ir.AssignListStmt) + e.assignList(n.Lhs, n.Rhs, "assign-pair-receive", n) + + case ir.OAS2FUNC: + n := n.(*ir.AssignListStmt) + e.stmts(n.Rhs[0].Init()) + ks := e.addrs(n.Lhs) + e.call(ks, n.Rhs[0], nil) + e.reassigned(ks, n) + case ir.ORETURN: + n := n.(*ir.ReturnStmt) + results := e.curfn.Type().Results().FieldSlice() + dsts := make([]ir.Node, len(results)) + for i, res := range results { + dsts[i] = res.Nname.(*ir.Name) + } + e.assignList(dsts, n.Results, "return", n) + case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER, ir.OCLOSE, ir.OCOPY, ir.ODELETE, ir.OPANIC, ir.OPRINT, ir.OPRINTN, ir.ORECOVER: + e.call(nil, n, nil) + case ir.OGO, ir.ODEFER: + n := n.(*ir.GoDeferStmt) + e.stmts(n.Call.Init()) + e.call(nil, n.Call, n) + + case ir.OTAILCALL: + // TODO(mdempsky): Treat like a normal call? esc.go used to just ignore it. + } +} + +func (e *escape) stmts(l ir.Nodes) { + for _, n := range l { + e.stmt(n) + } +} + +// block is like stmts, but preserves loopDepth. +func (e *escape) block(l ir.Nodes) { + old := e.loopDepth + e.stmts(l) + e.loopDepth = old +} + +func (e *escape) dcl(n *ir.Name) hole { + if n.Curfn != e.curfn || n.IsClosureVar() { + base.Fatalf("bad declaration of %v", n) + } + loc := e.oldLoc(n) + loc.loopDepth = e.loopDepth + return loc.asHole() +} diff --git a/src/cmd/compile/internal/escape/utils.go b/src/cmd/compile/internal/escape/utils.go new file mode 100644 index 0000000000..7100926bb8 --- /dev/null +++ b/src/cmd/compile/internal/escape/utils.go @@ -0,0 +1,215 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package escape + +import ( + "cmd/compile/internal/ir" + "cmd/compile/internal/typecheck" +) + +func isSliceSelfAssign(dst, src ir.Node) bool { + // Detect the following special case. + // + // func (b *Buffer) Foo() { + // n, m := ... + // b.buf = b.buf[n:m] + // } + // + // This assignment is a no-op for escape analysis, + // it does not store any new pointers into b that were not already there. + // However, without this special case b will escape, because we assign to OIND/ODOTPTR. + // Here we assume that the statement will not contain calls, + // that is, that order will move any calls to init. + // Otherwise base ONAME value could change between the moments + // when we evaluate it for dst and for src. + + // dst is ONAME dereference. + var dstX ir.Node + switch dst.Op() { + default: + return false + case ir.ODEREF: + dst := dst.(*ir.StarExpr) + dstX = dst.X + case ir.ODOTPTR: + dst := dst.(*ir.SelectorExpr) + dstX = dst.X + } + if dstX.Op() != ir.ONAME { + return false + } + // src is a slice operation. + switch src.Op() { + case ir.OSLICE, ir.OSLICE3, ir.OSLICESTR: + // OK. + case ir.OSLICEARR, ir.OSLICE3ARR: + // Since arrays are embedded into containing object, + // slice of non-pointer array will introduce a new pointer into b that was not already there + // (pointer to b itself). After such assignment, if b contents escape, + // b escapes as well. If we ignore such OSLICEARR, we will conclude + // that b does not escape when b contents do. + // + // Pointer to an array is OK since it's not stored inside b directly. + // For slicing an array (not pointer to array), there is an implicit OADDR. + // We check that to determine non-pointer array slicing. + src := src.(*ir.SliceExpr) + if src.X.Op() == ir.OADDR { + return false + } + default: + return false + } + // slice is applied to ONAME dereference. + var baseX ir.Node + switch base := src.(*ir.SliceExpr).X; base.Op() { + default: + return false + case ir.ODEREF: + base := base.(*ir.StarExpr) + baseX = base.X + case ir.ODOTPTR: + base := base.(*ir.SelectorExpr) + baseX = base.X + } + if baseX.Op() != ir.ONAME { + return false + } + // dst and src reference the same base ONAME. + return dstX.(*ir.Name) == baseX.(*ir.Name) +} + +// isSelfAssign reports whether assignment from src to dst can +// be ignored by the escape analysis as it's effectively a self-assignment. +func isSelfAssign(dst, src ir.Node) bool { + if isSliceSelfAssign(dst, src) { + return true + } + + // Detect trivial assignments that assign back to the same object. + // + // It covers these cases: + // val.x = val.y + // val.x[i] = val.y[j] + // val.x1.x2 = val.x1.y2 + // ... etc + // + // These assignments do not change assigned object lifetime. + + if dst == nil || src == nil || dst.Op() != src.Op() { + return false + } + + // The expression prefix must be both "safe" and identical. + switch dst.Op() { + case ir.ODOT, ir.ODOTPTR: + // Safe trailing accessors that are permitted to differ. + dst := dst.(*ir.SelectorExpr) + src := src.(*ir.SelectorExpr) + return ir.SameSafeExpr(dst.X, src.X) + case ir.OINDEX: + dst := dst.(*ir.IndexExpr) + src := src.(*ir.IndexExpr) + if mayAffectMemory(dst.Index) || mayAffectMemory(src.Index) { + return false + } + return ir.SameSafeExpr(dst.X, src.X) + default: + return false + } +} + +// mayAffectMemory reports whether evaluation of n may affect the program's +// memory state. If the expression can't affect memory state, then it can be +// safely ignored by the escape analysis. +func mayAffectMemory(n ir.Node) bool { + // We may want to use a list of "memory safe" ops instead of generally + // "side-effect free", which would include all calls and other ops that can + // allocate or change global state. For now, it's safer to start with the latter. + // + // We're ignoring things like division by zero, index out of range, + // and nil pointer dereference here. + + // TODO(rsc): It seems like it should be possible to replace this with + // an ir.Any looking for any op that's not the ones in the case statement. + // But that produces changes in the compiled output detected by buildall. + switch n.Op() { + case ir.ONAME, ir.OLITERAL, ir.ONIL: + return false + + case ir.OADD, ir.OSUB, ir.OOR, ir.OXOR, ir.OMUL, ir.OLSH, ir.ORSH, ir.OAND, ir.OANDNOT, ir.ODIV, ir.OMOD: + n := n.(*ir.BinaryExpr) + return mayAffectMemory(n.X) || mayAffectMemory(n.Y) + + case ir.OINDEX: + n := n.(*ir.IndexExpr) + return mayAffectMemory(n.X) || mayAffectMemory(n.Index) + + case ir.OCONVNOP, ir.OCONV: + n := n.(*ir.ConvExpr) + return mayAffectMemory(n.X) + + case ir.OLEN, ir.OCAP, ir.ONOT, ir.OBITNOT, ir.OPLUS, ir.ONEG, ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF: + n := n.(*ir.UnaryExpr) + return mayAffectMemory(n.X) + + case ir.ODOT, ir.ODOTPTR: + n := n.(*ir.SelectorExpr) + return mayAffectMemory(n.X) + + case ir.ODEREF: + n := n.(*ir.StarExpr) + return mayAffectMemory(n.X) + + default: + return true + } +} + +// HeapAllocReason returns the reason the given Node must be heap +// allocated, or the empty string if it doesn't. +func HeapAllocReason(n ir.Node) string { + if n == nil || n.Type() == nil { + return "" + } + + // Parameters are always passed via the stack. + if n.Op() == ir.ONAME { + n := n.(*ir.Name) + if n.Class == ir.PPARAM || n.Class == ir.PPARAMOUT { + return "" + } + } + + if n.Type().Width > ir.MaxStackVarSize { + return "too large for stack" + } + + if (n.Op() == ir.ONEW || n.Op() == ir.OPTRLIT) && n.Type().Elem().Width >= ir.MaxImplicitStackVarSize { + return "too large for stack" + } + + if n.Op() == ir.OCLOSURE && typecheck.ClosureType(n.(*ir.ClosureExpr)).Size() >= ir.MaxImplicitStackVarSize { + return "too large for stack" + } + if n.Op() == ir.OCALLPART && typecheck.PartialCallType(n.(*ir.SelectorExpr)).Size() >= ir.MaxImplicitStackVarSize { + return "too large for stack" + } + + if n.Op() == ir.OMAKESLICE { + n := n.(*ir.MakeExpr) + r := n.Cap + if r == nil { + r = n.Len + } + if !ir.IsSmallIntConst(r) { + return "non-constant size" + } + if t := n.Type(); t.Elem().Width != 0 && ir.Int64Val(r) >= ir.MaxImplicitStackVarSize/t.Elem().Width { + return "too large for stack" + } + } + + return "" +} -- GitLab From 541612b9746c1c314884af4079bfe8d340aaf953 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Mon, 21 Jun 2021 20:12:20 -0400 Subject: [PATCH 0330/2500] [dev.typeparams] cmd/gofmt: remove typeparams guards Remove logic related to guarding against allowing type parameters from cmd/gofmt. At this point, it was only restricting tests. Change-Id: Idd198389aaa422636d61af547a37be49f3be6c97 Reviewed-on: https://go-review.googlesource.com/c/go/+/329931 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/gofmt/doc.go | 3 --- src/cmd/gofmt/gofmt_test.go | 7 ------- src/cmd/gofmt/gofmt_typeparams_test.go | 12 ------------ src/cmd/gofmt/testdata/typeparams.golden | 2 +- src/cmd/gofmt/testdata/typeparams.input | 2 +- 5 files changed, 2 insertions(+), 24 deletions(-) delete mode 100644 src/cmd/gofmt/gofmt_typeparams_test.go diff --git a/src/cmd/gofmt/doc.go b/src/cmd/gofmt/doc.go index 68476e7d44..e340665594 100644 --- a/src/cmd/gofmt/doc.go +++ b/src/cmd/gofmt/doc.go @@ -26,9 +26,6 @@ The flags are: Do not print reformatted sources to standard output. If a file's formatting is different from gofmt's, print its name to standard output. - -G - Allow generic code, using type parameters. - See golang.org/issues/43651 for more information. -r rule Apply the rewrite rule to the source before reformatting. -s diff --git a/src/cmd/gofmt/gofmt_test.go b/src/cmd/gofmt/gofmt_test.go index f0d3f8780f..9ef7676214 100644 --- a/src/cmd/gofmt/gofmt_test.go +++ b/src/cmd/gofmt/gofmt_test.go @@ -54,8 +54,6 @@ func gofmtFlags(filename string, maxLines int) string { return "" } -var typeParamsEnabled = false - func runTest(t *testing.T, in, out string) { // process flags *simplifyAST = false @@ -78,11 +76,6 @@ func runTest(t *testing.T, in, out string) { case "-stdin": // fake flag - pretend input is from stdin stdin = true - case "-G": - // fake flag - test is for generic code - if !typeParamsEnabled { - return - } default: t.Errorf("unrecognized flag name: %s", name) } diff --git a/src/cmd/gofmt/gofmt_typeparams_test.go b/src/cmd/gofmt/gofmt_typeparams_test.go deleted file mode 100644 index 10641a77cb..0000000000 --- a/src/cmd/gofmt/gofmt_typeparams_test.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build typeparams -// +build typeparams - -package main - -func init() { - typeParamsEnabled = true -} diff --git a/src/cmd/gofmt/testdata/typeparams.golden b/src/cmd/gofmt/testdata/typeparams.golden index 35f08d1379..f71bd130db 100644 --- a/src/cmd/gofmt/testdata/typeparams.golden +++ b/src/cmd/gofmt/testdata/typeparams.golden @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//gofmt -G +//gofmt package typeparams diff --git a/src/cmd/gofmt/testdata/typeparams.input b/src/cmd/gofmt/testdata/typeparams.input index 7f3212c8e4..5d4c53d9f7 100644 --- a/src/cmd/gofmt/testdata/typeparams.input +++ b/src/cmd/gofmt/testdata/typeparams.input @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//gofmt -G +//gofmt package typeparams -- GitLab From 62095c66e042024fc631a3e9514b637ae4b5ae10 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Tue, 22 Jun 2021 10:13:54 -0400 Subject: [PATCH 0331/2500] [dev.typeparams] go/types: adjust logic for method expression arg naming CL 325369 improved this logic in types2. Port this improvement back to go/types. Change-Id: I5f859cbffd88bb3db09a81c2389269f7bd0869f9 Reviewed-on: https://go-review.googlesource.com/c/go/+/330069 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/call.go | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/go/types/call.go b/src/go/types/call.go index 3a04121e98..039c7bbaf5 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -587,16 +587,15 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { if sig.params != nil { params = sig.params.vars } - // Be consistent about named/unnamed parameters. - needName := true - for _, param := range params { - if param.Name() == "" { - needName = false - break - } - } + // Be consistent about named/unnamed parameters. This is not needed + // for type-checking, but the newly constructed signature may appear + // in an error message and then have mixed named/unnamed parameters. + // (An alternative would be to not print parameter names in errors, + // but it's useful to see them; this is cheap and method expressions + // are rare.) name := "" - if needName { + if len(params) > 0 && params[0].name != "" { + // name needed name = sig.recv.name if name == "" { name = "_" -- GitLab From c4e0c652fbf3b17cc89f72c6569fe255fe5e1047 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 22 Jun 2021 18:10:59 -0700 Subject: [PATCH 0332/2500] [dev.typeparams] cmd/compile: refactor CaptureName CaptureName currently does a few things: checks if a variable needs to be captured at all; checks if the variable has already been captured; and creates and saves a new variable. This full suite of functionality is useful for noder and irgen, but unified IR and other backend code only has a need for the last feature. This CL refactors CaptureName a little bit and extracts out NewClosureVar as a function usable for callers that don't need the extra features of CaptureName. Change-Id: I8a67c6375e44babe53344bf78e335535c57f9607 Reviewed-on: https://go-review.googlesource.com/c/go/+/330193 Trust: Matthew Dempsky Trust: Cuong Manh Le Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/ir/name.go | 47 +++++++++++++++--------- src/cmd/compile/internal/noder/reader.go | 13 ++----- 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index b6c68bc5e0..ff9784df1b 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -358,39 +358,52 @@ func (n *Name) Byval() bool { return n.Canonical().flags&nameByval != 0 } +// NewClosureVar creates a new closure variable for fn to refer to +// outer variable n. +func NewClosureVar(pos src.XPos, fn *Func, n *Name) *Name { + c := NewNameAt(pos, n.Sym()) + c.Curfn = fn + c.Class = PAUTOHEAP + c.SetIsClosureVar(true) + c.Defn = n.Canonical() + c.Outer = n + + fn.ClosureVars = append(fn.ClosureVars, c) + + return c +} + // CaptureName returns a Name suitable for referring to n from within function // fn or from the package block if fn is nil. If n is a free variable declared -// within a function that encloses fn, then CaptureName returns a closure -// variable that refers to n and adds it to fn.ClosureVars. Otherwise, it simply -// returns n. +// within a function that encloses fn, then CaptureName returns the closure +// variable that refers to n within fn, creating it if necessary. +// Otherwise, it simply returns n. func CaptureName(pos src.XPos, fn *Func, n *Name) *Name { - if n.IsClosureVar() { - base.FatalfAt(pos, "misuse of CaptureName on closure variable: %v", n) - } - if n.Op() != ONAME || n.Curfn == nil || n.Curfn == fn { + if n.Op() != ONAME || n.Curfn == nil { return n // okay to use directly } - if fn == nil { - base.FatalfAt(pos, "package-block reference to %v, declared in %v", n, n.Curfn) + if n.IsClosureVar() { + base.FatalfAt(pos, "misuse of CaptureName on closure variable: %v", n) } c := n.Innermost - if c != nil && c.Curfn == fn { + if c == nil { + c = n + } + if c.Curfn == fn { return c } + if fn == nil { + base.FatalfAt(pos, "package-block reference to %v, declared in %v", n, n.Curfn) + } + // Do not have a closure var for the active closure yet; make one. - c = NewNameAt(pos, n.Sym()) - c.Curfn = fn - c.Class = PAUTOHEAP - c.SetIsClosureVar(true) - c.Defn = n + c = NewClosureVar(pos, fn, c) // Link into list of active closure variables. // Popped from list in FinishCaptureNames. - c.Outer = n.Innermost n.Innermost = c - fn.ClosureVars = append(fn.ClosureVars, c) return c } diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 4fc9e7a777..b106e89892 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -1558,20 +1558,13 @@ func (r *reader) funcLit() ir.Node { fn.Nname.Ntype = ir.TypeNodeAt(typPos, xtype2) } - fn.ClosureVars = make([]*ir.Name, r.len()) - for i := range fn.ClosureVars { + fn.ClosureVars = make([]*ir.Name, 0, r.len()) + for len(fn.ClosureVars) < cap(fn.ClosureVars) { pos := r.pos() outer := r.useLocal() - cv := ir.NewNameAt(pos, outer.Sym()) + cv := ir.NewClosureVar(pos, fn, outer) r.setType(cv, outer.Type()) - cv.Curfn = fn - cv.Class = ir.PAUTOHEAP - cv.SetIsClosureVar(true) - cv.Defn = outer.Canonical() - cv.Outer = outer - - fn.ClosureVars[i] = cv } r.addBody(fn) -- GitLab From 493e177639140d83807ae72b6ea840ce025416ce Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 22 Jun 2021 18:15:21 -0700 Subject: [PATCH 0333/2500] [dev.typeparams] cmd/compile: allow typecheck of OCHECKNIL This CL makes OCHECKNIL typecheckable. Simplifies IR construction code slightly, and gives one convenient place to check for misuse. Change-Id: I280b8e47eddcac12947a41d6f911b25bc12a66bf Reviewed-on: https://go-review.googlesource.com/c/go/+/330194 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/typecheck/stmt.go | 9 +++++++++ src/cmd/compile/internal/typecheck/typecheck.go | 4 ++++ src/cmd/compile/internal/walk/builtin.go | 5 ++--- src/cmd/compile/internal/walk/closure.go | 8 +++----- src/cmd/compile/internal/walk/order.go | 12 +----------- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/cmd/compile/internal/typecheck/stmt.go b/src/cmd/compile/internal/typecheck/stmt.go index 922a01bfbe..cd00f1b3d1 100644 --- a/src/cmd/compile/internal/typecheck/stmt.go +++ b/src/cmd/compile/internal/typecheck/stmt.go @@ -237,6 +237,15 @@ func plural(n int) string { return "s" } +// tcCheckNil typechecks an OCHECKNIL node. +func tcCheckNil(n *ir.UnaryExpr) ir.Node { + n.X = Expr(n.X) + if !n.X.Type().IsPtrShaped() { + base.FatalfAt(n.Pos(), "%L is not pointer shaped", n.X) + } + return n +} + // tcFor typechecks an OFOR node. func tcFor(n *ir.ForStmt) ir.Node { Stmts(n.Init()) diff --git a/src/cmd/compile/internal/typecheck/typecheck.go b/src/cmd/compile/internal/typecheck/typecheck.go index b1a4e193d6..0367f7b034 100644 --- a/src/cmd/compile/internal/typecheck/typecheck.go +++ b/src/cmd/compile/internal/typecheck/typecheck.go @@ -876,6 +876,10 @@ func typecheck1(n ir.Node, top int) ir.Node { n := n.(*ir.TailCallStmt) return n + case ir.OCHECKNIL: + n := n.(*ir.UnaryExpr) + return tcCheckNil(n) + case ir.OSELECT: tcSelect(n.(*ir.SelectStmt)) return n diff --git a/src/cmd/compile/internal/walk/builtin.go b/src/cmd/compile/internal/walk/builtin.go index 62eb4298f4..be0f4c5208 100644 --- a/src/cmd/compile/internal/walk/builtin.go +++ b/src/cmd/compile/internal/walk/builtin.go @@ -677,9 +677,8 @@ func walkUnsafeSlice(n *ir.BinaryExpr, init *ir.Nodes) ir.Node { ptr := walkExpr(n.X, init) - c := ir.NewUnaryExpr(n.Pos(), ir.OCHECKNIL, ptr) - c.SetTypecheck(1) - init.Append(c) + check := ir.NewUnaryExpr(n.Pos(), ir.OCHECKNIL, ptr) + init.Append(typecheck.Stmt(check)) // TODO(mdempsky): checkptr instrumentation. Maybe merge into length // check above, along with nil check? Need to be careful about diff --git a/src/cmd/compile/internal/walk/closure.go b/src/cmd/compile/internal/walk/closure.go index feda3c3b4f..5db907d01d 100644 --- a/src/cmd/compile/internal/walk/closure.go +++ b/src/cmd/compile/internal/walk/closure.go @@ -178,11 +178,9 @@ func walkCallPart(n *ir.SelectorExpr, init *ir.Nodes) ir.Node { n.X = cheapExpr(n.X, init) n.X = walkExpr(n.X, nil) - tab := typecheck.Expr(ir.NewUnaryExpr(base.Pos, ir.OITAB, n.X)) - - c := ir.NewUnaryExpr(base.Pos, ir.OCHECKNIL, tab) - c.SetTypecheck(1) - init.Append(c) + tab := ir.NewUnaryExpr(base.Pos, ir.OITAB, n.X) + check := ir.NewUnaryExpr(base.Pos, ir.OCHECKNIL, tab) + init.Append(typecheck.Stmt(check)) } typ := typecheck.PartialCallType(n) diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go index b9aff03240..4d40cf890e 100644 --- a/src/cmd/compile/internal/walk/order.go +++ b/src/cmd/compile/internal/walk/order.go @@ -762,7 +762,7 @@ func (o *orderState) stmt(n ir.Node) { o.out = append(o.out, n) o.cleanTemp(t) - case ir.OCLOSE, ir.ORECV: + case ir.OCHECKNIL, ir.OCLOSE, ir.OPANIC, ir.ORECV: n := n.(*ir.UnaryExpr) t := o.markTemp() n.X = o.expr(n.X, nil) @@ -835,16 +835,6 @@ func (o *orderState) stmt(n ir.Node) { orderBlock(&n.Else, o.free) o.out = append(o.out, n) - case ir.OPANIC: - n := n.(*ir.UnaryExpr) - t := o.markTemp() - n.X = o.expr(n.X, nil) - if !n.X.Type().IsEmptyInterface() { - base.FatalfAt(n.Pos(), "bad argument to panic: %L", n.X) - } - o.out = append(o.out, n) - o.cleanTemp(t) - case ir.ORANGE: // n.Right is the expression being ranged over. // order it, and then make a copy if we need one. -- GitLab From e59a19ccebe87b84e69625d0b83df6d0fe2499db Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 22 Jun 2021 20:33:00 -0700 Subject: [PATCH 0334/2500] [dev.typeparams] cmd/compile: simplify walkGoDefer order already takes care of wrapping all go/defer function calls, so there's no need for walk to duplicate that logic: it's never going to be used. Change-Id: I54e545404e52ab8f9d60151d1bd2aff4b9bd8b72 Reviewed-on: https://go-review.googlesource.com/c/go/+/330270 Run-TryBot: Matthew Dempsky Reviewed-by: Cuong Manh Le Trust: Cuong Manh Le Trust: Matthew Dempsky TryBot-Result: Go Bot --- src/cmd/compile/internal/walk/stmt.go | 128 ++++---------------------- 1 file changed, 16 insertions(+), 112 deletions(-) diff --git a/src/cmd/compile/internal/walk/stmt.go b/src/cmd/compile/internal/walk/stmt.go index 0bf76680c4..e1ac652364 100644 --- a/src/cmd/compile/internal/walk/stmt.go +++ b/src/cmd/compile/internal/walk/stmt.go @@ -7,7 +7,6 @@ package walk import ( "cmd/compile/internal/base" "cmd/compile/internal/ir" - "cmd/compile/internal/typecheck" ) // The result of walkStmt MUST be assigned back to n, e.g. @@ -187,33 +186,26 @@ func walkFor(n *ir.ForStmt) ir.Node { return n } +// validGoDeferCall reports whether call is a valid call to appear in +// a go or defer statement; that is, whether it's a regular function +// call without arguments or results. +func validGoDeferCall(call ir.Node) bool { + if call, ok := call.(*ir.CallExpr); ok && call.Op() == ir.OCALLFUNC && len(call.KeepAlive) == 0 { + sig := call.X.Type() + return sig.NumParams()+sig.NumResults() == 0 + } + return false +} + // walkGoDefer walks an OGO or ODEFER node. func walkGoDefer(n *ir.GoDeferStmt) ir.Node { - var init ir.Nodes - switch call := n.Call; call.Op() { - case ir.OPRINT, ir.OPRINTN: - call := call.(*ir.CallExpr) - n.Call = wrapCall(call, &init) - - case ir.ODELETE: - call := call.(*ir.CallExpr) - n.Call = wrapCall(call, &init) - - case ir.OCOPY: - call := call.(*ir.BinaryExpr) - n.Call = walkCopy(call, &init, true) + if !validGoDeferCall(n.Call) { + base.FatalfAt(n.Pos(), "invalid %v call: %v", n.Op(), n.Call) + } - case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER: - call := call.(*ir.CallExpr) - if len(call.KeepAlive) > 0 { - n.Call = wrapCall(call, &init) - } else { - n.Call = walkExpr(call, &init) - } + var init ir.Nodes + n.Call = walkExpr(n.Call, &init) - default: - n.Call = walkExpr(call, &init) - } if len(init) > 0 { init.Append(n) return ir.NewBlockStmt(n.Pos(), init) @@ -229,94 +221,6 @@ func walkIf(n *ir.IfStmt) ir.Node { return n } -// Rewrite -// go builtin(x, y, z) -// into -// go func(a1, a2, a3) { -// builtin(a1, a2, a3) -// }(x, y, z) -// for print, println, and delete. -// -// Rewrite -// go f(x, y, uintptr(unsafe.Pointer(z))) -// into -// go func(a1, a2, a3) { -// f(a1, a2, uintptr(a3)) -// }(x, y, unsafe.Pointer(z)) -// for function contains unsafe-uintptr arguments. - -var wrapCall_prgen int - -// The result of wrapCall MUST be assigned back to n, e.g. -// n.Left = wrapCall(n.Left, init) -func wrapCall(n *ir.CallExpr, init *ir.Nodes) ir.Node { - if len(n.Init()) != 0 { - walkStmtList(n.Init()) - init.Append(ir.TakeInit(n)...) - } - - isBuiltinCall := n.Op() != ir.OCALLFUNC && n.Op() != ir.OCALLMETH && n.Op() != ir.OCALLINTER - - // Turn f(a, b, []T{c, d, e}...) back into f(a, b, c, d, e). - if !isBuiltinCall && n.IsDDD { - undoVariadic(n) - } - - wrapArgs := n.Args - // If there's a receiver argument, it needs to be passed through the wrapper too. - if n.Op() == ir.OCALLMETH || n.Op() == ir.OCALLINTER { - recv := n.X.(*ir.SelectorExpr).X - wrapArgs = append([]ir.Node{recv}, wrapArgs...) - } - - // origArgs keeps track of what argument is uintptr-unsafe/unsafe-uintptr conversion. - origArgs := make([]ir.Node, len(wrapArgs)) - var funcArgs []*ir.Field - for i, arg := range wrapArgs { - s := typecheck.LookupNum("a", i) - if !isBuiltinCall && arg.Op() == ir.OCONVNOP && arg.Type().IsUintptr() && arg.(*ir.ConvExpr).X.Type().IsUnsafePtr() { - origArgs[i] = arg - arg = arg.(*ir.ConvExpr).X - wrapArgs[i] = arg - } - funcArgs = append(funcArgs, ir.NewField(base.Pos, s, nil, arg.Type())) - } - t := ir.NewFuncType(base.Pos, nil, funcArgs, nil) - - wrapCall_prgen++ - sym := typecheck.LookupNum("wrap·", wrapCall_prgen) - fn := typecheck.DeclFunc(sym, t) - - args := ir.ParamNames(t.Type()) - for i, origArg := range origArgs { - if origArg == nil { - continue - } - args[i] = ir.NewConvExpr(base.Pos, origArg.Op(), origArg.Type(), args[i]) - } - if n.Op() == ir.OCALLMETH || n.Op() == ir.OCALLINTER { - // Move wrapped receiver argument back to its appropriate place. - recv := typecheck.Expr(args[0]) - n.X.(*ir.SelectorExpr).X = recv - args = args[1:] - } - call := ir.NewCallExpr(base.Pos, n.Op(), n.X, args) - if !isBuiltinCall { - call.SetOp(ir.OCALL) - call.IsDDD = n.IsDDD - } - fn.Body = []ir.Node{call} - - typecheck.FinishFuncBody() - - typecheck.Func(fn) - typecheck.Stmts(fn.Body) - typecheck.Target.Decls = append(typecheck.Target.Decls, fn) - - call = ir.NewCallExpr(base.Pos, ir.OCALL, fn.Nname, wrapArgs) - return walkExpr(typecheck.Stmt(call), init) -} - // undoVariadic turns a call to a variadic function of the form // // f(a, b, []T{c, d, e}...) -- GitLab From 1a445dab6676b2a5c0b15b313eabec5a79ea99a3 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 22 Jun 2021 20:37:42 -0700 Subject: [PATCH 0335/2500] [dev.typeparams] cmd/compile: remove CallExpr.PreserveClosure This flag is only needed to prevent the directClosureCall optimization in walkCall, when called for walkGoDefer. But walkGoDefer don't need to call walkCall: at this point in the compile, the call expression isn't a real call anymore. Instead, we just need to walkExpr on the function expression. Change-Id: I8a5176cfe1bff53700cbd21ed1b479ebd9a839ad Reviewed-on: https://go-review.googlesource.com/c/go/+/330271 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le Trust: Matthew Dempsky --- src/cmd/compile/internal/ir/expr.go | 13 ++++++------- src/cmd/compile/internal/walk/closure.go | 8 -------- src/cmd/compile/internal/walk/order.go | 6 +----- src/cmd/compile/internal/walk/stmt.go | 4 +++- 4 files changed, 10 insertions(+), 21 deletions(-) diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 779793b2f2..b46fd905fe 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -157,13 +157,12 @@ const ( type CallExpr struct { miniExpr origNode - X Node - Args Nodes - KeepAlive []*Name // vars to be kept alive until call returns - IsDDD bool - Use CallUse - NoInline bool - PreserveClosure bool // disable directClosureCall for this call + X Node + Args Nodes + KeepAlive []*Name // vars to be kept alive until call returns + IsDDD bool + Use CallUse + NoInline bool } func NewCallExpr(pos src.XPos, op Op, fun Node, args []Node) *CallExpr { diff --git a/src/cmd/compile/internal/walk/closure.go b/src/cmd/compile/internal/walk/closure.go index 5db907d01d..2b7fe8f926 100644 --- a/src/cmd/compile/internal/walk/closure.go +++ b/src/cmd/compile/internal/walk/closure.go @@ -37,14 +37,6 @@ func directClosureCall(n *ir.CallExpr) { return // leave for walkClosure to handle } - // If wrapGoDefer() in the order phase has flagged this call, - // avoid eliminating the closure even if there is a direct call to - // (the closure is needed to simplify the register ABI). See - // wrapGoDefer for more details. - if n.PreserveClosure { - return - } - // We are going to insert captured variables before input args. var params []*types.Field var decls []*ir.Name diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go index 4d40cf890e..c24f80508a 100644 --- a/src/cmd/compile/internal/walk/order.go +++ b/src/cmd/compile/internal/walk/order.go @@ -1564,11 +1564,10 @@ func (o *orderState) wrapGoDefer(n *ir.GoDeferStmt) { // TODO: maybe not wrap if the called function has no arguments and // only in-register results? if len(callArgs) == 0 && call.Op() == ir.OCALLFUNC && callX.Type().NumResults() == 0 { - if c, ok := call.(*ir.CallExpr); ok && callX != nil && callX.Op() == ir.OCLOSURE { + if callX.Op() == ir.OCLOSURE { clo := callX.(*ir.ClosureExpr) clo.Func.SetClosureCalled(false) clo.IsGoWrap = true - c.PreserveClosure = true } return } @@ -1771,9 +1770,6 @@ func (o *orderState) wrapGoDefer(n *ir.GoDeferStmt) { topcall := ir.NewCallExpr(n.Pos(), ir.OCALL, clo, nil) typecheck.Call(topcall) - // Tag the call to insure that directClosureCall doesn't undo our work. - topcall.PreserveClosure = true - fn.SetClosureCalled(false) // Finally, point the defer statement at the newly generated call. diff --git a/src/cmd/compile/internal/walk/stmt.go b/src/cmd/compile/internal/walk/stmt.go index e1ac652364..2352719da3 100644 --- a/src/cmd/compile/internal/walk/stmt.go +++ b/src/cmd/compile/internal/walk/stmt.go @@ -204,7 +204,9 @@ func walkGoDefer(n *ir.GoDeferStmt) ir.Node { } var init ir.Nodes - n.Call = walkExpr(n.Call, &init) + + call := n.Call.(*ir.CallExpr) + call.X = walkExpr(call.X, &init) if len(init) > 0 { init.Append(n) -- GitLab From 99732b9070ea23c13f7ed9ff8518304e34942ad4 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 22 Jun 2021 20:53:14 -0700 Subject: [PATCH 0336/2500] [dev.typeparams] cmd/compile: refactor escape analysis of calls This CL is a prep refactoring for an upcoming CL to move go/defer wrapping into escape analysis. That CL is unfortunately unavoidably complex and subtle, so this CL takes care of some more mundane refactoring details. Change-Id: Ifbefe1d522a8d57066646be09536437f42e7082c Reviewed-on: https://go-review.googlesource.com/c/go/+/330251 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Matthew Dempsky Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/escape/call.go | 78 ++++++++++++++----------- src/cmd/compile/internal/escape/expr.go | 2 +- src/cmd/compile/internal/escape/stmt.go | 7 +-- 3 files changed, 48 insertions(+), 39 deletions(-) diff --git a/src/cmd/compile/internal/escape/call.go b/src/cmd/compile/internal/escape/call.go index 28a3b679a5..8511259d47 100644 --- a/src/cmd/compile/internal/escape/call.go +++ b/src/cmd/compile/internal/escape/call.go @@ -13,26 +13,24 @@ import ( // call evaluates a call expressions, including builtin calls. ks // should contain the holes representing where the function callee's -// results flows; where is the OGO/ODEFER context of the call, if any. -func (e *escape) call(ks []hole, call, where ir.Node) { - topLevelDefer := where != nil && where.Op() == ir.ODEFER && e.loopDepth == 1 - if topLevelDefer { - // force stack allocation of defer record, unless - // open-coded defers are used (see ssa.go) - where.SetEsc(ir.EscNever) - } +// results flows. +func (e *escape) call(ks []hole, call ir.Node) { + e.callCommon(ks, call, nil) +} - argument := func(k hole, arg ir.Node) { - if topLevelDefer { - // Top level defers arguments don't escape to - // heap, but they do need to last until end of - // function. - k = e.later(k) - } else if where != nil { - k = e.heapHole() +func (e *escape) callCommon(ks []hole, call ir.Node, where *ir.GoDeferStmt) { + argument := func(k hole, argp *ir.Node) { + if where != nil { + if where.Esc() == ir.EscNever { + // Top-level defers arguments don't escape to heap, + // but they do need to last until end of function. + k = e.later(k) + } else { + k = e.heapHole() + } } - e.expr(k.note(call, "call parameter"), arg) + e.expr(k.note(call, "call parameter"), *argp) } switch call.Op() { @@ -70,15 +68,15 @@ func (e *escape) call(ks []hole, call, where ir.Node) { } if r := fntype.Recv(); r != nil { - argument(e.tagHole(ks, fn, r), call.X.(*ir.SelectorExpr).X) + argument(e.tagHole(ks, fn, r), &call.X.(*ir.SelectorExpr).X) } else { // Evaluate callee function expression. - argument(e.discardHole(), call.X) + argument(e.discardHole(), &call.X) } args := call.Args for i, param := range fntype.Params().FieldSlice() { - argument(e.tagHole(ks, fn, param), args[i]) + argument(e.tagHole(ks, fn, param), &args[i]) } case ir.OAPPEND: @@ -93,54 +91,66 @@ func (e *escape) call(ks []hole, call, where ir.Node) { if args[0].Type().Elem().HasPointers() { appendeeK = e.teeHole(appendeeK, e.heapHole().deref(call, "appendee slice")) } - argument(appendeeK, args[0]) + argument(appendeeK, &args[0]) if call.IsDDD { appendedK := e.discardHole() if args[1].Type().IsSlice() && args[1].Type().Elem().HasPointers() { appendedK = e.heapHole().deref(call, "appended slice...") } - argument(appendedK, args[1]) + argument(appendedK, &args[1]) } else { - for _, arg := range args[1:] { - argument(e.heapHole(), arg) + for i := 1; i < len(args); i++ { + argument(e.heapHole(), &args[i]) } } case ir.OCOPY: call := call.(*ir.BinaryExpr) - argument(e.discardHole(), call.X) + argument(e.discardHole(), &call.X) copiedK := e.discardHole() if call.Y.Type().IsSlice() && call.Y.Type().Elem().HasPointers() { copiedK = e.heapHole().deref(call, "copied slice") } - argument(copiedK, call.Y) + argument(copiedK, &call.Y) case ir.OPANIC: call := call.(*ir.UnaryExpr) - argument(e.heapHole(), call.X) + argument(e.heapHole(), &call.X) case ir.OCOMPLEX: call := call.(*ir.BinaryExpr) - argument(e.discardHole(), call.X) - argument(e.discardHole(), call.Y) + argument(e.discardHole(), &call.X) + argument(e.discardHole(), &call.Y) case ir.ODELETE, ir.OPRINT, ir.OPRINTN, ir.ORECOVER: call := call.(*ir.CallExpr) - for _, arg := range call.Args { - argument(e.discardHole(), arg) + for i := range call.Args { + argument(e.discardHole(), &call.Args[i]) } case ir.OLEN, ir.OCAP, ir.OREAL, ir.OIMAG, ir.OCLOSE: call := call.(*ir.UnaryExpr) - argument(e.discardHole(), call.X) + argument(e.discardHole(), &call.X) case ir.OUNSAFEADD, ir.OUNSAFESLICE: call := call.(*ir.BinaryExpr) - argument(ks[0], call.X) - argument(e.discardHole(), call.Y) + argument(ks[0], &call.X) + argument(e.discardHole(), &call.Y) } } +func (e *escape) goDeferStmt(n *ir.GoDeferStmt) { + topLevelDefer := n.Op() == ir.ODEFER && e.loopDepth == 1 + if topLevelDefer { + // force stack allocation of defer record, unless + // open-coded defers are used (see ssa.go) + n.SetEsc(ir.EscNever) + } + + e.stmts(n.Call.Init()) + e.callCommon(nil, n.Call, n) +} + // tagHole returns a hole for evaluating an argument passed to param. // ks should contain the holes representing where the function // callee's results flows. fn is the statically-known callee function, diff --git a/src/cmd/compile/internal/escape/expr.go b/src/cmd/compile/internal/escape/expr.go index 5b280c76f1..cb95221dd5 100644 --- a/src/cmd/compile/internal/escape/expr.go +++ b/src/cmd/compile/internal/escape/expr.go @@ -139,7 +139,7 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) { e.discard(n.X) case ir.OCALLMETH, ir.OCALLFUNC, ir.OCALLINTER, ir.OLEN, ir.OCAP, ir.OCOMPLEX, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.OCOPY, ir.OUNSAFEADD, ir.OUNSAFESLICE: - e.call([]hole{k}, n, nil) + e.call([]hole{k}, n) case ir.ONEW: n := n.(*ir.UnaryExpr) diff --git a/src/cmd/compile/internal/escape/stmt.go b/src/cmd/compile/internal/escape/stmt.go index d3e47290d3..0bdb07b278 100644 --- a/src/cmd/compile/internal/escape/stmt.go +++ b/src/cmd/compile/internal/escape/stmt.go @@ -163,7 +163,7 @@ func (e *escape) stmt(n ir.Node) { n := n.(*ir.AssignListStmt) e.stmts(n.Rhs[0].Init()) ks := e.addrs(n.Lhs) - e.call(ks, n.Rhs[0], nil) + e.call(ks, n.Rhs[0]) e.reassigned(ks, n) case ir.ORETURN: n := n.(*ir.ReturnStmt) @@ -174,11 +174,10 @@ func (e *escape) stmt(n ir.Node) { } e.assignList(dsts, n.Results, "return", n) case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER, ir.OCLOSE, ir.OCOPY, ir.ODELETE, ir.OPANIC, ir.OPRINT, ir.OPRINTN, ir.ORECOVER: - e.call(nil, n, nil) + e.call(nil, n) case ir.OGO, ir.ODEFER: n := n.(*ir.GoDeferStmt) - e.stmts(n.Call.Init()) - e.call(nil, n.Call, n) + e.goDeferStmt(n) case ir.OTAILCALL: // TODO(mdempsky): Treat like a normal call? esc.go used to just ignore it. -- GitLab From 107b1fce6401b7f5fa12f6e51746a2d0c86b65ca Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 23 Jun 2021 14:39:44 +0700 Subject: [PATCH 0337/2500] [dev.typeparams] cmd/compile: explain why expandInline needed Change-Id: Ica9817675b4eb929a000640f9ae873b75fc5a2e3 Reviewed-on: https://go-review.googlesource.com/c/go/+/330290 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/noder/reader.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index b106e89892..df9dccc156 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -1956,8 +1956,9 @@ func (r *reader) inlReturn(ret *ir.ReturnStmt) *ir.BlockStmt { // expandInline reads in an extra copy of IR to populate // fn.Inl.{Dcl,Body}. func expandInline(fn *ir.Func, pri pkgReaderIndex) { - // TODO(mdempsky): Remove this function. It's currently needed for - // dwarfgen for some reason, but we should be able to provide it + // TODO(mdempsky): Remove this function. It's currently needed by + // dwarfgen/dwarf.go:preInliningDcls, which requires fn.Inl.Dcl to + // create abstract function DIEs. But we should be able to provide it // with the same information some other way. fndcls := len(fn.Dcl) -- GitLab From 70f4ab656575842b3a4ce54960f2c3eb7230e8a6 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 22 Jun 2021 22:21:09 -0700 Subject: [PATCH 0338/2500] [dev.typeparams] cmd/compile: remove SetClosureCalled(false) hacks The current go/defer wrapping code goes to some length to clear ClosureCalled when a function call will end up not being called directly, and so it will need to use the context register. But we already have a flag to indicate we need to use the context register: Needctxt. The real issue here is just that buildssa was using fn.ClosureCalled instead of fn.Needctxt. Change-Id: Ic9f5f23b66eb467fc61fa84eacb45d46c54133d2 Reviewed-on: https://go-review.googlesource.com/c/go/+/330329 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/ssagen/ssa.go | 2 +- src/cmd/compile/internal/walk/order.go | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 7a6bf878e1..659ba02b5b 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -535,7 +535,7 @@ func buildssa(fn *ir.Func, worker int) *ssa.Func { } // Populate closure variables. - if !fn.ClosureCalled() { + if fn.Needctxt() { clo := s.entryNewValue0(ssa.OpGetClosurePtr, s.f.Config.Types.BytePtr) offset := int64(types.PtrSize) // PtrSize to skip past function entry PC field for _, n := range fn.ClosureVars { diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go index c24f80508a..75657cd3e4 100644 --- a/src/cmd/compile/internal/walk/order.go +++ b/src/cmd/compile/internal/walk/order.go @@ -1566,7 +1566,6 @@ func (o *orderState) wrapGoDefer(n *ir.GoDeferStmt) { if len(callArgs) == 0 && call.Op() == ir.OCALLFUNC && callX.Type().NumResults() == 0 { if callX.Op() == ir.OCLOSURE { clo := callX.(*ir.ClosureExpr) - clo.Func.SetClosureCalled(false) clo.IsGoWrap = true } return @@ -1691,12 +1690,6 @@ func (o *orderState) wrapGoDefer(n *ir.GoDeferStmt) { // Deal with "defer returnsafunc()(x, y)" (for // example) by copying the callee expression. fnExpr = mkArgCopy(callX) - if callX.Op() == ir.OCLOSURE { - // For "defer func(...)", in addition to copying the - // closure into a temp, mark it as no longer directly - // called. - callX.(*ir.ClosureExpr).Func.SetClosureCalled(false) - } } } @@ -1770,8 +1763,6 @@ func (o *orderState) wrapGoDefer(n *ir.GoDeferStmt) { topcall := ir.NewCallExpr(n.Pos(), ir.OCALL, clo, nil) typecheck.Call(topcall) - fn.SetClosureCalled(false) - // Finally, point the defer statement at the newly generated call. n.Call = topcall } -- GitLab From 9be8303df9e3aa5f4ea1879e82a3edbf54b78dbf Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 22 Jun 2021 13:45:51 -0700 Subject: [PATCH 0339/2500] [dev.typeparams] cmd/compile: add ORECOVERFP, OGETCALLER{PC,SP} ops This CLs adds new frontend ops that will be used in the next CL. Split out separately so generated code is less distracting in the main CL. Change-Id: I66125e0ec2217bfa05f7b0ea0bc99ada13f563f7 Reviewed-on: https://go-review.googlesource.com/c/go/+/330191 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/compile/internal/ir/node.go | 7 +- src/cmd/compile/internal/ir/op_string.go | 115 ++++++++++++----------- 2 files changed, 64 insertions(+), 58 deletions(-) diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 7c3dc10e46..fa7c9cc276 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -237,6 +237,7 @@ const ( OSLICE3ARR // X[Low : High : Max] (X is pointer to array) OSLICEHEADER // sliceheader{Ptr, Len, Cap} (Ptr is unsafe.Pointer, Len is length, Cap is capacity) ORECOVER // recover() + ORECOVERFP // recover(Args) w/ explicit FP argument ORECV // <-X ORUNESTR // Type(X) (Type is string, X is rune) OSELRECV2 // like OAS2: Lhs = Rhs where len(Lhs)=2, len(Rhs)=1, Rhs[0].Op = ORECV (appears as .Var of OCASE) @@ -318,8 +319,10 @@ const ( OLINKSYMOFFSET // offset within a name // arch-specific opcodes - OTAILCALL // tail call to another function - OGETG // runtime.getg() (read g pointer) + OTAILCALL // tail call to another function + OGETG // runtime.getg() (read g pointer) + OGETCALLERPC // runtime.getcallerpc() (continuation PC in caller frame) + OGETCALLERSP // runtime.getcallersp() (stack pointer in caller frame) OEND ) diff --git a/src/cmd/compile/internal/ir/op_string.go b/src/cmd/compile/internal/ir/op_string.go index 405a0c6b3c..80c8d09c1e 100644 --- a/src/cmd/compile/internal/ir/op_string.go +++ b/src/cmd/compile/internal/ir/op_string.go @@ -109,65 +109,68 @@ func _() { _ = x[OSLICE3ARR-98] _ = x[OSLICEHEADER-99] _ = x[ORECOVER-100] - _ = x[ORECV-101] - _ = x[ORUNESTR-102] - _ = x[OSELRECV2-103] - _ = x[OIOTA-104] - _ = x[OREAL-105] - _ = x[OIMAG-106] - _ = x[OCOMPLEX-107] - _ = x[OALIGNOF-108] - _ = x[OOFFSETOF-109] - _ = x[OSIZEOF-110] - _ = x[OUNSAFEADD-111] - _ = x[OUNSAFESLICE-112] - _ = x[OMETHEXPR-113] - _ = x[OBLOCK-114] - _ = x[OBREAK-115] - _ = x[OCASE-116] - _ = x[OCONTINUE-117] - _ = x[ODEFER-118] - _ = x[OFALL-119] - _ = x[OFOR-120] - _ = x[OFORUNTIL-121] - _ = x[OGOTO-122] - _ = x[OIF-123] - _ = x[OLABEL-124] - _ = x[OGO-125] - _ = x[ORANGE-126] - _ = x[ORETURN-127] - _ = x[OSELECT-128] - _ = x[OSWITCH-129] - _ = x[OTYPESW-130] - _ = x[OFUNCINST-131] - _ = x[OTCHAN-132] - _ = x[OTMAP-133] - _ = x[OTSTRUCT-134] - _ = x[OTINTER-135] - _ = x[OTFUNC-136] - _ = x[OTARRAY-137] - _ = x[OTSLICE-138] - _ = x[OINLCALL-139] - _ = x[OEFACE-140] - _ = x[OITAB-141] - _ = x[OIDATA-142] - _ = x[OSPTR-143] - _ = x[OCFUNC-144] - _ = x[OCHECKNIL-145] - _ = x[OVARDEF-146] - _ = x[OVARKILL-147] - _ = x[OVARLIVE-148] - _ = x[ORESULT-149] - _ = x[OINLMARK-150] - _ = x[OLINKSYMOFFSET-151] - _ = x[OTAILCALL-152] - _ = x[OGETG-153] - _ = x[OEND-154] + _ = x[ORECOVERFP-101] + _ = x[ORECV-102] + _ = x[ORUNESTR-103] + _ = x[OSELRECV2-104] + _ = x[OIOTA-105] + _ = x[OREAL-106] + _ = x[OIMAG-107] + _ = x[OCOMPLEX-108] + _ = x[OALIGNOF-109] + _ = x[OOFFSETOF-110] + _ = x[OSIZEOF-111] + _ = x[OUNSAFEADD-112] + _ = x[OUNSAFESLICE-113] + _ = x[OMETHEXPR-114] + _ = x[OBLOCK-115] + _ = x[OBREAK-116] + _ = x[OCASE-117] + _ = x[OCONTINUE-118] + _ = x[ODEFER-119] + _ = x[OFALL-120] + _ = x[OFOR-121] + _ = x[OFORUNTIL-122] + _ = x[OGOTO-123] + _ = x[OIF-124] + _ = x[OLABEL-125] + _ = x[OGO-126] + _ = x[ORANGE-127] + _ = x[ORETURN-128] + _ = x[OSELECT-129] + _ = x[OSWITCH-130] + _ = x[OTYPESW-131] + _ = x[OFUNCINST-132] + _ = x[OTCHAN-133] + _ = x[OTMAP-134] + _ = x[OTSTRUCT-135] + _ = x[OTINTER-136] + _ = x[OTFUNC-137] + _ = x[OTARRAY-138] + _ = x[OTSLICE-139] + _ = x[OINLCALL-140] + _ = x[OEFACE-141] + _ = x[OITAB-142] + _ = x[OIDATA-143] + _ = x[OSPTR-144] + _ = x[OCFUNC-145] + _ = x[OCHECKNIL-146] + _ = x[OVARDEF-147] + _ = x[OVARKILL-148] + _ = x[OVARLIVE-149] + _ = x[ORESULT-150] + _ = x[OINLMARK-151] + _ = x[OLINKSYMOFFSET-152] + _ = x[OTAILCALL-153] + _ = x[OGETG-154] + _ = x[OGETCALLERPC-155] + _ = x[OGETCALLERSP-156] + _ = x[OEND-157] } -const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESSLICE2ARRPTRASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECVRUNESTRSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFUNSAFEADDUNSAFESLICEMETHEXPRBLOCKBREAKCASECONTINUEDEFERFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWFUNCINSTTCHANTMAPTSTRUCTTINTERTFUNCTARRAYTSLICEINLCALLEFACEITABIDATASPTRCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKLINKSYMOFFSETTAILCALLGETGEND" +const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESSLICE2ARRPTRASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECOVERFPRECVRUNESTRSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFUNSAFEADDUNSAFESLICEMETHEXPRBLOCKBREAKCASECONTINUEDEFERFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWFUNCINSTTCHANTMAPTSTRUCTTINTERTFUNCTARRAYTSLICEINLCALLEFACEITABIDATASPTRCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKLINKSYMOFFSETTAILCALLGETGGETCALLERPCGETCALLERSPEND" -var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 136, 138, 141, 151, 158, 165, 172, 176, 180, 188, 196, 205, 213, 216, 221, 228, 235, 241, 250, 258, 266, 272, 276, 285, 292, 296, 299, 306, 314, 321, 327, 330, 336, 343, 351, 355, 362, 370, 372, 374, 376, 378, 380, 382, 387, 392, 400, 403, 412, 415, 419, 427, 434, 443, 456, 459, 462, 465, 468, 471, 474, 480, 483, 486, 492, 496, 499, 503, 508, 513, 519, 524, 528, 533, 541, 549, 555, 564, 575, 582, 586, 593, 601, 605, 609, 613, 620, 627, 635, 641, 650, 661, 669, 674, 679, 683, 691, 696, 700, 703, 711, 715, 717, 722, 724, 729, 735, 741, 747, 753, 761, 766, 770, 777, 783, 788, 794, 800, 807, 812, 816, 821, 825, 830, 838, 844, 851, 858, 864, 871, 884, 892, 896, 899} +var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 136, 138, 141, 151, 158, 165, 172, 176, 180, 188, 196, 205, 213, 216, 221, 228, 235, 241, 250, 258, 266, 272, 276, 285, 292, 296, 299, 306, 314, 321, 327, 330, 336, 343, 351, 355, 362, 370, 372, 374, 376, 378, 380, 382, 387, 392, 400, 403, 412, 415, 419, 427, 434, 443, 456, 459, 462, 465, 468, 471, 474, 480, 483, 486, 492, 496, 499, 503, 508, 513, 519, 524, 528, 533, 541, 549, 555, 564, 575, 582, 591, 595, 602, 610, 614, 618, 622, 629, 636, 644, 650, 659, 670, 678, 683, 688, 692, 700, 705, 709, 712, 720, 724, 726, 731, 733, 738, 744, 750, 756, 762, 770, 775, 779, 786, 792, 797, 803, 809, 816, 821, 825, 830, 834, 839, 847, 853, 860, 867, 873, 880, 893, 901, 905, 916, 927, 930} func (i Op) String() string { if i >= Op(len(_Op_index)-1) { -- GitLab From 3fa42437b5d6326aa1ae04726ad4319459280433 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Mon, 21 Jun 2021 15:22:32 -0700 Subject: [PATCH 0340/2500] [dev.fuzz] internal/fuzz: fix race in worker RPC logic We want worker RPCs to return as soon as the context is cancelled, which happens if the user presses ^C, we hit the time limit, or another worker discovers a crasher. RPCs typically block when reading pipes: the server waits for call arguments from the client, and the client waits for results from the server. Since io.Reader.Read doesn't accept a context.Context and reads on pipe file descriptors are difficult to reliably unblock, we've done this by calling Read in a goroutine, and returning from the parent function when ctx.Done() is closed, even if the underlying goroutine isn't finished. In workerServer.serve, we also called the fuzz function in the same goroutine. This resulted in a bug: serve could return while the fuzz function was still running. The fuzz function could observe side effects from cleanup functions registered with F.Cleanup. This change refactors read cancellation logic into contextReader. Only the underlying Read is done in a goroutine. workerServe.serve won't return while the fuzz function is running. Fixes #46632 Change-Id: Id1ed31f6521155c7c8e76dd52a2d70aa93cab201 Reviewed-on: https://go-review.googlesource.com/c/go/+/329920 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/internal/fuzz/worker.go | 143 +++++++++++++++++------------------- 1 file changed, 68 insertions(+), 75 deletions(-) diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 34871024c3..e1fc999104 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -577,57 +577,33 @@ type workerServer struct { // does not return errors from method calls; those are passed through serialized // responses. func (ws *workerServer) serve(ctx context.Context) error { - // This goroutine may stay blocked after serve returns because the underlying - // read blocks, even after the file descriptor in this process is closed. The - // pipe must be closed by the client, too. - errC := make(chan error, 1) - go func() { - enc := json.NewEncoder(ws.fuzzOut) - dec := json.NewDecoder(ws.fuzzIn) - for { - if ctx.Err() != nil { - return - } - - var c call - if err := dec.Decode(&c); err == io.EOF { - return - } else if err != nil { - errC <- err - return - } - if ctx.Err() != nil { - return - } - - var resp interface{} - switch { - case c.Fuzz != nil: - resp = ws.fuzz(ctx, *c.Fuzz) - case c.Minimize != nil: - resp = ws.minimize(ctx, *c.Minimize) - case c.Ping != nil: - resp = ws.ping(ctx, *c.Ping) - default: - errC <- errors.New("no arguments provided for any call") - return + enc := json.NewEncoder(ws.fuzzOut) + dec := json.NewDecoder(&contextReader{ctx: ctx, r: ws.fuzzIn}) + for { + var c call + if err := dec.Decode(&c); err != nil { + if err == io.EOF || err == ctx.Err() { + return nil + } else { + return err } + } - if err := enc.Encode(resp); err != nil { - errC <- err - return - } + var resp interface{} + switch { + case c.Fuzz != nil: + resp = ws.fuzz(ctx, *c.Fuzz) + case c.Minimize != nil: + resp = ws.minimize(ctx, *c.Minimize) + case c.Ping != nil: + resp = ws.ping(ctx, *c.Ping) + default: + return errors.New("no arguments provided for any call") } - }() - select { - case <-ctx.Done(): - // Stop handling messages when ctx.Done() is closed. This normally happens - // when the worker process receives a SIGINT signal, which on POSIX platforms - // is sent to the process group when ^C is pressed. - return ctx.Err() - case err := <-errC: - return err + if err := enc.Encode(resp); err != nil { + return err + } } } @@ -871,18 +847,11 @@ func (ws *workerServer) ping(ctx context.Context, args pingArgs) pingResponse { // workerServer). type workerClient struct { workerComm - - mu sync.Mutex - enc *json.Encoder - dec *json.Decoder + mu sync.Mutex } func newWorkerClient(comm workerComm) *workerClient { - return &workerClient{ - workerComm: comm, - enc: json.NewEncoder(comm.fuzzIn), - dec: json.NewDecoder(comm.fuzzOut), - } + return &workerClient{workerComm: comm} } // Close shuts down the connection to the RPC server (the worker process) by @@ -932,7 +901,7 @@ func (wc *workerClient) minimize(ctx context.Context, valueIn []byte, args minim wc.memMu <- mem c := call{Minimize: &args} - err = wc.call(ctx, c, &resp) + err = wc.callLocked(ctx, c, &resp) mem, ok = <-wc.memMu if !ok { return nil, minimizeResponse{}, errSharedMemClosed @@ -958,7 +927,7 @@ func (wc *workerClient) fuzz(ctx context.Context, valueIn []byte, args fuzzArgs) wc.memMu <- mem c := call{Fuzz: &args} - err = wc.call(ctx, c, &resp) + err = wc.callLocked(ctx, c, &resp) mem, ok = <-wc.memMu if !ok { return nil, fuzzResponse{}, errSharedMemClosed @@ -972,30 +941,54 @@ func (wc *workerClient) fuzz(ctx context.Context, valueIn []byte, args fuzzArgs) // ping tells the worker to call the ping method. See workerServer.ping. func (wc *workerClient) ping(ctx context.Context) error { + wc.mu.Lock() + defer wc.mu.Unlock() c := call{Ping: &pingArgs{}} var resp pingResponse - return wc.call(ctx, c, &resp) + return wc.callLocked(ctx, c, &resp) +} + +// callLocked sends an RPC from the coordinator to the worker process and waits +// for the response. The callLocked may be cancelled with ctx. +func (wc *workerClient) callLocked(ctx context.Context, c call, resp interface{}) (err error) { + enc := json.NewEncoder(wc.fuzzIn) + dec := json.NewDecoder(&contextReader{ctx: ctx, r: wc.fuzzOut}) + if err := enc.Encode(c); err != nil { + return err + } + return dec.Decode(resp) } -// call sends an RPC from the coordinator to the worker process and waits for -// the response. The call may be cancelled with ctx. -func (wc *workerClient) call(ctx context.Context, c call, resp interface{}) (err error) { - // This goroutine may stay blocked after call returns because the underlying - // read blocks, even after the file descriptor in this process is closed. The - // pipe must be closed by the server, too. - errC := make(chan error, 1) +// contextReader wraps a Reader with a Context. If the context is cancelled +// while the underlying reader is blocked, Read returns immediately. +// +// This is useful for reading from a pipe. Closing a pipe file descriptor does +// not unblock pending Reads on that file descriptor. All copies of the pipe's +// other file descriptor (the write end) must be closed in all processes that +// inherit it. This is difficult to do correctly in the situation we care about +// (process group termination). +type contextReader struct { + ctx context.Context + r io.Reader +} + +func (cr *contextReader) Read(b []byte) (n int, err error) { + if err := cr.ctx.Err(); err != nil { + return 0, err + } + done := make(chan struct{}) + + // This goroutine may stay blocked after Read returns because the underlying + // read is blocked. go func() { - if err := wc.enc.Encode(c); err != nil { - errC <- err - return - } - errC <- wc.dec.Decode(resp) + n, err = cr.r.Read(b) + close(done) }() select { - case <-ctx.Done(): - return ctx.Err() - case err := <-errC: - return err + case <-cr.ctx.Done(): + return 0, cr.ctx.Err() + case <-done: + return n, err } } -- GitLab From 574ec1c6457c7779cd20db873fef2e2ed7e31ff1 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 22 Jun 2021 13:44:18 -0700 Subject: [PATCH 0341/2500] [dev.typeparams] cmd/compile: desugar ORECOVER into ORECOVERFP Currently ORECOVER is a single operation that both (1) calculates the (logical) caller frame pointer and (2) calls runtime.gorecover. This is normally fine, but it's inconvenient for regabi, which wants to wrap "defer recover()" into "defer func() { recover() }" and needs (1) and (2) to happen at different times. The current solution is to apply walkRecover early to split it into the two steps, but calling it during order is a minor layering violation. It works well today because the order and walk phases are closely related anyway and walkRecover is relatively simple, but it won't work for go/defer wrapping earlier into the frontend. This CL adds a new, lower-level ORECOVERFP primitive, which represents just part (2); and OGETCALLER{PC,SP} primitives, which provide a way to compute (1) in the frontend too. OGETCALLERPC isn't needed/used today, but it seems worth including for completeness. Maybe it will be useful at some point for intrinsifying runtime.getcaller{pc,sp}, like we already do for runtime.getg. Change-Id: Iaa8ae51e09306c45c147b6759a5b7c24dcc317ca Reviewed-on: https://go-review.googlesource.com/c/go/+/330192 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Matthew Dempsky Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/escape/call.go | 3 ++ src/cmd/compile/internal/escape/desugar.go | 37 +++++++++++++++++++ src/cmd/compile/internal/escape/expr.go | 7 +--- src/cmd/compile/internal/ir/expr.go | 8 +++- src/cmd/compile/internal/ssagen/ssa.go | 8 ++++ src/cmd/compile/internal/typecheck/func.go | 15 ++++++++ .../compile/internal/typecheck/typecheck.go | 12 ++++++ src/cmd/compile/internal/walk/builtin.go | 13 ++----- src/cmd/compile/internal/walk/expr.go | 6 +-- src/cmd/compile/internal/walk/order.go | 13 ++----- src/cmd/compile/internal/walk/stmt.go | 2 +- src/cmd/compile/internal/walk/walk.go | 2 +- 12 files changed, 94 insertions(+), 32 deletions(-) create mode 100644 src/cmd/compile/internal/escape/desugar.go diff --git a/src/cmd/compile/internal/escape/call.go b/src/cmd/compile/internal/escape/call.go index 8511259d47..1f2d59af35 100644 --- a/src/cmd/compile/internal/escape/call.go +++ b/src/cmd/compile/internal/escape/call.go @@ -123,11 +123,14 @@ func (e *escape) callCommon(ks []hole, call ir.Node, where *ir.GoDeferStmt) { call := call.(*ir.BinaryExpr) argument(e.discardHole(), &call.X) argument(e.discardHole(), &call.Y) + case ir.ODELETE, ir.OPRINT, ir.OPRINTN, ir.ORECOVER: call := call.(*ir.CallExpr) + fixRecoverCall(call) for i := range call.Args { argument(e.discardHole(), &call.Args[i]) } + case ir.OLEN, ir.OCAP, ir.OREAL, ir.OIMAG, ir.OCLOSE: call := call.(*ir.UnaryExpr) argument(e.discardHole(), &call.X) diff --git a/src/cmd/compile/internal/escape/desugar.go b/src/cmd/compile/internal/escape/desugar.go new file mode 100644 index 0000000000..8b3cc25cf9 --- /dev/null +++ b/src/cmd/compile/internal/escape/desugar.go @@ -0,0 +1,37 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package escape + +import ( + "cmd/compile/internal/base" + "cmd/compile/internal/ir" + "cmd/compile/internal/typecheck" + "cmd/compile/internal/types" +) + +// TODO(mdempsky): Desugaring doesn't belong during escape analysis, +// but for now it's the most convenient place for some rewrites. + +// fixRecoverCall rewrites an ORECOVER call into ORECOVERFP, +// adding an explicit frame pointer argument. +// If call is not an ORECOVER call, it's left unmodified. +func fixRecoverCall(call *ir.CallExpr) { + if call.Op() != ir.ORECOVER { + return + } + + pos := call.Pos() + + // FP is equal to caller's SP plus FixedFrameSize(). + var fp ir.Node = ir.NewCallExpr(pos, ir.OGETCALLERSP, nil, nil) + if off := base.Ctxt.FixedFrameSize(); off != 0 { + fp = ir.NewBinaryExpr(fp.Pos(), ir.OADD, fp, ir.NewInt(off)) + } + // TODO(mdempsky): Replace *int32 with unsafe.Pointer, without upsetting checkptr. + fp = ir.NewConvExpr(pos, ir.OCONVNOP, types.NewPtr(types.Types[types.TINT32]), fp) + + call.SetOp(ir.ORECOVERFP) + call.Args = []ir.Node{typecheck.Expr(fp)} +} diff --git a/src/cmd/compile/internal/escape/expr.go b/src/cmd/compile/internal/escape/expr.go index cb95221dd5..c10e866990 100644 --- a/src/cmd/compile/internal/escape/expr.go +++ b/src/cmd/compile/internal/escape/expr.go @@ -43,7 +43,7 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) { default: base.Fatalf("unexpected expr: %s %v", n.Op().String(), n) - case ir.OLITERAL, ir.ONIL, ir.OGETG, ir.OTYPE, ir.OMETHEXPR, ir.OLINKSYMOFFSET: + case ir.OLITERAL, ir.ONIL, ir.OGETG, ir.OGETCALLERPC, ir.OGETCALLERSP, ir.OTYPE, ir.OMETHEXPR, ir.OLINKSYMOFFSET: // nop case ir.ONAME: @@ -138,7 +138,7 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) { n := n.(*ir.UnaryExpr) e.discard(n.X) - case ir.OCALLMETH, ir.OCALLFUNC, ir.OCALLINTER, ir.OLEN, ir.OCAP, ir.OCOMPLEX, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.OCOPY, ir.OUNSAFEADD, ir.OUNSAFESLICE: + case ir.OCALLMETH, ir.OCALLFUNC, ir.OCALLINTER, ir.OLEN, ir.OCAP, ir.OCOMPLEX, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.OCOPY, ir.ORECOVER, ir.OUNSAFEADD, ir.OUNSAFESLICE: e.call([]hole{k}, n) case ir.ONEW: @@ -158,9 +158,6 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) { e.spill(k, n) e.discard(n.Len) - case ir.ORECOVER: - // nop - case ir.OCALLPART: // Flow the receiver argument to both the closure and // to the receiver parameter. diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index b46fd905fe..4659b99fbf 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -180,8 +180,12 @@ func (n *CallExpr) SetOp(op Op) { switch op { default: panic(n.no("SetOp " + op.String())) - case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH, - OAPPEND, ODELETE, OGETG, OMAKE, OPRINT, OPRINTN, ORECOVER: + case OAPPEND, + OCALL, OCALLFUNC, OCALLINTER, OCALLMETH, + ODELETE, + OGETG, OGETCALLERPC, OGETCALLERSP, + OMAKE, OPRINT, OPRINTN, + ORECOVER, ORECOVERFP: n.op = op } } diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 659ba02b5b..93847a39a3 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -3135,6 +3135,14 @@ func (s *state) expr(n ir.Node) *ssa.Value { n := n.(*ir.CallExpr) return s.newValue1(ssa.OpGetG, n.Type(), s.mem()) + case ir.OGETCALLERPC: + n := n.(*ir.CallExpr) + return s.newValue0(ssa.OpGetCallerPC, n.Type()) + + case ir.OGETCALLERSP: + n := n.(*ir.CallExpr) + return s.newValue0(ssa.OpGetCallerSP, n.Type()) + case ir.OAPPEND: return s.append(n.(*ir.CallExpr), false) diff --git a/src/cmd/compile/internal/typecheck/func.go b/src/cmd/compile/internal/typecheck/func.go index bd21977f26..031279f42c 100644 --- a/src/cmd/compile/internal/typecheck/func.go +++ b/src/cmd/compile/internal/typecheck/func.go @@ -967,6 +967,21 @@ func tcRecover(n *ir.CallExpr) ir.Node { return n } +// tcRecoverFP typechecks an ORECOVERFP node. +func tcRecoverFP(n *ir.CallExpr) ir.Node { + if len(n.Args) != 1 { + base.FatalfAt(n.Pos(), "wrong number of arguments: %v", n) + } + + n.Args[0] = Expr(n.Args[0]) + if !n.Args[0].Type().IsPtrShaped() { + base.FatalfAt(n.Pos(), "%L is not pointer shaped", n.Args[0]) + } + + n.SetType(types.Types[types.TINTER]) + return n +} + // tcUnsafeAdd typechecks an OUNSAFEADD node. func tcUnsafeAdd(n *ir.BinaryExpr) *ir.BinaryExpr { if !types.AllowsGoVersion(curpkg(), 1, 17) { diff --git a/src/cmd/compile/internal/typecheck/typecheck.go b/src/cmd/compile/internal/typecheck/typecheck.go index 0367f7b034..f7de43c79f 100644 --- a/src/cmd/compile/internal/typecheck/typecheck.go +++ b/src/cmd/compile/internal/typecheck/typecheck.go @@ -776,6 +776,10 @@ func typecheck1(n ir.Node, top int) ir.Node { n := n.(*ir.CallExpr) return tcRecover(n) + case ir.ORECOVERFP: + n := n.(*ir.CallExpr) + return tcRecoverFP(n) + case ir.OUNSAFEADD: n := n.(*ir.BinaryExpr) return tcUnsafeAdd(n) @@ -809,6 +813,14 @@ func typecheck1(n ir.Node, top int) ir.Node { n.SetType(types.Types[types.TUINTPTR]) return n + case ir.OGETCALLERPC, ir.OGETCALLERSP: + n := n.(*ir.CallExpr) + if len(n.Args) != 0 { + base.FatalfAt(n.Pos(), "unexpected arguments: %v", n) + } + n.SetType(types.Types[types.TUINTPTR]) + return n + case ir.OCONVNOP: n := n.(*ir.ConvExpr) n.X = Expr(n.X) diff --git a/src/cmd/compile/internal/walk/builtin.go b/src/cmd/compile/internal/walk/builtin.go index be0f4c5208..135eaee6bc 100644 --- a/src/cmd/compile/internal/walk/builtin.go +++ b/src/cmd/compile/internal/walk/builtin.go @@ -641,16 +641,9 @@ func walkPrint(nn *ir.CallExpr, init *ir.Nodes) ir.Node { return walkStmt(typecheck.Stmt(r)) } -// walkRecover walks an ORECOVER node. -func walkRecover(nn *ir.CallExpr, init *ir.Nodes) ir.Node { - // Call gorecover with the FP of this frame. - // FP is equal to caller's SP plus FixedFrameSize(). - var fp ir.Node = mkcall("getcallersp", types.Types[types.TUINTPTR], init) - if off := base.Ctxt.FixedFrameSize(); off != 0 { - fp = ir.NewBinaryExpr(fp.Pos(), ir.OADD, fp, ir.NewInt(off)) - } - fp = ir.NewConvExpr(fp.Pos(), ir.OCONVNOP, types.NewPtr(types.Types[types.TINT32]), fp) - return mkcall("gorecover", nn.Type(), init, fp) +// walkRecover walks an ORECOVERFP node. +func walkRecoverFP(nn *ir.CallExpr, init *ir.Nodes) ir.Node { + return mkcall("gorecover", nn.Type(), init, walkExpr(nn.Args[0], init)) } func walkUnsafeSlice(n *ir.BinaryExpr, init *ir.Nodes) ir.Node { diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go index 2fb907710b..070954be27 100644 --- a/src/cmd/compile/internal/walk/expr.go +++ b/src/cmd/compile/internal/walk/expr.go @@ -82,7 +82,7 @@ func walkExpr1(n ir.Node, init *ir.Nodes) ir.Node { base.Fatalf("walkExpr: switch 1 unknown op %+v", n.Op()) panic("unreachable") - case ir.ONONAME, ir.OGETG: + case ir.OGETG, ir.OGETCALLERPC, ir.OGETCALLERSP: return n case ir.OTYPE, ir.ONAME, ir.OLITERAL, ir.ONIL, ir.OLINKSYMOFFSET: @@ -161,8 +161,8 @@ func walkExpr1(n ir.Node, init *ir.Nodes) ir.Node { n := n.(*ir.UnaryExpr) return mkcall("gopanic", nil, init, n.X) - case ir.ORECOVER: - return walkRecover(n.(*ir.CallExpr), init) + case ir.ORECOVERFP: + return walkRecoverFP(n.(*ir.CallExpr), init) case ir.OCFUNC: return n diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go index 75657cd3e4..ff8e95b330 100644 --- a/src/cmd/compile/internal/walk/order.go +++ b/src/cmd/compile/internal/walk/order.go @@ -777,10 +777,10 @@ func (o *orderState) stmt(n ir.Node) { o.out = append(o.out, n) o.cleanTemp(t) - case ir.OPRINT, ir.OPRINTN, ir.ORECOVER: + case ir.OPRINT, ir.OPRINTN, ir.ORECOVERFP: n := n.(*ir.CallExpr) t := o.markTemp() - o.exprList(n.Args) + o.call(n) o.out = append(o.out, n) o.cleanTemp(t) @@ -790,13 +790,6 @@ func (o *orderState) stmt(n ir.Node) { t := o.markTemp() o.init(n.Call) o.call(n.Call) - if n.Call.Op() == ir.ORECOVER { - // Special handling of "defer recover()". We need to evaluate the FP - // argument before wrapping. - var init ir.Nodes - n.Call = walkRecover(n.Call.(*ir.CallExpr), &init) - o.stmtList(init) - } o.wrapGoDefer(n) o.out = append(o.out, n) o.cleanTemp(t) @@ -1270,7 +1263,7 @@ func (o *orderState) expr1(n, lhs ir.Node) ir.Node { ir.OMAKESLICECOPY, ir.ONEW, ir.OREAL, - ir.ORECOVER, + ir.ORECOVERFP, ir.OSTR2BYTES, ir.OSTR2BYTESTMP, ir.OSTR2RUNES: diff --git a/src/cmd/compile/internal/walk/stmt.go b/src/cmd/compile/internal/walk/stmt.go index 2352719da3..bcc0a3e517 100644 --- a/src/cmd/compile/internal/walk/stmt.go +++ b/src/cmd/compile/internal/walk/stmt.go @@ -49,7 +49,7 @@ func walkStmt(n ir.Node) ir.Node { ir.OPRINT, ir.OPRINTN, ir.OPANIC, - ir.ORECOVER, + ir.ORECOVERFP, ir.OGETG: if n.Typecheck() == 0 { base.Fatalf("missing typecheck: %+v", n) diff --git a/src/cmd/compile/internal/walk/walk.go b/src/cmd/compile/internal/walk/walk.go index 26da6e3145..6e992a91b8 100644 --- a/src/cmd/compile/internal/walk/walk.go +++ b/src/cmd/compile/internal/walk/walk.go @@ -343,7 +343,7 @@ func mayCall(n ir.Node) bool { ir.OCAP, ir.OIMAG, ir.OLEN, ir.OREAL, ir.OCONVNOP, ir.ODOT, ir.OCFUNC, ir.OIDATA, ir.OITAB, ir.OSPTR, - ir.OBYTES2STRTMP, ir.OGETG, ir.OSLICEHEADER: + ir.OBYTES2STRTMP, ir.OGETG, ir.OGETCALLERPC, ir.OGETCALLERSP, ir.OSLICEHEADER: // ok: operations that don't require function calls. // Expand as needed. } -- GitLab From 0a0e3a3dea72d8d64d4250c9f7649da3b942eae5 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 21 Jun 2021 22:35:01 -0700 Subject: [PATCH 0342/2500] [dev.typeparams] cmd/compile: move call logic from order.go to escape This CL moves two bits of related code from order.go to escape analysis: 1. The recognition of "unsafe uintptr" arguments passed to syscall-like functions. 2. The wrapping of go/defer function calls in parameter-free function literals. As with previous CLs, it would be nice to push this logic even further forward, but for now escape analysis seems most pragmatic. A couple side benefits: 1. It allows getting rid of the uintptrEscapesHack kludge. 2. When inserting wrappers, we can move some expressions into the wrapper and escape analyze them better. For example, the test expectation changes are all due to slice literals in go/defer calls where the slice is now constructed at the call site, and can now be stack allocated. Change-Id: I73679bcad7fa8d61d2fc52d4cea0dc5ff0de8c0c Reviewed-on: https://go-review.googlesource.com/c/go/+/330330 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Matthew Dempsky Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/escape/call.go | 237 ++++++++++++++-- src/cmd/compile/internal/escape/escape.go | 9 +- src/cmd/compile/internal/escape/expr.go | 8 +- src/cmd/compile/internal/escape/graph.go | 4 - src/cmd/compile/internal/ir/func.go | 11 + src/cmd/compile/internal/walk/order.go | 317 ---------------------- src/cmd/compile/internal/walk/stmt.go | 19 -- test/escape2.go | 12 +- test/escape2n.go | 12 +- test/fixedbugs/issue31573.go | 30 +- 10 files changed, 259 insertions(+), 400 deletions(-) diff --git a/src/cmd/compile/internal/escape/call.go b/src/cmd/compile/internal/escape/call.go index 1f2d59af35..7b9dbe0dbc 100644 --- a/src/cmd/compile/internal/escape/call.go +++ b/src/cmd/compile/internal/escape/call.go @@ -9,30 +9,35 @@ import ( "cmd/compile/internal/ir" "cmd/compile/internal/typecheck" "cmd/compile/internal/types" + "cmd/internal/src" ) // call evaluates a call expressions, including builtin calls. ks // should contain the holes representing where the function callee's // results flows. func (e *escape) call(ks []hole, call ir.Node) { - e.callCommon(ks, call, nil) + var init ir.Nodes + e.callCommon(ks, call, &init, nil) + if len(init) != 0 { + call.(*ir.CallExpr).PtrInit().Append(init...) + } } -func (e *escape) callCommon(ks []hole, call ir.Node, where *ir.GoDeferStmt) { - argument := func(k hole, argp *ir.Node) { - if where != nil { - if where.Esc() == ir.EscNever { - // Top-level defers arguments don't escape to heap, - // but they do need to last until end of function. - k = e.later(k) - } else { - k = e.heapHole() - } - } +func (e *escape) callCommon(ks []hole, call ir.Node, init *ir.Nodes, wrapper *ir.Func) { + + // argumentPragma handles escape analysis of argument *argp to the + // given hole. If the function callee is known, pragma is the + // function's pragma flags; otherwise 0. + argumentFunc := func(fn *ir.Name, k hole, argp *ir.Node) { + e.rewriteArgument(argp, init, call, fn, wrapper) e.expr(k.note(call, "call parameter"), *argp) } + argument := func(k hole, argp *ir.Node) { + argumentFunc(nil, k, argp) + } + switch call.Op() { default: ir.Dump("esc", call) @@ -43,6 +48,11 @@ func (e *escape) callCommon(ks []hole, call ir.Node, where *ir.GoDeferStmt) { typecheck.FixVariadicCall(call) // Pick out the function callee, if statically known. + // + // TODO(mdempsky): Change fn from *ir.Name to *ir.Func, but some + // functions (e.g., runtime builtins, method wrappers, generated + // eq/hash functions) don't have it set. Investigate whether + // that's a concern. var fn *ir.Name switch call.Op() { case ir.OCALLFUNC: @@ -68,15 +78,20 @@ func (e *escape) callCommon(ks []hole, call ir.Node, where *ir.GoDeferStmt) { } if r := fntype.Recv(); r != nil { - argument(e.tagHole(ks, fn, r), &call.X.(*ir.SelectorExpr).X) + dot := call.X.(*ir.SelectorExpr) + argumentFunc(fn, e.tagHole(ks, fn, r), &dot.X) } else { // Evaluate callee function expression. + // + // Note: We use argument and not argumentFunc, because call.X + // here may be an argument to runtime.{new,defer}proc, but it's + // not an argument to fn itself. argument(e.discardHole(), &call.X) } args := call.Args for i, param := range fntype.Params().FieldSlice() { - argument(e.tagHole(ks, fn, param), &args[i]) + argumentFunc(fn, e.tagHole(ks, fn, param), &args[i]) } case ir.OAPPEND: @@ -142,16 +157,196 @@ func (e *escape) callCommon(ks []hole, call ir.Node, where *ir.GoDeferStmt) { } } +// goDeferStmt analyzes a "go" or "defer" statement. +// +// In the process, it also normalizes the statement to always use a +// simple function call with no arguments and no results. For example, +// it rewrites: +// +// defer f(x, y) +// +// into: +// +// x1, y1 := x, y +// defer func() { f(x1, y1) }() func (e *escape) goDeferStmt(n *ir.GoDeferStmt) { - topLevelDefer := n.Op() == ir.ODEFER && e.loopDepth == 1 - if topLevelDefer { + k := e.heapHole() + if n.Op() == ir.ODEFER && e.loopDepth == 1 { + // Top-level defer arguments don't escape to the heap, + // but they do need to last until they're invoked. + k = e.later(e.discardHole()) + // force stack allocation of defer record, unless // open-coded defers are used (see ssa.go) n.SetEsc(ir.EscNever) } - e.stmts(n.Call.Init()) - e.callCommon(nil, n.Call, n) + call := n.Call + + init := n.PtrInit() + init.Append(ir.TakeInit(call)...) + e.stmts(*init) + + // If the function is already a zero argument/result function call, + // just escape analyze it normally. + if call, ok := call.(*ir.CallExpr); ok && call.Op() == ir.OCALLFUNC { + if sig := call.X.Type(); sig.NumParams()+sig.NumResults() == 0 { + if clo, ok := call.X.(*ir.ClosureExpr); ok && n.Op() == ir.OGO { + clo.IsGoWrap = true + } + e.expr(k, call.X) + return + } + } + + // Create a new no-argument function that we'll hand off to defer. + fn := ir.NewClosureFunc(n.Pos(), true) + fn.SetWrapper(true) + fn.Nname.SetType(types.NewSignature(types.LocalPkg, nil, nil, nil, nil)) + fn.Body = []ir.Node{call} + + clo := fn.OClosure + if n.Op() == ir.OGO { + clo.IsGoWrap = true + } + + e.callCommon(nil, call, init, fn) + e.closures = append(e.closures, closure{e.spill(k, clo), clo}) + + // Create new top level call to closure. + n.Call = ir.NewCallExpr(call.Pos(), ir.OCALL, clo, nil) + ir.WithFunc(e.curfn, func() { + typecheck.Stmt(n.Call) + }) +} + +// rewriteArgument rewrites the argument *argp of the given call expression. +// fn is the static callee function, if known. +// wrapper is the go/defer wrapper function for call, if any. +func (e *escape) rewriteArgument(argp *ir.Node, init *ir.Nodes, call ir.Node, fn *ir.Name, wrapper *ir.Func) { + var pragma ir.PragmaFlag + if fn != nil && fn.Func != nil { + pragma = fn.Func.Pragma + } + + // unsafeUintptr rewrites "uintptr(ptr)" arguments to syscall-like + // functions, so that ptr is kept alive and/or escaped as + // appropriate. unsafeUintptr also reports whether it modified arg0. + unsafeUintptr := func(arg0 ir.Node) bool { + if pragma&(ir.UintptrKeepAlive|ir.UintptrEscapes) == 0 { + return false + } + + // If the argument is really a pointer being converted to uintptr, + // arrange for the pointer to be kept alive until the call returns, + // by copying it into a temp and marking that temp + // still alive when we pop the temp stack. + if arg0.Op() != ir.OCONVNOP || !arg0.Type().IsUintptr() { + return false + } + arg := arg0.(*ir.ConvExpr) + + if !arg.X.Type().IsUnsafePtr() { + return false + } + + // Create and declare a new pointer-typed temp variable. + tmp := e.wrapExpr(arg.Pos(), &arg.X, init, call, wrapper) + + if pragma&ir.UintptrEscapes != 0 { + e.flow(e.heapHole().note(arg, "//go:uintptrescapes"), e.oldLoc(tmp)) + } + + if pragma&ir.UintptrKeepAlive != 0 { + call := call.(*ir.CallExpr) + + // SSA implements CallExpr.KeepAlive using OpVarLive, which + // doesn't support PAUTOHEAP variables. I tried changing it to + // use OpKeepAlive, but that ran into issues of its own. + // For now, the easy solution is to explicitly copy to (yet + // another) new temporary variable. + keep := tmp + if keep.Class == ir.PAUTOHEAP { + keep = e.copyExpr(arg.Pos(), tmp, call.PtrInit(), wrapper, false) + } + + keep.SetAddrtaken(true) // ensure SSA keeps the tmp variable + call.KeepAlive = append(call.KeepAlive, keep) + } + + return true + } + + visit := func(pos src.XPos, argp *ir.Node) { + if unsafeUintptr(*argp) { + return + } + + if wrapper != nil { + e.wrapExpr(pos, argp, init, call, wrapper) + } + } + + // Peel away any slice lits. + if arg := *argp; arg.Op() == ir.OSLICELIT { + list := arg.(*ir.CompLitExpr).List + for i := range list { + visit(arg.Pos(), &list[i]) + } + } else { + visit(call.Pos(), argp) + } +} + +// wrapExpr replaces *exprp with a temporary variable copy. If wrapper +// is non-nil, the variable will be captured for use within that +// function. +func (e *escape) wrapExpr(pos src.XPos, exprp *ir.Node, init *ir.Nodes, call ir.Node, wrapper *ir.Func) *ir.Name { + tmp := e.copyExpr(pos, *exprp, init, e.curfn, true) + + if wrapper != nil { + // Currently for "defer i.M()" if i is nil it panics at the point + // of defer statement, not when deferred function is called. We + // need to do the nil check outside of the wrapper. + if call.Op() == ir.OCALLINTER && exprp == &call.(*ir.CallExpr).X.(*ir.SelectorExpr).X { + check := ir.NewUnaryExpr(pos, ir.OCHECKNIL, ir.NewUnaryExpr(pos, ir.OITAB, tmp)) + init.Append(typecheck.Stmt(check)) + } + + e.oldLoc(tmp).captured = true + + cv := ir.NewClosureVar(pos, wrapper, tmp) + cv.SetType(tmp.Type()) + tmp = typecheck.Expr(cv).(*ir.Name) + } + + *exprp = tmp + return tmp +} + +// copyExpr creates and returns a new temporary variable within fn; +// appends statements to init to declare and initialize it to expr; +// and escape analyzes the data flow if analyze is true. +func (e *escape) copyExpr(pos src.XPos, expr ir.Node, init *ir.Nodes, fn *ir.Func, analyze bool) *ir.Name { + if ir.HasUniquePos(expr) { + pos = expr.Pos() + } + + tmp := typecheck.TempAt(pos, fn, expr.Type()) + + stmts := []ir.Node{ + ir.NewDecl(pos, ir.ODCL, tmp), + ir.NewAssignStmt(pos, tmp, expr), + } + typecheck.Stmts(stmts) + init.Append(stmts...) + + if analyze { + e.newLoc(tmp, false) + e.stmts(stmts) + } + + return tmp } // tagHole returns a hole for evaluating an argument passed to param. @@ -170,12 +365,6 @@ func (e *escape) tagHole(ks []hole, fn *ir.Name, param *types.Field) hole { // Call to previously tagged function. - if fn.Func != nil && fn.Func.Pragma&ir.UintptrEscapes != 0 && (param.Type.IsUintptr() || param.IsDDD() && param.Type.Elem().IsUintptr()) { - k := e.heapHole() - k.uintptrEscapesHack = true - return k - } - var tagKs []hole esc := parseLeaks(param.Note) diff --git a/src/cmd/compile/internal/escape/escape.go b/src/cmd/compile/internal/escape/escape.go index 8f75ae8b42..324d0da3fe 100644 --- a/src/cmd/compile/internal/escape/escape.go +++ b/src/cmd/compile/internal/escape/escape.go @@ -282,6 +282,11 @@ func (b *batch) finish(fns []*ir.Func) { // Update n.Esc based on escape analysis results. + // Omit escape diagnostics for go/defer wrappers, at least for now. + // Historically, we haven't printed them, and test cases don't expect them. + // TODO(mdempsky): Update tests to expect this. + goDeferWrapper := n.Op() == ir.OCLOSURE && n.(*ir.ClosureExpr).Func.Wrapper() + if loc.escapes { if n.Op() == ir.ONAME { if base.Flag.CompilingRuntime { @@ -291,7 +296,7 @@ func (b *batch) finish(fns []*ir.Func) { base.WarnfAt(n.Pos(), "moved to heap: %v", n) } } else { - if base.Flag.LowerM != 0 { + if base.Flag.LowerM != 0 && !goDeferWrapper { base.WarnfAt(n.Pos(), "%v escapes to heap", n) } if logopt.Enabled() { @@ -301,7 +306,7 @@ func (b *batch) finish(fns []*ir.Func) { } n.SetEsc(ir.EscHeap) } else { - if base.Flag.LowerM != 0 && n.Op() != ir.ONAME { + if base.Flag.LowerM != 0 && n.Op() != ir.ONAME && !goDeferWrapper { base.WarnfAt(n.Pos(), "%v does not escape", n) } n.SetEsc(ir.EscNone) diff --git a/src/cmd/compile/internal/escape/expr.go b/src/cmd/compile/internal/escape/expr.go index c10e866990..71c8eec6ef 100644 --- a/src/cmd/compile/internal/escape/expr.go +++ b/src/cmd/compile/internal/escape/expr.go @@ -30,12 +30,7 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) { base.Pos = lno }() - uintptrEscapesHack := k.uintptrEscapesHack - k.uintptrEscapesHack = false - - if uintptrEscapesHack && n.Op() == ir.OCONVNOP && n.(*ir.ConvExpr).X.Type().IsUnsafePtr() { - // nop - } else if k.derefs >= 0 && !n.Type().HasPointers() { + if k.derefs >= 0 && !n.Type().HasPointers() { k.dst = &e.blankLoc } @@ -198,7 +193,6 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) { case ir.OSLICELIT: n := n.(*ir.CompLitExpr) k = e.spill(k, n) - k.uintptrEscapesHack = uintptrEscapesHack // for ...uintptr parameters for _, elt := range n.List { if elt.Op() == ir.OKEY { diff --git a/src/cmd/compile/internal/escape/graph.go b/src/cmd/compile/internal/escape/graph.go index 3581fce30d..6316435dfe 100644 --- a/src/cmd/compile/internal/escape/graph.go +++ b/src/cmd/compile/internal/escape/graph.go @@ -129,10 +129,6 @@ type hole struct { // the expression, independent of whether the address will actually // be stored into a variable. addrtaken bool - - // uintptrEscapesHack indicates this context is evaluating an - // argument for a //go:uintptrescapes function. - uintptrEscapesHack bool } type note struct { diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go index 6480becc93..3501f83ab1 100644 --- a/src/cmd/compile/internal/ir/func.go +++ b/src/cmd/compile/internal/ir/func.go @@ -278,6 +278,17 @@ func PkgFuncName(f *Func) string { var CurFunc *Func +// WithFunc invokes do with CurFunc and base.Pos set to curfn and +// curfn.Pos(), respectively, and then restores their previous values +// before returning. +func WithFunc(curfn *Func, do func()) { + oldfn, oldpos := CurFunc, base.Pos + defer func() { CurFunc, base.Pos = oldfn, oldpos }() + + CurFunc, base.Pos = curfn, curfn.Pos() + do() +} + func FuncSymName(s *types.Sym) string { return s.Name + "·f" } diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go index ff8e95b330..62d9b95be9 100644 --- a/src/cmd/compile/internal/walk/order.go +++ b/src/cmd/compile/internal/walk/order.go @@ -552,48 +552,6 @@ func (o *orderState) call(nn ir.Node) { n.X = o.expr(n.X, nil) o.exprList(n.Args) - - // Pick out the function callee, if statically known. - // TODO(mdempsky): De-duplicate with similar code in escape analysis. - var callee *ir.Func - switch n.Op() { - case ir.OCALLFUNC: - if fn, ok := n.X.(*ir.Name); ok && fn.Op() == ir.ONAME && fn.Class == ir.PFUNC { - callee = fn.Func - } - case ir.OCALLMETH: - callee = ir.MethodExprName(n.X).Func - } - - if callee == nil || callee.Pragma&ir.UintptrKeepAlive == 0 { - return - } - - keepAlive := func(args []ir.Node) { - // If the argument is really a pointer being converted to uintptr, - // arrange for the pointer to be kept alive until the call returns, - // by copying it into a temp and marking that temp - // still alive when we pop the temp stack. - for _, arg := range args { - if arg.Op() == ir.OCONVNOP && arg.Type().IsUintptr() { - arg := arg.(*ir.ConvExpr) - if arg.X.Type().IsUnsafePtr() { - x := o.copyExpr(arg.X) - arg.X = x - x.SetAddrtaken(true) // ensure SSA keeps the x variable - n.KeepAlive = append(n.KeepAlive, x) - } - } - } - } - - last := len(n.Args) - 1 - if n.IsDDD && n.Args[last].Op() == ir.OSLICELIT { - keepAlive(n.Args[:last]) - keepAlive(n.Args[last].(*ir.CompLitExpr).List) - } else { - keepAlive(n.Args) - } } // mapAssign appends n to o.out. @@ -790,7 +748,6 @@ func (o *orderState) stmt(n ir.Node) { t := o.markTemp() o.init(n.Call) o.call(n.Call) - o.wrapGoDefer(n) o.out = append(o.out, n) o.cleanTemp(t) @@ -1486,280 +1443,6 @@ func (o *orderState) as2ok(n *ir.AssignListStmt) { o.stmt(typecheck.Stmt(as)) } -var wrapGoDefer_prgen int - -// wrapGoDefer wraps the target of a "go" or "defer" statement with a -// new "function with no arguments" closure. Specifically, it converts -// -// defer f(x, y) -// -// to -// -// x1, y1 := x, y -// defer func() { f(x1, y1) }() -// -// This is primarily to enable a quicker bringup of defers under the -// new register ABI; by doing this conversion, we can simplify the -// code in the runtime that invokes defers on the panic path. -func (o *orderState) wrapGoDefer(n *ir.GoDeferStmt) { - call := n.Call - - var callX ir.Node // thing being called - var callArgs []ir.Node // call arguments - var keepAlive []*ir.Name // KeepAlive list from call, if present - - // A helper to recreate the call within the closure. - var mkNewCall func(pos src.XPos, op ir.Op, fun ir.Node, args []ir.Node) ir.Node - - // Defer calls come in many shapes and sizes; not all of them - // are ir.CallExpr's. Examine the type to see what we're dealing with. - switch x := call.(type) { - case *ir.CallExpr: - callX = x.X - callArgs = x.Args - keepAlive = x.KeepAlive - mkNewCall = func(pos src.XPos, op ir.Op, fun ir.Node, args []ir.Node) ir.Node { - newcall := ir.NewCallExpr(pos, op, fun, args) - newcall.IsDDD = x.IsDDD - return ir.Node(newcall) - } - case *ir.UnaryExpr: // ex: OCLOSE - callArgs = []ir.Node{x.X} - mkNewCall = func(pos src.XPos, op ir.Op, fun ir.Node, args []ir.Node) ir.Node { - if len(args) != 1 { - panic("internal error, expecting single arg") - } - return ir.Node(ir.NewUnaryExpr(pos, op, args[0])) - } - case *ir.BinaryExpr: // ex: OCOPY - callArgs = []ir.Node{x.X, x.Y} - mkNewCall = func(pos src.XPos, op ir.Op, fun ir.Node, args []ir.Node) ir.Node { - if len(args) != 2 { - panic("internal error, expecting two args") - } - return ir.Node(ir.NewBinaryExpr(pos, op, args[0], args[1])) - } - default: - panic("unhandled op") - } - - // No need to wrap if called func has no args, no receiver, and no results. - // However in the case of "defer func() { ... }()" we need to - // protect against the possibility of directClosureCall rewriting - // things so that the call does have arguments. - // - // Do wrap method calls (OCALLMETH, OCALLINTER), because it has - // a receiver. - // - // Also do wrap builtin functions, because they may be expanded to - // calls with arguments (e.g. ORECOVER). - // - // TODO: maybe not wrap if the called function has no arguments and - // only in-register results? - if len(callArgs) == 0 && call.Op() == ir.OCALLFUNC && callX.Type().NumResults() == 0 { - if callX.Op() == ir.OCLOSURE { - clo := callX.(*ir.ClosureExpr) - clo.IsGoWrap = true - } - return - } - - if c, ok := call.(*ir.CallExpr); ok { - // To simplify things, turn f(a, b, []T{c, d, e}...) back - // into f(a, b, c, d, e) -- when the final call is run through the - // type checker below, it will rebuild the proper slice literal. - undoVariadic(c) - callX = c.X - callArgs = c.Args - } - - // This is set to true if the closure we're generating escapes - // (needs heap allocation). - cloEscapes := func() bool { - if n.Op() == ir.OGO { - // For "go", assume that all closures escape. - return true - } - // For defer, just use whatever result escape analysis - // has determined for the defer. - return n.Esc() != ir.EscNever - }() - - // A helper for making a copy of an argument. Note that it is - // not safe to use o.copyExpr(arg) if we're putting a - // reference to the temp into the closure (as opposed to - // copying it in by value), since in the by-reference case we - // need a temporary whose lifetime extends to the end of the - // function (as opposed to being local to the current block or - // statement being ordered). - mkArgCopy := func(arg ir.Node) *ir.Name { - t := arg.Type() - byval := t.Size() <= 128 || cloEscapes - var argCopy *ir.Name - if byval { - argCopy = o.copyExpr(arg) - } else { - argCopy = typecheck.Temp(t) - o.append(ir.NewAssignStmt(base.Pos, argCopy, arg)) - } - // The value of 128 below is meant to be consistent with code - // in escape analysis that picks byval/byaddr based on size. - argCopy.SetByval(byval) - return argCopy - } - - // getUnsafeArg looks for an unsafe.Pointer arg that has been - // previously captured into the call's keepalive list, returning - // the name node for it if found. - getUnsafeArg := func(arg ir.Node) *ir.Name { - // Look for uintptr(unsafe.Pointer(name)) - if arg.Op() != ir.OCONVNOP { - return nil - } - if !arg.Type().IsUintptr() { - return nil - } - if !arg.(*ir.ConvExpr).X.Type().IsUnsafePtr() { - return nil - } - arg = arg.(*ir.ConvExpr).X - argname, ok := arg.(*ir.Name) - if !ok { - return nil - } - for i := range keepAlive { - if argname == keepAlive[i] { - return argname - } - } - return nil - } - - // Copy the arguments to the function into temps. - // - // For calls with uintptr(unsafe.Pointer(...)) args that are being - // kept alive (see code in (*orderState).call that does this), use - // the existing arg copy instead of creating a new copy. - unsafeArgs := make([]*ir.Name, len(callArgs)) - origArgs := callArgs - var newNames []*ir.Name - for i := range callArgs { - arg := callArgs[i] - var argname *ir.Name - unsafeArgName := getUnsafeArg(arg) - if unsafeArgName != nil { - // arg has been copied already, use keepalive copy - argname = unsafeArgName - unsafeArgs[i] = unsafeArgName - } else { - argname = mkArgCopy(arg) - } - newNames = append(newNames, argname) - } - - // Deal with cases where the function expression (what we're - // calling) is not a simple function symbol. - var fnExpr *ir.Name - var methSelectorExpr *ir.SelectorExpr - if callX != nil { - switch { - case callX.Op() == ir.ODOTMETH || callX.Op() == ir.ODOTINTER: - // Handle defer of a method call, e.g. "defer v.MyMethod(x, y)" - n := callX.(*ir.SelectorExpr) - n.X = mkArgCopy(n.X) - methSelectorExpr = n - if callX.Op() == ir.ODOTINTER { - // Currently for "defer i.M()" if i is nil it panics at the - // point of defer statement, not when deferred function is called. - // (I think there is an issue discussing what is the intended - // behavior but I cannot find it.) - // We need to do the nil check outside of the wrapper. - tab := typecheck.Expr(ir.NewUnaryExpr(base.Pos, ir.OITAB, n.X)) - c := ir.NewUnaryExpr(n.Pos(), ir.OCHECKNIL, tab) - c.SetTypecheck(1) - o.append(c) - } - case !(callX.Op() == ir.ONAME && callX.(*ir.Name).Class == ir.PFUNC): - // Deal with "defer returnsafunc()(x, y)" (for - // example) by copying the callee expression. - fnExpr = mkArgCopy(callX) - } - } - - // Create a new no-argument function that we'll hand off to defer. - fn := ir.NewClosureFunc(base.Pos, true) - fn.Nname.SetType(types.NewSignature(types.LocalPkg, nil, nil, nil, nil)) - fn.SetWrapper(true) - - // helper for capturing reference to a var declared in an outer scope. - capName := func(pos src.XPos, fn *ir.Func, n *ir.Name) *ir.Name { - t := n.Type() - cv := ir.CaptureName(pos, fn, n) - cv.SetType(t) - return typecheck.Expr(cv).(*ir.Name) - } - - // Call args (x1, y1) need to be captured as part of the newly - // created closure. - newCallArgs := []ir.Node{} - for i := range newNames { - var arg ir.Node - arg = capName(callArgs[i].Pos(), fn, newNames[i]) - if unsafeArgs[i] != nil { - arg = ir.NewConvExpr(arg.Pos(), origArgs[i].Op(), origArgs[i].Type(), arg) - } - newCallArgs = append(newCallArgs, arg) - } - // Also capture the function or method expression (if needed) into - // the closure. - if fnExpr != nil { - callX = capName(callX.Pos(), fn, fnExpr) - } - if methSelectorExpr != nil { - methSelectorExpr.X = capName(callX.Pos(), fn, methSelectorExpr.X.(*ir.Name)) - } - - // This flags a builtin as opposed to a regular call. - irregular := (call.Op() != ir.OCALLFUNC && - call.Op() != ir.OCALLMETH && - call.Op() != ir.OCALLINTER) - - // Construct new function body: f(x1, y1) - op := ir.OCALL - if irregular { - op = call.Op() - } - newcall := mkNewCall(call.Pos(), op, callX, newCallArgs) - - // Finalize body, register function on the main decls list. - fn.Body = []ir.Node{newcall} - ir.FinishCaptureNames(n.Pos(), ir.CurFunc, fn) - - // Create closure expr - clo := typecheck.Expr(fn.OClosure).(*ir.ClosureExpr) - - // Set escape properties for closure. - if n.Op() == ir.OGO { - // For "go", assume that the closure is going to escape. - clo.SetEsc(ir.EscHeap) - clo.IsGoWrap = true - } else { - // For defer, just use whatever result escape analysis - // has determined for the defer. - if n.Esc() == ir.EscNever { - clo.SetTransient(true) - clo.SetEsc(ir.EscNone) - } - } - - // Create new top level call to closure over argless function. - topcall := ir.NewCallExpr(n.Pos(), ir.OCALL, clo, nil) - typecheck.Call(topcall) - - // Finally, point the defer statement at the newly generated call. - n.Call = topcall -} - // isFuncPCIntrinsic returns whether n is a direct call of internal/abi.FuncPCABIxxx functions. func isFuncPCIntrinsic(n *ir.CallExpr) bool { if n.Op() != ir.OCALLFUNC || n.X.Op() != ir.ONAME { diff --git a/src/cmd/compile/internal/walk/stmt.go b/src/cmd/compile/internal/walk/stmt.go index bcc0a3e517..0c216d2e8a 100644 --- a/src/cmd/compile/internal/walk/stmt.go +++ b/src/cmd/compile/internal/walk/stmt.go @@ -222,22 +222,3 @@ func walkIf(n *ir.IfStmt) ir.Node { walkStmtList(n.Else) return n } - -// undoVariadic turns a call to a variadic function of the form -// -// f(a, b, []T{c, d, e}...) -// -// back into -// -// f(a, b, c, d, e) -// -func undoVariadic(call *ir.CallExpr) { - if call.IsDDD { - last := len(call.Args) - 1 - if va := call.Args[last]; va.Op() == ir.OSLICELIT { - va := va.(*ir.CompLitExpr) - call.Args = append(call.Args[:last], va.List...) - call.IsDDD = false - } - } -} diff --git a/test/escape2.go b/test/escape2.go index 04ab635aa5..e3e5904cde 100644 --- a/test/escape2.go +++ b/test/escape2.go @@ -667,13 +667,13 @@ func foo76e() { func foo76f() { for { // TODO: This one really only escapes its scope, but we don't distinguish yet. - defer myprint(nil, 1, 2, 3) // ERROR "... argument escapes to heap$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" + defer myprint(nil, 1, 2, 3) // ERROR "... argument does not escape$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" } } func foo76g() { for { - defer myprint1(nil, 1, 2, 3) // ERROR "... argument escapes to heap$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" + defer myprint1(nil, 1, 2, 3) // ERROR "... argument does not escape$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" } } @@ -1148,16 +1148,16 @@ L100: func foo121() { for i := 0; i < 10; i++ { - defer myprint(nil, i) // ERROR "... argument escapes to heap$" "i escapes to heap$" - go myprint(nil, i) // ERROR "... argument escapes to heap$" "i escapes to heap$" + defer myprint(nil, i) // ERROR "... argument does not escape$" "i escapes to heap$" + go myprint(nil, i) // ERROR "... argument does not escape$" "i escapes to heap$" } } // same as foo121 but check across import func foo121b() { for i := 0; i < 10; i++ { - defer fmt.Printf("%d", i) // ERROR "... argument escapes to heap$" "i escapes to heap$" - go fmt.Printf("%d", i) // ERROR "... argument escapes to heap$" "i escapes to heap$" + defer fmt.Printf("%d", i) // ERROR "... argument does not escape$" "i escapes to heap$" + go fmt.Printf("%d", i) // ERROR "... argument does not escape$" "i escapes to heap$" } } diff --git a/test/escape2n.go b/test/escape2n.go index 01a25795f4..57cc1a0163 100644 --- a/test/escape2n.go +++ b/test/escape2n.go @@ -667,13 +667,13 @@ func foo76e() { func foo76f() { for { // TODO: This one really only escapes its scope, but we don't distinguish yet. - defer myprint(nil, 1, 2, 3) // ERROR "... argument escapes to heap$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" + defer myprint(nil, 1, 2, 3) // ERROR "... argument does not escape$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" } } func foo76g() { for { - defer myprint1(nil, 1, 2, 3) // ERROR "... argument escapes to heap$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" + defer myprint1(nil, 1, 2, 3) // ERROR "... argument does not escape$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" } } @@ -1148,16 +1148,16 @@ L100: func foo121() { for i := 0; i < 10; i++ { - defer myprint(nil, i) // ERROR "... argument escapes to heap$" "i escapes to heap$" - go myprint(nil, i) // ERROR "... argument escapes to heap$" "i escapes to heap$" + defer myprint(nil, i) // ERROR "... argument does not escape$" "i escapes to heap$" + go myprint(nil, i) // ERROR "... argument does not escape$" "i escapes to heap$" } } // same as foo121 but check across import func foo121b() { for i := 0; i < 10; i++ { - defer fmt.Printf("%d", i) // ERROR "... argument escapes to heap$" "i escapes to heap$" - go fmt.Printf("%d", i) // ERROR "... argument escapes to heap$" "i escapes to heap$" + defer fmt.Printf("%d", i) // ERROR "... argument does not escape$" "i escapes to heap$" + go fmt.Printf("%d", i) // ERROR "... argument does not escape$" "i escapes to heap$" } } diff --git a/test/fixedbugs/issue31573.go b/test/fixedbugs/issue31573.go index 005910e00d..eaab563431 100644 --- a/test/fixedbugs/issue31573.go +++ b/test/fixedbugs/issue31573.go @@ -19,31 +19,31 @@ func g() { defer f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int{...} does not escape$" "new\(int\) does not escape$" go f() - go f(new(int)) // ERROR "... argument escapes to heap$" "new\(int\) escapes to heap$" - go f(new(int), new(int)) // ERROR "... argument escapes to heap$" "new\(int\) escapes to heap$" + go f(new(int)) // ERROR "... argument does not escape$" "new\(int\) escapes to heap$" + go f(new(int), new(int)) // ERROR "... argument does not escape$" "new\(int\) escapes to heap$" go f(nil...) - go f([]*int{}...) // ERROR "\[\]\*int{} escapes to heap$" - go f([]*int{new(int)}...) // ERROR "\[\]\*int{...} escapes to heap$" "new\(int\) escapes to heap$" - go f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int{...} escapes to heap$" "new\(int\) escapes to heap$" + go f([]*int{}...) // ERROR "\[\]\*int{} does not escape$" + go f([]*int{new(int)}...) // ERROR "\[\]\*int{...} does not escape$" "new\(int\) escapes to heap$" + go f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int{...} does not escape$" "new\(int\) escapes to heap$" for { defer f() - defer f(new(int)) // ERROR "... argument escapes to heap$" "new\(int\) escapes to heap$" - defer f(new(int), new(int)) // ERROR "... argument escapes to heap$" "new\(int\) escapes to heap$" + defer f(new(int)) // ERROR "... argument does not escape$" "new\(int\) escapes to heap$" + defer f(new(int), new(int)) // ERROR "... argument does not escape$" "new\(int\) escapes to heap$" defer f(nil...) - defer f([]*int{}...) // ERROR "\[\]\*int{} escapes to heap$" - defer f([]*int{new(int)}...) // ERROR "\[\]\*int{...} escapes to heap$" "new\(int\) escapes to heap$" - defer f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int{...} escapes to heap$" "new\(int\) escapes to heap$" + defer f([]*int{}...) // ERROR "\[\]\*int{} does not escape$" + defer f([]*int{new(int)}...) // ERROR "\[\]\*int{...} does not escape$" "new\(int\) escapes to heap$" + defer f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int{...} does not escape$" "new\(int\) escapes to heap$" go f() - go f(new(int)) // ERROR "... argument escapes to heap$" "new\(int\) escapes to heap$" - go f(new(int), new(int)) // ERROR "... argument escapes to heap$" "new\(int\) escapes to heap$" + go f(new(int)) // ERROR "... argument does not escape$" "new\(int\) escapes to heap$" + go f(new(int), new(int)) // ERROR "... argument does not escape$" "new\(int\) escapes to heap$" go f(nil...) - go f([]*int{}...) // ERROR "\[\]\*int{} escapes to heap$" - go f([]*int{new(int)}...) // ERROR "\[\]\*int{...} escapes to heap$" "new\(int\) escapes to heap$" - go f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int{...} escapes to heap$" "new\(int\) escapes to heap$" + go f([]*int{}...) // ERROR "\[\]\*int{} does not escape$" + go f([]*int{new(int)}...) // ERROR "\[\]\*int{...} does not escape$" "new\(int\) escapes to heap$" + go f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int{...} does not escape$" "new\(int\) escapes to heap$" } } -- GitLab From eb691fdd62c9f1dc36c9c9a974ac2ddad677fd99 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 23 Jun 2021 00:31:16 -0700 Subject: [PATCH 0343/2500] [dev.typeparams] cmd/compile: escape analysis of method expression calls This CL extends escape analysis to analyze function calls using method expressions the same as it would a normal method call. That is, it now analyzes "T.M(recv, args...)" the same as "recv.M(args...)". This is useful because it means the frontend can eventually stop supporting both function calls and method calls. We can simply desugar method calls into function calls, like we already do in the backend to simplify SSA construction. Change-Id: I9cd5ec0d534cbcd9860f0014c86e4ae416920c26 Reviewed-on: https://go-review.googlesource.com/c/go/+/330331 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Matthew Dempsky Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/escape/call.go | 37 +++++++++++++++++-------- test/escape5.go | 3 +- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/cmd/compile/internal/escape/call.go b/src/cmd/compile/internal/escape/call.go index 7b9dbe0dbc..850b9cbde2 100644 --- a/src/cmd/compile/internal/escape/call.go +++ b/src/cmd/compile/internal/escape/call.go @@ -56,11 +56,15 @@ func (e *escape) callCommon(ks []hole, call ir.Node, init *ir.Nodes, wrapper *ir var fn *ir.Name switch call.Op() { case ir.OCALLFUNC: - switch v := ir.StaticValue(call.X); { - case v.Op() == ir.ONAME && v.(*ir.Name).Class == ir.PFUNC: - fn = v.(*ir.Name) - case v.Op() == ir.OCLOSURE: + switch v := ir.StaticValue(call.X); v.Op() { + case ir.ONAME: + if v := v.(*ir.Name); v.Class == ir.PFUNC { + fn = v + } + case ir.OCLOSURE: fn = v.(*ir.ClosureExpr).Func.Nname + case ir.OMETHEXPR: + fn = ir.MethodExprName(v) } case ir.OCALLMETH: fn = ir.MethodExprName(call.X) @@ -77,19 +81,30 @@ func (e *escape) callCommon(ks []hole, call ir.Node, init *ir.Nodes, wrapper *ir } } - if r := fntype.Recv(); r != nil { - dot := call.X.(*ir.SelectorExpr) - argumentFunc(fn, e.tagHole(ks, fn, r), &dot.X) - } else { + var recvp *ir.Node + if call.Op() == ir.OCALLFUNC { // Evaluate callee function expression. // - // Note: We use argument and not argumentFunc, because call.X - // here may be an argument to runtime.{new,defer}proc, but it's - // not an argument to fn itself. + // Note: We use argument and not argumentFunc, because while + // call.X here may be an argument to runtime.{new,defer}proc, + // it's not an argument to fn itself. argument(e.discardHole(), &call.X) + } else { + recvp = &call.X.(*ir.SelectorExpr).X } args := call.Args + if recv := fntype.Recv(); recv != nil { + if recvp == nil { + // Function call using method expression. Recevier argument is + // at the front of the regular arguments list. + recvp = &args[0] + args = args[1:] + } + + argumentFunc(fn, e.tagHole(ks, fn, recv), recvp) + } + for i, param := range fntype.Params().FieldSlice() { argumentFunc(fn, e.tagHole(ks, fn, param), &args[i]) } diff --git a/test/escape5.go b/test/escape5.go index 73acfb46a9..97aaf23b2d 100644 --- a/test/escape5.go +++ b/test/escape5.go @@ -180,8 +180,7 @@ func _() { } func fbad24305() { - // BAD u should not be heap allocated - var u U // ERROR "moved to heap: u" + var u U (*U).M(&u) (*U).N(&u) } -- GitLab From a72a499c24cfcfce2a16ac7c228c2c914c4f36c4 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 23 Jun 2021 00:49:03 -0700 Subject: [PATCH 0344/2500] [dev.typeparams] cmd/compile: optimize wrapping of constant arguments When wrapping a go/defer statement like: go f(g(), "x", 42) we were wrapping it like: _0, _1, _2, _3 := f, g(), "x", 42 go func() { _0(_1, _2, _3) }() This is simple and general (and often necessary), but suboptimal in some cases, such as this. Instead of evaluating the constant arguments at the go/defer statement, and storing them into the closure context, we can just keep them in the wrapped call expression. This CL changes the code to instead generate (assuming f is a declared function, not a function-typed variable): _0 := g() go func() { f(_0, "x", 42) }() Change-Id: I2bdd4951e7ee93363e1656ecf9b5bd69a121c38a Reviewed-on: https://go-review.googlesource.com/c/go/+/330332 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Matthew Dempsky Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/escape/call.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/cmd/compile/internal/escape/call.go b/src/cmd/compile/internal/escape/call.go index 850b9cbde2..b8e28cd46a 100644 --- a/src/cmd/compile/internal/escape/call.go +++ b/src/cmd/compile/internal/escape/call.go @@ -293,6 +293,18 @@ func (e *escape) rewriteArgument(argp *ir.Node, init *ir.Nodes, call ir.Node, fn } visit := func(pos src.XPos, argp *ir.Node) { + // Optimize a few common constant expressions. By leaving these + // untouched in the call expression, we let the wrapper handle + // evaluating them, rather than taking up closure context space. + switch arg := *argp; arg.Op() { + case ir.OLITERAL, ir.ONIL, ir.OMETHEXPR: + return + case ir.ONAME: + if arg.(*ir.Name).Class == ir.PFUNC { + return + } + } + if unsafeUintptr(*argp) { return } -- GitLab From df99a270b36fe9f0b8bd43ba05e305fa738d2de6 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Wed, 16 Jun 2021 11:10:17 -0700 Subject: [PATCH 0345/2500] [dev.fuzz] testing: capture coverage even if tRunner failed Call SnapshotCoverage when the fuzzFn panics, or t.Fatal(f) is called. We currently don't use this coverage for anything, but it is necessary to allow the coordinator to continue when loading a corpus that contains an input that causes crashes. We will also probably want this behavior once we allow the fuzzer to continue after finding a crasher, since the input used to find one crasher may be a useful input for further mutation. Fixes #46633 Change-Id: I40ed5440c88fa354d90a4ff4ae2bf8a19bf3254f Reviewed-on: https://go-review.googlesource.com/c/go/+/328650 Trust: Roland Shoemaker Trust: Katie Hockman Run-TryBot: Roland Shoemaker TryBot-Result: Go Bot Reviewed-by: Katie Hockman Reviewed-by: Jay Conrod --- src/testing/fuzz.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index b4c1ffcdd5..fc1212b142 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -354,9 +354,13 @@ func (f *F) Fuzz(ff interface{}) { for _, v := range e.Values { args = append(args, reflect.ValueOf(v)) } + // Before reseting the current coverage, defer the snapshot so that we + // make sure it is called right before the tRunner function exits, + // regardless of whether it was executed cleanly, panicked, or if the + // fuzzFn called t.Fatal. + defer f.fuzzContext.snapshotCoverage() f.fuzzContext.resetCoverage() fn.Call(args) - f.fuzzContext.snapshotCoverage() }) <-t.signal f.inFuzzFn = false -- GitLab From 8165256bc2e3298b0d612471d7d2e6c005b984de Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 23 Jun 2021 12:08:42 -0700 Subject: [PATCH 0346/2500] [dev.typeparams] cmd/compile/internal/syntax: go/ast-style walk API This CL adds go/ast's Visitor, Walk, and Inspect functions to package syntax. Having functions with the same API and semantics as their go/ast counterparts reduces the mental load of context switching between go/ast and syntax. It also renames the existing Walk function into Crawl, and marks it as a deprecated wrapper around Inspect. (I named it "Crawl" because it's less functional than "Walk"... get it??) There aren't that many callers to Crawl, so we can probably remove it in the future. But it doesn't seem pressing, and I'm more concerned about the risk of forgetting to invert a bool condition somewhere. Change-Id: Ib2fb275873a1d1a730249c9cb584864cb6ec370e Reviewed-on: https://go-review.googlesource.com/c/go/+/330429 Run-TryBot: Matthew Dempsky Trust: Matthew Dempsky Trust: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/noder/irgen.go | 2 +- src/cmd/compile/internal/noder/quirks.go | 8 +-- src/cmd/compile/internal/noder/writer.go | 14 ++-- src/cmd/compile/internal/syntax/walk.go | 72 +++++++++++++++---- .../internal/types2/errorcalls_test.go | 2 +- .../compile/internal/types2/issues_test.go | 2 +- .../compile/internal/types2/resolver_test.go | 4 +- 7 files changed, 74 insertions(+), 30 deletions(-) diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index aac8b5e641..9d14b06d3c 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -191,7 +191,7 @@ Outer: // Double check for any type-checking inconsistencies. This can be // removed once we're confident in IR generation results. - syntax.Walk(p.file, func(n syntax.Node) bool { + syntax.Crawl(p.file, func(n syntax.Node) bool { g.validate(n) return false }) diff --git a/src/cmd/compile/internal/noder/quirks.go b/src/cmd/compile/internal/noder/quirks.go index 91b4c22025..914c5d2bd7 100644 --- a/src/cmd/compile/internal/noder/quirks.go +++ b/src/cmd/compile/internal/noder/quirks.go @@ -36,7 +36,7 @@ func posBasesOf(noders []*noder) []*syntax.PosBase { var bases []*syntax.PosBase for _, p := range noders { - syntax.Walk(p.file, func(n syntax.Node) bool { + syntax.Crawl(p.file, func(n syntax.Node) bool { if b := n.Pos().Base(); !seen[b] { bases = append(bases, b) seen[b] = true @@ -74,7 +74,7 @@ func importedObjsOf(curpkg *types2.Package, info *types2.Info, noders []*noder) } for _, p := range noders { - syntax.Walk(p.file, func(n syntax.Node) bool { + syntax.Crawl(p.file, func(n syntax.Node) bool { switch n := n.(type) { case *syntax.ConstDecl: assoc(n, n.NameList...) @@ -167,7 +167,7 @@ func importedObjsOf(curpkg *types2.Package, info *types2.Info, noders []*noder) if n == nil { return } - syntax.Walk(n, func(n syntax.Node) bool { + syntax.Crawl(n, func(n syntax.Node) bool { switch n := n.(type) { case *syntax.Name: checkdef(n) @@ -237,7 +237,7 @@ func importedObjsOf(curpkg *types2.Package, info *types2.Info, noders []*noder) } if phase >= 5 { - syntax.Walk(p.file, func(n syntax.Node) bool { + syntax.Crawl(p.file, func(n syntax.Node) bool { if name, ok := n.(*syntax.Name); ok { if obj, ok := info.Uses[name]; ok { resolveObj(name.Pos(), obj) diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index cc749b0d1e..bc89e1a262 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -1318,7 +1318,7 @@ func (w *writer) captureVars(expr *syntax.FuncLit) (closureVars []posObj, locals // function literal as the position of the intermediary capture. if quirksMode() && rbracePos == (syntax.Pos{}) { rbracePos = n.Body.Rbrace - syntax.Walk(n.Body, visitor) + syntax.Crawl(n.Body, visitor) rbracePos = syntax.Pos{} return true } @@ -1327,17 +1327,17 @@ func (w *writer) captureVars(expr *syntax.FuncLit) (closureVars []posObj, locals // Quirk: typecheck visits (and thus captures) the RHS of // assignment statements before the LHS. if quirksMode() && (n.Op == 0 || n.Op == syntax.Def) { - syntax.Walk(n.Rhs, visitor) - syntax.Walk(n.Lhs, visitor) + syntax.Crawl(n.Rhs, visitor) + syntax.Crawl(n.Lhs, visitor) return true } case *syntax.RangeClause: // Quirk: Similarly, it visits the expression to be iterated // over before the iteration variables. if quirksMode() { - syntax.Walk(n.X, visitor) + syntax.Crawl(n.X, visitor) if n.Lhs != nil { - syntax.Walk(n.Lhs, visitor) + syntax.Crawl(n.Lhs, visitor) } return true } @@ -1345,7 +1345,7 @@ func (w *writer) captureVars(expr *syntax.FuncLit) (closureVars []posObj, locals return false } - syntax.Walk(expr.Body, visitor) + syntax.Crawl(expr.Body, visitor) return } @@ -1392,7 +1392,7 @@ func (pw *pkgWriter) collectDecls(noders []*noder) { for _, p := range noders { var importedEmbed, importedUnsafe bool - syntax.Walk(p.file, func(n syntax.Node) bool { + syntax.Crawl(p.file, func(n syntax.Node) bool { switch n := n.(type) { case *syntax.File: pw.checkPragmas(n.Pragma, ir.GoBuildPragma, false) diff --git a/src/cmd/compile/internal/syntax/walk.go b/src/cmd/compile/internal/syntax/walk.go index c26e97a0d8..ef213daf7d 100644 --- a/src/cmd/compile/internal/syntax/walk.go +++ b/src/cmd/compile/internal/syntax/walk.go @@ -8,31 +8,73 @@ package syntax import "fmt" -// Walk traverses a syntax in pre-order: It starts by calling f(root); -// root must not be nil. If f returns false (== "continue"), Walk calls +// Inspect traverses an AST in pre-order: It starts by calling +// f(node); node must not be nil. If f returns true, Inspect invokes f +// recursively for each of the non-nil children of node, followed by a +// call of f(nil). +// +// See Walk for caveats about shared nodes. +func Inspect(root Node, f func(Node) bool) { + Walk(root, inspector(f)) +} + +type inspector func(Node) bool + +func (v inspector) Visit(node Node) Visitor { + if v(node) { + return v + } + return nil +} + +// Crawl traverses a syntax in pre-order: It starts by calling f(root); +// root must not be nil. If f returns false (== "continue"), Crawl calls // f recursively for each of the non-nil children of that node; if f -// returns true (== "stop"), Walk does not traverse the respective node's +// returns true (== "stop"), Crawl does not traverse the respective node's // children. +// +// See Walk for caveats about shared nodes. +// +// Deprecated: Use Inspect instead. +func Crawl(root Node, f func(Node) bool) { + Inspect(root, func(node Node) bool { + return node != nil && !f(node) + }) +} + +// Walk traverses an AST in pre-order: It starts by calling +// v.Visit(node); node must not be nil. If the visitor w returned by +// v.Visit(node) is not nil, Walk is invoked recursively with visitor +// w for each of the non-nil children of node, followed by a call of +// w.Visit(nil). +// // Some nodes may be shared among multiple parent nodes (e.g., types in // field lists such as type T in "a, b, c T"). Such shared nodes are // walked multiple times. // TODO(gri) Revisit this design. It may make sense to walk those nodes // only once. A place where this matters is types2.TestResolveIdents. -func Walk(root Node, f func(Node) bool) { - w := walker{f} - w.node(root) +func Walk(root Node, v Visitor) { + walker{v}.node(root) +} + +// A Visitor's Visit method is invoked for each node encountered by Walk. +// If the result visitor w is not nil, Walk visits each of the children +// of node with the visitor w, followed by a call of w.Visit(nil). +type Visitor interface { + Visit(node Node) (w Visitor) } type walker struct { - f func(Node) bool + v Visitor } -func (w *walker) node(n Node) { +func (w walker) node(n Node) { if n == nil { panic("invalid syntax tree: nil node") } - if w.f(n) { + w.v = w.v.Visit(n) + if w.v == nil { return } @@ -285,33 +327,35 @@ func (w *walker) node(n Node) { default: panic(fmt.Sprintf("internal error: unknown node type %T", n)) } + + w.v.Visit(nil) } -func (w *walker) declList(list []Decl) { +func (w walker) declList(list []Decl) { for _, n := range list { w.node(n) } } -func (w *walker) exprList(list []Expr) { +func (w walker) exprList(list []Expr) { for _, n := range list { w.node(n) } } -func (w *walker) stmtList(list []Stmt) { +func (w walker) stmtList(list []Stmt) { for _, n := range list { w.node(n) } } -func (w *walker) nameList(list []*Name) { +func (w walker) nameList(list []*Name) { for _, n := range list { w.node(n) } } -func (w *walker) fieldList(list []*Field) { +func (w walker) fieldList(list []*Field) { for _, n := range list { w.node(n) } diff --git a/src/cmd/compile/internal/types2/errorcalls_test.go b/src/cmd/compile/internal/types2/errorcalls_test.go index 28bb33aaff..80b05f9f0f 100644 --- a/src/cmd/compile/internal/types2/errorcalls_test.go +++ b/src/cmd/compile/internal/types2/errorcalls_test.go @@ -18,7 +18,7 @@ func TestErrorCalls(t *testing.T) { } for _, file := range files { - syntax.Walk(file, func(n syntax.Node) bool { + syntax.Crawl(file, func(n syntax.Node) bool { call, _ := n.(*syntax.CallExpr) if call == nil { return false diff --git a/src/cmd/compile/internal/types2/issues_test.go b/src/cmd/compile/internal/types2/issues_test.go index e716a48038..aafe8de367 100644 --- a/src/cmd/compile/internal/types2/issues_test.go +++ b/src/cmd/compile/internal/types2/issues_test.go @@ -321,7 +321,7 @@ func TestIssue25627(t *testing.T) { } } - syntax.Walk(f, func(n syntax.Node) bool { + syntax.Crawl(f, func(n syntax.Node) bool { if decl, _ := n.(*syntax.TypeDecl); decl != nil { if tv, ok := info.Types[decl.Type]; ok && decl.Name.Value == "T" { want := strings.Count(src, ";") + 1 diff --git a/src/cmd/compile/internal/types2/resolver_test.go b/src/cmd/compile/internal/types2/resolver_test.go index aee435ff5f..a02abce081 100644 --- a/src/cmd/compile/internal/types2/resolver_test.go +++ b/src/cmd/compile/internal/types2/resolver_test.go @@ -143,7 +143,7 @@ func TestResolveIdents(t *testing.T) { // check that qualified identifiers are resolved for _, f := range files { - syntax.Walk(f, func(n syntax.Node) bool { + syntax.Crawl(f, func(n syntax.Node) bool { if s, ok := n.(*syntax.SelectorExpr); ok { if x, ok := s.X.(*syntax.Name); ok { obj := uses[x] @@ -177,7 +177,7 @@ func TestResolveIdents(t *testing.T) { foundDefs := make(map[*syntax.Name]bool) var both []string for _, f := range files { - syntax.Walk(f, func(n syntax.Node) bool { + syntax.Crawl(f, func(n syntax.Node) bool { if x, ok := n.(*syntax.Name); ok { var objects int if _, found := uses[x]; found { -- GitLab From ee4fc0c1bc300f181388ef6dd187ca8b8737efd2 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Fri, 18 Jun 2021 14:09:21 -0700 Subject: [PATCH 0347/2500] [dev.typeparams] Fix issues related to dictionaries and method calls with embedded fields - Fix handling of method expressions with embedded fields. Fix an incorrect lookup for method expressions, which have only the top-level type (and don't have DOT operations for the embedded fields). Add the embedded field dot operations into the closure. - Don't need a dictionary and so don't build a closure if the last embedded field reached in a method expression is an interface value. - Fix methodWrapper() to use the computed 'dot' node in the generic-only part of the code. - For a method expression, don't create a generic wrapper if the last embedded field reached before the method lookup is an interface. Copied cmd/compile/internal/types2/testdata/fixedbugs/issue44688.go2 to test/typeparam/issue44688.go, made it fully runnable (rather than just for compilation), and added a bunch more tests. Change-Id: I90c1aa569e1c7272e986c9d2ae683e553c3a38a1 Reviewed-on: https://go-review.googlesource.com/c/go/+/329550 Run-TryBot: Dan Scales TryBot-Result: Go Bot Trust: Dan Scales Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 30 +++- .../compile/internal/reflectdata/reflect.go | 13 +- test/typeparam/issue44688.go | 150 ++++++++++++++++++ 3 files changed, 184 insertions(+), 9 deletions(-) create mode 100644 test/typeparam/issue44688.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 8b53671dbe..710289b76c 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -76,8 +76,10 @@ func (g *irgen) stencil() { // generic F, not immediately called closureRequired = true } - if n.Op() == ir.OMETHEXPR && len(n.(*ir.SelectorExpr).X.Type().RParams()) > 0 { - // T.M, T a type which is generic, not immediately called + if n.Op() == ir.OMETHEXPR && len(n.(*ir.SelectorExpr).X.Type().RParams()) > 0 && !types.IsInterfaceMethod(n.(*ir.SelectorExpr).Selection.Type) { + // T.M, T a type which is generic, not immediately + // called. Not necessary if the method selected is + // actually for an embedded interface field. closureRequired = true } if n.Op() == ir.OCALL && n.(*ir.CallExpr).X.Op() == ir.OFUNCINST { @@ -156,7 +158,8 @@ func (g *irgen) stencil() { // TODO: only set outer!=nil if this instantiation uses // a type parameter from outer. See comment in buildClosure. return g.buildClosure(outer, x) - case x.Op() == ir.OMETHEXPR && len(deref(x.(*ir.SelectorExpr).X.Type()).RParams()) > 0: // TODO: test for ptr-to-method case + case x.Op() == ir.OMETHEXPR && len(deref(x.(*ir.SelectorExpr).X.Type()).RParams()) > 0 && + !types.IsInterfaceMethod(x.(*ir.SelectorExpr).Selection.Type): // TODO: test for ptr-to-method case return g.buildClosure(outer, x) } return x @@ -230,9 +233,14 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { } } } - t := se.X.Type() - baseSym := t.OrigSym - baseType := baseSym.Def.(*ir.Name).Type() + + // se.X.Type() is the top-level type of the method expression. To + // correctly handle method expressions involving embedded fields, + // look up the generic method below using the type of the receiver + // of se.Selection, since that will be the type that actually has + // the method. + recv := deref(se.Selection.Type.Recv().Type) + baseType := recv.OrigSym.Def.Type() var gf *ir.Name for _, m := range baseType.Methods().Slice() { if se.Sel == m.Sym { @@ -382,7 +390,15 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { } // Then all the other arguments (including receiver for method expressions). for i := 0; i < typ.NumParams(); i++ { - args = append(args, formalParams[i].Nname.(*ir.Name)) + if x.Op() == ir.OMETHEXPR && i == 0 { + // If we are doing a method expression, we need to + // explicitly traverse any embedded fields in the receiver + // argument in order to call the method instantiation. + dot := typecheck.AddImplicitDots(ir.NewSelectorExpr(base.Pos, ir.OXDOT, formalParams[0].Nname.(*ir.Name), x.(*ir.SelectorExpr).Sel)) + args = append(args, dot.X) + } else { + args = append(args, formalParams[i].Nname.(*ir.Name)) + } } // Build call itself. diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 9e070895a0..52534db70d 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -1786,6 +1786,11 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy } dot := typecheck.AddImplicitDots(ir.NewSelectorExpr(base.Pos, ir.OXDOT, nthis, method.Sym)) + if generic && dot.X != nthis && dot.X.Type().IsInterface() { + // We followed some embedded fields, and the last type was + // actually an interface, so no need for a dictionary. + generic = false + } // generate call // It's not possible to use a tail call when dynamic linking on ppc64le. The @@ -1824,9 +1829,13 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy } args = append(args, getDictionary(".inst."+ir.MethodSym(orig, method.Sym).Name, targs)) // TODO: remove .inst. if indirect { - args = append(args, ir.NewStarExpr(base.Pos, nthis)) + args = append(args, ir.NewStarExpr(base.Pos, dot.X)) + } else if methodrcvr.IsPtr() && methodrcvr.Elem() == dot.X.Type() { + // Case where method call is via a non-pointer + // embedded field with a pointer method. + args = append(args, typecheck.NodAddrAt(base.Pos, dot.X)) } else { - args = append(args, nthis) + args = append(args, dot.X) } args = append(args, ir.ParamNames(tfn.Type())...) diff --git a/test/typeparam/issue44688.go b/test/typeparam/issue44688.go new file mode 100644 index 0000000000..d70f94f706 --- /dev/null +++ b/test/typeparam/issue44688.go @@ -0,0 +1,150 @@ +// run -gcflags=-G=3 +//go:build goexperiment.unified +// +build !goexperiment.unified + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// derived & expanded from cmd/compile/internal/types2/testdata/fixedbugs/issue44688.go2 + +package main + +type A1[T any] struct{ + val T +} + +func (p *A1[T]) m1(val T) { + p.val = val +} + +type A2[T any] interface { + m2(T) +} + +type B1[T any] struct { + filler int + *A1[T] + A2[T] +} + +type B2[T any] interface { + A2[T] +} + +type ImpA2[T any] struct { + f T +} + +func (a2 *ImpA2[T]) m2(s T) { + a2.f = s +} + +type C[T any] struct { + filler1 int + filler2 int + B1[T] +} + +type D[T any] struct { + filler1 int + filler2 int + filler3 int + C[T] +} + +func test1[T any](arg T) { + // calling embedded methods + var b1 B1[T] + b1.A1 = &A1[T]{} + b1.A2 = &ImpA2[T]{} + + b1.A1.m1(arg) + b1.m1(arg) + + b1.A2.m2(arg) + b1.m2(arg) + + var b2 B2[T] + b2 = &ImpA2[T]{} + b2.m2(arg) + + // a deeper nesting + var d D[T] + d.C.B1.A1 = &A1[T]{} + d.C.B1.A2 = &ImpA2[T]{} + d.m1(arg) + d.m2(arg) + + // calling method expressions + m1x := B1[T].m1 + m1x(b1, arg) + m2x := B2[T].m2 + m2x(b2, arg) + + // calling method values + m1v := b1.m1 + m1v(arg) + m2v := b1.m2 + m2v(arg) + b2v := b2.m2 + b2v(arg) +} + +func test2() { + // calling embedded methods + var b1 B1[string] + b1.A1 = &A1[string]{} + b1.A2 = &ImpA2[string]{} + + b1.A1.m1("") + b1.m1("") + + b1.A2.m2("") + b1.m2("") + + var b2 B2[string] + b2 = &ImpA2[string]{} + b2.m2("") + + // a deeper nesting + var d D[string] + d.C.B1.A1 = &A1[string]{} + d.C.B1.A2 = &ImpA2[string]{} + d.m1("") + d.m2("") + + // calling method expressions + m1x := B1[string].m1 + m1x(b1, "") + m2x := B2[string].m2 + m2x(b2, "") + + // calling method values + m1v := b1.m1 + m1v("") + m2v := b1.m2 + m2v("") + b2v := b2.m2 + b2v("") +} + +// actual test case from issue + +type A[T any] struct{} + +func (*A[T]) f(T) {} + +type B[T any] struct{ A[T] } + +func test3() { + var b B[string] + b.A.f("") + b.f("") +} + +func main() { + test1[string]("") + test2() + test3() +} -- GitLab From 9bdbf73c98b21c602f1304993176a6db0714f802 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 23 Jun 2021 14:04:11 -0700 Subject: [PATCH 0348/2500] [dev.typeparams] cmd/compile: simplify writer.collectDecls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous code for walking the syntax AST to find declarations needed to know whether a declaration appeared within block scope, but syntax.Crawl (née syntax.Walk) made that somewhat awkward. This CL simplifies it a little, taking advantage of syntax.Walk's support for keeping per-subtree state. Change-Id: I03c7da8c44bec40f88e983852dc6bbab7e6ac13c Reviewed-on: https://go-review.googlesource.com/c/go/+/330549 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/noder/writer.go | 148 +++++++++++++---------- 1 file changed, 85 insertions(+), 63 deletions(-) diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index bc89e1a262..889a96ef9c 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -1386,89 +1386,111 @@ type typeDeclGen struct { gen int } -func (pw *pkgWriter) collectDecls(noders []*noder) { - var typegen int +type fileImports struct { + importedEmbed, importedUnsafe bool +} - for _, p := range noders { - var importedEmbed, importedUnsafe bool +type declCollector struct { + pw *pkgWriter + typegen *int + file *fileImports + withinFunc bool +} - syntax.Crawl(p.file, func(n syntax.Node) bool { - switch n := n.(type) { - case *syntax.File: - pw.checkPragmas(n.Pragma, ir.GoBuildPragma, false) +func (c *declCollector) Visit(n syntax.Node) syntax.Visitor { + pw := c.pw - case *syntax.ImportDecl: - pw.checkPragmas(n.Pragma, 0, false) + switch n := n.(type) { + case *syntax.File: + pw.checkPragmas(n.Pragma, ir.GoBuildPragma, false) - switch pkgNameOf(pw.info, n).Imported().Path() { - case "embed": - importedEmbed = true - case "unsafe": - importedUnsafe = true - } + case *syntax.ImportDecl: + pw.checkPragmas(n.Pragma, 0, false) - case *syntax.ConstDecl: - pw.checkPragmas(n.Pragma, 0, false) + switch pkgNameOf(pw.info, n).Imported().Path() { + case "embed": + c.file.importedEmbed = true + case "unsafe": + c.file.importedUnsafe = true + } - case *syntax.FuncDecl: - pw.checkPragmas(n.Pragma, funcPragmas, false) + case *syntax.ConstDecl: + pw.checkPragmas(n.Pragma, 0, false) - obj := pw.info.Defs[n.Name].(*types2.Func) - pw.funDecls[obj] = n + case *syntax.FuncDecl: + pw.checkPragmas(n.Pragma, funcPragmas, false) - case *syntax.TypeDecl: - obj := pw.info.Defs[n.Name].(*types2.TypeName) - d := typeDeclGen{TypeDecl: n} + obj := pw.info.Defs[n.Name].(*types2.Func) + pw.funDecls[obj] = n - if n.Alias { - pw.checkPragmas(n.Pragma, 0, false) - } else { - pw.checkPragmas(n.Pragma, typePragmas, false) + case *syntax.TypeDecl: + obj := pw.info.Defs[n.Name].(*types2.TypeName) + d := typeDeclGen{TypeDecl: n} - // Assign a unique ID to function-scoped defined types. - if !isGlobal(obj) { - typegen++ - d.gen = typegen - } - } + if n.Alias { + pw.checkPragmas(n.Pragma, 0, false) + } else { + pw.checkPragmas(n.Pragma, typePragmas, false) - pw.typDecls[obj] = d + // Assign a unique ID to function-scoped defined types. + if !isGlobal(obj) { + *c.typegen++ + d.gen = *c.typegen + } + } - case *syntax.VarDecl: - pw.checkPragmas(n.Pragma, 0, true) + pw.typDecls[obj] = d - if p, ok := n.Pragma.(*pragmas); ok && len(p.Embeds) > 0 { - obj := pw.info.Defs[n.NameList[0]].(*types2.Var) - // TODO(mdempsky): isGlobal(obj) gives false positive errors - // for //go:embed directives on package-scope blank - // variables. - if err := checkEmbed(n, importedEmbed, !isGlobal(obj)); err != nil { - pw.errorf(p.Embeds[0].Pos, "%s", err) - } - } + case *syntax.VarDecl: + pw.checkPragmas(n.Pragma, 0, true) - // Workaround for #46208. For variable declarations that - // declare multiple variables and have an explicit type - // expression, the type expression is evaluated multiple - // times. This affects toolstash -cmp, because iexport is - // sensitive to *types.Type pointer identity. - if quirksMode() && n.Type != nil { - tv, ok := pw.info.Types[n.Type] - assert(ok) - assert(tv.IsType()) - for _, name := range n.NameList { - obj := pw.info.Defs[name].(*types2.Var) - pw.dups.add(obj.Type(), tv.Type) - } - } + if p, ok := n.Pragma.(*pragmas); ok && len(p.Embeds) > 0 { + if err := checkEmbed(n, c.file.importedEmbed, c.withinFunc); err != nil { + pw.errorf(p.Embeds[0].Pos, "%s", err) } - return false + } + + // Workaround for #46208. For variable declarations that + // declare multiple variables and have an explicit type + // expression, the type expression is evaluated multiple + // times. This affects toolstash -cmp, because iexport is + // sensitive to *types.Type pointer identity. + if quirksMode() && n.Type != nil { + tv, ok := pw.info.Types[n.Type] + assert(ok) + assert(tv.IsType()) + for _, name := range n.NameList { + obj := pw.info.Defs[name].(*types2.Var) + pw.dups.add(obj.Type(), tv.Type) + } + } + + case *syntax.BlockStmt: + if !c.withinFunc { + copy := *c + copy.withinFunc = true + return © + } + } + + return c +} + +func (pw *pkgWriter) collectDecls(noders []*noder) { + var typegen int + for _, p := range noders { + var file fileImports + + syntax.Walk(p.file, &declCollector{ + pw: pw, + typegen: &typegen, + file: &file, }) pw.cgoPragmas = append(pw.cgoPragmas, p.pragcgobuf...) for _, l := range p.linknames { - if !importedUnsafe { + if !file.importedUnsafe { pw.errorf(l.pos, "//go:linkname only allowed in Go files that import \"unsafe\"") continue } -- GitLab From b55cc6687d8f805663e9e803ad5293d1b399ce37 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 23 Jun 2021 23:56:01 +0700 Subject: [PATCH 0349/2500] [dev.typeparams] cmd/compile: use r.hasTypeParams in typIdx CL 329571 fold the checking has type params logic, but did not realize that the instance in typIdx can be folded, too. Change-Id: I4682af3779535af6a6e843972cada12ba1bae6ae Reviewed-on: https://go-review.googlesource.com/c/go/+/330389 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/noder/reader.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index df9dccc156..d2fe575ffd 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -345,7 +345,7 @@ func (pr *pkgReader) typIdx(idx int, implicits, explicits []*types.Type) *types. // TODO(mdempsky): If we're clever, we should be able to still cache // types by tracking which type parameters are used. However, in my // attempts so far, I haven't yet succeeded in being clever enough. - if len(implicits)+len(explicits) == 0 { + if !r.hasTypeParams() { pr.typs[idx] = typ } -- GitLab From cc04ab463dd6c86ad8d22bbadba4d325fffa2131 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Wed, 23 Jun 2021 16:23:37 -0700 Subject: [PATCH 0350/2500] [dev.fuzz] testing: report T.Deadline when running seed values T.Deadline should return the test deadline, set with -timeout. When fuzz targets are run with seed values as unit tests, either with or without -fuzz, T.Deadline should work inside the fuzz function. There is no deadline when fuzzing, even if -fuzztime is set, since workers may have much shorter deadlines, and fuzz function behavior shouldn't be time-dependent anyway. Fixes #46220 Change-Id: I84aaeb9d7bfdc12bdcb6f1ab3fe67b3067ad2dfe Reviewed-on: https://go-review.googlesource.com/c/go/+/330509 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- .../go/testdata/script/test_fuzz_deadline.txt | 37 +++++++++++++++++++ src/testing/fuzz.go | 3 +- src/testing/testing.go | 2 +- 3 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 src/cmd/go/testdata/script/test_fuzz_deadline.txt diff --git a/src/cmd/go/testdata/script/test_fuzz_deadline.txt b/src/cmd/go/testdata/script/test_fuzz_deadline.txt new file mode 100644 index 0000000000..f0826478ec --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_deadline.txt @@ -0,0 +1,37 @@ +# TODO(jayconrod): support shared memory on more platforms. +[!darwin] [!linux] [!windows] skip + +[short] skip + +# The fuzz function should be able to detect whether -timeout +# was set with T.Deadline. Note there is no F.Deadline, and +# there is no timeout while fuzzing, even if -fuzztime is set. +go test -run=FuzzDeadline -wantdeadline=true # -timeout defaults to 10m +go test -run=FuzzDeadline -timeout=0 -wantdeadline=false +! go test -run=FuzzDeadline -timeout=1s -wantdeadline=false +go test -run=FuzzDeadline -timeout=1s -wantdeadline=true +go test -fuzz=FuzzDeadline -timeout=0 -fuzztime=1s -wantdeadline=false +go test -fuzz=FuzzDeadline -timeout=0 -fuzztime=100x -wantdeadline=false + +-- go.mod -- +module fzz + +go 1.16 +-- fuzz_deadline_test.go -- +package fuzz_test + +import ( + "flag" + "testing" +) + +var wantDeadline = flag.Bool("wantdeadline", false, "whether the test should have a deadline") + +func FuzzDeadline(f *testing.F) { + f.Add("run once") + f.Fuzz(func (t *testing.T, _ string) { + if _, hasDeadline := t.Deadline(); hasDeadline != *wantDeadline { + t.Fatalf("function got %v; want %v", hasDeadline, *wantDeadline) + } + }) +} diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index fc1212b142..55e5397193 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -491,13 +491,14 @@ type fuzzContext struct { // runFuzzTargets runs the fuzz targets matching the pattern for -run. This will // only run the f.Fuzz function for each seed corpus without using the fuzzing // engine to generate or mutate inputs. -func runFuzzTargets(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran, ok bool) { +func runFuzzTargets(deps testDeps, fuzzTargets []InternalFuzzTarget, deadline time.Time) (ran, ok bool) { ok = true if len(fuzzTargets) == 0 || *isFuzzWorker { return ran, ok } m := newMatcher(deps.MatchString, *match, "-test.run") tctx := newTestContext(*parallel, m) + tctx.deadline = deadline fctx := &fuzzContext{ importPath: deps.ImportPath, readCorpus: deps.ReadCorpus, diff --git a/src/testing/testing.go b/src/testing/testing.go index fa92dbb005..581271e748 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1595,7 +1595,7 @@ func (m *M) Run() (code int) { deadline := m.startAlarm() haveExamples = len(m.examples) > 0 testRan, testOk := runTests(m.deps.MatchString, m.tests, deadline) - fuzzTargetsRan, fuzzTargetsOk := runFuzzTargets(m.deps, m.fuzzTargets) + fuzzTargetsRan, fuzzTargetsOk := runFuzzTargets(m.deps, m.fuzzTargets, deadline) exampleRan, exampleOk := runExamples(m.deps.MatchString, m.examples) m.stopAlarm() if !testRan && !exampleRan && !fuzzTargetsRan && *matchBenchmarks == "" && *matchFuzz == "" { -- GitLab From df00abc61b415eb05d4df9fd2bf3fdda1aaaaba3 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 24 Jun 2021 09:07:52 -0700 Subject: [PATCH 0351/2500] [dev.typeparams] cmd/compile: skip escape analysis diagnostics for wrappers This CL changes escape analysis to skip reporting diagnostics (at least for parameter tagging) for generated wrappers. We're inconsistent about when/where wrappers are generated, which made errorcheck tests of escape analysis unnecessarily brittle to changes in wrapper generation. This CL addresses this making errorcheck tests only care about tagging of the actual functions themselves, not the wrappers too. Change-Id: Ia1a0b9dabee4d4162b05647f871db03b032c945a Reviewed-on: https://go-review.googlesource.com/c/go/+/330689 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/escape/escape.go | 17 +++++++++++------ test/uintptrescapes2.go | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/cmd/compile/internal/escape/escape.go b/src/cmd/compile/internal/escape/escape.go index 324d0da3fe..317bc98473 100644 --- a/src/cmd/compile/internal/escape/escape.go +++ b/src/cmd/compile/internal/escape/escape.go @@ -365,6 +365,11 @@ func (b *batch) paramTag(fn *ir.Func, narg int, f *types.Field) string { return fmt.Sprintf("arg#%d", narg) } + // Only report diagnostics for user code; + // not for wrappers generated around them. + // TODO(mdempsky): Generalize this. + diagnose := base.Flag.LowerM != 0 && !(fn.Wrapper() || fn.Dupok()) + if len(fn.Body) == 0 { // Assume that uintptr arguments must be held live across the call. // This is most important for syscall.Syscall. @@ -375,7 +380,7 @@ func (b *batch) paramTag(fn *ir.Func, narg int, f *types.Field) string { fn.Pragma |= ir.UintptrKeepAlive if f.Type.IsUintptr() { - if base.Flag.LowerM != 0 { + if diagnose { base.WarnfAt(f.Pos, "assuming %v is unsafe uintptr", name()) } return "" @@ -390,11 +395,11 @@ func (b *batch) paramTag(fn *ir.Func, narg int, f *types.Field) string { // External functions are assumed unsafe, unless // //go:noescape is given before the declaration. if fn.Pragma&ir.Noescape != 0 { - if base.Flag.LowerM != 0 && f.Sym != nil { + if diagnose && f.Sym != nil { base.WarnfAt(f.Pos, "%v does not escape", name()) } } else { - if base.Flag.LowerM != 0 && f.Sym != nil { + if diagnose && f.Sym != nil { base.WarnfAt(f.Pos, "leaking param: %v", name()) } esc.AddHeap(0) @@ -407,14 +412,14 @@ func (b *batch) paramTag(fn *ir.Func, narg int, f *types.Field) string { fn.Pragma |= ir.UintptrKeepAlive if f.Type.IsUintptr() { - if base.Flag.LowerM != 0 { + if diagnose { base.WarnfAt(f.Pos, "marking %v as escaping uintptr", name()) } return "" } if f.IsDDD() && f.Type.Elem().IsUintptr() { // final argument is ...uintptr. - if base.Flag.LowerM != 0 { + if diagnose { base.WarnfAt(f.Pos, "marking %v as escaping ...uintptr", name()) } return "" @@ -436,7 +441,7 @@ func (b *batch) paramTag(fn *ir.Func, narg int, f *types.Field) string { esc := loc.paramEsc esc.Optimize() - if base.Flag.LowerM != 0 && !loc.escapes { + if diagnose && !loc.escapes { if esc.Empty() { base.WarnfAt(f.Pos, "%v does not escape", name()) } diff --git a/test/uintptrescapes2.go b/test/uintptrescapes2.go index 3ff1d94042..656286c0ff 100644 --- a/test/uintptrescapes2.go +++ b/test/uintptrescapes2.go @@ -30,7 +30,7 @@ type T struct{} func (T) M1(a uintptr) {} // ERROR "escaping uintptr" //go:uintptrescapes -func (T) M2(a ...uintptr) {} // ERROR "escaping ...uintptr" "leaking param: a" +func (T) M2(a ...uintptr) {} // ERROR "escaping ...uintptr" func TestF1() { var t int // ERROR "moved to heap" -- GitLab From ddb09af1b85ee9ae278ef338df56c4d91c1acd0d Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 7 Jun 2021 18:13:15 -0700 Subject: [PATCH 0352/2500] [dev.typeparams] cmd/compile: add derived types and subdictionaries to dictionaries This is code in progress to generate the two main other types of entries in dictionaries: - all types in the instantiated function derived from the type arguments (which are currently concrete, but will eventually be gcshapes) - pointers (i.e. mainly the unique name) to all needed sub-dictionaries In order to generate these entries, we now generate cached information gfInfo about generic functions/methods that can be used for creating the instantiated dictionaries. We use the type substituter to compute the right type args for instantiated sub-dictionaries. If infoPrintMode is changed to true, the code prints out all the information gathered about generic functions, and also the entries in all the dictionaries that are instantiated. The debug mode also prints out the locations where we need main dictionaries in non-instantiated functions. Other changes: - Moved the dictionary generation back to stencil.go from reflect.go, since we need to do extra analysis for the new dictionary entries. In the process, made getInstantiation generate both the function instantiation and the associated dictionary. - Put in small change for now in reflect.go, so that we don't try generate separate dictionaries for Value[T].get and the auto-generated (*Value[T]).get. The auto-generated wrapper shouldn't really need a dictionary. - Detected, but not handling yet, a new case which needs dictionaries - closures that have function params or captured variables whose types are derived from type arguments. - Added new tests in dictionaryCapture for use of method value/expressions in generic functions and for mutually recursive generic functions. Change-Id: If0cbde8805a9f673a23f5ec798769c85c9c5359b Reviewed-on: https://go-review.googlesource.com/c/go/+/327311 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/ir/expr.go | 5 + src/cmd/compile/internal/noder/irgen.go | 13 + src/cmd/compile/internal/noder/stencil.go | 306 ++++++++++++++++-- .../compile/internal/reflectdata/reflect.go | 63 ++-- test/typeparam/dictionaryCapture.go | 66 ++++ 5 files changed, 398 insertions(+), 55 deletions(-) diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 4659b99fbf..81b2c52b87 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -700,6 +700,11 @@ func (n *UnaryExpr) SetOp(op Op) { } } +// Probably temporary: using Implicit() flag to mark generic function nodes that +// are called to make getGfInfo analysis easier in one pre-order pass. +func (n *InstExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 } +func (n *InstExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) } + // An InstExpr is a generic function or type instantiation. type InstExpr struct { miniExpr diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index 9d14b06d3c..8f39061250 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -96,6 +96,15 @@ func check2(noders []*noder) { } } +// gfInfo is information gathered on a generic function. +type gfInfo struct { + tparams []*types.Type + derivedTypes []*types.Type + // Node in generic function that requires a subdictionary. Some of these + // are not function/method values (not strictly calls). + subDictCalls []ir.Node +} + type irgen struct { target *ir.Package self *types2.Package @@ -110,6 +119,10 @@ type irgen struct { instTypeList []*types.Type dnum int // for generating unique dictionary variables + + // Map from generic function to information about its type params, derived + // types, and subdictionaries. + gfInfoMap map[*types.Sym]*gfInfo } func (g *irgen) generate(noders []*noder) { diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 710289b76c..1917c95be7 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -10,12 +10,15 @@ package noder import ( "cmd/compile/internal/base" "cmd/compile/internal/ir" + "cmd/compile/internal/objw" "cmd/compile/internal/reflectdata" "cmd/compile/internal/typecheck" "cmd/compile/internal/types" + "cmd/internal/obj" "cmd/internal/src" "fmt" "go/constant" + "strings" ) func assert(p bool) { @@ -24,6 +27,16 @@ func assert(p bool) { } } +// Temporary - for outputting information on derived types, dictionaries, sub-dictionaries. +// Turn off when running tests. +var infoPrintMode = false + +func infoPrint(format string, a ...interface{}) { + if infoPrintMode { + fmt.Printf(format, a...) + } +} + // stencil scans functions for instantiated generic function calls and creates the // required instantiations for simple generic functions. It also creates // instantiated methods for all fully-instantiated generic types that have been @@ -31,6 +44,7 @@ func assert(p bool) { // process. func (g *irgen) stencil() { g.target.Stencils = make(map[*types.Sym]*ir.Func) + g.gfInfoMap = make(map[*types.Sym]*gfInfo) // Instantiate the methods of instantiated generic types that we have seen so far. g.instantiateMethods() @@ -87,7 +101,14 @@ func (g *irgen) stencil() { // instantiation. call := n.(*ir.CallExpr) inst := call.X.(*ir.InstExpr) - st := g.getInstantiationForNode(inst) + st, dict := g.getInstantiationForNode(inst) + if infoPrintMode && g.target.Stencils[decl.Sym()] == nil { + if inst.X.Op() == ir.OCALLPART { + fmt.Printf("Main dictionary in %v at generic method call: %v - %v\n", decl, inst.X, call) + } else { + fmt.Printf("Main dictionary in %v at generic function call: %v - %v\n", decl, inst.X, call) + } + } // Replace the OFUNCINST with a direct reference to the // new stenciled function call.X = st.Nname @@ -99,7 +120,6 @@ func (g *irgen) stencil() { call.Args.Prepend(inst.X.(*ir.SelectorExpr).X) } // Add dictionary to argument list. - dict := reflectdata.GetDictionaryForInstantiation(inst) call.Args.Prepend(dict) // Transform the Call now, which changes OCALL // to OCALLFUNC and does typecheckaste/assignconvfn. @@ -125,10 +145,9 @@ func (g *irgen) stencil() { } } - st := g.getInstantiation(gf, targs, true) + st, dict := g.getInstantiation(gf, targs, true) call.SetOp(ir.OCALL) call.X = st.Nname - dict := reflectdata.GetDictionaryForMethod(gf, targs) call.Args.Prepend(dict, meth.X) // Transform the Call now, which changes OCALL // to OCALLFUNC and does typecheckaste/assignconvfn. @@ -212,13 +231,14 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { // For functions, the target expects a dictionary as its first argument. // For method values, the target expects a dictionary and the receiver // as its first two arguments. - target = g.getInstantiation(gf, targs, rcvrValue != nil) - - // The value to use for the dictionary argument. - if rcvrValue == nil { - dictValue = reflectdata.GetDictionaryForFunc(gf, targs) - } else { - dictValue = reflectdata.GetDictionaryForMethod(gf, targs) + // dictValue is the value to use for the dictionary argument. + target, dictValue = g.getInstantiation(gf, targs, rcvrValue != nil) + if infoPrintMode && (outer == nil || g.target.Stencils[outer.Sym()] == nil) { + if rcvrValue == nil { + fmt.Printf("Main dictionary in %v for function value %v\n", outer, inst.X) + } else { + fmt.Printf("Main dictionary in %v for method value %v\n", outer, inst.X) + } } } else { // ir.OMETHEXPR // Method expression T.M where T is a generic type. @@ -248,8 +268,10 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { break } } - target = g.getInstantiation(gf, targs, true) - dictValue = reflectdata.GetDictionaryForMethod(gf, targs) + target, dictValue = g.getInstantiation(gf, targs, true) + if infoPrintMode && (outer == nil || g.target.Stencils[outer.Sym()] == nil) { + fmt.Printf("Main dictionary in %v for method expression %v\n", outer, x) + } } // Build a closure to implement a function instantiation. @@ -444,7 +466,7 @@ func (g *irgen) instantiateMethods() { baseType := baseSym.Def.(*ir.Name).Type() for j, _ := range typ.Methods().Slice() { baseNname := baseType.Methods().Slice()[j].Nname.(*ir.Name) - // Eagerly generate the instantiations that implement these methods. + // Eagerly generate the instantiations and dictionaries that implement these methods. // We don't use the instantiations here, just generate them (and any // further instantiations those generate, etc.). // Note that we don't set the Func for any methods on instantiated @@ -452,16 +474,16 @@ func (g *irgen) instantiateMethods() { // Direct method calls go directly to the instantiations, implemented above. // Indirect method calls use wrappers generated in reflectcall. Those wrappers // will use these instantiations if they are needed (for interface tables or reflection). - _ = g.getInstantiation(baseNname, typ.RParams(), true) + _, _ = g.getInstantiation(baseNname, typ.RParams(), true) } } g.instTypeList = nil } -// getInstantiationForNode returns the function/method instantiation for a -// InstExpr node inst. -func (g *irgen) getInstantiationForNode(inst *ir.InstExpr) *ir.Func { +// getInstantiationForNode returns the function/method instantiation and +// dictionary value for a InstExpr node inst. +func (g *irgen) getInstantiationForNode(inst *ir.InstExpr) (*ir.Func, ir.Node) { if meth, ok := inst.X.(*ir.SelectorExpr); ok { return g.getInstantiation(meth.Selection.Nname.(*ir.Name), typecheck.TypesOf(inst.Targs), true) } else { @@ -469,10 +491,10 @@ func (g *irgen) getInstantiationForNode(inst *ir.InstExpr) *ir.Func { } } -// getInstantiation gets the instantiantion of the function or method nameNode +// getInstantiation gets the instantiantion and dictionary of the function or method nameNode // with the type arguments targs. If the instantiated function is not already // cached, then it calls genericSubst to create the new instantiation. -func (g *irgen) getInstantiation(nameNode *ir.Name, targs []*types.Type, isMeth bool) *ir.Func { +func (g *irgen) getInstantiation(nameNode *ir.Name, targs []*types.Type, isMeth bool) (*ir.Func, ir.Node) { if nameNode.Func.Body == nil && nameNode.Func.Inl != nil { // If there is no body yet but Func.Inl exists, then we can can // import the whole generic body. @@ -497,7 +519,7 @@ func (g *irgen) getInstantiation(nameNode *ir.Name, targs []*types.Type, isMeth ir.Dump(fmt.Sprintf("\nstenciled %v", st), st) } } - return st + return st, g.getDictionary(sym.Name, nameNode, targs) } // Struct containing info needed for doing the substitution as we create the @@ -994,3 +1016,245 @@ func deref(t *types.Type) *types.Type { } return t } + +// getDictionary returns the dictionary for the named instantiated function, which +// is instantiated from generic function or method gf, with the type arguments targs. +func (g *irgen) getDictionary(name string, gf *ir.Name, targs []*types.Type) ir.Node { + if len(targs) == 0 { + base.Fatalf("%s should have type arguments", name) + } + + // The dictionary for this instantiation is named after the function + // and concrete types it is instantiated with. + // TODO: decouple this naming from the instantiation naming. The instantiation + // naming will be based on GC shapes, this naming must be fully stenciled. + if !strings.HasPrefix(name, ".inst.") { + base.Fatalf("%s should start in .inst.", name) + } + + info := g.getGfInfo(gf) + + name = ".dict." + name[6:] + + // Get a symbol representing the dictionary. + sym := typecheck.Lookup(name) + + // Initialize the dictionary, if we haven't yet already. + if lsym := sym.Linksym(); len(lsym.P) == 0 { + infoPrint("Creating dictionary %v\n", name) + off := 0 + // Emit an entry for each targ (concrete type or gcshape). + for _, t := range targs { + infoPrint(" * %v\n", t) + s := reflectdata.TypeLinksym(t) + off = objw.SymPtr(lsym, off, s, 0) + } + subst := typecheck.Tsubster{ + Tparams: info.tparams, + Targs: targs, + } + // Emit an entry for each derived type (after substituting targs) + for _, t := range info.derivedTypes { + ts := subst.Typ(t) + infoPrint(" - %v\n", ts) + s := reflectdata.TypeLinksym(ts) + off = objw.SymPtr(lsym, off, s, 0) + } + // Emit an entry for each subdictionary (after substituting targs) + // TODO: actually emit symbol for the subdictionary entry + for _, n := range info.subDictCalls { + if n.Op() == ir.OCALL { + call := n.(*ir.CallExpr) + if call.X.Op() == ir.OXDOT { + subtargs := deref(n.(*ir.CallExpr).X.(*ir.SelectorExpr).X.Type()).RParams() + s2targs := make([]*types.Type, len(subtargs)) + for i, t := range subtargs { + s2targs[i] = subst.Typ(t) + } + sym := typecheck.MakeInstName(ir.MethodSym(call.X.(*ir.SelectorExpr).X.Type(), call.X.(*ir.SelectorExpr).Sel), s2targs, true) + infoPrint(" - Subdict .dict.%v\n", sym.Name[6:]) + } else { + inst := n.(*ir.CallExpr).X.(*ir.InstExpr) + var nameNode *ir.Name + var meth *ir.SelectorExpr + var isMeth bool + if meth, isMeth = inst.X.(*ir.SelectorExpr); isMeth { + nameNode = meth.Selection.Nname.(*ir.Name) + } else { + nameNode = inst.X.(*ir.Name) + } + subtargs := typecheck.TypesOf(inst.Targs) + for i, t := range subtargs { + subtargs[i] = subst.Typ(t) + } + sym := typecheck.MakeInstName(nameNode.Sym(), subtargs, isMeth) + // TODO: This can actually be a static + // main dictionary, if all of the subtargs + // are concrete types (!HasTParam) + infoPrint(" - Subdict .dict.%v\n", sym.Name[6:]) + } + } else if n.Op() == ir.OFUNCINST { + inst := n.(*ir.InstExpr) + nameNode := inst.X.(*ir.Name) + subtargs := typecheck.TypesOf(inst.Targs) + for i, t := range subtargs { + subtargs[i] = subst.Typ(t) + } + sym := typecheck.MakeInstName(nameNode.Sym(), subtargs, false) + // TODO: This can actually be a static + // main dictionary, if all of the subtargs + // are concrete types (!HasTParam) + infoPrint(" - Subdict .dict.%v\n", sym.Name[6:]) + } else if n.Op() == ir.OXDOT { + selExpr := n.(*ir.SelectorExpr) + subtargs := selExpr.X.Type().RParams() + s2targs := make([]*types.Type, len(subtargs)) + for i, t := range subtargs { + s2targs[i] = subst.Typ(t) + } + sym := typecheck.MakeInstName(ir.MethodSym(selExpr.X.Type(), selExpr.Sel), s2targs, true) + infoPrint(" - Subdict .dict.%v\n", sym.Name[6:]) + } + // TODO: handle closure cases that need sub-dictionaries + } + objw.Global(lsym, int32(off), obj.DUPOK|obj.RODATA) + } + + // Make a node referencing the dictionary symbol. + n := typecheck.NewName(sym) + n.SetType(types.Types[types.TUINTPTR]) // should probably be [...]uintptr, but doesn't really matter + n.SetTypecheck(1) + n.Class = ir.PEXTERN + sym.Def = n + + // Return the address of the dictionary. + np := typecheck.NodAddr(n) + // Note: treat dictionary pointers as uintptrs, so they aren't pointers + // with respect to GC. That saves on stack scanning work, write barriers, etc. + // We can get away with it because dictionaries are global variables. + // TODO: use a cast, or is typing directly ok? + np.SetType(types.Types[types.TUINTPTR]) + np.SetTypecheck(1) + return np +} + +// getGfInfo get information for a generic function - type params, derived generic +// types, and subdictionaries. +func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo { + infop := g.gfInfoMap[gn.Sym()] + if infop != nil { + return infop + } + + var info gfInfo + gf := gn.Func + recv := gf.Type().Recv() + if recv != nil { + info.tparams = deref(recv.Type).RParams() + } else { + info.tparams = make([]*types.Type, len(gn.Type().TParams().FieldSlice())) + for i, f := range gn.Type().TParams().FieldSlice() { + info.tparams[i] = f.Type + } + } + for _, n := range gf.Dcl { + addType(&info, n, n.Type()) + } + + if infoPrintMode { + fmt.Printf(">>> Info for %v\n", gn) + for _, t := range info.tparams { + fmt.Printf(" Typeparam %v\n", t) + } + for _, t := range info.derivedTypes { + fmt.Printf(" Derived type %v\n", t) + } + } + + for _, stmt := range gf.Body { + ir.Visit(stmt, func(n ir.Node) { + if n.Op() == ir.OFUNCINST && !n.(*ir.InstExpr).Implicit() { + infoPrint(" Closure&subdictionary required at generic function value %v\n", n.(*ir.InstExpr).X) + info.subDictCalls = append(info.subDictCalls, n) + } else if n.Op() == ir.OXDOT && !n.(*ir.SelectorExpr).Implicit() && + !n.(*ir.SelectorExpr).X.Type().IsInterface() && + len(n.(*ir.SelectorExpr).X.Type().RParams()) > 0 { + // Fix this - doesn't account for embedded fields, etc. + field := typecheck.Lookdot1(n.(*ir.SelectorExpr), n.(*ir.SelectorExpr).Sel, n.(*ir.SelectorExpr).X.Type(), n.(*ir.SelectorExpr).X.Type().Fields(), 0) + if field == nil { + if n.(*ir.SelectorExpr).X.Op() == ir.OTYPE { + infoPrint(" Closure&subdictionary required at generic meth expr %v\n", n) + } else { + infoPrint(" Closure&subdictionary required at generic meth value %v\n", n) + } + info.subDictCalls = append(info.subDictCalls, n) + } + } + if n.Op() == ir.OCALL && n.(*ir.CallExpr).X.Op() == ir.OFUNCINST { + infoPrint(" Subdictionary at generic function call: %v - %v\n", n.(*ir.CallExpr).X.(*ir.InstExpr).X, n) + n.(*ir.CallExpr).X.(*ir.InstExpr).SetImplicit(true) + info.subDictCalls = append(info.subDictCalls, n) + } + if n.Op() == ir.OCALL && n.(*ir.CallExpr).X.Op() == ir.OXDOT && + !n.(*ir.CallExpr).X.(*ir.SelectorExpr).X.Type().IsInterface() && + len(deref(n.(*ir.CallExpr).X.(*ir.SelectorExpr).X.Type()).RParams()) > 0 { + infoPrint(" Subdictionary at generic method call: %v\n", n) + n.(*ir.CallExpr).X.(*ir.SelectorExpr).SetImplicit(true) + info.subDictCalls = append(info.subDictCalls, n) + } + if n.Op() == ir.OCLOSURE { + oldfn := n.(*ir.ClosureExpr).Func + needDict := false + if oldfn.Nname.Type().HasTParam() { + needDict = true + infoPrint(" Subdictionary for closure that has generic params: %v\n", oldfn) + } else { + for _, cv := range oldfn.ClosureVars { + if cv.Type().HasTParam() { + needDict = true + infoPrint(" Subdictionary for closure that has generic capture: %v\n", oldfn) + break + } + } + } + if needDict { + info.subDictCalls = append(info.subDictCalls, n) + } + } + + addType(&info, n, n.Type()) + }) + } + g.gfInfoMap[gn.Sym()] = &info + return &info +} + +// addType adds t to info.derivedTypes if it is parameterized type (which is not +// just a simple type param) that is different from any existing type on +// info.derivedTypes. +func addType(info *gfInfo, n ir.Node, t *types.Type) { + if t == nil || !t.HasTParam() { + return + } + if t.IsTypeParam() && t.Underlying() == t { + return + } + if t.Kind() == types.TFUNC && n != nil && + (n.Op() != ir.ONAME || n.Name().Class == ir.PFUNC) { + // For now, only record function types that are associate with a + // local/global variable (a name which is not a named global + // function). + return + } + if t.Kind() == types.TSTRUCT && t.IsFuncArgStruct() { + // Multiple return values are not a relevant new type (?). + return + } + // Ignore a derived type we've already added. + for _, et := range info.derivedTypes { + if types.Identical(t, et) { + return + } + } + info.derivedTypes = append(info.derivedTypes, t) +} diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 52534db70d..8378fab36d 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -1716,8 +1716,12 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy rcvr = rcvr.PtrTo() } generic := false - if !rcvr.IsInterface() && len(rcvr.RParams()) > 0 || rcvr.IsPtr() && len(rcvr.Elem().RParams()) > 0 { // TODO: right detection? - // TODO: check that we do the right thing when rcvr.IsInterface(). + if !types.IsInterfaceMethod(method.Type) && + (len(rcvr.RParams()) > 0 || + rcvr.IsPtr() && len(rcvr.Elem().RParams()) > 0) { // TODO: right detection? + // Don't need dictionary if we are reaching a method (possibly via + // an embedded field) which is an interface method. + // TODO: check that we do the right thing when method is an interface method. generic = true } if base.Debug.Unified != 0 { @@ -1786,12 +1790,6 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy } dot := typecheck.AddImplicitDots(ir.NewSelectorExpr(base.Pos, ir.OXDOT, nthis, method.Sym)) - if generic && dot.X != nthis && dot.X.Type().IsInterface() { - // We followed some embedded fields, and the last type was - // actually an interface, so no need for a dictionary. - generic = false - } - // generate call // It's not possible to use a tail call when dynamic linking on ppc64le. The // bad scenario is when a local call is made to the wrapper: the wrapper will @@ -1815,6 +1813,14 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy } else { fn.SetWrapper(true) // ignore frame for panic+recover matching var call *ir.CallExpr + + if generic && dot.X != nthis { + // TODO: for now, we don't try to generate dictionary wrappers for + // any methods involving embedded fields, because we're not + // generating the needed dictionaries in instantiateMethods. + generic = false + } + if generic { var args []ir.Node var targs []*types.Type @@ -1827,7 +1833,17 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy fmt.Printf("%s\n", ir.MethodSym(orig, method.Sym).Name) panic("multiple .inst.") } - args = append(args, getDictionary(".inst."+ir.MethodSym(orig, method.Sym).Name, targs)) // TODO: remove .inst. + // Temporary fix: the wrapper for an auto-generated + // pointer/non-pointer receiver method should share the + // same dictionary as the corresponding original + // (user-written) method. + baseOrig := orig + if baseOrig.IsPtr() && !method.Type.Recv().Type.IsPtr() { + baseOrig = baseOrig.Elem() + } else if !baseOrig.IsPtr() && method.Type.Recv().Type.IsPtr() { + baseOrig = types.NewPtr(baseOrig) + } + args = append(args, getDictionary(".inst."+ir.MethodSym(baseOrig, method.Sym).Name, targs)) // TODO: remove .inst. if indirect { args = append(args, ir.NewStarExpr(base.Pos, dot.X)) } else if methodrcvr.IsPtr() && methodrcvr.Elem() == dot.X.Type() { @@ -1852,6 +1868,9 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy } target := ir.AsNode(sym.Def) call = ir.NewCallExpr(base.Pos, ir.OCALL, target, args) + // Fill-in the generic method node that was not filled in + // in instantiateMethod. + method.Nname = fn.Nname } else { call = ir.NewCallExpr(base.Pos, ir.OCALL, dot, nil) call.Args = ir.ParamNames(tfn.Type()) @@ -1924,23 +1943,6 @@ func MarkUsedIfaceMethod(n *ir.CallExpr) { r.Type = objabi.R_USEIFACEMETHOD } -// getDictionaryForInstantiation returns the dictionary that should be used for invoking -// the concrete instantiation described by inst. -func GetDictionaryForInstantiation(inst *ir.InstExpr) ir.Node { - targs := typecheck.TypesOf(inst.Targs) - if meth, ok := inst.X.(*ir.SelectorExpr); ok { - return GetDictionaryForMethod(meth.Selection.Nname.(*ir.Name), targs) - } - return GetDictionaryForFunc(inst.X.(*ir.Name), targs) -} - -func GetDictionaryForFunc(fn *ir.Name, targs []*types.Type) ir.Node { - return getDictionary(typecheck.MakeInstName(fn.Sym(), targs, false).Name, targs) -} -func GetDictionaryForMethod(meth *ir.Name, targs []*types.Type) ir.Node { - return getDictionary(typecheck.MakeInstName(meth.Sym(), targs, true).Name, targs) -} - // getDictionary returns the dictionary for the given named generic function // or method, with the given type arguments. // TODO: pass a reference to the generic function instead? We might need @@ -1964,14 +1966,7 @@ func getDictionary(name string, targs []*types.Type) ir.Node { // Initialize the dictionary, if we haven't yet already. if lsym := sym.Linksym(); len(lsym.P) == 0 { - off := 0 - // Emit an entry for each concrete type. - for _, t := range targs { - s := TypeLinksym(t) - off = objw.SymPtr(lsym, off, s, 0) - } - // TODO: subdictionaries - objw.Global(lsym, int32(off), obj.DUPOK|obj.RODATA) + base.Fatalf("Dictionary should have alredy been generated: %v", sym) } // Make a node referencing the dictionary symbol. diff --git a/test/typeparam/dictionaryCapture.go b/test/typeparam/dictionaryCapture.go index 1b2ee1de91..af508859e1 100644 --- a/test/typeparam/dictionaryCapture.go +++ b/test/typeparam/dictionaryCapture.go @@ -10,12 +10,19 @@ package main +import ( + "fmt" +) + func main() { functions() methodExpressions() + genMethodExpressions[int](7) methodValues() + genMethodValues[int](7) interfaceMethods() globals() + recursive() } func g0[T any](x T) { @@ -72,6 +79,20 @@ func methodExpressions() { is77(f2(x)) } +func genMethodExpressions[T comparable](want T) { + x := s[T]{a: want} + f0 := s[T].g0 + f0(x) + f1 := s[T].g1 + if got := f1(x); got != want { + panic(fmt.Sprintf("f1(x) == %d, want %d", got, want)) + } + f2 := s[T].g2 + if got1, got2 := f2(x); got1 != want || got2 != want { + panic(fmt.Sprintf("f2(x) == %d, %d, want %d, %d", got1, got2, want, want)) + } +} + func methodValues() { x := s[int]{a:7} f0 := x.g0 @@ -82,6 +103,20 @@ func methodValues() { is77(f2()) } +func genMethodValues[T comparable](want T) { + x := s[T]{a: want} + f0 := x.g0 + f0() + f1 := x.g1 + if got := f1(); got != want { + panic(fmt.Sprintf("f1() == %d, want %d", got, want)) + } + f2 := x.g2 + if got1, got2 := f2(); got1 != want || got2 != want { + panic(fmt.Sprintf("f2() == %d, %d, want %d, %d", got1, got2, want, want)) + } +} + var x interface{ g0() g1()int @@ -124,3 +159,34 @@ func globals() { is7(ii1()) is77(ii2()) } + + +func recursive() { + if got, want := recur1[int](5), 110; got != want { + panic(fmt.Sprintf("recur1[int](5) = %d, want = %d", got, want)) + } +} + +type Integer interface { + int | int32 | int64 +} + +func recur1[T Integer](n T) T { + if n == 0 || n == 1 { + return T(1) + } else { + return n * recur2(n - 1) + } +} + +func recur2[T Integer](n T) T { + list := make([]T, n) + for i, _ := range list { + list[i] = T(i+1) + } + var sum T + for _, elt := range list { + sum += elt + } + return sum + recur1(n-1) +} -- GitLab From 808dca3b2d305570b3f1e003ff221557405f59b9 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 24 Jun 2021 12:57:20 -0700 Subject: [PATCH 0353/2500] [dev.typeparams] cmd/compile: suppress liveness diagnostics of wrappers Similar to the previous CL to suppress escape analysis diagnostics for method wrappers, suppress liveness analysis diagnostics too. It's hardly useful to know that all of a wrapper method's arguments are live at entry. Change-Id: I0d1e44552c6334ee3b454adc107430232abcb56a Reviewed-on: https://go-review.googlesource.com/c/go/+/330749 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/liveness/plive.go | 4 ++++ test/live.go | 2 +- test/live_regabi.go | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/liveness/plive.go b/src/cmd/compile/internal/liveness/plive.go index f5c2ef7709..2705eac4f7 100644 --- a/src/cmd/compile/internal/liveness/plive.go +++ b/src/cmd/compile/internal/liveness/plive.go @@ -1082,6 +1082,10 @@ func (lv *liveness) showlive(v *ssa.Value, live bitvec.BitVec) { if base.Flag.Live == 0 || ir.FuncName(lv.fn) == "init" || strings.HasPrefix(ir.FuncName(lv.fn), ".") { return } + if lv.fn.Wrapper() || lv.fn.Dupok() { + // Skip reporting liveness information for compiler-generated wrappers. + return + } if !(v == nil || v.Op.IsCall()) { // Historically we only printed this information at // calls. Keep doing so. diff --git a/test/live.go b/test/live.go index 5b14932cae..856e56f3d2 100644 --- a/test/live.go +++ b/test/live.go @@ -688,7 +688,7 @@ type T struct{} func (*T) Foo(ptr *int) {} -type R struct{ *T } // ERRORAUTO "live at entry to \(\*R\)\.Foo: \.this ptr" "live at entry to R\.Foo: \.this ptr" +type R struct{ *T } // issue 18860: output arguments must be live all the time if there is a defer. // In particular, at printint r must be live. diff --git a/test/live_regabi.go b/test/live_regabi.go index c35a27e4e0..d362ee287d 100644 --- a/test/live_regabi.go +++ b/test/live_regabi.go @@ -683,7 +683,7 @@ type T struct{} func (*T) Foo(ptr *int) {} -type R struct{ *T } // ERRORAUTO "live at entry to \(\*R\)\.Foo: \.this ptr" "live at entry to R\.Foo: \.this ptr" +type R struct{ *T } // issue 18860: output arguments must be live all the time if there is a defer. // In particular, at printint r must be live. -- GitLab From 75ad32377378b4d6fa831b67a7f6aaf68cbe07d4 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 24 Jun 2021 14:32:21 -0700 Subject: [PATCH 0354/2500] [dev.typeparams] test: skip -G=3 testing under GOEXPERIMENT=unified In normal build configurations, we test both -G=0 and -G=3 so that we can test both typecheck and types2. However, GOEXPERIMENT=unified always uses types2, so testing both is redundant. Change-Id: I697d2ad916d8b17cfaf4f0b6b32eec380d4e7906 Reviewed-on: https://go-review.googlesource.com/c/go/+/330755 Run-TryBot: Matthew Dempsky Trust: Matthew Dempsky Reviewed-by: Robert Griesemer --- test/run.go | 63 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/test/run.go b/test/run.go index f8bb8c081c..ad92d8bb79 100644 --- a/test/run.go +++ b/test/run.go @@ -42,13 +42,36 @@ var ( linkshared = flag.Bool("linkshared", false, "") updateErrors = flag.Bool("update_errors", false, "update error messages in test file based on compiler output") runoutputLimit = flag.Int("l", defaultRunOutputLimit(), "number of parallel runoutput tests to run") - generics = flag.String("G", "0,3", "a comma-separated list of -G compiler flags to test with") force = flag.Bool("f", false, "run expected-failure generics tests rather than skipping them") + generics = flag.String("G", defaultGLevels, "a comma-separated list of -G compiler flags to test with") shard = flag.Int("shard", 0, "shard index to run. Only applicable if -shards is non-zero.") shards = flag.Int("shards", 0, "number of shards. If 0, all tests are run. This is used by the continuous build.") ) +var unifiedEnabled, defaultGLevels = func() (bool, string) { + // TODO(mdempsky): Change this to just "go env GOEXPERIMENT" after + // CL 328751 is merged back to dev.typeparams. In the mean time, we + // infer whether the "unified" experiment is default enabled by + // inspecting the output from `go tool compile -V`. + output := runOutput(goTool(), "tool", "compile", "-V") + + // TODO(mdempsky): This will give false negatives if the unified + // experiment is enabled by default, but presumably at that point we + // won't need to disable tests for it anymore anyway. + enabled := strings.Contains(output, "unified") + + // Normal test runs should test with both -G=0 and -G=3 for types2 + // coverage. But the unified experiment always uses types2, so + // testing with -G=3 is redundant. + glevels := "0,3" + if enabled { + glevels = "0" + } + + return enabled, glevels +}() + // defaultAllCodeGen returns the default value of the -all_codegen // flag. By default, we prefer to be fast (returning false), except on // the linux-amd64 builder that's already very fast, so we get more @@ -58,9 +81,8 @@ func defaultAllCodeGen() bool { } var ( - goos, goarch string - cgoEnabled bool - unifiedEnabled bool + goos, goarch string + cgoEnabled bool // dirs are the directories to look for *.go files in. // TODO(bradfitz): just use all directories? @@ -97,26 +119,8 @@ func main() { goos = getenv("GOOS", runtime.GOOS) goarch = getenv("GOARCH", runtime.GOARCH) - cgoCmd := exec.Command(goTool(), "env", "CGO_ENABLED") - cgoEnv, err := cgoCmd.Output() - if err != nil { - log.Fatalf("running %v: %v", cgoCmd, err) - } - cgoEnabled, _ = strconv.ParseBool(strings.TrimSpace(string(cgoEnv))) - - // TODO(mdempsky): Change this to just "go env GOEXPERIMENT" after - // CL 328751 is merged back to dev.typeparams. In the mean time, we - // infer whether the "unified" experiment is defult enabled by - // inspecting the output from `go tool compile -V`. - compileCmd := exec.Command(goTool(), "tool", "compile", "-V") - compileOutput, err := compileCmd.Output() - if err != nil { - log.Fatalf("running %v: %v", compileCmd, err) - } - // TODO(mdempsky): This will give false negatives if the unified - // experiment is enabled by default, but presumably at that point we - // won't need to disable tests for it anymore anyway. - unifiedEnabled = strings.Contains(string(compileOutput), "unified") + cgoEnv := runOutput(goTool(), "env", "CGO_ENABLED") + cgoEnabled, _ = strconv.ParseBool(strings.TrimSpace(cgoEnv)) findExecCmd() @@ -203,6 +207,17 @@ func main() { } } +// runOutput runs the specified command and returns its output as a +// string. If the command fails, runOutput logs the error and exits. +func runOutput(name string, args ...string) string { + cmd := exec.Command(name, args...) + output, err := cmd.Output() + if err != nil { + log.Fatalf("running %v: %v", cmd, err) + } + return string(output) +} + // goTool reports the path of the go tool to use to run the tests. // If possible, use the same Go used to run run.go, otherwise // fallback to the go version found in the PATH. -- GitLab From aee209c04426c50bb045e058b4f618ed306b7d62 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 24 Jun 2021 14:13:39 +0700 Subject: [PATCH 0355/2500] [dev.typeparams] cmd/compile: catch another mis-used OCALLMETH in backend OCALLMETH is rewritten by walkCall to OCALLFUNC, and other places in backend have already caught it. So do the same thing in state.expr for consistency and prevent mis-use in frontend side. While at it, also remove un-used function getParam. Change-Id: I03e1ea907e0bcb05fa35fa81804c33b5c9a4d77e Reviewed-on: https://go-review.googlesource.com/c/go/+/330669 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ssagen/ssa.go | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 93847a39a3..9212c5776e 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -279,18 +279,6 @@ func regAbiForFuncType(ft *types.Func) bool { return np > 0 && strings.Contains(ft.Params.FieldType(np-1).String(), magicLastTypeName) } -// getParam returns the Field of ith param of node n (which is a -// function/method/interface call), where the receiver of a method call is -// considered as the 0th parameter. This does not include the receiver of an -// interface call. -func getParam(n *ir.CallExpr, i int) *types.Field { - t := n.X.Type() - if n.Op() == ir.OCALLMETH { - base.Fatalf("OCALLMETH missed by walkCall") - } - return t.Params().Field(i) -} - // dvarint writes a varint v to the funcdata in symbol x and returns the new offset func dvarint(x *obj.LSym, off int, v int64) int { if v < 0 || v > 1e9 { @@ -3127,10 +3115,14 @@ func (s *state) expr(n ir.Node) *ssa.Value { } fallthrough - case ir.OCALLINTER, ir.OCALLMETH: + case ir.OCALLINTER: n := n.(*ir.CallExpr) return s.callResult(n, callNormal) + case ir.OCALLMETH: + base.Fatalf("OCALLMETH missed by walkCall") + panic("unreachable") + case ir.OGETG: n := n.(*ir.CallExpr) return s.newValue1(ssa.OpGetG, n.Type(), s.mem()) -- GitLab From f190a9280ddcaa958610e104a3f6c105fedd3fee Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 24 Jun 2021 22:39:16 +0700 Subject: [PATCH 0356/2500] [dev.typeparams] cmd/compile: simplify usemethod By checking for method name first. Passes toolstash -cmp Change-Id: I1f4125157a8bc247e4766a882467b805a205a3c2 Reviewed-on: https://go-review.googlesource.com/c/go/+/330670 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/walk/expr.go | 67 ++++++++++++--------------- 1 file changed, 30 insertions(+), 37 deletions(-) diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go index 070954be27..bbf289d90e 100644 --- a/src/cmd/compile/internal/walk/expr.go +++ b/src/cmd/compile/internal/walk/expr.go @@ -931,42 +931,8 @@ func bounded(n ir.Node, max int64) bool { return false } -// usemethod checks interface method calls for uses of reflect.Type.Method. +// usemethod checks calls for uses of reflect.Type.{Method,MethodByName}. func usemethod(n *ir.CallExpr) { - t := n.X.Type() - - // Looking for either of: - // Method(int) reflect.Method - // MethodByName(string) (reflect.Method, bool) - // - // TODO(crawshaw): improve precision of match by working out - // how to check the method name. - if n := t.NumParams(); n != 1 { - return - } - if n := t.NumResults(); n != 1 && n != 2 { - return - } - p0 := t.Params().Field(0) - res0 := t.Results().Field(0) - var res1 *types.Field - if t.NumResults() == 2 { - res1 = t.Results().Field(1) - } - - if res1 == nil { - if p0.Type.Kind() != types.TINT { - return - } - } else { - if !p0.Type.IsString() { - return - } - if !res1.Type.IsBoolean() { - return - } - } - // Don't mark reflect.(*rtype).Method, etc. themselves in the reflect package. // Those functions may be alive via the itab, which should not cause all methods // alive. We only want to mark their callers. @@ -977,10 +943,37 @@ func usemethod(n *ir.CallExpr) { } } - // Note: Don't rely on res0.Type.String() since its formatting depends on multiple factors + dot, ok := n.X.(*ir.SelectorExpr) + if !ok { + return + } + + // Looking for either direct method calls and interface method calls of: + // reflect.Type.Method - func(int) reflect.Method + // reflect.Type.MethodByName - func(string) (reflect.Method, bool) + var pKind types.Kind + + switch dot.Sel.Name { + case "Method": + pKind = types.TINT + case "MethodByName": + pKind = types.TSTRING + default: + return + } + + t := dot.Selection.Type + if t.NumParams() != 1 || t.Params().Field(0).Type.Kind() != pKind { + return + } + if t.NumResults() == 2 && t.Results().Field(1).Type.Kind() != types.TBOOL { + return + } + + // Note: Don't rely on Field.Type.String() since its formatting depends on multiple factors // (including global variables such as numImports - was issue #19028). // Also need to check for reflect package itself (see Issue #38515). - if s := res0.Type.Sym(); s != nil && s.Name == "Method" && types.IsReflectPkg(s.Pkg) { + if s := t.Results().Field(0).Type.Sym(); s != nil && s.Name == "Method" && types.IsReflectPkg(s.Pkg) { ir.CurFunc.SetReflectMethod(true) // The LSym is initialized at this point. We need to set the attribute on the LSym. ir.CurFunc.LSym.Set(obj.AttrReflectMethod, true) -- GitLab From 2493c727425547db935a1c6e519bc19d01476380 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 24 Jun 2021 23:05:09 +0700 Subject: [PATCH 0357/2500] [dev.typeparams] cmd/compile: rewrite method call into method expression during escape analysis CL 330331 extended escape analysis to analyze method expression calls the same as normal method calls. We can now simply desugar method calls into function calls in escape analysis. To do this, two things must be changed: - Folding the rewrite method call to method expression call into an export function in typecheck package, so others can re-use it. - walkCall now have to call usemethod for method expression calls. (It seems to me this is a bug in current tip, because if one write (*rtype).Method(typ, i) in package "reflect", then the function won't be marked with AttrReflectMethod) Passes toolstash -cmp. Change-Id: I4745ab6110b417c7fd32949cc799811a882cd2ec Reviewed-on: https://go-review.googlesource.com/c/go/+/330671 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- .../internal/devirtualize/devirtualize.go | 1 - src/cmd/compile/internal/escape/call.go | 1 + src/cmd/compile/internal/typecheck/func.go | 21 ++++++++++++++++++- src/cmd/compile/internal/walk/expr.go | 16 ++------------ 4 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/cmd/compile/internal/devirtualize/devirtualize.go b/src/cmd/compile/internal/devirtualize/devirtualize.go index 60ba208d08..f52499e07f 100644 --- a/src/cmd/compile/internal/devirtualize/devirtualize.go +++ b/src/cmd/compile/internal/devirtualize/devirtualize.go @@ -50,7 +50,6 @@ func Call(call *ir.CallExpr) { if base.Flag.LowerM != 0 { base.WarnfAt(call.Pos(), "devirtualizing %v to %v", sel, typ) } - call.SetOp(ir.OCALLMETH) call.X = x case ir.ODOTINTER: // Promoted method from embedded interface-typed field (#42279). diff --git a/src/cmd/compile/internal/escape/call.go b/src/cmd/compile/internal/escape/call.go index b8e28cd46a..62727a8ef8 100644 --- a/src/cmd/compile/internal/escape/call.go +++ b/src/cmd/compile/internal/escape/call.go @@ -46,6 +46,7 @@ func (e *escape) callCommon(ks []hole, call ir.Node, init *ir.Nodes, wrapper *ir case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER: call := call.(*ir.CallExpr) typecheck.FixVariadicCall(call) + typecheck.FixMethodCall(call) // Pick out the function callee, if statically known. // diff --git a/src/cmd/compile/internal/typecheck/func.go b/src/cmd/compile/internal/typecheck/func.go index 031279f42c..00770c87cf 100644 --- a/src/cmd/compile/internal/typecheck/func.go +++ b/src/cmd/compile/internal/typecheck/func.go @@ -15,7 +15,7 @@ import ( "go/token" ) -// package all the arguments that match a ... T parameter into a []T. +// MakeDotArgs package all the arguments that match a ... T parameter into a []T. func MakeDotArgs(pos src.XPos, typ *types.Type, args []ir.Node) ir.Node { var n ir.Node if len(args) == 0 { @@ -57,6 +57,25 @@ func FixVariadicCall(call *ir.CallExpr) { call.IsDDD = true } +// FixMethodCall rewrites a method call t.M(...) into a function call T.M(t, ...). +func FixMethodCall(call *ir.CallExpr) { + if call.X.Op() != ir.ODOTMETH { + return + } + + dot := call.X.(*ir.SelectorExpr) + + fn := Expr(ir.NewSelectorExpr(dot.Pos(), ir.OXDOT, ir.TypeNode(dot.X.Type()), dot.Selection.Sym)) + + args := make([]ir.Node, 1+len(call.Args)) + args[0] = dot.X + copy(args[1:], call.Args) + + call.SetOp(ir.OCALLFUNC) + call.X = fn + call.Args = args +} + // ClosureType returns the struct type used to hold all the information // needed in the closure for clo (clo must be a OCLOSURE node). // The address of a variable of the returned type can be cast to a func. diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go index bbf289d90e..d8bded8075 100644 --- a/src/cmd/compile/internal/walk/expr.go +++ b/src/cmd/compile/internal/walk/expr.go @@ -489,7 +489,7 @@ func walkAddString(n *ir.AddStringExpr, init *ir.Nodes) ir.Node { // walkCall walks an OCALLFUNC, OCALLINTER, or OCALLMETH node. func walkCall(n *ir.CallExpr, init *ir.Nodes) ir.Node { - if n.Op() == ir.OCALLINTER || n.Op() == ir.OCALLMETH { + if n.Op() == ir.OCALLINTER || n.X.Op() == ir.OMETHEXPR { // We expect both interface call reflect.Type.Method and concrete // call reflect.(*rtype).Method. usemethod(n) @@ -549,20 +549,8 @@ func walkCall1(n *ir.CallExpr, init *ir.Nodes) { } n.SetWalked(true) - // If this is a method call t.M(...), - // rewrite into a function call T.M(t, ...). - // TODO(mdempsky): Do this right after type checking. if n.Op() == ir.OCALLMETH { - withRecv := make([]ir.Node, len(n.Args)+1) - dot := n.X.(*ir.SelectorExpr) - withRecv[0] = dot.X - copy(withRecv[1:], n.Args) - n.Args = withRecv - - dot = ir.NewSelectorExpr(dot.Pos(), ir.OXDOT, ir.TypeNode(dot.X.Type()), dot.Selection.Sym) - - n.SetOp(ir.OCALLFUNC) - n.X = typecheck.Expr(dot) + typecheck.FixMethodCall(n) } args := n.Args -- GitLab From badb98364b3710933de89bfe579fb8d1f82741c8 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 23 Jun 2021 14:45:34 -0700 Subject: [PATCH 0358/2500] [dev.typeparams] cmd/compile: switch CaptureVars to use syntax.Walk This CL refactors CaptureVars to use a visitor type so it's easier to break out helper functions to review. It also simplifies the quirks-mode handling of function literals: instead of trying to maintain information about whether we're inside a function literal or not, it now just rewrites the recorded position information for any newly added free variables after walking the function literal. (Quirks mode is only for "toolstash -cmp"-style binary output testing of normal code and will eventually be removed, so I don't think it's important that this is an O(N^2) algorithm for deeply nested function literals with lots of free variables.) Change-Id: I0689984f6d88cf9937d4706d2d8de96415eaeee3 Reviewed-on: https://go-review.googlesource.com/c/go/+/330789 Trust: Matthew Dempsky Trust: Robert Griesemer Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/noder/writer.go | 140 +++++++++++++---------- 1 file changed, 82 insertions(+), 58 deletions(-) diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 889a96ef9c..cc44a80a42 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -1264,90 +1264,114 @@ type posObj struct { } // captureVars returns the free variables used by the given function -// literal. +// literal. The closureVars result is the list of free variables +// captured by expr, and localsIdx is a map from free variable to +// index. See varCaptor's identically named fields for more details. func (w *writer) captureVars(expr *syntax.FuncLit) (closureVars []posObj, localsIdx map[types2.Object]int) { scope, ok := w.p.info.Scopes[expr.Type] assert(ok) - localsIdx = make(map[types2.Object]int) - // TODO(mdempsky): This code needs to be cleaned up (e.g., to avoid // traversing nested function literals multiple times). This will be // easier after we drop quirks mode. - var rbracePos syntax.Pos + v := varCaptor{ + w: w, + scope: scope, + localsIdx: make(map[types2.Object]int), + } - var visitor func(n syntax.Node) bool - visitor = func(n syntax.Node) bool { + syntax.Walk(expr, &v) - // Constant expressions don't count towards capturing. - if n, ok := n.(syntax.Expr); ok { - if tv, ok := w.p.info.Types[n]; ok && tv.Value != nil { - return true - } + return v.closureVars, v.localsIdx +} + +// varCaptor implements syntax.Visitor for enumerating free variables +// used by a function literal. +type varCaptor struct { + w *writer + scope *types2.Scope + + // closureVars lists free variables along with the position where + // they first appeared, in order of appearance. + closureVars []posObj + + // localsIdx is a map from free variables to their index within + // closureVars. + localsIdx map[types2.Object]int +} + +func (v *varCaptor) capture(n *syntax.Name) { + obj, ok := v.w.p.info.Uses[n].(*types2.Var) + if !ok || obj.IsField() { + return // not a variable + } + + if obj.Parent() == obj.Pkg().Scope() { + return // global variable + } + + if _, ok := v.localsIdx[obj]; ok { + return // already captured + } + + for parent := obj.Parent(); parent != obj.Pkg().Scope(); parent = parent.Parent() { + if parent == v.scope { + return // object declared within our scope } + } - switch n := n.(type) { - case *syntax.Name: - if obj, ok := w.p.info.Uses[n].(*types2.Var); ok && !obj.IsField() && obj.Pkg() == w.p.curpkg && obj.Parent() != obj.Pkg().Scope() { - // Found a local variable. See if it chains up to scope. - parent := obj.Parent() - for { - if parent == scope { - break - } - if parent == obj.Pkg().Scope() { - if _, present := localsIdx[obj]; !present { - pos := rbracePos - if pos == (syntax.Pos{}) { - pos = n.Pos() - } - - idx := len(closureVars) - closureVars = append(closureVars, posObj{pos, obj}) - localsIdx[obj] = idx - } - break - } - parent = parent.Parent() - } - } + idx := len(v.closureVars) + v.closureVars = append(v.closureVars, posObj{n.Pos(), obj}) + v.localsIdx[obj] = idx +} + +func (v *varCaptor) Visit(n syntax.Node) syntax.Visitor { + // Constant expressions don't count towards capturing. + if n, ok := n.(syntax.Expr); ok { + if tv, ok := v.w.p.info.Types[n]; ok && tv.Value != nil { + return nil + } + } + + if n, ok := n.(*syntax.Name); ok { + v.capture(n) + } + if quirksMode() { + switch n := n.(type) { case *syntax.FuncLit: // Quirk: typecheck uses the rbrace position position of the // function literal as the position of the intermediary capture. - if quirksMode() && rbracePos == (syntax.Pos{}) { - rbracePos = n.Body.Rbrace - syntax.Crawl(n.Body, visitor) - rbracePos = syntax.Pos{} - return true + end := len(v.closureVars) + syntax.Walk(n.Type, v) // unnecessary to walk, but consistent with non-quirks mode + syntax.Walk(n.Body, v) + for i := end; i < len(v.closureVars); i++ { + v.closureVars[i].pos = n.Body.Rbrace } + return nil case *syntax.AssignStmt: // Quirk: typecheck visits (and thus captures) the RHS of - // assignment statements before the LHS. - if quirksMode() && (n.Op == 0 || n.Op == syntax.Def) { - syntax.Crawl(n.Rhs, visitor) - syntax.Crawl(n.Lhs, visitor) - return true + // assignment statements (but not op= statements) before the LHS. + if n.Op == 0 || n.Op == syntax.Def { + syntax.Walk(n.Rhs, v) + syntax.Walk(n.Lhs, v) + return nil } + case *syntax.RangeClause: - // Quirk: Similarly, it visits the expression to be iterated - // over before the iteration variables. - if quirksMode() { - syntax.Crawl(n.X, visitor) - if n.Lhs != nil { - syntax.Crawl(n.Lhs, visitor) - } - return true + // Quirk: Similarly, typecheck visits the expression to be + // iterated over before the iteration variables. + syntax.Walk(n.X, v) + if n.Lhs != nil { + syntax.Walk(n.Lhs, v) } + return nil } - - return false } - syntax.Crawl(expr.Body, visitor) - return + return v } func (w *writer) exprList(expr syntax.Expr) { -- GitLab From 3f1a517a45d2e443a327e0b28df17698e299ea50 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 24 Jun 2021 11:31:56 -0700 Subject: [PATCH 0359/2500] [dev.typeparams] cmd/compile: refactor "need to emit" logic for types This CL refactors out a single reflectdata.NeedEmit function that reports whether the current compilation unit needs to emit the runtime type descriptor and method wrappers for a given type. As a minor side bonus, this CL also skips compiling the "error.Error" wrapper in non-runtime packages. Package runtime already unconditionally emitted the runtime type descriptor for error, so we just need to make sure it emits the wrapper and other packages don't. Passes toolstash -cmp. Change-Id: Ic9ea219dfba8a0a57f2f42f817bdff7618732bff Reviewed-on: https://go-review.googlesource.com/c/go/+/330754 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- .../compile/internal/reflectdata/reflect.go | 91 +++++++++++-------- 1 file changed, 55 insertions(+), 36 deletions(-) diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 8378fab36d..ba4bbc7631 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -927,29 +927,27 @@ func writeType(t *types.Type) *obj.LSym { if t.IsPtr() && t.Sym() == nil && t.Elem().Sym() != nil { tbase = t.Elem() } + if tbase.Kind() == types.TFORW { + base.Fatalf("unresolved defined type: %v", tbase) + } + dupok := 0 - if tbase.Sym() == nil { + if tbase.Sym() == nil { // TODO(mdempsky): Probably need DUPOK for instantiated types too. dupok = obj.DUPOK } - if base.Ctxt.Pkgpath != "runtime" || (tbase != types.Types[tbase.Kind()] && tbase != types.ByteType && tbase != types.RuneType && tbase != types.ErrorType) { // int, float, etc - // Named types from other files are defined only by those files. - // However, as an exception, we can write out instantiated types - // in the local package, even if they may be marked as part of - // another package (the package of their base generic type). - if tbase.Sym() != nil && tbase.Sym().Pkg != types.LocalPkg && - !tbase.IsFullyInstantiated() { - if i := typecheck.BaseTypeIndex(t); i >= 0 { - lsym.Pkg = tbase.Sym().Pkg.Prefix - lsym.SymIdx = int32(i) - lsym.Set(obj.AttrIndexed, true) - } - return lsym - } - // TODO(mdempsky): Investigate whether this can happen. - if tbase.Kind() == types.TFORW { - return lsym + if !NeedEmit(tbase) { + if i := typecheck.BaseTypeIndex(t); i >= 0 { + lsym.Pkg = tbase.Sym().Pkg.Prefix + lsym.SymIdx = int32(i) + lsym.Set(obj.AttrIndexed, true) } + + // TODO(mdempsky): Investigate whether this still happens. + // If we know we don't need to emit code for a type, + // we should have a link-symbol index for it. + // See also TODO in NeedEmit. + return lsym } ot := 0 @@ -1678,6 +1676,44 @@ func CollectPTabs() { } } +// NeedEmit reports whether typ is a type that we need to emit code +// for (e.g., runtime type descriptors, method wrappers). +func NeedEmit(typ *types.Type) bool { + // TODO(mdempsky): Export data should keep track of which anonymous + // and instantiated types were emitted, so at least downstream + // packages can skip re-emitting them. + // + // Perhaps we can just generalize the linker-symbol indexing to + // track the index of arbitrary types, not just defined types, and + // use its presence to detect this. The same idea would work for + // instantiated generic functions too. + + switch sym := typ.Sym(); { + case sym == nil: + // Anonymous type; possibly never seen before or ever again. + // Need to emit to be safe (however, see TODO above). + return true + + case sym.Pkg == types.LocalPkg: + // Local defined type; our responsibility. + return true + + case base.Ctxt.Pkgpath == "runtime" && (sym.Pkg == types.BuiltinPkg || sym.Pkg == ir.Pkgs.Unsafe): + // Package runtime is responsible for including code for builtin + // types (predeclared and package unsafe). + return true + + case typ.IsFullyInstantiated(): + // Instantiated type; possibly instantiated with unique type arguments. + // Need to emit to be safe (however, see TODO above). + return true + + default: + // Should have been emitted by an imported package. + return false + } +} + // Generate a wrapper function to convert from // a receiver of type T to a receiver of type U. // That is, @@ -1739,24 +1775,7 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy return lsym } - // imported reports whether typ is a defined type that was declared - // in an imported package, and therefore must have been compiled in - // that package. - importedType := func(typ *types.Type) bool { - return typ.Sym() != nil && typ.Sym().Pkg != types.LocalPkg && - - // Exception: need wrapper for error.Error (#29304). - // TODO(mdempsky): Put this in package runtime, like we do for - // the type descriptors for predeclared types. - typ != types.ErrorType && - - // Exception: parameterized types may have been instantiated - // with new type arguments, so we don't assume they've been - // compiled before. - !typ.IsFullyInstantiated() - } - - if importedType(rcvr) || rcvr.IsPtr() && importedType(rcvr.Elem()) { + if !NeedEmit(rcvr) || rcvr.IsPtr() && !NeedEmit(rcvr.Elem()) { return lsym } -- GitLab From f4198f85d505c21eee3f2686466e72daa7413232 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 23 Jun 2021 21:33:24 -0700 Subject: [PATCH 0360/2500] [dev.typeparams] cmd/compile: generate wrappers within unified IR This CL extends unified IR to handle creating wrapper methods. There's relatively little about this code that's actually specific to unified IR, but rewriting this logic allows a few benefits: 1. It decouples unified IR from reflectdata.methodWrapper, so the latter code can evolve freely for -G=3's needs. This will also allow the new code to evolve to unified IR's wrapper needs, which I anticipate will operate slightly differently. 2. It provided an opportunity to revisit a lot of the code and simplify/update it to current style. E.g., in the process, I discovered #46903, which unified IR now gets correctly. (I have not yet attempted to fix reflectdata.methodWrapper.) 3. It gives a convenient way for unified IR to ensure all of the wrapper methods it needs are generated correctly. For now, the wrapper generation is specific to non-quirks mode. Change-Id: I5798de6b141f29e8eb6a5c563e7049627ff2868a Reviewed-on: https://go-review.googlesource.com/c/go/+/330569 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/gc/main.go | 2 +- src/cmd/compile/internal/noder/reader.go | 190 +++++++++++++++++- src/cmd/compile/internal/noder/unified.go | 7 + .../compile/internal/reflectdata/reflect.go | 10 +- test/fixedbugs/issue46903.go | 32 +++ test/typeparam/issue44688.go | 2 - 6 files changed, 234 insertions(+), 9 deletions(-) create mode 100644 test/fixedbugs/issue46903.go diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index c0346c0206..c94f19fd47 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -186,6 +186,7 @@ func Main(archInit func(*ssagen.ArchInfo)) { base.AutogeneratedPos = makePos(src.NewFileBase("", ""), 1, 0) typecheck.InitUniverse() + typecheck.InitRuntime() // Parse and typecheck input. noder.LoadPackage(flag.Args()) @@ -194,7 +195,6 @@ func Main(archInit func(*ssagen.ArchInfo)) { // Prepare for backend processing. This must happen before pkginit, // because it generates itabs for initializing global variables. - typecheck.InitRuntime() ssagen.InitConfig() // Build init task. diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index d2fe575ffd..3a496816cc 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -16,6 +16,7 @@ import ( "cmd/compile/internal/deadcode" "cmd/compile/internal/dwarfgen" "cmd/compile/internal/ir" + "cmd/compile/internal/reflectdata" "cmd/compile/internal/typecheck" "cmd/compile/internal/types" "cmd/internal/obj" @@ -419,7 +420,7 @@ func (r *reader) interfaceType() *types.Type { if len(fields) == 0 { return types.Types[types.TINTER] // empty interface } - return types.NewInterface(tpkg, fields) + return r.needWrapper(types.NewInterface(tpkg, fields)) } func (r *reader) structType() *types.Type { @@ -440,7 +441,7 @@ func (r *reader) structType() *types.Type { } fields[i] = f } - return types.NewStruct(tpkg, fields) + return r.needWrapper(types.NewStruct(tpkg, fields)) } func (r *reader) signature(tpkg *types.Pkg, recv *types.Field) *types.Type { @@ -597,6 +598,10 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node typ.Methods().Set(methods) } + if !typ.IsPtr() { + r.needWrapper(typ) + } + return name case objVar: @@ -2015,3 +2020,184 @@ func usedLocals(body []ir.Node) ir.NameSet { }) return used } + +// @@@ Method wrappers + +// needWrapperTypes lists types for which we may need to generate +// method wrappers. +var needWrapperTypes []*types.Type + +func (r *reader) needWrapper(typ *types.Type) *types.Type { + // TODO(mdempsky): Be more judicious about generating wrappers. + // For now, generating all possible wrappers is simple and correct, + // but potentially wastes a lot of time/space. + + if typ.IsPtr() { + base.Fatalf("bad pointer type: %v", typ) + } + + needWrapperTypes = append(needWrapperTypes, typ) + return typ +} + +func (r *reader) wrapTypes(target *ir.Package) { + // always generate a wrapper for error.Error (#29304) + r.needWrapper(types.ErrorType) + + seen := make(map[string]*types.Type) + for _, typ := range needWrapperTypes { + if typ.Sym() == nil { + key := typ.ShortString() + if prev := seen[key]; prev != nil { + if !types.Identical(typ, prev) { + base.Fatalf("collision: types %v and %v have short string %q", typ, prev, key) + } + continue + } + seen[key] = typ + } + + r.wrapType(typ, target) + } + + needWrapperTypes = nil +} + +func (r *reader) wrapType(typ *types.Type, target *ir.Package) { + if !typ.IsInterface() { + typecheck.CalcMethods(typ) + } + for _, meth := range typ.AllMethods().Slice() { + if meth.Sym.IsBlank() || !meth.IsMethod() { + base.FatalfAt(meth.Pos, "invalid method: %v", meth) + } + + r.methodWrapper(0, typ, meth, target) + + // For non-interface types, we also want *T wrappers. + if !typ.IsInterface() { + r.methodWrapper(1, typ, meth, target) + + // For not-in-heap types, *T is a scalar, not pointer shaped, + // so the interface wrappers use **T. + if typ.NotInHeap() { + r.methodWrapper(2, typ, meth, target) + } + } + } +} + +func (r *reader) methodWrapper(derefs int, tbase *types.Type, method *types.Field, target *ir.Package) { + wrapper := tbase + for i := 0; i < derefs; i++ { + wrapper = types.NewPtr(wrapper) + } + + sym := ir.MethodSym(wrapper, method.Sym) + assert(!sym.Siggen()) + sym.SetSiggen(true) + + wrappee := method.Type.Recv().Type + if types.Identical(wrapper, wrappee) || + !types.IsMethodApplicable(wrapper, method) || + !reflectdata.NeedEmit(tbase) { + return + } + + // TODO(mdempsky): Use method.Pos instead? + pos := base.AutogeneratedPos + + fn := ir.NewFunc(pos) + fn.SetDupok(true) // TODO(mdempsky): Leave unset for local, non-generic wrappers? + fn.SetWrapper(true) // TODO(mdempsky): Leave unset for tail calls? + + fn.Nname = ir.NewNameAt(pos, sym) + ir.MarkFunc(fn.Nname) + fn.Nname.Func = fn + fn.Nname.Defn = fn + + sig := newWrapperType(wrapper, method.Type) + r.setType(fn.Nname, sig) + + // TODO(mdempsky): De-duplicate with similar logic in funcargs. + defParams := func(class ir.Class, params ...*types.Field) { + for _, param := range params { + name := ir.NewNameAt(param.Pos, param.Sym) + name.Class = class + r.setType(name, param.Type) + + name.Curfn = fn + fn.Dcl = append(fn.Dcl, name) + + param.Nname = name + } + } + + defParams(ir.PPARAM, sig.Recv()) + defParams(ir.PPARAM, sig.Params().FieldSlice()...) + defParams(ir.PPARAMOUT, sig.Results().FieldSlice()...) + + var recv ir.Node = sig.Recv().Nname.(*ir.Name) + + // For simple *T wrappers around T methods, panicwrap produces a + // nicer panic message. + if wrapper.IsPtr() && types.Identical(wrapper.Elem(), wrappee) { + cond := ir.NewBinaryExpr(pos, ir.OEQ, recv, types.BuiltinPkg.Lookup("nil").Def.(ir.Node)) + then := []ir.Node{ir.NewCallExpr(pos, ir.OCALL, typecheck.LookupRuntime("panicwrap"), nil)} + fn.Body.Append(ir.NewIfStmt(pos, cond, then, nil)) + } + + // Add implicit derefs, as necessary. typecheck will add one deref, + // but not-in-heap types will need another for their **T wrappers. + for i := 0; i < derefs; i++ { + recv = Implicit(ir.NewStarExpr(pos, recv)) + } + + args := make([]ir.Node, sig.NumParams()) + for i, param := range sig.Params().FieldSlice() { + args[i] = param.Nname.(*ir.Name) + } + + fn.Body.Append(newTailCall(pos, method, recv, args)) + + target.Decls = append(target.Decls, fn) +} + +// newWrapperType returns a copy of the given signature type, but with +// the receiver parameter type substituted with wrapper. +func newWrapperType(wrapper, sig *types.Type) *types.Type { + clone := func(params []*types.Field) []*types.Field { + res := make([]*types.Field, len(params)) + for i, param := range params { + sym := param.Sym + if sym == nil || sym.Name == "_" { + sym = typecheck.LookupNum(".anon", i) + } + res[i] = types.NewField(param.Pos, sym, param.Type) + res[i].SetIsDDD(param.IsDDD()) + } + return res + } + + recv := types.NewField(sig.Recv().Pos, typecheck.Lookup(".this"), wrapper) + params := clone(sig.Params().FieldSlice()) + results := clone(sig.Results().FieldSlice()) + + return types.NewSignature(types.NoPkg, recv, nil, params, results) +} + +func newTailCall(pos src.XPos, method *types.Field, recv ir.Node, args []ir.Node) ir.Node { + // TODO(mdempsky): Support creating OTAILCALL, when possible. See reflectdata.methodWrapper. + // Not urgent though, because tail calls are currently incompatible with regabi anyway. + + call := ir.NewCallExpr(pos, ir.OCALL, ir.NewSelectorExpr(pos, ir.OXDOT, recv, method.Sym), args) + call.IsDDD = method.Type.IsVariadic() + + if method.Type.NumResults() == 0 { + return call + } + + ret := ir.NewReturnStmt(pos, nil) + ret.Results = []ir.Node{call} + return ret +} diff --git a/src/cmd/compile/internal/noder/unified.go b/src/cmd/compile/internal/noder/unified.go index 7a1bb88537..292fd13c67 100644 --- a/src/cmd/compile/internal/noder/unified.go +++ b/src/cmd/compile/internal/noder/unified.go @@ -74,6 +74,8 @@ func unified(noders []*noder) { if !quirksMode() { writeNewExportFunc = writeNewExport + } else if base.Flag.G != 0 { + base.Errorf("cannot use -G and -d=quirksmode together") } newReadImportFunc = func(data string, pkg1 *types.Pkg, check *types2.Checker, packages map[string]*types2.Package) (pkg2 *types2.Package, err error) { @@ -126,6 +128,11 @@ func unified(noders []*noder) { } todoBodies = nil + if !quirksMode() { + // TODO(mdempsky): Investigate generating wrappers in quirks mode too. + r.wrapTypes(target) + } + // Don't use range--typecheck can add closures to Target.Decls. for i := 0; i < len(target.Decls); i++ { target.Decls[i] = typecheck.Stmt(target.Decls[i]) diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index ba4bbc7631..8421e36b3d 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -1760,10 +1760,6 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy // TODO: check that we do the right thing when method is an interface method. generic = true } - if base.Debug.Unified != 0 { - // TODO(mdempsky): Support dictionaries for unified IR. - generic = false - } newnam := ir.MethodSym(rcvr, method.Sym) lsym := newnam.Linksym() if newnam.Siggen() { @@ -1771,6 +1767,12 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy } newnam.SetSiggen(true) + // Except in quirks mode, unified IR creates its own wrappers. + // Complain loudly if it missed any. + if base.Debug.Unified != 0 && base.Debug.UnifiedQuirks == 0 { + base.FatalfAt(method.Pos, "missing wrapper for %+v (%+v, %v) / %+v / %+v", rcvr, orig, types.IsDirectIface(orig), method.Sym, newnam) + } + if !generic && types.Identical(rcvr, method.Type.Recv().Type) { return lsym } diff --git a/test/fixedbugs/issue46903.go b/test/fixedbugs/issue46903.go new file mode 100644 index 0000000000..3237a583d5 --- /dev/null +++ b/test/fixedbugs/issue46903.go @@ -0,0 +1,32 @@ +// run +//go:build goexperiment.unified +// +build goexperiment.unified + +// TODO(mdempsky): Enable test unconditionally. This test should pass +// for non-unified mode too. + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +//go:notinheap +type A struct{ B } +type B struct{ x byte } +type I interface{ M() *B } + +func (p *B) M() *B { return p } + +var ( + a A + i I = &a +) + +func main() { + got, want := i.M(), &a.B + if got != want { + println(got, "!=", want) + panic("FAIL") + } +} diff --git a/test/typeparam/issue44688.go b/test/typeparam/issue44688.go index d70f94f706..de1140b67c 100644 --- a/test/typeparam/issue44688.go +++ b/test/typeparam/issue44688.go @@ -1,6 +1,4 @@ // run -gcflags=-G=3 -//go:build goexperiment.unified -// +build !goexperiment.unified // Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style -- GitLab From 9fe7c38d3d7cd8a90e33515981dd00e1233563c9 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 25 Jun 2021 01:49:26 -0700 Subject: [PATCH 0361/2500] [dev.typeparams] cmd/compile: fix TestUnifiedCompare We need to start the capture walk from expr.Body, not expr, otherwise in quirks mode we'll set all of the captured variables' positions to expr.Body.Rbrace. Change-Id: Ic93f2773ae3756c2ec88dac17b4e9fb5a0771734 Reviewed-on: https://go-review.googlesource.com/c/go/+/330889 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/noder/writer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index cc44a80a42..8765f85362 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -1281,7 +1281,7 @@ func (w *writer) captureVars(expr *syntax.FuncLit) (closureVars []posObj, locals localsIdx: make(map[types2.Object]int), } - syntax.Walk(expr, &v) + syntax.Walk(expr.Body, &v) return v.closureVars, v.localsIdx } -- GitLab From 1b60284c0a375de2349540771a3bc1a719ddf52e Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 25 Jun 2021 01:54:50 -0700 Subject: [PATCH 0362/2500] [dev.typeparams] cmd/compile: simplify variable capturing in unified IR While initially building out unified IR, I didn't have any indexing scheme. Everything was written out in order. Consequently, if I wanted to write A before B, I had to compute A before B. One particular example of this is handling closure variables: the reader needs the list of closure variables before it can start reading the function body, so I had to write them out first, and so I had to compute them first in a separate, dedicated pass. However, that constraint went away a while ago. For example, it's now possible to replace the two-pass closure variable capture with a single pass. We just write out the function body earlier, but then wait to write out its index. I anticipate this approach will make it easier to implement dictionaries: rather than needing a separate pass to correctly recognize and handle all of the generics cases, we can just hook into the existing logic. Change-Id: Iab1e07f9202cd5d2b6864eef10116960456214df Reviewed-on: https://go-review.googlesource.com/c/go/+/330851 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/noder/linker.go | 2 - src/cmd/compile/internal/noder/reader.go | 54 +++--- src/cmd/compile/internal/noder/writer.go | 223 ++++++----------------- 3 files changed, 80 insertions(+), 199 deletions(-) diff --git a/src/cmd/compile/internal/noder/linker.go b/src/cmd/compile/internal/noder/linker.go index 7291138160..23e9446759 100644 --- a/src/cmd/compile/internal/noder/linker.go +++ b/src/cmd/compile/internal/noder/linker.go @@ -209,8 +209,6 @@ func (l *linker) relocFuncExt(w *encoder, name *ir.Name) { pri, ok := bodyReader[name.Func] assert(ok) - w.sync(syncAddBody) - w.sync(syncImplicitTypes) w.reloc(relocBody, l.relocIdx(pri.pr, relocBody, pri.idx)) } diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 3a496816cc..0423fcce98 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -105,8 +105,9 @@ type reader struct { // separately so that it doesn't take up space in every reader // instance. - curfn *ir.Func - locals []*ir.Name + curfn *ir.Func + locals []*ir.Name + closureVars []*ir.Name funarghack bool @@ -775,10 +776,10 @@ func (r *reader) funcExt(name *ir.Name) { Cost: int32(r.len()), CanDelayResults: r.bool(), } - r.addBody(name.Func) + r.addBody(name.Func, r.explicits) } } else { - r.addBody(name.Func) + r.addBody(name.Func, r.explicits) } r.sync(syncEOF) } @@ -840,25 +841,7 @@ var bodyReader = map[*ir.Func]pkgReaderIndex{} // constructed. var todoBodies []*ir.Func -// Keep in sync with writer.implicitTypes -// Also see comment there for why r.implicits and r.explicits should -// never both be non-empty. -func (r *reader) implicitTypes() []*types.Type { - r.sync(syncImplicitTypes) - - implicits := r.implicits - if len(implicits) == 0 { - implicits = r.explicits - } else { - assert(len(r.explicits) == 0) - } - return implicits -} - -func (r *reader) addBody(fn *ir.Func) { - r.sync(syncAddBody) - - implicits := r.implicitTypes() +func (r *reader) addBody(fn *ir.Func, implicits []*types.Type) { pri := pkgReaderIndex{r.p, r.reloc(relocBody), implicits} bodyReader[fn] = pri @@ -877,7 +860,7 @@ func (pri pkgReaderIndex) funcBody(fn *ir.Func) { func (r *reader) funcBody(fn *ir.Func) { r.curfn = fn - r.locals = fn.ClosureVars + r.closureVars = fn.ClosureVars // TODO(mdempsky): Get rid of uses of typecheck.NodAddrAt so we // don't have to set ir.CurFunc. @@ -1004,7 +987,10 @@ func (r *reader) addLocal(name *ir.Name, ctxt ir.Class) { func (r *reader) useLocal() *ir.Name { r.sync(syncUseObjLocal) - return r.locals[r.len()] + if r.bool() { + return r.locals[r.len()] + } + return r.closureVars[r.len()] } func (r *reader) openScope() { @@ -1088,8 +1074,11 @@ func (r *reader) stmt1(tag codeStmt, out *ir.Nodes) ir.Node { case stmtAssign: pos := r.pos() - names, lhs := r.assignList() + + // TODO(mdempsky): After quirks mode is gone, swap these + // statements so we visit LHS before RHS again. rhs := r.exprList() + names, lhs := r.assignList() if len(rhs) == 0 { for _, name := range names { @@ -1225,8 +1214,12 @@ func (r *reader) forStmt(label *types.Sym) ir.Node { if r.bool() { pos := r.pos() - names, lhs := r.assignList() + + // TODO(mdempsky): After quirks mode is gone, swap these + // statements so we read LHS before X again. x := r.expr() + names, lhs := r.assignList() + body := r.blockStmt() r.closeAnotherScope() @@ -1572,7 +1565,7 @@ func (r *reader) funcLit() ir.Node { r.setType(cv, outer.Type()) } - r.addBody(fn) + r.addBody(fn, r.implicits) return fn.OClosure } @@ -1777,8 +1770,9 @@ func InlineCall(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExp r.inlTreeIndex = inlIndex r.inlPosBases = make(map[*src.PosBase]*src.PosBase) - for _, cv := range r.inlFunc.ClosureVars { - r.locals = append(r.locals, cv.Outer) + r.closureVars = make([]*ir.Name, len(r.inlFunc.ClosureVars)) + for i, cv := range r.inlFunc.ClosureVars { + r.closureVars[i] = cv.Outer } r.funcargs(fn) diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 8765f85362..04969100f0 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -97,7 +97,10 @@ type writer struct { explicitIdx map[*types2.TypeParam]int // variables declared within this function - localsIdx map[types2.Object]int + localsIdx map[*types2.Var]int + + closureVars []posObj + closureVarsIdx map[*types2.Var]int } func (pw *pkgWriter) newWriter(k reloc, marker syncMarker) *writer { @@ -626,11 +629,15 @@ func (w *writer) funcExt(obj *types2.Func) { } } + sig, block := obj.Type().(*types2.Signature), decl.Body + body, closureVars := w.p.bodyIdx(w.p.curpkg, sig, block, w.explicitIdx) + assert(len(closureVars) == 0) + w.sync(syncFuncExt) w.pragmaFlag(pragma) w.linkname(obj) w.bool(false) // stub extension - w.addBody(obj.Type().(*types2.Signature), decl.Body, make(map[types2.Object]int)) + w.reloc(relocBody, body) w.sync(syncEOF) } @@ -665,41 +672,9 @@ func (w *writer) pragmaFlag(p ir.PragmaFlag) { // @@@ Function bodies -func (w *writer) implicitTypes() map[*types2.TypeParam]int { - w.sync(syncImplicitTypes) - - // TODO(mdempsky): Theoretically, I think at this point we want to - // extend the implicit type parameters list with any new explicit - // type parameters. - // - // However, I believe that's moot: declared functions and methods - // have explicit type parameters, but are always declared at package - // scope (which has no implicit type parameters); and function - // literals can appear within a type-parameterized function (i.e., - // implicit type parameters), but cannot have explicit type - // parameters of their own. - // - // So I think it's safe to just use whichever is non-empty. - implicitIdx := w.implicitIdx - if len(implicitIdx) == 0 { - implicitIdx = w.explicitIdx - } else { - assert(len(w.explicitIdx) == 0) - } - return implicitIdx -} - -func (w *writer) addBody(sig *types2.Signature, block *syntax.BlockStmt, localsIdx map[types2.Object]int) { - w.sync(syncAddBody) - - implicits := w.implicitTypes() - w.reloc(relocBody, w.p.bodyIdx(w.p.curpkg, sig, block, implicits, localsIdx)) -} - -func (pw *pkgWriter) bodyIdx(pkg *types2.Package, sig *types2.Signature, block *syntax.BlockStmt, implicitIdx map[*types2.TypeParam]int, localsIdx map[types2.Object]int) int { +func (pw *pkgWriter) bodyIdx(pkg *types2.Package, sig *types2.Signature, block *syntax.BlockStmt, implicitIdx map[*types2.TypeParam]int) (idx int, closureVars []posObj) { w := pw.newWriter(relocBody, syncFuncBody) w.implicitIdx = implicitIdx - w.localsIdx = localsIdx w.funcargs(sig) if w.bool(block != nil) { @@ -707,7 +682,7 @@ func (pw *pkgWriter) bodyIdx(pkg *types2.Package, sig *types2.Signature, block * w.pos(block.Rbrace) } - return w.flush() + return w.flush(), w.closureVars } func (w *writer) funcargs(sig *types2.Signature) { @@ -730,19 +705,35 @@ func (w *writer) funcarg(param *types2.Var, result bool) { } } -func (w *writer) addLocal(obj types2.Object) { +func (w *writer) addLocal(obj *types2.Var) { w.sync(syncAddLocal) idx := len(w.localsIdx) if enableSync { w.int(idx) } + if w.localsIdx == nil { + w.localsIdx = make(map[*types2.Var]int) + } w.localsIdx[obj] = idx } -func (w *writer) useLocal(obj types2.Object) { +func (w *writer) useLocal(pos syntax.Pos, obj *types2.Var) { w.sync(syncUseObjLocal) - idx, ok := w.localsIdx[obj] - assert(ok) + + if idx, ok := w.localsIdx[obj]; w.bool(ok) { + w.len(idx) + return + } + + idx, ok := w.closureVarsIdx[obj] + if !ok { + if w.closureVarsIdx == nil { + w.closureVarsIdx = make(map[*types2.Var]int) + } + idx = len(w.closureVars) + w.closureVars = append(w.closureVars, posObj{pos, obj}) + w.closureVarsIdx[obj] = idx + } w.len(idx) } @@ -806,8 +797,8 @@ func (w *writer) stmt1(stmt syntax.Stmt) { default: w.code(stmtAssign) w.pos(stmt) - w.assignList(stmt.Lhs) w.exprList(stmt.Rhs) + w.assignList(stmt.Lhs) } case *syntax.BlockStmt: @@ -877,6 +868,8 @@ func (w *writer) assignList(expr syntax.Expr) { for _, expr := range exprs { if name, ok := expr.(*syntax.Name); ok && name.Value != "_" { if obj, ok := w.p.info.Defs[name]; ok { + obj := obj.(*types2.Var) + w.bool(true) w.pos(obj) w.localIdent(obj) @@ -923,16 +916,16 @@ func (w *writer) declStmt(decl syntax.Decl) { for i, name := range decl.NameList { w.code(stmtAssign) w.pos(decl) - w.assignList(name) w.exprList(values[i]) + w.assignList(name) } break } w.code(stmtAssign) w.pos(decl) - w.assignList(namesAsExpr(decl.NameList)) w.exprList(decl.Values) + w.assignList(namesAsExpr(decl.NameList)) } } @@ -949,8 +942,8 @@ func (w *writer) forStmt(stmt *syntax.ForStmt) { if rang, ok := stmt.Init.(*syntax.RangeClause); w.bool(ok) { w.pos(rang) - w.assignList(rang.Lhs) w.expr(rang.X) + w.assignList(rang.Lhs) } else { w.pos(stmt) w.stmt(stmt.Init) @@ -1092,15 +1085,17 @@ func (w *writer) expr(expr syntax.Expr) { } if obj != nil { - if _, ok := w.localsIdx[obj]; ok { - assert(len(targs) == 0) - w.code(exprLocal) - w.useLocal(obj) + if isGlobal(obj) { + w.code(exprName) + w.obj(obj, targs) return } - w.code(exprName) - w.obj(obj, targs) + obj := obj.(*types2.Var) + assert(len(targs) == 0) + + w.code(exprLocal) + w.useLocal(expr.Pos(), obj) return } @@ -1248,130 +1243,24 @@ func (w *writer) funcLit(expr *syntax.FuncLit) { w.pos(expr.Type) // for QuirksMode w.signature(sig) - closureVars, localsIdx := w.captureVars(expr) + block := expr.Body + body, closureVars := w.p.bodyIdx(w.p.curpkg, sig, block, w.implicitIdx) + w.len(len(closureVars)) - for _, closureVar := range closureVars { - w.pos(closureVar.pos) - w.useLocal(closureVar.obj) + for _, cv := range closureVars { + w.pos(cv.pos) + if quirksMode() { + cv.pos = expr.Body.Rbrace + } + w.useLocal(cv.pos, cv.obj) } - w.addBody(sig, expr.Body, localsIdx) + w.reloc(relocBody, body) } type posObj struct { pos syntax.Pos - obj types2.Object -} - -// captureVars returns the free variables used by the given function -// literal. The closureVars result is the list of free variables -// captured by expr, and localsIdx is a map from free variable to -// index. See varCaptor's identically named fields for more details. -func (w *writer) captureVars(expr *syntax.FuncLit) (closureVars []posObj, localsIdx map[types2.Object]int) { - scope, ok := w.p.info.Scopes[expr.Type] - assert(ok) - - // TODO(mdempsky): This code needs to be cleaned up (e.g., to avoid - // traversing nested function literals multiple times). This will be - // easier after we drop quirks mode. - - v := varCaptor{ - w: w, - scope: scope, - localsIdx: make(map[types2.Object]int), - } - - syntax.Walk(expr.Body, &v) - - return v.closureVars, v.localsIdx -} - -// varCaptor implements syntax.Visitor for enumerating free variables -// used by a function literal. -type varCaptor struct { - w *writer - scope *types2.Scope - - // closureVars lists free variables along with the position where - // they first appeared, in order of appearance. - closureVars []posObj - - // localsIdx is a map from free variables to their index within - // closureVars. - localsIdx map[types2.Object]int -} - -func (v *varCaptor) capture(n *syntax.Name) { - obj, ok := v.w.p.info.Uses[n].(*types2.Var) - if !ok || obj.IsField() { - return // not a variable - } - - if obj.Parent() == obj.Pkg().Scope() { - return // global variable - } - - if _, ok := v.localsIdx[obj]; ok { - return // already captured - } - - for parent := obj.Parent(); parent != obj.Pkg().Scope(); parent = parent.Parent() { - if parent == v.scope { - return // object declared within our scope - } - } - - idx := len(v.closureVars) - v.closureVars = append(v.closureVars, posObj{n.Pos(), obj}) - v.localsIdx[obj] = idx -} - -func (v *varCaptor) Visit(n syntax.Node) syntax.Visitor { - // Constant expressions don't count towards capturing. - if n, ok := n.(syntax.Expr); ok { - if tv, ok := v.w.p.info.Types[n]; ok && tv.Value != nil { - return nil - } - } - - if n, ok := n.(*syntax.Name); ok { - v.capture(n) - } - - if quirksMode() { - switch n := n.(type) { - case *syntax.FuncLit: - // Quirk: typecheck uses the rbrace position position of the - // function literal as the position of the intermediary capture. - end := len(v.closureVars) - syntax.Walk(n.Type, v) // unnecessary to walk, but consistent with non-quirks mode - syntax.Walk(n.Body, v) - for i := end; i < len(v.closureVars); i++ { - v.closureVars[i].pos = n.Body.Rbrace - } - return nil - - case *syntax.AssignStmt: - // Quirk: typecheck visits (and thus captures) the RHS of - // assignment statements (but not op= statements) before the LHS. - if n.Op == 0 || n.Op == syntax.Def { - syntax.Walk(n.Rhs, v) - syntax.Walk(n.Lhs, v) - return nil - } - - case *syntax.RangeClause: - // Quirk: Similarly, typecheck visits the expression to be - // iterated over before the iteration variables. - syntax.Walk(n.X, v) - if n.Lhs != nil { - syntax.Walk(n.Lhs, v) - } - return nil - } - } - - return v + obj *types2.Var } func (w *writer) exprList(expr syntax.Expr) { -- GitLab From 942edc750292060450fda38835c452f6125447c3 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 25 Jun 2021 10:04:51 -0700 Subject: [PATCH 0363/2500] [dev.typeparams] cmd/compile: rename types.Type.{Short,Long}String to {Link,Name}String The original names "ShortString" and "LongString" refer back to the fmt verbs used to request their formatting styles. However, I always get confused working with them, in particular because (1) the "ShortString" description, which uses package-path qualification, is actually generally longer than the "LongString" description, which uses package-name qualification; and (2) the documentation mentions how they're often used, but doesn't actually describe why they're safe for those purposes. This CL renames them to "LinkString" and "NameString", respectively, based on their primary use cases. It also attempts to more completely describe the strings they return and how they can be used correctly. Change-Id: I9158ae3eafa8ac53da31a78c7a6d929dc0199afe Reviewed-on: https://go-review.googlesource.com/c/go/+/330910 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/noder/reader.go | 4 +- .../compile/internal/reflectdata/reflect.go | 8 ++-- src/cmd/compile/internal/typecheck/stmt.go | 2 +- src/cmd/compile/internal/types/fmt.go | 38 ++++++++++++++----- src/cmd/compile/internal/types/type.go | 2 +- src/cmd/compile/internal/walk/order.go | 4 +- 6 files changed, 39 insertions(+), 19 deletions(-) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 0423fcce98..459e1d1703 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -631,7 +631,7 @@ func (r *reader) mangle(sym *types.Sym) *types.Sym { } // TODO(mdempsky): We need the linker to replace "" in the symbol // names here. - buf.WriteString(targ.ShortString()) + buf.WriteString(targ.LinkString()) } } buf.WriteByte(']') @@ -2041,7 +2041,7 @@ func (r *reader) wrapTypes(target *ir.Package) { seen := make(map[string]*types.Type) for _, typ := range needWrapperTypes { if typ.Sym() == nil { - key := typ.ShortString() + key := typ.LinkString() if prev := seen[key]; prev != nil { if !types.Identical(typ, prev) { base.Fatalf("collision: types %v and %v have short string %q", typ, prev, key) diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 8421e36b3d..316c7eb293 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -717,7 +717,7 @@ func dcommontype(lsym *obj.LSym, t *types.Type) int { } exported := false - p := t.LongString() + p := t.NameString() // If we're writing out type T, // we are very likely to write out type *T as well. // Use the string "*T"[1:] for "T", so that the two @@ -781,11 +781,11 @@ func dcommontype(lsym *obj.LSym, t *types.Type) int { // TrackSym returns the symbol for tracking use of field/method f, assumed // to be a member of struct/interface type t. func TrackSym(t *types.Type, f *types.Field) *obj.LSym { - return base.PkgLinksym("go.track", t.ShortString()+"."+f.Sym.Name, obj.ABI0) + return base.PkgLinksym("go.track", t.LinkString()+"."+f.Sym.Name, obj.ABI0) } func TypeSymPrefix(prefix string, t *types.Type) *types.Sym { - p := prefix + "." + t.ShortString() + p := prefix + "." + t.LinkString() s := types.TypeSymLookup(p) // This function is for looking up type-related generated functions @@ -833,7 +833,7 @@ func TypePtr(t *types.Type) *ir.AddrExpr { // ITabAddr returns an expression representing a pointer to the itab // for concrete type typ implementing interface iface. func ITabAddr(typ, iface *types.Type) *ir.AddrExpr { - s, existed := ir.Pkgs.Itab.LookupOK(typ.ShortString() + "," + iface.ShortString()) + s, existed := ir.Pkgs.Itab.LookupOK(typ.LinkString() + "," + iface.LinkString()) lsym := s.Linksym() if !existed { diff --git a/src/cmd/compile/internal/typecheck/stmt.go b/src/cmd/compile/internal/typecheck/stmt.go index cd00f1b3d1..313491ba0b 100644 --- a/src/cmd/compile/internal/typecheck/stmt.go +++ b/src/cmd/compile/internal/typecheck/stmt.go @@ -678,7 +678,7 @@ func (s *typeSet) add(pos src.XPos, typ *types.Type) { // LongString does not uniquely identify types, so we need to // disambiguate collisions with types.Identical. // TODO(mdempsky): Add a method that *is* unique. - ls := typ.LongString() + ls := typ.NameString() prevs := s.m[ls] for _, prev := range prevs { if types.Identical(typ, prev.typ) { diff --git a/src/cmd/compile/internal/types/fmt.go b/src/cmd/compile/internal/types/fmt.go index b4d1f6c8bb..095b795d03 100644 --- a/src/cmd/compile/internal/types/fmt.go +++ b/src/cmd/compile/internal/types/fmt.go @@ -242,17 +242,37 @@ func (t *Type) String() string { return tconv(t, 0, fmtGo) } -// ShortString generates a short description of t. -// It is used in autogenerated method names, reflection, -// and itab names. -func (t *Type) ShortString() string { +// LinkString returns an unexpanded string description of t, suitable +// for use in link symbols. "Unexpanded" here means that the +// description uses `"".` to qualify identifiers from the current +// package, and "expansion" refers to the renaming step performed by +// the linker to replace these qualifiers with proper `path/to/pkg.` +// qualifiers. +// +// After expansion, the description corresponds to type identity. That +// is, for any pair of types t1 and t2, Identical(t1, t2) and +// expand(t1.LinkString()) == expand(t2.LinkString()) report the same +// value. +// +// Within a single compilation unit, LinkString always returns the +// same unexpanded description for identical types. Thus it's safe to +// use as a map key to implement a type-identity-keyed map. However, +// make sure all LinkString calls used for this purpose happen within +// the same compile process; the string keys are not stable across +// multiple processes. +func (t *Type) LinkString() string { return tconv(t, 0, fmtTypeID) } -// LongString generates a complete description of t. -// It is useful for reflection, -// or when a unique fingerprint or hash of a type is required. -func (t *Type) LongString() string { +// NameString generates a user-readable, mostly unique string +// description of t. NameString always returns the same description +// for identical types, even across compilation units. +// +// NameString qualifies identifiers by package name, so it has +// collisions when different packages share the same names and +// identifiers. It also does not distinguish function-scope defined +// types from package-scoped defined types or from each other. +func (t *Type) NameString() string { return tconv(t, 0, fmtTypeIDName) } @@ -677,7 +697,7 @@ func FmtConst(v constant.Value, sharp bool) string { // TypeHash computes a hash value for type t to use in type switch statements. func TypeHash(t *Type) uint32 { - p := t.LongString() + p := t.NameString() // Using MD5 is overkill, but reduces accidental collisions. h := md5.Sum([]byte(p)) diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 075009d6a3..7f75000797 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -2129,7 +2129,7 @@ func TypeSymLookup(name string) *Sym { } func TypeSymName(t *Type) string { - name := t.ShortString() + name := t.LinkString() // Use a separate symbol name for Noalg types for #17752. if TypeHasNoAlg(t) { name = "noalg." + name diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go index 62d9b95be9..59701613c3 100644 --- a/src/cmd/compile/internal/walk/order.go +++ b/src/cmd/compile/internal/walk/order.go @@ -78,7 +78,7 @@ func (o *orderState) newTemp(t *types.Type, clear bool) *ir.Name { var v *ir.Name // Note: LongString is close to the type equality we want, // but not exactly. We still need to double-check with types.Identical. - key := t.LongString() + key := t.NameString() a := o.free[key] for i, n := range a { if types.Identical(t, n.Type()) { @@ -370,7 +370,7 @@ func (o *orderState) markTemp() ordermarker { // which must have been returned by markTemp. func (o *orderState) popTemp(mark ordermarker) { for _, n := range o.temp[mark:] { - key := n.Type().LongString() + key := n.Type().NameString() o.free[key] = append(o.free[key], n) } o.temp = o.temp[:mark] -- GitLab From ed647b16d02da4571c22baac23c302f2d888b88b Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 25 Jun 2021 10:15:40 -0700 Subject: [PATCH 0364/2500] [dev.typeparams] cmd/compile: use Type.LinkString for map keys This CL changes typecheck and order to use Type.LinkString for computing map keys instead of Type.NameString. As mentioned in the LinkString docs (added by the previous CL), LinkString reliably maps type identity to string equality as long as the LinkString calls all happen within the same compilation unit (which they do here). This eliminates the need for subsequent types.Identical checks. Change-Id: I32ff591e69d6f23f2dc6ebd5af343618ebe89013 Reviewed-on: https://go-review.googlesource.com/c/go/+/330911 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Matthew Dempsky Reviewed-by: Robert Griesemer --- .../compile/internal/reflectdata/reflect.go | 9 +++++-- src/cmd/compile/internal/typecheck/stmt.go | 25 ++++++------------- src/cmd/compile/internal/walk/order.go | 24 +++++++----------- 3 files changed, 23 insertions(+), 35 deletions(-) diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 316c7eb293..351aaab399 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -1388,7 +1388,7 @@ func WriteBasicTypes() { type typeAndStr struct { t *types.Type - short string + short string // "short" here means NameString regular string } @@ -1401,8 +1401,13 @@ func (a typesByString) Less(i, j int) bool { } // When the only difference between the types is whether // they refer to byte or uint8, such as **byte vs **uint8, - // the types' ShortStrings can be identical. + // the types' NameStrings can be identical. // To preserve deterministic sort ordering, sort these by String(). + // + // TODO(mdempsky): This all seems suspect. Using LinkString would + // avoid naming collisions, and there shouldn't be a reason to care + // about "byte" vs "uint8": they share the same runtime type + // descriptor anyway. if a[i].regular != a[j].regular { return a[i].regular < a[j].regular } diff --git a/src/cmd/compile/internal/typecheck/stmt.go b/src/cmd/compile/internal/typecheck/stmt.go index 313491ba0b..54cf508acc 100644 --- a/src/cmd/compile/internal/typecheck/stmt.go +++ b/src/cmd/compile/internal/typecheck/stmt.go @@ -662,29 +662,18 @@ func tcSwitchType(n *ir.SwitchStmt) { } type typeSet struct { - m map[string][]typeSetEntry -} - -type typeSetEntry struct { - pos src.XPos - typ *types.Type + m map[string]src.XPos } func (s *typeSet) add(pos src.XPos, typ *types.Type) { if s.m == nil { - s.m = make(map[string][]typeSetEntry) + s.m = make(map[string]src.XPos) } - // LongString does not uniquely identify types, so we need to - // disambiguate collisions with types.Identical. - // TODO(mdempsky): Add a method that *is* unique. - ls := typ.NameString() - prevs := s.m[ls] - for _, prev := range prevs { - if types.Identical(typ, prev.typ) { - base.ErrorfAt(pos, "duplicate case %v in type switch\n\tprevious case at %s", typ, base.FmtPos(prev.pos)) - return - } + ls := typ.LinkString() + if prev, ok := s.m[ls]; ok { + base.ErrorfAt(pos, "duplicate case %v in type switch\n\tprevious case at %s", typ, base.FmtPos(prev)) + return } - s.m[ls] = append(prevs, typeSetEntry{pos, typ}) + s.m[ls] = pos } diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go index 59701613c3..9912feba63 100644 --- a/src/cmd/compile/internal/walk/order.go +++ b/src/cmd/compile/internal/walk/order.go @@ -51,7 +51,7 @@ import ( type orderState struct { out []ir.Node // list of generated statements temp []*ir.Name // stack of temporary variables - free map[string][]*ir.Name // free list of unused temporaries, by type.LongString(). + free map[string][]*ir.Name // free list of unused temporaries, by type.LinkString(). edit func(ir.Node) ir.Node // cached closure of o.exprNoLHS } @@ -76,20 +76,14 @@ func (o *orderState) append(stmt ir.Node) { // If clear is true, newTemp emits code to zero the temporary. func (o *orderState) newTemp(t *types.Type, clear bool) *ir.Name { var v *ir.Name - // Note: LongString is close to the type equality we want, - // but not exactly. We still need to double-check with types.Identical. - key := t.NameString() - a := o.free[key] - for i, n := range a { - if types.Identical(t, n.Type()) { - v = a[i] - a[i] = a[len(a)-1] - a = a[:len(a)-1] - o.free[key] = a - break + key := t.LinkString() + if a := o.free[key]; len(a) > 0 { + v = a[len(a)-1] + if !types.Identical(t, v.Type()) { + base.Fatalf("expected %L to have type %v", v, t) } - } - if v == nil { + o.free[key] = a[:len(a)-1] + } else { v = typecheck.Temp(t) } if clear { @@ -370,7 +364,7 @@ func (o *orderState) markTemp() ordermarker { // which must have been returned by markTemp. func (o *orderState) popTemp(mark ordermarker) { for _, n := range o.temp[mark:] { - key := n.Type().NameString() + key := n.Type().LinkString() o.free[key] = append(o.free[key], n) } o.temp = o.temp[:mark] -- GitLab From d417b8cf87bd8e0f8362aa1cc9b7dadd221731c9 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Fri, 25 Jun 2021 14:01:54 +0700 Subject: [PATCH 0365/2500] [dev.typeparams] cmd/compile: clarify comment about checking reflect.Method in usemethod Followup discussion in CL 330670. Change-Id: Icec2d5d5715666a6967e18ac9ab3d802b47569da Reviewed-on: https://go-review.googlesource.com/c/go/+/330830 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/walk/expr.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go index d8bded8075..6928f2ac70 100644 --- a/src/cmd/compile/internal/walk/expr.go +++ b/src/cmd/compile/internal/walk/expr.go @@ -958,9 +958,8 @@ func usemethod(n *ir.CallExpr) { return } - // Note: Don't rely on Field.Type.String() since its formatting depends on multiple factors - // (including global variables such as numImports - was issue #19028). - // Also need to check for reflect package itself (see Issue #38515). + // Check that first result type is "reflect.Method". Note that we have to check sym name and sym package + // separately, as we can't check for exact string "reflect.Method" reliably (e.g., see #19028 and #38515). if s := t.Results().Field(0).Type.Sym(); s != nil && s.Name == "Method" && types.IsReflectPkg(s.Pkg) { ir.CurFunc.SetReflectMethod(true) // The LSym is initialized at this point. We need to set the attribute on the LSym. -- GitLab From 942bcc2d4f4e66b617c225aed1ba4d4d42a08ed2 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sat, 26 Jun 2021 13:57:51 +0700 Subject: [PATCH 0366/2500] [dev.typeparams] cmd/compile: fix wrong AST generation in devirtualization CL 330671 moved rewrite method calls to escape analysis. It accidently made the AST invalid, by removing the OCALLMETH set operation during devirtualization pass. Change-Id: I862ffd7f880de55969d7784d9e7b3c38894f6b68 Reviewed-on: https://go-review.googlesource.com/c/go/+/330832 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/devirtualize/devirtualize.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cmd/compile/internal/devirtualize/devirtualize.go b/src/cmd/compile/internal/devirtualize/devirtualize.go index f52499e07f..60ba208d08 100644 --- a/src/cmd/compile/internal/devirtualize/devirtualize.go +++ b/src/cmd/compile/internal/devirtualize/devirtualize.go @@ -50,6 +50,7 @@ func Call(call *ir.CallExpr) { if base.Flag.LowerM != 0 { base.WarnfAt(call.Pos(), "devirtualizing %v to %v", sel, typ) } + call.SetOp(ir.OCALLMETH) call.X = x case ir.ODOTINTER: // Promoted method from embedded interface-typed field (#42279). -- GitLab From 180c338c6893c2e8b7f4692ed62f92a1ed0cd1e8 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sat, 26 Jun 2021 14:34:56 +0700 Subject: [PATCH 0367/2500] [dev.typeparams] cmd/compile: restore check for OCALLMETH in walkCall Since when walkCall1 still need to handle OCALLMETH. Change-Id: Iadb12a0965169c63f97978c96412012ef4fa02df Reviewed-on: https://go-review.googlesource.com/c/go/+/330833 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/walk/expr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go index 6928f2ac70..86c6d44501 100644 --- a/src/cmd/compile/internal/walk/expr.go +++ b/src/cmd/compile/internal/walk/expr.go @@ -489,7 +489,7 @@ func walkAddString(n *ir.AddStringExpr, init *ir.Nodes) ir.Node { // walkCall walks an OCALLFUNC, OCALLINTER, or OCALLMETH node. func walkCall(n *ir.CallExpr, init *ir.Nodes) ir.Node { - if n.Op() == ir.OCALLINTER || n.X.Op() == ir.OMETHEXPR { + if n.Op() == ir.OCALLINTER || n.Op() == ir.OCALLMETH || n.X.Op() == ir.OMETHEXPR { // We expect both interface call reflect.Type.Method and concrete // call reflect.(*rtype).Method. usemethod(n) -- GitLab From 0cf71f7f92c2623a132ab3257690826643d548af Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Fri, 25 Jun 2021 22:24:29 +0700 Subject: [PATCH 0368/2500] [dev.typeparams] cmd/compile: rewrite method calls during typecheck CL 330671 move rewriting method call to method expression to escape analysis. This CL move the rewriting up further, into typecheck. It helps simplify the code for dowstream passes, as they now only have to deal with OCALLFUNC. There're two notes: - For -G=3, we can't rewrite d.M() where d is an instantiated receiver in transformCall, but let irgen.stencil to rewrite it. - Escape analysis still have to check for rewriting method calls, as the devirtualization pass can still generate OCALLMETH. Does not pass toolstash, since when the export data now contains method expression calls instead of method calls. Change-Id: I77465ef04d50dc4efedddca7eb55b3fc9483db0e Reviewed-on: https://go-review.googlesource.com/c/go/+/330831 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/escape/call.go | 2 +- src/cmd/compile/internal/inline/inl.go | 79 +++++++++------------ src/cmd/compile/internal/noder/reader.go | 3 +- src/cmd/compile/internal/noder/transform.go | 3 + src/cmd/compile/internal/typecheck/func.go | 1 + src/cmd/compile/internal/walk/convert.go | 4 +- src/cmd/compile/internal/walk/expr.go | 11 +-- src/cmd/compile/internal/walk/order.go | 19 +++-- src/cmd/compile/internal/walk/stmt.go | 1 - src/cmd/compile/internal/walk/walk.go | 2 +- 10 files changed, 65 insertions(+), 60 deletions(-) diff --git a/src/cmd/compile/internal/escape/call.go b/src/cmd/compile/internal/escape/call.go index 62727a8ef8..46bfe65aff 100644 --- a/src/cmd/compile/internal/escape/call.go +++ b/src/cmd/compile/internal/escape/call.go @@ -68,7 +68,7 @@ func (e *escape) callCommon(ks []hole, call ir.Node, init *ir.Nodes, wrapper *ir fn = ir.MethodExprName(v) } case ir.OCALLMETH: - fn = ir.MethodExprName(call.X) + base.FatalfAt(call.Pos(), "OCALLMETH missed by typecheck") } fntype := call.X.Type() diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index 0620191bbf..3086d093c0 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -273,6 +273,19 @@ func (v *hairyVisitor) doNode(n ir.Node) bool { } } } + if n.X.Op() == ir.OMETHEXPR { + if meth := ir.MethodExprName(n.X); meth != nil { + fn := meth.Func + if fn != nil && types.IsRuntimePkg(fn.Sym().Pkg) && fn.Sym().Name == "heapBits.nextArena" { + // Special case: explicitly allow + // mid-stack inlining of + // runtime.heapBits.next even though + // it calls slow-path + // runtime.heapBits.nextArena. + break + } + } + } if ir.IsIntrinsicCall(n) { // Treat like any other node. @@ -287,28 +300,8 @@ func (v *hairyVisitor) doNode(n ir.Node) bool { // Call cost for non-leaf inlining. v.budget -= v.extraCallCost - // Call is okay if inlinable and we have the budget for the body. case ir.OCALLMETH: - n := n.(*ir.CallExpr) - t := n.X.Type() - if t == nil { - base.Fatalf("no function type for [%p] %+v\n", n.X, n.X) - } - fn := ir.MethodExprName(n.X).Func - if types.IsRuntimePkg(fn.Sym().Pkg) && fn.Sym().Name == "heapBits.nextArena" { - // Special case: explicitly allow - // mid-stack inlining of - // runtime.heapBits.next even though - // it calls slow-path - // runtime.heapBits.nextArena. - break - } - if fn.Inl != nil { - v.budget -= fn.Inl.Cost - break - } - // Call cost for non-leaf inlining. - v.budget -= v.extraCallCost + base.FatalfAt(n.Pos(), "OCALLMETH missed by typecheck") // Things that are too hairy, irrespective of the budget case ir.OCALL, ir.OCALLINTER: @@ -575,7 +568,9 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool, edit func(ir.No case ir.ODEFER, ir.OGO: n := n.(*ir.GoDeferStmt) switch call := n.Call; call.Op() { - case ir.OCALLFUNC, ir.OCALLMETH: + case ir.OCALLMETH: + base.FatalfAt(call.Pos(), "OCALLMETH missed by typecheck") + case ir.OCALLFUNC: call := call.(*ir.CallExpr) call.NoInline = true } @@ -585,11 +580,18 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool, edit func(ir.No case ir.OCLOSURE: return n case ir.OCALLMETH: - // Prevent inlining some reflect.Value methods when using checkptr, - // even when package reflect was compiled without it (#35073). + base.FatalfAt(n.Pos(), "OCALLMETH missed by typecheck") + case ir.OCALLFUNC: n := n.(*ir.CallExpr) - if s := ir.MethodExprName(n.X).Sym(); base.Debug.Checkptr != 0 && types.IsReflectPkg(s.Pkg) && (s.Name == "Value.UnsafeAddr" || s.Name == "Value.Pointer") { - return n + if n.X.Op() == ir.OMETHEXPR { + // Prevent inlining some reflect.Value methods when using checkptr, + // even when package reflect was compiled without it (#35073). + if meth := ir.MethodExprName(n.X); meth != nil { + s := meth.Sym() + if base.Debug.Checkptr != 0 && types.IsReflectPkg(s.Pkg) && (s.Name == "Value.UnsafeAddr" || s.Name == "Value.Pointer") { + return n + } + } } } @@ -611,7 +613,9 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool, edit func(ir.No // transmogrify this node itself unless inhibited by the // switch at the top of this function. switch n.Op() { - case ir.OCALLFUNC, ir.OCALLMETH: + case ir.OCALLMETH: + base.FatalfAt(n.Pos(), "OCALLMETH missed by typecheck") + case ir.OCALLFUNC: n := n.(*ir.CallExpr) if n.NoInline { return n @@ -631,19 +635,8 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool, edit func(ir.No if fn := inlCallee(call.X); fn != nil && fn.Inl != nil { n = mkinlcall(call, fn, maxCost, inlMap, edit) } - case ir.OCALLMETH: - call = n.(*ir.CallExpr) - if base.Flag.LowerM > 3 { - fmt.Printf("%v:call to meth %v\n", ir.Line(n), call.X.(*ir.SelectorExpr).Sel) - } - - // typecheck should have resolved ODOTMETH->type, whose nname points to the actual function. - if call.X.Type() == nil { - base.Fatalf("no function type for [%p] %+v\n", call.X, call.X) - } - - n = mkinlcall(call, ir.MethodExprName(call.X).Func, maxCost, inlMap, edit) + base.FatalfAt(n.Pos(), "OCALLMETH missed by typecheck") } base.Pos = lno @@ -723,7 +716,7 @@ var SSADumpInline = func(*ir.Func) {} // instead. var NewInline = func(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExpr { return nil } -// If n is a call node (OCALLFUNC or OCALLMETH), and fn is an ONAME node for a +// If n is a OCALLFUNC node, and fn is an ONAME node for a // function with an inlinable body, return an OINLCALL node that can replace n. // The returned node's Ninit has the parameter assignments, the Nbody is the // inlined function body, and (List, Rlist) contain the (input, output) @@ -906,11 +899,7 @@ func oldInline(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExpr as := ir.NewAssignListStmt(base.Pos, ir.OAS2, nil, nil) as.Def = true if call.Op() == ir.OCALLMETH { - sel := call.X.(*ir.SelectorExpr) - if sel.X == nil { - base.Fatalf("method call without receiver: %+v", call) - } - as.Rhs.Append(sel.X) + base.FatalfAt(call.Pos(), "OCALLMETH missed by typecheck") } as.Rhs.Append(call.Args...) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 459e1d1703..e5ad3f4b8e 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -1807,8 +1807,7 @@ func InlineCall(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExp var args ir.Nodes if call.Op() == ir.OCALLMETH { - assert(call.X.Op() == ir.ODOTMETH) - args.Append(call.X.(*ir.SelectorExpr).X) + base.FatalfAt(call.Pos(), "OCALLMETH missed by typecheck") } args.Append(call.Args...) diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index 946d335f07..30d6e34ae4 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -149,6 +149,9 @@ func transformCall(n *ir.CallExpr) { } typecheckaste(ir.OCALL, n.X, n.IsDDD, t.Params(), n.Args) + if l.Op() == ir.ODOTMETH && len(deref(n.X.Type().Recv().Type).RParams()) == 0 { + typecheck.FixMethodCall(n) + } if t.NumResults() == 1 { n.SetType(l.Type().Results().Field(0).Type) diff --git a/src/cmd/compile/internal/typecheck/func.go b/src/cmd/compile/internal/typecheck/func.go index 00770c87cf..20b991be56 100644 --- a/src/cmd/compile/internal/typecheck/func.go +++ b/src/cmd/compile/internal/typecheck/func.go @@ -516,6 +516,7 @@ func tcCall(n *ir.CallExpr, top int) ir.Node { } typecheckaste(ir.OCALL, n.X, n.IsDDD, t.Params(), n.Args, func() string { return fmt.Sprintf("argument to %v", n.X) }) + FixMethodCall(n) if t.NumResults() == 0 { return n } diff --git a/src/cmd/compile/internal/walk/convert.go b/src/cmd/compile/internal/walk/convert.go index 5297332f6b..e659ee59f1 100644 --- a/src/cmd/compile/internal/walk/convert.go +++ b/src/cmd/compile/internal/walk/convert.go @@ -462,7 +462,9 @@ func walkCheckPtrArithmetic(n *ir.ConvExpr, init *ir.Nodes) ir.Node { // TODO(mdempsky): Make stricter. We only need to exempt // reflect.Value.Pointer and reflect.Value.UnsafeAddr. switch n.X.Op() { - case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER: + case ir.OCALLMETH: + base.FatalfAt(n.X.Pos(), "OCALLMETH missed by typecheck") + case ir.OCALLFUNC, ir.OCALLINTER: return n } diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go index 86c6d44501..f7675c3b7d 100644 --- a/src/cmd/compile/internal/walk/expr.go +++ b/src/cmd/compile/internal/walk/expr.go @@ -167,7 +167,7 @@ func walkExpr1(n ir.Node, init *ir.Nodes) ir.Node { case ir.OCFUNC: return n - case ir.OCALLINTER, ir.OCALLFUNC, ir.OCALLMETH: + case ir.OCALLINTER, ir.OCALLFUNC: n := n.(*ir.CallExpr) return walkCall(n, init) @@ -487,9 +487,12 @@ func walkAddString(n *ir.AddStringExpr, init *ir.Nodes) ir.Node { return r1 } -// walkCall walks an OCALLFUNC, OCALLINTER, or OCALLMETH node. +// walkCall walks an OCALLFUNC or OCALLINTER node. func walkCall(n *ir.CallExpr, init *ir.Nodes) ir.Node { - if n.Op() == ir.OCALLINTER || n.Op() == ir.OCALLMETH || n.X.Op() == ir.OMETHEXPR { + if n.Op() == ir.OCALLMETH { + base.FatalfAt(n.Pos(), "OCALLMETH missed by typecheck") + } + if n.Op() == ir.OCALLINTER || n.X.Op() == ir.OMETHEXPR { // We expect both interface call reflect.Type.Method and concrete // call reflect.(*rtype).Method. usemethod(n) @@ -550,7 +553,7 @@ func walkCall1(n *ir.CallExpr, init *ir.Nodes) { n.SetWalked(true) if n.Op() == ir.OCALLMETH { - typecheck.FixMethodCall(n) + base.FatalfAt(n.Pos(), "OCALLMETH missed by typecheck") } args := n.Args diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go index 9912feba63..16a124d2ff 100644 --- a/src/cmd/compile/internal/walk/order.go +++ b/src/cmd/compile/internal/walk/order.go @@ -506,15 +506,18 @@ func (o *orderState) init(n ir.Node) { } // call orders the call expression n. -// n.Op is OCALLMETH/OCALLFUNC/OCALLINTER or a builtin like OCOPY. +// n.Op is OCALLFUNC/OCALLINTER or a builtin like OCOPY. func (o *orderState) call(nn ir.Node) { if len(nn.Init()) > 0 { // Caller should have already called o.init(nn). base.Fatalf("%v with unexpected ninit", nn.Op()) } + if nn.Op() == ir.OCALLMETH { + base.FatalfAt(nn.Pos(), "OCALLMETH missed by typecheck") + } // Builtin functions. - if nn.Op() != ir.OCALLFUNC && nn.Op() != ir.OCALLMETH && nn.Op() != ir.OCALLINTER { + if nn.Op() != ir.OCALLFUNC && nn.Op() != ir.OCALLINTER { switch n := nn.(type) { default: base.Fatalf("unexpected call: %+v", n) @@ -707,7 +710,7 @@ func (o *orderState) stmt(n ir.Node) { o.out = append(o.out, n) // Special: handle call arguments. - case ir.OCALLFUNC, ir.OCALLINTER, ir.OCALLMETH: + case ir.OCALLFUNC, ir.OCALLINTER: n := n.(*ir.CallExpr) t := o.markTemp() o.call(n) @@ -1147,7 +1150,10 @@ func (o *orderState) expr1(n, lhs ir.Node) ir.Node { case ir.OCONVNOP: n := n.(*ir.ConvExpr) - if n.Type().IsKind(types.TUNSAFEPTR) && n.X.Type().IsKind(types.TUINTPTR) && (n.X.Op() == ir.OCALLFUNC || n.X.Op() == ir.OCALLINTER || n.X.Op() == ir.OCALLMETH) { + if n.X.Op() == ir.OCALLMETH { + base.FatalfAt(n.X.Pos(), "OCALLMETH missed by typecheck") + } + if n.Type().IsKind(types.TUNSAFEPTR) && n.X.Type().IsKind(types.TUINTPTR) && (n.X.Op() == ir.OCALLFUNC || n.X.Op() == ir.OCALLINTER) { call := n.X.(*ir.CallExpr) // When reordering unsafe.Pointer(f()) into a separate // statement, the conversion and function call must stay @@ -1200,9 +1206,12 @@ func (o *orderState) expr1(n, lhs ir.Node) ir.Node { o.out = append(o.out, nif) return r + case ir.OCALLMETH: + base.FatalfAt(n.Pos(), "OCALLMETH missed by typecheck") + panic("unreachable") + case ir.OCALLFUNC, ir.OCALLINTER, - ir.OCALLMETH, ir.OCAP, ir.OCOMPLEX, ir.OCOPY, diff --git a/src/cmd/compile/internal/walk/stmt.go b/src/cmd/compile/internal/walk/stmt.go index 0c216d2e8a..4581bca3df 100644 --- a/src/cmd/compile/internal/walk/stmt.go +++ b/src/cmd/compile/internal/walk/stmt.go @@ -40,7 +40,6 @@ func walkStmt(n ir.Node) ir.Node { ir.OAS2MAPR, ir.OCLOSE, ir.OCOPY, - ir.OCALLMETH, ir.OCALLINTER, ir.OCALL, ir.OCALLFUNC, diff --git a/src/cmd/compile/internal/walk/walk.go b/src/cmd/compile/internal/walk/walk.go index 6e992a91b8..f687127fee 100644 --- a/src/cmd/compile/internal/walk/walk.go +++ b/src/cmd/compile/internal/walk/walk.go @@ -308,7 +308,7 @@ func mayCall(n ir.Node) bool { default: base.FatalfAt(n.Pos(), "mayCall %+v", n) - case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER, + case ir.OCALLFUNC, ir.OCALLINTER, ir.OUNSAFEADD, ir.OUNSAFESLICE: return true -- GitLab From 27e3b797bb6f3bc88b83897ae337aa83904c2a1a Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sat, 26 Jun 2021 15:28:16 +0700 Subject: [PATCH 0369/2500] [dev.typeparams] cmd/compile: remove OCALLMETH Fatals in SSA generation CL 330831 moved rewrite method calls to typecheck pass, then add Fatalf check for mis-used of OCALLMETH in all frontend passes. The check in SSA generation pass is now redundant. Change-Id: If959b774ab3c3aeefabf32333f77b9a93c156ce3 Reviewed-on: https://go-review.googlesource.com/c/go/+/330834 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ssagen/ssa.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 2bf34b0a84..8367751dd5 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -3119,10 +3119,6 @@ func (s *state) expr(n ir.Node) *ssa.Value { n := n.(*ir.CallExpr) return s.callResult(n, callNormal) - case ir.OCALLMETH: - base.Fatalf("OCALLMETH missed by walkCall") - panic("unreachable") - case ir.OGETG: n := n.(*ir.CallExpr) return s.newValue1(ssa.OpGetG, n.Type(), s.mem()) @@ -4860,8 +4856,6 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val // not the point of defer statement. s.maybeNilCheckClosure(closure, k) } - case ir.OCALLMETH: - base.Fatalf("OCALLMETH missed by walkCall") case ir.OCALLINTER: if fn.Op() != ir.ODOTINTER { s.Fatalf("OCALLINTER: n.Left not an ODOTINTER: %v", fn.Op()) @@ -4951,9 +4945,6 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val // Write args. t := n.X.Type() args := n.Args - if n.Op() == ir.OCALLMETH { - base.Fatalf("OCALLMETH missed by walkCall") - } for _, p := range params.InParams() { // includes receiver for interface calls ACArgs = append(ACArgs, p.Type) -- GitLab From 3ea0fcfe15663a7fb62f8570cc5991dc0f7c0260 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sun, 27 Jun 2021 00:51:16 +0700 Subject: [PATCH 0370/2500] [dev.typeparams] cmd/compile: do not skip TestUnifiedCompare in short mode Instead, just testing the runtime package in short mode instead of std. So trybot can help catching any mistake earlier. Change-Id: I5bc859a59afa13a10d436a798258ac154c7d27b2 Reviewed-on: https://go-review.googlesource.com/c/go/+/330836 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/noder/unified_test.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/noder/unified_test.go b/src/cmd/compile/internal/noder/unified_test.go index 4732892f6c..ca91b49fbb 100644 --- a/src/cmd/compile/internal/noder/unified_test.go +++ b/src/cmd/compile/internal/noder/unified_test.go @@ -16,7 +16,7 @@ import ( ) var ( - flagPkgs = flag.String("pkgs", "std", "list of packages to compare") + flagPkgs = flag.String("pkgs", "std", "list of packages to compare (ignored in -short mode)") flagAll = flag.Bool("all", false, "enable testing of all GOOS/GOARCH targets") flagParallel = flag.Bool("parallel", false, "test GOOS/GOARCH targets in parallel") ) @@ -37,10 +37,6 @@ var ( // command's -run flag for subtest matching is recommended for less // powerful machines. func TestUnifiedCompare(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode") - } - targets, err := exec.Command("go", "tool", "dist", "list").Output() if err != nil { t.Fatal(err) @@ -112,11 +108,17 @@ type pkg struct { func loadPackages(t *testing.T, goos, goarch, gcflags string) []pkg { args := []string{"list", "-e", "-export", "-json", "-gcflags=all=" + gcflags, "--"} - args = append(args, strings.Fields(*flagPkgs)...) + if testing.Short() { + t.Log("short testing mode; only testing package runtime") + args = append(args, "runtime") + } else { + args = append(args, strings.Fields(*flagPkgs)...) + } cmd := exec.Command("go", args...) cmd.Env = append(os.Environ(), "GOOS="+goos, "GOARCH="+goarch) cmd.Stderr = os.Stderr + t.Logf("running %v", cmd) stdout, err := cmd.StdoutPipe() if err != nil { t.Fatal(err) -- GitLab From d44ed5d14486728e2f9dfb9f682f37d6fb4024cb Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Sat, 26 Jun 2021 12:44:53 -0700 Subject: [PATCH 0371/2500] [dev.typeparams] cmd/compile: add method value wrappers to unified IR Method value wrappers will need dictionary support too, so bring them under the unified IR umbrella as well. Change-Id: Iec36bb04efdf59843d1b00f55d2c44bc841fa2ef Reviewed-on: https://go-review.googlesource.com/c/go/+/331190 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le Trust: Matthew Dempsky --- src/cmd/compile/internal/noder/reader.go | 141 ++++++++++++++++------- 1 file changed, 99 insertions(+), 42 deletions(-) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index e5ad3f4b8e..66c0e99d11 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -2065,6 +2065,8 @@ func (r *reader) wrapType(typ *types.Type, target *ir.Package) { base.FatalfAt(meth.Pos, "invalid method: %v", meth) } + r.methodValueWrapper(typ, meth, target) + r.methodWrapper(0, typ, meth, target) // For non-interface types, we also want *T wrappers. @@ -2100,21 +2102,81 @@ func (r *reader) methodWrapper(derefs int, tbase *types.Type, method *types.Fiel // TODO(mdempsky): Use method.Pos instead? pos := base.AutogeneratedPos + fn := r.newWrapperFunc(pos, sym, wrapper, method, target) + + var recv ir.Node = fn.Nname.Type().Recv().Nname.(*ir.Name) + + // For simple *T wrappers around T methods, panicwrap produces a + // nicer panic message. + if wrapper.IsPtr() && types.Identical(wrapper.Elem(), wrappee) { + cond := ir.NewBinaryExpr(pos, ir.OEQ, recv, types.BuiltinPkg.Lookup("nil").Def.(ir.Node)) + then := []ir.Node{ir.NewCallExpr(pos, ir.OCALL, typecheck.LookupRuntime("panicwrap"), nil)} + fn.Body.Append(ir.NewIfStmt(pos, cond, then, nil)) + } + + // typecheck will add one implicit deref, if necessary, + // but not-in-heap types require more for their **T wrappers. + for i := 1; i < derefs; i++ { + recv = Implicit(ir.NewStarExpr(pos, recv)) + } + + addTailCall(pos, fn, recv, method) +} + +func (r *reader) methodValueWrapper(tbase *types.Type, method *types.Field, target *ir.Package) { + recvType := tbase + if !tbase.IsInterface() { + recvType = method.Type.Recv().Type + if !types.Identical(tbase, types.ReceiverBaseType(recvType)) { + return + } + } + + sym := ir.MethodSymSuffix(recvType, method.Sym, "-fm") + assert(!sym.Uniq()) + sym.SetUniq(true) + + // TODO(mdempsky): Fix typecheck to not depend on creation of + // imported method value wrappers. + if false && !reflectdata.NeedEmit(tbase) { + return + } + + // TODO(mdempsky): Use method.Pos instead? + pos := base.AutogeneratedPos + + fn := r.newWrapperFunc(pos, sym, nil, method, target) + fn.SetNeedctxt(true) + sym.Def = fn + + // Declare and initialize variable holding receiver. + recv := ir.NewNameAt(pos, typecheck.Lookup(".this")) + recv.Class = ir.PAUTOHEAP + recv.SetType(recvType) + recv.Curfn = fn + recv.SetIsClosureVar(true) + recv.SetByval(true) + fn.ClosureVars = append(fn.ClosureVars, recv) + + addTailCall(pos, fn, recv, method) +} + +func (r *reader) newWrapperFunc(pos src.XPos, sym *types.Sym, wrapper *types.Type, method *types.Field, target *ir.Package) *ir.Func { fn := ir.NewFunc(pos) - fn.SetDupok(true) // TODO(mdempsky): Leave unset for local, non-generic wrappers? - fn.SetWrapper(true) // TODO(mdempsky): Leave unset for tail calls? + fn.SetDupok(true) // TODO(mdempsky): Leave unset for local, non-generic wrappers? - fn.Nname = ir.NewNameAt(pos, sym) - ir.MarkFunc(fn.Nname) - fn.Nname.Func = fn - fn.Nname.Defn = fn + name := ir.NewNameAt(pos, sym) + ir.MarkFunc(name) + name.Func = fn + name.Defn = fn + fn.Nname = name - sig := newWrapperType(wrapper, method.Type) - r.setType(fn.Nname, sig) + sig := newWrapperType(wrapper, method) + r.setType(name, sig) // TODO(mdempsky): De-duplicate with similar logic in funcargs. - defParams := func(class ir.Class, params ...*types.Field) { - for _, param := range params { + defParams := func(class ir.Class, params *types.Type) { + for _, param := range params.FieldSlice() { name := ir.NewNameAt(param.Pos, param.Sym) name.Class = class r.setType(name, param.Type) @@ -2126,39 +2188,20 @@ func (r *reader) methodWrapper(derefs int, tbase *types.Type, method *types.Fiel } } - defParams(ir.PPARAM, sig.Recv()) - defParams(ir.PPARAM, sig.Params().FieldSlice()...) - defParams(ir.PPARAMOUT, sig.Results().FieldSlice()...) - - var recv ir.Node = sig.Recv().Nname.(*ir.Name) - - // For simple *T wrappers around T methods, panicwrap produces a - // nicer panic message. - if wrapper.IsPtr() && types.Identical(wrapper.Elem(), wrappee) { - cond := ir.NewBinaryExpr(pos, ir.OEQ, recv, types.BuiltinPkg.Lookup("nil").Def.(ir.Node)) - then := []ir.Node{ir.NewCallExpr(pos, ir.OCALL, typecheck.LookupRuntime("panicwrap"), nil)} - fn.Body.Append(ir.NewIfStmt(pos, cond, then, nil)) - } - - // Add implicit derefs, as necessary. typecheck will add one deref, - // but not-in-heap types will need another for their **T wrappers. - for i := 0; i < derefs; i++ { - recv = Implicit(ir.NewStarExpr(pos, recv)) - } - - args := make([]ir.Node, sig.NumParams()) - for i, param := range sig.Params().FieldSlice() { - args[i] = param.Nname.(*ir.Name) - } - - fn.Body.Append(newTailCall(pos, method, recv, args)) + defParams(ir.PPARAM, sig.Recvs()) + defParams(ir.PPARAM, sig.Params()) + defParams(ir.PPARAMOUT, sig.Results()) target.Decls = append(target.Decls, fn) + + return fn } // newWrapperType returns a copy of the given signature type, but with -// the receiver parameter type substituted with wrapper. -func newWrapperType(wrapper, sig *types.Type) *types.Type { +// the receiver parameter type substituted with recvType. +// If recvType is nil, newWrapperType returns a signature +// without a receiver parameter. +func newWrapperType(recvType *types.Type, method *types.Field) *types.Type { clone := func(params []*types.Field) []*types.Field { res := make([]*types.Field, len(params)) for i, param := range params { @@ -2172,25 +2215,39 @@ func newWrapperType(wrapper, sig *types.Type) *types.Type { return res } - recv := types.NewField(sig.Recv().Pos, typecheck.Lookup(".this"), wrapper) + sig := method.Type + + var recv *types.Field + if recvType != nil { + recv = types.NewField(sig.Recv().Pos, typecheck.Lookup(".this"), recvType) + } params := clone(sig.Params().FieldSlice()) results := clone(sig.Results().FieldSlice()) return types.NewSignature(types.NoPkg, recv, nil, params, results) } -func newTailCall(pos src.XPos, method *types.Field, recv ir.Node, args []ir.Node) ir.Node { +func addTailCall(pos src.XPos, fn *ir.Func, recv ir.Node, method *types.Field) { + sig := fn.Nname.Type() + args := make([]ir.Node, sig.NumParams()) + for i, param := range sig.Params().FieldSlice() { + args[i] = param.Nname.(*ir.Name) + } + // TODO(mdempsky): Support creating OTAILCALL, when possible. See reflectdata.methodWrapper. // Not urgent though, because tail calls are currently incompatible with regabi anyway. + fn.SetWrapper(true) // TODO(mdempsky): Leave unset for tail calls? + call := ir.NewCallExpr(pos, ir.OCALL, ir.NewSelectorExpr(pos, ir.OXDOT, recv, method.Sym), args) call.IsDDD = method.Type.IsVariadic() if method.Type.NumResults() == 0 { - return call + fn.Body.Append(call) + return } ret := ir.NewReturnStmt(pos, nil) ret.Results = []ir.Node{call} - return ret + fn.Body.Append(ret) } -- GitLab From 1b995f91a526ff165952218848c3173026a8dc53 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sun, 27 Jun 2021 01:28:38 +0700 Subject: [PATCH 0372/2500] [dev.typeparams] cmd/compile: rename OCALLPART to OMETHVALUE Go spec call them "method values", not "partial calls". Note that we use "OMETHVALUE" (as opposed to "OMETHODVALUE") to be consistent with "OMETHEXPR". Change-Id: I1efd985d4b567a1b4b20aeb603eb82db579edbd5 Reviewed-on: https://go-review.googlesource.com/c/go/+/330837 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/escape/escape.go | 2 +- src/cmd/compile/internal/escape/expr.go | 2 +- src/cmd/compile/internal/escape/utils.go | 2 +- src/cmd/compile/internal/inline/inl.go | 2 +- src/cmd/compile/internal/ir/expr.go | 6 +- src/cmd/compile/internal/ir/fmt.go | 4 +- src/cmd/compile/internal/ir/func.go | 8 +- src/cmd/compile/internal/ir/node.go | 4 +- src/cmd/compile/internal/ir/op_string.go | 168 +++++++++--------- src/cmd/compile/internal/ir/scc.go | 2 +- src/cmd/compile/internal/noder/expr.go | 4 +- src/cmd/compile/internal/noder/helpers.go | 4 +- src/cmd/compile/internal/noder/stencil.go | 10 +- src/cmd/compile/internal/noder/transform.go | 4 +- src/cmd/compile/internal/pkginit/initorder.go | 2 +- src/cmd/compile/internal/typecheck/const.go | 2 +- src/cmd/compile/internal/typecheck/crawler.go | 2 +- src/cmd/compile/internal/typecheck/expr.go | 2 +- src/cmd/compile/internal/typecheck/func.go | 4 +- src/cmd/compile/internal/typecheck/iexport.go | 4 +- src/cmd/compile/internal/typecheck/iimport.go | 6 +- src/cmd/compile/internal/walk/closure.go | 2 +- src/cmd/compile/internal/walk/expr.go | 4 +- src/cmd/compile/internal/walk/order.go | 2 +- 24 files changed, 126 insertions(+), 126 deletions(-) diff --git a/src/cmd/compile/internal/escape/escape.go b/src/cmd/compile/internal/escape/escape.go index 317bc98473..04d0c2356c 100644 --- a/src/cmd/compile/internal/escape/escape.go +++ b/src/cmd/compile/internal/escape/escape.go @@ -315,7 +315,7 @@ func (b *batch) finish(fns []*ir.Func) { case ir.OCLOSURE: n := n.(*ir.ClosureExpr) n.SetTransient(true) - case ir.OCALLPART: + case ir.OMETHVALUE: n := n.(*ir.SelectorExpr) n.SetTransient(true) case ir.OSLICELIT: diff --git a/src/cmd/compile/internal/escape/expr.go b/src/cmd/compile/internal/escape/expr.go index 71c8eec6ef..dfcd55734a 100644 --- a/src/cmd/compile/internal/escape/expr.go +++ b/src/cmd/compile/internal/escape/expr.go @@ -153,7 +153,7 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) { e.spill(k, n) e.discard(n.Len) - case ir.OCALLPART: + case ir.OMETHVALUE: // Flow the receiver argument to both the closure and // to the receiver parameter. diff --git a/src/cmd/compile/internal/escape/utils.go b/src/cmd/compile/internal/escape/utils.go index 7100926bb8..1ac4cc6029 100644 --- a/src/cmd/compile/internal/escape/utils.go +++ b/src/cmd/compile/internal/escape/utils.go @@ -193,7 +193,7 @@ func HeapAllocReason(n ir.Node) string { if n.Op() == ir.OCLOSURE && typecheck.ClosureType(n.(*ir.ClosureExpr)).Size() >= ir.MaxImplicitStackVarSize { return "too large for stack" } - if n.Op() == ir.OCALLPART && typecheck.PartialCallType(n.(*ir.SelectorExpr)).Size() >= ir.MaxImplicitStackVarSize { + if n.Op() == ir.OMETHVALUE && typecheck.PartialCallType(n.(*ir.SelectorExpr)).Size() >= ir.MaxImplicitStackVarSize { return "too large for stack" } diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index 3086d093c0..a6961e4e4d 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -416,7 +416,7 @@ func (v *hairyVisitor) doNode(n ir.Node) bool { // and don't charge for the OBLOCK itself. The ++ undoes the -- below. v.budget++ - case ir.OCALLPART, ir.OSLICELIT: + case ir.OMETHVALUE, ir.OSLICELIT: v.budget-- // Hack for toolstash -cmp. case ir.OMETHEXPR: diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 81b2c52b87..919cb3362f 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -519,7 +519,7 @@ type SelectorExpr struct { Sel *types.Sym // The actual selected field - may not be filled in until typechecking. Selection *types.Field - Prealloc *Name // preallocated storage for OCALLPART, if any + Prealloc *Name // preallocated storage for OMETHVALUE, if any } func NewSelectorExpr(pos src.XPos, op Op, x Node, sel *types.Sym) *SelectorExpr { @@ -533,7 +533,7 @@ func (n *SelectorExpr) SetOp(op Op) { switch op { default: panic(n.no("SetOp " + op.String())) - case OXDOT, ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OCALLPART, OMETHEXPR: + case OXDOT, ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OMETHVALUE, OMETHEXPR: n.op = op } } @@ -1098,7 +1098,7 @@ func MethodExprName(n Node) *Name { // MethodExprFunc is like MethodExprName, but returns the types.Field instead. func MethodExprFunc(n Node) *types.Field { switch n.Op() { - case ODOTMETH, OMETHEXPR, OCALLPART: + case ODOTMETH, OMETHEXPR, OMETHVALUE: return n.(*SelectorExpr).Selection } base.Fatalf("unexpected node: %v (%v)", n, n.Op()) diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index d9cc5f109f..ae62d5f51b 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -237,7 +237,7 @@ var OpPrec = []int{ ODOTTYPE: 8, ODOT: 8, OXDOT: 8, - OCALLPART: 8, + OMETHVALUE: 8, OMETHEXPR: 8, OPLUS: 7, ONOT: 7, @@ -757,7 +757,7 @@ func exprFmt(n Node, s fmt.State, prec int) { n := n.(*StructKeyExpr) fmt.Fprintf(s, "%v:%v", n.Field, n.Value) - case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH, OCALLPART, OMETHEXPR: + case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH, OMETHVALUE, OMETHEXPR: n := n.(*SelectorExpr) exprFmt(n.X, s, nprec) if n.Sel == nil { diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go index 3501f83ab1..3b9e36d4c5 100644 --- a/src/cmd/compile/internal/ir/func.go +++ b/src/cmd/compile/internal/ir/func.go @@ -40,14 +40,14 @@ import ( // constructs a fresh node. // // A method value (t.M) is represented by ODOTMETH/ODOTINTER -// when it is called directly and by OCALLPART otherwise. +// when it is called directly and by OMETHVALUE otherwise. // These are like method expressions, except that for ODOTMETH/ODOTINTER, // the method name is stored in Sym instead of Right. -// Each OCALLPART ends up being implemented as a new +// Each OMETHVALUE ends up being implemented as a new // function, a bit like a closure, with its own ODCLFUNC. -// The OCALLPART uses n.Func to record the linkage to +// The OMETHVALUE uses n.Func to record the linkage to // the generated ODCLFUNC, but there is no -// pointer from the Func back to the OCALLPART. +// pointer from the Func back to the OMETHVALUE. type Func struct { miniNode Body Nodes diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index fa7c9cc276..f6eae58b04 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -159,7 +159,6 @@ const ( OCALLFUNC // X(Args) (function call f(args)) OCALLMETH // X(Args) (direct method call x.Method(args)) OCALLINTER // X(Args) (interface method call x.Method(args)) - OCALLPART // X.Sel (method expression x.Method, not called) OCAP // cap(X) OCLOSE // close(X) OCLOSURE // func Type { Func.Closure.Body } (func literal) @@ -250,7 +249,8 @@ const ( OSIZEOF // unsafe.Sizeof(X) OUNSAFEADD // unsafe.Add(X, Y) OUNSAFESLICE // unsafe.Slice(X, Y) - OMETHEXPR // method expression + OMETHEXPR // X(Args) (method expression T.Method(args), first argument is the method receiver) + OMETHVALUE // X.Sel (method expression t.Method, not called) // statements OBLOCK // { List } (block of code) diff --git a/src/cmd/compile/internal/ir/op_string.go b/src/cmd/compile/internal/ir/op_string.go index 80c8d09c1e..05a37a60b1 100644 --- a/src/cmd/compile/internal/ir/op_string.go +++ b/src/cmd/compile/internal/ir/op_string.go @@ -41,88 +41,88 @@ func _() { _ = x[OCALLFUNC-30] _ = x[OCALLMETH-31] _ = x[OCALLINTER-32] - _ = x[OCALLPART-33] - _ = x[OCAP-34] - _ = x[OCLOSE-35] - _ = x[OCLOSURE-36] - _ = x[OCOMPLIT-37] - _ = x[OMAPLIT-38] - _ = x[OSTRUCTLIT-39] - _ = x[OARRAYLIT-40] - _ = x[OSLICELIT-41] - _ = x[OPTRLIT-42] - _ = x[OCONV-43] - _ = x[OCONVIFACE-44] - _ = x[OCONVNOP-45] - _ = x[OCOPY-46] - _ = x[ODCL-47] - _ = x[ODCLFUNC-48] - _ = x[ODCLCONST-49] - _ = x[ODCLTYPE-50] - _ = x[ODELETE-51] - _ = x[ODOT-52] - _ = x[ODOTPTR-53] - _ = x[ODOTMETH-54] - _ = x[ODOTINTER-55] - _ = x[OXDOT-56] - _ = x[ODOTTYPE-57] - _ = x[ODOTTYPE2-58] - _ = x[OEQ-59] - _ = x[ONE-60] - _ = x[OLT-61] - _ = x[OLE-62] - _ = x[OGE-63] - _ = x[OGT-64] - _ = x[ODEREF-65] - _ = x[OINDEX-66] - _ = x[OINDEXMAP-67] - _ = x[OKEY-68] - _ = x[OSTRUCTKEY-69] - _ = x[OLEN-70] - _ = x[OMAKE-71] - _ = x[OMAKECHAN-72] - _ = x[OMAKEMAP-73] - _ = x[OMAKESLICE-74] - _ = x[OMAKESLICECOPY-75] - _ = x[OMUL-76] - _ = x[ODIV-77] - _ = x[OMOD-78] - _ = x[OLSH-79] - _ = x[ORSH-80] - _ = x[OAND-81] - _ = x[OANDNOT-82] - _ = x[ONEW-83] - _ = x[ONOT-84] - _ = x[OBITNOT-85] - _ = x[OPLUS-86] - _ = x[ONEG-87] - _ = x[OOROR-88] - _ = x[OPANIC-89] - _ = x[OPRINT-90] - _ = x[OPRINTN-91] - _ = x[OPAREN-92] - _ = x[OSEND-93] - _ = x[OSLICE-94] - _ = x[OSLICEARR-95] - _ = x[OSLICESTR-96] - _ = x[OSLICE3-97] - _ = x[OSLICE3ARR-98] - _ = x[OSLICEHEADER-99] - _ = x[ORECOVER-100] - _ = x[ORECOVERFP-101] - _ = x[ORECV-102] - _ = x[ORUNESTR-103] - _ = x[OSELRECV2-104] - _ = x[OIOTA-105] - _ = x[OREAL-106] - _ = x[OIMAG-107] - _ = x[OCOMPLEX-108] - _ = x[OALIGNOF-109] - _ = x[OOFFSETOF-110] - _ = x[OSIZEOF-111] - _ = x[OUNSAFEADD-112] - _ = x[OUNSAFESLICE-113] - _ = x[OMETHEXPR-114] + _ = x[OCAP-33] + _ = x[OCLOSE-34] + _ = x[OCLOSURE-35] + _ = x[OCOMPLIT-36] + _ = x[OMAPLIT-37] + _ = x[OSTRUCTLIT-38] + _ = x[OARRAYLIT-39] + _ = x[OSLICELIT-40] + _ = x[OPTRLIT-41] + _ = x[OCONV-42] + _ = x[OCONVIFACE-43] + _ = x[OCONVNOP-44] + _ = x[OCOPY-45] + _ = x[ODCL-46] + _ = x[ODCLFUNC-47] + _ = x[ODCLCONST-48] + _ = x[ODCLTYPE-49] + _ = x[ODELETE-50] + _ = x[ODOT-51] + _ = x[ODOTPTR-52] + _ = x[ODOTMETH-53] + _ = x[ODOTINTER-54] + _ = x[OXDOT-55] + _ = x[ODOTTYPE-56] + _ = x[ODOTTYPE2-57] + _ = x[OEQ-58] + _ = x[ONE-59] + _ = x[OLT-60] + _ = x[OLE-61] + _ = x[OGE-62] + _ = x[OGT-63] + _ = x[ODEREF-64] + _ = x[OINDEX-65] + _ = x[OINDEXMAP-66] + _ = x[OKEY-67] + _ = x[OSTRUCTKEY-68] + _ = x[OLEN-69] + _ = x[OMAKE-70] + _ = x[OMAKECHAN-71] + _ = x[OMAKEMAP-72] + _ = x[OMAKESLICE-73] + _ = x[OMAKESLICECOPY-74] + _ = x[OMUL-75] + _ = x[ODIV-76] + _ = x[OMOD-77] + _ = x[OLSH-78] + _ = x[ORSH-79] + _ = x[OAND-80] + _ = x[OANDNOT-81] + _ = x[ONEW-82] + _ = x[ONOT-83] + _ = x[OBITNOT-84] + _ = x[OPLUS-85] + _ = x[ONEG-86] + _ = x[OOROR-87] + _ = x[OPANIC-88] + _ = x[OPRINT-89] + _ = x[OPRINTN-90] + _ = x[OPAREN-91] + _ = x[OSEND-92] + _ = x[OSLICE-93] + _ = x[OSLICEARR-94] + _ = x[OSLICESTR-95] + _ = x[OSLICE3-96] + _ = x[OSLICE3ARR-97] + _ = x[OSLICEHEADER-98] + _ = x[ORECOVER-99] + _ = x[ORECOVERFP-100] + _ = x[ORECV-101] + _ = x[ORUNESTR-102] + _ = x[OSELRECV2-103] + _ = x[OIOTA-104] + _ = x[OREAL-105] + _ = x[OIMAG-106] + _ = x[OCOMPLEX-107] + _ = x[OALIGNOF-108] + _ = x[OOFFSETOF-109] + _ = x[OSIZEOF-110] + _ = x[OUNSAFEADD-111] + _ = x[OUNSAFESLICE-112] + _ = x[OMETHEXPR-113] + _ = x[OMETHVALUE-114] _ = x[OBLOCK-115] _ = x[OBREAK-116] _ = x[OCASE-117] @@ -168,9 +168,9 @@ func _() { _ = x[OEND-157] } -const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESSLICE2ARRPTRASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECOVERFPRECVRUNESTRSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFUNSAFEADDUNSAFESLICEMETHEXPRBLOCKBREAKCASECONTINUEDEFERFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWFUNCINSTTCHANTMAPTSTRUCTTINTERTFUNCTARRAYTSLICEINLCALLEFACEITABIDATASPTRCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKLINKSYMOFFSETTAILCALLGETGGETCALLERPCGETCALLERSPEND" +const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESSLICE2ARRPTRASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECOVERFPRECVRUNESTRSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFUNSAFEADDUNSAFESLICEMETHEXPRMETHVALUEBLOCKBREAKCASECONTINUEDEFERFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWFUNCINSTTCHANTMAPTSTRUCTTINTERTFUNCTARRAYTSLICEINLCALLEFACEITABIDATASPTRCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKLINKSYMOFFSETTAILCALLGETGGETCALLERPCGETCALLERSPEND" -var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 136, 138, 141, 151, 158, 165, 172, 176, 180, 188, 196, 205, 213, 216, 221, 228, 235, 241, 250, 258, 266, 272, 276, 285, 292, 296, 299, 306, 314, 321, 327, 330, 336, 343, 351, 355, 362, 370, 372, 374, 376, 378, 380, 382, 387, 392, 400, 403, 412, 415, 419, 427, 434, 443, 456, 459, 462, 465, 468, 471, 474, 480, 483, 486, 492, 496, 499, 503, 508, 513, 519, 524, 528, 533, 541, 549, 555, 564, 575, 582, 591, 595, 602, 610, 614, 618, 622, 629, 636, 644, 650, 659, 670, 678, 683, 688, 692, 700, 705, 709, 712, 720, 724, 726, 731, 733, 738, 744, 750, 756, 762, 770, 775, 779, 786, 792, 797, 803, 809, 816, 821, 825, 830, 834, 839, 847, 853, 860, 867, 873, 880, 893, 901, 905, 916, 927, 930} +var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 136, 138, 141, 151, 158, 165, 172, 176, 180, 188, 196, 205, 208, 213, 220, 227, 233, 242, 250, 258, 264, 268, 277, 284, 288, 291, 298, 306, 313, 319, 322, 328, 335, 343, 347, 354, 362, 364, 366, 368, 370, 372, 374, 379, 384, 392, 395, 404, 407, 411, 419, 426, 435, 448, 451, 454, 457, 460, 463, 466, 472, 475, 478, 484, 488, 491, 495, 500, 505, 511, 516, 520, 525, 533, 541, 547, 556, 567, 574, 583, 587, 594, 602, 606, 610, 614, 621, 628, 636, 642, 651, 662, 670, 679, 684, 689, 693, 701, 706, 710, 713, 721, 725, 727, 732, 734, 739, 745, 751, 757, 763, 771, 776, 780, 787, 793, 798, 804, 810, 817, 822, 826, 831, 835, 840, 848, 854, 861, 868, 874, 881, 894, 902, 906, 917, 928, 931} func (i Op) String() string { if i >= Op(len(_Op_index)-1) { diff --git a/src/cmd/compile/internal/ir/scc.go b/src/cmd/compile/internal/ir/scc.go index 83c6074170..2cfceaa1f6 100644 --- a/src/cmd/compile/internal/ir/scc.go +++ b/src/cmd/compile/internal/ir/scc.go @@ -90,7 +90,7 @@ func (v *bottomUpVisitor) visit(n *Func) uint32 { if n := n.(*Name); n.Class == PFUNC { do(n.Defn) } - case ODOTMETH, OCALLPART, OMETHEXPR: + case ODOTMETH, OMETHVALUE, OMETHEXPR: if fn := MethodExprName(n); fn != nil { do(fn.Defn) } diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 98dc504ee9..017e98986f 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -196,7 +196,7 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { } } -// selectorExpr resolves the choice of ODOT, ODOTPTR, OCALLPART (eventually +// selectorExpr resolves the choice of ODOT, ODOTPTR, OMETHVALUE (eventually // ODOTMETH & ODOTINTER), and OMETHEXPR and deals with embedded fields here rather // than in typecheck.go. func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.SelectorExpr) ir.Node { @@ -273,7 +273,7 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto // the base generic type. The instantiated type may not // have method bodies filled in, if it was imported. method := recvType.Methods().Index(last).Nname.(*ir.Name) - n = ir.NewSelectorExpr(pos, ir.OCALLPART, x, typecheck.Lookup(expr.Sel.Value)) + n = ir.NewSelectorExpr(pos, ir.OMETHVALUE, x, typecheck.Lookup(expr.Sel.Value)) n.(*ir.SelectorExpr).Selection = types.NewField(pos, method.Sym(), method.Type()) n.(*ir.SelectorExpr).Selection.Nname = method typed(method.Type(), n) diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index 456df312a6..6ab318318b 100644 --- a/src/cmd/compile/internal/noder/helpers.go +++ b/src/cmd/compile/internal/noder/helpers.go @@ -166,7 +166,7 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) case *ir.ClosureExpr: fun.Func.SetClosureCalled(true) case *ir.SelectorExpr: - if fun.Op() == ir.OCALLPART { + if fun.Op() == ir.OMETHVALUE { op := ir.ODOTMETH if fun.X.Type().IsInterface() { op = ir.ODOTINTER @@ -251,7 +251,7 @@ func DotMethod(pos src.XPos, x ir.Node, index int) *ir.SelectorExpr { // Method value. typ := typecheck.NewMethodType(method.Type, nil) - return dot(pos, typ, ir.OCALLPART, x, method) + return dot(pos, typ, ir.OMETHVALUE, x, method) } // MethodExpr returns a OMETHEXPR node with the indicated index into the methods diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 1917c95be7..60d56c206f 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -103,7 +103,7 @@ func (g *irgen) stencil() { inst := call.X.(*ir.InstExpr) st, dict := g.getInstantiationForNode(inst) if infoPrintMode && g.target.Stencils[decl.Sym()] == nil { - if inst.X.Op() == ir.OCALLPART { + if inst.X.Op() == ir.OMETHVALUE { fmt.Printf("Main dictionary in %v at generic method call: %v - %v\n", decl, inst.X, call) } else { fmt.Printf("Main dictionary in %v at generic function call: %v - %v\n", decl, inst.X, call) @@ -112,7 +112,7 @@ func (g *irgen) stencil() { // Replace the OFUNCINST with a direct reference to the // new stenciled function call.X = st.Nname - if inst.X.Op() == ir.OCALLPART { + if inst.X.Op() == ir.OMETHVALUE { // When we create an instantiation of a method // call, we make it a function. So, move the // receiver to be the first arg of the function @@ -218,7 +218,7 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { if inst.X.Op() == ir.ONAME { // Instantiating a generic function call. gf = inst.X.(*ir.Name) - } else if inst.X.Op() == ir.OCALLPART { + } else if inst.X.Op() == ir.OMETHVALUE { // Instantiating a method value x.M. se := inst.X.(*ir.SelectorExpr) rcvrValue = se.X @@ -826,7 +826,7 @@ func (subst *subster) node(n ir.Node) ir.Node { // instantiated receiver type. We need to do this now, // since the access/selection to the method for the real // type is very different from the selection for the type - // param. m will be transformed to an OCALLPART node. It + // param. m will be transformed to an OMETHVALUE node. It // will be transformed to an ODOTMETH or ODOTINTER node if // we find in the OCALL case below that the method value // is actually called. @@ -841,7 +841,7 @@ func (subst *subster) node(n ir.Node) ir.Node { // type argument. m = transformConvCall(m.(*ir.CallExpr)) - case ir.OCALLPART: + case ir.OMETHVALUE: // Redo the transformation of OXDOT, now that we // know the method value is being called. Then // transform the call. diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index 30d6e34ae4..660c4a19e6 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -564,7 +564,7 @@ func transformAsOp(n *ir.AssignOpStmt) { } // transformDot transforms an OXDOT (or ODOT) or ODOT, ODOTPTR, ODOTMETH, -// ODOTINTER, or OCALLPART, as appropriate. It adds in extra nodes as needed to +// ODOTINTER, or OMETHVALUE, as appropriate. It adds in extra nodes as needed to // access embedded fields. Corresponds to typecheck.tcDot. func transformDot(n *ir.SelectorExpr, isCall bool) ir.Node { assert(n.Type() != nil && n.Typecheck() == 1) @@ -588,7 +588,7 @@ func transformDot(n *ir.SelectorExpr, isCall bool) ir.Node { assert(f != nil) if (n.Op() == ir.ODOTINTER || n.Op() == ir.ODOTMETH) && !isCall { - n.SetOp(ir.OCALLPART) + n.SetOp(ir.OMETHVALUE) if len(n.X.Type().RParams()) > 0 || n.X.Type().IsPtr() && len(n.X.Type().Elem().RParams()) > 0 { // TODO: MethodValueWrapper needed for generics? // Or did we successfully desugar all that at stencil time? diff --git a/src/cmd/compile/internal/pkginit/initorder.go b/src/cmd/compile/internal/pkginit/initorder.go index 97d69629fb..0aad63a69f 100644 --- a/src/cmd/compile/internal/pkginit/initorder.go +++ b/src/cmd/compile/internal/pkginit/initorder.go @@ -304,7 +304,7 @@ func (d *initDeps) visit(n ir.Node) { n := n.(*ir.ClosureExpr) d.inspectList(n.Func.Body) - case ir.ODOTMETH, ir.OCALLPART, ir.OMETHEXPR: + case ir.ODOTMETH, ir.OMETHVALUE, ir.OMETHEXPR: d.foundDep(ir.MethodExprName(n)) } } diff --git a/src/cmd/compile/internal/typecheck/const.go b/src/cmd/compile/internal/typecheck/const.go index 761b043794..f8150d249a 100644 --- a/src/cmd/compile/internal/typecheck/const.go +++ b/src/cmd/compile/internal/typecheck/const.go @@ -901,7 +901,7 @@ func evalunsafe(n ir.Node) int64 { switch tsel.Op() { case ir.ODOT, ir.ODOTPTR: break - case ir.OCALLPART: + case ir.OMETHVALUE: base.Errorf("invalid expression %v: argument is a method value", n) return 0 default: diff --git a/src/cmd/compile/internal/typecheck/crawler.go b/src/cmd/compile/internal/typecheck/crawler.go index 655ac6e465..9a348b9f37 100644 --- a/src/cmd/compile/internal/typecheck/crawler.go +++ b/src/cmd/compile/internal/typecheck/crawler.go @@ -201,7 +201,7 @@ func (p *crawler) markInlBody(n *ir.Name) { p.checkGenericType(n.Type()) case ir.OTYPE: p.checkGenericType(n.Type()) - case ir.OCALLPART: + case ir.OMETHVALUE: // Okay, because we don't yet inline indirect // calls to method values. case ir.OCLOSURE: diff --git a/src/cmd/compile/internal/typecheck/expr.go b/src/cmd/compile/internal/typecheck/expr.go index d52f011072..f039cbab08 100644 --- a/src/cmd/compile/internal/typecheck/expr.go +++ b/src/cmd/compile/internal/typecheck/expr.go @@ -541,7 +541,7 @@ func tcDot(n *ir.SelectorExpr, top int) ir.Node { } if (n.Op() == ir.ODOTINTER || n.Op() == ir.ODOTMETH) && top&ctxCallee == 0 { - n.SetOp(ir.OCALLPART) + n.SetOp(ir.OMETHVALUE) n.SetType(MethodValueWrapper(n).Type()) } return n diff --git a/src/cmd/compile/internal/typecheck/func.go b/src/cmd/compile/internal/typecheck/func.go index 20b991be56..f4fcfddcf1 100644 --- a/src/cmd/compile/internal/typecheck/func.go +++ b/src/cmd/compile/internal/typecheck/func.go @@ -126,7 +126,7 @@ func ClosureType(clo *ir.ClosureExpr) *types.Type { } // PartialCallType returns the struct type used to hold all the information -// needed in the closure for n (n must be a OCALLPART node). +// needed in the closure for n (n must be a OMETHVALUE node). // The address of a variable of the returned type can be cast to a func. func PartialCallType(n *ir.SelectorExpr) *types.Type { t := types.NewStruct(types.NoPkg, []*types.Field{ @@ -225,7 +225,7 @@ func fnpkg(fn *ir.Name) *types.Pkg { // // TODO(mdempsky): Move into walk. This isn't part of type checking. func MethodValueWrapper(dot *ir.SelectorExpr) *ir.Func { - if dot.Op() != ir.OCALLPART { + if dot.Op() != ir.OMETHVALUE { base.Fatalf("MethodValueWrapper: unexpected %v (%v)", dot, dot.Op()) } diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 10d4bd6e7e..b17af815ec 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -1775,7 +1775,7 @@ func (w *exportWriter) expr(n ir.Node) { // case OSTRUCTKEY: // unreachable - handled in case OSTRUCTLIT by elemList - case ir.OXDOT, ir.ODOT, ir.ODOTPTR, ir.ODOTINTER, ir.ODOTMETH, ir.OCALLPART, ir.OMETHEXPR: + case ir.OXDOT, ir.ODOT, ir.ODOTPTR, ir.ODOTINTER, ir.ODOTMETH, ir.OMETHVALUE, ir.OMETHEXPR: n := n.(*ir.SelectorExpr) if go117ExportTypes { // For go117ExportTypes, we usually see all ops except @@ -1792,7 +1792,7 @@ func (w *exportWriter) expr(n ir.Node) { if n.Op() == ir.ODOT || n.Op() == ir.ODOTPTR || n.Op() == ir.ODOTINTER { w.exoticField(n.Selection) } - // n.Selection is not required for OMETHEXPR, ODOTMETH, and OCALLPART. It will + // n.Selection is not required for OMETHEXPR, ODOTMETH, and OMETHVALUE. It will // be reconstructed during import. n.Selection is computed during // transformDot() for OXDOT. } diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index d94f649a45..7b61260e79 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1357,7 +1357,7 @@ func (r *importReader) node() ir.Node { // case OSTRUCTKEY: // unreachable - handled in case OSTRUCTLIT by elemList - case ir.OXDOT, ir.ODOT, ir.ODOTPTR, ir.ODOTINTER, ir.ODOTMETH, ir.OCALLPART, ir.OMETHEXPR: + case ir.OXDOT, ir.ODOT, ir.ODOTPTR, ir.ODOTINTER, ir.ODOTMETH, ir.OMETHVALUE, ir.OMETHEXPR: // For !go117ExportTypes, we should only see OXDOT. // For go117ExportTypes, we usually see all the other ops, but can see // OXDOT for generic functions. @@ -1373,12 +1373,12 @@ func (r *importReader) node() ir.Node { switch op { case ir.ODOT, ir.ODOTPTR, ir.ODOTINTER: n.Selection = r.exoticField() - case ir.ODOTMETH, ir.OCALLPART, ir.OMETHEXPR: + case ir.ODOTMETH, ir.OMETHVALUE, ir.OMETHEXPR: // These require a Lookup to link to the correct declaration. rcvrType := expr.Type() typ := n.Type() n.Selection = Lookdot(n, rcvrType, 1) - if op == ir.OCALLPART || op == ir.OMETHEXPR { + if op == ir.OMETHVALUE || op == ir.OMETHEXPR { // Lookdot clobbers the opcode and type, undo that. n.SetOp(op) n.SetType(typ) diff --git a/src/cmd/compile/internal/walk/closure.go b/src/cmd/compile/internal/walk/closure.go index 2b7fe8f926..f399a26689 100644 --- a/src/cmd/compile/internal/walk/closure.go +++ b/src/cmd/compile/internal/walk/closure.go @@ -156,7 +156,7 @@ func closureArgs(clo *ir.ClosureExpr) []ir.Node { return args } -func walkCallPart(n *ir.SelectorExpr, init *ir.Nodes) ir.Node { +func walkMethodValue(n *ir.SelectorExpr, init *ir.Nodes) ir.Node { // Create closure in the form of a composite literal. // For x.M with receiver (x) type T, the generated code looks like: // diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go index f7675c3b7d..19fb188526 100644 --- a/src/cmd/compile/internal/walk/expr.go +++ b/src/cmd/compile/internal/walk/expr.go @@ -308,8 +308,8 @@ func walkExpr1(n ir.Node, init *ir.Nodes) ir.Node { case ir.OCLOSURE: return walkClosure(n.(*ir.ClosureExpr), init) - case ir.OCALLPART: - return walkCallPart(n.(*ir.SelectorExpr), init) + case ir.OMETHVALUE: + return walkMethodValue(n.(*ir.SelectorExpr), init) } // No return! Each case must return (or panic), diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go index 16a124d2ff..007af03d4b 100644 --- a/src/cmd/compile/internal/walk/order.go +++ b/src/cmd/compile/internal/walk/order.go @@ -1275,7 +1275,7 @@ func (o *orderState) expr1(n, lhs ir.Node) ir.Node { } return n - case ir.OCALLPART: + case ir.OMETHVALUE: n := n.(*ir.SelectorExpr) n.X = o.expr(n.X, nil) if n.Transient() { -- GitLab From 20a04f60417b60ab5c1ce2dfcdefce1ff57f5914 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sun, 27 Jun 2021 01:31:03 +0700 Subject: [PATCH 0373/2500] [dev.typeparams] cmd/compile: delay method value wrapper generation until walk As walk already create the wrapper if necessary. With this change, test/inline.go need to be changed to use errorcheckwithauto, for matching "inlining call to ..." in autogenerated position for method value wrapper, since when we don't generate the wrapper immediately during typecheck. Change-Id: I9ffbec9ad3c2b7295546976e2fa517336c13c89b Reviewed-on: https://go-review.googlesource.com/c/go/+/330838 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/typecheck/expr.go | 2 +- test/inline.go | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/typecheck/expr.go b/src/cmd/compile/internal/typecheck/expr.go index f039cbab08..7e974dfda8 100644 --- a/src/cmd/compile/internal/typecheck/expr.go +++ b/src/cmd/compile/internal/typecheck/expr.go @@ -542,7 +542,7 @@ func tcDot(n *ir.SelectorExpr, top int) ir.Node { if (n.Op() == ir.ODOTINTER || n.Op() == ir.ODOTMETH) && top&ctxCallee == 0 { n.SetOp(ir.OMETHVALUE) - n.SetType(MethodValueWrapper(n).Type()) + n.SetType(NewMethodType(n.Type(), nil)) } return n } diff --git a/test/inline.go b/test/inline.go index 472a941dca..2cda07b2da 100644 --- a/test/inline.go +++ b/test/inline.go @@ -1,4 +1,4 @@ -// errorcheck -0 -m -d=inlfuncswithclosures=1 +// errorcheckwithauto -0 -m -d=inlfuncswithclosures=1 // Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style @@ -169,6 +169,7 @@ func k() (T, int, int) { return T{}, 0, 0 } // ERROR "can inline k" func _() { // ERROR "can inline _" T.meth(k()) // ERROR "inlining call to k" "inlining call to T.meth" + // ERRORAUTO "inlining call to T.meth" } func small1() { // ERROR "can inline small1" @@ -232,12 +233,13 @@ Loop: // Issue #18493 - make sure we can do inlining of functions with a method value type T1 struct{} -func (a T1) meth(val int) int { // ERROR "can inline T1.meth" "inlining call to T1.meth" +func (a T1) meth(val int) int { // ERROR "can inline T1.meth" return val + 5 } func getMeth(t1 T1) func(int) int { // ERROR "can inline getMeth" return t1.meth // ERROR "t1.meth escapes to heap" + // ERRORAUTO "inlining call to T1.meth" } func ii() { // ERROR "can inline ii" -- GitLab From a8861b907dc9d6fece2d515e45dc5091ffd4be63 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sun, 27 Jun 2021 22:10:03 +0700 Subject: [PATCH 0374/2500] [dev.typeparams] cmd/compile: port CL 330838 for -G=3 So next CL can move MethodValueWrapper to walk, since when walk is now the only place which uses this function. Change-Id: Id3be359bfc38efb022451cb7f9e53c2868fe7e12 Reviewed-on: https://go-review.googlesource.com/c/go/+/330840 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/noder/transform.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index 660c4a19e6..c3fa8042f2 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -594,7 +594,7 @@ func transformDot(n *ir.SelectorExpr, isCall bool) ir.Node { // Or did we successfully desugar all that at stencil time? return n } - n.SetType(typecheck.MethodValueWrapper(n).Type()) + n.SetType(typecheck.NewMethodType(n.Type(), nil)) } return n } -- GitLab From f99b3fe2ab6b142bc49b653c6547655cb7114625 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sun, 27 Jun 2021 22:25:21 +0700 Subject: [PATCH 0375/2500] [dev.typeparams] cmd/compile: move MethodValueWrapper to walk walk is the only pass that use the function, so un-export it, too. Change-Id: I32ec64d1c15fda7bb54bd8efa528ed32c102876d Reviewed-on: https://go-review.googlesource.com/c/go/+/330841 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/typecheck/func.go | 80 ---------------------- src/cmd/compile/internal/walk/closure.go | 80 +++++++++++++++++++++- 2 files changed, 79 insertions(+), 81 deletions(-) diff --git a/src/cmd/compile/internal/typecheck/func.go b/src/cmd/compile/internal/typecheck/func.go index f4fcfddcf1..5f9f8c6ebd 100644 --- a/src/cmd/compile/internal/typecheck/func.go +++ b/src/cmd/compile/internal/typecheck/func.go @@ -218,86 +218,6 @@ func fnpkg(fn *ir.Name) *types.Pkg { return fn.Sym().Pkg } -// MethodValueWrapper returns the DCLFUNC node representing the -// wrapper function (*-fm) needed for the given method value. If the -// wrapper function hasn't already been created yet, it's created and -// added to Target.Decls. -// -// TODO(mdempsky): Move into walk. This isn't part of type checking. -func MethodValueWrapper(dot *ir.SelectorExpr) *ir.Func { - if dot.Op() != ir.OMETHVALUE { - base.Fatalf("MethodValueWrapper: unexpected %v (%v)", dot, dot.Op()) - } - - t0 := dot.Type() - meth := dot.Sel - rcvrtype := dot.X.Type() - sym := ir.MethodSymSuffix(rcvrtype, meth, "-fm") - - if sym.Uniq() { - return sym.Def.(*ir.Func) - } - sym.SetUniq(true) - - savecurfn := ir.CurFunc - saveLineNo := base.Pos - ir.CurFunc = nil - - // Set line number equal to the line number where the method is declared. - if pos := dot.Selection.Pos; pos.IsKnown() { - base.Pos = pos - } - // Note: !dot.Selection.Pos.IsKnown() happens for method expressions where - // the method is implicitly declared. The Error method of the - // built-in error type is one such method. We leave the line - // number at the use of the method expression in this - // case. See issue 29389. - - tfn := ir.NewFuncType(base.Pos, nil, - NewFuncParams(t0.Params(), true), - NewFuncParams(t0.Results(), false)) - - fn := DeclFunc(sym, tfn) - fn.SetDupok(true) - fn.SetNeedctxt(true) - fn.SetWrapper(true) - - // Declare and initialize variable holding receiver. - ptr := ir.NewNameAt(base.Pos, Lookup(".this")) - ptr.Class = ir.PAUTOHEAP - ptr.SetType(rcvrtype) - ptr.Curfn = fn - ptr.SetIsClosureVar(true) - ptr.SetByval(true) - fn.ClosureVars = append(fn.ClosureVars, ptr) - - call := ir.NewCallExpr(base.Pos, ir.OCALL, ir.NewSelectorExpr(base.Pos, ir.OXDOT, ptr, meth), nil) - call.Args = ir.ParamNames(tfn.Type()) - call.IsDDD = tfn.Type().IsVariadic() - - var body ir.Node = call - if t0.NumResults() != 0 { - ret := ir.NewReturnStmt(base.Pos, nil) - ret.Results = []ir.Node{call} - body = ret - } - - fn.Body = []ir.Node{body} - FinishFuncBody() - - Func(fn) - // Need to typecheck the body of the just-generated wrapper. - // typecheckslice() requires that Curfn is set when processing an ORETURN. - ir.CurFunc = fn - Stmts(fn.Body) - sym.Def = fn - Target.Decls = append(Target.Decls, fn) - ir.CurFunc = savecurfn - base.Pos = saveLineNo - - return fn -} - // tcClosure typechecks an OCLOSURE node. It also creates the named // function associated with the closure. // TODO: This creation of the named function should probably really be done in a diff --git a/src/cmd/compile/internal/walk/closure.go b/src/cmd/compile/internal/walk/closure.go index f399a26689..a86ed2ab80 100644 --- a/src/cmd/compile/internal/walk/closure.go +++ b/src/cmd/compile/internal/walk/closure.go @@ -179,7 +179,7 @@ func walkMethodValue(n *ir.SelectorExpr, init *ir.Nodes) ir.Node { clos := ir.NewCompLitExpr(base.Pos, ir.OCOMPLIT, ir.TypeNode(typ), nil) clos.SetEsc(n.Esc()) - clos.List = []ir.Node{ir.NewUnaryExpr(base.Pos, ir.OCFUNC, typecheck.MethodValueWrapper(n).Nname), n.X} + clos.List = []ir.Node{ir.NewUnaryExpr(base.Pos, ir.OCFUNC, methodValueWrapper(n).Nname), n.X} addr := typecheck.NodAddr(clos) addr.SetEsc(n.Esc()) @@ -198,3 +198,81 @@ func walkMethodValue(n *ir.SelectorExpr, init *ir.Nodes) ir.Node { return walkExpr(cfn, init) } + +// methodValueWrapper returns the DCLFUNC node representing the +// wrapper function (*-fm) needed for the given method value. If the +// wrapper function hasn't already been created yet, it's created and +// added to typecheck.Target.Decls. +func methodValueWrapper(dot *ir.SelectorExpr) *ir.Func { + if dot.Op() != ir.OMETHVALUE { + base.Fatalf("methodValueWrapper: unexpected %v (%v)", dot, dot.Op()) + } + + t0 := dot.Type() + meth := dot.Sel + rcvrtype := dot.X.Type() + sym := ir.MethodSymSuffix(rcvrtype, meth, "-fm") + + if sym.Uniq() { + return sym.Def.(*ir.Func) + } + sym.SetUniq(true) + + savecurfn := ir.CurFunc + saveLineNo := base.Pos + ir.CurFunc = nil + + // Set line number equal to the line number where the method is declared. + if pos := dot.Selection.Pos; pos.IsKnown() { + base.Pos = pos + } + // Note: !dot.Selection.Pos.IsKnown() happens for method expressions where + // the method is implicitly declared. The Error method of the + // built-in error type is one such method. We leave the line + // number at the use of the method expression in this + // case. See issue 29389. + + tfn := ir.NewFuncType(base.Pos, nil, + typecheck.NewFuncParams(t0.Params(), true), + typecheck.NewFuncParams(t0.Results(), false)) + + fn := typecheck.DeclFunc(sym, tfn) + fn.SetDupok(true) + fn.SetNeedctxt(true) + fn.SetWrapper(true) + + // Declare and initialize variable holding receiver. + ptr := ir.NewNameAt(base.Pos, typecheck.Lookup(".this")) + ptr.Class = ir.PAUTOHEAP + ptr.SetType(rcvrtype) + ptr.Curfn = fn + ptr.SetIsClosureVar(true) + ptr.SetByval(true) + fn.ClosureVars = append(fn.ClosureVars, ptr) + + call := ir.NewCallExpr(base.Pos, ir.OCALL, ir.NewSelectorExpr(base.Pos, ir.OXDOT, ptr, meth), nil) + call.Args = ir.ParamNames(tfn.Type()) + call.IsDDD = tfn.Type().IsVariadic() + + var body ir.Node = call + if t0.NumResults() != 0 { + ret := ir.NewReturnStmt(base.Pos, nil) + ret.Results = []ir.Node{call} + body = ret + } + + fn.Body = []ir.Node{body} + typecheck.FinishFuncBody() + + typecheck.Func(fn) + // Need to typecheck the body of the just-generated wrapper. + // typecheckslice() requires that Curfn is set when processing an ORETURN. + ir.CurFunc = fn + typecheck.Stmts(fn.Body) + sym.Def = fn + typecheck.Target.Decls = append(typecheck.Target.Decls, fn) + ir.CurFunc = savecurfn + base.Pos = saveLineNo + + return fn +} -- GitLab From 1cfa89e5dc22906e18725a9e21890b78c62c720e Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Thu, 3 Jun 2021 15:09:39 -0400 Subject: [PATCH 0376/2500] [dev.fuzz] internal/fuzz: use scratch []byte for mutations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The mutator will now use a scratch []byte when mutating []byte and string types. I ran the following target locally: func FuzzBytesFromStringCmp(f *testing.F) { f.Fuzz(func(t *testing.T, a, b string) { bytes.Compare([]byte(a), []byte(b)) }) } Before the change, execs were <400/sec: === FUZZ FuzzBytesFromStringCmp fuzzing, elapsed: 3.0s, execs: 1090 (363/sec), workers: 8 ... fuzzing, elapsed: 6.0s, execs: 2290 (382/sec), workers: 8 ... fuzzing, elapsed: 9.0s, execs: 3491 (388/sec), workers: 8 ... fuzzing, elapsed: 12.0s, execs: 4691 (391/sec), workers: 8 ... fuzzing, elapsed: 15.0s, execs: 5869 (391/sec), workers: 8 ... fuzzing, elapsed: 18.0s, execs: 7056 (392/sec), workers: 8 ... After the change, the execs are ~6000/sec === FUZZ FuzzBytesFromStringCmp fuzzing, elapsed: 3.0s, execs: 155129 (51687/sec), workers: 8 ... fuzzing, elapsed: 6.0s, execs: 303710 (50606/sec), workers: 8 ... fuzzing, elapsed: 9.0s, execs: 454314 (50470/sec), workers: 8 ... fuzzing, elapsed: 12.0s, execs: 603212 (50262/sec), workers: 8 ... fuzzing, elapsed: 15.0s, execs: 756165 (50401/sec), workers: 8 ... fuzzing, elapsed: 18.0s, execs: 899293 (49955/sec), workers: 8 ... Which is comparable to the same target with two []byte as input: === FUZZ FuzzBytesCmp fuzzing, elapsed: 3.0s, execs: 152348 (50757/sec), workers: 8 ... fuzzing, elapsed: 6.0s, execs: 314386 (52387/sec), workers: 8 ... fuzzing, elapsed: 9.0s, execs: 487413 (54148/sec), workers: 8 ... fuzzing, elapsed: 12.0s, execs: 646886 (53901/sec), workers: 8 ... fuzzing, elapsed: 15.0s, execs: 814257 (54266/sec), workers: 8 ... fuzzing, elapsed: 18.0s, execs: 983214 (54619/sec), workers: 8 ... Benchark results: name old time/op new time/op delta MutatorBytes/1-8 7.70ms ± 3% 0.00ms ± 3% -99.99% (p=0.029 n=4+4) MutatorBytes/10-8 7.88ms ± 2% 0.00ms ± 6% -99.99% (p=0.029 n=4+4) MutatorBytes/100-8 7.87ms ± 1% 0.00ms ± 2% -99.99% (p=0.029 n=4+4) MutatorBytes/1000-8 8.11ms ± 5% 0.00ms ± 2% -99.99% (p=0.029 n=4+4) MutatorBytes/10000-8 8.11ms ± 4% 0.00ms ± 2% -99.99% (p=0.029 n=4+4) MutatorBytes/100000-8 8.28ms ±10% 0.00ms ± 4% -99.96% (p=0.029 n=4+4) MutatorString/1-8 7.89ms ± 5% 0.00ms ±17% -99.99% (p=0.029 n=4+4) MutatorString/10-8 7.91ms ± 4% 0.00ms ± 7% -99.99% (p=0.029 n=4+4) MutatorString/100-8 8.08ms ± 4% 0.00ms ± 7% -99.99% (p=0.029 n=4+4) MutatorString/1000-8 8.11ms ± 6% 0.00ms ±11% -99.99% (p=0.029 n=4+4) MutatorString/10000-8 8.04ms ± 7% 0.00ms ± 8% -99.98% (p=0.029 n=4+4) MutatorString/100000-8 8.24ms ± 7% 0.01ms ±13% -99.82% (p=0.029 n=4+4) Fixes #46543 Change-Id: I8b078ed3adc1bb6310c33afc49bb6cd78e7e976c Reviewed-on: https://go-review.googlesource.com/c/go/+/324849 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Roland Shoemaker Reviewed-by: Jay Conrod --- src/internal/fuzz/mutator.go | 34 +++++++++++++++++++------------ src/internal/fuzz/mutator_test.go | 11 +++++----- src/testing/fuzz.go | 13 ++++++++++-- 3 files changed, 38 insertions(+), 20 deletions(-) diff --git a/src/internal/fuzz/mutator.go b/src/internal/fuzz/mutator.go index 2d7dbe6ed8..9aa56782b0 100644 --- a/src/internal/fuzz/mutator.go +++ b/src/internal/fuzz/mutator.go @@ -13,7 +13,8 @@ import ( ) type mutator struct { - r mutatorRand + r mutatorRand + scratch []byte // scratch slice to avoid additional allocations } func newMutator() *mutator { @@ -95,27 +96,34 @@ func (m *mutator) mutate(vals []interface{}, maxBytes int) { case byte: // uint8 vals[i] = byte(m.mutateUInt(uint64(v), math.MaxUint8)) case string: - // TODO(jayconrod,katiehockman): Keep a []byte somewhere (maybe in - // mutator) that we mutate repeatedly to avoid re-allocating the data - // every time. if len(v) > maxPerVal { panic(fmt.Sprintf("cannot mutate bytes of length %d", len(v))) } - b := []byte(v) - if cap(b) < maxPerVal { - b = append(make([]byte, 0, maxPerVal), b...) + if cap(m.scratch) < maxPerVal { + m.scratch = append(make([]byte, 0, maxPerVal), v...) + } else { + m.scratch = m.scratch[:len(v)] + copy(m.scratch, v) } - m.mutateBytes(&b) - vals[i] = string(b) + m.mutateBytes(&m.scratch) + var s string + shdr := (*reflect.StringHeader)(unsafe.Pointer(&s)) + bhdr := (*reflect.SliceHeader)(unsafe.Pointer(&m.scratch)) + shdr.Data = bhdr.Data + shdr.Len = bhdr.Len + vals[i] = s case []byte: if len(v) > maxPerVal { panic(fmt.Sprintf("cannot mutate bytes of length %d", len(v))) } - if cap(v) < maxPerVal { - v = append(make([]byte, 0, maxPerVal), v...) + if cap(m.scratch) < maxPerVal { + m.scratch = append(make([]byte, 0, maxPerVal), v...) + } else { + m.scratch = m.scratch[:len(v)] + copy(m.scratch, v) } - m.mutateBytes(&v) - vals[i] = v + m.mutateBytes(&m.scratch) + vals[i] = m.scratch default: panic(fmt.Sprintf("type not supported for mutating: %T", vals[i])) } diff --git a/src/internal/fuzz/mutator_test.go b/src/internal/fuzz/mutator_test.go index 5fcfb27c16..ee2912dfd2 100644 --- a/src/internal/fuzz/mutator_test.go +++ b/src/internal/fuzz/mutator_test.go @@ -15,6 +15,7 @@ func BenchmarkMutatorBytes(b *testing.B) { origEnv := os.Getenv("GODEBUG") defer func() { os.Setenv("GODEBUG", origEnv) }() os.Setenv("GODEBUG", fmt.Sprintf("%s,fuzzseed=123", origEnv)) + m := newMutator() for _, size := range []int{ 1, @@ -24,7 +25,6 @@ func BenchmarkMutatorBytes(b *testing.B) { 10000, 100000, } { - size := size b.Run(strconv.Itoa(size), func(b *testing.B) { buf := make([]byte, size) b.ResetTimer() @@ -32,7 +32,7 @@ func BenchmarkMutatorBytes(b *testing.B) { for i := 0; i < b.N; i++ { // resize buffer to the correct shape and reset the PCG buf = buf[0:size] - m := newMutator() + m.r = newPcgRand() m.mutate([]interface{}{buf}, workerSharedMemSize) } }) @@ -43,6 +43,7 @@ func BenchmarkMutatorString(b *testing.B) { origEnv := os.Getenv("GODEBUG") defer func() { os.Setenv("GODEBUG", origEnv) }() os.Setenv("GODEBUG", fmt.Sprintf("%s,fuzzseed=123", origEnv)) + m := newMutator() for _, size := range []int{ 1, @@ -52,7 +53,6 @@ func BenchmarkMutatorString(b *testing.B) { 10000, 100000, } { - size := size b.Run(strconv.Itoa(size), func(b *testing.B) { buf := make([]byte, size) b.ResetTimer() @@ -60,7 +60,7 @@ func BenchmarkMutatorString(b *testing.B) { for i := 0; i < b.N; i++ { // resize buffer to the correct shape and reset the PCG buf = buf[0:size] - m := newMutator() + m.r = newPcgRand() m.mutate([]interface{}{string(buf)}, workerSharedMemSize) } }) @@ -71,6 +71,7 @@ func BenchmarkMutatorAllBasicTypes(b *testing.B) { origEnv := os.Getenv("GODEBUG") defer func() { os.Setenv("GODEBUG", origEnv) }() os.Setenv("GODEBUG", fmt.Sprintf("%s,fuzzseed=123", origEnv)) + m := newMutator() types := []interface{}{ []byte(""), @@ -92,7 +93,7 @@ func BenchmarkMutatorAllBasicTypes(b *testing.B) { for _, t := range types { b.Run(fmt.Sprintf("%T", t), func(b *testing.B) { for i := 0; i < b.N; i++ { - m := newMutator() + m.r = newPcgRand() m.mutate([]interface{}{t}, workerSharedMemSize) } }) diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 55e5397193..d62eb55dec 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -258,9 +258,18 @@ var supportedTypes = map[reflect.Type]bool{ // Fuzz runs the fuzz function, ff, for fuzz testing. If ff fails for a set of // arguments, those arguments will be added to the seed corpus. // +// ff must be a function with no return value whose first argument is *T and +// whose remaining arguments are the types to be fuzzed. +// For example: +// +// f.Fuzz(func(t *testing.T, b []byte, i int) { ... }) +// +// This function should be fast, deterministic, and stateless. +// None of the pointers to any input data should be retained between executions. +// // This is a terminal function which will terminate the currently running fuzz -// target by calling runtime.Goexit. To run any code after this function, use -// Cleanup. +// target by calling runtime.Goexit. +// To run any code after fuzzing stops, use (*F).Cleanup. func (f *F) Fuzz(ff interface{}) { if f.fuzzCalled { panic("testing: F.Fuzz called more than once") -- GitLab From 64e6c75924a57306d8009cef4802b0b9ca4b7891 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 28 Jun 2021 11:50:26 -0700 Subject: [PATCH 0377/2500] [dev.typeparams] cmd/compile: port fix for issue46725 to transform.go Allow fix for issue46725 to work for -G=3 mode. Change-Id: Id522fbc2278cf878cb3f95b3205a2122c164ae29 Reviewed-on: https://go-review.googlesource.com/c/go/+/331470 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/noder/transform.go | 14 +++++++++++++- src/cmd/compile/internal/typecheck/stmt.go | 2 +- src/cmd/compile/internal/typecheck/typecheck.go | 6 +++--- test/run.go | 1 - 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index c3fa8042f2..7a685c4b47 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -329,8 +329,20 @@ assignOK: r.Use = ir.CallUseList rtyp := r.Type() + mismatched := false + failed := false for i := range lhs { - checkLHS(i, rtyp.Field(i).Type) + result := rtyp.Field(i).Type + checkLHS(i, result) + + if lhs[i].Type() == nil || result == nil { + failed = true + } else if lhs[i] != ir.BlankNode && !types.Identical(lhs[i].Type(), result) { + mismatched = true + } + } + if mismatched && !failed { + typecheck.RewriteMultiValueCall(stmt, r) } return } diff --git a/src/cmd/compile/internal/typecheck/stmt.go b/src/cmd/compile/internal/typecheck/stmt.go index 54cf508acc..f1275f29c0 100644 --- a/src/cmd/compile/internal/typecheck/stmt.go +++ b/src/cmd/compile/internal/typecheck/stmt.go @@ -217,7 +217,7 @@ assignOK: } } if mismatched && !failed { - rewriteMultiValueCall(stmt, r) + RewriteMultiValueCall(stmt, r) } return } diff --git a/src/cmd/compile/internal/typecheck/typecheck.go b/src/cmd/compile/internal/typecheck/typecheck.go index f7de43c79f..232c0e66ef 100644 --- a/src/cmd/compile/internal/typecheck/typecheck.go +++ b/src/cmd/compile/internal/typecheck/typecheck.go @@ -962,12 +962,12 @@ func typecheckargs(n ir.InitNode) { } // Rewrite f(g()) into t1, t2, ... = g(); f(t1, t2, ...). - rewriteMultiValueCall(n, list[0]) + RewriteMultiValueCall(n, list[0]) } -// rewriteMultiValueCall rewrites multi-valued f() to use temporaries, +// RewriteMultiValueCall rewrites multi-valued f() to use temporaries, // so the backend wouldn't need to worry about tuple-valued expressions. -func rewriteMultiValueCall(n ir.InitNode, call ir.Node) { +func RewriteMultiValueCall(n ir.InitNode, call ir.Node) { // If we're outside of function context, then this call will // be executed during the generated init function. However, // init.go hasn't yet created it. Instead, associate the diff --git a/test/run.go b/test/run.go index ad92d8bb79..d04f7d20ed 100644 --- a/test/run.go +++ b/test/run.go @@ -2131,7 +2131,6 @@ var excludedFiles = map[string]bool{ "fixedbugs/issue4232.go": true, // types2 reports (correct) extra errors "fixedbugs/issue4452.go": true, // types2 reports (correct) extra errors "fixedbugs/issue4510.go": true, // types2 reports different (but ok) line numbers - "fixedbugs/issue46725.go": true, // fix applied to typecheck needs to be ported to irgen/transform "fixedbugs/issue5609.go": true, // types2 needs a better error message "fixedbugs/issue7525b.go": true, // types2 reports init cycle error on different line - ok otherwise "fixedbugs/issue7525c.go": true, // types2 reports init cycle error on different line - ok otherwise -- GitLab From dfa8fd861ca99614f03ce409584c4f9ea3e6a3da Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 28 Jun 2021 10:57:26 -0700 Subject: [PATCH 0378/2500] [dev.typeparams] cmd/compile: add a field (method) name for function in TestABIUtilsInterfaces Not having a field name for the method is not really correct, and makes it look like an embedded field. In fact, currently types.CalcSize() in abitest() is creating an error that is not actually reported. Change-Id: I98c3a4abf5b6d610d9c3c56ce1042078374b5417 Reviewed-on: https://go-review.googlesource.com/c/go/+/331469 Run-TryBot: Dan Scales TryBot-Result: Go Bot Trust: Dan Scales Reviewed-by: Than McIntosh --- src/cmd/compile/internal/test/abiutils_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/test/abiutils_test.go b/src/cmd/compile/internal/test/abiutils_test.go index b752c48612..b7901be69b 100644 --- a/src/cmd/compile/internal/test/abiutils_test.go +++ b/src/cmd/compile/internal/test/abiutils_test.go @@ -310,7 +310,7 @@ func TestABIUtilsInterfaces(t *testing.T) { pei := types.NewPtr(ei) // *interface{} fldt := mkFuncType(types.FakeRecvType(), []*types.Type{}, []*types.Type{types.UntypedString}) - field := types.NewField(src.NoXPos, nil, fldt) + field := types.NewField(src.NoXPos, typecheck.Lookup("f"), fldt) nei := types.NewInterface(types.LocalPkg, []*types.Field{field}) i16 := types.Types[types.TINT16] tb := types.Types[types.TBOOL] @@ -322,12 +322,12 @@ func TestABIUtilsInterfaces(t *testing.T) { IN 0: R{ I0 I1 I2 } spilloffset: 0 typ: struct { int16; int16; bool } IN 1: R{ I3 I4 } spilloffset: 8 typ: interface {} IN 2: R{ I5 I6 } spilloffset: 24 typ: interface {} - IN 3: R{ I7 I8 } spilloffset: 40 typ: interface { () untyped string } + IN 3: R{ I7 I8 } spilloffset: 40 typ: interface { .f() untyped string } IN 4: R{ } offset: 0 typ: *interface {} - IN 5: R{ } offset: 8 typ: interface { () untyped string } + IN 5: R{ } offset: 8 typ: interface { .f() untyped string } IN 6: R{ } offset: 24 typ: int16 OUT 0: R{ I0 I1 } spilloffset: -1 typ: interface {} - OUT 1: R{ I2 I3 } spilloffset: -1 typ: interface { () untyped string } + OUT 1: R{ I2 I3 } spilloffset: -1 typ: interface { .f() untyped string } OUT 2: R{ I4 } spilloffset: -1 typ: *interface {} offsetToSpillArea: 32 spillAreaSize: 56 `) -- GitLab From 5fa6bbc669c22f05deb421c324b90b30ae3caa08 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Sat, 26 Jun 2021 18:18:16 -0700 Subject: [PATCH 0379/2500] [dev.typeparams] cmd/compile: clean up instantiation and dictionary naming Separate generation of instantiation and dictionary name generation. Add code to add subdictionaries to a dictionary. Not quite working yet, as we need to trigger generation of the subdictionaries for methods. Change-Id: I0d46053eba695b217630b06ef2f990f6a0b52d83 Reviewed-on: https://go-review.googlesource.com/c/go/+/331209 Trust: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 55 +++++++++---------- .../compile/internal/reflectdata/reflect.go | 22 ++------ src/cmd/compile/internal/typecheck/subr.go | 51 ++++++++++++----- 3 files changed, 68 insertions(+), 60 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 60d56c206f..49781ddc07 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -18,7 +18,6 @@ import ( "cmd/internal/src" "fmt" "go/constant" - "strings" ) func assert(p bool) { @@ -519,7 +518,7 @@ func (g *irgen) getInstantiation(nameNode *ir.Name, targs []*types.Type, isMeth ir.Dump(fmt.Sprintf("\nstenciled %v", st), st) } } - return st, g.getDictionary(sym.Name, nameNode, targs) + return st, g.getDictionaryValue(nameNode, targs, isMeth) } // Struct containing info needed for doing the substitution as we create the @@ -1017,31 +1016,21 @@ func deref(t *types.Type) *types.Type { return t } -// getDictionary returns the dictionary for the named instantiated function, which -// is instantiated from generic function or method gf, with the type arguments targs. -func (g *irgen) getDictionary(name string, gf *ir.Name, targs []*types.Type) ir.Node { +// getDictionarySym returns the dictionary for the named generic function gf, which +// is instantiated with the type arguments targs. +func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) *types.Sym { if len(targs) == 0 { - base.Fatalf("%s should have type arguments", name) - } - - // The dictionary for this instantiation is named after the function - // and concrete types it is instantiated with. - // TODO: decouple this naming from the instantiation naming. The instantiation - // naming will be based on GC shapes, this naming must be fully stenciled. - if !strings.HasPrefix(name, ".inst.") { - base.Fatalf("%s should start in .inst.", name) + base.Fatalf("%s should have type arguments", gf.Sym().Name) } info := g.getGfInfo(gf) - name = ".dict." + name[6:] - // Get a symbol representing the dictionary. - sym := typecheck.Lookup(name) + sym := typecheck.MakeDictName(gf.Sym(), targs, isMeth) // Initialize the dictionary, if we haven't yet already. if lsym := sym.Linksym(); len(lsym.P) == 0 { - infoPrint("Creating dictionary %v\n", name) + infoPrint("Creating dictionary %v\n", sym.Name) off := 0 // Emit an entry for each targ (concrete type or gcshape). for _, t := range targs { @@ -1061,8 +1050,8 @@ func (g *irgen) getDictionary(name string, gf *ir.Name, targs []*types.Type) ir. off = objw.SymPtr(lsym, off, s, 0) } // Emit an entry for each subdictionary (after substituting targs) - // TODO: actually emit symbol for the subdictionary entry for _, n := range info.subDictCalls { + var sym *types.Sym if n.Op() == ir.OCALL { call := n.(*ir.CallExpr) if call.X.Op() == ir.OXDOT { @@ -1071,8 +1060,7 @@ func (g *irgen) getDictionary(name string, gf *ir.Name, targs []*types.Type) ir. for i, t := range subtargs { s2targs[i] = subst.Typ(t) } - sym := typecheck.MakeInstName(ir.MethodSym(call.X.(*ir.SelectorExpr).X.Type(), call.X.(*ir.SelectorExpr).Sel), s2targs, true) - infoPrint(" - Subdict .dict.%v\n", sym.Name[6:]) + sym = typecheck.MakeDictName(ir.MethodSym(call.X.(*ir.SelectorExpr).X.Type(), call.X.(*ir.SelectorExpr).Sel), s2targs, true) } else { inst := n.(*ir.CallExpr).X.(*ir.InstExpr) var nameNode *ir.Name @@ -1087,11 +1075,10 @@ func (g *irgen) getDictionary(name string, gf *ir.Name, targs []*types.Type) ir. for i, t := range subtargs { subtargs[i] = subst.Typ(t) } - sym := typecheck.MakeInstName(nameNode.Sym(), subtargs, isMeth) + sym = g.getDictionarySym(nameNode, subtargs, isMeth) // TODO: This can actually be a static // main dictionary, if all of the subtargs // are concrete types (!HasTParam) - infoPrint(" - Subdict .dict.%v\n", sym.Name[6:]) } } else if n.Op() == ir.OFUNCINST { inst := n.(*ir.InstExpr) @@ -1100,11 +1087,10 @@ func (g *irgen) getDictionary(name string, gf *ir.Name, targs []*types.Type) ir. for i, t := range subtargs { subtargs[i] = subst.Typ(t) } - sym := typecheck.MakeInstName(nameNode.Sym(), subtargs, false) + sym = g.getDictionarySym(nameNode, subtargs, false) // TODO: This can actually be a static // main dictionary, if all of the subtargs // are concrete types (!HasTParam) - infoPrint(" - Subdict .dict.%v\n", sym.Name[6:]) } else if n.Op() == ir.OXDOT { selExpr := n.(*ir.SelectorExpr) subtargs := selExpr.X.Type().RParams() @@ -1112,13 +1098,26 @@ func (g *irgen) getDictionary(name string, gf *ir.Name, targs []*types.Type) ir. for i, t := range subtargs { s2targs[i] = subst.Typ(t) } - sym := typecheck.MakeInstName(ir.MethodSym(selExpr.X.Type(), selExpr.Sel), s2targs, true) - infoPrint(" - Subdict .dict.%v\n", sym.Name[6:]) + sym = typecheck.MakeDictName(ir.MethodSym(selExpr.X.Type(), selExpr.Sel), s2targs, true) + } + // TODO: handle closure cases that need sub-dictionaries, get rid of conditional + if sym != nil { + // TODO: uncomment once we're sure all the + // subdictionaries are created correctly. + // Methods above aren't yet generating dictionaries recursively yet. + //off = objw.SymPtr(lsym, off, sym.Linksym(), 0) + infoPrint(" - Subdict %v\n", sym.Name) } - // TODO: handle closure cases that need sub-dictionaries } objw.Global(lsym, int32(off), obj.DUPOK|obj.RODATA) + + // Add any new, fully instantiated types seen during the substitution to g.instTypeList. + g.instTypeList = append(g.instTypeList, subst.InstTypeList...) } + return sym +} +func (g *irgen) getDictionaryValue(gf *ir.Name, targs []*types.Type, isMeth bool) ir.Node { + sym := g.getDictionarySym(gf, targs, isMeth) // Make a node referencing the dictionary symbol. n := typecheck.NewName(sym) diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 351aaab399..27522ca85e 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -1869,7 +1869,7 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy } else if !baseOrig.IsPtr() && method.Type.Recv().Type.IsPtr() { baseOrig = types.NewPtr(baseOrig) } - args = append(args, getDictionary(".inst."+ir.MethodSym(baseOrig, method.Sym).Name, targs)) // TODO: remove .inst. + args = append(args, getDictionary(ir.MethodSym(baseOrig, method.Sym), targs)) if indirect { args = append(args, ir.NewStarExpr(base.Pos, dot.X)) } else if methodrcvr.IsPtr() && methodrcvr.Elem() == dot.X.Type() { @@ -1971,28 +1971,16 @@ func MarkUsedIfaceMethod(n *ir.CallExpr) { // getDictionary returns the dictionary for the given named generic function // or method, with the given type arguments. -// TODO: pass a reference to the generic function instead? We might need -// that to look up protodictionaries. -func getDictionary(name string, targs []*types.Type) ir.Node { +func getDictionary(gf *types.Sym, targs []*types.Type) ir.Node { if len(targs) == 0 { - base.Fatalf("%s should have type arguments", name) + base.Fatalf("%s should have type arguments", gf.Name) } - // The dictionary for this instantiation is named after the function - // and concrete types it is instantiated with. - // TODO: decouple this naming from the instantiation naming. The instantiation - // naming will be based on GC shapes, this naming must be fully stenciled. - if !strings.HasPrefix(name, ".inst.") { - base.Fatalf("%s should start in .inst.", name) - } - name = ".dict." + name[6:] - - // Get a symbol representing the dictionary. - sym := typecheck.Lookup(name) + sym := typecheck.MakeDictName(gf, targs, true) // Initialize the dictionary, if we haven't yet already. if lsym := sym.Linksym(); len(lsym.P) == 0 { - base.Fatalf("Dictionary should have alredy been generated: %v", sym) + base.Fatalf("Dictionary should have already been generated: %s.%s", sym.Pkg.Path, sym.Name) } // Make a node referencing the dictionary symbol. diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index fb6d660db5..db1faaf6f7 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -888,19 +888,10 @@ func TypesOf(x []ir.Node) []*types.Type { return r } -// MakeInstName makes the unique name for a stenciled generic function or method, -// based on the name of the function fnsym and the targs. It replaces any -// existing bracket type list in the name. makeInstName asserts that fnsym has -// brackets in its name if and only if hasBrackets is true. -// -// Names of declared generic functions have no brackets originally, so hasBrackets -// should be false. Names of generic methods already have brackets, since the new -// type parameter is specified in the generic type of the receiver (e.g. func -// (func (v *value[T]).set(...) { ... } has the original name (*value[T]).set. -// -// The standard naming is something like: 'genFn[int,bool]' for functions and -// '(*genType[int,bool]).methodName' for methods -func MakeInstName(fnsym *types.Sym, targs []*types.Type, hasBrackets bool) *types.Sym { +// makeGenericName returns the name of the generic function instantiated +// with the given types. +// name is the name of the generic function or method. +func makeGenericName(name string, targs []*types.Type, hasBrackets bool) string { b := bytes.NewBufferString("") // Determine if the type args are concrete types or new typeparams. @@ -922,7 +913,6 @@ func MakeInstName(fnsym *types.Sym, targs []*types.Type, hasBrackets bool) *type b.WriteString(".inst.") } - name := fnsym.Name i := strings.Index(name, "[") assert(hasBrackets == (i >= 0)) if i >= 0 { @@ -952,7 +942,38 @@ func MakeInstName(fnsym *types.Sym, targs []*types.Type, hasBrackets bool) *type if strings.HasPrefix(b.String(), ".inst..inst.") { panic(fmt.Sprintf("multiple .inst. prefix in %s", b.String())) } - return fnsym.Pkg.Lookup(b.String()) + return b.String() +} + +// MakeInstName makes the unique name for a stenciled generic function or method, +// based on the name of the function fnsym and the targs. It replaces any +// existing bracket type list in the name. makeInstName asserts that fnsym has +// brackets in its name if and only if hasBrackets is true. +// +// Names of declared generic functions have no brackets originally, so hasBrackets +// should be false. Names of generic methods already have brackets, since the new +// type parameter is specified in the generic type of the receiver (e.g. func +// (func (v *value[T]).set(...) { ... } has the original name (*value[T]).set. +// +// The standard naming is something like: 'genFn[int,bool]' for functions and +// '(*genType[int,bool]).methodName' for methods +func MakeInstName(gf *types.Sym, targs []*types.Type, hasBrackets bool) *types.Sym { + return gf.Pkg.Lookup(makeGenericName(gf.Name, targs, hasBrackets)) +} + +func MakeDictName(gf *types.Sym, targs []*types.Type, hasBrackets bool) *types.Sym { + for _, targ := range targs { + if targ.HasTParam() { + fmt.Printf("FUNCTION %s\n", gf.Name) + for _, targ := range targs { + fmt.Printf(" PARAM %+v\n", targ) + } + panic("dictionary should always have concrete type args") + } + } + name := makeGenericName(gf.Name, targs, hasBrackets) + name = ".dict." + name[6:] + return gf.Pkg.Lookup(name) } func assert(p bool) { -- GitLab From 6a5f7e8498b7cd53bb5461fbf777aa83aea067a8 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 8 Jun 2021 15:58:16 -0700 Subject: [PATCH 0380/2500] [dev.typeparams] cmd/compile: use dictionary entries for more conversion cases This CL handles I(x) where I is an interface type and x has typeparam type. Change-Id: Ib99de2b741d588947f5e0164255f6365e98acd8a Reviewed-on: https://go-review.googlesource.com/c/go/+/326189 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 79 ++++++++++++++++------- test/typeparam/ifaceconv.go | 9 ++- 2 files changed, 62 insertions(+), 26 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 49781ddc07..29ee863a71 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -838,7 +838,15 @@ func (subst *subster) node(n ir.Node) ir.Node { case ir.OTYPE: // Transform the conversion, now that we know the // type argument. - m = transformConvCall(m.(*ir.CallExpr)) + m = transformConvCall(call) + if m.Op() == ir.OCONVIFACE { + if srcType := x.(*ir.CallExpr).Args[0].Type(); srcType.IsTypeParam() { // TODO: or derived type + // Note: srcType uses x.Args[0], not m.X or call.Args[0], because + // we need the type before the type parameter -> type argument substitution. + c := m.(*ir.ConvExpr) + m = subst.convertUsingDictionary(c.Pos(), c.X, c.Type(), srcType) + } + } case ir.OMETHVALUE: // Redo the transformation of OXDOT, now that we @@ -919,30 +927,10 @@ func (subst *subster) node(n ir.Node) ir.Node { case ir.OCONVIFACE: x := x.(*ir.ConvExpr) - // TODO: handle converting from derived types. For now, just from naked - // type parameters. - if x.X.Type().IsTypeParam() { - // Load the actual runtime._type of the type parameter from the dictionary. - rt := subst.getDictionaryType(m.Pos(), x.X.Type()) - - // At this point, m is an interface type with a data word we want. - // But the type word represents a gcshape type, which we don't want. - // Replace with the instantiated type loaded from the dictionary. - m = ir.NewUnaryExpr(m.Pos(), ir.OIDATA, m) - typed(types.Types[types.TUNSAFEPTR], m) - m = ir.NewBinaryExpr(m.Pos(), ir.OEFACE, rt, m) - if !x.Type().IsEmptyInterface() { - // We just built an empty interface{}. Type it as such, - // then assert it to the required non-empty interface. - typed(types.NewInterface(types.LocalPkg, nil), m) - m = ir.NewTypeAssertExpr(m.Pos(), m, nil) - } - typed(x.Type(), m) - // TODO: we're throwing away the type word of the original version - // of m here (it would be OITAB(m)), which probably took some - // work to generate. Can we avoid generating it at all? - // (The linker will throw them away if not needed, so it would just - // save toolchain work, not binary size.) + // Note: x's argument is still typed as a type parameter. + // m's argument now has an instantiated type. + if t := x.X.Type(); t.IsTypeParam() { + m = subst.convertUsingDictionary(x.Pos(), m.(*ir.ConvExpr).X, m.Type(), t) } } return m @@ -951,6 +939,47 @@ func (subst *subster) node(n ir.Node) ir.Node { return edit(n) } +// convertUsingDictionary converts value v from generic type src to an interface type dst. +func (subst *subster) convertUsingDictionary(pos src.XPos, v ir.Node, dst, src *types.Type) ir.Node { + // TODO: handle converting from derived types. For now, just from naked + // type parameters. + if !src.IsTypeParam() { + base.Fatalf("source must be a type parameter %+v", src) + } + if !dst.IsInterface() { + base.Fatalf("can only convert type parameters to interfaces %+v -> %+v", src, dst) + } + // Load the actual runtime._type of the type parameter from the dictionary. + rt := subst.getDictionaryType(pos, src) + + // Convert value to an interface type, so the data field is what we want. + if !v.Type().IsInterface() { + v = ir.NewConvExpr(v.Pos(), ir.OCONVIFACE, nil, v) + typed(types.NewInterface(types.LocalPkg, nil), v) + } + + // At this point, v is an interface type with a data word we want. + // But the type word represents a gcshape type, which we don't want. + // Replace with the instantiated type loaded from the dictionary. + data := ir.NewUnaryExpr(pos, ir.OIDATA, v) + typed(types.Types[types.TUNSAFEPTR], data) + var i ir.Node = ir.NewBinaryExpr(pos, ir.OEFACE, rt, data) + if !dst.IsEmptyInterface() { + // We just built an empty interface{}. Type it as such, + // then assert it to the required non-empty interface. + typed(types.NewInterface(types.LocalPkg, nil), i) + i = ir.NewTypeAssertExpr(pos, i, nil) + } + typed(dst, i) + // TODO: we're throwing away the type word of the original version + // of m here (it would be OITAB(m)), which probably took some + // work to generate. Can we avoid generating it at all? + // (The linker will throw them away if not needed, so it would just + // save toolchain work, not binary size.) + return i + +} + func (subst *subster) namelist(l []*ir.Name) []*ir.Name { s := make([]*ir.Name, len(l)) for i, n := range l { diff --git a/test/typeparam/ifaceconv.go b/test/typeparam/ifaceconv.go index 0b0776815c..32c2dbe7c2 100644 --- a/test/typeparam/ifaceconv.go +++ b/test/typeparam/ifaceconv.go @@ -38,10 +38,14 @@ func h[T C](x T) interface{foo() int} { return i } func i[T C](x T) C { - var i C = x + var i C = x // conversion in assignment return i } +func j[T C](t T) C { + return C(t) // explicit conversion +} + func main() { if got, want := f[int](7), 7; got != want { panic(fmt.Sprintf("got %d want %d", got, want)) @@ -55,4 +59,7 @@ func main() { if got, want := i[myInt](7).foo(), 8; got != want { panic(fmt.Sprintf("got %d want %d", got, want)) } + if got, want := j[myInt](7).foo(), 8; got != want { + panic(fmt.Sprintf("got %d want %d", got, want)) + } } -- GitLab From f503740ccf6302ed13c7722ea50c6880a17703fb Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 28 Jun 2021 22:41:50 -0700 Subject: [PATCH 0381/2500] [dev.typeparams] cmd/compile: add derived-type dictionaries to unified IR This CL updates the unified IR export data serialization to explicitly and separately record the derived types used by a declaration. The readers currently just use this data to construct types/IR the same as before, but eventually we can use it for emitting GC-shape dictionaries. Change-Id: I7d67ad9b3f1fbe69664bf19e056bc94f73507220 Reviewed-on: https://go-review.googlesource.com/c/go/+/331829 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le Trust: Cuong Manh Le Trust: Matthew Dempsky --- src/cmd/compile/internal/noder/linker.go | 32 ++- src/cmd/compile/internal/noder/reader.go | 184 +++++++++-------- src/cmd/compile/internal/noder/reader2.go | 142 ++++++++----- src/cmd/compile/internal/noder/reloc.go | 1 + src/cmd/compile/internal/noder/unified.go | 2 +- src/cmd/compile/internal/noder/writer.go | 237 ++++++++++++++-------- 6 files changed, 378 insertions(+), 220 deletions(-) diff --git a/src/cmd/compile/internal/noder/linker.go b/src/cmd/compile/internal/noder/linker.go index 23e9446759..ed47a355d8 100644 --- a/src/cmd/compile/internal/noder/linker.go +++ b/src/cmd/compile/internal/noder/linker.go @@ -134,11 +134,15 @@ func (l *linker) relocObj(pr *pkgReader, idx int) int { } w := l.pw.newEncoderRaw(relocObj) - bside := l.pw.newEncoderRaw(relocObjExt) - assert(bside.idx == w.idx) + wext := l.pw.newEncoderRaw(relocObjExt) + wdict := l.pw.newEncoderRaw(relocObjDict) + l.decls[sym] = w.idx + assert(wext.idx == w.idx) + assert(wdict.idx == w.idx) l.relocCommon(pr, &w, relocObj, idx) + l.relocCommon(pr, &wdict, relocObjDict, idx) var obj *ir.Name if path == "" { @@ -153,18 +157,18 @@ func (l *linker) relocObj(pr *pkgReader, idx int) int { } if obj != nil { - bside.sync(syncObject1) + wext.sync(syncObject1) switch tag { case objFunc: - l.relocFuncExt(&bside, obj) + l.relocFuncExt(&wext, obj) case objType: - l.relocTypeExt(&bside, obj) + l.relocTypeExt(&wext, obj) case objVar: - l.relocVarExt(&bside, obj) + l.relocVarExt(&wext, obj) } - bside.flush() + wext.flush() } else { - l.relocCommon(pr, &bside, relocObjExt, idx) + l.relocCommon(pr, &wext, relocObjExt, idx) } return w.idx @@ -286,7 +290,17 @@ func (pr *pkgDecoder) peekObj(idx int) (string, string, codeObj, []int) { bounds := make([]int, r.len()) for i := range bounds { r.sync(syncType) - bounds[i] = r.reloc(relocType) + if r.bool() { + r.len() + } else { + r.reloc(relocType) + } + + // TODO(mdempsky): This result now needs to include the 'derived' + // bool too, but none of the callers currently depend on it + // anyway. Either fix it to be meaningful, or just get rid of it + // altogether. + bounds[i] = -1 } tag := codeObj(r.code(syncCodeObj)) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 66c0e99d11..4b42ae1ec3 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -54,14 +54,14 @@ func newPkgReader(pr pkgDecoder) *pkgReader { } type pkgReaderIndex struct { - pr *pkgReader - idx int - implicits []*types.Type + pr *pkgReader + idx int + dict *readerDict } func (pri pkgReaderIndex) asReader(k reloc, marker syncMarker) *reader { r := pri.pr.newReader(k, pri.idx, marker) - r.implicits = pri.implicits + r.dict = pri.dict return r } @@ -77,29 +77,10 @@ type reader struct { p *pkgReader - // Implicit and explicit type arguments in use for reading the - // current object. For example: - // - // func F[T any]() { - // type X[U any] struct { t T; u U } - // var _ X[string] - // } - // - // var _ = F[int] - // - // While instantiating F[int], we need to in turn instantiate - // X[string]. [int] and [string] are explicit type arguments for F - // and X, respectively; but [int] is also the implicit type - // arguments for X. - // - // (As an analogy to function literals, explicits are the function - // literal's formal parameters, while implicits are variables - // captured by the function literal.) - implicits []*types.Type - explicits []*types.Type - ext *reader + dict *readerDict + // TODO(mdempsky): The state below is all specific to reading // function bodies. It probably makes sense to split it out // separately so that it doesn't take up space in every reader @@ -135,6 +116,35 @@ type reader struct { inlvars, retvars ir.Nodes } +type readerDict struct { + // targs holds the implicit and explicit type arguments in use for + // reading the current object. For example: + // + // func F[T any]() { + // type X[U any] struct { t T; u U } + // var _ X[string] + // } + // + // var _ = F[int] + // + // While instantiating F[int], we need to in turn instantiate + // X[string]. [int] and [string] are explicit type arguments for F + // and X, respectively; but [int] is also the implicit type + // arguments for X. + // + // (As an analogy to function literals, explicits are the function + // literal's formal parameters, while implicits are variables + // captured by the function literal.) + targs []*types.Type + + // implicits counts how many of types within targs are implicit type + // arguments; the rest are explicit. + implicits int + + derivedReloc []int // reloc index of the derived type's descriptor + derived []*types.Type // slice of previously computed derived types +} + func (r *reader) setType(n ir.Node, typ *types.Type) { n.SetType(typ) n.SetTypecheck(1) @@ -283,17 +293,28 @@ func (r *reader) doPkg() *types.Pkg { func (r *reader) typ() *types.Type { r.sync(syncType) - return r.p.typIdx(r.reloc(relocType), r.implicits, r.explicits) + if r.bool() { + return r.p.typIdx(r.len(), r.dict) + } + return r.p.typIdx(r.reloc(relocType), nil) } -func (pr *pkgReader) typIdx(idx int, implicits, explicits []*types.Type) *types.Type { - if typ := pr.typs[idx]; typ != nil { +func (pr *pkgReader) typIdx(idx int, dict *readerDict) *types.Type { + var where **types.Type + if dict != nil { + where = &dict.derived[idx] + idx = dict.derivedReloc[idx] + } else { + where = &pr.typs[idx] + } + + if typ := *where; typ != nil { return typ } r := pr.newReader(relocType, idx, syncTypeIdx) - r.implicits = implicits - r.explicits = explicits + r.dict = dict + typ := r.doTyp() assert(typ != nil) @@ -336,21 +357,13 @@ func (pr *pkgReader) typIdx(idx int, implicits, explicits []*types.Type) *types. // // The idx 1, corresponding with type I was resolved successfully // after r.doTyp() call. - if typ := pr.typs[idx]; typ != nil { - return typ - } - // If we have type parameters, the type might refer to them, and it - // wouldn't be safe to reuse those in other contexts. So we - // conservatively avoid caching them in that case. - // - // TODO(mdempsky): If we're clever, we should be able to still cache - // types by tracking which type parameters are used. However, in my - // attempts so far, I haven't yet succeeded in being clever enough. - if !r.hasTypeParams() { - pr.typs[idx] = typ + if prev := *where; prev != nil { + return prev } + *where = typ + if !typ.IsUntyped() { types.CheckSize(typ) } @@ -372,11 +385,7 @@ func (r *reader) doTyp() *types.Type { return obj.Type() case typeTypeParam: - idx := r.len() - if idx < len(r.implicits) { - return r.implicits[idx] - } - return r.explicits[idx-len(r.implicits)] + return r.dict.targs[r.len()] case typeArray: len := int64(r.uint64()) @@ -490,7 +499,12 @@ func (r *reader) obj() ir.Node { explicits[i] = r.typ() } - return r.p.objIdx(idx, r.implicits, explicits) + var implicits []*types.Type + if r.dict != nil { + implicits = r.dict.targs + } + + return r.p.objIdx(idx, implicits, explicits) } func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node { @@ -499,14 +513,11 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node _, sym := r.qualifiedIdent() - // Middle dot indicates local defined type; see writer.sym. - // TODO(mdempsky): Come up with a better way to handle this. - if strings.Contains(sym.Name, "·") { - r.implicits = implicits - r.ext.implicits = implicits - } - r.explicits = explicits - r.ext.explicits = explicits + dict := &readerDict{} + r.dict = dict + r.ext.dict = dict + + r.typeParamBounds(sym, implicits, explicits) origSym := sym @@ -515,9 +526,17 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node return sym.Def.(ir.Node) } - r.typeParamBounds(origSym) tag := codeObj(r.code(syncCodeObj)) + { + rdict := pr.newReader(relocObjDict, idx, syncObject1) + r.dict.derivedReloc = make([]int, rdict.len()) + r.dict.derived = make([]*types.Type, len(r.dict.derivedReloc)) + for i := range r.dict.derived { + r.dict.derivedReloc[i] = rdict.reloc(relocType) + } + } + do := func(op ir.Op, hasTParams bool) *ir.Name { pos := r.pos() if hasTParams { @@ -542,7 +561,7 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node case objStub: if pri, ok := objReader[origSym]; ok { - return pri.pr.objIdx(pri.idx, pri.implicits, r.explicits) + return pri.pr.objIdx(pri.idx, nil, explicits) } if haveLegacyImports { assert(!r.hasTypeParams()) @@ -621,46 +640,50 @@ func (r *reader) mangle(sym *types.Sym) *types.Sym { var buf bytes.Buffer buf.WriteString(sym.Name) buf.WriteByte('[') - for i, targs := range [2][]*types.Type{r.implicits, r.explicits} { - if i > 0 && len(r.implicits) != 0 && len(r.explicits) != 0 { - buf.WriteByte(';') - } - for j, targ := range targs { - if j > 0 { + for i, targ := range r.dict.targs { + if i > 0 { + if i == r.dict.implicits { + buf.WriteByte(';') + } else { buf.WriteByte(',') } - // TODO(mdempsky): We need the linker to replace "" in the symbol - // names here. - buf.WriteString(targ.LinkString()) } + buf.WriteString(targ.LinkString()) } buf.WriteByte(']') return sym.Pkg.Lookup(buf.String()) } -func (r *reader) typeParamBounds(sym *types.Sym) { +func (r *reader) typeParamBounds(sym *types.Sym, implicits, explicits []*types.Type) { r.sync(syncTypeParamBounds) nimplicits := r.len() nexplicits := r.len() - if len(r.implicits) != nimplicits || len(r.explicits) != nexplicits { - base.Fatalf("%v has %v+%v params, but instantiated with %v+%v args", sym, nimplicits, nexplicits, len(r.implicits), len(r.explicits)) + if nimplicits > len(implicits) || nexplicits != len(explicits) { + base.Fatalf("%v has %v+%v params, but instantiated with %v+%v args", sym, nimplicits, nexplicits, len(implicits), len(explicits)) } + r.dict.targs = append(implicits[:nimplicits:nimplicits], explicits...) + r.dict.implicits = nimplicits + // For stenciling, we can just skip over the type parameters. - for range r.explicits { + for range r.dict.targs[r.dict.implicits:] { // Skip past bounds without actually evaluating them. r.sync(syncType) - r.reloc(relocType) + if r.bool() { + r.len() + } else { + r.reloc(relocType) + } } } func (r *reader) typeParamNames() { r.sync(syncTypeParamNames) - for range r.explicits { + for range r.dict.targs[r.dict.implicits:] { r.pos() r.localIdent() } @@ -729,7 +752,7 @@ func (r *reader) selector() (origPkg *types.Pkg, sym *types.Sym) { } func (r *reader) hasTypeParams() bool { - return len(r.implicits)+len(r.explicits) != 0 + return r.dict != nil && len(r.dict.targs) != 0 } // @@@ Compiler extensions @@ -776,10 +799,10 @@ func (r *reader) funcExt(name *ir.Name) { Cost: int32(r.len()), CanDelayResults: r.bool(), } - r.addBody(name.Func, r.explicits) + r.addBody(name.Func) } } else { - r.addBody(name.Func, r.explicits) + r.addBody(name.Func) } r.sync(syncEOF) } @@ -795,8 +818,7 @@ func (r *reader) typeExt(name *ir.Name) { // type descriptor is written out as DUPOK and method wrappers are // generated even for imported types. var targs []*types.Type - targs = append(targs, r.implicits...) - targs = append(targs, r.explicits...) + targs = append(targs, r.dict.targs...) typ.SetRParams(targs) } @@ -841,8 +863,8 @@ var bodyReader = map[*ir.Func]pkgReaderIndex{} // constructed. var todoBodies []*ir.Func -func (r *reader) addBody(fn *ir.Func, implicits []*types.Type) { - pri := pkgReaderIndex{r.p, r.reloc(relocBody), implicits} +func (r *reader) addBody(fn *ir.Func) { + pri := pkgReaderIndex{r.p, r.reloc(relocBody), r.dict} bodyReader[fn] = pri if r.curfn == nil { @@ -1565,7 +1587,7 @@ func (r *reader) funcLit() ir.Node { r.setType(cv, outer.Type()) } - r.addBody(fn, r.implicits) + r.addBody(fn) return fn.OClosure } diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index 174bd3f5bd..89f224d389 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -57,7 +57,21 @@ type reader2 struct { p *pkgReader2 - tparams []*types2.TypeName + dict *reader2Dict +} + +type reader2Dict struct { + bounds []reader2TypeBound + + tparams []*types2.TypeParam + + derivedReloc []int + derived []types2.Type +} + +type reader2TypeBound struct { + derived bool + boundIdx int } func (pr *pkgReader2) newReader(k reloc, idx int, marker syncMarker) *reader2 { @@ -163,28 +177,37 @@ func (r *reader2) doPkg() *types2.Package { func (r *reader2) typ() types2.Type { r.sync(syncType) - return r.p.typIdx(r.reloc(relocType), r.tparams) + if r.bool() { + return r.p.typIdx(r.len(), r.dict) + } + return r.p.typIdx(r.reloc(relocType), nil) } -func (pr *pkgReader2) typIdx(idx int, tparams []*types2.TypeName) types2.Type { - if typ := pr.typs[idx]; typ != nil { +func (pr *pkgReader2) typIdx(idx int, dict *reader2Dict) types2.Type { + var where *types2.Type + if dict != nil { + where = &dict.derived[idx] + idx = dict.derivedReloc[idx] + } else { + where = &pr.typs[idx] + } + + if typ := *where; typ != nil { return typ } r := pr.newReader(relocType, idx, syncTypeIdx) - r.tparams = tparams + r.dict = dict + typ := r.doTyp() assert(typ != nil) - if pr.typs[idx] != nil { - // See comment in pkgReader.typIdx. - return pr.typs[idx] - } - - if len(tparams) == 0 { - pr.typs[idx] = typ + // See comment in pkgReader.typIdx explaining how this happens. + if prev := *where; prev != nil { + return prev } + *where = typ return typ } @@ -206,8 +229,7 @@ func (r *reader2) doTyp() (res types2.Type) { return name.Type() case typeTypeParam: - idx := r.len() - return r.tparams[idx].Type().(*types2.TypeParam) + return r.dict.tparams[r.len()] case typeArray: len := int64(r.uint64()) @@ -330,10 +352,12 @@ func (r *reader2) obj() (types2.Object, []types2.Type) { func (pr *pkgReader2) objIdx(idx int) (*types2.Package, string) { r := pr.newReader(relocObj, idx, syncObject1) + r.dict = &reader2Dict{} + objPkg, objName := r.qualifiedIdent() assert(objName != "") - bounds := r.typeParamBounds() + r.typeParamBounds() tag := codeObj(r.code(syncCodeObj)) if tag == objStub { @@ -341,6 +365,15 @@ func (pr *pkgReader2) objIdx(idx int) (*types2.Package, string) { return objPkg, objName } + { + rdict := r.p.newReader(relocObjDict, idx, syncObject1) + r.dict.derivedReloc = make([]int, rdict.len()) + r.dict.derived = make([]types2.Type, len(r.dict.derivedReloc)) + for i := range r.dict.derived { + r.dict.derivedReloc[i] = rdict.reloc(relocType) + } + } + objPkg.Scope().InsertLazy(objName, func() types2.Object { switch tag { default: @@ -358,21 +391,16 @@ func (pr *pkgReader2) objIdx(idx int) (*types2.Package, string) { case objFunc: pos := r.pos() - r.typeParamNames(bounds) + tparams := r.typeParamNames() sig := r.signature(nil) - if len(r.tparams) != 0 { - sig.SetTParams(r.tparams) - } + sig.SetTParams(tparams) return types2.NewFunc(pos, objPkg, objName, sig) case objType: pos := r.pos() return types2.NewTypeNameLazy(pos, objPkg, objName, func(named *types2.Named) (tparams []*types2.TypeName, underlying types2.Type, methods []*types2.Func) { - r.typeParamNames(bounds) - if len(r.tparams) != 0 { - tparams = r.tparams - } + tparams = r.typeParamNames() // TODO(mdempsky): Rewrite receiver types to underlying is an // Interface? The go/types importer does this (I think because @@ -382,7 +410,7 @@ func (pr *pkgReader2) objIdx(idx int) (*types2.Package, string) { methods = make([]*types2.Func, r.len()) for i := range methods { - methods[i] = r.method(bounds) + methods[i] = r.method() } return @@ -403,51 +431,73 @@ func (r *reader2) value() (types2.Type, constant.Value) { return r.typ(), r.rawValue() } -func (r *reader2) typeParamBounds() []int { +func (r *reader2) typeParamBounds() { r.sync(syncTypeParamBounds) - // exported types never have implicit type parameters - // TODO(mdempsky): Hide this from public importer. - assert(r.len() == 0) + if implicits := r.len(); implicits != 0 { + base.Fatalf("unexpected object with %v implicit type parameter(s)", implicits) + } - bounds := make([]int, r.len()) - for i := range bounds { + r.dict.bounds = make([]reader2TypeBound, r.len()) + for i := range r.dict.bounds { + b := &r.dict.bounds[i] r.sync(syncType) - bounds[i] = r.reloc(relocType) + b.derived = r.bool() + if b.derived { + b.boundIdx = r.len() + } else { + b.boundIdx = r.reloc(relocType) + } } - return bounds } -func (r *reader2) typeParamNames(bounds []int) { +func (r *reader2) typeParamNames() []*types2.TypeName { r.sync(syncTypeParamNames) - r.tparams = make([]*types2.TypeName, len(bounds)) + // Note: This code assumes it only processes objects without + // implement type parameters. This is currently fine, because + // reader2 is only used to read in exported declarations, which are + // always package scoped. + + if len(r.dict.bounds) == 0 { + return nil + } + + // Careful: Type parameter lists may have cycles. To allow for this, + // we construct the type parameter list in two passes: first we + // create all the TypeNames and TypeParams, then we construct and + // set the bound type. - for i := range r.tparams { + names := make([]*types2.TypeName, len(r.dict.bounds)) + r.dict.tparams = make([]*types2.TypeParam, len(r.dict.bounds)) + for i := range r.dict.bounds { pos := r.pos() pkg, name := r.localIdent() - obj := types2.NewTypeName(pos, pkg, name, nil) - r.p.check.NewTypeParam(obj, i, nil) - r.tparams[i] = obj + names[i] = types2.NewTypeName(pos, pkg, name, nil) + r.dict.tparams[i] = r.p.check.NewTypeParam(names[i], i, nil) } - for i, tparam := range r.tparams { - bound := r.p.typIdx(bounds[i], r.tparams) - tparam.Type().(*types2.TypeParam).SetBound(bound) + for i, bound := range r.dict.bounds { + var dict *reader2Dict + if bound.derived { + dict = r.dict + } + boundType := r.p.typIdx(bound.boundIdx, dict) + r.dict.tparams[i].SetBound(boundType) } + + return names } -func (r *reader2) method(bounds []int) *types2.Func { +func (r *reader2) method() *types2.Func { r.sync(syncMethod) pos := r.pos() pkg, name := r.selector() - r.typeParamNames(bounds) + rparams := r.typeParamNames() sig := r.signature(r.param()) - if len(r.tparams) != 0 { - sig.SetRParams(r.tparams) - } + sig.SetRParams(rparams) _ = r.pos() // TODO(mdempsky): Remove; this is a hacker for linker.go. return types2.NewFunc(pos, pkg, name, sig) diff --git a/src/cmd/compile/internal/noder/reloc.go b/src/cmd/compile/internal/noder/reloc.go index 961de49419..4eb6bcdb1c 100644 --- a/src/cmd/compile/internal/noder/reloc.go +++ b/src/cmd/compile/internal/noder/reloc.go @@ -34,6 +34,7 @@ const ( relocType relocObj relocObjExt + relocObjDict relocBody numRelocs = iota diff --git a/src/cmd/compile/internal/noder/unified.go b/src/cmd/compile/internal/noder/unified.go index 292fd13c67..8397f14be8 100644 --- a/src/cmd/compile/internal/noder/unified.go +++ b/src/cmd/compile/internal/noder/unified.go @@ -122,7 +122,7 @@ func unified(noders []*noder) { // Instantiated generic function: add to Decls for typechecking // and compilation. - if len(pri.implicits) != 0 && fn.OClosure == nil { + if pri.dict != nil && len(pri.dict.targs) != 0 && fn.OClosure == nil { target.Decls = append(target.Decls, fn) } } diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 04969100f0..6348a56741 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -87,20 +87,27 @@ type writer struct { // scope closes, and then maybe we can just use the same map for // storing the TypeParams too (as their TypeName instead). - // type parameters. explicitIdx has the type parameters declared on - // the current object, while implicitIdx has the type parameters - // declared on the enclosing object (if any). - // - // TODO(mdempsky): Merge these back together, now that I've got them - // working. - implicitIdx map[*types2.TypeParam]int - explicitIdx map[*types2.TypeParam]int - // variables declared within this function localsIdx map[*types2.Var]int closureVars []posObj closureVarsIdx map[*types2.Var]int + + dict *writerDict + derived bool +} + +// A writerDict tracks types and objects that are used by a declaration. +type writerDict struct { + implicits []*types2.TypeName + + // derived is a slice of type indices for computing derived types + // (i.e., types that depend on the declaration's type parameters). + derived []int + + // derivedIdx maps a Type to its corresponding index within the + // derived slice, if present. + derivedIdx map[types2.Type]int } func (pw *pkgWriter) newWriter(k reloc, marker syncMarker) *writer { @@ -193,30 +200,39 @@ func (pw *pkgWriter) pkgIdx(pkg *types2.Package) int { // @@@ Types func (w *writer) typ(typ types2.Type) { + idx, derived := w.p.typIdx(typ, w.dict) + w.sync(syncType) + if w.bool(derived) { + w.len(idx) + w.derived = true + } else { + w.reloc(relocType, idx) + } +} +// typIdx returns the index where the export data description of type +// can be read back in. If no such index exists yet, it's created. +// +// typIdx also reports whether typ is a derived type; that is, whether +// its identity depends on type parameters. +func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) (int, bool) { if quirksMode() { - typ = w.p.dups.orig(typ) + typ = pw.dups.orig(typ) } - w.reloc(relocType, w.p.typIdx(typ, w.implicitIdx, w.explicitIdx)) -} - -func (pw *pkgWriter) typIdx(typ types2.Type, implicitIdx, explicitIdx map[*types2.TypeParam]int) int { if idx, ok := pw.typsIdx[typ]; ok { - return idx + return idx, false + } + if dict != nil { + if idx, ok := dict.derivedIdx[typ]; ok { + return idx, true + } } w := pw.newWriter(relocType, syncTypeIdx) - w.implicitIdx = implicitIdx - w.explicitIdx = explicitIdx - - pw.typsIdx[typ] = w.idx // handle cycles - w.doTyp(typ) - return w.flush() -} + w.dict = dict -func (w *writer) doTyp(typ types2.Type) { switch typ := typ.(type) { default: base.Fatalf("unexpected type: %v (%T)", typ, typ) @@ -251,14 +267,19 @@ func (w *writer) doTyp(typ types2.Type) { w.obj(orig.Obj(), typ.TArgs()) case *types2.TypeParam: + index := func() int { + for idx, name := range w.dict.implicits { + if name.Type().(*types2.TypeParam) == typ { + return idx + } + } + + return len(w.dict.implicits) + typ.Index() + }() + + w.derived = true w.code(typeTypeParam) - if idx, ok := w.implicitIdx[typ]; ok { - w.len(idx) - } else if idx, ok := w.explicitIdx[typ]; ok { - w.len(len(w.implicitIdx) + idx) - } else { - w.p.fatalf(typ.Obj(), "%v not in %v or %v", typ, w.implicitIdx, w.explicitIdx) - } + w.len(index) case *types2.Array: w.code(typeArray) @@ -300,6 +321,16 @@ func (w *writer) doTyp(typ types2.Type) { w.code(typeUnion) w.unionType(typ) } + + if w.derived { + idx := len(dict.derived) + dict.derived = append(dict.derived, w.flush()) + dict.derivedIdx[typ] = idx + return idx, true + } + + pw.typsIdx[typ] = w.idx + return w.flush(), false } func (w *writer) structType(typ *types2.Struct) { @@ -367,13 +398,16 @@ func (w *writer) param(param *types2.Var) { // @@@ Objects func (w *writer) obj(obj types2.Object, explicits []types2.Type) { - w.sync(syncObject) - - var implicitIdx map[*types2.TypeParam]int - if isDefinedType(obj) && !isGlobal(obj) { - implicitIdx = w.implicitIdx + if isDefinedType(obj) && obj.Pkg() == w.p.curpkg { + decl, ok := w.p.typDecls[obj.(*types2.TypeName)] + assert(ok) + if len(decl.implicits) != 0 { + w.derived = true + } } - w.reloc(relocObj, w.p.objIdx(obj, implicitIdx)) + + w.sync(syncObject) + w.reloc(relocObj, w.p.objIdx(obj)) w.len(len(explicits)) for _, explicit := range explicits { @@ -381,37 +415,61 @@ func (w *writer) obj(obj types2.Object, explicits []types2.Type) { } } -func (pw *pkgWriter) objIdx(obj types2.Object, implicitIdx map[*types2.TypeParam]int) int { +func (pw *pkgWriter) objIdx(obj types2.Object) int { if idx, ok := pw.globalsIdx[obj]; ok { return idx } + dict := &writerDict{ + derivedIdx: make(map[types2.Type]int), + } + + if isDefinedType(obj) && obj.Pkg() == pw.curpkg { + decl, ok := pw.typDecls[obj.(*types2.TypeName)] + assert(ok) + dict.implicits = decl.implicits + } + w := pw.newWriter(relocObj, syncObject1) w.ext = pw.newWriter(relocObjExt, syncObject1) + wdict := pw.newWriter(relocObjDict, syncObject1) + + pw.globalsIdx[obj] = w.idx // break cycles assert(w.ext.idx == w.idx) + assert(wdict.idx == w.idx) + + w.dict = dict + w.ext.dict = dict - pw.globalsIdx[obj] = w.idx + // Ident goes first so importer can avoid unnecessary work if + // they've already resolved this object. + w.qualifiedIdent(obj) - w.implicitIdx = implicitIdx - w.ext.implicitIdx = implicitIdx + w.typeParamBounds(objTypeParams(obj)) w.doObj(obj) w.flush() w.ext.flush() + // Done writing out the object description; write out the list of + // derived types that we found along the way. + // + // TODO(mdempsky): Record details about how derived types are + // actually used so reader can optimize its runtime dictionaries. + // + // TODO(mdempsky): Record details about which instantiated functions + // are used too. + wdict.len(len(dict.derived)) + for _, typ := range dict.derived { + wdict.reloc(relocType, typ) + } + wdict.flush() + return w.idx } func (w *writer) doObj(obj types2.Object) { - // Ident goes first so importer can avoid unnecessary work if - // they've already resolved this object. - w.qualifiedIdent(obj) - - tparams := objTypeParams(obj) - w.setTypeParams(tparams) - w.typeParamBounds(tparams) - if obj.Pkg() != w.p.curpkg { w.code(objStub) return @@ -504,29 +562,12 @@ func (w *writer) value(typ types2.Type, val constant.Value) { w.rawValue(val) } -func (w *writer) setTypeParams(tparams []*types2.TypeName) { - if len(tparams) == 0 { - return - } - - explicitIdx := make(map[*types2.TypeParam]int) - for _, tparam := range tparams { - explicitIdx[tparam.Type().(*types2.TypeParam)] = len(explicitIdx) - } - - w.explicitIdx = explicitIdx - w.ext.explicitIdx = explicitIdx -} - func (w *writer) typeParamBounds(tparams []*types2.TypeName) { w.sync(syncTypeParamBounds) - // TODO(mdempsky): Remove. It's useful for debugging at the moment, - // but it doesn't belong here. - w.len(len(w.implicitIdx)) - w.len(len(w.explicitIdx)) - assert(len(w.explicitIdx) == len(tparams)) + w.len(len(w.dict.implicits)) + w.len(len(tparams)) for _, tparam := range tparams { w.typ(tparam.Type().(*types2.TypeParam).Bound()) } @@ -546,9 +587,6 @@ func (w *writer) method(meth *types2.Func) { assert(ok) sig := meth.Type().(*types2.Signature) - assert(len(w.explicitIdx) == len(sig.RParams())) - w.setTypeParams(sig.RParams()) - w.sync(syncMethod) w.pos(meth) w.selector(meth) @@ -566,11 +604,14 @@ func (w *writer) qualifiedIdent(obj types2.Object) { w.sync(syncSym) name := obj.Name() - if isDefinedType(obj) && !isGlobal(obj) { - // TODO(mdempsky): Find a better solution, this is terrible. + if isDefinedType(obj) && obj.Pkg() == w.p.curpkg { decl, ok := w.p.typDecls[obj.(*types2.TypeName)] assert(ok) - name = fmt.Sprintf("%s·%v", name, decl.gen) + if decl.gen != 0 { + // TODO(mdempsky): Find a better solution than embedding middle + // dot in the symbol name; this is terrible. + name = fmt.Sprintf("%s·%v", name, decl.gen) + } } w.pkg(obj.Pkg()) @@ -630,7 +671,7 @@ func (w *writer) funcExt(obj *types2.Func) { } sig, block := obj.Type().(*types2.Signature), decl.Body - body, closureVars := w.p.bodyIdx(w.p.curpkg, sig, block, w.explicitIdx) + body, closureVars := w.p.bodyIdx(w.p.curpkg, sig, block, w.dict) assert(len(closureVars) == 0) w.sync(syncFuncExt) @@ -672,9 +713,9 @@ func (w *writer) pragmaFlag(p ir.PragmaFlag) { // @@@ Function bodies -func (pw *pkgWriter) bodyIdx(pkg *types2.Package, sig *types2.Signature, block *syntax.BlockStmt, implicitIdx map[*types2.TypeParam]int) (idx int, closureVars []posObj) { +func (pw *pkgWriter) bodyIdx(pkg *types2.Package, sig *types2.Signature, block *syntax.BlockStmt, dict *writerDict) (idx int, closureVars []posObj) { w := pw.newWriter(relocBody, syncFuncBody) - w.implicitIdx = implicitIdx + w.dict = dict w.funcargs(sig) if w.bool(block != nil) { @@ -1238,14 +1279,13 @@ func (w *writer) funcLit(expr *syntax.FuncLit) { assert(ok) sig := tv.Type.(*types2.Signature) + body, closureVars := w.p.bodyIdx(w.p.curpkg, sig, expr.Body, w.dict) + w.sync(syncFuncLit) w.pos(expr) w.pos(expr.Type) // for QuirksMode w.signature(sig) - block := expr.Body - body, closureVars := w.p.bodyIdx(w.p.curpkg, sig, block, w.implicitIdx) - w.len(len(closureVars)) for _, cv := range closureVars { w.pos(cv.pos) @@ -1297,6 +1337,9 @@ func (w *writer) op(op ir.Op) { type typeDeclGen struct { *syntax.TypeDecl gen int + + // Implicit type parameters in scope at this type declaration. + implicits []*types2.TypeName } type fileImports struct { @@ -1308,6 +1351,19 @@ type declCollector struct { typegen *int file *fileImports withinFunc bool + implicits []*types2.TypeName +} + +func (c *declCollector) withTParams(obj types2.Object) *declCollector { + tparams := objTypeParams(obj) + if len(tparams) == 0 { + return c + } + + copy := *c + copy.implicits = copy.implicits[:len(copy.implicits):len(copy.implicits)] + copy.implicits = append(copy.implicits, objTypeParams(obj)...) + return © } func (c *declCollector) Visit(n syntax.Node) syntax.Visitor { @@ -1336,9 +1392,11 @@ func (c *declCollector) Visit(n syntax.Node) syntax.Visitor { obj := pw.info.Defs[n.Name].(*types2.Func) pw.funDecls[obj] = n + return c.withTParams(obj) + case *syntax.TypeDecl: obj := pw.info.Defs[n.Name].(*types2.TypeName) - d := typeDeclGen{TypeDecl: n} + d := typeDeclGen{TypeDecl: n, implicits: c.implicits} if n.Alias { pw.checkPragmas(n.Pragma, 0, false) @@ -1346,7 +1404,7 @@ func (c *declCollector) Visit(n syntax.Node) syntax.Visitor { pw.checkPragmas(n.Pragma, typePragmas, false) // Assign a unique ID to function-scoped defined types. - if !isGlobal(obj) { + if c.withinFunc { *c.typegen++ d.gen = *c.typegen } @@ -1354,6 +1412,12 @@ func (c *declCollector) Visit(n syntax.Node) syntax.Visitor { pw.typDecls[obj] = d + // TODO(mdempsky): Omit? Not strictly necessary; only matters for + // type declarations within function literals within parameterized + // type declarations, but types2 the function literals will be + // constant folded away. + return c.withTParams(obj) + case *syntax.VarDecl: pw.checkPragmas(n.Pragma, 0, true) @@ -1510,8 +1574,11 @@ func (w *writer) pkgDecl(decl syntax.Decl) { break // skip generic type decls } - name := w.p.info.Defs[decl.Name].(*types2.TypeName) + if decl.Name.Value == "_" { + break // skip blank type decls + } + name := w.p.info.Defs[decl.Name].(*types2.TypeName) // Skip type declarations for interfaces that are only usable as // type parameter bounds. if iface, ok := name.Type().Underlying().(*types2.Interface); ok && iface.IsConstraint() { @@ -1671,7 +1738,11 @@ func fieldIndex(info *types2.Info, str *types2.Struct, key *syntax.Name) int { func objTypeParams(obj types2.Object) []*types2.TypeName { switch obj := obj.(type) { case *types2.Func: - return obj.Type().(*types2.Signature).TParams() + sig := obj.Type().(*types2.Signature) + if sig.Recv() != nil { + return sig.RParams() + } + return sig.TParams() case *types2.TypeName: if !obj.IsAlias() { return obj.Type().(*types2.Named).TParams() -- GitLab From 4b5fdb0b7a362cb6fa6ad551757104e490483121 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 17 Jun 2021 17:49:15 -0700 Subject: [PATCH 0382/2500] [dev.typeparams] cmd/compile/internal/types2: introduce type set abstraction for interfaces With this change, interfaces are "completed" on-demand, when needed, and the respective information (set of all methods, type constraints) is recorded in a new typeSet data structure. As a consequence, interfaces don't need to be explicitly completed anymore and (internal) uses of interfaces have become much simpler. This change also introduces a new field Interface.complete to indicate that all methods and embedded elements have been set up. This prevent the computation and recording (!) of a partial type set for erroneous programs (if we compute the partial type set and store it, subsequent type set accesses use the wrong type set which may lead to follow-on errors). Change-Id: I1ffc907f7d0fb93b3e987fe5ff9c6fa5cae00d7f Reviewed-on: https://go-review.googlesource.com/c/go/+/329309 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/builtins.go | 2 +- src/cmd/compile/internal/types2/call.go | 1 - src/cmd/compile/internal/types2/expr.go | 1 - src/cmd/compile/internal/types2/infer.go | 27 ++-- src/cmd/compile/internal/types2/interface.go | 64 +++++----- src/cmd/compile/internal/types2/lookup.go | 17 +-- src/cmd/compile/internal/types2/predicates.go | 12 +- src/cmd/compile/internal/types2/sanitize.go | 8 +- .../compile/internal/types2/sizeof_test.go | 3 +- src/cmd/compile/internal/types2/subst.go | 15 ++- .../types2/testdata/check/cycles4.src | 15 ++- src/cmd/compile/internal/types2/type.go | 119 ++++++------------ src/cmd/compile/internal/types2/typeset.go | 70 +++++++++++ src/cmd/compile/internal/types2/typestring.go | 13 +- src/cmd/compile/internal/types2/typexpr.go | 8 +- src/cmd/compile/internal/types2/unify.go | 12 +- src/cmd/compile/internal/types2/universe.go | 4 +- 17 files changed, 205 insertions(+), 186 deletions(-) create mode 100644 src/cmd/compile/internal/types2/typeset.go diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 8f2d849ef5..ffe872e7ab 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -783,7 +783,7 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { tpar := NewTypeName(nopos, check.pkg, "", nil) ptyp := check.NewTypeParam(tpar, 0, &emptyInterface) // assigns type to tpar as a side-effect tsum := newUnion(rtypes, tildes) - ptyp.bound = &Interface{allMethods: markComplete, allTypes: tsum} + ptyp.bound = &Interface{complete: true, tset: &TypeSet{types: tsum}} return ptyp } diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 8c717cd1e5..8c17a2f808 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -99,7 +99,6 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { check.expr(x, call.ArgList[0]) if x.mode != invalid { if t := asInterface(T); t != nil { - check.completeInterface(nopos, t) if t.IsConstraint() { check.errorf(call, "cannot use interface %s in conversion (contains type list or is comparable)", T) break diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index d1cb27de16..7fba179e44 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -735,7 +735,6 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const // Update operand types to the default type rather than the target // (interface) type: values must have concrete dynamic types. // Untyped nil was handled upfront. - check.completeInterface(nopos, t) if !t.Empty() { return nil, nil, _InvalidUntypedConversion // cannot assign untyped values to non-empty interfaces } diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index 63cd63aacc..791e25e9f0 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -321,24 +321,13 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { return w.isParameterized(t.params) || w.isParameterized(t.results) case *Interface: - if t.allMethods != nil { - // interface is complete - quick test - for _, m := range t.allMethods { - if w.isParameterized(m.typ) { - return true - } + tset := t.typeSet() + for _, m := range tset.methods { + if w.isParameterized(m.typ) { + return true } - return w.isParameterized(t.allTypes) } - - return t.iterate(func(t *Interface) bool { - for _, m := range t.methods { - if w.isParameterized(m.typ) { - return true - } - } - return w.isParameterizedList(t.embeddeds) - }, nil) + return w.isParameterized(tset.types) case *Map: return w.isParameterized(t.key) || w.isParameterized(t.elem) @@ -476,15 +465,15 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty // structuralType returns the structural type of a constraint, if any. func (check *Checker) structuralType(constraint Type) Type { if iface, _ := under(constraint).(*Interface); iface != nil { - check.completeInterface(nopos, iface) - if u, _ := iface.allTypes.(*Union); u != nil { + types := iface.typeSet().types + if u, _ := types.(*Union); u != nil { if u.NumTerms() == 1 { // TODO(gri) do we need to respect tilde? return u.types[0] } return nil } - return iface.allTypes + return types } return nil } diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index c79026f00d..4dee923422 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -95,9 +95,13 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType check.posMap[ityp] = append(check.posMap[ityp], tlist[0].(*syntax.Operation).X.Pos()) } + // All methods and embedded elements for this interface are collected; + // i.e., this interface is may be used in a type set computation. + ityp.complete = true + if len(ityp.methods) == 0 && len(ityp.embeddeds) == 0 { // empty interface - ityp.allMethods = markComplete + ityp.tset = &topTypeSet return } @@ -105,7 +109,10 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType sortMethods(ityp.methods) sortTypes(ityp.embeddeds) - check.later(func() { check.completeInterface(iface.Pos(), ityp) }) + // Compute type set with a non-nil *Checker as soon as possible + // to report any errors. Subsequent uses of type sets should be + // using this computed type set and won't need to pass in a *Checker. + check.later(func() { newTypeSet(check, iface.Pos(), ityp) }) } func flattenUnion(list []syntax.Expr, x syntax.Expr) []syntax.Expr { @@ -116,26 +123,27 @@ func flattenUnion(list []syntax.Expr, x syntax.Expr) []syntax.Expr { return append(list, x) } -func (check *Checker) completeInterface(pos syntax.Pos, ityp *Interface) { - if ityp.allMethods != nil { - return +// newTypeSet may be called with check == nil. +// TODO(gri) move this function into typeset.go eventually +func newTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *TypeSet { + if ityp.tset != nil { + return ityp.tset } - // completeInterface may be called via the LookupFieldOrMethod, - // MissingMethod, Identical, or IdenticalIgnoreTags external API - // in which case check will be nil. In this case, type-checking - // must be finished and all interfaces should have been completed. - if check == nil { - panic("internal error: incomplete interface") + // If the interface is not fully set up yet, the type set will + // not be complete, which may lead to errors when using the the + // type set (e.g. missing method). Don't compute a partial type + // set (and don't store it!), so that we still compute the full + // type set eventually. Instead, return the top type set and + // let any follow-on errors play out. + // + // TODO(gri) Consider recording when this happens and reporting + // it as an error (but only if there were no other errors so to + // to not have unnecessary follow-on errors). + if !ityp.complete { + return &topTypeSet } - completeInterface(check, pos, ityp) -} - -// completeInterface may be called with check == nil. -func completeInterface(check *Checker, pos syntax.Pos, ityp *Interface) { - assert(ityp.allMethods == nil) - if check != nil && check.conf.Trace { // Types don't generally have position information. // If we don't have a valid pos provided, try to use @@ -144,11 +152,11 @@ func completeInterface(check *Checker, pos syntax.Pos, ityp *Interface) { pos = ityp.methods[0].pos } - check.trace(pos, "complete %s", ityp) + check.trace(pos, "type set for %s", ityp) check.indent++ defer func() { check.indent-- - check.trace(pos, "=> %s (methods = %v, types = %v)", ityp, ityp.allMethods, ityp.allTypes) + check.trace(pos, "=> %s ", ityp.typeSet()) }() } @@ -157,7 +165,7 @@ func completeInterface(check *Checker, pos syntax.Pos, ityp *Interface) { // have valid interfaces. Mark the interface as complete to avoid // infinite recursion if the validType check occurs later for some // reason. - ityp.allMethods = markComplete + ityp.tset = new(TypeSet) // TODO(gri) is this sufficient? // Methods of embedded interfaces are collected unchanged; i.e., the identity // of a method I.m's Func Object of an interface I is the same as that of @@ -231,13 +239,11 @@ func completeInterface(check *Checker, pos syntax.Pos, ityp *Interface) { var types Type switch t := under(typ).(type) { case *Interface: - if t.allMethods == nil { - completeInterface(check, pos, t) - } - for _, m := range t.allMethods { + tset := newTypeSet(check, pos, t) + for _, m := range tset.methods { addMethod(pos, m, false) // use embedding position pos rather than m.pos } - types = t.allTypes + types = tset.types case *Union: // TODO(gri) combine with default case once we have // converted all tests to new notation and we @@ -274,9 +280,11 @@ func completeInterface(check *Checker, pos syntax.Pos, ityp *Interface) { if methods != nil { sortMethods(methods) - ityp.allMethods = methods + ityp.tset.methods = methods } - ityp.allTypes = allTypes + ityp.tset.types = allTypes + + return ityp.tset } func sortTypes(list []Type) { diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index 93ed620449..9fcec44d53 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -182,9 +182,7 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack case *Interface: // look for a matching method - // TODO(gri) t.allMethods is sorted - use binary search - check.completeInterface(nopos, t) - if i, m := lookupMethod(t.allMethods, pkg, name); m != nil { + if i, m := t.typeSet().LookupMethod(pkg, name); m != nil { assert(m.typ != nil) index = concat(e.index, i) if obj != nil || e.multiples { @@ -195,7 +193,7 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack } case *TypeParam: - if i, m := lookupMethod(t.Bound().allMethods, pkg, name); m != nil { + if i, m := t.Bound().typeSet().LookupMethod(pkg, name); m != nil { assert(m.typ != nil) index = concat(e.index, i) if obj != nil || e.multiples { @@ -307,18 +305,15 @@ func MissingMethod(V Type, T *Interface, static bool) (method *Func, wrongType b // To improve error messages, also report the wrong signature // when the method exists on *V instead of V. func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, wrongType *Func) { - check.completeInterface(nopos, T) - // fast path for common case if T.Empty() { return } if ityp := asInterface(V); ityp != nil { - check.completeInterface(nopos, ityp) - // TODO(gri) allMethods is sorted - can do this more efficiently - for _, m := range T.allMethods { - _, f := lookupMethod(ityp.allMethods, m.pkg, m.name) + // TODO(gri) the methods are sorted - could do this more efficiently + for _, m := range T.typeSet().methods { + _, f := ityp.typeSet().LookupMethod(m.pkg, m.name) if f == nil { // if m is the magic method == we're ok (interfaces are comparable) @@ -356,7 +351,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // A concrete type implements T if it implements all methods of T. Vd, _ := deref(V) Vn := asNamed(Vd) - for _, m := range T.allMethods { + for _, m := range T.typeSet().methods { // TODO(gri) should this be calling lookupFieldOrMethod instead (and why not)? obj, _, _ := check.rawLookupFieldOrMethod(V, false, m.pkg, m.name) diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 66de249044..73af127188 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -287,16 +287,8 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { // the same names and identical function types. Lower-case method names from // different packages are always different. The order of the methods is irrelevant. if y, ok := y.(*Interface); ok { - // If identical0 is called (indirectly) via an external API entry point - // (such as Identical, IdenticalIgnoreTags, etc.), check is nil. But in - // that case, interfaces are expected to be complete and lazy completion - // here is not needed. - if check != nil { - check.completeInterface(nopos, x) - check.completeInterface(nopos, y) - } - a := x.allMethods - b := y.allMethods + a := x.typeSet().methods + b := y.typeSet().methods if len(a) == len(b) { // Interface types are the only types where cycles can occur // that are not "terminated" via named types; and such cycles diff --git a/src/cmd/compile/internal/types2/sanitize.go b/src/cmd/compile/internal/types2/sanitize.go index 406b46e574..3d2323a0a2 100644 --- a/src/cmd/compile/internal/types2/sanitize.go +++ b/src/cmd/compile/internal/types2/sanitize.go @@ -112,9 +112,11 @@ func (s sanitizer) typ(typ Type) Type { case *Interface: s.funcList(t.methods) s.typeList(t.embeddeds) - s.funcList(t.allMethods) - if allTypes := s.typ(t.allTypes); allTypes != t.allTypes { - t.allTypes = allTypes + // TODO(gri) do we need to sanitize type sets? + tset := t.typeSet() + s.funcList(tset.methods) + if types := s.typ(tset.types); types != tset.types { + tset.types = types } case *Map: diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go index 3cb162764c..0b1f7dacad 100644 --- a/src/cmd/compile/internal/types2/sizeof_test.go +++ b/src/cmd/compile/internal/types2/sizeof_test.go @@ -28,7 +28,7 @@ func TestSizeof(t *testing.T) { {Tuple{}, 12, 24}, {Signature{}, 44, 88}, {Union{}, 24, 48}, - {Interface{}, 52, 104}, + {Interface{}, 40, 80}, {Map{}, 16, 32}, {Chan{}, 12, 24}, {Named{}, 84, 160}, @@ -49,6 +49,7 @@ func TestSizeof(t *testing.T) { // Misc {Scope{}, 56, 96}, {Package{}, 40, 80}, + {TypeSet{}, 20, 40}, } for _, test := range tests { diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 3ef65c2e92..38bd07b8a2 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -136,6 +136,7 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, poslis // satisfies reports whether the type argument targ satisfies the constraint of type parameter // parameter tpar (after any of its type parameters have been substituted through smap). // A suitable error is reported if the result is false. +// TODO(gri) This should be a method of interfaces or type sets. func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap *substMap) bool { iface := tpar.Bound() if iface.Empty() { @@ -150,8 +151,7 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap // targ must implement iface (methods) // - check only if we have methods - check.completeInterface(nopos, iface) - if len(iface.allMethods) > 0 { + if iface.NumMethods() > 0 { // If the type argument is a pointer to a type parameter, the type argument's // method set is empty. // TODO(gri) is this what we want? (spec question) @@ -182,7 +182,7 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap } // targ's underlying type must also be one of the interface types listed, if any - if iface.allTypes == nil { + if iface.typeSet().types == nil { return true // nothing to do } @@ -190,7 +190,7 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap // list of iface types (i.e., the targ type list must be a non-empty subset of the iface types). if targ := asTypeParam(targ); targ != nil { targBound := targ.Bound() - if targBound.allTypes == nil { + if targBound.typeSet().types == nil { check.softErrorf(pos, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ) return false } @@ -198,7 +198,7 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap // TODO(gri) incorporate tilde information! if !iface.isSatisfiedBy(typ) { // TODO(gri) match this error message with the one below (or vice versa) - check.softErrorf(pos, "%s does not satisfy %s (%s type constraint %s not found in %s)", targ, tpar.bound, targ, typ, iface.allTypes) + check.softErrorf(pos, "%s does not satisfy %s (%s type constraint %s not found in %s)", targ, tpar.bound, targ, typ, iface.typeSet().types) return false } return true @@ -207,7 +207,7 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap // Otherwise, targ's type or underlying type must also be one of the interface types listed, if any. if !iface.isSatisfiedBy(targ) { - check.softErrorf(pos, "%s does not satisfy %s (%s not found in %s)", targ, tpar.bound, targ, iface.allTypes) + check.softErrorf(pos, "%s does not satisfy %s (%s not found in %s)", targ, tpar.bound, targ, iface.typeSet().types) return false } @@ -312,12 +312,11 @@ func (subst *subster) typ(typ Type) Type { methods, mcopied := subst.funcList(t.methods) embeddeds, ecopied := subst.typeList(t.embeddeds) if mcopied || ecopied { - iface := &Interface{methods: methods, embeddeds: embeddeds} + iface := &Interface{methods: methods, embeddeds: embeddeds, complete: t.complete} if subst.check == nil { panic("internal error: cannot instantiate interfaces yet") } subst.check.posMap[iface] = subst.check.posMap[t] // satisfy completeInterface requirement - subst.check.completeInterface(nopos, iface) return iface } diff --git a/src/cmd/compile/internal/types2/testdata/check/cycles4.src b/src/cmd/compile/internal/types2/testdata/check/cycles4.src index 445babca68..924aabf475 100644 --- a/src/cmd/compile/internal/types2/testdata/check/cycles4.src +++ b/src/cmd/compile/internal/types2/testdata/check/cycles4.src @@ -4,6 +4,8 @@ package p +import "unsafe" + // Check that all methods of T are collected before // determining the result type of m (which embeds // all methods of T). @@ -13,7 +15,7 @@ type T interface { E } -var _ = T.m(nil).m().e() +var _ int = T.m(nil).m().e() type E interface { e() int @@ -22,7 +24,7 @@ type E interface { // Check that unresolved forward chains are followed // (see also comment in resolver.go, checker.typeDecl). -var _ = C.m(nil).m().e() +var _ int = C.m(nil).m().e() type A B @@ -108,3 +110,12 @@ type Element interface { type Event interface { Target() Element } + +// Check that accessing an interface method too early doesn't lead +// to follow-on errors due to an incorrectly computed type set. + +type T8 interface { + m() [unsafe.Sizeof(T8.m /* ERROR undefined */ )]int +} + +var _ = T8.m // no error expected here diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 10cb651d0c..122e408ead 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -264,18 +264,20 @@ func (s *Signature) Variadic() bool { return s.variadic } // An Interface represents an interface type. type Interface struct { + obj Object // type name object defining this interface; or nil (for better error messages) methods []*Func // ordered list of explicitly declared methods - embeddeds []Type // ordered list of explicitly embedded types + embeddeds []Type // ordered list of explicitly embedded elements + complete bool // indicates that obj, methods, and embeddeds are set and type set can be computed - allMethods []*Func // ordered list of methods declared with or embedded in this interface (TODO(gri): replace with mset) - allTypes Type // intersection of all embedded and locally declared types (TODO(gri) need better field name) - - obj Object // type declaration defining this interface; or nil (for better error messages) + tset *TypeSet // type set described by this interface, computed lazily } +// typeSet returns the type set for interface t. +func (t *Interface) typeSet() *TypeSet { return newTypeSet(nil, nopos, t) } + // is reports whether interface t represents types that all satisfy f. func (t *Interface) is(f func(Type, bool) bool) bool { - switch t := t.allTypes.(type) { + switch t := t.typeSet().types.(type) { case nil, *top: // TODO(gri) should settle on top or nil to represent this case return false // we must have at least one type! (was bug) @@ -286,21 +288,14 @@ func (t *Interface) is(f func(Type, bool) bool) bool { } } -// emptyInterface represents the empty (completed) interface -var emptyInterface = Interface{allMethods: markComplete} - -// markComplete is used to mark an empty interface as completely -// set up by setting the allMethods field to a non-nil empty slice. -var markComplete = make([]*Func, 0) +// emptyInterface represents the empty interface +var emptyInterface = Interface{complete: true, tset: &topTypeSet} -// NewInterface returns a new (incomplete) interface for the given methods and embedded types. -// Each embedded type must have an underlying type of interface type. -// NewInterface takes ownership of the provided methods and may modify their types by setting -// missing receivers. To compute the method set of the interface, Complete must be called. +// NewInterface returns a new interface for the given methods and embedded types. +// NewInterface takes ownership of the provided methods and may modify their types +// by setting missing receivers. // -// Deprecated: Use NewInterfaceType instead which allows any (even non-defined) interface types -// to be embedded. This is necessary for interfaces that embed alias type names referring to -// non-defined (literal) interface types. +// Deprecated: Use NewInterfaceType instead which allows arbitrary embedded types. func NewInterface(methods []*Func, embeddeds []*Named) *Interface { tnames := make([]Type, len(embeddeds)) for i, t := range embeddeds { @@ -309,9 +304,9 @@ func NewInterface(methods []*Func, embeddeds []*Named) *Interface { return NewInterfaceType(methods, tnames) } -// NewInterfaceType returns a new (incomplete) interface for the given methods and embedded types. -// NewInterfaceType takes ownership of the provided methods and may modify their types by setting -// missing receivers. To compute the method set of the interface, Complete must be called. +// NewInterfaceType returns a new interface for the given methods and embedded types. +// NewInterfaceType takes ownership of the provided methods and may modify their types +// by setting missing receivers. func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface { if len(methods) == 0 && len(embeddeds) == 0 { return &emptyInterface @@ -331,6 +326,8 @@ func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface { typ.methods = methods typ.embeddeds = embeddeds + typ.complete = true + return typ } @@ -354,72 +351,27 @@ func (t *Interface) Embedded(i int) *Named { tname, _ := t.embeddeds[i].(*Named) func (t *Interface) EmbeddedType(i int) Type { return t.embeddeds[i] } // NumMethods returns the total number of methods of interface t. -// The interface must have been completed. -func (t *Interface) NumMethods() int { t.Complete(); return len(t.allMethods) } +func (t *Interface) NumMethods() int { return t.typeSet().NumMethods() } // Method returns the i'th method of interface t for 0 <= i < t.NumMethods(). // The methods are ordered by their unique Id. -// The interface must have been completed. -func (t *Interface) Method(i int) *Func { t.Complete(); return t.allMethods[i] } +func (t *Interface) Method(i int) *Func { return t.typeSet().Method(i) } // Empty reports whether t is the empty interface. -func (t *Interface) Empty() bool { - t.Complete() - return len(t.allMethods) == 0 && t.allTypes == nil -} - -// HasTypeList reports whether interface t has a type list, possibly from an embedded type. -func (t *Interface) HasTypeList() bool { - t.Complete() - return t.allTypes != nil -} +func (t *Interface) Empty() bool { return t.typeSet().IsTop() } // IsComparable reports whether interface t is or embeds the predeclared interface "comparable". -func (t *Interface) IsComparable() bool { - t.Complete() - _, m := lookupMethod(t.allMethods, nil, "==") - return m != nil -} +func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() } -// IsConstraint reports t.HasTypeList() || t.IsComparable(). -func (t *Interface) IsConstraint() bool { - return t.HasTypeList() || t.IsComparable() -} - -// iterate calls f with t and then with any embedded interface of t, recursively, until f returns true. -// iterate reports whether any call to f returned true. -// TODO(gri) This is now only used by infer.go - see if we can eliminate it. -func (t *Interface) iterate(f func(*Interface) bool, seen map[*Interface]bool) bool { - if f(t) { - return true - } - for _, e := range t.embeddeds { - // e should be an interface but be careful (it may be invalid) - if e := asInterface(e); e != nil { - // Cyclic interfaces such as "type E interface { E }" are not permitted - // but they are still constructed and we need to detect such cycles. - if seen[e] { - continue - } - if seen == nil { - seen = make(map[*Interface]bool) - } - seen[e] = true - if e.iterate(f, seen) { - return true - } - } - } - return false -} +// IsConstraint reports whether interface t is not just a method set. +func (t *Interface) IsConstraint() bool { return !t.typeSet().IsMethodSet() } // isSatisfiedBy reports whether interface t's type list is satisfied by the type typ. // If the type list is empty (absent), typ trivially satisfies the interface. // TODO(gri) This is not a great name. Eventually, we should have a more comprehensive // "implements" predicate. func (t *Interface) isSatisfiedBy(typ Type) bool { - t.Complete() - switch t := t.allTypes.(type) { + switch t := t.typeSet().types.(type) { case nil: return true // no type restrictions case *Union: @@ -430,15 +382,22 @@ func (t *Interface) isSatisfiedBy(typ Type) bool { } } -// Complete computes the interface's method set. It must be called by users of +// Complete computes the interface's type set. It must be called by users of // NewInterfaceType and NewInterface after the interface's embedded types are // fully defined and before using the interface type in any way other than to // form other types. The interface must not contain duplicate methods or a // panic occurs. Complete returns the receiver. +// +// Deprecated: Type sets are now computed lazily, on demand; this function +// is only here for backward-compatibility. It does not have to +// be called explicitly anymore. func (t *Interface) Complete() *Interface { - if t.allMethods == nil { - completeInterface(nil, nopos, t) - } + // Some tests are still depending on the state change + // (string representation of an Interface not containing an + // /* incomplete */ marker) caused by the explicit Complete + // call, so we compute the type set eagerly here. + t.complete = true + t.typeSet() return t } @@ -674,7 +633,7 @@ func (t *TypeParam) Bound() *Interface { pos = n.obj.pos } // TODO(gri) switch this to an unexported method on Checker. - t.check.completeInterface(pos, iface) + newTypeSet(t.check, pos, iface) return iface } @@ -700,7 +659,7 @@ func optype(typ Type) Type { // for a type parameter list of the form: // (type T interface { type T }). // See also issue #39680. - if a := t.Bound().allTypes; a != nil { + if a := t.Bound().typeSet().types; a != nil { // If we have a union with a single entry, ignore // any tilde because under(~t) == under(t). if u, _ := a.(*Union); u != nil && u.NumTerms() == 1 { diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go new file mode 100644 index 0000000000..44e5929413 --- /dev/null +++ b/src/cmd/compile/internal/types2/typeset.go @@ -0,0 +1,70 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types2 + +import ( + "bytes" +) + +// topTypeSet may be used as type set for the empty interface. +var topTypeSet TypeSet + +// A TypeSet represents the type set of an interface. +type TypeSet struct { + // TODO(gri) consider using a set for the methods for faster lookup + methods []*Func // all methods of the interface; sorted by unique ID + types Type // typically a *Union; nil means no type restrictions +} + +func (s *TypeSet) String() string { + if s.IsTop() { + return "⊤" + } + + var buf bytes.Buffer + buf.WriteByte('{') + for i, m := range s.methods { + if i > 0 { + buf.WriteByte(';') + } + buf.WriteByte(' ') + buf.WriteString(m.String()) + } + if len(s.methods) > 0 && s.types != nil { + buf.WriteByte(';') + } + if s.types != nil { + buf.WriteByte(' ') + writeType(&buf, s.types, nil, nil) + } + + buf.WriteString(" }") // there was a least one method or type + return buf.String() +} + +// IsTop reports whether type set s is the top type set (corresponding to the empty interface). +func (s *TypeSet) IsTop() bool { return len(s.methods) == 0 && s.types == nil } + +// IsMethodSet reports whether the type set s is described by a single set of methods. +func (s *TypeSet) IsMethodSet() bool { return s.types == nil && !s.IsComparable() } + +// IsComparable reports whether each type in the set is comparable. +func (s *TypeSet) IsComparable() bool { + _, m := s.LookupMethod(nil, "==") + return m != nil +} + +// NumMethods returns the number of methods available. +func (s *TypeSet) NumMethods() int { return len(s.methods) } + +// Method returns the i'th method of type set s for 0 <= i < s.NumMethods(). +// The methods are ordered by their unique ID. +func (s *TypeSet) Method(i int) *Func { return s.methods[i] } + +// LookupMethod returns the index of and method with matching package and name, or (-1, nil). +func (s *TypeSet) LookupMethod(pkg *Package, name string) (int, *Func) { + // TODO(gri) s.methods is sorted - consider binary search + return lookupMethod(s.methods, pkg, name) +} diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index f08c41c2a3..4925252b39 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -189,7 +189,8 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { if gcCompatibilityMode { // print flattened interface // (useful to compare against gc-generated interfaces) - for i, m := range t.allMethods { + tset := t.typeSet() + for i, m := range tset.methods { if i > 0 { buf.WriteString("; ") } @@ -197,12 +198,12 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { writeSignature(buf, m.typ.(*Signature), qf, visited) empty = false } - if !empty && t.allTypes != nil { + if !empty && tset.types != nil { buf.WriteString("; ") } - if t.allTypes != nil { + if tset.types != nil { buf.WriteString("type ") - writeType(buf, t.allTypes, qf, visited) + writeType(buf, tset.types, qf, visited) } } else { // print explicit interface methods and embedded types @@ -225,7 +226,9 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { empty = false } } - if debug && (t.allMethods == nil || len(t.methods) > len(t.allMethods)) { + // print /* incomplete */ if needed to satisfy existing tests + // TODO(gri) get rid of this eventually + if debug && t.tset == nil { if !empty { buf.WriteByte(' ') } diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 583bb464b2..fe676be2ef 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -141,12 +141,12 @@ func (check *Checker) ordinaryType(pos syntax.Pos, typ Type) { // interface methods. Delay this check to the end of type-checking. check.later(func() { if t := asInterface(typ); t != nil { - check.completeInterface(pos, t) // TODO(gri) is this the correct position? - if t.allTypes != nil { - check.softErrorf(pos, "interface contains type constraints (%s)", t.allTypes) + tset := newTypeSet(check, pos, t) // TODO(gri) is this the correct position? + if tset.types != nil { + check.softErrorf(pos, "interface contains type constraints (%s)", tset.types) return } - if t.IsComparable() { + if tset.IsComparable() { check.softErrorf(pos, "interface is (or embeds) comparable") } } diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index e5983dd40c..9a51dcb6d4 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -361,16 +361,8 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { // the same names and identical function types. Lower-case method names from // different packages are always different. The order of the methods is irrelevant. if y, ok := y.(*Interface); ok { - // If identical0 is called (indirectly) via an external API entry point - // (such as Identical, IdenticalIgnoreTags, etc.), check is nil. But in - // that case, interfaces are expected to be complete and lazy completion - // here is not needed. - if u.check != nil { - u.check.completeInterface(nopos, x) - u.check.completeInterface(nopos, y) - } - a := x.allMethods - b := y.allMethods + a := x.typeSet().methods + b := y.typeSet().methods if len(a) == len(b) { // Interface types are the only types where cycles can occur // that are not "terminated" via named types; and such cycles diff --git a/src/cmd/compile/internal/types2/universe.go b/src/cmd/compile/internal/types2/universe.go index 76d4e55e84..2bcc49778e 100644 --- a/src/cmd/compile/internal/types2/universe.go +++ b/src/cmd/compile/internal/types2/universe.go @@ -88,7 +88,7 @@ func defPredeclaredTypes() { res := NewVar(nopos, nil, "", Typ[String]) sig := &Signature{results: NewTuple(res)} err := NewFunc(nopos, nil, "Error", sig) - typ := &Named{underlying: NewInterfaceType([]*Func{err}, nil).Complete()} + typ := &Named{underlying: NewInterfaceType([]*Func{err}, nil)} sig.recv = NewVar(nopos, nil, "", typ) def(NewTypeName(nopos, nil, "error", typ)) } @@ -216,7 +216,7 @@ func defPredeclaredComparable() { // set up later to match the usual interface method assumptions. sig := new(Signature) eql := NewFunc(nopos, nil, "==", sig) - iface := NewInterfaceType([]*Func{eql}, nil).Complete() + iface := NewInterfaceType([]*Func{eql}, nil) // set up the defined type for the interface obj := NewTypeName(nopos, nil, "comparable", nil) -- GitLab From 1ff43d1b179eb96a34b9007e10d78e2278643f3f Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 28 Jun 2021 16:00:26 -0700 Subject: [PATCH 0383/2500] [dev.typeparams] cmd/compile/internal/types2: remove unused *Checker arguments (cleanup) Simplified names and unnecessary function indirections where possible. Change-Id: I1c7a386393d086fd7ad29f892e03f048781f3547 Reviewed-on: https://go-review.googlesource.com/c/go/+/331512 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/api.go | 4 +- src/cmd/compile/internal/types2/builtins.go | 6 +-- src/cmd/compile/internal/types2/call.go | 4 +- .../compile/internal/types2/conversions.go | 6 +-- src/cmd/compile/internal/types2/expr.go | 6 +-- src/cmd/compile/internal/types2/infer.go | 4 +- src/cmd/compile/internal/types2/interface.go | 2 +- src/cmd/compile/internal/types2/lookup.go | 45 ++++++++----------- src/cmd/compile/internal/types2/operand.go | 8 ++-- src/cmd/compile/internal/types2/predicates.go | 40 ++++++----------- src/cmd/compile/internal/types2/stmt.go | 4 +- src/cmd/compile/internal/types2/unify.go | 13 +++--- 12 files changed, 61 insertions(+), 81 deletions(-) diff --git a/src/cmd/compile/internal/types2/api.go b/src/cmd/compile/internal/types2/api.go index 4f7f35e61b..ae4fb6ad10 100644 --- a/src/cmd/compile/internal/types2/api.go +++ b/src/cmd/compile/internal/types2/api.go @@ -430,11 +430,11 @@ func Implements(V Type, T *Interface) bool { // Identical reports whether x and y are identical types. // Receivers of Signature types are ignored. func Identical(x, y Type) bool { - return (*Checker)(nil).identical(x, y) + return identical(x, y, true, nil) } // IdenticalIgnoreTags reports whether x and y are identical types if tags are ignored. // Receivers of Signature types are ignored. func IdenticalIgnoreTags(x, y Type) bool { - return (*Checker)(nil).identicalIgnoreTags(x, y) + return identical(x, y, false, nil) } diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index ffe872e7ab..7ba26509e8 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -281,7 +281,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( } // both argument types must be identical - if !check.identical(x.typ, y.typ) { + if !Identical(x.typ, y.typ) { check.errorf(x, invalidOp+"%v (mismatched types %s and %s)", call, x.typ, y.typ) return } @@ -346,7 +346,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( return } - if !check.identical(dst, src) { + if !Identical(dst, src) { check.errorf(x, invalidArg+"arguments to copy %s and %s have different element types %s and %s", x, &y, dst, src) return } @@ -635,7 +635,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( base := derefStructPtr(x.typ) sel := selx.Sel.Value - obj, index, indirect := check.lookupFieldOrMethod(base, false, check.pkg, sel) + obj, index, indirect := LookupFieldOrMethod(base, false, check.pkg, sel) switch obj.(type) { case nil: check.errorf(x, invalidArg+"%s has no single field %s", base, sel) diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 8c17a2f808..34dafce8bf 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -467,7 +467,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) { check.instantiatedOperand(x) - obj, index, indirect = check.lookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel) + obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel) if obj == nil { switch { case index != nil: @@ -497,7 +497,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) { } else { changeCase = string(unicode.ToUpper(r)) + sel[1:] } - if obj, _, _ = check.lookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, changeCase); obj != nil { + if obj, _, _ = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, changeCase); obj != nil { why += ", but does have " + changeCase } } diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go index 30201e2b7f..6c26a4c446 100644 --- a/src/cmd/compile/internal/types2/conversions.go +++ b/src/cmd/compile/internal/types2/conversions.go @@ -93,7 +93,7 @@ func (x *operand) convertibleTo(check *Checker, T Type) bool { V := x.typ Vu := under(V) Tu := under(T) - if check.identicalIgnoreTags(Vu, Tu) { + if IdenticalIgnoreTags(Vu, Tu) { return true } @@ -101,7 +101,7 @@ func (x *operand) convertibleTo(check *Checker, T Type) bool { // have identical underlying types if tags are ignored" if V, ok := V.(*Pointer); ok { if T, ok := T.(*Pointer); ok { - if check.identicalIgnoreTags(under(V.base), under(T.base)) { + if IdenticalIgnoreTags(under(V.base), under(T.base)) { return true } } @@ -142,7 +142,7 @@ func (x *operand) convertibleTo(check *Checker, T Type) bool { if s := asSlice(V); s != nil { if p := asPointer(T); p != nil { if a := asArray(p.Elem()); a != nil { - if check.identical(s.Elem(), a.Elem()) { + if Identical(s.Elem(), a.Elem()) { if check == nil || check.allowVersion(check.pkg, 1, 17) { return true } diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 7fba179e44..1cb0ad4752 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -1000,7 +1000,7 @@ func (check *Checker) binary(x *operand, e syntax.Expr, lhs, rhs syntax.Expr, op return } - if !check.identical(x.typ, y.typ) { + if !Identical(x.typ, y.typ) { // only report an error if we have valid types // (otherwise we had an error reported elsewhere already) if x.typ != Typ[Invalid] && y.typ != Typ[Invalid] { @@ -1329,7 +1329,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin xkey := keyVal(x.val) if asInterface(utyp.key) != nil { for _, vtyp := range visited[xkey] { - if check.identical(vtyp, x.typ) { + if Identical(vtyp, x.typ) { duplicate = true break } @@ -1550,7 +1550,7 @@ func (check *Checker) typeAssertion(pos syntax.Pos, x *operand, xtyp *Interface, } var msg string if wrongType != nil { - if check.identical(method.typ, wrongType.typ) { + if Identical(method.typ, wrongType.typ) { msg = fmt.Sprintf("missing method %s (%s has pointer receiver)", method.name, method.name) } else { msg = fmt.Sprintf("wrong type for method %s (have %s, want %s)", method.name, wrongType.typ, method.typ) diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index 791e25e9f0..e5d94e44d9 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -94,7 +94,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeName, targs []Type, p // Unify parameter and argument types for generic parameters with typed arguments // and collect the indices of generic parameters with untyped arguments. // Terminology: generic parameter = function parameter with a type-parameterized type - u := newUnifier(check, false) + u := newUnifier(false) u.x.init(tparams) // Set the type arguments which we know already. @@ -374,7 +374,7 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty // Setup bidirectional unification between those structural bounds // and the corresponding type arguments (which may be nil!). - u := newUnifier(check, false) + u := newUnifier(false) u.x.init(tparams) u.y = u.x // type parameters between LHS and RHS of unification are identical diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index 4dee923422..499b078dc0 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -211,7 +211,7 @@ func newTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *TypeSet { } // check != nil check.later(func() { - if !check.allowVersion(m.pkg, 1, 14) || !check.identical(m.typ, other.Type()) { + if !check.allowVersion(m.pkg, 1, 14) || !Identical(m.typ, other.Type()) { var err error_ err.errorf(pos, "duplicate method %s", m.name) err.errorf(mpos[other.(*Func)], "other declaration of %s", m.name) diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index 9fcec44d53..d59a2f474c 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -6,6 +6,11 @@ package types2 +// Internal use of LookupFieldOrMethod: If the obj result is a method +// associated with a concrete (non-interface) type, the method's signature +// may not be fully set up. Call Checker.objDecl(obj, nil) before accessing +// the method's type. + // LookupFieldOrMethod looks up a field or method with given package and name // in T and returns the corresponding *Var or *Func, an index sequence, and a // bool indicating if there were any pointer indirections on the path to the @@ -33,19 +38,6 @@ package types2 // the method's formal receiver base type, nor was the receiver addressable. // func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) { - return (*Checker)(nil).lookupFieldOrMethod(T, addressable, pkg, name) -} - -// Internal use of Checker.lookupFieldOrMethod: If the obj result is a method -// associated with a concrete (non-interface) type, the method's signature -// may not be fully set up. Call Checker.objDecl(obj, nil) before accessing -// the method's type. -// TODO(gri) Now that we provide the *Checker, we can probably remove this -// caveat by calling Checker.objDecl from lookupFieldOrMethod. Investigate. - -// lookupFieldOrMethod is like the external version but completes interfaces -// as necessary. -func (check *Checker) lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) { // Methods cannot be associated to a named pointer type // (spec: "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 @@ -55,7 +47,7 @@ func (check *Checker) lookupFieldOrMethod(T Type, addressable bool, pkg *Package // not have found it for T (see also issue 8590). if t := asNamed(T); t != nil { if p, _ := t.Underlying().(*Pointer); p != nil { - obj, index, indirect = check.rawLookupFieldOrMethod(p, false, pkg, name) + obj, index, indirect = lookupFieldOrMethod(p, false, pkg, name) if _, ok := obj.(*Func); ok { return nil, nil, false } @@ -63,7 +55,7 @@ func (check *Checker) lookupFieldOrMethod(T Type, addressable bool, pkg *Package } } - return check.rawLookupFieldOrMethod(T, addressable, pkg, name) + return lookupFieldOrMethod(T, addressable, pkg, name) } // TODO(gri) The named type consolidation and seen maps below must be @@ -71,10 +63,9 @@ func (check *Checker) lookupFieldOrMethod(T Type, addressable bool, pkg *Package // types always have only one representation (even when imported // indirectly via different packages.) -// rawLookupFieldOrMethod should only be called by lookupFieldOrMethod and missingMethod. -func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) { +// lookupFieldOrMethod should only be called by LookupFieldOrMethod and missingMethod. +func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) { // WARNING: The code in this function is extremely subtle - do not modify casually! - // This function and NewMethodSet should be kept in sync. if name == "_" { return // blank fields/methods are never found @@ -228,7 +219,7 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack return } - current = check.consolidateMultiples(next) + current = consolidateMultiples(next) } return nil, nil, false // not found @@ -245,7 +236,7 @@ type embeddedType struct { // consolidateMultiples collects multiple list entries with the same type // into a single entry marked as containing multiples. The result is the // consolidated list. -func (check *Checker) consolidateMultiples(list []embeddedType) []embeddedType { +func consolidateMultiples(list []embeddedType) []embeddedType { if len(list) <= 1 { return list // at most one entry - nothing to do } @@ -253,7 +244,7 @@ func (check *Checker) consolidateMultiples(list []embeddedType) []embeddedType { n := 0 // number of entries w/ unique type prev := make(map[Type]int) // index at which type was previously seen for _, e := range list { - if i, found := check.lookupType(prev, e.typ); found { + if i, found := lookupType(prev, e.typ); found { list[i].multiples = true // ignore this entry } else { @@ -265,14 +256,14 @@ func (check *Checker) consolidateMultiples(list []embeddedType) []embeddedType { return list[:n] } -func (check *Checker) lookupType(m map[Type]int, typ Type) (int, bool) { +func lookupType(m map[Type]int, typ Type) (int, bool) { // fast path: maybe the types are equal if i, found := m[typ]; found { return i, true } for t, i := range m { - if check.identical(t, typ) { + if Identical(t, typ) { return i, true } } @@ -338,7 +329,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // to see if they can be made to match. // TODO(gri) is this always correct? what about type bounds? // (Alternative is to rename/subst type parameters and compare.) - u := newUnifier(check, true) + u := newUnifier(true) u.x.init(ftyp.tparams) if !u.unify(ftyp, mtyp) { return m, f @@ -353,12 +344,12 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, Vn := asNamed(Vd) for _, m := range T.typeSet().methods { // TODO(gri) should this be calling lookupFieldOrMethod instead (and why not)? - obj, _, _ := check.rawLookupFieldOrMethod(V, false, m.pkg, m.name) + obj, _, _ := lookupFieldOrMethod(V, false, m.pkg, m.name) // Check if *V implements this method of T. if obj == nil { ptr := NewPointer(V) - obj, _, _ = check.rawLookupFieldOrMethod(ptr, false, m.pkg, m.name) + obj, _, _ = lookupFieldOrMethod(ptr, false, m.pkg, m.name) if obj != nil { return m, obj.(*Func) } @@ -414,7 +405,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // to see if they can be made to match. // TODO(gri) is this always correct? what about type bounds? // (Alternative is to rename/subst type parameters and compare.) - u := newUnifier(check, true) + u := newUnifier(true) if len(ftyp.tparams) > 0 { // We reach here only if we accept method type parameters. // In this case, unification must consider any receiver diff --git a/src/cmd/compile/internal/types2/operand.go b/src/cmd/compile/internal/types2/operand.go index fdc6ec52aa..83cc239d93 100644 --- a/src/cmd/compile/internal/types2/operand.go +++ b/src/cmd/compile/internal/types2/operand.go @@ -255,7 +255,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er } // x's type is identical to T - if check.identical(V, T) { + if Identical(V, T) { return true, 0 } @@ -287,7 +287,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er // x's type V and T have identical underlying types // and at least one of V or T is not a named type - if check.identical(Vu, Tu) && (!isNamed(V) || !isNamed(T)) { + if Identical(Vu, Tu) && (!isNamed(V) || !isNamed(T)) { return true, 0 } @@ -296,7 +296,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er if m, wrongType := check.missingMethod(V, Ti, true); m != nil /* Implements(V, Ti) */ { if reason != nil { if wrongType != nil { - if check.identical(m.typ, wrongType.typ) { + if Identical(m.typ, wrongType.typ) { *reason = fmt.Sprintf("missing method %s (%s has pointer receiver)", m.name, m.name) } else { *reason = fmt.Sprintf("wrong type for method %s (have %s, want %s)", m.Name(), wrongType.typ, m.typ) @@ -315,7 +315,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er // type, x's type V and T have identical element types, // and at least one of V or T is not a named type if Vc, ok := Vu.(*Chan); ok && Vc.dir == SendRecv { - if Tc, ok := Tu.(*Chan); ok && check.identical(Vc.elem, Tc.elem) { + if Tc, ok := Tu.(*Chan); ok && Identical(Vc.elem, Tc.elem) { return !isNamed(V) || !isNamed(T), _InvalidChanAssign } } diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 73af127188..5ff7840d6f 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -147,18 +147,6 @@ func hasNil(typ Type) bool { return false } -// identical reports whether x and y are identical types. -// Receivers of Signature types are ignored. -func (check *Checker) identical(x, y Type) bool { - return check.identical0(x, y, true, nil) -} - -// identicalIgnoreTags reports whether x and y are identical types if tags are ignored. -// Receivers of Signature types are ignored. -func (check *Checker) identicalIgnoreTags(x, y Type) bool { - return check.identical0(x, y, false, nil) -} - // An ifacePair is a node in a stack of interface type pairs compared for identity. type ifacePair struct { x, y *Interface @@ -170,7 +158,7 @@ func (p *ifacePair) identical(q *ifacePair) bool { } // For changes to this code the corresponding changes should be made to unifier.nify. -func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { +func identical(x, y Type, cmpTags bool, p *ifacePair) bool { // types must be expanded for comparison x = expandf(x) y = expandf(y) @@ -194,13 +182,13 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { if y, ok := y.(*Array); ok { // If one or both array lengths are unknown (< 0) due to some error, // assume they are the same to avoid spurious follow-on errors. - return (x.len < 0 || y.len < 0 || x.len == y.len) && check.identical0(x.elem, y.elem, cmpTags, p) + return (x.len < 0 || y.len < 0 || x.len == y.len) && identical(x.elem, y.elem, cmpTags, p) } case *Slice: // Two slice types are identical if they have identical element types. if y, ok := y.(*Slice); ok { - return check.identical0(x.elem, y.elem, cmpTags, p) + return identical(x.elem, y.elem, cmpTags, p) } case *Struct: @@ -215,7 +203,7 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { if f.embedded != g.embedded || cmpTags && x.Tag(i) != y.Tag(i) || !f.sameId(g.pkg, g.name) || - !check.identical0(f.typ, g.typ, cmpTags, p) { + !identical(f.typ, g.typ, cmpTags, p) { return false } } @@ -226,7 +214,7 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { case *Pointer: // Two pointer types are identical if they have identical base types. if y, ok := y.(*Pointer); ok { - return check.identical0(x.base, y.base, cmpTags, p) + return identical(x.base, y.base, cmpTags, p) } case *Tuple: @@ -237,7 +225,7 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { if x != nil { for i, v := range x.vars { w := y.vars[i] - if !check.identical0(v.typ, w.typ, cmpTags, p) { + if !identical(v.typ, w.typ, cmpTags, p) { return false } } @@ -255,9 +243,9 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { // parameter names. if y, ok := y.(*Signature); ok { return x.variadic == y.variadic && - check.identicalTParams(x.tparams, y.tparams, cmpTags, p) && - check.identical0(x.params, y.params, cmpTags, p) && - check.identical0(x.results, y.results, cmpTags, p) + identicalTParams(x.tparams, y.tparams, cmpTags, p) && + identical(x.params, y.params, cmpTags, p) && + identical(x.results, y.results, cmpTags, p) } case *Union: @@ -325,7 +313,7 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { } for i, f := range a { g := b[i] - if f.Id() != g.Id() || !check.identical0(f.typ, g.typ, cmpTags, q) { + if f.Id() != g.Id() || !identical(f.typ, g.typ, cmpTags, q) { return false } } @@ -336,14 +324,14 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { case *Map: // Two map types are identical if they have identical key and value types. if y, ok := y.(*Map); ok { - return check.identical0(x.key, y.key, cmpTags, p) && check.identical0(x.elem, y.elem, cmpTags, p) + return identical(x.key, y.key, cmpTags, p) && identical(x.elem, y.elem, cmpTags, p) } case *Chan: // Two channel types are identical if they have identical value types // and the same direction. if y, ok := y.(*Chan); ok { - return x.dir == y.dir && check.identical0(x.elem, y.elem, cmpTags, p) + return x.dir == y.dir && identical(x.elem, y.elem, cmpTags, p) } case *Named: @@ -376,13 +364,13 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { return false } -func (check *Checker) identicalTParams(x, y []*TypeName, cmpTags bool, p *ifacePair) bool { +func identicalTParams(x, y []*TypeName, cmpTags bool, p *ifacePair) bool { if len(x) != len(y) { return false } for i, x := range x { y := y[i] - if !check.identical0(x.typ.(*TypeParam).bound, y.typ.(*TypeParam).bound, cmpTags, p) { + if !identical(x.typ.(*TypeParam).bound, y.typ.(*TypeParam).bound, cmpTags, p) { return false } } diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index ab66432126..b41b23fedb 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -256,7 +256,7 @@ L: // look for duplicate types for a given value // (quadratic algorithm, but these lists tend to be very short) for _, vt := range seen[val] { - if check.identical(v.typ, vt.typ) { + if Identical(v.typ, vt.typ) { var err error_ err.errorf(&v, "duplicate case %s in expression switch", &v) err.errorf(vt.pos, "previous case") @@ -282,7 +282,7 @@ L: // look for duplicate types // (quadratic algorithm, but type switches tend to be reasonably small) for t, other := range seen { - if T == nil && t == nil || T != nil && t != nil && check.identical(T, t) { + if T == nil && t == nil || T != nil && t != nil && Identical(T, t) { // talk about "case" rather than "type" because of nil case Ts := "nil" if T != nil { diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index 9a51dcb6d4..4e1f832203 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -6,7 +6,10 @@ package types2 -import "bytes" +import ( + "bytes" + "fmt" +) // The unifier maintains two separate sets of type parameters x and y // which are used to resolve type parameters in the x and y arguments @@ -34,7 +37,6 @@ import "bytes" // and the respective types inferred for each type parameter. // A unifier is created by calling newUnifier. type unifier struct { - check *Checker exact bool x, y tparamsList // x and y must initialized via tparamsList.init types []Type // inferred types, shared by x and y @@ -45,8 +47,8 @@ type unifier struct { // exactly. If exact is not set, a named type's underlying type // is considered if unification would fail otherwise, and the // direction of channels is ignored. -func newUnifier(check *Checker, exact bool) *unifier { - u := &unifier{check: check, exact: exact} +func newUnifier(exact bool) *unifier { + u := &unifier{exact: exact} u.x.unifier = u u.y.unifier = u return u @@ -453,8 +455,7 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { // avoid a crash in case of nil type default: - u.check.dump("### u.nify(%s, %s), u.x.tparams = %s", x, y, u.x.tparams) - unreachable() + panic(fmt.Sprintf("### u.nify(%s, %s), u.x.tparams = %s", x, y, u.x.tparams)) } return false -- GitLab From f0206e3df2f134cb1a13402aefbb6caeec4fc126 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 28 Jun 2021 17:21:26 -0700 Subject: [PATCH 0384/2500] [dev.typeparams] cmd/compile/internal/types2: move embedding positions from Checker to Interface This change moves the position information to the place where it is actually used. It also simplifies getting rid of it after use. In the process, fixed a latent bug: Before this CL, embedded types were sorted, but the corresponding embedding positions were not. Removed the sorting altogether as it is not needed for type-checking. Change-Id: I48003f317196d814326424430336b6cb222fdee6 Reviewed-on: https://go-review.googlesource.com/c/go/+/331514 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/check.go | 12 ++--- src/cmd/compile/internal/types2/interface.go | 46 +++++++------------ .../compile/internal/types2/sizeof_test.go | 2 +- src/cmd/compile/internal/types2/subst.go | 1 - src/cmd/compile/internal/types2/type.go | 10 ++-- 5 files changed, 28 insertions(+), 43 deletions(-) diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go index 5d3c2c8ad2..071afef058 100644 --- a/src/cmd/compile/internal/types2/check.go +++ b/src/cmd/compile/internal/types2/check.go @@ -82,12 +82,11 @@ type Checker struct { conf *Config pkg *Package *Info - version version // accepted language version - nextID uint64 // unique Id for type parameters (first valid Id is 1) - objMap map[Object]*declInfo // maps package-level objects and (non-interface) methods to declaration info - impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package - posMap map[*Interface][]syntax.Pos // maps interface types to lists of embedded interface positions - typMap map[string]*Named // maps an instantiated named type hash to a *Named type + version version // accepted language version + nextID uint64 // unique Id for type parameters (first valid Id is 1) + objMap map[Object]*declInfo // maps package-level objects and (non-interface) methods to declaration info + impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package + typMap map[string]*Named // maps an instantiated named type hash to a *Named type // pkgPathMap maps package names to the set of distinct import paths we've // seen for that name, anywhere in the import graph. It is used for @@ -189,7 +188,6 @@ func NewChecker(conf *Config, pkg *Package, info *Info) *Checker { version: version, objMap: make(map[Object]*declInfo), impMap: make(map[importKey]*Package), - posMap: make(map[*Interface][]syntax.Pos), typMap: make(map[string]*Named), } } diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index 499b078dc0..e667830db3 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -14,11 +14,18 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType var tlist []syntax.Expr // types collected from all type lists var tname *syntax.Name // most recent "type" name + addEmbedded := func(pos syntax.Pos, typ Type) { + ityp.embeddeds = append(ityp.embeddeds, typ) + if ityp.embedPos == nil { + ityp.embedPos = new([]syntax.Pos) + } + *ityp.embedPos = append(*ityp.embedPos, pos) + } + for _, f := range iface.MethodList { if f.Name == nil { // We have an embedded type; possibly a union of types. - ityp.embeddeds = append(ityp.embeddeds, parseUnion(check, flattenUnion(nil, f.Type))) - check.posMap[ityp] = append(check.posMap[ityp], f.Type.Pos()) + addEmbedded(f.Type.Pos(), parseUnion(check, flattenUnion(nil, f.Type))) continue } // f.Name != nil @@ -89,10 +96,9 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType // If we saw a type list, add it like an embedded union. if tlist != nil { - ityp.embeddeds = append(ityp.embeddeds, parseUnion(check, tlist)) // Types T in a type list are added as ~T expressions but we don't // have the position of the '~'. Use the first type position instead. - check.posMap[ityp] = append(check.posMap[ityp], tlist[0].(*syntax.Operation).X.Pos()) + addEmbedded(tlist[0].(*syntax.Operation).X.Pos(), parseUnion(check, tlist)) } // All methods and embedded elements for this interface are collected; @@ -106,8 +112,8 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType } // sort for API stability + // (don't sort embeddeds: they must correspond to *embedPos entries) sortMethods(ityp.methods) - sortTypes(ityp.embeddeds) // Compute type set with a non-nil *Checker as soon as possible // to report any errors. Subsequent uses of type sets should be @@ -227,14 +233,13 @@ func newTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *TypeSet { // collect embedded elements var allTypes Type - var posList []syntax.Pos - if check != nil { - posList = check.posMap[ityp] - } for i, typ := range ityp.embeddeds { + // The embedding position is nil for imported interfaces + // and also for interface copies after substitution (but + // in that case we don't need to report errors again). var pos syntax.Pos // embedding position - if posList != nil { - pos = posList[i] + if ityp.embedPos != nil { + pos = (*ityp.embedPos)[i] } var types Type switch t := under(typ).(type) { @@ -268,6 +273,7 @@ func newTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *TypeSet { } allTypes = intersect(allTypes, types) } + ityp.embedPos = nil // not needed anymore (errors have been reported) // process todo's (this only happens if check == nil) for i := 0; i < len(todo); i += 2 { @@ -287,24 +293,6 @@ func newTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *TypeSet { return ityp.tset } -func sortTypes(list []Type) { - sort.Stable(byUniqueTypeName(list)) -} - -// byUniqueTypeName named type lists can be sorted by their unique type names. -type byUniqueTypeName []Type - -func (a byUniqueTypeName) Len() int { return len(a) } -func (a byUniqueTypeName) Less(i, j int) bool { return sortObj(a[i]).less(sortObj(a[j])) } -func (a byUniqueTypeName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } - -func sortObj(t Type) *object { - if named := asNamed(t); named != nil { - return &named.obj.object - } - return nil -} - func sortMethods(list []*Func) { sort.Sort(byUniqueMethodName(list)) } diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go index 0b1f7dacad..82e1221b67 100644 --- a/src/cmd/compile/internal/types2/sizeof_test.go +++ b/src/cmd/compile/internal/types2/sizeof_test.go @@ -28,7 +28,7 @@ func TestSizeof(t *testing.T) { {Tuple{}, 12, 24}, {Signature{}, 44, 88}, {Union{}, 24, 48}, - {Interface{}, 40, 80}, + {Interface{}, 44, 88}, {Map{}, 16, 32}, {Chan{}, 12, 24}, {Named{}, 84, 160}, diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 38bd07b8a2..db01c36f7a 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -316,7 +316,6 @@ func (subst *subster) typ(typ Type) Type { if subst.check == nil { panic("internal error: cannot instantiate interfaces yet") } - subst.check.posMap[iface] = subst.check.posMap[t] // satisfy completeInterface requirement return iface } diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 122e408ead..2cfcabbdb5 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -264,10 +264,11 @@ func (s *Signature) Variadic() bool { return s.variadic } // An Interface represents an interface type. type Interface struct { - obj Object // type name object defining this interface; or nil (for better error messages) - methods []*Func // ordered list of explicitly declared methods - embeddeds []Type // ordered list of explicitly embedded elements - complete bool // indicates that obj, methods, and embeddeds are set and type set can be computed + obj Object // type name object defining this interface; or nil (for better error messages) + methods []*Func // ordered list of explicitly declared methods + embeddeds []Type // ordered list of explicitly embedded elements + embedPos *[]syntax.Pos // positions of embedded elements; or nil (for error messages) - use pointer to save space + complete bool // indicates that all fields (except for tset) are set up tset *TypeSet // type set described by this interface, computed lazily } @@ -322,7 +323,6 @@ func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface { // sort for API stability sortMethods(methods) - sortTypes(embeddeds) typ.methods = methods typ.embeddeds = embeddeds -- GitLab From b47cbc2ffec163f30690613b3a9c3f7f108cd512 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 28 Jun 2021 17:37:41 -0700 Subject: [PATCH 0385/2500] [dev.typeparams] cmd/compile/internal/types2: move newTypeSet function into typeset.go No functional changes except for import declaration and comment adjustments. Change-Id: I75fb5edba8b89a5aad7c9b4ddb427c201265def0 Reviewed-on: https://go-review.googlesource.com/c/go/+/331515 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/interface.go | 190 +--------------- src/cmd/compile/internal/types2/typeset.go | 228 +++++++++++++++++-- 2 files changed, 209 insertions(+), 209 deletions(-) diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index e667830db3..18dc573340 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -4,11 +4,7 @@ package types2 -import ( - "cmd/compile/internal/syntax" - "fmt" - "sort" -) +import "cmd/compile/internal/syntax" func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType, def *Named) { var tlist []syntax.Expr // types collected from all type lists @@ -128,187 +124,3 @@ func flattenUnion(list []syntax.Expr, x syntax.Expr) []syntax.Expr { } return append(list, x) } - -// newTypeSet may be called with check == nil. -// TODO(gri) move this function into typeset.go eventually -func newTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *TypeSet { - if ityp.tset != nil { - return ityp.tset - } - - // If the interface is not fully set up yet, the type set will - // not be complete, which may lead to errors when using the the - // type set (e.g. missing method). Don't compute a partial type - // set (and don't store it!), so that we still compute the full - // type set eventually. Instead, return the top type set and - // let any follow-on errors play out. - // - // TODO(gri) Consider recording when this happens and reporting - // it as an error (but only if there were no other errors so to - // to not have unnecessary follow-on errors). - if !ityp.complete { - return &topTypeSet - } - - if check != nil && check.conf.Trace { - // Types don't generally have position information. - // If we don't have a valid pos provided, try to use - // one close enough. - if !pos.IsKnown() && len(ityp.methods) > 0 { - pos = ityp.methods[0].pos - } - - check.trace(pos, "type set for %s", ityp) - check.indent++ - defer func() { - check.indent-- - check.trace(pos, "=> %s ", ityp.typeSet()) - }() - } - - // An infinitely expanding interface (due to a cycle) is detected - // elsewhere (Checker.validType), so here we simply assume we only - // have valid interfaces. Mark the interface as complete to avoid - // infinite recursion if the validType check occurs later for some - // reason. - ityp.tset = new(TypeSet) // TODO(gri) is this sufficient? - - // Methods of embedded interfaces are collected unchanged; i.e., the identity - // of a method I.m's Func Object of an interface I is the same as that of - // the method m in an interface that embeds interface I. On the other hand, - // if a method is embedded via multiple overlapping embedded interfaces, we - // don't provide a guarantee which "original m" got chosen for the embedding - // interface. See also issue #34421. - // - // If we don't care to provide this identity guarantee anymore, instead of - // reusing the original method in embeddings, we can clone the method's Func - // Object and give it the position of a corresponding embedded interface. Then - // we can get rid of the mpos map below and simply use the cloned method's - // position. - - var todo []*Func - var seen objset - var methods []*Func - mpos := make(map[*Func]syntax.Pos) // method specification or method embedding position, for good error messages - addMethod := func(pos syntax.Pos, m *Func, explicit bool) { - switch other := seen.insert(m); { - case other == nil: - methods = append(methods, m) - mpos[m] = pos - case explicit: - if check == nil { - panic(fmt.Sprintf("%s: duplicate method %s", m.pos, m.name)) - } - // check != nil - var err error_ - err.errorf(pos, "duplicate method %s", m.name) - err.errorf(mpos[other.(*Func)], "other declaration of %s", m.name) - check.report(&err) - default: - // We have a duplicate method name in an embedded (not explicitly declared) method. - // Check method signatures after all types are computed (issue #33656). - // If we're pre-go1.14 (overlapping embeddings are not permitted), report that - // error here as well (even though we could do it eagerly) because it's the same - // error message. - if check == nil { - // check method signatures after all locally embedded interfaces are computed - todo = append(todo, m, other.(*Func)) - break - } - // check != nil - check.later(func() { - if !check.allowVersion(m.pkg, 1, 14) || !Identical(m.typ, other.Type()) { - var err error_ - err.errorf(pos, "duplicate method %s", m.name) - err.errorf(mpos[other.(*Func)], "other declaration of %s", m.name) - check.report(&err) - } - }) - } - } - - for _, m := range ityp.methods { - addMethod(m.pos, m, true) - } - - // collect embedded elements - var allTypes Type - for i, typ := range ityp.embeddeds { - // The embedding position is nil for imported interfaces - // and also for interface copies after substitution (but - // in that case we don't need to report errors again). - var pos syntax.Pos // embedding position - if ityp.embedPos != nil { - pos = (*ityp.embedPos)[i] - } - var types Type - switch t := under(typ).(type) { - case *Interface: - tset := newTypeSet(check, pos, t) - for _, m := range tset.methods { - addMethod(pos, m, false) // use embedding position pos rather than m.pos - } - types = tset.types - case *Union: - // TODO(gri) combine with default case once we have - // converted all tests to new notation and we - // can report an error when we don't have an - // interface before go1.18. - types = typ - case *TypeParam: - if check != nil && !check.allowVersion(check.pkg, 1, 18) { - check.errorf(pos, "%s is a type parameter, not an interface", typ) - continue - } - types = typ - default: - if typ == Typ[Invalid] { - continue - } - if check != nil && !check.allowVersion(check.pkg, 1, 18) { - check.errorf(pos, "%s is not an interface", typ) - continue - } - types = typ - } - allTypes = intersect(allTypes, types) - } - ityp.embedPos = nil // not needed anymore (errors have been reported) - - // process todo's (this only happens if check == nil) - for i := 0; i < len(todo); i += 2 { - m := todo[i] - other := todo[i+1] - if !Identical(m.typ, other.typ) { - panic(fmt.Sprintf("%s: duplicate method %s", m.pos, m.name)) - } - } - - if methods != nil { - sortMethods(methods) - ityp.tset.methods = methods - } - ityp.tset.types = allTypes - - return ityp.tset -} - -func sortMethods(list []*Func) { - sort.Sort(byUniqueMethodName(list)) -} - -func assertSortedMethods(list []*Func) { - if !debug { - panic("internal error: assertSortedMethods called outside debug mode") - } - if !sort.IsSorted(byUniqueMethodName(list)) { - panic("internal error: methods not sorted") - } -} - -// byUniqueMethodName method lists can be sorted by their unique method names. -type byUniqueMethodName []*Func - -func (a byUniqueMethodName) Len() int { return len(a) } -func (a byUniqueMethodName) Less(i, j int) bool { return a[i].less(&a[j].object) } -func (a byUniqueMethodName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index 44e5929413..ce4a776f8f 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -6,10 +6,13 @@ package types2 import ( "bytes" + "cmd/compile/internal/syntax" + "fmt" + "sort" ) -// topTypeSet may be used as type set for the empty interface. -var topTypeSet TypeSet +// ---------------------------------------------------------------------------- +// API // A TypeSet represents the type set of an interface. type TypeSet struct { @@ -18,6 +21,31 @@ type TypeSet struct { types Type // typically a *Union; nil means no type restrictions } +// IsTop reports whether type set s is the top type set (corresponding to the empty interface). +func (s *TypeSet) IsTop() bool { return len(s.methods) == 0 && s.types == nil } + +// IsMethodSet reports whether the type set s is described by a single set of methods. +func (s *TypeSet) IsMethodSet() bool { return s.types == nil && !s.IsComparable() } + +// IsComparable reports whether each type in the set is comparable. +func (s *TypeSet) IsComparable() bool { + _, m := s.LookupMethod(nil, "==") + return m != nil +} + +// NumMethods returns the number of methods available. +func (s *TypeSet) NumMethods() int { return len(s.methods) } + +// Method returns the i'th method of type set s for 0 <= i < s.NumMethods(). +// The methods are ordered by their unique ID. +func (s *TypeSet) Method(i int) *Func { return s.methods[i] } + +// LookupMethod returns the index of and method with matching package and name, or (-1, nil). +func (s *TypeSet) LookupMethod(pkg *Package, name string) (int, *Func) { + // TODO(gri) s.methods is sorted - consider binary search + return lookupMethod(s.methods, pkg, name) +} + func (s *TypeSet) String() string { if s.IsTop() { return "⊤" @@ -44,27 +72,187 @@ func (s *TypeSet) String() string { return buf.String() } -// IsTop reports whether type set s is the top type set (corresponding to the empty interface). -func (s *TypeSet) IsTop() bool { return len(s.methods) == 0 && s.types == nil } +// ---------------------------------------------------------------------------- +// Implementation -// IsMethodSet reports whether the type set s is described by a single set of methods. -func (s *TypeSet) IsMethodSet() bool { return s.types == nil && !s.IsComparable() } +// topTypeSet may be used as type set for the empty interface. +var topTypeSet TypeSet -// IsComparable reports whether each type in the set is comparable. -func (s *TypeSet) IsComparable() bool { - _, m := s.LookupMethod(nil, "==") - return m != nil -} +// newTypeSet may be called with check == nil. +func newTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *TypeSet { + if ityp.tset != nil { + return ityp.tset + } -// NumMethods returns the number of methods available. -func (s *TypeSet) NumMethods() int { return len(s.methods) } + // If the interface is not fully set up yet, the type set will + // not be complete, which may lead to errors when using the the + // type set (e.g. missing method). Don't compute a partial type + // set (and don't store it!), so that we still compute the full + // type set eventually. Instead, return the top type set and + // let any follow-on errors play out. + if !ityp.complete { + return &topTypeSet + } -// Method returns the i'th method of type set s for 0 <= i < s.NumMethods(). -// The methods are ordered by their unique ID. -func (s *TypeSet) Method(i int) *Func { return s.methods[i] } + if check != nil && check.conf.Trace { + // Types don't generally have position information. + // If we don't have a valid pos provided, try to use + // one close enough. + if !pos.IsKnown() && len(ityp.methods) > 0 { + pos = ityp.methods[0].pos + } -// LookupMethod returns the index of and method with matching package and name, or (-1, nil). -func (s *TypeSet) LookupMethod(pkg *Package, name string) (int, *Func) { - // TODO(gri) s.methods is sorted - consider binary search - return lookupMethod(s.methods, pkg, name) + check.trace(pos, "type set for %s", ityp) + check.indent++ + defer func() { + check.indent-- + check.trace(pos, "=> %s ", ityp.typeSet()) + }() + } + + // An infinitely expanding interface (due to a cycle) is detected + // elsewhere (Checker.validType), so here we simply assume we only + // have valid interfaces. Mark the interface as complete to avoid + // infinite recursion if the validType check occurs later for some + // reason. + ityp.tset = new(TypeSet) // TODO(gri) is this sufficient? + + // Methods of embedded interfaces are collected unchanged; i.e., the identity + // of a method I.m's Func Object of an interface I is the same as that of + // the method m in an interface that embeds interface I. On the other hand, + // if a method is embedded via multiple overlapping embedded interfaces, we + // don't provide a guarantee which "original m" got chosen for the embedding + // interface. See also issue #34421. + // + // If we don't care to provide this identity guarantee anymore, instead of + // reusing the original method in embeddings, we can clone the method's Func + // Object and give it the position of a corresponding embedded interface. Then + // we can get rid of the mpos map below and simply use the cloned method's + // position. + + var todo []*Func + var seen objset + var methods []*Func + mpos := make(map[*Func]syntax.Pos) // method specification or method embedding position, for good error messages + addMethod := func(pos syntax.Pos, m *Func, explicit bool) { + switch other := seen.insert(m); { + case other == nil: + methods = append(methods, m) + mpos[m] = pos + case explicit: + if check == nil { + panic(fmt.Sprintf("%s: duplicate method %s", m.pos, m.name)) + } + // check != nil + var err error_ + err.errorf(pos, "duplicate method %s", m.name) + err.errorf(mpos[other.(*Func)], "other declaration of %s", m.name) + check.report(&err) + default: + // We have a duplicate method name in an embedded (not explicitly declared) method. + // Check method signatures after all types are computed (issue #33656). + // If we're pre-go1.14 (overlapping embeddings are not permitted), report that + // error here as well (even though we could do it eagerly) because it's the same + // error message. + if check == nil { + // check method signatures after all locally embedded interfaces are computed + todo = append(todo, m, other.(*Func)) + break + } + // check != nil + check.later(func() { + if !check.allowVersion(m.pkg, 1, 14) || !Identical(m.typ, other.Type()) { + var err error_ + err.errorf(pos, "duplicate method %s", m.name) + err.errorf(mpos[other.(*Func)], "other declaration of %s", m.name) + check.report(&err) + } + }) + } + } + + for _, m := range ityp.methods { + addMethod(m.pos, m, true) + } + + // collect embedded elements + var allTypes Type + for i, typ := range ityp.embeddeds { + // The embedding position is nil for imported interfaces + // and also for interface copies after substitution (but + // in that case we don't need to report errors again). + var pos syntax.Pos // embedding position + if ityp.embedPos != nil { + pos = (*ityp.embedPos)[i] + } + var types Type + switch t := under(typ).(type) { + case *Interface: + tset := newTypeSet(check, pos, t) + for _, m := range tset.methods { + addMethod(pos, m, false) // use embedding position pos rather than m.pos + } + types = tset.types + case *Union: + // TODO(gri) combine with default case once we have + // converted all tests to new notation and we + // can report an error when we don't have an + // interface before go1.18. + types = typ + case *TypeParam: + if check != nil && !check.allowVersion(check.pkg, 1, 18) { + check.errorf(pos, "%s is a type parameter, not an interface", typ) + continue + } + types = typ + default: + if typ == Typ[Invalid] { + continue + } + if check != nil && !check.allowVersion(check.pkg, 1, 18) { + check.errorf(pos, "%s is not an interface", typ) + continue + } + types = typ + } + allTypes = intersect(allTypes, types) + } + ityp.embedPos = nil // not needed anymore (errors have been reported) + + // process todo's (this only happens if check == nil) + for i := 0; i < len(todo); i += 2 { + m := todo[i] + other := todo[i+1] + if !Identical(m.typ, other.typ) { + panic(fmt.Sprintf("%s: duplicate method %s", m.pos, m.name)) + } + } + + if methods != nil { + sortMethods(methods) + ityp.tset.methods = methods + } + ityp.tset.types = allTypes + + return ityp.tset +} + +func sortMethods(list []*Func) { + sort.Sort(byUniqueMethodName(list)) } + +func assertSortedMethods(list []*Func) { + if !debug { + panic("internal error: assertSortedMethods called outside debug mode") + } + if !sort.IsSorted(byUniqueMethodName(list)) { + panic("internal error: methods not sorted") + } +} + +// byUniqueMethodName method lists can be sorted by their unique method names. +type byUniqueMethodName []*Func + +func (a byUniqueMethodName) Len() int { return len(a) } +func (a byUniqueMethodName) Less(i, j int) bool { return a[i].less(&a[j].object) } +func (a byUniqueMethodName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -- GitLab From 8767b87ab54acca33c487ee46e237049b663b1c4 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 21 Jun 2021 17:04:59 -0700 Subject: [PATCH 0386/2500] [dev.typeparams] cmd/compile: functions to create GC shape types/names for a concrete type Created functions to create GC shape type and names, based on a proposal from Keith. Kept unsigned and signed integer types as different, since they have different shift operations. Included adding in alignment fields where padding is required between fields, even though that seems like it will be fairly uncommon to use. Added some extra unusual struct typeparams (for testing the gcshape names/types) in index.go test. Change-Id: I8132bbd28098bd933435b8972ac5cc0b39f4c0df Reviewed-on: https://go-review.googlesource.com/c/go/+/329921 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 198 ++++++++++++++++++++++ test/typeparam/index.go | 36 ++++ 2 files changed, 234 insertions(+) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 29ee863a71..b228e40258 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -8,6 +8,7 @@ package noder import ( + "bytes" "cmd/compile/internal/base" "cmd/compile/internal/ir" "cmd/compile/internal/objw" @@ -18,6 +19,7 @@ import ( "cmd/internal/src" "fmt" "go/constant" + "strconv" ) func assert(p bool) { @@ -490,6 +492,195 @@ func (g *irgen) getInstantiationForNode(inst *ir.InstExpr) (*ir.Func, ir.Node) { } } +func addGcType(fl []*types.Field, t *types.Type) []*types.Field { + return append(fl, types.NewField(base.Pos, typecheck.Lookup("F"+strconv.Itoa(len(fl))), t)) +} + +const INTTYPE = types.TINT64 // XX fix for 32-bit arch +const UINTTYPE = types.TUINT64 // XX fix for 32-bit arch +const INTSTRING = "i8" // XX fix for 32-bit arch +const UINTSTRING = "u8" // XX fix for 32-bit arch + +// accumGcshape adds fields to fl resulting from the GCshape transformation of +// type t. The string associated with the GCshape transformation of t is added to +// buf. fieldSym is the sym of the field associated with type t, if it is in a +// struct. fieldSym could be used to have special naming for blank fields, etc. +func accumGcshape(fl []*types.Field, buf *bytes.Buffer, t *types.Type, fieldSym *types.Sym) []*types.Field { + + // t.Kind() is already the kind of the underlying type, so no need to + // reference t.Underlying() to reference the underlying type. + assert(t.Kind() == t.Underlying().Kind()) + + switch t.Kind() { + case types.TINT8: + fl = addGcType(fl, types.Types[types.TINT8]) + buf.WriteString("i1") + + case types.TUINT8: + fl = addGcType(fl, types.Types[types.TUINT8]) + buf.WriteString("u1") + + case types.TINT16: + fl = addGcType(fl, types.Types[types.TINT16]) + buf.WriteString("i2") + + case types.TUINT16: + fl = addGcType(fl, types.Types[types.TUINT16]) + buf.WriteString("u2") + + case types.TINT32: + fl = addGcType(fl, types.Types[types.TINT32]) + buf.WriteString("i4") + + case types.TUINT32: + fl = addGcType(fl, types.Types[types.TUINT32]) + buf.WriteString("u4") + + case types.TINT64: + fl = addGcType(fl, types.Types[types.TINT64]) + buf.WriteString("i8") + + case types.TUINT64: + fl = addGcType(fl, types.Types[types.TUINT64]) + buf.WriteString("u8") + + case types.TINT: + fl = addGcType(fl, types.Types[INTTYPE]) + buf.WriteString(INTSTRING) + + case types.TUINT, types.TUINTPTR: + fl = addGcType(fl, types.Types[UINTTYPE]) + buf.WriteString(UINTSTRING) + + case types.TCOMPLEX64: + fl = addGcType(fl, types.Types[types.TFLOAT32]) + fl = addGcType(fl, types.Types[types.TFLOAT32]) + buf.WriteString("f4") + buf.WriteString("f4") + + case types.TCOMPLEX128: + fl = addGcType(fl, types.Types[types.TFLOAT64]) + fl = addGcType(fl, types.Types[types.TFLOAT64]) + buf.WriteString("f8") + buf.WriteString("f8") + + case types.TFLOAT32: + fl = addGcType(fl, types.Types[types.TFLOAT32]) + buf.WriteString("f4") + + case types.TFLOAT64: + fl = addGcType(fl, types.Types[types.TFLOAT64]) + buf.WriteString("f8") + + case types.TBOOL: + fl = addGcType(fl, types.Types[types.TINT8]) + buf.WriteString("i1") + + case types.TPTR: + fl = addGcType(fl, types.Types[types.TUNSAFEPTR]) + buf.WriteString("p") + + case types.TFUNC: + fl = addGcType(fl, types.Types[types.TUNSAFEPTR]) + buf.WriteString("p") + + case types.TSLICE: + fl = addGcType(fl, types.Types[types.TUNSAFEPTR]) + fl = addGcType(fl, types.Types[INTTYPE]) + fl = addGcType(fl, types.Types[INTTYPE]) + buf.WriteString("p") + buf.WriteString(INTSTRING) + buf.WriteString(INTSTRING) + + case types.TARRAY: + n := t.NumElem() + if n == 1 { + fl = accumGcshape(fl, buf, t.Elem(), nil) + } else if n > 0 { + // Represent an array with more than one element as its + // unique type, since it must be treated differently for + // regabi. + fl = addGcType(fl, t) + buf.WriteByte('[') + buf.WriteString(strconv.Itoa(int(n))) + buf.WriteString("](") + var ignore []*types.Field + // But to determine its gcshape name, we must call + // accumGcShape() on t.Elem(). + accumGcshape(ignore, buf, t.Elem(), nil) + buf.WriteByte(')') + } + + case types.TSTRUCT: + nfields := t.NumFields() + for i, f := range t.Fields().Slice() { + fl = accumGcshape(fl, buf, f.Type, f.Sym) + + // Check if we need to add an alignment field. + var pad int64 + if i < nfields-1 { + pad = t.Field(i+1).Offset - f.Offset - f.Type.Width + } else { + pad = t.Width - f.Offset - f.Type.Width + } + if pad > 0 { + // There is padding between fields or at end of + // struct. Add an alignment field. + fl = addGcType(fl, types.NewArray(types.Types[types.TUINT8], pad)) + buf.WriteString("a") + buf.WriteString(strconv.Itoa(int(pad))) + } + } + + case types.TCHAN: + fl = addGcType(fl, types.Types[types.TUNSAFEPTR]) + buf.WriteString("p") + + case types.TMAP: + fl = addGcType(fl, types.Types[types.TUNSAFEPTR]) + buf.WriteString("p") + + case types.TINTER: + fl = addGcType(fl, types.Types[types.TUNSAFEPTR]) + fl = addGcType(fl, types.Types[types.TUNSAFEPTR]) + buf.WriteString("pp") + + case types.TFORW, types.TANY: + assert(false) + + case types.TSTRING: + fl = addGcType(fl, types.Types[types.TUNSAFEPTR]) + fl = addGcType(fl, types.Types[INTTYPE]) + buf.WriteString("p") + buf.WriteString(INTSTRING) + + case types.TUNSAFEPTR: + fl = addGcType(fl, types.Types[types.TUNSAFEPTR]) + buf.WriteString("p") + + default: // Everything TTYPEPARAM and below in list of Kinds + assert(false) + } + + return fl +} + +// gcshapeType returns the GCshape type and name corresponding to type t. +func gcshapeType(t *types.Type) (*types.Type, string) { + var fl []*types.Field + buf := bytes.NewBufferString("") + + // Call CallSize so type sizes and field offsets are available. + types.CalcSize(t) + fl = accumGcshape(fl, buf, t, nil) + // TODO: Should gcshapes be in a global package, so we don't have to + // duplicate in each package? Or at least in the specified source package + // of a function/method instantiation? + gcshape := types.NewStruct(types.LocalPkg, fl) + assert(gcshape.Size() == t.Size()) + return gcshape, buf.String() +} + // getInstantiation gets the instantiantion and dictionary of the function or method nameNode // with the type arguments targs. If the instantiated function is not already // cached, then it calls genericSubst to create the new instantiation. @@ -506,6 +697,13 @@ func (g *irgen) getInstantiation(nameNode *ir.Name, targs []*types.Type, isMeth sym := typecheck.MakeInstName(nameNode.Sym(), targs, isMeth) st := g.target.Stencils[sym] if st == nil { + if false { + // Testing out gcshapeType() and gcshapeName() + for i, t := range targs { + gct, gcs := gcshapeType(t) + fmt.Printf("targ %d: %v %v\n", i, gct, gcs) + } + } // If instantiation doesn't exist yet, create it and add // to the list of decls. st = g.genericSubst(sym, nameNode, targs, isMeth) diff --git a/test/typeparam/index.go b/test/typeparam/index.go index cb9b2613c3..80824efac3 100644 --- a/test/typeparam/index.go +++ b/test/typeparam/index.go @@ -26,6 +26,26 @@ type obj struct { x int } +type obj2 struct { + x int8 + y float64 +} + +type obj3 struct { + x int64 + y int8 +} + +type inner struct { + y int64 + z int32 +} + +type obj4 struct { + x int32 + s inner +} + func main() { want := 2 @@ -43,4 +63,20 @@ func main() { if got := Index(vec3, vec3[2]); got != want { panic(fmt.Sprintf("got %d, want %d", got, want)) } + + vec4 := []obj2{obj2{2, 3.0}, obj2{3, 4.0}, obj2{4, 5.0}} + if got := Index(vec4, vec4[2]); got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } + + vec5 := []obj3{obj3{2, 3}, obj3{3, 4}, obj3{4, 5}} + if got := Index(vec5, vec5[2]); got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } + + vec6 := []obj4{obj4{2, inner{3, 4}}, obj4{3, inner{4, 5}}, obj4{4, inner{5, 6}}} + if got := Index(vec6, vec6[2]); got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } } + -- GitLab From 372b31273539b988fe887d7b7cc2ed14439278e6 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 30 Jun 2021 19:20:28 -0700 Subject: [PATCH 0387/2500] [dev.typeparams] cmd/compile: refactor top-level typechecking in unified IR This CL is a first step towards incremental typechecking during IR construction within unified IR. Namely, all top-level declarations are now typechecked as they're constructed, except for assignments (which aren't really declarations anyway). Change-Id: I65763a7659bf2e0f5e89dfe9e709d60e0fa4c631 Reviewed-on: https://go-review.googlesource.com/c/go/+/332097 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/noder/reader.go | 24 +++++++++--- src/cmd/compile/internal/noder/unified.go | 47 ++++++++++++++++------- 2 files changed, 53 insertions(+), 18 deletions(-) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 4b42ae1ec3..24977ed7f0 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -784,6 +784,8 @@ func (r *reader) funcExt(name *ir.Name) { fn.Pragma = r.pragmaFlag() r.linkname(name) + typecheck.Func(fn) + if r.bool() { fn.ABI = obj.ABI(r.uint64()) @@ -2124,7 +2126,7 @@ func (r *reader) methodWrapper(derefs int, tbase *types.Type, method *types.Fiel // TODO(mdempsky): Use method.Pos instead? pos := base.AutogeneratedPos - fn := r.newWrapperFunc(pos, sym, wrapper, method, target) + fn := r.newWrapperFunc(pos, sym, wrapper, method) var recv ir.Node = fn.Nname.Type().Recv().Nname.(*ir.Name) @@ -2143,6 +2145,8 @@ func (r *reader) methodWrapper(derefs int, tbase *types.Type, method *types.Fiel } addTailCall(pos, fn, recv, method) + + r.finishWrapperFunc(fn, target) } func (r *reader) methodValueWrapper(tbase *types.Type, method *types.Field, target *ir.Package) { @@ -2167,7 +2171,7 @@ func (r *reader) methodValueWrapper(tbase *types.Type, method *types.Field, targ // TODO(mdempsky): Use method.Pos instead? pos := base.AutogeneratedPos - fn := r.newWrapperFunc(pos, sym, nil, method, target) + fn := r.newWrapperFunc(pos, sym, nil, method) fn.SetNeedctxt(true) sym.Def = fn @@ -2181,9 +2185,11 @@ func (r *reader) methodValueWrapper(tbase *types.Type, method *types.Field, targ fn.ClosureVars = append(fn.ClosureVars, recv) addTailCall(pos, fn, recv, method) + + r.finishWrapperFunc(fn, target) } -func (r *reader) newWrapperFunc(pos src.XPos, sym *types.Sym, wrapper *types.Type, method *types.Field, target *ir.Package) *ir.Func { +func (r *reader) newWrapperFunc(pos src.XPos, sym *types.Sym, wrapper *types.Type, method *types.Field) *ir.Func { fn := ir.NewFunc(pos) fn.SetDupok(true) // TODO(mdempsky): Leave unset for local, non-generic wrappers? @@ -2214,11 +2220,19 @@ func (r *reader) newWrapperFunc(pos src.XPos, sym *types.Sym, wrapper *types.Typ defParams(ir.PPARAM, sig.Params()) defParams(ir.PPARAMOUT, sig.Results()) - target.Decls = append(target.Decls, fn) - return fn } +func (r *reader) finishWrapperFunc(fn *ir.Func, target *ir.Package) { + typecheck.Func(fn) + + ir.WithFunc(fn, func() { + typecheck.Stmts(fn.Body) + }) + + target.Decls = append(target.Decls, fn) +} + // newWrapperType returns a copy of the given signature type, but with // the receiver parameter type substituted with recvType. // If recvType is nil, newWrapperType returns a signature diff --git a/src/cmd/compile/internal/noder/unified.go b/src/cmd/compile/internal/noder/unified.go index 8397f14be8..03bcb2755b 100644 --- a/src/cmd/compile/internal/noder/unified.go +++ b/src/cmd/compile/internal/noder/unified.go @@ -109,6 +109,16 @@ func unified(noders []*noder) { r.ext = r r.pkgInit(types.LocalPkg, target) + // Type-check any top-level assignments. We ignore non-assignments + // here because other declarations are typechecked as they're + // constructed. + for i, ndecls := 0, len(target.Decls); i < ndecls; i++ { + switch n := target.Decls[i]; n.Op() { + case ir.OAS, ir.OAS2: + target.Decls[i] = typecheck.Stmt(n) + } + } + // Don't use range--bodyIdx can add closures to todoBodies. for len(todoBodies) > 0 { // The order we expand bodies doesn't matter, so pop from the end @@ -122,22 +132,12 @@ func unified(noders []*noder) { // Instantiated generic function: add to Decls for typechecking // and compilation. - if pri.dict != nil && len(pri.dict.targs) != 0 && fn.OClosure == nil { + if fn.OClosure == nil && len(pri.dict.targs) != 0 { target.Decls = append(target.Decls, fn) } } todoBodies = nil - if !quirksMode() { - // TODO(mdempsky): Investigate generating wrappers in quirks mode too. - r.wrapTypes(target) - } - - // Don't use range--typecheck can add closures to Target.Decls. - for i := 0; i < len(target.Decls); i++ { - target.Decls[i] = typecheck.Stmt(target.Decls[i]) - } - // Don't use range--typecheck can add closures to Target.Decls. for i := 0; i < len(target.Decls); i++ { if fn, ok := target.Decls[i].(*ir.Func); ok { @@ -145,8 +145,9 @@ func unified(noders []*noder) { s := fmt.Sprintf("\nbefore typecheck %v", fn) ir.Dump(s, fn) } - ir.CurFunc = fn - typecheck.Stmts(fn.Body) + ir.WithFunc(fn, func() { + typecheck.Stmts(fn.Body) + }) if base.Flag.W > 1 { s := fmt.Sprintf("\nafter typecheck %v", fn) ir.Dump(s, fn) @@ -154,6 +155,26 @@ func unified(noders []*noder) { } } + if !quirksMode() { + // TODO(mdempsky): Investigate generating wrappers in quirks mode too. + r.wrapTypes(target) + } + + // Check that nothing snuck past typechecking. + for _, n := range target.Decls { + if n.Typecheck() == 0 { + base.FatalfAt(n.Pos(), "missed typecheck: %v", n) + } + + // For functions, check that at least their first statement (if + // any) was typechecked too. + if fn, ok := n.(*ir.Func); ok && len(fn.Body) != 0 { + if stmt := fn.Body[0]; stmt.Typecheck() == 0 { + base.FatalfAt(stmt.Pos(), "missed typecheck: %v", stmt) + } + } + } + base.ExitIfErrors() // just in case } -- GitLab From 706c580ee1db800353752629882209ef6509a0b4 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 1 Jul 2021 00:28:05 -0700 Subject: [PATCH 0388/2500] [dev.typeparams] cmd/compile: simplify autotmpname Rather than manually formatting a byte-string and then using a map lookup to convert it to string, we can just use a slice. This avoids both the overhead of formatting the byte slice and the map lookup. Change-Id: Ia7b883632ea990ce9ee848dd4b4e4cdfbd611212 Reviewed-on: https://go-review.googlesource.com/c/go/+/332191 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/typecheck/dcl.go | 31 +++++++++++++++++------ 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/internal/typecheck/dcl.go b/src/cmd/compile/internal/typecheck/dcl.go index 5f8b8b3d41..f3ccbb4ac0 100644 --- a/src/cmd/compile/internal/typecheck/dcl.go +++ b/src/cmd/compile/internal/typecheck/dcl.go @@ -6,7 +6,7 @@ package typecheck import ( "fmt" - "strconv" + "sync" "cmd/compile/internal/base" "cmd/compile/internal/ir" @@ -430,15 +430,30 @@ func TempAt(pos src.XPos, curfn *ir.Func, t *types.Type) *ir.Name { return n } +var ( + autotmpnamesmu sync.Mutex + autotmpnames []string +) + // autotmpname returns the name for an autotmp variable numbered n. func autotmpname(n int) string { - // Give each tmp a different name so that they can be registerized. - // Add a preceding . to avoid clashing with legal names. - const prefix = ".autotmp_" - // Start with a buffer big enough to hold a large n. - b := []byte(prefix + " ")[:len(prefix)] - b = strconv.AppendInt(b, int64(n), 10) - return types.InternString(b) + autotmpnamesmu.Lock() + defer autotmpnamesmu.Unlock() + + // Grow autotmpnames, if needed. + if n >= len(autotmpnames) { + autotmpnames = append(autotmpnames, make([]string, n+1-len(autotmpnames))...) + autotmpnames = autotmpnames[:cap(autotmpnames)] + } + + s := autotmpnames[n] + if s == "" { + // Give each tmp a different name so that they can be registerized. + // Add a preceding . to avoid clashing with legal names. + s = fmt.Sprintf(".autotmp_%d", n) + autotmpnames[n] = s + } + return s } // f is method type, with receiver. -- GitLab From 1cd505c353e4656ba28fd8de8708e8c8e6c21cbf Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 28 Jun 2021 19:41:29 -0700 Subject: [PATCH 0389/2500] [dev.typeparams] cmd/compile/internal/types2: "comparable" must not be visible before Go 1.18 While at it, clean up the setup of comparable in universe.go. Fixes #46090 Change-Id: I9655b3e137a03763d677d9a2a730c5570ccff6dc Reviewed-on: https://go-review.googlesource.com/c/go/+/331517 Trust: Robert Griesemer Reviewed-by: Robert Findley --- .../types2/testdata/fixedbugs/issue46090.go2 | 9 +++ src/cmd/compile/internal/types2/typexpr.go | 2 +- src/cmd/compile/internal/types2/universe.go | 61 +++++++------------ 3 files changed, 32 insertions(+), 40 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue46090.go2 diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46090.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46090.go2 new file mode 100644 index 0000000000..81b31974c8 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46090.go2 @@ -0,0 +1,9 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// The predeclared type comparable is not visible before Go 1.18. + +package go1_17 + +type _ comparable // ERROR undeclared diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index fe676be2ef..5626fed756 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -25,7 +25,7 @@ func (check *Checker) ident(x *operand, e *syntax.Name, def *Named, wantType boo // Note that we cannot use check.lookup here because the returned scope // may be different from obj.Parent(). See also Scope.LookupParent doc. scope, obj := check.scope.LookupParent(e.Value, check.pos) - if obj == nil { + if obj == nil || obj == universeComparable && !check.allowVersion(check.pkg, 1, 18) { if e.Value == "_" { check.error(e, "cannot use _ as value or type") } else { diff --git a/src/cmd/compile/internal/types2/universe.go b/src/cmd/compile/internal/types2/universe.go index 2bcc49778e..c9b53bac92 100644 --- a/src/cmd/compile/internal/types2/universe.go +++ b/src/cmd/compile/internal/types2/universe.go @@ -20,11 +20,12 @@ var Universe *Scope var Unsafe *Package var ( - universeIota *Const - universeByte *Basic // uint8 alias, but has name "byte" - universeRune *Basic // int32 alias, but has name "rune" - universeAny *Interface - universeError *Named + universeIota *Const + universeByte *Basic // uint8 alias, but has name "byte" + universeRune *Basic // int32 alias, but has name "rune" + universeAny *Interface + universeError *Named + universeComparable Object ) // Typ contains the predeclared *Basic types indexed by their @@ -77,21 +78,30 @@ func defPredeclaredTypes() { def(NewTypeName(nopos, nil, t.name, t)) } - // any - // (Predeclared and entered into universe scope so we do all the - // usual checks; but removed again from scope later since it's - // only visible as constraint in a type parameter list.) + // type any = interface{} + // Entered into universe scope so we do all the usual checks; + // but removed again from scope later since it's only visible + // as constraint in a type parameter list. def(NewTypeName(nopos, nil, "any", &emptyInterface)) - // Error has a nil package in its qualified name since it is in no package + // type error interface{ Error() string } { res := NewVar(nopos, nil, "", Typ[String]) - sig := &Signature{results: NewTuple(res)} + sig := NewSignature(nil, nil, NewTuple(res), false) err := NewFunc(nopos, nil, "Error", sig) typ := &Named{underlying: NewInterfaceType([]*Func{err}, nil)} sig.recv = NewVar(nopos, nil, "", typ) def(NewTypeName(nopos, nil, "error", typ)) } + + // type comparable interface{ ==() } + { + sig := NewSignature(nil, nil, nil, false) + eql := NewFunc(nopos, nil, "==", sig) + typ := &Named{underlying: NewInterfaceType([]*Func{eql}, nil)} + sig.recv = NewVar(nopos, nil, "", typ) + def(NewTypeName(nopos, nil, "comparable", typ)) + } } var predeclaredConsts = [...]struct { @@ -200,33 +210,6 @@ func DefPredeclaredTestFuncs() { def(newBuiltin(_Trace)) } -func defPredeclaredComparable() { - // The "comparable" interface can be imagined as defined like - // - // type comparable interface { - // == () untyped bool - // != () untyped bool - // } - // - // == and != cannot be user-declared but we can declare - // a magic method == and check for its presence when needed. - - // Define interface { == () }. We don't care about the signature - // for == so leave it empty except for the receiver, which is - // set up later to match the usual interface method assumptions. - sig := new(Signature) - eql := NewFunc(nopos, nil, "==", sig) - iface := NewInterfaceType([]*Func{eql}, nil) - - // set up the defined type for the interface - obj := NewTypeName(nopos, nil, "comparable", nil) - named := NewNamed(obj, iface, nil) - obj.color_ = black - sig.recv = NewVar(nopos, nil, "", named) // complete == signature - - def(obj) -} - func init() { Universe = NewScope(nil, nopos, nopos, "universe") Unsafe = NewPackage("unsafe", "unsafe") @@ -236,13 +219,13 @@ func init() { defPredeclaredConsts() defPredeclaredNil() defPredeclaredFuncs() - defPredeclaredComparable() universeIota = Universe.Lookup("iota").(*Const) universeByte = Universe.Lookup("byte").(*TypeName).typ.(*Basic) universeRune = Universe.Lookup("rune").(*TypeName).typ.(*Basic) universeAny = Universe.Lookup("any").(*TypeName).typ.(*Interface) universeError = Universe.Lookup("error").(*TypeName).typ.(*Named) + universeComparable = Universe.Lookup("comparable") // "any" is only visible as constraint in a type parameter list delete(Universe.elems, "any") -- GitLab From 9cb1b0f50b5852b24e1a7b66f09faa1a521ae108 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 29 Jun 2021 12:22:21 -0700 Subject: [PATCH 0390/2500] [dev.typeparams] cmd/compile/internal/types2: delay interface check for type bounds While at it, clean up code for collecting/declaring type parameters. For #40789. Change-Id: I0855137d5ee85c0ae2fa60d33b28c24a33132fbc Reviewed-on: https://go-review.googlesource.com/c/go/+/331690 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/decl.go | 85 +++++++------------ src/cmd/compile/internal/types2/signature.go | 7 +- .../types2/testdata/fixedbugs/issue40789.go2 | 37 ++++++++ src/cmd/compile/internal/types2/type.go | 6 +- 4 files changed, 76 insertions(+), 59 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue40789.go2 diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 00b4ef7010..d36da06f42 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -674,75 +674,52 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named } -func (check *Checker) collectTypeParams(list []*syntax.Field) (tparams []*TypeName) { - // Type parameter lists should not be empty. The parser will - // complain but we still may get an incorrect AST: ignore it. - if len(list) == 0 { - return - } +func (check *Checker) collectTypeParams(list []*syntax.Field) []*TypeName { + tparams := make([]*TypeName, len(list)) - // Declare type parameters up-front, with empty interface as type bound. + // Declare type parameters up-front. // The scope of type parameters starts at the beginning of the type parameter - // list (so we can have mutually recursive parameterized interfaces). - for _, f := range list { - tparams = check.declareTypeParam(tparams, f.Name) + // list (so we can have mutually recursive parameterized type bounds). + for i, f := range list { + tparams[i] = check.declareTypeParam(i, f.Name) } var bound Type - for i, j := 0, 0; i < len(list); i = j { - f := list[i] - - // determine the range of type parameters list[i:j] with identical type bound - // (declared as in (type a, b, c B)) - j = i + 1 - for j < len(list) && list[j].Type == f.Type { - j++ - } - - // this should never be the case, but be careful - if f.Type == nil { - continue - } - - // The predeclared identifier "any" is visible only as a constraint - // in a type parameter list. Look for it before general constraint - // resolution. - if tident, _ := unparen(f.Type).(*syntax.Name); tident != nil && tident.Value == "any" && check.lookup("any") == nil { - bound = universeAny - } else { - bound = check.typ(f.Type) - } - - // type bound must be an interface - // TODO(gri) We should delay the interface check because - // we may not have a complete interface yet: - // type C(type T C) interface {} - // (issue #39724). - if _, ok := under(bound).(*Interface); ok { - // set the type bounds - for i < j { - tparams[i].typ.(*TypeParam).bound = bound - i++ - } - } else if bound != Typ[Invalid] { - check.errorf(f.Type, "%s is not an interface", bound) + for i, f := range list { + // Optimization: Re-use the previous type bound if it hasn't changed. + // This also preserves the grouped output of type parameter lists + // when printing type strings. + if i == 0 || f.Type != list[i-1].Type { + bound = check.boundType(f.Type) } + tparams[i].typ.(*TypeParam).bound = bound } - return + return tparams } -func (check *Checker) declareTypeParam(tparams []*TypeName, name *syntax.Name) []*TypeName { +func (check *Checker) declareTypeParam(index int, name *syntax.Name) *TypeName { tpar := NewTypeName(name.Pos(), check.pkg, name.Value, nil) - check.NewTypeParam(tpar, len(tparams), &emptyInterface) // assigns type to tpar as a side-effect + check.NewTypeParam(tpar, index, nil) // assigns type to tpar as a side-effect check.declare(check.scope, name, tpar, check.scope.pos) // TODO(gri) check scope position - tparams = append(tparams, tpar) + return tpar +} - if check.conf.Trace { - check.trace(name.Pos(), "type param = %v", tparams[len(tparams)-1]) +// boundType type-checks the type expression e and returns its type, or Typ[Invalid]. +// The type must be an interface, including the predeclared type "any". +func (check *Checker) boundType(e syntax.Expr) Type { + // The predeclared identifier "any" is visible only as a type bound in a type parameter list. + if name, _ := unparen(e).(*syntax.Name); name != nil && name.Value == "any" && check.lookup("any") == nil { + return universeAny } - return tparams + bound := check.typ(e) + check.later(func() { + if _, ok := under(bound).(*Interface); !ok && bound != Typ[Invalid] { + check.errorf(e, "%s is not an interface", bound) + } + }) + return bound } func (check *Checker) collectMethods(obj *TypeName) { diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index a7edc5ac03..01158187ba 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -48,10 +48,9 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] // blank identifiers were found => use rewritten receiver type recvTyp = isubst(recvPar.Type, smap) } - // TODO(gri) rework declareTypeParams - sig.rparams = nil - for _, rparam := range rparams { - sig.rparams = check.declareTypeParam(sig.rparams, rparam) + sig.rparams = make([]*TypeName, len(rparams)) + for i, rparam := range rparams { + sig.rparams[i] = check.declareTypeParam(i, rparam) } // determine receiver type to get its type parameters // and the respective type parameter bounds diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue40789.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue40789.go2 new file mode 100644 index 0000000000..9eea4ad60a --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue40789.go2 @@ -0,0 +1,37 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "fmt" + +func main() { + m := map[string]int{ + "a": 6, + "b": 7, + } + fmt.Println(copyMap[map[string]int, string, int](m)) +} + +type Map[K comparable, V any] interface { + map[K] V +} + +func copyMap[M Map[K, V], K comparable, V any](m M) M { + m1 := make(M) + for k, v := range m { + m1[k] = v + } + return m1 +} + +// simpler test case from the same issue + +type A[X comparable] interface { + []X +} + +func f[B A[X], X comparable]() B { + return nil +} diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 2cfcabbdb5..05e6d77d22 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -626,7 +626,11 @@ func (t *TypeParam) SetId(id uint64) { } func (t *TypeParam) Bound() *Interface { - iface := asInterface(t.bound) + // we may not have an interface (error reported elsewhere) + iface, _ := under(t.bound).(*Interface) + if iface == nil { + return &emptyInterface + } // use the type bound position if we have one pos := nopos if n, _ := t.bound.(*Named); n != nil { -- GitLab From 1eb756689c413c84bb2bf91396b54028671bc541 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 30 Jun 2021 11:21:32 -0700 Subject: [PATCH 0391/2500] [dev.typeparams] cmd/compile/internal/types2: make Interface.obj a *TypeName We know the exact type, so make it that. This saves some code and a word of space with each Interface. Follow-up on a comment in https://golang.org/cl/329309. Change-Id: I827e39d17aae159a52ac563544c5e6d017bc05ec Reviewed-on: https://go-review.googlesource.com/c/go/+/332011 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/call.go | 7 +++---- src/cmd/compile/internal/types2/sizeof_test.go | 2 +- src/cmd/compile/internal/types2/type.go | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 34dafce8bf..3377270ef8 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -479,11 +479,10 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) { var why string if tpar := asTypeParam(x.typ); tpar != nil { // Type parameter bounds don't specify fields, so don't mention "field". - switch obj := tpar.Bound().obj.(type) { - case nil: + if tname := tpar.Bound().obj; tname != nil { + why = check.sprintf("interface %s has no method %s", tname.name, sel) + } else { why = check.sprintf("type bound for %s has no method %s", x.typ, sel) - case *TypeName: - why = check.sprintf("interface %s has no method %s", obj.name, sel) } } else { why = check.sprintf("type %s has no field or method %s", x.typ, sel) diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go index 82e1221b67..0b1f7dacad 100644 --- a/src/cmd/compile/internal/types2/sizeof_test.go +++ b/src/cmd/compile/internal/types2/sizeof_test.go @@ -28,7 +28,7 @@ func TestSizeof(t *testing.T) { {Tuple{}, 12, 24}, {Signature{}, 44, 88}, {Union{}, 24, 48}, - {Interface{}, 44, 88}, + {Interface{}, 40, 80}, {Map{}, 16, 32}, {Chan{}, 12, 24}, {Named{}, 84, 160}, diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 05e6d77d22..f8aa453d5c 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -264,7 +264,7 @@ func (s *Signature) Variadic() bool { return s.variadic } // An Interface represents an interface type. type Interface struct { - obj Object // type name object defining this interface; or nil (for better error messages) + obj *TypeName // corresponding declared object; or nil (for better error messages) methods []*Func // ordered list of explicitly declared methods embeddeds []Type // ordered list of explicitly embedded elements embedPos *[]syntax.Pos // positions of embedded elements; or nil (for error messages) - use pointer to save space -- GitLab From fac21803ce513b3d8cab1629f37fd0a9ea2fbe07 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 30 Jun 2021 12:45:51 -0700 Subject: [PATCH 0392/2500] [dev.typeparams] cmd/compile/internal/types2: rename newTypeSet -> computeTypeSet Follow-up on comment in https://golang.org/cl/329309. Change-Id: I31f746180237b916c1825fa1688641849478ba41 Reviewed-on: https://go-review.googlesource.com/c/go/+/332089 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/interface.go | 2 +- src/cmd/compile/internal/types2/type.go | 4 ++-- src/cmd/compile/internal/types2/typeset.go | 6 +++--- src/cmd/compile/internal/types2/typexpr.go | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index 18dc573340..1f4e80951a 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -114,7 +114,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType // Compute type set with a non-nil *Checker as soon as possible // to report any errors. Subsequent uses of type sets should be // using this computed type set and won't need to pass in a *Checker. - check.later(func() { newTypeSet(check, iface.Pos(), ityp) }) + check.later(func() { computeTypeSet(check, iface.Pos(), ityp) }) } func flattenUnion(list []syntax.Expr, x syntax.Expr) []syntax.Expr { diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index f8aa453d5c..b41dceea70 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -274,7 +274,7 @@ type Interface struct { } // typeSet returns the type set for interface t. -func (t *Interface) typeSet() *TypeSet { return newTypeSet(nil, nopos, t) } +func (t *Interface) typeSet() *TypeSet { return computeTypeSet(nil, nopos, t) } // is reports whether interface t represents types that all satisfy f. func (t *Interface) is(f func(Type, bool) bool) bool { @@ -637,7 +637,7 @@ func (t *TypeParam) Bound() *Interface { pos = n.obj.pos } // TODO(gri) switch this to an unexported method on Checker. - newTypeSet(t.check, pos, iface) + computeTypeSet(t.check, pos, iface) return iface } diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index ce4a776f8f..265221501f 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -78,8 +78,8 @@ func (s *TypeSet) String() string { // topTypeSet may be used as type set for the empty interface. var topTypeSet TypeSet -// newTypeSet may be called with check == nil. -func newTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *TypeSet { +// computeTypeSet may be called with check == nil. +func computeTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *TypeSet { if ityp.tset != nil { return ityp.tset } @@ -188,7 +188,7 @@ func newTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *TypeSet { var types Type switch t := under(typ).(type) { case *Interface: - tset := newTypeSet(check, pos, t) + tset := computeTypeSet(check, pos, t) for _, m := range tset.methods { addMethod(pos, m, false) // use embedding position pos rather than m.pos } diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 5626fed756..e861f7e784 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -141,7 +141,7 @@ func (check *Checker) ordinaryType(pos syntax.Pos, typ Type) { // interface methods. Delay this check to the end of type-checking. check.later(func() { if t := asInterface(typ); t != nil { - tset := newTypeSet(check, pos, t) // TODO(gri) is this the correct position? + tset := computeTypeSet(check, pos, t) // TODO(gri) is this the correct position? if tset.types != nil { check.softErrorf(pos, "interface contains type constraints (%s)", tset.types) return -- GitLab From 1aadb18f83bd9e0e2faf2ccc9bce301108aa1221 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 30 Jun 2021 12:56:50 -0700 Subject: [PATCH 0393/2500] [dev.typeparams] cmd/compile/internal/types2: move Struct type decl into struct.go (cleanup) Change-Id: I074550236785091d2f79dd5de73c3462614c5c0e Reviewed-on: https://go-review.googlesource.com/c/go/+/332090 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/struct.go | 46 +++++++++++++++++++++++ src/cmd/compile/internal/types2/type.go | 39 ------------------- 2 files changed, 46 insertions(+), 39 deletions(-) diff --git a/src/cmd/compile/internal/types2/struct.go b/src/cmd/compile/internal/types2/struct.go index 302b9886f4..f1d82fb50c 100644 --- a/src/cmd/compile/internal/types2/struct.go +++ b/src/cmd/compile/internal/types2/struct.go @@ -9,6 +9,52 @@ import ( "strconv" ) +// ---------------------------------------------------------------------------- +// API + +// A Struct represents a struct type. +type Struct struct { + fields []*Var + tags []string // field tags; nil if there are no tags +} + +// NewStruct returns a new struct with the given fields and corresponding field tags. +// If a field with index i has a tag, tags[i] must be that tag, but len(tags) may be +// only as long as required to hold the tag with the largest index i. Consequently, +// if no field has a tag, tags may be nil. +func NewStruct(fields []*Var, tags []string) *Struct { + var fset objset + for _, f := range fields { + if f.name != "_" && fset.insert(f) != nil { + panic("multiple fields with the same name") + } + } + if len(tags) > len(fields) { + panic("more tags than fields") + } + return &Struct{fields: fields, tags: tags} +} + +// NumFields returns the number of fields in the struct (including blank and embedded fields). +func (s *Struct) NumFields() int { return len(s.fields) } + +// Field returns the i'th field for 0 <= i < NumFields(). +func (s *Struct) Field(i int) *Var { return s.fields[i] } + +// Tag returns the i'th field tag for 0 <= i < NumFields(). +func (s *Struct) Tag(i int) string { + if i < len(s.tags) { + return s.tags[i] + } + return "" +} + +func (s *Struct) Underlying() Type { return s } +func (s *Struct) String() string { return TypeString(s, nil) } + +// ---------------------------------------------------------------------------- +// Implementation + func (check *Checker) structType(styp *Struct, e *syntax.StructType) { if e.FieldList == nil { return diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index b41dceea70..aff97f9a98 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -124,43 +124,6 @@ func NewSlice(elem Type) *Slice { return &Slice{elem: elem} } // Elem returns the element type of slice s. func (s *Slice) Elem() Type { return s.elem } -// A Struct represents a struct type. -type Struct struct { - fields []*Var - tags []string // field tags; nil if there are no tags -} - -// NewStruct returns a new struct with the given fields and corresponding field tags. -// If a field with index i has a tag, tags[i] must be that tag, but len(tags) may be -// only as long as required to hold the tag with the largest index i. Consequently, -// if no field has a tag, tags may be nil. -func NewStruct(fields []*Var, tags []string) *Struct { - var fset objset - for _, f := range fields { - if f.name != "_" && fset.insert(f) != nil { - panic("multiple fields with the same name") - } - } - if len(tags) > len(fields) { - panic("more tags than fields") - } - return &Struct{fields: fields, tags: tags} -} - -// NumFields returns the number of fields in the struct (including blank and embedded fields). -func (s *Struct) NumFields() int { return len(s.fields) } - -// Field returns the i'th field for 0 <= i < NumFields(). -func (s *Struct) Field(i int) *Var { return s.fields[i] } - -// Tag returns the i'th field tag for 0 <= i < NumFields(). -func (s *Struct) Tag(i int) string { - if i < len(s.tags) { - return s.tags[i] - } - return "" -} - // A Pointer represents a pointer type. type Pointer struct { base Type // element type @@ -741,7 +704,6 @@ var theTop = &top{} func (t *Basic) Underlying() Type { return t } func (t *Array) Underlying() Type { return t } func (t *Slice) Underlying() Type { return t } -func (t *Struct) Underlying() Type { return t } func (t *Pointer) Underlying() Type { return t } func (t *Tuple) Underlying() Type { return t } func (t *Signature) Underlying() Type { return t } @@ -757,7 +719,6 @@ func (t *top) Underlying() Type { return t } func (t *Basic) String() string { return TypeString(t, nil) } func (t *Array) String() string { return TypeString(t, nil) } func (t *Slice) String() string { return TypeString(t, nil) } -func (t *Struct) String() string { return TypeString(t, nil) } func (t *Pointer) String() string { return TypeString(t, nil) } func (t *Tuple) String() string { return TypeString(t, nil) } func (t *Signature) String() string { return TypeString(t, nil) } -- GitLab From 0e0b80cb56ba3bd2128417d9368b4e74b1e45d95 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 30 Jun 2021 13:00:14 -0700 Subject: [PATCH 0394/2500] [dev.typeparams] cmd/compile/internal/types2: move Signature type decl into signature.go (cleanup) Change-Id: I68c9da6a87cdc15bde8bffa8cb86fb8705eb1f8e Reviewed-on: https://go-review.googlesource.com/c/go/+/332091 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/signature.go | 71 ++++++++++++++++++++ src/cmd/compile/internal/types2/type.go | 64 ------------------ 2 files changed, 71 insertions(+), 64 deletions(-) diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index 01158187ba..ab9a1c487e 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -9,6 +9,77 @@ import ( "fmt" ) +// ---------------------------------------------------------------------------- +// API + +// A Signature represents a (non-builtin) function or method type. +// The receiver is ignored when comparing signatures for identity. +type Signature struct { + // We need to keep the scope in Signature (rather than passing it around + // and store it in the Func Object) because when type-checking a function + // literal we call the general type checker which returns a general Type. + // We then unpack the *Signature and use the scope for the literal body. + rparams []*TypeName // receiver type parameters from left to right; or nil + tparams []*TypeName // type parameters from left to right; or nil + scope *Scope // function scope, present for package-local signatures + recv *Var // nil if not a method + params *Tuple // (incoming) parameters from left to right; or nil + results *Tuple // (outgoing) results from left to right; or nil + variadic bool // true if the last parameter's type is of the form ...T (or string, for append built-in only) +} + +// NewSignature returns a new function type for the given receiver, parameters, +// and results, either of which may be nil. If variadic is set, the function +// is variadic, it must have at least one parameter, and the last parameter +// must be of unnamed slice type. +func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature { + if variadic { + n := params.Len() + if n == 0 { + panic("types2.NewSignature: variadic function must have at least one parameter") + } + if _, ok := params.At(n - 1).typ.(*Slice); !ok { + panic("types2.NewSignature: variadic parameter must be of unnamed slice type") + } + } + return &Signature{recv: recv, params: params, results: results, variadic: variadic} +} + +// Recv returns the receiver of signature s (if a method), or nil if a +// function. It is ignored when comparing signatures for identity. +// +// For an abstract method, Recv returns the enclosing interface either +// as a *Named or an *Interface. Due to embedding, an interface may +// contain methods whose receiver type is a different interface. +func (s *Signature) Recv() *Var { return s.recv } + +// TParams returns the type parameters of signature s, or nil. +func (s *Signature) TParams() []*TypeName { return s.tparams } + +// RParams returns the receiver type params of signature s, or nil. +func (s *Signature) RParams() []*TypeName { return s.rparams } + +// SetTParams sets the type parameters of signature s. +func (s *Signature) SetTParams(tparams []*TypeName) { s.tparams = tparams } + +// SetRParams sets the receiver type params of signature s. +func (s *Signature) SetRParams(rparams []*TypeName) { s.rparams = rparams } + +// Params returns the parameters of signature s, or nil. +func (s *Signature) Params() *Tuple { return s.params } + +// Results returns the results of signature s, or nil. +func (s *Signature) Results() *Tuple { return s.results } + +// Variadic reports whether the signature s is variadic. +func (s *Signature) Variadic() bool { return s.variadic } + +func (s *Signature) Underlying() Type { return s } +func (s *Signature) String() string { return TypeString(s, nil) } + +// ---------------------------------------------------------------------------- +// Implementation + // Disabled by default, but enabled when running tests (via types_test.go). var acceptMethodTypeParams bool diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index aff97f9a98..3a9511de48 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -163,68 +163,6 @@ func (t *Tuple) Len() int { // At returns the i'th variable of tuple t. func (t *Tuple) At(i int) *Var { return t.vars[i] } -// A Signature represents a (non-builtin) function or method type. -// The receiver is ignored when comparing signatures for identity. -type Signature struct { - // We need to keep the scope in Signature (rather than passing it around - // and store it in the Func Object) because when type-checking a function - // literal we call the general type checker which returns a general Type. - // We then unpack the *Signature and use the scope for the literal body. - rparams []*TypeName // receiver type parameters from left to right; or nil - tparams []*TypeName // type parameters from left to right; or nil - scope *Scope // function scope, present for package-local signatures - recv *Var // nil if not a method - params *Tuple // (incoming) parameters from left to right; or nil - results *Tuple // (outgoing) results from left to right; or nil - variadic bool // true if the last parameter's type is of the form ...T (or string, for append built-in only) -} - -// NewSignature returns a new function type for the given receiver, parameters, -// and results, either of which may be nil. If variadic is set, the function -// is variadic, it must have at least one parameter, and the last parameter -// must be of unnamed slice type. -func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature { - if variadic { - n := params.Len() - if n == 0 { - panic("types2.NewSignature: variadic function must have at least one parameter") - } - if _, ok := params.At(n - 1).typ.(*Slice); !ok { - panic("types2.NewSignature: variadic parameter must be of unnamed slice type") - } - } - return &Signature{recv: recv, params: params, results: results, variadic: variadic} -} - -// Recv returns the receiver of signature s (if a method), or nil if a -// function. It is ignored when comparing signatures for identity. -// -// For an abstract method, Recv returns the enclosing interface either -// as a *Named or an *Interface. Due to embedding, an interface may -// contain methods whose receiver type is a different interface. -func (s *Signature) Recv() *Var { return s.recv } - -// TParams returns the type parameters of signature s, or nil. -func (s *Signature) TParams() []*TypeName { return s.tparams } - -// RParams returns the receiver type params of signature s, or nil. -func (s *Signature) RParams() []*TypeName { return s.rparams } - -// SetTParams sets the type parameters of signature s. -func (s *Signature) SetTParams(tparams []*TypeName) { s.tparams = tparams } - -// SetRParams sets the receiver type params of signature s. -func (s *Signature) SetRParams(rparams []*TypeName) { s.rparams = rparams } - -// Params returns the parameters of signature s, or nil. -func (s *Signature) Params() *Tuple { return s.params } - -// Results returns the results of signature s, or nil. -func (s *Signature) Results() *Tuple { return s.results } - -// Variadic reports whether the signature s is variadic. -func (s *Signature) Variadic() bool { return s.variadic } - // An Interface represents an interface type. type Interface struct { obj *TypeName // corresponding declared object; or nil (for better error messages) @@ -706,7 +644,6 @@ func (t *Array) Underlying() Type { return t } func (t *Slice) Underlying() Type { return t } func (t *Pointer) Underlying() Type { return t } func (t *Tuple) Underlying() Type { return t } -func (t *Signature) Underlying() Type { return t } func (t *Interface) Underlying() Type { return t } func (t *Map) Underlying() Type { return t } func (t *Chan) Underlying() Type { return t } @@ -721,7 +658,6 @@ func (t *Array) String() string { return TypeString(t, nil) } func (t *Slice) String() string { return TypeString(t, nil) } func (t *Pointer) String() string { return TypeString(t, nil) } func (t *Tuple) String() string { return TypeString(t, nil) } -func (t *Signature) String() string { return TypeString(t, nil) } func (t *Interface) String() string { return TypeString(t, nil) } func (t *Map) String() string { return TypeString(t, nil) } func (t *Chan) String() string { return TypeString(t, nil) } -- GitLab From 9ba294e15bf09636ce3069ad577d8411c9730504 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 30 Jun 2021 15:38:56 -0700 Subject: [PATCH 0395/2500] [dev.typeparams] cmd/compile: fix getDictionarySym for methods references, write out sub-dictionaries For method references (only), selectorExpr() now computes n.Selection, which is the generic method that is selected. This allows us to compute as needed the proper sub-dictionary for method reference. Also cleans up some code for distinguishing method references from references to a field that has a function value (especially in the presence of embedded fields). Change-Id: I9c5b789c15537ff48c70ca7a6444aa0420178a3a Reviewed-on: https://go-review.googlesource.com/c/go/+/332095 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/expr.go | 29 +++++++++++++++++--- src/cmd/compile/internal/noder/stencil.go | 33 ++++++++++------------- src/cmd/compile/internal/noder/types.go | 14 ++++++---- 3 files changed, 48 insertions(+), 28 deletions(-) diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 017e98986f..d974b291d0 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -206,6 +206,30 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto // only be fully transformed once it has an instantiated type. n := ir.NewSelectorExpr(pos, ir.OXDOT, x, typecheck.Lookup(expr.Sel.Value)) typed(g.typ(typ), n) + + // Fill in n.Selection for a generic method reference, even though we + // won't use it directly, since it is useful for analysis. + // Specifically do not fill in for fields or interfaces methods, so + // n.Selection being non-nil means a method reference, rather than an + // interface reference or reference to a field with a function value. + obj2 := g.info.Selections[expr].Obj() + sig := types2.AsSignature(obj2.Type()) + if sig == nil || sig.Recv() == nil { + return n + } + // recvType is the type of the last embedded field. Because of the + // way methods are imported, g.obj(obj2) doesn't work across + // packages, so we have to lookup the method via the receiver type. + recvType := deref2(sig.Recv().Type()) + if types2.AsInterface(recvType.Underlying()) != nil { + return n + } + + index := g.info.Selections[expr].Index() + last := index[len(index)-1] + recvObj := types2.AsNamed(recvType).Obj() + recv := g.pkg(recvObj.Pkg()).Lookup(recvObj.Name()).Def + n.Selection = recv.Type().Methods().Index(last) return n } @@ -308,10 +332,7 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto // getTargs gets the targs associated with the receiver of a selected method func getTargs(selinfo *types2.Selection) []types2.Type { - r := selinfo.Recv() - if p := types2.AsPointer(r); p != nil { - r = p.Elem() - } + r := deref2(selinfo.Recv()) n := types2.AsNamed(r) if n == nil { base.Fatalf("Incorrect type for selinfo %v", selinfo) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index b228e40258..c04300a165 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1282,14 +1282,15 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) if n.Op() == ir.OCALL { call := n.(*ir.CallExpr) if call.X.Op() == ir.OXDOT { - subtargs := deref(n.(*ir.CallExpr).X.(*ir.SelectorExpr).X.Type()).RParams() + subtargs := deref(call.X.(*ir.SelectorExpr).X.Type()).RParams() s2targs := make([]*types.Type, len(subtargs)) for i, t := range subtargs { s2targs[i] = subst.Typ(t) } - sym = typecheck.MakeDictName(ir.MethodSym(call.X.(*ir.SelectorExpr).X.Type(), call.X.(*ir.SelectorExpr).Sel), s2targs, true) + nameNode := call.X.(*ir.SelectorExpr).Selection.Nname.(*ir.Name) + sym = g.getDictionarySym(nameNode, s2targs, true) } else { - inst := n.(*ir.CallExpr).X.(*ir.InstExpr) + inst := call.X.(*ir.InstExpr) var nameNode *ir.Name var meth *ir.SelectorExpr var isMeth bool @@ -1325,14 +1326,12 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) for i, t := range subtargs { s2targs[i] = subst.Typ(t) } - sym = typecheck.MakeDictName(ir.MethodSym(selExpr.X.Type(), selExpr.Sel), s2targs, true) + nameNode := selExpr.Selection.Nname.(*ir.Name) + sym = g.getDictionarySym(nameNode, s2targs, true) } // TODO: handle closure cases that need sub-dictionaries, get rid of conditional if sym != nil { - // TODO: uncomment once we're sure all the - // subdictionaries are created correctly. - // Methods above aren't yet generating dictionaries recursively yet. - //off = objw.SymPtr(lsym, off, sym.Linksym(), 0) + off = objw.SymPtr(lsym, off, sym.Linksym(), 0) infoPrint(" - Subdict %v\n", sym.Name) } } @@ -1403,18 +1402,14 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo { infoPrint(" Closure&subdictionary required at generic function value %v\n", n.(*ir.InstExpr).X) info.subDictCalls = append(info.subDictCalls, n) } else if n.Op() == ir.OXDOT && !n.(*ir.SelectorExpr).Implicit() && - !n.(*ir.SelectorExpr).X.Type().IsInterface() && + n.(*ir.SelectorExpr).Selection != nil && len(n.(*ir.SelectorExpr).X.Type().RParams()) > 0 { - // Fix this - doesn't account for embedded fields, etc. - field := typecheck.Lookdot1(n.(*ir.SelectorExpr), n.(*ir.SelectorExpr).Sel, n.(*ir.SelectorExpr).X.Type(), n.(*ir.SelectorExpr).X.Type().Fields(), 0) - if field == nil { - if n.(*ir.SelectorExpr).X.Op() == ir.OTYPE { - infoPrint(" Closure&subdictionary required at generic meth expr %v\n", n) - } else { - infoPrint(" Closure&subdictionary required at generic meth value %v\n", n) - } - info.subDictCalls = append(info.subDictCalls, n) + if n.(*ir.SelectorExpr).X.Op() == ir.OTYPE { + infoPrint(" Closure&subdictionary required at generic meth expr %v\n", n) + } else { + infoPrint(" Closure&subdictionary required at generic meth value %v\n", n) } + info.subDictCalls = append(info.subDictCalls, n) } if n.Op() == ir.OCALL && n.(*ir.CallExpr).X.Op() == ir.OFUNCINST { infoPrint(" Subdictionary at generic function call: %v - %v\n", n.(*ir.CallExpr).X.(*ir.InstExpr).X, n) @@ -1422,7 +1417,7 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo { info.subDictCalls = append(info.subDictCalls, n) } if n.Op() == ir.OCALL && n.(*ir.CallExpr).X.Op() == ir.OXDOT && - !n.(*ir.CallExpr).X.(*ir.SelectorExpr).X.Type().IsInterface() && + n.(*ir.CallExpr).X.(*ir.SelectorExpr).Selection != nil && len(deref(n.(*ir.CallExpr).X.(*ir.SelectorExpr).X.Type()).RParams()) > 0 { infoPrint(" Subdictionary at generic method call: %v\n", n) n.(*ir.CallExpr).X.(*ir.SelectorExpr).SetImplicit(true) diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index b37793b2d0..a0b7fea7cb 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -278,11 +278,7 @@ func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) { methods := make([]*types.Field, typ.NumMethods()) for i := range methods { m := typ.Method(i) - recvType := types2.AsSignature(m.Type()).Recv().Type() - ptr := types2.AsPointer(recvType) - if ptr != nil { - recvType = ptr.Elem() - } + recvType := deref2(types2.AsSignature(m.Type()).Recv().Type()) var meth *ir.Name if m.Pkg() != g.self { // Imported methods cannot be loaded by name (what @@ -471,3 +467,11 @@ var dirs = [...]types.ChanDir{ types2.SendOnly: types.Csend, types2.RecvOnly: types.Crecv, } + +// deref2 does a single deref of types2 type t, if it is a pointer type. +func deref2(t types2.Type) types2.Type { + if ptr := types2.AsPointer(t); ptr != nil { + t = ptr.Elem() + } + return t +} -- GitLab From 838079beef0f4bfd1dfc3077ed469fced5cb32ae Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 1 Jul 2021 11:44:43 -0700 Subject: [PATCH 0396/2500] [dev.typeparams] cmd/internal/dwarf: remove putInlinedFunc's callersym param This parameter is only used for debugging, and all of putInlinedFunc's callers were actually passing the callee symbol instead. Change-Id: I964825a514cc42a1b0bcbce4ef11a1a47084d882 Reviewed-on: https://go-review.googlesource.com/c/go/+/332370 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/internal/dwarf/dwarf.go | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/cmd/internal/dwarf/dwarf.go b/src/cmd/internal/dwarf/dwarf.go index ec441c2bcb..860c7d6c0d 100644 --- a/src/cmd/internal/dwarf/dwarf.go +++ b/src/cmd/internal/dwarf/dwarf.go @@ -1266,7 +1266,7 @@ func PutAbstractFunc(ctxt Context, s *FnState) error { // its corresponding 'abstract' DIE (containing location-independent // attributes such as name, type, etc). Inlined subroutine DIEs can // have other inlined subroutine DIEs as children. -func putInlinedFunc(ctxt Context, s *FnState, callersym Sym, callIdx int) error { +func putInlinedFunc(ctxt Context, s *FnState, callIdx int) error { ic := s.InlCalls.Calls[callIdx] callee := ic.AbsFunSym @@ -1277,7 +1277,7 @@ func putInlinedFunc(ctxt Context, s *FnState, callersym Sym, callIdx int) error Uleb128put(ctxt, s.Info, int64(abbrev)) if logDwarf { - ctxt.Logf("putInlinedFunc(caller=%v,callee=%v,abbrev=%d)\n", callersym, callee, abbrev) + ctxt.Logf("putInlinedFunc(callee=%v,abbrev=%d)\n", callee, abbrev) } // Abstract origin. @@ -1312,8 +1312,7 @@ func putInlinedFunc(ctxt Context, s *FnState, callersym Sym, callIdx int) error // Children of this inline. for _, sib := range inlChildren(callIdx, &s.InlCalls) { - absfn := s.InlCalls.Calls[sib].AbsFunSym - err := putInlinedFunc(ctxt, s, absfn, sib) + err := putInlinedFunc(ctxt, s, sib) if err != nil { return err } @@ -1354,8 +1353,7 @@ func PutConcreteFunc(ctxt Context, s *FnState) error { // Inlined subroutines. for _, sib := range inlChildren(-1, &s.InlCalls) { - absfn := s.InlCalls.Calls[sib].AbsFunSym - err := putInlinedFunc(ctxt, s, absfn, sib) + err := putInlinedFunc(ctxt, s, sib) if err != nil { return err } @@ -1402,8 +1400,7 @@ func PutDefaultFunc(ctxt Context, s *FnState) error { // Inlined subroutines. for _, sib := range inlChildren(-1, &s.InlCalls) { - absfn := s.InlCalls.Calls[sib].AbsFunSym - err := putInlinedFunc(ctxt, s, absfn, sib) + err := putInlinedFunc(ctxt, s, sib) if err != nil { return err } -- GitLab From 9c1e7d9eff564df532c31114e2b833752519f0a2 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 30 Jun 2021 13:03:57 -0700 Subject: [PATCH 0397/2500] [dev.typeparams] cmd/compile/internal/types2: move Interface type decl into interface.go (cleanup) Change-Id: Ie1ba50c82afb7409f9495a19b8629c61c6a8d4dc Reviewed-on: https://go-review.googlesource.com/c/go/+/332092 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/interface.go | 148 +++++++++++++++++++ src/cmd/compile/internal/types2/type.go | 141 ------------------ 2 files changed, 148 insertions(+), 141 deletions(-) diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index 1f4e80951a..c344f8ed01 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -6,6 +6,154 @@ package types2 import "cmd/compile/internal/syntax" +// ---------------------------------------------------------------------------- +// API + +// An Interface represents an interface type. +type Interface struct { + obj *TypeName // corresponding declared object; or nil (for better error messages) + methods []*Func // ordered list of explicitly declared methods + embeddeds []Type // ordered list of explicitly embedded elements + embedPos *[]syntax.Pos // positions of embedded elements; or nil (for error messages) - use pointer to save space + complete bool // indicates that all fields (except for tset) are set up + + tset *TypeSet // type set described by this interface, computed lazily +} + +// typeSet returns the type set for interface t. +func (t *Interface) typeSet() *TypeSet { return computeTypeSet(nil, nopos, t) } + +// is reports whether interface t represents types that all satisfy f. +func (t *Interface) is(f func(Type, bool) bool) bool { + switch t := t.typeSet().types.(type) { + case nil, *top: + // TODO(gri) should settle on top or nil to represent this case + return false // we must have at least one type! (was bug) + case *Union: + return t.is(func(typ Type, tilde bool) bool { return f(typ, tilde) }) + default: + return f(t, false) + } +} + +// emptyInterface represents the empty interface +var emptyInterface = Interface{complete: true, tset: &topTypeSet} + +// NewInterface returns a new interface for the given methods and embedded types. +// NewInterface takes ownership of the provided methods and may modify their types +// by setting missing receivers. +// +// Deprecated: Use NewInterfaceType instead which allows arbitrary embedded types. +func NewInterface(methods []*Func, embeddeds []*Named) *Interface { + tnames := make([]Type, len(embeddeds)) + for i, t := range embeddeds { + tnames[i] = t + } + return NewInterfaceType(methods, tnames) +} + +// NewInterfaceType returns a new interface for the given methods and embedded types. +// NewInterfaceType takes ownership of the provided methods and may modify their types +// by setting missing receivers. +func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface { + if len(methods) == 0 && len(embeddeds) == 0 { + return &emptyInterface + } + + // set method receivers if necessary + typ := new(Interface) + for _, m := range methods { + if sig := m.typ.(*Signature); sig.recv == nil { + sig.recv = NewVar(m.pos, m.pkg, "", typ) + } + } + + // sort for API stability + sortMethods(methods) + + typ.methods = methods + typ.embeddeds = embeddeds + typ.complete = true + + return typ +} + +// NumExplicitMethods returns the number of explicitly declared methods of interface t. +func (t *Interface) NumExplicitMethods() int { return len(t.methods) } + +// ExplicitMethod returns the i'th explicitly declared method of interface t for 0 <= i < t.NumExplicitMethods(). +// The methods are ordered by their unique Id. +func (t *Interface) ExplicitMethod(i int) *Func { return t.methods[i] } + +// NumEmbeddeds returns the number of embedded types in interface t. +func (t *Interface) NumEmbeddeds() int { return len(t.embeddeds) } + +// Embedded returns the i'th embedded defined (*Named) type of interface t for 0 <= i < t.NumEmbeddeds(). +// The result is nil if the i'th embedded type is not a defined type. +// +// Deprecated: Use EmbeddedType which is not restricted to defined (*Named) types. +func (t *Interface) Embedded(i int) *Named { tname, _ := t.embeddeds[i].(*Named); return tname } + +// EmbeddedType returns the i'th embedded type of interface t for 0 <= i < t.NumEmbeddeds(). +func (t *Interface) EmbeddedType(i int) Type { return t.embeddeds[i] } + +// NumMethods returns the total number of methods of interface t. +func (t *Interface) NumMethods() int { return t.typeSet().NumMethods() } + +// Method returns the i'th method of interface t for 0 <= i < t.NumMethods(). +// The methods are ordered by their unique Id. +func (t *Interface) Method(i int) *Func { return t.typeSet().Method(i) } + +// Empty reports whether t is the empty interface. +func (t *Interface) Empty() bool { return t.typeSet().IsTop() } + +// IsComparable reports whether interface t is or embeds the predeclared interface "comparable". +func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() } + +// IsConstraint reports whether interface t is not just a method set. +func (t *Interface) IsConstraint() bool { return !t.typeSet().IsMethodSet() } + +// isSatisfiedBy reports whether interface t's type list is satisfied by the type typ. +// If the type list is empty (absent), typ trivially satisfies the interface. +// TODO(gri) This is not a great name. Eventually, we should have a more comprehensive +// "implements" predicate. +func (t *Interface) isSatisfiedBy(typ Type) bool { + switch t := t.typeSet().types.(type) { + case nil: + return true // no type restrictions + case *Union: + r, _ := t.intersect(typ, false) + return r != nil + default: + return Identical(t, typ) + } +} + +// Complete computes the interface's type set. It must be called by users of +// NewInterfaceType and NewInterface after the interface's embedded types are +// fully defined and before using the interface type in any way other than to +// form other types. The interface must not contain duplicate methods or a +// panic occurs. Complete returns the receiver. +// +// Deprecated: Type sets are now computed lazily, on demand; this function +// is only here for backward-compatibility. It does not have to +// be called explicitly anymore. +func (t *Interface) Complete() *Interface { + // Some tests are still depending on the state change + // (string representation of an Interface not containing an + // /* incomplete */ marker) caused by the explicit Complete + // call, so we compute the type set eagerly here. + t.complete = true + t.typeSet() + return t +} + +func (t *Interface) Underlying() Type { return t } +func (t *Interface) String() string { return TypeString(t, nil) } + +// ---------------------------------------------------------------------------- +// Implementation + func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType, def *Named) { var tlist []syntax.Expr // types collected from all type lists var tname *syntax.Name // most recent "type" name diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 3a9511de48..e2e10d21ae 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -163,145 +163,6 @@ func (t *Tuple) Len() int { // At returns the i'th variable of tuple t. func (t *Tuple) At(i int) *Var { return t.vars[i] } -// An Interface represents an interface type. -type Interface struct { - obj *TypeName // corresponding declared object; or nil (for better error messages) - methods []*Func // ordered list of explicitly declared methods - embeddeds []Type // ordered list of explicitly embedded elements - embedPos *[]syntax.Pos // positions of embedded elements; or nil (for error messages) - use pointer to save space - complete bool // indicates that all fields (except for tset) are set up - - tset *TypeSet // type set described by this interface, computed lazily -} - -// typeSet returns the type set for interface t. -func (t *Interface) typeSet() *TypeSet { return computeTypeSet(nil, nopos, t) } - -// is reports whether interface t represents types that all satisfy f. -func (t *Interface) is(f func(Type, bool) bool) bool { - switch t := t.typeSet().types.(type) { - case nil, *top: - // TODO(gri) should settle on top or nil to represent this case - return false // we must have at least one type! (was bug) - case *Union: - return t.is(func(typ Type, tilde bool) bool { return f(typ, tilde) }) - default: - return f(t, false) - } -} - -// emptyInterface represents the empty interface -var emptyInterface = Interface{complete: true, tset: &topTypeSet} - -// NewInterface returns a new interface for the given methods and embedded types. -// NewInterface takes ownership of the provided methods and may modify their types -// by setting missing receivers. -// -// Deprecated: Use NewInterfaceType instead which allows arbitrary embedded types. -func NewInterface(methods []*Func, embeddeds []*Named) *Interface { - tnames := make([]Type, len(embeddeds)) - for i, t := range embeddeds { - tnames[i] = t - } - return NewInterfaceType(methods, tnames) -} - -// NewInterfaceType returns a new interface for the given methods and embedded types. -// NewInterfaceType takes ownership of the provided methods and may modify their types -// by setting missing receivers. -func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface { - if len(methods) == 0 && len(embeddeds) == 0 { - return &emptyInterface - } - - // set method receivers if necessary - typ := new(Interface) - for _, m := range methods { - if sig := m.typ.(*Signature); sig.recv == nil { - sig.recv = NewVar(m.pos, m.pkg, "", typ) - } - } - - // sort for API stability - sortMethods(methods) - - typ.methods = methods - typ.embeddeds = embeddeds - typ.complete = true - - return typ -} - -// NumExplicitMethods returns the number of explicitly declared methods of interface t. -func (t *Interface) NumExplicitMethods() int { return len(t.methods) } - -// ExplicitMethod returns the i'th explicitly declared method of interface t for 0 <= i < t.NumExplicitMethods(). -// The methods are ordered by their unique Id. -func (t *Interface) ExplicitMethod(i int) *Func { return t.methods[i] } - -// NumEmbeddeds returns the number of embedded types in interface t. -func (t *Interface) NumEmbeddeds() int { return len(t.embeddeds) } - -// Embedded returns the i'th embedded defined (*Named) type of interface t for 0 <= i < t.NumEmbeddeds(). -// The result is nil if the i'th embedded type is not a defined type. -// -// Deprecated: Use EmbeddedType which is not restricted to defined (*Named) types. -func (t *Interface) Embedded(i int) *Named { tname, _ := t.embeddeds[i].(*Named); return tname } - -// EmbeddedType returns the i'th embedded type of interface t for 0 <= i < t.NumEmbeddeds(). -func (t *Interface) EmbeddedType(i int) Type { return t.embeddeds[i] } - -// NumMethods returns the total number of methods of interface t. -func (t *Interface) NumMethods() int { return t.typeSet().NumMethods() } - -// Method returns the i'th method of interface t for 0 <= i < t.NumMethods(). -// The methods are ordered by their unique Id. -func (t *Interface) Method(i int) *Func { return t.typeSet().Method(i) } - -// Empty reports whether t is the empty interface. -func (t *Interface) Empty() bool { return t.typeSet().IsTop() } - -// IsComparable reports whether interface t is or embeds the predeclared interface "comparable". -func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() } - -// IsConstraint reports whether interface t is not just a method set. -func (t *Interface) IsConstraint() bool { return !t.typeSet().IsMethodSet() } - -// isSatisfiedBy reports whether interface t's type list is satisfied by the type typ. -// If the type list is empty (absent), typ trivially satisfies the interface. -// TODO(gri) This is not a great name. Eventually, we should have a more comprehensive -// "implements" predicate. -func (t *Interface) isSatisfiedBy(typ Type) bool { - switch t := t.typeSet().types.(type) { - case nil: - return true // no type restrictions - case *Union: - r, _ := t.intersect(typ, false) - return r != nil - default: - return Identical(t, typ) - } -} - -// Complete computes the interface's type set. It must be called by users of -// NewInterfaceType and NewInterface after the interface's embedded types are -// fully defined and before using the interface type in any way other than to -// form other types. The interface must not contain duplicate methods or a -// panic occurs. Complete returns the receiver. -// -// Deprecated: Type sets are now computed lazily, on demand; this function -// is only here for backward-compatibility. It does not have to -// be called explicitly anymore. -func (t *Interface) Complete() *Interface { - // Some tests are still depending on the state change - // (string representation of an Interface not containing an - // /* incomplete */ marker) caused by the explicit Complete - // call, so we compute the type set eagerly here. - t.complete = true - t.typeSet() - return t -} - // A Map represents a map type. type Map struct { key, elem Type @@ -644,7 +505,6 @@ func (t *Array) Underlying() Type { return t } func (t *Slice) Underlying() Type { return t } func (t *Pointer) Underlying() Type { return t } func (t *Tuple) Underlying() Type { return t } -func (t *Interface) Underlying() Type { return t } func (t *Map) Underlying() Type { return t } func (t *Chan) Underlying() Type { return t } func (t *Named) Underlying() Type { return t.expand().underlying } @@ -658,7 +518,6 @@ func (t *Array) String() string { return TypeString(t, nil) } func (t *Slice) String() string { return TypeString(t, nil) } func (t *Pointer) String() string { return TypeString(t, nil) } func (t *Tuple) String() string { return TypeString(t, nil) } -func (t *Interface) String() string { return TypeString(t, nil) } func (t *Map) String() string { return TypeString(t, nil) } func (t *Chan) String() string { return TypeString(t, nil) } func (t *Named) String() string { return TypeString(t, nil) } -- GitLab From 30e5f266ed202740cfe0b7a9fde6117d6e1d6064 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 30 Jun 2021 13:26:11 -0700 Subject: [PATCH 0398/2500] [dev.typeparams] cmd/compile/internal/types2: move (remaining) type decls into their own files (cleanup) This change moves the type declarations and associated methods for each of the remaining Type types into their respective files. Except for import and comment adjustments, and receiver name adjustments for the Underlying and String methods, no functional changes are made. Change-Id: I3b9ccab3c85abea4852bacd28c2e47cec05c0bac Reviewed-on: https://go-review.googlesource.com/c/go/+/332093 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/array.go | 25 + src/cmd/compile/internal/types2/basic.go | 82 +++ src/cmd/compile/internal/types2/chan.go | 35 ++ src/cmd/compile/internal/types2/instance.go | 58 +++ src/cmd/compile/internal/types2/map.go | 24 + src/cmd/compile/internal/types2/named.go | 144 ++++++ src/cmd/compile/internal/types2/pointer.go | 19 + src/cmd/compile/internal/types2/slice.go | 19 + src/cmd/compile/internal/types2/tuple.go | 36 ++ src/cmd/compile/internal/types2/type.go | 501 +------------------ src/cmd/compile/internal/types2/typeparam.go | 80 +++ 11 files changed, 540 insertions(+), 483 deletions(-) create mode 100644 src/cmd/compile/internal/types2/array.go create mode 100644 src/cmd/compile/internal/types2/basic.go create mode 100644 src/cmd/compile/internal/types2/chan.go create mode 100644 src/cmd/compile/internal/types2/instance.go create mode 100644 src/cmd/compile/internal/types2/map.go create mode 100644 src/cmd/compile/internal/types2/named.go create mode 100644 src/cmd/compile/internal/types2/pointer.go create mode 100644 src/cmd/compile/internal/types2/slice.go create mode 100644 src/cmd/compile/internal/types2/tuple.go create mode 100644 src/cmd/compile/internal/types2/typeparam.go diff --git a/src/cmd/compile/internal/types2/array.go b/src/cmd/compile/internal/types2/array.go new file mode 100644 index 0000000000..502d49bc25 --- /dev/null +++ b/src/cmd/compile/internal/types2/array.go @@ -0,0 +1,25 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types2 + +// An Array represents an array type. +type Array struct { + len int64 + elem Type +} + +// NewArray returns a new array type for the given element type and length. +// A negative length indicates an unknown length. +func NewArray(elem Type, len int64) *Array { return &Array{len: len, elem: elem} } + +// Len returns the length of array a. +// A negative result indicates an unknown length. +func (a *Array) Len() int64 { return a.len } + +// Elem returns element type of array a. +func (a *Array) Elem() Type { return a.elem } + +func (a *Array) Underlying() Type { return a } +func (a *Array) String() string { return TypeString(a, nil) } diff --git a/src/cmd/compile/internal/types2/basic.go b/src/cmd/compile/internal/types2/basic.go new file mode 100644 index 0000000000..2fd973cafb --- /dev/null +++ b/src/cmd/compile/internal/types2/basic.go @@ -0,0 +1,82 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types2 + +// BasicKind describes the kind of basic type. +type BasicKind int + +const ( + Invalid BasicKind = iota // type is invalid + + // predeclared types + Bool + Int + Int8 + Int16 + Int32 + Int64 + Uint + Uint8 + Uint16 + Uint32 + Uint64 + Uintptr + Float32 + Float64 + Complex64 + Complex128 + String + UnsafePointer + + // types for untyped values + UntypedBool + UntypedInt + UntypedRune + UntypedFloat + UntypedComplex + UntypedString + UntypedNil + + // aliases + Byte = Uint8 + Rune = Int32 +) + +// BasicInfo is a set of flags describing properties of a basic type. +type BasicInfo int + +// Properties of basic types. +const ( + IsBoolean BasicInfo = 1 << iota + IsInteger + IsUnsigned + IsFloat + IsComplex + IsString + IsUntyped + + IsOrdered = IsInteger | IsFloat | IsString + IsNumeric = IsInteger | IsFloat | IsComplex + IsConstType = IsBoolean | IsNumeric | IsString +) + +// A Basic represents a basic type. +type Basic struct { + kind BasicKind + info BasicInfo + name string +} + +// Kind returns the kind of basic type b. +func (b *Basic) Kind() BasicKind { return b.kind } + +// Info returns information about properties of basic type b. +func (b *Basic) Info() BasicInfo { return b.info } + +// Name returns the name of basic type b. +func (b *Basic) Name() string { return b.name } + +func (b *Basic) Underlying() Type { return b } +func (b *Basic) String() string { return TypeString(b, nil) } diff --git a/src/cmd/compile/internal/types2/chan.go b/src/cmd/compile/internal/types2/chan.go new file mode 100644 index 0000000000..77650dfb09 --- /dev/null +++ b/src/cmd/compile/internal/types2/chan.go @@ -0,0 +1,35 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types2 + +// A Chan represents a channel type. +type Chan struct { + dir ChanDir + elem Type +} + +// A ChanDir value indicates a channel direction. +type ChanDir int + +// The direction of a channel is indicated by one of these constants. +const ( + SendRecv ChanDir = iota + SendOnly + RecvOnly +) + +// NewChan returns a new channel type for the given direction and element type. +func NewChan(dir ChanDir, elem Type) *Chan { + return &Chan{dir: dir, elem: elem} +} + +// Dir returns the direction of channel c. +func (c *Chan) Dir() ChanDir { return c.dir } + +// Elem returns the element type of channel c. +func (c *Chan) Elem() Type { return c.elem } + +func (c *Chan) Underlying() Type { return c } +func (c *Chan) String() string { return TypeString(c, nil) } diff --git a/src/cmd/compile/internal/types2/instance.go b/src/cmd/compile/internal/types2/instance.go new file mode 100644 index 0000000000..9d6097e874 --- /dev/null +++ b/src/cmd/compile/internal/types2/instance.go @@ -0,0 +1,58 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types2 + +import "cmd/compile/internal/syntax" + +// An instance represents an instantiated generic type syntactically +// (without expanding the instantiation). Type instances appear only +// during type-checking and are replaced by their fully instantiated +// (expanded) types before the end of type-checking. +type instance struct { + check *Checker // for lazy instantiation + pos syntax.Pos // position of type instantiation; for error reporting only + base *Named // parameterized type to be instantiated + targs []Type // type arguments + poslist []syntax.Pos // position of each targ; for error reporting only + value Type // base(targs...) after instantiation or Typ[Invalid]; nil if not yet set +} + +// expand returns the instantiated (= expanded) type of t. +// The result is either an instantiated *Named type, or +// Typ[Invalid] if there was an error. +func (t *instance) expand() Type { + v := t.value + if v == nil { + v = t.check.instantiate(t.pos, t.base, t.targs, t.poslist) + if v == nil { + v = Typ[Invalid] + } + t.value = v + } + // After instantiation we must have an invalid or a *Named type. + if debug && v != Typ[Invalid] { + _ = v.(*Named) + } + return v +} + +// expand expands a type instance into its instantiated +// type and leaves all other types alone. expand does +// not recurse. +func expand(typ Type) Type { + if t, _ := typ.(*instance); t != nil { + return t.expand() + } + return typ +} + +// expandf is set to expand. +// Call expandf when calling expand causes compile-time cycle error. +var expandf func(Type) Type + +func init() { expandf = expand } + +func (t *instance) Underlying() Type { return t } +func (t *instance) String() string { return TypeString(t, nil) } diff --git a/src/cmd/compile/internal/types2/map.go b/src/cmd/compile/internal/types2/map.go new file mode 100644 index 0000000000..0d3464caae --- /dev/null +++ b/src/cmd/compile/internal/types2/map.go @@ -0,0 +1,24 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types2 + +// A Map represents a map type. +type Map struct { + key, elem Type +} + +// NewMap returns a new map for the given key and element types. +func NewMap(key, elem Type) *Map { + return &Map{key: key, elem: elem} +} + +// Key returns the key type of map m. +func (m *Map) Key() Type { return m.key } + +// Elem returns the element type of map m. +func (m *Map) Elem() Type { return m.elem } + +func (t *Map) Underlying() Type { return t } +func (t *Map) String() string { return TypeString(t, nil) } diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go new file mode 100644 index 0000000000..2005dfbd84 --- /dev/null +++ b/src/cmd/compile/internal/types2/named.go @@ -0,0 +1,144 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types2 + +import "sync" + +// TODO(gri) Clean up Named struct below; specifically the fromRHS field (can we use underlying?). + +// A Named represents a named (defined) type. +type Named struct { + check *Checker // for Named.under implementation; nilled once under has been called + info typeInfo // for cycle detection + obj *TypeName // corresponding declared object + orig *Named // original, uninstantiated type + fromRHS Type // type (on RHS of declaration) this *Named type is derived from (for cycle reporting) + underlying Type // possibly a *Named during setup; never a *Named once set up completely + tparams []*TypeName // type parameters, or nil + targs []Type // type arguments (after instantiation), or nil + methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily + + resolve func(*Named) ([]*TypeName, Type, []*Func) + once sync.Once +} + +// NewNamed returns a new named type for the given type name, underlying type, and associated methods. +// If the given type name obj doesn't have a type yet, its type is set to the returned named type. +// The underlying type must not be a *Named. +func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named { + if _, ok := underlying.(*Named); ok { + panic("types2.NewNamed: underlying type must not be *Named") + } + return (*Checker)(nil).newNamed(obj, nil, underlying, nil, methods) +} + +func (t *Named) expand() *Named { + if t.resolve == nil { + return t + } + + t.once.Do(func() { + // TODO(mdempsky): Since we're passing t to resolve anyway + // (necessary because types2 expects the receiver type for methods + // on defined interface types to be the Named rather than the + // underlying Interface), maybe it should just handle calling + // SetTParams, SetUnderlying, and AddMethod instead? Those + // methods would need to support reentrant calls though. It would + // also make the API more future-proof towards further extensions + // (like SetTParams). + + tparams, underlying, methods := t.resolve(t) + + switch underlying.(type) { + case nil, *Named: + panic("invalid underlying type") + } + + t.tparams = tparams + t.underlying = underlying + t.methods = methods + }) + return t +} + +// newNamed is like NewNamed but with a *Checker receiver and additional orig argument. +func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams []*TypeName, methods []*Func) *Named { + typ := &Named{check: check, obj: obj, orig: orig, fromRHS: underlying, underlying: underlying, tparams: tparams, methods: methods} + if typ.orig == nil { + typ.orig = typ + } + if obj.typ == nil { + obj.typ = typ + } + // Ensure that typ is always expanded, at which point the check field can be + // nilled out. + // + // Note that currently we cannot nil out check inside typ.under(), because + // it's possible that typ is expanded multiple times. + // + // TODO(gri): clean this up so that under is the only function mutating + // named types. + if check != nil { + check.later(func() { + switch typ.under().(type) { + case *Named, *instance: + panic("internal error: unexpanded underlying type") + } + typ.check = nil + }) + } + return typ +} + +// Obj returns the type name for the named type t. +func (t *Named) Obj() *TypeName { return t.obj } + +// Orig returns the original generic type an instantiated type is derived from. +// If t is not an instantiated type, the result is t. +func (t *Named) Orig() *Named { return t.orig } + +// TODO(gri) Come up with a better representation and API to distinguish +// between parameterized instantiated and non-instantiated types. + +// TParams returns the type parameters of the named type t, or nil. +// The result is non-nil for an (originally) parameterized type even if it is instantiated. +func (t *Named) TParams() []*TypeName { return t.expand().tparams } + +// SetTParams sets the type parameters of the named type t. +func (t *Named) SetTParams(tparams []*TypeName) { t.expand().tparams = tparams } + +// TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated. +func (t *Named) TArgs() []Type { return t.targs } + +// SetTArgs sets the type arguments of the named type t. +func (t *Named) SetTArgs(args []Type) { t.targs = args } + +// NumMethods returns the number of explicit methods whose receiver is named type t. +func (t *Named) NumMethods() int { return len(t.expand().methods) } + +// Method returns the i'th method of named type t for 0 <= i < t.NumMethods(). +func (t *Named) Method(i int) *Func { return t.expand().methods[i] } + +// SetUnderlying sets the underlying type and marks t as complete. +func (t *Named) SetUnderlying(underlying Type) { + if underlying == nil { + panic("types2.Named.SetUnderlying: underlying type must not be nil") + } + if _, ok := underlying.(*Named); ok { + panic("types2.Named.SetUnderlying: underlying type must not be *Named") + } + t.expand().underlying = underlying +} + +// AddMethod adds method m unless it is already in the method list. +func (t *Named) AddMethod(m *Func) { + t.expand() + if i, _ := lookupMethod(t.methods, m.pkg, m.name); i < 0 { + t.methods = append(t.methods, m) + } +} + +func (t *Named) Underlying() Type { return t.expand().underlying } +func (t *Named) String() string { return TypeString(t, nil) } diff --git a/src/cmd/compile/internal/types2/pointer.go b/src/cmd/compile/internal/types2/pointer.go new file mode 100644 index 0000000000..63055fc6b0 --- /dev/null +++ b/src/cmd/compile/internal/types2/pointer.go @@ -0,0 +1,19 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types2 + +// A Pointer represents a pointer type. +type Pointer struct { + base Type // element type +} + +// NewPointer returns a new pointer type for the given element (base) type. +func NewPointer(elem Type) *Pointer { return &Pointer{base: elem} } + +// Elem returns the element type for the given pointer p. +func (p *Pointer) Elem() Type { return p.base } + +func (p *Pointer) Underlying() Type { return p } +func (p *Pointer) String() string { return TypeString(p, nil) } diff --git a/src/cmd/compile/internal/types2/slice.go b/src/cmd/compile/internal/types2/slice.go new file mode 100644 index 0000000000..9c22a6fb1b --- /dev/null +++ b/src/cmd/compile/internal/types2/slice.go @@ -0,0 +1,19 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types2 + +// A Slice represents a slice type. +type Slice struct { + elem Type +} + +// NewSlice returns a new slice type for the given element type. +func NewSlice(elem Type) *Slice { return &Slice{elem: elem} } + +// Elem returns the element type of slice s. +func (s *Slice) Elem() Type { return s.elem } + +func (s *Slice) Underlying() Type { return s } +func (s *Slice) String() string { return TypeString(s, nil) } diff --git a/src/cmd/compile/internal/types2/tuple.go b/src/cmd/compile/internal/types2/tuple.go new file mode 100644 index 0000000000..a3946beab5 --- /dev/null +++ b/src/cmd/compile/internal/types2/tuple.go @@ -0,0 +1,36 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types2 + +// A Tuple represents an ordered list of variables; a nil *Tuple is a valid (empty) tuple. +// Tuples are used as components of signatures and to represent the type of multiple +// assignments; they are not first class types of Go. +type Tuple struct { + vars []*Var +} + +// NewTuple returns a new tuple for the given variables. +func NewTuple(x ...*Var) *Tuple { + if len(x) > 0 { + return &Tuple{vars: x} + } + // TODO(gri) Don't represent empty tuples with a (*Tuple)(nil) pointer; + // it's too subtle and causes problems. + return nil +} + +// Len returns the number variables of tuple t. +func (t *Tuple) Len() int { + if t != nil { + return len(t.vars) + } + return 0 +} + +// At returns the i'th variable of tuple t. +func (t *Tuple) At(i int) *Var { return t.vars[i] } + +func (t *Tuple) Underlying() Type { return t } +func (t *Tuple) String() string { return TypeString(t, nil) } diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index e2e10d21ae..e3f63f63b5 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -4,12 +4,6 @@ package types2 -import ( - "cmd/compile/internal/syntax" - "sync" - "sync/atomic" -) - // A Type represents a type of Go. // All types implement the Type interface. type Type interface { @@ -22,394 +16,31 @@ type Type interface { String() string } -// BasicKind describes the kind of basic type. -type BasicKind int - -const ( - Invalid BasicKind = iota // type is invalid - - // predeclared types - Bool - Int - Int8 - Int16 - Int32 - Int64 - Uint - Uint8 - Uint16 - Uint32 - Uint64 - Uintptr - Float32 - Float64 - Complex64 - Complex128 - String - UnsafePointer - - // types for untyped values - UntypedBool - UntypedInt - UntypedRune - UntypedFloat - UntypedComplex - UntypedString - UntypedNil - - // aliases - Byte = Uint8 - Rune = Int32 -) - -// BasicInfo is a set of flags describing properties of a basic type. -type BasicInfo int - -// Properties of basic types. -const ( - IsBoolean BasicInfo = 1 << iota - IsInteger - IsUnsigned - IsFloat - IsComplex - IsString - IsUntyped - - IsOrdered = IsInteger | IsFloat | IsString - IsNumeric = IsInteger | IsFloat | IsComplex - IsConstType = IsBoolean | IsNumeric | IsString -) - -// A Basic represents a basic type. -type Basic struct { - kind BasicKind - info BasicInfo - name string -} - -// Kind returns the kind of basic type b. -func (b *Basic) Kind() BasicKind { return b.kind } - -// Info returns information about properties of basic type b. -func (b *Basic) Info() BasicInfo { return b.info } - -// Name returns the name of basic type b. -func (b *Basic) Name() string { return b.name } - -// An Array represents an array type. -type Array struct { - len int64 - elem Type -} - -// NewArray returns a new array type for the given element type and length. -// A negative length indicates an unknown length. -func NewArray(elem Type, len int64) *Array { return &Array{len: len, elem: elem} } - -// Len returns the length of array a. -// A negative result indicates an unknown length. -func (a *Array) Len() int64 { return a.len } - -// Elem returns element type of array a. -func (a *Array) Elem() Type { return a.elem } - -// A Slice represents a slice type. -type Slice struct { - elem Type -} - -// NewSlice returns a new slice type for the given element type. -func NewSlice(elem Type) *Slice { return &Slice{elem: elem} } - -// Elem returns the element type of slice s. -func (s *Slice) Elem() Type { return s.elem } - -// A Pointer represents a pointer type. -type Pointer struct { - base Type // element type -} - -// NewPointer returns a new pointer type for the given element (base) type. -func NewPointer(elem Type) *Pointer { return &Pointer{base: elem} } - -// Elem returns the element type for the given pointer p. -func (p *Pointer) Elem() Type { return p.base } - -// A Tuple represents an ordered list of variables; a nil *Tuple is a valid (empty) tuple. -// Tuples are used as components of signatures and to represent the type of multiple -// assignments; they are not first class types of Go. -type Tuple struct { - vars []*Var -} - -// NewTuple returns a new tuple for the given variables. -func NewTuple(x ...*Var) *Tuple { - if len(x) > 0 { - return &Tuple{vars: x} - } - // TODO(gri) Don't represent empty tuples with a (*Tuple)(nil) pointer; - // it's too subtle and causes problems. - return nil -} - -// Len returns the number variables of tuple t. -func (t *Tuple) Len() int { - if t != nil { - return len(t.vars) - } - return 0 -} - -// At returns the i'th variable of tuple t. -func (t *Tuple) At(i int) *Var { return t.vars[i] } - -// A Map represents a map type. -type Map struct { - key, elem Type -} - -// NewMap returns a new map for the given key and element types. -func NewMap(key, elem Type) *Map { - return &Map{key: key, elem: elem} -} - -// Key returns the key type of map m. -func (m *Map) Key() Type { return m.key } - -// Elem returns the element type of map m. -func (m *Map) Elem() Type { return m.elem } - -// A Chan represents a channel type. -type Chan struct { - dir ChanDir - elem Type -} - -// A ChanDir value indicates a channel direction. -type ChanDir int - -// The direction of a channel is indicated by one of these constants. -const ( - SendRecv ChanDir = iota - SendOnly - RecvOnly -) - -// NewChan returns a new channel type for the given direction and element type. -func NewChan(dir ChanDir, elem Type) *Chan { - return &Chan{dir: dir, elem: elem} -} - -// Dir returns the direction of channel c. -func (c *Chan) Dir() ChanDir { return c.dir } - -// Elem returns the element type of channel c. -func (c *Chan) Elem() Type { return c.elem } - -// TODO(gri) Clean up Named struct below; specifically the fromRHS field (can we use underlying?). - -// A Named represents a named (defined) type. -type Named struct { - check *Checker // for Named.under implementation; nilled once under has been called - info typeInfo // for cycle detection - obj *TypeName // corresponding declared object - orig *Named // original, uninstantiated type - fromRHS Type // type (on RHS of declaration) this *Named type is derived from (for cycle reporting) - underlying Type // possibly a *Named during setup; never a *Named once set up completely - tparams []*TypeName // type parameters, or nil - targs []Type // type arguments (after instantiation), or nil - methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily +// top represents the top of the type lattice. +// It is the underlying type of a type parameter that +// can be satisfied by any type (ignoring methods), +// because its type constraint contains no restrictions +// besides methods. +type top struct{} - resolve func(*Named) ([]*TypeName, Type, []*Func) - once sync.Once -} +// theTop is the singleton top type. +var theTop = &top{} -// NewNamed returns a new named type for the given type name, underlying type, and associated methods. -// If the given type name obj doesn't have a type yet, its type is set to the returned named type. -// The underlying type must not be a *Named. -func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named { - if _, ok := underlying.(*Named); ok { - panic("types2.NewNamed: underlying type must not be *Named") - } - return (*Checker)(nil).newNamed(obj, nil, underlying, nil, methods) -} +func (t *top) Underlying() Type { return t } +func (t *top) String() string { return TypeString(t, nil) } -func (t *Named) expand() *Named { - if t.resolve == nil { - return t +// under returns the true expanded underlying type. +// If it doesn't exist, the result is Typ[Invalid]. +// under must only be called when a type is known +// to be fully set up. +func under(t Type) Type { + // TODO(gri) is this correct for *Union? + if n := asNamed(t); n != nil { + return n.under() } - - t.once.Do(func() { - // TODO(mdempsky): Since we're passing t to resolve anyway - // (necessary because types2 expects the receiver type for methods - // on defined interface types to be the Named rather than the - // underlying Interface), maybe it should just handle calling - // SetTParams, SetUnderlying, and AddMethod instead? Those - // methods would need to support reentrant calls though. It would - // also make the API more future-proof towards further extensions - // (like SetTParams). - - tparams, underlying, methods := t.resolve(t) - - switch underlying.(type) { - case nil, *Named: - panic("invalid underlying type") - } - - t.tparams = tparams - t.underlying = underlying - t.methods = methods - }) return t } -// newNamed is like NewNamed but with a *Checker receiver and additional orig argument. -func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams []*TypeName, methods []*Func) *Named { - typ := &Named{check: check, obj: obj, orig: orig, fromRHS: underlying, underlying: underlying, tparams: tparams, methods: methods} - if typ.orig == nil { - typ.orig = typ - } - if obj.typ == nil { - obj.typ = typ - } - // Ensure that typ is always expanded, at which point the check field can be - // nilled out. - // - // Note that currently we cannot nil out check inside typ.under(), because - // it's possible that typ is expanded multiple times. - // - // TODO(gri): clean this up so that under is the only function mutating - // named types. - if check != nil { - check.later(func() { - switch typ.under().(type) { - case *Named, *instance: - panic("internal error: unexpanded underlying type") - } - typ.check = nil - }) - } - return typ -} - -// Obj returns the type name for the named type t. -func (t *Named) Obj() *TypeName { return t.obj } - -// Orig returns the original generic type an instantiated type is derived from. -// If t is not an instantiated type, the result is t. -func (t *Named) Orig() *Named { return t.orig } - -// TODO(gri) Come up with a better representation and API to distinguish -// between parameterized instantiated and non-instantiated types. - -// TParams returns the type parameters of the named type t, or nil. -// The result is non-nil for an (originally) parameterized type even if it is instantiated. -func (t *Named) TParams() []*TypeName { return t.expand().tparams } - -// SetTParams sets the type parameters of the named type t. -func (t *Named) SetTParams(tparams []*TypeName) { t.expand().tparams = tparams } - -// TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated. -func (t *Named) TArgs() []Type { return t.targs } - -// SetTArgs sets the type arguments of the named type t. -func (t *Named) SetTArgs(args []Type) { t.targs = args } - -// NumMethods returns the number of explicit methods whose receiver is named type t. -func (t *Named) NumMethods() int { return len(t.expand().methods) } - -// Method returns the i'th method of named type t for 0 <= i < t.NumMethods(). -func (t *Named) Method(i int) *Func { return t.expand().methods[i] } - -// SetUnderlying sets the underlying type and marks t as complete. -func (t *Named) SetUnderlying(underlying Type) { - if underlying == nil { - panic("types2.Named.SetUnderlying: underlying type must not be nil") - } - if _, ok := underlying.(*Named); ok { - panic("types2.Named.SetUnderlying: underlying type must not be *Named") - } - t.expand().underlying = underlying -} - -// AddMethod adds method m unless it is already in the method list. -func (t *Named) AddMethod(m *Func) { - t.expand() - if i, _ := lookupMethod(t.methods, m.pkg, m.name); i < 0 { - t.methods = append(t.methods, m) - } -} - -// Note: This is a uint32 rather than a uint64 because the -// respective 64 bit atomic instructions are not available -// on all platforms. -var lastID uint32 - -// nextID returns a value increasing monotonically by 1 with -// each call, starting with 1. It may be called concurrently. -func nextID() uint64 { return uint64(atomic.AddUint32(&lastID, 1)) } - -// A TypeParam represents a type parameter type. -type TypeParam struct { - check *Checker // for lazy type bound completion - id uint64 // unique id, for debugging only - obj *TypeName // corresponding type name - index int // type parameter index in source order, starting at 0 - bound Type // *Named or *Interface; underlying type is always *Interface -} - -// Obj returns the type name for the type parameter t. -func (t *TypeParam) Obj() *TypeName { return t.obj } - -// NewTypeParam returns a new TypeParam. bound can be nil (and set later). -func (check *Checker) NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam { - // Always increment lastID, even if it is not used. - id := nextID() - if check != nil { - check.nextID++ - id = check.nextID - } - typ := &TypeParam{check: check, id: id, obj: obj, index: index, bound: bound} - if obj.typ == nil { - obj.typ = typ - } - return typ -} - -// Index returns the index of the type param within its param list. -func (t *TypeParam) Index() int { - return t.index -} - -// SetId sets the unique id of a type param. Should only be used for type params -// in imported generic types. -func (t *TypeParam) SetId(id uint64) { - t.id = id -} - -func (t *TypeParam) Bound() *Interface { - // we may not have an interface (error reported elsewhere) - iface, _ := under(t.bound).(*Interface) - if iface == nil { - return &emptyInterface - } - // use the type bound position if we have one - pos := nopos - if n, _ := t.bound.(*Named); n != nil { - pos = n.obj.pos - } - // TODO(gri) switch this to an unexported method on Checker. - computeTypeSet(t.check, pos, iface) - return iface -} - -func (t *TypeParam) SetBound(bound Type) { - if bound == nil { - panic("types2.TypeParam.SetBound: bound must not be nil") - } - t.bound = bound -} - // optype returns a type's operational type. Except for // type parameters, the operational type is the same // as the underlying type (as returned by under). For @@ -441,102 +72,6 @@ func optype(typ Type) Type { return under(typ) } -// An instance represents an instantiated generic type syntactically -// (without expanding the instantiation). Type instances appear only -// during type-checking and are replaced by their fully instantiated -// (expanded) types before the end of type-checking. -type instance struct { - check *Checker // for lazy instantiation - pos syntax.Pos // position of type instantiation; for error reporting only - base *Named // parameterized type to be instantiated - targs []Type // type arguments - poslist []syntax.Pos // position of each targ; for error reporting only - value Type // base(targs...) after instantiation or Typ[Invalid]; nil if not yet set -} - -// expand returns the instantiated (= expanded) type of t. -// The result is either an instantiated *Named type, or -// Typ[Invalid] if there was an error. -func (t *instance) expand() Type { - v := t.value - if v == nil { - v = t.check.instantiate(t.pos, t.base, t.targs, t.poslist) - if v == nil { - v = Typ[Invalid] - } - t.value = v - } - // After instantiation we must have an invalid or a *Named type. - if debug && v != Typ[Invalid] { - _ = v.(*Named) - } - return v -} - -// expand expands a type instance into its instantiated -// type and leaves all other types alone. expand does -// not recurse. -func expand(typ Type) Type { - if t, _ := typ.(*instance); t != nil { - return t.expand() - } - return typ -} - -// expandf is set to expand. -// Call expandf when calling expand causes compile-time cycle error. -var expandf func(Type) Type - -func init() { expandf = expand } - -// top represents the top of the type lattice. -// It is the underlying type of a type parameter that -// can be satisfied by any type (ignoring methods), -// because its type constraint contains no restrictions -// besides methods. -type top struct{} - -// theTop is the singleton top type. -var theTop = &top{} - -// Type-specific implementations of Underlying. -func (t *Basic) Underlying() Type { return t } -func (t *Array) Underlying() Type { return t } -func (t *Slice) Underlying() Type { return t } -func (t *Pointer) Underlying() Type { return t } -func (t *Tuple) Underlying() Type { return t } -func (t *Map) Underlying() Type { return t } -func (t *Chan) Underlying() Type { return t } -func (t *Named) Underlying() Type { return t.expand().underlying } -func (t *TypeParam) Underlying() Type { return t } -func (t *instance) Underlying() Type { return t } -func (t *top) Underlying() Type { return t } - -// Type-specific implementations of String. -func (t *Basic) String() string { return TypeString(t, nil) } -func (t *Array) String() string { return TypeString(t, nil) } -func (t *Slice) String() string { return TypeString(t, nil) } -func (t *Pointer) String() string { return TypeString(t, nil) } -func (t *Tuple) String() string { return TypeString(t, nil) } -func (t *Map) String() string { return TypeString(t, nil) } -func (t *Chan) String() string { return TypeString(t, nil) } -func (t *Named) String() string { return TypeString(t, nil) } -func (t *TypeParam) String() string { return TypeString(t, nil) } -func (t *instance) String() string { return TypeString(t, nil) } -func (t *top) String() string { return TypeString(t, nil) } - -// under returns the true expanded underlying type. -// If it doesn't exist, the result is Typ[Invalid]. -// under must only be called when a type is known -// to be fully set up. -func under(t Type) Type { - // TODO(gri) is this correct for *Union? - if n := asNamed(t); n != nil { - return n.under() - } - return t -} - // Converters // // A converter must only be called when a type is diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go new file mode 100644 index 0000000000..5c74405912 --- /dev/null +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -0,0 +1,80 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types2 + +import "sync/atomic" + +// Note: This is a uint32 rather than a uint64 because the +// respective 64 bit atomic instructions are not available +// on all platforms. +var lastID uint32 + +// nextID returns a value increasing monotonically by 1 with +// each call, starting with 1. It may be called concurrently. +func nextID() uint64 { return uint64(atomic.AddUint32(&lastID, 1)) } + +// A TypeParam represents a type parameter type. +type TypeParam struct { + check *Checker // for lazy type bound completion + id uint64 // unique id, for debugging only + obj *TypeName // corresponding type name + index int // type parameter index in source order, starting at 0 + bound Type // *Named or *Interface; underlying type is always *Interface +} + +// Obj returns the type name for the type parameter t. +func (t *TypeParam) Obj() *TypeName { return t.obj } + +// NewTypeParam returns a new TypeParam. bound can be nil (and set later). +func (check *Checker) NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam { + // Always increment lastID, even if it is not used. + id := nextID() + if check != nil { + check.nextID++ + id = check.nextID + } + typ := &TypeParam{check: check, id: id, obj: obj, index: index, bound: bound} + if obj.typ == nil { + obj.typ = typ + } + return typ +} + +// Index returns the index of the type param within its param list. +func (t *TypeParam) Index() int { + return t.index +} + +// SetId sets the unique id of a type param. Should only be used for type params +// in imported generic types. +func (t *TypeParam) SetId(id uint64) { + t.id = id +} + +func (t *TypeParam) Bound() *Interface { + // we may not have an interface (error reported elsewhere) + iface, _ := under(t.bound).(*Interface) + if iface == nil { + return &emptyInterface + } + // use the type bound position if we have one + pos := nopos + if n, _ := t.bound.(*Named); n != nil { + pos = n.obj.pos + } + // TODO(gri) switch this to an unexported method on Checker. + computeTypeSet(t.check, pos, iface) + return iface +} + +func (t *TypeParam) SetBound(bound Type) { + if bound == nil { + panic("types2.TypeParam.SetBound: bound must not be nil") + } + t.bound = bound +} + +func (t *TypeParam) Underlying() Type { return t } +func (t *TypeParam) String() string { return TypeString(t, nil) } -- GitLab From 2aea44204ef8e3467bd2d21865e3d2b8045f3d12 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 1 Jul 2021 12:47:58 -0700 Subject: [PATCH 0399/2500] [dev.typeparams] cmd/compile: enable generics syntax with -lang=go1.18 We already use -lang=go1.18 to control the types2 type checker behavior. This CL does the same for the parser. Also, disable an assertion in the unified IR linker that depended on the -G flag. This assertion was more useful during initial bootstrapping of that code, but it's less critical now. With these two changes, "GOEXPERIMENT=unified ./make.bash" is enough to get a fully functional generics-enabled toolchain. There's no need to continue specifying custom compiler flags later on. Change-Id: I7766381926f3bb17eee2e5fcc182a38a39e937e1 Reviewed-on: https://go-review.googlesource.com/c/go/+/332373 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Matthew Dempsky Trust: Robert Griesemer Reviewed-by: Robert Griesemer Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/noder/linker.go | 6 ++++-- src/cmd/compile/internal/noder/noder.go | 6 +++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/noder/linker.go b/src/cmd/compile/internal/noder/linker.go index ed47a355d8..eefb5083e5 100644 --- a/src/cmd/compile/internal/noder/linker.go +++ b/src/cmd/compile/internal/noder/linker.go @@ -149,9 +149,11 @@ func (l *linker) relocObj(pr *pkgReader, idx int) int { var ok bool obj, ok = sym.Def.(*ir.Name) - // Generic types and functions won't have definitions. + // Generic types and functions and declared constraint types won't + // have definitions. // For now, just generically copy their extension data. - if !ok && base.Flag.G == 0 { + // TODO(mdempsky): Restore assertion. + if !ok && false { base.Fatalf("missing definition for %v", sym) } } diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index 3d83129aea..6a2aacd3fe 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -9,6 +9,7 @@ import ( "fmt" "go/constant" "go/token" + "internal/buildcfg" "os" "path/filepath" "runtime" @@ -30,8 +31,11 @@ import ( func LoadPackage(filenames []string) { base.Timer.Start("fe", "parse") + // -G=3 and unified expect generics syntax, but -G=0 does not. + supportsGenerics := base.Flag.G != 0 || buildcfg.Experiment.Unified + mode := syntax.CheckBranches - if base.Flag.G != 0 { + if supportsGenerics && types.AllowsGoVersion(types.LocalPkg, 1, 18) { mode |= syntax.AllowGenerics } -- GitLab From a18726a648df48917e0ed1404cf6cdbc81acd495 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 1 Jul 2021 15:23:41 -0700 Subject: [PATCH 0400/2500] [dev.typeparams] cmd/compile: incremental typecheck during unified IR This CL changes unified IR to incrementally typecheck the IR as it's constructed. This is significant, because it means reader can now use typecheck.Expr to typecheck sub-expressions when it's needed. This should be helpful for construction and insertion of dictionaries. This CL does introduce two quirks outside of unified IR itself, which simplify preserving binary output: 1. Top-level declarations are sorted after they're constructed, to avoid worrying about the order that closures are added. 2. Zero-padding autotmp_N variable names. Interleaving typechecking means autotmp variables are sometimes named differently (since their naming depends on the number of variables declared so far), and this ensures that code that sorts variables by names doesn't suddenly sort autotmp_8/autotmp_9 differently than it would have sorted autotmp_9/autotmp_10. While at it, this CL also updated reader to use ir.WithFunc instead of manually setting and restoring ir.CurFunc. There's now only one remaining direct use of ir.CurFunc. Change-Id: I6233b4c059596e471c53166f94750917d710462f Reviewed-on: https://go-review.googlesource.com/c/go/+/332469 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/gc/main.go | 15 +++ src/cmd/compile/internal/noder/reader.go | 100 ++++++++++++------ src/cmd/compile/internal/noder/unified.go | 17 --- .../compile/internal/noder/unified_test.go | 2 +- src/cmd/compile/internal/typecheck/dcl.go | 11 +- 5 files changed, 92 insertions(+), 53 deletions(-) diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index c94f19fd47..68017516df 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -32,6 +32,7 @@ import ( "log" "os" "runtime" + "sort" ) func hidePanic() { @@ -202,6 +203,20 @@ func Main(archInit func(*ssagen.ArchInfo)) { typecheck.Export(initTask) } + // Stability quirk: sort top-level declarations, so we're not + // sensitive to the order that functions are added. In particular, + // the order that noder+typecheck add function closures is very + // subtle, and not important to reproduce. + // + // Note: This needs to happen after pkginit.Task, otherwise it risks + // changing the order in which top-level variables are initialized. + if base.Debug.UnifiedQuirks != 0 { + s := typecheck.Target.Decls + sort.SliceStable(s, func(i, j int) bool { + return s[i].Pos().Before(s[j].Pos()) + }) + } + // Eliminate some obviously dead code. // Must happen after typechecking. for _, n := range typecheck.Target.Decls { diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 24977ed7f0..275baead04 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -886,27 +886,25 @@ func (r *reader) funcBody(fn *ir.Func) { r.curfn = fn r.closureVars = fn.ClosureVars - // TODO(mdempsky): Get rid of uses of typecheck.NodAddrAt so we - // don't have to set ir.CurFunc. - outerCurFunc := ir.CurFunc - ir.CurFunc = fn + ir.WithFunc(fn, func() { + r.funcargs(fn) - r.funcargs(fn) + if !r.bool() { + return + } - if r.bool() { body := r.stmts() if body == nil { pos := src.NoXPos if quirksMode() { pos = funcParamsEndPos(fn) } - body = []ir.Node{ir.NewBlockStmt(pos, nil)} + body = []ir.Node{typecheck.Stmt(ir.NewBlockStmt(pos, nil))} } fn.Body = body fn.Endlineno = r.pos() - } + }) - ir.CurFunc = outerCurFunc r.marker.WriteTo(fn) } @@ -1045,7 +1043,42 @@ func (r *reader) closeAnotherScope() { scopeVars := r.scopeVars[len(r.scopeVars)-1] r.scopeVars = r.scopeVars[:len(r.scopeVars)-1] - if scopeVars == len(r.curfn.Dcl) { + // Quirkish: noder decides which scopes to keep before + // typechecking, whereas incremental typechecking during IR + // construction can result in new autotemps being allocated. To + // produce identical output, we ignore autotemps here for the + // purpose of deciding whether to retract the scope. + // + // This is important for net/http/fcgi, because it contains: + // + // var body io.ReadCloser + // if len(content) > 0 { + // body, req.pw = io.Pipe() + // } else { … } + // + // Notably, io.Pipe is inlinable, and inlining it introduces a ~R0 + // variable at the call site. + // + // Noder does not preserve the scope where the io.Pipe() call + // resides, because it doesn't contain any declared variables in + // source. So the ~R0 variable ends up being assigned to the + // enclosing scope instead. + // + // However, typechecking this assignment also introduces + // autotemps, because io.Pipe's results need conversion before + // they can be assigned to their respective destination variables. + // + // TODO(mdempsky): We should probably just keep all scopes, and + // let dwarfgen take care of pruning them instead. + retract := true + for _, n := range r.curfn.Dcl[scopeVars:] { + if !n.AutoTemp() { + retract = false + break + } + } + + if retract { // no variables were declared in this scope, so we can retract it. r.marker.Unpush() } else { @@ -1068,6 +1101,7 @@ func (r *reader) stmt() ir.Node { } func (r *reader) stmts() []ir.Node { + assert(ir.CurFunc == r.curfn) var res ir.Nodes r.sync(syncStmts) @@ -1079,7 +1113,7 @@ func (r *reader) stmts() []ir.Node { } if n := r.stmt1(tag, &res); n != nil { - res.Append(n) + res.Append(typecheck.Stmt(n)) } } } @@ -1108,7 +1142,7 @@ func (r *reader) stmt1(tag codeStmt, out *ir.Nodes) ir.Node { for _, name := range names { as := ir.NewAssignStmt(pos, name, nil) as.PtrInit().Append(ir.NewDecl(pos, ir.ODCL, name)) - out.Append(as) + out.Append(typecheck.Stmt(as)) } return nil } @@ -1488,6 +1522,9 @@ func (r *reader) expr() ir.Node { case exprCall: fun := r.expr() + if clo, ok := fun.(*ir.ClosureExpr); ok { + clo.Func.SetClosureCalled(true) + } pos := r.pos() args := r.exprs() dots := r.bool() @@ -1574,11 +1611,15 @@ func (r *reader) funcLit() ir.Node { } fn := ir.NewClosureFunc(opos, r.curfn != nil) + clo := fn.OClosure + ir.NameClosure(clo, r.curfn) r.setType(fn.Nname, xtype2) if quirksMode() { fn.Nname.Ntype = ir.TypeNodeAt(typPos, xtype2) } + typecheck.Func(fn) + r.setType(clo, fn.Type()) fn.ClosureVars = make([]*ir.Name, 0, r.len()) for len(fn.ClosureVars) < cap(fn.ClosureVars) { @@ -1591,7 +1632,8 @@ func (r *reader) funcLit() ir.Node { r.addBody(fn) - return fn.OClosure + // TODO(mdempsky): Remove hard-coding of typecheck.Target. + return ir.UseClosure(clo, typecheck.Target) } func (r *reader) exprList() []ir.Node { @@ -1788,7 +1830,7 @@ func InlineCall(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExp r.setType(tmpfn.Nname, fn.Type()) r.curfn = tmpfn - r.inlCaller = ir.CurFunc + r.inlCaller = callerfn r.inlCall = call r.inlFunc = fn r.inlTreeIndex = inlIndex @@ -1872,17 +1914,13 @@ func InlineCall(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExp nparams := len(r.curfn.Dcl) - oldcurfn := ir.CurFunc - ir.CurFunc = r.curfn - - r.curfn.Body = r.stmts() - r.curfn.Endlineno = r.pos() + ir.WithFunc(r.curfn, func() { + r.curfn.Body = r.stmts() + r.curfn.Endlineno = r.pos() - typecheck.Stmts(r.curfn.Body) - deadcode.Func(r.curfn) + deadcode.Func(r.curfn) - // Replace any "return" statements within the function body. - { + // Replace any "return" statements within the function body. var edit func(ir.Node) ir.Node edit = func(n ir.Node) ir.Node { if ret, ok := n.(*ir.ReturnStmt); ok { @@ -1892,9 +1930,7 @@ func InlineCall(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExp return n } edit(r.curfn) - } - - ir.CurFunc = oldcurfn + }) body := ir.Nodes(r.curfn.Body) @@ -1998,15 +2034,11 @@ func expandInline(fn *ir.Func, pri pkgReaderIndex) { r.funarghack = true r.funcBody(tmpfn) - } - - oldcurfn := ir.CurFunc - ir.CurFunc = tmpfn - typecheck.Stmts(tmpfn.Body) - deadcode.Func(tmpfn) - - ir.CurFunc = oldcurfn + ir.WithFunc(tmpfn, func() { + deadcode.Func(tmpfn) + }) + } used := usedLocals(tmpfn.Body) diff --git a/src/cmd/compile/internal/noder/unified.go b/src/cmd/compile/internal/noder/unified.go index 03bcb2755b..39989778f8 100644 --- a/src/cmd/compile/internal/noder/unified.go +++ b/src/cmd/compile/internal/noder/unified.go @@ -138,23 +138,6 @@ func unified(noders []*noder) { } todoBodies = nil - // Don't use range--typecheck can add closures to Target.Decls. - for i := 0; i < len(target.Decls); i++ { - if fn, ok := target.Decls[i].(*ir.Func); ok { - if base.Flag.W > 1 { - s := fmt.Sprintf("\nbefore typecheck %v", fn) - ir.Dump(s, fn) - } - ir.WithFunc(fn, func() { - typecheck.Stmts(fn.Body) - }) - if base.Flag.W > 1 { - s := fmt.Sprintf("\nafter typecheck %v", fn) - ir.Dump(s, fn) - } - } - } - if !quirksMode() { // TODO(mdempsky): Investigate generating wrappers in quirks mode too. r.wrapTypes(target) diff --git a/src/cmd/compile/internal/noder/unified_test.go b/src/cmd/compile/internal/noder/unified_test.go index ca91b49fbb..26173682fb 100644 --- a/src/cmd/compile/internal/noder/unified_test.go +++ b/src/cmd/compile/internal/noder/unified_test.go @@ -54,7 +54,7 @@ func TestUnifiedCompare(t *testing.T) { t.Parallel() } - pkgs1 := loadPackages(t, goos, goarch, "-d=unified=0 -d=inlfuncswithclosures=0") + pkgs1 := loadPackages(t, goos, goarch, "-d=unified=0 -d=inlfuncswithclosures=0 -d=unifiedquirks=1") pkgs2 := loadPackages(t, goos, goarch, "-d=unified=1 -d=inlfuncswithclosures=0 -d=unifiedquirks=1") if len(pkgs1) != len(pkgs2) { diff --git a/src/cmd/compile/internal/typecheck/dcl.go b/src/cmd/compile/internal/typecheck/dcl.go index f3ccbb4ac0..66d755089a 100644 --- a/src/cmd/compile/internal/typecheck/dcl.go +++ b/src/cmd/compile/internal/typecheck/dcl.go @@ -450,7 +450,16 @@ func autotmpname(n int) string { if s == "" { // Give each tmp a different name so that they can be registerized. // Add a preceding . to avoid clashing with legal names. - s = fmt.Sprintf(".autotmp_%d", n) + prefix := ".autotmp_%d" + + // In quirks mode, pad out the number to stabilize variable + // sorting. This ensures autotmps 8 and 9 sort the same way even + // if they get renumbered to 9 and 10, respectively. + if base.Debug.UnifiedQuirks != 0 { + prefix = ".autotmp_%06d" + } + + s = fmt.Sprintf(prefix, n) autotmpnames[n] = s } return s -- GitLab From 6dec18cc75021bfbfac267941a567b257721208b Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 28 Jun 2021 18:04:58 -0700 Subject: [PATCH 0401/2500] [dev.typeparams] cmd/compile: start using sub-dictionary entries where needed Added new struct instInfo for information about an instantiation (of a generic function/method with gcshapes or concrete types). We use this to remember the dictionary param node, the nodes where sub-dictionaries need to be used, etc. The instInfo map replaces the Stencil map in Package. Added code to access sub-dictionary entries at the appropriate call sites. We are currently still calculating the corresponding main dictionary, even when we really only need a sub-dictionary. I'll clean that up in a follow-up CL. Added code to deal with "generic" closures (closures that reference some generic variables/types). We decided that closures will share the same dictionary as the containing function (accessing the dictionary via a closure variable). So, the getGfInfo function now traverses all the nodes of each closure in a function that it is analyzing, so that a function's dictionary has all the entries needed for all its closures as well. Also, the instInfo of a closure is largely shared with its containing function. A good test for generic closures already exists with orderedmap.go. Other improvements: - Only create sub-dictionary entries when the function/method call/value or closure actually has type params in it. Added new test file subdict.go with an example where a generic method has an instantiated method call that does not depend not have type params. Change-Id: I691b9dc024a89d2305fcf1d8ba8540e53c9d103f Reviewed-on: https://go-review.googlesource.com/c/go/+/331516 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/ir/package.go | 3 - src/cmd/compile/internal/noder/irgen.go | 32 +- src/cmd/compile/internal/noder/stencil.go | 344 +++++++++++++++------- test/typeparam/subdict.go | 42 +++ 4 files changed, 309 insertions(+), 112 deletions(-) create mode 100644 test/typeparam/subdict.go diff --git a/src/cmd/compile/internal/ir/package.go b/src/cmd/compile/internal/ir/package.go index e4b93d113e..3896e2b91b 100644 --- a/src/cmd/compile/internal/ir/package.go +++ b/src/cmd/compile/internal/ir/package.go @@ -32,7 +32,4 @@ type Package struct { // Exported (or re-exported) symbols. Exports []*Name - - // Map from function names of stencils to already-created stencils. - Stencils map[*types.Sym]*Func } diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index 8f39061250..299d468a15 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -100,11 +100,34 @@ func check2(noders []*noder) { type gfInfo struct { tparams []*types.Type derivedTypes []*types.Type - // Node in generic function that requires a subdictionary. Some of these - // are not function/method values (not strictly calls). + // Nodes in generic function that requires a subdictionary. Includes + // method and function calls (OCALL), function values (OFUNCINST), method + // values/expressions (OXDOT). subDictCalls []ir.Node } +// instInfo is information gathered on an gcshape (or fully concrete) +// instantiation of a function. +type instInfo struct { + fun *ir.Func // The instantiated function (with body) + dictParam *ir.Name // The node inside fun that refers to the dictionary param + // Addr of static dictionary associated with this instantiation. This is the + // dictionary you should pass if all the type args are concreate. Soon to be + // removed, when creating static dictionary and instantiated function are + // separated. + dictAddr ir.Node + + gf *ir.Name // The associated generic function + gfInfo *gfInfo + + startSubDict int // Start of dict entries for subdictionaries + dictLen int // Total number of entries in dictionary + + // Map from nodes in instantiated fun (OCALL, OCALLMETHOD, OFUNCINST, and + // OMETHEXPR) to the associated dictionary entry for a sub-dictionary + dictEntryMap map[ir.Node]int +} + type irgen struct { target *ir.Package self *types2.Package @@ -123,6 +146,11 @@ type irgen struct { // Map from generic function to information about its type params, derived // types, and subdictionaries. gfInfoMap map[*types.Sym]*gfInfo + + // Map from a name of function that been instantiated to information about + // its instantiated function, associated generic function/method, and the + // mapping from IR nodes to dictionary entries. + instInfoMap map[*types.Sym]*instInfo } func (g *irgen) generate(noders []*noder) { diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index c04300a165..9d70e0e299 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -44,7 +44,7 @@ func infoPrint(format string, a ...interface{}) { // encountered already or new ones that are encountered during the stenciling // process. func (g *irgen) stencil() { - g.target.Stencils = make(map[*types.Sym]*ir.Func) + g.instInfoMap = make(map[*types.Sym]*instInfo) g.gfInfoMap = make(map[*types.Sym]*gfInfo) // Instantiate the methods of instantiated generic types that we have seen so far. @@ -86,6 +86,9 @@ func (g *irgen) stencil() { // to calling that function directly. modified := false closureRequired := false + // declInfo will be non-nil exactly if we are scanning an instantiated function + declInfo := g.instInfoMap[decl.Sym()] + ir.Visit(decl, func(n ir.Node) { if n.Op() == ir.OFUNCINST { // generic F, not immediately called @@ -103,11 +106,24 @@ func (g *irgen) stencil() { call := n.(*ir.CallExpr) inst := call.X.(*ir.InstExpr) st, dict := g.getInstantiationForNode(inst) - if infoPrintMode && g.target.Stencils[decl.Sym()] == nil { + dictkind := "Main dictionary" + if declInfo != nil { + // Get the dictionary arg via sub-dictionary reference + entry, ok := declInfo.dictEntryMap[n] + // If the entry is not found, it must be that + // this node was did not have any type args + // that depend on type params, so we need a + // main dictionary, not a sub-dictionary. + if ok { + dict = getDictionaryEntry(n.Pos(), declInfo.dictParam, entry, declInfo.dictLen) + dictkind = "Sub-dictionary" + } + } + if infoPrintMode { if inst.X.Op() == ir.OMETHVALUE { - fmt.Printf("Main dictionary in %v at generic method call: %v - %v\n", decl, inst.X, call) + fmt.Printf("%s in %v at generic method call: %v - %v\n", dictkind, decl, inst.X, call) } else { - fmt.Printf("Main dictionary in %v at generic function call: %v - %v\n", decl, inst.X, call) + fmt.Printf("%s in %v at generic function call: %v - %v\n", dictkind, decl, inst.X, call) } } // Replace the OFUNCINST with a direct reference to the @@ -147,6 +163,17 @@ func (g *irgen) stencil() { } st, dict := g.getInstantiation(gf, targs, true) + entry, ok := declInfo.dictEntryMap[n] + // TODO: Not creating sub-dictionary entry for + // absDifference in absdiff.go yet. Unusual case, + // where there are different generic method + // implementations of Abs in absDifference. + if ok { + if infoPrintMode { + fmt.Printf("Sub-dictionary in %v at generic method call: %v\n", decl, call) + } + dict = getDictionaryEntry(n.Pos(), declInfo.dictParam, entry, declInfo.dictLen) + } call.SetOp(ir.OCALL) call.X = st.Nname call.Args.Prepend(dict, meth.X) @@ -175,8 +202,6 @@ func (g *irgen) stencil() { ir.EditChildren(x, edit) switch { case x.Op() == ir.OFUNCINST: - // TODO: only set outer!=nil if this instantiation uses - // a type parameter from outer. See comment in buildClosure. return g.buildClosure(outer, x) case x.Op() == ir.OMETHEXPR && len(deref(x.(*ir.SelectorExpr).X.Type()).RParams()) > 0 && !types.IsInterfaceMethod(x.(*ir.SelectorExpr).Selection.Type): // TODO: test for ptr-to-method case @@ -208,6 +233,11 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { var dictValue ir.Node // dictionary to use var rcvrValue ir.Node // receiver, if a method value typ := x.Type() // type of the closure + var outerInfo *instInfo + if outer != nil { + outerInfo = g.instInfoMap[outer.Sym()] + } + usingSubdict := false if x.Op() == ir.OFUNCINST { inst := x.(*ir.InstExpr) @@ -234,11 +264,20 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { // as its first two arguments. // dictValue is the value to use for the dictionary argument. target, dictValue = g.getInstantiation(gf, targs, rcvrValue != nil) - if infoPrintMode && (outer == nil || g.target.Stencils[outer.Sym()] == nil) { + dictkind := "Main dictionary" + if outerInfo != nil { + entry, ok := outerInfo.dictEntryMap[x] + if ok { + dictValue = getDictionaryEntry(x.Pos(), outerInfo.dictParam, entry, outerInfo.dictLen) + dictkind = "Sub-dictionary" + usingSubdict = true + } + } + if infoPrintMode { if rcvrValue == nil { - fmt.Printf("Main dictionary in %v for function value %v\n", outer, inst.X) + fmt.Printf("%s in %v for generic function value %v\n", dictkind, outer, inst.X) } else { - fmt.Printf("Main dictionary in %v for method value %v\n", outer, inst.X) + fmt.Printf("%s in %v for generic method value %v\n", dictkind, outer, inst.X) } } } else { // ir.OMETHEXPR @@ -270,8 +309,17 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { } } target, dictValue = g.getInstantiation(gf, targs, true) - if infoPrintMode && (outer == nil || g.target.Stencils[outer.Sym()] == nil) { - fmt.Printf("Main dictionary in %v for method expression %v\n", outer, x) + dictkind := "Main dictionary" + if outerInfo != nil { + entry, ok := outerInfo.dictEntryMap[x] + if ok { + dictValue = getDictionaryEntry(x.Pos(), outerInfo.dictParam, entry, outerInfo.dictLen) + dictkind = "Sub-dictionary" + usingSubdict = true + } + } + if infoPrintMode { + fmt.Printf("%s in %v for method expression %v\n", dictkind, outer, x) } } @@ -386,14 +434,12 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { // First, figure out the dictionary argument. var dict2Var ir.Node - if outer != nil { - // If there's an outer function, the dictionary value will be read from - // the dictionary of the outer function. - // TODO: only use a subdictionary if any of the instantiating types - // depend on the type params of the outer function. + if usingSubdict { + // Capture sub-dictionary calculated in the outer function dict2Var = ir.CaptureName(pos, fn, dictVar) + typed(types.Types[types.TUINTPTR], dict2Var) } else { - // No outer function, instantiating types are known concrete types. + // Static dictionary, so can be used directly in the closure dict2Var = dictValue } // Also capture the receiver variable. @@ -695,8 +741,8 @@ func (g *irgen) getInstantiation(nameNode *ir.Name, targs []*types.Type, isMeth nameNode.Func.Dcl = nameNode.Func.Inl.Dcl } sym := typecheck.MakeInstName(nameNode.Sym(), targs, isMeth) - st := g.target.Stencils[sym] - if st == nil { + info := g.instInfoMap[sym] + if info == nil { if false { // Testing out gcshapeType() and gcshapeName() for i, t := range targs { @@ -706,27 +752,38 @@ func (g *irgen) getInstantiation(nameNode *ir.Name, targs []*types.Type, isMeth } // If instantiation doesn't exist yet, create it and add // to the list of decls. - st = g.genericSubst(sym, nameNode, targs, isMeth) + gfInfo := g.getGfInfo(nameNode) + info = &instInfo{ + gf: nameNode, + gfInfo: gfInfo, + startSubDict: len(targs) + len(gfInfo.derivedTypes), + dictLen: len(targs) + len(gfInfo.derivedTypes) + len(gfInfo.subDictCalls), + dictEntryMap: make(map[ir.Node]int), + } + // genericSubst fills in info.dictParam and info.dictEntryMap. + st := g.genericSubst(sym, nameNode, targs, isMeth, info) + info.fun = st + info.dictAddr = g.getDictionaryValue(nameNode, targs, isMeth) + g.instInfoMap[sym] = info // This ensures that the linker drops duplicates of this instantiation. // All just works! st.SetDupok(true) - g.target.Stencils[sym] = st g.target.Decls = append(g.target.Decls, st) if base.Flag.W > 1 { ir.Dump(fmt.Sprintf("\nstenciled %v", st), st) } } - return st, g.getDictionaryValue(nameNode, targs, isMeth) + return info.fun, info.dictAddr } // Struct containing info needed for doing the substitution as we create the // instantiation of a generic function with specified type arguments. type subster struct { - g *irgen - isMethod bool // If a method is being instantiated - newf *ir.Func // Func node for the new stenciled function - ts typecheck.Tsubster - dictionary *ir.Name // Name of dictionary variable + g *irgen + isMethod bool // If a method is being instantiated + newf *ir.Func // Func node for the new stenciled function + ts typecheck.Tsubster + info *instInfo // Place to put extra info in the instantiation } // genericSubst returns a new function with name newsym. The function is an @@ -734,8 +791,8 @@ type subster struct { // args targs. For a method with a generic receiver, it returns an instantiated // function type where the receiver becomes the first parameter. Otherwise the // instantiated method would still need to be transformed by later compiler -// phases. -func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []*types.Type, isMethod bool) *ir.Func { +// phases. genericSubst fills in info.dictParam and info.dictEntryMap. +func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []*types.Type, isMethod bool, info *instInfo) *ir.Func { var tparams []*types.Type if isMethod { // Get the type params from the method receiver (after skipping @@ -769,6 +826,7 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []*type g: g, isMethod: isMethod, newf: newf, + info: info, ts: typecheck.Tsubster{ Tparams: tparams, Targs: targs, @@ -778,13 +836,7 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []*type newf.Dcl = make([]*ir.Name, 0, len(gf.Dcl)+1) - // Replace the types in the function signature. - // Ugly: also, we have to insert the Name nodes of the parameters/results into - // the function type. The current function type has no Nname fields set, - // because it came via conversion from the types2 type. - oldt := nameNode.Type() - // We also transform a generic method type to the corresponding - // instantiated function type where the dictionary is the first parameter. + // Create the needed dictionary param dictionarySym := newsym.Pkg.Lookup(".dict") dictionaryType := types.Types[types.TUINTPTR] dictionaryName := ir.NewNameAt(gf.Pos(), dictionarySym) @@ -800,11 +852,21 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []*type } dictionaryArg := types.NewField(gf.Pos(), dictionarySym, dictionaryType) dictionaryArg.Nname = dictionaryName - subst.dictionary = dictionaryName + info.dictParam = dictionaryName + + // We add the dictionary as the first parameter in the function signature. + // We also transform a method type to the corresponding function type + // (make the receiver be the next parameter after the dictionary). + oldt := nameNode.Type() var args []*types.Field args = append(args, dictionaryArg) args = append(args, oldt.Recvs().FieldSlice()...) args = append(args, oldt.Params().FieldSlice()...) + + // Replace the types in the function signature via subst.fields. + // Ugly: also, we have to insert the Name nodes of the parameters/results into + // the function type. The current function type has no Nname fields set, + // because it came via conversion from the types2 type. newt := types.NewSignature(oldt.Pkg(), nil, nil, subst.fields(ir.PPARAM, args, newf.Dcl), subst.fields(ir.PPARAMOUT, oldt.Results().FieldSlice(), newf.Dcl)) @@ -884,6 +946,26 @@ func (g *irgen) checkDictionary(name *ir.Name, targs []*types.Type) (code []ir.N return } +// getDictionaryEntry gets the i'th entry in the dictionary dict. +func getDictionaryEntry(pos src.XPos, dict *ir.Name, i int, size int) ir.Node { + // Convert dictionary to *[N]uintptr + // All entries in the dictionary are pointers. They all point to static data, though, so we + // treat them as uintptrs so the GC doesn't need to keep track of them. + d := ir.NewConvExpr(pos, ir.OCONVNOP, types.Types[types.TUNSAFEPTR], dict) + d.SetTypecheck(1) + d = ir.NewConvExpr(pos, ir.OCONVNOP, types.NewArray(types.Types[types.TUINTPTR], int64(size)).PtrTo(), d) + d.SetTypecheck(1) + + // Load entry i out of the dictionary. + deref := ir.NewStarExpr(pos, d) + typed(d.Type().Elem(), deref) + idx := ir.NewConstExpr(constant.MakeUint64(uint64(i)), dict) // TODO: what to set orig to? + typed(types.Types[types.TUINTPTR], idx) + r := ir.NewIndexExpr(pos, deref, idx) + typed(types.Types[types.TUINTPTR], r) + return r +} + // getDictionaryType returns a *runtime._type from the dictionary corresponding to the input type. // The input type must be a type parameter (TODO: or a local derived type). func (subst *subster) getDictionaryType(pos src.XPos, t *types.Type) ir.Node { @@ -898,21 +980,10 @@ func (subst *subster) getDictionaryType(pos src.XPos, t *types.Type) ir.Node { base.Fatalf(fmt.Sprintf("couldn't find type param %+v", t)) } - // Convert dictionary to *[N]uintptr - // All entries in the dictionary are pointers. They all point to static data, though, so we - // treat them as uintptrs so the GC doesn't need to keep track of them. - d := ir.NewConvExpr(pos, ir.OCONVNOP, types.Types[types.TUNSAFEPTR], subst.dictionary) - d.SetTypecheck(1) - d = ir.NewConvExpr(pos, ir.OCONVNOP, types.NewArray(types.Types[types.TUINTPTR], int64(len(tparams))).PtrTo(), d) - d.SetTypecheck(1) - - // Load entry i out of the dictionary. - deref := ir.NewStarExpr(pos, d) - typed(d.Type().Elem(), deref) - idx := ir.NewConstExpr(constant.MakeUint64(uint64(i)), subst.dictionary) // TODO: what to set orig to? - typed(types.Types[types.TUINTPTR], idx) - r := ir.NewIndexExpr(pos, deref, idx) - typed(types.Types[types.TUINT8].PtrTo(), r) // standard typing of a *runtime._type in the compiler is *byte + r := getDictionaryEntry(pos, subst.info.dictParam, i, len(tparams)) + // change type of retrieved dictionary entry to *byte, which is the + // standard typing of a *runtime._type in the compiler + typed(types.Types[types.TUINT8].PtrTo(), r) return r } @@ -957,6 +1028,18 @@ func (subst *subster) node(n ir.Node) ir.Node { m.SetType(subst.ts.Typ(x.Type())) } } + + for i, de := range subst.info.gfInfo.subDictCalls { + if de == x { + // Remember the dictionary entry associated with this + // node in the instantiated function + // TODO: make sure this remains correct with respect to the + // transformations below. + subst.info.dictEntryMap[m] = subst.info.startSubDict + i + break + } + } + ir.EditChildren(m, edit) m.SetTypecheck(1) @@ -1109,7 +1192,26 @@ func (subst *subster) node(n ir.Node) ir.Node { ir.CurFunc = newfn subst.newf = newfn newfn.Dcl = subst.namelist(oldfn.Dcl) - newfn.ClosureVars = subst.namelist(oldfn.ClosureVars) + + // Make a closure variable for the dictionary of the + // containing function. + cdict := ir.CaptureName(oldfn.Pos(), newfn, subst.info.dictParam) + typed(types.Types[types.TUINTPTR], cdict) + ir.FinishCaptureNames(oldfn.Pos(), saveNewf, newfn) + newfn.ClosureVars = append(newfn.ClosureVars, subst.namelist(oldfn.ClosureVars)...) + + // Create inst info for the instantiated closure. The dict + // param is the closure variable for the dictionary of the + // outer function. Since the dictionary is shared, use the + // same entries for startSubDict, dictLen, dictEntryMap. + cinfo := &instInfo{ + fun: newfn, + dictParam: cdict, + startSubDict: subst.info.startSubDict, + dictLen: subst.info.dictLen, + dictEntryMap: subst.info.dictEntryMap, + } + subst.g.instInfoMap[newfn.Nname.Sym()] = cinfo typed(subst.ts.Typ(oldfn.Nname.Type()), newfn.Nname) typed(newfn.Nname.Type(), newfn.OClosure) @@ -1257,7 +1359,7 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) // Initialize the dictionary, if we haven't yet already. if lsym := sym.Linksym(); len(lsym.P) == 0 { - infoPrint("Creating dictionary %v\n", sym.Name) + infoPrint("=== Creating dictionary %v\n", sym.Name) off := 0 // Emit an entry for each targ (concrete type or gcshape). for _, t := range targs { @@ -1279,7 +1381,8 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) // Emit an entry for each subdictionary (after substituting targs) for _, n := range info.subDictCalls { var sym *types.Sym - if n.Op() == ir.OCALL { + switch n.Op() { + case ir.OCALL: call := n.(*ir.CallExpr) if call.X.Op() == ir.OXDOT { subtargs := deref(call.X.(*ir.SelectorExpr).X.Type()).RParams() @@ -1304,11 +1407,9 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) subtargs[i] = subst.Typ(t) } sym = g.getDictionarySym(nameNode, subtargs, isMeth) - // TODO: This can actually be a static - // main dictionary, if all of the subtargs - // are concrete types (!HasTParam) } - } else if n.Op() == ir.OFUNCINST { + + case ir.OFUNCINST: inst := n.(*ir.InstExpr) nameNode := inst.X.(*ir.Name) subtargs := typecheck.TypesOf(inst.Targs) @@ -1316,10 +1417,8 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) subtargs[i] = subst.Typ(t) } sym = g.getDictionarySym(nameNode, subtargs, false) - // TODO: This can actually be a static - // main dictionary, if all of the subtargs - // are concrete types (!HasTParam) - } else if n.Op() == ir.OXDOT { + + case ir.OXDOT: selExpr := n.(*ir.SelectorExpr) subtargs := selExpr.X.Type().RParams() s2targs := make([]*types.Type, len(subtargs)) @@ -1328,14 +1427,16 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) } nameNode := selExpr.Selection.Nname.(*ir.Name) sym = g.getDictionarySym(nameNode, s2targs, true) + + default: + assert(false) } - // TODO: handle closure cases that need sub-dictionaries, get rid of conditional - if sym != nil { - off = objw.SymPtr(lsym, off, sym.Linksym(), 0) - infoPrint(" - Subdict %v\n", sym.Name) - } + + off = objw.SymPtr(lsym, off, sym.Linksym(), 0) + infoPrint(" - Subdict %v\n", sym.Name) } objw.Global(lsym, int32(off), obj.DUPOK|obj.RODATA) + infoPrint("=== Done dictionary\n") // Add any new, fully instantiated types seen during the substitution to g.instTypeList. g.instTypeList = append(g.instTypeList, subst.InstTypeList...) @@ -1363,6 +1464,26 @@ func (g *irgen) getDictionaryValue(gf *ir.Name, targs []*types.Type, isMeth bool return np } +// hasTParamNodes returns true if the type of any node in targs has a typeparam. +func hasTParamNodes(targs []ir.Node) bool { + for _, n := range targs { + if n.Type().HasTParam() { + return true + } + } + return false +} + +// hasTParamNodes returns true if any type in targs has a typeparam. +func hasTParamTypes(targs []*types.Type) bool { + for _, t := range targs { + if t.HasTParam() { + return true + } + } + return false +} + // getGfInfo get information for a generic function - type params, derived generic // types, and subdictionaries. func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo { @@ -1377,8 +1498,9 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo { if recv != nil { info.tparams = deref(recv.Type).RParams() } else { - info.tparams = make([]*types.Type, len(gn.Type().TParams().FieldSlice())) - for i, f := range gn.Type().TParams().FieldSlice() { + tparams := gn.Type().TParams().FieldSlice() + info.tparams = make([]*types.Type, len(tparams)) + for i, f := range tparams { info.tparams[i] = f.Type } } @@ -1387,23 +1509,28 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo { } if infoPrintMode { - fmt.Printf(">>> Info for %v\n", gn) + fmt.Printf(">>> GfInfo for %v\n", gn) for _, t := range info.tparams { fmt.Printf(" Typeparam %v\n", t) } - for _, t := range info.derivedTypes { - fmt.Printf(" Derived type %v\n", t) - } } - for _, stmt := range gf.Body { - ir.Visit(stmt, func(n ir.Node) { - if n.Op() == ir.OFUNCINST && !n.(*ir.InstExpr).Implicit() { + var visitFunc func(ir.Node) + visitFunc = func(n ir.Node) { + if n.Op() == ir.OFUNCINST && !n.(*ir.InstExpr).Implicit() { + if hasTParamNodes(n.(*ir.InstExpr).Targs) { infoPrint(" Closure&subdictionary required at generic function value %v\n", n.(*ir.InstExpr).X) info.subDictCalls = append(info.subDictCalls, n) - } else if n.Op() == ir.OXDOT && !n.(*ir.SelectorExpr).Implicit() && - n.(*ir.SelectorExpr).Selection != nil && - len(n.(*ir.SelectorExpr).X.Type().RParams()) > 0 { + } + } else if n.Op() == ir.OXDOT && !n.(*ir.SelectorExpr).Implicit() && + n.(*ir.SelectorExpr).Selection != nil && + len(n.(*ir.SelectorExpr).X.Type().RParams()) > 0 { + if n.(*ir.SelectorExpr).X.Op() == ir.OTYPE { + infoPrint(" Closure&subdictionary required at generic meth expr %v\n", n) + } else { + infoPrint(" Closure&subdictionary required at generic meth value %v\n", n) + } + if hasTParamTypes(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) { if n.(*ir.SelectorExpr).X.Op() == ir.OTYPE { infoPrint(" Closure&subdictionary required at generic meth expr %v\n", n) } else { @@ -1411,40 +1538,43 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo { } info.subDictCalls = append(info.subDictCalls, n) } - if n.Op() == ir.OCALL && n.(*ir.CallExpr).X.Op() == ir.OFUNCINST { - infoPrint(" Subdictionary at generic function call: %v - %v\n", n.(*ir.CallExpr).X.(*ir.InstExpr).X, n) - n.(*ir.CallExpr).X.(*ir.InstExpr).SetImplicit(true) + } + if n.Op() == ir.OCALL && n.(*ir.CallExpr).X.Op() == ir.OFUNCINST { + n.(*ir.CallExpr).X.(*ir.InstExpr).SetImplicit(true) + if hasTParamNodes(n.(*ir.CallExpr).X.(*ir.InstExpr).Targs) { + infoPrint(" Subdictionary at generic function/method call: %v - %v\n", n.(*ir.CallExpr).X.(*ir.InstExpr).X, n) info.subDictCalls = append(info.subDictCalls, n) } - if n.Op() == ir.OCALL && n.(*ir.CallExpr).X.Op() == ir.OXDOT && - n.(*ir.CallExpr).X.(*ir.SelectorExpr).Selection != nil && - len(deref(n.(*ir.CallExpr).X.(*ir.SelectorExpr).X.Type()).RParams()) > 0 { + } + if n.Op() == ir.OCALL && n.(*ir.CallExpr).X.Op() == ir.OXDOT && + n.(*ir.CallExpr).X.(*ir.SelectorExpr).Selection != nil && + len(deref(n.(*ir.CallExpr).X.(*ir.SelectorExpr).X.Type()).RParams()) > 0 { + n.(*ir.CallExpr).X.(*ir.SelectorExpr).SetImplicit(true) + if hasTParamTypes(deref(n.(*ir.CallExpr).X.(*ir.SelectorExpr).X.Type()).RParams()) { infoPrint(" Subdictionary at generic method call: %v\n", n) - n.(*ir.CallExpr).X.(*ir.SelectorExpr).SetImplicit(true) info.subDictCalls = append(info.subDictCalls, n) } - if n.Op() == ir.OCLOSURE { - oldfn := n.(*ir.ClosureExpr).Func - needDict := false - if oldfn.Nname.Type().HasTParam() { - needDict = true - infoPrint(" Subdictionary for closure that has generic params: %v\n", oldfn) - } else { - for _, cv := range oldfn.ClosureVars { - if cv.Type().HasTParam() { - needDict = true - infoPrint(" Subdictionary for closure that has generic capture: %v\n", oldfn) - break - } - } - } - if needDict { - info.subDictCalls = append(info.subDictCalls, n) - } + } + if n.Op() == ir.OCLOSURE { + // Visit the closure body and add all relevant entries to the + // dictionary of the outer function (closure will just use + // the dictionary of the outer function). + for _, n1 := range n.(*ir.ClosureExpr).Func.Body { + ir.Visit(n1, visitFunc) } + } - addType(&info, n, n.Type()) - }) + addType(&info, n, n.Type()) + } + + for _, stmt := range gf.Body { + ir.Visit(stmt, visitFunc) + } + if infoPrintMode { + for _, t := range info.derivedTypes { + fmt.Printf(" Derived type %v\n", t) + } + fmt.Printf(">>> Done Gfinfo\n") } g.gfInfoMap[gn.Sym()] = &info return &info diff --git a/test/typeparam/subdict.go b/test/typeparam/subdict.go new file mode 100644 index 0000000000..c899af6d0d --- /dev/null +++ b/test/typeparam/subdict.go @@ -0,0 +1,42 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test cases where a main dictionary is needed inside a generic function/method, because +// we are calling a method on a fully-instantiated type or a fully-instantiated function. +// (probably not common situations, of course) + +package main + +import ( + "fmt" +) + +type value[T comparable] struct { + val T +} + +func (v *value[T]) test(def T) bool { + return (v.val == def) +} + +func (v *value[T]) get(def T) T { + var c value[int] + if c.test(32) { + return def + } else if v.test(def) { + return def + } else { + return v.val + } +} + + +func main() { + var s value[string] + if got, want := s.get("ab"), ""; got != want { + panic(fmt.Sprintf("get() == %d, want %d", got, want)) + } +} -- GitLab From b994cc69e05d7821a08f75619f356ecfe5ca9b43 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Fri, 2 Jul 2021 12:32:38 -0700 Subject: [PATCH 0402/2500] [dev.typeparams] cmd/compile: separate out creating instantiations from creating dictionaries We often need to create a function/method instantiation, but not a dictionary, because the call to the instantiation will be using a sub-dictionary. Also, main dictionaries are only need for concrete, non-gcshape types, whereas instantiations will be for gcshape types (or concrete types, for strict stenciling). Created a helper function getDictOrSubdict() to reduce duplicated code. Also, moved gfGetGfInfo() call in getDictionarySym() inside conditional where it is needed, to avoid extra work when dictionary has already been created. Change-Id: I06587cb2ddc77de2f991e9f9eaf462d2c5a5d45e Reviewed-on: https://go-review.googlesource.com/c/go/+/332550 Trust: Dan Scales Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/irgen.go | 5 - src/cmd/compile/internal/noder/stencil.go | 117 ++++++++++++---------- 2 files changed, 62 insertions(+), 60 deletions(-) diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index 299d468a15..64c29435b5 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -111,11 +111,6 @@ type gfInfo struct { type instInfo struct { fun *ir.Func // The instantiated function (with body) dictParam *ir.Name // The node inside fun that refers to the dictionary param - // Addr of static dictionary associated with this instantiation. This is the - // dictionary you should pass if all the type args are concreate. Soon to be - // removed, when creating static dictionary and instantiated function are - // separated. - dictAddr ir.Node gf *ir.Name // The associated generic function gfInfo *gfInfo diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 9d70e0e299..d35e036ae6 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -105,21 +105,15 @@ func (g *irgen) stencil() { // instantiation. call := n.(*ir.CallExpr) inst := call.X.(*ir.InstExpr) - st, dict := g.getInstantiationForNode(inst) - dictkind := "Main dictionary" - if declInfo != nil { - // Get the dictionary arg via sub-dictionary reference - entry, ok := declInfo.dictEntryMap[n] - // If the entry is not found, it must be that - // this node was did not have any type args - // that depend on type params, so we need a - // main dictionary, not a sub-dictionary. - if ok { - dict = getDictionaryEntry(n.Pos(), declInfo.dictParam, entry, declInfo.dictLen) + nameNode, isMeth := g.getInstNameNode(inst) + targs := typecheck.TypesOf(inst.Targs) + st := g.getInstantiation(nameNode, targs, isMeth) + dictValue, usingSubdict := g.getDictOrSubdict(declInfo, n, nameNode, targs, isMeth) + if infoPrintMode { + dictkind := "Main dictionary" + if usingSubdict { dictkind = "Sub-dictionary" } - } - if infoPrintMode { if inst.X.Op() == ir.OMETHVALUE { fmt.Printf("%s in %v at generic method call: %v - %v\n", dictkind, decl, inst.X, call) } else { @@ -137,7 +131,7 @@ func (g *irgen) stencil() { call.Args.Prepend(inst.X.(*ir.SelectorExpr).X) } // Add dictionary to argument list. - call.Args.Prepend(dict) + call.Args.Prepend(dictValue) // Transform the Call now, which changes OCALL // to OCALLFUNC and does typecheckaste/assignconvfn. transformCall(call) @@ -162,21 +156,18 @@ func (g *irgen) stencil() { } } - st, dict := g.getInstantiation(gf, targs, true) - entry, ok := declInfo.dictEntryMap[n] - // TODO: Not creating sub-dictionary entry for + st := g.getInstantiation(gf, targs, true) + dictValue, usingSubdict := g.getDictOrSubdict(declInfo, n, gf, targs, true) + _ = usingSubdict + // TODO: We should do assert(usingSubdict) here, but + // not creating sub-dictionary entry for // absDifference in absdiff.go yet. Unusual case, // where there are different generic method // implementations of Abs in absDifference. - if ok { - if infoPrintMode { - fmt.Printf("Sub-dictionary in %v at generic method call: %v\n", decl, call) - } - dict = getDictionaryEntry(n.Pos(), declInfo.dictParam, entry, declInfo.dictLen) - } + call.SetOp(ir.OCALL) call.X = st.Nname - call.Args.Prepend(dict, meth.X) + call.Args.Prepend(dictValue, meth.X) // Transform the Call now, which changes OCALL // to OCALLFUNC and does typecheckaste/assignconvfn. transformCall(call) @@ -263,17 +254,13 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { // For method values, the target expects a dictionary and the receiver // as its first two arguments. // dictValue is the value to use for the dictionary argument. - target, dictValue = g.getInstantiation(gf, targs, rcvrValue != nil) - dictkind := "Main dictionary" - if outerInfo != nil { - entry, ok := outerInfo.dictEntryMap[x] - if ok { - dictValue = getDictionaryEntry(x.Pos(), outerInfo.dictParam, entry, outerInfo.dictLen) + target = g.getInstantiation(gf, targs, rcvrValue != nil) + dictValue, usingSubdict = g.getDictOrSubdict(outerInfo, x, gf, targs, rcvrValue != nil) + if infoPrintMode { + dictkind := "Main dictionary" + if usingSubdict { dictkind = "Sub-dictionary" - usingSubdict = true } - } - if infoPrintMode { if rcvrValue == nil { fmt.Printf("%s in %v for generic function value %v\n", dictkind, outer, inst.X) } else { @@ -308,17 +295,13 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { break } } - target, dictValue = g.getInstantiation(gf, targs, true) - dictkind := "Main dictionary" - if outerInfo != nil { - entry, ok := outerInfo.dictEntryMap[x] - if ok { - dictValue = getDictionaryEntry(x.Pos(), outerInfo.dictParam, entry, outerInfo.dictLen) + target = g.getInstantiation(gf, targs, true) + dictValue, usingSubdict = g.getDictOrSubdict(outerInfo, x, gf, targs, true) + if infoPrintMode { + dictkind := "Main dictionary" + if usingSubdict { dictkind = "Sub-dictionary" - usingSubdict = true } - } - if infoPrintMode { fmt.Printf("%s in %v for method expression %v\n", dictkind, outer, x) } } @@ -497,8 +480,8 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { return ir.InitExpr(init, c) } -// instantiateMethods instantiates all the methods of all fully-instantiated -// generic types that have been added to g.instTypeList. +// instantiateMethods instantiates all the methods (and associated dictionaries) of +// all fully-instantiated generic types that have been added to g.instTypeList. func (g *irgen) instantiateMethods() { for i := 0; i < len(g.instTypeList); i++ { typ := g.instTypeList[i] @@ -521,21 +504,46 @@ func (g *irgen) instantiateMethods() { // Direct method calls go directly to the instantiations, implemented above. // Indirect method calls use wrappers generated in reflectcall. Those wrappers // will use these instantiations if they are needed (for interface tables or reflection). - _, _ = g.getInstantiation(baseNname, typ.RParams(), true) + _ = g.getInstantiation(baseNname, typ.RParams(), true) + _ = g.getDictionarySym(baseNname, typ.RParams(), true) } } g.instTypeList = nil } -// getInstantiationForNode returns the function/method instantiation and -// dictionary value for a InstExpr node inst. -func (g *irgen) getInstantiationForNode(inst *ir.InstExpr) (*ir.Func, ir.Node) { +// getInstNameNode returns the name node for the method or function being instantiated, and a bool which is true if a method is being instantiated. +func (g *irgen) getInstNameNode(inst *ir.InstExpr) (*ir.Name, bool) { if meth, ok := inst.X.(*ir.SelectorExpr); ok { - return g.getInstantiation(meth.Selection.Nname.(*ir.Name), typecheck.TypesOf(inst.Targs), true) + return meth.Selection.Nname.(*ir.Name), true } else { - return g.getInstantiation(inst.X.(*ir.Name), typecheck.TypesOf(inst.Targs), false) + return inst.X.(*ir.Name), false + } +} + +// getDictOrSubdict returns, for a method/function call or reference (node n) in an +// instantiation (described by instInfo), a node which is accessing a sub-dictionary +// or main/static dictionary, as needed, and also returns a boolean indicating if a +// sub-dictionary was accessed. nameNode is the particular function or method being +// called/referenced, and targs are the type arguments. +func (g *irgen) getDictOrSubdict(declInfo *instInfo, n ir.Node, nameNode *ir.Name, targs []*types.Type, isMeth bool) (ir.Node, bool) { + var dict ir.Node + usingSubdict := false + if declInfo != nil { + // Get the dictionary arg via sub-dictionary reference + entry, ok := declInfo.dictEntryMap[n] + // If the entry is not found, it may be that this node did not have + // any type args that depend on type params, so we need a main + // dictionary, not a sub-dictionary. + if ok { + dict = getDictionaryEntry(n.Pos(), declInfo.dictParam, entry, declInfo.dictLen) + usingSubdict = true + } + } + if !usingSubdict { + dict = g.getDictionaryValue(nameNode, targs, isMeth) } + return dict, usingSubdict } func addGcType(fl []*types.Field, t *types.Type) []*types.Field { @@ -730,7 +738,7 @@ func gcshapeType(t *types.Type) (*types.Type, string) { // getInstantiation gets the instantiantion and dictionary of the function or method nameNode // with the type arguments targs. If the instantiated function is not already // cached, then it calls genericSubst to create the new instantiation. -func (g *irgen) getInstantiation(nameNode *ir.Name, targs []*types.Type, isMeth bool) (*ir.Func, ir.Node) { +func (g *irgen) getInstantiation(nameNode *ir.Name, targs []*types.Type, isMeth bool) *ir.Func { if nameNode.Func.Body == nil && nameNode.Func.Inl != nil { // If there is no body yet but Func.Inl exists, then we can can // import the whole generic body. @@ -763,7 +771,6 @@ func (g *irgen) getInstantiation(nameNode *ir.Name, targs []*types.Type, isMeth // genericSubst fills in info.dictParam and info.dictEntryMap. st := g.genericSubst(sym, nameNode, targs, isMeth, info) info.fun = st - info.dictAddr = g.getDictionaryValue(nameNode, targs, isMeth) g.instInfoMap[sym] = info // This ensures that the linker drops duplicates of this instantiation. // All just works! @@ -773,7 +780,7 @@ func (g *irgen) getInstantiation(nameNode *ir.Name, targs []*types.Type, isMeth ir.Dump(fmt.Sprintf("\nstenciled %v", st), st) } } - return info.fun, info.dictAddr + return info.fun } // Struct containing info needed for doing the substitution as we create the @@ -1352,13 +1359,13 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) base.Fatalf("%s should have type arguments", gf.Sym().Name) } - info := g.getGfInfo(gf) - // Get a symbol representing the dictionary. sym := typecheck.MakeDictName(gf.Sym(), targs, isMeth) // Initialize the dictionary, if we haven't yet already. if lsym := sym.Linksym(); len(lsym.P) == 0 { + info := g.getGfInfo(gf) + infoPrint("=== Creating dictionary %v\n", sym.Name) off := 0 // Emit an entry for each targ (concrete type or gcshape). -- GitLab From ef39edefe1c59c0d5dbe0c23e95a664a2ad46839 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 2 Jul 2021 16:39:49 -0700 Subject: [PATCH 0403/2500] [dev.typeparams] src,cmd: bump go.mod to 'go 1.18' Necessary for building/testing generics code within src/ or src/cmd/ since CL 332373, and we'll need to do this eventually anyway. Change-Id: Ia8c658c92d861fd3803fa18bfc80407c3381b411 Reviewed-on: https://go-review.googlesource.com/c/go/+/332554 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: Keith Randall TryBot-Result: Go Bot --- src/cmd/go.mod | 2 +- src/go.mod | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/go.mod b/src/cmd/go.mod index cd03968eed..da304e292b 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -1,6 +1,6 @@ module cmd -go 1.17 +go 1.18 require ( github.com/google/pprof v0.0.0-20210506205249-923b5ab0fc1a diff --git a/src/go.mod b/src/go.mod index 379dcf504e..1fb8cbfcbe 100644 --- a/src/go.mod +++ b/src/go.mod @@ -1,6 +1,6 @@ module std -go 1.17 +go 1.18 require ( golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e -- GitLab From 5dac279fbdd8a4273253de98a4e44484b20bec5b Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 2 Jul 2021 16:29:42 -0700 Subject: [PATCH 0404/2500] [dev.typeparams] cmd/compile: formalize "hidden parameters" idea This CL formalizes the closure-var trick used for method-value wrappers to be reusable for defining other functions that take hidden parameters via the closure-context register. In particular, it: 1. Adds a new ir.NewHiddenParam function for creating hidden parameters. 2. Changes ir.NewClosureVar to copy Type/Typecheck from the closure variable, so that callers can needing to manually copy these. 3. Updates existing code accordingly (i.e., method-value wrappers to start using ir.NewHiddenParam, and closure builders to stop copying types). Longer term, I anticipate using this to pass dictionaries to stenciled functions within unified IR. Change-Id: I9da3ffdb2a26d15c6e89a21b4e080686d6dc872c Reviewed-on: https://go-review.googlesource.com/c/go/+/332612 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/escape/call.go | 4 +--- src/cmd/compile/internal/escape/escape.go | 10 ++++++-- src/cmd/compile/internal/escape/expr.go | 3 --- src/cmd/compile/internal/escape/graph.go | 8 +++++-- src/cmd/compile/internal/ir/name.go | 24 ++++++++++++++++++- src/cmd/compile/internal/noder/reader.go | 15 ++---------- src/cmd/compile/internal/typecheck/iimport.go | 9 ++----- src/cmd/compile/internal/walk/closure.go | 9 +------ 8 files changed, 43 insertions(+), 39 deletions(-) diff --git a/src/cmd/compile/internal/escape/call.go b/src/cmd/compile/internal/escape/call.go index 46bfe65aff..5bd748027e 100644 --- a/src/cmd/compile/internal/escape/call.go +++ b/src/cmd/compile/internal/escape/call.go @@ -343,9 +343,7 @@ func (e *escape) wrapExpr(pos src.XPos, exprp *ir.Node, init *ir.Nodes, call ir. e.oldLoc(tmp).captured = true - cv := ir.NewClosureVar(pos, wrapper, tmp) - cv.SetType(tmp.Type()) - tmp = typecheck.Expr(cv).(*ir.Name) + tmp = ir.NewClosureVar(pos, wrapper, tmp) } *exprp = tmp diff --git a/src/cmd/compile/internal/escape/escape.go b/src/cmd/compile/internal/escape/escape.go index 04d0c2356c..61e0121a40 100644 --- a/src/cmd/compile/internal/escape/escape.go +++ b/src/cmd/compile/internal/escape/escape.go @@ -183,8 +183,14 @@ func (b *batch) initFunc(fn *ir.Func) { // Allocate locations for local variables. for _, n := range fn.Dcl { - if n.Op() == ir.ONAME { - e.newLoc(n, false) + e.newLoc(n, false) + } + + // Also for hidden parameters (e.g., the ".this" parameter to a + // method value wrapper). + if fn.OClosure == nil { + for _, n := range fn.ClosureVars { + e.newLoc(n.Canonical(), false) } } diff --git a/src/cmd/compile/internal/escape/expr.go b/src/cmd/compile/internal/escape/expr.go index dfcd55734a..c2a679d474 100644 --- a/src/cmd/compile/internal/escape/expr.go +++ b/src/cmd/compile/internal/escape/expr.go @@ -46,9 +46,6 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) { if n.Class == ir.PFUNC || n.Class == ir.PEXTERN { return } - if n.IsClosureVar() && n.Defn == nil { - return // ".this" from method value wrapper - } e.flow(k, e.oldLoc(n)) case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT: diff --git a/src/cmd/compile/internal/escape/graph.go b/src/cmd/compile/internal/escape/graph.go index 6316435dfe..d3ae1da693 100644 --- a/src/cmd/compile/internal/escape/graph.go +++ b/src/cmd/compile/internal/escape/graph.go @@ -222,7 +222,9 @@ func (e *escape) newLoc(n ir.Node, transient bool) *location { } if n != nil && n.Op() == ir.ONAME { - n = n.(*ir.Name).Canonical() + if canon := n.(*ir.Name).Canonical(); n != canon { + base.Fatalf("newLoc on non-canonical %v (canonical is %v)", n, canon) + } } loc := &location{ n: n, @@ -234,7 +236,9 @@ func (e *escape) newLoc(n ir.Node, transient bool) *location { if n != nil { if n.Op() == ir.ONAME { n := n.(*ir.Name) - if n.Curfn != e.curfn { + if n.Class == ir.PPARAM && n.Curfn == nil { + // ok; hidden parameter + } else if n.Curfn != e.curfn { base.Fatalf("curfn mismatch: %v != %v for %v", n.Curfn, e.curfn, n) } diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index ff9784df1b..a2eec05013 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -358,7 +358,7 @@ func (n *Name) Byval() bool { return n.Canonical().flags&nameByval != 0 } -// NewClosureVar creates a new closure variable for fn to refer to +// NewClosureVar returns a new closure variable for fn to refer to // outer variable n. func NewClosureVar(pos src.XPos, fn *Func, n *Name) *Name { c := NewNameAt(pos, n.Sym()) @@ -368,11 +368,33 @@ func NewClosureVar(pos src.XPos, fn *Func, n *Name) *Name { c.Defn = n.Canonical() c.Outer = n + c.SetType(n.Type()) + c.SetTypecheck(n.Typecheck()) + fn.ClosureVars = append(fn.ClosureVars, c) return c } +// NewHiddenParam returns a new hidden parameter for fn with the given +// name and type. +func NewHiddenParam(pos src.XPos, fn *Func, sym *types.Sym, typ *types.Type) *Name { + if fn.OClosure != nil { + base.FatalfAt(fn.Pos(), "cannot add hidden parameters to closures") + } + + fn.SetNeedctxt(true) + + // Create a fake parameter, disassociated from any real function, to + // pretend to capture. + fake := NewNameAt(pos, sym) + fake.Class = PPARAM + fake.SetType(typ) + fake.SetByval(true) + + return NewClosureVar(pos, fn, fake) +} + // CaptureName returns a Name suitable for referring to n from within function // fn or from the package block if fn is nil. If n is a free variable declared // within a function that encloses fn, then CaptureName returns the closure diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 275baead04..14d982a1af 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -1623,11 +1623,7 @@ func (r *reader) funcLit() ir.Node { fn.ClosureVars = make([]*ir.Name, 0, r.len()) for len(fn.ClosureVars) < cap(fn.ClosureVars) { - pos := r.pos() - outer := r.useLocal() - - cv := ir.NewClosureVar(pos, fn, outer) - r.setType(cv, outer.Type()) + ir.NewClosureVar(r.pos(), fn, r.useLocal()) } r.addBody(fn) @@ -2204,17 +2200,10 @@ func (r *reader) methodValueWrapper(tbase *types.Type, method *types.Field, targ pos := base.AutogeneratedPos fn := r.newWrapperFunc(pos, sym, nil, method) - fn.SetNeedctxt(true) sym.Def = fn // Declare and initialize variable holding receiver. - recv := ir.NewNameAt(pos, typecheck.Lookup(".this")) - recv.Class = ir.PAUTOHEAP - recv.SetType(recvType) - recv.Curfn = fn - recv.SetIsClosureVar(true) - recv.SetByval(true) - fn.ClosureVars = append(fn.ClosureVars, recv) + recv := ir.NewHiddenParam(pos, fn, typecheck.Lookup(".this"), recvType) addTailCall(pos, fn, recv, method) diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 7b61260e79..a45bbfd1f8 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1289,13 +1289,8 @@ func (r *importReader) node() ir.Node { cvars := make([]*ir.Name, r.int64()) for i := range cvars { cvars[i] = ir.CaptureName(r.pos(), fn, r.localName().Canonical()) - if go117ExportTypes { - if cvars[i].Type() != nil || cvars[i].Defn == nil { - base.Fatalf("bad import of closure variable") - } - // Closure variable should have Defn set, which is its captured - // variable, and it gets the same type as the captured variable. - cvars[i].SetType(cvars[i].Defn.Type()) + if go117ExportTypes && cvars[i].Defn == nil { + base.Fatalf("bad import of closure variable") } } fn.ClosureVars = cvars diff --git a/src/cmd/compile/internal/walk/closure.go b/src/cmd/compile/internal/walk/closure.go index a86ed2ab80..7f6ef473bf 100644 --- a/src/cmd/compile/internal/walk/closure.go +++ b/src/cmd/compile/internal/walk/closure.go @@ -238,17 +238,10 @@ func methodValueWrapper(dot *ir.SelectorExpr) *ir.Func { fn := typecheck.DeclFunc(sym, tfn) fn.SetDupok(true) - fn.SetNeedctxt(true) fn.SetWrapper(true) // Declare and initialize variable holding receiver. - ptr := ir.NewNameAt(base.Pos, typecheck.Lookup(".this")) - ptr.Class = ir.PAUTOHEAP - ptr.SetType(rcvrtype) - ptr.Curfn = fn - ptr.SetIsClosureVar(true) - ptr.SetByval(true) - fn.ClosureVars = append(fn.ClosureVars, ptr) + ptr := ir.NewHiddenParam(base.Pos, fn, typecheck.Lookup(".this"), rcvrtype) call := ir.NewCallExpr(base.Pos, ir.OCALL, ir.NewSelectorExpr(base.Pos, ir.OXDOT, ptr, meth), nil) call.Args = ir.ParamNames(tfn.Type()) -- GitLab From ad2ba3ff518b9762e3f5497f0a8ce67c0e155aa8 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Sat, 3 Jul 2021 05:50:05 -0700 Subject: [PATCH 0405/2500] [dev.typeparams] src,cmd: run 'go mod tidy' Run 'go mod tidy' to satisfy the longtest builders. Change-Id: I5b31b63d0f273fca0833e44b826edfd726a1a958 Reviewed-on: https://go-review.googlesource.com/c/go/+/332669 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/go.sum | 23 ----------------------- src/go.sum | 7 ------- 2 files changed, 30 deletions(-) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index d728acaec9..7f0d978ef0 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -5,41 +5,18 @@ github.com/google/pprof v0.0.0-20210506205249-923b5ab0fc1a h1:jmAp/2PZAScNd62lTD github.com/google/pprof v0.0.0-20210506205249-923b5ab0fc1a/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 h1:mV02weKRL81bEnm8A0HT1/CAelMQDBuQIfLw8n+d6xI= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= golang.org/x/arch v0.0.0-20210502124803-cbf565b21d1e h1:pv3V0NlNSh5Q6AX/StwGLBjcLS7UN4m4Gq+V+uSecqM= golang.org/x/arch v0.0.0-20210502124803-cbf565b21d1e/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e h1:8foAy0aoO5GkqCvAEJ4VC4P3zksTg4X4aJCDpZzmgQI= golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.3-0.20210608190319-0f08993efd8a h1:e8qnjKz4EE6OjRki9wTadWSIogINvq10sMcuBRORxMY= golang.org/x/mod v0.4.3-0.20210608190319-0f08993efd8a/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 h1:yhBbb4IRs2HS9PPlAg6DMC6mUOKexJBNsLf4Z+6En1Q= golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210503060354-a79de5458b56 h1:b8jxX3zqjpqb2LklXPzKSGJhzyxCOZSz8ncv8Nv+y7w= golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.2-0.20210519160823-49064d2332f9 h1:2XlR/j4I4xz5GQZI7zBjqTfezYyRIE2jD5IMousB2rg= golang.org/x/tools v0.1.2-0.20210519160823-49064d2332f9/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/src/go.sum b/src/go.sum index 6e869b96f7..b3de6c526c 100644 --- a/src/go.sum +++ b/src/go.sum @@ -1,15 +1,8 @@ golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e h1:8foAy0aoO5GkqCvAEJ4VC4P3zksTg4X4aJCDpZzmgQI= golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I= golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 h1:yhBbb4IRs2HS9PPlAg6DMC6mUOKexJBNsLf4Z+6En1Q= golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7-0.20210503195748-5c7c50ebbd4f h1:yQJrRE0hDxDFmZLlRaw+3vusO4fwNHgHIjUOMO7bHYI= golang.org/x/text v0.3.7-0.20210503195748-5c7c50ebbd4f/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -- GitLab From c45d0eaadb77f11061cf9b18f521eb0b27e6bedb Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Sat, 3 Jul 2021 04:53:25 -0700 Subject: [PATCH 0406/2500] [dev.typeparams] cmd/compile: flatten OINLCALL in walk Inlining replaces inlined calls with OINLCALL nodes, and then somewhat clumsily tries to rewrite these in place without messing up order-of-evaluation rules. But handling these rules cleanly is much easier to do during order, and escape analysis is the only major pass between inlining and order. It's simpler to teach escape analysis how to analyze OINLCALL nodes than to try to hide them from escape analysis. Does not pass toolstash -cmp, but seems to just be line number changes. Change-Id: I1986cea39793e3e1ed5e887ba29d46364c6c532e Reviewed-on: https://go-review.googlesource.com/c/go/+/332649 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le Trust: Matthew Dempsky --- src/cmd/compile/internal/escape/call.go | 11 ++ src/cmd/compile/internal/escape/expr.go | 2 +- src/cmd/compile/internal/escape/stmt.go | 2 +- src/cmd/compile/internal/inline/inl.go | 110 +++++------------- src/cmd/compile/internal/ir/expr.go | 14 ++- src/cmd/compile/internal/ir/fmt.go | 9 ++ .../compile/internal/logopt/logopt_test.go | 2 +- src/cmd/compile/internal/noder/reader.go | 18 +-- src/cmd/compile/internal/typecheck/dcl.go | 1 + src/cmd/compile/internal/walk/order.go | 33 +++++- 10 files changed, 102 insertions(+), 100 deletions(-) diff --git a/src/cmd/compile/internal/escape/call.go b/src/cmd/compile/internal/escape/call.go index 5bd748027e..6fcfb1b3b4 100644 --- a/src/cmd/compile/internal/escape/call.go +++ b/src/cmd/compile/internal/escape/call.go @@ -110,6 +110,17 @@ func (e *escape) callCommon(ks []hole, call ir.Node, init *ir.Nodes, wrapper *ir argumentFunc(fn, e.tagHole(ks, fn, param), &args[i]) } + case ir.OINLCALL: + call := call.(*ir.InlinedCallExpr) + e.stmts(call.Body) + for i, result := range call.ReturnVars { + k := e.discardHole() + if ks != nil { + k = ks[i] + } + e.expr(k, result) + } + case ir.OAPPEND: call := call.(*ir.CallExpr) args := call.Args diff --git a/src/cmd/compile/internal/escape/expr.go b/src/cmd/compile/internal/escape/expr.go index c2a679d474..60b44fe0aa 100644 --- a/src/cmd/compile/internal/escape/expr.go +++ b/src/cmd/compile/internal/escape/expr.go @@ -130,7 +130,7 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) { n := n.(*ir.UnaryExpr) e.discard(n.X) - case ir.OCALLMETH, ir.OCALLFUNC, ir.OCALLINTER, ir.OLEN, ir.OCAP, ir.OCOMPLEX, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.OCOPY, ir.ORECOVER, ir.OUNSAFEADD, ir.OUNSAFESLICE: + case ir.OCALLMETH, ir.OCALLFUNC, ir.OCALLINTER, ir.OINLCALL, ir.OLEN, ir.OCAP, ir.OCOMPLEX, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.OCOPY, ir.ORECOVER, ir.OUNSAFEADD, ir.OUNSAFESLICE: e.call([]hole{k}, n) case ir.ONEW: diff --git a/src/cmd/compile/internal/escape/stmt.go b/src/cmd/compile/internal/escape/stmt.go index 0bdb07b278..c71848b8a1 100644 --- a/src/cmd/compile/internal/escape/stmt.go +++ b/src/cmd/compile/internal/escape/stmt.go @@ -173,7 +173,7 @@ func (e *escape) stmt(n ir.Node) { dsts[i] = res.Nname.(*ir.Name) } e.assignList(dsts, n.Results, "return", n) - case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER, ir.OCLOSE, ir.OCOPY, ir.ODELETE, ir.OPANIC, ir.OPRINT, ir.OPRINTN, ir.ORECOVER: + case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER, ir.OINLCALL, ir.OCLOSE, ir.OCOPY, ir.ODELETE, ir.OPANIC, ir.OPRINT, ir.OPRINTN, ir.ORECOVER: e.call(nil, n) case ir.OGO, ir.ODEFER: n := n.(*ir.GoDeferStmt) diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index a6961e4e4d..f1e927d643 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -515,37 +515,6 @@ func InlineCalls(fn *ir.Func) { ir.CurFunc = savefn } -// Turn an OINLCALL into a statement. -func inlconv2stmt(inlcall *ir.InlinedCallExpr) ir.Node { - n := ir.NewBlockStmt(inlcall.Pos(), nil) - n.List = inlcall.Init() - n.List.Append(inlcall.Body.Take()...) - return n -} - -// Turn an OINLCALL into a single valued expression. -// The result of inlconv2expr MUST be assigned back to n, e.g. -// n.Left = inlconv2expr(n.Left) -func inlconv2expr(n *ir.InlinedCallExpr) ir.Node { - r := n.ReturnVars[0] - return ir.InitExpr(append(n.Init(), n.Body...), r) -} - -// Turn the rlist (with the return values) of the OINLCALL in -// n into an expression list lumping the ninit and body -// containing the inlined statements on the first list element so -// order will be preserved. Used in return, oas2func and call -// statements. -func inlconv2list(n *ir.InlinedCallExpr) []ir.Node { - if n.Op() != ir.OINLCALL || len(n.ReturnVars) == 0 { - base.Fatalf("inlconv2list %+v\n", n) - } - - s := n.ReturnVars - s[0] = ir.InitExpr(append(n.Init(), n.Body...), s[0]) - return s -} - // inlnode recurses over the tree to find inlineable calls, which will // be turned into OINLCALLs by mkinlcall. When the recursion comes // back up will examine left, right, list, rlist, ninit, ntest, nincr, @@ -599,33 +568,18 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool, edit func(ir.No ir.EditChildren(n, edit) - if as := n; as.Op() == ir.OAS2FUNC { - as := as.(*ir.AssignListStmt) - if as.Rhs[0].Op() == ir.OINLCALL { - as.Rhs = inlconv2list(as.Rhs[0].(*ir.InlinedCallExpr)) - as.SetOp(ir.OAS2) - as.SetTypecheck(0) - n = typecheck.Stmt(as) - } - } - // with all the branches out of the way, it is now time to // transmogrify this node itself unless inhibited by the // switch at the top of this function. switch n.Op() { case ir.OCALLMETH: base.FatalfAt(n.Pos(), "OCALLMETH missed by typecheck") - case ir.OCALLFUNC: - n := n.(*ir.CallExpr) - if n.NoInline { - return n - } - } - var call *ir.CallExpr - switch n.Op() { case ir.OCALLFUNC: - call = n.(*ir.CallExpr) + call := n.(*ir.CallExpr) + if call.NoInline { + break + } if base.Flag.LowerM > 3 { fmt.Printf("%v:call to func %+v\n", ir.Line(n), call.X) } @@ -635,27 +589,10 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool, edit func(ir.No if fn := inlCallee(call.X); fn != nil && fn.Inl != nil { n = mkinlcall(call, fn, maxCost, inlMap, edit) } - case ir.OCALLMETH: - base.FatalfAt(n.Pos(), "OCALLMETH missed by typecheck") } base.Pos = lno - if n.Op() == ir.OINLCALL { - ic := n.(*ir.InlinedCallExpr) - switch call.Use { - default: - ir.Dump("call", call) - base.Fatalf("call missing use") - case ir.CallUseExpr: - n = inlconv2expr(ic) - case ir.CallUseStmt: - n = inlconv2stmt(ic) - case ir.CallUseList: - // leave for caller to convert - } - } - return n } @@ -811,6 +748,30 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b return res } +// CalleeEffects appends any side effects from evaluating callee to init. +func CalleeEffects(init *ir.Nodes, callee ir.Node) { + for { + switch callee.Op() { + case ir.ONAME, ir.OCLOSURE, ir.OMETHEXPR: + return // done + + case ir.OCONVNOP: + conv := callee.(*ir.ConvExpr) + init.Append(ir.TakeInit(conv)...) + callee = conv.X + + case ir.OINLCALL: + ic := callee.(*ir.InlinedCallExpr) + init.Append(ir.TakeInit(ic)...) + init.Append(ic.Body.Take()...) + callee = ic.SingleResult() + + default: + base.FatalfAt(callee.Pos(), "unexpected callee expression: %v", callee) + } + } +} + // oldInline creates an InlinedCallExpr to replace the given call // expression. fn is the callee function to be inlined. inlIndex is // the inlining tree position index, for use with src.NewInliningBase @@ -825,19 +786,10 @@ func oldInline(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExpr ninit := call.Init() // For normal function calls, the function callee expression - // may contain side effects (e.g., added by addinit during - // inlconv2expr or inlconv2list). Make sure to preserve these, + // may contain side effects. Make sure to preserve these, // if necessary (#42703). if call.Op() == ir.OCALLFUNC { - callee := call.X - for callee.Op() == ir.OCONVNOP { - conv := callee.(*ir.ConvExpr) - ninit.Append(ir.TakeInit(conv)...) - callee = conv.X - } - if callee.Op() != ir.ONAME && callee.Op() != ir.OCLOSURE && callee.Op() != ir.OMETHEXPR { - base.Fatalf("unexpected callee expression: %v", callee) - } + CalleeEffects(&ninit, call.X) } // Make temp names to use instead of the originals. @@ -979,6 +931,7 @@ func inlvar(var_ *ir.Name) *ir.Name { n := typecheck.NewName(var_.Sym()) n.SetType(var_.Type()) + n.SetTypecheck(1) n.Class = ir.PAUTO n.SetUsed(true) n.SetAutoTemp(var_.AutoTemp()) @@ -993,6 +946,7 @@ func inlvar(var_ *ir.Name) *ir.Name { func retvar(t *types.Field, i int) *ir.Name { n := typecheck.NewName(typecheck.LookupNum("~R", i)) n.SetType(t.Type) + n.SetTypecheck(1) n.Class = ir.PAUTO n.SetUsed(true) n.Curfn = ir.CurFunc // the calling function, not the called one diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 919cb3362f..4ff75e616d 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -345,7 +345,7 @@ func (n *StructKeyExpr) Sym() *types.Sym { return n.Field.Sym } type InlinedCallExpr struct { miniExpr Body Nodes - ReturnVars Nodes + ReturnVars Nodes // must be side-effect free } func NewInlinedCallExpr(pos src.XPos, body, retvars []Node) *InlinedCallExpr { @@ -357,6 +357,13 @@ func NewInlinedCallExpr(pos src.XPos, body, retvars []Node) *InlinedCallExpr { return n } +func (n *InlinedCallExpr) SingleResult() Node { + if have := len(n.ReturnVars); have != 1 { + base.FatalfAt(n.Pos(), "inlined call has %v results, expected 1", have) + } + return n.ReturnVars[0] +} + // A LogicalExpr is a expression X Op Y where Op is && or ||. // It is separate from BinaryExpr to make room for statements // that must be executed before Y but after X. @@ -800,6 +807,11 @@ func StaticValue(n Node) Node { continue } + if n.Op() == OINLCALL { + n = n.(*InlinedCallExpr).SingleResult() + continue + } + n1 := staticValue1(n) if n1 == nil { return n diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index ae62d5f51b..6f6e26dec4 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -859,6 +859,15 @@ func exprFmt(n Node, s fmt.State, prec int) { } fmt.Fprintf(s, "(%.v)", n.Args) + case OINLCALL: + n := n.(*InlinedCallExpr) + // TODO(mdempsky): Print Init and/or Body? + if len(n.ReturnVars) == 1 { + fmt.Fprintf(s, "%v", n.ReturnVars[0]) + return + } + fmt.Fprintf(s, "(.%v)", n.ReturnVars) + case OMAKEMAP, OMAKECHAN, OMAKESLICE: n := n.(*MakeExpr) if n.Cap != nil { diff --git a/src/cmd/compile/internal/logopt/logopt_test.go b/src/cmd/compile/internal/logopt/logopt_test.go index 41a11b0c70..902cbc8091 100644 --- a/src/cmd/compile/internal/logopt/logopt_test.go +++ b/src/cmd/compile/internal/logopt/logopt_test.go @@ -221,7 +221,7 @@ func s15a8(x *[15]int64) [15]int64 { `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":4,"character":9},"end":{"line":4,"character":9}}},"message":"inlineLoc"},`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from ~R0 = \u0026y.b (assign-pair)"},`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":3},"end":{"line":9,"character":3}}},"message":"escflow: flow: ~r0 = ~R0:"},`+ - `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":3},"end":{"line":9,"character":3}}},"message":"escflow: from return (*int)(~R0) (return)"}]}`) + `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":3},"end":{"line":9,"character":3}}},"message":"escflow: from return ~R0 (return)"}]}`) }) } diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 14d982a1af..d938dca5d4 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -15,6 +15,7 @@ import ( "cmd/compile/internal/base" "cmd/compile/internal/deadcode" "cmd/compile/internal/dwarfgen" + "cmd/compile/internal/inline" "cmd/compile/internal/ir" "cmd/compile/internal/reflectdata" "cmd/compile/internal/typecheck" @@ -1848,23 +1849,10 @@ func InlineCall(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExp init := ir.TakeInit(call) // For normal function calls, the function callee expression - // may contain side effects (e.g., added by addinit during - // inlconv2expr or inlconv2list). Make sure to preserve these, + // may contain side effects. Make sure to preserve these, // if necessary (#42703). if call.Op() == ir.OCALLFUNC { - callee := call.X - for callee.Op() == ir.OCONVNOP { - conv := callee.(*ir.ConvExpr) - init.Append(ir.TakeInit(conv)...) - callee = conv.X - } - - switch callee.Op() { - case ir.ONAME, ir.OCLOSURE, ir.OMETHEXPR: - // ok - default: - base.Fatalf("unexpected callee expression: %v", callee) - } + inline.CalleeEffects(&init, call.X) } var args ir.Nodes diff --git a/src/cmd/compile/internal/typecheck/dcl.go b/src/cmd/compile/internal/typecheck/dcl.go index 66d755089a..90d3020fe0 100644 --- a/src/cmd/compile/internal/typecheck/dcl.go +++ b/src/cmd/compile/internal/typecheck/dcl.go @@ -418,6 +418,7 @@ func TempAt(pos src.XPos, curfn *ir.Func, t *types.Type) *ir.Name { n := ir.NewNameAt(pos, s) s.Def = n n.SetType(t) + n.SetTypecheck(1) n.Class = ir.PAUTO n.SetEsc(ir.EscNever) n.Curfn = curfn diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go index 007af03d4b..eec340261e 100644 --- a/src/cmd/compile/internal/walk/order.go +++ b/src/cmd/compile/internal/walk/order.go @@ -655,9 +655,20 @@ func (o *orderState) stmt(n ir.Node) { n := n.(*ir.AssignListStmt) t := o.markTemp() o.exprList(n.Lhs) - o.init(n.Rhs[0]) - o.call(n.Rhs[0]) - o.as2func(n) + call := n.Rhs[0] + o.init(call) + if ic, ok := call.(*ir.InlinedCallExpr); ok { + o.stmtList(ic.Body) + + n.SetOp(ir.OAS2) + n.Rhs = ic.ReturnVars + + o.exprList(n.Rhs) + o.out = append(o.out, n) + } else { + o.call(call) + o.as2func(n) + } o.cleanTemp(t) // Special: use temporary variables to hold result, @@ -717,6 +728,17 @@ func (o *orderState) stmt(n ir.Node) { o.out = append(o.out, n) o.cleanTemp(t) + case ir.OINLCALL: + n := n.(*ir.InlinedCallExpr) + o.stmtList(n.Body) + + // discard results; double-check for no side effects + for _, result := range n.ReturnVars { + if staticinit.AnySideEffects(result) { + base.FatalfAt(result.Pos(), "inlined call result has side effects: %v", result) + } + } + case ir.OCHECKNIL, ir.OCLOSE, ir.OPANIC, ir.ORECV: n := n.(*ir.UnaryExpr) t := o.markTemp() @@ -1241,6 +1263,11 @@ func (o *orderState) expr1(n, lhs ir.Node) ir.Node { } return n + case ir.OINLCALL: + n := n.(*ir.InlinedCallExpr) + o.stmtList(n.Body) + return n.SingleResult() + case ir.OAPPEND: // Check for append(x, make([]T, y)...) . n := n.(*ir.CallExpr) -- GitLab From ea5369bac041e7a78e198f4412350cfd923215aa Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Sat, 3 Jul 2021 05:27:54 -0700 Subject: [PATCH 0407/2500] [dev.typeparams] cmd/compile: remove ir.CallUse Unneeded after the previous CL changed inlining to leave OINLCALL nodes in place. Change-Id: I9af09a86a21caa51a1117b3de17d7312dd702600 Reviewed-on: https://go-review.googlesource.com/c/go/+/332650 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le Trust: Matthew Dempsky --- src/cmd/compile/internal/ir/expr.go | 12 ------------ src/cmd/compile/internal/noder/helpers.go | 3 --- src/cmd/compile/internal/noder/stmt.go | 6 +----- src/cmd/compile/internal/noder/transform.go | 1 - src/cmd/compile/internal/typecheck/func.go | 4 ---- src/cmd/compile/internal/typecheck/iexport.go | 1 - src/cmd/compile/internal/typecheck/iimport.go | 1 - src/cmd/compile/internal/typecheck/stmt.go | 1 - 8 files changed, 1 insertion(+), 28 deletions(-) diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 4ff75e616d..9c800dcd1a 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -142,17 +142,6 @@ func (n *BinaryExpr) SetOp(op Op) { } } -// A CallUse records how the result of the call is used: -type CallUse byte - -const ( - _ CallUse = iota - - CallUseExpr // single expression result is used - CallUseList // list of results are used - CallUseStmt // results not used - call is a statement -) - // A CallExpr is a function call X(Args). type CallExpr struct { miniExpr @@ -161,7 +150,6 @@ type CallExpr struct { Args Nodes KeepAlive []*Name // vars to be kept alive until call returns IsDDD bool - Use CallUse NoInline bool } diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index 6ab318318b..08affe4411 100644 --- a/src/cmd/compile/internal/noder/helpers.go +++ b/src/cmd/compile/internal/noder/helpers.go @@ -113,9 +113,6 @@ func Binary(pos src.XPos, op ir.Op, typ *types.Type, x, y ir.Node) ir.Node { func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) ir.Node { n := ir.NewCallExpr(pos, ir.OCALL, fun, args) n.IsDDD = dots - // n.Use will be changed to ir.CallUseStmt in g.stmt() if this call is - // just a statement (any return values are ignored). - n.Use = ir.CallUseExpr if fun.Op() == ir.OTYPE { // Actually a type conversion, not a function call. diff --git a/src/cmd/compile/internal/noder/stmt.go b/src/cmd/compile/internal/noder/stmt.go index 32a1483b4a..672a732187 100644 --- a/src/cmd/compile/internal/noder/stmt.go +++ b/src/cmd/compile/internal/noder/stmt.go @@ -35,11 +35,7 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { case *syntax.BlockStmt: return ir.NewBlockStmt(g.pos(stmt), g.blockStmt(stmt)) case *syntax.ExprStmt: - x := g.expr(stmt.X) - if call, ok := x.(*ir.CallExpr); ok { - call.Use = ir.CallUseStmt - } - return x + return g.expr(stmt.X) case *syntax.SendStmt: n := ir.NewSendStmt(g.pos(stmt), g.expr(stmt.Chan), g.expr(stmt.Value)) if n.Chan.Type().HasTParam() || n.Value.Type().HasTParam() { diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index 7a685c4b47..e02b7e758d 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -326,7 +326,6 @@ assignOK: stmt := stmt.(*ir.AssignListStmt) stmt.SetOp(ir.OAS2FUNC) r := rhs[0].(*ir.CallExpr) - r.Use = ir.CallUseList rtyp := r.Type() mismatched := false diff --git a/src/cmd/compile/internal/typecheck/func.go b/src/cmd/compile/internal/typecheck/func.go index d0aad5ac07..68f0c20e52 100644 --- a/src/cmd/compile/internal/typecheck/func.go +++ b/src/cmd/compile/internal/typecheck/func.go @@ -317,10 +317,6 @@ func tcFunc(n *ir.Func) { // tcCall typechecks an OCALL node. func tcCall(n *ir.CallExpr, top int) ir.Node { - n.Use = ir.CallUseExpr - if top == ctxStmt { - n.Use = ir.CallUseStmt - } Stmts(n.Init()) // imported rewritten f(g()) calls (#30907) n.X = typecheck(n.X, ctxExpr|ctxType|ctxCallee) if n.X.Diag() { diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index b17af815ec..82bbda5228 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -1922,7 +1922,6 @@ func (w *exportWriter) expr(n ir.Node) { w.bool(n.IsDDD) if go117ExportTypes { w.exoticType(n.Type()) - w.uint64(uint64(n.Use)) } case ir.OMAKEMAP, ir.OMAKECHAN, ir.OMAKESLICE: diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index a45bbfd1f8..17e60effd6 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1465,7 +1465,6 @@ func (r *importReader) node() ir.Node { n.IsDDD = r.bool() if go117ExportTypes { n.SetType(r.exoticType()) - n.Use = ir.CallUse(r.uint64()) } return n diff --git a/src/cmd/compile/internal/typecheck/stmt.go b/src/cmd/compile/internal/typecheck/stmt.go index f1275f29c0..0143411822 100644 --- a/src/cmd/compile/internal/typecheck/stmt.go +++ b/src/cmd/compile/internal/typecheck/stmt.go @@ -201,7 +201,6 @@ assignOK: stmt := stmt.(*ir.AssignListStmt) stmt.SetOp(ir.OAS2FUNC) r := rhs[0].(*ir.CallExpr) - r.Use = ir.CallUseList rtyp := r.Type() mismatched := false -- GitLab From 899b158ee9e99642bdbea2008d7cc70382db6545 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Sat, 3 Jul 2021 11:22:26 -0700 Subject: [PATCH 0408/2500] [dev.typeparams] cmd/compile: set Func.ClosureCalled in escape analysis The Func.ClosureCalled flag is an optimization used by escape analysis to detect closures that were directly called, so we know we have visibility of the result flows. It's not needed by any other phases of the compiler, so we might as well calculate it within escape analysis too. This saves some trouble during IR construction and trying to maintain the ClosureCalled flag through inlining and copying. Passes toolstash -cmp. Change-Id: Ic53cecb7ac439745c0dfba2cd202b9cc40f1e47c Reviewed-on: https://go-review.googlesource.com/c/go/+/332691 Run-TryBot: Matthew Dempsky Trust: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/escape/call.go | 7 +++++++ src/cmd/compile/internal/inline/inl.go | 9 +-------- src/cmd/compile/internal/ir/func.go | 2 +- src/cmd/compile/internal/noder/helpers.go | 2 -- src/cmd/compile/internal/noder/reader.go | 3 --- src/cmd/compile/internal/noder/stencil.go | 2 -- src/cmd/compile/internal/typecheck/func.go | 2 -- 7 files changed, 9 insertions(+), 18 deletions(-) diff --git a/src/cmd/compile/internal/escape/call.go b/src/cmd/compile/internal/escape/call.go index 6fcfb1b3b4..9e5abed591 100644 --- a/src/cmd/compile/internal/escape/call.go +++ b/src/cmd/compile/internal/escape/call.go @@ -57,6 +57,13 @@ func (e *escape) callCommon(ks []hole, call ir.Node, init *ir.Nodes, wrapper *ir var fn *ir.Name switch call.Op() { case ir.OCALLFUNC: + // If we have a direct call to a closure (not just one we were + // able to statically resolve with ir.StaticValue), mark it as + // such so batch.outlives can optimize the flow results. + if call.X.Op() == ir.OCLOSURE { + call.X.(*ir.ClosureExpr).Func.SetClosureCalled(true) + } + switch v := ir.StaticValue(call.X); v.Op() { case ir.ONAME: if v := v.(*ir.Name); v.Class == ir.PFUNC { diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index f1e927d643..45a533fcaf 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -470,9 +470,6 @@ func inlcopy(n ir.Node) ir.Node { // x.Func.Body for iexport and local inlining. oldfn := x.Func newfn := ir.NewFunc(oldfn.Pos()) - if oldfn.ClosureCalled() { - newfn.SetClosureCalled(true) - } m.(*ir.ClosureExpr).Func = newfn newfn.Nname = ir.NewNameAt(oldfn.Nname.Pos(), oldfn.Nname.Sym()) // XXX OK to share fn.Type() ?? @@ -1154,11 +1151,7 @@ func (subst *inlsubst) closure(n *ir.ClosureExpr) ir.Node { // the closure is inlined in a specific function. newclo := newfn.OClosure newclo.SetInit(subst.list(n.Init())) - if oldfn.ClosureCalled() { - return typecheck.Callee(newclo) - } else { - return typecheck.Expr(newclo) - } + return typecheck.Expr(newclo) } // node recursively copies a node from the saved pristine body of the diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go index 3b9e36d4c5..269b6f14ec 100644 --- a/src/cmd/compile/internal/ir/func.go +++ b/src/cmd/compile/internal/ir/func.go @@ -202,7 +202,7 @@ const ( funcExportInline // include inline body in export data funcInstrumentBody // add race/msan instrumentation during SSA construction funcOpenCodedDeferDisallowed // can't do open-coded defers - funcClosureCalled // closure is only immediately called + funcClosureCalled // closure is only immediately called; used by escape analysis ) type SymAndPos struct { diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index 08affe4411..b0fb913ee8 100644 --- a/src/cmd/compile/internal/noder/helpers.go +++ b/src/cmd/compile/internal/noder/helpers.go @@ -160,8 +160,6 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) // Add information, now that we know that fun is actually being called. switch fun := fun.(type) { - case *ir.ClosureExpr: - fun.Func.SetClosureCalled(true) case *ir.SelectorExpr: if fun.Op() == ir.OMETHVALUE { op := ir.ODOTMETH diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index d938dca5d4..05cfc614a2 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -1523,9 +1523,6 @@ func (r *reader) expr() ir.Node { case exprCall: fun := r.expr() - if clo, ok := fun.(*ir.ClosureExpr); ok { - clo.Func.SetClosureCalled(true) - } pos := r.pos() args := r.exprs() dots := r.bool() diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index d35e036ae6..dbaebf7623 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1193,8 +1193,6 @@ func (subst *subster) node(n ir.Node) ir.Node { newfn := ir.NewClosureFunc(oldfn.Pos(), subst.newf != nil) ir.NameClosure(newfn.OClosure, subst.newf) - newfn.SetClosureCalled(oldfn.ClosureCalled()) - saveNewf := subst.newf ir.CurFunc = newfn subst.newf = newfn diff --git a/src/cmd/compile/internal/typecheck/func.go b/src/cmd/compile/internal/typecheck/func.go index 68f0c20e52..847e9b9aea 100644 --- a/src/cmd/compile/internal/typecheck/func.go +++ b/src/cmd/compile/internal/typecheck/func.go @@ -242,8 +242,6 @@ func tcClosure(clo *ir.ClosureExpr, top int) ir.Node { fn.Iota = x } - fn.SetClosureCalled(top&ctxCallee != 0) - ir.NameClosure(clo, ir.CurFunc) Func(fn) -- GitLab From cd00499c6125692d704ac8a04b07825ee1648207 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Sat, 3 Jul 2021 11:55:31 -0700 Subject: [PATCH 0409/2500] [dev.typeparams] cmd/compile: better Call constructor Historically, it's been tedious to create and typecheck ir.OCALL nodes, except by handing them off entirely to typecheck. This is because typecheck needed context on whether the call is an expression or statement, and to set flags like Func.ClosureCalled and CallExpr.Use. However, those flags have now been removed entirely by recent CLs, so we can instead just provide a better typecheck.Call function for constructing and typechecking arbitrary call nodes. Notably, this simplifies things for unified IR, which can now incrementally typecheck call expressions as it goes without worrying about context. Change-Id: Icbdc55c3bd8be84a242323bc45006f9dec09fdcd Reviewed-on: https://go-review.googlesource.com/c/go/+/332692 Run-TryBot: Matthew Dempsky Trust: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/noder/reader.go | 8 +++----- src/cmd/compile/internal/reflectdata/alg.go | 6 ++---- src/cmd/compile/internal/typecheck/typecheck.go | 17 +++++------------ src/cmd/compile/internal/walk/walk.go | 3 +-- 4 files changed, 11 insertions(+), 23 deletions(-) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 05cfc614a2..122bc70f24 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -1526,9 +1526,7 @@ func (r *reader) expr() ir.Node { pos := r.pos() args := r.exprs() dots := r.bool() - n := ir.NewCallExpr(pos, ir.OCALL, fun, args) - n.IsDDD = dots - return n + return typecheck.Call(pos, fun, args, dots) case exprTypeSwitchGuard: pos := r.pos() @@ -2281,8 +2279,8 @@ func addTailCall(pos src.XPos, fn *ir.Func, recv ir.Node, method *types.Field) { fn.SetWrapper(true) // TODO(mdempsky): Leave unset for tail calls? - call := ir.NewCallExpr(pos, ir.OCALL, ir.NewSelectorExpr(pos, ir.OXDOT, recv, method.Sym), args) - call.IsDDD = method.Type.IsVariadic() + dot := ir.NewSelectorExpr(pos, ir.OXDOT, recv, method.Sym) + call := typecheck.Call(pos, dot, args, method.Type.IsVariadic()).(*ir.CallExpr) if method.Type.NumResults() == 0 { fn.Body.Append(call) diff --git a/src/cmd/compile/internal/reflectdata/alg.go b/src/cmd/compile/internal/reflectdata/alg.go index 0707e0b61c..36ad389647 100644 --- a/src/cmd/compile/internal/reflectdata/alg.go +++ b/src/cmd/compile/internal/reflectdata/alg.go @@ -679,8 +679,7 @@ func EqString(s, t ir.Node) (eqlen *ir.BinaryExpr, eqmem *ir.CallExpr) { fn := typecheck.LookupRuntime("memequal") fn = typecheck.SubstArgTypes(fn, types.Types[types.TUINT8], types.Types[types.TUINT8]) - call := ir.NewCallExpr(base.Pos, ir.OCALL, fn, []ir.Node{sptr, tptr, ir.Copy(slen)}) - typecheck.Call(call) + call := typecheck.Call(base.Pos, fn, []ir.Node{sptr, tptr, ir.Copy(slen)}, false).(*ir.CallExpr) cmp := ir.NewBinaryExpr(base.Pos, ir.OEQ, slen, tlen) cmp = typecheck.Expr(cmp).(*ir.BinaryExpr) @@ -716,8 +715,7 @@ func EqInterface(s, t ir.Node) (eqtab *ir.BinaryExpr, eqdata *ir.CallExpr) { sdata.SetTypecheck(1) tdata.SetTypecheck(1) - call := ir.NewCallExpr(base.Pos, ir.OCALL, fn, []ir.Node{stab, sdata, tdata}) - typecheck.Call(call) + call := typecheck.Call(base.Pos, fn, []ir.Node{stab, sdata, tdata}, false).(*ir.CallExpr) cmp := ir.NewBinaryExpr(base.Pos, ir.OEQ, stab, ttab) cmp = typecheck.Expr(cmp).(*ir.BinaryExpr) diff --git a/src/cmd/compile/internal/typecheck/typecheck.go b/src/cmd/compile/internal/typecheck/typecheck.go index 21d3100f66..8f3d6cf4bb 100644 --- a/src/cmd/compile/internal/typecheck/typecheck.go +++ b/src/cmd/compile/internal/typecheck/typecheck.go @@ -13,6 +13,7 @@ import ( "cmd/compile/internal/base" "cmd/compile/internal/ir" "cmd/compile/internal/types" + "cmd/internal/src" ) // Function collecting autotmps generated during typechecking, @@ -34,18 +35,10 @@ func Stmt(n ir.Node) ir.Node { return typecheck(n, ctxStmt) } func Exprs(exprs []ir.Node) { typecheckslice(exprs, ctxExpr) } func Stmts(stmts []ir.Node) { typecheckslice(stmts, ctxStmt) } -func Call(call *ir.CallExpr) { - t := call.X.Type() - if t == nil { - panic("misuse of Call") - } - ctx := ctxStmt - if t.NumResults() > 0 { - ctx = ctxExpr | ctxMultiOK - } - if typecheck(call, ctx) != call { - panic("bad typecheck") - } +func Call(pos src.XPos, callee ir.Node, args []ir.Node, dots bool) ir.Node { + call := ir.NewCallExpr(pos, ir.OCALL, callee, args) + call.IsDDD = dots + return typecheck(call, ctxStmt|ctxExpr) } func Callee(n ir.Node) ir.Node { diff --git a/src/cmd/compile/internal/walk/walk.go b/src/cmd/compile/internal/walk/walk.go index f687127fee..6551fe7a64 100644 --- a/src/cmd/compile/internal/walk/walk.go +++ b/src/cmd/compile/internal/walk/walk.go @@ -113,8 +113,7 @@ func vmkcall(fn ir.Node, t *types.Type, init *ir.Nodes, va []ir.Node) *ir.CallEx base.Fatalf("vmkcall %v needs %v args got %v", fn, n, len(va)) } - call := ir.NewCallExpr(base.Pos, ir.OCALL, fn, va) - typecheck.Call(call) + call := typecheck.Call(base.Pos, fn, va, false).(*ir.CallExpr) call.SetType(t) return walkExpr(call, init).(*ir.CallExpr) } -- GitLab From 49ade6b298c269e6d405d43a2e42dec218e97660 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 2 Jul 2021 13:18:03 -0700 Subject: [PATCH 0410/2500] [dev.typeparams] test: add expected failure mechanism This CL changes the existing excluded-test mechanism into a known-failure mechanism instead. That is, it runs the test regardless, but only reports if it failed (or succeeded) unexpectedly. It also splits the known failures list into fine-grain failure lists for types2, types2 w/ 32-bit target, -G=3, and unified. Updates #46704. Change-Id: I1213cbccf1bab6a92d9bfcf0d971a2554249bbff Reviewed-on: https://go-review.googlesource.com/c/go/+/332551 Trust: Matthew Dempsky Trust: Dan Scales Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Dan Scales Reviewed-by: Robert Griesemer --- test/run.go | 282 +++++++++++++++++++++++---------------- test/typeparam/nested.go | 2 +- 2 files changed, 168 insertions(+), 116 deletions(-) diff --git a/test/run.go b/test/run.go index d04f7d20ed..ff8bf4b229 100644 --- a/test/run.go +++ b/test/run.go @@ -42,7 +42,7 @@ var ( linkshared = flag.Bool("linkshared", false, "") updateErrors = flag.Bool("update_errors", false, "update error messages in test file based on compiler output") runoutputLimit = flag.Int("l", defaultRunOutputLimit(), "number of parallel runoutput tests to run") - force = flag.Bool("f", false, "run expected-failure generics tests rather than skipping them") + force = flag.Bool("f", false, "ignore expected-failure test lists") generics = flag.String("G", defaultGLevels, "a comma-separated list of -G compiler flags to test with") shard = flag.Int("shard", 0, "shard index to run. Only applicable if -shards is non-zero.") @@ -175,8 +175,15 @@ func main() { status = "FAIL" } if test.err != nil { - status = "FAIL" errStr = test.err.Error() + if test.expectFail { + errStr += " (expected)" + } else { + status = "FAIL" + } + } else if test.expectFail { + status = "FAIL" + errStr = "unexpected success" } if status == "FAIL" { failed = true @@ -321,11 +328,45 @@ type test struct { tempDir string err error + + // expectFail indicates whether the (overall) test recipe is + // expected to fail under the current test configuration (e.g., -G=3 + // or GOEXPERIMENT=unified). + expectFail bool } -// usesTypes2 reports whether the compiler uses types2 for this test -// configuration (irrespective of flags specified by the test itself). -func (t *test) usesTypes2() bool { return unifiedEnabled || t.glevel != 0 } +// initExpectFail initializes t.expectFail based on the build+test +// configuration. It should only be called for tests known to use +// types2. +func (t *test) initExpectFail() { + if *force { + return + } + + failureSets := []map[string]bool{types2Failures} + + // Note: gccgo supports more 32-bit architectures than this, but + // hopefully the 32-bit failures are fixed before this matters. + switch goarch { + case "386", "arm", "mips", "mipsle": + failureSets = append(failureSets, types2Failures32Bit) + } + + if unifiedEnabled { + failureSets = append(failureSets, unifiedFailures) + } else { + failureSets = append(failureSets, g3Failures) + } + + filename := strings.Replace(t.goFileName(), "\\", "/", -1) // goFileName() uses \ on Windows + + for _, set := range failureSets { + if set[filename] { + t.expectFail = true + return + } + } +} func startTests(dir, gofile string, glevels []int) []*test { tests := make([]*test, len(glevels)) @@ -556,17 +597,6 @@ func (t *test) run() { close(t.donec) }() - if t.usesTypes2() && !*force { - // Files excluded from types2 testing. - filename := strings.Replace(t.goFileName(), "\\", "/", -1) // goFileName() uses \ on Windows - if excludedFiles[filename] { - if *verbose { - fmt.Printf("excl\t%s\n", filename) - } - return - } - } - srcBytes, err := ioutil.ReadFile(t.goFileName()) if err != nil { t.err = err @@ -703,12 +733,6 @@ func (t *test) run() { // at the specified -G level. If so, it may update flags as // necessary to test with -G. validForGLevel := func(tool Tool) bool { - if !t.usesTypes2() { - // tests should always pass when run w/o types2 (i.e., using the - // legacy typechecker). - return true - } - hasGFlag := false for _, flag := range flags { if strings.Contains(flag, "-G") { @@ -724,6 +748,14 @@ func (t *test) run() { return false } + if t.glevel == 0 && !hasGFlag && !unifiedEnabled { + // tests should always pass when run w/o types2 (i.e., using the + // legacy typechecker). + return true + } + + t.initExpectFail() + switch tool { case Build, Run: // ok; handled in goGcflags @@ -2071,103 +2103,123 @@ func overlayDir(dstRoot, srcRoot string) error { // List of files that the compiler cannot errorcheck with the new typechecker (compiler -G option). // Temporary scaffolding until we pass all the tests at which point this map can be removed. -// -// TODO(mdempsky): Split exclude list to disambiguate whether the -// failure is within types2, -G=3, or unified. -var excludedFiles = map[string]bool{ - "directive.go": true, // misplaced compiler directive checks - "float_lit3.go": true, // types2 reports extra errors - "import1.go": true, // types2 reports extra errors - "import6.go": true, // issue #43109 - "initializerr.go": true, // types2 reports extra errors - "linkname2.go": true, // error reported by noder (not running for types2 errorcheck test) - "notinheap.go": true, // types2 doesn't report errors about conversions that are invalid due to //go:notinheap - "printbig.go": true, // large untyped int passed to print (32-bit) - "shift1.go": true, // issue #42989 - "typecheck.go": true, // invalid function is not causing errors when called - "writebarrier.go": true, // correct diagnostics, but different lines (probably irgen's fault) - - "interface/private.go": true, // types2 phrases errors differently (doesn't use non-spec "private" term) - - "fixedbugs/bug114.go": true, // large untyped int passed to println (32-bit) - "fixedbugs/bug176.go": true, // types2 reports all errors (pref: types2) - "fixedbugs/bug195.go": true, // types2 reports slightly different (but correct) bugs - "fixedbugs/bug228.go": true, // types2 doesn't run when there are syntax errors - "fixedbugs/bug231.go": true, // types2 bug? (same error reported twice) - "fixedbugs/bug255.go": true, // types2 reports extra errors - "fixedbugs/bug374.go": true, // types2 reports extra errors - "fixedbugs/bug385_32.go": true, // types2 doesn't produce missing error "type .* too large" (32-bit specific) - "fixedbugs/bug388.go": true, // types2 not run due to syntax errors - "fixedbugs/bug412.go": true, // types2 produces a follow-on error - - "fixedbugs/issue10700.go": true, // types2 reports ok hint, but does not match regexp - "fixedbugs/issue11590.go": true, // types2 doesn't report a follow-on error (pref: types2) - "fixedbugs/issue11610.go": true, // types2 not run after syntax errors - "fixedbugs/issue11614.go": true, // types2 reports an extra error - "fixedbugs/issue14520.go": true, // missing import path error by types2 - "fixedbugs/issue16133.go": true, // types2 doesn't use package path for qualified identifiers when package name is ambiguous - "fixedbugs/issue16428.go": true, // types2 reports two instead of one error - "fixedbugs/issue17038.go": true, // types2 doesn't report a follow-on error (pref: types2) - "fixedbugs/issue17270.go": true, // ICE in irgen - "fixedbugs/issue17645.go": true, // multiple errors on same line - "fixedbugs/issue18331.go": true, // missing error about misuse of //go:noescape (irgen needs code from noder) - "fixedbugs/issue18419.go": true, // types2 reports - "fixedbugs/issue19012.go": true, // multiple errors on same line - "fixedbugs/issue20174.go": true, // ICE due to width not calculated (probably irgen's fault) - "fixedbugs/issue20233.go": true, // types2 reports two instead of one error (pref: compiler) - "fixedbugs/issue20245.go": true, // types2 reports two instead of one error (pref: compiler) - "fixedbugs/issue20250.go": true, // correct diagnostics, but different lines (probably irgen's fault) - "fixedbugs/issue21979.go": true, // types2 doesn't report a follow-on error (pref: types2) - "fixedbugs/issue23305.go": true, // large untyped int passed to println (32-bit) - "fixedbugs/issue23732.go": true, // types2 reports different (but ok) line numbers - "fixedbugs/issue25958.go": true, // types2 doesn't report a follow-on error (pref: types2) - "fixedbugs/issue28079b.go": true, // types2 reports follow-on errors - "fixedbugs/issue28268.go": true, // types2 reports follow-on errors - "fixedbugs/issue31053.go": true, // types2 reports "unknown field" instead of "cannot refer to unexported field" - "fixedbugs/issue33460.go": true, // types2 reports alternative positions in separate error - "fixedbugs/issue42058a.go": true, // types2 doesn't report "channel element type too large" - "fixedbugs/issue42058b.go": true, // types2 doesn't report "channel element type too large" - "fixedbugs/issue42284.go": true, // unified formats important constant expression differently in diagnostics - "fixedbugs/issue4232.go": true, // types2 reports (correct) extra errors - "fixedbugs/issue4452.go": true, // types2 reports (correct) extra errors - "fixedbugs/issue4510.go": true, // types2 reports different (but ok) line numbers - "fixedbugs/issue5609.go": true, // types2 needs a better error message - "fixedbugs/issue7525b.go": true, // types2 reports init cycle error on different line - ok otherwise - "fixedbugs/issue7525c.go": true, // types2 reports init cycle error on different line - ok otherwise - "fixedbugs/issue7525d.go": true, // types2 reports init cycle error on different line - ok otherwise - "fixedbugs/issue7525e.go": true, // types2 reports init cycle error on different line - ok otherwise - "fixedbugs/issue7525.go": true, // types2 reports init cycle error on different line - ok otherwise - "fixedbugs/issue9691.go": true, // "cannot assign to int(.autotmp_4)" (probably irgen's fault) - - // tests that rely on -m diagnostics, which currently differ with -G=3 - // - // TODO(mdempsky): Triage, though most of the issues seem to fall into: +var types2Failures = setOf( + "directive.go", // misplaced compiler directive checks + "float_lit3.go", // types2 reports extra errors + "import1.go", // types2 reports extra errors + "import6.go", // issue #43109 + "initializerr.go", // types2 reports extra errors + "linkname2.go", // error reported by noder (not running for types2 errorcheck test) + "notinheap.go", // types2 doesn't report errors about conversions that are invalid due to //go:notinheap + "shift1.go", // issue #42989 + "typecheck.go", // invalid function is not causing errors when called + + "interface/private.go", // types2 phrases errors differently (doesn't use non-spec "private" term) + + "fixedbugs/bug176.go", // types2 reports all errors (pref: types2) + "fixedbugs/bug195.go", // types2 reports slightly different (but correct) bugs + "fixedbugs/bug228.go", // types2 doesn't run when there are syntax errors + "fixedbugs/bug231.go", // types2 bug? (same error reported twice) + "fixedbugs/bug255.go", // types2 reports extra errors + "fixedbugs/bug374.go", // types2 reports extra errors + "fixedbugs/bug388.go", // types2 not run due to syntax errors + "fixedbugs/bug412.go", // types2 produces a follow-on error + + "fixedbugs/issue10700.go", // types2 reports ok hint, but does not match regexp + "fixedbugs/issue11590.go", // types2 doesn't report a follow-on error (pref: types2) + "fixedbugs/issue11610.go", // types2 not run after syntax errors + "fixedbugs/issue11614.go", // types2 reports an extra error + "fixedbugs/issue14520.go", // missing import path error by types2 + "fixedbugs/issue16133.go", // types2 doesn't use package path for qualified identifiers when package name is ambiguous + "fixedbugs/issue16428.go", // types2 reports two instead of one error + "fixedbugs/issue17038.go", // types2 doesn't report a follow-on error (pref: types2) + "fixedbugs/issue17645.go", // multiple errors on same line + "fixedbugs/issue18331.go", // missing error about misuse of //go:noescape (irgen needs code from noder) + "fixedbugs/issue18419.go", // types2 reports + "fixedbugs/issue19012.go", // multiple errors on same line + "fixedbugs/issue20233.go", // types2 reports two instead of one error (pref: compiler) + "fixedbugs/issue20245.go", // types2 reports two instead of one error (pref: compiler) + "fixedbugs/issue21979.go", // types2 doesn't report a follow-on error (pref: types2) + "fixedbugs/issue23732.go", // types2 reports different (but ok) line numbers + "fixedbugs/issue25958.go", // types2 doesn't report a follow-on error (pref: types2) + "fixedbugs/issue28079b.go", // types2 reports follow-on errors + "fixedbugs/issue28268.go", // types2 reports follow-on errors + "fixedbugs/issue31053.go", // types2 reports "unknown field" instead of "cannot refer to unexported field" + "fixedbugs/issue33460.go", // types2 reports alternative positions in separate error + "fixedbugs/issue42058a.go", // types2 doesn't report "channel element type too large" + "fixedbugs/issue42058b.go", // types2 doesn't report "channel element type too large" + "fixedbugs/issue4232.go", // types2 reports (correct) extra errors + "fixedbugs/issue4452.go", // types2 reports (correct) extra errors + "fixedbugs/issue4510.go", // types2 reports different (but ok) line numbers + "fixedbugs/issue5609.go", // types2 needs a better error message + "fixedbugs/issue7525b.go", // types2 reports init cycle error on different line - ok otherwise + "fixedbugs/issue7525c.go", // types2 reports init cycle error on different line - ok otherwise + "fixedbugs/issue7525d.go", // types2 reports init cycle error on different line - ok otherwise + "fixedbugs/issue7525e.go", // types2 reports init cycle error on different line - ok otherwise + "fixedbugs/issue7525.go", // types2 reports init cycle error on different line - ok otherwise +) + +var types2Failures32Bit = setOf( + "printbig.go", // large untyped int passed to print (32-bit) + "fixedbugs/bug114.go", // large untyped int passed to println (32-bit) + "fixedbugs/issue23305.go", // large untyped int passed to println (32-bit) + "fixedbugs/bug385_32.go", // types2 doesn't produce missing error "type .* too large" (32-bit specific) +) + +var g3Failures = setOf( + // TODO: Triage tests without explicit failure explanations. From a + // cursory inspection, they mostly fall into: // - Anonymous result parameters given different names (e.g., ~r0 vs ~r1) // - Some escape analysis diagnostics being printed without position information // - Some expressions printed differently (e.g., "int(100)" instead // of "100" or "&composite literal" instead of "&[4]int{...}"). - "closure3.go": true, - "escape2.go": true, - "escape2n.go": true, - "escape4.go": true, - "escape_calls.go": true, - "escape_field.go": true, - "escape_iface.go": true, - "escape_indir.go": true, - "escape_level.go": true, - "escape_map.go": true, - "escape_param.go": true, - "escape_slice.go": true, - "escape_struct_param1.go": true, - "escape_struct_param2.go": true, - "fixedbugs/issue12006.go": true, - "fixedbugs/issue13799.go": true, - "fixedbugs/issue21709.go": true, - "fixedbugs/issue31573.go": true, - "fixedbugs/issue37837.go": true, - "fixedbugs/issue39292.go": true, - "fixedbugs/issue7921.go": true, - "inline.go": true, + + "closure3.go", // prints "s escapes to heap" without line number + "escape2.go", + "escape2n.go", + "escape4.go", // prints "1 escapes to heap" without line number + "escape_calls.go", + "escape_field.go", + "escape_iface.go", + "escape_indir.go", + "escape_level.go", + "escape_map.go", + "escape_param.go", + "escape_slice.go", + "escape_struct_param1.go", + "escape_struct_param2.go", + "writebarrier.go", // correct diagnostics, but different lines (probably irgen's fault) + + "fixedbugs/issue12006.go", + "fixedbugs/issue13799.go", + "fixedbugs/issue17270.go", // ICE in irgen + "fixedbugs/issue20174.go", // ICE due to width not calculated (probably irgen's fault) + "fixedbugs/issue20250.go", // correct diagnostics, but different lines (probably irgen's fault) + "fixedbugs/issue21709.go", + "fixedbugs/issue31573.go", + "fixedbugs/issue37837.go", + "fixedbugs/issue39292.go", + "fixedbugs/issue7921.go", // prints "composite literal does not escape" but test expects "[]byte{...} does not escape" + "fixedbugs/issue9691.go", // "cannot assign to int(.autotmp_4)" (probably irgen's fault) + + "typeparam/nested.go", // -G=3 doesn't support function-local types with generics +) + +var unifiedFailures = setOf( + "closure3.go", // unified IR numbers closures differently than -d=inlfuncswithclosures + "escape4.go", // unified IR can inline f5 and f6; test doesn't expect this + "inline.go", // unified IR reports function literal diagnostics on different lines than -d=inlfuncswithclosures + + "fixedbugs/issue42284.go", // prints "T(0) does not escape", but test expects "a.I(a.T(0)) does not escape" + "fixedbugs/issue7921.go", // prints "… escapes to heap", but test expects "string(…) escapes to heap" +) + +func setOf(keys ...string) map[string]bool { + m := make(map[string]bool, len(keys)) + for _, key := range keys { + m[key] = true + } + return m } // splitQuoted splits the string s around each instance of one or more consecutive diff --git a/test/typeparam/nested.go b/test/typeparam/nested.go index 6512b3fc8f..c0037a3e6e 100644 --- a/test/typeparam/nested.go +++ b/test/typeparam/nested.go @@ -1,4 +1,4 @@ -// run -gcflags=all="-d=unified -G" +// run -gcflags=-G=3 // Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style -- GitLab From 5c42b6a953036b906626f5b25b7655641fbad060 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 8 Jun 2021 11:57:11 -0700 Subject: [PATCH 0411/2500] [dev.typeparams] test: add regress tests that fail(ed) with -G=3 This CL includes multiple test cases that exercise unique failures with -G=3 mode that did not affect unified IR mode. Most of these were found over a period of about 3 hours of manual experimentation. Thanks to Cuong Manh Le for test cases 11 and 12. Updates #46704. Change-Id: Ia2fa619536732b121b6c929329065c85b9384511 Reviewed-on: https://go-review.googlesource.com/c/go/+/326169 Trust: Matthew Dempsky Trust: Dan Scales Trust: Cuong Manh Le Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Dan Scales Reviewed-by: Robert Griesemer --- test/run.go | 15 +++++++++- test/typeparam/mdempsky/1.dir/a.go | 9 ++++++ test/typeparam/mdempsky/1.dir/b.go | 9 ++++++ test/typeparam/mdempsky/1.go | 7 +++++ test/typeparam/mdempsky/10.dir/a.go | 7 +++++ test/typeparam/mdempsky/10.dir/b.go | 17 ++++++++++++ test/typeparam/mdempsky/10.go | 7 +++++ test/typeparam/mdempsky/11.go | 16 +++++++++++ test/typeparam/mdempsky/12.dir/a.go | 11 ++++++++ test/typeparam/mdempsky/12.dir/main.go | 13 +++++++++ test/typeparam/mdempsky/12.go | 9 ++++++ test/typeparam/mdempsky/13.go | 38 ++++++++++++++++++++++++++ test/typeparam/mdempsky/14.go | 37 +++++++++++++++++++++++++ test/typeparam/mdempsky/2.go | 20 ++++++++++++++ test/typeparam/mdempsky/3.dir/a.go | 7 +++++ test/typeparam/mdempsky/3.dir/b.go | 9 ++++++ test/typeparam/mdempsky/3.go | 7 +++++ test/typeparam/mdempsky/4.dir/a.go | 12 ++++++++ test/typeparam/mdempsky/4.dir/b.go | 9 ++++++ test/typeparam/mdempsky/4.go | 7 +++++ test/typeparam/mdempsky/5.go | 15 ++++++++++ test/typeparam/mdempsky/6.go | 11 ++++++++ test/typeparam/mdempsky/7.dir/a.go | 9 ++++++ test/typeparam/mdempsky/7.dir/b.go | 9 ++++++ test/typeparam/mdempsky/7.go | 7 +++++ test/typeparam/mdempsky/8.dir/a.go | 7 +++++ test/typeparam/mdempsky/8.dir/b.go | 11 ++++++++ test/typeparam/mdempsky/8.go | 7 +++++ test/typeparam/mdempsky/9.go | 11 ++++++++ 29 files changed, 352 insertions(+), 1 deletion(-) create mode 100644 test/typeparam/mdempsky/1.dir/a.go create mode 100644 test/typeparam/mdempsky/1.dir/b.go create mode 100644 test/typeparam/mdempsky/1.go create mode 100644 test/typeparam/mdempsky/10.dir/a.go create mode 100644 test/typeparam/mdempsky/10.dir/b.go create mode 100644 test/typeparam/mdempsky/10.go create mode 100644 test/typeparam/mdempsky/11.go create mode 100644 test/typeparam/mdempsky/12.dir/a.go create mode 100644 test/typeparam/mdempsky/12.dir/main.go create mode 100644 test/typeparam/mdempsky/12.go create mode 100644 test/typeparam/mdempsky/13.go create mode 100644 test/typeparam/mdempsky/14.go create mode 100644 test/typeparam/mdempsky/2.go create mode 100644 test/typeparam/mdempsky/3.dir/a.go create mode 100644 test/typeparam/mdempsky/3.dir/b.go create mode 100644 test/typeparam/mdempsky/3.go create mode 100644 test/typeparam/mdempsky/4.dir/a.go create mode 100644 test/typeparam/mdempsky/4.dir/b.go create mode 100644 test/typeparam/mdempsky/4.go create mode 100644 test/typeparam/mdempsky/5.go create mode 100644 test/typeparam/mdempsky/6.go create mode 100644 test/typeparam/mdempsky/7.dir/a.go create mode 100644 test/typeparam/mdempsky/7.dir/b.go create mode 100644 test/typeparam/mdempsky/7.go create mode 100644 test/typeparam/mdempsky/8.dir/a.go create mode 100644 test/typeparam/mdempsky/8.dir/b.go create mode 100644 test/typeparam/mdempsky/8.go create mode 100644 test/typeparam/mdempsky/9.go diff --git a/test/run.go b/test/run.go index ff8bf4b229..df3befbf21 100644 --- a/test/run.go +++ b/test/run.go @@ -86,7 +86,7 @@ var ( // dirs are the directories to look for *.go files in. // TODO(bradfitz): just use all directories? - dirs = []string{".", "ken", "chan", "interface", "syntax", "dwarf", "fixedbugs", "codegen", "runtime", "abi", "typeparam"} + dirs = []string{".", "ken", "chan", "interface", "syntax", "dwarf", "fixedbugs", "codegen", "runtime", "abi", "typeparam", "typeparam/mdempsky"} // ratec controls the max number of tests running at a time. ratec chan bool @@ -2203,6 +2203,19 @@ var g3Failures = setOf( "fixedbugs/issue9691.go", // "cannot assign to int(.autotmp_4)" (probably irgen's fault) "typeparam/nested.go", // -G=3 doesn't support function-local types with generics + + "typeparam/mdempsky/1.go", + "typeparam/mdempsky/2.go", + "typeparam/mdempsky/3.go", + "typeparam/mdempsky/4.go", + "typeparam/mdempsky/5.go", + "typeparam/mdempsky/7.go", + "typeparam/mdempsky/8.go", + "typeparam/mdempsky/9.go", + "typeparam/mdempsky/11.go", + "typeparam/mdempsky/12.go", + "typeparam/mdempsky/13.go", + "typeparam/mdempsky/14.go", ) var unifiedFailures = setOf( diff --git a/test/typeparam/mdempsky/1.dir/a.go b/test/typeparam/mdempsky/1.dir/a.go new file mode 100644 index 0000000000..a668eb52dc --- /dev/null +++ b/test/typeparam/mdempsky/1.dir/a.go @@ -0,0 +1,9 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type T[_ any] int + +func F() { _ = new(T[int]) } diff --git a/test/typeparam/mdempsky/1.dir/b.go b/test/typeparam/mdempsky/1.dir/b.go new file mode 100644 index 0000000000..af6fef3f6d --- /dev/null +++ b/test/typeparam/mdempsky/1.dir/b.go @@ -0,0 +1,9 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "./a" + +func main() { a.F() } diff --git a/test/typeparam/mdempsky/1.go b/test/typeparam/mdempsky/1.go new file mode 100644 index 0000000000..87b4ff46c1 --- /dev/null +++ b/test/typeparam/mdempsky/1.go @@ -0,0 +1,7 @@ +// compiledir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored diff --git a/test/typeparam/mdempsky/10.dir/a.go b/test/typeparam/mdempsky/10.dir/a.go new file mode 100644 index 0000000000..95e111d347 --- /dev/null +++ b/test/typeparam/mdempsky/10.dir/a.go @@ -0,0 +1,7 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type I[T any] interface{ M() T } diff --git a/test/typeparam/mdempsky/10.dir/b.go b/test/typeparam/mdempsky/10.dir/b.go new file mode 100644 index 0000000000..0ef28fd02d --- /dev/null +++ b/test/typeparam/mdempsky/10.dir/b.go @@ -0,0 +1,17 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "./a" + +var m = a.I[int].M + +var never bool + +func main() { + if never { + m(nil) + } +} diff --git a/test/typeparam/mdempsky/10.go b/test/typeparam/mdempsky/10.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/mdempsky/10.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored diff --git a/test/typeparam/mdempsky/11.go b/test/typeparam/mdempsky/11.go new file mode 100644 index 0000000000..e86c038a10 --- /dev/null +++ b/test/typeparam/mdempsky/11.go @@ -0,0 +1,16 @@ +// errorcheck + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Reported by Cuong Manh Le. + +package p + +type a struct{} + +//go:notinheap +type b a + +var _ = (*b)(new(a)) // ERROR "cannot convert" diff --git a/test/typeparam/mdempsky/12.dir/a.go b/test/typeparam/mdempsky/12.dir/a.go new file mode 100644 index 0000000000..ee8be939a8 --- /dev/null +++ b/test/typeparam/mdempsky/12.dir/a.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type S[T any] struct { + F T +} + +var X = S[int]{} diff --git a/test/typeparam/mdempsky/12.dir/main.go b/test/typeparam/mdempsky/12.dir/main.go new file mode 100644 index 0000000000..2891322e29 --- /dev/null +++ b/test/typeparam/mdempsky/12.dir/main.go @@ -0,0 +1,13 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "./a" +) + +func main() { + _ = a.X +} diff --git a/test/typeparam/mdempsky/12.go b/test/typeparam/mdempsky/12.go new file mode 100644 index 0000000000..a2dc4daacc --- /dev/null +++ b/test/typeparam/mdempsky/12.go @@ -0,0 +1,9 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Reported by Cuong Manh Le. + +package ignored diff --git a/test/typeparam/mdempsky/13.go b/test/typeparam/mdempsky/13.go new file mode 100644 index 0000000000..dc1d29bce1 --- /dev/null +++ b/test/typeparam/mdempsky/13.go @@ -0,0 +1,38 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type Mer interface{ M() } + +func F[T Mer](expectPanic bool) { + defer func() { + err := recover() + if (err != nil) != expectPanic { + print("FAIL: (", err, " != nil) != ", expectPanic, "\n") + } + }() + + var t T + T.M(t) +} + +type MyMer int + +func (MyMer) M() {} + +func main() { + F[Mer](true) + F[struct{ Mer }](true) + F[*struct{ Mer }](true) + + F[MyMer](false) + F[*MyMer](true) + F[struct{ MyMer }](false) + F[struct{ *MyMer }](true) + F[*struct{ MyMer }](true) + F[*struct{ *MyMer }](true) +} diff --git a/test/typeparam/mdempsky/14.go b/test/typeparam/mdempsky/14.go new file mode 100644 index 0000000000..61f9436910 --- /dev/null +++ b/test/typeparam/mdempsky/14.go @@ -0,0 +1,37 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func Zero[T any]() (_ T) { return } + +type T[X any] int + +func (T[X]) M() { + var have interface{} = Zero[X]() + var want interface{} = Zero[MyInt]() + + if have != want { + println("FAIL") + } +} + +type I interface{ M() } + +type MyInt int +type U = T[MyInt] + +var x = U(0) +var i I = x + +func main() { + x.M() + U.M(x) + (*U).M(&x) + + i.M() + I.M(x) +} diff --git a/test/typeparam/mdempsky/2.go b/test/typeparam/mdempsky/2.go new file mode 100644 index 0000000000..f09730f949 --- /dev/null +++ b/test/typeparam/mdempsky/2.go @@ -0,0 +1,20 @@ +// compile -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type T[A, B, C any] int + +func (T[A, B, C]) m(x int) { + if x <= 0 { + return + } + T[B, C, A](0).m(x - 1) +} + +func main() { + T[int8, int16, int32](0).m(3) +} diff --git a/test/typeparam/mdempsky/3.dir/a.go b/test/typeparam/mdempsky/3.dir/a.go new file mode 100644 index 0000000000..cf456e8d48 --- /dev/null +++ b/test/typeparam/mdempsky/3.dir/a.go @@ -0,0 +1,7 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +func F[T interface{ chan int }](c T) {} diff --git a/test/typeparam/mdempsky/3.dir/b.go b/test/typeparam/mdempsky/3.dir/b.go new file mode 100644 index 0000000000..0cfd142f4c --- /dev/null +++ b/test/typeparam/mdempsky/3.dir/b.go @@ -0,0 +1,9 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package b + +import "./a" + +func g() { a.F(make(chan int)) } diff --git a/test/typeparam/mdempsky/3.go b/test/typeparam/mdempsky/3.go new file mode 100644 index 0000000000..87b4ff46c1 --- /dev/null +++ b/test/typeparam/mdempsky/3.go @@ -0,0 +1,7 @@ +// compiledir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored diff --git a/test/typeparam/mdempsky/4.dir/a.go b/test/typeparam/mdempsky/4.dir/a.go new file mode 100644 index 0000000000..cb672949ea --- /dev/null +++ b/test/typeparam/mdempsky/4.dir/a.go @@ -0,0 +1,12 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +func F[T any](T) { +Loop: + for { + break Loop + } +} diff --git a/test/typeparam/mdempsky/4.dir/b.go b/test/typeparam/mdempsky/4.dir/b.go new file mode 100644 index 0000000000..e1fb0e7c5e --- /dev/null +++ b/test/typeparam/mdempsky/4.dir/b.go @@ -0,0 +1,9 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package b + +import "./a" + +func f() { a.F(0) } diff --git a/test/typeparam/mdempsky/4.go b/test/typeparam/mdempsky/4.go new file mode 100644 index 0000000000..87b4ff46c1 --- /dev/null +++ b/test/typeparam/mdempsky/4.go @@ -0,0 +1,7 @@ +// compiledir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored diff --git a/test/typeparam/mdempsky/5.go b/test/typeparam/mdempsky/5.go new file mode 100644 index 0000000000..0d1ad39946 --- /dev/null +++ b/test/typeparam/mdempsky/5.go @@ -0,0 +1,15 @@ +// compile -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type X[T any] int + +func (X[T]) F(T) {} + +func x() { + X[interface{}](0).F(0) +} diff --git a/test/typeparam/mdempsky/6.go b/test/typeparam/mdempsky/6.go new file mode 100644 index 0000000000..a26ff62f6d --- /dev/null +++ b/test/typeparam/mdempsky/6.go @@ -0,0 +1,11 @@ +// compile -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type I[T any] interface{ M() T } + +var _ = I[int].M diff --git a/test/typeparam/mdempsky/7.dir/a.go b/test/typeparam/mdempsky/7.dir/a.go new file mode 100644 index 0000000000..59c5995611 --- /dev/null +++ b/test/typeparam/mdempsky/7.dir/a.go @@ -0,0 +1,9 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type I[T any] interface{ M() T } + +var X I[int] diff --git a/test/typeparam/mdempsky/7.dir/b.go b/test/typeparam/mdempsky/7.dir/b.go new file mode 100644 index 0000000000..9f70530811 --- /dev/null +++ b/test/typeparam/mdempsky/7.dir/b.go @@ -0,0 +1,9 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package b + +import "./a" + +var _ = a.X diff --git a/test/typeparam/mdempsky/7.go b/test/typeparam/mdempsky/7.go new file mode 100644 index 0000000000..87b4ff46c1 --- /dev/null +++ b/test/typeparam/mdempsky/7.go @@ -0,0 +1,7 @@ +// compiledir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored diff --git a/test/typeparam/mdempsky/8.dir/a.go b/test/typeparam/mdempsky/8.dir/a.go new file mode 100644 index 0000000000..607fe5e0af --- /dev/null +++ b/test/typeparam/mdempsky/8.dir/a.go @@ -0,0 +1,7 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +func F[T interface{ comparable }]() {} diff --git a/test/typeparam/mdempsky/8.dir/b.go b/test/typeparam/mdempsky/8.dir/b.go new file mode 100644 index 0000000000..ef2637b894 --- /dev/null +++ b/test/typeparam/mdempsky/8.dir/b.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package b + +import "./a" + +func init() { + a.F[func()]() // ERROR "does not satisfy comparable" +} diff --git a/test/typeparam/mdempsky/8.go b/test/typeparam/mdempsky/8.go new file mode 100644 index 0000000000..32cf4b830d --- /dev/null +++ b/test/typeparam/mdempsky/8.go @@ -0,0 +1,7 @@ +// errorcheckdir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored diff --git a/test/typeparam/mdempsky/9.go b/test/typeparam/mdempsky/9.go new file mode 100644 index 0000000000..b72516c4ea --- /dev/null +++ b/test/typeparam/mdempsky/9.go @@ -0,0 +1,11 @@ +// compile -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +func f[V any]() []V { return []V{0: *new(V)} } + +func g() { f[int]() } -- GitLab From 4676c3675e85a8a82a1513ef1f5e38aebc80ddc8 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sun, 4 Jul 2021 12:06:39 +0700 Subject: [PATCH 0412/2500] [dev.typeparams] cmd/compile: rename PartialCallType -> MethodValueType CL 330837 rename OCALLPART to OMETHVALUE, so do the same thing for PartialCallType for consistency. Change-Id: Id40eb35bbcee7719acfb41fce0e2b968879f9fef Reviewed-on: https://go-review.googlesource.com/c/go/+/332769 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/escape/utils.go | 2 +- src/cmd/compile/internal/typecheck/func.go | 8 ++++---- src/cmd/compile/internal/walk/closure.go | 2 +- src/cmd/compile/internal/walk/order.go | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cmd/compile/internal/escape/utils.go b/src/cmd/compile/internal/escape/utils.go index 6e2f9c424a..5f462ef570 100644 --- a/src/cmd/compile/internal/escape/utils.go +++ b/src/cmd/compile/internal/escape/utils.go @@ -193,7 +193,7 @@ func HeapAllocReason(n ir.Node) string { if n.Op() == ir.OCLOSURE && typecheck.ClosureType(n.(*ir.ClosureExpr)).Size() > ir.MaxImplicitStackVarSize { return "too large for stack" } - if n.Op() == ir.OMETHVALUE && typecheck.PartialCallType(n.(*ir.SelectorExpr)).Size() > ir.MaxImplicitStackVarSize { + if n.Op() == ir.OMETHVALUE && typecheck.MethodValueType(n.(*ir.SelectorExpr)).Size() > ir.MaxImplicitStackVarSize { return "too large for stack" } diff --git a/src/cmd/compile/internal/typecheck/func.go b/src/cmd/compile/internal/typecheck/func.go index 847e9b9aea..7dec65c1d6 100644 --- a/src/cmd/compile/internal/typecheck/func.go +++ b/src/cmd/compile/internal/typecheck/func.go @@ -125,10 +125,10 @@ func ClosureType(clo *ir.ClosureExpr) *types.Type { return typ } -// PartialCallType returns the struct type used to hold all the information -// needed in the closure for n (n must be a OMETHVALUE node). -// The address of a variable of the returned type can be cast to a func. -func PartialCallType(n *ir.SelectorExpr) *types.Type { +// MethodValueType returns the struct type used to hold all the information +// needed in the closure for a OMETHVALUE node. The address of a variable of +// the returned type can be cast to a func. +func MethodValueType(n *ir.SelectorExpr) *types.Type { t := types.NewStruct(types.NoPkg, []*types.Field{ types.NewField(base.Pos, Lookup("F"), types.Types[types.TUINTPTR]), types.NewField(base.Pos, Lookup("R"), n.X.Type()), diff --git a/src/cmd/compile/internal/walk/closure.go b/src/cmd/compile/internal/walk/closure.go index 7f6ef473bf..2d0b2dcc0e 100644 --- a/src/cmd/compile/internal/walk/closure.go +++ b/src/cmd/compile/internal/walk/closure.go @@ -175,7 +175,7 @@ func walkMethodValue(n *ir.SelectorExpr, init *ir.Nodes) ir.Node { init.Append(typecheck.Stmt(check)) } - typ := typecheck.PartialCallType(n) + typ := typecheck.MethodValueType(n) clos := ir.NewCompLitExpr(base.Pos, ir.OCOMPLIT, ir.TypeNode(typ), nil) clos.SetEsc(n.Esc()) diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go index eec340261e..cd2bbcb73b 100644 --- a/src/cmd/compile/internal/walk/order.go +++ b/src/cmd/compile/internal/walk/order.go @@ -1306,7 +1306,7 @@ func (o *orderState) expr1(n, lhs ir.Node) ir.Node { n := n.(*ir.SelectorExpr) n.X = o.expr(n.X, nil) if n.Transient() { - t := typecheck.PartialCallType(n) + t := typecheck.MethodValueType(n) n.Prealloc = o.newTemp(t, false) } return n -- GitLab From b4844c9f54eb6a559d8dc9333cf5b1e66dab8167 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 6 Jul 2021 10:53:00 -0700 Subject: [PATCH 0413/2500] [dev.typeparams] cmd/compile: handle the (*T).M method expression with dictionaries The (*T).M method expression is where M is a value method, but the type (*T) is a pointer to the main type. In this case, after following any embedded fields, we need to add an extra star operator when using the receiver arg in the closure call. Thanks to Cuong for finding/pointing out an example for this case (typeparam/mdempsky/14.go) This example also shows that we now need the ability to export/import OEFACE and OIDATA, which I added. Change-Id: Ida0f81ce757fff78fec6276c60052ed71d207454 Reviewed-on: https://go-review.googlesource.com/c/go/+/333014 Run-TryBot: Dan Scales Reviewed-by: Keith Randall TryBot-Result: Go Bot Trust: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 30 +++++++++++-------- src/cmd/compile/internal/typecheck/iexport.go | 4 +-- src/cmd/compile/internal/typecheck/iimport.go | 4 +-- test/run.go | 1 - test/typeparam/dictionaryCapture.go | 12 ++++++++ 5 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index dbaebf7623..656cab84d1 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -94,7 +94,7 @@ func (g *irgen) stencil() { // generic F, not immediately called closureRequired = true } - if n.Op() == ir.OMETHEXPR && len(n.(*ir.SelectorExpr).X.Type().RParams()) > 0 && !types.IsInterfaceMethod(n.(*ir.SelectorExpr).Selection.Type) { + if n.Op() == ir.OMETHEXPR && len(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) > 0 && !types.IsInterfaceMethod(n.(*ir.SelectorExpr).Selection.Type) { // T.M, T a type which is generic, not immediately // called. Not necessary if the method selected is // actually for an embedded interface field. @@ -229,6 +229,7 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { outerInfo = g.instInfoMap[outer.Sym()] } usingSubdict := false + valueMethod := false if x.Op() == ir.OFUNCINST { inst := x.(*ir.InstExpr) @@ -269,16 +270,10 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { } } else { // ir.OMETHEXPR // Method expression T.M where T is a generic type. - // TODO: Is (*T).M right? se := x.(*ir.SelectorExpr) - targs := se.X.Type().RParams() + targs := deref(se.X.Type()).RParams() if len(targs) == 0 { - if se.X.Type().IsPtr() { - targs = se.X.Type().Elem().RParams() - if len(targs) == 0 { - panic("bad") - } - } + panic("bad") } // se.X.Type() is the top-level type of the method expression. To @@ -295,6 +290,10 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { break } } + if !gf.Type().Recv().Type.IsPtr() { + // Remember if value method, so we can detect (*T).M case. + valueMethod = true + } target = g.getInstantiation(gf, targs, true) dictValue, usingSubdict = g.getDictOrSubdict(outerInfo, x, gf, targs, true) if infoPrintMode { @@ -446,8 +445,15 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { // If we are doing a method expression, we need to // explicitly traverse any embedded fields in the receiver // argument in order to call the method instantiation. - dot := typecheck.AddImplicitDots(ir.NewSelectorExpr(base.Pos, ir.OXDOT, formalParams[0].Nname.(*ir.Name), x.(*ir.SelectorExpr).Sel)) - args = append(args, dot.X) + arg0 := formalParams[0].Nname.(ir.Node) + arg0 = typecheck.AddImplicitDots(ir.NewSelectorExpr(base.Pos, ir.OXDOT, arg0, x.(*ir.SelectorExpr).Sel)).X + if valueMethod && arg0.Type().IsPtr() { + // For handling the (*T).M case: if we have a pointer + // receiver after following all the embedded fields, + // but it's a value method, add a star operator. + arg0 = ir.NewStarExpr(arg0.Pos(), arg0) + } + args = append(args, arg0) } else { args = append(args, formalParams[i].Nname.(*ir.Name)) } @@ -1342,7 +1348,7 @@ func (subst *subster) fields(class ir.Class, oldfields []*types.Field, dcl []*ir return newfields } -// defer does a single defer of type t, if it is a pointer type. +// deref does a single deref of type t, if it is a pointer type. func deref(t *types.Type) *types.Type { if t.IsPtr() { return t.Elem() diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 82bbda5228..b717c373f5 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -1957,7 +1957,7 @@ func (w *exportWriter) expr(n ir.Node) { w.typ(n.Type()) // unary expressions - case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT, ir.ORECV: + case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT, ir.ORECV, ir.OIDATA: n := n.(*ir.UnaryExpr) w.op(n.Op()) w.pos(n.Pos()) @@ -1993,7 +1993,7 @@ func (w *exportWriter) expr(n ir.Node) { // binary expressions case ir.OADD, ir.OAND, ir.OANDNOT, ir.ODIV, ir.OEQ, ir.OGE, ir.OGT, ir.OLE, ir.OLT, - ir.OLSH, ir.OMOD, ir.OMUL, ir.ONE, ir.OOR, ir.ORSH, ir.OSUB, ir.OXOR: + ir.OLSH, ir.OMOD, ir.OMUL, ir.ONE, ir.OOR, ir.ORSH, ir.OSUB, ir.OXOR, ir.OEFACE: n := n.(*ir.BinaryExpr) w.op(n.Op()) w.pos(n.Pos()) diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 17e60effd6..f178869e28 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1497,7 +1497,7 @@ func (r *importReader) node() ir.Node { return ir.NewLinksymOffsetExpr(pos, Lookup(name).Linksym(), int64(off), typ) // unary expressions - case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT, ir.ORECV: + case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT, ir.ORECV, ir.OIDATA: n := ir.NewUnaryExpr(r.pos(), op, r.expr()) if go117ExportTypes { n.SetType(r.typ()) @@ -1521,7 +1521,7 @@ func (r *importReader) node() ir.Node { // binary expressions case ir.OADD, ir.OAND, ir.OANDNOT, ir.ODIV, ir.OEQ, ir.OGE, ir.OGT, ir.OLE, ir.OLT, - ir.OLSH, ir.OMOD, ir.OMUL, ir.ONE, ir.OOR, ir.ORSH, ir.OSUB, ir.OXOR: + ir.OLSH, ir.OMOD, ir.OMUL, ir.ONE, ir.OOR, ir.ORSH, ir.OSUB, ir.OXOR, ir.OEFACE: n := ir.NewBinaryExpr(r.pos(), op, r.expr(), r.expr()) if go117ExportTypes { n.SetType(r.typ()) diff --git a/test/run.go b/test/run.go index df3befbf21..7afad0ec09 100644 --- a/test/run.go +++ b/test/run.go @@ -2215,7 +2215,6 @@ var g3Failures = setOf( "typeparam/mdempsky/11.go", "typeparam/mdempsky/12.go", "typeparam/mdempsky/13.go", - "typeparam/mdempsky/14.go", ) var unifiedFailures = setOf( diff --git a/test/typeparam/dictionaryCapture.go b/test/typeparam/dictionaryCapture.go index af508859e1..26af7a09b0 100644 --- a/test/typeparam/dictionaryCapture.go +++ b/test/typeparam/dictionaryCapture.go @@ -73,20 +73,32 @@ func methodExpressions() { x := s[int]{a:7} f0 := s[int].g0 f0(x) + f0p := (*s[int]).g0 + f0p(&x) f1 := s[int].g1 is7(f1(x)) + f1p := (*s[int]).g1 + is7(f1p(&x)) f2 := s[int].g2 is77(f2(x)) + f2p := (*s[int]).g2 + is77(f2p(&x)) } func genMethodExpressions[T comparable](want T) { x := s[T]{a: want} f0 := s[T].g0 f0(x) + f0p := (*s[T]).g0 + f0p(&x) f1 := s[T].g1 if got := f1(x); got != want { panic(fmt.Sprintf("f1(x) == %d, want %d", got, want)) } + f1p := (*s[T]).g1 + if got := f1p(&x); got != want { + panic(fmt.Sprintf("f1p(&x) == %d, want %d", got, want)) + } f2 := s[T].g2 if got1, got2 := f2(x); got1 != want || got2 != want { panic(fmt.Sprintf("f2(x) == %d, %d, want %d, %d", got1, got2, want, want)) -- GitLab From b614c05a151ffc45b8eb5725c9df399aca20663d Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 5 Jul 2021 20:58:56 -0700 Subject: [PATCH 0414/2500] [dev.typeparams] cmd/compile: add built-in name/type "comparable". This allows exporting comparable type bounds, and importing back into types2 for typechecking. Fixes typeparam/mdempsky/8.go Change-Id: I3ee12433df2ed68ac6ef4cad24be9fcdfaaca4e3 Reviewed-on: https://go-review.googlesource.com/c/go/+/333129 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Robert Griesemer Trust: Dan Scales --- src/cmd/compile/internal/importer/support.go | 2 ++ src/cmd/compile/internal/noder/types.go | 8 -------- src/cmd/compile/internal/typecheck/bexport.go | 2 ++ src/cmd/compile/internal/typecheck/universe.go | 15 +++++++++++++++ src/cmd/compile/internal/types/type.go | 2 ++ src/go/internal/gcimporter/support.go | 2 ++ test/run.go | 1 - 7 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/cmd/compile/internal/importer/support.go b/src/cmd/compile/internal/importer/support.go index 3d1f77afcd..7eecae15a6 100644 --- a/src/cmd/compile/internal/importer/support.go +++ b/src/cmd/compile/internal/importer/support.go @@ -101,6 +101,8 @@ var predeclared = []types2.Type{ // error types2.Universe.Lookup("error").Type(), + // comparable + types2.Universe.Lookup("comparable").Type(), // untyped types types2.Typ[types2.UntypedBool], diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index a0b7fea7cb..d925f991c8 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -189,14 +189,6 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { // With Go 1.18, an embedded element can be any type, not // just an interface. - if t := types2.AsInterface(e); t != nil { - if t.IsComparable() { - // Ignore predefined type 'comparable', since it - // doesn't resolve and it doesn't have any - // relevant methods. - continue - } - } embeddeds[j] = types.NewField(src.NoXPos, nil, g.typ1(e)) j++ } diff --git a/src/cmd/compile/internal/typecheck/bexport.go b/src/cmd/compile/internal/typecheck/bexport.go index 4a84bb13fa..45d67f6ea2 100644 --- a/src/cmd/compile/internal/typecheck/bexport.go +++ b/src/cmd/compile/internal/typecheck/bexport.go @@ -78,6 +78,8 @@ func predeclared() []*types.Type { // error types.ErrorType, + // comparable + types.ComparableType, // untyped types types.UntypedBool, diff --git a/src/cmd/compile/internal/typecheck/universe.go b/src/cmd/compile/internal/typecheck/universe.go index de185ab944..54f3c89c24 100644 --- a/src/cmd/compile/internal/typecheck/universe.go +++ b/src/cmd/compile/internal/typecheck/universe.go @@ -158,6 +158,15 @@ func InitUniverse() { s.Def = n types.CalcSize(types.ErrorType) + // comparable type (interface) + s = types.BuiltinPkg.Lookup("comparable") + n = ir.NewDeclNameAt(src.NoXPos, ir.OTYPE, s) + types.ComparableType = types.NewNamed(n) + types.ComparableType.SetUnderlying(makeComparableInterface()) + n.SetType(types.ComparableType) + s.Def = n + types.CalcSize(types.ComparableType) + types.Types[types.TUNSAFEPTR] = defBasic(types.TUNSAFEPTR, ir.Pkgs.Unsafe, "Pointer") // simple aliases @@ -338,6 +347,12 @@ func makeErrorInterface() *types.Type { return types.NewInterface(types.NoPkg, []*types.Field{method}) } +func makeComparableInterface() *types.Type { + sig := types.NewSignature(types.NoPkg, fakeRecvField(), nil, nil, nil) + method := types.NewField(src.NoXPos, Lookup("=="), sig) + return types.NewInterface(types.NoPkg, []*types.Field{method}) +} + // DeclareUniverse makes the universe block visible within the current package. func DeclareUniverse() { // Operationally, this is similar to a dot import of builtinpkg, except diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 7f75000797..28312111ad 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -123,6 +123,8 @@ var ( // Predeclared error interface type. ErrorType *Type + // Predeclared comparable interface type. + ComparableType *Type // Types to represent untyped string and boolean constants. UntypedString = New(TSTRING) diff --git a/src/go/internal/gcimporter/support.go b/src/go/internal/gcimporter/support.go index b8bb14dc49..bb2058172a 100644 --- a/src/go/internal/gcimporter/support.go +++ b/src/go/internal/gcimporter/support.go @@ -104,6 +104,8 @@ var predeclared = []types.Type{ // error types.Universe.Lookup("error").Type(), + // comparable + types.Universe.Lookup("comparable").Type(), // untyped types types.Typ[types.UntypedBool], diff --git a/test/run.go b/test/run.go index 7afad0ec09..713e2006dc 100644 --- a/test/run.go +++ b/test/run.go @@ -2210,7 +2210,6 @@ var g3Failures = setOf( "typeparam/mdempsky/4.go", "typeparam/mdempsky/5.go", "typeparam/mdempsky/7.go", - "typeparam/mdempsky/8.go", "typeparam/mdempsky/9.go", "typeparam/mdempsky/11.go", "typeparam/mdempsky/12.go", -- GitLab From 501725032cb8e0fd5ef75b50f949dda09ce4b441 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 6 Jul 2021 09:38:58 -0700 Subject: [PATCH 0415/2500] [dev.typeparams] cmd/compile: handle derived types that are converted to interfaces Up to this point, we were only handling typeparams that were converted to empty or non-empty interfaces. But we have a dictionary entry for each derived type (i.e. type derived from typeparams) as well. So, when doing a conversion, look for the source type in both the type params and derived types of the generic info, and then use the appropriate dictionary entry. Added some cases to ifaceconv.go (e.g. converting []T to an empty interface). Change-Id: I7bbad0128bec20ccccd93ae1d65c1ffd44ca79a0 Reviewed-on: https://go-review.googlesource.com/c/go/+/333011 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 60 +++++++++++++---------- test/typeparam/ifaceconv.go | 18 +++++++ 2 files changed, 52 insertions(+), 26 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 656cab84d1..ce9dc09bc3 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -979,21 +979,14 @@ func getDictionaryEntry(pos src.XPos, dict *ir.Name, i int, size int) ir.Node { return r } -// getDictionaryType returns a *runtime._type from the dictionary corresponding to the input type. -// The input type must be a type parameter (TODO: or a local derived type). -func (subst *subster) getDictionaryType(pos src.XPos, t *types.Type) ir.Node { - tparams := subst.ts.Tparams - var i = 0 - for i = range tparams { - if t == tparams[i] { - break - } - } - if i == len(tparams) { - base.Fatalf(fmt.Sprintf("couldn't find type param %+v", t)) +// getDictionaryType returns a *runtime._type from the dictionary entry i +// (which refers to a type param or a derived type that uses type params). +func (subst *subster) getDictionaryType(pos src.XPos, i int) ir.Node { + if i < 0 || i >= subst.info.startSubDict { + base.Fatalf(fmt.Sprintf("bad dict index %d", i)) } - r := getDictionaryEntry(pos, subst.info.dictParam, i, len(tparams)) + r := getDictionaryEntry(pos, subst.info.dictParam, i, subst.info.startSubDict) // change type of retrieved dictionary entry to *byte, which is the // standard typing of a *runtime._type in the compiler typed(types.Types[types.TUINT8].PtrTo(), r) @@ -1134,11 +1127,12 @@ func (subst *subster) node(n ir.Node) ir.Node { // type argument. m = transformConvCall(call) if m.Op() == ir.OCONVIFACE { - if srcType := x.(*ir.CallExpr).Args[0].Type(); srcType.IsTypeParam() { // TODO: or derived type - // Note: srcType uses x.Args[0], not m.X or call.Args[0], because - // we need the type before the type parameter -> type argument substitution. + // Note: srcType uses x.Args[0], not m.X or call.Args[0], because + // we need the type before the type parameter -> type argument substitution. + srcType := x.(*ir.CallExpr).Args[0].Type() + if ix := subst.findDictType(srcType); ix >= 0 { c := m.(*ir.ConvExpr) - m = subst.convertUsingDictionary(c.Pos(), c.X, c.Type(), srcType) + m = subst.convertUsingDictionary(c.Pos(), c.X, c.Type(), srcType, ix) } } @@ -1240,8 +1234,9 @@ func (subst *subster) node(n ir.Node) ir.Node { x := x.(*ir.ConvExpr) // Note: x's argument is still typed as a type parameter. // m's argument now has an instantiated type. - if t := x.X.Type(); t.IsTypeParam() { - m = subst.convertUsingDictionary(x.Pos(), m.(*ir.ConvExpr).X, m.Type(), t) + t := x.X.Type() + if ix := subst.findDictType(t); ix >= 0 { + m = subst.convertUsingDictionary(x.Pos(), m.(*ir.ConvExpr).X, m.Type(), t, ix) } } return m @@ -1250,18 +1245,31 @@ func (subst *subster) node(n ir.Node) ir.Node { return edit(n) } -// convertUsingDictionary converts value v from generic type src to an interface type dst. -func (subst *subster) convertUsingDictionary(pos src.XPos, v ir.Node, dst, src *types.Type) ir.Node { - // TODO: handle converting from derived types. For now, just from naked - // type parameters. - if !src.IsTypeParam() { - base.Fatalf("source must be a type parameter %+v", src) +// findDictType looks for type t in the typeparams or derived types in the generic +// function info subst.info.gfInfo. This will indicate the dictionary entry with the +// correct concrete type for the associated instantiated function. +func (subst *subster) findDictType(t *types.Type) int { + for i, dt := range subst.info.gfInfo.tparams { + if dt == t { + return i + } } + for i, dt := range subst.info.gfInfo.derivedTypes { + if types.Identical(dt, t) { + return i + len(subst.info.gfInfo.tparams) + } + } + return -1 +} + +// convertUsingDictionary converts value v from instantiated type src (which is index +// 'ix' in the instantiation's dictionary) to an interface type dst. +func (subst *subster) convertUsingDictionary(pos src.XPos, v ir.Node, dst, src *types.Type, ix int) ir.Node { if !dst.IsInterface() { base.Fatalf("can only convert type parameters to interfaces %+v -> %+v", src, dst) } // Load the actual runtime._type of the type parameter from the dictionary. - rt := subst.getDictionaryType(pos, src) + rt := subst.getDictionaryType(pos, ix) // Convert value to an interface type, so the data field is what we want. if !v.Type().IsInterface() { diff --git a/test/typeparam/ifaceconv.go b/test/typeparam/ifaceconv.go index 32c2dbe7c2..f4023366b9 100644 --- a/test/typeparam/ifaceconv.go +++ b/test/typeparam/ifaceconv.go @@ -18,6 +18,13 @@ func f[T any](x T) interface{} { var i interface{} = x return i } + +func fs[T any](x T) interface{} { + y := []T{x} + var i interface{} = y + return i +} + func g[T any](x T) E { var i E = x return i @@ -46,10 +53,18 @@ func j[T C](t T) C { return C(t) // explicit conversion } +func js[T any](x T) interface{} { + y := []T{x} + return interface{}(y) +} + func main() { if got, want := f[int](7), 7; got != want { panic(fmt.Sprintf("got %d want %d", got, want)) } + if got, want := fs[int](7), []int{7}; got.([]int)[0] != want[0] { + panic(fmt.Sprintf("got %d want %d", got, want)) + } if got, want := g[int](7), 7; got != want { panic(fmt.Sprintf("got %d want %d", got, want)) } @@ -62,4 +77,7 @@ func main() { if got, want := j[myInt](7).foo(), 8; got != want { panic(fmt.Sprintf("got %d want %d", got, want)) } + if got, want := js[int](7), []int{7}; got.([]int)[0] != want[0] { + panic(fmt.Sprintf("got %d want %d", got, want)) + } } -- GitLab From c65ca97a452f872516a7e9462cd27ac17d913747 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 7 Jul 2021 04:03:24 -0700 Subject: [PATCH 0416/2500] [dev.typeparams] cmd/compile: fix windows longtest builder CL 332469 broke the Windows longtest builders, because it changed the names assigned to autotmp variables that end up in export data. The naming of autotmps doesn't actually matter, so instead we can just hack iexport to write out "$autotmp" as a magic marker, and let the reader replace it with an appropriate unique name. This is a little hacky, but so is iexport's handling of autotmps already, and this should also go away eventually with unified IR. Change-Id: Ic17395337c745b66b9d63ee566299290214e6273 Reviewed-on: https://go-review.googlesource.com/c/go/+/333089 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: Cuong Manh Le TryBot-Result: Go Bot --- src/cmd/compile/internal/typecheck/iexport.go | 11 +++++++++-- src/cmd/compile/internal/typecheck/iimport.go | 12 ++++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index b717c373f5..0a48078bd0 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -2116,8 +2116,15 @@ func (w *exportWriter) localIdent(s *types.Sym) { return } - // TODO(mdempsky): Fix autotmp hack. - if i := strings.LastIndex(name, "."); i >= 0 && !strings.HasPrefix(name, ".autotmp_") && !strings.HasPrefix(name, ".dict") { // TODO: just use autotmp names for dictionaries? + // The name of autotmp variables isn't important; they just need to + // be unique. To stabilize the export data, simply write out "$" as + // a marker and let the importer generate its own unique name. + if strings.HasPrefix(name, ".autotmp_") { + w.string("$autotmp") + return + } + + if i := strings.LastIndex(name, "."); i >= 0 && !strings.HasPrefix(name, ".dict") { // TODO: just use autotmp names for dictionaries? base.Fatalf("unexpected dot in identifier: %v", name) } diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index f178869e28..7b7cd7f148 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -265,6 +265,7 @@ type importReader struct { // Slice of all dcls for function, including any interior closures allDcls []*ir.Name allClosureVars []*ir.Name + autotmpgen int } func (p *iimporter) newReader(off uint64, pkg *types.Pkg) *importReader { @@ -516,8 +517,15 @@ func (r *importReader) ident(selector bool) *types.Sym { return nil } pkg := r.currPkg - if selector && types.IsExported(name) { - pkg = types.LocalPkg + if selector { + if types.IsExported(name) { + pkg = types.LocalPkg + } + } else { + if name == "$autotmp" { + name = autotmpname(r.autotmpgen) + r.autotmpgen++ + } } return pkg.Lookup(name) } -- GitLab From 85267f402c3ba7ec91a3cf5e4e4a763fd1137deb Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 7 Jul 2021 14:42:26 -0700 Subject: [PATCH 0417/2500] [dev.typeparams] cmd/compile: move def of comparable to end of predeclared slices This avoids changing the export ABI. Change-Id: I58950c1f4c21859d91d66d352b88e8c0972b5b8c Reviewed-on: https://go-review.googlesource.com/c/go/+/333164 Trust: Dan Scales Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/importer/support.go | 5 +++-- src/cmd/compile/internal/typecheck/bexport.go | 5 +++-- src/go/internal/gcimporter/support.go | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/importer/support.go b/src/cmd/compile/internal/importer/support.go index 7eecae15a6..6ceb413601 100644 --- a/src/cmd/compile/internal/importer/support.go +++ b/src/cmd/compile/internal/importer/support.go @@ -101,8 +101,6 @@ var predeclared = []types2.Type{ // error types2.Universe.Lookup("error").Type(), - // comparable - types2.Universe.Lookup("comparable").Type(), // untyped types types2.Typ[types2.UntypedBool], @@ -121,6 +119,9 @@ var predeclared = []types2.Type{ // used internally by gc; never used by this package or in .a files anyType{}, + + // comparable + types2.Universe.Lookup("comparable").Type(), } type anyType struct{} diff --git a/src/cmd/compile/internal/typecheck/bexport.go b/src/cmd/compile/internal/typecheck/bexport.go index 45d67f6ea2..cc7f91f937 100644 --- a/src/cmd/compile/internal/typecheck/bexport.go +++ b/src/cmd/compile/internal/typecheck/bexport.go @@ -78,8 +78,6 @@ func predeclared() []*types.Type { // error types.ErrorType, - // comparable - types.ComparableType, // untyped types types.UntypedBool, @@ -98,6 +96,9 @@ func predeclared() []*types.Type { // any type, for builtin export data types.Types[types.TANY], + + // comparable + types.ComparableType, } } return predecl diff --git a/src/go/internal/gcimporter/support.go b/src/go/internal/gcimporter/support.go index bb2058172a..09810dd85b 100644 --- a/src/go/internal/gcimporter/support.go +++ b/src/go/internal/gcimporter/support.go @@ -104,8 +104,6 @@ var predeclared = []types.Type{ // error types.Universe.Lookup("error").Type(), - // comparable - types.Universe.Lookup("comparable").Type(), // untyped types types.Typ[types.UntypedBool], @@ -124,6 +122,9 @@ var predeclared = []types.Type{ // used internally by gc; never used by this package or in .a files anyType{}, + + // comparable + types.Universe.Lookup("comparable").Type(), } type anyType struct{} -- GitLab From 60cb2cab97ca6a28dcb4a58776ed85f840f534d5 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 7 Jul 2021 12:03:41 -0700 Subject: [PATCH 0418/2500] [dev.typeparams] cmd/compile: fix bug with types2.Instantiate with interface type param types2.subst has an assertion that check is non-nil, but which breaks Instantiate() with an interface type param (used when re-importing instatiated type to types2). But this check was added when Instantiate() was added, and things seem to work fine when the assertion is removed. Fixes test/typeparam/mdempsky/7.go. Change-Id: I4980f0b202a0b310a3c91a7a87f97576f54911de Reviewed-on: https://go-review.googlesource.com/c/go/+/333155 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Robert Griesemer Trust: Dan Scales --- src/cmd/compile/internal/types2/subst.go | 3 --- test/run.go | 1 - 2 files changed, 4 deletions(-) diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index db01c36f7a..7b4796fa2e 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -313,9 +313,6 @@ func (subst *subster) typ(typ Type) Type { embeddeds, ecopied := subst.typeList(t.embeddeds) if mcopied || ecopied { iface := &Interface{methods: methods, embeddeds: embeddeds, complete: t.complete} - if subst.check == nil { - panic("internal error: cannot instantiate interfaces yet") - } return iface } diff --git a/test/run.go b/test/run.go index 713e2006dc..0251dc1c6a 100644 --- a/test/run.go +++ b/test/run.go @@ -2209,7 +2209,6 @@ var g3Failures = setOf( "typeparam/mdempsky/3.go", "typeparam/mdempsky/4.go", "typeparam/mdempsky/5.go", - "typeparam/mdempsky/7.go", "typeparam/mdempsky/9.go", "typeparam/mdempsky/11.go", "typeparam/mdempsky/12.go", -- GitLab From 47547d8508ab416e28992e0e0965c9c25f840848 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 1 Jul 2021 22:10:01 -0700 Subject: [PATCH 0419/2500] [dev.typeparams] cmd/compile/internal/types2: disallow "free" type parameter as RHS of a type declaration For #45639. Change-Id: I20e331b04f464db81e916af75f70ec8ae73eb989 Reviewed-on: https://go-review.googlesource.com/c/go/+/332411 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/decl.go | 64 ++++++++++--------- .../types2/testdata/examples/types.go2 | 50 +++++++++------ .../types2/testdata/fixedbugs/issue45639.go2 | 12 ++++ src/cmd/compile/internal/types2/unify.go | 15 +++-- 4 files changed, 87 insertions(+), 54 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue45639.go2 diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index d36da06f42..4f91bc70c7 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -626,8 +626,8 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named alias = false } + // alias declaration if alias { - // type alias declaration if !check.allowVersion(check.pkg, 1, 9) { if check.conf.CompilerErrorMessages { check.error(tdecl, "type aliases only supported as of -lang=go1.9") @@ -638,40 +638,44 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named obj.typ = Typ[Invalid] obj.typ = check.anyType(tdecl.Type) + return + } - } else { - // defined type declaration - - named := check.newNamed(obj, nil, nil, nil, nil) - def.setUnderlying(named) + // type definition or generic type declaration + named := check.newNamed(obj, nil, nil, nil, nil) + def.setUnderlying(named) - if tdecl.TParamList != nil { - check.openScope(tdecl, "type parameters") - defer check.closeScope() - named.tparams = check.collectTypeParams(tdecl.TParamList) - } + if tdecl.TParamList != nil { + check.openScope(tdecl, "type parameters") + defer check.closeScope() + named.tparams = check.collectTypeParams(tdecl.TParamList) + } - // determine underlying type of named - named.fromRHS = check.definedType(tdecl.Type, named) + // determine underlying type of named + named.fromRHS = check.definedType(tdecl.Type, named) - // The underlying type of named may be itself a named type that is - // incomplete: - // - // type ( - // A B - // B *C - // C A - // ) - // - // The type of C is the (named) type of A which is incomplete, - // and which has as its underlying type the named type B. - // Determine the (final, unnamed) underlying type by resolving - // any forward chain. - // TODO(gri) Investigate if we can just use named.fromRHS here - // and rely on lazy computation of the underlying type. - named.underlying = under(named) + // The underlying type of named may be itself a named type that is + // incomplete: + // + // type ( + // A B + // B *C + // C A + // ) + // + // The type of C is the (named) type of A which is incomplete, + // and which has as its underlying type the named type B. + // Determine the (final, unnamed) underlying type by resolving + // any forward chain. + // TODO(gri) Investigate if we can just use named.fromRHS here + // and rely on lazy computation of the underlying type. + named.underlying = under(named) + + // If the RHS is a type parameter, it must be from this type declaration. + if tpar, _ := named.underlying.(*TypeParam); tpar != nil && tparamIndex(named.tparams, tpar) < 0 { + check.errorf(tdecl.Type, "cannot use function type parameter %s as RHS in type declaration", tpar) + named.underlying = Typ[Invalid] } - } func (check *Checker) collectTypeParams(list []*syntax.Field) []*TypeName { diff --git a/src/cmd/compile/internal/types2/testdata/examples/types.go2 b/src/cmd/compile/internal/types2/testdata/examples/types.go2 index 66e7a7b90e..4ecc34dfa4 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/types.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/types.go2 @@ -155,30 +155,40 @@ type _ struct { List /* ERROR List redeclared */ [int] } +// Issue #45639: We don't allow this anymore. Keep this code +// in case we decide to revisit this decision. +// // It's possible to declare local types whose underlying types // are type parameters. As with ordinary type definitions, the // types underlying properties are "inherited" but the methods // are not. -func _[T interface{ m(); ~int }]() { - type L T - var x L - - // m is not defined on L (it is not "inherited" from - // its underlying type). - x.m /* ERROR x.m undefined */ () - - // But the properties of T, such that as that it supports - // the operations of the types given by its type bound, - // are also the properties of L. - x++ - _ = x - x - - // On the other hand, if we define a local alias for T, - // that alias stands for T as expected. - type A = T - var y A - y.m() - _ = y < 0 +// func _[T interface{ m(); ~int }]() { +// type L T +// var x L +// +// // m is not defined on L (it is not "inherited" from +// // its underlying type). +// x.m /* ERROR x.m undefined */ () +// +// // But the properties of T, such that as that it supports +// // the operations of the types given by its type bound, +// // are also the properties of L. +// x++ +// _ = x - x +// +// // On the other hand, if we define a local alias for T, +// // that alias stands for T as expected. +// type A = T +// var y A +// y.m() +// _ = y < 0 +// } + +// It is not permitted to declare a local type whose underlying +// type is a type parameters not declared by that type declaration. +func _[T any]() { + type _ T // ERROR cannot use function type parameter T as RHS in type declaration + type _ [_ any] T // ERROR cannot use function type parameter T as RHS in type declaration } // As a special case, an explicit type argument may be omitted diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45639.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45639.go2 new file mode 100644 index 0000000000..441fb4cb34 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45639.go2 @@ -0,0 +1,12 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package P + +// It is not permitted to declare a local type whose underlying +// type is a type parameters not declared by that type declaration. +func _[T any]() { + type _ T // ERROR cannot use function type parameter T as RHS in type declaration + type _ [_ any] T // ERROR cannot use function type parameter T as RHS in type declaration +} diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index 4e1f832203..755622738a 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -150,10 +150,17 @@ func (u *unifier) join(i, j int) bool { // If typ is a type parameter of d, index returns the type parameter index. // Otherwise, the result is < 0. func (d *tparamsList) index(typ Type) int { - if t, ok := typ.(*TypeParam); ok { - if i := t.index; i < len(d.tparams) && d.tparams[i].typ == t { - return i - } + if tpar, ok := typ.(*TypeParam); ok { + return tparamIndex(d.tparams, tpar) + } + return -1 +} + +// If tpar is a type parameter in list, tparamIndex returns the type parameter index. +// Otherwise, the result is < 0. tpar must not be nil. +func tparamIndex(list []*TypeName, tpar *TypeParam) int { + if i := tpar.index; i < len(list) && list[i].typ == tpar { + return i } return -1 } -- GitLab From 03ec8de24b6fc8a2abeb4013ef603f5cdef9f874 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 2 Jul 2021 15:41:28 -0700 Subject: [PATCH 0420/2500] [dev.typeparams] cmd/compile/internal/types2: clean up index expr implementation for type parameters This makes the implementation match the intended spec behavior: Given an index expression a[x] where a is a type parameter, the index expression is valid if the constraint for a satisfies the following criteria: - Either all types in the constraint type set are maps, or none of them are. - If the (type set) types are maps, they must all have the same key type. (This may be too strict, perhaps it's sufficient to ensure assignability, but we can always relax that later.) - All (type set) types must have the same element types. - If there are any arrays, a constant index must be in range for the shortest array. Change-Id: I8c094c11e6fc9496c293871ccf93e3814c881e6f Reviewed-on: https://go-review.googlesource.com/c/go/+/332553 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/index.go | 119 +++++++++--------- .../types2/testdata/check/typeparams.go2 | 17 ++- .../types2/testdata/fixedbugs/issue45635.go2 | 5 +- src/cmd/compile/internal/types2/typeparam.go | 7 ++ src/cmd/compile/internal/types2/typeset.go | 15 +++ src/cmd/compile/internal/types2/typestring.go | 2 +- src/cmd/compile/internal/types2/union.go | 2 +- 7 files changed, 93 insertions(+), 74 deletions(-) diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index 47e0853a3b..5a4dcb4741 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -41,7 +41,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo // ordinary index expression valid := false length := int64(-1) // valid if >= 0 - switch typ := optype(x.typ).(type) { + switch typ := under(x.typ).(type) { case *Basic: if isString(typ) { valid = true @@ -80,7 +80,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo index := check.singleIndex(e) if index == nil { x.mode = invalid - return + return false } var key operand check.expr(&key, index) @@ -89,87 +89,80 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo x.mode = mapindex x.typ = typ.elem x.expr = e - return + return false - case *Union: - // A union type can be indexed if all of the union's terms - // support indexing and have the same index and element - // type. Special rules apply for maps in the union type. - var tkey, telem Type // key is for map types only - nmaps := 0 // number of map types in union type - if typ.underIs(func(t Type) bool { - var e Type - switch t := t.(type) { + case *TypeParam: + // TODO(gri) report detailed failure cause for better error messages + var tkey, telem Type // tkey != nil if we have maps + if typ.underIs(func(u Type) bool { + var key, elem Type + alen := int64(-1) // valid if >= 0 + switch t := u.(type) { case *Basic: - if isString(t) { - e = universeByte + if !isString(t) { + return false } + elem = universeByte case *Array: - e = t.elem + elem = t.elem + alen = t.len case *Pointer: - if t := asArray(t.base); t != nil { - e = t.elem + a, _ := under(t.base).(*Array) + if a == nil { + return false } + elem = a.elem + alen = a.len case *Slice: - e = t.elem + elem = t.elem case *Map: - // If there are multiple maps in the union type, - // they must have identical key types. - // TODO(gri) We may be able to relax this rule - // but it becomes complicated very quickly. - if tkey != nil && !Identical(t.key, tkey) { + key = t.key + elem = t.elem + default: + return false + } + assert(elem != nil) + if telem == nil { + // first type + tkey, telem = key, elem + length = alen + } else { + // all map keys must be identical (incl. all nil) + if !Identical(key, tkey) { return false } - tkey = t.key - e = t.elem - nmaps++ - case *TypeParam: - check.errorf(x, "type of %s contains a type parameter - cannot index (implementation restriction)", x) - case *instance: - unimplemented() - } - if e == nil || telem != nil && !Identical(e, telem) { - return false + // all element types must be identical + if !Identical(elem, telem) { + return false + } + tkey, telem = key, elem + // track the minimal length for arrays + if alen >= 0 && alen < length { + length = alen + } } - telem = e return true }) { - // If there are maps, the index expression must be assignable - // to the map key type (as for simple map index expressions). - if nmaps > 0 { + // For maps, the index expression must be assignable to the map key type. + if tkey != nil { index := check.singleIndex(e) if index == nil { x.mode = invalid - return + return false } var key operand check.expr(&key, index) check.assignment(&key, tkey, "map index") // ok to continue even if indexing failed - map element type is known - - // If there are only maps, we are done. - if nmaps == typ.NumTerms() { - x.mode = mapindex - x.typ = telem - x.expr = e - return - } - - // Otherwise we have mix of maps and other types. For - // now we require that the map key be an integer type. - // TODO(gri) This is probably not good enough. - valid = isInteger(tkey) - // avoid 2nd indexing error if indexing failed above - if !valid && key.mode == invalid { - x.mode = invalid - return - } - x.mode = value // map index expressions are not addressable - } else { - // no maps - valid = true - x.mode = variable + x.mode = mapindex + x.typ = telem + x.expr = e + return false } + + // no maps + valid = true + x.mode = variable x.typ = telem } } @@ -177,13 +170,13 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo if !valid { check.errorf(x, invalidOp+"cannot index %s", x) x.mode = invalid - return + return false } index := check.singleIndex(e) if index == nil { x.mode = invalid - return + return false } // In pathological (invalid) cases (e.g.: type T1 [][[]T1{}[0][0]]T0) diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 index 4074ef17ea..123567682a 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 @@ -98,18 +98,23 @@ func _[T any] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } func _[T interface{ ~int }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } func _[T interface{ ~string }] (x T, i int) { _ = x[i] } func _[T interface{ ~[]int }] (x T, i int) { _ = x[i] } -func _[T interface{ ~[10]int | ~*[20]int | ~map[int]int }] (x T, i int) { _ = x[i] } +func _[T interface{ ~[10]int | ~*[20]int | ~map[int]int }] (x T, i int) { _ = x /* ERROR cannot index */ [i] } // map and non-map types func _[T interface{ ~string | ~[]byte }] (x T, i int) { _ = x[i] } func _[T interface{ ~[]int | ~[1]rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } func _[T interface{ ~string | ~[]rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } -// indexing with various combinations of map types in type lists (see issue #42616) -func _[T interface{ ~[]E | ~map[int]E }, E any](x T, i int) { _ = x[i] } +// indexing with various combinations of map types in type sets (see issue #42616) +func _[T interface{ ~[]E | ~map[int]E }, E any](x T, i int) { _ = x /* ERROR cannot index */ [i] } // map and non-map types func _[T interface{ ~[]E }, E any](x T, i int) { _ = &x[i] } func _[T interface{ ~map[int]E }, E any](x T, i int) { _, _ = x[i] } // comma-ok permitted -func _[T interface{ ~[]E | ~map[int]E }, E any](x T, i int) { _ = &x /* ERROR cannot take address */ [i] } -func _[T interface{ ~[]E | ~map[int]E | ~map[uint]E }, E any](x T, i int) { _ = x /* ERROR cannot index */ [i] } // different map element types -func _[T interface{ ~[]E | ~map[string]E }, E any](x T, i int) { _ = x[i /* ERROR cannot use i */ ] } +func _[T interface{ ~map[int]E }, E any](x T, i int) { _ = &x /* ERROR cannot take address */ [i] } +func _[T interface{ ~map[int]E | ~map[uint]E }, E any](x T, i int) { _ = x /* ERROR cannot index */ [i] } // different map element types +func _[T interface{ ~[]E | ~map[string]E }, E any](x T, i int) { _ = x /* ERROR cannot index */ [i] } // map and non-map types + +// indexing with various combinations of array and other types in type sets +func _[T interface{ [10]int }](x T, i int) { _ = x[i]; _ = x[9]; _ = x[10 /* ERROR out of bounds */ ] } +func _[T interface{ [10]byte | string }](x T, i int) { _ = x[i]; _ = x[9]; _ = x[10 /* ERROR out of bounds */ ] } +func _[T interface{ [10]int | *[20]int | []int }](x T, i int) { _ = x[i]; _ = x[9]; _ = x[10 /* ERROR out of bounds */ ] } // slicing // TODO(gri) implement this diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45635.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45635.go2 index e9b57ae8f1..2937959105 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45635.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45635.go2 @@ -13,7 +13,7 @@ type N[T any] struct{} var _ N[] /* ERROR expecting type */ type I interface { - ~map[int]int | ~[]int + ~[]int } func _[T I](i, j int) { @@ -27,6 +27,5 @@ func _[T I](i, j int) { _ = s[i, j /* ERROR more than one index */ ] var t T - // TODO(gri) fix multiple error below - _ = t[i, j /* ERROR more than one index */ /* ERROR more than one index */ ] + _ = t[i, j /* ERROR more than one index */ ] } diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index 5c74405912..b73b4edf79 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -78,3 +78,10 @@ func (t *TypeParam) SetBound(bound Type) { func (t *TypeParam) Underlying() Type { return t } func (t *TypeParam) String() string { return TypeString(t, nil) } + +// ---------------------------------------------------------------------------- +// Implementation + +func (t *TypeParam) underIs(f func(Type) bool) bool { + return t.Bound().typeSet().underIs(f) +} diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index 265221501f..6ff8563974 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -75,6 +75,21 @@ func (s *TypeSet) String() string { // ---------------------------------------------------------------------------- // Implementation +// underIs reports whether f returned true for the underlying types of the +// enumerable types in the type set s. If the type set comprises all types +// f is called once with the top type; if the type set is empty, the result +// is false. +func (s *TypeSet) underIs(f func(Type) bool) bool { + switch t := s.types.(type) { + case nil: + return f(theTop) + default: + return f(t) + case *Union: + return t.underIs(f) + } +} + // topTypeSet may be used as type set for the empty interface. var topTypeSet TypeSet diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 4925252b39..f63a23c98c 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -164,7 +164,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { } for i, e := range t.types { if i > 0 { - buf.WriteString("|") + buf.WriteByte('|') } if t.tilde[i] { buf.WriteByte('~') diff --git a/src/cmd/compile/internal/types2/union.go b/src/cmd/compile/internal/types2/union.go index 30570b5e80..e5e851c1d2 100644 --- a/src/cmd/compile/internal/types2/union.go +++ b/src/cmd/compile/internal/types2/union.go @@ -57,7 +57,7 @@ func (u *Union) is(f func(Type, bool) bool) bool { return true } -// is reports whether f returned true for the underlying types of all terms of u. +// underIs reports whether f returned true for the underlying types of all terms of u. func (u *Union) underIs(f func(Type) bool) bool { if u.IsEmpty() { return false -- GitLab From d2bf94fb86b45609564919caa21c6b098b5197d3 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 2 Jul 2021 16:54:14 -0700 Subject: [PATCH 0421/2500] [dev.typeparams] cmd/compile/internal/types2: replace optype() with under() in various cases (cleanup) This makes the behavior for type parameter operands explicit in those cases. Change-Id: I38438af67de4432f1a691dc4947e4576445f031b Reviewed-on: https://go-review.googlesource.com/c/go/+/332555 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/builtins.go | 8 +++++--- src/cmd/compile/internal/types2/expr.go | 6 +++--- src/cmd/compile/internal/types2/index.go | 4 ++-- src/cmd/compile/internal/types2/predicates.go | 19 +++++++++---------- .../types2/testdata/check/typeparams.go2 | 2 +- src/cmd/compile/internal/types2/typeset.go | 1 + 6 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 7ba26509e8..83d1743ee2 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -332,13 +332,15 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( return } var src Type - switch t := optype(y.typ).(type) { + switch t := under(y.typ).(type) { case *Basic: if isString(y.typ) { src = universeByte } case *Slice: src = t.elem + case *TypeParam: + check.error(x, "copy on generic operands not yet implemented") } if dst == nil || src == nil { @@ -455,12 +457,12 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( var valid func(t Type) bool valid = func(t Type) bool { var m int - switch t := optype(t).(type) { + switch t := under(t).(type) { case *Slice: m = 2 case *Map, *Chan: m = 1 - case *Union: + case *TypeParam: return t.underIs(valid) default: return false diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 1cb0ad4752..bd35417c64 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -691,7 +691,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const return nil, nil, _InvalidUntypedConversion } - switch t := optype(target).(type) { + switch t := under(target).(type) { case *Basic: if x.mode == constant_ { v, code := check.representation(x, t) @@ -723,7 +723,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const default: return nil, nil, _InvalidUntypedConversion } - case *Union: + case *TypeParam: ok := t.underIs(func(t Type) bool { target, _, _ := check.implicitTypeAndValue(x, t) return target != nil @@ -1197,7 +1197,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin goto Error } - switch utyp := optype(base).(type) { + switch utyp := under(base).(type) { case *Struct: if len(e.ElemList) == 0 { break diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index 5a4dcb4741..d3e0c71f05 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -199,7 +199,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { valid := false length := int64(-1) // valid if >= 0 - switch typ := optype(x.typ).(type) { + switch typ := under(x.typ).(type) { case *Basic: if isString(typ) { if e.Full { @@ -239,7 +239,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { valid = true // x.typ doesn't change - case *Union, *TypeParam: + case *TypeParam: check.error(x, "generic slice expressions not yet implemented") x.mode = invalid return diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 5ff7840d6f..2f10898585 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -25,10 +25,10 @@ func isGeneric(typ Type) bool { } func is(typ Type, what BasicInfo) bool { - switch t := optype(typ).(type) { + switch t := under(typ).(type) { case *Basic: return t.info&what != 0 - case *Union: + case *TypeParam: return t.underIs(func(t Type) bool { return is(t, what) }) } return false @@ -56,7 +56,7 @@ func isNumericOrString(typ Type) bool { return is(typ, IsNumeric|IsString) } // are not fully set up. func isTyped(typ Type) bool { // isTyped is called with types that are not fully - // set up. Must not call Basic()! + // set up. Must not call asBasic()! // A *Named or *instance type is always typed, so // we only need to check if we have a true *Basic // type. @@ -97,18 +97,19 @@ func comparable(T Type, seen map[Type]bool) bool { seen[T] = true // If T is a type parameter not constrained by any type - // list (i.e., it's operational type is the top type), + // (i.e., it's operational type is the top type), // T is comparable if it has the == method. Otherwise, // the operational type "wins". For instance // // interface{ comparable; type []byte } // // is not comparable because []byte is not comparable. + // TODO(gri) this code is not 100% correct (see comment for TypeSet.IsComparable) if t := asTypeParam(T); t != nil && optype(t) == theTop { return t.Bound().IsComparable() } - switch t := optype(T).(type) { + switch t := under(T).(type) { case *Basic: // assume invalid types to be comparable // to avoid follow-up errors @@ -124,24 +125,22 @@ func comparable(T Type, seen map[Type]bool) bool { return true case *Array: return comparable(t.elem, seen) - case *Union: + case *TypeParam: return t.underIs(func(t Type) bool { return comparable(t, seen) }) - case *TypeParam: - return t.Bound().IsComparable() } return false } // hasNil reports whether a type includes the nil value. func hasNil(typ Type) bool { - switch t := optype(typ).(type) { + switch t := under(typ).(type) { case *Basic: return t.kind == UnsafePointer case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan: return true - case *Union: + case *TypeParam: return t.underIs(hasNil) } return false diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 index 123567682a..8a7f6eb2c2 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 @@ -119,7 +119,7 @@ func _[T interface{ [10]int | *[20]int | []int }](x T, i int) { _ = x[i]; _ = x[ // slicing // TODO(gri) implement this -func _[T interface{ ~string }] (x T, i, j, k int) { _ = x /* ERROR invalid operation */ [i:j:k] } +func _[T interface{ ~string }] (x T, i, j, k int) { _ = x /* ERROR generic slice expressions not yet implemented */ [i:j:k] } // len/cap built-ins diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index 6ff8563974..4aee8e4097 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -28,6 +28,7 @@ func (s *TypeSet) IsTop() bool { return len(s.methods) == 0 && s.types == nil } func (s *TypeSet) IsMethodSet() bool { return s.types == nil && !s.IsComparable() } // IsComparable reports whether each type in the set is comparable. +// TODO(gri) this is not correct - there may be s.types values containing non-comparable types func (s *TypeSet) IsComparable() bool { _, m := s.LookupMethod(nil, "==") return m != nil -- GitLab From 18135150b0ce945735d242eb6259ffc9b5c767d0 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 2 Jul 2021 18:12:02 -0700 Subject: [PATCH 0422/2500] [dev.typeparams] cmd/compile/internal/types2: don't permit method calls on ptr to type parameter receivers Simplify the implementation of asInterface while at it. For #47031. Change-Id: Ie7d4fbbab898d961ed3c0b7772ba9604641be13f Reviewed-on: https://go-review.googlesource.com/c/go/+/332609 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/lookup.go | 10 ++++++---- .../internal/types2/testdata/check/issues.go2 | 10 ++++------ .../types2/testdata/fixedbugs/issue47031.go2 | 20 +++++++++++++++++++ src/cmd/compile/internal/types2/type.go | 13 ++++++------ 4 files changed, 37 insertions(+), 16 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue47031.go2 diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index d59a2f474c..91be14bde3 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -73,10 +73,12 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o typ, isPtr := deref(T) - // *typ where typ is an interface has no methods. - // Be cautious: typ may be nil (issue 39634, crash #3). - if typ == nil || isPtr && IsInterface(typ) { - return + // *typ where typ is an interface or type parameter has no methods. + switch under(typ).(type) { + case *Interface, *TypeParam: + if isPtr { + return + } } // Start with typ as single entry at shallowest depth. diff --git a/src/cmd/compile/internal/types2/testdata/check/issues.go2 b/src/cmd/compile/internal/types2/testdata/check/issues.go2 index 59dd4ae465..88ae294d7c 100644 --- a/src/cmd/compile/internal/types2/testdata/check/issues.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/issues.go2 @@ -24,22 +24,20 @@ func _() { eql[io.Reader](nil, nil) } -// If we have a receiver of pointer type (below: *T) we must ignore -// the pointer in the implementation of the method lookup because -// the type bound of T is an interface and pointer to interface types -// have no methods and then the lookup would fail. +// If we have a receiver of pointer to type parameter type (below: *T) +// we don't have any methods, like for interfaces. type C[T any] interface { m() } // using type bound C func _[T C[T]](x *T) { - x.m() + x.m /* ERROR x\.m undefined */ () } // using an interface literal as bound func _[T interface{ m() }](x *T) { - x.m() + x.m /* ERROR x\.m undefined */ () } func f2[_ interface{ m1(); m2() }]() diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47031.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47031.go2 new file mode 100644 index 0000000000..b184f9b5b7 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47031.go2 @@ -0,0 +1,20 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type Mer interface { M() } + +func F[T Mer](p *T) { + p.M /* ERROR p\.M undefined */ () +} + +type MyMer int + +func (MyMer) M() {} + +func _() { + F(new(MyMer)) + F[Mer](nil) +} diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index e3f63f63b5..c2da97605b 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -112,11 +112,6 @@ func asSignature(t Type) *Signature { return op } -func asInterface(t Type) *Interface { - op, _ := optype(t).(*Interface) - return op -} - func asMap(t Type) *Map { op, _ := optype(t).(*Map) return op @@ -127,10 +122,16 @@ func asChan(t Type) *Chan { return op } -// If the argument to asNamed and asTypeParam is of the respective types +// If the argument to asInterface, asNamed, or asTypeParam is of the respective type // (possibly after expanding an instance type), these methods return that type. // Otherwise the result is nil. +// asInterface does not need to look at optype (type sets don't contain interfaces) +func asInterface(t Type) *Interface { + u, _ := under(t).(*Interface) + return u +} + func asNamed(t Type) *Named { e, _ := expand(t).(*Named) return e -- GitLab From 988d0248b404a82d8f5c5973610e8a56bffb38f4 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Wed, 7 Jul 2021 16:27:22 -0700 Subject: [PATCH 0423/2500] [dev.fuzz] internal/fuzz: improve handling of worker termination by signal With this change, we'll no longer silently ignore terminations by SIGKILL. We use SIGKILL to terminate unresponsive workers, but it can also be delivered by the OOM killer. When a worker is terminated by a signal not apparently due to a crash or interruption (like SIGKILL or SIGHUP, as opposed to SIGSEGV), we'll log a message, but we won't record a crash, since any given input is not likely to reproduce this termination. Fixes golang/go#46576 Change-Id: I6ef18a7cf5a457c7b9bc44cf5416378271216bfd Reviewed-on: https://go-review.googlesource.com/c/go/+/333190 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod Reviewed-by: Katie Hockman TryBot-Result: Go Bot --- .../script/test_fuzz_non_crash_signal.txt | 55 +++++++++++++++++++ src/internal/fuzz/sys_posix.go | 41 +++++++++++++- src/internal/fuzz/sys_unimplemented.go | 8 +++ src/internal/fuzz/sys_windows.go | 10 ++++ src/internal/fuzz/worker.go | 8 +++ 5 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt diff --git a/src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt b/src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt new file mode 100644 index 0000000000..a67bf63c0b --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt @@ -0,0 +1,55 @@ +# NOTE: this test is skipped on Windows, since there's no concept of signals. +# When a process terminates another process, it provides an exit code. +# TODO(jayconrod): support shared memory on more platforms. +[!darwin] [!freebsd] [!linux] skip +[short] skip + +# FuzzNonCrash sends itself a signal that does not appear to be a crash. +# We should not save a crasher. +! go test -fuzz=FuzzNonCrash +! exists testdata +! stdout unreachable +! stderr unreachable +stdout 'fuzzing process terminated by unexpected signal; no crash will be recorded: signal: killed' + +# FuzzCrash sends itself a signal that looks like a crash. +# We should save a crasher. +! go test -fuzz=FuzzCrash +exists testdata/corpus/FuzzCrash +stdout 'fuzzing process terminated unexpectedly' + +-- go.mod -- +module test + +go 1.17 +-- fuzz_posix_test.go -- +// +build darwin freebsd linux + +package fuzz + +import ( + "syscall" + "testing" +) + +func FuzzNonCrash(f *testing.F) { + f.Fuzz(func(*testing.T, bool) { + pid := syscall.Getpid() + if err := syscall.Kill(pid, syscall.SIGKILL); err != nil { + panic(err) + } + // signal may not be received immediately. Wait for it. + select{} + }) +} + +func FuzzCrash(f *testing.F) { + f.Fuzz(func(*testing.T, bool) { + pid := syscall.Getpid() + if err := syscall.Kill(pid, syscall.SIGILL); err != nil { + panic(err) + } + // signal may not be received immediately. Wait for it. + select{} + }) +} diff --git a/src/internal/fuzz/sys_posix.go b/src/internal/fuzz/sys_posix.go index 8ea84d2025..2473274ecf 100644 --- a/src/internal/fuzz/sys_posix.go +++ b/src/internal/fuzz/sys_posix.go @@ -88,5 +88,44 @@ func isInterruptError(err error) bool { return false } status := exitErr.Sys().(syscall.WaitStatus) - return status.Signal() == syscall.SIGINT || status.Signal() == syscall.SIGKILL + return status.Signal() == syscall.SIGINT +} + +// terminationSignal checks if err is an exec.ExitError with a signal status. +// If it is, terminationSignal returns the signal and true. +// If not, -1 and false. +func terminationSignal(err error) (os.Signal, bool) { + exitErr, ok := err.(*exec.ExitError) + if !ok || exitErr.ExitCode() >= 0 { + return syscall.Signal(-1), false + } + status := exitErr.Sys().(syscall.WaitStatus) + return status.Signal(), status.Signaled() +} + +// isCrashSignal returns whether a signal was likely to have been caused by an +// error in the program that received it, triggered by a fuzz input. For +// example, SIGSEGV would be received after a nil pointer dereference. +// Other signals like SIGKILL or SIGHUP are more likely to have been sent by +// another process, and we shouldn't record a crasher if the worker process +// receives one of these. +// +// Note that Go installs its own signal handlers on startup, so some of these +// signals may only be received if signal handlers are changed. For example, +// SIGSEGV is normally transformed into a panic that causes the process to exit +// with status 2 if not recovered, which we handle as a crash. +func isCrashSignal(signal os.Signal) bool { + switch signal { + case + syscall.SIGILL, // illegal instruction + syscall.SIGTRAP, // breakpoint + syscall.SIGABRT, // abort() called + syscall.SIGBUS, // invalid memory access (e.g., misaligned address) + syscall.SIGFPE, // math error, e.g., integer divide by zero + syscall.SIGSEGV, // invalid memory access (e.g., write to read-only) + syscall.SIGPIPE: // sent data to closed pipe or socket + return true + default: + return false + } } diff --git a/src/internal/fuzz/sys_unimplemented.go b/src/internal/fuzz/sys_unimplemented.go index 5f80379c22..827e36cf32 100644 --- a/src/internal/fuzz/sys_unimplemented.go +++ b/src/internal/fuzz/sys_unimplemented.go @@ -34,3 +34,11 @@ func getWorkerComm() (comm workerComm, err error) { func isInterruptError(err error) bool { panic("not implemented") } + +func terminationSignal(err error) (os.Signal, bool) { + panic("not implemented") +} + +func isCrashSignal(signal os.Signal) bool { + panic("not implemented") +} diff --git a/src/internal/fuzz/sys_windows.go b/src/internal/fuzz/sys_windows.go index 286501bc10..fabf954ba7 100644 --- a/src/internal/fuzz/sys_windows.go +++ b/src/internal/fuzz/sys_windows.go @@ -140,3 +140,13 @@ func isInterruptError(err error) bool { // returned by Wait. It looks like an ExitError with status 1. return false } + +// terminationSignal returns -1 and false because Windows doesn't have signals. +func terminationSignal(err error) (os.Signal, bool) { + return syscall.Signal(-1), false +} + +// isCrashSignal is not implemented because Windows doesn't have signals. +func isCrashSignal(signal os.Signal) bool { + panic("not implemented: no signals on windows") +} diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index e1fc999104..c3f4d74302 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -160,6 +160,14 @@ func (w *worker) coordinate(ctx context.Context) error { // Since we expect I/O errors around interrupts, ignore this error. return nil } + if sig, ok := terminationSignal(w.waitErr); ok && !isCrashSignal(sig) { + // Worker terminated by a signal that probably wasn't caused by a + // specific input to the fuzz function. For example, on Linux, + // the kernel (OOM killer) may send SIGKILL to a process using a lot + // of memory. Or the shell might send SIGHUP when the terminal + // is closed. Don't record a crasher. + return fmt.Errorf("fuzzing process terminated by unexpected signal; no crash will be recorded: %v", w.waitErr) + } // Unexpected termination. Set error message and fall through. // We'll restart the worker on the next iteration. resp.Err = fmt.Sprintf("fuzzing process terminated unexpectedly: %v", w.waitErr) -- GitLab From d4f6d161e439b3c2a56a4583d4b5acebe3fdeeee Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 7 Jul 2021 11:49:57 -0700 Subject: [PATCH 0424/2500] [dev.typeparams] cmd/compile: fix bunch of -G=3 bugs for test cases in test/typeparams/mdempsky 1.go, 12.go: similar to calculating type sizes, we delay computing instantiations during import until we get up to a top-level type, in order to make sure recursive types are complete. But we should always delay calculating sizes when we delay instantiating types, since otherwise we may try to calculate the size of an incomplete type. So, needed to add Defer/ResumeCheckSize in (*importReader).typ where we also defer instantiations. (iimport.go) 2.go: when doing type substition, we have to handle named, parameterized basic types i.e. the type has a type parameter even though the underlying type is a basic type that doesn't depend on the parameter. (subr.go) 3.go: for go 1.18, we allow arbitrary types in interfaces. We had already allowed union types and tilde types, but didn't allow regular non-interface types in Go 1.17 for compatibility. Just skip an error in the case of 1.18. (size.go) 5.go: types2 and types1 differ in how they print out interfaces. types1 puts a space between "interface" and "{", types2 does not. So, since some typenames come from types2 and some from types1, we need to remove the space when printing out type arguments. (iimport.go/subr.go) 9.go: in subst.node(), we were missing the KeyExpr case where a node has no type. The assertion is just there, to make sure we understand all the cases where there is no type to translate. We could just remove the whole error check. (stencil.go) 13.go: in subst.node(), missed handling the case where a method expression is immediate called (which of course, is quite unusual, since then there's no real reason to have used the method expression syntax in that case). Just needed to add ir.OMETHEXPR in the OCALL switch statement. (stencil.go) Change-Id: I202cbe9541dfafe740e3b84b44982d6181738ea0 Reviewed-on: https://go-review.googlesource.com/c/go/+/333165 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 5 +++-- src/cmd/compile/internal/typecheck/iimport.go | 8 +++++++- src/cmd/compile/internal/typecheck/subr.go | 10 +++++++++- src/cmd/compile/internal/types/size.go | 7 +++++-- test/run.go | 11 ++--------- 5 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index ce9dc09bc3..d292bfd5c6 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1026,7 +1026,8 @@ func (subst *subster) node(n ir.Node) ir.Node { // an error. _, isCallExpr := m.(*ir.CallExpr) _, isStructKeyExpr := m.(*ir.StructKeyExpr) - if !isCallExpr && !isStructKeyExpr && x.Op() != ir.OPANIC && + _, isKeyExpr := m.(*ir.KeyExpr) + if !isCallExpr && !isStructKeyExpr && !isKeyExpr && x.Op() != ir.OPANIC && x.Op() != ir.OCLOSE { base.Fatalf(fmt.Sprintf("Nil type for %v", x)) } @@ -1136,7 +1137,7 @@ func (subst *subster) node(n ir.Node) ir.Node { } } - case ir.OMETHVALUE: + case ir.OMETHVALUE, ir.OMETHEXPR: // Redo the transformation of OXDOT, now that we // know the method value is being called. Then // transform the call. diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 7b7cd7f148..4a97267f05 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -567,9 +567,11 @@ func (r *importReader) pos() src.XPos { func (r *importReader) typ() *types.Type { // If this is a top-level type call, defer type instantiations until the // type is fully constructed. + types.DeferCheckSize() deferDoInst() t := r.p.typAt(r.uint64()) resumeDoInst() + types.ResumeCheckSize() return t } @@ -1738,7 +1740,11 @@ func InstTypeName(name string, targs []*types.Type) string { b.WriteString(targ.Sym().Pkg.Name) b.WriteByte('.') } - b.WriteString(targ.String()) + // types1 uses "interface {" and types2 uses "interface{" - convert + // to consistent types2 format. + tstring := targ.String() + tstring = strings.Replace(tstring, "interface {", "interface{", -1) + b.WriteString(tstring) } b.WriteByte(']') return b.String() diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index db1faaf6f7..d9e6612dfc 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -931,7 +931,11 @@ func makeGenericName(name string, targs []*types.Type, hasBrackets bool) string b.WriteString(targ.Sym().Pkg.Name) b.WriteByte('.') } - b.WriteString(targ.String()) + // types1 uses "interface {" and types2 uses "interface{" - convert + // to consistent types2 format. + tstring := targ.String() + tstring = strings.Replace(tstring, "interface {", "interface{", -1) + b.WriteString(tstring) } b.WriteString("]") if i >= 0 { @@ -1163,6 +1167,10 @@ func (ts *Tsubster) Typ(t *types.Type) *types.Type { } else { assert(false) } + case types.TINT, types.TINT8, types.TINT16, types.TINT32, types.TINT64, + types.TUINT, types.TUINT8, types.TUINT16, types.TUINT32, types.TUINT64, + types.TUINTPTR, types.TBOOL, types.TSTRING: + newt = t.Underlying() } if newt == nil { // Even though there were typeparams in the type, there may be no diff --git a/src/cmd/compile/internal/types/size.go b/src/cmd/compile/internal/types/size.go index f5a74f83b3..89391ade68 100644 --- a/src/cmd/compile/internal/types/size.go +++ b/src/cmd/compile/internal/types/size.go @@ -128,9 +128,12 @@ func expandiface(t *Type) { continue } - // Once we go to 1.18, then embedded types can be anything, but - // for now, just interfaces and unions. + // In 1.18, embedded types can be anything. In Go 1.17, we disallow + // embedding anything other than interfaces. if !m.Type.IsInterface() { + if AllowsGoVersion(t.Pkg(), 1, 18) { + continue + } base.ErrorfAt(m.Pos, "interface contains embedded non-interface, non-union %v", m.Type) m.SetBroke(true) t.SetBroke(true) diff --git a/test/run.go b/test/run.go index 0251dc1c6a..90861786df 100644 --- a/test/run.go +++ b/test/run.go @@ -2204,15 +2204,8 @@ var g3Failures = setOf( "typeparam/nested.go", // -G=3 doesn't support function-local types with generics - "typeparam/mdempsky/1.go", - "typeparam/mdempsky/2.go", - "typeparam/mdempsky/3.go", - "typeparam/mdempsky/4.go", - "typeparam/mdempsky/5.go", - "typeparam/mdempsky/9.go", - "typeparam/mdempsky/11.go", - "typeparam/mdempsky/12.go", - "typeparam/mdempsky/13.go", + "typeparam/mdempsky/4.go", // -G=3 can't export functions with labeled breaks in loops + "typeparam/mdempsky/11.go", // types2/noder2 should give conversion error, because of "notinheap" mismatch ) var unifiedFailures = setOf( -- GitLab From 42fe1327878dc0956d2c6407a54112fa5e75bd34 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 7 Jul 2021 16:15:53 -0700 Subject: [PATCH 0425/2500] [dev.typeparams] cmd/compile: cleanup ABI utils tests This CL cleans a few minor nits with the ABI utils tests that are now necessary because of cleanups that happened on master: 1. Initialize types.LocalPkg; this needs to be set for selector names to be handled correctly. 2. In TestABIUtilsInterfaces, switch to using an exported identifier, so it doesn't need to be package qualified. 3. While here, change the method result type from "untyped string" to just "string". Constants are the only declared object that can ever have an untyped type. Change-Id: Iabed46594361a516317a1c2d20c3d59bdb519844 Reviewed-on: https://go-review.googlesource.com/c/go/+/333189 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/compile/internal/test/abiutils_test.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/cmd/compile/internal/test/abiutils_test.go b/src/cmd/compile/internal/test/abiutils_test.go index b7901be69b..839546bcb8 100644 --- a/src/cmd/compile/internal/test/abiutils_test.go +++ b/src/cmd/compile/internal/test/abiutils_test.go @@ -33,6 +33,8 @@ func TestMain(m *testing.M) { base.Ctxt.DiagFunc = base.Errorf base.Ctxt.DiagFlush = base.FlushErrors base.Ctxt.Bso = bufio.NewWriter(os.Stdout) + types.LocalPkg = types.NewPkg("", "local") + types.LocalPkg.Prefix = `""` types.PtrSize = ssagen.Arch.LinkArch.PtrSize types.RegSize = ssagen.Arch.LinkArch.RegSize typecheck.InitUniverse() @@ -309,8 +311,8 @@ func TestABIUtilsInterfaces(t *testing.T) { ei := types.Types[types.TINTER] // interface{} pei := types.NewPtr(ei) // *interface{} fldt := mkFuncType(types.FakeRecvType(), []*types.Type{}, - []*types.Type{types.UntypedString}) - field := types.NewField(src.NoXPos, typecheck.Lookup("f"), fldt) + []*types.Type{types.Types[types.TSTRING]}) + field := types.NewField(src.NoXPos, typecheck.Lookup("F"), fldt) nei := types.NewInterface(types.LocalPkg, []*types.Field{field}) i16 := types.Types[types.TINT16] tb := types.Types[types.TBOOL] @@ -322,12 +324,12 @@ func TestABIUtilsInterfaces(t *testing.T) { IN 0: R{ I0 I1 I2 } spilloffset: 0 typ: struct { int16; int16; bool } IN 1: R{ I3 I4 } spilloffset: 8 typ: interface {} IN 2: R{ I5 I6 } spilloffset: 24 typ: interface {} - IN 3: R{ I7 I8 } spilloffset: 40 typ: interface { .f() untyped string } + IN 3: R{ I7 I8 } spilloffset: 40 typ: interface { F() string } IN 4: R{ } offset: 0 typ: *interface {} - IN 5: R{ } offset: 8 typ: interface { .f() untyped string } + IN 5: R{ } offset: 8 typ: interface { F() string } IN 6: R{ } offset: 24 typ: int16 OUT 0: R{ I0 I1 } spilloffset: -1 typ: interface {} - OUT 1: R{ I2 I3 } spilloffset: -1 typ: interface { .f() untyped string } + OUT 1: R{ I2 I3 } spilloffset: -1 typ: interface { F() string } OUT 2: R{ I4 } spilloffset: -1 typ: *interface {} offsetToSpillArea: 32 spillAreaSize: 56 `) -- GitLab From 04acb8a7b9fc0212687cc25aa2598d12f6aceb74 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Thu, 8 Jul 2021 12:07:01 -0700 Subject: [PATCH 0426/2500] [dev.typeparams] cmd/compile: report mismatch between types because of //go:notinheap types2 currently ignores pragmas, so it does not catch a conversion error when converting a pointer to a type which is NOT marked notinheap to a pointer to a convertible type, but which is marked notinheap. So, we specifically check for this error in transformConv() and report it during noder2. Change-Id: I6e9c9ee29f53fa5e490c1ac8306e2191db59eeb4 Reviewed-on: https://go-review.googlesource.com/c/go/+/333369 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Robert Griesemer Trust: Robert Griesemer Trust: Dan Scales --- src/cmd/compile/internal/noder/irgen.go | 4 ++++ src/cmd/compile/internal/noder/transform.go | 10 +++++++++- test/run.go | 3 +-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index 64c29435b5..880073a89e 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -219,6 +219,10 @@ Outer: } } + // Check for unusual case where noder2 encounters a type error that types2 + // doesn't check for (e.g. notinheap incompatibility). + base.ExitIfErrors() + typecheck.DeclareUniverse() for _, p := range noders { diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index e02b7e758d..efbc8f68ce 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -85,7 +85,15 @@ func stringtoruneslit(n *ir.ConvExpr) ir.Node { // etc. Corresponds to typecheck.tcConv. func transformConv(n *ir.ConvExpr) ir.Node { t := n.X.Type() - op, _ := typecheck.Convertop(n.X.Op() == ir.OLITERAL, t, n.Type()) + op, why := typecheck.Convertop(n.X.Op() == ir.OLITERAL, t, n.Type()) + if op == ir.OXXX { + // types2 currently ignores pragmas, so a 'notinheap' mismatch is the + // one type-related error that it does not catch. This error will be + // caught here by Convertop (see two checks near beginning of + // Convertop) and reported at the end of noding. + base.ErrorfAt(n.Pos(), "cannot convert %L to type %v%s", n.X, n.Type(), why) + return n + } n.SetOp(op) switch n.Op() { case ir.OCONVNOP: diff --git a/test/run.go b/test/run.go index 90861786df..d6209c2591 100644 --- a/test/run.go +++ b/test/run.go @@ -2204,8 +2204,7 @@ var g3Failures = setOf( "typeparam/nested.go", // -G=3 doesn't support function-local types with generics - "typeparam/mdempsky/4.go", // -G=3 can't export functions with labeled breaks in loops - "typeparam/mdempsky/11.go", // types2/noder2 should give conversion error, because of "notinheap" mismatch + "typeparam/mdempsky/4.go", // -G=3 can't export functions with labeled breaks in loops ) var unifiedFailures = setOf( -- GitLab From 69d945fc6e80475c163f96ba86fe716e77bb0104 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 7 Jul 2021 21:38:49 -0700 Subject: [PATCH 0427/2500] [dev.typeparams] cmd/compile/internal/types2: use scope numbers to identify local types Rather than using a local types' position information, use the type name's scope numbers to uniquely identify the type from others with the same name. We use scope numbers rather than indices (with number-1 == index) to preserve the invariant that the zero value for a scope is a ready to use empty scope. Using scope numbers turned out to be fairly simple after all and provides a reasonably stable identification which will make debugging simpler. A scope number series may be a bit longer than a unique ID for each type name but local types should be reasonably rare. Also did a minor cleanup in universe.go to ensure Named.orig is set up correctly (there's still an open TODO but with a work-around). Change-Id: I73935fa9bd960809fd5c95fe8b8a535c313cfc8f Reviewed-on: https://go-review.googlesource.com/c/go/+/333192 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley TryBot-Result: Go Bot --- src/cmd/compile/internal/types2/instance.go | 2 +- src/cmd/compile/internal/types2/scope.go | 4 ++- .../compile/internal/types2/sizeof_test.go | 2 +- src/cmd/compile/internal/types2/subst.go | 2 -- src/cmd/compile/internal/types2/typestring.go | 29 +++++++++++-------- src/cmd/compile/internal/types2/universe.go | 12 +++++--- 6 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/cmd/compile/internal/types2/instance.go b/src/cmd/compile/internal/types2/instance.go index 9d6097e874..b133fd1e65 100644 --- a/src/cmd/compile/internal/types2/instance.go +++ b/src/cmd/compile/internal/types2/instance.go @@ -16,7 +16,7 @@ type instance struct { base *Named // parameterized type to be instantiated targs []Type // type arguments poslist []syntax.Pos // position of each targ; for error reporting only - value Type // base(targs...) after instantiation or Typ[Invalid]; nil if not yet set + value Type // base[targs...] after instantiation or Typ[Invalid]; nil if not yet set } // expand returns the instantiated (= expanded) type of t. diff --git a/src/cmd/compile/internal/types2/scope.go b/src/cmd/compile/internal/types2/scope.go index 2f1814a631..095875d94b 100644 --- a/src/cmd/compile/internal/types2/scope.go +++ b/src/cmd/compile/internal/types2/scope.go @@ -23,6 +23,7 @@ import ( type Scope struct { parent *Scope children []*Scope + number int // parent.children[number-1] is this scope; 0 if there is no parent elems map[string]Object // lazily allocated pos, end syntax.Pos // scope extent; may be invalid comment string // for debugging only @@ -32,10 +33,11 @@ type Scope struct { // NewScope returns a new, empty scope contained in the given parent // scope, if any. The comment is for debugging only. func NewScope(parent *Scope, pos, end syntax.Pos, comment string) *Scope { - s := &Scope{parent, nil, nil, pos, end, comment, false} + s := &Scope{parent, nil, 0, nil, pos, end, comment, false} // don't add children to Universe scope! if parent != nil && parent != Universe { parent.children = append(parent.children, s) + s.number = len(parent.children) } return s } diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go index 0b1f7dacad..a51d0c43d5 100644 --- a/src/cmd/compile/internal/types2/sizeof_test.go +++ b/src/cmd/compile/internal/types2/sizeof_test.go @@ -47,7 +47,7 @@ func TestSizeof(t *testing.T) { {Nil{}, 56, 88}, // Misc - {Scope{}, 56, 96}, + {Scope{}, 60, 104}, {Package{}, 40, 80}, {TypeSet{}, 20, 40}, } diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 7b4796fa2e..59efe8a045 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -422,8 +422,6 @@ func (subst *subster) typ(typ Type) Type { var instanceHashing = 0 -// TODO(gri) Eventually, this should be more sophisticated. -// It won't work correctly for locally declared types. func instantiatedHash(typ *Named, targs []Type) string { assert(instanceHashing == 0) instanceHashing++ diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index f63a23c98c..44099133a0 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -363,22 +363,27 @@ func writeTypeName(buf *bytes.Buffer, obj *TypeName, qf Qualifier) { buf.WriteString(obj.name) if instanceHashing != 0 { - // For local defined types, use the (original!) TypeName's position - // to disambiguate. This is overkill, and could probably instead - // just be the pointer value (if we assume a non-moving GC) or - // a unique ID (like cmd/compile uses). But this works for now, - // and is convenient for debugging. - - // TODO(mdempsky): I still don't fully understand why typ.orig.orig - // can differ from typ.orig, or whether looping more than twice is - // ever necessary. + // For local defined types, use the (original!) TypeName's scope + // numbers to disambiguate. typ := obj.typ.(*Named) + // TODO(gri) Figure out why typ.orig != typ.orig.orig sometimes + // and whether the loop can iterate more than twice. + // (It seems somehow connected to instance types.) for typ.orig != typ { typ = typ.orig } - if orig := typ.obj; orig.pkg != nil && orig.parent != orig.pkg.scope { - fmt.Fprintf(buf, "@%q", orig.pos) - } + writeScopeNumbers(buf, typ.obj.parent) + } +} + +// writeScopeNumbers writes the number sequence for this scope to buf +// in the form ".i.j.k" where i, j, k, etc. stand for scope numbers. +// If a scope is nil or has no parent (such as a package scope), nothing +// is written. +func writeScopeNumbers(buf *bytes.Buffer, s *Scope) { + if s != nil && s.number > 0 { + writeScopeNumbers(buf, s.parent) + fmt.Fprintf(buf, ".%d", s.number) } } diff --git a/src/cmd/compile/internal/types2/universe.go b/src/cmd/compile/internal/types2/universe.go index c9b53bac92..d328b13a8e 100644 --- a/src/cmd/compile/internal/types2/universe.go +++ b/src/cmd/compile/internal/types2/universe.go @@ -86,21 +86,25 @@ func defPredeclaredTypes() { // type error interface{ Error() string } { + obj := NewTypeName(nopos, nil, "error", nil) + obj.setColor(black) res := NewVar(nopos, nil, "", Typ[String]) sig := NewSignature(nil, nil, NewTuple(res), false) err := NewFunc(nopos, nil, "Error", sig) - typ := &Named{underlying: NewInterfaceType([]*Func{err}, nil)} + typ := NewNamed(obj, NewInterfaceType([]*Func{err}, nil), nil) sig.recv = NewVar(nopos, nil, "", typ) - def(NewTypeName(nopos, nil, "error", typ)) + def(obj) } // type comparable interface{ ==() } { + obj := NewTypeName(nopos, nil, "comparable", nil) + obj.setColor(black) sig := NewSignature(nil, nil, nil, false) eql := NewFunc(nopos, nil, "==", sig) - typ := &Named{underlying: NewInterfaceType([]*Func{eql}, nil)} + typ := NewNamed(obj, NewInterfaceType([]*Func{eql}, nil), nil) sig.recv = NewVar(nopos, nil, "", typ) - def(NewTypeName(nopos, nil, "comparable", typ)) + def(obj) } } -- GitLab From f2ed30c31edf67bd753a10891dfeb5aeb65c95dd Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 8 Jul 2021 19:57:24 -0700 Subject: [PATCH 0428/2500] [dev.typeparams] cmd/compile/internal/types2: recursive substitution must terminate (bug fix) When types2.Instantiate is called externally, no *Checker is provided and substitution doesn't have access to Checker.typMap; and instantiation of recursive generic types leads to an infinite recursion in subst. There was a local subster.cache but it was only set and never used. Replaced subster.cache with subster.typMap, which is set to the global Checker.typMap if available, and set to a local map otherwise. This prevents such infinite recursions. Added a simple test. More generally, because we don't have a global type map for external instantiations, instantiating the same type twice, independently but with the same type arguments, will result in two different types. This is not correct. We need to provide some form of context for external instantiations (which means the importers). This is a separate but related issue which is not yet addressed (filed #47103). Change-Id: I541556c677db54f7396fd0c88c7467894dfcf2e7 Reviewed-on: https://go-review.googlesource.com/c/go/+/333383 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/api_test.go | 23 +++++++++++++ src/cmd/compile/internal/types2/subst.go | 38 ++++++++++++--------- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index c7f3e490aa..1c535387d4 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -1846,3 +1846,26 @@ func f(x T) T { return foo.F(x) } } } } + +func TestInstantiate(t *testing.T) { + // eventually we like more tests but this is a start + const src = genericPkg + "p; type T[P any] *T[P]" + pkg, err := pkgFor(".", src, nil) + if err != nil { + t.Fatal(err) + } + + // type T should have one type parameter + T := pkg.Scope().Lookup("T").Type().(*Named) + if n := len(T.TParams()); n != 1 { + t.Fatalf("expected 1 type parameter; found %d", n) + } + + // instantiation should succeed (no endless recursion) + res := Instantiate(nopos, T, []Type{Typ[Int]}) + + // instantiated type should point to itself + if res.Underlying().(*Pointer).Elem() != res { + t.Fatalf("unexpected result type: %s", res) + } +} diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 59efe8a045..6e4e778b20 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -233,15 +233,27 @@ func (check *Checker) subst(pos syntax.Pos, typ Type, smap *substMap) Type { } // general case - subst := subster{check, pos, make(map[Type]Type), smap} + var subst subster + subst.pos = pos + subst.smap = smap + if check != nil { + subst.check = check + subst.typMap = check.typMap + } else { + // If we don't have a *Checker and its global type map, + // use a local version. Besides avoiding duplicate work, + // the type map prevents infinite recursive substitution + // for recursive types (example: type T[P any] *T[P]). + subst.typMap = make(map[string]*Named) + } return subst.typ(typ) } type subster struct { - check *Checker - pos syntax.Pos - cache map[Type]Type - smap *substMap + pos syntax.Pos + smap *substMap + check *Checker // nil if called via Instantiate + typMap map[string]*Named } func (subst *subster) typ(typ Type) Type { @@ -382,22 +394,16 @@ func (subst *subster) typ(typ Type) Type { // before creating a new named type, check if we have this one already h := instantiatedHash(t, new_targs) dump(">>> new type hash: %s", h) - if subst.check != nil { - if named, found := subst.check.typMap[h]; found { - dump(">>> found %s", named) - subst.cache[t] = named - return named - } + if named, found := subst.typMap[h]; found { + dump(">>> found %s", named) + return named } - // create a new named type and populate caches to avoid endless recursion + // create a new named type and populate typMap to avoid endless recursion tname := NewTypeName(subst.pos, t.obj.pkg, t.obj.name, nil) named := subst.check.newNamed(tname, t, t.Underlying(), t.TParams(), t.methods) // method signatures are updated lazily named.targs = new_targs - if subst.check != nil { - subst.check.typMap[h] = named - } - subst.cache[t] = named + subst.typMap[h] = named // do the substitution dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, new_targs) -- GitLab From 5059aed9dd33e35d3d0d88be945b2aed8265e1c3 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 9 Jul 2021 11:15:23 -0700 Subject: [PATCH 0429/2500] [dev.typeparams] internal/buildcfg: allow regabiwrappers on all GOARCH There's nothing GOARCH-specific about ABI wrappers, so allow enabling them on all architectures. For unified IR, I want to have a testing mode where we add dictionary parameters even to non-generic functions, as a way to help stress test that they're handled correctly. This requires callers to know to supply the appropriate dictionary arguments when calling them. Calls generated by the Go compiler know to do this, but calls written in assembly won't. Reusing the regabi wrappers is a convenient choke-point for inserting dictionary arguments for assembly calls. Change-Id: Ic2c06b7626730289c5405829b61653d1daec430b Reviewed-on: https://go-review.googlesource.com/c/go/+/333453 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/internal/buildcfg/exp.go | 1 - 1 file changed, 1 deletion(-) diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go index 6e8bf30743..0245574ec1 100644 --- a/src/internal/buildcfg/exp.go +++ b/src/internal/buildcfg/exp.go @@ -111,7 +111,6 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (flags, baseline goexperiment } // regabi is only supported on amd64 and arm64. if goarch != "amd64" && goarch != "arm64" { - flags.RegabiWrappers = false flags.RegabiReflect = false flags.RegabiArgs = false } -- GitLab From a12ad271195d88ffa8f68ad01547560fb4d2ab49 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 7 Jul 2021 23:32:49 -0700 Subject: [PATCH 0430/2500] [dev.typeparams] cmd/compile: report functions declared in Go and assembly This CL reuses the symabi wrapper information to warn when a function is defined both in Go (i.e., has a function declaration with a body) and in assembly (i.e., has a TEXT instruction). This will eventually produce a linker error anyway, but we can provide a slightly nicer error message earlier. Change-Id: Ia107f813343c0b10f4cd1013e7c72e67149ee52e Reviewed-on: https://go-review.googlesource.com/c/go/+/333454 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/compile/internal/ssagen/abi.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cmd/compile/internal/ssagen/abi.go b/src/cmd/compile/internal/ssagen/abi.go index e460adaf95..6d8c53e722 100644 --- a/src/cmd/compile/internal/ssagen/abi.go +++ b/src/cmd/compile/internal/ssagen/abi.go @@ -152,6 +152,9 @@ func (s *SymABIs) GenABIWrappers() { // Apply definitions. defABI, hasDefABI := s.defs[symName] if hasDefABI { + if len(fn.Body) != 0 { + base.ErrorfAt(fn.Pos(), "%v defined in both Go and assembly", fn) + } fn.ABI = defABI } -- GitLab From 3c3c1d8d2856e7859f4ba36b19c91f1538546d2a Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 9 Jul 2021 17:47:15 -0700 Subject: [PATCH 0431/2500] [dev.typeparams] cmd/compile: more incremental typecheck for unified IR CL 332469 changed the unified IR reader to incrementally typecheck each statement as they're read/constructed. This CL goes further to incrementally typecheck each expression. While here, this CL reorganizes a few things to make this go more smoothly. In particular, it renames expr to expr0 and adds a new expr wrapper that applies typecheck.Expr; gets rid of exprTypeSwitchguard by moving that logic into switchStmt; and splits exprConvert out from exprCall, which simplifies the logic for typechecking the calleee expression somewhat. Change-Id: I6289de9388dc94a947971f4b7213aafeb2faa5dc Reviewed-on: https://go-review.googlesource.com/c/go/+/333730 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Matthew Dempsky Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/noder/codes.go | 4 +-- src/cmd/compile/internal/noder/reader.go | 43 ++++++++++++++++++------ src/cmd/compile/internal/noder/writer.go | 34 +++++++++++++------ 3 files changed, 57 insertions(+), 24 deletions(-) diff --git a/src/cmd/compile/internal/noder/codes.go b/src/cmd/compile/internal/noder/codes.go index 4a6a4e8307..f8cb7729ac 100644 --- a/src/cmd/compile/internal/noder/codes.go +++ b/src/cmd/compile/internal/noder/codes.go @@ -107,9 +107,7 @@ const ( exprUnaryOp exprBinaryOp exprCall - - // TODO(mdempsky): Handle in switchStmt directly instead. - exprTypeSwitchGuard + exprConvert ) type codeDecl int diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 122bc70f24..19e51d9eba 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -1252,7 +1252,7 @@ func (r *reader) assignList() ([]*ir.Name, []ir.Node) { continue } - lhs[i] = r.expr() + lhs[i] = typecheck.AssignExpr(r.expr0()) } return names, lhs @@ -1351,7 +1351,21 @@ func (r *reader) switchStmt(label *types.Sym) ir.Node { r.openScope() pos := r.pos() init := r.stmt() - tag := r.expr() + + var tag ir.Node + if r.bool() { + pos := r.pos() + var ident *ir.Ident + if r.bool() { + pos := r.pos() + sym := typecheck.Lookup(r.string()) + ident = ir.NewIdent(pos, sym) + } + x := r.expr() + tag = ir.NewTypeSwitchGuard(pos, ident, x) + } else { + tag = r.expr() + } tswitch, ok := tag.(*ir.TypeSwitchGuard) if ok && tswitch.Tag == nil { @@ -1432,7 +1446,19 @@ func (r *reader) initDefn(defn ir.InitNode, names []*ir.Name) bool { // @@@ Expressions +// expr reads and returns a typechecked expression. func (r *reader) expr() ir.Node { + n := r.expr0() + if n == nil || n.Op() == ir.OTYPE { + // TODO(mdempsky): Push this responsibility up to callers? + return n + } + return typecheck.Expr(n) +} + +// expr0 reads and returns an expression, possibly untypechecked. +// The caller must typecheck the result as appropriate for its context. +func (r *reader) expr0() ir.Node { switch tag := codeExpr(r.code(syncExpr)); tag { default: panic("unhandled expression") @@ -1522,22 +1548,17 @@ func (r *reader) expr() ir.Node { return ir.NewBinaryExpr(pos, op, x, y) case exprCall: - fun := r.expr() + fun := typecheck.Callee(r.expr0()) pos := r.pos() args := r.exprs() dots := r.bool() return typecheck.Call(pos, fun, args, dots) - case exprTypeSwitchGuard: + case exprConvert: + typ := r.typ() pos := r.pos() - var tag *ir.Ident - if r.bool() { - pos := r.pos() - sym := typecheck.Lookup(r.string()) - tag = ir.NewIdent(pos, sym) - } x := r.expr() - return ir.NewTypeSwitchGuard(pos, tag, x) + return ir.NewConvExpr(pos, ir.OCONV, typ, x) } } diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 6348a56741..3f9310514a 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -1033,7 +1033,17 @@ func (w *writer) switchStmt(stmt *syntax.SwitchStmt) { w.openScope(stmt.Pos()) w.pos(stmt) w.stmt(stmt.Init) - w.expr(stmt.Tag) + + if guard, ok := stmt.Tag.(*syntax.TypeSwitchGuard); w.bool(ok) { + w.pos(guard) + if tag := guard.Lhs; w.bool(tag != nil) { + w.pos(tag) + w.string(tag.Value) + } + w.expr(guard.X) + } else { + w.expr(stmt.Tag) + } w.len(len(stmt.Body)) for i, clause := range stmt.Body { @@ -1207,6 +1217,19 @@ func (w *writer) expr(expr syntax.Expr) { w.expr(expr.Y) case *syntax.CallExpr: + tv, ok := w.p.info.Types[expr.Fun] + assert(ok) + if tv.IsType() { + assert(len(expr.ArgList) == 1) + assert(!expr.HasDots) + + w.code(exprConvert) + w.typ(tv.Type) + w.pos(expr) + w.expr(expr.ArgList[0]) + break + } + w.code(exprCall) if inf, ok := w.p.info.Inferred[expr]; ok { @@ -1223,15 +1246,6 @@ func (w *writer) expr(expr syntax.Expr) { w.pos(expr) w.exprs(expr.ArgList) w.bool(expr.HasDots) - - case *syntax.TypeSwitchGuard: - w.code(exprTypeSwitchGuard) - w.pos(expr) - if tag := expr.Lhs; w.bool(tag != nil) { - w.pos(tag) - w.string(tag.Value) - } - w.expr(expr.X) } } -- GitLab From 0dcab98fd829e845a83fed996025f96b8b1165b1 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 9 Jul 2021 19:47:45 -0700 Subject: [PATCH 0432/2500] [dev.typeparams] cmd/compile: slightly more incremental unified typecheck This CL pushes the typecheck.Expr calls further down to the IR construction points. It turns out we don't really care about typecheck.AssignExpr, because it's only used to distinguish whether ir.BlankNode is allowed. We can avoid that issue by just skipping the call to typecheck.Expr for blank nodes. Similarly, for typecheck.Callee, only two details matter: (1) don't report errors for builtin functions (which aren't allowed outside of callee contexts); and (2) method-value selector expressions need to have Op ODOTMETH/ODOTINTER rather than OMETHVALUE. The first can be handled by simply skipping typecheck on Names (as with ir.BlankNode, we don't need to typecheck these). The second currently requires adding a 'callee bool' parameter to disambiguate the context. The other option would be for exprCall to reset the fun's Op from OMETHVALUE to OXDOT and let typecheck handle it a second time. But I anticipate needing to add extra logic in the exprSelector case which would be harder to undo, so this seems somewhat better. Change-Id: I1a8dfb6af04265ab466fd7f4cb6ee8b479e92282 Reviewed-on: https://go-review.googlesource.com/c/go/+/333769 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le Trust: Matthew Dempsky --- src/cmd/compile/internal/noder/reader.go | 76 +++++++++++++----------- src/cmd/compile/internal/noder/writer.go | 31 +++++++--- 2 files changed, 64 insertions(+), 43 deletions(-) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 19e51d9eba..25aac6c026 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -1252,7 +1252,7 @@ func (r *reader) assignList() ([]*ir.Name, []ir.Node) { continue } - lhs[i] = typecheck.AssignExpr(r.expr0()) + lhs[i] = r.expr() } return names, lhs @@ -1447,18 +1447,13 @@ func (r *reader) initDefn(defn ir.InitNode, names []*ir.Name) bool { // @@@ Expressions // expr reads and returns a typechecked expression. -func (r *reader) expr() ir.Node { - n := r.expr0() - if n == nil || n.Op() == ir.OTYPE { - // TODO(mdempsky): Push this responsibility up to callers? - return n - } - return typecheck.Expr(n) -} +func (r *reader) expr() (res ir.Node) { + defer func() { + if res != nil && res.Typecheck() == 0 { + base.FatalfAt(res.Pos(), "%v missed typecheck", res) + } + }() -// expr0 reads and returns an expression, possibly untypechecked. -// The caller must typecheck the result as appropriate for its context. -func (r *reader) expr0() ir.Node { switch tag := codeExpr(r.code(syncExpr)); tag { default: panic("unhandled expression") @@ -1467,23 +1462,30 @@ func (r *reader) expr0() ir.Node { return nil case exprBlank: - return ir.BlankNode + // blank only allowed in LHS of assignments + // TODO(mdempsky): Handle directly in assignList instead? + return typecheck.AssignExpr(ir.BlankNode) case exprLocal: - return r.useLocal() + return typecheck.Expr(r.useLocal()) case exprName: - return r.obj() + // Callee instead of Expr allows builtins + // TODO(mdempsky): Handle builtins directly in exprCall, like method calls? + return typecheck.Callee(r.obj()) case exprType: - return ir.TypeNode(r.typ()) + // TODO(mdempsky): ir.TypeNode should probably return a typecheck'd node. + n := ir.TypeNode(r.typ()) + n.SetTypecheck(1) + return n case exprConst: pos := r.pos() typ, val := r.value() op := r.op() orig := r.string() - return OrigConst(pos, typ, val, op, orig) + return typecheck.Expr(OrigConst(pos, typ, val, op, orig)) case exprCompLit: return r.compLit() @@ -1495,13 +1497,13 @@ func (r *reader) expr0() ir.Node { x := r.expr() pos := r.pos() _, sym := r.selector() - return ir.NewSelectorExpr(pos, ir.OXDOT, x, sym) + return typecheck.Expr(ir.NewSelectorExpr(pos, ir.OXDOT, x, sym)) case exprIndex: x := r.expr() pos := r.pos() index := r.expr() - return ir.NewIndexExpr(pos, x, index) + return typecheck.Expr(ir.NewIndexExpr(pos, x, index)) case exprSlice: x := r.expr() @@ -1514,13 +1516,13 @@ func (r *reader) expr0() ir.Node { if index[2] != nil { op = ir.OSLICE3 } - return ir.NewSliceExpr(pos, op, x, index[0], index[1], index[2]) + return typecheck.Expr(ir.NewSliceExpr(pos, op, x, index[0], index[1], index[2])) case exprAssert: x := r.expr() pos := r.pos() typ := r.expr().(ir.Ntype) - return ir.NewTypeAssertExpr(pos, x, typ) + return typecheck.Expr(ir.NewTypeAssertExpr(pos, x, typ)) case exprUnaryOp: op := r.op() @@ -1529,11 +1531,11 @@ func (r *reader) expr0() ir.Node { switch op { case ir.OADDR: - return typecheck.NodAddrAt(pos, x) + return typecheck.Expr(typecheck.NodAddrAt(pos, x)) case ir.ODEREF: - return ir.NewStarExpr(pos, x) + return typecheck.Expr(ir.NewStarExpr(pos, x)) } - return ir.NewUnaryExpr(pos, op, x) + return typecheck.Expr(ir.NewUnaryExpr(pos, op, x)) case exprBinaryOp: op := r.op() @@ -1543,12 +1545,17 @@ func (r *reader) expr0() ir.Node { switch op { case ir.OANDAND, ir.OOROR: - return ir.NewLogicalExpr(pos, op, x, y) + return typecheck.Expr(ir.NewLogicalExpr(pos, op, x, y)) } - return ir.NewBinaryExpr(pos, op, x, y) + return typecheck.Expr(ir.NewBinaryExpr(pos, op, x, y)) case exprCall: - fun := typecheck.Callee(r.expr0()) + fun := r.expr() + if r.bool() { // method call + pos := r.pos() + _, sym := r.selector() + fun = typecheck.Callee(ir.NewSelectorExpr(pos, ir.OXDOT, fun, sym)) + } pos := r.pos() args := r.exprs() dots := r.bool() @@ -1558,17 +1565,17 @@ func (r *reader) expr0() ir.Node { typ := r.typ() pos := r.pos() x := r.expr() - return ir.NewConvExpr(pos, ir.OCONV, typ, x) + return typecheck.Expr(ir.NewConvExpr(pos, ir.OCONV, typ, x)) } } func (r *reader) compLit() ir.Node { r.sync(syncCompLit) pos := r.pos() - typ := r.typ() + typ0 := r.typ() - isPtrLit := typ.IsPtr() - if isPtrLit { + typ := typ0 + if typ.IsPtr() { typ = typ.Elem() } if typ.Kind() == types.TFORW { @@ -1591,9 +1598,10 @@ func (r *reader) compLit() ir.Node { *elemp = wrapName(r.pos(), r.expr()) } - lit := ir.NewCompLitExpr(pos, ir.OCOMPLIT, ir.TypeNode(typ), elems) - if isPtrLit { - return typecheck.NodAddrAt(pos, lit) + lit := typecheck.Expr(ir.NewCompLitExpr(pos, ir.OCOMPLIT, ir.TypeNode(typ), elems)) + if typ0.IsPtr() { + lit = typecheck.Expr(typecheck.NodAddrAt(pos, lit)) + lit.SetType(typ0) } return lit } diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 3f9310514a..21aeb5678d 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -1230,19 +1230,32 @@ func (w *writer) expr(expr syntax.Expr) { break } - w.code(exprCall) + writeFunExpr := func() { + if selector, ok := unparen(expr.Fun).(*syntax.SelectorExpr); ok { + if sel, ok := w.p.info.Selections[selector]; ok && sel.Kind() == types2.MethodVal { + w.expr(selector.X) + w.bool(true) // method call + w.pos(selector) + w.selector(sel.Obj()) + return + } + } - if inf, ok := w.p.info.Inferred[expr]; ok { - obj, _ := lookupObj(w.p.info, expr.Fun) - assert(obj != nil) + if inf, ok := w.p.info.Inferred[expr]; ok { + obj, _ := lookupObj(w.p.info, expr.Fun) + assert(obj != nil) - // As if w.expr(expr.Fun), but using inf.TArgs instead. - w.code(exprName) - w.obj(obj, inf.TArgs) - } else { - w.expr(expr.Fun) + // As if w.expr(expr.Fun), but using inf.TArgs instead. + w.code(exprName) + w.obj(obj, inf.TArgs) + } else { + w.expr(expr.Fun) + } + w.bool(false) // not a method call (i.e., normal function call) } + w.code(exprCall) + writeFunExpr() w.pos(expr) w.exprs(expr.ArgList) w.bool(expr.HasDots) -- GitLab From 1c783dc1480e8dec8bd4e76b744238607ea527f0 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Fri, 2 Jul 2021 17:51:20 -0700 Subject: [PATCH 0433/2500] [dev.typeparams] Add optional sub-dict entry for typeparam bound calls In the case that a generic function/method f does a method call on a type param allowed by its bound, an instantiation of f may do a direct method call of a concrete type or a method call defined on a generic type, depending on whether the passed type in a concrete type or an instantiated type with the appropriate method defined. See the test case boundmethod.go added to this change. In order to keep the dictionary format the same for all instantiations of a generic function/method, I decided to have an optional sub-dictionary entry for "bounds" calls. At the point that we are creating the actual dictionary, we can then fill in the needed sub-dictionary, if the type arg is an instantiated type, or a zeroed dictionary entry, if type arg is not instantiated and the method will be on a concrete type. In order to implement this, I now fill in n.Selection for "bounds" method calls in generic functions as well. Also, I need to calculate n.Selection correctly during import for the case where it is now set - method calls on generic types, and bounds calls on typeparams. With this change, the dictionaries/sub-dictionaries are correct for absdiff.go. The new test boundmethod.go illustrates the case where the bound sub-dict entry is not used for a dictionary for stringify[myint], but is used for a dictionary for stringify[StringInt[myint]]. Change-Id: Ie2bcb971b7019a9f1da68c97eb03da2333327457 Reviewed-on: https://go-review.googlesource.com/c/go/+/333456 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Dan Scales --- src/cmd/compile/internal/noder/expr.go | 30 +++++-- src/cmd/compile/internal/noder/stencil.go | 81 ++++++++++++++----- src/cmd/compile/internal/typecheck/iexport.go | 6 +- src/cmd/compile/internal/typecheck/iimport.go | 22 +++++ test/typeparam/boundmethod.go | 60 ++++++++++++++ 5 files changed, 172 insertions(+), 27 deletions(-) create mode 100644 test/typeparam/boundmethod.go diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index d974b291d0..16470a5449 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -207,29 +207,43 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto n := ir.NewSelectorExpr(pos, ir.OXDOT, x, typecheck.Lookup(expr.Sel.Value)) typed(g.typ(typ), n) - // Fill in n.Selection for a generic method reference, even though we - // won't use it directly, since it is useful for analysis. - // Specifically do not fill in for fields or interfaces methods, so - // n.Selection being non-nil means a method reference, rather than an - // interface reference or reference to a field with a function value. + // Fill in n.Selection for a generic method reference or a bound + // interface method, even though we won't use it directly, since it + // is useful for analysis. Specifically do not fill in for fields or + // other interfaces methods (method call on an interface value), so + // n.Selection being non-nil means a method reference for a generic + // type or a method reference due to a bound. obj2 := g.info.Selections[expr].Obj() sig := types2.AsSignature(obj2.Type()) if sig == nil || sig.Recv() == nil { return n } - // recvType is the type of the last embedded field. Because of the + index := g.info.Selections[expr].Index() + last := index[len(index)-1] + // recvType is the receiver of the method being called. Because of the // way methods are imported, g.obj(obj2) doesn't work across // packages, so we have to lookup the method via the receiver type. recvType := deref2(sig.Recv().Type()) if types2.AsInterface(recvType.Underlying()) != nil { + fieldType := n.X.Type() + for _, ix := range index[:len(index)-1] { + fieldType = fieldType.Field(ix).Type + } + if fieldType.Kind() == types.TTYPEPARAM { + n.Selection = fieldType.Bound().AllMethods().Index(last) + //fmt.Printf(">>>>> %v: Bound call %v\n", base.FmtPos(pos), n.Sel) + } else { + assert(fieldType.Kind() == types.TINTER) + //fmt.Printf(">>>>> %v: Interface call %v\n", base.FmtPos(pos), n.Sel) + } return n } - index := g.info.Selections[expr].Index() - last := index[len(index)-1] recvObj := types2.AsNamed(recvType).Obj() recv := g.pkg(recvObj.Pkg()).Lookup(recvObj.Name()).Def n.Selection = recv.Type().Methods().Index(last) + //fmt.Printf(">>>>> %v: Method call %v\n", base.FmtPos(pos), n.Sel) + return n } diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index d292bfd5c6..1759fbc4cf 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -158,12 +158,9 @@ func (g *irgen) stencil() { st := g.getInstantiation(gf, targs, true) dictValue, usingSubdict := g.getDictOrSubdict(declInfo, n, gf, targs, true) - _ = usingSubdict - // TODO: We should do assert(usingSubdict) here, but - // not creating sub-dictionary entry for - // absDifference in absdiff.go yet. Unusual case, - // where there are different generic method - // implementations of Abs in absDifference. + // We have to be using a subdictionary, since this is + // a generic method call. + assert(usingSubdict) call.SetOp(ir.OCALL) call.X = st.Nname @@ -741,10 +738,9 @@ func gcshapeType(t *types.Type) (*types.Type, string) { return gcshape, buf.String() } -// getInstantiation gets the instantiantion and dictionary of the function or method nameNode -// with the type arguments targs. If the instantiated function is not already -// cached, then it calls genericSubst to create the new instantiation. -func (g *irgen) getInstantiation(nameNode *ir.Name, targs []*types.Type, isMeth bool) *ir.Func { +// checkFetchBody checks if a generic body can be fetched, but hasn't been loaded +// yet. If so, it imports the body. +func checkFetchBody(nameNode *ir.Name) { if nameNode.Func.Body == nil && nameNode.Func.Inl != nil { // If there is no body yet but Func.Inl exists, then we can can // import the whole generic body. @@ -754,6 +750,13 @@ func (g *irgen) getInstantiation(nameNode *ir.Name, targs []*types.Type, isMeth nameNode.Func.Body = nameNode.Func.Inl.Body nameNode.Func.Dcl = nameNode.Func.Inl.Dcl } +} + +// getInstantiation gets the instantiantion and dictionary of the function or method nameNode +// with the type arguments targs. If the instantiated function is not already +// cached, then it calls genericSubst to create the new instantiation. +func (g *irgen) getInstantiation(nameNode *ir.Name, targs []*types.Type, isMeth bool) *ir.Func { + checkFetchBody(nameNode) sym := typecheck.MakeInstName(nameNode.Sym(), targs, isMeth) info := g.instInfoMap[sym] if info == nil { @@ -1405,13 +1408,41 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) case ir.OCALL: call := n.(*ir.CallExpr) if call.X.Op() == ir.OXDOT { - subtargs := deref(call.X.(*ir.SelectorExpr).X.Type()).RParams() - s2targs := make([]*types.Type, len(subtargs)) - for i, t := range subtargs { - s2targs[i] = subst.Typ(t) + var nameNode *ir.Name + se := call.X.(*ir.SelectorExpr) + if types.IsInterfaceMethod(se.Selection.Type) { + // This is a method call enabled by a type bound. + tmpse := ir.NewSelectorExpr(base.Pos, ir.OXDOT, se.X, se.Sel) + tmpse = typecheck.AddImplicitDots(tmpse) + tparam := tmpse.X.Type() + assert(tparam.IsTypeParam()) + recvType := targs[tparam.Index()] + if len(recvType.RParams()) == 0 { + // No sub-dictionary entry is + // actually needed, since the + // typeparam is not an + // instantiated type that + // will have generic methods. + break + } + // This is a method call for an + // instantiated type, so we need a + // sub-dictionary. + targs := recvType.RParams() + genRecvType := recvType.OrigSym.Def.Type() + nameNode = typecheck.Lookdot1(call.X, se.Sel, genRecvType, genRecvType.Methods(), 1).Nname.(*ir.Name) + sym = g.getDictionarySym(nameNode, targs, true) + } else { + // This is the case of a normal + // method call on a generic type. + nameNode = call.X.(*ir.SelectorExpr).Selection.Nname.(*ir.Name) + subtargs := deref(call.X.(*ir.SelectorExpr).X.Type()).RParams() + s2targs := make([]*types.Type, len(subtargs)) + for i, t := range subtargs { + s2targs[i] = subst.Typ(t) + } + sym = g.getDictionarySym(nameNode, s2targs, true) } - nameNode := call.X.(*ir.SelectorExpr).Selection.Nname.(*ir.Name) - sym = g.getDictionarySym(nameNode, s2targs, true) } else { inst := call.X.(*ir.InstExpr) var nameNode *ir.Name @@ -1452,8 +1483,14 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) assert(false) } - off = objw.SymPtr(lsym, off, sym.Linksym(), 0) - infoPrint(" - Subdict %v\n", sym.Name) + if sym == nil { + // Unused sub-dictionary entry, just emit 0. + off = objw.Uintptr(lsym, off, 0) + infoPrint(" - Unused subdict entry\n") + } else { + off = objw.SymPtr(lsym, off, sym.Linksym(), 0) + infoPrint(" - Subdict %v\n", sym.Name) + } } objw.Global(lsym, int32(off), obj.DUPOK|obj.RODATA) infoPrint("=== Done dictionary\n") @@ -1512,6 +1549,7 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo { return infop } + checkFetchBody(gn) var info gfInfo gf := gn.Func recv := gf.Type().Recv() @@ -1575,6 +1613,13 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo { info.subDictCalls = append(info.subDictCalls, n) } } + if n.Op() == ir.OCALL && n.(*ir.CallExpr).X.Op() == ir.OXDOT && + n.(*ir.CallExpr).X.(*ir.SelectorExpr).Selection != nil && + deref(n.(*ir.CallExpr).X.(*ir.SelectorExpr).X.Type()).IsTypeParam() { + n.(*ir.CallExpr).X.(*ir.SelectorExpr).SetImplicit(true) + infoPrint(" Optional subdictionary at generic bound call: %v\n", n) + info.subDictCalls = append(info.subDictCalls, n) + } if n.Op() == ir.OCLOSURE { // Visit the closure body and add all relevant entries to the // dictionary of the outer function (closure will just use diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 0a48078bd0..4fbc48f17b 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -1789,7 +1789,11 @@ func (w *exportWriter) expr(n ir.Node) { w.exoticSelector(n.Sel) if go117ExportTypes { w.exoticType(n.Type()) - if n.Op() == ir.ODOT || n.Op() == ir.ODOTPTR || n.Op() == ir.ODOTINTER { + if n.Op() == ir.OXDOT { + // n.Selection for method references will be + // reconstructed during import. + w.bool(n.Selection != nil) + } else if n.Op() == ir.ODOT || n.Op() == ir.ODOTPTR || n.Op() == ir.ODOTINTER { w.exoticField(n.Selection) } // n.Selection is not required for OMETHEXPR, ODOTMETH, and OMETHVALUE. It will diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 4a97267f05..bf7f84b5cd 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1376,6 +1376,28 @@ func (r *importReader) node() ir.Node { if go117ExportTypes { n.SetType(r.exoticType()) switch op { + case ir.OXDOT: + hasSelection := r.bool() + // We reconstruct n.Selection for method calls on + // generic types and method calls due to type param + // bounds. Otherwise, n.Selection is nil. + if hasSelection { + n1 := ir.NewSelectorExpr(pos, op, expr, sel) + AddImplicitDots(n1) + var m *types.Field + if n1.X.Type().IsTypeParam() { + genType := n1.X.Type().Bound() + m = Lookdot1(n1, sel, genType, genType.AllMethods(), 1) + } else { + genType := types.ReceiverBaseType(n1.X.Type()) + if genType.IsInstantiatedGeneric() { + genType = genType.OrigSym.Def.Type() + } + m = Lookdot1(n1, sel, genType, genType.Methods(), 1) + } + assert(m != nil) + n.Selection = m + } case ir.ODOT, ir.ODOTPTR, ir.ODOTINTER: n.Selection = r.exoticField() case ir.ODOTMETH, ir.OMETHVALUE, ir.OMETHEXPR: diff --git a/test/typeparam/boundmethod.go b/test/typeparam/boundmethod.go new file mode 100644 index 0000000000..c150f9d85a --- /dev/null +++ b/test/typeparam/boundmethod.go @@ -0,0 +1,60 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This test illustrates how a type bound method (String below) can be implemented +// either by a concrete type (myint below) or a instantiated generic type +// (StringInt[myint] below). + +package main + +import ( + "fmt" + "reflect" + "strconv" +) + +type myint int + +//go:noinline +func (m myint) String() string { + return strconv.Itoa(int(m)) +} + +type Stringer interface { + String() string +} + +func stringify[T Stringer](s []T) (ret []string) { + for _, v := range s { + ret = append(ret, v.String()) + } + return ret +} + +type StringInt[T any] T + +//go:noinline +func (m StringInt[T]) String() string { + return "aa" +} + +func main() { + x := []myint{myint(1), myint(2), myint(3)} + + got := stringify(x) + want := []string{"1", "2", "3"} + if !reflect.DeepEqual(got, want) { + panic(fmt.Sprintf("got %s, want %s", got, want)) + } + + x2 := []StringInt[myint]{StringInt[myint](1), StringInt[myint](2), StringInt[myint](3)} + + got2 := stringify(x2) + want2 := []string{"aa", "aa", "aa"} + if !reflect.DeepEqual(got2, want2) { + panic(fmt.Sprintf("got %s, want %s", got2, want2)) + } +} -- GitLab From 22e926546732e4ea1fb20551be4b91f51f3b6e65 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 9 Jul 2021 13:02:24 -0700 Subject: [PATCH 0434/2500] [dev.typeparams] cmd/compile/internal/types2: replace types2.Instantiate with Checker.Instantiate Allow Checker.Instantiate to work with a nil *Checker receiver (for now). This opens the door to passing in a *Checker at all times. Also, added a verify flag to Instantiate, InstantiateLazy, and instance, to be able to control if constraint satisfaction should be checked or not. Removed types2.Instantiate. For #47103. Change-Id: Ie00ce41b3e50a0fc4341e013922e5f874276d282 Reviewed-on: https://go-review.googlesource.com/c/go/+/333569 Trust: Robert Griesemer Reviewed-by: Robert Findley Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/importer/iimport.go | 3 +- src/cmd/compile/internal/noder/reader2.go | 2 +- src/cmd/compile/internal/types2/api_test.go | 4 +- src/cmd/compile/internal/types2/call.go | 4 +- src/cmd/compile/internal/types2/instance.go | 3 +- .../compile/internal/types2/instantiate.go | 64 ++----------------- .../compile/internal/types2/sizeof_test.go | 2 +- src/cmd/compile/internal/types2/subst.go | 55 ++++++++++------ src/cmd/compile/internal/types2/typexpr.go | 2 + 9 files changed, 56 insertions(+), 83 deletions(-) diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index 14e64891b8..453fa40f2d 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -665,7 +665,8 @@ func (r *importReader) doType(base *types2.Named) types2.Type { baseType := r.typ() // The imported instantiated type doesn't include any methods, so // we must always use the methods of the base (orig) type. - t := types2.Instantiate(pos, baseType, targs) + var check *types2.Checker // TODO provide a non-nil *Checker + t := check.Instantiate(pos, baseType, targs, nil, false) return t case unionType: diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index 89f224d389..92569ff843 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -224,7 +224,7 @@ func (r *reader2) doTyp() (res types2.Type) { obj, targs := r.obj() name := obj.(*types2.TypeName) if len(targs) != 0 { - return r.p.check.InstantiateLazy(syntax.Pos{}, name.Type(), targs) + return r.p.check.InstantiateLazy(syntax.Pos{}, name.Type(), targs, false) } return name.Type() diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index 1c535387d4..74e3da3fe1 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -1862,7 +1862,9 @@ func TestInstantiate(t *testing.T) { } // instantiation should succeed (no endless recursion) - res := Instantiate(nopos, T, []Type{Typ[Int]}) + // even with a nil *Checker + var check *Checker + res := check.Instantiate(nopos, T, []Type{Typ[Int]}, nil, false) // instantiated type should point to itself if res.Underlying().(*Pointer).Elem() != res { diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 3377270ef8..0d9637e696 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -56,7 +56,7 @@ func (check *Checker) funcInst(x *operand, inst *syntax.IndexExpr) { } // instantiate function signature - res := check.instantiate(x.Pos(), sig, targs, poslist).(*Signature) + res := check.Instantiate(x.Pos(), sig, targs, poslist, true).(*Signature) assert(res.tparams == nil) // signature is not generic anymore if inferred { check.recordInferred(inst, targs, res) @@ -326,7 +326,7 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T } // compute result signature - rsig = check.instantiate(call.Pos(), sig, targs, nil).(*Signature) + rsig = check.Instantiate(call.Pos(), sig, targs, nil, true).(*Signature) assert(rsig.tparams == nil) // signature is not generic anymore check.recordInferred(call, targs, rsig) diff --git a/src/cmd/compile/internal/types2/instance.go b/src/cmd/compile/internal/types2/instance.go index b133fd1e65..65c2015507 100644 --- a/src/cmd/compile/internal/types2/instance.go +++ b/src/cmd/compile/internal/types2/instance.go @@ -16,6 +16,7 @@ type instance struct { base *Named // parameterized type to be instantiated targs []Type // type arguments poslist []syntax.Pos // position of each targ; for error reporting only + verify bool // if set, constraint satisfaction is verified value Type // base[targs...] after instantiation or Typ[Invalid]; nil if not yet set } @@ -25,7 +26,7 @@ type instance struct { func (t *instance) expand() Type { v := t.value if v == nil { - v = t.check.instantiate(t.pos, t.base, t.targs, t.poslist) + v = t.check.Instantiate(t.pos, t.base, t.targs, t.poslist, t.verify) if v == nil { v = Typ[Invalid] } diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 85c897a909..b289607de6 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -9,71 +9,19 @@ import ( "fmt" ) -// Instantiate instantiates the type typ with the given type arguments. -// typ must be a *Named or a *Signature type, it must be generic, and -// its number of type parameters must match the number of provided type -// arguments. The result is a new, instantiated (not generic) type of -// the same kind (either a *Named or a *Signature). The type arguments -// are not checked against the constraints of the type parameters. -// Any methods attached to a *Named are simply copied; they are not -// instantiated. -func Instantiate(pos syntax.Pos, typ Type, targs []Type) (res Type) { - // TODO(gri) This code is basically identical to the prolog - // in Checker.instantiate. Factor. - var tparams []*TypeName - switch t := typ.(type) { - case *Named: - tparams = t.TParams() - case *Signature: - tparams = t.tparams - defer func() { - // If we had an unexpected failure somewhere don't panic below when - // asserting res.(*Signature). Check for *Signature in case Typ[Invalid] - // is returned. - if _, ok := res.(*Signature); !ok { - return - } - // If the signature doesn't use its type parameters, subst - // will not make a copy. In that case, make a copy now (so - // we can set tparams to nil w/o causing side-effects). - if t == res { - copy := *t - res = © - } - // After instantiating a generic signature, it is not generic - // anymore; we need to set tparams to nil. - res.(*Signature).tparams = nil - }() - - default: - panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) - } - - // the number of supplied types must match the number of type parameters - if len(targs) != len(tparams) { - panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, len(targs), len(tparams))) - } - - if len(tparams) == 0 { - return typ // nothing to do (minor optimization) - } - - smap := makeSubstMap(tparams, targs) - return (*Checker)(nil).subst(pos, typ, smap) -} - // InstantiateLazy is like Instantiate, but avoids actually // instantiating the type until needed. -func (check *Checker) InstantiateLazy(pos syntax.Pos, typ Type, targs []Type) (res Type) { +func (check *Checker) InstantiateLazy(pos syntax.Pos, typ Type, targs []Type, verify bool) (res Type) { base := asNamed(typ) if base == nil { panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } return &instance{ - check: check, - pos: pos, - base: base, - targs: targs, + check: check, + pos: pos, + base: base, + targs: targs, + verify: verify, } } diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go index a51d0c43d5..f7f191f629 100644 --- a/src/cmd/compile/internal/types2/sizeof_test.go +++ b/src/cmd/compile/internal/types2/sizeof_test.go @@ -33,7 +33,7 @@ func TestSizeof(t *testing.T) { {Chan{}, 12, 24}, {Named{}, 84, 160}, {TypeParam{}, 28, 48}, - {instance{}, 52, 96}, + {instance{}, 56, 104}, {top{}, 0, 0}, // Objects diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 6e4e778b20..32cf527372 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -53,8 +53,24 @@ func (m *substMap) lookup(tpar *TypeParam) Type { return tpar } -func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, poslist []syntax.Pos) (res Type) { - if check.conf.Trace { +// Instantiate instantiates the type typ with the given type arguments +// targs. To check type constraint satisfaction, verify must be set. +// pos and posList correspond to the instantiation and type argument +// positions respectively; posList may be nil or shorter than the number +// of type arguments provided. +// typ must be a *Named or a *Signature type, and its number of type +// parameters must match the number of provided type arguments. +// The receiver (check) may be nil if and only if verify is not set. +// The result is a new, instantiated (not generic) type of the same kind +// (either a *Named or a *Signature). +// Any methods attached to a *Named are simply copied; they are not +// instantiated. +func (check *Checker) Instantiate(pos syntax.Pos, typ Type, targs []Type, posList []syntax.Pos, verify bool) (res Type) { + if verify && check == nil { + panic("cannot have nil receiver if verify is set") + } + + if check != nil && check.conf.Trace { check.trace(pos, "-- instantiating %s with %s", typ, typeListString(targs)) check.indent++ defer func() { @@ -70,7 +86,7 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, poslis }() } - assert(len(poslist) <= len(targs)) + assert(len(posList) <= len(targs)) // TODO(gri) What is better here: work with TypeParams, or work with TypeNames? var tparams []*TypeName @@ -97,18 +113,19 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, poslis // anymore; we need to set tparams to nil. res.(*Signature).tparams = nil }() - default: - check.dump("%v: cannot instantiate %v", pos, typ) - unreachable() // only defined types and (defined) functions can be generic - + // only types and functions can be generic + panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } // the number of supplied types must match the number of type parameters if len(targs) != len(tparams) { // TODO(gri) provide better error message - check.errorf(pos, "got %d arguments but %d type parameters", len(targs), len(tparams)) - return Typ[Invalid] + if check != nil { + check.errorf(pos, "got %d arguments but %d type parameters", len(targs), len(tparams)) + return Typ[Invalid] + } + panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, len(targs), len(tparams))) } if len(tparams) == 0 { @@ -118,15 +135,17 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, poslis smap := makeSubstMap(tparams, targs) // check bounds - for i, tname := range tparams { - // best position for error reporting - pos := pos - if i < len(poslist) { - pos = poslist[i] - } - // stop checking bounds after the first failure - if !check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap) { - break + if verify { + for i, tname := range tparams { + // best position for error reporting + pos := pos + if i < len(posList) { + pos = posList[i] + } + // stop checking bounds after the first failure + if !check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap) { + break + } } } diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index e861f7e784..d69dd3c496 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -423,12 +423,14 @@ func (check *Checker) instantiatedType(x syntax.Expr, targs []syntax.Expr, def * // create a new type instance rather than instantiate the type // TODO(gri) should do argument number check here rather than // when instantiating the type? + // TODO(gri) use InstantiateLazy here (cleanup) typ := new(instance) def.setUnderlying(typ) typ.check = check typ.pos = x.Pos() typ.base = base + typ.verify = true // evaluate arguments (always) typ.targs = check.typeList(targs) -- GitLab From 70f1246a9f861bdfe2ea81db0f1545bd31ff6d49 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 9 Jul 2021 13:15:46 -0700 Subject: [PATCH 0435/2500] [dev.typeparams] cmd/compile/internal/types2: move instantiation code to instantiate.go (cleanup) No code changes besides moving the two functions and updating a couple of file comments. Change-Id: I13a6a78b6e8c132c20c7f81a329f31d5edab0453 Reviewed-on: https://go-review.googlesource.com/c/go/+/333589 Trust: Robert Griesemer Reviewed-by: Robert Findley --- .../compile/internal/types2/instantiate.go | 183 +++++++++++++++++ src/cmd/compile/internal/types2/subst.go | 184 +----------------- 2 files changed, 184 insertions(+), 183 deletions(-) diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index b289607de6..5ccd511acb 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// This file implements instantiation of generic types +// through substitution of type parameters by type arguments. + package types2 import ( @@ -9,6 +12,105 @@ import ( "fmt" ) +// Instantiate instantiates the type typ with the given type arguments +// targs. To check type constraint satisfaction, verify must be set. +// pos and posList correspond to the instantiation and type argument +// positions respectively; posList may be nil or shorter than the number +// of type arguments provided. +// typ must be a *Named or a *Signature type, and its number of type +// parameters must match the number of provided type arguments. +// The receiver (check) may be nil if and only if verify is not set. +// The result is a new, instantiated (not generic) type of the same kind +// (either a *Named or a *Signature). +// Any methods attached to a *Named are simply copied; they are not +// instantiated. +func (check *Checker) Instantiate(pos syntax.Pos, typ Type, targs []Type, posList []syntax.Pos, verify bool) (res Type) { + if verify && check == nil { + panic("cannot have nil receiver if verify is set") + } + + if check != nil && check.conf.Trace { + check.trace(pos, "-- instantiating %s with %s", typ, typeListString(targs)) + check.indent++ + defer func() { + check.indent-- + var under Type + if res != nil { + // Calling under() here may lead to endless instantiations. + // Test case: type T[P any] T[P] + // TODO(gri) investigate if that's a bug or to be expected. + under = res.Underlying() + } + check.trace(pos, "=> %s (under = %s)", res, under) + }() + } + + assert(len(posList) <= len(targs)) + + // TODO(gri) What is better here: work with TypeParams, or work with TypeNames? + var tparams []*TypeName + switch t := typ.(type) { + case *Named: + tparams = t.TParams() + case *Signature: + tparams = t.tparams + defer func() { + // If we had an unexpected failure somewhere don't panic below when + // asserting res.(*Signature). Check for *Signature in case Typ[Invalid] + // is returned. + if _, ok := res.(*Signature); !ok { + return + } + // If the signature doesn't use its type parameters, subst + // will not make a copy. In that case, make a copy now (so + // we can set tparams to nil w/o causing side-effects). + if t == res { + copy := *t + res = © + } + // After instantiating a generic signature, it is not generic + // anymore; we need to set tparams to nil. + res.(*Signature).tparams = nil + }() + default: + // only types and functions can be generic + panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) + } + + // the number of supplied types must match the number of type parameters + if len(targs) != len(tparams) { + // TODO(gri) provide better error message + if check != nil { + check.errorf(pos, "got %d arguments but %d type parameters", len(targs), len(tparams)) + return Typ[Invalid] + } + panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, len(targs), len(tparams))) + } + + if len(tparams) == 0 { + return typ // nothing to do (minor optimization) + } + + smap := makeSubstMap(tparams, targs) + + // check bounds + if verify { + for i, tname := range tparams { + // best position for error reporting + pos := pos + if i < len(posList) { + pos = posList[i] + } + // stop checking bounds after the first failure + if !check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap) { + break + } + } + } + + return check.subst(pos, typ, smap) +} + // InstantiateLazy is like Instantiate, but avoids actually // instantiating the type until needed. func (check *Checker) InstantiateLazy(pos syntax.Pos, typ Type, targs []Type, verify bool) (res Type) { @@ -25,3 +127,84 @@ func (check *Checker) InstantiateLazy(pos syntax.Pos, typ Type, targs []Type, ve verify: verify, } } + +// satisfies reports whether the type argument targ satisfies the constraint of type parameter +// parameter tpar (after any of its type parameters have been substituted through smap). +// A suitable error is reported if the result is false. +// TODO(gri) This should be a method of interfaces or type sets. +func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap *substMap) bool { + iface := tpar.Bound() + if iface.Empty() { + return true // no type bound + } + + // The type parameter bound is parameterized with the same type parameters + // as the instantiated type; before we can use it for bounds checking we + // need to instantiate it with the type arguments with which we instantiate + // the parameterized type. + iface = check.subst(pos, iface, smap).(*Interface) + + // targ must implement iface (methods) + // - check only if we have methods + if iface.NumMethods() > 0 { + // If the type argument is a pointer to a type parameter, the type argument's + // method set is empty. + // TODO(gri) is this what we want? (spec question) + if base, isPtr := deref(targ); isPtr && asTypeParam(base) != nil { + check.errorf(pos, "%s has no methods", targ) + return false + } + if m, wrong := check.missingMethod(targ, iface, true); m != nil { + // TODO(gri) needs to print updated name to avoid major confusion in error message! + // (print warning for now) + // Old warning: + // check.softErrorf(pos, "%s does not satisfy %s (warning: name not updated) = %s (missing method %s)", targ, tpar.bound, iface, m) + if m.name == "==" { + // We don't want to report "missing method ==". + check.softErrorf(pos, "%s does not satisfy comparable", targ) + } else if wrong != nil { + // TODO(gri) This can still report uninstantiated types which makes the error message + // more difficult to read then necessary. + check.softErrorf(pos, + "%s does not satisfy %s: wrong method signature\n\tgot %s\n\twant %s", + targ, tpar.bound, wrong, m, + ) + } else { + check.softErrorf(pos, "%s does not satisfy %s (missing method %s)", targ, tpar.bound, m.name) + } + return false + } + } + + // targ's underlying type must also be one of the interface types listed, if any + if iface.typeSet().types == nil { + return true // nothing to do + } + + // If targ is itself a type parameter, each of its possible types, but at least one, must be in the + // list of iface types (i.e., the targ type list must be a non-empty subset of the iface types). + if targ := asTypeParam(targ); targ != nil { + targBound := targ.Bound() + if targBound.typeSet().types == nil { + check.softErrorf(pos, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ) + return false + } + return iface.is(func(typ Type, tilde bool) bool { + // TODO(gri) incorporate tilde information! + if !iface.isSatisfiedBy(typ) { + // TODO(gri) match this error message with the one below (or vice versa) + check.softErrorf(pos, "%s does not satisfy %s (%s type constraint %s not found in %s)", targ, tpar.bound, targ, typ, iface.typeSet().types) + return false + } + return true + }) + } + + // Otherwise, targ's type or underlying type must also be one of the interface types listed, if any. + if !iface.isSatisfiedBy(targ) { + check.softErrorf(pos, "%s does not satisfy %s (%s not found in %s)", targ, tpar.bound, targ, iface.typeSet().types) + return false + } + + return true +} diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 32cf527372..63b234a60e 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -2,9 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// This file implements instantiation of generic types -// through substitution of type parameters by actual -// types. +// This file implements type parameter substitution. package types2 @@ -53,186 +51,6 @@ func (m *substMap) lookup(tpar *TypeParam) Type { return tpar } -// Instantiate instantiates the type typ with the given type arguments -// targs. To check type constraint satisfaction, verify must be set. -// pos and posList correspond to the instantiation and type argument -// positions respectively; posList may be nil or shorter than the number -// of type arguments provided. -// typ must be a *Named or a *Signature type, and its number of type -// parameters must match the number of provided type arguments. -// The receiver (check) may be nil if and only if verify is not set. -// The result is a new, instantiated (not generic) type of the same kind -// (either a *Named or a *Signature). -// Any methods attached to a *Named are simply copied; they are not -// instantiated. -func (check *Checker) Instantiate(pos syntax.Pos, typ Type, targs []Type, posList []syntax.Pos, verify bool) (res Type) { - if verify && check == nil { - panic("cannot have nil receiver if verify is set") - } - - if check != nil && check.conf.Trace { - check.trace(pos, "-- instantiating %s with %s", typ, typeListString(targs)) - check.indent++ - defer func() { - check.indent-- - var under Type - if res != nil { - // Calling under() here may lead to endless instantiations. - // Test case: type T[P any] T[P] - // TODO(gri) investigate if that's a bug or to be expected. - under = res.Underlying() - } - check.trace(pos, "=> %s (under = %s)", res, under) - }() - } - - assert(len(posList) <= len(targs)) - - // TODO(gri) What is better here: work with TypeParams, or work with TypeNames? - var tparams []*TypeName - switch t := typ.(type) { - case *Named: - tparams = t.TParams() - case *Signature: - tparams = t.tparams - defer func() { - // If we had an unexpected failure somewhere don't panic below when - // asserting res.(*Signature). Check for *Signature in case Typ[Invalid] - // is returned. - if _, ok := res.(*Signature); !ok { - return - } - // If the signature doesn't use its type parameters, subst - // will not make a copy. In that case, make a copy now (so - // we can set tparams to nil w/o causing side-effects). - if t == res { - copy := *t - res = © - } - // After instantiating a generic signature, it is not generic - // anymore; we need to set tparams to nil. - res.(*Signature).tparams = nil - }() - default: - // only types and functions can be generic - panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) - } - - // the number of supplied types must match the number of type parameters - if len(targs) != len(tparams) { - // TODO(gri) provide better error message - if check != nil { - check.errorf(pos, "got %d arguments but %d type parameters", len(targs), len(tparams)) - return Typ[Invalid] - } - panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, len(targs), len(tparams))) - } - - if len(tparams) == 0 { - return typ // nothing to do (minor optimization) - } - - smap := makeSubstMap(tparams, targs) - - // check bounds - if verify { - for i, tname := range tparams { - // best position for error reporting - pos := pos - if i < len(posList) { - pos = posList[i] - } - // stop checking bounds after the first failure - if !check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap) { - break - } - } - } - - return check.subst(pos, typ, smap) -} - -// satisfies reports whether the type argument targ satisfies the constraint of type parameter -// parameter tpar (after any of its type parameters have been substituted through smap). -// A suitable error is reported if the result is false. -// TODO(gri) This should be a method of interfaces or type sets. -func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap *substMap) bool { - iface := tpar.Bound() - if iface.Empty() { - return true // no type bound - } - - // The type parameter bound is parameterized with the same type parameters - // as the instantiated type; before we can use it for bounds checking we - // need to instantiate it with the type arguments with which we instantiate - // the parameterized type. - iface = check.subst(pos, iface, smap).(*Interface) - - // targ must implement iface (methods) - // - check only if we have methods - if iface.NumMethods() > 0 { - // If the type argument is a pointer to a type parameter, the type argument's - // method set is empty. - // TODO(gri) is this what we want? (spec question) - if base, isPtr := deref(targ); isPtr && asTypeParam(base) != nil { - check.errorf(pos, "%s has no methods", targ) - return false - } - if m, wrong := check.missingMethod(targ, iface, true); m != nil { - // TODO(gri) needs to print updated name to avoid major confusion in error message! - // (print warning for now) - // Old warning: - // check.softErrorf(pos, "%s does not satisfy %s (warning: name not updated) = %s (missing method %s)", targ, tpar.bound, iface, m) - if m.name == "==" { - // We don't want to report "missing method ==". - check.softErrorf(pos, "%s does not satisfy comparable", targ) - } else if wrong != nil { - // TODO(gri) This can still report uninstantiated types which makes the error message - // more difficult to read then necessary. - check.softErrorf(pos, - "%s does not satisfy %s: wrong method signature\n\tgot %s\n\twant %s", - targ, tpar.bound, wrong, m, - ) - } else { - check.softErrorf(pos, "%s does not satisfy %s (missing method %s)", targ, tpar.bound, m.name) - } - return false - } - } - - // targ's underlying type must also be one of the interface types listed, if any - if iface.typeSet().types == nil { - return true // nothing to do - } - - // If targ is itself a type parameter, each of its possible types, but at least one, must be in the - // list of iface types (i.e., the targ type list must be a non-empty subset of the iface types). - if targ := asTypeParam(targ); targ != nil { - targBound := targ.Bound() - if targBound.typeSet().types == nil { - check.softErrorf(pos, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ) - return false - } - return iface.is(func(typ Type, tilde bool) bool { - // TODO(gri) incorporate tilde information! - if !iface.isSatisfiedBy(typ) { - // TODO(gri) match this error message with the one below (or vice versa) - check.softErrorf(pos, "%s does not satisfy %s (%s type constraint %s not found in %s)", targ, tpar.bound, targ, typ, iface.typeSet().types) - return false - } - return true - }) - } - - // Otherwise, targ's type or underlying type must also be one of the interface types listed, if any. - if !iface.isSatisfiedBy(targ) { - check.softErrorf(pos, "%s does not satisfy %s (%s not found in %s)", targ, tpar.bound, targ, iface.typeSet().types) - return false - } - - return true -} - // subst returns the type typ with its type parameters tpars replaced by // the corresponding type arguments targs, recursively. // subst is functional in the sense that it doesn't modify the incoming -- GitLab From d0324eb8fbabc6295d0170ba1527517d014a84a4 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 9 Jul 2021 15:04:15 -0700 Subject: [PATCH 0436/2500] [dev.typeparams] cmd/compile/internal/types2: use InstantiateLazy to create instance types (cleanup) This change concentrates the creation is lazily instantiated types in one place (InstantiateLazy). This should also make it easier to replace the implementation of lazily instantiated types (e.g. getting rid of instance types). Change-Id: I452c463219b466ce79f227c44fb67b79d428842a Reviewed-on: https://go-review.googlesource.com/c/go/+/333669 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/noder/reader2.go | 2 +- src/cmd/compile/internal/types2/instance.go | 4 +- .../compile/internal/types2/instantiate.go | 16 ++++--- src/cmd/compile/internal/types2/typexpr.go | 43 +++++++------------ 4 files changed, 27 insertions(+), 38 deletions(-) diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index 92569ff843..ac29f6f519 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -224,7 +224,7 @@ func (r *reader2) doTyp() (res types2.Type) { obj, targs := r.obj() name := obj.(*types2.TypeName) if len(targs) != 0 { - return r.p.check.InstantiateLazy(syntax.Pos{}, name.Type(), targs, false) + return r.p.check.InstantiateLazy(syntax.Pos{}, name.Type(), targs, nil, false) } return name.Type() diff --git a/src/cmd/compile/internal/types2/instance.go b/src/cmd/compile/internal/types2/instance.go index 65c2015507..798d58811f 100644 --- a/src/cmd/compile/internal/types2/instance.go +++ b/src/cmd/compile/internal/types2/instance.go @@ -15,7 +15,7 @@ type instance struct { pos syntax.Pos // position of type instantiation; for error reporting only base *Named // parameterized type to be instantiated targs []Type // type arguments - poslist []syntax.Pos // position of each targ; for error reporting only + posList []syntax.Pos // position of each targ; for error reporting only verify bool // if set, constraint satisfaction is verified value Type // base[targs...] after instantiation or Typ[Invalid]; nil if not yet set } @@ -26,7 +26,7 @@ type instance struct { func (t *instance) expand() Type { v := t.value if v == nil { - v = t.check.Instantiate(t.pos, t.base, t.targs, t.poslist, t.verify) + v = t.check.Instantiate(t.pos, t.base, t.targs, t.posList, t.verify) if v == nil { v = Typ[Invalid] } diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 5ccd511acb..cc96375027 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -112,19 +112,21 @@ func (check *Checker) Instantiate(pos syntax.Pos, typ Type, targs []Type, posLis } // InstantiateLazy is like Instantiate, but avoids actually -// instantiating the type until needed. -func (check *Checker) InstantiateLazy(pos syntax.Pos, typ Type, targs []Type, verify bool) (res Type) { +// instantiating the type until needed. typ must be a *Named +// type. +func (check *Checker) InstantiateLazy(pos syntax.Pos, typ Type, targs []Type, posList []syntax.Pos, verify bool) Type { base := asNamed(typ) if base == nil { panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } return &instance{ - check: check, - pos: pos, - base: base, - targs: targs, - verify: verify, + check: check, + pos: pos, + base: base, + targs: targs, + posList: posList, + verify: verify, } } diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index d69dd3c496..a14d498cec 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -410,45 +410,32 @@ func (check *Checker) typOrNil(e syntax.Expr) Type { return Typ[Invalid] } -func (check *Checker) instantiatedType(x syntax.Expr, targs []syntax.Expr, def *Named) Type { - b := check.genericType(x, true) // TODO(gri) what about cycles? - if b == Typ[Invalid] { - return b // error already reported +func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def *Named) Type { + base := check.genericType(x, true) + if base == Typ[Invalid] { + return base // error already reported } - base := asNamed(b) - if base == nil { - unreachable() // should have been caught by genericType - } - - // create a new type instance rather than instantiate the type - // TODO(gri) should do argument number check here rather than - // when instantiating the type? - // TODO(gri) use InstantiateLazy here (cleanup) - typ := new(instance) - def.setUnderlying(typ) - typ.check = check - typ.pos = x.Pos() - typ.base = base - typ.verify = true - - // evaluate arguments (always) - typ.targs = check.typeList(targs) - if typ.targs == nil { + // evaluate arguments + targs := check.typeList(targsx) + if targs == nil { def.setUnderlying(Typ[Invalid]) // avoid later errors due to lazy instantiation return Typ[Invalid] } - // determine argument positions (for error reporting) - typ.poslist = make([]syntax.Pos, len(targs)) - for i, arg := range targs { - typ.poslist[i] = syntax.StartPos(arg) + // determine argument positions + posList := make([]syntax.Pos, len(targs)) + for i, arg := range targsx { + posList[i] = syntax.StartPos(arg) } + typ := check.InstantiateLazy(x.Pos(), base, targs, posList, true) + def.setUnderlying(typ) + // make sure we check instantiation works at least once // and that the resulting type is valid check.later(func() { - t := typ.expand() + t := typ.(*instance).expand() check.validType(t, nil) }) -- GitLab From e5faa8d84ba8583dd16758227249fab42ef3a1e0 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 9 Jul 2021 16:02:45 -0700 Subject: [PATCH 0437/2500] [dev.typeparams] cmd/compile/internal/types2: move methods on *Named into named.go (cleanup) No other code changes except for an additional comment. Change-Id: Ica3cea446c6c88f4f81a86d77b289a0b54b1e76f Reviewed-on: https://go-review.googlesource.com/c/go/+/333671 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/decl.go | 96 ----------------------- src/cmd/compile/internal/types2/named.go | 99 ++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 96 deletions(-) diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 4f91bc70c7..9fb9815f4d 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -515,102 +515,6 @@ func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init syntax.Expr) { check.initVars(lhs, []syntax.Expr{init}, nopos) } -// under returns the expanded underlying type of n0; possibly by following -// forward chains of named types. If an underlying type is found, resolve -// the chain by setting the underlying type for each defined type in the -// chain before returning it. If no underlying type is found or a cycle -// is detected, the result is Typ[Invalid]. If a cycle is detected and -// n0.check != nil, the cycle is reported. -func (n0 *Named) under() Type { - u := n0.Underlying() - - if u == Typ[Invalid] { - return u - } - - // If the underlying type of a defined type is not a defined - // (incl. instance) type, then that is the desired underlying - // type. - switch u.(type) { - case nil: - return Typ[Invalid] - default: - // common case - return u - case *Named, *instance: - // handled below - } - - if n0.check == nil { - panic("internal error: Named.check == nil but type is incomplete") - } - - // Invariant: after this point n0 as well as any named types in its - // underlying chain should be set up when this function exits. - check := n0.check - - // If we can't expand u at this point, it is invalid. - n := asNamed(u) - if n == nil { - n0.underlying = Typ[Invalid] - return n0.underlying - } - - // Otherwise, follow the forward chain. - seen := map[*Named]int{n0: 0} - path := []Object{n0.obj} - for { - u = n.Underlying() - if u == nil { - u = Typ[Invalid] - break - } - var n1 *Named - switch u1 := u.(type) { - case *Named: - n1 = u1 - case *instance: - n1, _ = u1.expand().(*Named) - if n1 == nil { - u = Typ[Invalid] - } - } - if n1 == nil { - break // end of chain - } - - seen[n] = len(seen) - path = append(path, n.obj) - n = n1 - - if i, ok := seen[n]; ok { - // cycle - check.cycleError(path[i:]) - u = Typ[Invalid] - break - } - } - - for n := range seen { - // We should never have to update the underlying type of an imported type; - // those underlying types should have been resolved during the import. - // Also, doing so would lead to a race condition (was issue #31749). - // Do this check always, not just in debug mode (it's cheap). - if n.obj.pkg != check.pkg { - panic("internal error: imported type with unresolved underlying type") - } - n.underlying = u - } - - return u -} - -func (n *Named) setUnderlying(typ Type) { - if n != nil { - n.underlying = typ - } -} - func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named) { assert(obj.typ == nil) diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index 2005dfbd84..da098b58b7 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -142,3 +142,102 @@ func (t *Named) AddMethod(m *Func) { func (t *Named) Underlying() Type { return t.expand().underlying } func (t *Named) String() string { return TypeString(t, nil) } + +// ---------------------------------------------------------------------------- +// Implementation + +// under returns the expanded underlying type of n0; possibly by following +// forward chains of named types. If an underlying type is found, resolve +// the chain by setting the underlying type for each defined type in the +// chain before returning it. If no underlying type is found or a cycle +// is detected, the result is Typ[Invalid]. If a cycle is detected and +// n0.check != nil, the cycle is reported. +func (n0 *Named) under() Type { + u := n0.Underlying() + + if u == Typ[Invalid] { + return u + } + + // If the underlying type of a defined type is not a defined + // (incl. instance) type, then that is the desired underlying + // type. + switch u.(type) { + case nil: + return Typ[Invalid] + default: + // common case + return u + case *Named, *instance: + // handled below + } + + if n0.check == nil { + panic("internal error: Named.check == nil but type is incomplete") + } + + // Invariant: after this point n0 as well as any named types in its + // underlying chain should be set up when this function exits. + check := n0.check + + // If we can't expand u at this point, it is invalid. + n := asNamed(u) + if n == nil { + n0.underlying = Typ[Invalid] + return n0.underlying + } + + // Otherwise, follow the forward chain. + seen := map[*Named]int{n0: 0} + path := []Object{n0.obj} + for { + u = n.Underlying() + if u == nil { + u = Typ[Invalid] + break + } + var n1 *Named + switch u1 := u.(type) { + case *Named: + n1 = u1 + case *instance: + n1, _ = u1.expand().(*Named) + if n1 == nil { + u = Typ[Invalid] + } + } + if n1 == nil { + break // end of chain + } + + seen[n] = len(seen) + path = append(path, n.obj) + n = n1 + + if i, ok := seen[n]; ok { + // cycle + check.cycleError(path[i:]) + u = Typ[Invalid] + break + } + } + + for n := range seen { + // We should never have to update the underlying type of an imported type; + // those underlying types should have been resolved during the import. + // Also, doing so would lead to a race condition (was issue #31749). + // Do this check always, not just in debug mode (it's cheap). + if n.obj.pkg != check.pkg { + panic("internal error: imported type with unresolved underlying type") + } + n.underlying = u + } + + return u +} + +func (n *Named) setUnderlying(typ Type) { + if n != nil { + n.underlying = typ + } +} -- GitLab From 82744bfbfc2d0407ecf1bf055f548c3948d4683b Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 13 Jul 2021 13:25:16 -0700 Subject: [PATCH 0438/2500] [dev.typeparams] cmd/compile: handle objStub earlier in reader There's no point in reading the object dictionary for a stub declaration. Only the package that contains the full object definition will contain an object dictionary. Change-Id: I458b77d20745105bf46190ef552312bdb5ca4d06 Reviewed-on: https://go-review.googlesource.com/c/go/+/334409 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/noder/reader.go | 38 +++++++++++++----------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 25aac6c026..2351d1d0ba 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -520,14 +520,22 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node r.typeParamBounds(sym, implicits, explicits) - origSym := sym - - sym = r.mangle(sym) - if !sym.IsBlank() && sym.Def != nil { - return sym.Def.(ir.Node) - } - tag := codeObj(r.code(syncCodeObj)) + if tag == objStub { + assert(!sym.IsBlank()) + switch sym.Pkg { + case types.BuiltinPkg, ir.Pkgs.Unsafe: + return sym.Def.(ir.Node) + } + if pri, ok := objReader[sym]; ok { + return pri.pr.objIdx(pri.idx, nil, explicits) + } + if haveLegacyImports { + assert(!r.hasTypeParams()) + return typecheck.Resolve(ir.NewIdent(src.NoXPos, sym)) + } + base.Fatalf("unresolved stub: %v", sym) + } { rdict := pr.newReader(relocObjDict, idx, syncObject1) @@ -538,6 +546,11 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node } } + sym = r.mangle(sym) + if !sym.IsBlank() && sym.Def != nil { + return sym.Def.(*ir.Name) + } + do := func(op ir.Op, hasTParams bool) *ir.Name { pos := r.pos() if hasTParams { @@ -560,17 +573,6 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node default: panic("unexpected object") - case objStub: - if pri, ok := objReader[origSym]; ok { - return pri.pr.objIdx(pri.idx, nil, explicits) - } - if haveLegacyImports { - assert(!r.hasTypeParams()) - return typecheck.Resolve(ir.NewIdent(src.NoXPos, origSym)) - } - base.Fatalf("unresolved stub: %v", origSym) - panic("unreachable") - case objAlias: name := do(ir.OTYPE, false) r.setType(name, r.typ()) -- GitLab From 5517053d178d1259f6f1a9c2d65efbf335002cea Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 13 Jul 2021 09:09:32 -0700 Subject: [PATCH 0439/2500] [dev.typeparams] cmd/compile: record more typ/fun info for dictionaries in unified IR Records whether a derived type is needed at run-time as well as instantiated functions that rely on derived types (and thus need sub-dictionaries). Change-Id: I2f2036976bfce5b3b4372fba88b4116dafa7e6b7 Reviewed-on: https://go-review.googlesource.com/c/go/+/334349 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/noder/reader.go | 57 +++++++-- src/cmd/compile/internal/noder/reader2.go | 50 ++++---- src/cmd/compile/internal/noder/unified.go | 3 + src/cmd/compile/internal/noder/writer.go | 139 ++++++++++++++++++---- 4 files changed, 188 insertions(+), 61 deletions(-) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 2351d1d0ba..de708769ba 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -142,8 +142,11 @@ type readerDict struct { // arguments; the rest are explicit. implicits int - derivedReloc []int // reloc index of the derived type's descriptor - derived []*types.Type // slice of previously computed derived types + derived []derivedInfo // reloc index of the derived type's descriptor + derivedTypes []*types.Type // slice of previously computed derived types + + funcs []objInfo + funcsObj []ir.Node } func (r *reader) setType(n ir.Node, typ *types.Type) { @@ -293,18 +296,23 @@ func (r *reader) doPkg() *types.Pkg { // @@@ Types func (r *reader) typ() *types.Type { + return r.p.typIdx(r.typInfo(), r.dict) +} + +func (r *reader) typInfo() typeInfo { r.sync(syncType) if r.bool() { - return r.p.typIdx(r.len(), r.dict) + return typeInfo{idx: r.len(), derived: true} } - return r.p.typIdx(r.reloc(relocType), nil) + return typeInfo{idx: r.reloc(relocType), derived: false} } -func (pr *pkgReader) typIdx(idx int, dict *readerDict) *types.Type { +func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict) *types.Type { + idx := info.idx var where **types.Type - if dict != nil { - where = &dict.derived[idx] - idx = dict.derivedReloc[idx] + if info.derived { + where = &dict.derivedTypes[idx] + idx = dict.derived[idx].idx } else { where = &pr.typs[idx] } @@ -493,6 +501,23 @@ var objReader = map[*types.Sym]pkgReaderIndex{} func (r *reader) obj() ir.Node { r.sync(syncObject) + if r.bool() { + idx := r.len() + obj := r.dict.funcsObj[idx] + if obj == nil { + fn := r.dict.funcs[idx] + targs := make([]*types.Type, len(fn.explicits)) + for i, targ := range fn.explicits { + targs[i] = r.p.typIdx(targ, r.dict) + } + + obj = r.p.objIdx(fn.idx, nil, targs) + assert(r.dict.funcsObj[idx] == nil) + r.dict.funcsObj[idx] = obj + } + return obj + } + idx := r.reloc(relocObj) explicits := make([]*types.Type, r.len()) @@ -539,10 +564,20 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node { rdict := pr.newReader(relocObjDict, idx, syncObject1) - r.dict.derivedReloc = make([]int, rdict.len()) - r.dict.derived = make([]*types.Type, len(r.dict.derivedReloc)) + r.dict.derived = make([]derivedInfo, rdict.len()) + r.dict.derivedTypes = make([]*types.Type, len(r.dict.derived)) for i := range r.dict.derived { - r.dict.derivedReloc[i] = rdict.reloc(relocType) + r.dict.derived[i] = derivedInfo{rdict.reloc(relocType), rdict.bool()} + } + r.dict.funcs = make([]objInfo, rdict.len()) + r.dict.funcsObj = make([]ir.Node, len(r.dict.funcs)) + for i := range r.dict.funcs { + objIdx := rdict.reloc(relocObj) + targs := make([]typeInfo, rdict.len()) + for j := range targs { + targs[j] = rdict.typInfo() + } + r.dict.funcs[i] = objInfo{idx: objIdx, explicits: targs} } } diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index ac29f6f519..a2339145fa 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -61,12 +61,12 @@ type reader2 struct { } type reader2Dict struct { - bounds []reader2TypeBound + bounds []typeInfo tparams []*types2.TypeParam - derivedReloc []int - derived []types2.Type + derived []derivedInfo + derivedTypes []types2.Type } type reader2TypeBound struct { @@ -176,18 +176,23 @@ func (r *reader2) doPkg() *types2.Package { // @@@ Types func (r *reader2) typ() types2.Type { + return r.p.typIdx(r.typInfo(), r.dict) +} + +func (r *reader2) typInfo() typeInfo { r.sync(syncType) if r.bool() { - return r.p.typIdx(r.len(), r.dict) + return typeInfo{idx: r.len(), derived: true} } - return r.p.typIdx(r.reloc(relocType), nil) + return typeInfo{idx: r.reloc(relocType), derived: false} } -func (pr *pkgReader2) typIdx(idx int, dict *reader2Dict) types2.Type { +func (pr *pkgReader2) typIdx(info typeInfo, dict *reader2Dict) types2.Type { + idx := info.idx var where *types2.Type - if dict != nil { - where = &dict.derived[idx] - idx = dict.derivedReloc[idx] + if info.derived { + where = &dict.derivedTypes[idx] + idx = dict.derived[idx].idx } else { where = &pr.typs[idx] } @@ -339,6 +344,8 @@ func (r *reader2) param() *types2.Var { func (r *reader2) obj() (types2.Object, []types2.Type) { r.sync(syncObject) + assert(!r.bool()) + pkg, name := r.p.objIdx(r.reloc(relocObj)) obj := pkg.Scope().Lookup(name) @@ -367,11 +374,12 @@ func (pr *pkgReader2) objIdx(idx int) (*types2.Package, string) { { rdict := r.p.newReader(relocObjDict, idx, syncObject1) - r.dict.derivedReloc = make([]int, rdict.len()) - r.dict.derived = make([]types2.Type, len(r.dict.derivedReloc)) + r.dict.derived = make([]derivedInfo, rdict.len()) + r.dict.derivedTypes = make([]types2.Type, len(r.dict.derived)) for i := range r.dict.derived { - r.dict.derivedReloc[i] = rdict.reloc(relocType) + r.dict.derived[i] = derivedInfo{rdict.reloc(relocType), rdict.bool()} } + // function references follow, but reader2 doesn't need those } objPkg.Scope().InsertLazy(objName, func() types2.Object { @@ -438,16 +446,9 @@ func (r *reader2) typeParamBounds() { base.Fatalf("unexpected object with %v implicit type parameter(s)", implicits) } - r.dict.bounds = make([]reader2TypeBound, r.len()) + r.dict.bounds = make([]typeInfo, r.len()) for i := range r.dict.bounds { - b := &r.dict.bounds[i] - r.sync(syncType) - b.derived = r.bool() - if b.derived { - b.boundIdx = r.len() - } else { - b.boundIdx = r.reloc(relocType) - } + r.dict.bounds[i] = r.typInfo() } } @@ -479,12 +480,7 @@ func (r *reader2) typeParamNames() []*types2.TypeName { } for i, bound := range r.dict.bounds { - var dict *reader2Dict - if bound.derived { - dict = r.dict - } - boundType := r.p.typIdx(bound.boundIdx, dict) - r.dict.tparams[i].SetBound(boundType) + r.dict.tparams[i].SetBound(r.p.typIdx(bound, r.dict)) } return names diff --git a/src/cmd/compile/internal/noder/unified.go b/src/cmd/compile/internal/noder/unified.go index 39989778f8..e8c203ae46 100644 --- a/src/cmd/compile/internal/noder/unified.go +++ b/src/cmd/compile/internal/noder/unified.go @@ -259,6 +259,7 @@ func readPackage(pr *pkgReader, importpkg *types.Pkg) { for i, n := 0, r.len(); i < n; i++ { r.sync(syncObject) + assert(!r.bool()) idx := r.reloc(relocObj) assert(r.len() == 0) @@ -293,6 +294,7 @@ func writeNewExport(out io.Writer) { for i, n := 0, r.len(); i < n; i++ { r.sync(syncObject) + assert(!r.bool()) idx := r.reloc(relocObj) assert(r.len() == 0) @@ -325,6 +327,7 @@ func writeNewExport(out io.Writer) { w.len(len(idxs)) for _, idx := range idxs { w.sync(syncObject) + w.bool(false) w.reloc(relocObj, idx) w.len(0) } diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 21aeb5678d..48884056f3 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -103,11 +103,53 @@ type writerDict struct { // derived is a slice of type indices for computing derived types // (i.e., types that depend on the declaration's type parameters). - derived []int + derived []derivedInfo // derivedIdx maps a Type to its corresponding index within the // derived slice, if present. derivedIdx map[types2.Type]int + + // funcs lists references to generic functions that were + // instantiated with derived types (i.e., that require + // sub-dictionaries when called at run time). + funcs []objInfo +} + +type derivedInfo struct { + idx int + needed bool +} + +type typeInfo struct { + idx int + derived bool +} + +type objInfo struct { + idx int // index for the generic function declaration + explicits []typeInfo // info for the type arguments +} + +func (info objInfo) anyDerived() bool { + for _, explicit := range info.explicits { + if explicit.derived { + return true + } + } + return false +} + +func (info objInfo) equals(other objInfo) bool { + if info.idx != other.idx { + return false + } + assert(len(info.explicits) == len(other.explicits)) + for i, targ := range info.explicits { + if targ != other.explicits[i] { + return false + } + } + return true } func (pw *pkgWriter) newWriter(k reloc, marker syncMarker) *writer { @@ -200,14 +242,16 @@ func (pw *pkgWriter) pkgIdx(pkg *types2.Package) int { // @@@ Types func (w *writer) typ(typ types2.Type) { - idx, derived := w.p.typIdx(typ, w.dict) + w.typInfo(w.p.typIdx(typ, w.dict)) +} +func (w *writer) typInfo(info typeInfo) { w.sync(syncType) - if w.bool(derived) { - w.len(idx) + if w.bool(info.derived) { + w.len(info.idx) w.derived = true } else { - w.reloc(relocType, idx) + w.reloc(relocType, info.idx) } } @@ -216,17 +260,17 @@ func (w *writer) typ(typ types2.Type) { // // typIdx also reports whether typ is a derived type; that is, whether // its identity depends on type parameters. -func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) (int, bool) { +func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo { if quirksMode() { typ = pw.dups.orig(typ) } if idx, ok := pw.typsIdx[typ]; ok { - return idx, false + return typeInfo{idx: idx, derived: false} } if dict != nil { if idx, ok := dict.derivedIdx[typ]; ok { - return idx, true + return typeInfo{idx: idx, derived: true} } } @@ -324,13 +368,13 @@ func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) (int, bool) { if w.derived { idx := len(dict.derived) - dict.derived = append(dict.derived, w.flush()) + dict.derived = append(dict.derived, derivedInfo{idx: w.flush()}) dict.derivedIdx[typ] = idx - return idx, true + return typeInfo{idx: idx, derived: true} } pw.typsIdx[typ] = w.idx - return w.flush(), false + return typeInfo{idx: w.flush(), derived: false} } func (w *writer) structType(typ *types2.Struct) { @@ -398,6 +442,34 @@ func (w *writer) param(param *types2.Var) { // @@@ Objects func (w *writer) obj(obj types2.Object, explicits []types2.Type) { + explicitInfos := make([]typeInfo, len(explicits)) + for i, explicit := range explicits { + explicitInfos[i] = w.p.typIdx(explicit, w.dict) + } + info := objInfo{idx: w.p.objIdx(obj), explicits: explicitInfos} + + if _, ok := obj.(*types2.Func); ok && info.anyDerived() { + idx := -1 + for i, prev := range w.dict.funcs { + if prev.equals(info) { + idx = i + } + } + if idx < 0 { + idx = len(w.dict.funcs) + w.dict.funcs = append(w.dict.funcs, info) + } + + // TODO(mdempsky): Push up into expr; this shouldn't appear + // outside of expression context. + w.sync(syncObject) + w.bool(true) + w.len(idx) + return + } + + // TODO(mdempsky): Push up into typIdx; this shouldn't be needed + // except while writing out types. if isDefinedType(obj) && obj.Pkg() == w.p.curpkg { decl, ok := w.p.typDecls[obj.(*types2.TypeName)] assert(ok) @@ -407,11 +479,12 @@ func (w *writer) obj(obj types2.Object, explicits []types2.Type) { } w.sync(syncObject) - w.reloc(relocObj, w.p.objIdx(obj)) + w.bool(false) + w.reloc(relocObj, info.idx) - w.len(len(explicits)) - for _, explicit := range explicits { - w.typ(explicit) + w.len(len(info.explicits)) + for _, info := range info.explicits { + w.typInfo(info) } } @@ -453,16 +526,19 @@ func (pw *pkgWriter) objIdx(obj types2.Object) int { w.ext.flush() // Done writing out the object description; write out the list of - // derived types that we found along the way. - // - // TODO(mdempsky): Record details about how derived types are - // actually used so reader can optimize its runtime dictionaries. - // - // TODO(mdempsky): Record details about which instantiated functions - // are used too. + // derived types and instantiated functions found along the way. wdict.len(len(dict.derived)) for _, typ := range dict.derived { - wdict.reloc(relocType, typ) + wdict.reloc(relocType, typ.idx) + wdict.bool(typ.needed) + } + wdict.len(len(dict.funcs)) + for _, fn := range dict.funcs { + wdict.reloc(relocObj, fn.idx) + wdict.len(len(fn.explicits)) + for _, targ := range fn.explicits { + wdict.typInfo(targ) + } } wdict.flush() @@ -1103,6 +1179,9 @@ func (w *writer) expr(expr syntax.Expr) { obj, targs := lookupObj(w.p.info, expr) if tv, ok := w.p.info.Types[expr]; ok { + // TODO(mdempsky): Be more judicious about which types are marked as "needed". + w.needType(tv.Type) + if tv.IsType() { w.code(exprType) w.typ(tv.Type) @@ -1356,6 +1435,20 @@ func (w *writer) op(op ir.Op) { w.len(int(op)) } +func (w *writer) needType(typ types2.Type) { + // Decompose tuple into component element types. + if typ, ok := typ.(*types2.Tuple); ok { + for i := 0; i < typ.Len(); i++ { + w.needType(typ.At(i).Type()) + } + return + } + + if info := w.p.typIdx(typ, w.dict); info.derived { + w.dict.derived[info.idx].needed = true + } +} + // @@@ Package initialization // Caution: This code is still clumsy, because toolstash -cmp is -- GitLab From 2b10d7ff0be9ee5ebe1856349714f78936bf059d Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Wed, 14 Jul 2021 14:19:36 -0400 Subject: [PATCH 0440/2500] [dev.typeparams] go/types: export the Config.GoVersion field Export the types.Config.GoVersion field, so that users can specify a language compatibility version for go/types to enforce. Updates #46648 Change-Id: I9e00122925faf0006cfb08c3f2d022619d5d54d5 Reviewed-on: https://go-review.googlesource.com/c/go/+/334533 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/api.go | 4 ++-- src/go/types/check.go | 4 ++-- src/go/types/check_test.go | 2 +- src/go/types/stdlib_test.go | 3 +-- src/go/types/types_test.go | 6 ------ 5 files changed, 6 insertions(+), 13 deletions(-) diff --git a/src/go/types/api.go b/src/go/types/api.go index d3a95bc991..2bfbb8ce0c 100644 --- a/src/go/types/api.go +++ b/src/go/types/api.go @@ -103,12 +103,12 @@ type ImporterFrom interface { // A Config specifies the configuration for type checking. // The zero value for Config is a ready-to-use default configuration. type Config struct { - // goVersion describes the accepted Go language version. The string + // GoVersion describes the accepted Go language version. The string // must follow the format "go%d.%d" (e.g. "go1.12") or it must be // empty; an empty string indicates the latest language version. // If the format is invalid, invoking the type checker will cause a // panic. - goVersion string + GoVersion string // If IgnoreFuncBodies is set, function bodies are not // type-checked. diff --git a/src/go/types/check.go b/src/go/types/check.go index e82056e722..aea319f463 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -180,9 +180,9 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch info = new(Info) } - version, err := parseGoVersion(conf.goVersion) + version, err := parseGoVersion(conf.GoVersion) if err != nil { - panic(fmt.Sprintf("invalid Go version %q (%v)", conf.goVersion, err)) + panic(fmt.Sprintf("invalid Go version %q (%v)", conf.GoVersion, err)) } return &Checker{ diff --git a/src/go/types/check_test.go b/src/go/types/check_test.go index a5720f992e..f0cfced97f 100644 --- a/src/go/types/check_test.go +++ b/src/go/types/check_test.go @@ -244,7 +244,7 @@ func testFiles(t *testing.T, sizes Sizes, filenames []string, srcs [][]byte, man // typecheck and collect typechecker errors var conf Config conf.Sizes = sizes - SetGoVersion(&conf, goVersion) + conf.GoVersion = goVersion // special case for importC.src if len(filenames) == 1 { diff --git a/src/go/types/stdlib_test.go b/src/go/types/stdlib_test.go index d86a77a110..3eb7519a91 100644 --- a/src/go/types/stdlib_test.go +++ b/src/go/types/stdlib_test.go @@ -140,8 +140,7 @@ func testTestDir(t *testing.T, path string, ignore ...string) { // parse and type-check file file, err := parser.ParseFile(fset, filename, nil, 0) if err == nil { - conf := Config{Importer: stdLibImporter} - SetGoVersion(&conf, goVersion) + conf := Config{GoVersion: goVersion, Importer: stdLibImporter} _, err = conf.Check(filename, fset, []*ast.File{file}, nil) } diff --git a/src/go/types/types_test.go b/src/go/types/types_test.go index 7990414f42..f2358c6e19 100644 --- a/src/go/types/types_test.go +++ b/src/go/types/types_test.go @@ -4,11 +4,5 @@ package types -// SetGoVersion sets the unexported goVersion field on config, so that tests -// which assert on behavior for older Go versions can set it. -func SetGoVersion(config *Config, goVersion string) { - config.goVersion = goVersion -} - // Debug is set if go/types is built with debug mode enabled. const Debug = debug -- GitLab From e3e6cd30221185d6e4fa76f109f96fdede580729 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 13 Jul 2021 22:21:54 -0700 Subject: [PATCH 0441/2500] [dev.typeparams] cmd/compile: fix escape printout bugs for -G=3 Call SetPos() in g.expr() so it is available for any new nodes. Print out the actual type for a composite literal in exprFmt() if available, else use Ntype if available. Seems generally useful, since the type name is always more useful than just 'composite literal'. Fixes a bunch of cases that are excluded in run.go for -G=3. Change-Id: I40b9bba88027ea4f36d419e3989e7f14891bea04 Reviewed-on: https://go-review.googlesource.com/c/go/+/334609 Trust: Dan Scales Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/fmt.go | 4 +++ src/cmd/compile/internal/noder/expr.go | 5 ++++ test/run.go | 34 +++----------------------- 3 files changed, 12 insertions(+), 31 deletions(-) diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index 6f6e26dec4..e8dd9df69d 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -714,6 +714,10 @@ func exprFmt(n Node, s fmt.State, prec int) { fmt.Fprintf(s, "... argument") return } + if typ := n.Type(); typ != nil { + fmt.Fprintf(s, "%v{%s}", typ, ellipsisIf(len(n.List) != 0)) + return + } if n.Ntype != nil { fmt.Fprintf(s, "%v{%s}", n.Ntype, ellipsisIf(len(n.List) != 0)) return diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 16470a5449..66ce1bfe4c 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -88,6 +88,11 @@ func (g *irgen) expr(expr syntax.Expr) ir.Node { func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { pos := g.pos(expr) + assert(pos.IsKnown()) + + // Set base.Pos for transformation code that still uses base.Pos, rather than + // the pos of the node being converted. + base.Pos = pos switch expr := expr.(type) { case *syntax.Name: diff --git a/test/run.go b/test/run.go index d6209c2591..82d49270f2 100644 --- a/test/run.go +++ b/test/run.go @@ -2167,40 +2167,12 @@ var types2Failures32Bit = setOf( ) var g3Failures = setOf( - // TODO: Triage tests without explicit failure explanations. From a - // cursory inspection, they mostly fall into: - // - Anonymous result parameters given different names (e.g., ~r0 vs ~r1) - // - Some escape analysis diagnostics being printed without position information - // - Some expressions printed differently (e.g., "int(100)" instead - // of "100" or "&composite literal" instead of "&[4]int{...}"). - - "closure3.go", // prints "s escapes to heap" without line number - "escape2.go", - "escape2n.go", - "escape4.go", // prints "1 escapes to heap" without line number - "escape_calls.go", - "escape_field.go", - "escape_iface.go", - "escape_indir.go", - "escape_level.go", - "escape_map.go", - "escape_param.go", - "escape_slice.go", - "escape_struct_param1.go", - "escape_struct_param2.go", - "writebarrier.go", // correct diagnostics, but different lines (probably irgen's fault) - - "fixedbugs/issue12006.go", - "fixedbugs/issue13799.go", + "writebarrier.go", // correct diagnostics, but different lines (probably irgen's fault) "fixedbugs/issue17270.go", // ICE in irgen "fixedbugs/issue20174.go", // ICE due to width not calculated (probably irgen's fault) "fixedbugs/issue20250.go", // correct diagnostics, but different lines (probably irgen's fault) - "fixedbugs/issue21709.go", - "fixedbugs/issue31573.go", - "fixedbugs/issue37837.go", - "fixedbugs/issue39292.go", - "fixedbugs/issue7921.go", // prints "composite literal does not escape" but test expects "[]byte{...} does not escape" - "fixedbugs/issue9691.go", // "cannot assign to int(.autotmp_4)" (probably irgen's fault) + "fixedbugs/issue37837.go", // ICE due to width not calculated + "fixedbugs/issue9691.go", // "cannot assign to int(.autotmp_4)" (probably irgen's fault) "typeparam/nested.go", // -G=3 doesn't support function-local types with generics -- GitLab From ff33d3dc3a47a4eed17728b8460de4572198cec3 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 9 Jul 2021 17:12:07 -0700 Subject: [PATCH 0442/2500] [dev.typeparams] cmd/compile/internal/types2: implement <-ch where ch is of type parameter type For #43671 Change-Id: I7db4b3886fab44ec0de7c0935e0ab21c26e3335c Reviewed-on: https://go-review.googlesource.com/c/go/+/333709 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/expr.go | 36 +++++++++--- .../types2/testdata/fixedbugs/issue43671.go2 | 58 +++++++++++++++++++ 2 files changed, 85 insertions(+), 9 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue43671.go2 diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index bd35417c64..d4425a2bfd 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -157,6 +157,14 @@ var op2str2 = [...]string{ syntax.Shl: "shift", } +func underIs(typ Type, f func(Type) bool) bool { + u := under(typ) + if tpar, _ := u.(*TypeParam); tpar != nil { + return tpar.underIs(f) + } + return f(u) +} + func (check *Checker) unary(x *operand, e *syntax.Operation) { check.expr(x, e.X) if x.mode == invalid { @@ -177,19 +185,29 @@ func (check *Checker) unary(x *operand, e *syntax.Operation) { return case syntax.Recv: - typ := asChan(x.typ) - if typ == nil { - check.errorf(x, invalidOp+"cannot receive from non-channel %s", x) - x.mode = invalid - return - } - if typ.dir == SendOnly { - check.errorf(x, invalidOp+"cannot receive from send-only channel %s", x) + var elem Type + if !underIs(x.typ, func(u Type) bool { + ch, _ := u.(*Chan) + if ch == nil { + check.errorf(x, invalidOp+"cannot receive from non-channel %s", x) + return false + } + if ch.dir == SendOnly { + check.errorf(x, invalidOp+"cannot receive from send-only channel %s", x) + return false + } + if elem != nil && !Identical(ch.elem, elem) { + check.errorf(x, invalidOp+"channels of %s must have the same element type", x) + return false + } + elem = ch.elem + return true + }) { x.mode = invalid return } x.mode = commaok - x.typ = typ.elem + x.typ = elem check.hasCallOrRecv = true return } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43671.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43671.go2 new file mode 100644 index 0000000000..6cc3801cc9 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43671.go2 @@ -0,0 +1,58 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type C0 interface{ int } +type C1 interface{ chan int } +type C2 interface{ chan int | <-chan int } +type C3 interface{ chan int | chan float32 } +type C4 interface{ chan int | chan<- int } +type C5[T any] interface{ ~chan T | <-chan T } + +func _[T any](ch T) { + <-ch // ERROR cannot receive from non-channel +} + +func _[T C0](ch T) { + <-ch // ERROR cannot receive from non-channel +} + +func _[T C1](ch T) { + <-ch +} + +func _[T C2](ch T) { + <-ch +} + +func _[T C3](ch T) { + <-ch // ERROR channels of ch .* must have the same element type +} + +func _[T C4](ch T) { + <-ch // ERROR cannot receive from send-only channel +} + +func _[T C5[X], X any](ch T, x X) { + x = <-ch +} + +// test case from issue, slightly modified +type RecvChan[T any] interface { + ~chan T | ~<-chan T +} + +func _[T any, C RecvChan[T]](ch C) T { + return <-ch +} + +func f[T any, C interface{ chan T }](ch C) T { + return <-ch +} + +func _(ch chan int) { + var x int = f(ch) // test constraint type inference for this case + _ = x +} -- GitLab From 6511922a142e6adbd91bec93e2c4d51a93955713 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 9 Jul 2021 17:43:25 -0700 Subject: [PATCH 0443/2500] [dev.typeparams] cmd/compile/internal/types2: implement ch <- x where ch is of type parameter type For #47115. Change-Id: Ib9c8652c0346029369735ccf7ee9098ab1ae7fd3 Reviewed-on: https://go-review.googlesource.com/c/go/+/333712 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/stmt.go | 36 ++++++++++------- .../types2/testdata/fixedbugs/issue47115.go2 | 40 +++++++++++++++++++ 2 files changed, 62 insertions(+), 14 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue47115.go2 diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index b41b23fedb..9b8295c4f4 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -352,25 +352,33 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) { check.errorf(&x, "%s %s", &x, msg) case *syntax.SendStmt: - var ch, x operand + var ch, val operand check.expr(&ch, s.Chan) - check.expr(&x, s.Value) - if ch.mode == invalid || x.mode == invalid { + check.expr(&val, s.Value) + if ch.mode == invalid || val.mode == invalid { return } - - tch := asChan(ch.typ) - if tch == nil { - check.errorf(s, invalidOp+"cannot send to non-chan type %s", ch.typ) - return - } - - if tch.dir == RecvOnly { - check.errorf(s, invalidOp+"cannot send to receive-only type %s", tch) + var elem Type + if !underIs(ch.typ, func(u Type) bool { + uch, _ := u.(*Chan) + if uch == nil { + check.errorf(s, invalidOp+"cannot send to non-channel %s", &ch) + return false + } + if uch.dir == RecvOnly { + check.errorf(s, invalidOp+"cannot send to receive-only channel %s", &ch) + return false + } + if elem != nil && !Identical(uch.elem, elem) { + check.errorf(s, invalidOp+"channels of %s must have the same element type", &ch) + return false + } + elem = uch.elem + return true + }) { return } - - check.assignment(&x, tch.elem, "send") + check.assignment(&val, elem, "send") case *syntax.AssignStmt: lhs := unpackExpr(s.Lhs) diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47115.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47115.go2 new file mode 100644 index 0000000000..00828eb997 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47115.go2 @@ -0,0 +1,40 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type C0 interface{ int } +type C1 interface{ chan int } +type C2 interface{ chan int | <-chan int } +type C3 interface{ chan int | chan float32 } +type C4 interface{ chan int | chan<- int } +type C5[T any] interface{ ~chan T | chan<- T } + +func _[T any](ch T) { + ch /* ERROR cannot send to non-channel */ <- 0 +} + +func _[T C0](ch T) { + ch /* ERROR cannot send to non-channel */ <- 0 +} + +func _[T C1](ch T) { + ch <- 0 +} + +func _[T C2](ch T) { + ch /* ERROR cannot send to receive-only channel */ <- 0 +} + +func _[T C3](ch T) { + ch /* ERROR channels of ch .* must have the same element type */ <- 0 +} + +func _[T C4](ch T) { + ch <- 0 +} + +func _[T C5[X], X any](ch T, x X) { + ch <- x +} -- GitLab From 5f0ea40c67839ae82b6018fe881f173f9b09d306 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 9 Jul 2021 18:26:57 -0700 Subject: [PATCH 0444/2500] [dev.typeparams] cmd/compile/internal/types2: implement close(ch) where ch is of type parameter type Change-Id: I45189468553e83390fd2640b5708c60a7852fbb5 Reviewed-on: https://go-review.googlesource.com/c/go/+/333713 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/builtins.go | 22 +++++--- .../types2/testdata/check/builtins.go2 | 55 ++++++++++++++++--- .../types2/testdata/check/builtins.src | 2 +- src/cmd/compile/internal/types2/type.go | 7 --- test/chan/perm.go | 2 +- 5 files changed, 62 insertions(+), 26 deletions(-) diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 83d1743ee2..e1795aedac 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -212,19 +212,23 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( case _Close: // close(c) - c := asChan(x.typ) - if c == nil { - check.errorf(x, invalidArg+"%s is not a channel", x) - return - } - if c.dir == RecvOnly { - check.errorf(x, invalidArg+"%s must not be a receive-only channel", x) + if !underIs(x.typ, func(u Type) bool { + uch, _ := u.(*Chan) + if uch == nil { + check.errorf(x, invalidOp+"cannot close non-channel %s", x) + return false + } + if uch.dir == RecvOnly { + check.errorf(x, invalidOp+"cannot close receive-only channel %s", x) + return false + } + return true + }) { return } - x.mode = novalue if check.Types != nil { - check.recordBuiltinType(call.Fun, makeSig(nil, c)) + check.recordBuiltinType(call.Fun, makeSig(nil, x.typ)) } case _Complex: diff --git a/src/cmd/compile/internal/types2/testdata/check/builtins.go2 b/src/cmd/compile/internal/types2/testdata/check/builtins.go2 index 5bb67efec9..71295bf434 100644 --- a/src/cmd/compile/internal/types2/testdata/check/builtins.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/builtins.go2 @@ -6,6 +6,45 @@ package builtins +// close + +type C0 interface{ int } +type C1 interface{ chan int } +type C2 interface{ chan int | <-chan int } +type C3 interface{ chan int | chan float32 } +type C4 interface{ chan int | chan<- int } +type C5[T any] interface{ ~chan T | chan<- T } + +func _[T any](ch T) { + close(ch /* ERROR cannot close non-channel */) +} + +func _[T C0](ch T) { + close(ch /* ERROR cannot close non-channel */) +} + +func _[T C1](ch T) { + close(ch) +} + +func _[T C2](ch T) { + close(ch /* ERROR cannot close receive-only channel */) +} + +func _[T C3](ch T) { + close(ch) +} + +func _[T C4](ch T) { + close(ch) +} + +func _[T C5[X], X any](ch T) { + close(ch) +} + +// make + type Bmc interface { ~map[rune]string | ~chan int } @@ -22,31 +61,31 @@ type Bss interface { ~[]int | ~[]string } -func _[T any] () { - _ = make(T /* ERROR invalid argument */ ) - _ = make(T /* ERROR invalid argument */ , 10) - _ = make(T /* ERROR invalid argument */ , 10, 20) +func _[T any]() { + _ = make(T /* ERROR invalid argument */) + _ = make(T /* ERROR invalid argument */, 10) + _ = make(T /* ERROR invalid argument */, 10, 20) } -func _[T Bmc] () { +func _[T Bmc]() { _ = make(T) _ = make(T, 10) _ = make /* ERROR expects 1 or 2 arguments */ (T, 10, 20) } -func _[T Bms] () { +func _[T Bms]() { _ = make /* ERROR expects 2 arguments */ (T) _ = make(T, 10) _ = make /* ERROR expects 2 arguments */ (T, 10, 20) } -func _[T Bcs] () { +func _[T Bcs]() { _ = make /* ERROR expects 2 arguments */ (T) _ = make(T, 10) _ = make /* ERROR expects 2 arguments */ (T, 10, 20) } -func _[T Bss] () { +func _[T Bss]() { _ = make /* ERROR expects 2 or 3 arguments */ (T) _ = make(T, 10) _ = make(T, 10, 20) diff --git a/src/cmd/compile/internal/types2/testdata/check/builtins.src b/src/cmd/compile/internal/types2/testdata/check/builtins.src index 6d1f47129b..17e4068d65 100644 --- a/src/cmd/compile/internal/types2/testdata/check/builtins.src +++ b/src/cmd/compile/internal/types2/testdata/check/builtins.src @@ -144,7 +144,7 @@ func close1() { var r <-chan int close() // ERROR not enough arguments close(1, 2) // ERROR too many arguments - close(42 /* ERROR not a channel */) + close(42 /* ERROR cannot close non-channel */) close(r /* ERROR receive-only channel */) close(c) _ = close /* ERROR used as value */ (c) diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index c2da97605b..84cf36de2c 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -105,8 +105,6 @@ func asPointer(t Type) *Pointer { return op } -// asTuple is not needed - not provided - func asSignature(t Type) *Signature { op, _ := optype(t).(*Signature) return op @@ -117,11 +115,6 @@ func asMap(t Type) *Map { return op } -func asChan(t Type) *Chan { - op, _ := optype(t).(*Chan) - return op -} - // If the argument to asInterface, asNamed, or asTypeParam is of the respective type // (possibly after expanding an instance type), these methods return that type. // Otherwise the result is nil. diff --git a/test/chan/perm.go b/test/chan/perm.go index 4c94ab7ffa..04046723a4 100644 --- a/test/chan/perm.go +++ b/test/chan/perm.go @@ -66,5 +66,5 @@ func main() { close(c) close(cs) close(cr) // ERROR "receive" - close(n) // ERROR "invalid operation.*non-chan type|must be channel|not a channel" + close(n) // ERROR "invalid operation.*non-chan type|must be channel|non-channel" } -- GitLab From 95f8e64fc0ff53e4df6ba03e8dbbaf3d18695d1b Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 9 Jul 2021 19:03:48 -0700 Subject: [PATCH 0445/2500] [dev.typeparams] cmd/compile/internal/types2: implement delete(m, k) where m is of type parameter type Change-Id: Iaf33c15128af911b6101df9885cb8b5a8495b942 Reviewed-on: https://go-review.googlesource.com/c/go/+/333729 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/builtins.go | 27 +++++++++++--- .../types2/testdata/check/builtins.go2 | 37 +++++++++++++++++++ src/cmd/compile/internal/types2/type.go | 5 --- 3 files changed, 58 insertions(+), 11 deletions(-) diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index e1795aedac..1f7eb23cdf 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -364,25 +364,40 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( x.typ = Typ[Int] case _Delete: - // delete(m, k) - m := asMap(x.typ) - if m == nil { - check.errorf(x, invalidArg+"%s is not a map", x) + // delete(map_, key) + // map_ must be a map type or a type parameter describing map types. + // The key cannot be a type parameter for now. + map_ := x.typ + var key Type + if !underIs(map_, func(u Type) bool { + map_, _ := u.(*Map) + if map_ == nil { + check.errorf(x, invalidArg+"%s is not a map", x) + return false + } + if key != nil && !Identical(map_.key, key) { + check.errorf(x, invalidArg+"maps of %s must have identical key types", x) + return false + } + key = map_.key + return true + }) { return } + arg(x, 1) // k if x.mode == invalid { return } - check.assignment(x, m.key, "argument to delete") + check.assignment(x, key, "argument to delete") if x.mode == invalid { return } x.mode = novalue if check.Types != nil { - check.recordBuiltinType(call.Fun, makeSig(nil, m, m.key)) + check.recordBuiltinType(call.Fun, makeSig(nil, map_, key)) } case _Imag, _Real: diff --git a/src/cmd/compile/internal/types2/testdata/check/builtins.go2 b/src/cmd/compile/internal/types2/testdata/check/builtins.go2 index 71295bf434..8fe6d7b332 100644 --- a/src/cmd/compile/internal/types2/testdata/check/builtins.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/builtins.go2 @@ -43,6 +43,43 @@ func _[T C5[X], X any](ch T) { close(ch) } +// delete + +type M0 interface{ int } +type M1 interface{ map[string]int } +type M2 interface { map[string]int | map[string]float64 } +type M3 interface{ map[string]int | map[rune]int } +type M4[K comparable, V any] interface{ map[K]V | map[rune]V } + +func _[T any](m T) { + delete(m /* ERROR not a map */, "foo") +} + +func _[T M0](m T) { + delete(m /* ERROR not a map */, "foo") +} + +func _[T M1](m T) { + delete(m, "foo") +} + +func _[T M2](m T) { + delete(m, "foo") + delete(m, 0 /* ERROR cannot use .* as string */) +} + +func _[T M3](m T) { + delete(m /* ERROR must have identical key types */, "foo") +} + +func _[T M4[rune, V], V any](m T) { + delete(m, 'k') +} + +func _[T M4[K, V], K comparable, V any](m T) { + delete(m /* ERROR must have identical key types */, "foo") +} + // make type Bmc interface { diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 84cf36de2c..b41b50393d 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -110,11 +110,6 @@ func asSignature(t Type) *Signature { return op } -func asMap(t Type) *Map { - op, _ := optype(t).(*Map) - return op -} - // If the argument to asInterface, asNamed, or asTypeParam is of the respective type // (possibly after expanding an instance type), these methods return that type. // Otherwise the result is nil. -- GitLab From 2a8087817c18314d81c4165258487cdba73ebc71 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 9 Jul 2021 21:18:12 -0700 Subject: [PATCH 0446/2500] [dev.typeparams] cmd/compile/internal/types2: cleanups around receiver type checks Generic receiver types may be defined such that an instantiated receiver ends up being a pointer type. Disallow them as we do for non-generic receivers. Change-Id: I6612a52615a2999375c35aa1d69ab42f37d9f55d Reviewed-on: https://go-review.googlesource.com/c/go/+/333770 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/signature.go | 32 ++++++++++++------- .../types2/testdata/examples/methods.go2 | 17 ++++++++++ 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index ab9a1c487e..fa5c3f7a9b 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -211,9 +211,10 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] // spec: "The receiver type must be of the form T or *T where T is a type name." // (ignore invalid types - error was reported before) - if t := rtyp; t != Typ[Invalid] { + if rtyp != Typ[Invalid] { var err string - if T := asNamed(t); T != nil { + switch T := rtyp.(type) { + case *Named: // spec: "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." @@ -224,23 +225,30 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] err = "" } } else { - switch u := optype(T).(type) { - case *Basic: - // unsafe.Pointer is treated like a regular pointer - if u.kind == UnsafePointer { - err = "unsafe.Pointer" + // The underlying type of a receiver base type can be a type parameter; + // e.g. for methods with a generic receiver T[P] with type T[P any] P. + underIs(T, func(u Type) bool { + switch u := u.(type) { + case *Basic: + // unsafe.Pointer is treated like a regular pointer + if u.kind == UnsafePointer { + err = "unsafe.Pointer" + return false + } + case *Pointer, *Interface: + err = "pointer or interface type" + return false } - case *Pointer, *Interface: - err = "pointer or interface type" - } + return true + }) } - } else if T := asBasic(t); T != nil { + case *Basic: err = "basic or unnamed type" if check.conf.CompilerErrorMessages { check.errorf(recv.pos, "cannot define new methods on non-local type %s", recv.typ) err = "" } - } else { + default: check.errorf(recv.pos, "invalid receiver type %s", recv.typ) } if err != "" { diff --git a/src/cmd/compile/internal/types2/testdata/examples/methods.go2 b/src/cmd/compile/internal/types2/testdata/examples/methods.go2 index 76c6539e1b..4e87041e54 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/methods.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/methods.go2 @@ -6,6 +6,8 @@ package p +import "unsafe" + // Parameterized types may have methods. type T1[A any] struct{ a A } @@ -94,3 +96,18 @@ func (_ T2[_, _, _]) _() int { return 42 } type T0 struct{} func (T0) _() {} func (T1[A]) _() {} + +// A generic receiver type may constrain its type parameter such +// that it must be a pointer type. Such receiver types are not +// permitted. +type T3a[P interface{ ~int | ~string | ~float64 }] P + +func (T3a[_]) m() {} // this is ok + +type T3b[P interface{ ~unsafe.Pointer }] P + +func (T3b /* ERROR invalid receiver */ [_]) m() {} + +type T3c[P interface{ *int | *string }] P + +func (T3c /* ERROR invalid receiver */ [_]) m() {} -- GitLab From dd8bdf4a1fceb06231eb73c026f4a7fe41f00dc1 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sun, 11 Jul 2021 15:27:49 -0700 Subject: [PATCH 0447/2500] [dev.typeparams] cmd/compile/internal/types2: interface identity must consider full type set There is no (obvious) way to test this at the moment because we don't permit such constraint interfaces as ordinary types. Change-Id: Ieeec023ed82a2c71ed50d111f26916aba4a59099 Reviewed-on: https://go-review.googlesource.com/c/go/+/333889 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/predicates.go | 17 +++++++++++++---- src/cmd/compile/internal/types2/unify.go | 12 ++++++++---- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 2f10898585..e862c0fca8 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -270,12 +270,21 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { } case *Interface: + // Two interface types are identical if they describe the same type sets. + // With the existing implementation restriction, this simplifies to: + // // Two interface types are identical if they have the same set of methods with - // the same names and identical function types. Lower-case method names from - // different packages are always different. The order of the methods is irrelevant. + // the same names and identical function types, and if any type restrictions + // are the same. Lower-case method names from different packages are always + // different. The order of the methods is irrelevant. if y, ok := y.(*Interface); ok { - a := x.typeSet().methods - b := y.typeSet().methods + xset := x.typeSet() + yset := y.typeSet() + if !Identical(xset.types, yset.types) { + return false + } + a := xset.methods + b := yset.methods if len(a) == len(b) { // Interface types are the only types where cycles can occur // that are not "terminated" via named types; and such cycles diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index 755622738a..7221356354 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -362,16 +362,20 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { } case *Union: - // This should not happen with the current internal use of union types. - panic("type inference across union types not implemented") + panic("unimplemented: unification with type sets described by types") case *Interface: // Two interface types are identical if they have the same set of methods with // the same names and identical function types. Lower-case method names from // different packages are always different. The order of the methods is irrelevant. if y, ok := y.(*Interface); ok { - a := x.typeSet().methods - b := y.typeSet().methods + xset := x.typeSet() + yset := y.typeSet() + if !Identical(xset.types, yset.types) { + return false + } + a := xset.methods + b := yset.methods if len(a) == len(b) { // Interface types are the only types where cycles can occur // that are not "terminated" via named types; and such cycles -- GitLab From 3a047326e896302724378e5d6b8684851ccfdbfd Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sun, 11 Jul 2021 15:59:22 -0700 Subject: [PATCH 0448/2500] [dev.typeparams] cmd/compile/internal/types2: fix generic type indirection Change-Id: If25ceb2aa403b94608760be331faa2aff11c47cc Reviewed-on: https://go-review.googlesource.com/c/go/+/333890 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/expr.go | 21 ++++++++++---- .../types2/testdata/examples/operations.go2 | 29 +++++++++++++++++++ 2 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/examples/operations.go2 diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index d4425a2bfd..008c2446fc 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -1479,13 +1479,24 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin case typexpr: x.typ = &Pointer{base: x.typ} default: - if typ := asPointer(x.typ); typ != nil { - x.mode = variable - x.typ = typ.base - } else { - check.errorf(x, invalidOp+"cannot indirect %s", x) + var base Type + if !underIs(x.typ, func(u Type) bool { + p, _ := u.(*Pointer) + if p == nil { + check.errorf(x, invalidOp+"cannot indirect %s", x) + return false + } + if base != nil && !Identical(p.base, base) { + check.errorf(x, invalidOp+"pointers of %s must have identical base types", x) + return false + } + base = p.base + return true + }) { goto Error } + x.mode = variable + x.typ = base } break } diff --git a/src/cmd/compile/internal/types2/testdata/examples/operations.go2 b/src/cmd/compile/internal/types2/testdata/examples/operations.go2 new file mode 100644 index 0000000000..18e4d6080c --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/examples/operations.go2 @@ -0,0 +1,29 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +// indirection + +func _[P any](p P) { + _ = *p // ERROR cannot indirect p +} + +func _[P interface{ int }](p P) { + _ = *p // ERROR cannot indirect p +} + +func _[P interface{ *int }](p P) { + _ = *p +} + +func _[P interface{ *int | *string }](p P) { + _ = *p // ERROR must have identical base types +} + +type intPtr *int + +func _[P interface{ *int | intPtr } ](p P) { + var _ int = *p +} -- GitLab From 4ff0e04c2e409aaeebe0cf5287dbed735f84e974 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 12 Jul 2021 22:39:39 -0700 Subject: [PATCH 0449/2500] [dev.typeparams] cmd/compile/internal/types2: embedding stand-alone type parameters is not permitted For #47127. Change-Id: Ie979ff56ae7c2dd0e5ce0ff39588f98ae68b5ee9 Reviewed-on: https://go-review.googlesource.com/c/go/+/334151 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- .../internal/types2/testdata/check/issues.go2 | 2 +- .../types2/testdata/check/tinference.go2 | 42 ++++++++++--------- .../types2/testdata/fixedbugs/issue39634.go2 | 7 ++-- .../types2/testdata/fixedbugs/issue39680.go2 | 4 ++ .../types2/testdata/fixedbugs/issue39948.go2 | 10 +---- .../types2/testdata/fixedbugs/issue47127.go2 | 37 ++++++++++++++++ src/cmd/compile/internal/types2/typeset.go | 8 ++-- src/cmd/compile/internal/types2/union.go | 11 +++-- test/typeparam/typelist.go | 6 +++ 9 files changed, 87 insertions(+), 40 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue47127.go2 diff --git a/src/cmd/compile/internal/types2/testdata/check/issues.go2 b/src/cmd/compile/internal/types2/testdata/check/issues.go2 index 88ae294d7c..32c4320d27 100644 --- a/src/cmd/compile/internal/types2/testdata/check/issues.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/issues.go2 @@ -232,7 +232,7 @@ func _[T interface{ ~func() }](f T) { type sliceOf[E any] interface{ ~[]E } -func append[T interface{}, S sliceOf[T], T2 interface{ T }](s S, t ...T2) S +func append[T interface{}, S sliceOf[T], T2 interface{}](s S, t ...T2) S var f func() var cancelSlice []context.CancelFunc diff --git a/src/cmd/compile/internal/types2/testdata/check/tinference.go2 b/src/cmd/compile/internal/types2/testdata/check/tinference.go2 index 2fdb39ca7a..1b70981759 100644 --- a/src/cmd/compile/internal/types2/testdata/check/tinference.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/tinference.go2 @@ -8,19 +8,20 @@ import "strconv" type any interface{} -func f0[A any, B interface{~C}, C interface{~D}, D interface{~A}](A, B, C, D) -func _() { - f := f0[string] - f("a", "b", "c", "d") - f0("a", "b", "c", "d") -} - -func f1[A any, B interface{~A}](A, B) -func _() { - f := f1[int] - f(int(0), int(0)) - f1(int(0), int(0)) -} +// Embedding stand-alone type parameters is not permitted for now. Disabled. +// func f0[A any, B interface{~C}, C interface{~D}, D interface{~A}](A, B, C, D) +// func _() { +// f := f0[string] +// f("a", "b", "c", "d") +// f0("a", "b", "c", "d") +// } +// +// func f1[A any, B interface{~A}](A, B) +// func _() { +// f := f1[int] +// f(int(0), int(0)) +// f1(int(0), int(0)) +// } func f2[A any, B interface{~[]A}](A, B) func _() { @@ -29,13 +30,14 @@ func _() { f2(byte(0), []byte{}) } -func f3[A any, B interface{~C}, C interface{~*A}](A, B, C) -func _() { - f := f3[int] - var x int - f(x, &x, &x) - f3(x, &x, &x) -} +// Embedding stand-alone type parameters is not permitted for now. Disabled. +// func f3[A any, B interface{~C}, C interface{~*A}](A, B, C) +// func _() { +// f := f3[int] +// var x int +// f(x, &x, &x) +// f3(x, &x, &x) +// } func f4[A any, B interface{~[]C}, C interface{~*A}](A, B, C) func _() { diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 index 6d002f5d2f..5cb15e7e58 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 @@ -31,9 +31,10 @@ type x7[A any] struct{ foo7 } func main7() { var _ foo7 = x7[int]{} } // crash 8 -type foo8[A any] interface { ~A } -func bar8[A foo8[A]](a A) {} -func main8() {} +// Embedding stand-alone type parameters is not permitted for now. Disabled. +// type foo8[A any] interface { ~A } +// func bar8[A foo8[A]](a A) {} +// func main8() {} // crash 9 type foo9[A any] interface { foo9 /* ERROR illegal cycle */ [A] } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39680.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39680.go2 index 01eadd2dbf..e56bc35475 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39680.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39680.go2 @@ -4,6 +4,9 @@ package p +// Embedding stand-alone type parameters is not permitted for now. Disabled. + +/* import "fmt" // Minimal test case. @@ -25,3 +28,4 @@ func Print[T constr[T]](s []T) { func f() { Print([]string{"Hello, ", "playground\n"}) } +*/ diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39948.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39948.go2 index 6372397ed9..e38e57268d 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39948.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39948.go2 @@ -2,14 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// TODO(gri) Eventually, once we disallow type lists, we need to -// adjust this code: for 1.17 we don't accept type parameters, -// and for 1.18 this code is valid. -// Leaving for now so we can see that existing errors -// are being reported. - -package go1_17 // don't permit non-interface elements in interfaces +package p type T[P any] interface{ - P // ERROR P is a type parameter, not an interface + P // ERROR cannot embed a type parameter } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47127.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47127.go2 new file mode 100644 index 0000000000..387c946957 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47127.go2 @@ -0,0 +1,37 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Embedding of stand-alone type parameters is not permitted. + +package p + +type ( + _[P any] interface{ *P | []P | chan P | map[string]P } + _[P any] interface{ P /* ERROR "cannot embed a type parameter" */ } + _[P any] interface{ ~P /* ERROR "cannot embed a type parameter" */ } + _[P any] interface{ int | P /* ERROR "cannot embed a type parameter" */ } + _[P any] interface{ int | ~P /* ERROR "cannot embed a type parameter" */ } +) + +func _[P any]() { + type ( + _[P any] interface{ *P | []P | chan P | map[string]P } + _[P any] interface{ P /* ERROR "cannot embed a type parameter" */ } + _[P any] interface{ ~P /* ERROR "cannot embed a type parameter" */ } + _[P any] interface{ int | P /* ERROR "cannot embed a type parameter" */ } + _[P any] interface{ int | ~P /* ERROR "cannot embed a type parameter" */ } + + _ interface{ *P | []P | chan P | map[string]P } + _ interface{ P /* ERROR "cannot embed a type parameter" */ } + _ interface{ ~P /* ERROR "cannot embed a type parameter" */ } + _ interface{ int | P /* ERROR "cannot embed a type parameter" */ } + _ interface{ int | ~P /* ERROR "cannot embed a type parameter" */ } + ) +} + +func _[P any, Q interface{ *P | []P | chan P | map[string]P }]() +func _[P any, Q interface{ P /* ERROR "cannot embed a type parameter" */ }]() +func _[P any, Q interface{ ~P /* ERROR "cannot embed a type parameter" */ }]() +func _[P any, Q interface{ int | P /* ERROR "cannot embed a type parameter" */ }]() +func _[P any, Q interface{ int | ~P /* ERROR "cannot embed a type parameter" */ }]() diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index 4aee8e4097..8e6af8e65c 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -216,11 +216,9 @@ func computeTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *TypeSet { // interface before go1.18. types = typ case *TypeParam: - if check != nil && !check.allowVersion(check.pkg, 1, 18) { - check.errorf(pos, "%s is a type parameter, not an interface", typ) - continue - } - types = typ + // Embedding stand-alone type parameters is not permitted for now. + // This case is handled during union parsing. + unreachable() default: if typ == Typ[Invalid] { continue diff --git a/src/cmd/compile/internal/types2/union.go b/src/cmd/compile/internal/types2/union.go index e5e851c1d2..5983a73ec6 100644 --- a/src/cmd/compile/internal/types2/union.go +++ b/src/cmd/compile/internal/types2/union.go @@ -128,13 +128,18 @@ func parseUnion(check *Checker, tlist []syntax.Expr) Type { return newUnion(types, tilde) } -func parseTilde(check *Checker, x syntax.Expr) (Type, bool) { - tilde := false +func parseTilde(check *Checker, x syntax.Expr) (typ Type, tilde bool) { if op, _ := x.(*syntax.Operation); op != nil && op.Op == syntax.Tilde { x = op.X tilde = true } - return check.anyType(x), tilde + typ = check.anyType(x) + // embedding stand-alone type parameters is not permitted (issue #47127). + if _, ok := under(typ).(*TypeParam); ok { + check.error(x, "cannot embed a type parameter") + typ = Typ[Invalid] + } + return } // intersect computes the intersection of the types x and y, diff --git a/test/typeparam/typelist.go b/test/typeparam/typelist.go index bd90d86fcf..5c51c9c461 100644 --- a/test/typeparam/typelist.go +++ b/test/typeparam/typelist.go @@ -67,6 +67,8 @@ func _[V any, T interface { type map[string]V }](p T) V { // Testing partial and full type inference, including the case where the types can // be inferred without needing the types of the function arguments. +// Cannot embed stand-alone type parameters. Disabled for now. +/* func f0[A any, B interface{type C}, C interface{type D}, D interface{type A}](A, B, C, D) func _() { f := f0[string] @@ -82,6 +84,7 @@ func _() { f(0, 0) f1(0, 0) } +*/ func f2[A any, B interface{type []A}](_ A, _ B) func _() { @@ -92,6 +95,8 @@ func _() { // f2(0, []byte{}) - this one doesn't work } +// Cannot embed stand-alone type parameters. Disabled for now. +/* func f3[A any, B interface{type C}, C interface{type *A}](a A, _ B, c C) func _() { f := f3[int] @@ -99,6 +104,7 @@ func _() { f(x, &x, &x) f3(x, &x, &x) } +*/ func f4[A any, B interface{type []C}, C interface{type *A}](_ A, _ B, c C) func _() { -- GitLab From 6b85a218b86fbc46916d838724d674baf312cc3c Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 15 Jul 2021 13:06:13 -0700 Subject: [PATCH 0450/2500] [dev.typeparams] cmd/compile: make TestUnifiedCompare insensitive to default -G level The test currently fails if the default -G level is changed from 0 to 3, and it only makes sense to run in -G=0 mode anyway. So might as well hard code it that way. Change-Id: I026d25d567157df5d3f2ca3c68d31d75d9c74532 Reviewed-on: https://go-review.googlesource.com/c/go/+/334910 Trust: Matthew Dempsky Trust: Dan Scales Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/unified_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/noder/unified_test.go b/src/cmd/compile/internal/noder/unified_test.go index 26173682fb..96cc66f775 100644 --- a/src/cmd/compile/internal/noder/unified_test.go +++ b/src/cmd/compile/internal/noder/unified_test.go @@ -54,8 +54,8 @@ func TestUnifiedCompare(t *testing.T) { t.Parallel() } - pkgs1 := loadPackages(t, goos, goarch, "-d=unified=0 -d=inlfuncswithclosures=0 -d=unifiedquirks=1") - pkgs2 := loadPackages(t, goos, goarch, "-d=unified=1 -d=inlfuncswithclosures=0 -d=unifiedquirks=1") + pkgs1 := loadPackages(t, goos, goarch, "-d=unified=0 -d=inlfuncswithclosures=0 -d=unifiedquirks=1 -G=0") + pkgs2 := loadPackages(t, goos, goarch, "-d=unified=1 -d=inlfuncswithclosures=0 -d=unifiedquirks=1 -G=0") if len(pkgs1) != len(pkgs2) { t.Fatalf("length mismatch: %v != %v", len(pkgs1), len(pkgs2)) -- GitLab From 334f2fc045b7d9d846cccba01b3a0dbf70ddb0db Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 11 Jun 2021 10:58:43 -0400 Subject: [PATCH 0451/2500] [dev.typeparams] go/*: switch from ListExpr to MultiIndexExpr When instantiating a generic type or function with multiple type arguments, we need to represent an index expression with multiple indexes in the AST. Previous to this CL this was done with a new ast.ListExpr node, which allowed packing multiple expressions into a single ast.Expr. This compositional pattern can be both inefficient and cumbersome to work with, and introduces a new node type that only exists to augment the meaning of an existing node type. By comparison, other specializations of syntax are given distinct nodes in go/ast, for example variations of switch or for statements, so the use of ListExpr was also (arguably) inconsistent. This CL removes ListExpr, and instead adds a MultiIndexExpr node, which is exactly like IndexExpr but allows for multiple index arguments. This requires special handling for this new node type, but a new wrapper in the typeparams helper package largely mitigates this special handling. Change-Id: I65eb29c025c599bae37501716284dc7eb953b2ad Reviewed-on: https://go-review.googlesource.com/c/go/+/327149 Trust: Robert Findley Reviewed-by: Robert Griesemer Run-TryBot: Robert Findley TryBot-Result: Go Bot --- src/go/ast/ast.go | 56 ++++++++---------- src/go/ast/walk.go | 11 ++-- src/go/internal/typeparams/typeparams.go | 58 ++++++++++++------- src/go/parser/parser.go | 22 +++++-- src/go/printer/nodes.go | 20 +++---- src/go/types/call.go | 46 +++++++-------- src/go/types/expr.go | 14 ++--- src/go/types/exprstring.go | 8 +-- src/go/types/index.go | 37 +++++------- src/go/types/resolver.go | 10 ++-- src/go/types/signature.go | 27 ++++----- src/go/types/testdata/check/typeinst.go2 | 6 +- .../types/testdata/fixedbugs/issue45635.go2 | 2 +- src/go/types/typexpr.go | 20 +++---- 14 files changed, 170 insertions(+), 167 deletions(-) diff --git a/src/go/ast/ast.go b/src/go/ast/ast.go index a34cafcb4e..b0f1330564 100644 --- a/src/go/ast/ast.go +++ b/src/go/ast/ast.go @@ -344,6 +344,15 @@ type ( Rbrack token.Pos // position of "]" } + // A MultiIndexExpr node represents an expression followed by multiple + // indices. + MultiIndexExpr struct { + X Expr // expression + Lbrack token.Pos // position of "[" + Indices []Expr // index expressions + Rbrack token.Pos // position of "]" + } + // A SliceExpr node represents an expression followed by slice indices. SliceExpr struct { X Expr // expression @@ -374,13 +383,6 @@ type ( Rparen token.Pos // position of ")" } - // A ListExpr node represents a list of expressions separated by commas. - // ListExpr nodes are used as index in IndexExpr nodes representing type - // or function instantiations with more than one type argument. - ListExpr struct { - ElemList []Expr - } - // A StarExpr node represents an expression of the form "*" Expression. // Semantically it could be a unary "*" expression, or a pointer type. // @@ -494,21 +496,16 @@ func (x *CompositeLit) Pos() token.Pos { func (x *ParenExpr) Pos() token.Pos { return x.Lparen } func (x *SelectorExpr) Pos() token.Pos { return x.X.Pos() } func (x *IndexExpr) Pos() token.Pos { return x.X.Pos() } +func (x *MultiIndexExpr) Pos() token.Pos { return x.X.Pos() } func (x *SliceExpr) Pos() token.Pos { return x.X.Pos() } func (x *TypeAssertExpr) Pos() token.Pos { return x.X.Pos() } func (x *CallExpr) Pos() token.Pos { return x.Fun.Pos() } -func (x *ListExpr) Pos() token.Pos { - if len(x.ElemList) > 0 { - return x.ElemList[0].Pos() - } - return token.NoPos -} -func (x *StarExpr) Pos() token.Pos { return x.Star } -func (x *UnaryExpr) Pos() token.Pos { return x.OpPos } -func (x *BinaryExpr) Pos() token.Pos { return x.X.Pos() } -func (x *KeyValueExpr) Pos() token.Pos { return x.Key.Pos() } -func (x *ArrayType) Pos() token.Pos { return x.Lbrack } -func (x *StructType) Pos() token.Pos { return x.Struct } +func (x *StarExpr) Pos() token.Pos { return x.Star } +func (x *UnaryExpr) Pos() token.Pos { return x.OpPos } +func (x *BinaryExpr) Pos() token.Pos { return x.X.Pos() } +func (x *KeyValueExpr) Pos() token.Pos { return x.Key.Pos() } +func (x *ArrayType) Pos() token.Pos { return x.Lbrack } +func (x *StructType) Pos() token.Pos { return x.Struct } func (x *FuncType) Pos() token.Pos { if x.Func.IsValid() || x.Params == nil { // see issue 3870 return x.Func @@ -533,21 +530,16 @@ func (x *CompositeLit) End() token.Pos { return x.Rbrace + 1 } func (x *ParenExpr) End() token.Pos { return x.Rparen + 1 } func (x *SelectorExpr) End() token.Pos { return x.Sel.End() } func (x *IndexExpr) End() token.Pos { return x.Rbrack + 1 } +func (x *MultiIndexExpr) End() token.Pos { return x.Rbrack + 1 } func (x *SliceExpr) End() token.Pos { return x.Rbrack + 1 } func (x *TypeAssertExpr) End() token.Pos { return x.Rparen + 1 } func (x *CallExpr) End() token.Pos { return x.Rparen + 1 } -func (x *ListExpr) End() token.Pos { - if len(x.ElemList) > 0 { - return x.ElemList[len(x.ElemList)-1].End() - } - return token.NoPos -} -func (x *StarExpr) End() token.Pos { return x.X.End() } -func (x *UnaryExpr) End() token.Pos { return x.X.End() } -func (x *BinaryExpr) End() token.Pos { return x.Y.End() } -func (x *KeyValueExpr) End() token.Pos { return x.Value.End() } -func (x *ArrayType) End() token.Pos { return x.Elt.End() } -func (x *StructType) End() token.Pos { return x.Fields.End() } +func (x *StarExpr) End() token.Pos { return x.X.End() } +func (x *UnaryExpr) End() token.Pos { return x.X.End() } +func (x *BinaryExpr) End() token.Pos { return x.Y.End() } +func (x *KeyValueExpr) End() token.Pos { return x.Value.End() } +func (x *ArrayType) End() token.Pos { return x.Elt.End() } +func (x *StructType) End() token.Pos { return x.Fields.End() } func (x *FuncType) End() token.Pos { if x.Results != nil { return x.Results.End() @@ -570,10 +562,10 @@ func (*CompositeLit) exprNode() {} func (*ParenExpr) exprNode() {} func (*SelectorExpr) exprNode() {} func (*IndexExpr) exprNode() {} +func (*MultiIndexExpr) exprNode() {} func (*SliceExpr) exprNode() {} func (*TypeAssertExpr) exprNode() {} func (*CallExpr) exprNode() {} -func (*ListExpr) exprNode() {} func (*StarExpr) exprNode() {} func (*UnaryExpr) exprNode() {} func (*BinaryExpr) exprNode() {} diff --git a/src/go/ast/walk.go b/src/go/ast/walk.go index 02fef5901d..c8abc40972 100644 --- a/src/go/ast/walk.go +++ b/src/go/ast/walk.go @@ -116,6 +116,12 @@ func Walk(v Visitor, node Node) { Walk(v, n.X) Walk(v, n.Index) + case *MultiIndexExpr: + Walk(v, n.X) + for _, index := range n.Indices { + Walk(v, index) + } + case *SliceExpr: Walk(v, n.X) if n.Low != nil { @@ -138,11 +144,6 @@ func Walk(v Visitor, node Node) { Walk(v, n.Fun) walkExprList(v, n.Args) - case *ListExpr: - for _, elem := range n.ElemList { - Walk(v, elem) - } - case *StarExpr: Walk(v, n.X) diff --git a/src/go/internal/typeparams/typeparams.go b/src/go/internal/typeparams/typeparams.go index b4251bda7e..e102b77ef8 100644 --- a/src/go/internal/typeparams/typeparams.go +++ b/src/go/internal/typeparams/typeparams.go @@ -7,40 +7,54 @@ package typeparams import ( "fmt" "go/ast" + "go/token" ) const Enabled = true -func PackExpr(list []ast.Expr) ast.Expr { - switch len(list) { +func PackIndexExpr(x ast.Expr, lbrack token.Pos, exprs []ast.Expr, rbrack token.Pos) ast.Expr { + switch len(exprs) { case 0: - // Return an empty ListExpr here, rather than nil, as IndexExpr.Index must - // never be nil. - // TODO(rFindley) would a BadExpr be more appropriate here? - return &ast.ListExpr{} + panic("internal error: PackIndexExpr with empty expr slice") case 1: - return list[0] + return &ast.IndexExpr{ + X: x, + Lbrack: lbrack, + Index: exprs[0], + Rbrack: rbrack, + } default: - return &ast.ListExpr{ElemList: list} + return &ast.MultiIndexExpr{ + X: x, + Lbrack: lbrack, + Indices: exprs, + Rbrack: rbrack, + } } } -// TODO(gri) Should find a more efficient solution that doesn't -// require introduction of a new slice for simple -// expressions. -func UnpackExpr(x ast.Expr) []ast.Expr { - if x, _ := x.(*ast.ListExpr); x != nil { - return x.ElemList - } - if x != nil { - return []ast.Expr{x} - } - return nil +// IndexExpr wraps an ast.IndexExpr or ast.MultiIndexExpr into the +// MultiIndexExpr interface. +// +// Orig holds the original ast.Expr from which this IndexExpr was derived. +type IndexExpr struct { + Orig ast.Expr // the wrapped expr, which may be distinct from MultiIndexExpr below. + *ast.MultiIndexExpr } -func IsListExpr(n ast.Node) bool { - _, ok := n.(*ast.ListExpr) - return ok +func UnpackIndexExpr(n ast.Node) *IndexExpr { + switch e := n.(type) { + case *ast.IndexExpr: + return &IndexExpr{e, &ast.MultiIndexExpr{ + X: e.X, + Lbrack: e.Lbrack, + Indices: []ast.Expr{e.Index}, + Rbrack: e.Rbrack, + }} + case *ast.MultiIndexExpr: + return &IndexExpr{e, e} + } + return nil } func Get(n ast.Node) *ast.FieldList { diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go index c0a3cc66fe..d108259171 100644 --- a/src/go/parser/parser.go +++ b/src/go/parser/parser.go @@ -600,7 +600,7 @@ func (p *parser) parseArrayFieldOrTypeInstance(x *ast.Ident) (*ast.Ident, ast.Ex } // x[P], x[P1, P2], ... - return nil, &ast.IndexExpr{X: x, Lbrack: lbrack, Index: typeparams.PackExpr(args), Rbrack: rbrack} + return nil, typeparams.PackIndexExpr(x, lbrack, args, rbrack) } func (p *parser) parseFieldDecl() *ast.Field { @@ -991,7 +991,7 @@ func (p *parser) parseMethodSpec() *ast.Field { p.exprLev-- } rbrack := p.expectClosing(token.RBRACK, "type argument list") - typ = &ast.IndexExpr{X: ident, Lbrack: lbrack, Index: typeparams.PackExpr(list), Rbrack: rbrack} + typ = typeparams.PackIndexExpr(ident, lbrack, list, rbrack) } case p.tok == token.LPAREN: // ordinary method @@ -1178,7 +1178,6 @@ func (p *parser) parseTypeInstance(typ ast.Expr) ast.Expr { } opening := p.expect(token.LBRACK) - p.exprLev++ var list []ast.Expr for p.tok != token.RBRACK && p.tok != token.EOF { @@ -1192,7 +1191,17 @@ func (p *parser) parseTypeInstance(typ ast.Expr) ast.Expr { closing := p.expectClosing(token.RBRACK, "type argument list") - return &ast.IndexExpr{X: typ, Lbrack: opening, Index: typeparams.PackExpr(list), Rbrack: closing} + if len(list) == 0 { + p.errorExpected(closing, "type argument list") + return &ast.IndexExpr{ + X: typ, + Lbrack: opening, + Index: &ast.BadExpr{From: opening + 1, To: closing}, + Rbrack: closing, + } + } + + return typeparams.PackIndexExpr(typ, opening, list, closing) } func (p *parser) tryIdentOrType() ast.Expr { @@ -1455,7 +1464,7 @@ func (p *parser) parseIndexOrSliceOrInstance(x ast.Expr) ast.Expr { } // instance expression - return &ast.IndexExpr{X: x, Lbrack: lbrack, Index: typeparams.PackExpr(args), Rbrack: rbrack} + return typeparams.PackIndexExpr(x, lbrack, args, rbrack) } func (p *parser) parseCallOrConversion(fun ast.Expr) *ast.CallExpr { @@ -1557,6 +1566,7 @@ func (p *parser) checkExpr(x ast.Expr) ast.Expr { panic("unreachable") case *ast.SelectorExpr: case *ast.IndexExpr: + case *ast.MultiIndexExpr: case *ast.SliceExpr: case *ast.TypeAssertExpr: // If t.Type == nil we have a type assertion of the form @@ -1646,7 +1656,7 @@ func (p *parser) parsePrimaryExpr() (x ast.Expr) { return } // x is possibly a composite literal type - case *ast.IndexExpr: + case *ast.IndexExpr, *ast.MultiIndexExpr: if p.exprLev < 0 { return } diff --git a/src/go/printer/nodes.go b/src/go/printer/nodes.go index 913281ea6c..239fcbde1c 100644 --- a/src/go/printer/nodes.go +++ b/src/go/printer/nodes.go @@ -871,17 +871,15 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) { // TODO(gri): should treat[] like parentheses and undo one level of depth p.expr1(x.X, token.HighestPrec, 1) p.print(x.Lbrack, token.LBRACK) - // Note: we're a bit defensive here to handle the case of a ListExpr of - // length 1. - if list := typeparams.UnpackExpr(x.Index); len(list) > 0 { - if len(list) > 1 { - p.exprList(x.Lbrack, list, depth+1, commaTerm, x.Rbrack, false) - } else { - p.expr0(list[0], depth+1) - } - } else { - p.expr0(x.Index, depth+1) - } + p.expr0(x.Index, depth+1) + p.print(x.Rbrack, token.RBRACK) + + case *ast.MultiIndexExpr: + // TODO(gri): as for IndexExpr, should treat [] like parentheses and undo + // one level of depth + p.expr1(x.X, token.HighestPrec, 1) + p.print(x.Lbrack, token.LBRACK) + p.exprList(x.Lbrack, x.Indices, depth+1, commaTerm, x.Rbrack, false) p.print(x.Rbrack, token.RBRACK) case *ast.SliceExpr: diff --git a/src/go/types/call.go b/src/go/types/call.go index 039c7bbaf5..337ee741c6 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -16,23 +16,22 @@ import ( // funcInst type-checks a function instantiation inst and returns the result in x. // The operand x must be the evaluation of inst.X and its type must be a signature. -func (check *Checker) funcInst(x *operand, inst *ast.IndexExpr) { - xlist := typeparams.UnpackExpr(inst.Index) - targs := check.typeList(xlist) +func (check *Checker) funcInst(x *operand, ix *typeparams.IndexExpr) { + targs := check.typeList(ix.Indices) if targs == nil { x.mode = invalid - x.expr = inst + x.expr = ix.Orig return } - assert(len(targs) == len(xlist)) + assert(len(targs) == len(ix.Indices)) // check number of type arguments (got) vs number of type parameters (want) sig := x.typ.(*Signature) got, want := len(targs), len(sig.tparams) if got > want { - check.errorf(xlist[got-1], _Todo, "got %d type arguments but want %d", got, want) + check.errorf(ix.Indices[got-1], _Todo, "got %d type arguments but want %d", got, want) x.mode = invalid - x.expr = inst + x.expr = ix.Orig return } @@ -40,11 +39,11 @@ func (check *Checker) funcInst(x *operand, inst *ast.IndexExpr) { inferred := false if got < want { - targs = check.infer(inst, sig.tparams, targs, nil, nil, true) + targs = check.infer(ix.Orig, sig.tparams, targs, nil, nil, true) if targs == nil { // error was already reported x.mode = invalid - x.expr = inst + x.expr = ix.Orig return } got = len(targs) @@ -55,8 +54,8 @@ func (check *Checker) funcInst(x *operand, inst *ast.IndexExpr) { // determine argument positions (for error reporting) // TODO(rFindley) use a positioner here? instantiate would need to be // updated accordingly. - poslist := make([]token.Pos, len(xlist)) - for i, x := range xlist { + poslist := make([]token.Pos, len(ix.Indices)) + for i, x := range ix.Indices { poslist[i] = x.Pos() } @@ -64,25 +63,27 @@ func (check *Checker) funcInst(x *operand, inst *ast.IndexExpr) { res := check.instantiate(x.Pos(), sig, targs, poslist).(*Signature) assert(res.tparams == nil) // signature is not generic anymore if inferred { - check.recordInferred(inst, targs, res) + check.recordInferred(ix.Orig, targs, res) } x.typ = res x.mode = value - x.expr = inst + x.expr = ix.Orig } func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { - var inst *ast.IndexExpr - if iexpr, _ := call.Fun.(*ast.IndexExpr); iexpr != nil { - if check.indexExpr(x, iexpr) { + ix := typeparams.UnpackIndexExpr(call.Fun) + if ix != nil { + if check.indexExpr(x, ix) { // Delay function instantiation to argument checking, // where we combine type and value arguments for type // inference. assert(x.mode == value) - inst = iexpr + } else { + ix = nil } - x.expr = iexpr + x.expr = call.Fun check.record(x) + } else { check.exprOrType(x, call.Fun) } @@ -149,21 +150,20 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { // evaluate type arguments, if any var targs []Type - if inst != nil { - xlist := typeparams.UnpackExpr(inst.Index) - targs = check.typeList(xlist) + if ix != nil { + targs = check.typeList(ix.Indices) if targs == nil { check.use(call.Args...) x.mode = invalid x.expr = call return statement } - assert(len(targs) == len(xlist)) + assert(len(targs) == len(ix.Indices)) // check number of type arguments (got) vs number of type parameters (want) got, want := len(targs), len(sig.tparams) if got > want { - check.errorf(xlist[want], _Todo, "got %d type arguments but want %d", got, want) + check.errorf(ix.Indices[want], _Todo, "got %d type arguments but want %d", got, want) check.use(call.Args...) x.mode = invalid x.expr = call diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 402d96f66a..95f2a8d6ab 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -1331,9 +1331,10 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { case *ast.SelectorExpr: check.selector(x, e) - case *ast.IndexExpr: - if check.indexExpr(x, e) { - check.funcInst(x, e) + case *ast.IndexExpr, *ast.MultiIndexExpr: + ix := typeparams.UnpackIndexExpr(e) + if check.indexExpr(x, ix) { + check.funcInst(x, ix) } if x.mode == invalid { goto Error @@ -1423,12 +1424,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { // types, which are comparatively rare. default: - if typeparams.IsListExpr(e) { - // catch-all for unexpected expression lists - check.errorf(e, _Todo, "unexpected list of expressions") - } else { - panic(fmt.Sprintf("%s: unknown expression type %T", check.fset.Position(e.Pos()), e)) - } + panic(fmt.Sprintf("%s: unknown expression type %T", check.fset.Position(e.Pos()), e)) } // everything went well diff --git a/src/go/types/exprstring.go b/src/go/types/exprstring.go index f05e6424d4..aee8a5ba5f 100644 --- a/src/go/types/exprstring.go +++ b/src/go/types/exprstring.go @@ -67,11 +67,11 @@ func WriteExpr(buf *bytes.Buffer, x ast.Expr) { buf.WriteByte('.') buf.WriteString(x.Sel.Name) - case *ast.IndexExpr: - WriteExpr(buf, x.X) + case *ast.IndexExpr, *ast.MultiIndexExpr: + ix := typeparams.UnpackIndexExpr(x) + WriteExpr(buf, ix.X) buf.WriteByte('[') - exprs := typeparams.UnpackExpr(x.Index) - for i, e := range exprs { + for i, e := range ix.Indices { if i > 0 { buf.WriteString(", ") } diff --git a/src/go/types/index.go b/src/go/types/index.go index 5bc1d0af8d..7c7aa382ff 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -15,18 +15,18 @@ import ( // If e is a valid function instantiation, indexExpr returns true. // In that case x represents the uninstantiated function value and // it is the caller's responsibility to instantiate the function. -func (check *Checker) indexExpr(x *operand, e *ast.IndexExpr) (isFuncInst bool) { - check.exprOrType(x, e.X) +func (check *Checker) indexExpr(x *operand, expr *typeparams.IndexExpr) (isFuncInst bool) { + check.exprOrType(x, expr.X) switch x.mode { case invalid: - check.use(typeparams.UnpackExpr(e.Index)...) + check.use(expr.Indices...) return false case typexpr: // type instantiation x.mode = invalid - x.typ = check.varType(e) + x.typ = check.varType(expr.Orig) if x.typ != Typ[Invalid] { x.mode = typexpr } @@ -77,7 +77,7 @@ func (check *Checker) indexExpr(x *operand, e *ast.IndexExpr) (isFuncInst bool) x.typ = typ.elem case *Map: - index := check.singleIndex(e) + index := check.singleIndex(expr) if index == nil { x.mode = invalid return @@ -88,7 +88,7 @@ func (check *Checker) indexExpr(x *operand, e *ast.IndexExpr) (isFuncInst bool) // ok to continue even if indexing failed - map element type is known x.mode = mapindex x.typ = typ.elem - x.expr = e + x.expr = expr.Orig return case *Union: @@ -137,7 +137,7 @@ func (check *Checker) indexExpr(x *operand, e *ast.IndexExpr) (isFuncInst bool) // If there are maps, the index expression must be assignable // to the map key type (as for simple map index expressions). if nmaps > 0 { - index := check.singleIndex(e) + index := check.singleIndex(expr) if index == nil { x.mode = invalid return @@ -151,7 +151,7 @@ func (check *Checker) indexExpr(x *operand, e *ast.IndexExpr) (isFuncInst bool) if nmaps == typ.NumTerms() { x.mode = mapindex x.typ = telem - x.expr = e + x.expr = expr.Orig return } @@ -180,7 +180,7 @@ func (check *Checker) indexExpr(x *operand, e *ast.IndexExpr) (isFuncInst bool) return } - index := check.singleIndex(e) + index := check.singleIndex(expr) if index == nil { x.mode = invalid return @@ -311,23 +311,16 @@ L: // singleIndex returns the (single) index from the index expression e. // If the index is missing, or if there are multiple indices, an error // is reported and the result is nil. -func (check *Checker) singleIndex(e *ast.IndexExpr) ast.Expr { - index := e.Index - if index == nil { - check.invalidAST(e, "missing index for %s", e) - return nil - } - - indexes := typeparams.UnpackExpr(index) - if len(indexes) == 0 { - check.invalidAST(index, "index expression %v with 0 indices", index) +func (check *Checker) singleIndex(expr *typeparams.IndexExpr) ast.Expr { + if len(expr.Indices) == 0 { + check.invalidAST(expr.Orig, "index expression %v with 0 indices", expr) return nil } - if len(indexes) > 1 { + if len(expr.Indices) > 1 { // TODO(rFindley) should this get a distinct error code? - check.invalidOp(indexes[1], _InvalidIndex, "more than one index") + check.invalidOp(expr.Indices[1], _InvalidIndex, "more than one index") } - return indexes[0] + return expr.Indices[0] } // index checks an index expression for validity. diff --git a/src/go/types/resolver.go b/src/go/types/resolver.go index 4892218b75..1434e6deb1 100644 --- a/src/go/types/resolver.go +++ b/src/go/types/resolver.go @@ -499,10 +499,12 @@ L: // unpack receiver type } // unpack type parameters, if any - if ptyp, _ := rtyp.(*ast.IndexExpr); ptyp != nil { - rtyp = ptyp.X + switch rtyp.(type) { + case *ast.IndexExpr, *ast.MultiIndexExpr: + ix := typeparams.UnpackIndexExpr(rtyp) + rtyp = ix.X if unpackParams { - for _, arg := range typeparams.UnpackExpr(ptyp.Index) { + for _, arg := range ix.Indices { var par *ast.Ident switch arg := arg.(type) { case *ast.Ident: @@ -510,7 +512,7 @@ L: // unpack receiver type case *ast.BadExpr: // ignore - error already reported by parser case nil: - check.invalidAST(ptyp, "parameterized receiver contains nil parameters") + check.invalidAST(ix.Orig, "parameterized receiver contains nil parameters") default: check.errorf(arg, _Todo, "receiver type parameter %s must be an identifier", arg) } diff --git a/src/go/types/signature.go b/src/go/types/signature.go index 5489b493ba..f56fe047c8 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -244,24 +244,21 @@ func isubst(x ast.Expr, smap map[*ast.Ident]*ast.Ident) ast.Expr { new.X = X return &new } - case *ast.IndexExpr: - elems := typeparams.UnpackExpr(n.Index) - var newElems []ast.Expr - for i, elem := range elems { - new := isubst(elem, smap) - if new != elem { - if newElems == nil { - newElems = make([]ast.Expr, len(elems)) - copy(newElems, elems) + case *ast.IndexExpr, *ast.MultiIndexExpr: + ix := typeparams.UnpackIndexExpr(x) + var newIndexes []ast.Expr + for i, index := range ix.Indices { + new := isubst(index, smap) + if new != index { + if newIndexes == nil { + newIndexes = make([]ast.Expr, len(ix.Indices)) + copy(newIndexes, ix.Indices) } - newElems[i] = new + newIndexes[i] = new } } - if newElems != nil { - index := typeparams.PackExpr(newElems) - new := *n - new.Index = index - return &new + if newIndexes != nil { + return typeparams.PackIndexExpr(ix.X, ix.Lbrack, newIndexes, ix.Rbrack) } case *ast.ParenExpr: return isubst(n.X, smap) // no need to keep parentheses diff --git a/src/go/types/testdata/check/typeinst.go2 b/src/go/types/testdata/check/typeinst.go2 index 3184a4b5b1..069bd3bc16 100644 --- a/src/go/types/testdata/check/typeinst.go2 +++ b/src/go/types/testdata/check/typeinst.go2 @@ -33,11 +33,11 @@ var _ A3 var x int type _ x /* ERROR not a type */ [int] -type _ int /* ERROR not a generic type */ [] -type _ myInt /* ERROR not a generic type */ [] +type _ int /* ERROR not a generic type */ [] // ERROR expected type argument list +type _ myInt /* ERROR not a generic type */ [] // ERROR expected type argument list // TODO(gri) better error messages -type _ T1 /* ERROR got 0 arguments but 1 type parameters */ [] +type _ T1[] // ERROR expected type argument list type _ T1[x /* ERROR not a type */ ] type _ T1 /* ERROR got 2 arguments but 1 type parameters */ [int, float32] diff --git a/src/go/types/testdata/fixedbugs/issue45635.go2 b/src/go/types/testdata/fixedbugs/issue45635.go2 index 0f62980343..c6784e12fd 100644 --- a/src/go/types/testdata/fixedbugs/issue45635.go2 +++ b/src/go/types/testdata/fixedbugs/issue45635.go2 @@ -10,7 +10,7 @@ func main() { type N[T any] struct{} -var _ N /* ERROR "0 arguments but 1 type parameters" */ [] +var _ N [] // ERROR expected type argument list type I interface { ~map[int]int | ~[]int diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index e6be7b72e4..f62b41831e 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -261,13 +261,13 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) { check.errorf(&x, _NotAType, "%s is not a type", &x) } - case *ast.IndexExpr: + case *ast.IndexExpr, *ast.MultiIndexExpr: + ix := typeparams.UnpackIndexExpr(e) if typeparams.Enabled { - exprs := typeparams.UnpackExpr(e.Index) - return check.instantiatedType(e.X, exprs, def) + return check.instantiatedType(ix, def) } check.errorf(e0, _NotAType, "%s is not a type", e0) - check.use(e.X) + check.use(ix.X) case *ast.ParenExpr: // Generic types must be instantiated before they can be used in any form. @@ -403,8 +403,8 @@ func (check *Checker) typeOrNil(e ast.Expr) Type { return Typ[Invalid] } -func (check *Checker) instantiatedType(x ast.Expr, targs []ast.Expr, def *Named) Type { - b := check.genericType(x, true) // TODO(gri) what about cycles? +func (check *Checker) instantiatedType(ix *typeparams.IndexExpr, def *Named) Type { + b := check.genericType(ix.X, true) // TODO(gri) what about cycles? if b == Typ[Invalid] { return b // error already reported } @@ -420,19 +420,19 @@ func (check *Checker) instantiatedType(x ast.Expr, targs []ast.Expr, def *Named) def.setUnderlying(typ) typ.check = check - typ.pos = x.Pos() + typ.pos = ix.X.Pos() typ.base = base // evaluate arguments (always) - typ.targs = check.typeList(targs) + typ.targs = check.typeList(ix.Indices) if typ.targs == nil { def.setUnderlying(Typ[Invalid]) // avoid later errors due to lazy instantiation return Typ[Invalid] } // determine argument positions (for error reporting) - typ.poslist = make([]token.Pos, len(targs)) - for i, arg := range targs { + typ.poslist = make([]token.Pos, len(ix.Indices)) + for i, arg := range ix.Indices { typ.poslist[i] = arg.Pos() } -- GitLab From 3d8453e00e3d0a6f23cec06bcad08cf740ec5940 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 15 Jul 2021 16:42:25 -0700 Subject: [PATCH 0452/2500] [dev.typeparams] cmd/compile/internal/types2: more consistent handling of predeclared "any" Rather than removing "any" from the universe scope, keep it predeclared but provide a better error message. While at it, remove some unnecessary type assertions. Change-Id: I10603274282ea6afc107f703ab194f32bd334dd1 Reviewed-on: https://go-review.googlesource.com/c/go/+/334911 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/decl.go | 5 ++-- .../compile/internal/types2/object_test.go | 2 +- .../types2/testdata/check/typeparams.go2 | 8 +++--- src/cmd/compile/internal/types2/typexpr.go | 13 +++++++++- src/cmd/compile/internal/types2/universe.go | 26 +++++++------------ test/fixedbugs/issue14652.go | 2 +- test/typeparam/tparam1.go | 4 +-- 7 files changed, 33 insertions(+), 27 deletions(-) diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 9fb9815f4d..4f656e374a 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -617,8 +617,9 @@ func (check *Checker) declareTypeParam(index int, name *syntax.Name) *TypeName { // The type must be an interface, including the predeclared type "any". func (check *Checker) boundType(e syntax.Expr) Type { // The predeclared identifier "any" is visible only as a type bound in a type parameter list. - if name, _ := unparen(e).(*syntax.Name); name != nil && name.Value == "any" && check.lookup("any") == nil { - return universeAny + // If we allow "any" for general use, this if-statement can be removed (issue #33232). + if name, _ := unparen(e).(*syntax.Name); name != nil && name.Value == "any" && check.lookup("any") == universeAny { + return universeAny.Type() } bound := check.typ(e) diff --git a/src/cmd/compile/internal/types2/object_test.go b/src/cmd/compile/internal/types2/object_test.go index 7f63c79332..a86733a5c9 100644 --- a/src/cmd/compile/internal/types2/object_test.go +++ b/src/cmd/compile/internal/types2/object_test.go @@ -25,7 +25,7 @@ func TestIsAlias(t *testing.T) { check(Unsafe.Scope().Lookup("Pointer").(*TypeName), false) for _, name := range Universe.Names() { if obj, _ := Universe.Lookup(name).(*TypeName); obj != nil { - check(obj, name == "byte" || name == "rune") + check(obj, name == "any" || name == "byte" || name == "rune") } } diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 index 8a7f6eb2c2..2755a539e5 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 @@ -6,11 +6,11 @@ package p // import "io" // for type assertion tests -// The predeclared identifier "any" is only visible as a constraint +// The predeclared identifier "any" can only be used as a constraint // in a type parameter list. -var _ any // ERROR undeclared -func _[_ any /* ok here */ , _ interface{any /* ERROR undeclared */ }](any /* ERROR undeclared */ ) { - var _ any /* ERROR undeclared */ +var _ any // ERROR cannot use any outside constraint position +func _[_ any /* ok here */ , _ interface{any /* ERROR constraint */ }](any /* ERROR constraint */ ) { + var _ any /* ERROR constraint */ } func identity[T any](x T) T { return x } diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index a14d498cec..83cefa19ba 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -25,7 +25,8 @@ func (check *Checker) ident(x *operand, e *syntax.Name, def *Named, wantType boo // Note that we cannot use check.lookup here because the returned scope // may be different from obj.Parent(). See also Scope.LookupParent doc. scope, obj := check.scope.LookupParent(e.Value, check.pos) - if obj == nil || obj == universeComparable && !check.allowVersion(check.pkg, 1, 18) { + switch obj { + case nil: if e.Value == "_" { check.error(e, "cannot use _ as value or type") } else { @@ -36,6 +37,16 @@ func (check *Checker) ident(x *operand, e *syntax.Name, def *Named, wantType boo } } return + case universeAny, universeComparable: + if !check.allowVersion(check.pkg, 1, 18) { + check.errorf(e, "undeclared name: %s (requires version go1.18 or later)", e.Value) + return + } + // If we allow "any" for general use, this if-statement can be removed (issue #33232). + if obj == universeAny { + check.error(e, "cannot use any outside constraint position") + return + } } check.recordUse(e, obj) diff --git a/src/cmd/compile/internal/types2/universe.go b/src/cmd/compile/internal/types2/universe.go index d328b13a8e..e2dd0df69e 100644 --- a/src/cmd/compile/internal/types2/universe.go +++ b/src/cmd/compile/internal/types2/universe.go @@ -20,11 +20,11 @@ var Universe *Scope var Unsafe *Package var ( - universeIota *Const - universeByte *Basic // uint8 alias, but has name "byte" - universeRune *Basic // int32 alias, but has name "rune" - universeAny *Interface - universeError *Named + universeIota Object + universeByte Type // uint8 alias, but has name "byte" + universeRune Type // int32 alias, but has name "rune" + universeAny Object + universeError Type universeComparable Object ) @@ -79,9 +79,6 @@ func defPredeclaredTypes() { } // type any = interface{} - // Entered into universe scope so we do all the usual checks; - // but removed again from scope later since it's only visible - // as constraint in a type parameter list. def(NewTypeName(nopos, nil, "any", &emptyInterface)) // type error interface{ Error() string } @@ -224,15 +221,12 @@ func init() { defPredeclaredNil() defPredeclaredFuncs() - universeIota = Universe.Lookup("iota").(*Const) - universeByte = Universe.Lookup("byte").(*TypeName).typ.(*Basic) - universeRune = Universe.Lookup("rune").(*TypeName).typ.(*Basic) - universeAny = Universe.Lookup("any").(*TypeName).typ.(*Interface) - universeError = Universe.Lookup("error").(*TypeName).typ.(*Named) + universeIota = Universe.Lookup("iota") + universeByte = Universe.Lookup("byte").Type() + universeRune = Universe.Lookup("rune").Type() + universeAny = Universe.Lookup("any") + universeError = Universe.Lookup("error").Type() universeComparable = Universe.Lookup("comparable") - - // "any" is only visible as constraint in a type parameter list - delete(Universe.elems, "any") } // Objects with names containing blanks are internal and not entered into diff --git a/test/fixedbugs/issue14652.go b/test/fixedbugs/issue14652.go index d53b412668..14a223977b 100644 --- a/test/fixedbugs/issue14652.go +++ b/test/fixedbugs/issue14652.go @@ -6,4 +6,4 @@ package p -var x any // ERROR "undefined: any|undefined type .*any.*" +var x any // ERROR "undefined: any|undefined type .*any.*|cannot use any outside constraint position" diff --git a/test/typeparam/tparam1.go b/test/typeparam/tparam1.go index 7043933326..2bcc4af3db 100644 --- a/test/typeparam/tparam1.go +++ b/test/typeparam/tparam1.go @@ -10,8 +10,8 @@ package tparam1 // The predeclared identifier "any" is only visible as a constraint // in a type parameter list. -var _ any // ERROR "undefined" -func _(_ any) // ERROR "undefined" +var _ any // ERROR "cannot use any outside constraint position" +func _(_ any) // ERROR "cannot use any outside constraint position" type _[_ any /* ok here */ ] struct{} const N = 10 -- GitLab From ed9e109dc9a3523100d19e6f259edccbd7dd3cba Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sun, 11 Jul 2021 13:06:54 -0700 Subject: [PATCH 0453/2500] [dev.typeparams] cmd/compile: fix small -G=3 issues for tests disabled in run.go - set correct position for closure capture variable in (*irgen).use() (issue20250.go) Also, evaluate rhs, lhs in that order in assignment statements to match noder1 (affects ordering of closure variables). - make sure to set Assign flag properly in (*irgen).forStmt() for range variables which are map accesses (issue9691.go) - make sure CheckSize() is call on the base type for top-level types converted by (*irgen).typ() that are pointer types (issue20174.go and issue37837.go) - deal with parentheses properly in validation function (*irgen).validate() (issue17270.go) - avoid HasNil call on type TTYPEPARAM - types2 typechecker will have already checked validity of the typeparam having nil value (new test issue39755.go) Change-Id: Ie68004d964698aea047e19e7dcd79b297e9d47ca Reviewed-on: https://go-review.googlesource.com/c/go/+/334733 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/object.go | 2 +- src/cmd/compile/internal/noder/stmt.go | 14 ++++++++-- src/cmd/compile/internal/noder/types.go | 5 ++++ src/cmd/compile/internal/noder/validate.go | 10 ++++++- src/cmd/compile/internal/typecheck/iexport.go | 4 ++- test/run.go | 7 +---- test/typeparam/issue39755.go | 27 +++++++++++++++++++ 7 files changed, 58 insertions(+), 11 deletions(-) create mode 100644 test/typeparam/issue39755.go diff --git a/src/cmd/compile/internal/noder/object.go b/src/cmd/compile/internal/noder/object.go index 581a3652ec..40c0b9cf42 100644 --- a/src/cmd/compile/internal/noder/object.go +++ b/src/cmd/compile/internal/noder/object.go @@ -29,7 +29,7 @@ func (g *irgen) use(name *syntax.Name) *ir.Name { if !ok { base.FatalfAt(g.pos(name), "unknown name %v", name) } - obj := ir.CaptureName(g.pos(obj2), ir.CurFunc, g.obj(obj2)) + obj := ir.CaptureName(g.pos(name), ir.CurFunc, g.obj(obj2)) if obj.Defn != nil && obj.Defn.Op() == ir.ONAME { // If CaptureName created a closure variable, then transfer the // type of the captured name to the new closure variable. diff --git a/src/cmd/compile/internal/noder/stmt.go b/src/cmd/compile/internal/noder/stmt.go index 672a732187..b7085c4776 100644 --- a/src/cmd/compile/internal/noder/stmt.go +++ b/src/cmd/compile/internal/noder/stmt.go @@ -57,7 +57,10 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { if stmt.Rhs == nil { n = IncDec(g.pos(stmt), op, g.expr(stmt.Lhs)) } else { - n = ir.NewAssignOpStmt(g.pos(stmt), op, g.expr(stmt.Lhs), g.expr(stmt.Rhs)) + // Eval rhs before lhs, for compatibility with noder1 + rhs := g.expr(stmt.Rhs) + lhs := g.expr(stmt.Lhs) + n = ir.NewAssignOpStmt(g.pos(stmt), op, lhs, rhs) } if n.X.Typecheck() == 3 { n.SetTypecheck(3) @@ -68,8 +71,9 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { return n } - names, lhs := g.assignList(stmt.Lhs, stmt.Op == syntax.Def) + // Eval rhs before lhs, for compatibility with noder1 rhs := g.exprList(stmt.Rhs) + names, lhs := g.assignList(stmt.Lhs, stmt.Op == syntax.Def) // We must delay transforming the assign statement if any of the // lhs or rhs nodes are also delayed, since transformAssign needs @@ -262,6 +266,12 @@ func (g *irgen) forStmt(stmt *syntax.ForStmt) ir.Node { key, value := unpackTwo(lhs) n := ir.NewRangeStmt(g.pos(r), key, value, g.expr(r.X), g.blockStmt(stmt.Body)) n.Def = initDefn(n, names) + if key != nil { + transformCheckAssign(n, key) + } + if value != nil { + transformCheckAssign(n, value) + } return n } diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index d925f991c8..c18ae3a1fc 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -39,6 +39,11 @@ func (g *irgen) typ(typ types2.Type) *types.Type { // recursive types have been fully constructed before we call CheckSize. if res != nil && !res.IsUntyped() && !res.IsFuncArgStruct() && !res.HasTParam() { types.CheckSize(res) + if res.IsPtr() { + // Pointers always have their size set, even though their element + // may not have its size set. + types.CheckSize(res.Elem()) + } } return res } diff --git a/src/cmd/compile/internal/noder/validate.go b/src/cmd/compile/internal/noder/validate.go index b926222c89..68a059b96f 100644 --- a/src/cmd/compile/internal/noder/validate.go +++ b/src/cmd/compile/internal/noder/validate.go @@ -55,7 +55,15 @@ func (g *irgen) validate(n syntax.Node) { case *syntax.CallExpr: tv := g.info.Types[n.Fun] if tv.IsBuiltin() { - switch builtin := n.Fun.(type) { + fun := n.Fun + for { + builtin, ok := fun.(*syntax.ParenExpr) + if !ok { + break + } + fun = builtin.X + } + switch builtin := fun.(type) { case *syntax.Name: g.validateBuiltin(builtin.Value, n) case *syntax.SelectorExpr: diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 4fbc48f17b..b054c73ad8 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -1636,7 +1636,9 @@ func (w *exportWriter) expr(n ir.Node) { // (somewhat closely following the structure of exprfmt in fmt.go) case ir.ONIL: n := n.(*ir.NilExpr) - if !n.Type().HasNil() { + // If n is a typeparam, it will have already been checked + // for proper use by the types2 typechecker. + if !n.Type().IsTypeParam() && !n.Type().HasNil() { base.Fatalf("unexpected type for nil: %v", n.Type()) } w.op(ir.ONIL) diff --git a/test/run.go b/test/run.go index 82d49270f2..3ccf1046ce 100644 --- a/test/run.go +++ b/test/run.go @@ -2167,12 +2167,7 @@ var types2Failures32Bit = setOf( ) var g3Failures = setOf( - "writebarrier.go", // correct diagnostics, but different lines (probably irgen's fault) - "fixedbugs/issue17270.go", // ICE in irgen - "fixedbugs/issue20174.go", // ICE due to width not calculated (probably irgen's fault) - "fixedbugs/issue20250.go", // correct diagnostics, but different lines (probably irgen's fault) - "fixedbugs/issue37837.go", // ICE due to width not calculated - "fixedbugs/issue9691.go", // "cannot assign to int(.autotmp_4)" (probably irgen's fault) + "writebarrier.go", // correct diagnostics, but different lines (probably irgen's fault) "typeparam/nested.go", // -G=3 doesn't support function-local types with generics diff --git a/test/typeparam/issue39755.go b/test/typeparam/issue39755.go new file mode 100644 index 0000000000..13a575d16f --- /dev/null +++ b/test/typeparam/issue39755.go @@ -0,0 +1,27 @@ +// compile -G=3 + +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// copied from cmd/compile/internal/types2/testdata/fixedbugs/issue39755.go + +package p + +func _[T interface{~map[string]int}](x T) { + _ = x == nil +} + +// simplified test case from issue + +type PathParamsConstraint interface { + ~map[string]string | ~[]struct{key, value string} +} + +type PathParams[T PathParamsConstraint] struct { + t T +} + +func (pp *PathParams[T]) IsNil() bool { + return pp.t == nil // this must succeed +} -- GitLab From 10c8b7c1d7bb973a0b2bc6858b4d5b705cdaa402 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Mon, 12 Jul 2021 16:12:55 -0700 Subject: [PATCH 0454/2500] [dev.typeparams] cmd/compile: use dictionary to convert arguments of ==, != to interfaces When comparing a value whose type is a type parameter to an interface, we need to convert that type parameter to an interface using the dictionary entries. Change-Id: I409c9e36e376fe4ef8163407d0fd4e84496d5b65 Reviewed-on: https://go-review.googlesource.com/c/go/+/334150 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 15 +++++ test/typeparam/equal.go | 71 +++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 test/typeparam/equal.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 1759fbc4cf..f4935fe22a 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1242,6 +1242,21 @@ func (subst *subster) node(n ir.Node) ir.Node { if ix := subst.findDictType(t); ix >= 0 { m = subst.convertUsingDictionary(x.Pos(), m.(*ir.ConvExpr).X, m.Type(), t, ix) } + case ir.OEQ, ir.ONE: + // Equality between a non-interface and an interface requires the non-interface + // to be promoted to an interface. + x := x.(*ir.BinaryExpr) + m := m.(*ir.BinaryExpr) + if i := x.Y.Type(); i.IsInterface() { + if ix := subst.findDictType(x.X.Type()); ix >= 0 { + m.X = subst.convertUsingDictionary(m.X.Pos(), m.X, i, x.X.Type(), ix) + } + } + if i := x.X.Type(); i.IsInterface() { + if ix := subst.findDictType(x.Y.Type()); ix >= 0 { + m.Y = subst.convertUsingDictionary(m.Y.Pos(), m.Y, i, x.X.Type(), ix) + } + } } return m } diff --git a/test/typeparam/equal.go b/test/typeparam/equal.go new file mode 100644 index 0000000000..6776b19d12 --- /dev/null +++ b/test/typeparam/equal.go @@ -0,0 +1,71 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// comparisons of type parameters to interfaces + +package main + +func f[T comparable](t, u T) bool { + // Comparing two type parameters directly. + // (Not really testing comparisons to interfaces, but just 'cause we're here.) + return t == u +} + +func g[T comparable](t T, i interface{}) bool { + // Compare type parameter value to empty interface. + return t == i +} + +type I interface { + foo() +} + +type C interface { + comparable + I +} + +func h[T C](t T, i I) bool { + // Compare type parameter value to nonempty interface. + return t == i +} + +type myint int + +func (x myint) foo() { +} + +func k[T comparable](t T, i interface{}) bool { + // Compare derived type value to interface. + return struct{a, b T}{t, t} == i +} + +func main() { + assert(f(3, 3)) + assert(!f(3, 5)) + assert(g(3, 3)) + assert(!g(3, 5)) + assert(h(myint(3), myint(3))) + assert(!h(myint(3), myint(5))) + + type S struct { a, b float64 } + + assert(f(S{3,5}, S{3,5})) + assert(!f(S{3,5}, S{4,6})) + assert(g(S{3,5}, S{3,5})) + assert(!g(S{3,5}, S{4,6})) + + assert(k(3, struct{a, b int}{3, 3})) + assert(!k(3, struct{a, b int}{3, 4})) +} + +func assert(b bool) { + if !b { + panic("assertion failed") + } +} + + -- GitLab From b296e54618ea09b89154173a2bfb200203a731bf Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Thu, 15 Jul 2021 22:06:38 -0400 Subject: [PATCH 0455/2500] [dev.typeparams] go/types: port lazy import resolution from types2 This is a straightforward port of CL 323569 to go/types. It is line-for-line identical, except where names are unexported to preserve the current go/types API. Change-Id: I4c78211bff90f982ca2e90ed224946716118ee31 Reviewed-on: https://go-review.googlesource.com/c/go/+/334893 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/check.go | 2 +- src/go/types/decl.go | 7 +-- src/go/types/instantiate.go | 18 ++++++- src/go/types/labels.go | 3 +- src/go/types/lookup.go | 5 +- src/go/types/object.go | 8 ++++ src/go/types/predicates.go | 2 +- src/go/types/resolver.go | 19 +++++--- src/go/types/sanitize.go | 1 + src/go/types/scope.go | 93 +++++++++++++++++++++++++++++++++---- src/go/types/signature.go | 2 +- src/go/types/sizeof_test.go | 2 +- src/go/types/stmt.go | 3 +- src/go/types/subst.go | 12 ++--- src/go/types/type.go | 46 +++++++++++++++--- src/go/types/typestring.go | 4 +- src/go/types/typexpr.go | 2 +- 17 files changed, 186 insertions(+), 43 deletions(-) diff --git a/src/go/types/check.go b/src/go/types/check.go index aea319f463..3e534de08a 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -73,7 +73,7 @@ type importKey struct { // A dotImportKey describes a dot-imported object in the given scope. type dotImportKey struct { scope *Scope - obj Object + name string } // A Checker maintains the state of the type checker. diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 12ee51b920..761418c4fb 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -576,7 +576,7 @@ func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init ast.Expr) { // is detected, the result is Typ[Invalid]. If a cycle is detected and // n0.check != nil, the cycle is reported. func (n0 *Named) under() Type { - u := n0.underlying + u := n0.Underlying() if u == Typ[Invalid] { return u @@ -614,7 +614,7 @@ func (n0 *Named) under() Type { seen := map[*Named]int{n0: 0} path := []Object{n0.obj} for { - u = n.underlying + u = n.Underlying() if u == nil { u = Typ[Invalid] break @@ -814,7 +814,7 @@ func (check *Checker) collectMethods(obj *TypeName) { // and field names must be distinct." base := asNamed(obj.typ) // shouldn't fail but be conservative if base != nil { - if t, _ := base.underlying.(*Struct); t != nil { + if t, _ := base.Underlying().(*Struct); t != nil { for _, fld := range t.fields { if fld.name != "_" { assert(mset.insert(fld) == nil) @@ -850,6 +850,7 @@ func (check *Checker) collectMethods(obj *TypeName) { } if base != nil { + base.expand() // TODO(mdempsky): Probably unnecessary. base.methods = append(base.methods, m) } } diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 6f8c4983f4..1c15ac199c 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -23,7 +23,7 @@ func Instantiate(pos token.Pos, typ Type, targs []Type) (res Type) { var tparams []*TypeName switch t := typ.(type) { case *Named: - tparams = t.tparams + tparams = t.TParams() case *Signature: tparams = t.tparams defer func() { @@ -61,3 +61,19 @@ func Instantiate(pos token.Pos, typ Type, targs []Type) (res Type) { smap := makeSubstMap(tparams, targs) return (*Checker)(nil).subst(pos, typ, smap) } + +// InstantiateLazy is like Instantiate, but avoids actually +// instantiating the type until needed. +func (check *Checker) InstantiateLazy(pos token.Pos, typ Type, targs []Type) (res Type) { + base := asNamed(typ) + if base == nil { + panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) + } + + return &instance{ + check: check, + pos: pos, + base: base, + targs: targs, + } +} diff --git a/src/go/types/labels.go b/src/go/types/labels.go index 8cf6e63645..f3b7f211f3 100644 --- a/src/go/types/labels.go +++ b/src/go/types/labels.go @@ -36,7 +36,8 @@ func (check *Checker) labels(body *ast.BlockStmt) { } // spec: "It is illegal to define a label that is never used." - for _, obj := range all.elems { + for name, obj := range all.elems { + obj = resolve(name, obj) if lbl := obj.(*Label); !lbl.used { check.softErrorf(lbl, _UnusedLabel, "label %s declared but not used", lbl.name) } diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index 3e89b6cc2b..5b22c4744e 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -56,7 +56,7 @@ func (check *Checker) lookupFieldOrMethod(T Type, addressable bool, pkg *Package // pointer type but discard the result if it is a method since we would // not have found it for T (see also issue 8590). if t := asNamed(T); t != nil { - if p, _ := t.underlying.(*Pointer); p != nil { + if p, _ := t.Underlying().(*Pointer); p != nil { obj, index, indirect = check.rawLookupFieldOrMethod(p, false, pkg, name) if _, ok := obj.(*Func); ok { return nil, nil, false @@ -128,6 +128,7 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack seen[named] = true // look for a matching attached method + named.expand() if i, m := lookupMethod(named.methods, pkg, name); m != nil { // potential match // caution: method may not have a proper signature yet @@ -400,7 +401,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // In order to compare the signatures, substitute the receiver // type parameters of ftyp with V's instantiation type arguments. // This lazily instantiates the signature of method f. - if Vn != nil && len(Vn.tparams) > 0 { + if Vn != nil && len(Vn.TParams()) > 0 { // Be careful: The number of type arguments may not match // the number of receiver parameters. If so, an error was // reported earlier but the length discrepancy is still diff --git a/src/go/types/object.go b/src/go/types/object.go index 50346ec691..7913008814 100644 --- a/src/go/types/object.go +++ b/src/go/types/object.go @@ -230,6 +230,14 @@ func NewTypeName(pos token.Pos, pkg *Package, name string, typ Type) *TypeName { return &TypeName{object{nil, pos, pkg, name, typ, 0, colorFor(typ), token.NoPos}} } +// _NewTypeNameLazy returns a new defined type like NewTypeName, but it +// lazily calls resolve to finish constructing the Named object. +func _NewTypeNameLazy(pos token.Pos, pkg *Package, name string, resolve func(named *Named) (tparams []*TypeName, underlying Type, methods []*Func)) *TypeName { + obj := NewTypeName(pos, pkg, name, nil) + NewNamed(obj, nil, nil).resolve = resolve + return obj +} + // IsAlias reports whether obj is an alias name for a type. func (obj *TypeName) IsAlias() bool { switch t := obj.typ.(type) { diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 6aa5825943..9f3e324597 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -25,7 +25,7 @@ func isNamed(typ Type) bool { func isGeneric(typ Type) bool { // A parameterized type is only instantiated if it doesn't have an instantiation already. named, _ := typ.(*Named) - return named != nil && named.obj != nil && named.tparams != nil && named.targs == nil + return named != nil && named.obj != nil && named.TParams() != nil && named.targs == nil } func is(typ Type, what BasicInfo) bool { diff --git a/src/go/types/resolver.go b/src/go/types/resolver.go index 1434e6deb1..5e58c3dcfd 100644 --- a/src/go/types/resolver.go +++ b/src/go/types/resolver.go @@ -309,20 +309,24 @@ func (check *Checker) collectObjects() { check.dotImportMap = make(map[dotImportKey]*PkgName) } // merge imported scope with file scope - for _, obj := range imp.scope.elems { + for name, obj := range imp.scope.elems { + // Note: Avoid eager resolve(name, obj) here, so we only + // resolve dot-imported objects as needed. + // A package scope may contain non-exported objects, // do not import them! - if obj.Exported() { + if token.IsExported(name) { // declare dot-imported object // (Do not use check.declare because it modifies the object // via Object.setScopePos, which leads to a race condition; // the object may be imported into more than one file scope // concurrently. See issue #32154.) - if alt := fileScope.Insert(obj); alt != nil { - check.errorf(d.spec.Name, _DuplicateDecl, "%s redeclared in this block", obj.Name()) + if alt := fileScope.Lookup(name); alt != nil { + check.errorf(d.spec.Name, _DuplicateDecl, "%s redeclared in this block", alt.Name()) check.reportAltDecl(alt) } else { - check.dotImportMap[dotImportKey{fileScope, obj}] = pkgName + fileScope.insert(name, obj) + check.dotImportMap[dotImportKey{fileScope, name}] = pkgName } } } @@ -443,8 +447,9 @@ func (check *Checker) collectObjects() { // verify that objects in package and file scopes have different names for _, scope := range fileScopes { - for _, obj := range scope.elems { - if alt := pkg.scope.Lookup(obj.Name()); alt != nil { + for name, obj := range scope.elems { + if alt := pkg.scope.Lookup(name); alt != nil { + obj = resolve(name, obj) if pkg, ok := obj.(*PkgName); ok { check.errorf(alt, _DuplicateDecl, "%s already declared through import of %s", alt.Name(), pkg.Imported()) check.reportAltDecl(pkg) diff --git a/src/go/types/sanitize.go b/src/go/types/sanitize.go index 05e7d8b4bf..f54ab68624 100644 --- a/src/go/types/sanitize.go +++ b/src/go/types/sanitize.go @@ -135,6 +135,7 @@ func (s sanitizer) typ(typ Type) Type { if debug && t.check != nil { panic("internal error: Named.check != nil") } + t.expand() if orig := s.typ(t.fromRHS); orig != t.fromRHS { t.fromRHS = orig } diff --git a/src/go/types/scope.go b/src/go/types/scope.go index 26c28d1c4e..fa6e0ecb8f 100644 --- a/src/go/types/scope.go +++ b/src/go/types/scope.go @@ -13,6 +13,7 @@ import ( "io" "sort" "strings" + "sync" ) // A Scope maintains a set of objects and links to its containing @@ -66,7 +67,7 @@ func (s *Scope) Child(i int) *Scope { return s.children[i] } // Lookup returns the object in scope s with the given name if such an // object exists; otherwise the result is nil. func (s *Scope) Lookup(name string) Object { - return s.elems[name] + return resolve(name, s.elems[name]) } // LookupParent follows the parent chain of scopes starting with s until @@ -81,7 +82,7 @@ func (s *Scope) Lookup(name string) Object { // whose scope is the scope of the package that exported them. func (s *Scope) LookupParent(name string, pos token.Pos) (*Scope, Object) { for ; s != nil; s = s.parent { - if obj := s.elems[name]; obj != nil && (!pos.IsValid() || obj.scopePos() <= pos) { + if obj := s.Lookup(name); obj != nil && (!pos.IsValid() || obj.scopePos() <= pos) { return s, obj } } @@ -95,19 +96,38 @@ func (s *Scope) LookupParent(name string, pos token.Pos) (*Scope, Object) { // if not already set, and returns nil. func (s *Scope) Insert(obj Object) Object { name := obj.Name() - if alt := s.elems[name]; alt != nil { + if alt := s.Lookup(name); alt != nil { return alt } - if s.elems == nil { - s.elems = make(map[string]Object) - } - s.elems[name] = obj + s.insert(name, obj) if obj.Parent() == nil { obj.setParent(s) } return nil } +// _InsertLazy is like Insert, but allows deferring construction of the +// inserted object until it's accessed with Lookup. The Object +// returned by resolve must have the same name as given to _InsertLazy. +// If s already contains an alternative object with the same name, +// _InsertLazy leaves s unchanged and returns false. Otherwise it +// records the binding and returns true. The object's parent scope +// will be set to s after resolve is called. +func (s *Scope) _InsertLazy(name string, resolve func() Object) bool { + if s.elems[name] != nil { + return false + } + s.insert(name, &lazyObject{parent: s, resolve: resolve}) + return true +} + +func (s *Scope) insert(name string, obj Object) { + if s.elems == nil { + s.elems = make(map[string]Object) + } + s.elems[name] = obj +} + // squash merges s with its parent scope p by adding all // objects of s to p, adding all children of s to the // children of p, and removing s from p's children. @@ -117,7 +137,8 @@ func (s *Scope) Insert(obj Object) Object { func (s *Scope) squash(err func(obj, alt Object)) { p := s.parent assert(p != nil) - for _, obj := range s.elems { + for name, obj := range s.elems { + obj = resolve(name, obj) obj.setParent(nil) if alt := p.Insert(obj); alt != nil { err(obj, alt) @@ -196,7 +217,7 @@ func (s *Scope) WriteTo(w io.Writer, n int, recurse bool) { indn1 := indn + ind for _, name := range s.Names() { - fmt.Fprintf(w, "%s%s\n", indn1, s.elems[name]) + fmt.Fprintf(w, "%s%s\n", indn1, s.Lookup(name)) } if recurse { @@ -214,3 +235,57 @@ func (s *Scope) String() string { s.WriteTo(&buf, 0, false) return buf.String() } + +// A lazyObject represents an imported Object that has not been fully +// resolved yet by its importer. +type lazyObject struct { + parent *Scope + resolve func() Object + obj Object + once sync.Once +} + +// resolve returns the Object represented by obj, resolving lazy +// objects as appropriate. +func resolve(name string, obj Object) Object { + if lazy, ok := obj.(*lazyObject); ok { + lazy.once.Do(func() { + obj := lazy.resolve() + + if _, ok := obj.(*lazyObject); ok { + panic("recursive lazy object") + } + if obj.Name() != name { + panic("lazy object has unexpected name") + } + + if obj.Parent() == nil { + obj.setParent(lazy.parent) + } + lazy.obj = obj + }) + + obj = lazy.obj + } + return obj +} + +// stub implementations so *lazyObject implements Object and we can +// store them directly into Scope.elems. +func (*lazyObject) Parent() *Scope { panic("unreachable") } +func (*lazyObject) Pos() token.Pos { panic("unreachable") } +func (*lazyObject) Pkg() *Package { panic("unreachable") } +func (*lazyObject) Name() string { panic("unreachable") } +func (*lazyObject) Type() Type { panic("unreachable") } +func (*lazyObject) Exported() bool { panic("unreachable") } +func (*lazyObject) Id() string { panic("unreachable") } +func (*lazyObject) String() string { panic("unreachable") } +func (*lazyObject) order() uint32 { panic("unreachable") } +func (*lazyObject) color() color { panic("unreachable") } +func (*lazyObject) setType(Type) { panic("unreachable") } +func (*lazyObject) setOrder(uint32) { panic("unreachable") } +func (*lazyObject) setColor(color color) { panic("unreachable") } +func (*lazyObject) setParent(*Scope) { panic("unreachable") } +func (*lazyObject) sameId(pkg *Package, name string) bool { panic("unreachable") } +func (*lazyObject) scopePos() token.Pos { panic("unreachable") } +func (*lazyObject) setScopePos(pos token.Pos) { panic("unreachable") } diff --git a/src/go/types/signature.go b/src/go/types/signature.go index f56fe047c8..9be2cce752 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -57,7 +57,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast // again when we type-check the signature. // TODO(gri) maybe the receiver should be marked as invalid instead? if recv := asNamed(check.genericType(rname, false)); recv != nil { - recvTParams = recv.tparams + recvTParams = recv.TParams() } } // provide type parameter bounds diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index 9459f67769..9710edab15 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -30,7 +30,7 @@ func TestSizeof(t *testing.T) { {Interface{}, 52, 104}, {Map{}, 16, 32}, {Chan{}, 12, 24}, - {Named{}, 68, 136}, + {Named{}, 84, 160}, {_TypeParam{}, 28, 48}, {instance{}, 44, 88}, {top{}, 0, 0}, diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index 9dcaceaca7..afef833490 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -65,7 +65,8 @@ func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body func (check *Checker) usage(scope *Scope) { var unused []*Var - for _, elem := range scope.elems { + for name, elem := range scope.elems { + elem = resolve(name, elem) if v, _ := elem.(*Var); v != nil && !v.used { unused = append(unused, v) } diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 025eba0f8c..dc30bfbe67 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -79,7 +79,7 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, poslist var tparams []*TypeName switch t := typ.(type) { case *Named: - tparams = t.tparams + tparams = t.TParams() case *Signature: tparams = t.tparams defer func() { @@ -351,7 +351,7 @@ func (subst *subster) typ(typ Type) Type { } } - if t.tparams == nil { + if t.TParams() == nil { dump(">>> %s is not parameterized", t) return t // type is not parameterized } @@ -361,7 +361,7 @@ func (subst *subster) typ(typ Type) Type { if len(t.targs) > 0 { // already instantiated dump(">>> %s already instantiated", t) - assert(len(t.targs) == len(t.tparams)) + assert(len(t.targs) == len(t.TParams())) // For each (existing) type argument targ, determine if it needs // to be substituted; i.e., if it is or contains a type parameter // that has a type argument for it. @@ -371,7 +371,7 @@ func (subst *subster) typ(typ Type) Type { if newTarg != targ { dump(">>> substituted %d targ %s => %s", i, targ, newTarg) if newTargs == nil { - newTargs = make([]Type, len(t.tparams)) + newTargs = make([]Type, len(t.TParams())) copy(newTargs, t.targs) } newTargs[i] = newTarg @@ -402,7 +402,7 @@ func (subst *subster) typ(typ Type) Type { // create a new named type and populate caches to avoid endless recursion tname := NewTypeName(subst.pos, t.obj.pkg, t.obj.name, nil) - named := subst.check.newNamed(tname, t, t.underlying, t.tparams, t.methods) // method signatures are updated lazily + named := subst.check.newNamed(tname, t, t.Underlying(), t.TParams(), t.methods) // method signatures are updated lazily named.targs = newTargs if subst.check != nil { subst.check.typMap[h] = named @@ -411,7 +411,7 @@ func (subst *subster) typ(typ Type) Type { // do the substitution dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, newTargs) - named.underlying = subst.typOrNil(t.underlying) + named.underlying = subst.typOrNil(t.Underlying()) named.fromRHS = named.underlying // for cycle detection (Checker.validType) return named diff --git a/src/go/types/type.go b/src/go/types/type.go index 7429056865..d555a8f684 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -6,6 +6,7 @@ package types import ( "go/token" + "sync" "sync/atomic" ) @@ -504,6 +505,9 @@ type Named struct { tparams []*TypeName // type parameters, or nil targs []Type // type arguments (after instantiation), or nil methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily + + resolve func(*Named) ([]*TypeName, Type, []*Func) + once sync.Once } // NewNamed returns a new named type for the given type name, underlying type, and associated methods. @@ -516,6 +520,35 @@ func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named { return (*Checker)(nil).newNamed(obj, nil, underlying, nil, methods) } +func (t *Named) expand() *Named { + if t.resolve == nil { + return t + } + + t.once.Do(func() { + // TODO(mdempsky): Since we're passing t to resolve anyway + // (necessary because types2 expects the receiver type for methods + // on defined interface types to be the Named rather than the + // underlying Interface), maybe it should just handle calling + // SetTParams, SetUnderlying, and AddMethod instead? Those + // methods would need to support reentrant calls though. It would + // also make the API more future-proof towards further extensions + // (like SetTParams). + + tparams, underlying, methods := t.resolve(t) + + switch underlying.(type) { + case nil, *Named: + panic("invalid underlying type") + } + + t.tparams = tparams + t.underlying = underlying + t.methods = methods + }) + return t +} + func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams []*TypeName, methods []*Func) *Named { typ := &Named{check: check, obj: obj, orig: orig, fromRHS: underlying, underlying: underlying, tparams: tparams, methods: methods} if typ.orig == nil { @@ -556,10 +589,10 @@ func (t *Named) _Orig() *Named { return t.orig } // _TParams returns the type parameters of the named type t, or nil. // The result is non-nil for an (originally) parameterized type even if it is instantiated. -func (t *Named) _TParams() []*TypeName { return t.tparams } +func (t *Named) _TParams() []*TypeName { return t.expand().tparams } // _SetTParams sets the type parameters of the named type t. -func (t *Named) _SetTParams(tparams []*TypeName) { t.tparams = tparams } +func (t *Named) _SetTParams(tparams []*TypeName) { t.expand().tparams = tparams } // _TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated. func (t *Named) _TArgs() []Type { return t.targs } @@ -568,10 +601,10 @@ func (t *Named) _TArgs() []Type { return t.targs } func (t *Named) _SetTArgs(args []Type) { t.targs = args } // NumMethods returns the number of explicit methods whose receiver is named type t. -func (t *Named) NumMethods() int { return len(t.methods) } +func (t *Named) NumMethods() int { return len(t.expand().methods) } // Method returns the i'th method of named type t for 0 <= i < t.NumMethods(). -func (t *Named) Method(i int) *Func { return t.methods[i] } +func (t *Named) Method(i int) *Func { return t.expand().methods[i] } // SetUnderlying sets the underlying type and marks t as complete. func (t *Named) SetUnderlying(underlying Type) { @@ -581,11 +614,12 @@ func (t *Named) SetUnderlying(underlying Type) { if _, ok := underlying.(*Named); ok { panic("types.Named.SetUnderlying: underlying type must not be *Named") } - t.underlying = underlying + t.expand().underlying = underlying } // AddMethod adds method m unless it is already in the method list. func (t *Named) AddMethod(m *Func) { + t.expand() if i, _ := lookupMethod(t.methods, m.pkg, m.name); i < 0 { t.methods = append(t.methods, m) } @@ -736,7 +770,7 @@ func (t *Signature) Underlying() Type { return t } func (t *Interface) Underlying() Type { return t } func (t *Map) Underlying() Type { return t } func (t *Chan) Underlying() Type { return t } -func (t *Named) Underlying() Type { return t.underlying } +func (t *Named) Underlying() Type { return t.expand().underlying } func (t *_TypeParam) Underlying() Type { return t } func (t *instance) Underlying() Type { return t } func (t *top) Underlying() Type { return t } diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 73465a35b7..79b4f74ff3 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -273,9 +273,9 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { buf.WriteByte('[') writeTypeList(buf, t.targs, qf, visited) buf.WriteByte(']') - } else if t.tparams != nil { + } else if t.TParams() != nil { // parameterized type - writeTParamList(buf, t.tparams, qf, visited) + writeTParamList(buf, t.TParams(), qf, visited) } case *_TypeParam: diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index f62b41831e..249a3ac5c5 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -56,7 +56,7 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool) // If so, mark the respective package as used. // (This code is only needed for dot-imports. Without them, // we only have to mark variables, see *Var case below). - if pkgName := check.dotImportMap[dotImportKey{scope, obj}]; pkgName != nil { + if pkgName := check.dotImportMap[dotImportKey{scope, obj.Name()}]; pkgName != nil { pkgName.used = true } -- GitLab From 24f9eb2de34d8d92dac4c6ffaa55ff2234c639d2 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Thu, 15 Jul 2021 22:49:00 -0400 Subject: [PATCH 0456/2500] [dev.typeparams] go/types: introduce type set abstraction for interfaces This is a port of CL 329309 to go/types, with minor updates for API differences and to handle methodset.go, which doesn't exist in types2. A couple pre-existing comments were adjusted to match types2. Change-Id: I3fd556e1326013a694ff5edb8518ca24c27bd10b Reviewed-on: https://go-review.googlesource.com/c/go/+/334894 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/api_typeparams.go | 4 - src/go/types/builtins.go | 2 +- src/go/types/call.go | 3 +- src/go/types/expr.go | 1 - src/go/types/infer.go | 27 ++---- src/go/types/interface.go | 63 ++++++------ src/go/types/lookup.go | 19 ++-- src/go/types/methodset.go | 4 +- src/go/types/predicates.go | 20 +--- src/go/types/sanitize.go | 8 +- src/go/types/sizeof_test.go | 3 +- src/go/types/subst.go | 15 ++- src/go/types/testdata/check/cycles4.src | 15 ++- src/go/types/type.go | 121 ++++++++---------------- src/go/types/typeset.go | 70 ++++++++++++++ src/go/types/typestring.go | 13 ++- src/go/types/typexpr.go | 8 +- src/go/types/unify.go | 13 +-- src/go/types/universe.go | 4 +- 19 files changed, 210 insertions(+), 203 deletions(-) create mode 100644 src/go/types/typeset.go diff --git a/src/go/types/api_typeparams.go b/src/go/types/api_typeparams.go index 6aaefbb6b2..864103df63 100644 --- a/src/go/types/api_typeparams.go +++ b/src/go/types/api_typeparams.go @@ -21,10 +21,6 @@ func NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam { func (s *Signature) TParams() []*TypeName { return s._TParams() } func (s *Signature) SetTParams(tparams []*TypeName) { s._SetTParams(tparams) } -func (t *Interface) HasTypeList() bool { return t._HasTypeList() } -func (t *Interface) IsComparable() bool { return t._IsComparable() } -func (t *Interface) IsConstraint() bool { return t._IsConstraint() } - func (t *Named) TParams() []*TypeName { return t._TParams() } func (t *Named) TArgs() []Type { return t._TArgs() } func (t *Named) SetTArgs(args []Type) { t._SetTArgs(args) } diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index cfaeab611b..5670790856 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -785,7 +785,7 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { tpar := NewTypeName(token.NoPos, nil /* = Universe pkg */, "", nil) ptyp := check.newTypeParam(tpar, 0, &emptyInterface) // assigns type to tpar as a side-effect tsum := newUnion(rtypes, tildes) - ptyp.bound = &Interface{allMethods: markComplete, allTypes: tsum} + ptyp.bound = &Interface{complete: true, tset: &TypeSet{types: tsum}} return ptyp } diff --git a/src/go/types/call.go b/src/go/types/call.go index 337ee741c6..cef5e9fc59 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -109,8 +109,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { break } if t := asInterface(T); t != nil { - check.completeInterface(token.NoPos, t) - if t._IsConstraint() { + if t.IsConstraint() { check.errorf(call, _Todo, "cannot use interface %s in conversion (contains type list or is comparable)", T) break } diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 95f2a8d6ab..c8adea45e2 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -682,7 +682,6 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const return Typ[UntypedNil], nil, 0 } // cannot assign untyped values to non-empty interfaces - check.completeInterface(token.NoPos, t) if !t.Empty() { return nil, nil, _InvalidUntypedConversion } diff --git a/src/go/types/infer.go b/src/go/types/infer.go index 5a4f939bb1..ae53f68e48 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -316,24 +316,13 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { return w.isParameterized(t.params) || w.isParameterized(t.results) case *Interface: - if t.allMethods != nil { - // TODO(rFindley) at some point we should enforce completeness here - for _, m := range t.allMethods { - if w.isParameterized(m.typ) { - return true - } + tset := t.typeSet() + for _, m := range tset.methods { + if w.isParameterized(m.typ) { + return true } - return w.isParameterized(t.allTypes) } - - return t.iterate(func(t *Interface) bool { - for _, m := range t.methods { - if w.isParameterized(m.typ) { - return true - } - } - return w.isParameterizedList(t.embeddeds) - }, nil) + return w.isParameterized(tset.types) case *Map: return w.isParameterized(t.key) || w.isParameterized(t.elem) @@ -471,15 +460,15 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty // structuralType returns the structural type of a constraint, if any. func (check *Checker) structuralType(constraint Type) Type { if iface, _ := under(constraint).(*Interface); iface != nil { - check.completeInterface(token.NoPos, iface) - if u, _ := iface.allTypes.(*Union); u != nil { + types := iface.typeSet().types + if u, _ := types.(*Union); u != nil { if u.NumTerms() == 1 { // TODO(gri) do we need to respect tilde? return u.types[0] } return nil } - return iface.allTypes + return types } return nil } diff --git a/src/go/types/interface.go b/src/go/types/interface.go index 947e76dc17..3a4da569ab 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -98,9 +98,13 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d check.posMap[ityp] = append(check.posMap[ityp], tlist[0].(*ast.UnaryExpr).X.Pos()) } + // All methods and embedded elements for this interface are collected; + // i.e., this interface is may be used in a type set computation. + ityp.complete = true + if len(ityp.methods) == 0 && len(ityp.embeddeds) == 0 { // empty interface - ityp.allMethods = markComplete + ityp.tset = &topTypeSet return } @@ -108,7 +112,10 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d sortMethods(ityp.methods) sortTypes(ityp.embeddeds) - check.later(func() { check.completeInterface(iface.Pos(), ityp) }) + // Compute type set with a non-nil *Checker as soon as possible + // to report any errors. Subsequent uses of type sets should be + // using this computed type set and won't need to pass in a *Checker. + check.later(func() { newTypeSet(check, iface.Pos(), ityp) }) } func flattenUnion(list []ast.Expr, x ast.Expr) []ast.Expr { @@ -119,24 +126,26 @@ func flattenUnion(list []ast.Expr, x ast.Expr) []ast.Expr { return append(list, x) } -func (check *Checker) completeInterface(pos token.Pos, ityp *Interface) { - if ityp.allMethods != nil { - return +// newTypeSet may be called with check == nil. +// TODO(gri) move this function into typeset.go eventually +func newTypeSet(check *Checker, pos token.Pos, ityp *Interface) *TypeSet { + if ityp.tset != nil { + return ityp.tset } - // completeInterface may be called via the LookupFieldOrMethod, - // MissingMethod, Identical, or IdenticalIgnoreTags external API - // in which case check will be nil. In this case, type-checking - // must be finished and all interfaces should have been completed. - if check == nil { - panic("internal error: incomplete interface") + // If the interface is not fully set up yet, the type set will + // not be complete, which may lead to errors when using the the + // type set (e.g. missing method). Don't compute a partial type + // set (and don't store it!), so that we still compute the full + // type set eventually. Instead, return the top type set and + // let any follow-on errors play out. + // + // TODO(gri) Consider recording when this happens and reporting + // it as an error (but only if there were no other errors so to + // to not have unnecessary follow-on errors). + if !ityp.complete { + return &topTypeSet } - completeInterface(check, pos, ityp) -} - -// completeInterface may be called with check == nil. -func completeInterface(check *Checker, pos token.Pos, ityp *Interface) { - assert(ityp.allMethods == nil) if check != nil && trace { // Types don't generally have position information. @@ -146,11 +155,11 @@ func completeInterface(check *Checker, pos token.Pos, ityp *Interface) { pos = ityp.methods[0].pos } - check.trace(pos, "complete %s", ityp) + check.trace(pos, "type set for %s", ityp) check.indent++ defer func() { check.indent-- - check.trace(pos, "=> %s (methods = %v, types = %v)", ityp, ityp.allMethods, ityp.allTypes) + check.trace(pos, "=> %s ", ityp.typeSet()) }() } @@ -159,7 +168,7 @@ func completeInterface(check *Checker, pos token.Pos, ityp *Interface) { // have valid interfaces. Mark the interface as complete to avoid // infinite recursion if the validType check occurs later for some // reason. - ityp.allMethods = markComplete + ityp.tset = new(TypeSet) // TODO(gri) is this sufficient? // Methods of embedded interfaces are collected unchanged; i.e., the identity // of a method I.m's Func Object of an interface I is the same as that of @@ -229,14 +238,12 @@ func completeInterface(check *Checker, pos token.Pos, ityp *Interface) { var types Type switch t := under(typ).(type) { case *Interface: - if t.allMethods == nil { - completeInterface(check, pos, t) - } - for _, m := range t.allMethods { + tset := newTypeSet(check, pos, t) + for _, m := range tset.methods { addMethod(pos, m, false) // use embedding position pos rather than m.pos } - types = t.allTypes + types = tset.types case *Union: // TODO(gri) combine with default case once we have // converted all tests to new notation and we @@ -273,9 +280,11 @@ func completeInterface(check *Checker, pos token.Pos, ityp *Interface) { if methods != nil { sort.Sort(byUniqueMethodName(methods)) - ityp.allMethods = methods + ityp.tset.methods = methods } - ityp.allTypes = allTypes + ityp.tset.types = allTypes + + return ityp.tset } func sortTypes(list []Type) { diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index 5b22c4744e..4ce4b3217c 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -186,9 +186,7 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack case *Interface: // look for a matching method - // TODO(gri) t.allMethods is sorted - use binary search - check.completeInterface(token.NoPos, t) - if i, m := lookupMethod(t.allMethods, pkg, name); m != nil { + if i, m := t.typeSet().LookupMethod(pkg, name); m != nil { assert(m.typ != nil) index = concat(e.index, i) if obj != nil || e.multiples { @@ -199,9 +197,7 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack } case *_TypeParam: - // only consider explicit methods in the type parameter bound, not - // methods that may be common to all types in the type list. - if i, m := lookupMethod(t.Bound().allMethods, pkg, name); m != nil { + if i, m := t.Bound().typeSet().LookupMethod(pkg, name); m != nil { assert(m.typ != nil) index = concat(e.index, i) if obj != nil || e.multiples { @@ -307,18 +303,15 @@ func MissingMethod(V Type, T *Interface, static bool) (method *Func, wrongType b // To improve error messages, also report the wrong signature // when the method exists on *V instead of V. func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, wrongType *Func) { - check.completeInterface(token.NoPos, T) - // fast path for common case if T.Empty() { return } if ityp := asInterface(V); ityp != nil { - check.completeInterface(token.NoPos, ityp) - // TODO(gri) allMethods is sorted - can do this more efficiently - for _, m := range T.allMethods { - _, f := lookupMethod(ityp.allMethods, m.pkg, m.name) + // TODO(gri) the methods are sorted - could do this more efficiently + for _, m := range T.typeSet().methods { + _, f := ityp.typeSet().LookupMethod(m.pkg, m.name) if f == nil { // if m is the magic method == we're ok (interfaces are comparable) @@ -356,7 +349,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // A concrete type implements T if it implements all methods of T. Vd, _ := deref(V) Vn := asNamed(Vd) - for _, m := range T.allMethods { + for _, m := range T.typeSet().methods { // TODO(gri) should this be calling lookupFieldOrMethod instead (and why not)? obj, _, _ := check.rawLookupFieldOrMethod(V, false, m.pkg, m.name) diff --git a/src/go/types/methodset.go b/src/go/types/methodset.go index ae8011a2ee..71d634bf36 100644 --- a/src/go/types/methodset.go +++ b/src/go/types/methodset.go @@ -157,10 +157,10 @@ func NewMethodSet(T Type) *MethodSet { } case *Interface: - mset = mset.add(t.allMethods, e.index, true, e.multiples) + mset = mset.add(t.typeSet().methods, e.index, true, e.multiples) case *_TypeParam: - mset = mset.add(t.Bound().allMethods, e.index, true, e.multiples) + mset = mset.add(t.Bound().typeSet().methods, e.index, true, e.multiples) } } diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 9f3e324597..7f6eee8120 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -6,10 +6,6 @@ package types -import ( - "go/token" -) - // isNamed reports whether typ has a name. // isNamed may be called with types that are not fully set up. func isNamed(typ Type) bool { @@ -109,7 +105,7 @@ func comparable(T Type, seen map[Type]bool) bool { // // is not comparable because []byte is not comparable. if t := asTypeParam(T); t != nil && optype(t) == theTop { - return t.Bound()._IsComparable() + return t.Bound().IsComparable() } switch t := optype(T).(type) { @@ -133,7 +129,7 @@ func comparable(T Type, seen map[Type]bool) bool { return comparable(t, seen) }) case *_TypeParam: - return t.Bound()._IsComparable() + return t.Bound().IsComparable() } return false } @@ -291,16 +287,8 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { // the same names and identical function types. Lower-case method names from // different packages are always different. The order of the methods is irrelevant. if y, ok := y.(*Interface); ok { - // If identical0 is called (indirectly) via an external API entry point - // (such as Identical, IdenticalIgnoreTags, etc.), check is nil. But in - // that case, interfaces are expected to be complete and lazy completion - // here is not needed. - if check != nil { - check.completeInterface(token.NoPos, x) - check.completeInterface(token.NoPos, y) - } - a := x.allMethods - b := y.allMethods + a := x.typeSet().methods + b := y.typeSet().methods if len(a) == len(b) { // Interface types are the only types where cycles can occur // that are not "terminated" via named types; and such cycles diff --git a/src/go/types/sanitize.go b/src/go/types/sanitize.go index f54ab68624..df09a6a38f 100644 --- a/src/go/types/sanitize.go +++ b/src/go/types/sanitize.go @@ -113,9 +113,11 @@ func (s sanitizer) typ(typ Type) Type { case *Interface: s.funcList(t.methods) s.typeList(t.embeddeds) - s.funcList(t.allMethods) - if allTypes := s.typ(t.allTypes); allTypes != t.allTypes { - t.allTypes = allTypes + // TODO(gri) do we need to sanitize type sets? + tset := t.typeSet() + s.funcList(tset.methods) + if types := s.typ(tset.types); types != tset.types { + tset.types = types } case *Map: diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index 9710edab15..05a171f498 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -27,7 +27,7 @@ func TestSizeof(t *testing.T) { {Tuple{}, 12, 24}, {Signature{}, 44, 88}, {Union{}, 24, 48}, - {Interface{}, 52, 104}, + {Interface{}, 40, 80}, {Map{}, 16, 32}, {Chan{}, 12, 24}, {Named{}, 84, 160}, @@ -48,6 +48,7 @@ func TestSizeof(t *testing.T) { // Misc {Scope{}, 40, 80}, {Package{}, 40, 80}, + {TypeSet{}, 20, 40}, } for _, test := range tests { got := reflect.TypeOf(test.val).Size() diff --git a/src/go/types/subst.go b/src/go/types/subst.go index dc30bfbe67..0e2e7f408a 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -139,6 +139,7 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, poslist // satisfies reports whether the type argument targ satisfies the constraint of type parameter // parameter tpar (after any of its type parameters have been substituted through smap). // A suitable error is reported if the result is false. +// TODO(gri) This should be a method of interfaces or type sets. func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *_TypeParam, smap *substMap) bool { iface := tpar.Bound() if iface.Empty() { @@ -153,8 +154,7 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *_TypeParam, smap // targ must implement iface (methods) // - check only if we have methods - check.completeInterface(token.NoPos, iface) - if len(iface.allMethods) > 0 { + if iface.NumMethods() > 0 { // If the type argument is a pointer to a type parameter, the type argument's // method set is empty. // TODO(gri) is this what we want? (spec question) @@ -186,7 +186,7 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *_TypeParam, smap } // targ's underlying type must also be one of the interface types listed, if any - if iface.allTypes == nil { + if iface.typeSet().types == nil { return true // nothing to do } @@ -194,7 +194,7 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *_TypeParam, smap // list of iface types (i.e., the targ type list must be a non-empty subset of the iface types). if targ := asTypeParam(targ); targ != nil { targBound := targ.Bound() - if targBound.allTypes == nil { + if targBound.typeSet().types == nil { check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ) return false } @@ -202,7 +202,7 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *_TypeParam, smap // TODO(gri) incorporate tilde information! if !iface.isSatisfiedBy(typ) { // TODO(gri) match this error message with the one below (or vice versa) - check.softErrorf(atPos(pos), 0, "%s does not satisfy %s (%s type constraint %s not found in %s)", targ, tpar.bound, targ, typ, iface.allTypes) + check.softErrorf(atPos(pos), 0, "%s does not satisfy %s (%s type constraint %s not found in %s)", targ, tpar.bound, targ, typ, iface.typeSet().types) return false } return true @@ -211,7 +211,7 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *_TypeParam, smap // Otherwise, targ's type or underlying type must also be one of the interface types listed, if any. if !iface.isSatisfiedBy(targ) { - check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s not found in %s)", targ, tpar.bound, targ, iface.allTypes) + check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s not found in %s)", targ, tpar.bound, targ, iface.typeSet().types) return false } @@ -316,12 +316,11 @@ func (subst *subster) typ(typ Type) Type { methods, mcopied := subst.funcList(t.methods) embeddeds, ecopied := subst.typeList(t.embeddeds) if mcopied || ecopied { - iface := &Interface{methods: methods, embeddeds: embeddeds} + iface := &Interface{methods: methods, embeddeds: embeddeds, complete: t.complete} if subst.check == nil { panic("internal error: cannot instantiate interfaces yet") } subst.check.posMap[iface] = subst.check.posMap[t] // satisfy completeInterface requirement - subst.check.completeInterface(token.NoPos, iface) return iface } diff --git a/src/go/types/testdata/check/cycles4.src b/src/go/types/testdata/check/cycles4.src index 445babca68..924aabf475 100644 --- a/src/go/types/testdata/check/cycles4.src +++ b/src/go/types/testdata/check/cycles4.src @@ -4,6 +4,8 @@ package p +import "unsafe" + // Check that all methods of T are collected before // determining the result type of m (which embeds // all methods of T). @@ -13,7 +15,7 @@ type T interface { E } -var _ = T.m(nil).m().e() +var _ int = T.m(nil).m().e() type E interface { e() int @@ -22,7 +24,7 @@ type E interface { // Check that unresolved forward chains are followed // (see also comment in resolver.go, checker.typeDecl). -var _ = C.m(nil).m().e() +var _ int = C.m(nil).m().e() type A B @@ -108,3 +110,12 @@ type Element interface { type Event interface { Target() Element } + +// Check that accessing an interface method too early doesn't lead +// to follow-on errors due to an incorrectly computed type set. + +type T8 interface { + m() [unsafe.Sizeof(T8.m /* ERROR undefined */ )]int +} + +var _ = T8.m // no error expected here diff --git a/src/go/types/type.go b/src/go/types/type.go index d555a8f684..4dcc511b93 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -258,18 +258,20 @@ func (s *Signature) Variadic() bool { return s.variadic } // An Interface represents an interface type. type Interface struct { + obj Object // type name object defining this interface; or nil (for better error messages) methods []*Func // ordered list of explicitly declared methods - embeddeds []Type // ordered list of explicitly embedded types + embeddeds []Type // ordered list of explicitly embedded elements + complete bool // indicates that obj, methods, and embeddeds are set and type set can be computed - allMethods []*Func // ordered list of methods declared with or embedded in this interface (TODO(gri): replace with mset) - allTypes Type // intersection of all embedded and locally declared types (TODO(gri) need better field name) - - obj Object // type declaration defining this interface; or nil (for better error messages) + tset *TypeSet // type set described by this interface, computed lazily } +// typeSet returns the type set for interface t. +func (t *Interface) typeSet() *TypeSet { return newTypeSet(nil, token.NoPos, t) } + // is reports whether interface t represents types that all satisfy f. func (t *Interface) is(f func(Type, bool) bool) bool { - switch t := t.allTypes.(type) { + switch t := t.typeSet().types.(type) { case nil, *top: // TODO(gri) should settle on top or nil to represent this case return false // we must have at least one type! (was bug) @@ -281,20 +283,13 @@ func (t *Interface) is(f func(Type, bool) bool) bool { } // emptyInterface represents the empty (completed) interface -var emptyInterface = Interface{allMethods: markComplete} - -// markComplete is used to mark an empty interface as completely -// set up by setting the allMethods field to a non-nil empty slice. -var markComplete = make([]*Func, 0) +var emptyInterface = Interface{complete: true, tset: &topTypeSet} -// NewInterface returns a new (incomplete) interface for the given methods and embedded types. -// Each embedded type must have an underlying type of interface type. -// NewInterface takes ownership of the provided methods and may modify their types by setting -// missing receivers. To compute the method set of the interface, Complete must be called. +// NewInterface returns a new interface for the given methods and embedded types. +// NewInterface takes ownership of the provided methods and may modify their types +// by setting missing receivers. // -// Deprecated: Use NewInterfaceType instead which allows any (even non-defined) interface types -// to be embedded. This is necessary for interfaces that embed alias type names referring to -// non-defined (literal) interface types. +// Deprecated: Use NewInterfaceType instead which allows arbitrary embedded types. func NewInterface(methods []*Func, embeddeds []*Named) *Interface { tnames := make([]Type, len(embeddeds)) for i, t := range embeddeds { @@ -303,12 +298,9 @@ func NewInterface(methods []*Func, embeddeds []*Named) *Interface { return NewInterfaceType(methods, tnames) } -// NewInterfaceType returns a new (incomplete) interface for the given methods and embedded types. -// Each embedded type must have an underlying type of interface type (this property is not -// verified for defined types, which may be in the process of being set up and which don't -// have a valid underlying type yet). -// NewInterfaceType takes ownership of the provided methods and may modify their types by setting -// missing receivers. To compute the method set of the interface, Complete must be called. +// NewInterfaceType returns a new interface for the given methods and embedded types. +// NewInterfaceType takes ownership of the provided methods and may modify their types +// by setting missing receivers. func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface { if len(methods) == 0 && len(embeddeds) == 0 { return &emptyInterface @@ -338,6 +330,8 @@ func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface { typ.methods = methods typ.embeddeds = embeddeds + typ.complete = true + return typ } @@ -361,64 +355,20 @@ func (t *Interface) Embedded(i int) *Named { tname, _ := t.embeddeds[i].(*Named) func (t *Interface) EmbeddedType(i int) Type { return t.embeddeds[i] } // NumMethods returns the total number of methods of interface t. -// The interface must have been completed. -func (t *Interface) NumMethods() int { t.Complete(); return len(t.allMethods) } +func (t *Interface) NumMethods() int { return t.typeSet().NumMethods() } // Method returns the i'th method of interface t for 0 <= i < t.NumMethods(). // The methods are ordered by their unique Id. -// The interface must have been completed. -func (t *Interface) Method(i int) *Func { t.Complete(); return t.allMethods[i] } +func (t *Interface) Method(i int) *Func { return t.typeSet().Method(i) } // Empty reports whether t is the empty interface. -func (t *Interface) Empty() bool { - t.Complete() - return len(t.allMethods) == 0 && t.allTypes == nil -} - -// _HasTypeList reports whether interface t has a type list, possibly from an embedded type. -func (t *Interface) _HasTypeList() bool { - t.Complete() - return t.allTypes != nil -} - -// _IsComparable reports whether interface t is or embeds the predeclared interface "comparable". -func (t *Interface) _IsComparable() bool { - t.Complete() - _, m := lookupMethod(t.allMethods, nil, "==") - return m != nil -} +func (t *Interface) Empty() bool { return t.typeSet().IsTop() } -// _IsConstraint reports t.HasTypeList() || t.IsComparable(). -func (t *Interface) _IsConstraint() bool { - return t._HasTypeList() || t._IsComparable() -} +// IsComparable reports whether interface t is or embeds the predeclared interface "comparable". +func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() } -// iterate calls f with t and then with any embedded interface of t, recursively, until f returns true. -// iterate reports whether any call to f returned true. -// TODO(rfindley) This is now only used by infer.go - see if we can eliminate it. -func (t *Interface) iterate(f func(*Interface) bool, seen map[*Interface]bool) bool { - if f(t) { - return true - } - for _, e := range t.embeddeds { - // e should be an interface but be careful (it may be invalid) - if e := asInterface(e); e != nil { - // Cyclic interfaces such as "type E interface { E }" are not permitted - // but they are still constructed and we need to detect such cycles. - if seen[e] { - continue - } - if seen == nil { - seen = make(map[*Interface]bool) - } - seen[e] = true - if e.iterate(f, seen) { - return true - } - } - } - return false -} +// IsConstraint reports whether interface t is not just a method set. +func (t *Interface) IsConstraint() bool { return !t.typeSet().IsMethodSet() } // isSatisfiedBy reports whether interface t's type list is satisfied by the type typ. // If the type list is empty (absent), typ trivially satisfies the interface. @@ -426,7 +376,7 @@ func (t *Interface) iterate(f func(*Interface) bool, seen map[*Interface]bool) b // "implements" predicate. func (t *Interface) isSatisfiedBy(typ Type) bool { t.Complete() - switch t := t.allTypes.(type) { + switch t := t.typeSet().types.(type) { case nil: return true // no type restrictions case *Union: @@ -437,15 +387,22 @@ func (t *Interface) isSatisfiedBy(typ Type) bool { } } -// Complete computes the interface's method set. It must be called by users of +// Complete computes the interface's type set. It must be called by users of // NewInterfaceType and NewInterface after the interface's embedded types are // fully defined and before using the interface type in any way other than to // form other types. The interface must not contain duplicate methods or a // panic occurs. Complete returns the receiver. +// +// Deprecated: Type sets are now computed lazily, on demand; this function +// is only here for backward-compatibility. It does not have to +// be called explicitly anymore. func (t *Interface) Complete() *Interface { - if t.allMethods == nil { - completeInterface(nil, token.NoPos, t) - } + // Some tests are still depending on the state change + // (string representation of an Interface not containing an + // /* incomplete */ marker) caused by the explicit Complete + // call, so we compute the type set eagerly here. + t.complete = true + t.typeSet() return t } @@ -668,7 +625,7 @@ func (t *_TypeParam) Bound() *Interface { pos = n.obj.pos } // TODO(rFindley) switch this to an unexported method on Checker. - t.check.completeInterface(pos, iface) + newTypeSet(t.check, pos, iface) return iface } @@ -685,7 +642,7 @@ func optype(typ Type) Type { // for a type parameter list of the form: // (type T interface { type T }). // See also issue #39680. - if a := t.Bound().allTypes; a != nil && a != typ { + if a := t.Bound().typeSet().types; a != nil && a != typ { // If we have a union with a single entry, ignore // any tilde because under(~t) == under(t). if u, _ := a.(*Union); u != nil && u.NumTerms() == 1 { diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go new file mode 100644 index 0000000000..9ba04b97bf --- /dev/null +++ b/src/go/types/typeset.go @@ -0,0 +1,70 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +import ( + "bytes" +) + +// topTypeSet may be used as type set for the empty interface. +var topTypeSet TypeSet + +// A TypeSet represents the type set of an interface. +type TypeSet struct { + // TODO(gri) consider using a set for the methods for faster lookup + methods []*Func // all methods of the interface; sorted by unique ID + types Type // typically a *Union; nil means no type restrictions +} + +func (s *TypeSet) String() string { + if s.IsTop() { + return "⊤" + } + + var buf bytes.Buffer + buf.WriteByte('{') + for i, m := range s.methods { + if i > 0 { + buf.WriteByte(';') + } + buf.WriteByte(' ') + buf.WriteString(m.String()) + } + if len(s.methods) > 0 && s.types != nil { + buf.WriteByte(';') + } + if s.types != nil { + buf.WriteByte(' ') + writeType(&buf, s.types, nil, nil) + } + + buf.WriteString(" }") // there was a least one method or type + return buf.String() +} + +// IsTop reports whether type set s is the top type set (corresponding to the empty interface). +func (s *TypeSet) IsTop() bool { return len(s.methods) == 0 && s.types == nil } + +// IsMethodSet reports whether the type set s is described by a single set of methods. +func (s *TypeSet) IsMethodSet() bool { return s.types == nil && !s.IsComparable() } + +// IsComparable reports whether each type in the set is comparable. +func (s *TypeSet) IsComparable() bool { + _, m := s.LookupMethod(nil, "==") + return m != nil +} + +// NumMethods returns the number of methods available. +func (s *TypeSet) NumMethods() int { return len(s.methods) } + +// Method returns the i'th method of type set s for 0 <= i < s.NumMethods(). +// The methods are ordered by their unique ID. +func (s *TypeSet) Method(i int) *Func { return s.methods[i] } + +// LookupMethod returns the index of and method with matching package and name, or (-1, nil). +func (s *TypeSet) LookupMethod(pkg *Package, name string) (int, *Func) { + // TODO(gri) s.methods is sorted - consider binary search + return lookupMethod(s.methods, pkg, name) +} diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 79b4f74ff3..fb398de502 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -190,7 +190,8 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { if gcCompatibilityMode { // print flattened interface // (useful to compare against gc-generated interfaces) - for i, m := range t.allMethods { + tset := t.typeSet() + for i, m := range tset.methods { if i > 0 { buf.WriteString("; ") } @@ -198,12 +199,12 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { writeSignature(buf, m.typ.(*Signature), qf, visited) empty = false } - if !empty && t.allTypes != nil { + if !empty && tset.types != nil { buf.WriteString("; ") } - if t.allTypes != nil { + if tset.types != nil { buf.WriteString("type ") - writeType(buf, t.allTypes, qf, visited) + writeType(buf, tset.types, qf, visited) } } else { // print explicit interface methods and embedded types @@ -226,7 +227,9 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { empty = false } } - if debug && (t.allMethods == nil || len(t.methods) > len(t.allMethods)) { + // print /* incomplete */ if needed to satisfy existing tests + // TODO(gri) get rid of this eventually + if debug && t.tset == nil { if !empty { buf.WriteByte(' ') } diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 249a3ac5c5..070b0ade3e 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -140,12 +140,12 @@ func (check *Checker) ordinaryType(pos positioner, typ Type) { // type-checking. check.later(func() { if t := asInterface(typ); t != nil { - check.completeInterface(pos.Pos(), t) // TODO(gri) is this the correct position? - if t.allTypes != nil { - check.softErrorf(pos, _Todo, "interface contains type constraints (%s)", t.allTypes) + tset := newTypeSet(check, pos.Pos(), t) // TODO(gri) is this the correct position? + if tset.types != nil { + check.softErrorf(pos, _Todo, "interface contains type constraints (%s)", tset.types) return } - if t._IsComparable() { + if tset.IsComparable() { check.softErrorf(pos, _Todo, "interface is (or embeds) comparable") } } diff --git a/src/go/types/unify.go b/src/go/types/unify.go index 7c58c6c512..bc611db347 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -8,7 +8,6 @@ package types import ( "bytes" - "go/token" "sort" ) @@ -361,16 +360,8 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { // the same names and identical function types. Lower-case method names from // different packages are always different. The order of the methods is irrelevant. if y, ok := y.(*Interface); ok { - // If identical0 is called (indirectly) via an external API entry point - // (such as Identical, IdenticalIgnoreTags, etc.), check is nil. But in - // that case, interfaces are expected to be complete and lazy completion - // here is not needed. - if u.check != nil { - u.check.completeInterface(token.NoPos, x) - u.check.completeInterface(token.NoPos, y) - } - a := x.allMethods - b := y.allMethods + a := x.typeSet().methods + b := y.typeSet().methods if len(a) == len(b) { // Interface types are the only types where cycles can occur // that are not "terminated" via named types; and such cycles diff --git a/src/go/types/universe.go b/src/go/types/universe.go index d7feb2c609..7ce401827e 100644 --- a/src/go/types/universe.go +++ b/src/go/types/universe.go @@ -90,7 +90,7 @@ func defPredeclaredTypes() { res := NewVar(token.NoPos, nil, "", Typ[String]) sig := &Signature{results: NewTuple(res)} err := NewFunc(token.NoPos, nil, "Error", sig) - typ := &Named{underlying: NewInterfaceType([]*Func{err}, nil).Complete()} + typ := &Named{underlying: NewInterfaceType([]*Func{err}, nil)} sig.recv = NewVar(token.NoPos, nil, "", typ) def(NewTypeName(token.NoPos, nil, "error", typ)) } @@ -218,7 +218,7 @@ func defPredeclaredComparable() { // set up later to match the usual interface method assumptions. sig := new(Signature) eql := NewFunc(token.NoPos, nil, "==", sig) - iface := NewInterfaceType([]*Func{eql}, nil).Complete() + iface := NewInterfaceType([]*Func{eql}, nil) // set up the defined type for the interface obj := NewTypeName(token.NoPos, nil, "comparable", nil) -- GitLab From fce6290e0ac18ca2d5cc635adf4c3a77b375a49a Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Thu, 15 Jul 2021 23:18:59 -0400 Subject: [PATCH 0457/2500] [dev.typeparams] go/types: remove typeparams wrappers and aliases These wrappers and aliases were necessary when we had different versions of the API depending on the typeparams build constraint, but now they're just boilerplate. Remove them. Notably the documentation for types.Info is restored. Change-Id: I5363d1d5df47649c2641c03328dfba45b1456278 Reviewed-on: https://go-review.googlesource.com/c/go/+/334895 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/api.go | 100 +++++++++++++++++++- src/go/types/api_test.go | 123 +++++++++++++++++++++++++ src/go/types/api_typeparams.go | 48 ---------- src/go/types/api_typeparams_test.go | 136 ---------------------------- src/go/types/check.go | 4 +- src/go/types/decl.go | 2 +- src/go/types/index.go | 4 +- src/go/types/infer.go | 6 +- src/go/types/lookup.go | 4 +- src/go/types/methodset.go | 4 +- src/go/types/predicates.go | 8 +- src/go/types/sanitize.go | 4 +- src/go/types/signature.go | 4 +- src/go/types/sizeof_test.go | 2 +- src/go/types/subst.go | 16 ++-- src/go/types/type.go | 87 +++++++++--------- src/go/types/typestring.go | 6 +- src/go/types/unify.go | 6 +- 18 files changed, 302 insertions(+), 262 deletions(-) delete mode 100644 src/go/types/api_typeparams.go delete mode 100644 src/go/types/api_typeparams_test.go diff --git a/src/go/types/api.go b/src/go/types/api.go index 2bfbb8ce0c..2815a6d027 100644 --- a/src/go/types/api.go +++ b/src/go/types/api.go @@ -162,6 +162,102 @@ func srcimporter_setUsesCgo(conf *Config) { conf.go115UsesCgo = true } +// Info holds result type information for a type-checked package. +// Only the information for which a map is provided is collected. +// If the package has type errors, the collected information may +// be incomplete. +type Info struct { + // Types maps expressions to their types, and for constant + // expressions, also their values. Invalid expressions are + // omitted. + // + // For (possibly parenthesized) identifiers denoting built-in + // functions, the recorded signatures are call-site specific: + // if the call result is not a constant, the recorded type is + // an argument-specific signature. Otherwise, the recorded type + // is invalid. + // + // The Types map does not record the type of every identifier, + // only those that appear where an arbitrary expression is + // permitted. For instance, the identifier f in a selector + // expression x.f is found only in the Selections map, the + // identifier z in a variable declaration 'var z int' is found + // only in the Defs map, and identifiers denoting packages in + // qualified identifiers are collected in the Uses map. + Types map[ast.Expr]TypeAndValue + + // Inferred maps calls of parameterized functions that use + // type inference to the inferred type arguments and signature + // of the function called. The recorded "call" expression may be + // an *ast.CallExpr (as in f(x)), or an *ast.IndexExpr (s in f[T]). + Inferred map[ast.Expr]Inferred + + // Defs maps identifiers to the objects they define (including + // package names, dots "." of dot-imports, and blank "_" identifiers). + // For identifiers that do not denote objects (e.g., the package name + // in package clauses, or symbolic variables t in t := x.(type) of + // type switch headers), the corresponding objects are nil. + // + // For an embedded field, Defs returns the field *Var it defines. + // + // Invariant: Defs[id] == nil || Defs[id].Pos() == id.Pos() + Defs map[*ast.Ident]Object + + // Uses maps identifiers to the objects they denote. + // + // For an embedded field, Uses returns the *TypeName it denotes. + // + // Invariant: Uses[id].Pos() != id.Pos() + Uses map[*ast.Ident]Object + + // Implicits maps nodes to their implicitly declared objects, if any. + // The following node and object types may appear: + // + // node declared object + // + // *ast.ImportSpec *PkgName for imports without renames + // *ast.CaseClause type-specific *Var for each type switch case clause (incl. default) + // *ast.Field anonymous parameter *Var (incl. unnamed results) + // + Implicits map[ast.Node]Object + + // Selections maps selector expressions (excluding qualified identifiers) + // to their corresponding selections. + Selections map[*ast.SelectorExpr]*Selection + + // Scopes maps ast.Nodes to the scopes they define. Package scopes are not + // associated with a specific node but with all files belonging to a package. + // Thus, the package scope can be found in the type-checked Package object. + // Scopes nest, with the Universe scope being the outermost scope, enclosing + // the package scope, which contains (one or more) files scopes, which enclose + // function scopes which in turn enclose statement and function literal scopes. + // Note that even though package-level functions are declared in the package + // scope, the function scopes are embedded in the file scope of the file + // containing the function declaration. + // + // The following node types may appear in Scopes: + // + // *ast.File + // *ast.FuncType + // *ast.BlockStmt + // *ast.IfStmt + // *ast.SwitchStmt + // *ast.TypeSwitchStmt + // *ast.CaseClause + // *ast.CommClause + // *ast.ForStmt + // *ast.RangeStmt + // + Scopes map[ast.Node]*Scope + + // InitOrder is the list of package-level initializers in the order in which + // they must be executed. Initializers referring to variables related by an + // initialization dependency appear in topological order, the others appear + // in source order. Variables without an initialization expression do not + // appear in this list. + InitOrder []*Initializer +} + // The Info struct is found in api_notypeparams.go and api_typeparams.go. // TypeOf returns the type of expression e, or nil if not found. @@ -254,9 +350,9 @@ func (tv TypeAndValue) HasOk() bool { return tv.mode == commaok || tv.mode == mapindex } -// _Inferred reports the _Inferred type arguments and signature +// Inferred reports the Inferred type arguments and signature // for a parameterized function call that uses type inference. -type _Inferred struct { +type Inferred struct { TArgs []Type Sig *Signature } diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index 6a7218d90f..ef248781cc 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -389,6 +389,129 @@ func TestTypesInfo(t *testing.T) { } } +func TestInferredInfo(t *testing.T) { + var tests = []struct { + src string + fun string + targs []string + sig string + }{ + {genericPkg + `p0; func f[T any](T); func _() { f(42) }`, + `f`, + []string{`int`}, + `func(int)`, + }, + {genericPkg + `p1; func f[T any](T) T; func _() { f('@') }`, + `f`, + []string{`rune`}, + `func(rune) rune`, + }, + {genericPkg + `p2; func f[T any](...T) T; func _() { f(0i) }`, + `f`, + []string{`complex128`}, + `func(...complex128) complex128`, + }, + {genericPkg + `p3; func f[A, B, C any](A, *B, []C); func _() { f(1.2, new(string), []byte{}) }`, + `f`, + []string{`float64`, `string`, `byte`}, + `func(float64, *string, []byte)`, + }, + {genericPkg + `p4; func f[A, B any](A, *B, ...[]B); func _() { f(1.2, new(byte)) }`, + `f`, + []string{`float64`, `byte`}, + `func(float64, *byte, ...[]byte)`, + }, + + {genericPkg + `s1; func f[T any, P interface{~*T}](x T); func _(x string) { f(x) }`, + `f`, + []string{`string`, `*string`}, + `func(x string)`, + }, + {genericPkg + `s2; func f[T any, P interface{~*T}](x []T); func _(x []int) { f(x) }`, + `f`, + []string{`int`, `*int`}, + `func(x []int)`, + }, + {genericPkg + `s3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]](x []T); func _(x []int) { f(x) }`, + `f`, + []string{`int`, `chan<- int`}, + `func(x []int)`, + }, + {genericPkg + `s4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T); func _(x []int) { f(x) }`, + `f`, + []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, + `func(x []int)`, + }, + + {genericPkg + `t1; func f[T any, P interface{~*T}]() T; func _() { _ = f[string] }`, + `f`, + []string{`string`, `*string`}, + `func() string`, + }, + {genericPkg + `t2; type C[T any] interface{~chan<- T}; func f[T any, P C[T]]() []T; func _() { _ = f[int] }`, + `f`, + []string{`int`, `chan<- int`}, + `func() []int`, + }, + {genericPkg + `t3; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T; func _() { _ = f[int] }`, + `f`, + []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, + `func() []int`, + }, + } + + for _, test := range tests { + info := Info{} + info.Inferred = make(map[ast.Expr]Inferred) + name, err := mayTypecheck(t, "InferredInfo", test.src, &info) + if err != nil { + t.Errorf("package %s: %v", name, err) + continue + } + + // look for inferred type arguments and signature + var targs []Type + var sig *Signature + for call, inf := range info.Inferred { + var fun ast.Expr + switch x := call.(type) { + case *ast.CallExpr: + fun = x.Fun + case *ast.IndexExpr: + fun = x.X + default: + panic(fmt.Sprintf("unexpected call expression type %T", call)) + } + if ExprString(fun) == test.fun { + targs = inf.TArgs + sig = inf.Sig + break + } + } + if targs == nil { + t.Errorf("package %s: no inferred information found for %s", name, test.fun) + continue + } + + // check that type arguments are correct + if len(targs) != len(test.targs) { + t.Errorf("package %s: got %d type arguments; want %d", name, len(targs), len(test.targs)) + continue + } + for i, targ := range targs { + if got := targ.String(); got != test.targs[i] { + t.Errorf("package %s, %d. type argument: got %s; want %s", name, i, got, test.targs[i]) + continue + } + } + + // check that signature is correct + if got := sig.String(); got != test.sig { + t.Errorf("package %s: got %s; want %s", name, got, test.sig) + } + } +} + func TestDefsInfo(t *testing.T) { var tests = []struct { src string diff --git a/src/go/types/api_typeparams.go b/src/go/types/api_typeparams.go deleted file mode 100644 index 864103df63..0000000000 --- a/src/go/types/api_typeparams.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package types - -import ( - "go/ast" -) - -type ( - Inferred = _Inferred - TypeParam = _TypeParam -) - -// NewTypeParam returns a new TypeParam. -func NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam { - return (*Checker)(nil).newTypeParam(obj, index, bound) -} - -func (s *Signature) TParams() []*TypeName { return s._TParams() } -func (s *Signature) SetTParams(tparams []*TypeName) { s._SetTParams(tparams) } - -func (t *Named) TParams() []*TypeName { return t._TParams() } -func (t *Named) TArgs() []Type { return t._TArgs() } -func (t *Named) SetTArgs(args []Type) { t._SetTArgs(args) } - -// Info is documented in api_notypeparams.go. -type Info struct { - Types map[ast.Expr]TypeAndValue - - // Inferred maps calls of parameterized functions that use type inference to - // the Inferred type arguments and signature of the function called. The - // recorded "call" expression may be an *ast.CallExpr (as in f(x)), or an - // *ast.IndexExpr (s in f[T]). - Inferred map[ast.Expr]_Inferred - - Defs map[*ast.Ident]Object - Uses map[*ast.Ident]Object - Implicits map[ast.Node]Object - Selections map[*ast.SelectorExpr]*Selection - Scopes map[ast.Node]*Scope - InitOrder []*Initializer -} - -func getInferred(info *Info) map[ast.Expr]_Inferred { - return info.Inferred -} diff --git a/src/go/types/api_typeparams_test.go b/src/go/types/api_typeparams_test.go deleted file mode 100644 index d9117b8412..0000000000 --- a/src/go/types/api_typeparams_test.go +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package types_test - -import ( - "fmt" - "go/ast" - "testing" - - . "go/types" -) - -func TestInferredInfo(t *testing.T) { - var tests = []struct { - src string - fun string - targs []string - sig string - }{ - {genericPkg + `p0; func f[T any](T); func _() { f(42) }`, - `f`, - []string{`int`}, - `func(int)`, - }, - {genericPkg + `p1; func f[T any](T) T; func _() { f('@') }`, - `f`, - []string{`rune`}, - `func(rune) rune`, - }, - {genericPkg + `p2; func f[T any](...T) T; func _() { f(0i) }`, - `f`, - []string{`complex128`}, - `func(...complex128) complex128`, - }, - {genericPkg + `p3; func f[A, B, C any](A, *B, []C); func _() { f(1.2, new(string), []byte{}) }`, - `f`, - []string{`float64`, `string`, `byte`}, - `func(float64, *string, []byte)`, - }, - {genericPkg + `p4; func f[A, B any](A, *B, ...[]B); func _() { f(1.2, new(byte)) }`, - `f`, - []string{`float64`, `byte`}, - `func(float64, *byte, ...[]byte)`, - }, - - {genericPkg + `s1; func f[T any, P interface{~*T}](x T); func _(x string) { f(x) }`, - `f`, - []string{`string`, `*string`}, - `func(x string)`, - }, - {genericPkg + `s2; func f[T any, P interface{~*T}](x []T); func _(x []int) { f(x) }`, - `f`, - []string{`int`, `*int`}, - `func(x []int)`, - }, - {genericPkg + `s3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]](x []T); func _(x []int) { f(x) }`, - `f`, - []string{`int`, `chan<- int`}, - `func(x []int)`, - }, - {genericPkg + `s4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T); func _(x []int) { f(x) }`, - `f`, - []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, - `func(x []int)`, - }, - - {genericPkg + `t1; func f[T any, P interface{~*T}]() T; func _() { _ = f[string] }`, - `f`, - []string{`string`, `*string`}, - `func() string`, - }, - {genericPkg + `t2; type C[T any] interface{~chan<- T}; func f[T any, P C[T]]() []T; func _() { _ = f[int] }`, - `f`, - []string{`int`, `chan<- int`}, - `func() []int`, - }, - {genericPkg + `t3; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T; func _() { _ = f[int] }`, - `f`, - []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, - `func() []int`, - }, - } - - for _, test := range tests { - info := Info{} - info.Inferred = make(map[ast.Expr]Inferred) - name, err := mayTypecheck(t, "InferredInfo", test.src, &info) - if err != nil { - t.Errorf("package %s: %v", name, err) - continue - } - - // look for inferred type arguments and signature - var targs []Type - var sig *Signature - for call, inf := range info.Inferred { - var fun ast.Expr - switch x := call.(type) { - case *ast.CallExpr: - fun = x.Fun - case *ast.IndexExpr: - fun = x.X - default: - panic(fmt.Sprintf("unexpected call expression type %T", call)) - } - if ExprString(fun) == test.fun { - targs = inf.TArgs - sig = inf.Sig - break - } - } - if targs == nil { - t.Errorf("package %s: no inferred information found for %s", name, test.fun) - continue - } - - // check that type arguments are correct - if len(targs) != len(test.targs) { - t.Errorf("package %s: got %d type arguments; want %d", name, len(targs), len(test.targs)) - continue - } - for i, targ := range targs { - if got := targ.String(); got != test.targs[i] { - t.Errorf("package %s, %d. type argument: got %s; want %s", name, i, got, test.targs[i]) - continue - } - } - - // check that signature is correct - if got := sig.String(); got != test.sig { - t.Errorf("package %s: got %s; want %s", name, got, test.sig) - } - } -} diff --git a/src/go/types/check.go b/src/go/types/check.go index 3e534de08a..30aa8a9f0c 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -412,8 +412,8 @@ func (check *Checker) recordCommaOkTypes(x ast.Expr, a [2]Type) { func (check *Checker) recordInferred(call ast.Expr, targs []Type, sig *Signature) { assert(call != nil) assert(sig != nil) - if m := getInferred(check.Info); m != nil { - m[call] = _Inferred{targs, sig} + if m := check.Info.Inferred; m != nil { + m[call] = Inferred{targs, sig} } } diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 761418c4fb..ac1b3815d2 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -740,7 +740,7 @@ func (check *Checker) collectTypeParams(list *ast.FieldList) (tparams []*TypeNam setBoundAt := func(at int, bound Type) { assert(IsInterface(bound)) - tparams[at].typ.(*_TypeParam).bound = bound + tparams[at].typ.(*TypeParam).bound = bound } index := 0 diff --git a/src/go/types/index.go b/src/go/types/index.go index 7c7aa382ff..769626dcc2 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -123,7 +123,7 @@ func (check *Checker) indexExpr(x *operand, expr *typeparams.IndexExpr) (isFuncI tkey = t.key e = t.elem nmaps++ - case *_TypeParam: + case *TypeParam: check.errorf(x, 0, "type of %s contains a type parameter - cannot index (implementation restriction)", x) case *instance: panic("unimplemented") @@ -246,7 +246,7 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { valid = true // x.typ doesn't change - case *Union, *_TypeParam: + case *Union, *TypeParam: check.errorf(x, 0, "generic slice expressions not yet implemented") x.mode = invalid return diff --git a/src/go/types/infer.go b/src/go/types/infer.go index ae53f68e48..dda188ef10 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -189,7 +189,7 @@ func (check *Checker) infer(posn positioner, tparams []*TypeName, targs []Type, // only parameter type it can possibly match against is a *TypeParam. // Thus, only consider untyped arguments for generic parameters that // are not of composite types and which don't have a type inferred yet. - if tpar, _ := par.typ.(*_TypeParam); tpar != nil && targs[tpar.index] == nil { + if tpar, _ := par.typ.(*TypeParam); tpar != nil && targs[tpar.index] == nil { arg := args[i] targ := Default(arg.typ) // The default type for an untyped nil is untyped nil. We must not @@ -333,7 +333,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { case *Named: return w.isParameterizedList(t.targs) - case *_TypeParam: + case *TypeParam: // t must be one of w.tparams return t.index < len(w.tparams) && w.tparams[t.index].typ == t @@ -382,7 +382,7 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty // Unify type parameters with their structural constraints, if any. for _, tpar := range tparams { - typ := tpar.typ.(*_TypeParam) + typ := tpar.typ.(*TypeParam) sbound := check.structuralType(typ.bound) if sbound != nil { if !u.unify(typ, sbound) { diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index 4ce4b3217c..cdd2f1bd51 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -107,7 +107,7 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack var next []embeddedType // embedded types found at current depth // look for (pkg, name) in all types at current depth - var tpar *_TypeParam // set if obj receiver is a type parameter + var tpar *TypeParam // set if obj receiver is a type parameter for _, e := range current { typ := e.typ @@ -196,7 +196,7 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack indirect = e.indirect } - case *_TypeParam: + case *TypeParam: if i, m := t.Bound().typeSet().LookupMethod(pkg, name); m != nil { assert(m.typ != nil) index = concat(e.index, i) diff --git a/src/go/types/methodset.go b/src/go/types/methodset.go index 71d634bf36..53c0b71dfd 100644 --- a/src/go/types/methodset.go +++ b/src/go/types/methodset.go @@ -130,7 +130,7 @@ func NewMethodSet(T Type) *MethodSet { // continue with underlying type, but only if it's not a type parameter // TODO(rFindley): should this use named.under()? Can there be a difference? typ = named.underlying - if _, ok := typ.(*_TypeParam); ok { + if _, ok := typ.(*TypeParam); ok { continue } } @@ -159,7 +159,7 @@ func NewMethodSet(T Type) *MethodSet { case *Interface: mset = mset.add(t.typeSet().methods, e.index, true, e.multiples) - case *_TypeParam: + case *TypeParam: mset = mset.add(t.Bound().typeSet().methods, e.index, true, e.multiples) } } diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 7f6eee8120..2524ad0367 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -10,7 +10,7 @@ package types // isNamed may be called with types that are not fully set up. func isNamed(typ Type) bool { switch typ.(type) { - case *Basic, *Named, *_TypeParam, *instance: + case *Basic, *Named, *TypeParam, *instance: return true } return false @@ -128,7 +128,7 @@ func comparable(T Type, seen map[Type]bool) bool { return t.underIs(func(t Type) bool { return comparable(t, seen) }) - case *_TypeParam: + case *TypeParam: return t.Bound().IsComparable() } return false @@ -356,7 +356,7 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { return x.obj == y.obj } - case *_TypeParam: + case *TypeParam: // nothing to do (x and y being equal is caught in the very beginning of this function) // case *instance: @@ -382,7 +382,7 @@ func (check *Checker) identicalTParams(x, y []*TypeName, cmpTags bool, p *ifaceP } for i, x := range x { y := y[i] - if !check.identical0(x.typ.(*_TypeParam).bound, y.typ.(*_TypeParam).bound, cmpTags, p) { + if !check.identical0(x.typ.(*TypeParam).bound, y.typ.(*TypeParam).bound, cmpTags, p) { return false } } diff --git a/src/go/types/sanitize.go b/src/go/types/sanitize.go index df09a6a38f..62b91ef8c3 100644 --- a/src/go/types/sanitize.go +++ b/src/go/types/sanitize.go @@ -24,7 +24,7 @@ func sanitizeInfo(info *Info) { } } - inferred := getInferred(info) + inferred := info.Inferred for e, inf := range inferred { changed := false for i, targ := range inf.TArgs { @@ -147,7 +147,7 @@ func (s sanitizer) typ(typ Type) Type { s.typeList(t.targs) s.funcList(t.methods) - case *_TypeParam: + case *TypeParam: if bound := s.typ(t.bound); bound != t.bound { t.bound = bound } diff --git a/src/go/types/signature.go b/src/go/types/signature.go index 9be2cce752..8048ba6519 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -70,7 +70,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast } smap := makeSubstMap(recvTParams, list) for i, tname := range sig.rparams { - bound := recvTParams[i].typ.(*_TypeParam).bound + bound := recvTParams[i].typ.(*TypeParam).bound // bound is (possibly) parameterized in the context of the // receiver type declaration. Substitute parameters for the // current context. @@ -78,7 +78,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast // (no bound == empty interface) if bound != nil { bound = check.subst(tname.pos, bound, smap) - tname.typ.(*_TypeParam).bound = bound + tname.typ.(*TypeParam).bound = bound } } } diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index 05a171f498..8f5f42b415 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -31,7 +31,7 @@ func TestSizeof(t *testing.T) { {Map{}, 16, 32}, {Chan{}, 12, 24}, {Named{}, 84, 160}, - {_TypeParam{}, 28, 48}, + {TypeParam{}, 28, 48}, {instance{}, 44, 88}, {top{}, 0, 0}, diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 0e2e7f408a..a4852ce86f 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -22,21 +22,21 @@ type substMap struct { // TODO(gri) rewrite that code, get rid of this field, and make this // struct just the map (proj) targs []Type - proj map[*_TypeParam]Type + proj map[*TypeParam]Type } // makeSubstMap creates a new substitution map mapping tpars[i] to targs[i]. // If targs[i] is nil, tpars[i] is not substituted. func makeSubstMap(tpars []*TypeName, targs []Type) *substMap { assert(len(tpars) == len(targs)) - proj := make(map[*_TypeParam]Type, len(tpars)) + proj := make(map[*TypeParam]Type, len(tpars)) for i, tpar := range tpars { // We must expand type arguments otherwise *instance // types end up as components in composite types. // TODO(gri) explain why this causes problems, if it does targ := expand(targs[i]) // possibly nil targs[i] = targ - proj[tpar.typ.(*_TypeParam)] = targ + proj[tpar.typ.(*TypeParam)] = targ } return &substMap{targs, proj} } @@ -49,7 +49,7 @@ func (m *substMap) empty() bool { return len(m.proj) == 0 } -func (m *substMap) lookup(tpar *_TypeParam) Type { +func (m *substMap) lookup(tpar *TypeParam) Type { if t := m.proj[tpar]; t != nil { return t } @@ -128,7 +128,7 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, poslist } // stop checking bounds after the first failure - if !check.satisfies(pos, targs[i], tname.typ.(*_TypeParam), smap) { + if !check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap) { break } } @@ -140,7 +140,7 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, poslist // parameter tpar (after any of its type parameters have been substituted through smap). // A suitable error is reported if the result is false. // TODO(gri) This should be a method of interfaces or type sets. -func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *_TypeParam, smap *substMap) bool { +func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap *substMap) bool { iface := tpar.Bound() if iface.Empty() { return true // no type bound @@ -232,7 +232,7 @@ func (check *Checker) subst(pos token.Pos, typ Type, smap *substMap) Type { switch t := typ.(type) { case *Basic: return typ // nothing to do - case *_TypeParam: + case *TypeParam: return smap.lookup(t) } @@ -415,7 +415,7 @@ func (subst *subster) typ(typ Type) Type { return named - case *_TypeParam: + case *TypeParam: return subst.smap.lookup(t) case *instance: diff --git a/src/go/types/type.go b/src/go/types/type.go index 4dcc511b93..7445fa59ab 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -242,10 +242,10 @@ func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature { func (s *Signature) Recv() *Var { return s.recv } // _TParams returns the type parameters of signature s, or nil. -func (s *Signature) _TParams() []*TypeName { return s.tparams } +func (s *Signature) TParams() []*TypeName { return s.tparams } // _SetTParams sets the type parameters of signature s. -func (s *Signature) _SetTParams(tparams []*TypeName) { s.tparams = tparams } +func (s *Signature) SetTParams(tparams []*TypeName) { s.tparams = tparams } // Params returns the parameters of signature s, or nil. func (s *Signature) Params() *Tuple { return s.params } @@ -546,16 +546,16 @@ func (t *Named) _Orig() *Named { return t.orig } // _TParams returns the type parameters of the named type t, or nil. // The result is non-nil for an (originally) parameterized type even if it is instantiated. -func (t *Named) _TParams() []*TypeName { return t.expand().tparams } +func (t *Named) TParams() []*TypeName { return t.expand().tparams } // _SetTParams sets the type parameters of the named type t. -func (t *Named) _SetTParams(tparams []*TypeName) { t.expand().tparams = tparams } +func (t *Named) SetTParams(tparams []*TypeName) { t.expand().tparams = tparams } // _TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated. -func (t *Named) _TArgs() []Type { return t.targs } +func (t *Named) TArgs() []Type { return t.targs } // SetTArgs sets the type arguments of the named type t. -func (t *Named) _SetTArgs(args []Type) { t.targs = args } +func (t *Named) SetTArgs(args []Type) { t.targs = args } // NumMethods returns the number of explicit methods whose receiver is named type t. func (t *Named) NumMethods() int { return len(t.expand().methods) } @@ -591,8 +591,8 @@ var lastID uint32 // each call, starting with 1. It may be called concurrently. func nextID() uint64 { return uint64(atomic.AddUint32(&lastID, 1)) } -// A _TypeParam represents a type parameter type. -type _TypeParam struct { +// A TypeParam represents a type parameter type. +type TypeParam struct { check *Checker // for lazy type bound completion id uint64 // unique id, for debugging only obj *TypeName // corresponding type name @@ -600,7 +600,12 @@ type _TypeParam struct { bound Type // *Named or *Interface; underlying type is always *Interface } -func (check *Checker) newTypeParam(obj *TypeName, index int, bound Type) *_TypeParam { +// NewTypeParam returns a new TypeParam. +func NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam { + return (*Checker)(nil).newTypeParam(obj, index, bound) +} + +func (check *Checker) newTypeParam(obj *TypeName, index int, bound Type) *TypeParam { assert(bound != nil) // Always increment lastID, even if it is not used. @@ -610,14 +615,14 @@ func (check *Checker) newTypeParam(obj *TypeName, index int, bound Type) *_TypeP id = check.nextID } - typ := &_TypeParam{check: check, id: id, obj: obj, index: index, bound: bound} + typ := &TypeParam{check: check, id: id, obj: obj, index: index, bound: bound} if obj.typ == nil { obj.typ = typ } return typ } -func (t *_TypeParam) Bound() *Interface { +func (t *TypeParam) Bound() *Interface { iface := asInterface(t.bound) // use the type bound position if we have one pos := token.NoPos @@ -717,36 +722,36 @@ type top struct{} var theTop = &top{} // Type-specific implementations of Underlying. -func (t *Basic) Underlying() Type { return t } -func (t *Array) Underlying() Type { return t } -func (t *Slice) Underlying() Type { return t } -func (t *Struct) Underlying() Type { return t } -func (t *Pointer) Underlying() Type { return t } -func (t *Tuple) Underlying() Type { return t } -func (t *Signature) Underlying() Type { return t } -func (t *Interface) Underlying() Type { return t } -func (t *Map) Underlying() Type { return t } -func (t *Chan) Underlying() Type { return t } -func (t *Named) Underlying() Type { return t.expand().underlying } -func (t *_TypeParam) Underlying() Type { return t } -func (t *instance) Underlying() Type { return t } -func (t *top) Underlying() Type { return t } +func (t *Basic) Underlying() Type { return t } +func (t *Array) Underlying() Type { return t } +func (t *Slice) Underlying() Type { return t } +func (t *Struct) Underlying() Type { return t } +func (t *Pointer) Underlying() Type { return t } +func (t *Tuple) Underlying() Type { return t } +func (t *Signature) Underlying() Type { return t } +func (t *Interface) Underlying() Type { return t } +func (t *Map) Underlying() Type { return t } +func (t *Chan) Underlying() Type { return t } +func (t *Named) Underlying() Type { return t.expand().underlying } +func (t *TypeParam) Underlying() Type { return t } +func (t *instance) Underlying() Type { return t } +func (t *top) Underlying() Type { return t } // Type-specific implementations of String. -func (t *Basic) String() string { return TypeString(t, nil) } -func (t *Array) String() string { return TypeString(t, nil) } -func (t *Slice) String() string { return TypeString(t, nil) } -func (t *Struct) String() string { return TypeString(t, nil) } -func (t *Pointer) String() string { return TypeString(t, nil) } -func (t *Tuple) String() string { return TypeString(t, nil) } -func (t *Signature) String() string { return TypeString(t, nil) } -func (t *Interface) String() string { return TypeString(t, nil) } -func (t *Map) String() string { return TypeString(t, nil) } -func (t *Chan) String() string { return TypeString(t, nil) } -func (t *Named) String() string { return TypeString(t, nil) } -func (t *_TypeParam) String() string { return TypeString(t, nil) } -func (t *instance) String() string { return TypeString(t, nil) } -func (t *top) String() string { return TypeString(t, nil) } +func (t *Basic) String() string { return TypeString(t, nil) } +func (t *Array) String() string { return TypeString(t, nil) } +func (t *Slice) String() string { return TypeString(t, nil) } +func (t *Struct) String() string { return TypeString(t, nil) } +func (t *Pointer) String() string { return TypeString(t, nil) } +func (t *Tuple) String() string { return TypeString(t, nil) } +func (t *Signature) String() string { return TypeString(t, nil) } +func (t *Interface) String() string { return TypeString(t, nil) } +func (t *Map) String() string { return TypeString(t, nil) } +func (t *Chan) String() string { return TypeString(t, nil) } +func (t *Named) String() string { return TypeString(t, nil) } +func (t *TypeParam) String() string { return TypeString(t, nil) } +func (t *instance) String() string { return TypeString(t, nil) } +func (t *top) String() string { return TypeString(t, nil) } // under returns the true expanded underlying type. // If it doesn't exist, the result is Typ[Invalid]. @@ -827,7 +832,7 @@ func asNamed(t Type) *Named { return e } -func asTypeParam(t Type) *_TypeParam { - u, _ := under(t).(*_TypeParam) +func asTypeParam(t Type) *TypeParam { + u, _ := under(t).(*TypeParam) return u } diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index fb398de502..d234d86e61 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -281,7 +281,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { writeTParamList(buf, t.TParams(), qf, visited) } - case *_TypeParam: + case *TypeParam: s := "?" if t.obj != nil { s = t.obj.name @@ -321,7 +321,7 @@ func writeTParamList(buf *bytes.Buffer, list []*TypeName, qf Qualifier, visited for i, p := range list { // TODO(rFindley) support 'any' sugar here. var b Type = &emptyInterface - if t, _ := p.typ.(*_TypeParam); t != nil && t.bound != nil { + if t, _ := p.typ.(*TypeParam); t != nil && t.bound != nil { b = t.bound } if i > 0 { @@ -334,7 +334,7 @@ func writeTParamList(buf *bytes.Buffer, list []*TypeName, qf Qualifier, visited } prev = b - if t, _ := p.typ.(*_TypeParam); t != nil { + if t, _ := p.typ.(*TypeParam); t != nil { writeType(buf, t, qf, visited) } else { buf.WriteString(p.name) diff --git a/src/go/types/unify.go b/src/go/types/unify.go index bc611db347..43189d3b69 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -99,7 +99,7 @@ func (d *tparamsList) init(tparams []*TypeName) { } if debug { for i, tpar := range tparams { - assert(i == tpar.typ.(*_TypeParam).index) + assert(i == tpar.typ.(*TypeParam).index) } } d.tparams = tparams @@ -147,7 +147,7 @@ func (u *unifier) join(i, j int) bool { // If typ is a type parameter of d, index returns the type parameter index. // Otherwise, the result is < 0. func (d *tparamsList) index(typ Type) int { - if t, ok := typ.(*_TypeParam); ok { + if t, ok := typ.(*TypeParam); ok { if i := t.index; i < len(d.tparams) && d.tparams[i].typ == t { return i } @@ -439,7 +439,7 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { } } - case *_TypeParam: + case *TypeParam: // Two type parameters (which are not part of the type parameters of the // enclosing type as those are handled in the beginning of this function) // are identical if they originate in the same declaration. -- GitLab From b98b8b9b5be2ccbfc5aaf2a983fe5d439f91bc94 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 09:21:36 -0400 Subject: [PATCH 0458/2500] [dev.typeparams] go/types: remove unused *Checker arguments (cleanup) This is a straightforward port of CL 331512 to go/types. API usage in methodset.go was also updated. Change-Id: I6701265c9d2ae40eb9aa0ea5f00c98ce3516edab Reviewed-on: https://go-review.googlesource.com/c/go/+/335009 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/api.go | 4 ++-- src/go/types/builtins.go | 6 ++--- src/go/types/call.go | 4 ++-- src/go/types/conversions.go | 6 ++--- src/go/types/expr.go | 6 ++--- src/go/types/infer.go | 4 ++-- src/go/types/interface.go | 2 +- src/go/types/lookup.go | 45 +++++++++++++++---------------------- src/go/types/methodset.go | 7 +----- src/go/types/operand.go | 8 +++---- src/go/types/predicates.go | 40 ++++++++++++--------------------- src/go/types/stmt.go | 4 ++-- src/go/types/unify.go | 9 ++++---- 13 files changed, 59 insertions(+), 86 deletions(-) diff --git a/src/go/types/api.go b/src/go/types/api.go index 2815a6d027..6c0ceb7b7c 100644 --- a/src/go/types/api.go +++ b/src/go/types/api.go @@ -422,11 +422,11 @@ func Implements(V Type, T *Interface) bool { // Identical reports whether x and y are identical types. // Receivers of Signature types are ignored. func Identical(x, y Type) bool { - return (*Checker)(nil).identical(x, y) + return identical(x, y, true, nil) } // IdenticalIgnoreTags reports whether x and y are identical types if tags are ignored. // Receivers of Signature types are ignored. func IdenticalIgnoreTags(x, y Type) bool { - return (*Checker)(nil).identicalIgnoreTags(x, y) + return identical(x, y, false, nil) } diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 5670790856..e976e76cf1 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -286,7 +286,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b } // both argument types must be identical - if !check.identical(x.typ, y.typ) { + if !Identical(x.typ, y.typ) { check.invalidArg(x, _InvalidComplex, "mismatched types %s and %s", x.typ, y.typ) return } @@ -351,7 +351,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b return } - if !check.identical(dst, src) { + if !Identical(dst, src) { check.invalidArg(x, _InvalidCopy, "arguments to copy %s and %s have different element types %s and %s", x, &y, dst, src) return } @@ -644,7 +644,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b base := derefStructPtr(x.typ) sel := selx.Sel.Name - obj, index, indirect := check.lookupFieldOrMethod(base, false, check.pkg, sel) + obj, index, indirect := LookupFieldOrMethod(base, false, check.pkg, sel) switch obj.(type) { case nil: check.invalidArg(x, _MissingFieldOrMethod, "%s has no single field %s", base, sel) diff --git a/src/go/types/call.go b/src/go/types/call.go index cef5e9fc59..4e5b98a12e 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -470,7 +470,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { check.instantiatedOperand(x) - obj, index, indirect = check.lookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel) + obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel) if obj == nil { switch { case index != nil: @@ -500,7 +500,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { } else { changeCase = string(unicode.ToUpper(r)) + sel[1:] } - if obj, _, _ = check.lookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, changeCase); obj != nil { + if obj, _, _ = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, changeCase); obj != nil { why += ", but does have " + changeCase } } diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go index ad6d3eef10..a1fcdd4fd8 100644 --- a/src/go/types/conversions.go +++ b/src/go/types/conversions.go @@ -94,7 +94,7 @@ func (x *operand) convertibleTo(check *Checker, T Type, reason *string) bool { V := x.typ Vu := under(V) Tu := under(T) - if check.identicalIgnoreTags(Vu, Tu) { + if IdenticalIgnoreTags(Vu, Tu) { return true } @@ -102,7 +102,7 @@ func (x *operand) convertibleTo(check *Checker, T Type, reason *string) bool { // have identical underlying types if tags are ignored" if V, ok := V.(*Pointer); ok { if T, ok := T.(*Pointer); ok { - if check.identicalIgnoreTags(under(V.base), under(T.base)) { + if IdenticalIgnoreTags(under(V.base), under(T.base)) { return true } } @@ -143,7 +143,7 @@ func (x *operand) convertibleTo(check *Checker, T Type, reason *string) bool { if s := asSlice(V); s != nil { if p := asPointer(T); p != nil { if a := asArray(p.Elem()); a != nil { - if check.identical(s.Elem(), a.Elem()) { + if Identical(s.Elem(), a.Elem()) { if check == nil || check.allowVersion(check.pkg, 1, 17) { return true } diff --git a/src/go/types/expr.go b/src/go/types/expr.go index c8adea45e2..edd7caf1c9 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -955,7 +955,7 @@ func (check *Checker) binary(x *operand, e ast.Expr, lhs, rhs ast.Expr, op token return } - if !check.identical(x.typ, y.typ) { + if !Identical(x.typ, y.typ) { // only report an error if we have valid types // (otherwise we had an error reported elsewhere already) if x.typ != Typ[Invalid] && y.typ != Typ[Invalid] { @@ -1281,7 +1281,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { xkey := keyVal(x.val) if asInterface(utyp.key) != nil { for _, vtyp := range visited[xkey] { - if check.identical(vtyp, x.typ) { + if Identical(vtyp, x.typ) { duplicate = true break } @@ -1468,7 +1468,7 @@ func (check *Checker) typeAssertion(at positioner, x *operand, xtyp *Interface, } var msg string if wrongType != nil { - if check.identical(method.typ, wrongType.typ) { + if Identical(method.typ, wrongType.typ) { msg = fmt.Sprintf("missing method %s (%s has pointer receiver)", method.name, method.name) } else { msg = fmt.Sprintf("wrong type for method %s (have %s, want %s)", method.name, wrongType.typ, method.typ) diff --git a/src/go/types/infer.go b/src/go/types/infer.go index dda188ef10..9faf7b7520 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -93,7 +93,7 @@ func (check *Checker) infer(posn positioner, tparams []*TypeName, targs []Type, // Unify parameter and argument types for generic parameters with typed arguments // and collect the indices of generic parameters with untyped arguments. // Terminology: generic parameter = function parameter with a type-parameterized type - u := newUnifier(check, false) + u := newUnifier(false) u.x.init(tparams) // Set the type arguments which we know already. @@ -369,7 +369,7 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty // Setup bidirectional unification between those structural bounds // and the corresponding type arguments (which may be nil!). - u := newUnifier(check, false) + u := newUnifier(false) u.x.init(tparams) u.y = u.x // type parameters between LHS and RHS of unification are identical diff --git a/src/go/types/interface.go b/src/go/types/interface.go index 3a4da569ab..73fde3421a 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -212,7 +212,7 @@ func newTypeSet(check *Checker, pos token.Pos, ityp *Interface) *TypeSet { } // check != nil check.later(func() { - if !check.allowVersion(m.pkg, 1, 14) || !check.identical(m.typ, other.Type()) { + if !check.allowVersion(m.pkg, 1, 14) || !Identical(m.typ, other.Type()) { check.errorf(atPos(pos), _DuplicateDecl, "duplicate method %s", m.name) check.errorf(atPos(mpos[other.(*Func)]), _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented } diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index cdd2f1bd51..70e3b4281d 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -8,6 +8,11 @@ package types import "go/token" +// Internal use of LookupFieldOrMethod: If the obj result is a method +// associated with a concrete (non-interface) type, the method's signature +// may not be fully set up. Call Checker.objDecl(obj, nil) before accessing +// the method's type. + // LookupFieldOrMethod looks up a field or method with given package and name // in T and returns the corresponding *Var or *Func, an index sequence, and a // bool indicating if there were any pointer indirections on the path to the @@ -35,19 +40,6 @@ import "go/token" // the method's formal receiver base type, nor was the receiver addressable. // func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) { - return (*Checker)(nil).lookupFieldOrMethod(T, addressable, pkg, name) -} - -// Internal use of Checker.lookupFieldOrMethod: If the obj result is a method -// associated with a concrete (non-interface) type, the method's signature -// may not be fully set up. Call Checker.objDecl(obj, nil) before accessing -// the method's type. -// TODO(gri) Now that we provide the *Checker, we can probably remove this -// caveat by calling Checker.objDecl from lookupFieldOrMethod. Investigate. - -// lookupFieldOrMethod is like the external version but completes interfaces -// as necessary. -func (check *Checker) lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) { // Methods cannot be associated to a named pointer type // (spec: "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 @@ -57,7 +49,7 @@ func (check *Checker) lookupFieldOrMethod(T Type, addressable bool, pkg *Package // not have found it for T (see also issue 8590). if t := asNamed(T); t != nil { if p, _ := t.Underlying().(*Pointer); p != nil { - obj, index, indirect = check.rawLookupFieldOrMethod(p, false, pkg, name) + obj, index, indirect = lookupFieldOrMethod(p, false, pkg, name) if _, ok := obj.(*Func); ok { return nil, nil, false } @@ -65,7 +57,7 @@ func (check *Checker) lookupFieldOrMethod(T Type, addressable bool, pkg *Package } } - return check.rawLookupFieldOrMethod(T, addressable, pkg, name) + return lookupFieldOrMethod(T, addressable, pkg, name) } // TODO(gri) The named type consolidation and seen maps below must be @@ -73,10 +65,9 @@ func (check *Checker) lookupFieldOrMethod(T Type, addressable bool, pkg *Package // types always have only one representation (even when imported // indirectly via different packages.) -// rawLookupFieldOrMethod should only be called by lookupFieldOrMethod and missingMethod. -func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) { +// lookupFieldOrMethod should only be called by LookupFieldOrMethod and missingMethod. +func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) { // WARNING: The code in this function is extremely subtle - do not modify casually! - // This function and NewMethodSet should be kept in sync. if name == "_" { return // blank fields/methods are never found @@ -226,7 +217,7 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack return } - current = check.consolidateMultiples(next) + current = consolidateMultiples(next) } return nil, nil, false // not found @@ -243,7 +234,7 @@ type embeddedType struct { // consolidateMultiples collects multiple list entries with the same type // into a single entry marked as containing multiples. The result is the // consolidated list. -func (check *Checker) consolidateMultiples(list []embeddedType) []embeddedType { +func consolidateMultiples(list []embeddedType) []embeddedType { if len(list) <= 1 { return list // at most one entry - nothing to do } @@ -251,7 +242,7 @@ func (check *Checker) consolidateMultiples(list []embeddedType) []embeddedType { n := 0 // number of entries w/ unique type prev := make(map[Type]int) // index at which type was previously seen for _, e := range list { - if i, found := check.lookupType(prev, e.typ); found { + if i, found := lookupType(prev, e.typ); found { list[i].multiples = true // ignore this entry } else { @@ -263,14 +254,14 @@ func (check *Checker) consolidateMultiples(list []embeddedType) []embeddedType { return list[:n] } -func (check *Checker) lookupType(m map[Type]int, typ Type) (int, bool) { +func lookupType(m map[Type]int, typ Type) (int, bool) { // fast path: maybe the types are equal if i, found := m[typ]; found { return i, true } for t, i := range m { - if check.identical(t, typ) { + if Identical(t, typ) { return i, true } } @@ -336,7 +327,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // to see if they can be made to match. // TODO(gri) is this always correct? what about type bounds? // (Alternative is to rename/subst type parameters and compare.) - u := newUnifier(check, true) + u := newUnifier(true) u.x.init(ftyp.tparams) if !u.unify(ftyp, mtyp) { return m, f @@ -351,12 +342,12 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, Vn := asNamed(Vd) for _, m := range T.typeSet().methods { // TODO(gri) should this be calling lookupFieldOrMethod instead (and why not)? - obj, _, _ := check.rawLookupFieldOrMethod(V, false, m.pkg, m.name) + obj, _, _ := lookupFieldOrMethod(V, false, m.pkg, m.name) // Check if *V implements this method of T. if obj == nil { ptr := NewPointer(V) - obj, _, _ = check.rawLookupFieldOrMethod(ptr, false, m.pkg, m.name) + obj, _, _ = lookupFieldOrMethod(ptr, false, m.pkg, m.name) if obj != nil { return m, obj.(*Func) } @@ -412,7 +403,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // to see if they can be made to match. // TODO(gri) is this always correct? what about type bounds? // (Alternative is to rename/subst type parameters and compare.) - u := newUnifier(check, true) + u := newUnifier(true) u.x.init(ftyp.rparams) if !u.unify(ftyp, mtyp) { return m, f diff --git a/src/go/types/methodset.go b/src/go/types/methodset.go index 53c0b71dfd..491917d6bc 100644 --- a/src/go/types/methodset.go +++ b/src/go/types/methodset.go @@ -190,12 +190,7 @@ func NewMethodSet(T Type) *MethodSet { } } - // It's ok to call consolidateMultiples with a nil *Checker because - // MethodSets are not used internally (outside debug mode). When used - // externally, interfaces are expected to be completed and then we do - // not need a *Checker to complete them when (indirectly) calling - // Checker.identical via consolidateMultiples. - current = (*Checker)(nil).consolidateMultiples(next) + current = consolidateMultiples(next) } if len(base) == 0 { diff --git a/src/go/types/operand.go b/src/go/types/operand.go index 81dc66e800..1d0f5b80b6 100644 --- a/src/go/types/operand.go +++ b/src/go/types/operand.go @@ -240,7 +240,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er } // x's type is identical to T - if check.identical(V, T) { + if Identical(V, T) { return true, 0 } @@ -272,7 +272,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er // x's type V and T have identical underlying types // and at least one of V or T is not a named type - if check.identical(Vu, Tu) && (!isNamed(V) || !isNamed(T)) { + if Identical(Vu, Tu) && (!isNamed(V) || !isNamed(T)) { return true, 0 } @@ -281,7 +281,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er if m, wrongType := check.missingMethod(V, Ti, true); m != nil /* Implements(V, Ti) */ { if reason != nil { if wrongType != nil { - if check.identical(m.typ, wrongType.typ) { + if Identical(m.typ, wrongType.typ) { *reason = fmt.Sprintf("missing method %s (%s has pointer receiver)", m.name, m.name) } else { *reason = fmt.Sprintf("wrong type for method %s (have %s, want %s)", m.Name(), wrongType.typ, m.typ) @@ -300,7 +300,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er // type, x's type V and T have identical element types, // and at least one of V or T is not a named type if Vc, ok := Vu.(*Chan); ok && Vc.dir == SendRecv { - if Tc, ok := Tu.(*Chan); ok && check.identical(Vc.elem, Tc.elem) { + if Tc, ok := Tu.(*Chan); ok && Identical(Vc.elem, Tc.elem) { return !isNamed(V) || !isNamed(T), _InvalidChanAssign } } diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 2524ad0367..c3c168647d 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -147,18 +147,6 @@ func hasNil(typ Type) bool { return false } -// identical reports whether x and y are identical types. -// Receivers of Signature types are ignored. -func (check *Checker) identical(x, y Type) bool { - return check.identical0(x, y, true, nil) -} - -// identicalIgnoreTags reports whether x and y are identical types if tags are ignored. -// Receivers of Signature types are ignored. -func (check *Checker) identicalIgnoreTags(x, y Type) bool { - return check.identical0(x, y, false, nil) -} - // An ifacePair is a node in a stack of interface type pairs compared for identity. type ifacePair struct { x, y *Interface @@ -170,7 +158,7 @@ func (p *ifacePair) identical(q *ifacePair) bool { } // For changes to this code the corresponding changes should be made to unifier.nify. -func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { +func identical(x, y Type, cmpTags bool, p *ifacePair) bool { // types must be expanded for comparison x = expandf(x) y = expandf(y) @@ -194,13 +182,13 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { if y, ok := y.(*Array); ok { // If one or both array lengths are unknown (< 0) due to some error, // assume they are the same to avoid spurious follow-on errors. - return (x.len < 0 || y.len < 0 || x.len == y.len) && check.identical0(x.elem, y.elem, cmpTags, p) + return (x.len < 0 || y.len < 0 || x.len == y.len) && identical(x.elem, y.elem, cmpTags, p) } case *Slice: // Two slice types are identical if they have identical element types. if y, ok := y.(*Slice); ok { - return check.identical0(x.elem, y.elem, cmpTags, p) + return identical(x.elem, y.elem, cmpTags, p) } case *Struct: @@ -215,7 +203,7 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { if f.embedded != g.embedded || cmpTags && x.Tag(i) != y.Tag(i) || !f.sameId(g.pkg, g.name) || - !check.identical0(f.typ, g.typ, cmpTags, p) { + !identical(f.typ, g.typ, cmpTags, p) { return false } } @@ -226,7 +214,7 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { case *Pointer: // Two pointer types are identical if they have identical base types. if y, ok := y.(*Pointer); ok { - return check.identical0(x.base, y.base, cmpTags, p) + return identical(x.base, y.base, cmpTags, p) } case *Tuple: @@ -237,7 +225,7 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { if x != nil { for i, v := range x.vars { w := y.vars[i] - if !check.identical0(v.typ, w.typ, cmpTags, p) { + if !identical(v.typ, w.typ, cmpTags, p) { return false } } @@ -255,9 +243,9 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { // parameter names. if y, ok := y.(*Signature); ok { return x.variadic == y.variadic && - check.identicalTParams(x.tparams, y.tparams, cmpTags, p) && - check.identical0(x.params, y.params, cmpTags, p) && - check.identical0(x.results, y.results, cmpTags, p) + identicalTParams(x.tparams, y.tparams, cmpTags, p) && + identical(x.params, y.params, cmpTags, p) && + identical(x.results, y.results, cmpTags, p) } case *Union: @@ -325,7 +313,7 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { } for i, f := range a { g := b[i] - if f.Id() != g.Id() || !check.identical0(f.typ, g.typ, cmpTags, q) { + if f.Id() != g.Id() || !identical(f.typ, g.typ, cmpTags, q) { return false } } @@ -336,14 +324,14 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { case *Map: // Two map types are identical if they have identical key and value types. if y, ok := y.(*Map); ok { - return check.identical0(x.key, y.key, cmpTags, p) && check.identical0(x.elem, y.elem, cmpTags, p) + return identical(x.key, y.key, cmpTags, p) && identical(x.elem, y.elem, cmpTags, p) } case *Chan: // Two channel types are identical if they have identical value types // and the same direction. if y, ok := y.(*Chan); ok { - return x.dir == y.dir && check.identical0(x.elem, y.elem, cmpTags, p) + return x.dir == y.dir && identical(x.elem, y.elem, cmpTags, p) } case *Named: @@ -376,13 +364,13 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { return false } -func (check *Checker) identicalTParams(x, y []*TypeName, cmpTags bool, p *ifacePair) bool { +func identicalTParams(x, y []*TypeName, cmpTags bool, p *ifacePair) bool { if len(x) != len(y) { return false } for i, x := range x { y := y[i] - if !check.identical0(x.typ.(*TypeParam).bound, y.typ.(*TypeParam).bound, cmpTags, p) { + if !identical(x.typ.(*TypeParam).bound, y.typ.(*TypeParam).bound, cmpTags, p) { return false } } diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index afef833490..53fccb0a64 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -265,7 +265,7 @@ L: // look for duplicate types for a given value // (quadratic algorithm, but these lists tend to be very short) for _, vt := range seen[val] { - if check.identical(v.typ, vt.typ) { + if Identical(v.typ, vt.typ) { check.errorf(&v, _DuplicateCase, "duplicate case %s in expression switch", &v) check.error(atPos(vt.pos), _DuplicateCase, "\tprevious case") // secondary error, \t indented continue L @@ -289,7 +289,7 @@ L: // look for duplicate types // (quadratic algorithm, but type switches tend to be reasonably small) for t, other := range seen { - if T == nil && t == nil || T != nil && t != nil && check.identical(T, t) { + if T == nil && t == nil || T != nil && t != nil && Identical(T, t) { // talk about "case" rather than "type" because of nil case Ts := "nil" if T != nil { diff --git a/src/go/types/unify.go b/src/go/types/unify.go index 43189d3b69..762000db32 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -8,6 +8,7 @@ package types import ( "bytes" + "fmt" "sort" ) @@ -37,7 +38,6 @@ import ( // and the respective types inferred for each type parameter. // A unifier is created by calling newUnifier. type unifier struct { - check *Checker exact bool x, y tparamsList // x and y must initialized via tparamsList.init types []Type // inferred types, shared by x and y @@ -48,8 +48,8 @@ type unifier struct { // exactly. If exact is not set, a named type's underlying type // is considered if unification would fail otherwise, and the // direction of channels is ignored. -func newUnifier(check *Checker, exact bool) *unifier { - u := &unifier{check: check, exact: exact} +func newUnifier(exact bool) *unifier { + u := &unifier{exact: exact} u.x.unifier = u u.y.unifier = u return u @@ -452,8 +452,7 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { // avoid a crash in case of nil type default: - u.check.dump("### u.nify(%s, %s), u.x.tparams = %s", x, y, u.x.tparams) - unreachable() + panic(fmt.Sprintf("### u.nify(%s, %s), u.x.tparams = %s", x, y, u.x.tparams)) } return false -- GitLab From fe4f13404d553958c5b5889ce8b94144798d07bf Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 09:34:34 -0400 Subject: [PATCH 0459/2500] [dev.typeparams] go/types: move embedding positions from Checker to Interface This is a straightforward port of CL 331514 to go/types, with minor adjustments for the different position API. Change-Id: I714b3f1cd5a0e8d249912bb589d456885a87e167 Reviewed-on: https://go-review.googlesource.com/c/go/+/335030 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/check.go | 12 ++++----- src/go/types/interface.go | 50 ++++++++++++++----------------------- src/go/types/sizeof_test.go | 2 +- src/go/types/subst.go | 1 - src/go/types/type.go | 10 ++++---- 5 files changed, 30 insertions(+), 45 deletions(-) diff --git a/src/go/types/check.go b/src/go/types/check.go index 30aa8a9f0c..4398475501 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -85,12 +85,11 @@ type Checker struct { fset *token.FileSet pkg *Package *Info - version version // accepted language version - nextID uint64 // unique Id for type parameters (first valid Id is 1) - objMap map[Object]*declInfo // maps package-level objects and (non-interface) methods to declaration info - impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package - posMap map[*Interface][]token.Pos // maps interface types to lists of embedded interface positions - typMap map[string]*Named // maps an instantiated named type hash to a *Named type + version version // accepted language version + nextID uint64 // unique Id for type parameters (first valid Id is 1) + objMap map[Object]*declInfo // maps package-level objects and (non-interface) methods to declaration info + impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package + typMap map[string]*Named // maps an instantiated named type hash to a *Named type // pkgPathMap maps package names to the set of distinct import paths we've // seen for that name, anywhere in the import graph. It is used for @@ -193,7 +192,6 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch version: version, objMap: make(map[Object]*declInfo), impMap: make(map[importKey]*Package), - posMap: make(map[*Interface][]token.Pos), typMap: make(map[string]*Named), } } diff --git a/src/go/types/interface.go b/src/go/types/interface.go index 73fde3421a..ccc95dd841 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -16,11 +16,18 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d var tlist []ast.Expr var tname *ast.Ident // "type" name of first entry in a type list declaration + addEmbedded := func(pos token.Pos, typ Type) { + ityp.embeddeds = append(ityp.embeddeds, typ) + if ityp.embedPos == nil { + ityp.embedPos = new([]token.Pos) + } + *ityp.embedPos = append(*ityp.embedPos, pos) + } + for _, f := range iface.Methods.List { if len(f.Names) == 0 { // We have an embedded type; possibly a union of types. - ityp.embeddeds = append(ityp.embeddeds, parseUnion(check, flattenUnion(nil, f.Type))) - check.posMap[ityp] = append(check.posMap[ityp], f.Type.Pos()) + addEmbedded(f.Type.Pos(), parseUnion(check, flattenUnion(nil, f.Type))) continue } @@ -92,10 +99,9 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d // type constraints if tlist != nil { - ityp.embeddeds = append(ityp.embeddeds, parseUnion(check, tlist)) - // Types T in a type list are added as ~T expressions but we don't - // have the position of the '~'. Use the first type position instead. - check.posMap[ityp] = append(check.posMap[ityp], tlist[0].(*ast.UnaryExpr).X.Pos()) + // TODO(rfindley): this differs from types2 due to the use of Pos() below, + // which should actually be on the ~. Confirm that this position is correct. + addEmbedded(tlist[0].Pos(), parseUnion(check, tlist)) } // All methods and embedded elements for this interface are collected; @@ -110,7 +116,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d // sort for API stability sortMethods(ityp.methods) - sortTypes(ityp.embeddeds) + // (don't sort embeddeds: they must correspond to *embedPos entries) // Compute type set with a non-nil *Checker as soon as possible // to report any errors. Subsequent uses of type sets should be @@ -226,14 +232,13 @@ func newTypeSet(check *Checker, pos token.Pos, ityp *Interface) *TypeSet { // collect embedded elements var allTypes Type - var posList []token.Pos - if check != nil { - posList = check.posMap[ityp] - } for i, typ := range ityp.embeddeds { + // The embedding position is nil for imported interfaces + // and also for interface copies after substitution (but + // in that case we don't need to report errors again). var pos token.Pos // embedding position - if posList != nil { - pos = posList[i] + if ityp.embedPos != nil { + pos = (*ityp.embedPos)[i] } var types Type switch t := under(typ).(type) { @@ -268,6 +273,7 @@ func newTypeSet(check *Checker, pos token.Pos, ityp *Interface) *TypeSet { } allTypes = intersect(allTypes, types) } + ityp.embedPos = nil // not needed anymore (errors have been reported) // process todo's (this only happens if check == nil) for i := 0; i < len(todo); i += 2 { @@ -287,24 +293,6 @@ func newTypeSet(check *Checker, pos token.Pos, ityp *Interface) *TypeSet { return ityp.tset } -func sortTypes(list []Type) { - sort.Stable(byUniqueTypeName(list)) -} - -// byUniqueTypeName named type lists can be sorted by their unique type names. -type byUniqueTypeName []Type - -func (a byUniqueTypeName) Len() int { return len(a) } -func (a byUniqueTypeName) Less(i, j int) bool { return sortName(a[i]) < sortName(a[j]) } -func (a byUniqueTypeName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } - -func sortName(t Type) string { - if named := asNamed(t); named != nil { - return named.obj.Id() - } - return "" -} - func sortMethods(list []*Func) { sort.Sort(byUniqueMethodName(list)) } diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index 8f5f42b415..b8f191ee86 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -27,7 +27,7 @@ func TestSizeof(t *testing.T) { {Tuple{}, 12, 24}, {Signature{}, 44, 88}, {Union{}, 24, 48}, - {Interface{}, 40, 80}, + {Interface{}, 44, 88}, {Map{}, 16, 32}, {Chan{}, 12, 24}, {Named{}, 84, 160}, diff --git a/src/go/types/subst.go b/src/go/types/subst.go index a4852ce86f..41ffcd0d1e 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -320,7 +320,6 @@ func (subst *subster) typ(typ Type) Type { if subst.check == nil { panic("internal error: cannot instantiate interfaces yet") } - subst.check.posMap[iface] = subst.check.posMap[t] // satisfy completeInterface requirement return iface } diff --git a/src/go/types/type.go b/src/go/types/type.go index 7445fa59ab..c1b307b642 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -258,10 +258,11 @@ func (s *Signature) Variadic() bool { return s.variadic } // An Interface represents an interface type. type Interface struct { - obj Object // type name object defining this interface; or nil (for better error messages) - methods []*Func // ordered list of explicitly declared methods - embeddeds []Type // ordered list of explicitly embedded elements - complete bool // indicates that obj, methods, and embeddeds are set and type set can be computed + obj Object // type name object defining this interface; or nil (for better error messages) + methods []*Func // ordered list of explicitly declared methods + embeddeds []Type // ordered list of explicitly embedded elements + embedPos *[]token.Pos // positions of embedded elements; or nil (for error messages) - use pointer to save space + complete bool // indicates that obj, methods, and embeddeds are set and type set can be computed tset *TypeSet // type set described by this interface, computed lazily } @@ -326,7 +327,6 @@ func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface { // sort for API stability sortMethods(methods) - sortTypes(embeddeds) typ.methods = methods typ.embeddeds = embeddeds -- GitLab From 79955155e9a68ce47c50f0c77b7f41b10d093dab Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 09:39:05 -0400 Subject: [PATCH 0460/2500] [dev.typeparams] go/types: move newTypeSet function into typeset.go This is a straightforward port of CL 331515 to go/types. Change-Id: I05c687e7dd7a64a8a7815c4483ff7fbb06b37627 Reviewed-on: https://go-review.googlesource.com/c/go/+/335031 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer --- src/go/types/interface.go | 183 ------------------------------ src/go/types/typeset.go | 229 ++++++++++++++++++++++++++++++++++---- 2 files changed, 209 insertions(+), 203 deletions(-) diff --git a/src/go/types/interface.go b/src/go/types/interface.go index ccc95dd841..fd7b55ab2f 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -5,11 +5,9 @@ package types import ( - "fmt" "go/ast" "go/internal/typeparams" "go/token" - "sort" ) func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, def *Named) { @@ -131,184 +129,3 @@ func flattenUnion(list []ast.Expr, x ast.Expr) []ast.Expr { } return append(list, x) } - -// newTypeSet may be called with check == nil. -// TODO(gri) move this function into typeset.go eventually -func newTypeSet(check *Checker, pos token.Pos, ityp *Interface) *TypeSet { - if ityp.tset != nil { - return ityp.tset - } - - // If the interface is not fully set up yet, the type set will - // not be complete, which may lead to errors when using the the - // type set (e.g. missing method). Don't compute a partial type - // set (and don't store it!), so that we still compute the full - // type set eventually. Instead, return the top type set and - // let any follow-on errors play out. - // - // TODO(gri) Consider recording when this happens and reporting - // it as an error (but only if there were no other errors so to - // to not have unnecessary follow-on errors). - if !ityp.complete { - return &topTypeSet - } - - if check != nil && trace { - // Types don't generally have position information. - // If we don't have a valid pos provided, try to use - // one close enough. - if !pos.IsValid() && len(ityp.methods) > 0 { - pos = ityp.methods[0].pos - } - - check.trace(pos, "type set for %s", ityp) - check.indent++ - defer func() { - check.indent-- - check.trace(pos, "=> %s ", ityp.typeSet()) - }() - } - - // An infinitely expanding interface (due to a cycle) is detected - // elsewhere (Checker.validType), so here we simply assume we only - // have valid interfaces. Mark the interface as complete to avoid - // infinite recursion if the validType check occurs later for some - // reason. - ityp.tset = new(TypeSet) // TODO(gri) is this sufficient? - - // Methods of embedded interfaces are collected unchanged; i.e., the identity - // of a method I.m's Func Object of an interface I is the same as that of - // the method m in an interface that embeds interface I. On the other hand, - // if a method is embedded via multiple overlapping embedded interfaces, we - // don't provide a guarantee which "original m" got chosen for the embedding - // interface. See also issue #34421. - // - // If we don't care to provide this identity guarantee anymore, instead of - // reusing the original method in embeddings, we can clone the method's Func - // Object and give it the position of a corresponding embedded interface. Then - // we can get rid of the mpos map below and simply use the cloned method's - // position. - - var todo []*Func - var seen objset - var methods []*Func - mpos := make(map[*Func]token.Pos) // method specification or method embedding position, for good error messages - addMethod := func(pos token.Pos, m *Func, explicit bool) { - switch other := seen.insert(m); { - case other == nil: - methods = append(methods, m) - mpos[m] = pos - case explicit: - if check == nil { - panic(fmt.Sprintf("%v: duplicate method %s", m.pos, m.name)) - } - // check != nil - check.errorf(atPos(pos), _DuplicateDecl, "duplicate method %s", m.name) - check.errorf(atPos(mpos[other.(*Func)]), _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented - default: - // We have a duplicate method name in an embedded (not explicitly declared) method. - // Check method signatures after all types are computed (issue #33656). - // If we're pre-go1.14 (overlapping embeddings are not permitted), report that - // error here as well (even though we could do it eagerly) because it's the same - // error message. - if check == nil { - // check method signatures after all locally embedded interfaces are computed - todo = append(todo, m, other.(*Func)) - break - } - // check != nil - check.later(func() { - if !check.allowVersion(m.pkg, 1, 14) || !Identical(m.typ, other.Type()) { - check.errorf(atPos(pos), _DuplicateDecl, "duplicate method %s", m.name) - check.errorf(atPos(mpos[other.(*Func)]), _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented - } - }) - } - } - - for _, m := range ityp.methods { - addMethod(m.pos, m, true) - } - - // collect embedded elements - var allTypes Type - for i, typ := range ityp.embeddeds { - // The embedding position is nil for imported interfaces - // and also for interface copies after substitution (but - // in that case we don't need to report errors again). - var pos token.Pos // embedding position - if ityp.embedPos != nil { - pos = (*ityp.embedPos)[i] - } - var types Type - switch t := under(typ).(type) { - case *Interface: - tset := newTypeSet(check, pos, t) - for _, m := range tset.methods { - addMethod(pos, m, false) // use embedding position pos rather than m.pos - - } - types = tset.types - case *Union: - // TODO(gri) combine with default case once we have - // converted all tests to new notation and we - // can report an error when we don't have an - // interface before go1.18. - types = typ - case *TypeParam: - if check != nil && !check.allowVersion(check.pkg, 1, 18) { - check.errorf(atPos(pos), _InvalidIfaceEmbed, "%s is a type parameter, not an interface", typ) - continue - } - types = typ - default: - if typ == Typ[Invalid] { - continue - } - if check != nil && !check.allowVersion(check.pkg, 1, 18) { - check.errorf(atPos(pos), _InvalidIfaceEmbed, "%s is not an interface", typ) - continue - } - types = typ - } - allTypes = intersect(allTypes, types) - } - ityp.embedPos = nil // not needed anymore (errors have been reported) - - // process todo's (this only happens if check == nil) - for i := 0; i < len(todo); i += 2 { - m := todo[i] - other := todo[i+1] - if !Identical(m.typ, other.typ) { - panic(fmt.Sprintf("%v: duplicate method %s", m.pos, m.name)) - } - } - - if methods != nil { - sort.Sort(byUniqueMethodName(methods)) - ityp.tset.methods = methods - } - ityp.tset.types = allTypes - - return ityp.tset -} - -func sortMethods(list []*Func) { - sort.Sort(byUniqueMethodName(list)) -} - -func assertSortedMethods(list []*Func) { - if !debug { - panic("internal error: assertSortedMethods called outside debug mode") - } - if !sort.IsSorted(byUniqueMethodName(list)) { - panic("internal error: methods not sorted") - } -} - -// byUniqueMethodName method lists can be sorted by their unique method names. -type byUniqueMethodName []*Func - -func (a byUniqueMethodName) Len() int { return len(a) } -func (a byUniqueMethodName) Less(i, j int) bool { return a[i].Id() < a[j].Id() } -func (a byUniqueMethodName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index 9ba04b97bf..b349d4922c 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -6,10 +6,13 @@ package types import ( "bytes" + "fmt" + "go/token" + "sort" ) -// topTypeSet may be used as type set for the empty interface. -var topTypeSet TypeSet +// ---------------------------------------------------------------------------- +// API // A TypeSet represents the type set of an interface. type TypeSet struct { @@ -18,6 +21,31 @@ type TypeSet struct { types Type // typically a *Union; nil means no type restrictions } +// IsTop reports whether type set s is the top type set (corresponding to the empty interface). +func (s *TypeSet) IsTop() bool { return len(s.methods) == 0 && s.types == nil } + +// IsMethodSet reports whether the type set s is described by a single set of methods. +func (s *TypeSet) IsMethodSet() bool { return s.types == nil && !s.IsComparable() } + +// IsComparable reports whether each type in the set is comparable. +func (s *TypeSet) IsComparable() bool { + _, m := s.LookupMethod(nil, "==") + return m != nil +} + +// NumMethods returns the number of methods available. +func (s *TypeSet) NumMethods() int { return len(s.methods) } + +// Method returns the i'th method of type set s for 0 <= i < s.NumMethods(). +// The methods are ordered by their unique ID. +func (s *TypeSet) Method(i int) *Func { return s.methods[i] } + +// LookupMethod returns the index of and method with matching package and name, or (-1, nil). +func (s *TypeSet) LookupMethod(pkg *Package, name string) (int, *Func) { + // TODO(gri) s.methods is sorted - consider binary search + return lookupMethod(s.methods, pkg, name) +} + func (s *TypeSet) String() string { if s.IsTop() { return "⊤" @@ -44,27 +72,188 @@ func (s *TypeSet) String() string { return buf.String() } -// IsTop reports whether type set s is the top type set (corresponding to the empty interface). -func (s *TypeSet) IsTop() bool { return len(s.methods) == 0 && s.types == nil } +// ---------------------------------------------------------------------------- +// Implementation -// IsMethodSet reports whether the type set s is described by a single set of methods. -func (s *TypeSet) IsMethodSet() bool { return s.types == nil && !s.IsComparable() } +// topTypeSet may be used as type set for the empty interface. +var topTypeSet TypeSet -// IsComparable reports whether each type in the set is comparable. -func (s *TypeSet) IsComparable() bool { - _, m := s.LookupMethod(nil, "==") - return m != nil -} +// newTypeSet may be called with check == nil. +func newTypeSet(check *Checker, pos token.Pos, ityp *Interface) *TypeSet { + if ityp.tset != nil { + return ityp.tset + } -// NumMethods returns the number of methods available. -func (s *TypeSet) NumMethods() int { return len(s.methods) } + // If the interface is not fully set up yet, the type set will + // not be complete, which may lead to errors when using the the + // type set (e.g. missing method). Don't compute a partial type + // set (and don't store it!), so that we still compute the full + // type set eventually. Instead, return the top type set and + // let any follow-on errors play out. + // + // TODO(gri) Consider recording when this happens and reporting + // it as an error (but only if there were no other errors so to + // to not have unnecessary follow-on errors). + if !ityp.complete { + return &topTypeSet + } -// Method returns the i'th method of type set s for 0 <= i < s.NumMethods(). -// The methods are ordered by their unique ID. -func (s *TypeSet) Method(i int) *Func { return s.methods[i] } + if check != nil && trace { + // Types don't generally have position information. + // If we don't have a valid pos provided, try to use + // one close enough. + if !pos.IsValid() && len(ityp.methods) > 0 { + pos = ityp.methods[0].pos + } -// LookupMethod returns the index of and method with matching package and name, or (-1, nil). -func (s *TypeSet) LookupMethod(pkg *Package, name string) (int, *Func) { - // TODO(gri) s.methods is sorted - consider binary search - return lookupMethod(s.methods, pkg, name) + check.trace(pos, "type set for %s", ityp) + check.indent++ + defer func() { + check.indent-- + check.trace(pos, "=> %s ", ityp.typeSet()) + }() + } + + // An infinitely expanding interface (due to a cycle) is detected + // elsewhere (Checker.validType), so here we simply assume we only + // have valid interfaces. Mark the interface as complete to avoid + // infinite recursion if the validType check occurs later for some + // reason. + ityp.tset = new(TypeSet) // TODO(gri) is this sufficient? + + // Methods of embedded interfaces are collected unchanged; i.e., the identity + // of a method I.m's Func Object of an interface I is the same as that of + // the method m in an interface that embeds interface I. On the other hand, + // if a method is embedded via multiple overlapping embedded interfaces, we + // don't provide a guarantee which "original m" got chosen for the embedding + // interface. See also issue #34421. + // + // If we don't care to provide this identity guarantee anymore, instead of + // reusing the original method in embeddings, we can clone the method's Func + // Object and give it the position of a corresponding embedded interface. Then + // we can get rid of the mpos map below and simply use the cloned method's + // position. + + var todo []*Func + var seen objset + var methods []*Func + mpos := make(map[*Func]token.Pos) // method specification or method embedding position, for good error messages + addMethod := func(pos token.Pos, m *Func, explicit bool) { + switch other := seen.insert(m); { + case other == nil: + methods = append(methods, m) + mpos[m] = pos + case explicit: + if check == nil { + panic(fmt.Sprintf("%v: duplicate method %s", m.pos, m.name)) + } + // check != nil + check.errorf(atPos(pos), _DuplicateDecl, "duplicate method %s", m.name) + check.errorf(atPos(mpos[other.(*Func)]), _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented + default: + // We have a duplicate method name in an embedded (not explicitly declared) method. + // Check method signatures after all types are computed (issue #33656). + // If we're pre-go1.14 (overlapping embeddings are not permitted), report that + // error here as well (even though we could do it eagerly) because it's the same + // error message. + if check == nil { + // check method signatures after all locally embedded interfaces are computed + todo = append(todo, m, other.(*Func)) + break + } + // check != nil + check.later(func() { + if !check.allowVersion(m.pkg, 1, 14) || !Identical(m.typ, other.Type()) { + check.errorf(atPos(pos), _DuplicateDecl, "duplicate method %s", m.name) + check.errorf(atPos(mpos[other.(*Func)]), _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented + } + }) + } + } + + for _, m := range ityp.methods { + addMethod(m.pos, m, true) + } + + // collect embedded elements + var allTypes Type + for i, typ := range ityp.embeddeds { + // The embedding position is nil for imported interfaces + // and also for interface copies after substitution (but + // in that case we don't need to report errors again). + var pos token.Pos // embedding position + if ityp.embedPos != nil { + pos = (*ityp.embedPos)[i] + } + var types Type + switch t := under(typ).(type) { + case *Interface: + tset := newTypeSet(check, pos, t) + for _, m := range tset.methods { + addMethod(pos, m, false) // use embedding position pos rather than m.pos + + } + types = tset.types + case *Union: + // TODO(gri) combine with default case once we have + // converted all tests to new notation and we + // can report an error when we don't have an + // interface before go1.18. + types = typ + case *TypeParam: + if check != nil && !check.allowVersion(check.pkg, 1, 18) { + check.errorf(atPos(pos), _InvalidIfaceEmbed, "%s is a type parameter, not an interface", typ) + continue + } + types = typ + default: + if typ == Typ[Invalid] { + continue + } + if check != nil && !check.allowVersion(check.pkg, 1, 18) { + check.errorf(atPos(pos), _InvalidIfaceEmbed, "%s is not an interface", typ) + continue + } + types = typ + } + allTypes = intersect(allTypes, types) + } + ityp.embedPos = nil // not needed anymore (errors have been reported) + + // process todo's (this only happens if check == nil) + for i := 0; i < len(todo); i += 2 { + m := todo[i] + other := todo[i+1] + if !Identical(m.typ, other.typ) { + panic(fmt.Sprintf("%v: duplicate method %s", m.pos, m.name)) + } + } + + if methods != nil { + sort.Sort(byUniqueMethodName(methods)) + ityp.tset.methods = methods + } + ityp.tset.types = allTypes + + return ityp.tset +} + +func sortMethods(list []*Func) { + sort.Sort(byUniqueMethodName(list)) } + +func assertSortedMethods(list []*Func) { + if !debug { + panic("internal error: assertSortedMethods called outside debug mode") + } + if !sort.IsSorted(byUniqueMethodName(list)) { + panic("internal error: methods not sorted") + } +} + +// byUniqueMethodName method lists can be sorted by their unique method names. +type byUniqueMethodName []*Func + +func (a byUniqueMethodName) Len() int { return len(a) } +func (a byUniqueMethodName) Less(i, j int) bool { return a[i].Id() < a[j].Id() } +func (a byUniqueMethodName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -- GitLab From 726ffce659a173951186097b26489570cff24fd3 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 09:44:08 -0400 Subject: [PATCH 0461/2500] [dev.typeparams] go/types: "comparable" must not be visible before Go 1.18 This is a straightforward port of CL 331517 to go/types. Change-Id: Id00761fd5dffb4d09e19f086d18ddc20f11528d0 Reviewed-on: https://go-review.googlesource.com/c/go/+/335032 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- .../types/testdata/fixedbugs/issue46090.go2 | 9 +++ src/go/types/typexpr.go | 2 +- src/go/types/universe.go | 64 +++++++------------ 3 files changed, 32 insertions(+), 43 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue46090.go2 diff --git a/src/go/types/testdata/fixedbugs/issue46090.go2 b/src/go/types/testdata/fixedbugs/issue46090.go2 new file mode 100644 index 0000000000..81b31974c8 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue46090.go2 @@ -0,0 +1,9 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// The predeclared type comparable is not visible before Go 1.18. + +package go1_17 + +type _ comparable // ERROR undeclared diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 070b0ade3e..64a1b37cef 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -27,7 +27,7 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool) // Note that we cannot use check.lookup here because the returned scope // may be different from obj.Parent(). See also Scope.LookupParent doc. scope, obj := check.scope.LookupParent(e.Name, check.pos) - if obj == nil { + if obj == nil || obj == universeComparable && !check.allowVersion(check.pkg, 1, 18) { if e.Name == "_" { check.errorf(e, _InvalidBlank, "cannot use _ as value or type") } else { diff --git a/src/go/types/universe.go b/src/go/types/universe.go index 7ce401827e..540b0ac118 100644 --- a/src/go/types/universe.go +++ b/src/go/types/universe.go @@ -8,7 +8,6 @@ package types import ( "go/constant" - "go/internal/typeparams" "go/token" "strings" ) @@ -22,11 +21,12 @@ var Universe *Scope var Unsafe *Package var ( - universeIota *Const - universeByte *Basic // uint8 alias, but has name "byte" - universeRune *Basic // int32 alias, but has name "rune" - universeAny *Interface - universeError *Named + universeIota *Const + universeByte *Basic // uint8 alias, but has name "byte" + universeRune *Basic // int32 alias, but has name "rune" + universeAny *Interface + universeError *Named + universeComparable Object ) // Typ contains the predeclared *Basic types indexed by their @@ -79,21 +79,30 @@ func defPredeclaredTypes() { def(NewTypeName(token.NoPos, nil, t.name, t)) } - // any - // (Predeclared and entered into universe scope so we do all the - // usual checks; but removed again from scope later since it's - // only visible as constraint in a type parameter list.) + // type any = interface{} + // Entered into universe scope so we do all the usual checks; + // but removed again from scope later since it's only visible + // as constraint in a type parameter list. def(NewTypeName(token.NoPos, nil, "any", &emptyInterface)) - // Error has a nil package in its qualified name since it is in no package + // type error interface{ Error() string } { res := NewVar(token.NoPos, nil, "", Typ[String]) - sig := &Signature{results: NewTuple(res)} + sig := NewSignature(nil, nil, NewTuple(res), false) err := NewFunc(token.NoPos, nil, "Error", sig) typ := &Named{underlying: NewInterfaceType([]*Func{err}, nil)} sig.recv = NewVar(token.NoPos, nil, "", typ) def(NewTypeName(token.NoPos, nil, "error", typ)) } + + // type comparable interface{ ==() } + { + sig := NewSignature(nil, nil, nil, false) + eql := NewFunc(token.NoPos, nil, "==", sig) + typ := &Named{underlying: NewInterfaceType([]*Func{eql}, nil)} + sig.recv = NewVar(token.NoPos, nil, "", typ) + def(NewTypeName(token.NoPos, nil, "comparable", typ)) + } } var predeclaredConsts = [...]struct { @@ -202,33 +211,6 @@ func DefPredeclaredTestFuncs() { def(newBuiltin(_Trace)) } -func defPredeclaredComparable() { - // The "comparable" interface can be imagined as defined like - // - // type comparable interface { - // == () untyped bool - // != () untyped bool - // } - // - // == and != cannot be user-declared but we can declare - // a magic method == and check for its presence when needed. - - // Define interface { == () }. We don't care about the signature - // for == so leave it empty except for the receiver, which is - // set up later to match the usual interface method assumptions. - sig := new(Signature) - eql := NewFunc(token.NoPos, nil, "==", sig) - iface := NewInterfaceType([]*Func{eql}, nil) - - // set up the defined type for the interface - obj := NewTypeName(token.NoPos, nil, "comparable", nil) - named := NewNamed(obj, iface, nil) - obj.color_ = black - sig.recv = NewVar(token.NoPos, nil, "", named) // complete == signature - - def(obj) -} - func init() { Universe = NewScope(nil, token.NoPos, token.NoPos, "universe") Unsafe = NewPackage("unsafe", "unsafe") @@ -238,15 +220,13 @@ func init() { defPredeclaredConsts() defPredeclaredNil() defPredeclaredFuncs() - if typeparams.Enabled { - defPredeclaredComparable() - } universeIota = Universe.Lookup("iota").(*Const) universeByte = Universe.Lookup("byte").(*TypeName).typ.(*Basic) universeRune = Universe.Lookup("rune").(*TypeName).typ.(*Basic) universeAny = Universe.Lookup("any").(*TypeName).typ.(*Interface) universeError = Universe.Lookup("error").(*TypeName).typ.(*Named) + universeComparable = Universe.Lookup("comparable") // "any" is only visible as constraint in a type parameter list delete(Universe.elems, "any") -- GitLab From 5f50a6442e25c406bea7f2a967f2080f89b4e0f6 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 09:51:19 -0400 Subject: [PATCH 0462/2500] [dev.typeparams] go/internal/typeparams: remove the Enabled guard Type parameters are now always enabled. Users should guard against type checking generic code by using the types.Config.GoVersion field. This cleans up some differences with types2. Change-Id: Ie3e35a549e456a90a10d6a7e158ff58653cc1394 Reviewed-on: https://go-review.googlesource.com/c/go/+/335033 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/internal/typeparams/typeparams.go | 2 -- src/go/parser/error_test.go | 6 +----- src/go/parser/parser.go | 2 +- src/go/parser/resolver_test.go | 6 +----- src/go/parser/short_test.go | 6 ------ src/go/printer/printer_test.go | 4 ---- src/go/types/api_test.go | 9 --------- src/go/types/check_test.go | 14 ++------------ src/go/types/methodset_test.go | 7 ++----- src/go/types/typexpr.go | 7 ++----- 10 files changed, 9 insertions(+), 54 deletions(-) diff --git a/src/go/internal/typeparams/typeparams.go b/src/go/internal/typeparams/typeparams.go index e102b77ef8..3191654d4f 100644 --- a/src/go/internal/typeparams/typeparams.go +++ b/src/go/internal/typeparams/typeparams.go @@ -10,8 +10,6 @@ import ( "go/token" ) -const Enabled = true - func PackIndexExpr(x ast.Expr, lbrack token.Pos, exprs []ast.Expr, rbrack token.Pos) ast.Expr { switch len(exprs) { case 0: diff --git a/src/go/parser/error_test.go b/src/go/parser/error_test.go index e22ab12451..f35ba0b501 100644 --- a/src/go/parser/error_test.go +++ b/src/go/parser/error_test.go @@ -189,11 +189,7 @@ func TestErrors(t *testing.T) { t.Run(name, func(t *testing.T) { if !d.IsDir() && !strings.HasPrefix(name, ".") && (strings.HasSuffix(name, ".src") || strings.HasSuffix(name, ".go2")) { mode := DeclarationErrors | AllErrors - if strings.HasSuffix(name, ".go2") { - if !typeparams.Enabled { - return - } - } else { + if !strings.HasSuffix(name, ".go2") { mode |= typeparams.DisallowParsing } checkErrors(t, filepath.Join(testdata, name), nil, mode, true) diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go index d108259171..bdc2ad308c 100644 --- a/src/go/parser/parser.go +++ b/src/go/parser/parser.go @@ -77,7 +77,7 @@ func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode Mod } func (p *parser) parseTypeParams() bool { - return typeparams.Enabled && p.mode&typeparams.DisallowParsing == 0 + return p.mode&typeparams.DisallowParsing == 0 } // ---------------------------------------------------------------------------- diff --git a/src/go/parser/resolver_test.go b/src/go/parser/resolver_test.go index 625c009c91..0c06c592d5 100644 --- a/src/go/parser/resolver_test.go +++ b/src/go/parser/resolver_test.go @@ -41,11 +41,7 @@ func TestResolution(t *testing.T) { path := filepath.Join(dir, fi.Name()) src := readFile(path) // panics on failure var mode Mode - if strings.HasSuffix(path, ".go2") { - if !typeparams.Enabled { - t.Skip("type params are not enabled") - } - } else { + if !strings.HasSuffix(path, ".go2") { mode |= typeparams.DisallowParsing } file, err := ParseFile(fset, path, src, mode) diff --git a/src/go/parser/short_test.go b/src/go/parser/short_test.go index 2467ccb4a7..bfc6f6714b 100644 --- a/src/go/parser/short_test.go +++ b/src/go/parser/short_test.go @@ -133,9 +133,6 @@ func TestValid(t *testing.T) { } }) t.Run("tparams", func(t *testing.T) { - if !typeparams.Enabled { - t.Skip("type params are not enabled") - } for _, src := range valids { checkErrors(t, src, src, DeclarationErrors|AllErrors, false) } @@ -268,9 +265,6 @@ func TestInvalid(t *testing.T) { } }) t.Run("tparams", func(t *testing.T) { - if !typeparams.Enabled { - t.Skip("type params are not enabled") - } for _, src := range invalids { checkErrors(t, src, src, DeclarationErrors|AllErrors, true) } diff --git a/src/go/printer/printer_test.go b/src/go/printer/printer_test.go index 20c97b8c08..ff8be4ae97 100644 --- a/src/go/printer/printer_test.go +++ b/src/go/printer/printer_test.go @@ -10,7 +10,6 @@ import ( "flag" "fmt" "go/ast" - "go/internal/typeparams" "go/parser" "go/token" "io" @@ -222,9 +221,6 @@ var data = []entry{ func TestFiles(t *testing.T) { t.Parallel() for _, e := range data { - if !typeparams.Enabled && e.mode&allowTypeParams != 0 { - continue - } source := filepath.Join(dataDir, e.source) golden := filepath.Join(dataDir, e.golden) mode := e.mode diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index ef248781cc..e6c209dda0 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -353,9 +353,6 @@ func TestTypesInfo(t *testing.T) { } for _, test := range tests { - if strings.HasPrefix(test.src, genericPkg) && !typeparams.Enabled { - continue - } info := Info{Types: make(map[ast.Expr]TypeAndValue)} var name string if strings.HasPrefix(test.src, broken) { @@ -534,9 +531,6 @@ func TestDefsInfo(t *testing.T) { } for _, test := range tests { - if strings.HasPrefix(test.src, genericPkg) && !typeparams.Enabled { - continue - } info := Info{ Defs: make(map[*ast.Ident]Object), } @@ -582,9 +576,6 @@ func TestUsesInfo(t *testing.T) { } for _, test := range tests { - if strings.HasPrefix(test.src, genericPkg) && !typeparams.Enabled { - continue - } info := Info{ Uses: make(map[*ast.Ident]Object), } diff --git a/src/go/types/check_test.go b/src/go/types/check_test.go index f0cfced97f..692004facf 100644 --- a/src/go/types/check_test.go +++ b/src/go/types/check_test.go @@ -207,10 +207,8 @@ func testFiles(t *testing.T, sizes Sizes, filenames []string, srcs [][]byte, man t.Fatal("no source files") } - if strings.HasSuffix(filenames[0], ".go2") && !typeparams.Enabled { - t.Skip("type params are not enabled") - } - if strings.HasSuffix(filenames[0], ".go1") && typeparams.Enabled { + if strings.HasSuffix(filenames[0], ".go1") { + // TODO(rfindley): re-enable this test by using GoVersion. t.Skip("type params are enabled") } @@ -356,14 +354,6 @@ func TestIndexRepresentability(t *testing.T) { testFiles(t, &StdSizes{4, 4}, []string{"index.go"}, [][]byte{[]byte(src)}, false, nil) } -func TestIssue46453(t *testing.T) { - if typeparams.Enabled { - t.Skip("type params are enabled") - } - const src = "package p\ntype _ comparable // ERROR \"undeclared name: comparable\"" - testFiles(t, nil, []string{"issue46453.go"}, [][]byte{[]byte(src)}, false, nil) -} - func TestCheck(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/check", false) } func TestExamples(t *testing.T) { testDirFiles(t, "testdata/examples", false) } func TestFixedbugs(t *testing.T) { testDirFiles(t, "testdata/fixedbugs", false) } diff --git a/src/go/types/methodset_test.go b/src/go/types/methodset_test.go index 4a373fa2c4..566356ad6d 100644 --- a/src/go/types/methodset_test.go +++ b/src/go/types/methodset_test.go @@ -7,7 +7,6 @@ package types_test import ( "testing" - "go/internal/typeparams" . "go/types" ) @@ -101,9 +100,7 @@ func TestNewMethodSet(t *testing.T) { check(src, methods, false) } - if typeparams.Enabled { - for src, methods := range genericTests { - check(src, methods, true) - } + for src, methods := range genericTests { + check(src, methods, true) } } diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 64a1b37cef..ea39473b51 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -263,11 +263,8 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) { case *ast.IndexExpr, *ast.MultiIndexExpr: ix := typeparams.UnpackIndexExpr(e) - if typeparams.Enabled { - return check.instantiatedType(ix, def) - } - check.errorf(e0, _NotAType, "%s is not a type", e0) - check.use(ix.X) + // TODO(rfindley): type instantiation should require go1.18 + return check.instantiatedType(ix, def) case *ast.ParenExpr: // Generic types must be instantiated before they can be used in any form. -- GitLab From 0f4198b5e287a655a6f2f67c9b5bdc758c9eae1e Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 10:27:17 -0400 Subject: [PATCH 0463/2500] [dev.typeparams] go/types: delay interface check for type bounds This is a port of CL 331690 to go/types. It diverges from that CL due to the different representation of Fields in the AST. Change-Id: I3ae9ac3a0172dc58ac748f28772d87b00db0732a Reviewed-on: https://go-review.googlesource.com/c/go/+/335034 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/decl.go | 58 ++++++++----------- .../types/testdata/fixedbugs/issue40789.go2 | 37 ++++++++++++ src/go/types/type.go | 6 +- 3 files changed, 65 insertions(+), 36 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue40789.go2 diff --git a/src/go/types/decl.go b/src/go/types/decl.go index ac1b3815d2..f0e7c5d5ad 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -724,13 +724,8 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { } -func (check *Checker) collectTypeParams(list *ast.FieldList) (tparams []*TypeName) { - // Type parameter lists should not be empty. The parser will - // complain but we still may get an incorrect AST: ignore it. - if list.NumFields() == 0 { - return - } - +func (check *Checker) collectTypeParams(list *ast.FieldList) []*TypeName { + var tparams []*TypeName // Declare type parameters up-front, with empty interface as type bound. // The scope of type parameters starts at the beginning of the type parameter // list (so we can have mutually recursive parameterized interfaces). @@ -738,46 +733,22 @@ func (check *Checker) collectTypeParams(list *ast.FieldList) (tparams []*TypeNam tparams = check.declareTypeParams(tparams, f.Names) } - setBoundAt := func(at int, bound Type) { - assert(IsInterface(bound)) - tparams[at].typ.(*TypeParam).bound = bound - } - index := 0 var bound Type for _, f := range list.List { if f.Type == nil { goto next } - - // The predeclared identifier "any" is visible only as a constraint - // in a type parameter list. Look for it before general constraint - // resolution. - if tident, _ := unparen(f.Type).(*ast.Ident); tident != nil && tident.Name == "any" && check.lookup("any") == nil { - bound = universeAny - } else { - bound = check.typ(f.Type) - } - - // type bound must be an interface - // TODO(gri) We should delay the interface check because - // we may not have a complete interface yet: - // type C(type T C) interface {} - // (issue #39724). - if _, ok := under(bound).(*Interface); ok { - // Otherwise, set the bound for each type parameter. - for i := range f.Names { - setBoundAt(index+i, bound) - } - } else if bound != Typ[Invalid] { - check.errorf(f.Type, _Todo, "%s is not an interface", bound) + bound = check.boundType(f.Type) + for i := range f.Names { + tparams[index+i].typ.(*TypeParam).bound = bound } next: index += len(f.Names) } - return + return tparams } func (check *Checker) declareTypeParams(tparams []*TypeName, names []*ast.Ident) []*TypeName { @@ -795,6 +766,23 @@ func (check *Checker) declareTypeParams(tparams []*TypeName, names []*ast.Ident) return tparams } +// boundType type-checks the type expression e and returns its type, or Typ[Invalid]. +// The type must be an interface, including the predeclared type "any". +func (check *Checker) boundType(e ast.Expr) Type { + // The predeclared identifier "any" is visible only as a type bound in a type parameter list. + if name, _ := unparen(e).(*ast.Ident); name != nil && name.Name == "any" && check.lookup("any") == nil { + return universeAny + } + + bound := check.typ(e) + check.later(func() { + if _, ok := under(bound).(*Interface); !ok && bound != Typ[Invalid] { + check.errorf(e, _Todo, "%s is not an interface", bound) + } + }) + return bound +} + func (check *Checker) collectMethods(obj *TypeName) { // get associated methods // (Checker.collectObjects only collects methods with non-blank names; diff --git a/src/go/types/testdata/fixedbugs/issue40789.go2 b/src/go/types/testdata/fixedbugs/issue40789.go2 new file mode 100644 index 0000000000..9eea4ad60a --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue40789.go2 @@ -0,0 +1,37 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "fmt" + +func main() { + m := map[string]int{ + "a": 6, + "b": 7, + } + fmt.Println(copyMap[map[string]int, string, int](m)) +} + +type Map[K comparable, V any] interface { + map[K] V +} + +func copyMap[M Map[K, V], K comparable, V any](m M) M { + m1 := make(M) + for k, v := range m { + m1[k] = v + } + return m1 +} + +// simpler test case from the same issue + +type A[X comparable] interface { + []X +} + +func f[B A[X], X comparable]() B { + return nil +} diff --git a/src/go/types/type.go b/src/go/types/type.go index c1b307b642..03c1586774 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -623,7 +623,11 @@ func (check *Checker) newTypeParam(obj *TypeName, index int, bound Type) *TypePa } func (t *TypeParam) Bound() *Interface { - iface := asInterface(t.bound) + // we may not have an interface (error reported elsewhere) + iface, _ := under(t.bound).(*Interface) + if iface == nil { + return &emptyInterface + } // use the type bound position if we have one pos := token.NoPos if n, _ := t.bound.(*Named); n != nil { -- GitLab From de209e693a251c772a37e7deb274574d8b8759ce Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 10:33:59 -0400 Subject: [PATCH 0464/2500] [dev.typeparams] go/types: make Interface.obj a *TypeName This is a straightforward port of CL 332011 to go/types. Change-Id: I682791886c8496c52094f3688e36934afbd7a241 Reviewed-on: https://go-review.googlesource.com/c/go/+/335035 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/call.go | 7 +++---- src/go/types/sizeof_test.go | 2 +- src/go/types/type.go | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/go/types/call.go b/src/go/types/call.go index 4e5b98a12e..bcd569e82f 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -482,11 +482,10 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { var why string if tpar := asTypeParam(x.typ); tpar != nil { // Type parameter bounds don't specify fields, so don't mention "field". - switch obj := tpar.Bound().obj.(type) { - case nil: + if tname := tpar.Bound().obj; tname != nil { + why = check.sprintf("interface %s has no method %s", tname.name, sel) + } else { why = check.sprintf("type bound for %s has no method %s", x.typ, sel) - case *TypeName: - why = check.sprintf("interface %s has no method %s", obj.name, sel) } } else { why = check.sprintf("type %s has no field or method %s", x.typ, sel) diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index b8f191ee86..8f5f42b415 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -27,7 +27,7 @@ func TestSizeof(t *testing.T) { {Tuple{}, 12, 24}, {Signature{}, 44, 88}, {Union{}, 24, 48}, - {Interface{}, 44, 88}, + {Interface{}, 40, 80}, {Map{}, 16, 32}, {Chan{}, 12, 24}, {Named{}, 84, 160}, diff --git a/src/go/types/type.go b/src/go/types/type.go index 03c1586774..459ce9e72c 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -258,7 +258,7 @@ func (s *Signature) Variadic() bool { return s.variadic } // An Interface represents an interface type. type Interface struct { - obj Object // type name object defining this interface; or nil (for better error messages) + obj *TypeName // type name object defining this interface; or nil (for better error messages) methods []*Func // ordered list of explicitly declared methods embeddeds []Type // ordered list of explicitly embedded elements embedPos *[]token.Pos // positions of embedded elements; or nil (for error messages) - use pointer to save space -- GitLab From 7c35f5c2fc5975cda9480a8549643f23fbb2ac7d Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 10:36:42 -0400 Subject: [PATCH 0465/2500] [dev.typeparams] go/types: rename newTypeSet -> computeTypeSet This is a port of CL 332089 to go/types. Change-Id: I39321eaee184c8204bd255b7770a0770ecb25fda Reviewed-on: https://go-review.googlesource.com/c/go/+/335036 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/interface.go | 2 +- src/go/types/type.go | 4 ++-- src/go/types/typeset.go | 6 +++--- src/go/types/typexpr.go | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/go/types/interface.go b/src/go/types/interface.go index fd7b55ab2f..367fc79477 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -119,7 +119,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d // Compute type set with a non-nil *Checker as soon as possible // to report any errors. Subsequent uses of type sets should be // using this computed type set and won't need to pass in a *Checker. - check.later(func() { newTypeSet(check, iface.Pos(), ityp) }) + check.later(func() { computeTypeSet(check, iface.Pos(), ityp) }) } func flattenUnion(list []ast.Expr, x ast.Expr) []ast.Expr { diff --git a/src/go/types/type.go b/src/go/types/type.go index 459ce9e72c..ce857d1c80 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -268,7 +268,7 @@ type Interface struct { } // typeSet returns the type set for interface t. -func (t *Interface) typeSet() *TypeSet { return newTypeSet(nil, token.NoPos, t) } +func (t *Interface) typeSet() *TypeSet { return computeTypeSet(nil, token.NoPos, t) } // is reports whether interface t represents types that all satisfy f. func (t *Interface) is(f func(Type, bool) bool) bool { @@ -634,7 +634,7 @@ func (t *TypeParam) Bound() *Interface { pos = n.obj.pos } // TODO(rFindley) switch this to an unexported method on Checker. - newTypeSet(t.check, pos, iface) + computeTypeSet(t.check, pos, iface) return iface } diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index b349d4922c..e979e90e6f 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -78,8 +78,8 @@ func (s *TypeSet) String() string { // topTypeSet may be used as type set for the empty interface. var topTypeSet TypeSet -// newTypeSet may be called with check == nil. -func newTypeSet(check *Checker, pos token.Pos, ityp *Interface) *TypeSet { +// computeTypeSet may be called with check == nil. +func computeTypeSet(check *Checker, pos token.Pos, ityp *Interface) *TypeSet { if ityp.tset != nil { return ityp.tset } @@ -188,7 +188,7 @@ func newTypeSet(check *Checker, pos token.Pos, ityp *Interface) *TypeSet { var types Type switch t := under(typ).(type) { case *Interface: - tset := newTypeSet(check, pos, t) + tset := computeTypeSet(check, pos, t) for _, m := range tset.methods { addMethod(pos, m, false) // use embedding position pos rather than m.pos diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index ea39473b51..342317048b 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -140,7 +140,7 @@ func (check *Checker) ordinaryType(pos positioner, typ Type) { // type-checking. check.later(func() { if t := asInterface(typ); t != nil { - tset := newTypeSet(check, pos.Pos(), t) // TODO(gri) is this the correct position? + tset := computeTypeSet(check, pos.Pos(), t) // TODO(gri) is this the correct position? if tset.types != nil { check.softErrorf(pos, _Todo, "interface contains type constraints (%s)", tset.types) return -- GitLab From b3e7f23a480513039c0aa6edac95a9718b02cab2 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 10:39:55 -0400 Subject: [PATCH 0466/2500] [dev.typeparams] go/types: move Struct type decl into struct.go (cleanup) This is a port of CL 332090 to go/types. Change-Id: Idc480374f5efe0e7f34f76f37ffd02a3aef59c67 Reviewed-on: https://go-review.googlesource.com/c/go/+/335037 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer --- src/go/types/struct.go | 46 ++++++++++++++++++++++++++++++++++++++++++ src/go/types/type.go | 39 ----------------------------------- 2 files changed, 46 insertions(+), 39 deletions(-) diff --git a/src/go/types/struct.go b/src/go/types/struct.go index 1fec9ea527..d1fb813c14 100644 --- a/src/go/types/struct.go +++ b/src/go/types/struct.go @@ -10,6 +10,52 @@ import ( "strconv" ) +// ---------------------------------------------------------------------------- +// API + +// A Struct represents a struct type. +type Struct struct { + fields []*Var + tags []string // field tags; nil if there are no tags +} + +// NewStruct returns a new struct with the given fields and corresponding field tags. +// If a field with index i has a tag, tags[i] must be that tag, but len(tags) may be +// only as long as required to hold the tag with the largest index i. Consequently, +// if no field has a tag, tags may be nil. +func NewStruct(fields []*Var, tags []string) *Struct { + var fset objset + for _, f := range fields { + if f.name != "_" && fset.insert(f) != nil { + panic("multiple fields with the same name") + } + } + if len(tags) > len(fields) { + panic("more tags than fields") + } + return &Struct{fields: fields, tags: tags} +} + +// NumFields returns the number of fields in the struct (including blank and embedded fields). +func (s *Struct) NumFields() int { return len(s.fields) } + +// Field returns the i'th field for 0 <= i < NumFields(). +func (s *Struct) Field(i int) *Var { return s.fields[i] } + +// Tag returns the i'th field tag for 0 <= i < NumFields(). +func (s *Struct) Tag(i int) string { + if i < len(s.tags) { + return s.tags[i] + } + return "" +} + +func (t *Struct) Underlying() Type { return t } +func (t *Struct) String() string { return TypeString(t, nil) } + +// ---------------------------------------------------------------------------- +// Implementation + func (check *Checker) structType(styp *Struct, e *ast.StructType) { list := e.Fields if list == nil { diff --git a/src/go/types/type.go b/src/go/types/type.go index ce857d1c80..6cd6c6b51f 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -124,43 +124,6 @@ func NewSlice(elem Type) *Slice { return &Slice{elem: elem} } // Elem returns the element type of slice s. func (s *Slice) Elem() Type { return s.elem } -// A Struct represents a struct type. -type Struct struct { - fields []*Var - tags []string // field tags; nil if there are no tags -} - -// NewStruct returns a new struct with the given fields and corresponding field tags. -// If a field with index i has a tag, tags[i] must be that tag, but len(tags) may be -// only as long as required to hold the tag with the largest index i. Consequently, -// if no field has a tag, tags may be nil. -func NewStruct(fields []*Var, tags []string) *Struct { - var fset objset - for _, f := range fields { - if f.name != "_" && fset.insert(f) != nil { - panic("multiple fields with the same name") - } - } - if len(tags) > len(fields) { - panic("more tags than fields") - } - return &Struct{fields: fields, tags: tags} -} - -// NumFields returns the number of fields in the struct (including blank and embedded fields). -func (s *Struct) NumFields() int { return len(s.fields) } - -// Field returns the i'th field for 0 <= i < NumFields(). -func (s *Struct) Field(i int) *Var { return s.fields[i] } - -// Tag returns the i'th field tag for 0 <= i < NumFields(). -func (s *Struct) Tag(i int) string { - if i < len(s.tags) { - return s.tags[i] - } - return "" -} - // A Pointer represents a pointer type. type Pointer struct { base Type // element type @@ -729,7 +692,6 @@ var theTop = &top{} func (t *Basic) Underlying() Type { return t } func (t *Array) Underlying() Type { return t } func (t *Slice) Underlying() Type { return t } -func (t *Struct) Underlying() Type { return t } func (t *Pointer) Underlying() Type { return t } func (t *Tuple) Underlying() Type { return t } func (t *Signature) Underlying() Type { return t } @@ -745,7 +707,6 @@ func (t *top) Underlying() Type { return t } func (t *Basic) String() string { return TypeString(t, nil) } func (t *Array) String() string { return TypeString(t, nil) } func (t *Slice) String() string { return TypeString(t, nil) } -func (t *Struct) String() string { return TypeString(t, nil) } func (t *Pointer) String() string { return TypeString(t, nil) } func (t *Tuple) String() string { return TypeString(t, nil) } func (t *Signature) String() string { return TypeString(t, nil) } -- GitLab From e12d43866d3d68441cbbf858bca21ae20b1deeb9 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 10:43:26 -0400 Subject: [PATCH 0467/2500] [dev.typeparams] go/types: move Signature type decl into signature.go (cleanup) This is a port of CL 332091 to go/types. Notably types.Signature is missing APIs for RParams. This is left for a later CL, when the API is finalized. Change-Id: I70b664d656e8c1e32958a75e1d13eab5f3281bf9 Reviewed-on: https://go-review.googlesource.com/c/go/+/335038 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/signature.go | 65 +++++++++++++++++++++++++++++++++++++++ src/go/types/type.go | 58 ---------------------------------- 2 files changed, 65 insertions(+), 58 deletions(-) diff --git a/src/go/types/signature.go b/src/go/types/signature.go index 8048ba6519..665514587e 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -11,6 +11,71 @@ import ( "go/token" ) +// ---------------------------------------------------------------------------- +// API + +// A Signature represents a (non-builtin) function or method type. +// The receiver is ignored when comparing signatures for identity. +type Signature struct { + // We need to keep the scope in Signature (rather than passing it around + // and store it in the Func Object) because when type-checking a function + // literal we call the general type checker which returns a general Type. + // We then unpack the *Signature and use the scope for the literal body. + rparams []*TypeName // receiver type parameters from left to right, or nil + tparams []*TypeName // type parameters from left to right, or nil + scope *Scope // function scope, present for package-local signatures + recv *Var // nil if not a method + params *Tuple // (incoming) parameters from left to right; or nil + results *Tuple // (outgoing) results from left to right; or nil + variadic bool // true if the last parameter's type is of the form ...T (or string, for append built-in only) +} + +// NewSignature returns a new function type for the given receiver, parameters, +// and results, either of which may be nil. If variadic is set, the function +// is variadic, it must have at least one parameter, and the last parameter +// must be of unnamed slice type. +func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature { + if variadic { + n := params.Len() + if n == 0 { + panic("types.NewSignature: variadic function must have at least one parameter") + } + if _, ok := params.At(n - 1).typ.(*Slice); !ok { + panic("types.NewSignature: variadic parameter must be of unnamed slice type") + } + } + return &Signature{recv: recv, params: params, results: results, variadic: variadic} +} + +// Recv returns the receiver of signature s (if a method), or nil if a +// function. It is ignored when comparing signatures for identity. +// +// For an abstract method, Recv returns the enclosing interface either +// as a *Named or an *Interface. Due to embedding, an interface may +// contain methods whose receiver type is a different interface. +func (s *Signature) Recv() *Var { return s.recv } + +// _TParams returns the type parameters of signature s, or nil. +func (s *Signature) TParams() []*TypeName { return s.tparams } + +// _SetTParams sets the type parameters of signature s. +func (s *Signature) SetTParams(tparams []*TypeName) { s.tparams = tparams } + +// Params returns the parameters of signature s, or nil. +func (s *Signature) Params() *Tuple { return s.params } + +// Results returns the results of signature s, or nil. +func (s *Signature) Results() *Tuple { return s.results } + +// Variadic reports whether the signature s is variadic. +func (s *Signature) Variadic() bool { return s.variadic } + +func (t *Signature) Underlying() Type { return t } +func (t *Signature) String() string { return TypeString(t, nil) } + +// ---------------------------------------------------------------------------- +// Implementation + // funcType type-checks a function or method type. func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast.FuncType) { check.openScope(ftyp, "function") diff --git a/src/go/types/type.go b/src/go/types/type.go index 6cd6c6b51f..a4c47d17ea 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -163,62 +163,6 @@ func (t *Tuple) Len() int { // At returns the i'th variable of tuple t. func (t *Tuple) At(i int) *Var { return t.vars[i] } -// A Signature represents a (non-builtin) function or method type. -// The receiver is ignored when comparing signatures for identity. -type Signature struct { - // We need to keep the scope in Signature (rather than passing it around - // and store it in the Func Object) because when type-checking a function - // literal we call the general type checker which returns a general Type. - // We then unpack the *Signature and use the scope for the literal body. - rparams []*TypeName // receiver type parameters from left to right, or nil - tparams []*TypeName // type parameters from left to right, or nil - scope *Scope // function scope, present for package-local signatures - recv *Var // nil if not a method - params *Tuple // (incoming) parameters from left to right; or nil - results *Tuple // (outgoing) results from left to right; or nil - variadic bool // true if the last parameter's type is of the form ...T (or string, for append built-in only) -} - -// NewSignature returns a new function type for the given receiver, parameters, -// and results, either of which may be nil. If variadic is set, the function -// is variadic, it must have at least one parameter, and the last parameter -// must be of unnamed slice type. -func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature { - if variadic { - n := params.Len() - if n == 0 { - panic("types.NewSignature: variadic function must have at least one parameter") - } - if _, ok := params.At(n - 1).typ.(*Slice); !ok { - panic("types.NewSignature: variadic parameter must be of unnamed slice type") - } - } - return &Signature{recv: recv, params: params, results: results, variadic: variadic} -} - -// Recv returns the receiver of signature s (if a method), or nil if a -// function. It is ignored when comparing signatures for identity. -// -// For an abstract method, Recv returns the enclosing interface either -// as a *Named or an *Interface. Due to embedding, an interface may -// contain methods whose receiver type is a different interface. -func (s *Signature) Recv() *Var { return s.recv } - -// _TParams returns the type parameters of signature s, or nil. -func (s *Signature) TParams() []*TypeName { return s.tparams } - -// _SetTParams sets the type parameters of signature s. -func (s *Signature) SetTParams(tparams []*TypeName) { s.tparams = tparams } - -// Params returns the parameters of signature s, or nil. -func (s *Signature) Params() *Tuple { return s.params } - -// Results returns the results of signature s, or nil. -func (s *Signature) Results() *Tuple { return s.results } - -// Variadic reports whether the signature s is variadic. -func (s *Signature) Variadic() bool { return s.variadic } - // An Interface represents an interface type. type Interface struct { obj *TypeName // type name object defining this interface; or nil (for better error messages) @@ -694,7 +638,6 @@ func (t *Array) Underlying() Type { return t } func (t *Slice) Underlying() Type { return t } func (t *Pointer) Underlying() Type { return t } func (t *Tuple) Underlying() Type { return t } -func (t *Signature) Underlying() Type { return t } func (t *Interface) Underlying() Type { return t } func (t *Map) Underlying() Type { return t } func (t *Chan) Underlying() Type { return t } @@ -709,7 +652,6 @@ func (t *Array) String() string { return TypeString(t, nil) } func (t *Slice) String() string { return TypeString(t, nil) } func (t *Pointer) String() string { return TypeString(t, nil) } func (t *Tuple) String() string { return TypeString(t, nil) } -func (t *Signature) String() string { return TypeString(t, nil) } func (t *Interface) String() string { return TypeString(t, nil) } func (t *Map) String() string { return TypeString(t, nil) } func (t *Chan) String() string { return TypeString(t, nil) } -- GitLab From 624d152db711cff77466b2049ae29377a110396a Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 10:45:51 -0400 Subject: [PATCH 0468/2500] [dev.typeparams] go/types: move Interface type decl into interface.go (cleanup) This is a port of CL 332092 to go/types. Change-Id: I9971c49570424368575108832eac0cd978eb3fe6 Reviewed-on: https://go-review.googlesource.com/c/go/+/335039 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/interface.go | 160 ++++++++++++++++++++++++++++++++++++++ src/go/types/type.go | 152 ------------------------------------ 2 files changed, 160 insertions(+), 152 deletions(-) diff --git a/src/go/types/interface.go b/src/go/types/interface.go index 367fc79477..91270cfcd3 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -10,6 +10,166 @@ import ( "go/token" ) +// ---------------------------------------------------------------------------- +// API + +// An Interface represents an interface type. +type Interface struct { + obj *TypeName // type name object defining this interface; or nil (for better error messages) + methods []*Func // ordered list of explicitly declared methods + embeddeds []Type // ordered list of explicitly embedded elements + embedPos *[]token.Pos // positions of embedded elements; or nil (for error messages) - use pointer to save space + complete bool // indicates that obj, methods, and embeddeds are set and type set can be computed + + tset *TypeSet // type set described by this interface, computed lazily +} + +// typeSet returns the type set for interface t. +func (t *Interface) typeSet() *TypeSet { return computeTypeSet(nil, token.NoPos, t) } + +// is reports whether interface t represents types that all satisfy f. +func (t *Interface) is(f func(Type, bool) bool) bool { + switch t := t.typeSet().types.(type) { + case nil, *top: + // TODO(gri) should settle on top or nil to represent this case + return false // we must have at least one type! (was bug) + case *Union: + return t.is(func(typ Type, tilde bool) bool { return f(typ, tilde) }) + default: + return f(t, false) + } +} + +// emptyInterface represents the empty (completed) interface +var emptyInterface = Interface{complete: true, tset: &topTypeSet} + +// NewInterface returns a new interface for the given methods and embedded types. +// NewInterface takes ownership of the provided methods and may modify their types +// by setting missing receivers. +// +// Deprecated: Use NewInterfaceType instead which allows arbitrary embedded types. +func NewInterface(methods []*Func, embeddeds []*Named) *Interface { + tnames := make([]Type, len(embeddeds)) + for i, t := range embeddeds { + tnames[i] = t + } + return NewInterfaceType(methods, tnames) +} + +// NewInterfaceType returns a new interface for the given methods and embedded types. +// NewInterfaceType takes ownership of the provided methods and may modify their types +// by setting missing receivers. +func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface { + if len(methods) == 0 && len(embeddeds) == 0 { + return &emptyInterface + } + + // set method receivers if necessary + typ := new(Interface) + for _, m := range methods { + if sig := m.typ.(*Signature); sig.recv == nil { + sig.recv = NewVar(m.pos, m.pkg, "", typ) + } + } + + // TODO(rfindley): this guard is not present in types2. Remove it? + // All embedded types should be interfaces; however, defined types + // may not yet be fully resolved. Only verify that non-defined types + // are interfaces. This matches the behavior of the code before the + // fix for #25301 (issue #25596). + for _, t := range embeddeds { + if _, ok := t.(*Named); !ok && !IsInterface(t) { + panic("embedded type is not an interface") + } + } + + // sort for API stability + sortMethods(methods) + + typ.methods = methods + typ.embeddeds = embeddeds + typ.complete = true + + return typ +} + +// NumExplicitMethods returns the number of explicitly declared methods of interface t. +func (t *Interface) NumExplicitMethods() int { return len(t.methods) } + +// ExplicitMethod returns the i'th explicitly declared method of interface t for 0 <= i < t.NumExplicitMethods(). +// The methods are ordered by their unique Id. +func (t *Interface) ExplicitMethod(i int) *Func { return t.methods[i] } + +// NumEmbeddeds returns the number of embedded types in interface t. +func (t *Interface) NumEmbeddeds() int { return len(t.embeddeds) } + +// Embedded returns the i'th embedded defined (*Named) type of interface t for 0 <= i < t.NumEmbeddeds(). +// The result is nil if the i'th embedded type is not a defined type. +// +// Deprecated: Use EmbeddedType which is not restricted to defined (*Named) types. +func (t *Interface) Embedded(i int) *Named { tname, _ := t.embeddeds[i].(*Named); return tname } + +// EmbeddedType returns the i'th embedded type of interface t for 0 <= i < t.NumEmbeddeds(). +func (t *Interface) EmbeddedType(i int) Type { return t.embeddeds[i] } + +// NumMethods returns the total number of methods of interface t. +func (t *Interface) NumMethods() int { return t.typeSet().NumMethods() } + +// Method returns the i'th method of interface t for 0 <= i < t.NumMethods(). +// The methods are ordered by their unique Id. +func (t *Interface) Method(i int) *Func { return t.typeSet().Method(i) } + +// Empty reports whether t is the empty interface. +func (t *Interface) Empty() bool { return t.typeSet().IsTop() } + +// IsComparable reports whether interface t is or embeds the predeclared interface "comparable". +func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() } + +// IsConstraint reports whether interface t is not just a method set. +func (t *Interface) IsConstraint() bool { return !t.typeSet().IsMethodSet() } + +// isSatisfiedBy reports whether interface t's type list is satisfied by the type typ. +// If the type list is empty (absent), typ trivially satisfies the interface. +// TODO(gri) This is not a great name. Eventually, we should have a more comprehensive +// "implements" predicate. +func (t *Interface) isSatisfiedBy(typ Type) bool { + t.Complete() + switch t := t.typeSet().types.(type) { + case nil: + return true // no type restrictions + case *Union: + r, _ := t.intersect(typ, false) + return r != nil + default: + return Identical(t, typ) + } +} + +// Complete computes the interface's type set. It must be called by users of +// NewInterfaceType and NewInterface after the interface's embedded types are +// fully defined and before using the interface type in any way other than to +// form other types. The interface must not contain duplicate methods or a +// panic occurs. Complete returns the receiver. +// +// Deprecated: Type sets are now computed lazily, on demand; this function +// is only here for backward-compatibility. It does not have to +// be called explicitly anymore. +func (t *Interface) Complete() *Interface { + // Some tests are still depending on the state change + // (string representation of an Interface not containing an + // /* incomplete */ marker) caused by the explicit Complete + // call, so we compute the type set eagerly here. + t.complete = true + t.typeSet() + return t +} + +func (t *Interface) Underlying() Type { return t } +func (t *Interface) String() string { return TypeString(t, nil) } + +// ---------------------------------------------------------------------------- +// Implementation + func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, def *Named) { var tlist []ast.Expr var tname *ast.Ident // "type" name of first entry in a type list declaration diff --git a/src/go/types/type.go b/src/go/types/type.go index a4c47d17ea..2adc2fa3ca 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -163,156 +163,6 @@ func (t *Tuple) Len() int { // At returns the i'th variable of tuple t. func (t *Tuple) At(i int) *Var { return t.vars[i] } -// An Interface represents an interface type. -type Interface struct { - obj *TypeName // type name object defining this interface; or nil (for better error messages) - methods []*Func // ordered list of explicitly declared methods - embeddeds []Type // ordered list of explicitly embedded elements - embedPos *[]token.Pos // positions of embedded elements; or nil (for error messages) - use pointer to save space - complete bool // indicates that obj, methods, and embeddeds are set and type set can be computed - - tset *TypeSet // type set described by this interface, computed lazily -} - -// typeSet returns the type set for interface t. -func (t *Interface) typeSet() *TypeSet { return computeTypeSet(nil, token.NoPos, t) } - -// is reports whether interface t represents types that all satisfy f. -func (t *Interface) is(f func(Type, bool) bool) bool { - switch t := t.typeSet().types.(type) { - case nil, *top: - // TODO(gri) should settle on top or nil to represent this case - return false // we must have at least one type! (was bug) - case *Union: - return t.is(func(typ Type, tilde bool) bool { return f(typ, tilde) }) - default: - return f(t, false) - } -} - -// emptyInterface represents the empty (completed) interface -var emptyInterface = Interface{complete: true, tset: &topTypeSet} - -// NewInterface returns a new interface for the given methods and embedded types. -// NewInterface takes ownership of the provided methods and may modify their types -// by setting missing receivers. -// -// Deprecated: Use NewInterfaceType instead which allows arbitrary embedded types. -func NewInterface(methods []*Func, embeddeds []*Named) *Interface { - tnames := make([]Type, len(embeddeds)) - for i, t := range embeddeds { - tnames[i] = t - } - return NewInterfaceType(methods, tnames) -} - -// NewInterfaceType returns a new interface for the given methods and embedded types. -// NewInterfaceType takes ownership of the provided methods and may modify their types -// by setting missing receivers. -func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface { - if len(methods) == 0 && len(embeddeds) == 0 { - return &emptyInterface - } - - // set method receivers if necessary - typ := new(Interface) - for _, m := range methods { - if sig := m.typ.(*Signature); sig.recv == nil { - sig.recv = NewVar(m.pos, m.pkg, "", typ) - } - } - - // All embedded types should be interfaces; however, defined types - // may not yet be fully resolved. Only verify that non-defined types - // are interfaces. This matches the behavior of the code before the - // fix for #25301 (issue #25596). - for _, t := range embeddeds { - if _, ok := t.(*Named); !ok && !IsInterface(t) { - panic("embedded type is not an interface") - } - } - - // sort for API stability - sortMethods(methods) - - typ.methods = methods - typ.embeddeds = embeddeds - typ.complete = true - - return typ -} - -// NumExplicitMethods returns the number of explicitly declared methods of interface t. -func (t *Interface) NumExplicitMethods() int { return len(t.methods) } - -// ExplicitMethod returns the i'th explicitly declared method of interface t for 0 <= i < t.NumExplicitMethods(). -// The methods are ordered by their unique Id. -func (t *Interface) ExplicitMethod(i int) *Func { return t.methods[i] } - -// NumEmbeddeds returns the number of embedded types in interface t. -func (t *Interface) NumEmbeddeds() int { return len(t.embeddeds) } - -// Embedded returns the i'th embedded defined (*Named) type of interface t for 0 <= i < t.NumEmbeddeds(). -// The result is nil if the i'th embedded type is not a defined type. -// -// Deprecated: Use EmbeddedType which is not restricted to defined (*Named) types. -func (t *Interface) Embedded(i int) *Named { tname, _ := t.embeddeds[i].(*Named); return tname } - -// EmbeddedType returns the i'th embedded type of interface t for 0 <= i < t.NumEmbeddeds(). -func (t *Interface) EmbeddedType(i int) Type { return t.embeddeds[i] } - -// NumMethods returns the total number of methods of interface t. -func (t *Interface) NumMethods() int { return t.typeSet().NumMethods() } - -// Method returns the i'th method of interface t for 0 <= i < t.NumMethods(). -// The methods are ordered by their unique Id. -func (t *Interface) Method(i int) *Func { return t.typeSet().Method(i) } - -// Empty reports whether t is the empty interface. -func (t *Interface) Empty() bool { return t.typeSet().IsTop() } - -// IsComparable reports whether interface t is or embeds the predeclared interface "comparable". -func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() } - -// IsConstraint reports whether interface t is not just a method set. -func (t *Interface) IsConstraint() bool { return !t.typeSet().IsMethodSet() } - -// isSatisfiedBy reports whether interface t's type list is satisfied by the type typ. -// If the type list is empty (absent), typ trivially satisfies the interface. -// TODO(gri) This is not a great name. Eventually, we should have a more comprehensive -// "implements" predicate. -func (t *Interface) isSatisfiedBy(typ Type) bool { - t.Complete() - switch t := t.typeSet().types.(type) { - case nil: - return true // no type restrictions - case *Union: - r, _ := t.intersect(typ, false) - return r != nil - default: - return Identical(t, typ) - } -} - -// Complete computes the interface's type set. It must be called by users of -// NewInterfaceType and NewInterface after the interface's embedded types are -// fully defined and before using the interface type in any way other than to -// form other types. The interface must not contain duplicate methods or a -// panic occurs. Complete returns the receiver. -// -// Deprecated: Type sets are now computed lazily, on demand; this function -// is only here for backward-compatibility. It does not have to -// be called explicitly anymore. -func (t *Interface) Complete() *Interface { - // Some tests are still depending on the state change - // (string representation of an Interface not containing an - // /* incomplete */ marker) caused by the explicit Complete - // call, so we compute the type set eagerly here. - t.complete = true - t.typeSet() - return t -} - // A Map represents a map type. type Map struct { key, elem Type @@ -638,7 +488,6 @@ func (t *Array) Underlying() Type { return t } func (t *Slice) Underlying() Type { return t } func (t *Pointer) Underlying() Type { return t } func (t *Tuple) Underlying() Type { return t } -func (t *Interface) Underlying() Type { return t } func (t *Map) Underlying() Type { return t } func (t *Chan) Underlying() Type { return t } func (t *Named) Underlying() Type { return t.expand().underlying } @@ -652,7 +501,6 @@ func (t *Array) String() string { return TypeString(t, nil) } func (t *Slice) String() string { return TypeString(t, nil) } func (t *Pointer) String() string { return TypeString(t, nil) } func (t *Tuple) String() string { return TypeString(t, nil) } -func (t *Interface) String() string { return TypeString(t, nil) } func (t *Map) String() string { return TypeString(t, nil) } func (t *Chan) String() string { return TypeString(t, nil) } func (t *Named) String() string { return TypeString(t, nil) } -- GitLab From 521828091c73e2af67bc2210b7c94cc54076f17b Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 10:59:53 -0400 Subject: [PATCH 0469/2500] [dev.typeparams] go/types: move (remaining) type decls into their own files (cleanup) This is a port of CL 332093 to go/types. A missing comment is added to named.go, and some TODOs were added to converge on the TypeParam API. Change-Id: I781a1d0d3fc6c11bb323123e954c106094d998ef Reviewed-on: https://go-review.googlesource.com/c/go/+/335040 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/array.go | 25 ++ src/go/types/basic.go | 82 +++++++ src/go/types/chan.go | 35 +++ src/go/types/instance.go | 58 +++++ src/go/types/map.go | 24 ++ src/go/types/named.go | 144 +++++++++++ src/go/types/pointer.go | 19 ++ src/go/types/slice.go | 19 ++ src/go/types/tuple.go | 36 +++ src/go/types/type.go | 486 ++------------------------------------ src/go/types/typeparam.go | 72 ++++++ 11 files changed, 532 insertions(+), 468 deletions(-) create mode 100644 src/go/types/array.go create mode 100644 src/go/types/basic.go create mode 100644 src/go/types/chan.go create mode 100644 src/go/types/instance.go create mode 100644 src/go/types/map.go create mode 100644 src/go/types/named.go create mode 100644 src/go/types/pointer.go create mode 100644 src/go/types/slice.go create mode 100644 src/go/types/tuple.go create mode 100644 src/go/types/typeparam.go diff --git a/src/go/types/array.go b/src/go/types/array.go new file mode 100644 index 0000000000..5b28474bb3 --- /dev/null +++ b/src/go/types/array.go @@ -0,0 +1,25 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +// An Array represents an array type. +type Array struct { + len int64 + elem Type +} + +// NewArray returns a new array type for the given element type and length. +// A negative length indicates an unknown length. +func NewArray(elem Type, len int64) *Array { return &Array{len: len, elem: elem} } + +// Len returns the length of array a. +// A negative result indicates an unknown length. +func (a *Array) Len() int64 { return a.len } + +// Elem returns element type of array a. +func (a *Array) Elem() Type { return a.elem } + +func (t *Array) Underlying() Type { return t } +func (t *Array) String() string { return TypeString(t, nil) } diff --git a/src/go/types/basic.go b/src/go/types/basic.go new file mode 100644 index 0000000000..215923f657 --- /dev/null +++ b/src/go/types/basic.go @@ -0,0 +1,82 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +// BasicKind describes the kind of basic type. +type BasicKind int + +const ( + Invalid BasicKind = iota // type is invalid + + // predeclared types + Bool + Int + Int8 + Int16 + Int32 + Int64 + Uint + Uint8 + Uint16 + Uint32 + Uint64 + Uintptr + Float32 + Float64 + Complex64 + Complex128 + String + UnsafePointer + + // types for untyped values + UntypedBool + UntypedInt + UntypedRune + UntypedFloat + UntypedComplex + UntypedString + UntypedNil + + // aliases + Byte = Uint8 + Rune = Int32 +) + +// BasicInfo is a set of flags describing properties of a basic type. +type BasicInfo int + +// Properties of basic types. +const ( + IsBoolean BasicInfo = 1 << iota + IsInteger + IsUnsigned + IsFloat + IsComplex + IsString + IsUntyped + + IsOrdered = IsInteger | IsFloat | IsString + IsNumeric = IsInteger | IsFloat | IsComplex + IsConstType = IsBoolean | IsNumeric | IsString +) + +// A Basic represents a basic type. +type Basic struct { + kind BasicKind + info BasicInfo + name string +} + +// Kind returns the kind of basic type b. +func (b *Basic) Kind() BasicKind { return b.kind } + +// Info returns information about properties of basic type b. +func (b *Basic) Info() BasicInfo { return b.info } + +// Name returns the name of basic type b. +func (b *Basic) Name() string { return b.name } + +func (t *Basic) Underlying() Type { return t } +func (t *Basic) String() string { return TypeString(t, nil) } diff --git a/src/go/types/chan.go b/src/go/types/chan.go new file mode 100644 index 0000000000..1f7b72be30 --- /dev/null +++ b/src/go/types/chan.go @@ -0,0 +1,35 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +// A Chan represents a channel type. +type Chan struct { + dir ChanDir + elem Type +} + +// A ChanDir value indicates a channel direction. +type ChanDir int + +// The direction of a channel is indicated by one of these constants. +const ( + SendRecv ChanDir = iota + SendOnly + RecvOnly +) + +// NewChan returns a new channel type for the given direction and element type. +func NewChan(dir ChanDir, elem Type) *Chan { + return &Chan{dir: dir, elem: elem} +} + +// Dir returns the direction of channel c. +func (c *Chan) Dir() ChanDir { return c.dir } + +// Elem returns the element type of channel c. +func (c *Chan) Elem() Type { return c.elem } + +func (t *Chan) Underlying() Type { return t } +func (t *Chan) String() string { return TypeString(t, nil) } diff --git a/src/go/types/instance.go b/src/go/types/instance.go new file mode 100644 index 0000000000..c57a947060 --- /dev/null +++ b/src/go/types/instance.go @@ -0,0 +1,58 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +import "go/token" + +// An instance represents an instantiated generic type syntactically +// (without expanding the instantiation). Type instances appear only +// during type-checking and are replaced by their fully instantiated +// (expanded) types before the end of type-checking. +type instance struct { + check *Checker // for lazy instantiation + pos token.Pos // position of type instantiation; for error reporting only + base *Named // parameterized type to be instantiated + targs []Type // type arguments + poslist []token.Pos // position of each targ; for error reporting only + value Type // base(targs...) after instantiation or Typ[Invalid]; nil if not yet set +} + +// expand returns the instantiated (= expanded) type of t. +// The result is either an instantiated *Named type, or +// Typ[Invalid] if there was an error. +func (t *instance) expand() Type { + v := t.value + if v == nil { + v = t.check.instantiate(t.pos, t.base, t.targs, t.poslist) + if v == nil { + v = Typ[Invalid] + } + t.value = v + } + // After instantiation we must have an invalid or a *Named type. + if debug && v != Typ[Invalid] { + _ = v.(*Named) + } + return v +} + +// expand expands a type instance into its instantiated +// type and leaves all other types alone. expand does +// not recurse. +func expand(typ Type) Type { + if t, _ := typ.(*instance); t != nil { + return t.expand() + } + return typ +} + +// expandf is set to expand. +// Call expandf when calling expand causes compile-time cycle error. +var expandf func(Type) Type + +func init() { expandf = expand } + +func (t *instance) Underlying() Type { return t } +func (t *instance) String() string { return TypeString(t, nil) } diff --git a/src/go/types/map.go b/src/go/types/map.go new file mode 100644 index 0000000000..01e13b214e --- /dev/null +++ b/src/go/types/map.go @@ -0,0 +1,24 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +// A Map represents a map type. +type Map struct { + key, elem Type +} + +// NewMap returns a new map for the given key and element types. +func NewMap(key, elem Type) *Map { + return &Map{key: key, elem: elem} +} + +// Key returns the key type of map m. +func (m *Map) Key() Type { return m.key } + +// Elem returns the element type of map m. +func (m *Map) Elem() Type { return m.elem } + +func (t *Map) Underlying() Type { return t } +func (t *Map) String() string { return TypeString(t, nil) } diff --git a/src/go/types/named.go b/src/go/types/named.go new file mode 100644 index 0000000000..8f2e8706a1 --- /dev/null +++ b/src/go/types/named.go @@ -0,0 +1,144 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +import "sync" + +// TODO(rfindley) Clean up Named struct below; specifically the fromRHS field (can we use underlying?). + +// A Named represents a named (defined) type. +type Named struct { + check *Checker // for Named.under implementation; nilled once under has been called + info typeInfo // for cycle detection + obj *TypeName // corresponding declared object + orig *Named // original, uninstantiated type + fromRHS Type // type (on RHS of declaration) this *Named type is derived of (for cycle reporting) + underlying Type // possibly a *Named during setup; never a *Named once set up completely + tparams []*TypeName // type parameters, or nil + targs []Type // type arguments (after instantiation), or nil + methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily + + resolve func(*Named) ([]*TypeName, Type, []*Func) + once sync.Once +} + +// NewNamed returns a new named type for the given type name, underlying type, and associated methods. +// If the given type name obj doesn't have a type yet, its type is set to the returned named type. +// The underlying type must not be a *Named. +func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named { + if _, ok := underlying.(*Named); ok { + panic("types.NewNamed: underlying type must not be *Named") + } + return (*Checker)(nil).newNamed(obj, nil, underlying, nil, methods) +} + +func (t *Named) expand() *Named { + if t.resolve == nil { + return t + } + + t.once.Do(func() { + // TODO(mdempsky): Since we're passing t to resolve anyway + // (necessary because types2 expects the receiver type for methods + // on defined interface types to be the Named rather than the + // underlying Interface), maybe it should just handle calling + // SetTParams, SetUnderlying, and AddMethod instead? Those + // methods would need to support reentrant calls though. It would + // also make the API more future-proof towards further extensions + // (like SetTParams). + + tparams, underlying, methods := t.resolve(t) + + switch underlying.(type) { + case nil, *Named: + panic("invalid underlying type") + } + + t.tparams = tparams + t.underlying = underlying + t.methods = methods + }) + return t +} + +// newNamed is like NewNamed but with a *Checker receiver and additional orig argument. +func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams []*TypeName, methods []*Func) *Named { + typ := &Named{check: check, obj: obj, orig: orig, fromRHS: underlying, underlying: underlying, tparams: tparams, methods: methods} + if typ.orig == nil { + typ.orig = typ + } + if obj.typ == nil { + obj.typ = typ + } + // Ensure that typ is always expanded, at which point the check field can be + // nilled out. + // + // Note that currently we cannot nil out check inside typ.under(), because + // it's possible that typ is expanded multiple times. + // + // TODO(rFindley): clean this up so that under is the only function mutating + // named types. + if check != nil { + check.later(func() { + switch typ.under().(type) { + case *Named, *instance: + panic("internal error: unexpanded underlying type") + } + typ.check = nil + }) + } + return typ +} + +// Obj returns the type name for the named type t. +func (t *Named) Obj() *TypeName { return t.obj } + +// _Orig returns the original generic type an instantiated type is derived from. +// If t is not an instantiated type, the result is t. +func (t *Named) _Orig() *Named { return t.orig } + +// TODO(gri) Come up with a better representation and API to distinguish +// between parameterized instantiated and non-instantiated types. + +// _TParams returns the type parameters of the named type t, or nil. +// The result is non-nil for an (originally) parameterized type even if it is instantiated. +func (t *Named) TParams() []*TypeName { return t.expand().tparams } + +// _SetTParams sets the type parameters of the named type t. +func (t *Named) SetTParams(tparams []*TypeName) { t.expand().tparams = tparams } + +// _TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated. +func (t *Named) TArgs() []Type { return t.targs } + +// SetTArgs sets the type arguments of the named type t. +func (t *Named) SetTArgs(args []Type) { t.targs = args } + +// NumMethods returns the number of explicit methods whose receiver is named type t. +func (t *Named) NumMethods() int { return len(t.expand().methods) } + +// Method returns the i'th method of named type t for 0 <= i < t.NumMethods(). +func (t *Named) Method(i int) *Func { return t.expand().methods[i] } + +// SetUnderlying sets the underlying type and marks t as complete. +func (t *Named) SetUnderlying(underlying Type) { + if underlying == nil { + panic("types.Named.SetUnderlying: underlying type must not be nil") + } + if _, ok := underlying.(*Named); ok { + panic("types.Named.SetUnderlying: underlying type must not be *Named") + } + t.expand().underlying = underlying +} + +// AddMethod adds method m unless it is already in the method list. +func (t *Named) AddMethod(m *Func) { + t.expand() + if i, _ := lookupMethod(t.methods, m.pkg, m.name); i < 0 { + t.methods = append(t.methods, m) + } +} + +func (t *Named) Underlying() Type { return t.expand().underlying } +func (t *Named) String() string { return TypeString(t, nil) } diff --git a/src/go/types/pointer.go b/src/go/types/pointer.go new file mode 100644 index 0000000000..6352ee57e2 --- /dev/null +++ b/src/go/types/pointer.go @@ -0,0 +1,19 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +// A Pointer represents a pointer type. +type Pointer struct { + base Type // element type +} + +// NewPointer returns a new pointer type for the given element (base) type. +func NewPointer(elem Type) *Pointer { return &Pointer{base: elem} } + +// Elem returns the element type for the given pointer p. +func (p *Pointer) Elem() Type { return p.base } + +func (t *Pointer) Underlying() Type { return t } +func (t *Pointer) String() string { return TypeString(t, nil) } diff --git a/src/go/types/slice.go b/src/go/types/slice.go new file mode 100644 index 0000000000..debdd81586 --- /dev/null +++ b/src/go/types/slice.go @@ -0,0 +1,19 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +// A Slice represents a slice type. +type Slice struct { + elem Type +} + +// NewSlice returns a new slice type for the given element type. +func NewSlice(elem Type) *Slice { return &Slice{elem: elem} } + +// Elem returns the element type of slice s. +func (s *Slice) Elem() Type { return s.elem } + +func (t *Slice) Underlying() Type { return t } +func (t *Slice) String() string { return TypeString(t, nil) } diff --git a/src/go/types/tuple.go b/src/go/types/tuple.go new file mode 100644 index 0000000000..16d28bc9a6 --- /dev/null +++ b/src/go/types/tuple.go @@ -0,0 +1,36 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +// A Tuple represents an ordered list of variables; a nil *Tuple is a valid (empty) tuple. +// Tuples are used as components of signatures and to represent the type of multiple +// assignments; they are not first class types of Go. +type Tuple struct { + vars []*Var +} + +// NewTuple returns a new tuple for the given variables. +func NewTuple(x ...*Var) *Tuple { + if len(x) > 0 { + return &Tuple{vars: x} + } + // TODO(gri) Don't represent empty tuples with a (*Tuple)(nil) pointer; + // it's too subtle and causes problems. + return nil +} + +// Len returns the number variables of tuple t. +func (t *Tuple) Len() int { + if t != nil { + return len(t.vars) + } + return 0 +} + +// At returns the i'th variable of tuple t. +func (t *Tuple) At(i int) *Var { return t.vars[i] } + +func (t *Tuple) Underlying() Type { return t } +func (t *Tuple) String() string { return TypeString(t, nil) } diff --git a/src/go/types/type.go b/src/go/types/type.go index 2adc2fa3ca..662dd859f0 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -4,12 +4,6 @@ package types -import ( - "go/token" - "sync" - "sync/atomic" -) - // A Type represents a type of Go. // All types implement the Type interface. type Type interface { @@ -22,379 +16,31 @@ type Type interface { String() string } -// BasicKind describes the kind of basic type. -type BasicKind int - -const ( - Invalid BasicKind = iota // type is invalid - - // predeclared types - Bool - Int - Int8 - Int16 - Int32 - Int64 - Uint - Uint8 - Uint16 - Uint32 - Uint64 - Uintptr - Float32 - Float64 - Complex64 - Complex128 - String - UnsafePointer - - // types for untyped values - UntypedBool - UntypedInt - UntypedRune - UntypedFloat - UntypedComplex - UntypedString - UntypedNil - - // aliases - Byte = Uint8 - Rune = Int32 -) - -// BasicInfo is a set of flags describing properties of a basic type. -type BasicInfo int - -// Properties of basic types. -const ( - IsBoolean BasicInfo = 1 << iota - IsInteger - IsUnsigned - IsFloat - IsComplex - IsString - IsUntyped - - IsOrdered = IsInteger | IsFloat | IsString - IsNumeric = IsInteger | IsFloat | IsComplex - IsConstType = IsBoolean | IsNumeric | IsString -) - -// A Basic represents a basic type. -type Basic struct { - kind BasicKind - info BasicInfo - name string -} - -// Kind returns the kind of basic type b. -func (b *Basic) Kind() BasicKind { return b.kind } - -// Info returns information about properties of basic type b. -func (b *Basic) Info() BasicInfo { return b.info } - -// Name returns the name of basic type b. -func (b *Basic) Name() string { return b.name } - -// An Array represents an array type. -type Array struct { - len int64 - elem Type -} - -// NewArray returns a new array type for the given element type and length. -// A negative length indicates an unknown length. -func NewArray(elem Type, len int64) *Array { return &Array{len: len, elem: elem} } - -// Len returns the length of array a. -// A negative result indicates an unknown length. -func (a *Array) Len() int64 { return a.len } - -// Elem returns element type of array a. -func (a *Array) Elem() Type { return a.elem } - -// A Slice represents a slice type. -type Slice struct { - elem Type -} - -// NewSlice returns a new slice type for the given element type. -func NewSlice(elem Type) *Slice { return &Slice{elem: elem} } - -// Elem returns the element type of slice s. -func (s *Slice) Elem() Type { return s.elem } - -// A Pointer represents a pointer type. -type Pointer struct { - base Type // element type -} - -// NewPointer returns a new pointer type for the given element (base) type. -func NewPointer(elem Type) *Pointer { return &Pointer{base: elem} } - -// Elem returns the element type for the given pointer p. -func (p *Pointer) Elem() Type { return p.base } - -// A Tuple represents an ordered list of variables; a nil *Tuple is a valid (empty) tuple. -// Tuples are used as components of signatures and to represent the type of multiple -// assignments; they are not first class types of Go. -type Tuple struct { - vars []*Var -} - -// NewTuple returns a new tuple for the given variables. -func NewTuple(x ...*Var) *Tuple { - if len(x) > 0 { - return &Tuple{vars: x} - } - // TODO(gri) Don't represent empty tuples with a (*Tuple)(nil) pointer; - // it's too subtle and causes problems. - return nil -} - -// Len returns the number variables of tuple t. -func (t *Tuple) Len() int { - if t != nil { - return len(t.vars) - } - return 0 -} - -// At returns the i'th variable of tuple t. -func (t *Tuple) At(i int) *Var { return t.vars[i] } - -// A Map represents a map type. -type Map struct { - key, elem Type -} - -// NewMap returns a new map for the given key and element types. -func NewMap(key, elem Type) *Map { - return &Map{key: key, elem: elem} -} - -// Key returns the key type of map m. -func (m *Map) Key() Type { return m.key } - -// Elem returns the element type of map m. -func (m *Map) Elem() Type { return m.elem } - -// A Chan represents a channel type. -type Chan struct { - dir ChanDir - elem Type -} - -// A ChanDir value indicates a channel direction. -type ChanDir int - -// The direction of a channel is indicated by one of these constants. -const ( - SendRecv ChanDir = iota - SendOnly - RecvOnly -) - -// NewChan returns a new channel type for the given direction and element type. -func NewChan(dir ChanDir, elem Type) *Chan { - return &Chan{dir: dir, elem: elem} -} - -// Dir returns the direction of channel c. -func (c *Chan) Dir() ChanDir { return c.dir } - -// Elem returns the element type of channel c. -func (c *Chan) Elem() Type { return c.elem } - -// TODO(rfindley) Clean up Named struct below; specifically the fromRHS field (can we use underlying?). - -// A Named represents a named (defined) type. -type Named struct { - check *Checker // for Named.under implementation; nilled once under has been called - info typeInfo // for cycle detection - obj *TypeName // corresponding declared object - orig *Named // original, uninstantiated type - fromRHS Type // type (on RHS of declaration) this *Named type is derived of (for cycle reporting) - underlying Type // possibly a *Named during setup; never a *Named once set up completely - tparams []*TypeName // type parameters, or nil - targs []Type // type arguments (after instantiation), or nil - methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily +// top represents the top of the type lattice. +// It is the underlying type of a type parameter that +// can be satisfied by any type (ignoring methods), +// because its type constraint contains no restrictions +// besides methods. +type top struct{} - resolve func(*Named) ([]*TypeName, Type, []*Func) - once sync.Once -} +// theTop is the singleton top type. +var theTop = &top{} -// NewNamed returns a new named type for the given type name, underlying type, and associated methods. -// If the given type name obj doesn't have a type yet, its type is set to the returned named type. -// The underlying type must not be a *Named. -func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named { - if _, ok := underlying.(*Named); ok { - panic("types.NewNamed: underlying type must not be *Named") - } - return (*Checker)(nil).newNamed(obj, nil, underlying, nil, methods) -} +func (t *top) Underlying() Type { return t } +func (t *top) String() string { return TypeString(t, nil) } -func (t *Named) expand() *Named { - if t.resolve == nil { - return t +// under returns the true expanded underlying type. +// If it doesn't exist, the result is Typ[Invalid]. +// under must only be called when a type is known +// to be fully set up. +func under(t Type) Type { + // TODO(gri) is this correct for *Union? + if n := asNamed(t); n != nil { + return n.under() } - - t.once.Do(func() { - // TODO(mdempsky): Since we're passing t to resolve anyway - // (necessary because types2 expects the receiver type for methods - // on defined interface types to be the Named rather than the - // underlying Interface), maybe it should just handle calling - // SetTParams, SetUnderlying, and AddMethod instead? Those - // methods would need to support reentrant calls though. It would - // also make the API more future-proof towards further extensions - // (like SetTParams). - - tparams, underlying, methods := t.resolve(t) - - switch underlying.(type) { - case nil, *Named: - panic("invalid underlying type") - } - - t.tparams = tparams - t.underlying = underlying - t.methods = methods - }) return t } -func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams []*TypeName, methods []*Func) *Named { - typ := &Named{check: check, obj: obj, orig: orig, fromRHS: underlying, underlying: underlying, tparams: tparams, methods: methods} - if typ.orig == nil { - typ.orig = typ - } - if obj.typ == nil { - obj.typ = typ - } - // Ensure that typ is always expanded, at which point the check field can be - // nilled out. - // - // Note that currently we cannot nil out check inside typ.under(), because - // it's possible that typ is expanded multiple times. - // - // TODO(rFindley): clean this up so that under is the only function mutating - // named types. - if check != nil { - check.later(func() { - switch typ.under().(type) { - case *Named, *instance: - panic("internal error: unexpanded underlying type") - } - typ.check = nil - }) - } - return typ -} - -// Obj returns the type name for the named type t. -func (t *Named) Obj() *TypeName { return t.obj } - -// _Orig returns the original generic type an instantiated type is derived from. -// If t is not an instantiated type, the result is t. -func (t *Named) _Orig() *Named { return t.orig } - -// TODO(gri) Come up with a better representation and API to distinguish -// between parameterized instantiated and non-instantiated types. - -// _TParams returns the type parameters of the named type t, or nil. -// The result is non-nil for an (originally) parameterized type even if it is instantiated. -func (t *Named) TParams() []*TypeName { return t.expand().tparams } - -// _SetTParams sets the type parameters of the named type t. -func (t *Named) SetTParams(tparams []*TypeName) { t.expand().tparams = tparams } - -// _TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated. -func (t *Named) TArgs() []Type { return t.targs } - -// SetTArgs sets the type arguments of the named type t. -func (t *Named) SetTArgs(args []Type) { t.targs = args } - -// NumMethods returns the number of explicit methods whose receiver is named type t. -func (t *Named) NumMethods() int { return len(t.expand().methods) } - -// Method returns the i'th method of named type t for 0 <= i < t.NumMethods(). -func (t *Named) Method(i int) *Func { return t.expand().methods[i] } - -// SetUnderlying sets the underlying type and marks t as complete. -func (t *Named) SetUnderlying(underlying Type) { - if underlying == nil { - panic("types.Named.SetUnderlying: underlying type must not be nil") - } - if _, ok := underlying.(*Named); ok { - panic("types.Named.SetUnderlying: underlying type must not be *Named") - } - t.expand().underlying = underlying -} - -// AddMethod adds method m unless it is already in the method list. -func (t *Named) AddMethod(m *Func) { - t.expand() - if i, _ := lookupMethod(t.methods, m.pkg, m.name); i < 0 { - t.methods = append(t.methods, m) - } -} - -// Note: This is a uint32 rather than a uint64 because the -// respective 64 bit atomic instructions are not available -// on all platforms. -var lastID uint32 - -// nextID returns a value increasing monotonically by 1 with -// each call, starting with 1. It may be called concurrently. -func nextID() uint64 { return uint64(atomic.AddUint32(&lastID, 1)) } - -// A TypeParam represents a type parameter type. -type TypeParam struct { - check *Checker // for lazy type bound completion - id uint64 // unique id, for debugging only - obj *TypeName // corresponding type name - index int // type parameter index in source order, starting at 0 - bound Type // *Named or *Interface; underlying type is always *Interface -} - -// NewTypeParam returns a new TypeParam. -func NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam { - return (*Checker)(nil).newTypeParam(obj, index, bound) -} - -func (check *Checker) newTypeParam(obj *TypeName, index int, bound Type) *TypeParam { - assert(bound != nil) - - // Always increment lastID, even if it is not used. - id := nextID() - if check != nil { - check.nextID++ - id = check.nextID - } - - typ := &TypeParam{check: check, id: id, obj: obj, index: index, bound: bound} - if obj.typ == nil { - obj.typ = typ - } - return typ -} - -func (t *TypeParam) Bound() *Interface { - // we may not have an interface (error reported elsewhere) - iface, _ := under(t.bound).(*Interface) - if iface == nil { - return &emptyInterface - } - // use the type bound position if we have one - pos := token.NoPos - if n, _ := t.bound.(*Named); n != nil { - pos = n.obj.pos - } - // TODO(rFindley) switch this to an unexported method on Checker. - computeTypeSet(t.check, pos, iface) - return iface -} - // optype returns a type's operational type. Except for type parameters, // the operational type is the same as the underlying type (as returned // by under). For Type parameters, the operational type is determined @@ -424,102 +70,6 @@ func optype(typ Type) Type { return under(typ) } -// An instance represents an instantiated generic type syntactically -// (without expanding the instantiation). Type instances appear only -// during type-checking and are replaced by their fully instantiated -// (expanded) types before the end of type-checking. -type instance struct { - check *Checker // for lazy instantiation - pos token.Pos // position of type instantiation; for error reporting only - base *Named // parameterized type to be instantiated - targs []Type // type arguments - poslist []token.Pos // position of each targ; for error reporting only - value Type // base(targs...) after instantiation or Typ[Invalid]; nil if not yet set -} - -// expand returns the instantiated (= expanded) type of t. -// The result is either an instantiated *Named type, or -// Typ[Invalid] if there was an error. -func (t *instance) expand() Type { - v := t.value - if v == nil { - v = t.check.instantiate(t.pos, t.base, t.targs, t.poslist) - if v == nil { - v = Typ[Invalid] - } - t.value = v - } - // After instantiation we must have an invalid or a *Named type. - if debug && v != Typ[Invalid] { - _ = v.(*Named) - } - return v -} - -// expand expands a type instance into its instantiated -// type and leaves all other types alone. expand does -// not recurse. -func expand(typ Type) Type { - if t, _ := typ.(*instance); t != nil { - return t.expand() - } - return typ -} - -// expandf is set to expand. -// Call expandf when calling expand causes compile-time cycle error. -var expandf func(Type) Type - -func init() { expandf = expand } - -// top represents the top of the type lattice. -// It is the underlying type of a type parameter that -// can be satisfied by any type (ignoring methods), -// because its type constraint contains no restrictions -// besides methods. -type top struct{} - -// theTop is the singleton top type. -var theTop = &top{} - -// Type-specific implementations of Underlying. -func (t *Basic) Underlying() Type { return t } -func (t *Array) Underlying() Type { return t } -func (t *Slice) Underlying() Type { return t } -func (t *Pointer) Underlying() Type { return t } -func (t *Tuple) Underlying() Type { return t } -func (t *Map) Underlying() Type { return t } -func (t *Chan) Underlying() Type { return t } -func (t *Named) Underlying() Type { return t.expand().underlying } -func (t *TypeParam) Underlying() Type { return t } -func (t *instance) Underlying() Type { return t } -func (t *top) Underlying() Type { return t } - -// Type-specific implementations of String. -func (t *Basic) String() string { return TypeString(t, nil) } -func (t *Array) String() string { return TypeString(t, nil) } -func (t *Slice) String() string { return TypeString(t, nil) } -func (t *Pointer) String() string { return TypeString(t, nil) } -func (t *Tuple) String() string { return TypeString(t, nil) } -func (t *Map) String() string { return TypeString(t, nil) } -func (t *Chan) String() string { return TypeString(t, nil) } -func (t *Named) String() string { return TypeString(t, nil) } -func (t *TypeParam) String() string { return TypeString(t, nil) } -func (t *instance) String() string { return TypeString(t, nil) } -func (t *top) String() string { return TypeString(t, nil) } - -// under returns the true expanded underlying type. -// If it doesn't exist, the result is Typ[Invalid]. -// under must only be called when a type is known -// to be fully set up. -func under(t Type) Type { - // TODO(gri) is this correct for *Union? - if n := asNamed(t); n != nil { - return n.under() - } - return t -} - // Converters // // A converter must only be called when a type is diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go new file mode 100644 index 0000000000..e134508855 --- /dev/null +++ b/src/go/types/typeparam.go @@ -0,0 +1,72 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +import ( + "go/token" + "sync/atomic" +) + +// Note: This is a uint32 rather than a uint64 because the +// respective 64 bit atomic instructions are not available +// on all platforms. +var lastID uint32 + +// nextID returns a value increasing monotonically by 1 with +// each call, starting with 1. It may be called concurrently. +func nextID() uint64 { return uint64(atomic.AddUint32(&lastID, 1)) } + +// A TypeParam represents a type parameter type. +type TypeParam struct { + check *Checker // for lazy type bound completion + id uint64 // unique id, for debugging only + obj *TypeName // corresponding type name + index int // type parameter index in source order, starting at 0 + bound Type // *Named or *Interface; underlying type is always *Interface +} + +// NewTypeParam returns a new TypeParam. +func NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam { + return (*Checker)(nil).newTypeParam(obj, index, bound) +} + +// TODO(rfindley): this is factored slightly differently in types2. +func (check *Checker) newTypeParam(obj *TypeName, index int, bound Type) *TypeParam { + assert(bound != nil) + + // Always increment lastID, even if it is not used. + id := nextID() + if check != nil { + check.nextID++ + id = check.nextID + } + + typ := &TypeParam{check: check, id: id, obj: obj, index: index, bound: bound} + if obj.typ == nil { + obj.typ = typ + } + return typ +} + +// TODO(rfindley): types2 to has Index and SetID. Should we add them here? + +func (t *TypeParam) Bound() *Interface { + // we may not have an interface (error reported elsewhere) + iface, _ := under(t.bound).(*Interface) + if iface == nil { + return &emptyInterface + } + // use the type bound position if we have one + pos := token.NoPos + if n, _ := t.bound.(*Named); n != nil { + pos = n.obj.pos + } + // TODO(rFindley) switch this to an unexported method on Checker. + computeTypeSet(t.check, pos, iface) + return iface +} + +func (t *TypeParam) Underlying() Type { return t } +func (t *TypeParam) String() string { return TypeString(t, nil) } -- GitLab From c4cd76fbbbf0f8b89fee70783103b0c3abb68756 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 12:45:35 -0400 Subject: [PATCH 0470/2500] [dev.typeparams] go/types: disallow "free" type parameter as RHS of a type declaration This is a port of CL 332411 to go/types. methodset_test.go is similarly updated. Change-Id: I332b1837a954acc9d3b7e0e2ad2bec3425f088f7 Reviewed-on: https://go-review.googlesource.com/c/go/+/335109 Reviewed-by: Robert Griesemer Run-TryBot: Robert Findley TryBot-Result: Go Bot Trust: Robert Findley --- src/go/types/decl.go | 64 ++++++++++--------- src/go/types/methodset_test.go | 5 +- src/go/types/testdata/examples/types.go2 | 50 +++++++++------ .../types/testdata/fixedbugs/issue45639.go2 | 12 ++++ src/go/types/unify.go | 15 +++-- 5 files changed, 90 insertions(+), 56 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue45639.go2 diff --git a/src/go/types/decl.go b/src/go/types/decl.go index f0e7c5d5ad..921530595a 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -680,48 +680,52 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { alias = false } + // alias declaration if alias { - // type alias declaration if !check.allowVersion(check.pkg, 1, 9) { check.errorf(atPos(tdecl.Assign), _BadDecl, "type aliases requires go1.9 or later") } obj.typ = Typ[Invalid] obj.typ = check.anyType(tdecl.Type) + return + } - } else { - // defined type declaration - - named := check.newNamed(obj, nil, nil, nil, nil) - def.setUnderlying(named) + // type definition or generic type declaration + named := check.newNamed(obj, nil, nil, nil, nil) + def.setUnderlying(named) - if tparams := typeparams.Get(tdecl); tparams != nil { - check.openScope(tdecl, "type parameters") - defer check.closeScope() - named.tparams = check.collectTypeParams(tparams) - } + if tparams := typeparams.Get(tdecl); tparams != nil { + check.openScope(tdecl, "type parameters") + defer check.closeScope() + named.tparams = check.collectTypeParams(tparams) + } - // determine underlying type of named - named.fromRHS = check.definedType(tdecl.Type, named) + // determine underlying type of named + named.fromRHS = check.definedType(tdecl.Type, named) - // The underlying type of named may be itself a named type that is - // incomplete: - // - // type ( - // A B - // B *C - // C A - // ) - // - // The type of C is the (named) type of A which is incomplete, - // and which has as its underlying type the named type B. - // Determine the (final, unnamed) underlying type by resolving - // any forward chain. - // TODO(gri) Investigate if we can just use named.fromRHS here - // and rely on lazy computation of the underlying type. - named.underlying = under(named) + // The underlying type of named may be itself a named type that is + // incomplete: + // + // type ( + // A B + // B *C + // C A + // ) + // + // The type of C is the (named) type of A which is incomplete, + // and which has as its underlying type the named type B. + // Determine the (final, unnamed) underlying type by resolving + // any forward chain. + // TODO(gri) Investigate if we can just use named.fromRHS here + // and rely on lazy computation of the underlying type. + named.underlying = under(named) + + // If the RHS is a type parameter, it must be from this type declaration. + if tpar, _ := named.underlying.(*TypeParam); tpar != nil && tparamIndex(named.tparams, tpar) < 0 { + check.errorf(tdecl.Type, _Todo, "cannot use function type parameter %s as RHS in type declaration", tpar) + named.underlying = Typ[Invalid] } - } func (check *Checker) collectTypeParams(list *ast.FieldList) []*TypeName { diff --git a/src/go/types/methodset_test.go b/src/go/types/methodset_test.go index 566356ad6d..5b29b2f0fe 100644 --- a/src/go/types/methodset_test.go +++ b/src/go/types/methodset_test.go @@ -50,8 +50,9 @@ func TestNewMethodSet(t *testing.T) { "type C interface{ f() }; func g[T C]() { var a T; _ = a }": {{"f", []int{0}, true}}, "type C interface{ f() }; func g[T C]() { var a struct{T}; _ = a }": {{"f", []int{0, 0}, true}}, - // Issue #45639. - "type C interface{ f() }; func g[T C]() { type Y T; var a Y; _ = a }": {}, + // Issue #45639: We don't allow this anymore. Keep this code in case we + // decide to revisit this decision. + // "type C interface{ f() }; func g[T C]() { type Y T; var a Y; _ = a }": {}, } check := func(src string, methods []method, generic bool) { diff --git a/src/go/types/testdata/examples/types.go2 b/src/go/types/testdata/examples/types.go2 index 8cdd7f2fd2..a7544f79ea 100644 --- a/src/go/types/testdata/examples/types.go2 +++ b/src/go/types/testdata/examples/types.go2 @@ -161,30 +161,40 @@ type _ struct { * /* ERROR List redeclared */ List[int] } +// Issue #45639: We don't allow this anymore. Keep this code +// in case we decide to revisit this decision. +// // It's possible to declare local types whose underlying types // are type parameters. As with ordinary type definitions, the // types underlying properties are "inherited" but the methods // are not. -func _[T interface{ m(); ~int }]() { - type L T - var x L - - // m is not defined on L (it is not "inherited" from - // its underlying type). - x.m /* ERROR x.m undefined */ () - - // But the properties of T, such that as that it supports - // the operations of the types given by its type bound, - // are also the properties of L. - x++ - _ = x - x - - // On the other hand, if we define a local alias for T, - // that alias stands for T as expected. - type A = T - var y A - y.m() - _ = y < 0 +//func _[T interface{ m(); ~int }]() { +// type L T +// var x L +// +// // m is not defined on L (it is not "inherited" from +// // its underlying type). +// x.m /* ERROR x.m undefined */ () +// +// // But the properties of T, such that as that it supports +// // the operations of the types given by its type bound, +// // are also the properties of L. +// x++ +// _ = x - x +// +// // On the other hand, if we define a local alias for T, +// // that alias stands for T as expected. +// type A = T +// var y A +// y.m() +// _ = y < 0 +//} + +// It is not permitted to declare a local type whose underlying +// type is a type parameters not declared by that type declaration. +func _[T any]() { + type _ T // ERROR cannot use function type parameter T as RHS in type declaration + type _ [_ any] T // ERROR cannot use function type parameter T as RHS in type declaration } // As a special case, an explicit type argument may be omitted diff --git a/src/go/types/testdata/fixedbugs/issue45639.go2 b/src/go/types/testdata/fixedbugs/issue45639.go2 new file mode 100644 index 0000000000..441fb4cb34 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue45639.go2 @@ -0,0 +1,12 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package P + +// It is not permitted to declare a local type whose underlying +// type is a type parameters not declared by that type declaration. +func _[T any]() { + type _ T // ERROR cannot use function type parameter T as RHS in type declaration + type _ [_ any] T // ERROR cannot use function type parameter T as RHS in type declaration +} diff --git a/src/go/types/unify.go b/src/go/types/unify.go index 762000db32..84c8ae718f 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -147,10 +147,17 @@ func (u *unifier) join(i, j int) bool { // If typ is a type parameter of d, index returns the type parameter index. // Otherwise, the result is < 0. func (d *tparamsList) index(typ Type) int { - if t, ok := typ.(*TypeParam); ok { - if i := t.index; i < len(d.tparams) && d.tparams[i].typ == t { - return i - } + if tpar, ok := typ.(*TypeParam); ok { + return tparamIndex(d.tparams, tpar) + } + return -1 +} + +// If tpar is a type parameter in list, tparamIndex returns the type parameter index. +// Otherwise, the result is < 0. tpar must not be nil. +func tparamIndex(list []*TypeName, tpar *TypeParam) int { + if i := tpar.index; i < len(list) && list[i].typ == tpar { + return i } return -1 } -- GitLab From e9836fe31897ef6e8a5c82c3f8fc8c2b31a3bea3 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 12:54:37 -0400 Subject: [PATCH 0471/2500] [dev.typeparams] go/types: clean up index expr implementation for type parameters This is a port of CL 332553 to go/types. The "expr" variable is renamed to "e" in Checker.indexExpr to be consistent with types2. Change-Id: I7905bebf2e8dab47256361362b16becf7596cf95 Reviewed-on: https://go-review.googlesource.com/c/go/+/335110 Reviewed-by: Robert Griesemer Run-TryBot: Robert Findley TryBot-Result: Go Bot Trust: Robert Findley --- src/go/types/index.go | 135 +++++++++--------- src/go/types/testdata/check/typeparams.go2 | 17 ++- .../types/testdata/fixedbugs/issue45635.go2 | 5 +- src/go/types/typeparam.go | 7 + src/go/types/typeset.go | 15 ++ src/go/types/typestring.go | 2 +- src/go/types/union.go | 2 +- 7 files changed, 101 insertions(+), 82 deletions(-) diff --git a/src/go/types/index.go b/src/go/types/index.go index 769626dcc2..036752c734 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -15,18 +15,18 @@ import ( // If e is a valid function instantiation, indexExpr returns true. // In that case x represents the uninstantiated function value and // it is the caller's responsibility to instantiate the function. -func (check *Checker) indexExpr(x *operand, expr *typeparams.IndexExpr) (isFuncInst bool) { - check.exprOrType(x, expr.X) +func (check *Checker) indexExpr(x *operand, e *typeparams.IndexExpr) (isFuncInst bool) { + check.exprOrType(x, e.X) switch x.mode { case invalid: - check.use(expr.Indices...) + check.use(e.Indices...) return false case typexpr: // type instantiation x.mode = invalid - x.typ = check.varType(expr.Orig) + x.typ = check.varType(e.Orig) if x.typ != Typ[Invalid] { x.mode = typexpr } @@ -41,7 +41,7 @@ func (check *Checker) indexExpr(x *operand, expr *typeparams.IndexExpr) (isFuncI valid := false length := int64(-1) // valid if >= 0 - switch typ := optype(x.typ).(type) { + switch typ := under(x.typ).(type) { case *Basic: if isString(typ) { valid = true @@ -77,10 +77,10 @@ func (check *Checker) indexExpr(x *operand, expr *typeparams.IndexExpr) (isFuncI x.typ = typ.elem case *Map: - index := check.singleIndex(expr) + index := check.singleIndex(e) if index == nil { x.mode = invalid - return + return false } var key operand check.expr(&key, index) @@ -88,88 +88,81 @@ func (check *Checker) indexExpr(x *operand, expr *typeparams.IndexExpr) (isFuncI // ok to continue even if indexing failed - map element type is known x.mode = mapindex x.typ = typ.elem - x.expr = expr.Orig - return + x.expr = e.Orig + return false - case *Union: - // A union type can be indexed if all of the union's terms - // support indexing and have the same index and element - // type. Special rules apply for maps in the union type. - var tkey, telem Type // key is for map types only - nmaps := 0 // number of map types in union type - if typ.underIs(func(t Type) bool { - var e Type - switch t := t.(type) { + case *TypeParam: + // TODO(gri) report detailed failure cause for better error messages + var tkey, telem Type // tkey != nil if we have maps + if typ.underIs(func(u Type) bool { + var key, elem Type + alen := int64(-1) // valid if >= 0 + switch t := u.(type) { case *Basic: - if isString(t) { - e = universeByte + if !isString(t) { + return false } + elem = universeByte case *Array: - e = t.elem + elem = t.elem + alen = t.len case *Pointer: - if t := asArray(t.base); t != nil { - e = t.elem + a, _ := under(t.base).(*Array) + if a == nil { + return false } + elem = a.elem + alen = a.len case *Slice: - e = t.elem + elem = t.elem case *Map: - // If there are multiple maps in the union type, - // they must have identical key types. - // TODO(gri) We may be able to relax this rule - // but it becomes complicated very quickly. - if tkey != nil && !Identical(t.key, tkey) { + key = t.key + elem = t.elem + default: + return false + } + assert(elem != nil) + if telem == nil { + // first type + tkey, telem = key, elem + length = alen + } else { + // all map keys must be identical (incl. all nil) + if !Identical(key, tkey) { return false } - tkey = t.key - e = t.elem - nmaps++ - case *TypeParam: - check.errorf(x, 0, "type of %s contains a type parameter - cannot index (implementation restriction)", x) - case *instance: - panic("unimplemented") - } - if e == nil || telem != nil && !Identical(e, telem) { - return false + // all element types must be identical + if !Identical(elem, telem) { + return false + } + tkey, telem = key, elem + // track the minimal length for arrays + if alen >= 0 && alen < length { + length = alen + } } - telem = e return true }) { - // If there are maps, the index expression must be assignable - // to the map key type (as for simple map index expressions). - if nmaps > 0 { - index := check.singleIndex(expr) + // For maps, the index expression must be assignable to the map key type. + if tkey != nil { + index := check.singleIndex(e) if index == nil { x.mode = invalid - return + return false } var key operand check.expr(&key, index) check.assignment(&key, tkey, "map index") // ok to continue even if indexing failed - map element type is known - - // If there are only maps, we are done. - if nmaps == typ.NumTerms() { - x.mode = mapindex - x.typ = telem - x.expr = expr.Orig - return - } - - // Otherwise we have mix of maps and other types. For - // now we require that the map key be an integer type. - // TODO(gri) This is probably not good enough. - valid = isInteger(tkey) - // avoid 2nd indexing error if indexing failed above - if !valid && key.mode == invalid { - x.mode = invalid - return - } - x.mode = value // map index expressions are not addressable - } else { - // no maps - valid = true - x.mode = variable + x.mode = mapindex + x.typ = telem + x.expr = e + return false } + + // no maps + valid = true + x.mode = variable x.typ = telem } } @@ -177,13 +170,13 @@ func (check *Checker) indexExpr(x *operand, expr *typeparams.IndexExpr) (isFuncI if !valid { check.invalidOp(x, _NonIndexableOperand, "cannot index %s", x) x.mode = invalid - return + return false } - index := check.singleIndex(expr) + index := check.singleIndex(e) if index == nil { x.mode = invalid - return + return false } // In pathological (invalid) cases (e.g.: type T1 [][[]T1{}[0][0]]T0) diff --git a/src/go/types/testdata/check/typeparams.go2 b/src/go/types/testdata/check/typeparams.go2 index 5b4361d279..b832e6b760 100644 --- a/src/go/types/testdata/check/typeparams.go2 +++ b/src/go/types/testdata/check/typeparams.go2 @@ -98,18 +98,23 @@ func _[T any] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } func _[T interface{ ~int }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } func _[T interface{ ~string }] (x T, i int) { _ = x[i] } func _[T interface{ ~[]int }] (x T, i int) { _ = x[i] } -func _[T interface{ ~[10]int | ~*[20]int | ~map[int]int }] (x T, i int) { _ = x[i] } +func _[T interface{ ~[10]int | ~*[20]int | ~map[int]int }] (x T, i int) { _ = x /* ERROR cannot index */ [i] } // map and non-map types func _[T interface{ ~string | ~[]byte }] (x T, i int) { _ = x[i] } func _[T interface{ ~[]int | ~[1]rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } func _[T interface{ ~string | ~[]rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } -// indexing with various combinations of map types in type lists (see issue #42616) -func _[T interface{ ~[]E | ~map[int]E }, E any](x T, i int) { _ = x[i] } +// indexing with various combinations of map types in type sets (see issue #42616) +func _[T interface{ ~[]E | ~map[int]E }, E any](x T, i int) { _ = x /* ERROR cannot index */ [i] } // map and non-map types func _[T interface{ ~[]E }, E any](x T, i int) { _ = &x[i] } func _[T interface{ ~map[int]E }, E any](x T, i int) { _, _ = x[i] } // comma-ok permitted -func _[T interface{ ~[]E | ~map[int]E }, E any](x T, i int) { _ = &x /* ERROR cannot take address */ [i] } -func _[T interface{ ~[]E | ~map[int]E | ~map[uint]E }, E any](x T, i int) { _ = x /* ERROR cannot index */ [i] } // different map element types -func _[T interface{ ~[]E | ~map[string]E }, E any](x T, i int) { _ = x[i /* ERROR cannot use i */ ] } +func _[T interface{ ~map[int]E }, E any](x T, i int) { _ = &x /* ERROR cannot take address */ [i] } +func _[T interface{ ~map[int]E | ~map[uint]E }, E any](x T, i int) { _ = x /* ERROR cannot index */ [i] } // different map element types +func _[T interface{ ~[]E | ~map[string]E }, E any](x T, i int) { _ = x /* ERROR cannot index */ [i] } // map and non-map types + +// indexing with various combinations of array and other types in type sets +func _[T interface{ [10]int }](x T, i int) { _ = x[i]; _ = x[9]; _ = x[10 /* ERROR out of bounds */ ] } +func _[T interface{ [10]byte | string }](x T, i int) { _ = x[i]; _ = x[9]; _ = x[10 /* ERROR out of bounds */ ] } +func _[T interface{ [10]int | *[20]int | []int }](x T, i int) { _ = x[i]; _ = x[9]; _ = x[10 /* ERROR out of bounds */ ] } // slicing // TODO(gri) implement this diff --git a/src/go/types/testdata/fixedbugs/issue45635.go2 b/src/go/types/testdata/fixedbugs/issue45635.go2 index c6784e12fd..fc50797b17 100644 --- a/src/go/types/testdata/fixedbugs/issue45635.go2 +++ b/src/go/types/testdata/fixedbugs/issue45635.go2 @@ -13,7 +13,7 @@ type N[T any] struct{} var _ N [] // ERROR expected type argument list type I interface { - ~map[int]int | ~[]int + ~[]int } func _[T I](i, j int) { @@ -27,6 +27,5 @@ func _[T I](i, j int) { _ = s[i, j /* ERROR "more than one index" */ ] var t T - // TODO(rFindley) Fix the duplicate error below. - _ = t[i, j /* ERROR "more than one index" */ /* ERROR "more than one index" */ ] + _ = t[i, j /* ERROR "more than one index" */ ] } diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index e134508855..92b048f247 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -70,3 +70,10 @@ func (t *TypeParam) Bound() *Interface { func (t *TypeParam) Underlying() Type { return t } func (t *TypeParam) String() string { return TypeString(t, nil) } + +// ---------------------------------------------------------------------------- +// Implementation + +func (t *TypeParam) underIs(f func(Type) bool) bool { + return t.Bound().typeSet().underIs(f) +} diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index e979e90e6f..3fe48892fe 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -75,6 +75,21 @@ func (s *TypeSet) String() string { // ---------------------------------------------------------------------------- // Implementation +// underIs reports whether f returned true for the underlying types of the +// enumerable types in the type set s. If the type set comprises all types +// f is called once with the top type; if the type set is empty, the result +// is false. +func (s *TypeSet) underIs(f func(Type) bool) bool { + switch t := s.types.(type) { + case nil: + return f(theTop) + default: + return f(t) + case *Union: + return t.underIs(f) + } +} + // topTypeSet may be used as type set for the empty interface. var topTypeSet TypeSet diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index d234d86e61..aef5e2013b 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -165,7 +165,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { } for i, e := range t.types { if i > 0 { - buf.WriteString("|") + buf.WriteByte('|') } if t.tilde[i] { buf.WriteByte('~') diff --git a/src/go/types/union.go b/src/go/types/union.go index 690b734d76..7c69ec7b10 100644 --- a/src/go/types/union.go +++ b/src/go/types/union.go @@ -60,7 +60,7 @@ func (u *Union) is(f func(Type, bool) bool) bool { return true } -// is reports whether f returned true for the underlying types of all terms of u. +// underIs reports whether f returned true for the underlying types of all terms of u. func (u *Union) underIs(f func(Type) bool) bool { if u.IsEmpty() { return false -- GitLab From df778e6fd9a8ad4f50f734f08b8d07d4ce597c02 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 13:03:06 -0400 Subject: [PATCH 0472/2500] [dev.typeparams] go/types: replace optype() with under() in various cases (cleanup) This is a port of CL 332555 to go/types. Change-Id: I9b26bba8b605f5bbbd8f0f81fd6651a4a3ff4b57 Reviewed-on: https://go-review.googlesource.com/c/go/+/335111 Reviewed-by: Robert Griesemer Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot --- src/go/types/builtins.go | 8 +++++--- src/go/types/expr.go | 6 +++--- src/go/types/index.go | 6 +++--- src/go/types/predicates.go | 17 ++++++++--------- src/go/types/testdata/check/typeparams.go2 | 2 +- src/go/types/typeset.go | 1 + 6 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index e976e76cf1..9b2a75458c 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -337,13 +337,15 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b return } var src Type - switch t := optype(y.typ).(type) { + switch t := under(y.typ).(type) { case *Basic: if isString(y.typ) { src = universeByte } case *Slice: src = t.elem + case *TypeParam: + check.error(x, _Todo, "copy on generic operands not yet implemented") } if dst == nil || src == nil { @@ -464,12 +466,12 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b var valid func(t Type) bool valid = func(t Type) bool { var m int - switch t := optype(t).(type) { + switch t := under(t).(type) { case *Slice: m = 2 case *Map, *Chan: m = 1 - case *Union: + case *TypeParam: return t.underIs(valid) default: return false diff --git a/src/go/types/expr.go b/src/go/types/expr.go index edd7caf1c9..46f6e33463 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -622,7 +622,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const return x.typ, nil, 0 } - switch t := optype(target).(type) { + switch t := under(target).(type) { case *Basic: if x.mode == constant_ { v, code := check.representation(x, t) @@ -661,7 +661,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const default: return nil, nil, _InvalidUntypedConversion } - case *Union: + case *TypeParam: ok := t.underIs(func(t Type) bool { target, _, _ := check.implicitTypeAndValue(x, t) return target != nil @@ -1151,7 +1151,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { goto Error } - switch utyp := optype(base).(type) { + switch utyp := under(base).(type) { case *Struct: if len(e.Elts) == 0 { break diff --git a/src/go/types/index.go b/src/go/types/index.go index 036752c734..b2a5a2e948 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -199,7 +199,7 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { valid := false length := int64(-1) // valid if >= 0 - switch typ := optype(x.typ).(type) { + switch typ := under(x.typ).(type) { case *Basic: if isString(typ) { if e.Slice3 { @@ -239,8 +239,8 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { valid = true // x.typ doesn't change - case *Union, *TypeParam: - check.errorf(x, 0, "generic slice expressions not yet implemented") + case *TypeParam: + check.errorf(x, _Todo, "generic slice expressions not yet implemented") x.mode = invalid return } diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index c3c168647d..c9be121839 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -25,10 +25,10 @@ func isGeneric(typ Type) bool { } func is(typ Type, what BasicInfo) bool { - switch t := optype(typ).(type) { + switch t := under(typ).(type) { case *Basic: return t.info&what != 0 - case *Union: + case *TypeParam: return t.underIs(func(typ Type) bool { return is(typ, what) }) } return false @@ -97,18 +97,19 @@ func comparable(T Type, seen map[Type]bool) bool { seen[T] = true // If T is a type parameter not constrained by any type - // list (i.e., it's operational type is the top type), + // (i.e., it's operational type is the top type), // T is comparable if it has the == method. Otherwise, // the operational type "wins". For instance // // interface{ comparable; type []byte } // // is not comparable because []byte is not comparable. + // TODO(gri) this code is not 100% correct (see comment for TypeSet.IsComparable) if t := asTypeParam(T); t != nil && optype(t) == theTop { return t.Bound().IsComparable() } - switch t := optype(T).(type) { + switch t := under(T).(type) { case *Basic: // assume invalid types to be comparable // to avoid follow-up errors @@ -124,24 +125,22 @@ func comparable(T Type, seen map[Type]bool) bool { return true case *Array: return comparable(t.elem, seen) - case *Union: + case *TypeParam: return t.underIs(func(t Type) bool { return comparable(t, seen) }) - case *TypeParam: - return t.Bound().IsComparable() } return false } // hasNil reports whether a type includes the nil value. func hasNil(typ Type) bool { - switch t := optype(typ).(type) { + switch t := under(typ).(type) { case *Basic: return t.kind == UnsafePointer case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan: return true - case *Union: + case *TypeParam: return t.underIs(hasNil) } return false diff --git a/src/go/types/testdata/check/typeparams.go2 b/src/go/types/testdata/check/typeparams.go2 index b832e6b760..0e3795724b 100644 --- a/src/go/types/testdata/check/typeparams.go2 +++ b/src/go/types/testdata/check/typeparams.go2 @@ -119,7 +119,7 @@ func _[T interface{ [10]int | *[20]int | []int }](x T, i int) { _ = x[i]; _ = x[ // slicing // TODO(gri) implement this -func _[T interface{ ~string }] (x T, i, j, k int) { _ = x /* ERROR invalid operation */ [i:j:k] } +func _[T interface{ ~string }] (x T, i, j, k int) { _ = x /* ERROR generic slice expressions not yet implemented */ [i:j:k] } // len/cap built-ins diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index 3fe48892fe..d8fe42f7d0 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -28,6 +28,7 @@ func (s *TypeSet) IsTop() bool { return len(s.methods) == 0 && s.types == nil } func (s *TypeSet) IsMethodSet() bool { return s.types == nil && !s.IsComparable() } // IsComparable reports whether each type in the set is comparable. +// TODO(gri) this is not correct - there may be s.types values containing non-comparable types func (s *TypeSet) IsComparable() bool { _, m := s.LookupMethod(nil, "==") return m != nil -- GitLab From 9b85985d36a7cc7117e9c14bc1d2632844a5a818 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Fri, 9 Jul 2021 16:27:22 -0700 Subject: [PATCH 0473/2500] [dev.typeparams] Separate out gcshape types that are instantiated types Distinguish the gcshape of all top-level instantiated type from normal concrete types, even if they have the exact same underlying "shape", because in a function instantiation, any method call on this type arg will be a generic method call (requiring a dictionary), rather than a direct method call on the underlying type (no dictionary). So, we add the instshape prefix to the gcshape name for instantiated types, and we make it a defined type with that name. Change-Id: I33056269d24f3451a2632a5ce6a481108f533c9c Reviewed-on: https://go-review.googlesource.com/c/go/+/335169 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 28 ++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index f4935fe22a..7eac8573c9 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -729,11 +729,37 @@ func gcshapeType(t *types.Type) (*types.Type, string) { // Call CallSize so type sizes and field offsets are available. types.CalcSize(t) + + instType := t.Sym() != nil && t.IsFullyInstantiated() + if instType { + // We distinguish the gcshape of all top-level instantiated type from + // normal concrete types, even if they have the exact same underlying + // "shape", because in a function instantiation, any method call on + // this type arg will be a generic method call (requiring a + // dictionary), rather than a direct method call on the underlying + // type (no dictionary). So, we add the instshape prefix to the + // normal gcshape name, and will make it a defined type with that + // name below. + buf.WriteString("instshape-") + } fl = accumGcshape(fl, buf, t, nil) + // TODO: Should gcshapes be in a global package, so we don't have to // duplicate in each package? Or at least in the specified source package // of a function/method instantiation? gcshape := types.NewStruct(types.LocalPkg, fl) + gcname := buf.String() + if instType { + // Lookup or create type with name 'gcname' (with instshape prefix). + newsym := t.Sym().Pkg.Lookup(gcname) + if newsym.Def != nil { + gcshape = newsym.Def.Type() + } else { + newt := typecheck.NewIncompleteNamedType(t.Pos(), newsym) + newt.SetUnderlying(gcshape.Underlying()) + gcshape = newt + } + } assert(gcshape.Size() == t.Size()) return gcshape, buf.String() } @@ -764,7 +790,7 @@ func (g *irgen) getInstantiation(nameNode *ir.Name, targs []*types.Type, isMeth // Testing out gcshapeType() and gcshapeName() for i, t := range targs { gct, gcs := gcshapeType(t) - fmt.Printf("targ %d: %v %v\n", i, gct, gcs) + fmt.Printf("targ %d: %v %v %v\n", i, gcs, gct, gct.Underlying()) } } // If instantiation doesn't exist yet, create it and add -- GitLab From 76b39959f4edc8b877506fe7cfe674ceaf64a627 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 13:15:24 -0400 Subject: [PATCH 0474/2500] [dev.typeparams] go/types: don't permit method calls on ptr to type parameter receivers This is a port of CL 332609 to go/types. Change-Id: I3482ea1b97bc7101b987ef312cd6cade80a5843f Reviewed-on: https://go-review.googlesource.com/c/go/+/335112 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/lookup.go | 10 ++++++---- src/go/types/testdata/check/issues.go2 | 10 ++++------ .../types/testdata/fixedbugs/issue47031.go2 | 20 +++++++++++++++++++ src/go/types/type.go | 12 +++++------ 4 files changed, 36 insertions(+), 16 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue47031.go2 diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index 70e3b4281d..304ae6e3c9 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -75,10 +75,12 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o typ, isPtr := deref(T) - // *typ where typ is an interface has no methods. - // Be cautious: typ may be nil (issue 39634, crash #3). - if typ == nil || isPtr && IsInterface(typ) { - return + // *typ where typ is an interface or type parameter has no methods. + switch under(typ).(type) { + case *Interface, *TypeParam: + if isPtr { + return + } } // Start with typ as single entry at shallowest depth. diff --git a/src/go/types/testdata/check/issues.go2 b/src/go/types/testdata/check/issues.go2 index c655fb99a4..607da1df19 100644 --- a/src/go/types/testdata/check/issues.go2 +++ b/src/go/types/testdata/check/issues.go2 @@ -24,22 +24,20 @@ func _() { eql[io.Reader](nil, nil) } -// If we have a receiver of pointer type (below: *T) we must ignore -// the pointer in the implementation of the method lookup because -// the type bound of T is an interface and pointer to interface types -// have no methods and then the lookup would fail. +// If we have a receiver of pointer to type parameter type (below: *T) +// we don't have any methods, like for interfaces. type C[T any] interface { m() } // using type bound C func _[T C[T]](x *T) { - x.m() + x.m /* ERROR x\.m undefined */ () } // using an interface literal as bound func _[T interface{ m() }](x *T) { - x.m() + x.m /* ERROR x\.m undefined */ () } // In a generic function body all method calls will be pointer method calls. diff --git a/src/go/types/testdata/fixedbugs/issue47031.go2 b/src/go/types/testdata/fixedbugs/issue47031.go2 new file mode 100644 index 0000000000..b184f9b5b7 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue47031.go2 @@ -0,0 +1,20 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type Mer interface { M() } + +func F[T Mer](p *T) { + p.M /* ERROR p\.M undefined */ () +} + +type MyMer int + +func (MyMer) M() {} + +func _() { + F(new(MyMer)) + F[Mer](nil) +} diff --git a/src/go/types/type.go b/src/go/types/type.go index 662dd859f0..0a6fff0dca 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -113,11 +113,6 @@ func asSignature(t Type) *Signature { return op } -func asInterface(t Type) *Interface { - op, _ := optype(t).(*Interface) - return op -} - func asMap(t Type) *Map { op, _ := optype(t).(*Map) return op @@ -128,10 +123,15 @@ func asChan(t Type) *Chan { return op } -// If the argument to asNamed and asTypeParam is of the respective types +// If the argument to asInterface, asNamed, or asTypeParam is of the respective type // (possibly after expanding an instance type), these methods return that type. // Otherwise the result is nil. +func asInterface(t Type) *Interface { + op, _ := optype(t).(*Interface) + return op +} + func asNamed(t Type) *Named { e, _ := expand(t).(*Named) return e -- GitLab From ccf95f17dd87683d915f7b11d88530b5f8f8efa2 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 13:27:57 -0400 Subject: [PATCH 0475/2500] [dev.typeparams] go/types: support local defined types This is a port of CL 327170 to go/types. Tests were not ported; they can be added later. Change-Id: Ic9fd681ac06dd187c1715efaf882b11353bc395a Reviewed-on: https://go-review.googlesource.com/c/go/+/335113 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/subst.go | 5 +++++ src/go/types/typestring.go | 34 +++++++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 41ffcd0d1e..d8388a948b 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -428,14 +428,19 @@ func (subst *subster) typ(typ Type) Type { return typ } +var instanceHashing = 0 + // TODO(gri) Eventually, this should be more sophisticated. // It won't work correctly for locally declared types. func instantiatedHash(typ *Named, targs []Type) string { + assert(instanceHashing == 0) + instanceHashing++ var buf bytes.Buffer writeTypeName(&buf, typ.obj, nil) buf.WriteByte('[') writeTypeList(&buf, targs, nil, nil) buf.WriteByte(']') + instanceHashing-- // With respect to the represented type, whether a // type is fully expanded or stored as instance diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index aef5e2013b..f348d185c5 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -348,17 +348,33 @@ func writeTParamList(buf *bytes.Buffer, list []*TypeName, qf Qualifier, visited } func writeTypeName(buf *bytes.Buffer, obj *TypeName, qf Qualifier) { - s := "" - if obj != nil { - if obj.pkg != nil { - writePackage(buf, obj.pkg, qf) + if obj == nil { + buf.WriteString("") + return + } + if obj.pkg != nil { + writePackage(buf, obj.pkg, qf) + } + buf.WriteString(obj.name) + + if instanceHashing != 0 { + // For local defined types, use the (original!) TypeName's position + // to disambiguate. This is overkill, and could probably instead + // just be the pointer value (if we assume a non-moving GC) or + // a unique ID (like cmd/compile uses). But this works for now, + // and is convenient for debugging. + + // TODO(mdempsky): I still don't fully understand why typ.orig.orig + // can differ from typ.orig, or whether looping more than twice is + // ever necessary. + typ := obj.typ.(*Named) + for typ.orig != typ { + typ = typ.orig + } + if orig := typ.obj; orig.pkg != nil && orig.parent != orig.pkg.scope { + fmt.Fprintf(buf, "@%q", orig.pos) } - // TODO(gri): function-local named types should be displayed - // differently from named types at package level to avoid - // ambiguity. - s = obj.name } - buf.WriteString(s) } func writeTuple(buf *bytes.Buffer, tup *Tuple, variadic bool, qf Qualifier, visited []Type) { -- GitLab From c7c13ae4323f9f1d658625a9a774525789ee4d71 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 14:20:18 -0400 Subject: [PATCH 0476/2500] [dev.typeparams] go/types: use scope numbers to identify local types This is a port of CL 333192 to go/types. Change-Id: I12fd6b682d40c4d30b9ac0e87c463843cf5030d2 Reviewed-on: https://go-review.googlesource.com/c/go/+/335114 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer --- src/go/types/instance.go | 2 +- src/go/types/scope.go | 4 +++- src/go/types/sizeof_test.go | 2 +- src/go/types/subst.go | 2 -- src/go/types/typestring.go | 29 +++++++++++++++++------------ src/go/types/universe.go | 12 ++++++++---- 6 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/go/types/instance.go b/src/go/types/instance.go index c57a947060..99771104bf 100644 --- a/src/go/types/instance.go +++ b/src/go/types/instance.go @@ -16,7 +16,7 @@ type instance struct { base *Named // parameterized type to be instantiated targs []Type // type arguments poslist []token.Pos // position of each targ; for error reporting only - value Type // base(targs...) after instantiation or Typ[Invalid]; nil if not yet set + value Type // base[targs...] after instantiation or Typ[Invalid]; nil if not yet set } // expand returns the instantiated (= expanded) type of t. diff --git a/src/go/types/scope.go b/src/go/types/scope.go index fa6e0ecb8f..010727eb72 100644 --- a/src/go/types/scope.go +++ b/src/go/types/scope.go @@ -23,6 +23,7 @@ import ( type Scope struct { parent *Scope children []*Scope + number int // parent.children[number-1] is this scope; 0 if there is no parent elems map[string]Object // lazily allocated pos, end token.Pos // scope extent; may be invalid comment string // for debugging only @@ -32,10 +33,11 @@ type Scope struct { // NewScope returns a new, empty scope contained in the given parent // scope, if any. The comment is for debugging only. func NewScope(parent *Scope, pos, end token.Pos, comment string) *Scope { - s := &Scope{parent, nil, nil, pos, end, comment, false} + s := &Scope{parent, nil, 0, nil, pos, end, comment, false} // don't add children to Universe scope! if parent != nil && parent != Universe { parent.children = append(parent.children, s) + s.number = len(parent.children) } return s } diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index 8f5f42b415..d03e1ea0cb 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -46,7 +46,7 @@ func TestSizeof(t *testing.T) { {Nil{}, 40, 72}, // Misc - {Scope{}, 40, 80}, + {Scope{}, 44, 88}, {Package{}, 40, 80}, {TypeSet{}, 20, 40}, } diff --git a/src/go/types/subst.go b/src/go/types/subst.go index d8388a948b..4809b8c47a 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -430,8 +430,6 @@ func (subst *subster) typ(typ Type) Type { var instanceHashing = 0 -// TODO(gri) Eventually, this should be more sophisticated. -// It won't work correctly for locally declared types. func instantiatedHash(typ *Named, targs []Type) string { assert(instanceHashing == 0) instanceHashing++ diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index f348d185c5..4e73030613 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -358,22 +358,27 @@ func writeTypeName(buf *bytes.Buffer, obj *TypeName, qf Qualifier) { buf.WriteString(obj.name) if instanceHashing != 0 { - // For local defined types, use the (original!) TypeName's position - // to disambiguate. This is overkill, and could probably instead - // just be the pointer value (if we assume a non-moving GC) or - // a unique ID (like cmd/compile uses). But this works for now, - // and is convenient for debugging. - - // TODO(mdempsky): I still don't fully understand why typ.orig.orig - // can differ from typ.orig, or whether looping more than twice is - // ever necessary. + // For local defined types, use the (original!) TypeName's scope + // numbers to disambiguate. typ := obj.typ.(*Named) + // TODO(gri) Figure out why typ.orig != typ.orig.orig sometimes + // and whether the loop can iterate more than twice. + // (It seems somehow connected to instance types.) for typ.orig != typ { typ = typ.orig } - if orig := typ.obj; orig.pkg != nil && orig.parent != orig.pkg.scope { - fmt.Fprintf(buf, "@%q", orig.pos) - } + writeScopeNumbers(buf, typ.obj.parent) + } +} + +// writeScopeNumbers writes the number sequence for this scope to buf +// in the form ".i.j.k" where i, j, k, etc. stand for scope numbers. +// If a scope is nil or has no parent (such as a package scope), nothing +// is written. +func writeScopeNumbers(buf *bytes.Buffer, s *Scope) { + if s != nil && s.number > 0 { + writeScopeNumbers(buf, s.parent) + fmt.Fprintf(buf, ".%d", s.number) } } diff --git a/src/go/types/universe.go b/src/go/types/universe.go index 540b0ac118..7c1e29b856 100644 --- a/src/go/types/universe.go +++ b/src/go/types/universe.go @@ -87,21 +87,25 @@ func defPredeclaredTypes() { // type error interface{ Error() string } { + obj := NewTypeName(token.NoPos, nil, "error", nil) + obj.setColor(black) res := NewVar(token.NoPos, nil, "", Typ[String]) sig := NewSignature(nil, nil, NewTuple(res), false) err := NewFunc(token.NoPos, nil, "Error", sig) - typ := &Named{underlying: NewInterfaceType([]*Func{err}, nil)} + typ := NewNamed(obj, NewInterfaceType([]*Func{err}, nil), nil) sig.recv = NewVar(token.NoPos, nil, "", typ) - def(NewTypeName(token.NoPos, nil, "error", typ)) + def(obj) } // type comparable interface{ ==() } { + obj := NewTypeName(token.NoPos, nil, "comparable", nil) + obj.setColor(black) sig := NewSignature(nil, nil, nil, false) eql := NewFunc(token.NoPos, nil, "==", sig) - typ := &Named{underlying: NewInterfaceType([]*Func{eql}, nil)} + typ := NewNamed(obj, NewInterfaceType([]*Func{eql}, nil), nil) sig.recv = NewVar(token.NoPos, nil, "", typ) - def(NewTypeName(token.NoPos, nil, "comparable", typ)) + def(obj) } } -- GitLab From 43ad1ffa990358e60130ca9395210315e59e059a Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 14:30:15 -0400 Subject: [PATCH 0477/2500] [dev.typeparams] go/types: recursive substitution must terminate (bug fix) This is a port of CL 333383 to go/types. Change-Id: I7ff68116cbe63337dbcc834c473a2a5588274e36 Reviewed-on: https://go-review.googlesource.com/c/go/+/335115 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/api_test.go | 23 +++++++++++++++++++++++ src/go/types/subst.go | 38 ++++++++++++++++++++++---------------- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index e6c209dda0..9ca24db1de 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -1817,3 +1817,26 @@ func f(x T) T { return foo.F(x) } } } } + +func TestInstantiate(t *testing.T) { + // eventually we like more tests but this is a start + const src = genericPkg + "p; type T[P any] *T[P]" + pkg, err := pkgFor(".", src, nil) + if err != nil { + t.Fatal(err) + } + + // type T should have one type parameter + T := pkg.Scope().Lookup("T").Type().(*Named) + if n := len(T.TParams()); n != 1 { + t.Fatalf("expected 1 type parameter; found %d", n) + } + + // instantiation should succeed (no endless recursion) + res := Instantiate(token.NoPos, T, []Type{Typ[Int]}) + + // instantiated type should point to itself + if res.Underlying().(*Pointer).Elem() != res { + t.Fatalf("unexpected result type: %s", res) + } +} diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 4809b8c47a..64146be27e 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -237,15 +237,27 @@ func (check *Checker) subst(pos token.Pos, typ Type, smap *substMap) Type { } // general case - subst := subster{check, pos, make(map[Type]Type), smap} + var subst subster + subst.pos = pos + subst.smap = smap + if check != nil { + subst.check = check + subst.typMap = check.typMap + } else { + // If we don't have a *Checker and its global type map, + // use a local version. Besides avoiding duplicate work, + // the type map prevents infinite recursive substitution + // for recursive types (example: type T[P any] *T[P]). + subst.typMap = make(map[string]*Named) + } return subst.typ(typ) } type subster struct { - check *Checker - pos token.Pos - cache map[Type]Type - smap *substMap + pos token.Pos + smap *substMap + check *Checker // nil if called via Instantiate + typMap map[string]*Named } func (subst *subster) typ(typ Type) Type { @@ -390,22 +402,16 @@ func (subst *subster) typ(typ Type) Type { // before creating a new named type, check if we have this one already h := instantiatedHash(t, newTargs) dump(">>> new type hash: %s", h) - if subst.check != nil { - if named, found := subst.check.typMap[h]; found { - dump(">>> found %s", named) - subst.cache[t] = named - return named - } + if named, found := subst.typMap[h]; found { + dump(">>> found %s", named) + return named } - // create a new named type and populate caches to avoid endless recursion + // create a new named type and populate typMap to avoid endless recursion tname := NewTypeName(subst.pos, t.obj.pkg, t.obj.name, nil) named := subst.check.newNamed(tname, t, t.Underlying(), t.TParams(), t.methods) // method signatures are updated lazily named.targs = newTargs - if subst.check != nil { - subst.check.typMap[h] = named - } - subst.cache[t] = named + subst.typMap[h] = named // do the substitution dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, newTargs) -- GitLab From b96f1b94191f7a404599e61b8cdd8ac010805545 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 14:43:30 -0400 Subject: [PATCH 0478/2500] [dev.typeparams] go/types: add some missing APIs for the importer This is a partial port of CL 319930, containing only changes to go/types. Importer changes will be made in a separate CL. The TypeParams APIs are left unexported for now; they will be exported when they are needed. Change-Id: I74bd246d4c174cb38f8360d921c733fa03900eab Reviewed-on: https://go-review.googlesource.com/c/go/+/335143 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/api_test.go | 12 ++++++------ src/go/types/signature.go | 7 +++++-- src/go/types/typeparam.go | 13 ++++++++++++- src/go/types/typestring.go | 7 +++++++ 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index 9ca24db1de..0a91f139fe 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -331,16 +331,16 @@ func TestTypesInfo(t *testing.T) { {broken + `x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string][-1]int`}, // parameterized functions - {genericPkg + `p0; func f[T any](T); var _ = f[int]`, `f`, `func[T₁ interface{}](T₁)`}, + {genericPkg + `p0; func f[T any](T); var _ = f[int]`, `f`, `func[generic_p0.T₁ interface{}](generic_p0.T₁)`}, {genericPkg + `p1; func f[T any](T); var _ = f[int]`, `f[int]`, `func(int)`}, - {genericPkg + `p2; func f[T any](T); func _() { f(42) }`, `f`, `func[T₁ interface{}](T₁)`}, + {genericPkg + `p2; func f[T any](T); func _() { f(42) }`, `f`, `func[generic_p2.T₁ interface{}](generic_p2.T₁)`}, {genericPkg + `p3; func f[T any](T); func _() { f(42) }`, `f(42)`, `()`}, // type parameters {genericPkg + `t0; type t[] int; var _ t`, `t`, `generic_t0.t`}, // t[] is a syntax error that is ignored in this test in favor of t - {genericPkg + `t1; type t[P any] int; var _ t[int]`, `t`, `generic_t1.t[P₁ interface{}]`}, - {genericPkg + `t2; type t[P interface{}] int; var _ t[int]`, `t`, `generic_t2.t[P₁ interface{}]`}, - {genericPkg + `t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `generic_t3.t[P₁, Q₂ interface{}]`}, + {genericPkg + `t1; type t[P any] int; var _ t[int]`, `t`, `generic_t1.t[generic_t1.P₁ interface{}]`}, + {genericPkg + `t2; type t[P interface{}] int; var _ t[int]`, `t`, `generic_t2.t[generic_t2.P₁ interface{}]`}, + {genericPkg + `t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `generic_t3.t[generic_t3.P₁, generic_t3.Q₂ interface{}]`}, // TODO (rFindley): compare with types2, which resolves the type broken_t4.t[P₁, Q₂ interface{m()}] here {broken + `t4; type t[P, Q interface{ m() }] int; var _ t[int, int]`, `t`, `broken_t4.t`}, @@ -349,7 +349,7 @@ func TestTypesInfo(t *testing.T) { {genericPkg + `g0; type t[P any] int; var x struct{ f t[int] }; var _ = x.f`, `x.f`, `generic_g0.t[int]`}, // issue 45096 - {genericPkg + `issue45096; func _[T interface{ ~int8 | ~int16 | ~int32 }](x T) { _ = x < 0 }`, `0`, `T₁`}, + {genericPkg + `issue45096; func _[T interface{ ~int8 | ~int16 | ~int32 }](x T) { _ = x < 0 }`, `0`, `generic_issue45096.T₁`}, } for _, test := range tests { diff --git a/src/go/types/signature.go b/src/go/types/signature.go index 665514587e..85a735120f 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -55,12 +55,15 @@ func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature { // contain methods whose receiver type is a different interface. func (s *Signature) Recv() *Var { return s.recv } -// _TParams returns the type parameters of signature s, or nil. +// TParams returns the type parameters of signature s, or nil. func (s *Signature) TParams() []*TypeName { return s.tparams } -// _SetTParams sets the type parameters of signature s. +// SetTParams sets the type parameters of signature s. func (s *Signature) SetTParams(tparams []*TypeName) { s.tparams = tparams } +// SetRParams sets the receiver type params of signature s. +func (s *Signature) SetRParams(rparams []*TypeName) { s.rparams = rparams } + // Params returns the parameters of signature s, or nil. func (s *Signature) Params() *Tuple { return s.params } diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index 92b048f247..89ac3ecf38 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -50,7 +50,18 @@ func (check *Checker) newTypeParam(obj *TypeName, index int, bound Type) *TypePa return typ } -// TODO(rfindley): types2 to has Index and SetID. Should we add them here? +// TODO(rfindley): remove or export these placeholder APIs. + +// Index returns the index of the type param within its param list. +func (t *TypeParam) _Index() int { + return t.index +} + +// SetId sets the unique id of a type param. Should only be used for type params +// in imported generic types. +func (t *TypeParam) _SetId(id uint64) { + t.id = id +} func (t *TypeParam) Bound() *Interface { // we may not have an interface (error reported elsewhere) diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 4e73030613..cba678588a 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -284,6 +284,13 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { case *TypeParam: s := "?" if t.obj != nil { + // Optionally write out package for typeparams (like Named). + // TODO(rfindley): this is required for import/export, so + // we maybe need a separate function that won't be changed + // for debugging purposes. + if t.obj.pkg != nil { + writePackage(buf, t.obj.pkg, qf) + } s = t.obj.name } buf.WriteString(s + subscript(t.id)) -- GitLab From 22a38ba5caa49fb7d494b09fedef90afb674cd77 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 14:54:21 -0400 Subject: [PATCH 0479/2500] [dev.typeparams] go/types: remove unnecessary guard from NewInterfaceType This is a partial port of CL 322609, containing only changes to go/types. Importer changes will be made in a separate CL. Change-Id: I50af3c1ed5e949bb28a3462d717c0eb29a5f31ab Reviewed-on: https://go-review.googlesource.com/c/go/+/335144 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/interface.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/go/types/interface.go b/src/go/types/interface.go index 91270cfcd3..686dd7a786 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -72,17 +72,6 @@ func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface { } } - // TODO(rfindley): this guard is not present in types2. Remove it? - // All embedded types should be interfaces; however, defined types - // may not yet be fully resolved. Only verify that non-defined types - // are interfaces. This matches the behavior of the code before the - // fix for #25301 (issue #25596). - for _, t := range embeddeds { - if _, ok := t.(*Named); !ok && !IsInterface(t) { - panic("embedded type is not an interface") - } - } - // sort for API stability sortMethods(methods) -- GitLab From 9e147c55b7a08b487efff3a87a27ed8c463cf347 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 19:01:16 -0400 Subject: [PATCH 0480/2500] [dev.typeparams] go/types: update TypeParam APIs to match types2 This is a partial port of CL 323029, consisting only of changes to go/types. Changes to the importer will be made in a separate CL. Change-Id: I3b300f5e8f4df36c2c87e3f164705cd3c36218ac Reviewed-on: https://go-review.googlesource.com/c/go/+/335145 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/builtins.go | 8 +++++--- src/go/types/decl.go | 2 +- src/go/types/type.go | 12 +++++++----- src/go/types/typeparam.go | 19 +++++++++---------- 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 9b2a75458c..2573bac69e 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -783,9 +783,11 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { return nil } - // construct a suitable new type parameter - tpar := NewTypeName(token.NoPos, nil /* = Universe pkg */, "", nil) - ptyp := check.newTypeParam(tpar, 0, &emptyInterface) // assigns type to tpar as a side-effect + // Construct a suitable new type parameter for the sum type. The + // type param is placed in the current package so export/import + // works as expected. + tpar := NewTypeName(token.NoPos, check.pkg, "", nil) + ptyp := check.NewTypeParam(tpar, 0, &emptyInterface) // assigns type to tpar as a side-effect tsum := newUnion(rtypes, tildes) ptyp.bound = &Interface{complete: true, tset: &TypeSet{types: tsum}} diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 921530595a..d68070d049 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -758,7 +758,7 @@ func (check *Checker) collectTypeParams(list *ast.FieldList) []*TypeName { func (check *Checker) declareTypeParams(tparams []*TypeName, names []*ast.Ident) []*TypeName { for _, name := range names { tpar := NewTypeName(name.Pos(), check.pkg, name.Name, nil) - check.newTypeParam(tpar, len(tparams), &emptyInterface) // assigns type to tpar as a side-effect + check.NewTypeParam(tpar, len(tparams), &emptyInterface) // assigns type to tpar as a side-effect check.declare(check.scope, name, tpar, check.scope.pos) // TODO(gri) check scope position tparams = append(tparams, tpar) } diff --git a/src/go/types/type.go b/src/go/types/type.go index 0a6fff0dca..e0498fece2 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -41,11 +41,13 @@ func under(t Type) Type { return t } -// optype returns a type's operational type. Except for type parameters, -// the operational type is the same as the underlying type (as returned -// by under). For Type parameters, the operational type is determined -// by the corresponding type constraint. The result may be the top type, -// but it is never the incoming type parameter. +// optype returns a type's operational type. Except for +// type parameters, the operational type is the same +// as the underlying type (as returned by under). For +// Type parameters, the operational type is determined +// by the corresponding type bound's type list. The +// result may be the bottom or top type, but it is never +// the incoming type parameter. func optype(typ Type) Type { if t := asTypeParam(typ); t != nil { // If the optype is typ, return the top type as we have diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index 89ac3ecf38..e42c24f8cb 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -27,22 +27,14 @@ type TypeParam struct { bound Type // *Named or *Interface; underlying type is always *Interface } -// NewTypeParam returns a new TypeParam. -func NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam { - return (*Checker)(nil).newTypeParam(obj, index, bound) -} - -// TODO(rfindley): this is factored slightly differently in types2. -func (check *Checker) newTypeParam(obj *TypeName, index int, bound Type) *TypeParam { - assert(bound != nil) - +// NewTypeParam returns a new TypeParam. bound can be nil (and set later). +func (check *Checker) NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam { // Always increment lastID, even if it is not used. id := nextID() if check != nil { check.nextID++ id = check.nextID } - typ := &TypeParam{check: check, id: id, obj: obj, index: index, bound: bound} if obj.typ == nil { obj.typ = typ @@ -79,6 +71,13 @@ func (t *TypeParam) Bound() *Interface { return iface } +func (t *TypeParam) _SetBound(bound Type) { + if bound == nil { + panic("internal error: bound must not be nil") + } + t.bound = bound +} + func (t *TypeParam) Underlying() Type { return t } func (t *TypeParam) String() string { return TypeString(t, nil) } -- GitLab From 41ff0aac13fd0537702a7f28091a841bef233548 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 19:49:43 -0400 Subject: [PATCH 0481/2500] [dev.typeparams] go/types: replace types2.Instantiate with Checker.Instantiate This is a partial port of CL 333569 containing just changes to go/types. Changes to the importer wil be made in a separate CL. Change-Id: I9383e260b76402875ca6eb23c4478a6a3e8c1f0d Reviewed-on: https://go-review.googlesource.com/c/go/+/335071 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/types/api_test.go | 4 ++- src/go/types/call.go | 4 +-- src/go/types/instance.go | 3 +- src/go/types/instantiate.go | 64 ++++--------------------------------- src/go/types/sizeof_test.go | 2 +- src/go/types/subst.go | 54 +++++++++++++++++++++---------- src/go/types/typexpr.go | 2 ++ 7 files changed, 53 insertions(+), 80 deletions(-) diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index 0a91f139fe..444cb44087 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -1833,7 +1833,9 @@ func TestInstantiate(t *testing.T) { } // instantiation should succeed (no endless recursion) - res := Instantiate(token.NoPos, T, []Type{Typ[Int]}) + // even with a nil *Checker + var check *Checker + res := check.Instantiate(token.NoPos, T, []Type{Typ[Int]}, nil, false) // instantiated type should point to itself if res.Underlying().(*Pointer).Elem() != res { diff --git a/src/go/types/call.go b/src/go/types/call.go index bcd569e82f..9453b53c3a 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -60,7 +60,7 @@ func (check *Checker) funcInst(x *operand, ix *typeparams.IndexExpr) { } // instantiate function signature - res := check.instantiate(x.Pos(), sig, targs, poslist).(*Signature) + res := check.Instantiate(x.Pos(), sig, targs, poslist, true).(*Signature) assert(res.tparams == nil) // signature is not generic anymore if inferred { check.recordInferred(ix.Orig, targs, res) @@ -333,7 +333,7 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type } // compute result signature - rsig = check.instantiate(call.Pos(), sig, targs, nil).(*Signature) + rsig = check.Instantiate(call.Pos(), sig, targs, nil, true).(*Signature) assert(rsig.tparams == nil) // signature is not generic anymore check.recordInferred(call, targs, rsig) diff --git a/src/go/types/instance.go b/src/go/types/instance.go index 99771104bf..143ba693a6 100644 --- a/src/go/types/instance.go +++ b/src/go/types/instance.go @@ -16,6 +16,7 @@ type instance struct { base *Named // parameterized type to be instantiated targs []Type // type arguments poslist []token.Pos // position of each targ; for error reporting only + verify bool // if set, constraint satisfaction is verified value Type // base[targs...] after instantiation or Typ[Invalid]; nil if not yet set } @@ -25,7 +26,7 @@ type instance struct { func (t *instance) expand() Type { v := t.value if v == nil { - v = t.check.instantiate(t.pos, t.base, t.targs, t.poslist) + v = t.check.Instantiate(t.pos, t.base, t.targs, t.poslist, t.verify) if v == nil { v = Typ[Invalid] } diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 1c15ac199c..61b9055326 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -9,71 +9,19 @@ import ( "go/token" ) -// Instantiate instantiates the type typ with the given type arguments. -// typ must be a *Named or a *Signature type, it must be generic, and -// its number of type parameters must match the number of provided type -// arguments. The result is a new, instantiated (not generic) type of -// the same kind (either a *Named or a *Signature). The type arguments -// are not checked against the constraints of the type parameters. -// Any methods attached to a *Named are simply copied; they are not -// instantiated. -func Instantiate(pos token.Pos, typ Type, targs []Type) (res Type) { - // TODO(gri) This code is basically identical to the prolog - // in Checker.instantiate. Factor. - var tparams []*TypeName - switch t := typ.(type) { - case *Named: - tparams = t.TParams() - case *Signature: - tparams = t.tparams - defer func() { - // If we had an unexpected failure somewhere don't panic below when - // asserting res.(*Signature). Check for *Signature in case Typ[Invalid] - // is returned. - if _, ok := res.(*Signature); !ok { - return - } - // If the signature doesn't use its type parameters, subst - // will not make a copy. In that case, make a copy now (so - // we can set tparams to nil w/o causing side-effects). - if t == res { - copy := *t - res = © - } - // After instantiating a generic signature, it is not generic - // anymore; we need to set tparams to nil. - res.(*Signature).tparams = nil - }() - - default: - panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) - } - - // the number of supplied types must match the number of type parameters - if len(targs) != len(tparams) { - panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, len(targs), len(tparams))) - } - - if len(tparams) == 0 { - return typ // nothing to do (minor optimization) - } - - smap := makeSubstMap(tparams, targs) - return (*Checker)(nil).subst(pos, typ, smap) -} - // InstantiateLazy is like Instantiate, but avoids actually // instantiating the type until needed. -func (check *Checker) InstantiateLazy(pos token.Pos, typ Type, targs []Type) (res Type) { +func (check *Checker) InstantiateLazy(pos token.Pos, typ Type, targs []Type, verify bool) (res Type) { base := asNamed(typ) if base == nil { panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } return &instance{ - check: check, - pos: pos, - base: base, - targs: targs, + check: check, + pos: pos, + base: base, + targs: targs, + verify: verify, } } diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index d03e1ea0cb..8c18de8675 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -32,7 +32,7 @@ func TestSizeof(t *testing.T) { {Chan{}, 12, 24}, {Named{}, 84, 160}, {TypeParam{}, 28, 48}, - {instance{}, 44, 88}, + {instance{}, 48, 96}, {top{}, 0, 0}, // Objects diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 64146be27e..d367369158 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -56,8 +56,24 @@ func (m *substMap) lookup(tpar *TypeParam) Type { return tpar } -func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, poslist []token.Pos) (res Type) { - if trace { +// Instantiate instantiates the type typ with the given type arguments +// targs. To check type constraint satisfaction, verify must be set. +// pos and posList correspond to the instantiation and type argument +// positions respectively; posList may be nil or shorter than the number +// of type arguments provided. +// typ must be a *Named or a *Signature type, and its number of type +// parameters must match the number of provided type arguments. +// The receiver (check) may be nil if and only if verify is not set. +// The result is a new, instantiated (not generic) type of the same kind +// (either a *Named or a *Signature). +// Any methods attached to a *Named are simply copied; they are not +// instantiated. +func (check *Checker) Instantiate(pos token.Pos, typ Type, targs []Type, posList []token.Pos, verify bool) (res Type) { + if verify && check == nil { + panic("cannot have nil receiver if verify is set") + } + + if check != nil && trace { check.trace(pos, "-- instantiating %s with %s", typ, typeListString(targs)) check.indent++ defer func() { @@ -73,7 +89,7 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, poslist }() } - assert(len(poslist) <= len(targs)) + assert(len(posList) <= len(targs)) // TODO(gri) What is better here: work with TypeParams, or work with TypeNames? var tparams []*TypeName @@ -100,17 +116,19 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, poslist // anymore; we need to set tparams to nil. res.(*Signature).tparams = nil }() - default: - check.dump("%v: cannot instantiate %v", pos, typ) - unreachable() // only defined types and (defined) functions can be generic + // only types and functions can be generic + panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } // the number of supplied types must match the number of type parameters if len(targs) != len(tparams) { // TODO(gri) provide better error message - check.errorf(atPos(pos), _Todo, "got %d arguments but %d type parameters", len(targs), len(tparams)) - return Typ[Invalid] + if check != nil { + check.errorf(atPos(pos), _Todo, "got %d arguments but %d type parameters", len(targs), len(tparams)) + return Typ[Invalid] + } + panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, len(targs), len(tparams))) } if len(tparams) == 0 { @@ -120,16 +138,18 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, poslist smap := makeSubstMap(tparams, targs) // check bounds - for i, tname := range tparams { - // best position for error reporting - pos := pos - if i < len(poslist) { - pos = poslist[i] - } + if verify { + for i, tname := range tparams { + // best position for error reporting + pos := pos + if i < len(posList) { + pos = posList[i] + } - // stop checking bounds after the first failure - if !check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap) { - break + // stop checking bounds after the first failure + if !check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap) { + break + } } } diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 342317048b..e93c50a087 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -413,12 +413,14 @@ func (check *Checker) instantiatedType(ix *typeparams.IndexExpr, def *Named) Typ // create a new type instance rather than instantiate the type // TODO(gri) should do argument number check here rather than // when instantiating the type? + // TODO(gri) use InstantiateLazy here (cleanup) typ := new(instance) def.setUnderlying(typ) typ.check = check typ.pos = ix.X.Pos() typ.base = base + typ.verify = true // evaluate arguments (always) typ.targs = check.typeList(ix.Indices) -- GitLab From 4a72be87b354e7ae641ccebfb57242ee24c8d7f4 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 19:52:46 -0400 Subject: [PATCH 0482/2500] [dev.typeparams] go/types: move instantiation code to instantiate.go (cleanup) This is a port of CL 333589 to go/types. Change-Id: Ib9fb1b09e10c400e62d20b55ff0558f3a92fc0eb Reviewed-on: https://go-review.googlesource.com/c/go/+/335072 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/instantiate.go | 185 +++++++++++++++++++++++++++++++++++ src/go/types/subst.go | 186 +----------------------------------- 2 files changed, 186 insertions(+), 185 deletions(-) diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 61b9055326..55e34ca0c1 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// This file implements instantiation of generic types +// through substitution of type parameters by type arguments. + package types import ( @@ -9,6 +12,106 @@ import ( "go/token" ) +// Instantiate instantiates the type typ with the given type arguments +// targs. To check type constraint satisfaction, verify must be set. +// pos and posList correspond to the instantiation and type argument +// positions respectively; posList may be nil or shorter than the number +// of type arguments provided. +// typ must be a *Named or a *Signature type, and its number of type +// parameters must match the number of provided type arguments. +// The receiver (check) may be nil if and only if verify is not set. +// The result is a new, instantiated (not generic) type of the same kind +// (either a *Named or a *Signature). +// Any methods attached to a *Named are simply copied; they are not +// instantiated. +func (check *Checker) Instantiate(pos token.Pos, typ Type, targs []Type, posList []token.Pos, verify bool) (res Type) { + if verify && check == nil { + panic("cannot have nil receiver if verify is set") + } + + if check != nil && trace { + check.trace(pos, "-- instantiating %s with %s", typ, typeListString(targs)) + check.indent++ + defer func() { + check.indent-- + var under Type + if res != nil { + // Calling under() here may lead to endless instantiations. + // Test case: type T[P any] T[P] + // TODO(gri) investigate if that's a bug or to be expected. + under = res.Underlying() + } + check.trace(pos, "=> %s (under = %s)", res, under) + }() + } + + assert(len(posList) <= len(targs)) + + // TODO(gri) What is better here: work with TypeParams, or work with TypeNames? + var tparams []*TypeName + switch t := typ.(type) { + case *Named: + tparams = t.TParams() + case *Signature: + tparams = t.tparams + defer func() { + // If we had an unexpected failure somewhere don't panic below when + // asserting res.(*Signature). Check for *Signature in case Typ[Invalid] + // is returned. + if _, ok := res.(*Signature); !ok { + return + } + // If the signature doesn't use its type parameters, subst + // will not make a copy. In that case, make a copy now (so + // we can set tparams to nil w/o causing side-effects). + if t == res { + copy := *t + res = © + } + // After instantiating a generic signature, it is not generic + // anymore; we need to set tparams to nil. + res.(*Signature).tparams = nil + }() + default: + // only types and functions can be generic + panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) + } + + // the number of supplied types must match the number of type parameters + if len(targs) != len(tparams) { + // TODO(gri) provide better error message + if check != nil { + check.errorf(atPos(pos), _Todo, "got %d arguments but %d type parameters", len(targs), len(tparams)) + return Typ[Invalid] + } + panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, len(targs), len(tparams))) + } + + if len(tparams) == 0 { + return typ // nothing to do (minor optimization) + } + + smap := makeSubstMap(tparams, targs) + + // check bounds + if verify { + for i, tname := range tparams { + // best position for error reporting + pos := pos + if i < len(posList) { + pos = posList[i] + } + + // stop checking bounds after the first failure + if !check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap) { + break + } + } + } + + return check.subst(pos, typ, smap) +} + // InstantiateLazy is like Instantiate, but avoids actually // instantiating the type until needed. func (check *Checker) InstantiateLazy(pos token.Pos, typ Type, targs []Type, verify bool) (res Type) { @@ -25,3 +128,85 @@ func (check *Checker) InstantiateLazy(pos token.Pos, typ Type, targs []Type, ver verify: verify, } } + +// satisfies reports whether the type argument targ satisfies the constraint of type parameter +// parameter tpar (after any of its type parameters have been substituted through smap). +// A suitable error is reported if the result is false. +// TODO(gri) This should be a method of interfaces or type sets. +func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap *substMap) bool { + iface := tpar.Bound() + if iface.Empty() { + return true // no type bound + } + + // The type parameter bound is parameterized with the same type parameters + // as the instantiated type; before we can use it for bounds checking we + // need to instantiate it with the type arguments with which we instantiate + // the parameterized type. + iface = check.subst(pos, iface, smap).(*Interface) + + // targ must implement iface (methods) + // - check only if we have methods + if iface.NumMethods() > 0 { + // If the type argument is a pointer to a type parameter, the type argument's + // method set is empty. + // TODO(gri) is this what we want? (spec question) + if base, isPtr := deref(targ); isPtr && asTypeParam(base) != nil { + check.errorf(atPos(pos), 0, "%s has no methods", targ) + return false + } + if m, wrong := check.missingMethod(targ, iface, true); m != nil { + // TODO(gri) needs to print updated name to avoid major confusion in error message! + // (print warning for now) + // Old warning: + // check.softErrorf(pos, "%s does not satisfy %s (warning: name not updated) = %s (missing method %s)", targ, tpar.bound, iface, m) + if m.name == "==" { + // We don't want to report "missing method ==". + check.softErrorf(atPos(pos), 0, "%s does not satisfy comparable", targ) + } else if wrong != nil { + // TODO(gri) This can still report uninstantiated types which makes the error message + // more difficult to read then necessary. + // TODO(rFindley) should this use parentheses rather than ':' for qualification? + check.softErrorf(atPos(pos), _Todo, + "%s does not satisfy %s: wrong method signature\n\tgot %s\n\twant %s", + targ, tpar.bound, wrong, m, + ) + } else { + check.softErrorf(atPos(pos), 0, "%s does not satisfy %s (missing method %s)", targ, tpar.bound, m.name) + } + return false + } + } + + // targ's underlying type must also be one of the interface types listed, if any + if iface.typeSet().types == nil { + return true // nothing to do + } + + // If targ is itself a type parameter, each of its possible types, but at least one, must be in the + // list of iface types (i.e., the targ type list must be a non-empty subset of the iface types). + if targ := asTypeParam(targ); targ != nil { + targBound := targ.Bound() + if targBound.typeSet().types == nil { + check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ) + return false + } + return iface.is(func(typ Type, tilde bool) bool { + // TODO(gri) incorporate tilde information! + if !iface.isSatisfiedBy(typ) { + // TODO(gri) match this error message with the one below (or vice versa) + check.softErrorf(atPos(pos), 0, "%s does not satisfy %s (%s type constraint %s not found in %s)", targ, tpar.bound, targ, typ, iface.typeSet().types) + return false + } + return true + }) + } + + // Otherwise, targ's type or underlying type must also be one of the interface types listed, if any. + if !iface.isSatisfiedBy(targ) { + check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s not found in %s)", targ, tpar.bound, targ, iface.typeSet().types) + return false + } + + return true +} diff --git a/src/go/types/subst.go b/src/go/types/subst.go index d367369158..ec85a6bfc4 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -2,9 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// This file implements instantiation of generic types -// through substitution of type parameters by actual -// types. +// This file implements type parameter substitution. package types @@ -56,188 +54,6 @@ func (m *substMap) lookup(tpar *TypeParam) Type { return tpar } -// Instantiate instantiates the type typ with the given type arguments -// targs. To check type constraint satisfaction, verify must be set. -// pos and posList correspond to the instantiation and type argument -// positions respectively; posList may be nil or shorter than the number -// of type arguments provided. -// typ must be a *Named or a *Signature type, and its number of type -// parameters must match the number of provided type arguments. -// The receiver (check) may be nil if and only if verify is not set. -// The result is a new, instantiated (not generic) type of the same kind -// (either a *Named or a *Signature). -// Any methods attached to a *Named are simply copied; they are not -// instantiated. -func (check *Checker) Instantiate(pos token.Pos, typ Type, targs []Type, posList []token.Pos, verify bool) (res Type) { - if verify && check == nil { - panic("cannot have nil receiver if verify is set") - } - - if check != nil && trace { - check.trace(pos, "-- instantiating %s with %s", typ, typeListString(targs)) - check.indent++ - defer func() { - check.indent-- - var under Type - if res != nil { - // Calling under() here may lead to endless instantiations. - // Test case: type T[P any] T[P] - // TODO(gri) investigate if that's a bug or to be expected. - under = res.Underlying() - } - check.trace(pos, "=> %s (under = %s)", res, under) - }() - } - - assert(len(posList) <= len(targs)) - - // TODO(gri) What is better here: work with TypeParams, or work with TypeNames? - var tparams []*TypeName - switch t := typ.(type) { - case *Named: - tparams = t.TParams() - case *Signature: - tparams = t.tparams - defer func() { - // If we had an unexpected failure somewhere don't panic below when - // asserting res.(*Signature). Check for *Signature in case Typ[Invalid] - // is returned. - if _, ok := res.(*Signature); !ok { - return - } - // If the signature doesn't use its type parameters, subst - // will not make a copy. In that case, make a copy now (so - // we can set tparams to nil w/o causing side-effects). - if t == res { - copy := *t - res = © - } - // After instantiating a generic signature, it is not generic - // anymore; we need to set tparams to nil. - res.(*Signature).tparams = nil - }() - default: - // only types and functions can be generic - panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) - } - - // the number of supplied types must match the number of type parameters - if len(targs) != len(tparams) { - // TODO(gri) provide better error message - if check != nil { - check.errorf(atPos(pos), _Todo, "got %d arguments but %d type parameters", len(targs), len(tparams)) - return Typ[Invalid] - } - panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, len(targs), len(tparams))) - } - - if len(tparams) == 0 { - return typ // nothing to do (minor optimization) - } - - smap := makeSubstMap(tparams, targs) - - // check bounds - if verify { - for i, tname := range tparams { - // best position for error reporting - pos := pos - if i < len(posList) { - pos = posList[i] - } - - // stop checking bounds after the first failure - if !check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap) { - break - } - } - } - - return check.subst(pos, typ, smap) -} - -// satisfies reports whether the type argument targ satisfies the constraint of type parameter -// parameter tpar (after any of its type parameters have been substituted through smap). -// A suitable error is reported if the result is false. -// TODO(gri) This should be a method of interfaces or type sets. -func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap *substMap) bool { - iface := tpar.Bound() - if iface.Empty() { - return true // no type bound - } - - // The type parameter bound is parameterized with the same type parameters - // as the instantiated type; before we can use it for bounds checking we - // need to instantiate it with the type arguments with which we instantiate - // the parameterized type. - iface = check.subst(pos, iface, smap).(*Interface) - - // targ must implement iface (methods) - // - check only if we have methods - if iface.NumMethods() > 0 { - // If the type argument is a pointer to a type parameter, the type argument's - // method set is empty. - // TODO(gri) is this what we want? (spec question) - if base, isPtr := deref(targ); isPtr && asTypeParam(base) != nil { - check.errorf(atPos(pos), 0, "%s has no methods", targ) - return false - } - if m, wrong := check.missingMethod(targ, iface, true); m != nil { - // TODO(gri) needs to print updated name to avoid major confusion in error message! - // (print warning for now) - // Old warning: - // check.softErrorf(pos, "%s does not satisfy %s (warning: name not updated) = %s (missing method %s)", targ, tpar.bound, iface, m) - if m.name == "==" { - // We don't want to report "missing method ==". - check.softErrorf(atPos(pos), 0, "%s does not satisfy comparable", targ) - } else if wrong != nil { - // TODO(gri) This can still report uninstantiated types which makes the error message - // more difficult to read then necessary. - // TODO(rFindley) should this use parentheses rather than ':' for qualification? - check.softErrorf(atPos(pos), _Todo, - "%s does not satisfy %s: wrong method signature\n\tgot %s\n\twant %s", - targ, tpar.bound, wrong, m, - ) - } else { - check.softErrorf(atPos(pos), 0, "%s does not satisfy %s (missing method %s)", targ, tpar.bound, m.name) - } - return false - } - } - - // targ's underlying type must also be one of the interface types listed, if any - if iface.typeSet().types == nil { - return true // nothing to do - } - - // If targ is itself a type parameter, each of its possible types, but at least one, must be in the - // list of iface types (i.e., the targ type list must be a non-empty subset of the iface types). - if targ := asTypeParam(targ); targ != nil { - targBound := targ.Bound() - if targBound.typeSet().types == nil { - check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ) - return false - } - return iface.is(func(typ Type, tilde bool) bool { - // TODO(gri) incorporate tilde information! - if !iface.isSatisfiedBy(typ) { - // TODO(gri) match this error message with the one below (or vice versa) - check.softErrorf(atPos(pos), 0, "%s does not satisfy %s (%s type constraint %s not found in %s)", targ, tpar.bound, targ, typ, iface.typeSet().types) - return false - } - return true - }) - } - - // Otherwise, targ's type or underlying type must also be one of the interface types listed, if any. - if !iface.isSatisfiedBy(targ) { - check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s not found in %s)", targ, tpar.bound, targ, iface.typeSet().types) - return false - } - - return true -} - // subst returns the type typ with its type parameters tpars replaced by // the corresponding type arguments targs, recursively. // subst is functional in the sense that it doesn't modify the incoming -- GitLab From 22f39ba208189413440671c63baca7173d1d4774 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 19:58:59 -0400 Subject: [PATCH 0483/2500] [dev.typeparams] go/types: use InstantiateLazy to create instance types (cleanup) This is a port of CL 333669 to go/types, adjusted for the position and IndexExpr APIs, and excluding the noder changes. Change-Id: I3ac4bbf271947c3cf80ab04c462a91657316f4fe Reviewed-on: https://go-review.googlesource.com/c/go/+/335073 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/instance.go | 4 ++-- src/go/types/instantiate.go | 16 +++++++------ src/go/types/typexpr.go | 45 +++++++++++++------------------------ 3 files changed, 27 insertions(+), 38 deletions(-) diff --git a/src/go/types/instance.go b/src/go/types/instance.go index 143ba693a6..25f1442881 100644 --- a/src/go/types/instance.go +++ b/src/go/types/instance.go @@ -15,7 +15,7 @@ type instance struct { pos token.Pos // position of type instantiation; for error reporting only base *Named // parameterized type to be instantiated targs []Type // type arguments - poslist []token.Pos // position of each targ; for error reporting only + posList []token.Pos // position of each targ; for error reporting only verify bool // if set, constraint satisfaction is verified value Type // base[targs...] after instantiation or Typ[Invalid]; nil if not yet set } @@ -26,7 +26,7 @@ type instance struct { func (t *instance) expand() Type { v := t.value if v == nil { - v = t.check.Instantiate(t.pos, t.base, t.targs, t.poslist, t.verify) + v = t.check.Instantiate(t.pos, t.base, t.targs, t.posList, t.verify) if v == nil { v = Typ[Invalid] } diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 55e34ca0c1..99ffb9e604 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -113,19 +113,21 @@ func (check *Checker) Instantiate(pos token.Pos, typ Type, targs []Type, posList } // InstantiateLazy is like Instantiate, but avoids actually -// instantiating the type until needed. -func (check *Checker) InstantiateLazy(pos token.Pos, typ Type, targs []Type, verify bool) (res Type) { +// instantiating the type until needed. typ must be a *Named +// type. +func (check *Checker) InstantiateLazy(pos token.Pos, typ Type, targs []Type, posList []token.Pos, verify bool) Type { base := asNamed(typ) if base == nil { panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } return &instance{ - check: check, - pos: pos, - base: base, - targs: targs, - verify: verify, + check: check, + pos: pos, + base: base, + targs: targs, + posList: posList, + verify: verify, } } diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index e93c50a087..9a9fe32cb3 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -264,7 +264,7 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) { case *ast.IndexExpr, *ast.MultiIndexExpr: ix := typeparams.UnpackIndexExpr(e) // TODO(rfindley): type instantiation should require go1.18 - return check.instantiatedType(ix, def) + return check.instantiatedType(ix.X, ix.Indices, def) case *ast.ParenExpr: // Generic types must be instantiated before they can be used in any form. @@ -400,45 +400,32 @@ func (check *Checker) typeOrNil(e ast.Expr) Type { return Typ[Invalid] } -func (check *Checker) instantiatedType(ix *typeparams.IndexExpr, def *Named) Type { - b := check.genericType(ix.X, true) // TODO(gri) what about cycles? - if b == Typ[Invalid] { - return b // error already reported +func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named) Type { + base := check.genericType(x, true) + if base == Typ[Invalid] { + return base // error already reported } - base := asNamed(b) - if base == nil { - unreachable() // should have been caught by genericType - } - - // create a new type instance rather than instantiate the type - // TODO(gri) should do argument number check here rather than - // when instantiating the type? - // TODO(gri) use InstantiateLazy here (cleanup) - typ := new(instance) - def.setUnderlying(typ) - typ.check = check - typ.pos = ix.X.Pos() - typ.base = base - typ.verify = true - - // evaluate arguments (always) - typ.targs = check.typeList(ix.Indices) - if typ.targs == nil { + // evaluate arguments + targs := check.typeList(targsx) + if targs == nil { def.setUnderlying(Typ[Invalid]) // avoid later errors due to lazy instantiation return Typ[Invalid] } - // determine argument positions (for error reporting) - typ.poslist = make([]token.Pos, len(ix.Indices)) - for i, arg := range ix.Indices { - typ.poslist[i] = arg.Pos() + // determine argument positions + posList := make([]token.Pos, len(targs)) + for i, arg := range targsx { + posList[i] = arg.Pos() } + typ := check.InstantiateLazy(x.Pos(), base, targs, posList, true) + def.setUnderlying(typ) + // make sure we check instantiation works at least once // and that the resulting type is valid check.later(func() { - t := typ.expand() + t := typ.(*instance).expand() check.validType(t, nil) }) -- GitLab From 796ac6d5f24f725794a3620d767d30c52f232a60 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 20:07:01 -0400 Subject: [PATCH 0484/2500] [dev.typeparams] go/types: move methods on *Named into named.go This is a port of CL 333671 to go/types. Change-Id: Ic2f66b49f1db68fb93d5095131733e99a37b9cbf Reviewed-on: https://go-review.googlesource.com/c/go/+/335074 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/decl.go | 96 ----------------------------------------- src/go/types/named.go | 99 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 96 deletions(-) diff --git a/src/go/types/decl.go b/src/go/types/decl.go index d68070d049..8fae59ffe8 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -569,102 +569,6 @@ func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init ast.Expr) { check.initVars(lhs, []ast.Expr{init}, token.NoPos) } -// under returns the expanded underlying type of n0; possibly by following -// forward chains of named types. If an underlying type is found, resolve -// the chain by setting the underlying type for each defined type in the -// chain before returning it. If no underlying type is found or a cycle -// is detected, the result is Typ[Invalid]. If a cycle is detected and -// n0.check != nil, the cycle is reported. -func (n0 *Named) under() Type { - u := n0.Underlying() - - if u == Typ[Invalid] { - return u - } - - // If the underlying type of a defined type is not a defined - // (incl. instance) type, then that is the desired underlying - // type. - switch u.(type) { - case nil: - return Typ[Invalid] - default: - // common case - return u - case *Named, *instance: - // handled below - } - - if n0.check == nil { - panic("internal error: Named.check == nil but type is incomplete") - } - - // Invariant: after this point n0 as well as any named types in its - // underlying chain should be set up when this function exits. - check := n0.check - - // If we can't expand u at this point, it is invalid. - n := asNamed(u) - if n == nil { - n0.underlying = Typ[Invalid] - return n0.underlying - } - - // Otherwise, follow the forward chain. - seen := map[*Named]int{n0: 0} - path := []Object{n0.obj} - for { - u = n.Underlying() - if u == nil { - u = Typ[Invalid] - break - } - var n1 *Named - switch u1 := u.(type) { - case *Named: - n1 = u1 - case *instance: - n1, _ = u1.expand().(*Named) - if n1 == nil { - u = Typ[Invalid] - } - } - if n1 == nil { - break // end of chain - } - - seen[n] = len(seen) - path = append(path, n.obj) - n = n1 - - if i, ok := seen[n]; ok { - // cycle - check.cycleError(path[i:]) - u = Typ[Invalid] - break - } - } - - for n := range seen { - // We should never have to update the underlying type of an imported type; - // those underlying types should have been resolved during the import. - // Also, doing so would lead to a race condition (was issue #31749). - // Do this check always, not just in debug mode (it's cheap). - if n.obj.pkg != check.pkg { - panic("internal error: imported type with unresolved underlying type") - } - n.underlying = u - } - - return u -} - -func (n *Named) setUnderlying(typ Type) { - if n != nil { - n.underlying = typ - } -} - func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { assert(obj.typ == nil) diff --git a/src/go/types/named.go b/src/go/types/named.go index 8f2e8706a1..4511f395e0 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -142,3 +142,102 @@ func (t *Named) AddMethod(m *Func) { func (t *Named) Underlying() Type { return t.expand().underlying } func (t *Named) String() string { return TypeString(t, nil) } + +// ---------------------------------------------------------------------------- +// Implementation + +// under returns the expanded underlying type of n0; possibly by following +// forward chains of named types. If an underlying type is found, resolve +// the chain by setting the underlying type for each defined type in the +// chain before returning it. If no underlying type is found or a cycle +// is detected, the result is Typ[Invalid]. If a cycle is detected and +// n0.check != nil, the cycle is reported. +func (n0 *Named) under() Type { + u := n0.Underlying() + + if u == Typ[Invalid] { + return u + } + + // If the underlying type of a defined type is not a defined + // (incl. instance) type, then that is the desired underlying + // type. + switch u.(type) { + case nil: + return Typ[Invalid] + default: + // common case + return u + case *Named, *instance: + // handled below + } + + if n0.check == nil { + panic("internal error: Named.check == nil but type is incomplete") + } + + // Invariant: after this point n0 as well as any named types in its + // underlying chain should be set up when this function exits. + check := n0.check + + // If we can't expand u at this point, it is invalid. + n := asNamed(u) + if n == nil { + n0.underlying = Typ[Invalid] + return n0.underlying + } + + // Otherwise, follow the forward chain. + seen := map[*Named]int{n0: 0} + path := []Object{n0.obj} + for { + u = n.Underlying() + if u == nil { + u = Typ[Invalid] + break + } + var n1 *Named + switch u1 := u.(type) { + case *Named: + n1 = u1 + case *instance: + n1, _ = u1.expand().(*Named) + if n1 == nil { + u = Typ[Invalid] + } + } + if n1 == nil { + break // end of chain + } + + seen[n] = len(seen) + path = append(path, n.obj) + n = n1 + + if i, ok := seen[n]; ok { + // cycle + check.cycleError(path[i:]) + u = Typ[Invalid] + break + } + } + + for n := range seen { + // We should never have to update the underlying type of an imported type; + // those underlying types should have been resolved during the import. + // Also, doing so would lead to a race condition (was issue #31749). + // Do this check always, not just in debug mode (it's cheap). + if n.obj.pkg != check.pkg { + panic("internal error: imported type with unresolved underlying type") + } + n.underlying = u + } + + return u +} + +func (n *Named) setUnderlying(typ Type) { + if n != nil { + n.underlying = typ + } +} -- GitLab From d6d7f8458e9e4360d7b0a4e42c5c850ae27bac8d Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 20:16:27 -0400 Subject: [PATCH 0485/2500] [dev.typeparams] go/types: implement <-ch where ch is of type parameter type This is a port of CL 333709 to go/types, adjusted for the different error API. Fixes #43671 Change-Id: Ifd340149bfbcabe401cec74398cb83f2ae812e51 Reviewed-on: https://go-review.googlesource.com/c/go/+/335075 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/expr.go | 36 +++++++++--- .../types/testdata/fixedbugs/issue43671.go2 | 58 +++++++++++++++++++ 2 files changed, 85 insertions(+), 9 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue43671.go2 diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 46f6e33463..751a360890 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -144,6 +144,14 @@ var op2str2 = [...]string{ token.SHL: "shift", } +func underIs(typ Type, f func(Type) bool) bool { + u := under(typ) + if tpar, _ := u.(*TypeParam); tpar != nil { + return tpar.underIs(f) + } + return f(u) +} + // The unary expression e may be nil. It's passed in for better error messages only. func (check *Checker) unary(x *operand, e *ast.UnaryExpr) { check.expr(x, e.X) @@ -164,19 +172,29 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr) { return case token.ARROW: - typ := asChan(x.typ) - if typ == nil { - check.invalidOp(x, _InvalidReceive, "cannot receive from non-channel %s", x) - x.mode = invalid - return - } - if typ.dir == SendOnly { - check.invalidOp(x, _InvalidReceive, "cannot receive from send-only channel %s", x) + var elem Type + if !underIs(x.typ, func(u Type) bool { + ch, _ := u.(*Chan) + if ch == nil { + check.invalidOp(x, _InvalidReceive, "cannot receive from non-channel %s", x) + return false + } + if ch.dir == SendOnly { + check.invalidOp(x, _InvalidReceive, "cannot receive from send-only channel %s", x) + return false + } + if elem != nil && !Identical(ch.elem, elem) { + check.invalidOp(x, _Todo, "channels of %s must have the same element type", x) + return false + } + elem = ch.elem + return true + }) { x.mode = invalid return } x.mode = commaok - x.typ = typ.elem + x.typ = elem check.hasCallOrRecv = true return } diff --git a/src/go/types/testdata/fixedbugs/issue43671.go2 b/src/go/types/testdata/fixedbugs/issue43671.go2 new file mode 100644 index 0000000000..6cc3801cc9 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue43671.go2 @@ -0,0 +1,58 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type C0 interface{ int } +type C1 interface{ chan int } +type C2 interface{ chan int | <-chan int } +type C3 interface{ chan int | chan float32 } +type C4 interface{ chan int | chan<- int } +type C5[T any] interface{ ~chan T | <-chan T } + +func _[T any](ch T) { + <-ch // ERROR cannot receive from non-channel +} + +func _[T C0](ch T) { + <-ch // ERROR cannot receive from non-channel +} + +func _[T C1](ch T) { + <-ch +} + +func _[T C2](ch T) { + <-ch +} + +func _[T C3](ch T) { + <-ch // ERROR channels of ch .* must have the same element type +} + +func _[T C4](ch T) { + <-ch // ERROR cannot receive from send-only channel +} + +func _[T C5[X], X any](ch T, x X) { + x = <-ch +} + +// test case from issue, slightly modified +type RecvChan[T any] interface { + ~chan T | ~<-chan T +} + +func _[T any, C RecvChan[T]](ch C) T { + return <-ch +} + +func f[T any, C interface{ chan T }](ch C) T { + return <-ch +} + +func _(ch chan int) { + var x int = f(ch) // test constraint type inference for this case + _ = x +} -- GitLab From 19b4142f240172d525f81d1b4efb5679f147b474 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 20:22:59 -0400 Subject: [PATCH 0486/2500] [dev.typeparams] go/types: implement ch <- x where ch is of type parameter type This is a port of CL 333712 to go/types, adjusted for the different error reporting API and to position errors on the arrows. Fixes #43671 Change-Id: I7d2de249e86d272c89a046f60e632e75848ff865 Reviewed-on: https://go-review.googlesource.com/c/go/+/335076 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/stmt.go | 36 ++++++++++------- .../types/testdata/fixedbugs/issue47115.go2 | 40 +++++++++++++++++++ 2 files changed, 62 insertions(+), 14 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue47115.go2 diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index 53fccb0a64..0f0a2e4d9f 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -361,25 +361,33 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { check.errorf(&x, code, "%s %s", &x, msg) case *ast.SendStmt: - var ch, x operand + var ch, val operand check.expr(&ch, s.Chan) - check.expr(&x, s.Value) - if ch.mode == invalid || x.mode == invalid { + check.expr(&val, s.Value) + if ch.mode == invalid || val.mode == invalid { return } - - tch := asChan(ch.typ) - if tch == nil { - check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "cannot send to non-chan type %s", ch.typ) - return - } - - if tch.dir == RecvOnly { - check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "cannot send to receive-only type %s", tch) + var elem Type + if !underIs(ch.typ, func(u Type) bool { + uch, _ := u.(*Chan) + if uch == nil { + check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "cannot send to non-channel %s", &ch) + return false + } + if uch.dir == RecvOnly { + check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "cannot send to receive-only channel %s", &ch) + return false + } + if elem != nil && !Identical(uch.elem, elem) { + check.invalidOp(inNode(s, s.Arrow), _Todo, "channels of %s must have the same element type", &ch) + return false + } + elem = uch.elem + return true + }) { return } - - check.assignment(&x, tch.elem, "send") + check.assignment(&val, elem, "send") case *ast.IncDecStmt: var op token.Token diff --git a/src/go/types/testdata/fixedbugs/issue47115.go2 b/src/go/types/testdata/fixedbugs/issue47115.go2 new file mode 100644 index 0000000000..6694219b54 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue47115.go2 @@ -0,0 +1,40 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type C0 interface{ int } +type C1 interface{ chan int } +type C2 interface{ chan int | <-chan int } +type C3 interface{ chan int | chan float32 } +type C4 interface{ chan int | chan<- int } +type C5[T any] interface{ ~chan T | chan<- T } + +func _[T any](ch T) { + ch <- /* ERROR cannot send to non-channel */ 0 +} + +func _[T C0](ch T) { + ch <- /* ERROR cannot send to non-channel */ 0 +} + +func _[T C1](ch T) { + ch <- 0 +} + +func _[T C2](ch T) { + ch <-/* ERROR cannot send to receive-only channel */ 0 +} + +func _[T C3](ch T) { + ch <- /* ERROR channels of ch .* must have the same element type */ 0 +} + +func _[T C4](ch T) { + ch <- 0 +} + +func _[T C5[X], X any](ch T, x X) { + ch <- x +} -- GitLab From cf7e66b7d4c74f45a767068c926ff74c76231f5f Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 20:30:45 -0400 Subject: [PATCH 0487/2500] [dev.typeparams] go/types: implement close(ch) where ch is of type parameter type This is a port of CL 333713 to go/types. Change-Id: I517f52592f65cc76e11a12d9148b20c12d9e3e81 Reviewed-on: https://go-review.googlesource.com/c/go/+/335077 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/builtins.go | 22 ++++++---- src/go/types/testdata/check/builtins.go2 | 55 ++++++++++++++++++++---- src/go/types/testdata/check/builtins.src | 2 +- src/go/types/type.go | 10 ----- 4 files changed, 61 insertions(+), 28 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 2573bac69e..c8348f4259 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -217,19 +217,23 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b case _Close: // close(c) - c := asChan(x.typ) - if c == nil { - check.invalidArg(x, _InvalidClose, "%s is not a channel", x) - return - } - if c.dir == RecvOnly { - check.invalidArg(x, _InvalidClose, "%s must not be a receive-only channel", x) + if !underIs(x.typ, func(u Type) bool { + uch, _ := u.(*Chan) + if uch == nil { + check.invalidOp(x, _InvalidClose, "cannot close non-channel %s", x) + return false + } + if uch.dir == RecvOnly { + check.invalidOp(x, _InvalidClose, "cannot close receive-only channel %s", x) + return false + } + return true + }) { return } - x.mode = novalue if check.Types != nil { - check.recordBuiltinType(call.Fun, makeSig(nil, c)) + check.recordBuiltinType(call.Fun, makeSig(nil, x.typ)) } case _Complex: diff --git a/src/go/types/testdata/check/builtins.go2 b/src/go/types/testdata/check/builtins.go2 index 5bb67efec9..71295bf434 100644 --- a/src/go/types/testdata/check/builtins.go2 +++ b/src/go/types/testdata/check/builtins.go2 @@ -6,6 +6,45 @@ package builtins +// close + +type C0 interface{ int } +type C1 interface{ chan int } +type C2 interface{ chan int | <-chan int } +type C3 interface{ chan int | chan float32 } +type C4 interface{ chan int | chan<- int } +type C5[T any] interface{ ~chan T | chan<- T } + +func _[T any](ch T) { + close(ch /* ERROR cannot close non-channel */) +} + +func _[T C0](ch T) { + close(ch /* ERROR cannot close non-channel */) +} + +func _[T C1](ch T) { + close(ch) +} + +func _[T C2](ch T) { + close(ch /* ERROR cannot close receive-only channel */) +} + +func _[T C3](ch T) { + close(ch) +} + +func _[T C4](ch T) { + close(ch) +} + +func _[T C5[X], X any](ch T) { + close(ch) +} + +// make + type Bmc interface { ~map[rune]string | ~chan int } @@ -22,31 +61,31 @@ type Bss interface { ~[]int | ~[]string } -func _[T any] () { - _ = make(T /* ERROR invalid argument */ ) - _ = make(T /* ERROR invalid argument */ , 10) - _ = make(T /* ERROR invalid argument */ , 10, 20) +func _[T any]() { + _ = make(T /* ERROR invalid argument */) + _ = make(T /* ERROR invalid argument */, 10) + _ = make(T /* ERROR invalid argument */, 10, 20) } -func _[T Bmc] () { +func _[T Bmc]() { _ = make(T) _ = make(T, 10) _ = make /* ERROR expects 1 or 2 arguments */ (T, 10, 20) } -func _[T Bms] () { +func _[T Bms]() { _ = make /* ERROR expects 2 arguments */ (T) _ = make(T, 10) _ = make /* ERROR expects 2 arguments */ (T, 10, 20) } -func _[T Bcs] () { +func _[T Bcs]() { _ = make /* ERROR expects 2 arguments */ (T) _ = make(T, 10) _ = make /* ERROR expects 2 arguments */ (T, 10, 20) } -func _[T Bss] () { +func _[T Bss]() { _ = make /* ERROR expects 2 or 3 arguments */ (T) _ = make(T, 10) _ = make(T, 10, 20) diff --git a/src/go/types/testdata/check/builtins.src b/src/go/types/testdata/check/builtins.src index 3707528914..7fd6a4b032 100644 --- a/src/go/types/testdata/check/builtins.src +++ b/src/go/types/testdata/check/builtins.src @@ -144,7 +144,7 @@ func close1() { var r <-chan int close() // ERROR not enough arguments close(1, 2) // ERROR too many arguments - close(42 /* ERROR not a channel */) + close(42 /* ERROR cannot close non-channel */) close(r /* ERROR receive-only channel */) close(c) _ = close /* ERROR used as value */ (c) diff --git a/src/go/types/type.go b/src/go/types/type.go index e0498fece2..bbb7100ef4 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -105,11 +105,6 @@ func asPointer(t Type) *Pointer { return op } -func asTuple(t Type) *Tuple { - op, _ := optype(t).(*Tuple) - return op -} - func asSignature(t Type) *Signature { op, _ := optype(t).(*Signature) return op @@ -120,11 +115,6 @@ func asMap(t Type) *Map { return op } -func asChan(t Type) *Chan { - op, _ := optype(t).(*Chan) - return op -} - // If the argument to asInterface, asNamed, or asTypeParam is of the respective type // (possibly after expanding an instance type), these methods return that type. // Otherwise the result is nil. -- GitLab From b3d91e3a24f95a6a5906dab28c3392a542ccc81c Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 20:34:00 -0400 Subject: [PATCH 0488/2500] [dev.typeparams] go/types: implement delete(m, k) where m is of type parameter type This is a port of CL 333729 to go/types. Change-Id: I8682f549a7a15124b1b338f8c73e83a57d138368 Reviewed-on: https://go-review.googlesource.com/c/go/+/335078 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/builtins.go | 27 +++++++++++++---- src/go/types/testdata/check/builtins.go2 | 37 ++++++++++++++++++++++++ src/go/types/type.go | 5 ---- 3 files changed, 58 insertions(+), 11 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index c8348f4259..eb3503fd6b 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -369,25 +369,40 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b x.typ = Typ[Int] case _Delete: - // delete(m, k) - m := asMap(x.typ) - if m == nil { - check.invalidArg(x, _InvalidDelete, "%s is not a map", x) + // delete(map_, key) + // map_ must be a map type or a type parameter describing map types. + // The key cannot be a type parameter for now. + map_ := x.typ + var key Type + if !underIs(map_, func(u Type) bool { + map_, _ := u.(*Map) + if map_ == nil { + check.invalidArg(x, _InvalidDelete, "%s is not a map", x) + return false + } + if key != nil && !Identical(map_.key, key) { + check.invalidArg(x, _Todo, "maps of %s must have identical key types", x) + return false + } + key = map_.key + return true + }) { return } + arg(x, 1) // k if x.mode == invalid { return } - check.assignment(x, m.key, "argument to delete") + check.assignment(x, key, "argument to delete") if x.mode == invalid { return } x.mode = novalue if check.Types != nil { - check.recordBuiltinType(call.Fun, makeSig(nil, m, m.key)) + check.recordBuiltinType(call.Fun, makeSig(nil, map_, key)) } case _Imag, _Real: diff --git a/src/go/types/testdata/check/builtins.go2 b/src/go/types/testdata/check/builtins.go2 index 71295bf434..8fe6d7b332 100644 --- a/src/go/types/testdata/check/builtins.go2 +++ b/src/go/types/testdata/check/builtins.go2 @@ -43,6 +43,43 @@ func _[T C5[X], X any](ch T) { close(ch) } +// delete + +type M0 interface{ int } +type M1 interface{ map[string]int } +type M2 interface { map[string]int | map[string]float64 } +type M3 interface{ map[string]int | map[rune]int } +type M4[K comparable, V any] interface{ map[K]V | map[rune]V } + +func _[T any](m T) { + delete(m /* ERROR not a map */, "foo") +} + +func _[T M0](m T) { + delete(m /* ERROR not a map */, "foo") +} + +func _[T M1](m T) { + delete(m, "foo") +} + +func _[T M2](m T) { + delete(m, "foo") + delete(m, 0 /* ERROR cannot use .* as string */) +} + +func _[T M3](m T) { + delete(m /* ERROR must have identical key types */, "foo") +} + +func _[T M4[rune, V], V any](m T) { + delete(m, 'k') +} + +func _[T M4[K, V], K comparable, V any](m T) { + delete(m /* ERROR must have identical key types */, "foo") +} + // make type Bmc interface { diff --git a/src/go/types/type.go b/src/go/types/type.go index bbb7100ef4..b575b11e4e 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -110,11 +110,6 @@ func asSignature(t Type) *Signature { return op } -func asMap(t Type) *Map { - op, _ := optype(t).(*Map) - return op -} - // If the argument to asInterface, asNamed, or asTypeParam is of the respective type // (possibly after expanding an instance type), these methods return that type. // Otherwise the result is nil. -- GitLab From baeabf3b366fad1eae113f8334451906dac61c0d Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 20:40:58 -0400 Subject: [PATCH 0489/2500] [dev.typeparams] go/types: cleanups around receiver type checks This is a port of CL 333770 to go/types, adjusted for the error reporting API and to not support compiler error messages. An error message changed (to 'invalid receiver type' from just 'invalid receiver'), so a test had to be adjusted. Change-Id: I166e8831d8c9f98ebfb0270fe5221586fc112825 Reviewed-on: https://go-review.googlesource.com/c/go/+/335079 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/signature.go | 34 ++++++++++++------- src/go/types/testdata/examples/methods.go2 | 17 ++++++++++ .../types/testdata/fixedbugs/issue28251.src | 2 +- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/src/go/types/signature.go b/src/go/types/signature.go index 85a735120f..da01ec801a 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -199,30 +199,40 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast // spec: "The receiver type must be of the form T or *T where T is a type name." // (ignore invalid types - error was reported before) - if t := rtyp; t != Typ[Invalid] { + if rtyp != Typ[Invalid] { var err string - if T := asNamed(t); T != nil { + switch T := rtyp.(type) { + case *Named: // spec: "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." if T.obj.pkg != check.pkg { err = "type not defined in this package" } else { - switch u := optype(T).(type) { - case *Basic: - // unsafe.Pointer is treated like a regular pointer - if u.kind == UnsafePointer { - err = "unsafe.Pointer" + // The underlying type of a receiver base type can be a type parameter; + // e.g. for methods with a generic receiver T[P] with type T[P any] P. + underIs(T, func(u Type) bool { + switch u := u.(type) { + case *Basic: + // unsafe.Pointer is treated like a regular pointer + if u.kind == UnsafePointer { + err = "unsafe.Pointer" + return false + } + case *Pointer, *Interface: + err = "pointer or interface type" + return false } - case *Pointer, *Interface: - err = "pointer or interface type" - } + return true + }) } - } else { + case *Basic: err = "basic or unnamed type" + default: + check.errorf(recv, _InvalidRecv, "invalid receiver type %s", recv.typ) } if err != "" { - check.errorf(recv, _InvalidRecv, "invalid receiver %s (%s)", recv.typ, err) + check.errorf(recv, _InvalidRecv, "invalid receiver type %s (%s)", recv.typ, err) // ok to continue } } diff --git a/src/go/types/testdata/examples/methods.go2 b/src/go/types/testdata/examples/methods.go2 index 76c6539e1b..4e87041e54 100644 --- a/src/go/types/testdata/examples/methods.go2 +++ b/src/go/types/testdata/examples/methods.go2 @@ -6,6 +6,8 @@ package p +import "unsafe" + // Parameterized types may have methods. type T1[A any] struct{ a A } @@ -94,3 +96,18 @@ func (_ T2[_, _, _]) _() int { return 42 } type T0 struct{} func (T0) _() {} func (T1[A]) _() {} + +// A generic receiver type may constrain its type parameter such +// that it must be a pointer type. Such receiver types are not +// permitted. +type T3a[P interface{ ~int | ~string | ~float64 }] P + +func (T3a[_]) m() {} // this is ok + +type T3b[P interface{ ~unsafe.Pointer }] P + +func (T3b /* ERROR invalid receiver */ [_]) m() {} + +type T3c[P interface{ *int | *string }] P + +func (T3c /* ERROR invalid receiver */ [_]) m() {} diff --git a/src/go/types/testdata/fixedbugs/issue28251.src b/src/go/types/testdata/fixedbugs/issue28251.src index cd79e0e8b5..ef5e61df47 100644 --- a/src/go/types/testdata/fixedbugs/issue28251.src +++ b/src/go/types/testdata/fixedbugs/issue28251.src @@ -60,6 +60,6 @@ type ( T11 = T ) -func (T9 /* ERROR invalid receiver \*\*T */ ) m9() {} +func (T9 /* ERROR invalid receiver type \*\*T */ ) m9() {} func _() { (T{}).m9 /* ERROR has no field or method m9 */ () } func _() { (&T{}).m9 /* ERROR has no field or method m9 */ () } -- GitLab From 62f6f130fe1c6cbe9d2c1ea5160e83fb1cfa208a Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 20:46:39 -0400 Subject: [PATCH 0490/2500] [dev.typeparams] go/types: interface identity must consider full type set This is a port of CL 333889 to go/types. Change-Id: I66cefb81a33f4677efc18c1ca923ded374a87f12 Reviewed-on: https://go-review.googlesource.com/c/go/+/335080 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/predicates.go | 17 +++++++++++++---- src/go/types/unify.go | 12 ++++++++---- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index c9be121839..ea2bed720a 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -270,12 +270,21 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { } case *Interface: + // Two interface types are identical if they describe the same type sets. + // With the existing implementation restriction, this simplifies to: + // // Two interface types are identical if they have the same set of methods with - // the same names and identical function types. Lower-case method names from - // different packages are always different. The order of the methods is irrelevant. + // the same names and identical function types, and if any type restrictions + // are the same. Lower-case method names from different packages are always + // different. The order of the methods is irrelevant. if y, ok := y.(*Interface); ok { - a := x.typeSet().methods - b := y.typeSet().methods + xset := x.typeSet() + yset := y.typeSet() + if !Identical(xset.types, yset.types) { + return false + } + a := xset.methods + b := yset.methods if len(a) == len(b) { // Interface types are the only types where cycles can occur // that are not "terminated" via named types; and such cycles diff --git a/src/go/types/unify.go b/src/go/types/unify.go index 84c8ae718f..da57e533cc 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -359,16 +359,20 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { } case *Union: - // This should not happen with the current internal use of union types. - panic("type inference across union types not implemented") + panic("unimplemented: unification with type sets described by types") case *Interface: // Two interface types are identical if they have the same set of methods with // the same names and identical function types. Lower-case method names from // different packages are always different. The order of the methods is irrelevant. if y, ok := y.(*Interface); ok { - a := x.typeSet().methods - b := y.typeSet().methods + xset := x.typeSet() + yset := y.typeSet() + if !Identical(xset.types, yset.types) { + return false + } + a := xset.methods + b := yset.methods if len(a) == len(b) { // Interface types are the only types where cycles can occur // that are not "terminated" via named types; and such cycles -- GitLab From 82f875d735fd07957a2224d2c73c677ddfdeef0d Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 20:50:18 -0400 Subject: [PATCH 0491/2500] [dev.typeparams] go/types: fix generic type indirection This is a port of CL 333890 to go/types. Change-Id: I8ee20f405dad98083bb5e91636044d132a95d909 Reviewed-on: https://go-review.googlesource.com/c/go/+/335081 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/expr.go | 21 ++++++++++---- src/go/types/testdata/examples/operations.go2 | 29 +++++++++++++++++++ 2 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 src/go/types/testdata/examples/operations.go2 diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 751a360890..b55f51185f 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -1400,13 +1400,24 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { case typexpr: x.typ = &Pointer{base: x.typ} default: - if typ := asPointer(x.typ); typ != nil { - x.mode = variable - x.typ = typ.base - } else { - check.invalidOp(x, _InvalidIndirection, "cannot indirect %s", x) + var base Type + if !underIs(x.typ, func(u Type) bool { + p, _ := u.(*Pointer) + if p == nil { + check.invalidOp(x, _InvalidIndirection, "cannot indirect %s", x) + return false + } + if base != nil && !Identical(p.base, base) { + check.invalidOp(x, _Todo, "pointers of %s must have identical base types", x) + return false + } + base = p.base + return true + }) { goto Error } + x.mode = variable + x.typ = base } case *ast.UnaryExpr: diff --git a/src/go/types/testdata/examples/operations.go2 b/src/go/types/testdata/examples/operations.go2 new file mode 100644 index 0000000000..18e4d6080c --- /dev/null +++ b/src/go/types/testdata/examples/operations.go2 @@ -0,0 +1,29 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +// indirection + +func _[P any](p P) { + _ = *p // ERROR cannot indirect p +} + +func _[P interface{ int }](p P) { + _ = *p // ERROR cannot indirect p +} + +func _[P interface{ *int }](p P) { + _ = *p +} + +func _[P interface{ *int | *string }](p P) { + _ = *p // ERROR must have identical base types +} + +type intPtr *int + +func _[P interface{ *int | intPtr } ](p P) { + var _ int = *p +} -- GitLab From 7e714f448eaf2c489c32bfff5c00f5f5ad6ea289 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 16 Jul 2021 20:57:10 -0400 Subject: [PATCH 0492/2500] [dev.typeparams] go/types: embedding stand-alone type parameters is not permitted This is a port of CL 334151 to go/types. Fixes #47127 Change-Id: I57d69c498d2649a9e1657559e4c0271333096c88 Reviewed-on: https://go-review.googlesource.com/c/go/+/335082 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/testdata/check/issues.go2 | 2 +- src/go/types/testdata/check/tinference.go2 | 42 ++++++++++--------- .../types/testdata/fixedbugs/issue39634.go2 | 7 ++-- .../types/testdata/fixedbugs/issue39680.go2 | 4 ++ .../types/testdata/fixedbugs/issue39948.go2 | 10 +---- .../types/testdata/fixedbugs/issue47127.go2 | 37 ++++++++++++++++ src/go/types/typeset.go | 8 ++-- src/go/types/union.go | 11 +++-- 8 files changed, 81 insertions(+), 40 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue47127.go2 diff --git a/src/go/types/testdata/check/issues.go2 b/src/go/types/testdata/check/issues.go2 index 607da1df19..c57f002303 100644 --- a/src/go/types/testdata/check/issues.go2 +++ b/src/go/types/testdata/check/issues.go2 @@ -239,7 +239,7 @@ func _[T interface{ ~func() }](f T) { type sliceOf[E any] interface{ ~[]E } -func append[T interface{}, S sliceOf[T], T2 interface{ T }](s S, t ...T2) S +func append[T interface{}, S sliceOf[T], T2 interface{}](s S, t ...T2) S var f func() var cancelSlice []context.CancelFunc diff --git a/src/go/types/testdata/check/tinference.go2 b/src/go/types/testdata/check/tinference.go2 index 7ed358e078..44e8dc0059 100644 --- a/src/go/types/testdata/check/tinference.go2 +++ b/src/go/types/testdata/check/tinference.go2 @@ -11,19 +11,20 @@ type any interface{} // TODO(rFindley) the below partially applied function types should probably // not be permitted (spec question). -func f0[A any, B interface{~C}, C interface{~D}, D interface{~A}](A, B, C, D) -func _() { - f := f0[string] - f("a", "b", "c", "d") - f0("a", "b", "c", "d") -} - -func f1[A any, B interface{~A}](A, B) -func _() { - f := f1[int] - f(int(0), int(0)) - f1(int(0), int(0)) -} +// Embedding stand-alone type parameters is not permitted for now. Disabled. +// func f0[A any, B interface{~C}, C interface{~D}, D interface{~A}](A, B, C, D) +// func _() { +// f := f0[string] +// f("a", "b", "c", "d") +// f0("a", "b", "c", "d") +// } +// +// func f1[A any, B interface{~A}](A, B) +// func _() { +// f := f1[int] +// f(int(0), int(0)) +// f1(int(0), int(0)) +// } func f2[A any, B interface{~[]A}](A, B) func _() { @@ -32,13 +33,14 @@ func _() { f2(byte(0), []byte{}) } -func f3[A any, B interface{~C}, C interface{~*A}](A, B, C) -func _() { - f := f3[int] - var x int - f(x, &x, &x) - f3(x, &x, &x) -} +// Embedding stand-alone type parameters is not permitted for now. Disabled. +// func f3[A any, B interface{~C}, C interface{~*A}](A, B, C) +// func _() { +// f := f3[int] +// var x int +// f(x, &x, &x) +// f3(x, &x, &x) +// } func f4[A any, B interface{~[]C}, C interface{~*A}](A, B, C) func _() { diff --git a/src/go/types/testdata/fixedbugs/issue39634.go2 b/src/go/types/testdata/fixedbugs/issue39634.go2 index 2a1367373f..aec404e294 100644 --- a/src/go/types/testdata/fixedbugs/issue39634.go2 +++ b/src/go/types/testdata/fixedbugs/issue39634.go2 @@ -31,9 +31,10 @@ type x7[A any] struct{ foo7 } func main7() { var _ foo7 = x7[int]{} } // crash 8 -type foo8[A any] interface { ~A } -func bar8[A foo8[A]](a A) {} -func main8() {} +// Embedding stand-alone type parameters is not permitted for now. Disabled. +// type foo8[A any] interface { ~A } +// func bar8[A foo8[A]](a A) {} +// func main8() {} // crash 9 type foo9[A any] interface { foo9 /* ERROR illegal cycle */ [A] } diff --git a/src/go/types/testdata/fixedbugs/issue39680.go2 b/src/go/types/testdata/fixedbugs/issue39680.go2 index 01eadd2dbf..e56bc35475 100644 --- a/src/go/types/testdata/fixedbugs/issue39680.go2 +++ b/src/go/types/testdata/fixedbugs/issue39680.go2 @@ -4,6 +4,9 @@ package p +// Embedding stand-alone type parameters is not permitted for now. Disabled. + +/* import "fmt" // Minimal test case. @@ -25,3 +28,4 @@ func Print[T constr[T]](s []T) { func f() { Print([]string{"Hello, ", "playground\n"}) } +*/ diff --git a/src/go/types/testdata/fixedbugs/issue39948.go2 b/src/go/types/testdata/fixedbugs/issue39948.go2 index d83084b52a..e38e57268d 100644 --- a/src/go/types/testdata/fixedbugs/issue39948.go2 +++ b/src/go/types/testdata/fixedbugs/issue39948.go2 @@ -2,14 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// TODO(rfindley) Eventually, once we disallow type lists, we need to -// adjust this code: for 1.17 we don't accept type parameters, -// and for 1.18 this code is valid. -// Leaving for now so we can see that existing errors -// are being reported. - -package go1_17 // don't permit non-interface elements in interfaces +package p type T[P any] interface{ - P // ERROR P is a type parameter, not an interface + P // ERROR cannot embed a type parameter } diff --git a/src/go/types/testdata/fixedbugs/issue47127.go2 b/src/go/types/testdata/fixedbugs/issue47127.go2 new file mode 100644 index 0000000000..387c946957 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue47127.go2 @@ -0,0 +1,37 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Embedding of stand-alone type parameters is not permitted. + +package p + +type ( + _[P any] interface{ *P | []P | chan P | map[string]P } + _[P any] interface{ P /* ERROR "cannot embed a type parameter" */ } + _[P any] interface{ ~P /* ERROR "cannot embed a type parameter" */ } + _[P any] interface{ int | P /* ERROR "cannot embed a type parameter" */ } + _[P any] interface{ int | ~P /* ERROR "cannot embed a type parameter" */ } +) + +func _[P any]() { + type ( + _[P any] interface{ *P | []P | chan P | map[string]P } + _[P any] interface{ P /* ERROR "cannot embed a type parameter" */ } + _[P any] interface{ ~P /* ERROR "cannot embed a type parameter" */ } + _[P any] interface{ int | P /* ERROR "cannot embed a type parameter" */ } + _[P any] interface{ int | ~P /* ERROR "cannot embed a type parameter" */ } + + _ interface{ *P | []P | chan P | map[string]P } + _ interface{ P /* ERROR "cannot embed a type parameter" */ } + _ interface{ ~P /* ERROR "cannot embed a type parameter" */ } + _ interface{ int | P /* ERROR "cannot embed a type parameter" */ } + _ interface{ int | ~P /* ERROR "cannot embed a type parameter" */ } + ) +} + +func _[P any, Q interface{ *P | []P | chan P | map[string]P }]() +func _[P any, Q interface{ P /* ERROR "cannot embed a type parameter" */ }]() +func _[P any, Q interface{ ~P /* ERROR "cannot embed a type parameter" */ }]() +func _[P any, Q interface{ int | P /* ERROR "cannot embed a type parameter" */ }]() +func _[P any, Q interface{ int | ~P /* ERROR "cannot embed a type parameter" */ }]() diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index d8fe42f7d0..3df2f1235f 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -217,11 +217,9 @@ func computeTypeSet(check *Checker, pos token.Pos, ityp *Interface) *TypeSet { // interface before go1.18. types = typ case *TypeParam: - if check != nil && !check.allowVersion(check.pkg, 1, 18) { - check.errorf(atPos(pos), _InvalidIfaceEmbed, "%s is a type parameter, not an interface", typ) - continue - } - types = typ + // Embedding stand-alone type parameters is not permitted for now. + // This case is handled during union parsing. + unreachable() default: if typ == Typ[Invalid] { continue diff --git a/src/go/types/union.go b/src/go/types/union.go index 7c69ec7b10..556be46bf6 100644 --- a/src/go/types/union.go +++ b/src/go/types/union.go @@ -131,13 +131,18 @@ func parseUnion(check *Checker, tlist []ast.Expr) Type { return newUnion(types, tilde) } -func parseTilde(check *Checker, x ast.Expr) (Type, bool) { - tilde := false +func parseTilde(check *Checker, x ast.Expr) (typ Type, tilde bool) { if op, _ := x.(*ast.UnaryExpr); op != nil && op.Op == token.TILDE { x = op.X tilde = true } - return check.anyType(x), tilde + typ = check.anyType(x) + // embedding stand-alone type parameters is not permitted (issue #47127). + if _, ok := under(typ).(*TypeParam); ok { + check.error(x, _Todo, "cannot embed a type parameter") + typ = Typ[Invalid] + } + return } // intersect computes the intersection of the types x and y, -- GitLab From 6bf2667d4ef7dee76d308c0ac7acd0d409213b8a Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Mon, 19 Jul 2021 10:58:40 -0400 Subject: [PATCH 0493/2500] [dev.typeparams] go/types: more consistent handling of predeclared "any" This is a port of CL 334911 to go/types. Change-Id: I2cafdc76cb4d06ba82188c530f35952c1f77d292 Reviewed-on: https://go-review.googlesource.com/c/go/+/335569 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/decl.go | 5 +++-- src/go/types/object_test.go | 2 +- src/go/types/testdata/check/typeparams.go2 | 8 +++---- src/go/types/typexpr.go | 15 +++++++++++-- src/go/types/universe.go | 26 +++++++++------------- 5 files changed, 31 insertions(+), 25 deletions(-) diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 8fae59ffe8..e38124f077 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -678,8 +678,9 @@ func (check *Checker) declareTypeParams(tparams []*TypeName, names []*ast.Ident) // The type must be an interface, including the predeclared type "any". func (check *Checker) boundType(e ast.Expr) Type { // The predeclared identifier "any" is visible only as a type bound in a type parameter list. - if name, _ := unparen(e).(*ast.Ident); name != nil && name.Name == "any" && check.lookup("any") == nil { - return universeAny + // If we allow "any" for general use, this if-statement can be removed (issue #33232). + if name, _ := unparen(e).(*ast.Ident); name != nil && name.Name == "any" && check.lookup("any") == universeAny { + return universeAny.Type() } bound := check.typ(e) diff --git a/src/go/types/object_test.go b/src/go/types/object_test.go index 2b6057bd93..0ff8fdd6fa 100644 --- a/src/go/types/object_test.go +++ b/src/go/types/object_test.go @@ -22,7 +22,7 @@ func TestIsAlias(t *testing.T) { check(Unsafe.Scope().Lookup("Pointer").(*TypeName), false) for _, name := range Universe.Names() { if obj, _ := Universe.Lookup(name).(*TypeName); obj != nil { - check(obj, name == "byte" || name == "rune") + check(obj, name == "any" || name == "byte" || name == "rune") } } diff --git a/src/go/types/testdata/check/typeparams.go2 b/src/go/types/testdata/check/typeparams.go2 index 0e3795724b..b03725ff2a 100644 --- a/src/go/types/testdata/check/typeparams.go2 +++ b/src/go/types/testdata/check/typeparams.go2 @@ -6,11 +6,11 @@ package p // import "io" // for type assertion tests -// The predeclared identifier "any" is only visible as a constraint +// The predeclared identifier "any" can only be used as a constraint // in a type parameter list. -var _ any // ERROR undeclared -func _[_ any /* ok here */ , _ interface{any /* ERROR undeclared */ }](any /* ERROR undeclared */ ) { - var _ any /* ERROR undeclared */ +var _ any // ERROR cannot use any outside constraint position +func _[_ any /* ok here */ , _ interface{any /* ERROR constraint */ }](any /* ERROR constraint */ ) { + var _ any /* ERROR constraint */ } func identity[T any](x T) T { return x } diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 9a9fe32cb3..f2c4762a6b 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -27,13 +27,24 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool) // Note that we cannot use check.lookup here because the returned scope // may be different from obj.Parent(). See also Scope.LookupParent doc. scope, obj := check.scope.LookupParent(e.Name, check.pos) - if obj == nil || obj == universeComparable && !check.allowVersion(check.pkg, 1, 18) { + switch obj { + case nil: if e.Name == "_" { - check.errorf(e, _InvalidBlank, "cannot use _ as value or type") + check.error(e, _InvalidBlank, "cannot use _ as value or type") } else { check.errorf(e, _UndeclaredName, "undeclared name: %s", e.Name) } return + case universeAny, universeComparable: + if !check.allowVersion(check.pkg, 1, 18) { + check.errorf(e, _UndeclaredName, "undeclared name: %s (requires version go1.18 or later)", e.Name) + return + } + // If we allow "any" for general use, this if-statement can be removed (issue #33232). + if obj == universeAny { + check.error(e, _Todo, "cannot use any outside constraint position") + return + } } check.recordUse(e, obj) diff --git a/src/go/types/universe.go b/src/go/types/universe.go index 7c1e29b856..59952bc642 100644 --- a/src/go/types/universe.go +++ b/src/go/types/universe.go @@ -21,11 +21,11 @@ var Universe *Scope var Unsafe *Package var ( - universeIota *Const - universeByte *Basic // uint8 alias, but has name "byte" - universeRune *Basic // int32 alias, but has name "rune" - universeAny *Interface - universeError *Named + universeIota Object + universeByte Type // uint8 alias, but has name "byte" + universeRune Type // int32 alias, but has name "rune" + universeAny Object + universeError Type universeComparable Object ) @@ -80,9 +80,6 @@ func defPredeclaredTypes() { } // type any = interface{} - // Entered into universe scope so we do all the usual checks; - // but removed again from scope later since it's only visible - // as constraint in a type parameter list. def(NewTypeName(token.NoPos, nil, "any", &emptyInterface)) // type error interface{ Error() string } @@ -225,15 +222,12 @@ func init() { defPredeclaredNil() defPredeclaredFuncs() - universeIota = Universe.Lookup("iota").(*Const) - universeByte = Universe.Lookup("byte").(*TypeName).typ.(*Basic) - universeRune = Universe.Lookup("rune").(*TypeName).typ.(*Basic) - universeAny = Universe.Lookup("any").(*TypeName).typ.(*Interface) - universeError = Universe.Lookup("error").(*TypeName).typ.(*Named) + universeIota = Universe.Lookup("iota") + universeByte = Universe.Lookup("byte").Type() + universeRune = Universe.Lookup("rune").Type() + universeAny = Universe.Lookup("any") + universeError = Universe.Lookup("error").Type() universeComparable = Universe.Lookup("comparable") - - // "any" is only visible as constraint in a type parameter list - delete(Universe.elems, "any") } // Objects with names containing blanks are internal and not entered into -- GitLab From c6d3d0b0ad10926fc1952deda913d139ed608cb3 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 11 Jun 2021 12:40:42 -0400 Subject: [PATCH 0494/2500] [dev.typeparams] go/types: fix the type parameter index in applyTypeFunc We should preserve type parameter indices when transforming them using applyTypeFunc. Change-Id: Ib75f5cf1a146bd7e6850368fa954c1affcba3ad1 Reviewed-on: https://go-review.googlesource.com/c/go/+/327269 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/cmd/compile/internal/types2/builtins.go | 2 +- src/go/types/builtins.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 1f7eb23cdf..14be24e251 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -802,7 +802,7 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { // type param is placed in the current package so export/import // works as expected. tpar := NewTypeName(nopos, check.pkg, "", nil) - ptyp := check.NewTypeParam(tpar, 0, &emptyInterface) // assigns type to tpar as a side-effect + ptyp := check.NewTypeParam(tpar, tp.index, &emptyInterface) // assigns type to tpar as a side-effect tsum := newUnion(rtypes, tildes) ptyp.bound = &Interface{complete: true, tset: &TypeSet{types: tsum}} diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index eb3503fd6b..2edf901165 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -806,7 +806,7 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { // type param is placed in the current package so export/import // works as expected. tpar := NewTypeName(token.NoPos, check.pkg, "", nil) - ptyp := check.NewTypeParam(tpar, 0, &emptyInterface) // assigns type to tpar as a side-effect + ptyp := check.NewTypeParam(tpar, tp.index, &emptyInterface) // assigns type to tpar as a side-effect tsum := newUnion(rtypes, tildes) ptyp.bound = &Interface{complete: true, tset: &TypeSet{types: tsum}} -- GitLab From d14b7011a57fd7638dd4b67f1c2d031edf49f36e Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Mon, 12 Jul 2021 14:31:58 -0700 Subject: [PATCH 0495/2500] [dev.fuzz] internal/fuzz: fix two bugs in BenchmarkWorkerFuzzOverhead * The exec count must be set to 0 before calling workerServer.fuzz. This was causing fuzz to run indefinitely after the first benchmark iteration, since it wouldn't hit the termination condition of being equal to fuzzArgs.Limit. * Added an assertion that the count must be lower than fuzzArgs.Limit at the beginning of workerServer.fuzz. * Also closed and deleted shared memory at the end of each benchmark run. Change-Id: Iab465f8a4997ebd652aec04d0ff9bb60b802829e Reviewed-on: https://go-review.googlesource.com/c/go/+/334129 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/internal/fuzz/worker.go | 3 +++ src/internal/fuzz/worker_test.go | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index c3f4d74302..d8cc10d3d4 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -632,6 +632,9 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo resp.Count = mem.header().count ws.memMu <- mem }() + if args.Limit > 0 && mem.header().count >= args.Limit { + panic(fmt.Sprintf("mem.header().count %d already exceeds args.Limit %d", mem.header().count, args.Limit)) + } vals, err := unmarshalCorpusFile(mem.valueCopy()) if err != nil { diff --git a/src/internal/fuzz/worker_test.go b/src/internal/fuzz/worker_test.go index 10d61b19db..b536b3db12 100644 --- a/src/internal/fuzz/worker_test.go +++ b/src/internal/fuzz/worker_test.go @@ -25,6 +25,11 @@ func BenchmarkWorkerFuzzOverhead(b *testing.B) { if err != nil { b.Fatalf("failed to create temporary shared memory file: %s", err) } + defer func() { + if err := mem.Close(); err != nil { + b.Error(err) + } + }() initialVal := []interface{}{make([]byte, 32)} encodedVals := marshalCorpusFile(initialVal...) @@ -36,6 +41,7 @@ func BenchmarkWorkerFuzzOverhead(b *testing.B) { for i := 0; i < b.N; i++ { ws.m = newMutator() mem.setValue(encodedVals) + mem.header().count = 0 ws.fuzz(context.Background(), fuzzArgs{Limit: 1}) } -- GitLab From 3e06338c5ddb6cfd639015ba24655f9c9df87ef7 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Fri, 9 Jul 2021 15:24:15 -0700 Subject: [PATCH 0496/2500] [dev.fuzz] internal/fuzz: add more benchmarks for workers * Benchmark{Marshal,Unmarshal}CorpusFile - measures time it takes to serialize and deserialize byte slices of various lengths. * BenchmarkWorkerPing - spins up a worker and measures time it takes to ping it N times as a rough measure of RPC latency. * BenchmarkWorkerFuzz - spins up a worker and measures time it takes to mutate an input and call a trivial fuzz function N times. Also a few small fixes to make this easier. Change-Id: Id7f2dc6c6c05005cf286f30e6cc92a54bf44fbf7 Reviewed-on: https://go-review.googlesource.com/c/go/+/333670 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/internal/fuzz/encoding_test.go | 42 +++++++++++++ src/internal/fuzz/fuzz.go | 32 +++------- src/internal/fuzz/worker.go | 26 +++++++- src/internal/fuzz/worker_test.go | 98 ++++++++++++++++++++++++++++++ 4 files changed, 170 insertions(+), 28 deletions(-) diff --git a/src/internal/fuzz/encoding_test.go b/src/internal/fuzz/encoding_test.go index 3cd8d0e2ab..314f82a995 100644 --- a/src/internal/fuzz/encoding_test.go +++ b/src/internal/fuzz/encoding_test.go @@ -5,6 +5,7 @@ package fuzz import ( + "strconv" "strings" "testing" ) @@ -120,3 +121,44 @@ float32(2.5)`, }) } } + +// BenchmarkMarshalCorpusFile measures the time it takes to serialize byte +// slices of various sizes to a corpus file. The slice contains a repeating +// sequence of bytes 0-255 to mix escaped and non-escaped characters. +func BenchmarkMarshalCorpusFile(b *testing.B) { + buf := make([]byte, 1024*1024) + for i := 0; i < len(buf); i++ { + buf[i] = byte(i) + } + + for sz := 1; sz <= len(buf); sz <<= 1 { + sz := sz + b.Run(strconv.Itoa(sz), func(b *testing.B) { + for i := 0; i < b.N; i++ { + b.SetBytes(int64(sz)) + marshalCorpusFile(buf[:sz]) + } + }) + } +} + +// BenchmarkUnmarshalCorpusfile measures the time it takes to deserialize +// files encoding byte slices of various sizes. The slice contains a repeating +// sequence of bytes 0-255 to mix escaped and non-escaped characters. +func BenchmarkUnmarshalCorpusFile(b *testing.B) { + buf := make([]byte, 1024*1024) + for i := 0; i < len(buf); i++ { + buf[i] = byte(i) + } + + for sz := 1; sz <= len(buf); sz <<= 1 { + sz := sz + data := marshalCorpusFile(buf[:sz]) + b.Run(strconv.Itoa(sz), func(b *testing.B) { + for i := 0; i < b.N; i++ { + b.SetBytes(int64(sz)) + unmarshalCorpusFile(data) + } + }) + } +} diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 9ffa8beb16..673727e291 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -110,30 +110,6 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err defer cancel() } - // TODO(jayconrod): do we want to support fuzzing different binaries? - dir := "" // same as self - binPath := os.Args[0] - args := append([]string{"-test.fuzzworker"}, os.Args[1:]...) - env := os.Environ() // same as self - - // newWorker creates a worker but doesn't start it yet. - newWorker := func() (*worker, error) { - mem, err := sharedMemTempFile(workerSharedMemSize) - if err != nil { - return nil, err - } - memMu := make(chan *sharedMem, 1) - memMu <- mem - return &worker{ - dir: dir, - binPath: binPath, - args: args, - env: env[:len(env):len(env)], // copy on append to ensure workers don't overwrite each other. - coordinator: c, - memMu: memMu, - }, nil - } - // fuzzCtx is used to stop workers, for example, after finding a crasher. fuzzCtx, cancelWorkers := context.WithCancel(ctx) defer cancelWorkers() @@ -163,11 +139,17 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err } // Start workers. + // TODO(jayconrod): do we want to support fuzzing different binaries? + dir := "" // same as self + binPath := os.Args[0] + args := append([]string{"-test.fuzzworker"}, os.Args[1:]...) + env := os.Environ() // same as self + errC := make(chan error) workers := make([]*worker, opts.Parallel) for i := range workers { var err error - workers[i], err = newWorker() + workers[i], err = newWorker(c, dir, binPath, args, env) if err != nil { return err } diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index d8cc10d3d4..2acbf30ead 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -59,6 +59,23 @@ type worker struct { termC chan struct{} // closed by wait when worker process terminates } +func newWorker(c *coordinator, dir, binPath string, args, env []string) (*worker, error) { + mem, err := sharedMemTempFile(workerSharedMemSize) + if err != nil { + return nil, err + } + memMu := make(chan *sharedMem, 1) + memMu <- mem + return &worker{ + dir: dir, + binPath: binPath, + args: args, + env: env[:len(env):len(env)], // copy on append to ensure workers don't overwrite each other. + coordinator: c, + memMu: memMu, + }, nil +} + // cleanup releases persistent resources associated with the worker. func (w *worker) cleanup() error { mem := <-w.memMu @@ -625,8 +642,11 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo start := time.Now() defer func() { resp.TotalDuration = time.Since(start) }() - fuzzCtx, cancel := context.WithTimeout(ctx, args.Timeout) - defer cancel() + if args.Timeout != 0 { + var cancel func() + ctx, cancel = context.WithTimeout(ctx, args.Timeout) + defer cancel() + } mem := <-ws.memMu defer func() { resp.Count = mem.header().count @@ -654,7 +674,7 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo } for { select { - case <-fuzzCtx.Done(): + case <-ctx.Done(): return resp default: diff --git a/src/internal/fuzz/worker_test.go b/src/internal/fuzz/worker_test.go index b536b3db12..6c75fc412c 100644 --- a/src/internal/fuzz/worker_test.go +++ b/src/internal/fuzz/worker_test.go @@ -6,11 +6,26 @@ package fuzz import ( "context" + "flag" "fmt" + "io" "os" + "os/signal" + "reflect" "testing" ) +var benchmarkWorkerFlag = flag.Bool("benchmarkworker", false, "") + +func TestMain(m *testing.M) { + flag.Parse() + if *benchmarkWorkerFlag { + runBenchmarkWorker() + return + } + os.Exit(m.Run()) +} + func BenchmarkWorkerFuzzOverhead(b *testing.B) { origEnv := os.Getenv("GODEBUG") defer func() { os.Setenv("GODEBUG", origEnv) }() @@ -46,3 +61,86 @@ func BenchmarkWorkerFuzzOverhead(b *testing.B) { ws.fuzz(context.Background(), fuzzArgs{Limit: 1}) } } + +// BenchmarkWorkerPing acts as the coordinator and measures the time it takes +// a worker to respond to N pings. This is a rough measure of our RPC latency. +func BenchmarkWorkerPing(b *testing.B) { + b.SetParallelism(1) + w := newWorkerForTest(b) + for i := 0; i < b.N; i++ { + if err := w.client.ping(context.Background()); err != nil { + b.Fatal(err) + } + } +} + +// BenchmarkWorkerFuzz acts as the coordinator and measures the time it takes +// a worker to mutate a given input and call a trivial fuzz function N times. +func BenchmarkWorkerFuzz(b *testing.B) { + b.SetParallelism(1) + w := newWorkerForTest(b) + data := marshalCorpusFile([]byte(nil)) + for i := int64(0); i < int64(b.N); { + args := fuzzArgs{ + Limit: int64(b.N) - i, + Timeout: workerFuzzDuration, + } + _, resp, err := w.client.fuzz(context.Background(), data, args) + if err != nil { + b.Fatal(err) + } + if resp.Err != "" { + b.Fatal(resp.Err) + } + if resp.Count == 0 { + b.Fatal("worker did not make progress") + } + i += resp.Count + } +} + +// newWorkerForTest creates and starts a worker process for testing or +// benchmarking. The worker process calls RunFuzzWorker, which responds to +// RPC messages until it's stopped. The process is stopped and cleaned up +// automatically when the test is done. +func newWorkerForTest(tb testing.TB) *worker { + tb.Helper() + c, err := newCoordinator(CoordinateFuzzingOpts{ + Types: []reflect.Type{reflect.TypeOf([]byte(nil))}, + Log: io.Discard, + }) + if err != nil { + tb.Fatal(err) + } + dir := "" // same as self + binPath := os.Args[0] // same as self + args := append(os.Args[1:], "-benchmarkworker") + env := os.Environ() // same as self + w, err := newWorker(c, dir, binPath, args, env) + if err != nil { + tb.Fatal(err) + } + tb.Cleanup(func() { + if err := w.cleanup(); err != nil { + tb.Error(err) + } + }) + if err := w.startAndPing(context.Background()); err != nil { + tb.Fatal(err) + } + tb.Cleanup(func() { + if err := w.stop(); err != nil { + tb.Error(err) + } + }) + return w +} + +func runBenchmarkWorker() { + ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt) + defer cancel() + fn := func(CorpusEntry) error { return nil } + if err := RunFuzzWorker(ctx, fn); err != nil && err != ctx.Err() { + panic(err) + } +} -- GitLab From 2a0825d01f2cd68f5d82b3335f943bcf6f565f09 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Mon, 12 Jul 2021 15:39:43 -0700 Subject: [PATCH 0497/2500] [dev.fuzz] internal/fuzz: avoid marshaling input before calling fuzz function Previously, before each call to the fuzz function, the worker process marshalled the mutated input into shared memory. If the worker process terminates unexpectedly, it's important that the coordinator can find the crashing input in shared memory. Profiling shows this marshalling is very expensive though. This change takes another strategy. Instead of marshaling each mutated input, the worker process no longer modifies the input in shared memory at all. Instead, it saves its PRNG state in shared memory and increments a counter before each fuzz function call. If the worker process terminates, the coordinator can reconstruct the crashing value using this information. This change gives a ~10x increase in execs/s for a trivial fuzz function with -parallel=1. Change-Id: I18cf326c252727385dc53ea2518922b1f6ae36b6 Reviewed-on: https://go-review.googlesource.com/c/go/+/334149 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- .../script/test_fuzz_mutator_repeat.txt | 66 +++++++++++ src/internal/fuzz/mem.go | 3 + src/internal/fuzz/mutators_byteslice_test.go | 8 ++ src/internal/fuzz/pcg.go | 13 +++ src/internal/fuzz/worker.go | 107 +++++++++++------- src/internal/fuzz/worker_test.go | 5 +- 6 files changed, 158 insertions(+), 44 deletions(-) create mode 100644 src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt diff --git a/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt b/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt new file mode 100644 index 0000000000..0924ed37e6 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt @@ -0,0 +1,66 @@ +# TODO(jayconrod): support shared memory on more platforms. +[!darwin] [!linux] [!windows] skip + +# Verify that the fuzzing engine records the actual crashing input, even when +# a worker process terminates without communicating the crashing input back +# to the coordinator. + +[short] skip + +# Start fuzzing. The worker crashes after ~100 iterations. +# The fuzz function writes the crashing input to "want" before exiting. +# The fuzzing engine reconstructs the crashing input and saves it to testdata. +! exists want +! go test -fuzz=. -parallel=1 +stdout 'fuzzing process terminated unexpectedly' +stdout 'Crash written to testdata' + +# Run the fuzz target without fuzzing. The fuzz function is called with the +# crashing input in testdata. The test passes if that input is identical to +# the one saved in "want". +exists want +go test -want=want + +-- go.mod -- +module fuzz + +go 1.17 +-- fuzz_test.go -- +package fuzz + +import ( + "bytes" + "flag" + "os" + "testing" +) + +var wantFlag = flag.String("want", "", "file containing previous crashing input") + +func FuzzRepeat(f *testing.F) { + i := 0 + f.Fuzz(func(t *testing.T, b []byte) { + i++ + if i == 100 { + f, err := os.OpenFile("want", os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666) + if err != nil { + // Couldn't create the file, probably because it already exists, + // and we're minimizing now. Return without crashing. + return + } + f.Write(b) + f.Close() + os.Exit(1) // crash without communicating + } + + if *wantFlag != "" { + want, err := os.ReadFile(*wantFlag) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(want, b) { + t.Fatalf("inputs are not equal!\n got: %q\nwant:%q", b, want) + } + } + }) +} diff --git a/src/internal/fuzz/mem.go b/src/internal/fuzz/mem.go index a7792321ee..ccd4da2455 100644 --- a/src/internal/fuzz/mem.go +++ b/src/internal/fuzz/mem.go @@ -43,6 +43,9 @@ type sharedMemHeader struct { // valueLen is the length of the value that was last fuzzed. valueLen int + + // randState and randInc hold the state of a pseudo-random number generator. + randState, randInc uint64 } // sharedMemSize returns the size needed for a shared memory buffer that can diff --git a/src/internal/fuzz/mutators_byteslice_test.go b/src/internal/fuzz/mutators_byteslice_test.go index 4b8652cf03..50a39a9a5b 100644 --- a/src/internal/fuzz/mutators_byteslice_test.go +++ b/src/internal/fuzz/mutators_byteslice_test.go @@ -44,6 +44,14 @@ func (mr *mockRand) bool() bool { return b } +func (mr *mockRand) save(*uint64, *uint64) { + panic("unimplemented") +} + +func (mr *mockRand) restore(uint64, uint64) { + panic("unimplemented") +} + func TestByteSliceMutators(t *testing.T) { for _, tc := range []struct { name string diff --git a/src/internal/fuzz/pcg.go b/src/internal/fuzz/pcg.go index 0b799aab02..c9ea0afcf8 100644 --- a/src/internal/fuzz/pcg.go +++ b/src/internal/fuzz/pcg.go @@ -19,6 +19,9 @@ type mutatorRand interface { uint32n(uint32) uint32 exp2() int bool() bool + + save(randState, randInc *uint64) + restore(randState, randInc uint64) } // The functions in pcg implement a 32 bit PRNG with a 64 bit period: pcg xsh rr @@ -74,6 +77,16 @@ func (r *pcgRand) step() { r.state += r.inc } +func (r *pcgRand) save(randState, randInc *uint64) { + *randState = r.state + *randInc = r.inc +} + +func (r *pcgRand) restore(randState, randInc uint64) { + r.state = randState + r.inc = randInc +} + // uint32 returns a pseudo-random uint32. func (r *pcgRand) uint32() uint32 { x := r.state diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 2acbf30ead..e3029bcd66 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -5,6 +5,7 @@ package fuzz import ( + "bytes" "context" "crypto/sha256" "encoding/json" @@ -156,7 +157,7 @@ func (w *worker) coordinate(ctx context.Context) error { // to the client. args.CoverageData = input.coverageData } - value, resp, err := w.client.fuzz(ctx, input.entry.Data, args) + entry, resp, err := w.client.fuzz(ctx, input.entry, args) if err != nil { // Error communicating with worker. w.stop() @@ -194,26 +195,11 @@ func (w *worker) coordinate(ctx context.Context) error { count: resp.Count, totalDuration: resp.TotalDuration, entryDuration: resp.InterestingDuration, + entry: entry, } if resp.Err != "" { - h := sha256.Sum256(value) - name := fmt.Sprintf("%x", h[:4]) - result.entry = CorpusEntry{ - Name: name, - Parent: input.entry.Name, - Data: value, - Generation: input.entry.Generation + 1, - } result.crasherMsg = resp.Err } else if resp.CoverageData != nil { - h := sha256.Sum256(value) - name := fmt.Sprintf("%x", h[:4]) - result.entry = CorpusEntry{ - Name: name, - Parent: input.entry.Name, - Data: value, - Generation: input.entry.Generation + 1, - } result.coverageData = resp.CoverageData } w.coordinator.resultC <- result @@ -252,7 +238,7 @@ func (w *worker) minimize(ctx context.Context, input fuzzResult) (min fuzzResult Limit: w.coordinator.opts.MinimizeLimit, Timeout: w.coordinator.opts.MinimizeTimeout, } - value, resp, err := w.client.minimize(ctx, input.entry.Data, args) + minEntry, resp, err := w.client.minimize(ctx, input.entry, args) if err != nil { // Error communicating with worker. w.stop() @@ -274,7 +260,7 @@ func (w *worker) minimize(ctx context.Context, input fuzzResult) (min fuzzResult min.crasherMsg = resp.Err min.count = resp.Count min.totalDuration = resp.Duration - min.entry.Data = value + min.entry = minEntry return min, nil } @@ -369,7 +355,9 @@ func (w *worker) start() (err error) { // called later by stop. w.cmd = cmd w.termC = make(chan struct{}) - w.client = newWorkerClient(workerComm{fuzzIn: fuzzInW, fuzzOut: fuzzOutR, memMu: w.memMu}) + comm := workerComm{fuzzIn: fuzzInW, fuzzOut: fuzzOutR, memMu: w.memMu} + m := newMutator() + w.client = newWorkerClient(comm, m) go func() { w.waitErr = w.cmd.Wait() @@ -632,9 +620,17 @@ func (ws *workerServer) serve(ctx context.Context) error { } } -// fuzz runs the test function on random variations of a given input value for -// a given amount of time. fuzz returns early if it finds an input that crashes -// the fuzz function or an input that expands coverage. +// fuzz runs the test function on random variations of the input value in shared +// memory for a limited duration or number of iterations. +// +// fuzz returns early if it finds an input that crashes the fuzz function (with +// fuzzResponse.Err set) or an input that expands coverage (with +// fuzzResponse.InterestingDuration set). +// +// fuzz does not modify the input in shared memory. Instead, it saves the +// initial PRNG state in shared memory and increments a counter in shared +// memory before each call to the test function. The caller may reconstruct +// the crashing input with this information, since the PRNG is deterministic. func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzResponse) { if args.CoverageData != nil { ws.coverageData = args.CoverageData @@ -648,6 +644,7 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo defer cancel() } mem := <-ws.memMu + ws.m.r.save(&mem.header().randState, &mem.header().randInc) defer func() { resp.Count = mem.header().count ws.memMu <- mem @@ -680,7 +677,6 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo default: mem.header().count++ ws.m.mutate(vals, cap(mem.valueRef())) - writeToMem(vals, mem) fStart := time.Now() err := ws.fuzzFn(CorpusEntry{Values: vals}) fDur := time.Since(fStart) @@ -879,10 +875,11 @@ func (ws *workerServer) ping(ctx context.Context, args pingArgs) pingResponse { type workerClient struct { workerComm mu sync.Mutex + m *mutator } -func newWorkerClient(comm workerComm) *workerClient { - return &workerClient{workerComm: comm} +func newWorkerClient(comm workerComm, m *mutator) *workerClient { + return &workerClient{workerComm: comm, m: m} } // Close shuts down the connection to the RPC server (the worker process) by @@ -919,55 +916,81 @@ var errSharedMemClosed = errors.New("internal error: shared memory was closed an // minimize tells the worker to call the minimize method. See // workerServer.minimize. -func (wc *workerClient) minimize(ctx context.Context, valueIn []byte, args minimizeArgs) (valueOut []byte, resp minimizeResponse, err error) { +func (wc *workerClient) minimize(ctx context.Context, entryIn CorpusEntry, args minimizeArgs) (entryOut CorpusEntry, resp minimizeResponse, err error) { wc.mu.Lock() defer wc.mu.Unlock() mem, ok := <-wc.memMu if !ok { - return nil, minimizeResponse{}, errSharedMemClosed + return CorpusEntry{}, minimizeResponse{}, errSharedMemClosed } mem.header().count = 0 - mem.setValue(valueIn) + mem.setValue(entryIn.Data) wc.memMu <- mem + defer func() { wc.memMu <- mem }() c := call{Minimize: &args} - err = wc.callLocked(ctx, c, &resp) + callErr := wc.callLocked(ctx, c, &resp) mem, ok = <-wc.memMu if !ok { - return nil, minimizeResponse{}, errSharedMemClosed + return CorpusEntry{}, minimizeResponse{}, errSharedMemClosed + } + entryOut.Data = mem.valueCopy() + entryOut.Values, err = unmarshalCorpusFile(entryOut.Data) + if err != nil { + panic(fmt.Sprintf("workerClient.minimize unmarshaling minimized value: %v", err)) } - valueOut = mem.valueCopy() resp.Count = mem.header().count - wc.memMu <- mem - return valueOut, resp, err + return entryOut, resp, callErr } // fuzz tells the worker to call the fuzz method. See workerServer.fuzz. -func (wc *workerClient) fuzz(ctx context.Context, valueIn []byte, args fuzzArgs) (valueOut []byte, resp fuzzResponse, err error) { +func (wc *workerClient) fuzz(ctx context.Context, entryIn CorpusEntry, args fuzzArgs) (entryOut CorpusEntry, resp fuzzResponse, err error) { wc.mu.Lock() defer wc.mu.Unlock() mem, ok := <-wc.memMu if !ok { - return nil, fuzzResponse{}, errSharedMemClosed + return CorpusEntry{}, fuzzResponse{}, errSharedMemClosed } mem.header().count = 0 - mem.setValue(valueIn) + mem.setValue(entryIn.Data) wc.memMu <- mem c := call{Fuzz: &args} - err = wc.callLocked(ctx, c, &resp) + callErr := wc.callLocked(ctx, c, &resp) mem, ok = <-wc.memMu if !ok { - return nil, fuzzResponse{}, errSharedMemClosed + return CorpusEntry{}, fuzzResponse{}, errSharedMemClosed } - valueOut = mem.valueCopy() + defer func() { wc.memMu <- mem }() resp.Count = mem.header().count - wc.memMu <- mem - return valueOut, resp, err + if !bytes.Equal(entryIn.Data, mem.valueRef()) { + panic("workerServer.fuzz modified input") + } + valuesOut, err := unmarshalCorpusFile(entryIn.Data) + if err != nil { + panic(fmt.Sprintf("unmarshaling fuzz input value after call: %v", err)) + } + wc.m.r.restore(mem.header().randState, mem.header().randInc) + for i := int64(0); i < mem.header().count; i++ { + wc.m.mutate(valuesOut, cap(mem.valueRef())) + } + dataOut := marshalCorpusFile(valuesOut...) + + h := sha256.Sum256(dataOut) + name := fmt.Sprintf("%x", h[:4]) + entryOut = CorpusEntry{ + Name: name, + Parent: entryIn.Name, + Data: dataOut, + Values: valuesOut, + Generation: entryIn.Generation + 1, + } + + return entryOut, resp, callErr } // ping tells the worker to call the ping method. See workerServer.ping. diff --git a/src/internal/fuzz/worker_test.go b/src/internal/fuzz/worker_test.go index 6c75fc412c..2369b4ce3f 100644 --- a/src/internal/fuzz/worker_test.go +++ b/src/internal/fuzz/worker_test.go @@ -79,13 +79,14 @@ func BenchmarkWorkerPing(b *testing.B) { func BenchmarkWorkerFuzz(b *testing.B) { b.SetParallelism(1) w := newWorkerForTest(b) - data := marshalCorpusFile([]byte(nil)) + entry := CorpusEntry{Values: []interface{}{[]byte(nil)}} + entry.Data = marshalCorpusFile(entry.Values...) for i := int64(0); i < int64(b.N); { args := fuzzArgs{ Limit: int64(b.N) - i, Timeout: workerFuzzDuration, } - _, resp, err := w.client.fuzz(context.Background(), data, args) + _, resp, err := w.client.fuzz(context.Background(), entry, args) if err != nil { b.Fatal(err) } -- GitLab From ab361499ef7fc7079c78b566f9ff7d68c267b430 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Wed, 7 Jul 2021 19:41:02 -0400 Subject: [PATCH 0498/2500] [dev.cmdgo] cmd/go/testdata/script: fix a small typo in modfile_flag Change-Id: Id854869e581645dad7a250d40b150ebaf541c043 Reviewed-on: https://go-review.googlesource.com/c/go/+/334931 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/testdata/script/modfile_flag.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/go/testdata/script/modfile_flag.txt b/src/cmd/go/testdata/script/modfile_flag.txt index 0ad0880817..5852c31189 100644 --- a/src/cmd/go/testdata/script/modfile_flag.txt +++ b/src/cmd/go/testdata/script/modfile_flag.txt @@ -73,7 +73,7 @@ cmp go.mod go.mod.orig cmp go.sum go.sum.orig -# If the altnernate mod file does not have a ".mod" suffix, an error +# If the alternate mod file does not have a ".mod" suffix, an error # should be reported. cp go.alt.mod goaltmod ! go mod tidy -modfile=goaltmod -- GitLab From 6a931673f0b655e7ca538826af21a54d3f958070 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 20 Jul 2021 13:28:12 -0700 Subject: [PATCH 0499/2500] [dev.typeparams] cmd/compile: add base.Assertf{,At} functions We have almost 200 uses of the "assert" helper functions in noder and typecheck. Clearly the tiny bit of extra convenience of writing a one-line assertion rather than an if+panic is helpful, so we might as well add functions for this to base itself so that it's easier to write more informative error messages. Change-Id: I06e2db2f0455af063937b25a53ca42f9413cf496 Reviewed-on: https://go-review.googlesource.com/c/go/+/336050 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/base/print.go | 21 +++++++++++++++++++++ src/cmd/compile/internal/noder/stencil.go | 4 +--- src/cmd/compile/internal/typecheck/subr.go | 4 +--- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/base/print.go b/src/cmd/compile/internal/base/print.go index b095fd704d..4afe2eb9ee 100644 --- a/src/cmd/compile/internal/base/print.go +++ b/src/cmd/compile/internal/base/print.go @@ -233,6 +233,27 @@ func FatalfAt(pos src.XPos, format string, args ...interface{}) { ErrorExit() } +// Assert reports "assertion failed" with Fatalf, unless b is true. +func Assert(b bool) { + if !b { + Fatalf("assertion failed") + } +} + +// Assertf reports a fatal error with Fatalf, unless b is true. +func Assertf(b bool, format string, args ...interface{}) { + if !b { + Fatalf(format, args...) + } +} + +// AssertfAt reports a fatal error with FatalfAt, unless b is true. +func AssertfAt(b bool, pos src.XPos, format string, args ...interface{}) { + if !b { + FatalfAt(pos, format, args...) + } +} + // hcrash crashes the compiler when -h is set, to find out where a message is generated. func hcrash() { if Flag.LowerH != 0 { diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 7eac8573c9..72ecd80cf5 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -23,9 +23,7 @@ import ( ) func assert(p bool) { - if !p { - panic("assertion failed") - } + base.Assert(p) } // Temporary - for outputting information on derived types, dictionaries, sub-dictionaries. diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index d9e6612dfc..a795524b2b 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -981,9 +981,7 @@ func MakeDictName(gf *types.Sym, targs []*types.Type, hasBrackets bool) *types.S } func assert(p bool) { - if !p { - panic("assertion failed") - } + base.Assert(p) } // General type substituter, for replacing typeparams with type args. -- GitLab From d5f6ba943c4e8f39d1bd20c79f4e9274ad10c103 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sat, 17 Jul 2021 00:15:07 +0700 Subject: [PATCH 0500/2500] [dev.typeparams] test: add regression test for go/defer wrapper CL 330330 moved logic for wrapping go/defer from order to esacpe analysis. It introduced a bug involves go/defer statement with ABI0 functions. Consider this following code: package p //go:cgo_unsafe_args func g(*int) (r1 struct{}) { return } func f() { defer g(new(int)) } g is a cgo-like generated function with ABI0. While compiling g, we set the offset per ABI0. The function f is rewritten into: func f() { _0, _1 := g, new(int) defer func() { _0(_1) }() } The temporary _0 hold function value with the same type as g, but with class PAUTO. Thus ssagen/ssa.go:state.call cannot handle it and use ABIDefault to set the offset, causes the offset of r1 changed CL 330332 intended to optimize code generated for wrapping function, by rewriting the wrapper function into: func f() { _0 := new(int) defer func() { g(_0) }() } So it fixed the bug unintentionally. This CL add regression test for this bug, and also add a comment to explain while not wrapping declared function is important. Updates #47227 Change-Id: I75c83d1d9cc7fd4699e6b218a295d0c0a10ef471 Reviewed-on: https://go-review.googlesource.com/c/go/+/334882 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/escape/call.go | 2 ++ test/fixedbugs/issue47227.go | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 test/fixedbugs/issue47227.go diff --git a/src/cmd/compile/internal/escape/call.go b/src/cmd/compile/internal/escape/call.go index 9e5abed591..65c76d6870 100644 --- a/src/cmd/compile/internal/escape/call.go +++ b/src/cmd/compile/internal/escape/call.go @@ -320,6 +320,8 @@ func (e *escape) rewriteArgument(argp *ir.Node, init *ir.Nodes, call ir.Node, fn return case ir.ONAME: if arg.(*ir.Name).Class == ir.PFUNC { + // TODO(cuonglm): figure it why this is necessary, we should not depend on this to make + // ABI analyze works correctly (see #47227 and discussion in CL 334882). return } } diff --git a/test/fixedbugs/issue47227.go b/test/fixedbugs/issue47227.go new file mode 100644 index 0000000000..a14efc9a68 --- /dev/null +++ b/test/fixedbugs/issue47227.go @@ -0,0 +1,23 @@ +// run fake-arg-to-force-use-of-go-run + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build cgo +// +build cgo + +package main + +// void f(int *p) { *p = 0x12345678; } +import "C" + +func main() { + var x C.int + func() { + defer C.f(&x) + }() + if x != 0x12345678 { + panic("FAIL") + } +} -- GitLab From 897970688b326f7baa8ad8e3330fb552d94b0014 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 20 Jul 2021 16:52:37 -0700 Subject: [PATCH 0501/2500] [dev.typeparams] cmd/compile: cleanup unified IR file format a little This CL makes two changes: 1. It moves object symbols and code tags into a new "relocName" relocation, which should eventually allow getting rid of objStub. 2. It moves the type parameter data into the relocObjDict relocation, so everything related to writing out dictionaries is contained there. Change-Id: If0f7ff7d9384e8664957c3180bf6f20e97bcff6e Reviewed-on: https://go-review.googlesource.com/c/go/+/336051 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/noder/linker.go | 31 +++------ src/cmd/compile/internal/noder/reader.go | 79 +++++++++++----------- src/cmd/compile/internal/noder/reader2.go | 43 ++++++------ src/cmd/compile/internal/noder/reloc.go | 1 + src/cmd/compile/internal/noder/sync.go | 1 + src/cmd/compile/internal/noder/unified.go | 4 +- src/cmd/compile/internal/noder/writer.go | 81 +++++++++++++---------- 7 files changed, 124 insertions(+), 116 deletions(-) diff --git a/src/cmd/compile/internal/noder/linker.go b/src/cmd/compile/internal/noder/linker.go index eefb5083e5..2bc7f7c608 100644 --- a/src/cmd/compile/internal/noder/linker.go +++ b/src/cmd/compile/internal/noder/linker.go @@ -110,7 +110,7 @@ func (l *linker) relocPkg(pr *pkgReader, idx int) int { } func (l *linker) relocObj(pr *pkgReader, idx int) int { - path, name, tag, _ := pr.peekObj(idx) + path, name, tag := pr.peekObj(idx) sym := types.NewPkg(path, "").Lookup(name) if newidx, ok := l.decls[sym]; ok { @@ -127,7 +127,7 @@ func (l *linker) relocObj(pr *pkgReader, idx int) int { pr = pri.pr idx = pri.idx - path2, name2, tag2, _ := pr.peekObj(idx) + path2, name2, tag2 := pr.peekObj(idx) sym2 := types.NewPkg(path2, "").Lookup(name2) assert(sym == sym2) assert(tag2 != objStub) @@ -135,13 +135,16 @@ func (l *linker) relocObj(pr *pkgReader, idx int) int { w := l.pw.newEncoderRaw(relocObj) wext := l.pw.newEncoderRaw(relocObjExt) + wname := l.pw.newEncoderRaw(relocName) wdict := l.pw.newEncoderRaw(relocObjDict) l.decls[sym] = w.idx assert(wext.idx == w.idx) + assert(wname.idx == w.idx) assert(wdict.idx == w.idx) l.relocCommon(pr, &w, relocObj, idx) + l.relocCommon(pr, &wname, relocName, idx) l.relocCommon(pr, &wdict, relocObjDict, idx) var obj *ir.Name @@ -279,33 +282,15 @@ func (pr *pkgDecoder) peekPkgPath(idx int) string { return path } -func (pr *pkgDecoder) peekObj(idx int) (string, string, codeObj, []int) { - r := pr.newDecoder(relocObj, idx, syncObject1) +func (pr *pkgDecoder) peekObj(idx int) (string, string, codeObj) { + r := pr.newDecoder(relocName, idx, syncObject1) r.sync(syncSym) r.sync(syncPkg) path := pr.peekPkgPath(r.reloc(relocPkg)) name := r.string() assert(name != "") - r.sync(syncTypeParamBounds) - r.len() // implicits - bounds := make([]int, r.len()) - for i := range bounds { - r.sync(syncType) - if r.bool() { - r.len() - } else { - r.reloc(relocType) - } - - // TODO(mdempsky): This result now needs to include the 'derived' - // bool too, but none of the callers currently depend on it - // anyway. Either fix it to be meaningful, or just get rid of it - // altogether. - bounds[i] = -1 - } - tag := codeObj(r.code(syncCodeObj)) - return path, name, tag, bounds + return path, name, tag } diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index de708769ba..44d1c4f28b 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -534,18 +534,10 @@ func (r *reader) obj() ir.Node { } func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node { - r := pr.newReader(relocObj, idx, syncObject1) - r.ext = pr.newReader(relocObjExt, idx, syncObject1) - - _, sym := r.qualifiedIdent() - - dict := &readerDict{} - r.dict = dict - r.ext.dict = dict - - r.typeParamBounds(sym, implicits, explicits) + rname := pr.newReader(relocName, idx, syncObject1) + _, sym := rname.qualifiedIdent() + tag := codeObj(rname.code(syncCodeObj)) - tag := codeObj(r.code(syncCodeObj)) if tag == objStub { assert(!sym.IsBlank()) switch sym.Pkg { @@ -556,30 +548,19 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node return pri.pr.objIdx(pri.idx, nil, explicits) } if haveLegacyImports { - assert(!r.hasTypeParams()) + assert(len(explicits) == 0) return typecheck.Resolve(ir.NewIdent(src.NoXPos, sym)) } base.Fatalf("unresolved stub: %v", sym) } - { - rdict := pr.newReader(relocObjDict, idx, syncObject1) - r.dict.derived = make([]derivedInfo, rdict.len()) - r.dict.derivedTypes = make([]*types.Type, len(r.dict.derived)) - for i := range r.dict.derived { - r.dict.derived[i] = derivedInfo{rdict.reloc(relocType), rdict.bool()} - } - r.dict.funcs = make([]objInfo, rdict.len()) - r.dict.funcsObj = make([]ir.Node, len(r.dict.funcs)) - for i := range r.dict.funcs { - objIdx := rdict.reloc(relocObj) - targs := make([]typeInfo, rdict.len()) - for j := range targs { - targs[j] = rdict.typInfo() - } - r.dict.funcs[i] = objInfo{idx: objIdx, explicits: targs} - } - } + dict := pr.objDictIdx(sym, idx, implicits, explicits) + + r := pr.newReader(relocObj, idx, syncObject1) + r.ext = pr.newReader(relocObjExt, idx, syncObject1) + + r.dict = dict + r.ext.dict = dict sym = r.mangle(sym) if !sym.IsBlank() && sym.Def != nil { @@ -692,8 +673,10 @@ func (r *reader) mangle(sym *types.Sym) *types.Sym { return sym.Pkg.Lookup(buf.String()) } -func (r *reader) typeParamBounds(sym *types.Sym, implicits, explicits []*types.Type) { - r.sync(syncTypeParamBounds) +func (pr *pkgReader) objDictIdx(sym *types.Sym, idx int, implicits, explicits []*types.Type) *readerDict { + r := pr.newReader(relocObjDict, idx, syncObject1) + + var dict readerDict nimplicits := r.len() nexplicits := r.len() @@ -702,12 +685,11 @@ func (r *reader) typeParamBounds(sym *types.Sym, implicits, explicits []*types.T base.Fatalf("%v has %v+%v params, but instantiated with %v+%v args", sym, nimplicits, nexplicits, len(implicits), len(explicits)) } - r.dict.targs = append(implicits[:nimplicits:nimplicits], explicits...) - r.dict.implicits = nimplicits + dict.targs = append(implicits[:nimplicits:nimplicits], explicits...) + dict.implicits = nimplicits // For stenciling, we can just skip over the type parameters. - - for range r.dict.targs[r.dict.implicits:] { + for range dict.targs[dict.implicits:] { // Skip past bounds without actually evaluating them. r.sync(syncType) if r.bool() { @@ -716,6 +698,25 @@ func (r *reader) typeParamBounds(sym *types.Sym, implicits, explicits []*types.T r.reloc(relocType) } } + + dict.derived = make([]derivedInfo, r.len()) + dict.derivedTypes = make([]*types.Type, len(dict.derived)) + for i := range dict.derived { + dict.derived[i] = derivedInfo{r.reloc(relocType), r.bool()} + } + + dict.funcs = make([]objInfo, r.len()) + dict.funcsObj = make([]ir.Node, len(dict.funcs)) + for i := range dict.funcs { + objIdx := r.reloc(relocObj) + targs := make([]typeInfo, r.len()) + for j := range targs { + targs[j] = r.typInfo() + } + dict.funcs[i] = objInfo{idx: objIdx, explicits: targs} + } + + return &dict } func (r *reader) typeParamNames() { @@ -790,7 +791,11 @@ func (r *reader) selector() (origPkg *types.Pkg, sym *types.Sym) { } func (r *reader) hasTypeParams() bool { - return r.dict != nil && len(r.dict.targs) != 0 + return r.dict.hasTypeParams() +} + +func (dict *readerDict) hasTypeParams() bool { + return dict != nil && len(dict.targs) != 0 } // @@@ Compiler extensions diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index a2339145fa..297fa59439 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -358,29 +358,22 @@ func (r *reader2) obj() (types2.Object, []types2.Type) { } func (pr *pkgReader2) objIdx(idx int) (*types2.Package, string) { - r := pr.newReader(relocObj, idx, syncObject1) - r.dict = &reader2Dict{} + rname := pr.newReader(relocName, idx, syncObject1) - objPkg, objName := r.qualifiedIdent() + objPkg, objName := rname.qualifiedIdent() assert(objName != "") - r.typeParamBounds() - tag := codeObj(r.code(syncCodeObj)) + tag := codeObj(rname.code(syncCodeObj)) if tag == objStub { assert(objPkg == nil) return objPkg, objName } - { - rdict := r.p.newReader(relocObjDict, idx, syncObject1) - r.dict.derived = make([]derivedInfo, rdict.len()) - r.dict.derivedTypes = make([]types2.Type, len(r.dict.derived)) - for i := range r.dict.derived { - r.dict.derived[i] = derivedInfo{rdict.reloc(relocType), rdict.bool()} - } - // function references follow, but reader2 doesn't need those - } + dict := pr.objDictIdx(idx) + + r := pr.newReader(relocObj, idx, syncObject1) + r.dict = dict objPkg.Scope().InsertLazy(objName, func() types2.Object { switch tag { @@ -439,17 +432,29 @@ func (r *reader2) value() (types2.Type, constant.Value) { return r.typ(), r.rawValue() } -func (r *reader2) typeParamBounds() { - r.sync(syncTypeParamBounds) +func (pr *pkgReader2) objDictIdx(idx int) *reader2Dict { + r := pr.newReader(relocObjDict, idx, syncObject1) + + var dict reader2Dict if implicits := r.len(); implicits != 0 { base.Fatalf("unexpected object with %v implicit type parameter(s)", implicits) } - r.dict.bounds = make([]typeInfo, r.len()) - for i := range r.dict.bounds { - r.dict.bounds[i] = r.typInfo() + dict.bounds = make([]typeInfo, r.len()) + for i := range dict.bounds { + dict.bounds[i] = r.typInfo() + } + + dict.derived = make([]derivedInfo, r.len()) + dict.derivedTypes = make([]types2.Type, len(dict.derived)) + for i := range dict.derived { + dict.derived[i] = derivedInfo{r.reloc(relocType), r.bool()} } + + // function references follow, but reader2 doesn't need those + + return &dict } func (r *reader2) typeParamNames() []*types2.TypeName { diff --git a/src/cmd/compile/internal/noder/reloc.go b/src/cmd/compile/internal/noder/reloc.go index 4eb6bcdb1c..669a6182e6 100644 --- a/src/cmd/compile/internal/noder/reloc.go +++ b/src/cmd/compile/internal/noder/reloc.go @@ -31,6 +31,7 @@ const ( relocMeta relocPosBase relocPkg + relocName relocType relocObj relocObjExt diff --git a/src/cmd/compile/internal/noder/sync.go b/src/cmd/compile/internal/noder/sync.go index aef98dbd78..7af558f8b2 100644 --- a/src/cmd/compile/internal/noder/sync.go +++ b/src/cmd/compile/internal/noder/sync.go @@ -183,4 +183,5 @@ const ( syncTypeParamNames syncTypeParamBounds syncImplicitTypes + syncObjectName ) diff --git a/src/cmd/compile/internal/noder/unified.go b/src/cmd/compile/internal/noder/unified.go index e8c203ae46..9f80ca000d 100644 --- a/src/cmd/compile/internal/noder/unified.go +++ b/src/cmd/compile/internal/noder/unified.go @@ -263,7 +263,7 @@ func readPackage(pr *pkgReader, importpkg *types.Pkg) { idx := r.reloc(relocObj) assert(r.len() == 0) - path, name, code, _ := r.p.peekObj(idx) + path, name, code := r.p.peekObj(idx) if code != objStub { objReader[types.NewPkg(path, "").Lookup(name)] = pkgReaderIndex{pr, idx, nil} } @@ -298,7 +298,7 @@ func writeNewExport(out io.Writer) { idx := r.reloc(relocObj) assert(r.len() == 0) - xpath, xname, xtag, _ := pr.peekObj(idx) + xpath, xname, xtag := pr.peekObj(idx) assert(xpath == pr.pkgPath) assert(xtag != objStub) diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 48884056f3..bf60246d64 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -505,60 +505,45 @@ func (pw *pkgWriter) objIdx(obj types2.Object) int { w := pw.newWriter(relocObj, syncObject1) w.ext = pw.newWriter(relocObjExt, syncObject1) + wname := pw.newWriter(relocName, syncObject1) wdict := pw.newWriter(relocObjDict, syncObject1) pw.globalsIdx[obj] = w.idx // break cycles assert(w.ext.idx == w.idx) + assert(wname.idx == w.idx) assert(wdict.idx == w.idx) w.dict = dict w.ext.dict = dict - // Ident goes first so importer can avoid unnecessary work if - // they've already resolved this object. - w.qualifiedIdent(obj) - - w.typeParamBounds(objTypeParams(obj)) - - w.doObj(obj) - + code := w.doObj(obj) w.flush() w.ext.flush() - // Done writing out the object description; write out the list of - // derived types and instantiated functions found along the way. - wdict.len(len(dict.derived)) - for _, typ := range dict.derived { - wdict.reloc(relocType, typ.idx) - wdict.bool(typ.needed) - } - wdict.len(len(dict.funcs)) - for _, fn := range dict.funcs { - wdict.reloc(relocObj, fn.idx) - wdict.len(len(fn.explicits)) - for _, targ := range fn.explicits { - wdict.typInfo(targ) - } - } + wname.qualifiedIdent(obj) + wname.code(code) + wname.flush() + + wdict.objDict(obj, w.dict) wdict.flush() return w.idx } -func (w *writer) doObj(obj types2.Object) { +func (w *writer) doObj(obj types2.Object) codeObj { if obj.Pkg() != w.p.curpkg { - w.code(objStub) - return + return objStub } switch obj := obj.(type) { default: w.p.unexpected("object", obj) + panic("unreachable") case *types2.Const: - w.code(objConst) w.pos(obj) w.value(obj.Type(), obj.Val()) + return objConst case *types2.Func: decl, ok := w.p.funDecls[obj] @@ -584,28 +569,26 @@ func (w *writer) doObj(obj types2.Object) { sig = types2.NewSignature(nil, types2.NewTuple(params...), sig.Results(), sig.Variadic()) } - w.code(objFunc) w.pos(obj) w.typeParamNames(sig.TParams()) w.signature(sig) w.pos(decl) w.ext.funcExt(obj) + return objFunc case *types2.TypeName: decl, ok := w.p.typDecls[obj] assert(ok) if obj.IsAlias() { - w.code(objAlias) w.pos(obj) w.typ(obj.Type()) - break + return objAlias } named := obj.Type().(*types2.Named) assert(named.TArgs() == nil) - w.code(objType) w.pos(obj) w.typeParamNames(named.TParams()) w.ext.typeExt(obj) @@ -616,11 +599,13 @@ func (w *writer) doObj(obj types2.Object) { w.method(named.Method(i)) } + return objType + case *types2.Var: - w.code(objVar) w.pos(obj) w.typ(obj.Type()) w.ext.varExt(obj) + return objVar } } @@ -638,15 +623,41 @@ func (w *writer) value(typ types2.Type, val constant.Value) { w.rawValue(val) } -func (w *writer) typeParamBounds(tparams []*types2.TypeName) { - w.sync(syncTypeParamBounds) +// objDict writes the dictionary needed for reading the given object. +func (w *writer) objDict(obj types2.Object, dict *writerDict) { + // TODO(mdempsky): Split objDict into multiple entries? reader.go + // doesn't care about the type parameter bounds, and reader2.go + // doesn't care about referenced functions. + + w.dict = dict // TODO(mdempsky): This is a bit sketchy. - w.len(len(w.dict.implicits)) + w.len(len(dict.implicits)) + tparams := objTypeParams(obj) w.len(len(tparams)) for _, tparam := range tparams { w.typ(tparam.Type().(*types2.TypeParam).Bound()) } + + nderived := len(dict.derived) + w.len(nderived) + for _, typ := range dict.derived { + w.reloc(relocType, typ.idx) + w.bool(typ.needed) + } + + nfuncs := len(dict.funcs) + w.len(nfuncs) + for _, fn := range dict.funcs { + w.reloc(relocObj, fn.idx) + w.len(len(fn.explicits)) + for _, targ := range fn.explicits { + w.typInfo(targ) + } + } + + assert(len(dict.derived) == nderived) + assert(len(dict.funcs) == nfuncs) } func (w *writer) typeParamNames(tparams []*types2.TypeName) { -- GitLab From a7a17f0ca86d252dc1ef20b5852c352ade5f8610 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Wed, 9 Jun 2021 19:30:16 -0700 Subject: [PATCH 0502/2500] [dev.typeparams] cmd/compile: introduce named gcshape types Still 1-1 with real types, but now with their own names! Shape types are implicitly convertible to (and convertible from) the types they represent. Change-Id: I0133a8d8fbeb369380574b075a32b3c987e314d5 Reviewed-on: https://go-review.googlesource.com/c/go/+/335170 Run-TryBot: Keith Randall Trust: Keith Randall Trust: Dan Scales Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 150 +++++++++++++++++- src/cmd/compile/internal/noder/types.go | 2 +- .../compile/internal/reflectdata/reflect.go | 33 +++- src/cmd/compile/internal/typecheck/subr.go | 104 +++++++++--- src/cmd/compile/internal/types/identity.go | 9 ++ src/cmd/compile/internal/types/type.go | 46 ++++++ src/cmd/internal/obj/objfile.go | 5 + 7 files changed, 317 insertions(+), 32 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 72ecd80cf5..905ea0c88c 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -128,6 +128,7 @@ func (g *irgen) stencil() { // call. call.Args.Prepend(inst.X.(*ir.SelectorExpr).X) } + // Add dictionary to argument list. call.Args.Prepend(dictValue) // Transform the Call now, which changes OCALL @@ -486,6 +487,10 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { func (g *irgen) instantiateMethods() { for i := 0; i < len(g.instTypeList); i++ { typ := g.instTypeList[i] + if typ.HasShape() { + // Shape types should not have any methods. + continue + } // Mark runtime type as needed, since this ensures that the // compiler puts out the needed DWARF symbols, when this // instantiated type has a different package from the local @@ -781,7 +786,12 @@ func checkFetchBody(nameNode *ir.Name) { // cached, then it calls genericSubst to create the new instantiation. func (g *irgen) getInstantiation(nameNode *ir.Name, targs []*types.Type, isMeth bool) *ir.Func { checkFetchBody(nameNode) - sym := typecheck.MakeInstName(nameNode.Sym(), targs, isMeth) + + // Convert type arguments to their shape, so we can reduce the number + // of instantiations we have to generate. + shapes := typecheck.ShapifyList(targs) + + sym := typecheck.MakeInstName(nameNode.Sym(), shapes, isMeth) info := g.instInfoMap[sym] if info == nil { if false { @@ -802,7 +812,7 @@ func (g *irgen) getInstantiation(nameNode *ir.Name, targs []*types.Type, isMeth dictEntryMap: make(map[ir.Node]int), } // genericSubst fills in info.dictParam and info.dictEntryMap. - st := g.genericSubst(sym, nameNode, targs, isMeth, info) + st := g.genericSubst(sym, nameNode, shapes, targs, isMeth, info) info.fun = st g.instInfoMap[sym] = info // This ensures that the linker drops duplicates of this instantiation. @@ -824,6 +834,18 @@ type subster struct { newf *ir.Func // Func node for the new stenciled function ts typecheck.Tsubster info *instInfo // Place to put extra info in the instantiation + + // Which type parameter the shape type came from. + shape2param map[*types.Type]*types.Type + + // unshapeify maps from shape types to the concrete types they represent. + // TODO: remove when we no longer need it. + unshapify typecheck.Tsubster + concretify typecheck.Tsubster + + // TODO: some sort of map from to index in the + // dictionary where a *runtime.itab for the corresponding pair resides. } // genericSubst returns a new function with name newsym. The function is an @@ -832,7 +854,7 @@ type subster struct { // function type where the receiver becomes the first parameter. Otherwise the // instantiated method would still need to be transformed by later compiler // phases. genericSubst fills in info.dictParam and info.dictEntryMap. -func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []*types.Type, isMethod bool, info *instInfo) *ir.Func { +func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes, targs []*types.Type, isMethod bool, info *instInfo) *ir.Func { var tparams []*types.Type if isMethod { // Get the type params from the method receiver (after skipping @@ -847,6 +869,11 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []*type tparams[i] = f.Type } } + for i := range targs { + if targs[i].HasShape() { + base.Fatalf("generiSubst shape %s %+v %+v\n", newsym.Name, shapes[i], targs[i]) + } + } gf := nameNode.Func // Pos of the instantiated function is same as the generic function newf := ir.NewFunc(gf.Pos()) @@ -860,6 +887,7 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []*type // depend on ir.CurFunc being set. ir.CurFunc = newf + assert(len(tparams) == len(shapes)) assert(len(tparams) == len(targs)) subst := &subster{ @@ -869,9 +897,26 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []*type info: info, ts: typecheck.Tsubster{ Tparams: tparams, + Targs: shapes, + Vars: make(map[*ir.Name]*ir.Name), + }, + shape2param: map[*types.Type]*types.Type{}, + unshapify: typecheck.Tsubster{ + Tparams: shapes, Targs: targs, Vars: make(map[*ir.Name]*ir.Name), }, + concretify: typecheck.Tsubster{ + Tparams: tparams, + Targs: targs, + Vars: make(map[*ir.Name]*ir.Name), + }, + } + for i := range shapes { + if !shapes[i].IsShape() { + panic("must be a shape type") + } + subst.shape2param[shapes[i]] = tparams[i] } newf.Dcl = make([]*ir.Name, 0, len(gf.Dcl)+1) @@ -919,16 +964,25 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []*type newf.Body = subst.list(gf.Body) // Add code to check that the dictionary is correct. - newf.Body.Prepend(g.checkDictionary(dictionaryName, targs)...) + // TODO: must go away when we move to many->1 shape to concrete mapping. + newf.Body.Prepend(subst.checkDictionary(dictionaryName, targs)...) ir.CurFunc = savef // Add any new, fully instantiated types seen during the substitution to // g.instTypeList. g.instTypeList = append(g.instTypeList, subst.ts.InstTypeList...) + g.instTypeList = append(g.instTypeList, subst.unshapify.InstTypeList...) + g.instTypeList = append(g.instTypeList, subst.concretify.InstTypeList...) return newf } +func (subst *subster) unshapifyTyp(t *types.Type) *types.Type { + res := subst.unshapify.Typ(t) + types.CheckSize(res) + return res +} + // localvar creates a new name node for the specified local variable and enters it // in subst.vars. It substitutes type arguments for type parameters in the type of // name as needed. @@ -950,7 +1004,7 @@ func (subst *subster) localvar(name *ir.Name) *ir.Name { // checkDictionary returns code that does runtime consistency checks // between the dictionary and the types it should contain. -func (g *irgen) checkDictionary(name *ir.Name, targs []*types.Type) (code []ir.Node) { +func (subst *subster) checkDictionary(name *ir.Name, targs []*types.Type) (code []ir.Node) { if false { return // checking turned off } @@ -965,6 +1019,13 @@ func (g *irgen) checkDictionary(name *ir.Name, targs []*types.Type) (code []ir.N // Check that each type entry in the dictionary is correct. for i, t := range targs { + if t.HasShape() { + // Check the concrete type, not the shape type. + // TODO: can this happen? + //t = subst.unshapify.Typ(t) + base.Fatalf("shape type in dictionary %s %+v\n", name.Sym().Name, t) + continue + } want := reflectdata.TypePtr(t) typed(types.Types[types.TUINTPTR], want) deref := ir.NewStarExpr(pos, d) @@ -1144,11 +1205,36 @@ func (subst *subster) node(n ir.Node) ir.Node { // will be transformed to an ODOTMETH or ODOTINTER node if // we find in the OCALL case below that the method value // is actually called. - transformDot(m.(*ir.SelectorExpr), false) + mse := m.(*ir.SelectorExpr) + if src := mse.X.Type(); src.IsShape() { + // The only dot on a shape type value are methods. + if mse.X.Op() == ir.OTYPE { + // Method expression T.M + // Fall back from shape type to concrete type. + src = subst.unshapifyTyp(src) + mse.X = ir.TypeNode(src) + } else { + // Implement x.M as a conversion-to-bound-interface + // 1) convert x to the bound interface + // 2) call M on that interface + dst := subst.concretify.Typ(subst.shape2param[src].Bound()) + // Mark that we use the methods of this concrete type. + // Otherwise the linker deadcode-eliminates them :( + reflectdata.MarkTypeUsedInInterface(subst.unshapifyTyp(src), subst.newf.Sym().Linksym()) + ix := subst.findDictType(subst.shape2param[src]) + assert(ix >= 0) + mse.X = subst.convertUsingDictionary(m.Pos(), mse.X, dst, subst.shape2param[src], ix) + } + } + transformDot(mse, false) + if mse.Op() == ir.OMETHEXPR && mse.X.Type().HasShape() { + mse.X = ir.TypeNodeAt(mse.X.Pos(), subst.unshapifyTyp(mse.X.Type())) + } m.SetTypecheck(1) case ir.OCALL: call := m.(*ir.CallExpr) + convcheck := false switch call.X.Op() { case ir.OTYPE: // Transform the conversion, now that we know the @@ -1170,7 +1256,9 @@ func (subst *subster) node(n ir.Node) ir.Node { // transform the call. call.X.(*ir.SelectorExpr).SetOp(ir.OXDOT) transformDot(call.X.(*ir.SelectorExpr), true) + call.X.SetType(subst.unshapifyTyp(call.X.Type())) transformCall(call) + convcheck = true case ir.ODOT, ir.ODOTPTR: // An OXDOT for a generic receiver was resolved to @@ -1178,6 +1266,7 @@ func (subst *subster) node(n ir.Node) ir.Node { // value. Transform the call to that function, now // that the OXDOT was resolved. transformCall(call) + convcheck = true case ir.ONAME: name := call.X.Name() @@ -1190,15 +1279,24 @@ func (subst *subster) node(n ir.Node) ir.Node { default: base.FatalfAt(call.Pos(), "Unexpected builtin op") } + switch m.Op() { + case ir.OAPPEND: + // Append needs to pass a concrete type to the runtime. + // TODO: there's no way to record a dictionary-loaded type for walk to use here + m.SetType(subst.unshapifyTyp(m.Type())) + } + } else { // This is the case of a function value that was a // type parameter (implied to be a function via a // structural constraint) which is now resolved. transformCall(call) + convcheck = true } case ir.OCLOSURE: transformCall(call) + convcheck = true case ir.OFUNCINST: // A call with an OFUNCINST will get transformed @@ -1208,6 +1306,16 @@ func (subst *subster) node(n ir.Node) ir.Node { default: base.FatalfAt(call.Pos(), fmt.Sprintf("Unexpected op with CALL during stenciling: %v", call.X.Op())) } + if convcheck { + for i, arg := range x.(*ir.CallExpr).Args { + if arg.Type().HasTParam() && arg.Op() != ir.OCONVIFACE && + call.Args[i].Op() == ir.OCONVIFACE { + ix := subst.findDictType(arg.Type()) + assert(ix >= 0) + call.Args[i] = subst.convertUsingDictionary(arg.Pos(), call.Args[i].(*ir.ConvExpr).X, call.Args[i].Type(), arg.Type(), ix) + } + } + } case ir.OCLOSURE: // We're going to create a new closure from scratch, so clear m @@ -1281,6 +1389,29 @@ func (subst *subster) node(n ir.Node) ir.Node { m.Y = subst.convertUsingDictionary(m.Y.Pos(), m.Y, i, x.X.Type(), ix) } } + + case ir.ONEW: + // New needs to pass a concrete type to the runtime. + // Or maybe it doesn't? We could use a shape type. + // TODO: need to modify m.X? I don't think any downstream passes use it. + m.SetType(subst.unshapifyTyp(m.Type())) + + case ir.OPTRLIT: + m := m.(*ir.AddrExpr) + // Walk uses the type of the argument of ptrlit. Also could be a shape type? + m.X.SetType(subst.unshapifyTyp(m.X.Type())) + + case ir.OMETHEXPR: + se := m.(*ir.SelectorExpr) + se.X = ir.TypeNodeAt(se.X.Pos(), subst.unshapifyTyp(se.X.Type())) + case ir.OFUNCINST: + inst := m.(*ir.InstExpr) + targs2 := make([]ir.Node, len(inst.Targs)) + for i, n := range inst.Targs { + targs2[i] = ir.TypeNodeAt(n.Pos(), subst.unshapifyTyp(n.Type())) + // TODO: need an ir.Name node? + } + inst.Targs = targs2 } return m } @@ -1414,6 +1545,13 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) base.Fatalf("%s should have type arguments", gf.Sym().Name) } + // Enforce that only concrete types can make it to here. + for _, t := range targs { + if t.IsShape() { + panic(fmt.Sprintf("shape %+v in dictionary for %s", t, gf.Sym().Name)) + } + } + // Get a symbol representing the dictionary. sym := typecheck.MakeDictName(gf.Sym(), targs, isMeth) diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index c18ae3a1fc..d073526ada 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -327,7 +327,7 @@ func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) { methods[i].Nname = meth } ntyp.Methods().Set(methods) - if !ntyp.HasTParam() { + if !ntyp.HasTParam() && !ntyp.HasShape() { // Generate all the methods for a new fully-instantiated type. g.instTypeList = append(g.instTypeList, ntyp) } diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index b20fc8cccc..2236c7f1cf 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -302,6 +302,9 @@ func MapIterType(t *types.Type) *types.Type { // methods returns the methods of the non-interface type t, sorted by name. // Generates stub functions as needed. func methods(t *types.Type) []*typeSig { + if t.HasShape() { + return nil + } // method type mt := types.ReceiverBaseType(t) @@ -1215,6 +1218,7 @@ func NeedRuntimeType(t *types.Type) { if t.HasTParam() { // Generic types don't have a runtime type descriptor (but will // have a dictionary) + // TODO: also shape type here? return } if _, ok := signatset[t]; !ok { @@ -1276,6 +1280,9 @@ func writeITab(lsym *obj.LSym, typ, iface *types.Type) { for _, m := range methods(typ) { if m.name == sigs[0].Sym { entries = append(entries, m.isym) + if m.isym == nil { + panic("NO ISYM") + } sigs = sigs[1:] if len(sigs) == 0 { break @@ -1764,6 +1771,17 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy // an embedded field) which is an interface method. // TODO: check that we do the right thing when method is an interface method. generic = true + + targs := rcvr.RParams() + if rcvr.IsPtr() { + targs = rcvr.Elem().RParams() + } + // TODO: why do shape-instantiated types exist? + for _, t := range targs { + if t.HasShape() { + base.Fatalf("method on type instantiated with shapes targ:%+v rcvr:%+v", t, rcvr) + } + } } newnam := ir.MethodSym(rcvr, method.Sym) lsym := newnam.Linksym() @@ -1881,9 +1899,13 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy } args = append(args, ir.ParamNames(tfn.Type())...) - // TODO: Once we enter the gcshape world, we'll need a way to look up - // the stenciled implementation to use for this concrete type. Essentially, - // erase the concrete types and replace them with gc shape representatives. + // Target method uses shaped names. + targs2 := make([]*types.Type, len(targs)) + for i, t := range targs { + targs2[i] = typecheck.Shaped[t] + } + targs = targs2 + sym := typecheck.MakeInstName(ir.MethodSym(methodrcvr, method.Sym), targs, true) if sym.Def == nil { // Currently we make sure that we have all the instantiations @@ -1975,6 +1997,11 @@ func getDictionary(gf *types.Sym, targs []*types.Type) ir.Node { if len(targs) == 0 { base.Fatalf("%s should have type arguments", gf.Name) } + for _, t := range targs { + if t.HasShape() { + base.Fatalf("dictionary for %s should only use concrete types: %+v", gf.Name, t) + } + } sym := typecheck.MakeDictName(gf, targs, true) diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index a795524b2b..c6ffa175f1 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -353,9 +353,10 @@ func Assignop(src, dst *types.Type) (ir.Op, string) { return ir.OCONVNOP, "" } - // 2. src and dst have identical underlying types - // and either src or dst is not a named type or - // both are empty interface types. + // 2. src and dst have identical underlying types and + // a. either src or dst is not a named type, or + // b. both are empty interface types, or + // c. at least one is a gcshape type. // For assignable but different non-empty interface types, // we want to recompute the itab. Recomputing the itab ensures // that itabs are unique (thus an interface with a compile-time @@ -372,12 +373,23 @@ func Assignop(src, dst *types.Type) (ir.Op, string) { // which need to have their itab updated. return ir.OCONVNOP, "" } + if src.IsShape() || dst.IsShape() { + // Conversion between a shape type and one of the types + // it represents also needs no conversion. + return ir.OCONVNOP, "" + } } // 3. dst is an interface type and src implements dst. if dst.IsInterface() && src.Kind() != types.TNIL { var missing, have *types.Field var ptr int + if src.IsShape() { + // Shape types implement things they have already + // been typechecked to implement, even if they + // don't have the methods for them. + return ir.OCONVIFACE, "" + } if implements(src, dst, &missing, &have, &ptr) { return ir.OCONVIFACE, "" } @@ -898,8 +910,8 @@ func makeGenericName(name string, targs []*types.Type, hasBrackets bool) string hasTParam := false for _, targ := range targs { if hasTParam { - assert(targ.HasTParam()) - } else if targ.HasTParam() { + assert(targ.HasTParam() || targ.HasShape()) + } else if targ.HasTParam() || targ.HasShape() { hasTParam = true } } @@ -1002,14 +1014,14 @@ type Tsubster struct { // result is t; otherwise the result is a new type. It deals with recursive types // by using TFORW types and finding partially or fully created types via sym.Def. func (ts *Tsubster) Typ(t *types.Type) *types.Type { - if !t.HasTParam() && t.Kind() != types.TFUNC { + if !t.HasTParam() && !t.HasShape() && t.Kind() != types.TFUNC { // Note: function types need to be copied regardless, as the // types of closures may contain declarations that need // to be copied. See #45738. return t } - if t.IsTypeParam() { + if t.IsTypeParam() || t.IsShape() { for i, tp := range ts.Tparams { if tp == t { return ts.Targs[i] @@ -1038,6 +1050,7 @@ func (ts *Tsubster) Typ(t *types.Type) *types.Type { var newsym *types.Sym var neededTargs []*types.Type + var targsChanged bool var forw *types.Type if t.Sym() != nil { @@ -1046,6 +1059,9 @@ func (ts *Tsubster) Typ(t *types.Type) *types.Type { neededTargs = make([]*types.Type, len(t.RParams())) for i, rparam := range t.RParams() { neededTargs[i] = ts.Typ(rparam) + if !types.Identical(neededTargs[i], rparam) { + targsChanged = true + } } // For a named (defined) type, we have to change the name of the // type as well. We do this first, so we can look up if we've @@ -1074,7 +1090,7 @@ func (ts *Tsubster) Typ(t *types.Type) *types.Type { switch t.Kind() { case types.TTYPEPARAM: - if t.Sym() == newsym { + if t.Sym() == newsym && !targsChanged { // The substitution did not change the type. return t } @@ -1086,26 +1102,26 @@ func (ts *Tsubster) Typ(t *types.Type) *types.Type { case types.TARRAY: elem := t.Elem() newelem := ts.Typ(elem) - if newelem != elem { + if newelem != elem || targsChanged { newt = types.NewArray(newelem, t.NumElem()) } case types.TPTR: elem := t.Elem() newelem := ts.Typ(elem) - if newelem != elem { + if newelem != elem || targsChanged { newt = types.NewPtr(newelem) } case types.TSLICE: elem := t.Elem() newelem := ts.Typ(elem) - if newelem != elem { + if newelem != elem || targsChanged { newt = types.NewSlice(newelem) } case types.TSTRUCT: - newt = ts.tstruct(t, false) + newt = ts.tstruct(t, targsChanged) if newt == t { newt = nil } @@ -1114,7 +1130,7 @@ func (ts *Tsubster) Typ(t *types.Type) *types.Type { newrecvs := ts.tstruct(t.Recvs(), false) newparams := ts.tstruct(t.Params(), false) newresults := ts.tstruct(t.Results(), false) - if newrecvs != t.Recvs() || newparams != t.Params() || newresults != t.Results() { + if newrecvs != t.Recvs() || newparams != t.Params() || newresults != t.Results() || targsChanged { // If any types have changed, then the all the fields of // of recv, params, and results must be copied, because they have // offset fields that are dependent, and so must have an @@ -1144,14 +1160,14 @@ func (ts *Tsubster) Typ(t *types.Type) *types.Type { case types.TMAP: newkey := ts.Typ(t.Key()) newval := ts.Typ(t.Elem()) - if newkey != t.Key() || newval != t.Elem() { + if newkey != t.Key() || newval != t.Elem() || targsChanged { newt = types.NewMap(newkey, newval) } case types.TCHAN: elem := t.Elem() newelem := ts.Typ(elem) - if newelem != elem { + if newelem != elem || targsChanged { newt = types.NewChan(newelem, t.ChanDir()) if !newt.HasTParam() { // TODO(danscales): not sure why I have to do this @@ -1167,7 +1183,7 @@ func (ts *Tsubster) Typ(t *types.Type) *types.Type { } case types.TINT, types.TINT8, types.TINT16, types.TINT32, types.TINT64, types.TUINT, types.TUINT8, types.TUINT16, types.TUINT32, types.TUINT64, - types.TUINTPTR, types.TBOOL, types.TSTRING: + types.TUINTPTR, types.TBOOL, types.TSTRING, types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128: newt = t.Underlying() } if newt == nil { @@ -1177,15 +1193,17 @@ func (ts *Tsubster) Typ(t *types.Type) *types.Type { return t } - if t.Sym() == nil { - // Not a named type, so there was no forwarding type and there are - // no methods to substitute. + if t.Sym() == nil && t.Kind() != types.TINTER { + // Not a named type or interface type, so there was no forwarding type + // and there are no methods to substitute. assert(t.Methods().Len() == 0) return newt } - forw.SetUnderlying(newt) - newt = forw + if forw != nil { + forw.SetUnderlying(newt) + newt = forw + } if t.Kind() != types.TINTER && t.Methods().Len() > 0 { // Fill in the method info for the new type. @@ -1207,7 +1225,7 @@ func (ts *Tsubster) Typ(t *types.Type) *types.Type { newfields[i].Nname = nname } newt.Methods().Set(newfields) - if !newt.HasTParam() { + if !newt.HasTParam() && !newt.HasShape() { // Generate all the methods for a new fully-instantiated type. ts.InstTypeList = append(ts.InstTypeList, newt) } @@ -1305,3 +1323,45 @@ func (ts *Tsubster) tinter(t *types.Type) *types.Type { func genericTypeName(sym *types.Sym) string { return sym.Name[0:strings.Index(sym.Name, "[")] } + +// Shapify takes a concrete type and returns a GCshape type that can +// be used in place of the input type and still generate identical code. +// TODO: this could take the generic function and base its decisions +// on how that generic function uses this type argument. For instance, +// if it doesn't use it as a function argument/return value, then +// we don't need to distinguish int64 and float64 (because they only +// differ in how they get passed as arguments). For now, we only +// unify two different types if they are identical in every possible way. +func Shapify(t *types.Type) *types.Type { + if t.IsShape() { + return t // TODO: is this right? + } + if s := Shaped[t]; s != nil { + return s //TODO: keep? + } + + // For now, there is a 1-1 mapping between regular types and shape types. + sym := Lookup(fmt.Sprintf(".shape%d", snum)) + snum++ + name := ir.NewDeclNameAt(t.Pos(), ir.OTYPE, sym) + s := types.NewNamed(name) + s.SetUnderlying(t.Underlying()) + s.SetIsShape(true) + name.SetType(s) + name.SetTypecheck(1) + // TODO: add methods to s that the bound has? + Shaped[t] = s + return s +} + +var snum int + +var Shaped = map[*types.Type]*types.Type{} + +func ShapifyList(targs []*types.Type) []*types.Type { + r := make([]*types.Type, len(targs)) + for i, t := range targs { + r[i] = Shapify(t) + } + return r +} diff --git a/src/cmd/compile/internal/types/identity.go b/src/cmd/compile/internal/types/identity.go index dde9f51856..0a78092f07 100644 --- a/src/cmd/compile/internal/types/identity.go +++ b/src/cmd/compile/internal/types/identity.go @@ -29,6 +29,14 @@ func identical(t1, t2 *Type, cmpTags bool, assumedEqual map[typePair]struct{}) b return false } if t1.sym != nil || t2.sym != nil { + if t1.HasShape() || t2.HasShape() { + switch t1.kind { + case TINT8, TUINT8, TINT16, TUINT16, TINT32, TUINT32, TINT64, TUINT64, TINT, TUINT, TUINTPTR, TCOMPLEX64, TCOMPLEX128, TFLOAT32, TFLOAT64, TBOOL, TSTRING, TUNSAFEPTR: + return true + } + // fall through to unnamed type comparison for complex types. + goto cont + } // Special case: we keep byte/uint8 and rune/int32 // separate for error messages. Treat them as equal. switch t1.kind { @@ -40,6 +48,7 @@ func identical(t1, t2 *Type, cmpTags bool, assumedEqual map[typePair]struct{}) b return false } } +cont: // Any cyclic type must go through a named type, and if one is // named, it is only identical to the other if they are the diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 28312111ad..e6ae0e7bc1 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -210,6 +210,7 @@ const ( typeDeferwidth // width computation has been deferred and type is on deferredTypeStack typeRecur typeHasTParam // there is a typeparam somewhere in the type (generic function or type) + typeIsShape // represents a set of closely related types, for generics ) func (t *Type) NotInHeap() bool { return t.flags&typeNotInHeap != 0 } @@ -218,12 +219,14 @@ func (t *Type) Noalg() bool { return t.flags&typeNoalg != 0 } func (t *Type) Deferwidth() bool { return t.flags&typeDeferwidth != 0 } func (t *Type) Recur() bool { return t.flags&typeRecur != 0 } func (t *Type) HasTParam() bool { return t.flags&typeHasTParam != 0 } +func (t *Type) IsShape() bool { return t.flags&typeIsShape != 0 } func (t *Type) SetNotInHeap(b bool) { t.flags.set(typeNotInHeap, b) } func (t *Type) SetBroke(b bool) { t.flags.set(typeBroke, b) } func (t *Type) SetNoalg(b bool) { t.flags.set(typeNoalg, b) } func (t *Type) SetDeferwidth(b bool) { t.flags.set(typeDeferwidth, b) } func (t *Type) SetRecur(b bool) { t.flags.set(typeRecur, b) } +func (t *Type) SetIsShape(b bool) { t.flags.set(typeIsShape, b) } // Generic types should never have alg functions. func (t *Type) SetHasTParam(b bool) { t.flags.set(typeHasTParam, b); t.flags.set(typeNoalg, b) } @@ -2147,3 +2150,46 @@ var ( ) var SimType [NTYPE]Kind + +// Reports whether t has a shape type anywere. +func (t *Type) HasShape() bool { + return t.HasShape1(map[*Type]bool{}) +} +func (t *Type) HasShape1(visited map[*Type]bool) bool { + if t.IsShape() { + return true + } + if visited[t] { + return false + } + visited[t] = true + if t.Sym() != nil { + for _, u := range t.RParams() { + if u.HasShape1(visited) { + return true + } + } + } + switch t.Kind() { + case TPTR, TARRAY, TSLICE, TCHAN: + return t.Elem().HasShape1(visited) + case TMAP: + return t.Elem().HasShape1(visited) || t.Key().HasShape1(visited) + case TSTRUCT: + for _, f := range t.FieldSlice() { + if f.Type.HasShape1(visited) { + return true + } + } + case TFUNC: + for _, a := range RecvsParamsResults { + for _, f := range a(t).FieldSlice() { + if f.Type.HasShape1(visited) { + return true + } + } + } + // TODO: TINTER - check methods? + } + return false +} diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index 24fb5a19de..01466ea736 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -452,6 +452,11 @@ func (w *writer) contentHash(s *LSym) goobj.HashType { binary.LittleEndian.PutUint64(tmp[6:14], uint64(r.Add)) h.Write(tmp[:]) rs := r.Sym + if rs == nil { + fmt.Printf("symbol: %s\n", s) + fmt.Printf("relocation: %#v\n", r) + panic("nil symbol target in relocation") + } switch rs.PkgIdx { case goobj.PkgIdxHashed64: h.Write([]byte{0}) -- GitLab From 73af5f718f6012c0a76cabd43c91505d5a80c169 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Mon, 19 Jul 2021 16:49:32 -0700 Subject: [PATCH 0503/2500] [dev.typeparams] cmd/compile: disable failing generic tests We'll have to revisit eventually, but disabling for now. Change-Id: Ic34cfe451939d61884079bb125b9290db1e05e47 Reviewed-on: https://go-review.googlesource.com/c/go/+/335829 Run-TryBot: Keith Randall Trust: Keith Randall Trust: Dan Scales Reviewed-by: Dan Scales --- test/run.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/run.go b/test/run.go index ce0d645985..6e0c12d46b 100644 --- a/test/run.go +++ b/test/run.go @@ -2173,6 +2173,11 @@ var g3Failures = setOf( "typeparam/nested.go", // -G=3 doesn't support function-local types with generics "typeparam/mdempsky/4.go", // -G=3 can't export functions with labeled breaks in loops + + "typeparam/cons.go", // causes an unreachable method + "typeparam/dictionaryCapture.go", // segv, dictionary access failure? + "typeparam/issue44688.go", // interface conversion fails due to missing method + "typeparam/mdempsky/14.go", // interface comparison failure ) var unifiedFailures = setOf( -- GitLab From 2fe4b14795fe20fa3ba8efbe92b88f2d564509d2 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 20 Jul 2021 12:55:51 -0700 Subject: [PATCH 0504/2500] [dev.typeparams] cmd/compile: ensure methods of generic types survive linker pruning Calling MarkTypeUsedInInterface before inlining is problematic (when using the containing function as the reference source), because we end up attaching a relocation to the original function, which is then deadcode removed because all instances of it were inlined. (All other current uses of MarkTypeUsedInInterface happen after inlining, so they don't have this problem.) Instead, attach the relocation to the dictionary in which the type appears. This should always work, because if the dictionary is ever deadcode eliminated, then the type can never be put in an interface, which means we indeed don't need its methods. This CL is a bit overkill, as not *all* types in the dictionary need this mark, but it is sufficient for now. Change-Id: I2d39456691f1c3df8efe3bddc3b9017e0ef37a7f Reviewed-on: https://go-review.googlesource.com/c/go/+/336012 Trust: Keith Randall Trust: Dan Scales Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 905ea0c88c..9e0f198262 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -566,7 +566,6 @@ const UINTSTRING = "u8" // XX fix for 32-bit arch // buf. fieldSym is the sym of the field associated with type t, if it is in a // struct. fieldSym could be used to have special naming for blank fields, etc. func accumGcshape(fl []*types.Field, buf *bytes.Buffer, t *types.Type, fieldSym *types.Sym) []*types.Field { - // t.Kind() is already the kind of the underlying type, so no need to // reference t.Underlying() to reference the underlying type. assert(t.Kind() == t.Underlying().Kind()) @@ -1220,7 +1219,6 @@ func (subst *subster) node(n ir.Node) ir.Node { dst := subst.concretify.Typ(subst.shape2param[src].Bound()) // Mark that we use the methods of this concrete type. // Otherwise the linker deadcode-eliminates them :( - reflectdata.MarkTypeUsedInInterface(subst.unshapifyTyp(src), subst.newf.Sym().Linksym()) ix := subst.findDictType(subst.shape2param[src]) assert(ix >= 0) mse.X = subst.convertUsingDictionary(m.Pos(), mse.X, dst, subst.shape2param[src], ix) @@ -1566,6 +1564,11 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) infoPrint(" * %v\n", t) s := reflectdata.TypeLinksym(t) off = objw.SymPtr(lsym, off, s, 0) + // Ensure that methods on t don't get deadcode eliminated + // by the linker. + // TODO: This is somewhat overkill, we really only need it + // for types that are put into interfaces. + reflectdata.MarkTypeUsedInInterface(t, lsym) } subst := typecheck.Tsubster{ Tparams: info.tparams, @@ -1577,6 +1580,7 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) infoPrint(" - %v\n", ts) s := reflectdata.TypeLinksym(ts) off = objw.SymPtr(lsym, off, s, 0) + reflectdata.MarkTypeUsedInInterface(ts, lsym) } // Emit an entry for each subdictionary (after substituting targs) for _, n := range info.subDictCalls { -- GitLab From 4a97fe8c2298ae879904d3cf304ca29500abf169 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 20 Jul 2021 14:52:19 -0700 Subject: [PATCH 0505/2500] [dev.typeparams] cmd/compile: avoid adding incorrectly instantiated types to the dictionary FUNCINST nodes aren't instantiated correctly. Skip those types when adding to the set of types considered for the dictionary. Those types include those which are uninstantiated(have tparams), and those with type parameters that aren't a parameter of the containing function (they are the type parameter of the function being called). Allow func types to be put in the dictionary. Change-Id: I26bab85d3eebc2f54d02b4bba5e31407faf7c5b2 Reviewed-on: https://go-review.googlesource.com/c/go/+/336129 Reviewed-by: Dan Scales Trust: Dan Scales Trust: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 63 +++++++++++++++++++++-- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 9e0f198262..460d926a0d 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1836,11 +1836,7 @@ func addType(info *gfInfo, n ir.Node, t *types.Type) { if t.IsTypeParam() && t.Underlying() == t { return } - if t.Kind() == types.TFUNC && n != nil && - (n.Op() != ir.ONAME || n.Name().Class == ir.PFUNC) { - // For now, only record function types that are associate with a - // local/global variable (a name which is not a named global - // function). + if !parameterizedBy(t, info.tparams) { return } if t.Kind() == types.TSTRUCT && t.IsFuncArgStruct() { @@ -1855,3 +1851,60 @@ func addType(info *gfInfo, n ir.Node, t *types.Type) { } info.derivedTypes = append(info.derivedTypes, t) } + +// parameterizedBy returns true if t is parameterized by (at most) params. +func parameterizedBy(t *types.Type, params []*types.Type) bool { + return parameterizedBy1(t, params, map[*types.Type]bool{}) +} +func parameterizedBy1(t *types.Type, params []*types.Type, visited map[*types.Type]bool) bool { + if visited[t] { + return true + } + visited[t] = true + switch t.Kind() { + case types.TTYPEPARAM: + for _, p := range params { + if p == t { + return true + } + } + return false + + case types.TARRAY, types.TPTR, types.TSLICE, types.TCHAN: + return parameterizedBy1(t.Elem(), params, visited) + + case types.TMAP: + return parameterizedBy1(t.Key(), params, visited) && parameterizedBy1(t.Elem(), params, visited) + + case types.TFUNC: + if t.NumTParams() > 0 { + return false + } + return parameterizedBy1(t.Recvs(), params, visited) && parameterizedBy1(t.Params(), params, visited) && parameterizedBy1(t.Results(), params, visited) + + case types.TSTRUCT: + for _, f := range t.Fields().Slice() { + if !parameterizedBy1(f.Type, params, visited) { + return false + } + } + return true + + case types.TINTER: + for _, f := range t.Methods().Slice() { + if !parameterizedBy1(f.Type, params, visited) { + return false + } + } + return true + + case types.TINT, types.TINT8, types.TINT16, types.TINT32, types.TINT64, + types.TUINT, types.TUINT8, types.TUINT16, types.TUINT32, types.TUINT64, + types.TUINTPTR, types.TBOOL, types.TSTRING, types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128: + return true + + default: + base.Fatalf("bad type kind %+v", t) + return true + } +} -- GitLab From e6a2cf233f736e6852b64b53d66dbda21c2e062d Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 20 Jul 2021 15:02:01 -0700 Subject: [PATCH 0506/2500] [dev.typeparams] cmd/compile: get runtime stuff working Remaining stuff from Dan's CL 335412 to get tests passing. - Removed PTRLIT case in node() that was added with the gcshape change. I don't think it is needed anymore. - Modified (*itab).init() to add an irrelevant pointer (the itab itself) for the '==' entry of interfaces with 'comparable'. That entry is not used, so we just want to avoid the error that the given type doesn't actually have an '==' method. Change-Id: I9b2d4c8342c0b2048d76e003d95023f4ccd559f5 Reviewed-on: https://go-review.googlesource.com/c/go/+/336149 Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales Trust: Dan Scales Trust: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 5 ----- src/runtime/iface.go | 10 ++++++++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 460d926a0d..cff36dd3bf 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1394,11 +1394,6 @@ func (subst *subster) node(n ir.Node) ir.Node { // TODO: need to modify m.X? I don't think any downstream passes use it. m.SetType(subst.unshapifyTyp(m.Type())) - case ir.OPTRLIT: - m := m.(*ir.AddrExpr) - // Walk uses the type of the argument of ptrlit. Also could be a shape type? - m.X.SetType(subst.unshapifyTyp(m.X.Type())) - case ir.OMETHEXPR: se := m.(*ir.SelectorExpr) se.X = ir.TypeNodeAt(se.X.Pos(), subst.unshapifyTyp(se.X.Type())) diff --git a/src/runtime/iface.go b/src/runtime/iface.go index 79a49c0dff..71bd2d2f07 100644 --- a/src/runtime/iface.go +++ b/src/runtime/iface.go @@ -214,6 +214,16 @@ imethods: if ipkg == "" { ipkg = inter.pkgpath.name() } + if iname == "==" { + // Don't need '==' method right now (from comparable), + // just fill in with a random pointer for now. + if k == 0 { + fun0 = unsafe.Pointer(m) + } else { + methods[k] = unsafe.Pointer(m) + } + continue imethods + } for ; j < nt; j++ { t := &xmhdr[j] tname := typ.nameOff(t.name) -- GitLab From f19e49e7b185472b8ff919285e740cc198596497 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 20 Jul 2021 09:37:35 -0700 Subject: [PATCH 0507/2500] [dev.typeparams] cmd/compile: added a builtins.go test, fixed one bug The builtins.go test is derived from cmd/compile/internal/types2/testdata/check/builtins.go2, after removing the error cases. Added a few extra tests for len/cap/append. Fixed one bug, which is that DELETE operations can't be transformed if their argument is a typeparam. Also, the tranform of LEN/CAP calls does not need to be delayed. Removed out-date references to the old typechecker in the comments. Change-Id: If7a21506a7ff63ff7c8e87ccd614ef4ff3a0d3c8 Reviewed-on: https://go-review.googlesource.com/c/go/+/336010 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Dan Scales --- src/cmd/compile/internal/noder/helpers.go | 23 ++--- src/cmd/compile/internal/noder/stencil.go | 2 +- test/typeparam/builtins.go | 114 ++++++++++++++++++++++ 3 files changed, 124 insertions(+), 15 deletions(-) create mode 100644 test/typeparam/builtins.go diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index b0fb913ee8..7da5aa3102 100644 --- a/src/cmd/compile/internal/noder/helpers.go +++ b/src/cmd/compile/internal/noder/helpers.go @@ -126,22 +126,17 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) } if fun, ok := fun.(*ir.Name); ok && fun.BuiltinOp != 0 { - // For Builtin ops, we currently stay with using the old - // typechecker to transform the call to a more specific expression - // and possibly use more specific ops. However, for a bunch of the - // ops, we delay doing the old typechecker if any of the args have - // type params, for a variety of reasons: + // For most Builtin ops, we delay doing transformBuiltin if any of the + // args have type params, for a variety of reasons: // - // OMAKE: hard to choose specific ops OMAKESLICE, etc. until arg type is known - // OREAL/OIMAG: can't determine type float32/float64 until arg type know - // OLEN/OCAP: old typechecker will complain if arg is not obviously a slice/array. - // OAPPEND: old typechecker will complain if arg is not obviously slice, etc. - // - // We will eventually break out the transforming functionality - // needed for builtin's, and call it here or during stenciling, as - // appropriate. + // OMAKE: transformMake can't choose specific ops OMAKESLICE, etc. + // until arg type is known + // OREAL/OIMAG: transformRealImag can't determine type float32/float64 + // until arg type known + // OAPPEND: transformAppend requires that the arg is a slice + // ODELETE: transformDelete requires that the arg is a map switch fun.BuiltinOp { - case ir.OMAKE, ir.OREAL, ir.OIMAG, ir.OLEN, ir.OCAP, ir.OAPPEND: + case ir.OMAKE, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.ODELETE: hasTParam := false for _, arg := range args { if arg.Type().HasTParam() { diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index cff36dd3bf..d1527c5d5c 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1270,7 +1270,7 @@ func (subst *subster) node(n ir.Node) ir.Node { name := call.X.Name() if name.BuiltinOp != ir.OXXX { switch name.BuiltinOp { - case ir.OMAKE, ir.OREAL, ir.OIMAG, ir.OLEN, ir.OCAP, ir.OAPPEND: + case ir.OMAKE, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.ODELETE: // Transform these builtins now that we // know the type of the args. m = transformBuiltin(call) diff --git a/test/typeparam/builtins.go b/test/typeparam/builtins.go new file mode 100644 index 0000000000..3fe6f79391 --- /dev/null +++ b/test/typeparam/builtins.go @@ -0,0 +1,114 @@ +// compile -G=3 + +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file tests built-in calls on generic types. + +// derived and expanded from cmd/compile/internal/types2/testdata/check/builtins.go2 + +package builtins + +// close + +type C0 interface{ int } +type C1 interface{ chan int } +type C2 interface{ chan int | <-chan int } +type C3 interface{ chan int | chan float32 } +type C4 interface{ chan int | chan<- int } +type C5[T any] interface{ ~chan T | chan<- T } + +func _[T C1](ch T) { + close(ch) +} + +func _[T C3](ch T) { + close(ch) +} + +func _[T C4](ch T) { + close(ch) +} + +func _[T C5[X], X any](ch T) { + close(ch) +} + +// delete + +type M0 interface{ int } +type M1 interface{ map[string]int } +type M2 interface { map[string]int | map[string]float64 } +type M3 interface{ map[string]int | map[rune]int } +type M4[K comparable, V any] interface{ map[K]V | map[rune]V } + +func _[T M1](m T) { + delete(m, "foo") +} + +func _[T M2](m T) { + delete(m, "foo") +} + +func _[T M4[rune, V], V any](m T) { + delete(m, 'k') +} + +// make + +type Bmc interface { + ~map[rune]string | ~chan int +} + +type Bms interface { + ~map[string]int | ~[]int +} + +type Bcs interface { + ~chan bool | ~[]float64 +} + +type Bss interface { + ~[]int | ~[]string +} + +func _[T Bmc]() { + _ = make(T) + _ = make(T, 10) +} + +func _[T Bms]() { + _ = make(T, 10) +} + +func _[T Bcs]() { + _ = make(T, 10) +} + +func _[T Bss]() { + _ = make(T, 10) + _ = make(T, 10, 20) +} + +// len/cap + +type Slice[T any] interface { + type []T +} + +func _[T any, S Slice[T]]() { + x := make(S, 5, 10) + _ = len(x) + _ = cap(x) +} + +// append + +func _[T any, S Slice[T]]() { + x := make(S, 5) + y := make(S, 2) + var z T + _ = append(x, y...) + _ = append(x, z) +} -- GitLab From dcc8350ad304714824cc8e5b8a00105dabb61c54 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sun, 18 Jul 2021 22:10:13 -0700 Subject: [PATCH 0508/2500] [dev.typeparams] cmd/compile: handle ++/-- in noder2 for operands with generic type types2 will have already proved the expression's type is compatible, so just assign the one const to have the same type as the operand. Fixes #47258. Change-Id: If0844e6bf6d0a5e6b11453b87df71353863ccc5d Reviewed-on: https://go-review.googlesource.com/c/go/+/336009 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Dan Scales --- src/cmd/compile/internal/noder/helpers.go | 12 ++++++++- test/typeparam/issue47258.go | 32 +++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 test/typeparam/issue47258.go diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index 7da5aa3102..15b3277908 100644 --- a/src/cmd/compile/internal/noder/helpers.go +++ b/src/cmd/compile/internal/noder/helpers.go @@ -337,5 +337,15 @@ var one = constant.MakeInt64(1) func IncDec(pos src.XPos, op ir.Op, x ir.Node) *ir.AssignOpStmt { assert(x.Type() != nil) - return ir.NewAssignOpStmt(pos, op, x, typecheck.DefaultLit(ir.NewBasicLit(pos, one), x.Type())) + bl := ir.NewBasicLit(pos, one) + if x.Type().HasTParam() { + // If the operand is generic, then types2 will have proved it must be + // a type that fits with increment/decrement, so just set the type of + // "one" to n.Type(). This works even for types that are eventually + // float or complex. + typed(x.Type(), bl) + } else { + bl = typecheck.DefaultLit(bl, x.Type()) + } + return ir.NewAssignOpStmt(pos, op, x, bl) } diff --git a/test/typeparam/issue47258.go b/test/typeparam/issue47258.go new file mode 100644 index 0000000000..76629f7424 --- /dev/null +++ b/test/typeparam/issue47258.go @@ -0,0 +1,32 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" +) + +type Numeric interface { + int32|int64|float64|complex64 +} + +//go:noline +func inc[T Numeric](x T) T { + x++ + return x +} +func main() { + if got, want := inc(int32(5)), int32(6); got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } + if got, want := inc(float64(5)), float64(6.0); got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } + if got, want := inc(complex64(5)), complex64(6.0); got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } +} -- GitLab From 4e6836e82c981af7c041474f139b3de03906c3b0 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 20 Jul 2021 19:18:15 -0700 Subject: [PATCH 0509/2500] [dev.typeparams] Fix the types of the OFUNCINST nodes in noder2 types2 doesn't actually give us the type of an instantiated function/method after the type args have been applied. So, do a substitution at the point that we create the OFUNCINST nodes. We also needed to add in translation of the typeparams of a function signature in the type substituter. If the type params of the function become all concrete after the substitution, then we just drop them, since the whole signature must now be concrete. Change-Id: I6116d2aa248be6924ec9e6d8516678db45aa65c4 Reviewed-on: https://go-review.googlesource.com/c/go/+/336370 Run-TryBot: Dan Scales TryBot-Result: Go Bot Trust: Dan Scales Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/expr.go | 44 +++++++++++++++++++--- src/cmd/compile/internal/typecheck/subr.go | 16 +++++++- 2 files changed, 52 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 66ce1bfe4c..131ee89cbb 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -80,7 +80,7 @@ func (g *irgen) expr(expr syntax.Expr) ir.Node { if n.Typecheck() != 1 && n.Typecheck() != 3 { base.FatalfAt(g.pos(expr), "missed typecheck: %+v", n) } - if !g.match(n.Type(), typ, tv.HasOk()) { + if n.Op() != ir.OFUNCINST && !g.match(n.Type(), typ, tv.HasOk()) { base.FatalfAt(g.pos(expr), "expected %L to have type %v", n, typ) } return n @@ -128,11 +128,14 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { // includes the additional inferred type args fun.(*ir.InstExpr).Targs = targs } else { - // Create a function instantiation here, given - // there are only inferred type args (e.g. - // min(5,6), where min is a generic function) + // Create a function instantiation here, given there + // are only inferred type args (e.g. min(5,6), where + // min is a generic function). Substitute the type + // args for the type params in the uninstantiated function's + // type. inst := ir.NewInstExpr(pos, ir.OFUNCINST, fun, targs) - typed(fun.Type(), inst) + newt := g.substType(fun.Type(), fun.Type().TParams(), targs) + typed(newt, inst) fun = inst } @@ -169,7 +172,14 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { panic("Incorrect argument for generic func instantiation") } n := ir.NewInstExpr(pos, ir.OFUNCINST, x, targs) - typed(g.typ(typ), n) + newt := g.typ(typ) + // Substitute the type args for the type params in the uninstantiated + // function's type. If there aren't enough type args, then the rest + // will be inferred at the call node, so don't try the substitution yet. + if x.Type().TParams().NumFields() == len(targs) { + newt = g.substType(g.typ(typ), x.Type().TParams(), targs) + } + typed(newt, n) return n case *syntax.SelectorExpr: @@ -201,6 +211,28 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { } } +// substType does a normal type substition, but tparams is in the form of a field +// list, and targs is in terms of a slice of type nodes. substType records any newly +// instantiated types into g.instTypeList. +func (g *irgen) substType(typ *types.Type, tparams *types.Type, targs []ir.Node) *types.Type { + fields := tparams.FieldSlice() + tparams1 := make([]*types.Type, len(fields)) + for i, f := range fields { + tparams1[i] = f.Type + } + targs1 := make([]*types.Type, len(targs)) + for i, n := range targs { + targs1[i] = n.Type() + } + ts := typecheck.Tsubster{ + Tparams: tparams1, + Targs: targs1, + } + newt := ts.Typ(typ) + g.instTypeList = append(g.instTypeList, ts.InstTypeList...) + return newt +} + // selectorExpr resolves the choice of ODOT, ODOTPTR, OMETHVALUE (eventually // ODOTMETH & ODOTINTER), and OMETHEXPR and deals with embedded fields here rather // than in typecheck.go. diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index c6ffa175f1..53221bc1cd 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1130,7 +1130,10 @@ func (ts *Tsubster) Typ(t *types.Type) *types.Type { newrecvs := ts.tstruct(t.Recvs(), false) newparams := ts.tstruct(t.Params(), false) newresults := ts.tstruct(t.Results(), false) - if newrecvs != t.Recvs() || newparams != t.Params() || newresults != t.Results() || targsChanged { + // Translate the tparams of a signature. + newtparams := ts.tstruct(t.TParams(), false) + if newrecvs != t.Recvs() || newparams != t.Params() || + newresults != t.Results() || newtparams != t.TParams() || targsChanged { // If any types have changed, then the all the fields of // of recv, params, and results must be copied, because they have // offset fields that are dependent, and so must have an @@ -1148,7 +1151,16 @@ func (ts *Tsubster) Typ(t *types.Type) *types.Type { if newresults == t.Results() { newresults = ts.tstruct(t.Results(), true) } - newt = types.NewSignature(t.Pkg(), newrecv, t.TParams().FieldSlice(), newparams.FieldSlice(), newresults.FieldSlice()) + var tparamfields []*types.Field + if newtparams.HasTParam() { + tparamfields = newtparams.FieldSlice() + } else { + // Completely remove the tparams from the resulting + // signature, if the tparams are now concrete types. + tparamfields = nil + } + newt = types.NewSignature(t.Pkg(), newrecv, tparamfields, + newparams.FieldSlice(), newresults.FieldSlice()) } case types.TINTER: -- GitLab From ee20dff27debb738ca3a89a7a30113771c1c078f Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sun, 18 Jul 2021 11:09:12 -0700 Subject: [PATCH 0510/2500] [dev.typeparams] Get dictionaryCapture.go working. METHVALUE in a generic function (that is not called) was not causing buildClosure() to be called and therefore not using dictionaries. Also, had to add an extra check to make sure that if we have a FUNCINST node above a METHVALUE, we only call buildClosure once. Change-Id: I49756152fc343e5ac1c449e697960fc2a0f482ae Reviewed-on: https://go-review.googlesource.com/c/go/+/336429 Reviewed-by: Keith Randall Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot --- src/cmd/compile/internal/noder/stencil.go | 26 ++++++++++++++++++----- test/run.go | 7 +++--- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index d1527c5d5c..71edc82dea 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -92,8 +92,8 @@ func (g *irgen) stencil() { // generic F, not immediately called closureRequired = true } - if n.Op() == ir.OMETHEXPR && len(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) > 0 && !types.IsInterfaceMethod(n.(*ir.SelectorExpr).Selection.Type) { - // T.M, T a type which is generic, not immediately + if (n.Op() == ir.OMETHEXPR || n.Op() == ir.OMETHVALUE) && len(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) > 0 && !types.IsInterfaceMethod(n.(*ir.SelectorExpr).Selection.Type) { + // T.M or x.M, where T or x is generic, but not immediately // called. Not necessary if the method selected is // actually for an embedded interface field. closureRequired = true @@ -180,18 +180,31 @@ func (g *irgen) stencil() { // in the infrequent case of an OFUNCINST without a corresponding // call. if closureRequired { + modified = true var edit func(ir.Node) ir.Node var outer *ir.Func if f, ok := decl.(*ir.Func); ok { outer = f } edit = func(x ir.Node) ir.Node { + if x.Op() == ir.OFUNCINST { + child := x.(*ir.InstExpr).X + if child.Op() == ir.OMETHEXPR || child.Op() == ir.OMETHVALUE { + // Call EditChildren on child (x.X), + // not x, so that we don't do + // buildClosure() on the + // METHEXPR/METHVALUE nodes as well. + ir.EditChildren(child, edit) + return g.buildClosure(outer, x) + } + } ir.EditChildren(x, edit) switch { case x.Op() == ir.OFUNCINST: return g.buildClosure(outer, x) - case x.Op() == ir.OMETHEXPR && len(deref(x.(*ir.SelectorExpr).X.Type()).RParams()) > 0 && - !types.IsInterfaceMethod(x.(*ir.SelectorExpr).Selection.Type): // TODO: test for ptr-to-method case + case (x.Op() == ir.OMETHEXPR || x.Op() == ir.OMETHVALUE) && + len(deref(x.(*ir.SelectorExpr).X.Type()).RParams()) > 0 && + !types.IsInterfaceMethod(x.(*ir.SelectorExpr).Selection.Type): return g.buildClosure(outer, x) } return x @@ -264,13 +277,16 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { fmt.Printf("%s in %v for generic method value %v\n", dictkind, outer, inst.X) } } - } else { // ir.OMETHEXPR + } else { // ir.OMETHEXPR or ir.METHVALUE // Method expression T.M where T is a generic type. se := x.(*ir.SelectorExpr) targs := deref(se.X.Type()).RParams() if len(targs) == 0 { panic("bad") } + if x.Op() == ir.OMETHVALUE { + rcvrValue = se.X + } // se.X.Type() is the top-level type of the method expression. To // correctly handle method expressions involving embedded fields, diff --git a/test/run.go b/test/run.go index 6e0c12d46b..55c508dd42 100644 --- a/test/run.go +++ b/test/run.go @@ -2174,10 +2174,9 @@ var g3Failures = setOf( "typeparam/mdempsky/4.go", // -G=3 can't export functions with labeled breaks in loops - "typeparam/cons.go", // causes an unreachable method - "typeparam/dictionaryCapture.go", // segv, dictionary access failure? - "typeparam/issue44688.go", // interface conversion fails due to missing method - "typeparam/mdempsky/14.go", // interface comparison failure + "typeparam/cons.go", // causes an unreachable method + "typeparam/issue44688.go", // interface conversion fails due to missing method + "typeparam/mdempsky/14.go", // interface comparison failure ) var unifiedFailures = setOf( -- GitLab From 8e9109e95a8c4be92ba018a1353104706acf8466 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 19 Jul 2021 12:41:30 -0700 Subject: [PATCH 0511/2500] [dev.typeparams] Fix problem with 14.go Removed a case in transformCall() where we were setting a type on n, which isn't needed, since noder2 already set the type of n. More importantly, we are losing information, since the type of the results may be a shape type, but the actual type of call is the known type from types2, which may be a concrete type (in this case Zero[MyInt]). That concrete type will then be used correctly if the concrete result is converted to an interface. If we are inlining the call to Zero[MyInt], we need to add an implicit CONVNOP operation, since we are going to use the result variable directly, which has a shape type. So, add an implicit CONVNOP to remember that the known type is the concrete type. Also cleaned up 14.go a bit, so it is more understandable. Renamed type T to AnyInt, since T is used elsewhere as a type parameter. Reformatted Zero function and added a comment. Change-Id: Id917a2e054e0bbae9bd302232853fa8741d49b64 Reviewed-on: https://go-review.googlesource.com/c/go/+/336430 Trust: Dan Scales Reviewed-by: Keith Randall --- src/cmd/compile/internal/ir/expr.go | 8 ++++++++ src/cmd/compile/internal/noder/transform.go | 2 -- test/run.go | 5 ++--- test/typeparam/mdempsky/14.go | 11 +++++++---- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 9c800dcd1a..09d6d87f06 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -349,6 +349,14 @@ func (n *InlinedCallExpr) SingleResult() Node { if have := len(n.ReturnVars); have != 1 { base.FatalfAt(n.Pos(), "inlined call has %v results, expected 1", have) } + if !n.Type().HasShape() && n.ReturnVars[0].Type().HasShape() { + // If the type of the call is not a shape, but the type of the return value + // is a shape, we need to do an implicit conversion, so the real type + // of n is maintained. + r := NewConvExpr(n.Pos(), OCONVNOP, n.Type(), n.ReturnVars[0]) + r.SetTypecheck(1) + return r + } return n.ReturnVars[0] } diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index efbc8f68ce..86bdb91395 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -161,8 +161,6 @@ func transformCall(n *ir.CallExpr) { typecheck.FixMethodCall(n) } if t.NumResults() == 1 { - n.SetType(l.Type().Results().Field(0).Type) - if n.Op() == ir.OCALLFUNC && n.X.Op() == ir.ONAME { if sym := n.X.(*ir.Name).Sym(); types.IsRuntimePkg(sym.Pkg) && sym.Name == "getg" { // Emit code for runtime.getg() directly instead of calling function. diff --git a/test/run.go b/test/run.go index 55c508dd42..1e01d16067 100644 --- a/test/run.go +++ b/test/run.go @@ -2174,9 +2174,8 @@ var g3Failures = setOf( "typeparam/mdempsky/4.go", // -G=3 can't export functions with labeled breaks in loops - "typeparam/cons.go", // causes an unreachable method - "typeparam/issue44688.go", // interface conversion fails due to missing method - "typeparam/mdempsky/14.go", // interface comparison failure + "typeparam/cons.go", // causes an unreachable method + "typeparam/issue44688.go", // interface conversion fails due to missing method ) var unifiedFailures = setOf( diff --git a/test/typeparam/mdempsky/14.go b/test/typeparam/mdempsky/14.go index 61f9436910..ba685bc35c 100644 --- a/test/typeparam/mdempsky/14.go +++ b/test/typeparam/mdempsky/14.go @@ -6,11 +6,14 @@ package main -func Zero[T any]() (_ T) { return } +// Zero returns the zero value of T +func Zero[T any]() (_ T) { + return +} -type T[X any] int +type AnyInt[X any] int -func (T[X]) M() { +func (AnyInt[X]) M() { var have interface{} = Zero[X]() var want interface{} = Zero[MyInt]() @@ -22,7 +25,7 @@ func (T[X]) M() { type I interface{ M() } type MyInt int -type U = T[MyInt] +type U = AnyInt[MyInt] var x = U(0) var i I = x -- GitLab From 61f69d2559a1177c23dea06343a4784514e8dd85 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Mon, 19 Jul 2021 13:11:50 -0400 Subject: [PATCH 0512/2500] [dev.typeparams] go/types: merge instance and Named to eliminate sanitization Storing temporary syntactic information using an *instance type forces us to be careful not to leak references to *instance in the checker output. This is complex and error prone, as types are written in many places during type checking. Instead, temporarily pin the necessary syntactic information directly to the Named type during the type checking pass. This allows us to avoid having to sanitize references. This includes a couple of small, unrelated changes that were made in the process of debugging: - eliminate the expandf indirection: it is no longer necessary - include type parameters when printing objects For #46151 Change-Id: I767e35b289f2fea512a168997af0f861cd242175 Reviewed-on: https://go-review.googlesource.com/c/go/+/335929 Trust: Robert Findley Trust: Robert Griesemer Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/check.go | 4 - src/go/types/decl.go | 8 +- src/go/types/infer.go | 3 - src/go/types/instance.go | 53 +++---- src/go/types/instantiate.go | 67 ++++---- src/go/types/named.go | 28 ++-- src/go/types/object.go | 3 + src/go/types/predicates.go | 6 +- src/go/types/sanitize.go | 206 ------------------------- src/go/types/sizeof_test.go | 1 - src/go/types/subst.go | 15 +- src/go/types/testdata/check/issues.go2 | 4 +- src/go/types/typeparam.go | 3 +- src/go/types/typestring.go | 7 - src/go/types/typexpr.go | 2 +- 15 files changed, 96 insertions(+), 314 deletions(-) delete mode 100644 src/go/types/sanitize.go diff --git a/src/go/types/check.go b/src/go/types/check.go index 4398475501..b2d076dc68 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -273,10 +273,6 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) { check.recordUntyped() - if check.Info != nil { - sanitizeInfo(check.Info) - } - check.pkg.complete = true // no longer needed - release memory diff --git a/src/go/types/decl.go b/src/go/types/decl.go index e38124f077..1195104b59 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -317,6 +317,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { } case *Named: + t.complete() // don't touch the type if it is from a different package or the Universe scope // (doing so would lead to a race condition - was issue #35049) if t.obj.pkg != check.pkg { @@ -349,9 +350,6 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { panic("internal error: cycle start not found") } return t.info - - case *instance: - return check.validType(t.expand(), path) } return valid @@ -607,6 +605,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { // determine underlying type of named named.fromRHS = check.definedType(tdecl.Type, named) + assert(named.fromRHS != nil) // The underlying type of named may be itself a named type that is // incomplete: @@ -685,7 +684,8 @@ func (check *Checker) boundType(e ast.Expr) Type { bound := check.typ(e) check.later(func() { - if _, ok := under(bound).(*Interface); !ok && bound != Typ[Invalid] { + u := under(bound) + if _, ok := u.(*Interface); !ok && u != Typ[Invalid] { check.errorf(e, _Todo, "%s is not an interface", bound) } }) diff --git a/src/go/types/infer.go b/src/go/types/infer.go index 9faf7b7520..774d2fd158 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -337,9 +337,6 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { // t must be one of w.tparams return t.index < len(w.tparams) && w.tparams[t.index].typ == t - case *instance: - return w.isParameterizedList(t.targs) - default: unreachable() } diff --git a/src/go/types/instance.go b/src/go/types/instance.go index 25f1442881..205cb47046 100644 --- a/src/go/types/instance.go +++ b/src/go/types/instance.go @@ -4,56 +4,39 @@ package types +// TODO(rfindley): move this code to named.go. + import "go/token" -// An instance represents an instantiated generic type syntactically -// (without expanding the instantiation). Type instances appear only -// during type-checking and are replaced by their fully instantiated -// (expanded) types before the end of type-checking. +// instance holds a Checker along with syntactic information +// information, for use in lazy instantiation. type instance struct { - check *Checker // for lazy instantiation + check *Checker pos token.Pos // position of type instantiation; for error reporting only - base *Named // parameterized type to be instantiated - targs []Type // type arguments posList []token.Pos // position of each targ; for error reporting only verify bool // if set, constraint satisfaction is verified - value Type // base[targs...] after instantiation or Typ[Invalid]; nil if not yet set } -// expand returns the instantiated (= expanded) type of t. -// The result is either an instantiated *Named type, or -// Typ[Invalid] if there was an error. -func (t *instance) expand() Type { - v := t.value - if v == nil { - v = t.check.Instantiate(t.pos, t.base, t.targs, t.posList, t.verify) - if v == nil { - v = Typ[Invalid] - } - t.value = v - } - // After instantiation we must have an invalid or a *Named type. - if debug && v != Typ[Invalid] { - _ = v.(*Named) +// complete ensures that the underlying type of n is instantiated. +// The underlying type will be Typ[Invalid] if there was an error. +// TODO(rfindley): expand would be a better name for this method, but conflicts +// with the existing concept of lazy expansion. Need to reconcile this. +func (n *Named) complete() { + if n.instance != nil && len(n.targs) > 0 && n.underlying == nil { + check := n.instance.check + inst := check.instantiate(n.instance.pos, n.orig.underlying, n.tparams, n.targs, n.instance.posList, n.instance.verify) + n.underlying = inst + n.fromRHS = inst + n.methods = n.orig.methods } - return v } // expand expands a type instance into its instantiated // type and leaves all other types alone. expand does // not recurse. func expand(typ Type) Type { - if t, _ := typ.(*instance); t != nil { - return t.expand() + if t, _ := typ.(*Named); t != nil { + t.complete() } return typ } - -// expandf is set to expand. -// Call expandf when calling expand causes compile-time cycle error. -var expandf func(Type) Type - -func init() { expandf = expand } - -func (t *instance) Underlying() Type { return t } -func (t *instance) String() string { return TypeString(t, nil) } diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 99ffb9e604..270652149f 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -25,29 +25,6 @@ import ( // Any methods attached to a *Named are simply copied; they are not // instantiated. func (check *Checker) Instantiate(pos token.Pos, typ Type, targs []Type, posList []token.Pos, verify bool) (res Type) { - if verify && check == nil { - panic("cannot have nil receiver if verify is set") - } - - if check != nil && trace { - check.trace(pos, "-- instantiating %s with %s", typ, typeListString(targs)) - check.indent++ - defer func() { - check.indent-- - var under Type - if res != nil { - // Calling under() here may lead to endless instantiations. - // Test case: type T[P any] T[P] - // TODO(gri) investigate if that's a bug or to be expected. - under = res.Underlying() - } - check.trace(pos, "=> %s (under = %s)", res, under) - }() - } - - assert(len(posList) <= len(targs)) - - // TODO(gri) What is better here: work with TypeParams, or work with TypeNames? var tparams []*TypeName switch t := typ.(type) { case *Named: @@ -77,6 +54,10 @@ func (check *Checker) Instantiate(pos token.Pos, typ Type, targs []Type, posList panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } + return check.instantiate(pos, typ, tparams, targs, posList, verify) +} + +func (check *Checker) instantiate(pos token.Pos, typ Type, tparams []*TypeName, targs []Type, posList []token.Pos, verify bool) (res Type) { // the number of supplied types must match the number of type parameters if len(targs) != len(tparams) { // TODO(gri) provide better error message @@ -86,6 +67,29 @@ func (check *Checker) Instantiate(pos token.Pos, typ Type, targs []Type, posList } panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, len(targs), len(tparams))) } + if verify && check == nil { + panic("cannot have nil receiver if verify is set") + } + + if check != nil && trace { + check.trace(pos, "-- instantiating %s with %s", typ, typeListString(targs)) + check.indent++ + defer func() { + check.indent-- + var under Type + if res != nil { + // Calling under() here may lead to endless instantiations. + // Test case: type T[P any] T[P] + // TODO(gri) investigate if that's a bug or to be expected. + under = res.Underlying() + } + check.trace(pos, "=> %s (under = %s)", res, under) + }() + } + + assert(len(posList) <= len(targs)) + + // TODO(gri) What is better here: work with TypeParams, or work with TypeNames? if len(tparams) == 0 { return typ // nothing to do (minor optimization) @@ -120,15 +124,26 @@ func (check *Checker) InstantiateLazy(pos token.Pos, typ Type, targs []Type, pos if base == nil { panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } + h := instantiatedHash(base, targs) + if check != nil { + if named := check.typMap[h]; named != nil { + return named + } + } - return &instance{ + tname := NewTypeName(pos, base.obj.pkg, base.obj.name, nil) + named := check.newNamed(tname, base, nil, base.tparams, base.methods) // methods are instantiated lazily + named.targs = targs + named.instance = &instance{ check: check, pos: pos, - base: base, - targs: targs, posList: posList, verify: verify, } + if check != nil { + check.typMap[h] = named + } + return named } // satisfies reports whether the type argument targ satisfies the constraint of type parameter diff --git a/src/go/types/named.go b/src/go/types/named.go index 4511f395e0..a500f5663b 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -10,7 +10,7 @@ import "sync" // A Named represents a named (defined) type. type Named struct { - check *Checker // for Named.under implementation; nilled once under has been called + instance *instance // syntactic information for lazy instantiation info typeInfo // for cycle detection obj *TypeName // corresponding declared object orig *Named // original, uninstantiated type @@ -65,7 +65,13 @@ func (t *Named) expand() *Named { // newNamed is like NewNamed but with a *Checker receiver and additional orig argument. func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams []*TypeName, methods []*Func) *Named { - typ := &Named{check: check, obj: obj, orig: orig, fromRHS: underlying, underlying: underlying, tparams: tparams, methods: methods} + var inst *instance + if check != nil { + inst = &instance{ + check: check, + } + } + typ := &Named{instance: inst, obj: obj, orig: orig, fromRHS: underlying, underlying: underlying, tparams: tparams, methods: methods} if typ.orig == nil { typ.orig = typ } @@ -83,10 +89,10 @@ func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tpar if check != nil { check.later(func() { switch typ.under().(type) { - case *Named, *instance: + case *Named: panic("internal error: unexpanded underlying type") } - typ.check = nil + typ.instance = nil }) } return typ @@ -153,6 +159,8 @@ func (t *Named) String() string { return TypeString(t, nil) } // is detected, the result is Typ[Invalid]. If a cycle is detected and // n0.check != nil, the cycle is reported. func (n0 *Named) under() Type { + n0.complete() + u := n0.Underlying() if u == Typ[Invalid] { @@ -168,17 +176,17 @@ func (n0 *Named) under() Type { default: // common case return u - case *Named, *instance: + case *Named: // handled below } - if n0.check == nil { + if n0.instance == nil || n0.instance.check == nil { panic("internal error: Named.check == nil but type is incomplete") } // Invariant: after this point n0 as well as any named types in its // underlying chain should be set up when this function exits. - check := n0.check + check := n0.instance.check // If we can't expand u at this point, it is invalid. n := asNamed(u) @@ -199,12 +207,8 @@ func (n0 *Named) under() Type { var n1 *Named switch u1 := u.(type) { case *Named: + u1.complete() n1 = u1 - case *instance: - n1, _ = u1.expand().(*Named) - if n1 == nil { - u = Typ[Invalid] - } } if n1 == nil { break // end of chain diff --git a/src/go/types/object.go b/src/go/types/object.go index 7913008814..4ea2837ea7 100644 --- a/src/go/types/object.go +++ b/src/go/types/object.go @@ -429,6 +429,9 @@ func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) { if _, ok := typ.(*Basic); ok { return } + if named, _ := typ.(*Named); named != nil && len(named.tparams) > 0 { + writeTParamList(buf, named.tparams, qf, nil) + } if tname.IsAlias() { buf.WriteString(" =") } else { diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index ea2bed720a..ce350f4470 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -10,7 +10,7 @@ package types // isNamed may be called with types that are not fully set up. func isNamed(typ Type) bool { switch typ.(type) { - case *Basic, *Named, *TypeParam, *instance: + case *Basic, *Named, *TypeParam: return true } return false @@ -159,8 +159,8 @@ func (p *ifacePair) identical(q *ifacePair) bool { // For changes to this code the corresponding changes should be made to unifier.nify. func identical(x, y Type, cmpTags bool, p *ifacePair) bool { // types must be expanded for comparison - x = expandf(x) - y = expandf(y) + x = expand(x) + y = expand(y) if x == y { return true diff --git a/src/go/types/sanitize.go b/src/go/types/sanitize.go deleted file mode 100644 index 62b91ef8c3..0000000000 --- a/src/go/types/sanitize.go +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package types - -// sanitizeInfo walks the types contained in info to ensure that all instances -// are expanded. -// -// This includes some objects that may be shared across concurrent -// type-checking passes (such as those in the universe scope), so we are -// careful here not to write types that are already sanitized. This avoids a -// data race as any shared types should already be sanitized. -func sanitizeInfo(info *Info) { - var s sanitizer = make(map[Type]Type) - - // Note: Some map entries are not references. - // If modified, they must be assigned back. - - for e, tv := range info.Types { - if typ := s.typ(tv.Type); typ != tv.Type { - tv.Type = typ - info.Types[e] = tv - } - } - - inferred := info.Inferred - for e, inf := range inferred { - changed := false - for i, targ := range inf.TArgs { - if typ := s.typ(targ); typ != targ { - inf.TArgs[i] = typ - changed = true - } - } - if typ := s.typ(inf.Sig); typ != inf.Sig { - inf.Sig = typ.(*Signature) - changed = true - } - if changed { - inferred[e] = inf - } - } - - for _, obj := range info.Defs { - if obj != nil { - if typ := s.typ(obj.Type()); typ != obj.Type() { - obj.setType(typ) - } - } - } - - for _, obj := range info.Uses { - if obj != nil { - if typ := s.typ(obj.Type()); typ != obj.Type() { - obj.setType(typ) - } - } - } - - // TODO(gri) sanitize as needed - // - info.Implicits - // - info.Selections - // - info.Scopes - // - info.InitOrder -} - -type sanitizer map[Type]Type - -func (s sanitizer) typ(typ Type) Type { - if typ == nil { - return nil - } - - if t, found := s[typ]; found { - return t - } - s[typ] = typ - - switch t := typ.(type) { - case *Basic, *top: - // nothing to do - - case *Array: - if elem := s.typ(t.elem); elem != t.elem { - t.elem = elem - } - - case *Slice: - if elem := s.typ(t.elem); elem != t.elem { - t.elem = elem - } - - case *Struct: - s.varList(t.fields) - - case *Pointer: - if base := s.typ(t.base); base != t.base { - t.base = base - } - - case *Tuple: - s.tuple(t) - - case *Signature: - s.var_(t.recv) - s.tuple(t.params) - s.tuple(t.results) - - case *Union: - s.typeList(t.types) - - case *Interface: - s.funcList(t.methods) - s.typeList(t.embeddeds) - // TODO(gri) do we need to sanitize type sets? - tset := t.typeSet() - s.funcList(tset.methods) - if types := s.typ(tset.types); types != tset.types { - tset.types = types - } - - case *Map: - if key := s.typ(t.key); key != t.key { - t.key = key - } - if elem := s.typ(t.elem); elem != t.elem { - t.elem = elem - } - - case *Chan: - if elem := s.typ(t.elem); elem != t.elem { - t.elem = elem - } - - case *Named: - if debug && t.check != nil { - panic("internal error: Named.check != nil") - } - t.expand() - if orig := s.typ(t.fromRHS); orig != t.fromRHS { - t.fromRHS = orig - } - if under := s.typ(t.underlying); under != t.underlying { - t.underlying = under - } - s.typeList(t.targs) - s.funcList(t.methods) - - case *TypeParam: - if bound := s.typ(t.bound); bound != t.bound { - t.bound = bound - } - - case *instance: - typ = t.expand() - s[t] = typ - - default: - panic("unimplemented") - } - - return typ -} - -func (s sanitizer) var_(v *Var) { - if v != nil { - if typ := s.typ(v.typ); typ != v.typ { - v.typ = typ - } - } -} - -func (s sanitizer) varList(list []*Var) { - for _, v := range list { - s.var_(v) - } -} - -func (s sanitizer) tuple(t *Tuple) { - if t != nil { - s.varList(t.vars) - } -} - -func (s sanitizer) func_(f *Func) { - if f != nil { - if typ := s.typ(f.typ); typ != f.typ { - f.typ = typ - } - } -} - -func (s sanitizer) funcList(list []*Func) { - for _, f := range list { - s.func_(f) - } -} - -func (s sanitizer) typeList(list []Type) { - for i, t := range list { - if typ := s.typ(t); typ != t { - list[i] = typ - } - } -} diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index 8c18de8675..fc548f7c58 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -32,7 +32,6 @@ func TestSizeof(t *testing.T) { {Chan{}, 12, 24}, {Named{}, 84, 160}, {TypeParam{}, 28, 48}, - {instance{}, 48, 96}, {top{}, 0, 0}, // Objects diff --git a/src/go/types/subst.go b/src/go/types/subst.go index ec85a6bfc4..42be508cd9 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -29,12 +29,7 @@ func makeSubstMap(tpars []*TypeName, targs []Type) *substMap { assert(len(tpars) == len(targs)) proj := make(map[*TypeParam]Type, len(tpars)) for i, tpar := range tpars { - // We must expand type arguments otherwise *instance - // types end up as components in composite types. - // TODO(gri) explain why this causes problems, if it does - targ := expand(targs[i]) // possibly nil - targs[i] = targ - proj[tpar.typ.(*TypeParam)] = targ + proj[tpar.typ.(*TypeParam)] = targs[i] } return &substMap{targs, proj} } @@ -86,6 +81,7 @@ func (check *Checker) subst(pos token.Pos, typ Type, smap *substMap) Type { // for recursive types (example: type T[P any] *T[P]). subst.typMap = make(map[string]*Named) } + return subst.typ(typ) } @@ -248,10 +244,13 @@ func (subst *subster) typ(typ Type) Type { named := subst.check.newNamed(tname, t, t.Underlying(), t.TParams(), t.methods) // method signatures are updated lazily named.targs = newTargs subst.typMap[h] = named + t.complete() // must happen after typMap update to avoid infinite recursion // do the substitution dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, newTargs) named.underlying = subst.typOrNil(t.Underlying()) + dump(">>> underlying: %v", named.underlying) + assert(named.underlying != nil) named.fromRHS = named.underlying // for cycle detection (Checker.validType) return named @@ -259,10 +258,6 @@ func (subst *subster) typ(typ Type) Type { case *TypeParam: return subst.smap.lookup(t) - case *instance: - // TODO(gri) can we avoid the expansion here and just substitute the type parameters? - return subst.typ(t.expand()) - default: panic("unimplemented") } diff --git a/src/go/types/testdata/check/issues.go2 b/src/go/types/testdata/check/issues.go2 index c57f002303..ce0d608216 100644 --- a/src/go/types/testdata/check/issues.go2 +++ b/src/go/types/testdata/check/issues.go2 @@ -81,8 +81,10 @@ func (u T2[U]) Add1() U { return u.s + 1 } +// TODO(rfindley): we should probably report an error here as well, not +// just when the type is first instantiated. func NewT2[U any]() T2[U /* ERROR U has no type constraints */ ] { - return T2[U /* ERROR U has no type constraints */ ]{} + return T2[U]{} } func _() { diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index e42c24f8cb..bb5b28cdf8 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -24,7 +24,8 @@ type TypeParam struct { id uint64 // unique id, for debugging only obj *TypeName // corresponding type name index int // type parameter index in source order, starting at 0 - bound Type // *Named or *Interface; underlying type is always *Interface + // TODO(rfindley): this could also be Typ[Invalid]. Verify that this is handled correctly. + bound Type // *Named or *Interface; underlying type is always *Interface } // NewTypeParam returns a new TypeParam. bound can be nil (and set later). diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index cba678588a..ef3808230a 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -295,13 +295,6 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { } buf.WriteString(s + subscript(t.id)) - case *instance: - buf.WriteByte(instanceMarker) // indicate "non-evaluated" syntactic instance - writeTypeName(buf, t.base.obj, qf) - buf.WriteByte('[') - writeTypeList(buf, t.targs, qf, visited) - buf.WriteByte(']') - case *top: buf.WriteString("⊤") diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index f2c4762a6b..a812ba6519 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -436,7 +436,7 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named // make sure we check instantiation works at least once // and that the resulting type is valid check.later(func() { - t := typ.(*instance).expand() + t := expand(typ) check.validType(t, nil) }) -- GitLab From b7149b781fda907078b9312d301ea384e91482ef Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Tue, 20 Jul 2021 13:07:50 -0400 Subject: [PATCH 0513/2500] [dev.typeparams] go/types: trigger verification while resolving instance The refactoring of CL 335929 to merge the instance and Named types resulted in type instances only being evaluated once. As a side effect, we only verified constraints once per unique instantiation expression. This can be confusing if type instantations are occurring far apart in the code. Resolve this by lifting up the verification logic into Instantiate and InstantiateLazy. Change-Id: Icd5a482d097d983073955c62931441edfd92f5c2 Reviewed-on: https://go-review.googlesource.com/c/go/+/335978 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/instance.go | 2 +- src/go/types/instantiate.go | 52 +++++++++++++++----------- src/go/types/testdata/check/issues.go2 | 4 +- 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/src/go/types/instance.go b/src/go/types/instance.go index 205cb47046..9d31b42690 100644 --- a/src/go/types/instance.go +++ b/src/go/types/instance.go @@ -24,7 +24,7 @@ type instance struct { func (n *Named) complete() { if n.instance != nil && len(n.targs) > 0 && n.underlying == nil { check := n.instance.check - inst := check.instantiate(n.instance.pos, n.orig.underlying, n.tparams, n.targs, n.instance.posList, n.instance.verify) + inst := check.instantiate(n.instance.pos, n.orig.underlying, n.tparams, n.targs, n.instance.posList) n.underlying = inst n.fromRHS = inst n.methods = n.orig.methods diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 270652149f..14bbf2b12b 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -54,10 +54,14 @@ func (check *Checker) Instantiate(pos token.Pos, typ Type, targs []Type, posList panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } - return check.instantiate(pos, typ, tparams, targs, posList, verify) + inst := check.instantiate(pos, typ, tparams, targs, posList) + if verify && len(tparams) == len(targs) { + check.verify(pos, tparams, targs, posList) + } + return inst } -func (check *Checker) instantiate(pos token.Pos, typ Type, tparams []*TypeName, targs []Type, posList []token.Pos, verify bool) (res Type) { +func (check *Checker) instantiate(pos token.Pos, typ Type, tparams []*TypeName, targs []Type, posList []token.Pos) (res Type) { // the number of supplied types must match the number of type parameters if len(targs) != len(tparams) { // TODO(gri) provide better error message @@ -67,9 +71,6 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, tparams []*TypeName, } panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, len(targs), len(tparams))) } - if verify && check == nil { - panic("cannot have nil receiver if verify is set") - } if check != nil && trace { check.trace(pos, "-- instantiating %s with %s", typ, typeListString(targs)) @@ -97,22 +98,6 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, tparams []*TypeName, smap := makeSubstMap(tparams, targs) - // check bounds - if verify { - for i, tname := range tparams { - // best position for error reporting - pos := pos - if i < len(posList) { - pos = posList[i] - } - - // stop checking bounds after the first failure - if !check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap) { - break - } - } - } - return check.subst(pos, typ, smap) } @@ -124,6 +109,11 @@ func (check *Checker) InstantiateLazy(pos token.Pos, typ Type, targs []Type, pos if base == nil { panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } + if verify && len(base.tparams) == len(targs) { + check.later(func() { + check.verify(pos, base.tparams, targs, posList) + }) + } h := instantiatedHash(base, targs) if check != nil { if named := check.typMap[h]; named != nil { @@ -146,6 +136,26 @@ func (check *Checker) InstantiateLazy(pos token.Pos, typ Type, targs []Type, pos return named } +func (check *Checker) verify(pos token.Pos, tparams []*TypeName, targs []Type, posList []token.Pos) { + if check == nil { + panic("cannot have nil Checker if verifying constraints") + } + + smap := makeSubstMap(tparams, targs) + for i, tname := range tparams { + // best position for error reporting + pos := pos + if i < len(posList) { + pos = posList[i] + } + + // stop checking bounds after the first failure + if !check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap) { + break + } + } +} + // satisfies reports whether the type argument targ satisfies the constraint of type parameter // parameter tpar (after any of its type parameters have been substituted through smap). // A suitable error is reported if the result is false. diff --git a/src/go/types/testdata/check/issues.go2 b/src/go/types/testdata/check/issues.go2 index ce0d608216..c57f002303 100644 --- a/src/go/types/testdata/check/issues.go2 +++ b/src/go/types/testdata/check/issues.go2 @@ -81,10 +81,8 @@ func (u T2[U]) Add1() U { return u.s + 1 } -// TODO(rfindley): we should probably report an error here as well, not -// just when the type is first instantiated. func NewT2[U any]() T2[U /* ERROR U has no type constraints */ ] { - return T2[U]{} + return T2[U /* ERROR U has no type constraints */ ]{} } func _() { -- GitLab From 311baf65f49f4b15396f7e88c05bc97d47f2e4ed Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 2 Jul 2021 15:42:20 -0700 Subject: [PATCH 0514/2500] [dev.typeparams] test: cleanup 'go env' and -goexperiment This CL makes two related changes: 1. It uses 'go env -json' to query the environment configuration, rather than attempting to manually reconstruct the values that cmd/go is going to use. 2. It changes the -goexperiment flag to *extend* any ambient GOEXPERIMENT configuration. Notably, this means that '-goexperiment fieldtrack' now tests fieldtracking in conjunction with any other experiments (e.g., unified IR). Tests that want to test an exact GOEXPERIMENT config should use '-goexperiment none,foo' instead. Change-Id: I96a97198209e540e934fe7035110c3ae3a8f0e6a Reviewed-on: https://go-review.googlesource.com/c/go/+/332610 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- test/run.go | 66 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/test/run.go b/test/run.go index 1e01d16067..23eebcee2e 100644 --- a/test/run.go +++ b/test/run.go @@ -9,6 +9,7 @@ package main import ( "bytes" + "encoding/json" "errors" "flag" "fmt" @@ -49,17 +50,36 @@ var ( shards = flag.Int("shards", 0, "number of shards. If 0, all tests are run. This is used by the continuous build.") ) -var unifiedEnabled, defaultGLevels = func() (bool, string) { - // TODO(mdempsky): Change this to just "go env GOEXPERIMENT" after - // CL 328751 is merged back to dev.typeparams. In the mean time, we - // infer whether the "unified" experiment is default enabled by - // inspecting the output from `go tool compile -V`. - output := runOutput(goTool(), "tool", "compile", "-V") +type envVars struct { + GOOS string + GOARCH string + GOEXPERIMENT string + CGO_ENABLED string +} + +var env = func() (res envVars) { + cmd := exec.Command("go", "env", "-json") + stdout, err := cmd.StdoutPipe() + if err != nil { + log.Fatal("StdoutPipe:", err) + } + if err := cmd.Start(); err != nil { + log.Fatal("Start:", err) + } + if err := json.NewDecoder(stdout).Decode(&res); err != nil { + log.Fatal("Decode:", err) + } + if err := cmd.Wait(); err != nil { + log.Fatal("Wait:", err) + } + return +}() +var unifiedEnabled, defaultGLevels = func() (bool, string) { // TODO(mdempsky): This will give false negatives if the unified // experiment is enabled by default, but presumably at that point we // won't need to disable tests for it anymore anyway. - enabled := strings.Contains(output, "unified") + enabled := strings.Contains(","+env.GOEXPERIMENT+",", ",unified,") // Normal test runs should test with both -G=0 and -G=3 for types2 // coverage. But the unified experiment always uses types2, so @@ -81,8 +101,9 @@ func defaultAllCodeGen() bool { } var ( - goos, goarch string - cgoEnabled bool + goos = env.GOOS + goarch = env.GOARCH + cgoEnabled, _ = strconv.ParseBool(env.CGO_ENABLED) // dirs are the directories to look for *.go files in. // TODO(bradfitz): just use all directories? @@ -116,12 +137,6 @@ func main() { glevels = append(glevels, glevel) } - goos = getenv("GOOS", runtime.GOOS) - goarch = getenv("GOARCH", runtime.GOARCH) - - cgoEnv := runOutput(goTool(), "env", "CGO_ENABLED") - cgoEnabled, _ = strconv.ParseBool(strings.TrimSpace(cgoEnv)) - findExecCmd() // Disable parallelism if printing or if using a simulator. @@ -214,17 +229,6 @@ func main() { } } -// runOutput runs the specified command and returns its output as a -// string. If the command fails, runOutput logs the error and exits. -func runOutput(name string, args ...string) string { - cmd := exec.Command(name, args...) - output, err := cmd.Output() - if err != nil { - log.Fatalf("running %v: %v", cmd, err) - } - return string(output) -} - // goTool reports the path of the go tool to use to run the tests. // If possible, use the same Go used to run run.go, otherwise // fallback to the go version found in the PATH. @@ -672,6 +676,8 @@ func (t *test) run() { return } + goexp := env.GOEXPERIMENT + // collect flags for len(args) > 0 && strings.HasPrefix(args[0], "-") { switch args[0] { @@ -698,7 +704,11 @@ func (t *test) run() { } case "-goexperiment": // set GOEXPERIMENT environment args = args[1:] - runenv = append(runenv, "GOEXPERIMENT="+args[0]) + if goexp != "" { + goexp += "," + } + goexp += args[0] + runenv = append(runenv, "GOEXPERIMENT="+goexp) default: flags = append(flags, args[0]) @@ -1258,7 +1268,7 @@ func (t *test) run() { runInDir = "" var out []byte var err error - if len(flags)+len(args) == 0 && t.goGcflagsIsEmpty() && !*linkshared && goarch == runtime.GOARCH && goos == runtime.GOOS { + if len(flags)+len(args) == 0 && t.goGcflagsIsEmpty() && !*linkshared && goarch == runtime.GOARCH && goos == runtime.GOOS && goexp == env.GOEXPERIMENT { // If we're not using special go command flags, // skip all the go command machinery. // This avoids any time the go command would -- GitLab From 6f57139c7a6bc776f1335aca13d276d36343cf7c Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Wed, 21 Jul 2021 10:21:23 -0400 Subject: [PATCH 0515/2500] [dev.typeparams] go/types: set type parameter indices when they are bound It is invalid to use a type parameter for more than one type, so we can avoid passing the type parameter index to NewTypeParam and just set it when type parameters are bound to a type via SetTParams or during type checking. In order to enforce the correctness of this change, introduce a TypeParams type to represent a list of type parameters that have been associated with a type. For now, expose this new type as the API for type parameters, but this is of course not necessarily a final API. Allowing *TypeParams to be nil also decreases the size of Named and Signature, which is good as most instances of these types will not be parameterized. Change-Id: Ia1e39ba51edb05bb535eb5f41c34e9dd02d39c38 Reviewed-on: https://go-review.googlesource.com/c/go/+/336249 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/api_test.go | 2 +- src/go/types/assignments.go | 2 +- src/go/types/builtins.go | 3 ++- src/go/types/call.go | 20 +++++++-------- src/go/types/decl.go | 8 +++--- src/go/types/index.go | 2 +- src/go/types/instance.go | 2 +- src/go/types/instantiate.go | 10 ++++---- src/go/types/lookup.go | 18 ++++++------- src/go/types/named.go | 16 ++++++------ src/go/types/object.go | 4 +-- src/go/types/predicates.go | 2 +- src/go/types/signature.go | 25 +++++++++++-------- src/go/types/sizeof_test.go | 4 +-- src/go/types/subst.go | 4 +-- src/go/types/typeparam.go | 50 ++++++++++++++++++++++++++++++++++--- src/go/types/typestring.go | 4 +-- 17 files changed, 111 insertions(+), 65 deletions(-) diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index 444cb44087..b2d532c4c8 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -1828,7 +1828,7 @@ func TestInstantiate(t *testing.T) { // type T should have one type parameter T := pkg.Scope().Lookup("T").Type().(*Named) - if n := len(T.TParams()); n != 1 { + if n := T.TParams().Len(); n != 1 { t.Fatalf("expected 1 type parameter; found %d", n) } diff --git a/src/go/types/assignments.go b/src/go/types/assignments.go index 18eae62184..595f426e10 100644 --- a/src/go/types/assignments.go +++ b/src/go/types/assignments.go @@ -71,7 +71,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { } // A generic (non-instantiated) function value cannot be assigned to a variable. - if sig := asSignature(x.typ); sig != nil && len(sig.tparams) > 0 { + if sig := asSignature(x.typ); sig != nil && sig.TParams().Len() > 0 { check.errorf(x, _Todo, "cannot use generic function %s without instantiation in %s", x, context) } diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 2edf901165..b6fb36b185 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -806,7 +806,8 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { // type param is placed in the current package so export/import // works as expected. tpar := NewTypeName(token.NoPos, check.pkg, "", nil) - ptyp := check.NewTypeParam(tpar, tp.index, &emptyInterface) // assigns type to tpar as a side-effect + ptyp := check.NewTypeParam(tpar, &emptyInterface) // assigns type to tpar as a side-effect + ptyp.index = tp.index tsum := newUnion(rtypes, tildes) ptyp.bound = &Interface{complete: true, tset: &TypeSet{types: tsum}} diff --git a/src/go/types/call.go b/src/go/types/call.go index 9453b53c3a..96d0429af9 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -27,7 +27,7 @@ func (check *Checker) funcInst(x *operand, ix *typeparams.IndexExpr) { // check number of type arguments (got) vs number of type parameters (want) sig := x.typ.(*Signature) - got, want := len(targs), len(sig.tparams) + got, want := len(targs), sig.TParams().Len() if got > want { check.errorf(ix.Indices[got-1], _Todo, "got %d type arguments but want %d", got, want) x.mode = invalid @@ -39,7 +39,7 @@ func (check *Checker) funcInst(x *operand, ix *typeparams.IndexExpr) { inferred := false if got < want { - targs = check.infer(ix.Orig, sig.tparams, targs, nil, nil, true) + targs = check.infer(ix.Orig, sig.TParams().list(), targs, nil, nil, true) if targs == nil { // error was already reported x.mode = invalid @@ -160,7 +160,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { assert(len(targs) == len(ix.Indices)) // check number of type arguments (got) vs number of type parameters (want) - got, want := len(targs), len(sig.tparams) + got, want := len(targs), sig.TParams().Len() if got > want { check.errorf(ix.Indices[want], _Todo, "got %d type arguments but want %d", got, want) check.use(call.Args...) @@ -194,7 +194,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { // if type inference failed, a parametrized result must be invalidated // (operands cannot have a parametrized type) - if x.mode == value && len(sig.tparams) > 0 && isParameterized(sig.tparams, x.typ) { + if x.mode == value && sig.TParams().Len() > 0 && isParameterized(sig.TParams().list(), x.typ) { x.mode = invalid } @@ -324,10 +324,10 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type } // infer type arguments and instantiate signature if necessary - if len(sig.tparams) > 0 { + if sig.TParams().Len() > 0 { // TODO(gri) provide position information for targs so we can feed // it to the instantiate call for better error reporting - targs := check.infer(call, sig.tparams, targs, sigParams, args, true) + targs := check.infer(call, sig.TParams().list(), targs, sigParams, args, true) if targs == nil { return // error already reported } @@ -341,7 +341,7 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type // need to compute it from the adjusted list; otherwise we can // simply use the result signature's parameter list. if adjusted { - sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(sig.tparams, targs)).(*Tuple) + sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(sig.TParams().list(), targs)).(*Tuple) } else { sigParams = rsig.params } @@ -517,7 +517,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { // the signature accordingly. // TODO(gri) factor this code out sig := m.typ.(*Signature) - if len(sig.rparams) > 0 { + if sig.RParams().Len() > 0 { // For inference to work, we must use the receiver type // matching the receiver in the actual method declaration. // If the method is embedded, the matching receiver is the @@ -545,7 +545,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { // the receiver type arguments here, the receiver must be be otherwise invalid // and an error has been reported elsewhere. arg := operand{mode: variable, expr: x.expr, typ: recv} - targs := check.infer(m, sig.rparams, nil, NewTuple(sig.recv), []*operand{&arg}, false /* no error reporting */) + targs := check.infer(m, sig.RParams().list(), nil, NewTuple(sig.recv), []*operand{&arg}, false /* no error reporting */) if targs == nil { // We may reach here if there were other errors (see issue #40056). goto Error @@ -554,7 +554,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { // (If we modify m, some tests will fail; possibly because the m is in use.) // TODO(gri) investigate and provide a correct explanation here copy := *m - copy.typ = check.subst(e.Pos(), m.typ, makeSubstMap(sig.rparams, targs)) + copy.typ = check.subst(e.Pos(), m.typ, makeSubstMap(sig.RParams().list(), targs)) obj = © } // TODO(gri) we also need to do substitution for parameterized interface methods diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 1195104b59..be7753d9d1 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -625,13 +625,13 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { named.underlying = under(named) // If the RHS is a type parameter, it must be from this type declaration. - if tpar, _ := named.underlying.(*TypeParam); tpar != nil && tparamIndex(named.tparams, tpar) < 0 { + if tpar, _ := named.underlying.(*TypeParam); tpar != nil && tparamIndex(named.tparams.list(), tpar) < 0 { check.errorf(tdecl.Type, _Todo, "cannot use function type parameter %s as RHS in type declaration", tpar) named.underlying = Typ[Invalid] } } -func (check *Checker) collectTypeParams(list *ast.FieldList) []*TypeName { +func (check *Checker) collectTypeParams(list *ast.FieldList) *TypeParams { var tparams []*TypeName // Declare type parameters up-front, with empty interface as type bound. // The scope of type parameters starts at the beginning of the type parameter @@ -655,13 +655,13 @@ func (check *Checker) collectTypeParams(list *ast.FieldList) []*TypeName { index += len(f.Names) } - return tparams + return bindTParams(tparams) } func (check *Checker) declareTypeParams(tparams []*TypeName, names []*ast.Ident) []*TypeName { for _, name := range names { tpar := NewTypeName(name.Pos(), check.pkg, name.Name, nil) - check.NewTypeParam(tpar, len(tparams), &emptyInterface) // assigns type to tpar as a side-effect + check.NewTypeParam(tpar, &emptyInterface) // assigns type to tpar as a side-effect check.declare(check.scope, name, tpar, check.scope.pos) // TODO(gri) check scope position tparams = append(tparams, tpar) } diff --git a/src/go/types/index.go b/src/go/types/index.go index b2a5a2e948..a49bc5519c 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -33,7 +33,7 @@ func (check *Checker) indexExpr(x *operand, e *typeparams.IndexExpr) (isFuncInst return false case value: - if sig := asSignature(x.typ); sig != nil && len(sig.tparams) > 0 { + if sig := asSignature(x.typ); sig != nil && sig.TParams().Len() > 0 { // function instantiation return true } diff --git a/src/go/types/instance.go b/src/go/types/instance.go index 9d31b42690..7e158ea352 100644 --- a/src/go/types/instance.go +++ b/src/go/types/instance.go @@ -24,7 +24,7 @@ type instance struct { func (n *Named) complete() { if n.instance != nil && len(n.targs) > 0 && n.underlying == nil { check := n.instance.check - inst := check.instantiate(n.instance.pos, n.orig.underlying, n.tparams, n.targs, n.instance.posList) + inst := check.instantiate(n.instance.pos, n.orig.underlying, n.TParams().list(), n.targs, n.instance.posList) n.underlying = inst n.fromRHS = inst n.methods = n.orig.methods diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 14bbf2b12b..7e2f3173c3 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -28,9 +28,9 @@ func (check *Checker) Instantiate(pos token.Pos, typ Type, targs []Type, posList var tparams []*TypeName switch t := typ.(type) { case *Named: - tparams = t.TParams() + tparams = t.TParams().list() case *Signature: - tparams = t.tparams + tparams = t.TParams().list() defer func() { // If we had an unexpected failure somewhere don't panic below when // asserting res.(*Signature). Check for *Signature in case Typ[Invalid] @@ -109,9 +109,9 @@ func (check *Checker) InstantiateLazy(pos token.Pos, typ Type, targs []Type, pos if base == nil { panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } - if verify && len(base.tparams) == len(targs) { + if verify && base.TParams().Len() == len(targs) { check.later(func() { - check.verify(pos, base.tparams, targs, posList) + check.verify(pos, base.tparams.list(), targs, posList) }) } h := instantiatedHash(base, targs) @@ -122,7 +122,7 @@ func (check *Checker) InstantiateLazy(pos token.Pos, typ Type, targs []Type, pos } tname := NewTypeName(pos, base.obj.pkg, base.obj.name, nil) - named := check.newNamed(tname, base, nil, base.tparams, base.methods) // methods are instantiated lazily + named := check.newNamed(tname, base, nil, base.TParams(), base.methods) // methods are instantiated lazily named.targs = targs named.instance = &instance{ check: check, diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index 304ae6e3c9..8b1d70a978 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -317,10 +317,10 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // both methods must have the same number of type parameters ftyp := f.typ.(*Signature) mtyp := m.typ.(*Signature) - if len(ftyp.tparams) != len(mtyp.tparams) { + if ftyp.TParams().Len() != mtyp.TParams().Len() { return m, f } - if len(ftyp.tparams) > 0 { + if ftyp.TParams().Len() > 0 { panic("internal error: method with type parameters") } @@ -330,7 +330,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // TODO(gri) is this always correct? what about type bounds? // (Alternative is to rename/subst type parameters and compare.) u := newUnifier(true) - u.x.init(ftyp.tparams) + u.x.init(ftyp.TParams().list()) if !u.unify(ftyp, mtyp) { return m, f } @@ -373,10 +373,10 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // both methods must have the same number of type parameters ftyp := f.typ.(*Signature) mtyp := m.typ.(*Signature) - if len(ftyp.tparams) != len(mtyp.tparams) { + if ftyp.TParams().Len() != mtyp.TParams().Len() { return m, f } - if len(ftyp.tparams) > 0 { + if ftyp.TParams().Len() > 0 { panic("internal error: method with type parameters") } @@ -387,17 +387,17 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // In order to compare the signatures, substitute the receiver // type parameters of ftyp with V's instantiation type arguments. // This lazily instantiates the signature of method f. - if Vn != nil && len(Vn.TParams()) > 0 { + if Vn != nil && Vn.TParams().Len() > 0 { // Be careful: The number of type arguments may not match // the number of receiver parameters. If so, an error was // reported earlier but the length discrepancy is still // here. Exit early in this case to prevent an assertion // failure in makeSubstMap. // TODO(gri) Can we avoid this check by fixing the lengths? - if len(ftyp.rparams) != len(Vn.targs) { + if len(ftyp.RParams().list()) != len(Vn.targs) { return } - ftyp = check.subst(token.NoPos, ftyp, makeSubstMap(ftyp.rparams, Vn.targs)).(*Signature) + ftyp = check.subst(token.NoPos, ftyp, makeSubstMap(ftyp.RParams().list(), Vn.targs)).(*Signature) } // If the methods have type parameters we don't care whether they @@ -406,7 +406,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // TODO(gri) is this always correct? what about type bounds? // (Alternative is to rename/subst type parameters and compare.) u := newUnifier(true) - u.x.init(ftyp.rparams) + u.x.init(ftyp.RParams().list()) if !u.unify(ftyp, mtyp) { return m, f } diff --git a/src/go/types/named.go b/src/go/types/named.go index a500f5663b..03af3fbc5a 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -16,7 +16,7 @@ type Named struct { orig *Named // original, uninstantiated type fromRHS Type // type (on RHS of declaration) this *Named type is derived of (for cycle reporting) underlying Type // possibly a *Named during setup; never a *Named once set up completely - tparams []*TypeName // type parameters, or nil + tparams *TypeParams // type parameters, or nil targs []Type // type arguments (after instantiation), or nil methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily @@ -56,7 +56,7 @@ func (t *Named) expand() *Named { panic("invalid underlying type") } - t.tparams = tparams + t.tparams = bindTParams(tparams) t.underlying = underlying t.methods = methods }) @@ -64,7 +64,7 @@ func (t *Named) expand() *Named { } // newNamed is like NewNamed but with a *Checker receiver and additional orig argument. -func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams []*TypeName, methods []*Func) *Named { +func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams *TypeParams, methods []*Func) *Named { var inst *instance if check != nil { inst = &instance{ @@ -108,14 +108,14 @@ func (t *Named) _Orig() *Named { return t.orig } // TODO(gri) Come up with a better representation and API to distinguish // between parameterized instantiated and non-instantiated types. -// _TParams returns the type parameters of the named type t, or nil. +// TParams returns the type parameters of the named type t, or nil. // The result is non-nil for an (originally) parameterized type even if it is instantiated. -func (t *Named) TParams() []*TypeName { return t.expand().tparams } +func (t *Named) TParams() *TypeParams { return t.expand().tparams } -// _SetTParams sets the type parameters of the named type t. -func (t *Named) SetTParams(tparams []*TypeName) { t.expand().tparams = tparams } +// SetTParams sets the type parameters of the named type t. +func (t *Named) SetTParams(tparams []*TypeName) { t.expand().tparams = bindTParams(tparams) } -// _TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated. +// TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated. func (t *Named) TArgs() []Type { return t.targs } // SetTArgs sets the type arguments of the named type t. diff --git a/src/go/types/object.go b/src/go/types/object.go index 4ea2837ea7..7266623fbe 100644 --- a/src/go/types/object.go +++ b/src/go/types/object.go @@ -429,8 +429,8 @@ func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) { if _, ok := typ.(*Basic); ok { return } - if named, _ := typ.(*Named); named != nil && len(named.tparams) > 0 { - writeTParamList(buf, named.tparams, qf, nil) + if named, _ := typ.(*Named); named != nil && named.TParams().Len() > 0 { + writeTParamList(buf, named.TParams().list(), qf, nil) } if tname.IsAlias() { buf.WriteString(" =") diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index ce350f4470..181e2fcfc5 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -242,7 +242,7 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { // parameter names. if y, ok := y.(*Signature); ok { return x.variadic == y.variadic && - identicalTParams(x.tparams, y.tparams, cmpTags, p) && + identicalTParams(x.TParams().list(), y.TParams().list(), cmpTags, p) && identical(x.params, y.params, cmpTags, p) && identical(x.results, y.results, cmpTags, p) } diff --git a/src/go/types/signature.go b/src/go/types/signature.go index da01ec801a..5a69bb17b5 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -21,8 +21,8 @@ type Signature struct { // and store it in the Func Object) because when type-checking a function // literal we call the general type checker which returns a general Type. // We then unpack the *Signature and use the scope for the literal body. - rparams []*TypeName // receiver type parameters from left to right, or nil - tparams []*TypeName // type parameters from left to right, or nil + rparams *TypeParams // receiver type parameters from left to right, or nil + tparams *TypeParams // type parameters from left to right, or nil scope *Scope // function scope, present for package-local signatures recv *Var // nil if not a method params *Tuple // (incoming) parameters from left to right; or nil @@ -56,13 +56,16 @@ func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature { func (s *Signature) Recv() *Var { return s.recv } // TParams returns the type parameters of signature s, or nil. -func (s *Signature) TParams() []*TypeName { return s.tparams } +func (s *Signature) TParams() *TypeParams { return s.tparams } // SetTParams sets the type parameters of signature s. -func (s *Signature) SetTParams(tparams []*TypeName) { s.tparams = tparams } +func (s *Signature) SetTParams(tparams []*TypeName) { s.tparams = bindTParams(tparams) } + +// RParams returns the receiver type parameters of signature s, or nil. +func (s *Signature) RParams() *TypeParams { return s.rparams } // SetRParams sets the receiver type params of signature s. -func (s *Signature) SetRParams(rparams []*TypeName) { s.rparams = rparams } +func (s *Signature) SetRParams(rparams []*TypeName) { s.rparams = bindTParams(rparams) } // Params returns the parameters of signature s, or nil. func (s *Signature) Params() *Tuple { return s.params } @@ -115,7 +118,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast // blank identifiers were found => use rewritten receiver type recvTyp = isubst(recvPar.List[0].Type, smap) } - sig.rparams = check.declareTypeParams(nil, rparams) + sig.rparams = bindTParams(check.declareTypeParams(nil, rparams)) // determine receiver type to get its type parameters // and the respective type parameter bounds var recvTParams []*TypeName @@ -125,19 +128,19 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast // again when we type-check the signature. // TODO(gri) maybe the receiver should be marked as invalid instead? if recv := asNamed(check.genericType(rname, false)); recv != nil { - recvTParams = recv.TParams() + recvTParams = recv.TParams().list() } } // provide type parameter bounds // - only do this if we have the right number (otherwise an error is reported elsewhere) - if len(sig.rparams) == len(recvTParams) { + if sig.RParams().Len() == len(recvTParams) { // We have a list of *TypeNames but we need a list of Types. - list := make([]Type, len(sig.rparams)) - for i, t := range sig.rparams { + list := make([]Type, sig.RParams().Len()) + for i, t := range sig.RParams().list() { list[i] = t.typ } smap := makeSubstMap(recvTParams, list) - for i, tname := range sig.rparams { + for i, tname := range sig.RParams().list() { bound := recvTParams[i].typ.(*TypeParam).bound // bound is (possibly) parameterized in the context of the // receiver type declaration. Substitute parameters for the diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index fc548f7c58..29e298103b 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -25,12 +25,12 @@ func TestSizeof(t *testing.T) { {Struct{}, 24, 48}, {Pointer{}, 8, 16}, {Tuple{}, 12, 24}, - {Signature{}, 44, 88}, + {Signature{}, 28, 56}, {Union{}, 24, 48}, {Interface{}, 40, 80}, {Map{}, 16, 32}, {Chan{}, 12, 24}, - {Named{}, 84, 160}, + {Named{}, 76, 144}, {TypeParam{}, 28, 48}, {top{}, 0, 0}, diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 42be508cd9..197d79b6a8 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -203,7 +203,7 @@ func (subst *subster) typ(typ Type) Type { if len(t.targs) > 0 { // already instantiated dump(">>> %s already instantiated", t) - assert(len(t.targs) == len(t.TParams())) + assert(len(t.targs) == t.TParams().Len()) // For each (existing) type argument targ, determine if it needs // to be substituted; i.e., if it is or contains a type parameter // that has a type argument for it. @@ -213,7 +213,7 @@ func (subst *subster) typ(typ Type) Type { if newTarg != targ { dump(">>> substituted %d targ %s => %s", i, targ, newTarg) if newTargs == nil { - newTargs = make([]Type, len(t.TParams())) + newTargs = make([]Type, t.TParams().Len()) copy(newTargs, t.targs) } newTargs[i] = newTarg diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index bb5b28cdf8..8c18b52a9a 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -28,15 +28,19 @@ type TypeParam struct { bound Type // *Named or *Interface; underlying type is always *Interface } -// NewTypeParam returns a new TypeParam. bound can be nil (and set later). -func (check *Checker) NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam { +// NewTypeParam returns a new TypeParam. Type parameters may be set on a Named +// or Signature type by calling SetTParams. Setting a type parameter on more +// than one type will result in a panic. +// +// The bound argument can be nil, and set later via SetBound. +func (check *Checker) NewTypeParam(obj *TypeName, bound Type) *TypeParam { // Always increment lastID, even if it is not used. id := nextID() if check != nil { check.nextID++ id = check.nextID } - typ := &TypeParam{check: check, id: id, obj: obj, index: index, bound: bound} + typ := &TypeParam{check: check, id: id, obj: obj, index: -1, bound: bound} if obj.typ == nil { obj.typ = typ } @@ -56,6 +60,8 @@ func (t *TypeParam) _SetId(id uint64) { t.id = id } +// TODO(rfindley): document the Bound and SetBound methods. + func (t *TypeParam) Bound() *Interface { // we may not have an interface (error reported elsewhere) iface, _ := under(t.bound).(*Interface) @@ -72,7 +78,7 @@ func (t *TypeParam) Bound() *Interface { return iface } -func (t *TypeParam) _SetBound(bound Type) { +func (t *TypeParam) SetBound(bound Type) { if bound == nil { panic("internal error: bound must not be nil") } @@ -82,6 +88,42 @@ func (t *TypeParam) _SetBound(bound Type) { func (t *TypeParam) Underlying() Type { return t } func (t *TypeParam) String() string { return TypeString(t, nil) } +// TypeParams holds a list of type parameters bound to a type. +type TypeParams struct{ tparams []*TypeName } + +// Len returns the number of type parameters in the list. +// It is safe to call on a nil receiver. +func (tps *TypeParams) Len() int { + return len(tps.list()) +} + +// At returns the i'th type parameter in the list. +// It is safe to call on a nil receiver. +func (tps *TypeParams) At(i int) *TypeName { + return tps.list()[i] +} + +func (tps *TypeParams) list() []*TypeName { + if tps == nil { + return nil + } + return tps.tparams +} + +func bindTParams(list []*TypeName) *TypeParams { + if len(list) == 0 { + return nil + } + for i, tp := range list { + typ := tp.Type().(*TypeParam) + if typ.index >= 0 { + panic("internal error: type parameter bound more than once") + } + typ.index = i + } + return &TypeParams{tparams: list} +} + // ---------------------------------------------------------------------------- // Implementation diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index ef3808230a..18c436e3ef 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -278,7 +278,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { buf.WriteByte(']') } else if t.TParams() != nil { // parameterized type - writeTParamList(buf, t.TParams(), qf, visited) + writeTParamList(buf, t.TParams().list(), qf, visited) } case *TypeParam: @@ -425,7 +425,7 @@ func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) { func writeSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier, visited []Type) { if sig.tparams != nil { - writeTParamList(buf, sig.tparams, qf, visited) + writeTParamList(buf, sig.TParams().list(), qf, visited) } writeTuple(buf, sig.params, sig.variadic, qf, visited) -- GitLab From 5ba06495c1ab2c0e7f6e25260d1f92b5008c380e Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Wed, 21 Jul 2021 11:26:00 -0400 Subject: [PATCH 0516/2500] [dev.typeparams] go/types: use the TParams API consistently Even internally to the type checker, we should use the TParams and RParams methods instead of accessing fields directly, as TParams may be lazily expanded, and in the future we may want to pack receiver and function type parameters into a single field on Signature. We should also not differentiate a nil *TParamList from an empty *TParamList. Change-Id: I85c616e6c708a89b6a5eb1e69fe0b014276eda90 Reviewed-on: https://go-review.googlesource.com/c/go/+/336251 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer --- src/go/types/call.go | 4 ++-- src/go/types/decl.go | 2 +- src/go/types/subst.go | 2 +- src/go/types/typestring.go | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/go/types/call.go b/src/go/types/call.go index 96d0429af9..16b8e4eb7c 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -61,7 +61,7 @@ func (check *Checker) funcInst(x *operand, ix *typeparams.IndexExpr) { // instantiate function signature res := check.Instantiate(x.Pos(), sig, targs, poslist, true).(*Signature) - assert(res.tparams == nil) // signature is not generic anymore + assert(res.TParams().Len() == 0) // signature is not generic anymore if inferred { check.recordInferred(ix.Orig, targs, res) } @@ -334,7 +334,7 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type // compute result signature rsig = check.Instantiate(call.Pos(), sig, targs, nil, true).(*Signature) - assert(rsig.tparams == nil) // signature is not generic anymore + assert(rsig.TParams().Len() == 0) // signature is not generic anymore check.recordInferred(call, targs, rsig) // Optimization: Only if the parameter list was adjusted do we diff --git a/src/go/types/decl.go b/src/go/types/decl.go index be7753d9d1..ad88c30282 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -625,7 +625,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { named.underlying = under(named) // If the RHS is a type parameter, it must be from this type declaration. - if tpar, _ := named.underlying.(*TypeParam); tpar != nil && tparamIndex(named.tparams.list(), tpar) < 0 { + if tpar, _ := named.underlying.(*TypeParam); tpar != nil && tparamIndex(named.TParams().list(), tpar) < 0 { check.errorf(tdecl.Type, _Todo, "cannot use function type parameter %s as RHS in type declaration", tpar) named.underlying = Typ[Invalid] } diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 197d79b6a8..60fc7ae819 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -193,7 +193,7 @@ func (subst *subster) typ(typ Type) Type { } } - if t.TParams() == nil { + if t.TParams().Len() == 0 { dump(">>> %s is not parameterized", t) return t // type is not parameterized } diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 18c436e3ef..6a9e7f2ac8 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -276,7 +276,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { buf.WriteByte('[') writeTypeList(buf, t.targs, qf, visited) buf.WriteByte(']') - } else if t.TParams() != nil { + } else if t.TParams().Len() != 0 { // parameterized type writeTParamList(buf, t.TParams().list(), qf, visited) } @@ -424,7 +424,7 @@ func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) { } func writeSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier, visited []Type) { - if sig.tparams != nil { + if sig.TParams().Len() != 0 { writeTParamList(buf, sig.TParams().list(), qf, visited) } -- GitLab From fca3e5c4452e8dac6c7ae028dcccc323e1d57ed5 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 22 Jul 2021 23:54:19 +0700 Subject: [PATCH 0517/2500] [dev.typeparams] cmd/compile: fix missing condition in usemethod CL 330670 simplified usemethod, but dropped the previous condition to ensure the function have 1 or 2 result. This CL restore that condition, and also add a test for it. Change-Id: I434e3736785b43ceea0b386d8d9d01ad78a4ccd2 Reviewed-on: https://go-review.googlesource.com/c/go/+/336609 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/walk/expr.go | 9 ++++++++- test/reflectmethod8.go | 26 ++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 test/reflectmethod8.go diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go index 19fb188526..eed6ef86c2 100644 --- a/src/cmd/compile/internal/walk/expr.go +++ b/src/cmd/compile/internal/walk/expr.go @@ -957,7 +957,14 @@ func usemethod(n *ir.CallExpr) { if t.NumParams() != 1 || t.Params().Field(0).Type.Kind() != pKind { return } - if t.NumResults() == 2 && t.Results().Field(1).Type.Kind() != types.TBOOL { + switch t.NumResults() { + case 1: + // ok + case 2: + if t.Results().Field(1).Type.Kind() != types.TBOOL { + return + } + default: return } diff --git a/test/reflectmethod8.go b/test/reflectmethod8.go new file mode 100644 index 0000000000..482163bae6 --- /dev/null +++ b/test/reflectmethod8.go @@ -0,0 +1,26 @@ +// compile + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Make sure that the compiler can analyze non-reflect +// Type.{Method,MethodByName} calls. + +package p + +type I interface { + MethodByName(string) + Method(int) +} + +type M struct{} + +func (M) MethodByName(string) {} +func (M) Method(int) {} + +func f() { + var m M + I.MethodByName(m, "") + I.Method(m, 42) +} -- GitLab From 80127a7dfe6951fb16d2b67dbe9badb5952e3a2f Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sun, 18 Jul 2021 15:51:31 -0700 Subject: [PATCH 0518/2500] [dev.typeparams] cmd/compile/internal/types2: adjust unsafe.Alignof/Offsetof/Sizeof Changed the implementation such that the result is a variable rather than a constant if the argument type (or the struct in case of unsafe.Offsetof) has a size that depends on type parameters. Minor unrelated adjustments. For #40301. Change-Id: I1e988f1479b95648ad95a455c764ead829d75749 Reviewed-on: https://go-review.googlesource.com/c/go/+/335413 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/builtins.go | 73 ++++++++---- .../compile/internal/types2/builtins_test.go | 13 ++- src/cmd/compile/internal/types2/infer.go | 4 +- src/cmd/compile/internal/types2/sizes.go | 10 +- .../types2/testdata/check/builtins.go2 | 107 ++++++++++++++++++ .../types2/testdata/fixedbugs/issue40301.go2 | 4 +- 6 files changed, 182 insertions(+), 29 deletions(-) diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 14be24e251..2af2679d5e 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -624,19 +624,22 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( case _Alignof: // unsafe.Alignof(x T) uintptr - if asTypeParam(x.typ) != nil { - check.errorf(call, invalidOp+"unsafe.Alignof undefined for %s", x) - return - } check.assignment(x, nil, "argument to unsafe.Alignof") if x.mode == invalid { return } - x.mode = constant_ - x.val = constant.MakeInt64(check.conf.alignof(x.typ)) + if hasVarSize(x.typ) { + x.mode = value + if check.Types != nil { + check.recordBuiltinType(call.Fun, makeSig(Typ[Uintptr], x.typ)) + } + } else { + x.mode = constant_ + x.val = constant.MakeInt64(check.conf.alignof(x.typ)) + // result is constant - no need to record signature + } x.typ = Typ[Uintptr] - // result is constant - no need to record signature case _Offsetof: // unsafe.Offsetof(x T) uintptr, where x must be a selector @@ -674,30 +677,43 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( return } - // TODO(gri) Should we pass x.typ instead of base (and indirect report if derefStructPtr indirected)? + // TODO(gri) Should we pass x.typ instead of base (and have indirect report if derefStructPtr indirected)? check.recordSelection(selx, FieldVal, base, obj, index, false) - offs := check.conf.offsetof(base, index) - x.mode = constant_ - x.val = constant.MakeInt64(offs) + // The field offset is considered a variable even if the field is declared before + // the part of the struct which is variable-sized. This makes both the rules + // simpler and also permits (or at least doesn't prevent) a compiler from re- + // arranging struct fields if it wanted to. + if hasVarSize(base) { + x.mode = value + if check.Types != nil { + check.recordBuiltinType(call.Fun, makeSig(Typ[Uintptr], obj.Type())) + } + } else { + x.mode = constant_ + x.val = constant.MakeInt64(check.conf.offsetof(base, index)) + // result is constant - no need to record signature + } x.typ = Typ[Uintptr] - // result is constant - no need to record signature case _Sizeof: // unsafe.Sizeof(x T) uintptr - if asTypeParam(x.typ) != nil { - check.errorf(call, invalidOp+"unsafe.Sizeof undefined for %s", x) - return - } check.assignment(x, nil, "argument to unsafe.Sizeof") if x.mode == invalid { return } - x.mode = constant_ - x.val = constant.MakeInt64(check.conf.sizeof(x.typ)) + if hasVarSize(x.typ) { + x.mode = value + if check.Types != nil { + check.recordBuiltinType(call.Fun, makeSig(Typ[Uintptr], x.typ)) + } + } else { + x.mode = constant_ + x.val = constant.MakeInt64(check.conf.sizeof(x.typ)) + // result is constant - no need to record signature + } x.typ = Typ[Uintptr] - // result is constant - no need to record signature case _Slice: // unsafe.Slice(ptr *T, len IntegerType) []T @@ -769,6 +785,25 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( return true } +// hasVarSize reports if the size of type t is variable due to type parameters. +func hasVarSize(t Type) bool { + switch t := under(t).(type) { + case *Array: + return hasVarSize(t.elem) + case *Struct: + for _, f := range t.fields { + if hasVarSize(f.typ) { + return true + } + } + case *TypeParam: + return true + case *Named, *Union, *instance, *top: + unreachable() + } + return false +} + // applyTypeFunc applies f to x. If x is a type parameter, // the result is a type parameter constrained by an new // interface bound. The type bounds for that interface diff --git a/src/cmd/compile/internal/types2/builtins_test.go b/src/cmd/compile/internal/types2/builtins_test.go index 82c786b86e..52dbba1cb9 100644 --- a/src/cmd/compile/internal/types2/builtins_test.go +++ b/src/cmd/compile/internal/types2/builtins_test.go @@ -7,6 +7,7 @@ package types2_test import ( "cmd/compile/internal/syntax" "fmt" + "strings" "testing" . "cmd/compile/internal/types2" @@ -111,12 +112,15 @@ var builtinCalls = []struct { {"Alignof", `_ = unsafe.Alignof(0)`, `invalid type`}, // constant {"Alignof", `var x struct{}; _ = unsafe.Alignof(x)`, `invalid type`}, // constant + {"Alignof", `var x P; _ = unsafe.Alignof(x)`, `func(p.P₁) uintptr`}, {"Offsetof", `var x struct{f bool}; _ = unsafe.Offsetof(x.f)`, `invalid type`}, // constant {"Offsetof", `var x struct{_ int; f bool}; _ = unsafe.Offsetof((&x).f)`, `invalid type`}, // constant + {"Offsetof", `var x struct{_ int; f P}; _ = unsafe.Offsetof((&x).f)`, `func(p.P₁) uintptr`}, {"Sizeof", `_ = unsafe.Sizeof(0)`, `invalid type`}, // constant {"Sizeof", `var x struct{}; _ = unsafe.Sizeof(x)`, `invalid type`}, // constant + {"Sizeof", `var x P; _ = unsafe.Sizeof(x)`, `func(p.P₁) uintptr`}, {"Slice", `var p *int; _ = unsafe.Slice(p, 1)`, `func(*int, int) []int`}, {"Slice", `var p *byte; var n uintptr; _ = unsafe.Slice(p, n)`, `func(*byte, uintptr) []byte`}, @@ -149,9 +153,14 @@ func TestBuiltinSignatures(t *testing.T) { } } +func parseGenericSrc(path, src string) (*syntax.File, error) { + errh := func(error) {} // dummy error handler so that parsing continues in presence of errors + return syntax.Parse(syntax.NewFileBase(path), strings.NewReader(src), errh, nil, syntax.AllowGenerics) +} + func testBuiltinSignature(t *testing.T, name, src0, want string) { - src := fmt.Sprintf(`package p; import "unsafe"; type _ unsafe.Pointer /* use unsafe */; func _() { %s }`, src0) - f, err := parseSrc("", src) + src := fmt.Sprintf(`package p; import "unsafe"; type _ unsafe.Pointer /* use unsafe */; func _[P any]() { %s }`, src0) + f, err := parseGenericSrc("", src) if err != nil { t.Errorf("%s: %s", src0, err) return diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index e5d94e44d9..b44ff7377a 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -401,8 +401,8 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty // u.x.types() now contains the incoming type arguments plus any additional type // arguments for which there were structural constraints. The newly inferred non- - // nil entries may still contain references to other type parameters. For instance, - // for [A any, B interface{type []C}, C interface{type *A}], if A == int + // nil entries may still contain references to other type parameters. + // For instance, for [A any, B interface{ []C }, C interface{ *A }], if A == int // was given, unification produced the type list [int, []C, *A]. We eliminate the // remaining type parameters by substituting the type parameters in this type list // until nothing changes anymore. diff --git a/src/cmd/compile/internal/types2/sizes.go b/src/cmd/compile/internal/types2/sizes.go index cb789598e5..6a3d19d8ea 100644 --- a/src/cmd/compile/internal/types2/sizes.go +++ b/src/cmd/compile/internal/types2/sizes.go @@ -48,7 +48,7 @@ type StdSizes struct { func (s *StdSizes) Alignof(T Type) int64 { // For arrays and structs, alignment is defined in terms // of alignment of the elements and fields, respectively. - switch t := optype(T).(type) { + switch t := under(T).(type) { case *Array: // spec: "For a variable x of array type: unsafe.Alignof(x) // is the same as unsafe.Alignof(x[0]), but at least 1." @@ -73,6 +73,8 @@ func (s *StdSizes) Alignof(T Type) int64 { if t.Info()&IsString != 0 { return s.WordSize } + case *TypeParam, *Union: + unreachable() } a := s.Sizeof(T) // may be 0 // spec: "For a variable x of any type: unsafe.Alignof(x) is at least 1." @@ -118,7 +120,7 @@ var basicSizes = [...]byte{ } func (s *StdSizes) Sizeof(T Type) int64 { - switch t := optype(T).(type) { + switch t := under(T).(type) { case *Basic: assert(isTyped(T)) k := t.kind @@ -148,10 +150,10 @@ func (s *StdSizes) Sizeof(T Type) int64 { } offsets := s.Offsetsof(t.fields) return offsets[n-1] + s.Sizeof(t.fields[n-1].typ) - case *Union: - panic("Sizeof unimplemented for union") case *Interface: return s.WordSize * 2 + case *TypeParam, *Union: + unreachable() } return s.WordSize // catch-all } diff --git a/src/cmd/compile/internal/types2/testdata/check/builtins.go2 b/src/cmd/compile/internal/types2/testdata/check/builtins.go2 index 8fe6d7b332..3881090603 100644 --- a/src/cmd/compile/internal/types2/testdata/check/builtins.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/builtins.go2 @@ -6,6 +6,8 @@ package builtins +import "unsafe" + // close type C0 interface{ int } @@ -127,3 +129,108 @@ func _[T Bss]() { _ = make(T, 10) _ = make(T, 10, 20) } + +// unsafe.Alignof + +func _[T comparable]() { + var ( + b int64 + a [10]T + s struct{ f T } + p *T + l []T + f func(T) + i interface{ m() T } + c chan T + m map[T]T + t T + ) + + const bb = unsafe.Alignof(b) + assert(bb == 8) + const _ = unsafe /* ERROR not constant */ .Alignof(a) + const _ = unsafe /* ERROR not constant */ .Alignof(s) + const pp = unsafe.Alignof(p) + assert(pp == 8) + const ll = unsafe.Alignof(l) + assert(ll == 8) + const ff = unsafe.Alignof(f) + assert(ff == 8) + const ii = unsafe.Alignof(i) + assert(ii == 8) + const cc = unsafe.Alignof(c) + assert(cc == 8) + const mm = unsafe.Alignof(m) + assert(mm == 8) + const _ = unsafe /* ERROR not constant */ .Alignof(t) +} + +// unsafe.Offsetof + +func _[T comparable]() { + var ( + b struct{ _, f int64 } + a struct{ _, f [10]T } + s struct{ _, f struct{ f T } } + p struct{ _, f *T } + l struct{ _, f []T } + f struct{ _, f func(T) } + i struct{ _, f interface{ m() T } } + c struct{ _, f chan T } + m struct{ _, f map[T]T } + t struct{ _, f T } + ) + + const bb = unsafe.Offsetof(b.f) + assert(bb == 8) + const _ = unsafe /* ERROR not constant */ .Alignof(a) + const _ = unsafe /* ERROR not constant */ .Alignof(s) + const pp = unsafe.Offsetof(p.f) + assert(pp == 8) + const ll = unsafe.Offsetof(l.f) + assert(ll == 24) + const ff = unsafe.Offsetof(f.f) + assert(ff == 8) + const ii = unsafe.Offsetof(i.f) + assert(ii == 16) + const cc = unsafe.Offsetof(c.f) + assert(cc == 8) + const mm = unsafe.Offsetof(m.f) + assert(mm == 8) + const _ = unsafe /* ERROR not constant */ .Alignof(t) +} + +// unsafe.Sizeof + +func _[T comparable]() { + var ( + b int64 + a [10]T + s struct{ f T } + p *T + l []T + f func(T) + i interface{ m() T } + c chan T + m map[T]T + t T + ) + + const bb = unsafe.Sizeof(b) + assert(bb == 8) + const _ = unsafe /* ERROR not constant */ .Alignof(a) + const _ = unsafe /* ERROR not constant */ .Alignof(s) + const pp = unsafe.Sizeof(p) + assert(pp == 8) + const ll = unsafe.Sizeof(l) + assert(ll == 24) + const ff = unsafe.Sizeof(f) + assert(ff == 8) + const ii = unsafe.Sizeof(i) + assert(ii == 16) + const cc = unsafe.Sizeof(c) + assert(cc == 8) + const mm = unsafe.Sizeof(m) + assert(mm == 8) + const _ = unsafe /* ERROR not constant */ .Alignof(t) +} diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue40301.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue40301.go2 index 5d97855f8a..c78f9a1fa0 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue40301.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue40301.go2 @@ -7,6 +7,6 @@ package p import "unsafe" func _[T any](x T) { - _ = unsafe /* ERROR undefined */ .Alignof(x) - _ = unsafe /* ERROR undefined */ .Sizeof(x) + _ = unsafe.Alignof(x) + _ = unsafe.Sizeof(x) } -- GitLab From 73162a54c2885d32d40067d2e4fbe26bbe5c7d65 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Fri, 23 Jul 2021 00:24:50 +0700 Subject: [PATCH 0519/2500] [dev.typeparams] cmd/compile: remove outdate TODO in escape analysis We now understand the root cause of #47227, it will be fixed in #47317. Change-Id: Ifcd44f887a0bd3195818df33e409bd3e818e0b27 Reviewed-on: https://go-review.googlesource.com/c/go/+/336610 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le Reviewed-by: Matthew Dempsky TryBot-Result: Go Bot --- src/cmd/compile/internal/escape/call.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/cmd/compile/internal/escape/call.go b/src/cmd/compile/internal/escape/call.go index 65c76d6870..9e5abed591 100644 --- a/src/cmd/compile/internal/escape/call.go +++ b/src/cmd/compile/internal/escape/call.go @@ -320,8 +320,6 @@ func (e *escape) rewriteArgument(argp *ir.Node, init *ir.Nodes, call ir.Node, fn return case ir.ONAME: if arg.(*ir.Name).Class == ir.PFUNC { - // TODO(cuonglm): figure it why this is necessary, we should not depend on this to make - // ABI analyze works correctly (see #47227 and discussion in CL 334882). return } } -- GitLab From 5cb84f0604797df436d8fde548d4f797b3a6c245 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Wed, 21 Jul 2021 19:17:20 -0700 Subject: [PATCH 0520/2500] [dev.typeparams] cmd/compile: make sure types added to the dictionary are instantiated correctly Make sure the instantiating types are the type parameters of the containing function (or types derived from those). The one exception is the argument of a OFUNCINST, whose type parameters are those of the declaration site of the function or method being instantiated. We skip those types. Change-Id: I4b3ff22eb8a81a76476930cf8ed2a7dd6489d8b8 Reviewed-on: https://go-review.googlesource.com/c/go/+/336352 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 31 ++++++++++++++++++----- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 71edc82dea..59f11bbe23 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -22,6 +22,9 @@ import ( "strconv" ) +// Enable extra consistency checks. +const doubleCheck = true + func assert(p bool) { base.Assert(p) } @@ -1820,7 +1823,6 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo { ir.Visit(n1, visitFunc) } } - addType(&info, n, n.Type()) } @@ -1847,9 +1849,17 @@ func addType(info *gfInfo, n ir.Node, t *types.Type) { if t.IsTypeParam() && t.Underlying() == t { return } - if !parameterizedBy(t, info.tparams) { + if t.Kind() == types.TFUNC && n != nil && + (t.Recv() != nil || + n.Op() == ir.ONAME && n.Name().Class == ir.PFUNC) { + // Don't use the type of a named generic function or method, + // since that is parameterized by other typeparams. + // (They all come from arguments of a FUNCINST node.) return } + if doubleCheck && !parameterizedBy(t, info.tparams) { + base.Fatalf("adding type with invalid parameters %+v", t) + } if t.Kind() == types.TSTRUCT && t.IsFuncArgStruct() { // Multiple return values are not a relevant new type (?). return @@ -1872,13 +1882,25 @@ func parameterizedBy1(t *types.Type, params []*types.Type, visited map[*types.Ty return true } visited[t] = true + + if t.Sym() != nil && len(t.RParams()) > 0 { + // This defined type is instantiated. Check the instantiating types. + for _, r := range t.RParams() { + if !parameterizedBy1(r, params, visited) { + return false + } + } + return true + } switch t.Kind() { case types.TTYPEPARAM: + // Check if t is one of the allowed parameters in scope. for _, p := range params { if p == t { return true } } + // Couldn't find t in the list of allowed parameters. return false case types.TARRAY, types.TPTR, types.TSLICE, types.TCHAN: @@ -1888,10 +1910,7 @@ func parameterizedBy1(t *types.Type, params []*types.Type, visited map[*types.Ty return parameterizedBy1(t.Key(), params, visited) && parameterizedBy1(t.Elem(), params, visited) case types.TFUNC: - if t.NumTParams() > 0 { - return false - } - return parameterizedBy1(t.Recvs(), params, visited) && parameterizedBy1(t.Params(), params, visited) && parameterizedBy1(t.Results(), params, visited) + return parameterizedBy1(t.TParams(), params, visited) && parameterizedBy1(t.Recvs(), params, visited) && parameterizedBy1(t.Params(), params, visited) && parameterizedBy1(t.Results(), params, visited) case types.TSTRUCT: for _, f := range t.Fields().Slice() { -- GitLab From a627fcd3c4fdacdc9bbcccdb926e4804ca6d6815 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Fri, 14 May 2021 11:46:26 -0400 Subject: [PATCH 0521/2500] [dev.cmdgo] cmd/go: replace Target with MainModules, allowing for multiple targets This change replaces the Target variable that represents the main module and the pathPrefix and inGorootSrc which provide other information about the main module with a single MainModules value that represents multiple main modules and holds their path prefixes, module roots, and whether they are in GOROOT/src. In cases where the code checks Target or its previously associated variables, the code now checks or iterates over MainModules. In some cases, the code still assumes a single main module by calling MainModules.MustGetSingleMainModule. Some of those cases are correct: for instance, there is always only one main module for mod=vendor. Other cases are accompanied with TODOs and will have to be fixed in future CLs to properly support multiple main modules. This CL (and other cls on top of it) are planned to be checked into a branch to allow for those evaluating the workspaces proposal to try it hands on. For #45713 Change-Id: I3b699e1d5cad8c76d62dc567b8460de8c73a87ea Reviewed-on: https://go-review.googlesource.com/c/go/+/334932 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/get/get.go | 6 +- src/cmd/go/internal/load/pkg.go | 7 +- src/cmd/go/internal/modcmd/download.go | 14 +- src/cmd/go/internal/modcmd/vendor.go | 2 +- src/cmd/go/internal/modget/get.go | 50 ++-- src/cmd/go/internal/modget/query.go | 6 +- src/cmd/go/internal/modload/build.go | 19 +- src/cmd/go/internal/modload/buildlist.go | 77 +++--- src/cmd/go/internal/modload/edit.go | 20 +- src/cmd/go/internal/modload/import.go | 24 +- src/cmd/go/internal/modload/init.go | 286 ++++++++++++++++------- src/cmd/go/internal/modload/list.go | 6 +- src/cmd/go/internal/modload/load.go | 148 +++++++----- src/cmd/go/internal/modload/modfile.go | 12 +- src/cmd/go/internal/modload/mvs.go | 4 +- src/cmd/go/internal/modload/query.go | 111 +++++---- src/cmd/go/internal/modload/search.go | 15 +- src/cmd/go/internal/modload/vendor.go | 1 + src/cmd/go/internal/mvs/mvs.go | 34 +-- src/cmd/go/internal/mvs/mvs_test.go | 2 +- src/cmd/go/internal/search/search.go | 33 +-- 21 files changed, 563 insertions(+), 314 deletions(-) diff --git a/src/cmd/go/internal/get/get.go b/src/cmd/go/internal/get/get.go index 3c16dc3040..cc676428e2 100644 --- a/src/cmd/go/internal/get/get.go +++ b/src/cmd/go/internal/get/get.go @@ -225,7 +225,8 @@ func downloadPaths(patterns []string) []string { base.ExitIfErrors() var pkgs []string - for _, m := range search.ImportPathsQuiet(patterns) { + noModRoots := []string{} + for _, m := range search.ImportPathsQuiet(patterns, noModRoots) { if len(m.Pkgs) == 0 && strings.Contains(m.Pattern(), "...") { pkgs = append(pkgs, m.Pattern()) } else { @@ -315,7 +316,8 @@ func download(arg string, parent *load.Package, stk *load.ImportStack, mode int) if wildcardOkay && strings.Contains(arg, "...") { match := search.NewMatch(arg) if match.IsLocal() { - match.MatchDirs() + noModRoots := []string{} // We're in gopath mode, so there are no modroots. + match.MatchDirs(noModRoots) args = match.Dirs } else { match.MatchPackages() diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index a83cc9a812..ac89127a4b 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -1450,9 +1450,9 @@ func disallowInternal(ctx context.Context, srcDir string, importer *Package, imp // The importer is a list of command-line files. // Pretend that the import path is the import path of the // directory containing them. - // If the directory is outside the main module, this will resolve to ".", + // If the directory is outside the main modules, this will resolve to ".", // which is not a prefix of any valid module. - importerPath = modload.DirImportPath(ctx, importer.Dir) + importerPath, _ = modload.MainModules.DirImportPath(ctx, importer.Dir) } parentOfInternal := p.ImportPath[:i] if str.HasPathPrefix(importerPath, parentOfInternal) { @@ -2447,7 +2447,8 @@ func PackagesAndErrors(ctx context.Context, opts PackageOpts, patterns []string) } matches, _ = modload.LoadPackages(ctx, modOpts, patterns...) } else { - matches = search.ImportPaths(patterns) + noModRoots := []string{} + matches = search.ImportPaths(patterns, noModRoots) } var ( diff --git a/src/cmd/go/internal/modcmd/download.go b/src/cmd/go/internal/modcmd/download.go index 0e5af85237..3c88a4b900 100644 --- a/src/cmd/go/internal/modcmd/download.go +++ b/src/cmd/go/internal/modcmd/download.go @@ -91,12 +91,18 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { args = []string{"all"} } if modload.HasModRoot() { - modload.LoadModFile(ctx) // to fill Target - targetAtUpgrade := modload.Target.Path + "@upgrade" - targetAtPatch := modload.Target.Path + "@patch" + modload.LoadModFile(ctx) // to fill MainModules + + if len(modload.MainModules.Versions()) != 1 { + panic(modload.TODOWorkspaces("TODO: multiple main modules not supported in Download")) + } + mainModule := modload.MainModules.Versions()[0] + + targetAtUpgrade := mainModule.Path + "@upgrade" + targetAtPatch := mainModule.Path + "@patch" for _, arg := range args { switch arg { - case modload.Target.Path, targetAtUpgrade, targetAtPatch: + case mainModule.Path, targetAtUpgrade, targetAtPatch: os.Stderr.WriteString("go mod download: skipping argument " + arg + " that resolves to the main module\n") } } diff --git a/src/cmd/go/internal/modcmd/vendor.go b/src/cmd/go/internal/modcmd/vendor.go index 713d5f9f3f..3506655a4a 100644 --- a/src/cmd/go/internal/modcmd/vendor.go +++ b/src/cmd/go/internal/modcmd/vendor.go @@ -82,7 +82,7 @@ func runVendor(ctx context.Context, cmd *base.Command, args []string) { modpkgs := make(map[module.Version][]string) for _, pkg := range pkgs { m := modload.PackageModule(pkg) - if m.Path == "" || m == modload.Target { + if m.Path == "" || m.Version == "" && modload.MainModules.Contains(m.Path) { continue } modpkgs[m] = append(modpkgs[m], pkg) diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index 9672e5598e..3c8b5a7090 100644 --- a/src/cmd/go/internal/modget/get.go +++ b/src/cmd/go/internal/modget/get.go @@ -389,9 +389,11 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { haveExternalExe := false for _, pkg := range pkgs { - if pkg.Name == "main" && pkg.Module != nil && pkg.Module.Path != modload.Target.Path { - haveExternalExe = true - break + if pkg.Name == "main" && pkg.Module != nil { + if !modload.MainModules.Contains(pkg.Module.Path) { + haveExternalExe = true + break + } } } if haveExternalExe { @@ -675,7 +677,9 @@ func (r *resolver) queryNone(ctx context.Context, q *query) { if !q.isWildcard() { q.pathOnce(q.pattern, func() pathSet { - if modload.HasModRoot() && q.pattern == modload.Target.Path { + hasModRoot := modload.HasModRoot() + if hasModRoot && modload.MainModules.Contains(q.pattern) { + v := module.Version{Path: q.pattern} // The user has explicitly requested to downgrade their own module to // version "none". This is not an entirely unreasonable request: it // could plausibly mean “downgrade away everything that depends on any @@ -686,7 +690,7 @@ func (r *resolver) queryNone(ctx context.Context, q *query) { // However, neither of those behaviors would be consistent with the // plain meaning of the query. To try to reduce confusion, reject the // query explicitly. - return errSet(&modload.QueryMatchesMainModuleError{Pattern: q.pattern, Query: q.version}) + return errSet(&modload.QueryMatchesMainModuleError{MainModule: v, Pattern: q.pattern, Query: q.version}) } return pathSet{mod: module.Version{Path: q.pattern, Version: "none"}} @@ -698,8 +702,8 @@ func (r *resolver) queryNone(ctx context.Context, q *query) { continue } q.pathOnce(curM.Path, func() pathSet { - if modload.HasModRoot() && curM == modload.Target { - return errSet(&modload.QueryMatchesMainModuleError{Pattern: q.pattern, Query: q.version}) + if modload.HasModRoot() && curM.Version == "" && modload.MainModules.Contains(curM.Path) { + return errSet(&modload.QueryMatchesMainModuleError{MainModule: curM, Pattern: q.pattern, Query: q.version}) } return pathSet{mod: module.Version{Path: curM.Path, Version: "none"}} }) @@ -718,12 +722,12 @@ func (r *resolver) performLocalQueries(ctx context.Context) { // Absolute paths like C:\foo and relative paths like ../foo... are // restricted to matching packages in the main module. - pkgPattern := modload.DirImportPath(ctx, q.pattern) + pkgPattern, mainModule := modload.MainModules.DirImportPath(ctx, q.pattern) if pkgPattern == "." { return errSet(fmt.Errorf("%s%s is not within module rooted at %s", q.pattern, absDetail, modload.ModRoot())) } - match := modload.MatchInModule(ctx, pkgPattern, modload.Target, imports.AnyTags()) + match := modload.MatchInModule(ctx, pkgPattern, mainModule, imports.AnyTags()) if len(match.Errs) > 0 { return pathSet{err: match.Errs[0]} } @@ -739,7 +743,7 @@ func (r *resolver) performLocalQueries(ctx context.Context) { return pathSet{} } - return pathSet{pkgMods: []module.Version{modload.Target}} + return pathSet{pkgMods: []module.Version{mainModule}} }) } } @@ -789,11 +793,12 @@ func (r *resolver) queryWildcard(ctx context.Context, q *query) { return pathSet{} } - if curM.Path == modload.Target.Path && !versionOkForMainModule(q.version) { + if modload.MainModules.Contains(curM.Path) && !versionOkForMainModule(q.version) { if q.matchesPath(curM.Path) { return errSet(&modload.QueryMatchesMainModuleError{ - Pattern: q.pattern, - Query: q.version, + MainModule: curM, + Pattern: q.pattern, + Query: q.version, }) } @@ -1159,8 +1164,8 @@ func (r *resolver) loadPackages(ctx context.Context, patterns []string, findPack } opts.AllowPackage = func(ctx context.Context, path string, m module.Version) error { - if m.Path == "" || m == modload.Target { - // Packages in the standard library and main module are already at their + if m.Path == "" || m.Version == "" && modload.MainModules.Contains(m.Path) { + // Packages in the standard library and main modules are already at their // latest (and only) available versions. return nil } @@ -1370,11 +1375,11 @@ func (r *resolver) disambiguate(cs pathSet) (filtered pathSet, isPackage bool, m continue } - if m.Path == modload.Target.Path { - if m.Version == modload.Target.Version { + if modload.MainModules.Contains(m.Path) { + if m.Version == "" { return pathSet{}, true, m, true } - // The main module can only be set to its own version. + // A main module can only be set to its own version. continue } @@ -1744,10 +1749,11 @@ func (r *resolver) resolve(q *query, m module.Version) { panic("internal error: resolving a module.Version with an empty path") } - if m.Path == modload.Target.Path && m.Version != modload.Target.Version { + if modload.MainModules.Contains(m.Path) && m.Version != "" { reportError(q, &modload.QueryMatchesMainModuleError{ - Pattern: q.pattern, - Query: q.version, + MainModule: module.Version{Path: m.Path}, + Pattern: q.pattern, + Query: q.version, }) return } @@ -1775,7 +1781,7 @@ func (r *resolver) updateBuildList(ctx context.Context, additions []module.Versi resolved := make([]module.Version, 0, len(r.resolvedVersion)) for mPath, rv := range r.resolvedVersion { - if mPath != modload.Target.Path { + if !modload.MainModules.Contains(mPath) { resolved = append(resolved, module.Version{Path: mPath, Version: rv.version}) } } diff --git a/src/cmd/go/internal/modget/query.go b/src/cmd/go/internal/modget/query.go index 1a5a60f7eb..bbb364fa5e 100644 --- a/src/cmd/go/internal/modget/query.go +++ b/src/cmd/go/internal/modget/query.go @@ -192,9 +192,9 @@ func (q *query) validate() error { // TODO(bcmills): "all@none" seems like a totally reasonable way to // request that we remove all module requirements, leaving only the main // module and standard library. Perhaps we should implement that someday. - return &modload.QueryMatchesMainModuleError{ - Pattern: q.pattern, - Query: q.version, + return &modload.QueryUpgradesAllError{ + MainModules: modload.MainModules.Versions(), + Query: q.version, } } } diff --git a/src/cmd/go/internal/modload/build.go b/src/cmd/go/internal/modload/build.go index 76e1ad589f..a5c5ad9b44 100644 --- a/src/cmd/go/internal/modload/build.go +++ b/src/cmd/go/internal/modload/build.go @@ -212,20 +212,21 @@ func addDeprecation(ctx context.Context, m *modinfo.ModulePublic) { // in rs (which may be nil to indicate that m was not loaded from a requirement // graph). func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode ListMode) *modinfo.ModulePublic { - if m == Target { + if m.Version == "" && MainModules.Contains(m.Path) { info := &modinfo.ModulePublic{ Path: m.Path, Version: m.Version, Main: true, } - if v, ok := rawGoVersion.Load(Target); ok { + _ = TODOWorkspaces("handle rawGoVersion here") + if v, ok := rawGoVersion.Load(m); ok { info.GoVersion = v.(string) } else { panic("internal error: GoVersion not set for main module") } - if HasModRoot() { - info.Dir = ModRoot() - info.GoMod = ModFilePath() + if modRoot := MainModules.ModRoot(m); modRoot != "" { + info.Dir = modRoot + info.GoMod = modFilePath(modRoot) } return info } @@ -397,7 +398,8 @@ func mustFindModule(ld *loader, target, path string) module.Version { } if path == "command-line-arguments" { - return Target + _ = TODOWorkspaces("support multiple main modules; search by modroot") + return MainModules.mustGetSingleMainModule() } base.Fatalf("build %v: cannot find module for path %v", target, path) @@ -406,13 +408,14 @@ func mustFindModule(ld *loader, target, path string) module.Version { // findModule searches for the module that contains the package at path. // If the package was loaded, its containing module and true are returned. -// Otherwise, module.Version{} and false are returend. +// Otherwise, module.Version{} and false are returned. func findModule(ld *loader, path string) (module.Version, bool) { if pkg, ok := ld.pkgCache.Get(path).(*loadPkg); ok { return pkg.mod, pkg.mod != module.Version{} } if path == "command-line-arguments" { - return Target, true + _ = TODOWorkspaces("support multiple main modules; search by modroot") + return MainModules.mustGetSingleMainModule(), true } return module.Version{}, false } diff --git a/src/cmd/go/internal/modload/buildlist.go b/src/cmd/go/internal/modload/buildlist.go index 604a57b437..959ee25df4 100644 --- a/src/cmd/go/internal/modload/buildlist.go +++ b/src/cmd/go/internal/modload/buildlist.go @@ -40,7 +40,7 @@ type Requirements struct { depth modDepth // rootModules is the set of module versions explicitly required by the main - // module, sorted and capped to length. It may contain duplicates, and may + // modules, sorted and capped to length. It may contain duplicates, and may // contain multiple versions for a given module path. rootModules []module.Version maxRootVersion map[string]string @@ -99,8 +99,8 @@ var requirements *Requirements // *Requirements before any other method. func newRequirements(depth modDepth, rootModules []module.Version, direct map[string]bool) *Requirements { for i, m := range rootModules { - if m == Target { - panic(fmt.Sprintf("newRequirements called with untrimmed build list: rootModules[%v] is Target", i)) + if m.Version == "" && MainModules.Contains(m.Path) { + panic(fmt.Sprintf("newRequirements called with untrimmed build list: rootModules[%v] is a main module", i)) } if m.Path == "" || m.Version == "" { panic(fmt.Sprintf("bad requirement: rootModules[%v] = %v", i, m)) @@ -135,9 +135,14 @@ func newRequirements(depth modDepth, rootModules []module.Version, direct map[st func (rs *Requirements) initVendor(vendorList []module.Version) { rs.graphOnce.Do(func() { mg := &ModuleGraph{ - g: mvs.NewGraph(cmpVersion, []module.Version{Target}), + g: mvs.NewGraph(cmpVersion, MainModules.Versions()), } + if MainModules.Len() != 1 { + panic("There should be exactly one main moudle in Vendor mode.") + } + mainModule := MainModules.Versions()[0] + if rs.depth == lazy { // The roots of a lazy module should already include every module in the // vendor list, because the vendored modules are the same as those @@ -158,7 +163,7 @@ func (rs *Requirements) initVendor(vendorList []module.Version) { // Now we can treat the rest of the module graph as effectively “pruned // out”, like a more aggressive version of lazy loading: in vendor mode, // the root requirements *are* the complete module graph. - mg.g.Require(Target, rs.rootModules) + mg.g.Require(mainModule, rs.rootModules) } else { // The transitive requirements of the main module are not in general available // from the vendor directory, and we don't actually know how we got from @@ -170,7 +175,7 @@ func (rs *Requirements) initVendor(vendorList []module.Version) { // graph, but still distinguishes between direct and indirect // dependencies. vendorMod := module.Version{Path: "vendor/modules.txt", Version: ""} - mg.g.Require(Target, append(rs.rootModules, vendorMod)) + mg.g.Require(mainModule, append(rs.rootModules, vendorMod)) mg.g.Require(vendorMod, vendorList) } @@ -182,8 +187,8 @@ func (rs *Requirements) initVendor(vendorList []module.Version) { // path, or the zero module.Version and ok=false if the module is not a root // dependency. func (rs *Requirements) rootSelected(path string) (version string, ok bool) { - if path == Target.Path { - return Target.Version, true + if MainModules.Contains(path) { + return "", true } if v, ok := rs.maxRootVersion[path]; ok { return v, true @@ -261,10 +266,15 @@ func readModGraph(ctx context.Context, depth modDepth, roots []module.Version) ( mu sync.Mutex // guards mg.g and hasError during loading hasError bool mg = &ModuleGraph{ - g: mvs.NewGraph(cmpVersion, []module.Version{Target}), + g: mvs.NewGraph(cmpVersion, MainModules.Versions()), } ) - mg.g.Require(Target, roots) + for _, m := range MainModules.Versions() { + // Require all roots from all main modules. + _ = TODOWorkspaces("This isn't the correct behavior. " + + "Fix this when the requirements struct is updated to reflect the struct of the module graph.") + mg.g.Require(m, roots) + } var ( loadQueue = par.NewQueue(runtime.GOMAXPROCS(0)) @@ -391,10 +401,12 @@ func (mg *ModuleGraph) findError() error { } func (mg *ModuleGraph) allRootsSelected() bool { - roots, _ := mg.g.RequiredBy(Target) - for _, m := range roots { - if mg.Selected(m.Path) != m.Version { - return false + for _, mm := range MainModules.Versions() { + roots, _ := mg.g.RequiredBy(mm) + for _, m := range roots { + if mg.Selected(m.Path) != m.Version { + return false + } } } return true @@ -533,10 +545,11 @@ type Conflict struct { // both retain the same versions of all packages in pkgs and satisfy the // lazy loading invariants (if applicable). func tidyRoots(ctx context.Context, rs *Requirements, pkgs []*loadPkg) (*Requirements, error) { + mainModule := MainModules.mustGetSingleMainModule() if rs.depth == eager { - return tidyEagerRoots(ctx, rs.direct, pkgs) + return tidyEagerRoots(ctx, mainModule, rs.direct, pkgs) } - return tidyLazyRoots(ctx, rs.direct, pkgs) + return tidyLazyRoots(ctx, mainModule, rs.direct, pkgs) } func updateRoots(ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version, rootsImported bool) (*Requirements, error) { @@ -561,10 +574,10 @@ func updateRoots(ctx context.Context, direct map[string]bool, rs *Requirements, // To ensure that the loading process eventually converges, the caller should // add any needed roots from the tidy root set (without removing existing untidy // roots) until the set of roots has converged. -func tidyLazyRoots(ctx context.Context, direct map[string]bool, pkgs []*loadPkg) (*Requirements, error) { +func tidyLazyRoots(ctx context.Context, mainModule module.Version, direct map[string]bool, pkgs []*loadPkg) (*Requirements, error) { var ( roots []module.Version - pathIncluded = map[string]bool{Target.Path: true} + pathIncluded = map[string]bool{mainModule.Path: true} ) // We start by adding roots for every package in "all". // @@ -842,7 +855,9 @@ func updateLazyRoots(ctx context.Context, direct map[string]bool, rs *Requiremen roots = make([]module.Version, 0, len(rs.rootModules)) rootsUpgraded = false inRootPaths := make(map[string]bool, len(rs.rootModules)+1) - inRootPaths[Target.Path] = true + for _, mm := range MainModules.Versions() { + inRootPaths[mm.Path] = true + } for _, m := range rs.rootModules { if inRootPaths[m.Path] { // This root specifies a redundant path. We already retained the @@ -939,7 +954,7 @@ func spotCheckRoots(ctx context.Context, rs *Requirements, mods map[module.Versi // tidyEagerRoots returns a minimal set of root requirements that maintains the // selected version of every module that provided a package in pkgs, and // includes the selected version of every such module in direct as a root. -func tidyEagerRoots(ctx context.Context, direct map[string]bool, pkgs []*loadPkg) (*Requirements, error) { +func tidyEagerRoots(ctx context.Context, mainModule module.Version, direct map[string]bool, pkgs []*loadPkg) (*Requirements, error) { var ( keep []module.Version keptPath = map[string]bool{} @@ -962,7 +977,7 @@ func tidyEagerRoots(ctx context.Context, direct map[string]bool, pkgs []*loadPkg } } - min, err := mvs.Req(Target, rootPaths, &mvsReqs{roots: keep}) + min, err := mvs.Req(mainModule, rootPaths, &mvsReqs{roots: keep}) if err != nil { return nil, err } @@ -1051,7 +1066,7 @@ func updateEagerRoots(ctx context.Context, direct map[string]bool, rs *Requireme // This is only for convenience and clarity for end users: in an eager module, // the choice of explicit vs. implicit dependency has no impact on MVS // selection (for itself or any other module). - keep := append(mg.BuildList()[1:], add...) + keep := append(mg.BuildList()[MainModules.Len():], add...) for _, m := range keep { if direct[m.Path] && !inRootPaths[m.Path] { rootPaths = append(rootPaths, m.Path) @@ -1059,16 +1074,22 @@ func updateEagerRoots(ctx context.Context, direct map[string]bool, rs *Requireme } } - min, err := mvs.Req(Target, rootPaths, &mvsReqs{roots: keep}) - if err != nil { - return rs, err + // TODO(matloob): Make roots into a map. + var roots []module.Version + for _, mainModule := range MainModules.Versions() { + min, err := mvs.Req(mainModule, rootPaths, &mvsReqs{roots: keep}) + if err != nil { + return rs, err + } + roots = append(roots, min...) } - if rs.depth == eager && reflect.DeepEqual(min, rs.rootModules) && reflect.DeepEqual(direct, rs.direct) { + if rs.depth == eager && reflect.DeepEqual(roots, rs.rootModules) && reflect.DeepEqual(direct, rs.direct) { // The root set is unchanged and rs was already eager, so keep rs to // preserve its cached ModuleGraph (if any). return rs, nil } - return newRequirements(eager, min, direct), nil + + return newRequirements(eager, roots, direct), nil } // convertDepth returns a version of rs with the given depth. @@ -1098,5 +1119,5 @@ func convertDepth(ctx context.Context, rs *Requirements, depth modDepth) (*Requi if err != nil { return rs, err } - return newRequirements(lazy, mg.BuildList()[1:], rs.direct), nil + return newRequirements(lazy, mg.BuildList()[MainModules.Len():], rs.direct), nil } diff --git a/src/cmd/go/internal/modload/edit.go b/src/cmd/go/internal/modload/edit.go index c350b9d1b5..796721c90c 100644 --- a/src/cmd/go/internal/modload/edit.go +++ b/src/cmd/go/internal/modload/edit.go @@ -75,7 +75,7 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel // We promote the modules in mustSelect to be explicit requirements. var rootPaths []string for _, m := range mustSelect { - if m.Version != "none" && m.Path != Target.Path { + if !MainModules.Contains(m.Path) && m.Version != "none" { rootPaths = append(rootPaths, m.Path) } } @@ -97,7 +97,7 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel } } - roots, err = mvs.Req(Target, rootPaths, &mvsReqs{roots: mods}) + roots, err = mvs.Req(MainModules.mustGetSingleMainModule(), rootPaths, &mvsReqs{roots: mods}) if err != nil { return nil, false, err } @@ -218,8 +218,8 @@ func raiseLimitsForUpgrades(ctx context.Context, maxVersion map[string]string, d eagerUpgrades = tryUpgrade } else { for _, m := range tryUpgrade { - if m.Path == Target.Path { - // Target is already considered to be higher than any possible m, so we + if MainModules.Contains(m.Path) { + // The main module versions are already considered to be higher than any possible m, so we // won't be upgrading to it anyway and there is no point scanning its // dependencies. continue @@ -318,7 +318,7 @@ func selectPotentiallyImportedModules(ctx context.Context, limiter *versionLimit mods = make([]module.Version, 0, len(limiter.selected)) for path, v := range limiter.selected { - if v != "none" && path != Target.Path { + if v != "none" && !MainModules.Contains(path) { mods = append(mods, module.Version{Path: path, Version: v}) } } @@ -334,7 +334,7 @@ func selectPotentiallyImportedModules(ctx context.Context, limiter *versionLimit } mods = make([]module.Version, 0, len(limiter.selected)) for path, _ := range limiter.selected { - if path != Target.Path { + if !MainModules.Contains(path) { if v := mg.Selected(path); v != "none" { mods = append(mods, module.Version{Path: path, Version: v}) } @@ -415,10 +415,14 @@ func (dq dqState) isDisqualified() bool { // itself lazy, its unrestricted dependencies are skipped when scanning // requirements. func newVersionLimiter(depth modDepth, max map[string]string) *versionLimiter { + selected := make(map[string]string) + for _, m := range MainModules.Versions() { + selected[m.Path] = m.Version + } return &versionLimiter{ depth: depth, max: max, - selected: map[string]string{Target.Path: Target.Version}, + selected: selected, dqReason: map[module.Version]dqState{}, requiring: map[module.Version][]module.Version{}, } @@ -492,7 +496,7 @@ func (l *versionLimiter) Select(m module.Version) (conflict module.Version, err // as is feasible, we don't want to retain test dependencies that are only // marginally relevant at best. func (l *versionLimiter) check(m module.Version, depth modDepth) dqState { - if m.Version == "none" || m == Target { + if m.Version == "none" || m == MainModules.mustGetSingleMainModule() { // version "none" has no requirements, and the dependencies of Target are // tautological. return dqState{} diff --git a/src/cmd/go/internal/modload/import.go b/src/cmd/go/internal/modload/import.go index d2bbe5cbe0..7b5305e4bb 100644 --- a/src/cmd/go/internal/modload/import.go +++ b/src/cmd/go/internal/modload/import.go @@ -257,11 +257,13 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M // Is the package in the standard library? pathIsStd := search.IsStandardImportPath(path) if pathIsStd && goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, path) { - if targetInGorootSrc { - if dir, ok, err := dirInModule(path, targetPrefix, ModRoot(), true); err != nil { - return module.Version{}, dir, err - } else if ok { - return Target, dir, nil + for _, mainModule := range MainModules.Versions() { + if MainModules.InGorootSrc(mainModule) { + if dir, ok, err := dirInModule(path, MainModules.PathPrefix(mainModule), MainModules.ModRoot(mainModule), true); err != nil { + return module.Version{}, dir, err + } else if ok { + return mainModule, dir, nil + } } } dir := filepath.Join(cfg.GOROOT, "src", path) @@ -271,8 +273,10 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M // -mod=vendor is special. // Everything must be in the main module or the main module's vendor directory. if cfg.BuildMod == "vendor" { - mainDir, mainOK, mainErr := dirInModule(path, targetPrefix, ModRoot(), true) - vendorDir, vendorOK, _ := dirInModule(path, "", filepath.Join(ModRoot(), "vendor"), false) + mainModule := MainModules.mustGetSingleMainModule() + modRoot := MainModules.ModRoot(mainModule) + mainDir, mainOK, mainErr := dirInModule(path, MainModules.PathPrefix(mainModule), modRoot, true) + vendorDir, vendorOK, _ := dirInModule(path, "", filepath.Join(modRoot, "vendor"), false) if mainOK && vendorOK { return module.Version{}, "", &AmbiguousImportError{importPath: path, Dirs: []string{mainDir, vendorDir}} } @@ -280,7 +284,7 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M // Note that we're not checking that the package exists. // We'll leave that for load. if !vendorOK && mainDir != "" { - return Target, mainDir, nil + return mainModule, mainDir, nil } if mainErr != nil { return module.Version{}, "", mainErr @@ -638,8 +642,8 @@ func dirInModule(path, mpath, mdir string, isLocal bool) (dir string, haveGoFile // The isLocal return value reports whether the replacement, // if any, is local to the filesystem. func fetch(ctx context.Context, mod module.Version, needSum bool) (dir string, isLocal bool, err error) { - if mod == Target { - return ModRoot(), true, nil + if modRoot := MainModules.ModRoot(mod); modRoot != "" { + return modRoot, true, nil } if r := Replacement(mod); r.Path != "" { if r.Version == "" { diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index cbc7289afa..33f9163038 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -45,26 +45,108 @@ var ( allowMissingModuleImports bool ) +func TODOWorkspaces(s string) error { + return fmt.Errorf("need to support this for workspaces: %s", s) +} + // Variables set in Init. var ( initialized bool - modRoot string - gopath string + + // The directory containing go.work file. Set if in a go.work file is found + // and the go command is operating in workspace mode. + workRoot string + + // These are primarily used to initialize the MainModules, and should be + // eventually superceded by them but are still used in cases where the module + // roots are required but MainModules hasn't been initialized yet. Set to + // the modRoots of the main modules. + // modRoots != nil implies len(modRoots) > 0 + modRoots []string + gopath string ) -// Variables set in initTarget (during {Load,Create}ModFile). -var ( - Target module.Version +type MainModuleSet struct { + // versions are the module.Version values of each of the main modules. + // For each of them, the Path fields are ordinary module paths and the Version + // fields are empty strings. + versions []module.Version - // targetPrefix is the path prefix for packages in Target, without a trailing - // slash. For most modules, targetPrefix is just Target.Path, but the + // modRoot maps each module in versions to its absolute filesystem path. + modRoot map[module.Version]string + + // pathPrefix is the path prefix for packages in the module, without a trailing + // slash. For most modules, pathPrefix is just version.Path, but the // standard-library module "std" has an empty prefix. - targetPrefix string + pathPrefix map[module.Version]string - // targetInGorootSrc caches whether modRoot is within GOROOT/src. + // inGorootSrc caches whether modRoot is within GOROOT/src. // The "std" module is special within GOROOT/src, but not otherwise. - targetInGorootSrc bool -) + inGorootSrc map[module.Version]bool +} + +func (mms *MainModuleSet) PathPrefix(m module.Version) string { + return mms.pathPrefix[m] +} + +// Versions returns the module.Version values of each of the main modules. +// For each of them, the Path fields are ordinary module paths and the Version +// fields are empty strings. +// Callers should not modify the returned slice. +func (mms *MainModuleSet) Versions() []module.Version { + if mms == nil { + return nil + } + return mms.versions +} + +func (mms *MainModuleSet) Contains(path string) bool { + if mms == nil { + return false + } + for _, v := range mms.versions { + if v.Path == path { + return true + } + } + return false +} + +func (mms *MainModuleSet) ModRoot(m module.Version) string { + _ = TODOWorkspaces(" Do we need the Init? The original modRoot calls it. Audit callers.") + Init() + if mms == nil { + return "" + } + return mms.modRoot[m] +} + +func (mms *MainModuleSet) InGorootSrc(m module.Version) bool { + if mms == nil { + return false + } + return mms.inGorootSrc[m] +} + +func (mms *MainModuleSet) mustGetSingleMainModule() module.Version { + if mms == nil || len(mms.versions) == 0 { + panic("internal error: mustGetSingleMainModule called in context with no main modules") + } + if len(mms.versions) != 1 { + _ = TODOWorkspaces("Check if we're in workspace mode before returning the below error.") + panic("internal error: mustGetSingleMainModule called in workspace mode") + } + return mms.versions[0] +} + +func (mms *MainModuleSet) Len() int { + if mms == nil { + return 0 + } + return len(mms.versions) +} + +var MainModules *MainModuleSet type Root int @@ -169,18 +251,17 @@ func Init() { if os.Getenv("GCM_INTERACTIVE") == "" { os.Setenv("GCM_INTERACTIVE", "never") } - - if modRoot != "" { + if modRoots != nil { // modRoot set before Init was called ("go mod init" does this). // No need to search for go.mod. } else if RootMode == NoRoot { if cfg.ModFile != "" && !base.InGOFLAGS("-modfile") { base.Fatalf("go: -modfile cannot be used with commands that ignore the current module") } - modRoot = "" + modRoots = nil } else { - modRoot = findModuleRoot(base.Cwd()) - if modRoot == "" { + modRoots = findModuleRoots(base.Cwd()) + if modRoots == nil { if cfg.ModFile != "" { base.Fatalf("go: cannot find main module, but -modfile was set.\n\t-modfile cannot be used to set the module root directory.") } @@ -192,13 +273,13 @@ func Init() { // Stay in GOPATH mode. return } - } else if search.InDir(modRoot, os.TempDir()) == "." { + } else if search.InDir(modRoots[0], os.TempDir()) == "." { // If you create /tmp/go.mod for experimenting, // then any tests that create work directories under /tmp // will find it and get modules when they're not expecting them. // It's a bit of a peculiar thing to disallow but quite mysterious // when it happens. See golang.org/issue/26708. - modRoot = "" + modRoots = nil fmt.Fprintf(os.Stderr, "go: warning: ignoring go.mod in system temp root %v\n", os.TempDir()) if !mustUseModules { return @@ -221,7 +302,7 @@ func Init() { base.Fatalf("$GOPATH/go.mod exists but should not") } - if modRoot == "" { + if modRoots == nil { // We're in module mode, but not inside a module. // // Commands like 'go build', 'go run', 'go list' have no go.mod file to @@ -240,8 +321,8 @@ func Init() { // // See golang.org/issue/32027. } else { + _ = TODOWorkspaces("Instead of modfile path, find modfile OR workfile path depending on mode") modfetch.GoSumFile = strings.TrimSuffix(ModFilePath(), ".mod") + ".sum" - search.SetModRoot(modRoot) } } @@ -255,7 +336,7 @@ func Init() { // be called until the command is installed and flags are parsed. Instead of // calling Init and Enabled, the main package can call this function. func WillBeEnabled() bool { - if modRoot != "" || cfg.ModulesEnabled { + if modRoots != nil || cfg.ModulesEnabled { // Already enabled. return true } @@ -276,11 +357,12 @@ func WillBeEnabled() bool { return false } - if modRoot := findModuleRoot(base.Cwd()); modRoot == "" { + if modRoots := findModuleRoots(base.Cwd()); modRoots == nil { // GO111MODULE is 'auto', and we can't find a module root. // Stay in GOPATH mode. return false - } else if search.InDir(modRoot, os.TempDir()) == "." { + } else if search.InDir(modRoots[0], os.TempDir()) == "." { + _ = TODOWorkspaces("modRoots[0] is not right here") // If you create /tmp/go.mod for experimenting, // then any tests that create work directories under /tmp // will find it and get modules when they're not expecting them. @@ -297,7 +379,7 @@ func WillBeEnabled() bool { // (usually through MustModRoot). func Enabled() bool { Init() - return modRoot != "" || cfg.ModulesEnabled + return modRoots != nil || cfg.ModulesEnabled } // ModRoot returns the root of the main module. @@ -306,7 +388,10 @@ func ModRoot() string { if !HasModRoot() { die() } - return modRoot + if len(modRoots) != 1 { + panic(TODOWorkspaces("need to handle multiple modroots here")) + } + return modRoots[0] } // HasModRoot reports whether a main module is present. @@ -314,7 +399,7 @@ func ModRoot() string { // does not require a main module. func HasModRoot() bool { Init() - return modRoot != "" + return modRoots != nil } // ModFilePath returns the effective path of the go.mod file. Normally, this @@ -322,9 +407,10 @@ func HasModRoot() bool { // change its location. ModFilePath calls base.Fatalf if there is no main // module, even if -modfile is set. func ModFilePath() string { - if !HasModRoot() { - die() - } + return modFilePath(ModRoot()) +} + +func modFilePath(modRoot string) string { if cfg.ModFile != "" { return cfg.ModFile } @@ -402,11 +488,12 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { } Init() - if modRoot == "" { - Target = module.Version{Path: "command-line-arguments"} - targetPrefix = "command-line-arguments" + if len(modRoots) == 0 { + _ = TODOWorkspaces("Instead of creating a fake module with an empty modroot, make MainModules.Len() == 0 mean that we're in module mode but not inside any module.") + mainModule := module.Version{Path: "command-line-arguments"} + MainModules = makeMainModules([]module.Version{mainModule}, []string{""}) goVersion := LatestGoVersion() - rawGoVersion.Store(Target, goVersion) + rawGoVersion.Store(mainModule, goVersion) requirements = newRequirements(modDepthFromGoVersion(goVersion), nil, nil) return requirements, false } @@ -428,9 +515,13 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { base.Fatalf("go: no module declaration in go.mod. To specify the module path:\n\tgo mod edit -module=example.com/mod") } + // For now, this code assumes there's a single main module, because there's + // no way to specify multiple main modules yet. TODO(#45713): update this + // in a later CL. modFile = f - initTarget(f.Module.Mod) - index = indexModFile(data, f, fixed) + mainModule := f.Module.Mod + MainModules = makeMainModules([]module.Version{mainModule}, modRoots) + index = indexModFile(data, f, mainModule, fixed) if err := module.CheckImportPath(f.Module.Mod.Path); err != nil { if pathErr, ok := err.(*module.InvalidPathError); ok { @@ -451,7 +542,7 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { // TODO(#45551): Do something more principled instead of checking // cfg.CmdName directly here. if cfg.BuildMod == "mod" && cfg.CmdName != "mod graph" && cfg.CmdName != "mod why" { - addGoStmt(LatestGoVersion()) + addGoStmt(mainModule, LatestGoVersion()) if go117EnableLazyLoading { // We need to add a 'go' version to the go.mod file, but we must assume // that its existing contents match something between Go 1.11 and 1.16. @@ -464,7 +555,7 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { } } } else { - rawGoVersion.Store(Target, modFileGoVersion()) + rawGoVersion.Store(mainModule, modFileGoVersion()) } } @@ -482,7 +573,8 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { // exactly the same as in the legacy configuration (for example, we can't get // packages at multiple versions from the same module). func CreateModFile(ctx context.Context, modPath string) { - modRoot = base.Cwd() + modRoot := base.Cwd() + modRoots = []string{modRoot} Init() modFilePath := ModFilePath() if _, err := fsys.Stat(modFilePath); err == nil { @@ -510,8 +602,8 @@ func CreateModFile(ctx context.Context, modPath string) { fmt.Fprintf(os.Stderr, "go: creating new go.mod: module %s\n", modPath) modFile = new(modfile.File) modFile.AddModuleStmt(modPath) - initTarget(modFile.Module.Mod) - addGoStmt(LatestGoVersion()) // Add the go directive before converted module requirements. + MainModules = makeMainModules([]module.Version{modFile.Module.Mod}, []string{modRoot}) + addGoStmt(modFile.Module.Mod, LatestGoVersion()) // Add the go directive before converted module requirements. convertedFrom, err := convertLegacyConfig(modPath) if convertedFrom != "" { @@ -609,32 +701,50 @@ func AllowMissingModuleImports() { allowMissingModuleImports = true } -// initTarget sets Target and associated variables according to modFile, -func initTarget(m module.Version) { - Target = m - targetPrefix = m.Path - - if rel := search.InDir(base.Cwd(), cfg.GOROOTsrc); rel != "" { - targetInGorootSrc = true - if m.Path == "std" { - // The "std" module in GOROOT/src is the Go standard library. Unlike other - // modules, the packages in the "std" module have no import-path prefix. - // - // Modules named "std" outside of GOROOT/src do not receive this special - // treatment, so it is possible to run 'go test .' in other GOROOTs to - // test individual packages using a combination of the modified package - // and the ordinary standard library. - // (See https://golang.org/issue/30756.) - targetPrefix = "" +// makeMainModules creates a MainModuleSet and associated variables according to +// the given main modules. +func makeMainModules(ms []module.Version, rootDirs []string) *MainModuleSet { + for _, m := range ms { + if m.Version != "" { + panic("mainModulesCalled with module.Version with non empty Version field: " + fmt.Sprintf("%#v", m)) } } + mainModules := &MainModuleSet{ + versions: ms[:len(ms):len(ms)], + inGorootSrc: map[module.Version]bool{}, + pathPrefix: map[module.Version]string{}, + modRoot: map[module.Version]string{}, + } + for i, m := range ms { + mainModules.pathPrefix[m] = m.Path + mainModules.modRoot[m] = rootDirs[i] + + if rel := search.InDir(rootDirs[i], cfg.GOROOTsrc); rel != "" { + mainModules.inGorootSrc[m] = true + if m.Path == "std" { + // The "std" module in GOROOT/src is the Go standard library. Unlike other + // modules, the packages in the "std" module have no import-path prefix. + // + // Modules named "std" outside of GOROOT/src do not receive this special + // treatment, so it is possible to run 'go test .' in other GOROOTs to + // test individual packages using a combination of the modified package + // and the ordinary standard library. + // (See https://golang.org/issue/30756.) + mainModules.pathPrefix[m] = "" + } + } + } + return mainModules } // requirementsFromModFile returns the set of non-excluded requirements from // the global modFile. func requirementsFromModFile(ctx context.Context) *Requirements { roots := make([]module.Version, 0, len(modFile.Require)) - mPathCount := map[string]int{Target.Path: 1} + mPathCount := make(map[string]int) + for _, m := range MainModules.Versions() { + mPathCount[m.Path] = 1 + } direct := map[string]bool{} for _, r := range modFile.Require { if index != nil && index.exclude[r.Mod] { @@ -687,7 +797,7 @@ func setDefaultBuildMod() { cfg.BuildMod = "mod" return } - if modRoot == "" { + if modRoots == nil { if allowMissingModuleImports { cfg.BuildMod = "mod" } else { @@ -696,23 +806,25 @@ func setDefaultBuildMod() { return } - if fi, err := fsys.Stat(filepath.Join(modRoot, "vendor")); err == nil && fi.IsDir() { - modGo := "unspecified" - if index != nil && index.goVersionV != "" { - if semver.Compare(index.goVersionV, "v1.14") >= 0 { - // The Go version is at least 1.14, and a vendor directory exists. - // Set -mod=vendor by default. - cfg.BuildMod = "vendor" - cfg.BuildModReason = "Go version in go.mod is at least 1.14 and vendor directory exists." - return - } else { - modGo = index.goVersionV[1:] + if len(modRoots) == 1 { + if fi, err := fsys.Stat(filepath.Join(modRoots[0], "vendor")); err == nil && fi.IsDir() { + modGo := "unspecified" + if index != nil && index.goVersionV != "" { + if semver.Compare(index.goVersionV, "v1.14") >= 0 { + // The Go version is at least 1.14, and a vendor directory exists. + // Set -mod=vendor by default. + cfg.BuildMod = "vendor" + cfg.BuildModReason = "Go version in go.mod is at least 1.14 and vendor directory exists." + return + } else { + modGo = index.goVersionV[1:] + } } - } - // Since a vendor directory exists, we should record why we didn't use it. - // This message won't normally be shown, but it may appear with import errors. - cfg.BuildModReason = fmt.Sprintf("Go version in go.mod is %s, so vendor directory was not used.", modGo) + // Since a vendor directory exists, we should record why we didn't use it. + // This message won't normally be shown, but it may appear with import errors. + cfg.BuildModReason = fmt.Sprintf("Go version in go.mod is %s, so vendor directory was not used.", modGo) + } } cfg.BuildMod = "readonly" @@ -733,7 +845,10 @@ func convertLegacyConfig(modPath string) (from string, err error) { return modOnly.Mod, nil } for _, name := range altConfigs { - cfg := filepath.Join(modRoot, name) + if len(modRoots) != 1 { + panic(TODOWorkspaces("what do do here?")) + } + cfg := filepath.Join(modRoots[0], name) data, err := os.ReadFile(cfg) if err == nil { convert := modconv.Converters[name] @@ -751,14 +866,14 @@ func convertLegacyConfig(modPath string) (from string, err error) { // addGoStmt adds a go directive to the go.mod file if it does not already // include one. The 'go' version added, if any, is the latest version supported // by this toolchain. -func addGoStmt(v string) { +func addGoStmt(mod module.Version, v string) { if modFile.Go != nil && modFile.Go.Version != "" { return } if err := modFile.AddGoStmt(v); err != nil { base.Fatalf("go: internal error: %v", err) } - rawGoVersion.Store(Target, v) + rawGoVersion.Store(mod, v) } // LatestGoVersion returns the latest version of the Go language supported by @@ -809,7 +924,7 @@ var altConfigs = []string{ ".git/config", } -func findModuleRoot(dir string) (root string) { +func findModuleRoots(dir string) (roots []string) { if dir == "" { panic("dir not set") } @@ -818,7 +933,7 @@ func findModuleRoot(dir string) (root string) { // Look for enclosing go.mod. for { if fi, err := fsys.Stat(filepath.Join(dir, "go.mod")); err == nil && !fi.IsDir() { - return dir + return []string{dir} } d := filepath.Dir(dir) if d == dir { @@ -826,7 +941,7 @@ func findModuleRoot(dir string) (root string) { } dir = d } - return "" + return nil } func findAltConfig(dir string) (root, name string) { @@ -987,7 +1102,8 @@ func commitRequirements(ctx context.Context, goVersion string, rs *Requirements) return } - if modRoot == "" { + if MainModules.Len() != 1 || MainModules.ModRoot(MainModules.Versions()[0]) == "" { + _ = TODOWorkspaces("also check that workspace mode is off") // We aren't in a module, so we don't have anywhere to write a go.mod file. return } @@ -1032,8 +1148,14 @@ func commitRequirements(ctx context.Context, goVersion string, rs *Requirements) base.Fatalf("go: %v", err) } defer func() { + if MainModules.Len() != 1 { + panic(TODOWorkspaces("There should be exactly one main module when committing reqs")) + } + + mainModule := MainModules.Versions()[0] + // At this point we have determined to make the go.mod file on disk equal to new. - index = indexModFile(new, modFile, false) + index = indexModFile(new, modFile, mainModule, false) // Update go.sum after releasing the side lock and refreshing the index. // 'go mod init' shouldn't write go.sum, since it will be incomplete. diff --git a/src/cmd/go/internal/modload/list.go b/src/cmd/go/internal/modload/list.go index ccdeb9b1d1..1862bef494 100644 --- a/src/cmd/go/internal/modload/list.go +++ b/src/cmd/go/internal/modload/list.go @@ -79,7 +79,11 @@ func ListModules(ctx context.Context, args []string, mode ListMode) ([]*modinfo. func listModules(ctx context.Context, rs *Requirements, args []string, mode ListMode) (_ *Requirements, mods []*modinfo.ModulePublic, mgErr error) { if len(args) == 0 { - return rs, []*modinfo.ModulePublic{moduleInfo(ctx, rs, Target, mode)}, nil + var ms []*modinfo.ModulePublic + for _, m := range MainModules.Versions() { + ms = append(ms, moduleInfo(ctx, rs, m, mode)) + } + return rs, ms, nil } needFullGraph := false diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index a3a8021c04..77d2dc4030 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -274,7 +274,9 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma // If we're outside of a module, ensure that the failure mode // indicates that. - ModRoot() + if !HasModRoot() { + die() + } if ld != nil { m.AddError(err) @@ -306,7 +308,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma // The initial roots are the packages in the main module. // loadFromRoots will expand that to "all". m.Errs = m.Errs[:0] - matchPackages(ctx, m, opts.Tags, omitStd, []module.Version{Target}) + matchPackages(ctx, m, opts.Tags, omitStd, MainModules.Versions()) } else { // Starting with the packages in the main module, // enumerate the full list of "all". @@ -443,7 +445,7 @@ func matchLocalDirs(ctx context.Context, m *search.Match, rs *Requirements) { } } - m.MatchDirs() + m.MatchDirs(modRoots) } // resolveLocalPackage resolves a filesystem path to a package path. @@ -485,49 +487,70 @@ func resolveLocalPackage(ctx context.Context, dir string, rs *Requirements) (str } } - if modRoot != "" && absDir == modRoot { - if absDir == cfg.GOROOTsrc { - return "", errPkgIsGorootSrc + for _, mod := range MainModules.Versions() { + modRoot := MainModules.ModRoot(mod) + if modRoot != "" && absDir == modRoot { + if absDir == cfg.GOROOTsrc { + return "", errPkgIsGorootSrc + } + return MainModules.PathPrefix(mod), nil } - return targetPrefix, nil } // Note: The checks for @ here are just to avoid misinterpreting // the module cache directories (formerly GOPATH/src/mod/foo@v1.5.2/bar). // It's not strictly necessary but helpful to keep the checks. - if modRoot != "" && strings.HasPrefix(absDir, modRoot+string(filepath.Separator)) && !strings.Contains(absDir[len(modRoot):], "@") { - suffix := filepath.ToSlash(absDir[len(modRoot):]) - if strings.HasPrefix(suffix, "/vendor/") { - if cfg.BuildMod != "vendor" { - return "", fmt.Errorf("without -mod=vendor, directory %s has no package path", absDir) + var pkgNotFoundErr error + pkgNotFoundLongestPrefix := "" + for _, mainModule := range MainModules.Versions() { + modRoot := MainModules.ModRoot(mainModule) + if modRoot != "" && strings.HasPrefix(absDir, modRoot+string(filepath.Separator)) && !strings.Contains(absDir[len(modRoot):], "@") { + suffix := filepath.ToSlash(absDir[len(modRoot):]) + if strings.HasPrefix(suffix, "/vendor/") { + if cfg.BuildMod != "vendor" { + return "", fmt.Errorf("without -mod=vendor, directory %s has no package path", absDir) + } + + readVendorList() + pkg := strings.TrimPrefix(suffix, "/vendor/") + if _, ok := vendorPkgModule[pkg]; !ok { + return "", fmt.Errorf("directory %s is not a package listed in vendor/modules.txt", absDir) + } + return pkg, nil } - readVendorList() - pkg := strings.TrimPrefix(suffix, "/vendor/") - if _, ok := vendorPkgModule[pkg]; !ok { - return "", fmt.Errorf("directory %s is not a package listed in vendor/modules.txt", absDir) + mainModulePrefix := MainModules.PathPrefix(mainModule) + if mainModulePrefix == "" { + pkg := strings.TrimPrefix(suffix, "/") + if pkg == "builtin" { + // "builtin" is a pseudo-package with a real source file. + // It's not included in "std", so it shouldn't resolve from "." + // within module "std" either. + return "", errPkgIsBuiltin + } + return pkg, nil } - return pkg, nil - } - if targetPrefix == "" { - pkg := strings.TrimPrefix(suffix, "/") - if pkg == "builtin" { - // "builtin" is a pseudo-package with a real source file. - // It's not included in "std", so it shouldn't resolve from "." - // within module "std" either. - return "", errPkgIsBuiltin + pkg := mainModulePrefix + suffix + if _, ok, err := dirInModule(pkg, mainModulePrefix, modRoot, true); err != nil { + return "", err + } else if !ok { + // This main module could contain the directory but doesn't. Other main + // modules might contain the directory, so wait till we finish the loop + // to see if another main module contains directory. But if not, + // return an error. + if len(mainModulePrefix) > len(pkgNotFoundLongestPrefix) { + pkgNotFoundLongestPrefix = mainModulePrefix + pkgNotFoundErr = &PackageNotInModuleError{Mod: mainModule, Pattern: pkg} + + } + continue } return pkg, nil } - - pkg := targetPrefix + suffix - if _, ok, err := dirInModule(pkg, targetPrefix, modRoot, true); err != nil { - return "", err - } else if !ok { - return "", &PackageNotInModuleError{Mod: Target, Pattern: pkg} - } - return pkg, nil + } + if pkgNotFoundErr != nil { + return "", pkgNotFoundErr } if sub := search.InDir(absDir, cfg.GOROOTsrc); sub != "" && sub != "." && !strings.Contains(sub, "@") { @@ -649,10 +672,10 @@ func ImportFromFiles(ctx context.Context, gofiles []string) { } // DirImportPath returns the effective import path for dir, -// provided it is within the main module, or else returns ".". -func DirImportPath(ctx context.Context, dir string) string { +// provided it is within a main module, or else returns ".". +func (mms *MainModuleSet) DirImportPath(ctx context.Context, dir string) (path string, m module.Version) { if !HasModRoot() { - return "." + return ".", module.Version{} } LoadModFile(ctx) // Sets targetPrefix. @@ -662,17 +685,32 @@ func DirImportPath(ctx context.Context, dir string) string { dir = filepath.Clean(dir) } - if dir == modRoot { - return targetPrefix - } - if strings.HasPrefix(dir, modRoot+string(filepath.Separator)) { - suffix := filepath.ToSlash(dir[len(modRoot):]) - if strings.HasPrefix(suffix, "/vendor/") { - return strings.TrimPrefix(suffix, "/vendor/") + var longestPrefix string + var longestPrefixPath string + var longestPrefixVersion module.Version + for _, v := range mms.Versions() { + modRoot := mms.ModRoot(v) + if dir == modRoot { + return mms.PathPrefix(v), v + } + if strings.HasPrefix(dir, modRoot+string(filepath.Separator)) { + pathPrefix := MainModules.PathPrefix(v) + if pathPrefix > longestPrefix { + longestPrefix = pathPrefix + longestPrefixVersion = v + suffix := filepath.ToSlash(dir[len(modRoot):]) + if strings.HasPrefix(suffix, "/vendor/") { + longestPrefixPath = strings.TrimPrefix(suffix, "/vendor/") + } + longestPrefixPath = mms.PathPrefix(v) + suffix + } } - return targetPrefix + suffix } - return "." + if len(longestPrefix) > 0 { + return longestPrefixPath, longestPrefixVersion + } + + return ".", module.Version{} } // TargetPackages returns the list of packages in the target (top-level) module @@ -685,7 +723,7 @@ func TargetPackages(ctx context.Context, pattern string) *search.Match { ModRoot() // Emits an error if Target cannot contain packages. m := search.NewMatch(pattern) - matchPackages(ctx, m, imports.AnyTags(), omitStd, []module.Version{Target}) + matchPackages(ctx, m, imports.AnyTags(), omitStd, MainModules.Versions()) return m } @@ -931,10 +969,7 @@ func (pkg *loadPkg) fromExternalModule() bool { if pkg.mod.Path == "" { return false // loaded from the standard library, not a module } - if pkg.mod.Path == Target.Path { - return false // loaded from the main module. - } - return true + return !MainModules.Contains(pkg.mod.Path) } var errMissing = errors.New("cannot find package") @@ -1205,7 +1240,7 @@ func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err err } for _, pkg := range ld.pkgs { - if pkg.mod != Target { + if pkg.mod.Version != "" || !MainModules.Contains(pkg.mod.Path) { continue } for _, dep := range pkg.imports { @@ -1462,7 +1497,7 @@ func (ld *loader) applyPkgFlags(ctx context.Context, pkg *loadPkg, flags loadPkg // so it's ok if we call it more than is strictly necessary. wantTest := false switch { - case ld.allPatternIsRoot && pkg.mod == Target: + case ld.allPatternIsRoot && MainModules.Contains(pkg.mod.Path): // We are loading the "all" pattern, which includes packages imported by // tests in the main module. This package is in the main module, so we // need to identify the imports of its test even if LoadTests is not set. @@ -1483,7 +1518,7 @@ func (ld *loader) applyPkgFlags(ctx context.Context, pkg *loadPkg, flags loadPkg if wantTest { var testFlags loadPkgFlags - if pkg.mod == Target || (ld.allClosesOverTests && new.has(pkgInAll)) { + if MainModules.Contains(pkg.mod.Path) || (ld.allClosesOverTests && new.has(pkgInAll)) { // Tests of packages in the main module are in "all", in the sense that // they cause the packages they import to also be in "all". So are tests // of packages in "all" if "all" closes over test dependencies. @@ -1630,7 +1665,7 @@ func (ld *loader) load(ctx context.Context, pkg *loadPkg) { if pkg.dir == "" { return } - if pkg.mod == Target { + if MainModules.Contains(pkg.mod.Path) { // Go ahead and mark pkg as in "all". This provides the invariant that a // package that is *only* imported by other packages in "all" is always // marked as such before loading its imports. @@ -1735,13 +1770,14 @@ func (ld *loader) stdVendor(parentPath, path string) string { } if str.HasPathPrefix(parentPath, "cmd") { - if !ld.VendorModulesInGOROOTSrc || Target.Path != "cmd" { + if !ld.VendorModulesInGOROOTSrc || !MainModules.Contains("cmd") { vendorPath := pathpkg.Join("cmd", "vendor", path) + if _, err := os.Stat(filepath.Join(cfg.GOROOTsrc, filepath.FromSlash(vendorPath))); err == nil { return vendorPath } } - } else if !ld.VendorModulesInGOROOTSrc || Target.Path != "std" || str.HasPathPrefix(parentPath, "vendor") { + } else if !ld.VendorModulesInGOROOTSrc || !MainModules.Contains("std") || str.HasPathPrefix(parentPath, "vendor") { // If we are outside of the 'std' module, resolve imports from within 'std' // to the vendor directory. // diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index 1145ac4ba5..7b9f6e863a 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -331,7 +331,7 @@ func resolveReplacement(m module.Version) module.Version { // indexModFile rebuilds the index of modFile. // If modFile has been changed since it was first read, // modFile.Cleanup must be called before indexModFile. -func indexModFile(data []byte, modFile *modfile.File, needsFix bool) *modFileIndex { +func indexModFile(data []byte, modFile *modfile.File, mod module.Version, needsFix bool) *modFileIndex { i := new(modFileIndex) i.data = data i.dataNeedsFix = needsFix @@ -343,12 +343,12 @@ func indexModFile(data []byte, modFile *modfile.File, needsFix bool) *modFileInd i.goVersionV = "" if modFile.Go == nil { - rawGoVersion.Store(Target, "") + rawGoVersion.Store(mod, "") } else { // We're going to use the semver package to compare Go versions, so go ahead // and add the "v" prefix it expects once instead of every time. i.goVersionV = "v" + modFile.Go.Version - rawGoVersion.Store(Target, modFile.Go.Version) + rawGoVersion.Store(mod, modFile.Go.Version) } i.require = make(map[module.Version]requireMeta, len(modFile.Require)) @@ -488,8 +488,8 @@ type retraction struct { // // The caller must not modify the returned summary. func goModSummary(m module.Version) (*modFileSummary, error) { - if m == Target { - panic("internal error: goModSummary called on the Target module") + if m.Version == "" && MainModules.Contains(m.Path) { + panic("internal error: goModSummary called on a main module") } if cfg.BuildMod == "vendor" { @@ -583,7 +583,7 @@ func goModSummary(m module.Version) (*modFileSummary, error) { // // rawGoModSummary cannot be used on the Target module. func rawGoModSummary(m module.Version) (*modFileSummary, error) { - if m == Target { + if m.Path == "" && MainModules.Contains(m.Path) { panic("internal error: rawGoModSummary called on the Target module") } diff --git a/src/cmd/go/internal/modload/mvs.go b/src/cmd/go/internal/modload/mvs.go index 87619b4ace..40224d534b 100644 --- a/src/cmd/go/internal/modload/mvs.go +++ b/src/cmd/go/internal/modload/mvs.go @@ -42,7 +42,7 @@ type mvsReqs struct { } func (r *mvsReqs) Required(mod module.Version) ([]module.Version, error) { - if mod == Target { + if MainModules.Contains(mod.Path) { // Use the build list as it existed when r was constructed, not the current // global build list. return r.roots, nil @@ -113,7 +113,7 @@ func versions(ctx context.Context, path string, allowed AllowedFunc) ([]string, func previousVersion(m module.Version) (module.Version, error) { // TODO(golang.org/issue/38714): thread tracing context through MVS. - if m == Target { + if MainModules.Contains(m.Path) { return module.Version{Path: m.Path, Version: "none"}, nil } diff --git a/src/cmd/go/internal/modload/query.go b/src/cmd/go/internal/modload/query.go index 6f6c6e8c98..83e80d009b 100644 --- a/src/cmd/go/internal/modload/query.go +++ b/src/cmd/go/internal/modload/query.go @@ -110,11 +110,12 @@ func queryProxy(ctx context.Context, proxy, path, query, current string, allowed allowed = func(context.Context, module.Version) error { return nil } } - if path == Target.Path && (query == "upgrade" || query == "patch") { - if err := allowed(ctx, Target); err != nil { + if MainModules.Contains(path) && (query == "upgrade" || query == "patch") { + m := module.Version{Path: path} + if err := allowed(ctx, m); err != nil { return nil, fmt.Errorf("internal error: main module version is not allowed: %w", err) } - return &modfetch.RevInfo{Version: Target.Version}, nil + return &modfetch.RevInfo{Version: m.Version}, nil } if path == "std" || path == "cmd" { @@ -551,7 +552,7 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin return m.Errs[0] } - var match func(mod module.Version, root string, isLocal bool) *search.Match + var match func(mod module.Version, roots []string, isLocal bool) *search.Match matchPattern := search.MatchPattern(pattern) if i := strings.Index(pattern, "..."); i >= 0 { @@ -559,30 +560,32 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin if base == "." { return nil, nil, &WildcardInFirstElementError{Pattern: pattern, Query: query} } - match = func(mod module.Version, root string, isLocal bool) *search.Match { + match = func(mod module.Version, roots []string, isLocal bool) *search.Match { m := search.NewMatch(pattern) matchPackages(ctx, m, imports.AnyTags(), omitStd, []module.Version{mod}) return m } } else { - match = func(mod module.Version, root string, isLocal bool) *search.Match { + match = func(mod module.Version, roots []string, isLocal bool) *search.Match { m := search.NewMatch(pattern) prefix := mod.Path - if mod == Target { - prefix = targetPrefix + if MainModules.Contains(mod.Path) { + prefix = MainModules.PathPrefix(module.Version{Path: mod.Path}) } - if _, ok, err := dirInModule(pattern, prefix, root, isLocal); err != nil { - m.AddError(err) - } else if ok { - m.Pkgs = []string{pattern} + for _, root := range roots { + if _, ok, err := dirInModule(pattern, prefix, root, isLocal); err != nil { + m.AddError(err) + } else if ok { + m.Pkgs = []string{pattern} + } } return m } } - var queryMatchesMainModule bool - if HasModRoot() { - m := match(Target, modRoot, true) + var mainModuleMatches []module.Version + for _, mainModule := range MainModules.Versions() { + m := match(mainModule, modRoots, true) if len(m.Pkgs) > 0 { if query != "upgrade" && query != "patch" { return nil, nil, &QueryMatchesPackagesInMainModuleError{ @@ -591,12 +594,12 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin Packages: m.Pkgs, } } - if err := allowed(ctx, Target); err != nil { - return nil, nil, fmt.Errorf("internal error: package %s is in the main module (%s), but version is not allowed: %w", pattern, Target.Path, err) + if err := allowed(ctx, mainModule); err != nil { + return nil, nil, fmt.Errorf("internal error: package %s is in the main module (%s), but version is not allowed: %w", pattern, mainModule.Path, err) } return []QueryResult{{ - Mod: Target, - Rev: &modfetch.RevInfo{Version: Target.Version}, + Mod: mainModule, + Rev: &modfetch.RevInfo{Version: mainModule.Version}, Packages: m.Pkgs, }}, nil, nil } @@ -604,15 +607,17 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin return nil, nil, err } - if matchPattern(Target.Path) { - queryMatchesMainModule = true + var matchesMainModule bool + if matchPattern(mainModule.Path) { + mainModuleMatches = append(mainModuleMatches, mainModule) + matchesMainModule = true } - if (query == "upgrade" || query == "patch") && queryMatchesMainModule { - if err := allowed(ctx, Target); err == nil { + if (query == "upgrade" || query == "patch") && matchesMainModule { + if err := allowed(ctx, mainModule); err == nil { modOnly = &QueryResult{ - Mod: Target, - Rev: &modfetch.RevInfo{Version: Target.Version}, + Mod: mainModule, + Rev: &modfetch.RevInfo{Version: mainModule.Version}, } } } @@ -625,14 +630,17 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin if len(candidateModules) == 0 { if modOnly != nil { return nil, modOnly, nil - } else if queryMatchesMainModule { + } else if len(mainModuleMatches) != 0 { + _ = TODOWorkspaces("add multiple main modules to the error?") return nil, nil, &QueryMatchesMainModuleError{ - Pattern: pattern, - Query: query, + MainModule: mainModuleMatches[0], + Pattern: pattern, + Query: query, } } else { + _ = TODOWorkspaces("This should maybe be PackageNotInModule*s* error with the main modules that are prefixes of base") return nil, nil, &PackageNotInModuleError{ - Mod: Target, + Mod: MainModules.Versions()[0], Query: query, Pattern: pattern, } @@ -656,7 +664,7 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin if err != nil { return r, err } - m := match(r.Mod, root, isLocal) + m := match(r.Mod, []string{root}, isLocal) r.Packages = m.Pkgs if len(r.Packages) == 0 && !matchPattern(path) { if err := firstError(m); err != nil { @@ -684,7 +692,7 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin return err }) - if queryMatchesMainModule && len(results) == 0 && modOnly == nil && errors.Is(err, fs.ErrNotExist) { + if len(mainModuleMatches) > 0 && len(results) == 0 && modOnly == nil && errors.Is(err, fs.ErrNotExist) { return nil, nil, &QueryMatchesMainModuleError{ Pattern: pattern, Query: query, @@ -701,8 +709,13 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin func modulePrefixesExcludingTarget(path string) []string { prefixes := make([]string, 0, strings.Count(path, "/")+1) + mainModulePrefixes := make(map[string]bool) + for _, m := range MainModules.Versions() { + mainModulePrefixes[m.Path] = true + } + for { - if path != targetPrefix { + if !mainModulePrefixes[path] { if _, _, ok := module.SplitPathVersion(path); ok { prefixes = append(prefixes, path) } @@ -759,7 +772,7 @@ func queryPrefixModules(ctx context.Context, candidateModules []string, queryMod case *PackageNotInModuleError: // Given the option, prefer to attribute “package not in module” // to modules other than the main one. - if noPackage == nil || noPackage.Mod == Target { + if noPackage == nil || MainModules.Contains(noPackage.Mod.Path) { noPackage = rErr } case *NoMatchingVersionError: @@ -885,11 +898,11 @@ type PackageNotInModuleError struct { } func (e *PackageNotInModuleError) Error() string { - if e.Mod == Target { + if MainModules.Contains(e.Mod.Path) { if strings.Contains(e.Pattern, "...") { - return fmt.Sprintf("main module (%s) does not contain packages matching %s", Target.Path, e.Pattern) + return fmt.Sprintf("main module (%s) does not contain packages matching %s", e.Mod.Path, e.Pattern) } - return fmt.Sprintf("main module (%s) does not contain package %s", Target.Path, e.Pattern) + return fmt.Sprintf("main module (%s) does not contain package %s", e.Mod.Path, e.Pattern) } found := "" @@ -1094,16 +1107,34 @@ func (rr *replacementRepo) replacementStat(v string) (*modfetch.RevInfo, error) // a version of the main module that cannot be satisfied. // (The main module's version cannot be changed.) type QueryMatchesMainModuleError struct { - Pattern string - Query string + MainModule module.Version + Pattern string + Query string } func (e *QueryMatchesMainModuleError) Error() string { - if e.Pattern == Target.Path { + if MainModules.Contains(e.Pattern) { return fmt.Sprintf("can't request version %q of the main module (%s)", e.Query, e.Pattern) } - return fmt.Sprintf("can't request version %q of pattern %q that includes the main module (%s)", e.Query, e.Pattern, Target.Path) + return fmt.Sprintf("can't request version %q of pattern %q that includes the main module (%s)", e.Query, e.Pattern, e.MainModule.Path) +} + +// A QueryUpgradesAllError indicates that a query requests +// an upgrade on the all pattern. +// (The main module's version cannot be changed.) +type QueryUpgradesAllError struct { + MainModules []module.Version + Query string +} + +func (e *QueryUpgradesAllError) Error() string { + var plural string = "" + if len(e.MainModules) != 1 { + plural = "s" + } + + return fmt.Sprintf("can't request version %q of pattern \"all\" that includes the main module%s", e.Query, plural) } // A QueryMatchesPackagesInMainModuleError indicates that a query cannot be diff --git a/src/cmd/go/internal/modload/search.go b/src/cmd/go/internal/modload/search.go index 658fc6f55a..799c48e50a 100644 --- a/src/cmd/go/internal/modload/search.go +++ b/src/cmd/go/internal/modload/search.go @@ -131,9 +131,10 @@ func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, f } if cfg.BuildMod == "vendor" { - if HasModRoot() { - walkPkgs(ModRoot(), targetPrefix, pruneGoMod|pruneVendor) - walkPkgs(filepath.Join(ModRoot(), "vendor"), "", pruneVendor) + mod := MainModules.mustGetSingleMainModule() + if modRoot := MainModules.ModRoot(mod); modRoot != "" { + walkPkgs(modRoot, MainModules.PathPrefix(mod), pruneGoMod|pruneVendor) + walkPkgs(filepath.Join(modRoot, "vendor"), "", pruneVendor) } return } @@ -147,12 +148,12 @@ func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, f root, modPrefix string isLocal bool ) - if mod == Target { - if !HasModRoot() { + if MainModules.Contains(mod.Path) { + if MainModules.ModRoot(mod) == "" { continue // If there is no main module, we can't search in it. } - root = ModRoot() - modPrefix = targetPrefix + root = MainModules.ModRoot(mod) + modPrefix = MainModules.PathPrefix(mod) isLocal = true } else { var err error diff --git a/src/cmd/go/internal/modload/vendor.go b/src/cmd/go/internal/modload/vendor.go index 80713b0812..e26da15a8f 100644 --- a/src/cmd/go/internal/modload/vendor.go +++ b/src/cmd/go/internal/modload/vendor.go @@ -219,6 +219,7 @@ func checkVendorConsistency() { } if vendErrors.Len() > 0 { + modRoot := MainModules.ModRoot(MainModules.mustGetSingleMainModule()) base.Fatalf("go: inconsistent vendoring in %s:%s\n\n\tTo ignore the vendor directory, use -mod=readonly or -mod=mod.\n\tTo sync the vendor directory, run:\n\t\tgo mod vendor", modRoot, vendErrors) } } diff --git a/src/cmd/go/internal/mvs/mvs.go b/src/cmd/go/internal/mvs/mvs.go index 6969f90f2e..566fa4b6b3 100644 --- a/src/cmd/go/internal/mvs/mvs.go +++ b/src/cmd/go/internal/mvs/mvs.go @@ -8,6 +8,7 @@ package mvs import ( "fmt" + "reflect" "sort" "sync" @@ -85,11 +86,11 @@ type DowngradeReqs interface { // of the list are sorted by path. // // See https://research.swtch.com/vgo-mvs for details. -func BuildList(target module.Version, reqs Reqs) ([]module.Version, error) { - return buildList(target, reqs, nil) +func BuildList(targets []module.Version, reqs Reqs) ([]module.Version, error) { + return buildList(targets, reqs, nil) } -func buildList(target module.Version, reqs Reqs, upgrade func(module.Version) (module.Version, error)) ([]module.Version, error) { +func buildList(targets []module.Version, reqs Reqs, upgrade func(module.Version) (module.Version, error)) ([]module.Version, error) { cmp := func(v1, v2 string) int { if reqs.Max(v1, v2) != v1 { return -1 @@ -102,7 +103,7 @@ func buildList(target module.Version, reqs Reqs, upgrade func(module.Version) (m var ( mu sync.Mutex - g = NewGraph(cmp, []module.Version{target}) + g = NewGraph(cmp, targets) upgrades = map[module.Version]module.Version{} errs = map[module.Version]error{} // (non-nil errors only) ) @@ -110,7 +111,9 @@ func buildList(target module.Version, reqs Reqs, upgrade func(module.Version) (m // Explore work graph in parallel in case reqs.Required // does high-latency network operations. var work par.Work - work.Add(target) + for _, target := range targets { + work.Add(target) + } work.Do(10, func(item interface{}) { m := item.(module.Version) @@ -168,12 +171,12 @@ func buildList(target module.Version, reqs Reqs, upgrade func(module.Version) (m // The final list is the minimum version of each module found in the graph. list := g.BuildList() - if v := list[0]; v != target { + if vs := list[:len(targets)]; !reflect.DeepEqual(vs, targets) { // target.Version will be "" for modload, the main client of MVS. // "" denotes the main module, which has no version. However, MVS treats // version strings as opaque, so "" is not a special value here. // See golang.org/issue/31491, golang.org/issue/29773. - panic(fmt.Sprintf("mistake: chose version %q instead of target %+v", v, target)) + panic(fmt.Sprintf("mistake: chose versions %+v instead of targets %+v", vs, targets)) } return list, nil } @@ -181,8 +184,8 @@ func buildList(target module.Version, reqs Reqs, upgrade func(module.Version) (m // Req returns the minimal requirement list for the target module, // with the constraint that all module paths listed in base must // appear in the returned list. -func Req(target module.Version, base []string, reqs Reqs) ([]module.Version, error) { - list, err := BuildList(target, reqs) +func Req(mainModule module.Version, base []string, reqs Reqs) ([]module.Version, error) { + list, err := BuildList([]module.Version{mainModule}, reqs) if err != nil { return nil, err } @@ -194,7 +197,8 @@ func Req(target module.Version, base []string, reqs Reqs) ([]module.Version, err // Compute postorder, cache requirements. var postorder []module.Version reqCache := map[module.Version][]module.Version{} - reqCache[target] = nil + reqCache[mainModule] = nil + var walk func(module.Version) error walk = func(m module.Version) error { _, ok := reqCache[m] @@ -273,7 +277,7 @@ func Req(target module.Version, base []string, reqs Reqs) ([]module.Version, err // UpgradeAll returns a build list for the target module // in which every module is upgraded to its latest version. func UpgradeAll(target module.Version, reqs UpgradeReqs) ([]module.Version, error) { - return buildList(target, reqs, func(m module.Version) (module.Version, error) { + return buildList([]module.Version{target}, reqs, func(m module.Version) (module.Version, error) { if m.Path == target.Path { return target, nil } @@ -308,7 +312,7 @@ func Upgrade(target module.Version, reqs UpgradeReqs, upgrade ...module.Version) } } - return buildList(target, &override{target, list, reqs}, func(m module.Version) (module.Version, error) { + return buildList([]module.Version{target}, &override{target, list, reqs}, func(m module.Version) (module.Version, error) { if v, ok := upgradeTo[m.Path]; ok { return module.Version{Path: m.Path, Version: v}, nil } @@ -331,7 +335,7 @@ func Downgrade(target module.Version, reqs DowngradeReqs, downgrade ...module.Ve // // In order to generate those new requirements, we need to identify versions // for every module in the build list — not just reqs.Required(target). - list, err := BuildList(target, reqs) + list, err := BuildList([]module.Version{target}, reqs) if err != nil { return nil, err } @@ -446,7 +450,7 @@ List: // list with the actual versions of the downgraded modules as selected by MVS, // instead of our initial downgrades. // (See the downhiddenartifact and downhiddencross test cases). - actual, err := BuildList(target, &override{ + actual, err := BuildList([]module.Version{target}, &override{ target: target, list: downgraded, Reqs: reqs, @@ -466,7 +470,7 @@ List: } } - return BuildList(target, &override{ + return BuildList([]module.Version{target}, &override{ target: target, list: downgraded, Reqs: reqs, diff --git a/src/cmd/go/internal/mvs/mvs_test.go b/src/cmd/go/internal/mvs/mvs_test.go index 598ed66688..26d004fee2 100644 --- a/src/cmd/go/internal/mvs/mvs_test.go +++ b/src/cmd/go/internal/mvs/mvs_test.go @@ -507,7 +507,7 @@ func Test(t *testing.T) { t.Fatalf("build takes one argument: %q", line) } fns = append(fns, func(t *testing.T) { - list, err := BuildList(m(kf[1]), reqs) + list, err := BuildList([]module.Version{m(kf[1])}, reqs) checkList(t, key, list, err, val) }) continue diff --git a/src/cmd/go/internal/search/search.go b/src/cmd/go/internal/search/search.go index a0c806a259..ebd4990a68 100644 --- a/src/cmd/go/internal/search/search.go +++ b/src/cmd/go/internal/search/search.go @@ -202,12 +202,6 @@ func (m *Match) MatchPackages() { } } -var modRoot string - -func SetModRoot(dir string) { - modRoot = dir -} - // MatchDirs sets m.Dirs to a non-nil slice containing all directories that // potentially match a local pattern. The pattern must begin with an absolute // path, or "./", or "../". On Windows, the pattern may use slash or backslash @@ -215,7 +209,7 @@ func SetModRoot(dir string) { // // If any errors may have caused the set of directories to be incomplete, // MatchDirs appends those errors to m.Errs. -func (m *Match) MatchDirs() { +func (m *Match) MatchDirs(modRoots []string) { m.Dirs = []string{} if !m.IsLocal() { m.AddError(fmt.Errorf("internal error: MatchDirs: %s is not a valid filesystem pattern", m.pattern)) @@ -253,15 +247,24 @@ func (m *Match) MatchDirs() { // We need to preserve the ./ for pattern matching // and in the returned import paths. - if modRoot != "" { + if len(modRoots) > 1 { abs, err := filepath.Abs(dir) if err != nil { m.AddError(err) return } - if !hasFilepathPrefix(abs, modRoot) { - m.AddError(fmt.Errorf("directory %s is outside module root (%s)", abs, modRoot)) - return + var found bool + for _, modRoot := range modRoots { + if modRoot != "" && hasFilepathPrefix(abs, modRoot) { + found = true + } + } + if !found { + plural := "" + if len(modRoots) > 1 { + plural = "s" + } + m.AddError(fmt.Errorf("directory %s is outside module root%s (%s)", abs, plural, strings.Join(modRoots, ", "))) } } @@ -424,19 +427,19 @@ func WarnUnmatched(matches []*Match) { // ImportPaths returns the matching paths to use for the given command line. // It calls ImportPathsQuiet and then WarnUnmatched. -func ImportPaths(patterns []string) []*Match { - matches := ImportPathsQuiet(patterns) +func ImportPaths(patterns, modRoots []string) []*Match { + matches := ImportPathsQuiet(patterns, modRoots) WarnUnmatched(matches) return matches } // ImportPathsQuiet is like ImportPaths but does not warn about patterns with no matches. -func ImportPathsQuiet(patterns []string) []*Match { +func ImportPathsQuiet(patterns, modRoots []string) []*Match { var out []*Match for _, a := range CleanPatterns(patterns) { m := NewMatch(a) if m.IsLocal() { - m.MatchDirs() + m.MatchDirs(modRoots) // Change the file import path to a regular import path if the package // is in GOPATH or GOROOT. We don't report errors here; LoadImport -- GitLab From d8ceb133cac65b47c3f5bb292fbb28690c8b89a5 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 21 Jul 2021 11:43:57 -0700 Subject: [PATCH 0522/2500] [dev.typeparams] runtime: mark TestGcSys as flaky I don't know what this test is doing, but it very frequently flakes for me while testing mundane compiler CLs. According to the issue log, it's been flaky for ~3 years. Updates #37331. Change-Id: I81c43ad646ee12d4c6561290a54e4bf637695bc6 Reviewed-on: https://go-review.googlesource.com/c/go/+/336349 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/runtime/gc_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/runtime/gc_test.go b/src/runtime/gc_test.go index 5e7c6c574f..0ec5331534 100644 --- a/src/runtime/gc_test.go +++ b/src/runtime/gc_test.go @@ -21,6 +21,7 @@ import ( ) func TestGcSys(t *testing.T) { + t.Skip("skipping known-flaky test; golang.org/issue/37331") if os.Getenv("GOGC") == "off" { t.Skip("skipping test; GOGC=off in environment") } -- GitLab From 4cdc65d32a3f0378cc508e8eb395063b83683fd4 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 22 Jul 2021 15:30:01 -0700 Subject: [PATCH 0523/2500] [dev.typeparams] cmd/compile/internal/types: format union types Previously it was just printing . Now it prints things like int32|~int64. Change-Id: I960b011ce8ed360020a49ae7809d85d1d1fdbfb2 Reviewed-on: https://go-review.googlesource.com/c/go/+/336692 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/types/fmt.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/cmd/compile/internal/types/fmt.go b/src/cmd/compile/internal/types/fmt.go index a52dd060a0..0824f6d093 100644 --- a/src/cmd/compile/internal/types/fmt.go +++ b/src/cmd/compile/internal/types/fmt.go @@ -590,6 +590,18 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type b.WriteString(fmt.Sprintf("%p", t)) } + case TUNION: + for i := 0; i < t.NumTerms(); i++ { + if i > 0 { + b.WriteString("|") + } + elem, tilde := t.Term(i) + if tilde { + b.WriteString("~") + } + tconv2(b, elem, 0, mode, visited) + } + case Txxx: b.WriteString("Txxx") -- GitLab From 12866bd8ea13e43bc5995f58cdeb67ffd64a1c8c Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 21 Jul 2021 16:23:17 -0700 Subject: [PATCH 0524/2500] [dev.typeparams] Add CONVIFACE nodes in noder2, where possible Changes to add CONVIFACE nodes where possible in noder2, even when the args are typeparams. The transformation to insert a CONVIFACE node can usually happen when there an obvious assignment/conversion to an interface type from a non-interface type. So, we now do this tranformation for: - direct conversions to an interface type - function arguments that are implicitly converted to an interface based on the parameter types. - EQ/NE comparison of an interface and a non-interface With this change, we can remove some special case checks for CONVIFACE nodes after transformation in node(), and instead just have the one check in the CONVIFACE check. Change-Id: I7cf2ef920aebf9e5553210aeaf19f344e128ca62 Reviewed-on: https://go-review.googlesource.com/c/go/+/336992 Trust: Dan Scales Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/helpers.go | 40 +++++++++++++------- src/cmd/compile/internal/noder/stencil.go | 41 +-------------------- src/cmd/compile/internal/noder/transform.go | 21 ++++++----- 3 files changed, 41 insertions(+), 61 deletions(-) diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index 15b3277908..2b00a9d7a6 100644 --- a/src/cmd/compile/internal/noder/helpers.go +++ b/src/cmd/compile/internal/noder/helpers.go @@ -116,9 +116,12 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) if fun.Op() == ir.OTYPE { // Actually a type conversion, not a function call. - if fun.Type().HasTParam() || args[0].Type().HasTParam() { - // For type params, don't typecheck until we actually know - // the type. + if !fun.Type().IsInterface() && + (fun.Type().HasTParam() || args[0].Type().HasTParam()) { + // For type params, we can transform if fun.Type() is known + // to be an interface (in which case a CONVIFACE node will be + // inserted). Otherwise, don't typecheck until we actually + // know the type. return typed(typ, n) } typed(typ, n) @@ -169,11 +172,15 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) } if fun.Type().HasTParam() { - // If the fun arg is or has a type param, don't do any extra - // transformations, since we may not have needed properties yet - // (e.g. number of return values, etc). The type param is probably - // described by a structural constraint that requires it to be a - // certain function type, etc., but we don't want to analyze that. + // If the fun arg is or has a type param, we can't do all the + // transformations, since we may not have needed properties yet. + // (e.g. number of return values, etc). However, if we do have the + // function type (even though it is parameterized), then can add in + // any needed CONVIFACE nodes. We can't do anything if fun is a type + // param (which is probably described by a structural constraint) + if fun.Type().Kind() == types.TFUNC { + typecheckaste(ir.OCALL, fun, n.IsDDD, fun.Type().Params(), n.Args, true) + } return typed(typ, n) } @@ -203,11 +210,18 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) func Compare(pos src.XPos, typ *types.Type, op ir.Op, x, y ir.Node) ir.Node { n := ir.NewBinaryExpr(pos, op, x, y) if x.Type().HasTParam() || y.Type().HasTParam() { - // Delay transformCompare() if either arg has a type param, since - // it needs to know the exact types to decide on any needed conversions. - n.SetType(typ) - n.SetTypecheck(3) - return n + xIsInt := x.Type().IsInterface() + yIsInt := y.Type().IsInterface() + if !(xIsInt && !yIsInt || !xIsInt && yIsInt) { + // If either arg is a type param, then we can still do the + // transformCompare() if we know that one arg is an interface + // and the other is not. Otherwise, we delay + // transformCompare(), since it needs to know the exact types + // to decide on any needed conversions. + n.SetType(typ) + n.SetTypecheck(3) + return n + } } typed(typ, n) transformCompare(n) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 59f11bbe23..a8f9cf3b3e 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1251,21 +1251,13 @@ func (subst *subster) node(n ir.Node) ir.Node { case ir.OCALL: call := m.(*ir.CallExpr) - convcheck := false switch call.X.Op() { case ir.OTYPE: // Transform the conversion, now that we know the // type argument. m = transformConvCall(call) - if m.Op() == ir.OCONVIFACE { - // Note: srcType uses x.Args[0], not m.X or call.Args[0], because - // we need the type before the type parameter -> type argument substitution. - srcType := x.(*ir.CallExpr).Args[0].Type() - if ix := subst.findDictType(srcType); ix >= 0 { - c := m.(*ir.ConvExpr) - m = subst.convertUsingDictionary(c.Pos(), c.X, c.Type(), srcType, ix) - } - } + // CONVIFACE transformation was already done in node2 + assert(m.Op() != ir.OCONVIFACE) case ir.OMETHVALUE, ir.OMETHEXPR: // Redo the transformation of OXDOT, now that we @@ -1275,7 +1267,6 @@ func (subst *subster) node(n ir.Node) ir.Node { transformDot(call.X.(*ir.SelectorExpr), true) call.X.SetType(subst.unshapifyTyp(call.X.Type())) transformCall(call) - convcheck = true case ir.ODOT, ir.ODOTPTR: // An OXDOT for a generic receiver was resolved to @@ -1283,7 +1274,6 @@ func (subst *subster) node(n ir.Node) ir.Node { // value. Transform the call to that function, now // that the OXDOT was resolved. transformCall(call) - convcheck = true case ir.ONAME: name := call.X.Name() @@ -1308,12 +1298,10 @@ func (subst *subster) node(n ir.Node) ir.Node { // type parameter (implied to be a function via a // structural constraint) which is now resolved. transformCall(call) - convcheck = true } case ir.OCLOSURE: transformCall(call) - convcheck = true case ir.OFUNCINST: // A call with an OFUNCINST will get transformed @@ -1323,16 +1311,6 @@ func (subst *subster) node(n ir.Node) ir.Node { default: base.FatalfAt(call.Pos(), fmt.Sprintf("Unexpected op with CALL during stenciling: %v", call.X.Op())) } - if convcheck { - for i, arg := range x.(*ir.CallExpr).Args { - if arg.Type().HasTParam() && arg.Op() != ir.OCONVIFACE && - call.Args[i].Op() == ir.OCONVIFACE { - ix := subst.findDictType(arg.Type()) - assert(ix >= 0) - call.Args[i] = subst.convertUsingDictionary(arg.Pos(), call.Args[i].(*ir.ConvExpr).X, call.Args[i].Type(), arg.Type(), ix) - } - } - } case ir.OCLOSURE: // We're going to create a new closure from scratch, so clear m @@ -1391,21 +1369,6 @@ func (subst *subster) node(n ir.Node) ir.Node { if ix := subst.findDictType(t); ix >= 0 { m = subst.convertUsingDictionary(x.Pos(), m.(*ir.ConvExpr).X, m.Type(), t, ix) } - case ir.OEQ, ir.ONE: - // Equality between a non-interface and an interface requires the non-interface - // to be promoted to an interface. - x := x.(*ir.BinaryExpr) - m := m.(*ir.BinaryExpr) - if i := x.Y.Type(); i.IsInterface() { - if ix := subst.findDictType(x.X.Type()); ix >= 0 { - m.X = subst.convertUsingDictionary(m.X.Pos(), m.X, i, x.X.Type(), ix) - } - } - if i := x.X.Type(); i.IsInterface() { - if ix := subst.findDictType(x.Y.Type()); ix >= 0 { - m.Y = subst.convertUsingDictionary(m.Y.Pos(), m.Y, i, x.X.Type(), ix) - } - } case ir.ONEW: // New needs to pass a concrete type to the runtime. diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index 86bdb91395..f89ae13237 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -156,7 +156,7 @@ func transformCall(n *ir.CallExpr) { n.SetOp(ir.OCALLFUNC) } - typecheckaste(ir.OCALL, n.X, n.IsDDD, t.Params(), n.Args) + typecheckaste(ir.OCALL, n.X, n.IsDDD, t.Params(), n.Args, false) if l.Op() == ir.ODOTMETH && len(deref(n.X.Type().Recv().Type).RParams()) == 0 { typecheck.FixMethodCall(n) } @@ -194,7 +194,7 @@ func transformCompare(n *ir.BinaryExpr) { aop, _ := typecheck.Assignop(lt, rt) if aop != ir.OXXX { types.CalcSize(lt) - if rt.IsInterface() == lt.IsInterface() || lt.Width >= 1<<16 { + if lt.HasTParam() || rt.IsInterface() == lt.IsInterface() || lt.Width >= 1<<16 { l = ir.NewConvExpr(base.Pos, aop, rt, l) l.SetTypecheck(1) } @@ -207,7 +207,7 @@ func transformCompare(n *ir.BinaryExpr) { aop, _ := typecheck.Assignop(rt, lt) if aop != ir.OXXX { types.CalcSize(rt) - if rt.IsInterface() == lt.IsInterface() || rt.Width >= 1<<16 { + if rt.HasTParam() || rt.IsInterface() == lt.IsInterface() || rt.Width >= 1<<16 { r = ir.NewConvExpr(base.Pos, aop, lt, r) r.SetTypecheck(1) } @@ -468,8 +468,11 @@ func assignconvfn(n ir.Node, t *types.Type) ir.Node { return r } -// Corresponds to typecheck.typecheckaste. -func typecheckaste(op ir.Op, call ir.Node, isddd bool, tstruct *types.Type, nl ir.Nodes) { +// Corresponds to typecheck.typecheckaste, but we add an extra flag convifaceOnly +// only. If convifaceOnly is true, we only do interface conversion. We use this to do +// early insertion of CONVIFACE nodes during noder2, when the function or args may +// have typeparams. +func typecheckaste(op ir.Op, call ir.Node, isddd bool, tstruct *types.Type, nl ir.Nodes, convifaceOnly bool) { var t *types.Type var i int @@ -488,7 +491,7 @@ func typecheckaste(op ir.Op, call ir.Node, isddd bool, tstruct *types.Type, nl i if isddd { n = nl[i] ir.SetPos(n) - if n.Type() != nil { + if n.Type() != nil && (!convifaceOnly || t.IsInterface()) { nl[i] = assignconvfn(n, t) } return @@ -498,7 +501,7 @@ func typecheckaste(op ir.Op, call ir.Node, isddd bool, tstruct *types.Type, nl i for ; i < len(nl); i++ { n = nl[i] ir.SetPos(n) - if n.Type() != nil { + if n.Type() != nil && (!convifaceOnly || t.IsInterface()) { nl[i] = assignconvfn(n, t.Elem()) } } @@ -507,7 +510,7 @@ func typecheckaste(op ir.Op, call ir.Node, isddd bool, tstruct *types.Type, nl i n = nl[i] ir.SetPos(n) - if n.Type() != nil { + if n.Type() != nil && (!convifaceOnly || t.IsInterface()) { nl[i] = assignconvfn(n, t) } i++ @@ -529,7 +532,7 @@ func transformReturn(rs *ir.ReturnStmt) { return } - typecheckaste(ir.ORETURN, nil, false, ir.CurFunc.Type().Results(), nl) + typecheckaste(ir.ORETURN, nil, false, ir.CurFunc.Type().Results(), nl, false) } // transformSelect transforms a select node, creating an assignment list as needed -- GitLab From 02c01725002a73739cefbc9fcf2575469be6da13 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 12 Jul 2021 19:34:15 -0700 Subject: [PATCH 0525/2500] [dev.typeparams] cmd/compile: add dictionary entries for itab conversion This fix the case where a type param or derived type is converted to a non-empty interface. Previously, we were converting to an empty interface and then using DOTTYPE to convert to the correct non-empty interface. In that case, we can get the needed itab directly from the dictionary. This is needed for correctness from shapes, if the destination interface is parameterized, else we will incorrectly convert to the shape version of the interface. Creating/writing an itab can involve generating wrappers for a bunch of methods, which may use dictionaries. So, all the dictionaries/instantiations are being generated on the fly and have recursive relationships, it is simplest to finish creating/writing the itabs at the end of the stenciling phase. So, we create a list of the dictionaries which need to be completed by writing out their itab entries. The existing tests ordered.go, ifaceconv.go, and issue44688.go make use of this optimization. Got itab conversions for bound calls working, except for 13.go. Also, want to get rid of the concretify, but I think we need more info on the Bound from types2. Change-Id: If552958a7b8a435500d6cc42c401572c367b30d1 Reviewed-on: https://go-review.googlesource.com/c/go/+/336993 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/irgen.go | 19 ++- src/cmd/compile/internal/noder/stencil.go | 127 +++++++++++++----- .../compile/internal/reflectdata/reflect.go | 18 +++ test/run.go | 3 +- 4 files changed, 134 insertions(+), 33 deletions(-) diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index 880073a89e..6a8763c908 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -104,6 +104,9 @@ type gfInfo struct { // method and function calls (OCALL), function values (OFUNCINST), method // values/expressions (OXDOT). subDictCalls []ir.Node + // Nodes in generic functions that are a conversion from a typeparam/derived + // type to a specific interface. + itabConvs []ir.Node } // instInfo is information gathered on an gcshape (or fully concrete) @@ -115,8 +118,9 @@ type instInfo struct { gf *ir.Name // The associated generic function gfInfo *gfInfo - startSubDict int // Start of dict entries for subdictionaries - dictLen int // Total number of entries in dictionary + startSubDict int // Start of dict entries for subdictionaries + startItabConv int // Start of dict entries for itab conversions + dictLen int // Total number of entries in dictionary // Map from nodes in instantiated fun (OCALL, OCALLMETHOD, OFUNCINST, and // OMETHEXPR) to the associated dictionary entry for a sub-dictionary @@ -146,6 +150,17 @@ type irgen struct { // its instantiated function, associated generic function/method, and the // mapping from IR nodes to dictionary entries. instInfoMap map[*types.Sym]*instInfo + + // dictionary syms which we need to finish, by writing out any itabconv + // entries. + dictSymsToFinalize []*delayInfo +} + +type delayInfo struct { + gf *ir.Name + targs []*types.Type + sym *types.Sym + off int } func (g *irgen) generate(noders []*noder) { diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index a8f9cf3b3e..461083d171 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -225,6 +225,7 @@ func (g *irgen) stencil() { g.instantiateMethods() } + g.finalizeSyms() } // buildClosure makes a closure to implement x, a OFUNCINST or OMETHEXPR @@ -823,11 +824,12 @@ func (g *irgen) getInstantiation(nameNode *ir.Name, targs []*types.Type, isMeth // to the list of decls. gfInfo := g.getGfInfo(nameNode) info = &instInfo{ - gf: nameNode, - gfInfo: gfInfo, - startSubDict: len(targs) + len(gfInfo.derivedTypes), - dictLen: len(targs) + len(gfInfo.derivedTypes) + len(gfInfo.subDictCalls), - dictEntryMap: make(map[ir.Node]int), + gf: nameNode, + gfInfo: gfInfo, + startSubDict: len(targs) + len(gfInfo.derivedTypes), + startItabConv: len(targs) + len(gfInfo.derivedTypes) + len(gfInfo.subDictCalls), + dictLen: len(targs) + len(gfInfo.derivedTypes) + len(gfInfo.subDictCalls) + len(gfInfo.itabConvs), + dictEntryMap: make(map[ir.Node]int), } // genericSubst fills in info.dictParam and info.dictEntryMap. st := g.genericSubst(sym, nameNode, shapes, targs, isMeth, info) @@ -1235,12 +1237,9 @@ func (subst *subster) node(n ir.Node) ir.Node { // Implement x.M as a conversion-to-bound-interface // 1) convert x to the bound interface // 2) call M on that interface - dst := subst.concretify.Typ(subst.shape2param[src].Bound()) - // Mark that we use the methods of this concrete type. - // Otherwise the linker deadcode-eliminates them :( - ix := subst.findDictType(subst.shape2param[src]) - assert(ix >= 0) - mse.X = subst.convertUsingDictionary(m.Pos(), mse.X, dst, subst.shape2param[src], ix) + gsrc := x.(*ir.SelectorExpr).X.Type() + dst := subst.concretify.Typ(gsrc.Bound()) + mse.X = subst.convertUsingDictionary(m.Pos(), mse.X, x, dst, gsrc) } } transformDot(mse, false) @@ -1365,9 +1364,8 @@ func (subst *subster) node(n ir.Node) ir.Node { x := x.(*ir.ConvExpr) // Note: x's argument is still typed as a type parameter. // m's argument now has an instantiated type. - t := x.X.Type() - if ix := subst.findDictType(t); ix >= 0 { - m = subst.convertUsingDictionary(x.Pos(), m.(*ir.ConvExpr).X, m.Type(), t, ix) + if x.X.Type().HasTParam() { + m = subst.convertUsingDictionary(m.Pos(), m.(*ir.ConvExpr).X, x, m.Type(), x.X.Type()) } case ir.ONEW: @@ -1411,14 +1409,35 @@ func (subst *subster) findDictType(t *types.Type) int { return -1 } -// convertUsingDictionary converts value v from instantiated type src (which is index -// 'ix' in the instantiation's dictionary) to an interface type dst. -func (subst *subster) convertUsingDictionary(pos src.XPos, v ir.Node, dst, src *types.Type, ix int) ir.Node { - if !dst.IsInterface() { - base.Fatalf("can only convert type parameters to interfaces %+v -> %+v", src, dst) +// convertUsingDictionary converts value v from instantiated type src to an interface +// type dst, by returning a new set of nodes that make use of a dictionary entry. src +// is the generic (not shape) type, and gn is the original generic node of the +// CONVIFACE node or XDOT node (for a bound method call) that is causing the +// conversion. +func (subst *subster) convertUsingDictionary(pos src.XPos, v ir.Node, gn ir.Node, dst, src *types.Type) ir.Node { + assert(src.HasTParam()) + assert(dst.IsInterface()) + + var rt ir.Node + if !dst.IsEmptyInterface() { + // We should have an itab entry in the dictionary. Using this itab + // will be more efficient than converting to an empty interface first + // and then type asserting to dst. + ix := -1 + for i, ic := range subst.info.gfInfo.itabConvs { + if ic == gn { + ix = subst.info.startItabConv + i + break + } + } + assert(ix >= 0) + rt = getDictionaryEntry(pos, subst.info.dictParam, ix, subst.info.dictLen) + } else { + ix := subst.findDictType(src) + assert(ix >= 0) + // Load the actual runtime._type of the type parameter from the dictionary. + rt = subst.getDictionaryType(pos, ix) } - // Load the actual runtime._type of the type parameter from the dictionary. - rt := subst.getDictionaryType(pos, ix) // Convert value to an interface type, so the data field is what we want. if !v.Type().IsInterface() { @@ -1432,12 +1451,6 @@ func (subst *subster) convertUsingDictionary(pos src.XPos, v ir.Node, dst, src * data := ir.NewUnaryExpr(pos, ir.OIDATA, v) typed(types.Types[types.TUNSAFEPTR], data) var i ir.Node = ir.NewBinaryExpr(pos, ir.OEFACE, rt, data) - if !dst.IsEmptyInterface() { - // We just built an empty interface{}. Type it as such, - // then assert it to the required non-empty interface. - typed(types.NewInterface(types.LocalPkg, nil), i) - i = ir.NewTypeAssertExpr(pos, i, nil) - } typed(dst, i) // TODO: we're throwing away the type word of the original version // of m here (it would be OITAB(m)), which probably took some @@ -1650,14 +1663,58 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) infoPrint(" - Subdict %v\n", sym.Name) } } - objw.Global(lsym, int32(off), obj.DUPOK|obj.RODATA) - infoPrint("=== Done dictionary\n") - // Add any new, fully instantiated types seen during the substitution to g.instTypeList. + delay := &delayInfo{ + gf: gf, + targs: targs, + sym: sym, + off: off, + } + g.dictSymsToFinalize = append(g.dictSymsToFinalize, delay) g.instTypeList = append(g.instTypeList, subst.InstTypeList...) } return sym } + +// finalizeSyms finishes up all dictionaries on g.dictSymsToFinalize, by writing out +// any needed LSyms for itabs. The itab lsyms create wrappers which need various +// dictionaries and method instantiations to be complete, so, to avoid recursive +// dependencies, we finalize the itab lsyms only after all dictionaries syms and +// instantiations have been created. +func (g *irgen) finalizeSyms() { + for _, d := range g.dictSymsToFinalize { + lsym := d.sym.Linksym() + info := g.getGfInfo(d.gf) + + subst := typecheck.Tsubster{ + Tparams: info.tparams, + Targs: d.targs, + } + + // Emit an entry for each itab + for _, n := range info.itabConvs { + var srctype, dsttype *types.Type + if n.Op() == ir.OXDOT { + se := n.(*ir.SelectorExpr) + srctype = subst.Typ(se.X.Type()) + dsttype = subst.Typ(se.X.Type().Bound()) + } else { + assert(n.Op() == ir.OCONVIFACE) + srctype = subst.Typ(n.(*ir.ConvExpr).X.Type()) + dsttype = subst.Typ(n.Type()) + } + itabLsym := reflectdata.ITabLsym(srctype, dsttype) + d.off = objw.SymPtr(lsym, d.off, itabLsym, 0) + } + + objw.Global(lsym, int32(d.off), obj.DUPOK|obj.RODATA) + infoPrint("=== Finalized dictionary %s\n", d.sym.Name) + + g.instTypeList = append(g.instTypeList, subst.InstTypeList...) + } + g.dictSymsToFinalize = nil +} + func (g *irgen) getDictionaryValue(gf *ir.Name, targs []*types.Type, isMeth bool) ir.Node { sym := g.getDictionarySym(gf, targs, isMeth) @@ -1778,6 +1835,16 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo { infoPrint(" Optional subdictionary at generic bound call: %v\n", n) info.subDictCalls = append(info.subDictCalls, n) } + if n.Op() == ir.OCONVIFACE && n.Type().IsInterface() && + !n.Type().IsEmptyInterface() && + n.(*ir.ConvExpr).X.Type().HasTParam() { + infoPrint(" Itab for interface conv: %v\n", n) + info.itabConvs = append(info.itabConvs, n) + } + if n.Op() == ir.OXDOT && n.(*ir.SelectorExpr).X.Type().IsTypeParam() { + infoPrint(" Itab for interface conv: %v\n", n) + info.itabConvs = append(info.itabConvs, n) + } if n.Op() == ir.OCLOSURE { // Visit the closure body and add all relevant entries to the // dictionary of the outer function (closure will just use diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 2236c7f1cf..1391102d0f 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -833,6 +833,18 @@ func TypePtr(t *types.Type) *ir.AddrExpr { return typecheck.Expr(typecheck.NodAddr(n)).(*ir.AddrExpr) } +// ITabLsym returns the LSym representing the itab for concreate type typ +// implementing interface iface. +func ITabLsym(typ, iface *types.Type) *obj.LSym { + s, existed := ir.Pkgs.Itab.LookupOK(typ.LinkString() + "," + iface.LinkString()) + lsym := s.Linksym() + + if !existed { + writeITab(lsym, typ, iface) + } + return lsym +} + // ITabAddr returns an expression representing a pointer to the itab // for concrete type typ implementing interface iface. func ITabAddr(typ, iface *types.Type) *ir.AddrExpr { @@ -1288,6 +1300,12 @@ func writeITab(lsym *obj.LSym, typ, iface *types.Type) { break } } + if sigs[0].Sym.Name == "==" { + sigs = sigs[1:] + if len(sigs) == 0 { + break + } + } } if len(sigs) != 0 { base.Fatalf("incomplete itab") diff --git a/test/run.go b/test/run.go index 23eebcee2e..5624654fec 100644 --- a/test/run.go +++ b/test/run.go @@ -2182,7 +2182,8 @@ var g3Failures = setOf( "typeparam/nested.go", // -G=3 doesn't support function-local types with generics - "typeparam/mdempsky/4.go", // -G=3 can't export functions with labeled breaks in loops + "typeparam/mdempsky/4.go", // -G=3 can't export functions with labeled breaks in loops + "typeparam/mdempsky/13.go", // problem with interface as as a type arg. "typeparam/cons.go", // causes an unreachable method "typeparam/issue44688.go", // interface conversion fails due to missing method -- GitLab From e6d956e1c521b948257dd20056436d133df176f6 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Fri, 23 Jul 2021 14:38:04 -0700 Subject: [PATCH 0526/2500] [dev.typeparams] cmd/compile: add CONVIFACE nodes for return values during noder2 Even if we can otherwise transform a return statement because of type params, add CONVIFACE nodes where appropriate. Change-Id: Ia2216d5f6805926075ba6802a4385eee1d63e37e Reviewed-on: https://go-review.googlesource.com/c/go/+/337049 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stmt.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/cmd/compile/internal/noder/stmt.go b/src/cmd/compile/internal/noder/stmt.go index b7085c4776..5af4a2da9c 100644 --- a/src/cmd/compile/internal/noder/stmt.go +++ b/src/cmd/compile/internal/noder/stmt.go @@ -128,6 +128,11 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { if e.Type().HasTParam() { // Delay transforming the return statement if any of the // return values have a type param. + if !ir.HasNamedResults(ir.CurFunc) { + // But add CONVIFACE nodes where needed if + // any of the return values have interface type. + typecheckaste(ir.ORETURN, nil, false, ir.CurFunc.Type().Results(), n.Results, true) + } n.SetTypecheck(3) return n } -- GitLab From 6992dcdad9b94a2b33b957474ef0eb210d563a40 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 23 Jul 2021 15:23:57 -0700 Subject: [PATCH 0527/2500] [dev.typeparams] cmd/compile: fix some issues with cons.go Add a test to make sure there's no invalid OCONVIFACEs when stenciling is done. Use concrete types for the type of DOTTYPE and DOTTYPE2. MarkTypeUsedInInterface - should we allow types with shape types underneath? I think the itab CL will help with this (at least, for a remaining cons.go issue). Change-Id: I2c96d74e8daaca26cadc84ea94abb9a27c0bb240 Reviewed-on: https://go-review.googlesource.com/c/go/+/337069 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 24 ++++++++++++++++++- .../compile/internal/reflectdata/reflect.go | 6 +++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 461083d171..85538f590d 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -994,6 +994,26 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes, targs g.instTypeList = append(g.instTypeList, subst.unshapify.InstTypeList...) g.instTypeList = append(g.instTypeList, subst.concretify.InstTypeList...) + if doubleCheck { + okConvs := map[ir.Node]bool{} + ir.Visit(newf, func(n ir.Node) { + if n.Op() == ir.OIDATA { + // IDATA(OCONVIFACE(x)) is ok, as we don't use the type of x. + // TODO: use some other op besides OCONVIFACE. ONEW might work + // (with appropriate direct vs. indirect interface cases). + okConvs[n.(*ir.UnaryExpr).X] = true + } + if n.Op() == ir.OCONVIFACE && !okConvs[n] { + c := n.(*ir.ConvExpr) + if c.X.Type().HasShape() { + ir.Dump("BAD FUNCTION", newf) + ir.Dump("BAD CONVERSION", c) + base.Fatalf("converting shape type to interface") + } + } + }) + } + return newf } @@ -1367,6 +1387,8 @@ func (subst *subster) node(n ir.Node) ir.Node { if x.X.Type().HasTParam() { m = subst.convertUsingDictionary(m.Pos(), m.(*ir.ConvExpr).X, x, m.Type(), x.X.Type()) } + case ir.ODOTTYPE, ir.ODOTTYPE2: + m.SetType(subst.unshapifyTyp(m.Type())) case ir.ONEW: // New needs to pass a concrete type to the runtime. @@ -1535,7 +1557,7 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) // Enforce that only concrete types can make it to here. for _, t := range targs { - if t.IsShape() { + if t.HasShape() { panic(fmt.Sprintf("shape %+v in dictionary for %s", t, gf.Sym().Name)) } } diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 1391102d0f..875d53b3cc 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -1982,6 +1982,12 @@ var ZeroSize int64 // MarkTypeUsedInInterface marks that type t is converted to an interface. // This information is used in the linker in dead method elimination. func MarkTypeUsedInInterface(t *types.Type, from *obj.LSym) { + if t.HasShape() { + // TODO: shape types shouldn't be put in interfaces, so we shouldn't ever get here. + // We don't from ../noder/stencil.go, but we do from ../walk/walk.go when we let + // shape types become the types of interfaces. + //base.Fatalf("shape types have no methods %+v", t) + } tsym := TypeLinksym(t) // Emit a marker relocation. The linker will know the type is converted // to an interface if "from" is reachable. -- GitLab From 9f928f9318efb9e6a9d45e7ed959afaaee4b7315 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 23 Jul 2021 10:00:10 -0400 Subject: [PATCH 0528/2500] [dev.typeparams] go/types, types2: set tset when constructing interfaces in the universe As of CL 334894, type sets are lazily evaluated on interfaces. For the universe interfaces error and comparable, this can lead to data races when type checking concurrently. Fix this by computing their type set when they are defined. Tested using the repro from #47345. I considered checking this in as a test, but it probably wouldn't add much value going forward. Fixes #47345 Change-Id: I014a511b8e3c092c86201a8bfc7f5f494f8f20e8 Reviewed-on: https://go-review.googlesource.com/c/go/+/336910 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/universe.go | 8 ++++++-- src/go/types/universe.go | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/types2/universe.go b/src/cmd/compile/internal/types2/universe.go index e2dd0df69e..0f711a6b68 100644 --- a/src/cmd/compile/internal/types2/universe.go +++ b/src/cmd/compile/internal/types2/universe.go @@ -88,7 +88,9 @@ func defPredeclaredTypes() { res := NewVar(nopos, nil, "", Typ[String]) sig := NewSignature(nil, nil, NewTuple(res), false) err := NewFunc(nopos, nil, "Error", sig) - typ := NewNamed(obj, NewInterfaceType([]*Func{err}, nil), nil) + ityp := NewInterfaceType([]*Func{err}, nil) + computeTypeSet(nil, nopos, ityp) // prevent races due to lazy computation of tset + typ := NewNamed(obj, ityp, nil) sig.recv = NewVar(nopos, nil, "", typ) def(obj) } @@ -99,7 +101,9 @@ func defPredeclaredTypes() { obj.setColor(black) sig := NewSignature(nil, nil, nil, false) eql := NewFunc(nopos, nil, "==", sig) - typ := NewNamed(obj, NewInterfaceType([]*Func{eql}, nil), nil) + ityp := NewInterfaceType([]*Func{eql}, nil) + computeTypeSet(nil, nopos, ityp) // prevent races due to lazy computation of tset + typ := NewNamed(obj, ityp, nil) sig.recv = NewVar(nopos, nil, "", typ) def(obj) } diff --git a/src/go/types/universe.go b/src/go/types/universe.go index 59952bc642..489587f393 100644 --- a/src/go/types/universe.go +++ b/src/go/types/universe.go @@ -89,7 +89,9 @@ func defPredeclaredTypes() { res := NewVar(token.NoPos, nil, "", Typ[String]) sig := NewSignature(nil, nil, NewTuple(res), false) err := NewFunc(token.NoPos, nil, "Error", sig) - typ := NewNamed(obj, NewInterfaceType([]*Func{err}, nil), nil) + ityp := NewInterfaceType([]*Func{err}, nil) + computeTypeSet(nil, token.NoPos, ityp) // prevent races due to lazy computation of tset + typ := NewNamed(obj, ityp, nil) sig.recv = NewVar(token.NoPos, nil, "", typ) def(obj) } @@ -100,7 +102,9 @@ func defPredeclaredTypes() { obj.setColor(black) sig := NewSignature(nil, nil, nil, false) eql := NewFunc(token.NoPos, nil, "==", sig) - typ := NewNamed(obj, NewInterfaceType([]*Func{eql}, nil), nil) + ityp := NewInterfaceType([]*Func{eql}, nil) + computeTypeSet(nil, token.NoPos, ityp) // prevent races due to lazy computation of tset + typ := NewNamed(obj, ityp, nil) sig.recv = NewVar(token.NoPos, nil, "", typ) def(obj) } -- GitLab From 77e0bf294cc431d5608c183d56b6aadbb95b09b0 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 23 Jul 2021 18:10:58 -0700 Subject: [PATCH 0529/2500] [dev.typeparams] cmd/compile: introduce OCONVIDATA op This operation computes just the data field needed to put its argument into an interface. Used by generics because we produce the type field of an interface using dictionaries (instead of statically). With this operation defined, we can now assert that shape types are never marked as used in interfaces (the only previous use was IDATA(CONVIFACE(t))). Change-Id: Idb1eb5f3b238285cb99413d382599c0621b7681a Reviewed-on: https://go-review.googlesource.com/c/go/+/337109 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/escape/expr.go | 2 +- src/cmd/compile/internal/ir/expr.go | 2 +- src/cmd/compile/internal/ir/fmt.go | 4 +- src/cmd/compile/internal/ir/node.go | 1 + src/cmd/compile/internal/ir/op_string.go | 233 +++++++++--------- src/cmd/compile/internal/noder/stencil.go | 22 +- .../compile/internal/reflectdata/reflect.go | 6 +- src/cmd/compile/internal/typecheck/iexport.go | 2 +- src/cmd/compile/internal/typecheck/iimport.go | 2 +- src/cmd/compile/internal/walk/assign.go | 1 + src/cmd/compile/internal/walk/convert.go | 14 +- src/cmd/compile/internal/walk/expr.go | 7 + src/cmd/compile/internal/walk/order.go | 10 +- 13 files changed, 161 insertions(+), 145 deletions(-) diff --git a/src/cmd/compile/internal/escape/expr.go b/src/cmd/compile/internal/escape/expr.go index 60b44fe0aa..b7423e114a 100644 --- a/src/cmd/compile/internal/escape/expr.go +++ b/src/cmd/compile/internal/escape/expr.go @@ -109,7 +109,7 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) { } else { e.expr(k, n.X) } - case ir.OCONVIFACE: + case ir.OCONVIFACE, ir.OCONVIDATA: n := n.(*ir.ConvExpr) if !n.X.Type().IsInterface() && !types.IsDirectIface(n.X.Type()) { k = e.spill(k, n) diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 09d6d87f06..86323e6b8f 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -270,7 +270,7 @@ func (n *ConvExpr) SetOp(op Op) { switch op { default: panic(n.no("SetOp " + op.String())) - case OCONV, OCONVIFACE, OCONVNOP, OBYTES2STR, OBYTES2STRTMP, ORUNES2STR, OSTR2BYTES, OSTR2BYTESTMP, OSTR2RUNES, ORUNESTR, OSLICE2ARRPTR: + case OCONV, OCONVIFACE, OCONVIDATA, OCONVNOP, OBYTES2STR, OBYTES2STRTMP, ORUNES2STR, OSTR2BYTES, OSTR2BYTESTMP, OSTR2RUNES, ORUNESTR, OSLICE2ARRPTR: n.op = op } } diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index e8dd9df69d..3c5a928590 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -185,6 +185,7 @@ var OpPrec = []int{ OCLOSE: 8, OCOMPLIT: 8, OCONVIFACE: 8, + OCONVIDATA: 8, OCONVNOP: 8, OCONV: 8, OCOPY: 8, @@ -546,7 +547,7 @@ func exprFmt(n Node, s fmt.State, prec int) { n = nn.X continue } - case OCONV, OCONVNOP, OCONVIFACE: + case OCONV, OCONVNOP, OCONVIFACE, OCONVIDATA: nn := nn.(*ConvExpr) if nn.Implicit() { n = nn.X @@ -813,6 +814,7 @@ func exprFmt(n Node, s fmt.State, prec int) { case OCONV, OCONVIFACE, + OCONVIDATA, OCONVNOP, OBYTES2STR, ORUNES2STR, diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index f6eae58b04..0fbc867c1d 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -170,6 +170,7 @@ const ( OPTRLIT // &X (X is composite literal) OCONV // Type(X) (type conversion) OCONVIFACE // Type(X) (type conversion, to interface) + OCONVIDATA // Builds a data word to store X in an interface. Equivalent to IDATA(CONVIFACE(X)). Is an ir.ConvExpr. OCONVNOP // Type(X) (type conversion, no effect) OCOPY // copy(X, Y) ODCL // var X (declares X of type X.Type) diff --git a/src/cmd/compile/internal/ir/op_string.go b/src/cmd/compile/internal/ir/op_string.go index 05a37a60b1..0235d5eab3 100644 --- a/src/cmd/compile/internal/ir/op_string.go +++ b/src/cmd/compile/internal/ir/op_string.go @@ -52,125 +52,126 @@ func _() { _ = x[OPTRLIT-41] _ = x[OCONV-42] _ = x[OCONVIFACE-43] - _ = x[OCONVNOP-44] - _ = x[OCOPY-45] - _ = x[ODCL-46] - _ = x[ODCLFUNC-47] - _ = x[ODCLCONST-48] - _ = x[ODCLTYPE-49] - _ = x[ODELETE-50] - _ = x[ODOT-51] - _ = x[ODOTPTR-52] - _ = x[ODOTMETH-53] - _ = x[ODOTINTER-54] - _ = x[OXDOT-55] - _ = x[ODOTTYPE-56] - _ = x[ODOTTYPE2-57] - _ = x[OEQ-58] - _ = x[ONE-59] - _ = x[OLT-60] - _ = x[OLE-61] - _ = x[OGE-62] - _ = x[OGT-63] - _ = x[ODEREF-64] - _ = x[OINDEX-65] - _ = x[OINDEXMAP-66] - _ = x[OKEY-67] - _ = x[OSTRUCTKEY-68] - _ = x[OLEN-69] - _ = x[OMAKE-70] - _ = x[OMAKECHAN-71] - _ = x[OMAKEMAP-72] - _ = x[OMAKESLICE-73] - _ = x[OMAKESLICECOPY-74] - _ = x[OMUL-75] - _ = x[ODIV-76] - _ = x[OMOD-77] - _ = x[OLSH-78] - _ = x[ORSH-79] - _ = x[OAND-80] - _ = x[OANDNOT-81] - _ = x[ONEW-82] - _ = x[ONOT-83] - _ = x[OBITNOT-84] - _ = x[OPLUS-85] - _ = x[ONEG-86] - _ = x[OOROR-87] - _ = x[OPANIC-88] - _ = x[OPRINT-89] - _ = x[OPRINTN-90] - _ = x[OPAREN-91] - _ = x[OSEND-92] - _ = x[OSLICE-93] - _ = x[OSLICEARR-94] - _ = x[OSLICESTR-95] - _ = x[OSLICE3-96] - _ = x[OSLICE3ARR-97] - _ = x[OSLICEHEADER-98] - _ = x[ORECOVER-99] - _ = x[ORECOVERFP-100] - _ = x[ORECV-101] - _ = x[ORUNESTR-102] - _ = x[OSELRECV2-103] - _ = x[OIOTA-104] - _ = x[OREAL-105] - _ = x[OIMAG-106] - _ = x[OCOMPLEX-107] - _ = x[OALIGNOF-108] - _ = x[OOFFSETOF-109] - _ = x[OSIZEOF-110] - _ = x[OUNSAFEADD-111] - _ = x[OUNSAFESLICE-112] - _ = x[OMETHEXPR-113] - _ = x[OMETHVALUE-114] - _ = x[OBLOCK-115] - _ = x[OBREAK-116] - _ = x[OCASE-117] - _ = x[OCONTINUE-118] - _ = x[ODEFER-119] - _ = x[OFALL-120] - _ = x[OFOR-121] - _ = x[OFORUNTIL-122] - _ = x[OGOTO-123] - _ = x[OIF-124] - _ = x[OLABEL-125] - _ = x[OGO-126] - _ = x[ORANGE-127] - _ = x[ORETURN-128] - _ = x[OSELECT-129] - _ = x[OSWITCH-130] - _ = x[OTYPESW-131] - _ = x[OFUNCINST-132] - _ = x[OTCHAN-133] - _ = x[OTMAP-134] - _ = x[OTSTRUCT-135] - _ = x[OTINTER-136] - _ = x[OTFUNC-137] - _ = x[OTARRAY-138] - _ = x[OTSLICE-139] - _ = x[OINLCALL-140] - _ = x[OEFACE-141] - _ = x[OITAB-142] - _ = x[OIDATA-143] - _ = x[OSPTR-144] - _ = x[OCFUNC-145] - _ = x[OCHECKNIL-146] - _ = x[OVARDEF-147] - _ = x[OVARKILL-148] - _ = x[OVARLIVE-149] - _ = x[ORESULT-150] - _ = x[OINLMARK-151] - _ = x[OLINKSYMOFFSET-152] - _ = x[OTAILCALL-153] - _ = x[OGETG-154] - _ = x[OGETCALLERPC-155] - _ = x[OGETCALLERSP-156] - _ = x[OEND-157] + _ = x[OCONVIDATA-44] + _ = x[OCONVNOP-45] + _ = x[OCOPY-46] + _ = x[ODCL-47] + _ = x[ODCLFUNC-48] + _ = x[ODCLCONST-49] + _ = x[ODCLTYPE-50] + _ = x[ODELETE-51] + _ = x[ODOT-52] + _ = x[ODOTPTR-53] + _ = x[ODOTMETH-54] + _ = x[ODOTINTER-55] + _ = x[OXDOT-56] + _ = x[ODOTTYPE-57] + _ = x[ODOTTYPE2-58] + _ = x[OEQ-59] + _ = x[ONE-60] + _ = x[OLT-61] + _ = x[OLE-62] + _ = x[OGE-63] + _ = x[OGT-64] + _ = x[ODEREF-65] + _ = x[OINDEX-66] + _ = x[OINDEXMAP-67] + _ = x[OKEY-68] + _ = x[OSTRUCTKEY-69] + _ = x[OLEN-70] + _ = x[OMAKE-71] + _ = x[OMAKECHAN-72] + _ = x[OMAKEMAP-73] + _ = x[OMAKESLICE-74] + _ = x[OMAKESLICECOPY-75] + _ = x[OMUL-76] + _ = x[ODIV-77] + _ = x[OMOD-78] + _ = x[OLSH-79] + _ = x[ORSH-80] + _ = x[OAND-81] + _ = x[OANDNOT-82] + _ = x[ONEW-83] + _ = x[ONOT-84] + _ = x[OBITNOT-85] + _ = x[OPLUS-86] + _ = x[ONEG-87] + _ = x[OOROR-88] + _ = x[OPANIC-89] + _ = x[OPRINT-90] + _ = x[OPRINTN-91] + _ = x[OPAREN-92] + _ = x[OSEND-93] + _ = x[OSLICE-94] + _ = x[OSLICEARR-95] + _ = x[OSLICESTR-96] + _ = x[OSLICE3-97] + _ = x[OSLICE3ARR-98] + _ = x[OSLICEHEADER-99] + _ = x[ORECOVER-100] + _ = x[ORECOVERFP-101] + _ = x[ORECV-102] + _ = x[ORUNESTR-103] + _ = x[OSELRECV2-104] + _ = x[OIOTA-105] + _ = x[OREAL-106] + _ = x[OIMAG-107] + _ = x[OCOMPLEX-108] + _ = x[OALIGNOF-109] + _ = x[OOFFSETOF-110] + _ = x[OSIZEOF-111] + _ = x[OUNSAFEADD-112] + _ = x[OUNSAFESLICE-113] + _ = x[OMETHEXPR-114] + _ = x[OMETHVALUE-115] + _ = x[OBLOCK-116] + _ = x[OBREAK-117] + _ = x[OCASE-118] + _ = x[OCONTINUE-119] + _ = x[ODEFER-120] + _ = x[OFALL-121] + _ = x[OFOR-122] + _ = x[OFORUNTIL-123] + _ = x[OGOTO-124] + _ = x[OIF-125] + _ = x[OLABEL-126] + _ = x[OGO-127] + _ = x[ORANGE-128] + _ = x[ORETURN-129] + _ = x[OSELECT-130] + _ = x[OSWITCH-131] + _ = x[OTYPESW-132] + _ = x[OFUNCINST-133] + _ = x[OTCHAN-134] + _ = x[OTMAP-135] + _ = x[OTSTRUCT-136] + _ = x[OTINTER-137] + _ = x[OTFUNC-138] + _ = x[OTARRAY-139] + _ = x[OTSLICE-140] + _ = x[OINLCALL-141] + _ = x[OEFACE-142] + _ = x[OITAB-143] + _ = x[OIDATA-144] + _ = x[OSPTR-145] + _ = x[OCFUNC-146] + _ = x[OCHECKNIL-147] + _ = x[OVARDEF-148] + _ = x[OVARKILL-149] + _ = x[OVARLIVE-150] + _ = x[ORESULT-151] + _ = x[OINLMARK-152] + _ = x[OLINKSYMOFFSET-153] + _ = x[OTAILCALL-154] + _ = x[OGETG-155] + _ = x[OGETCALLERPC-156] + _ = x[OGETCALLERSP-157] + _ = x[OEND-158] } -const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESSLICE2ARRPTRASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECOVERFPRECVRUNESTRSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFUNSAFEADDUNSAFESLICEMETHEXPRMETHVALUEBLOCKBREAKCASECONTINUEDEFERFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWFUNCINSTTCHANTMAPTSTRUCTTINTERTFUNCTARRAYTSLICEINLCALLEFACEITABIDATASPTRCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKLINKSYMOFFSETTAILCALLGETGGETCALLERPCGETCALLERSPEND" +const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESSLICE2ARRPTRASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVIDATACONVNOPCOPYDCLDCLFUNCDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECOVERFPRECVRUNESTRSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFUNSAFEADDUNSAFESLICEMETHEXPRMETHVALUEBLOCKBREAKCASECONTINUEDEFERFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWFUNCINSTTCHANTMAPTSTRUCTTINTERTFUNCTARRAYTSLICEINLCALLEFACEITABIDATASPTRCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKLINKSYMOFFSETTAILCALLGETGGETCALLERPCGETCALLERSPEND" -var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 136, 138, 141, 151, 158, 165, 172, 176, 180, 188, 196, 205, 208, 213, 220, 227, 233, 242, 250, 258, 264, 268, 277, 284, 288, 291, 298, 306, 313, 319, 322, 328, 335, 343, 347, 354, 362, 364, 366, 368, 370, 372, 374, 379, 384, 392, 395, 404, 407, 411, 419, 426, 435, 448, 451, 454, 457, 460, 463, 466, 472, 475, 478, 484, 488, 491, 495, 500, 505, 511, 516, 520, 525, 533, 541, 547, 556, 567, 574, 583, 587, 594, 602, 606, 610, 614, 621, 628, 636, 642, 651, 662, 670, 679, 684, 689, 693, 701, 706, 710, 713, 721, 725, 727, 732, 734, 739, 745, 751, 757, 763, 771, 776, 780, 787, 793, 798, 804, 810, 817, 822, 826, 831, 835, 840, 848, 854, 861, 868, 874, 881, 894, 902, 906, 917, 928, 931} +var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 136, 138, 141, 151, 158, 165, 172, 176, 180, 188, 196, 205, 208, 213, 220, 227, 233, 242, 250, 258, 264, 268, 277, 286, 293, 297, 300, 307, 315, 322, 328, 331, 337, 344, 352, 356, 363, 371, 373, 375, 377, 379, 381, 383, 388, 393, 401, 404, 413, 416, 420, 428, 435, 444, 457, 460, 463, 466, 469, 472, 475, 481, 484, 487, 493, 497, 500, 504, 509, 514, 520, 525, 529, 534, 542, 550, 556, 565, 576, 583, 592, 596, 603, 611, 615, 619, 623, 630, 637, 645, 651, 660, 671, 679, 688, 693, 698, 702, 710, 715, 719, 722, 730, 734, 736, 741, 743, 748, 754, 760, 766, 772, 780, 785, 789, 796, 802, 807, 813, 819, 826, 831, 835, 840, 844, 849, 857, 863, 870, 877, 883, 890, 903, 911, 915, 926, 937, 940} func (i Op) String() string { if i >= Op(len(_Op_index)-1) { diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 85538f590d..e308dd7a05 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1461,24 +1461,18 @@ func (subst *subster) convertUsingDictionary(pos src.XPos, v ir.Node, gn ir.Node rt = subst.getDictionaryType(pos, ix) } - // Convert value to an interface type, so the data field is what we want. - if !v.Type().IsInterface() { - v = ir.NewConvExpr(v.Pos(), ir.OCONVIFACE, nil, v) - typed(types.NewInterface(types.LocalPkg, nil), v) + // Figure out what the data field of the interface will be. + var data ir.Node + if v.Type().IsInterface() { + data = ir.NewUnaryExpr(pos, ir.OIDATA, v) + } else { + data = ir.NewConvExpr(pos, ir.OCONVIDATA, nil, v) } - - // At this point, v is an interface type with a data word we want. - // But the type word represents a gcshape type, which we don't want. - // Replace with the instantiated type loaded from the dictionary. - data := ir.NewUnaryExpr(pos, ir.OIDATA, v) typed(types.Types[types.TUNSAFEPTR], data) + + // Build an interface from the type and data parts. var i ir.Node = ir.NewBinaryExpr(pos, ir.OEFACE, rt, data) typed(dst, i) - // TODO: we're throwing away the type word of the original version - // of m here (it would be OITAB(m)), which probably took some - // work to generate. Can we avoid generating it at all? - // (The linker will throw them away if not needed, so it would just - // save toolchain work, not binary size.) return i } diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 875d53b3cc..7eba5fb41e 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -1983,10 +1983,8 @@ var ZeroSize int64 // This information is used in the linker in dead method elimination. func MarkTypeUsedInInterface(t *types.Type, from *obj.LSym) { if t.HasShape() { - // TODO: shape types shouldn't be put in interfaces, so we shouldn't ever get here. - // We don't from ../noder/stencil.go, but we do from ../walk/walk.go when we let - // shape types become the types of interfaces. - //base.Fatalf("shape types have no methods %+v", t) + // Shape types shouldn't be put in interfaces, so we shouldn't ever get here. + base.Fatalf("shape types have no methods %+v", t) } tsym := TypeLinksym(t) // Emit a marker relocation. The linker will know the type is converted diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index b054c73ad8..25a0bfbb3a 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -1873,7 +1873,7 @@ func (w *exportWriter) expr(n ir.Node) { w.op(ir.OEND) } - case ir.OCONV, ir.OCONVIFACE, ir.OCONVNOP, ir.OBYTES2STR, ir.ORUNES2STR, ir.OSTR2BYTES, ir.OSTR2RUNES, ir.ORUNESTR, ir.OSLICE2ARRPTR: + case ir.OCONV, ir.OCONVIFACE, ir.OCONVIDATA, ir.OCONVNOP, ir.OBYTES2STR, ir.ORUNES2STR, ir.OSTR2BYTES, ir.OSTR2RUNES, ir.ORUNESTR, ir.OSLICE2ARRPTR: n := n.(*ir.ConvExpr) if go117ExportTypes { w.op(n.Op()) diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 9bef07b636..b389c7fcb0 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1446,7 +1446,7 @@ func (r *importReader) node() ir.Node { } return n - case ir.OCONV, ir.OCONVIFACE, ir.OCONVNOP, ir.OBYTES2STR, ir.ORUNES2STR, ir.OSTR2BYTES, ir.OSTR2RUNES, ir.ORUNESTR, ir.OSLICE2ARRPTR: + case ir.OCONV, ir.OCONVIFACE, ir.OCONVIDATA, ir.OCONVNOP, ir.OBYTES2STR, ir.ORUNES2STR, ir.OSTR2BYTES, ir.OSTR2RUNES, ir.ORUNESTR, ir.OSLICE2ARRPTR: if !go117ExportTypes && op != ir.OCONV { // unreachable - mapped to OCONV case by exporter goto error diff --git a/src/cmd/compile/internal/walk/assign.go b/src/cmd/compile/internal/walk/assign.go index 6d697a53ae..d4c1aafdc1 100644 --- a/src/cmd/compile/internal/walk/assign.go +++ b/src/cmd/compile/internal/walk/assign.go @@ -429,6 +429,7 @@ func readsMemory(n ir.Node) bool { ir.OBITNOT, ir.OCONV, ir.OCONVIFACE, + ir.OCONVIDATA, ir.OCONVNOP, ir.ODIV, ir.ODOT, diff --git a/src/cmd/compile/internal/walk/convert.go b/src/cmd/compile/internal/walk/convert.go index e659ee59f1..d15575f643 100644 --- a/src/cmd/compile/internal/walk/convert.go +++ b/src/cmd/compile/internal/walk/convert.go @@ -39,14 +39,22 @@ func walkConv(n *ir.ConvExpr, init *ir.Nodes) ir.Node { return typecheck.Conv(mkcall(fn, types.Types[result], init, typecheck.Conv(n.X, types.Types[param])), n.Type()) } -// walkConvInterface walks an OCONVIFACE node. +// walkConvInterface walks an OCONVIFACE or OCONVIDATA node. func walkConvInterface(n *ir.ConvExpr, init *ir.Nodes) ir.Node { + n.X = walkExpr(n.X, init) fromType := n.X.Type() toType := n.Type() - - if !fromType.IsInterface() && !ir.IsBlank(ir.CurFunc.Nname) { // skip unnamed functions (func _()) + if n.Op() == ir.OCONVIDATA { + // Just convert to empty interface, to make it easy. + // The caller throws away the type word. + toType = types.NewInterface(types.LocalPkg, nil) + // Note: don't pass fromType to MarkTypeUsedInInterface because it is likely + // a shape type. The appropriate call to MarkTypeUsedInInterface will come + // when building the dictionary (from which the matching type word will come). + } else if !fromType.IsInterface() && !ir.IsBlank(ir.CurFunc.Nname) { + // skip unnamed functions (func _()) reflectdata.MarkTypeUsedInInterface(fromType, ir.CurFunc.LSym) } diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go index eed6ef86c2..f0d37198d3 100644 --- a/src/cmd/compile/internal/walk/expr.go +++ b/src/cmd/compile/internal/walk/expr.go @@ -206,6 +206,13 @@ func walkExpr1(n ir.Node, init *ir.Nodes) ir.Node { n := n.(*ir.ConvExpr) return walkConvInterface(n, init) + case ir.OCONVIDATA: + n := n.(*ir.ConvExpr) + r := ir.NewUnaryExpr(n.Pos(), ir.OIDATA, walkConvInterface(n, init)) + r.SetType(types.Types[types.TUNSAFEPTR]) + r.SetTypecheck(1) + return r + case ir.OCONV, ir.OCONVNOP: n := n.(*ir.ConvExpr) return walkConv(n, init) diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go index cd2bbcb73b..fe6ae3fda0 100644 --- a/src/cmd/compile/internal/walk/order.go +++ b/src/cmd/compile/internal/walk/order.go @@ -1156,16 +1156,20 @@ func (o *orderState) expr1(n, lhs ir.Node) ir.Node { // concrete type (not interface) argument might need an addressable // temporary to pass to the runtime conversion routine. - case ir.OCONVIFACE: + case ir.OCONVIFACE, ir.OCONVIDATA: n := n.(*ir.ConvExpr) n.X = o.expr(n.X, nil) if n.X.Type().IsInterface() { return n } - if _, _, needsaddr := convFuncName(n.X.Type(), n.Type()); needsaddr || isStaticCompositeLiteral(n.X) { + to := n.Type() + if n.Op() == ir.OCONVIDATA { + to = types.NewInterface(types.LocalPkg, nil) + } + if _, _, needsaddr := convFuncName(n.X.Type(), to); needsaddr || isStaticCompositeLiteral(n.X) { // Need a temp if we need to pass the address to the conversion function. // We also process static composite literal node here, making a named static global - // whose address we can put directly in an interface (see OCONVIFACE case in walk). + // whose address we can put directly in an interface (see OCONVIFACE/OCONVIDATA case in walk). n.X = o.addrTemp(n.X) } return n -- GitLab From 3dc0a0a2c5a7d8959a43265d4f73d7e2e509de5e Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Fri, 23 Jul 2021 17:19:51 -0700 Subject: [PATCH 0530/2500] [dev.typeparams] cmd/compile: get rid of concretify use for bounds. We just need to substitute from the typeparams to the shapes for the dst type of the bound. Removed concretify substituter, not used anymore. Also removed shape2params, not needed anymore. However, since the dst type is now not concrete, this gives more cases where the linker can't find a method. I realized that we need to call MarkUsedIfaceMethod to mark a method as used on a particular interface, else a type's method can be still deadcoded even though MarkTypeUsedInInterface has been called on the concrete type. I added a new version MarkUsedIfaceMethodIndex to fit my use case. Change-Id: Id67b72b350889dd3688b42739c337d5d79a0d1a2 Reviewed-on: https://go-review.googlesource.com/c/go/+/337230 Trust: Dan Scales Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 36 +++++++++---------- .../compile/internal/reflectdata/reflect.go | 12 ++++++- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index e308dd7a05..f1de1152c5 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -855,13 +855,9 @@ type subster struct { ts typecheck.Tsubster info *instInfo // Place to put extra info in the instantiation - // Which type parameter the shape type came from. - shape2param map[*types.Type]*types.Type - // unshapeify maps from shape types to the concrete types they represent. // TODO: remove when we no longer need it. - unshapify typecheck.Tsubster - concretify typecheck.Tsubster + unshapify typecheck.Tsubster // TODO: some sort of map from to index in the // dictionary where a *runtime.itab for the corresponding Date: Sun, 18 Jul 2021 11:10:41 -0700 Subject: [PATCH 0531/2500] [dev.typeparams] transformDot() should set Selection and tc flag for added ODOTs Fixes -G=3 issue with issue44688.go. Change-Id: Ie98c0cbd48683dedd115332043f14c8f3160f46c Reviewed-on: https://go-review.googlesource.com/c/go/+/337029 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Dan Scales --- src/cmd/compile/internal/noder/transform.go | 18 ++++++++++++++++++ test/run.go | 3 +-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index f89ae13237..2fe55a6852 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -591,6 +591,24 @@ func transformDot(n *ir.SelectorExpr, isCall bool) ir.Node { if n.Op() == ir.OXDOT { n = typecheck.AddImplicitDots(n) n.SetOp(ir.ODOT) + + // Set the Selection field and typecheck flag for any new ODOT nodes + // added by AddImplicitDots(), and also transform to ODOTPTR if + // needed. Equivalent to 'n.X = typecheck(n.X, ctxExpr|ctxType)' in + // tcDot. + for n1 := n; n1.X.Op() == ir.ODOT; { + n1 = n1.X.(*ir.SelectorExpr) + if !n1.Implicit() { + break + } + t1 := n1.X.Type() + if t1.IsPtr() && !t1.Elem().IsInterface() { + t1 = t1.Elem() + n1.SetOp(ir.ODOTPTR) + } + typecheck.Lookdot(n1, t1, 0) + n1.SetTypecheck(1) + } } t := n.X.Type() diff --git a/test/run.go b/test/run.go index 5624654fec..1e7fab4359 100644 --- a/test/run.go +++ b/test/run.go @@ -2185,8 +2185,7 @@ var g3Failures = setOf( "typeparam/mdempsky/4.go", // -G=3 can't export functions with labeled breaks in loops "typeparam/mdempsky/13.go", // problem with interface as as a type arg. - "typeparam/cons.go", // causes an unreachable method - "typeparam/issue44688.go", // interface conversion fails due to missing method + "typeparam/cons.go", // causes an unreachable method ) var unifiedFailures = setOf( -- GitLab From b27c7e30dc5d222766057e62c16cb765b636d244 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Sat, 24 Jul 2021 14:11:27 -0700 Subject: [PATCH 0532/2500] [dev.typeparams] cmd/compile: fix HasShape, add dottype test HasShape needs a TINTER case. Add a test for x.(T) in various situations. Needs the fix above. Also remove ONEW unshapify case. It is ok for ONEW to have a shape type, as it will just be passed to mallocgc, or possibly used as a stack object type, both of which are ok. Change-Id: Ibddf8f5c8c254d32cb5ebcaca7dc94b4c00ab893 Reviewed-on: https://go-review.googlesource.com/c/go/+/337231 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 6 -- src/cmd/compile/internal/types/type.go | 8 ++- test/typeparam/dottype.go | 81 +++++++++++++++++++++++ test/typeparam/dottype.out | 8 +++ 4 files changed, 96 insertions(+), 7 deletions(-) create mode 100644 test/typeparam/dottype.go create mode 100644 test/typeparam/dottype.out diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index f1de1152c5..575b879762 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1376,12 +1376,6 @@ func (subst *subster) node(n ir.Node) ir.Node { case ir.ODOTTYPE, ir.ODOTTYPE2: m.SetType(subst.unshapifyTyp(m.Type())) - case ir.ONEW: - // New needs to pass a concrete type to the runtime. - // Or maybe it doesn't? We could use a shape type. - // TODO: need to modify m.X? I don't think any downstream passes use it. - m.SetType(subst.unshapifyTyp(m.Type())) - case ir.OMETHEXPR: se := m.(*ir.SelectorExpr) se.X = ir.TypeNodeAt(se.X.Pos(), subst.unshapifyTyp(se.X.Type())) diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index e6ae0e7bc1..58ac4db95a 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -2189,7 +2189,13 @@ func (t *Type) HasShape1(visited map[*Type]bool) bool { } } } - // TODO: TINTER - check methods? + case TINTER: + for _, f := range t.Methods().Slice() { + if f.Type.HasShape1(visited) { + return true + } + } + return false } return false } diff --git a/test/typeparam/dottype.go b/test/typeparam/dottype.go new file mode 100644 index 0000000000..0131f64202 --- /dev/null +++ b/test/typeparam/dottype.go @@ -0,0 +1,81 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func f[T any](x interface{}) T { + return x.(T) +} +func f2[T any](x interface{}) (T, bool) { + t, ok := x.(T) + return t, ok +} + +type I interface { + foo() +} + +type myint int + +func (myint) foo() { +} + +type myfloat float64 + +func (myfloat) foo() { +} + +func g[T I](x I) T { + return x.(T) +} +func g2[T I](x I) (T, bool) { + t, ok := x.(T) + return t, ok +} + +func h[T any](x interface{}) struct{a, b T} { + return x.(struct{a, b T}) +} + +func k[T any](x interface{}) interface { bar() T } { + return x.(interface{bar() T }) +} + +type mybar int +func (x mybar) bar() int { + return int(x) +} + + +func main() { + var i interface{} = int(3) + var j I = myint(3) + var x interface{} = float64(3) + var y I = myfloat(3) + + println(f[int](i)) + shouldpanic(func() { f[int](x) }) + println(f2[int](i)) + println(f2[int](x)) + + println(g[myint](j)) + shouldpanic(func() { g[myint](y) }) + println(g2[myint](j)) + println(g2[myint](y)) + + println(h[int](struct{a, b int}{3, 5}).a) + + println(k[int](mybar(3)).bar()) +} +func shouldpanic(x func()) { + defer func() { + e := recover() + if e == nil { + panic("didn't panic") + } + }() + x() +} diff --git a/test/typeparam/dottype.out b/test/typeparam/dottype.out new file mode 100644 index 0000000000..058c923a5c --- /dev/null +++ b/test/typeparam/dottype.out @@ -0,0 +1,8 @@ +3 +3 true +0 false +3 +3 true +0 false +3 +3 -- GitLab From bfcb7c4c8adadd6191c3fdacf2b59136b0da5c1c Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 2 Jul 2021 16:59:01 -0700 Subject: [PATCH 0533/2500] [dev.typeparams] cmd/compile: fix unified IR support for //go:nointerface This CL changes fixedbugs/issue30862.go into a "runindir" test so that it can use '-goexperiment fieldtrack' and test that //go:nointerface works with cmd/compile. In particular, this revealed that -G=3 and unified IR did not handle it correctly. This CL also fixes unified IR's support for //go:nointerface and adds a test that checks that //go:nointerface, promoted methods, and generics all interact as expected. Updates #47045. Change-Id: Ib8acff8ae18bf124520d00c98e8915699cba2abd Reviewed-on: https://go-review.googlesource.com/c/go/+/332611 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Matthew Dempsky Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/noder/reader.go | 5 +- test/fixedbugs/issue30862.dir/{ => a}/a.go | 0 test/fixedbugs/issue30862.dir/{ => b}/b.go | 2 +- test/fixedbugs/issue30862.dir/main.go | 2 +- test/fixedbugs/issue30862.go | 4 +- test/run.go | 6 +- test/typeparam/mdempsky/15.go | 69 ++++++++++++++++++++++ 7 files changed, 78 insertions(+), 10 deletions(-) rename test/fixedbugs/issue30862.dir/{ => a}/a.go (100%) rename test/fixedbugs/issue30862.dir/{ => b}/b.go (95%) create mode 100644 test/typeparam/mdempsky/15.go diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 44d1c4f28b..516bf8f1f7 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -750,13 +750,12 @@ func (r *reader) method() *types.Field { name.Func = ir.NewFunc(r.pos()) name.Func.Nname = name - // TODO(mdempsky): Make sure we're handling //go:nointerface - // correctly. I don't think this is exercised within the Go repo. - r.ext.funcExt(name) meth := types.NewField(name.Func.Pos(), sym, typ) meth.Nname = name + meth.SetNointerface(name.Func.Pragma&ir.Nointerface != 0) + return meth } diff --git a/test/fixedbugs/issue30862.dir/a.go b/test/fixedbugs/issue30862.dir/a/a.go similarity index 100% rename from test/fixedbugs/issue30862.dir/a.go rename to test/fixedbugs/issue30862.dir/a/a.go diff --git a/test/fixedbugs/issue30862.dir/b.go b/test/fixedbugs/issue30862.dir/b/b.go similarity index 95% rename from test/fixedbugs/issue30862.dir/b.go rename to test/fixedbugs/issue30862.dir/b/b.go index 3e501bb8dc..230221d503 100644 --- a/test/fixedbugs/issue30862.dir/b.go +++ b/test/fixedbugs/issue30862.dir/b/b.go @@ -4,7 +4,7 @@ package b -import "./a" +import "issue30862.dir/a" type EmbedImported struct { a.NoitfStruct diff --git a/test/fixedbugs/issue30862.dir/main.go b/test/fixedbugs/issue30862.dir/main.go index 80db0e13a8..1489c5a342 100644 --- a/test/fixedbugs/issue30862.dir/main.go +++ b/test/fixedbugs/issue30862.dir/main.go @@ -8,7 +8,7 @@ import ( "fmt" "os" - "./b" + "issue30862.dir/b" ) // Test case for issue 30862. diff --git a/test/fixedbugs/issue30862.go b/test/fixedbugs/issue30862.go index ba122cc3c8..acac71e2cc 100644 --- a/test/fixedbugs/issue30862.go +++ b/test/fixedbugs/issue30862.go @@ -1,4 +1,4 @@ -// rundir +// runindir -goexperiment fieldtrack // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style @@ -9,6 +9,4 @@ // is set when building it, whereas gccgo has field tracking // enabled by default (hence the build tag below). -// +build gccgo - package ignored diff --git a/test/run.go b/test/run.go index 1e7fab4359..2e72d55b76 100644 --- a/test/run.go +++ b/test/run.go @@ -2180,12 +2180,14 @@ var types2Failures32Bit = setOf( var g3Failures = setOf( "writebarrier.go", // correct diagnostics, but different lines (probably irgen's fault) + "fixedbugs/issue30862.go", // -G=3 doesn't handle //go:nointerface + + "typeparam/cons.go", // causes an unreachable method "typeparam/nested.go", // -G=3 doesn't support function-local types with generics "typeparam/mdempsky/4.go", // -G=3 can't export functions with labeled breaks in loops "typeparam/mdempsky/13.go", // problem with interface as as a type arg. - - "typeparam/cons.go", // causes an unreachable method + "typeparam/mdempsky/15.go", // ICE in (*irgen).buildClosure ) var unifiedFailures = setOf( diff --git a/test/typeparam/mdempsky/15.go b/test/typeparam/mdempsky/15.go new file mode 100644 index 0000000000..4899fc75ee --- /dev/null +++ b/test/typeparam/mdempsky/15.go @@ -0,0 +1,69 @@ +// run -goexperiment fieldtrack -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test that generics, promoted methods, and //go:nointerface +// interoperate as expected. + +package main + +import ( + "reflect" +) + +func TypeString[T any]() string { + return reflect.TypeOf(new(T)).Elem().String() +} + +func Test[T, Bad, Good any]() { + switch interface{}(new(T)).(type) { + case Bad: + println("FAIL:", TypeString[T](), "matched", TypeString[Bad]()) + case Good: + // ok + default: + println("FAIL:", TypeString[T](), "did not match", TypeString[Good]()) + } +} + +func TestE[T any]() { Test[T, interface{ EBad() }, interface{ EGood() }]() } +func TestX[T any]() { Test[T, interface{ XBad() }, interface{ XGood() }]() } + +type E struct{} + +//go:nointerface +func (E) EBad() {} +func (E) EGood() {} + +type X[T any] struct{ E } + +//go:nointerface +func (X[T]) XBad() {} +func (X[T]) XGood() {} + +type W struct{ X[int] } + +func main() { + _ = E.EGood + _ = E.EBad + + TestE[E]() + + _ = X[int].EGood + _ = X[int].EBad + _ = X[int].XGood + _ = X[int].XBad + + TestE[X[int]]() + TestX[X[int]]() + + _ = W.EGood + _ = W.EBad + _ = W.XGood + _ = W.XBad + + TestE[W]() + TestX[W]() +} -- GitLab From b93f646125882fc59a6dd5a9c83813dce674bc6b Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 21 Jul 2021 16:36:49 -0700 Subject: [PATCH 0534/2500] [dev.typeparams] cmd/compile/internal/types2: fix a bug in package qualification logic This is a partial port of https://golang.org/cl/330629, containing only the actual bug fix and adjustements to another test file. The respective test case has not been ported yet as it requires some bigger adjustments. For #46905 Change-Id: Ibd20658b8a31855da20cf56e24bcce9560656ca0 Reviewed-on: https://go-review.googlesource.com/c/go/+/336350 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley TryBot-Result: Go Bot --- src/cmd/compile/internal/types2/errors.go | 2 +- src/cmd/compile/internal/types2/testdata/check/issues.src | 4 ++-- test/run.go | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/types2/errors.go b/src/cmd/compile/internal/types2/errors.go index af4ecb2300..8c5e185f6c 100644 --- a/src/cmd/compile/internal/types2/errors.go +++ b/src/cmd/compile/internal/types2/errors.go @@ -111,7 +111,7 @@ func (check *Checker) qualifier(pkg *Package) string { if check.pkgPathMap == nil { check.pkgPathMap = make(map[string]map[string]bool) check.seenPkgMap = make(map[*Package]bool) - check.markImports(pkg) + check.markImports(check.pkg) } // If the same package name was used by multiple packages, display the full path. if len(check.pkgPathMap[pkg.name]) > 1 { diff --git a/src/cmd/compile/internal/types2/testdata/check/issues.src b/src/cmd/compile/internal/types2/testdata/check/issues.src index 60d23b3c3b..7219a560b1 100644 --- a/src/cmd/compile/internal/types2/testdata/check/issues.src +++ b/src/cmd/compile/internal/types2/testdata/check/issues.src @@ -332,7 +332,7 @@ func issue28281g() (... /* ERROR can only use ... with final parameter in list * func issue26234a(f *syn.File) { // The error message below should refer to the actual package name (syntax) // not the local package name (syn). - f.foo /* ERROR f.foo undefined \(type \*syntax.File has no field or method foo\) */ + f.foo /* ERROR f\.foo undefined \(type \*syntax\.File has no field or method foo\) */ } type T struct { @@ -361,7 +361,7 @@ func issue35895() { // Because both t1 and t2 have the same global package name (template), // qualify packages with full path name in this case. - var _ t1.Template = t2 /* ERROR cannot use .* \(value of type "html/template".Template\) as "text/template".Template */ .Template{} + var _ t1.Template = t2 /* ERROR cannot use .* \(value of type .html/template.\.Template\) as .text/template.\.Template */ .Template{} } func issue42989(s uint) { diff --git a/test/run.go b/test/run.go index 2e72d55b76..edf26a5d82 100644 --- a/test/run.go +++ b/test/run.go @@ -2140,7 +2140,6 @@ var types2Failures = setOf( "fixedbugs/issue11610.go", // types2 not run after syntax errors "fixedbugs/issue11614.go", // types2 reports an extra error "fixedbugs/issue14520.go", // missing import path error by types2 - "fixedbugs/issue16133.go", // types2 doesn't use package path for qualified identifiers when package name is ambiguous "fixedbugs/issue16428.go", // types2 reports two instead of one error "fixedbugs/issue17038.go", // types2 doesn't report a follow-on error (pref: types2) "fixedbugs/issue17645.go", // multiple errors on same line -- GitLab From 9e3274bb3d8170efba1c0b42fa09334f1d3f6677 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 21 Jul 2021 16:45:00 -0700 Subject: [PATCH 0535/2500] [dev.typeparams] cmd/compile/internal/types2: import regexp/syntax instead of cmd/compile/internal/syntax This is a straight port of https://golang.org/cl/330431. For #43232 Change-Id: I5954bdff22a524eaa08754947da9b428b27f7d95 Reviewed-on: https://go-review.googlesource.com/c/go/+/336351 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/testdata/check/issues.src | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/types2/testdata/check/issues.src b/src/cmd/compile/internal/types2/testdata/check/issues.src index 7219a560b1..692ed37ef4 100644 --- a/src/cmd/compile/internal/types2/testdata/check/issues.src +++ b/src/cmd/compile/internal/types2/testdata/check/issues.src @@ -6,7 +6,7 @@ package go1_17 // don't permit non-interface elements in interfaces import ( "fmt" - syn "cmd/compile/internal/syntax" + syn "regexp/syntax" t1 "text/template" t2 "html/template" ) @@ -329,10 +329,10 @@ func (... /* ERROR can only use ... with final parameter in list */ TT) f() func issue28281g() (... /* ERROR can only use ... with final parameter in list */ TT) // Issue #26234: Make various field/method lookup errors easier to read by matching cmd/compile's output -func issue26234a(f *syn.File) { +func issue26234a(f *syn.Prog) { // The error message below should refer to the actual package name (syntax) // not the local package name (syn). - f.foo /* ERROR f\.foo undefined \(type \*syntax\.File has no field or method foo\) */ + f.foo /* ERROR f\.foo undefined \(type \*syntax\.Prog has no field or method foo\) */ } type T struct { @@ -357,7 +357,7 @@ func issue35895() { var _ T = 0 // ERROR cannot use 0 \(untyped int constant\) as T // There is only one package with name syntax imported, only use the (global) package name in error messages. - var _ *syn.File = 0 // ERROR cannot use 0 \(untyped int constant\) as \*syntax.File + var _ *syn.Prog = 0 // ERROR cannot use 0 \(untyped int constant\) as \*syntax.Prog // Because both t1 and t2 have the same global package name (template), // qualify packages with full path name in this case. -- GitLab From d6753fd491c101e71f5e86d87b44d396828e2deb Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 23 Jul 2021 10:26:07 -0700 Subject: [PATCH 0536/2500] [dev.typeparams] cmd/compile/internal/types2: implement TypeParam.Constraint Change-Id: I95a96f9dbd199cee3a4be8f42cd64e7f44ba5e5b Reviewed-on: https://go-review.googlesource.com/c/go/+/336989 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley TryBot-Result: Go Bot --- src/cmd/compile/internal/types2/typeparam.go | 32 ++++++++++++-------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index b73b4edf79..0aca227c0a 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -53,20 +53,28 @@ func (t *TypeParam) SetId(id uint64) { t.id = id } -func (t *TypeParam) Bound() *Interface { - // we may not have an interface (error reported elsewhere) - iface, _ := under(t.bound).(*Interface) - if iface == nil { - return &emptyInterface +// Constraint returns the type constraint specified for t. +func (t *TypeParam) Constraint() Type { + // compute the type set if possible (we may not have an interface) + if iface, _ := under(t.bound).(*Interface); iface != nil { + // use the type bound position if we have one + pos := nopos + if n, _ := t.bound.(*Named); n != nil { + pos = n.obj.pos + } + computeTypeSet(t.check, pos, iface) } - // use the type bound position if we have one - pos := nopos - if n, _ := t.bound.(*Named); n != nil { - pos = n.obj.pos + return t.bound +} + +// Bound returns the underlying type of the type parameter's +// constraint. +// Deprecated for external use. Use Constraint instead. +func (t *TypeParam) Bound() *Interface { + if iface, _ := under(t.Constraint()).(*Interface); iface != nil { + return iface } - // TODO(gri) switch this to an unexported method on Checker. - computeTypeSet(t.check, pos, iface) - return iface + return &emptyInterface } func (t *TypeParam) SetBound(bound Type) { -- GitLab From 37d2219960340614f4d7e67c2e620013594e131a Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 26 Jul 2021 12:13:45 -0700 Subject: [PATCH 0537/2500] [dev.typeparams] cmd/compile/internal/types2: embedded type cannot be a (pointer to) a type parameter Change-Id: I5eb03ae349925f0799dd866e207221429bc9fb3c Reviewed-on: https://go-review.googlesource.com/c/go/+/337353 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/struct.go | 4 +++- .../internal/types2/testdata/check/typeparams.go2 | 4 ++-- .../internal/types2/testdata/fixedbugs/issue39938.go2 | 4 ++-- test/typeparam/interfacearg.go | 10 +++++----- test/typeparam/lockable.go | 10 +++++----- 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/cmd/compile/internal/types2/struct.go b/src/cmd/compile/internal/types2/struct.go index f1d82fb50c..f0c27c0150 100644 --- a/src/cmd/compile/internal/types2/struct.go +++ b/src/cmd/compile/internal/types2/struct.go @@ -135,7 +135,7 @@ func (check *Checker) structType(styp *Struct, e *syntax.StructType) { embeddedPos := pos check.later(func() { t, isPtr := deref(embeddedTyp) - switch t := optype(t).(type) { + switch t := under(t).(type) { case *Basic: if t == Typ[Invalid] { // error was reported before @@ -147,6 +147,8 @@ func (check *Checker) structType(styp *Struct, e *syntax.StructType) { } case *Pointer: check.error(embeddedPos, "embedded field type cannot be a pointer") + case *TypeParam: + check.error(embeddedPos, "embedded field type cannot be a (pointer to a) type parameter") case *Interface: if isPtr { check.error(embeddedPos, "embedded field type cannot be a pointer to an interface") diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 index 2755a539e5..54efd1485b 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 @@ -79,11 +79,11 @@ var _ *int = new[int]() func _[T any](map[T /* ERROR invalid map key type T \(missing comparable constraint\) */]int) // w/o constraint we don't know if T is comparable -func f1[T1 any](struct{T1}) int +func f1[T1 any](struct{T1 /* ERROR cannot be a .* type parameter */ }) int var _ = f1[int](struct{T1}{}) type T1 = int -func f2[t1 any](struct{t1; x float32}) int +func f2[t1 any](struct{t1 /* ERROR cannot be a .* type parameter */ ; x float32}) int var _ = f2[t1](struct{t1; x float32}{}) type t1 = int diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39938.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39938.go2 index 76e7e369ca..0da6e103fd 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39938.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39938.go2 @@ -8,8 +8,8 @@ package p type E0[P any] P type E1[P any] *P -type E2[P any] struct{ P } -type E3[P any] struct{ *P } +type E2[P any] struct{ _ P } +type E3[P any] struct{ _ *P } type T0 /* ERROR illegal cycle */ struct { _ E0[T0] diff --git a/test/typeparam/interfacearg.go b/test/typeparam/interfacearg.go index e2d85e3647..1d19499318 100644 --- a/test/typeparam/interfacearg.go +++ b/test/typeparam/interfacearg.go @@ -9,14 +9,14 @@ package main type I interface{} type _S[T any] struct { - *T + x *T } // F is a non-generic function, but has a type _S[I] which is instantiated from a // generic type. Test that _S[I] is successfully exported. func F() { v := _S[I]{} - if v.T != nil { + if v.x != nil { panic(v) } } @@ -33,9 +33,9 @@ func _F1[T interface{ M() }](t T) { } func F2() { - _F1(&S1{}) - _F1(S2{}) - _F1(&S2{}) + _F1(&S1{}) + _F1(S2{}) + _F1(&S2{}) } func main() { diff --git a/test/typeparam/lockable.go b/test/typeparam/lockable.go index 3a03652cd8..9372c76b4d 100644 --- a/test/typeparam/lockable.go +++ b/test/typeparam/lockable.go @@ -11,7 +11,7 @@ import "sync" // A Lockable is a value that may be safely simultaneously accessed // from multiple goroutines via the Get and Set methods. type Lockable[T any] struct { - T + x T mu sync.Mutex } @@ -19,18 +19,18 @@ type Lockable[T any] struct { func (l *Lockable[T]) get() T { l.mu.Lock() defer l.mu.Unlock() - return l.T + return l.x } // set sets the value in a Lockable. func (l *Lockable[T]) set(v T) { l.mu.Lock() defer l.mu.Unlock() - l.T = v + l.x = v } func main() { - sl := Lockable[string]{T: "a"} + sl := Lockable[string]{x: "a"} if got := sl.get(); got != "a" { panic(got) } @@ -39,7 +39,7 @@ func main() { panic(got) } - il := Lockable[int]{T: 1} + il := Lockable[int]{x: 1} if got := il.get(); got != 1 { panic(got) } -- GitLab From 3cd15e02ed26d86556cb59ff509a1f5a08bca29e Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Fri, 30 Apr 2021 18:09:01 -0400 Subject: [PATCH 0538/2500] [dev.cmdgo] cmd: pull in x/mod on the dev.cmdgo branch This change changes the requirement on golang.org/x/mod to require the top of the dev.cmdgo branch of that repository. This allows the code on this branch to use the changes on the branch on that repo for parsing go.work files. It also vendors in those changes using go mod vendor. Generated using: go get -d golang.org/x/mod@dev.cmdgo go mod tidy go mod vendor For #45713 Change-Id: I7a20835937c13f90d17c0f39d96b435daec89fba Reviewed-on: https://go-review.googlesource.com/c/go/+/334933 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 +- .../vendor/golang.org/x/mod/modfile/rule.go | 250 ++++++++++++------ .../vendor/golang.org/x/mod/modfile/work.go | 234 ++++++++++++++++ src/cmd/vendor/modules.txt | 2 +- 5 files changed, 407 insertions(+), 85 deletions(-) create mode 100644 src/cmd/vendor/golang.org/x/mod/modfile/work.go diff --git a/src/cmd/go.mod b/src/cmd/go.mod index cd03968eed..21d7d8b75a 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -7,7 +7,7 @@ require ( github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 // indirect golang.org/x/arch v0.0.0-20210502124803-cbf565b21d1e golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e // indirect - golang.org/x/mod v0.4.3-0.20210608190319-0f08993efd8a + golang.org/x/mod v0.4.3-0.20210723200715-e41a6a4f3b61 golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 // indirect golang.org/x/term v0.0.0-20210503060354-a79de5458b56 golang.org/x/tools v0.1.2-0.20210519160823-49064d2332f9 diff --git a/src/cmd/go.sum b/src/cmd/go.sum index d728acaec9..529b152b77 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -13,8 +13,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e h1:8foAy0aoO5GkqCvAEJ4VC4P3zksTg4X4aJCDpZzmgQI= golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.3-0.20210608190319-0f08993efd8a h1:e8qnjKz4EE6OjRki9wTadWSIogINvq10sMcuBRORxMY= -golang.org/x/mod v0.4.3-0.20210608190319-0f08993efd8a/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.4.3-0.20210723200715-e41a6a4f3b61 h1:gQY3CVezomIImcWCpxp6Mhj+fXCOZ+gD8/88326LVqw= +golang.org/x/mod v0.4.3-0.20210723200715-e41a6a4f3b61/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= diff --git a/src/cmd/vendor/golang.org/x/mod/modfile/rule.go b/src/cmd/vendor/golang.org/x/mod/modfile/rule.go index 78f83fa714..d6a2d3879e 100644 --- a/src/cmd/vendor/golang.org/x/mod/modfile/rule.go +++ b/src/cmd/vendor/golang.org/x/mod/modfile/rule.go @@ -423,68 +423,12 @@ func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, a } case "replace": - arrow := 2 - if len(args) >= 2 && args[1] == "=>" { - arrow = 1 - } - if len(args) < arrow+2 || len(args) > arrow+3 || args[arrow] != "=>" { - errorf("usage: %s module/path [v1.2.3] => other/module v1.4\n\t or %s module/path [v1.2.3] => ../local/directory", verb, verb) - return - } - s, err := parseString(&args[0]) - if err != nil { - errorf("invalid quoted string: %v", err) - return - } - pathMajor, err := modulePathMajor(s) - if err != nil { - wrapModPathError(s, err) - return - } - var v string - if arrow == 2 { - v, err = parseVersion(verb, s, &args[1], fix) - if err != nil { - wrapError(err) - return - } - if err := module.CheckPathMajor(v, pathMajor); err != nil { - wrapModPathError(s, err) - return - } - } - ns, err := parseString(&args[arrow+1]) - if err != nil { - errorf("invalid quoted string: %v", err) + replace, wrappederr := parseReplace(f.Syntax.Name, line, verb, args, fix) + if wrappederr != nil { + *errs = append(*errs, *wrappederr) return } - nv := "" - if len(args) == arrow+2 { - if !IsDirectoryPath(ns) { - errorf("replacement module without version must be directory path (rooted or starting with ./ or ../)") - return - } - if filepath.Separator == '/' && strings.Contains(ns, `\`) { - errorf("replacement directory appears to be Windows path (on a non-windows system)") - return - } - } - if len(args) == arrow+3 { - nv, err = parseVersion(verb, ns, &args[arrow+2], fix) - if err != nil { - wrapError(err) - return - } - if IsDirectoryPath(ns) { - errorf("replacement module directory path %q cannot have version", ns) - return - } - } - f.Replace = append(f.Replace, &Replace{ - Old: module.Version{Path: s, Version: v}, - New: module.Version{Path: ns, Version: nv}, - Syntax: line, - }) + f.Replace = append(f.Replace, replace) case "retract": rationale := parseDirectiveComment(block, line) @@ -515,6 +459,83 @@ func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, a } } +func parseReplace(filename string, line *Line, verb string, args []string, fix VersionFixer) (*Replace, *Error) { + wrapModPathError := func(modPath string, err error) *Error { + return &Error{ + Filename: filename, + Pos: line.Start, + ModPath: modPath, + Verb: verb, + Err: err, + } + } + wrapError := func(err error) *Error { + return &Error{ + Filename: filename, + Pos: line.Start, + Err: err, + } + } + errorf := func(format string, args ...interface{}) *Error { + return wrapError(fmt.Errorf(format, args...)) + } + + arrow := 2 + if len(args) >= 2 && args[1] == "=>" { + arrow = 1 + } + if len(args) < arrow+2 || len(args) > arrow+3 || args[arrow] != "=>" { + return nil, errorf("usage: %s module/path [v1.2.3] => other/module v1.4\n\t or %s module/path [v1.2.3] => ../local/directory", verb, verb) + } + s, err := parseString(&args[0]) + if err != nil { + return nil, errorf("invalid quoted string: %v", err) + } + pathMajor, err := modulePathMajor(s) + if err != nil { + return nil, wrapModPathError(s, err) + + } + var v string + if arrow == 2 { + v, err = parseVersion(verb, s, &args[1], fix) + if err != nil { + return nil, wrapError(err) + } + if err := module.CheckPathMajor(v, pathMajor); err != nil { + return nil, wrapModPathError(s, err) + } + } + ns, err := parseString(&args[arrow+1]) + if err != nil { + return nil, errorf("invalid quoted string: %v", err) + } + nv := "" + if len(args) == arrow+2 { + if !IsDirectoryPath(ns) { + return nil, errorf("replacement module without version must be directory path (rooted or starting with ./ or ../)") + } + if filepath.Separator == '/' && strings.Contains(ns, `\`) { + return nil, errorf("replacement directory appears to be Windows path (on a non-windows system)") + } + } + if len(args) == arrow+3 { + nv, err = parseVersion(verb, ns, &args[arrow+2], fix) + if err != nil { + return nil, wrapError(err) + } + if IsDirectoryPath(ns) { + return nil, errorf("replacement module directory path %q cannot have version", ns) + + } + } + return &Replace{ + Old: module.Version{Path: s, Version: v}, + New: module.Version{Path: ns, Version: nv}, + Syntax: line, + }, nil +} + // fixRetract applies fix to each retract directive in f, appending any errors // to errs. // @@ -556,6 +577,63 @@ func (f *File) fixRetract(fix VersionFixer, errs *ErrorList) { } } +func (f *WorkFile) add(errs *ErrorList, line *Line, verb string, args []string, fix VersionFixer) { + wrapError := func(err error) { + *errs = append(*errs, Error{ + Filename: f.Syntax.Name, + Pos: line.Start, + Err: err, + }) + } + errorf := func(format string, args ...interface{}) { + wrapError(fmt.Errorf(format, args...)) + } + + switch verb { + default: + errorf("unknown directive: %s", verb) + + case "go": + if f.Go != nil { + errorf("repeated go statement") + return + } + if len(args) != 1 { + errorf("go directive expects exactly one argument") + return + } else if !GoVersionRE.MatchString(args[0]) { + errorf("invalid go version '%s': must match format 1.23", args[0]) + return + } + + f.Go = &Go{Syntax: line} + f.Go.Version = args[0] + + case "directory": + if len(args) != 1 { + errorf("usage: %s local/dir", verb) + return + } + s, err := parseString(&args[0]) + if err != nil { + errorf("invalid quoted string: %v", err) + return + } + f.Directory = append(f.Directory, &Directory{ + Path: s, + Syntax: line, + }) + + case "replace": + replace, wrappederr := parseReplace(f.Syntax.Name, line, verb, args, fix) + if wrappederr != nil { + *errs = append(*errs, *wrappederr) + return + } + f.Replace = append(f.Replace, replace) + } +} + // IsDirectoryPath reports whether the given path should be interpreted // as a directory path. Just like on the go command line, relative paths // and rooted paths are directory paths; the rest are module paths. @@ -1165,6 +1243,10 @@ func (f *File) DropExclude(path, vers string) error { } func (f *File) AddReplace(oldPath, oldVers, newPath, newVers string) error { + return addReplace(f.Syntax, &f.Replace, oldPath, oldVers, newPath, newVers) +} + +func addReplace(syntax *FileSyntax, replace *[]*Replace, oldPath, oldVers, newPath, newVers string) error { need := true old := module.Version{Path: oldPath, Version: oldVers} new := module.Version{Path: newPath, Version: newVers} @@ -1178,12 +1260,12 @@ func (f *File) AddReplace(oldPath, oldVers, newPath, newVers string) error { } var hint *Line - for _, r := range f.Replace { + for _, r := range *replace { if r.Old.Path == oldPath && (oldVers == "" || r.Old.Version == oldVers) { if need { // Found replacement for old; update to use new. r.New = new - f.Syntax.updateLine(r.Syntax, tokens...) + syntax.updateLine(r.Syntax, tokens...) need = false continue } @@ -1196,7 +1278,7 @@ func (f *File) AddReplace(oldPath, oldVers, newPath, newVers string) error { } } if need { - f.Replace = append(f.Replace, &Replace{Old: old, New: new, Syntax: f.Syntax.addLine(hint, tokens...)}) + *replace = append(*replace, &Replace{Old: old, New: new, Syntax: syntax.addLine(hint, tokens...)}) } return nil } @@ -1282,30 +1364,36 @@ func (f *File) SortBlocks() { // retract directives are not de-duplicated since comments are // meaningful, and versions may be retracted multiple times. func (f *File) removeDups() { + removeDups(f.Syntax, &f.Exclude, &f.Replace) +} + +func removeDups(syntax *FileSyntax, exclude *[]*Exclude, replace *[]*Replace) { kill := make(map[*Line]bool) // Remove duplicate excludes. - haveExclude := make(map[module.Version]bool) - for _, x := range f.Exclude { - if haveExclude[x.Mod] { - kill[x.Syntax] = true - continue + if exclude != nil { + haveExclude := make(map[module.Version]bool) + for _, x := range *exclude { + if haveExclude[x.Mod] { + kill[x.Syntax] = true + continue + } + haveExclude[x.Mod] = true } - haveExclude[x.Mod] = true - } - var excl []*Exclude - for _, x := range f.Exclude { - if !kill[x.Syntax] { - excl = append(excl, x) + var excl []*Exclude + for _, x := range *exclude { + if !kill[x.Syntax] { + excl = append(excl, x) + } } + *exclude = excl } - f.Exclude = excl // Remove duplicate replacements. // Later replacements take priority over earlier ones. haveReplace := make(map[module.Version]bool) - for i := len(f.Replace) - 1; i >= 0; i-- { - x := f.Replace[i] + for i := len(*replace) - 1; i >= 0; i-- { + x := (*replace)[i] if haveReplace[x.Old] { kill[x.Syntax] = true continue @@ -1313,18 +1401,18 @@ func (f *File) removeDups() { haveReplace[x.Old] = true } var repl []*Replace - for _, x := range f.Replace { + for _, x := range *replace { if !kill[x.Syntax] { repl = append(repl, x) } } - f.Replace = repl + *replace = repl // Duplicate require and retract directives are not removed. // Drop killed statements from the syntax tree. var stmts []Expr - for _, stmt := range f.Syntax.Stmt { + for _, stmt := range syntax.Stmt { switch stmt := stmt.(type) { case *Line: if kill[stmt] { @@ -1344,7 +1432,7 @@ func (f *File) removeDups() { } stmts = append(stmts, stmt) } - f.Syntax.Stmt = stmts + syntax.Stmt = stmts } // lineLess returns whether li should be sorted before lj. It sorts diff --git a/src/cmd/vendor/golang.org/x/mod/modfile/work.go b/src/cmd/vendor/golang.org/x/mod/modfile/work.go new file mode 100644 index 0000000000..b1fabff51b --- /dev/null +++ b/src/cmd/vendor/golang.org/x/mod/modfile/work.go @@ -0,0 +1,234 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package modfile + +import ( + "fmt" + "sort" + "strings" +) + +// A WorkFile is the parsed, interpreted form of a go.work file. +type WorkFile struct { + Go *Go + Directory []*Directory + Replace []*Replace + + Syntax *FileSyntax +} + +// A Directory is a single directory statement. +type Directory struct { + Path string // Directory path of module. + ModulePath string // Module path in the comment. + Syntax *Line +} + +// ParseWork parses and returns a go.work file. +// +// file is the name of the file, used in positions and errors. +// +// data is the content of the file. +// +// fix is an optional function that canonicalizes module versions. +// If fix is nil, all module versions must be canonical (module.CanonicalVersion +// must return the same string). +func ParseWork(file string, data []byte, fix VersionFixer) (*WorkFile, error) { + fs, err := parse(file, data) + if err != nil { + return nil, err + } + f := &WorkFile{ + Syntax: fs, + } + var errs ErrorList + + for _, x := range fs.Stmt { + switch x := x.(type) { + case *Line: + f.add(&errs, x, x.Token[0], x.Token[1:], fix) + + case *LineBlock: + if len(x.Token) > 1 { + errs = append(errs, Error{ + Filename: file, + Pos: x.Start, + Err: fmt.Errorf("unknown block type: %s", strings.Join(x.Token, " ")), + }) + continue + } + switch x.Token[0] { + default: + errs = append(errs, Error{ + Filename: file, + Pos: x.Start, + Err: fmt.Errorf("unknown block type: %s", strings.Join(x.Token, " ")), + }) + continue + case "directory", "replace": + for _, l := range x.Line { + f.add(&errs, l, x.Token[0], l.Token, fix) + } + } + } + } + + if len(errs) > 0 { + return nil, errs + } + return f, nil +} + +// Cleanup cleans up the file f after any edit operations. +// To avoid quadratic behavior, modifications like DropRequire +// clear the entry but do not remove it from the slice. +// Cleanup cleans out all the cleared entries. +func (f *WorkFile) Cleanup() { + w := 0 + for _, r := range f.Directory { + if r.Path != "" { + f.Directory[w] = r + w++ + } + } + f.Directory = f.Directory[:w] + + w = 0 + for _, r := range f.Replace { + if r.Old.Path != "" { + f.Replace[w] = r + w++ + } + } + f.Replace = f.Replace[:w] + + f.Syntax.Cleanup() +} + +func (f *WorkFile) AddGoStmt(version string) error { + if !GoVersionRE.MatchString(version) { + return fmt.Errorf("invalid language version string %q", version) + } + if f.Go == nil { + stmt := &Line{Token: []string{"go", version}} + f.Go = &Go{ + Version: version, + Syntax: stmt, + } + // Find the first non-comment-only block that's and add + // the go statement before it. That will keep file comments at the top. + i := 0 + for i = 0; i < len(f.Syntax.Stmt); i++ { + if _, ok := f.Syntax.Stmt[i].(*CommentBlock); !ok { + break + } + } + f.Syntax.Stmt = append(append(f.Syntax.Stmt[:i:i], stmt), f.Syntax.Stmt[i:]...) + } else { + f.Go.Version = version + f.Syntax.updateLine(f.Go.Syntax, "go", version) + } + return nil +} + +func (f *WorkFile) AddDirectory(diskPath, modulePath string) error { + need := true + for _, d := range f.Directory { + if d.Path == diskPath { + if need { + d.ModulePath = modulePath + f.Syntax.updateLine(d.Syntax, "directory", AutoQuote(diskPath)) + need = false + } else { + d.Syntax.markRemoved() + *d = Directory{} + } + } + } + + if need { + f.AddNewDirectory(diskPath, modulePath) + } + return nil +} + +func (f *WorkFile) AddNewDirectory(diskPath, modulePath string) { + line := f.Syntax.addLine(nil, "directory", AutoQuote(diskPath)) + f.Directory = append(f.Directory, &Directory{Path: diskPath, ModulePath: modulePath, Syntax: line}) +} + +func (f *WorkFile) SetDirectory(dirs []*Directory) { + need := make(map[string]string) + for _, d := range dirs { + need[d.Path] = d.ModulePath + } + + for _, d := range f.Directory { + if modulePath, ok := need[d.Path]; ok { + d.ModulePath = modulePath + } else { + d.Syntax.markRemoved() + *d = Directory{} + } + } + + // TODO(#45713): Add module path to comment. + + for diskPath, modulePath := range need { + f.AddNewDirectory(diskPath, modulePath) + } + f.SortBlocks() +} + +func (f *WorkFile) DropDirectory(path string) error { + for _, d := range f.Directory { + if d.Path == path { + d.Syntax.markRemoved() + *d = Directory{} + } + } + return nil +} + +func (f *WorkFile) AddReplace(oldPath, oldVers, newPath, newVers string) error { + return addReplace(f.Syntax, &f.Replace, oldPath, oldVers, newPath, newVers) +} + +func (f *WorkFile) DropReplace(oldPath, oldVers string) error { + for _, r := range f.Replace { + if r.Old.Path == oldPath && r.Old.Version == oldVers { + r.Syntax.markRemoved() + *r = Replace{} + } + } + return nil +} + +func (f *WorkFile) SortBlocks() { + f.removeDups() // otherwise sorting is unsafe + + for _, stmt := range f.Syntax.Stmt { + block, ok := stmt.(*LineBlock) + if !ok { + continue + } + sort.SliceStable(block.Line, func(i, j int) bool { + return lineLess(block.Line[i], block.Line[j]) + }) + } +} + +// removeDups removes duplicate replace directives. +// +// Later replace directives take priority. +// +// require directives are not de-duplicated. That's left up to higher-level +// logic (MVS). +// +// retract directives are not de-duplicated since comments are +// meaningful, and versions may be retracted multiple times. +func (f *WorkFile) removeDups() { + removeDups(f.Syntax, nil, &f.Replace) +} diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 34dbdaf5dd..beceef5392 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -28,7 +28,7 @@ golang.org/x/arch/x86/x86asm ## explicit; go 1.17 golang.org/x/crypto/ed25519 golang.org/x/crypto/ed25519/internal/edwards25519 -# golang.org/x/mod v0.4.3-0.20210608190319-0f08993efd8a +# golang.org/x/mod v0.4.3-0.20210723200715-e41a6a4f3b61 ## explicit; go 1.17 golang.org/x/mod/internal/lazyregexp golang.org/x/mod/modfile -- GitLab From 7ce257147fe0ab3413c8e36909c2408c833efdb8 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Tue, 8 Jun 2021 17:07:10 -0400 Subject: [PATCH 0539/2500] [dev.cmdgo] cmd/go: add the workspace mode This change adds the outline of the implementation of the workspace mode. The go command will now locate go.work files, and read them to determine which modules are in the workspace. It will then put those modules in the root of the workspace when building the build list. It supports building, running, testing, and listing in workspaces. There are still many TODOs for undone work and other changes to fix certain cases. Some of these undone parts include: replaces and go.work.sum files, as well as go mod {test,why,verify}, excludes in workspaces, updating work files to include module names in comments and setting the GOWORK variable. For #45713 Change-Id: I72716af7a300a2896087fc8a79c04e951d248278 Reviewed-on: https://go-review.googlesource.com/c/go/+/334934 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/alldocs.go | 8 + src/cmd/go/internal/base/flag.go | 7 + src/cmd/go/internal/cfg/cfg.go | 6 +- src/cmd/go/internal/envcmd/env.go | 1 + src/cmd/go/internal/list/list.go | 3 + src/cmd/go/internal/modcmd/download.go | 3 + src/cmd/go/internal/modcmd/graph.go | 3 + src/cmd/go/internal/modcmd/verify.go | 3 + src/cmd/go/internal/modcmd/why.go | 2 + src/cmd/go/internal/modload/init.go | 224 +++++++++++++++++++------ src/cmd/go/internal/run/run.go | 3 + src/cmd/go/internal/test/test.go | 2 + src/cmd/go/internal/test/testflag.go | 1 + src/cmd/go/internal/work/build.go | 10 ++ src/cmd/go/testdata/script/work.txt | 71 ++++++++ 15 files changed, 296 insertions(+), 51 deletions(-) create mode 100644 src/cmd/go/testdata/script/work.txt diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 90eb3e2a00..e7c2e6b51b 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -167,6 +167,14 @@ // directory, but it is not accessed. When -modfile is specified, an // alternate go.sum file is also used: its path is derived from the // -modfile flag by trimming the ".mod" extension and appending ".sum". +// -workfile file +// in module aware mode, use the given go.work file as a workspace file. +// By default or when -workfile is "auto", the go command searches for a +// file named go.work in the current directory and then containing directories +// until one is found. If a valid go.work file is found, the modules +// specified will collectively be used as the main modules. If -workfile +// is "off", or a go.work file is not found in "auto" mode, workspace +// mode is disabled. // -overlay file // read a JSON config file that provides an overlay for build operations. // The file is a JSON struct with a single field, named 'Replace', that diff --git a/src/cmd/go/internal/base/flag.go b/src/cmd/go/internal/base/flag.go index 677f819682..2262e2e992 100644 --- a/src/cmd/go/internal/base/flag.go +++ b/src/cmd/go/internal/base/flag.go @@ -62,6 +62,13 @@ func AddModFlag(flags *flag.FlagSet) { flags.Var(explicitStringFlag{value: &cfg.BuildMod, explicit: &cfg.BuildModExplicit}, "mod", "") } +// AddWorkfileFlag adds the workfile flag to the flag set. It enables workspace +// mode for commands that support it by resetting the cfg.WorkFile variable +// to "" (equivalent to auto) rather than off. +func AddWorkfileFlag(flags *flag.FlagSet) { + flags.Var(explicitStringFlag{value: &cfg.WorkFile, explicit: &cfg.WorkFileExplicit}, "workfile", "") +} + // AddModCommonFlags adds the module-related flags common to build commands // and 'go mod' subcommands. func AddModCommonFlags(flags *flag.FlagSet) { diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go index 57a3c1ff6f..da616ee1dd 100644 --- a/src/cmd/go/internal/cfg/cfg.go +++ b/src/cmd/go/internal/cfg/cfg.go @@ -47,8 +47,10 @@ var ( BuildWork bool // -work flag BuildX bool // -x flag - ModCacheRW bool // -modcacherw flag - ModFile string // -modfile flag + ModCacheRW bool // -modcacherw flag + ModFile string // -modfile flag + WorkFile string // -workfile flag + WorkFileExplicit bool // whether -workfile was set explicitly CmdName string // "build", "install", "list", "mod tidy", etc. diff --git a/src/cmd/go/internal/envcmd/env.go b/src/cmd/go/internal/envcmd/env.go index 1553d26391..f68090f21f 100644 --- a/src/cmd/go/internal/envcmd/env.go +++ b/src/cmd/go/internal/envcmd/env.go @@ -145,6 +145,7 @@ func findEnv(env []cfg.EnvVar, name string) string { // ExtraEnvVars returns environment variables that should not leak into child processes. func ExtraEnvVars() []cfg.EnvVar { gomod := "" + modload.Init() if modload.HasModRoot() { gomod = filepath.Join(modload.ModRoot(), "go.mod") } else if modload.Enabled() { diff --git a/src/cmd/go/internal/list/list.go b/src/cmd/go/internal/list/list.go index 7cb9ec6d94..04630dc341 100644 --- a/src/cmd/go/internal/list/list.go +++ b/src/cmd/go/internal/list/list.go @@ -316,6 +316,7 @@ For more about modules, see https://golang.org/ref/mod. func init() { CmdList.Run = runList // break init cycle work.AddBuildFlags(CmdList, work.DefaultBuildFlags) + base.AddWorkfileFlag(&CmdList.Flag) } var ( @@ -336,6 +337,8 @@ var ( var nl = []byte{'\n'} func runList(ctx context.Context, cmd *base.Command, args []string) { + modload.InitWorkfile() + if *listFmt != "" && *listJson == true { base.Fatalf("go list -f cannot be used with -json") } diff --git a/src/cmd/go/internal/modcmd/download.go b/src/cmd/go/internal/modcmd/download.go index 3c88a4b900..6a99cb01e1 100644 --- a/src/cmd/go/internal/modcmd/download.go +++ b/src/cmd/go/internal/modcmd/download.go @@ -66,6 +66,7 @@ func init() { // TODO(jayconrod): https://golang.org/issue/35849 Apply -x to other 'go mod' commands. cmdDownload.Flag.BoolVar(&cfg.BuildX, "x", false, "") base.AddModCommonFlags(&cmdDownload.Flag) + base.AddWorkfileFlag(&cmdDownload.Flag) } type moduleJSON struct { @@ -81,6 +82,8 @@ type moduleJSON struct { } func runDownload(ctx context.Context, cmd *base.Command, args []string) { + modload.InitWorkfile() + // Check whether modules are enabled and whether we're in a module. modload.ForceUseModules = true if !modload.HasModRoot() && len(args) == 0 { diff --git a/src/cmd/go/internal/modcmd/graph.go b/src/cmd/go/internal/modcmd/graph.go index 903bd9970f..5ef1d4ed04 100644 --- a/src/cmd/go/internal/modcmd/graph.go +++ b/src/cmd/go/internal/modcmd/graph.go @@ -42,9 +42,12 @@ var ( func init() { cmdGraph.Flag.Var(&graphGo, "go", "") base.AddModCommonFlags(&cmdGraph.Flag) + base.AddWorkfileFlag(&cmdGraph.Flag) } func runGraph(ctx context.Context, cmd *base.Command, args []string) { + modload.InitWorkfile() + if len(args) > 0 { base.Fatalf("go mod graph: graph takes no arguments") } diff --git a/src/cmd/go/internal/modcmd/verify.go b/src/cmd/go/internal/modcmd/verify.go index 5a6eca32cf..14c4d76bc3 100644 --- a/src/cmd/go/internal/modcmd/verify.go +++ b/src/cmd/go/internal/modcmd/verify.go @@ -39,9 +39,12 @@ See https://golang.org/ref/mod#go-mod-verify for more about 'go mod verify'. func init() { base.AddModCommonFlags(&cmdVerify.Flag) + base.AddWorkfileFlag(&cmdVerify.Flag) } func runVerify(ctx context.Context, cmd *base.Command, args []string) { + modload.InitWorkfile() + if len(args) != 0 { // NOTE(rsc): Could take a module pattern. base.Fatalf("go mod verify: verify takes no arguments") diff --git a/src/cmd/go/internal/modcmd/why.go b/src/cmd/go/internal/modcmd/why.go index 3b14b27c8c..eef5fa5ae8 100644 --- a/src/cmd/go/internal/modcmd/why.go +++ b/src/cmd/go/internal/modcmd/why.go @@ -61,9 +61,11 @@ var ( func init() { cmdWhy.Run = runWhy // break init cycle base.AddModCommonFlags(&cmdWhy.Flag) + base.AddWorkfileFlag(&cmdWhy.Flag) } func runWhy(ctx context.Context, cmd *base.Command, args []string) { + modload.InitWorkfile() modload.ForceUseModules = true modload.RootMode = modload.NeedRoot diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 33f9163038..f211e1767c 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -53,10 +53,6 @@ func TODOWorkspaces(s string) error { var ( initialized bool - // The directory containing go.work file. Set if in a go.work file is found - // and the go command is operating in workspace mode. - workRoot string - // These are primarily used to initialize the MainModules, and should be // eventually superceded by them but are still used in cases where the module // roots are required but MainModules hasn't been initialized yet. Set to @@ -66,6 +62,12 @@ var ( gopath string ) +// Variable set in InitWorkfile +var ( + // Set to the path to the go.work file, or "" if workspace mode is disabled. + workFilePath string +) + type MainModuleSet struct { // versions are the module.Version values of each of the main modules. // For each of them, the Path fields are ordinary module paths and the Version @@ -187,6 +189,20 @@ func BinDir() string { return filepath.Join(gopath, "bin") } +// InitWorkfile initializes the workFilePath variable for commands that +// operate in workspace mode. It should not be called by other commands, +// for example 'go mod tidy', that don't operate in workspace mode. +func InitWorkfile() { + switch cfg.WorkFile { + case "off": + workFilePath = "" + case "", "auto": + workFilePath = findWorkspaceFile(base.Cwd()) + default: + workFilePath = cfg.WorkFile + } +} + // Init determines whether module mode is enabled, locates the root of the // current module (if any), sets environment variables for Git subprocesses, and // configures the cfg, codehost, load, modfetch, and search packages for use @@ -259,6 +275,8 @@ func Init() { base.Fatalf("go: -modfile cannot be used with commands that ignore the current module") } modRoots = nil + } else if inWorkspaceMode() { + // We're in workspace mode. } else { modRoots = findModuleRoots(base.Cwd()) if modRoots == nil { @@ -293,6 +311,7 @@ func Init() { // We're in module mode. Set any global variables that need to be set. cfg.ModulesEnabled = true setDefaultBuildMod() + _ = TODOWorkspaces("ensure that buildmod is readonly") list := filepath.SplitList(cfg.BuildContext.GOPATH) if len(list) == 0 || list[0] == "" { base.Fatalf("missing $GOPATH") @@ -302,7 +321,17 @@ func Init() { base.Fatalf("$GOPATH/go.mod exists but should not") } - if modRoots == nil { + if inWorkspaceMode() { + + _ = TODOWorkspaces("go.work.sum, and also allow modfetch to fall back to individual go.sums") + _ = TODOWorkspaces("replaces") + var err error + modRoots, err = loadWorkFile(workFilePath) + if err != nil { + base.Fatalf("reading go.work: %v", err) + } + // TODO(matloob) should workRoot just be workFile? + } else if modRoots == nil { // We're in module mode, but not inside a module. // // Commands like 'go build', 'go run', 'go list' have no go.mod file to @@ -388,12 +417,24 @@ func ModRoot() string { if !HasModRoot() { die() } + if inWorkspaceMode() { + panic("ModRoot called in workspace mode") + } + // This is similar to MustGetSingleMainModule but we can't call that + // because MainModules may not yet exist when ModRoot is called. if len(modRoots) != 1 { - panic(TODOWorkspaces("need to handle multiple modroots here")) + panic("not in workspace mode but there are multiple ModRoots") } return modRoots[0] } +func inWorkspaceMode() bool { + if !initialized { + panic("inWorkspaceMode called before modload.Init called") + } + return workFilePath != "" +} + // HasModRoot reports whether a main module is present. // HasModRoot may return false even if Enabled returns true: for example, 'get' // does not require a main module. @@ -451,6 +492,31 @@ func (goModDirtyError) Error() string { var errGoModDirty error = goModDirtyError{} +func loadWorkFile(path string) (modRoots []string, err error) { + workDir := filepath.Dir(path) + workData, err := lockedfile.Read(path) + if err != nil { + return nil, err + } + wf, err := modfile.ParseWork(path, workData, nil) + if err != nil { + return nil, err + } + seen := map[string]bool{} + for _, d := range wf.Directory { + modRoot := d.Path + if !filepath.IsAbs(modRoot) { + modRoot = filepath.Join(workDir, modRoot) + } + if seen[modRoot] { + return nil, fmt.Errorf("path %s appears multiple times in workspace", modRoot) + } + seen[modRoot] = true + modRoots = append(modRoots, modRoot) + } + return modRoots, nil +} + // LoadModFile sets Target and, if there is a main module, parses the initial // build list from its go.mod file. // @@ -498,40 +564,62 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { return requirements, false } - gomod := ModFilePath() - data, err := lockedfile.Read(gomod) - if err != nil { - base.Fatalf("go: %v", err) - } + var modFiles []*modfile.File + var mainModules []module.Version + for _, modroot := range modRoots { + gomod := modFilePath(modroot) + var data []byte + var err error + if gomodActual, ok := fsys.OverlayPath(gomod); ok { + // Don't lock go.mod if it's part of the overlay. + // On Plan 9, locking requires chmod, and we don't want to modify any file + // in the overlay. See #44700. + data, err = os.ReadFile(gomodActual) + } else { + data, err = lockedfile.Read(gomodActual) + } + if err != nil { + base.Fatalf("go: %v", err) + } - var fixed bool - f, err := modfile.Parse(gomod, data, fixVersion(ctx, &fixed)) - if err != nil { - // Errors returned by modfile.Parse begin with file:line. - base.Fatalf("go: errors parsing go.mod:\n%s\n", err) - } - if f.Module == nil { - // No module declaration. Must add module path. - base.Fatalf("go: no module declaration in go.mod. To specify the module path:\n\tgo mod edit -module=example.com/mod") - } + var fixed bool + f, err := modfile.Parse(gomod, data, fixVersion(ctx, &fixed)) + if err != nil { + // Errors returned by modfile.Parse begin with file:line. + base.Fatalf("go: errors parsing go.mod:\n%s\n", err) + } + if f.Module == nil { + // No module declaration. Must add module path. + base.Fatalf("go: no module declaration in go.mod. To specify the module path:\n\tgo mod edit -module=example.com/mod") + } - // For now, this code assumes there's a single main module, because there's - // no way to specify multiple main modules yet. TODO(#45713): update this - // in a later CL. - modFile = f - mainModule := f.Module.Mod - MainModules = makeMainModules([]module.Version{mainModule}, modRoots) - index = indexModFile(data, f, mainModule, fixed) + modFile = f // TODO(golang.org/cl/327329): remove the global modFile variable and replace it with multiple modfiles + modFiles = append(modFiles, f) + mainModule := f.Module.Mod + mainModules = append(mainModules, mainModule) + index = indexModFile(data, f, mainModule, fixed) - if err := module.CheckImportPath(f.Module.Mod.Path); err != nil { - if pathErr, ok := err.(*module.InvalidPathError); ok { - pathErr.Kind = "module" + if err := module.CheckImportPath(f.Module.Mod.Path); err != nil { + if pathErr, ok := err.(*module.InvalidPathError); ok { + pathErr.Kind = "module" + } + base.Fatalf("go: %v", err) } - base.Fatalf("go: %v", err) } + MainModules = makeMainModules(mainModules, modRoots) setDefaultBuildMod() // possibly enable automatic vendoring - rs = requirementsFromModFile(ctx) + rs = requirementsFromModFiles(ctx, modFiles) + + if inWorkspaceMode() { + // We don't need to do anything for vendor or update the mod file so + // return early. + + _ = TODOWorkspaces("don't worry about commits for now, but eventually will want to update go.work files") + return rs, false + } + + mainModule := MainModules.mustGetSingleMainModule() if cfg.BuildMod == "vendor" { readVendorList() @@ -549,6 +637,7 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { // Go 1.11 through 1.16 have eager requirements, but the latest Go // version uses lazy requirements instead — so we need to cnvert the // requirements to be lazy. + var err error rs, err = convertDepth(ctx, rs, lazy) if err != nil { base.Fatalf("go: %v", err) @@ -613,7 +702,7 @@ func CreateModFile(ctx context.Context, modPath string) { base.Fatalf("go: %v", err) } - commitRequirements(ctx, modFileGoVersion(), requirementsFromModFile(ctx)) + commitRequirements(ctx, modFileGoVersion(), requirementsFromModFiles(ctx, []*modfile.File{modFile})) // Suggest running 'go mod tidy' unless the project is empty. Even if we // imported all the correct requirements above, we're probably missing @@ -737,29 +826,36 @@ func makeMainModules(ms []module.Version, rootDirs []string) *MainModuleSet { return mainModules } -// requirementsFromModFile returns the set of non-excluded requirements from +// requirementsFromModFiles returns the set of non-excluded requirements from // the global modFile. -func requirementsFromModFile(ctx context.Context) *Requirements { - roots := make([]module.Version, 0, len(modFile.Require)) +func requirementsFromModFiles(ctx context.Context, modFiles []*modfile.File) *Requirements { + rootCap := 0 + for i := range modFiles { + rootCap += len(modFiles[i].Require) + } + roots := make([]module.Version, 0, rootCap) mPathCount := make(map[string]int) for _, m := range MainModules.Versions() { mPathCount[m.Path] = 1 } direct := map[string]bool{} - for _, r := range modFile.Require { - if index != nil && index.exclude[r.Mod] { - if cfg.BuildMod == "mod" { - fmt.Fprintf(os.Stderr, "go: dropping requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version) - } else { - fmt.Fprintf(os.Stderr, "go: ignoring requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version) + for _, modFile := range modFiles { + // TODO(golang.org/cl/327329): Use the correct index here. + for _, r := range modFile.Require { + if index != nil && index.exclude[r.Mod] { + if cfg.BuildMod == "mod" { + fmt.Fprintf(os.Stderr, "go: dropping requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version) + } else { + fmt.Fprintf(os.Stderr, "go: ignoring requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version) + } + continue } - continue - } - roots = append(roots, r.Mod) - mPathCount[r.Mod.Path]++ - if !r.Indirect { - direct[r.Mod.Path] = true + roots = append(roots, r.Mod) + mPathCount[r.Mod.Path]++ + if !r.Indirect { + direct[r.Mod.Path] = true + } } } module.Sort(roots) @@ -786,6 +882,11 @@ func requirementsFromModFile(ctx context.Context) *Requirements { // wasn't provided. setDefaultBuildMod may be called multiple times. func setDefaultBuildMod() { if cfg.BuildModExplicit { + if inWorkspaceMode() { + base.Fatalf("go: -mod can't be set explicitly when in workspace mode." + + "\n\tRemove the -mod flag to use the default readonly value," + + "\n\tor set -workfile=off to disable workspace mode.") + } // Don't override an explicit '-mod=' argument. return } @@ -944,6 +1045,31 @@ func findModuleRoots(dir string) (roots []string) { return nil } +func findWorkspaceFile(dir string) (root string) { + if dir == "" { + panic("dir not set") + } + dir = filepath.Clean(dir) + + // Look for enclosing go.mod. + for { + f := filepath.Join(dir, "go.work") + if fi, err := fsys.Stat(f); err == nil && !fi.IsDir() { + return f + } + d := filepath.Dir(dir) + if d == dir { + break + } + if d == cfg.GOROOT { + _ = TODOWorkspaces("Address how go.work files interact with GOROOT") + return "" // As a special case, don't cross GOROOT to find a go.work file. + } + dir = d + } + return "" +} + func findAltConfig(dir string) (root, name string) { if dir == "" { panic("dir not set") diff --git a/src/cmd/go/internal/run/run.go b/src/cmd/go/internal/run/run.go index 784f7162df..7d9e2930ab 100644 --- a/src/cmd/go/internal/run/run.go +++ b/src/cmd/go/internal/run/run.go @@ -65,6 +65,7 @@ func init() { CmdRun.Run = runRun // break init loop work.AddBuildFlags(CmdRun, work.DefaultBuildFlags) + base.AddWorkfileFlag(&CmdRun.Flag) CmdRun.Flag.Var((*base.StringsFlag)(&work.ExecCmd), "exec", "") } @@ -73,6 +74,8 @@ func printStderr(args ...interface{}) (int, error) { } func runRun(ctx context.Context, cmd *base.Command, args []string) { + modload.InitWorkfile() + if shouldUseOutsideModuleMode(args) { // Set global module flags for 'go run cmd@version'. // This must be done before modload.Init, but we need to call work.BuildInit diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 59ea1ef544..5fcea18caa 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -29,6 +29,7 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/load" "cmd/go/internal/lockedfile" + "cmd/go/internal/modload" "cmd/go/internal/search" "cmd/go/internal/str" "cmd/go/internal/trace" @@ -577,6 +578,7 @@ var defaultVetFlags = []string{ } func runTest(ctx context.Context, cmd *base.Command, args []string) { + modload.InitWorkfile() pkgArgs, testArgs = testFlags(args) if cfg.DebugTrace != "" { diff --git a/src/cmd/go/internal/test/testflag.go b/src/cmd/go/internal/test/testflag.go index 08f1efa2c0..f129346d0d 100644 --- a/src/cmd/go/internal/test/testflag.go +++ b/src/cmd/go/internal/test/testflag.go @@ -29,6 +29,7 @@ import ( func init() { work.AddBuildFlags(CmdTest, work.OmitVFlag) + base.AddWorkfileFlag(&CmdTest.Flag) cf := CmdTest.Flag cf.BoolVar(&testC, "c", false, "") diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go index 0ed2389cd5..c51dd398c2 100644 --- a/src/cmd/go/internal/work/build.go +++ b/src/cmd/go/internal/work/build.go @@ -121,6 +121,14 @@ and test commands: directory, but it is not accessed. When -modfile is specified, an alternate go.sum file is also used: its path is derived from the -modfile flag by trimming the ".mod" extension and appending ".sum". + -workfile file + in module aware mode, use the given go.work file as a workspace file. + By default or when -workfile is "auto", the go command searches for a + file named go.work in the current directory and then containing directories + until one is found. If a valid go.work file is found, the modules + specified will collectively be used as the main modules. If -workfile + is "off", or a go.work file is not found in "auto" mode, workspace + mode is disabled. -overlay file read a JSON config file that provides an overlay for build operations. The file is a JSON struct with a single field, named 'Replace', that @@ -201,6 +209,7 @@ func init() { AddBuildFlags(CmdBuild, DefaultBuildFlags) AddBuildFlags(CmdInstall, DefaultBuildFlags) + base.AddWorkfileFlag(&CmdBuild.Flag) } // Note that flags consulted by other parts of the code @@ -364,6 +373,7 @@ var pkgsFilter = func(pkgs []*load.Package) []*load.Package { return pkgs } var runtimeVersion = runtime.Version() func runBuild(ctx context.Context, cmd *base.Command, args []string) { + modload.InitWorkfile() BuildInit() var b Builder b.Init() diff --git a/src/cmd/go/testdata/script/work.txt b/src/cmd/go/testdata/script/work.txt new file mode 100644 index 0000000000..f2b51ca629 --- /dev/null +++ b/src/cmd/go/testdata/script/work.txt @@ -0,0 +1,71 @@ +go run example.com/b +stdout 'Hello from module A' + +# And try from a different directory +cd c +go run example.com/b +stdout 'Hello from module A' +cd $GOPATH/src + +go list all # all includes both modules +stdout 'example.com/a' +stdout 'example.com/b' + +# -mod can't be set in workspace mode, even to readonly +! go list -mod=readonly all +stderr '^go: -mod can''t be set explicitly' +go list -mod=readonly -workfile=off all + +# Test that duplicates in the directory list return an error +cp go.work go.work.backup +cp go.work.dup go.work +! go run example.com/b +stderr 'reading go.work: path .* appears multiple times in workspace' +cp go.work.backup go.work + +-- go.work.dup -- +go 1.17 + +directory ( + a + b + ../src/a +) +-- go.work -- +go 1.17 + +directory ( + ./a + ./b +) + +-- a/go.mod -- + +module example.com/a + +-- a/a.go -- +package a + +import "fmt" + +func HelloFromA() { + fmt.Println("Hello from module A") +} + +-- b/go.mod -- + +module example.com/b + +-- b/main.go -- +package main + +import "example.com/a" + +func main() { + a.HelloFromA() +} + +-- c/README -- +Create this directory so we can cd to +it and make sure paths are interpreted +relative to the go.work, not the cwd. -- GitLab From cb14e673ec62f09f1216c3d40b03a460785a931e Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 26 Jul 2021 10:54:57 -0400 Subject: [PATCH 0540/2500] [dev.typeparams] runtime: don't keep stack uintptr across potential stack move Currently, deferproc stores the caller SP as a uintptr in a local variable across a call to newdefer, but newdefer could grow the stack and invalidate this saved SP, causing deferproc to store a stale SP in the defer record. This would lead to us later failing to match that defer to its calling frame, and we wouldn't run the defer at the right time (or possibly at all). It turns out this isn't crashing horribly right now only because the compiler happens to only materialize the result of getcallersp when this variable is used, *after* the call to newdefer. But this is clearly on thin ice, so this CL moves the getcallersp() to the place where we actually need the result. Change-Id: Iae8ab226e03e4482f16acfb965885f0bd83a13b0 Reviewed-on: https://go-review.googlesource.com/c/go/+/337649 Trust: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/panic.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/runtime/panic.go b/src/runtime/panic.go index abf76537b0..85d39b9250 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -234,9 +234,6 @@ func deferproc(fn *funcval) { // TODO: Make deferproc just take a func(). throw("defer on system stack") } - sp := getcallersp() - callerpc := getcallerpc() - d := newdefer() if d._panic != nil { throw("deferproc: d.panic != nil after newdefer") @@ -244,8 +241,11 @@ func deferproc(fn *funcval) { // TODO: Make deferproc just take a func(). d.link = gp._defer gp._defer = d d.fn = fn - d.pc = callerpc - d.sp = sp + d.pc = getcallerpc() + // We must not be preempted between calling getcallersp and + // storing it to d.sp because getcallersp's result is a + // uintptr stack pointer. + d.sp = getcallersp() // deferproc returns 0 normally. // a deferred func that stops a panic -- GitLab From 5d8f90f90405e9faa9c5425627024d2cfa67faa3 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Mon, 26 Jul 2021 19:37:10 -0700 Subject: [PATCH 0541/2500] [dev.typeparams] cmd/compile: don't need to unshapify append calls append is fine using shape types. Change-Id: Iae829b9b5929d4dc7aa74bed57da13d4f6d746be Reviewed-on: https://go-review.googlesource.com/c/go/+/337669 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 575b879762..e482281a3c 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1291,13 +1291,6 @@ func (subst *subster) node(n ir.Node) ir.Node { default: base.FatalfAt(call.Pos(), "Unexpected builtin op") } - switch m.Op() { - case ir.OAPPEND: - // Append needs to pass a concrete type to the runtime. - // TODO: there's no way to record a dictionary-loaded type for walk to use here - m.SetType(subst.unshapifyTyp(m.Type())) - } - } else { // This is the case of a function value that was a // type parameter (implied to be a function via a -- GitLab From c751e2e6ba30fc319c93b9cfe207dc7d1b48c3fb Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 26 Jul 2021 14:50:57 -0700 Subject: [PATCH 0542/2500] [dev.typeparams] cmd/compile/internal/types2: use comparable bit rather than ==() method This removes the special "==" methods from comparable interfaces in favor of a "comparable" flag in TypeSets indicating that the interface is or embeds comparable. Fixes various related implementation inaccuracies. While at it, fix setup of the predeclared error and comparable interface types by associating their respective type name objects with them. For #47411. Change-Id: I409f880c8c8f2fe345621401267e4aaabd17124d Reviewed-on: https://go-review.googlesource.com/c/go/+/337354 Trust: Robert Griesemer Reviewed-by: Robert Findley --- .../compile/internal/types2/instantiate.go | 16 ++++++++--- src/cmd/compile/internal/types2/interface.go | 2 +- src/cmd/compile/internal/types2/lookup.go | 10 +------ src/cmd/compile/internal/types2/predicates.go | 17 +----------- .../compile/internal/types2/sizeof_test.go | 2 +- .../internal/types2/testdata/check/issues.go2 | 6 ++--- .../types2/testdata/fixedbugs/issue47411.go2 | 26 ++++++++++++++++++ src/cmd/compile/internal/types2/typeset.go | 27 +++++++++++++++---- src/cmd/compile/internal/types2/universe.go | 12 +++------ 9 files changed, 71 insertions(+), 47 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go2 diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index cc96375027..db398c6563 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -146,6 +146,17 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap // the parameterized type. iface = check.subst(pos, iface, smap).(*Interface) + // if iface is comparable, targ must be comparable + // TODO(gri) the error messages needs to be better, here + if iface.IsComparable() && !Comparable(targ) { + if tpar := asTypeParam(targ); tpar != nil && tpar.Bound().typeSet().IsTop() { + check.softErrorf(pos, "%s has no constraints", targ) + return false + } + check.softErrorf(pos, "%s does not satisfy comparable", targ) + return false + } + // targ must implement iface (methods) // - check only if we have methods if iface.NumMethods() > 0 { @@ -161,10 +172,7 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap // (print warning for now) // Old warning: // check.softErrorf(pos, "%s does not satisfy %s (warning: name not updated) = %s (missing method %s)", targ, tpar.bound, iface, m) - if m.name == "==" { - // We don't want to report "missing method ==". - check.softErrorf(pos, "%s does not satisfy comparable", targ) - } else if wrong != nil { + if wrong != nil { // TODO(gri) This can still report uninstantiated types which makes the error message // more difficult to read then necessary. check.softErrorf(pos, diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index c344f8ed01..cf8ec1a5e2 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -107,7 +107,7 @@ func (t *Interface) Method(i int) *Func { return t.typeSet().Method(i) } // Empty reports whether t is the empty interface. func (t *Interface) Empty() bool { return t.typeSet().IsTop() } -// IsComparable reports whether interface t is or embeds the predeclared interface "comparable". +// IsComparable reports whether each type in interface t's type set is comparable. func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() } // IsConstraint reports whether interface t is not just a method set. diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index 91be14bde3..ecf6926c0a 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -308,11 +308,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, for _, m := range T.typeSet().methods { _, f := ityp.typeSet().LookupMethod(m.pkg, m.name) - if f == nil { - // if m is the magic method == we're ok (interfaces are comparable) - if m.name == "==" || !static { - continue - } + if f == nil && static { return m, f } @@ -360,10 +356,6 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // we must have a method (not a field of matching function type) f, _ := obj.(*Func) if f == nil { - // if m is the magic method == and V is comparable, we're ok - if m.name == "==" && Comparable(V) { - continue - } return m, nil } diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index e862c0fca8..f2215b36cb 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -96,19 +96,6 @@ func comparable(T Type, seen map[Type]bool) bool { } seen[T] = true - // If T is a type parameter not constrained by any type - // (i.e., it's operational type is the top type), - // T is comparable if it has the == method. Otherwise, - // the operational type "wins". For instance - // - // interface{ comparable; type []byte } - // - // is not comparable because []byte is not comparable. - // TODO(gri) this code is not 100% correct (see comment for TypeSet.IsComparable) - if t := asTypeParam(T); t != nil && optype(t) == theTop { - return t.Bound().IsComparable() - } - switch t := under(T).(type) { case *Basic: // assume invalid types to be comparable @@ -126,9 +113,7 @@ func comparable(T Type, seen map[Type]bool) bool { case *Array: return comparable(t.elem, seen) case *TypeParam: - return t.underIs(func(t Type) bool { - return comparable(t, seen) - }) + return t.Bound().IsComparable() } return false } diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go index f7f191f629..22ef369683 100644 --- a/src/cmd/compile/internal/types2/sizeof_test.go +++ b/src/cmd/compile/internal/types2/sizeof_test.go @@ -49,7 +49,7 @@ func TestSizeof(t *testing.T) { // Misc {Scope{}, 60, 104}, {Package{}, 40, 80}, - {TypeSet{}, 20, 40}, + {TypeSet{}, 24, 48}, } for _, test := range tests { diff --git a/src/cmd/compile/internal/types2/testdata/check/issues.go2 b/src/cmd/compile/internal/types2/testdata/check/issues.go2 index 32c4320d27..1ede383ebe 100644 --- a/src/cmd/compile/internal/types2/testdata/check/issues.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/issues.go2 @@ -58,7 +58,7 @@ func _() { type T1[P interface{~uint}] struct{} func _[P any]() { - _ = T1[P /* ERROR P has no type constraints */ ]{} + _ = T1[P /* ERROR P has no constraints */ ]{} } // This is the original (simplified) program causing the same issue. @@ -74,8 +74,8 @@ func (u T2[U]) Add1() U { return u.s + 1 } -func NewT2[U any]() T2[U /* ERROR U has no type constraints */ ] { - return T2[U /* ERROR U has no type constraints */ ]{} +func NewT2[U any]() T2[U /* ERROR U has no constraints */ ] { + return T2[U /* ERROR U has no constraints */ ]{} } func _() { diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go2 new file mode 100644 index 0000000000..72968f9d43 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go2 @@ -0,0 +1,26 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func f[_ comparable]() +func g[_ interface{interface{comparable; ~int|~string}}]() + +func _[P comparable, + Q interface{ comparable; ~int|~string }, + R any, // not comparable + S interface{ comparable; ~func() }, // not comparable +]() { + _ = f[int] + _ = f[P] + _ = f[Q] + _ = f[func( /* ERROR does not satisfy comparable */ )] + _ = f[R /* ERROR R has no constraints */ ] + + _ = g[int] + _ = g[P /* ERROR P has no type constraints */ ] + _ = g[Q] + _ = g[func( /* ERROR does not satisfy comparable */ )] + _ = g[R /* ERROR R has no constraints */ ] +} diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index 8e6af8e65c..cc28625070 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -16,22 +16,30 @@ import ( // A TypeSet represents the type set of an interface. type TypeSet struct { + comparable bool // if set, the interface is or embeds comparable // TODO(gri) consider using a set for the methods for faster lookup methods []*Func // all methods of the interface; sorted by unique ID types Type // typically a *Union; nil means no type restrictions } // IsTop reports whether type set s is the top type set (corresponding to the empty interface). -func (s *TypeSet) IsTop() bool { return len(s.methods) == 0 && s.types == nil } +func (s *TypeSet) IsTop() bool { return !s.comparable && len(s.methods) == 0 && s.types == nil } // IsMethodSet reports whether the type set s is described by a single set of methods. -func (s *TypeSet) IsMethodSet() bool { return s.types == nil && !s.IsComparable() } +func (s *TypeSet) IsMethodSet() bool { return !s.comparable && s.types == nil } // IsComparable reports whether each type in the set is comparable. -// TODO(gri) this is not correct - there may be s.types values containing non-comparable types func (s *TypeSet) IsComparable() bool { - _, m := s.LookupMethod(nil, "==") - return m != nil + if s.types == nil { + return s.comparable + } + tcomparable := s.underIs(func(u Type) bool { + return Comparable(u) + }) + if !s.comparable { + return tcomparable + } + return s.comparable && tcomparable } // NumMethods returns the number of methods available. @@ -54,6 +62,12 @@ func (s *TypeSet) String() string { var buf bytes.Buffer buf.WriteByte('{') + if s.comparable { + buf.WriteString(" comparable") + if len(s.methods) > 0 || s.types != nil { + buf.WriteByte(';') + } + } for i, m := range s.methods { if i > 0 { buf.WriteByte(';') @@ -205,6 +219,9 @@ func computeTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *TypeSet { switch t := under(typ).(type) { case *Interface: tset := computeTypeSet(check, pos, t) + if tset.comparable { + ityp.tset.comparable = true + } for _, m := range tset.methods { addMethod(pos, m, false) // use embedding position pos rather than m.pos } diff --git a/src/cmd/compile/internal/types2/universe.go b/src/cmd/compile/internal/types2/universe.go index 0f711a6b68..a3dd4bd0d6 100644 --- a/src/cmd/compile/internal/types2/universe.go +++ b/src/cmd/compile/internal/types2/universe.go @@ -88,23 +88,19 @@ func defPredeclaredTypes() { res := NewVar(nopos, nil, "", Typ[String]) sig := NewSignature(nil, nil, NewTuple(res), false) err := NewFunc(nopos, nil, "Error", sig) - ityp := NewInterfaceType([]*Func{err}, nil) + ityp := &Interface{obj, []*Func{err}, nil, nil, true, nil} computeTypeSet(nil, nopos, ityp) // prevent races due to lazy computation of tset typ := NewNamed(obj, ityp, nil) sig.recv = NewVar(nopos, nil, "", typ) def(obj) } - // type comparable interface{ ==() } + // type comparable interface{ /* type set marked comparable */ } { obj := NewTypeName(nopos, nil, "comparable", nil) obj.setColor(black) - sig := NewSignature(nil, nil, nil, false) - eql := NewFunc(nopos, nil, "==", sig) - ityp := NewInterfaceType([]*Func{eql}, nil) - computeTypeSet(nil, nopos, ityp) // prevent races due to lazy computation of tset - typ := NewNamed(obj, ityp, nil) - sig.recv = NewVar(nopos, nil, "", typ) + ityp := &Interface{obj, nil, nil, nil, true, &TypeSet{true, nil, nil}} + NewNamed(obj, ityp, nil) def(obj) } } -- GitLab From f05f5ceffa6edec89436a825176eefdd1fe828e5 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Tue, 8 Jun 2021 17:07:10 -0400 Subject: [PATCH 0543/2500] [dev.cmdgo] cmd/go: fold index and modFile into MainModules For #45713 Change-Id: I5e4b0ae16dcc9ba5ac30683370a3a1d3416e24f2 Reviewed-on: https://go-review.googlesource.com/c/go/+/334935 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/modload/import.go | 114 +++++++++++++------------ src/cmd/go/internal/modload/init.go | 95 ++++++++++++++++----- src/cmd/go/internal/modload/modfile.go | 85 +++++++++++------- src/cmd/go/internal/modload/query.go | 84 ++++++++++++------ src/cmd/go/internal/modload/vendor.go | 3 +- 5 files changed, 243 insertions(+), 138 deletions(-) diff --git a/src/cmd/go/internal/modload/import.go b/src/cmd/go/internal/modload/import.go index 7b5305e4bb..b6b9bf65b8 100644 --- a/src/cmd/go/internal/modload/import.go +++ b/src/cmd/go/internal/modload/import.go @@ -414,69 +414,71 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M func queryImport(ctx context.Context, path string, rs *Requirements) (module.Version, error) { // To avoid spurious remote fetches, try the latest replacement for each // module (golang.org/issue/26241). - if index != nil { - var mods []module.Version - for mp, mv := range index.highestReplaced { - if !maybeInModule(path, mp) { - continue - } - if mv == "" { - // The only replacement is a wildcard that doesn't specify a version, so - // synthesize a pseudo-version with an appropriate major version and a - // timestamp below any real timestamp. That way, if the main module is - // used from within some other module, the user will be able to upgrade - // the requirement to any real version they choose. - if _, pathMajor, ok := module.SplitPathVersion(mp); ok && len(pathMajor) > 0 { - mv = module.ZeroPseudoVersion(pathMajor[1:]) - } else { - mv = module.ZeroPseudoVersion("v0") + var mods []module.Version + for _, v := range MainModules.Versions() { + if index := MainModules.Index(v); index != nil { + for mp, mv := range index.highestReplaced { + if !maybeInModule(path, mp) { + continue } + if mv == "" { + // The only replacement is a wildcard that doesn't specify a version, so + // synthesize a pseudo-version with an appropriate major version and a + // timestamp below any real timestamp. That way, if the main module is + // used from within some other module, the user will be able to upgrade + // the requirement to any real version they choose. + if _, pathMajor, ok := module.SplitPathVersion(mp); ok && len(pathMajor) > 0 { + mv = module.ZeroPseudoVersion(pathMajor[1:]) + } else { + mv = module.ZeroPseudoVersion("v0") + } + } + mg, err := rs.Graph(ctx) + if err != nil { + return module.Version{}, err + } + if cmpVersion(mg.Selected(mp), mv) >= 0 { + // We can't resolve the import by adding mp@mv to the module graph, + // because the selected version of mp is already at least mv. + continue + } + mods = append(mods, module.Version{Path: mp, Version: mv}) } - mg, err := rs.Graph(ctx) - if err != nil { - return module.Version{}, err - } - if cmpVersion(mg.Selected(mp), mv) >= 0 { - // We can't resolve the import by adding mp@mv to the module graph, - // because the selected version of mp is already at least mv. - continue - } - mods = append(mods, module.Version{Path: mp, Version: mv}) } + } - // Every module path in mods is a prefix of the import path. - // As in QueryPattern, prefer the longest prefix that satisfies the import. - sort.Slice(mods, func(i, j int) bool { - return len(mods[i].Path) > len(mods[j].Path) - }) - for _, m := range mods { - needSum := true - root, isLocal, err := fetch(ctx, m, needSum) - if err != nil { - if sumErr := (*sumMissingError)(nil); errors.As(err, &sumErr) { - return module.Version{}, &ImportMissingSumError{importPath: path} - } - return module.Version{}, err - } - if _, ok, err := dirInModule(path, m.Path, root, isLocal); err != nil { - return m, err - } else if ok { - if cfg.BuildMod == "readonly" { - return module.Version{}, &ImportMissingError{Path: path, replaced: m} - } - return m, nil + // Every module path in mods is a prefix of the import path. + // As in QueryPattern, prefer the longest prefix that satisfies the import. + sort.Slice(mods, func(i, j int) bool { + return len(mods[i].Path) > len(mods[j].Path) + }) + for _, m := range mods { + needSum := true + root, isLocal, err := fetch(ctx, m, needSum) + if err != nil { + if sumErr := (*sumMissingError)(nil); errors.As(err, &sumErr) { + return module.Version{}, &ImportMissingSumError{importPath: path} } + return module.Version{}, err } - if len(mods) > 0 && module.CheckPath(path) != nil { - // The package path is not valid to fetch remotely, - // so it can only exist in a replaced module, - // and we know from the above loop that it is not. - return module.Version{}, &PackageNotInModuleError{ - Mod: mods[0], - Query: "latest", - Pattern: path, - Replacement: Replacement(mods[0]), + if _, ok, err := dirInModule(path, m.Path, root, isLocal); err != nil { + return m, err + } else if ok { + if cfg.BuildMod == "readonly" { + return module.Version{}, &ImportMissingError{Path: path, replaced: m} } + return m, nil + } + } + if len(mods) > 0 && module.CheckPath(path) != nil { + // The package path is not valid to fetch remotely, + // so it can only exist in a replaced module, + // and we know from the above loop that it is not. + return module.Version{}, &PackageNotInModuleError{ + Mod: mods[0], + Query: "latest", + Pattern: path, + Replacement: Replacement(mods[0]), } } diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index f211e1767c..607054d1eb 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -17,6 +17,7 @@ import ( "path/filepath" "strconv" "strings" + "sync" "cmd/go/internal/base" "cmd/go/internal/cfg" @@ -85,6 +86,11 @@ type MainModuleSet struct { // inGorootSrc caches whether modRoot is within GOROOT/src. // The "std" module is special within GOROOT/src, but not otherwise. inGorootSrc map[module.Version]bool + + modFiles map[module.Version]*modfile.File + + indexMu sync.Mutex + indices map[module.Version]*modFileIndex } func (mms *MainModuleSet) PathPrefix(m module.Version) string { @@ -141,6 +147,36 @@ func (mms *MainModuleSet) mustGetSingleMainModule() module.Version { return mms.versions[0] } +func (mms *MainModuleSet) GetSingleIndexOrNil() *modFileIndex { + if mms == nil { + return nil + } + if len(mms.versions) == 0 { + return nil + } + if len(mms.versions) != 1 { + _ = TODOWorkspaces("Check if we're in workspace mode before returning the below error.") + panic("internal error: mustGetSingleMainModule called in workspace mode") + } + return mms.indices[mms.versions[0]] +} + +func (mms *MainModuleSet) Index(m module.Version) *modFileIndex { + mms.indexMu.Lock() + defer mms.indexMu.Unlock() + return mms.indices[m] +} + +func (mms *MainModuleSet) SetIndex(m module.Version, index *modFileIndex) { + mms.indexMu.Lock() + defer mms.indexMu.Unlock() + mms.indices[m] = index +} + +func (mms *MainModuleSet) ModFile(m module.Version) *modfile.File { + return mms.modFiles[m] +} + func (mms *MainModuleSet) Len() int { if mms == nil { return 0 @@ -178,6 +214,7 @@ const ( // in go.mod, edit it before loading. func ModFile() *modfile.File { Init() + modFile := MainModules.ModFile(MainModules.mustGetSingleMainModule()) if modFile == nil { die() } @@ -557,7 +594,7 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { if len(modRoots) == 0 { _ = TODOWorkspaces("Instead of creating a fake module with an empty modroot, make MainModules.Len() == 0 mean that we're in module mode but not inside any module.") mainModule := module.Version{Path: "command-line-arguments"} - MainModules = makeMainModules([]module.Version{mainModule}, []string{""}) + MainModules = makeMainModules([]module.Version{mainModule}, []string{""}, []*modfile.File{nil}, []*modFileIndex{nil}) goVersion := LatestGoVersion() rawGoVersion.Store(mainModule, goVersion) requirements = newRequirements(modDepthFromGoVersion(goVersion), nil, nil) @@ -566,6 +603,7 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { var modFiles []*modfile.File var mainModules []module.Version + var indices []*modFileIndex for _, modroot := range modRoots { gomod := modFilePath(modroot) var data []byte @@ -593,11 +631,10 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { base.Fatalf("go: no module declaration in go.mod. To specify the module path:\n\tgo mod edit -module=example.com/mod") } - modFile = f // TODO(golang.org/cl/327329): remove the global modFile variable and replace it with multiple modfiles modFiles = append(modFiles, f) mainModule := f.Module.Mod mainModules = append(mainModules, mainModule) - index = indexModFile(data, f, mainModule, fixed) + indices = append(indices, indexModFile(data, f, mainModule, fixed)) if err := module.CheckImportPath(f.Module.Mod.Path); err != nil { if pathErr, ok := err.(*module.InvalidPathError); ok { @@ -607,7 +644,7 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { } } - MainModules = makeMainModules(mainModules, modRoots) + MainModules = makeMainModules(mainModules, modRoots, modFiles, indices) setDefaultBuildMod() // possibly enable automatic vendoring rs = requirementsFromModFiles(ctx, modFiles) @@ -623,14 +660,16 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { if cfg.BuildMod == "vendor" { readVendorList() - checkVendorConsistency() + index := MainModules.Index(mainModule) + modFile := MainModules.ModFile(mainModule) + checkVendorConsistency(index, modFile) rs.initVendor(vendorList) } - if index.goVersionV == "" { + if MainModules.Index(mainModule).goVersionV == "" { // TODO(#45551): Do something more principled instead of checking // cfg.CmdName directly here. if cfg.BuildMod == "mod" && cfg.CmdName != "mod graph" && cfg.CmdName != "mod why" { - addGoStmt(mainModule, LatestGoVersion()) + addGoStmt(MainModules.ModFile(mainModule), mainModule, LatestGoVersion()) if go117EnableLazyLoading { // We need to add a 'go' version to the go.mod file, but we must assume // that its existing contents match something between Go 1.11 and 1.16. @@ -689,12 +728,12 @@ func CreateModFile(ctx context.Context, modPath string) { } fmt.Fprintf(os.Stderr, "go: creating new go.mod: module %s\n", modPath) - modFile = new(modfile.File) + modFile := new(modfile.File) modFile.AddModuleStmt(modPath) - MainModules = makeMainModules([]module.Version{modFile.Module.Mod}, []string{modRoot}) - addGoStmt(modFile.Module.Mod, LatestGoVersion()) // Add the go directive before converted module requirements. + MainModules = makeMainModules([]module.Version{modFile.Module.Mod}, []string{modRoot}, []*modfile.File{modFile}, []*modFileIndex{nil}) + addGoStmt(modFile, modFile.Module.Mod, LatestGoVersion()) // Add the go directive before converted module requirements. - convertedFrom, err := convertLegacyConfig(modPath) + convertedFrom, err := convertLegacyConfig(modFile, modPath) if convertedFrom != "" { fmt.Fprintf(os.Stderr, "go: copying requirements from %s\n", base.ShortPath(convertedFrom)) } @@ -792,7 +831,7 @@ func AllowMissingModuleImports() { // makeMainModules creates a MainModuleSet and associated variables according to // the given main modules. -func makeMainModules(ms []module.Version, rootDirs []string) *MainModuleSet { +func makeMainModules(ms []module.Version, rootDirs []string, modFiles []*modfile.File, indices []*modFileIndex) *MainModuleSet { for _, m := range ms { if m.Version != "" { panic("mainModulesCalled with module.Version with non empty Version field: " + fmt.Sprintf("%#v", m)) @@ -803,10 +842,14 @@ func makeMainModules(ms []module.Version, rootDirs []string) *MainModuleSet { inGorootSrc: map[module.Version]bool{}, pathPrefix: map[module.Version]string{}, modRoot: map[module.Version]string{}, + modFiles: map[module.Version]*modfile.File{}, + indices: map[module.Version]*modFileIndex{}, } for i, m := range ms { mainModules.pathPrefix[m] = m.Path mainModules.modRoot[m] = rootDirs[i] + mainModules.modFiles[m] = modFiles[i] + mainModules.indices[m] = indices[i] if rel := search.InDir(rootDirs[i], cfg.GOROOTsrc); rel != "" { mainModules.inGorootSrc[m] = true @@ -840,15 +883,18 @@ func requirementsFromModFiles(ctx context.Context, modFiles []*modfile.File) *Re } direct := map[string]bool{} for _, modFile := range modFiles { - // TODO(golang.org/cl/327329): Use the correct index here. + requirement: for _, r := range modFile.Require { - if index != nil && index.exclude[r.Mod] { - if cfg.BuildMod == "mod" { - fmt.Fprintf(os.Stderr, "go: dropping requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version) - } else { - fmt.Fprintf(os.Stderr, "go: ignoring requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version) + // TODO(#45713): Maybe join + for _, mainModule := range MainModules.Versions() { + if index := MainModules.Index(mainModule); index != nil && index.exclude[r.Mod] { + if cfg.BuildMod == "mod" { + fmt.Fprintf(os.Stderr, "go: dropping requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version) + } else { + fmt.Fprintf(os.Stderr, "go: ignoring requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version) + } + continue requirement } - continue } roots = append(roots, r.Mod) @@ -908,6 +954,7 @@ func setDefaultBuildMod() { } if len(modRoots) == 1 { + index := MainModules.GetSingleIndexOrNil() if fi, err := fsys.Stat(filepath.Join(modRoots[0], "vendor")); err == nil && fi.IsDir() { modGo := "unspecified" if index != nil && index.goVersionV != "" { @@ -933,7 +980,7 @@ func setDefaultBuildMod() { // convertLegacyConfig imports module requirements from a legacy vendoring // configuration file, if one is present. -func convertLegacyConfig(modPath string) (from string, err error) { +func convertLegacyConfig(modFile *modfile.File, modPath string) (from string, err error) { noneSelected := func(path string) (version string) { return "none" } queryPackage := func(path, rev string) (module.Version, error) { pkgMods, modOnly, err := QueryPattern(context.Background(), path, rev, noneSelected, nil) @@ -967,7 +1014,7 @@ func convertLegacyConfig(modPath string) (from string, err error) { // addGoStmt adds a go directive to the go.mod file if it does not already // include one. The 'go' version added, if any, is the latest version supported // by this toolchain. -func addGoStmt(mod module.Version, v string) { +func addGoStmt(modFile *modfile.File, mod module.Version, v string) { if modFile.Go != nil && modFile.Go.Version != "" { return } @@ -1231,8 +1278,11 @@ func commitRequirements(ctx context.Context, goVersion string, rs *Requirements) if MainModules.Len() != 1 || MainModules.ModRoot(MainModules.Versions()[0]) == "" { _ = TODOWorkspaces("also check that workspace mode is off") // We aren't in a module, so we don't have anywhere to write a go.mod file. + _ = TODOWorkspaces("also check that workspace mode is off") return } + mainModule := MainModules.Versions()[0] + modFile := MainModules.ModFile(mainModule) var list []*modfile.Require for _, m := range rs.rootModules { @@ -1251,6 +1301,7 @@ func commitRequirements(ctx context.Context, goVersion string, rs *Requirements) } modFile.Cleanup() + index := MainModules.GetSingleIndexOrNil() dirty := index.modFileIsDirty(modFile) if dirty && cfg.BuildMod != "mod" { // If we're about to fail due to -mod=readonly, @@ -1281,7 +1332,7 @@ func commitRequirements(ctx context.Context, goVersion string, rs *Requirements) mainModule := MainModules.Versions()[0] // At this point we have determined to make the go.mod file on disk equal to new. - index = indexModFile(new, modFile, mainModule, false) + MainModules.SetIndex(mainModule, indexModFile(new, modFile, mainModule, false)) // Update go.sum after releasing the side lock and refreshing the index. // 'go mod init' shouldn't write go.sum, since it will be incomplete. diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index 7b9f6e863a..f5332ef52f 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -54,11 +54,13 @@ const ( go117LazyTODO = false ) -var modFile *modfile.File - // modFileGoVersion returns the (non-empty) Go version at which the requirements // in modFile are intepreted, or the latest Go version if modFile is nil. func modFileGoVersion() string { + _ = TODOWorkspaces("this is obviously wrong.") + // Yes we're picking arbitrarily, we'll have to pass through the version + // we care about + modFile := MainModules.ModFile(MainModules.Versions()[0]) if modFile == nil { return LatestGoVersion() } @@ -90,9 +92,6 @@ type modFileIndex struct { exclude map[module.Version]bool } -// index is the index of the go.mod file as of when it was last read or written. -var index *modFileIndex - type requireMeta struct { indirect bool } @@ -135,8 +134,10 @@ var ErrDisallowed = errors.New("disallowed module version") // CheckExclusions returns an error equivalent to ErrDisallowed if module m is // excluded by the main module's go.mod file. func CheckExclusions(ctx context.Context, m module.Version) error { - if index != nil && index.exclude[m] { - return module.VersionError(m, errExcluded) + for _, mainModule := range MainModules.Versions() { + if index := MainModules.Index(mainModule); index != nil && index.exclude[m] { + return module.VersionError(m, errExcluded) + } } return nil } @@ -304,19 +305,37 @@ func CheckDeprecation(ctx context.Context, m module.Version) (deprecation string return summary.deprecated, nil } +func replacement(mod module.Version, index *modFileIndex) (fromVersion string, to module.Version, ok bool) { + if r, ok := index.replace[mod]; ok { + return mod.Version, r, true + } + if r, ok := index.replace[module.Version{Path: mod.Path}]; ok { + return "", r, true + } + return "", module.Version{}, false +} + // Replacement returns the replacement for mod, if any, from go.mod. // If there is no replacement for mod, Replacement returns // a module.Version with Path == "". func Replacement(mod module.Version) module.Version { - if index != nil { - if r, ok := index.replace[mod]; ok { - return r - } - if r, ok := index.replace[module.Version{Path: mod.Path}]; ok { - return r + _ = TODOWorkspaces("support replaces in the go.work file") + foundFrom, found, foundModRoot := "", module.Version{}, "" + for _, v := range MainModules.Versions() { + if index := MainModules.Index(v); index != nil { + if from, r, ok := replacement(mod, index); ok { + modRoot := MainModules.ModRoot(v) + if foundModRoot != "" && foundFrom != from && found != r { + _ = TODOWorkspaces("once the go.work file supports replaces, recommend them as a way to override conflicts") + base.Errorf("conflicting replacements found for %v in workspace modules defined by %v and %v", + mod, modFilePath(foundModRoot), modFilePath(modRoot)) + return found + } + found, foundModRoot = r, modRoot + } } } - return module.Version{} + return found } // resolveReplacement returns the module actually used to load the source code @@ -551,27 +570,29 @@ func goModSummary(m module.Version) (*modFileSummary, error) { } } - if index != nil && len(index.exclude) > 0 { - // Drop any requirements on excluded versions. - // Don't modify the cached summary though, since we might need the raw - // summary separately. - haveExcludedReqs := false - for _, r := range summary.require { - if index.exclude[r] { - haveExcludedReqs = true - break - } - } - if haveExcludedReqs { - s := new(modFileSummary) - *s = *summary - s.require = make([]module.Version, 0, len(summary.require)) + for _, mainModule := range MainModules.Versions() { + if index := MainModules.Index(mainModule); index != nil && len(index.exclude) > 0 { + // Drop any requirements on excluded versions. + // Don't modify the cached summary though, since we might need the raw + // summary separately. + haveExcludedReqs := false for _, r := range summary.require { - if !index.exclude[r] { - s.require = append(s.require, r) + if index.exclude[r] { + haveExcludedReqs = true + break + } + } + if haveExcludedReqs { + s := new(modFileSummary) + *s = *summary + s.require = make([]module.Version, 0, len(summary.require)) + for _, r := range summary.require { + if !index.exclude[r] { + s.require = append(s.require, r) + } } + summary = s } - summary = s } } return summary, nil diff --git a/src/cmd/go/internal/modload/query.go b/src/cmd/go/internal/modload/query.go index 83e80d009b..05ef0a9c48 100644 --- a/src/cmd/go/internal/modload/query.go +++ b/src/cmd/go/internal/modload/query.go @@ -973,14 +973,18 @@ func lookupRepo(proxy, path string) (repo versionRepo, err error) { repo = emptyRepo{path: path, err: err} } - if index == nil { - return repo, err - } - if _, ok := index.highestReplaced[path]; !ok { - return repo, err + // TODO(#45713): Join all the highestReplaced fields into a single value. + for _, mm := range MainModules.Versions() { + index := MainModules.Index(mm) + if index == nil { + continue + } + if _, ok := index.highestReplaced[path]; ok { + return &replacementRepo{repo: repo}, nil + } } - return &replacementRepo{repo: repo}, nil + return repo, err } // An emptyRepo is a versionRepo that contains no versions. @@ -1019,11 +1023,13 @@ func (rr *replacementRepo) Versions(prefix string) ([]string, error) { } versions := repoVersions - if index != nil && len(index.replace) > 0 { - path := rr.ModulePath() - for m, _ := range index.replace { - if m.Path == path && strings.HasPrefix(m.Version, prefix) && m.Version != "" && !module.IsPseudoVersion(m.Version) { - versions = append(versions, m.Version) + for _, mm := range MainModules.Versions() { + if index := MainModules.Index(mm); index != nil && len(index.replace) > 0 { + path := rr.ModulePath() + for m, _ := range index.replace { + if m.Path == path && strings.HasPrefix(m.Version, prefix) && m.Version != "" && !module.IsPseudoVersion(m.Version) { + versions = append(versions, m.Version) + } } } } @@ -1041,7 +1047,16 @@ func (rr *replacementRepo) Versions(prefix string) ([]string, error) { func (rr *replacementRepo) Stat(rev string) (*modfetch.RevInfo, error) { info, err := rr.repo.Stat(rev) - if err == nil || index == nil || len(index.replace) == 0 { + if err == nil { + return info, err + } + var hasReplacements bool + for _, v := range MainModules.Versions() { + if index := MainModules.Index(v); index != nil && len(index.replace) > 0 { + hasReplacements = true + } + } + if !hasReplacements { return info, err } @@ -1068,27 +1083,42 @@ func (rr *replacementRepo) Stat(rev string) (*modfetch.RevInfo, error) { func (rr *replacementRepo) Latest() (*modfetch.RevInfo, error) { info, err := rr.repo.Latest() + path := rr.ModulePath() - if index != nil { - path := rr.ModulePath() - if v, ok := index.highestReplaced[path]; ok { - if v == "" { - // The only replacement is a wildcard that doesn't specify a version, so - // synthesize a pseudo-version with an appropriate major version and a - // timestamp below any real timestamp. That way, if the main module is - // used from within some other module, the user will be able to upgrade - // the requirement to any real version they choose. - if _, pathMajor, ok := module.SplitPathVersion(path); ok && len(pathMajor) > 0 { - v = module.PseudoVersion(pathMajor[1:], "", time.Time{}, "000000000000") - } else { - v = module.PseudoVersion("v0", "", time.Time{}, "000000000000") + highestReplaced, found := "", false + for _, mm := range MainModules.Versions() { + if index := MainModules.Index(mm); index != nil { + if v, ok := index.highestReplaced[path]; ok { + if !found { + highestReplaced, found = v, true + continue + } + if semver.Compare(v, highestReplaced) > 0 { + highestReplaced = v } } + } + } - if err != nil || semver.Compare(v, info.Version) > 0 { - return rr.replacementStat(v) + if found { + v := highestReplaced + + if v == "" { + // The only replacement is a wildcard that doesn't specify a version, so + // synthesize a pseudo-version with an appropriate major version and a + // timestamp below any real timestamp. That way, if the main module is + // used from within some other module, the user will be able to upgrade + // the requirement to any real version they choose. + if _, pathMajor, ok := module.SplitPathVersion(path); ok && len(pathMajor) > 0 { + v = module.PseudoVersion(pathMajor[1:], "", time.Time{}, "000000000000") + } else { + v = module.PseudoVersion("v0", "", time.Time{}, "000000000000") } } + + if err != nil || semver.Compare(v, info.Version) > 0 { + return rr.replacementStat(v) + } } return info, err diff --git a/src/cmd/go/internal/modload/vendor.go b/src/cmd/go/internal/modload/vendor.go index e26da15a8f..6dc8b6cf82 100644 --- a/src/cmd/go/internal/modload/vendor.go +++ b/src/cmd/go/internal/modload/vendor.go @@ -15,6 +15,7 @@ import ( "cmd/go/internal/base" + "golang.org/x/mod/modfile" "golang.org/x/mod/module" "golang.org/x/mod/semver" ) @@ -134,7 +135,7 @@ func readVendorList() { // checkVendorConsistency verifies that the vendor/modules.txt file matches (if // go 1.14) or at least does not contradict (go 1.13 or earlier) the // requirements and replacements listed in the main module's go.mod file. -func checkVendorConsistency() { +func checkVendorConsistency(index *modFileIndex, modFile *modfile.File) { readVendorList() pre114 := false -- GitLab From b2205eab0efef6cba784aca4436cb0ef8ac0a4de Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Mon, 14 Jun 2021 19:22:58 -0400 Subject: [PATCH 0544/2500] [dev.cmdgo] cmd/go: add go mod initwork command This command is used to create a go.work file with a set of modules given in the arguments to the command. For #45713 Change-Id: I09f8cefc5849dd43c234dc4a37091791fcc02ebe Reviewed-on: https://go-review.googlesource.com/c/go/+/334936 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/alldocs.go | 18 +++++++++ src/cmd/go/internal/modcmd/initwork.go | 54 ++++++++++++++++++++++++++ src/cmd/go/internal/modcmd/mod.go | 1 + src/cmd/go/internal/modload/init.go | 18 +++++++++ src/cmd/go/testdata/script/work.txt | 10 +++-- 5 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 src/cmd/go/internal/modcmd/initwork.go diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index e7c2e6b51b..fb99dccb46 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -1034,6 +1034,7 @@ // edit edit go.mod from tools or scripts // graph print module requirement graph // init initialize new module in current directory +// initwork initialize workspace file // tidy add missing and remove unused modules // vendor make vendored copy of dependencies // verify verify dependencies have expected content @@ -1229,6 +1230,23 @@ // See https://golang.org/ref/mod#go-mod-init for more about 'go mod init'. // // +// Initialize workspace file +// +// Usage: +// +// go mod initwork [moddirs] +// +// go mod initwork initializes and writes a new go.work file in the current +// directory, in effect creating a new workspace at the current directory. +// +// go mod initwork optionally accepts paths to the workspace modules as arguments. +// If the argument is omitted, an empty workspace with no modules will be created. +// +// See the workspaces design proposal at +// https://go.googlesource.com/proposal/+/master/design/45713-workspace.md for +// more information. +// +// // Add missing and remove unused modules // // Usage: diff --git a/src/cmd/go/internal/modcmd/initwork.go b/src/cmd/go/internal/modcmd/initwork.go new file mode 100644 index 0000000000..30653503bc --- /dev/null +++ b/src/cmd/go/internal/modcmd/initwork.go @@ -0,0 +1,54 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// go mod initwork + +package modcmd + +import ( + "cmd/go/internal/base" + "cmd/go/internal/modload" + "context" + "path/filepath" +) + +var _ = modload.TODOWorkspaces("Add more documentation below.T hough this is" + + "enough for those trying workspaces out, there should be more through" + + "documentation if the proposal is accepted.") + +var cmdInitwork = &base.Command{ + UsageLine: "go mod initwork [moddirs]", + Short: "initialize workspace file", + Long: `go mod initwork initializes and writes a new go.work file in the current +directory, in effect creating a new workspace at the current directory. + +go mod initwork optionally accepts paths to the workspace modules as arguments. +If the argument is omitted, an empty workspace with no modules will be created. + +See the workspaces design proposal at +https://go.googlesource.com/proposal/+/master/design/45713-workspace.md for +more information. +`, + Run: runInitwork, +} + +func init() { + base.AddModCommonFlags(&cmdInitwork.Flag) + base.AddWorkfileFlag(&cmdInitwork.Flag) +} + +func runInitwork(ctx context.Context, cmd *base.Command, args []string) { + modload.InitWorkfile() + + modload.ForceUseModules = true + + // TODO(matloob): support using the -workfile path + // To do that properly, we'll have to make the module directories + // make dirs relative to workFile path before adding the paths to + // the directory entries + + workFile := filepath.Join(base.Cwd(), "go.work") + + modload.CreateWorkFile(ctx, workFile, args) +} diff --git a/src/cmd/go/internal/modcmd/mod.go b/src/cmd/go/internal/modcmd/mod.go index d72d0cacd6..3586b44c1a 100644 --- a/src/cmd/go/internal/modcmd/mod.go +++ b/src/cmd/go/internal/modcmd/mod.go @@ -25,6 +25,7 @@ See 'go help modules' for an overview of module functionality. cmdEdit, cmdGraph, cmdInit, + cmdInitwork, cmdTidy, cmdVendor, cmdVerify, diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 607054d1eb..18f0f2b8f8 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -767,6 +767,24 @@ func CreateModFile(ctx context.Context, modPath string) { } } +// CreateWorkFile initializes a new workspace by creating a go.work file. +func CreateWorkFile(ctx context.Context, workFile string, modDirs []string) { + _ = TODOWorkspaces("Report an error if the file already exists.") + + goV := LatestGoVersion() // Use current Go version by default + workF := new(modfile.WorkFile) + workF.Syntax = new(modfile.FileSyntax) + workF.AddGoStmt(goV) + + for _, dir := range modDirs { + _ = TODOWorkspaces("Add the module path of the module.") + workF.AddDirectory(dir, "") + } + + data := modfile.Format(workF.Syntax) + lockedfile.Write(workFile, bytes.NewReader(data), 0644) +} + // fixVersion returns a modfile.VersionFixer implemented using the Query function. // // It resolves commit hashes and branch names to versions, diff --git a/src/cmd/go/testdata/script/work.txt b/src/cmd/go/testdata/script/work.txt index f2b51ca629..c68ca89a76 100644 --- a/src/cmd/go/testdata/script/work.txt +++ b/src/cmd/go/testdata/script/work.txt @@ -1,3 +1,6 @@ +go mod initwork ./a ./b +cmp go.work go.work.want + go run example.com/b stdout 'Hello from module A' @@ -31,14 +34,13 @@ directory ( b ../src/a ) --- go.work -- +-- go.work.want -- go 1.17 directory ( - ./a - ./b + ./a + ./b ) - -- a/go.mod -- module example.com/a -- GitLab From 72233d27c4dcbbbbb53f06bdafd4a0fb8d652662 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 20 Jul 2021 14:37:53 -0700 Subject: [PATCH 0545/2500] [dev.cmdgo] cmd/go: add -testsum flag to update go.sum in script tests -testsum may be set to "tidy", "listm", or "listall". When set, TestScript runs 'go mod tidy', 'go list -m -mod=mod all', or 'go list -mod=mod all' at the beginning of each test that has a go.mod file in its root directory. If the test passes and go.mod or go.sum was updated, TestScript will rewrite the test file with the initial content of go.mod and go.sum (after the above command). This is useful for writing tests that need a working go.sum and for fixing tests that rely on -mod=mod. For golang/go#41302 Change-Id: I63a5667621a5082ccedfc1bff33c3969c29e8b3d Reviewed-on: https://go-review.googlesource.com/c/go/+/336150 Run-TryBot: Jay Conrod TryBot-Result: Go Bot Trust: Jay Conrod Reviewed-by: Michael Matloob --- src/cmd/go/script_test.go | 81 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go index 639e907db0..9ca297e89b 100644 --- a/src/cmd/go/script_test.go +++ b/src/cmd/go/script_test.go @@ -11,6 +11,7 @@ import ( "bytes" "context" "errors" + "flag" "fmt" "go/build" "internal/testenv" @@ -35,6 +36,8 @@ import ( "cmd/internal/sys" ) +var testSum = flag.String("testsum", "", `may be tidy, listm, or listall. If set, TestScript generates a go.sum file at the beginning of each test and updates test files if they pass.`) + // TestScript runs the tests in testdata/script/*.txt. func TestScript(t *testing.T) { testenv.MustHaveGoBuild(t) @@ -269,6 +272,22 @@ func (ts *testScript) run() { ts.mark = ts.log.Len() } + // With -testsum, if a go.mod file is present in the test's initial + // working directory, run 'go mod tidy'. + if *testSum != "" { + if ts.updateSum(a) { + defer func() { + if ts.t.Failed() { + return + } + data := txtar.Format(a) + if err := os.WriteFile(ts.file, data, 0666); err != nil { + ts.t.Errorf("rewriting test file: %v", err) + } + }() + } + } + // Run script. // See testdata/script/README for documentation of script form. script := string(a.Comment) @@ -1341,6 +1360,68 @@ func (ts *testScript) parse(line string) command { return cmd } +// updateSum runs 'go mod tidy', 'go list -mod=mod -m all', or +// 'go list -mod=mod all' in the test's current directory if a file named +// "go.mod" is present after the archive has been extracted. updateSum modifies +// archive and returns true if go.mod or go.sum were changed. +func (ts *testScript) updateSum(archive *txtar.Archive) (rewrite bool) { + gomodIdx, gosumIdx := -1, -1 + for i := range archive.Files { + switch archive.Files[i].Name { + case "go.mod": + gomodIdx = i + case "go.sum": + gosumIdx = i + } + } + if gomodIdx < 0 { + return false + } + + switch *testSum { + case "tidy": + ts.cmdGo(success, []string{"mod", "tidy"}) + case "listm": + ts.cmdGo(success, []string{"list", "-m", "-mod=mod", "all"}) + case "listall": + ts.cmdGo(success, []string{"list", "-mod=mod", "all"}) + default: + ts.t.Fatalf(`unknown value for -testsum %q; may be "tidy", "listm", or "listall"`, *testSum) + } + + newGomodData, err := os.ReadFile(filepath.Join(ts.cd, "go.mod")) + if err != nil { + ts.t.Fatalf("reading go.mod after -testsum: %v", err) + } + if !bytes.Equal(newGomodData, archive.Files[gomodIdx].Data) { + archive.Files[gomodIdx].Data = newGomodData + rewrite = true + } + + newGosumData, err := os.ReadFile(filepath.Join(ts.cd, "go.sum")) + if err != nil && !os.IsNotExist(err) { + ts.t.Fatalf("reading go.sum after -testsum: %v", err) + } + switch { + case os.IsNotExist(err) && gosumIdx >= 0: + // go.sum was deleted. + rewrite = true + archive.Files = append(archive.Files[:gosumIdx], archive.Files[gosumIdx+1:]...) + case err == nil && gosumIdx < 0: + // go.sum was created. + rewrite = true + gosumIdx = gomodIdx + 1 + archive.Files = append(archive.Files, txtar.File{}) + copy(archive.Files[gosumIdx+1:], archive.Files[gosumIdx:]) + archive.Files[gosumIdx] = txtar.File{Name: "go.sum", Data: newGosumData} + case err == nil && gosumIdx >= 0 && !bytes.Equal(newGosumData, archive.Files[gosumIdx].Data): + // go.sum was changed. + rewrite = true + archive.Files[gosumIdx].Data = newGosumData + } + return rewrite +} + // diff returns a formatted diff of the two texts, // showing the entire text and the minimum line-level // additions and removals to turn text1 into text2. -- GitLab From 2c8acf63c233430f8fb48f37c6ec54a29bd53c28 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 20 Jul 2021 14:46:40 -0700 Subject: [PATCH 0546/2500] [dev.cmdgo] cmd/go: make fewer 'go mod' commands update go.mod 'go mod graph', 'go mod vendor', 'go mod verify', and 'go mod why' will no longer edit go.mod or go.sum. 'go mod graph', 'go mod verify', and 'go mod why' may still fetch files and look up packages as if they were able to update go.mod. They're useful for debugging and should still work when go.mod is a little broken. This is implemented in modload.setDefaultBuildMod based on command name for now. Super gross. Sorry. This should be fixed with a larger refactoring for #40775. Fixes golang/go#45551 Change-Id: If5f225937180d32e9a5dd252c78d988042bbdedf Reviewed-on: https://go-review.googlesource.com/c/go/+/336151 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Michael Matloob --- src/cmd/go/internal/modload/init.go | 21 +++++++++++++---- src/cmd/go/testdata/script/mod_all.txt | 2 +- src/cmd/go/testdata/script/mod_e.txt | 23 ++++++++++++------- src/cmd/go/testdata/script/mod_get_commit.txt | 2 +- .../go/testdata/script/mod_getmode_vendor.txt | 1 + .../go/testdata/script/mod_list_retract.txt | 4 +++- src/cmd/go/testdata/script/mod_retention.txt | 8 ++++--- src/cmd/go/testdata/script/mod_tidy_error.txt | 4 ++-- .../go/testdata/script/mod_vendor_replace.txt | 5 +++- .../testdata/script/mod_vendor_trimpath.txt | 6 ++++- .../script/mod_vendor_unused_only.txt | 2 ++ src/cmd/go/testdata/script/mod_verify.txt | 5 ---- src/cmd/go/testdata/script/modfile_flag.txt | 5 ++++ 13 files changed, 61 insertions(+), 27 deletions(-) diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 18f0f2b8f8..3758786562 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -955,12 +955,25 @@ func setDefaultBuildMod() { return } - if cfg.CmdName == "get" || strings.HasPrefix(cfg.CmdName, "mod ") { - // 'get' and 'go mod' commands may update go.mod automatically. - // TODO(jayconrod): should this narrower? Should 'go mod download' or - // 'go mod graph' update go.mod by default? + // TODO(#40775): commands should pass in the module mode as an option + // to modload functions instead of relying on an implicit setting + // based on command name. + switch cfg.CmdName { + case "get", "mod download", "mod init", "mod tidy": + // These commands are intended to update go.mod and go.sum. cfg.BuildMod = "mod" return + case "mod graph", "mod verify", "mod why": + // These commands should not update go.mod or go.sum, but they should be + // able to fetch modules not in go.sum and should not report errors if + // go.mod is inconsistent. They're useful for debugging, and they need + // to work in buggy situations. + cfg.BuildMod = "mod" + allowWriteGoMod = false + return + case "mod vendor": + cfg.BuildMod = "readonly" + return } if modRoots == nil { if allowMissingModuleImports { diff --git a/src/cmd/go/testdata/script/mod_all.txt b/src/cmd/go/testdata/script/mod_all.txt index 090eeee22d..6fa2d83239 100644 --- a/src/cmd/go/testdata/script/mod_all.txt +++ b/src/cmd/go/testdata/script/mod_all.txt @@ -315,7 +315,7 @@ go 1.15 require ( example.com/a v0.1.0 - example.com/b v0.1.0 + example.com/b v0.1.0 // indirect example.com/q v0.1.0 example.com/r v0.1.0 // indirect example.com/t v0.1.0 diff --git a/src/cmd/go/testdata/script/mod_e.txt b/src/cmd/go/testdata/script/mod_e.txt index 3a0d18dabc..3cffaf6ef1 100644 --- a/src/cmd/go/testdata/script/mod_e.txt +++ b/src/cmd/go/testdata/script/mod_e.txt @@ -24,11 +24,11 @@ cmp go.mod.orig go.mod ! go mod vendor -stderr '^example.com/untidy imports\n\texample.net/directnotfound: cannot find module providing package example.net/directnotfound: module example.net/directnotfound: reading http://.*: 404 Not Found$' +stderr '^example.com/untidy imports\n\texample.net/directnotfound: no required module provides package example.net/directnotfound; to add it:\n\tgo get example.net/directnotfound$' -stderr '^example.com/untidy imports\n\texample.net/m imports\n\texample.net/indirectnotfound: cannot find module providing package example.net/indirectnotfound: module example.net/indirectnotfound: reading http://.*: 404 Not Found$' +stderr '^example.com/untidy imports\n\texample.net/m: module example.net/m provides package example.net/m and is replaced but not required; to add it:\n\tgo get example.net/m@v0.1.0$' -stderr '^example.com/untidy tested by\n\texample.com/untidy.test imports\n\texample.net/directtestnotfound: cannot find module providing package example.net/directtestnotfound: module example.net/directtestnotfound: reading http://.*: 404 Not Found$' +stderr '^example.com/untidy tested by\n\texample.com/untidy.test imports\n\texample.net/directtestnotfound: no required module provides package example.net/directtestnotfound; to add it:\n\tgo get example.net/directtestnotfound$' ! stderr 'indirecttestnotfound' # Vendor prunes test dependencies. @@ -43,15 +43,22 @@ stderr -count=4 'cannot find module providing package' cmp go.mod.final go.mod -# 'go mod vendor -e' still logs the errors, but succeeds and updates go.mod. - +# 'go mod vendor -e' still logs the errors, but creates a vendor directory +# and exits with status 0. +# 'go mod vendor -e' does not update go.mod and will not vendor packages that +# would require changing go.mod, for example, by adding a requirement. cp go.mod.orig go.mod go mod vendor -e -stderr -count=3 'cannot find module providing package' -cmp go.mod.final go.mod +stderr -count=2 'no required module provides package' +stderr '^example.com/untidy imports\n\texample.net/m: module example.net/m provides package example.net/m and is replaced but not required; to add it:\n\tgo get example.net/m@v0.1.0$' exists vendor/modules.txt -exists vendor/example.net/m/m.go +! exists vendor/example.net +go mod edit -require example.net/m@v0.1.0 +go mod vendor -e +stderr -count=3 'no required module provides package' +exists vendor/modules.txt +exists vendor/example.net/m/m.go -- go.mod -- module example.com/untidy diff --git a/src/cmd/go/testdata/script/mod_get_commit.txt b/src/cmd/go/testdata/script/mod_get_commit.txt index 4649491a53..0cf94ae182 100644 --- a/src/cmd/go/testdata/script/mod_get_commit.txt +++ b/src/cmd/go/testdata/script/mod_get_commit.txt @@ -44,7 +44,7 @@ go mod edit -require rsc.io/quote@23179ee grep 'rsc.io/quote 23179ee' go.mod # but other commands fix them -go mod graph +go list -m -mod=mod all grep 'rsc.io/quote v1.5.1' go.mod -- go.mod -- diff --git a/src/cmd/go/testdata/script/mod_getmode_vendor.txt b/src/cmd/go/testdata/script/mod_getmode_vendor.txt index d3df2078b0..00070c03b5 100644 --- a/src/cmd/go/testdata/script/mod_getmode_vendor.txt +++ b/src/cmd/go/testdata/script/mod_getmode_vendor.txt @@ -25,6 +25,7 @@ stderr 'go list -m: can''t match module patterns using the vendor directory\n\t\ -- go.mod -- module x +go 1.16 -- x.go -- package x import _ "rsc.io/quote" diff --git a/src/cmd/go/testdata/script/mod_list_retract.txt b/src/cmd/go/testdata/script/mod_list_retract.txt index 4b13348515..b7147aa182 100644 --- a/src/cmd/go/testdata/script/mod_list_retract.txt +++ b/src/cmd/go/testdata/script/mod_list_retract.txt @@ -101,7 +101,9 @@ module example.com/use go 1.15 require example.com/retract v1.0.0-bad - +-- go.sum -- +example.com/retract v1.0.0-bad h1:liAW69rbtjY67x2CcNzat668L/w+YGgNX3lhJsWIJis= +example.com/retract v1.0.0-bad/go.mod h1:0DvGGofJ9hr1q63cBrOY/jSY52OwhRGA0K47NE80I5Y= -- use.go -- package use diff --git a/src/cmd/go/testdata/script/mod_retention.txt b/src/cmd/go/testdata/script/mod_retention.txt index 7a371b1806..481c10d2b7 100644 --- a/src/cmd/go/testdata/script/mod_retention.txt +++ b/src/cmd/go/testdata/script/mod_retention.txt @@ -39,12 +39,14 @@ go list -mod=mod all cmp go.mod go.mod.tidy # "// indirect" comments should be added if appropriate. +# TODO(#42504): add case for 'go list -mod=mod -tags=any all' when -tags=any +# is supported. Only a command that loads "all" without build constraints +# (except "ignore") has enough information to add "// indirect" comments. +# 'go mod tidy' and 'go mod vendor' are the only commands that do that, +# but 'go mod vendor' cannot write go.mod. cp go.mod.toodirect go.mod go list all cmp go.mod go.mod.toodirect -go mod vendor # loads everything, so adds "// indirect" comments. -cmp go.mod go.mod.tidy -rm -r vendor # Redundant requirements should be preserved... diff --git a/src/cmd/go/testdata/script/mod_tidy_error.txt b/src/cmd/go/testdata/script/mod_tidy_error.txt index 395537b1a7..51fc65fa7a 100644 --- a/src/cmd/go/testdata/script/mod_tidy_error.txt +++ b/src/cmd/go/testdata/script/mod_tidy_error.txt @@ -10,8 +10,8 @@ stderr '^issue27063 imports\n\tissue27063/other imports\n\tother.example.com/non ! go mod vendor ! stderr 'package nonexist is not in GOROOT' -stderr '^issue27063 imports\n\tnonexist.example.com: cannot find module providing package nonexist.example.com' -stderr '^issue27063 imports\n\tissue27063/other imports\n\tother.example.com/nonexist: cannot find module providing package other.example.com/nonexist' +stderr '^issue27063 imports\n\tnonexist.example.com: no required module provides package nonexist.example.com; to add it:\n\tgo get nonexist.example.com$' +stderr '^issue27063 imports\n\tissue27063/other imports\n\tother.example.com/nonexist: no required module provides package other.example.com/nonexist; to add it:\n\tgo get other.example.com/nonexist$' -- go.mod -- module issue27063 diff --git a/src/cmd/go/testdata/script/mod_vendor_replace.txt b/src/cmd/go/testdata/script/mod_vendor_replace.txt index 0c1c1d22f5..1820af62ad 100644 --- a/src/cmd/go/testdata/script/mod_vendor_replace.txt +++ b/src/cmd/go/testdata/script/mod_vendor_replace.txt @@ -36,7 +36,6 @@ module example.com/replace require rsc.io/quote/v3 v3.0.0 replace rsc.io/quote/v3 => ./local/not-rsc.io/quote/v3 - -- imports.go -- package replace @@ -64,3 +63,7 @@ require ( not-rsc.io/quote/v3 v3.0.0 ) replace not-rsc.io/quote/v3 => rsc.io/quote/v3 v3.0.0 +-- multiple-paths/go.sum -- +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +rsc.io/quote/v3 v3.0.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/src/cmd/go/testdata/script/mod_vendor_trimpath.txt b/src/cmd/go/testdata/script/mod_vendor_trimpath.txt index 5451aa773c..d9d9d98897 100644 --- a/src/cmd/go/testdata/script/mod_vendor_trimpath.txt +++ b/src/cmd/go/testdata/script/mod_vendor_trimpath.txt @@ -29,8 +29,12 @@ stdout '^example.com/stack@v1.0.0/stack.go$' -- go.mod -- module example.com/main -require example.com/stack v1.0.0 +go 1.17 +require example.com/stack v1.0.0 +-- go.sum -- +example.com/stack v1.0.0 h1:IEDLeew5NytZ8vrgCF/QVem3H3SR3QMttdu9HfJvk9I= +example.com/stack v1.0.0/go.mod h1:7wFEbaV5e5O7wJ8aBdqQOR//UXppm/pwnwziMKViuI4= -- main.go -- package main diff --git a/src/cmd/go/testdata/script/mod_vendor_unused_only.txt b/src/cmd/go/testdata/script/mod_vendor_unused_only.txt index 839c6453cf..accd9f373d 100644 --- a/src/cmd/go/testdata/script/mod_vendor_unused_only.txt +++ b/src/cmd/go/testdata/script/mod_vendor_unused_only.txt @@ -12,6 +12,8 @@ module example.com/m go 1.14 require example.com v1.0.0 // indirect +-- go.sum -- +example.com v1.0.0/go.mod h1:WRiieAqDBb1hVdDXLLdxNtCDWNfehn7FWyPC5Oz2vB4= -- go1.14-modules.txt -- # example.com v1.0.0 ## explicit diff --git a/src/cmd/go/testdata/script/mod_verify.txt b/src/cmd/go/testdata/script/mod_verify.txt index b5106659a9..f02d15aa28 100644 --- a/src/cmd/go/testdata/script/mod_verify.txt +++ b/src/cmd/go/testdata/script/mod_verify.txt @@ -39,11 +39,6 @@ stderr 'go.mod: checksum mismatch' # go.sum should be created and updated automatically. rm go.sum -go mod graph -exists go.sum -grep '^rsc.io/quote v1.1.0/go.mod ' go.sum -! grep '^rsc.io/quote v1.1.0 ' go.sum - go mod tidy grep '^rsc.io/quote v1.1.0/go.mod ' go.sum grep '^rsc.io/quote v1.1.0 ' go.sum diff --git a/src/cmd/go/testdata/script/modfile_flag.txt b/src/cmd/go/testdata/script/modfile_flag.txt index 5852c31189..7cce581e55 100644 --- a/src/cmd/go/testdata/script/modfile_flag.txt +++ b/src/cmd/go/testdata/script/modfile_flag.txt @@ -24,6 +24,11 @@ stdout '^go.alt.mod$' go mod edit -require rsc.io/quote@v1.5.2 grep rsc.io/quote go.alt.mod +# 'go list -m' should add sums to the alternate go.sum. +go list -m -mod=mod all +grep '^rsc.io/quote v1.5.2/go.mod ' go.alt.sum +! grep '^rsc.io/quote v1.5.2 ' go.alt.sum + # other 'go mod' commands should work. 'go mod vendor' is tested later. go mod download rsc.io/quote go mod graph -- GitLab From e00a6ec084605b773cdb87971de5b5536c0cc13e Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sun, 25 Jul 2021 18:27:15 -0700 Subject: [PATCH 0547/2500] [dev.typeparams] cmd/compile: mark methods of instantiated interface types as used Fix the cons.go missing method error. Mark all the methods of instantiated interface types as used. We could try to record all the exact methods used for generic interface types, but for now, just mark all the methods as used so that their methods are not dead-code eliminated. Change-Id: I35685eda82476244371379b97691a1b8506ef0f7 Reviewed-on: https://go-review.googlesource.com/c/go/+/337349 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 25 +++++++++++++++++------ test/run.go | 1 - 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index e482281a3c..02a380e63f 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1515,6 +1515,23 @@ func deref(t *types.Type) *types.Type { return t } +// markTypeUsed marks type t as used in order to help avoid dead-code elimination of +// needed methods. +func markTypeUsed(t *types.Type, lsym *obj.LSym) { + if t.IsInterface() { + // Mark all the methods of the interface as used. + // TODO: we should really only mark the interface methods + // that are actually called in the application. + for i, _ := range t.AllMethods().Slice() { + reflectdata.MarkUsedIfaceMethodIndex(lsym, t, i) + } + } else { + // TODO: This is somewhat overkill, we really only need it + // for types that are put into interfaces. + reflectdata.MarkTypeUsedInInterface(t, lsym) + } +} + // getDictionarySym returns the dictionary for the named generic function gf, which // is instantiated with the type arguments targs. func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) *types.Sym { @@ -1543,11 +1560,7 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) infoPrint(" * %v\n", t) s := reflectdata.TypeLinksym(t) off = objw.SymPtr(lsym, off, s, 0) - // Ensure that methods on t don't get deadcode eliminated - // by the linker. - // TODO: This is somewhat overkill, we really only need it - // for types that are put into interfaces. - reflectdata.MarkTypeUsedInInterface(t, lsym) + markTypeUsed(t, lsym) } subst := typecheck.Tsubster{ Tparams: info.tparams, @@ -1559,7 +1572,7 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) infoPrint(" - %v\n", ts) s := reflectdata.TypeLinksym(ts) off = objw.SymPtr(lsym, off, s, 0) - reflectdata.MarkTypeUsedInInterface(ts, lsym) + markTypeUsed(ts, lsym) } // Emit an entry for each subdictionary (after substituting targs) for _, n := range info.subDictCalls { diff --git a/test/run.go b/test/run.go index edf26a5d82..4971043ab6 100644 --- a/test/run.go +++ b/test/run.go @@ -2181,7 +2181,6 @@ var g3Failures = setOf( "fixedbugs/issue30862.go", // -G=3 doesn't handle //go:nointerface - "typeparam/cons.go", // causes an unreachable method "typeparam/nested.go", // -G=3 doesn't support function-local types with generics "typeparam/mdempsky/4.go", // -G=3 can't export functions with labeled breaks in loops -- GitLab From 288a83dcffef18514e8c01f0ca2053c6be185305 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Mon, 28 Jun 2021 15:48:03 -0400 Subject: [PATCH 0548/2500] [dev.cmdgo] cmd/go: maintain a go.work.sum file This change causes the go command to maintain a separate go.work.sum file when in workspace mode rather than using the go.sum files from the individual modules. This isn't quite what the proposal spec specifies, which is that the sums that don't exist in any of the workspace modules are added to go.work.sum rather than the necessary sums. That will be done in a future change. Change-Id: I528b9b153a93a4cd67c5af471ad6d5bd3628578b Reviewed-on: https://go-review.googlesource.com/c/go/+/334939 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/modfetch/fetch.go | 15 ++++---- src/cmd/go/internal/modload/buildlist.go | 4 +-- src/cmd/go/internal/modload/import.go | 4 ++- src/cmd/go/internal/modload/init.go | 24 ++++++++++--- src/cmd/go/internal/modload/load.go | 4 ++- src/cmd/go/internal/modload/modfile.go | 2 +- src/cmd/go/testdata/script/work.txt | 46 +++++++++++++++++++++--- src/cmd/go/testdata/script/work_sum.txt | 33 +++++++++++++++++ 8 files changed, 113 insertions(+), 19 deletions(-) create mode 100644 src/cmd/go/testdata/script/work_sum.txt diff --git a/src/cmd/go/internal/modfetch/fetch.go b/src/cmd/go/internal/modfetch/fetch.go index e40593abae..7b3525e914 100644 --- a/src/cmd/go/internal/modfetch/fetch.go +++ b/src/cmd/go/internal/modfetch/fetch.go @@ -681,19 +681,21 @@ func isValidSum(data []byte) bool { return true } +var ErrGoSumDirty = errors.New("updates to go.sum needed, disabled by -mod=readonly") + // WriteGoSum writes the go.sum file if it needs to be updated. // // keep is used to check whether a newly added sum should be saved in go.sum. // It should have entries for both module content sums and go.mod sums // (version ends with "/go.mod"). Existing sums will be preserved unless they // have been marked for deletion with TrimGoSum. -func WriteGoSum(keep map[module.Version]bool) { +func WriteGoSum(keep map[module.Version]bool, readonly bool) error { goSum.mu.Lock() defer goSum.mu.Unlock() // If we haven't read the go.sum file yet, don't bother writing it. if !goSum.enabled { - return + return nil } // Check whether we need to add sums for which keep[m] is true or remove @@ -711,10 +713,10 @@ Outer: } } if !dirty { - return + return nil } - if cfg.BuildMod == "readonly" { - base.Fatalf("go: updates to go.sum needed, disabled by -mod=readonly") + if readonly { + return ErrGoSumDirty } // Make a best-effort attempt to acquire the side lock, only to exclude @@ -759,11 +761,12 @@ Outer: }) if err != nil { - base.Fatalf("go: updating go.sum: %v", err) + return fmt.Errorf("updating go.sum: %w", err) } goSum.status = make(map[modSum]modSumStatus) goSum.overwrite = false + return nil } // TrimGoSum trims go.sum to contain only the modules needed for reproducible diff --git a/src/cmd/go/internal/modload/buildlist.go b/src/cmd/go/internal/modload/buildlist.go index 959ee25df4..d2957a34c4 100644 --- a/src/cmd/go/internal/modload/buildlist.go +++ b/src/cmd/go/internal/modload/buildlist.go @@ -807,7 +807,7 @@ func updateLazyRoots(ctx context.Context, direct map[string]bool, rs *Requiremen // We've added or upgraded one or more roots, so load the full module // graph so that we can update those roots to be consistent with other // requirements. - if cfg.BuildMod != "mod" { + if mustHaveCompleteRequirements() { // Our changes to the roots may have moved dependencies into or out of // the lazy-loading horizon, which could in turn change the selected // versions of other modules. (Unlike for eager modules, for lazy @@ -1007,7 +1007,7 @@ func updateEagerRoots(ctx context.Context, direct map[string]bool, rs *Requireme return rs, err } - if cfg.BuildMod != "mod" { + if mustHaveCompleteRequirements() { // Instead of actually updating the requirements, just check that no updates // are needed. if rs == nil { diff --git a/src/cmd/go/internal/modload/import.go b/src/cmd/go/internal/modload/import.go index b6b9bf65b8..773d8b600b 100644 --- a/src/cmd/go/internal/modload/import.go +++ b/src/cmd/go/internal/modload/import.go @@ -32,6 +32,8 @@ type ImportMissingError struct { Module module.Version QueryErr error + ImportingModule module.Version + // isStd indicates whether we would expect to find the package in the standard // library. This is normally true for all dotless import paths, but replace // directives can cause us to treat the replaced paths as also being in @@ -673,7 +675,7 @@ func fetch(ctx context.Context, mod module.Version, needSum bool) (dir string, i mod = r } - if HasModRoot() && cfg.BuildMod == "readonly" && needSum && !modfetch.HaveSum(mod) { + if HasModRoot() && cfg.BuildMod == "readonly" && !inWorkspaceMode() && needSum && !modfetch.HaveSum(mod) { return "", false, module.VersionError(mod, &sumMissingError{}) } diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 3758786562..00dfc8b2dc 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -367,6 +367,7 @@ func Init() { if err != nil { base.Fatalf("reading go.work: %v", err) } + modfetch.GoSumFile = workFilePath + ".sum" // TODO(matloob) should workRoot just be workFile? } else if modRoots == nil { // We're in module mode, but not inside a module. @@ -1009,6 +1010,10 @@ func setDefaultBuildMod() { cfg.BuildMod = "readonly" } +func mustHaveCompleteRequirements() bool { + return cfg.BuildMod != "mod" && !inWorkspaceMode() +} + // convertLegacyConfig imports module requirements from a legacy vendoring // configuration file, if one is present. func convertLegacyConfig(modFile *modfile.File, modPath string) (from string, err error) { @@ -1306,10 +1311,17 @@ func commitRequirements(ctx context.Context, goVersion string, rs *Requirements) return } + if inWorkspaceMode() { + // go.mod files aren't updated in workspace mode, but we still want to + // update the go.work.sum file. + if err := modfetch.WriteGoSum(keepSums(ctx, loaded, rs, addBuildListZipSums), mustHaveCompleteRequirements()); err != nil { + base.Fatalf("go: %v", err) + } + return + } + if MainModules.Len() != 1 || MainModules.ModRoot(MainModules.Versions()[0]) == "" { - _ = TODOWorkspaces("also check that workspace mode is off") // We aren't in a module, so we don't have anywhere to write a go.mod file. - _ = TODOWorkspaces("also check that workspace mode is off") return } mainModule := MainModules.Versions()[0] @@ -1346,7 +1358,9 @@ func commitRequirements(ctx context.Context, goVersion string, rs *Requirements) // Don't write go.mod, but write go.sum in case we added or trimmed sums. // 'go mod init' shouldn't write go.sum, since it will be incomplete. if cfg.CmdName != "mod init" { - modfetch.WriteGoSum(keepSums(ctx, loaded, rs, addBuildListZipSums)) + if err := modfetch.WriteGoSum(keepSums(ctx, loaded, rs, addBuildListZipSums), mustHaveCompleteRequirements()); err != nil { + base.Fatalf("go: %v", err) + } } return } @@ -1368,7 +1382,9 @@ func commitRequirements(ctx context.Context, goVersion string, rs *Requirements) // Update go.sum after releasing the side lock and refreshing the index. // 'go mod init' shouldn't write go.sum, since it will be incomplete. if cfg.CmdName != "mod init" { - modfetch.WriteGoSum(keepSums(ctx, loaded, rs, addBuildListZipSums)) + if err := modfetch.WriteGoSum(keepSums(ctx, loaded, rs, addBuildListZipSums), mustHaveCompleteRequirements()); err != nil { + base.Fatalf("go: %v", err) + } } }() diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index 77d2dc4030..e7b03b08e9 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -403,7 +403,9 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma // loaded.requirements, but here we may have also loaded (and want to // preserve checksums for) additional entities from compatRS, which are // only needed for compatibility with ld.TidyCompatibleVersion. - modfetch.WriteGoSum(keep) + if err := modfetch.WriteGoSum(keep, mustHaveCompleteRequirements()); err != nil { + base.Fatalf("go: %v", err) + } } } diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index f5332ef52f..79126a46b5 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -532,7 +532,7 @@ func goModSummary(m module.Version) (*modFileSummary, error) { } actual := resolveReplacement(m) - if HasModRoot() && cfg.BuildMod == "readonly" && actual.Version != "" { + if HasModRoot() && cfg.BuildMod == "readonly" && !inWorkspaceMode() && actual.Version != "" { key := module.Version{Path: actual.Path, Version: actual.Version + "/go.mod"} if !modfetch.HaveSum(key) { suggestion := fmt.Sprintf("; to add it:\n\tgo mod download %s", m.Path) diff --git a/src/cmd/go/testdata/script/work.txt b/src/cmd/go/testdata/script/work.txt index c68ca89a76..0d820fffc2 100644 --- a/src/cmd/go/testdata/script/work.txt +++ b/src/cmd/go/testdata/script/work.txt @@ -1,13 +1,20 @@ go mod initwork ./a ./b cmp go.work go.work.want +! go run example.com/b +stderr 'a(\\|/)a.go:4:8: no required module provides package rsc.io/quote; to add it:\n\tgo get rsc.io/quote' +cd a +go get rsc.io/quote +go env GOMOD # go env GOMOD reports the module in a single module context +stdout $GOPATH(\\|/)src(\\|/)a(\\|/)go.mod +cd .. go run example.com/b -stdout 'Hello from module A' +stdout 'Hello, world.' # And try from a different directory cd c -go run example.com/b -stdout 'Hello from module A' +go run example.com/b +stdout 'Hello, world.' cd $GOPATH/src go list all # all includes both modules @@ -26,6 +33,9 @@ cp go.work.dup go.work stderr 'reading go.work: path .* appears multiple times in workspace' cp go.work.backup go.work +cp go.work.d go.work +go run example.com/d + -- go.work.dup -- go 1.17 @@ -41,6 +51,14 @@ directory ( ./a ./b ) +-- go.work.d -- +go 1.17 + +directory ( + a + b + d +) -- a/go.mod -- module example.com/a @@ -49,9 +67,10 @@ module example.com/a package a import "fmt" +import "rsc.io/quote" func HelloFromA() { - fmt.Println("Hello from module A") + fmt.Println(quote.Hello()) } -- b/go.mod -- @@ -66,8 +85,27 @@ import "example.com/a" func main() { a.HelloFromA() } +-- b/lib/hello.go -- +package lib + +import "example.com/a" + +func Hello() { + a.HelloFromA() +} -- c/README -- Create this directory so we can cd to it and make sure paths are interpreted relative to the go.work, not the cwd. +-- d/go.mod -- +module example.com/d + +-- d/main.go -- +package main + +import "example.com/b/lib" + +func main() { + lib.Hello() +} diff --git a/src/cmd/go/testdata/script/work_sum.txt b/src/cmd/go/testdata/script/work_sum.txt new file mode 100644 index 0000000000..99f66a4003 --- /dev/null +++ b/src/cmd/go/testdata/script/work_sum.txt @@ -0,0 +1,33 @@ +# Test adding sums to go.work.sum when sum isn't in go.mod. + +go run . +cmp go.work.sum want.sum + +-- want.sum -- +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0= +rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +-- go.work -- +go 1.18 + +directory . +-- go.mod -- +go 1.18 + +module example.com/hi + +require "rsc.io/quote" v1.5.2 +-- main.go -- +package main + +import ( + "fmt" + "rsc.io/quote" +) + +func main() { + fmt.Println(quote.Hello()) +} \ No newline at end of file -- GitLab From 176baafd5b6d968fc0df25b344ffe826e47e6879 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Wed, 28 Jul 2021 12:32:08 -0400 Subject: [PATCH 0549/2500] [dev.cmdgo] cmd/go: sort roots when joining multiple main module roots When concatenating multiple main modules' roots we need to resort the list of main module roots. This avoids a panic from unsorted main module roots. This will get better when we have structured module roots. Change-Id: I68fed47b0f3b131ed3dadf45db3c442286a0ced0 Reviewed-on: https://go-review.googlesource.com/c/go/+/338111 Trust: Michael Matloob Run-TryBot: Michael Matloob Reviewed-by: Jay Conrod --- src/cmd/go/internal/modload/buildlist.go | 3 +++ src/cmd/go/testdata/script/work.txt | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/cmd/go/internal/modload/buildlist.go b/src/cmd/go/internal/modload/buildlist.go index d2957a34c4..4fbe563cb8 100644 --- a/src/cmd/go/internal/modload/buildlist.go +++ b/src/cmd/go/internal/modload/buildlist.go @@ -1083,6 +1083,9 @@ func updateEagerRoots(ctx context.Context, direct map[string]bool, rs *Requireme } roots = append(roots, min...) } + if MainModules.Len() > 1 { + module.Sort(roots) + } if rs.depth == eager && reflect.DeepEqual(roots, rs.rootModules) && reflect.DeepEqual(direct, rs.direct) { // The root set is unchanged and rs was already eager, so keep rs to // preserve its cached ModuleGraph (if any). diff --git a/src/cmd/go/testdata/script/work.txt b/src/cmd/go/testdata/script/work.txt index 0d820fffc2..eeaf92eaec 100644 --- a/src/cmd/go/testdata/script/work.txt +++ b/src/cmd/go/testdata/script/work.txt @@ -36,6 +36,11 @@ cp go.work.backup go.work cp go.work.d go.work go run example.com/d +# Test that we don't run into "newRequirements called with unsorted roots" +# panic with unsorted main modules. +cp go.work.backwards go.work +go run example.com/d + -- go.work.dup -- go 1.17 @@ -109,3 +114,12 @@ import "example.com/b/lib" func main() { lib.Hello() } + +-- go.work.backwards -- +go 1.18 + +directory ( + d + b + a +) \ No newline at end of file -- GitLab From 473e493d18c277d69e40a4930af045d474ff2be4 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Wed, 21 Jul 2021 12:12:22 -0400 Subject: [PATCH 0550/2500] [dev.typeparams] cmd/compile/internal/types2: merge instance and Named to eliminate sanitization This is a port of CL 335929 to types2. It differs significantly from that CL to handle lazy loading, which wasn't tested in go/types. Additionally, the *Checker field was moved out of instance and back onto Named. This way we can tell whether a Named type is uninstantiated simply by checking whether Named.instance is non-nil, which simplified the code considerably. Fixes #46151 Change-Id: I617263bcfaa768ac5442213cecad8d567c2749fc Reviewed-on: https://go-review.googlesource.com/c/go/+/336252 Trust: Robert Findley Trust: Robert Griesemer Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/builtins.go | 2 +- src/cmd/compile/internal/types2/check.go | 5 - src/cmd/compile/internal/types2/decl.go | 12 +- src/cmd/compile/internal/types2/infer.go | 3 - src/cmd/compile/internal/types2/instance.go | 62 ++---- .../compile/internal/types2/instantiate.go | 72 +++--- src/cmd/compile/internal/types2/lookup.go | 2 +- src/cmd/compile/internal/types2/named.go | 45 ++-- src/cmd/compile/internal/types2/object.go | 3 + src/cmd/compile/internal/types2/predicates.go | 8 +- src/cmd/compile/internal/types2/sanitize.go | 205 ------------------ .../compile/internal/types2/sizeof_test.go | 3 +- src/cmd/compile/internal/types2/subst.go | 15 +- .../internal/types2/testdata/check/issues.go2 | 4 +- src/cmd/compile/internal/types2/typeparam.go | 3 +- src/cmd/compile/internal/types2/typestring.go | 10 +- src/cmd/compile/internal/types2/typexpr.go | 2 +- 17 files changed, 127 insertions(+), 329 deletions(-) delete mode 100644 src/cmd/compile/internal/types2/sanitize.go diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 2af2679d5e..b9fcf3c898 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -798,7 +798,7 @@ func hasVarSize(t Type) bool { } case *TypeParam: return true - case *Named, *Union, *instance, *top: + case *Named, *Union, *top: unreachable() } return false diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go index 071afef058..6bc965c497 100644 --- a/src/cmd/compile/internal/types2/check.go +++ b/src/cmd/compile/internal/types2/check.go @@ -282,11 +282,6 @@ func (check *Checker) checkFiles(files []*syntax.File) (err error) { print("== recordUntyped ==") check.recordUntyped() - if check.Info != nil { - print("== sanitizeInfo ==") - sanitizeInfo(check.Info) - } - check.pkg.complete = true // no longer needed - release memory diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 4f656e374a..6ca8f75e9a 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -317,6 +317,8 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { } case *Named: + t.expand() + // don't touch the type if it is from a different package or the Universe scope // (doing so would lead to a race condition - was issue #35049) if t.obj.pkg != check.pkg { @@ -349,9 +351,6 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { panic("internal error: cycle start not found") } return t.info - - case *instance: - return check.validType(t.expand(), path) } return valid @@ -557,7 +556,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named // determine underlying type of named named.fromRHS = check.definedType(tdecl.Type, named) - + assert(named.fromRHS != nil) // The underlying type of named may be itself a named type that is // incomplete: // @@ -624,7 +623,8 @@ func (check *Checker) boundType(e syntax.Expr) Type { bound := check.typ(e) check.later(func() { - if _, ok := under(bound).(*Interface); !ok && bound != Typ[Invalid] { + u := under(bound) + if _, ok := u.(*Interface); !ok && u != Typ[Invalid] { check.errorf(e, "%s is not an interface", bound) } }) @@ -692,7 +692,7 @@ func (check *Checker) collectMethods(obj *TypeName) { } if base != nil { - base.expand() // TODO(mdempsky): Probably unnecessary. + base.load() // TODO(mdempsky): Probably unnecessary. base.methods = append(base.methods, m) } } diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index b44ff7377a..6e7a217709 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -342,9 +342,6 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { // t must be one of w.tparams return t.index < len(w.tparams) && w.tparams[t.index].typ == t - case *instance: - return w.isParameterizedList(t.targs) - default: unreachable() } diff --git a/src/cmd/compile/internal/types2/instance.go b/src/cmd/compile/internal/types2/instance.go index 798d58811f..df0fc17ba7 100644 --- a/src/cmd/compile/internal/types2/instance.go +++ b/src/cmd/compile/internal/types2/instance.go @@ -4,56 +4,40 @@ package types2 +// TODO(rfindley): move this code to named.go. + import "cmd/compile/internal/syntax" -// An instance represents an instantiated generic type syntactically -// (without expanding the instantiation). Type instances appear only -// during type-checking and are replaced by their fully instantiated -// (expanded) types before the end of type-checking. +// instance holds position information for use in lazy instantiation. +// +// TODO(rfindley): come up with a better name for this type, now that its usage +// has changed. type instance struct { - check *Checker // for lazy instantiation pos syntax.Pos // position of type instantiation; for error reporting only - base *Named // parameterized type to be instantiated - targs []Type // type arguments posList []syntax.Pos // position of each targ; for error reporting only - verify bool // if set, constraint satisfaction is verified - value Type // base[targs...] after instantiation or Typ[Invalid]; nil if not yet set + verify bool // if set, check constraint satisfaction upon instantiation } -// expand returns the instantiated (= expanded) type of t. -// The result is either an instantiated *Named type, or -// Typ[Invalid] if there was an error. -func (t *instance) expand() Type { - v := t.value - if v == nil { - v = t.check.Instantiate(t.pos, t.base, t.targs, t.posList, t.verify) - if v == nil { - v = Typ[Invalid] - } - t.value = v - } - // After instantiation we must have an invalid or a *Named type. - if debug && v != Typ[Invalid] { - _ = v.(*Named) +// expand ensures that the underlying type of n is instantiated. +// The underlying type will be Typ[Invalid] if there was an error. +func (n *Named) expand() { + if n.instance != nil { + // n must be loaded before instantiation, in order to have accurate + // tparams. This is done implicitly by the call to n.TParams, but making it + // explicit is harmless: load is idempotent. + n.load() + inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams(), n.targs, n.instance.posList, n.instance.verify) + n.underlying = inst + n.fromRHS = inst + n.instance = nil } - return v } -// expand expands a type instance into its instantiated -// type and leaves all other types alone. expand does -// not recurse. +// expand expands uninstantiated named types and leaves all other types alone. +// expand does not recurse. func expand(typ Type) Type { - if t, _ := typ.(*instance); t != nil { - return t.expand() + if t, _ := typ.(*Named); t != nil { + t.expand() } return typ } - -// expandf is set to expand. -// Call expandf when calling expand causes compile-time cycle error. -var expandf func(Type) Type - -func init() { expandf = expand } - -func (t *instance) Underlying() Type { return t } -func (t *instance) String() string { return TypeString(t, nil) } diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index db398c6563..1294b08490 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -25,28 +25,6 @@ import ( // Any methods attached to a *Named are simply copied; they are not // instantiated. func (check *Checker) Instantiate(pos syntax.Pos, typ Type, targs []Type, posList []syntax.Pos, verify bool) (res Type) { - if verify && check == nil { - panic("cannot have nil receiver if verify is set") - } - - if check != nil && check.conf.Trace { - check.trace(pos, "-- instantiating %s with %s", typ, typeListString(targs)) - check.indent++ - defer func() { - check.indent-- - var under Type - if res != nil { - // Calling under() here may lead to endless instantiations. - // Test case: type T[P any] T[P] - // TODO(gri) investigate if that's a bug or to be expected. - under = res.Underlying() - } - check.trace(pos, "=> %s (under = %s)", res, under) - }() - } - - assert(len(posList) <= len(targs)) - // TODO(gri) What is better here: work with TypeParams, or work with TypeNames? var tparams []*TypeName switch t := typ.(type) { @@ -76,7 +54,10 @@ func (check *Checker) Instantiate(pos syntax.Pos, typ Type, targs []Type, posLis // only types and functions can be generic panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } + return check.instantiate(pos, typ, tparams, targs, posList, verify) +} +func (check *Checker) instantiate(pos syntax.Pos, typ Type, tparams []*TypeName, targs []Type, posList []syntax.Pos, verify bool) (res Type) { // the number of supplied types must match the number of type parameters if len(targs) != len(tparams) { // TODO(gri) provide better error message @@ -86,6 +67,27 @@ func (check *Checker) Instantiate(pos syntax.Pos, typ Type, targs []Type, posLis } panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, len(targs), len(tparams))) } + if verify && check == nil { + panic("cannot have nil receiver if verify is set") + } + + if check != nil && check.conf.Trace { + check.trace(pos, "-- instantiating %s with %s", typ, typeListString(targs)) + check.indent++ + defer func() { + check.indent-- + var under Type + if res != nil { + // Calling under() here may lead to endless instantiations. + // Test case: type T[P any] T[P] + // TODO(gri) investigate if that's a bug or to be expected. + under = res.Underlying() + } + check.trace(pos, "=> %s (under = %s)", res, under) + }() + } + + assert(len(posList) <= len(targs)) if len(tparams) == 0 { return typ // nothing to do (minor optimization) @@ -115,19 +117,35 @@ func (check *Checker) Instantiate(pos syntax.Pos, typ Type, targs []Type, posLis // instantiating the type until needed. typ must be a *Named // type. func (check *Checker) InstantiateLazy(pos syntax.Pos, typ Type, targs []Type, posList []syntax.Pos, verify bool) Type { - base := asNamed(typ) + // Don't use asNamed here: we don't want to expand the base during lazy + // instantiation. + base := typ.(*Named) + if base == nil { panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } + h := instantiatedHash(base, targs) + if check != nil { + // typ may already have been instantiated with identical type arguments. In + // that case, re-use the existing instance. + if named := check.typMap[h]; named != nil { + return named + } + } - return &instance{ - check: check, + tname := NewTypeName(pos, base.obj.pkg, base.obj.name, nil) + named := check.newNamed(tname, base, nil, nil, nil) // methods and tparams are set when named is loaded. + named.targs = targs + named.instance = &instance{ pos: pos, - base: base, - targs: targs, posList: posList, verify: verify, } + + if check != nil { + check.typMap[h] = named + } + return named } // satisfies reports whether the type argument targ satisfies the constraint of type parameter diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index ecf6926c0a..9e9d6dfb29 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -119,7 +119,7 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o seen[named] = true // look for a matching attached method - named.expand() + named.load() if i, m := lookupMethod(named.methods, pkg, name); m != nil { // potential match // caution: method may not have a proper signature yet diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index da098b58b7..a88aeb0077 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -10,12 +10,13 @@ import "sync" // A Named represents a named (defined) type. type Named struct { - check *Checker // for Named.under implementation; nilled once under has been called + check *Checker info typeInfo // for cycle detection obj *TypeName // corresponding declared object orig *Named // original, uninstantiated type fromRHS Type // type (on RHS of declaration) this *Named type is derived from (for cycle reporting) underlying Type // possibly a *Named during setup; never a *Named once set up completely + instance *instance // position information for lazy instantiation, or nil tparams []*TypeName // type parameters, or nil targs []Type // type arguments (after instantiation), or nil methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily @@ -34,7 +35,19 @@ func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named { return (*Checker)(nil).newNamed(obj, nil, underlying, nil, methods) } -func (t *Named) expand() *Named { +func (t *Named) load() *Named { + // If t is an instantiated type, it derives its methods and tparams from its + // base type. Since we expect type parameters and methods to be set after a + // call to load, we must load the base and copy here. + // + // underlying is set when t is expanded. + // + // By convention, a type instance is loaded iff its tparams are set. + if len(t.targs) > 0 && t.tparams == nil { + t.orig.load() + t.tparams = t.orig.tparams + t.methods = t.orig.methods + } if t.resolve == nil { return t } @@ -83,7 +96,7 @@ func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tpar if check != nil { check.later(func() { switch typ.under().(type) { - case *Named, *instance: + case *Named: panic("internal error: unexpanded underlying type") } typ.check = nil @@ -104,10 +117,12 @@ func (t *Named) Orig() *Named { return t.orig } // TParams returns the type parameters of the named type t, or nil. // The result is non-nil for an (originally) parameterized type even if it is instantiated. -func (t *Named) TParams() []*TypeName { return t.expand().tparams } +func (t *Named) TParams() []*TypeName { + return t.load().tparams +} // SetTParams sets the type parameters of the named type t. -func (t *Named) SetTParams(tparams []*TypeName) { t.expand().tparams = tparams } +func (t *Named) SetTParams(tparams []*TypeName) { t.load().tparams = tparams } // TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated. func (t *Named) TArgs() []Type { return t.targs } @@ -116,10 +131,10 @@ func (t *Named) TArgs() []Type { return t.targs } func (t *Named) SetTArgs(args []Type) { t.targs = args } // NumMethods returns the number of explicit methods whose receiver is named type t. -func (t *Named) NumMethods() int { return len(t.expand().methods) } +func (t *Named) NumMethods() int { return len(t.load().methods) } // Method returns the i'th method of named type t for 0 <= i < t.NumMethods(). -func (t *Named) Method(i int) *Func { return t.expand().methods[i] } +func (t *Named) Method(i int) *Func { return t.load().methods[i] } // SetUnderlying sets the underlying type and marks t as complete. func (t *Named) SetUnderlying(underlying Type) { @@ -129,18 +144,18 @@ func (t *Named) SetUnderlying(underlying Type) { if _, ok := underlying.(*Named); ok { panic("types2.Named.SetUnderlying: underlying type must not be *Named") } - t.expand().underlying = underlying + t.load().underlying = underlying } // AddMethod adds method m unless it is already in the method list. func (t *Named) AddMethod(m *Func) { - t.expand() + t.load() if i, _ := lookupMethod(t.methods, m.pkg, m.name); i < 0 { t.methods = append(t.methods, m) } } -func (t *Named) Underlying() Type { return t.expand().underlying } +func (t *Named) Underlying() Type { return t.load().underlying } func (t *Named) String() string { return TypeString(t, nil) } // ---------------------------------------------------------------------------- @@ -153,6 +168,8 @@ func (t *Named) String() string { return TypeString(t, nil) } // is detected, the result is Typ[Invalid]. If a cycle is detected and // n0.check != nil, the cycle is reported. func (n0 *Named) under() Type { + n0.expand() + u := n0.Underlying() if u == Typ[Invalid] { @@ -168,7 +185,7 @@ func (n0 *Named) under() Type { default: // common case return u - case *Named, *instance: + case *Named: // handled below } @@ -199,12 +216,8 @@ func (n0 *Named) under() Type { var n1 *Named switch u1 := u.(type) { case *Named: + u1.expand() n1 = u1 - case *instance: - n1, _ = u1.expand().(*Named) - if n1 == nil { - u = Typ[Invalid] - } } if n1 == nil { break // end of chain diff --git a/src/cmd/compile/internal/types2/object.go b/src/cmd/compile/internal/types2/object.go index 82297ff17f..48fd1e44de 100644 --- a/src/cmd/compile/internal/types2/object.go +++ b/src/cmd/compile/internal/types2/object.go @@ -475,6 +475,9 @@ func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) { if _, ok := typ.(*Basic); ok { return } + if named, _ := typ.(*Named); named != nil && len(named.tparams) > 0 { + writeTParamList(buf, named.tparams, qf, nil) + } if tname.IsAlias() { buf.WriteString(" =") } else { diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index f2215b36cb..e448ade9e5 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -10,7 +10,7 @@ package types2 // isNamed may be called with types that are not fully set up. func isNamed(typ Type) bool { switch typ.(type) { - case *Basic, *Named, *TypeParam, *instance: + case *Basic, *Named, *TypeParam: return true } return false @@ -21,7 +21,7 @@ func isNamed(typ Type) bool { func isGeneric(typ Type) bool { // A parameterized type is only instantiated if it doesn't have an instantiation already. named, _ := typ.(*Named) - return named != nil && named.obj != nil && named.TParams() != nil && named.targs == nil + return named != nil && named.obj != nil && named.targs == nil && named.TParams() != nil } func is(typ Type, what BasicInfo) bool { @@ -144,8 +144,8 @@ func (p *ifacePair) identical(q *ifacePair) bool { // For changes to this code the corresponding changes should be made to unifier.nify. func identical(x, y Type, cmpTags bool, p *ifacePair) bool { // types must be expanded for comparison - x = expandf(x) - y = expandf(y) + x = expand(x) + y = expand(y) if x == y { return true diff --git a/src/cmd/compile/internal/types2/sanitize.go b/src/cmd/compile/internal/types2/sanitize.go deleted file mode 100644 index 3d2323a0a2..0000000000 --- a/src/cmd/compile/internal/types2/sanitize.go +++ /dev/null @@ -1,205 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package types2 - -// sanitizeInfo walks the types contained in info to ensure that all instances -// are expanded. -// -// This includes some objects that may be shared across concurrent -// type-checking passes (such as those in the universe scope), so we are -// careful here not to write types that are already sanitized. This avoids a -// data race as any shared types should already be sanitized. -func sanitizeInfo(info *Info) { - var s sanitizer = make(map[Type]Type) - - // Note: Some map entries are not references. - // If modified, they must be assigned back. - - for e, tv := range info.Types { - if typ := s.typ(tv.Type); typ != tv.Type { - tv.Type = typ - info.Types[e] = tv - } - } - - for e, inf := range info.Inferred { - changed := false - for i, targ := range inf.TArgs { - if typ := s.typ(targ); typ != targ { - inf.TArgs[i] = typ - changed = true - } - } - if typ := s.typ(inf.Sig); typ != inf.Sig { - inf.Sig = typ.(*Signature) - changed = true - } - if changed { - info.Inferred[e] = inf - } - } - - for _, obj := range info.Defs { - if obj != nil { - if typ := s.typ(obj.Type()); typ != obj.Type() { - obj.setType(typ) - } - } - } - - for _, obj := range info.Uses { - if obj != nil { - if typ := s.typ(obj.Type()); typ != obj.Type() { - obj.setType(typ) - } - } - } - - // TODO(gri) sanitize as needed - // - info.Implicits - // - info.Selections - // - info.Scopes - // - info.InitOrder -} - -type sanitizer map[Type]Type - -func (s sanitizer) typ(typ Type) Type { - if typ == nil { - return nil - } - - if t, found := s[typ]; found { - return t - } - s[typ] = typ - - switch t := typ.(type) { - case *Basic, *top: - // nothing to do - - case *Array: - if elem := s.typ(t.elem); elem != t.elem { - t.elem = elem - } - - case *Slice: - if elem := s.typ(t.elem); elem != t.elem { - t.elem = elem - } - - case *Struct: - s.varList(t.fields) - - case *Pointer: - if base := s.typ(t.base); base != t.base { - t.base = base - } - - case *Tuple: - s.tuple(t) - - case *Signature: - s.var_(t.recv) - s.tuple(t.params) - s.tuple(t.results) - - case *Union: - s.typeList(t.types) - - case *Interface: - s.funcList(t.methods) - s.typeList(t.embeddeds) - // TODO(gri) do we need to sanitize type sets? - tset := t.typeSet() - s.funcList(tset.methods) - if types := s.typ(tset.types); types != tset.types { - tset.types = types - } - - case *Map: - if key := s.typ(t.key); key != t.key { - t.key = key - } - if elem := s.typ(t.elem); elem != t.elem { - t.elem = elem - } - - case *Chan: - if elem := s.typ(t.elem); elem != t.elem { - t.elem = elem - } - - case *Named: - if debug && t.check != nil { - panic("internal error: Named.check != nil") - } - t.expand() - if orig := s.typ(t.fromRHS); orig != t.fromRHS { - t.fromRHS = orig - } - if under := s.typ(t.underlying); under != t.underlying { - t.underlying = under - } - s.typeList(t.targs) - s.funcList(t.methods) - - case *TypeParam: - if bound := s.typ(t.bound); bound != t.bound { - t.bound = bound - } - - case *instance: - typ = t.expand() - s[t] = typ - - default: - unimplemented() - } - - return typ -} - -func (s sanitizer) var_(v *Var) { - if v != nil { - if typ := s.typ(v.typ); typ != v.typ { - v.typ = typ - } - } -} - -func (s sanitizer) varList(list []*Var) { - for _, v := range list { - s.var_(v) - } -} - -func (s sanitizer) tuple(t *Tuple) { - if t != nil { - s.varList(t.vars) - } -} - -func (s sanitizer) func_(f *Func) { - if f != nil { - if typ := s.typ(f.typ); typ != f.typ { - f.typ = typ - } - } -} - -func (s sanitizer) funcList(list []*Func) { - for _, f := range list { - s.func_(f) - } -} - -func (s sanitizer) typeList(list []Type) { - for i, t := range list { - if typ := s.typ(t); typ != t { - list[i] = typ - } - } -} diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go index 22ef369683..a62b7cb3e2 100644 --- a/src/cmd/compile/internal/types2/sizeof_test.go +++ b/src/cmd/compile/internal/types2/sizeof_test.go @@ -31,9 +31,8 @@ func TestSizeof(t *testing.T) { {Interface{}, 40, 80}, {Map{}, 16, 32}, {Chan{}, 12, 24}, - {Named{}, 84, 160}, + {Named{}, 88, 168}, {TypeParam{}, 28, 48}, - {instance{}, 56, 104}, {top{}, 0, 0}, // Objects diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 63b234a60e..87e3e3018e 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -26,12 +26,7 @@ func makeSubstMap(tpars []*TypeName, targs []Type) *substMap { assert(len(tpars) == len(targs)) proj := make(map[*TypeParam]Type, len(tpars)) for i, tpar := range tpars { - // We must expand type arguments otherwise *instance - // types end up as components in composite types. - // TODO(gri) explain why this causes problems, if it does - targ := expand(targs[i]) // possibly nil - targs[i] = targ - proj[tpar.typ.(*TypeParam)] = targ + proj[tpar.typ.(*TypeParam)] = targs[i] } return &substMap{targs, proj} } @@ -83,6 +78,7 @@ func (check *Checker) subst(pos syntax.Pos, typ Type, smap *substMap) Type { // for recursive types (example: type T[P any] *T[P]). subst.typMap = make(map[string]*Named) } + return subst.typ(typ) } @@ -241,10 +237,13 @@ func (subst *subster) typ(typ Type) Type { named := subst.check.newNamed(tname, t, t.Underlying(), t.TParams(), t.methods) // method signatures are updated lazily named.targs = new_targs subst.typMap[h] = named + t.expand() // must happen after typMap update to avoid infinite recursion // do the substitution dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, new_targs) named.underlying = subst.typOrNil(t.Underlying()) + dump(">>> underlying: %v", named.underlying) + assert(named.underlying != nil) named.fromRHS = named.underlying // for cycle detection (Checker.validType) return named @@ -252,10 +251,6 @@ func (subst *subster) typ(typ Type) Type { case *TypeParam: return subst.smap.lookup(t) - case *instance: - // TODO(gri) can we avoid the expansion here and just substitute the type parameters? - return subst.typ(t.expand()) - default: unimplemented() } diff --git a/src/cmd/compile/internal/types2/testdata/check/issues.go2 b/src/cmd/compile/internal/types2/testdata/check/issues.go2 index 1ede383ebe..e29357de0b 100644 --- a/src/cmd/compile/internal/types2/testdata/check/issues.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/issues.go2 @@ -74,8 +74,10 @@ func (u T2[U]) Add1() U { return u.s + 1 } +// TODO(rfindley): we should probably report an error here as well, not +// just when the type is first instantiated. func NewT2[U any]() T2[U /* ERROR U has no constraints */ ] { - return T2[U /* ERROR U has no constraints */ ]{} + return T2[U]{} } func _() { diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index 0aca227c0a..b66256cf00 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -21,7 +21,8 @@ type TypeParam struct { id uint64 // unique id, for debugging only obj *TypeName // corresponding type name index int // type parameter index in source order, starting at 0 - bound Type // *Named or *Interface; underlying type is always *Interface + // TODO(rfindley): this could also be Typ[Invalid]. Verify that this is handled correctly. + bound Type // *Named or *Interface; underlying type is always *Interface } // Obj returns the type name for the type parameter t. diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 44099133a0..74d2f1dc51 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -269,6 +269,9 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { } case *Named: + if t.instance != nil { + buf.WriteByte(instanceMarker) + } writeTypeName(buf, t.obj, qf) if t.targs != nil { // instantiated type @@ -294,13 +297,6 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { } buf.WriteString(s + subscript(t.id)) - case *instance: - buf.WriteByte(instanceMarker) // indicate "non-evaluated" syntactic instance - writeTypeName(buf, t.base.obj, qf) - buf.WriteByte('[') - writeTypeList(buf, t.targs, qf, visited) - buf.WriteByte(']') - case *top: buf.WriteString("⊤") diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 83cefa19ba..c55d5c093a 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -446,7 +446,7 @@ func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def // make sure we check instantiation works at least once // and that the resulting type is valid check.later(func() { - t := typ.(*instance).expand() + t := expand(typ) check.validType(t, nil) }) -- GitLab From 53557530093938e19c21f6b02a482939ac6e634b Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 28 Jul 2021 13:39:30 -0700 Subject: [PATCH 0551/2500] [dev.typeparams] test/typeparam: gofmt -w We don't usually reformat the test directory, but all of the files in test/typeparam are syntactically valid. I suspect the misformattings here are because developers aren't re-installing gofmt with -tags=typeparams, not intentionally exercising non-standard formatting. Change-Id: I3767d480434c19225568f3c7d656dc8589197183 Reviewed-on: https://go-review.googlesource.com/c/go/+/338093 Trust: Matthew Dempsky Trust: Robert Griesemer Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- test/typeparam/absdiff.go | 6 +- test/typeparam/absdiffimp.dir/a.go | 2 +- test/typeparam/aliasimp.dir/a.go | 2 +- test/typeparam/aliasimp.dir/main.go | 2 +- test/typeparam/boundmethod.go | 44 +++++----- test/typeparam/builtins.go | 4 +- test/typeparam/chans.go | 2 +- test/typeparam/chansimp.dir/a.go | 2 +- test/typeparam/combine.go | 28 +++--- test/typeparam/cons.go | 4 +- test/typeparam/dictionaryCapture-noinline.go | 26 +++--- test/typeparam/dictionaryCapture.go | 31 ++++--- test/typeparam/dottype.go | 12 +-- test/typeparam/double.go | 10 +-- test/typeparam/equal.go | 20 ++--- test/typeparam/fact.go | 4 +- test/typeparam/factimp.dir/a.go | 4 +- test/typeparam/graph.go | 1 - test/typeparam/ifaceconv.go | 6 +- test/typeparam/index.go | 1 - test/typeparam/interfacearg.go | 2 + test/typeparam/issue39755.go | 4 +- test/typeparam/issue44688.go | 2 +- test/typeparam/issue45817.go | 3 +- test/typeparam/issue46472.go | 2 +- test/typeparam/issue47258.go | 2 +- test/typeparam/list.go | 26 +++--- test/typeparam/list2.go | 4 +- test/typeparam/listimp.dir/a.go | 50 +++++------ test/typeparam/listimp.dir/main.go | 72 ++++++++-------- test/typeparam/listimp2.dir/a.go | 2 +- test/typeparam/listimp2.dir/main.go | 1 - test/typeparam/lockable.go | 2 +- test/typeparam/mapimp.dir/a.go | 10 +-- test/typeparam/mincheck.dir/a.go | 10 +-- test/typeparam/minimp.dir/a.go | 10 +-- test/typeparam/mutualimp.dir/a.go | 3 +- test/typeparam/ordered.go | 14 +-- test/typeparam/orderedmap.go | 10 +-- test/typeparam/orderedmapsimp.dir/a.go | 10 +-- test/typeparam/orderedmapsimp.dir/main.go | 2 +- test/typeparam/pair.go | 5 +- test/typeparam/pairimp.dir/a.go | 4 +- test/typeparam/pairimp.dir/main.go | 27 +++--- test/typeparam/sets.go | 2 +- test/typeparam/settable.go | 1 - test/typeparam/sliceimp.dir/a.go | 26 +++--- test/typeparam/sliceimp.dir/main.go | 64 +++++++------- test/typeparam/slices.go | 90 ++++++++++---------- test/typeparam/smallest.go | 8 +- test/typeparam/smoketest.go | 4 +- test/typeparam/stringable.go | 4 +- test/typeparam/struct.go | 6 +- test/typeparam/subdict.go | 3 +- test/typeparam/sum.go | 4 +- test/typeparam/tparam1.go | 16 ++-- test/typeparam/typelist.go | 30 ++++--- test/typeparam/valimp.dir/a.go | 10 +-- test/typeparam/valimp.dir/main.go | 85 +++++++++--------- 59 files changed, 423 insertions(+), 418 deletions(-) diff --git a/test/typeparam/absdiff.go b/test/typeparam/absdiff.go index e76a998b4d..cad6e84c4e 100644 --- a/test/typeparam/absdiff.go +++ b/test/typeparam/absdiff.go @@ -61,7 +61,7 @@ type complexAbs[T Complex] T func (a complexAbs[T]) Abs() complexAbs[T] { r := float64(real(a)) i := float64(imag(a)) - d := math.Sqrt(r * r + i * i) + d := math.Sqrt(r*r + i*i) return complexAbs[T](complex(d, 0)) } @@ -88,10 +88,10 @@ func main() { panic(fmt.Sprintf("got = %v, want = %v", got, want)) } - if got, want := complexAbsDifference(5.0 + 2.0i, 2.0 - 2.0i), 5+0i; got != want { + if got, want := complexAbsDifference(5.0+2.0i, 2.0-2.0i), 5+0i; got != want { panic(fmt.Sprintf("got = %v, want = %v", got, want)) } - if got, want := complexAbsDifference(2.0 - 2.0i, 5.0 + 2.0i), 5+0i; got != want { + if got, want := complexAbsDifference(2.0-2.0i, 5.0+2.0i), 5+0i; got != want { panic(fmt.Sprintf("got = %v, want = %v", got, want)) } } diff --git a/test/typeparam/absdiffimp.dir/a.go b/test/typeparam/absdiffimp.dir/a.go index df81dcf538..7b5bfbe2ac 100644 --- a/test/typeparam/absdiffimp.dir/a.go +++ b/test/typeparam/absdiffimp.dir/a.go @@ -58,7 +58,7 @@ type complexAbs[T Complex] T func (a complexAbs[T]) Abs() complexAbs[T] { r := float64(real(a)) i := float64(imag(a)) - d := math.Sqrt(r * r + i * i) + d := math.Sqrt(r*r + i*i) return complexAbs[T](complex(d, 0)) } diff --git a/test/typeparam/aliasimp.dir/a.go b/test/typeparam/aliasimp.dir/a.go index 3fac4aac98..c64e87c10f 100644 --- a/test/typeparam/aliasimp.dir/a.go +++ b/test/typeparam/aliasimp.dir/a.go @@ -5,5 +5,5 @@ package a type Rimp[T any] struct { - F T + F T } diff --git a/test/typeparam/aliasimp.dir/main.go b/test/typeparam/aliasimp.dir/main.go index 6638fa9454..221a6c758d 100644 --- a/test/typeparam/aliasimp.dir/main.go +++ b/test/typeparam/aliasimp.dir/main.go @@ -7,7 +7,7 @@ package main import "a" type R[T any] struct { - F T + F T } type S = R diff --git a/test/typeparam/boundmethod.go b/test/typeparam/boundmethod.go index c150f9d85a..3deabbcdce 100644 --- a/test/typeparam/boundmethod.go +++ b/test/typeparam/boundmethod.go @@ -11,50 +11,50 @@ package main import ( - "fmt" - "reflect" - "strconv" + "fmt" + "reflect" + "strconv" ) type myint int //go:noinline func (m myint) String() string { - return strconv.Itoa(int(m)) + return strconv.Itoa(int(m)) } type Stringer interface { - String() string + String() string } func stringify[T Stringer](s []T) (ret []string) { - for _, v := range s { - ret = append(ret, v.String()) - } - return ret + for _, v := range s { + ret = append(ret, v.String()) + } + return ret } type StringInt[T any] T //go:noinline func (m StringInt[T]) String() string { - return "aa" + return "aa" } func main() { - x := []myint{myint(1), myint(2), myint(3)} + x := []myint{myint(1), myint(2), myint(3)} - got := stringify(x) - want := []string{"1", "2", "3"} - if !reflect.DeepEqual(got, want) { - panic(fmt.Sprintf("got %s, want %s", got, want)) - } + got := stringify(x) + want := []string{"1", "2", "3"} + if !reflect.DeepEqual(got, want) { + panic(fmt.Sprintf("got %s, want %s", got, want)) + } - x2 := []StringInt[myint]{StringInt[myint](1), StringInt[myint](2), StringInt[myint](3)} + x2 := []StringInt[myint]{StringInt[myint](1), StringInt[myint](2), StringInt[myint](3)} - got2 := stringify(x2) - want2 := []string{"aa", "aa", "aa"} - if !reflect.DeepEqual(got2, want2) { - panic(fmt.Sprintf("got %s, want %s", got2, want2)) - } + got2 := stringify(x2) + want2 := []string{"aa", "aa", "aa"} + if !reflect.DeepEqual(got2, want2) { + panic(fmt.Sprintf("got %s, want %s", got2, want2)) + } } diff --git a/test/typeparam/builtins.go b/test/typeparam/builtins.go index 3fe6f79391..819588b07d 100644 --- a/test/typeparam/builtins.go +++ b/test/typeparam/builtins.go @@ -39,7 +39,9 @@ func _[T C5[X], X any](ch T) { type M0 interface{ int } type M1 interface{ map[string]int } -type M2 interface { map[string]int | map[string]float64 } +type M2 interface { + map[string]int | map[string]float64 +} type M3 interface{ map[string]int | map[rune]int } type M4[K comparable, V any] interface{ map[K]V | map[rune]V } diff --git a/test/typeparam/chans.go b/test/typeparam/chans.go index 2fcd4af75e..c30c21c37b 100644 --- a/test/typeparam/chans.go +++ b/test/typeparam/chans.go @@ -183,7 +183,7 @@ func _Ranger[Elem any]() (*_Sender[Elem], *_Receiver[Elem]) { values: c, done: d, } - r := &_Receiver[Elem] { + r := &_Receiver[Elem]{ values: c, done: d, } diff --git a/test/typeparam/chansimp.dir/a.go b/test/typeparam/chansimp.dir/a.go index a3f73b2199..7321992704 100644 --- a/test/typeparam/chansimp.dir/a.go +++ b/test/typeparam/chansimp.dir/a.go @@ -176,7 +176,7 @@ func Ranger[Elem any]() (*Sender[Elem], *Receiver[Elem]) { values: c, done: d, } - r := &Receiver[Elem] { + r := &Receiver[Elem]{ values: c, done: d, } diff --git a/test/typeparam/combine.go b/test/typeparam/combine.go index 0e120cf242..5dfdb78442 100644 --- a/test/typeparam/combine.go +++ b/test/typeparam/combine.go @@ -13,18 +13,18 @@ import ( type Gen[A any] func() (A, bool) func Combine[T1, T2, T any](g1 Gen[T1], g2 Gen[T2], join func(T1, T2) T) Gen[T] { - return func() (T, bool) { - var t T - t1, ok := g1() - if !ok { - return t, false - } - t2, ok := g2() - if !ok { - return t, false - } - return join(t1, t2), true - } + return func() (T, bool) { + var t T + t1, ok := g1() + if !ok { + return t, false + } + t2, ok := g2() + if !ok { + return t, false + } + return join(t1, t2), true + } } type Pair[A, B any] struct { @@ -37,7 +37,7 @@ func _NewPair[A, B any](a A, b B) Pair[A, B] { } func Combine2[A, B any](ga Gen[A], gb Gen[B]) Gen[Pair[A, B]] { - return Combine(ga, gb, _NewPair[A, B]) + return Combine(ga, gb, _NewPair[A, B]) } func main() { @@ -60,6 +60,6 @@ func main() { } gc4 := Combine2(g1, g3) if got, ok := gc4(); !ok || got.A != 3 || got.B != "y" { - panic (fmt.Sprintf("got %v, %v, wanted {3, y}, true", got, ok)) + panic(fmt.Sprintf("got %v, %v, wanted {3, y}, true", got, ok)) } } diff --git a/test/typeparam/cons.go b/test/typeparam/cons.go index f20514fb66..4750392a95 100644 --- a/test/typeparam/cons.go +++ b/test/typeparam/cons.go @@ -51,7 +51,7 @@ type List[a any] interface { Match(casenil Function[Nil[a], any], casecons Function[Cons[a], any]) any } -type Nil[a any] struct{ +type Nil[a any] struct { } func (xs Nil[a]) Match(casenil Function[Nil[a], any], casecons Function[Cons[a], any]) any { @@ -67,7 +67,7 @@ func (xs Cons[a]) Match(casenil Function[Nil[a], any], casecons Function[Cons[a] return casecons.Apply(xs) } -type mapNil[a, b any] struct{ +type mapNil[a, b any] struct { } func (m mapNil[a, b]) Apply(_ Nil[a]) any { diff --git a/test/typeparam/dictionaryCapture-noinline.go b/test/typeparam/dictionaryCapture-noinline.go index 4b46d5f57f..ad5bfa008e 100644 --- a/test/typeparam/dictionaryCapture-noinline.go +++ b/test/typeparam/dictionaryCapture-noinline.go @@ -44,7 +44,7 @@ func is7(x int) { } func is77(x, y int) { if x != 7 || y != 7 { - println(x,y) + println(x, y) panic("assertion failed") } } @@ -63,7 +63,7 @@ func (x s[T]) g2() (T, T) { } func methodExpressions() { - x := s[int]{a:7} + x := s[int]{a: 7} f0 := s[int].g0 f0(x) f1 := s[int].g1 @@ -73,7 +73,7 @@ func methodExpressions() { } func methodValues() { - x := s[int]{a:7} + x := s[int]{a: 7} f0 := x.g0 f0() f1 := x.g1 @@ -82,20 +82,20 @@ func methodValues() { is77(f2()) } -var x interface{ +var x interface { g0() - g1()int - g2()(int,int) -} = s[int]{a:7} -var y interface{} = s[int]{a:7} + g1() int + g2() (int, int) +} = s[int]{a: 7} +var y interface{} = s[int]{a: 7} func interfaceMethods() { x.g0() is7(x.g1()) is77(x.g2()) - y.(interface{g0()}).g0() - is7(y.(interface{g1()int}).g1()) - is77(y.(interface{g2()(int,int)}).g2()) + y.(interface{ g0() }).g0() + is7(y.(interface{ g1() int }).g1()) + is77(y.(interface{ g2() (int, int) }).g2()) } // Also check for instantiations outside functions. @@ -107,7 +107,7 @@ var hh0 = s[int].g0 var hh1 = s[int].g1 var hh2 = s[int].g2 -var xtop = s[int]{a:7} +var xtop = s[int]{a: 7} var ii0 = x.g0 var ii1 = x.g1 var ii2 = x.g2 @@ -116,7 +116,7 @@ func globals() { gg0(7) is7(gg1(7)) is77(gg2(7)) - x := s[int]{a:7} + x := s[int]{a: 7} hh0(x) is7(hh1(x)) is77(hh2(x)) diff --git a/test/typeparam/dictionaryCapture.go b/test/typeparam/dictionaryCapture.go index 26af7a09b0..7c7948145a 100644 --- a/test/typeparam/dictionaryCapture.go +++ b/test/typeparam/dictionaryCapture.go @@ -51,7 +51,7 @@ func is7(x int) { } func is77(x, y int) { if x != 7 || y != 7 { - println(x,y) + println(x, y) panic("assertion failed") } } @@ -70,7 +70,7 @@ func (x s[T]) g2() (T, T) { } func methodExpressions() { - x := s[int]{a:7} + x := s[int]{a: 7} f0 := s[int].g0 f0(x) f0p := (*s[int]).g0 @@ -106,7 +106,7 @@ func genMethodExpressions[T comparable](want T) { } func methodValues() { - x := s[int]{a:7} + x := s[int]{a: 7} f0 := x.g0 f0() f1 := x.g1 @@ -129,20 +129,20 @@ func genMethodValues[T comparable](want T) { } } -var x interface{ +var x interface { g0() - g1()int - g2()(int,int) -} = s[int]{a:7} -var y interface{} = s[int]{a:7} + g1() int + g2() (int, int) +} = s[int]{a: 7} +var y interface{} = s[int]{a: 7} func interfaceMethods() { x.g0() is7(x.g1()) is77(x.g2()) - y.(interface{g0()}).g0() - is7(y.(interface{g1()int}).g1()) - is77(y.(interface{g2()(int,int)}).g2()) + y.(interface{ g0() }).g0() + is7(y.(interface{ g1() int }).g1()) + is77(y.(interface{ g2() (int, int) }).g2()) } // Also check for instantiations outside functions. @@ -154,7 +154,7 @@ var hh0 = s[int].g0 var hh1 = s[int].g1 var hh2 = s[int].g2 -var xtop = s[int]{a:7} +var xtop = s[int]{a: 7} var ii0 = x.g0 var ii1 = x.g1 var ii2 = x.g2 @@ -163,7 +163,7 @@ func globals() { gg0(7) is7(gg1(7)) is77(gg2(7)) - x := s[int]{a:7} + x := s[int]{a: 7} hh0(x) is7(hh1(x)) is77(hh2(x)) @@ -172,7 +172,6 @@ func globals() { is77(ii2()) } - func recursive() { if got, want := recur1[int](5), 110; got != want { panic(fmt.Sprintf("recur1[int](5) = %d, want = %d", got, want)) @@ -187,14 +186,14 @@ func recur1[T Integer](n T) T { if n == 0 || n == 1 { return T(1) } else { - return n * recur2(n - 1) + return n * recur2(n-1) } } func recur2[T Integer](n T) T { list := make([]T, n) for i, _ := range list { - list[i] = T(i+1) + list[i] = T(i + 1) } var sum T for _, elt := range list { diff --git a/test/typeparam/dottype.go b/test/typeparam/dottype.go index 0131f64202..89a9b02111 100644 --- a/test/typeparam/dottype.go +++ b/test/typeparam/dottype.go @@ -36,20 +36,20 @@ func g2[T I](x I) (T, bool) { return t, ok } -func h[T any](x interface{}) struct{a, b T} { - return x.(struct{a, b T}) +func h[T any](x interface{}) struct{ a, b T } { + return x.(struct{ a, b T }) } -func k[T any](x interface{}) interface { bar() T } { - return x.(interface{bar() T }) +func k[T any](x interface{}) interface{ bar() T } { + return x.(interface{ bar() T }) } type mybar int + func (x mybar) bar() int { return int(x) } - func main() { var i interface{} = int(3) var j I = myint(3) @@ -66,7 +66,7 @@ func main() { println(g2[myint](j)) println(g2[myint](y)) - println(h[int](struct{a, b int}{3, 5}).a) + println(h[int](struct{ a, b int }{3, 5}).a) println(k[int](mybar(3)).bar()) } diff --git a/test/typeparam/double.go b/test/typeparam/double.go index 6652613814..6ddb6b2d08 100644 --- a/test/typeparam/double.go +++ b/test/typeparam/double.go @@ -44,29 +44,29 @@ func main() { want := MySlice{2, 4, 6} got := _DoubleElems[MySlice, int](arg) if !reflect.DeepEqual(got, want) { - panic(fmt.Sprintf("got %s, want %s", got, want)) + panic(fmt.Sprintf("got %s, want %s", got, want)) } // constraint type inference got = _DoubleElems[MySlice](arg) if !reflect.DeepEqual(got, want) { - panic(fmt.Sprintf("got %s, want %s", got, want)) + panic(fmt.Sprintf("got %s, want %s", got, want)) } got = _DoubleElems(arg) if !reflect.DeepEqual(got, want) { - panic(fmt.Sprintf("got %s, want %s", got, want)) + panic(fmt.Sprintf("got %s, want %s", got, want)) } farg := MyFloatSlice{1.2, 2.0, 3.5} fwant := MyFloatSlice{2.4, 4.0, 7.0} fgot := _DoubleElems(farg) if !reflect.DeepEqual(fgot, fwant) { - panic(fmt.Sprintf("got %s, want %s", fgot, fwant)) + panic(fmt.Sprintf("got %s, want %s", fgot, fwant)) } fgot = _DoubleElems2(farg) if !reflect.DeepEqual(fgot, fwant) { - panic(fmt.Sprintf("got %s, want %s", fgot, fwant)) + panic(fmt.Sprintf("got %s, want %s", fgot, fwant)) } } diff --git a/test/typeparam/equal.go b/test/typeparam/equal.go index 6776b19d12..a1d3e8ae02 100644 --- a/test/typeparam/equal.go +++ b/test/typeparam/equal.go @@ -40,7 +40,7 @@ func (x myint) foo() { func k[T comparable](t T, i interface{}) bool { // Compare derived type value to interface. - return struct{a, b T}{t, t} == i + return struct{ a, b T }{t, t} == i } func main() { @@ -51,21 +51,19 @@ func main() { assert(h(myint(3), myint(3))) assert(!h(myint(3), myint(5))) - type S struct { a, b float64 } + type S struct{ a, b float64 } - assert(f(S{3,5}, S{3,5})) - assert(!f(S{3,5}, S{4,6})) - assert(g(S{3,5}, S{3,5})) - assert(!g(S{3,5}, S{4,6})) + assert(f(S{3, 5}, S{3, 5})) + assert(!f(S{3, 5}, S{4, 6})) + assert(g(S{3, 5}, S{3, 5})) + assert(!g(S{3, 5}, S{4, 6})) - assert(k(3, struct{a, b int}{3, 3})) - assert(!k(3, struct{a, b int}{3, 4})) + assert(k(3, struct{ a, b int }{3, 3})) + assert(!k(3, struct{ a, b int }{3, 4})) } -func assert(b bool) { +func assert(b bool) { if !b { panic("assertion failed") } } - - diff --git a/test/typeparam/fact.go b/test/typeparam/fact.go index baa7fbc68e..e19cfe6956 100644 --- a/test/typeparam/fact.go +++ b/test/typeparam/fact.go @@ -8,11 +8,11 @@ package main import "fmt" -func fact[T interface { ~int | ~int64 | ~float64 }](n T) T { +func fact[T interface{ ~int | ~int64 | ~float64 }](n T) T { if n == 1 { return 1 } - return n * fact(n - 1) + return n * fact(n-1) } func main() { diff --git a/test/typeparam/factimp.dir/a.go b/test/typeparam/factimp.dir/a.go index cb1ff2615b..0bd73a88e7 100644 --- a/test/typeparam/factimp.dir/a.go +++ b/test/typeparam/factimp.dir/a.go @@ -4,9 +4,9 @@ package a -func Fact[T interface { int | int64 | float64 }](n T) T { +func Fact[T interface{ int | int64 | float64 }](n T) T { if n == 1 { return 1 } - return n * Fact(n - 1) + return n * Fact(n-1) } diff --git a/test/typeparam/graph.go b/test/typeparam/graph.go index f2a2630ad0..cecf349a9a 100644 --- a/test/typeparam/graph.go +++ b/test/typeparam/graph.go @@ -225,7 +225,6 @@ func TestShortestPath() { } } - func main() { TestShortestPath() } diff --git a/test/typeparam/ifaceconv.go b/test/typeparam/ifaceconv.go index f4023366b9..ee3a9e0dc3 100644 --- a/test/typeparam/ifaceconv.go +++ b/test/typeparam/ifaceconv.go @@ -37,11 +37,11 @@ type C interface { type myInt int func (x myInt) foo() int { - return int(x+1) + return int(x + 1) } -func h[T C](x T) interface{foo() int} { - var i interface{foo()int} = x +func h[T C](x T) interface{ foo() int } { + var i interface{ foo() int } = x return i } func i[T C](x T) C { diff --git a/test/typeparam/index.go b/test/typeparam/index.go index 80824efac3..906f76d325 100644 --- a/test/typeparam/index.go +++ b/test/typeparam/index.go @@ -79,4 +79,3 @@ func main() { panic(fmt.Sprintf("got %d, want %d", got, want)) } } - diff --git a/test/typeparam/interfacearg.go b/test/typeparam/interfacearg.go index 1d19499318..28ea3e3afb 100644 --- a/test/typeparam/interfacearg.go +++ b/test/typeparam/interfacearg.go @@ -23,9 +23,11 @@ func F() { // Testing the various combinations of method expressions. type S1 struct{} + func (*S1) M() {} type S2 struct{} + func (S2) M() {} func _F1[T interface{ M() }](t T) { diff --git a/test/typeparam/issue39755.go b/test/typeparam/issue39755.go index 13a575d16f..c4b6902eea 100644 --- a/test/typeparam/issue39755.go +++ b/test/typeparam/issue39755.go @@ -8,14 +8,14 @@ package p -func _[T interface{~map[string]int}](x T) { +func _[T interface{ ~map[string]int }](x T) { _ = x == nil } // simplified test case from issue type PathParamsConstraint interface { - ~map[string]string | ~[]struct{key, value string} + ~map[string]string | ~[]struct{ key, value string } } type PathParams[T PathParamsConstraint] struct { diff --git a/test/typeparam/issue44688.go b/test/typeparam/issue44688.go index de1140b67c..5ebce72628 100644 --- a/test/typeparam/issue44688.go +++ b/test/typeparam/issue44688.go @@ -8,7 +8,7 @@ package main -type A1[T any] struct{ +type A1[T any] struct { val T } diff --git a/test/typeparam/issue45817.go b/test/typeparam/issue45817.go index 744698f40b..1efee3b0af 100644 --- a/test/typeparam/issue45817.go +++ b/test/typeparam/issue45817.go @@ -13,11 +13,12 @@ import ( type s[T any] struct { a T } + func (x s[T]) f() T { return x.a } func main() { - x := s[int]{a:7} + x := s[int]{a: 7} f := x.f if got, want := f(), 7; got != want { panic(fmt.Sprintf("got %d, want %d", got, want)) diff --git a/test/typeparam/issue46472.go b/test/typeparam/issue46472.go index bab48e7d2f..cd4d923ef5 100644 --- a/test/typeparam/issue46472.go +++ b/test/typeparam/issue46472.go @@ -10,7 +10,7 @@ func foo[T any](d T) { switch v := interface{}(d).(type) { case string: if v != "x" { - panic("unexpected v: "+v) + panic("unexpected v: " + v) } } diff --git a/test/typeparam/issue47258.go b/test/typeparam/issue47258.go index 76629f7424..717329471e 100644 --- a/test/typeparam/issue47258.go +++ b/test/typeparam/issue47258.go @@ -11,7 +11,7 @@ import ( ) type Numeric interface { - int32|int64|float64|complex64 + int32 | int64 | float64 | complex64 } //go:noline diff --git a/test/typeparam/list.go b/test/typeparam/list.go index c63c9bff79..adfe72f1de 100644 --- a/test/typeparam/list.go +++ b/test/typeparam/list.go @@ -11,10 +11,10 @@ import ( ) type Ordered interface { - ~int | ~int8 | ~int16 | ~int32 | ~int64 | - ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | - ~float32 | ~float64 | - ~string + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 | + ~string } // _List is a linked list of ordered values of type T. @@ -34,9 +34,9 @@ func (l *_List[T]) Largest() T { } type OrderedNum interface { - ~int | ~int8 | ~int16 | ~int32 | ~int64 | - ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | - ~float32 | ~float64 + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 } // _ListNum is a linked _List of ordered numeric values of type T. @@ -64,40 +64,40 @@ func main() { i2 := &_List[int]{i3, 3} i1 := &_List[int]{i2, 2} if got, want := i1.Largest(), 3; got != want { - panic(fmt.Sprintf("got %d, want %d", got, want)) + panic(fmt.Sprintf("got %d, want %d", got, want)) } b3 := &_List[byte]{nil, byte(1)} b2 := &_List[byte]{b3, byte(3)} b1 := &_List[byte]{b2, byte(2)} if got, want := b1.Largest(), byte(3); got != want { - panic(fmt.Sprintf("got %d, want %d", got, want)) + panic(fmt.Sprintf("got %d, want %d", got, want)) } f3 := &_List[float64]{nil, 13.5} f2 := &_List[float64]{f3, 1.2} f1 := &_List[float64]{f2, 4.5} if got, want := f1.Largest(), 13.5; got != want { - panic(fmt.Sprintf("got %f, want %f", got, want)) + panic(fmt.Sprintf("got %f, want %f", got, want)) } s3 := &_List[string]{nil, "dd"} s2 := &_List[string]{s3, "aa"} s1 := &_List[string]{s2, "bb"} if got, want := s1.Largest(), "dd"; got != want { - panic(fmt.Sprintf("got %s, want %s", got, want)) + panic(fmt.Sprintf("got %s, want %s", got, want)) } j3 := &_ListNum[int]{nil, 1} j2 := &_ListNum[int]{j3, 32} j1 := &_ListNum[int]{j2, 2} if got, want := j1.ClippedLargest(), 2; got != want { - panic(fmt.Sprintf("got %d, want %d", got, want)) + panic(fmt.Sprintf("got %d, want %d", got, want)) } g3 := &_ListNum[float64]{nil, 13.5} g2 := &_ListNum[float64]{g3, 1.2} g1 := &_ListNum[float64]{g2, 4.5} if got, want := g1.ClippedLargest(), 4.5; got != want { - panic(fmt.Sprintf("got %f, want %f", got, want)) + panic(fmt.Sprintf("got %f, want %f", got, want)) } } diff --git a/test/typeparam/list2.go b/test/typeparam/list2.go index 32023cf319..e7f346c78e 100644 --- a/test/typeparam/list2.go +++ b/test/typeparam/list2.go @@ -50,7 +50,7 @@ func (e *_Element[T]) Prev() *_Element[T] { // The zero value for _List is an empty list ready to use. type _List[T any] struct { root _Element[T] // sentinel list element, only &root, root.prev, and root.next are used - len int // current list length excluding (this) sentinel element + len int // current list length excluding (this) sentinel element } // Init initializes or clears list l. @@ -594,7 +594,6 @@ func TestTransform() { checkList(l2, []interface{}{"1", "2"}) } - func main() { TestList() TestExtending() @@ -607,4 +606,3 @@ func main() { TestInsertAfterUnknownMark() TestTransform() } - diff --git a/test/typeparam/listimp.dir/a.go b/test/typeparam/listimp.dir/a.go index 2b5b23cde3..bf1641af9c 100644 --- a/test/typeparam/listimp.dir/a.go +++ b/test/typeparam/listimp.dir/a.go @@ -5,49 +5,49 @@ package a type Ordered interface { - ~int | ~int8 | ~int16 | ~int32 | ~int64 | - ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | - ~float32 | ~float64 | - ~string + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 | + ~string } // List is a linked list of ordered values of type T. type List[T Ordered] struct { - Next *List[T] - Val T + Next *List[T] + Val T } func (l *List[T]) Largest() T { - var max T - for p := l; p != nil; p = p.Next { - if p.Val > max { - max = p.Val - } - } - return max + var max T + for p := l; p != nil; p = p.Next { + if p.Val > max { + max = p.Val + } + } + return max } type OrderedNum interface { - ~int | ~int8 | ~int16 | ~int32 | ~int64 | - ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | - ~float32 | ~float64 + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 } // ListNum is a linked _List of ordered numeric values of type T. type ListNum[T OrderedNum] struct { - Next *ListNum[T] - Val T + Next *ListNum[T] + Val T } const Clip = 5 // clippedLargest returns the largest in the list of OrderNums, but a max of 5. func (l *ListNum[T]) ClippedLargest() T { - var max T - for p := l; p != nil; p = p.Next { - if p.Val > max && p.Val < Clip { - max = p.Val - } - } - return max + var max T + for p := l; p != nil; p = p.Next { + if p.Val > max && p.Val < Clip { + max = p.Val + } + } + return max } diff --git a/test/typeparam/listimp.dir/main.go b/test/typeparam/listimp.dir/main.go index d43ad508be..985ff59a18 100644 --- a/test/typeparam/listimp.dir/main.go +++ b/test/typeparam/listimp.dir/main.go @@ -10,43 +10,43 @@ import ( ) func main() { - i3 := &a.List[int]{nil, 1} - i2 := &a.List[int]{i3, 3} - i1 := &a.List[int]{i2, 2} - if got, want := i1.Largest(), 3; got != want { - panic(fmt.Sprintf("got %d, want %d", got, want)) - } + i3 := &a.List[int]{nil, 1} + i2 := &a.List[int]{i3, 3} + i1 := &a.List[int]{i2, 2} + if got, want := i1.Largest(), 3; got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } - b3 := &a.List[byte]{nil, byte(1)} - b2 := &a.List[byte]{b3, byte(3)} - b1 := &a.List[byte]{b2, byte(2)} - if got, want := b1.Largest(), byte(3); got != want { - panic(fmt.Sprintf("got %d, want %d", got, want)) - } + b3 := &a.List[byte]{nil, byte(1)} + b2 := &a.List[byte]{b3, byte(3)} + b1 := &a.List[byte]{b2, byte(2)} + if got, want := b1.Largest(), byte(3); got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } - f3 := &a.List[float64]{nil, 13.5} - f2 := &a.List[float64]{f3, 1.2} - f1 := &a.List[float64]{f2, 4.5} - if got, want := f1.Largest(), 13.5; got != want { - panic(fmt.Sprintf("got %f, want %f", got, want)) - } + f3 := &a.List[float64]{nil, 13.5} + f2 := &a.List[float64]{f3, 1.2} + f1 := &a.List[float64]{f2, 4.5} + if got, want := f1.Largest(), 13.5; got != want { + panic(fmt.Sprintf("got %f, want %f", got, want)) + } - s3 := &a.List[string]{nil, "dd"} - s2 := &a.List[string]{s3, "aa"} - s1 := &a.List[string]{s2, "bb"} - if got, want := s1.Largest(), "dd"; got != want { - panic(fmt.Sprintf("got %s, want %s", got, want)) - } - j3 := &a.ListNum[int]{nil, 1} - j2 := &a.ListNum[int]{j3, 32} - j1 := &a.ListNum[int]{j2, 2} - if got, want := j1.ClippedLargest(), 2; got != want { - panic(fmt.Sprintf("got %d, want %d", got, want)) - } - g3 := &a.ListNum[float64]{nil, 13.5} - g2 := &a.ListNum[float64]{g3, 1.2} - g1 := &a.ListNum[float64]{g2, 4.5} - if got, want := g1.ClippedLargest(), 4.5; got != want { - panic(fmt.Sprintf("got %f, want %f", got, want)) - } + s3 := &a.List[string]{nil, "dd"} + s2 := &a.List[string]{s3, "aa"} + s1 := &a.List[string]{s2, "bb"} + if got, want := s1.Largest(), "dd"; got != want { + panic(fmt.Sprintf("got %s, want %s", got, want)) + } + j3 := &a.ListNum[int]{nil, 1} + j2 := &a.ListNum[int]{j3, 32} + j1 := &a.ListNum[int]{j2, 2} + if got, want := j1.ClippedLargest(), 2; got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } + g3 := &a.ListNum[float64]{nil, 13.5} + g2 := &a.ListNum[float64]{g3, 1.2} + g1 := &a.ListNum[float64]{g2, 4.5} + if got, want := g1.ClippedLargest(), 4.5; got != want { + panic(fmt.Sprintf("got %f, want %f", got, want)) + } } diff --git a/test/typeparam/listimp2.dir/a.go b/test/typeparam/listimp2.dir/a.go index 76ad669767..3a7dfc3999 100644 --- a/test/typeparam/listimp2.dir/a.go +++ b/test/typeparam/listimp2.dir/a.go @@ -44,7 +44,7 @@ func (e *Element[T]) Prev() *Element[T] { // The zero value for List is an empty list ready to use. type List[T any] struct { root Element[T] // sentinel list element, only &root, root.prev, and root.next are used - len int // current list length excluding (this) sentinel element + len int // current list length excluding (this) sentinel element } // Init initializes or clears list l. diff --git a/test/typeparam/listimp2.dir/main.go b/test/typeparam/listimp2.dir/main.go index 0c2c38e399..226e1a9a57 100644 --- a/test/typeparam/listimp2.dir/main.go +++ b/test/typeparam/listimp2.dir/main.go @@ -301,7 +301,6 @@ func TestTransform() { checkList(l2, []interface{}{"1", "2"}) } - func main() { TestList() TestExtending() diff --git a/test/typeparam/lockable.go b/test/typeparam/lockable.go index 9372c76b4d..9b20d87bb7 100644 --- a/test/typeparam/lockable.go +++ b/test/typeparam/lockable.go @@ -11,7 +11,7 @@ import "sync" // A Lockable is a value that may be safely simultaneously accessed // from multiple goroutines via the Get and Set methods. type Lockable[T any] struct { - x T + x T mu sync.Mutex } diff --git a/test/typeparam/mapimp.dir/a.go b/test/typeparam/mapimp.dir/a.go index 6835e214b8..cbfa80ac6b 100644 --- a/test/typeparam/mapimp.dir/a.go +++ b/test/typeparam/mapimp.dir/a.go @@ -7,9 +7,9 @@ package a // Map calls the function f on every element of the slice s, // returning a new slice of the results. func Mapper[F, T any](s []F, f func(F) T) []T { - r := make([]T, len(s)) - for i, v := range s { - r[i] = f(v) - } - return r + r := make([]T, len(s)) + for i, v := range s { + r[i] = f(v) + } + return r } diff --git a/test/typeparam/mincheck.dir/a.go b/test/typeparam/mincheck.dir/a.go index 7d42492b74..fa0f249e61 100644 --- a/test/typeparam/mincheck.dir/a.go +++ b/test/typeparam/mincheck.dir/a.go @@ -5,12 +5,12 @@ package a type Ordered interface { - int | int64 | float64 + int | int64 | float64 } func Min[T Ordered](x, y T) T { - if x < y { - return x - } - return y + if x < y { + return x + } + return y } diff --git a/test/typeparam/minimp.dir/a.go b/test/typeparam/minimp.dir/a.go index 6c3e0eba36..fabde62c5d 100644 --- a/test/typeparam/minimp.dir/a.go +++ b/test/typeparam/minimp.dir/a.go @@ -5,12 +5,12 @@ package a type Ordered interface { - ~int | ~int64 | ~float64 | ~string + ~int | ~int64 | ~float64 | ~string } func Min[T Ordered](x, y T) T { - if x < y { - return x - } - return y + if x < y { + return x + } + return y } diff --git a/test/typeparam/mutualimp.dir/a.go b/test/typeparam/mutualimp.dir/a.go index 56ca57cea5..5b924d3ce5 100644 --- a/test/typeparam/mutualimp.dir/a.go +++ b/test/typeparam/mutualimp.dir/a.go @@ -5,7 +5,8 @@ package a type X int + func (x X) M() X { return x } func F[T interface{ M() U }, U interface{ M() T }]() {} -func G() { F[X, X]() } +func G() { F[X, X]() } diff --git a/test/typeparam/ordered.go b/test/typeparam/ordered.go index 699505ec75..0f539d659c 100644 --- a/test/typeparam/ordered.go +++ b/test/typeparam/ordered.go @@ -13,15 +13,15 @@ import ( ) type Ordered interface { - ~int | ~int8 | ~int16 | ~int32 | ~int64 | - ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | - ~float32 | ~float64 | - ~string + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 | + ~string } type orderedSlice[Elem Ordered] []Elem -func (s orderedSlice[Elem]) Len() int { return len(s) } +func (s orderedSlice[Elem]) Len() int { return len(s) } func (s orderedSlice[Elem]) Less(i, j int) bool { if s[i] < s[j] { return true @@ -32,7 +32,7 @@ func (s orderedSlice[Elem]) Less(i, j int) bool { } return false } -func (s orderedSlice[Elem]) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s orderedSlice[Elem]) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func _OrderedSlice[Elem Ordered](s []Elem) { sort.Sort(orderedSlice[Elem](s)) @@ -68,7 +68,7 @@ func testOrdered[Elem Ordered](name string, s []Elem, sorter func([]Elem)) bool } for i := len(s1) - 1; i > 0; i-- { if s1[i] < s1[i-1] { - fmt.Printf("%s: element %d (%v) < element %d (%v)", name, i, s1[i], i - 1, s1[i - 1]) + fmt.Printf("%s: element %d (%v) < element %d (%v)", name, i, s1[i], i-1, s1[i-1]) ok = false } } diff --git a/test/typeparam/orderedmap.go b/test/typeparam/orderedmap.go index 6a895bd396..1f077333b8 100644 --- a/test/typeparam/orderedmap.go +++ b/test/typeparam/orderedmap.go @@ -15,10 +15,10 @@ import ( ) type Ordered interface { - ~int | ~int8 | ~int16 | ~int32 | ~int64 | - ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | - ~float32 | ~float64 | - ~string + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 | + ~string } // _Map is an ordered map. @@ -230,7 +230,7 @@ func _Ranger[Elem any]() (*_Sender[Elem], *_Receiver[Elem]) { values: c, done: d, } - r := &_Receiver[Elem] { + r := &_Receiver[Elem]{ values: c, done: d, } diff --git a/test/typeparam/orderedmapsimp.dir/a.go b/test/typeparam/orderedmapsimp.dir/a.go index 37fc3e79b9..d6a2de5d7b 100644 --- a/test/typeparam/orderedmapsimp.dir/a.go +++ b/test/typeparam/orderedmapsimp.dir/a.go @@ -10,10 +10,10 @@ import ( ) type Ordered interface { - ~int | ~int8 | ~int16 | ~int32 | ~int64 | - ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | - ~float32 | ~float64 | - ~string + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 | + ~string } // Map is an ordered map. @@ -170,7 +170,7 @@ func Ranger[Elem any]() (*Sender[Elem], *Receiver[Elem]) { values: c, done: d, } - r := &Receiver[Elem] { + r := &Receiver[Elem]{ values: c, done: d, } diff --git a/test/typeparam/orderedmapsimp.dir/main.go b/test/typeparam/orderedmapsimp.dir/main.go index ac4cee6a78..978f1e763c 100644 --- a/test/typeparam/orderedmapsimp.dir/main.go +++ b/test/typeparam/orderedmapsimp.dir/main.go @@ -17,7 +17,7 @@ func TestMap() { panic(fmt.Sprintf("unexpectedly found %q in empty map", []byte("a"))) } - for _, c := range []int{ 'a', 'c', 'b' } { + for _, c := range []int{'a', 'c', 'b'} { if !m.Insert([]byte(string(c)), c) { panic(fmt.Sprintf("key %q unexpectedly already present", []byte(string(c)))) } diff --git a/test/typeparam/pair.go b/test/typeparam/pair.go index 57742022b1..c1427b9c52 100644 --- a/test/typeparam/pair.go +++ b/test/typeparam/pair.go @@ -25,7 +25,10 @@ func main() { panic(fmt.Sprintf("unexpected f2 size == %d, want %d", got, want)) } - type mypair struct { f1 int32; f2 int64 } + type mypair struct { + f1 int32 + f2 int64 + } mp := mypair(p) if mp.f1 != 1 || mp.f2 != 2 { panic(fmt.Sprintf("mp == %#v, want %#v", mp, mypair{1, 2})) diff --git a/test/typeparam/pairimp.dir/a.go b/test/typeparam/pairimp.dir/a.go index 27b2412961..a984fba37b 100644 --- a/test/typeparam/pairimp.dir/a.go +++ b/test/typeparam/pairimp.dir/a.go @@ -5,6 +5,6 @@ package a type Pair[F1, F2 any] struct { - Field1 F1 - Field2 F2 + Field1 F1 + Field2 F2 } diff --git a/test/typeparam/pairimp.dir/main.go b/test/typeparam/pairimp.dir/main.go index fc2face81d..027fdd9ce7 100644 --- a/test/typeparam/pairimp.dir/main.go +++ b/test/typeparam/pairimp.dir/main.go @@ -11,17 +11,20 @@ import ( ) func main() { - p := a.Pair[int32, int64]{1, 2} - if got, want := unsafe.Sizeof(p.Field1), uintptr(4); got != want { - panic(fmt.Sprintf("unexpected f1 size == %d, want %d", got, want)) - } - if got, want := unsafe.Sizeof(p.Field2), uintptr(8); got != want { - panic(fmt.Sprintf("unexpected f2 size == %d, want %d", got, want)) - } + p := a.Pair[int32, int64]{1, 2} + if got, want := unsafe.Sizeof(p.Field1), uintptr(4); got != want { + panic(fmt.Sprintf("unexpected f1 size == %d, want %d", got, want)) + } + if got, want := unsafe.Sizeof(p.Field2), uintptr(8); got != want { + panic(fmt.Sprintf("unexpected f2 size == %d, want %d", got, want)) + } - type mypair struct { Field1 int32; Field2 int64 } - mp := mypair(p) - if mp.Field1 != 1 || mp.Field2 != 2 { - panic(fmt.Sprintf("mp == %#v, want %#v", mp, mypair{1, 2})) - } + type mypair struct { + Field1 int32 + Field2 int64 + } + mp := mypair(p) + if mp.Field1 != 1 || mp.Field2 != 2 { + panic(fmt.Sprintf("mp == %#v, want %#v", mp, mypair{1, 2})) + } } diff --git a/test/typeparam/sets.go b/test/typeparam/sets.go index 258514489e..4f07b590e3 100644 --- a/test/typeparam/sets.go +++ b/test/typeparam/sets.go @@ -160,7 +160,7 @@ func TestSet() { vals := s1.Values() sort.Ints(vals) w1 := []int{1, 2, 3, 4} - if !_SliceEqual(vals, w1) { + if !_SliceEqual(vals, w1) { panic(fmt.Sprintf("(%v).Values() == %v, want %v", s1, vals, w1)) } } diff --git a/test/typeparam/settable.go b/test/typeparam/settable.go index d0b831b533..99455e93fa 100644 --- a/test/typeparam/settable.go +++ b/test/typeparam/settable.go @@ -44,7 +44,6 @@ func fromStrings1a[T any, PT Setter[T]](s []string) []PT { return result } - // Takes one type parameter and a set function func fromStrings2[T any](s []string, set func(*T, string)) []T { results := make([]T, len(s)) diff --git a/test/typeparam/sliceimp.dir/a.go b/test/typeparam/sliceimp.dir/a.go index 61b1b17a98..da12e9f9fc 100644 --- a/test/typeparam/sliceimp.dir/a.go +++ b/test/typeparam/sliceimp.dir/a.go @@ -5,26 +5,26 @@ package a type Ordered interface { - ~int | ~int8 | ~int16 | ~int32 | ~int64 | - ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | - ~float32 | ~float64 | - ~string + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 | + ~string } // Max returns the maximum of two values of some ordered type. func Max[T Ordered](a, b T) T { - if a > b { - return a - } - return b + if a > b { + return a + } + return b } // Min returns the minimum of two values of some ordered type. func Min[T Ordered](a, b T) T { - if a < b { - return a - } - return b + if a < b { + return a + } + return b } // Equal reports whether two slices are equal: the same length and all @@ -121,7 +121,7 @@ func Append[T any](s []T, t ...T) []T { if tot <= cap(s) { s = s[:tot] } else { - news := make([]T, tot, tot + tot/2) + news := make([]T, tot, tot+tot/2) Copy(news, s) s = news } diff --git a/test/typeparam/sliceimp.dir/main.go b/test/typeparam/sliceimp.dir/main.go index 2d4d3b2831..0f79e10018 100644 --- a/test/typeparam/sliceimp.dir/main.go +++ b/test/typeparam/sliceimp.dir/main.go @@ -12,42 +12,42 @@ import ( ) type Integer interface { - ~int | ~int8 | ~int16 | ~int32 | ~int64 | - ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr } func TestEqual() { - s1 := []int{1, 2, 3} - if !a.Equal(s1, s1) { - panic(fmt.Sprintf("a.Equal(%v, %v) = false, want true", s1, s1)) - } - s2 := []int{1, 2, 3} - if !a.Equal(s1, s2) { - panic(fmt.Sprintf("a.Equal(%v, %v) = false, want true", s1, s2)) - } - s2 = append(s2, 4) - if a.Equal(s1, s2) { - panic(fmt.Sprintf("a.Equal(%v, %v) = true, want false", s1, s2)) - } - - s3 := []float64{1, 2, math.NaN()} - if !a.Equal(s3, s3) { - panic(fmt.Sprintf("a.Equal(%v, %v) = false, want true", s3, s3)) - } - - if a.Equal(s1, nil) { - panic(fmt.Sprintf("a.Equal(%v, nil) = true, want false", s1)) - } - if a.Equal(nil, s1) { - panic(fmt.Sprintf("a.Equal(nil, %v) = true, want false", s1)) - } - if !a.Equal(s1[:0], nil) { - panic(fmt.Sprintf("a.Equal(%v, nil = false, want true", s1[:0])) - } + s1 := []int{1, 2, 3} + if !a.Equal(s1, s1) { + panic(fmt.Sprintf("a.Equal(%v, %v) = false, want true", s1, s1)) + } + s2 := []int{1, 2, 3} + if !a.Equal(s1, s2) { + panic(fmt.Sprintf("a.Equal(%v, %v) = false, want true", s1, s2)) + } + s2 = append(s2, 4) + if a.Equal(s1, s2) { + panic(fmt.Sprintf("a.Equal(%v, %v) = true, want false", s1, s2)) + } + + s3 := []float64{1, 2, math.NaN()} + if !a.Equal(s3, s3) { + panic(fmt.Sprintf("a.Equal(%v, %v) = false, want true", s3, s3)) + } + + if a.Equal(s1, nil) { + panic(fmt.Sprintf("a.Equal(%v, nil) = true, want false", s1)) + } + if a.Equal(nil, s1) { + panic(fmt.Sprintf("a.Equal(nil, %v) = true, want false", s1)) + } + if !a.Equal(s1[:0], nil) { + panic(fmt.Sprintf("a.Equal(%v, nil = false, want true", s1[:0])) + } } func offByOne[Elem Integer](a, b Elem) bool { - return a == b + 1 || a == b - 1 + return a == b+1 || a == b-1 } func TestEqualFn() { @@ -92,12 +92,12 @@ func TestMap() { func TestReduce() { s1 := []int{1, 2, 3} - r := a.Reduce(s1, 0, func(f float64, i int) float64 { return float64(i) * 2.5 + f }) + r := a.Reduce(s1, 0, func(f float64, i int) float64 { return float64(i)*2.5 + f }) if want := 15.0; r != want { panic(fmt.Sprintf("a.Reduce(%v, 0, ...) = %v, want %v", s1, r, want)) } - if got := a.Reduce(nil, 0, func(i, j int) int { return i + j}); got != 0 { + if got := a.Reduce(nil, 0, func(i, j int) int { return i + j }); got != 0 { panic(fmt.Sprintf("a.Reduce(nil, 0, add) = %v, want 0", got)) } } diff --git a/test/typeparam/slices.go b/test/typeparam/slices.go index 50783a5439..b5e8e0c606 100644 --- a/test/typeparam/slices.go +++ b/test/typeparam/slices.go @@ -15,31 +15,31 @@ import ( ) type Ordered interface { - ~int | ~int8 | ~int16 | ~int32 | ~int64 | - ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | - ~float32 | ~float64 | - ~string + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 | + ~string } type Integer interface { - ~int | ~int8 | ~int16 | ~int32 | ~int64 | - ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr } // Max returns the maximum of two values of some ordered type. func _Max[T Ordered](a, b T) T { - if a > b { - return a - } - return b + if a > b { + return a + } + return b } // Min returns the minimum of two values of some ordered type. func _Min[T Ordered](a, b T) T { - if a < b { - return a - } - return b + if a < b { + return a + } + return b } // _Equal reports whether two slices are equal: the same length and all @@ -136,7 +136,7 @@ func _Append[T any](s []T, t ...T) []T { if tot <= cap(s) { s = s[:tot] } else { - news := make([]T, tot, tot + tot/2) + news := make([]T, tot, tot+tot/2) _Copy(news, s) s = news } @@ -156,37 +156,37 @@ func _Copy[T any](s, t []T) int { } func TestEqual() { - s1 := []int{1, 2, 3} - if !_Equal(s1, s1) { - panic(fmt.Sprintf("_Equal(%v, %v) = false, want true", s1, s1)) - } - s2 := []int{1, 2, 3} - if !_Equal(s1, s2) { - panic(fmt.Sprintf("_Equal(%v, %v) = false, want true", s1, s2)) - } - s2 = append(s2, 4) - if _Equal(s1, s2) { - panic(fmt.Sprintf("_Equal(%v, %v) = true, want false", s1, s2)) - } - - s3 := []float64{1, 2, math.NaN()} - if !_Equal(s3, s3) { - panic(fmt.Sprintf("_Equal(%v, %v) = false, want true", s3, s3)) - } - - if _Equal(s1, nil) { - panic(fmt.Sprintf("_Equal(%v, nil) = true, want false", s1)) - } - if _Equal(nil, s1) { - panic(fmt.Sprintf("_Equal(nil, %v) = true, want false", s1)) - } - if !_Equal(s1[:0], nil) { - panic(fmt.Sprintf("_Equal(%v, nil = false, want true", s1[:0])) - } + s1 := []int{1, 2, 3} + if !_Equal(s1, s1) { + panic(fmt.Sprintf("_Equal(%v, %v) = false, want true", s1, s1)) + } + s2 := []int{1, 2, 3} + if !_Equal(s1, s2) { + panic(fmt.Sprintf("_Equal(%v, %v) = false, want true", s1, s2)) + } + s2 = append(s2, 4) + if _Equal(s1, s2) { + panic(fmt.Sprintf("_Equal(%v, %v) = true, want false", s1, s2)) + } + + s3 := []float64{1, 2, math.NaN()} + if !_Equal(s3, s3) { + panic(fmt.Sprintf("_Equal(%v, %v) = false, want true", s3, s3)) + } + + if _Equal(s1, nil) { + panic(fmt.Sprintf("_Equal(%v, nil) = true, want false", s1)) + } + if _Equal(nil, s1) { + panic(fmt.Sprintf("_Equal(nil, %v) = true, want false", s1)) + } + if !_Equal(s1[:0], nil) { + panic(fmt.Sprintf("_Equal(%v, nil = false, want true", s1[:0])) + } } func offByOne[Elem Integer](a, b Elem) bool { - return a == b + 1 || a == b - 1 + return a == b+1 || a == b-1 } func TestEqualFn() { @@ -231,12 +231,12 @@ func TestMap() { func TestReduce() { s1 := []int{1, 2, 3} - r := _Reduce(s1, 0, func(f float64, i int) float64 { return float64(i) * 2.5 + f }) + r := _Reduce(s1, 0, func(f float64, i int) float64 { return float64(i)*2.5 + f }) if want := 15.0; r != want { panic(fmt.Sprintf("_Reduce(%v, 0, ...) = %v, want %v", s1, r, want)) } - if got := _Reduce(nil, 0, func(i, j int) int { return i + j}); got != 0 { + if got := _Reduce(nil, 0, func(i, j int) int { return i + j }); got != 0 { panic(fmt.Sprintf("_Reduce(nil, 0, add) = %v, want 0", got)) } } diff --git a/test/typeparam/smallest.go b/test/typeparam/smallest.go index 3fead6a067..af1d72d899 100644 --- a/test/typeparam/smallest.go +++ b/test/typeparam/smallest.go @@ -11,10 +11,10 @@ import ( ) type Ordered interface { - ~int | ~int8 | ~int16 | ~int32 | ~int64 | - ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | - ~float32 | ~float64 | - ~string + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 | + ~string } func Smallest[T Ordered](s []T) T { diff --git a/test/typeparam/smoketest.go b/test/typeparam/smoketest.go index d92e02713d..eeda25964f 100644 --- a/test/typeparam/smoketest.go +++ b/test/typeparam/smoketest.go @@ -29,8 +29,8 @@ type _ T2[int, string, struct{}] type _ T3[bool] // methods -func (T1[P]) m1() {} -func (T1[_]) m2() {} +func (T1[P]) m1() {} +func (T1[_]) m2() {} func (x T2[P1, P2, P3]) m() {} // type lists diff --git a/test/typeparam/stringable.go b/test/typeparam/stringable.go index 20da012cb8..855a1edb3b 100644 --- a/test/typeparam/stringable.go +++ b/test/typeparam/stringable.go @@ -38,9 +38,9 @@ func (a myint) String() string { } func main() { - v := StringableList[myint]{ myint(1), myint(2) } + v := StringableList[myint]{myint(1), myint(2)} if got, want := v.String(), "1, 2"; got != want { - panic(fmt.Sprintf("got %s, want %s", got, want)) + panic(fmt.Sprintf("got %s, want %s", got, want)) } } diff --git a/test/typeparam/struct.go b/test/typeparam/struct.go index 093f6935e6..ad1b41ddac 100644 --- a/test/typeparam/struct.go +++ b/test/typeparam/struct.go @@ -35,15 +35,15 @@ type S3 struct { func main() { s1 := S1{Eint{2}, "foo"} if got, want := s1.E.v, 2; got != want { - panic(fmt.Sprintf("got %d, want %d", got, want)) + panic(fmt.Sprintf("got %d, want %d", got, want)) } s2 := S2{Eint{3}, Ebool{true}, "foo"} if got, want := s2.Eint.v, 3; got != want { - panic(fmt.Sprintf("got %d, want %d", got, want)) + panic(fmt.Sprintf("got %d, want %d", got, want)) } var s3 S3 s3.E = &Eint{4} if got, want := s3.E.v, 4; got != want { - panic(fmt.Sprintf("got %d, want %d", got, want)) + panic(fmt.Sprintf("got %d, want %d", got, want)) } } diff --git a/test/typeparam/subdict.go b/test/typeparam/subdict.go index c899af6d0d..b4e84baf8a 100644 --- a/test/typeparam/subdict.go +++ b/test/typeparam/subdict.go @@ -4,7 +4,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Test cases where a main dictionary is needed inside a generic function/method, because +// Test cases where a main dictionary is needed inside a generic function/method, because // we are calling a method on a fully-instantiated type or a fully-instantiated function. // (probably not common situations, of course) @@ -33,7 +33,6 @@ func (v *value[T]) get(def T) T { } } - func main() { var s value[string] if got, want := s.get("ab"), ""; got != want { diff --git a/test/typeparam/sum.go b/test/typeparam/sum.go index 53e6face11..d444e007a3 100644 --- a/test/typeparam/sum.go +++ b/test/typeparam/sum.go @@ -40,11 +40,11 @@ func main() { fwant := vec2[0] + vec2[1] fgot := Sum[float64](vec2) - if Abs(fgot - fwant) > 1e-10 { + if Abs(fgot-fwant) > 1e-10 { panic(fmt.Sprintf("got %f, want %f", fgot, fwant)) } fgot = Sum(vec2) - if Abs(fgot - fwant) > 1e-10 { + if Abs(fgot-fwant) > 1e-10 { panic(fmt.Sprintf("got %f, want %f", fgot, fwant)) } } diff --git a/test/typeparam/tparam1.go b/test/typeparam/tparam1.go index 2bcc4af3db..a196caf976 100644 --- a/test/typeparam/tparam1.go +++ b/test/typeparam/tparam1.go @@ -10,18 +10,18 @@ package tparam1 // The predeclared identifier "any" is only visible as a constraint // in a type parameter list. -var _ any // ERROR "cannot use any outside constraint position" +var _ any // ERROR "cannot use any outside constraint position" func _(_ any) // ERROR "cannot use any outside constraint position" -type _[_ any /* ok here */ ] struct{} +type _[_ any /* ok here */] struct{} const N = 10 type ( - _[] struct{} // slice - _[N] struct{} // array - _[T any] struct{} - _[T, T any] struct{} // ERROR "T redeclared" - _[T1, T2 any, T3 any] struct{} + _ []struct{} // slice + _ [N]struct{} // array + _[T any] struct{} + _[T, T any] struct{} // ERROR "T redeclared" + _[T1, T2 any, T3 any] struct{} ) func _[T any]() @@ -36,7 +36,7 @@ func _[T C]() func _[T struct{}]() // ERROR "not an interface" func _[T interface{ m() T }]() func _[T1 interface{ m() T2 }, T2 interface{ m() T1 }]() { - var _ T1 + var _ T1 } // TODO(gri) expand this diff --git a/test/typeparam/typelist.go b/test/typeparam/typelist.go index 5c51c9c461..3d035bf457 100644 --- a/test/typeparam/typelist.go +++ b/test/typeparam/typelist.go @@ -10,19 +10,19 @@ package p // Assignability of an unnamed pointer type to a type parameter that // has a matching underlying type. -func _[T interface{}, PT interface{type *T}] (x T) PT { - return &x +func _[T interface{}, PT interface{ type *T }](x T) PT { + return &x } // Indexing of generic types containing type parameters in their type list: func at[T interface{ type []E }, E any](x T, i int) E { - return x[i] + return x[i] } // A generic type inside a function acts like a named type. Its underlying // type is itself, its "operational type" is defined by the type list in // the tybe bound, if any. -func _[T interface{type int}](x T) { +func _[T interface{ type int }](x T) { type myint int var _ int = int(x) var _ T = 42 @@ -30,7 +30,7 @@ func _[T interface{type int}](x T) { } // Indexing a generic type which has a structural contraints to be an array. -func _[T interface { type [10]int }](x T) { +func _[T interface{ type [10]int }](x T) { _ = x[9] // ok } @@ -44,7 +44,7 @@ func _[T interface{ type *int }](p T) int { func _[T interface{ type chan int }](ch T) int { // This would deadlock if executed (but ok for a compile test) ch <- 0 - return <- ch + return <-ch } // Calling of a generic type which has a structural constraint to be a function. @@ -59,11 +59,10 @@ func _[T interface{ type func(string) int }](f T) int { } // Map access of a generic type which has a structural constraint to be a map. -func _[V any, T interface { type map[string]V }](p T) V { +func _[V any, T interface{ type map[string]V }](p T) V { return p["test"] } - // Testing partial and full type inference, including the case where the types can // be inferred without needing the types of the function arguments. @@ -86,7 +85,7 @@ func _() { } */ -func f2[A any, B interface{type []A}](_ A, _ B) +func f2[A any, B interface{ type []A }](_ A, _ B) func _() { f := f2[byte] f(byte(0), []byte{}) @@ -106,7 +105,7 @@ func _() { } */ -func f4[A any, B interface{type []C}, C interface{type *A}](_ A, _ B, c C) +func f4[A any, B interface{ type []C }, C interface{ type *A }](_ A, _ B, c C) func _() { f := f4[int] var x int @@ -114,15 +113,20 @@ func _() { f4(x, []*int{}, &x) } -func f5[A interface{type struct{b B; c C}}, B any, C interface{type *B}](x B) A +func f5[A interface { + type struct { + b B + c C + } +}, B any, C interface{ type *B }](x B) A func _() { x := f5(1.2) var _ float64 = x.b var _ float64 = *x.c } -func f6[A any, B interface{type struct{f []A}}](B) A +func f6[A any, B interface{ type struct{ f []A } }](B) A func _() { - x := f6(struct{f []string}{}) + x := f6(struct{ f []string }{}) var _ string = x } diff --git a/test/typeparam/valimp.dir/a.go b/test/typeparam/valimp.dir/a.go index 5aa5ebfa97..2ed0063cfd 100644 --- a/test/typeparam/valimp.dir/a.go +++ b/test/typeparam/valimp.dir/a.go @@ -5,7 +5,7 @@ package a type Value[T any] struct { - val T + val T } // The noinline directive should survive across import, and prevent instantiations @@ -13,20 +13,20 @@ type Value[T any] struct { //go:noinline func Get[T any](v *Value[T]) T { - return v.val + return v.val } //go:noinline func Set[T any](v *Value[T], val T) { - v.val = val + v.val = val } //go:noinline func (v *Value[T]) Set(val T) { - v.val = val + v.val = val } //go:noinline func (v *Value[T]) Get() T { - return v.val + return v.val } diff --git a/test/typeparam/valimp.dir/main.go b/test/typeparam/valimp.dir/main.go index 925fb1e699..606ff2273a 100644 --- a/test/typeparam/valimp.dir/main.go +++ b/test/typeparam/valimp.dir/main.go @@ -10,47 +10,46 @@ import ( ) func main() { - var v1 a.Value[int] - - a.Set(&v1, 1) - if got, want := a.Get(&v1), 1; got != want { - panic(fmt.Sprintf("Get() == %d, want %d", got, want)) - } - v1.Set(2) - if got, want := v1.Get(), 2; got != want { - panic(fmt.Sprintf("Get() == %d, want %d", got, want)) - } - v1p := new(a.Value[int]) - a.Set(v1p, 3) - if got, want := a.Get(v1p), 3; got != want { - panic(fmt.Sprintf("Get() == %d, want %d", got, want)) - } - - v1p.Set(4) - if got, want := v1p.Get(), 4; got != want { - panic(fmt.Sprintf("Get() == %d, want %d", got, want)) - } - - var v2 a.Value[string] - a.Set(&v2, "a") - if got, want := a.Get(&v2), "a"; got != want { - panic(fmt.Sprintf("Get() == %q, want %q", got, want)) - } - - v2.Set("b") - if got, want := a.Get(&v2), "b"; got != want { - panic(fmt.Sprintf("Get() == %q, want %q", got, want)) - } - - v2p := new(a.Value[string]) - a.Set(v2p, "c") - if got, want := a.Get(v2p), "c"; got != want { - panic(fmt.Sprintf("Get() == %d, want %d", got, want)) - } - - v2p.Set("d") - if got, want := v2p.Get(), "d"; got != want { - panic(fmt.Sprintf("Get() == %d, want %d", got, want)) - } + var v1 a.Value[int] + + a.Set(&v1, 1) + if got, want := a.Get(&v1), 1; got != want { + panic(fmt.Sprintf("Get() == %d, want %d", got, want)) + } + v1.Set(2) + if got, want := v1.Get(), 2; got != want { + panic(fmt.Sprintf("Get() == %d, want %d", got, want)) + } + v1p := new(a.Value[int]) + a.Set(v1p, 3) + if got, want := a.Get(v1p), 3; got != want { + panic(fmt.Sprintf("Get() == %d, want %d", got, want)) + } + + v1p.Set(4) + if got, want := v1p.Get(), 4; got != want { + panic(fmt.Sprintf("Get() == %d, want %d", got, want)) + } + + var v2 a.Value[string] + a.Set(&v2, "a") + if got, want := a.Get(&v2), "a"; got != want { + panic(fmt.Sprintf("Get() == %q, want %q", got, want)) + } + + v2.Set("b") + if got, want := a.Get(&v2), "b"; got != want { + panic(fmt.Sprintf("Get() == %q, want %q", got, want)) + } + + v2p := new(a.Value[string]) + a.Set(v2p, "c") + if got, want := a.Get(v2p), "c"; got != want { + panic(fmt.Sprintf("Get() == %d, want %d", got, want)) + } + + v2p.Set("d") + if got, want := v2p.Get(), "d"; got != want { + panic(fmt.Sprintf("Get() == %d, want %d", got, want)) + } } - -- GitLab From adedf54288e826bd93ccf22ad104f768d42289d4 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 28 Jul 2021 12:59:14 -0700 Subject: [PATCH 0552/2500] [dev.typeparams] test: rename blank functions This CL renames blank functions in the test/ directory so that they don't rely on the compiler doing anything more than typechecking them. In particular, I ran this search to find files that used blank functions and methods: $ git grep -l '^func.*\b_(' | xargs grep -n '^' | grep '\.go:1:' | grep -v '// errorcheck$' I then skipped updating a few files: * blank.go * fixedbugs/issue11699.go * fixedbugs/issue29870.go These tests specifically check that blank functions/methods work. * interface/fail.go Not sure the motivation for the blank method here, but it's empty anyway. * typeparam/tparam1.go Type-checking test, but uses "-G" (to use types2 instead of typecheck). Updates #47446. Change-Id: I9ec1714f499808768bd0dcd7ae6016fb2b078e5e Reviewed-on: https://go-review.googlesource.com/c/go/+/338094 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- test/escape5.go | 4 ++-- test/escape_goto.go | 6 +++--- test/fixedbugs/bug267.go | 2 +- test/fixedbugs/issue22076.go | 4 ++-- test/fixedbugs/issue27557.go | 6 +++--- test/fixedbugs/issue45258.go | 2 +- test/fixedbugs/issue8042.go | 6 +++--- test/fixedbugs/issue8761.go | 6 +++--- test/inline.go | 4 ++-- test/typeparam/issue45547.go | 2 +- test/typeparam/typelist.go | 14 +++++++------- 11 files changed, 28 insertions(+), 28 deletions(-) diff --git a/test/escape5.go b/test/escape5.go index 97aaf23b2d..089130dad5 100644 --- a/test/escape5.go +++ b/test/escape5.go @@ -173,13 +173,13 @@ type U int func (*U) M() {} func (_ *U) N() {} -func _() { +func fbad24305a() { var u U u.M() u.N() } -func fbad24305() { +func fbad24305b() { var u U (*U).M(&u) (*U).N(&u) diff --git a/test/escape_goto.go b/test/escape_goto.go index f024a9afe3..90da5a2151 100644 --- a/test/escape_goto.go +++ b/test/escape_goto.go @@ -10,7 +10,7 @@ package escape var x bool -func _() { +func f1() { var p *int loop: if x { @@ -22,7 +22,7 @@ loop: _ = p } -func _() { +func f2() { var p *int if x { loop: @@ -33,7 +33,7 @@ func _() { _ = p } -func _() { +func f3() { var p *int if x { loop: diff --git a/test/fixedbugs/bug267.go b/test/fixedbugs/bug267.go index cf8bf841f8..b61216a9d5 100644 --- a/test/fixedbugs/bug267.go +++ b/test/fixedbugs/bug267.go @@ -10,7 +10,7 @@ type T []int var a []bool -func _() { +func f1() { if a[T{42}[0]] { } // if (a[T{42}[0]]) {} // this compiles diff --git a/test/fixedbugs/issue22076.go b/test/fixedbugs/issue22076.go index 5d628b96bd..b383a674e2 100644 --- a/test/fixedbugs/issue22076.go +++ b/test/fixedbugs/issue22076.go @@ -13,12 +13,12 @@ import . "bytes" var _ Reader // use "bytes" import -func _() { +func f1() { Buffer := 0 _ = Buffer } -func _() { +func f2() { for Buffer := range []int{} { _ = Buffer } diff --git a/test/fixedbugs/issue27557.go b/test/fixedbugs/issue27557.go index e35ab5a169..f609b27faa 100644 --- a/test/fixedbugs/issue27557.go +++ b/test/fixedbugs/issue27557.go @@ -8,19 +8,19 @@ package p var sink interface{} -func _() { +func f1() { var t T f := t.noescape // ERROR "t.noescape does not escape" f() } -func _() { +func f2() { var t T // ERROR "moved to heap" f := t.escape // ERROR "t.escape does not escape" f() } -func _() { +func f3() { var t T // ERROR "moved to heap" f := t.returns // ERROR "t.returns does not escape" sink = f() diff --git a/test/fixedbugs/issue45258.go b/test/fixedbugs/issue45258.go index f4d6fccf17..b026c0c8f5 100644 --- a/test/fixedbugs/issue45258.go +++ b/test/fixedbugs/issue45258.go @@ -22,7 +22,7 @@ func (r *impl) Foo() Barer { func (r *impl) Bar() {} -func _() { +func f1() { var r Fooer = &impl{} r.Foo().Bar() } diff --git a/test/fixedbugs/issue8042.go b/test/fixedbugs/issue8042.go index 5639f97bb8..be15ef06cd 100644 --- a/test/fixedbugs/issue8042.go +++ b/test/fixedbugs/issue8042.go @@ -9,7 +9,7 @@ package p -func _() { +func f1() { goto L1 const x = 0 L1: @@ -18,7 +18,7 @@ L1: L2: } -func _() { +func f2() { { goto L1 } @@ -31,7 +31,7 @@ L1: L2: } -func _(d int) { +func f3(d int) { if d > 0 { goto L1 } else { diff --git a/test/fixedbugs/issue8761.go b/test/fixedbugs/issue8761.go index 7f458f7f03..e5130e1ff5 100644 --- a/test/fixedbugs/issue8761.go +++ b/test/fixedbugs/issue8761.go @@ -10,17 +10,17 @@ package p -func _() { +func f1() { type C chan int _ = [1][]C{[]C{make(chan int)}} } -func _() { +func f2() { type C interface{} _ = [1][]C{[]C{recover()}} } -func _() { +func f3() { type C *int _ = [1][]C{[]C{new(int)}} } diff --git a/test/inline.go b/test/inline.go index 2cda07b2da..a73c0ba7b1 100644 --- a/test/inline.go +++ b/test/inline.go @@ -49,7 +49,7 @@ func j(x int) int { // ERROR "can inline j" } } -func _() int { // ERROR "can inline _" +func f2() int { // ERROR "can inline f2" tmp1 := h tmp2 := tmp1 return tmp2(0) // ERROR "inlining call to h" @@ -167,7 +167,7 @@ func (T) meth(int, int) {} // ERROR "can inline T.meth" func k() (T, int, int) { return T{}, 0, 0 } // ERROR "can inline k" -func _() { // ERROR "can inline _" +func f3() { // ERROR "can inline f3" T.meth(k()) // ERROR "inlining call to k" "inlining call to T.meth" // ERRORAUTO "inlining call to T.meth" } diff --git a/test/typeparam/issue45547.go b/test/typeparam/issue45547.go index 0a08d66b70..b354d4d7f6 100644 --- a/test/typeparam/issue45547.go +++ b/test/typeparam/issue45547.go @@ -11,7 +11,7 @@ func f[T any]() (f, g T) { return f, g } // Tests for generic function instantiation on the right hande side of multi-value // assignments. -func _() { +func g() { // Multi-value assignment within a function var _, _ = f[int]() } diff --git a/test/typeparam/typelist.go b/test/typeparam/typelist.go index 3d035bf457..a68ae1b5cd 100644 --- a/test/typeparam/typelist.go +++ b/test/typeparam/typelist.go @@ -69,14 +69,14 @@ func _[V any, T interface{ type map[string]V }](p T) V { // Cannot embed stand-alone type parameters. Disabled for now. /* func f0[A any, B interface{type C}, C interface{type D}, D interface{type A}](A, B, C, D) -func _() { +func f0x() { f := f0[string] f("a", "b", "c", "d") f0("a", "b", "c", "d") } func f1[A any, B interface{type A}](A, B) -func _() { +func f1x() { f := f1[int] f(int(0), int(0)) f1(int(0), int(0)) @@ -86,7 +86,7 @@ func _() { */ func f2[A any, B interface{ type []A }](_ A, _ B) -func _() { +func f2x() { f := f2[byte] f(byte(0), []byte{}) f2(byte(0), []byte{}) @@ -97,7 +97,7 @@ func _() { // Cannot embed stand-alone type parameters. Disabled for now. /* func f3[A any, B interface{type C}, C interface{type *A}](a A, _ B, c C) -func _() { +func f3x() { f := f3[int] var x int f(x, &x, &x) @@ -106,7 +106,7 @@ func _() { */ func f4[A any, B interface{ type []C }, C interface{ type *A }](_ A, _ B, c C) -func _() { +func f4x() { f := f4[int] var x int f(x, []*int{}, &x) @@ -119,14 +119,14 @@ func f5[A interface { c C } }, B any, C interface{ type *B }](x B) A -func _() { +func f5x() { x := f5(1.2) var _ float64 = x.b var _ float64 = *x.c } func f6[A any, B interface{ type struct{ f []A } }](B) A -func _() { +func f6x() { x := f6(struct{ f []string }{}) var _ string = x } -- GitLab From 506fd520d5cd6ea075ac82e79a23c502c1540170 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 28 Jul 2021 13:17:32 -0700 Subject: [PATCH 0553/2500] [dev.typeparams] cmd/compile: don't compile blank functions After typechecking a blank function, we can clear out its body and skip applying middle-end optimizations (inlining, escape analysis). We already skip sending them through SSA, and the previous CL updated inlining and escape analysis regress tests to not depend on compiling blank functions. Updates #47446. Change-Id: Ie678763b0e6ff13dd606ce14906b1ccf1bbccaae Reviewed-on: https://go-review.googlesource.com/c/go/+/338095 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/typecheck/typecheck.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/typecheck/typecheck.go b/src/cmd/compile/internal/typecheck/typecheck.go index 8f3d6cf4bb..db1b11c4cf 100644 --- a/src/cmd/compile/internal/typecheck/typecheck.go +++ b/src/cmd/compile/internal/typecheck/typecheck.go @@ -51,8 +51,8 @@ func FuncBody(n *ir.Func) { Stmts(n.Body) CheckUnused(n) CheckReturn(n) - if base.Errors() > errorsBefore { - n.Body = nil // type errors; do not compile + if ir.IsBlank(n.Nname) || base.Errors() > errorsBefore { + n.Body = nil // blank function or type errors; do not compile } } -- GitLab From 4a47e40a14c2051656d4ff4b768fe21a5fc308fa Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 28 Jul 2021 13:17:56 -0700 Subject: [PATCH 0554/2500] [dev.typeparams] cmd/compile: don't export blank functions in unified IR After the previous two CLs, there's no need for unified IR to write/read blank functions anymore: types2 has already checked that they're valid, and the compiler backend is going to ignore them. Allows dropping code for worrying about blank methods and will probably simplify some of the object handling code eventually too. Fixes #47446. Change-Id: I03cb722793d676a246b1ab768b5cf0d3d2578b12 Reviewed-on: https://go-review.googlesource.com/c/go/+/338096 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/noder/writer.go | 25 +++++------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index bf60246d64..7b2285556e 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -550,25 +550,6 @@ func (w *writer) doObj(obj types2.Object) codeObj { assert(ok) sig := obj.Type().(*types2.Signature) - // Rewrite blank methods into blank functions. - // They aren't included in the receiver type's method set, - // and we still want to write them out to be compiled - // for regression tests. - // TODO(mdempsky): Change regress tests to avoid relying - // on blank functions/methods, so we can just ignore them - // altogether. - if recv := sig.Recv(); recv != nil { - assert(obj.Name() == "_") - assert(sig.TParams() == nil) - - params := make([]*types2.Var, 1+sig.Params().Len()) - params[0] = recv - for i := 0; i < sig.Params().Len(); i++ { - params[1+i] = sig.Params().At(i) - } - sig = types2.NewSignature(nil, types2.NewTuple(params...), sig.Results(), sig.Variadic()) - } - w.pos(obj) w.typeParamNames(sig.TParams()) w.signature(sig) @@ -1683,6 +1664,10 @@ func (w *writer) pkgDecl(decl syntax.Decl) { w.pkgObjs(decl.NameList...) case *syntax.FuncDecl: + if decl.Name.Value == "_" { + break // skip blank functions + } + obj := w.p.info.Defs[decl.Name].(*types2.Func) sig := obj.Type().(*types2.Signature) @@ -1690,7 +1675,7 @@ func (w *writer) pkgDecl(decl syntax.Decl) { break // skip generic functions } - if recv := sig.Recv(); recv != nil && obj.Name() != "_" { + if recv := sig.Recv(); recv != nil { w.code(declMethod) w.typ(recvBase(recv)) w.selector(obj) -- GitLab From f4f503e0a3ac7fbf9f57c7fe34cecc8df383e334 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Mon, 26 Jul 2021 17:41:02 -0700 Subject: [PATCH 0555/2500] [dev.typeparams] cmd/compile: implement generic .(T) operations Introduce new dynamic dottype operations which take a dynamic instead of static type to convert to. Change-Id: I5824a1fea056fe811b1226ce059e1e8da1baa335 Reviewed-on: https://go-review.googlesource.com/c/go/+/337609 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/escape/expr.go | 4 + src/cmd/compile/internal/ir/expr.go | 23 ++++ src/cmd/compile/internal/ir/node.go | 4 + src/cmd/compile/internal/ir/node_gen.go | 28 +++++ src/cmd/compile/internal/ir/op_string.go | 16 +-- src/cmd/compile/internal/noder/stencil.go | 43 +++++++- src/cmd/compile/internal/ssagen/ssa.go | 122 ++++++++++++++-------- src/cmd/compile/internal/walk/expr.go | 11 ++ src/cmd/compile/internal/walk/order.go | 4 + test/typeparam/dottype.go | 5 + test/typeparam/dottype.out | 2 + 11 files changed, 209 insertions(+), 53 deletions(-) diff --git a/src/cmd/compile/internal/escape/expr.go b/src/cmd/compile/internal/escape/expr.go index b7423e114a..4a6304d47a 100644 --- a/src/cmd/compile/internal/escape/expr.go +++ b/src/cmd/compile/internal/escape/expr.go @@ -74,6 +74,10 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) { case ir.ODOTTYPE, ir.ODOTTYPE2: n := n.(*ir.TypeAssertExpr) e.expr(k.dotType(n.Type(), n, "dot"), n.X) + case ir.ODYNAMICDOTTYPE, ir.ODYNAMICDOTTYPE2: + n := n.(*ir.DynamicTypeAssertExpr) + e.expr(k.dotType(n.Type(), n, "dot"), n.X) + // n.T doesn't need to be tracked; it always points to read-only storage. case ir.OINDEX: n := n.(*ir.IndexExpr) if n.X.Type().IsArray() { diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 86323e6b8f..9c5fbbc9aa 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -677,6 +677,29 @@ func (n *TypeAssertExpr) SetOp(op Op) { } } +// A DynamicTypeAssertExpr asserts that X is of dynamic type T. +type DynamicTypeAssertExpr struct { + miniExpr + X Node + // N = not an interface + // E = empty interface + // I = nonempty interface + // For E->N, T is a *runtime.type for N + // For I->N, T is a *runtime.itab for N+I + // For E->I, T is a *runtime.type for I + // For I->I, ditto + // For I->E, T is a *runtime.type for interface{} (unnecessary, but just to fill in the slot) + // For E->E, ditto + T Node +} + +func NewDynamicTypeAssertExpr(pos src.XPos, op Op, x, t Node) *DynamicTypeAssertExpr { + n := &DynamicTypeAssertExpr{X: x, T: t} + n.pos = pos + n.op = op + return n +} + // A UnaryExpr is a unary expression Op X, // or Op(X) for a builtin function that does not end up being a call. type UnaryExpr struct { diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index 0fbc867c1d..e5f0c38f86 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -319,6 +319,10 @@ const ( OINLMARK // start of an inlined body, with file/line of caller. Xoffset is an index into the inline tree. OLINKSYMOFFSET // offset within a name + // opcodes for generics + ODYNAMICDOTTYPE + ODYNAMICDOTTYPE2 + // arch-specific opcodes OTAILCALL // tail call to another function OGETG // runtime.getg() (read g pointer) diff --git a/src/cmd/compile/internal/ir/node_gen.go b/src/cmd/compile/internal/ir/node_gen.go index 9a4858d037..56db6bb9cf 100644 --- a/src/cmd/compile/internal/ir/node_gen.go +++ b/src/cmd/compile/internal/ir/node_gen.go @@ -463,6 +463,34 @@ func (n *Decl) editChildren(edit func(Node) Node) { } } +func (n *DynamicTypeAssertExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) } +func (n *DynamicTypeAssertExpr) copy() Node { + c := *n + c.init = copyNodes(c.init) + return &c +} +func (n *DynamicTypeAssertExpr) doChildren(do func(Node) bool) bool { + if doNodes(n.init, do) { + return true + } + if n.X != nil && do(n.X) { + return true + } + if n.T != nil && do(n.T) { + return true + } + return false +} +func (n *DynamicTypeAssertExpr) editChildren(edit func(Node) Node) { + editNodes(n.init, edit) + if n.X != nil { + n.X = edit(n.X).(Node) + } + if n.T != nil { + n.T = edit(n.T).(Node) + } +} + func (n *ForStmt) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) } func (n *ForStmt) copy() Node { c := *n diff --git a/src/cmd/compile/internal/ir/op_string.go b/src/cmd/compile/internal/ir/op_string.go index 0235d5eab3..7b08ee287a 100644 --- a/src/cmd/compile/internal/ir/op_string.go +++ b/src/cmd/compile/internal/ir/op_string.go @@ -162,16 +162,18 @@ func _() { _ = x[ORESULT-151] _ = x[OINLMARK-152] _ = x[OLINKSYMOFFSET-153] - _ = x[OTAILCALL-154] - _ = x[OGETG-155] - _ = x[OGETCALLERPC-156] - _ = x[OGETCALLERSP-157] - _ = x[OEND-158] + _ = x[ODYNAMICDOTTYPE-154] + _ = x[ODYNAMICDOTTYPE2-155] + _ = x[OTAILCALL-156] + _ = x[OGETG-157] + _ = x[OGETCALLERPC-158] + _ = x[OGETCALLERSP-159] + _ = x[OEND-160] } -const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESSLICE2ARRPTRASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVIDATACONVNOPCOPYDCLDCLFUNCDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECOVERFPRECVRUNESTRSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFUNSAFEADDUNSAFESLICEMETHEXPRMETHVALUEBLOCKBREAKCASECONTINUEDEFERFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWFUNCINSTTCHANTMAPTSTRUCTTINTERTFUNCTARRAYTSLICEINLCALLEFACEITABIDATASPTRCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKLINKSYMOFFSETTAILCALLGETGGETCALLERPCGETCALLERSPEND" +const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESSLICE2ARRPTRASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVIDATACONVNOPCOPYDCLDCLFUNCDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECOVERFPRECVRUNESTRSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFUNSAFEADDUNSAFESLICEMETHEXPRMETHVALUEBLOCKBREAKCASECONTINUEDEFERFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWFUNCINSTTCHANTMAPTSTRUCTTINTERTFUNCTARRAYTSLICEINLCALLEFACEITABIDATASPTRCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKLINKSYMOFFSETDYNAMICDOTTYPEDYNAMICDOTTYPE2TAILCALLGETGGETCALLERPCGETCALLERSPEND" -var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 136, 138, 141, 151, 158, 165, 172, 176, 180, 188, 196, 205, 208, 213, 220, 227, 233, 242, 250, 258, 264, 268, 277, 286, 293, 297, 300, 307, 315, 322, 328, 331, 337, 344, 352, 356, 363, 371, 373, 375, 377, 379, 381, 383, 388, 393, 401, 404, 413, 416, 420, 428, 435, 444, 457, 460, 463, 466, 469, 472, 475, 481, 484, 487, 493, 497, 500, 504, 509, 514, 520, 525, 529, 534, 542, 550, 556, 565, 576, 583, 592, 596, 603, 611, 615, 619, 623, 630, 637, 645, 651, 660, 671, 679, 688, 693, 698, 702, 710, 715, 719, 722, 730, 734, 736, 741, 743, 748, 754, 760, 766, 772, 780, 785, 789, 796, 802, 807, 813, 819, 826, 831, 835, 840, 844, 849, 857, 863, 870, 877, 883, 890, 903, 911, 915, 926, 937, 940} +var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 136, 138, 141, 151, 158, 165, 172, 176, 180, 188, 196, 205, 208, 213, 220, 227, 233, 242, 250, 258, 264, 268, 277, 286, 293, 297, 300, 307, 315, 322, 328, 331, 337, 344, 352, 356, 363, 371, 373, 375, 377, 379, 381, 383, 388, 393, 401, 404, 413, 416, 420, 428, 435, 444, 457, 460, 463, 466, 469, 472, 475, 481, 484, 487, 493, 497, 500, 504, 509, 514, 520, 525, 529, 534, 542, 550, 556, 565, 576, 583, 592, 596, 603, 611, 615, 619, 623, 630, 637, 645, 651, 660, 671, 679, 688, 693, 698, 702, 710, 715, 719, 722, 730, 734, 736, 741, 743, 748, 754, 760, 766, 772, 780, 785, 789, 796, 802, 807, 813, 819, 826, 831, 835, 840, 844, 849, 857, 863, 870, 877, 883, 890, 903, 917, 932, 940, 944, 955, 966, 969} func (i Op) String() string { if i >= Op(len(_Op_index)-1) { diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 02a380e63f..70a2c7b97f 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1039,6 +1039,7 @@ func (subst *subster) checkDictionary(name *ir.Name, targs []*types.Type) (code d.SetTypecheck(1) d = ir.NewConvExpr(pos, ir.OCONVNOP, types.NewArray(types.Types[types.TUINTPTR], int64(len(targs))).PtrTo(), d) d.SetTypecheck(1) + types.CheckSize(d.Type().Elem()) // Check that each type entry in the dictionary is correct. for i, t := range targs { @@ -1079,6 +1080,7 @@ func getDictionaryEntry(pos src.XPos, dict *ir.Name, i int, size int) ir.Node { d.SetTypecheck(1) d = ir.NewConvExpr(pos, ir.OCONVNOP, types.NewArray(types.Types[types.TUINTPTR], int64(size)).PtrTo(), d) d.SetTypecheck(1) + types.CheckSize(d.Type().Elem()) // Load entry i out of the dictionary. deref := ir.NewStarExpr(pos, d) @@ -1367,7 +1369,31 @@ func (subst *subster) node(n ir.Node) ir.Node { m = subst.convertUsingDictionary(m.Pos(), m.(*ir.ConvExpr).X, x, m.Type(), x.X.Type()) } case ir.ODOTTYPE, ir.ODOTTYPE2: - m.SetType(subst.unshapifyTyp(m.Type())) + dt := m.(*ir.TypeAssertExpr) + var rt ir.Node + if dt.Type().IsInterface() || dt.X.Type().IsEmptyInterface() { + ix := subst.findDictType(x.Type()) + assert(ix >= 0) + rt = subst.getDictionaryType(dt.Pos(), ix) + } else { + // nonempty interface to noninterface. Need an itab. + ix := -1 + for i, ic := range subst.info.gfInfo.itabConvs { + if ic == x { + ix = subst.info.startItabConv + i + break + } + } + assert(ix >= 0) + rt = getDictionaryEntry(dt.Pos(), subst.info.dictParam, ix, subst.info.dictLen) + } + op := ir.ODYNAMICDOTTYPE + if x.Op() == ir.ODOTTYPE2 { + op = ir.ODYNAMICDOTTYPE2 + } + m = ir.NewDynamicTypeAssertExpr(dt.Pos(), op, dt.X, rt) + m.SetType(dt.Type()) + m.SetTypecheck(1) case ir.OMETHEXPR: se := m.(*ir.SelectorExpr) @@ -1696,7 +1722,8 @@ func (g *irgen) finalizeSyms() { // Emit an entry for each itab for _, n := range info.itabConvs { var srctype, dsttype *types.Type - if n.Op() == ir.OXDOT { + switch n.Op() { + case ir.OXDOT: se := n.(*ir.SelectorExpr) srctype = subst.Typ(se.X.Type()) dsttype = subst.Typ(se.X.Type().Bound()) @@ -1712,10 +1739,14 @@ func (g *irgen) finalizeSyms() { } } assert(found) - } else { - assert(n.Op() == ir.OCONVIFACE) + case ir.ODOTTYPE, ir.ODOTTYPE2: + srctype = subst.Typ(n.(*ir.TypeAssertExpr).Type()) + dsttype = subst.Typ(n.(*ir.TypeAssertExpr).X.Type()) + case ir.OCONVIFACE: srctype = subst.Typ(n.(*ir.ConvExpr).X.Type()) dsttype = subst.Typ(n.Type()) + default: + base.Fatalf("itab entry with unknown op %s", n.Op()) } itabLsym := reflectdata.ITabLsym(srctype, dsttype) d.off = objw.SymPtr(lsym, d.off, itabLsym, 0) @@ -1859,6 +1890,10 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo { infoPrint(" Itab for interface conv: %v\n", n) info.itabConvs = append(info.itabConvs, n) } + if (n.Op() == ir.ODOTTYPE || n.Op() == ir.ODOTTYPE2) && !n.(*ir.TypeAssertExpr).Type().IsInterface() && !n.(*ir.TypeAssertExpr).X.Type().IsEmptyInterface() { + infoPrint(" Itab for dot type: %v\n", n) + info.itabConvs = append(info.itabConvs, n) + } if n.Op() == ir.OCLOSURE { // Visit the closure body and add all relevant entries to the // dictionary of the outer function (closure will just use diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index d2e0d57b28..7e2f6a7471 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -1423,7 +1423,12 @@ func (s *state) stmt(n ir.Node) { case ir.OAS2DOTTYPE: n := n.(*ir.AssignListStmt) - res, resok := s.dottype(n.Rhs[0].(*ir.TypeAssertExpr), true) + var res, resok *ssa.Value + if n.Rhs[0].Op() == ir.ODOTTYPE2 { + res, resok = s.dottype(n.Rhs[0].(*ir.TypeAssertExpr), true) + } else { + res, resok = s.dynamicDottype(n.Rhs[0].(*ir.DynamicTypeAssertExpr), true) + } deref := false if !TypeOK(n.Rhs[0].Type()) { if res.Op != ssa.OpLoad { @@ -2680,6 +2685,11 @@ func (s *state) expr(n ir.Node) *ssa.Value { res, _ := s.dottype(n, false) return res + case ir.ODYNAMICDOTTYPE: + n := n.(*ir.DynamicTypeAssertExpr) + res, _ := s.dynamicDottype(n, false) + return res + // binary ops case ir.OLT, ir.OEQ, ir.ONE, ir.OLE, ir.OGE, ir.OGT: n := n.(*ir.BinaryExpr) @@ -5147,9 +5157,13 @@ func (s *state) addr(n ir.Node) *ssa.Value { case ir.OCALLFUNC, ir.OCALLINTER: n := n.(*ir.CallExpr) return s.callAddr(n, callNormal) - case ir.ODOTTYPE: - n := n.(*ir.TypeAssertExpr) - v, _ := s.dottype(n, false) + case ir.ODOTTYPE, ir.ODYNAMICDOTTYPE: + var v *ssa.Value + if n.Op() == ir.ODOTTYPE { + v, _ = s.dottype(n.(*ir.TypeAssertExpr), false) + } else { + v, _ = s.dynamicDottype(n.(*ir.DynamicTypeAssertExpr), false) + } if v.Op != ssa.OpLoad { s.Fatalf("dottype of non-load") } @@ -6043,14 +6057,38 @@ func (s *state) floatToUint(cvttab *f2uCvtTab, n ir.Node, x *ssa.Value, ft, tt * func (s *state) dottype(n *ir.TypeAssertExpr, commaok bool) (res, resok *ssa.Value) { iface := s.expr(n.X) // input interface target := s.reflectType(n.Type()) // target type - byteptr := s.f.Config.Types.BytePtr + var targetItab *ssa.Value + if n.Itab != nil { + targetItab = s.expr(n.Itab) + } + return s.dottype1(n.Pos(), n.X.Type(), n.Type(), iface, target, targetItab, commaok) +} - if n.Type().IsInterface() { - if n.Type().IsEmptyInterface() { +func (s *state) dynamicDottype(n *ir.DynamicTypeAssertExpr, commaok bool) (res, resok *ssa.Value) { + iface := s.expr(n.X) + target := s.expr(n.T) + var itab *ssa.Value + if !n.X.Type().IsEmptyInterface() && !n.Type().IsInterface() { + byteptr := s.f.Config.Types.BytePtr + itab = target + target = s.load(byteptr, s.newValue1I(ssa.OpOffPtr, byteptr, int64(types.PtrSize), itab)) // itab.typ + } + return s.dottype1(n.Pos(), n.X.Type(), n.Type(), iface, target, itab, commaok) +} + +// dottype1 implements a x.(T) operation. iface is the argument (x), dst is the type we're asserting to (T) +// and src is the type we're asserting from. +// target is the *runtime._type of dst. +// If src is a nonempty interface and dst is not an interface, targetItab is an itab representing (dst, src). Otherwise it is nil. +// commaok is true if the caller wants a boolean success value. Otherwise, the generated code panics if the conversion fails. +func (s *state) dottype1(pos src.XPos, src, dst *types.Type, iface, target, targetItab *ssa.Value, commaok bool) (res, resok *ssa.Value) { + byteptr := s.f.Config.Types.BytePtr + if dst.IsInterface() { + if dst.IsEmptyInterface() { // Converting to an empty interface. // Input could be an empty or nonempty interface. if base.Debug.TypeAssert > 0 { - base.WarnfAt(n.Pos(), "type assertion inlined") + base.WarnfAt(pos, "type assertion inlined") } // Get itab/type field from input. @@ -6058,7 +6096,7 @@ func (s *state) dottype(n *ir.TypeAssertExpr, commaok bool) (res, resok *ssa.Val // Conversion succeeds iff that field is not nil. cond := s.newValue2(ssa.OpNeqPtr, types.Types[types.TBOOL], itab, s.constNil(byteptr)) - if n.X.Type().IsEmptyInterface() && commaok { + if src.IsEmptyInterface() && commaok { // Converting empty interface to empty interface with ,ok is just a nil check. return iface, cond } @@ -6080,7 +6118,7 @@ func (s *state) dottype(n *ir.TypeAssertExpr, commaok bool) (res, resok *ssa.Val // On success, return (perhaps modified) input interface. s.startBlock(bOk) - if n.X.Type().IsEmptyInterface() { + if src.IsEmptyInterface() { res = iface // Use input interface unchanged. return } @@ -6088,7 +6126,7 @@ func (s *state) dottype(n *ir.TypeAssertExpr, commaok bool) (res, resok *ssa.Val off := s.newValue1I(ssa.OpOffPtr, byteptr, int64(types.PtrSize), itab) typ := s.load(byteptr, off) idata := s.newValue1(ssa.OpIData, byteptr, iface) - res = s.newValue2(ssa.OpIMake, n.Type(), typ, idata) + res = s.newValue2(ssa.OpIMake, dst, typ, idata) return } @@ -6110,62 +6148,62 @@ func (s *state) dottype(n *ir.TypeAssertExpr, commaok bool) (res, resok *ssa.Val bFail.AddEdgeTo(bEnd) s.startBlock(bEnd) idata := s.newValue1(ssa.OpIData, byteptr, iface) - res = s.newValue2(ssa.OpIMake, n.Type(), s.variable(typVar, byteptr), idata) + res = s.newValue2(ssa.OpIMake, dst, s.variable(typVar, byteptr), idata) resok = cond delete(s.vars, typVar) return } // converting to a nonempty interface needs a runtime call. if base.Debug.TypeAssert > 0 { - base.WarnfAt(n.Pos(), "type assertion not inlined") + base.WarnfAt(pos, "type assertion not inlined") } if !commaok { fn := ir.Syms.AssertI2I - if n.X.Type().IsEmptyInterface() { + if src.IsEmptyInterface() { fn = ir.Syms.AssertE2I } data := s.newValue1(ssa.OpIData, types.Types[types.TUNSAFEPTR], iface) tab := s.newValue1(ssa.OpITab, byteptr, iface) tab = s.rtcall(fn, true, []*types.Type{byteptr}, target, tab)[0] - return s.newValue2(ssa.OpIMake, n.Type(), tab, data), nil + return s.newValue2(ssa.OpIMake, dst, tab, data), nil } fn := ir.Syms.AssertI2I2 - if n.X.Type().IsEmptyInterface() { + if src.IsEmptyInterface() { fn = ir.Syms.AssertE2I2 } - res = s.rtcall(fn, true, []*types.Type{n.Type()}, target, iface)[0] - resok = s.newValue2(ssa.OpNeqInter, types.Types[types.TBOOL], res, s.constInterface(n.Type())) + res = s.rtcall(fn, true, []*types.Type{dst}, target, iface)[0] + resok = s.newValue2(ssa.OpNeqInter, types.Types[types.TBOOL], res, s.constInterface(dst)) return } if base.Debug.TypeAssert > 0 { - base.WarnfAt(n.Pos(), "type assertion inlined") + base.WarnfAt(pos, "type assertion inlined") } // Converting to a concrete type. - direct := types.IsDirectIface(n.Type()) + direct := types.IsDirectIface(dst) itab := s.newValue1(ssa.OpITab, byteptr, iface) // type word of interface if base.Debug.TypeAssert > 0 { - base.WarnfAt(n.Pos(), "type assertion inlined") + base.WarnfAt(pos, "type assertion inlined") } - var targetITab *ssa.Value - if n.X.Type().IsEmptyInterface() { + var wantedFirstWord *ssa.Value + if src.IsEmptyInterface() { // Looking for pointer to target type. - targetITab = target + wantedFirstWord = target } else { // Looking for pointer to itab for target type and source interface. - targetITab = s.expr(n.Itab) + wantedFirstWord = targetItab } var tmp ir.Node // temporary for use with large types var addr *ssa.Value // address of tmp - if commaok && !TypeOK(n.Type()) { + if commaok && !TypeOK(dst) { // unSSAable type, use temporary. // TODO: get rid of some of these temporaries. - tmp, addr = s.temp(n.Pos(), n.Type()) + tmp, addr = s.temp(pos, dst) } - cond := s.newValue2(ssa.OpEqPtr, types.Types[types.TBOOL], itab, targetITab) + cond := s.newValue2(ssa.OpEqPtr, types.Types[types.TBOOL], itab, wantedFirstWord) b := s.endBlock() b.Kind = ssa.BlockIf b.SetControl(cond) @@ -6179,8 +6217,8 @@ func (s *state) dottype(n *ir.TypeAssertExpr, commaok bool) (res, resok *ssa.Val if !commaok { // on failure, panic by calling panicdottype s.startBlock(bFail) - taddr := s.reflectType(n.X.Type()) - if n.X.Type().IsEmptyInterface() { + taddr := s.reflectType(src) + if src.IsEmptyInterface() { s.rtcall(ir.Syms.PanicdottypeE, false, nil, itab, target, taddr) } else { s.rtcall(ir.Syms.PanicdottypeI, false, nil, itab, target, taddr) @@ -6189,10 +6227,10 @@ func (s *state) dottype(n *ir.TypeAssertExpr, commaok bool) (res, resok *ssa.Val // on success, return data from interface s.startBlock(bOk) if direct { - return s.newValue1(ssa.OpIData, n.Type(), iface), nil + return s.newValue1(ssa.OpIData, dst, iface), nil } - p := s.newValue1(ssa.OpIData, types.NewPtr(n.Type()), iface) - return s.load(n.Type(), p), nil + p := s.newValue1(ssa.OpIData, types.NewPtr(dst), iface) + return s.load(dst, p), nil } // commaok is the more complicated case because we have @@ -6206,14 +6244,14 @@ func (s *state) dottype(n *ir.TypeAssertExpr, commaok bool) (res, resok *ssa.Val s.startBlock(bOk) if tmp == nil { if direct { - s.vars[valVar] = s.newValue1(ssa.OpIData, n.Type(), iface) + s.vars[valVar] = s.newValue1(ssa.OpIData, dst, iface) } else { - p := s.newValue1(ssa.OpIData, types.NewPtr(n.Type()), iface) - s.vars[valVar] = s.load(n.Type(), p) + p := s.newValue1(ssa.OpIData, types.NewPtr(dst), iface) + s.vars[valVar] = s.load(dst, p) } } else { - p := s.newValue1(ssa.OpIData, types.NewPtr(n.Type()), iface) - s.move(n.Type(), addr, p) + p := s.newValue1(ssa.OpIData, types.NewPtr(dst), iface) + s.move(dst, addr, p) } s.vars[okVar] = s.constBool(true) s.endBlock() @@ -6222,9 +6260,9 @@ func (s *state) dottype(n *ir.TypeAssertExpr, commaok bool) (res, resok *ssa.Val // type assertion failed s.startBlock(bFail) if tmp == nil { - s.vars[valVar] = s.zeroVal(n.Type()) + s.vars[valVar] = s.zeroVal(dst) } else { - s.zero(n.Type(), addr) + s.zero(dst, addr) } s.vars[okVar] = s.constBool(false) s.endBlock() @@ -6233,10 +6271,10 @@ func (s *state) dottype(n *ir.TypeAssertExpr, commaok bool) (res, resok *ssa.Val // merge point s.startBlock(bEnd) if tmp == nil { - res = s.variable(valVar, n.Type()) + res = s.variable(valVar, dst) delete(s.vars, valVar) } else { - res = s.load(n.Type(), addr) + res = s.load(dst, addr) s.vars[memVar] = s.newValue1A(ssa.OpVarKill, types.TypeMem, tmp.(*ir.Name), s.mem()) } resok = s.variable(okVar, types.Types[types.TBOOL]) diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go index f0d37198d3..f95b6f4639 100644 --- a/src/cmd/compile/internal/walk/expr.go +++ b/src/cmd/compile/internal/walk/expr.go @@ -136,6 +136,10 @@ func walkExpr1(n ir.Node, init *ir.Nodes) ir.Node { n := n.(*ir.TypeAssertExpr) return walkDotType(n, init) + case ir.ODYNAMICDOTTYPE, ir.ODYNAMICDOTTYPE2: + n := n.(*ir.DynamicTypeAssertExpr) + return walkDynamicDotType(n, init) + case ir.OLEN, ir.OCAP: n := n.(*ir.UnaryExpr) return walkLenCap(n, init) @@ -669,6 +673,13 @@ func walkDotType(n *ir.TypeAssertExpr, init *ir.Nodes) ir.Node { return n } +// walkDynamicdotType walks an ODYNAMICDOTTYPE or ODYNAMICDOTTYPE2 node. +func walkDynamicDotType(n *ir.DynamicTypeAssertExpr, init *ir.Nodes) ir.Node { + n.X = walkExpr(n.X, init) + n.T = walkExpr(n.T, init) + return n +} + // walkIndex walks an OINDEX node. func walkIndex(n *ir.IndexExpr, init *ir.Nodes) ir.Node { n.X = walkExpr(n.X, init) diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go index fe6ae3fda0..c5fd0c1e1d 100644 --- a/src/cmd/compile/internal/walk/order.go +++ b/src/cmd/compile/internal/walk/order.go @@ -686,6 +686,10 @@ func (o *orderState) stmt(n ir.Node) { case ir.ODOTTYPE2: r := r.(*ir.TypeAssertExpr) r.X = o.expr(r.X, nil) + case ir.ODYNAMICDOTTYPE2: + r := r.(*ir.DynamicTypeAssertExpr) + r.X = o.expr(r.X, nil) + r.T = o.expr(r.T, nil) case ir.ORECV: r := r.(*ir.UnaryExpr) r.X = o.expr(r.X, nil) diff --git a/test/typeparam/dottype.go b/test/typeparam/dottype.go index 89a9b02111..c9c900c096 100644 --- a/test/typeparam/dottype.go +++ b/test/typeparam/dottype.go @@ -69,6 +69,11 @@ func main() { println(h[int](struct{ a, b int }{3, 5}).a) println(k[int](mybar(3)).bar()) + + type large struct {a,b,c,d,e,f int} + println(f[large](large{}).a) + l2, ok := f2[large](large{}) + println(l2.a, ok) } func shouldpanic(x func()) { defer func() { diff --git a/test/typeparam/dottype.out b/test/typeparam/dottype.out index 058c923a5c..8e6a3c2552 100644 --- a/test/typeparam/dottype.out +++ b/test/typeparam/dottype.out @@ -6,3 +6,5 @@ 0 false 3 3 +0 +0 true -- GitLab From 2fa8f00915893670964e05e14be7202f6f97760b Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 27 Jul 2021 19:14:30 -0700 Subject: [PATCH 0556/2500] [dev.typeparams] cmd/compile/internal/types2: implement type terms Type terms will be used to represent a type set as a list of type terms. Eventually, a type term may also include a method set. Groundwork for the implementation of lazily computed type sets for union expressions. Change-Id: Ic88750af21f697ce0b52a2259eff40bee115964c Reviewed-on: https://go-review.googlesource.com/c/go/+/338049 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/typeterm.go | 166 ++++++++++++++ .../compile/internal/types2/typeterm_test.go | 205 ++++++++++++++++++ 2 files changed, 371 insertions(+) create mode 100644 src/cmd/compile/internal/types2/typeterm.go create mode 100644 src/cmd/compile/internal/types2/typeterm_test.go diff --git a/src/cmd/compile/internal/types2/typeterm.go b/src/cmd/compile/internal/types2/typeterm.go new file mode 100644 index 0000000000..59a89cb004 --- /dev/null +++ b/src/cmd/compile/internal/types2/typeterm.go @@ -0,0 +1,166 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types2 + +// TODO(gri) use a different symbol instead of ⊤ for the set of all types +// (⊤ is hard to distinguish from T in some fonts) + +// A term describes elementary type sets: +// +// ∅: (*term)(nil) == ∅ // set of no types (empty set) +// ⊤: &term{} == ⊤ // set of all types +// T: &term{false, T} == {T} // set of type T +// ~t: &term{true, t} == {t' | under(t') == t} // set of types with underlying type t +// +type term struct { + tilde bool // valid if typ != nil + typ Type +} + +func (x *term) String() string { + switch { + case x == nil: + return "∅" + case x.typ == nil: + return "⊤" + case x.tilde: + return "~" + x.typ.String() + default: + return x.typ.String() + } +} + +// equal reports whether x and y represent the same type set. +func (x *term) equal(y *term) bool { + // easy cases + switch { + case x == nil || y == nil: + return x == y + case x.typ == nil || y.typ == nil: + return x.typ == y.typ + } + // ∅ ⊂ x, y ⊂ ⊤ + + return x.tilde == y.tilde && Identical(x.typ, y.typ) +} + +// union returns the union x ∪ y: zero, one, or two non-nil terms. +func (x *term) union(y *term) (_, _ *term) { + // easy cases + switch { + case x == nil && y == nil: + return nil, nil // ∅ ∪ ∅ == ∅ + case x == nil: + return y, nil // ∅ ∪ y == y + case y == nil: + return x, nil // x ∪ ∅ == x + case x.typ == nil: + return x, nil // ⊤ ∪ y == ⊤ + case y.typ == nil: + return y, nil // x ∪ ⊤ == ⊤ + } + // ∅ ⊂ x, y ⊂ ⊤ + + if x.disjoint(y) { + return x, y // x ∪ y == (x, y) if x ∩ y == ∅ + } + // x.typ == y.typ + + // ~t ∪ ~t == ~t + // ~t ∪ T == ~t + // T ∪ ~t == ~t + // T ∪ T == T + if x.tilde || !y.tilde { + return x, nil + } + return y, nil +} + +// intersect returns the intersection x ∩ y. +func (x *term) intersect(y *term) *term { + // easy cases + switch { + case x == nil || y == nil: + return nil // ∅ ∩ y == ∅ and ∩ ∅ == ∅ + case x.typ == nil: + return y // ⊤ ∩ y == y + case y.typ == nil: + return x // x ∩ ⊤ == x + } + // ∅ ⊂ x, y ⊂ ⊤ + + if x.disjoint(y) { + return nil // x ∩ y == ∅ if x ∩ y == ∅ + } + // x.typ == y.typ + + // ~t ∩ ~t == ~t + // ~t ∩ T == T + // T ∩ ~t == T + // T ∩ T == T + if !x.tilde || y.tilde { + return x + } + return y +} + +// includes reports whether t ∈ x. +func (x *term) includes(t Type) bool { + // easy cases + switch { + case x == nil: + return false // t ∈ ∅ == false + case x.typ == nil: + return true // t ∈ ⊤ == true + } + // ∅ ⊂ x ⊂ ⊤ + + u := t + if x.tilde { + u = under(u) + } + return Identical(x.typ, u) +} + +// subsetOf reports whether x ⊆ y. +func (x *term) subsetOf(y *term) bool { + // easy cases + switch { + case x == nil: + return true // ∅ ⊆ y == true + case y == nil: + return false // x ⊆ ∅ == false since x != ∅ + case y.typ == nil: + return true // x ⊆ ⊤ == true + case x.typ == nil: + return false // ⊤ ⊆ y == false since y != ⊤ + } + // ∅ ⊂ x, y ⊂ ⊤ + + if x.disjoint(y) { + return false // x ⊆ y == false if x ∩ y == ∅ + } + // x.typ == y.typ + + // ~t ⊆ ~t == true + // ~t ⊆ T == false + // T ⊆ ~t == true + // T ⊆ T == true + return !x.tilde || y.tilde +} + +// disjoint reports whether x ∩ y == ∅. +// x.typ and y.typ must not be nil. +func (x *term) disjoint(y *term) bool { + ux := x.typ + if y.tilde { + ux = under(ux) + } + uy := y.typ + if x.tilde { + uy = under(uy) + } + return !Identical(ux, uy) +} diff --git a/src/cmd/compile/internal/types2/typeterm_test.go b/src/cmd/compile/internal/types2/typeterm_test.go new file mode 100644 index 0000000000..4676fb0437 --- /dev/null +++ b/src/cmd/compile/internal/types2/typeterm_test.go @@ -0,0 +1,205 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types2 + +import ( + "strings" + "testing" +) + +var testTerms = map[string]*term{ + "∅": nil, + "⊤": &term{}, + "int": &term{false, Typ[Int]}, + "~int": &term{true, Typ[Int]}, + "string": &term{false, Typ[String]}, + "~string": &term{true, Typ[String]}, + // TODO(gri) add a defined type +} + +func TestTermString(t *testing.T) { + for want, x := range testTerms { + if got := x.String(); got != want { + t.Errorf("%v.String() == %v; want %v", x, got, want) + } + } +} + +func split(s string, n int) []string { + r := strings.Split(s, " ") + if len(r) != n { + panic("invalid test case: " + s) + } + return r +} + +func testTerm(name string) *term { + r, ok := testTerms[name] + if !ok { + panic("invalid test argument: " + name) + } + return r +} + +func TestTermEqual(t *testing.T) { + for _, test := range []string{ + "∅ ∅ T", + "⊤ ⊤ T", + "int int T", + "~int ~int T", + "∅ ⊤ F", + "∅ int F", + "∅ ~int F", + "⊤ int F", + "⊤ ~int F", + "int ~int F", + } { + args := split(test, 3) + x := testTerm(args[0]) + y := testTerm(args[1]) + want := args[2] == "T" + if got := x.equal(y); got != want { + t.Errorf("%v.equal(%v) = %v; want %v", x, y, got, want) + } + // equal is symmetric + x, y = y, x + if got := x.equal(y); got != want { + t.Errorf("%v.equal(%v) = %v; want %v", x, y, got, want) + } + } +} + +func TestTermUnion(t *testing.T) { + for _, test := range []string{ + "∅ ∅ ∅ ∅", + "∅ ⊤ ⊤ ∅", + "∅ int int ∅", + "∅ ~int ~int ∅", + "⊤ ⊤ ⊤ ∅", + "⊤ int ⊤ ∅", + "⊤ ~int ⊤ ∅", + "int int int ∅", + "int ~int ~int ∅", + "int string int string", + "int ~string int ~string", + "~int ~string ~int ~string", + + // union is symmetric, but the result order isn't - repeat symmetric cases explictly + "⊤ ∅ ⊤ ∅", + "int ∅ int ∅", + "~int ∅ ~int ∅", + "int ⊤ ⊤ ∅", + "~int ⊤ ⊤ ∅", + "~int int ~int ∅", + "string int string int", + "~string int ~string int", + "~string ~int ~string ~int", + } { + args := split(test, 4) + x := testTerm(args[0]) + y := testTerm(args[1]) + want1 := testTerm(args[2]) + want2 := testTerm(args[3]) + if got1, got2 := x.union(y); !got1.equal(want1) || !got2.equal(want2) { + t.Errorf("%v.union(%v) = %v, %v; want %v, %v", x, y, got1, got2, want1, want2) + } + } +} + +func TestTermIntersection(t *testing.T) { + for _, test := range []string{ + "∅ ∅ ∅", + "∅ ⊤ ∅", + "∅ int ∅", + "∅ ~int ∅", + "⊤ ⊤ ⊤", + "⊤ int int", + "⊤ ~int ~int", + "int int int", + "int ~int int", + "int string ∅", + "int ~string ∅", + "~int ~string ∅", + } { + args := split(test, 3) + x := testTerm(args[0]) + y := testTerm(args[1]) + want := testTerm(args[2]) + if got := x.intersect(y); !got.equal(want) { + t.Errorf("%v.intersect(%v) = %v; want %v", x, y, got, want) + } + // intersect is symmetric + x, y = y, x + if got := x.intersect(y); !got.equal(want) { + t.Errorf("%v.intersect(%v) = %v; want %v", x, y, got, want) + } + } +} + +func TestTermIncludes(t *testing.T) { + for _, test := range []string{ + "∅ int F", + "⊤ int T", + "int int T", + "~int int T", + "string int F", + "~string int F", + } { + args := split(test, 3) + x := testTerm(args[0]) + y := testTerm(args[1]).typ + want := args[2] == "T" + if got := x.includes(y); got != want { + t.Errorf("%v.includes(%v) = %v; want %v", x, y, got, want) + } + } +} + +func TestTermSubsetOf(t *testing.T) { + for _, test := range []string{ + "∅ ∅ T", + "⊤ ⊤ T", + "int int T", + "~int ~int T", + "∅ ⊤ T", + "∅ int T", + "∅ ~int T", + "⊤ int F", + "⊤ ~int F", + "int ~int T", + } { + args := split(test, 3) + x := testTerm(args[0]) + y := testTerm(args[1]) + want := args[2] == "T" + if got := x.subsetOf(y); got != want { + t.Errorf("%v.subsetOf(%v) = %v; want %v", x, y, got, want) + } + } +} + +func TestTermDisjoint(t *testing.T) { + for _, test := range []string{ + "int int F", + "~int ~int F", + "int ~int F", + "int string T", + "int ~string T", + "~int ~string T", + } { + args := split(test, 3) + x := testTerm(args[0]) + y := testTerm(args[1]) + want := args[2] == "T" + if got := x.disjoint(y); got != want { + t.Errorf("%v.disjoint(%v) = %v; want %v", x, y, got, want) + } + // disjoint is symmetric + x, y = y, x + if got := x.disjoint(y); got != want { + t.Errorf("%v.disjoint(%v) = %v; want %v", x, y, got, want) + } + } +} -- GitLab From ff0c0dbca6a7a3a3d6528481829679be4c9d7e94 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 27 Jul 2021 19:13:26 -0700 Subject: [PATCH 0557/2500] [dev.typeparams] cmd/compile/internal/types2: use type terms to represent unions This is just an internal representation change for now. Change-Id: I7e0126e9b17850ec020c2a60db13582761557bea Reviewed-on: https://go-review.googlesource.com/c/go/+/338092 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/infer.go | 18 ++- src/cmd/compile/internal/types2/interface.go | 6 +- src/cmd/compile/internal/types2/operand.go | 6 +- src/cmd/compile/internal/types2/predicates.go | 16 +-- .../compile/internal/types2/sizeof_test.go | 3 +- src/cmd/compile/internal/types2/subst.go | 22 +++- .../types2/testdata/examples/constraints.go2 | 6 +- src/cmd/compile/internal/types2/type.go | 2 +- src/cmd/compile/internal/types2/typeset.go | 7 ++ src/cmd/compile/internal/types2/typestring.go | 6 +- src/cmd/compile/internal/types2/union.go | 117 +++++++++++------- 11 files changed, 130 insertions(+), 79 deletions(-) diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index 6e7a217709..00548b402e 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -308,7 +308,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { } case *Union: - return w.isParameterizedList(t.types) + return w.isParameterizedTermList(t.terms) case *Signature: // t.tparams may not be nil if we are looking at a signature @@ -336,7 +336,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { return w.isParameterized(t.elem) case *Named: - return w.isParameterizedList(t.targs) + return w.isParameterizedTypeList(t.targs) case *TypeParam: // t must be one of w.tparams @@ -349,7 +349,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { return false } -func (w *tpWalker) isParameterizedList(list []Type) bool { +func (w *tpWalker) isParameterizedTypeList(list []Type) bool { for _, t := range list { if w.isParameterized(t) { return true @@ -358,6 +358,15 @@ func (w *tpWalker) isParameterizedList(list []Type) bool { return false } +func (w *tpWalker) isParameterizedTermList(list []*term) bool { + for _, t := range list { + if w.isParameterized(t.typ) { + return true + } + } + return false +} + // inferB returns the list of actual type arguments inferred from the type parameters' // bounds and an initial set of type arguments. If type inference is impossible because // unification fails, an error is reported if report is set to true, the resulting types @@ -466,7 +475,8 @@ func (check *Checker) structuralType(constraint Type) Type { if u, _ := types.(*Union); u != nil { if u.NumTerms() == 1 { // TODO(gri) do we need to respect tilde? - return u.types[0] + t, _ := u.Term(0) + return t } return nil } diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index cf8ec1a5e2..fc1f5ffe00 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -30,7 +30,7 @@ func (t *Interface) is(f func(Type, bool) bool) bool { // TODO(gri) should settle on top or nil to represent this case return false // we must have at least one type! (was bug) case *Union: - return t.is(func(typ Type, tilde bool) bool { return f(typ, tilde) }) + return t.is(func(t *term) bool { return f(t.typ, t.tilde) }) default: return f(t, false) } @@ -260,8 +260,8 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType sortMethods(ityp.methods) // Compute type set with a non-nil *Checker as soon as possible - // to report any errors. Subsequent uses of type sets should be - // using this computed type set and won't need to pass in a *Checker. + // to report any errors. Subsequent uses of type sets will use + // this computed type set and won't need to pass in a *Checker. check.later(func() { computeTypeSet(check, iface.Pos(), ityp) }) } diff --git a/src/cmd/compile/internal/types2/operand.go b/src/cmd/compile/internal/types2/operand.go index 83cc239d93..01c720d1f7 100644 --- a/src/cmd/compile/internal/types2/operand.go +++ b/src/cmd/compile/internal/types2/operand.go @@ -270,13 +270,13 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er // x is an untyped value representable by a value of type T. if isUntyped(Vu) { if t, ok := Tu.(*Union); ok { - return t.is(func(t Type, tilde bool) bool { + return t.is(func(t *term) bool { // TODO(gri) this could probably be more efficient - if tilde { + if t.tilde { // TODO(gri) We need to check assignability // for the underlying type of x. } - ok, _ := x.assignableTo(check, t, reason) + ok, _ := x.assignableTo(check, t.typ, reason) return ok }), _IncompatibleAssign } diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index e448ade9e5..cd9fa3f564 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -238,20 +238,8 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { // types - each type appears exactly once. Thus, two union types // must contain the same number of types to have chance of // being equal. - if y, ok := y.(*Union); ok && x.NumTerms() == y.NumTerms() { - // Every type in x.types must be in y.types. - // Quadratic algorithm, but probably good enough for now. - // TODO(gri) we need a fast quick type ID/hash for all types. - L: - for i, xt := range x.types { - for j, yt := range y.types { - if Identical(xt, yt) && x.tilde[i] == y.tilde[j] { - continue L // x is in y.types - } - } - return false // x is not in y.types - } - return true + if y, ok := y.(*Union); ok { + return identicalTerms(x.terms, y.terms) } case *Interface: diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go index a62b7cb3e2..70cf3709e5 100644 --- a/src/cmd/compile/internal/types2/sizeof_test.go +++ b/src/cmd/compile/internal/types2/sizeof_test.go @@ -27,12 +27,13 @@ func TestSizeof(t *testing.T) { {Pointer{}, 8, 16}, {Tuple{}, 12, 24}, {Signature{}, 44, 88}, - {Union{}, 24, 48}, + {Union{}, 12, 24}, {Interface{}, 40, 80}, {Map{}, 16, 32}, {Chan{}, 12, 24}, {Named{}, 88, 168}, {TypeParam{}, 28, 48}, + {term{}, 12, 24}, {top{}, 0, 0}, // Objects diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 87e3e3018e..fc71343431 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -145,12 +145,12 @@ func (subst *subster) typ(typ Type) Type { } case *Union: - types, copied := subst.typeList(t.types) + terms, copied := subst.termList(t.terms) if copied { // TODO(gri) Remove duplicates that may have crept in after substitution // (unlikely but possible). This matters for the Identical // predicate on unions. - return newUnion(types, t.tilde) + return &Union{terms} } case *Interface: @@ -386,3 +386,21 @@ func (subst *subster) typeList(in []Type) (out []Type, copied bool) { } return } + +func (subst *subster) termList(in []*term) (out []*term, copied bool) { + out = in + for i, t := range in { + if u := subst.typ(t.typ); u != t.typ { + if !copied { + // first function that got substituted => allocate new out slice + // and copy all functions + new := make([]*term, len(in)) + copy(new, out) + out = new + copied = true + } + out[i] = &term{t.tilde, u} + } + } + return +} diff --git a/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 b/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 index d9805fe694..28aa19bb12 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 @@ -31,9 +31,9 @@ type ( _ interface{int|~ /* ERROR duplicate term int */ int } _ interface{~int|~ /* ERROR duplicate term int */ int } - // For now we do not permit interfaces with ~ or in unions. - _ interface{~ /* ERROR cannot use interface */ interface{}} - _ interface{int|interface /* ERROR cannot use interface */ {}} + // For now we do not permit interfaces with methods in unions. + _ interface{~ /* ERROR invalid use of ~ */ interface{}} + _ interface{int|interface /* ERROR cannot use .* in union */ { m() }} ) type ( diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index b41b50393d..80054372bc 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -60,7 +60,7 @@ func optype(typ Type) Type { // If we have a union with a single entry, ignore // any tilde because under(~t) == under(t). if u, _ := a.(*Union); u != nil && u.NumTerms() == 1 { - a = u.types[0] + a, _ = u.Term(0) } if a != typ { // a != typ and a is a type parameter => under(a) != typ, so this is ok diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index cc28625070..5a334b2f53 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -42,6 +42,13 @@ func (s *TypeSet) IsComparable() bool { return s.comparable && tcomparable } +// TODO(gri) IsTypeSet is not a great name. Find a better one. + +// IsTypeSet reports whether the type set s is represented by a finite set of underlying types. +func (s *TypeSet) IsTypeSet() bool { + return !s.comparable && len(s.methods) == 0 +} + // NumMethods returns the number of methods available. func (s *TypeSet) NumMethods() int { return len(s.methods) } diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 74d2f1dc51..1da3f7f8ed 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -162,14 +162,14 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { buf.WriteString("⊥") break } - for i, e := range t.types { + for i, t := range t.terms { if i > 0 { buf.WriteByte('|') } - if t.tilde[i] { + if t.tilde { buf.WriteByte('~') } - writeType(buf, e, qf, visited) + writeType(buf, t.typ, qf, visited) } case *Interface: diff --git a/src/cmd/compile/internal/types2/union.go b/src/cmd/compile/internal/types2/union.go index 5983a73ec6..1215ef9057 100644 --- a/src/cmd/compile/internal/types2/union.go +++ b/src/cmd/compile/internal/types2/union.go @@ -10,10 +10,8 @@ import "cmd/compile/internal/syntax" // API // A Union represents a union of terms. -// A term is a type with a ~ (tilde) flag. type Union struct { - types []Type // types are unique - tilde []bool // if tilde[i] is set, terms[i] is of the form ~T + terms []*term } // NewUnion returns a new Union type with the given terms (types[i], tilde[i]). @@ -21,9 +19,9 @@ type Union struct { // of no types. func NewUnion(types []Type, tilde []bool) *Union { return newUnion(types, tilde) } -func (u *Union) IsEmpty() bool { return len(u.types) == 0 } -func (u *Union) NumTerms() int { return len(u.types) } -func (u *Union) Term(i int) (Type, bool) { return u.types[i], u.tilde[i] } +func (u *Union) IsEmpty() bool { return len(u.terms) == 0 } +func (u *Union) NumTerms() int { return len(u.terms) } +func (u *Union) Term(i int) (Type, bool) { t := u.terms[i]; return t.typ, t.tilde } func (u *Union) Underlying() Type { return u } func (u *Union) String() string { return TypeString(u, nil) } @@ -39,18 +37,20 @@ func newUnion(types []Type, tilde []bool) *Union { return emptyUnion } t := new(Union) - t.types = types - t.tilde = tilde + t.terms = make([]*term, len(types)) + for i, typ := range types { + t.terms[i] = &term{tilde[i], typ} + } return t } -// is reports whether f returned true for all terms (type, tilde) of u. -func (u *Union) is(f func(Type, bool) bool) bool { +// is reports whether f returns true for all terms of u. +func (u *Union) is(f func(*term) bool) bool { if u.IsEmpty() { return false } - for i, t := range u.types { - if !f(t, u.tilde[i]) { + for _, t := range u.terms { + if !f(t) { return false } } @@ -62,8 +62,8 @@ func (u *Union) underIs(f func(Type) bool) bool { if u.IsEmpty() { return false } - for _, t := range u.types { - if !f(under(t)) { + for _, t := range u.terms { + if !f(under(t.typ)) { return false } } @@ -83,7 +83,7 @@ func parseUnion(check *Checker, tlist []syntax.Expr) Type { } // Ensure that each type is only present once in the type list. - // It's ok to do this check at the end because it's not a requirement + // It's ok to do this check later because it's not a requirement // for correctness of the code. // Note: This is a quadratic algorithm, but unions tend to be short. check.later(func() { @@ -96,7 +96,7 @@ func parseUnion(check *Checker, tlist []syntax.Expr) Type { x := tlist[i] pos := syntax.StartPos(x) // We may not know the position of x if it was a typechecker- - // introduced ~T type of a type list entry T. Use the position + // introduced ~T term for a type list entry T. Use the position // of T instead. // TODO(gri) remove this test once we don't support type lists anymore if !pos.IsKnown() { @@ -106,13 +106,24 @@ func parseUnion(check *Checker, tlist []syntax.Expr) Type { } u := under(t) - if tilde[i] && !Identical(u, t) { - check.errorf(x, "invalid use of ~ (underlying type of %s is %s)", t, u) - continue // don't report another error for t + f, _ := u.(*Interface) + if tilde[i] { + if f != nil { + check.errorf(x, "invalid use of ~ (%s is an interface)", t) + continue // don't report another error for t + } + + if !Identical(u, t) { + check.errorf(x, "invalid use of ~ (underlying type of %s is %s)", t, u) + continue // don't report another error for t + } } - if _, ok := u.(*Interface); ok { - // A single type with a ~ is a single-term union. - check.errorf(pos, "cannot use interface %s with ~ or inside a union (implementation restriction)", t) + + // Stand-alone embedded interfaces are ok and are handled by the single-type case + // in the beginning. Embedded interfaces with tilde are excluded above. If we reach + // here, we must have at least two terms in the union. + if f != nil && !f.typeSet().IsTypeSet() { + check.errorf(pos, "cannot use %s in union (interface contains methods)", t) continue // don't report another error for t } @@ -164,25 +175,7 @@ func intersect(x, y Type) (r Type) { yu, _ := y.(*Union) switch { case xu != nil && yu != nil: - // Quadratic algorithm, but good enough for now. - // TODO(gri) fix asymptotic performance - var types []Type - var tilde []bool - for j, y := range yu.types { - yt := yu.tilde[j] - if r, rt := xu.intersect(y, yt); r != nil { - // Terms x[i] and y[j] match: Select the one that - // is not a ~t because that is the intersection - // type. If both are ~t, they are identical: - // T ∩ T = T - // T ∩ ~t = T - // ~t ∩ T = T - // ~t ∩ ~t = ~t - types = append(types, r) - tilde = append(tilde, rt) - } - } - return newUnion(types, tilde) + return &Union{intersectTerms(xu.terms, yu.terms)} case xu != nil: if r, _ := xu.intersect(y, false); r != nil { @@ -216,14 +209,16 @@ func includes(list []Type, typ Type) bool { // intersect computes the intersection of the union u and term (y, yt) // and returns the intersection term, if any. Otherwise the result is // (nil, false). +// TODO(gri) this needs to cleaned up/removed once we switch to lazy +// union type set computation. func (u *Union) intersect(y Type, yt bool) (Type, bool) { under_y := under(y) - for i, x := range u.types { - xt := u.tilde[i] + for _, x := range u.terms { + xt := x.tilde // determine which types xx, yy to compare - xx := x + xx := x.typ if yt { - xx = under(x) + xx = under(xx) } yy := y if xt { @@ -239,3 +234,35 @@ func (u *Union) intersect(y Type, yt bool) (Type, bool) { } return nil, false } + +func identicalTerms(list1, list2 []*term) bool { + if len(list1) != len(list2) { + return false + } + // Every term in list1 must be in list2. + // Quadratic algorithm, but probably good enough for now. + // TODO(gri) we need a fast quick type ID/hash for all types. +L: + for _, x := range list1 { + for _, y := range list2 { + if x.equal(y) { + continue L // x is in list2 + } + } + return false + } + return true +} + +func intersectTerms(list1, list2 []*term) (list []*term) { + // Quadratic algorithm, but good enough for now. + // TODO(gri) fix asymptotic performance + for _, x := range list1 { + for _, y := range list2 { + if r := x.intersect(y); r != nil { + list = append(list, r) + } + } + } + return +} -- GitLab From c079b6baaa781e71a48661c05063d1d2754937f8 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 28 Jul 2021 13:50:09 -0700 Subject: [PATCH 0558/2500] [dev.typeparams] cmd/compile/internal/types2: trigger verification while resolving instance This is a straight port of CL 335978 with minor adjustements to white space and an error message. Change-Id: Icfcb562f75802a119ce5d02427bffecf7e279b2f Reviewed-on: https://go-review.googlesource.com/c/go/+/338097 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/instance.go | 2 +- .../compile/internal/types2/instantiate.go | 59 +++++++++++-------- .../internal/types2/testdata/check/issues.go2 | 4 +- 3 files changed, 37 insertions(+), 28 deletions(-) diff --git a/src/cmd/compile/internal/types2/instance.go b/src/cmd/compile/internal/types2/instance.go index df0fc17ba7..711d7de53c 100644 --- a/src/cmd/compile/internal/types2/instance.go +++ b/src/cmd/compile/internal/types2/instance.go @@ -26,7 +26,7 @@ func (n *Named) expand() { // tparams. This is done implicitly by the call to n.TParams, but making it // explicit is harmless: load is idempotent. n.load() - inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams(), n.targs, n.instance.posList, n.instance.verify) + inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams(), n.targs, n.instance.posList) n.underlying = inst n.fromRHS = inst n.instance = nil diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 1294b08490..7a40cea889 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -54,10 +54,15 @@ func (check *Checker) Instantiate(pos syntax.Pos, typ Type, targs []Type, posLis // only types and functions can be generic panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } - return check.instantiate(pos, typ, tparams, targs, posList, verify) + + inst := check.instantiate(pos, typ, tparams, targs, posList) + if verify && len(tparams) == len(targs) { + check.verify(pos, tparams, targs, posList) + } + return inst } -func (check *Checker) instantiate(pos syntax.Pos, typ Type, tparams []*TypeName, targs []Type, posList []syntax.Pos, verify bool) (res Type) { +func (check *Checker) instantiate(pos syntax.Pos, typ Type, tparams []*TypeName, targs []Type, posList []syntax.Pos) (res Type) { // the number of supplied types must match the number of type parameters if len(targs) != len(tparams) { // TODO(gri) provide better error message @@ -67,9 +72,6 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, tparams []*TypeName, } panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, len(targs), len(tparams))) } - if verify && check == nil { - panic("cannot have nil receiver if verify is set") - } if check != nil && check.conf.Trace { check.trace(pos, "-- instantiating %s with %s", typ, typeListString(targs)) @@ -93,24 +95,7 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, tparams []*TypeName, return typ // nothing to do (minor optimization) } - smap := makeSubstMap(tparams, targs) - - // check bounds - if verify { - for i, tname := range tparams { - // best position for error reporting - pos := pos - if i < len(posList) { - pos = posList[i] - } - // stop checking bounds after the first failure - if !check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap) { - break - } - } - } - - return check.subst(pos, typ, smap) + return check.subst(pos, typ, makeSubstMap(tparams, targs)) } // InstantiateLazy is like Instantiate, but avoids actually @@ -120,10 +105,16 @@ func (check *Checker) InstantiateLazy(pos syntax.Pos, typ Type, targs []Type, po // Don't use asNamed here: we don't want to expand the base during lazy // instantiation. base := typ.(*Named) - if base == nil { panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } + + if verify && len(base.tparams) == len(targs) { + check.later(func() { + check.verify(pos, base.tparams, targs, posList) + }) + } + h := instantiatedHash(base, targs) if check != nil { // typ may already have been instantiated with identical type arguments. In @@ -148,6 +139,26 @@ func (check *Checker) InstantiateLazy(pos syntax.Pos, typ Type, targs []Type, po return named } +func (check *Checker) verify(pos syntax.Pos, tparams []*TypeName, targs []Type, posList []syntax.Pos) { + if check == nil { + panic("cannot have nil Checker if verifying constraints") + } + + smap := makeSubstMap(tparams, targs) + for i, tname := range tparams { + // best position for error reporting + pos := pos + if i < len(posList) { + pos = posList[i] + } + + // stop checking bounds after the first failure + if !check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap) { + break + } + } +} + // satisfies reports whether the type argument targ satisfies the constraint of type parameter // parameter tpar (after any of its type parameters have been substituted through smap). // A suitable error is reported if the result is false. diff --git a/src/cmd/compile/internal/types2/testdata/check/issues.go2 b/src/cmd/compile/internal/types2/testdata/check/issues.go2 index e29357de0b..1ede383ebe 100644 --- a/src/cmd/compile/internal/types2/testdata/check/issues.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/issues.go2 @@ -74,10 +74,8 @@ func (u T2[U]) Add1() U { return u.s + 1 } -// TODO(rfindley): we should probably report an error here as well, not -// just when the type is first instantiated. func NewT2[U any]() T2[U /* ERROR U has no constraints */ ] { - return T2[U]{} + return T2[U /* ERROR U has no constraints */ ]{} } func _() { -- GitLab From af903261e7e6af8ce932433cf87a60381781bfb9 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 28 Jul 2021 14:01:06 -0700 Subject: [PATCH 0559/2500] [dev.typeparams] go/types, types2: remove instance.verify field (cleanup) This field is not needed anymore. Follow-up on CL 335978 and CL 338097. Change-Id: I8032e5153ba65c6a4aaf6575ac6d5a15a61f1b81 Reviewed-on: https://go-review.googlesource.com/c/go/+/338098 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/instance.go | 1 - src/cmd/compile/internal/types2/instantiate.go | 8 ++------ src/go/types/instance.go | 1 - src/go/types/instantiate.go | 8 ++------ 4 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/cmd/compile/internal/types2/instance.go b/src/cmd/compile/internal/types2/instance.go index 711d7de53c..e18688771c 100644 --- a/src/cmd/compile/internal/types2/instance.go +++ b/src/cmd/compile/internal/types2/instance.go @@ -15,7 +15,6 @@ import "cmd/compile/internal/syntax" type instance struct { pos syntax.Pos // position of type instantiation; for error reporting only posList []syntax.Pos // position of each targ; for error reporting only - verify bool // if set, check constraint satisfaction upon instantiation } // expand ensures that the underlying type of n is instantiated. diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 7a40cea889..ee790ba6d6 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -127,15 +127,11 @@ func (check *Checker) InstantiateLazy(pos syntax.Pos, typ Type, targs []Type, po tname := NewTypeName(pos, base.obj.pkg, base.obj.name, nil) named := check.newNamed(tname, base, nil, nil, nil) // methods and tparams are set when named is loaded. named.targs = targs - named.instance = &instance{ - pos: pos, - posList: posList, - verify: verify, - } - + named.instance = &instance{pos, posList} if check != nil { check.typMap[h] = named } + return named } diff --git a/src/go/types/instance.go b/src/go/types/instance.go index 7e158ea352..5e0447b434 100644 --- a/src/go/types/instance.go +++ b/src/go/types/instance.go @@ -14,7 +14,6 @@ type instance struct { check *Checker pos token.Pos // position of type instantiation; for error reporting only posList []token.Pos // position of each targ; for error reporting only - verify bool // if set, constraint satisfaction is verified } // complete ensures that the underlying type of n is instantiated. diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 7e2f3173c3..1d3bbc2667 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -124,15 +124,11 @@ func (check *Checker) InstantiateLazy(pos token.Pos, typ Type, targs []Type, pos tname := NewTypeName(pos, base.obj.pkg, base.obj.name, nil) named := check.newNamed(tname, base, nil, base.TParams(), base.methods) // methods are instantiated lazily named.targs = targs - named.instance = &instance{ - check: check, - pos: pos, - posList: posList, - verify: verify, - } + named.instance = &instance{check, pos, posList} if check != nil { check.typMap[h] = named } + return named } -- GitLab From 27552e9172c5a9f7bbd8428c6e30eac14bb5e0b0 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 28 Jul 2021 15:29:19 -0700 Subject: [PATCH 0560/2500] [dev.typeparams] cmd/compile: set type parameter indices when they are bound This is a port of CL 336249 with adjustments due to slightly different handling of type parameter declaration in types2. The CL also contains adjustments to the compiler front-end. With this change it is not necessary to export type parameter indices. Filed issue #47451 so we don't forget. Change-Id: I2834f7be313fcb4763dff2a9058f1983ee6a81b3 Reviewed-on: https://go-review.googlesource.com/c/go/+/338192 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/importer/iimport.go | 7 ++- src/cmd/compile/internal/noder/decl.go | 6 +-- src/cmd/compile/internal/noder/expr.go | 2 +- src/cmd/compile/internal/noder/reader2.go | 2 +- src/cmd/compile/internal/noder/types.go | 10 ++-- src/cmd/compile/internal/noder/writer.go | 26 +++++++---- src/cmd/compile/internal/types2/api_test.go | 2 +- .../compile/internal/types2/assignments.go | 2 +- src/cmd/compile/internal/types2/builtins.go | 3 +- src/cmd/compile/internal/types2/call.go | 20 ++++---- src/cmd/compile/internal/types2/decl.go | 12 ++--- src/cmd/compile/internal/types2/index.go | 2 +- src/cmd/compile/internal/types2/instance.go | 2 +- .../compile/internal/types2/instantiate.go | 10 ++-- src/cmd/compile/internal/types2/lookup.go | 22 ++++----- src/cmd/compile/internal/types2/named.go | 12 ++--- src/cmd/compile/internal/types2/object.go | 4 +- src/cmd/compile/internal/types2/predicates.go | 2 +- src/cmd/compile/internal/types2/signature.go | 31 +++++++------ .../compile/internal/types2/sizeof_test.go | 4 +- src/cmd/compile/internal/types2/subst.go | 4 +- src/cmd/compile/internal/types2/typeparam.go | 46 +++++++++++++++++-- src/cmd/compile/internal/types2/typestring.go | 4 +- 23 files changed, 142 insertions(+), 93 deletions(-) diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index 453fa40f2d..999b2aa1dc 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -368,10 +368,13 @@ func (r *importReader) obj(name string) { if r.p.exportVersion < iexportVersionGenerics { errorf("unexpected type param type") } - index := int(r.int64()) + // Type parameter indices are lazily "allocated". + // There's no need to export them anymore. + // TODO change the export format accordingly + _ = int(r.int64()) name0, sub := parseSubscript(name) tn := types2.NewTypeName(pos, r.currPkg, name0, nil) - t := (*types2.Checker)(nil).NewTypeParam(tn, index, nil) + t := (*types2.Checker)(nil).NewTypeParam(tn, nil) if sub == 0 { errorf("missing subscript") } diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go index 96abbe66ae..2416d1a49e 100644 --- a/src/cmd/compile/internal/noder/decl.go +++ b/src/cmd/compile/internal/noder/decl.go @@ -167,10 +167,10 @@ func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) { ntyp.SetUnderlying(g.typeExpr(decl.Type)) tparams := otyp.(*types2.Named).TParams() - if len(tparams) > 0 { - rparams := make([]*types.Type, len(tparams)) + if n := tparams.Len(); n > 0 { + rparams := make([]*types.Type, n) for i := range rparams { - rparams[i] = g.typ(tparams[i].Type()) + rparams[i] = g.typ(tparams.At(i).Type()) } // This will set hasTParam flag if any rparams are not concrete types. ntyp.SetRParams(rparams) diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 131ee89cbb..a0d3cad699 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -337,7 +337,7 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto if wantPtr { recvType2Base = types2.AsPointer(recvType2).Elem() } - if len(types2.AsNamed(recvType2Base).TParams()) > 0 { + if types2.AsNamed(recvType2Base).TParams().Len() > 0 { // recvType2 is the original generic type that is // instantiated for this method call. // selinfo.Recv() is the instantiated type diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index 297fa59439..3e310e26c4 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -481,7 +481,7 @@ func (r *reader2) typeParamNames() []*types2.TypeName { pkg, name := r.localIdent() names[i] = types2.NewTypeName(pos, pkg, name, nil) - r.dict.tparams[i] = r.p.check.NewTypeParam(names[i], i, nil) + r.dict.tparams[i] = r.p.check.NewTypeParam(names[i], nil) } for i, bound := range r.dict.bounds { diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index d073526ada..3f7280a823 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -304,9 +304,9 @@ func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) { } else { meth2 = ir.NewNameAt(meth.Pos(), newsym) rparams := types2.AsSignature(m.Type()).RParams() - tparams := make([]*types.Type, len(rparams)) - for i, rparam := range rparams { - tparams[i] = g.typ1(rparam.Type()) + tparams := make([]*types.Type, rparams.Len()) + for i := range tparams { + tparams[i] = g.typ1(rparams.At(i).Type()) } assert(len(tparams) == len(targs)) ts := typecheck.Tsubster{ @@ -336,9 +336,9 @@ func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) { func (g *irgen) signature(recv *types.Field, sig *types2.Signature) *types.Type { tparams2 := sig.TParams() - tparams := make([]*types.Field, len(tparams2)) + tparams := make([]*types.Field, tparams2.Len()) for i := range tparams { - tp := tparams2[i] + tp := tparams2.At(i) tparams[i] = types.NewField(g.pos(tp), g.sym(tp), g.typ1(tp.Type())) } diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 7b2285556e..0fc7e4f38c 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -299,7 +299,7 @@ func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo { // Type aliases can refer to uninstantiated generic types, so we // might see len(TParams) != 0 && len(TArgs) == 0 here. // TODO(mdempsky): Revisit after #46477 is resolved. - assert(len(typ.TParams()) == len(typ.TArgs()) || len(typ.TArgs()) == 0) + assert(typ.TParams().Len() == len(typ.TArgs()) || len(typ.TArgs()) == 0) // TODO(mdempsky): Why do we need to loop here? orig := typ @@ -615,9 +615,10 @@ func (w *writer) objDict(obj types2.Object, dict *writerDict) { w.len(len(dict.implicits)) tparams := objTypeParams(obj) - w.len(len(tparams)) - for _, tparam := range tparams { - w.typ(tparam.Type().(*types2.TypeParam).Bound()) + ntparams := tparams.Len() + w.len(ntparams) + for i := 0; i < ntparams; i++ { + w.typ(tparams.At(i).Type().(*types2.TypeParam).Bound()) } nderived := len(dict.derived) @@ -641,10 +642,12 @@ func (w *writer) objDict(obj types2.Object, dict *writerDict) { assert(len(dict.funcs) == nfuncs) } -func (w *writer) typeParamNames(tparams []*types2.TypeName) { +func (w *writer) typeParamNames(tparams *types2.TypeParams) { w.sync(syncTypeParamNames) - for _, tparam := range tparams { + ntparams := tparams.Len() + for i := 0; i < ntparams; i++ { + tparam := tparams.At(i) w.pos(tparam) w.localIdent(tparam) } @@ -1468,13 +1471,16 @@ type declCollector struct { func (c *declCollector) withTParams(obj types2.Object) *declCollector { tparams := objTypeParams(obj) - if len(tparams) == 0 { + n := tparams.Len() + if n == 0 { return c } copy := *c copy.implicits = copy.implicits[:len(copy.implicits):len(copy.implicits)] - copy.implicits = append(copy.implicits, objTypeParams(obj)...) + for i := 0; i < n; i++ { + copy.implicits = append(copy.implicits, tparams.At(i)) + } return © } @@ -1705,7 +1711,7 @@ func (w *writer) pkgDecl(decl syntax.Decl) { // TODO(mdempsky): Revisit after #46477 is resolved. if name.IsAlias() { named, ok := name.Type().(*types2.Named) - if ok && len(named.TParams()) != 0 && len(named.TArgs()) == 0 { + if ok && named.TParams().Len() != 0 && len(named.TArgs()) == 0 { break } } @@ -1851,7 +1857,7 @@ func fieldIndex(info *types2.Info, str *types2.Struct, key *syntax.Name) int { } // objTypeParams returns the type parameters on the given object. -func objTypeParams(obj types2.Object) []*types2.TypeName { +func objTypeParams(obj types2.Object) *types2.TypeParams { switch obj := obj.(type) { case *types2.Func: sig := obj.Type().(*types2.Signature) diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index 74e3da3fe1..1d3347a6de 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -1857,7 +1857,7 @@ func TestInstantiate(t *testing.T) { // type T should have one type parameter T := pkg.Scope().Lookup("T").Type().(*Named) - if n := len(T.TParams()); n != 1 { + if n := T.TParams().Len(); n != 1 { t.Fatalf("expected 1 type parameter; found %d", n) } diff --git a/src/cmd/compile/internal/types2/assignments.go b/src/cmd/compile/internal/types2/assignments.go index 583118c8b2..6184fc2ea5 100644 --- a/src/cmd/compile/internal/types2/assignments.go +++ b/src/cmd/compile/internal/types2/assignments.go @@ -68,7 +68,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { // x.typ is typed // A generic (non-instantiated) function value cannot be assigned to a variable. - if sig := asSignature(x.typ); sig != nil && len(sig.tparams) > 0 { + if sig := asSignature(x.typ); sig != nil && sig.TParams().Len() > 0 { check.errorf(x, "cannot use generic function %s without instantiation in %s", x, context) } diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index b9fcf3c898..7ef9e7be63 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -837,7 +837,8 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { // type param is placed in the current package so export/import // works as expected. tpar := NewTypeName(nopos, check.pkg, "", nil) - ptyp := check.NewTypeParam(tpar, tp.index, &emptyInterface) // assigns type to tpar as a side-effect + ptyp := check.NewTypeParam(tpar, &emptyInterface) // assigns type to tpar as a side-effect + ptyp.index = tp.index tsum := newUnion(rtypes, tildes) ptyp.bound = &Interface{complete: true, tset: &TypeSet{types: tsum}} diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 0d9637e696..dee49b44a4 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -26,7 +26,7 @@ func (check *Checker) funcInst(x *operand, inst *syntax.IndexExpr) { // check number of type arguments (got) vs number of type parameters (want) sig := x.typ.(*Signature) - got, want := len(targs), len(sig.tparams) + got, want := len(targs), sig.TParams().Len() if !useConstraintTypeInference && got != want || got > want { check.errorf(xlist[got-1], "got %d type arguments but want %d", got, want) x.mode = invalid @@ -37,7 +37,7 @@ func (check *Checker) funcInst(x *operand, inst *syntax.IndexExpr) { // if we don't have enough type arguments, try type inference inferred := false if got < want { - targs = check.infer(inst.Pos(), sig.tparams, targs, nil, nil, true) + targs = check.infer(inst.Pos(), sig.TParams().list(), targs, nil, nil, true) if targs == nil { // error was already reported x.mode = invalid @@ -155,7 +155,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { assert(len(targs) == len(xlist)) // check number of type arguments (got) vs number of type parameters (want) - got, want := len(targs), len(sig.tparams) + got, want := len(targs), sig.TParams().Len() if got > want { check.errorf(xlist[want], "got %d type arguments but want %d", got, want) check.use(call.ArgList...) @@ -189,7 +189,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { // if type inference failed, a parametrized result must be invalidated // (operands cannot have a parametrized type) - if x.mode == value && len(sig.tparams) > 0 && isParameterized(sig.tparams, x.typ) { + if x.mode == value && sig.TParams().Len() > 0 && isParameterized(sig.TParams().list(), x.typ) { x.mode = invalid } @@ -317,10 +317,10 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T } // infer type arguments and instantiate signature if necessary - if len(sig.tparams) > 0 { + if sig.TParams().Len() > 0 { // TODO(gri) provide position information for targs so we can feed // it to the instantiate call for better error reporting - targs = check.infer(call.Pos(), sig.tparams, targs, sigParams, args, true) + targs := check.infer(call.Pos(), sig.TParams().list(), targs, sigParams, args, true) if targs == nil { return // error already reported } @@ -334,7 +334,7 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T // need to compute it from the adjusted list; otherwise we can // simply use the result signature's parameter list. if adjusted { - sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(sig.tparams, targs)).(*Tuple) + sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(sig.TParams().list(), targs)).(*Tuple) } else { sigParams = rsig.params } @@ -516,7 +516,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) { // the signature accordingly. // TODO(gri) factor this code out sig := m.typ.(*Signature) - if len(sig.rparams) > 0 { + if sig.RParams().Len() > 0 { // For inference to work, we must use the receiver type // matching the receiver in the actual method declaration. // If the method is embedded, the matching receiver is the @@ -545,7 +545,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) { // the receiver type arguments here, the receiver must be be otherwise invalid // and an error has been reported elsewhere. arg := operand{mode: variable, expr: x.expr, typ: recv} - targs := check.infer(m.pos, sig.rparams, nil, NewTuple(sig.recv), []*operand{&arg}, false /* no error reporting */) + targs := check.infer(m.pos, sig.RParams().list(), nil, NewTuple(sig.recv), []*operand{&arg}, false /* no error reporting */) //check.dump("### inferred targs = %s", targs) if targs == nil { // We may reach here if there were other errors (see issue #40056). @@ -555,7 +555,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) { // (If we modify m, some tests will fail; possibly because the m is in use.) // TODO(gri) investigate and provide a correct explanation here copy := *m - copy.typ = check.subst(e.Pos(), m.typ, makeSubstMap(sig.rparams, targs)) + copy.typ = check.subst(e.Pos(), m.typ, makeSubstMap(sig.RParams().list(), targs)) obj = © } // TODO(gri) we also need to do substitution for parameterized interface methods diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 6ca8f75e9a..c867d87603 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -575,20 +575,20 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named named.underlying = under(named) // If the RHS is a type parameter, it must be from this type declaration. - if tpar, _ := named.underlying.(*TypeParam); tpar != nil && tparamIndex(named.tparams, tpar) < 0 { + if tpar, _ := named.underlying.(*TypeParam); tpar != nil && tparamIndex(named.tparams.list(), tpar) < 0 { check.errorf(tdecl.Type, "cannot use function type parameter %s as RHS in type declaration", tpar) named.underlying = Typ[Invalid] } } -func (check *Checker) collectTypeParams(list []*syntax.Field) []*TypeName { +func (check *Checker) collectTypeParams(list []*syntax.Field) *TypeParams { tparams := make([]*TypeName, len(list)) // Declare type parameters up-front. // The scope of type parameters starts at the beginning of the type parameter // list (so we can have mutually recursive parameterized type bounds). for i, f := range list { - tparams[i] = check.declareTypeParam(i, f.Name) + tparams[i] = check.declareTypeParam(f.Name) } var bound Type @@ -602,12 +602,12 @@ func (check *Checker) collectTypeParams(list []*syntax.Field) []*TypeName { tparams[i].typ.(*TypeParam).bound = bound } - return tparams + return bindTParams(tparams) } -func (check *Checker) declareTypeParam(index int, name *syntax.Name) *TypeName { +func (check *Checker) declareTypeParam(name *syntax.Name) *TypeName { tpar := NewTypeName(name.Pos(), check.pkg, name.Value, nil) - check.NewTypeParam(tpar, index, nil) // assigns type to tpar as a side-effect + check.NewTypeParam(tpar, nil) // assigns type to tpar as a side-effect check.declare(check.scope, name, tpar, check.scope.pos) // TODO(gri) check scope position return tpar } diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index d3e0c71f05..e8755a1a68 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -32,7 +32,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo return false case value: - if sig := asSignature(x.typ); sig != nil && len(sig.tparams) > 0 { + if sig := asSignature(x.typ); sig != nil && sig.TParams().Len() > 0 { // function instantiation return true } diff --git a/src/cmd/compile/internal/types2/instance.go b/src/cmd/compile/internal/types2/instance.go index e18688771c..40e89289a2 100644 --- a/src/cmd/compile/internal/types2/instance.go +++ b/src/cmd/compile/internal/types2/instance.go @@ -25,7 +25,7 @@ func (n *Named) expand() { // tparams. This is done implicitly by the call to n.TParams, but making it // explicit is harmless: load is idempotent. n.load() - inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams(), n.targs, n.instance.posList) + inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams().list(), n.targs, n.instance.posList) n.underlying = inst n.fromRHS = inst n.instance = nil diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index ee790ba6d6..9f9f8a7f5d 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -29,9 +29,9 @@ func (check *Checker) Instantiate(pos syntax.Pos, typ Type, targs []Type, posLis var tparams []*TypeName switch t := typ.(type) { case *Named: - tparams = t.TParams() + tparams = t.TParams().list() case *Signature: - tparams = t.tparams + tparams = t.TParams().list() defer func() { // If we had an unexpected failure somewhere don't panic below when // asserting res.(*Signature). Check for *Signature in case Typ[Invalid] @@ -109,9 +109,9 @@ func (check *Checker) InstantiateLazy(pos syntax.Pos, typ Type, targs []Type, po panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } - if verify && len(base.tparams) == len(targs) { + if verify && base.TParams().Len() == len(targs) { check.later(func() { - check.verify(pos, base.tparams, targs, posList) + check.verify(pos, base.tparams.list(), targs, posList) }) } @@ -125,7 +125,7 @@ func (check *Checker) InstantiateLazy(pos syntax.Pos, typ Type, targs []Type, po } tname := NewTypeName(pos, base.obj.pkg, base.obj.name, nil) - named := check.newNamed(tname, base, nil, nil, nil) // methods and tparams are set when named is loaded. + named := check.newNamed(tname, base, nil, nil, nil) // methods and tparams are set when named is loaded named.targs = targs named.instance = &instance{pos, posList} if check != nil { diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index 9e9d6dfb29..3819a9ffb8 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -315,10 +315,10 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // both methods must have the same number of type parameters ftyp := f.typ.(*Signature) mtyp := m.typ.(*Signature) - if len(ftyp.tparams) != len(mtyp.tparams) { + if ftyp.TParams().Len() != mtyp.TParams().Len() { return m, f } - if !acceptMethodTypeParams && len(ftyp.tparams) > 0 { + if !acceptMethodTypeParams && ftyp.TParams().Len() > 0 { panic("internal error: method with type parameters") } @@ -328,7 +328,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // TODO(gri) is this always correct? what about type bounds? // (Alternative is to rename/subst type parameters and compare.) u := newUnifier(true) - u.x.init(ftyp.tparams) + u.x.init(ftyp.TParams().list()) if !u.unify(ftyp, mtyp) { return m, f } @@ -367,10 +367,10 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // both methods must have the same number of type parameters ftyp := f.typ.(*Signature) mtyp := m.typ.(*Signature) - if len(ftyp.tparams) != len(mtyp.tparams) { + if ftyp.TParams().Len() != mtyp.TParams().Len() { return m, f } - if !acceptMethodTypeParams && len(ftyp.tparams) > 0 { + if !acceptMethodTypeParams && ftyp.TParams().Len() > 0 { panic("internal error: method with type parameters") } @@ -381,17 +381,17 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // In order to compare the signatures, substitute the receiver // type parameters of ftyp with V's instantiation type arguments. // This lazily instantiates the signature of method f. - if Vn != nil && len(Vn.TParams()) > 0 { + if Vn != nil && Vn.TParams().Len() > 0 { // Be careful: The number of type arguments may not match // the number of receiver parameters. If so, an error was // reported earlier but the length discrepancy is still // here. Exit early in this case to prevent an assertion // failure in makeSubstMap. // TODO(gri) Can we avoid this check by fixing the lengths? - if len(ftyp.rparams) != len(Vn.targs) { + if len(ftyp.RParams().list()) != len(Vn.targs) { return } - ftyp = check.subst(nopos, ftyp, makeSubstMap(ftyp.rparams, Vn.targs)).(*Signature) + ftyp = check.subst(nopos, ftyp, makeSubstMap(ftyp.RParams().list(), Vn.targs)).(*Signature) } // If the methods have type parameters we don't care whether they @@ -400,7 +400,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // TODO(gri) is this always correct? what about type bounds? // (Alternative is to rename/subst type parameters and compare.) u := newUnifier(true) - if len(ftyp.tparams) > 0 { + if ftyp.TParams().Len() > 0 { // We reach here only if we accept method type parameters. // In this case, unification must consider any receiver // and method type parameters as "free" type parameters. @@ -410,9 +410,9 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // unimplemented call so that we test this code if we // enable method type parameters. unimplemented() - u.x.init(append(ftyp.rparams, ftyp.tparams...)) + u.x.init(append(ftyp.RParams().list(), ftyp.TParams().list()...)) } else { - u.x.init(ftyp.rparams) + u.x.init(ftyp.RParams().list()) } if !u.unify(ftyp, mtyp) { return m, f diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index a88aeb0077..96f2db1429 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -17,7 +17,7 @@ type Named struct { fromRHS Type // type (on RHS of declaration) this *Named type is derived from (for cycle reporting) underlying Type // possibly a *Named during setup; never a *Named once set up completely instance *instance // position information for lazy instantiation, or nil - tparams []*TypeName // type parameters, or nil + tparams *TypeParams // type parameters, or nil targs []Type // type arguments (after instantiation), or nil methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily @@ -69,7 +69,7 @@ func (t *Named) load() *Named { panic("invalid underlying type") } - t.tparams = tparams + t.tparams = bindTParams(tparams) t.underlying = underlying t.methods = methods }) @@ -77,7 +77,7 @@ func (t *Named) load() *Named { } // newNamed is like NewNamed but with a *Checker receiver and additional orig argument. -func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams []*TypeName, methods []*Func) *Named { +func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams *TypeParams, methods []*Func) *Named { typ := &Named{check: check, obj: obj, orig: orig, fromRHS: underlying, underlying: underlying, tparams: tparams, methods: methods} if typ.orig == nil { typ.orig = typ @@ -117,12 +117,10 @@ func (t *Named) Orig() *Named { return t.orig } // TParams returns the type parameters of the named type t, or nil. // The result is non-nil for an (originally) parameterized type even if it is instantiated. -func (t *Named) TParams() []*TypeName { - return t.load().tparams -} +func (t *Named) TParams() *TypeParams { return t.load().tparams } // SetTParams sets the type parameters of the named type t. -func (t *Named) SetTParams(tparams []*TypeName) { t.load().tparams = tparams } +func (t *Named) SetTParams(tparams []*TypeName) { t.load().tparams = bindTParams(tparams) } // TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated. func (t *Named) TArgs() []Type { return t.targs } diff --git a/src/cmd/compile/internal/types2/object.go b/src/cmd/compile/internal/types2/object.go index 48fd1e44de..8263ccae0c 100644 --- a/src/cmd/compile/internal/types2/object.go +++ b/src/cmd/compile/internal/types2/object.go @@ -475,8 +475,8 @@ func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) { if _, ok := typ.(*Basic); ok { return } - if named, _ := typ.(*Named); named != nil && len(named.tparams) > 0 { - writeTParamList(buf, named.tparams, qf, nil) + if named, _ := typ.(*Named); named != nil && named.TParams().Len() > 0 { + writeTParamList(buf, named.TParams().list(), qf, nil) } if tname.IsAlias() { buf.WriteString(" =") diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index cd9fa3f564..f3aeafcbb7 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -227,7 +227,7 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { // parameter names. if y, ok := y.(*Signature); ok { return x.variadic == y.variadic && - identicalTParams(x.tparams, y.tparams, cmpTags, p) && + identicalTParams(x.TParams().list(), y.TParams().list(), cmpTags, p) && identical(x.params, y.params, cmpTags, p) && identical(x.results, y.results, cmpTags, p) } diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index fa5c3f7a9b..832f37a6af 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -19,8 +19,8 @@ type Signature struct { // and store it in the Func Object) because when type-checking a function // literal we call the general type checker which returns a general Type. // We then unpack the *Signature and use the scope for the literal body. - rparams []*TypeName // receiver type parameters from left to right; or nil - tparams []*TypeName // type parameters from left to right; or nil + rparams *TypeParams // receiver type parameters from left to right, or nil + tparams *TypeParams // type parameters from left to right, or nil scope *Scope // function scope, present for package-local signatures recv *Var // nil if not a method params *Tuple // (incoming) parameters from left to right; or nil @@ -54,16 +54,16 @@ func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature { func (s *Signature) Recv() *Var { return s.recv } // TParams returns the type parameters of signature s, or nil. -func (s *Signature) TParams() []*TypeName { return s.tparams } - -// RParams returns the receiver type params of signature s, or nil. -func (s *Signature) RParams() []*TypeName { return s.rparams } +func (s *Signature) TParams() *TypeParams { return s.tparams } // SetTParams sets the type parameters of signature s. -func (s *Signature) SetTParams(tparams []*TypeName) { s.tparams = tparams } +func (s *Signature) SetTParams(tparams []*TypeName) { s.tparams = bindTParams(tparams) } + +// RParams returns the receiver type parameters of signature s, or nil. +func (s *Signature) RParams() *TypeParams { return s.rparams } // SetRParams sets the receiver type params of signature s. -func (s *Signature) SetRParams(rparams []*TypeName) { s.rparams = rparams } +func (s *Signature) SetRParams(rparams []*TypeName) { s.rparams = bindTParams(rparams) } // Params returns the parameters of signature s, or nil. func (s *Signature) Params() *Tuple { return s.params } @@ -119,10 +119,11 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] // blank identifiers were found => use rewritten receiver type recvTyp = isubst(recvPar.Type, smap) } - sig.rparams = make([]*TypeName, len(rparams)) + rlist := make([]*TypeName, len(rparams)) for i, rparam := range rparams { - sig.rparams[i] = check.declareTypeParam(i, rparam) + rlist[i] = check.declareTypeParam(rparam) } + sig.rparams = bindTParams(rlist) // determine receiver type to get its type parameters // and the respective type parameter bounds var recvTParams []*TypeName @@ -132,19 +133,19 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] // again when we type-check the signature. // TODO(gri) maybe the receiver should be marked as invalid instead? if recv := asNamed(check.genericType(rname, false)); recv != nil { - recvTParams = recv.TParams() + recvTParams = recv.TParams().list() } } // provide type parameter bounds // - only do this if we have the right number (otherwise an error is reported elsewhere) - if len(sig.rparams) == len(recvTParams) { + if sig.RParams().Len() == len(recvTParams) { // We have a list of *TypeNames but we need a list of Types. - list := make([]Type, len(sig.rparams)) - for i, t := range sig.rparams { + list := make([]Type, sig.RParams().Len()) + for i, t := range sig.RParams().list() { list[i] = t.typ } smap := makeSubstMap(recvTParams, list) - for i, tname := range sig.rparams { + for i, tname := range sig.RParams().list() { bound := recvTParams[i].typ.(*TypeParam).bound // bound is (possibly) parameterized in the context of the // receiver type declaration. Substitute parameters for the diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go index 70cf3709e5..8255e6ded4 100644 --- a/src/cmd/compile/internal/types2/sizeof_test.go +++ b/src/cmd/compile/internal/types2/sizeof_test.go @@ -26,12 +26,12 @@ func TestSizeof(t *testing.T) { {Struct{}, 24, 48}, {Pointer{}, 8, 16}, {Tuple{}, 12, 24}, - {Signature{}, 44, 88}, + {Signature{}, 28, 56}, {Union{}, 12, 24}, {Interface{}, 40, 80}, {Map{}, 16, 32}, {Chan{}, 12, 24}, - {Named{}, 88, 168}, + {Named{}, 80, 152}, {TypeParam{}, 28, 48}, {term{}, 12, 24}, {top{}, 0, 0}, diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index fc71343431..54cd005640 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -197,7 +197,7 @@ func (subst *subster) typ(typ Type) Type { if len(t.targs) > 0 { // already instantiated dump(">>> %s already instantiated", t) - assert(len(t.targs) == len(t.TParams())) + assert(len(t.targs) == t.TParams().Len()) // For each (existing) type argument targ, determine if it needs // to be substituted; i.e., if it is or contains a type parameter // that has a type argument for it. @@ -207,7 +207,7 @@ func (subst *subster) typ(typ Type) Type { if new_targ != targ { dump(">>> substituted %d targ %s => %s", i, targ, new_targ) if new_targs == nil { - new_targs = make([]Type, len(t.TParams())) + new_targs = make([]Type, t.TParams().Len()) copy(new_targs, t.targs) } new_targs[i] = new_targ diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index b66256cf00..aff03a5f04 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -28,15 +28,19 @@ type TypeParam struct { // Obj returns the type name for the type parameter t. func (t *TypeParam) Obj() *TypeName { return t.obj } -// NewTypeParam returns a new TypeParam. bound can be nil (and set later). -func (check *Checker) NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam { +// NewTypeParam returns a new TypeParam. Type parameters may be set on a Named +// or Signature type by calling SetTParams. Setting a type parameter on more +// than one type will result in a panic. +// +// The bound argument can be nil, and set later via SetBound. +func (check *Checker) NewTypeParam(obj *TypeName, bound Type) *TypeParam { // Always increment lastID, even if it is not used. id := nextID() if check != nil { check.nextID++ id = check.nextID } - typ := &TypeParam{check: check, id: id, obj: obj, index: index, bound: bound} + typ := &TypeParam{check: check, id: id, obj: obj, index: -1, bound: bound} if obj.typ == nil { obj.typ = typ } @@ -88,6 +92,42 @@ func (t *TypeParam) SetBound(bound Type) { func (t *TypeParam) Underlying() Type { return t } func (t *TypeParam) String() string { return TypeString(t, nil) } +// TypeParams holds a list of type parameters bound to a type. +type TypeParams struct{ tparams []*TypeName } + +// Len returns the number of type parameters in the list. +// It is safe to call on a nil receiver. +func (tps *TypeParams) Len() int { + return len(tps.list()) +} + +// At returns the i'th type parameter in the list. +// It is safe to call on a nil receiver. +func (tps *TypeParams) At(i int) *TypeName { + return tps.list()[i] +} + +func (tps *TypeParams) list() []*TypeName { + if tps == nil { + return nil + } + return tps.tparams +} + +func bindTParams(list []*TypeName) *TypeParams { + if len(list) == 0 { + return nil + } + for i, tp := range list { + typ := tp.Type().(*TypeParam) + if typ.index >= 0 { + panic("internal error: type parameter bound more than once") + } + typ.index = i + } + return &TypeParams{tparams: list} +} + // ---------------------------------------------------------------------------- // Implementation diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 1da3f7f8ed..7a8b5a6eee 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -280,7 +280,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { buf.WriteByte(']') } else if t.TParams() != nil { // parameterized type - writeTParamList(buf, t.TParams(), qf, visited) + writeTParamList(buf, t.TParams().list(), qf, visited) } case *TypeParam: @@ -426,7 +426,7 @@ func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) { func writeSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier, visited []Type) { if sig.tparams != nil { - writeTParamList(buf, sig.tparams, qf, visited) + writeTParamList(buf, sig.TParams().list(), qf, visited) } writeTuple(buf, sig.params, sig.variadic, qf, visited) -- GitLab From 46cc68638143770206e0894add7021990a9bec52 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 28 Jul 2021 15:38:28 -0700 Subject: [PATCH 0561/2500] [dev.typeparams] cmd/compile/internal/types2: use the TParams API consistently This is a clean port of CL 336251. Change-Id: I08415c3e9b6cef33594e7d56c4115ddde8030381 Reviewed-on: https://go-review.googlesource.com/c/go/+/338193 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/call.go | 4 ++-- src/cmd/compile/internal/types2/decl.go | 2 +- src/cmd/compile/internal/types2/subst.go | 2 +- src/cmd/compile/internal/types2/typestring.go | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index dee49b44a4..e1acf50213 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -57,7 +57,7 @@ func (check *Checker) funcInst(x *operand, inst *syntax.IndexExpr) { // instantiate function signature res := check.Instantiate(x.Pos(), sig, targs, poslist, true).(*Signature) - assert(res.tparams == nil) // signature is not generic anymore + assert(res.TParams().Len() == 0) // signature is not generic anymore if inferred { check.recordInferred(inst, targs, res) } @@ -327,7 +327,7 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T // compute result signature rsig = check.Instantiate(call.Pos(), sig, targs, nil, true).(*Signature) - assert(rsig.tparams == nil) // signature is not generic anymore + assert(rsig.TParams().Len() == 0) // signature is not generic anymore check.recordInferred(call, targs, rsig) // Optimization: Only if the parameter list was adjusted do we diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index c867d87603..cf4d4c95a7 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -575,7 +575,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named named.underlying = under(named) // If the RHS is a type parameter, it must be from this type declaration. - if tpar, _ := named.underlying.(*TypeParam); tpar != nil && tparamIndex(named.tparams.list(), tpar) < 0 { + if tpar, _ := named.underlying.(*TypeParam); tpar != nil && tparamIndex(named.TParams().list(), tpar) < 0 { check.errorf(tdecl.Type, "cannot use function type parameter %s as RHS in type declaration", tpar) named.underlying = Typ[Invalid] } diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 54cd005640..e497e17463 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -187,7 +187,7 @@ func (subst *subster) typ(typ Type) Type { } } - if t.TParams() == nil { + if t.TParams().Len() == 0 { dump(">>> %s is not parameterized", t) return t // type is not parameterized } diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 7a8b5a6eee..b7e32c9860 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -278,7 +278,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { buf.WriteByte('[') writeTypeList(buf, t.targs, qf, visited) buf.WriteByte(']') - } else if t.TParams() != nil { + } else if t.TParams().Len() != 0 { // parameterized type writeTParamList(buf, t.TParams().list(), qf, visited) } @@ -425,7 +425,7 @@ func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) { } func writeSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier, visited []Type) { - if sig.tparams != nil { + if sig.TParams().Len() != 0 { writeTParamList(buf, sig.TParams().list(), qf, visited) } -- GitLab From 5ecbd811b54f478244b7e54a621f32b5b8e3ea95 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 28 Jul 2021 16:58:57 -0700 Subject: [PATCH 0562/2500] [dev.typeparams] cmd/compile/internal/types2: (TypeParam) SetBound -> SetConstraint This matches the accessor named Constraint, and any documentation we have so far. Use iface instead of Bound internally to types2; keep Bound because of two external uses but mark it as deprecated. Adjust clients. Change-Id: Id1a2c2f28259a16082e875eee0534d46cf157336 Reviewed-on: https://go-review.googlesource.com/c/go/+/338196 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/importer/iimport.go | 2 +- src/cmd/compile/internal/noder/reader2.go | 2 +- src/cmd/compile/internal/types2/builtins.go | 2 +- src/cmd/compile/internal/types2/call.go | 2 +- .../compile/internal/types2/instantiate.go | 6 ++--- src/cmd/compile/internal/types2/lookup.go | 2 +- src/cmd/compile/internal/types2/predicates.go | 2 +- src/cmd/compile/internal/types2/type.go | 2 +- src/cmd/compile/internal/types2/typeparam.go | 26 ++++++++++++------- 9 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index 999b2aa1dc..3dd28033a1 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -384,7 +384,7 @@ func (r *importReader) obj(name string) { id := ident{r.currPkg.Name(), name} r.p.tparamIndex[id] = t - t.SetBound(r.typ()) + t.SetConstraint(r.typ()) case 'V': typ := r.typ() diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index 3e310e26c4..d183934900 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -485,7 +485,7 @@ func (r *reader2) typeParamNames() []*types2.TypeName { } for i, bound := range r.dict.bounds { - r.dict.tparams[i].SetBound(r.p.typIdx(bound, r.dict)) + r.dict.tparams[i].SetConstraint(r.p.typIdx(bound, r.dict)) } return names diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 7ef9e7be63..7b2c92bfa8 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -817,7 +817,7 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { // type and collect possible result types at the same time. var rtypes []Type var tildes []bool - if !tp.Bound().is(func(typ Type, tilde bool) bool { + if !tp.iface().is(func(typ Type, tilde bool) bool { if r := f(typ); r != nil { rtypes = append(rtypes, r) tildes = append(tildes, tilde) diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index e1acf50213..049d80dd9e 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -479,7 +479,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) { var why string if tpar := asTypeParam(x.typ); tpar != nil { // Type parameter bounds don't specify fields, so don't mention "field". - if tname := tpar.Bound().obj; tname != nil { + if tname := tpar.iface().obj; tname != nil { why = check.sprintf("interface %s has no method %s", tname.name, sel) } else { why = check.sprintf("type bound for %s has no method %s", x.typ, sel) diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 9f9f8a7f5d..357f041c46 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -160,7 +160,7 @@ func (check *Checker) verify(pos syntax.Pos, tparams []*TypeName, targs []Type, // A suitable error is reported if the result is false. // TODO(gri) This should be a method of interfaces or type sets. func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap *substMap) bool { - iface := tpar.Bound() + iface := tpar.iface() if iface.Empty() { return true // no type bound } @@ -174,7 +174,7 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap // if iface is comparable, targ must be comparable // TODO(gri) the error messages needs to be better, here if iface.IsComparable() && !Comparable(targ) { - if tpar := asTypeParam(targ); tpar != nil && tpar.Bound().typeSet().IsTop() { + if tpar := asTypeParam(targ); tpar != nil && tpar.iface().typeSet().IsTop() { check.softErrorf(pos, "%s has no constraints", targ) return false } @@ -219,7 +219,7 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap // If targ is itself a type parameter, each of its possible types, but at least one, must be in the // list of iface types (i.e., the targ type list must be a non-empty subset of the iface types). if targ := asTypeParam(targ); targ != nil { - targBound := targ.Bound() + targBound := targ.iface() if targBound.typeSet().types == nil { check.softErrorf(pos, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ) return false diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index 3819a9ffb8..41e5bc7811 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -186,7 +186,7 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o } case *TypeParam: - if i, m := t.Bound().typeSet().LookupMethod(pkg, name); m != nil { + if i, m := t.iface().typeSet().LookupMethod(pkg, name); m != nil { assert(m.typ != nil) index = concat(e.index, i) if obj != nil || e.multiples { diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index f3aeafcbb7..84342b2796 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -113,7 +113,7 @@ func comparable(T Type, seen map[Type]bool) bool { case *Array: return comparable(t.elem, seen) case *TypeParam: - return t.Bound().IsComparable() + return t.iface().IsComparable() } return false } diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 80054372bc..a943926189 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -56,7 +56,7 @@ func optype(typ Type) Type { // for a type parameter list of the form: // (type T interface { type T }). // See also issue #39680. - if a := t.Bound().typeSet().types; a != nil { + if a := t.iface().typeSet().types; a != nil { // If we have a union with a single entry, ignore // any tilde because under(~t) == under(t). if u, _ := a.(*Union); u != nil && u.NumTerms() == 1 { diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index aff03a5f04..9f8c921bf1 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -72,21 +72,27 @@ func (t *TypeParam) Constraint() Type { return t.bound } -// Bound returns the underlying type of the type parameter's -// constraint. -// Deprecated for external use. Use Constraint instead. -func (t *TypeParam) Bound() *Interface { +// SetConstraint sets the type constraint for t. +func (t *TypeParam) SetConstraint(bound Type) { + if bound == nil { + panic("types2.TypeParam.SetConstraint: bound must not be nil") + } + t.bound = bound +} + +// iface returns the constraint interface of t. +func (t *TypeParam) iface() *Interface { if iface, _ := under(t.Constraint()).(*Interface); iface != nil { return iface } return &emptyInterface } -func (t *TypeParam) SetBound(bound Type) { - if bound == nil { - panic("types2.TypeParam.SetBound: bound must not be nil") - } - t.bound = bound +// Bound returns the constraint interface of t. +// Deprecated. Only here for the compiler. +// TODO(gri) remove in favor of uses of Constraint. +func (t *TypeParam) Bound() *Interface { + return t.iface() } func (t *TypeParam) Underlying() Type { return t } @@ -132,5 +138,5 @@ func bindTParams(list []*TypeName) *TypeParams { // Implementation func (t *TypeParam) underIs(f func(Type) bool) bool { - return t.Bound().typeSet().underIs(f) + return t.iface().typeSet().underIs(f) } -- GitLab From 600b7b431bd546841c04a27d4ac73af1e4f2fcc4 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 26 Jul 2021 19:25:40 -0700 Subject: [PATCH 0563/2500] [dev.typeparams] cmd/compile: handle meth expressions on typeparams Rewrite a method expression such as 'T.String' (where T is type param and String is part of its type bound Stringer) as: func(rcvr T, other params...) { return Stringer(rcvr).String(other params...) } New function buildClosure2 to create the needed closure. The conversion Stringer(rcvr) uses the dictionary in the outer function. For a method expression like 'Test[T].finish' (where finish is a method of Test[T]), we can already deal with this in buildClosure(). We just need fix transformDot() to allow the method lookup to fail, since shapes have no methods on them. That's fine, since for any instantiated receiver type, we always use the methods on the generic base type. Also removed the OMETHEXPR case in the main switch of node(), which isn't needed any (and removes one more potential unshapify). Also, fixed two small bugs with handling closures that have generic params or generic captured variables. Need to set the instInfo for the closure in the subst struct when descending into a closure during genericSubst() and was missing initializing the startItabConv and gfInfo fields in the closure info. Change-Id: I6dadedd1378477936a27c9c544c014cd2083cfb7 Reviewed-on: https://go-review.googlesource.com/c/go/+/338129 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 214 +++++++++++++------- src/cmd/compile/internal/noder/transform.go | 6 +- test/typeparam/boundmethod.go | 54 ++++- 3 files changed, 198 insertions(+), 76 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 70a2c7b97f..83abee1dd2 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -357,8 +357,7 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { // } // Make a new internal function. - fn := ir.NewClosureFunc(pos, outer != nil) - ir.NameClosure(fn.OClosure, outer) + fn, formalParams, formalResults := startClosure(pos, outer, typ) // This is the dictionary we want to use. // It may be a constant, or it may be a dictionary acquired from the outer function's dictionary. @@ -395,38 +394,6 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { outer.Dcl = append(outer.Dcl, rcvrVar) } - // Build formal argument and return lists. - var formalParams []*types.Field // arguments of closure - var formalResults []*types.Field // returns of closure - for i := 0; i < typ.NumParams(); i++ { - t := typ.Params().Field(i).Type - arg := ir.NewNameAt(pos, typecheck.LookupNum("a", i)) - arg.Class = ir.PPARAM - typed(t, arg) - arg.Curfn = fn - fn.Dcl = append(fn.Dcl, arg) - f := types.NewField(pos, arg.Sym(), t) - f.Nname = arg - formalParams = append(formalParams, f) - } - for i := 0; i < typ.NumResults(); i++ { - t := typ.Results().Field(i).Type - result := ir.NewNameAt(pos, typecheck.LookupNum("r", i)) // TODO: names not needed? - result.Class = ir.PPARAMOUT - typed(t, result) - result.Curfn = fn - fn.Dcl = append(fn.Dcl, result) - f := types.NewField(pos, result.Sym(), t) - f.Nname = result - formalResults = append(formalResults, f) - } - - // Build an internal function with the right signature. - closureType := types.NewSignature(x.Type().Pkg(), nil, nil, formalParams, formalResults) - typed(closureType, fn.Nname) - typed(x.Type(), fn.OClosure) - fn.SetTypecheck(1) - // Build body of closure. This involves just calling the wrapped function directly // with the additional dictionary argument. @@ -1092,14 +1059,15 @@ func getDictionaryEntry(pos src.XPos, dict *ir.Name, i int, size int) ir.Node { return r } -// getDictionaryType returns a *runtime._type from the dictionary entry i -// (which refers to a type param or a derived type that uses type params). -func (subst *subster) getDictionaryType(pos src.XPos, i int) ir.Node { - if i < 0 || i >= subst.info.startSubDict { +// getDictionaryType returns a *runtime._type from the dictionary entry i (which +// refers to a type param or a derived type that uses type params). It uses the +// specified dictionary dictParam, rather than the one in info.dictParam. +func getDictionaryType(info *instInfo, dictParam *ir.Name, pos src.XPos, i int) ir.Node { + if i < 0 || i >= info.startSubDict { base.Fatalf(fmt.Sprintf("bad dict index %d", i)) } - r := getDictionaryEntry(pos, subst.info.dictParam, i, subst.info.startSubDict) + r := getDictionaryEntry(pos, info.dictParam, i, info.startSubDict) // change type of retrieved dictionary entry to *byte, which is the // standard typing of a *runtime._type in the compiler typed(types.Types[types.TUINT8].PtrTo(), r) @@ -1235,9 +1203,9 @@ func (subst *subster) node(n ir.Node) ir.Node { // The only dot on a shape type value are methods. if mse.X.Op() == ir.OTYPE { // Method expression T.M - // Fall back from shape type to concrete type. - src = subst.unshapifyTyp(src) - mse.X = ir.TypeNode(src) + m = subst.g.buildClosure2(subst.newf, subst.info, m, x) + // No need for transformDot - buildClosure2 has already + // transformed to OCALLINTER/ODOTINTER. } else { // Implement x.M as a conversion-to-bound-interface // 1) convert x to the bound interface @@ -1247,12 +1215,11 @@ func (subst *subster) node(n ir.Node) ir.Node { if dst.HasTParam() { dst = subst.ts.Typ(dst) } - mse.X = subst.convertUsingDictionary(m.Pos(), mse.X, x, dst, gsrc) + mse.X = convertUsingDictionary(subst.info, subst.info.dictParam, m.Pos(), mse.X, x, dst, gsrc) + transformDot(mse, false) } - } - transformDot(mse, false) - if mse.Op() == ir.OMETHEXPR && mse.X.Type().HasShape() { - mse.X = ir.TypeNodeAt(mse.X.Pos(), subst.unshapifyTyp(mse.X.Type())) + } else { + transformDot(mse, false) } m.SetTypecheck(1) @@ -1341,11 +1308,14 @@ func (subst *subster) node(n ir.Node) ir.Node { // outer function. Since the dictionary is shared, use the // same entries for startSubDict, dictLen, dictEntryMap. cinfo := &instInfo{ - fun: newfn, - dictParam: cdict, - startSubDict: subst.info.startSubDict, - dictLen: subst.info.dictLen, - dictEntryMap: subst.info.dictEntryMap, + fun: newfn, + dictParam: cdict, + gf: subst.info.gf, + gfInfo: subst.info.gfInfo, + startSubDict: subst.info.startSubDict, + startItabConv: subst.info.startItabConv, + dictLen: subst.info.dictLen, + dictEntryMap: subst.info.dictEntryMap, } subst.g.instInfoMap[newfn.Nname.Sym()] = cinfo @@ -1353,8 +1323,11 @@ func (subst *subster) node(n ir.Node) ir.Node { typed(newfn.Nname.Type(), newfn.OClosure) newfn.SetTypecheck(1) + outerinfo := subst.info + subst.info = cinfo // Make sure type of closure function is set before doing body. newfn.Body = subst.list(oldfn.Body) + subst.info = outerinfo subst.newf = saveNewf ir.CurFunc = saveNewf @@ -1366,15 +1339,15 @@ func (subst *subster) node(n ir.Node) ir.Node { // Note: x's argument is still typed as a type parameter. // m's argument now has an instantiated type. if x.X.Type().HasTParam() { - m = subst.convertUsingDictionary(m.Pos(), m.(*ir.ConvExpr).X, x, m.Type(), x.X.Type()) + m = convertUsingDictionary(subst.info, subst.info.dictParam, m.Pos(), m.(*ir.ConvExpr).X, x, m.Type(), x.X.Type()) } case ir.ODOTTYPE, ir.ODOTTYPE2: dt := m.(*ir.TypeAssertExpr) var rt ir.Node if dt.Type().IsInterface() || dt.X.Type().IsEmptyInterface() { - ix := subst.findDictType(x.Type()) + ix := findDictType(subst.info, x.Type()) assert(ix >= 0) - rt = subst.getDictionaryType(dt.Pos(), ix) + rt = getDictionaryType(subst.info, subst.info.dictParam, dt.Pos(), ix) } else { // nonempty interface to noninterface. Need an itab. ix := -1 @@ -1395,9 +1368,6 @@ func (subst *subster) node(n ir.Node) ir.Node { m.SetType(dt.Type()) m.SetTypecheck(1) - case ir.OMETHEXPR: - se := m.(*ir.SelectorExpr) - se.X = ir.TypeNodeAt(se.X.Pos(), subst.unshapifyTyp(se.X.Type())) case ir.OFUNCINST: inst := m.(*ir.InstExpr) targs2 := make([]ir.Node, len(inst.Targs)) @@ -1414,17 +1384,17 @@ func (subst *subster) node(n ir.Node) ir.Node { } // findDictType looks for type t in the typeparams or derived types in the generic -// function info subst.info.gfInfo. This will indicate the dictionary entry with the +// function info.gfInfo. This will indicate the dictionary entry with the // correct concrete type for the associated instantiated function. -func (subst *subster) findDictType(t *types.Type) int { - for i, dt := range subst.info.gfInfo.tparams { +func findDictType(info *instInfo, t *types.Type) int { + for i, dt := range info.gfInfo.tparams { if dt == t { return i } } - for i, dt := range subst.info.gfInfo.derivedTypes { + for i, dt := range info.gfInfo.derivedTypes { if types.Identical(dt, t) { - return i + len(subst.info.gfInfo.tparams) + return i + len(info.gfInfo.tparams) } } return -1 @@ -1435,7 +1405,7 @@ func (subst *subster) findDictType(t *types.Type) int { // is the generic (not shape) type, and gn is the original generic node of the // CONVIFACE node or XDOT node (for a bound method call) that is causing the // conversion. -func (subst *subster) convertUsingDictionary(pos src.XPos, v ir.Node, gn ir.Node, dst, src *types.Type) ir.Node { +func convertUsingDictionary(info *instInfo, dictParam *ir.Name, pos src.XPos, v ir.Node, gn ir.Node, dst, src *types.Type) ir.Node { assert(src.HasTParam()) assert(dst.IsInterface()) @@ -1445,19 +1415,19 @@ func (subst *subster) convertUsingDictionary(pos src.XPos, v ir.Node, gn ir.Node // will be more efficient than converting to an empty interface first // and then type asserting to dst. ix := -1 - for i, ic := range subst.info.gfInfo.itabConvs { + for i, ic := range info.gfInfo.itabConvs { if ic == gn { - ix = subst.info.startItabConv + i + ix = info.startItabConv + i break } } assert(ix >= 0) - rt = getDictionaryEntry(pos, subst.info.dictParam, ix, subst.info.dictLen) + rt = getDictionaryEntry(pos, dictParam, ix, info.dictLen) } else { - ix := subst.findDictType(src) + ix := findDictType(info, src) assert(ix >= 0) // Load the actual runtime._type of the type parameter from the dictionary. - rt = subst.getDictionaryType(pos, ix) + rt = getDictionaryType(info, dictParam, pos, ix) } // Figure out what the data field of the interface will be. @@ -1670,7 +1640,7 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) case ir.OXDOT: selExpr := n.(*ir.SelectorExpr) - subtargs := selExpr.X.Type().RParams() + subtargs := deref(selExpr.X.Type()).RParams() s2targs := make([]*types.Type, len(subtargs)) for i, t := range subtargs { s2targs[i] = subst.Typ(t) @@ -1842,7 +1812,7 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo { } } else if n.Op() == ir.OXDOT && !n.(*ir.SelectorExpr).Implicit() && n.(*ir.SelectorExpr).Selection != nil && - len(n.(*ir.SelectorExpr).X.Type().RParams()) > 0 { + len(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) > 0 { if n.(*ir.SelectorExpr).X.Op() == ir.OTYPE { infoPrint(" Closure&subdictionary required at generic meth expr %v\n", n) } else { @@ -2017,3 +1987,105 @@ func parameterizedBy1(t *types.Type, params []*types.Type, visited map[*types.Ty return true } } + +// startClosures starts creation of a closure that has the function type typ. It +// creates all the formal params and results according to the type typ. On return, +// the body and closure variables of the closure must still be filled in, and +// ir.UseClosure() called. +func startClosure(pos src.XPos, outer *ir.Func, typ *types.Type) (*ir.Func, []*types.Field, []*types.Field) { + // Make a new internal function. + fn := ir.NewClosureFunc(pos, outer != nil) + ir.NameClosure(fn.OClosure, outer) + + // Build formal argument and return lists. + var formalParams []*types.Field // arguments of closure + var formalResults []*types.Field // returns of closure + for i := 0; i < typ.NumParams(); i++ { + t := typ.Params().Field(i).Type + arg := ir.NewNameAt(pos, typecheck.LookupNum("a", i)) + arg.Class = ir.PPARAM + typed(t, arg) + arg.Curfn = fn + fn.Dcl = append(fn.Dcl, arg) + f := types.NewField(pos, arg.Sym(), t) + f.Nname = arg + formalParams = append(formalParams, f) + } + for i := 0; i < typ.NumResults(); i++ { + t := typ.Results().Field(i).Type + result := ir.NewNameAt(pos, typecheck.LookupNum("r", i)) // TODO: names not needed? + result.Class = ir.PPARAMOUT + typed(t, result) + result.Curfn = fn + fn.Dcl = append(fn.Dcl, result) + f := types.NewField(pos, result.Sym(), t) + f.Nname = result + formalResults = append(formalResults, f) + } + + // Build an internal function with the right signature. + closureType := types.NewSignature(typ.Pkg(), nil, nil, formalParams, formalResults) + typed(closureType, fn.Nname) + typed(typ, fn.OClosure) + fn.SetTypecheck(1) + return fn, formalParams, formalResults + +} + +// buildClosure2 makes a closure to implement a method expression m (generic form x) +// which has a shape type as receiver. If the receiver is exactly a shape (i.e. from +// a typeparam), then the body of the closure converts the first argument (the +// receiver) to the interface bound type, and makes an interface call with the +// remaining arguments. +// +// The returned closure is fully substituted and has already has any needed +// transformations done. +func (g *irgen) buildClosure2(outer *ir.Func, info *instInfo, m, x ir.Node) ir.Node { + pos := m.Pos() + typ := m.Type() // type of the closure + + fn, formalParams, formalResults := startClosure(pos, outer, typ) + + // Capture dictionary calculated in the outer function + dictVar := ir.CaptureName(pos, fn, info.dictParam) + typed(types.Types[types.TUINTPTR], dictVar) + + // Build arguments to call inside the closure. + var args []ir.Node + for i := 0; i < typ.NumParams(); i++ { + args = append(args, formalParams[i].Nname.(*ir.Name)) + } + + // Build call itself. This involves converting the first argument to the + // bound type (an interface) using the dictionary, and then making an + // interface call with the remaining arguments. + var innerCall ir.Node + rcvr := args[0] + args = args[1:] + assert(m.(*ir.SelectorExpr).X.Type().IsShape()) + rcvr = convertUsingDictionary(info, dictVar, pos, rcvr, x, x.(*ir.SelectorExpr).X.Type().Bound(), x.(*ir.SelectorExpr).X.Type()) + dot := ir.NewSelectorExpr(pos, ir.ODOTINTER, rcvr, x.(*ir.SelectorExpr).Sel) + dot.Selection = typecheck.Lookdot1(dot, dot.Sel, dot.X.Type(), dot.X.Type().AllMethods(), 1) + + typed(x.(*ir.SelectorExpr).Selection.Type, dot) + innerCall = ir.NewCallExpr(pos, ir.OCALLINTER, dot, args) + t := m.Type() + if t.NumResults() == 0 { + innerCall.SetTypecheck(1) + } else if t.NumResults() == 1 { + typed(t.Results().Field(0).Type, innerCall) + } else { + typed(t.Results(), innerCall) + } + if len(formalResults) > 0 { + innerCall = ir.NewReturnStmt(pos, []ir.Node{innerCall}) + innerCall.SetTypecheck(1) + } + fn.Body = []ir.Node{innerCall} + + // We're all done with the captured dictionary + ir.FinishCaptureNames(pos, outer, fn) + + // Do final checks on closure and return it. + return ir.UseClosure(fn.OClosure, g.target) +} diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index 2fe55a6852..9c791d8a7b 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -664,7 +664,11 @@ func transformMethodExpr(n *ir.SelectorExpr) (res ir.Node) { s := n.Sel m := typecheck.Lookdot1(n, s, t, ms, 0) - assert(m != nil) + if !t.HasShape() { + // It's OK to not find the method if t is instantiated by shape types, + // because we will use the methods on the generic type anyway. + assert(m != nil) + } n.SetOp(ir.OMETHEXPR) n.Selection = m diff --git a/test/typeparam/boundmethod.go b/test/typeparam/boundmethod.go index 3deabbcdce..22f416422d 100644 --- a/test/typeparam/boundmethod.go +++ b/test/typeparam/boundmethod.go @@ -29,32 +29,78 @@ type Stringer interface { func stringify[T Stringer](s []T) (ret []string) { for _, v := range s { + // Test normal bounds method call on type param + x1 := v.String() + + // Test converting type param to its bound interface first + v1 := Stringer(v) + x2 := v1.String() + + // Test method expression with type param type + f1 := T.String + x3 := f1(v) + + // Test creating and calling closure equivalent to the method expression + f2 := func(v1 T) string { + return Stringer(v1).String() + } + x4 := f2(v) + + if x1 != x2 || x2 != x3 || x3 != x4 { + panic(fmt.Sprintf("Mismatched values %v, %v, %v, %v\n", x1, x2, x3, x4)) + } + ret = append(ret, v.String()) } return ret } -type StringInt[T any] T +type Ints interface { + ~int32 | ~int +} + +type StringInt[T Ints] T //go:noinline func (m StringInt[T]) String() string { - return "aa" + return strconv.Itoa(int(m)) +} + +type StringStruct[T Ints] struct { + f T +} + +func (m StringStruct[T]) String() string { + return strconv.Itoa(int(m.f)) } func main() { x := []myint{myint(1), myint(2), myint(3)} + // stringify on a normal type, whose bound method is associated with the base type. got := stringify(x) want := []string{"1", "2", "3"} if !reflect.DeepEqual(got, want) { panic(fmt.Sprintf("got %s, want %s", got, want)) } - x2 := []StringInt[myint]{StringInt[myint](1), StringInt[myint](2), StringInt[myint](3)} + x2 := []StringInt[myint]{StringInt[myint](5), StringInt[myint](7), StringInt[myint](6)} + // stringify on an instantiated type, whose bound method is associated with + // the generic type StringInt[T], which maps directly to T. got2 := stringify(x2) - want2 := []string{"aa", "aa", "aa"} + want2 := []string{ "5", "7", "6" } if !reflect.DeepEqual(got2, want2) { panic(fmt.Sprintf("got %s, want %s", got2, want2)) } + + // stringify on an instantiated type, whose bound method is associated with + // the generic type StringStruct[T], which maps to a struct containing T. + x3 := []StringStruct[myint]{StringStruct[myint]{f: 11}, StringStruct[myint]{f: 10}, StringStruct[myint]{f: 9}} + + got3 := stringify(x3) + want3 := []string{ "11", "10", "9" } + if !reflect.DeepEqual(got3, want3) { + panic(fmt.Sprintf("got %s, want %s", got3, want3)) + } } -- GitLab From 35dbdda2feecd04fde8d44441fef58aabaf0a78a Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Thu, 29 Jul 2021 07:27:35 -0700 Subject: [PATCH 0564/2500] [dev.typeparams] cmd/compile: remove remaining uses of Unshapify The other uses of Unshapify were really only there to allow for the dictionary checking code at the beginning of generic functions/methods. But that will go away as soon as we start combining real shapes. If we get rid of that code, we can get rid of the unshapify calls elsewhere. The only tricky part is that getInstantiation now gets targs that may each either be a shape or concrete type, and it must translate any concrete types to shapes, while leaving the already existing shapes. Change-Id: Ib2b9072b921f8e064958548a1078d82f1d040c9f Reviewed-on: https://go-review.googlesource.com/c/go/+/338289 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 97 ++++++++--------------- 1 file changed, 35 insertions(+), 62 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 83abee1dd2..037f309a82 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -768,38 +768,49 @@ func checkFetchBody(nameNode *ir.Name) { } // getInstantiation gets the instantiantion and dictionary of the function or method nameNode -// with the type arguments targs. If the instantiated function is not already +// with the type arguments shapes. If the instantiated function is not already // cached, then it calls genericSubst to create the new instantiation. -func (g *irgen) getInstantiation(nameNode *ir.Name, targs []*types.Type, isMeth bool) *ir.Func { +func (g *irgen) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMeth bool) *ir.Func { checkFetchBody(nameNode) - // Convert type arguments to their shape, so we can reduce the number - // of instantiations we have to generate. - shapes := typecheck.ShapifyList(targs) + // Convert any non-shape type arguments to their shape, so we can reduce the + // number of instantiations we have to generate. You can actually have a mix + // of shape and non-shape arguments, because of inferred or explicitly + // specified concrete type args. + var s1 []*types.Type + for i, t := range shapes { + if !t.HasShape() { + if s1 == nil { + s1 = make([]*types.Type, len(shapes)) + for j := 0; j < i; j++ { + s1[j] = shapes[j] + } + } + s1[i] = typecheck.Shapify(t) + } else if s1 != nil { + s1[i] = shapes[i] + } + } + if s1 != nil { + shapes = s1 + } sym := typecheck.MakeInstName(nameNode.Sym(), shapes, isMeth) info := g.instInfoMap[sym] if info == nil { - if false { - // Testing out gcshapeType() and gcshapeName() - for i, t := range targs { - gct, gcs := gcshapeType(t) - fmt.Printf("targ %d: %v %v %v\n", i, gcs, gct, gct.Underlying()) - } - } // If instantiation doesn't exist yet, create it and add // to the list of decls. gfInfo := g.getGfInfo(nameNode) info = &instInfo{ gf: nameNode, gfInfo: gfInfo, - startSubDict: len(targs) + len(gfInfo.derivedTypes), - startItabConv: len(targs) + len(gfInfo.derivedTypes) + len(gfInfo.subDictCalls), - dictLen: len(targs) + len(gfInfo.derivedTypes) + len(gfInfo.subDictCalls) + len(gfInfo.itabConvs), + startSubDict: len(shapes) + len(gfInfo.derivedTypes), + startItabConv: len(shapes) + len(gfInfo.derivedTypes) + len(gfInfo.subDictCalls), + dictLen: len(shapes) + len(gfInfo.derivedTypes) + len(gfInfo.subDictCalls) + len(gfInfo.itabConvs), dictEntryMap: make(map[ir.Node]int), } // genericSubst fills in info.dictParam and info.dictEntryMap. - st := g.genericSubst(sym, nameNode, shapes, targs, isMeth, info) + st := g.genericSubst(sym, nameNode, shapes, isMeth, info) info.fun = st g.instInfoMap[sym] = info // This ensures that the linker drops duplicates of this instantiation. @@ -821,23 +832,15 @@ type subster struct { newf *ir.Func // Func node for the new stenciled function ts typecheck.Tsubster info *instInfo // Place to put extra info in the instantiation - - // unshapeify maps from shape types to the concrete types they represent. - // TODO: remove when we no longer need it. - unshapify typecheck.Tsubster - - // TODO: some sort of map from to index in the - // dictionary where a *runtime.itab for the corresponding pair resides. } // genericSubst returns a new function with name newsym. The function is an // instantiation of a generic function or method specified by namedNode with type -// args targs. For a method with a generic receiver, it returns an instantiated -// function type where the receiver becomes the first parameter. Otherwise the -// instantiated method would still need to be transformed by later compiler -// phases. genericSubst fills in info.dictParam and info.dictEntryMap. -func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes, targs []*types.Type, isMethod bool, info *instInfo) *ir.Func { +// args shapes. For a method with a generic receiver, it returns an instantiated +// function type where the receiver becomes the first parameter. For either a generic +// method or function, a dictionary parameter is the added as the very first +// parameter. genericSubst fills in info.dictParam and info.dictEntryMap. +func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes []*types.Type, isMethod bool, info *instInfo) *ir.Func { var tparams []*types.Type if isMethod { // Get the type params from the method receiver (after skipping @@ -852,11 +855,6 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes, targs tparams[i] = f.Type } } - for i := range targs { - if targs[i].HasShape() { - base.Fatalf("generiSubst shape %s %+v %+v\n", newsym.Name, shapes[i], targs[i]) - } - } gf := nameNode.Func // Pos of the instantiated function is same as the generic function newf := ir.NewFunc(gf.Pos()) @@ -871,7 +869,6 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes, targs ir.CurFunc = newf assert(len(tparams) == len(shapes)) - assert(len(tparams) == len(targs)) subst := &subster{ g: g, @@ -883,11 +880,6 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes, targs Targs: shapes, Vars: make(map[*ir.Name]*ir.Name), }, - unshapify: typecheck.Tsubster{ - Tparams: shapes, - Targs: targs, - Vars: make(map[*ir.Name]*ir.Name), - }, } newf.Dcl = make([]*ir.Name, 0, len(gf.Dcl)+1) @@ -935,14 +927,14 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes, targs newf.Body = subst.list(gf.Body) // Add code to check that the dictionary is correct. - // TODO: must go away when we move to many->1 shape to concrete mapping. - newf.Body.Prepend(subst.checkDictionary(dictionaryName, targs)...) + // TODO: must be adjusted to deal with shapes, but will go away soon when we move + // to many->1 shape to concrete mapping. + // newf.Body.Prepend(subst.checkDictionary(dictionaryName, shapes)...) ir.CurFunc = savef // Add any new, fully instantiated types seen during the substitution to // g.instTypeList. g.instTypeList = append(g.instTypeList, subst.ts.InstTypeList...) - g.instTypeList = append(g.instTypeList, subst.unshapify.InstTypeList...) if doubleCheck { okConvs := map[ir.Node]bool{} @@ -967,12 +959,6 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes, targs return newf } -func (subst *subster) unshapifyTyp(t *types.Type) *types.Type { - res := subst.unshapify.Typ(t) - types.CheckSize(res) - return res -} - // localvar creates a new name node for the specified local variable and enters it // in subst.vars. It substitutes type arguments for type parameters in the type of // name as needed. @@ -1012,10 +998,7 @@ func (subst *subster) checkDictionary(name *ir.Name, targs []*types.Type) (code for i, t := range targs { if t.HasShape() { // Check the concrete type, not the shape type. - // TODO: can this happen? - //t = subst.unshapify.Typ(t) base.Fatalf("shape type in dictionary %s %+v\n", name.Sym().Name, t) - continue } want := reflectdata.TypePtr(t) typed(types.Types[types.TUINTPTR], want) @@ -1239,7 +1222,6 @@ func (subst *subster) node(n ir.Node) ir.Node { // transform the call. call.X.(*ir.SelectorExpr).SetOp(ir.OXDOT) transformDot(call.X.(*ir.SelectorExpr), true) - call.X.SetType(subst.unshapifyTyp(call.X.Type())) transformCall(call) case ir.ODOT, ir.ODOTPTR: @@ -1367,15 +1349,6 @@ func (subst *subster) node(n ir.Node) ir.Node { m = ir.NewDynamicTypeAssertExpr(dt.Pos(), op, dt.X, rt) m.SetType(dt.Type()) m.SetTypecheck(1) - - case ir.OFUNCINST: - inst := m.(*ir.InstExpr) - targs2 := make([]ir.Node, len(inst.Targs)) - for i, n := range inst.Targs { - targs2[i] = ir.TypeNodeAt(n.Pos(), subst.unshapifyTyp(n.Type())) - // TODO: need an ir.Name node? - } - inst.Targs = targs2 } return m } -- GitLab From 1d35d8ffa5561d1b69ede515c94c2785eaf29e1f Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 29 Jul 2021 15:58:13 -0700 Subject: [PATCH 0565/2500] [dev.typeparams] cmd/compile: switch unified IR from TypeParam.Bound to TypeParam.Constraint Change-Id: Id68d41f09e78343953167cb1e38fb1ebc41a34d4 Reviewed-on: https://go-review.googlesource.com/c/go/+/338429 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/cmd/compile/internal/noder/writer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 0fc7e4f38c..07d4363f89 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -618,7 +618,7 @@ func (w *writer) objDict(obj types2.Object, dict *writerDict) { ntparams := tparams.Len() w.len(ntparams) for i := 0; i < ntparams; i++ { - w.typ(tparams.At(i).Type().(*types2.TypeParam).Bound()) + w.typ(tparams.At(i).Type().(*types2.TypeParam).Constraint()) } nderived := len(dict.derived) -- GitLab From 3e7571f6ffb65a7d45c8035f7f8d2409bfda3307 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 29 Jul 2021 16:01:30 -0700 Subject: [PATCH 0566/2500] [dev.typeparams] go/types,cmd/compile/internal/types2: fix TypeParams.At docs Presumably the "It is safe to call on a nil receiver" comment was mistakenly copied from TypeParams.Len, which is actually safe to call on a nil receiver. Change-Id: Iec5ae32c98dc91ce84a6207b47f2b1e530bdbfe2 Reviewed-on: https://go-review.googlesource.com/c/go/+/338430 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/typeparam.go | 1 - src/go/types/typeparam.go | 1 - 2 files changed, 2 deletions(-) diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index 9f8c921bf1..2614f467b1 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -108,7 +108,6 @@ func (tps *TypeParams) Len() int { } // At returns the i'th type parameter in the list. -// It is safe to call on a nil receiver. func (tps *TypeParams) At(i int) *TypeName { return tps.list()[i] } diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index 8c18b52a9a..a3d60c1648 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -98,7 +98,6 @@ func (tps *TypeParams) Len() int { } // At returns the i'th type parameter in the list. -// It is safe to call on a nil receiver. func (tps *TypeParams) At(i int) *TypeName { return tps.list()[i] } -- GitLab From 27283d208f1757f388ac84d2989e24ee3edcb869 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Thu, 29 Jul 2021 13:36:36 -0700 Subject: [PATCH 0567/2500] [dev.typeparams] cmd/compile: remove now-unneeded check for '==' method for comparable type Comparable type no longer has a special method '=='. Change-Id: I152f324d83343a66300050479181a6607fb7ca26 Reviewed-on: https://go-review.googlesource.com/c/go/+/338409 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Dan Scales --- src/runtime/iface.go | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/runtime/iface.go b/src/runtime/iface.go index 71bd2d2f07..79a49c0dff 100644 --- a/src/runtime/iface.go +++ b/src/runtime/iface.go @@ -214,16 +214,6 @@ imethods: if ipkg == "" { ipkg = inter.pkgpath.name() } - if iname == "==" { - // Don't need '==' method right now (from comparable), - // just fill in with a random pointer for now. - if k == 0 { - fun0 = unsafe.Pointer(m) - } else { - methods[k] = unsafe.Pointer(m) - } - continue imethods - } for ; j < nt; j++ { t := &xmhdr[j] tname := typ.nameOff(t.name) -- GitLab From 4480e3b11ab6dcd8d4c6a1e87388f573ff49f429 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Thu, 29 Jul 2021 16:39:49 -0400 Subject: [PATCH 0568/2500] [dev.typeparams] go/types: backport lazy loading changes from CL 336252 When CL 336252 was created (itself a port of CL 335929), types2 tests revealed that lazy expansion of instances was not behaving correctly with respect to lazy loading of Named types. This CL ports the fixes from CL 336252 back to go/types. Change-Id: Iffc6c84a708449633153b800dfb98ff57402893c Reviewed-on: https://go-review.googlesource.com/c/go/+/338369 Trust: Robert Findley Trust: Robert Griesemer Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/decl.go | 4 +-- src/go/types/instance.go | 29 ++++++++++++---------- src/go/types/instantiate.go | 11 ++++++--- src/go/types/lookup.go | 2 +- src/go/types/named.go | 49 +++++++++++++++++++++---------------- src/go/types/predicates.go | 2 +- src/go/types/sizeof_test.go | 2 +- src/go/types/subst.go | 2 +- src/go/types/typestring.go | 3 +++ 9 files changed, 61 insertions(+), 43 deletions(-) diff --git a/src/go/types/decl.go b/src/go/types/decl.go index ad88c30282..831b1da589 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -317,7 +317,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { } case *Named: - t.complete() + t.expand() // don't touch the type if it is from a different package or the Universe scope // (doing so would lead to a race condition - was issue #35049) if t.obj.pkg != check.pkg { @@ -747,7 +747,7 @@ func (check *Checker) collectMethods(obj *TypeName) { } if base != nil { - base.expand() // TODO(mdempsky): Probably unnecessary. + base.load() // TODO(mdempsky): Probably unnecessary. base.methods = append(base.methods, m) } } diff --git a/src/go/types/instance.go b/src/go/types/instance.go index 5e0447b434..1223c9f6f1 100644 --- a/src/go/types/instance.go +++ b/src/go/types/instance.go @@ -8,34 +8,37 @@ package types import "go/token" -// instance holds a Checker along with syntactic information -// information, for use in lazy instantiation. +// instance holds position information for use in lazy instantiation. +// +// TODO(rfindley): come up with a better name for this type, now that its usage +// has changed. type instance struct { - check *Checker pos token.Pos // position of type instantiation; for error reporting only posList []token.Pos // position of each targ; for error reporting only } -// complete ensures that the underlying type of n is instantiated. +// expand ensures that the underlying type of n is instantiated. // The underlying type will be Typ[Invalid] if there was an error. // TODO(rfindley): expand would be a better name for this method, but conflicts // with the existing concept of lazy expansion. Need to reconcile this. -func (n *Named) complete() { - if n.instance != nil && len(n.targs) > 0 && n.underlying == nil { - check := n.instance.check - inst := check.instantiate(n.instance.pos, n.orig.underlying, n.TParams().list(), n.targs, n.instance.posList) +func (n *Named) expand() { + if n.instance != nil { + // n must be loaded before instantiation, in order to have accurate + // tparams. This is done implicitly by the call to n.TParams, but making it + // explicit is harmless: load is idempotent. + n.load() + inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams().list(), n.targs, n.instance.posList) n.underlying = inst n.fromRHS = inst - n.methods = n.orig.methods + n.instance = nil } } -// expand expands a type instance into its instantiated -// type and leaves all other types alone. expand does -// not recurse. +// expand expands uninstantiated named types and leaves all other types alone. +// expand does not recurse. func expand(typ Type) Type { if t, _ := typ.(*Named); t != nil { - t.complete() + t.expand() } return typ } diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 1d3bbc2667..28d68cad0e 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -105,7 +105,9 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, tparams []*TypeName, // instantiating the type until needed. typ must be a *Named // type. func (check *Checker) InstantiateLazy(pos token.Pos, typ Type, targs []Type, posList []token.Pos, verify bool) Type { - base := asNamed(typ) + // Don't use asNamed here: we don't want to expand the base during lazy + // instantiation. + base := typ.(*Named) if base == nil { panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } @@ -116,15 +118,18 @@ func (check *Checker) InstantiateLazy(pos token.Pos, typ Type, targs []Type, pos } h := instantiatedHash(base, targs) if check != nil { + // typ may already have been instantiated with identical type arguments. In + // that case, re-use the existing instance. if named := check.typMap[h]; named != nil { return named } } tname := NewTypeName(pos, base.obj.pkg, base.obj.name, nil) - named := check.newNamed(tname, base, nil, base.TParams(), base.methods) // methods are instantiated lazily + named := check.newNamed(tname, base, nil, nil, nil) // methods and tparams are set when named is loaded. named.targs = targs - named.instance = &instance{check, pos, posList} + named.instance = &instance{pos, posList} + if check != nil { check.typMap[h] = named } diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index 8b1d70a978..07baf2a48b 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -121,7 +121,7 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o seen[named] = true // look for a matching attached method - named.expand() + named.load() if i, m := lookupMethod(named.methods, pkg, name); m != nil { // potential match // caution: method may not have a proper signature yet diff --git a/src/go/types/named.go b/src/go/types/named.go index 03af3fbc5a..87eaa3179e 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -10,12 +10,13 @@ import "sync" // A Named represents a named (defined) type. type Named struct { - instance *instance // syntactic information for lazy instantiation + check *Checker info typeInfo // for cycle detection obj *TypeName // corresponding declared object orig *Named // original, uninstantiated type fromRHS Type // type (on RHS of declaration) this *Named type is derived of (for cycle reporting) underlying Type // possibly a *Named during setup; never a *Named once set up completely + instance *instance // syntactic information for lazy instantiation tparams *TypeParams // type parameters, or nil targs []Type // type arguments (after instantiation), or nil methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily @@ -34,7 +35,19 @@ func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named { return (*Checker)(nil).newNamed(obj, nil, underlying, nil, methods) } -func (t *Named) expand() *Named { +func (t *Named) load() *Named { + // If t is an instantiated type, it derives its methods and tparams from its + // base type. Since we expect type parameters and methods to be set after a + // call to load, we must load the base and copy here. + // + // underlying is set when t is expanded. + // + // By convention, a type instance is loaded iff its tparams are set. + if len(t.targs) > 0 && t.tparams == nil { + t.orig.load() + t.tparams = t.orig.tparams + t.methods = t.orig.methods + } if t.resolve == nil { return t } @@ -65,13 +78,7 @@ func (t *Named) expand() *Named { // newNamed is like NewNamed but with a *Checker receiver and additional orig argument. func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams *TypeParams, methods []*Func) *Named { - var inst *instance - if check != nil { - inst = &instance{ - check: check, - } - } - typ := &Named{instance: inst, obj: obj, orig: orig, fromRHS: underlying, underlying: underlying, tparams: tparams, methods: methods} + typ := &Named{check: check, obj: obj, orig: orig, fromRHS: underlying, underlying: underlying, tparams: tparams, methods: methods} if typ.orig == nil { typ.orig = typ } @@ -92,7 +99,7 @@ func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tpar case *Named: panic("internal error: unexpanded underlying type") } - typ.instance = nil + typ.check = nil }) } return typ @@ -110,10 +117,10 @@ func (t *Named) _Orig() *Named { return t.orig } // TParams returns the type parameters of the named type t, or nil. // The result is non-nil for an (originally) parameterized type even if it is instantiated. -func (t *Named) TParams() *TypeParams { return t.expand().tparams } +func (t *Named) TParams() *TypeParams { return t.load().tparams } // SetTParams sets the type parameters of the named type t. -func (t *Named) SetTParams(tparams []*TypeName) { t.expand().tparams = bindTParams(tparams) } +func (t *Named) SetTParams(tparams []*TypeName) { t.load().tparams = bindTParams(tparams) } // TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated. func (t *Named) TArgs() []Type { return t.targs } @@ -122,10 +129,10 @@ func (t *Named) TArgs() []Type { return t.targs } func (t *Named) SetTArgs(args []Type) { t.targs = args } // NumMethods returns the number of explicit methods whose receiver is named type t. -func (t *Named) NumMethods() int { return len(t.expand().methods) } +func (t *Named) NumMethods() int { return len(t.load().methods) } // Method returns the i'th method of named type t for 0 <= i < t.NumMethods(). -func (t *Named) Method(i int) *Func { return t.expand().methods[i] } +func (t *Named) Method(i int) *Func { return t.load().methods[i] } // SetUnderlying sets the underlying type and marks t as complete. func (t *Named) SetUnderlying(underlying Type) { @@ -135,18 +142,18 @@ func (t *Named) SetUnderlying(underlying Type) { if _, ok := underlying.(*Named); ok { panic("types.Named.SetUnderlying: underlying type must not be *Named") } - t.expand().underlying = underlying + t.load().underlying = underlying } // AddMethod adds method m unless it is already in the method list. func (t *Named) AddMethod(m *Func) { - t.expand() + t.load() if i, _ := lookupMethod(t.methods, m.pkg, m.name); i < 0 { t.methods = append(t.methods, m) } } -func (t *Named) Underlying() Type { return t.expand().underlying } +func (t *Named) Underlying() Type { return t.load().underlying } func (t *Named) String() string { return TypeString(t, nil) } // ---------------------------------------------------------------------------- @@ -159,7 +166,7 @@ func (t *Named) String() string { return TypeString(t, nil) } // is detected, the result is Typ[Invalid]. If a cycle is detected and // n0.check != nil, the cycle is reported. func (n0 *Named) under() Type { - n0.complete() + n0.expand() u := n0.Underlying() @@ -180,13 +187,13 @@ func (n0 *Named) under() Type { // handled below } - if n0.instance == nil || n0.instance.check == nil { + if n0.check == nil { panic("internal error: Named.check == nil but type is incomplete") } // Invariant: after this point n0 as well as any named types in its // underlying chain should be set up when this function exits. - check := n0.instance.check + check := n0.check // If we can't expand u at this point, it is invalid. n := asNamed(u) @@ -207,7 +214,7 @@ func (n0 *Named) under() Type { var n1 *Named switch u1 := u.(type) { case *Named: - u1.complete() + u1.expand() n1 = u1 } if n1 == nil { diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 181e2fcfc5..41e0c25d6b 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -21,7 +21,7 @@ func isNamed(typ Type) bool { func isGeneric(typ Type) bool { // A parameterized type is only instantiated if it doesn't have an instantiation already. named, _ := typ.(*Named) - return named != nil && named.obj != nil && named.TParams() != nil && named.targs == nil + return named != nil && named.obj != nil && named.targs == nil && named.TParams() != nil } func is(typ Type, what BasicInfo) bool { diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index 29e298103b..c8758663ec 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -30,7 +30,7 @@ func TestSizeof(t *testing.T) { {Interface{}, 40, 80}, {Map{}, 16, 32}, {Chan{}, 12, 24}, - {Named{}, 76, 144}, + {Named{}, 80, 152}, {TypeParam{}, 28, 48}, {top{}, 0, 0}, diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 60fc7ae819..c05e51d425 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -244,7 +244,7 @@ func (subst *subster) typ(typ Type) Type { named := subst.check.newNamed(tname, t, t.Underlying(), t.TParams(), t.methods) // method signatures are updated lazily named.targs = newTargs subst.typMap[h] = named - t.complete() // must happen after typMap update to avoid infinite recursion + t.expand() // must happen after typMap update to avoid infinite recursion // do the substitution dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, newTargs) diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 6a9e7f2ac8..74b18a9ec8 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -270,6 +270,9 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { } case *Named: + if t.instance != nil { + buf.WriteByte(instanceMarker) + } writeTypeName(buf, t.obj, qf) if t.targs != nil { // instantiated type -- GitLab From 137089ffb9c16288d2620a2c65dd56406f32eb84 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Wed, 14 Jul 2021 13:52:00 -0700 Subject: [PATCH 0569/2500] [dev.cmdgo] cmd/internal/str: move package from cmd/go/internal/str This will let cmd/cgo and cmd/link use this package for argument parsing. For golang/go#41400 Change-Id: I12ee21151bf3f00f3e8d427faaaab2453c823117 Reviewed-on: https://go-review.googlesource.com/c/go/+/334730 Trust: Jay Conrod Reviewed-by: Michael Matloob --- src/cmd/go/internal/base/base.go | 2 +- src/cmd/go/internal/base/flag.go | 2 +- src/cmd/go/internal/fix/fix.go | 2 +- src/cmd/go/internal/fmtcmd/fmt.go | 2 +- src/cmd/go/internal/generate/generate.go | 2 +- src/cmd/go/internal/get/get.go | 2 +- src/cmd/go/internal/list/list.go | 2 +- src/cmd/go/internal/load/flag.go | 2 +- src/cmd/go/internal/load/pkg.go | 2 +- src/cmd/go/internal/load/test.go | 2 +- src/cmd/go/internal/modcmd/vendor.go | 2 +- src/cmd/go/internal/modfetch/codehost/codehost.go | 2 +- src/cmd/go/internal/modfetch/codehost/vcs.go | 2 +- src/cmd/go/internal/modget/query.go | 2 +- src/cmd/go/internal/modload/load.go | 2 +- src/cmd/go/internal/modload/query.go | 2 +- src/cmd/go/internal/run/run.go | 2 +- src/cmd/go/internal/test/test.go | 2 +- src/cmd/go/internal/vcs/vcs.go | 2 +- src/cmd/go/internal/work/buildid.go | 2 +- src/cmd/go/internal/work/exec.go | 2 +- src/cmd/go/internal/work/gc.go | 2 +- src/cmd/go/internal/work/gccgo.go | 2 +- src/cmd/{go => }/internal/str/path.go | 0 src/cmd/{go => }/internal/str/str.go | 0 src/cmd/{go => }/internal/str/str_test.go | 0 26 files changed, 23 insertions(+), 23 deletions(-) rename src/cmd/{go => }/internal/str/path.go (100%) rename src/cmd/{go => }/internal/str/str.go (100%) rename src/cmd/{go => }/internal/str/str_test.go (100%) diff --git a/src/cmd/go/internal/base/base.go b/src/cmd/go/internal/base/base.go index 954ce47a98..0144525e30 100644 --- a/src/cmd/go/internal/base/base.go +++ b/src/cmd/go/internal/base/base.go @@ -17,7 +17,7 @@ import ( "sync" "cmd/go/internal/cfg" - "cmd/go/internal/str" + "cmd/internal/str" ) // A Command is an implementation of a go command diff --git a/src/cmd/go/internal/base/flag.go b/src/cmd/go/internal/base/flag.go index 2262e2e992..7e5121bffb 100644 --- a/src/cmd/go/internal/base/flag.go +++ b/src/cmd/go/internal/base/flag.go @@ -9,7 +9,7 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/fsys" - "cmd/go/internal/str" + "cmd/internal/str" ) // A StringsFlag is a command-line flag that interprets its argument diff --git a/src/cmd/go/internal/fix/fix.go b/src/cmd/go/internal/fix/fix.go index 988d45e71c..cc5940fccd 100644 --- a/src/cmd/go/internal/fix/fix.go +++ b/src/cmd/go/internal/fix/fix.go @@ -10,7 +10,7 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/load" "cmd/go/internal/modload" - "cmd/go/internal/str" + "cmd/internal/str" "context" "fmt" "os" diff --git a/src/cmd/go/internal/fmtcmd/fmt.go b/src/cmd/go/internal/fmtcmd/fmt.go index 8a04008753..2b89a078ac 100644 --- a/src/cmd/go/internal/fmtcmd/fmt.go +++ b/src/cmd/go/internal/fmtcmd/fmt.go @@ -18,7 +18,7 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/load" "cmd/go/internal/modload" - "cmd/go/internal/str" + "cmd/internal/str" ) func init() { diff --git a/src/cmd/go/internal/generate/generate.go b/src/cmd/go/internal/generate/generate.go index 80ea32b428..d7f2eb4610 100644 --- a/src/cmd/go/internal/generate/generate.go +++ b/src/cmd/go/internal/generate/generate.go @@ -25,8 +25,8 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/load" "cmd/go/internal/modload" - "cmd/go/internal/str" "cmd/go/internal/work" + "cmd/internal/str" ) var CmdGenerate = &base.Command{ diff --git a/src/cmd/go/internal/get/get.go b/src/cmd/go/internal/get/get.go index cc676428e2..075594b271 100644 --- a/src/cmd/go/internal/get/get.go +++ b/src/cmd/go/internal/get/get.go @@ -17,10 +17,10 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/load" "cmd/go/internal/search" - "cmd/go/internal/str" "cmd/go/internal/vcs" "cmd/go/internal/web" "cmd/go/internal/work" + "cmd/internal/str" "golang.org/x/mod/module" ) diff --git a/src/cmd/go/internal/list/list.go b/src/cmd/go/internal/list/list.go index 04630dc341..704d61e7c1 100644 --- a/src/cmd/go/internal/list/list.go +++ b/src/cmd/go/internal/list/list.go @@ -23,8 +23,8 @@ import ( "cmd/go/internal/load" "cmd/go/internal/modinfo" "cmd/go/internal/modload" - "cmd/go/internal/str" "cmd/go/internal/work" + "cmd/internal/str" ) var CmdList = &base.Command{ diff --git a/src/cmd/go/internal/load/flag.go b/src/cmd/go/internal/load/flag.go index 440cb86134..4e0cb5bc19 100644 --- a/src/cmd/go/internal/load/flag.go +++ b/src/cmd/go/internal/load/flag.go @@ -6,7 +6,7 @@ package load import ( "cmd/go/internal/base" - "cmd/go/internal/str" + "cmd/internal/str" "fmt" "strings" ) diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index ac89127a4b..f0613a4c0a 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -36,8 +36,8 @@ import ( "cmd/go/internal/modload" "cmd/go/internal/par" "cmd/go/internal/search" - "cmd/go/internal/str" "cmd/go/internal/trace" + "cmd/internal/str" "cmd/internal/sys" "golang.org/x/mod/modfile" diff --git a/src/cmd/go/internal/load/test.go b/src/cmd/go/internal/load/test.go index c828296566..42eefe37ba 100644 --- a/src/cmd/go/internal/load/test.go +++ b/src/cmd/go/internal/load/test.go @@ -22,8 +22,8 @@ import ( "unicode/utf8" "cmd/go/internal/fsys" - "cmd/go/internal/str" "cmd/go/internal/trace" + "cmd/internal/str" ) var TestMainDeps = []string{ diff --git a/src/cmd/go/internal/modcmd/vendor.go b/src/cmd/go/internal/modcmd/vendor.go index 3506655a4a..6273afbbe6 100644 --- a/src/cmd/go/internal/modcmd/vendor.go +++ b/src/cmd/go/internal/modcmd/vendor.go @@ -24,7 +24,7 @@ import ( "cmd/go/internal/imports" "cmd/go/internal/load" "cmd/go/internal/modload" - "cmd/go/internal/str" + "cmd/internal/str" "golang.org/x/mod/module" "golang.org/x/mod/semver" diff --git a/src/cmd/go/internal/modfetch/codehost/codehost.go b/src/cmd/go/internal/modfetch/codehost/codehost.go index 378fbae34f..efb4b1516a 100644 --- a/src/cmd/go/internal/modfetch/codehost/codehost.go +++ b/src/cmd/go/internal/modfetch/codehost/codehost.go @@ -21,7 +21,7 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/lockedfile" - "cmd/go/internal/str" + "cmd/internal/str" ) // Downloaded size limits. diff --git a/src/cmd/go/internal/modfetch/codehost/vcs.go b/src/cmd/go/internal/modfetch/codehost/vcs.go index c2cca084e3..5d810d2621 100644 --- a/src/cmd/go/internal/modfetch/codehost/vcs.go +++ b/src/cmd/go/internal/modfetch/codehost/vcs.go @@ -20,7 +20,7 @@ import ( "cmd/go/internal/lockedfile" "cmd/go/internal/par" - "cmd/go/internal/str" + "cmd/internal/str" ) // A VCSError indicates an error using a version control system. diff --git a/src/cmd/go/internal/modget/query.go b/src/cmd/go/internal/modget/query.go index bbb364fa5e..76041906f2 100644 --- a/src/cmd/go/internal/modget/query.go +++ b/src/cmd/go/internal/modget/query.go @@ -14,7 +14,7 @@ import ( "cmd/go/internal/base" "cmd/go/internal/modload" "cmd/go/internal/search" - "cmd/go/internal/str" + "cmd/internal/str" "golang.org/x/mod/module" ) diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index e7b03b08e9..a643cca0a9 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -118,7 +118,7 @@ import ( "cmd/go/internal/mvs" "cmd/go/internal/par" "cmd/go/internal/search" - "cmd/go/internal/str" + "cmd/internal/str" "golang.org/x/mod/module" "golang.org/x/mod/semver" diff --git a/src/cmd/go/internal/modload/query.go b/src/cmd/go/internal/modload/query.go index 05ef0a9c48..ba137eda1d 100644 --- a/src/cmd/go/internal/modload/query.go +++ b/src/cmd/go/internal/modload/query.go @@ -21,8 +21,8 @@ import ( "cmd/go/internal/imports" "cmd/go/internal/modfetch" "cmd/go/internal/search" - "cmd/go/internal/str" "cmd/go/internal/trace" + "cmd/internal/str" "golang.org/x/mod/module" "golang.org/x/mod/semver" diff --git a/src/cmd/go/internal/run/run.go b/src/cmd/go/internal/run/run.go index 7d9e2930ab..931fdcef8f 100644 --- a/src/cmd/go/internal/run/run.go +++ b/src/cmd/go/internal/run/run.go @@ -18,8 +18,8 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/load" "cmd/go/internal/modload" - "cmd/go/internal/str" "cmd/go/internal/work" + "cmd/internal/str" ) var CmdRun = &base.Command{ diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 5fcea18caa..5e02a397a6 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -31,9 +31,9 @@ import ( "cmd/go/internal/lockedfile" "cmd/go/internal/modload" "cmd/go/internal/search" - "cmd/go/internal/str" "cmd/go/internal/trace" "cmd/go/internal/work" + "cmd/internal/str" "cmd/internal/test2json" ) diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go index 91485f6f74..97b2a631ae 100644 --- a/src/cmd/go/internal/vcs/vcs.go +++ b/src/cmd/go/internal/vcs/vcs.go @@ -23,8 +23,8 @@ import ( "cmd/go/internal/base" "cmd/go/internal/cfg" "cmd/go/internal/search" - "cmd/go/internal/str" "cmd/go/internal/web" + "cmd/internal/str" "golang.org/x/mod/module" ) diff --git a/src/cmd/go/internal/work/buildid.go b/src/cmd/go/internal/work/buildid.go index 4e9189a363..15f944d2af 100644 --- a/src/cmd/go/internal/work/buildid.go +++ b/src/cmd/go/internal/work/buildid.go @@ -15,8 +15,8 @@ import ( "cmd/go/internal/cache" "cmd/go/internal/cfg" "cmd/go/internal/fsys" - "cmd/go/internal/str" "cmd/internal/buildid" + "cmd/internal/str" ) // Build IDs diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index b506b83656..d51ec144f3 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -34,8 +34,8 @@ import ( "cmd/go/internal/fsys" "cmd/go/internal/load" "cmd/go/internal/modload" - "cmd/go/internal/str" "cmd/go/internal/trace" + "cmd/internal/str" ) // actionList returns the list of actions in the dag rooted at root diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go index 85da4f89f9..c5f3fc264f 100644 --- a/src/cmd/go/internal/work/gc.go +++ b/src/cmd/go/internal/work/gc.go @@ -20,8 +20,8 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/fsys" "cmd/go/internal/load" - "cmd/go/internal/str" "cmd/internal/objabi" + "cmd/internal/str" "cmd/internal/sys" "crypto/sha1" ) diff --git a/src/cmd/go/internal/work/gccgo.go b/src/cmd/go/internal/work/gccgo.go index 1499536932..3cb7b64183 100644 --- a/src/cmd/go/internal/work/gccgo.go +++ b/src/cmd/go/internal/work/gccgo.go @@ -16,8 +16,8 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/fsys" "cmd/go/internal/load" - "cmd/go/internal/str" "cmd/internal/pkgpath" + "cmd/internal/str" ) // The Gccgo toolchain. diff --git a/src/cmd/go/internal/str/path.go b/src/cmd/internal/str/path.go similarity index 100% rename from src/cmd/go/internal/str/path.go rename to src/cmd/internal/str/path.go diff --git a/src/cmd/go/internal/str/str.go b/src/cmd/internal/str/str.go similarity index 100% rename from src/cmd/go/internal/str/str.go rename to src/cmd/internal/str/str.go diff --git a/src/cmd/go/internal/str/str_test.go b/src/cmd/internal/str/str_test.go similarity index 100% rename from src/cmd/go/internal/str/str_test.go rename to src/cmd/internal/str/str_test.go -- GitLab From 3a69cef65a856afd1f8b9d5c22e6729d0f4d84ac Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Wed, 14 Jul 2021 15:37:06 -0700 Subject: [PATCH 0570/2500] [dev.cmdgo] cmd/internal/str: add utilities for quoting and splitting args JoinAndQuoteFields does the inverse of SplitQuotedFields: it joins a list of arguments with spaces into one string, quoting arguments that contain spaces or quotes. QuotedStringListFlag uses SplitQuotedFields and JoinAndQuoteFields together to define new flags that accept lists of arguments. For golang/go#41400 Change-Id: I4986b753cb5e6fabb5b489bf26aedab889f853f5 Reviewed-on: https://go-review.googlesource.com/c/go/+/334731 Trust: Jay Conrod Trust: Michael Matloob Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills Reviewed-by: Michael Matloob --- src/cmd/internal/str/str.go | 72 +++++++++++++++++++++++++++ src/cmd/internal/str/str_test.go | 83 +++++++++++++++++++++++++++++++- 2 files changed, 154 insertions(+), 1 deletion(-) diff --git a/src/cmd/internal/str/str.go b/src/cmd/internal/str/str.go index 9106ebf74d..409cf8f7b4 100644 --- a/src/cmd/internal/str/str.go +++ b/src/cmd/internal/str/str.go @@ -7,7 +7,9 @@ package str import ( "bytes" + "flag" "fmt" + "strings" "unicode" "unicode/utf8" ) @@ -153,3 +155,73 @@ func SplitQuotedFields(s string) ([]string, error) { } return f, nil } + +// JoinAndQuoteFields joins a list of arguments into a string that can be parsed +// with SplitQuotedFields. Arguments are quoted only if necessary; arguments +// without spaces or quotes are kept as-is. No argument may contain both +// single and double quotes. +func JoinAndQuoteFields(args []string) (string, error) { + var buf []byte + for i, arg := range args { + if i > 0 { + buf = append(buf, ' ') + } + var sawSpace, sawSingleQuote, sawDoubleQuote bool + for _, c := range arg { + switch { + case c > unicode.MaxASCII: + continue + case isSpaceByte(byte(c)): + sawSpace = true + case c == '\'': + sawSingleQuote = true + case c == '"': + sawDoubleQuote = true + } + } + switch { + case !sawSpace && !sawSingleQuote && !sawDoubleQuote: + buf = append(buf, []byte(arg)...) + + case !sawSingleQuote: + buf = append(buf, '\'') + buf = append(buf, []byte(arg)...) + buf = append(buf, '\'') + + case !sawDoubleQuote: + buf = append(buf, '"') + buf = append(buf, []byte(arg)...) + buf = append(buf, '"') + + default: + return "", fmt.Errorf("argument %q contains both single and double quotes and cannot be quoted", arg) + } + } + return string(buf), nil +} + +// A QuotedStringListFlag parses a list of string arguments encoded with +// JoinAndQuoteFields. It is useful for flags like cmd/link's -extldflags. +type QuotedStringListFlag []string + +var _ flag.Value = (*QuotedStringListFlag)(nil) + +func (f *QuotedStringListFlag) Set(v string) error { + fs, err := SplitQuotedFields(v) + if err != nil { + return err + } + *f = fs[:len(fs):len(fs)] + return nil +} + +func (f *QuotedStringListFlag) String() string { + if f == nil { + return "" + } + s, err := JoinAndQuoteFields(*f) + if err != nil { + return strings.Join(*f, " ") + } + return s +} diff --git a/src/cmd/internal/str/str_test.go b/src/cmd/internal/str/str_test.go index 147ce1a63e..3609af6a06 100644 --- a/src/cmd/internal/str/str_test.go +++ b/src/cmd/internal/str/str_test.go @@ -4,7 +4,11 @@ package str -import "testing" +import ( + "reflect" + "strings" + "testing" +) var foldDupTests = []struct { list []string @@ -25,3 +29,80 @@ func TestFoldDup(t *testing.T) { } } } + +func TestSplitQuotedFields(t *testing.T) { + for _, test := range []struct { + name string + value string + want []string + wantErr string + }{ + {name: "empty", value: "", want: nil}, + {name: "space", value: " ", want: nil}, + {name: "one", value: "a", want: []string{"a"}}, + {name: "leading_space", value: " a", want: []string{"a"}}, + {name: "trailing_space", value: "a ", want: []string{"a"}}, + {name: "two", value: "a b", want: []string{"a", "b"}}, + {name: "two_multi_space", value: "a b", want: []string{"a", "b"}}, + {name: "two_tab", value: "a\tb", want: []string{"a", "b"}}, + {name: "two_newline", value: "a\nb", want: []string{"a", "b"}}, + {name: "quote_single", value: `'a b'`, want: []string{"a b"}}, + {name: "quote_double", value: `"a b"`, want: []string{"a b"}}, + {name: "quote_both", value: `'a '"b "`, want: []string{"a ", "b "}}, + {name: "quote_contains", value: `'a "'"'b"`, want: []string{`a "`, `'b`}}, + {name: "escape", value: `\'`, want: []string{`\'`}}, + {name: "quote_unclosed", value: `'a`, wantErr: "unterminated ' string"}, + } { + t.Run(test.name, func(t *testing.T) { + got, err := SplitQuotedFields(test.value) + if err != nil { + if test.wantErr == "" { + t.Fatalf("unexpected error: %v", err) + } else if errMsg := err.Error(); !strings.Contains(errMsg, test.wantErr) { + t.Fatalf("error %q does not contain %q", errMsg, test.wantErr) + } + return + } + if test.wantErr != "" { + t.Fatalf("unexpected success; wanted error containing %q", test.wantErr) + } + if !reflect.DeepEqual(got, test.want) { + t.Errorf("got %q; want %q", got, test.want) + } + }) + } +} + +func TestJoinAndQuoteFields(t *testing.T) { + for _, test := range []struct { + name string + args []string + want, wantErr string + }{ + {name: "empty", args: nil, want: ""}, + {name: "one", args: []string{"a"}, want: "a"}, + {name: "two", args: []string{"a", "b"}, want: "a b"}, + {name: "space", args: []string{"a ", "b"}, want: "'a ' b"}, + {name: "newline", args: []string{"a\n", "b"}, want: "'a\n' b"}, + {name: "quote", args: []string{`'a `, "b"}, want: `"'a " b`}, + {name: "unquoteable", args: []string{`'"`}, wantErr: "contains both single and double quotes and cannot be quoted"}, + } { + t.Run(test.name, func(t *testing.T) { + got, err := JoinAndQuoteFields(test.args) + if err != nil { + if test.wantErr == "" { + t.Fatalf("unexpected error: %v", err) + } else if errMsg := err.Error(); !strings.Contains(errMsg, test.wantErr) { + t.Fatalf("error %q does not contain %q", errMsg, test.wantErr) + } + return + } + if test.wantErr != "" { + t.Fatalf("unexpected success; wanted error containing %q", test.wantErr) + } + if got != test.want { + t.Errorf("got %s; want %s", got, test.want) + } + }) + } +} -- GitLab From 52e970b1c86f18806232adb0e1f42636645d21ff Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Wed, 14 Jul 2021 16:57:24 -0700 Subject: [PATCH 0571/2500] [dev.cmdgo] cmd: support space and quotes in CC and CXX The CC and CXX environment variables now support spaces and quotes (both double and single). This fixes two issues: first, if CC is a single path that contains spaces (like 'c:\Program Files\gcc\bin\gcc.exe'), that should now work if the space is quoted or escaped (#41400). Second, if CC or CXX has multiple arguments (like 'gcc -O2'), they are now split correctly, and the arguments are passed before other arguments when invoking the C compiler. Previously, strings.Fields was used to split arguments, and the arguments were placed later in the command line. (#43078). Fixes golang/go#41400 Fixes golang/go#43078 Change-Id: I2d5d89ddb19c94adef65982a8137b01f037d5c11 Reviewed-on: https://go-review.googlesource.com/c/go/+/334732 Trust: Jay Conrod Trust: Michael Matloob Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Michael Matloob --- src/cmd/cgo/gcc.go | 46 ++++++++++----- src/cmd/cgo/main.go | 8 +-- .../compile/internal/ssa/stmtlines_test.go | 7 ++- src/cmd/dist/buildtool.go | 1 + src/cmd/go/internal/envcmd/env.go | 34 +++++++---- src/cmd/go/internal/work/exec.go | 43 +++++--------- src/cmd/go/internal/work/gc.go | 37 +++++------- src/cmd/go/internal/work/init.go | 16 +++++- src/cmd/go/script_test.go | 1 + .../testdata/script/cgo_path_space_quote.txt | 56 +++++++++++++++++++ src/cmd/internal/dwarf/dwarf.go | 6 +- src/cmd/link/dwarf_test.go | 8 ++- src/cmd/link/internal/ld/lib.go | 39 ++++++++----- src/cmd/link/internal/ld/main.go | 7 ++- 14 files changed, 206 insertions(+), 103 deletions(-) create mode 100644 src/cmd/go/testdata/script/cgo_path_space_quote.txt diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index a73e998877..92adb1ed9c 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -23,10 +23,13 @@ import ( "internal/xcoff" "math" "os" + "os/exec" "strconv" "strings" "unicode" "unicode/utf8" + + "cmd/internal/str" ) var debugDefine = flag.Bool("debug-define", false, "print relevant #defines") @@ -382,7 +385,7 @@ func (p *Package) guessKinds(f *File) []*Name { stderr = p.gccErrors(b.Bytes()) } if stderr == "" { - fatalf("%s produced no output\non input:\n%s", p.gccBaseCmd()[0], b.Bytes()) + fatalf("%s produced no output\non input:\n%s", gccBaseCmd[0], b.Bytes()) } completed := false @@ -457,7 +460,7 @@ func (p *Package) guessKinds(f *File) []*Name { } if !completed { - fatalf("%s did not produce error at completed:1\non input:\n%s\nfull error output:\n%s", p.gccBaseCmd()[0], b.Bytes(), stderr) + fatalf("%s did not produce error at completed:1\non input:\n%s\nfull error output:\n%s", gccBaseCmd[0], b.Bytes(), stderr) } for i, n := range names { @@ -488,7 +491,7 @@ func (p *Package) guessKinds(f *File) []*Name { // to users debugging preamble mistakes. See issue 8442. preambleErrors := p.gccErrors([]byte(f.Preamble)) if len(preambleErrors) > 0 { - error_(token.NoPos, "\n%s errors for preamble:\n%s", p.gccBaseCmd()[0], preambleErrors) + error_(token.NoPos, "\n%s errors for preamble:\n%s", gccBaseCmd[0], preambleErrors) } fatalf("unresolved names") @@ -1545,20 +1548,37 @@ func gofmtPos(n ast.Expr, pos token.Pos) string { return fmt.Sprintf("/*line :%d:%d*/%s", p.Line, p.Column, s) } -// gccBaseCmd returns the start of the compiler command line. +// checkGCCBaseCmd returns the start of the compiler command line. // It uses $CC if set, or else $GCC, or else the compiler recorded // during the initial build as defaultCC. // defaultCC is defined in zdefaultcc.go, written by cmd/dist. -func (p *Package) gccBaseCmd() []string { +// +// The compiler command line is split into arguments on whitespace. Quotes +// are understood, so arguments may contain whitespace. +// +// checkGCCBaseCmd confirms that the compiler exists in PATH, returning +// an error if it does not. +func checkGCCBaseCmd() ([]string, error) { // Use $CC if set, since that's what the build uses. - if ret := strings.Fields(os.Getenv("CC")); len(ret) > 0 { - return ret + value := os.Getenv("CC") + if value == "" { + // Try $GCC if set, since that's what we used to use. + value = os.Getenv("GCC") + } + if value == "" { + value = defaultCC(goos, goarch) + } + args, err := str.SplitQuotedFields(value) + if err != nil { + return nil, err + } + if len(args) == 0 { + return nil, errors.New("CC not set and no default found") } - // Try $GCC if set, since that's what we used to use. - if ret := strings.Fields(os.Getenv("GCC")); len(ret) > 0 { - return ret + if _, err := exec.LookPath(args[0]); err != nil { + return nil, fmt.Errorf("C compiler %q not found: %v", args[0], err) } - return strings.Fields(defaultCC(goos, goarch)) + return args[:len(args):len(args)], nil } // gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm". @@ -1604,7 +1624,7 @@ func gccTmp() string { // gccCmd returns the gcc command line to use for compiling // the input. func (p *Package) gccCmd() []string { - c := append(p.gccBaseCmd(), + c := append(gccBaseCmd, "-w", // no warnings "-Wno-error", // warnings are not errors "-o"+gccTmp(), // write object to tmp @@ -2005,7 +2025,7 @@ func (p *Package) gccDebug(stdin []byte, nnames int) (d *dwarf.Data, ints []int6 // #defines that gcc encountered while processing the input // and its included files. func (p *Package) gccDefines(stdin []byte) string { - base := append(p.gccBaseCmd(), "-E", "-dM", "-xc") + base := append(gccBaseCmd, "-E", "-dM", "-xc") base = append(base, p.gccMachine()...) stdout, _ := runGcc(stdin, append(append(base, p.GccOptions...), "-")) return stdout diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go index c6a0c525e6..14642b7576 100644 --- a/src/cmd/cgo/main.go +++ b/src/cmd/cgo/main.go @@ -21,7 +21,6 @@ import ( "io" "io/ioutil" "os" - "os/exec" "path/filepath" "reflect" "runtime" @@ -248,6 +247,7 @@ var importSyscall = flag.Bool("import_syscall", true, "import syscall in generat var trimpath = flag.String("trimpath", "", "applies supplied rewrites or trims prefixes to recorded source file paths") var goarch, goos, gomips, gomips64 string +var gccBaseCmd []string func main() { objabi.AddVersionFlag() // -V @@ -305,10 +305,10 @@ func main() { p := newPackage(args[:i]) // We need a C compiler to be available. Check this. - gccName := p.gccBaseCmd()[0] - _, err := exec.LookPath(gccName) + var err error + gccBaseCmd, err = checkGCCBaseCmd() if err != nil { - fatalf("C compiler %q not found: %v", gccName, err) + fatalf("%v", err) os.Exit(2) } diff --git a/src/cmd/compile/internal/ssa/stmtlines_test.go b/src/cmd/compile/internal/ssa/stmtlines_test.go index a510d0b3d0..843db8c07e 100644 --- a/src/cmd/compile/internal/ssa/stmtlines_test.go +++ b/src/cmd/compile/internal/ssa/stmtlines_test.go @@ -2,6 +2,7 @@ package ssa_test import ( cmddwarf "cmd/internal/dwarf" + "cmd/internal/str" "debug/dwarf" "debug/elf" "debug/macho" @@ -57,7 +58,11 @@ func TestStmtLines(t *testing.T) { if extld == "" { extld = "gcc" } - enabled, err := cmddwarf.IsDWARFEnabledOnAIXLd(extld) + extldArgs, err := str.SplitQuotedFields(extld) + if err != nil { + t.Fatal(err) + } + enabled, err := cmddwarf.IsDWARFEnabledOnAIXLd(extldArgs) if err != nil { t.Fatal(err) } diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go index 26b33e389f..320c62f850 100644 --- a/src/cmd/dist/buildtool.go +++ b/src/cmd/dist/buildtool.go @@ -47,6 +47,7 @@ var bootstrapDirs = []string{ "cmd/internal/objabi", "cmd/internal/pkgpath", "cmd/internal/src", + "cmd/internal/str", "cmd/internal/sys", "cmd/link", "cmd/link/internal/...", diff --git a/src/cmd/go/internal/envcmd/env.go b/src/cmd/go/internal/envcmd/env.go index f68090f21f..5c45e34330 100644 --- a/src/cmd/go/internal/envcmd/env.go +++ b/src/cmd/go/internal/envcmd/env.go @@ -26,6 +26,7 @@ import ( "cmd/go/internal/load" "cmd/go/internal/modload" "cmd/go/internal/work" + "cmd/internal/str" ) var CmdEnv = &base.Command{ @@ -104,13 +105,13 @@ func MkEnv() []cfg.EnvVar { env = append(env, cfg.EnvVar{Name: key, Value: val}) } - cc := cfg.DefaultCC(cfg.Goos, cfg.Goarch) - if env := strings.Fields(cfg.Getenv("CC")); len(env) > 0 { - cc = env[0] + cc := cfg.Getenv("CC") + if cc == "" { + cc = cfg.DefaultCC(cfg.Goos, cfg.Goarch) } - cxx := cfg.DefaultCXX(cfg.Goos, cfg.Goarch) - if env := strings.Fields(cfg.Getenv("CXX")); len(env) > 0 { - cxx = env[0] + cxx := cfg.Getenv("CXX") + if cxx == "" { + cxx = cfg.DefaultCXX(cfg.Goos, cfg.Goarch) } env = append(env, cfg.EnvVar{Name: "AR", Value: envOr("AR", "ar")}) env = append(env, cfg.EnvVar{Name: "CC", Value: cc}) @@ -458,10 +459,23 @@ func checkEnvWrite(key, val string) error { if !filepath.IsAbs(val) && val != "" { return fmt.Errorf("GOPATH entry is relative; must be absolute path: %q", val) } - // Make sure CC and CXX are absolute paths - case "CC", "CXX", "GOMODCACHE": - if !filepath.IsAbs(val) && val != "" && val != filepath.Base(val) { - return fmt.Errorf("%s entry is relative; must be absolute path: %q", key, val) + case "GOMODCACHE": + if !filepath.IsAbs(val) && val != "" { + return fmt.Errorf("GOMODCACHE entry is relative; must be absolute path: %q", val) + } + case "CC", "CXX": + if val == "" { + break + } + args, err := str.SplitQuotedFields(val) + if err != nil { + return fmt.Errorf("invalid %s: %v", key, err) + } + if len(args) == 0 { + return fmt.Errorf("%s entry cannot contain only space", key) + } + if !filepath.IsAbs(args[0]) && args[0] != filepath.Base(args[0]) { + return fmt.Errorf("%s entry is relative; must be absolute path: %q", key, args[0]) } } diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index d51ec144f3..6c646ebf28 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -1480,6 +1480,8 @@ func (b *Builder) getPkgConfigFlags(p *load.Package) (cflags, ldflags []string, return nil, nil, errPrintedOutput } if len(out) > 0 { + // NOTE: we don't attempt to parse quotes and unescapes here. pkg-config + // is typically used within shell backticks, which treats quotes literally. ldflags = strings.Fields(string(out)) if err := checkLinkerFlags("LDFLAGS", "pkg-config --libs", ldflags); err != nil { return nil, nil, err @@ -2422,12 +2424,6 @@ func (b *Builder) gccld(a *Action, p *load.Package, objdir, outfile string, flag return err } -// Grab these before main helpfully overwrites them. -var ( - origCC = cfg.Getenv("CC") - origCXX = cfg.Getenv("CXX") -) - // gccCmd returns a gcc command line prefix // defaultCC is defined in zdefaultcc.go, written by cmd/dist. func (b *Builder) GccCmd(incdir, workdir string) []string { @@ -2447,40 +2443,23 @@ func (b *Builder) gfortranCmd(incdir, workdir string) []string { // ccExe returns the CC compiler setting without all the extra flags we add implicitly. func (b *Builder) ccExe() []string { - return b.compilerExe(origCC, cfg.DefaultCC(cfg.Goos, cfg.Goarch)) + return envList("CC", cfg.DefaultCC(cfg.Goos, cfg.Goarch)) } // cxxExe returns the CXX compiler setting without all the extra flags we add implicitly. func (b *Builder) cxxExe() []string { - return b.compilerExe(origCXX, cfg.DefaultCXX(cfg.Goos, cfg.Goarch)) + return envList("CXX", cfg.DefaultCXX(cfg.Goos, cfg.Goarch)) } // fcExe returns the FC compiler setting without all the extra flags we add implicitly. func (b *Builder) fcExe() []string { - return b.compilerExe(cfg.Getenv("FC"), "gfortran") -} - -// compilerExe returns the compiler to use given an -// environment variable setting (the value not the name) -// and a default. The resulting slice is usually just the name -// of the compiler but can have additional arguments if they -// were present in the environment value. -// For example if CC="gcc -DGOPHER" then the result is ["gcc", "-DGOPHER"]. -func (b *Builder) compilerExe(envValue string, def string) []string { - compiler := strings.Fields(envValue) - if len(compiler) == 0 { - compiler = strings.Fields(def) - } - return compiler + return envList("FC", "gfortran") } // compilerCmd returns a command line prefix for the given environment // variable and using the default command when the variable is empty. func (b *Builder) compilerCmd(compiler []string, incdir, workdir string) []string { - // NOTE: env.go's mkEnv knows that the first three - // strings returned are "gcc", "-I", incdir (and cuts them off). - a := []string{compiler[0], "-I", incdir} - a = append(a, compiler[1:]...) + a := append(compiler, "-I", incdir) // Definitely want -fPIC but on Windows gcc complains // "-fPIC ignored for target (all code is position independent)" @@ -2651,12 +2630,20 @@ func (b *Builder) gccArchArgs() []string { // envList returns the value of the given environment variable broken // into fields, using the default value when the variable is empty. +// +// The environment variable must be quoted correctly for +// str.SplitQuotedFields. This should be done before building +// anything, for example, in BuildInit. func envList(key, def string) []string { v := cfg.Getenv(key) if v == "" { v = def } - return strings.Fields(v) + args, err := str.SplitQuotedFields(v) + if err != nil { + panic(fmt.Sprintf("could not parse environment variable %s with value %q: %v", key, v, err)) + } + return args } // CFlags returns the flags to use when invoking the C, C++ or Fortran compilers, or cgo. diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go index c5f3fc264f..1fc825de47 100644 --- a/src/cmd/go/internal/work/gc.go +++ b/src/cmd/go/internal/work/gc.go @@ -536,33 +536,18 @@ func packInternal(afile string, ofiles []string) error { } // setextld sets the appropriate linker flags for the specified compiler. -func setextld(ldflags []string, compiler []string) []string { +func setextld(ldflags []string, compiler []string) ([]string, error) { for _, f := range ldflags { if f == "-extld" || strings.HasPrefix(f, "-extld=") { // don't override -extld if supplied - return ldflags + return ldflags, nil } } - ldflags = append(ldflags, "-extld="+compiler[0]) - if len(compiler) > 1 { - extldflags := false - add := strings.Join(compiler[1:], " ") - for i, f := range ldflags { - if f == "-extldflags" && i+1 < len(ldflags) { - ldflags[i+1] = add + " " + ldflags[i+1] - extldflags = true - break - } else if strings.HasPrefix(f, "-extldflags=") { - ldflags[i] = "-extldflags=" + add + " " + ldflags[i][len("-extldflags="):] - extldflags = true - break - } - } - if !extldflags { - ldflags = append(ldflags, "-extldflags="+add) - } + joined, err := str.JoinAndQuoteFields(compiler) + if err != nil { + return nil, err } - return ldflags + return append(ldflags, "-extld="+joined), nil } // pluginPath computes the package path for a plugin main package. @@ -649,7 +634,10 @@ func (gcToolchain) ld(b *Builder, root *Action, out, importcfg, mainpkg string) } ldflags = append(ldflags, forcedLdflags...) ldflags = append(ldflags, root.Package.Internal.Ldflags...) - ldflags = setextld(ldflags, compiler) + ldflags, err := setextld(ldflags, compiler) + if err != nil { + return err + } // On OS X when using external linking to build a shared library, // the argument passed here to -o ends up recorded in the final @@ -693,7 +681,10 @@ func (gcToolchain) ldShared(b *Builder, root *Action, toplevelactions []*Action, } else { compiler = envList("CC", cfg.DefaultCC(cfg.Goos, cfg.Goarch)) } - ldflags = setextld(ldflags, compiler) + ldflags, err := setextld(ldflags, compiler) + if err != nil { + return err + } for _, d := range toplevelactions { if !strings.HasSuffix(d.Target, ".a") { // omit unsafe etc and actions for other shared libraries continue diff --git a/src/cmd/go/internal/work/init.go b/src/cmd/go/internal/work/init.go index 37a3e2d0ff..022137390f 100644 --- a/src/cmd/go/internal/work/init.go +++ b/src/cmd/go/internal/work/init.go @@ -11,6 +11,7 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/fsys" "cmd/go/internal/modload" + "cmd/internal/str" "cmd/internal/sys" "flag" "fmt" @@ -39,9 +40,18 @@ func BuildInit() { cfg.BuildPkgdir = p } - // Make sure CC and CXX are absolute paths - for _, key := range []string{"CC", "CXX"} { - if path := cfg.Getenv(key); !filepath.IsAbs(path) && path != "" && path != filepath.Base(path) { + // Make sure CC, CXX, and FC are absolute paths. + for _, key := range []string{"CC", "CXX", "FC"} { + value := cfg.Getenv(key) + args, err := str.SplitQuotedFields(value) + if err != nil { + base.Fatalf("go %s: %s environment variable could not be parsed: %v", flag.Args()[0], key, err) + } + if len(args) == 0 { + continue + } + path := args[0] + if !filepath.IsAbs(path) && path != filepath.Base(path) { base.Fatalf("go %s: %s environment variable is relative; must be absolute path: %s\n", flag.Args()[0], key, path) } } diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go index 9ca297e89b..8a7c77a46f 100644 --- a/src/cmd/go/script_test.go +++ b/src/cmd/go/script_test.go @@ -184,6 +184,7 @@ func (ts *testScript) setup() { "devnull=" + os.DevNull, "goversion=" + goVersion(ts), ":=" + string(os.PathListSeparator), + "/=" + string(os.PathSeparator), } if !testenv.HasExternalNetwork() { ts.env = append(ts.env, "TESTGONETWORK=panic", "TESTGOVCS=panic") diff --git a/src/cmd/go/testdata/script/cgo_path_space_quote.txt b/src/cmd/go/testdata/script/cgo_path_space_quote.txt new file mode 100644 index 0000000000..3b89bfb800 --- /dev/null +++ b/src/cmd/go/testdata/script/cgo_path_space_quote.txt @@ -0,0 +1,56 @@ +# This test checks that the CC environment variable may contain quotes and +# spaces. Arguments are normally split on spaces, tabs, newlines. If an +# argument contains these characters, the entire argument may be quoted +# with single or double quotes. This is the same as -gcflags and similar +# options. + +[short] skip +[!exec:clang] [!exec:gcc] skip + +env GOENV=$WORK/go.env +mkdir 'program files' +go build -o 'program files' './which cc/which cc.go' +[exec:clang] env CC='"'$PWD${/}program' 'files${/}which' 'cc"' 'clang +[!exec:clang] env CC='"'$PWD${/}program' 'files${/}which' 'cc"' 'gcc +go env CC +stdout 'program files[/\\]which cc" (clang|gcc)$' +go env -w CC=$CC +env CC= +go env CC +stdout 'program files[/\\]which cc" (clang|gcc)$' + +go run . + +-- go.mod -- +module test + +go 1.17 +-- which cc/which cc.go -- +package main + +import ( + "fmt" + "os" + "os/exec" +) + +func main() { + args := append([]string{"-DWRAPPER_WAS_USED=1"}, os.Args[2:]...) + cmd := exec.Command(os.Args[1], args...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} +-- hello.go -- +package main + +// int x = WRAPPER_WAS_USED; +import "C" +import "fmt" + +func main() { + fmt.Println(C.x) +} diff --git a/src/cmd/internal/dwarf/dwarf.go b/src/cmd/internal/dwarf/dwarf.go index ec441c2bcb..54c4c4d56d 100644 --- a/src/cmd/internal/dwarf/dwarf.go +++ b/src/cmd/internal/dwarf/dwarf.go @@ -1620,8 +1620,10 @@ func (s byChildIndex) Swap(i, j int) { s[i], s[j] = s[j], s[i] } // current extld. // AIX ld doesn't support DWARF with -bnoobjreorder with version // prior to 7.2.2. -func IsDWARFEnabledOnAIXLd(extld string) (bool, error) { - out, err := exec.Command(extld, "-Wl,-V").CombinedOutput() +func IsDWARFEnabledOnAIXLd(extld []string) (bool, error) { + name, args := extld[0], extld[1:] + args = append(args, "-Wl,-V") + out, err := exec.Command(name, args...).CombinedOutput() if err != nil { // The normal output should display ld version and // then fails because ".main" is not defined: diff --git a/src/cmd/link/dwarf_test.go b/src/cmd/link/dwarf_test.go index 3ca59bd47f..f7bbb014d9 100644 --- a/src/cmd/link/dwarf_test.go +++ b/src/cmd/link/dwarf_test.go @@ -8,6 +8,7 @@ import ( "bytes" cmddwarf "cmd/internal/dwarf" "cmd/internal/objfile" + "cmd/internal/str" "debug/dwarf" "internal/testenv" "os" @@ -67,8 +68,11 @@ func testDWARF(t *testing.T, buildmode string, expectDWARF bool, env ...string) if extld == "" { extld = "gcc" } - var err error - expectDWARF, err = cmddwarf.IsDWARFEnabledOnAIXLd(extld) + extldArgs, err := str.SplitQuotedFields(extld) + if err != nil { + t.Fatal(err) + } + expectDWARF, err = cmddwarf.IsDWARFEnabledOnAIXLd(extldArgs) if err != nil { t.Fatal(err) } diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 644faeb2fb..4cfee4a1e7 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -464,23 +464,24 @@ func loadinternal(ctxt *Link, name string) *sym.Library { } // extld returns the current external linker. -func (ctxt *Link) extld() string { - if *flagExtld == "" { - *flagExtld = "gcc" +func (ctxt *Link) extld() []string { + if len(flagExtld) == 0 { + flagExtld = []string{"gcc"} } - return *flagExtld + return flagExtld } // findLibPathCmd uses cmd command to find gcc library libname. // It returns library full path if found, or "none" if not found. func (ctxt *Link) findLibPathCmd(cmd, libname string) string { extld := ctxt.extld() - args := hostlinkArchArgs(ctxt.Arch) + name, args := extld[0], extld[1:] + args = append(args, hostlinkArchArgs(ctxt.Arch)...) args = append(args, cmd) if ctxt.Debugvlog != 0 { ctxt.Logf("%s %v\n", extld, args) } - out, err := exec.Command(extld, args...).Output() + out, err := exec.Command(name, args...).Output() if err != nil { if ctxt.Debugvlog != 0 { ctxt.Logf("not using a %s file because compiler failed\n%v\n%s\n", libname, err, out) @@ -1240,7 +1241,7 @@ func (ctxt *Link) hostlink() { } var argv []string - argv = append(argv, ctxt.extld()) + argv = append(argv, ctxt.extld()...) argv = append(argv, hostlinkArchArgs(ctxt.Arch)...) if *FlagS || debug_s { @@ -1401,7 +1402,9 @@ func (ctxt *Link) hostlink() { // If gold is not installed, gcc will silently switch // back to ld.bfd. So we parse the version information // and provide a useful error if gold is missing. - cmd := exec.Command(*flagExtld, "-fuse-ld=gold", "-Wl,--version") + name, args := flagExtld[0], flagExtld[1:] + args = append(args, "-fuse-ld=gold", "-Wl,--version") + cmd := exec.Command(name, args...) if out, err := cmd.CombinedOutput(); err == nil { if !bytes.Contains(out, []byte("GNU gold")) { log.Fatalf("ARM external linker must be gold (issue #15696), but is not: %s", out) @@ -1414,7 +1417,9 @@ func (ctxt *Link) hostlink() { altLinker = "bfd" // Provide a useful error if ld.bfd is missing. - cmd := exec.Command(*flagExtld, "-fuse-ld=bfd", "-Wl,--version") + name, args := flagExtld[0], flagExtld[1:] + args = append(args, "-fuse-ld=bfd", "-Wl,--version") + cmd := exec.Command(name, args...) if out, err := cmd.CombinedOutput(); err == nil { if !bytes.Contains(out, []byte("GNU ld")) { log.Fatalf("ARM64 external linker must be ld.bfd (issue #35197), please install devel/binutils") @@ -1482,10 +1487,11 @@ func (ctxt *Link) hostlink() { argv = append(argv, "/lib/crt0_64.o") extld := ctxt.extld() + name, args := extld[0], extld[1:] // Get starting files. getPathFile := func(file string) string { - args := []string{"-maix64", "--print-file-name=" + file} - out, err := exec.Command(extld, args...).CombinedOutput() + args := append(args, "-maix64", "--print-file-name="+file) + out, err := exec.Command(name, args...).CombinedOutput() if err != nil { log.Fatalf("running %s failed: %v\n%s", extld, err, out) } @@ -1567,14 +1573,18 @@ func (ctxt *Link) hostlink() { } } - for _, p := range strings.Fields(*flagExtldflags) { + for _, p := range flagExtldflags { argv = append(argv, p) checkStatic(p) } if ctxt.HeadType == objabi.Hwindows { // Determine which linker we're using. Add in the extldflags in // case used has specified "-fuse-ld=...". - cmd := exec.Command(*flagExtld, *flagExtldflags, "-Wl,--version") + extld := ctxt.extld() + name, args := extld[0], extld[1:] + args = append(args, flagExtldflags...) + args = append(args, "-Wl,--version") + cmd := exec.Command(name, args...) usingLLD := false if out, err := cmd.CombinedOutput(); err == nil { if bytes.Contains(out, []byte("LLD ")) { @@ -1718,8 +1728,7 @@ func linkerFlagSupported(arch *sys.Arch, linker, altLinker, flag string) bool { flags := hostlinkArchArgs(arch) keep := false skip := false - extldflags := strings.Fields(*flagExtldflags) - for _, f := range append(extldflags, ldflag...) { + for _, f := range append(flagExtldflags, ldflag...) { if keep { flags = append(flags, f) keep = false diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go index cba0e3d81f..33b03b5024 100644 --- a/src/cmd/link/internal/ld/main.go +++ b/src/cmd/link/internal/ld/main.go @@ -34,6 +34,7 @@ import ( "bufio" "cmd/internal/goobj" "cmd/internal/objabi" + "cmd/internal/str" "cmd/internal/sys" "cmd/link/internal/benchmark" "flag" @@ -53,6 +54,8 @@ var ( func init() { flag.Var(&rpath, "r", "set the ELF dynamic linker search `path` to dir1:dir2:...") + flag.Var(&flagExtld, "extld", "use `linker` when linking in external mode") + flag.Var(&flagExtldflags, "extldflags", "pass `flags` to external linker") } // Flags used by the linker. The exported flags are used by the architecture-specific packages. @@ -72,8 +75,8 @@ var ( flagLibGCC = flag.String("libgcc", "", "compiler support lib for internal linking; use \"none\" to disable") flagTmpdir = flag.String("tmpdir", "", "use `directory` for temporary files") - flagExtld = flag.String("extld", "", "use `linker` when linking in external mode") - flagExtldflags = flag.String("extldflags", "", "pass `flags` to external linker") + flagExtld str.QuotedStringListFlag + flagExtldflags str.QuotedStringListFlag flagExtar = flag.String("extar", "", "archive program for buildmode=c-archive") flagA = flag.Bool("a", false, "no-op (deprecated)") -- GitLab From ea94e5d3c57fadea088cdc5002e014b3c7ef4bc1 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 23 Jul 2021 15:03:00 -0400 Subject: [PATCH 0572/2500] [dev.typeparams] runtime: use func() for deferred functions Prior to regabi, a deferred function could have any signature, so the runtime always manipulated them as funcvals. Now, a deferred function is always func(). Hence, this CL makes the runtime's manipulation of deferred functions more type-safe by using func() directly instead of *funcval. Change-Id: Ib55f38ed49107f74149725c65044e4690761971d Reviewed-on: https://go-review.googlesource.com/c/go/+/337650 Trust: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/asm_amd64.s | 2 +- src/runtime/asm_riscv64.s | 2 +- src/runtime/heapdump.go | 5 +++-- src/runtime/panic.go | 28 +++++++++------------------- src/runtime/runtime2.go | 8 ++++---- src/runtime/stubs.go | 2 +- 6 files changed, 19 insertions(+), 28 deletions(-) diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index 50ffa30ac5..0f719b2664 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -662,7 +662,7 @@ TEXT ·publicationBarrier(SB),NOSPLIT,$0-0 // compile barrier. RET -// func jmpdefer(fv *funcval, argp uintptr) +// func jmpdefer(fv func(), argp uintptr) // argp is a caller SP. // called from deferreturn. // 1. pop the caller diff --git a/src/runtime/asm_riscv64.s b/src/runtime/asm_riscv64.s index 69ab88f1d2..9957ae201b 100644 --- a/src/runtime/asm_riscv64.s +++ b/src/runtime/asm_riscv64.s @@ -248,7 +248,7 @@ TEXT gogo<>(SB), NOSPLIT|NOFRAME, $0 MOV gobuf_pc(T0), T0 JALR ZERO, T0 -// func jmpdefer(fv *funcval, argp uintptr) +// func jmpdefer(fv func(), argp uintptr) // called from deferreturn // 1. grab stored return address from the caller's frame // 2. sub 8 bytes to get back to JAL deferreturn diff --git a/src/runtime/heapdump.go b/src/runtime/heapdump.go index 18e4666fa4..8fb30d95b9 100644 --- a/src/runtime/heapdump.go +++ b/src/runtime/heapdump.go @@ -381,12 +381,13 @@ func dumpgoroutine(gp *g) { dumpint(uint64(uintptr(unsafe.Pointer(gp)))) dumpint(uint64(d.sp)) dumpint(uint64(d.pc)) - dumpint(uint64(uintptr(unsafe.Pointer(d.fn)))) + fn := *(**funcval)(unsafe.Pointer(&d.fn)) + dumpint(uint64(uintptr(unsafe.Pointer(fn)))) if d.fn == nil { // d.fn can be nil for open-coded defers dumpint(uint64(0)) } else { - dumpint(uint64(uintptr(unsafe.Pointer(d.fn.fn)))) + dumpint(uint64(uintptr(unsafe.Pointer(fn.fn)))) } dumpint(uint64(uintptr(unsafe.Pointer(d.link)))) } diff --git a/src/runtime/panic.go b/src/runtime/panic.go index 85d39b9250..35f3b44a4d 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -227,7 +227,7 @@ func panicmemAddr(addr uintptr) { // Create a new deferred function fn, which has no arguments and results. // The compiler turns a defer statement into a call to this. -func deferproc(fn *funcval) { // TODO: Make deferproc just take a func(). +func deferproc(fn func()) { gp := getg() if gp.m.curg != gp { // go code on the system stack can't defer @@ -303,16 +303,6 @@ func deferprocStack(d *_defer) { // been set and must not be clobbered. } -// deferFunc returns d's deferred function. This is temporary while we -// support both modes of GOEXPERIMENT=regabidefer. Once we commit to -// that experiment, we should change the type of d.fn. -//go:nosplit -func deferFunc(d *_defer) func() { - var fn func() - *(**funcval)(unsafe.Pointer(&fn)) = d.fn - return fn -} - // Each P holds a pool for defers. // Allocate a Defer, usually using per-P pool. @@ -470,9 +460,8 @@ func deferreturn() { // If the defer function pointer is nil, force the seg fault to happen // here rather than in jmpdefer. gentraceback() throws an error if it is // called with a callback on an LR architecture and jmpdefer is on the - // stack, because the stack trace can be incorrect in that case - see - // issue #8153). - _ = fn.fn + // stack, because jmpdefer manipulates SP (see issue #8153). + _ = **(**funcval)(unsafe.Pointer(&fn)) jmpdefer(fn, argp) } @@ -536,7 +525,7 @@ func Goexit() { } else { // Save the pc/sp in deferCallSave(), so we can "recover" back to this // loop if necessary. - deferCallSave(&p, deferFunc(d)) + deferCallSave(&p, d.fn) } if p.aborted { // We had a recursive panic in the defer d we started, and @@ -728,12 +717,14 @@ func runOpenDeferFrame(gp *g, d *_defer) bool { if deferBits&(1< Date: Mon, 26 Jul 2021 12:04:36 -0400 Subject: [PATCH 0573/2500] [dev.typeparams] runtime: remove unnecessary split-prevention from defer code Prior to regabi, the compiler passed defer arguments to the runtime as untyped values on the stack. This meant a lot of defer-related runtime functions had to be very careful not to grow the stack or allow preemption since the stack could not be safely scanned or moved. However, with regabi, every defer is now simply a func() from the runtime's perspective, which means we no longer have untyped values on the stack when we enter defer-related runtime code. Hence, this CL removes a lot of the now-unnecessary carefulness in the defer implementation. Specifically, deferreturn no longer needs to be nosplit because it doesn't copy untyped defer arguments to its caller's frame (we also update some stale comments in deferreturn). freedefer no longer needs to be nosplit because it's none of its callers are deeply nosplit. And newdefer and freedefer no longer need to switch to the systemstack on their slow paths to avoid stack growth. deferprocStack is the only function that still needs to be nosplit, but that's because the compiler calls it with uninitialized live pointer slots on the stack (maybe we should change that, but that's a very different fix). Change-Id: I1156ec90bff2613fe4b48b84b375943349ce637d Reviewed-on: https://go-review.googlesource.com/c/go/+/337651 Trust: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/panic.go | 84 +++++++++++++++----------------------------- 1 file changed, 29 insertions(+), 55 deletions(-) diff --git a/src/runtime/panic.go b/src/runtime/panic.go index 35f3b44a4d..e66fe27be0 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -261,10 +261,8 @@ func deferproc(fn func()) { // deferprocStack queues a new deferred function with a defer record on the stack. // The defer record must have its fn field initialized. // All other fields can contain junk. -// The defer record must be immediately followed in memory by -// the arguments of the defer. -// Nosplit because the arguments on the stack won't be scanned -// until the defer record is spliced into the gp._defer list. +// Nosplit because of the uninitialized pointer fields on the stack. +// //go:nosplit func deferprocStack(d *_defer) { gp := getg() @@ -313,18 +311,14 @@ func newdefer() *_defer { gp := getg() pp := gp.m.p.ptr() if len(pp.deferpool) == 0 && sched.deferpool != nil { - // Take the slow path on the system stack so - // we don't grow newdefer's stack. - systemstack(func() { - lock(&sched.deferlock) - for len(pp.deferpool) < cap(pp.deferpool)/2 && sched.deferpool != nil { - d := sched.deferpool - sched.deferpool = d.link - d.link = nil - pp.deferpool = append(pp.deferpool, d) - } - unlock(&sched.deferlock) - }) + lock(&sched.deferlock) + for len(pp.deferpool) < cap(pp.deferpool)/2 && sched.deferpool != nil { + d := sched.deferpool + sched.deferpool = d.link + d.link = nil + pp.deferpool = append(pp.deferpool, d) + } + unlock(&sched.deferlock) } if n := len(pp.deferpool); n > 0 { d = pp.deferpool[n-1] @@ -341,11 +335,6 @@ func newdefer() *_defer { // Free the given defer. // The defer cannot be used after this call. -// -// This must not grow the stack because there may be a frame without a -// stack map when this is called. -// -//go:nosplit func freedefer(d *_defer) { if d._panic != nil { freedeferpanic() @@ -359,28 +348,23 @@ func freedefer(d *_defer) { pp := getg().m.p.ptr() if len(pp.deferpool) == cap(pp.deferpool) { // Transfer half of local cache to the central cache. - // - // Take this slow path on the system stack so - // we don't grow freedefer's stack. - systemstack(func() { - var first, last *_defer - for len(pp.deferpool) > cap(pp.deferpool)/2 { - n := len(pp.deferpool) - d := pp.deferpool[n-1] - pp.deferpool[n-1] = nil - pp.deferpool = pp.deferpool[:n-1] - if first == nil { - first = d - } else { - last.link = d - } - last = d + var first, last *_defer + for len(pp.deferpool) > cap(pp.deferpool)/2 { + n := len(pp.deferpool) + d := pp.deferpool[n-1] + pp.deferpool[n-1] = nil + pp.deferpool = pp.deferpool[:n-1] + if first == nil { + first = d + } else { + last.link = d } - lock(&sched.deferlock) - last.link = sched.deferpool - sched.deferpool = first - unlock(&sched.deferlock) - }) + last = d + } + lock(&sched.deferlock) + last.link = sched.deferpool + sched.deferpool = first + unlock(&sched.deferlock) } // These lines used to be simply `*d = _defer{}` but that @@ -420,12 +404,6 @@ func freedeferfn() { // to have been called by the caller of deferreturn at the point // just before deferreturn was called. The effect is that deferreturn // is called again and again until there are no more deferred functions. -// -// Declared as nosplit, because the function should not be preempted once we start -// modifying the caller's frame in order to reuse the frame to call the deferred -// function. -// -//go:nosplit func deferreturn() { gp := getg() d := gp._defer @@ -446,13 +424,6 @@ func deferreturn() { return } - // Moving arguments around. - // - // Everything called after this point must be recursively - // nosplit because the garbage collector won't know the form - // of the arguments until the jmpdefer can flip the PC over to - // fn. - argp := getcallersp() + sys.MinFrameSize fn := d.fn d.fn = nil gp._defer = d.link @@ -462,6 +433,9 @@ func deferreturn() { // called with a callback on an LR architecture and jmpdefer is on the // stack, because jmpdefer manipulates SP (see issue #8153). _ = **(**funcval)(unsafe.Pointer(&fn)) + // We must not split the stack between computing argp and + // calling jmpdefer because argp is a uintptr stack pointer. + argp := getcallersp() + sys.MinFrameSize jmpdefer(fn, argp) } -- GitLab From fd0011dca5b35ec07ff53df4c3231a2a119796a9 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 26 Jul 2021 15:44:22 -0400 Subject: [PATCH 0574/2500] [dev.typeparams] runtime,cmd/compile,cmd/link: replace jmpdefer with a loop Currently, deferreturn runs deferred functions by backing up its return PC to the deferreturn call, and then effectively tail-calling the deferred function (via jmpdefer). The effect of this is that the deferred function appears to be called directly from the deferee, and when it returns, the deferee calls deferreturn again so it can run the next deferred function if necessary. This unusual flow control leads to a large number of special cases and complications all over the tool chain. This used to be necessary because deferreturn copied the deferred function's argument frame directly into its caller's frame and then had to invoke that call as if it had been called from its caller's frame so it could access it arguments. But now that we've simplified defer processing so the runtime only deals with argument-less closures, this approach is no longer necessary. This CL simplifies all of this by making deferreturn simply call deferred functions in a loop. This eliminates the need for jmpdefer, so we can delete a bunch of per-architecture assembly code. This eliminates several special cases on Wasm, since it couldn't support these calling shenanigans directly and thus had to simulate the loop a different way. Now Wasm can largely work the way the other platforms do. This eliminates the per-architecture Ginsnopdefer operation. On PPC64, this was necessary to reload the TOC pointer after the tail call (since TOC pointers in general make tail calls impossible). The tail call is gone, and in the case where we do force a jump to the deferreturn call when recovering from an open-coded defer, we go through gogo (via runtime.recovery), which handles the TOC. On other platforms, we needed a NOP so traceback didn't get confused by seeing the return to the CALL instruction, rather than the usual return to the instruction following the CALL instruction. Now we don't inject a return to the CALL instruction at all, so this NOP is also unnecessary. The one potential effect of this is that deferreturn could now appear in stack traces from deferred functions. However, this could already happen from open-coded defers, so we've long since marked deferreturn as a "wrapper" so it gets elided not only from printed stack traces, but from runtime.Callers*. Change-Id: Ie9f700cd3fb774f498c9edce363772a868407bf7 Reviewed-on: https://go-review.googlesource.com/c/go/+/337652 Trust: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/compile/internal/amd64/galign.go | 1 - src/cmd/compile/internal/arm/galign.go | 1 - src/cmd/compile/internal/arm64/galign.go | 1 - src/cmd/compile/internal/mips/galign.go | 1 - src/cmd/compile/internal/mips64/galign.go | 1 - src/cmd/compile/internal/ppc64/galign.go | 1 - src/cmd/compile/internal/ppc64/ggen.go | 27 ---------- src/cmd/compile/internal/riscv64/galign.go | 1 - src/cmd/compile/internal/s390x/galign.go | 1 - src/cmd/compile/internal/ssagen/arch.go | 3 +- src/cmd/compile/internal/ssagen/ssa.go | 12 ----- src/cmd/compile/internal/wasm/ssa.go | 7 ++- src/cmd/compile/internal/x86/galign.go | 1 - src/cmd/internal/obj/arm/asm5.go | 11 ++-- src/cmd/internal/obj/wasm/wasmobj.go | 36 -------------- src/cmd/internal/obj/x86/asm6.go | 1 - src/cmd/internal/objabi/funcid.go | 2 - src/cmd/link/internal/ld/pcln.go | 9 ++-- src/runtime/asm_386.s | 20 -------- src/runtime/asm_amd64.s | 15 ------ src/runtime/asm_arm.s | 14 ------ src/runtime/asm_arm64.s | 17 ------- src/runtime/asm_mips64x.s | 16 ------ src/runtime/asm_mipsx.s | 16 ------ src/runtime/asm_ppc64x.s | 28 ----------- src/runtime/asm_riscv64.s | 15 ------ src/runtime/asm_s390x.s | 15 ------ src/runtime/asm_wasm.s | 29 ----------- src/runtime/panic.go | 58 ++++++++++------------ src/runtime/stubs.go | 2 - src/runtime/symtab.go | 1 - 31 files changed, 39 insertions(+), 324 deletions(-) diff --git a/src/cmd/compile/internal/amd64/galign.go b/src/cmd/compile/internal/amd64/galign.go index 3b13e123a7..ca44263afc 100644 --- a/src/cmd/compile/internal/amd64/galign.go +++ b/src/cmd/compile/internal/amd64/galign.go @@ -18,7 +18,6 @@ func Init(arch *ssagen.ArchInfo) { arch.ZeroRange = zerorange arch.Ginsnop = ginsnop - arch.Ginsnopdefer = ginsnop arch.SSAMarkMoves = ssaMarkMoves arch.SSAGenValue = ssaGenValue diff --git a/src/cmd/compile/internal/arm/galign.go b/src/cmd/compile/internal/arm/galign.go index d68500280d..23e52bacbf 100644 --- a/src/cmd/compile/internal/arm/galign.go +++ b/src/cmd/compile/internal/arm/galign.go @@ -18,7 +18,6 @@ func Init(arch *ssagen.ArchInfo) { arch.SoftFloat = buildcfg.GOARM == 5 arch.ZeroRange = zerorange arch.Ginsnop = ginsnop - arch.Ginsnopdefer = ginsnop arch.SSAMarkMoves = func(s *ssagen.State, b *ssa.Block) {} arch.SSAGenValue = ssaGenValue diff --git a/src/cmd/compile/internal/arm64/galign.go b/src/cmd/compile/internal/arm64/galign.go index 2a61b9dd99..3ebd860de8 100644 --- a/src/cmd/compile/internal/arm64/galign.go +++ b/src/cmd/compile/internal/arm64/galign.go @@ -18,7 +18,6 @@ func Init(arch *ssagen.ArchInfo) { arch.PadFrame = padframe arch.ZeroRange = zerorange arch.Ginsnop = ginsnop - arch.Ginsnopdefer = ginsnop arch.SSAMarkMoves = func(s *ssagen.State, b *ssa.Block) {} arch.SSAGenValue = ssaGenValue diff --git a/src/cmd/compile/internal/mips/galign.go b/src/cmd/compile/internal/mips/galign.go index f892923ba0..4e6897042e 100644 --- a/src/cmd/compile/internal/mips/galign.go +++ b/src/cmd/compile/internal/mips/galign.go @@ -21,7 +21,6 @@ func Init(arch *ssagen.ArchInfo) { arch.SoftFloat = (buildcfg.GOMIPS == "softfloat") arch.ZeroRange = zerorange arch.Ginsnop = ginsnop - arch.Ginsnopdefer = ginsnop arch.SSAMarkMoves = func(s *ssagen.State, b *ssa.Block) {} arch.SSAGenValue = ssaGenValue arch.SSAGenBlock = ssaGenBlock diff --git a/src/cmd/compile/internal/mips64/galign.go b/src/cmd/compile/internal/mips64/galign.go index af81366e51..412bc71aab 100644 --- a/src/cmd/compile/internal/mips64/galign.go +++ b/src/cmd/compile/internal/mips64/galign.go @@ -21,7 +21,6 @@ func Init(arch *ssagen.ArchInfo) { arch.SoftFloat = buildcfg.GOMIPS64 == "softfloat" arch.ZeroRange = zerorange arch.Ginsnop = ginsnop - arch.Ginsnopdefer = ginsnop arch.SSAMarkMoves = func(s *ssagen.State, b *ssa.Block) {} arch.SSAGenValue = ssaGenValue diff --git a/src/cmd/compile/internal/ppc64/galign.go b/src/cmd/compile/internal/ppc64/galign.go index 590290fa37..bff3e38f42 100644 --- a/src/cmd/compile/internal/ppc64/galign.go +++ b/src/cmd/compile/internal/ppc64/galign.go @@ -20,7 +20,6 @@ func Init(arch *ssagen.ArchInfo) { arch.ZeroRange = zerorange arch.Ginsnop = ginsnop - arch.Ginsnopdefer = ginsnopdefer arch.SSAMarkMoves = ssaMarkMoves arch.SSAGenValue = ssaGenValue diff --git a/src/cmd/compile/internal/ppc64/ggen.go b/src/cmd/compile/internal/ppc64/ggen.go index c76962cfb8..3ae6422bf9 100644 --- a/src/cmd/compile/internal/ppc64/ggen.go +++ b/src/cmd/compile/internal/ppc64/ggen.go @@ -53,30 +53,3 @@ func ginsnop(pp *objw.Progs) *obj.Prog { p.To.Reg = ppc64.REG_R0 return p } - -func ginsnopdefer(pp *objw.Progs) *obj.Prog { - // On PPC64 two nops are required in the defer case. - // - // (see gc/cgen.go, gc/plive.go -- copy of comment below) - // - // On ppc64, when compiling Go into position - // independent code on ppc64le we insert an - // instruction to reload the TOC pointer from the - // stack as well. See the long comment near - // jmpdefer in runtime/asm_ppc64.s for why. - // If the MOVD is not needed, insert a hardware NOP - // so that the same number of instructions are used - // on ppc64 in both shared and non-shared modes. - - ginsnop(pp) - if base.Ctxt.Flag_shared { - p := pp.Prog(ppc64.AMOVD) - p.From.Type = obj.TYPE_MEM - p.From.Offset = 24 - p.From.Reg = ppc64.REGSP - p.To.Type = obj.TYPE_REG - p.To.Reg = ppc64.REG_R2 - return p - } - return ginsnop(pp) -} diff --git a/src/cmd/compile/internal/riscv64/galign.go b/src/cmd/compile/internal/riscv64/galign.go index 338248a7cf..846ed8fb38 100644 --- a/src/cmd/compile/internal/riscv64/galign.go +++ b/src/cmd/compile/internal/riscv64/galign.go @@ -16,7 +16,6 @@ func Init(arch *ssagen.ArchInfo) { arch.MAXWIDTH = 1 << 50 arch.Ginsnop = ginsnop - arch.Ginsnopdefer = ginsnop arch.ZeroRange = zeroRange arch.SSAMarkMoves = ssaMarkMoves diff --git a/src/cmd/compile/internal/s390x/galign.go b/src/cmd/compile/internal/s390x/galign.go index b004a2db0a..d880834c22 100644 --- a/src/cmd/compile/internal/s390x/galign.go +++ b/src/cmd/compile/internal/s390x/galign.go @@ -16,7 +16,6 @@ func Init(arch *ssagen.ArchInfo) { arch.ZeroRange = zerorange arch.Ginsnop = ginsnop - arch.Ginsnopdefer = ginsnop arch.SSAMarkMoves = ssaMarkMoves arch.SSAGenValue = ssaGenValue diff --git a/src/cmd/compile/internal/ssagen/arch.go b/src/cmd/compile/internal/ssagen/arch.go index 957fb3e84a..483e45cad4 100644 --- a/src/cmd/compile/internal/ssagen/arch.go +++ b/src/cmd/compile/internal/ssagen/arch.go @@ -29,8 +29,7 @@ type ArchInfo struct { // at function entry, and it is ok to clobber registers. ZeroRange func(*objw.Progs, *obj.Prog, int64, int64, *uint32) *obj.Prog - Ginsnop func(*objw.Progs) *obj.Prog - Ginsnopdefer func(*objw.Progs) *obj.Prog // special ginsnop for deferreturn + Ginsnop func(*objw.Progs) *obj.Prog // SSAMarkMoves marks any MOVXconst ops that need to avoid clobbering flags. SSAMarkMoves func(*State, *ssa.Block) diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 7e2f6a7471..161469ea67 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -7335,18 +7335,6 @@ func (s *State) PrepareCall(v *ssa.Value) { call, ok := v.Aux.(*ssa.AuxCall) - if ok && call.Fn == ir.Syms.Deferreturn { - // Deferred calls will appear to be returning to - // the CALL deferreturn(SB) that we are about to emit. - // However, the stack trace code will show the line - // of the instruction byte before the return PC. - // To avoid that being an unrelated instruction, - // insert an actual hardware NOP that will have the right line number. - // This is different from obj.ANOP, which is a virtual no-op - // that doesn't make it into the instruction stream. - Arch.Ginsnopdefer(s.pp) - } - if ok { // Record call graph information for nowritebarrierrec // analysis. diff --git a/src/cmd/compile/internal/wasm/ssa.go b/src/cmd/compile/internal/wasm/ssa.go index 31b09016eb..0b2ca3fdbb 100644 --- a/src/cmd/compile/internal/wasm/ssa.go +++ b/src/cmd/compile/internal/wasm/ssa.go @@ -24,7 +24,6 @@ func Init(arch *ssagen.ArchInfo) { arch.ZeroRange = zeroRange arch.Ginsnop = ginsnop - arch.Ginsnopdefer = ginsnop arch.SSAMarkMoves = ssaMarkMoves arch.SSAGenValue = ssaGenValue @@ -126,7 +125,11 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { case ssa.OpWasmLoweredStaticCall, ssa.OpWasmLoweredClosureCall, ssa.OpWasmLoweredInterCall: s.PrepareCall(v) if call, ok := v.Aux.(*ssa.AuxCall); ok && call.Fn == ir.Syms.Deferreturn { - // add a resume point before call to deferreturn so it can be called again via jmpdefer + // The runtime needs to inject jumps to + // deferreturn calls using the address in + // _func.deferreturn. Hence, the call to + // deferreturn must itself be a resumption + // point so it gets a target PC. s.Prog(wasm.ARESUMEPOINT) } if v.Op == ssa.OpWasmLoweredClosureCall { diff --git a/src/cmd/compile/internal/x86/galign.go b/src/cmd/compile/internal/x86/galign.go index 00a20e429f..5565bd32c7 100644 --- a/src/cmd/compile/internal/x86/galign.go +++ b/src/cmd/compile/internal/x86/galign.go @@ -34,7 +34,6 @@ func Init(arch *ssagen.ArchInfo) { arch.ZeroRange = zerorange arch.Ginsnop = ginsnop - arch.Ginsnopdefer = ginsnop arch.SSAMarkMoves = ssaMarkMoves } diff --git a/src/cmd/internal/obj/arm/asm5.go b/src/cmd/internal/obj/arm/asm5.go index ccf5f9e7f8..7b1682776e 100644 --- a/src/cmd/internal/obj/arm/asm5.go +++ b/src/cmd/internal/obj/arm/asm5.go @@ -355,11 +355,10 @@ var oprange [ALAST & obj.AMask][]Optab var xcmp [C_GOK + 1][C_GOK + 1]bool var ( - deferreturn *obj.LSym - symdiv *obj.LSym - symdivu *obj.LSym - symmod *obj.LSym - symmodu *obj.LSym + symdiv *obj.LSym + symdivu *obj.LSym + symmod *obj.LSym + symmodu *obj.LSym ) // Note about encoding: Prog.scond holds the condition encoding, @@ -1219,8 +1218,6 @@ func buildop(ctxt *obj.Link) { return } - deferreturn = ctxt.LookupABI("runtime.deferreturn", obj.ABIInternal) - symdiv = ctxt.Lookup("runtime._div") symdivu = ctxt.Lookup("runtime._divu") symmod = ctxt.Lookup("runtime._mod") diff --git a/src/cmd/internal/obj/wasm/wasmobj.go b/src/cmd/internal/obj/wasm/wasmobj.go index ceeae7a257..4d276db678 100644 --- a/src/cmd/internal/obj/wasm/wasmobj.go +++ b/src/cmd/internal/obj/wasm/wasmobj.go @@ -129,8 +129,6 @@ var ( morestackNoCtxt *obj.LSym gcWriteBarrier *obj.LSym sigpanic *obj.LSym - deferreturn *obj.LSym - jmpdefer *obj.LSym ) const ( @@ -143,10 +141,6 @@ func instinit(ctxt *obj.Link) { morestackNoCtxt = ctxt.Lookup("runtime.morestack_noctxt") gcWriteBarrier = ctxt.LookupABI("runtime.gcWriteBarrier", obj.ABIInternal) sigpanic = ctxt.LookupABI("runtime.sigpanic", obj.ABIInternal) - deferreturn = ctxt.LookupABI("runtime.deferreturn", obj.ABIInternal) - // jmpdefer is defined in assembly as ABI0. The compiler will - // generate a direct ABI0 call from Go, so look for that. - jmpdefer = ctxt.LookupABI(`"".jmpdefer`, obj.ABI0) } func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { @@ -423,12 +417,6 @@ func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { pcAfterCall-- // sigpanic expects to be called without advancing the pc } - // jmpdefer manipulates the return address on the stack so deferreturn gets called repeatedly. - // Model this in WebAssembly with a loop. - if call.To.Sym == deferreturn { - p = appendp(p, ALoop) - } - // SP -= 8 p = appendp(p, AGet, regAddr(REG_SP)) p = appendp(p, AI32Const, constAddr(8)) @@ -479,15 +467,6 @@ func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { break } - // jmpdefer removes the frame of deferreturn from the Go stack. - // However, its WebAssembly function still returns normally, - // so we need to return from deferreturn without removing its - // stack frame (no RET), because the frame is already gone. - if call.To.Sym == jmpdefer { - p = appendp(p, AReturn) - break - } - // return value of call is on the top of the stack, indicating whether to unwind the WebAssembly stack if call.As == ACALLNORESUME && call.To.Sym != sigpanic { // sigpanic unwinds the stack, but it never resumes // trying to unwind WebAssembly stack but call has no resume point, terminate with error @@ -500,21 +479,6 @@ func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { unwindExitBranches = append(unwindExitBranches, p) } - // jump to before the call if jmpdefer has reset the return address to the call's PC - if call.To.Sym == deferreturn { - // get PC_B from -8(SP) - p = appendp(p, AGet, regAddr(REG_SP)) - p = appendp(p, AI32Const, constAddr(8)) - p = appendp(p, AI32Sub) - p = appendp(p, AI32Load16U, constAddr(0)) - p = appendp(p, ATee, regAddr(REG_PC_B)) - - p = appendp(p, AI32Const, constAddr(call.Pc)) - p = appendp(p, AI32Eq) - p = appendp(p, ABrIf, constAddr(0)) - p = appendp(p, AEnd) // end of Loop - } - case obj.ARET, ARETUNWIND: ret := *p p.As = obj.ANOP diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go index 17fa76727e..331a98dfef 100644 --- a/src/cmd/internal/obj/x86/asm6.go +++ b/src/cmd/internal/obj/x86/asm6.go @@ -43,7 +43,6 @@ import ( var ( plan9privates *obj.LSym - deferreturn *obj.LSym ) // Instruction layout. diff --git a/src/cmd/internal/objabi/funcid.go b/src/cmd/internal/objabi/funcid.go index d881cdd061..68f6a26a76 100644 --- a/src/cmd/internal/objabi/funcid.go +++ b/src/cmd/internal/objabi/funcid.go @@ -34,7 +34,6 @@ const ( FuncID_gogo FuncID_gopanic FuncID_handleAsyncEvent - FuncID_jmpdefer FuncID_mcall FuncID_morestack FuncID_mstart @@ -60,7 +59,6 @@ var funcIDs = map[string]FuncID{ "gogo": FuncID_gogo, "gopanic": FuncID_gopanic, "handleAsyncEvent": FuncID_handleAsyncEvent, - "jmpdefer": FuncID_jmpdefer, "main": FuncID_runtime_main, "mcall": FuncID_mcall, "morestack": FuncID_morestack, diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index 05fd302369..70e3e1284b 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -129,11 +129,10 @@ func computeDeferReturn(ctxt *Link, deferReturnSym, s loader.Sym) uint32 { for ri := 0; ri < relocs.Count(); ri++ { r := relocs.At(ri) if target.IsWasm() && r.Type() == objabi.R_ADDR { - // Wasm does not have a live variable set at the deferreturn - // call itself. Instead it has one identified by the - // resumption point immediately preceding the deferreturn. - // The wasm code has a R_ADDR relocation which is used to - // set the resumption point to PC_B. + // wasm/ssa.go generates an ARESUMEPOINT just + // before the deferreturn call. The "PC" of + // the deferreturn call is stored in the + // R_ADDR relocation on the ARESUMEPOINT. lastWasmAddr = uint32(r.Add()) } if r.Type().IsDirectCall() && (r.Sym() == deferReturnSym || ldr.IsDeferReturnTramp(r.Sym())) { diff --git a/src/runtime/asm_386.s b/src/runtime/asm_386.s index dd2ea458cc..11c60309f4 100644 --- a/src/runtime/asm_386.s +++ b/src/runtime/asm_386.s @@ -582,26 +582,6 @@ TEXT ·publicationBarrier(SB),NOSPLIT,$0-0 // compile barrier. RET -// void jmpdefer(fn, sp); -// called from deferreturn. -// 1. pop the caller -// 2. sub 5 bytes (the length of CALL & a 32 bit displacement) from the callers -// return (when building for shared libraries, subtract 16 bytes -- 5 bytes -// for CALL & displacement to call __x86.get_pc_thunk.cx, 6 bytes for the -// LEAL to load the offset into BX, and finally 5 for the call & displacement) -// 3. jmp to the argument -TEXT runtime·jmpdefer(SB), NOSPLIT, $0-8 - MOVL fv+0(FP), DX // fn - MOVL argp+4(FP), BX // caller sp - LEAL -4(BX), SP // caller sp after CALL -#ifdef GOBUILDMODE_shared - SUBL $16, (SP) // return to CALL again -#else - SUBL $5, (SP) // return to CALL again -#endif - MOVL 0(DX), BX - JMP BX // but first run the deferred function - // Save state of caller into g->sched, // but using fake PC from systemstack_switch. // Must only be called from functions with no locals ($0) diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index 0f719b2664..2d8f4c2412 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -662,21 +662,6 @@ TEXT ·publicationBarrier(SB),NOSPLIT,$0-0 // compile barrier. RET -// func jmpdefer(fv func(), argp uintptr) -// argp is a caller SP. -// called from deferreturn. -// 1. pop the caller -// 2. sub 5 bytes from the callers return -// 3. jmp to the argument -TEXT runtime·jmpdefer(SB), NOSPLIT, $0-16 - MOVQ fv+0(FP), DX // fn - MOVQ argp+8(FP), BX // caller sp - LEAQ -8(BX), SP // caller sp after CALL - MOVQ -8(SP), BP // restore BP as if deferreturn returned (harmless if framepointers not in use) - SUBQ $5, (SP) // return to CALL again - MOVQ 0(DX), BX - JMP BX // but first run the deferred function - // Save state of caller into g->sched, // but using fake PC from systemstack_switch. // Must only be called from functions with no locals ($0) diff --git a/src/runtime/asm_arm.s b/src/runtime/asm_arm.s index 5c2bc00fe8..a1164781d2 100644 --- a/src/runtime/asm_arm.s +++ b/src/runtime/asm_arm.s @@ -506,20 +506,6 @@ CALLFN(·call268435456, 268435456) CALLFN(·call536870912, 536870912) CALLFN(·call1073741824, 1073741824) -// void jmpdefer(fn, sp); -// called from deferreturn. -// 1. grab stored LR for caller -// 2. sub 4 bytes to get back to BL deferreturn -// 3. B to fn -TEXT runtime·jmpdefer(SB),NOSPLIT,$0-8 - MOVW 0(R13), LR - MOVW $-4(LR), LR // BL deferreturn - MOVW fv+0(FP), R7 - MOVW argp+4(FP), R13 - MOVW $-4(R13), R13 // SP is 4 below argp, due to saved LR - MOVW 0(R7), R1 - B (R1) - // Save state of caller into g->sched, // but using fake PC from systemstack_switch. // Must only be called from functions with no locals ($0) diff --git a/src/runtime/asm_arm64.s b/src/runtime/asm_arm64.s index e7c5fa3225..e51ce2f831 100644 --- a/src/runtime/asm_arm64.s +++ b/src/runtime/asm_arm64.s @@ -982,23 +982,6 @@ again: CBNZ R0, again RET -// void jmpdefer(fv, sp); -// called from deferreturn. -// 1. grab stored LR for caller -// 2. sub 4 bytes to get back to BL deferreturn -// 3. BR to fn -TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16 - MOVD 0(RSP), R0 - SUB $4, R0 - MOVD R0, LR - - MOVD fv+0(FP), R26 - MOVD argp+8(FP), R0 - MOVD R0, RSP - SUB $8, RSP - MOVD 0(R26), R3 - B (R3) - // Save state of caller into g->sched, // but using fake PC from systemstack_switch. // Must only be called from functions with no locals ($0) diff --git a/src/runtime/asm_mips64x.s b/src/runtime/asm_mips64x.s index f3ac453d99..b2e2384c36 100644 --- a/src/runtime/asm_mips64x.s +++ b/src/runtime/asm_mips64x.s @@ -384,22 +384,6 @@ CALLFN(·call1073741824, 1073741824) TEXT runtime·procyield(SB),NOSPLIT,$0-0 RET -// void jmpdefer(fv, sp); -// called from deferreturn. -// 1. grab stored LR for caller -// 2. sub 8 bytes to get back to JAL deferreturn -// 3. JMP to fn -TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16 - MOVV 0(R29), R31 - ADDV $-8, R31 - - MOVV fv+0(FP), REGCTXT - MOVV argp+8(FP), R29 - ADDV $-8, R29 - NOR R0, R0 // prevent scheduling - MOVV 0(REGCTXT), R4 - JMP (R4) - // Save state of caller into g->sched, // but using fake PC from systemstack_switch. // Must only be called from functions with no locals ($0) diff --git a/src/runtime/asm_mipsx.s b/src/runtime/asm_mipsx.s index 4dc165849e..87a1344e8f 100644 --- a/src/runtime/asm_mipsx.s +++ b/src/runtime/asm_mipsx.s @@ -382,22 +382,6 @@ CALLFN(·call1073741824, 1073741824) TEXT runtime·procyield(SB),NOSPLIT,$0-4 RET -// void jmpdefer(fv, sp); -// called from deferreturn. -// 1. grab stored LR for caller -// 2. sub 8 bytes to get back to JAL deferreturn -// 3. JMP to fn -TEXT runtime·jmpdefer(SB),NOSPLIT,$0-8 - MOVW 0(R29), R31 - ADDU $-8, R31 - - MOVW fv+0(FP), REGCTXT - MOVW argp+4(FP), R29 - ADDU $-4, R29 - NOR R0, R0 // prevent scheduling - MOVW 0(REGCTXT), R4 - JMP (R4) - // Save state of caller into g->sched, // but using fake PC from systemstack_switch. // Must only be called from functions with no locals ($0) diff --git a/src/runtime/asm_ppc64x.s b/src/runtime/asm_ppc64x.s index a789d041e4..5dc96c5947 100644 --- a/src/runtime/asm_ppc64x.s +++ b/src/runtime/asm_ppc64x.s @@ -503,34 +503,6 @@ again: OR R6, R6, R6 // Set PPR priority back to medium-low RET -// void jmpdefer(fv, sp); -// called from deferreturn. -// 1. grab stored LR for caller -// 2. sub 8 bytes to get back to either nop or toc reload before deferreturn -// 3. BR to fn -// When dynamically linking Go, it is not sufficient to rewind to the BL -// deferreturn -- we might be jumping between modules and so we need to reset -// the TOC pointer in r2. To do this, codegen inserts MOVD 24(R1), R2 *before* -// the BL deferreturn and jmpdefer rewinds to that. -TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16 - MOVD 0(R1), R31 - SUB $8, R31 - MOVD R31, LR - - MOVD fv+0(FP), R11 - MOVD argp+8(FP), R1 - SUB $FIXED_FRAME, R1 -#ifdef GOOS_aix - // AIX won't trigger a SIGSEGV if R11 = nil - // So it manually triggers it - CMP R0, R11 - BNE 2(PC) - MOVD R0, 0(R0) -#endif - MOVD 0(R11), R12 - MOVD R12, CTR - BR (CTR) - // Save state of caller into g->sched, // but using fake PC from systemstack_switch. // Must only be called from functions with no locals ($0) diff --git a/src/runtime/asm_riscv64.s b/src/runtime/asm_riscv64.s index 9957ae201b..9927a817f7 100644 --- a/src/runtime/asm_riscv64.s +++ b/src/runtime/asm_riscv64.s @@ -248,21 +248,6 @@ TEXT gogo<>(SB), NOSPLIT|NOFRAME, $0 MOV gobuf_pc(T0), T0 JALR ZERO, T0 -// func jmpdefer(fv func(), argp uintptr) -// called from deferreturn -// 1. grab stored return address from the caller's frame -// 2. sub 8 bytes to get back to JAL deferreturn -// 3. JMP to fn -TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16 - MOV 0(X2), RA - ADD $-8, RA - - MOV fv+0(FP), CTXT - MOV argp+8(FP), X2 - ADD $-8, X2 - MOV 0(CTXT), T0 - JALR ZERO, T0 - // func procyield(cycles uint32) TEXT runtime·procyield(SB),NOSPLIT,$0-0 RET diff --git a/src/runtime/asm_s390x.s b/src/runtime/asm_s390x.s index 534cb6112c..d4110d563f 100644 --- a/src/runtime/asm_s390x.s +++ b/src/runtime/asm_s390x.s @@ -480,21 +480,6 @@ TEXT callfnMVC<>(SB),NOSPLIT|NOFRAME,$0-0 TEXT runtime·procyield(SB),NOSPLIT,$0-0 RET -// void jmpdefer(fv, sp); -// called from deferreturn. -// 1. grab stored LR for caller -// 2. sub 6 bytes to get back to BL deferreturn (size of BRASL instruction) -// 3. BR to fn -TEXT runtime·jmpdefer(SB),NOSPLIT|NOFRAME,$0-16 - MOVD 0(R15), R1 - SUB $6, R1, LR - - MOVD fv+0(FP), R12 - MOVD argp+8(FP), R15 - SUB $8, R15 - MOVD 0(R12), R3 - BR (R3) - // Save state of caller into g->sched, // but using fake PC from systemstack_switch. // Must only be called from functions with no locals ($0) diff --git a/src/runtime/asm_wasm.s b/src/runtime/asm_wasm.s index 53c271aa70..d885da6e70 100644 --- a/src/runtime/asm_wasm.s +++ b/src/runtime/asm_wasm.s @@ -193,35 +193,6 @@ TEXT runtime·return0(SB), NOSPLIT, $0-0 MOVD $0, RET0 RET -TEXT runtime·jmpdefer(SB), NOSPLIT, $0-16 - MOVD fv+0(FP), CTXT - - Get CTXT - I64Eqz - If - CALLNORESUME runtime·sigpanic(SB) - End - - // caller sp after CALL - I64Load argp+8(FP) - I64Const $8 - I64Sub - I32WrapI64 - Set SP - - // decrease PC_B by 1 to CALL again - Get SP - I32Load16U (SP) - I32Const $1 - I32Sub - I32Store16 $0 - - // but first run the deferred function - Get CTXT - I32WrapI64 - I64Load $0 - JMP - TEXT runtime·asminit(SB), NOSPLIT, $0-0 // No per-thread init. RET diff --git a/src/runtime/panic.go b/src/runtime/panic.go index e66fe27be0..4b8bca6c56 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -396,47 +396,39 @@ func freedeferfn() { throw("freedefer with d.fn != nil") } -// Run a deferred function if there is one. +// deferreturn runs deferred functions for the caller's frame. // The compiler inserts a call to this at the end of any // function which calls defer. -// If there is a deferred function, this will call runtime·jmpdefer, -// which will jump to the deferred function such that it appears -// to have been called by the caller of deferreturn at the point -// just before deferreturn was called. The effect is that deferreturn -// is called again and again until there are no more deferred functions. func deferreturn() { gp := getg() - d := gp._defer - if d == nil { - return - } - sp := getcallersp() - if d.sp != sp { - return - } - if d.openDefer { - done := runOpenDeferFrame(gp, d) - if !done { - throw("unfinished open-coded defers in deferreturn") + for { + d := gp._defer + if d == nil { + return } + sp := getcallersp() + if d.sp != sp { + return + } + if d.openDefer { + done := runOpenDeferFrame(gp, d) + if !done { + throw("unfinished open-coded defers in deferreturn") + } + gp._defer = d.link + freedefer(d) + // If this frame uses open defers, then this + // must be the only defer record for the + // frame, so we can just return. + return + } + + fn := d.fn + d.fn = nil gp._defer = d.link freedefer(d) - return + fn() } - - fn := d.fn - d.fn = nil - gp._defer = d.link - freedefer(d) - // If the defer function pointer is nil, force the seg fault to happen - // here rather than in jmpdefer. gentraceback() throws an error if it is - // called with a callback on an LR architecture and jmpdefer is on the - // stack, because jmpdefer manipulates SP (see issue #8153). - _ = **(**funcval)(unsafe.Pointer(&fn)) - // We must not split the stack between computing argp and - // calling jmpdefer because argp is a uintptr stack pointer. - argp := getcallersp() + sys.MinFrameSize - jmpdefer(fn, argp) } // Goexit terminates the goroutine that calls it. No other goroutine is affected. diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go index b94acdea1f..fc29a1bac3 100644 --- a/src/runtime/stubs.go +++ b/src/runtime/stubs.go @@ -176,8 +176,6 @@ func cgocallback(fn, frame, ctxt uintptr) func gogo(buf *gobuf) -//go:noescape -func jmpdefer(fv func(), argp uintptr) func asminit() func setg(gg *g) func breakpoint() diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 44ea0710c6..d08aa0b320 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -331,7 +331,6 @@ const ( funcID_gogo funcID_gopanic funcID_handleAsyncEvent - funcID_jmpdefer funcID_mcall funcID_morestack funcID_mstart -- GitLab From 40e561d9337afbae221b34d6d0811761f32412f6 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 30 Jul 2021 09:06:38 -0700 Subject: [PATCH 0575/2500] [dev.typeparams] cmd/compile: allow types with the same underlying type to have the same shape First baby step to sharing the underlying implementation among several types. Change-Id: I6a156176d2b7f0131a87285a03b881ce380c26ed Reviewed-on: https://go-review.googlesource.com/c/go/+/338610 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- .../compile/internal/reflectdata/reflect.go | 2 +- src/cmd/compile/internal/typecheck/subr.go | 22 +++++-------- test/typeparam/shape1.go | 33 +++++++++++++++++++ test/typeparam/shape1.out | 2 ++ 4 files changed, 44 insertions(+), 15 deletions(-) create mode 100644 test/typeparam/shape1.go create mode 100644 test/typeparam/shape1.out diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 3bf248a7ad..dca8de74f3 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -1920,7 +1920,7 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy // Target method uses shaped names. targs2 := make([]*types.Type, len(targs)) for i, t := range targs { - targs2[i] = typecheck.Shaped[t] + targs2[i] = typecheck.Shapify(t) } targs = targs2 diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 53221bc1cd..e2f0a57e71 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1348,32 +1348,26 @@ func Shapify(t *types.Type) *types.Type { if t.IsShape() { return t // TODO: is this right? } - if s := Shaped[t]; s != nil { + // Map all types with the same underlying type to the same shape. + u := t.Underlying() + + if s := shaped[u]; s != nil { return s //TODO: keep? } - // For now, there is a 1-1 mapping between regular types and shape types. sym := Lookup(fmt.Sprintf(".shape%d", snum)) snum++ - name := ir.NewDeclNameAt(t.Pos(), ir.OTYPE, sym) + name := ir.NewDeclNameAt(u.Pos(), ir.OTYPE, sym) s := types.NewNamed(name) - s.SetUnderlying(t.Underlying()) + s.SetUnderlying(u) s.SetIsShape(true) name.SetType(s) name.SetTypecheck(1) // TODO: add methods to s that the bound has? - Shaped[t] = s + shaped[u] = s return s } var snum int -var Shaped = map[*types.Type]*types.Type{} - -func ShapifyList(targs []*types.Type) []*types.Type { - r := make([]*types.Type, len(targs)) - for i, t := range targs { - r[i] = Shapify(t) - } - return r -} +var shaped = map[*types.Type]*types.Type{} diff --git a/test/typeparam/shape1.go b/test/typeparam/shape1.go new file mode 100644 index 0000000000..3c9e71ea63 --- /dev/null +++ b/test/typeparam/shape1.go @@ -0,0 +1,33 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type I interface { + foo() int +} + +// There should be a single instantiation of f in this program. +func f[T I](x T) int { + return x.foo() +} + +type squarer int + +func (x squarer) foo() int { + return int(x*x) +} + +type doubler int + +func (x doubler) foo() int { + return int(2*x) +} + +func main() { + println(f(squarer(5))) + println(f(doubler(5))) +} diff --git a/test/typeparam/shape1.out b/test/typeparam/shape1.out new file mode 100644 index 0000000000..28391fde66 --- /dev/null +++ b/test/typeparam/shape1.out @@ -0,0 +1,2 @@ +25 +10 -- GitLab From e3e9f0bb2d6cc15b201fe2e0a0ac095d62cf4b8c Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 30 Jul 2021 16:40:17 -0400 Subject: [PATCH 0576/2500] [dev.typeparams] Revert "[dev.typeparams] runtime,cmd/compile,cmd/link: replace jmpdefer with a loop" This reverts CL 227652. I'm reverting CL 337651 and this builds on top of it. Change-Id: I03ce363be44c2a3defff2e43e7b1aad83386820d Reviewed-on: https://go-review.googlesource.com/c/go/+/338709 Trust: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/compile/internal/amd64/galign.go | 1 + src/cmd/compile/internal/arm/galign.go | 1 + src/cmd/compile/internal/arm64/galign.go | 1 + src/cmd/compile/internal/mips/galign.go | 1 + src/cmd/compile/internal/mips64/galign.go | 1 + src/cmd/compile/internal/ppc64/galign.go | 1 + src/cmd/compile/internal/ppc64/ggen.go | 27 ++++++++++ src/cmd/compile/internal/riscv64/galign.go | 1 + src/cmd/compile/internal/s390x/galign.go | 1 + src/cmd/compile/internal/ssagen/arch.go | 3 +- src/cmd/compile/internal/ssagen/ssa.go | 12 +++++ src/cmd/compile/internal/wasm/ssa.go | 7 +-- src/cmd/compile/internal/x86/galign.go | 1 + src/cmd/internal/obj/arm/asm5.go | 11 ++-- src/cmd/internal/obj/wasm/wasmobj.go | 36 ++++++++++++++ src/cmd/internal/obj/x86/asm6.go | 1 + src/cmd/internal/objabi/funcid.go | 2 + src/cmd/link/internal/ld/pcln.go | 9 ++-- src/runtime/asm_386.s | 20 ++++++++ src/runtime/asm_amd64.s | 15 ++++++ src/runtime/asm_arm.s | 14 ++++++ src/runtime/asm_arm64.s | 17 +++++++ src/runtime/asm_mips64x.s | 16 ++++++ src/runtime/asm_mipsx.s | 16 ++++++ src/runtime/asm_ppc64x.s | 28 +++++++++++ src/runtime/asm_riscv64.s | 15 ++++++ src/runtime/asm_s390x.s | 15 ++++++ src/runtime/asm_wasm.s | 29 +++++++++++ src/runtime/panic.go | 58 ++++++++++++---------- src/runtime/stubs.go | 2 + src/runtime/symtab.go | 1 + 31 files changed, 324 insertions(+), 39 deletions(-) diff --git a/src/cmd/compile/internal/amd64/galign.go b/src/cmd/compile/internal/amd64/galign.go index ca44263afc..3b13e123a7 100644 --- a/src/cmd/compile/internal/amd64/galign.go +++ b/src/cmd/compile/internal/amd64/galign.go @@ -18,6 +18,7 @@ func Init(arch *ssagen.ArchInfo) { arch.ZeroRange = zerorange arch.Ginsnop = ginsnop + arch.Ginsnopdefer = ginsnop arch.SSAMarkMoves = ssaMarkMoves arch.SSAGenValue = ssaGenValue diff --git a/src/cmd/compile/internal/arm/galign.go b/src/cmd/compile/internal/arm/galign.go index 23e52bacbf..d68500280d 100644 --- a/src/cmd/compile/internal/arm/galign.go +++ b/src/cmd/compile/internal/arm/galign.go @@ -18,6 +18,7 @@ func Init(arch *ssagen.ArchInfo) { arch.SoftFloat = buildcfg.GOARM == 5 arch.ZeroRange = zerorange arch.Ginsnop = ginsnop + arch.Ginsnopdefer = ginsnop arch.SSAMarkMoves = func(s *ssagen.State, b *ssa.Block) {} arch.SSAGenValue = ssaGenValue diff --git a/src/cmd/compile/internal/arm64/galign.go b/src/cmd/compile/internal/arm64/galign.go index 3ebd860de8..2a61b9dd99 100644 --- a/src/cmd/compile/internal/arm64/galign.go +++ b/src/cmd/compile/internal/arm64/galign.go @@ -18,6 +18,7 @@ func Init(arch *ssagen.ArchInfo) { arch.PadFrame = padframe arch.ZeroRange = zerorange arch.Ginsnop = ginsnop + arch.Ginsnopdefer = ginsnop arch.SSAMarkMoves = func(s *ssagen.State, b *ssa.Block) {} arch.SSAGenValue = ssaGenValue diff --git a/src/cmd/compile/internal/mips/galign.go b/src/cmd/compile/internal/mips/galign.go index 4e6897042e..f892923ba0 100644 --- a/src/cmd/compile/internal/mips/galign.go +++ b/src/cmd/compile/internal/mips/galign.go @@ -21,6 +21,7 @@ func Init(arch *ssagen.ArchInfo) { arch.SoftFloat = (buildcfg.GOMIPS == "softfloat") arch.ZeroRange = zerorange arch.Ginsnop = ginsnop + arch.Ginsnopdefer = ginsnop arch.SSAMarkMoves = func(s *ssagen.State, b *ssa.Block) {} arch.SSAGenValue = ssaGenValue arch.SSAGenBlock = ssaGenBlock diff --git a/src/cmd/compile/internal/mips64/galign.go b/src/cmd/compile/internal/mips64/galign.go index 412bc71aab..af81366e51 100644 --- a/src/cmd/compile/internal/mips64/galign.go +++ b/src/cmd/compile/internal/mips64/galign.go @@ -21,6 +21,7 @@ func Init(arch *ssagen.ArchInfo) { arch.SoftFloat = buildcfg.GOMIPS64 == "softfloat" arch.ZeroRange = zerorange arch.Ginsnop = ginsnop + arch.Ginsnopdefer = ginsnop arch.SSAMarkMoves = func(s *ssagen.State, b *ssa.Block) {} arch.SSAGenValue = ssaGenValue diff --git a/src/cmd/compile/internal/ppc64/galign.go b/src/cmd/compile/internal/ppc64/galign.go index bff3e38f42..590290fa37 100644 --- a/src/cmd/compile/internal/ppc64/galign.go +++ b/src/cmd/compile/internal/ppc64/galign.go @@ -20,6 +20,7 @@ func Init(arch *ssagen.ArchInfo) { arch.ZeroRange = zerorange arch.Ginsnop = ginsnop + arch.Ginsnopdefer = ginsnopdefer arch.SSAMarkMoves = ssaMarkMoves arch.SSAGenValue = ssaGenValue diff --git a/src/cmd/compile/internal/ppc64/ggen.go b/src/cmd/compile/internal/ppc64/ggen.go index 3ae6422bf9..c76962cfb8 100644 --- a/src/cmd/compile/internal/ppc64/ggen.go +++ b/src/cmd/compile/internal/ppc64/ggen.go @@ -53,3 +53,30 @@ func ginsnop(pp *objw.Progs) *obj.Prog { p.To.Reg = ppc64.REG_R0 return p } + +func ginsnopdefer(pp *objw.Progs) *obj.Prog { + // On PPC64 two nops are required in the defer case. + // + // (see gc/cgen.go, gc/plive.go -- copy of comment below) + // + // On ppc64, when compiling Go into position + // independent code on ppc64le we insert an + // instruction to reload the TOC pointer from the + // stack as well. See the long comment near + // jmpdefer in runtime/asm_ppc64.s for why. + // If the MOVD is not needed, insert a hardware NOP + // so that the same number of instructions are used + // on ppc64 in both shared and non-shared modes. + + ginsnop(pp) + if base.Ctxt.Flag_shared { + p := pp.Prog(ppc64.AMOVD) + p.From.Type = obj.TYPE_MEM + p.From.Offset = 24 + p.From.Reg = ppc64.REGSP + p.To.Type = obj.TYPE_REG + p.To.Reg = ppc64.REG_R2 + return p + } + return ginsnop(pp) +} diff --git a/src/cmd/compile/internal/riscv64/galign.go b/src/cmd/compile/internal/riscv64/galign.go index 846ed8fb38..338248a7cf 100644 --- a/src/cmd/compile/internal/riscv64/galign.go +++ b/src/cmd/compile/internal/riscv64/galign.go @@ -16,6 +16,7 @@ func Init(arch *ssagen.ArchInfo) { arch.MAXWIDTH = 1 << 50 arch.Ginsnop = ginsnop + arch.Ginsnopdefer = ginsnop arch.ZeroRange = zeroRange arch.SSAMarkMoves = ssaMarkMoves diff --git a/src/cmd/compile/internal/s390x/galign.go b/src/cmd/compile/internal/s390x/galign.go index d880834c22..b004a2db0a 100644 --- a/src/cmd/compile/internal/s390x/galign.go +++ b/src/cmd/compile/internal/s390x/galign.go @@ -16,6 +16,7 @@ func Init(arch *ssagen.ArchInfo) { arch.ZeroRange = zerorange arch.Ginsnop = ginsnop + arch.Ginsnopdefer = ginsnop arch.SSAMarkMoves = ssaMarkMoves arch.SSAGenValue = ssaGenValue diff --git a/src/cmd/compile/internal/ssagen/arch.go b/src/cmd/compile/internal/ssagen/arch.go index 483e45cad4..957fb3e84a 100644 --- a/src/cmd/compile/internal/ssagen/arch.go +++ b/src/cmd/compile/internal/ssagen/arch.go @@ -29,7 +29,8 @@ type ArchInfo struct { // at function entry, and it is ok to clobber registers. ZeroRange func(*objw.Progs, *obj.Prog, int64, int64, *uint32) *obj.Prog - Ginsnop func(*objw.Progs) *obj.Prog + Ginsnop func(*objw.Progs) *obj.Prog + Ginsnopdefer func(*objw.Progs) *obj.Prog // special ginsnop for deferreturn // SSAMarkMoves marks any MOVXconst ops that need to avoid clobbering flags. SSAMarkMoves func(*State, *ssa.Block) diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 161469ea67..7e2f6a7471 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -7335,6 +7335,18 @@ func (s *State) PrepareCall(v *ssa.Value) { call, ok := v.Aux.(*ssa.AuxCall) + if ok && call.Fn == ir.Syms.Deferreturn { + // Deferred calls will appear to be returning to + // the CALL deferreturn(SB) that we are about to emit. + // However, the stack trace code will show the line + // of the instruction byte before the return PC. + // To avoid that being an unrelated instruction, + // insert an actual hardware NOP that will have the right line number. + // This is different from obj.ANOP, which is a virtual no-op + // that doesn't make it into the instruction stream. + Arch.Ginsnopdefer(s.pp) + } + if ok { // Record call graph information for nowritebarrierrec // analysis. diff --git a/src/cmd/compile/internal/wasm/ssa.go b/src/cmd/compile/internal/wasm/ssa.go index 0b2ca3fdbb..31b09016eb 100644 --- a/src/cmd/compile/internal/wasm/ssa.go +++ b/src/cmd/compile/internal/wasm/ssa.go @@ -24,6 +24,7 @@ func Init(arch *ssagen.ArchInfo) { arch.ZeroRange = zeroRange arch.Ginsnop = ginsnop + arch.Ginsnopdefer = ginsnop arch.SSAMarkMoves = ssaMarkMoves arch.SSAGenValue = ssaGenValue @@ -125,11 +126,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { case ssa.OpWasmLoweredStaticCall, ssa.OpWasmLoweredClosureCall, ssa.OpWasmLoweredInterCall: s.PrepareCall(v) if call, ok := v.Aux.(*ssa.AuxCall); ok && call.Fn == ir.Syms.Deferreturn { - // The runtime needs to inject jumps to - // deferreturn calls using the address in - // _func.deferreturn. Hence, the call to - // deferreturn must itself be a resumption - // point so it gets a target PC. + // add a resume point before call to deferreturn so it can be called again via jmpdefer s.Prog(wasm.ARESUMEPOINT) } if v.Op == ssa.OpWasmLoweredClosureCall { diff --git a/src/cmd/compile/internal/x86/galign.go b/src/cmd/compile/internal/x86/galign.go index 5565bd32c7..00a20e429f 100644 --- a/src/cmd/compile/internal/x86/galign.go +++ b/src/cmd/compile/internal/x86/galign.go @@ -34,6 +34,7 @@ func Init(arch *ssagen.ArchInfo) { arch.ZeroRange = zerorange arch.Ginsnop = ginsnop + arch.Ginsnopdefer = ginsnop arch.SSAMarkMoves = ssaMarkMoves } diff --git a/src/cmd/internal/obj/arm/asm5.go b/src/cmd/internal/obj/arm/asm5.go index 7b1682776e..ccf5f9e7f8 100644 --- a/src/cmd/internal/obj/arm/asm5.go +++ b/src/cmd/internal/obj/arm/asm5.go @@ -355,10 +355,11 @@ var oprange [ALAST & obj.AMask][]Optab var xcmp [C_GOK + 1][C_GOK + 1]bool var ( - symdiv *obj.LSym - symdivu *obj.LSym - symmod *obj.LSym - symmodu *obj.LSym + deferreturn *obj.LSym + symdiv *obj.LSym + symdivu *obj.LSym + symmod *obj.LSym + symmodu *obj.LSym ) // Note about encoding: Prog.scond holds the condition encoding, @@ -1218,6 +1219,8 @@ func buildop(ctxt *obj.Link) { return } + deferreturn = ctxt.LookupABI("runtime.deferreturn", obj.ABIInternal) + symdiv = ctxt.Lookup("runtime._div") symdivu = ctxt.Lookup("runtime._divu") symmod = ctxt.Lookup("runtime._mod") diff --git a/src/cmd/internal/obj/wasm/wasmobj.go b/src/cmd/internal/obj/wasm/wasmobj.go index 4d276db678..ceeae7a257 100644 --- a/src/cmd/internal/obj/wasm/wasmobj.go +++ b/src/cmd/internal/obj/wasm/wasmobj.go @@ -129,6 +129,8 @@ var ( morestackNoCtxt *obj.LSym gcWriteBarrier *obj.LSym sigpanic *obj.LSym + deferreturn *obj.LSym + jmpdefer *obj.LSym ) const ( @@ -141,6 +143,10 @@ func instinit(ctxt *obj.Link) { morestackNoCtxt = ctxt.Lookup("runtime.morestack_noctxt") gcWriteBarrier = ctxt.LookupABI("runtime.gcWriteBarrier", obj.ABIInternal) sigpanic = ctxt.LookupABI("runtime.sigpanic", obj.ABIInternal) + deferreturn = ctxt.LookupABI("runtime.deferreturn", obj.ABIInternal) + // jmpdefer is defined in assembly as ABI0. The compiler will + // generate a direct ABI0 call from Go, so look for that. + jmpdefer = ctxt.LookupABI(`"".jmpdefer`, obj.ABI0) } func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { @@ -417,6 +423,12 @@ func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { pcAfterCall-- // sigpanic expects to be called without advancing the pc } + // jmpdefer manipulates the return address on the stack so deferreturn gets called repeatedly. + // Model this in WebAssembly with a loop. + if call.To.Sym == deferreturn { + p = appendp(p, ALoop) + } + // SP -= 8 p = appendp(p, AGet, regAddr(REG_SP)) p = appendp(p, AI32Const, constAddr(8)) @@ -467,6 +479,15 @@ func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { break } + // jmpdefer removes the frame of deferreturn from the Go stack. + // However, its WebAssembly function still returns normally, + // so we need to return from deferreturn without removing its + // stack frame (no RET), because the frame is already gone. + if call.To.Sym == jmpdefer { + p = appendp(p, AReturn) + break + } + // return value of call is on the top of the stack, indicating whether to unwind the WebAssembly stack if call.As == ACALLNORESUME && call.To.Sym != sigpanic { // sigpanic unwinds the stack, but it never resumes // trying to unwind WebAssembly stack but call has no resume point, terminate with error @@ -479,6 +500,21 @@ func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { unwindExitBranches = append(unwindExitBranches, p) } + // jump to before the call if jmpdefer has reset the return address to the call's PC + if call.To.Sym == deferreturn { + // get PC_B from -8(SP) + p = appendp(p, AGet, regAddr(REG_SP)) + p = appendp(p, AI32Const, constAddr(8)) + p = appendp(p, AI32Sub) + p = appendp(p, AI32Load16U, constAddr(0)) + p = appendp(p, ATee, regAddr(REG_PC_B)) + + p = appendp(p, AI32Const, constAddr(call.Pc)) + p = appendp(p, AI32Eq) + p = appendp(p, ABrIf, constAddr(0)) + p = appendp(p, AEnd) // end of Loop + } + case obj.ARET, ARETUNWIND: ret := *p p.As = obj.ANOP diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go index 331a98dfef..17fa76727e 100644 --- a/src/cmd/internal/obj/x86/asm6.go +++ b/src/cmd/internal/obj/x86/asm6.go @@ -43,6 +43,7 @@ import ( var ( plan9privates *obj.LSym + deferreturn *obj.LSym ) // Instruction layout. diff --git a/src/cmd/internal/objabi/funcid.go b/src/cmd/internal/objabi/funcid.go index 68f6a26a76..d881cdd061 100644 --- a/src/cmd/internal/objabi/funcid.go +++ b/src/cmd/internal/objabi/funcid.go @@ -34,6 +34,7 @@ const ( FuncID_gogo FuncID_gopanic FuncID_handleAsyncEvent + FuncID_jmpdefer FuncID_mcall FuncID_morestack FuncID_mstart @@ -59,6 +60,7 @@ var funcIDs = map[string]FuncID{ "gogo": FuncID_gogo, "gopanic": FuncID_gopanic, "handleAsyncEvent": FuncID_handleAsyncEvent, + "jmpdefer": FuncID_jmpdefer, "main": FuncID_runtime_main, "mcall": FuncID_mcall, "morestack": FuncID_morestack, diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index 70e3e1284b..05fd302369 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -129,10 +129,11 @@ func computeDeferReturn(ctxt *Link, deferReturnSym, s loader.Sym) uint32 { for ri := 0; ri < relocs.Count(); ri++ { r := relocs.At(ri) if target.IsWasm() && r.Type() == objabi.R_ADDR { - // wasm/ssa.go generates an ARESUMEPOINT just - // before the deferreturn call. The "PC" of - // the deferreturn call is stored in the - // R_ADDR relocation on the ARESUMEPOINT. + // Wasm does not have a live variable set at the deferreturn + // call itself. Instead it has one identified by the + // resumption point immediately preceding the deferreturn. + // The wasm code has a R_ADDR relocation which is used to + // set the resumption point to PC_B. lastWasmAddr = uint32(r.Add()) } if r.Type().IsDirectCall() && (r.Sym() == deferReturnSym || ldr.IsDeferReturnTramp(r.Sym())) { diff --git a/src/runtime/asm_386.s b/src/runtime/asm_386.s index 11c60309f4..dd2ea458cc 100644 --- a/src/runtime/asm_386.s +++ b/src/runtime/asm_386.s @@ -582,6 +582,26 @@ TEXT ·publicationBarrier(SB),NOSPLIT,$0-0 // compile barrier. RET +// void jmpdefer(fn, sp); +// called from deferreturn. +// 1. pop the caller +// 2. sub 5 bytes (the length of CALL & a 32 bit displacement) from the callers +// return (when building for shared libraries, subtract 16 bytes -- 5 bytes +// for CALL & displacement to call __x86.get_pc_thunk.cx, 6 bytes for the +// LEAL to load the offset into BX, and finally 5 for the call & displacement) +// 3. jmp to the argument +TEXT runtime·jmpdefer(SB), NOSPLIT, $0-8 + MOVL fv+0(FP), DX // fn + MOVL argp+4(FP), BX // caller sp + LEAL -4(BX), SP // caller sp after CALL +#ifdef GOBUILDMODE_shared + SUBL $16, (SP) // return to CALL again +#else + SUBL $5, (SP) // return to CALL again +#endif + MOVL 0(DX), BX + JMP BX // but first run the deferred function + // Save state of caller into g->sched, // but using fake PC from systemstack_switch. // Must only be called from functions with no locals ($0) diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index 2d8f4c2412..0f719b2664 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -662,6 +662,21 @@ TEXT ·publicationBarrier(SB),NOSPLIT,$0-0 // compile barrier. RET +// func jmpdefer(fv func(), argp uintptr) +// argp is a caller SP. +// called from deferreturn. +// 1. pop the caller +// 2. sub 5 bytes from the callers return +// 3. jmp to the argument +TEXT runtime·jmpdefer(SB), NOSPLIT, $0-16 + MOVQ fv+0(FP), DX // fn + MOVQ argp+8(FP), BX // caller sp + LEAQ -8(BX), SP // caller sp after CALL + MOVQ -8(SP), BP // restore BP as if deferreturn returned (harmless if framepointers not in use) + SUBQ $5, (SP) // return to CALL again + MOVQ 0(DX), BX + JMP BX // but first run the deferred function + // Save state of caller into g->sched, // but using fake PC from systemstack_switch. // Must only be called from functions with no locals ($0) diff --git a/src/runtime/asm_arm.s b/src/runtime/asm_arm.s index a1164781d2..5c2bc00fe8 100644 --- a/src/runtime/asm_arm.s +++ b/src/runtime/asm_arm.s @@ -506,6 +506,20 @@ CALLFN(·call268435456, 268435456) CALLFN(·call536870912, 536870912) CALLFN(·call1073741824, 1073741824) +// void jmpdefer(fn, sp); +// called from deferreturn. +// 1. grab stored LR for caller +// 2. sub 4 bytes to get back to BL deferreturn +// 3. B to fn +TEXT runtime·jmpdefer(SB),NOSPLIT,$0-8 + MOVW 0(R13), LR + MOVW $-4(LR), LR // BL deferreturn + MOVW fv+0(FP), R7 + MOVW argp+4(FP), R13 + MOVW $-4(R13), R13 // SP is 4 below argp, due to saved LR + MOVW 0(R7), R1 + B (R1) + // Save state of caller into g->sched, // but using fake PC from systemstack_switch. // Must only be called from functions with no locals ($0) diff --git a/src/runtime/asm_arm64.s b/src/runtime/asm_arm64.s index e51ce2f831..e7c5fa3225 100644 --- a/src/runtime/asm_arm64.s +++ b/src/runtime/asm_arm64.s @@ -982,6 +982,23 @@ again: CBNZ R0, again RET +// void jmpdefer(fv, sp); +// called from deferreturn. +// 1. grab stored LR for caller +// 2. sub 4 bytes to get back to BL deferreturn +// 3. BR to fn +TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16 + MOVD 0(RSP), R0 + SUB $4, R0 + MOVD R0, LR + + MOVD fv+0(FP), R26 + MOVD argp+8(FP), R0 + MOVD R0, RSP + SUB $8, RSP + MOVD 0(R26), R3 + B (R3) + // Save state of caller into g->sched, // but using fake PC from systemstack_switch. // Must only be called from functions with no locals ($0) diff --git a/src/runtime/asm_mips64x.s b/src/runtime/asm_mips64x.s index b2e2384c36..f3ac453d99 100644 --- a/src/runtime/asm_mips64x.s +++ b/src/runtime/asm_mips64x.s @@ -384,6 +384,22 @@ CALLFN(·call1073741824, 1073741824) TEXT runtime·procyield(SB),NOSPLIT,$0-0 RET +// void jmpdefer(fv, sp); +// called from deferreturn. +// 1. grab stored LR for caller +// 2. sub 8 bytes to get back to JAL deferreturn +// 3. JMP to fn +TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16 + MOVV 0(R29), R31 + ADDV $-8, R31 + + MOVV fv+0(FP), REGCTXT + MOVV argp+8(FP), R29 + ADDV $-8, R29 + NOR R0, R0 // prevent scheduling + MOVV 0(REGCTXT), R4 + JMP (R4) + // Save state of caller into g->sched, // but using fake PC from systemstack_switch. // Must only be called from functions with no locals ($0) diff --git a/src/runtime/asm_mipsx.s b/src/runtime/asm_mipsx.s index 87a1344e8f..4dc165849e 100644 --- a/src/runtime/asm_mipsx.s +++ b/src/runtime/asm_mipsx.s @@ -382,6 +382,22 @@ CALLFN(·call1073741824, 1073741824) TEXT runtime·procyield(SB),NOSPLIT,$0-4 RET +// void jmpdefer(fv, sp); +// called from deferreturn. +// 1. grab stored LR for caller +// 2. sub 8 bytes to get back to JAL deferreturn +// 3. JMP to fn +TEXT runtime·jmpdefer(SB),NOSPLIT,$0-8 + MOVW 0(R29), R31 + ADDU $-8, R31 + + MOVW fv+0(FP), REGCTXT + MOVW argp+4(FP), R29 + ADDU $-4, R29 + NOR R0, R0 // prevent scheduling + MOVW 0(REGCTXT), R4 + JMP (R4) + // Save state of caller into g->sched, // but using fake PC from systemstack_switch. // Must only be called from functions with no locals ($0) diff --git a/src/runtime/asm_ppc64x.s b/src/runtime/asm_ppc64x.s index 5dc96c5947..a789d041e4 100644 --- a/src/runtime/asm_ppc64x.s +++ b/src/runtime/asm_ppc64x.s @@ -503,6 +503,34 @@ again: OR R6, R6, R6 // Set PPR priority back to medium-low RET +// void jmpdefer(fv, sp); +// called from deferreturn. +// 1. grab stored LR for caller +// 2. sub 8 bytes to get back to either nop or toc reload before deferreturn +// 3. BR to fn +// When dynamically linking Go, it is not sufficient to rewind to the BL +// deferreturn -- we might be jumping between modules and so we need to reset +// the TOC pointer in r2. To do this, codegen inserts MOVD 24(R1), R2 *before* +// the BL deferreturn and jmpdefer rewinds to that. +TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16 + MOVD 0(R1), R31 + SUB $8, R31 + MOVD R31, LR + + MOVD fv+0(FP), R11 + MOVD argp+8(FP), R1 + SUB $FIXED_FRAME, R1 +#ifdef GOOS_aix + // AIX won't trigger a SIGSEGV if R11 = nil + // So it manually triggers it + CMP R0, R11 + BNE 2(PC) + MOVD R0, 0(R0) +#endif + MOVD 0(R11), R12 + MOVD R12, CTR + BR (CTR) + // Save state of caller into g->sched, // but using fake PC from systemstack_switch. // Must only be called from functions with no locals ($0) diff --git a/src/runtime/asm_riscv64.s b/src/runtime/asm_riscv64.s index 9927a817f7..9957ae201b 100644 --- a/src/runtime/asm_riscv64.s +++ b/src/runtime/asm_riscv64.s @@ -248,6 +248,21 @@ TEXT gogo<>(SB), NOSPLIT|NOFRAME, $0 MOV gobuf_pc(T0), T0 JALR ZERO, T0 +// func jmpdefer(fv func(), argp uintptr) +// called from deferreturn +// 1. grab stored return address from the caller's frame +// 2. sub 8 bytes to get back to JAL deferreturn +// 3. JMP to fn +TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16 + MOV 0(X2), RA + ADD $-8, RA + + MOV fv+0(FP), CTXT + MOV argp+8(FP), X2 + ADD $-8, X2 + MOV 0(CTXT), T0 + JALR ZERO, T0 + // func procyield(cycles uint32) TEXT runtime·procyield(SB),NOSPLIT,$0-0 RET diff --git a/src/runtime/asm_s390x.s b/src/runtime/asm_s390x.s index d4110d563f..534cb6112c 100644 --- a/src/runtime/asm_s390x.s +++ b/src/runtime/asm_s390x.s @@ -480,6 +480,21 @@ TEXT callfnMVC<>(SB),NOSPLIT|NOFRAME,$0-0 TEXT runtime·procyield(SB),NOSPLIT,$0-0 RET +// void jmpdefer(fv, sp); +// called from deferreturn. +// 1. grab stored LR for caller +// 2. sub 6 bytes to get back to BL deferreturn (size of BRASL instruction) +// 3. BR to fn +TEXT runtime·jmpdefer(SB),NOSPLIT|NOFRAME,$0-16 + MOVD 0(R15), R1 + SUB $6, R1, LR + + MOVD fv+0(FP), R12 + MOVD argp+8(FP), R15 + SUB $8, R15 + MOVD 0(R12), R3 + BR (R3) + // Save state of caller into g->sched, // but using fake PC from systemstack_switch. // Must only be called from functions with no locals ($0) diff --git a/src/runtime/asm_wasm.s b/src/runtime/asm_wasm.s index d885da6e70..53c271aa70 100644 --- a/src/runtime/asm_wasm.s +++ b/src/runtime/asm_wasm.s @@ -193,6 +193,35 @@ TEXT runtime·return0(SB), NOSPLIT, $0-0 MOVD $0, RET0 RET +TEXT runtime·jmpdefer(SB), NOSPLIT, $0-16 + MOVD fv+0(FP), CTXT + + Get CTXT + I64Eqz + If + CALLNORESUME runtime·sigpanic(SB) + End + + // caller sp after CALL + I64Load argp+8(FP) + I64Const $8 + I64Sub + I32WrapI64 + Set SP + + // decrease PC_B by 1 to CALL again + Get SP + I32Load16U (SP) + I32Const $1 + I32Sub + I32Store16 $0 + + // but first run the deferred function + Get CTXT + I32WrapI64 + I64Load $0 + JMP + TEXT runtime·asminit(SB), NOSPLIT, $0-0 // No per-thread init. RET diff --git a/src/runtime/panic.go b/src/runtime/panic.go index 4b8bca6c56..e66fe27be0 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -396,39 +396,47 @@ func freedeferfn() { throw("freedefer with d.fn != nil") } -// deferreturn runs deferred functions for the caller's frame. +// Run a deferred function if there is one. // The compiler inserts a call to this at the end of any // function which calls defer. +// If there is a deferred function, this will call runtime·jmpdefer, +// which will jump to the deferred function such that it appears +// to have been called by the caller of deferreturn at the point +// just before deferreturn was called. The effect is that deferreturn +// is called again and again until there are no more deferred functions. func deferreturn() { gp := getg() - for { - d := gp._defer - if d == nil { - return - } - sp := getcallersp() - if d.sp != sp { - return - } - if d.openDefer { - done := runOpenDeferFrame(gp, d) - if !done { - throw("unfinished open-coded defers in deferreturn") - } - gp._defer = d.link - freedefer(d) - // If this frame uses open defers, then this - // must be the only defer record for the - // frame, so we can just return. - return + d := gp._defer + if d == nil { + return + } + sp := getcallersp() + if d.sp != sp { + return + } + if d.openDefer { + done := runOpenDeferFrame(gp, d) + if !done { + throw("unfinished open-coded defers in deferreturn") } - - fn := d.fn - d.fn = nil gp._defer = d.link freedefer(d) - fn() + return } + + fn := d.fn + d.fn = nil + gp._defer = d.link + freedefer(d) + // If the defer function pointer is nil, force the seg fault to happen + // here rather than in jmpdefer. gentraceback() throws an error if it is + // called with a callback on an LR architecture and jmpdefer is on the + // stack, because jmpdefer manipulates SP (see issue #8153). + _ = **(**funcval)(unsafe.Pointer(&fn)) + // We must not split the stack between computing argp and + // calling jmpdefer because argp is a uintptr stack pointer. + argp := getcallersp() + sys.MinFrameSize + jmpdefer(fn, argp) } // Goexit terminates the goroutine that calls it. No other goroutine is affected. diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go index fc29a1bac3..b94acdea1f 100644 --- a/src/runtime/stubs.go +++ b/src/runtime/stubs.go @@ -176,6 +176,8 @@ func cgocallback(fn, frame, ctxt uintptr) func gogo(buf *gobuf) +//go:noescape +func jmpdefer(fv func(), argp uintptr) func asminit() func setg(gg *g) func breakpoint() diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index d08aa0b320..44ea0710c6 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -331,6 +331,7 @@ const ( funcID_gogo funcID_gopanic funcID_handleAsyncEvent + funcID_jmpdefer funcID_mcall funcID_morestack funcID_mstart -- GitLab From 7bed50e667cf1b4ba5b2ec7ca699c835c696e454 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 30 Jul 2021 16:41:11 -0400 Subject: [PATCH 0577/2500] [dev.typeparams] Revert "[dev.typeparams] runtime: remove unnecessary split-prevention from defer code" This reverts CL 337651. This causes `go test -count 1000 -run TestDeferHeapAndStack runtime` to fail with a SIGSEGV freedefer [https://build.golang.org/log/c113b366cc6d51146db02a07b4d7dd931133efd5] and possibly sometimes a GC bad pointer panic [https://build.golang.org/log/5b1cef7a9ad68704e9ef3ce3ad2fefca3ba86998]. Change-Id: Ie56c274b78603c81191213b302225ae19de27fb9 Reviewed-on: https://go-review.googlesource.com/c/go/+/338710 Trust: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/panic.go | 84 +++++++++++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 29 deletions(-) diff --git a/src/runtime/panic.go b/src/runtime/panic.go index e66fe27be0..35f3b44a4d 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -261,8 +261,10 @@ func deferproc(fn func()) { // deferprocStack queues a new deferred function with a defer record on the stack. // The defer record must have its fn field initialized. // All other fields can contain junk. -// Nosplit because of the uninitialized pointer fields on the stack. -// +// The defer record must be immediately followed in memory by +// the arguments of the defer. +// Nosplit because the arguments on the stack won't be scanned +// until the defer record is spliced into the gp._defer list. //go:nosplit func deferprocStack(d *_defer) { gp := getg() @@ -311,14 +313,18 @@ func newdefer() *_defer { gp := getg() pp := gp.m.p.ptr() if len(pp.deferpool) == 0 && sched.deferpool != nil { - lock(&sched.deferlock) - for len(pp.deferpool) < cap(pp.deferpool)/2 && sched.deferpool != nil { - d := sched.deferpool - sched.deferpool = d.link - d.link = nil - pp.deferpool = append(pp.deferpool, d) - } - unlock(&sched.deferlock) + // Take the slow path on the system stack so + // we don't grow newdefer's stack. + systemstack(func() { + lock(&sched.deferlock) + for len(pp.deferpool) < cap(pp.deferpool)/2 && sched.deferpool != nil { + d := sched.deferpool + sched.deferpool = d.link + d.link = nil + pp.deferpool = append(pp.deferpool, d) + } + unlock(&sched.deferlock) + }) } if n := len(pp.deferpool); n > 0 { d = pp.deferpool[n-1] @@ -335,6 +341,11 @@ func newdefer() *_defer { // Free the given defer. // The defer cannot be used after this call. +// +// This must not grow the stack because there may be a frame without a +// stack map when this is called. +// +//go:nosplit func freedefer(d *_defer) { if d._panic != nil { freedeferpanic() @@ -348,23 +359,28 @@ func freedefer(d *_defer) { pp := getg().m.p.ptr() if len(pp.deferpool) == cap(pp.deferpool) { // Transfer half of local cache to the central cache. - var first, last *_defer - for len(pp.deferpool) > cap(pp.deferpool)/2 { - n := len(pp.deferpool) - d := pp.deferpool[n-1] - pp.deferpool[n-1] = nil - pp.deferpool = pp.deferpool[:n-1] - if first == nil { - first = d - } else { - last.link = d + // + // Take this slow path on the system stack so + // we don't grow freedefer's stack. + systemstack(func() { + var first, last *_defer + for len(pp.deferpool) > cap(pp.deferpool)/2 { + n := len(pp.deferpool) + d := pp.deferpool[n-1] + pp.deferpool[n-1] = nil + pp.deferpool = pp.deferpool[:n-1] + if first == nil { + first = d + } else { + last.link = d + } + last = d } - last = d - } - lock(&sched.deferlock) - last.link = sched.deferpool - sched.deferpool = first - unlock(&sched.deferlock) + lock(&sched.deferlock) + last.link = sched.deferpool + sched.deferpool = first + unlock(&sched.deferlock) + }) } // These lines used to be simply `*d = _defer{}` but that @@ -404,6 +420,12 @@ func freedeferfn() { // to have been called by the caller of deferreturn at the point // just before deferreturn was called. The effect is that deferreturn // is called again and again until there are no more deferred functions. +// +// Declared as nosplit, because the function should not be preempted once we start +// modifying the caller's frame in order to reuse the frame to call the deferred +// function. +// +//go:nosplit func deferreturn() { gp := getg() d := gp._defer @@ -424,6 +446,13 @@ func deferreturn() { return } + // Moving arguments around. + // + // Everything called after this point must be recursively + // nosplit because the garbage collector won't know the form + // of the arguments until the jmpdefer can flip the PC over to + // fn. + argp := getcallersp() + sys.MinFrameSize fn := d.fn d.fn = nil gp._defer = d.link @@ -433,9 +462,6 @@ func deferreturn() { // called with a callback on an LR architecture and jmpdefer is on the // stack, because jmpdefer manipulates SP (see issue #8153). _ = **(**funcval)(unsafe.Pointer(&fn)) - // We must not split the stack between computing argp and - // calling jmpdefer because argp is a uintptr stack pointer. - argp := getcallersp() + sys.MinFrameSize jmpdefer(fn, argp) } -- GitLab From 90830699aee61a154e989b2d9f8ce3ff4eabbce1 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Fri, 30 Jul 2021 14:10:25 -0400 Subject: [PATCH 0578/2500] [dev.cmdgo] cmd/go: allow expliticly setting -mod=readonly in workspace mode Change-Id: Iedbe47d087d17984a9d839c13c4b7e6c1fa0deaa Reviewed-on: https://go-review.googlesource.com/c/go/+/338594 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/modload/init.go | 4 ++-- src/cmd/go/testdata/script/work.txt | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index a3337d6d23..53c73cb4a0 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -947,8 +947,8 @@ func requirementsFromModFiles(ctx context.Context, modFiles []*modfile.File) *Re // wasn't provided. setDefaultBuildMod may be called multiple times. func setDefaultBuildMod() { if cfg.BuildModExplicit { - if inWorkspaceMode() { - base.Fatalf("go: -mod can't be set explicitly when in workspace mode." + + if inWorkspaceMode() && cfg.BuildMod != "readonly" { + base.Fatalf("go: -mod may only be set to readonly when in workspace mode." + "\n\tRemove the -mod flag to use the default readonly value," + "\n\tor set -workfile=off to disable workspace mode.") } diff --git a/src/cmd/go/testdata/script/work.txt b/src/cmd/go/testdata/script/work.txt index eeaf92eaec..bcbabbacef 100644 --- a/src/cmd/go/testdata/script/work.txt +++ b/src/cmd/go/testdata/script/work.txt @@ -21,10 +21,11 @@ go list all # all includes both modules stdout 'example.com/a' stdout 'example.com/b' -# -mod can't be set in workspace mode, even to readonly -! go list -mod=readonly all -stderr '^go: -mod can''t be set explicitly' -go list -mod=readonly -workfile=off all +# -mod can only be set to readonly in workspace mode +go list -mod=readonly all +! go list -mod=mod all +stderr '^go: -mod may only be set to readonly when in workspace mode' +go list -mod=mod -workfile=off all # Test that duplicates in the directory list return an error cp go.work go.work.backup -- GitLab From 47694b59eb30bfe6a1c12a2eaaf631a4e956b9c7 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Mon, 28 Jun 2021 15:48:03 -0400 Subject: [PATCH 0579/2500] [dev.cmdgo] cmd/go: provide a more helpful missing required module error in workspaces If the user is in a workspace, they might not be in the main module they need to run go get from to add a module that provides a missing dependency. Figure out what that module is from the import stack (there might be multiple but we pick according to the stack computed by the loader for errors) and tell the user to cd to that directory first in the message. Change-Id: I7c919eb61ea3dd122334ff1acd2d7e817cad4b25 Reviewed-on: https://go-review.googlesource.com/c/go/+/334940 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/modload/import.go | 5 +++- src/cmd/go/internal/modload/init.go | 33 +++++++++++++++++++-------- src/cmd/go/internal/modload/load.go | 9 ++++++++ src/cmd/go/testdata/script/work.txt | 2 +- 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/cmd/go/internal/modload/import.go b/src/cmd/go/internal/modload/import.go index 773d8b600b..088d0c14ec 100644 --- a/src/cmd/go/internal/modload/import.go +++ b/src/cmd/go/internal/modload/import.go @@ -32,7 +32,7 @@ type ImportMissingError struct { Module module.Version QueryErr error - ImportingModule module.Version + ImportingMainModule module.Version // isStd indicates whether we would expect to find the package in the standard // library. This is normally true for all dotless import paths, but replace @@ -73,6 +73,9 @@ func (e *ImportMissingError) Error() string { if e.QueryErr != nil { return fmt.Sprintf("%s: %v", message, e.QueryErr) } + if e.ImportingMainModule.Path != "" && e.ImportingMainModule != MainModules.ModContainingCWD() { + return fmt.Sprintf("%s; to add it:\n\tcd %s\n\tgo get %s", message, MainModules.ModRoot(e.ImportingMainModule), e.Path) + } return fmt.Sprintf("%s; to add it:\n\tgo get %s", message, e.Path) } diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 53c73cb4a0..18b07cb125 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -89,6 +89,8 @@ type MainModuleSet struct { modFiles map[module.Version]*modfile.File + modContainingCWD module.Version + indexMu sync.Mutex indices map[module.Version]*modFileIndex } @@ -184,6 +186,13 @@ func (mms *MainModuleSet) Len() int { return len(mms.versions) } +// ModContainingCWD returns the main module containing the working directory, +// or module.Version{} if none of the main modules contain the working +// directory. +func (mms *MainModuleSet) ModContainingCWD() module.Version { + return mms.modContainingCWD +} + var MainModules *MainModuleSet type Root int @@ -315,8 +324,7 @@ func Init() { } else if inWorkspaceMode() { // We're in workspace mode. } else { - modRoots = findModuleRoots(base.Cwd()) - if modRoots == nil { + if modRoot := findModuleRoot(base.Cwd()); modRoot == "" { if cfg.ModFile != "" { base.Fatalf("go: cannot find main module, but -modfile was set.\n\t-modfile cannot be used to set the module root directory.") } @@ -328,17 +336,18 @@ func Init() { // Stay in GOPATH mode. return } - } else if search.InDir(modRoots[0], os.TempDir()) == "." { + } else if search.InDir(modRoot, os.TempDir()) == "." { // If you create /tmp/go.mod for experimenting, // then any tests that create work directories under /tmp // will find it and get modules when they're not expecting them. // It's a bit of a peculiar thing to disallow but quite mysterious // when it happens. See golang.org/issue/26708. - modRoots = nil fmt.Fprintf(os.Stderr, "go: warning: ignoring go.mod in system temp root %v\n", os.TempDir()) if !mustUseModules { return } + } else { + modRoots = []string{modRoot} } } if cfg.ModFile != "" && !strings.HasSuffix(cfg.ModFile, ".mod") { @@ -424,12 +433,11 @@ func WillBeEnabled() bool { return false } - if modRoots := findModuleRoots(base.Cwd()); modRoots == nil { + if modRoot := findModuleRoot(base.Cwd()); modRoot == "" { // GO111MODULE is 'auto', and we can't find a module root. // Stay in GOPATH mode. return false - } else if search.InDir(modRoots[0], os.TempDir()) == "." { - _ = TODOWorkspaces("modRoots[0] is not right here") + } else if search.InDir(modRoot, os.TempDir()) == "." { // If you create /tmp/go.mod for experimenting, // then any tests that create work directories under /tmp // will find it and get modules when they're not expecting them. @@ -856,6 +864,7 @@ func makeMainModules(ms []module.Version, rootDirs []string, modFiles []*modfile panic("mainModulesCalled with module.Version with non empty Version field: " + fmt.Sprintf("%#v", m)) } } + modRootContainingCWD := findModuleRoot(base.Cwd()) mainModules := &MainModuleSet{ versions: ms[:len(ms):len(ms)], inGorootSrc: map[module.Version]bool{}, @@ -870,6 +879,10 @@ func makeMainModules(ms []module.Version, rootDirs []string, modFiles []*modfile mainModules.modFiles[m] = modFiles[i] mainModules.indices[m] = indices[i] + if mainModules.modRoot[m] == modRootContainingCWD { + mainModules.modContainingCWD = m + } + if rel := search.InDir(rootDirs[i], cfg.GOROOTsrc); rel != "" { mainModules.inGorootSrc[m] = true if m.Path == "std" { @@ -1108,7 +1121,7 @@ var altConfigs = []string{ ".git/config", } -func findModuleRoots(dir string) (roots []string) { +func findModuleRoot(dir string) (roots string) { if dir == "" { panic("dir not set") } @@ -1117,7 +1130,7 @@ func findModuleRoots(dir string) (roots []string) { // Look for enclosing go.mod. for { if fi, err := fsys.Stat(filepath.Join(dir, "go.mod")); err == nil && !fi.IsDir() { - return []string{dir} + return dir } d := filepath.Dir(dir) if d == dir { @@ -1125,7 +1138,7 @@ func findModuleRoots(dir string) (roots []string) { } dir = d } - return nil + return "" } func findWorkspaceFile(dir string) (root string) { diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index 67d7ec65da..7def3c2625 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -1364,6 +1364,15 @@ func (ld *loader) resolveMissingImports(ctx context.Context) (modAddedBy map[mod var err error mod, err = queryImport(ctx, pkg.path, ld.requirements) if err != nil { + var ime *ImportMissingError + if errors.As(err, &ime) { + for curstack := pkg.stack; curstack != nil; curstack = curstack.stack { + if MainModules.Contains(curstack.mod.Path) { + ime.ImportingMainModule = curstack.mod + break + } + } + } // pkg.err was already non-nil, so we can reasonably attribute the error // for pkg to either the original error or the one returned by // queryImport. The existing error indicates only that we couldn't find diff --git a/src/cmd/go/testdata/script/work.txt b/src/cmd/go/testdata/script/work.txt index bcbabbacef..9be0958579 100644 --- a/src/cmd/go/testdata/script/work.txt +++ b/src/cmd/go/testdata/script/work.txt @@ -2,7 +2,7 @@ go mod initwork ./a ./b cmp go.work go.work.want ! go run example.com/b -stderr 'a(\\|/)a.go:4:8: no required module provides package rsc.io/quote; to add it:\n\tgo get rsc.io/quote' +stderr 'a(\\|/)a.go:4:8: no required module provides package rsc.io/quote; to add it:\n\tcd '$WORK(\\|/)gopath(\\|/)src(\\|/)a'\n\tgo get rsc.io/quote' cd a go get rsc.io/quote go env GOMOD # go env GOMOD reports the module in a single module context -- GitLab From b3b53e1dad8681e3c21522513e4539813a5a3de7 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Sun, 4 Jul 2021 13:27:18 -0400 Subject: [PATCH 0580/2500] [dev.cmdgo] cmd/go: thread through modroots providing replacements modload.Replacement and modload.resolveReplacement now also return the modroot of the module providing a replacement so that we can correctly construct the path of a replaced module (because the path in the module.Version is relative to the modroot). For #45713 Change-Id: I8c69ccbcc1f40201071e35fcf93d6b5d0ed4cdf7 Reviewed-on: https://go-review.googlesource.com/c/go/+/334941 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/modcmd/vendor.go | 3 +- src/cmd/go/internal/modget/get.go | 4 +- src/cmd/go/internal/modload/build.go | 14 ++--- src/cmd/go/internal/modload/import.go | 5 +- src/cmd/go/internal/modload/init.go | 14 +++-- src/cmd/go/internal/modload/load.go | 4 +- src/cmd/go/internal/modload/modfile.go | 72 +++++++++++++++----------- src/cmd/go/internal/modload/query.go | 10 ++-- src/cmd/go/internal/modload/vendor.go | 2 +- 9 files changed, 74 insertions(+), 54 deletions(-) diff --git a/src/cmd/go/internal/modcmd/vendor.go b/src/cmd/go/internal/modcmd/vendor.go index 6273afbbe6..774fc3052f 100644 --- a/src/cmd/go/internal/modcmd/vendor.go +++ b/src/cmd/go/internal/modcmd/vendor.go @@ -128,7 +128,8 @@ func runVendor(ctx context.Context, cmd *base.Command, args []string) { } for _, m := range vendorMods { - line := moduleLine(m, modload.Replacement(m)) + replacement, _ := modload.Replacement(m) + line := moduleLine(m, replacement) io.WriteString(w, line) goVersion := "" diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index 3c8b5a7090..6eae44f1a4 100644 --- a/src/cmd/go/internal/modget/get.go +++ b/src/cmd/go/internal/modget/get.go @@ -1615,7 +1615,7 @@ func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []strin i := i m := r.buildList[i] mActual := m - if mRepl := modload.Replacement(m); mRepl.Path != "" { + if mRepl, _ := modload.Replacement(m); mRepl.Path != "" { mActual = mRepl } old := module.Version{Path: m.Path, Version: r.initialVersion[m.Path]} @@ -1623,7 +1623,7 @@ func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []strin continue } oldActual := old - if oldRepl := modload.Replacement(old); oldRepl.Path != "" { + if oldRepl, _ := modload.Replacement(old); oldRepl.Path != "" { oldActual = oldRepl } if mActual == oldActual || mActual.Version == "" || !modfetch.HaveSum(oldActual) { diff --git a/src/cmd/go/internal/modload/build.go b/src/cmd/go/internal/modload/build.go index a5c5ad9b44..2973586479 100644 --- a/src/cmd/go/internal/modload/build.go +++ b/src/cmd/go/internal/modload/build.go @@ -241,7 +241,7 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li } // completeFromModCache fills in the extra fields in m using the module cache. - completeFromModCache := func(m *modinfo.ModulePublic) { + completeFromModCache := func(m *modinfo.ModulePublic, replacedFrom string) { checksumOk := func(suffix string) bool { return rs == nil || m.Version == "" || cfg.BuildMod == "mod" || modfetch.HaveSum(module.Version{Path: m.Path, Version: m.Version + suffix}) @@ -260,7 +260,7 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li if m.GoVersion == "" && checksumOk("/go.mod") { // Load the go.mod file to determine the Go version, since it hasn't // already been populated from rawGoVersion. - if summary, err := rawGoModSummary(mod); err == nil && summary.goVersion != "" { + if summary, err := rawGoModSummary(mod, replacedFrom); err == nil && summary.goVersion != "" { m.GoVersion = summary.goVersion } } @@ -290,11 +290,11 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li if rs == nil { // If this was an explicitly-versioned argument to 'go mod download' or // 'go list -m', report the actual requested version, not its replacement. - completeFromModCache(info) // Will set m.Error in vendor mode. + completeFromModCache(info, "") // Will set m.Error in vendor mode. return info } - r := Replacement(m) + r, replacedFrom := Replacement(m) if r.Path == "" { if cfg.BuildMod == "vendor" { // It's tempting to fill in the "Dir" field to point within the vendor @@ -303,7 +303,7 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li // interleave packages from different modules if one module path is a // prefix of the other. } else { - completeFromModCache(info) + completeFromModCache(info, "") } return info } @@ -328,7 +328,7 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li info.Replace.GoMod = filepath.Join(info.Replace.Dir, "go.mod") } if cfg.BuildMod != "vendor" { - completeFromModCache(info.Replace) + completeFromModCache(info.Replace, replacedFrom) info.Dir = info.Replace.Dir info.GoMod = info.Replace.GoMod info.Retracted = info.Replace.Retracted @@ -368,7 +368,7 @@ func PackageBuildInfo(path string, deps []string) string { mv = "(devel)" } fmt.Fprintf(&buf, "%s\t%s\t%s", token, m.Path, mv) - if r := Replacement(m); r.Path == "" { + if r, _ := Replacement(m); r.Path == "" { fmt.Fprintf(&buf, "\t%s\n", modfetch.Sum(m)) } else { fmt.Fprintf(&buf, "\n=>\t%s\t%s\t%s\n", r.Path, r.Version, modfetch.Sum(r)) diff --git a/src/cmd/go/internal/modload/import.go b/src/cmd/go/internal/modload/import.go index 088d0c14ec..5741299281 100644 --- a/src/cmd/go/internal/modload/import.go +++ b/src/cmd/go/internal/modload/import.go @@ -479,11 +479,12 @@ func queryImport(ctx context.Context, path string, rs *Requirements) (module.Ver // The package path is not valid to fetch remotely, // so it can only exist in a replaced module, // and we know from the above loop that it is not. + replacement, _ := Replacement(mods[0]) return module.Version{}, &PackageNotInModuleError{ Mod: mods[0], Query: "latest", Pattern: path, - Replacement: Replacement(mods[0]), + Replacement: replacement, } } @@ -652,7 +653,7 @@ func fetch(ctx context.Context, mod module.Version, needSum bool) (dir string, i if modRoot := MainModules.ModRoot(mod); modRoot != "" { return modRoot, true, nil } - if r := Replacement(mod); r.Path != "" { + if r, _ := Replacement(mod); r.Path != "" { if r.Version == "" { dir = r.Path if !filepath.IsAbs(dir) { diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 18b07cb125..de8adbafc4 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -1475,7 +1475,8 @@ func keepSums(ctx context.Context, ld *loader, rs *Requirements, which whichSums for prefix := pkg.path; prefix != "."; prefix = path.Dir(prefix) { if v, ok := rs.rootSelected(prefix); ok && v != "none" { m := module.Version{Path: prefix, Version: v} - keep[resolveReplacement(m)] = true + r, _ := resolveReplacement(m) + keep[r] = true } } continue @@ -1486,7 +1487,8 @@ func keepSums(ctx context.Context, ld *loader, rs *Requirements, which whichSums for prefix := pkg.path; prefix != "."; prefix = path.Dir(prefix) { if v := mg.Selected(prefix); v != "none" { m := module.Version{Path: prefix, Version: v} - keep[resolveReplacement(m)] = true + r, _ := resolveReplacement(m) + keep[r] = true } } } @@ -1498,7 +1500,7 @@ func keepSums(ctx context.Context, ld *loader, rs *Requirements, which whichSums // Save sums for the root modules (or their replacements), but don't // incur the cost of loading the graph just to find and retain the sums. for _, m := range rs.rootModules { - r := resolveReplacement(m) + r, _ := resolveReplacement(m) keep[modkey(r)] = true if which == addBuildListZipSums { keep[r] = true @@ -1511,13 +1513,15 @@ func keepSums(ctx context.Context, ld *loader, rs *Requirements, which whichSums // The requirements from m's go.mod file are present in the module graph, // so they are relevant to the MVS result regardless of whether m was // actually selected. - keep[modkey(resolveReplacement(m))] = true + r, _ := resolveReplacement(m) + keep[modkey(r)] = true } }) if which == addBuildListZipSums { for _, m := range mg.BuildList() { - keep[resolveReplacement(m)] = true + r, _ := resolveReplacement(m) + keep[r] = true } } } diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index 7def3c2625..dd69e2afbf 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -582,7 +582,7 @@ func pathInModuleCache(ctx context.Context, dir string, rs *Requirements) string tryMod := func(m module.Version) (string, bool) { var root string var err error - if repl := Replacement(m); repl.Path != "" && repl.Version == "" { + if repl, _ := Replacement(m); repl.Path != "" && repl.Version == "" { root = repl.Path if !filepath.IsAbs(root) { root = filepath.Join(ModRoot(), root) @@ -1800,7 +1800,7 @@ func (ld *loader) checkMultiplePaths() { firstPath := map[module.Version]string{} for _, mod := range mods { - src := resolveReplacement(mod) + src, _ := resolveReplacement(mod) if prev, ok := firstPath[src]; !ok { firstPath[src] = mod.Path } else if prev != mod.Path { diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index 31e79a3646..bc5c83dffc 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -171,7 +171,7 @@ func CheckRetractions(ctx context.Context, m module.Version) (err error) { // Cannot be retracted. return nil } - if repl := Replacement(module.Version{Path: m.Path}); repl.Path != "" { + if repl, _ := Replacement(module.Version{Path: m.Path}); repl.Path != "" { // All versions of the module were replaced. // Don't load retractions, since we'd just load the replacement. return nil @@ -188,11 +188,11 @@ func CheckRetractions(ctx context.Context, m module.Version) (err error) { // We load the raw file here: the go.mod file may have a different module // path that we expect if the module or its repository was renamed. // We still want to apply retractions to other aliases of the module. - rm, err := queryLatestVersionIgnoringRetractions(ctx, m.Path) + rm, replacedFrom, err := queryLatestVersionIgnoringRetractions(ctx, m.Path) if err != nil { return err } - summary, err := rawGoModSummary(rm) + summary, err := rawGoModSummary(rm, replacedFrom) if err != nil { return err } @@ -290,17 +290,17 @@ func CheckDeprecation(ctx context.Context, m module.Version) (deprecation string // Don't look up deprecation. return "", nil } - if repl := Replacement(module.Version{Path: m.Path}); repl.Path != "" { + if repl, _ := Replacement(module.Version{Path: m.Path}); repl.Path != "" { // All versions of the module were replaced. // We'll look up deprecation separately for the replacement. return "", nil } - latest, err := queryLatestVersionIgnoringRetractions(ctx, m.Path) + latest, replacedFrom, err := queryLatestVersionIgnoringRetractions(ctx, m.Path) if err != nil { return "", err } - summary, err := rawGoModSummary(latest) + summary, err := rawGoModSummary(latest, replacedFrom) if err != nil { return "", err } @@ -317,10 +317,11 @@ func replacement(mod module.Version, index *modFileIndex) (fromVersion string, t return "", module.Version{}, false } -// Replacement returns the replacement for mod, if any, from go.mod. +// Replacement returns the replacement for mod, if any, and and the module root +// directory of the main module containing the replace directive. // If there is no replacement for mod, Replacement returns // a module.Version with Path == "". -func Replacement(mod module.Version) module.Version { +func Replacement(mod module.Version) (module.Version, string) { _ = TODOWorkspaces("support replaces in the go.work file") foundFrom, found, foundModRoot := "", module.Version{}, "" for _, v := range MainModules.Versions() { @@ -331,22 +332,24 @@ func Replacement(mod module.Version) module.Version { _ = TODOWorkspaces("once the go.work file supports replaces, recommend them as a way to override conflicts") base.Errorf("conflicting replacements found for %v in workspace modules defined by %v and %v", mod, modFilePath(foundModRoot), modFilePath(modRoot)) - return found + return found, foundModRoot } found, foundModRoot = r, modRoot } } } - return found + return found, foundModRoot } // resolveReplacement returns the module actually used to load the source code // for m: either m itself, or the replacement for m (iff m is replaced). -func resolveReplacement(m module.Version) module.Version { - if r := Replacement(m); r.Path != "" { - return r +// It also returns the modroot of the module providing the replacement if +// one was found. +func resolveReplacement(m module.Version) (module.Version, string) { + if r, replacedFrom := Replacement(m); r.Path != "" { + return r, replacedFrom } - return m + return m, "" } // indexModFile rebuilds the index of modFile. @@ -533,7 +536,7 @@ func goModSummary(m module.Version) (*modFileSummary, error) { return summary, nil } - actual := resolveReplacement(m) + actual, replacedFrom := resolveReplacement(m) if HasModRoot() && cfg.BuildMod == "readonly" && !inWorkspaceMode() && actual.Version != "" { key := module.Version{Path: actual.Path, Version: actual.Version + "/go.mod"} if !modfetch.HaveSum(key) { @@ -541,7 +544,7 @@ func goModSummary(m module.Version) (*modFileSummary, error) { return nil, module.VersionError(actual, &sumMissingError{suggestion: suggestion}) } } - summary, err := rawGoModSummary(actual) + summary, err := rawGoModSummary(actual, replacedFrom) if err != nil { return nil, err } @@ -605,18 +608,23 @@ func goModSummary(m module.Version) (*modFileSummary, error) { // its dependencies. // // rawGoModSummary cannot be used on the Target module. -func rawGoModSummary(m module.Version) (*modFileSummary, error) { + +func rawGoModSummary(m module.Version, replacedFrom string) (*modFileSummary, error) { if m.Path == "" && MainModules.Contains(m.Path) { panic("internal error: rawGoModSummary called on the Target module") } + type key struct { + m module.Version + replacedFrom string + } type cached struct { summary *modFileSummary err error } - c := rawGoModSummaryCache.Do(m, func() interface{} { + c := rawGoModSummaryCache.Do(key{m, replacedFrom}, func() interface{} { summary := new(modFileSummary) - name, data, err := rawGoModData(m) + name, data, err := rawGoModData(m, replacedFrom) if err != nil { return cached{nil, err} } @@ -666,12 +674,15 @@ var rawGoModSummaryCache par.Cache // module.Version → rawGoModSummary result // // Unlike rawGoModSummary, rawGoModData does not cache its results in memory. // Use rawGoModSummary instead unless you specifically need these bytes. -func rawGoModData(m module.Version) (name string, data []byte, err error) { +func rawGoModData(m module.Version, replacedFrom string) (name string, data []byte, err error) { if m.Version == "" { // m is a replacement module with only a file path. dir := m.Path if !filepath.IsAbs(dir) { - dir = filepath.Join(ModRoot(), dir) + if replacedFrom == "" { + panic(fmt.Errorf("missing module root of main module providing replacement with relative path: %v", dir)) + } + dir = filepath.Join(replacedFrom, dir) } name = filepath.Join(dir, "go.mod") if gomodActual, ok := fsys.OverlayPath(name); ok { @@ -706,19 +717,20 @@ func rawGoModData(m module.Version) (name string, data []byte, err error) { // // If the queried latest version is replaced, // queryLatestVersionIgnoringRetractions returns the replacement. -func queryLatestVersionIgnoringRetractions(ctx context.Context, path string) (latest module.Version, err error) { +func queryLatestVersionIgnoringRetractions(ctx context.Context, path string) (latest module.Version, replacedFrom string, err error) { type entry struct { - latest module.Version - err error + latest module.Version + replacedFrom string // if latest is a replacement + err error } e := latestVersionIgnoringRetractionsCache.Do(path, func() interface{} { ctx, span := trace.StartSpan(ctx, "queryLatestVersionIgnoringRetractions "+path) defer span.Done() - if repl := Replacement(module.Version{Path: path}); repl.Path != "" { + if repl, replFrom := Replacement(module.Version{Path: path}); repl.Path != "" { // All versions of the module were replaced. // No need to query. - return &entry{latest: repl} + return &entry{latest: repl, replacedFrom: replFrom} } // Find the latest version of the module. @@ -730,12 +742,12 @@ func queryLatestVersionIgnoringRetractions(ctx context.Context, path string) (la return &entry{err: err} } latest := module.Version{Path: path, Version: rev.Version} - if repl := resolveReplacement(latest); repl.Path != "" { - latest = repl + if repl, replFrom := resolveReplacement(latest); repl.Path != "" { + latest, replacedFrom = repl, replFrom } - return &entry{latest: latest} + return &entry{latest: latest, replacedFrom: replacedFrom} }).(*entry) - return e.latest, e.err + return e.latest, e.replacedFrom, e.err } var latestVersionIgnoringRetractionsCache par.Cache // path → queryLatestVersionIgnoringRetractions result diff --git a/src/cmd/go/internal/modload/query.go b/src/cmd/go/internal/modload/query.go index a7031856ae..6d6bfe774c 100644 --- a/src/cmd/go/internal/modload/query.go +++ b/src/cmd/go/internal/modload/query.go @@ -513,9 +513,10 @@ func QueryPackages(ctx context.Context, pattern, query string, current func(stri pkgMods, modOnly, err := QueryPattern(ctx, pattern, query, current, allowed) if len(pkgMods) == 0 && err == nil { + replacement, _ := Replacement(modOnly.Mod) return nil, &PackageNotInModuleError{ Mod: modOnly.Mod, - Replacement: Replacement(modOnly.Mod), + Replacement: replacement, Query: query, Pattern: pattern, } @@ -670,9 +671,10 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin if err := firstError(m); err != nil { return r, err } + replacement, _ := Replacement(r.Mod) return r, &PackageNotInModuleError{ Mod: r.Mod, - Replacement: Replacement(r.Mod), + Replacement: replacement, Query: query, Pattern: pattern, } @@ -964,7 +966,7 @@ func moduleHasRootPackage(ctx context.Context, m module.Version) (bool, error) { // we don't need to verify it in go.sum. This makes 'go list -m -u' faster // and simpler. func versionHasGoMod(_ context.Context, m module.Version) (bool, error) { - _, data, err := rawGoModData(m) + _, data, err := rawGoModData(m, "") if err != nil { return false, err } @@ -1093,7 +1095,7 @@ func (rr *replacementRepo) Stat(rev string) (*modfetch.RevInfo, error) { } } - if r := Replacement(module.Version{Path: path, Version: v}); r.Path == "" { + if r, _ := Replacement(module.Version{Path: path, Version: v}); r.Path == "" { return info, err } return rr.replacementStat(v) diff --git a/src/cmd/go/internal/modload/vendor.go b/src/cmd/go/internal/modload/vendor.go index 6dc8b6cf82..b2da3783ea 100644 --- a/src/cmd/go/internal/modload/vendor.go +++ b/src/cmd/go/internal/modload/vendor.go @@ -209,7 +209,7 @@ func checkVendorConsistency(index *modFileIndex, modFile *modfile.File) { } for _, mod := range vendorReplaced { - r := Replacement(mod) + r, _ := Replacement(mod) if r == (module.Version{}) { vendErrorf(mod, "is marked as replaced in vendor/modules.txt, but not replaced in go.mod") continue -- GitLab From 3799012990a324db968b8f377a5faf541cf20ac7 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Wed, 16 Jun 2021 18:46:23 -0400 Subject: [PATCH 0581/2500] [dev.cmdgo] cmd/go: add go mod editwork command go mod editwork behaves similarly to go mod edit: it has flags to change the go version, and add and remove directory and replace directives. For #45713 Change-Id: I1c795c122bfe461d6e87dd731692e0bf1bbe2bf7 Reviewed-on: https://go-review.googlesource.com/c/go/+/334938 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/alldocs.go | 72 ++++++ src/cmd/go/internal/modcmd/editwork.go | 282 +++++++++++++++++++++++ src/cmd/go/internal/modcmd/mod.go | 1 + src/cmd/go/internal/modload/init.go | 6 + src/cmd/go/testdata/script/work_edit.txt | 157 +++++++++++++ 5 files changed, 518 insertions(+) create mode 100644 src/cmd/go/internal/modcmd/editwork.go create mode 100644 src/cmd/go/testdata/script/work_edit.txt diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index af1ee39684..e0973acbf4 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -1032,6 +1032,7 @@ // // download download modules to local cache // edit edit go.mod from tools or scripts +// editwork edit go.work from tools or scripts // graph print module requirement graph // init initialize new module in current directory // initwork initialize workspace file @@ -1191,6 +1192,77 @@ // See https://golang.org/ref/mod#go-mod-edit for more about 'go mod edit'. // // +// Edit go.work from tools or scripts +// +// Usage: +// +// go mod editwork [editing flags] [go.work] +// +// Editwork provides a command-line interface for editing go.work, +// for use primarily by tools or scripts. It only reads go.work; +// it does not look up information about the modules involved. +// If no file is specified, editwork looks for a go.work file in the current +// directory and its parent directories +// +// The editing flags specify a sequence of editing operations. +// +// The -fmt flag reformats the go.work file without making other changes. +// This reformatting is also implied by any other modifications that use or +// rewrite the go.mod file. The only time this flag is needed is if no other +// flags are specified, as in 'go mod editwork -fmt'. +// +// The -directory=path and -dropdirectory=path flags +// add and drop a directory from the go.work files set of module directories. +// +// The -replace=old[@v]=new[@v] flag adds a replacement of the given +// module path and version pair. If the @v in old@v is omitted, a +// replacement without a version on the left side is added, which applies +// to all versions of the old module path. If the @v in new@v is omitted, +// the new path should be a local module root directory, not a module +// path. Note that -replace overrides any redundant replacements for old[@v], +// so omitting @v will drop existing replacements for specific versions. +// +// The -dropreplace=old[@v] flag drops a replacement of the given +// module path and version pair. If the @v is omitted, a replacement without +// a version on the left side is dropped. +// +// The -directory, -dropdirectory, -replace, and -dropreplace, +// editing flags may be repeated, and the changes are applied in the order given. +// +// The -go=version flag sets the expected Go language version. +// +// The -print flag prints the final go.work in its text format instead of +// writing it back to go.mod. +// +// The -json flag prints the final go.work file in JSON format instead of +// writing it back to go.mod. The JSON output corresponds to these Go types: +// +// type Module struct { +// Path string +// Version string +// } +// +// type GoWork struct { +// Go string +// Directory []Directory +// Replace []Replace +// } +// +// type Directory struct { +// Path string +// ModulePath string +// } +// +// type Replace struct { +// Old Module +// New Module +// } +// +// See the workspaces design proposal at +// https://go.googlesource.com/proposal/+/master/design/45713-workspace.md for +// more information. +// +// // Print module requirement graph // // Usage: diff --git a/src/cmd/go/internal/modcmd/editwork.go b/src/cmd/go/internal/modcmd/editwork.go new file mode 100644 index 0000000000..f05d9245e7 --- /dev/null +++ b/src/cmd/go/internal/modcmd/editwork.go @@ -0,0 +1,282 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// go mod editwork + +package modcmd + +import ( + "bytes" + "cmd/go/internal/base" + "cmd/go/internal/lockedfile" + "cmd/go/internal/modload" + "context" + "encoding/json" + "errors" + "os" + "strings" + + "golang.org/x/mod/modfile" +) + +var cmdEditwork = &base.Command{ + UsageLine: "go mod editwork [editing flags] [go.work]", + Short: "edit go.work from tools or scripts", + Long: `Editwork provides a command-line interface for editing go.work, +for use primarily by tools or scripts. It only reads go.work; +it does not look up information about the modules involved. +If no file is specified, editwork looks for a go.work file in the current +directory and its parent directories + +The editing flags specify a sequence of editing operations. + +The -fmt flag reformats the go.work file without making other changes. +This reformatting is also implied by any other modifications that use or +rewrite the go.mod file. The only time this flag is needed is if no other +flags are specified, as in 'go mod editwork -fmt'. + +The -directory=path and -dropdirectory=path flags +add and drop a directory from the go.work files set of module directories. + +The -replace=old[@v]=new[@v] flag adds a replacement of the given +module path and version pair. If the @v in old@v is omitted, a +replacement without a version on the left side is added, which applies +to all versions of the old module path. If the @v in new@v is omitted, +the new path should be a local module root directory, not a module +path. Note that -replace overrides any redundant replacements for old[@v], +so omitting @v will drop existing replacements for specific versions. + +The -dropreplace=old[@v] flag drops a replacement of the given +module path and version pair. If the @v is omitted, a replacement without +a version on the left side is dropped. + +The -directory, -dropdirectory, -replace, and -dropreplace, +editing flags may be repeated, and the changes are applied in the order given. + +The -go=version flag sets the expected Go language version. + +The -print flag prints the final go.work in its text format instead of +writing it back to go.mod. + +The -json flag prints the final go.work file in JSON format instead of +writing it back to go.mod. The JSON output corresponds to these Go types: + + type Module struct { + Path string + Version string + } + + type GoWork struct { + Go string + Directory []Directory + Replace []Replace + } + + type Directory struct { + Path string + ModulePath string + } + + type Replace struct { + Old Module + New Module + } + +See the workspaces design proposal at +https://go.googlesource.com/proposal/+/master/design/45713-workspace.md for +more information. +`, +} + +var ( + editworkFmt = cmdEditwork.Flag.Bool("fmt", false, "") + editworkGo = cmdEditwork.Flag.String("go", "", "") + editworkJSON = cmdEditwork.Flag.Bool("json", false, "") + editworkPrint = cmdEditwork.Flag.Bool("print", false, "") + workedits []func(file *modfile.WorkFile) // edits specified in flags +) + +func init() { + cmdEditwork.Run = runEditwork // break init cycle + + cmdEditwork.Flag.Var(flagFunc(flagEditworkDirectory), "directory", "") + cmdEditwork.Flag.Var(flagFunc(flagEditworkDropDirectory), "dropdirectory", "") + cmdEditwork.Flag.Var(flagFunc(flagEditworkReplace), "replace", "") + cmdEditwork.Flag.Var(flagFunc(flagEditworkDropReplace), "dropreplace", "") + + base.AddWorkfileFlag(&cmdEditwork.Flag) +} + +func runEditwork(ctx context.Context, cmd *base.Command, args []string) { + anyFlags := + *editworkGo != "" || + *editworkJSON || + *editworkPrint || + *editworkFmt || + len(workedits) > 0 + + if !anyFlags { + base.Fatalf("go mod edit: no flags specified (see 'go help mod edit').") + } + + if *editworkJSON && *editworkPrint { + base.Fatalf("go mod edit: cannot use both -json and -print") + } + + if len(args) > 1 { + base.Fatalf("go mod edit: too many arguments") + } + var gowork string + if len(args) == 1 { + gowork = args[0] + } else { + modload.InitWorkfile() + gowork = modload.WorkFilePath() + } + + if *editworkGo != "" { + if !modfile.GoVersionRE.MatchString(*editworkGo) { + base.Fatalf(`go mod: invalid -go option; expecting something like "-go %s"`, modload.LatestGoVersion()) + } + } + + data, err := lockedfile.Read(gowork) + if err != nil { + base.Fatalf("go: %v", err) + } + + workFile, err := modfile.ParseWork(gowork, data, nil) + if err != nil { + base.Fatalf("go: errors parsing %s:\n%s", base.ShortPath(gowork), err) + } + + if *editworkGo != "" { + if err := workFile.AddGoStmt(*editworkGo); err != nil { + base.Fatalf("go: internal error: %v", err) + } + } + + if len(workedits) > 0 { + for _, edit := range workedits { + edit(workFile) + } + } + workFile.SortBlocks() + workFile.Cleanup() // clean file after edits + + if *editworkJSON { + editworkPrintJSON(workFile) + return + } + + out := modfile.Format(workFile.Syntax) + + if *editworkPrint { + os.Stdout.Write(out) + return + } + + err = lockedfile.Transform(gowork, func(lockedData []byte) ([]byte, error) { + if !bytes.Equal(lockedData, data) { + return nil, errors.New("go.work changed during editing; not overwriting") + } + return out, nil + }) + if err != nil { + base.Fatalf("go: %v", err) + } +} + +// flagEditworkDirectory implements the -directory flag. +func flagEditworkDirectory(arg string) { + workedits = append(workedits, func(f *modfile.WorkFile) { + if err := f.AddDirectory(arg, ""); err != nil { + base.Fatalf("go mod: -directory=%s: %v", arg, err) + } + }) +} + +// flagEditworkDropDirectory implements the -dropdirectory flag. +func flagEditworkDropDirectory(arg string) { + workedits = append(workedits, func(f *modfile.WorkFile) { + if err := f.DropDirectory(arg); err != nil { + base.Fatalf("go mod: -dropdirectory=%s: %v", arg, err) + } + }) +} + +// flagReplace implements the -replace flag. +func flagEditworkReplace(arg string) { + var i int + if i = strings.Index(arg, "="); i < 0 { + base.Fatalf("go mod: -replace=%s: need old[@v]=new[@w] (missing =)", arg) + } + old, new := strings.TrimSpace(arg[:i]), strings.TrimSpace(arg[i+1:]) + if strings.HasPrefix(new, ">") { + base.Fatalf("go mod: -replace=%s: separator between old and new is =, not =>", arg) + } + oldPath, oldVersion, err := parsePathVersionOptional("old", old, false) + if err != nil { + base.Fatalf("go mod: -replace=%s: %v", arg, err) + } + newPath, newVersion, err := parsePathVersionOptional("new", new, true) + if err != nil { + base.Fatalf("go mod: -replace=%s: %v", arg, err) + } + if newPath == new && !modfile.IsDirectoryPath(new) { + base.Fatalf("go mod: -replace=%s: unversioned new path must be local directory", arg) + } + + workedits = append(workedits, func(f *modfile.WorkFile) { + if err := f.AddReplace(oldPath, oldVersion, newPath, newVersion); err != nil { + base.Fatalf("go mod: -replace=%s: %v", arg, err) + } + }) +} + +// flagDropReplace implements the -dropreplace flag. +func flagEditworkDropReplace(arg string) { + path, version, err := parsePathVersionOptional("old", arg, true) + if err != nil { + base.Fatalf("go mod: -dropreplace=%s: %v", arg, err) + } + workedits = append(workedits, func(f *modfile.WorkFile) { + if err := f.DropReplace(path, version); err != nil { + base.Fatalf("go mod: -dropreplace=%s: %v", arg, err) + } + }) +} + +// editPrintJSON prints the -json output. +func editworkPrintJSON(workFile *modfile.WorkFile) { + var f workfileJSON + if workFile.Go != nil { + f.Go = workFile.Go.Version + } + for _, d := range workFile.Directory { + f.Directory = append(f.Directory, directoryJSON{DiskPath: d.Path, ModPath: d.ModulePath}) + } + + for _, r := range workFile.Replace { + f.Replace = append(f.Replace, replaceJSON{r.Old, r.New}) + } + data, err := json.MarshalIndent(&f, "", "\t") + if err != nil { + base.Fatalf("go: internal error: %v", err) + } + data = append(data, '\n') + os.Stdout.Write(data) +} + +// workfileJSON is the -json output data structure. +type workfileJSON struct { + Go string `json:",omitempty"` + Directory []directoryJSON + Replace []replaceJSON +} + +type directoryJSON struct { + DiskPath string + ModPath string `json:",omitempty"` +} diff --git a/src/cmd/go/internal/modcmd/mod.go b/src/cmd/go/internal/modcmd/mod.go index 3586b44c1a..29aad58324 100644 --- a/src/cmd/go/internal/modcmd/mod.go +++ b/src/cmd/go/internal/modcmd/mod.go @@ -23,6 +23,7 @@ See 'go help modules' for an overview of module functionality. Commands: []*base.Command{ cmdDownload, cmdEdit, + cmdEditwork, cmdGraph, cmdInit, cmdInitwork, diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index de8adbafc4..5dd946215b 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -249,6 +249,12 @@ func InitWorkfile() { } } +// WorkFilePath returns the path of the go.work file, or "" if not in +// workspace mode. WorkFilePath must be called after InitWorkfile. +func WorkFilePath() string { + return workFilePath +} + // Init determines whether module mode is enabled, locates the root of the // current module (if any), sets environment variables for Git subprocesses, and // configures the cfg, codehost, load, modfetch, and search packages for use diff --git a/src/cmd/go/testdata/script/work_edit.txt b/src/cmd/go/testdata/script/work_edit.txt new file mode 100644 index 0000000000..0717086ee7 --- /dev/null +++ b/src/cmd/go/testdata/script/work_edit.txt @@ -0,0 +1,157 @@ +# Test editing go.work files. + +go mod initwork m +cmp go.work go.work.want_initial + +go mod editwork -directory n +cmp go.work go.work.want_directory_n + +go mod editwork -go 1.18 +cmp go.work go.work.want_go_118 + +go mod editwork -dropdirectory m +cmp go.work go.work.want_dropdirectory_m + +go mod editwork -replace=x.1@v1.3.0=y.1@v1.4.0 -replace='x.1@v1.4.0 = ../z' +cmp go.work go.work.want_add_replaces + +go mod editwork -directory n -directory ../a -directory /b -directory c -directory c +cmp go.work go.work.want_multidirectory + +go mod editwork -dropdirectory /b -dropdirectory n +cmp go.work go.work.want_multidropdirectory + +go mod editwork -dropreplace='x.1@v1.4.0' +cmp go.work go.work.want_dropreplace + +go mod editwork -print -go 1.19 -directory b -dropdirectory c -replace 'x.1@v1.4.0 = ../z' -dropreplace x.1 -dropreplace x.1@v1.3.0 +cmp stdout go.work.want_print + +go mod editwork -json -go 1.19 -directory b -dropdirectory c -replace 'x.1@v1.4.0 = ../z' -dropreplace x.1 -dropreplace x.1@v1.3.0 +cmp stdout go.work.want_json + +go mod editwork -print -fmt -workfile unformatted +cmp stdout formatted + +-- go.work.want_initial -- +go 1.17 + +directory m +-- go.work.want_directory_n -- +go 1.17 + +directory ( + m + n +) +-- go.work.want_go_118 -- +go 1.18 + +directory ( + m + n +) +-- go.work.want_dropdirectory_m -- +go 1.18 + +directory n +-- go.work.want_add_replaces -- +go 1.18 + +directory n + +replace ( + x.1 v1.3.0 => y.1 v1.4.0 + x.1 v1.4.0 => ../z +) +-- go.work.want_multidirectory -- +go 1.18 + +directory ( + ../a + /b + c + n +) + +replace ( + x.1 v1.3.0 => y.1 v1.4.0 + x.1 v1.4.0 => ../z +) +-- go.work.want_multidropdirectory -- +go 1.18 + +directory ( + ../a + c +) + +replace ( + x.1 v1.3.0 => y.1 v1.4.0 + x.1 v1.4.0 => ../z +) +-- go.work.want_dropreplace -- +go 1.18 + +directory ( + ../a + c +) + +replace x.1 v1.3.0 => y.1 v1.4.0 +-- go.work.want_print -- +go 1.19 + +directory ( + ../a + b +) + +replace x.1 v1.4.0 => ../z +-- go.work.want_json -- +{ + "Go": "1.19", + "Directory": [ + { + "DiskPath": "../a" + }, + { + "DiskPath": "b" + } + ], + "Replace": [ + { + "Old": { + "Path": "x.1", + "Version": "v1.4.0" + }, + "New": { + "Path": "../z" + } + } + ] +} +-- unformatted -- +go 1.17 + directory ( + a + b + c + ) + replace ( + x.1 v1.3.0 => y.1 v1.4.0 + x.1 v1.4.0 => ../z + ) +-- formatted -- +go 1.17 + +directory ( + a + b + c +) + +replace ( + x.1 v1.3.0 => y.1 v1.4.0 + x.1 v1.4.0 => ../z +) \ No newline at end of file -- GitLab From 0b8a9ccb25cd9b8f78eb47b1934522af3fb4108f Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 30 Jul 2021 14:00:27 -0700 Subject: [PATCH 0582/2500] [dev.typeparams] cmd/compile: make all pointer types have the same shape Except unsafe.Pointer. It has a different Kind, which makes it trickier. Change-Id: I12582afb6e591bea35da9e43ac8d141ed19532a3 Reviewed-on: https://go-review.googlesource.com/c/go/+/338749 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/typecheck/subr.go | 6 ++++++ src/cmd/compile/internal/types/identity.go | 2 +- test/typeparam/shape1.go | 19 ++++++++++++++++++- test/typeparam/shape1.out | 2 ++ 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index e2f0a57e71..5ee4152e1c 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1351,6 +1351,12 @@ func Shapify(t *types.Type) *types.Type { // Map all types with the same underlying type to the same shape. u := t.Underlying() + // All pointers have the same shape. + // TODO: Make unsafe.Pointer the same shape as normal pointers. + if u.Kind() == types.TPTR { + u = types.Types[types.TUINT8].PtrTo() + } + if s := shaped[u]; s != nil { return s //TODO: keep? } diff --git a/src/cmd/compile/internal/types/identity.go b/src/cmd/compile/internal/types/identity.go index 0a78092f07..dc39acced8 100644 --- a/src/cmd/compile/internal/types/identity.go +++ b/src/cmd/compile/internal/types/identity.go @@ -31,7 +31,7 @@ func identical(t1, t2 *Type, cmpTags bool, assumedEqual map[typePair]struct{}) b if t1.sym != nil || t2.sym != nil { if t1.HasShape() || t2.HasShape() { switch t1.kind { - case TINT8, TUINT8, TINT16, TUINT16, TINT32, TUINT32, TINT64, TUINT64, TINT, TUINT, TUINTPTR, TCOMPLEX64, TCOMPLEX128, TFLOAT32, TFLOAT64, TBOOL, TSTRING, TUNSAFEPTR: + case TINT8, TUINT8, TINT16, TUINT16, TINT32, TUINT32, TINT64, TUINT64, TINT, TUINT, TUINTPTR, TCOMPLEX64, TCOMPLEX128, TFLOAT32, TFLOAT64, TBOOL, TSTRING, TPTR, TUNSAFEPTR: return true } // fall through to unnamed type comparison for complex types. diff --git a/test/typeparam/shape1.go b/test/typeparam/shape1.go index 3c9e71ea63..de1ea65ed2 100644 --- a/test/typeparam/shape1.go +++ b/test/typeparam/shape1.go @@ -10,7 +10,8 @@ type I interface { foo() int } -// There should be a single instantiation of f in this program. +// There should be one instantiation of f for both squarer and doubler. +// Similarly, there should be one instantiation of f for both *incrementer and *decrementer. func f[T I](x T) int { return x.foo() } @@ -27,7 +28,23 @@ func (x doubler) foo() int { return int(2*x) } +type incrementer int16 + +func (x *incrementer) foo() int { + return int(*x+1) +} + +type decrementer int32 + +func (x *decrementer) foo() int{ + return int(*x-1) +} + func main() { println(f(squarer(5))) println(f(doubler(5))) + var i incrementer = 5 + println(f(&i)) + var d decrementer = 5 + println(f(&d)) } diff --git a/test/typeparam/shape1.out b/test/typeparam/shape1.out index 28391fde66..da9a12ded5 100644 --- a/test/typeparam/shape1.out +++ b/test/typeparam/shape1.out @@ -1,2 +1,4 @@ 25 10 +6 +4 -- GitLab From aa3d54da07bea208cd7c5860875b2d3fbbfeb825 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 9 Jun 2021 20:01:12 -0400 Subject: [PATCH 0583/2500] [dev.typeparams] runtime: rewrite softfloat functions to avoid using floats Currently, most softfloat functions take uint32/64 arguments (for bit representation of float32/64) and operate on uint32/64. But there are exeptions where the function take float arguments and operate on float. So they are only actually softfloat if the helper functions themselves are translated (by the compiler's softfloat mode). These are mostly fine (besides being a bit convoluted). But with register ABIs this inconsistency adds complexity to the compiler to generate such calls, because it needs to be called with the right ABI. Rewrite the functions to operate on uint32/64 directly, using other helper functions. So they all take uint32/64 arguments and return uint32/64. Change-Id: Id9383b74bcbafee44160cc5b58ab245bffbbdfd2 Reviewed-on: https://go-review.googlesource.com/c/go/+/327273 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: David Chase --- src/runtime/softfloat64.go | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/runtime/softfloat64.go b/src/runtime/softfloat64.go index 13bee6c1d7..084aa132d9 100644 --- a/src/runtime/softfloat64.go +++ b/src/runtime/softfloat64.go @@ -562,36 +562,38 @@ func f64toint64(x uint64) int64 { return val } -func f64touint64(x float64) uint64 { - if x < float64(1<<63) { - return uint64(int64(x)) +func f64touint64(x uint64) uint64 { + var m uint64 = 0x43e0000000000000 // float64 1<<63 + if fgt64(m, x) { + return uint64(f64toint64(x)) } - y := x - float64(1<<63) - z := uint64(int64(y)) + y := fadd64(x, -m) + z := uint64(f64toint64(y)) return z | (1 << 63) } -func f32touint64(x float32) uint64 { - if x < float32(1<<63) { - return uint64(int64(x)) +func f32touint64(x uint32) uint64 { + var m uint32 = 0x5f000000 // float32 1<<63 + if fgt32(m, x) { + return uint64(f32toint64(x)) } - y := x - float32(1<<63) - z := uint64(int64(y)) + y := fadd32(x, -m) + z := uint64(f32toint64(y)) return z | (1 << 63) } -func fuint64to64(x uint64) float64 { +func fuint64to64(x uint64) uint64 { if int64(x) >= 0 { - return float64(int64(x)) + return fint64to64(int64(x)) } - // See ../cmd/compile/internal/gc/ssa.go:uint64Tofloat + // See ../cmd/compile/internal/ssagen/ssa.go:uint64Tofloat y := x & 1 z := x >> 1 z = z | y - r := float64(int64(z)) - return r + r + r := fint64to64(int64(z)) + return fadd64(r, r) } -func fuint64to32(x uint64) float32 { - return float32(fuint64to64(x)) +func fuint64to32(x uint64) uint32 { + return f64to32(fuint64to64(x)) } -- GitLab From 283991bd7fb5f0004a8d6c27a8b8038e4d448719 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 29 Jul 2021 11:14:54 -0700 Subject: [PATCH 0584/2500] [dev.typeparams] cmd/compile/internal/types2: print constraint info for type param operands Change-Id: Ic7a249fc150b526835db744431bef500c20fbd26 Reviewed-on: https://go-review.googlesource.com/c/go/+/338309 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/operand.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/types2/operand.go b/src/cmd/compile/internal/types2/operand.go index 01c720d1f7..34d35b2594 100644 --- a/src/cmd/compile/internal/types2/operand.go +++ b/src/cmd/compile/internal/types2/operand.go @@ -176,16 +176,20 @@ func operandString(x *operand, qf Qualifier) string { if hasType { if x.typ != Typ[Invalid] { var intro string - switch { - case isGeneric(x.typ): - intro = " of generic type " - case asTypeParam(x.typ) != nil: - intro = " of type parameter type " - default: + var tpar *TypeParam + if isGeneric(x.typ) { + intro = " of parameterized type " + } else if tpar = asTypeParam(x.typ); tpar != nil { + intro = " of type parameter " + } else { intro = " of type " } buf.WriteString(intro) WriteType(&buf, x.typ, qf) + if tpar != nil { + buf.WriteString(" constrained by ") + WriteType(&buf, tpar.bound, qf) // do not compute interface type sets here + } } else { buf.WriteString(" with invalid type") } -- GitLab From 156eeb40a6d918bcac82871af1b8e428a5414159 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sun, 1 Aug 2021 20:29:07 -0700 Subject: [PATCH 0585/2500] [dev.typeparams] cmd/compile: make HasShape() more efficient by implementing with a type flag Implement HasShape() similar to how HasTParam() is implemented. Fixes #47456 Change-Id: Icbd538574237faad2c4cd8c8e187725a1df47637 Reviewed-on: https://go-review.googlesource.com/c/go/+/339029 Reviewed-by: Keith Randall Trust: Dan Scales --- src/cmd/compile/internal/typecheck/subr.go | 1 + src/cmd/compile/internal/types/type.go | 106 ++++++++++----------- 2 files changed, 54 insertions(+), 53 deletions(-) diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 5ee4152e1c..968d7a0d6d 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1367,6 +1367,7 @@ func Shapify(t *types.Type) *types.Type { s := types.NewNamed(name) s.SetUnderlying(u) s.SetIsShape(true) + s.SetHasShape(true) name.SetType(s) name.SetTypecheck(1) // TODO: add methods to s that the bound has? diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 58ac4db95a..1f01498ca1 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -211,6 +211,7 @@ const ( typeRecur typeHasTParam // there is a typeparam somewhere in the type (generic function or type) typeIsShape // represents a set of closely related types, for generics + typeHasShape // there is a shape somewhere in the type ) func (t *Type) NotInHeap() bool { return t.flags&typeNotInHeap != 0 } @@ -220,17 +221,21 @@ func (t *Type) Deferwidth() bool { return t.flags&typeDeferwidth != 0 } func (t *Type) Recur() bool { return t.flags&typeRecur != 0 } func (t *Type) HasTParam() bool { return t.flags&typeHasTParam != 0 } func (t *Type) IsShape() bool { return t.flags&typeIsShape != 0 } +func (t *Type) HasShape() bool { return t.flags&typeHasShape != 0 } func (t *Type) SetNotInHeap(b bool) { t.flags.set(typeNotInHeap, b) } func (t *Type) SetBroke(b bool) { t.flags.set(typeBroke, b) } func (t *Type) SetNoalg(b bool) { t.flags.set(typeNoalg, b) } func (t *Type) SetDeferwidth(b bool) { t.flags.set(typeDeferwidth, b) } func (t *Type) SetRecur(b bool) { t.flags.set(typeRecur, b) } -func (t *Type) SetIsShape(b bool) { t.flags.set(typeIsShape, b) } // Generic types should never have alg functions. func (t *Type) SetHasTParam(b bool) { t.flags.set(typeHasTParam, b); t.flags.set(typeNoalg, b) } +// Should always do SetHasShape(true) when doing SeIsShape(true). +func (t *Type) SetIsShape(b bool) { t.flags.set(typeIsShape, b) } +func (t *Type) SetHasShape(b bool) { t.flags.set(typeHasShape, b) } + // Kind returns the kind of type t. func (t *Type) Kind() Kind { return t.kind } @@ -271,9 +276,6 @@ func (t *Type) SetRParams(rparams []*Type) { base.Fatalf("Setting nil or zero-length rparams") } t.rparams = &rparams - if t.HasTParam() { - return - } // HasTParam should be set if any rparam is or has a type param. This is // to handle the case of a generic type which doesn't reference any of its // type params (e.g. most commonly, an empty struct). @@ -282,6 +284,10 @@ func (t *Type) SetRParams(rparams []*Type) { t.SetHasTParam(true) break } + if rparam.HasShape() { + t.SetHasShape(true) + break + } } } @@ -624,6 +630,9 @@ func NewArray(elem *Type, bound int64) *Type { if elem.HasTParam() { t.SetHasTParam(true) } + if elem.HasShape() { + t.SetHasShape(true) + } return t } @@ -642,6 +651,9 @@ func NewSlice(elem *Type) *Type { if elem.HasTParam() { t.SetHasTParam(true) } + if elem.HasShape() { + t.SetHasShape(true) + } return t } @@ -654,6 +666,9 @@ func NewChan(elem *Type, dir ChanDir) *Type { if elem.HasTParam() { t.SetHasTParam(true) } + if elem.HasShape() { + t.SetHasShape(true) + } return t } @@ -664,6 +679,9 @@ func NewTuple(t1, t2 *Type) *Type { if t1.HasTParam() || t2.HasTParam() { t.SetHasTParam(true) } + if t1.HasShape() || t2.HasShape() { + t.SetHasShape(true) + } return t } @@ -695,6 +713,9 @@ func NewMap(k, v *Type) *Type { if k.HasTParam() || v.HasTParam() { t.SetHasTParam(true) } + if k.HasShape() || v.HasShape() { + t.SetHasShape(true) + } return t } @@ -719,6 +740,9 @@ func NewPtr(elem *Type) *Type { // when this entry was cached. t.SetHasTParam(true) } + if elem.HasShape() { + t.SetHasShape(true) + } return t } @@ -732,6 +756,9 @@ func NewPtr(elem *Type) *Type { if elem.HasTParam() { t.SetHasTParam(true) } + if elem.HasShape() { + t.SetHasShape(true) + } return t } @@ -1768,6 +1795,9 @@ func (t *Type) SetUnderlying(underlying *Type) { if underlying.HasTParam() { t.SetHasTParam(true) } + if underlying.HasShape() { + t.SetHasShape(true) + } // spec: "The declared type does not inherit any methods bound // to the existing type, but the method set of an interface @@ -1799,6 +1829,15 @@ func fieldsHasTParam(fields []*Field) bool { return false } +func fieldsHasShape(fields []*Field) bool { + for _, f := range fields { + if f.Type != nil && f.Type.HasShape() { + return true + } + } + return false +} + // NewBasic returns a new basic type of the given kind. func NewBasic(kind Kind, obj Object) *Type { t := New(kind) @@ -1818,6 +1857,10 @@ func NewInterface(pkg *Pkg, methods []*Field) *Type { t.SetHasTParam(true) break } + if f.Type != nil && f.Type.HasShape() { + t.SetHasShape(true) + break + } } if anyBroke(methods) { t.SetBroke(true) @@ -1923,6 +1966,9 @@ func NewSignature(pkg *Pkg, recv *Field, tparams, params, results []*Field) *Typ fieldsHasTParam(results) { t.SetHasTParam(true) } + if fieldsHasShape(recvs) || fieldsHasShape(params) || fieldsHasShape(results) { + t.SetHasShape(true) + } return t } @@ -1938,6 +1984,9 @@ func NewStruct(pkg *Pkg, fields []*Field) *Type { if fieldsHasTParam(fields) { t.SetHasTParam(true) } + if fieldsHasShape(fields) { + t.SetHasShape(true) + } return t } @@ -2150,52 +2199,3 @@ var ( ) var SimType [NTYPE]Kind - -// Reports whether t has a shape type anywere. -func (t *Type) HasShape() bool { - return t.HasShape1(map[*Type]bool{}) -} -func (t *Type) HasShape1(visited map[*Type]bool) bool { - if t.IsShape() { - return true - } - if visited[t] { - return false - } - visited[t] = true - if t.Sym() != nil { - for _, u := range t.RParams() { - if u.HasShape1(visited) { - return true - } - } - } - switch t.Kind() { - case TPTR, TARRAY, TSLICE, TCHAN: - return t.Elem().HasShape1(visited) - case TMAP: - return t.Elem().HasShape1(visited) || t.Key().HasShape1(visited) - case TSTRUCT: - for _, f := range t.FieldSlice() { - if f.Type.HasShape1(visited) { - return true - } - } - case TFUNC: - for _, a := range RecvsParamsResults { - for _, f := range a(t).FieldSlice() { - if f.Type.HasShape1(visited) { - return true - } - } - } - case TINTER: - for _, f := range t.Methods().Slice() { - if f.Type.HasShape1(visited) { - return true - } - } - return false - } - return false -} -- GitLab From c3c19731a9dd128b5b81c9062416804a5a4893d2 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 29 Jul 2021 22:24:37 -0700 Subject: [PATCH 0586/2500] [dev.typeparams] cmd/compile/internal/types2: move instance.go contents into named.go (cleanup) This just moves the code around the instance type into named.go where it belongs. While at it, also removed some left-over references to instance types (which are gone). Removed instance.go. Change-Id: I302a86ca50675b0be54f6138fa47f48f00f9c98f Reviewed-on: https://go-review.googlesource.com/c/go/+/338469 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/instance.go | 42 ------------------- src/cmd/compile/internal/types2/named.go | 38 ++++++++++++++++- src/cmd/compile/internal/types2/predicates.go | 6 --- src/cmd/compile/internal/types2/unify.go | 3 -- 4 files changed, 37 insertions(+), 52 deletions(-) delete mode 100644 src/cmd/compile/internal/types2/instance.go diff --git a/src/cmd/compile/internal/types2/instance.go b/src/cmd/compile/internal/types2/instance.go deleted file mode 100644 index 40e89289a2..0000000000 --- a/src/cmd/compile/internal/types2/instance.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package types2 - -// TODO(rfindley): move this code to named.go. - -import "cmd/compile/internal/syntax" - -// instance holds position information for use in lazy instantiation. -// -// TODO(rfindley): come up with a better name for this type, now that its usage -// has changed. -type instance struct { - pos syntax.Pos // position of type instantiation; for error reporting only - posList []syntax.Pos // position of each targ; for error reporting only -} - -// expand ensures that the underlying type of n is instantiated. -// The underlying type will be Typ[Invalid] if there was an error. -func (n *Named) expand() { - if n.instance != nil { - // n must be loaded before instantiation, in order to have accurate - // tparams. This is done implicitly by the call to n.TParams, but making it - // explicit is harmless: load is idempotent. - n.load() - inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams().list(), n.targs, n.instance.posList) - n.underlying = inst - n.fromRHS = inst - n.instance = nil - } -} - -// expand expands uninstantiated named types and leaves all other types alone. -// expand does not recurse. -func expand(typ Type) Type { - if t, _ := typ.(*Named); t != nil { - t.expand() - } - return typ -} diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index 96f2db1429..8ded197df5 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -4,7 +4,10 @@ package types2 -import "sync" +import ( + "cmd/compile/internal/syntax" + "sync" +) // TODO(gri) Clean up Named struct below; specifically the fromRHS field (can we use underlying?). @@ -252,3 +255,36 @@ func (n *Named) setUnderlying(typ Type) { n.underlying = typ } } + +// instance holds position information for use in lazy instantiation. +// +// TODO(rfindley): come up with a better name for this type, now that its usage +// has changed. +type instance struct { + pos syntax.Pos // position of type instantiation; for error reporting only + posList []syntax.Pos // position of each targ; for error reporting only +} + +// expand ensures that the underlying type of n is instantiated. +// The underlying type will be Typ[Invalid] if there was an error. +func (n *Named) expand() { + if n.instance != nil { + // n must be loaded before instantiation, in order to have accurate + // tparams. This is done implicitly by the call to n.TParams, but making it + // explicit is harmless: load is idempotent. + n.load() + inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams().list(), n.targs, n.instance.posList) + n.underlying = inst + n.fromRHS = inst + n.instance = nil + } +} + +// expand expands uninstantiated named types and leaves all other types alone. +// expand does not recurse. +func expand(typ Type) Type { + if t, _ := typ.(*Named); t != nil { + t.expand() + } + return typ +} diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 84342b2796..bb7fedda3b 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -57,9 +57,6 @@ func isNumericOrString(typ Type) bool { return is(typ, IsNumeric|IsString) } func isTyped(typ Type) bool { // isTyped is called with types that are not fully // set up. Must not call asBasic()! - // A *Named or *instance type is always typed, so - // we only need to check if we have a true *Basic - // type. t, _ := typ.(*Basic) return t == nil || t.info&IsUntyped == 0 } @@ -328,9 +325,6 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { case *TypeParam: // nothing to do (x and y being equal is caught in the very beginning of this function) - // case *instance: - // unreachable since types are expanded - case *top: // Either both types are theTop in which case the initial x == y check // will have caught them. Otherwise they are not identical. diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index 7221356354..aa9a23d243 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -459,9 +459,6 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { // are identical if they originate in the same declaration. return x == y - // case *instance: - // unreachable since types are expanded - case nil: // avoid a crash in case of nil type -- GitLab From e56234a30544c043b45601ce01601e3a03e00d63 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 2 Aug 2021 11:07:45 -0700 Subject: [PATCH 0587/2500] [dev.typeparams] cmd/compile: simple shape cleanups - Changed some early returns to asserts (instantiateMethods and Shapify should never take a shape arg) - Added suggested change (by Ingo) to use copy() in getInstantiation() - Clarified that shape types never have methods in Shapify(), removed some TODO comments. Change-Id: Ia2164ffe670a777f7797bbb45c7ef5e6e9e15357 Reviewed-on: https://go-review.googlesource.com/c/go/+/338971 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 9 ++------- src/cmd/compile/internal/typecheck/subr.go | 10 +++++----- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 037f309a82..c006c4af44 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -474,10 +474,7 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { func (g *irgen) instantiateMethods() { for i := 0; i < len(g.instTypeList); i++ { typ := g.instTypeList[i] - if typ.HasShape() { - // Shape types should not have any methods. - continue - } + assert(!typ.HasShape()) // Mark runtime type as needed, since this ensures that the // compiler puts out the needed DWARF symbols, when this // instantiated type has a different package from the local @@ -782,9 +779,7 @@ func (g *irgen) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMeth if !t.HasShape() { if s1 == nil { s1 = make([]*types.Type, len(shapes)) - for j := 0; j < i; j++ { - s1[j] = shapes[j] - } + copy(s1[0:i], shapes[0:i]) } s1[i] = typecheck.Shapify(t) } else if s1 != nil { diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 968d7a0d6d..25db24259c 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1338,6 +1338,9 @@ func genericTypeName(sym *types.Sym) string { // Shapify takes a concrete type and returns a GCshape type that can // be used in place of the input type and still generate identical code. +// No methods are added - all methods calls directly on a shape should +// be done by converting to an interface using the dictionary. +// // TODO: this could take the generic function and base its decisions // on how that generic function uses this type argument. For instance, // if it doesn't use it as a function argument/return value, then @@ -1345,9 +1348,7 @@ func genericTypeName(sym *types.Sym) string { // differ in how they get passed as arguments). For now, we only // unify two different types if they are identical in every possible way. func Shapify(t *types.Type) *types.Type { - if t.IsShape() { - return t // TODO: is this right? - } + assert(!t.HasShape()) // Map all types with the same underlying type to the same shape. u := t.Underlying() @@ -1358,7 +1359,7 @@ func Shapify(t *types.Type) *types.Type { } if s := shaped[u]; s != nil { - return s //TODO: keep? + return s } sym := Lookup(fmt.Sprintf(".shape%d", snum)) @@ -1370,7 +1371,6 @@ func Shapify(t *types.Type) *types.Type { s.SetHasShape(true) name.SetType(s) name.SetTypecheck(1) - // TODO: add methods to s that the bound has? shaped[u] = s return s } -- GitLab From 1b193598b3a4ad3138626ca97bca752e9e63b21c Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 2 Aug 2021 18:01:46 -0700 Subject: [PATCH 0588/2500] [dev.typeparams] cmd/compile: fail early on unexpected types2.Invalid In unified IR, fail right away if we find a types2.Invalid while writing out the package. This provides a clearer error message for https://github.com/golang/go/issues/25838#issuecomment-448746670. Updates #25838. Change-Id: I6902fdd891fc31bbb832b6fdba00eca301282409 Reviewed-on: https://go-review.googlesource.com/c/go/+/338973 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/noder/writer.go | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 07d4363f89..eb1db623b4 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -282,18 +282,22 @@ func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo { base.Fatalf("unexpected type: %v (%T)", typ, typ) case *types2.Basic: - if kind := typ.Kind(); types2.Typ[kind] == typ { + switch kind := typ.Kind(); { + case kind == types2.Invalid: + base.Fatalf("unexpected types2.Invalid") + + case types2.Typ[kind] == typ: w.code(typeBasic) w.len(int(kind)) - break - } - // Handle "byte" and "rune" as references to their TypeName. - obj := types2.Universe.Lookup(typ.Name()) - assert(obj.Type() == typ) + default: + // Handle "byte" and "rune" as references to their TypeName. + obj := types2.Universe.Lookup(typ.Name()) + assert(obj.Type() == typ) - w.code(typeNamed) - w.obj(obj, nil) + w.code(typeNamed) + w.obj(obj, nil) + } case *types2.Named: // Type aliases can refer to uninstantiated generic types, so we -- GitLab From 656f0888b7de3b96792c1444bc15fe2e586ab5ef Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 9 Jun 2021 20:14:15 -0400 Subject: [PATCH 0589/2500] [dev.typeparams] cmd/compile: make softfloat mode work with register ABI Previously, softfloat mode does not work with register ABI, mainly because the compiler doesn't know how to pass floating point arguments and results. According to the ABI it should be passed in FP registers, but there isn't any in softfloat mode. This CL makes it work. When softfloat is used, we define the ABI as having 0 floating point registers (because there aren't any). The integer registers are unchanged. So floating point arguments and results are passed in memory. Another option is to pass (the bit representation of) floating point values in integer registers. But this complicates things because it'd need to reorder integer argument registers. Change-Id: Ibecbeccb658c10a868fa7f2dcf75138f719cc809 Reviewed-on: https://go-review.googlesource.com/c/go/+/327274 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: David Chase --- src/cmd/compile/internal/gc/main.go | 3 --- src/cmd/compile/internal/ssa/config.go | 6 ++++- src/cmd/compile/internal/ssa/expand_calls.go | 14 +++++++--- src/cmd/compile/internal/ssa/export_test.go | 2 +- src/cmd/compile/internal/ssa/softfloat.go | 1 + src/cmd/compile/internal/ssagen/ssa.go | 27 +++++++++++++++++--- test/fixedbugs/issue26163.go | 2 +- test/fixedbugs/issue28688.go | 2 +- 8 files changed, 43 insertions(+), 14 deletions(-) diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 68017516df..6a373ce33d 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -160,9 +160,6 @@ func Main(archInit func(*ssagen.ArchInfo)) { dwarf.EnableLogging(base.Debug.DwarfInl != 0) } if base.Debug.SoftFloat != 0 { - if buildcfg.Experiment.RegabiArgs { - log.Fatalf("softfloat mode with GOEXPERIMENT=regabiargs not implemented ") - } ssagen.Arch.SoftFloat = true } diff --git a/src/cmd/compile/internal/ssa/config.go b/src/cmd/compile/internal/ssa/config.go index b08a394368..32e3a0860e 100644 --- a/src/cmd/compile/internal/ssa/config.go +++ b/src/cmd/compile/internal/ssa/config.go @@ -171,7 +171,7 @@ type Frontend interface { } // NewConfig returns a new configuration object for the given architecture. -func NewConfig(arch string, types Types, ctxt *obj.Link, optimize bool) *Config { +func NewConfig(arch string, types Types, ctxt *obj.Link, optimize, softfloat bool) *Config { c := &Config{arch: arch, Types: types} c.useAvg = true c.useHmul = true @@ -320,6 +320,10 @@ func NewConfig(arch string, types Types, ctxt *obj.Link, optimize bool) *Config c.optimize = optimize c.useSSE = true c.UseFMA = true + c.SoftFloat = softfloat + if softfloat { + c.floatParamRegs = nil // no FP registers in softfloat mode + } c.ABI0 = abi.NewABIConfig(0, 0, ctxt.FixedFrameSize()) c.ABI1 = abi.NewABIConfig(len(c.intParamRegs), len(c.floatParamRegs), ctxt.FixedFrameSize()) diff --git a/src/cmd/compile/internal/ssa/expand_calls.go b/src/cmd/compile/internal/ssa/expand_calls.go index 7e973ab205..a8c6c26dad 100644 --- a/src/cmd/compile/internal/ssa/expand_calls.go +++ b/src/cmd/compile/internal/ssa/expand_calls.go @@ -215,7 +215,7 @@ func (x *expandState) isAlreadyExpandedAggregateType(t *types.Type) bool { return false } return t.IsStruct() || t.IsArray() || t.IsComplex() || t.IsInterface() || t.IsString() || t.IsSlice() || - t.Size() > x.regSize && t.IsInteger() + (t.Size() > x.regSize && (t.IsInteger() || (x.f.Config.SoftFloat && t.IsFloat()))) } // offsetFrom creates an offset from a pointer, simplifying chained offsets and offsets from SP @@ -380,6 +380,12 @@ func (x *expandState) rewriteSelect(leaf *Value, selector *Value, offset int64, // The OpLoad was created to load the single field of the IData // This case removes that StructSelect. if leafType != selector.Type { + if x.f.Config.SoftFloat && selector.Type.IsFloat() { + if x.debug { + x.Printf("---OpLoad, break\n") + } + break // softfloat pass will take care of that + } x.f.Fatalf("Unexpected Load as selector, leaf=%s, selector=%s\n", leaf.LongString(), selector.LongString()) } leaf.copyOf(selector) @@ -525,11 +531,11 @@ func (x *expandState) rewriteSelect(leaf *Value, selector *Value, offset int64, case OpComplexReal: ls := x.rewriteSelect(leaf, selector.Args[0], offset, regOffset) - locs = x.splitSlots(ls, ".real", 0, leafType) + locs = x.splitSlots(ls, ".real", 0, selector.Type) case OpComplexImag: - ls := x.rewriteSelect(leaf, selector.Args[0], offset+leafType.Width, regOffset+RO_complex_imag) // result is FloatNN, width of result is offset of imaginary part. - locs = x.splitSlots(ls, ".imag", leafType.Width, leafType) + ls := x.rewriteSelect(leaf, selector.Args[0], offset+selector.Type.Width, regOffset+RO_complex_imag) // result is FloatNN, width of result is offset of imaginary part. + locs = x.splitSlots(ls, ".imag", selector.Type.Width, selector.Type) case OpStringLen, OpSliceLen: ls := x.rewriteSelect(leaf, selector.Args[0], offset+x.ptrSize, regOffset+RO_slice_len) diff --git a/src/cmd/compile/internal/ssa/export_test.go b/src/cmd/compile/internal/ssa/export_test.go index 8ed8a0c4a6..6d3c0f3ccb 100644 --- a/src/cmd/compile/internal/ssa/export_test.go +++ b/src/cmd/compile/internal/ssa/export_test.go @@ -39,7 +39,7 @@ func testConfigArch(tb testing.TB, arch string) *Conf { tb.Fatal("testTypes is 64-bit only") } c := &Conf{ - config: NewConfig(arch, testTypes, ctxt, true), + config: NewConfig(arch, testTypes, ctxt, true, false), tb: tb, } return c diff --git a/src/cmd/compile/internal/ssa/softfloat.go b/src/cmd/compile/internal/ssa/softfloat.go index a8a8f83629..351f824a9f 100644 --- a/src/cmd/compile/internal/ssa/softfloat.go +++ b/src/cmd/compile/internal/ssa/softfloat.go @@ -63,6 +63,7 @@ func softfloat(f *Func) { v.Aux = f.Config.Types.UInt32 case 8: v.Aux = f.Config.Types.UInt64 + newInt64 = true default: v.Fatalf("bad float type with size %d", size) } diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 7e2f6a7471..1a0a98f6aa 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -87,8 +87,7 @@ func InitConfig() { _ = types.NewPtr(types.Types[types.TINT64]) // *int64 _ = types.NewPtr(types.ErrorType) // *error types.NewPtrCacheEnabled = false - ssaConfig = ssa.NewConfig(base.Ctxt.Arch.Name, *types_, base.Ctxt, base.Flag.N == 0) - ssaConfig.SoftFloat = Arch.SoftFloat + ssaConfig = ssa.NewConfig(base.Ctxt.Arch.Name, *types_, base.Ctxt, base.Flag.N == 0, Arch.SoftFloat) ssaConfig.Race = base.Flag.Race ssaCaches = make([]ssa.Cache, base.Flag.LowerC) @@ -3653,6 +3652,16 @@ func softfloatInit() { // TODO: do not emit sfcall if operation can be optimized to constant in later // opt phase func (s *state) sfcall(op ssa.Op, args ...*ssa.Value) (*ssa.Value, bool) { + f2i := func(t *types.Type) *types.Type { + switch t.Kind() { + case types.TFLOAT32: + return types.Types[types.TUINT32] + case types.TFLOAT64: + return types.Types[types.TUINT64] + } + return t + } + if callDef, ok := softFloatOps[op]; ok { switch op { case ssa.OpLess32F, @@ -3665,7 +3674,19 @@ func (s *state) sfcall(op ssa.Op, args ...*ssa.Value) (*ssa.Value, bool) { args[1] = s.newValue1(s.ssaOp(ir.ONEG, types.Types[callDef.rtype]), args[1].Type, args[1]) } - result := s.rtcall(callDef.rtfn, true, []*types.Type{types.Types[callDef.rtype]}, args...)[0] + // runtime functions take uints for floats and returns uints. + // Convert to uints so we use the right calling convention. + for i, a := range args { + if a.Type.IsFloat() { + args[i] = s.newValue1(ssa.OpCopy, f2i(a.Type), a) + } + } + + rt := types.Types[callDef.rtype] + result := s.rtcall(callDef.rtfn, true, []*types.Type{f2i(rt)}, args...)[0] + if rt.IsFloat() { + result = s.newValue1(ssa.OpCopy, rt, result) + } if op == ssa.OpNeq32F || op == ssa.OpNeq64F { result = s.newValue1(ssa.OpNot, result.Type, result) } diff --git a/test/fixedbugs/issue26163.go b/test/fixedbugs/issue26163.go index d141a2797d..3f3d77859d 100644 --- a/test/fixedbugs/issue26163.go +++ b/test/fixedbugs/issue26163.go @@ -1,4 +1,4 @@ -// compile -N -d=softfloat -goexperiment noregabiargs +// compile -N -d=softfloat // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/test/fixedbugs/issue28688.go b/test/fixedbugs/issue28688.go index 8ef0802812..0d2000e149 100644 --- a/test/fixedbugs/issue28688.go +++ b/test/fixedbugs/issue28688.go @@ -1,4 +1,4 @@ -// run -gcflags=-d=softfloat -goexperiment noregabiargs +// run -gcflags=-d=softfloat // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style -- GitLab From fe73f28dc5e22ab6b54b7433dd6e63caf5c9da72 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 3 Aug 2021 10:37:33 -0700 Subject: [PATCH 0590/2500] [dev.typeparams] cmd/compile: set sym.Def to ir.Name for method value wrappers The code for generating method value wrappers is weird that it sets sym.Def to the generated ir.Func, whereas normally sym.Def points to ir.Name. While here, change methodValueWrapper to return the ir.Name too, since that's what the caller wants. Change-Id: I3da5320ca0bf4d32d7b420345454f19075d19a26 Reviewed-on: https://go-review.googlesource.com/c/go/+/339410 Trust: Matthew Dempsky Trust: Cuong Manh Le Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/noder/reader.go | 2 +- src/cmd/compile/internal/walk/closure.go | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 516bf8f1f7..83979a91c8 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -2253,7 +2253,7 @@ func (r *reader) methodValueWrapper(tbase *types.Type, method *types.Field, targ pos := base.AutogeneratedPos fn := r.newWrapperFunc(pos, sym, nil, method) - sym.Def = fn + sym.Def = fn.Nname // Declare and initialize variable holding receiver. recv := ir.NewHiddenParam(pos, fn, typecheck.Lookup(".this"), recvType) diff --git a/src/cmd/compile/internal/walk/closure.go b/src/cmd/compile/internal/walk/closure.go index 2d0b2dcc0e..902e01ef38 100644 --- a/src/cmd/compile/internal/walk/closure.go +++ b/src/cmd/compile/internal/walk/closure.go @@ -179,7 +179,7 @@ func walkMethodValue(n *ir.SelectorExpr, init *ir.Nodes) ir.Node { clos := ir.NewCompLitExpr(base.Pos, ir.OCOMPLIT, ir.TypeNode(typ), nil) clos.SetEsc(n.Esc()) - clos.List = []ir.Node{ir.NewUnaryExpr(base.Pos, ir.OCFUNC, methodValueWrapper(n).Nname), n.X} + clos.List = []ir.Node{ir.NewUnaryExpr(base.Pos, ir.OCFUNC, methodValueWrapper(n)), n.X} addr := typecheck.NodAddr(clos) addr.SetEsc(n.Esc()) @@ -199,11 +199,11 @@ func walkMethodValue(n *ir.SelectorExpr, init *ir.Nodes) ir.Node { return walkExpr(cfn, init) } -// methodValueWrapper returns the DCLFUNC node representing the +// methodValueWrapper returns the ONAME node representing the // wrapper function (*-fm) needed for the given method value. If the // wrapper function hasn't already been created yet, it's created and // added to typecheck.Target.Decls. -func methodValueWrapper(dot *ir.SelectorExpr) *ir.Func { +func methodValueWrapper(dot *ir.SelectorExpr) *ir.Name { if dot.Op() != ir.OMETHVALUE { base.Fatalf("methodValueWrapper: unexpected %v (%v)", dot, dot.Op()) } @@ -214,7 +214,7 @@ func methodValueWrapper(dot *ir.SelectorExpr) *ir.Func { sym := ir.MethodSymSuffix(rcvrtype, meth, "-fm") if sym.Uniq() { - return sym.Def.(*ir.Func) + return sym.Def.(*ir.Name) } sym.SetUniq(true) @@ -262,10 +262,10 @@ func methodValueWrapper(dot *ir.SelectorExpr) *ir.Func { // typecheckslice() requires that Curfn is set when processing an ORETURN. ir.CurFunc = fn typecheck.Stmts(fn.Body) - sym.Def = fn + sym.Def = fn.Nname typecheck.Target.Decls = append(typecheck.Target.Decls, fn) ir.CurFunc = savecurfn base.Pos = saveLineNo - return fn + return fn.Nname } -- GitLab From 7ab875402985ea5a31512fb9750dc0f809e06861 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 2 Aug 2021 23:56:13 -0700 Subject: [PATCH 0591/2500] [dev.typeparams] cmd/compile: avoid redundant method wrappers in unified IR Currently, unified IR takes a simple approach of generating method wrappers for every anonymous type that it sees. This is correct, but spends a lot of time in code generation and bloats the object files with duplicate method wrappers that the linker discards. This CL changes it to distinguish anonymous types that were found in imported packages vs the local package. The simple win here is that now we stop emitting wrappers for imported types; but by keeping track of them and marking them as "have" instead of "need", we can avoid emitting wrappers for types that appear in both the local package and imported packages. This can be improved further, but this is a simple first step that prevents large protobuf projects from blowing up build cache limits. Change-Id: Ia65e8981cb1f067eca2bd072b9bbb77c27b95207 Reviewed-on: https://go-review.googlesource.com/c/go/+/339411 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/noder/reader.go | 69 +++++++++++++------ .../compile/internal/reflectdata/reflect.go | 3 +- 2 files changed, 49 insertions(+), 23 deletions(-) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 83979a91c8..5481812b18 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -2125,16 +2125,32 @@ func usedLocals(body []ir.Node) ir.NameSet { // method wrappers. var needWrapperTypes []*types.Type -func (r *reader) needWrapper(typ *types.Type) *types.Type { - // TODO(mdempsky): Be more judicious about generating wrappers. - // For now, generating all possible wrappers is simple and correct, - // but potentially wastes a lot of time/space. +// haveWrapperTypes lists types for which we know we already have +// method wrappers, because we found the type in an imported package. +var haveWrapperTypes []*types.Type +func (r *reader) needWrapper(typ *types.Type) *types.Type { if typ.IsPtr() { base.Fatalf("bad pointer type: %v", typ) } - needWrapperTypes = append(needWrapperTypes, typ) + // If a type was found in an imported package, then we can assume + // that package (or one of its transitive dependencies) already + // generated method wrappers for it. + // + // Exception: If we're instantiating an imported generic type or + // function, we might be instantiating it with type arguments not + // previously seen before. + // + // TODO(mdempsky): Distinguish when a generic function or type was + // instantiated in an imported package so that we can add types to + // haveWrapperTypes instead. + if r.p != localPkgReader && !r.hasTypeParams() { + haveWrapperTypes = append(haveWrapperTypes, typ) + } else { + needWrapperTypes = append(needWrapperTypes, typ) + } + return typ } @@ -2143,21 +2159,33 @@ func (r *reader) wrapTypes(target *ir.Package) { r.needWrapper(types.ErrorType) seen := make(map[string]*types.Type) - for _, typ := range needWrapperTypes { - if typ.Sym() == nil { - key := typ.LinkString() - if prev := seen[key]; prev != nil { - if !types.Identical(typ, prev) { - base.Fatalf("collision: types %v and %v have short string %q", typ, prev, key) - } - continue + addType := func(typ *types.Type) bool { + if typ.Sym() != nil { + return true + } + + key := typ.LinkString() + if prev := seen[key]; prev != nil { + if !types.Identical(typ, prev) { + base.Fatalf("collision: types %v and %v have short string %q", typ, prev, key) } - seen[key] = typ + return false } - r.wrapType(typ, target) + seen[key] = typ + return true } + for _, typ := range haveWrapperTypes { + addType(typ) + } + haveWrapperTypes = nil + + for _, typ := range needWrapperTypes { + if addType(typ) { + r.wrapType(typ, target) + } + } needWrapperTypes = nil } @@ -2243,12 +2271,6 @@ func (r *reader) methodValueWrapper(tbase *types.Type, method *types.Field, targ assert(!sym.Uniq()) sym.SetUniq(true) - // TODO(mdempsky): Fix typecheck to not depend on creation of - // imported method value wrappers. - if false && !reflectdata.NeedEmit(tbase) { - return - } - // TODO(mdempsky): Use method.Pos instead? pos := base.AutogeneratedPos @@ -2258,6 +2280,11 @@ func (r *reader) methodValueWrapper(tbase *types.Type, method *types.Field, targ // Declare and initialize variable holding receiver. recv := ir.NewHiddenParam(pos, fn, typecheck.Lookup(".this"), recvType) + if !reflectdata.NeedEmit(tbase) { + typecheck.Func(fn) + return + } + addTailCall(pos, fn, recv, method) r.finishWrapperFunc(fn, target) diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index dca8de74f3..19cf2a0a12 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -1809,9 +1809,8 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy newnam.SetSiggen(true) // Except in quirks mode, unified IR creates its own wrappers. - // Complain loudly if it missed any. if base.Debug.Unified != 0 && base.Debug.UnifiedQuirks == 0 { - base.FatalfAt(method.Pos, "missing wrapper for %+v (%+v, %v) / %+v / %+v", rcvr, orig, types.IsDirectIface(orig), method.Sym, newnam) + return lsym } if !generic && types.Identical(rcvr, method.Type.Recv().Type) { -- GitLab From 4e07341afd65e4000466b6b324781e8c3565a0d9 Mon Sep 17 00:00:00 2001 From: korzhao Date: Tue, 3 Aug 2021 20:56:58 +0000 Subject: [PATCH 0592/2500] [dev.fuzz] cmd/go: 'go clean -fuzzcache' should not delete compiled files This change adds -fuzzcache to the list of flags that prevents 'go clean' from cleaning packages by default. Fixes #47478 Change-Id: I07c9c24ff6359e45e9661b307a671274ab2d7212 GitHub-Last-Rev: 4929618c1fedafc3712a9ffdd1691a92042334eb GitHub-Pull-Request: golang/go#47483 Reviewed-on: https://go-review.googlesource.com/c/go/+/338752 Reviewed-by: Jay Conrod Trust: Jay Conrod Trust: Roland Shoemaker Trust: Bryan C. Mills --- src/cmd/go/internal/clean/clean.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/go/internal/clean/clean.go b/src/cmd/go/internal/clean/clean.go index e0d3c9e0c6..13d6961511 100644 --- a/src/cmd/go/internal/clean/clean.go +++ b/src/cmd/go/internal/clean/clean.go @@ -116,7 +116,7 @@ func runClean(ctx context.Context, cmd *base.Command, args []string) { // or no other target (such as a cache) was requested to be cleaned. cleanPkg := len(args) > 0 || cleanI || cleanR if (!modload.Enabled() || modload.HasModRoot()) && - !cleanCache && !cleanModcache && !cleanTestcache { + !cleanCache && !cleanModcache && !cleanTestcache && !cleanFuzzcache { cleanPkg = true } -- GitLab From 077925e2b008a258f5204aab8a454294b9cdca96 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 26 Jul 2021 12:04:36 -0400 Subject: [PATCH 0593/2500] [dev.typeparams] runtime: remove unnecessary split-prevention from defer code Prior to regabi, the compiler passed defer arguments to the runtime as untyped values on the stack. This meant a lot of defer-related runtime functions had to be very careful not to grow the stack or allow preemption since the stack could not be safely scanned or moved. However, with regabi, every defer is now simply a func() from the runtime's perspective, which means we no longer have untyped values on the stack when we enter defer-related runtime code. Hence, this CL removes a lot of the now-unnecessary carefulness in the defer implementation. Specifically, deferreturn no longer needs to be nosplit because it doesn't copy untyped defer arguments to its caller's frame (we also update some stale comments in deferreturn). freedefer no longer needs to be nosplit because it's none of its callers are deeply nosplit. And newdefer and freedefer no longer need to switch to the systemstack on their slow paths to avoid stack growth. deferprocStack is the only function that still needs to be nosplit, but that's because the compiler calls it with uninitialized live pointer slots on the stack (maybe we should change that, but that's a very different fix). This is a retry of CL 337651, which was rolled back. This version disables preemption in newdefer and freedefer while they hold the current P. Change-Id: Ibf469addc0b69dc3ba9a3d1a5e0c2804b7b4b244 Reviewed-on: https://go-review.googlesource.com/c/go/+/339396 Trust: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/panic.go | 98 ++++++++++++++++++-------------------------- 1 file changed, 40 insertions(+), 58 deletions(-) diff --git a/src/runtime/panic.go b/src/runtime/panic.go index 35f3b44a4d..b77376b598 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -261,10 +261,8 @@ func deferproc(fn func()) { // deferprocStack queues a new deferred function with a defer record on the stack. // The defer record must have its fn field initialized. // All other fields can contain junk. -// The defer record must be immediately followed in memory by -// the arguments of the defer. -// Nosplit because the arguments on the stack won't be scanned -// until the defer record is spliced into the gp._defer list. +// Nosplit because of the uninitialized pointer fields on the stack. +// //go:nosplit func deferprocStack(d *_defer) { gp := getg() @@ -310,27 +308,26 @@ func deferprocStack(d *_defer) { // added to any defer chain yet. func newdefer() *_defer { var d *_defer - gp := getg() - pp := gp.m.p.ptr() + mp := acquirem() + pp := mp.p.ptr() if len(pp.deferpool) == 0 && sched.deferpool != nil { - // Take the slow path on the system stack so - // we don't grow newdefer's stack. - systemstack(func() { - lock(&sched.deferlock) - for len(pp.deferpool) < cap(pp.deferpool)/2 && sched.deferpool != nil { - d := sched.deferpool - sched.deferpool = d.link - d.link = nil - pp.deferpool = append(pp.deferpool, d) - } - unlock(&sched.deferlock) - }) + lock(&sched.deferlock) + for len(pp.deferpool) < cap(pp.deferpool)/2 && sched.deferpool != nil { + d := sched.deferpool + sched.deferpool = d.link + d.link = nil + pp.deferpool = append(pp.deferpool, d) + } + unlock(&sched.deferlock) } if n := len(pp.deferpool); n > 0 { d = pp.deferpool[n-1] pp.deferpool[n-1] = nil pp.deferpool = pp.deferpool[:n-1] } + releasem(mp) + mp, pp = nil, nil + if d == nil { // Allocate new defer. d = new(_defer) @@ -341,11 +338,6 @@ func newdefer() *_defer { // Free the given defer. // The defer cannot be used after this call. -// -// This must not grow the stack because there may be a frame without a -// stack map when this is called. -// -//go:nosplit func freedefer(d *_defer) { if d._panic != nil { freedeferpanic() @@ -356,31 +348,28 @@ func freedefer(d *_defer) { if !d.heap { return } - pp := getg().m.p.ptr() + + mp := acquirem() + pp := mp.p.ptr() if len(pp.deferpool) == cap(pp.deferpool) { // Transfer half of local cache to the central cache. - // - // Take this slow path on the system stack so - // we don't grow freedefer's stack. - systemstack(func() { - var first, last *_defer - for len(pp.deferpool) > cap(pp.deferpool)/2 { - n := len(pp.deferpool) - d := pp.deferpool[n-1] - pp.deferpool[n-1] = nil - pp.deferpool = pp.deferpool[:n-1] - if first == nil { - first = d - } else { - last.link = d - } - last = d + var first, last *_defer + for len(pp.deferpool) > cap(pp.deferpool)/2 { + n := len(pp.deferpool) + d := pp.deferpool[n-1] + pp.deferpool[n-1] = nil + pp.deferpool = pp.deferpool[:n-1] + if first == nil { + first = d + } else { + last.link = d } - lock(&sched.deferlock) - last.link = sched.deferpool - sched.deferpool = first - unlock(&sched.deferlock) - }) + last = d + } + lock(&sched.deferlock) + last.link = sched.deferpool + sched.deferpool = first + unlock(&sched.deferlock) } // These lines used to be simply `*d = _defer{}` but that @@ -398,6 +387,9 @@ func freedefer(d *_defer) { d.link = nil pp.deferpool = append(pp.deferpool, d) + + releasem(mp) + mp, pp = nil, nil } // Separate function so that it can split stack. @@ -420,12 +412,6 @@ func freedeferfn() { // to have been called by the caller of deferreturn at the point // just before deferreturn was called. The effect is that deferreturn // is called again and again until there are no more deferred functions. -// -// Declared as nosplit, because the function should not be preempted once we start -// modifying the caller's frame in order to reuse the frame to call the deferred -// function. -// -//go:nosplit func deferreturn() { gp := getg() d := gp._defer @@ -446,13 +432,6 @@ func deferreturn() { return } - // Moving arguments around. - // - // Everything called after this point must be recursively - // nosplit because the garbage collector won't know the form - // of the arguments until the jmpdefer can flip the PC over to - // fn. - argp := getcallersp() + sys.MinFrameSize fn := d.fn d.fn = nil gp._defer = d.link @@ -462,6 +441,9 @@ func deferreturn() { // called with a callback on an LR architecture and jmpdefer is on the // stack, because jmpdefer manipulates SP (see issue #8153). _ = **(**funcval)(unsafe.Pointer(&fn)) + // We must not split the stack between computing argp and + // calling jmpdefer because argp is a uintptr stack pointer. + argp := getcallersp() + sys.MinFrameSize jmpdefer(fn, argp) } -- GitLab From 1a0630aef474320e71595ed1a4a984fc7c7bbc0a Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 26 Jul 2021 15:44:22 -0400 Subject: [PATCH 0594/2500] [dev.typeparams] runtime,cmd/compile,cmd/link: replace jmpdefer with a loop Currently, deferreturn runs deferred functions by backing up its return PC to the deferreturn call, and then effectively tail-calling the deferred function (via jmpdefer). The effect of this is that the deferred function appears to be called directly from the deferee, and when it returns, the deferee calls deferreturn again so it can run the next deferred function if necessary. This unusual flow control leads to a large number of special cases and complications all over the tool chain. This used to be necessary because deferreturn copied the deferred function's argument frame directly into its caller's frame and then had to invoke that call as if it had been called from its caller's frame so it could access it arguments. But now that we've simplified defer processing so the runtime only deals with argument-less closures, this approach is no longer necessary. This CL simplifies all of this by making deferreturn simply call deferred functions in a loop. This eliminates the need for jmpdefer, so we can delete a bunch of per-architecture assembly code. This eliminates several special cases on Wasm, since it couldn't support these calling shenanigans directly and thus had to simulate the loop a different way. Now Wasm can largely work the way the other platforms do. This eliminates the per-architecture Ginsnopdefer operation. On PPC64, this was necessary to reload the TOC pointer after the tail call (since TOC pointers in general make tail calls impossible). The tail call is gone, and in the case where we do force a jump to the deferreturn call when recovering from an open-coded defer, we go through gogo (via runtime.recovery), which handles the TOC. On other platforms, we needed a NOP so traceback didn't get confused by seeing the return to the CALL instruction, rather than the usual return to the instruction following the CALL instruction. Now we don't inject a return to the CALL instruction at all, so this NOP is also unnecessary. The one potential effect of this is that deferreturn could now appear in stack traces from deferred functions. However, this could already happen from open-coded defers, so we've long since marked deferreturn as a "wrapper" so it gets elided not only from printed stack traces, but from runtime.Callers*. This is a retry of CL 337652 because we had to back out its parent. There are no changes in this version. Change-Id: I3f54b7fec1d7ccac71cc6cf6835c6a46b7e5fb6c Reviewed-on: https://go-review.googlesource.com/c/go/+/339397 Trust: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/compile/internal/amd64/galign.go | 1 - src/cmd/compile/internal/arm/galign.go | 1 - src/cmd/compile/internal/arm64/galign.go | 1 - src/cmd/compile/internal/mips/galign.go | 1 - src/cmd/compile/internal/mips64/galign.go | 1 - src/cmd/compile/internal/ppc64/galign.go | 1 - src/cmd/compile/internal/ppc64/ggen.go | 27 ---------- src/cmd/compile/internal/riscv64/galign.go | 1 - src/cmd/compile/internal/s390x/galign.go | 1 - src/cmd/compile/internal/ssagen/arch.go | 3 +- src/cmd/compile/internal/ssagen/ssa.go | 12 ----- src/cmd/compile/internal/wasm/ssa.go | 7 ++- src/cmd/compile/internal/x86/galign.go | 1 - src/cmd/internal/obj/arm/asm5.go | 11 ++-- src/cmd/internal/obj/wasm/wasmobj.go | 36 -------------- src/cmd/internal/obj/x86/asm6.go | 1 - src/cmd/internal/objabi/funcid.go | 2 - src/cmd/link/internal/ld/pcln.go | 9 ++-- src/runtime/asm_386.s | 20 -------- src/runtime/asm_amd64.s | 15 ------ src/runtime/asm_arm.s | 14 ------ src/runtime/asm_arm64.s | 17 ------- src/runtime/asm_mips64x.s | 16 ------ src/runtime/asm_mipsx.s | 16 ------ src/runtime/asm_ppc64x.s | 28 ----------- src/runtime/asm_riscv64.s | 15 ------ src/runtime/asm_s390x.s | 15 ------ src/runtime/asm_wasm.s | 29 ----------- src/runtime/panic.go | 58 ++++++++++------------ src/runtime/stubs.go | 2 - src/runtime/symtab.go | 1 - 31 files changed, 39 insertions(+), 324 deletions(-) diff --git a/src/cmd/compile/internal/amd64/galign.go b/src/cmd/compile/internal/amd64/galign.go index 3b13e123a7..ca44263afc 100644 --- a/src/cmd/compile/internal/amd64/galign.go +++ b/src/cmd/compile/internal/amd64/galign.go @@ -18,7 +18,6 @@ func Init(arch *ssagen.ArchInfo) { arch.ZeroRange = zerorange arch.Ginsnop = ginsnop - arch.Ginsnopdefer = ginsnop arch.SSAMarkMoves = ssaMarkMoves arch.SSAGenValue = ssaGenValue diff --git a/src/cmd/compile/internal/arm/galign.go b/src/cmd/compile/internal/arm/galign.go index d68500280d..23e52bacbf 100644 --- a/src/cmd/compile/internal/arm/galign.go +++ b/src/cmd/compile/internal/arm/galign.go @@ -18,7 +18,6 @@ func Init(arch *ssagen.ArchInfo) { arch.SoftFloat = buildcfg.GOARM == 5 arch.ZeroRange = zerorange arch.Ginsnop = ginsnop - arch.Ginsnopdefer = ginsnop arch.SSAMarkMoves = func(s *ssagen.State, b *ssa.Block) {} arch.SSAGenValue = ssaGenValue diff --git a/src/cmd/compile/internal/arm64/galign.go b/src/cmd/compile/internal/arm64/galign.go index 2a61b9dd99..3ebd860de8 100644 --- a/src/cmd/compile/internal/arm64/galign.go +++ b/src/cmd/compile/internal/arm64/galign.go @@ -18,7 +18,6 @@ func Init(arch *ssagen.ArchInfo) { arch.PadFrame = padframe arch.ZeroRange = zerorange arch.Ginsnop = ginsnop - arch.Ginsnopdefer = ginsnop arch.SSAMarkMoves = func(s *ssagen.State, b *ssa.Block) {} arch.SSAGenValue = ssaGenValue diff --git a/src/cmd/compile/internal/mips/galign.go b/src/cmd/compile/internal/mips/galign.go index f892923ba0..4e6897042e 100644 --- a/src/cmd/compile/internal/mips/galign.go +++ b/src/cmd/compile/internal/mips/galign.go @@ -21,7 +21,6 @@ func Init(arch *ssagen.ArchInfo) { arch.SoftFloat = (buildcfg.GOMIPS == "softfloat") arch.ZeroRange = zerorange arch.Ginsnop = ginsnop - arch.Ginsnopdefer = ginsnop arch.SSAMarkMoves = func(s *ssagen.State, b *ssa.Block) {} arch.SSAGenValue = ssaGenValue arch.SSAGenBlock = ssaGenBlock diff --git a/src/cmd/compile/internal/mips64/galign.go b/src/cmd/compile/internal/mips64/galign.go index af81366e51..412bc71aab 100644 --- a/src/cmd/compile/internal/mips64/galign.go +++ b/src/cmd/compile/internal/mips64/galign.go @@ -21,7 +21,6 @@ func Init(arch *ssagen.ArchInfo) { arch.SoftFloat = buildcfg.GOMIPS64 == "softfloat" arch.ZeroRange = zerorange arch.Ginsnop = ginsnop - arch.Ginsnopdefer = ginsnop arch.SSAMarkMoves = func(s *ssagen.State, b *ssa.Block) {} arch.SSAGenValue = ssaGenValue diff --git a/src/cmd/compile/internal/ppc64/galign.go b/src/cmd/compile/internal/ppc64/galign.go index 590290fa37..bff3e38f42 100644 --- a/src/cmd/compile/internal/ppc64/galign.go +++ b/src/cmd/compile/internal/ppc64/galign.go @@ -20,7 +20,6 @@ func Init(arch *ssagen.ArchInfo) { arch.ZeroRange = zerorange arch.Ginsnop = ginsnop - arch.Ginsnopdefer = ginsnopdefer arch.SSAMarkMoves = ssaMarkMoves arch.SSAGenValue = ssaGenValue diff --git a/src/cmd/compile/internal/ppc64/ggen.go b/src/cmd/compile/internal/ppc64/ggen.go index c76962cfb8..3ae6422bf9 100644 --- a/src/cmd/compile/internal/ppc64/ggen.go +++ b/src/cmd/compile/internal/ppc64/ggen.go @@ -53,30 +53,3 @@ func ginsnop(pp *objw.Progs) *obj.Prog { p.To.Reg = ppc64.REG_R0 return p } - -func ginsnopdefer(pp *objw.Progs) *obj.Prog { - // On PPC64 two nops are required in the defer case. - // - // (see gc/cgen.go, gc/plive.go -- copy of comment below) - // - // On ppc64, when compiling Go into position - // independent code on ppc64le we insert an - // instruction to reload the TOC pointer from the - // stack as well. See the long comment near - // jmpdefer in runtime/asm_ppc64.s for why. - // If the MOVD is not needed, insert a hardware NOP - // so that the same number of instructions are used - // on ppc64 in both shared and non-shared modes. - - ginsnop(pp) - if base.Ctxt.Flag_shared { - p := pp.Prog(ppc64.AMOVD) - p.From.Type = obj.TYPE_MEM - p.From.Offset = 24 - p.From.Reg = ppc64.REGSP - p.To.Type = obj.TYPE_REG - p.To.Reg = ppc64.REG_R2 - return p - } - return ginsnop(pp) -} diff --git a/src/cmd/compile/internal/riscv64/galign.go b/src/cmd/compile/internal/riscv64/galign.go index 338248a7cf..846ed8fb38 100644 --- a/src/cmd/compile/internal/riscv64/galign.go +++ b/src/cmd/compile/internal/riscv64/galign.go @@ -16,7 +16,6 @@ func Init(arch *ssagen.ArchInfo) { arch.MAXWIDTH = 1 << 50 arch.Ginsnop = ginsnop - arch.Ginsnopdefer = ginsnop arch.ZeroRange = zeroRange arch.SSAMarkMoves = ssaMarkMoves diff --git a/src/cmd/compile/internal/s390x/galign.go b/src/cmd/compile/internal/s390x/galign.go index b004a2db0a..d880834c22 100644 --- a/src/cmd/compile/internal/s390x/galign.go +++ b/src/cmd/compile/internal/s390x/galign.go @@ -16,7 +16,6 @@ func Init(arch *ssagen.ArchInfo) { arch.ZeroRange = zerorange arch.Ginsnop = ginsnop - arch.Ginsnopdefer = ginsnop arch.SSAMarkMoves = ssaMarkMoves arch.SSAGenValue = ssaGenValue diff --git a/src/cmd/compile/internal/ssagen/arch.go b/src/cmd/compile/internal/ssagen/arch.go index 957fb3e84a..483e45cad4 100644 --- a/src/cmd/compile/internal/ssagen/arch.go +++ b/src/cmd/compile/internal/ssagen/arch.go @@ -29,8 +29,7 @@ type ArchInfo struct { // at function entry, and it is ok to clobber registers. ZeroRange func(*objw.Progs, *obj.Prog, int64, int64, *uint32) *obj.Prog - Ginsnop func(*objw.Progs) *obj.Prog - Ginsnopdefer func(*objw.Progs) *obj.Prog // special ginsnop for deferreturn + Ginsnop func(*objw.Progs) *obj.Prog // SSAMarkMoves marks any MOVXconst ops that need to avoid clobbering flags. SSAMarkMoves func(*State, *ssa.Block) diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 1a0a98f6aa..b0f2585e3a 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -7356,18 +7356,6 @@ func (s *State) PrepareCall(v *ssa.Value) { call, ok := v.Aux.(*ssa.AuxCall) - if ok && call.Fn == ir.Syms.Deferreturn { - // Deferred calls will appear to be returning to - // the CALL deferreturn(SB) that we are about to emit. - // However, the stack trace code will show the line - // of the instruction byte before the return PC. - // To avoid that being an unrelated instruction, - // insert an actual hardware NOP that will have the right line number. - // This is different from obj.ANOP, which is a virtual no-op - // that doesn't make it into the instruction stream. - Arch.Ginsnopdefer(s.pp) - } - if ok { // Record call graph information for nowritebarrierrec // analysis. diff --git a/src/cmd/compile/internal/wasm/ssa.go b/src/cmd/compile/internal/wasm/ssa.go index 31b09016eb..0b2ca3fdbb 100644 --- a/src/cmd/compile/internal/wasm/ssa.go +++ b/src/cmd/compile/internal/wasm/ssa.go @@ -24,7 +24,6 @@ func Init(arch *ssagen.ArchInfo) { arch.ZeroRange = zeroRange arch.Ginsnop = ginsnop - arch.Ginsnopdefer = ginsnop arch.SSAMarkMoves = ssaMarkMoves arch.SSAGenValue = ssaGenValue @@ -126,7 +125,11 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { case ssa.OpWasmLoweredStaticCall, ssa.OpWasmLoweredClosureCall, ssa.OpWasmLoweredInterCall: s.PrepareCall(v) if call, ok := v.Aux.(*ssa.AuxCall); ok && call.Fn == ir.Syms.Deferreturn { - // add a resume point before call to deferreturn so it can be called again via jmpdefer + // The runtime needs to inject jumps to + // deferreturn calls using the address in + // _func.deferreturn. Hence, the call to + // deferreturn must itself be a resumption + // point so it gets a target PC. s.Prog(wasm.ARESUMEPOINT) } if v.Op == ssa.OpWasmLoweredClosureCall { diff --git a/src/cmd/compile/internal/x86/galign.go b/src/cmd/compile/internal/x86/galign.go index 00a20e429f..5565bd32c7 100644 --- a/src/cmd/compile/internal/x86/galign.go +++ b/src/cmd/compile/internal/x86/galign.go @@ -34,7 +34,6 @@ func Init(arch *ssagen.ArchInfo) { arch.ZeroRange = zerorange arch.Ginsnop = ginsnop - arch.Ginsnopdefer = ginsnop arch.SSAMarkMoves = ssaMarkMoves } diff --git a/src/cmd/internal/obj/arm/asm5.go b/src/cmd/internal/obj/arm/asm5.go index ccf5f9e7f8..7b1682776e 100644 --- a/src/cmd/internal/obj/arm/asm5.go +++ b/src/cmd/internal/obj/arm/asm5.go @@ -355,11 +355,10 @@ var oprange [ALAST & obj.AMask][]Optab var xcmp [C_GOK + 1][C_GOK + 1]bool var ( - deferreturn *obj.LSym - symdiv *obj.LSym - symdivu *obj.LSym - symmod *obj.LSym - symmodu *obj.LSym + symdiv *obj.LSym + symdivu *obj.LSym + symmod *obj.LSym + symmodu *obj.LSym ) // Note about encoding: Prog.scond holds the condition encoding, @@ -1219,8 +1218,6 @@ func buildop(ctxt *obj.Link) { return } - deferreturn = ctxt.LookupABI("runtime.deferreturn", obj.ABIInternal) - symdiv = ctxt.Lookup("runtime._div") symdivu = ctxt.Lookup("runtime._divu") symmod = ctxt.Lookup("runtime._mod") diff --git a/src/cmd/internal/obj/wasm/wasmobj.go b/src/cmd/internal/obj/wasm/wasmobj.go index ceeae7a257..4d276db678 100644 --- a/src/cmd/internal/obj/wasm/wasmobj.go +++ b/src/cmd/internal/obj/wasm/wasmobj.go @@ -129,8 +129,6 @@ var ( morestackNoCtxt *obj.LSym gcWriteBarrier *obj.LSym sigpanic *obj.LSym - deferreturn *obj.LSym - jmpdefer *obj.LSym ) const ( @@ -143,10 +141,6 @@ func instinit(ctxt *obj.Link) { morestackNoCtxt = ctxt.Lookup("runtime.morestack_noctxt") gcWriteBarrier = ctxt.LookupABI("runtime.gcWriteBarrier", obj.ABIInternal) sigpanic = ctxt.LookupABI("runtime.sigpanic", obj.ABIInternal) - deferreturn = ctxt.LookupABI("runtime.deferreturn", obj.ABIInternal) - // jmpdefer is defined in assembly as ABI0. The compiler will - // generate a direct ABI0 call from Go, so look for that. - jmpdefer = ctxt.LookupABI(`"".jmpdefer`, obj.ABI0) } func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { @@ -423,12 +417,6 @@ func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { pcAfterCall-- // sigpanic expects to be called without advancing the pc } - // jmpdefer manipulates the return address on the stack so deferreturn gets called repeatedly. - // Model this in WebAssembly with a loop. - if call.To.Sym == deferreturn { - p = appendp(p, ALoop) - } - // SP -= 8 p = appendp(p, AGet, regAddr(REG_SP)) p = appendp(p, AI32Const, constAddr(8)) @@ -479,15 +467,6 @@ func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { break } - // jmpdefer removes the frame of deferreturn from the Go stack. - // However, its WebAssembly function still returns normally, - // so we need to return from deferreturn without removing its - // stack frame (no RET), because the frame is already gone. - if call.To.Sym == jmpdefer { - p = appendp(p, AReturn) - break - } - // return value of call is on the top of the stack, indicating whether to unwind the WebAssembly stack if call.As == ACALLNORESUME && call.To.Sym != sigpanic { // sigpanic unwinds the stack, but it never resumes // trying to unwind WebAssembly stack but call has no resume point, terminate with error @@ -500,21 +479,6 @@ func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { unwindExitBranches = append(unwindExitBranches, p) } - // jump to before the call if jmpdefer has reset the return address to the call's PC - if call.To.Sym == deferreturn { - // get PC_B from -8(SP) - p = appendp(p, AGet, regAddr(REG_SP)) - p = appendp(p, AI32Const, constAddr(8)) - p = appendp(p, AI32Sub) - p = appendp(p, AI32Load16U, constAddr(0)) - p = appendp(p, ATee, regAddr(REG_PC_B)) - - p = appendp(p, AI32Const, constAddr(call.Pc)) - p = appendp(p, AI32Eq) - p = appendp(p, ABrIf, constAddr(0)) - p = appendp(p, AEnd) // end of Loop - } - case obj.ARET, ARETUNWIND: ret := *p p.As = obj.ANOP diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go index 17fa76727e..331a98dfef 100644 --- a/src/cmd/internal/obj/x86/asm6.go +++ b/src/cmd/internal/obj/x86/asm6.go @@ -43,7 +43,6 @@ import ( var ( plan9privates *obj.LSym - deferreturn *obj.LSym ) // Instruction layout. diff --git a/src/cmd/internal/objabi/funcid.go b/src/cmd/internal/objabi/funcid.go index d881cdd061..68f6a26a76 100644 --- a/src/cmd/internal/objabi/funcid.go +++ b/src/cmd/internal/objabi/funcid.go @@ -34,7 +34,6 @@ const ( FuncID_gogo FuncID_gopanic FuncID_handleAsyncEvent - FuncID_jmpdefer FuncID_mcall FuncID_morestack FuncID_mstart @@ -60,7 +59,6 @@ var funcIDs = map[string]FuncID{ "gogo": FuncID_gogo, "gopanic": FuncID_gopanic, "handleAsyncEvent": FuncID_handleAsyncEvent, - "jmpdefer": FuncID_jmpdefer, "main": FuncID_runtime_main, "mcall": FuncID_mcall, "morestack": FuncID_morestack, diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index 05fd302369..70e3e1284b 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -129,11 +129,10 @@ func computeDeferReturn(ctxt *Link, deferReturnSym, s loader.Sym) uint32 { for ri := 0; ri < relocs.Count(); ri++ { r := relocs.At(ri) if target.IsWasm() && r.Type() == objabi.R_ADDR { - // Wasm does not have a live variable set at the deferreturn - // call itself. Instead it has one identified by the - // resumption point immediately preceding the deferreturn. - // The wasm code has a R_ADDR relocation which is used to - // set the resumption point to PC_B. + // wasm/ssa.go generates an ARESUMEPOINT just + // before the deferreturn call. The "PC" of + // the deferreturn call is stored in the + // R_ADDR relocation on the ARESUMEPOINT. lastWasmAddr = uint32(r.Add()) } if r.Type().IsDirectCall() && (r.Sym() == deferReturnSym || ldr.IsDeferReturnTramp(r.Sym())) { diff --git a/src/runtime/asm_386.s b/src/runtime/asm_386.s index dd2ea458cc..11c60309f4 100644 --- a/src/runtime/asm_386.s +++ b/src/runtime/asm_386.s @@ -582,26 +582,6 @@ TEXT ·publicationBarrier(SB),NOSPLIT,$0-0 // compile barrier. RET -// void jmpdefer(fn, sp); -// called from deferreturn. -// 1. pop the caller -// 2. sub 5 bytes (the length of CALL & a 32 bit displacement) from the callers -// return (when building for shared libraries, subtract 16 bytes -- 5 bytes -// for CALL & displacement to call __x86.get_pc_thunk.cx, 6 bytes for the -// LEAL to load the offset into BX, and finally 5 for the call & displacement) -// 3. jmp to the argument -TEXT runtime·jmpdefer(SB), NOSPLIT, $0-8 - MOVL fv+0(FP), DX // fn - MOVL argp+4(FP), BX // caller sp - LEAL -4(BX), SP // caller sp after CALL -#ifdef GOBUILDMODE_shared - SUBL $16, (SP) // return to CALL again -#else - SUBL $5, (SP) // return to CALL again -#endif - MOVL 0(DX), BX - JMP BX // but first run the deferred function - // Save state of caller into g->sched, // but using fake PC from systemstack_switch. // Must only be called from functions with no locals ($0) diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index 0f719b2664..2d8f4c2412 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -662,21 +662,6 @@ TEXT ·publicationBarrier(SB),NOSPLIT,$0-0 // compile barrier. RET -// func jmpdefer(fv func(), argp uintptr) -// argp is a caller SP. -// called from deferreturn. -// 1. pop the caller -// 2. sub 5 bytes from the callers return -// 3. jmp to the argument -TEXT runtime·jmpdefer(SB), NOSPLIT, $0-16 - MOVQ fv+0(FP), DX // fn - MOVQ argp+8(FP), BX // caller sp - LEAQ -8(BX), SP // caller sp after CALL - MOVQ -8(SP), BP // restore BP as if deferreturn returned (harmless if framepointers not in use) - SUBQ $5, (SP) // return to CALL again - MOVQ 0(DX), BX - JMP BX // but first run the deferred function - // Save state of caller into g->sched, // but using fake PC from systemstack_switch. // Must only be called from functions with no locals ($0) diff --git a/src/runtime/asm_arm.s b/src/runtime/asm_arm.s index 5c2bc00fe8..a1164781d2 100644 --- a/src/runtime/asm_arm.s +++ b/src/runtime/asm_arm.s @@ -506,20 +506,6 @@ CALLFN(·call268435456, 268435456) CALLFN(·call536870912, 536870912) CALLFN(·call1073741824, 1073741824) -// void jmpdefer(fn, sp); -// called from deferreturn. -// 1. grab stored LR for caller -// 2. sub 4 bytes to get back to BL deferreturn -// 3. B to fn -TEXT runtime·jmpdefer(SB),NOSPLIT,$0-8 - MOVW 0(R13), LR - MOVW $-4(LR), LR // BL deferreturn - MOVW fv+0(FP), R7 - MOVW argp+4(FP), R13 - MOVW $-4(R13), R13 // SP is 4 below argp, due to saved LR - MOVW 0(R7), R1 - B (R1) - // Save state of caller into g->sched, // but using fake PC from systemstack_switch. // Must only be called from functions with no locals ($0) diff --git a/src/runtime/asm_arm64.s b/src/runtime/asm_arm64.s index e7c5fa3225..e51ce2f831 100644 --- a/src/runtime/asm_arm64.s +++ b/src/runtime/asm_arm64.s @@ -982,23 +982,6 @@ again: CBNZ R0, again RET -// void jmpdefer(fv, sp); -// called from deferreturn. -// 1. grab stored LR for caller -// 2. sub 4 bytes to get back to BL deferreturn -// 3. BR to fn -TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16 - MOVD 0(RSP), R0 - SUB $4, R0 - MOVD R0, LR - - MOVD fv+0(FP), R26 - MOVD argp+8(FP), R0 - MOVD R0, RSP - SUB $8, RSP - MOVD 0(R26), R3 - B (R3) - // Save state of caller into g->sched, // but using fake PC from systemstack_switch. // Must only be called from functions with no locals ($0) diff --git a/src/runtime/asm_mips64x.s b/src/runtime/asm_mips64x.s index f3ac453d99..b2e2384c36 100644 --- a/src/runtime/asm_mips64x.s +++ b/src/runtime/asm_mips64x.s @@ -384,22 +384,6 @@ CALLFN(·call1073741824, 1073741824) TEXT runtime·procyield(SB),NOSPLIT,$0-0 RET -// void jmpdefer(fv, sp); -// called from deferreturn. -// 1. grab stored LR for caller -// 2. sub 8 bytes to get back to JAL deferreturn -// 3. JMP to fn -TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16 - MOVV 0(R29), R31 - ADDV $-8, R31 - - MOVV fv+0(FP), REGCTXT - MOVV argp+8(FP), R29 - ADDV $-8, R29 - NOR R0, R0 // prevent scheduling - MOVV 0(REGCTXT), R4 - JMP (R4) - // Save state of caller into g->sched, // but using fake PC from systemstack_switch. // Must only be called from functions with no locals ($0) diff --git a/src/runtime/asm_mipsx.s b/src/runtime/asm_mipsx.s index 4dc165849e..87a1344e8f 100644 --- a/src/runtime/asm_mipsx.s +++ b/src/runtime/asm_mipsx.s @@ -382,22 +382,6 @@ CALLFN(·call1073741824, 1073741824) TEXT runtime·procyield(SB),NOSPLIT,$0-4 RET -// void jmpdefer(fv, sp); -// called from deferreturn. -// 1. grab stored LR for caller -// 2. sub 8 bytes to get back to JAL deferreturn -// 3. JMP to fn -TEXT runtime·jmpdefer(SB),NOSPLIT,$0-8 - MOVW 0(R29), R31 - ADDU $-8, R31 - - MOVW fv+0(FP), REGCTXT - MOVW argp+4(FP), R29 - ADDU $-4, R29 - NOR R0, R0 // prevent scheduling - MOVW 0(REGCTXT), R4 - JMP (R4) - // Save state of caller into g->sched, // but using fake PC from systemstack_switch. // Must only be called from functions with no locals ($0) diff --git a/src/runtime/asm_ppc64x.s b/src/runtime/asm_ppc64x.s index a789d041e4..5dc96c5947 100644 --- a/src/runtime/asm_ppc64x.s +++ b/src/runtime/asm_ppc64x.s @@ -503,34 +503,6 @@ again: OR R6, R6, R6 // Set PPR priority back to medium-low RET -// void jmpdefer(fv, sp); -// called from deferreturn. -// 1. grab stored LR for caller -// 2. sub 8 bytes to get back to either nop or toc reload before deferreturn -// 3. BR to fn -// When dynamically linking Go, it is not sufficient to rewind to the BL -// deferreturn -- we might be jumping between modules and so we need to reset -// the TOC pointer in r2. To do this, codegen inserts MOVD 24(R1), R2 *before* -// the BL deferreturn and jmpdefer rewinds to that. -TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16 - MOVD 0(R1), R31 - SUB $8, R31 - MOVD R31, LR - - MOVD fv+0(FP), R11 - MOVD argp+8(FP), R1 - SUB $FIXED_FRAME, R1 -#ifdef GOOS_aix - // AIX won't trigger a SIGSEGV if R11 = nil - // So it manually triggers it - CMP R0, R11 - BNE 2(PC) - MOVD R0, 0(R0) -#endif - MOVD 0(R11), R12 - MOVD R12, CTR - BR (CTR) - // Save state of caller into g->sched, // but using fake PC from systemstack_switch. // Must only be called from functions with no locals ($0) diff --git a/src/runtime/asm_riscv64.s b/src/runtime/asm_riscv64.s index 9957ae201b..9927a817f7 100644 --- a/src/runtime/asm_riscv64.s +++ b/src/runtime/asm_riscv64.s @@ -248,21 +248,6 @@ TEXT gogo<>(SB), NOSPLIT|NOFRAME, $0 MOV gobuf_pc(T0), T0 JALR ZERO, T0 -// func jmpdefer(fv func(), argp uintptr) -// called from deferreturn -// 1. grab stored return address from the caller's frame -// 2. sub 8 bytes to get back to JAL deferreturn -// 3. JMP to fn -TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16 - MOV 0(X2), RA - ADD $-8, RA - - MOV fv+0(FP), CTXT - MOV argp+8(FP), X2 - ADD $-8, X2 - MOV 0(CTXT), T0 - JALR ZERO, T0 - // func procyield(cycles uint32) TEXT runtime·procyield(SB),NOSPLIT,$0-0 RET diff --git a/src/runtime/asm_s390x.s b/src/runtime/asm_s390x.s index 534cb6112c..d4110d563f 100644 --- a/src/runtime/asm_s390x.s +++ b/src/runtime/asm_s390x.s @@ -480,21 +480,6 @@ TEXT callfnMVC<>(SB),NOSPLIT|NOFRAME,$0-0 TEXT runtime·procyield(SB),NOSPLIT,$0-0 RET -// void jmpdefer(fv, sp); -// called from deferreturn. -// 1. grab stored LR for caller -// 2. sub 6 bytes to get back to BL deferreturn (size of BRASL instruction) -// 3. BR to fn -TEXT runtime·jmpdefer(SB),NOSPLIT|NOFRAME,$0-16 - MOVD 0(R15), R1 - SUB $6, R1, LR - - MOVD fv+0(FP), R12 - MOVD argp+8(FP), R15 - SUB $8, R15 - MOVD 0(R12), R3 - BR (R3) - // Save state of caller into g->sched, // but using fake PC from systemstack_switch. // Must only be called from functions with no locals ($0) diff --git a/src/runtime/asm_wasm.s b/src/runtime/asm_wasm.s index 53c271aa70..d885da6e70 100644 --- a/src/runtime/asm_wasm.s +++ b/src/runtime/asm_wasm.s @@ -193,35 +193,6 @@ TEXT runtime·return0(SB), NOSPLIT, $0-0 MOVD $0, RET0 RET -TEXT runtime·jmpdefer(SB), NOSPLIT, $0-16 - MOVD fv+0(FP), CTXT - - Get CTXT - I64Eqz - If - CALLNORESUME runtime·sigpanic(SB) - End - - // caller sp after CALL - I64Load argp+8(FP) - I64Const $8 - I64Sub - I32WrapI64 - Set SP - - // decrease PC_B by 1 to CALL again - Get SP - I32Load16U (SP) - I32Const $1 - I32Sub - I32Store16 $0 - - // but first run the deferred function - Get CTXT - I32WrapI64 - I64Load $0 - JMP - TEXT runtime·asminit(SB), NOSPLIT, $0-0 // No per-thread init. RET diff --git a/src/runtime/panic.go b/src/runtime/panic.go index b77376b598..b2158d376e 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -404,47 +404,39 @@ func freedeferfn() { throw("freedefer with d.fn != nil") } -// Run a deferred function if there is one. +// deferreturn runs deferred functions for the caller's frame. // The compiler inserts a call to this at the end of any // function which calls defer. -// If there is a deferred function, this will call runtime·jmpdefer, -// which will jump to the deferred function such that it appears -// to have been called by the caller of deferreturn at the point -// just before deferreturn was called. The effect is that deferreturn -// is called again and again until there are no more deferred functions. func deferreturn() { gp := getg() - d := gp._defer - if d == nil { - return - } - sp := getcallersp() - if d.sp != sp { - return - } - if d.openDefer { - done := runOpenDeferFrame(gp, d) - if !done { - throw("unfinished open-coded defers in deferreturn") + for { + d := gp._defer + if d == nil { + return } + sp := getcallersp() + if d.sp != sp { + return + } + if d.openDefer { + done := runOpenDeferFrame(gp, d) + if !done { + throw("unfinished open-coded defers in deferreturn") + } + gp._defer = d.link + freedefer(d) + // If this frame uses open defers, then this + // must be the only defer record for the + // frame, so we can just return. + return + } + + fn := d.fn + d.fn = nil gp._defer = d.link freedefer(d) - return + fn() } - - fn := d.fn - d.fn = nil - gp._defer = d.link - freedefer(d) - // If the defer function pointer is nil, force the seg fault to happen - // here rather than in jmpdefer. gentraceback() throws an error if it is - // called with a callback on an LR architecture and jmpdefer is on the - // stack, because jmpdefer manipulates SP (see issue #8153). - _ = **(**funcval)(unsafe.Pointer(&fn)) - // We must not split the stack between computing argp and - // calling jmpdefer because argp is a uintptr stack pointer. - argp := getcallersp() + sys.MinFrameSize - jmpdefer(fn, argp) } // Goexit terminates the goroutine that calls it. No other goroutine is affected. diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go index b94acdea1f..fc29a1bac3 100644 --- a/src/runtime/stubs.go +++ b/src/runtime/stubs.go @@ -176,8 +176,6 @@ func cgocallback(fn, frame, ctxt uintptr) func gogo(buf *gobuf) -//go:noescape -func jmpdefer(fv func(), argp uintptr) func asminit() func setg(gg *g) func breakpoint() diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 44ea0710c6..d08aa0b320 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -331,7 +331,6 @@ const ( funcID_gogo funcID_gopanic funcID_handleAsyncEvent - funcID_jmpdefer funcID_mcall funcID_morestack funcID_mstart -- GitLab From 88bd92bb6dd7997b415723c9c4a8d26ebe17634b Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 3 Aug 2021 17:03:42 -0400 Subject: [PATCH 0595/2500] [dev.typeparams] runtime: simplify freedefer Currently, freedefer manually zeros all the fields in the _defer because simply assigning _defer{} used to cause a nosplit stack overflow. freedefer is no longer nosplit, so go back to the simpler, more robust code. Change-Id: I881f557bab3b1ee7ab29b68e7fb56d0fe6d35d8d Reviewed-on: https://go-review.googlesource.com/c/go/+/339669 Trust: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/panic.go | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/runtime/panic.go b/src/runtime/panic.go index b2158d376e..48b1b5dd9d 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -372,19 +372,7 @@ func freedefer(d *_defer) { unlock(&sched.deferlock) } - // These lines used to be simply `*d = _defer{}` but that - // started causing a nosplit stack overflow via typedmemmove. - d.started = false - d.openDefer = false - d.sp = 0 - d.pc = 0 - d.framepc = 0 - d.varp = 0 - d.fd = nil - // d._panic and d.fn must be nil already. - // If not, we would have called freedeferpanic or freedeferfn above, - // both of which throw. - d.link = nil + *d = _defer{} pp.deferpool = append(pp.deferpool, d) -- GitLab From 1ea3596b4103fcbe8741f8af48a119aa8220180b Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Tue, 3 Aug 2021 16:22:00 -0400 Subject: [PATCH 0596/2500] [dev.typeparams] go/types: adjust unsafe.Alignof/Offsetof/Sizeof This is a port of CL 335413 to go/types, adjusted for the parsing API of go/parser. Change-Id: Ie6836add7d027aaf5d6d3dae65222b1d15bd7558 Reviewed-on: https://go-review.googlesource.com/c/go/+/339649 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/builtins.go | 73 ++++++++---- src/go/types/builtins_test.go | 7 +- src/go/types/infer.go | 4 +- src/go/types/sizes.go | 10 +- src/go/types/testdata/check/builtins.go2 | 107 ++++++++++++++++++ .../types/testdata/fixedbugs/issue40301.go2 | 4 +- 6 files changed, 177 insertions(+), 28 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index b6fb36b185..ecb9920a81 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -633,19 +633,22 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b case _Alignof: // unsafe.Alignof(x T) uintptr - if asTypeParam(x.typ) != nil { - check.invalidOp(call, _Todo, "unsafe.Alignof undefined for %s", x) - return - } check.assignment(x, nil, "argument to unsafe.Alignof") if x.mode == invalid { return } - x.mode = constant_ - x.val = constant.MakeInt64(check.conf.alignof(x.typ)) + if hasVarSize(x.typ) { + x.mode = value + if check.Types != nil { + check.recordBuiltinType(call.Fun, makeSig(Typ[Uintptr], x.typ)) + } + } else { + x.mode = constant_ + x.val = constant.MakeInt64(check.conf.alignof(x.typ)) + // result is constant - no need to record signature + } x.typ = Typ[Uintptr] - // result is constant - no need to record signature case _Offsetof: // unsafe.Offsetof(x T) uintptr, where x must be a selector @@ -683,30 +686,43 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b return } - // TODO(gri) Should we pass x.typ instead of base (and indirect report if derefStructPtr indirected)? + // TODO(gri) Should we pass x.typ instead of base (and have indirect report if derefStructPtr indirected)? check.recordSelection(selx, FieldVal, base, obj, index, false) - offs := check.conf.offsetof(base, index) - x.mode = constant_ - x.val = constant.MakeInt64(offs) + // The field offset is considered a variable even if the field is declared before + // the part of the struct which is variable-sized. This makes both the rules + // simpler and also permits (or at least doesn't prevent) a compiler from re- + // arranging struct fields if it wanted to. + if hasVarSize(base) { + x.mode = value + if check.Types != nil { + check.recordBuiltinType(call.Fun, makeSig(Typ[Uintptr], obj.Type())) + } + } else { + x.mode = constant_ + x.val = constant.MakeInt64(check.conf.offsetof(base, index)) + // result is constant - no need to record signature + } x.typ = Typ[Uintptr] - // result is constant - no need to record signature case _Sizeof: // unsafe.Sizeof(x T) uintptr - if asTypeParam(x.typ) != nil { - check.invalidOp(call, _Todo, "unsafe.Sizeof undefined for %s", x) - return - } check.assignment(x, nil, "argument to unsafe.Sizeof") if x.mode == invalid { return } - x.mode = constant_ - x.val = constant.MakeInt64(check.conf.sizeof(x.typ)) + if hasVarSize(x.typ) { + x.mode = value + if check.Types != nil { + check.recordBuiltinType(call.Fun, makeSig(Typ[Uintptr], x.typ)) + } + } else { + x.mode = constant_ + x.val = constant.MakeInt64(check.conf.sizeof(x.typ)) + // result is constant - no need to record signature + } x.typ = Typ[Uintptr] - // result is constant - no need to record signature case _Slice: // unsafe.Slice(ptr *T, len IntegerType) []T @@ -778,6 +794,25 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b return true } +// hasVarSize reports if the size of type t is variable due to type parameters. +func hasVarSize(t Type) bool { + switch t := under(t).(type) { + case *Array: + return hasVarSize(t.elem) + case *Struct: + for _, f := range t.fields { + if hasVarSize(f.typ) { + return true + } + } + case *TypeParam: + return true + case *Named, *Union, *top: + unreachable() + } + return false +} + // applyTypeFunc applies f to x. If x is a type parameter, // the result is a type parameter constrained by an new // interface bound. The type bounds for that interface diff --git a/src/go/types/builtins_test.go b/src/go/types/builtins_test.go index 11de9a1ac1..cee3d315e5 100644 --- a/src/go/types/builtins_test.go +++ b/src/go/types/builtins_test.go @@ -113,12 +113,15 @@ var builtinCalls = []struct { {"Alignof", `_ = unsafe.Alignof(0)`, `invalid type`}, // constant {"Alignof", `var x struct{}; _ = unsafe.Alignof(x)`, `invalid type`}, // constant + {"Alignof", `var x P; _ = unsafe.Alignof(x)`, `func(p.P₁) uintptr`}, {"Offsetof", `var x struct{f bool}; _ = unsafe.Offsetof(x.f)`, `invalid type`}, // constant {"Offsetof", `var x struct{_ int; f bool}; _ = unsafe.Offsetof((&x).f)`, `invalid type`}, // constant + {"Offsetof", `var x struct{_ int; f P}; _ = unsafe.Offsetof((&x).f)`, `func(p.P₁) uintptr`}, {"Sizeof", `_ = unsafe.Sizeof(0)`, `invalid type`}, // constant {"Sizeof", `var x struct{}; _ = unsafe.Sizeof(x)`, `invalid type`}, // constant + {"Sizeof", `var x P; _ = unsafe.Sizeof(x)`, `func(p.P₁) uintptr`}, {"Slice", `var p *int; _ = unsafe.Slice(p, 1)`, `func(*int, int) []int`}, {"Slice", `var p *byte; var n uintptr; _ = unsafe.Slice(p, n)`, `func(*byte, uintptr) []byte`}, @@ -151,8 +154,10 @@ func TestBuiltinSignatures(t *testing.T) { } } +// parseGenericSrc in types2 is not necessary. We can just parse in testBuiltinSignature below. + func testBuiltinSignature(t *testing.T, name, src0, want string) { - src := fmt.Sprintf(`package p; import "unsafe"; type _ unsafe.Pointer /* use unsafe */; func _() { %s }`, src0) + src := fmt.Sprintf(`package p; import "unsafe"; type _ unsafe.Pointer /* use unsafe */; func _[P any]() { %s }`, src0) f, err := parser.ParseFile(fset, "", src, 0) if err != nil { t.Errorf("%s: %s", src0, err) diff --git a/src/go/types/infer.go b/src/go/types/infer.go index 774d2fd158..f3f69e01b6 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -393,8 +393,8 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty // u.x.types() now contains the incoming type arguments plus any additional type // arguments for which there were structural constraints. The newly inferred non- - // nil entries may still contain references to other type parameters. For instance, - // for [A any, B interface{type []C}, C interface{type *A}], if A == int + // nil entries may still contain references to other type parameters. + // For instance, for [A any, B interface{ []C }, C interface{ *A }], if A == int // was given, unification produced the type list [int, []C, *A]. We eliminate the // remaining type parameters by substituting the type parameters in this type list // until nothing changes anymore. diff --git a/src/go/types/sizes.go b/src/go/types/sizes.go index 35219836ec..4c85bfe057 100644 --- a/src/go/types/sizes.go +++ b/src/go/types/sizes.go @@ -48,7 +48,7 @@ type StdSizes struct { func (s *StdSizes) Alignof(T Type) int64 { // For arrays and structs, alignment is defined in terms // of alignment of the elements and fields, respectively. - switch t := optype(T).(type) { + switch t := under(T).(type) { case *Array: // spec: "For a variable x of array type: unsafe.Alignof(x) // is the same as unsafe.Alignof(x[0]), but at least 1." @@ -73,6 +73,8 @@ func (s *StdSizes) Alignof(T Type) int64 { if t.Info()&IsString != 0 { return s.WordSize } + case *TypeParam, *Union: + unreachable() } a := s.Sizeof(T) // may be 0 // spec: "For a variable x of any type: unsafe.Alignof(x) is at least 1." @@ -118,7 +120,7 @@ var basicSizes = [...]byte{ } func (s *StdSizes) Sizeof(T Type) int64 { - switch t := optype(T).(type) { + switch t := under(T).(type) { case *Basic: assert(isTyped(T)) k := t.kind @@ -148,10 +150,10 @@ func (s *StdSizes) Sizeof(T Type) int64 { } offsets := s.Offsetsof(t.fields) return offsets[n-1] + s.Sizeof(t.fields[n-1].typ) - case *Union: - panic("Sizeof unimplemented for union") case *Interface: return s.WordSize * 2 + case *TypeParam, *Union: + unreachable() } return s.WordSize // catch-all } diff --git a/src/go/types/testdata/check/builtins.go2 b/src/go/types/testdata/check/builtins.go2 index 8fe6d7b332..3881090603 100644 --- a/src/go/types/testdata/check/builtins.go2 +++ b/src/go/types/testdata/check/builtins.go2 @@ -6,6 +6,8 @@ package builtins +import "unsafe" + // close type C0 interface{ int } @@ -127,3 +129,108 @@ func _[T Bss]() { _ = make(T, 10) _ = make(T, 10, 20) } + +// unsafe.Alignof + +func _[T comparable]() { + var ( + b int64 + a [10]T + s struct{ f T } + p *T + l []T + f func(T) + i interface{ m() T } + c chan T + m map[T]T + t T + ) + + const bb = unsafe.Alignof(b) + assert(bb == 8) + const _ = unsafe /* ERROR not constant */ .Alignof(a) + const _ = unsafe /* ERROR not constant */ .Alignof(s) + const pp = unsafe.Alignof(p) + assert(pp == 8) + const ll = unsafe.Alignof(l) + assert(ll == 8) + const ff = unsafe.Alignof(f) + assert(ff == 8) + const ii = unsafe.Alignof(i) + assert(ii == 8) + const cc = unsafe.Alignof(c) + assert(cc == 8) + const mm = unsafe.Alignof(m) + assert(mm == 8) + const _ = unsafe /* ERROR not constant */ .Alignof(t) +} + +// unsafe.Offsetof + +func _[T comparable]() { + var ( + b struct{ _, f int64 } + a struct{ _, f [10]T } + s struct{ _, f struct{ f T } } + p struct{ _, f *T } + l struct{ _, f []T } + f struct{ _, f func(T) } + i struct{ _, f interface{ m() T } } + c struct{ _, f chan T } + m struct{ _, f map[T]T } + t struct{ _, f T } + ) + + const bb = unsafe.Offsetof(b.f) + assert(bb == 8) + const _ = unsafe /* ERROR not constant */ .Alignof(a) + const _ = unsafe /* ERROR not constant */ .Alignof(s) + const pp = unsafe.Offsetof(p.f) + assert(pp == 8) + const ll = unsafe.Offsetof(l.f) + assert(ll == 24) + const ff = unsafe.Offsetof(f.f) + assert(ff == 8) + const ii = unsafe.Offsetof(i.f) + assert(ii == 16) + const cc = unsafe.Offsetof(c.f) + assert(cc == 8) + const mm = unsafe.Offsetof(m.f) + assert(mm == 8) + const _ = unsafe /* ERROR not constant */ .Alignof(t) +} + +// unsafe.Sizeof + +func _[T comparable]() { + var ( + b int64 + a [10]T + s struct{ f T } + p *T + l []T + f func(T) + i interface{ m() T } + c chan T + m map[T]T + t T + ) + + const bb = unsafe.Sizeof(b) + assert(bb == 8) + const _ = unsafe /* ERROR not constant */ .Alignof(a) + const _ = unsafe /* ERROR not constant */ .Alignof(s) + const pp = unsafe.Sizeof(p) + assert(pp == 8) + const ll = unsafe.Sizeof(l) + assert(ll == 24) + const ff = unsafe.Sizeof(f) + assert(ff == 8) + const ii = unsafe.Sizeof(i) + assert(ii == 16) + const cc = unsafe.Sizeof(c) + assert(cc == 8) + const mm = unsafe.Sizeof(m) + assert(mm == 8) + const _ = unsafe /* ERROR not constant */ .Alignof(t) +} diff --git a/src/go/types/testdata/fixedbugs/issue40301.go2 b/src/go/types/testdata/fixedbugs/issue40301.go2 index 5d97855f8a..c78f9a1fa0 100644 --- a/src/go/types/testdata/fixedbugs/issue40301.go2 +++ b/src/go/types/testdata/fixedbugs/issue40301.go2 @@ -7,6 +7,6 @@ package p import "unsafe" func _[T any](x T) { - _ = unsafe /* ERROR undefined */ .Alignof(x) - _ = unsafe /* ERROR undefined */ .Sizeof(x) + _ = unsafe.Alignof(x) + _ = unsafe.Sizeof(x) } -- GitLab From 89897473e289a58bf9608d525f1e9b4abd970c8d Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Tue, 3 Aug 2021 16:24:20 -0400 Subject: [PATCH 0597/2500] [dev.typeparams] go/types: implement TypeParam.Constraint This is a clean port of CL 336989 to go/types. Change-Id: Ib8dbe03f420d28ada6d5fc7003ab0c82c7e06c41 Reviewed-on: https://go-review.googlesource.com/c/go/+/339650 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/typeparam.go | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index a3d60c1648..8cb44ea25e 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -60,24 +60,32 @@ func (t *TypeParam) _SetId(id uint64) { t.id = id } -// TODO(rfindley): document the Bound and SetBound methods. +// Constraint returns the type constraint specified for t. +func (t *TypeParam) Constraint() Type { + // compute the type set if possible (we may not have an interface) + if iface, _ := under(t.bound).(*Interface); iface != nil { + // use the type bound position if we have one + pos := token.NoPos + if n, _ := t.bound.(*Named); n != nil { + pos = n.obj.pos + } + computeTypeSet(t.check, pos, iface) + } + return t.bound +} +// Bound returns the underlying type of the type parameter's +// constraint. +// Deprecated for external use. Use Constraint instead. func (t *TypeParam) Bound() *Interface { - // we may not have an interface (error reported elsewhere) - iface, _ := under(t.bound).(*Interface) - if iface == nil { - return &emptyInterface + if iface, _ := under(t.Constraint()).(*Interface); iface != nil { + return iface } - // use the type bound position if we have one - pos := token.NoPos - if n, _ := t.bound.(*Named); n != nil { - pos = n.obj.pos - } - // TODO(rFindley) switch this to an unexported method on Checker. - computeTypeSet(t.check, pos, iface) - return iface + return &emptyInterface } +// TODO(rfindley): document the SetBound methods. + func (t *TypeParam) SetBound(bound Type) { if bound == nil { panic("internal error: bound must not be nil") -- GitLab From 18e0503724e64c3d55dbc705eb4f08be2fde1b32 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Tue, 3 Aug 2021 16:32:23 -0400 Subject: [PATCH 0598/2500] [dev.typeparams] go/types: embedded type cannot be a (pointer to) a type parameter This is a port of CL 337353 to go/types, adjusted for the error API and to comment out a test for MethodSet. Some nearby error messages that were using errorf rather than error were also adjusted. Fixes #43621 Change-Id: I28c9747e044ec7a2863f6890db69475fb8c29231 Reviewed-on: https://go-review.googlesource.com/c/go/+/339651 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/methodset_test.go | 12 +++++++----- src/go/types/struct.go | 10 ++++++---- src/go/types/testdata/check/typeparams.go2 | 4 ++-- src/go/types/testdata/fixedbugs/issue39938.go2 | 4 ++-- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/go/types/methodset_test.go b/src/go/types/methodset_test.go index 5b29b2f0fe..73a8442f21 100644 --- a/src/go/types/methodset_test.go +++ b/src/go/types/methodset_test.go @@ -46,12 +46,14 @@ func TestNewMethodSet(t *testing.T) { genericTests := map[string][]method{ // By convention, look up a in the scope of "g" - "type C interface{ f() }; func g[T C](a T){}": {{"f", []int{0}, true}}, - "type C interface{ f() }; func g[T C]() { var a T; _ = a }": {{"f", []int{0}, true}}, - "type C interface{ f() }; func g[T C]() { var a struct{T}; _ = a }": {{"f", []int{0, 0}, true}}, + "type C interface{ f() }; func g[T C](a T){}": {{"f", []int{0}, true}}, + "type C interface{ f() }; func g[T C]() { var a T; _ = a }": {{"f", []int{0}, true}}, - // Issue #45639: We don't allow this anymore. Keep this code in case we - // decide to revisit this decision. + // Issue #43621: We don't allow this anymore. Keep this code in case we + // decide to revisit this decision. + // "type C interface{ f() }; func g[T C]() { var a struct{T}; _ = a }": {{"f", []int{0, 0}, true}}, + + // Issue #45639: We also don't allow this anymore. // "type C interface{ f() }; func g[T C]() { type Y T; var a Y; _ = a }": {}, } diff --git a/src/go/types/struct.go b/src/go/types/struct.go index d1fb813c14..48b07346dc 100644 --- a/src/go/types/struct.go +++ b/src/go/types/struct.go @@ -136,7 +136,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) { check.later(func() { t, isPtr := deref(embeddedTyp) - switch t := optype(t).(type) { + switch t := under(t).(type) { case *Basic: if t == Typ[Invalid] { // error was reported before @@ -144,13 +144,15 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) { } // unsafe.Pointer is treated like a regular pointer if t.kind == UnsafePointer { - check.errorf(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be unsafe.Pointer") + check.error(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be unsafe.Pointer") } case *Pointer: - check.errorf(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a pointer") + check.error(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a pointer") + case *TypeParam: + check.error(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a (pointer to a) type parameter") case *Interface: if isPtr { - check.errorf(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a pointer to an interface") + check.error(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a pointer to an interface") } } }) diff --git a/src/go/types/testdata/check/typeparams.go2 b/src/go/types/testdata/check/typeparams.go2 index b03725ff2a..77cd65d19a 100644 --- a/src/go/types/testdata/check/typeparams.go2 +++ b/src/go/types/testdata/check/typeparams.go2 @@ -79,11 +79,11 @@ var _ *int = new[int]() func _[T any](map[T /* ERROR incomparable map key type T \(missing comparable constraint\) */]int) // w/o constraint we don't know if T is comparable -func f1[T1 any](struct{T1}) int +func f1[T1 any](struct{T1 /* ERROR cannot be a .* type parameter */ }) int var _ = f1[int](struct{T1}{}) type T1 = int -func f2[t1 any](struct{t1; x float32}) int +func f2[t1 any](struct{t1 /* ERROR cannot be a .* type parameter */ ; x float32}) int var _ = f2[t1](struct{t1; x float32}{}) type t1 = int diff --git a/src/go/types/testdata/fixedbugs/issue39938.go2 b/src/go/types/testdata/fixedbugs/issue39938.go2 index 76e7e369ca..0da6e103fd 100644 --- a/src/go/types/testdata/fixedbugs/issue39938.go2 +++ b/src/go/types/testdata/fixedbugs/issue39938.go2 @@ -8,8 +8,8 @@ package p type E0[P any] P type E1[P any] *P -type E2[P any] struct{ P } -type E3[P any] struct{ *P } +type E2[P any] struct{ _ P } +type E3[P any] struct{ _ *P } type T0 /* ERROR illegal cycle */ struct { _ E0[T0] -- GitLab From e0d09072123c40cfef3015be146b55e0d26a67dd Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Tue, 3 Aug 2021 16:47:15 -0400 Subject: [PATCH 0599/2500] [dev.typeparams] go/types: use comparable bit rather than ==() method This is a port of CL 337354 to go/types, adjusted for the error reporting API and to reposition a couple error messages in issue47411.go2 (the go/types position is probably better). A panic is also fixed in lookup.go when method lookup fails and static == false. I'll send a fix for types2 in a separate CL. For #47411 Change-Id: Icc48f03c3958695f581f10e8675c1f32434c424b Reviewed-on: https://go-review.googlesource.com/c/go/+/339652 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/instantiate.go | 16 +++++++++--- src/go/types/interface.go | 2 +- src/go/types/lookup.go | 7 +---- src/go/types/predicates.go | 17 +----------- src/go/types/sizeof_test.go | 2 +- src/go/types/testdata/check/issues.go2 | 6 ++--- .../types/testdata/fixedbugs/issue47411.go2 | 26 +++++++++++++++++++ src/go/types/typeset.go | 26 ++++++++++++++++--- src/go/types/universe.go | 12 +++------ 9 files changed, 71 insertions(+), 43 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue47411.go2 diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 28d68cad0e..2e6c20723b 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -173,6 +173,17 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap // the parameterized type. iface = check.subst(pos, iface, smap).(*Interface) + // if iface is comparable, targ must be comparable + // TODO(gri) the error messages needs to be better, here + if iface.IsComparable() && !Comparable(targ) { + if tpar := asTypeParam(targ); tpar != nil && tpar.Bound().typeSet().IsTop() { + check.softErrorf(atPos(pos), _Todo, "%s has no constraints", targ) + return false + } + check.softErrorf(atPos(pos), _Todo, "%s does not satisfy comparable", targ) + return false + } + // targ must implement iface (methods) // - check only if we have methods if iface.NumMethods() > 0 { @@ -188,10 +199,7 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap // (print warning for now) // Old warning: // check.softErrorf(pos, "%s does not satisfy %s (warning: name not updated) = %s (missing method %s)", targ, tpar.bound, iface, m) - if m.name == "==" { - // We don't want to report "missing method ==". - check.softErrorf(atPos(pos), 0, "%s does not satisfy comparable", targ) - } else if wrong != nil { + if wrong != nil { // TODO(gri) This can still report uninstantiated types which makes the error message // more difficult to read then necessary. // TODO(rFindley) should this use parentheses rather than ':' for qualification? diff --git a/src/go/types/interface.go b/src/go/types/interface.go index 686dd7a786..51eff8fbdd 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -111,7 +111,7 @@ func (t *Interface) Method(i int) *Func { return t.typeSet().Method(i) } // Empty reports whether t is the empty interface. func (t *Interface) Empty() bool { return t.typeSet().IsTop() } -// IsComparable reports whether interface t is or embeds the predeclared interface "comparable". +// IsComparable reports whether each type in interface t's type set is comparable. func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() } // IsConstraint reports whether interface t is not just a method set. diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index 07baf2a48b..6d38db4523 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -307,8 +307,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, _, f := ityp.typeSet().LookupMethod(m.pkg, m.name) if f == nil { - // if m is the magic method == we're ok (interfaces are comparable) - if m.name == "==" || !static { + if !static { continue } return m, f @@ -358,10 +357,6 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // we must have a method (not a field of matching function type) f, _ := obj.(*Func) if f == nil { - // if m is the magic method == and V is comparable, we're ok - if m.name == "==" && Comparable(V) { - continue - } return m, nil } diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 41e0c25d6b..caf72c2f2e 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -96,19 +96,6 @@ func comparable(T Type, seen map[Type]bool) bool { } seen[T] = true - // If T is a type parameter not constrained by any type - // (i.e., it's operational type is the top type), - // T is comparable if it has the == method. Otherwise, - // the operational type "wins". For instance - // - // interface{ comparable; type []byte } - // - // is not comparable because []byte is not comparable. - // TODO(gri) this code is not 100% correct (see comment for TypeSet.IsComparable) - if t := asTypeParam(T); t != nil && optype(t) == theTop { - return t.Bound().IsComparable() - } - switch t := under(T).(type) { case *Basic: // assume invalid types to be comparable @@ -126,9 +113,7 @@ func comparable(T Type, seen map[Type]bool) bool { case *Array: return comparable(t.elem, seen) case *TypeParam: - return t.underIs(func(t Type) bool { - return comparable(t, seen) - }) + return t.Bound().IsComparable() } return false } diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index c8758663ec..b892e7e521 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -47,7 +47,7 @@ func TestSizeof(t *testing.T) { // Misc {Scope{}, 44, 88}, {Package{}, 40, 80}, - {TypeSet{}, 20, 40}, + {TypeSet{}, 24, 48}, } for _, test := range tests { got := reflect.TypeOf(test.val).Size() diff --git a/src/go/types/testdata/check/issues.go2 b/src/go/types/testdata/check/issues.go2 index c57f002303..6a1a10ad49 100644 --- a/src/go/types/testdata/check/issues.go2 +++ b/src/go/types/testdata/check/issues.go2 @@ -65,7 +65,7 @@ func _() { type T1[P interface{~uint}] struct{} func _[P any]() { - _ = T1[P /* ERROR P has no type constraints */ ]{} + _ = T1[P /* ERROR P has no constraints */ ]{} } // This is the original (simplified) program causing the same issue. @@ -81,8 +81,8 @@ func (u T2[U]) Add1() U { return u.s + 1 } -func NewT2[U any]() T2[U /* ERROR U has no type constraints */ ] { - return T2[U /* ERROR U has no type constraints */ ]{} +func NewT2[U any]() T2[U /* ERROR U has no constraints */ ] { + return T2[U /* ERROR U has no constraints */ ]{} } func _() { diff --git a/src/go/types/testdata/fixedbugs/issue47411.go2 b/src/go/types/testdata/fixedbugs/issue47411.go2 new file mode 100644 index 0000000000..7326205863 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue47411.go2 @@ -0,0 +1,26 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func f[_ comparable]() +func g[_ interface{interface{comparable; ~int|~string}}]() + +func _[P comparable, + Q interface{ comparable; ~int|~string }, + R any, // not comparable + S interface{ comparable; ~func() }, // not comparable +]() { + _ = f[int] + _ = f[P] + _ = f[Q] + _ = f[func /* ERROR does not satisfy comparable */ ()] + _ = f[R /* ERROR R has no constraints */ ] + + _ = g[int] + _ = g[P /* ERROR P has no type constraints */ ] + _ = g[Q] + _ = g[func /* ERROR does not satisfy comparable */()] + _ = g[R /* ERROR R has no constraints */ ] +} diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index 3df2f1235f..226e438cc9 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -16,22 +16,31 @@ import ( // A TypeSet represents the type set of an interface. type TypeSet struct { + comparable bool // if set, the interface is or embeds comparable // TODO(gri) consider using a set for the methods for faster lookup methods []*Func // all methods of the interface; sorted by unique ID types Type // typically a *Union; nil means no type restrictions } // IsTop reports whether type set s is the top type set (corresponding to the empty interface). -func (s *TypeSet) IsTop() bool { return len(s.methods) == 0 && s.types == nil } +func (s *TypeSet) IsTop() bool { return !s.comparable && len(s.methods) == 0 && s.types == nil } // IsMethodSet reports whether the type set s is described by a single set of methods. -func (s *TypeSet) IsMethodSet() bool { return s.types == nil && !s.IsComparable() } +func (s *TypeSet) IsMethodSet() bool { return !s.comparable && s.types == nil } // IsComparable reports whether each type in the set is comparable. // TODO(gri) this is not correct - there may be s.types values containing non-comparable types func (s *TypeSet) IsComparable() bool { - _, m := s.LookupMethod(nil, "==") - return m != nil + if s.types == nil { + return s.comparable + } + tcomparable := s.underIs(func(u Type) bool { + return Comparable(u) + }) + if !s.comparable { + return tcomparable + } + return s.comparable && tcomparable } // NumMethods returns the number of methods available. @@ -54,6 +63,12 @@ func (s *TypeSet) String() string { var buf bytes.Buffer buf.WriteByte('{') + if s.comparable { + buf.WriteString(" comparable") + if len(s.methods) > 0 || s.types != nil { + buf.WriteByte(';') + } + } for i, m := range s.methods { if i > 0 { buf.WriteByte(';') @@ -205,6 +220,9 @@ func computeTypeSet(check *Checker, pos token.Pos, ityp *Interface) *TypeSet { switch t := under(typ).(type) { case *Interface: tset := computeTypeSet(check, pos, t) + if tset.comparable { + ityp.tset.comparable = true + } for _, m := range tset.methods { addMethod(pos, m, false) // use embedding position pos rather than m.pos diff --git a/src/go/types/universe.go b/src/go/types/universe.go index 489587f393..e2b3bd7c18 100644 --- a/src/go/types/universe.go +++ b/src/go/types/universe.go @@ -89,23 +89,19 @@ func defPredeclaredTypes() { res := NewVar(token.NoPos, nil, "", Typ[String]) sig := NewSignature(nil, nil, NewTuple(res), false) err := NewFunc(token.NoPos, nil, "Error", sig) - ityp := NewInterfaceType([]*Func{err}, nil) + ityp := &Interface{obj, []*Func{err}, nil, nil, true, nil} computeTypeSet(nil, token.NoPos, ityp) // prevent races due to lazy computation of tset typ := NewNamed(obj, ityp, nil) sig.recv = NewVar(token.NoPos, nil, "", typ) def(obj) } - // type comparable interface{ ==() } + // type comparable interface{ /* type set marked comparable */ } { obj := NewTypeName(token.NoPos, nil, "comparable", nil) obj.setColor(black) - sig := NewSignature(nil, nil, nil, false) - eql := NewFunc(token.NoPos, nil, "==", sig) - ityp := NewInterfaceType([]*Func{eql}, nil) - computeTypeSet(nil, token.NoPos, ityp) // prevent races due to lazy computation of tset - typ := NewNamed(obj, ityp, nil) - sig.recv = NewVar(token.NoPos, nil, "", typ) + ityp := &Interface{obj, nil, nil, nil, true, &TypeSet{true, nil, nil}} + NewNamed(obj, ityp, nil) def(obj) } } -- GitLab From 5b51cf47dcf08d86eb1de22850ebd7d75e7a02af Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Tue, 3 Aug 2021 16:50:35 -0400 Subject: [PATCH 0600/2500] [dev.typeparams] go/types: implement type terms This is a port of CL 338049 to go/types. It identical to that CL, except for eliding unnecessary typenames from the testTerms declaration. Change-Id: Ieb04d7bbc20063044eb63ea985f75d529f030cd7 Reviewed-on: https://go-review.googlesource.com/c/go/+/339653 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/typeterm.go | 166 +++++++++++++++++++++++++++ src/go/types/typeterm_test.go | 205 ++++++++++++++++++++++++++++++++++ 2 files changed, 371 insertions(+) create mode 100644 src/go/types/typeterm.go create mode 100644 src/go/types/typeterm_test.go diff --git a/src/go/types/typeterm.go b/src/go/types/typeterm.go new file mode 100644 index 0000000000..dbd055a580 --- /dev/null +++ b/src/go/types/typeterm.go @@ -0,0 +1,166 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +// TODO(gri) use a different symbol instead of ⊤ for the set of all types +// (⊤ is hard to distinguish from T in some fonts) + +// A term describes elementary type sets: +// +// ∅: (*term)(nil) == ∅ // set of no types (empty set) +// ⊤: &term{} == ⊤ // set of all types +// T: &term{false, T} == {T} // set of type T +// ~t: &term{true, t} == {t' | under(t') == t} // set of types with underlying type t +// +type term struct { + tilde bool // valid if typ != nil + typ Type +} + +func (x *term) String() string { + switch { + case x == nil: + return "∅" + case x.typ == nil: + return "⊤" + case x.tilde: + return "~" + x.typ.String() + default: + return x.typ.String() + } +} + +// equal reports whether x and y represent the same type set. +func (x *term) equal(y *term) bool { + // easy cases + switch { + case x == nil || y == nil: + return x == y + case x.typ == nil || y.typ == nil: + return x.typ == y.typ + } + // ∅ ⊂ x, y ⊂ ⊤ + + return x.tilde == y.tilde && Identical(x.typ, y.typ) +} + +// union returns the union x ∪ y: zero, one, or two non-nil terms. +func (x *term) union(y *term) (_, _ *term) { + // easy cases + switch { + case x == nil && y == nil: + return nil, nil // ∅ ∪ ∅ == ∅ + case x == nil: + return y, nil // ∅ ∪ y == y + case y == nil: + return x, nil // x ∪ ∅ == x + case x.typ == nil: + return x, nil // ⊤ ∪ y == ⊤ + case y.typ == nil: + return y, nil // x ∪ ⊤ == ⊤ + } + // ∅ ⊂ x, y ⊂ ⊤ + + if x.disjoint(y) { + return x, y // x ∪ y == (x, y) if x ∩ y == ∅ + } + // x.typ == y.typ + + // ~t ∪ ~t == ~t + // ~t ∪ T == ~t + // T ∪ ~t == ~t + // T ∪ T == T + if x.tilde || !y.tilde { + return x, nil + } + return y, nil +} + +// intersect returns the intersection x ∩ y. +func (x *term) intersect(y *term) *term { + // easy cases + switch { + case x == nil || y == nil: + return nil // ∅ ∩ y == ∅ and ∩ ∅ == ∅ + case x.typ == nil: + return y // ⊤ ∩ y == y + case y.typ == nil: + return x // x ∩ ⊤ == x + } + // ∅ ⊂ x, y ⊂ ⊤ + + if x.disjoint(y) { + return nil // x ∩ y == ∅ if x ∩ y == ∅ + } + // x.typ == y.typ + + // ~t ∩ ~t == ~t + // ~t ∩ T == T + // T ∩ ~t == T + // T ∩ T == T + if !x.tilde || y.tilde { + return x + } + return y +} + +// includes reports whether t ∈ x. +func (x *term) includes(t Type) bool { + // easy cases + switch { + case x == nil: + return false // t ∈ ∅ == false + case x.typ == nil: + return true // t ∈ ⊤ == true + } + // ∅ ⊂ x ⊂ ⊤ + + u := t + if x.tilde { + u = under(u) + } + return Identical(x.typ, u) +} + +// subsetOf reports whether x ⊆ y. +func (x *term) subsetOf(y *term) bool { + // easy cases + switch { + case x == nil: + return true // ∅ ⊆ y == true + case y == nil: + return false // x ⊆ ∅ == false since x != ∅ + case y.typ == nil: + return true // x ⊆ ⊤ == true + case x.typ == nil: + return false // ⊤ ⊆ y == false since y != ⊤ + } + // ∅ ⊂ x, y ⊂ ⊤ + + if x.disjoint(y) { + return false // x ⊆ y == false if x ∩ y == ∅ + } + // x.typ == y.typ + + // ~t ⊆ ~t == true + // ~t ⊆ T == false + // T ⊆ ~t == true + // T ⊆ T == true + return !x.tilde || y.tilde +} + +// disjoint reports whether x ∩ y == ∅. +// x.typ and y.typ must not be nil. +func (x *term) disjoint(y *term) bool { + ux := x.typ + if y.tilde { + ux = under(ux) + } + uy := y.typ + if x.tilde { + uy = under(uy) + } + return !Identical(ux, uy) +} diff --git a/src/go/types/typeterm_test.go b/src/go/types/typeterm_test.go new file mode 100644 index 0000000000..391ff3e05f --- /dev/null +++ b/src/go/types/typeterm_test.go @@ -0,0 +1,205 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +import ( + "strings" + "testing" +) + +var testTerms = map[string]*term{ + "∅": nil, + "⊤": {}, + "int": {false, Typ[Int]}, + "~int": {true, Typ[Int]}, + "string": {false, Typ[String]}, + "~string": {true, Typ[String]}, + // TODO(gri) add a defined type +} + +func TestTermString(t *testing.T) { + for want, x := range testTerms { + if got := x.String(); got != want { + t.Errorf("%v.String() == %v; want %v", x, got, want) + } + } +} + +func split(s string, n int) []string { + r := strings.Split(s, " ") + if len(r) != n { + panic("invalid test case: " + s) + } + return r +} + +func testTerm(name string) *term { + r, ok := testTerms[name] + if !ok { + panic("invalid test argument: " + name) + } + return r +} + +func TestTermEqual(t *testing.T) { + for _, test := range []string{ + "∅ ∅ T", + "⊤ ⊤ T", + "int int T", + "~int ~int T", + "∅ ⊤ F", + "∅ int F", + "∅ ~int F", + "⊤ int F", + "⊤ ~int F", + "int ~int F", + } { + args := split(test, 3) + x := testTerm(args[0]) + y := testTerm(args[1]) + want := args[2] == "T" + if got := x.equal(y); got != want { + t.Errorf("%v.equal(%v) = %v; want %v", x, y, got, want) + } + // equal is symmetric + x, y = y, x + if got := x.equal(y); got != want { + t.Errorf("%v.equal(%v) = %v; want %v", x, y, got, want) + } + } +} + +func TestTermUnion(t *testing.T) { + for _, test := range []string{ + "∅ ∅ ∅ ∅", + "∅ ⊤ ⊤ ∅", + "∅ int int ∅", + "∅ ~int ~int ∅", + "⊤ ⊤ ⊤ ∅", + "⊤ int ⊤ ∅", + "⊤ ~int ⊤ ∅", + "int int int ∅", + "int ~int ~int ∅", + "int string int string", + "int ~string int ~string", + "~int ~string ~int ~string", + + // union is symmetric, but the result order isn't - repeat symmetric cases explictly + "⊤ ∅ ⊤ ∅", + "int ∅ int ∅", + "~int ∅ ~int ∅", + "int ⊤ ⊤ ∅", + "~int ⊤ ⊤ ∅", + "~int int ~int ∅", + "string int string int", + "~string int ~string int", + "~string ~int ~string ~int", + } { + args := split(test, 4) + x := testTerm(args[0]) + y := testTerm(args[1]) + want1 := testTerm(args[2]) + want2 := testTerm(args[3]) + if got1, got2 := x.union(y); !got1.equal(want1) || !got2.equal(want2) { + t.Errorf("%v.union(%v) = %v, %v; want %v, %v", x, y, got1, got2, want1, want2) + } + } +} + +func TestTermIntersection(t *testing.T) { + for _, test := range []string{ + "∅ ∅ ∅", + "∅ ⊤ ∅", + "∅ int ∅", + "∅ ~int ∅", + "⊤ ⊤ ⊤", + "⊤ int int", + "⊤ ~int ~int", + "int int int", + "int ~int int", + "int string ∅", + "int ~string ∅", + "~int ~string ∅", + } { + args := split(test, 3) + x := testTerm(args[0]) + y := testTerm(args[1]) + want := testTerm(args[2]) + if got := x.intersect(y); !got.equal(want) { + t.Errorf("%v.intersect(%v) = %v; want %v", x, y, got, want) + } + // intersect is symmetric + x, y = y, x + if got := x.intersect(y); !got.equal(want) { + t.Errorf("%v.intersect(%v) = %v; want %v", x, y, got, want) + } + } +} + +func TestTermIncludes(t *testing.T) { + for _, test := range []string{ + "∅ int F", + "⊤ int T", + "int int T", + "~int int T", + "string int F", + "~string int F", + } { + args := split(test, 3) + x := testTerm(args[0]) + y := testTerm(args[1]).typ + want := args[2] == "T" + if got := x.includes(y); got != want { + t.Errorf("%v.includes(%v) = %v; want %v", x, y, got, want) + } + } +} + +func TestTermSubsetOf(t *testing.T) { + for _, test := range []string{ + "∅ ∅ T", + "⊤ ⊤ T", + "int int T", + "~int ~int T", + "∅ ⊤ T", + "∅ int T", + "∅ ~int T", + "⊤ int F", + "⊤ ~int F", + "int ~int T", + } { + args := split(test, 3) + x := testTerm(args[0]) + y := testTerm(args[1]) + want := args[2] == "T" + if got := x.subsetOf(y); got != want { + t.Errorf("%v.subsetOf(%v) = %v; want %v", x, y, got, want) + } + } +} + +func TestTermDisjoint(t *testing.T) { + for _, test := range []string{ + "int int F", + "~int ~int F", + "int ~int F", + "int string T", + "int ~string T", + "~int ~string T", + } { + args := split(test, 3) + x := testTerm(args[0]) + y := testTerm(args[1]) + want := args[2] == "T" + if got := x.disjoint(y); got != want { + t.Errorf("%v.disjoint(%v) = %v; want %v", x, y, got, want) + } + // disjoint is symmetric + x, y = y, x + if got := x.disjoint(y); got != want { + t.Errorf("%v.disjoint(%v) = %v; want %v", x, y, got, want) + } + } +} -- GitLab From 880ab6209e618c7dd6e47fa07e66176cd801eba1 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Tue, 3 Aug 2021 20:36:02 -0400 Subject: [PATCH 0601/2500] [dev.typeparams] cmd/compile/internal/types2: fix a panic in missingMethod When static == false, missingMethod incorrectly continues with a nil Func. Also remove some unnecessary type names from typeterm_test.go, which was done in the go/types port. Change-Id: I21fa637ac82b115563d3601314a470a5a43f9ae0 Reviewed-on: https://go-review.googlesource.com/c/go/+/339672 Trust: Robert Findley Trust: Robert Griesemer Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/lookup.go | 5 ++++- src/cmd/compile/internal/types2/typeterm_test.go | 10 +++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index 41e5bc7811..f62c3771d2 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -308,7 +308,10 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, for _, m := range T.typeSet().methods { _, f := ityp.typeSet().LookupMethod(m.pkg, m.name) - if f == nil && static { + if f == nil { + if !static { + continue + } return m, f } diff --git a/src/cmd/compile/internal/types2/typeterm_test.go b/src/cmd/compile/internal/types2/typeterm_test.go index 4676fb0437..cc4e30d989 100644 --- a/src/cmd/compile/internal/types2/typeterm_test.go +++ b/src/cmd/compile/internal/types2/typeterm_test.go @@ -11,11 +11,11 @@ import ( var testTerms = map[string]*term{ "∅": nil, - "⊤": &term{}, - "int": &term{false, Typ[Int]}, - "~int": &term{true, Typ[Int]}, - "string": &term{false, Typ[String]}, - "~string": &term{true, Typ[String]}, + "⊤": {}, + "int": {false, Typ[Int]}, + "~int": {true, Typ[Int]}, + "string": {false, Typ[String]}, + "~string": {true, Typ[String]}, // TODO(gri) add a defined type } -- GitLab From ed3667d0795c6567dc5635d6c5c38c2abff4c8e4 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Tue, 3 Aug 2021 21:10:42 -0400 Subject: [PATCH 0602/2500] [dev.typeparams] go/types: use type terms to represent unions This is a straightforward port of CL 338092 to go/types. Change-Id: I414ec0ad95648c201e85fd2b4f494b1206c658e7 Reviewed-on: https://go-review.googlesource.com/c/go/+/339674 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/infer.go | 18 ++- src/go/types/interface.go | 6 +- src/go/types/operand.go | 6 +- src/go/types/predicates.go | 16 +-- src/go/types/sizeof_test.go | 3 +- src/go/types/subst.go | 22 +++- .../types/testdata/examples/constraints.go2 | 6 +- src/go/types/type.go | 2 +- src/go/types/typeset.go | 7 ++ src/go/types/typestring.go | 6 +- src/go/types/union.go | 117 +++++++++++------- 11 files changed, 130 insertions(+), 79 deletions(-) diff --git a/src/go/types/infer.go b/src/go/types/infer.go index f3f69e01b6..6e70a103e7 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -303,7 +303,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { } case *Union: - return w.isParameterizedList(t.types) + return w.isParameterizedTermList(t.terms) case *Signature: // t.tparams may not be nil if we are looking at a signature @@ -331,7 +331,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { return w.isParameterized(t.elem) case *Named: - return w.isParameterizedList(t.targs) + return w.isParameterizedTypeList(t.targs) case *TypeParam: // t must be one of w.tparams @@ -344,7 +344,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { return false } -func (w *tpWalker) isParameterizedList(list []Type) bool { +func (w *tpWalker) isParameterizedTypeList(list []Type) bool { for _, t := range list { if w.isParameterized(t) { return true @@ -353,6 +353,15 @@ func (w *tpWalker) isParameterizedList(list []Type) bool { return false } +func (w *tpWalker) isParameterizedTermList(list []*term) bool { + for _, t := range list { + if w.isParameterized(t.typ) { + return true + } + } + return false +} + // inferB returns the list of actual type arguments inferred from the type parameters' // bounds and an initial set of type arguments. If type inference is impossible because // unification fails, an error is reported if report is set to true, the resulting types @@ -461,7 +470,8 @@ func (check *Checker) structuralType(constraint Type) Type { if u, _ := types.(*Union); u != nil { if u.NumTerms() == 1 { // TODO(gri) do we need to respect tilde? - return u.types[0] + t, _ := u.Term(0) + return t } return nil } diff --git a/src/go/types/interface.go b/src/go/types/interface.go index 51eff8fbdd..e98e40179c 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -34,7 +34,7 @@ func (t *Interface) is(f func(Type, bool) bool) bool { // TODO(gri) should settle on top or nil to represent this case return false // we must have at least one type! (was bug) case *Union: - return t.is(func(typ Type, tilde bool) bool { return f(typ, tilde) }) + return t.is(func(t *term) bool { return f(t.typ, t.tilde) }) default: return f(t, false) } @@ -266,8 +266,8 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d // (don't sort embeddeds: they must correspond to *embedPos entries) // Compute type set with a non-nil *Checker as soon as possible - // to report any errors. Subsequent uses of type sets should be - // using this computed type set and won't need to pass in a *Checker. + // to report any errors. Subsequent uses of type sets will use + // this computed type set and won't need to pass in a *Checker. check.later(func() { computeTypeSet(check, iface.Pos(), ityp) }) } diff --git a/src/go/types/operand.go b/src/go/types/operand.go index 1d0f5b80b6..c605cf781c 100644 --- a/src/go/types/operand.go +++ b/src/go/types/operand.go @@ -255,13 +255,13 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er // x is an untyped value representable by a value of type T. if isUntyped(Vu) { if t, ok := Tu.(*Union); ok { - return t.is(func(t Type, tilde bool) bool { + return t.is(func(t *term) bool { // TODO(gri) this could probably be more efficient - if tilde { + if t.tilde { // TODO(gri) We need to check assignability // for the underlying type of x. } - ok, _ := x.assignableTo(check, t, reason) + ok, _ := x.assignableTo(check, t.typ, reason) return ok }), _IncompatibleAssign } diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index caf72c2f2e..579d35da42 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -238,20 +238,8 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { // types - each type appears exactly once. Thus, two union types // must contain the same number of types to have chance of // being equal. - if y, ok := y.(*Union); ok && x.NumTerms() == y.NumTerms() { - // Every type in x.types must be in y.types. - // Quadratic algorithm, but probably good enough for now. - // TODO(gri) we need a fast quick type ID/hash for all types. - L: - for i, xt := range x.types { - for j, yt := range y.types { - if Identical(xt, yt) && x.tilde[i] == y.tilde[j] { - continue L // x is in y.types - } - } - return false // x is not in y.types - } - return true + if y, ok := y.(*Union); ok { + return identicalTerms(x.terms, y.terms) } case *Interface: diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index b892e7e521..75122b0273 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -26,12 +26,13 @@ func TestSizeof(t *testing.T) { {Pointer{}, 8, 16}, {Tuple{}, 12, 24}, {Signature{}, 28, 56}, - {Union{}, 24, 48}, + {Union{}, 12, 24}, {Interface{}, 40, 80}, {Map{}, 16, 32}, {Chan{}, 12, 24}, {Named{}, 80, 152}, {TypeParam{}, 28, 48}, + {term{}, 12, 24}, {top{}, 0, 0}, // Objects diff --git a/src/go/types/subst.go b/src/go/types/subst.go index c05e51d425..322e30d357 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -148,12 +148,12 @@ func (subst *subster) typ(typ Type) Type { } case *Union: - types, copied := subst.typeList(t.types) + terms, copied := subst.termList(t.terms) if copied { // TODO(gri) Remove duplicates that may have crept in after substitution // (unlikely but possible). This matters for the Identical // predicate on unions. - return newUnion(types, t.tilde) + return &Union{terms} } case *Interface: @@ -393,3 +393,21 @@ func (subst *subster) typeList(in []Type) (out []Type, copied bool) { } return } + +func (subst *subster) termList(in []*term) (out []*term, copied bool) { + out = in + for i, t := range in { + if u := subst.typ(t.typ); u != t.typ { + if !copied { + // first function that got substituted => allocate new out slice + // and copy all functions + new := make([]*term, len(in)) + copy(new, out) + out = new + copied = true + } + out[i] = &term{t.tilde, u} + } + } + return +} diff --git a/src/go/types/testdata/examples/constraints.go2 b/src/go/types/testdata/examples/constraints.go2 index d9805fe694..28aa19bb12 100644 --- a/src/go/types/testdata/examples/constraints.go2 +++ b/src/go/types/testdata/examples/constraints.go2 @@ -31,9 +31,9 @@ type ( _ interface{int|~ /* ERROR duplicate term int */ int } _ interface{~int|~ /* ERROR duplicate term int */ int } - // For now we do not permit interfaces with ~ or in unions. - _ interface{~ /* ERROR cannot use interface */ interface{}} - _ interface{int|interface /* ERROR cannot use interface */ {}} + // For now we do not permit interfaces with methods in unions. + _ interface{~ /* ERROR invalid use of ~ */ interface{}} + _ interface{int|interface /* ERROR cannot use .* in union */ { m() }} ) type ( diff --git a/src/go/types/type.go b/src/go/types/type.go index b575b11e4e..2ad89d9705 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -60,7 +60,7 @@ func optype(typ Type) Type { // If we have a union with a single entry, ignore // any tilde because under(~t) == under(t). if u, _ := a.(*Union); u != nil && u.NumTerms() == 1 { - a = u.types[0] + a, _ = u.Term(0) } if a != typ { // a != typ and a is a type parameter => under(a) != typ, so this is ok diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index 226e438cc9..cbd867dd95 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -43,6 +43,13 @@ func (s *TypeSet) IsComparable() bool { return s.comparable && tcomparable } +// TODO(gri) IsTypeSet is not a great name. Find a better one. + +// IsTypeSet reports whether the type set s is represented by a finite set of underlying types. +func (s *TypeSet) IsTypeSet() bool { + return !s.comparable && len(s.methods) == 0 +} + // NumMethods returns the number of methods available. func (s *TypeSet) NumMethods() int { return len(s.methods) } diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 74b18a9ec8..c0c69624ec 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -163,14 +163,14 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { buf.WriteString("⊥") break } - for i, e := range t.types { + for i, t := range t.terms { if i > 0 { buf.WriteByte('|') } - if t.tilde[i] { + if t.tilde { buf.WriteByte('~') } - writeType(buf, e, qf, visited) + writeType(buf, t.typ, qf, visited) } case *Interface: diff --git a/src/go/types/union.go b/src/go/types/union.go index 556be46bf6..a56f9d29f3 100644 --- a/src/go/types/union.go +++ b/src/go/types/union.go @@ -13,10 +13,8 @@ import ( // API // A Union represents a union of terms. -// A term is a type with a ~ (tilde) flag. type Union struct { - types []Type // types are unique - tilde []bool // if tilde[i] is set, terms[i] is of the form ~T + terms []*term } // NewUnion returns a new Union type with the given terms (types[i], tilde[i]). @@ -24,9 +22,9 @@ type Union struct { // of no types. func NewUnion(types []Type, tilde []bool) *Union { return newUnion(types, tilde) } -func (u *Union) IsEmpty() bool { return len(u.types) == 0 } -func (u *Union) NumTerms() int { return len(u.types) } -func (u *Union) Term(i int) (Type, bool) { return u.types[i], u.tilde[i] } +func (u *Union) IsEmpty() bool { return len(u.terms) == 0 } +func (u *Union) NumTerms() int { return len(u.terms) } +func (u *Union) Term(i int) (Type, bool) { t := u.terms[i]; return t.typ, t.tilde } func (u *Union) Underlying() Type { return u } func (u *Union) String() string { return TypeString(u, nil) } @@ -42,18 +40,20 @@ func newUnion(types []Type, tilde []bool) *Union { return emptyUnion } t := new(Union) - t.types = types - t.tilde = tilde + t.terms = make([]*term, len(types)) + for i, typ := range types { + t.terms[i] = &term{tilde[i], typ} + } return t } -// is reports whether f returned true for all terms (type, tilde) of u. -func (u *Union) is(f func(Type, bool) bool) bool { +// is reports whether f returns true for all terms of u. +func (u *Union) is(f func(*term) bool) bool { if u.IsEmpty() { return false } - for i, t := range u.types { - if !f(t, u.tilde[i]) { + for _, t := range u.terms { + if !f(t) { return false } } @@ -65,8 +65,8 @@ func (u *Union) underIs(f func(Type) bool) bool { if u.IsEmpty() { return false } - for _, t := range u.types { - if !f(under(t)) { + for _, t := range u.terms { + if !f(under(t.typ)) { return false } } @@ -86,7 +86,7 @@ func parseUnion(check *Checker, tlist []ast.Expr) Type { } // Ensure that each type is only present once in the type list. - // It's ok to do this check at the end because it's not a requirement + // It's ok to do this check later because it's not a requirement // for correctness of the code. // Note: This is a quadratic algorithm, but unions tend to be short. check.later(func() { @@ -99,7 +99,7 @@ func parseUnion(check *Checker, tlist []ast.Expr) Type { x := tlist[i] pos := x.Pos() // We may not know the position of x if it was a typechecker- - // introduced ~T type of a type list entry T. Use the position + // introduced ~T term for a type list entry T. Use the position // of T instead. // TODO(rfindley) remove this test once we don't support type lists anymore if !pos.IsValid() { @@ -109,13 +109,24 @@ func parseUnion(check *Checker, tlist []ast.Expr) Type { } u := under(t) - if tilde[i] && !Identical(u, t) { - check.errorf(x, _Todo, "invalid use of ~ (underlying type of %s is %s)", t, u) - continue // don't report another error for t + f, _ := u.(*Interface) + if tilde[i] { + if f != nil { + check.errorf(x, _Todo, "invalid use of ~ (%s is an interface)", t) + continue // don't report another error for t + } + + if !Identical(u, t) { + check.errorf(x, _Todo, "invalid use of ~ (underlying type of %s is %s)", t, u) + continue // don't report another error for t + } } - if _, ok := u.(*Interface); ok { - // A single type with a ~ is a single-term union. - check.errorf(atPos(pos), _Todo, "cannot use interface %s with ~ or inside a union (implementation restriction)", t) + + // Stand-alone embedded interfaces are ok and are handled by the single-type case + // in the beginning. Embedded interfaces with tilde are excluded above. If we reach + // here, we must have at least two terms in the union. + if f != nil && !f.typeSet().IsTypeSet() { + check.errorf(atPos(pos), _Todo, "cannot use %s in union (interface contains methods)", t) continue // don't report another error for t } @@ -167,25 +178,7 @@ func intersect(x, y Type) (r Type) { yu, _ := y.(*Union) switch { case xu != nil && yu != nil: - // Quadratic algorithm, but good enough for now. - // TODO(gri) fix asymptotic performance - var types []Type - var tilde []bool - for j, y := range yu.types { - yt := yu.tilde[j] - if r, rt := xu.intersect(y, yt); r != nil { - // Terms x[i] and y[j] match: Select the one that - // is not a ~t because that is the intersection - // type. If both are ~t, they are identical: - // T ∩ T = T - // T ∩ ~t = T - // ~t ∩ T = T - // ~t ∩ ~t = ~t - types = append(types, r) - tilde = append(tilde, rt) - } - } - return newUnion(types, tilde) + return &Union{intersectTerms(xu.terms, yu.terms)} case xu != nil: if r, _ := xu.intersect(y, false); r != nil { @@ -219,14 +212,16 @@ func includes(list []Type, typ Type) bool { // intersect computes the intersection of the union u and term (y, yt) // and returns the intersection term, if any. Otherwise the result is // (nil, false). +// TODO(gri) this needs to cleaned up/removed once we switch to lazy +// union type set computation. func (u *Union) intersect(y Type, yt bool) (Type, bool) { under_y := under(y) - for i, x := range u.types { - xt := u.tilde[i] + for _, x := range u.terms { + xt := x.tilde // determine which types xx, yy to compare - xx := x + xx := x.typ if yt { - xx = under(x) + xx = under(xx) } yy := y if xt { @@ -242,3 +237,35 @@ func (u *Union) intersect(y Type, yt bool) (Type, bool) { } return nil, false } + +func identicalTerms(list1, list2 []*term) bool { + if len(list1) != len(list2) { + return false + } + // Every term in list1 must be in list2. + // Quadratic algorithm, but probably good enough for now. + // TODO(gri) we need a fast quick type ID/hash for all types. +L: + for _, x := range list1 { + for _, y := range list2 { + if x.equal(y) { + continue L // x is in list2 + } + } + return false + } + return true +} + +func intersectTerms(list1, list2 []*term) (list []*term) { + // Quadratic algorithm, but good enough for now. + // TODO(gri) fix asymptotic performance + for _, x := range list1 { + for _, y := range list2 { + if r := x.intersect(y); r != nil { + list = append(list, r) + } + } + } + return +} -- GitLab From 3efc8f9a8dc93ccacb8b139cafc44ee0709d8fdd Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Tue, 3 Aug 2021 21:14:31 -0400 Subject: [PATCH 0603/2500] [dev.typeparams] go/types: (TypeParam) SetBound -> SetConstraint This is a straightforward port of CL 338196 to go/types, minus the deprecated TypeParam.Bound() method (since it is not needed), plus an adjustment for methodset.go. Change-Id: Ie372bfeec245094102a2c3257a43499d75981447 Reviewed-on: https://go-review.googlesource.com/c/go/+/339675 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/builtins.go | 2 +- src/go/types/call.go | 2 +- src/go/types/instantiate.go | 6 +++--- src/go/types/lookup.go | 2 +- src/go/types/methodset.go | 2 +- src/go/types/predicates.go | 2 +- src/go/types/type.go | 2 +- src/go/types/typeparam.go | 25 +++++++++++-------------- 8 files changed, 20 insertions(+), 23 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index ecb9920a81..aae05438cd 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -826,7 +826,7 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { // type and collect possible result types at the same time. var rtypes []Type var tildes []bool - if !tp.Bound().is(func(typ Type, tilde bool) bool { + if !tp.iface().is(func(typ Type, tilde bool) bool { if r := f(typ); r != nil { rtypes = append(rtypes, r) tildes = append(tildes, tilde) diff --git a/src/go/types/call.go b/src/go/types/call.go index 16b8e4eb7c..da2f319a4a 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -482,7 +482,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { var why string if tpar := asTypeParam(x.typ); tpar != nil { // Type parameter bounds don't specify fields, so don't mention "field". - if tname := tpar.Bound().obj; tname != nil { + if tname := tpar.iface().obj; tname != nil { why = check.sprintf("interface %s has no method %s", tname.name, sel) } else { why = check.sprintf("type bound for %s has no method %s", x.typ, sel) diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 2e6c20723b..6d56eb7ea2 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -162,7 +162,7 @@ func (check *Checker) verify(pos token.Pos, tparams []*TypeName, targs []Type, p // A suitable error is reported if the result is false. // TODO(gri) This should be a method of interfaces or type sets. func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap *substMap) bool { - iface := tpar.Bound() + iface := tpar.iface() if iface.Empty() { return true // no type bound } @@ -176,7 +176,7 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap // if iface is comparable, targ must be comparable // TODO(gri) the error messages needs to be better, here if iface.IsComparable() && !Comparable(targ) { - if tpar := asTypeParam(targ); tpar != nil && tpar.Bound().typeSet().IsTop() { + if tpar := asTypeParam(targ); tpar != nil && tpar.iface().typeSet().IsTop() { check.softErrorf(atPos(pos), _Todo, "%s has no constraints", targ) return false } @@ -222,7 +222,7 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap // If targ is itself a type parameter, each of its possible types, but at least one, must be in the // list of iface types (i.e., the targ type list must be a non-empty subset of the iface types). if targ := asTypeParam(targ); targ != nil { - targBound := targ.Bound() + targBound := targ.iface() if targBound.typeSet().types == nil { check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ) return false diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index 6d38db4523..7cab336dbe 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -190,7 +190,7 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o } case *TypeParam: - if i, m := t.Bound().typeSet().LookupMethod(pkg, name); m != nil { + if i, m := t.iface().typeSet().LookupMethod(pkg, name); m != nil { assert(m.typ != nil) index = concat(e.index, i) if obj != nil || e.multiples { diff --git a/src/go/types/methodset.go b/src/go/types/methodset.go index 491917d6bc..1462601d58 100644 --- a/src/go/types/methodset.go +++ b/src/go/types/methodset.go @@ -160,7 +160,7 @@ func NewMethodSet(T Type) *MethodSet { mset = mset.add(t.typeSet().methods, e.index, true, e.multiples) case *TypeParam: - mset = mset.add(t.Bound().typeSet().methods, e.index, true, e.multiples) + mset = mset.add(t.iface().typeSet().methods, e.index, true, e.multiples) } } diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 579d35da42..f9cac34a03 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -113,7 +113,7 @@ func comparable(T Type, seen map[Type]bool) bool { case *Array: return comparable(t.elem, seen) case *TypeParam: - return t.Bound().IsComparable() + return t.iface().IsComparable() } return false } diff --git a/src/go/types/type.go b/src/go/types/type.go index 2ad89d9705..5819dd290c 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -56,7 +56,7 @@ func optype(typ Type) Type { // for a type parameter list of the form: // (type T interface { type T }). // See also issue #39680. - if a := t.Bound().typeSet().types; a != nil && a != typ { + if a := t.iface().typeSet().types; a != nil && a != typ { // If we have a union with a single entry, ignore // any tilde because under(~t) == under(t). if u, _ := a.(*Union); u != nil && u.NumTerms() == 1 { diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index 8cb44ea25e..33a516c209 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -74,23 +74,20 @@ func (t *TypeParam) Constraint() Type { return t.bound } -// Bound returns the underlying type of the type parameter's -// constraint. -// Deprecated for external use. Use Constraint instead. -func (t *TypeParam) Bound() *Interface { - if iface, _ := under(t.Constraint()).(*Interface); iface != nil { - return iface +// SetConstraint sets the type constraint for t. +func (t *TypeParam) SetConstraint(bound Type) { + if bound == nil { + panic("types2.TypeParam.SetConstraint: bound must not be nil") } - return &emptyInterface + t.bound = bound } -// TODO(rfindley): document the SetBound methods. - -func (t *TypeParam) SetBound(bound Type) { - if bound == nil { - panic("internal error: bound must not be nil") +// iface returns the constraint interface of t. +func (t *TypeParam) iface() *Interface { + if iface, _ := under(t.Constraint()).(*Interface); iface != nil { + return iface } - t.bound = bound + return &emptyInterface } func (t *TypeParam) Underlying() Type { return t } @@ -135,5 +132,5 @@ func bindTParams(list []*TypeName) *TypeParams { // Implementation func (t *TypeParam) underIs(f func(Type) bool) bool { - return t.Bound().typeSet().underIs(f) + return t.iface().typeSet().underIs(f) } -- GitLab From b01e775e9c05dd2e5fa19ea06ac09f9a12ae660e Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Tue, 3 Aug 2021 21:39:53 -0400 Subject: [PATCH 0604/2500] [dev.typeparams] go/types: print constraint info for type param operands This is a clean port of CL 338309 to go/types. Change-Id: Ie2c9e2ea51d6321af8bf149e43cd71b7ac282d13 Reviewed-on: https://go-review.googlesource.com/c/go/+/339676 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/operand.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/go/types/operand.go b/src/go/types/operand.go index c605cf781c..aea8bf5e7a 100644 --- a/src/go/types/operand.go +++ b/src/go/types/operand.go @@ -159,16 +159,20 @@ func operandString(x *operand, qf Qualifier) string { if hasType { if x.typ != Typ[Invalid] { var intro string - switch { - case isGeneric(x.typ): - intro = " of generic type " - case asTypeParam(x.typ) != nil: - intro = " of type parameter type " - default: + var tpar *TypeParam + if isGeneric(x.typ) { + intro = " of parameterized type " + } else if tpar = asTypeParam(x.typ); tpar != nil { + intro = " of type parameter " + } else { intro = " of type " } buf.WriteString(intro) WriteType(&buf, x.typ, qf) + if tpar != nil { + buf.WriteString(" constrained by ") + WriteType(&buf, tpar.bound, qf) // do not compute interface type sets here + } } else { buf.WriteString(" with invalid type") } -- GitLab From d27a889119ce05b1faae29aa549887e86ce453df Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Tue, 3 Aug 2021 21:43:39 -0400 Subject: [PATCH 0605/2500] [dev.typeparams] go/types: move instance.go contents into named.go (cleanup) This is a port of CL 338469 to go/types. Change-Id: I3ee655fa2dc7e789f210c8dec171b3358c4ff132 Reviewed-on: https://go-review.googlesource.com/c/go/+/339677 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/instance.go | 44 -------------------------------------- src/go/types/named.go | 40 +++++++++++++++++++++++++++++++++- src/go/types/predicates.go | 6 ------ src/go/types/unify.go | 3 --- 4 files changed, 39 insertions(+), 54 deletions(-) delete mode 100644 src/go/types/instance.go diff --git a/src/go/types/instance.go b/src/go/types/instance.go deleted file mode 100644 index 1223c9f6f1..0000000000 --- a/src/go/types/instance.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package types - -// TODO(rfindley): move this code to named.go. - -import "go/token" - -// instance holds position information for use in lazy instantiation. -// -// TODO(rfindley): come up with a better name for this type, now that its usage -// has changed. -type instance struct { - pos token.Pos // position of type instantiation; for error reporting only - posList []token.Pos // position of each targ; for error reporting only -} - -// expand ensures that the underlying type of n is instantiated. -// The underlying type will be Typ[Invalid] if there was an error. -// TODO(rfindley): expand would be a better name for this method, but conflicts -// with the existing concept of lazy expansion. Need to reconcile this. -func (n *Named) expand() { - if n.instance != nil { - // n must be loaded before instantiation, in order to have accurate - // tparams. This is done implicitly by the call to n.TParams, but making it - // explicit is harmless: load is idempotent. - n.load() - inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams().list(), n.targs, n.instance.posList) - n.underlying = inst - n.fromRHS = inst - n.instance = nil - } -} - -// expand expands uninstantiated named types and leaves all other types alone. -// expand does not recurse. -func expand(typ Type) Type { - if t, _ := typ.(*Named); t != nil { - t.expand() - } - return typ -} diff --git a/src/go/types/named.go b/src/go/types/named.go index 87eaa3179e..fc53783ab8 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -4,7 +4,10 @@ package types -import "sync" +import ( + "go/token" + "sync" +) // TODO(rfindley) Clean up Named struct below; specifically the fromRHS field (can we use underlying?). @@ -252,3 +255,38 @@ func (n *Named) setUnderlying(typ Type) { n.underlying = typ } } + +// instance holds position information for use in lazy instantiation. +// +// TODO(rfindley): come up with a better name for this type, now that its usage +// has changed. +type instance struct { + pos token.Pos // position of type instantiation; for error reporting only + posList []token.Pos // position of each targ; for error reporting only +} + +// expand ensures that the underlying type of n is instantiated. +// The underlying type will be Typ[Invalid] if there was an error. +// TODO(rfindley): expand would be a better name for this method, but conflicts +// with the existing concept of lazy expansion. Need to reconcile this. +func (n *Named) expand() { + if n.instance != nil { + // n must be loaded before instantiation, in order to have accurate + // tparams. This is done implicitly by the call to n.TParams, but making it + // explicit is harmless: load is idempotent. + n.load() + inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams().list(), n.targs, n.instance.posList) + n.underlying = inst + n.fromRHS = inst + n.instance = nil + } +} + +// expand expands uninstantiated named types and leaves all other types alone. +// expand does not recurse. +func expand(typ Type) Type { + if t, _ := typ.(*Named); t != nil { + t.expand() + } + return typ +} diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index f9cac34a03..23924693fd 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -57,9 +57,6 @@ func isNumericOrString(typ Type) bool { return is(typ, IsNumeric|IsString) } func isTyped(typ Type) bool { // isTyped is called with types that are not fully // set up. Must not call asBasic()! - // A *Named or *instance type is always typed, so - // we only need to check if we have a true *Basic - // type. t, _ := typ.(*Basic) return t == nil || t.info&IsUntyped == 0 } @@ -328,9 +325,6 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { case *TypeParam: // nothing to do (x and y being equal is caught in the very beginning of this function) - // case *instance: - // unreachable since types are expanded - case *top: // Either both types are theTop in which case the initial x == y check // will have caught them. Otherwise they are not identical. diff --git a/src/go/types/unify.go b/src/go/types/unify.go index da57e533cc..90a5cf7c72 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -456,9 +456,6 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { // are identical if they originate in the same declaration. return x == y - // case *instance: - // unreachable since types are expanded - case nil: // avoid a crash in case of nil type -- GitLab From e590cb64f940b2d4996a6e7773c1b855be952632 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Wed, 4 Aug 2021 08:54:09 -0400 Subject: [PATCH 0606/2500] [dev.typeparams] runtime: handle d.link carefully when freeing a defer CL 339396 allowed stack copying on entry to and during freedefer, but this introduced a subtle bug: if d is heap-allocated, and d.link points to a stack-allocated defer, stack copying during freedefer can briefly introduce a stale pointer, which the garbage collector can discover and panic about. This happens because d has already been unlinked from the defer chain when freedefer is called, so stack copying won't update stack pointers in it. Fix this by making freedefer nosplit again and immediately clearing d.link. This should fix the longtest builders, which currently fail on GOMAXPROCS=2 runtime -cpu=1,2,4 -quick in the TestDeferHeapAndStack test. This seems like the simplest fix, but it just deals with the subtlety rather than eliminating it. Really, every call site of freedefer (of which there are surprisingly many) has hidden subtlety between unlinking the defer and calling freedefer. We could consolidate the subtlety into each call site by requiring that they unlink the defer and set d.link to nil before calling freedefer. freedefer could check this condition like it checks that various other fields have already been zeroed. A more radical option is to replace freedefer with "popDefer", which would both pop the defer off the link and take care of freeing it. There would still be a brief moment of subtlety, but it would be in one place, in popDefer. Annoyingly, *almost* every call to freedefer just pops the defer from the head of the G's list, but there's one place when handling open-coded defers where we have to remove a defer from the middle of the list. I'm inclined to first fix that subtlety by only expanding open-coded defer records when they're at the head of the defer list, and then revisit the popDefer idea. Change-Id: I3130d2542c01a421a5d60e8c31f5379263219627 Reviewed-on: https://go-review.googlesource.com/c/go/+/339730 Trust: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/panic.go | 10 ++++++++++ src/runtime/runtime2.go | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/runtime/panic.go b/src/runtime/panic.go index 48b1b5dd9d..e4bdceb32f 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -338,7 +338,17 @@ func newdefer() *_defer { // Free the given defer. // The defer cannot be used after this call. +// +// This is nosplit because the incoming defer is in a perilous state. +// It's not on any defer list, so stack copying won't adjust stack +// pointers in it (namely, d.link). Hence, if we were to copy the +// stack, d could then contain a stale pointer. +// +//go:nosplit func freedefer(d *_defer) { + d.link = nil + // After this point we can copy the stack. + if d._panic != nil { freedeferpanic() } diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index b5e4b3dec8..c5e2501991 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -957,7 +957,7 @@ type _defer struct { pc uintptr // pc at time of defer fn func() // can be nil for open-coded defers _panic *_panic // panic that is running defer - link *_defer + link *_defer // next defer on G; can point to either heap or stack! // If openDefer is true, the fields below record values about the stack // frame and associated function that has the open-coded defer(s). sp -- GitLab From b730a26729ec8c00c3e31e564f9b5cf8b1deb580 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 3 Aug 2021 19:33:01 -0700 Subject: [PATCH 0607/2500] [dev.typeparams] cmd/compile: put shape types in their own package Put shape types in the top level package called ".shape". Name them using the serialization of the shape name, instead of the .shapeN names. This allows the linker to deduplicate instantiations across packages. Not sure that this is entirely correct, as shapes in this package may reference other packages (e.g. a field of a struct). But it seems to work for now. For the added test, when you look at the resulting binary (use the -k option with run.go) it has only one instantiation of F, and 4 call sites: $ objdump -d a.exe | grep _a\.F 1053cb0: e8 8b 00 00 00 callq 139 <_a.F[.shape.*uint8]> 1053ce9: e8 52 00 00 00 callq 82 <_a.F[.shape.*uint8]> _a.F[.shape.*uint8]: 1053d90: e8 ab ff ff ff callq -85 <_a.F[.shape.*uint8]> 1053dc9: e8 72 ff ff ff callq -142 <_a.F[.shape.*uint8]> Change-Id: I627f7e50210aabe4a10d0e2717d87b75ac82e99b Reviewed-on: https://go-review.googlesource.com/c/go/+/339595 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/reflectdata/reflect.go | 7 ++++++- src/cmd/compile/internal/typecheck/subr.go | 7 +++---- test/typeparam/dedup.dir/a.go | 10 ++++++++++ test/typeparam/dedup.dir/b.go | 14 ++++++++++++++ test/typeparam/dedup.dir/c.go | 14 ++++++++++++++ test/typeparam/dedup.dir/main.go | 15 +++++++++++++++ test/typeparam/dedup.go | 12 ++++++++++++ test/typeparam/dedup.out | 4 ++++ 8 files changed, 78 insertions(+), 5 deletions(-) create mode 100644 test/typeparam/dedup.dir/a.go create mode 100644 test/typeparam/dedup.dir/b.go create mode 100644 test/typeparam/dedup.dir/c.go create mode 100644 test/typeparam/dedup.dir/main.go create mode 100644 test/typeparam/dedup.go create mode 100644 test/typeparam/dedup.out diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 19cf2a0a12..a8df7a1a24 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -947,7 +947,7 @@ func writeType(t *types.Type) *obj.LSym { } dupok := 0 - if tbase.Sym() == nil { // TODO(mdempsky): Probably need DUPOK for instantiated types too. + if tbase.Sym() == nil || tbase.HasShape() { // TODO(mdempsky): Probably need DUPOK for instantiated types too. dupok = obj.DUPOK } @@ -1738,6 +1738,11 @@ func NeedEmit(typ *types.Type) bool { // Need to emit to be safe (however, see TODO above). return true + case typ.HasShape(): + // Shape type; need to emit even though it lives in the .shape package. + // TODO: make sure the linker deduplicates them (see dupok in writeType above). + return true + default: // Should have been emitted by an imported package. return false diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 25db24259c..53c3933370 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1362,8 +1362,7 @@ func Shapify(t *types.Type) *types.Type { return s } - sym := Lookup(fmt.Sprintf(".shape%d", snum)) - snum++ + sym := shapePkg.Lookup(u.LinkString()) name := ir.NewDeclNameAt(u.Pos(), ir.OTYPE, sym) s := types.NewNamed(name) s.SetUnderlying(u) @@ -1375,6 +1374,6 @@ func Shapify(t *types.Type) *types.Type { return s } -var snum int - var shaped = map[*types.Type]*types.Type{} + +var shapePkg = types.NewPkg(".shape", ".shape") diff --git a/test/typeparam/dedup.dir/a.go b/test/typeparam/dedup.dir/a.go new file mode 100644 index 0000000000..f5cb6dc762 --- /dev/null +++ b/test/typeparam/dedup.dir/a.go @@ -0,0 +1,10 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +//go:noinline +func F[T comparable](a, b T) bool { + return a == b +} diff --git a/test/typeparam/dedup.dir/b.go b/test/typeparam/dedup.dir/b.go new file mode 100644 index 0000000000..ce037e2d8a --- /dev/null +++ b/test/typeparam/dedup.dir/b.go @@ -0,0 +1,14 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package b + +import "a" + +func B() { + var x int64 + println(a.F(&x, &x)) + var y int32 + println(a.F(&y, &y)) +} diff --git a/test/typeparam/dedup.dir/c.go b/test/typeparam/dedup.dir/c.go new file mode 100644 index 0000000000..11a5d97642 --- /dev/null +++ b/test/typeparam/dedup.dir/c.go @@ -0,0 +1,14 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package c + +import "a" + +func C() { + var x int64 + println(a.F(&x, &x)) + var y int32 + println(a.F(&y, &y)) +} diff --git a/test/typeparam/dedup.dir/main.go b/test/typeparam/dedup.dir/main.go new file mode 100644 index 0000000000..dc3ff6f75f --- /dev/null +++ b/test/typeparam/dedup.dir/main.go @@ -0,0 +1,15 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "b" + "c" +) + +func main() { + b.B() + c.C() +} diff --git a/test/typeparam/dedup.go b/test/typeparam/dedup.go new file mode 100644 index 0000000000..dca4cf3a84 --- /dev/null +++ b/test/typeparam/dedup.go @@ -0,0 +1,12 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Note: this doesn't really test the deduplication of +// instantiations. It just provides an easy mechanism to build a +// binary that you can then check with objdump manually to make sure +// deduplication is happening. TODO: automate this somehow? + +package ignored diff --git a/test/typeparam/dedup.out b/test/typeparam/dedup.out new file mode 100644 index 0000000000..1140ff52e2 --- /dev/null +++ b/test/typeparam/dedup.out @@ -0,0 +1,4 @@ +true +true +true +true -- GitLab From e5fe769be15e60a1f4626cf30fb1f560cb9f317f Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 3 Aug 2021 20:43:39 -0700 Subject: [PATCH 0608/2500] [dev.typeparams] cmd/compile/internal/types2: implement term lists Prerequisite for clean implementation of type sets on top of term lists. Change-Id: Ice87f2f47327aa6b1f3eaad7f9af20ad7c548155 Reviewed-on: https://go-review.googlesource.com/c/go/+/339596 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/termlist.go | 167 +++++++++++ .../compile/internal/types2/termlist_test.go | 278 ++++++++++++++++++ 2 files changed, 445 insertions(+) create mode 100644 src/cmd/compile/internal/types2/termlist.go create mode 100644 src/cmd/compile/internal/types2/termlist_test.go diff --git a/src/cmd/compile/internal/types2/termlist.go b/src/cmd/compile/internal/types2/termlist.go new file mode 100644 index 0000000000..b2c26f41be --- /dev/null +++ b/src/cmd/compile/internal/types2/termlist.go @@ -0,0 +1,167 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types2 + +import "bytes" + +// A termlist represents the type set represented by the union +// t1 ∪ y2 ∪ ... tn of the type sets of the terms t1 to tn. +// A termlist is in normal form if all terms are disjoint. +// termlist operations don't require the operands to be in +// normal form. +type termlist []*term + +// topTermList represents the set of all types. +// It is in normal form. +var topTermlist = termlist{new(term)} + +// String prints the termlist exactly (without normalization). +func (xl termlist) String() string { + if len(xl) == 0 { + return "∅" + } + var buf bytes.Buffer + for i, x := range xl { + if i > 0 { + buf.WriteString(" ∪ ") + } + buf.WriteString(x.String()) + } + return buf.String() +} + +// isEmpty reports whether the termlist xl represents the empty set of types. +func (xl termlist) isEmpty() bool { + // If there's a non-nil term, the entire list is not empty. + // If the termlist is in normal form, this requires at most + // one iteration. + for _, x := range xl { + if x != nil { + return false + } + } + return true +} + +// isTop reports whether the termlist xl represents the set of all types. +func (xl termlist) isTop() bool { + // If there's a ⊤ (top) term, the entire list is ⊤ (top). + // If the termlist is in normal form, this requires at most + // one iteration. + for _, x := range xl { + if x != nil && x.typ == nil { + return true + } + } + return false +} + +// norm returns the normal form of xl. +func (xl termlist) norm() termlist { + // Quadratic algorithm, but good enough for now. + // TODO(gri) fix asymptotic performance + used := make([]bool, len(xl)) + var rl termlist + for i, xi := range xl { + if xi == nil || used[i] { + continue + } + for j := i + 1; j < len(xl); j++ { + xj := xl[j] + if xj == nil || used[j] { + continue + } + if u1, u2 := xi.union(xj); u2 == nil { + // If we encounter a ⊤ (top) term, the entire + // list is ⊤ (top). Exit early. + // (Note that this is not just an optimization; + // if we continue, we may end up with a ⊤ term + // and other terms and the result would not be + // in normal form.) + if u1.typ == nil { + return topTermlist + } + xi = u1 + used[j] = true // xj is now unioned into xi - ignore it in future iterations + } + } + rl = append(rl, xi) + } + return rl +} + +// If the type set represented by xl is specified by a single (non-⊤) term, +// structuralType returns that type. Otherwise it returns nil. +func (xl termlist) structuralType() Type { + if nl := xl.norm(); len(nl) == 1 { + return nl[0].typ // if nl.isTop() then typ is nil, which is ok + } + return nil +} + +// union returns the union xl ∪ yl. +func (xl termlist) union(yl termlist) termlist { + return append(xl, yl...).norm() +} + +// intersect returns the intersection xl ∩ yl. +func (xl termlist) intersect(yl termlist) termlist { + if xl.isEmpty() || yl.isEmpty() { + return nil + } + + // Quadratic algorithm, but good enough for now. + // TODO(gri) fix asymptotic performance + var rl termlist + for _, x := range xl { + for _, y := range yl { + if r := x.intersect(y); r != nil { + rl = append(rl, r) + } + } + } + return rl.norm() +} + +// equal reports whether xl and yl represent the same type set. +func (xl termlist) equal(yl termlist) bool { + // TODO(gri) this should be more efficient + return xl.subsetOf(yl) && yl.subsetOf(xl) +} + +// includes reports whether t ∈ xl. +func (xl termlist) includes(t Type) bool { + for _, x := range xl { + if x.includes(t) { + return true + } + } + return false +} + +// supersetOf reports whether y ⊆ xl. +func (xl termlist) supersetOf(y *term) bool { + for _, x := range xl { + if y.subsetOf(x) { + return true + } + } + return false +} + +// subsetOf reports whether xl ⊆ yl. +func (xl termlist) subsetOf(yl termlist) bool { + if yl.isEmpty() { + return xl.isEmpty() + } + + // each term x of xl must be a subset of yl + for _, x := range xl { + if !yl.supersetOf(x) { + return false // x is not a subset yl + } + } + return true +} diff --git a/src/cmd/compile/internal/types2/termlist_test.go b/src/cmd/compile/internal/types2/termlist_test.go new file mode 100644 index 0000000000..c36baeb86f --- /dev/null +++ b/src/cmd/compile/internal/types2/termlist_test.go @@ -0,0 +1,278 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types2 + +import ( + "strings" + "testing" +) + +// maketl makes a term list from a string of the term list. +func maketl(s string) termlist { + s = strings.Replace(s, " ", "", -1) + names := strings.Split(s, "∪") + r := make(termlist, len(names)) + for i, n := range names { + r[i] = testTerm(n) + } + return r +} + +func TestTermlistTop(t *testing.T) { + if !topTermlist.isTop() { + t.Errorf("topTermlist is not top") + } +} + +func TestTermlistString(t *testing.T) { + for _, want := range []string{ + "∅", + "⊤", + "int", + "~int", + "∅ ∪ ∅", + "⊤ ∪ ⊤", + "∅ ∪ ⊤ ∪ int", + } { + if got := maketl(want).String(); got != want { + t.Errorf("(%v).String() == %v", want, got) + } + } +} + +func TestTermlistIsEmpty(t *testing.T) { + for test, want := range map[string]bool{ + "∅": true, + "∅ ∪ ∅": true, + "∅ ∪ ∅ ∪ ⊤": false, + "⊤": false, + "⊤ ∪ int": false, + } { + xl := maketl(test) + got := xl.isEmpty() + if got != want { + t.Errorf("(%v).isEmpty() == %v; want %v", test, got, want) + } + } +} + +func TestTermlistIsTop(t *testing.T) { + for test, want := range map[string]bool{ + "∅": false, + "∅ ∪ ∅": false, + "int ∪ ~string": false, + "∅ ∪ ∅ ∪ ⊤": true, + "⊤": true, + "⊤ ∪ int": true, + } { + xl := maketl(test) + got := xl.isTop() + if got != want { + t.Errorf("(%v).isTop() == %v; want %v", test, got, want) + } + } +} + +func TestTermlistNorm(t *testing.T) { + for _, test := range []struct { + xl, want string + }{ + {"∅", "∅"}, + {"∅ ∪ ∅", "∅"}, + {"∅ ∪ int", "int"}, + {"⊤ ∪ int", "⊤"}, + {"~int ∪ int", "~int"}, + {"int ∪ ~string ∪ int", "int ∪ ~string"}, + {"~int ∪ string ∪ ⊤ ∪ ~string ∪ int", "⊤"}, + } { + xl := maketl(test.xl) + got := maketl(test.xl).norm() + if got.String() != test.want { + t.Errorf("(%v).norm() = %v; want %v", xl, got, test.want) + } + } +} + +func TestTermlistStructuralType(t *testing.T) { + // helper to deal with nil types + tstring := func(typ Type) string { + if typ == nil { + return "nil" + } + return typ.String() + } + + for test, want := range map[string]string{ + "∅": "nil", + "⊤": "nil", + "int": "int", + "~int": "int", + "~int ∪ string": "nil", + "∅ ∪ int": "int", + "∅ ∪ ~int": "int", + "∅ ∪ ~int ∪ string": "nil", + } { + xl := maketl(test) + got := tstring(xl.structuralType()) + if got != want { + t.Errorf("(%v).structuralType() == %v; want %v", test, got, want) + } + } +} + +func TestTermlistUnion(t *testing.T) { + for _, test := range []struct { + xl, yl, want string + }{ + + {"∅", "∅", "∅"}, + {"∅", "⊤", "⊤"}, + {"∅", "int", "int"}, + {"⊤", "~int", "⊤"}, + {"int", "~int", "~int"}, + {"int", "string", "int ∪ string"}, + {"int ∪ string", "~string", "int ∪ ~string"}, + {"~int ∪ string", "~string ∪ int", "~int ∪ ~string"}, + {"~int ∪ string ∪ ∅", "~string ∪ int", "~int ∪ ~string"}, + {"~int ∪ string ∪ ⊤", "~string ∪ int", "⊤"}, + } { + xl := maketl(test.xl) + yl := maketl(test.yl) + got := xl.union(yl).String() + if got != test.want { + t.Errorf("(%v).union(%v) = %v; want %v", test.xl, test.yl, got, test.want) + } + } +} + +func TestTermlistIntersect(t *testing.T) { + for _, test := range []struct { + xl, yl, want string + }{ + + {"∅", "∅", "∅"}, + {"∅", "⊤", "∅"}, + {"∅", "int", "∅"}, + {"⊤", "~int", "~int"}, + {"int", "~int", "int"}, + {"int", "string", "∅"}, + {"int ∪ string", "~string", "string"}, + {"~int ∪ string", "~string ∪ int", "int ∪ string"}, + {"~int ∪ string ∪ ∅", "~string ∪ int", "int ∪ string"}, + {"~int ∪ string ∪ ⊤", "~string ∪ int", "int ∪ ~string"}, + } { + xl := maketl(test.xl) + yl := maketl(test.yl) + got := xl.intersect(yl).String() + if got != test.want { + t.Errorf("(%v).intersect(%v) = %v; want %v", test.xl, test.yl, got, test.want) + } + } +} + +func TestTermlistEqual(t *testing.T) { + for _, test := range []struct { + xl, yl string + want bool + }{ + {"∅", "∅", true}, + {"∅", "⊤", false}, + {"⊤", "⊤", true}, + {"⊤ ∪ int", "⊤", true}, + {"⊤ ∪ int", "string ∪ ⊤", true}, + {"int ∪ ~string", "string ∪ int", false}, + {"int ∪ ~string ∪ ∅", "string ∪ int ∪ ~string", true}, + } { + xl := maketl(test.xl) + yl := maketl(test.yl) + got := xl.equal(yl) + if got != test.want { + t.Errorf("(%v).equal(%v) = %v; want %v", test.xl, test.yl, got, test.want) + } + } +} + +func TestTermlistIncludes(t *testing.T) { + for _, test := range []struct { + xl, typ string + want bool + }{ + {"∅", "int", false}, + {"⊤", "int", true}, + {"~int", "int", true}, + {"int", "string", false}, + {"~int", "string", false}, + {"int ∪ string", "string", true}, + {"~int ∪ string", "int", true}, + {"~int ∪ string ∪ ∅", "string", true}, + {"~string ∪ ∅ ∪ ⊤", "int", true}, + } { + xl := maketl(test.xl) + yl := testTerm(test.typ).typ + got := xl.includes(yl) + if got != test.want { + t.Errorf("(%v).includes(%v) = %v; want %v", test.xl, yl, got, test.want) + } + } +} + +func TestTermlistSupersetOf(t *testing.T) { + for _, test := range []struct { + xl, typ string + want bool + }{ + {"∅", "∅", true}, + {"∅", "⊤", false}, + {"∅", "int", false}, + {"⊤", "∅", true}, + {"⊤", "⊤", true}, + {"⊤", "int", true}, + {"⊤", "~int", true}, + {"~int", "int", true}, + {"~int", "~int", true}, + {"int", "~int", false}, + {"int", "string", false}, + {"~int", "string", false}, + {"int ∪ string", "string", true}, + {"int ∪ string", "~string", false}, + {"~int ∪ string", "int", true}, + {"~int ∪ string ∪ ∅", "string", true}, + {"~string ∪ ∅ ∪ ⊤", "int", true}, + } { + xl := maketl(test.xl) + y := testTerm(test.typ) + got := xl.supersetOf(y) + if got != test.want { + t.Errorf("(%v).supersetOf(%v) = %v; want %v", test.xl, y, got, test.want) + } + } +} + +func TestTermlistSubsetOf(t *testing.T) { + for _, test := range []struct { + xl, yl string + want bool + }{ + {"∅", "∅", true}, + {"∅", "⊤", true}, + {"⊤", "∅", false}, + {"⊤", "⊤", true}, + {"int", "int ∪ string", true}, + {"~int", "int ∪ string", false}, + {"~int", "string ∪ string ∪ int ∪ ~int", true}, + {"int ∪ string", "string", false}, + {"int ∪ string", "string ∪ int", true}, + {"int ∪ ~string", "string ∪ int", false}, + {"int ∪ ~string", "string ∪ int ∪ ⊤", true}, + {"int ∪ ~string", "string ∪ int ∪ ∅ ∪ string", false}, + } { + xl := maketl(test.xl) + yl := maketl(test.yl) + got := xl.subsetOf(yl) + if got != test.want { + t.Errorf("(%v).subsetOf(%v) = %v; want %v", test.xl, test.yl, got, test.want) + } + } +} -- GitLab From 0ec2a8b42d1aa94629ffebdb8f501435cfd14980 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Wed, 4 Aug 2021 10:43:08 -0400 Subject: [PATCH 0609/2500] [dev.typeparams] go/types: switch the TArgs API to NumTArgs/TArg As with other go/types APIs, we should not expose the underlying Named.targs slice. Change-Id: Iba869298fbd3856022ffe8ec2c3273341598c324 Reviewed-on: https://go-review.googlesource.com/c/go/+/340009 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/named.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/go/types/named.go b/src/go/types/named.go index fc53783ab8..f26b50aa81 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -125,8 +125,12 @@ func (t *Named) TParams() *TypeParams { return t.load().tparams } // SetTParams sets the type parameters of the named type t. func (t *Named) SetTParams(tparams []*TypeName) { t.load().tparams = bindTParams(tparams) } -// TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated. -func (t *Named) TArgs() []Type { return t.targs } +// NumTArgs returns the number of type arguments used to instantiate the named +// type t, or 0 if t is not an instantiated type. +func (t *Named) NumTArgs() int { return len(t.targs) } + +// TArgs returns the i'th type argument of the named type t for 0 <= i < t.NumTArgs(). +func (t *Named) TArg(i int) Type { return t.targs[i] } // SetTArgs sets the type arguments of the named type t. func (t *Named) SetTArgs(args []Type) { t.targs = args } -- GitLab From 1b708c0260b6627fc23dda30c3f1e691373c032d Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Wed, 4 Aug 2021 16:21:15 -0400 Subject: [PATCH 0610/2500] [dev.typeparams] go/types: remove a stale comment (cleanup) Remove a stale comment from when the new types.Info API was guarded behind the typeparams build constraint. Change-Id: I319ad0a9e4e4958efdb96c967bf13a0119b5647b Reviewed-on: https://go-review.googlesource.com/c/go/+/340010 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/api.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/go/types/api.go b/src/go/types/api.go index 6c0ceb7b7c..315f77f362 100644 --- a/src/go/types/api.go +++ b/src/go/types/api.go @@ -258,8 +258,6 @@ type Info struct { InitOrder []*Initializer } -// The Info struct is found in api_notypeparams.go and api_typeparams.go. - // TypeOf returns the type of expression e, or nil if not found. // Precondition: the Types, Uses and Defs maps are populated. // -- GitLab From 3cdf8b429e7550c04ab986327bf9aed8de08d6fa Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 4 Aug 2021 14:25:01 -0700 Subject: [PATCH 0611/2500] [dev.typeparams] cmd/compile: fixing case where type arg is an interface In this case, we can't use an itab for doing a bound call, since we're converting from an interface to an interface. We do a static or dynamic type assert in new function assertToBound(). The dynamic type assert in assertToBound() is only needed if a bound is parameterized. In that case, we must do a dynamic type assert, and therefore need a dictionary entry for the type bound (see change in getGfInfo). I'm not sure if we can somehow limit this case, since using an interface as a type arg AND having the type bound of the type arg be parameterized is a very unlikely case. Had to add the TUNION case to parameterizedBy1() (which is only used for extra checking). Added a bunch of these test cases to 13.go, which now passes. Change-Id: Ic22eed637fa879b5bbb46d36b40aaad6f90b9d01 Reviewed-on: https://go-review.googlesource.com/c/go/+/339898 Trust: Dan Scales Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 91 +++++++++++++++++++---- test/run.go | 1 - test/typeparam/mdempsky/13.go | 84 ++++++++++++++++----- 3 files changed, 142 insertions(+), 34 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index c006c4af44..b2677d5a77 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1181,7 +1181,7 @@ func (subst *subster) node(n ir.Node) ir.Node { // The only dot on a shape type value are methods. if mse.X.Op() == ir.OTYPE { // Method expression T.M - m = subst.g.buildClosure2(subst.newf, subst.info, m, x) + m = subst.g.buildClosure2(subst, m, x) // No need for transformDot - buildClosure2 has already // transformed to OCALLINTER/ODOTINTER. } else { @@ -1189,11 +1189,18 @@ func (subst *subster) node(n ir.Node) ir.Node { // 1) convert x to the bound interface // 2) call M on that interface gsrc := x.(*ir.SelectorExpr).X.Type() - dst := gsrc.Bound() + bound := gsrc.Bound() + dst := bound if dst.HasTParam() { dst = subst.ts.Typ(dst) } - mse.X = convertUsingDictionary(subst.info, subst.info.dictParam, m.Pos(), mse.X, x, dst, gsrc) + if src.IsInterface() { + // If type arg is an interface (unusual case), + // we do a type assert to the type bound. + mse.X = assertToBound(subst.info, subst.info.dictParam, m.Pos(), mse.X, bound, dst) + } else { + mse.X = convertUsingDictionary(subst.info, subst.info.dictParam, m.Pos(), mse.X, x, dst, gsrc) + } transformDot(mse, false) } } else { @@ -1554,10 +1561,10 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) tparam := tmpse.X.Type() assert(tparam.IsTypeParam()) recvType := targs[tparam.Index()] - if len(recvType.RParams()) == 0 { + if recvType.IsInterface() || len(recvType.RParams()) == 0 { // No sub-dictionary entry is // actually needed, since the - // typeparam is not an + // type arg is not an // instantiated type that // will have generic methods. break @@ -1686,8 +1693,14 @@ func (g *irgen) finalizeSyms() { default: base.Fatalf("itab entry with unknown op %s", n.Op()) } - itabLsym := reflectdata.ITabLsym(srctype, dsttype) - d.off = objw.SymPtr(lsym, d.off, itabLsym, 0) + if srctype.IsInterface() { + // No itab is wanted if src type is an interface. We + // will use a type assert instead. + d.off = objw.Uintptr(lsym, d.off, 0) + } else { + itabLsym := reflectdata.ITabLsym(srctype, dsttype) + d.off = objw.SymPtr(lsym, d.off, itabLsym, 0) + } } objw.Global(lsym, int32(d.off), obj.DUPOK|obj.RODATA) @@ -1760,6 +1773,17 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo { info.tparams[i] = f.Type } } + + for _, t := range info.tparams { + b := t.Bound() + if b.HasTParam() { + // If a type bound is parameterized (unusual case), then we + // may need its derived type to do a type assert when doing a + // bound call for a type arg that is an interface. + addType(&info, nil, b) + } + } + for _, n := range gf.Dcl { addType(&info, n, n.Type()) } @@ -1950,6 +1974,15 @@ func parameterizedBy1(t *types.Type, params []*types.Type, visited map[*types.Ty types.TUINTPTR, types.TBOOL, types.TSTRING, types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128: return true + case types.TUNION: + for i := 0; i < t.NumTerms(); i++ { + tt, _ := t.Term(i) + if !parameterizedBy1(tt, params, visited) { + return false + } + } + return true + default: base.Fatalf("bad type kind %+v", t) return true @@ -2000,15 +2033,32 @@ func startClosure(pos src.XPos, outer *ir.Func, typ *types.Type) (*ir.Func, []*t } +// assertToBound returns a new node that converts a node rcvr with interface type to +// the 'dst' interface type. bound is the unsubstituted form of dst. +func assertToBound(info *instInfo, dictVar *ir.Name, pos src.XPos, rcvr ir.Node, bound, dst *types.Type) ir.Node { + if bound.HasTParam() { + ix := findDictType(info, bound) + assert(ix >= 0) + rt := getDictionaryType(info, dictVar, pos, ix) + rcvr = ir.NewDynamicTypeAssertExpr(pos, ir.ODYNAMICDOTTYPE, rcvr, rt) + typed(dst, rcvr) + } else { + rcvr = ir.NewTypeAssertExpr(pos, rcvr, nil) + typed(bound, rcvr) + } + return rcvr +} + // buildClosure2 makes a closure to implement a method expression m (generic form x) // which has a shape type as receiver. If the receiver is exactly a shape (i.e. from -// a typeparam), then the body of the closure converts the first argument (the -// receiver) to the interface bound type, and makes an interface call with the -// remaining arguments. +// a typeparam), then the body of the closure converts m.X (the receiver) to the +// interface bound type, and makes an interface call with the remaining arguments. // -// The returned closure is fully substituted and has already has any needed +// The returned closure is fully substituted and has already had any needed // transformations done. -func (g *irgen) buildClosure2(outer *ir.Func, info *instInfo, m, x ir.Node) ir.Node { +func (g *irgen) buildClosure2(subst *subster, m, x ir.Node) ir.Node { + outer := subst.newf + info := subst.info pos := m.Pos() typ := m.Type() // type of the closure @@ -2031,11 +2081,24 @@ func (g *irgen) buildClosure2(outer *ir.Func, info *instInfo, m, x ir.Node) ir.N rcvr := args[0] args = args[1:] assert(m.(*ir.SelectorExpr).X.Type().IsShape()) - rcvr = convertUsingDictionary(info, dictVar, pos, rcvr, x, x.(*ir.SelectorExpr).X.Type().Bound(), x.(*ir.SelectorExpr).X.Type()) + gsrc := x.(*ir.SelectorExpr).X.Type() + bound := gsrc.Bound() + dst := bound + if dst.HasTParam() { + dst = subst.ts.Typ(bound) + } + if m.(*ir.SelectorExpr).X.Type().IsInterface() { + // If type arg is an interface (unusual case), we do a type assert to + // the type bound. + rcvr = assertToBound(info, dictVar, pos, rcvr, bound, dst) + } else { + rcvr = convertUsingDictionary(info, dictVar, pos, rcvr, x, dst, gsrc) + } dot := ir.NewSelectorExpr(pos, ir.ODOTINTER, rcvr, x.(*ir.SelectorExpr).Sel) dot.Selection = typecheck.Lookdot1(dot, dot.Sel, dot.X.Type(), dot.X.Type().AllMethods(), 1) - typed(x.(*ir.SelectorExpr).Selection.Type, dot) + // Do a type substitution on the generic bound, in case it is parameterized. + typed(subst.ts.Typ(x.(*ir.SelectorExpr).Selection.Type), dot) innerCall = ir.NewCallExpr(pos, ir.OCALLINTER, dot, args) t := m.Type() if t.NumResults() == 0 { diff --git a/test/run.go b/test/run.go index 4971043ab6..6296234d56 100644 --- a/test/run.go +++ b/test/run.go @@ -2184,7 +2184,6 @@ var g3Failures = setOf( "typeparam/nested.go", // -G=3 doesn't support function-local types with generics "typeparam/mdempsky/4.go", // -G=3 can't export functions with labeled breaks in loops - "typeparam/mdempsky/13.go", // problem with interface as as a type arg. "typeparam/mdempsky/15.go", // ICE in (*irgen).buildClosure ) diff --git a/test/typeparam/mdempsky/13.go b/test/typeparam/mdempsky/13.go index dc1d29bce1..b492774d3d 100644 --- a/test/typeparam/mdempsky/13.go +++ b/test/typeparam/mdempsky/13.go @@ -6,33 +6,79 @@ package main -type Mer interface{ M() } +// Interface which will be used as a regular interface type and as a type bound. +type Mer interface{ + M() +} -func F[T Mer](expectPanic bool) { - defer func() { - err := recover() - if (err != nil) != expectPanic { - print("FAIL: (", err, " != nil) != ", expectPanic, "\n") - } - }() +// Interface that is a superset of Mer. +type Mer2 interface { + M() + String() string +} - var t T +func F[T Mer](t T) { T.M(t) + t.M() } type MyMer int func (MyMer) M() {} +func (MyMer) String() string { + return "aa" +} + +// Parameterized interface +type Abs[T any] interface { + Abs() T +} + +func G[T Abs[U], U any](t T) { + T.Abs(t) + t.Abs() +} + +type MyInt int +func (m MyInt) Abs() MyInt { + if m < 0 { + return -m + } + return m +} + +type Abs2 interface { + Abs() MyInt +} + func main() { - F[Mer](true) - F[struct{ Mer }](true) - F[*struct{ Mer }](true) - - F[MyMer](false) - F[*MyMer](true) - F[struct{ MyMer }](false) - F[struct{ *MyMer }](true) - F[*struct{ MyMer }](true) - F[*struct{ *MyMer }](true) + mm := MyMer(3) + ms := struct{ Mer }{Mer: mm } + + // Testing F with an interface type arg: Mer and Mer2 + F[Mer](mm) + F[Mer2](mm) + F[struct{ Mer }](ms) + F[*struct{ Mer }](&ms) + + ms2 := struct { MyMer }{MyMer: mm} + ms3 := struct { *MyMer }{MyMer: &mm} + + // Testing F with a concrete type arg + F[MyMer](mm) + F[*MyMer](&mm) + F[struct{ MyMer }](ms2) + F[struct{ *MyMer }](ms3) + F[*struct{ MyMer }](&ms2) + F[*struct{ *MyMer }](&ms3) + + // Testing G with a concrete type args + mi := MyInt(-3) + G[MyInt,MyInt](mi) + + // Interface Abs[MyInt] holding an mi. + intMi := Abs[MyInt](mi) + // First type arg here is Abs[MyInt], an interface type. + G[Abs[MyInt],MyInt](intMi) } -- GitLab From 5dcb5e2cea883b1bd69b543841b137a287aa7037 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 4 Aug 2021 17:58:54 -0700 Subject: [PATCH 0612/2500] [dev.typeparams] cmd/compile: dictionary/shape cleanup - Removed gcshapeType - we're going with more granular shapes for now, and gradually coarsening later if needed. - Put in early return in getDictionarySym(), so the entire rest of the function can be un-indented by one level. - Removed some duplicated infoprint calls, and fixed one infoprint message in getGfInfo. Change-Id: I13acce8fdabdb21e903275b53ff78a1e6a378de2 Reviewed-on: https://go-review.googlesource.com/c/go/+/339901 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 443 ++++++---------------- 1 file changed, 113 insertions(+), 330 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index b2677d5a77..7cc37f1154 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -8,7 +8,6 @@ package noder import ( - "bytes" "cmd/compile/internal/base" "cmd/compile/internal/ir" "cmd/compile/internal/objw" @@ -19,7 +18,6 @@ import ( "cmd/internal/src" "fmt" "go/constant" - "strconv" ) // Enable extra consistency checks. @@ -536,220 +534,6 @@ func (g *irgen) getDictOrSubdict(declInfo *instInfo, n ir.Node, nameNode *ir.Nam return dict, usingSubdict } -func addGcType(fl []*types.Field, t *types.Type) []*types.Field { - return append(fl, types.NewField(base.Pos, typecheck.Lookup("F"+strconv.Itoa(len(fl))), t)) -} - -const INTTYPE = types.TINT64 // XX fix for 32-bit arch -const UINTTYPE = types.TUINT64 // XX fix for 32-bit arch -const INTSTRING = "i8" // XX fix for 32-bit arch -const UINTSTRING = "u8" // XX fix for 32-bit arch - -// accumGcshape adds fields to fl resulting from the GCshape transformation of -// type t. The string associated with the GCshape transformation of t is added to -// buf. fieldSym is the sym of the field associated with type t, if it is in a -// struct. fieldSym could be used to have special naming for blank fields, etc. -func accumGcshape(fl []*types.Field, buf *bytes.Buffer, t *types.Type, fieldSym *types.Sym) []*types.Field { - // t.Kind() is already the kind of the underlying type, so no need to - // reference t.Underlying() to reference the underlying type. - assert(t.Kind() == t.Underlying().Kind()) - - switch t.Kind() { - case types.TINT8: - fl = addGcType(fl, types.Types[types.TINT8]) - buf.WriteString("i1") - - case types.TUINT8: - fl = addGcType(fl, types.Types[types.TUINT8]) - buf.WriteString("u1") - - case types.TINT16: - fl = addGcType(fl, types.Types[types.TINT16]) - buf.WriteString("i2") - - case types.TUINT16: - fl = addGcType(fl, types.Types[types.TUINT16]) - buf.WriteString("u2") - - case types.TINT32: - fl = addGcType(fl, types.Types[types.TINT32]) - buf.WriteString("i4") - - case types.TUINT32: - fl = addGcType(fl, types.Types[types.TUINT32]) - buf.WriteString("u4") - - case types.TINT64: - fl = addGcType(fl, types.Types[types.TINT64]) - buf.WriteString("i8") - - case types.TUINT64: - fl = addGcType(fl, types.Types[types.TUINT64]) - buf.WriteString("u8") - - case types.TINT: - fl = addGcType(fl, types.Types[INTTYPE]) - buf.WriteString(INTSTRING) - - case types.TUINT, types.TUINTPTR: - fl = addGcType(fl, types.Types[UINTTYPE]) - buf.WriteString(UINTSTRING) - - case types.TCOMPLEX64: - fl = addGcType(fl, types.Types[types.TFLOAT32]) - fl = addGcType(fl, types.Types[types.TFLOAT32]) - buf.WriteString("f4") - buf.WriteString("f4") - - case types.TCOMPLEX128: - fl = addGcType(fl, types.Types[types.TFLOAT64]) - fl = addGcType(fl, types.Types[types.TFLOAT64]) - buf.WriteString("f8") - buf.WriteString("f8") - - case types.TFLOAT32: - fl = addGcType(fl, types.Types[types.TFLOAT32]) - buf.WriteString("f4") - - case types.TFLOAT64: - fl = addGcType(fl, types.Types[types.TFLOAT64]) - buf.WriteString("f8") - - case types.TBOOL: - fl = addGcType(fl, types.Types[types.TINT8]) - buf.WriteString("i1") - - case types.TPTR: - fl = addGcType(fl, types.Types[types.TUNSAFEPTR]) - buf.WriteString("p") - - case types.TFUNC: - fl = addGcType(fl, types.Types[types.TUNSAFEPTR]) - buf.WriteString("p") - - case types.TSLICE: - fl = addGcType(fl, types.Types[types.TUNSAFEPTR]) - fl = addGcType(fl, types.Types[INTTYPE]) - fl = addGcType(fl, types.Types[INTTYPE]) - buf.WriteString("p") - buf.WriteString(INTSTRING) - buf.WriteString(INTSTRING) - - case types.TARRAY: - n := t.NumElem() - if n == 1 { - fl = accumGcshape(fl, buf, t.Elem(), nil) - } else if n > 0 { - // Represent an array with more than one element as its - // unique type, since it must be treated differently for - // regabi. - fl = addGcType(fl, t) - buf.WriteByte('[') - buf.WriteString(strconv.Itoa(int(n))) - buf.WriteString("](") - var ignore []*types.Field - // But to determine its gcshape name, we must call - // accumGcShape() on t.Elem(). - accumGcshape(ignore, buf, t.Elem(), nil) - buf.WriteByte(')') - } - - case types.TSTRUCT: - nfields := t.NumFields() - for i, f := range t.Fields().Slice() { - fl = accumGcshape(fl, buf, f.Type, f.Sym) - - // Check if we need to add an alignment field. - var pad int64 - if i < nfields-1 { - pad = t.Field(i+1).Offset - f.Offset - f.Type.Width - } else { - pad = t.Width - f.Offset - f.Type.Width - } - if pad > 0 { - // There is padding between fields or at end of - // struct. Add an alignment field. - fl = addGcType(fl, types.NewArray(types.Types[types.TUINT8], pad)) - buf.WriteString("a") - buf.WriteString(strconv.Itoa(int(pad))) - } - } - - case types.TCHAN: - fl = addGcType(fl, types.Types[types.TUNSAFEPTR]) - buf.WriteString("p") - - case types.TMAP: - fl = addGcType(fl, types.Types[types.TUNSAFEPTR]) - buf.WriteString("p") - - case types.TINTER: - fl = addGcType(fl, types.Types[types.TUNSAFEPTR]) - fl = addGcType(fl, types.Types[types.TUNSAFEPTR]) - buf.WriteString("pp") - - case types.TFORW, types.TANY: - assert(false) - - case types.TSTRING: - fl = addGcType(fl, types.Types[types.TUNSAFEPTR]) - fl = addGcType(fl, types.Types[INTTYPE]) - buf.WriteString("p") - buf.WriteString(INTSTRING) - - case types.TUNSAFEPTR: - fl = addGcType(fl, types.Types[types.TUNSAFEPTR]) - buf.WriteString("p") - - default: // Everything TTYPEPARAM and below in list of Kinds - assert(false) - } - - return fl -} - -// gcshapeType returns the GCshape type and name corresponding to type t. -func gcshapeType(t *types.Type) (*types.Type, string) { - var fl []*types.Field - buf := bytes.NewBufferString("") - - // Call CallSize so type sizes and field offsets are available. - types.CalcSize(t) - - instType := t.Sym() != nil && t.IsFullyInstantiated() - if instType { - // We distinguish the gcshape of all top-level instantiated type from - // normal concrete types, even if they have the exact same underlying - // "shape", because in a function instantiation, any method call on - // this type arg will be a generic method call (requiring a - // dictionary), rather than a direct method call on the underlying - // type (no dictionary). So, we add the instshape prefix to the - // normal gcshape name, and will make it a defined type with that - // name below. - buf.WriteString("instshape-") - } - fl = accumGcshape(fl, buf, t, nil) - - // TODO: Should gcshapes be in a global package, so we don't have to - // duplicate in each package? Or at least in the specified source package - // of a function/method instantiation? - gcshape := types.NewStruct(types.LocalPkg, fl) - gcname := buf.String() - if instType { - // Lookup or create type with name 'gcname' (with instshape prefix). - newsym := t.Sym().Pkg.Lookup(gcname) - if newsym.Def != nil { - gcshape = newsym.Def.Type() - } else { - newt := typecheck.NewIncompleteNamedType(t.Pos(), newsym) - newt.SetUnderlying(gcshape.Underlying()) - gcshape = newt - } - } - assert(gcshape.Size() == t.Size()) - return gcshape, buf.String() -} - // checkFetchBody checks if a generic body can be fetched, but hasn't been loaded // yet. If so, it imports the body. func checkFetchBody(nameNode *ir.Name) { @@ -1521,131 +1305,135 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) sym := typecheck.MakeDictName(gf.Sym(), targs, isMeth) // Initialize the dictionary, if we haven't yet already. - if lsym := sym.Linksym(); len(lsym.P) == 0 { - info := g.getGfInfo(gf) - - infoPrint("=== Creating dictionary %v\n", sym.Name) - off := 0 - // Emit an entry for each targ (concrete type or gcshape). - for _, t := range targs { - infoPrint(" * %v\n", t) - s := reflectdata.TypeLinksym(t) - off = objw.SymPtr(lsym, off, s, 0) - markTypeUsed(t, lsym) - } - subst := typecheck.Tsubster{ - Tparams: info.tparams, - Targs: targs, - } - // Emit an entry for each derived type (after substituting targs) - for _, t := range info.derivedTypes { - ts := subst.Typ(t) - infoPrint(" - %v\n", ts) - s := reflectdata.TypeLinksym(ts) - off = objw.SymPtr(lsym, off, s, 0) - markTypeUsed(ts, lsym) - } - // Emit an entry for each subdictionary (after substituting targs) - for _, n := range info.subDictCalls { - var sym *types.Sym - switch n.Op() { - case ir.OCALL: - call := n.(*ir.CallExpr) - if call.X.Op() == ir.OXDOT { - var nameNode *ir.Name - se := call.X.(*ir.SelectorExpr) - if types.IsInterfaceMethod(se.Selection.Type) { - // This is a method call enabled by a type bound. - tmpse := ir.NewSelectorExpr(base.Pos, ir.OXDOT, se.X, se.Sel) - tmpse = typecheck.AddImplicitDots(tmpse) - tparam := tmpse.X.Type() - assert(tparam.IsTypeParam()) - recvType := targs[tparam.Index()] - if recvType.IsInterface() || len(recvType.RParams()) == 0 { - // No sub-dictionary entry is - // actually needed, since the - // type arg is not an - // instantiated type that - // will have generic methods. - break - } - // This is a method call for an - // instantiated type, so we need a - // sub-dictionary. - targs := recvType.RParams() - genRecvType := recvType.OrigSym.Def.Type() - nameNode = typecheck.Lookdot1(call.X, se.Sel, genRecvType, genRecvType.Methods(), 1).Nname.(*ir.Name) - sym = g.getDictionarySym(nameNode, targs, true) - } else { - // This is the case of a normal - // method call on a generic type. - nameNode = call.X.(*ir.SelectorExpr).Selection.Nname.(*ir.Name) - subtargs := deref(call.X.(*ir.SelectorExpr).X.Type()).RParams() - s2targs := make([]*types.Type, len(subtargs)) - for i, t := range subtargs { - s2targs[i] = subst.Typ(t) - } - sym = g.getDictionarySym(nameNode, s2targs, true) + lsym := sym.Linksym() + if len(lsym.P) > 0 { + // We already started creating this dictionary and its lsym. + return sym + } + + info := g.getGfInfo(gf) + + infoPrint("=== Creating dictionary %v\n", sym.Name) + off := 0 + // Emit an entry for each targ (concrete type or gcshape). + for _, t := range targs { + infoPrint(" * %v\n", t) + s := reflectdata.TypeLinksym(t) + off = objw.SymPtr(lsym, off, s, 0) + markTypeUsed(t, lsym) + } + subst := typecheck.Tsubster{ + Tparams: info.tparams, + Targs: targs, + } + // Emit an entry for each derived type (after substituting targs) + for _, t := range info.derivedTypes { + ts := subst.Typ(t) + infoPrint(" - %v\n", ts) + s := reflectdata.TypeLinksym(ts) + off = objw.SymPtr(lsym, off, s, 0) + markTypeUsed(ts, lsym) + } + // Emit an entry for each subdictionary (after substituting targs) + for _, n := range info.subDictCalls { + var sym *types.Sym + switch n.Op() { + case ir.OCALL: + call := n.(*ir.CallExpr) + if call.X.Op() == ir.OXDOT { + var nameNode *ir.Name + se := call.X.(*ir.SelectorExpr) + if types.IsInterfaceMethod(se.Selection.Type) { + // This is a method call enabled by a type bound. + tmpse := ir.NewSelectorExpr(base.Pos, ir.OXDOT, se.X, se.Sel) + tmpse = typecheck.AddImplicitDots(tmpse) + tparam := tmpse.X.Type() + assert(tparam.IsTypeParam()) + recvType := targs[tparam.Index()] + if recvType.IsInterface() || len(recvType.RParams()) == 0 { + // No sub-dictionary entry is + // actually needed, since the + // type arg is not an + // instantiated type that + // will have generic methods. + break } + // This is a method call for an + // instantiated type, so we need a + // sub-dictionary. + targs := recvType.RParams() + genRecvType := recvType.OrigSym.Def.Type() + nameNode = typecheck.Lookdot1(call.X, se.Sel, genRecvType, genRecvType.Methods(), 1).Nname.(*ir.Name) + sym = g.getDictionarySym(nameNode, targs, true) } else { - inst := call.X.(*ir.InstExpr) - var nameNode *ir.Name - var meth *ir.SelectorExpr - var isMeth bool - if meth, isMeth = inst.X.(*ir.SelectorExpr); isMeth { - nameNode = meth.Selection.Nname.(*ir.Name) - } else { - nameNode = inst.X.(*ir.Name) - } - subtargs := typecheck.TypesOf(inst.Targs) + // This is the case of a normal + // method call on a generic type. + nameNode = call.X.(*ir.SelectorExpr).Selection.Nname.(*ir.Name) + subtargs := deref(call.X.(*ir.SelectorExpr).X.Type()).RParams() + s2targs := make([]*types.Type, len(subtargs)) for i, t := range subtargs { - subtargs[i] = subst.Typ(t) + s2targs[i] = subst.Typ(t) } - sym = g.getDictionarySym(nameNode, subtargs, isMeth) + sym = g.getDictionarySym(nameNode, s2targs, true) + } + } else { + inst := call.X.(*ir.InstExpr) + var nameNode *ir.Name + var meth *ir.SelectorExpr + var isMeth bool + if meth, isMeth = inst.X.(*ir.SelectorExpr); isMeth { + nameNode = meth.Selection.Nname.(*ir.Name) + } else { + nameNode = inst.X.(*ir.Name) } - - case ir.OFUNCINST: - inst := n.(*ir.InstExpr) - nameNode := inst.X.(*ir.Name) subtargs := typecheck.TypesOf(inst.Targs) for i, t := range subtargs { subtargs[i] = subst.Typ(t) } - sym = g.getDictionarySym(nameNode, subtargs, false) - - case ir.OXDOT: - selExpr := n.(*ir.SelectorExpr) - subtargs := deref(selExpr.X.Type()).RParams() - s2targs := make([]*types.Type, len(subtargs)) - for i, t := range subtargs { - s2targs[i] = subst.Typ(t) - } - nameNode := selExpr.Selection.Nname.(*ir.Name) - sym = g.getDictionarySym(nameNode, s2targs, true) + sym = g.getDictionarySym(nameNode, subtargs, isMeth) + } - default: - assert(false) + case ir.OFUNCINST: + inst := n.(*ir.InstExpr) + nameNode := inst.X.(*ir.Name) + subtargs := typecheck.TypesOf(inst.Targs) + for i, t := range subtargs { + subtargs[i] = subst.Typ(t) } + sym = g.getDictionarySym(nameNode, subtargs, false) - if sym == nil { - // Unused sub-dictionary entry, just emit 0. - off = objw.Uintptr(lsym, off, 0) - infoPrint(" - Unused subdict entry\n") - } else { - off = objw.SymPtr(lsym, off, sym.Linksym(), 0) - infoPrint(" - Subdict %v\n", sym.Name) + case ir.OXDOT: + selExpr := n.(*ir.SelectorExpr) + subtargs := deref(selExpr.X.Type()).RParams() + s2targs := make([]*types.Type, len(subtargs)) + for i, t := range subtargs { + s2targs[i] = subst.Typ(t) } + nameNode := selExpr.Selection.Nname.(*ir.Name) + sym = g.getDictionarySym(nameNode, s2targs, true) + + default: + assert(false) } - delay := &delayInfo{ - gf: gf, - targs: targs, - sym: sym, - off: off, + if sym == nil { + // Unused sub-dictionary entry, just emit 0. + off = objw.Uintptr(lsym, off, 0) + infoPrint(" - Unused subdict entry\n") + } else { + off = objw.SymPtr(lsym, off, sym.Linksym(), 0) + infoPrint(" - Subdict %v\n", sym.Name) } - g.dictSymsToFinalize = append(g.dictSymsToFinalize, delay) - g.instTypeList = append(g.instTypeList, subst.InstTypeList...) } + + delay := &delayInfo{ + gf: gf, + targs: targs, + sym: sym, + off: off, + } + g.dictSymsToFinalize = append(g.dictSymsToFinalize, delay) + g.instTypeList = append(g.instTypeList, subst.InstTypeList...) return sym } @@ -1805,11 +1593,6 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo { } else if n.Op() == ir.OXDOT && !n.(*ir.SelectorExpr).Implicit() && n.(*ir.SelectorExpr).Selection != nil && len(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) > 0 { - if n.(*ir.SelectorExpr).X.Op() == ir.OTYPE { - infoPrint(" Closure&subdictionary required at generic meth expr %v\n", n) - } else { - infoPrint(" Closure&subdictionary required at generic meth value %v\n", n) - } if hasTParamTypes(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) { if n.(*ir.SelectorExpr).X.Op() == ir.OTYPE { infoPrint(" Closure&subdictionary required at generic meth expr %v\n", n) @@ -1849,7 +1632,7 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo { info.itabConvs = append(info.itabConvs, n) } if n.Op() == ir.OXDOT && n.(*ir.SelectorExpr).X.Type().IsTypeParam() { - infoPrint(" Itab for interface conv: %v\n", n) + infoPrint(" Itab for bound call: %v\n", n) info.itabConvs = append(info.itabConvs, n) } if (n.Op() == ir.ODOTTYPE || n.Op() == ir.ODOTTYPE2) && !n.(*ir.TypeAssertExpr).Type().IsInterface() && !n.(*ir.TypeAssertExpr).X.Type().IsEmptyInterface() { -- GitLab From 6dadee759c812961300c8d1a44959d14299fd9f8 Mon Sep 17 00:00:00 2001 From: Leonard Wang Date: Thu, 5 Aug 2021 23:04:16 +0800 Subject: [PATCH 0613/2500] [dev.typeparams] cmd/compile: unified importReader receiver name to r Change-Id: Iaf8ec7665282f4f8c0cb09a652e78aa97959274b Reviewed-on: https://go-review.googlesource.com/c/go/+/340150 Reviewed-by: Robert Griesemer Trust: Robert Griesemer Trust: Robert Findley Run-TryBot: Robert Griesemer TryBot-Result: Go Bot --- src/cmd/compile/internal/typecheck/iimport.go | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index b389c7fcb0..8d960e5808 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -412,14 +412,14 @@ func (r *importReader) doDecl(sym *types.Sym) *ir.Name { } } -func (p *importReader) value(typ *types.Type) constant.Value { +func (r *importReader) value(typ *types.Type) constant.Value { var kind constant.Kind var valType *types.Type if typ.IsTypeParam() { // If a constant had a typeparam type, then we wrote out its // actual constant kind as well. - kind = constant.Kind(p.int64()) + kind = constant.Kind(r.int64()) switch kind { case constant.Int: valType = types.Types[types.TINT64] @@ -435,24 +435,24 @@ func (p *importReader) value(typ *types.Type) constant.Value { switch kind { case constant.Bool: - return constant.MakeBool(p.bool()) + return constant.MakeBool(r.bool()) case constant.String: - return constant.MakeString(p.string()) + return constant.MakeString(r.string()) case constant.Int: var i big.Int - p.mpint(&i, valType) + r.mpint(&i, valType) return constant.Make(&i) case constant.Float: - return p.float(valType) + return r.float(valType) case constant.Complex: - return makeComplex(p.float(valType), p.float(valType)) + return makeComplex(r.float(valType), r.float(valType)) } base.Fatalf("unexpected value type: %v", typ) panic("unreachable") } -func (p *importReader) mpint(x *big.Int, typ *types.Type) { +func (r *importReader) mpint(x *big.Int, typ *types.Type) { signed, maxBytes := intSize(typ) maxSmall := 256 - maxBytes @@ -463,7 +463,7 @@ func (p *importReader) mpint(x *big.Int, typ *types.Type) { maxSmall = 256 } - n, _ := p.ReadByte() + n, _ := r.ReadByte() if uint(n) < maxSmall { v := int64(n) if signed { @@ -484,30 +484,30 @@ func (p *importReader) mpint(x *big.Int, typ *types.Type) { base.Fatalf("weird decoding: %v, %v => %v", n, signed, v) } b := make([]byte, v) - p.Read(b) + r.Read(b) x.SetBytes(b) if signed && n&1 != 0 { x.Neg(x) } } -func (p *importReader) float(typ *types.Type) constant.Value { +func (r *importReader) float(typ *types.Type) constant.Value { var mant big.Int - p.mpint(&mant, typ) + r.mpint(&mant, typ) var f big.Float f.SetInt(&mant) if f.Sign() != 0 { - f.SetMantExp(&f, int(p.int64())) + f.SetMantExp(&f, int(r.int64())) } return constant.Make(&f) } -func (p *importReader) mprat(orig constant.Value) constant.Value { - if !p.bool() { +func (r *importReader) mprat(orig constant.Value) constant.Value { + if !r.bool() { return orig } var rat big.Rat - rat.SetString(p.string()) + rat.SetString(r.string()) return constant.Make(&rat) } -- GitLab From bb5608dd5d056519bd90666b815e0b2bf65e5ee8 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 29 Jul 2021 11:10:04 -0700 Subject: [PATCH 0614/2500] [dev.typeparams] cmd/compile/internal/types2: implement type sets with term lists This CL resolves several known issues and TODOs. - Represent type sets with term lists and using term list abstractions. - Represent Unions internally as a list of (syntactical) terms. Use term operations to print terms and detect overlapping union entries. - Compute type sets corresponding to unions lazily, on demand. - Adjust code throughout. - Adjusted error check in test/typeparam/mincheck.dir/main.go to make test pass. Change-Id: Ib36fb7e1d343c2b6aec51d304f0f7d1ad415f999 Reviewed-on: https://go-review.googlesource.com/c/go/+/338310 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/builtins.go | 16 +- src/cmd/compile/internal/types2/infer.go | 37 +--- .../compile/internal/types2/instantiate.go | 24 +- src/cmd/compile/internal/types2/interface.go | 33 +-- src/cmd/compile/internal/types2/operand.go | 2 +- src/cmd/compile/internal/types2/predicates.go | 12 +- .../compile/internal/types2/sizeof_test.go | 4 +- src/cmd/compile/internal/types2/stmt.go | 2 +- src/cmd/compile/internal/types2/subst.go | 12 +- src/cmd/compile/internal/types2/termlist.go | 2 +- .../types2/testdata/check/typeinst2.go2 | 8 +- .../types2/testdata/check/typeparams.go2 | 65 +++--- .../types2/testdata/examples/constraints.go2 | 41 +++- .../types2/testdata/fixedbugs/issue41124.go2 | 10 +- src/cmd/compile/internal/types2/type.go | 21 +- src/cmd/compile/internal/types2/typeparam.go | 27 ++- src/cmd/compile/internal/types2/typeset.go | 169 ++++++++++---- src/cmd/compile/internal/types2/typestring.go | 25 ++- src/cmd/compile/internal/types2/typexpr.go | 16 +- src/cmd/compile/internal/types2/unify.go | 5 +- src/cmd/compile/internal/types2/union.go | 206 ++++-------------- src/cmd/compile/internal/types2/universe.go | 4 +- test/typeparam/mincheck.dir/main.go | 4 +- 23 files changed, 331 insertions(+), 414 deletions(-) diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 7b2c92bfa8..c022e79c97 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -144,7 +144,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( mode := invalid var typ Type var val constant.Value - switch typ = implicitArrayDeref(optype(x.typ)); t := typ.(type) { + switch typ = implicitArrayDeref(under(x.typ)); t := typ.(type) { case *Basic: if isString(t) && id == _Len { if x.mode == constant_ { @@ -178,9 +178,9 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( mode = value } - case *Union: + case *TypeParam: if t.underIs(func(t Type) bool { - switch t := t.(type) { + switch t := implicitArrayDeref(t).(type) { case *Basic: if isString(t) && id == _Len { return true @@ -817,10 +817,10 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { // type and collect possible result types at the same time. var rtypes []Type var tildes []bool - if !tp.iface().is(func(typ Type, tilde bool) bool { - if r := f(typ); r != nil { + if !tp.iface().typeSet().is(func(t *term) bool { + if r := f(t.typ); r != nil { rtypes = append(rtypes, r) - tildes = append(tildes, tilde) + tildes = append(tildes, t.tilde) return true } return false @@ -837,10 +837,8 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { // type param is placed in the current package so export/import // works as expected. tpar := NewTypeName(nopos, check.pkg, "", nil) - ptyp := check.NewTypeParam(tpar, &emptyInterface) // assigns type to tpar as a side-effect + ptyp := check.NewTypeParam(tpar, NewInterfaceType(nil, []Type{newUnion(rtypes, tildes)})) // assigns type to tpar as a side-effect ptyp.index = tp.index - tsum := newUnion(rtypes, tildes) - ptyp.bound = &Interface{complete: true, tset: &TypeSet{types: tsum}} return ptyp } diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index 00548b402e..a3772aa713 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -280,7 +280,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { }() switch t := typ.(type) { - case nil, *Basic: // TODO(gri) should nil be handled here? + case nil, *top, *Basic: // TODO(gri) should nil be handled here? break case *Array: @@ -307,9 +307,6 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { } } - case *Union: - return w.isParameterizedTermList(t.terms) - case *Signature: // t.tparams may not be nil if we are looking at a signature // of a generic function type (or an interface method) that is @@ -327,7 +324,9 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { return true } } - return w.isParameterized(tset.types) + return tset.is(func(t *term) bool { + return w.isParameterized(t.typ) + }) case *Map: return w.isParameterized(t.key) || w.isParameterized(t.elem) @@ -358,15 +357,6 @@ func (w *tpWalker) isParameterizedTypeList(list []Type) bool { return false } -func (w *tpWalker) isParameterizedTermList(list []*term) bool { - for _, t := range list { - if w.isParameterized(t.typ) { - return true - } - } - return false -} - // inferB returns the list of actual type arguments inferred from the type parameters' // bounds and an initial set of type arguments. If type inference is impossible because // unification fails, an error is reported if report is set to true, the resulting types @@ -394,7 +384,7 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty // Unify type parameters with their structural constraints, if any. for _, tpar := range tparams { typ := tpar.typ.(*TypeParam) - sbound := check.structuralType(typ.bound) + sbound := typ.structuralType() if sbound != nil { if !u.unify(typ, sbound) { if report { @@ -467,20 +457,3 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty return } - -// structuralType returns the structural type of a constraint, if any. -func (check *Checker) structuralType(constraint Type) Type { - if iface, _ := under(constraint).(*Interface); iface != nil { - types := iface.typeSet().types - if u, _ := types.(*Union); u != nil { - if u.NumTerms() == 1 { - // TODO(gri) do we need to respect tilde? - t, _ := u.Term(0) - return t - } - return nil - } - return types - } - return nil -} diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 357f041c46..b7ea193a06 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -212,7 +212,7 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap } // targ's underlying type must also be one of the interface types listed, if any - if iface.typeSet().types == nil { + if !iface.typeSet().hasTerms() { return true // nothing to do } @@ -220,24 +220,22 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap // list of iface types (i.e., the targ type list must be a non-empty subset of the iface types). if targ := asTypeParam(targ); targ != nil { targBound := targ.iface() - if targBound.typeSet().types == nil { + if !targBound.typeSet().hasTerms() { check.softErrorf(pos, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ) return false } - return iface.is(func(typ Type, tilde bool) bool { - // TODO(gri) incorporate tilde information! - if !iface.isSatisfiedBy(typ) { - // TODO(gri) match this error message with the one below (or vice versa) - check.softErrorf(pos, "%s does not satisfy %s (%s type constraint %s not found in %s)", targ, tpar.bound, targ, typ, iface.typeSet().types) - return false - } - return true - }) + if !targBound.typeSet().subsetOf(iface.typeSet()) { + // TODO(gri) need better error message + check.softErrorf(pos, "%s does not satisfy %s", targ, tpar.bound) + return false + } + return true } // Otherwise, targ's type or underlying type must also be one of the interface types listed, if any. - if !iface.isSatisfiedBy(targ) { - check.softErrorf(pos, "%s does not satisfy %s (%s not found in %s)", targ, tpar.bound, targ, iface.typeSet().types) + if !iface.typeSet().includes(targ) { + // TODO(gri) better error message + check.softErrorf(pos, "%s does not satisfy %s", targ, tpar.bound) return false } diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index fc1f5ffe00..aa7d0b05a0 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -21,20 +21,7 @@ type Interface struct { } // typeSet returns the type set for interface t. -func (t *Interface) typeSet() *TypeSet { return computeTypeSet(nil, nopos, t) } - -// is reports whether interface t represents types that all satisfy f. -func (t *Interface) is(f func(Type, bool) bool) bool { - switch t := t.typeSet().types.(type) { - case nil, *top: - // TODO(gri) should settle on top or nil to represent this case - return false // we must have at least one type! (was bug) - case *Union: - return t.is(func(t *term) bool { return f(t.typ, t.tilde) }) - default: - return f(t, false) - } -} +func (t *Interface) typeSet() *TypeSet { return computeInterfaceTypeSet(nil, nopos, t) } // emptyInterface represents the empty interface var emptyInterface = Interface{complete: true, tset: &topTypeSet} @@ -113,22 +100,6 @@ func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() } // IsConstraint reports whether interface t is not just a method set. func (t *Interface) IsConstraint() bool { return !t.typeSet().IsMethodSet() } -// isSatisfiedBy reports whether interface t's type list is satisfied by the type typ. -// If the type list is empty (absent), typ trivially satisfies the interface. -// TODO(gri) This is not a great name. Eventually, we should have a more comprehensive -// "implements" predicate. -func (t *Interface) isSatisfiedBy(typ Type) bool { - switch t := t.typeSet().types.(type) { - case nil: - return true // no type restrictions - case *Union: - r, _ := t.intersect(typ, false) - return r != nil - default: - return Identical(t, typ) - } -} - // Complete computes the interface's type set. It must be called by users of // NewInterfaceType and NewInterface after the interface's embedded types are // fully defined and before using the interface type in any way other than to @@ -262,7 +233,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType // Compute type set with a non-nil *Checker as soon as possible // to report any errors. Subsequent uses of type sets will use // this computed type set and won't need to pass in a *Checker. - check.later(func() { computeTypeSet(check, iface.Pos(), ityp) }) + check.later(func() { computeInterfaceTypeSet(check, iface.Pos(), ityp) }) } func flattenUnion(list []syntax.Expr, x syntax.Expr) []syntax.Expr { diff --git a/src/cmd/compile/internal/types2/operand.go b/src/cmd/compile/internal/types2/operand.go index 34d35b2594..8336451e9c 100644 --- a/src/cmd/compile/internal/types2/operand.go +++ b/src/cmd/compile/internal/types2/operand.go @@ -273,7 +273,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er // x is an untyped value representable by a value of type T. if isUntyped(Vu) { - if t, ok := Tu.(*Union); ok { + if t, ok := Tu.(*TypeParam); ok { return t.is(func(t *term) bool { // TODO(gri) this could probably be more efficient if t.tilde { diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index bb7fedda3b..afef488b96 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -229,16 +229,6 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { identical(x.results, y.results, cmpTags, p) } - case *Union: - // Two union types are identical if they contain the same terms. - // The set (list) of types in a union type consists of unique - // types - each type appears exactly once. Thus, two union types - // must contain the same number of types to have chance of - // being equal. - if y, ok := y.(*Union); ok { - return identicalTerms(x.terms, y.terms) - } - case *Interface: // Two interface types are identical if they describe the same type sets. // With the existing implementation restriction, this simplifies to: @@ -250,7 +240,7 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { if y, ok := y.(*Interface); ok { xset := x.typeSet() yset := y.typeSet() - if !Identical(xset.types, yset.types) { + if !xset.terms.equal(yset.terms) { return false } a := xset.methods diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go index 8255e6ded4..d2f53258f0 100644 --- a/src/cmd/compile/internal/types2/sizeof_test.go +++ b/src/cmd/compile/internal/types2/sizeof_test.go @@ -27,7 +27,7 @@ func TestSizeof(t *testing.T) { {Pointer{}, 8, 16}, {Tuple{}, 12, 24}, {Signature{}, 28, 56}, - {Union{}, 12, 24}, + {Union{}, 16, 32}, {Interface{}, 40, 80}, {Map{}, 16, 32}, {Chan{}, 12, 24}, @@ -49,7 +49,7 @@ func TestSizeof(t *testing.T) { // Misc {Scope{}, 60, 104}, {Package{}, 40, 80}, - {TypeSet{}, 24, 48}, + {TypeSet{}, 28, 56}, } for _, test := range tests { diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index 9b8295c4f4..1efce511f1 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -921,7 +921,7 @@ func rangeKeyVal(typ Type, wantKey, wantVal bool) (Type, Type, string) { msg = "receive from send-only channel" } return typ.elem, Typ[Invalid], msg - case *Union: + case *TypeParam: first := true var key, val Type var msg string diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index e497e17463..6c5f756491 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -145,12 +145,12 @@ func (subst *subster) typ(typ Type) Type { } case *Union: - terms, copied := subst.termList(t.terms) + terms, copied := subst.termlist(t.terms) if copied { - // TODO(gri) Remove duplicates that may have crept in after substitution - // (unlikely but possible). This matters for the Identical - // predicate on unions. - return &Union{terms} + // term list substitution may introduce duplicate terms (unlikely but possible). + // This is ok; lazy type set computation will determine the actual type set + // in normal form. + return &Union{terms, nil} } case *Interface: @@ -387,7 +387,7 @@ func (subst *subster) typeList(in []Type) (out []Type, copied bool) { return } -func (subst *subster) termList(in []*term) (out []*term, copied bool) { +func (subst *subster) termlist(in []*term) (out []*term, copied bool) { out = in for i, t := range in { if u := subst.typ(t.typ); u != t.typ { diff --git a/src/cmd/compile/internal/types2/termlist.go b/src/cmd/compile/internal/types2/termlist.go index b2c26f41be..07056edd97 100644 --- a/src/cmd/compile/internal/types2/termlist.go +++ b/src/cmd/compile/internal/types2/termlist.go @@ -13,7 +13,7 @@ import "bytes" // normal form. type termlist []*term -// topTermList represents the set of all types. +// topTermlist represents the set of all types. // It is in normal form. var topTermlist = termlist{new(term)} diff --git a/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 b/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 index 14d8f0ea8c..e90e4dde44 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 @@ -164,13 +164,13 @@ type _ interface { // for them to be all in a single list, and we report the error // as well.) type _ interface { - ~int|~int /* ERROR duplicate term int */ - ~int|int /* ERROR duplicate term int */ - int|int /* ERROR duplicate term int */ + ~int|~int /* ERROR overlapping terms ~int */ + ~int|int /* ERROR overlapping terms int */ + int|int /* ERROR overlapping terms int */ } type _ interface { - ~struct{f int} | ~struct{g int} | ~struct /* ERROR duplicate term */ {f int} + ~struct{f int} | ~struct{g int} | ~struct /* ERROR overlapping terms */ {f int} } // Interface type lists can contain any type, incl. *Named types. diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 index 54efd1485b..7392b88555 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 @@ -149,37 +149,40 @@ func _[T interface{}](x T) { for range x /* ERROR cannot range */ {} } -func _[T interface{ ~string | ~[]string }](x T) { - for range x {} - for i := range x { _ = i } - for i, _ := range x { _ = i } - for i, e := range x /* ERROR must have the same element type */ { _ = i } - for _, e := range x /* ERROR must have the same element type */ {} - var e rune - _ = e - for _, (e) = range x /* ERROR must have the same element type */ {} -} - - -func _[T interface{ ~string | ~[]rune | ~map[int]rune }](x T) { - for _, e := range x { _ = e } - for i, e := range x { _ = i; _ = e } -} - -func _[T interface{ ~string | ~[]rune | ~map[string]rune }](x T) { - for _, e := range x { _ = e } - for i, e := range x /* ERROR must have the same key type */ { _ = e } -} - -func _[T interface{ ~string | ~chan int }](x T) { - for range x {} - for i := range x { _ = i } - for i, _ := range x { _ = i } // TODO(gri) should get an error here: channels only return one value -} - -func _[T interface{ ~string | ~chan<-int }](x T) { - for i := range x /* ERROR send-only channel */ { _ = i } -} +// Disabled for now until we have clarified semantics of range. +// TODO(gri) fix this +// +// func _[T interface{ ~string | ~[]string }](x T) { +// for range x {} +// for i := range x { _ = i } +// for i, _ := range x { _ = i } +// for i, e := range x /* ERROR must have the same element type */ { _ = i } +// for _, e := range x /* ERROR must have the same element type */ {} +// var e rune +// _ = e +// for _, (e) = range x /* ERROR must have the same element type */ {} +// } +// +// +// func _[T interface{ ~string | ~[]rune | ~map[int]rune }](x T) { +// for _, e := range x { _ = e } +// for i, e := range x { _ = i; _ = e } +// } +// +// func _[T interface{ ~string | ~[]rune | ~map[string]rune }](x T) { +// for _, e := range x { _ = e } +// for i, e := range x /* ERROR must have the same key type */ { _ = e } +// } +// +// func _[T interface{ ~string | ~chan int }](x T) { +// for range x {} +// for i := range x { _ = i } +// for i, _ := range x { _ = i } // TODO(gri) should get an error here: channels only return one value +// } +// +// func _[T interface{ ~string | ~chan<-int }](x T) { +// for i := range x /* ERROR send-only channel */ { _ = i } +// } // type inference checks diff --git a/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 b/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 index 28aa19bb12..f40d18c63e 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 @@ -18,18 +18,25 @@ type ( } ) +type MyInt int + type ( // Arbitrary types may be embedded like interfaces. _ interface{int} _ interface{~int} // Types may be combined into a union. - _ interface{int|~string} + union interface{int|~string} - // Union terms must be unique independent of whether they are ~ or not. - _ interface{int|int /* ERROR duplicate term int */ } - _ interface{int|~ /* ERROR duplicate term int */ int } - _ interface{~int|~ /* ERROR duplicate term int */ int } + // Union terms must describe disjoint (non-overlapping) type sets. + _ interface{int|int /* ERROR overlapping terms int */ } + _ interface{int|~ /* ERROR overlapping terms ~int */ int } + _ interface{~int|~ /* ERROR overlapping terms ~int */ int } + _ interface{~int|MyInt /* ERROR overlapping terms p.MyInt and ~int */ } + _ interface{int|interface{}} + _ interface{int|~string|union} + _ interface{int|~string|interface{int}} + _ interface{union|union /* ERROR overlapping terms p.union and p.union */ } // For now we do not permit interfaces with methods in unions. _ interface{~ /* ERROR invalid use of ~ */ interface{}} @@ -45,6 +52,15 @@ type ( _ interface{~ /* ERROR invalid use of ~ */ bar } ) +// Stand-alone type parameters are not permitted as elements or terms in unions. +type ( + _[T interface{ *T } ] struct{} // ok + _[T interface{ int | *T } ] struct{} // ok + _[T interface{ T /* ERROR cannot embed a type parameter */ } ] struct{} + _[T interface{ ~T /* ERROR cannot embed a type parameter */ } ] struct{} + _[T interface{ int|T /* ERROR cannot embed a type parameter */ }] struct{} +) + // Multiple embedded union elements are intersected. The order in which they // appear in the interface doesn't matter since intersection is a symmetric // operation. @@ -58,3 +74,18 @@ func _[T interface{ ~int; myInt1|myInt2 }]() T { return T(0) } // Here the intersections are empty - there's no type that's in the type set of T. func _[T interface{ myInt1|myInt2; int }]() T { return T(0 /* ERROR cannot convert */ ) } func _[T interface{ int; myInt1|myInt2 }]() T { return T(0 /* ERROR cannot convert */ ) } + +// Union elements may be interfaces as long as they don't define +// any methods or embed comparable. + +type ( + Integer interface{ ~int|~int8|~int16|~int32|~int64 } + Unsigned interface{ ~uint|~uint8|~uint16|~uint32|~uint64 } + Floats interface{ ~float32|~float64 } + Complex interface{ ~complex64|~complex128 } + Number interface{ Integer|Unsigned|Floats|Complex } + Ordered interface{ Integer|Unsigned|Floats|~string } + + _ interface{ Number | error /* ERROR cannot use error in union */ } + _ interface{ Ordered | comparable /* ERROR cannot use comparable in union */ } +) diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2 index ab535049dd..60650432a4 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2 @@ -47,7 +47,7 @@ type _ struct{ } type _ struct{ - I3 // ERROR interface contains type constraints + I3 // ERROR interface is .* comparable } // General composite types. @@ -59,19 +59,19 @@ type ( _ []I1 // ERROR interface is .* comparable _ []I2 // ERROR interface contains type constraints - _ *I3 // ERROR interface contains type constraints + _ *I3 // ERROR interface is .* comparable _ map[I1 /* ERROR interface is .* comparable */ ]I2 // ERROR interface contains type constraints - _ chan I3 // ERROR interface contains type constraints + _ chan I3 // ERROR interface is .* comparable _ func(I1 /* ERROR interface is .* comparable */ ) _ func() I2 // ERROR interface contains type constraints ) // Other cases. -var _ = [...]I3 /* ERROR interface contains type constraints */ {} +var _ = [...]I3 /* ERROR interface is .* comparable */ {} func _(x interface{}) { - _ = x.(I3 /* ERROR interface contains type constraints */ ) + _ = x.(I3 /* ERROR interface is .* comparable */ ) } type T1[_ any] struct{} diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index a943926189..7ae2db3412 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -44,28 +44,21 @@ func under(t Type) Type { // optype returns a type's operational type. Except for // type parameters, the operational type is the same // as the underlying type (as returned by under). For -// Type parameters, the operational type is determined -// by the corresponding type bound's type list. The -// result may be the bottom or top type, but it is never -// the incoming type parameter. +// Type parameters, the operational type is the structural +// type, if any; otherwise it's the top type. +// The result is never the incoming type parameter. func optype(typ Type) Type { if t := asTypeParam(typ); t != nil { + // TODO(gri) review accuracy of this comment // If the optype is typ, return the top type as we have // no information. It also prevents infinite recursion // via the asTypeParam converter function. This can happen // for a type parameter list of the form: // (type T interface { type T }). // See also issue #39680. - if a := t.iface().typeSet().types; a != nil { - // If we have a union with a single entry, ignore - // any tilde because under(~t) == under(t). - if u, _ := a.(*Union); u != nil && u.NumTerms() == 1 { - a, _ = u.Term(0) - } - if a != typ { - // a != typ and a is a type parameter => under(a) != typ, so this is ok - return under(a) - } + if u := t.structuralType(); u != nil { + assert(u != typ) // "naked" type parameters cannot be embedded + return u } return theTop } diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index 2614f467b1..27e6e35588 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -67,7 +67,7 @@ func (t *TypeParam) Constraint() Type { if n, _ := t.bound.(*Named); n != nil { pos = n.obj.pos } - computeTypeSet(t.check, pos, iface) + computeInterfaceTypeSet(t.check, pos, iface) } return t.bound } @@ -80,14 +80,6 @@ func (t *TypeParam) SetConstraint(bound Type) { t.bound = bound } -// iface returns the constraint interface of t. -func (t *TypeParam) iface() *Interface { - if iface, _ := under(t.Constraint()).(*Interface); iface != nil { - return iface - } - return &emptyInterface -} - // Bound returns the constraint interface of t. // Deprecated. Only here for the compiler. // TODO(gri) remove in favor of uses of Constraint. @@ -136,6 +128,23 @@ func bindTParams(list []*TypeName) *TypeParams { // ---------------------------------------------------------------------------- // Implementation +// iface returns the constraint interface of t. +func (t *TypeParam) iface() *Interface { + if iface, _ := under(t.Constraint()).(*Interface); iface != nil { + return iface + } + return &emptyInterface +} + +// structuralType returns the structural type of the type parameter's constraint; or nil. +func (t *TypeParam) structuralType() Type { + return t.iface().typeSet().structuralType() +} + +func (t *TypeParam) is(f func(*term) bool) bool { + return t.iface().typeSet().is(f) +} + func (t *TypeParam) underIs(f func(Type) bool) bool { return t.iface().typeSet().underIs(f) } diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index 5a334b2f53..6e19115ff5 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -18,31 +18,32 @@ import ( type TypeSet struct { comparable bool // if set, the interface is or embeds comparable // TODO(gri) consider using a set for the methods for faster lookup - methods []*Func // all methods of the interface; sorted by unique ID - types Type // typically a *Union; nil means no type restrictions + methods []*Func // all methods of the interface; sorted by unique ID + terms termlist // type terms of the type set } -// IsTop reports whether type set s is the top type set (corresponding to the empty interface). -func (s *TypeSet) IsTop() bool { return !s.comparable && len(s.methods) == 0 && s.types == nil } +// IsEmpty reports whether type set s is the empty set. +func (s *TypeSet) IsEmpty() bool { return s.terms.isEmpty() } + +// IsTop reports whether type set s is the set of all types (corresponding to the empty interface). +func (s *TypeSet) IsTop() bool { return !s.comparable && len(s.methods) == 0 && s.terms.isTop() } + +// TODO(gri) IsMethodSet is not a great name for this predicate. Find a better one. // IsMethodSet reports whether the type set s is described by a single set of methods. -func (s *TypeSet) IsMethodSet() bool { return !s.comparable && s.types == nil } +func (s *TypeSet) IsMethodSet() bool { return !s.comparable && s.terms.isTop() } // IsComparable reports whether each type in the set is comparable. func (s *TypeSet) IsComparable() bool { - if s.types == nil { + if s.terms.isTop() { return s.comparable } - tcomparable := s.underIs(func(u Type) bool { - return Comparable(u) + return s.is(func(t *term) bool { + return Comparable(t.typ) }) - if !s.comparable { - return tcomparable - } - return s.comparable && tcomparable } -// TODO(gri) IsTypeSet is not a great name. Find a better one. +// TODO(gri) IsTypeSet is not a great name for this predicate. Find a better one. // IsTypeSet reports whether the type set s is represented by a finite set of underlying types. func (s *TypeSet) IsTypeSet() bool { @@ -63,15 +64,21 @@ func (s *TypeSet) LookupMethod(pkg *Package, name string) (int, *Func) { } func (s *TypeSet) String() string { - if s.IsTop() { + switch { + case s.IsEmpty(): + return "∅" + case s.IsTop(): return "⊤" } + hasMethods := len(s.methods) > 0 + hasTerms := s.hasTerms() + var buf bytes.Buffer buf.WriteByte('{') if s.comparable { buf.WriteString(" comparable") - if len(s.methods) > 0 || s.types != nil { + if hasMethods || hasTerms { buf.WriteByte(';') } } @@ -82,41 +89,77 @@ func (s *TypeSet) String() string { buf.WriteByte(' ') buf.WriteString(m.String()) } - if len(s.methods) > 0 && s.types != nil { + if hasMethods && hasTerms { buf.WriteByte(';') } - if s.types != nil { - buf.WriteByte(' ') - writeType(&buf, s.types, nil, nil) + if hasTerms { + buf.WriteString(s.terms.String()) } + buf.WriteString(" }") // there was at least one method or term - buf.WriteString(" }") // there was a least one method or type return buf.String() } // ---------------------------------------------------------------------------- // Implementation -// underIs reports whether f returned true for the underlying types of the -// enumerable types in the type set s. If the type set comprises all types -// f is called once with the top type; if the type set is empty, the result -// is false. +func (s *TypeSet) hasTerms() bool { return !s.terms.isTop() } +func (s *TypeSet) structuralType() Type { return s.terms.structuralType() } +func (s *TypeSet) includes(t Type) bool { return s.terms.includes(t) } +func (s1 *TypeSet) subsetOf(s2 *TypeSet) bool { return s1.terms.subsetOf(s2.terms) } + +// TODO(gri) TypeSet.is and TypeSet.underIs should probably also go into termlist.go + +var topTerm = term{false, theTop} + +func (s *TypeSet) is(f func(*term) bool) bool { + if len(s.terms) == 0 { + return false + } + for _, t := range s.terms { + // Terms represent the top term with a nil type. + // The rest of the type checker uses the top type + // instead. Convert. + // TODO(gri) investigate if we can do without this + if t.typ == nil { + t = &topTerm + } + if !f(t) { + return false + } + } + return true +} + func (s *TypeSet) underIs(f func(Type) bool) bool { - switch t := s.types.(type) { - case nil: - return f(theTop) - default: - return f(t) - case *Union: - return t.underIs(f) + if len(s.terms) == 0 { + return false + } + for _, t := range s.terms { + // see corresponding comment in TypeSet.is + u := t.typ + if u == nil { + u = theTop + } + // t == under(t) for ~t terms + if !t.tilde { + u = under(u) + } + if debug { + assert(Identical(u, under(u))) + } + if !f(u) { + return false + } } + return true } // topTypeSet may be used as type set for the empty interface. -var topTypeSet TypeSet +var topTypeSet = TypeSet{terms: topTermlist} -// computeTypeSet may be called with check == nil. -func computeTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *TypeSet { +// computeInterfaceTypeSet may be called with check == nil. +func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *TypeSet { if ityp.tset != nil { return ityp.tset } @@ -152,7 +195,7 @@ func computeTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *TypeSet { // have valid interfaces. Mark the interface as complete to avoid // infinite recursion if the validType check occurs later for some // reason. - ityp.tset = new(TypeSet) // TODO(gri) is this sufficient? + ityp.tset = &TypeSet{terms: topTermlist} // TODO(gri) is this sufficient? // Methods of embedded interfaces are collected unchanged; i.e., the identity // of a method I.m's Func Object of an interface I is the same as that of @@ -213,7 +256,7 @@ func computeTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *TypeSet { } // collect embedded elements - var allTypes Type + var allTerms = topTermlist for i, typ := range ityp.embeddeds { // The embedding position is nil for imported interfaces // and also for interface copies after substitution (but @@ -222,25 +265,22 @@ func computeTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *TypeSet { if ityp.embedPos != nil { pos = (*ityp.embedPos)[i] } - var types Type + var terms termlist switch t := under(typ).(type) { case *Interface: - tset := computeTypeSet(check, pos, t) + tset := computeInterfaceTypeSet(check, pos, t) if tset.comparable { ityp.tset.comparable = true } for _, m := range tset.methods { addMethod(pos, m, false) // use embedding position pos rather than m.pos } - types = tset.types + terms = tset.terms case *Union: - // TODO(gri) combine with default case once we have - // converted all tests to new notation and we - // can report an error when we don't have an - // interface before go1.18. - types = typ + tset := computeUnionTypeSet(check, pos, t) + terms = tset.terms case *TypeParam: - // Embedding stand-alone type parameters is not permitted for now. + // Embedding stand-alone type parameters is not permitted. // This case is handled during union parsing. unreachable() default: @@ -251,9 +291,11 @@ func computeTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *TypeSet { check.errorf(pos, "%s is not an interface", typ) continue } - types = typ + terms = termlist{{false, typ}} } - allTypes = intersect(allTypes, types) + // The type set of an interface is the intersection + // of the type sets of all its elements. + allTerms = allTerms.intersect(terms) } ityp.embedPos = nil // not needed anymore (errors have been reported) @@ -270,7 +312,7 @@ func computeTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *TypeSet { sortMethods(methods) ityp.tset.methods = methods } - ityp.tset.types = allTypes + ityp.tset.terms = allTerms return ityp.tset } @@ -294,3 +336,34 @@ type byUniqueMethodName []*Func func (a byUniqueMethodName) Len() int { return len(a) } func (a byUniqueMethodName) Less(i, j int) bool { return a[i].less(&a[j].object) } func (a byUniqueMethodName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +// computeUnionTypeSet may be called with check == nil. +func computeUnionTypeSet(check *Checker, pos syntax.Pos, utyp *Union) *TypeSet { + if utyp.tset != nil { + return utyp.tset + } + + // avoid infinite recursion (see also computeInterfaceTypeSet) + utyp.tset = new(TypeSet) + + var allTerms termlist + for _, t := range utyp.terms { + var terms termlist + switch u := under(t.typ).(type) { + case *Interface: + terms = computeInterfaceTypeSet(check, pos, u).terms + case *TypeParam: + // A stand-alone type parameters is not permitted as union term. + // This case is handled during union parsing. + unreachable() + default: + terms = termlist{t} + } + // The type set of a union expression is the union + // of the type sets of each term. + allTerms = allTerms.union(terms) + } + utyp.tset.terms = allTerms + + return utyp.tset +} diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index b7e32c9860..558da50528 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -158,9 +158,10 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { writeSignature(buf, t, qf, visited) case *Union: - if t.IsEmpty() { - buf.WriteString("⊥") - break + // Unions only appear as (syntactic) embedded elements + // in interfaces and syntactically cannot be empty. + if t.NumTerms() == 0 { + panic("internal error: empty union") } for i, t := range t.terms { if i > 0 { @@ -198,13 +199,21 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { writeSignature(buf, m.typ.(*Signature), qf, visited) empty = false } - if !empty && tset.types != nil { + if !empty && tset.hasTerms() { buf.WriteString("; ") } - if tset.types != nil { - buf.WriteString("type ") - writeType(buf, tset.types, qf, visited) - } + first := true + tset.is(func(t *term) bool { + if !first { + buf.WriteByte('|') + } + first = false + if t.tilde { + buf.WriteByte('~') + } + writeType(buf, t.typ, qf, visited) + return true + }) } else { // print explicit interface methods and embedded types for i, m := range t.methods { diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index c55d5c093a..fa4a1638b6 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -147,18 +147,18 @@ func (check *Checker) varType(e syntax.Expr) Type { // ordinaryType reports an error if typ is an interface type containing // type lists or is (or embeds) the predeclared type comparable. func (check *Checker) ordinaryType(pos syntax.Pos, typ Type) { - // We don't want to call under() (via Interface) or complete interfaces while we + // We don't want to call under() (via asInterface) or complete interfaces while we // are in the middle of type-checking parameter declarations that might belong to // interface methods. Delay this check to the end of type-checking. check.later(func() { if t := asInterface(typ); t != nil { - tset := computeTypeSet(check, pos, t) // TODO(gri) is this the correct position? - if tset.types != nil { - check.softErrorf(pos, "interface contains type constraints (%s)", tset.types) - return - } - if tset.IsComparable() { - check.softErrorf(pos, "interface is (or embeds) comparable") + tset := computeInterfaceTypeSet(check, pos, t) // TODO(gri) is this the correct position? + if !tset.IsMethodSet() { + if tset.comparable { + check.softErrorf(pos, "interface is (or embeds) comparable") + } else { + check.softErrorf(pos, "interface contains type constraints") + } } } }) diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index aa9a23d243..75b9a12197 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -361,9 +361,6 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { u.nify(x.results, y.results, p) } - case *Union: - panic("unimplemented: unification with type sets described by types") - case *Interface: // Two interface types are identical if they have the same set of methods with // the same names and identical function types. Lower-case method names from @@ -371,7 +368,7 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { if y, ok := y.(*Interface); ok { xset := x.typeSet() yset := y.typeSet() - if !Identical(xset.types, yset.types) { + if !xset.terms.equal(yset.terms) { return false } a := xset.methods diff --git a/src/cmd/compile/internal/types2/union.go b/src/cmd/compile/internal/types2/union.go index 1215ef9057..fcd83ce688 100644 --- a/src/cmd/compile/internal/types2/union.go +++ b/src/cmd/compile/internal/types2/union.go @@ -9,17 +9,17 @@ import "cmd/compile/internal/syntax" // ---------------------------------------------------------------------------- // API -// A Union represents a union of terms. +// A Union represents a union of terms embedded in an interface. type Union struct { - terms []*term + terms []*term // list of syntactical terms (not a canonicalized termlist) + tset *TypeSet // type set described by this union, computed lazily } // NewUnion returns a new Union type with the given terms (types[i], tilde[i]). -// The lengths of both arguments must match. An empty union represents the set -// of no types. +// The lengths of both arguments must match. It is an error to create an empty +// union; they are syntactically not possible. func NewUnion(types []Type, tilde []bool) *Union { return newUnion(types, tilde) } -func (u *Union) IsEmpty() bool { return len(u.terms) == 0 } func (u *Union) NumTerms() int { return len(u.terms) } func (u *Union) Term(i int) (Type, bool) { t := u.terms[i]; return t.typ, t.tilde } @@ -29,12 +29,10 @@ func (u *Union) String() string { return TypeString(u, nil) } // ---------------------------------------------------------------------------- // Implementation -var emptyUnion = new(Union) - func newUnion(types []Type, tilde []bool) *Union { assert(len(types) == len(tilde)) if len(types) == 0 { - return emptyUnion + panic("empty union") } t := new(Union) t.terms = make([]*term, len(types)) @@ -44,52 +42,23 @@ func newUnion(types []Type, tilde []bool) *Union { return t } -// is reports whether f returns true for all terms of u. -func (u *Union) is(f func(*term) bool) bool { - if u.IsEmpty() { - return false - } - for _, t := range u.terms { - if !f(t) { - return false - } - } - return true -} - -// underIs reports whether f returned true for the underlying types of all terms of u. -func (u *Union) underIs(f func(Type) bool) bool { - if u.IsEmpty() { - return false - } - for _, t := range u.terms { - if !f(under(t.typ)) { - return false - } - } - return true -} - func parseUnion(check *Checker, tlist []syntax.Expr) Type { - var types []Type - var tilde []bool + var terms []*term for _, x := range tlist { - t, d := parseTilde(check, x) - if len(tlist) == 1 && !d { - return t // single type + tilde, typ := parseTilde(check, x) + if len(tlist) == 1 && !tilde { + return typ // single type } - types = append(types, t) - tilde = append(tilde, d) + terms = append(terms, &term{tilde, typ}) } - // Ensure that each type is only present once in the type list. - // It's ok to do this check later because it's not a requirement - // for correctness of the code. + // Check validity of terms. + // Do this check later because it requires types to be set up. // Note: This is a quadratic algorithm, but unions tend to be short. check.later(func() { - for i, t := range types { - t := expand(t) - if t == Typ[Invalid] { + for i, t := range terms { + typ := expand(t.typ) + if typ == Typ[Invalid] { continue } @@ -105,16 +74,16 @@ func parseUnion(check *Checker, tlist []syntax.Expr) Type { } } - u := under(t) + u := under(typ) f, _ := u.(*Interface) - if tilde[i] { + if t.tilde { if f != nil { - check.errorf(x, "invalid use of ~ (%s is an interface)", t) + check.errorf(x, "invalid use of ~ (%s is an interface)", typ) continue // don't report another error for t } - if !Identical(u, t) { - check.errorf(x, "invalid use of ~ (underlying type of %s is %s)", t, u) + if !Identical(u, typ) { + check.errorf(x, "invalid use of ~ (underlying type of %s is %s)", typ, u) continue // don't report another error for t } } @@ -127,19 +96,18 @@ func parseUnion(check *Checker, tlist []syntax.Expr) Type { continue // don't report another error for t } - // Complain about duplicate entries a|a, but also a|~a, and ~a|~a. - // TODO(gri) We should also exclude myint|~int since myint is included in ~int. - if includes(types[:i], t) { - // TODO(gri) this currently doesn't print the ~ if present - check.softErrorf(pos, "duplicate term %s in union element", t) + // Report overlapping (non-disjoint) terms such as + // a|a, a|~a, ~a|~a, and ~a|A (where under(A) == a). + if j := overlappingTerm(terms[:i], t); j >= 0 { + check.softErrorf(pos, "overlapping terms %s and %s", t, terms[j]) } } }) - return newUnion(types, tilde) + return &Union{terms, nil} } -func parseTilde(check *Checker, x syntax.Expr) (typ Type, tilde bool) { +func parseTilde(check *Checker, x syntax.Expr) (tilde bool, typ Type) { if op, _ := x.(*syntax.Operation); op != nil && op.Op == syntax.Tilde { x = op.X tilde = true @@ -153,116 +121,20 @@ func parseTilde(check *Checker, x syntax.Expr) (typ Type, tilde bool) { return } -// intersect computes the intersection of the types x and y, -// A nil type stands for the set of all types; an empty union -// stands for the set of no types. -func intersect(x, y Type) (r Type) { - // If one of the types is nil (no restrictions) - // the result is the other type. - switch { - case x == nil: - return y - case y == nil: - return x - } - - // Compute the terms which are in both x and y. - // TODO(gri) This is not correct as it may not always compute - // the "largest" intersection. For instance, for - // x = myInt|~int, y = ~int - // we get the result myInt but we should get ~int. - xu, _ := x.(*Union) - yu, _ := y.(*Union) - switch { - case xu != nil && yu != nil: - return &Union{intersectTerms(xu.terms, yu.terms)} - - case xu != nil: - if r, _ := xu.intersect(y, false); r != nil { - return y - } - - case yu != nil: - if r, _ := yu.intersect(x, false); r != nil { - return x - } - - default: // xu == nil && yu == nil - if Identical(x, y) { - return x - } - } - - return emptyUnion -} - -// includes reports whether typ is in list. -func includes(list []Type, typ Type) bool { - for _, e := range list { - if Identical(typ, e) { - return true - } - } - return false -} - -// intersect computes the intersection of the union u and term (y, yt) -// and returns the intersection term, if any. Otherwise the result is -// (nil, false). -// TODO(gri) this needs to cleaned up/removed once we switch to lazy -// union type set computation. -func (u *Union) intersect(y Type, yt bool) (Type, bool) { - under_y := under(y) - for _, x := range u.terms { - xt := x.tilde - // determine which types xx, yy to compare - xx := x.typ - if yt { - xx = under(xx) - } - yy := y - if xt { - yy = under_y - } - if Identical(xx, yy) { - // T ∩ T = T - // T ∩ ~t = T - // ~t ∩ T = T - // ~t ∩ ~t = ~t - return xx, xt && yt - } - } - return nil, false -} - -func identicalTerms(list1, list2 []*term) bool { - if len(list1) != len(list2) { - return false - } - // Every term in list1 must be in list2. - // Quadratic algorithm, but probably good enough for now. - // TODO(gri) we need a fast quick type ID/hash for all types. -L: - for _, x := range list1 { - for _, y := range list2 { - if x.equal(y) { - continue L // x is in list2 +// overlappingTerm reports the index of the term x in terms which is +// overlapping (not disjoint) from y. The result is < 0 if there is no +// such term. +func overlappingTerm(terms []*term, y *term) int { + for i, x := range terms { + // disjoint requires non-nil, non-top arguments + if debug { + if x == nil || x.typ == nil || y == nil || y.typ == nil { + panic("internal error: empty or top union term") } } - return false - } - return true -} - -func intersectTerms(list1, list2 []*term) (list []*term) { - // Quadratic algorithm, but good enough for now. - // TODO(gri) fix asymptotic performance - for _, x := range list1 { - for _, y := range list2 { - if r := x.intersect(y); r != nil { - list = append(list, r) - } + if !x.disjoint(y) { + return i } } - return + return -1 } diff --git a/src/cmd/compile/internal/types2/universe.go b/src/cmd/compile/internal/types2/universe.go index a3dd4bd0d6..7b6c297d05 100644 --- a/src/cmd/compile/internal/types2/universe.go +++ b/src/cmd/compile/internal/types2/universe.go @@ -89,7 +89,7 @@ func defPredeclaredTypes() { sig := NewSignature(nil, nil, NewTuple(res), false) err := NewFunc(nopos, nil, "Error", sig) ityp := &Interface{obj, []*Func{err}, nil, nil, true, nil} - computeTypeSet(nil, nopos, ityp) // prevent races due to lazy computation of tset + computeInterfaceTypeSet(nil, nopos, ityp) // prevent races due to lazy computation of tset typ := NewNamed(obj, ityp, nil) sig.recv = NewVar(nopos, nil, "", typ) def(obj) @@ -99,7 +99,7 @@ func defPredeclaredTypes() { { obj := NewTypeName(nopos, nil, "comparable", nil) obj.setColor(black) - ityp := &Interface{obj, nil, nil, nil, true, &TypeSet{true, nil, nil}} + ityp := &Interface{obj, nil, nil, nil, true, &TypeSet{true, nil, topTermlist}} NewNamed(obj, ityp, nil) def(obj) } diff --git a/test/typeparam/mincheck.dir/main.go b/test/typeparam/mincheck.dir/main.go index 72d8effcc5..9cf2c6bafd 100644 --- a/test/typeparam/mincheck.dir/main.go +++ b/test/typeparam/mincheck.dir/main.go @@ -28,11 +28,11 @@ func main() { } const want2 = "ay" - if got := a.Min[string]("bb", "ay"); got != want2 { // ERROR "string does not satisfy interface{int|int64|float64}" + if got := a.Min[string]("bb", "ay"); got != want2 { // ERROR "string does not satisfy" panic(fmt.Sprintf("got %d, want %d", got, want2)) } - if got := a.Min("bb", "ay"); got != want2 { // ERROR "string does not satisfy interface{int|int64|float64}" + if got := a.Min("bb", "ay"); got != want2 { // ERROR "string does not satisfy" panic(fmt.Sprintf("got %d, want %d", got, want2)) } } -- GitLab From f14908d01b8c4832f9ad3939165d5eec969635e1 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 4 Aug 2021 12:12:27 -0700 Subject: [PATCH 0615/2500] [dev.typeparams] cmd/compile/internal/types2: remove unused gcCompatibilityMode flag (cleanup) This flag is not needed by types2 (and possibly can also be removed from go/types). Removed some unnecessary comments along the way. Updates #46174. Change-Id: I1a7a99f724205a084d1c9850bce6f6f5d33f83ca Reviewed-on: https://go-review.googlesource.com/c/go/+/339831 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/typestring.go | 98 +++---------------- 1 file changed, 13 insertions(+), 85 deletions(-) diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 558da50528..1416008b16 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -39,27 +39,6 @@ func RelativeTo(pkg *Package) Qualifier { } } -// If gcCompatibilityMode is set, printing of types is modified -// to match the representation of some types in the gc compiler: -// -// - byte and rune lose their alias name and simply stand for -// uint8 and int32 respectively -// - embedded interfaces get flattened (the embedding info is lost, -// and certain recursive interface types cannot be printed anymore) -// -// This makes it easier to compare packages computed with the type- -// checker vs packages imported from gc export data. -// -// Caution: This flag affects all uses of WriteType, globally. -// It is only provided for testing in conjunction with -// gc-generated data. -// -// This flag is exported in the x/tools/go/types package. We don't -// need it at the moment in the std repo and so we don't export it -// anymore. We should eventually try to remove it altogether. -// TODO(gri) remove this -var gcCompatibilityMode bool - // TypeString returns the string representation of typ. // The Qualifier controls the printing of // package-level objects, and may be nil. @@ -106,16 +85,6 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { break } } - - if gcCompatibilityMode { - // forget the alias names - switch t.kind { - case Byte: - t = Typ[Uint8] - case Rune: - t = Typ[Int32] - } - } buf.WriteString(t.name) case *Array: @@ -174,66 +143,25 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { } case *Interface: - // We write the source-level methods and embedded types rather - // than the actual method set since resolved method signatures - // may have non-printable cycles if parameters have embedded - // interface types that (directly or indirectly) embed the - // current interface. For instance, consider the result type - // of m: - // - // type T interface{ - // m() interface{ T } - // } - // buf.WriteString("interface{") empty := true - if gcCompatibilityMode { - // print flattened interface - // (useful to compare against gc-generated interfaces) - tset := t.typeSet() - for i, m := range tset.methods { - if i > 0 { - buf.WriteString("; ") - } - buf.WriteString(m.name) - writeSignature(buf, m.typ.(*Signature), qf, visited) - empty = false - } - if !empty && tset.hasTerms() { + for i, m := range t.methods { + if i > 0 { buf.WriteString("; ") } - first := true - tset.is(func(t *term) bool { - if !first { - buf.WriteByte('|') - } - first = false - if t.tilde { - buf.WriteByte('~') - } - writeType(buf, t.typ, qf, visited) - return true - }) - } else { - // print explicit interface methods and embedded types - for i, m := range t.methods { - if i > 0 { - buf.WriteString("; ") - } - buf.WriteString(m.name) - writeSignature(buf, m.typ.(*Signature), qf, visited) - empty = false - } - if !empty && len(t.embeddeds) > 0 { + buf.WriteString(m.name) + writeSignature(buf, m.typ.(*Signature), qf, visited) + empty = false + } + if !empty && len(t.embeddeds) > 0 { + buf.WriteString("; ") + } + for i, typ := range t.embeddeds { + if i > 0 { buf.WriteString("; ") } - for i, typ := range t.embeddeds { - if i > 0 { - buf.WriteString("; ") - } - writeType(buf, typ, qf, visited) - empty = false - } + writeType(buf, typ, qf, visited) + empty = false } // print /* incomplete */ if needed to satisfy existing tests // TODO(gri) get rid of this eventually -- GitLab From c5b6c36ddd0ecdee401c4e78da1addf64bdc6376 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 4 Aug 2021 12:27:26 -0700 Subject: [PATCH 0616/2500] [dev.typeparams] cmd/compile/internal/types2: remove TestIncompleteInterfaces (cleanup) TestIncompleteInterfaces is not useful anymore because interface printing always shows the syntactic type structure of an interface. Also remove the respective support code in interface printing and simplify that code. Move the newDefined and nopos support declarations unchanged into api_test.go where they are used. Updates #46167. Change-Id: I23e303bc4ae4271912ba75f201bd2b7cd4a17b3e Reviewed-on: https://go-review.googlesource.com/c/go/+/339832 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/api_test.go | 8 +++ src/cmd/compile/internal/types2/typestring.go | 25 +++----- .../internal/types2/typestring_test.go | 58 ------------------- 3 files changed, 15 insertions(+), 76 deletions(-) diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index 1d3347a6de..c625bd4959 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -1567,6 +1567,14 @@ func F(){ } } +var nopos syntax.Pos + +// newDefined creates a new defined type named T with the given underlying type. +func newDefined(underlying Type) *Named { + tname := NewTypeName(nopos, nil, "T", nil) + return NewNamed(tname, underlying, nil) +} + func TestConvertibleTo(t *testing.T) { for _, test := range []struct { v, t Type diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 1416008b16..628eeaf3dd 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -144,32 +144,21 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { case *Interface: buf.WriteString("interface{") - empty := true - for i, m := range t.methods { - if i > 0 { + first := true + for _, m := range t.methods { + if !first { buf.WriteString("; ") } + first = false buf.WriteString(m.name) writeSignature(buf, m.typ.(*Signature), qf, visited) - empty = false - } - if !empty && len(t.embeddeds) > 0 { - buf.WriteString("; ") } - for i, typ := range t.embeddeds { - if i > 0 { + for _, typ := range t.embeddeds { + if !first { buf.WriteString("; ") } + first = false writeType(buf, typ, qf, visited) - empty = false - } - // print /* incomplete */ if needed to satisfy existing tests - // TODO(gri) get rid of this eventually - if debug && t.tset == nil { - if !empty { - buf.WriteByte(' ') - } - buf.WriteString("/* incomplete */") } buf.WriteByte('}') diff --git a/src/cmd/compile/internal/types2/typestring_test.go b/src/cmd/compile/internal/types2/typestring_test.go index 88103b81b1..0ed2934961 100644 --- a/src/cmd/compile/internal/types2/typestring_test.go +++ b/src/cmd/compile/internal/types2/typestring_test.go @@ -136,64 +136,6 @@ func TestTypeString(t *testing.T) { } } -var nopos syntax.Pos - -func TestIncompleteInterfaces(t *testing.T) { - if !Debug { - t.Skip("requires type checker to be compiled with debug = true") - } - - sig := NewSignature(nil, nil, nil, false) - m := NewFunc(nopos, nil, "m", sig) - for _, test := range []struct { - typ *Interface - want string - }{ - {new(Interface), "interface{/* incomplete */}"}, - {new(Interface).Complete(), "interface{}"}, - - {NewInterface(nil, nil), "interface{}"}, - {NewInterface(nil, nil).Complete(), "interface{}"}, - {NewInterface([]*Func{}, nil), "interface{}"}, - {NewInterface([]*Func{}, nil).Complete(), "interface{}"}, - {NewInterface(nil, []*Named{}), "interface{}"}, - {NewInterface(nil, []*Named{}).Complete(), "interface{}"}, - {NewInterface([]*Func{m}, nil), "interface{m() /* incomplete */}"}, - {NewInterface([]*Func{m}, nil).Complete(), "interface{m()}"}, - {NewInterface(nil, []*Named{newDefined(new(Interface).Complete())}), "interface{T /* incomplete */}"}, - {NewInterface(nil, []*Named{newDefined(new(Interface).Complete())}).Complete(), "interface{T}"}, - {NewInterface(nil, []*Named{newDefined(NewInterface([]*Func{m}, nil))}), "interface{T /* incomplete */}"}, - {NewInterface(nil, []*Named{newDefined(NewInterface([]*Func{m}, nil).Complete())}), "interface{T /* incomplete */}"}, - {NewInterface(nil, []*Named{newDefined(NewInterface([]*Func{m}, nil).Complete())}).Complete(), "interface{T}"}, - - {NewInterfaceType(nil, nil), "interface{}"}, - {NewInterfaceType(nil, nil).Complete(), "interface{}"}, - {NewInterfaceType([]*Func{}, nil), "interface{}"}, - {NewInterfaceType([]*Func{}, nil).Complete(), "interface{}"}, - {NewInterfaceType(nil, []Type{}), "interface{}"}, - {NewInterfaceType(nil, []Type{}).Complete(), "interface{}"}, - {NewInterfaceType([]*Func{m}, nil), "interface{m() /* incomplete */}"}, - {NewInterfaceType([]*Func{m}, nil).Complete(), "interface{m()}"}, - {NewInterfaceType(nil, []Type{new(Interface).Complete()}), "interface{interface{} /* incomplete */}"}, - {NewInterfaceType(nil, []Type{new(Interface).Complete()}).Complete(), "interface{interface{}}"}, - {NewInterfaceType(nil, []Type{NewInterfaceType([]*Func{m}, nil)}), "interface{interface{m() /* incomplete */} /* incomplete */}"}, - {NewInterfaceType(nil, []Type{NewInterfaceType([]*Func{m}, nil).Complete()}), "interface{interface{m()} /* incomplete */}"}, - {NewInterfaceType(nil, []Type{NewInterfaceType([]*Func{m}, nil).Complete()}).Complete(), "interface{interface{m()}}"}, - } { - got := test.typ.String() - if got != test.want { - t.Errorf("got: %s, want: %s", got, test.want) - } - } -} - -// newDefined creates a new defined type named T with the given underlying type. -// Helper function for use with TestIncompleteInterfaces only. -func newDefined(underlying Type) *Named { - tname := NewTypeName(nopos, nil, "T", nil) - return NewNamed(tname, underlying, nil) -} - func TestQualifiedTypeString(t *testing.T) { p, _ := pkgFor("p.go", "package p; type T int", nil) q, _ := pkgFor("q.go", "package q", nil) -- GitLab From f78d538858a2d9aae975b2e2c144d23bcc22c22e Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 4 Aug 2021 12:57:23 -0700 Subject: [PATCH 0617/2500] [dev.typeparams] cmd/compile/internal/types2: cleanup panic calls End-users are not expected to deal with the details of panics, so providing extra information such as an "internal error" prefix or the name of the function invoking the panic are not helpful. Remove unnecessary panic verbiage if it is readily available from a stack trace (such as the function where it happens, and the fact that is is an "internal error"). Change-Id: I5f86bae6d2cca7c04ce692d17257da7ddee206d7 Reviewed-on: https://go-review.googlesource.com/c/go/+/339969 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/decl.go | 4 ++-- src/cmd/compile/internal/types2/errors.go | 4 ++-- src/cmd/compile/internal/types2/lookup.go | 4 ++-- src/cmd/compile/internal/types2/named.go | 12 ++++++------ src/cmd/compile/internal/types2/signature.go | 4 ++-- src/cmd/compile/internal/types2/stmt.go | 2 +- src/cmd/compile/internal/types2/typeparam.go | 4 ++-- src/cmd/compile/internal/types2/typeset.go | 4 ++-- src/cmd/compile/internal/types2/typestring.go | 6 +++--- src/cmd/compile/internal/types2/union.go | 2 +- src/cmd/compile/internal/types2/universe.go | 2 +- 11 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index cf4d4c95a7..bb33c287f3 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -340,7 +340,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { // cycle detected for i, tn := range path { if t.obj.pkg != check.pkg { - panic("internal error: type cycle via package-external type") + panic("type cycle via package-external type") } if tn == t.obj { check.cycleError(path[i:]) @@ -348,7 +348,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { return t.info } } - panic("internal error: cycle start not found") + panic("cycle start not found") } return t.info } diff --git a/src/cmd/compile/internal/types2/errors.go b/src/cmd/compile/internal/types2/errors.go index 8c5e185f6c..a68273271b 100644 --- a/src/cmd/compile/internal/types2/errors.go +++ b/src/cmd/compile/internal/types2/errors.go @@ -88,7 +88,7 @@ func sprintf(qf Qualifier, format string, args ...interface{}) string { case nil: arg = "" case operand: - panic("internal error: should always pass *operand") + panic("got operand instead of *operand") case *operand: arg = operandString(a, qf) case syntax.Pos: @@ -148,7 +148,7 @@ func (check *Checker) sprintf(format string, args ...interface{}) string { func (check *Checker) report(err *error_) { if err.empty() { - panic("internal error: reporting no error") + panic("no error to report") } check.err(err.pos(), err.msg(check.qualifier), err.soft) } diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index f62c3771d2..0363008ad9 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -322,7 +322,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, return m, f } if !acceptMethodTypeParams && ftyp.TParams().Len() > 0 { - panic("internal error: method with type parameters") + panic("method with type parameters") } // If the methods have type parameters we don't care whether they @@ -374,7 +374,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, return m, f } if !acceptMethodTypeParams && ftyp.TParams().Len() > 0 { - panic("internal error: method with type parameters") + panic("method with type parameters") } // If V is a (instantiated) generic type, its methods are still diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index 8ded197df5..14e073bfae 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -33,7 +33,7 @@ type Named struct { // The underlying type must not be a *Named. func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named { if _, ok := underlying.(*Named); ok { - panic("types2.NewNamed: underlying type must not be *Named") + panic("underlying type must not be *Named") } return (*Checker)(nil).newNamed(obj, nil, underlying, nil, methods) } @@ -100,7 +100,7 @@ func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tpar check.later(func() { switch typ.under().(type) { case *Named: - panic("internal error: unexpanded underlying type") + panic("unexpanded underlying type") } typ.check = nil }) @@ -140,10 +140,10 @@ func (t *Named) Method(i int) *Func { return t.load().methods[i] } // SetUnderlying sets the underlying type and marks t as complete. func (t *Named) SetUnderlying(underlying Type) { if underlying == nil { - panic("types2.Named.SetUnderlying: underlying type must not be nil") + panic("underlying type must not be nil") } if _, ok := underlying.(*Named); ok { - panic("types2.Named.SetUnderlying: underlying type must not be *Named") + panic("underlying type must not be *Named") } t.load().underlying = underlying } @@ -191,7 +191,7 @@ func (n0 *Named) under() Type { } if n0.check == nil { - panic("internal error: Named.check == nil but type is incomplete") + panic("Named.check == nil but type is incomplete") } // Invariant: after this point n0 as well as any named types in its @@ -242,7 +242,7 @@ func (n0 *Named) under() Type { // Also, doing so would lead to a race condition (was issue #31749). // Do this check always, not just in debug mode (it's cheap). if n.obj.pkg != check.pkg { - panic("internal error: imported type with unresolved underlying type") + panic("imported type with unresolved underlying type") } n.underlying = u } diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index 832f37a6af..14112462e1 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -36,10 +36,10 @@ func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature { if variadic { n := params.Len() if n == 0 { - panic("types2.NewSignature: variadic function must have at least one parameter") + panic("variadic function must have at least one parameter") } if _, ok := params.At(n - 1).typ.(*Slice); !ok { - panic("types2.NewSignature: variadic parameter must be of unnamed slice type") + panic("variadic parameter must be of unnamed slice type") } } return &Signature{recv: recv, params: params, results: results, variadic: variadic} diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index 1efce511f1..ad8efa91f8 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -14,7 +14,7 @@ import ( func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body *syntax.BlockStmt, iota constant.Value) { if check.conf.IgnoreFuncBodies { - panic("internal error: function body not ignored") + panic("function body not ignored") } if check.conf.Trace { diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index 27e6e35588..12513ed6dd 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -75,7 +75,7 @@ func (t *TypeParam) Constraint() Type { // SetConstraint sets the type constraint for t. func (t *TypeParam) SetConstraint(bound Type) { if bound == nil { - panic("types2.TypeParam.SetConstraint: bound must not be nil") + panic("nil constraint") } t.bound = bound } @@ -118,7 +118,7 @@ func bindTParams(list []*TypeName) *TypeParams { for i, tp := range list { typ := tp.Type().(*TypeParam) if typ.index >= 0 { - panic("internal error: type parameter bound more than once") + panic("type parameter bound more than once") } typ.index = i } diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index 6e19115ff5..c5fcb97ff9 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -323,10 +323,10 @@ func sortMethods(list []*Func) { func assertSortedMethods(list []*Func) { if !debug { - panic("internal error: assertSortedMethods called outside debug mode") + panic("assertSortedMethods called outside debug mode") } if !sort.IsSorted(byUniqueMethodName(list)) { - panic("internal error: methods not sorted") + panic("methods not sorted") } } diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 628eeaf3dd..b3675424a5 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -130,7 +130,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { // Unions only appear as (syntactic) embedded elements // in interfaces and syntactically cannot be empty. if t.NumTerms() == 0 { - panic("internal error: empty union") + panic("empty union") } for i, t := range t.terms { if i > 0 { @@ -183,7 +183,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { case RecvOnly: s = "<-chan " default: - panic("unreachable") + unreachable() } buf.WriteString(s) if parens { @@ -329,7 +329,7 @@ func writeTuple(buf *bytes.Buffer, tup *Tuple, variadic bool, qf Qualifier, visi // special case: // append(s, "foo"...) leads to signature func([]byte, string...) if t := asBasic(typ); t == nil || t.kind != String { - panic("internal error: string type expected") + panic("expected string type") } writeType(buf, typ, qf, visited) buf.WriteString("...") diff --git a/src/cmd/compile/internal/types2/union.go b/src/cmd/compile/internal/types2/union.go index fcd83ce688..0325c72dbb 100644 --- a/src/cmd/compile/internal/types2/union.go +++ b/src/cmd/compile/internal/types2/union.go @@ -129,7 +129,7 @@ func overlappingTerm(terms []*term, y *term) int { // disjoint requires non-nil, non-top arguments if debug { if x == nil || x.typ == nil || y == nil || y.typ == nil { - panic("internal error: empty or top union term") + panic("empty or top union term") } } if !x.disjoint(y) { diff --git a/src/cmd/compile/internal/types2/universe.go b/src/cmd/compile/internal/types2/universe.go index 7b6c297d05..55bf0982b3 100644 --- a/src/cmd/compile/internal/types2/universe.go +++ b/src/cmd/compile/internal/types2/universe.go @@ -258,6 +258,6 @@ func def(obj Object) { } } if scope.Insert(obj) != nil { - panic("internal error: double declaration") + panic("double declaration of predeclared identifier") } } -- GitLab From ac78501b9c4f7458c6b4352b1590db058d9ac27c Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Thu, 5 Aug 2021 23:26:21 -0700 Subject: [PATCH 0618/2500] [dev.typeparams] cmd/compile: make sure closures inside generic funcs are not compiled Closures inside generic functions were being added to the g.target.Decls list during noding, just like other closures. We remove generic functions/methods from g.target.Decls, so they don't get compiled (they're only available for export and stenciling). Most closures inside generic functions/methods were similarly being removed from g.target.Decls, because they have a generic parameter. But we need to ensure no closures in generic function/methods are left remaining in g.target.Decls, since we don't want them transformed and compiled. So, we set a flag in (*irgen) that records when we are noding a top-level generic function/method, and don't add any closures to g.target.Decls when the flag is true. Updates #47514 Change-Id: Id66b4c41d307ffa8f54cab6ce3646ade81606862 Reviewed-on: https://go-review.googlesource.com/c/go/+/340258 Trust: Dan Scales Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/decl.go | 4 ++++ src/cmd/compile/internal/noder/expr.go | 9 ++++++++- src/cmd/compile/internal/noder/irgen.go | 5 +++++ test/typeparam/issue47514.go | 20 ++++++++++++++++++++ 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 test/typeparam/issue47514.go diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go index 2416d1a49e..429c8a14c8 100644 --- a/src/cmd/compile/internal/noder/decl.go +++ b/src/cmd/compile/internal/noder/decl.go @@ -102,7 +102,11 @@ func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) { g.target.Inits = append(g.target.Inits, fn) } + if fn.Type().HasTParam() { + g.topFuncIsGeneric = true + } g.funcBody(fn, decl.Recv, decl.Type, decl.Body) + g.topFuncIsGeneric = false if fn.Type().HasTParam() && fn.Body != nil { // Set pointers to the dcls/body of a generic function/method in // the Inl struct, so it is marked for export, is available for diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index a0d3cad699..6e2b1a839b 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -465,7 +465,14 @@ func (g *irgen) funcLit(typ2 types2.Type, expr *syntax.FuncLit) ir.Node { cv.SetWalkdef(1) } - return ir.UseClosure(fn.OClosure, g.target) + if g.topFuncIsGeneric { + // Don't add any closure inside a generic function/method to the + // g.target.Decls list, even though it may not be generic itself. + // See issue #47514. + return ir.UseClosure(fn.OClosure, nil) + } else { + return ir.UseClosure(fn.OClosure, g.target) + } } func (g *irgen) typeExpr(typ syntax.Expr) *types.Type { diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index 6a8763c908..571e294416 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -154,6 +154,11 @@ type irgen struct { // dictionary syms which we need to finish, by writing out any itabconv // entries. dictSymsToFinalize []*delayInfo + + // True when we are compiling a top-level generic function or method. Use to + // avoid adding closures of generic functions/methods to the target.Decls + // list. + topFuncIsGeneric bool } type delayInfo struct { diff --git a/test/typeparam/issue47514.go b/test/typeparam/issue47514.go new file mode 100644 index 0000000000..947f254003 --- /dev/null +++ b/test/typeparam/issue47514.go @@ -0,0 +1,20 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test that closures inside a generic function are not exported, +// even though not themselves generic. + +package main + +func Do[T any]() { + _ = func() string { + return "" + } +} + +func main() { + Do[int]() +} -- GitLab From 5e33d11e1051734b2495021aa64ed9f47fbae87e Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Thu, 5 Aug 2021 15:59:39 -0700 Subject: [PATCH 0619/2500] [dev.typeparams] cmd/compile: do transformCall with non-shape type of call Do the transformCall using the original types2-derived type of the call (in particular, the types of the params as non-shapes). Currently, since we were using the param types of the instantiation, we might add in interface conversions to an interface with shapes in the one case of a full-instantiated generic call. So, we do the transformCall() before installing the shaped-based instantiation. transformCall() works correctly even in the case of OCALL/FUNCINST. Fixed two related bugs: - Fixed case where we still were not correctly substituting the types for a function instantiation. - The type substituter needs to copy field flags while substituting in tstruct. Change-Id: I14e960737d6840a75846ede480e6650534ba3af3 Reviewed-on: https://go-review.googlesource.com/c/go/+/340259 Trust: Dan Scales Run-TryBot: Dan Scales Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/expr.go | 8 ++++++-- src/cmd/compile/internal/noder/stencil.go | 11 ++++++++--- src/cmd/compile/internal/noder/transform.go | 3 ++- src/cmd/compile/internal/typecheck/subr.go | 6 ++++++ 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 6e2b1a839b..3e3c352a32 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -125,13 +125,17 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { } if fun.Op() == ir.OFUNCINST { // Replace explicit type args with the full list that - // includes the additional inferred type args + // includes the additional inferred type args. + // Substitute the type args for the type params in + // the generic function's type. fun.(*ir.InstExpr).Targs = targs + newt := g.substType(fun.Type(), fun.Type().TParams(), targs) + typed(newt, fun) } else { // Create a function instantiation here, given there // are only inferred type args (e.g. min(5,6), where // min is a generic function). Substitute the type - // args for the type params in the uninstantiated function's + // args for the type params in the generic function's // type. inst := ir.NewInstExpr(pos, ir.OFUNCINST, fun, targs) newt := g.substType(fun.Type(), fun.Type().TParams(), targs) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 7cc37f1154..b37f76dcee 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -119,6 +119,14 @@ func (g *irgen) stencil() { fmt.Printf("%s in %v at generic function call: %v - %v\n", dictkind, decl, inst.X, call) } } + + // Transform the Call now, which changes OCALL to + // OCALLFUNC and does typecheckaste/assignconvfn. Do + // it before installing the instantiation, so we are + // checking against non-shape param types in + // typecheckaste. + transformCall(call) + // Replace the OFUNCINST with a direct reference to the // new stenciled function call.X = st.Nname @@ -132,9 +140,6 @@ func (g *irgen) stencil() { // Add dictionary to argument list. call.Args.Prepend(dictValue) - // Transform the Call now, which changes OCALL - // to OCALLFUNC and does typecheckaste/assignconvfn. - transformCall(call) modified = true } if n.Op() == ir.OCALLMETH && n.(*ir.CallExpr).X.Op() == ir.ODOTMETH && len(deref(n.(*ir.CallExpr).X.Type().Recv().Type).RParams()) > 0 { diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index 9c791d8a7b..61af92b62a 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -130,7 +130,8 @@ func transformConvCall(n *ir.CallExpr) ir.Node { } // transformCall transforms a normal function/method call. Corresponds to last half -// (non-conversion, non-builtin part) of typecheck.tcCall. +// (non-conversion, non-builtin part) of typecheck.tcCall. This code should work even +// in the case of OCALL/OFUNCINST. func transformCall(n *ir.CallExpr) { // n.Type() can be nil for calls with no return value assert(n.Typecheck() == 1) diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 53c3933370..e840df56dc 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1278,6 +1278,12 @@ func (ts *Tsubster) tstruct(t *types.Type, force bool) *types.Type { // the type param, not the instantiated type). newfields[i] = types.NewField(f.Pos, f.Sym, t2) newfields[i].Embedded = f.Embedded + if f.IsDDD() { + newfields[i].SetIsDDD(true) + } + if f.Nointerface() { + newfields[i].SetNointerface(true) + } if f.Nname != nil && ts.Vars != nil { v := ts.Vars[f.Nname.(*ir.Name)] if v != nil { -- GitLab From 110343e4a2a953a581e34e91e51cef08856b0b0a Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Thu, 5 Aug 2021 10:17:40 -0700 Subject: [PATCH 0620/2500] [dev.typeparams] cmd/compile: cleanup wrapper code for generics Simple change - added some comments, but also removed some TODO comments which are now done or no longer a question. Cleaned up the initial check for generic methods. The one remaining TODO that really needs to be done is generating dictionary wrappers for any methods involving embedded fields. Given we are not doing this, I think this would only affect if a struct with an embedded field with methods was converted to an interface containing the embedded method, and then the method was called via that interface. Change-Id: I6a8a2885de33ad60b313c1899b659daef7550dfb Reviewed-on: https://go-review.googlesource.com/c/go/+/340260 Trust: Dan Scales Run-TryBot: Dan Scales Reviewed-by: Keith Randall --- .../compile/internal/reflectdata/reflect.go | 52 ++++++++++--------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index a8df7a1a24..b04e4d684f 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -303,6 +303,7 @@ func MapIterType(t *types.Type) *types.Type { // Generates stub functions as needed. func methods(t *types.Type) []*typeSig { if t.HasShape() { + // Shape types have no methods. return nil } // method type @@ -1228,9 +1229,8 @@ func InterfaceMethodOffset(ityp *types.Type, i int64) int64 { // NeedRuntimeType ensures that a runtime type descriptor is emitted for t. func NeedRuntimeType(t *types.Type) { if t.HasTParam() { - // Generic types don't have a runtime type descriptor (but will - // have a dictionary) - // TODO: also shape type here? + // Generic types don't really exist at run-time and have no runtime + // type descriptor. But we do write out shape types. return } if _, ok := signatset[t]; !ok { @@ -1786,26 +1786,28 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy if forItab && !types.IsDirectIface(rcvr) { rcvr = rcvr.PtrTo() } + generic := false - if !types.IsInterfaceMethod(method.Type) && - (len(rcvr.RParams()) > 0 || - rcvr.IsPtr() && len(rcvr.Elem().RParams()) > 0) { // TODO: right detection? - // Don't need dictionary if we are reaching a method (possibly via - // an embedded field) which is an interface method. - // TODO: check that we do the right thing when method is an interface method. - generic = true - - targs := rcvr.RParams() - if rcvr.IsPtr() { - targs = rcvr.Elem().RParams() - } - // TODO: why do shape-instantiated types exist? - for _, t := range targs { - if t.HasShape() { - base.Fatalf("method on type instantiated with shapes targ:%+v rcvr:%+v", t, rcvr) + // We don't need a dictionary if we are reaching a method (possibly via an + // embedded field) which is an interface method. + if !types.IsInterfaceMethod(method.Type) { + rcvr1 := rcvr + if rcvr1.IsPtr() { + rcvr1 = rcvr.Elem() + } + if len(rcvr1.RParams()) > 0 { + // If rcvr has rparams, remember method as generic, which + // means we need to add a dictionary to the wrapper. + generic = true + targs := rcvr1.RParams() + for _, t := range targs { + if t.HasShape() { + base.Fatalf("method on type instantiated with shapes targ:%+v rcvr:%+v", t, rcvr) + } } } } + newnam := ir.MethodSym(rcvr, method.Sym) lsym := newnam.Linksym() if newnam.Siggen() { @@ -1818,6 +1820,8 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy return lsym } + // For generic methods, we need to generate the wrapper even if the receiver + // types are identical, because we want to add the dictionary. if !generic && types.Identical(rcvr, method.Type.Recv().Type) { return lsym } @@ -1890,7 +1894,7 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy if generic { var args []ir.Node var targs []*types.Type - if rcvr.IsPtr() { // TODO: correct condition? + if rcvr.IsPtr() { targs = rcvr.Elem().RParams() } else { targs = rcvr.RParams() @@ -1899,10 +1903,9 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy fmt.Printf("%s\n", ir.MethodSym(orig, method.Sym).Name) panic("multiple .inst.") } - // Temporary fix: the wrapper for an auto-generated - // pointer/non-pointer receiver method should share the - // same dictionary as the corresponding original - // (user-written) method. + // The wrapper for an auto-generated pointer/non-pointer + // receiver method should share the same dictionary as the + // corresponding original (user-written) method. baseOrig := orig if baseOrig.IsPtr() && !method.Type.Recv().Type.IsPtr() { baseOrig = baseOrig.Elem() @@ -2058,7 +2061,6 @@ func getDictionary(gf *types.Sym, targs []*types.Type) ir.Node { // Note: treat dictionary pointers as uintptrs, so they aren't pointers // with respect to GC. That saves on stack scanning work, write barriers, etc. // We can get away with it because dictionaries are global variables. - // TODO: use a cast, or is typing directly ok? np.SetType(types.Types[types.TUINTPTR]) np.SetTypecheck(1) return np -- GitLab From 5aac85ad5ebfa9c2ecb01a3292bcf3513d876d7a Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 4 Aug 2021 15:18:37 -0700 Subject: [PATCH 0621/2500] [dev.typeparams] cmd/compile/internal/types2: better names for things (cleanup) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - use the symbol 𝓤 (as in 𝓤niverse) instead of ⊤ to denote the set of all types (for better readabilty, ⊤ is hard to distinguish from T in some fonts) - use isAll instead of isTop to test for the set of all types - use allTermlist instead of topTermlist to denote the termlist representing all types Change-Id: Idcb0b3398782b38653338e65173c0dbb935e430a Reviewed-on: https://go-review.googlesource.com/c/go/+/339891 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- .../compile/internal/types2/instantiate.go | 2 +- src/cmd/compile/internal/types2/interface.go | 2 +- src/cmd/compile/internal/types2/termlist.go | 22 +++--- .../compile/internal/types2/termlist_test.go | 78 +++++++++---------- src/cmd/compile/internal/types2/typeset.go | 22 +++--- src/cmd/compile/internal/types2/typeterm.go | 31 ++++---- .../compile/internal/types2/typeterm_test.go | 42 +++++----- src/cmd/compile/internal/types2/universe.go | 2 +- 8 files changed, 100 insertions(+), 101 deletions(-) diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index b7ea193a06..0bb4ac956b 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -174,7 +174,7 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap // if iface is comparable, targ must be comparable // TODO(gri) the error messages needs to be better, here if iface.IsComparable() && !Comparable(targ) { - if tpar := asTypeParam(targ); tpar != nil && tpar.iface().typeSet().IsTop() { + if tpar := asTypeParam(targ); tpar != nil && tpar.iface().typeSet().IsAll() { check.softErrorf(pos, "%s has no constraints", targ) return false } diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index aa7d0b05a0..f763f8ff44 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -92,7 +92,7 @@ func (t *Interface) NumMethods() int { return t.typeSet().NumMethods() } func (t *Interface) Method(i int) *Func { return t.typeSet().Method(i) } // Empty reports whether t is the empty interface. -func (t *Interface) Empty() bool { return t.typeSet().IsTop() } +func (t *Interface) Empty() bool { return t.typeSet().IsAll() } // IsComparable reports whether each type in interface t's type set is comparable. func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() } diff --git a/src/cmd/compile/internal/types2/termlist.go b/src/cmd/compile/internal/types2/termlist.go index 07056edd97..378ba6b8f4 100644 --- a/src/cmd/compile/internal/types2/termlist.go +++ b/src/cmd/compile/internal/types2/termlist.go @@ -13,9 +13,9 @@ import "bytes" // normal form. type termlist []*term -// topTermlist represents the set of all types. +// allTermlist represents the set of all types. // It is in normal form. -var topTermlist = termlist{new(term)} +var allTermlist = termlist{new(term)} // String prints the termlist exactly (without normalization). func (xl termlist) String() string { @@ -45,9 +45,9 @@ func (xl termlist) isEmpty() bool { return true } -// isTop reports whether the termlist xl represents the set of all types. -func (xl termlist) isTop() bool { - // If there's a ⊤ (top) term, the entire list is ⊤ (top). +// isAll reports whether the termlist xl represents the set of all types. +func (xl termlist) isAll() bool { + // If there's a 𝓤 term, the entire list is 𝓤. // If the termlist is in normal form, this requires at most // one iteration. for _, x := range xl { @@ -74,14 +74,14 @@ func (xl termlist) norm() termlist { continue } if u1, u2 := xi.union(xj); u2 == nil { - // If we encounter a ⊤ (top) term, the entire - // list is ⊤ (top). Exit early. + // If we encounter a 𝓤 term, the entire list is 𝓤. + // Exit early. // (Note that this is not just an optimization; - // if we continue, we may end up with a ⊤ term + // if we continue, we may end up with a 𝓤 term // and other terms and the result would not be // in normal form.) if u1.typ == nil { - return topTermlist + return allTermlist } xi = u1 used[j] = true // xj is now unioned into xi - ignore it in future iterations @@ -92,11 +92,11 @@ func (xl termlist) norm() termlist { return rl } -// If the type set represented by xl is specified by a single (non-⊤) term, +// If the type set represented by xl is specified by a single (non-𝓤) term, // structuralType returns that type. Otherwise it returns nil. func (xl termlist) structuralType() Type { if nl := xl.norm(); len(nl) == 1 { - return nl[0].typ // if nl.isTop() then typ is nil, which is ok + return nl[0].typ // if nl.isAll() then typ is nil, which is ok } return nil } diff --git a/src/cmd/compile/internal/types2/termlist_test.go b/src/cmd/compile/internal/types2/termlist_test.go index c36baeb86f..706b4c9756 100644 --- a/src/cmd/compile/internal/types2/termlist_test.go +++ b/src/cmd/compile/internal/types2/termlist_test.go @@ -21,20 +21,20 @@ func maketl(s string) termlist { } func TestTermlistTop(t *testing.T) { - if !topTermlist.isTop() { - t.Errorf("topTermlist is not top") + if !allTermlist.isAll() { + t.Errorf("allTermlist is not the set of all types") } } func TestTermlistString(t *testing.T) { for _, want := range []string{ "∅", - "⊤", + "𝓤", "int", "~int", "∅ ∪ ∅", - "⊤ ∪ ⊤", - "∅ ∪ ⊤ ∪ int", + "𝓤 ∪ 𝓤", + "∅ ∪ 𝓤 ∪ int", } { if got := maketl(want).String(); got != want { t.Errorf("(%v).String() == %v", want, got) @@ -46,9 +46,9 @@ func TestTermlistIsEmpty(t *testing.T) { for test, want := range map[string]bool{ "∅": true, "∅ ∪ ∅": true, - "∅ ∪ ∅ ∪ ⊤": false, - "⊤": false, - "⊤ ∪ int": false, + "∅ ∪ ∅ ∪ 𝓤": false, + "𝓤": false, + "𝓤 ∪ int": false, } { xl := maketl(test) got := xl.isEmpty() @@ -58,19 +58,19 @@ func TestTermlistIsEmpty(t *testing.T) { } } -func TestTermlistIsTop(t *testing.T) { +func TestTermlistIsAll(t *testing.T) { for test, want := range map[string]bool{ "∅": false, "∅ ∪ ∅": false, "int ∪ ~string": false, - "∅ ∪ ∅ ∪ ⊤": true, - "⊤": true, - "⊤ ∪ int": true, + "∅ ∪ ∅ ∪ 𝓤": true, + "𝓤": true, + "𝓤 ∪ int": true, } { xl := maketl(test) - got := xl.isTop() + got := xl.isAll() if got != want { - t.Errorf("(%v).isTop() == %v; want %v", test, got, want) + t.Errorf("(%v).isAll() == %v; want %v", test, got, want) } } } @@ -82,10 +82,10 @@ func TestTermlistNorm(t *testing.T) { {"∅", "∅"}, {"∅ ∪ ∅", "∅"}, {"∅ ∪ int", "int"}, - {"⊤ ∪ int", "⊤"}, + {"𝓤 ∪ int", "𝓤"}, {"~int ∪ int", "~int"}, {"int ∪ ~string ∪ int", "int ∪ ~string"}, - {"~int ∪ string ∪ ⊤ ∪ ~string ∪ int", "⊤"}, + {"~int ∪ string ∪ 𝓤 ∪ ~string ∪ int", "𝓤"}, } { xl := maketl(test.xl) got := maketl(test.xl).norm() @@ -106,7 +106,7 @@ func TestTermlistStructuralType(t *testing.T) { for test, want := range map[string]string{ "∅": "nil", - "⊤": "nil", + "𝓤": "nil", "int": "int", "~int": "int", "~int ∪ string": "nil", @@ -128,15 +128,15 @@ func TestTermlistUnion(t *testing.T) { }{ {"∅", "∅", "∅"}, - {"∅", "⊤", "⊤"}, + {"∅", "𝓤", "𝓤"}, {"∅", "int", "int"}, - {"⊤", "~int", "⊤"}, + {"𝓤", "~int", "𝓤"}, {"int", "~int", "~int"}, {"int", "string", "int ∪ string"}, {"int ∪ string", "~string", "int ∪ ~string"}, {"~int ∪ string", "~string ∪ int", "~int ∪ ~string"}, {"~int ∪ string ∪ ∅", "~string ∪ int", "~int ∪ ~string"}, - {"~int ∪ string ∪ ⊤", "~string ∪ int", "⊤"}, + {"~int ∪ string ∪ 𝓤", "~string ∪ int", "𝓤"}, } { xl := maketl(test.xl) yl := maketl(test.yl) @@ -153,15 +153,15 @@ func TestTermlistIntersect(t *testing.T) { }{ {"∅", "∅", "∅"}, - {"∅", "⊤", "∅"}, + {"∅", "𝓤", "∅"}, {"∅", "int", "∅"}, - {"⊤", "~int", "~int"}, + {"𝓤", "~int", "~int"}, {"int", "~int", "int"}, {"int", "string", "∅"}, {"int ∪ string", "~string", "string"}, {"~int ∪ string", "~string ∪ int", "int ∪ string"}, {"~int ∪ string ∪ ∅", "~string ∪ int", "int ∪ string"}, - {"~int ∪ string ∪ ⊤", "~string ∪ int", "int ∪ ~string"}, + {"~int ∪ string ∪ 𝓤", "~string ∪ int", "int ∪ ~string"}, } { xl := maketl(test.xl) yl := maketl(test.yl) @@ -178,10 +178,10 @@ func TestTermlistEqual(t *testing.T) { want bool }{ {"∅", "∅", true}, - {"∅", "⊤", false}, - {"⊤", "⊤", true}, - {"⊤ ∪ int", "⊤", true}, - {"⊤ ∪ int", "string ∪ ⊤", true}, + {"∅", "𝓤", false}, + {"𝓤", "𝓤", true}, + {"𝓤 ∪ int", "𝓤", true}, + {"𝓤 ∪ int", "string ∪ 𝓤", true}, {"int ∪ ~string", "string ∪ int", false}, {"int ∪ ~string ∪ ∅", "string ∪ int ∪ ~string", true}, } { @@ -200,14 +200,14 @@ func TestTermlistIncludes(t *testing.T) { want bool }{ {"∅", "int", false}, - {"⊤", "int", true}, + {"𝓤", "int", true}, {"~int", "int", true}, {"int", "string", false}, {"~int", "string", false}, {"int ∪ string", "string", true}, {"~int ∪ string", "int", true}, {"~int ∪ string ∪ ∅", "string", true}, - {"~string ∪ ∅ ∪ ⊤", "int", true}, + {"~string ∪ ∅ ∪ 𝓤", "int", true}, } { xl := maketl(test.xl) yl := testTerm(test.typ).typ @@ -224,12 +224,12 @@ func TestTermlistSupersetOf(t *testing.T) { want bool }{ {"∅", "∅", true}, - {"∅", "⊤", false}, + {"∅", "𝓤", false}, {"∅", "int", false}, - {"⊤", "∅", true}, - {"⊤", "⊤", true}, - {"⊤", "int", true}, - {"⊤", "~int", true}, + {"𝓤", "∅", true}, + {"𝓤", "𝓤", true}, + {"𝓤", "int", true}, + {"𝓤", "~int", true}, {"~int", "int", true}, {"~int", "~int", true}, {"int", "~int", false}, @@ -239,7 +239,7 @@ func TestTermlistSupersetOf(t *testing.T) { {"int ∪ string", "~string", false}, {"~int ∪ string", "int", true}, {"~int ∪ string ∪ ∅", "string", true}, - {"~string ∪ ∅ ∪ ⊤", "int", true}, + {"~string ∪ ∅ ∪ 𝓤", "int", true}, } { xl := maketl(test.xl) y := testTerm(test.typ) @@ -256,16 +256,16 @@ func TestTermlistSubsetOf(t *testing.T) { want bool }{ {"∅", "∅", true}, - {"∅", "⊤", true}, - {"⊤", "∅", false}, - {"⊤", "⊤", true}, + {"∅", "𝓤", true}, + {"𝓤", "∅", false}, + {"𝓤", "𝓤", true}, {"int", "int ∪ string", true}, {"~int", "int ∪ string", false}, {"~int", "string ∪ string ∪ int ∪ ~int", true}, {"int ∪ string", "string", false}, {"int ∪ string", "string ∪ int", true}, {"int ∪ ~string", "string ∪ int", false}, - {"int ∪ ~string", "string ∪ int ∪ ⊤", true}, + {"int ∪ ~string", "string ∪ int ∪ 𝓤", true}, {"int ∪ ~string", "string ∪ int ∪ ∅ ∪ string", false}, } { xl := maketl(test.xl) diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index c5fcb97ff9..83df51389b 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -25,17 +25,19 @@ type TypeSet struct { // IsEmpty reports whether type set s is the empty set. func (s *TypeSet) IsEmpty() bool { return s.terms.isEmpty() } -// IsTop reports whether type set s is the set of all types (corresponding to the empty interface). -func (s *TypeSet) IsTop() bool { return !s.comparable && len(s.methods) == 0 && s.terms.isTop() } +// IsAll reports whether type set s is the set of all types (corresponding to the empty interface). +func (s *TypeSet) IsAll() bool { + return !s.comparable && len(s.methods) == 0 && s.terms.isAll() +} // TODO(gri) IsMethodSet is not a great name for this predicate. Find a better one. // IsMethodSet reports whether the type set s is described by a single set of methods. -func (s *TypeSet) IsMethodSet() bool { return !s.comparable && s.terms.isTop() } +func (s *TypeSet) IsMethodSet() bool { return !s.comparable && s.terms.isAll() } // IsComparable reports whether each type in the set is comparable. func (s *TypeSet) IsComparable() bool { - if s.terms.isTop() { + if s.terms.isAll() { return s.comparable } return s.is(func(t *term) bool { @@ -67,8 +69,8 @@ func (s *TypeSet) String() string { switch { case s.IsEmpty(): return "∅" - case s.IsTop(): - return "⊤" + case s.IsAll(): + return "𝓤" } hasMethods := len(s.methods) > 0 @@ -103,7 +105,7 @@ func (s *TypeSet) String() string { // ---------------------------------------------------------------------------- // Implementation -func (s *TypeSet) hasTerms() bool { return !s.terms.isTop() } +func (s *TypeSet) hasTerms() bool { return !s.terms.isAll() } func (s *TypeSet) structuralType() Type { return s.terms.structuralType() } func (s *TypeSet) includes(t Type) bool { return s.terms.includes(t) } func (s1 *TypeSet) subsetOf(s2 *TypeSet) bool { return s1.terms.subsetOf(s2.terms) } @@ -156,7 +158,7 @@ func (s *TypeSet) underIs(f func(Type) bool) bool { } // topTypeSet may be used as type set for the empty interface. -var topTypeSet = TypeSet{terms: topTermlist} +var topTypeSet = TypeSet{terms: allTermlist} // computeInterfaceTypeSet may be called with check == nil. func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *TypeSet { @@ -195,7 +197,7 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *T // have valid interfaces. Mark the interface as complete to avoid // infinite recursion if the validType check occurs later for some // reason. - ityp.tset = &TypeSet{terms: topTermlist} // TODO(gri) is this sufficient? + ityp.tset = &TypeSet{terms: allTermlist} // TODO(gri) is this sufficient? // Methods of embedded interfaces are collected unchanged; i.e., the identity // of a method I.m's Func Object of an interface I is the same as that of @@ -256,7 +258,7 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *T } // collect embedded elements - var allTerms = topTermlist + var allTerms = allTermlist for i, typ := range ityp.embeddeds { // The embedding position is nil for imported interfaces // and also for interface copies after substitution (but diff --git a/src/cmd/compile/internal/types2/typeterm.go b/src/cmd/compile/internal/types2/typeterm.go index 59a89cb004..8edbefa579 100644 --- a/src/cmd/compile/internal/types2/typeterm.go +++ b/src/cmd/compile/internal/types2/typeterm.go @@ -4,13 +4,10 @@ package types2 -// TODO(gri) use a different symbol instead of ⊤ for the set of all types -// (⊤ is hard to distinguish from T in some fonts) - // A term describes elementary type sets: // // ∅: (*term)(nil) == ∅ // set of no types (empty set) -// ⊤: &term{} == ⊤ // set of all types +// 𝓤: &term{} == 𝓤 // set of all types (𝓤niverse) // T: &term{false, T} == {T} // set of type T // ~t: &term{true, t} == {t' | under(t') == t} // set of types with underlying type t // @@ -24,7 +21,7 @@ func (x *term) String() string { case x == nil: return "∅" case x.typ == nil: - return "⊤" + return "𝓤" case x.tilde: return "~" + x.typ.String() default: @@ -41,7 +38,7 @@ func (x *term) equal(y *term) bool { case x.typ == nil || y.typ == nil: return x.typ == y.typ } - // ∅ ⊂ x, y ⊂ ⊤ + // ∅ ⊂ x, y ⊂ 𝓤 return x.tilde == y.tilde && Identical(x.typ, y.typ) } @@ -57,11 +54,11 @@ func (x *term) union(y *term) (_, _ *term) { case y == nil: return x, nil // x ∪ ∅ == x case x.typ == nil: - return x, nil // ⊤ ∪ y == ⊤ + return x, nil // 𝓤 ∪ y == 𝓤 case y.typ == nil: - return y, nil // x ∪ ⊤ == ⊤ + return y, nil // x ∪ 𝓤 == 𝓤 } - // ∅ ⊂ x, y ⊂ ⊤ + // ∅ ⊂ x, y ⊂ 𝓤 if x.disjoint(y) { return x, y // x ∪ y == (x, y) if x ∩ y == ∅ @@ -85,11 +82,11 @@ func (x *term) intersect(y *term) *term { case x == nil || y == nil: return nil // ∅ ∩ y == ∅ and ∩ ∅ == ∅ case x.typ == nil: - return y // ⊤ ∩ y == y + return y // 𝓤 ∩ y == y case y.typ == nil: - return x // x ∩ ⊤ == x + return x // x ∩ 𝓤 == x } - // ∅ ⊂ x, y ⊂ ⊤ + // ∅ ⊂ x, y ⊂ 𝓤 if x.disjoint(y) { return nil // x ∩ y == ∅ if x ∩ y == ∅ @@ -113,9 +110,9 @@ func (x *term) includes(t Type) bool { case x == nil: return false // t ∈ ∅ == false case x.typ == nil: - return true // t ∈ ⊤ == true + return true // t ∈ 𝓤 == true } - // ∅ ⊂ x ⊂ ⊤ + // ∅ ⊂ x ⊂ 𝓤 u := t if x.tilde { @@ -133,11 +130,11 @@ func (x *term) subsetOf(y *term) bool { case y == nil: return false // x ⊆ ∅ == false since x != ∅ case y.typ == nil: - return true // x ⊆ ⊤ == true + return true // x ⊆ 𝓤 == true case x.typ == nil: - return false // ⊤ ⊆ y == false since y != ⊤ + return false // 𝓤 ⊆ y == false since y != 𝓤 } - // ∅ ⊂ x, y ⊂ ⊤ + // ∅ ⊂ x, y ⊂ 𝓤 if x.disjoint(y) { return false // x ⊆ y == false if x ∩ y == ∅ diff --git a/src/cmd/compile/internal/types2/typeterm_test.go b/src/cmd/compile/internal/types2/typeterm_test.go index cc4e30d989..a8cc362f56 100644 --- a/src/cmd/compile/internal/types2/typeterm_test.go +++ b/src/cmd/compile/internal/types2/typeterm_test.go @@ -11,7 +11,7 @@ import ( var testTerms = map[string]*term{ "∅": nil, - "⊤": {}, + "𝓤": {}, "int": {false, Typ[Int]}, "~int": {true, Typ[Int]}, "string": {false, Typ[String]}, @@ -46,14 +46,14 @@ func testTerm(name string) *term { func TestTermEqual(t *testing.T) { for _, test := range []string{ "∅ ∅ T", - "⊤ ⊤ T", + "𝓤 𝓤 T", "int int T", "~int ~int T", - "∅ ⊤ F", + "∅ 𝓤 F", "∅ int F", "∅ ~int F", - "⊤ int F", - "⊤ ~int F", + "𝓤 int F", + "𝓤 ~int F", "int ~int F", } { args := split(test, 3) @@ -74,12 +74,12 @@ func TestTermEqual(t *testing.T) { func TestTermUnion(t *testing.T) { for _, test := range []string{ "∅ ∅ ∅ ∅", - "∅ ⊤ ⊤ ∅", + "∅ 𝓤 𝓤 ∅", "∅ int int ∅", "∅ ~int ~int ∅", - "⊤ ⊤ ⊤ ∅", - "⊤ int ⊤ ∅", - "⊤ ~int ⊤ ∅", + "𝓤 𝓤 𝓤 ∅", + "𝓤 int 𝓤 ∅", + "𝓤 ~int 𝓤 ∅", "int int int ∅", "int ~int ~int ∅", "int string int string", @@ -87,11 +87,11 @@ func TestTermUnion(t *testing.T) { "~int ~string ~int ~string", // union is symmetric, but the result order isn't - repeat symmetric cases explictly - "⊤ ∅ ⊤ ∅", + "𝓤 ∅ 𝓤 ∅", "int ∅ int ∅", "~int ∅ ~int ∅", - "int ⊤ ⊤ ∅", - "~int ⊤ ⊤ ∅", + "int 𝓤 𝓤 ∅", + "~int 𝓤 𝓤 ∅", "~int int ~int ∅", "string int string int", "~string int ~string int", @@ -111,12 +111,12 @@ func TestTermUnion(t *testing.T) { func TestTermIntersection(t *testing.T) { for _, test := range []string{ "∅ ∅ ∅", - "∅ ⊤ ∅", + "∅ 𝓤 ∅", "∅ int ∅", "∅ ~int ∅", - "⊤ ⊤ ⊤", - "⊤ int int", - "⊤ ~int ~int", + "𝓤 𝓤 𝓤", + "𝓤 int int", + "𝓤 ~int ~int", "int int int", "int ~int int", "int string ∅", @@ -141,7 +141,7 @@ func TestTermIntersection(t *testing.T) { func TestTermIncludes(t *testing.T) { for _, test := range []string{ "∅ int F", - "⊤ int T", + "𝓤 int T", "int int T", "~int int T", "string int F", @@ -160,14 +160,14 @@ func TestTermIncludes(t *testing.T) { func TestTermSubsetOf(t *testing.T) { for _, test := range []string{ "∅ ∅ T", - "⊤ ⊤ T", + "𝓤 𝓤 T", "int int T", "~int ~int T", - "∅ ⊤ T", + "∅ 𝓤 T", "∅ int T", "∅ ~int T", - "⊤ int F", - "⊤ ~int F", + "𝓤 int F", + "𝓤 ~int F", "int ~int T", } { args := split(test, 3) diff --git a/src/cmd/compile/internal/types2/universe.go b/src/cmd/compile/internal/types2/universe.go index 55bf0982b3..f14c079222 100644 --- a/src/cmd/compile/internal/types2/universe.go +++ b/src/cmd/compile/internal/types2/universe.go @@ -99,7 +99,7 @@ func defPredeclaredTypes() { { obj := NewTypeName(nopos, nil, "comparable", nil) obj.setColor(black) - ityp := &Interface{obj, nil, nil, nil, true, &TypeSet{true, nil, topTermlist}} + ityp := &Interface{obj, nil, nil, nil, true, &TypeSet{true, nil, allTermlist}} NewNamed(obj, ityp, nil) def(obj) } -- GitLab From 93285c89d1146e2698d2b8e5bf45279961f5026e Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 4 Aug 2021 16:52:25 -0700 Subject: [PATCH 0622/2500] [dev.typeparams] cmd/compile/internal/types2: fix range over exprs of type parameter type For range expressions of type parameter type, the structural type of the type parameter's constraint determines the range operation. While at it, rename implicitArrayDeref to arrayPtrDeref. Change-Id: Ib631a8a14e717498e5264944f659309df1f68cc2 Reviewed-on: https://go-review.googlesource.com/c/go/+/339897 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/builtins.go | 9 +- src/cmd/compile/internal/types2/stmt.go | 37 +---- .../types2/testdata/check/typeparams.go2 | 137 +++++++++++++----- 3 files changed, 112 insertions(+), 71 deletions(-) diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index c022e79c97..e9df605fd1 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -144,7 +144,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( mode := invalid var typ Type var val constant.Value - switch typ = implicitArrayDeref(under(x.typ)); t := typ.(type) { + switch typ = arrayPtrDeref(under(x.typ)); t := typ.(type) { case *Basic: if isString(t) && id == _Len { if x.mode == constant_ { @@ -180,7 +180,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( case *TypeParam: if t.underIs(func(t Type) bool { - switch t := implicitArrayDeref(t).(type) { + switch t := arrayPtrDeref(t).(type) { case *Basic: if isString(t) && id == _Len { return true @@ -862,10 +862,9 @@ func makeSig(res Type, args ...Type) *Signature { return &Signature{params: params, results: result} } -// implicitArrayDeref returns A if typ is of the form *A and A is an array; +// arrayPtrDeref returns A if typ is of the form *A and A is an array; // otherwise it returns typ. -// -func implicitArrayDeref(typ Type) Type { +func arrayPtrDeref(typ Type) Type { if p, ok := typ.(*Pointer); ok { if a := asArray(p.base); a != nil { return a diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index ad8efa91f8..7865c2d4f4 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -789,9 +789,9 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s // determine key/value types var key, val Type if x.mode != invalid { + // Ranging over a type parameter is permitted if it has a structural type. typ := optype(x.typ) if _, ok := typ.(*Chan); ok && sValue != nil { - // TODO(gri) this also needs to happen for channels in generic variables check.softErrorf(sValue, "range over %s permits only one iteration variable", &x) // ok to continue } @@ -900,7 +900,7 @@ func isVarName(x syntax.Expr) bool { // variables are used or present; this matters if we range over a generic // type where not all keys or values are of the same type. func rangeKeyVal(typ Type, wantKey, wantVal bool) (Type, Type, string) { - switch typ := typ.(type) { + switch typ := arrayPtrDeref(typ).(type) { case *Basic: if isString(typ) { return Typ[Int], universeRune, "" // use 'rune' name @@ -909,10 +909,6 @@ func rangeKeyVal(typ Type, wantKey, wantVal bool) (Type, Type, string) { return Typ[Int], typ.elem, "" case *Slice: return Typ[Int], typ.elem, "" - case *Pointer: - if typ := asArray(typ.base); typ != nil { - return Typ[Int], typ.elem, "" - } case *Map: return typ.key, typ.elem, "" case *Chan: @@ -921,32 +917,9 @@ func rangeKeyVal(typ Type, wantKey, wantVal bool) (Type, Type, string) { msg = "receive from send-only channel" } return typ.elem, Typ[Invalid], msg - case *TypeParam: - first := true - var key, val Type - var msg string - typ.underIs(func(t Type) bool { - k, v, m := rangeKeyVal(t, wantKey, wantVal) - if k == nil || m != "" { - key, val, msg = k, v, m - return false - } - if first { - key, val, msg = k, v, m - first = false - return true - } - if wantKey && !Identical(key, k) { - key, val, msg = nil, nil, "all possible values must have the same key type" - return false - } - if wantVal && !Identical(val, v) { - key, val, msg = nil, nil, "all possible values must have the same element type" - return false - } - return true - }) - return key, val, msg + case *top: + // we have a type parameter with no structural type + return nil, nil, "no structural type" } return nil, nil, "" } diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 index 7392b88555..ba8e837346 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 @@ -149,40 +149,109 @@ func _[T interface{}](x T) { for range x /* ERROR cannot range */ {} } -// Disabled for now until we have clarified semantics of range. -// TODO(gri) fix this -// -// func _[T interface{ ~string | ~[]string }](x T) { -// for range x {} -// for i := range x { _ = i } -// for i, _ := range x { _ = i } -// for i, e := range x /* ERROR must have the same element type */ { _ = i } -// for _, e := range x /* ERROR must have the same element type */ {} -// var e rune -// _ = e -// for _, (e) = range x /* ERROR must have the same element type */ {} -// } -// -// -// func _[T interface{ ~string | ~[]rune | ~map[int]rune }](x T) { -// for _, e := range x { _ = e } -// for i, e := range x { _ = i; _ = e } -// } -// -// func _[T interface{ ~string | ~[]rune | ~map[string]rune }](x T) { -// for _, e := range x { _ = e } -// for i, e := range x /* ERROR must have the same key type */ { _ = e } -// } -// -// func _[T interface{ ~string | ~chan int }](x T) { -// for range x {} -// for i := range x { _ = i } -// for i, _ := range x { _ = i } // TODO(gri) should get an error here: channels only return one value -// } -// -// func _[T interface{ ~string | ~chan<-int }](x T) { -// for i := range x /* ERROR send-only channel */ { _ = i } -// } +type myString string + +func _[ + B1 interface{ string }, + B2 interface{ string | myString }, + + C1 interface{ chan int }, + C2 interface{ chan int | <-chan int }, + C3 interface{ chan<- int }, + + S1 interface{ []int }, + S2 interface{ []int | [10]int }, + + A1 interface{ [10]int }, + A2 interface{ [10]int | []int }, + + P1 interface{ *[10]int }, + P2 interface{ *[10]int | *[]int }, + + M1 interface{ map[string]int }, + M2 interface{ map[string]int | map[string]string }, +]() { + var b0 string + for range b0 {} + for _ = range b0 {} + for _, _ = range b0 {} + + var b1 B1 + for range b1 {} + for _ = range b1 {} + for _, _ = range b1 {} + + var b2 B2 + for range b2 /* ERROR cannot range over b2 .* no structural type */ {} + + var c0 chan int + for range c0 {} + for _ = range c0 {} + for _, _ /* ERROR permits only one iteration variable */ = range c0 {} + + var c1 C1 + for range c1 {} + for _ = range c1 {} + for _, _ /* ERROR permits only one iteration variable */ = range c1 {} + + var c2 C2 + for range c2 /* ERROR cannot range over c2 .* no structural type */ {} + + var c3 C3 + for range c3 /* ERROR receive from send-only channel */ {} + + var s0 []int + for range s0 {} + for _ = range s0 {} + for _, _ = range s0 {} + + var s1 S1 + for range s1 {} + for _ = range s1 {} + for _, _ = range s1 {} + + var s2 S2 + for range s2 /* ERROR cannot range over s2 .* no structural type */ {} + + var a0 []int + for range a0 {} + for _ = range a0 {} + for _, _ = range a0 {} + + var a1 A1 + for range a1 {} + for _ = range a1 {} + for _, _ = range a1 {} + + var a2 A2 + for range a2 /* ERROR cannot range over a2 .* no structural type */ {} + + var p0 *[10]int + for range p0 {} + for _ = range p0 {} + for _, _ = range p0 {} + + var p1 P1 + for range p1 {} + for _ = range p1 {} + for _, _ = range p1 {} + + var p2 P2 + for range p2 /* ERROR cannot range over p2 .* no structural type */ {} + + var m0 map[string]int + for range m0 {} + for _ = range m0 {} + for _, _ = range m0 {} + + var m1 M1 + for range m1 {} + for _ = range m1 {} + for _, _ = range m1 {} + + var m2 M2 + for range m2 /* ERROR cannot range over m2 .* no structural type */ {} +} // type inference checks -- GitLab From 0811108670a178eb3d1403da81bfed20a7ffe1d7 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 4 Aug 2021 18:01:41 -0700 Subject: [PATCH 0623/2500] [dev.typeparams] cmd/compile/internal/types2: fix make with type parameter argument For make with a type parameter argument, the structural type of the type parameter's constraint determines what make is making. Change-Id: I3b48f8ce3236b7624e0638b5f5be208c5915c987 Reviewed-on: https://go-review.googlesource.com/c/go/+/339899 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/builtins.go | 42 +++------- .../types2/testdata/check/builtins.go2 | 79 ++++++++----------- test/typeparam/builtins.go | 71 ++++++++--------- 3 files changed, 80 insertions(+), 112 deletions(-) diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index e9df605fd1..184cd027cb 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -472,39 +472,21 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( return } - min, max := -1, 10 - var valid func(t Type) bool - valid = func(t Type) bool { - var m int - switch t := under(t).(type) { - case *Slice: - m = 2 - case *Map, *Chan: - m = 1 - case *TypeParam: - return t.underIs(valid) - default: - return false - } - if m > min { - min = m - } - if m+1 < max { - max = m + 1 - } - return true - } - - if !valid(T) { + var min int // minimum number of arguments + switch optype(T).(type) { + case *Slice: + min = 2 + case *Map, *Chan: + min = 1 + case *top: + check.errorf(arg0, invalidArg+"cannot make %s; type parameter has no structural type", arg0) + return + default: check.errorf(arg0, invalidArg+"cannot make %s; type must be slice, map, or channel", arg0) return } - if nargs < min || max < nargs { - if min == max { - check.errorf(call, "%v expects %d arguments; found %d", call, min, nargs) - } else { - check.errorf(call, "%v expects %d or %d arguments; found %d", call, min, max, nargs) - } + if nargs < min || min+1 < nargs { + check.errorf(call, invalidOp+"%v expects %d or %d arguments; found %d", call, min, min+1, nargs) return } diff --git a/src/cmd/compile/internal/types2/testdata/check/builtins.go2 b/src/cmd/compile/internal/types2/testdata/check/builtins.go2 index 3881090603..0cfea93bf6 100644 --- a/src/cmd/compile/internal/types2/testdata/check/builtins.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/builtins.go2 @@ -84,50 +84,41 @@ func _[T M4[K, V], K comparable, V any](m T) { // make -type Bmc interface { - ~map[rune]string | ~chan int -} - -type Bms interface { - ~map[string]int | ~[]int -} - -type Bcs interface { - ~chan bool | ~[]float64 -} - -type Bss interface { - ~[]int | ~[]string -} - -func _[T any]() { - _ = make(T /* ERROR invalid argument */) - _ = make(T /* ERROR invalid argument */, 10) - _ = make(T /* ERROR invalid argument */, 10, 20) -} - -func _[T Bmc]() { - _ = make(T) - _ = make(T, 10) - _ = make /* ERROR expects 1 or 2 arguments */ (T, 10, 20) -} - -func _[T Bms]() { - _ = make /* ERROR expects 2 arguments */ (T) - _ = make(T, 10) - _ = make /* ERROR expects 2 arguments */ (T, 10, 20) -} - -func _[T Bcs]() { - _ = make /* ERROR expects 2 arguments */ (T) - _ = make(T, 10) - _ = make /* ERROR expects 2 arguments */ (T, 10, 20) -} - -func _[T Bss]() { - _ = make /* ERROR expects 2 or 3 arguments */ (T) - _ = make(T, 10) - _ = make(T, 10, 20) +func _[ + S1 interface{ []int }, + S2 interface{ []int | chan int }, + + M1 interface{ map[string]int }, + M2 interface{ map[string]int | chan int }, + + C1 interface{ chan int }, + C2 interface{ chan int | chan string }, +]() { + type S0 []int + _ = make([]int, 10) + _ = make(S0, 10) + _ = make(S1, 10) + _ = make /* ERROR not enough arguments */ () + _ = make /* ERROR expects 2 or 3 arguments */ (S1) + _ = make(S1, 10, 20) + _ = make /* ERROR expects 2 or 3 arguments */ (S1, 10, 20, 30) + _ = make(S2 /* ERROR cannot make .* no structural type */ , 10) + + type M0 map[string]int + _ = make(map[string]int) + _ = make(M0) + _ = make(M1) + _ = make(M1, 10) + _ = make/* ERROR expects 1 or 2 arguments */(M1, 10, 20) + _ = make(M2 /* ERROR cannot make .* no structural type */ ) + + type C0 chan int + _ = make(chan int) + _ = make(C0) + _ = make(C1) + _ = make(C1, 10) + _ = make/* ERROR expects 1 or 2 arguments */(C1, 10, 20) + _ = make(C2 /* ERROR cannot make .* no structural type */ ) } // unsafe.Alignof diff --git a/test/typeparam/builtins.go b/test/typeparam/builtins.go index 819588b07d..844cdae8ab 100644 --- a/test/typeparam/builtins.go +++ b/test/typeparam/builtins.go @@ -19,19 +19,19 @@ type C3 interface{ chan int | chan float32 } type C4 interface{ chan int | chan<- int } type C5[T any] interface{ ~chan T | chan<- T } -func _[T C1](ch T) { +func f1[T C1](ch T) { close(ch) } -func _[T C3](ch T) { +func f2[T C3](ch T) { close(ch) } -func _[T C4](ch T) { +func f3[T C4](ch T) { close(ch) } -func _[T C5[X], X any](ch T) { +func f4[T C5[X], X any](ch T) { close(ch) } @@ -45,61 +45,56 @@ type M2 interface { type M3 interface{ map[string]int | map[rune]int } type M4[K comparable, V any] interface{ map[K]V | map[rune]V } -func _[T M1](m T) { +func g1[T M1](m T) { delete(m, "foo") } -func _[T M2](m T) { +func g2[T M2](m T) { delete(m, "foo") } -func _[T M4[rune, V], V any](m T) { +func g3[T M4[rune, V], V any](m T) { delete(m, 'k') } // make -type Bmc interface { - ~map[rune]string | ~chan int -} - -type Bms interface { - ~map[string]int | ~[]int -} - -type Bcs interface { - ~chan bool | ~[]float64 -} +func m1[ + S1 interface{ []int }, + S2 interface{ []int | chan int }, -type Bss interface { - ~[]int | ~[]string -} + M1 interface{ map[string]int }, + M2 interface{ map[string]int | chan int }, -func _[T Bmc]() { - _ = make(T) - _ = make(T, 10) -} + C1 interface{ chan int }, + C2 interface{ chan int | chan string }, +]() { + type S0 []int + _ = make([]int, 10) + _ = make(S0, 10) + _ = make(S1, 10) + _ = make(S1, 10, 20) -func _[T Bms]() { - _ = make(T, 10) -} - -func _[T Bcs]() { - _ = make(T, 10) -} + type M0 map[string]int + _ = make(map[string]int) + _ = make(M0) + _ = make(M1) + _ = make(M1, 10) -func _[T Bss]() { - _ = make(T, 10) - _ = make(T, 10, 20) + type C0 chan int + _ = make(chan int) + _ = make(C0) + _ = make(C1) + _ = make(C1, 10) } // len/cap type Slice[T any] interface { - type []T + []T } -func _[T any, S Slice[T]]() { +func c1[T any, S Slice[T]]() { x := make(S, 5, 10) _ = len(x) _ = cap(x) @@ -107,7 +102,7 @@ func _[T any, S Slice[T]]() { // append -func _[T any, S Slice[T]]() { +func a1[T any, S Slice[T]]() { x := make(S, 5) y := make(S, 2) var z T -- GitLab From c3b57af8bc0fb4fe9b30e42891e9aff54c0c7a82 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 4 Aug 2021 21:10:31 -0700 Subject: [PATCH 0624/2500] [dev.typeparams] cmd/compile/internal/types2: minor cleanup of writeTParamList Change-Id: Iaa58b17ad65e93548bb3da8231e0cb6da0c48105 Reviewed-on: https://go-review.googlesource.com/c/go/+/339903 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/infer.go | 2 +- src/cmd/compile/internal/types2/typestring.go | 22 +++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index a3772aa713..ff4bb3ea17 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -83,7 +83,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeName, targs []Type, p // Substitute type arguments for their respective type parameters in params, // if any. Note that nil targs entries are ignored by check.subst. - // TODO(gri) Can we avoid this (we're setting known type argumemts below, + // TODO(gri) Can we avoid this (we're setting known type arguments below, // but that doesn't impact the isParameterized check for now). if params.Len() > 0 { smap := makeSubstMap(tparams, targs) diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index b3675424a5..ead17ba2f3 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -246,23 +246,27 @@ func writeTParamList(buf *bytes.Buffer, list []*TypeName, qf Qualifier, visited buf.WriteString("[") var prev Type for i, p := range list { - // TODO(gri) support 'any' sugar here. - var b Type = &emptyInterface - if t, _ := p.typ.(*TypeParam); t != nil && t.bound != nil { - b = t.bound + // Determine the type parameter and its constraint. + // list is expected to hold type parameter names, + // but don't crash if that's not the case. + tpar, _ := p.typ.(*TypeParam) + var bound Type + if tpar != nil { + bound = tpar.bound // should not be nil but we want to see it if it is } + if i > 0 { - if b != prev { - // type bound changed - write previous one before advancing + if bound != prev { + // bound changed - write previous one before advancing buf.WriteByte(' ') writeType(buf, prev, qf, visited) } buf.WriteString(", ") } - prev = b + prev = bound - if t, _ := p.typ.(*TypeParam); t != nil { - writeType(buf, t, qf, visited) + if tpar != nil { + writeType(buf, tpar, qf, visited) } else { buf.WriteString(p.name) } -- GitLab From 3a9fd99849bbd9eab7e4e14a4dda95239c41ab83 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 4 Aug 2021 21:17:54 -0700 Subject: [PATCH 0625/2500] [dev.typeparams] cmd/compile/internal/syntax: cleanup panic calls End-users are not expected to deal with the details of panics, so providing extra information such as an "internal error" prefix is not helpful. Matches the types2 changes made in https://golang.org/cl/339969 . Change-Id: Icb34a9daab981a84f41f8ae7ae5dc1b85b2d2c81 Reviewed-on: https://go-review.googlesource.com/c/go/+/339904 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/syntax/parser.go | 2 +- src/cmd/compile/internal/syntax/positions.go | 4 ++-- src/cmd/compile/internal/syntax/walk.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index 503dea7fae..acffd84885 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -604,7 +604,7 @@ func (p *parser) typeDecl(group *Group) Decl { } else { // x is the array length expression if debug && x == nil { - panic("internal error: nil expression") + panic("length expression is nil") } d.Type = p.arrayType(pos, x) } diff --git a/src/cmd/compile/internal/syntax/positions.go b/src/cmd/compile/internal/syntax/positions.go index b00f86c67c..93596559a0 100644 --- a/src/cmd/compile/internal/syntax/positions.go +++ b/src/cmd/compile/internal/syntax/positions.go @@ -12,7 +12,7 @@ func StartPos(n Node) Pos { for m := n; ; { switch n := m.(type) { case nil: - panic("internal error: nil") + panic("nil node") // packages case *File: @@ -124,7 +124,7 @@ func EndPos(n Node) Pos { for m := n; ; { switch n := m.(type) { case nil: - panic("internal error: nil") + panic("nil node") // packages case *File: diff --git a/src/cmd/compile/internal/syntax/walk.go b/src/cmd/compile/internal/syntax/walk.go index ef213daf7d..b025844204 100644 --- a/src/cmd/compile/internal/syntax/walk.go +++ b/src/cmd/compile/internal/syntax/walk.go @@ -70,7 +70,7 @@ type walker struct { func (w walker) node(n Node) { if n == nil { - panic("invalid syntax tree: nil node") + panic("nil node") } w.v = w.v.Visit(n) -- GitLab From 09d82689ed899d601a9f4b5615d67025dcdb958b Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 4 Aug 2021 22:22:54 -0700 Subject: [PATCH 0626/2500] [dev.typeparams] cmd/compile/internal/types2: add defined type to term/termlist tests Follow-up on https://golang.org/cl/339596 . Change-Id: Ifa249379df083f80176b9f99900be0bf12483f41 Reviewed-on: https://go-review.googlesource.com/c/go/+/339905 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- .../compile/internal/types2/termlist_test.go | 53 +++++++++++++++---- src/cmd/compile/internal/types2/typeterm.go | 3 ++ .../compile/internal/types2/typeterm_test.go | 36 ++++++++++++- 3 files changed, 82 insertions(+), 10 deletions(-) diff --git a/src/cmd/compile/internal/types2/termlist_test.go b/src/cmd/compile/internal/types2/termlist_test.go index 706b4c9756..2f3772ddeb 100644 --- a/src/cmd/compile/internal/types2/termlist_test.go +++ b/src/cmd/compile/internal/types2/termlist_test.go @@ -32,9 +32,11 @@ func TestTermlistString(t *testing.T) { "𝓤", "int", "~int", + "myInt", "∅ ∪ ∅", "𝓤 ∪ 𝓤", "∅ ∪ 𝓤 ∪ int", + "∅ ∪ 𝓤 ∪ int ∪ myInt", } { if got := maketl(want).String(); got != want { t.Errorf("(%v).String() == %v", want, got) @@ -44,11 +46,13 @@ func TestTermlistString(t *testing.T) { func TestTermlistIsEmpty(t *testing.T) { for test, want := range map[string]bool{ - "∅": true, - "∅ ∪ ∅": true, - "∅ ∪ ∅ ∪ 𝓤": false, - "𝓤": false, - "𝓤 ∪ int": false, + "∅": true, + "∅ ∪ ∅": true, + "∅ ∪ ∅ ∪ 𝓤": false, + "∅ ∪ ∅ ∪ myInt": false, + "𝓤": false, + "𝓤 ∪ int": false, + "𝓤 ∪ myInt ∪ ∅": false, } { xl := maketl(test) got := xl.isEmpty() @@ -63,9 +67,11 @@ func TestTermlistIsAll(t *testing.T) { "∅": false, "∅ ∪ ∅": false, "int ∪ ~string": false, + "~int ∪ myInt": false, "∅ ∪ ∅ ∪ 𝓤": true, "𝓤": true, "𝓤 ∪ int": true, + "myInt ∪ 𝓤": true, } { xl := maketl(test) got := xl.isAll() @@ -82,10 +88,15 @@ func TestTermlistNorm(t *testing.T) { {"∅", "∅"}, {"∅ ∪ ∅", "∅"}, {"∅ ∪ int", "int"}, + {"∅ ∪ myInt", "myInt"}, {"𝓤 ∪ int", "𝓤"}, + {"𝓤 ∪ myInt", "𝓤"}, + {"int ∪ myInt", "int ∪ myInt"}, {"~int ∪ int", "~int"}, + {"~int ∪ myInt", "~int"}, {"int ∪ ~string ∪ int", "int ∪ ~string"}, {"~int ∪ string ∪ 𝓤 ∪ ~string ∪ int", "𝓤"}, + {"~int ∪ string ∪ myInt ∪ ~string ∪ int", "~int ∪ ~string"}, } { xl := maketl(test.xl) got := maketl(test.xl).norm() @@ -108,8 +119,10 @@ func TestTermlistStructuralType(t *testing.T) { "∅": "nil", "𝓤": "nil", "int": "int", + "myInt": "myInt", "~int": "int", "~int ∪ string": "nil", + "~int ∪ myInt": "int", "∅ ∪ int": "int", "∅ ∪ ~int": "int", "∅ ∪ ~int ∪ string": "nil", @@ -133,10 +146,14 @@ func TestTermlistUnion(t *testing.T) { {"𝓤", "~int", "𝓤"}, {"int", "~int", "~int"}, {"int", "string", "int ∪ string"}, + {"int", "myInt", "int ∪ myInt"}, + {"~int", "myInt", "~int"}, {"int ∪ string", "~string", "int ∪ ~string"}, {"~int ∪ string", "~string ∪ int", "~int ∪ ~string"}, {"~int ∪ string ∪ ∅", "~string ∪ int", "~int ∪ ~string"}, + {"~int ∪ myInt ∪ ∅", "~string ∪ int", "~int ∪ ~string"}, {"~int ∪ string ∪ 𝓤", "~string ∪ int", "𝓤"}, + {"~int ∪ string ∪ myInt", "~string ∪ int", "~int ∪ ~string"}, } { xl := maketl(test.xl) yl := maketl(test.yl) @@ -155,13 +172,19 @@ func TestTermlistIntersect(t *testing.T) { {"∅", "∅", "∅"}, {"∅", "𝓤", "∅"}, {"∅", "int", "∅"}, + {"∅", "myInt", "∅"}, {"𝓤", "~int", "~int"}, + {"𝓤", "myInt", "myInt"}, {"int", "~int", "int"}, {"int", "string", "∅"}, + {"int", "myInt", "∅"}, + {"~int", "myInt", "myInt"}, {"int ∪ string", "~string", "string"}, {"~int ∪ string", "~string ∪ int", "int ∪ string"}, {"~int ∪ string ∪ ∅", "~string ∪ int", "int ∪ string"}, + {"~int ∪ myInt ∪ ∅", "~string ∪ int", "int"}, {"~int ∪ string ∪ 𝓤", "~string ∪ int", "int ∪ ~string"}, + {"~int ∪ string ∪ myInt", "~string ∪ int", "int ∪ string"}, } { xl := maketl(test.xl) yl := maketl(test.yl) @@ -182,7 +205,9 @@ func TestTermlistEqual(t *testing.T) { {"𝓤", "𝓤", true}, {"𝓤 ∪ int", "𝓤", true}, {"𝓤 ∪ int", "string ∪ 𝓤", true}, + {"𝓤 ∪ myInt", "string ∪ 𝓤", true}, {"int ∪ ~string", "string ∪ int", false}, + {"~int ∪ string", "string ∪ myInt", false}, {"int ∪ ~string ∪ ∅", "string ∪ int ∪ ~string", true}, } { xl := maketl(test.xl) @@ -204,10 +229,12 @@ func TestTermlistIncludes(t *testing.T) { {"~int", "int", true}, {"int", "string", false}, {"~int", "string", false}, + {"~int", "myInt", true}, {"int ∪ string", "string", true}, {"~int ∪ string", "int", true}, - {"~int ∪ string ∪ ∅", "string", true}, - {"~string ∪ ∅ ∪ 𝓤", "int", true}, + {"~int ∪ string", "myInt", true}, + {"~int ∪ myInt ∪ ∅", "myInt", true}, + {"myInt ∪ ∅ ∪ 𝓤", "int", true}, } { xl := maketl(test.xl) yl := testTerm(test.typ).typ @@ -230,16 +257,20 @@ func TestTermlistSupersetOf(t *testing.T) { {"𝓤", "𝓤", true}, {"𝓤", "int", true}, {"𝓤", "~int", true}, + {"𝓤", "myInt", true}, {"~int", "int", true}, {"~int", "~int", true}, + {"~int", "myInt", true}, {"int", "~int", false}, + {"myInt", "~int", false}, {"int", "string", false}, {"~int", "string", false}, {"int ∪ string", "string", true}, {"int ∪ string", "~string", false}, {"~int ∪ string", "int", true}, + {"~int ∪ string", "myInt", true}, {"~int ∪ string ∪ ∅", "string", true}, - {"~string ∪ ∅ ∪ 𝓤", "int", true}, + {"~string ∪ ∅ ∪ 𝓤", "myInt", true}, } { xl := maketl(test.xl) y := testTerm(test.typ) @@ -261,12 +292,16 @@ func TestTermlistSubsetOf(t *testing.T) { {"𝓤", "𝓤", true}, {"int", "int ∪ string", true}, {"~int", "int ∪ string", false}, + {"~int", "myInt ∪ string", false}, + {"myInt", "~int ∪ string", true}, {"~int", "string ∪ string ∪ int ∪ ~int", true}, + {"myInt", "string ∪ string ∪ ~int", true}, {"int ∪ string", "string", false}, {"int ∪ string", "string ∪ int", true}, {"int ∪ ~string", "string ∪ int", false}, - {"int ∪ ~string", "string ∪ int ∪ 𝓤", true}, + {"myInt ∪ ~string", "string ∪ int ∪ 𝓤", true}, {"int ∪ ~string", "string ∪ int ∪ ∅ ∪ string", false}, + {"int ∪ myInt", "string ∪ ~int ∪ ∅ ∪ string", true}, } { xl := maketl(test.xl) yl := maketl(test.yl) diff --git a/src/cmd/compile/internal/types2/typeterm.go b/src/cmd/compile/internal/types2/typeterm.go index 8edbefa579..1d7223f13c 100644 --- a/src/cmd/compile/internal/types2/typeterm.go +++ b/src/cmd/compile/internal/types2/typeterm.go @@ -151,6 +151,9 @@ func (x *term) subsetOf(y *term) bool { // disjoint reports whether x ∩ y == ∅. // x.typ and y.typ must not be nil. func (x *term) disjoint(y *term) bool { + if debug && (x.typ == nil || y.typ == nil) { + panic("invalid argument(s)") + } ux := x.typ if y.tilde { ux = under(ux) diff --git a/src/cmd/compile/internal/types2/typeterm_test.go b/src/cmd/compile/internal/types2/typeterm_test.go index a8cc362f56..5a5c1fa447 100644 --- a/src/cmd/compile/internal/types2/typeterm_test.go +++ b/src/cmd/compile/internal/types2/typeterm_test.go @@ -9,6 +9,11 @@ import ( "testing" ) +var myInt = func() Type { + tname := NewTypeName(nopos, nil, "myInt", nil) + return NewNamed(tname, Typ[Int], nil) +}() + var testTerms = map[string]*term{ "∅": nil, "𝓤": {}, @@ -16,7 +21,7 @@ var testTerms = map[string]*term{ "~int": {true, Typ[Int]}, "string": {false, Typ[String]}, "~string": {true, Typ[String]}, - // TODO(gri) add a defined type + "myInt": {false, myInt}, } func TestTermString(t *testing.T) { @@ -49,12 +54,16 @@ func TestTermEqual(t *testing.T) { "𝓤 𝓤 T", "int int T", "~int ~int T", + "myInt myInt T", "∅ 𝓤 F", "∅ int F", "∅ ~int F", "𝓤 int F", "𝓤 ~int F", + "𝓤 myInt F", "int ~int F", + "int myInt F", + "~int myInt F", } { args := split(test, 3) x := testTerm(args[0]) @@ -77,25 +86,33 @@ func TestTermUnion(t *testing.T) { "∅ 𝓤 𝓤 ∅", "∅ int int ∅", "∅ ~int ~int ∅", + "∅ myInt myInt ∅", "𝓤 𝓤 𝓤 ∅", "𝓤 int 𝓤 ∅", "𝓤 ~int 𝓤 ∅", + "𝓤 myInt 𝓤 ∅", "int int int ∅", "int ~int ~int ∅", "int string int string", "int ~string int ~string", + "int myInt int myInt", "~int ~string ~int ~string", + "~int myInt ~int ∅", // union is symmetric, but the result order isn't - repeat symmetric cases explictly "𝓤 ∅ 𝓤 ∅", "int ∅ int ∅", "~int ∅ ~int ∅", + "myInt ∅ myInt ∅", "int 𝓤 𝓤 ∅", "~int 𝓤 𝓤 ∅", + "myInt 𝓤 𝓤 ∅", "~int int ~int ∅", "string int string int", "~string int ~string int", + "myInt int myInt int", "~string ~int ~string ~int", + "myInt ~int ~int ∅", } { args := split(test, 4) x := testTerm(args[0]) @@ -114,14 +131,18 @@ func TestTermIntersection(t *testing.T) { "∅ 𝓤 ∅", "∅ int ∅", "∅ ~int ∅", + "∅ myInt ∅", "𝓤 𝓤 𝓤", "𝓤 int int", "𝓤 ~int ~int", + "𝓤 myInt myInt", "int int int", "int ~int int", "int string ∅", "int ~string ∅", + "int string ∅", "~int ~string ∅", + "~int myInt myInt", } { args := split(test, 3) x := testTerm(args[0]) @@ -144,8 +165,10 @@ func TestTermIncludes(t *testing.T) { "𝓤 int T", "int int T", "~int int T", + "~int myInt T", "string int F", "~string int F", + "myInt int F", } { args := split(test, 3) x := testTerm(args[0]) @@ -163,12 +186,19 @@ func TestTermSubsetOf(t *testing.T) { "𝓤 𝓤 T", "int int T", "~int ~int T", + "myInt myInt T", "∅ 𝓤 T", "∅ int T", "∅ ~int T", + "∅ myInt T", "𝓤 int F", "𝓤 ~int F", + "𝓤 myInt F", "int ~int T", + "int myInt F", + "~int myInt F", + "myInt int F", + "myInt ~int T", } { args := split(test, 3) x := testTerm(args[0]) @@ -187,7 +217,11 @@ func TestTermDisjoint(t *testing.T) { "int ~int F", "int string T", "int ~string T", + "int myInt T", "~int ~string T", + "~int myInt F", + "string myInt T", + "~string myInt T", } { args := split(test, 3) x := testTerm(args[0]) -- GitLab From 0d7dc417eaebd35249994bfd5cf211df9bf457c6 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 5 Aug 2021 13:24:15 -0700 Subject: [PATCH 0627/2500] [dev.typeparams] cmd/compile: change types2.Union API to accept a list of Terms Instead of providing a list of tildes and types, use a list of Terms to create a Union, with suitable accessors. Define the (exported) notion of a Term representing a union term. This simplified various uses and also will be easier to extend should we want to add more information to a Term in the future. Change-Id: I52fd73938bfa11bac60adbf10580b6d0680df4f1 Reviewed-on: https://go-review.googlesource.com/c/go/+/340250 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/importer/iimport.go | 10 ++-- src/cmd/compile/internal/noder/reader2.go | 10 ++-- src/cmd/compile/internal/noder/types.go | 8 +-- src/cmd/compile/internal/noder/writer.go | 10 ++-- src/cmd/compile/internal/types2/builtins.go | 8 ++- src/cmd/compile/internal/types2/subst.go | 6 +-- src/cmd/compile/internal/types2/typeset.go | 2 +- src/cmd/compile/internal/types2/typestring.go | 2 +- src/cmd/compile/internal/types2/union.go | 49 ++++++++++--------- 9 files changed, 52 insertions(+), 53 deletions(-) diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index 3dd28033a1..3aab32fc6b 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -677,13 +677,13 @@ func (r *importReader) doType(base *types2.Named) types2.Type { errorf("unexpected instantiation type") } nt := int(r.uint64()) - terms := make([]types2.Type, nt) - tildes := make([]bool, nt) + terms := make([]*types2.Term, nt) for i := range terms { - terms[i] = r.typ() - tildes[i] = r.bool() + typ := r.typ() + tilde := r.bool() + terms[i] = types2.NewTerm(tilde, typ) } - return types2.NewUnion(terms, tildes) + return types2.NewUnion(terms) } } diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index d183934900..0bea6675ea 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -281,13 +281,13 @@ func (r *reader2) structType() *types2.Struct { } func (r *reader2) unionType() *types2.Union { - terms := make([]types2.Type, r.len()) - tildes := make([]bool, len(terms)) + terms := make([]*types2.Term, r.len()) for i := range terms { - terms[i] = r.typ() - tildes[i] = r.bool() + typ := r.typ() + tilde := r.bool() + terms[i] = types2.NewTerm(tilde, typ) } - return types2.NewUnion(terms, tildes) + return types2.NewUnion(terms) } func (r *reader2) interfaceType() *types2.Interface { diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index 3f7280a823..4e80b1a0ff 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -232,13 +232,13 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { return tp case *types2.Union: - nt := typ.NumTerms() + nt := typ.Len() tlist := make([]*types.Type, nt) tildes := make([]bool, nt) for i := range tlist { - term, tilde := typ.Term(i) - tlist[i] = g.typ1(term) - tildes[i] = tilde + t := typ.Term(i) + tlist[i] = g.typ1(t.Type()) + tildes[i] = t.Tilde() } return types.NewUnion(tlist, tildes) diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index eb1db623b4..8b65559d1a 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -394,11 +394,11 @@ func (w *writer) structType(typ *types2.Struct) { } func (w *writer) unionType(typ *types2.Union) { - w.len(typ.NumTerms()) - for i := 0; i < typ.NumTerms(); i++ { - term, tilde := typ.Term(i) - w.typ(term) - w.bool(tilde) + w.len(typ.Len()) + for i := 0; i < typ.Len(); i++ { + t := typ.Term(i) + w.typ(t.Type()) + w.bool(t.Tilde()) } } diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 184cd027cb..eafe6e9eb8 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -797,12 +797,10 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { if tp := asTypeParam(x); tp != nil { // Test if t satisfies the requirements for the argument // type and collect possible result types at the same time. - var rtypes []Type - var tildes []bool + var terms []*Term if !tp.iface().typeSet().is(func(t *term) bool { if r := f(t.typ); r != nil { - rtypes = append(rtypes, r) - tildes = append(tildes, t.tilde) + terms = append(terms, NewTerm(t.tilde, r)) return true } return false @@ -819,7 +817,7 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { // type param is placed in the current package so export/import // works as expected. tpar := NewTypeName(nopos, check.pkg, "", nil) - ptyp := check.NewTypeParam(tpar, NewInterfaceType(nil, []Type{newUnion(rtypes, tildes)})) // assigns type to tpar as a side-effect + ptyp := check.NewTypeParam(tpar, NewInterfaceType(nil, []Type{NewUnion(terms)})) // assigns type to tpar as a side-effect ptyp.index = tp.index return ptyp diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 6c5f756491..26796fc604 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -387,19 +387,19 @@ func (subst *subster) typeList(in []Type) (out []Type, copied bool) { return } -func (subst *subster) termlist(in []*term) (out []*term, copied bool) { +func (subst *subster) termlist(in []*Term) (out []*Term, copied bool) { out = in for i, t := range in { if u := subst.typ(t.typ); u != t.typ { if !copied { // first function that got substituted => allocate new out slice // and copy all functions - new := make([]*term, len(in)) + new := make([]*Term, len(in)) copy(new, out) out = new copied = true } - out[i] = &term{t.tilde, u} + out[i] = NewTerm(t.tilde, u) } } return diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index 83df51389b..da364699ce 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -359,7 +359,7 @@ func computeUnionTypeSet(check *Checker, pos syntax.Pos, utyp *Union) *TypeSet { // This case is handled during union parsing. unreachable() default: - terms = termlist{t} + terms = termlist{(*term)(t)} } // The type set of a union expression is the union // of the type sets of each term. diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index ead17ba2f3..cb7cf73a62 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -129,7 +129,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { case *Union: // Unions only appear as (syntactic) embedded elements // in interfaces and syntactically cannot be empty. - if t.NumTerms() == 0 { + if t.Len() == 0 { panic("empty union") } for i, t := range t.terms { diff --git a/src/cmd/compile/internal/types2/union.go b/src/cmd/compile/internal/types2/union.go index 0325c72dbb..102826947c 100644 --- a/src/cmd/compile/internal/types2/union.go +++ b/src/cmd/compile/internal/types2/union.go @@ -11,45 +11,46 @@ import "cmd/compile/internal/syntax" // A Union represents a union of terms embedded in an interface. type Union struct { - terms []*term // list of syntactical terms (not a canonicalized termlist) + terms []*Term // list of syntactical terms (not a canonicalized termlist) tset *TypeSet // type set described by this union, computed lazily } -// NewUnion returns a new Union type with the given terms (types[i], tilde[i]). -// The lengths of both arguments must match. It is an error to create an empty -// union; they are syntactically not possible. -func NewUnion(types []Type, tilde []bool) *Union { return newUnion(types, tilde) } +// NewUnion returns a new Union type with the given terms. +// It is an error to create an empty union; they are syntactically not possible. +func NewUnion(terms []*Term) *Union { + if len(terms) == 0 { + panic("empty union") + } + return &Union{terms, nil} +} -func (u *Union) NumTerms() int { return len(u.terms) } -func (u *Union) Term(i int) (Type, bool) { t := u.terms[i]; return t.typ, t.tilde } +func (u *Union) Len() int { return len(u.terms) } +func (u *Union) Term(i int) *Term { return u.terms[i] } func (u *Union) Underlying() Type { return u } func (u *Union) String() string { return TypeString(u, nil) } +// A Term represents a term in a Union. +type Term term + +// NewTerm returns a new union term. +func NewTerm(tilde bool, typ Type) *Term { return &Term{tilde, typ} } + +func (t *Term) Tilde() bool { return t.tilde } +func (t *Term) Type() Type { return t.typ } +func (t *Term) String() string { return (*term)(t).String() } + // ---------------------------------------------------------------------------- // Implementation -func newUnion(types []Type, tilde []bool) *Union { - assert(len(types) == len(tilde)) - if len(types) == 0 { - panic("empty union") - } - t := new(Union) - t.terms = make([]*term, len(types)) - for i, typ := range types { - t.terms[i] = &term{tilde[i], typ} - } - return t -} - func parseUnion(check *Checker, tlist []syntax.Expr) Type { - var terms []*term + var terms []*Term for _, x := range tlist { tilde, typ := parseTilde(check, x) if len(tlist) == 1 && !tilde { return typ // single type } - terms = append(terms, &term{tilde, typ}) + terms = append(terms, NewTerm(tilde, typ)) } // Check validity of terms. @@ -124,7 +125,7 @@ func parseTilde(check *Checker, x syntax.Expr) (tilde bool, typ Type) { // overlappingTerm reports the index of the term x in terms which is // overlapping (not disjoint) from y. The result is < 0 if there is no // such term. -func overlappingTerm(terms []*term, y *term) int { +func overlappingTerm(terms []*Term, y *Term) int { for i, x := range terms { // disjoint requires non-nil, non-top arguments if debug { @@ -132,7 +133,7 @@ func overlappingTerm(terms []*term, y *term) int { panic("empty or top union term") } } - if !x.disjoint(y) { + if !(*term)(x).disjoint((*term)(y)) { return i } } -- GitLab From 313924f2726947eb0df5f8fd0462c3a7343f5bc9 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 5 Aug 2021 13:58:24 -0700 Subject: [PATCH 0628/2500] [dev.typeparams] cmd/compile: swap export order of union term components (cleanup) Export a term as a pair (tilde, type) rather than (type, tilde) to match the new Union/Term API. Change-Id: I221c09c2c746ae19fbae0c970ffb26fa7a8ac736 Reviewed-on: https://go-review.googlesource.com/c/go/+/340251 Trust: Robert Griesemer Trust: Dan Scales Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Dan Scales Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/importer/iimport.go | 7 ++----- src/cmd/compile/internal/noder/reader2.go | 4 +--- src/cmd/compile/internal/noder/writer.go | 2 +- src/cmd/compile/internal/typecheck/iexport.go | 6 +++--- src/cmd/compile/internal/typecheck/iimport.go | 2 +- 5 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index 3aab32fc6b..6dd8d595ae 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -676,12 +676,9 @@ func (r *importReader) doType(base *types2.Named) types2.Type { if r.p.exportVersion < iexportVersionGenerics { errorf("unexpected instantiation type") } - nt := int(r.uint64()) - terms := make([]*types2.Term, nt) + terms := make([]*types2.Term, r.uint64()) for i := range terms { - typ := r.typ() - tilde := r.bool() - terms[i] = types2.NewTerm(tilde, typ) + terms[i] = types2.NewTerm(r.bool(), r.typ()) } return types2.NewUnion(terms) } diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index 0bea6675ea..fe1f329c82 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -283,9 +283,7 @@ func (r *reader2) structType() *types2.Struct { func (r *reader2) unionType() *types2.Union { terms := make([]*types2.Term, r.len()) for i := range terms { - typ := r.typ() - tilde := r.bool() - terms[i] = types2.NewTerm(tilde, typ) + terms[i] = types2.NewTerm(r.bool(), r.typ()) } return types2.NewUnion(terms) } diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 8b65559d1a..b5028e7f69 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -397,8 +397,8 @@ func (w *writer) unionType(typ *types2.Union) { w.len(typ.Len()) for i := 0; i < typ.Len(); i++ { t := typ.Term(i) - w.typ(t.Type()) w.bool(t.Tilde()) + w.typ(t.Type()) } } diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 25a0bfbb3a..d877b03e48 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -1002,9 +1002,9 @@ func (w *exportWriter) doTyp(t *types.Type) { nt := t.NumTerms() w.uint64(uint64(nt)) for i := 0; i < nt; i++ { - t, b := t.Term(i) - w.typ(t) - w.bool(b) + typ, tilde := t.Term(i) + w.bool(tilde) + w.typ(typ) } default: diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 8d960e5808..2957212fb2 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -847,8 +847,8 @@ func (r *importReader) typ1() *types.Type { terms := make([]*types.Type, nt) tildes := make([]bool, nt) for i := range terms { - terms[i] = r.typ() tildes[i] = r.bool() + terms[i] = r.typ() } return types.NewUnion(terms, tildes) } -- GitLab From 9bd1817e417e9f07c6b3aba0189576bbf06f1592 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 5 Aug 2021 18:14:28 -0700 Subject: [PATCH 0629/2500] [dev.typeparams] cmd/compile/internal/types2: limit termlist lengths At the moment, operations on termlists are O(n^2). This is fine for normal-sized unions, but overlong termlist lenghts will lead to excessive type checking times. Limit the length of termlists to avoid "compilations that don't finish". Change-Id: I39a7fc61b01c9db06faeb49a0e014b1ede532710 Reviewed-on: https://go-review.googlesource.com/c/go/+/340254 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/interface.go | 2 +- .../internal/types2/testdata/check/unions.go2 | 66 +++++++++++++++++++ src/cmd/compile/internal/types2/typeset.go | 27 +++++++- .../compile/internal/types2/typeset_test.go | 15 +++++ src/cmd/compile/internal/types2/union.go | 12 +++- 5 files changed, 117 insertions(+), 5 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/check/unions.go2 create mode 100644 src/cmd/compile/internal/types2/typeset_test.go diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index f763f8ff44..89cf846598 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -140,7 +140,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType for _, f := range iface.MethodList { if f.Name == nil { // We have an embedded type; possibly a union of types. - addEmbedded(f.Type.Pos(), parseUnion(check, flattenUnion(nil, f.Type))) + addEmbedded(posFor(f.Type), parseUnion(check, flattenUnion(nil, f.Type))) continue } // f.Name != nil diff --git a/src/cmd/compile/internal/types2/testdata/check/unions.go2 b/src/cmd/compile/internal/types2/testdata/check/unions.go2 new file mode 100644 index 0000000000..bcd7de6644 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/check/unions.go2 @@ -0,0 +1,66 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Check that overlong unions don't bog down type checking. +// Disallow them for now. + +package p + +type t int + +type ( + t00 t; t01 t; t02 t; t03 t; t04 t; t05 t; t06 t; t07 t; t08 t; t09 t + t10 t; t11 t; t12 t; t13 t; t14 t; t15 t; t16 t; t17 t; t18 t; t19 t + t20 t; t21 t; t22 t; t23 t; t24 t; t25 t; t26 t; t27 t; t28 t; t29 t + t30 t; t31 t; t32 t; t33 t; t34 t; t35 t; t36 t; t37 t; t38 t; t39 t + t40 t; t41 t; t42 t; t43 t; t44 t; t45 t; t46 t; t47 t; t48 t; t49 t + t50 t; t51 t; t52 t; t53 t; t54 t; t55 t; t56 t; t57 t; t58 t; t59 t + t60 t; t61 t; t62 t; t63 t; t64 t; t65 t; t66 t; t67 t; t68 t; t69 t + t70 t; t71 t; t72 t; t73 t; t74 t; t75 t; t76 t; t77 t; t78 t; t79 t + t80 t; t81 t; t82 t; t83 t; t84 t; t85 t; t86 t; t87 t; t88 t; t89 t + t90 t; t91 t; t92 t; t93 t; t94 t; t95 t; t96 t; t97 t; t98 t; t99 t +) + +type u99 interface { + t00|t01|t02|t03|t04|t05|t06|t07|t08|t09| + t10|t11|t12|t13|t14|t15|t16|t17|t18|t19| + t20|t21|t22|t23|t24|t25|t26|t27|t28|t29| + t30|t31|t32|t33|t34|t35|t36|t37|t38|t39| + t40|t41|t42|t43|t44|t45|t46|t47|t48|t49| + t50|t51|t52|t53|t54|t55|t56|t57|t58|t59| + t60|t61|t62|t63|t64|t65|t66|t67|t68|t69| + t70|t71|t72|t73|t74|t75|t76|t77|t78|t79| + t80|t81|t82|t83|t84|t85|t86|t87|t88|t89| + t90|t91|t92|t93|t94|t95|t96|t97|t98 +} + +type u100a interface { + u99|float32 +} + +type u100b interface { + u99|float64 +} + +type u101 interface { + t00|t01|t02|t03|t04|t05|t06|t07|t08|t09| + t10|t11|t12|t13|t14|t15|t16|t17|t18|t19| + t20|t21|t22|t23|t24|t25|t26|t27|t28|t29| + t30|t31|t32|t33|t34|t35|t36|t37|t38|t39| + t40|t41|t42|t43|t44|t45|t46|t47|t48|t49| + t50|t51|t52|t53|t54|t55|t56|t57|t58|t59| + t60|t61|t62|t63|t64|t65|t66|t67|t68|t69| + t70|t71|t72|t73|t74|t75|t76|t77|t78|t79| + t80|t81|t82|t83|t84|t85|t86|t87|t88|t89| + t90|t91|t92|t93|t94|t95|t96|t97|t98|t99| + int // ERROR cannot handle more than 100 union terms +} + +type u102 interface { + int /* ERROR cannot handle more than 100 union terms */ |string|u100a +} + +type u200 interface { + u100a /* ERROR cannot handle more than 100 union terms */ |u100b +} diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index da364699ce..5955bbe805 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -268,9 +268,9 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *T pos = (*ityp.embedPos)[i] } var terms termlist - switch t := under(typ).(type) { + switch u := under(typ).(type) { case *Interface: - tset := computeInterfaceTypeSet(check, pos, t) + tset := computeInterfaceTypeSet(check, pos, u) if tset.comparable { ityp.tset.comparable = true } @@ -279,7 +279,10 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *T } terms = tset.terms case *Union: - tset := computeUnionTypeSet(check, pos, t) + tset := computeUnionTypeSet(check, pos, u) + if tset == &invalidTypeSet { + continue // ignore invalid unions + } terms = tset.terms case *TypeParam: // Embedding stand-alone type parameters is not permitted. @@ -297,6 +300,8 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *T } // The type set of an interface is the intersection // of the type sets of all its elements. + // Intersection cannot produce longer termlists and + // thus cannot overflow. allTerms = allTerms.intersect(terms) } ityp.embedPos = nil // not needed anymore (errors have been reported) @@ -339,7 +344,13 @@ func (a byUniqueMethodName) Len() int { return len(a) } func (a byUniqueMethodName) Less(i, j int) bool { return a[i].less(&a[j].object) } func (a byUniqueMethodName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +// invalidTypeSet is a singleton type set to signal an invalid type set +// due to an error. It's also a valid empty type set, so consumers of +// type sets may choose to ignore it. +var invalidTypeSet TypeSet + // computeUnionTypeSet may be called with check == nil. +// The result is &invalidTypeSet if the union overflows. func computeUnionTypeSet(check *Checker, pos syntax.Pos, utyp *Union) *TypeSet { if utyp.tset != nil { return utyp.tset @@ -359,11 +370,21 @@ func computeUnionTypeSet(check *Checker, pos syntax.Pos, utyp *Union) *TypeSet { // This case is handled during union parsing. unreachable() default: + if t.typ == Typ[Invalid] { + continue + } terms = termlist{(*term)(t)} } // The type set of a union expression is the union // of the type sets of each term. allTerms = allTerms.union(terms) + if len(allTerms) > maxTermCount { + if check != nil { + check.errorf(pos, "cannot handle more than %d union terms (implementation limitation)", maxTermCount) + } + utyp.tset = &invalidTypeSet + return utyp.tset + } } utyp.tset.terms = allTerms diff --git a/src/cmd/compile/internal/types2/typeset_test.go b/src/cmd/compile/internal/types2/typeset_test.go new file mode 100644 index 0000000000..0e14d523c8 --- /dev/null +++ b/src/cmd/compile/internal/types2/typeset_test.go @@ -0,0 +1,15 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types2 + +import "testing" + +func TestInvalidTypeSet(t *testing.T) { + if !invalidTypeSet.IsEmpty() { + t.Error("invalidTypeSet is not empty") + } +} + +// TODO(gri) add more tests diff --git a/src/cmd/compile/internal/types2/union.go b/src/cmd/compile/internal/types2/union.go index 102826947c..85aa3d9104 100644 --- a/src/cmd/compile/internal/types2/union.go +++ b/src/cmd/compile/internal/types2/union.go @@ -43,12 +43,22 @@ func (t *Term) String() string { return (*term)(t).String() } // ---------------------------------------------------------------------------- // Implementation +// Avoid excessive type-checking times due to quadratic termlist operations. +const maxTermCount = 100 + +// parseUnion parses the given list of type expressions tlist as a union of +// those expressions. The result is a Union type, or Typ[Invalid] for some +// errors. func parseUnion(check *Checker, tlist []syntax.Expr) Type { var terms []*Term for _, x := range tlist { tilde, typ := parseTilde(check, x) if len(tlist) == 1 && !tilde { - return typ // single type + return typ // single type (optimization) + } + if len(terms) >= maxTermCount { + check.errorf(x, "cannot handle more than %d union terms (implementation limitation)", maxTermCount) + return Typ[Invalid] } terms = append(terms, NewTerm(tilde, typ)) } -- GitLab From 9e0ac72d680e71d22c7d31950a16d4f92f08305a Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 5 Aug 2021 18:33:22 -0700 Subject: [PATCH 0630/2500] [dev.typeparams] cmd/compile/internal/types2: remove Interface.Complete (cleanup) Interface.Complete is not needed anymore. We can remove it in types2 (and eventually make it an empty function in go/types, where we must maintain the existing API). Change-Id: I689f0d6f3a83997d8ca5bae773b9af0083d0bf4f Reviewed-on: https://go-review.googlesource.com/c/go/+/340255 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/importer/iimport.go | 4 ---- src/cmd/compile/internal/noder/reader2.go | 4 +--- src/cmd/compile/internal/types2/interface.go | 19 ------------------- .../compile/internal/types2/issues_test.go | 3 ++- 4 files changed, 3 insertions(+), 27 deletions(-) diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index 6dd8d595ae..523b00313d 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -183,10 +183,6 @@ func ImportData(imports map[string]*types2.Package, data, path string) (pkg *typ p.doDecl(localpkg, name) } - for _, typ := range p.interfaceList { - typ.Complete() - } - // record all referenced packages as imports list := append(([]*types2.Package)(nil), pkgList[1:]...) sort.Sort(byPath(list)) diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index fe1f329c82..5637196dc0 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -303,9 +303,7 @@ func (r *reader2) interfaceType() *types2.Interface { embeddeds[i] = r.typ() } - typ := types2.NewInterfaceType(methods, embeddeds) - typ.Complete() - return typ + return types2.NewInterfaceType(methods, embeddeds) } func (r *reader2) signature(recv *types2.Var) *types2.Signature { diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index 89cf846598..2617f748de 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -100,25 +100,6 @@ func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() } // IsConstraint reports whether interface t is not just a method set. func (t *Interface) IsConstraint() bool { return !t.typeSet().IsMethodSet() } -// Complete computes the interface's type set. It must be called by users of -// NewInterfaceType and NewInterface after the interface's embedded types are -// fully defined and before using the interface type in any way other than to -// form other types. The interface must not contain duplicate methods or a -// panic occurs. Complete returns the receiver. -// -// Deprecated: Type sets are now computed lazily, on demand; this function -// is only here for backward-compatibility. It does not have to -// be called explicitly anymore. -func (t *Interface) Complete() *Interface { - // Some tests are still depending on the state change - // (string representation of an Interface not containing an - // /* incomplete */ marker) caused by the explicit Complete - // call, so we compute the type set eagerly here. - t.complete = true - t.typeSet() - return t -} - func (t *Interface) Underlying() Type { return t } func (t *Interface) String() string { return TypeString(t, nil) } diff --git a/src/cmd/compile/internal/types2/issues_test.go b/src/cmd/compile/internal/types2/issues_test.go index aafe8de367..9890b79323 100644 --- a/src/cmd/compile/internal/types2/issues_test.go +++ b/src/cmd/compile/internal/types2/issues_test.go @@ -402,8 +402,9 @@ func TestIssue28282(t *testing.T) { // create type interface { error } et := Universe.Lookup("error").Type() it := NewInterfaceType(nil, []Type{et}) - it.Complete() // verify that after completing the interface, the embedded method remains unchanged + // (interfaces are "completed" lazily now, so the completion happens implicitly when + // accessing Method(0)) want := et.Underlying().(*Interface).Method(0) got := it.Method(0) if got != want { -- GitLab From fc8e0cbbbaa5ae7c1e5b7b070ad80f41095ef18b Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Mon, 26 Jul 2021 10:39:38 -0700 Subject: [PATCH 0631/2500] [dev.cmdgo] cmd: update x/tools and remove copy of txtar golang.org/x/tools/txtar is the main location for this package. We don't need our own copy. Also, update cmd/vet tests for compatibility with CL 301949. For golang/go#47193 Change-Id: I480eb591f57a0d05b433a657653e2021e39354eb Reviewed-on: https://go-review.googlesource.com/c/go/+/337352 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 +- src/cmd/go/internal/fsys/fsys_test.go | 3 +- src/cmd/go/internal/txtar/archive_test.go | 67 ----------- src/cmd/go/proxy_test.go | 2 +- src/cmd/go/script_test.go | 3 +- src/cmd/go/testdata/addmod.go | 2 +- src/cmd/go/testdata/savedir.go | 2 +- .../tools/go/analysis/passes/printf/printf.go | 28 +++-- .../x/tools/go/ast/astutil/rewrite.go | 8 +- .../x/tools/internal/typeparams/doc.go | 11 ++ .../tools/internal/typeparams/notypeparams.go | 90 +++++++++++++++ .../x/tools/internal/typeparams/typeparams.go | 105 ++++++++++++++++++ .../golang.org/x/tools}/txtar/archive.go | 6 +- src/cmd/vendor/modules.txt | 4 +- src/cmd/vet/testdata/print/print.go | 8 +- 16 files changed, 249 insertions(+), 96 deletions(-) delete mode 100644 src/cmd/go/internal/txtar/archive_test.go create mode 100644 src/cmd/vendor/golang.org/x/tools/internal/typeparams/doc.go create mode 100644 src/cmd/vendor/golang.org/x/tools/internal/typeparams/notypeparams.go create mode 100644 src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams.go rename src/cmd/{go/internal => vendor/golang.org/x/tools}/txtar/archive.go (96%) diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 21d7d8b75a..b0a3f48045 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -10,6 +10,6 @@ require ( golang.org/x/mod v0.4.3-0.20210723200715-e41a6a4f3b61 golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 // indirect golang.org/x/term v0.0.0-20210503060354-a79de5458b56 - golang.org/x/tools v0.1.2-0.20210519160823-49064d2332f9 + golang.org/x/tools v0.1.6-0.20210726171848-ebce39e5e3d6 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 529b152b77..bf237d40bc 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -36,8 +36,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.2-0.20210519160823-49064d2332f9 h1:2XlR/j4I4xz5GQZI7zBjqTfezYyRIE2jD5IMousB2rg= -golang.org/x/tools v0.1.2-0.20210519160823-49064d2332f9/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.6-0.20210726171848-ebce39e5e3d6 h1:er++nfKy5Irv8JPDfJ68QzoVKQ6MBF7cf5xC15O4Zy0= +golang.org/x/tools v0.1.6-0.20210726171848-ebce39e5e3d6/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= diff --git a/src/cmd/go/internal/fsys/fsys_test.go b/src/cmd/go/internal/fsys/fsys_test.go index 7f175c7031..c080c14987 100644 --- a/src/cmd/go/internal/fsys/fsys_test.go +++ b/src/cmd/go/internal/fsys/fsys_test.go @@ -1,7 +1,6 @@ package fsys import ( - "cmd/go/internal/txtar" "encoding/json" "errors" "fmt" @@ -12,6 +11,8 @@ import ( "path/filepath" "reflect" "testing" + + "golang.org/x/tools/txtar" ) // initOverlay resets the overlay state to reflect the config. diff --git a/src/cmd/go/internal/txtar/archive_test.go b/src/cmd/go/internal/txtar/archive_test.go deleted file mode 100644 index 3f734f6762..0000000000 --- a/src/cmd/go/internal/txtar/archive_test.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package txtar - -import ( - "bytes" - "fmt" - "reflect" - "testing" -) - -var tests = []struct { - name string - text string - parsed *Archive -}{ - { - name: "basic", - text: `comment1 -comment2 --- file1 -- -File 1 text. --- foo --- -More file 1 text. --- file 2 -- -File 2 text. --- empty -- --- noNL -- -hello world`, - parsed: &Archive{ - Comment: []byte("comment1\ncomment2\n"), - Files: []File{ - {"file1", []byte("File 1 text.\n-- foo ---\nMore file 1 text.\n")}, - {"file 2", []byte("File 2 text.\n")}, - {"empty", []byte{}}, - {"noNL", []byte("hello world\n")}, - }, - }, - }, -} - -func Test(t *testing.T) { - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - a := Parse([]byte(tt.text)) - if !reflect.DeepEqual(a, tt.parsed) { - t.Fatalf("Parse: wrong output:\nhave:\n%s\nwant:\n%s", shortArchive(a), shortArchive(tt.parsed)) - } - text := Format(a) - a = Parse(text) - if !reflect.DeepEqual(a, tt.parsed) { - t.Fatalf("Parse after Format: wrong output:\nhave:\n%s\nwant:\n%s", shortArchive(a), shortArchive(tt.parsed)) - } - }) - } -} - -func shortArchive(a *Archive) string { - var buf bytes.Buffer - fmt.Fprintf(&buf, "comment: %q\n", a.Comment) - for _, f := range a.Files { - fmt.Fprintf(&buf, "file %q: %q\n", f.Name, f.Data) - } - return buf.String() -} diff --git a/src/cmd/go/proxy_test.go b/src/cmd/go/proxy_test.go index 74bfecc08d..a387fe67db 100644 --- a/src/cmd/go/proxy_test.go +++ b/src/cmd/go/proxy_test.go @@ -25,12 +25,12 @@ import ( "cmd/go/internal/modfetch/codehost" "cmd/go/internal/par" - "cmd/go/internal/txtar" "golang.org/x/mod/module" "golang.org/x/mod/semver" "golang.org/x/mod/sumdb" "golang.org/x/mod/sumdb/dirhash" + "golang.org/x/tools/txtar" ) var ( diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go index 8a7c77a46f..3c5855bd6f 100644 --- a/src/cmd/go/script_test.go +++ b/src/cmd/go/script_test.go @@ -31,9 +31,10 @@ import ( "cmd/go/internal/imports" "cmd/go/internal/par" "cmd/go/internal/robustio" - "cmd/go/internal/txtar" "cmd/go/internal/work" "cmd/internal/sys" + + "golang.org/x/tools/txtar" ) var testSum = flag.String("testsum", "", `may be tidy, listm, or listall. If set, TestScript generates a go.sum file at the beginning of each test and updates test files if they pass.`) diff --git a/src/cmd/go/testdata/addmod.go b/src/cmd/go/testdata/addmod.go index 03869e68de..a1ace4ce59 100644 --- a/src/cmd/go/testdata/addmod.go +++ b/src/cmd/go/testdata/addmod.go @@ -29,7 +29,7 @@ import ( "path/filepath" "strings" - "cmd/go/internal/txtar" + "golang.org/x/tools/txtar" ) func usage() { diff --git a/src/cmd/go/testdata/savedir.go b/src/cmd/go/testdata/savedir.go index d469c31a91..6a8a232702 100644 --- a/src/cmd/go/testdata/savedir.go +++ b/src/cmd/go/testdata/savedir.go @@ -24,7 +24,7 @@ import ( "strings" "unicode/utf8" - "../internal/txtar" + "golang.org/x/tools/txtar" ) func usage() { diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go index 822820f06e..6589478af0 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go @@ -555,7 +555,7 @@ func checkPrintf(pass *analysis.Pass, kind Kind, call *ast.CallExpr, fn *types.F format, idx := formatString(pass, call) if idx < 0 { if false { - pass.Reportf(call.Lparen, "can't check non-constant format in call to %s", fn.Name()) + pass.Reportf(call.Lparen, "can't check non-constant format in call to %s", fn.FullName()) } return } @@ -563,7 +563,7 @@ func checkPrintf(pass *analysis.Pass, kind Kind, call *ast.CallExpr, fn *types.F firstArg := idx + 1 // Arguments are immediately after format string. if !strings.Contains(format, "%") { if len(call.Args) > firstArg { - pass.Reportf(call.Lparen, "%s call has arguments but no formatting directives", fn.Name()) + pass.Reportf(call.Lparen, "%s call has arguments but no formatting directives", fn.FullName()) } return } @@ -577,7 +577,7 @@ func checkPrintf(pass *analysis.Pass, kind Kind, call *ast.CallExpr, fn *types.F if format[i] != '%' { continue } - state := parsePrintfVerb(pass, call, fn.Name(), format[i:], firstArg, argNum) + state := parsePrintfVerb(pass, call, fn.FullName(), format[i:], firstArg, argNum) if state == nil { return } @@ -589,8 +589,12 @@ func checkPrintf(pass *analysis.Pass, kind Kind, call *ast.CallExpr, fn *types.F anyIndex = true } if state.verb == 'w' { - if kind != KindErrorf { - pass.Reportf(call.Pos(), "%s call has error-wrapping directive %%w, which is only supported by Errorf", state.name) + switch kind { + case KindNone, KindPrint: + pass.Reportf(call.Pos(), "%s does not support error-wrapping directive %%w", state.name) + return + case KindPrintf: + pass.Reportf(call.Pos(), "%s call has error-wrapping directive %%w, which is only supported for functions backed by fmt.Errorf", state.name) return } if anyW { @@ -621,7 +625,7 @@ func checkPrintf(pass *analysis.Pass, kind Kind, call *ast.CallExpr, fn *types.F if maxArgNum != len(call.Args) { expect := maxArgNum - firstArg numArgs := len(call.Args) - firstArg - pass.ReportRangef(call, "%s call needs %v but has %v", fn.Name(), count(expect, "arg"), count(numArgs, "arg")) + pass.ReportRangef(call, "%s call needs %v but has %v", fn.FullName(), count(expect, "arg"), count(numArgs, "arg")) } } @@ -949,7 +953,7 @@ func recursiveStringer(pass *analysis.Pass, e ast.Expr) (string, bool) { } if id, ok := e.(*ast.Ident); ok { if pass.TypesInfo.Uses[id] == sig.Recv() { - return method.Name(), true + return method.FullName(), true } } return "", false @@ -1044,7 +1048,7 @@ func checkPrint(pass *analysis.Pass, call *ast.CallExpr, fn *types.Func) { if sel, ok := call.Args[0].(*ast.SelectorExpr); ok { if x, ok := sel.X.(*ast.Ident); ok { if x.Name == "os" && strings.HasPrefix(sel.Sel.Name, "Std") { - pass.ReportRangef(call, "%s does not take io.Writer but has first arg %s", fn.Name(), analysisutil.Format(pass.Fset, call.Args[0])) + pass.ReportRangef(call, "%s does not take io.Writer but has first arg %s", fn.FullName(), analysisutil.Format(pass.Fset, call.Args[0])) } } } @@ -1058,7 +1062,7 @@ func checkPrint(pass *analysis.Pass, call *ast.CallExpr, fn *types.Func) { if strings.Contains(s, "%") { m := printFormatRE.FindStringSubmatch(s) if m != nil { - pass.ReportRangef(call, "%s call has possible formatting directive %s", fn.Name(), m[0]) + pass.ReportRangef(call, "%s call has possible formatting directive %s", fn.FullName(), m[0]) } } } @@ -1068,16 +1072,16 @@ func checkPrint(pass *analysis.Pass, call *ast.CallExpr, fn *types.Func) { if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { str, _ := strconv.Unquote(lit.Value) if strings.HasSuffix(str, "\n") { - pass.ReportRangef(call, "%s arg list ends with redundant newline", fn.Name()) + pass.ReportRangef(call, "%s arg list ends with redundant newline", fn.FullName()) } } } for _, arg := range args { if isFunctionValue(pass, arg) { - pass.ReportRangef(call, "%s arg %s is a func value, not called", fn.Name(), analysisutil.Format(pass.Fset, arg)) + pass.ReportRangef(call, "%s arg %s is a func value, not called", fn.FullName(), analysisutil.Format(pass.Fset, arg)) } if methodName, ok := recursiveStringer(pass, arg); ok { - pass.ReportRangef(call, "%s arg %s causes recursive call to %s method", fn.Name(), analysisutil.Format(pass.Fset, arg), methodName) + pass.ReportRangef(call, "%s arg %s causes recursive call to %s method", fn.FullName(), analysisutil.Format(pass.Fset, arg), methodName) } } } diff --git a/src/cmd/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go b/src/cmd/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go index cf72ea990b..b949fc8407 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go +++ b/src/cmd/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go @@ -9,6 +9,8 @@ import ( "go/ast" "reflect" "sort" + + "golang.org/x/tools/internal/typeparams" ) // An ApplyFunc is invoked by Apply for each node n, even if n is nil, @@ -437,7 +439,11 @@ func (a *application) apply(parent ast.Node, name string, iter *iterator, n ast. } default: - panic(fmt.Sprintf("Apply: unexpected node type %T", n)) + if typeparams.IsListExpr(n) { + a.applyList(n, "ElemList") + } else { + panic(fmt.Sprintf("Apply: unexpected node type %T", n)) + } } if a.post != nil && !a.post(&a.cursor) { diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/doc.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/doc.go new file mode 100644 index 0000000000..5583947e21 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/doc.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package typeparams provides functions to work indirectly with type parameter +// data stored in go/ast and go/types objects, while these API are guarded by a +// build constraint. +// +// This package exists to make it easier for tools to work with generic code, +// while also compiling against older Go versions. +package typeparams diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/notypeparams.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/notypeparams.go new file mode 100644 index 0000000000..3a0abc7c18 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/notypeparams.go @@ -0,0 +1,90 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !typeparams || !go1.17 +// +build !typeparams !go1.17 + +package typeparams + +import ( + "go/ast" + "go/types" +) + +// NOTE: doc comments must be kept in sync with typeparams.go. + +// Enabled reports whether type parameters are enabled in the current build +// environment. +const Enabled = false + +// UnpackIndex extracts all index expressions from e. For non-generic code this +// is always one expression: e.Index, but may be more than one expression for +// generic type instantiation. +func UnpackIndex(e *ast.IndexExpr) []ast.Expr { + return []ast.Expr{e.Index} +} + +// IsListExpr reports whether n is an *ast.ListExpr, which is a new node type +// introduced to hold type arguments for generic type instantiation. +func IsListExpr(n ast.Node) bool { + return false +} + +// ForTypeDecl extracts the (possibly nil) type parameter node list from n. +func ForTypeDecl(*ast.TypeSpec) *ast.FieldList { + return nil +} + +// ForFuncDecl extracts the (possibly nil) type parameter node list from n. +func ForFuncDecl(*ast.FuncDecl) *ast.FieldList { + return nil +} + +// ForSignature extracts the (possibly empty) type parameter object list from +// sig. +func ForSignature(*types.Signature) []*types.TypeName { + return nil +} + +// HasTypeSet reports if iface has a type set. +func HasTypeSet(*types.Interface) bool { + return false +} + +// IsComparable reports if iface is the comparable interface. +func IsComparable(*types.Interface) bool { + return false +} + +// IsConstraint reports whether iface may only be used as a type parameter +// constraint (i.e. has a type set or is the comparable interface). +func IsConstraint(*types.Interface) bool { + return false +} + +// ForNamed extracts the (possibly empty) type parameter object list from +// named. +func ForNamed(*types.Named) []*types.TypeName { + return nil +} + +// NamedTArgs extracts the (possibly empty) type argument list from named. +func NamedTArgs(*types.Named) []types.Type { + return nil +} + +// InitInferred initializes info to record inferred type information. +func InitInferred(*types.Info) { +} + +// GetInferred extracts inferred type information from info for e. +// +// The expression e may have an inferred type if it is an *ast.IndexExpr +// representing partial instantiation of a generic function type for which type +// arguments have been inferred using constraint type inference, or if it is an +// *ast.CallExpr for which type type arguments have be inferred using both +// constraint type inference and function argument inference. +func GetInferred(*types.Info, ast.Expr) ([]types.Type, *types.Signature) { + return nil, nil +} diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams.go new file mode 100644 index 0000000000..6b7958af06 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams.go @@ -0,0 +1,105 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build typeparams && go1.17 +// +build typeparams,go1.17 + +package typeparams + +import ( + "go/ast" + "go/types" +) + +// NOTE: doc comments must be kept in sync with notypeparams.go. + +// Enabled reports whether type parameters are enabled in the current build +// environment. +const Enabled = true + +// UnpackIndex extracts all index expressions from e. For non-generic code this +// is always one expression: e.Index, but may be more than one expression for +// generic type instantiation. +func UnpackIndex(e *ast.IndexExpr) []ast.Expr { + if x, _ := e.Index.(*ast.ListExpr); x != nil { + return x.ElemList + } + if e.Index != nil { + return []ast.Expr{e.Index} + } + return nil +} + +// IsListExpr reports whether n is an *ast.ListExpr, which is a new node type +// introduced to hold type arguments for generic type instantiation. +func IsListExpr(n ast.Node) bool { + _, ok := n.(*ast.ListExpr) + return ok +} + +// ForTypeDecl extracts the (possibly nil) type parameter node list from n. +func ForTypeDecl(n *ast.TypeSpec) *ast.FieldList { + return n.TParams +} + +// ForFuncDecl extracts the (possibly nil) type parameter node list from n. +func ForFuncDecl(n *ast.FuncDecl) *ast.FieldList { + if n.Type != nil { + return n.Type.TParams + } + return nil +} + +// ForSignature extracts the (possibly empty) type parameter object list from +// sig. +func ForSignature(sig *types.Signature) []*types.TypeName { + return sig.TParams() +} + +// HasTypeSet reports if iface has a type set. +func HasTypeSet(iface *types.Interface) bool { + return iface.HasTypeList() +} + +// IsComparable reports if iface is the comparable interface. +func IsComparable(iface *types.Interface) bool { + return iface.IsComparable() +} + +// IsConstraint reports whether iface may only be used as a type parameter +// constraint (i.e. has a type set or is the comparable interface). +func IsConstraint(iface *types.Interface) bool { + return iface.IsConstraint() +} + +// ForNamed extracts the (possibly empty) type parameter object list from +// named. +func ForNamed(named *types.Named) []*types.TypeName { + return named.TParams() +} + +// NamedTArgs extracts the (possibly empty) type argument list from named. +func NamedTArgs(named *types.Named) []types.Type { + return named.TArgs() +} + +// InitInferred initializes info to record inferred type information. +func InitInferred(info *types.Info) { + info.Inferred = make(map[ast.Expr]types.Inferred) +} + +// GetInferred extracts inferred type information from info for e. +// +// The expression e may have an inferred type if it is an *ast.IndexExpr +// representing partial instantiation of a generic function type for which type +// arguments have been inferred using constraint type inference, or if it is an +// *ast.CallExpr for which type type arguments have be inferred using both +// constraint type inference and function argument inference. +func GetInferred(info *types.Info, e ast.Expr) ([]types.Type, *types.Signature) { + if info.Inferred == nil { + return nil, nil + } + inf := info.Inferred[e] + return inf.TArgs, inf.Sig +} diff --git a/src/cmd/go/internal/txtar/archive.go b/src/cmd/vendor/golang.org/x/tools/txtar/archive.go similarity index 96% rename from src/cmd/go/internal/txtar/archive.go rename to src/cmd/vendor/golang.org/x/tools/txtar/archive.go index 1796684877..214256617b 100644 --- a/src/cmd/go/internal/txtar/archive.go +++ b/src/cmd/vendor/golang.org/x/tools/txtar/archive.go @@ -34,7 +34,7 @@ package txtar import ( "bytes" "fmt" - "os" + "io/ioutil" "strings" ) @@ -66,7 +66,7 @@ func Format(a *Archive) []byte { // ParseFile parses the named file as an archive. func ParseFile(file string) (*Archive, error) { - data, err := os.ReadFile(file) + data, err := ioutil.ReadFile(file) if err != nil { return nil, err } @@ -121,7 +121,7 @@ func isMarker(data []byte) (name string, after []byte) { if i := bytes.IndexByte(data, '\n'); i >= 0 { data, after = data[:i], data[i+1:] } - if !bytes.HasSuffix(data, markerEnd) { + if !(bytes.HasSuffix(data, markerEnd) && len(data) >= len(marker)+len(markerEnd)) { return "", nil } return strings.TrimSpace(string(data[len(marker) : len(data)-len(markerEnd)])), after diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index beceef5392..e032ccc2c7 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -48,7 +48,7 @@ golang.org/x/sys/windows # golang.org/x/term v0.0.0-20210503060354-a79de5458b56 ## explicit; go 1.17 golang.org/x/term -# golang.org/x/tools v0.1.2-0.20210519160823-49064d2332f9 +# golang.org/x/tools v0.1.6-0.20210726171848-ebce39e5e3d6 ## explicit; go 1.17 golang.org/x/tools/cover golang.org/x/tools/go/analysis @@ -92,6 +92,8 @@ golang.org/x/tools/go/types/objectpath golang.org/x/tools/go/types/typeutil golang.org/x/tools/internal/analysisinternal golang.org/x/tools/internal/lsp/fuzzy +golang.org/x/tools/internal/typeparams +golang.org/x/tools/txtar # golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 ## explicit; go 1.11 golang.org/x/xerrors diff --git a/src/cmd/vet/testdata/print/print.go b/src/cmd/vet/testdata/print/print.go index fca594925f..be42a37717 100644 --- a/src/cmd/vet/testdata/print/print.go +++ b/src/cmd/vet/testdata/print/print.go @@ -491,10 +491,10 @@ type recursiveStringer int func (s recursiveStringer) String() string { _ = fmt.Sprintf("%d", s) _ = fmt.Sprintf("%#v", s) - _ = fmt.Sprintf("%v", s) // ERROR "Sprintf format %v with arg s causes recursive String method call" - _ = fmt.Sprintf("%v", &s) // ERROR "Sprintf format %v with arg &s causes recursive String method call" + _ = fmt.Sprintf("%v", s) // ERROR "Sprintf format %v with arg s causes recursive \(cmd/vet/testdata/print\.recursiveStringer\)\.String method call" + _ = fmt.Sprintf("%v", &s) // ERROR "Sprintf format %v with arg &s causes recursive \(cmd/vet/testdata/print\.recursiveStringer\)\.String method call" _ = fmt.Sprintf("%T", s) // ok; does not recursively call String - return fmt.Sprintln(s) // ERROR "Sprintln arg s causes recursive call to String method" + return fmt.Sprintln(s) // ERROR "Sprintln arg s causes recursive call to \(cmd/vet/testdata/print\.recursiveStringer\)\.String method" } type recursivePtrStringer int @@ -502,7 +502,7 @@ type recursivePtrStringer int func (p *recursivePtrStringer) String() string { _ = fmt.Sprintf("%v", *p) _ = fmt.Sprint(&p) // ok; prints address - return fmt.Sprintln(p) // ERROR "Sprintln arg p causes recursive call to String method" + return fmt.Sprintln(p) // ERROR "Sprintln arg p causes recursive call to \(\*cmd/vet/testdata/print\.recursivePtrStringer\)\.String method" } type BoolFormatter bool -- GitLab From 3025ce2fa83c86f3c802aab483535c39bad508ea Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 3 Aug 2021 14:51:46 -0700 Subject: [PATCH 0632/2500] [dev.cmdgo] cmd/go: address code review comments in test cgo_path_space_quote For CL 334732. Change-Id: I5cb88cd7d5e4edf6006bbaeb17723dac2cdf0fd5 Reviewed-on: https://go-review.googlesource.com/c/go/+/339590 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/testdata/script/cgo_path_space_quote.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cmd/go/testdata/script/cgo_path_space_quote.txt b/src/cmd/go/testdata/script/cgo_path_space_quote.txt index 3b89bfb800..9556101300 100644 --- a/src/cmd/go/testdata/script/cgo_path_space_quote.txt +++ b/src/cmd/go/testdata/script/cgo_path_space_quote.txt @@ -6,6 +6,7 @@ [short] skip [!exec:clang] [!exec:gcc] skip +[!cgo] skip env GOENV=$WORK/go.env mkdir 'program files' @@ -20,6 +21,7 @@ go env CC stdout 'program files[/\\]which cc" (clang|gcc)$' go run . +stdout 1 -- go.mod -- module test -- GitLab From d10a90471275bf2d91c4c853d7d1f75f23a70a32 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Fri, 6 Aug 2021 16:29:09 -0700 Subject: [PATCH 0633/2500] [dev.typeparams] cmd/compile: don't export/import type parameter indices anymore types2 now determines type parameter indices lazily, so we don't need them just as we are importing. We set them in types1 as we are importing the type param list itself. type param indices are not strongly needed in types1 - we only use them in one place which could be rewritten. But I kept them in analogy to types2 (TypeParam.Index). Fixes #47451 Change-Id: I30631f95c45a259354eaf7ec5194f71e799eb358 Reviewed-on: https://go-review.googlesource.com/c/go/+/340532 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Robert Griesemer Trust: Dan Scales --- src/cmd/compile/internal/importer/iimport.go | 4 ---- src/cmd/compile/internal/typecheck/iexport.go | 1 - src/cmd/compile/internal/typecheck/iimport.go | 9 +++++++-- src/cmd/compile/internal/types/type.go | 6 ++++++ 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index 523b00313d..99eb964415 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -364,10 +364,6 @@ func (r *importReader) obj(name string) { if r.p.exportVersion < iexportVersionGenerics { errorf("unexpected type param type") } - // Type parameter indices are lazily "allocated". - // There's no need to export them anymore. - // TODO change the export format accordingly - _ = int(r.int64()) name0, sub := parseSubscript(name) tn := types2.NewTypeName(pos, r.currPkg, name0, nil) t := (*types2.Checker)(nil).NewTypeParam(tn, nil) diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index d877b03e48..2944908bcb 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -531,7 +531,6 @@ func (p *iexporter) doDecl(n *ir.Name) { // A typeparam has a name, and has a type bound rather // than an underlying type. w.pos(n.Pos()) - w.int64(int64(n.Type().Index())) w.typ(n.Type().Bound()) break } diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 2957212fb2..2e8b18c0b7 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -388,8 +388,9 @@ func (r *importReader) doDecl(sym *types.Sym) *ir.Name { // this types2-to-types1 translation. return sym.Def.(*ir.Name) } - index := int(r.int64()) - t := types.NewTypeParam(sym, index) + // The typeparam index is set at the point where the containing type + // param list is imported. + t := types.NewTypeParam(sym, 0) // Nname needed to save the pos. nname := ir.NewDeclNameAt(pos, ir.OTYPE, sym) sym.Def = nname @@ -875,6 +876,9 @@ func (r *importReader) typeList() []*types.Type { ts := make([]*types.Type, n) for i := range ts { ts[i] = r.typ() + if ts[i].IsTypeParam() { + ts[i].SetIndex(i) + } } return ts } @@ -887,6 +891,7 @@ func (r *importReader) tparamList() []*types.Field { fs := make([]*types.Field, n) for i := range fs { typ := r.typ() + typ.SetIndex(i) fs[i] = types.NewField(typ.Pos(), typ.Sym(), typ) } return fs diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 1f01498ca1..099080f48f 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -1885,6 +1885,12 @@ func (t *Type) Index() int { return t.Extra.(*Typeparam).index } +// SetIndex sets the index of the type param within its param list. +func (t *Type) SetIndex(i int) { + t.wantEtype(TTYPEPARAM) + t.Extra.(*Typeparam).index = i +} + // SetBound sets the bound of a typeparam. func (t *Type) SetBound(bound *Type) { t.wantEtype(TTYPEPARAM) -- GitLab From 57668b84ff43b15746a25e9653c278d174ea483f Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Wed, 4 Aug 2021 22:18:23 -0700 Subject: [PATCH 0634/2500] [dev.typeparams] cmd/compile: simplify interface conversions Simplify the implementation of interface conversions in the compiler. Don't pass fields that aren't needed (the data word, usually) to the runtime. For generics, we need to put a dynamic type in an interface. The new dataWord function is exactly what we need (the type word will come from a dictionary). Change-Id: Iade5de5c174854b65ad248f35c7893c603f7be3d Reviewed-on: https://go-review.googlesource.com/c/go/+/340029 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/typecheck/builtin.go | 423 +++++++++--------- .../internal/typecheck/builtin/runtime.go | 19 +- src/cmd/compile/internal/walk/convert.go | 296 ++++++------ src/cmd/compile/internal/walk/expr.go | 5 +- src/cmd/compile/internal/walk/order.go | 6 +- src/runtime/iface.go | 91 ++-- test/devirt.go | 3 +- test/fixedbugs/issue20250.go | 2 +- test/live.go | 6 +- test/live_regabi.go | 6 +- 10 files changed, 395 insertions(+), 462 deletions(-) diff --git a/src/cmd/compile/internal/typecheck/builtin.go b/src/cmd/compile/internal/typecheck/builtin.go index 833b17b414..3f177d9173 100644 --- a/src/cmd/compile/internal/typecheck/builtin.go +++ b/src/cmd/compile/internal/typecheck/builtin.go @@ -71,137 +71,135 @@ var runtimeDecls = [...]struct { {"slicecopy", funcTag, 54}, {"decoderune", funcTag, 55}, {"countrunes", funcTag, 56}, - {"convI2I", funcTag, 57}, - {"convT16", funcTag, 59}, - {"convT32", funcTag, 61}, - {"convT64", funcTag, 62}, - {"convTstring", funcTag, 63}, - {"convTslice", funcTag, 66}, - {"convT2E", funcTag, 67}, - {"convT2Enoptr", funcTag, 67}, - {"convT2I", funcTag, 67}, - {"convT2Inoptr", funcTag, 67}, - {"assertE2I", funcTag, 68}, - {"assertE2I2", funcTag, 57}, - {"assertI2I", funcTag, 68}, - {"assertI2I2", funcTag, 57}, - {"panicdottypeE", funcTag, 69}, - {"panicdottypeI", funcTag, 69}, - {"panicnildottype", funcTag, 70}, - {"ifaceeq", funcTag, 72}, - {"efaceeq", funcTag, 72}, - {"fastrand", funcTag, 73}, - {"makemap64", funcTag, 75}, - {"makemap", funcTag, 76}, - {"makemap_small", funcTag, 77}, - {"mapaccess1", funcTag, 78}, - {"mapaccess1_fast32", funcTag, 79}, - {"mapaccess1_fast64", funcTag, 80}, - {"mapaccess1_faststr", funcTag, 81}, - {"mapaccess1_fat", funcTag, 82}, - {"mapaccess2", funcTag, 83}, - {"mapaccess2_fast32", funcTag, 84}, - {"mapaccess2_fast64", funcTag, 85}, - {"mapaccess2_faststr", funcTag, 86}, - {"mapaccess2_fat", funcTag, 87}, - {"mapassign", funcTag, 78}, - {"mapassign_fast32", funcTag, 79}, - {"mapassign_fast32ptr", funcTag, 88}, - {"mapassign_fast64", funcTag, 80}, - {"mapassign_fast64ptr", funcTag, 88}, - {"mapassign_faststr", funcTag, 81}, - {"mapiterinit", funcTag, 89}, - {"mapdelete", funcTag, 89}, - {"mapdelete_fast32", funcTag, 90}, - {"mapdelete_fast64", funcTag, 91}, - {"mapdelete_faststr", funcTag, 92}, - {"mapiternext", funcTag, 93}, - {"mapclear", funcTag, 94}, - {"makechan64", funcTag, 96}, - {"makechan", funcTag, 97}, - {"chanrecv1", funcTag, 99}, - {"chanrecv2", funcTag, 100}, - {"chansend1", funcTag, 102}, + {"convI2I", funcTag, 58}, + {"convT", funcTag, 59}, + {"convTnoptr", funcTag, 59}, + {"convT16", funcTag, 61}, + {"convT32", funcTag, 63}, + {"convT64", funcTag, 64}, + {"convTstring", funcTag, 65}, + {"convTslice", funcTag, 68}, + {"assertE2I", funcTag, 69}, + {"assertE2I2", funcTag, 70}, + {"assertI2I", funcTag, 69}, + {"assertI2I2", funcTag, 70}, + {"panicdottypeE", funcTag, 71}, + {"panicdottypeI", funcTag, 71}, + {"panicnildottype", funcTag, 72}, + {"ifaceeq", funcTag, 73}, + {"efaceeq", funcTag, 73}, + {"fastrand", funcTag, 74}, + {"makemap64", funcTag, 76}, + {"makemap", funcTag, 77}, + {"makemap_small", funcTag, 78}, + {"mapaccess1", funcTag, 79}, + {"mapaccess1_fast32", funcTag, 80}, + {"mapaccess1_fast64", funcTag, 81}, + {"mapaccess1_faststr", funcTag, 82}, + {"mapaccess1_fat", funcTag, 83}, + {"mapaccess2", funcTag, 84}, + {"mapaccess2_fast32", funcTag, 85}, + {"mapaccess2_fast64", funcTag, 86}, + {"mapaccess2_faststr", funcTag, 87}, + {"mapaccess2_fat", funcTag, 88}, + {"mapassign", funcTag, 79}, + {"mapassign_fast32", funcTag, 80}, + {"mapassign_fast32ptr", funcTag, 89}, + {"mapassign_fast64", funcTag, 81}, + {"mapassign_fast64ptr", funcTag, 89}, + {"mapassign_faststr", funcTag, 82}, + {"mapiterinit", funcTag, 90}, + {"mapdelete", funcTag, 90}, + {"mapdelete_fast32", funcTag, 91}, + {"mapdelete_fast64", funcTag, 92}, + {"mapdelete_faststr", funcTag, 93}, + {"mapiternext", funcTag, 94}, + {"mapclear", funcTag, 95}, + {"makechan64", funcTag, 97}, + {"makechan", funcTag, 98}, + {"chanrecv1", funcTag, 100}, + {"chanrecv2", funcTag, 101}, + {"chansend1", funcTag, 103}, {"closechan", funcTag, 30}, - {"writeBarrier", varTag, 104}, - {"typedmemmove", funcTag, 105}, - {"typedmemclr", funcTag, 106}, - {"typedslicecopy", funcTag, 107}, - {"selectnbsend", funcTag, 108}, - {"selectnbrecv", funcTag, 109}, - {"selectsetpc", funcTag, 110}, - {"selectgo", funcTag, 111}, + {"writeBarrier", varTag, 105}, + {"typedmemmove", funcTag, 106}, + {"typedmemclr", funcTag, 107}, + {"typedslicecopy", funcTag, 108}, + {"selectnbsend", funcTag, 109}, + {"selectnbrecv", funcTag, 110}, + {"selectsetpc", funcTag, 111}, + {"selectgo", funcTag, 112}, {"block", funcTag, 9}, - {"makeslice", funcTag, 112}, - {"makeslice64", funcTag, 113}, - {"makeslicecopy", funcTag, 114}, - {"growslice", funcTag, 116}, - {"unsafeslice", funcTag, 117}, - {"unsafeslice64", funcTag, 118}, - {"unsafeslicecheckptr", funcTag, 118}, - {"memmove", funcTag, 119}, - {"memclrNoHeapPointers", funcTag, 120}, - {"memclrHasPointers", funcTag, 120}, - {"memequal", funcTag, 121}, - {"memequal0", funcTag, 122}, - {"memequal8", funcTag, 122}, - {"memequal16", funcTag, 122}, - {"memequal32", funcTag, 122}, - {"memequal64", funcTag, 122}, - {"memequal128", funcTag, 122}, - {"f32equal", funcTag, 123}, - {"f64equal", funcTag, 123}, - {"c64equal", funcTag, 123}, - {"c128equal", funcTag, 123}, - {"strequal", funcTag, 123}, - {"interequal", funcTag, 123}, - {"nilinterequal", funcTag, 123}, - {"memhash", funcTag, 124}, - {"memhash0", funcTag, 125}, - {"memhash8", funcTag, 125}, - {"memhash16", funcTag, 125}, - {"memhash32", funcTag, 125}, - {"memhash64", funcTag, 125}, - {"memhash128", funcTag, 125}, - {"f32hash", funcTag, 125}, - {"f64hash", funcTag, 125}, - {"c64hash", funcTag, 125}, - {"c128hash", funcTag, 125}, - {"strhash", funcTag, 125}, - {"interhash", funcTag, 125}, - {"nilinterhash", funcTag, 125}, - {"int64div", funcTag, 126}, - {"uint64div", funcTag, 127}, - {"int64mod", funcTag, 126}, - {"uint64mod", funcTag, 127}, - {"float64toint64", funcTag, 128}, - {"float64touint64", funcTag, 129}, - {"float64touint32", funcTag, 130}, - {"int64tofloat64", funcTag, 131}, - {"uint64tofloat64", funcTag, 132}, - {"uint32tofloat64", funcTag, 133}, - {"complex128div", funcTag, 134}, - {"getcallerpc", funcTag, 135}, - {"getcallersp", funcTag, 135}, + {"makeslice", funcTag, 113}, + {"makeslice64", funcTag, 114}, + {"makeslicecopy", funcTag, 115}, + {"growslice", funcTag, 117}, + {"unsafeslice", funcTag, 118}, + {"unsafeslice64", funcTag, 119}, + {"unsafeslicecheckptr", funcTag, 119}, + {"memmove", funcTag, 120}, + {"memclrNoHeapPointers", funcTag, 121}, + {"memclrHasPointers", funcTag, 121}, + {"memequal", funcTag, 122}, + {"memequal0", funcTag, 123}, + {"memequal8", funcTag, 123}, + {"memequal16", funcTag, 123}, + {"memequal32", funcTag, 123}, + {"memequal64", funcTag, 123}, + {"memequal128", funcTag, 123}, + {"f32equal", funcTag, 124}, + {"f64equal", funcTag, 124}, + {"c64equal", funcTag, 124}, + {"c128equal", funcTag, 124}, + {"strequal", funcTag, 124}, + {"interequal", funcTag, 124}, + {"nilinterequal", funcTag, 124}, + {"memhash", funcTag, 125}, + {"memhash0", funcTag, 126}, + {"memhash8", funcTag, 126}, + {"memhash16", funcTag, 126}, + {"memhash32", funcTag, 126}, + {"memhash64", funcTag, 126}, + {"memhash128", funcTag, 126}, + {"f32hash", funcTag, 126}, + {"f64hash", funcTag, 126}, + {"c64hash", funcTag, 126}, + {"c128hash", funcTag, 126}, + {"strhash", funcTag, 126}, + {"interhash", funcTag, 126}, + {"nilinterhash", funcTag, 126}, + {"int64div", funcTag, 127}, + {"uint64div", funcTag, 128}, + {"int64mod", funcTag, 127}, + {"uint64mod", funcTag, 128}, + {"float64toint64", funcTag, 129}, + {"float64touint64", funcTag, 130}, + {"float64touint32", funcTag, 131}, + {"int64tofloat64", funcTag, 132}, + {"uint64tofloat64", funcTag, 133}, + {"uint32tofloat64", funcTag, 134}, + {"complex128div", funcTag, 135}, + {"getcallerpc", funcTag, 136}, + {"getcallersp", funcTag, 136}, {"racefuncenter", funcTag, 31}, {"racefuncexit", funcTag, 9}, {"raceread", funcTag, 31}, {"racewrite", funcTag, 31}, - {"racereadrange", funcTag, 136}, - {"racewriterange", funcTag, 136}, - {"msanread", funcTag, 136}, - {"msanwrite", funcTag, 136}, - {"msanmove", funcTag, 137}, - {"checkptrAlignment", funcTag, 138}, - {"checkptrArithmetic", funcTag, 140}, - {"libfuzzerTraceCmp1", funcTag, 141}, - {"libfuzzerTraceCmp2", funcTag, 142}, - {"libfuzzerTraceCmp4", funcTag, 143}, - {"libfuzzerTraceCmp8", funcTag, 144}, - {"libfuzzerTraceConstCmp1", funcTag, 141}, - {"libfuzzerTraceConstCmp2", funcTag, 142}, - {"libfuzzerTraceConstCmp4", funcTag, 143}, - {"libfuzzerTraceConstCmp8", funcTag, 144}, + {"racereadrange", funcTag, 137}, + {"racewriterange", funcTag, 137}, + {"msanread", funcTag, 137}, + {"msanwrite", funcTag, 137}, + {"msanmove", funcTag, 138}, + {"checkptrAlignment", funcTag, 139}, + {"checkptrArithmetic", funcTag, 141}, + {"libfuzzerTraceCmp1", funcTag, 142}, + {"libfuzzerTraceCmp2", funcTag, 143}, + {"libfuzzerTraceCmp4", funcTag, 144}, + {"libfuzzerTraceCmp8", funcTag, 145}, + {"libfuzzerTraceConstCmp1", funcTag, 142}, + {"libfuzzerTraceConstCmp2", funcTag, 143}, + {"libfuzzerTraceConstCmp4", funcTag, 144}, + {"libfuzzerTraceConstCmp8", funcTag, 145}, {"x86HasPOPCNT", varTag, 6}, {"x86HasSSE41", varTag, 6}, {"x86HasFMA", varTag, 6}, @@ -224,7 +222,7 @@ func params(tlist ...*types.Type) []*types.Field { } func runtimeTypes() []*types.Type { - var typs [145]*types.Type + var typs [146]*types.Type typs[0] = types.ByteType typs[1] = types.NewPtr(typs[0]) typs[2] = types.Types[types.TANY] @@ -282,93 +280,94 @@ func runtimeTypes() []*types.Type { typs[54] = newSig(params(typs[3], typs[15], typs[3], typs[15], typs[5]), params(typs[15])) typs[55] = newSig(params(typs[28], typs[15]), params(typs[46], typs[15])) typs[56] = newSig(params(typs[28]), params(typs[15])) - typs[57] = newSig(params(typs[1], typs[2]), params(typs[2])) - typs[58] = types.Types[types.TUINT16] - typs[59] = newSig(params(typs[58]), params(typs[7])) - typs[60] = types.Types[types.TUINT32] + typs[57] = types.NewPtr(typs[5]) + typs[58] = newSig(params(typs[1], typs[57]), params(typs[57])) + typs[59] = newSig(params(typs[1], typs[3]), params(typs[7])) + typs[60] = types.Types[types.TUINT16] typs[61] = newSig(params(typs[60]), params(typs[7])) - typs[62] = newSig(params(typs[24]), params(typs[7])) - typs[63] = newSig(params(typs[28]), params(typs[7])) - typs[64] = types.Types[types.TUINT8] - typs[65] = types.NewSlice(typs[64]) - typs[66] = newSig(params(typs[65]), params(typs[7])) - typs[67] = newSig(params(typs[1], typs[3]), params(typs[2])) - typs[68] = newSig(params(typs[1], typs[1]), params(typs[1])) - typs[69] = newSig(params(typs[1], typs[1], typs[1]), nil) - typs[70] = newSig(params(typs[1]), nil) - typs[71] = types.NewPtr(typs[5]) - typs[72] = newSig(params(typs[71], typs[7], typs[7]), params(typs[6])) - typs[73] = newSig(nil, params(typs[60])) - typs[74] = types.NewMap(typs[2], typs[2]) - typs[75] = newSig(params(typs[1], typs[22], typs[3]), params(typs[74])) - typs[76] = newSig(params(typs[1], typs[15], typs[3]), params(typs[74])) - typs[77] = newSig(nil, params(typs[74])) - typs[78] = newSig(params(typs[1], typs[74], typs[3]), params(typs[3])) - typs[79] = newSig(params(typs[1], typs[74], typs[60]), params(typs[3])) - typs[80] = newSig(params(typs[1], typs[74], typs[24]), params(typs[3])) - typs[81] = newSig(params(typs[1], typs[74], typs[28]), params(typs[3])) - typs[82] = newSig(params(typs[1], typs[74], typs[3], typs[1]), params(typs[3])) - typs[83] = newSig(params(typs[1], typs[74], typs[3]), params(typs[3], typs[6])) - typs[84] = newSig(params(typs[1], typs[74], typs[60]), params(typs[3], typs[6])) - typs[85] = newSig(params(typs[1], typs[74], typs[24]), params(typs[3], typs[6])) - typs[86] = newSig(params(typs[1], typs[74], typs[28]), params(typs[3], typs[6])) - typs[87] = newSig(params(typs[1], typs[74], typs[3], typs[1]), params(typs[3], typs[6])) - typs[88] = newSig(params(typs[1], typs[74], typs[7]), params(typs[3])) - typs[89] = newSig(params(typs[1], typs[74], typs[3]), nil) - typs[90] = newSig(params(typs[1], typs[74], typs[60]), nil) - typs[91] = newSig(params(typs[1], typs[74], typs[24]), nil) - typs[92] = newSig(params(typs[1], typs[74], typs[28]), nil) - typs[93] = newSig(params(typs[3]), nil) - typs[94] = newSig(params(typs[1], typs[74]), nil) - typs[95] = types.NewChan(typs[2], types.Cboth) - typs[96] = newSig(params(typs[1], typs[22]), params(typs[95])) - typs[97] = newSig(params(typs[1], typs[15]), params(typs[95])) - typs[98] = types.NewChan(typs[2], types.Crecv) - typs[99] = newSig(params(typs[98], typs[3]), nil) - typs[100] = newSig(params(typs[98], typs[3]), params(typs[6])) - typs[101] = types.NewChan(typs[2], types.Csend) - typs[102] = newSig(params(typs[101], typs[3]), nil) - typs[103] = types.NewArray(typs[0], 3) - typs[104] = types.NewStruct(types.NoPkg, []*types.Field{types.NewField(src.NoXPos, Lookup("enabled"), typs[6]), types.NewField(src.NoXPos, Lookup("pad"), typs[103]), types.NewField(src.NoXPos, Lookup("needed"), typs[6]), types.NewField(src.NoXPos, Lookup("cgo"), typs[6]), types.NewField(src.NoXPos, Lookup("alignme"), typs[24])}) - typs[105] = newSig(params(typs[1], typs[3], typs[3]), nil) - typs[106] = newSig(params(typs[1], typs[3]), nil) - typs[107] = newSig(params(typs[1], typs[3], typs[15], typs[3], typs[15]), params(typs[15])) - typs[108] = newSig(params(typs[101], typs[3]), params(typs[6])) - typs[109] = newSig(params(typs[3], typs[98]), params(typs[6], typs[6])) - typs[110] = newSig(params(typs[71]), nil) - typs[111] = newSig(params(typs[1], typs[1], typs[71], typs[15], typs[15], typs[6]), params(typs[15], typs[6])) - typs[112] = newSig(params(typs[1], typs[15], typs[15]), params(typs[7])) - typs[113] = newSig(params(typs[1], typs[22], typs[22]), params(typs[7])) - typs[114] = newSig(params(typs[1], typs[15], typs[15], typs[7]), params(typs[7])) - typs[115] = types.NewSlice(typs[2]) - typs[116] = newSig(params(typs[1], typs[115], typs[15]), params(typs[115])) - typs[117] = newSig(params(typs[1], typs[7], typs[15]), nil) - typs[118] = newSig(params(typs[1], typs[7], typs[22]), nil) - typs[119] = newSig(params(typs[3], typs[3], typs[5]), nil) - typs[120] = newSig(params(typs[7], typs[5]), nil) - typs[121] = newSig(params(typs[3], typs[3], typs[5]), params(typs[6])) - typs[122] = newSig(params(typs[3], typs[3]), params(typs[6])) - typs[123] = newSig(params(typs[7], typs[7]), params(typs[6])) - typs[124] = newSig(params(typs[7], typs[5], typs[5]), params(typs[5])) - typs[125] = newSig(params(typs[7], typs[5]), params(typs[5])) - typs[126] = newSig(params(typs[22], typs[22]), params(typs[22])) - typs[127] = newSig(params(typs[24], typs[24]), params(typs[24])) - typs[128] = newSig(params(typs[20]), params(typs[22])) - typs[129] = newSig(params(typs[20]), params(typs[24])) - typs[130] = newSig(params(typs[20]), params(typs[60])) - typs[131] = newSig(params(typs[22]), params(typs[20])) - typs[132] = newSig(params(typs[24]), params(typs[20])) - typs[133] = newSig(params(typs[60]), params(typs[20])) - typs[134] = newSig(params(typs[26], typs[26]), params(typs[26])) - typs[135] = newSig(nil, params(typs[5])) - typs[136] = newSig(params(typs[5], typs[5]), nil) - typs[137] = newSig(params(typs[5], typs[5], typs[5]), nil) - typs[138] = newSig(params(typs[7], typs[1], typs[5]), nil) - typs[139] = types.NewSlice(typs[7]) - typs[140] = newSig(params(typs[7], typs[139]), nil) - typs[141] = newSig(params(typs[64], typs[64]), nil) - typs[142] = newSig(params(typs[58], typs[58]), nil) + typs[62] = types.Types[types.TUINT32] + typs[63] = newSig(params(typs[62]), params(typs[7])) + typs[64] = newSig(params(typs[24]), params(typs[7])) + typs[65] = newSig(params(typs[28]), params(typs[7])) + typs[66] = types.Types[types.TUINT8] + typs[67] = types.NewSlice(typs[66]) + typs[68] = newSig(params(typs[67]), params(typs[7])) + typs[69] = newSig(params(typs[1], typs[1]), params(typs[1])) + typs[70] = newSig(params(typs[1], typs[2]), params(typs[2])) + typs[71] = newSig(params(typs[1], typs[1], typs[1]), nil) + typs[72] = newSig(params(typs[1]), nil) + typs[73] = newSig(params(typs[57], typs[7], typs[7]), params(typs[6])) + typs[74] = newSig(nil, params(typs[62])) + typs[75] = types.NewMap(typs[2], typs[2]) + typs[76] = newSig(params(typs[1], typs[22], typs[3]), params(typs[75])) + typs[77] = newSig(params(typs[1], typs[15], typs[3]), params(typs[75])) + typs[78] = newSig(nil, params(typs[75])) + typs[79] = newSig(params(typs[1], typs[75], typs[3]), params(typs[3])) + typs[80] = newSig(params(typs[1], typs[75], typs[62]), params(typs[3])) + typs[81] = newSig(params(typs[1], typs[75], typs[24]), params(typs[3])) + typs[82] = newSig(params(typs[1], typs[75], typs[28]), params(typs[3])) + typs[83] = newSig(params(typs[1], typs[75], typs[3], typs[1]), params(typs[3])) + typs[84] = newSig(params(typs[1], typs[75], typs[3]), params(typs[3], typs[6])) + typs[85] = newSig(params(typs[1], typs[75], typs[62]), params(typs[3], typs[6])) + typs[86] = newSig(params(typs[1], typs[75], typs[24]), params(typs[3], typs[6])) + typs[87] = newSig(params(typs[1], typs[75], typs[28]), params(typs[3], typs[6])) + typs[88] = newSig(params(typs[1], typs[75], typs[3], typs[1]), params(typs[3], typs[6])) + typs[89] = newSig(params(typs[1], typs[75], typs[7]), params(typs[3])) + typs[90] = newSig(params(typs[1], typs[75], typs[3]), nil) + typs[91] = newSig(params(typs[1], typs[75], typs[62]), nil) + typs[92] = newSig(params(typs[1], typs[75], typs[24]), nil) + typs[93] = newSig(params(typs[1], typs[75], typs[28]), nil) + typs[94] = newSig(params(typs[3]), nil) + typs[95] = newSig(params(typs[1], typs[75]), nil) + typs[96] = types.NewChan(typs[2], types.Cboth) + typs[97] = newSig(params(typs[1], typs[22]), params(typs[96])) + typs[98] = newSig(params(typs[1], typs[15]), params(typs[96])) + typs[99] = types.NewChan(typs[2], types.Crecv) + typs[100] = newSig(params(typs[99], typs[3]), nil) + typs[101] = newSig(params(typs[99], typs[3]), params(typs[6])) + typs[102] = types.NewChan(typs[2], types.Csend) + typs[103] = newSig(params(typs[102], typs[3]), nil) + typs[104] = types.NewArray(typs[0], 3) + typs[105] = types.NewStruct(types.NoPkg, []*types.Field{types.NewField(src.NoXPos, Lookup("enabled"), typs[6]), types.NewField(src.NoXPos, Lookup("pad"), typs[104]), types.NewField(src.NoXPos, Lookup("needed"), typs[6]), types.NewField(src.NoXPos, Lookup("cgo"), typs[6]), types.NewField(src.NoXPos, Lookup("alignme"), typs[24])}) + typs[106] = newSig(params(typs[1], typs[3], typs[3]), nil) + typs[107] = newSig(params(typs[1], typs[3]), nil) + typs[108] = newSig(params(typs[1], typs[3], typs[15], typs[3], typs[15]), params(typs[15])) + typs[109] = newSig(params(typs[102], typs[3]), params(typs[6])) + typs[110] = newSig(params(typs[3], typs[99]), params(typs[6], typs[6])) + typs[111] = newSig(params(typs[57]), nil) + typs[112] = newSig(params(typs[1], typs[1], typs[57], typs[15], typs[15], typs[6]), params(typs[15], typs[6])) + typs[113] = newSig(params(typs[1], typs[15], typs[15]), params(typs[7])) + typs[114] = newSig(params(typs[1], typs[22], typs[22]), params(typs[7])) + typs[115] = newSig(params(typs[1], typs[15], typs[15], typs[7]), params(typs[7])) + typs[116] = types.NewSlice(typs[2]) + typs[117] = newSig(params(typs[1], typs[116], typs[15]), params(typs[116])) + typs[118] = newSig(params(typs[1], typs[7], typs[15]), nil) + typs[119] = newSig(params(typs[1], typs[7], typs[22]), nil) + typs[120] = newSig(params(typs[3], typs[3], typs[5]), nil) + typs[121] = newSig(params(typs[7], typs[5]), nil) + typs[122] = newSig(params(typs[3], typs[3], typs[5]), params(typs[6])) + typs[123] = newSig(params(typs[3], typs[3]), params(typs[6])) + typs[124] = newSig(params(typs[7], typs[7]), params(typs[6])) + typs[125] = newSig(params(typs[7], typs[5], typs[5]), params(typs[5])) + typs[126] = newSig(params(typs[7], typs[5]), params(typs[5])) + typs[127] = newSig(params(typs[22], typs[22]), params(typs[22])) + typs[128] = newSig(params(typs[24], typs[24]), params(typs[24])) + typs[129] = newSig(params(typs[20]), params(typs[22])) + typs[130] = newSig(params(typs[20]), params(typs[24])) + typs[131] = newSig(params(typs[20]), params(typs[62])) + typs[132] = newSig(params(typs[22]), params(typs[20])) + typs[133] = newSig(params(typs[24]), params(typs[20])) + typs[134] = newSig(params(typs[62]), params(typs[20])) + typs[135] = newSig(params(typs[26], typs[26]), params(typs[26])) + typs[136] = newSig(nil, params(typs[5])) + typs[137] = newSig(params(typs[5], typs[5]), nil) + typs[138] = newSig(params(typs[5], typs[5], typs[5]), nil) + typs[139] = newSig(params(typs[7], typs[1], typs[5]), nil) + typs[140] = types.NewSlice(typs[7]) + typs[141] = newSig(params(typs[7], typs[140]), nil) + typs[142] = newSig(params(typs[66], typs[66]), nil) typs[143] = newSig(params(typs[60], typs[60]), nil) - typs[144] = newSig(params(typs[24], typs[24]), nil) + typs[144] = newSig(params(typs[62], typs[62]), nil) + typs[145] = newSig(params(typs[24], typs[24]), nil) return typs[:] } diff --git a/src/cmd/compile/internal/typecheck/builtin/runtime.go b/src/cmd/compile/internal/typecheck/builtin/runtime.go index 2b29ea3c08..605b904288 100644 --- a/src/cmd/compile/internal/typecheck/builtin/runtime.go +++ b/src/cmd/compile/internal/typecheck/builtin/runtime.go @@ -84,10 +84,15 @@ func decoderune(string, int) (retv rune, retk int) func countrunes(string) int // Non-empty-interface to non-empty-interface conversion. -func convI2I(typ *byte, elem any) (ret any) +func convI2I(typ *byte, itab *uintptr) (ret *uintptr) -// Specialized type-to-interface conversion. -// These return only a data pointer. +// Convert non-interface type to the data word of a (empty or nonempty) interface. +func convT(typ *byte, elem *any) unsafe.Pointer + +// Same as convT, for types with no pointers in them. +func convTnoptr(typ *byte, elem *any) unsafe.Pointer + +// Specialized versions of convT for specific types. // These functions take concrete types in the runtime. But they may // be used for a wider range of types, which have the same memory // layout as the parameter type. The compiler converts the @@ -99,14 +104,6 @@ func convT64(val uint64) unsafe.Pointer func convTstring(val string) unsafe.Pointer func convTslice(val []uint8) unsafe.Pointer -// Type to empty-interface conversion. -func convT2E(typ *byte, elem *any) (ret any) -func convT2Enoptr(typ *byte, elem *any) (ret any) - -// Type to non-empty-interface conversion. -func convT2I(tab *byte, elem *any) (ret any) -func convT2Inoptr(tab *byte, elem *any) (ret any) - // interface type assertions x.(T) func assertE2I(inter *byte, typ *byte) *byte func assertE2I2(inter *byte, eface any) (ret any) diff --git a/src/cmd/compile/internal/walk/convert.go b/src/cmd/compile/internal/walk/convert.go index d15575f643..27a07ce4b6 100644 --- a/src/cmd/compile/internal/walk/convert.go +++ b/src/cmd/compile/internal/walk/convert.go @@ -39,56 +39,100 @@ func walkConv(n *ir.ConvExpr, init *ir.Nodes) ir.Node { return typecheck.Conv(mkcall(fn, types.Types[result], init, typecheck.Conv(n.X, types.Types[param])), n.Type()) } -// walkConvInterface walks an OCONVIFACE or OCONVIDATA node. +// walkConvInterface walks an OCONVIFACE node. func walkConvInterface(n *ir.ConvExpr, init *ir.Nodes) ir.Node { n.X = walkExpr(n.X, init) fromType := n.X.Type() toType := n.Type() - if n.Op() == ir.OCONVIDATA { - // Just convert to empty interface, to make it easy. - // The caller throws away the type word. - toType = types.NewInterface(types.LocalPkg, nil) - // Note: don't pass fromType to MarkTypeUsedInInterface because it is likely - // a shape type. The appropriate call to MarkTypeUsedInInterface will come - // when building the dictionary (from which the matching type word will come). - } else if !fromType.IsInterface() && !ir.IsBlank(ir.CurFunc.Nname) { + if !fromType.IsInterface() && !ir.IsBlank(ir.CurFunc.Nname) { // skip unnamed functions (func _()) reflectdata.MarkTypeUsedInInterface(fromType, ir.CurFunc.LSym) } - // typeword generates the type word of the interface value. - typeword := func() ir.Node { + if !fromType.IsInterface() { + var typeWord ir.Node if toType.IsEmptyInterface() { - return reflectdata.TypePtr(fromType) + typeWord = reflectdata.TypePtr(fromType) + } else { + typeWord = reflectdata.ITabAddr(fromType, toType) } - return reflectdata.ITabAddr(fromType, toType) - } - - // Optimize convT2E or convT2I as a two-word copy when T is pointer-shaped. - if types.IsDirectIface(fromType) { - l := ir.NewBinaryExpr(base.Pos, ir.OEFACE, typeword(), n.X) + l := ir.NewBinaryExpr(base.Pos, ir.OEFACE, typeWord, dataWord(n.X, init, n.Esc() != ir.EscNone)) l.SetType(toType) l.SetTypecheck(n.Typecheck()) return l } + if fromType.IsEmptyInterface() { + base.Fatalf("OCONVIFACE can't operate on an empty interface") + } + + // Evaluate the input interface. + c := typecheck.Temp(fromType) + init.Append(ir.NewAssignStmt(base.Pos, c, n.X)) + + // Grab its parts. + itab := ir.NewUnaryExpr(base.Pos, ir.OITAB, c) + itab.SetType(types.Types[types.TUINTPTR].PtrTo()) + itab.SetTypecheck(1) + data := ir.NewUnaryExpr(base.Pos, ir.OIDATA, c) + data.SetType(types.Types[types.TUINT8].PtrTo()) // Type is generic pointer - we're just passing it through. + data.SetTypecheck(1) + + var typeWord ir.Node + if toType.IsEmptyInterface() { + // Implement interface to empty interface conversion. + // res = itab + // if res != nil { + // res = res.type + // } + typeWord = typecheck.Temp(types.NewPtr(types.Types[types.TUINT8])) + init.Append(ir.NewAssignStmt(base.Pos, typeWord, itab)) + nif := ir.NewIfStmt(base.Pos, typecheck.Expr(ir.NewBinaryExpr(base.Pos, ir.ONE, typeWord, typecheck.NodNil())), nil, nil) + nif.Body = []ir.Node{ir.NewAssignStmt(base.Pos, typeWord, itabType(typeWord))} + init.Append(nif) + } else { + // Must be converting I2I (more specific to less specific interface). + // res = convI2I(toType, itab) + fn := typecheck.LookupRuntime("convI2I") + types.CalcSize(fn.Type()) + call := ir.NewCallExpr(base.Pos, ir.OCALL, fn, nil) + call.Args = []ir.Node{reflectdata.TypePtr(toType), itab} + typeWord = walkExpr(typecheck.Expr(call), init) + } + + // Build the result. + // e = iface{typeWord, data} + e := ir.NewBinaryExpr(base.Pos, ir.OEFACE, typeWord, data) + e.SetType(toType) // assign type manually, typecheck doesn't understand OEFACE. + e.SetTypecheck(1) + return e +} + +// Returns the data word (the second word) used to represent n in an interface. +// n must not be of interface type. +// esc describes whether the result escapes. +func dataWord(n ir.Node, init *ir.Nodes, escapes bool) ir.Node { + fromType := n.Type() + + // If it's a pointer, it is its own representation. + if types.IsDirectIface(fromType) { + return n + } - // Optimize convT2{E,I} for many cases in which T is not pointer-shaped, - // by using an existing addressable value identical to n.Left - // or creating one on the stack. + // Try a bunch of cases to avoid an allocation. var value ir.Node switch { case fromType.Size() == 0: - // n.Left is zero-sized. Use zerobase. - cheapExpr(n.X, init) // Evaluate n.Left for side-effects. See issue 19246. + // n is zero-sized. Use zerobase. + cheapExpr(n, init) // Evaluate n for side-effects. See issue 19246. value = ir.NewLinksymExpr(base.Pos, ir.Syms.Zerobase, types.Types[types.TUINTPTR]) case fromType.IsBoolean() || (fromType.Size() == 1 && fromType.IsInteger()): - // n.Left is a bool/byte. Use staticuint64s[n.Left * 8] on little-endian - // and staticuint64s[n.Left * 8 + 7] on big-endian. - n.X = cheapExpr(n.X, init) - // byteindex widens n.Left so that the multiplication doesn't overflow. - index := ir.NewBinaryExpr(base.Pos, ir.OLSH, byteindex(n.X), ir.NewInt(3)) + // n is a bool/byte. Use staticuint64s[n * 8] on little-endian + // and staticuint64s[n * 8 + 7] on big-endian. + n = cheapExpr(n, init) + // byteindex widens n so that the multiplication doesn't overflow. + index := ir.NewBinaryExpr(base.Pos, ir.OLSH, byteindex(n), ir.NewInt(3)) if ssagen.Arch.LinkArch.ByteOrder == binary.BigEndian { index = ir.NewBinaryExpr(base.Pos, ir.OADD, index, ir.NewInt(7)) } @@ -98,118 +142,71 @@ func walkConvInterface(n *ir.ConvExpr, init *ir.Nodes) ir.Node { xe := ir.NewIndexExpr(base.Pos, staticuint64s, index) xe.SetBounded(true) value = xe - case n.X.Op() == ir.ONAME && n.X.(*ir.Name).Class == ir.PEXTERN && n.X.(*ir.Name).Readonly(): - // n.Left is a readonly global; use it directly. - value = n.X - case !fromType.IsInterface() && n.Esc() == ir.EscNone && fromType.Width <= 1024: - // n.Left does not escape. Use a stack temporary initialized to n.Left. + case n.Op() == ir.ONAME && n.(*ir.Name).Class == ir.PEXTERN && n.(*ir.Name).Readonly(): + // n is a readonly global; use it directly. + value = n + case !escapes && fromType.Width <= 1024: + // n does not escape. Use a stack temporary initialized to n. value = typecheck.Temp(fromType) - init.Append(typecheck.Stmt(ir.NewAssignStmt(base.Pos, value, n.X))) + init.Append(typecheck.Stmt(ir.NewAssignStmt(base.Pos, value, n))) } - if value != nil { - // Value is identical to n.Left. - // Construct the interface directly: {type/itab, &value}. - l := ir.NewBinaryExpr(base.Pos, ir.OEFACE, typeword(), typecheck.Expr(typecheck.NodAddr(value))) - l.SetType(toType) - l.SetTypecheck(n.Typecheck()) - return l - } - - // Implement interface to empty interface conversion. - // tmp = i.itab - // if tmp != nil { - // tmp = tmp.type - // } - // e = iface{tmp, i.data} - if toType.IsEmptyInterface() && fromType.IsInterface() && !fromType.IsEmptyInterface() { - // Evaluate the input interface. - c := typecheck.Temp(fromType) - init.Append(ir.NewAssignStmt(base.Pos, c, n.X)) - - // Get the itab out of the interface. - tmp := typecheck.Temp(types.NewPtr(types.Types[types.TUINT8])) - init.Append(ir.NewAssignStmt(base.Pos, tmp, typecheck.Expr(ir.NewUnaryExpr(base.Pos, ir.OITAB, c)))) - - // Get the type out of the itab. - nif := ir.NewIfStmt(base.Pos, typecheck.Expr(ir.NewBinaryExpr(base.Pos, ir.ONE, tmp, typecheck.NodNil())), nil, nil) - nif.Body = []ir.Node{ir.NewAssignStmt(base.Pos, tmp, itabType(tmp))} - init.Append(nif) - - // Build the result. - e := ir.NewBinaryExpr(base.Pos, ir.OEFACE, tmp, ifaceData(n.Pos(), c, types.NewPtr(types.Types[types.TUINT8]))) - e.SetType(toType) // assign type manually, typecheck doesn't understand OEFACE. - e.SetTypecheck(1) - return e + // The interface data word is &value. + return typecheck.Expr(typecheck.NodAddr(value)) } - fnname, argType, needsaddr := convFuncName(fromType, toType) - - if !needsaddr && !fromType.IsInterface() { - // Use a specialized conversion routine that only returns a data pointer. - // ptr = convT2X(val) - // e = iface{typ/tab, ptr} - fn := typecheck.LookupRuntime(fnname) - types.CalcSize(fromType) + // Time to do an allocation. We'll call into the runtime for that. + fnname, argType, needsaddr := dataWordFuncName(fromType) + fn := typecheck.LookupRuntime(fnname) - arg := n.X + var args []ir.Node + if needsaddr { + // Types of large or unknown size are passed by reference. + // Orderexpr arranged for n to be a temporary for all + // the conversions it could see. Comparison of an interface + // with a non-interface, especially in a switch on interface value + // with non-interface cases, is not visible to order.stmt, so we + // have to fall back on allocating a temp here. + if !ir.IsAddressable(n) { + n = copyExpr(n, fromType, init) + } + fn = typecheck.SubstArgTypes(fn, fromType) + args = []ir.Node{reflectdata.TypePtr(fromType), typecheck.NodAddr(n)} + } else { + // Use a specialized conversion routine that takes the type being + // converted by value, not by pointer. + var arg ir.Node switch { case fromType == argType: // already in the right type, nothing to do + arg = n case fromType.Kind() == argType.Kind(), fromType.IsPtrShaped() && argType.IsPtrShaped(): // can directly convert (e.g. named type to underlying type, or one pointer to another) - arg = ir.NewConvExpr(n.Pos(), ir.OCONVNOP, argType, arg) + // TODO: never happens because pointers are directIface? + arg = ir.NewConvExpr(n.Pos(), ir.OCONVNOP, argType, n) case fromType.IsInteger() && argType.IsInteger(): // can directly convert (e.g. int32 to uint32) - arg = ir.NewConvExpr(n.Pos(), ir.OCONV, argType, arg) + arg = ir.NewConvExpr(n.Pos(), ir.OCONV, argType, n) default: // unsafe cast through memory - arg = copyExpr(arg, arg.Type(), init) + arg = copyExpr(n, fromType, init) var addr ir.Node = typecheck.NodAddr(arg) addr = ir.NewConvExpr(n.Pos(), ir.OCONVNOP, argType.PtrTo(), addr) arg = ir.NewStarExpr(n.Pos(), addr) arg.SetType(argType) } - - call := ir.NewCallExpr(base.Pos, ir.OCALL, fn, nil) - call.Args = []ir.Node{arg} - e := ir.NewBinaryExpr(base.Pos, ir.OEFACE, typeword(), safeExpr(walkExpr(typecheck.Expr(call), init), init)) - e.SetType(toType) - e.SetTypecheck(1) - return e - } - - var tab ir.Node - if fromType.IsInterface() { - // convI2I - tab = reflectdata.TypePtr(toType) - } else { - // convT2x - tab = typeword() - } - - v := n.X - if needsaddr { - // Types of large or unknown size are passed by reference. - // Orderexpr arranged for n.Left to be a temporary for all - // the conversions it could see. Comparison of an interface - // with a non-interface, especially in a switch on interface value - // with non-interface cases, is not visible to order.stmt, so we - // have to fall back on allocating a temp here. - if !ir.IsAddressable(v) { - v = copyExpr(v, v.Type(), init) - } - v = typecheck.NodAddr(v) + args = []ir.Node{arg} } - - types.CalcSize(fromType) - fn := typecheck.LookupRuntime(fnname) - fn = typecheck.SubstArgTypes(fn, fromType, toType) - types.CalcSize(fn.Type()) call := ir.NewCallExpr(base.Pos, ir.OCALL, fn, nil) - call.Args = []ir.Node{tab, v} - return walkExpr(typecheck.Expr(call), init) + call.Args = args + return safeExpr(walkExpr(typecheck.Expr(call), init), init) +} + +// walkConvIData walks an OCONVIDATA node. +func walkConvIData(n *ir.ConvExpr, init *ir.Nodes) ir.Node { + n.X = walkExpr(n.X, init) + return dataWord(n.X, init, n.Esc() != ir.EscNone) } // walkBytesRunesToString walks an OBYTES2STR or ORUNES2STR node. @@ -320,50 +317,35 @@ func walkStringToRunes(n *ir.ConvExpr, init *ir.Nodes) ir.Node { return mkcall("stringtoslicerune", n.Type(), init, a, typecheck.Conv(n.X, types.Types[types.TSTRING])) } -// convFuncName builds the runtime function name for interface conversion. -// It also returns the argument type that the runtime function takes, and -// whether the function expects the data by address. -// Not all names are possible. For example, we never generate convE2E or convE2I. -func convFuncName(from, to *types.Type) (fnname string, argType *types.Type, needsaddr bool) { - tkind := to.Tie() - switch from.Tie() { - case 'I': - if tkind == 'I' { - return "convI2I", types.Types[types.TINTER], false - } - case 'T': +// dataWordFuncName returns the name of the function used to convert a value of type "from" +// to the data word of an interface. +// argType is the type the argument needs to be coerced to. +// needsaddr reports whether the value should be passed (needaddr==false) or its address (needsaddr==true). +func dataWordFuncName(from *types.Type) (fnname string, argType *types.Type, needsaddr bool) { + if from.IsInterface() { + base.Fatalf("can only handle non-interfaces") + } + switch { + case from.Size() == 2 && from.Align == 2: + return "convT16", types.Types[types.TUINT16], false + case from.Size() == 4 && from.Align == 4 && !from.HasPointers(): + return "convT32", types.Types[types.TUINT32], false + case from.Size() == 8 && from.Align == types.Types[types.TUINT64].Align && !from.HasPointers(): + return "convT64", types.Types[types.TUINT64], false + } + if sc := from.SoleComponent(); sc != nil { switch { - case from.Size() == 2 && from.Align == 2: - return "convT16", types.Types[types.TUINT16], false - case from.Size() == 4 && from.Align == 4 && !from.HasPointers(): - return "convT32", types.Types[types.TUINT32], false - case from.Size() == 8 && from.Align == types.Types[types.TUINT64].Align && !from.HasPointers(): - return "convT64", types.Types[types.TUINT64], false - } - if sc := from.SoleComponent(); sc != nil { - switch { - case sc.IsString(): - return "convTstring", types.Types[types.TSTRING], false - case sc.IsSlice(): - return "convTslice", types.NewSlice(types.Types[types.TUINT8]), false // the element type doesn't matter - } + case sc.IsString(): + return "convTstring", types.Types[types.TSTRING], false + case sc.IsSlice(): + return "convTslice", types.NewSlice(types.Types[types.TUINT8]), false // the element type doesn't matter } + } - switch tkind { - case 'E': - if !from.HasPointers() { - return "convT2Enoptr", types.Types[types.TUNSAFEPTR], true - } - return "convT2E", types.Types[types.TUNSAFEPTR], true - case 'I': - if !from.HasPointers() { - return "convT2Inoptr", types.Types[types.TUNSAFEPTR], true - } - return "convT2I", types.Types[types.TUNSAFEPTR], true - } + if from.HasPointers() { + return "convT", types.Types[types.TUNSAFEPTR], true } - base.Fatalf("unknown conv func %c2%c", from.Tie(), to.Tie()) - panic("unreachable") + return "convTnoptr", types.Types[types.TUNSAFEPTR], true } // rtconvfn returns the parameter and result types that will be used by a diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go index f95b6f4639..26e225440a 100644 --- a/src/cmd/compile/internal/walk/expr.go +++ b/src/cmd/compile/internal/walk/expr.go @@ -212,10 +212,7 @@ func walkExpr1(n ir.Node, init *ir.Nodes) ir.Node { case ir.OCONVIDATA: n := n.(*ir.ConvExpr) - r := ir.NewUnaryExpr(n.Pos(), ir.OIDATA, walkConvInterface(n, init)) - r.SetType(types.Types[types.TUNSAFEPTR]) - r.SetTypecheck(1) - return r + return walkConvIData(n, init) case ir.OCONV, ir.OCONVNOP: n := n.(*ir.ConvExpr) diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go index c5fd0c1e1d..6e336f565c 100644 --- a/src/cmd/compile/internal/walk/order.go +++ b/src/cmd/compile/internal/walk/order.go @@ -1166,11 +1166,7 @@ func (o *orderState) expr1(n, lhs ir.Node) ir.Node { if n.X.Type().IsInterface() { return n } - to := n.Type() - if n.Op() == ir.OCONVIDATA { - to = types.NewInterface(types.LocalPkg, nil) - } - if _, _, needsaddr := convFuncName(n.X.Type(), to); needsaddr || isStaticCompositeLiteral(n.X) { + if _, _, needsaddr := dataWordFuncName(n.X.Type()); needsaddr || isStaticCompositeLiteral(n.X) { // Need a temp if we need to pass the address to the conversion function. // We also process static composite literal node here, making a named static global // whose address we can put directly in an interface (see OCONVIFACE/OCONVIDATA case in walk). diff --git a/src/runtime/iface.go b/src/runtime/iface.go index 79a49c0dff..3d1d9d6ba1 100644 --- a/src/runtime/iface.go +++ b/src/runtime/iface.go @@ -316,20 +316,30 @@ var ( // The convXXX functions succeed on a nil input, whereas the assertXXX // functions fail on a nil input. -func convT2E(t *_type, elem unsafe.Pointer) (e eface) { +// convT converts a value of type t, which is pointed to by v, to a pointer that can +// be used as the second word of an interface value. +func convT(t *_type, v unsafe.Pointer) unsafe.Pointer { if raceenabled { - raceReadObjectPC(t, elem, getcallerpc(), abi.FuncPCABIInternal(convT2E)) + raceReadObjectPC(t, v, getcallerpc(), abi.FuncPCABIInternal(convT)) } if msanenabled { - msanread(elem, t.size) + msanread(v, t.size) } x := mallocgc(t.size, t, true) - // TODO: We allocate a zeroed object only to overwrite it with actual data. - // Figure out how to avoid zeroing. Also below in convT2Eslice, convT2I, convT2Islice. - typedmemmove(t, x, elem) - e._type = t - e.data = x - return + typedmemmove(t, x, v) + return x +} +func convTnoptr(t *_type, v unsafe.Pointer) unsafe.Pointer { + // TODO: maybe take size instead of type? + if raceenabled { + raceReadObjectPC(t, v, getcallerpc(), abi.FuncPCABIInternal(convTnoptr)) + } + if msanenabled { + msanread(v, t.size) + } + x := mallocgc(t.size, t, false) + memmove(x, v, t.size) + return x } func convT16(val uint16) (x unsafe.Pointer) { @@ -389,63 +399,16 @@ func convTslice(val []byte) (x unsafe.Pointer) { return } -func convT2Enoptr(t *_type, elem unsafe.Pointer) (e eface) { - if raceenabled { - raceReadObjectPC(t, elem, getcallerpc(), abi.FuncPCABIInternal(convT2Enoptr)) - } - if msanenabled { - msanread(elem, t.size) - } - x := mallocgc(t.size, t, false) - memmove(x, elem, t.size) - e._type = t - e.data = x - return -} - -func convT2I(tab *itab, elem unsafe.Pointer) (i iface) { - t := tab._type - if raceenabled { - raceReadObjectPC(t, elem, getcallerpc(), abi.FuncPCABIInternal(convT2I)) - } - if msanenabled { - msanread(elem, t.size) - } - x := mallocgc(t.size, t, true) - typedmemmove(t, x, elem) - i.tab = tab - i.data = x - return -} - -func convT2Inoptr(tab *itab, elem unsafe.Pointer) (i iface) { - t := tab._type - if raceenabled { - raceReadObjectPC(t, elem, getcallerpc(), abi.FuncPCABIInternal(convT2Inoptr)) - } - if msanenabled { - msanread(elem, t.size) - } - x := mallocgc(t.size, t, false) - memmove(x, elem, t.size) - i.tab = tab - i.data = x - return -} - -func convI2I(inter *interfacetype, i iface) (r iface) { - tab := i.tab - if tab == nil { - return +// convI2I returns the new itab to be used for the destination value +// when converting a value with itab src to the dst interface. +func convI2I(dst *interfacetype, src *itab) *itab { + if src == nil { + return nil } - if tab.inter == inter { - r.tab = tab - r.data = i.data - return + if src.inter == dst { + return src } - r.tab = getitab(inter, tab._type, false) - r.data = i.data - return + return getitab(dst, src._type, false) } func assertI2I(inter *interfacetype, tab *itab) *itab { diff --git a/test/devirt.go b/test/devirt.go index e0149d8229..d5c815222e 100644 --- a/test/devirt.go +++ b/test/devirt.go @@ -31,9 +31,8 @@ func main() { panic("not 3") } - // Can't do types that aren't "direct" interfaces (yet). r = indirectiface{3, 4, 5} - if r.Value() != 12 { + if r.Value() != 12 { // ERROR "de-virtualizing call$" panic("not 12") } } diff --git a/test/fixedbugs/issue20250.go b/test/fixedbugs/issue20250.go index 1a513bea56..aed7b25d1b 100644 --- a/test/fixedbugs/issue20250.go +++ b/test/fixedbugs/issue20250.go @@ -17,7 +17,7 @@ type T struct { func f(a T) { // ERROR "live at entry to f: a" var e interface{} // ERROR "stack object e interface \{\}$" func() { // ERROR "live at entry to f.func1: a &e" - e = a.s // ERROR "live at call to convT2E: &e" "stack object a T$" + e = a.s // ERROR "live at call to convT: &e" "stack object a T$" }() // Before the fix, both a and e were live at the previous line. _ = e diff --git a/test/live.go b/test/live.go index 856e56f3d2..6130f7f069 100644 --- a/test/live.go +++ b/test/live.go @@ -144,8 +144,8 @@ var i9 interface{} func f9() bool { g8() x := i9 - y := interface{}(g18()) // ERROR "live at call to convT2E: x.data$" "live at call to g18: x.data$" "stack object .autotmp_[0-9]+ \[2\]string$" - i9 = y // make y escape so the line above has to call convT2E + y := interface{}(g18()) // ERROR "live at call to convT: x.data$" "live at call to g18: x.data$" "stack object .autotmp_[0-9]+ \[2\]string$" + i9 = y // make y escape so the line above has to call convT return x != y } @@ -503,7 +503,7 @@ func f31(b1, b2, b3 bool) { g31(g18()) // ERROR "stack object .autotmp_[0-9]+ \[2\]string$" } if b2 { - h31(g18()) // ERROR "live at call to convT2E: .autotmp_[0-9]+$" "live at call to newobject: .autotmp_[0-9]+$" + h31(g18()) // ERROR "live at call to convT: .autotmp_[0-9]+$" "live at call to newobject: .autotmp_[0-9]+$" } if b3 { panic(g18()) diff --git a/test/live_regabi.go b/test/live_regabi.go index d362ee287d..2883b83bae 100644 --- a/test/live_regabi.go +++ b/test/live_regabi.go @@ -139,8 +139,8 @@ var i9 interface{} func f9() bool { g8() x := i9 - y := interface{}(g18()) // ERROR "live at call to convT2E: x.data$" "live at call to g18: x.data$" "stack object .autotmp_[0-9]+ \[2\]string$" - i9 = y // make y escape so the line above has to call convT2E + y := interface{}(g18()) // ERROR "live at call to convT: x.data$" "live at call to g18: x.data$" "stack object .autotmp_[0-9]+ \[2\]string$" + i9 = y // make y escape so the line above has to call convT return x != y } @@ -498,7 +498,7 @@ func f31(b1, b2, b3 bool) { g31(g18()) // ERROR "stack object .autotmp_[0-9]+ \[2\]string$" } if b2 { - h31(g18()) // ERROR "live at call to convT2E: .autotmp_[0-9]+$" "live at call to newobject: .autotmp_[0-9]+$" + h31(g18()) // ERROR "live at call to convT: .autotmp_[0-9]+$" "live at call to newobject: .autotmp_[0-9]+$" } if b3 { panic(g18()) -- GitLab From ca3c6985cd143f170699d22ed984b7eed0f68e4d Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 3 Aug 2021 08:10:17 -0700 Subject: [PATCH 0635/2500] [dev.typeparams] cmd/compile: implement generic type switches Add a new dynamicType node, which is used as a case entry when the type being switched to is generic. Change-Id: Ice77c6f224b8fdd3ff574fdf4a8ea5f6c7ddbe75 Reviewed-on: https://go-review.googlesource.com/c/go/+/339429 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall Reviewed-by: Dan Scales --- src/cmd/compile/internal/escape/expr.go | 3 ++ src/cmd/compile/internal/ir/expr.go | 9 ++++ src/cmd/compile/internal/ir/node.go | 8 ++-- src/cmd/compile/internal/ir/node_gen.go | 28 ++++++++++++ src/cmd/compile/internal/ir/op_string.go | 15 ++++--- src/cmd/compile/internal/ir/type.go | 14 ++++++ src/cmd/compile/internal/noder/irgen.go | 4 ++ src/cmd/compile/internal/noder/stencil.go | 50 +++++++++++++++++++++ src/cmd/compile/internal/noder/transform.go | 4 ++ src/cmd/compile/internal/typecheck/stmt.go | 4 ++ src/cmd/compile/internal/walk/switch.go | 45 +++++++++++++++---- test/typeparam/typeswitch1.go | 29 ++++++++++++ test/typeparam/typeswitch1.out | 5 +++ test/typeparam/typeswitch2.go | 31 +++++++++++++ test/typeparam/typeswitch2.out | 5 +++ test/typeparam/typeswitch3.go | 35 +++++++++++++++ test/typeparam/typeswitch3.out | 3 ++ test/typeparam/typeswitch4.go | 33 ++++++++++++++ test/typeparam/typeswitch4.out | 3 ++ test/typeparam/typeswitch5.go | 28 ++++++++++++ test/typeparam/typeswitch5.out | 4 ++ 21 files changed, 342 insertions(+), 18 deletions(-) create mode 100644 test/typeparam/typeswitch1.go create mode 100644 test/typeparam/typeswitch1.out create mode 100644 test/typeparam/typeswitch2.go create mode 100644 test/typeparam/typeswitch2.out create mode 100644 test/typeparam/typeswitch3.go create mode 100644 test/typeparam/typeswitch3.out create mode 100644 test/typeparam/typeswitch4.go create mode 100644 test/typeparam/typeswitch4.out create mode 100644 test/typeparam/typeswitch5.go create mode 100644 test/typeparam/typeswitch5.out diff --git a/src/cmd/compile/internal/escape/expr.go b/src/cmd/compile/internal/escape/expr.go index 4a6304d47a..62afb5b928 100644 --- a/src/cmd/compile/internal/escape/expr.go +++ b/src/cmd/compile/internal/escape/expr.go @@ -262,6 +262,9 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) { // Arguments of OADDSTR never escape; // runtime.concatstrings makes sure of that. e.discards(n.List) + + case ir.ODYNAMICTYPE: + // Nothing to do - argument is a *runtime._type (+ maybe a *runtime.itab) pointing to static data section } } diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 9c5fbbc9aa..dc28483907 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -700,6 +700,15 @@ func NewDynamicTypeAssertExpr(pos src.XPos, op Op, x, t Node) *DynamicTypeAssert return n } +func (n *DynamicTypeAssertExpr) SetOp(op Op) { + switch op { + default: + panic(n.no("SetOp " + op.String())) + case ODYNAMICDOTTYPE, ODYNAMICDOTTYPE2: + n.op = op + } +} + // A UnaryExpr is a unary expression Op X, // or Op(X) for a builtin function that does not end up being a call. type UnaryExpr struct { diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index e5f0c38f86..f071cb78ce 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -258,7 +258,8 @@ const ( OBREAK // break [Label] // OCASE: case List: Body (List==nil means default) // For OTYPESW, List is a OTYPE node for the specified type (or OLITERAL - // for nil), and, if a type-switch variable is specified, Rlist is an + // for nil) or an ODYNAMICTYPE indicating a runtime type for generics. + // If a type-switch variable is specified, Var is an // ONAME for the version of the type-switch variable with the specified // type. OCASE @@ -320,8 +321,9 @@ const ( OLINKSYMOFFSET // offset within a name // opcodes for generics - ODYNAMICDOTTYPE - ODYNAMICDOTTYPE2 + ODYNAMICDOTTYPE // x = i.(T) where T is a type parameter (or derived from a type parameter) + ODYNAMICDOTTYPE2 // x, ok = i.(T) where T is a type parameter (or derived from a type parameter) + ODYNAMICTYPE // a type node for type switches (represents a dynamic target type for a type switch) // arch-specific opcodes OTAILCALL // tail call to another function diff --git a/src/cmd/compile/internal/ir/node_gen.go b/src/cmd/compile/internal/ir/node_gen.go index 56db6bb9cf..aa41c03beb 100644 --- a/src/cmd/compile/internal/ir/node_gen.go +++ b/src/cmd/compile/internal/ir/node_gen.go @@ -463,6 +463,34 @@ func (n *Decl) editChildren(edit func(Node) Node) { } } +func (n *DynamicType) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) } +func (n *DynamicType) copy() Node { + c := *n + c.init = copyNodes(c.init) + return &c +} +func (n *DynamicType) doChildren(do func(Node) bool) bool { + if doNodes(n.init, do) { + return true + } + if n.X != nil && do(n.X) { + return true + } + if n.ITab != nil && do(n.ITab) { + return true + } + return false +} +func (n *DynamicType) editChildren(edit func(Node) Node) { + editNodes(n.init, edit) + if n.X != nil { + n.X = edit(n.X).(Node) + } + if n.ITab != nil { + n.ITab = edit(n.ITab).(Node) + } +} + func (n *DynamicTypeAssertExpr) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) } func (n *DynamicTypeAssertExpr) copy() Node { c := *n diff --git a/src/cmd/compile/internal/ir/op_string.go b/src/cmd/compile/internal/ir/op_string.go index 7b08ee287a..b8cee71818 100644 --- a/src/cmd/compile/internal/ir/op_string.go +++ b/src/cmd/compile/internal/ir/op_string.go @@ -164,16 +164,17 @@ func _() { _ = x[OLINKSYMOFFSET-153] _ = x[ODYNAMICDOTTYPE-154] _ = x[ODYNAMICDOTTYPE2-155] - _ = x[OTAILCALL-156] - _ = x[OGETG-157] - _ = x[OGETCALLERPC-158] - _ = x[OGETCALLERSP-159] - _ = x[OEND-160] + _ = x[ODYNAMICTYPE-156] + _ = x[OTAILCALL-157] + _ = x[OGETG-158] + _ = x[OGETCALLERPC-159] + _ = x[OGETCALLERSP-160] + _ = x[OEND-161] } -const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESSLICE2ARRPTRASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVIDATACONVNOPCOPYDCLDCLFUNCDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECOVERFPRECVRUNESTRSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFUNSAFEADDUNSAFESLICEMETHEXPRMETHVALUEBLOCKBREAKCASECONTINUEDEFERFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWFUNCINSTTCHANTMAPTSTRUCTTINTERTFUNCTARRAYTSLICEINLCALLEFACEITABIDATASPTRCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKLINKSYMOFFSETDYNAMICDOTTYPEDYNAMICDOTTYPE2TAILCALLGETGGETCALLERPCGETCALLERSPEND" +const _Op_name = "XXXNAMENONAMETYPEPACKLITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESSLICE2ARRPTRASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVIDATACONVNOPCOPYDCLDCLFUNCDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECOVERFPRECVRUNESTRSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFUNSAFEADDUNSAFESLICEMETHEXPRMETHVALUEBLOCKBREAKCASECONTINUEDEFERFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWFUNCINSTTCHANTMAPTSTRUCTTINTERTFUNCTARRAYTSLICEINLCALLEFACEITABIDATASPTRCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKLINKSYMOFFSETDYNAMICDOTTYPEDYNAMICDOTTYPE2DYNAMICTYPETAILCALLGETGGETCALLERPCGETCALLERSPEND" -var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 136, 138, 141, 151, 158, 165, 172, 176, 180, 188, 196, 205, 208, 213, 220, 227, 233, 242, 250, 258, 264, 268, 277, 286, 293, 297, 300, 307, 315, 322, 328, 331, 337, 344, 352, 356, 363, 371, 373, 375, 377, 379, 381, 383, 388, 393, 401, 404, 413, 416, 420, 428, 435, 444, 457, 460, 463, 466, 469, 472, 475, 481, 484, 487, 493, 497, 500, 504, 509, 514, 520, 525, 529, 534, 542, 550, 556, 565, 576, 583, 592, 596, 603, 611, 615, 619, 623, 630, 637, 645, 651, 660, 671, 679, 688, 693, 698, 702, 710, 715, 719, 722, 730, 734, 736, 741, 743, 748, 754, 760, 766, 772, 780, 785, 789, 796, 802, 807, 813, 819, 826, 831, 835, 840, 844, 849, 857, 863, 870, 877, 883, 890, 903, 917, 932, 940, 944, 955, 966, 969} +var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 37, 39, 42, 48, 52, 58, 64, 73, 85, 94, 103, 115, 124, 136, 138, 141, 151, 158, 165, 172, 176, 180, 188, 196, 205, 208, 213, 220, 227, 233, 242, 250, 258, 264, 268, 277, 286, 293, 297, 300, 307, 315, 322, 328, 331, 337, 344, 352, 356, 363, 371, 373, 375, 377, 379, 381, 383, 388, 393, 401, 404, 413, 416, 420, 428, 435, 444, 457, 460, 463, 466, 469, 472, 475, 481, 484, 487, 493, 497, 500, 504, 509, 514, 520, 525, 529, 534, 542, 550, 556, 565, 576, 583, 592, 596, 603, 611, 615, 619, 623, 630, 637, 645, 651, 660, 671, 679, 688, 693, 698, 702, 710, 715, 719, 722, 730, 734, 736, 741, 743, 748, 754, 760, 766, 772, 780, 785, 789, 796, 802, 807, 813, 819, 826, 831, 835, 840, 844, 849, 857, 863, 870, 877, 883, 890, 903, 917, 932, 943, 951, 955, 966, 977, 980} func (i Op) String() string { if i >= Op(len(_Op_index)-1) { diff --git a/src/cmd/compile/internal/ir/type.go b/src/cmd/compile/internal/ir/type.go index 431468375a..63dd673dcd 100644 --- a/src/cmd/compile/internal/ir/type.go +++ b/src/cmd/compile/internal/ir/type.go @@ -319,3 +319,17 @@ func TypeNodeAt(pos src.XPos, t *types.Type) Ntype { } return newTypeNode(pos, t) } + +// A DynamicType represents the target type in a type switch. +type DynamicType struct { + miniExpr + X Node // a *runtime._type for the targeted type + ITab Node // for type switches from nonempty interfaces to non-interfaces, this is the itab for that pair. +} + +func NewDynamicType(pos src.XPos, x Node) *DynamicType { + n := &DynamicType{X: x} + n.pos = pos + n.op = ODYNAMICTYPE + return n +} diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index 571e294416..7bc8a6bcc3 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -107,6 +107,10 @@ type gfInfo struct { // Nodes in generic functions that are a conversion from a typeparam/derived // type to a specific interface. itabConvs []ir.Node + // For type switches on nonempty interfaces, a map from OTYPE entries of + // HasTParam type, to the interface type we're switching from. + // TODO: what if the type we're switching from is a shape type? + type2switchType map[ir.Node]*types.Type } // instInfo is information gathered on an gcshape (or fully concrete) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index b37f76dcee..5f2250d2f4 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1140,6 +1140,38 @@ func (subst *subster) node(n ir.Node) ir.Node { m = ir.NewDynamicTypeAssertExpr(dt.Pos(), op, dt.X, rt) m.SetType(dt.Type()) m.SetTypecheck(1) + case ir.OCASE: + if _, ok := x.(*ir.CommClause); ok { + // This is not a type switch. TODO: Should we use an OSWITCH case here instead of OCASE? + break + } + x := x.(*ir.CaseClause) + m := m.(*ir.CaseClause) + for i, c := range x.List { + if c.Op() == ir.OTYPE && c.Type().HasTParam() { + // Use a *runtime._type for the dynamic type. + ix := findDictType(subst.info, c.Type()) + assert(ix >= 0) + dt := ir.NewDynamicType(c.Pos(), getDictionaryEntry(c.Pos(), subst.info.dictParam, ix, subst.info.dictLen)) + + // For type switch from nonemoty interfaces to non-interfaces, we need an itab as well. + if _, ok := subst.info.gfInfo.type2switchType[c]; ok { + // Type switch from nonempty interface. We need a *runtime.itab + // for the dynamic type. + ix := -1 + for i, ic := range subst.info.gfInfo.itabConvs { + if ic == c { + ix = subst.info.startItabConv + i + break + } + } + assert(ix >= 0) + dt.ITab = getDictionaryEntry(c.Pos(), subst.info.dictParam, ix, subst.info.dictLen) + } + typed(m.List[i].Type(), dt) + m.List[i] = dt + } + } } return m } @@ -1483,6 +1515,9 @@ func (g *irgen) finalizeSyms() { case ir.OCONVIFACE: srctype = subst.Typ(n.(*ir.ConvExpr).X.Type()) dsttype = subst.Typ(n.Type()) + case ir.OTYPE: + srctype = subst.Typ(n.Type()) + dsttype = subst.Typ(info.type2switchType[n]) default: base.Fatalf("itab entry with unknown op %s", n.Op()) } @@ -1652,6 +1687,21 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo { ir.Visit(n1, visitFunc) } } + if n.Op() == ir.OSWITCH && n.(*ir.SwitchStmt).Tag != nil && n.(*ir.SwitchStmt).Tag.Op() == ir.OTYPESW && !n.(*ir.SwitchStmt).Tag.(*ir.TypeSwitchGuard).X.Type().IsEmptyInterface() { + for _, cc := range n.(*ir.SwitchStmt).Cases { + for _, c := range cc.List { + if c.Op() == ir.OTYPE && c.Type().HasTParam() { + // Type switch from a non-empty interface to a noninterface. + infoPrint(" Itab for type switch: %v\n", c) + info.itabConvs = append(info.itabConvs, c) + if info.type2switchType == nil { + info.type2switchType = map[ir.Node]*types.Type{} + } + info.type2switchType[c] = n.(*ir.SwitchStmt).Tag.(*ir.TypeSwitchGuard).X.Type() + } + } + } + } addType(&info, n, n.Type()) } diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index 61af92b62a..ff113877df 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -313,6 +313,10 @@ assignOK: r := r.(*ir.TypeAssertExpr) stmt.SetOp(ir.OAS2DOTTYPE) r.SetOp(ir.ODOTTYPE2) + case ir.ODYNAMICDOTTYPE: + r := r.(*ir.DynamicTypeAssertExpr) + stmt.SetOp(ir.OAS2DOTTYPE) + r.SetOp(ir.ODYNAMICDOTTYPE2) default: break assignOK } diff --git a/src/cmd/compile/internal/typecheck/stmt.go b/src/cmd/compile/internal/typecheck/stmt.go index 0143411822..c322d490e5 100644 --- a/src/cmd/compile/internal/typecheck/stmt.go +++ b/src/cmd/compile/internal/typecheck/stmt.go @@ -172,6 +172,10 @@ assignOK: r := r.(*ir.TypeAssertExpr) stmt.SetOp(ir.OAS2DOTTYPE) r.SetOp(ir.ODOTTYPE2) + case ir.ODYNAMICDOTTYPE: + r := r.(*ir.DynamicTypeAssertExpr) + stmt.SetOp(ir.OAS2DOTTYPE) + r.SetOp(ir.ODYNAMICDOTTYPE2) default: break assignOK } diff --git a/src/cmd/compile/internal/walk/switch.go b/src/cmd/compile/internal/walk/switch.go index 162de018f6..3705c5b192 100644 --- a/src/cmd/compile/internal/walk/switch.go +++ b/src/cmd/compile/internal/walk/switch.go @@ -360,10 +360,10 @@ func walkSwitchType(sw *ir.SwitchStmt) { } if singleType != nil && singleType.IsInterface() { - s.Add(ncase.Pos(), n1.Type(), caseVar, jmp) + s.Add(ncase.Pos(), n1, caseVar, jmp) caseVarInitialized = true } else { - s.Add(ncase.Pos(), n1.Type(), nil, jmp) + s.Add(ncase.Pos(), n1, nil, jmp) } } @@ -377,6 +377,17 @@ func walkSwitchType(sw *ir.SwitchStmt) { } val = ifaceData(ncase.Pos(), s.facename, singleType) } + if len(ncase.List) == 1 && ncase.List[0].Op() == ir.ODYNAMICTYPE { + dt := ncase.List[0].(*ir.DynamicType) + x := ir.NewDynamicTypeAssertExpr(ncase.Pos(), ir.ODYNAMICDOTTYPE, val, dt.X) + if dt.ITab != nil { + // TODO: make ITab a separate field in DynamicTypeAssertExpr? + x.T = dt.ITab + } + x.SetType(caseVar.Type()) + x.SetTypecheck(1) + val = x + } l := []ir.Node{ ir.NewDecl(ncase.Pos(), ir.ODCL, caseVar), ir.NewAssignStmt(ncase.Pos(), caseVar, val), @@ -446,7 +457,8 @@ type typeClause struct { body ir.Nodes } -func (s *typeSwitch) Add(pos src.XPos, typ *types.Type, caseVar *ir.Name, jmp ir.Node) { +func (s *typeSwitch) Add(pos src.XPos, n1 ir.Node, caseVar *ir.Name, jmp ir.Node) { + typ := n1.Type() var body ir.Nodes if caseVar != nil { l := []ir.Node{ @@ -462,9 +474,25 @@ func (s *typeSwitch) Add(pos src.XPos, typ *types.Type, caseVar *ir.Name, jmp ir // cv, ok = iface.(type) as := ir.NewAssignListStmt(pos, ir.OAS2, nil, nil) as.Lhs = []ir.Node{caseVar, s.okname} // cv, ok = - dot := ir.NewTypeAssertExpr(pos, s.facename, nil) - dot.SetType(typ) // iface.(type) - as.Rhs = []ir.Node{dot} + switch n1.Op() { + case ir.OTYPE: + // Static type assertion (non-generic) + dot := ir.NewTypeAssertExpr(pos, s.facename, nil) + dot.SetType(typ) // iface.(type) + as.Rhs = []ir.Node{dot} + case ir.ODYNAMICTYPE: + // Dynamic type assertion (generic) + dt := n1.(*ir.DynamicType) + dot := ir.NewDynamicTypeAssertExpr(pos, ir.ODYNAMICDOTTYPE, s.facename, dt.X) + if dt.ITab != nil { + dot.T = dt.ITab + } + dot.SetType(typ) + dot.SetTypecheck(1) + as.Rhs = []ir.Node{dot} + default: + base.Fatalf("unhandled type case %s", n1.Op()) + } appendWalkStmt(&body, as) // if ok { goto label } @@ -473,9 +501,10 @@ func (s *typeSwitch) Add(pos src.XPos, typ *types.Type, caseVar *ir.Name, jmp ir nif.Body = []ir.Node{jmp} body.Append(nif) - if !typ.IsInterface() { + if n1.Op() == ir.OTYPE && !typ.IsInterface() { + // Defer static, noninterface cases so they can be binary searched by hash. s.clauses = append(s.clauses, typeClause{ - hash: types.TypeHash(typ), + hash: types.TypeHash(n1.Type()), body: body, }) return diff --git a/test/typeparam/typeswitch1.go b/test/typeparam/typeswitch1.go new file mode 100644 index 0000000000..27161b3db8 --- /dev/null +++ b/test/typeparam/typeswitch1.go @@ -0,0 +1,29 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func f[T any](i interface{}) { + switch i.(type) { + case T: + println("T") + case int: + println("int") + case int32, int16: + println("int32/int16") + case struct { a, b T }: + println("struct{T,T}") + default: + println("other") + } +} +func main() { + f[float64](float64(6)) + f[float64](int(7)) + f[float64](int32(8)) + f[float64](struct{a, b float64}{a:1, b:2}) + f[float64](int8(9)) +} diff --git a/test/typeparam/typeswitch1.out b/test/typeparam/typeswitch1.out new file mode 100644 index 0000000000..4bdbccfddb --- /dev/null +++ b/test/typeparam/typeswitch1.out @@ -0,0 +1,5 @@ +T +int +int32/int16 +struct{T,T} +other diff --git a/test/typeparam/typeswitch2.go b/test/typeparam/typeswitch2.go new file mode 100644 index 0000000000..913c56321c --- /dev/null +++ b/test/typeparam/typeswitch2.go @@ -0,0 +1,31 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "reflect" + +func f[T any](i interface{}) { + switch x := i.(type) { + case T: + println("T", x) + case int: + println("int", x) + case int32, int16: + println("int32/int16", reflect.ValueOf(x).Int()) + case struct { a, b T }: + println("struct{T,T}", x.a, x.b) + default: + println("other", reflect.ValueOf(x).Int()) + } +} +func main() { + f[float64](float64(6)) + f[float64](int(7)) + f[float64](int32(8)) + f[float64](struct{a, b float64}{a:1, b:2}) + f[float64](int8(9)) +} diff --git a/test/typeparam/typeswitch2.out b/test/typeparam/typeswitch2.out new file mode 100644 index 0000000000..944cc04cc6 --- /dev/null +++ b/test/typeparam/typeswitch2.out @@ -0,0 +1,5 @@ +T +6.000000e+000 +int 7 +int32/int16 8 +struct{T,T} +1.000000e+000 +2.000000e+000 +other 9 diff --git a/test/typeparam/typeswitch3.go b/test/typeparam/typeswitch3.go new file mode 100644 index 0000000000..6ab0301140 --- /dev/null +++ b/test/typeparam/typeswitch3.go @@ -0,0 +1,35 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type I interface { foo() int } + +type myint int + +func (x myint) foo() int { return int(x) } + +type myfloat float64 +func (x myfloat) foo() int { return int(x) } + +type myint32 int32 +func (x myint32) foo() int { return int(x) } + +func f[T I](i I) { + switch x := i.(type) { + case T: + println("T", x.foo()) + case myint: + println("myint", x.foo()) + default: + println("other", x.foo()) + } +} +func main() { + f[myfloat](myint(6)) + f[myfloat](myfloat(7)) + f[myfloat](myint32(8)) +} diff --git a/test/typeparam/typeswitch3.out b/test/typeparam/typeswitch3.out new file mode 100644 index 0000000000..2c69c72c30 --- /dev/null +++ b/test/typeparam/typeswitch3.out @@ -0,0 +1,3 @@ +myint 6 +T 7 +other 8 diff --git a/test/typeparam/typeswitch4.go b/test/typeparam/typeswitch4.go new file mode 100644 index 0000000000..6113026b65 --- /dev/null +++ b/test/typeparam/typeswitch4.go @@ -0,0 +1,33 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type I interface { foo() int } + +type myint int + +func (x myint) foo() int {return int(x)} + +type myfloat float64 +func (x myfloat) foo() int {return int(x)} + +type myint32 int32 +func (x myint32) foo() int { return int(x) } + +func f[T I](i I) { + switch x := i.(type) { + case T, myint32: + println("T/myint32", x.foo()) + default: + println("other", x.foo()) + } +} +func main() { + f[myfloat](myint(6)) + f[myfloat](myfloat(7)) + f[myfloat](myint32(8)) +} diff --git a/test/typeparam/typeswitch4.out b/test/typeparam/typeswitch4.out new file mode 100644 index 0000000000..b0d54077c9 --- /dev/null +++ b/test/typeparam/typeswitch4.out @@ -0,0 +1,3 @@ +other 6 +T/myint32 7 +T/myint32 8 diff --git a/test/typeparam/typeswitch5.go b/test/typeparam/typeswitch5.go new file mode 100644 index 0000000000..1fc6e0a14e --- /dev/null +++ b/test/typeparam/typeswitch5.go @@ -0,0 +1,28 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type myint int +func (x myint) foo() int {return int(x)} + +type myfloat float64 +func (x myfloat) foo() float64 {return float64(x) } + +func f[T any](i interface{}) { + switch x := i.(type) { + case interface { foo() T }: + println("fooer", x.foo()) + default: + println("other") + } +} +func main() { + f[int](myint(6)) + f[int](myfloat(7)) + f[float64](myint(8)) + f[float64](myfloat(9)) +} diff --git a/test/typeparam/typeswitch5.out b/test/typeparam/typeswitch5.out new file mode 100644 index 0000000000..6b4cb4416f --- /dev/null +++ b/test/typeparam/typeswitch5.out @@ -0,0 +1,4 @@ +fooer 6 +other +other +fooer +9.000000e+000 -- GitLab From 9f4d6a83594a04f0fc82c33f373b7e7bcf64f7f2 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Fri, 6 Aug 2021 13:24:14 -0700 Subject: [PATCH 0636/2500] [dev.typeparams] cmd/compile: call transformArgs before early typecheckaste in noder In the cases where we do an early call to typecheckaste() in noder to expose CONVIFACE nodes, we need a preceding call to transformArgs(). This is needed to allow typecheckaste() to run correctly, in the case of f(g()), where g has multiple return values. I also cleaned up the code a bit and commented the code in Call(), and we do the call to typecheckaste() in several more cases. In stencil.go:stencil(), I moved the transformCall earlier for the OCALLMETH/ODOTMETH case, just as I did in my previous CL for OCALL/OFUNCINST. By doing this, transformArgs no longer needs to deal with the extra dictionary args. Therefore, I was able to simply transformArgs() to look like typecheckargs() again, and make use of RewriteMultiValue directly. Updates #47514 Change-Id: I49eb82ac05707e50c2e2fb03e39458a70491d406 Reviewed-on: https://go-review.googlesource.com/c/go/+/340531 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/helpers.go | 45 ++++++------- src/cmd/compile/internal/noder/stencil.go | 11 ++-- src/cmd/compile/internal/noder/stmt.go | 1 + src/cmd/compile/internal/noder/transform.go | 70 +++------------------ test/typeparam/issue47514b.go | 19 ++++++ 5 files changed, 55 insertions(+), 91 deletions(-) create mode 100644 test/typeparam/issue47514b.go diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index 2b00a9d7a6..b9dbd030af 100644 --- a/src/cmd/compile/internal/noder/helpers.go +++ b/src/cmd/compile/internal/noder/helpers.go @@ -171,39 +171,34 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) } } - if fun.Type().HasTParam() { + if fun.Type().HasTParam() || fun.Op() == ir.OXDOT || fun.Op() == ir.OFUNCINST { // If the fun arg is or has a type param, we can't do all the - // transformations, since we may not have needed properties yet. - // (e.g. number of return values, etc). However, if we do have the - // function type (even though it is parameterized), then can add in - // any needed CONVIFACE nodes. We can't do anything if fun is a type - // param (which is probably described by a structural constraint) + // transformations, since we may not have needed properties yet + // (e.g. number of return values, etc). The same applies if a fun + // which is an XDOT could not be transformed yet because of a generic + // type in the X of the selector expression. + // + // A function instantiation (even if fully concrete) shouldn't be + // transformed yet, because we need to add the dictionary during the + // transformation. + // + // However, if we have a function type (even though it is + // parameterized), then we can add in any needed CONVIFACE nodes via + // typecheckaste(). We need to call transformArgs() to deal first + // with the f(g(()) case where g returns multiple return values. We + // can't do anything if fun is a type param (which is probably + // described by a structural constraint) if fun.Type().Kind() == types.TFUNC { + transformArgs(n) typecheckaste(ir.OCALL, fun, n.IsDDD, fun.Type().Params(), n.Args, true) } return typed(typ, n) } - if fun.Op() == ir.OXDOT { - if !fun.(*ir.SelectorExpr).X.Type().HasTParam() { - base.FatalfAt(pos, "Expecting type param receiver in %v", fun) - } - // For methods called in a generic function, don't do any extra - // transformations. We will do those later when we create the - // instantiated function and have the correct receiver type. - typed(typ, n) - return n - } - if fun.Op() != ir.OFUNCINST { - // If no type params, do the normal call transformations. This - // will convert OCALL to OCALLFUNC. - typed(typ, n) - transformCall(n) - return n - } - - // Leave the op as OCALL, which indicates the call still needs typechecking. + // If no type params, do the normal call transformations. This + // will convert OCALL to OCALLFUNC. typed(typ, n) + transformCall(n) return n } diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 5f2250d2f4..23e8090136 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -161,18 +161,21 @@ func (g *irgen) stencil() { } } + // Transform the Call now, which changes OCALL + // to OCALLFUNC and does typecheckaste/assignconvfn. + transformCall(call) + st := g.getInstantiation(gf, targs, true) dictValue, usingSubdict := g.getDictOrSubdict(declInfo, n, gf, targs, true) // We have to be using a subdictionary, since this is // a generic method call. assert(usingSubdict) - call.SetOp(ir.OCALL) + // Transform to a function call, by appending the + // dictionary and the receiver to the args. + call.SetOp(ir.OCALLFUNC) call.X = st.Nname call.Args.Prepend(dictValue, meth.X) - // Transform the Call now, which changes OCALL - // to OCALLFUNC and does typecheckaste/assignconvfn. - transformCall(call) modified = true } }) diff --git a/src/cmd/compile/internal/noder/stmt.go b/src/cmd/compile/internal/noder/stmt.go index 5af4a2da9c..1949f56095 100644 --- a/src/cmd/compile/internal/noder/stmt.go +++ b/src/cmd/compile/internal/noder/stmt.go @@ -129,6 +129,7 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { // Delay transforming the return statement if any of the // return values have a type param. if !ir.HasNamedResults(ir.CurFunc) { + transformArgs(n) // But add CONVIFACE nodes where needed if // any of the return values have interface type. typecheckaste(ir.ORETURN, nil, false, ir.CurFunc.Type().Results(), n.Results, true) diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index ff113877df..e1eeb8e739 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -365,7 +365,7 @@ assignOK: } } -// Corresponds to, but slightly more general than, typecheck.typecheckargs. +// Corresponds to typecheck.typecheckargs. Really just deals with multi-value calls. func transformArgs(n ir.InitNode) { var list []ir.Node switch n := n.(type) { @@ -379,76 +379,22 @@ func transformArgs(n ir.InitNode) { case *ir.ReturnStmt: list = n.Results } - - // Look to see if we have any multi-return functions as arguments. - extra := 0 - for _, arg := range list { - t := arg.Type() - if t.IsFuncArgStruct() { - num := t.Fields().Len() - if num <= 1 { - base.Fatalf("multi-return type with only %d parts", num) - } - extra += num - 1 - } - } - // If not, nothing to do. - if extra == 0 { + if len(list) != 1 { return } - // Rewrite f(..., g(), ...) into t1, ..., tN = g(); f(..., t1, ..., tN, ...). + t := list[0].Type() + if t == nil || !t.IsFuncArgStruct() { + return + } // Save n as n.Orig for fmt.go. if ir.Orig(n) == n { n.(ir.OrigNode).SetOrig(ir.SepCopy(n)) } - // If we're outside of function context, then this call will - // be executed during the generated init function. However, - // init.go hasn't yet created it. Instead, associate the - // temporary variables with InitTodoFunc for now, and init.go - // will reassociate them later when it's appropriate. - static := ir.CurFunc == nil - if static { - ir.CurFunc = typecheck.InitTodoFunc - } - - // Expand multi-return function calls. - // The spec only allows a multi-return function as an argument - // if it is the only argument. This code must handle calls to - // stenciled generic functions which have extra arguments - // (like the dictionary) so it must handle a slightly more general - // cases, like f(n, g()) where g is multi-return. - newList := make([]ir.Node, 0, len(list)+extra) - for _, arg := range list { - t := arg.Type() - if t.IsFuncArgStruct() { - as := ir.NewAssignListStmt(base.Pos, ir.OAS2, nil, []ir.Node{arg}) - for _, f := range t.FieldSlice() { - t := typecheck.Temp(f.Type) - as.PtrInit().Append(ir.NewDecl(base.Pos, ir.ODCL, t)) - as.Lhs.Append(t) - newList = append(newList, t) - } - transformAssign(as, as.Lhs, as.Rhs) - as.SetTypecheck(1) - n.PtrInit().Append(as) - } else { - newList = append(newList, arg) - } - } - - if static { - ir.CurFunc = nil - } - - switch n := n.(type) { - case *ir.CallExpr: - n.Args = newList - case *ir.ReturnStmt: - n.Results = newList - } + // Rewrite f(g()) into t1, t2, ... = g(); f(t1, t2, ...). + typecheck.RewriteMultiValueCall(n, list[0]) } // assignconvfn converts node n for assignment to type t. Corresponds to diff --git a/test/typeparam/issue47514b.go b/test/typeparam/issue47514b.go new file mode 100644 index 0000000000..5428a0edc5 --- /dev/null +++ b/test/typeparam/issue47514b.go @@ -0,0 +1,19 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func Do[T any](do func() (T, string)) { + _ = func() (T, string) { + return do() + } +} + +func main() { + Do[int](func() (int, string) { + return 3, "3" + }) +} -- GitLab From f5f79c47f900300e8ac962e73ae7c2c706489d67 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sat, 7 Aug 2021 22:26:46 -0700 Subject: [PATCH 0637/2500] [dev.typeparams] cmd/compile: use types2.Constraint() rather than types2.Bound() types2.Constraint() returns the top-level constraint type, including any unions or other interface elements. Because of that, we needed to add/fix some code in the type substituter and generic type instantiater in the importer to deal with unions and non-method members of an interface. Also, NewUnion was not correctly setting the HasTParam flag. I also added a better error message when a symbol is not found in (*deadcodePass).decodeIfaceMethod(). Change-Id: Id3668dc596dce63690fa05a9e5e42295b5e2bbb5 Reviewed-on: https://go-review.googlesource.com/c/go/+/340670 Trust: Dan Scales Run-TryBot: Dan Scales Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/types.go | 2 +- src/cmd/compile/internal/typecheck/iimport.go | 12 +++++++++-- src/cmd/compile/internal/typecheck/subr.go | 20 ++++++++++++++++++- src/cmd/compile/internal/types/type.go | 9 +++++++++ src/cmd/link/internal/ld/deadcode.go | 3 +++ 5 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index 4e80b1a0ff..8d596e599e 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -227,7 +227,7 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { // Set g.typs[typ] in case the bound methods reference typ. g.typs[typ] = tp - bound := g.typ1(typ.Bound()) + bound := g.typ1(typ.Constraint()) tp.SetBound(bound) return tp diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 2e8b18c0b7..d5f4bba98b 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1858,18 +1858,26 @@ func substInstType(t *types.Type, baseType *types.Type, targs []*types.Type) { newfields := make([]*types.Field, baseType.Methods().Len()) for i, f := range baseType.Methods().Slice() { + if !f.IsMethod() || types.IsInterfaceMethod(f.Type) { + // Do a normal substitution if this is a non-method (which + // means this must be an interface used as a constraint) or + // an interface method. + t2 := subst.Typ(f.Type) + newfields[i] = types.NewField(f.Pos, f.Sym, t2) + continue + } recvType := f.Type.Recv().Type if recvType.IsPtr() { recvType = recvType.Elem() } // Substitute in the method using the type params used in the // method (not the type params in the definition of the generic type). - subst := Tsubster{ + msubst := Tsubster{ Tparams: recvType.RParams(), Targs: targs, SubstForwFunc: doInst, } - t2 := subst.Typ(f.Type) + t2 := msubst.Typ(f.Type) oldsym := f.Nname.Sym() newsym := MakeInstName(oldsym, targs, true) var nname *ir.Name diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index e840df56dc..e86c4c6bca 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1165,7 +1165,7 @@ func (ts *Tsubster) Typ(t *types.Type) *types.Type { case types.TINTER: newt = ts.tinter(t) - if newt == t { + if newt == t && !targsChanged { newt = nil } @@ -1197,6 +1197,24 @@ func (ts *Tsubster) Typ(t *types.Type) *types.Type { types.TUINT, types.TUINT8, types.TUINT16, types.TUINT32, types.TUINT64, types.TUINTPTR, types.TBOOL, types.TSTRING, types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128: newt = t.Underlying() + case types.TUNION: + nt := t.NumTerms() + newterms := make([]*types.Type, nt) + tildes := make([]bool, nt) + changed := false + for i := 0; i < nt; i++ { + term, tilde := t.Term(i) + tildes[i] = tilde + newterms[i] = ts.Typ(term) + if newterms[i] != term { + changed = true + } + } + if changed { + newt = types.NewUnion(newterms, tildes) + } + default: + panic(fmt.Sprintf("Bad type in (*TSubster).Typ: %v", t.Kind())) } if newt == nil { // Even though there were typeparams in the type, there may be no diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 099080f48f..875b0ba82f 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -1912,6 +1912,15 @@ func NewUnion(terms []*Type, tildes []bool) *Type { } t.Extra.(*Union).terms = terms t.Extra.(*Union).tildes = tildes + nt := len(terms) + for i := 0; i < nt; i++ { + if terms[i].HasTParam() { + t.SetHasTParam(true) + } + if terms[i].HasShape() { + t.SetHasShape(true) + } + } return t } diff --git a/src/cmd/link/internal/ld/deadcode.go b/src/cmd/link/internal/ld/deadcode.go index 416e5da398..dd5dafc21b 100644 --- a/src/cmd/link/internal/ld/deadcode.go +++ b/src/cmd/link/internal/ld/deadcode.go @@ -408,6 +408,9 @@ func (d *deadcodePass) decodeMethodSig(ldr *loader.Loader, arch *sys.Arch, symId // Decode the method of interface type symbol symIdx at offset off. func (d *deadcodePass) decodeIfaceMethod(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, off int64) methodsig { p := ldr.Data(symIdx) + if p == nil { + panic(fmt.Sprintf("missing symbol %q", ldr.SymName(symIdx))) + } if decodetypeKind(arch, p)&kindMask != kindInterface { panic(fmt.Sprintf("symbol %q is not an interface", ldr.SymName(symIdx))) } -- GitLab From 508624f359f168cab32814f63d29a4305fb01588 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sun, 8 Aug 2021 12:37:35 -0700 Subject: [PATCH 0638/2500] [dev.typeparams] cmd/compile/internal/types2: expand is only required for *Named types Now that the pointer identity for a *Named type doesn't change anymore when going from lazy instantiated to actually instantiated (= expanded) state, expand() only needs to be called when we deal with *Named types and only if we care about a *Named type's internals. Remove the expand function and respective calls for all types and replace with specific t.expand() method calls where t is a *Named. Change-Id: If82299360d60108b00adc4013b29399aec90b940 Reviewed-on: https://go-review.googlesource.com/c/go/+/340749 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/builtins.go | 2 +- src/cmd/compile/internal/types2/expr.go | 1 - src/cmd/compile/internal/types2/named.go | 9 --------- src/cmd/compile/internal/types2/predicates.go | 6 ++---- src/cmd/compile/internal/types2/signature.go | 2 +- src/cmd/compile/internal/types2/type.go | 5 ++++- src/cmd/compile/internal/types2/typexpr.go | 3 +-- src/cmd/compile/internal/types2/unify.go | 6 ++---- src/cmd/compile/internal/types2/union.go | 11 +++++------ 9 files changed, 16 insertions(+), 29 deletions(-) diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index eafe6e9eb8..da2dcf54aa 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -46,7 +46,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( default: // make argument getter xlist, _ := check.exprList(call.ArgList, false) - arg = func(x *operand, i int) { *x = *xlist[i]; x.typ = expand(x.typ) } + arg = func(x *operand, i int) { *x = *xlist[i] } nargs = len(xlist) // evaluate first argument, if present if nargs > 0 { diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 008c2446fc..3c2b10cd7e 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -682,7 +682,6 @@ func (check *Checker) convertUntyped(x *operand, target Type) { // If x is a constant operand, the returned constant.Value will be the // representation of x in this context. func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, constant.Value, errorCode) { - target = expand(target) if x.mode == invalid || isTyped(x.typ) || target == Typ[Invalid] { return x.typ, nil, 0 } diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index 14e073bfae..e099660481 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -279,12 +279,3 @@ func (n *Named) expand() { n.instance = nil } } - -// expand expands uninstantiated named types and leaves all other types alone. -// expand does not recurse. -func expand(typ Type) Type { - if t, _ := typ.(*Named); t != nil { - t.expand() - } - return typ -} diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index afef488b96..1541b3f416 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -140,10 +140,6 @@ func (p *ifacePair) identical(q *ifacePair) bool { // For changes to this code the corresponding changes should be made to unifier.nify. func identical(x, y Type, cmpTags bool, p *ifacePair) bool { - // types must be expanded for comparison - x = expand(x) - y = expand(y) - if x == y { return true } @@ -306,6 +302,8 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { // Two named types are identical if their type names originate // in the same type declaration. if y, ok := y.(*Named); ok { + x.expand() + y.expand() // TODO(gri) Why is x == y not sufficient? And if it is, // we can just return false here because x == y // is caught in the very beginning of this function. diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index 14112462e1..48b11b289c 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -208,7 +208,6 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] // TODO(gri) We should delay rtyp expansion to when we actually need the // receiver; thus all checks here should be delayed to later. rtyp, _ := deref(recv.typ) - rtyp = expand(rtyp) // spec: "The receiver type must be of the form T or *T where T is a type name." // (ignore invalid types - error was reported before) @@ -216,6 +215,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] var err string switch T := rtyp.(type) { case *Named: + T.expand() // spec: "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." diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 7ae2db3412..637829613b 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -114,7 +114,10 @@ func asInterface(t Type) *Interface { } func asNamed(t Type) *Named { - e, _ := expand(t).(*Named) + e, _ := t.(*Named) + if e != nil { + e.expand() + } return e } diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index fa4a1638b6..6a9eacd31d 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -446,8 +446,7 @@ func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def // make sure we check instantiation works at least once // and that the resulting type is valid check.later(func() { - t := expand(typ) - check.validType(t, nil) + check.validType(typ, nil) }) return typ diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index 75b9a12197..ae81382fb0 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -229,10 +229,6 @@ func (u *unifier) nifyEq(x, y Type, p *ifacePair) bool { // code the corresponding changes should be made here. // Must not be called directly from outside the unifier. func (u *unifier) nify(x, y Type, p *ifacePair) bool { - // types must be expanded for comparison - x = expand(x) - y = expand(y) - if !u.exact { // If exact unification is known to fail because we attempt to // match a type name against an unnamed type literal, consider @@ -436,6 +432,8 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { // return x.obj == y.obj // } if y, ok := y.(*Named); ok { + x.expand() + y.expand() // TODO(gri) This is not always correct: two types may have the same names // in the same package if one of them is nested in a function. // Extremely unlikely but we need an always correct solution. diff --git a/src/cmd/compile/internal/types2/union.go b/src/cmd/compile/internal/types2/union.go index 85aa3d9104..f61c37a6af 100644 --- a/src/cmd/compile/internal/types2/union.go +++ b/src/cmd/compile/internal/types2/union.go @@ -68,8 +68,7 @@ func parseUnion(check *Checker, tlist []syntax.Expr) Type { // Note: This is a quadratic algorithm, but unions tend to be short. check.later(func() { for i, t := range terms { - typ := expand(t.typ) - if typ == Typ[Invalid] { + if t.typ == Typ[Invalid] { continue } @@ -85,16 +84,16 @@ func parseUnion(check *Checker, tlist []syntax.Expr) Type { } } - u := under(typ) + u := under(t.typ) f, _ := u.(*Interface) if t.tilde { if f != nil { - check.errorf(x, "invalid use of ~ (%s is an interface)", typ) + check.errorf(x, "invalid use of ~ (%s is an interface)", t.typ) continue // don't report another error for t } - if !Identical(u, typ) { - check.errorf(x, "invalid use of ~ (underlying type of %s is %s)", typ, u) + if !Identical(u, t.typ) { + check.errorf(x, "invalid use of ~ (underlying type of %s is %s)", t.typ, u) continue // don't report another error for t } } -- GitLab From e4cfa2f6dad8c73e98a4149948ded424df9c8501 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 9 Aug 2021 10:53:43 -0700 Subject: [PATCH 0639/2500] [dev.typeparams] cmd/compile/internal/types2: parameterized functions must have a body Add the respective check and add missing bodies to tests. Use {} as body for functions that don't return a result. Use { panic(0) } as body for functions that return a result. For #47069. Change-Id: Ia5d7525c9c036baf8a955d13bff448401e08235e Reviewed-on: https://go-review.googlesource.com/c/go/+/340911 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/api_test.go | 44 +++++++++---------- src/cmd/compile/internal/types2/decl.go | 4 ++ .../internal/types2/testdata/check/issues.go2 | 6 +-- .../internal/types2/testdata/check/map2.go2 | 2 +- .../types2/testdata/check/mtypeparams.go2 | 2 +- .../types2/testdata/check/tinference.go2 | 8 ++-- .../types2/testdata/check/typeinst2.go2 | 14 +++--- .../types2/testdata/check/typeparams.go2 | 42 +++++++++--------- .../types2/testdata/examples/functions.go2 | 28 +++++++----- .../types2/testdata/examples/inference.go2 | 8 ++-- .../types2/testdata/examples/types.go2 | 14 +++--- .../types2/testdata/fixedbugs/issue39634.go2 | 6 +-- .../types2/testdata/fixedbugs/issue39723.go2 | 2 +- .../types2/testdata/fixedbugs/issue39725.go2 | 4 +- .../types2/testdata/fixedbugs/issue39976.go2 | 2 +- .../types2/testdata/fixedbugs/issue40038.go2 | 2 +- .../types2/testdata/fixedbugs/issue40056.go2 | 2 +- .../types2/testdata/fixedbugs/issue40684.go2 | 4 +- .../types2/testdata/fixedbugs/issue41124.go2 | 4 +- .../types2/testdata/fixedbugs/issue47127.go2 | 10 ++--- .../types2/testdata/fixedbugs/issue47411.go2 | 4 +- test/typeparam/smoketest.go | 6 +-- test/typeparam/tparam1.go | 14 +++--- test/typeparam/typelist.go | 8 ++-- 24 files changed, 124 insertions(+), 116 deletions(-) diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index c625bd4959..d8844956af 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -329,10 +329,10 @@ func TestTypesInfo(t *testing.T) { {brokenPkg + `x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string]invalid type`}, // parameterized functions - {genericPkg + `p0; func f[T any](T); var _ = f[int]`, `f`, `func[generic_p0.T₁ interface{}](generic_p0.T₁)`}, - {genericPkg + `p1; func f[T any](T); var _ = f[int]`, `f[int]`, `func(int)`}, - {genericPkg + `p2; func f[T any](T); func _() { f(42) }`, `f`, `func[generic_p2.T₁ interface{}](generic_p2.T₁)`}, - {genericPkg + `p3; func f[T any](T); func _() { f(42) }`, `f(42)`, `()`}, + {genericPkg + `p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[generic_p0.T₁ interface{}](generic_p0.T₁)`}, + {genericPkg + `p1; func f[T any](T) {}; var _ = f[int]`, `f[int]`, `func(int)`}, + {genericPkg + `p2; func f[T any](T) {}; func _() { f(42) }`, `f`, `func[generic_p2.T₁ interface{}](generic_p2.T₁)`}, + {genericPkg + `p3; func f[T any](T) {}; func _() { f(42) }`, `f(42)`, `()`}, // type parameters {genericPkg + `t0; type t[] int; var _ t`, `t`, `generic_t0.t`}, // t[] is a syntax error that is ignored in this test in favor of t @@ -389,60 +389,60 @@ func TestInferredInfo(t *testing.T) { targs []string sig string }{ - {genericPkg + `p0; func f[T any](T); func _() { f(42) }`, + {genericPkg + `p0; func f[T any](T) {}; func _() { f(42) }`, `f`, []string{`int`}, `func(int)`, }, - {genericPkg + `p1; func f[T any](T) T; func _() { f('@') }`, + {genericPkg + `p1; func f[T any](T) T { panic(0) }; func _() { f('@') }`, `f`, []string{`rune`}, `func(rune) rune`, }, - {genericPkg + `p2; func f[T any](...T) T; func _() { f(0i) }`, + {genericPkg + `p2; func f[T any](...T) T { panic(0) }; func _() { f(0i) }`, `f`, []string{`complex128`}, `func(...complex128) complex128`, }, - {genericPkg + `p3; func f[A, B, C any](A, *B, []C); func _() { f(1.2, new(string), []byte{}) }`, + {genericPkg + `p3; func f[A, B, C any](A, *B, []C) {}; func _() { f(1.2, new(string), []byte{}) }`, `f`, []string{`float64`, `string`, `byte`}, `func(float64, *string, []byte)`, }, - {genericPkg + `p4; func f[A, B any](A, *B, ...[]B); func _() { f(1.2, new(byte)) }`, + {genericPkg + `p4; func f[A, B any](A, *B, ...[]B) {}; func _() { f(1.2, new(byte)) }`, `f`, []string{`float64`, `byte`}, `func(float64, *byte, ...[]byte)`, }, // we don't know how to translate these but we can type-check them - {genericPkg + `q0; type T struct{}; func (T) m[P any](P); func _(x T) { x.m(42) }`, + {genericPkg + `q0; type T struct{}; func (T) m[P any](P) {}; func _(x T) { x.m(42) }`, `x.m`, []string{`int`}, `func(int)`, }, - {genericPkg + `q1; type T struct{}; func (T) m[P any](P) P; func _(x T) { x.m(42) }`, + {genericPkg + `q1; type T struct{}; func (T) m[P any](P) P { panic(0) }; func _(x T) { x.m(42) }`, `x.m`, []string{`int`}, `func(int) int`, }, - {genericPkg + `q2; type T struct{}; func (T) m[P any](...P) P; func _(x T) { x.m(42) }`, + {genericPkg + `q2; type T struct{}; func (T) m[P any](...P) P { panic(0) }; func _(x T) { x.m(42) }`, `x.m`, []string{`int`}, `func(...int) int`, }, - {genericPkg + `q3; type T struct{}; func (T) m[A, B, C any](A, *B, []C); func _(x T) { x.m(1.2, new(string), []byte{}) }`, + {genericPkg + `q3; type T struct{}; func (T) m[A, B, C any](A, *B, []C) {}; func _(x T) { x.m(1.2, new(string), []byte{}) }`, `x.m`, []string{`float64`, `string`, `byte`}, `func(float64, *string, []byte)`, }, - {genericPkg + `q4; type T struct{}; func (T) m[A, B any](A, *B, ...[]B); func _(x T) { x.m(1.2, new(byte)) }`, + {genericPkg + `q4; type T struct{}; func (T) m[A, B any](A, *B, ...[]B) {}; func _(x T) { x.m(1.2, new(byte)) }`, `x.m`, []string{`float64`, `byte`}, `func(float64, *byte, ...[]byte)`, }, - {genericPkg + `r0; type T[P any] struct{}; func (_ T[P]) m[Q any](Q); func _[P any](x T[P]) { x.m(42) }`, + {genericPkg + `r0; type T[P any] struct{}; func (_ T[P]) m[Q any](Q) {}; func _[P any](x T[P]) { x.m(42) }`, `x.m`, []string{`int`}, `func(int)`, @@ -454,38 +454,38 @@ func TestInferredInfo(t *testing.T) { // `func(float64)`, // }, - {genericPkg + `s1; func f[T any, P interface{~*T}](x T); func _(x string) { f(x) }`, + {genericPkg + `s1; func f[T any, P interface{~*T}](x T) {}; func _(x string) { f(x) }`, `f`, []string{`string`, `*string`}, `func(x string)`, }, - {genericPkg + `s2; func f[T any, P interface{~*T}](x []T); func _(x []int) { f(x) }`, + {genericPkg + `s2; func f[T any, P interface{~*T}](x []T) {}; func _(x []int) { f(x) }`, `f`, []string{`int`, `*int`}, `func(x []int)`, }, - {genericPkg + `s3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]](x []T); func _(x []int) { f(x) }`, + {genericPkg + `s3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]](x []T) {}; func _(x []int) { f(x) }`, `f`, []string{`int`, `chan<- int`}, `func(x []int)`, }, - {genericPkg + `s4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T); func _(x []int) { f(x) }`, + {genericPkg + `s4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T) {}; func _(x []int) { f(x) }`, `f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func(x []int)`, }, - {genericPkg + `t1; func f[T any, P interface{~*T}]() T; func _() { _ = f[string] }`, + {genericPkg + `t1; func f[T any, P interface{~*T}]() T { panic(0) }; func _() { _ = f[string] }`, `f`, []string{`string`, `*string`}, `func() string`, }, - {genericPkg + `t2; type C[T any] interface{~chan<- T}; func f[T any, P C[T]]() []T; func _() { _ = f[int] }`, + {genericPkg + `t2; type C[T any] interface{~chan<- T}; func f[T any, P C[T]]() []T { return nil }; func _() { _ = f[int] }`, `f`, []string{`int`, `chan<- int`}, `func() []int`, }, - {genericPkg + `t3; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T; func _() { _ = f[int] }`, + {genericPkg + `t3; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = f[int] }`, `f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func() []int`, diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index bb33c287f3..bfccbc5dbf 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -719,6 +719,10 @@ func (check *Checker) funcDecl(obj *Func, decl *declInfo) { check.funcType(sig, fdecl.Recv, fdecl.TParamList, fdecl.Type) obj.color_ = saved + if len(fdecl.TParamList) > 0 && fdecl.Body == nil { + check.softErrorf(fdecl, "parameterized function is missing function body") + } + // function body must be type-checked after global declarations // (functions implemented elsewhere have no body) if !check.conf.IgnoreFuncBodies && fdecl.Body != nil { diff --git a/src/cmd/compile/internal/types2/testdata/check/issues.go2 b/src/cmd/compile/internal/types2/testdata/check/issues.go2 index 1ede383ebe..effc2db7ae 100644 --- a/src/cmd/compile/internal/types2/testdata/check/issues.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/issues.go2 @@ -40,7 +40,7 @@ func _[T interface{ m() }](x *T) { x.m /* ERROR x\.m undefined */ () } -func f2[_ interface{ m1(); m2() }]() +func f2[_ interface{ m1(); m2() }]() {} type T struct{} func (T) m1() @@ -232,7 +232,7 @@ func _[T interface{ ~func() }](f T) { type sliceOf[E any] interface{ ~[]E } -func append[T interface{}, S sliceOf[T], T2 interface{}](s S, t ...T2) S +func append[T interface{}, S sliceOf[T], T2 interface{}](s S, t ...T2) S { panic(0) } var f func() var cancelSlice []context.CancelFunc @@ -240,7 +240,7 @@ var _ = append[context.CancelFunc, []context.CancelFunc, context.CancelFunc](can // A generic function must be instantiated with a type, not a value. -func g[T any](T) T +func g[T any](T) T { panic(0) } var _ = g[int] var _ = g[nil /* ERROR is not a type */ ] diff --git a/src/cmd/compile/internal/types2/testdata/check/map2.go2 b/src/cmd/compile/internal/types2/testdata/check/map2.go2 index 2833445662..be2c49f621 100644 --- a/src/cmd/compile/internal/types2/testdata/check/map2.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/map2.go2 @@ -114,7 +114,7 @@ func (it *Iterator[K, V]) Next() (K, V, bool) { // chans -func chans_Ranger[T any]() (*chans_Sender[T], *chans_Receiver[T]) +func chans_Ranger[T any]() (*chans_Sender[T], *chans_Receiver[T]) { panic(0) } // A sender is used to send values to a Receiver. type chans_Sender[T any] struct { diff --git a/src/cmd/compile/internal/types2/testdata/check/mtypeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/mtypeparams.go2 index c2f282bae1..1b406593f8 100644 --- a/src/cmd/compile/internal/types2/testdata/check/mtypeparams.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/mtypeparams.go2 @@ -10,7 +10,7 @@ package p type S struct{} -func (S) m[T any](v T) +func (S) m[T any](v T) {} // TODO(gri) Once we collect interface method type parameters // in the parser, we can enable these tests again. diff --git a/src/cmd/compile/internal/types2/testdata/check/tinference.go2 b/src/cmd/compile/internal/types2/testdata/check/tinference.go2 index 1b70981759..0afb77c1e4 100644 --- a/src/cmd/compile/internal/types2/testdata/check/tinference.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/tinference.go2 @@ -23,7 +23,7 @@ type any interface{} // f1(int(0), int(0)) // } -func f2[A any, B interface{~[]A}](A, B) +func f2[A any, B interface{~[]A}](A, B) {} func _() { f := f2[byte] f(byte(0), []byte{}) @@ -39,7 +39,7 @@ func _() { // f3(x, &x, &x) // } -func f4[A any, B interface{~[]C}, C interface{~*A}](A, B, C) +func f4[A any, B interface{~[]C}, C interface{~*A}](A, B, C) {} func _() { f := f4[int] var x int @@ -47,14 +47,14 @@ func _() { f4(x, []*int{}, &x) } -func f5[A interface{~struct{b B; c C}}, B any, C interface{~*B}](x B) A +func f5[A interface{~struct{b B; c C}}, B any, C interface{~*B}](x B) A { panic(0) } func _() { x := f5(1.2) var _ float64 = x.b var _ float64 = *x.c } -func f6[A any, B interface{~struct{f []A}}](B) A +func f6[A any, B interface{~struct{f []A}}](B) A { panic(0) } func _() { x := f6(struct{f []string}{}) var _ string = x diff --git a/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 b/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 index e90e4dde44..d087c26a47 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 @@ -85,7 +85,7 @@ type NumericAbs[T any] interface { Abs() T } -func AbsDifference[T NumericAbs[T]](x T) +func AbsDifference[T NumericAbs[T]](x T) { panic(0) } type OrderedAbs[T any] T @@ -97,7 +97,7 @@ func OrderedAbsDifference[T any](x T) { // same code, reduced to essence -func g[P interface{ m() P }](x P) +func g[P interface{ m() P }](x P) { panic(0) } type T4[P any] P @@ -205,7 +205,7 @@ type I0 interface { E0 } -func f0[T I0]() +func f0[T I0]() {} var _ = f0[int] var _ = f0[bool] var _ = f0[string] @@ -216,7 +216,7 @@ type I01 interface { E1 } -func f01[T I01]() +func f01[T I01]() {} var _ = f01[int] var _ = f01[bool /* ERROR does not satisfy I0 */ ] var _ = f01[string] @@ -228,7 +228,7 @@ type I012 interface { E2 } -func f012[T I012]() +func f012[T I012]() {} var _ = f012[int /* ERROR does not satisfy I012 */ ] var _ = f012[bool /* ERROR does not satisfy I012 */ ] var _ = f012[string /* ERROR does not satisfy I012 */ ] @@ -239,7 +239,7 @@ type I12 interface { E2 } -func f12[T I12]() +func f12[T I12]() {} var _ = f12[int /* ERROR does not satisfy I12 */ ] var _ = f12[bool /* ERROR does not satisfy I12 */ ] var _ = f12[string /* ERROR does not satisfy I12 */ ] @@ -250,7 +250,7 @@ type I0_ interface { ~int } -func f0_[T I0_]() +func f0_[T I0_]() {} var _ = f0_[int] var _ = f0_[bool /* ERROR does not satisfy I0_ */ ] var _ = f0_[string /* ERROR does not satisfy I0_ */ ] diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 index ba8e837346..1ad80b1e1b 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 @@ -15,9 +15,9 @@ func _[_ any /* ok here */ , _ interface{any /* ERROR constraint */ }](any /* ER func identity[T any](x T) T { return x } -func _[_ any](x int) int -func _[T any](T /* ERROR redeclared */ T)() -func _[T, T /* ERROR redeclared */ any]() +func _[_ any](x int) int { panic(0) } +func _[T any](T /* ERROR redeclared */ T)() {} +func _[T, T /* ERROR redeclared */ any]() {} // Constraints (incl. any) may be parenthesized. func _[_ (any)]() {} @@ -77,18 +77,18 @@ func new[T any]() *T { var _ = new /* ERROR cannot use generic function new */ var _ *int = new[int]() -func _[T any](map[T /* ERROR invalid map key type T \(missing comparable constraint\) */]int) // w/o constraint we don't know if T is comparable +func _[T any](map[T /* ERROR invalid map key type T \(missing comparable constraint\) */]int) {} // w/o constraint we don't know if T is comparable -func f1[T1 any](struct{T1 /* ERROR cannot be a .* type parameter */ }) int +func f1[T1 any](struct{T1 /* ERROR cannot be a .* type parameter */ }) int { panic(0) } var _ = f1[int](struct{T1}{}) type T1 = int -func f2[t1 any](struct{t1 /* ERROR cannot be a .* type parameter */ ; x float32}) int +func f2[t1 any](struct{t1 /* ERROR cannot be a .* type parameter */ ; x float32}) int { panic(0) } var _ = f2[t1](struct{t1; x float32}{}) type t1 = int -func f3[A, B, C any](A, struct{x B}, func(A, struct{x B}, *C)) int +func f3[A, B, C any](A, struct{x B}, func(A, struct{x B}, *C)) int { panic(0) } var _ = f3[int, rune, bool](1, struct{x rune}{}, nil) @@ -257,28 +257,28 @@ func _[ var _ = new() /* ERROR cannot infer T */ -func f4[A, B, C any](A, B) C +func f4[A, B, C any](A, B) C { panic(0) } var _ = f4(1, 2) /* ERROR cannot infer C */ var _ = f4[int, float32, complex128](1, 2) -func f5[A, B, C any](A, []*B, struct{f []C}) int +func f5[A, B, C any](A, []*B, struct{f []C}) int { panic(0) } var _ = f5[int, float32, complex128](0, nil, struct{f []complex128}{}) var _ = f5(0, nil, struct{f []complex128}{}) // ERROR cannot infer var _ = f5(0, []*float32{new[float32]()}, struct{f []complex128}{}) -func f6[A any](A, []A) int +func f6[A any](A, []A) int { panic(0) } var _ = f6(0, nil) -func f6nil[A any](A) int +func f6nil[A any](A) int { panic(0) } var _ = f6nil(nil) // ERROR cannot infer // type inference with variadic functions -func f7[T any](...T) T +func f7[T any](...T) T { panic(0) } var _ int = f7() /* ERROR cannot infer T */ var _ int = f7(1) @@ -291,7 +291,7 @@ var _ = f7(float64(1), 2.3) var _ = f7(1, 2.3 /* ERROR does not match */ ) var _ = f7(1.2, 3 /* ERROR does not match */ ) -func f8[A, B any](A, B, ...B) int +func f8[A, B any](A, B, ...B) int { panic(0) } var _ = f8(1) /* ERROR not enough arguments */ var _ = f8(1, 2.3) @@ -318,7 +318,7 @@ func (T) m3[P any]() {} type S1[P any] struct { f P } -func f9[P any](x S1[P]) +func f9[P any](x S1[P]) {} func _() { f9[int](S1[int]{42}) @@ -327,7 +327,7 @@ func _() { type S2[A, B, C any] struct{} -func f10[X, Y, Z any](a S2[X, int, Z], b S2[X, Y, bool]) +func f10[X, Y, Z any](a S2[X, int, Z], b S2[X, Y, bool]) {} func _[P any]() { f10[int, float32, string](S2[int, int, string]{}, S2[int, float32, bool]{}) @@ -338,7 +338,7 @@ func _[P any]() { // corner case for type inference // (was bug: after instanting f11, the type-checker didn't mark f11 as non-generic) -func f11[T any]() +func f11[T any]() {} func _() { f11[int]() @@ -346,7 +346,7 @@ func _() { // the previous example was extracted from -func f12[T interface{m() T}]() +func f12[T interface{m() T}]() {} type A[T any] T @@ -374,15 +374,15 @@ func _[T any] (x T) { type R0 struct{} -func (R0) _[T any](x T) -func (R0 /* ERROR invalid receiver */ ) _[R0 any]() // scope of type parameters starts at "func" +func (R0) _[T any](x T) {} +func (R0 /* ERROR invalid receiver */ ) _[R0 any]() {} // scope of type parameters starts at "func" type R1[A, B any] struct{} func (_ R1[A, B]) m0(A, B) -func (_ R1[A, B]) m1[T any](A, B, T) T +func (_ R1[A, B]) m1[T any](A, B, T) T { panic(0) } func (_ R1 /* ERROR not a generic type */ [R1, _]) _() -func (_ R1[A, B]) _[A /* ERROR redeclared */ any](B) +func (_ R1[A, B]) _[A /* ERROR redeclared */ any](B) {} func _() { var r R1[int, string] diff --git a/src/cmd/compile/internal/types2/testdata/examples/functions.go2 b/src/cmd/compile/internal/types2/testdata/examples/functions.go2 index 154d09f528..ef8953cb43 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/functions.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/functions.go2 @@ -66,7 +66,7 @@ var _ float64 = foo(42, []float64{1.0}, &s) // Type inference works in a straight-forward manner even // for variadic functions. -func variadic[A, B any](A, B, ...B) int +func variadic[A, B any](A, B, ...B) int { panic(0) } // var _ = variadic(1) // ERROR not enough arguments var _ = variadic(1, 2.3) @@ -118,9 +118,9 @@ func max[T interface{ ~int }](x ...T) T { // Thus even if a type can be inferred successfully, the function // call may not be valid. -func fboth[T any](chan T) -func frecv[T any](<-chan T) -func fsend[T any](chan<- T) +func fboth[T any](chan T) {} +func frecv[T any](<-chan T) {} +func fsend[T any](chan<- T) {} func _() { var both chan int @@ -140,9 +140,9 @@ func _() { fsend(send) } -func ffboth[T any](func(chan T)) -func ffrecv[T any](func(<-chan T)) -func ffsend[T any](func(chan<- T)) +func ffboth[T any](func(chan T)) {} +func ffrecv[T any](func(<-chan T)) {} +func ffsend[T any](func(chan<- T)) {} func _() { var both func(chan int) @@ -169,9 +169,9 @@ func _() { // assignment is permitted, parameter passing is permitted as well, // so type inference should be able to handle these cases well. -func g1[T any]([]T) -func g2[T any]([]T, T) -func g3[T any](*T, ...T) +func g1[T any]([]T) {} +func g2[T any]([]T, T) {} +func g3[T any](*T, ...T) {} func _() { type intSlize []int @@ -195,7 +195,7 @@ func _() { // Here's a realistic example. -func append[T any](s []T, t ...T) []T +func append[T any](s []T, t ...T) []T { panic(0) } func _() { var f func() @@ -208,8 +208,12 @@ func _() { // (that would indicate a slice type). Thus, generic functions cannot // have empty type parameter lists, either. This is a syntax error. -func h[] /* ERROR empty type parameter list */ () +func h[] /* ERROR empty type parameter list */ () {} func _() { h[] /* ERROR operand */ () } + +// Parameterized functions must have a function body. + +func _ /* ERROR missing function body */ [P any]() diff --git a/src/cmd/compile/internal/types2/testdata/examples/inference.go2 b/src/cmd/compile/internal/types2/testdata/examples/inference.go2 index 75d47d2c9b..e169aec746 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/inference.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/inference.go2 @@ -10,7 +10,7 @@ type Ordered interface { ~int|~float64|~string } -func min[T Ordered](x, y T) T +func min[T Ordered](x, y T) T { panic(0) } func _() { // min can be called with explicit instantiation. @@ -37,7 +37,7 @@ func _() { _ = min("foo", "bar") } -func mixed[T1, T2, T3 any](T1, T2, T3) +func mixed[T1, T2, T3 any](T1, T2, T3) {} func _() { // mixed can be called with explicit instantiation. @@ -54,7 +54,7 @@ func _() { mixed[int, string](1.1 /* ERROR cannot use 1.1 */ , "", false) } -func related1[Slice interface{~[]Elem}, Elem any](s Slice, e Elem) +func related1[Slice interface{~[]Elem}, Elem any](s Slice, e Elem) {} func _() { // related1 can be called with explicit instantiation. @@ -78,7 +78,7 @@ func _() { related1(si, "foo" /* ERROR cannot use "foo" */ ) } -func related2[Elem any, Slice interface{~[]Elem}](e Elem, s Slice) +func related2[Elem any, Slice interface{~[]Elem}](e Elem, s Slice) {} func _() { // related2 can be called with explicit instantiation. diff --git a/src/cmd/compile/internal/types2/testdata/examples/types.go2 b/src/cmd/compile/internal/types2/testdata/examples/types.go2 index 4ecc34dfa4..d662444ead 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/types.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/types.go2 @@ -216,15 +216,15 @@ type B0 interface {} type B1[_ any] interface{} type B2[_, _ any] interface{} -func _[T1 B0]() -func _[T1 B1[T1]]() -func _[T1 B2 /* ERROR cannot use generic type .* without instantiation */ ]() +func _[T1 B0]() {} +func _[T1 B1[T1]]() {} +func _[T1 B2 /* ERROR cannot use generic type .* without instantiation */ ]() {} -func _[T1, T2 B0]() -func _[T1 B1[T1], T2 B1[T2]]() -func _[T1, T2 B2 /* ERROR cannot use generic type .* without instantiation */ ]() +func _[T1, T2 B0]() {} +func _[T1 B1[T1], T2 B1[T2]]() {} +func _[T1, T2 B2 /* ERROR cannot use generic type .* without instantiation */ ]() {} -func _[T1 B0, T2 B1[T2]]() // here B1 applies to T2 +func _[T1 B0, T2 B1[T2]]() {} // here B1 applies to T2 // When the type argument is left away, the type bound is // instantiated for each type parameter with that type diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 index 5cb15e7e58..8d14f8acaf 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 @@ -50,7 +50,7 @@ func (G15 /* ERROR generic type .* without instantiation */ ) p() // crash 16 type Foo16[T any] r16 /* ERROR not a type */ -func r16[T any]() Foo16[Foo16[T]] +func r16[T any]() Foo16[Foo16[T]] { panic(0) } // crash 17 type Y17 interface{ c() } @@ -58,7 +58,7 @@ type Z17 interface { c() Y17 Y17 /* ERROR duplicate method */ } -func F17[T Z17](T) +func F17[T Z17](T) {} // crash 18 type o18[T any] []func(_ o18[[]_ /* ERROR cannot use _ */ ]) @@ -88,5 +88,5 @@ type T26 = interface{ F26[ /* ERROR cannot have type parameters */ Z any]() } func F26[Z any]() T26 { return F26 /* ERROR without instantiation */ /* ERROR missing method */ [] /* ERROR operand */ } // crash 27 -func e27[T any]() interface{ x27 /* ERROR not a type */ } +func e27[T any]() interface{ x27 /* ERROR not a type */ } { panic(0) } func x27() { e27( /* ERROR cannot infer T */ ) } \ No newline at end of file diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39723.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39723.go2 index 367b3f1360..d5311ed3e7 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39723.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39723.go2 @@ -6,4 +6,4 @@ package p // A constraint must be an interface; it cannot // be a type parameter, for instance. -func _[A interface{ ~int }, B A /* ERROR not an interface */ ]() +func _[A interface{ ~int }, B A /* ERROR not an interface */ ]() {} diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39725.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39725.go2 index e19b6770bf..62dc45a596 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39725.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39725.go2 @@ -4,13 +4,13 @@ package p -func f1[T1, T2 any](T1, T2, struct{a T1; b T2}) +func f1[T1, T2 any](T1, T2, struct{a T1; b T2}) {} func _() { f1(42, string("foo"), struct /* ERROR does not match inferred type struct\{a int; b string\} */ {a, b int}{}) } // simplified test case from issue -func f2[T any](_ []T, _ func(T)) +func f2[T any](_ []T, _ func(T)) {} func _() { f2([]string{}, func /* ERROR does not match inferred type func\(string\) */ (f []byte) {}) } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39976.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39976.go2 index 3db4eae012..d703da90a2 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39976.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39976.go2 @@ -7,7 +7,7 @@ package p type policy[K, V any] interface{} type LRU[K, V any] struct{} -func NewCache[K, V any](p policy[K, V]) +func NewCache[K, V any](p policy[K, V]) {} func _() { var lru LRU[int, string] diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue40038.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue40038.go2 index 8948d61caa..0981a335da 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue40038.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue40038.go2 @@ -8,7 +8,7 @@ type A[T any] int func (A[T]) m(A[T]) -func f[P interface{m(P)}]() +func f[P interface{m(P)}]() {} func _() { _ = f[A[int]] diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue40056.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue40056.go2 index 747aab49dd..a3f3eecca0 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue40056.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue40056.go2 @@ -10,6 +10,6 @@ func _() { type S struct {} -func NewS[T any]() *S +func NewS[T any]() *S { panic(0) } func (_ *S /* ERROR S is not a generic type */ [T]) M() diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue40684.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue40684.go2 index 0269c3a62c..58d0f69f65 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue40684.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue40684.go2 @@ -6,8 +6,8 @@ package p type T[_ any] int -func f[_ any]() -func g[_, _ any]() +func f[_ any]() {} +func g[_, _ any]() {} func _() { _ = f[T /* ERROR without instantiation */ ] diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2 index 60650432a4..4642ab60fc 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2 @@ -79,9 +79,9 @@ type T3[_, _, _ any] struct{} var _ T1[I2 /* ERROR interface contains type constraints */ ] var _ T3[int, I2 /* ERROR interface contains type constraints */ , float32] -func f1[_ any]() int +func f1[_ any]() int { panic(0) } var _ = f1[I2 /* ERROR interface contains type constraints */ ]() -func f3[_, _, _ any]() int +func f3[_, _, _ any]() int { panic(0) } var _ = f3[int, I2 /* ERROR interface contains type constraints */ , float32]() func _(x interface{}) { diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47127.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47127.go2 index 387c946957..108d600a38 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47127.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47127.go2 @@ -30,8 +30,8 @@ func _[P any]() { ) } -func _[P any, Q interface{ *P | []P | chan P | map[string]P }]() -func _[P any, Q interface{ P /* ERROR "cannot embed a type parameter" */ }]() -func _[P any, Q interface{ ~P /* ERROR "cannot embed a type parameter" */ }]() -func _[P any, Q interface{ int | P /* ERROR "cannot embed a type parameter" */ }]() -func _[P any, Q interface{ int | ~P /* ERROR "cannot embed a type parameter" */ }]() +func _[P any, Q interface{ *P | []P | chan P | map[string]P }]() {} +func _[P any, Q interface{ P /* ERROR "cannot embed a type parameter" */ }]() {} +func _[P any, Q interface{ ~P /* ERROR "cannot embed a type parameter" */ }]() {} +func _[P any, Q interface{ int | P /* ERROR "cannot embed a type parameter" */ }]() {} +func _[P any, Q interface{ int | ~P /* ERROR "cannot embed a type parameter" */ }]() {} diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go2 index 72968f9d43..77281a19a2 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go2 @@ -4,8 +4,8 @@ package p -func f[_ comparable]() -func g[_ interface{interface{comparable; ~int|~string}}]() +func f[_ comparable]() {} +func g[_ interface{interface{comparable; ~int|~string}}]() {} func _[P comparable, Q interface{ comparable; ~int|~string }, diff --git a/test/typeparam/smoketest.go b/test/typeparam/smoketest.go index eeda25964f..5243dc5c3c 100644 --- a/test/typeparam/smoketest.go +++ b/test/typeparam/smoketest.go @@ -9,9 +9,9 @@ package smoketest // type parameters for functions -func f1[P any]() -func f2[P1, P2 any, P3 any]() -func f3[P interface{}](x P, y T1[int]) +func f1[P any]() {} +func f2[P1, P2 any, P3 any]() {} +func f3[P interface{}](x P, y T1[int]) {} // function instantiations var _ = f1[int] diff --git a/test/typeparam/tparam1.go b/test/typeparam/tparam1.go index a196caf976..698877a6f0 100644 --- a/test/typeparam/tparam1.go +++ b/test/typeparam/tparam1.go @@ -24,17 +24,17 @@ type ( _[T1, T2 any, T3 any] struct{} ) -func _[T any]() -func _[T, T any]() // ERROR "T redeclared" -func _[T1, T2 any](x T1) T2 +func _[T any]() {} +func _[T, T any]() {} // ERROR "T redeclared" +func _[T1, T2 any](x T1) T2 { panic(0) } // Type parameters are visible from opening [ to end of function. type C interface{} -func _[T interface{}]() -func _[T C]() -func _[T struct{}]() // ERROR "not an interface" -func _[T interface{ m() T }]() +func _[T interface{}]() {} +func _[T C]() {} +func _[T struct{}]() {}// ERROR "not an interface" +func _[T interface{ m() T }]() {} func _[T1 interface{ m() T2 }, T2 interface{ m() T1 }]() { var _ T1 } diff --git a/test/typeparam/typelist.go b/test/typeparam/typelist.go index a68ae1b5cd..5ba14261ab 100644 --- a/test/typeparam/typelist.go +++ b/test/typeparam/typelist.go @@ -85,7 +85,7 @@ func f1x() { } */ -func f2[A any, B interface{ type []A }](_ A, _ B) +func f2[A any, B interface{ type []A }](_ A, _ B) {} func f2x() { f := f2[byte] f(byte(0), []byte{}) @@ -105,7 +105,7 @@ func f3x() { } */ -func f4[A any, B interface{ type []C }, C interface{ type *A }](_ A, _ B, c C) +func f4[A any, B interface{ type []C }, C interface{ type *A }](_ A, _ B, c C) {} func f4x() { f := f4[int] var x int @@ -118,14 +118,14 @@ func f5[A interface { b B c C } -}, B any, C interface{ type *B }](x B) A +}, B any, C interface{ type *B }](x B) A { panic(0) } func f5x() { x := f5(1.2) var _ float64 = x.b var _ float64 = *x.c } -func f6[A any, B interface{ type struct{ f []A } }](B) A +func f6[A any, B interface{ type struct{ f []A } }](B) A { panic(0) } func f6x() { x := f6(struct{ f []string }{}) var _ string = x -- GitLab From 2fbf6aafe7de215a1d03e14aa488aa8fd31f56a7 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Mon, 9 Aug 2021 11:40:46 -0700 Subject: [PATCH 0640/2500] [dev.typeparams] cmd/compile: handle interface type parameters in type switches Change-Id: I9bba21a64d7e9f42395b6fcdf8aa3ca01cf131dc Reviewed-on: https://go-review.googlesource.com/c/go/+/340912 Trust: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 30 ++++++++++-------- test/typeparam/typeswitch6.go | 30 ++++++++++++++++++ test/typeparam/typeswitch6.out | 5 +++ test/typeparam/typeswitch7.go | 37 +++++++++++++++++++++++ test/typeparam/typeswitch7.out | 3 ++ 5 files changed, 93 insertions(+), 12 deletions(-) create mode 100644 test/typeparam/typeswitch6.go create mode 100644 test/typeparam/typeswitch6.out create mode 100644 test/typeparam/typeswitch7.go create mode 100644 test/typeparam/typeswitch7.out diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 23e8090136..6736f128e3 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1157,19 +1157,21 @@ func (subst *subster) node(n ir.Node) ir.Node { assert(ix >= 0) dt := ir.NewDynamicType(c.Pos(), getDictionaryEntry(c.Pos(), subst.info.dictParam, ix, subst.info.dictLen)) - // For type switch from nonemoty interfaces to non-interfaces, we need an itab as well. - if _, ok := subst.info.gfInfo.type2switchType[c]; ok { - // Type switch from nonempty interface. We need a *runtime.itab - // for the dynamic type. - ix := -1 - for i, ic := range subst.info.gfInfo.itabConvs { - if ic == c { - ix = subst.info.startItabConv + i - break + // For type switch from nonempty interfaces to non-interfaces, we need an itab as well. + if !m.List[i].Type().IsInterface() { + if _, ok := subst.info.gfInfo.type2switchType[c]; ok { + // Type switch from nonempty interface. We need a *runtime.itab + // for the dynamic type. + ix := -1 + for i, ic := range subst.info.gfInfo.itabConvs { + if ic == c { + ix = subst.info.startItabConv + i + break + } } + assert(ix >= 0) + dt.ITab = getDictionaryEntry(c.Pos(), subst.info.dictParam, ix, subst.info.dictLen) } - assert(ix >= 0) - dt.ITab = getDictionaryEntry(c.Pos(), subst.info.dictParam, ix, subst.info.dictLen) } typed(m.List[i].Type(), dt) m.List[i] = dt @@ -1484,6 +1486,8 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) // instantiations have been created. func (g *irgen) finalizeSyms() { for _, d := range g.dictSymsToFinalize { + infoPrint("=== Finalizing dictionary %s\n", d.sym.Name) + lsym := d.sym.Linksym() info := g.getGfInfo(d.gf) @@ -1528,9 +1532,11 @@ func (g *irgen) finalizeSyms() { // No itab is wanted if src type is an interface. We // will use a type assert instead. d.off = objw.Uintptr(lsym, d.off, 0) + infoPrint(" + Unused itab entry for %v\n", srctype) } else { itabLsym := reflectdata.ITabLsym(srctype, dsttype) d.off = objw.SymPtr(lsym, d.off, itabLsym, 0) + infoPrint(" + Itab for (%v,%v)\n", srctype, dsttype) } } @@ -1694,7 +1700,7 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo { for _, cc := range n.(*ir.SwitchStmt).Cases { for _, c := range cc.List { if c.Op() == ir.OTYPE && c.Type().HasTParam() { - // Type switch from a non-empty interface to a noninterface. + // Type switch from a non-empty interface - might need an itab. infoPrint(" Itab for type switch: %v\n", c) info.itabConvs = append(info.itabConvs, c) if info.type2switchType == nil { diff --git a/test/typeparam/typeswitch6.go b/test/typeparam/typeswitch6.go new file mode 100644 index 0000000000..574f4aa819 --- /dev/null +++ b/test/typeparam/typeswitch6.go @@ -0,0 +1,30 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func f[T any](i interface{}) { + switch i.(type) { + case T: + println("T") + case int: + println("int") + default: + println("other") + } +} + +type myint int +func (myint) foo() { +} + +func main() { + f[interface{}](nil) + f[interface{}](6) + f[interface{foo()}](nil) + f[interface{foo()}](7) + f[interface{foo()}](myint(8)) +} diff --git a/test/typeparam/typeswitch6.out b/test/typeparam/typeswitch6.out new file mode 100644 index 0000000000..441add5ec5 --- /dev/null +++ b/test/typeparam/typeswitch6.out @@ -0,0 +1,5 @@ +other +T +other +int +T diff --git a/test/typeparam/typeswitch7.go b/test/typeparam/typeswitch7.go new file mode 100644 index 0000000000..f2e1279fb4 --- /dev/null +++ b/test/typeparam/typeswitch7.go @@ -0,0 +1,37 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func f[T any](i interface{foo()}) { + switch i.(type) { + case interface{bar() T}: + println("barT") + case myint: + println("myint") + case myfloat: + println("myfloat") + default: + println("other") + } +} + +type myint int +func (myint) foo() { +} +func (x myint) bar() int { + return int(x) +} + +type myfloat float64 +func (myfloat) foo() { +} + +func main() { + f[int](nil) + f[int](myint(6)) + f[int](myfloat(7)) +} diff --git a/test/typeparam/typeswitch7.out b/test/typeparam/typeswitch7.out new file mode 100644 index 0000000000..d7fcad4fee --- /dev/null +++ b/test/typeparam/typeswitch7.out @@ -0,0 +1,3 @@ +other +barT +myfloat -- GitLab From 2e250cc95760e75a3f1fa082920eecd9f88fd096 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 10 Aug 2021 11:02:34 -0400 Subject: [PATCH 0641/2500] [dev.typeparams] cmd: update vendored golang.org/x/tools to 337cebd2c151 Update vendored golang.org/x/tools repo to pick up CL 339250 for assembly function check for register ABI. This is done with cd GOROOT/cmd go get golang.org/x/tools@master go mod tidy go mod vendor Update cmd/vet tests as the error ouput changes in CL 301949. The error message now includes full package-qualified name. Change-Id: I52dc7223aee9e011214254488bacf02dc5b4c2ef Reviewed-on: https://go-review.googlesource.com/c/go/+/341149 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Dmitri Shuralyov Reviewed-by: Than McIntosh --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 +- .../go/analysis/passes/asmdecl/asmdecl.go | 37 ++- .../tools/go/analysis/passes/printf/printf.go | 28 ++- .../x/tools/go/ast/astutil/rewrite.go | 10 +- .../x/tools/go/types/objectpath/objectpath.go | 2 +- .../x/tools/internal/lsp/fuzzy/input.go | 37 ++- .../x/tools/internal/lsp/fuzzy/matcher.go | 23 +- .../x/tools/internal/lsp/fuzzy/symbol.go | 224 ++++++++++++++++++ .../x/tools/internal/typeparams/common.go | 25 ++ .../tools/internal/typeparams/notypeparams.go | 93 ++++++++ .../x/tools/internal/typeparams/typeparams.go | 115 +++++++++ src/cmd/vendor/modules.txt | 3 +- src/cmd/vet/testdata/print/print.go | 8 +- 14 files changed, 563 insertions(+), 48 deletions(-) create mode 100644 src/cmd/vendor/golang.org/x/tools/internal/lsp/fuzzy/symbol.go create mode 100644 src/cmd/vendor/golang.org/x/tools/internal/typeparams/common.go create mode 100644 src/cmd/vendor/golang.org/x/tools/internal/typeparams/notypeparams.go create mode 100644 src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams.go diff --git a/src/cmd/go.mod b/src/cmd/go.mod index da304e292b..ccfff09885 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -10,6 +10,6 @@ require ( golang.org/x/mod v0.4.3-0.20210608190319-0f08993efd8a golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 // indirect golang.org/x/term v0.0.0-20210503060354-a79de5458b56 - golang.org/x/tools v0.1.2-0.20210519160823-49064d2332f9 + golang.org/x/tools v0.1.6-0.20210809225032-337cebd2c151 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 7f0d978ef0..f4d41f0d10 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -16,7 +16,7 @@ golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 h1:yhBbb4IRs2HS9PPlAg6DMC6mU golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210503060354-a79de5458b56 h1:b8jxX3zqjpqb2LklXPzKSGJhzyxCOZSz8ncv8Nv+y7w= golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY= -golang.org/x/tools v0.1.2-0.20210519160823-49064d2332f9 h1:2XlR/j4I4xz5GQZI7zBjqTfezYyRIE2jD5IMousB2rg= -golang.org/x/tools v0.1.2-0.20210519160823-49064d2332f9/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.6-0.20210809225032-337cebd2c151 h1:jHjT6WuVKEMzjJgrS1+r1wk54oxwqumUnvtn0QZXyXE= +golang.org/x/tools v0.1.6-0.20210809225032-337cebd2c151/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go index eb0016b18f..7b82d0b6dd 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go @@ -51,6 +51,11 @@ type asmArch struct { bigEndian bool stack string lr bool + // retRegs is a list of registers for return value in register ABI (ABIInternal). + // For now, as we only check whether we write to any result, here we only need to + // include the first integer register and first floating-point register. Accessing + // any of them counts as writing to result. + retRegs []string // calculated during initialization sizes types.Sizes intSize int @@ -79,8 +84,8 @@ type asmVar struct { var ( asmArch386 = asmArch{name: "386", bigEndian: false, stack: "SP", lr: false} asmArchArm = asmArch{name: "arm", bigEndian: false, stack: "R13", lr: true} - asmArchArm64 = asmArch{name: "arm64", bigEndian: false, stack: "RSP", lr: true} - asmArchAmd64 = asmArch{name: "amd64", bigEndian: false, stack: "SP", lr: false} + asmArchArm64 = asmArch{name: "arm64", bigEndian: false, stack: "RSP", lr: true, retRegs: []string{"R0", "F0"}} + asmArchAmd64 = asmArch{name: "amd64", bigEndian: false, stack: "SP", lr: false, retRegs: []string{"AX", "X0"}} asmArchMips = asmArch{name: "mips", bigEndian: true, stack: "R29", lr: true} asmArchMipsLE = asmArch{name: "mipsle", bigEndian: false, stack: "R29", lr: true} asmArchMips64 = asmArch{name: "mips64", bigEndian: true, stack: "R29", lr: true} @@ -137,7 +142,7 @@ var ( asmSP = re(`[^+\-0-9](([0-9]+)\(([A-Z0-9]+)\))`) asmOpcode = re(`^\s*(?:[A-Z0-9a-z_]+:)?\s*([A-Z]+)\s*([^,]*)(?:,\s*(.*))?`) ppc64Suff = re(`([BHWD])(ZU|Z|U|BR)?$`) - abiSuff = re(`^(.+)$`) + abiSuff = re(`^(.+)<(ABI.+)>$`) ) func run(pass *analysis.Pass) (interface{}, error) { @@ -185,6 +190,7 @@ Files: var ( fn *asmFunc fnName string + abi string localSize, argSize int wroteSP bool noframe bool @@ -195,18 +201,22 @@ Files: flushRet := func() { if fn != nil && fn.vars["ret"] != nil && !haveRetArg && len(retLine) > 0 { v := fn.vars["ret"] + resultStr := fmt.Sprintf("%d-byte ret+%d(FP)", v.size, v.off) + if abi == "ABIInternal" { + resultStr = "result register" + } for _, line := range retLine { - pass.Reportf(analysisutil.LineStart(tf, line), "[%s] %s: RET without writing to %d-byte ret+%d(FP)", arch, fnName, v.size, v.off) + pass.Reportf(analysisutil.LineStart(tf, line), "[%s] %s: RET without writing to %s", arch, fnName, resultStr) } } retLine = nil } - trimABI := func(fnName string) string { + trimABI := func(fnName string) (string, string) { m := abiSuff.FindStringSubmatch(fnName) if m != nil { - return m[1] + return m[1], m[2] } - return fnName + return fnName, "" } for lineno, line := range lines { lineno++ @@ -273,11 +283,12 @@ Files: // log.Printf("%s:%d: [%s] cannot check cross-package assembly function: %s is in package %s", fname, lineno, arch, fnName, pkgPath) fn = nil fnName = "" + abi = "" continue } } // Trim off optional ABI selector. - fnName := trimABI(fnName) + fnName, abi = trimABI(fnName) flag := m[3] fn = knownFunc[fnName][arch] if fn != nil { @@ -305,6 +316,7 @@ Files: flushRet() fn = nil fnName = "" + abi = "" continue } @@ -335,6 +347,15 @@ Files: haveRetArg = true } + if abi == "ABIInternal" && !haveRetArg { + for _, reg := range archDef.retRegs { + if strings.Contains(line, reg) { + haveRetArg = true + break + } + } + } + for _, m := range asmSP.FindAllStringSubmatch(line, -1) { if m[3] != archDef.stack || wroteSP || noframe { continue diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go index 822820f06e..6589478af0 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go @@ -555,7 +555,7 @@ func checkPrintf(pass *analysis.Pass, kind Kind, call *ast.CallExpr, fn *types.F format, idx := formatString(pass, call) if idx < 0 { if false { - pass.Reportf(call.Lparen, "can't check non-constant format in call to %s", fn.Name()) + pass.Reportf(call.Lparen, "can't check non-constant format in call to %s", fn.FullName()) } return } @@ -563,7 +563,7 @@ func checkPrintf(pass *analysis.Pass, kind Kind, call *ast.CallExpr, fn *types.F firstArg := idx + 1 // Arguments are immediately after format string. if !strings.Contains(format, "%") { if len(call.Args) > firstArg { - pass.Reportf(call.Lparen, "%s call has arguments but no formatting directives", fn.Name()) + pass.Reportf(call.Lparen, "%s call has arguments but no formatting directives", fn.FullName()) } return } @@ -577,7 +577,7 @@ func checkPrintf(pass *analysis.Pass, kind Kind, call *ast.CallExpr, fn *types.F if format[i] != '%' { continue } - state := parsePrintfVerb(pass, call, fn.Name(), format[i:], firstArg, argNum) + state := parsePrintfVerb(pass, call, fn.FullName(), format[i:], firstArg, argNum) if state == nil { return } @@ -589,8 +589,12 @@ func checkPrintf(pass *analysis.Pass, kind Kind, call *ast.CallExpr, fn *types.F anyIndex = true } if state.verb == 'w' { - if kind != KindErrorf { - pass.Reportf(call.Pos(), "%s call has error-wrapping directive %%w, which is only supported by Errorf", state.name) + switch kind { + case KindNone, KindPrint: + pass.Reportf(call.Pos(), "%s does not support error-wrapping directive %%w", state.name) + return + case KindPrintf: + pass.Reportf(call.Pos(), "%s call has error-wrapping directive %%w, which is only supported for functions backed by fmt.Errorf", state.name) return } if anyW { @@ -621,7 +625,7 @@ func checkPrintf(pass *analysis.Pass, kind Kind, call *ast.CallExpr, fn *types.F if maxArgNum != len(call.Args) { expect := maxArgNum - firstArg numArgs := len(call.Args) - firstArg - pass.ReportRangef(call, "%s call needs %v but has %v", fn.Name(), count(expect, "arg"), count(numArgs, "arg")) + pass.ReportRangef(call, "%s call needs %v but has %v", fn.FullName(), count(expect, "arg"), count(numArgs, "arg")) } } @@ -949,7 +953,7 @@ func recursiveStringer(pass *analysis.Pass, e ast.Expr) (string, bool) { } if id, ok := e.(*ast.Ident); ok { if pass.TypesInfo.Uses[id] == sig.Recv() { - return method.Name(), true + return method.FullName(), true } } return "", false @@ -1044,7 +1048,7 @@ func checkPrint(pass *analysis.Pass, call *ast.CallExpr, fn *types.Func) { if sel, ok := call.Args[0].(*ast.SelectorExpr); ok { if x, ok := sel.X.(*ast.Ident); ok { if x.Name == "os" && strings.HasPrefix(sel.Sel.Name, "Std") { - pass.ReportRangef(call, "%s does not take io.Writer but has first arg %s", fn.Name(), analysisutil.Format(pass.Fset, call.Args[0])) + pass.ReportRangef(call, "%s does not take io.Writer but has first arg %s", fn.FullName(), analysisutil.Format(pass.Fset, call.Args[0])) } } } @@ -1058,7 +1062,7 @@ func checkPrint(pass *analysis.Pass, call *ast.CallExpr, fn *types.Func) { if strings.Contains(s, "%") { m := printFormatRE.FindStringSubmatch(s) if m != nil { - pass.ReportRangef(call, "%s call has possible formatting directive %s", fn.Name(), m[0]) + pass.ReportRangef(call, "%s call has possible formatting directive %s", fn.FullName(), m[0]) } } } @@ -1068,16 +1072,16 @@ func checkPrint(pass *analysis.Pass, call *ast.CallExpr, fn *types.Func) { if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { str, _ := strconv.Unquote(lit.Value) if strings.HasSuffix(str, "\n") { - pass.ReportRangef(call, "%s arg list ends with redundant newline", fn.Name()) + pass.ReportRangef(call, "%s arg list ends with redundant newline", fn.FullName()) } } } for _, arg := range args { if isFunctionValue(pass, arg) { - pass.ReportRangef(call, "%s arg %s is a func value, not called", fn.Name(), analysisutil.Format(pass.Fset, arg)) + pass.ReportRangef(call, "%s arg %s is a func value, not called", fn.FullName(), analysisutil.Format(pass.Fset, arg)) } if methodName, ok := recursiveStringer(pass, arg); ok { - pass.ReportRangef(call, "%s arg %s causes recursive call to %s method", fn.Name(), analysisutil.Format(pass.Fset, arg), methodName) + pass.ReportRangef(call, "%s arg %s causes recursive call to %s method", fn.FullName(), analysisutil.Format(pass.Fset, arg), methodName) } } } diff --git a/src/cmd/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go b/src/cmd/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go index cf72ea990b..5fe75b14c7 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go +++ b/src/cmd/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go @@ -9,6 +9,8 @@ import ( "go/ast" "reflect" "sort" + + "golang.org/x/tools/internal/typeparams" ) // An ApplyFunc is invoked by Apply for each node n, even if n is nil, @@ -437,7 +439,13 @@ func (a *application) apply(parent ast.Node, name string, iter *iterator, n ast. } default: - panic(fmt.Sprintf("Apply: unexpected node type %T", n)) + if ix := typeparams.GetIndexExprData(n); ix != nil { + a.apply(n, "X", nil, ix.X) + // *ast.IndexExpr was handled above, so n must be an *ast.MultiIndexExpr. + a.applyList(n, "Indices") + } else { + panic(fmt.Sprintf("Apply: unexpected node type %T", n)) + } } if a.post != nil && !a.post(&a.cursor) { diff --git a/src/cmd/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go b/src/cmd/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go index cffd7acbee..81e8fdcf0c 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go +++ b/src/cmd/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go @@ -58,7 +58,7 @@ type Path string // - The only OT operator is Object.Type, // which we encode as '.' because dot cannot appear in an identifier. // - The TT operators are encoded as [EKPRU]. -// - The OT operators are encoded as [AFMO]; +// - The TO operators are encoded as [AFMO]; // three of these (At,Field,Method) require an integer operand, // which is encoded as a string of decimal digits. // These indices are stable across different representations diff --git a/src/cmd/vendor/golang.org/x/tools/internal/lsp/fuzzy/input.go b/src/cmd/vendor/golang.org/x/tools/internal/lsp/fuzzy/input.go index ac377035ec..c1038163f1 100644 --- a/src/cmd/vendor/golang.org/x/tools/internal/lsp/fuzzy/input.go +++ b/src/cmd/vendor/golang.org/x/tools/internal/lsp/fuzzy/input.go @@ -27,23 +27,23 @@ const ( // RuneRoles detects the roles of each byte rune in an input string and stores it in the output // slice. The rune role depends on the input type. Stops when it parsed all the runes in the string // or when it filled the output. If output is nil, then it gets created. -func RuneRoles(str string, reuse []RuneRole) []RuneRole { +func RuneRoles(candidate []byte, reuse []RuneRole) []RuneRole { var output []RuneRole - if cap(reuse) < len(str) { - output = make([]RuneRole, 0, len(str)) + if cap(reuse) < len(candidate) { + output = make([]RuneRole, 0, len(candidate)) } else { output = reuse[:0] } prev, prev2 := rtNone, rtNone - for i := 0; i < len(str); i++ { - r := rune(str[i]) + for i := 0; i < len(candidate); i++ { + r := rune(candidate[i]) role := RNone curr := rtLower - if str[i] <= unicode.MaxASCII { - curr = runeType(rt[str[i]] - '0') + if candidate[i] <= unicode.MaxASCII { + curr = runeType(rt[candidate[i]] - '0') } if curr == rtLower { @@ -58,7 +58,7 @@ func RuneRoles(str string, reuse []RuneRole) []RuneRole { if prev == rtUpper { // This and previous characters are both upper case. - if i+1 == len(str) { + if i+1 == len(candidate) { // This is last character, previous was also uppercase -> this is UCTail // i.e., (current char is C): aBC / BC / ABC role = RUCTail @@ -118,11 +118,26 @@ func LastSegment(input string, roles []RuneRole) string { return input[start+1 : end+1] } -// ToLower transforms the input string to lower case, which is stored in the output byte slice. +// fromChunks copies string chunks into the given buffer. +func fromChunks(chunks []string, buffer []byte) []byte { + ii := 0 + for _, chunk := range chunks { + for i := 0; i < len(chunk); i++ { + if ii >= cap(buffer) { + break + } + buffer[ii] = chunk[i] + ii++ + } + } + return buffer[:ii] +} + +// toLower transforms the input string to lower case, which is stored in the output byte slice. // The lower casing considers only ASCII values - non ASCII values are left unmodified. // Stops when parsed all input or when it filled the output slice. If output is nil, then it gets // created. -func ToLower(input string, reuse []byte) []byte { +func toLower(input []byte, reuse []byte) []byte { output := reuse if cap(reuse) < len(input) { output = make([]byte, len(input)) @@ -130,7 +145,7 @@ func ToLower(input string, reuse []byte) []byte { for i := 0; i < len(input); i++ { r := rune(input[i]) - if r <= unicode.MaxASCII { + if input[i] <= unicode.MaxASCII { if 'A' <= r && r <= 'Z' { r += 'a' - 'A' } diff --git a/src/cmd/vendor/golang.org/x/tools/internal/lsp/fuzzy/matcher.go b/src/cmd/vendor/golang.org/x/tools/internal/lsp/fuzzy/matcher.go index 16a643097d..265cdcf160 100644 --- a/src/cmd/vendor/golang.org/x/tools/internal/lsp/fuzzy/matcher.go +++ b/src/cmd/vendor/golang.org/x/tools/internal/lsp/fuzzy/matcher.go @@ -51,8 +51,12 @@ type Matcher struct { lastCandidateLen int // in bytes lastCandidateMatched bool - // Here we save the last candidate in lower-case. This is basically a byte slice we reuse for - // performance reasons, so the slice is not reallocated for every candidate. + // Reusable buffers to avoid allocating for every candidate. + // - inputBuf stores the concatenated input chunks + // - lowerBuf stores the last candidate in lower-case + // - rolesBuf stores the calculated roles for each rune in the last + // candidate. + inputBuf [MaxInputSize]byte lowerBuf [MaxInputSize]byte rolesBuf [MaxInputSize]RuneRole } @@ -72,7 +76,7 @@ func NewMatcher(pattern string) *Matcher { m := &Matcher{ pattern: pattern, - patternLower: ToLower(pattern, nil), + patternLower: toLower([]byte(pattern), nil), } for i, c := range m.patternLower { @@ -88,7 +92,7 @@ func NewMatcher(pattern string) *Matcher { m.patternShort = m.patternLower } - m.patternRoles = RuneRoles(pattern, nil) + m.patternRoles = RuneRoles([]byte(pattern), nil) if len(pattern) > 0 { maxCharScore := 4 @@ -102,10 +106,15 @@ func NewMatcher(pattern string) *Matcher { // This is not designed for parallel use. Multiple candidates must be scored sequentially. // Returns a score between 0 and 1 (0 - no match, 1 - perfect match). func (m *Matcher) Score(candidate string) float32 { + return m.ScoreChunks([]string{candidate}) +} + +func (m *Matcher) ScoreChunks(chunks []string) float32 { + candidate := fromChunks(chunks, m.inputBuf[:]) if len(candidate) > MaxInputSize { candidate = candidate[:MaxInputSize] } - lower := ToLower(candidate, m.lowerBuf[:]) + lower := toLower(candidate, m.lowerBuf[:]) m.lastCandidateLen = len(candidate) if len(m.pattern) == 0 { @@ -174,7 +183,7 @@ func (m *Matcher) MatchedRanges() []int { return ret } -func (m *Matcher) match(candidate string, candidateLower []byte) bool { +func (m *Matcher) match(candidate []byte, candidateLower []byte) bool { i, j := 0, 0 for ; i < len(candidateLower) && j < len(m.patternLower); i++ { if candidateLower[i] == m.patternLower[j] { @@ -192,7 +201,7 @@ func (m *Matcher) match(candidate string, candidateLower []byte) bool { return true } -func (m *Matcher) computeScore(candidate string, candidateLower []byte) int { +func (m *Matcher) computeScore(candidate []byte, candidateLower []byte) int { pattLen, candLen := len(m.pattern), len(candidate) for j := 0; j <= len(m.pattern); j++ { diff --git a/src/cmd/vendor/golang.org/x/tools/internal/lsp/fuzzy/symbol.go b/src/cmd/vendor/golang.org/x/tools/internal/lsp/fuzzy/symbol.go new file mode 100644 index 0000000000..062f491fb5 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/tools/internal/lsp/fuzzy/symbol.go @@ -0,0 +1,224 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fuzzy + +import ( + "unicode" +) + +// SymbolMatcher implements a fuzzy matching algorithm optimized for Go symbols +// of the form: +// example.com/path/to/package.object.field +// +// Knowing that we are matching symbols like this allows us to make the +// following optimizations: +// - We can incorporate right-to-left relevance directly into the score +// calculation. +// - We can match from right to left, discarding leading bytes if the input is +// too long. +// - We just take the right-most match without losing too much precision. This +// allows us to use an O(n) algorithm. +// - We can operate directly on chunked strings; in many cases we will +// be storing the package path and/or package name separately from the +// symbol or identifiers, so doing this avoids allocating strings. +// - We can return the index of the right-most match, allowing us to trim +// irrelevant qualification. +// +// This implementation is experimental, serving as a reference fast algorithm +// to compare to the fuzzy algorithm implemented by Matcher. +type SymbolMatcher struct { + // Using buffers of length 256 is both a reasonable size for most qualified + // symbols, and makes it easy to avoid bounds checks by using uint8 indexes. + pattern [256]rune + patternLen uint8 + inputBuffer [256]rune // avoid allocating when considering chunks + roles [256]uint32 // which roles does a rune play (word start, etc.) + segments [256]uint8 // how many segments from the right is each rune +} + +const ( + segmentStart uint32 = 1 << iota + wordStart + separator +) + +// NewSymbolMatcher creates a SymbolMatcher that may be used to match the given +// search pattern. +// +// Currently this matcher only accepts case-insensitive fuzzy patterns. +// +// TODO(rfindley): +// - implement smart-casing +// - implement space-separated groups +// - implement ', ^, and $ modifiers +// +// An empty pattern matches no input. +func NewSymbolMatcher(pattern string) *SymbolMatcher { + m := &SymbolMatcher{} + for _, p := range pattern { + m.pattern[m.patternLen] = unicode.ToLower(p) + m.patternLen++ + if m.patternLen == 255 || int(m.patternLen) == len(pattern) { + // break at 255 so that we can represent patternLen with a uint8. + break + } + } + return m +} + +// Match looks for the right-most match of the search pattern within the symbol +// represented by concatenating the given chunks, returning its offset and +// score. +// +// If a match is found, the first return value will hold the absolute byte +// offset within all chunks for the start of the symbol. In other words, the +// index of the match within strings.Join(chunks, ""). If no match is found, +// the first return value will be -1. +// +// The second return value will be the score of the match, which is always +// between 0 and 1, inclusive. A score of 0 indicates no match. +func (m *SymbolMatcher) Match(chunks []string) (int, float64) { + // Explicit behavior for an empty pattern. + // + // As a minor optimization, this also avoids nilness checks later on, since + // the compiler can prove that m != nil. + if m.patternLen == 0 { + return -1, 0 + } + + // First phase: populate the input buffer with lower-cased runes. + // + // We could also check for a forward match here, but since we'd have to write + // the entire input anyway this has negligible impact on performance. + + var ( + inputLen = uint8(0) + modifiers = wordStart | segmentStart + ) + +input: + for _, chunk := range chunks { + for _, r := range chunk { + if r == '.' || r == '/' { + modifiers |= separator + } + // optimization: avoid calls to unicode.ToLower, which can't be inlined. + l := r + if r <= unicode.MaxASCII { + if 'A' <= r && r <= 'Z' { + l = r + 'a' - 'A' + } + } else { + l = unicode.ToLower(r) + } + if l != r { + modifiers |= wordStart + } + m.inputBuffer[inputLen] = l + m.roles[inputLen] = modifiers + inputLen++ + if m.roles[inputLen-1]&separator != 0 { + modifiers = wordStart | segmentStart + } else { + modifiers = 0 + } + // TODO: we should prefer the right-most input if it overflows, rather + // than the left-most as we're doing here. + if inputLen == 255 { + break input + } + } + } + + // Second phase: find the right-most match, and count segments from the + // right. + + var ( + pi = uint8(m.patternLen - 1) // pattern index + p = m.pattern[pi] // pattern rune + start = -1 // start offset of match + rseg = uint8(0) + ) + const maxSeg = 3 // maximum number of segments from the right to count, for scoring purposes. + + for ii := inputLen - 1; ; ii-- { + r := m.inputBuffer[ii] + if rseg < maxSeg && m.roles[ii]&separator != 0 { + rseg++ + } + m.segments[ii] = rseg + if p == r { + if pi == 0 { + start = int(ii) + break + } + pi-- + p = m.pattern[pi] + } + // Don't check ii >= 0 in the loop condition: ii is a uint8. + if ii == 0 { + break + } + } + + if start < 0 { + // no match: skip scoring + return -1, 0 + } + + // Third phase: find the shortest match, and compute the score. + + // Score is the average score for each character. + // + // A character score is the multiple of: + // 1. 1.0 if the character starts a segment, .8 if the character start a + // mid-segment word, otherwise 0.6. This carries over to immediately + // following characters. + // 2. 1.0 if the character is part of the last segment, otherwise + // 1.0-.2*, with a max segment count of 3. + // + // This is a very naive algorithm, but it is fast. There's lots of prior art + // here, and we should leverage it. For example, we could explicitly consider + // character distance, and exact matches of words or segments. + // + // Also note that this might not actually find the highest scoring match, as + // doing so could require a non-linear algorithm, depending on how the score + // is calculated. + + pi = 0 + p = m.pattern[pi] + + const ( + segStreak = 1.0 + wordStreak = 0.8 + noStreak = 0.6 + perSegment = 0.2 // we count at most 3 segments above + ) + + streakBonus := noStreak + totScore := 0.0 + for ii := uint8(start); ii < inputLen; ii++ { + r := m.inputBuffer[ii] + if r == p { + pi++ + p = m.pattern[pi] + // Note: this could be optimized with some bit operations. + switch { + case m.roles[ii]&segmentStart != 0 && segStreak > streakBonus: + streakBonus = segStreak + case m.roles[ii]&wordStart != 0 && wordStreak > streakBonus: + streakBonus = wordStreak + } + totScore += streakBonus * (1.0 - float64(m.segments[ii])*perSegment) + if pi >= m.patternLen { + break + } + } else { + streakBonus = noStreak + } + } + + return start, totScore / float64(m.patternLen) +} diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/common.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/common.go new file mode 100644 index 0000000000..9fc6b4beb8 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/common.go @@ -0,0 +1,25 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package typeparams provides functions to work indirectly with type parameter +// data stored in go/ast and go/types objects, while these API are guarded by a +// build constraint. +// +// This package exists to make it easier for tools to work with generic code, +// while also compiling against older Go versions. +package typeparams + +import ( + "go/ast" + "go/token" +) + +// A IndexExprData holds data from both ast.IndexExpr and the new +// ast.MultiIndexExpr, which was introduced in Go 1.18. +type IndexExprData struct { + X ast.Expr // expression + Lbrack token.Pos // position of "[" + Indices []ast.Expr // index expressions + Rbrack token.Pos // position of "]" +} diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/notypeparams.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/notypeparams.go new file mode 100644 index 0000000000..e975e476f6 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/notypeparams.go @@ -0,0 +1,93 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !typeparams || !go1.18 +// +build !typeparams !go1.18 + +package typeparams + +import ( + "go/ast" + "go/types" +) + +// NOTE: doc comments must be kept in sync with typeparams.go. + +// Enabled reports whether type parameters are enabled in the current build +// environment. +const Enabled = false + +// GetIndexExprData extracts data from AST nodes that represent index +// expressions. +// +// For an ast.IndexExpr, the resulting IndexExprData will have exactly one +// index expression. For an ast.MultiIndexExpr (go1.18+), it may have a +// variable number of index expressions. +// +// For nodes that don't represent index expressions, GetIndexExprData returns +// nil. +func GetIndexExprData(n ast.Node) *IndexExprData { + if e, _ := n.(*ast.IndexExpr); e != nil { + return &IndexExprData{ + X: e.X, + Lbrack: e.Lbrack, + Indices: []ast.Expr{e.Index}, + Rbrack: e.Rbrack, + } + } + return nil +} + +// ForTypeDecl extracts the (possibly nil) type parameter node list from n. +func ForTypeDecl(*ast.TypeSpec) *ast.FieldList { + return nil +} + +// ForFuncDecl extracts the (possibly nil) type parameter node list from n. +func ForFuncDecl(*ast.FuncDecl) *ast.FieldList { + return nil +} + +// ForSignature extracts the (possibly empty) type parameter object list from +// sig. +func ForSignature(*types.Signature) []*types.TypeName { + return nil +} + +// IsComparable reports if iface is the comparable interface. +func IsComparable(*types.Interface) bool { + return false +} + +// IsConstraint reports whether iface may only be used as a type parameter +// constraint (i.e. has a type set or is the comparable interface). +func IsConstraint(*types.Interface) bool { + return false +} + +// ForNamed extracts the (possibly empty) type parameter object list from +// named. +func ForNamed(*types.Named) []*types.TypeName { + return nil +} + +// NamedTArgs extracts the (possibly empty) type argument list from named. +func NamedTArgs(*types.Named) []types.Type { + return nil +} + +// InitInferred initializes info to record inferred type information. +func InitInferred(*types.Info) { +} + +// GetInferred extracts inferred type information from info for e. +// +// The expression e may have an inferred type if it is an *ast.IndexExpr +// representing partial instantiation of a generic function type for which type +// arguments have been inferred using constraint type inference, or if it is an +// *ast.CallExpr for which type type arguments have be inferred using both +// constraint type inference and function argument inference. +func GetInferred(*types.Info, ast.Expr) ([]types.Type, *types.Signature) { + return nil, nil +} diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams.go new file mode 100644 index 0000000000..be6b0525f6 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams.go @@ -0,0 +1,115 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build typeparams && go1.18 +// +build typeparams,go1.18 + +package typeparams + +import ( + "go/ast" + "go/types" +) + +// NOTE: doc comments must be kept in sync with notypeparams.go. + +// Enabled reports whether type parameters are enabled in the current build +// environment. +const Enabled = true + +// GetIndexExprData extracts data from AST nodes that represent index +// expressions. +// +// For an ast.IndexExpr, the resulting IndexExprData will have exactly one +// index expression. For an ast.MultiIndexExpr (go1.18+), it may have a +// variable number of index expressions. +// +// For nodes that don't represent index expressions, GetIndexExprData returns +// nil. +func GetIndexExprData(n ast.Node) *IndexExprData { + switch e := n.(type) { + case *ast.IndexExpr: + return &IndexExprData{ + X: e.X, + Lbrack: e.Lbrack, + Indices: []ast.Expr{e.Index}, + Rbrack: e.Rbrack, + } + case *ast.MultiIndexExpr: + return (*IndexExprData)(e) + } + return nil +} + +// ForTypeDecl extracts the (possibly nil) type parameter node list from n. +func ForTypeDecl(n *ast.TypeSpec) *ast.FieldList { + return n.TParams +} + +// ForFuncDecl extracts the (possibly nil) type parameter node list from n. +func ForFuncDecl(n *ast.FuncDecl) *ast.FieldList { + if n.Type != nil { + return n.Type.TParams + } + return nil +} + +// ForSignature extracts the (possibly empty) type parameter object list from +// sig. +func ForSignature(sig *types.Signature) []*types.TypeName { + return tparamsSlice(sig.TParams()) +} + +// IsComparable reports if iface is the comparable interface. +func IsComparable(iface *types.Interface) bool { + return iface.IsComparable() +} + +// IsConstraint reports whether iface may only be used as a type parameter +// constraint (i.e. has a type set or is the comparable interface). +func IsConstraint(iface *types.Interface) bool { + return iface.IsConstraint() +} + +// ForNamed extracts the (possibly empty) type parameter object list from +// named. +func ForNamed(named *types.Named) []*types.TypeName { + return tparamsSlice(named.TParams()) +} + +func tparamsSlice(tparams *types.TypeParams) []*types.TypeName { + if tparams.Len() == 0 { + return nil + } + result := make([]*types.TypeName, tparams.Len()) + for i := 0; i < tparams.Len(); i++ { + result[i] = tparams.At(i) + } + return result +} + +// NamedTArgs extracts the (possibly empty) type argument list from named. +func NamedTArgs(named *types.Named) []types.Type { + return named.TArgs() +} + +// InitInferred initializes info to record inferred type information. +func InitInferred(info *types.Info) { + info.Inferred = make(map[ast.Expr]types.Inferred) +} + +// GetInferred extracts inferred type information from info for e. +// +// The expression e may have an inferred type if it is an *ast.IndexExpr +// representing partial instantiation of a generic function type for which type +// arguments have been inferred using constraint type inference, or if it is an +// *ast.CallExpr for which type type arguments have be inferred using both +// constraint type inference and function argument inference. +func GetInferred(info *types.Info, e ast.Expr) ([]types.Type, *types.Signature) { + if info.Inferred == nil { + return nil, nil + } + inf := info.Inferred[e] + return inf.TArgs, inf.Sig +} diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 34dbdaf5dd..c98bdcd344 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -48,7 +48,7 @@ golang.org/x/sys/windows # golang.org/x/term v0.0.0-20210503060354-a79de5458b56 ## explicit; go 1.17 golang.org/x/term -# golang.org/x/tools v0.1.2-0.20210519160823-49064d2332f9 +# golang.org/x/tools v0.1.6-0.20210809225032-337cebd2c151 ## explicit; go 1.17 golang.org/x/tools/cover golang.org/x/tools/go/analysis @@ -92,6 +92,7 @@ golang.org/x/tools/go/types/objectpath golang.org/x/tools/go/types/typeutil golang.org/x/tools/internal/analysisinternal golang.org/x/tools/internal/lsp/fuzzy +golang.org/x/tools/internal/typeparams # golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 ## explicit; go 1.11 golang.org/x/xerrors diff --git a/src/cmd/vet/testdata/print/print.go b/src/cmd/vet/testdata/print/print.go index fca594925f..46240e87bf 100644 --- a/src/cmd/vet/testdata/print/print.go +++ b/src/cmd/vet/testdata/print/print.go @@ -491,10 +491,10 @@ type recursiveStringer int func (s recursiveStringer) String() string { _ = fmt.Sprintf("%d", s) _ = fmt.Sprintf("%#v", s) - _ = fmt.Sprintf("%v", s) // ERROR "Sprintf format %v with arg s causes recursive String method call" - _ = fmt.Sprintf("%v", &s) // ERROR "Sprintf format %v with arg &s causes recursive String method call" + _ = fmt.Sprintf("%v", s) // ERROR "Sprintf format %v with arg s causes recursive .*String method call" + _ = fmt.Sprintf("%v", &s) // ERROR "Sprintf format %v with arg &s causes recursive .*String method call" _ = fmt.Sprintf("%T", s) // ok; does not recursively call String - return fmt.Sprintln(s) // ERROR "Sprintln arg s causes recursive call to String method" + return fmt.Sprintln(s) // ERROR "Sprintln arg s causes recursive call to .*String method" } type recursivePtrStringer int @@ -502,7 +502,7 @@ type recursivePtrStringer int func (p *recursivePtrStringer) String() string { _ = fmt.Sprintf("%v", *p) _ = fmt.Sprint(&p) // ok; prints address - return fmt.Sprintln(p) // ERROR "Sprintln arg p causes recursive call to String method" + return fmt.Sprintln(p) // ERROR "Sprintln arg p causes recursive call to .*String method" } type BoolFormatter bool -- GitLab From fb8579746c9de74a6faa70de544286e45bc8386e Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Mon, 2 Aug 2021 12:17:13 -0400 Subject: [PATCH 0642/2500] [dev.typeparams] internal/goexperiment: update comment for RegabiArgs requirements RegabiG and regabiDefer have been always enabled and removed from experiments. Update the comment. Change-Id: Ieaf4b4f0a7e0e9d6733a18932ca457be4f150d08 Reviewed-on: https://go-review.googlesource.com/c/go/+/341150 Trust: Cherry Mui Reviewed-by: Michael Knyszek --- src/internal/goexperiment/flags.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/internal/goexperiment/flags.go b/src/internal/goexperiment/flags.go index b7a62b3e26..0a61a0e5fc 100644 --- a/src/internal/goexperiment/flags.go +++ b/src/internal/goexperiment/flags.go @@ -80,10 +80,7 @@ type Flags struct { // RegabiArgs enables register arguments/results in all // compiled Go functions. // - // Requires wrappers (to do ABI translation), g (because - // runtime assembly that's been ported to ABIInternal uses the - // G register), reflect (so reflection calls use registers), - // and defer (because the runtime doesn't support passing - // register arguments to defer/go). + // Requires wrappers (to do ABI translation), and reflect (so + // reflection calls use registers). RegabiArgs bool } -- GitLab From 40ba119e3f990fd570ec928307e92a5b6a76bd0e Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 9 Aug 2021 16:00:29 -0700 Subject: [PATCH 0643/2500] [dev.typeparams] cmd/compile: keep export format unchanged if no type params are exported Added new export tags 'G' and 'U' to export parameterized functions/methods and parameterized types respectively. This has the advantage that the Go 1.18 format remains backward-compatible with the Go 1.17 format if no type parameters are exported. Change-Id: I9dba8faaa65609eb3f9c693bd0c79daee98bd865 Reviewed-on: https://go-review.googlesource.com/c/go/+/340989 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Robert Griesemer Reviewed-by: Robert Findley Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/importer/iimport.go | 13 ++++++----- src/cmd/compile/internal/typecheck/iexport.go | 23 +++++++++++-------- src/cmd/compile/internal/typecheck/iimport.go | 10 ++++---- src/go/internal/gcimporter/iimport.go | 19 +++++---------- 4 files changed, 31 insertions(+), 34 deletions(-) diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index 99eb964415..6051cdaf23 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -308,19 +308,18 @@ func (r *importReader) obj(name string) { r.declare(types2.NewConst(pos, r.currPkg, name, typ, val)) - case 'F': + case 'F', 'G': var tparams []*types2.TypeName - if r.p.exportVersion >= iexportVersionGenerics { + if tag == 'G' { tparams = r.tparamList() } sig := r.signature(nil) sig.SetTParams(tparams) - r.declare(types2.NewFunc(pos, r.currPkg, name, sig)) - case 'T': + case 'T', 'U': var tparams []*types2.TypeName - if r.p.exportVersion >= iexportVersionGenerics { + if tag == 'U' { tparams = r.tparamList() } @@ -328,7 +327,9 @@ func (r *importReader) obj(name string) { // declaration before recursing. obj := types2.NewTypeName(pos, r.currPkg, name, nil) named := types2.NewNamed(obj, nil, nil) - named.SetTParams(tparams) + if tag == 'U' { + named.SetTParams(tparams) + } r.declare(obj) underlying := r.p.typAt(r.uint64(), named).Underlying() diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 2944908bcb..5f510a0a25 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -314,12 +314,7 @@ func WriteExports(out io.Writer, extensions bool) { // Assemble header. var hdr intWriter hdr.WriteByte('i') - if base.Flag.G > 0 { - hdr.uint64(iexportVersionCurrent) - } else { - // Use old export format if doing -G=0 (no generics) - hdr.uint64(iexportVersionPosCol) - } + hdr.uint64(iexportVersionCurrent) hdr.uint64(uint64(p.strings.Len())) hdr.uint64(dataLen) @@ -487,7 +482,11 @@ func (p *iexporter) doDecl(n *ir.Name) { } // Function. - w.tag('F') + if n.Type().TParams().NumFields() == 0 { + w.tag('F') + } else { + w.tag('G') + } w.pos(n.Pos()) // The tparam list of the function type is the // declaration of the type params. So, write out the type @@ -495,7 +494,7 @@ func (p *iexporter) doDecl(n *ir.Name) { // referenced via their type offset (via typOff) in all // other places in the signature and function that they // are used. - if base.Flag.G > 0 { + if n.Type().TParams().NumFields() > 0 { w.tparamList(n.Type().TParams().FieldSlice()) } w.signature(n.Type()) @@ -544,10 +543,14 @@ func (p *iexporter) doDecl(n *ir.Name) { } // Defined type. - w.tag('T') + if len(n.Type().RParams()) == 0 { + w.tag('T') + } else { + w.tag('U') + } w.pos(n.Pos()) - if base.Flag.G > 0 { + if len(n.Type().RParams()) > 0 { // Export type parameters, if any, needed for this type w.typeList(n.Type().RParams()) } diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index d5f4bba98b..83974b6d56 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -305,9 +305,9 @@ func (r *importReader) doDecl(sym *types.Sym) *ir.Name { r.constExt(n) return n - case 'F': + case 'F', 'G': var tparams []*types.Field - if r.p.exportVersion >= iexportVersionGenerics { + if tag == 'G' { tparams = r.tparamList() } typ := r.signature(nil, tparams) @@ -316,9 +316,9 @@ func (r *importReader) doDecl(sym *types.Sym) *ir.Name { r.funcExt(n) return n - case 'T': + case 'T', 'U': var rparams []*types.Type - if r.p.exportVersion >= iexportVersionGenerics { + if tag == 'U' { rparams = r.typeList() } @@ -326,7 +326,7 @@ func (r *importReader) doDecl(sym *types.Sym) *ir.Name { // declaration before recursing. n := importtype(pos, sym) t := n.Type() - if rparams != nil { + if tag == 'U' { t.SetRParams(rparams) } diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go index b300860e94..d4778d3a74 100644 --- a/src/go/internal/gcimporter/iimport.go +++ b/src/go/internal/gcimporter/iimport.go @@ -290,24 +290,14 @@ func (r *importReader) obj(name string) { r.declare(types.NewConst(pos, r.currPkg, name, typ, val)) case 'F': - if r.p.exportVersion >= iexportVersionGenerics { - numTparams := r.uint64() - if numTparams > 0 { - errorf("unexpected tparam") - } - } sig := r.signature(nil) r.declare(types.NewFunc(pos, r.currPkg, name, sig)) - case 'T': - if r.p.exportVersion >= iexportVersionGenerics { - numTparams := r.uint64() - if numTparams > 0 { - errorf("unexpected tparam") - } - } + case 'G': + errorf("unexpected parameterized function/method") + case 'T': // Types can be recursive. We need to setup a stub // declaration before recursing. obj := types.NewTypeName(pos, r.currPkg, name, nil) @@ -328,6 +318,9 @@ func (r *importReader) obj(name string) { } } + case 'U': + errorf("unexpected parameterized type") + case 'V': typ := r.typ() -- GitLab From 0f34a92df76a7946e55d437264bbf5459b30f302 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Wed, 4 Aug 2021 10:45:16 -0400 Subject: [PATCH 0644/2500] [dev.typeparams] go/types: don't expose the TypeSet API for 1.18 The TypeSet API is very new and probably not necessary to expose outside of go/types, at least for 1.18. Users can check whether a type is contained within a type set via Implements, and can access the representation of the type set via the embedded Unions. Change-Id: Icc7355285785bee5aa7a8fe74052bcb0fedcd0a1 Reviewed-on: https://go-review.googlesource.com/c/go/+/341289 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/builtins.go | 2 +- src/go/types/interface.go | 4 ++-- src/go/types/sizeof_test.go | 2 +- src/go/types/typeset.go | 28 ++++++++++++++-------------- src/go/types/universe.go | 2 +- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index aae05438cd..c73d94658a 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -844,7 +844,7 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { ptyp := check.NewTypeParam(tpar, &emptyInterface) // assigns type to tpar as a side-effect ptyp.index = tp.index tsum := newUnion(rtypes, tildes) - ptyp.bound = &Interface{complete: true, tset: &TypeSet{types: tsum}} + ptyp.bound = &Interface{complete: true, tset: &_TypeSet{types: tsum}} return ptyp } diff --git a/src/go/types/interface.go b/src/go/types/interface.go index e98e40179c..d8f9671857 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -21,11 +21,11 @@ type Interface struct { embedPos *[]token.Pos // positions of embedded elements; or nil (for error messages) - use pointer to save space complete bool // indicates that obj, methods, and embeddeds are set and type set can be computed - tset *TypeSet // type set described by this interface, computed lazily + tset *_TypeSet // type set described by this interface, computed lazily } // typeSet returns the type set for interface t. -func (t *Interface) typeSet() *TypeSet { return computeTypeSet(nil, token.NoPos, t) } +func (t *Interface) typeSet() *_TypeSet { return computeTypeSet(nil, token.NoPos, t) } // is reports whether interface t represents types that all satisfy f. func (t *Interface) is(f func(Type, bool) bool) bool { diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index 75122b0273..67a9b39558 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -48,7 +48,7 @@ func TestSizeof(t *testing.T) { // Misc {Scope{}, 44, 88}, {Package{}, 40, 80}, - {TypeSet{}, 24, 48}, + {_TypeSet{}, 24, 48}, } for _, test := range tests { got := reflect.TypeOf(test.val).Size() diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index cbd867dd95..836f93047a 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -14,8 +14,8 @@ import ( // ---------------------------------------------------------------------------- // API -// A TypeSet represents the type set of an interface. -type TypeSet struct { +// A _TypeSet represents the type set of an interface. +type _TypeSet struct { comparable bool // if set, the interface is or embeds comparable // TODO(gri) consider using a set for the methods for faster lookup methods []*Func // all methods of the interface; sorted by unique ID @@ -23,14 +23,14 @@ type TypeSet struct { } // IsTop reports whether type set s is the top type set (corresponding to the empty interface). -func (s *TypeSet) IsTop() bool { return !s.comparable && len(s.methods) == 0 && s.types == nil } +func (s *_TypeSet) IsTop() bool { return !s.comparable && len(s.methods) == 0 && s.types == nil } // IsMethodSet reports whether the type set s is described by a single set of methods. -func (s *TypeSet) IsMethodSet() bool { return !s.comparable && s.types == nil } +func (s *_TypeSet) IsMethodSet() bool { return !s.comparable && s.types == nil } // IsComparable reports whether each type in the set is comparable. // TODO(gri) this is not correct - there may be s.types values containing non-comparable types -func (s *TypeSet) IsComparable() bool { +func (s *_TypeSet) IsComparable() bool { if s.types == nil { return s.comparable } @@ -46,24 +46,24 @@ func (s *TypeSet) IsComparable() bool { // TODO(gri) IsTypeSet is not a great name. Find a better one. // IsTypeSet reports whether the type set s is represented by a finite set of underlying types. -func (s *TypeSet) IsTypeSet() bool { +func (s *_TypeSet) IsTypeSet() bool { return !s.comparable && len(s.methods) == 0 } // NumMethods returns the number of methods available. -func (s *TypeSet) NumMethods() int { return len(s.methods) } +func (s *_TypeSet) NumMethods() int { return len(s.methods) } // Method returns the i'th method of type set s for 0 <= i < s.NumMethods(). // The methods are ordered by their unique ID. -func (s *TypeSet) Method(i int) *Func { return s.methods[i] } +func (s *_TypeSet) Method(i int) *Func { return s.methods[i] } // LookupMethod returns the index of and method with matching package and name, or (-1, nil). -func (s *TypeSet) LookupMethod(pkg *Package, name string) (int, *Func) { +func (s *_TypeSet) LookupMethod(pkg *Package, name string) (int, *Func) { // TODO(gri) s.methods is sorted - consider binary search return lookupMethod(s.methods, pkg, name) } -func (s *TypeSet) String() string { +func (s *_TypeSet) String() string { if s.IsTop() { return "⊤" } @@ -102,7 +102,7 @@ func (s *TypeSet) String() string { // enumerable types in the type set s. If the type set comprises all types // f is called once with the top type; if the type set is empty, the result // is false. -func (s *TypeSet) underIs(f func(Type) bool) bool { +func (s *_TypeSet) underIs(f func(Type) bool) bool { switch t := s.types.(type) { case nil: return f(theTop) @@ -114,10 +114,10 @@ func (s *TypeSet) underIs(f func(Type) bool) bool { } // topTypeSet may be used as type set for the empty interface. -var topTypeSet TypeSet +var topTypeSet _TypeSet // computeTypeSet may be called with check == nil. -func computeTypeSet(check *Checker, pos token.Pos, ityp *Interface) *TypeSet { +func computeTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_TypeSet { if ityp.tset != nil { return ityp.tset } @@ -157,7 +157,7 @@ func computeTypeSet(check *Checker, pos token.Pos, ityp *Interface) *TypeSet { // have valid interfaces. Mark the interface as complete to avoid // infinite recursion if the validType check occurs later for some // reason. - ityp.tset = new(TypeSet) // TODO(gri) is this sufficient? + ityp.tset = new(_TypeSet) // TODO(gri) is this sufficient? // Methods of embedded interfaces are collected unchanged; i.e., the identity // of a method I.m's Func Object of an interface I is the same as that of diff --git a/src/go/types/universe.go b/src/go/types/universe.go index e2b3bd7c18..83c54c8cd3 100644 --- a/src/go/types/universe.go +++ b/src/go/types/universe.go @@ -100,7 +100,7 @@ func defPredeclaredTypes() { { obj := NewTypeName(token.NoPos, nil, "comparable", nil) obj.setColor(black) - ityp := &Interface{obj, nil, nil, nil, true, &TypeSet{true, nil, nil}} + ityp := &Interface{obj, nil, nil, nil, true, &_TypeSet{true, nil, nil}} NewNamed(obj, ityp, nil) def(obj) } -- GitLab From 7308d747e7914b1dbb446988c2094f96b8e5116d Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Mon, 9 Aug 2021 13:39:32 -0400 Subject: [PATCH 0645/2500] [dev.typeparams] cmd/compile/internal/types2: remove Named.SetTArgs Calling SetTArgs without substituting can leave the type in incoherent state, so we should avoid exposing this API unless necessary. Since it is currently not used by the importer(s), it is probably not necessary to expose for 1.18, so remove it. Change-Id: I06bd7b5bbfacd3c65e2e66a9d5980f20cd1c10c1 Reviewed-on: https://go-review.googlesource.com/c/go/+/341290 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/named.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index e099660481..adf3eb3822 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -128,9 +128,6 @@ func (t *Named) SetTParams(tparams []*TypeName) { t.load().tparams = bindTParams // TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated. func (t *Named) TArgs() []Type { return t.targs } -// SetTArgs sets the type arguments of the named type t. -func (t *Named) SetTArgs(args []Type) { t.targs = args } - // NumMethods returns the number of explicit methods whose receiver is named type t. func (t *Named) NumMethods() int { return len(t.load().methods) } -- GitLab From 0888a8cd2dc3ad66e30ccb30eae8fbed065ea0f7 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 9 Aug 2021 15:13:22 -0700 Subject: [PATCH 0646/2500] [dev.typeparams] cmd/compile/internal/types2: remove unused TypeParam.Bound method Use TypeParam.Constraint instead. Change-Id: Iebd77d304f2b7238baa231fb9869c964f66ea355 Reviewed-on: https://go-review.googlesource.com/c/go/+/340990 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/typeparam.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index 12513ed6dd..4b4282efe0 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -80,13 +80,6 @@ func (t *TypeParam) SetConstraint(bound Type) { t.bound = bound } -// Bound returns the constraint interface of t. -// Deprecated. Only here for the compiler. -// TODO(gri) remove in favor of uses of Constraint. -func (t *TypeParam) Bound() *Interface { - return t.iface() -} - func (t *TypeParam) Underlying() Type { return t } func (t *TypeParam) String() string { return TypeString(t, nil) } -- GitLab From eeb7899137cda1c2cd60dab65ff41f627436db5b Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Mon, 2 Aug 2021 12:18:19 -0400 Subject: [PATCH 0647/2500] [dev.typeparams] internal/buildcfg: always enable regabi on AMD64 In Go 1.17 we added register ABI on AMD64 on Linux/macOS/Windows as a GOEXPERIMENT, on by default. In Go 1.18, we commit to always enabling register ABI on AMD64. Now "go build" for AMD64 always have goexperiment.regabi* tags set. However, at bootstrapping cmd/dist does not set the tags when building go_bootstrap. For this to work, unfortunately, we need to hard-code AMD64 to use register ABI in runtime code. Change-Id: I0b31e678e186b9cdeeb8502cd9e38ed0d7e72d4f Reviewed-on: https://go-review.googlesource.com/c/go/+/341151 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek Reviewed-by: Austin Clements --- src/internal/abi/abi_amd64.go | 3 --- src/internal/abi/abi_generic.go | 4 ++-- src/internal/buildcfg/exp.go | 4 +++- src/runtime/stubs.go | 10 ++-------- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/internal/abi/abi_amd64.go b/src/internal/abi/abi_amd64.go index aff71f6a58..d3c5678223 100644 --- a/src/internal/abi/abi_amd64.go +++ b/src/internal/abi/abi_amd64.go @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build goexperiment.regabireflect -// +build goexperiment.regabireflect - package abi const ( diff --git a/src/internal/abi/abi_generic.go b/src/internal/abi/abi_generic.go index 69400f930f..e8f94f805f 100644 --- a/src/internal/abi/abi_generic.go +++ b/src/internal/abi/abi_generic.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build !goexperiment.regabireflect -// +build !goexperiment.regabireflect +//go:build !goexperiment.regabireflect && !amd64 +// +build !goexperiment.regabireflect,!amd64 package abi diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go index 0245574ec1..384f2f96af 100644 --- a/src/internal/buildcfg/exp.go +++ b/src/internal/buildcfg/exp.go @@ -105,9 +105,11 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (flags, baseline goexperiment } } - // regabiwrappers is always enabled on amd64. + // regabi is always enabled on amd64. if goarch == "amd64" { flags.RegabiWrappers = true + flags.RegabiReflect = true + flags.RegabiArgs = true } // regabi is only supported on amd64 and arm64. if goarch != "amd64" && goarch != "arm64" { diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go index fc29a1bac3..8a520d7839 100644 --- a/src/runtime/stubs.go +++ b/src/runtime/stubs.go @@ -6,6 +6,7 @@ package runtime import ( "internal/abi" + "internal/goarch" "internal/goexperiment" "unsafe" ) @@ -419,12 +420,5 @@ func sigpanic0() // structure that is at least large enough to hold the // registers the system supports. // -// Currently it's set to zero because using the actual -// constant will break every part of the toolchain that -// uses finalizers or Windows callbacks to call functions -// The value that is currently commented out there should be -// the actual value once we're ready to use the register ABI -// everywhere. -// // Protected by finlock. -var intArgRegs = abi.IntArgRegs * goexperiment.RegabiArgsInt +var intArgRegs = abi.IntArgRegs * (goexperiment.RegabiArgsInt | goarch.IsAmd64) -- GitLab From d7d4f28a06b8633d433a925b0dfaeadf6530ae97 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Mon, 2 Aug 2021 18:28:40 -0400 Subject: [PATCH 0648/2500] [dev.typeparams] runtime, internal/bytealg: remove regabi fallback code on AMD64 As we commit to always enabling register ABI on AMD64, remove the fallback code. Change-Id: I30556858ba4bac367495fa94f6a8682ecd771196 Reviewed-on: https://go-review.googlesource.com/c/go/+/341152 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek Reviewed-by: Austin Clements --- src/internal/bytealg/compare_amd64.s | 32 ----- src/internal/bytealg/equal_amd64.s | 51 ------- src/runtime/asm_amd64.s | 202 --------------------------- src/runtime/memclr_amd64.s | 5 - src/runtime/memmove_amd64.s | 6 - src/runtime/race_amd64.s | 13 -- 6 files changed, 309 deletions(-) diff --git a/src/internal/bytealg/compare_amd64.s b/src/internal/bytealg/compare_amd64.s index 8295acb03a..4ccaca5e87 100644 --- a/src/internal/bytealg/compare_amd64.s +++ b/src/internal/bytealg/compare_amd64.s @@ -6,7 +6,6 @@ #include "textflag.h" TEXT ·Compare(SB),NOSPLIT,$0-56 -#ifdef GOEXPERIMENT_regabiargs // AX = a_base (want in SI) // BX = a_len (want in BX) // CX = a_cap (unused) @@ -15,17 +14,9 @@ TEXT ·Compare(SB),NOSPLIT,$0-56 // R8 = b_cap (unused) MOVQ SI, DX MOVQ AX, SI -#else - MOVQ a_base+0(FP), SI - MOVQ a_len+8(FP), BX - MOVQ b_base+24(FP), DI - MOVQ b_len+32(FP), DX - LEAQ ret+48(FP), R9 -#endif JMP cmpbody<>(SB) TEXT runtime·cmpstring(SB),NOSPLIT,$0-40 -#ifdef GOEXPERIMENT_regabiargs // AX = a_base (want in SI) // BX = a_len (want in BX) // CX = b_base (want in DI) @@ -33,13 +24,6 @@ TEXT runtime·cmpstring(SB),NOSPLIT,$0-40 MOVQ AX, SI MOVQ DI, DX MOVQ CX, DI -#else - MOVQ a_base+0(FP), SI - MOVQ a_len+8(FP), BX - MOVQ b_base+16(FP), DI - MOVQ b_len+24(FP), DX - LEAQ ret+32(FP), R9 -#endif JMP cmpbody<>(SB) // input: @@ -47,12 +31,8 @@ TEXT runtime·cmpstring(SB),NOSPLIT,$0-40 // DI = b // BX = alen // DX = blen -#ifndef GOEXPERIMENT_regabiargs -// R9 = address of output word (stores -1/0/1 here) -#else // output: // AX = output (-1/0/1) -#endif TEXT cmpbody<>(SB),NOSPLIT,$0-0 CMPQ SI, DI JEQ allsame @@ -100,9 +80,6 @@ diff16: CMPB CX, (DI)(BX*1) SETHI AX LEAQ -1(AX*2), AX // convert 1/0 to +1/-1 -#ifndef GOEXPERIMENT_regabiargs - MOVQ AX, (R9) -#endif RET // 0 through 16 bytes left, alen>=8, blen>=8 @@ -128,9 +105,6 @@ diff8: SHRQ CX, AX // move a's bit to bottom ANDQ $1, AX // mask bit LEAQ -1(AX*2), AX // 1/0 => +1/-1 -#ifndef GOEXPERIMENT_regabiargs - MOVQ AX, (R9) -#endif RET // 0-7 bytes in common @@ -169,9 +143,6 @@ di_finish: SHRQ CX, SI // move a's bit to bottom ANDQ $1, SI // mask bit LEAQ -1(SI*2), AX // 1/0 => +1/-1 -#ifndef GOEXPERIMENT_regabiargs - MOVQ AX, (R9) -#endif RET allsame: @@ -181,9 +152,6 @@ allsame: SETGT AX // 1 if alen > blen SETEQ CX // 1 if alen == blen LEAQ -1(CX)(AX*2), AX // 1,0,-1 result -#ifndef GOEXPERIMENT_regabiargs - MOVQ AX, (R9) -#endif RET // this works for >= 64 bytes of data. diff --git a/src/internal/bytealg/equal_amd64.s b/src/internal/bytealg/equal_amd64.s index 6f12d2a169..dd46e2e0fd 100644 --- a/src/internal/bytealg/equal_amd64.s +++ b/src/internal/bytealg/equal_amd64.s @@ -7,7 +7,6 @@ // memequal(a, b unsafe.Pointer, size uintptr) bool TEXT runtime·memequal(SB),NOSPLIT,$0-25 -#ifdef GOEXPERIMENT_regabiargs // AX = a (want in SI) // BX = b (want in DI) // CX = size (want in BX) @@ -20,22 +19,9 @@ neq: MOVQ BX, DI MOVQ CX, BX JMP memeqbody<>(SB) -#else - MOVQ a+0(FP), SI - MOVQ b+8(FP), DI - CMPQ SI, DI - JEQ eq - MOVQ size+16(FP), BX - LEAQ ret+24(FP), AX - JMP memeqbody<>(SB) -eq: - MOVB $1, ret+24(FP) - RET -#endif // memequal_varlen(a, b unsafe.Pointer) bool TEXT runtime·memequal_varlen(SB),NOSPLIT,$0-17 -#ifdef GOEXPERIMENT_regabiargs // AX = a (want in SI) // BX = b (want in DI) // 8(DX) = size (want in BX) @@ -48,29 +34,13 @@ neq: MOVQ BX, DI MOVQ 8(DX), BX // compiler stores size at offset 8 in the closure JMP memeqbody<>(SB) -#else - MOVQ a+0(FP), SI - MOVQ b+8(FP), DI - CMPQ SI, DI - JEQ eq - MOVQ 8(DX), BX // compiler stores size at offset 8 in the closure - LEAQ ret+16(FP), AX - JMP memeqbody<>(SB) -eq: - MOVB $1, ret+16(FP) - RET -#endif // Input: // a in SI // b in DI // count in BX -#ifndef GOEXPERIMENT_regabiargs -// address of result byte in AX -#else // Output: // result in AX -#endif TEXT memeqbody<>(SB),NOSPLIT,$0-0 CMPQ BX, $8 JB small @@ -104,11 +74,7 @@ hugeloop: SUBQ $64, BX CMPL DX, $0xffff JEQ hugeloop -#ifdef GOEXPERIMENT_regabiargs XORQ AX, AX // return 0 -#else - MOVB $0, (AX) -#endif RET // 64 bytes at a time using ymm registers @@ -129,11 +95,7 @@ hugeloop_avx2: CMPL DX, $0xffffffff JEQ hugeloop_avx2 VZEROUPPER -#ifdef GOEXPERIMENT_regabiargs XORQ AX, AX // return 0 -#else - MOVB $0, (AX) -#endif RET bigloop_avx2: @@ -150,11 +112,7 @@ bigloop: SUBQ $8, BX CMPQ CX, DX JEQ bigloop -#ifdef GOEXPERIMENT_regabiargs XORQ AX, AX // return 0 -#else - MOVB $0, (AX) -#endif RET // remaining 0-8 bytes @@ -162,11 +120,7 @@ leftover: MOVQ -8(SI)(BX*1), CX MOVQ -8(DI)(BX*1), DX CMPQ CX, DX -#ifdef GOEXPERIMENT_regabiargs SETEQ AX -#else - SETEQ (AX) -#endif RET small: @@ -201,10 +155,5 @@ di_finish: SUBQ SI, DI SHLQ CX, DI equal: -#ifdef GOEXPERIMENT_regabiargs SETEQ AX -#else - SETEQ (AX) -#endif RET - diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index 2d8f4c2412..2083ecb53e 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -277,7 +277,6 @@ TEXT gogo<>(SB), NOSPLIT, $0 // Switch to m->g0's stack, call fn(g). // Fn must never return. It should gogo(&g->sched) // to keep running g. -#ifdef GOEXPERIMENT_regabiargs TEXT runtime·mcall(SB), NOSPLIT, $0-8 MOVQ AX, DX // DX = fn @@ -306,38 +305,6 @@ goodm: POPQ AX JMP runtime·badmcall2(SB) RET -#else -TEXT runtime·mcall(SB), NOSPLIT, $0-8 - MOVQ fn+0(FP), DI - - get_tls(CX) - MOVQ g(CX), AX // save state in g->sched - MOVQ 0(SP), BX // caller's PC - MOVQ BX, (g_sched+gobuf_pc)(AX) - LEAQ fn+0(FP), BX // caller's SP - MOVQ BX, (g_sched+gobuf_sp)(AX) - MOVQ BP, (g_sched+gobuf_bp)(AX) - - // switch to m->g0 & its stack, call fn - MOVQ g(CX), BX - MOVQ g_m(BX), BX - MOVQ m_g0(BX), SI - CMPQ SI, AX // if g == m->g0 call badmcall - JNE 3(PC) - MOVQ $runtime·badmcall(SB), AX - JMP AX - MOVQ SI, g(CX) // g = m->g0 - MOVQ SI, R14 // set the g register - MOVQ (g_sched+gobuf_sp)(SI), SP // sp = m->g0->sched.sp - PUSHQ AX - MOVQ DI, DX - MOVQ 0(DI), DI - CALL DI - POPQ AX - MOVQ $runtime·badmcall2(SB), AX - JMP AX - RET -#endif // systemstack_switch is a dummy routine that systemstack leaves at the bottom // of the G stack. We need to distinguish the routine that @@ -465,7 +432,6 @@ TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0 MOVL $0, DX JMP runtime·morestack(SB) -#ifdef GOEXPERIMENT_regabireflect // spillArgs stores return values from registers to a *internal/abi.RegArgs in R12. TEXT ·spillArgs(SB),NOSPLIT,$0-0 MOVQ AX, 0(R12) @@ -521,15 +487,6 @@ TEXT ·unspillArgs(SB),NOSPLIT,$0-0 MOVQ 176(R12), X13 MOVQ 184(R12), X14 RET -#else -// spillArgs stores return values from registers to a pointer in R12. -TEXT ·spillArgs(SB),NOSPLIT,$0-0 - RET - -// unspillArgs loads args into registers from a pointer in R12. -TEXT ·unspillArgs(SB),NOSPLIT,$0-0 - RET -#endif // reflectcall: call a function with the given argument list // func call(stackArgsType *_type, f *FuncVal, stackArgs *byte, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs). @@ -988,61 +945,34 @@ done: // func memhash(p unsafe.Pointer, h, s uintptr) uintptr // hash function using AES hardware instructions TEXT runtime·memhash(SB),NOSPLIT,$0-32 -#ifdef GOEXPERIMENT_regabiargs // AX = ptr to data // BX = seed // CX = size -#endif CMPB runtime·useAeshash(SB), $0 JEQ noaes -#ifndef GOEXPERIMENT_regabiargs - MOVQ p+0(FP), AX // ptr to data - MOVQ s+16(FP), CX // size - LEAQ ret+24(FP), DX -#endif JMP aeshashbody<>(SB) noaes: JMP runtime·memhashFallback(SB) // func strhash(p unsafe.Pointer, h uintptr) uintptr TEXT runtime·strhash(SB),NOSPLIT,$0-24 -#ifdef GOEXPERIMENT_regabiargs // AX = ptr to string struct // BX = seed -#endif CMPB runtime·useAeshash(SB), $0 JEQ noaes -#ifndef GOEXPERIMENT_regabiargs - MOVQ p+0(FP), AX // ptr to string struct -#endif MOVQ 8(AX), CX // length of string MOVQ (AX), AX // string data -#ifndef GOEXPERIMENT_regabiargs - LEAQ ret+16(FP), DX -#endif JMP aeshashbody<>(SB) noaes: JMP runtime·strhashFallback(SB) // AX: data -#ifdef GOEXPERIMENT_regabiargs // BX: hash seed -#else -// h+8(FP): hash seed -#endif // CX: length -#ifdef GOEXPERIMENT_regabiargs // At return: AX = return value -#else -// DX: address to put return value -#endif TEXT aeshashbody<>(SB),NOSPLIT,$0-0 // Fill an SSE register with our seeds. -#ifdef GOEXPERIMENT_regabiargs MOVQ BX, X0 // 64 bits of per-table hash seed -#else - MOVQ h+8(FP), X0 // 64 bits of per-table hash seed -#endif PINSRW $4, CX, X0 // 16 bits of length PSHUFHW $0, X0, X0 // repeat length 4 times total MOVO X0, X1 // save unscrambled seed @@ -1079,11 +1009,7 @@ final1: AESENC X1, X1 // scramble combo 3 times AESENC X1, X1 AESENC X1, X1 -#ifdef GOEXPERIMENT_regabiargs MOVQ X1, AX // return X1 -#else - MOVQ X1, (DX) -#endif RET endofpage: @@ -1099,11 +1025,7 @@ endofpage: aes0: // Return scrambled input seed AESENC X0, X0 -#ifdef GOEXPERIMENT_regabiargs MOVQ X0, AX // return X0 -#else - MOVQ X0, (DX) -#endif RET aes16: @@ -1133,11 +1055,7 @@ aes17to32: // combine results PXOR X3, X2 -#ifdef GOEXPERIMENT_regabiargs MOVQ X2, AX // return X2 -#else - MOVQ X2, (DX) -#endif RET aes33to64: @@ -1179,11 +1097,7 @@ aes33to64: PXOR X6, X4 PXOR X7, X5 PXOR X5, X4 -#ifdef GOEXPERIMENT_regabiargs MOVQ X4, AX // return X4 -#else - MOVQ X4, (DX) -#endif RET aes65to128: @@ -1267,11 +1181,7 @@ aes65to128: PXOR X9, X8 // X15 must be zero on return PXOR X15, X15 -#ifdef GOEXPERIMENT_regabiargs MOVQ X8, AX // return X8 -#else - MOVQ X8, (DX) -#endif RET aes129plus: @@ -1389,37 +1299,22 @@ aesloop: PXOR X9, X8 // X15 must be zero on return PXOR X15, X15 -#ifdef GOEXPERIMENT_regabiargs MOVQ X8, AX // return X8 -#else - MOVQ X8, (DX) -#endif RET // func memhash32(p unsafe.Pointer, h uintptr) uintptr // ABIInternal for performance. TEXT runtime·memhash32(SB),NOSPLIT,$0-24 -#ifdef GOEXPERIMENT_regabiargs // AX = ptr to data // BX = seed -#endif CMPB runtime·useAeshash(SB), $0 JEQ noaes -#ifdef GOEXPERIMENT_regabiargs MOVQ BX, X0 // X0 = seed -#else - MOVQ p+0(FP), AX // ptr to data - MOVQ h+8(FP), X0 // seed -#endif PINSRD $2, (AX), X0 // data AESENC runtime·aeskeysched+0(SB), X0 AESENC runtime·aeskeysched+16(SB), X0 AESENC runtime·aeskeysched+32(SB), X0 -#ifdef GOEXPERIMENT_regabiargs MOVQ X0, AX // return X0 -#else - MOVQ X0, ret+16(FP) -#endif RET noaes: JMP runtime·memhash32Fallback(SB) @@ -1427,28 +1322,16 @@ noaes: // func memhash64(p unsafe.Pointer, h uintptr) uintptr // ABIInternal for performance. TEXT runtime·memhash64(SB),NOSPLIT,$0-24 -#ifdef GOEXPERIMENT_regabiargs // AX = ptr to data // BX = seed -#else -#endif CMPB runtime·useAeshash(SB), $0 JEQ noaes -#ifdef GOEXPERIMENT_regabiargs MOVQ BX, X0 // X0 = seed -#else - MOVQ p+0(FP), AX // ptr to data - MOVQ h+8(FP), X0 // seed -#endif PINSRQ $1, (AX), X0 // data AESENC runtime·aeskeysched+0(SB), X0 AESENC runtime·aeskeysched+16(SB), X0 AESENC runtime·aeskeysched+32(SB), X0 -#ifdef GOEXPERIMENT_regabiargs MOVQ X0, AX // return X0 -#else - MOVQ X0, ret+16(FP) -#endif RET noaes: JMP runtime·memhash64Fallback(SB) @@ -1925,146 +1808,61 @@ TEXT runtime·debugCallPanicked(SB),NOSPLIT,$16-16 // The tail call makes these stubs disappear in backtraces. // Defined as ABIInternal since they do not use the stack-based Go ABI. TEXT runtime·panicIndex(SB),NOSPLIT,$0-16 -#ifdef GOEXPERIMENT_regabiargs MOVQ CX, BX -#else - MOVQ AX, x+0(FP) - MOVQ CX, y+8(FP) -#endif JMP runtime·goPanicIndex(SB) TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16 -#ifdef GOEXPERIMENT_regabiargs MOVQ CX, BX -#else - MOVQ AX, x+0(FP) - MOVQ CX, y+8(FP) -#endif JMP runtime·goPanicIndexU(SB) TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16 -#ifdef GOEXPERIMENT_regabiargs MOVQ CX, AX MOVQ DX, BX -#else - MOVQ CX, x+0(FP) - MOVQ DX, y+8(FP) -#endif JMP runtime·goPanicSliceAlen(SB) TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-16 -#ifdef GOEXPERIMENT_regabiargs MOVQ CX, AX MOVQ DX, BX -#else - MOVQ CX, x+0(FP) - MOVQ DX, y+8(FP) -#endif JMP runtime·goPanicSliceAlenU(SB) TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-16 -#ifdef GOEXPERIMENT_regabiargs MOVQ CX, AX MOVQ DX, BX -#else - MOVQ CX, x+0(FP) - MOVQ DX, y+8(FP) -#endif JMP runtime·goPanicSliceAcap(SB) TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16 -#ifdef GOEXPERIMENT_regabiargs MOVQ CX, AX MOVQ DX, BX -#else - MOVQ CX, x+0(FP) - MOVQ DX, y+8(FP) -#endif JMP runtime·goPanicSliceAcapU(SB) TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16 -#ifdef GOEXPERIMENT_regabiargs MOVQ CX, BX -#else - MOVQ AX, x+0(FP) - MOVQ CX, y+8(FP) -#endif JMP runtime·goPanicSliceB(SB) TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16 -#ifdef GOEXPERIMENT_regabiargs MOVQ CX, BX -#else - MOVQ AX, x+0(FP) - MOVQ CX, y+8(FP) -#endif JMP runtime·goPanicSliceBU(SB) TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16 -#ifdef GOEXPERIMENT_regabiargs MOVQ DX, AX -#else - MOVQ DX, x+0(FP) - MOVQ BX, y+8(FP) -#endif JMP runtime·goPanicSlice3Alen(SB) TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-16 -#ifdef GOEXPERIMENT_regabiargs MOVQ DX, AX -#else - MOVQ DX, x+0(FP) - MOVQ BX, y+8(FP) -#endif JMP runtime·goPanicSlice3AlenU(SB) TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-16 -#ifdef GOEXPERIMENT_regabiargs MOVQ DX, AX -#else - MOVQ DX, x+0(FP) - MOVQ BX, y+8(FP) -#endif JMP runtime·goPanicSlice3Acap(SB) TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-16 -#ifdef GOEXPERIMENT_regabiargs MOVQ DX, AX -#else - MOVQ DX, x+0(FP) - MOVQ BX, y+8(FP) -#endif JMP runtime·goPanicSlice3AcapU(SB) TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-16 -#ifdef GOEXPERIMENT_regabiargs MOVQ CX, AX MOVQ DX, BX -#else - MOVQ CX, x+0(FP) - MOVQ DX, y+8(FP) -#endif JMP runtime·goPanicSlice3B(SB) TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16 -#ifdef GOEXPERIMENT_regabiargs MOVQ CX, AX MOVQ DX, BX -#else - MOVQ CX, x+0(FP) - MOVQ DX, y+8(FP) -#endif JMP runtime·goPanicSlice3BU(SB) TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16 -#ifdef GOEXPERIMENT_regabiargs MOVQ CX, BX -#else - MOVQ AX, x+0(FP) - MOVQ CX, y+8(FP) -#endif JMP runtime·goPanicSlice3C(SB) TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16 -#ifdef GOEXPERIMENT_regabiargs MOVQ CX, BX -#else - MOVQ AX, x+0(FP) - MOVQ CX, y+8(FP) -#endif JMP runtime·goPanicSlice3CU(SB) TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-16 -#ifdef GOEXPERIMENT_regabiargs MOVQ DX, AX -#else - MOVQ DX, x+0(FP) - MOVQ BX, y+8(FP) -#endif JMP runtime·goPanicSliceConvert(SB) #ifdef GOOS_android diff --git a/src/runtime/memclr_amd64.s b/src/runtime/memclr_amd64.s index 6c78869f4c..918a4b9e0e 100644 --- a/src/runtime/memclr_amd64.s +++ b/src/runtime/memclr_amd64.s @@ -13,14 +13,9 @@ // func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr) // ABIInternal for performance. TEXT runtime·memclrNoHeapPointers(SB), NOSPLIT, $0-16 -#ifdef GOEXPERIMENT_regabiargs // AX = ptr // BX = n MOVQ AX, DI // DI = ptr -#else - MOVQ ptr+0(FP), DI - MOVQ n+8(FP), BX -#endif XORQ AX, AX // MOVOU seems always faster than REP STOSQ. diff --git a/src/runtime/memmove_amd64.s b/src/runtime/memmove_amd64.s index af538d4bce..fa0c0e414f 100644 --- a/src/runtime/memmove_amd64.s +++ b/src/runtime/memmove_amd64.s @@ -34,18 +34,12 @@ // func memmove(to, from unsafe.Pointer, n uintptr) // ABIInternal for performance. TEXT runtime·memmove(SB), NOSPLIT, $0-24 -#ifdef GOEXPERIMENT_regabiargs // AX = to // BX = from // CX = n MOVQ AX, DI MOVQ BX, SI MOVQ CX, BX -#else - MOVQ to+0(FP), DI - MOVQ from+8(FP), SI - MOVQ n+16(FP), BX -#endif // REP instructions have a high startup cost, so we handle small sizes // with some straightline code. The REP MOVSQ instruction is really fast diff --git a/src/runtime/race_amd64.s b/src/runtime/race_amd64.s index 8a17113232..d42e415dca 100644 --- a/src/runtime/race_amd64.s +++ b/src/runtime/race_amd64.s @@ -46,11 +46,7 @@ // Defined as ABIInternal so as to avoid introducing a wrapper, // which would render runtime.getcallerpc ineffective. TEXT runtime·raceread(SB), NOSPLIT, $0-8 -#ifdef GOEXPERIMENT_regabiargs MOVQ AX, RARG1 -#else - MOVQ addr+0(FP), RARG1 -#endif MOVQ (SP), RARG2 // void __tsan_read(ThreadState *thr, void *addr, void *pc); MOVQ $__tsan_read(SB), AX @@ -76,11 +72,7 @@ TEXT runtime·racereadpc(SB), NOSPLIT, $0-24 // Defined as ABIInternal so as to avoid introducing a wrapper, // which would render runtime.getcallerpc ineffective. TEXT runtime·racewrite(SB), NOSPLIT, $0-8 -#ifdef GOEXPERIMENT_regabiargs MOVQ AX, RARG1 -#else - MOVQ addr+0(FP), RARG1 -#endif MOVQ (SP), RARG2 // void __tsan_write(ThreadState *thr, void *addr, void *pc); MOVQ $__tsan_write(SB), AX @@ -131,13 +123,8 @@ TEXT runtime·racereadrangepc1(SB), NOSPLIT, $0-24 // Defined as ABIInternal so as to avoid introducing a wrapper, // which would render runtime.getcallerpc ineffective. TEXT runtime·racewriterange(SB), NOSPLIT, $0-16 -#ifdef GOEXPERIMENT_regabiargs MOVQ AX, RARG1 MOVQ BX, RARG2 -#else - MOVQ addr+0(FP), RARG1 - MOVQ size+8(FP), RARG2 -#endif MOVQ (SP), RARG3 // void __tsan_write_range(ThreadState *thr, void *addr, uintptr size, void *pc); MOVQ $__tsan_write_range(SB), AX -- GitLab From aaf914d0e69198a96683c106abb5a931c4956f88 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Mon, 2 Aug 2021 16:02:45 -0400 Subject: [PATCH 0649/2500] [dev.cmdgo] cmd/go: remove modload.ModRoot function In some cases, ModRoot was being called in a multi module context. In those cases, pass in the correct main module. In other cases, a mainModule variable was already available, so call MainModules.ModRoot on that mainModule variable to make it more clear. In yet other cases ModRoot is just needed to determine GoMod, so determine modroot from the current directory in those cases. For #45713 Change-Id: I8c8aa633cfae40d0c8740bdbf985f2b60c9daf2c Reviewed-on: https://go-review.googlesource.com/c/go/+/339171 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/envcmd/env.go | 2 +- src/cmd/go/internal/modcmd/vendor.go | 2 +- src/cmd/go/internal/modget/get.go | 14 ++++++-- src/cmd/go/internal/modload/build.go | 2 +- src/cmd/go/internal/modload/import.go | 6 ++-- src/cmd/go/internal/modload/init.go | 48 +++++++++++--------------- src/cmd/go/internal/modload/load.go | 17 ++++++--- src/cmd/go/internal/modload/modfile.go | 2 +- src/cmd/go/internal/modload/vendor.go | 6 ++-- 9 files changed, 56 insertions(+), 43 deletions(-) diff --git a/src/cmd/go/internal/envcmd/env.go b/src/cmd/go/internal/envcmd/env.go index 5c45e34330..d23d539141 100644 --- a/src/cmd/go/internal/envcmd/env.go +++ b/src/cmd/go/internal/envcmd/env.go @@ -148,7 +148,7 @@ func ExtraEnvVars() []cfg.EnvVar { gomod := "" modload.Init() if modload.HasModRoot() { - gomod = filepath.Join(modload.ModRoot(), "go.mod") + gomod = modload.ModFilePath() } else if modload.Enabled() { gomod = os.DevNull } diff --git a/src/cmd/go/internal/modcmd/vendor.go b/src/cmd/go/internal/modcmd/vendor.go index 774fc3052f..a51ac21751 100644 --- a/src/cmd/go/internal/modcmd/vendor.go +++ b/src/cmd/go/internal/modcmd/vendor.go @@ -74,7 +74,7 @@ func runVendor(ctx context.Context, cmd *base.Command, args []string) { } _, pkgs := modload.LoadPackages(ctx, loadOpts, "all") - vdir := filepath.Join(modload.ModRoot(), "vendor") + vdir := filepath.Join(modload.VendorDir()) if err := os.RemoveAll(vdir); err != nil { base.Fatalf("go mod vendor: %v", err) } diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index 6eae44f1a4..3d831a14d8 100644 --- a/src/cmd/go/internal/modget/get.go +++ b/src/cmd/go/internal/modget/get.go @@ -724,7 +724,16 @@ func (r *resolver) performLocalQueries(ctx context.Context) { // restricted to matching packages in the main module. pkgPattern, mainModule := modload.MainModules.DirImportPath(ctx, q.pattern) if pkgPattern == "." { - return errSet(fmt.Errorf("%s%s is not within module rooted at %s", q.pattern, absDetail, modload.ModRoot())) + modload.MustHaveModRoot() + var modRoots []string + for _, m := range modload.MainModules.Versions() { + modRoots = append(modRoots, modload.MainModules.ModRoot(m)) + } + var plural string + if len(modRoots) != 1 { + plural = "s" + } + return errSet(fmt.Errorf("%s%s is not within module%s rooted at %s", q.pattern, absDetail, plural, strings.Join(modRoots, ", "))) } match := modload.MatchInModule(ctx, pkgPattern, mainModule, imports.AnyTags()) @@ -737,7 +746,8 @@ func (r *resolver) performLocalQueries(ctx context.Context) { return errSet(fmt.Errorf("no package in current directory")) } if !q.isWildcard() { - return errSet(fmt.Errorf("%s%s is not a package in module rooted at %s", q.pattern, absDetail, modload.ModRoot())) + modload.MustHaveModRoot() + return errSet(fmt.Errorf("%s%s is not a package in module rooted at %s", q.pattern, absDetail, modload.MainModules.ModRoot(mainModule))) } search.WarnUnmatched([]*search.Match{match}) return pathSet{} diff --git a/src/cmd/go/internal/modload/build.go b/src/cmd/go/internal/modload/build.go index 2973586479..3f2160d52d 100644 --- a/src/cmd/go/internal/modload/build.go +++ b/src/cmd/go/internal/modload/build.go @@ -323,7 +323,7 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li if filepath.IsAbs(r.Path) { info.Replace.Dir = r.Path } else { - info.Replace.Dir = filepath.Join(ModRoot(), r.Path) + info.Replace.Dir = filepath.Join(replacedFrom, r.Path) } info.Replace.GoMod = filepath.Join(info.Replace.Dir, "go.mod") } diff --git a/src/cmd/go/internal/modload/import.go b/src/cmd/go/internal/modload/import.go index 5741299281..de47974b9b 100644 --- a/src/cmd/go/internal/modload/import.go +++ b/src/cmd/go/internal/modload/import.go @@ -294,7 +294,7 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M if mainErr != nil { return module.Version{}, "", mainErr } - readVendorList() + readVendorList(mainModule) return vendorPkgModule[path], vendorDir, nil } @@ -653,11 +653,11 @@ func fetch(ctx context.Context, mod module.Version, needSum bool) (dir string, i if modRoot := MainModules.ModRoot(mod); modRoot != "" { return modRoot, true, nil } - if r, _ := Replacement(mod); r.Path != "" { + if r, replacedFrom := Replacement(mod); r.Path != "" { if r.Version == "" { dir = r.Path if !filepath.IsAbs(dir) { - dir = filepath.Join(ModRoot(), dir) + dir = filepath.Join(replacedFrom, dir) } // Ensure that the replacement directory actually exists: // dirInModule does not report errors for missing modules, diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 5dd946215b..1a91b83148 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -374,7 +374,6 @@ func Init() { } if inWorkspaceMode() { - _ = TODOWorkspaces("go.work.sum, and also allow modfetch to fall back to individual go.sums") _ = TODOWorkspaces("replaces") var err error @@ -403,8 +402,7 @@ func Init() { // // See golang.org/issue/32027. } else { - _ = TODOWorkspaces("Instead of modfile path, find modfile OR workfile path depending on mode") - modfetch.GoSumFile = strings.TrimSuffix(ModFilePath(), ".mod") + ".sum" + modfetch.GoSumFile = strings.TrimSuffix(modFilePath(modRoots[0]), ".mod") + ".sum" } } @@ -463,21 +461,8 @@ func Enabled() bool { return modRoots != nil || cfg.ModulesEnabled } -// ModRoot returns the root of the main module. -// It calls base.Fatalf if there is no main module. -func ModRoot() string { - if !HasModRoot() { - die() - } - if inWorkspaceMode() { - panic("ModRoot called in workspace mode") - } - // This is similar to MustGetSingleMainModule but we can't call that - // because MainModules may not yet exist when ModRoot is called. - if len(modRoots) != 1 { - panic("not in workspace mode but there are multiple ModRoots") - } - return modRoots[0] +func VendorDir() string { + return filepath.Join(MainModules.ModRoot(MainModules.mustGetSingleMainModule()), "vendor") } func inWorkspaceMode() bool { @@ -495,12 +480,21 @@ func HasModRoot() bool { return modRoots != nil } -// ModFilePath returns the effective path of the go.mod file. Normally, this -// "go.mod" in the directory returned by ModRoot, but the -modfile flag may -// change its location. ModFilePath calls base.Fatalf if there is no main +// MustHaveModRoot checks that a main module or main modules are present, +// and calls base.Fatalf if there are no main modules. +func MustHaveModRoot() { + Init() + if !HasModRoot() { + die() + } +} + +// ModFilePath returns the path that would be used for the go.mod +// file, if in module mode. ModFilePath calls base.Fatalf if there is no main // module, even if -modfile is set. func ModFilePath() string { - return modFilePath(ModRoot()) + MustHaveModRoot() + return modFilePath(findModuleRoot(base.Cwd())) } func modFilePath(modRoot string) string { @@ -674,7 +668,7 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { mainModule := MainModules.mustGetSingleMainModule() if cfg.BuildMod == "vendor" { - readVendorList() + readVendorList(mainModule) index := MainModules.Index(mainModule) modFile := MainModules.ModFile(mainModule) checkVendorConsistency(index, modFile) @@ -719,7 +713,7 @@ func CreateModFile(ctx context.Context, modPath string) { modRoot := base.Cwd() modRoots = []string{modRoot} Init() - modFilePath := ModFilePath() + modFilePath := modFilePath(modRoot) if _, err := fsys.Stat(modFilePath); err == nil { base.Fatalf("go: %s already exists", modFilePath) } @@ -1344,6 +1338,7 @@ func commitRequirements(ctx context.Context, goVersion string, rs *Requirements) return } mainModule := MainModules.Versions()[0] + modFilePath := modFilePath(MainModules.ModRoot(mainModule)) modFile := MainModules.ModFile(mainModule) var list []*modfile.Require @@ -1383,8 +1378,7 @@ func commitRequirements(ctx context.Context, goVersion string, rs *Requirements) } return } - gomod := ModFilePath() - if _, ok := fsys.OverlayPath(gomod); ok { + if _, ok := fsys.OverlayPath(modFilePath); ok { if dirty { base.Fatalf("go: updates to go.mod needed, but go.mod is part of the overlay specified with -overlay") } @@ -1422,7 +1416,7 @@ func commitRequirements(ctx context.Context, goVersion string, rs *Requirements) errNoChange := errors.New("no update needed") - err = lockedfile.Transform(ModFilePath(), func(old []byte) ([]byte, error) { + err = lockedfile.Transform(modFilePath, func(old []byte) ([]byte, error) { if bytes.Equal(old, new) { // The go.mod file is already equal to new, possibly as the result of some // other process. diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index dd69e2afbf..cb5a2d7a35 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -440,7 +440,16 @@ func matchLocalDirs(ctx context.Context, m *search.Match, rs *Requirements) { if !filepath.IsAbs(dir) { absDir = filepath.Join(base.Cwd(), dir) } - if search.InDir(absDir, cfg.GOROOTsrc) == "" && search.InDir(absDir, ModRoot()) == "" && pathInModuleCache(ctx, absDir, rs) == "" { + + modRoot := findModuleRoot(absDir) + found := false + for _, mod := range MainModules.Versions() { + if MainModules.ModRoot(mod) == modRoot { + found = true + break + } + } + if !found && search.InDir(absDir, cfg.GOROOTsrc) == "" && pathInModuleCache(ctx, absDir, rs) == "" { m.Dirs = []string{} m.AddError(fmt.Errorf("directory prefix %s outside available modules", base.ShortPath(absDir))) return @@ -513,7 +522,7 @@ func resolveLocalPackage(ctx context.Context, dir string, rs *Requirements) (str return "", fmt.Errorf("without -mod=vendor, directory %s has no package path", absDir) } - readVendorList() + readVendorList(mainModule) pkg := strings.TrimPrefix(suffix, "/vendor/") if _, ok := vendorPkgModule[pkg]; !ok { return "", fmt.Errorf("directory %s is not a package listed in vendor/modules.txt", absDir) @@ -582,10 +591,10 @@ func pathInModuleCache(ctx context.Context, dir string, rs *Requirements) string tryMod := func(m module.Version) (string, bool) { var root string var err error - if repl, _ := Replacement(m); repl.Path != "" && repl.Version == "" { + if repl, replModRoot := Replacement(m); repl.Path != "" && repl.Version == "" { root = repl.Path if !filepath.IsAbs(root) { - root = filepath.Join(ModRoot(), root) + root = filepath.Join(replModRoot, root) } } else if repl.Path != "" { root, err = modfetch.DownloadDir(repl) diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index bc5c83dffc..664fc0f91b 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -528,7 +528,7 @@ func goModSummary(m module.Version) (*modFileSummary, error) { // For every module other than the target, // return the full list of modules from modules.txt. - readVendorList() + readVendorList(MainModules.mustGetSingleMainModule()) // We don't know what versions the vendored module actually relies on, // so assume that it requires everything. diff --git a/src/cmd/go/internal/modload/vendor.go b/src/cmd/go/internal/modload/vendor.go index b2da3783ea..daa5888075 100644 --- a/src/cmd/go/internal/modload/vendor.go +++ b/src/cmd/go/internal/modload/vendor.go @@ -36,13 +36,13 @@ type vendorMetadata struct { } // readVendorList reads the list of vendored modules from vendor/modules.txt. -func readVendorList() { +func readVendorList(mainModule module.Version) { vendorOnce.Do(func() { vendorList = nil vendorPkgModule = make(map[string]module.Version) vendorVersion = make(map[string]string) vendorMeta = make(map[module.Version]vendorMetadata) - data, err := os.ReadFile(filepath.Join(ModRoot(), "vendor/modules.txt")) + data, err := os.ReadFile(filepath.Join(MainModules.ModRoot(mainModule), "vendor/modules.txt")) if err != nil { if !errors.Is(err, fs.ErrNotExist) { base.Fatalf("go: %s", err) @@ -136,7 +136,7 @@ func readVendorList() { // go 1.14) or at least does not contradict (go 1.13 or earlier) the // requirements and replacements listed in the main module's go.mod file. func checkVendorConsistency(index *modFileIndex, modFile *modfile.File) { - readVendorList() + readVendorList(MainModules.mustGetSingleMainModule()) pre114 := false if semver.Compare(index.goVersionV, "v1.14") < 0 { -- GitLab From 8ab59d812a222773c0a848aaa532630423eecc98 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 10 Aug 2021 12:49:21 -0700 Subject: [PATCH 0650/2500] [dev.typeparams] cmd/compile: change export version to 1.17 for testing This is a temporary change. We will revert this back before the 1.18 release. We make this change now to simplify testing, since a lot of tools will break on the new export version. Updates #47654. Change-Id: I0650fa753bb11229c71254d779dd61b5c1af9cdf Reviewed-on: https://go-review.googlesource.com/c/go/+/341211 Trust: Dan Scales Reviewed-by: Robert Griesemer Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/importer/iimport.go | 12 ++++++------ src/cmd/compile/internal/typecheck/iexport.go | 11 ++++++----- src/cmd/compile/internal/typecheck/iimport.go | 2 +- src/go/internal/gcimporter/iimport.go | 12 ++++++------ 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index 6051cdaf23..a317dfc34a 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -43,12 +43,12 @@ func (r *intReader) uint64() uint64 { // Keep this in sync with constants in iexport.go. const ( - iexportVersionGo1_11 = 0 - iexportVersionPosCol = 1 - iexportVersionGenerics = 2 + iexportVersionGo1_11 = 0 + iexportVersionPosCol = 1 + // TODO: before release, change this back to 2. + iexportVersionGenerics = iexportVersionPosCol - // Start of the unstable series of versions, remove "+ n" before release. - iexportVersionCurrent = iexportVersionGenerics + 1 + iexportVersionCurrent = iexportVersionGenerics ) type ident struct { @@ -99,7 +99,7 @@ func ImportData(imports map[string]*types2.Package, data, path string) (pkg *typ version = int64(r.uint64()) switch version { - case currentVersion, iexportVersionPosCol, iexportVersionGo1_11: + case /* iexportVersionGenerics, */ iexportVersionPosCol, iexportVersionGo1_11: default: if version > iexportVersionGenerics { errorf("unstable iexport format version %d, just rebuild compiler and std library", version) diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 5f510a0a25..75b4931c31 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -226,12 +226,13 @@ import ( // 1: added column details to Pos // 2: added information for generic function/types (currently unstable) const ( - iexportVersionGo1_11 = 0 - iexportVersionPosCol = 1 - iexportVersionGenerics = 2 + iexportVersionGo1_11 = 0 + iexportVersionPosCol = 1 + // TODO: before release, change this back to 2. Kept at previous version + // for now (for testing). + iexportVersionGenerics = iexportVersionPosCol - // Start of the unstable series of versions, remove "+ n" before release. - iexportVersionCurrent = iexportVersionGenerics + 1 + iexportVersionCurrent = iexportVersionGenerics ) // predeclReserved is the number of type offsets reserved for types diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 83974b6d56..2e3fdbc1bc 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -119,7 +119,7 @@ func ReadImports(pkg *types.Pkg, data string) { version := ird.uint64() switch version { - case iexportVersionCurrent, iexportVersionPosCol, iexportVersionGo1_11: + case /* iexportVersionGenerics, */ iexportVersionPosCol, iexportVersionGo1_11: default: if version > iexportVersionGenerics { base.Errorf("import %q: unstable export format version %d, just recompile", pkg.Path, version) diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go index d4778d3a74..dbc9b3a83e 100644 --- a/src/go/internal/gcimporter/iimport.go +++ b/src/go/internal/gcimporter/iimport.go @@ -43,12 +43,12 @@ func (r *intReader) uint64() uint64 { // Keep this in sync with constants in iexport.go. const ( - iexportVersionGo1_11 = 0 - iexportVersionPosCol = 1 - iexportVersionGenerics = 2 + iexportVersionGo1_11 = 0 + iexportVersionPosCol = 1 + // TODO: before release, change this back to 2. + iexportVersionGenerics = iexportVersionPosCol - // Start of the unstable series of versions, remove "+ n" before release. - iexportVersionCurrent = iexportVersionGenerics + 1 + iexportVersionCurrent = iexportVersionGenerics ) const predeclReserved = 32 @@ -91,7 +91,7 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, dataRea version = int64(r.uint64()) switch version { - case currentVersion, iexportVersionPosCol, iexportVersionGo1_11: + case /* iexportVersionGenerics, */ iexportVersionPosCol, iexportVersionGo1_11: default: if version > iexportVersionGenerics { errorf("unstable iexport format version %d, just rebuild compiler and std library", version) -- GitLab From 677dfe5ad677d7072ffd69963c407a8945e94ec5 Mon Sep 17 00:00:00 2001 From: zikaeroh Date: Tue, 3 Aug 2021 13:41:49 -0700 Subject: [PATCH 0651/2500] [dev.typeparams] cmd/compile: don't print out node pointer in ir.Dump This has been a part of the node dumping since the very beginning, but this makes diffing -W output pretty annoying. -d=dumpptrs already prints these out if needed. Change-Id: I9524a7f7b44ec780ae42a8a2a9588f11ab3950f9 Reviewed-on: https://go-review.googlesource.com/c/go/+/340253 Reviewed-by: Dan Scales Reviewed-by: Matthew Dempsky Trust: Dan Scales Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot --- src/cmd/compile/internal/ir/fmt.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index 3c5a928590..d19fe453ef 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -1006,7 +1006,7 @@ func (l Nodes) Format(s fmt.State, verb rune) { // Dump prints the message s followed by a debug dump of n. func Dump(s string, n Node) { - fmt.Printf("%s [%p]%+v\n", s, n, n) + fmt.Printf("%s%+v\n", s, n) } // DumpList prints the message s followed by a debug dump of each node in the list. -- GitLab From d397fc1169aa2491bc807812105371819366deb8 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Mon, 2 Aug 2021 15:54:51 -0400 Subject: [PATCH 0652/2500] [dev.cmdgo] don't give command-line-arguments a module Don't associate command-line-arguments with a module. Even though the sources in the command-line-arguments package may exist within the module's packages, the command-line-arguments package is distinct from the package in the module. It has its own identity, and further, even if all the same sources are listed, build tag filtering is not applied for command-line-arguments. For #45713 Change-Id: I555752021d58ea25e65699b4959f787ea5fa2cda Reviewed-on: https://go-review.googlesource.com/c/go/+/339170 Trust: Michael Matloob Trust: Bryan C. Mills Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/modload/build.go | 40 ++++--------------- .../mod_list_command_line_arguments.txt | 35 ++++++++++++++++ src/cmd/go/testdata/script/mod_outside.txt | 2 +- src/cmd/go/testdata/script/version.txt | 7 ++++ src/cmd/go/testdata/script/work.txt | 16 +++++++- 5 files changed, 65 insertions(+), 35 deletions(-) create mode 100644 src/cmd/go/testdata/script/mod_list_command_line_arguments.txt diff --git a/src/cmd/go/internal/modload/build.go b/src/cmd/go/internal/modload/build.go index 3f2160d52d..73b51c117a 100644 --- a/src/cmd/go/internal/modload/build.go +++ b/src/cmd/go/internal/modload/build.go @@ -341,15 +341,14 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li // for modules providing packages named by path and deps. path and deps must // name packages that were resolved successfully with LoadPackages. func PackageBuildInfo(path string, deps []string) string { - if isStandardImportPath(path) || !Enabled() { + if !Enabled() { return "" } - - target := mustFindModule(loaded, path, path) + target, _ := findModule(loaded, path) mdeps := make(map[module.Version]bool) for _, dep := range deps { - if !isStandardImportPath(dep) { - mdeps[mustFindModule(loaded, path, dep)] = true + if m, ok := findModule(loaded, dep); ok { + mdeps[m] = true } } var mods []module.Version @@ -375,7 +374,9 @@ func PackageBuildInfo(path string, deps []string) string { } } - writeEntry("mod", target) + if target.Path != "" { + writeEntry("mod", target) + } for _, mod := range mods { writeEntry("dep", mod) } @@ -383,29 +384,6 @@ func PackageBuildInfo(path string, deps []string) string { return buf.String() } -// mustFindModule is like findModule, but it calls base.Fatalf if the -// module can't be found. -// -// TODO(jayconrod): remove this. Callers should use findModule and return -// errors instead of relying on base.Fatalf. -func mustFindModule(ld *loader, target, path string) module.Version { - pkg, ok := ld.pkgCache.Get(path).(*loadPkg) - if ok { - if pkg.err != nil { - base.Fatalf("build %v: cannot load %v: %v", target, path, pkg.err) - } - return pkg.mod - } - - if path == "command-line-arguments" { - _ = TODOWorkspaces("support multiple main modules; search by modroot") - return MainModules.mustGetSingleMainModule() - } - - base.Fatalf("build %v: cannot find module for path %v", target, path) - panic("unreachable") -} - // findModule searches for the module that contains the package at path. // If the package was loaded, its containing module and true are returned. // Otherwise, module.Version{} and false are returned. @@ -413,10 +391,6 @@ func findModule(ld *loader, path string) (module.Version, bool) { if pkg, ok := ld.pkgCache.Get(path).(*loadPkg); ok { return pkg.mod, pkg.mod != module.Version{} } - if path == "command-line-arguments" { - _ = TODOWorkspaces("support multiple main modules; search by modroot") - return MainModules.mustGetSingleMainModule(), true - } return module.Version{}, false } diff --git a/src/cmd/go/testdata/script/mod_list_command_line_arguments.txt b/src/cmd/go/testdata/script/mod_list_command_line_arguments.txt new file mode 100644 index 0000000000..fd99ae84b2 --- /dev/null +++ b/src/cmd/go/testdata/script/mod_list_command_line_arguments.txt @@ -0,0 +1,35 @@ +# The command-line-arguments package does not belong to a module... +cd a +go list -f '{{.Module}}' ../b/b.go +stdout '^$' + +# ... even if the arguments are sources from that module +go list -f '{{.Module}}' a.go +stdout '^$' + +[short] skip + +# check that the version of command-line-arguments doesn't include a module +go build -o a.exe a.go +go version -m a.exe +stdout '^\tpath\tcommand-line-arguments$' +stdout '^\tdep\ta\t\(devel\)\t$' +! stdout mod + +-- a/go.mod -- +module a +go 1.17 +-- a/a.go -- +package main + +import "a/dep" + +func main() { + dep.D() +} +-- a/dep/dep.go -- +package dep + +func D() {} +-- b/b.go -- +package b \ No newline at end of file diff --git a/src/cmd/go/testdata/script/mod_outside.txt b/src/cmd/go/testdata/script/mod_outside.txt index 33341f7d4b..3b4559405a 100644 --- a/src/cmd/go/testdata/script/mod_outside.txt +++ b/src/cmd/go/testdata/script/mod_outside.txt @@ -251,7 +251,7 @@ stdout 'using example.com/version v1.0.1' # outside std. go run ./stdonly/stdonly.go stdout 'path is command-line-arguments$' -stdout 'main is command-line-arguments \(devel\)' +stdout 'main is $' # 'go generate' should work with file arguments. [exec:touch] go generate ./needmod/needmod.go diff --git a/src/cmd/go/testdata/script/version.txt b/src/cmd/go/testdata/script/version.txt index 8615a4aac5..f3aa57e8c7 100644 --- a/src/cmd/go/testdata/script/version.txt +++ b/src/cmd/go/testdata/script/version.txt @@ -28,6 +28,13 @@ go version -m fortune.exe stdout '^\tpath\trsc.io/fortune' stdout '^\tmod\trsc.io/fortune\tv1.0.0' +# Check the build info of a binary built from $GOROOT/src/cmd +go build -o test2json.exe cmd/test2json +go version -m test2json.exe +stdout '^test2json.exe: .+' +stdout '^\tpath\tcmd/test2json$' +! stdout 'mod' + # Repeat the test with -buildmode=pie. [!buildmode:pie] stop go build -buildmode=pie -o external.exe rsc.io/fortune diff --git a/src/cmd/go/testdata/script/work.txt b/src/cmd/go/testdata/script/work.txt index 9be0958579..095d6ff174 100644 --- a/src/cmd/go/testdata/script/work.txt +++ b/src/cmd/go/testdata/script/work.txt @@ -42,6 +42,13 @@ go run example.com/d cp go.work.backwards go.work go run example.com/d +# Test that command-line-arguments work inside and outside modules. +# This exercises the code that determines which module command-line-arguments +# belongs to. +go list ./b/main.go +go build -n -workfile=off -o foo foo.go +go build -n -o foo foo.go + -- go.work.dup -- go 1.17 @@ -123,4 +130,11 @@ directory ( d b a -) \ No newline at end of file +) + +-- foo.go -- +package main +import "fmt" +func main() { + fmt.Println("Hello, World") +} -- GitLab From 46fd547d899286982971474b329d7a95da4f2a6b Mon Sep 17 00:00:00 2001 From: Carlos Amedee Date: Wed, 11 Aug 2021 17:19:21 -0400 Subject: [PATCH 0653/2500] internal/goversion: update Version to 1.18 This is the start of the Go 1.18 development cycle, so update the Version value accordingly. It represents the Go 1.x version that will soon open up for development (and eventually become released). Updates #40705 Updates #47351 Change-Id: Icfb99e28529a3c9fb7394e114a34586f613dfcbf Reviewed-on: https://go-review.googlesource.com/c/go/+/341590 Trust: Carlos Amedee Run-TryBot: Carlos Amedee TryBot-Result: Go Bot Reviewed-by: Dmitri Shuralyov Reviewed-by: Matthew Dempsky Reviewed-by: Alexander Rakoczy --- src/internal/goversion/goversion.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal/goversion/goversion.go b/src/internal/goversion/goversion.go index 4cc15688c0..8fcea100dc 100644 --- a/src/internal/goversion/goversion.go +++ b/src/internal/goversion/goversion.go @@ -9,4 +9,4 @@ package goversion // // It should be updated at the start of each development cycle to be // the version of the next Go 1.x release. See golang.org/issue/40705. -const Version = 17 +const Version = 18 -- GitLab From 7e9f911ec4fd08ce9b4296f0aea4864b53064573 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Thu, 12 Aug 2021 09:58:54 -0700 Subject: [PATCH 0654/2500] [dev.typeparams] cmd/compile: remove some shape checks in type substituter, other cleanups The type substituter (typecheck.Typ()) was temporarily substituting from shapes back to concrete types, but doesn't need to anymore. So, remove two shape checks, so the type substituter is now only for substituting type params again. Several other cleanups: - renamed makeGenericName() to makeInstName1(), since that function is a helper to MakeInstName() and MakeDictName() that definitely makes instantiated names, not generic names. - removed the logic in makeInstName1() that adds the ".inst." prefix for concrete type args. We are only specifying concrete type args (as opposed to shape args) when we are calling from MakeDictName, and then we immediately strip of the .inst prefix anyway. - Added a comment on types.Identical that a shape type is considered identicall to another type if their underlying types are the same, or they are both pointers. Change-Id: I3e0206dbd403897797ae7bec3c527ae16b0b930a Reviewed-on: https://go-review.googlesource.com/c/go/+/341729 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Dan Scales --- src/cmd/compile/internal/typecheck/subr.go | 40 ++++++---------------- src/cmd/compile/internal/types/identity.go | 7 ++-- 2 files changed, 15 insertions(+), 32 deletions(-) diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index e86c4c6bca..c7a3718b31 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -900,31 +900,11 @@ func TypesOf(x []ir.Node) []*types.Type { return r } -// makeGenericName returns the name of the generic function instantiated -// with the given types. -// name is the name of the generic function or method. -func makeGenericName(name string, targs []*types.Type, hasBrackets bool) string { +// makeInstName1 returns the name of the generic function instantiated with the +// given types, which can have type params or shapes, or be concrete types. name is +// the name of the generic function or method. +func makeInstName1(name string, targs []*types.Type, hasBrackets bool) string { b := bytes.NewBufferString("") - - // Determine if the type args are concrete types or new typeparams. - hasTParam := false - for _, targ := range targs { - if hasTParam { - assert(targ.HasTParam() || targ.HasShape()) - } else if targ.HasTParam() || targ.HasShape() { - hasTParam = true - } - } - - // Marker to distinguish generic instantiations from fully stenciled wrapper functions. - // Once we move to GC shape implementations, this prefix will not be necessary as the - // GC shape naming will distinguish them. - // e.g. f[8bytenonpointer] vs. f[int]. - // For now, we use .inst.f[int] vs. f[int]. - if !hasTParam { - b.WriteString(".inst.") - } - i := strings.Index(name, "[") assert(hasBrackets == (i >= 0)) if i >= 0 { @@ -963,7 +943,7 @@ func makeGenericName(name string, targs []*types.Type, hasBrackets bool) string // MakeInstName makes the unique name for a stenciled generic function or method, // based on the name of the function fnsym and the targs. It replaces any -// existing bracket type list in the name. makeInstName asserts that fnsym has +// existing bracket type list in the name. MakeInstName asserts that fnsym has // brackets in its name if and only if hasBrackets is true. // // Names of declared generic functions have no brackets originally, so hasBrackets @@ -974,7 +954,7 @@ func makeGenericName(name string, targs []*types.Type, hasBrackets bool) string // The standard naming is something like: 'genFn[int,bool]' for functions and // '(*genType[int,bool]).methodName' for methods func MakeInstName(gf *types.Sym, targs []*types.Type, hasBrackets bool) *types.Sym { - return gf.Pkg.Lookup(makeGenericName(gf.Name, targs, hasBrackets)) + return gf.Pkg.Lookup(makeInstName1(gf.Name, targs, hasBrackets)) } func MakeDictName(gf *types.Sym, targs []*types.Type, hasBrackets bool) *types.Sym { @@ -987,8 +967,8 @@ func MakeDictName(gf *types.Sym, targs []*types.Type, hasBrackets bool) *types.S panic("dictionary should always have concrete type args") } } - name := makeGenericName(gf.Name, targs, hasBrackets) - name = ".dict." + name[6:] + name := makeInstName1(gf.Name, targs, hasBrackets) + name = ".dict." + name return gf.Pkg.Lookup(name) } @@ -1014,14 +994,14 @@ type Tsubster struct { // result is t; otherwise the result is a new type. It deals with recursive types // by using TFORW types and finding partially or fully created types via sym.Def. func (ts *Tsubster) Typ(t *types.Type) *types.Type { - if !t.HasTParam() && !t.HasShape() && t.Kind() != types.TFUNC { + if !t.HasTParam() && t.Kind() != types.TFUNC { // Note: function types need to be copied regardless, as the // types of closures may contain declarations that need // to be copied. See #45738. return t } - if t.IsTypeParam() || t.IsShape() { + if t.IsTypeParam() { for i, tp := range ts.Tparams { if tp == t { return ts.Targs[i] diff --git a/src/cmd/compile/internal/types/identity.go b/src/cmd/compile/internal/types/identity.go index dc39acced8..2e9e2f4fd8 100644 --- a/src/cmd/compile/internal/types/identity.go +++ b/src/cmd/compile/internal/types/identity.go @@ -4,8 +4,11 @@ package types -// Identical reports whether t1 and t2 are identical types, following -// the spec rules. Receiver parameter types are ignored. +// Identical reports whether t1 and t2 are identical types, following the spec rules. +// Receiver parameter types are ignored. Named (defined) types are only equal if they +// are pointer-equal - i.e. there must be a unique types.Type for each specific named +// type. Also, a type containing a shape type is considered identical to another type +// (shape or not) if their underlying types are the same, or they are both pointers. func Identical(t1, t2 *Type) bool { return identical(t1, t2, true, nil) } -- GitLab From 044ec4fa9818d785e2b0d4064514abcf4f252fcb Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 6 Aug 2021 13:21:25 -0400 Subject: [PATCH 0655/2500] time: fix docs for new comma layouts The current text is slightly inaccurate. Make it more correct. Change-Id: Iebe0051b74649d13982d7eefe3697f9e69c9b75d Reviewed-on: https://go-review.googlesource.com/c/go/+/340449 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Jay Conrod Reviewed-by: Damien Neil Reviewed-by: Ian Lance Taylor TryBot-Result: Go Bot --- doc/go1.17.html | 14 +++++++------- src/time/format.go | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/go1.17.html b/doc/go1.17.html index b65d13a040..c1b5ab3f6f 100644 --- a/doc/go1.17.html +++ b/doc/go1.17.html @@ -753,9 +753,9 @@ func Foo() bool {

The new - NullInt16 - and - NullByte + NullInt16 + and + NullByte structs represent the int16 and byte values that may be null. These can be used as destinations of the Scan method, similar to NullString. @@ -1205,11 +1205,11 @@ func Foo() bool {

The package now accepts comma "," as a separator for fractional seconds when parsing and formatting time. - The following time formats are now accepted: + For example, the following time layouts are now accepted:

    -
  • 2006-01-02 14:06:03,999999999 -0700 MST
  • -
  • Mon Jan _2 14:06:03,120007 2006
  • -
  • Mon Jan 2 14:06:03,120007 2006
  • +
  • 2006-01-02 15:04:05,999999999 -0700 MST
  • +
  • Mon Jan _2 15:04:05,000000 2006
  • +
  • Monday, January 2 15:04:05,000 2006

diff --git a/src/time/format.go b/src/time/format.go index bb173a21c2..f4b4f48142 100644 --- a/src/time/format.go +++ b/src/time/format.go @@ -77,9 +77,9 @@ import "errors" // The formats and 002 are space-padded and zero-padded // three-character day of year; there is no unpadded day of year format. // -// A decimal point followed by one or more zeros represents a fractional -// second, printed to the given number of decimal places. -// Either a comma or decimal point followed by one or more nines represents +// A comma or decimal point followed by one or more zeros represents +// a fractional second, printed to the given number of decimal places. +// A comma or decimal point followed by one or more nines represents // a fractional second, printed to the given number of decimal places, with // trailing zeros removed. // For example "15:04:05,000" or "15:04:05.000" formats or parses with -- GitLab From e2e1987b31a587bdb67856954ae9279721b3bba7 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Thu, 12 Aug 2021 14:33:58 -0700 Subject: [PATCH 0656/2500] [dev.cmdgo] cmd/link: fix TestBuildForTvOS This test was broken in CL 334732 on darwin. The test invokes 'go build' with a CC containing the arguments -framework CoreFoundation. Previously, the go command split CC on whitespace, and inserted the arguments after the command line when running CC directly. Those arguments weren't passed to cgo though, so cgo ran CC without -framework CoreFoundation (or any of the other flags). In CL 334732, we pass CC through to cgo, and cgo splits arguments using str.SplitQuotedFields. So -framework CoreFoundation actually gets passed to the C compiler. It appears that -framework flags are only meant to be used in linking operations, so when cgo invokes clang with -E (run preprocessor only), clang emits an error that -framework is unused. This change fixes the test by moving -framework CoreFoundation out of CC and into CGO_LDFLAGS. Change-Id: Ie884c3c0d8bea21fad57f325d19989ad39de7204 Reviewed-on: https://go-review.googlesource.com/c/go/+/341929 Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills Trust: Jay Conrod --- src/cmd/link/link_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go index 7230054bed..77d42cceda 100644 --- a/src/cmd/link/link_test.go +++ b/src/cmd/link/link_test.go @@ -282,8 +282,8 @@ func TestBuildForTvOS(t *testing.T) { "-isysroot", strings.TrimSpace(string(sdkPath)), "-mtvos-version-min=12.0", "-fembed-bitcode", - "-framework", "CoreFoundation", } + CGO_LDFLAGS := []string{"-framework", "CoreFoundation"} lib := filepath.Join("testdata", "testBuildFortvOS", "lib.go") tmpDir := t.TempDir() @@ -295,12 +295,14 @@ func TestBuildForTvOS(t *testing.T) { "GOARCH=arm64", "CC="+strings.Join(CC, " "), "CGO_CFLAGS=", // ensure CGO_CFLAGS does not contain any flags. Issue #35459 + "CGO_LDFLAGS="+strings.Join(CGO_LDFLAGS, " "), ) if out, err := cmd.CombinedOutput(); err != nil { t.Fatalf("%v: %v:\n%s", cmd.Args, err, out) } link := exec.Command(CC[0], CC[1:]...) + link.Args = append(link.Args, CGO_LDFLAGS...) link.Args = append(link.Args, "-o", filepath.Join(tmpDir, "a.out")) // Avoid writing to package directory. link.Args = append(link.Args, ar, filepath.Join("testdata", "testBuildFortvOS", "main.m")) if out, err := link.CombinedOutput(); err != nil { -- GitLab From 1fffeddfe9c977510d855277da57e0564700d6c3 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 20 Jul 2021 14:37:53 -0700 Subject: [PATCH 0657/2500] cmd/go: add -testsum flag to update go.sum in script tests -testsum may be set to "tidy", "listm", or "listall". When set, TestScript runs 'go mod tidy', 'go list -m -mod=mod all', or 'go list -mod=mod all' at the beginning of each test that has a go.mod file in its root directory. If the test passes and go.mod or go.sum was updated, TestScript will rewrite the test file with the initial content of go.mod and go.sum (after the above command). This is useful for writing tests that need a working go.sum and for fixing tests that rely on -mod=mod. For golang/go#41302 Change-Id: I63a5667621a5082ccedfc1bff33c3969c29e8b3d Reviewed-on: https://go-review.googlesource.com/c/go/+/336150 Run-TryBot: Jay Conrod TryBot-Result: Go Bot Trust: Jay Conrod Reviewed-by: Michael Matloob Reviewed-on: https://go-review.googlesource.com/c/go/+/341932 Reviewed-by: Bryan C. Mills --- src/cmd/go/script_test.go | 81 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go index 639e907db0..9ca297e89b 100644 --- a/src/cmd/go/script_test.go +++ b/src/cmd/go/script_test.go @@ -11,6 +11,7 @@ import ( "bytes" "context" "errors" + "flag" "fmt" "go/build" "internal/testenv" @@ -35,6 +36,8 @@ import ( "cmd/internal/sys" ) +var testSum = flag.String("testsum", "", `may be tidy, listm, or listall. If set, TestScript generates a go.sum file at the beginning of each test and updates test files if they pass.`) + // TestScript runs the tests in testdata/script/*.txt. func TestScript(t *testing.T) { testenv.MustHaveGoBuild(t) @@ -269,6 +272,22 @@ func (ts *testScript) run() { ts.mark = ts.log.Len() } + // With -testsum, if a go.mod file is present in the test's initial + // working directory, run 'go mod tidy'. + if *testSum != "" { + if ts.updateSum(a) { + defer func() { + if ts.t.Failed() { + return + } + data := txtar.Format(a) + if err := os.WriteFile(ts.file, data, 0666); err != nil { + ts.t.Errorf("rewriting test file: %v", err) + } + }() + } + } + // Run script. // See testdata/script/README for documentation of script form. script := string(a.Comment) @@ -1341,6 +1360,68 @@ func (ts *testScript) parse(line string) command { return cmd } +// updateSum runs 'go mod tidy', 'go list -mod=mod -m all', or +// 'go list -mod=mod all' in the test's current directory if a file named +// "go.mod" is present after the archive has been extracted. updateSum modifies +// archive and returns true if go.mod or go.sum were changed. +func (ts *testScript) updateSum(archive *txtar.Archive) (rewrite bool) { + gomodIdx, gosumIdx := -1, -1 + for i := range archive.Files { + switch archive.Files[i].Name { + case "go.mod": + gomodIdx = i + case "go.sum": + gosumIdx = i + } + } + if gomodIdx < 0 { + return false + } + + switch *testSum { + case "tidy": + ts.cmdGo(success, []string{"mod", "tidy"}) + case "listm": + ts.cmdGo(success, []string{"list", "-m", "-mod=mod", "all"}) + case "listall": + ts.cmdGo(success, []string{"list", "-mod=mod", "all"}) + default: + ts.t.Fatalf(`unknown value for -testsum %q; may be "tidy", "listm", or "listall"`, *testSum) + } + + newGomodData, err := os.ReadFile(filepath.Join(ts.cd, "go.mod")) + if err != nil { + ts.t.Fatalf("reading go.mod after -testsum: %v", err) + } + if !bytes.Equal(newGomodData, archive.Files[gomodIdx].Data) { + archive.Files[gomodIdx].Data = newGomodData + rewrite = true + } + + newGosumData, err := os.ReadFile(filepath.Join(ts.cd, "go.sum")) + if err != nil && !os.IsNotExist(err) { + ts.t.Fatalf("reading go.sum after -testsum: %v", err) + } + switch { + case os.IsNotExist(err) && gosumIdx >= 0: + // go.sum was deleted. + rewrite = true + archive.Files = append(archive.Files[:gosumIdx], archive.Files[gosumIdx+1:]...) + case err == nil && gosumIdx < 0: + // go.sum was created. + rewrite = true + gosumIdx = gomodIdx + 1 + archive.Files = append(archive.Files, txtar.File{}) + copy(archive.Files[gosumIdx+1:], archive.Files[gosumIdx:]) + archive.Files[gosumIdx] = txtar.File{Name: "go.sum", Data: newGosumData} + case err == nil && gosumIdx >= 0 && !bytes.Equal(newGosumData, archive.Files[gosumIdx].Data): + // go.sum was changed. + rewrite = true + archive.Files[gosumIdx].Data = newGosumData + } + return rewrite +} + // diff returns a formatted diff of the two texts, // showing the entire text and the minimum line-level // additions and removals to turn text1 into text2. -- GitLab From 4be75faa3ee79a273ff82d4f5b7f838ef3642f9d Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 20 Jul 2021 14:46:40 -0700 Subject: [PATCH 0658/2500] cmd/go: make fewer 'go mod' commands update go.mod 'go mod graph', 'go mod vendor', 'go mod verify', and 'go mod why' will no longer edit go.mod or go.sum. 'go mod graph', 'go mod verify', and 'go mod why' may still fetch files and look up packages as if they were able to update go.mod. They're useful for debugging and should still work when go.mod is a little broken. This is implemented in modload.setDefaultBuildMod based on command name for now. Super gross. Sorry. This should be fixed with a larger refactoring for #40775. Fixes golang/go#45551 Change-Id: If5f225937180d32e9a5dd252c78d988042bbdedf Reviewed-on: https://go-review.googlesource.com/c/go/+/336151 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Michael Matloob Reviewed-on: https://go-review.googlesource.com/c/go/+/341933 Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/modload/init.go | 21 +++++++++++++---- src/cmd/go/testdata/script/mod_all.txt | 2 +- src/cmd/go/testdata/script/mod_e.txt | 23 ++++++++++++------- src/cmd/go/testdata/script/mod_get_commit.txt | 2 +- .../go/testdata/script/mod_getmode_vendor.txt | 1 + .../go/testdata/script/mod_list_retract.txt | 4 +++- src/cmd/go/testdata/script/mod_retention.txt | 8 ++++--- src/cmd/go/testdata/script/mod_tidy_error.txt | 4 ++-- .../go/testdata/script/mod_vendor_replace.txt | 5 +++- .../testdata/script/mod_vendor_trimpath.txt | 6 ++++- .../script/mod_vendor_unused_only.txt | 2 ++ src/cmd/go/testdata/script/mod_verify.txt | 5 ---- src/cmd/go/testdata/script/modfile_flag.txt | 5 ++++ 13 files changed, 61 insertions(+), 27 deletions(-) diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 45f724d5e3..d5f9d10422 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -686,12 +686,25 @@ func setDefaultBuildMod() { return } - if cfg.CmdName == "get" || strings.HasPrefix(cfg.CmdName, "mod ") { - // 'get' and 'go mod' commands may update go.mod automatically. - // TODO(jayconrod): should this narrower? Should 'go mod download' or - // 'go mod graph' update go.mod by default? + // TODO(#40775): commands should pass in the module mode as an option + // to modload functions instead of relying on an implicit setting + // based on command name. + switch cfg.CmdName { + case "get", "mod download", "mod init", "mod tidy": + // These commands are intended to update go.mod and go.sum. cfg.BuildMod = "mod" return + case "mod graph", "mod verify", "mod why": + // These commands should not update go.mod or go.sum, but they should be + // able to fetch modules not in go.sum and should not report errors if + // go.mod is inconsistent. They're useful for debugging, and they need + // to work in buggy situations. + cfg.BuildMod = "mod" + allowWriteGoMod = false + return + case "mod vendor": + cfg.BuildMod = "readonly" + return } if modRoot == "" { if allowMissingModuleImports { diff --git a/src/cmd/go/testdata/script/mod_all.txt b/src/cmd/go/testdata/script/mod_all.txt index 090eeee22d..6fa2d83239 100644 --- a/src/cmd/go/testdata/script/mod_all.txt +++ b/src/cmd/go/testdata/script/mod_all.txt @@ -315,7 +315,7 @@ go 1.15 require ( example.com/a v0.1.0 - example.com/b v0.1.0 + example.com/b v0.1.0 // indirect example.com/q v0.1.0 example.com/r v0.1.0 // indirect example.com/t v0.1.0 diff --git a/src/cmd/go/testdata/script/mod_e.txt b/src/cmd/go/testdata/script/mod_e.txt index 3a0d18dabc..3cffaf6ef1 100644 --- a/src/cmd/go/testdata/script/mod_e.txt +++ b/src/cmd/go/testdata/script/mod_e.txt @@ -24,11 +24,11 @@ cmp go.mod.orig go.mod ! go mod vendor -stderr '^example.com/untidy imports\n\texample.net/directnotfound: cannot find module providing package example.net/directnotfound: module example.net/directnotfound: reading http://.*: 404 Not Found$' +stderr '^example.com/untidy imports\n\texample.net/directnotfound: no required module provides package example.net/directnotfound; to add it:\n\tgo get example.net/directnotfound$' -stderr '^example.com/untidy imports\n\texample.net/m imports\n\texample.net/indirectnotfound: cannot find module providing package example.net/indirectnotfound: module example.net/indirectnotfound: reading http://.*: 404 Not Found$' +stderr '^example.com/untidy imports\n\texample.net/m: module example.net/m provides package example.net/m and is replaced but not required; to add it:\n\tgo get example.net/m@v0.1.0$' -stderr '^example.com/untidy tested by\n\texample.com/untidy.test imports\n\texample.net/directtestnotfound: cannot find module providing package example.net/directtestnotfound: module example.net/directtestnotfound: reading http://.*: 404 Not Found$' +stderr '^example.com/untidy tested by\n\texample.com/untidy.test imports\n\texample.net/directtestnotfound: no required module provides package example.net/directtestnotfound; to add it:\n\tgo get example.net/directtestnotfound$' ! stderr 'indirecttestnotfound' # Vendor prunes test dependencies. @@ -43,15 +43,22 @@ stderr -count=4 'cannot find module providing package' cmp go.mod.final go.mod -# 'go mod vendor -e' still logs the errors, but succeeds and updates go.mod. - +# 'go mod vendor -e' still logs the errors, but creates a vendor directory +# and exits with status 0. +# 'go mod vendor -e' does not update go.mod and will not vendor packages that +# would require changing go.mod, for example, by adding a requirement. cp go.mod.orig go.mod go mod vendor -e -stderr -count=3 'cannot find module providing package' -cmp go.mod.final go.mod +stderr -count=2 'no required module provides package' +stderr '^example.com/untidy imports\n\texample.net/m: module example.net/m provides package example.net/m and is replaced but not required; to add it:\n\tgo get example.net/m@v0.1.0$' exists vendor/modules.txt -exists vendor/example.net/m/m.go +! exists vendor/example.net +go mod edit -require example.net/m@v0.1.0 +go mod vendor -e +stderr -count=3 'no required module provides package' +exists vendor/modules.txt +exists vendor/example.net/m/m.go -- go.mod -- module example.com/untidy diff --git a/src/cmd/go/testdata/script/mod_get_commit.txt b/src/cmd/go/testdata/script/mod_get_commit.txt index 4649491a53..0cf94ae182 100644 --- a/src/cmd/go/testdata/script/mod_get_commit.txt +++ b/src/cmd/go/testdata/script/mod_get_commit.txt @@ -44,7 +44,7 @@ go mod edit -require rsc.io/quote@23179ee grep 'rsc.io/quote 23179ee' go.mod # but other commands fix them -go mod graph +go list -m -mod=mod all grep 'rsc.io/quote v1.5.1' go.mod -- go.mod -- diff --git a/src/cmd/go/testdata/script/mod_getmode_vendor.txt b/src/cmd/go/testdata/script/mod_getmode_vendor.txt index d3df2078b0..00070c03b5 100644 --- a/src/cmd/go/testdata/script/mod_getmode_vendor.txt +++ b/src/cmd/go/testdata/script/mod_getmode_vendor.txt @@ -25,6 +25,7 @@ stderr 'go list -m: can''t match module patterns using the vendor directory\n\t\ -- go.mod -- module x +go 1.16 -- x.go -- package x import _ "rsc.io/quote" diff --git a/src/cmd/go/testdata/script/mod_list_retract.txt b/src/cmd/go/testdata/script/mod_list_retract.txt index 4b13348515..b7147aa182 100644 --- a/src/cmd/go/testdata/script/mod_list_retract.txt +++ b/src/cmd/go/testdata/script/mod_list_retract.txt @@ -101,7 +101,9 @@ module example.com/use go 1.15 require example.com/retract v1.0.0-bad - +-- go.sum -- +example.com/retract v1.0.0-bad h1:liAW69rbtjY67x2CcNzat668L/w+YGgNX3lhJsWIJis= +example.com/retract v1.0.0-bad/go.mod h1:0DvGGofJ9hr1q63cBrOY/jSY52OwhRGA0K47NE80I5Y= -- use.go -- package use diff --git a/src/cmd/go/testdata/script/mod_retention.txt b/src/cmd/go/testdata/script/mod_retention.txt index 7a371b1806..481c10d2b7 100644 --- a/src/cmd/go/testdata/script/mod_retention.txt +++ b/src/cmd/go/testdata/script/mod_retention.txt @@ -39,12 +39,14 @@ go list -mod=mod all cmp go.mod go.mod.tidy # "// indirect" comments should be added if appropriate. +# TODO(#42504): add case for 'go list -mod=mod -tags=any all' when -tags=any +# is supported. Only a command that loads "all" without build constraints +# (except "ignore") has enough information to add "// indirect" comments. +# 'go mod tidy' and 'go mod vendor' are the only commands that do that, +# but 'go mod vendor' cannot write go.mod. cp go.mod.toodirect go.mod go list all cmp go.mod go.mod.toodirect -go mod vendor # loads everything, so adds "// indirect" comments. -cmp go.mod go.mod.tidy -rm -r vendor # Redundant requirements should be preserved... diff --git a/src/cmd/go/testdata/script/mod_tidy_error.txt b/src/cmd/go/testdata/script/mod_tidy_error.txt index 395537b1a7..51fc65fa7a 100644 --- a/src/cmd/go/testdata/script/mod_tidy_error.txt +++ b/src/cmd/go/testdata/script/mod_tidy_error.txt @@ -10,8 +10,8 @@ stderr '^issue27063 imports\n\tissue27063/other imports\n\tother.example.com/non ! go mod vendor ! stderr 'package nonexist is not in GOROOT' -stderr '^issue27063 imports\n\tnonexist.example.com: cannot find module providing package nonexist.example.com' -stderr '^issue27063 imports\n\tissue27063/other imports\n\tother.example.com/nonexist: cannot find module providing package other.example.com/nonexist' +stderr '^issue27063 imports\n\tnonexist.example.com: no required module provides package nonexist.example.com; to add it:\n\tgo get nonexist.example.com$' +stderr '^issue27063 imports\n\tissue27063/other imports\n\tother.example.com/nonexist: no required module provides package other.example.com/nonexist; to add it:\n\tgo get other.example.com/nonexist$' -- go.mod -- module issue27063 diff --git a/src/cmd/go/testdata/script/mod_vendor_replace.txt b/src/cmd/go/testdata/script/mod_vendor_replace.txt index 0c1c1d22f5..1820af62ad 100644 --- a/src/cmd/go/testdata/script/mod_vendor_replace.txt +++ b/src/cmd/go/testdata/script/mod_vendor_replace.txt @@ -36,7 +36,6 @@ module example.com/replace require rsc.io/quote/v3 v3.0.0 replace rsc.io/quote/v3 => ./local/not-rsc.io/quote/v3 - -- imports.go -- package replace @@ -64,3 +63,7 @@ require ( not-rsc.io/quote/v3 v3.0.0 ) replace not-rsc.io/quote/v3 => rsc.io/quote/v3 v3.0.0 +-- multiple-paths/go.sum -- +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +rsc.io/quote/v3 v3.0.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/src/cmd/go/testdata/script/mod_vendor_trimpath.txt b/src/cmd/go/testdata/script/mod_vendor_trimpath.txt index 5451aa773c..d9d9d98897 100644 --- a/src/cmd/go/testdata/script/mod_vendor_trimpath.txt +++ b/src/cmd/go/testdata/script/mod_vendor_trimpath.txt @@ -29,8 +29,12 @@ stdout '^example.com/stack@v1.0.0/stack.go$' -- go.mod -- module example.com/main -require example.com/stack v1.0.0 +go 1.17 +require example.com/stack v1.0.0 +-- go.sum -- +example.com/stack v1.0.0 h1:IEDLeew5NytZ8vrgCF/QVem3H3SR3QMttdu9HfJvk9I= +example.com/stack v1.0.0/go.mod h1:7wFEbaV5e5O7wJ8aBdqQOR//UXppm/pwnwziMKViuI4= -- main.go -- package main diff --git a/src/cmd/go/testdata/script/mod_vendor_unused_only.txt b/src/cmd/go/testdata/script/mod_vendor_unused_only.txt index 839c6453cf..accd9f373d 100644 --- a/src/cmd/go/testdata/script/mod_vendor_unused_only.txt +++ b/src/cmd/go/testdata/script/mod_vendor_unused_only.txt @@ -12,6 +12,8 @@ module example.com/m go 1.14 require example.com v1.0.0 // indirect +-- go.sum -- +example.com v1.0.0/go.mod h1:WRiieAqDBb1hVdDXLLdxNtCDWNfehn7FWyPC5Oz2vB4= -- go1.14-modules.txt -- # example.com v1.0.0 ## explicit diff --git a/src/cmd/go/testdata/script/mod_verify.txt b/src/cmd/go/testdata/script/mod_verify.txt index b5106659a9..f02d15aa28 100644 --- a/src/cmd/go/testdata/script/mod_verify.txt +++ b/src/cmd/go/testdata/script/mod_verify.txt @@ -39,11 +39,6 @@ stderr 'go.mod: checksum mismatch' # go.sum should be created and updated automatically. rm go.sum -go mod graph -exists go.sum -grep '^rsc.io/quote v1.1.0/go.mod ' go.sum -! grep '^rsc.io/quote v1.1.0 ' go.sum - go mod tidy grep '^rsc.io/quote v1.1.0/go.mod ' go.sum grep '^rsc.io/quote v1.1.0 ' go.sum diff --git a/src/cmd/go/testdata/script/modfile_flag.txt b/src/cmd/go/testdata/script/modfile_flag.txt index 0ad0880817..baf25d31b8 100644 --- a/src/cmd/go/testdata/script/modfile_flag.txt +++ b/src/cmd/go/testdata/script/modfile_flag.txt @@ -24,6 +24,11 @@ stdout '^go.alt.mod$' go mod edit -require rsc.io/quote@v1.5.2 grep rsc.io/quote go.alt.mod +# 'go list -m' should add sums to the alternate go.sum. +go list -m -mod=mod all +grep '^rsc.io/quote v1.5.2/go.mod ' go.alt.sum +! grep '^rsc.io/quote v1.5.2 ' go.alt.sum + # other 'go mod' commands should work. 'go mod vendor' is tested later. go mod download rsc.io/quote go mod graph -- GitLab From 4c8ffb3baaabce1aa2139ce7739fec333ab80728 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Wed, 14 Jul 2021 13:52:00 -0700 Subject: [PATCH 0659/2500] cmd/internal/str: move package from cmd/go/internal/str This will let cmd/cgo and cmd/link use this package for argument parsing. For golang/go#41400 Change-Id: I12ee21151bf3f00f3e8d427faaaab2453c823117 Reviewed-on: https://go-review.googlesource.com/c/go/+/334730 Trust: Jay Conrod Reviewed-by: Michael Matloob Reviewed-on: https://go-review.googlesource.com/c/go/+/341934 Run-TryBot: Jay Conrod Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/base/base.go | 2 +- src/cmd/go/internal/base/flag.go | 2 +- src/cmd/go/internal/fix/fix.go | 2 +- src/cmd/go/internal/fmtcmd/fmt.go | 2 +- src/cmd/go/internal/generate/generate.go | 2 +- src/cmd/go/internal/get/get.go | 2 +- src/cmd/go/internal/list/list.go | 2 +- src/cmd/go/internal/load/flag.go | 2 +- src/cmd/go/internal/load/pkg.go | 2 +- src/cmd/go/internal/load/test.go | 2 +- src/cmd/go/internal/modcmd/vendor.go | 2 +- src/cmd/go/internal/modfetch/codehost/codehost.go | 2 +- src/cmd/go/internal/modfetch/codehost/vcs.go | 2 +- src/cmd/go/internal/modget/query.go | 2 +- src/cmd/go/internal/modload/load.go | 2 +- src/cmd/go/internal/modload/query.go | 2 +- src/cmd/go/internal/run/run.go | 2 +- src/cmd/go/internal/test/test.go | 2 +- src/cmd/go/internal/vcs/vcs.go | 2 +- src/cmd/go/internal/work/buildid.go | 2 +- src/cmd/go/internal/work/exec.go | 2 +- src/cmd/go/internal/work/gc.go | 2 +- src/cmd/go/internal/work/gccgo.go | 2 +- src/cmd/{go => }/internal/str/path.go | 0 src/cmd/{go => }/internal/str/str.go | 0 src/cmd/{go => }/internal/str/str_test.go | 0 26 files changed, 23 insertions(+), 23 deletions(-) rename src/cmd/{go => }/internal/str/path.go (100%) rename src/cmd/{go => }/internal/str/str.go (100%) rename src/cmd/{go => }/internal/str/str_test.go (100%) diff --git a/src/cmd/go/internal/base/base.go b/src/cmd/go/internal/base/base.go index 954ce47a98..0144525e30 100644 --- a/src/cmd/go/internal/base/base.go +++ b/src/cmd/go/internal/base/base.go @@ -17,7 +17,7 @@ import ( "sync" "cmd/go/internal/cfg" - "cmd/go/internal/str" + "cmd/internal/str" ) // A Command is an implementation of a go command diff --git a/src/cmd/go/internal/base/flag.go b/src/cmd/go/internal/base/flag.go index 677f819682..6914efa0e6 100644 --- a/src/cmd/go/internal/base/flag.go +++ b/src/cmd/go/internal/base/flag.go @@ -9,7 +9,7 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/fsys" - "cmd/go/internal/str" + "cmd/internal/str" ) // A StringsFlag is a command-line flag that interprets its argument diff --git a/src/cmd/go/internal/fix/fix.go b/src/cmd/go/internal/fix/fix.go index 988d45e71c..cc5940fccd 100644 --- a/src/cmd/go/internal/fix/fix.go +++ b/src/cmd/go/internal/fix/fix.go @@ -10,7 +10,7 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/load" "cmd/go/internal/modload" - "cmd/go/internal/str" + "cmd/internal/str" "context" "fmt" "os" diff --git a/src/cmd/go/internal/fmtcmd/fmt.go b/src/cmd/go/internal/fmtcmd/fmt.go index 8a04008753..2b89a078ac 100644 --- a/src/cmd/go/internal/fmtcmd/fmt.go +++ b/src/cmd/go/internal/fmtcmd/fmt.go @@ -18,7 +18,7 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/load" "cmd/go/internal/modload" - "cmd/go/internal/str" + "cmd/internal/str" ) func init() { diff --git a/src/cmd/go/internal/generate/generate.go b/src/cmd/go/internal/generate/generate.go index 80ea32b428..d7f2eb4610 100644 --- a/src/cmd/go/internal/generate/generate.go +++ b/src/cmd/go/internal/generate/generate.go @@ -25,8 +25,8 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/load" "cmd/go/internal/modload" - "cmd/go/internal/str" "cmd/go/internal/work" + "cmd/internal/str" ) var CmdGenerate = &base.Command{ diff --git a/src/cmd/go/internal/get/get.go b/src/cmd/go/internal/get/get.go index 3c16dc3040..836364e39b 100644 --- a/src/cmd/go/internal/get/get.go +++ b/src/cmd/go/internal/get/get.go @@ -17,10 +17,10 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/load" "cmd/go/internal/search" - "cmd/go/internal/str" "cmd/go/internal/vcs" "cmd/go/internal/web" "cmd/go/internal/work" + "cmd/internal/str" "golang.org/x/mod/module" ) diff --git a/src/cmd/go/internal/list/list.go b/src/cmd/go/internal/list/list.go index 7cb9ec6d94..4b8c0e9f48 100644 --- a/src/cmd/go/internal/list/list.go +++ b/src/cmd/go/internal/list/list.go @@ -23,8 +23,8 @@ import ( "cmd/go/internal/load" "cmd/go/internal/modinfo" "cmd/go/internal/modload" - "cmd/go/internal/str" "cmd/go/internal/work" + "cmd/internal/str" ) var CmdList = &base.Command{ diff --git a/src/cmd/go/internal/load/flag.go b/src/cmd/go/internal/load/flag.go index 440cb86134..4e0cb5bc19 100644 --- a/src/cmd/go/internal/load/flag.go +++ b/src/cmd/go/internal/load/flag.go @@ -6,7 +6,7 @@ package load import ( "cmd/go/internal/base" - "cmd/go/internal/str" + "cmd/internal/str" "fmt" "strings" ) diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index a83cc9a812..e44e71b366 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -36,8 +36,8 @@ import ( "cmd/go/internal/modload" "cmd/go/internal/par" "cmd/go/internal/search" - "cmd/go/internal/str" "cmd/go/internal/trace" + "cmd/internal/str" "cmd/internal/sys" "golang.org/x/mod/modfile" diff --git a/src/cmd/go/internal/load/test.go b/src/cmd/go/internal/load/test.go index c828296566..42eefe37ba 100644 --- a/src/cmd/go/internal/load/test.go +++ b/src/cmd/go/internal/load/test.go @@ -22,8 +22,8 @@ import ( "unicode/utf8" "cmd/go/internal/fsys" - "cmd/go/internal/str" "cmd/go/internal/trace" + "cmd/internal/str" ) var TestMainDeps = []string{ diff --git a/src/cmd/go/internal/modcmd/vendor.go b/src/cmd/go/internal/modcmd/vendor.go index 713d5f9f3f..b133ba7ea9 100644 --- a/src/cmd/go/internal/modcmd/vendor.go +++ b/src/cmd/go/internal/modcmd/vendor.go @@ -24,7 +24,7 @@ import ( "cmd/go/internal/imports" "cmd/go/internal/load" "cmd/go/internal/modload" - "cmd/go/internal/str" + "cmd/internal/str" "golang.org/x/mod/module" "golang.org/x/mod/semver" diff --git a/src/cmd/go/internal/modfetch/codehost/codehost.go b/src/cmd/go/internal/modfetch/codehost/codehost.go index 378fbae34f..efb4b1516a 100644 --- a/src/cmd/go/internal/modfetch/codehost/codehost.go +++ b/src/cmd/go/internal/modfetch/codehost/codehost.go @@ -21,7 +21,7 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/lockedfile" - "cmd/go/internal/str" + "cmd/internal/str" ) // Downloaded size limits. diff --git a/src/cmd/go/internal/modfetch/codehost/vcs.go b/src/cmd/go/internal/modfetch/codehost/vcs.go index c2cca084e3..5d810d2621 100644 --- a/src/cmd/go/internal/modfetch/codehost/vcs.go +++ b/src/cmd/go/internal/modfetch/codehost/vcs.go @@ -20,7 +20,7 @@ import ( "cmd/go/internal/lockedfile" "cmd/go/internal/par" - "cmd/go/internal/str" + "cmd/internal/str" ) // A VCSError indicates an error using a version control system. diff --git a/src/cmd/go/internal/modget/query.go b/src/cmd/go/internal/modget/query.go index 1a5a60f7eb..0a66517a49 100644 --- a/src/cmd/go/internal/modget/query.go +++ b/src/cmd/go/internal/modget/query.go @@ -14,7 +14,7 @@ import ( "cmd/go/internal/base" "cmd/go/internal/modload" "cmd/go/internal/search" - "cmd/go/internal/str" + "cmd/internal/str" "golang.org/x/mod/module" ) diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index bce9ad85f4..b54f670812 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -118,7 +118,7 @@ import ( "cmd/go/internal/mvs" "cmd/go/internal/par" "cmd/go/internal/search" - "cmd/go/internal/str" + "cmd/internal/str" "golang.org/x/mod/module" "golang.org/x/mod/semver" diff --git a/src/cmd/go/internal/modload/query.go b/src/cmd/go/internal/modload/query.go index e737ca90fc..d4c906a873 100644 --- a/src/cmd/go/internal/modload/query.go +++ b/src/cmd/go/internal/modload/query.go @@ -21,8 +21,8 @@ import ( "cmd/go/internal/imports" "cmd/go/internal/modfetch" "cmd/go/internal/search" - "cmd/go/internal/str" "cmd/go/internal/trace" + "cmd/internal/str" "golang.org/x/mod/module" "golang.org/x/mod/semver" diff --git a/src/cmd/go/internal/run/run.go b/src/cmd/go/internal/run/run.go index 784f7162df..9e9e49ec89 100644 --- a/src/cmd/go/internal/run/run.go +++ b/src/cmd/go/internal/run/run.go @@ -18,8 +18,8 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/load" "cmd/go/internal/modload" - "cmd/go/internal/str" "cmd/go/internal/work" + "cmd/internal/str" ) var CmdRun = &base.Command{ diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 59ea1ef544..aeba80eb68 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -30,9 +30,9 @@ import ( "cmd/go/internal/load" "cmd/go/internal/lockedfile" "cmd/go/internal/search" - "cmd/go/internal/str" "cmd/go/internal/trace" "cmd/go/internal/work" + "cmd/internal/str" "cmd/internal/test2json" ) diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go index 91485f6f74..97b2a631ae 100644 --- a/src/cmd/go/internal/vcs/vcs.go +++ b/src/cmd/go/internal/vcs/vcs.go @@ -23,8 +23,8 @@ import ( "cmd/go/internal/base" "cmd/go/internal/cfg" "cmd/go/internal/search" - "cmd/go/internal/str" "cmd/go/internal/web" + "cmd/internal/str" "golang.org/x/mod/module" ) diff --git a/src/cmd/go/internal/work/buildid.go b/src/cmd/go/internal/work/buildid.go index 4e9189a363..15f944d2af 100644 --- a/src/cmd/go/internal/work/buildid.go +++ b/src/cmd/go/internal/work/buildid.go @@ -15,8 +15,8 @@ import ( "cmd/go/internal/cache" "cmd/go/internal/cfg" "cmd/go/internal/fsys" - "cmd/go/internal/str" "cmd/internal/buildid" + "cmd/internal/str" ) // Build IDs diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index 5a225fb9f1..2aa099bf17 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -34,8 +34,8 @@ import ( "cmd/go/internal/fsys" "cmd/go/internal/load" "cmd/go/internal/modload" - "cmd/go/internal/str" "cmd/go/internal/trace" + "cmd/internal/str" ) // actionList returns the list of actions in the dag rooted at root diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go index 2ae908bc8f..70ca5d69f8 100644 --- a/src/cmd/go/internal/work/gc.go +++ b/src/cmd/go/internal/work/gc.go @@ -20,8 +20,8 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/fsys" "cmd/go/internal/load" - "cmd/go/internal/str" "cmd/internal/objabi" + "cmd/internal/str" "cmd/internal/sys" "crypto/sha1" ) diff --git a/src/cmd/go/internal/work/gccgo.go b/src/cmd/go/internal/work/gccgo.go index 1499536932..3cb7b64183 100644 --- a/src/cmd/go/internal/work/gccgo.go +++ b/src/cmd/go/internal/work/gccgo.go @@ -16,8 +16,8 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/fsys" "cmd/go/internal/load" - "cmd/go/internal/str" "cmd/internal/pkgpath" + "cmd/internal/str" ) // The Gccgo toolchain. diff --git a/src/cmd/go/internal/str/path.go b/src/cmd/internal/str/path.go similarity index 100% rename from src/cmd/go/internal/str/path.go rename to src/cmd/internal/str/path.go diff --git a/src/cmd/go/internal/str/str.go b/src/cmd/internal/str/str.go similarity index 100% rename from src/cmd/go/internal/str/str.go rename to src/cmd/internal/str/str.go diff --git a/src/cmd/go/internal/str/str_test.go b/src/cmd/internal/str/str_test.go similarity index 100% rename from src/cmd/go/internal/str/str_test.go rename to src/cmd/internal/str/str_test.go -- GitLab From 20a620fd9f7bc35739c1af3602d53808d0430814 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 12 Aug 2021 17:17:51 -0400 Subject: [PATCH 0660/2500] runtime: drop SIGPROF while in ARM < 7 kernel helpers On Linux ARMv6 and below runtime/internal/atomic.Cas calls into a kernel cas helper at a fixed address. If a SIGPROF arrives while executing the kernel helper, the sigprof lostAtomic logic will miss that we are potentially in the spinlock critical section, which could cause a deadlock when using atomics later in sigprof. Fixes #47505 Change-Id: If8ba0d0fc47e45d4e6c68eca98fac4c6ed4e43c1 Reviewed-on: https://go-review.googlesource.com/c/go/+/341889 Trust: Michael Pratt Run-TryBot: Michael Pratt Reviewed-by: Michael Knyszek Reviewed-by: Cherry Mui TryBot-Result: Go Bot --- src/runtime/proc.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index ec4be31db3..764f12769e 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -4619,7 +4619,7 @@ func sigprof(pc, sp, lr uintptr, gp *g, mp *m) { return } - // On mips{,le}, 64bit atomics are emulated with spinlocks, in + // On mips{,le}/arm, 64bit atomics are emulated with spinlocks, in // runtime/internal/atomic. If SIGPROF arrives while the program is inside // the critical section, it creates a deadlock (when writing the sample). // As a workaround, create a counter of SIGPROFs while in critical section @@ -4632,6 +4632,13 @@ func sigprof(pc, sp, lr uintptr, gp *g, mp *m) { return } } + if GOARCH == "arm" && goarm < 7 && GOOS == "linux" && pc&0xffff0000 == 0xffff0000 { + // runtime/internal/atomic functions call into kernel + // helpers on arm < 7. See + // runtime/internal/atomic/sys_linux_arm.s. + cpuprof.lostAtomic++ + return + } } // Profiling runs concurrently with GC, so it must not allocate. -- GitLab From 98f3d7fecbb8a9074f5f4ffc50bb016e194940b7 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Mon, 9 Aug 2021 20:29:14 -0400 Subject: [PATCH 0661/2500] all: gofmt more (but vendor, testdata, and top-level test directories) CL 294430 made packages in std and cmd modules use Go 1.17 gofmt format, adding //go:build lines. This change applies the same formatting to some more packages that 'go fmt' missed (e.g., syscall/js, runtime/msan), and everything else that is easy and safe to modify in bulk. Consider the top-level test directory, testdata, and vendor directories out of scope, since there are many files that don't follow strict gofmt formatting, often for intentional and legitimate reasons (testing gofmt itself, invalid Go programs that shouldn't crash the compiler, etc.). That makes it easy and safe to gofmt -w the .go files that are found with gofmt -l with aforementioned directories filtered out: $ gofmt -l . 2>/dev/null | \ grep -v '^test/' | \ grep -v '/testdata/' | \ grep -v '/vendor/' | wc -l 51 None of the 51 files are generated. After this change, the same command prints 0. For #41184. Change-Id: Ia96ee2a0f998d6a167d4473bcad17ad09bc1d86e Reviewed-on: https://go-review.googlesource.com/c/go/+/341009 Run-TryBot: Dmitri Shuralyov TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Dmitri Shuralyov --- misc/android/go_android_exec.go | 1 + misc/cgo/gmp/fib.go | 1 + misc/cgo/gmp/pi.go | 1 + misc/cgo/test/cgo_thread_lock.go | 1 + misc/cgo/test/cgo_unix_test.go | 1 + misc/cgo/test/issue1435.go | 1 + misc/cgo/test/issue18146.go | 1 + misc/cgo/test/issue21897.go | 1 + misc/cgo/test/issue21897b.go | 1 + misc/cgo/test/issue4029.go | 4 +++- misc/cgo/test/issue4029w.go | 1 + misc/cgo/test/issue6997_linux.go | 1 + misc/cgo/test/issue8517.go | 1 + misc/cgo/test/issue8694.go | 1 + misc/cgo/test/sigaltstack.go | 1 + misc/cgo/test/sigprocmask.go | 1 + misc/cgo/test/test_unix.go | 1 + misc/cgo/testso/noso_test.go | 1 + misc/cgo/testso/so_test.go | 1 + misc/cgo/testsovar/noso_test.go | 1 + misc/cgo/testsovar/so_test.go | 1 + misc/cgo/testtls/tls_test.go | 1 + misc/ios/detect.go | 1 + misc/reboot/experiment_toolid_test.go | 1 + src/cmd/compile/internal/base/bootstrap_false.go | 1 + src/cmd/compile/internal/base/bootstrap_true.go | 1 + src/cmd/compile/internal/noder/frames_go1.go | 1 + src/cmd/compile/internal/noder/frames_go17.go | 1 + src/cmd/compile/internal/ssa/gen/386Ops.go | 1 + src/cmd/compile/internal/ssa/gen/MIPS64Ops.go | 1 + src/cmd/compile/internal/ssa/gen/MIPSOps.go | 1 + src/cmd/compile/internal/ssa/gen/PPC64Ops.go | 1 + src/cmd/compile/internal/ssa/gen/RISCV64Ops.go | 1 + src/cmd/compile/internal/ssa/gen/S390XOps.go | 1 + src/cmd/compile/internal/ssa/gen/WasmOps.go | 1 + src/cmd/compile/internal/ssa/gen/dec64Ops.go | 1 + src/cmd/compile/internal/ssa/gen/decOps.go | 1 + src/internal/syscall/windows/exec_windows_test.go | 1 + src/internal/syscall/windows/mksyscall.go | 1 + src/internal/syscall/windows/registry/export_test.go | 1 + src/internal/syscall/windows/registry/key.go | 1 + src/internal/syscall/windows/registry/mksyscall.go | 1 + src/internal/syscall/windows/registry/registry_test.go | 1 + src/internal/syscall/windows/registry/syscall.go | 1 + src/internal/syscall/windows/registry/value.go | 1 + src/internal/syscall/windows/sysdll/sysdll.go | 1 + src/runtime/msan/msan.go | 4 +++- src/syscall/js/export_test.go | 1 + src/syscall/js/func.go | 1 + src/syscall/js/js.go | 1 + src/syscall/js/js_test.go | 1 + 51 files changed, 55 insertions(+), 2 deletions(-) diff --git a/misc/android/go_android_exec.go b/misc/android/go_android_exec.go index 3af2bee583..168ebe88a2 100644 --- a/misc/android/go_android_exec.go +++ b/misc/android/go_android_exec.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // This program can be used as go_android_GOARCH_exec by the Go tool. diff --git a/misc/cgo/gmp/fib.go b/misc/cgo/gmp/fib.go index f1091b1c54..f453fcf184 100644 --- a/misc/cgo/gmp/fib.go +++ b/misc/cgo/gmp/fib.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // Compute Fibonacci numbers with two goroutines diff --git a/misc/cgo/gmp/pi.go b/misc/cgo/gmp/pi.go index d5851e8e6b..5ea034900a 100644 --- a/misc/cgo/gmp/pi.go +++ b/misc/cgo/gmp/pi.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore package main diff --git a/misc/cgo/test/cgo_thread_lock.go b/misc/cgo/test/cgo_thread_lock.go index b105068518..3b9ac84549 100644 --- a/misc/cgo/test/cgo_thread_lock.go +++ b/misc/cgo/test/cgo_thread_lock.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux && freebsd && openbsd // +build linux,freebsd,openbsd package cgotest diff --git a/misc/cgo/test/cgo_unix_test.go b/misc/cgo/test/cgo_unix_test.go index e3d5916649..a324503a22 100644 --- a/misc/cgo/test/cgo_unix_test.go +++ b/misc/cgo/test/cgo_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !windows // +build !windows package cgotest diff --git a/misc/cgo/test/issue1435.go b/misc/cgo/test/issue1435.go index 92c6b99846..91db155c90 100644 --- a/misc/cgo/test/issue1435.go +++ b/misc/cgo/test/issue1435.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux && cgo // +build linux,cgo package cgotest diff --git a/misc/cgo/test/issue18146.go b/misc/cgo/test/issue18146.go index f92d6c7f93..e50f9ae530 100644 --- a/misc/cgo/test/issue18146.go +++ b/misc/cgo/test/issue18146.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !windows // +build !windows // Issue 18146: pthread_create failure during syscall.Exec. diff --git a/misc/cgo/test/issue21897.go b/misc/cgo/test/issue21897.go index d13246bd84..8f39252e68 100644 --- a/misc/cgo/test/issue21897.go +++ b/misc/cgo/test/issue21897.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin && cgo && !internal // +build darwin,cgo,!internal package cgotest diff --git a/misc/cgo/test/issue21897b.go b/misc/cgo/test/issue21897b.go index 08b5f4d808..50aece3528 100644 --- a/misc/cgo/test/issue21897b.go +++ b/misc/cgo/test/issue21897b.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !darwin || !cgo || internal // +build !darwin !cgo internal package cgotest diff --git a/misc/cgo/test/issue4029.go b/misc/cgo/test/issue4029.go index b2d131833a..90ca08cbfb 100644 --- a/misc/cgo/test/issue4029.go +++ b/misc/cgo/test/issue4029.go @@ -2,7 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !windows,!static +//go:build !windows && !static && (!darwin || (!internal_pie && !arm64)) +// +build !windows +// +build !static // +build !darwin !internal_pie,!arm64 // Excluded in darwin internal linking PIE mode, as dynamic export is not diff --git a/misc/cgo/test/issue4029w.go b/misc/cgo/test/issue4029w.go index b969bdd0fe..c2f59485e4 100644 --- a/misc/cgo/test/issue4029w.go +++ b/misc/cgo/test/issue4029w.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows || static || (darwin && internal_pie) || (darwin && arm64) // +build windows static darwin,internal_pie darwin,arm64 package cgotest diff --git a/misc/cgo/test/issue6997_linux.go b/misc/cgo/test/issue6997_linux.go index f19afb8b7a..4acc8c1a07 100644 --- a/misc/cgo/test/issue6997_linux.go +++ b/misc/cgo/test/issue6997_linux.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !android // +build !android // Test that pthread_cancel works as expected diff --git a/misc/cgo/test/issue8517.go b/misc/cgo/test/issue8517.go index 4e431df921..7316ab0335 100644 --- a/misc/cgo/test/issue8517.go +++ b/misc/cgo/test/issue8517.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !windows // +build !windows package cgotest diff --git a/misc/cgo/test/issue8694.go b/misc/cgo/test/issue8694.go index 89be7ea090..19071ce159 100644 --- a/misc/cgo/test/issue8694.go +++ b/misc/cgo/test/issue8694.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !android // +build !android package cgotest diff --git a/misc/cgo/test/sigaltstack.go b/misc/cgo/test/sigaltstack.go index 034cc4b371..6b371897a7 100644 --- a/misc/cgo/test/sigaltstack.go +++ b/misc/cgo/test/sigaltstack.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !windows && !android // +build !windows,!android // Test that the Go runtime still works if C code changes the signal stack. diff --git a/misc/cgo/test/sigprocmask.go b/misc/cgo/test/sigprocmask.go index e2b939f05e..983734cc7b 100644 --- a/misc/cgo/test/sigprocmask.go +++ b/misc/cgo/test/sigprocmask.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !windows // +build !windows package cgotest diff --git a/misc/cgo/test/test_unix.go b/misc/cgo/test/test_unix.go index 4a234469db..831b9ca625 100644 --- a/misc/cgo/test/test_unix.go +++ b/misc/cgo/test/test_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !windows // +build !windows package cgotest diff --git a/misc/cgo/testso/noso_test.go b/misc/cgo/testso/noso_test.go index c88aebfb02..1014534d62 100644 --- a/misc/cgo/testso/noso_test.go +++ b/misc/cgo/testso/noso_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !cgo // +build !cgo package so_test diff --git a/misc/cgo/testso/so_test.go b/misc/cgo/testso/so_test.go index 2023c51f11..6d14e32dc6 100644 --- a/misc/cgo/testso/so_test.go +++ b/misc/cgo/testso/so_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build cgo // +build cgo package so_test diff --git a/misc/cgo/testsovar/noso_test.go b/misc/cgo/testsovar/noso_test.go index c88aebfb02..1014534d62 100644 --- a/misc/cgo/testsovar/noso_test.go +++ b/misc/cgo/testsovar/noso_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !cgo // +build !cgo package so_test diff --git a/misc/cgo/testsovar/so_test.go b/misc/cgo/testsovar/so_test.go index 2023c51f11..6d14e32dc6 100644 --- a/misc/cgo/testsovar/so_test.go +++ b/misc/cgo/testsovar/so_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build cgo // +build cgo package so_test diff --git a/misc/cgo/testtls/tls_test.go b/misc/cgo/testtls/tls_test.go index 3076c2d594..a3b67c0044 100644 --- a/misc/cgo/testtls/tls_test.go +++ b/misc/cgo/testtls/tls_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !windows // +build !windows package cgotlstest diff --git a/misc/ios/detect.go b/misc/ios/detect.go index cde5723892..1cb8ae5ff7 100644 --- a/misc/ios/detect.go +++ b/misc/ios/detect.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // detect attempts to autodetect the correct diff --git a/misc/reboot/experiment_toolid_test.go b/misc/reboot/experiment_toolid_test.go index 4f40284d80..87a828e32f 100644 --- a/misc/reboot/experiment_toolid_test.go +++ b/misc/reboot/experiment_toolid_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build explicit // +build explicit // Package experiment_toolid_test verifies that GOEXPERIMENT settings built diff --git a/src/cmd/compile/internal/base/bootstrap_false.go b/src/cmd/compile/internal/base/bootstrap_false.go index de86644527..c77fcd7308 100644 --- a/src/cmd/compile/internal/base/bootstrap_false.go +++ b/src/cmd/compile/internal/base/bootstrap_false.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !compiler_bootstrap // +build !compiler_bootstrap package base diff --git a/src/cmd/compile/internal/base/bootstrap_true.go b/src/cmd/compile/internal/base/bootstrap_true.go index 81a17e1f6e..1eb58b2f9d 100644 --- a/src/cmd/compile/internal/base/bootstrap_true.go +++ b/src/cmd/compile/internal/base/bootstrap_true.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build compiler_bootstrap // +build compiler_bootstrap package base diff --git a/src/cmd/compile/internal/noder/frames_go1.go b/src/cmd/compile/internal/noder/frames_go1.go index 2958efd622..d00e0f51f9 100644 --- a/src/cmd/compile/internal/noder/frames_go1.go +++ b/src/cmd/compile/internal/noder/frames_go1.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !go1.7 // +build !go1.7 // TODO(mdempsky): Remove after #44505 is resolved diff --git a/src/cmd/compile/internal/noder/frames_go17.go b/src/cmd/compile/internal/noder/frames_go17.go index 273217e39a..48d77625b4 100644 --- a/src/cmd/compile/internal/noder/frames_go17.go +++ b/src/cmd/compile/internal/noder/frames_go17.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build go1.7 // +build go1.7 package noder diff --git a/src/cmd/compile/internal/ssa/gen/386Ops.go b/src/cmd/compile/internal/ssa/gen/386Ops.go index c4b49fbb23..91f33c8374 100644 --- a/src/cmd/compile/internal/ssa/gen/386Ops.go +++ b/src/cmd/compile/internal/ssa/gen/386Ops.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore package main diff --git a/src/cmd/compile/internal/ssa/gen/MIPS64Ops.go b/src/cmd/compile/internal/ssa/gen/MIPS64Ops.go index 77f251c0d3..a18cd4289d 100644 --- a/src/cmd/compile/internal/ssa/gen/MIPS64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/MIPS64Ops.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore package main diff --git a/src/cmd/compile/internal/ssa/gen/MIPSOps.go b/src/cmd/compile/internal/ssa/gen/MIPSOps.go index b92e8cb9f1..8177c7e2d1 100644 --- a/src/cmd/compile/internal/ssa/gen/MIPSOps.go +++ b/src/cmd/compile/internal/ssa/gen/MIPSOps.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore package main diff --git a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go index f7198b90c3..d7d8a33a0a 100644 --- a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore package main diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go index 0ac9c5f62a..0774d4c654 100644 --- a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore package main diff --git a/src/cmd/compile/internal/ssa/gen/S390XOps.go b/src/cmd/compile/internal/ssa/gen/S390XOps.go index 5b33ba710e..00fce8e0e5 100644 --- a/src/cmd/compile/internal/ssa/gen/S390XOps.go +++ b/src/cmd/compile/internal/ssa/gen/S390XOps.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore package main diff --git a/src/cmd/compile/internal/ssa/gen/WasmOps.go b/src/cmd/compile/internal/ssa/gen/WasmOps.go index c92878ca73..7f7ae5e837 100644 --- a/src/cmd/compile/internal/ssa/gen/WasmOps.go +++ b/src/cmd/compile/internal/ssa/gen/WasmOps.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore package main diff --git a/src/cmd/compile/internal/ssa/gen/dec64Ops.go b/src/cmd/compile/internal/ssa/gen/dec64Ops.go index 8c5883bc56..78fcea885a 100644 --- a/src/cmd/compile/internal/ssa/gen/dec64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/dec64Ops.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore package main diff --git a/src/cmd/compile/internal/ssa/gen/decOps.go b/src/cmd/compile/internal/ssa/gen/decOps.go index b826481c9f..d5cd79378c 100644 --- a/src/cmd/compile/internal/ssa/gen/decOps.go +++ b/src/cmd/compile/internal/ssa/gen/decOps.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore package main diff --git a/src/internal/syscall/windows/exec_windows_test.go b/src/internal/syscall/windows/exec_windows_test.go index 283d7cea94..0db626636e 100644 --- a/src/internal/syscall/windows/exec_windows_test.go +++ b/src/internal/syscall/windows/exec_windows_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows // +build windows package windows_test diff --git a/src/internal/syscall/windows/mksyscall.go b/src/internal/syscall/windows/mksyscall.go index 599f07601b..39f745db7a 100644 --- a/src/internal/syscall/windows/mksyscall.go +++ b/src/internal/syscall/windows/mksyscall.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build generate // +build generate package windows diff --git a/src/internal/syscall/windows/registry/export_test.go b/src/internal/syscall/windows/registry/export_test.go index 8badf6fdcf..d02d93f287 100644 --- a/src/internal/syscall/windows/registry/export_test.go +++ b/src/internal/syscall/windows/registry/export_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows // +build windows package registry diff --git a/src/internal/syscall/windows/registry/key.go b/src/internal/syscall/windows/registry/key.go index 612c48f084..ebe73a2e02 100644 --- a/src/internal/syscall/windows/registry/key.go +++ b/src/internal/syscall/windows/registry/key.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows // +build windows // Package registry provides access to the Windows registry. diff --git a/src/internal/syscall/windows/registry/mksyscall.go b/src/internal/syscall/windows/registry/mksyscall.go index 320abf7fc6..0a007df7cc 100644 --- a/src/internal/syscall/windows/registry/mksyscall.go +++ b/src/internal/syscall/windows/registry/mksyscall.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build generate // +build generate package registry diff --git a/src/internal/syscall/windows/registry/registry_test.go b/src/internal/syscall/windows/registry/registry_test.go index 5797162900..69b84e1c4c 100644 --- a/src/internal/syscall/windows/registry/registry_test.go +++ b/src/internal/syscall/windows/registry/registry_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows // +build windows package registry_test diff --git a/src/internal/syscall/windows/registry/syscall.go b/src/internal/syscall/windows/registry/syscall.go index a6525dac5d..bb61279361 100644 --- a/src/internal/syscall/windows/registry/syscall.go +++ b/src/internal/syscall/windows/registry/syscall.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows // +build windows package registry diff --git a/src/internal/syscall/windows/registry/value.go b/src/internal/syscall/windows/registry/value.go index dc3930a6bc..e1fc99c40d 100644 --- a/src/internal/syscall/windows/registry/value.go +++ b/src/internal/syscall/windows/registry/value.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows // +build windows package registry diff --git a/src/internal/syscall/windows/sysdll/sysdll.go b/src/internal/syscall/windows/sysdll/sysdll.go index c587c19c77..61b998e4cf 100644 --- a/src/internal/syscall/windows/sysdll/sysdll.go +++ b/src/internal/syscall/windows/sysdll/sysdll.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows // +build windows // Package sysdll is an internal leaf package that records and reports diff --git a/src/runtime/msan/msan.go b/src/runtime/msan/msan.go index c81577ddda..9908a8ec22 100644 --- a/src/runtime/msan/msan.go +++ b/src/runtime/msan/msan.go @@ -2,7 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build msan,linux +//go:build msan && linux && (amd64 || arm64) +// +build msan +// +build linux // +build amd64 arm64 package msan diff --git a/src/syscall/js/export_test.go b/src/syscall/js/export_test.go index 1b5ed3ce84..4bd9c5d595 100644 --- a/src/syscall/js/export_test.go +++ b/src/syscall/js/export_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js && wasm // +build js,wasm package js diff --git a/src/syscall/js/func.go b/src/syscall/js/func.go index da4cf68774..ab23e5fbfc 100644 --- a/src/syscall/js/func.go +++ b/src/syscall/js/func.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js && wasm // +build js,wasm package js diff --git a/src/syscall/js/js.go b/src/syscall/js/js.go index a48bbd4dd7..d805d69166 100644 --- a/src/syscall/js/js.go +++ b/src/syscall/js/js.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js && wasm // +build js,wasm // Package js gives access to the WebAssembly host environment when using the js/wasm architecture. diff --git a/src/syscall/js/js_test.go b/src/syscall/js/js_test.go index 5fc9107d40..8088a897f6 100644 --- a/src/syscall/js/js_test.go +++ b/src/syscall/js/js_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js && wasm // +build js,wasm // To run these tests: -- GitLab From 641e8bc2c7166135d3a63ed1a71a3aa495bc3c5d Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 16 Jul 2021 12:16:21 -0700 Subject: [PATCH 0662/2500] test: add test case that caused a gofrontend compiler crash For #47131 Change-Id: Ie2d5a2bd3dceec607544c43e6dc68bd5ea353091 Reviewed-on: https://go-review.googlesource.com/c/go/+/335172 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Cherry Mui Reviewed-by: Than McIntosh TryBot-Result: Go Bot --- test/fixedbugs/issue47131.dir/a.go | 13 +++++++++++++ test/fixedbugs/issue47131.dir/b.go | 12 ++++++++++++ test/fixedbugs/issue47131.go | 7 +++++++ 3 files changed, 32 insertions(+) create mode 100644 test/fixedbugs/issue47131.dir/a.go create mode 100644 test/fixedbugs/issue47131.dir/b.go create mode 100644 test/fixedbugs/issue47131.go diff --git a/test/fixedbugs/issue47131.dir/a.go b/test/fixedbugs/issue47131.dir/a.go new file mode 100644 index 0000000000..6e798d1d0c --- /dev/null +++ b/test/fixedbugs/issue47131.dir/a.go @@ -0,0 +1,13 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type MyInt int + +type MyIntAlias = MyInt + +func (mia *MyIntAlias) Get() int { + return int(*mia) +} diff --git a/test/fixedbugs/issue47131.dir/b.go b/test/fixedbugs/issue47131.dir/b.go new file mode 100644 index 0000000000..c658127ca9 --- /dev/null +++ b/test/fixedbugs/issue47131.dir/b.go @@ -0,0 +1,12 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package b + +import "./a" + +func F2() int { + var mia a.MyIntAlias + return mia.Get() +} diff --git a/test/fixedbugs/issue47131.go b/test/fixedbugs/issue47131.go new file mode 100644 index 0000000000..b83fbd7af1 --- /dev/null +++ b/test/fixedbugs/issue47131.go @@ -0,0 +1,7 @@ +// compiledir + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From bad1fc126536f14fd6f00a93e1b76320c1510bf2 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 9 Aug 2021 14:59:56 -0700 Subject: [PATCH 0663/2500] test: add test case for CL 340609 The first version of CL 340609 for gofrontend passed all existing tests, but not this one. For #42076 Change-Id: I6491e2f186091bdae140b7f7befa511806a6478a Reviewed-on: https://go-review.googlesource.com/c/go/+/340950 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Cherry Mui Reviewed-by: Than McIntosh --- test/fixedbugs/bug514.go | 55 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 test/fixedbugs/bug514.go diff --git a/test/fixedbugs/bug514.go b/test/fixedbugs/bug514.go new file mode 100644 index 0000000000..3fb7f32a30 --- /dev/null +++ b/test/fixedbugs/bug514.go @@ -0,0 +1,55 @@ +// run + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type iface interface { + Get() int +} + +//go:notinheap +type notInHeap struct { + i int +} + +type myInt struct { + f *notInHeap +} + +func (mi myInt) Get() int { + return int(mi.f.i) +} + +type embed struct { + *myInt +} + +var val = 1234 + +var valNotInHeap = notInHeap{val} + +func main() { + i := val + check(i) + mi := myInt{f: &valNotInHeap} + check(mi.Get()) + ifv := iface(mi) + check(ifv.Get()) + ifv = iface(&mi) + check(ifv.Get()) + em := embed{&mi} + check(em.Get()) + ifv = em + check(ifv.Get()) + ifv = &em + check(ifv.Get()) +} + +func check(v int) { + if v != val { + panic(v) + } +} -- GitLab From 2eb4d68833e28fce2701a9c39755413630921371 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 11 Aug 2021 15:34:29 -0700 Subject: [PATCH 0664/2500] runtime: don't use systemstack for BeforeFork/AfterFork In https://golang.org/cl/140930043 syscall.BeforeFork was changed to call beforefork via onM. This was done because at the time BeforeFork was written in C but was called from Go. While the runtime was being converted to Go, calls to complex C functions used onM to ensure that enough stack space was available. In https://golang.org/cl/172260043 the syscall.BeforeFork and beforefork functions were rewritten into Go. In this rewrite syscall.BeforeFork continue to call beforefork via onM, although because both functions were now in Go that was no longer necessary. In https://golang.org/cl/174950043 onM was renamed to systemstack, producing essentially the code we have today. Therefore, the use of systemstack in syscall.BeforeFork (and syscall.AfterFork) is a historical relic. Remove it. Change-Id: Ia570f556b20e8405afa6c5e707bd6f4ad18fd7ca Reviewed-on: https://go-review.googlesource.com/c/go/+/341335 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Austin Clements --- src/runtime/proc.go | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 764f12769e..cde1a11583 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -4104,7 +4104,10 @@ func exitsyscall0(gp *g) { schedule() // Never returns. } -func beforefork() { +// Called from syscall package before fork. +//go:linkname syscall_runtime_BeforeFork syscall.runtime_BeforeFork +//go:nosplit +func syscall_runtime_BeforeFork() { gp := getg().m.curg // Block signals during a fork, so that the child does not run @@ -4121,14 +4124,10 @@ func beforefork() { gp.stackguard0 = stackFork } -// Called from syscall package before fork. -//go:linkname syscall_runtime_BeforeFork syscall.runtime_BeforeFork +// Called from syscall package after fork in parent. +//go:linkname syscall_runtime_AfterFork syscall.runtime_AfterFork //go:nosplit -func syscall_runtime_BeforeFork() { - systemstack(beforefork) -} - -func afterfork() { +func syscall_runtime_AfterFork() { gp := getg().m.curg // See the comments in beforefork. @@ -4139,13 +4138,6 @@ func afterfork() { gp.m.locks-- } -// Called from syscall package after fork in parent. -//go:linkname syscall_runtime_AfterFork syscall.runtime_AfterFork -//go:nosplit -func syscall_runtime_AfterFork() { - systemstack(afterfork) -} - // inForkedChild is true while manipulating signals in the child process. // This is used to avoid calling libc functions in case we are using vfork. var inForkedChild bool -- GitLab From 89a4f996405684c117571e3a0813742b6a8269b7 Mon Sep 17 00:00:00 2001 From: 180909 <734461790@qq.com> Date: Wed, 11 Aug 2021 08:52:31 +0000 Subject: [PATCH 0665/2500] lib/time: fix tz-link ftp url Change-Id: Id09c01192dea6a6f26cbad7222946266587acfda GitHub-Last-Rev: c4f99aedcdc8316f13e8d9bfe9a00e48443fae9e GitHub-Pull-Request: golang/go#47639 Reviewed-on: https://go-review.googlesource.com/c/go/+/341389 Reviewed-by: Ian Lance Taylor Reviewed-by: Emmanuel Odeke --- lib/time/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/time/README b/lib/time/README index aab4daa7e2..edb8dccd26 100644 --- a/lib/time/README +++ b/lib/time/README @@ -4,7 +4,7 @@ The IANA asserts that the database is in the public domain. For more information, see https://www.iana.org/time-zones -ftp://ftp.iana.org/tz/code/tz-link.htm +ftp://ftp.iana.org/tz/code/tz-link.html http://tools.ietf.org/html/rfc6557 To rebuild the archive, read and run update.bash. -- GitLab From a95f1b51be6cdf39235dd4a00f03bab9bf17a3f3 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 13 Jul 2021 09:26:28 -0700 Subject: [PATCH 0666/2500] test: change issue10441.go from "build" to "compile" We use "build" for tests in the main package with a main function. We use "compile" for tests that are not in the main package. Change-Id: I9876b55a9e4672277483fd24e69058d439c66658 Reviewed-on: https://go-review.googlesource.com/c/go/+/334329 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Cherry Mui Reviewed-by: Dmitri Shuralyov TryBot-Result: Go Bot --- test/fixedbugs/issue10441.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fixedbugs/issue10441.go b/test/fixedbugs/issue10441.go index 9bc4948b15..7cd26d841b 100644 --- a/test/fixedbugs/issue10441.go +++ b/test/fixedbugs/issue10441.go @@ -1,4 +1,4 @@ -// build +// compile // Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style -- GitLab From 58490972c0d5a9dc59450474d38533faf69e4aaf Mon Sep 17 00:00:00 2001 From: korzhao Date: Tue, 10 Aug 2021 22:05:34 +0800 Subject: [PATCH 0667/2500] cmd/link: fix dead reference link Change-Id: I0f53cc2b845f8a52fece2aaba1445a0ecb9cdc53 Reviewed-on: https://go-review.googlesource.com/c/go/+/341129 Reviewed-by: Ian Lance Taylor Trust: Dmitri Shuralyov --- src/cmd/link/internal/loadelf/ldelf.go | 2 +- src/cmd/link/internal/loadmacho/ldmacho.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/link/internal/loadelf/ldelf.go b/src/cmd/link/internal/loadelf/ldelf.go index c6956297f6..b4f565a153 100644 --- a/src/cmd/link/internal/loadelf/ldelf.go +++ b/src/cmd/link/internal/loadelf/ldelf.go @@ -22,7 +22,7 @@ import ( /* Derived from Plan 9 from User Space's src/libmach/elf.h, elf.c -http://code.swtch.com/plan9port/src/tip/src/libmach/ +https://github.com/9fans/plan9port/tree/master/src/libmach/ Copyright © 2004 Russ Cox. Portions Copyright © 2008-2010 Google Inc. diff --git a/src/cmd/link/internal/loadmacho/ldmacho.go b/src/cmd/link/internal/loadmacho/ldmacho.go index e7d9eebc33..5402ecd748 100644 --- a/src/cmd/link/internal/loadmacho/ldmacho.go +++ b/src/cmd/link/internal/loadmacho/ldmacho.go @@ -18,7 +18,7 @@ import ( /* Derived from Plan 9 from User Space's src/libmach/elf.h, elf.c -http://code.swtch.com/plan9port/src/tip/src/libmach/ +https://github.com/9fans/plan9port/tree/master/src/libmach/ Copyright © 2004 Russ Cox. Portions Copyright © 2008-2010 Google Inc. -- GitLab From 7eaabae84d8b69216356b84ebc7c86917100f99a Mon Sep 17 00:00:00 2001 From: hitzhangjie Date: Sat, 7 Aug 2021 04:18:37 +0000 Subject: [PATCH 0668/2500] net: update IP.String doc to reflect RFC 5952 conformance Fixes #44485 Change-Id: I1b1bf14245ef738342ec881ac4c99adbfc9c5b7d GitHub-Last-Rev: ae0242c6d61fc0e80c58113a70db74829f6aa12c GitHub-Pull-Request: golang/go#47394 Reviewed-on: https://go-review.googlesource.com/c/go/+/337409 Trust: Dmitri Shuralyov Trust: Damien Neil Reviewed-by: Damien Neil --- src/net/ip.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/ip.go b/src/net/ip.go index 38e1aa2247..b016bef144 100644 --- a/src/net/ip.go +++ b/src/net/ip.go @@ -308,7 +308,7 @@ func ubtoa(dst []byte, start int, v byte) int { // It returns one of 4 forms: // - "", if ip has length 0 // - dotted decimal ("192.0.2.1"), if ip is an IPv4 or IP4-mapped IPv6 address -// - IPv6 ("2001:db8::1"), if ip is a valid IPv6 address +// - IPv6 conforming to RFC 5952 ("2001:db8::1"), if ip is a valid IPv6 address // - the hexadecimal form of ip, without punctuation, if no other cases apply func (ip IP) String() string { p := ip -- GitLab From fc27eb50ffcada3d4f5e7e00a5c120f474cc0da4 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Tue, 10 Aug 2021 14:00:56 -0400 Subject: [PATCH 0669/2500] cmd/compile/internal/types2: merge Instantiate and InstantiateLazy Instantiate and InstantiateLazy have the same signature; on first principles, if Instantiate should work for importers it should be possible to consolidate these APIs. This CL does this. In order to make it work, a typMap needs to be threaded through type expansion to prevent infinite recursion in the case that the Checker is nil. Notably, Named types now must be expanded before returning from Underlying(). This makes Underlying generally unsafe to call while type checking a package, so a helper function safeUnderlying is added to provide the previous behavior. This is probably overly conservative at most call sites, but cleanup is deferred to a later CL. Change-Id: I03cfb75bea0750862cd6eea4e3cdc875a7daa989 Reviewed-on: https://go-review.googlesource.com/c/go/+/341855 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/noder/reader2.go | 2 +- src/cmd/compile/internal/types2/api_test.go | 4 +- src/cmd/compile/internal/types2/call.go | 4 +- src/cmd/compile/internal/types2/decl.go | 5 ++- src/cmd/compile/internal/types2/expr.go | 2 +- src/cmd/compile/internal/types2/infer.go | 6 +-- .../compile/internal/types2/instantiate.go | 27 +++++-------- src/cmd/compile/internal/types2/lookup.go | 4 +- src/cmd/compile/internal/types2/named.go | 39 +++++++++++++++---- src/cmd/compile/internal/types2/predicates.go | 4 +- src/cmd/compile/internal/types2/signature.go | 4 +- src/cmd/compile/internal/types2/subst.go | 22 +++++++---- src/cmd/compile/internal/types2/type.go | 2 +- src/cmd/compile/internal/types2/typexpr.go | 14 ++++--- src/cmd/compile/internal/types2/unify.go | 4 +- 15 files changed, 87 insertions(+), 56 deletions(-) diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index 5637196dc0..97ea4fcb76 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -229,7 +229,7 @@ func (r *reader2) doTyp() (res types2.Type) { obj, targs := r.obj() name := obj.(*types2.TypeName) if len(targs) != 0 { - return r.p.check.InstantiateLazy(syntax.Pos{}, name.Type(), targs, nil, false) + return r.p.check.Instantiate(syntax.Pos{}, name.Type(), targs, nil, false) } return name.Type() diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index d8844956af..dfa4de1175 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -1875,7 +1875,7 @@ func TestInstantiate(t *testing.T) { res := check.Instantiate(nopos, T, []Type{Typ[Int]}, nil, false) // instantiated type should point to itself - if res.Underlying().(*Pointer).Elem() != res { - t.Fatalf("unexpected result type: %s", res) + if p := res.Underlying().(*Pointer).Elem(); p != res { + t.Fatalf("unexpected result type: %s points to %s", res, p) } } diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 049d80dd9e..94bcc4870b 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -334,7 +334,7 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T // need to compute it from the adjusted list; otherwise we can // simply use the result signature's parameter list. if adjusted { - sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(sig.TParams().list(), targs)).(*Tuple) + sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(sig.TParams().list(), targs), nil).(*Tuple) } else { sigParams = rsig.params } @@ -555,7 +555,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) { // (If we modify m, some tests will fail; possibly because the m is in use.) // TODO(gri) investigate and provide a correct explanation here copy := *m - copy.typ = check.subst(e.Pos(), m.typ, makeSubstMap(sig.RParams().list(), targs)) + copy.typ = check.subst(e.Pos(), m.typ, makeSubstMap(sig.RParams().list(), targs), nil) obj = © } // TODO(gri) we also need to do substitution for parameterized interface methods diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index bfccbc5dbf..24ec4cd029 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -317,7 +317,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { } case *Named: - t.expand() + t.expand(check.typMap) // don't touch the type if it is from a different package or the Universe scope // (doing so would lead to a race condition - was issue #35049) @@ -650,7 +650,8 @@ func (check *Checker) collectMethods(obj *TypeName) { // and field names must be distinct." base := asNamed(obj.typ) // shouldn't fail but be conservative if base != nil { - if t, _ := base.Underlying().(*Struct); t != nil { + u := safeUnderlying(base) // base should be expanded, but use safeUnderlying to be conservative + if t, _ := u.(*Struct); t != nil { for _, fld := range t.fields { if fld.name != "_" { assert(mset.insert(fld) == nil) diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 3c2b10cd7e..6d8b423714 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -661,7 +661,7 @@ func (check *Checker) updateExprVal(x syntax.Expr, val constant.Value) { func (check *Checker) convertUntyped(x *operand, target Type) { newType, val, code := check.implicitTypeAndValue(x, target) if code != 0 { - check.invalidConversion(code, x, target.Underlying()) + check.invalidConversion(code, x, safeUnderlying(target)) x.mode = invalid return } diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index ff4bb3ea17..7bf507471d 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -87,7 +87,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeName, targs []Type, p // but that doesn't impact the isParameterized check for now). if params.Len() > 0 { smap := makeSubstMap(tparams, targs) - params = check.subst(nopos, params, smap).(*Tuple) + params = check.subst(nopos, params, smap, nil).(*Tuple) } // --- 2 --- @@ -127,7 +127,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeName, targs []Type, p } } smap := makeSubstMap(tparams, targs) - inferred := check.subst(arg.Pos(), tpar, smap) + inferred := check.subst(arg.Pos(), tpar, smap, nil) if inferred != tpar { check.errorf(arg, "%s %s of %s does not match inferred type %s for %s", kind, targ, arg.expr, inferred, tpar) } else { @@ -427,7 +427,7 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty n := 0 for _, index := range dirty { t0 := types[index] - if t1 := check.subst(nopos, t0, smap); t1 != t0 { + if t1 := check.subst(nopos, t0, smap, nil); t1 != t0 { types[index] = t1 dirty[n] = index n++ diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 0bb4ac956b..a648a3c38c 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -29,7 +29,7 @@ func (check *Checker) Instantiate(pos syntax.Pos, typ Type, targs []Type, posLis var tparams []*TypeName switch t := typ.(type) { case *Named: - tparams = t.TParams().list() + return check.instantiateLazy(pos, t, targs, posList, verify) case *Signature: tparams = t.TParams().list() defer func() { @@ -55,14 +55,14 @@ func (check *Checker) Instantiate(pos syntax.Pos, typ Type, targs []Type, posLis panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } - inst := check.instantiate(pos, typ, tparams, targs, posList) + inst := check.instantiate(pos, typ, tparams, targs, posList, nil) if verify && len(tparams) == len(targs) { check.verify(pos, tparams, targs, posList) } return inst } -func (check *Checker) instantiate(pos syntax.Pos, typ Type, tparams []*TypeName, targs []Type, posList []syntax.Pos) (res Type) { +func (check *Checker) instantiate(pos syntax.Pos, typ Type, tparams []*TypeName, targs []Type, posList []syntax.Pos, typMap map[string]*Named) (res Type) { // the number of supplied types must match the number of type parameters if len(targs) != len(tparams) { // TODO(gri) provide better error message @@ -83,7 +83,7 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, tparams []*TypeName, // Calling under() here may lead to endless instantiations. // Test case: type T[P any] T[P] // TODO(gri) investigate if that's a bug or to be expected. - under = res.Underlying() + under = safeUnderlying(res) } check.trace(pos, "=> %s (under = %s)", res, under) }() @@ -95,21 +95,14 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, tparams []*TypeName, return typ // nothing to do (minor optimization) } - return check.subst(pos, typ, makeSubstMap(tparams, targs)) + return check.subst(pos, typ, makeSubstMap(tparams, targs), typMap) } -// InstantiateLazy is like Instantiate, but avoids actually -// instantiating the type until needed. typ must be a *Named -// type. -func (check *Checker) InstantiateLazy(pos syntax.Pos, typ Type, targs []Type, posList []syntax.Pos, verify bool) Type { - // Don't use asNamed here: we don't want to expand the base during lazy - // instantiation. - base := typ.(*Named) - if base == nil { - panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) - } - +// instantiateLazy avoids actually instantiating the type until needed. typ +// must be a *Named type. +func (check *Checker) instantiateLazy(pos syntax.Pos, base *Named, targs []Type, posList []syntax.Pos, verify bool) Type { if verify && base.TParams().Len() == len(targs) { + // TODO: lift the nil check in verify to here. check.later(func() { check.verify(pos, base.tparams.list(), targs, posList) }) @@ -169,7 +162,7 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap // as the instantiated type; before we can use it for bounds checking we // need to instantiate it with the type arguments with which we instantiate // the parameterized type. - iface = check.subst(pos, iface, smap).(*Interface) + iface = check.subst(pos, iface, smap, nil).(*Interface) // if iface is comparable, targ must be comparable // TODO(gri) the error messages needs to be better, here diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index 0363008ad9..3779d17b3d 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -46,7 +46,7 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o // pointer type but discard the result if it is a method since we would // not have found it for T (see also issue 8590). if t := asNamed(T); t != nil { - if p, _ := t.Underlying().(*Pointer); p != nil { + if p, _ := safeUnderlying(t).(*Pointer); p != nil { obj, index, indirect = lookupFieldOrMethod(p, false, pkg, name) if _, ok := obj.(*Func); ok { return nil, nil, false @@ -394,7 +394,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, if len(ftyp.RParams().list()) != len(Vn.targs) { return } - ftyp = check.subst(nopos, ftyp, makeSubstMap(ftyp.RParams().list(), Vn.targs)).(*Signature) + ftyp = check.subst(nopos, ftyp, makeSubstMap(ftyp.RParams().list(), Vn.targs), nil).(*Signature) } // If the methods have type parameters we don't care whether they diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index adf3eb3822..b12e59b586 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -153,7 +153,7 @@ func (t *Named) AddMethod(m *Func) { } } -func (t *Named) Underlying() Type { return t.load().underlying } +func (t *Named) Underlying() Type { return t.load().expand(nil).underlying } func (t *Named) String() string { return TypeString(t, nil) } // ---------------------------------------------------------------------------- @@ -166,9 +166,9 @@ func (t *Named) String() string { return TypeString(t, nil) } // is detected, the result is Typ[Invalid]. If a cycle is detected and // n0.check != nil, the cycle is reported. func (n0 *Named) under() Type { - n0.expand() + n0.expand(nil) - u := n0.Underlying() + u := n0.load().underlying if u == Typ[Invalid] { return u @@ -206,7 +206,7 @@ func (n0 *Named) under() Type { seen := map[*Named]int{n0: 0} path := []Object{n0.obj} for { - u = n.Underlying() + u = n.load().underlying if u == nil { u = Typ[Invalid] break @@ -214,7 +214,7 @@ func (n0 *Named) under() Type { var n1 *Named switch u1 := u.(type) { case *Named: - u1.expand() + u1.expand(nil) n1 = u1 } if n1 == nil { @@ -264,15 +264,40 @@ type instance struct { // expand ensures that the underlying type of n is instantiated. // The underlying type will be Typ[Invalid] if there was an error. -func (n *Named) expand() { +func (n *Named) expand(typMap map[string]*Named) *Named { if n.instance != nil { // n must be loaded before instantiation, in order to have accurate // tparams. This is done implicitly by the call to n.TParams, but making it // explicit is harmless: load is idempotent. n.load() - inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams().list(), n.targs, n.instance.posList) + if typMap == nil { + if n.check != nil { + typMap = n.check.typMap + } else { + // If we're instantiating lazily, we might be outside the scope of a + // type-checking pass. In that case we won't have a pre-existing + // typMap, but don't want to create a duplicate of the current instance + // in the process of expansion. + h := instantiatedHash(n.orig, n.targs) + typMap = map[string]*Named{h: n} + } + } + + inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams().list(), n.targs, n.instance.posList, typMap) n.underlying = inst n.fromRHS = inst n.instance = nil } + return n +} + +// safeUnderlying returns the underlying of typ without expanding instances, to +// avoid infinite recursion. +// +// TODO(rfindley): eliminate this function or give it a better name. +func safeUnderlying(typ Type) Type { + if t, _ := typ.(*Named); t != nil { + return t.load().underlying + } + return typ.Underlying() } diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 1541b3f416..070a0b3932 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -302,8 +302,8 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { // Two named types are identical if their type names originate // in the same type declaration. if y, ok := y.(*Named); ok { - x.expand() - y.expand() + x.expand(nil) + y.expand(nil) // TODO(gri) Why is x == y not sufficient? And if it is, // we can just return false here because x == y // is caught in the very beginning of this function. diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index 48b11b289c..c4c209b357 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -153,7 +153,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] // TODO(gri) should we assume now that bounds always exist? // (no bound == empty interface) if bound != nil { - bound = check.subst(tname.pos, bound, smap) + bound = check.subst(tname.pos, bound, smap, nil) tname.typ.(*TypeParam).bound = bound } } @@ -215,7 +215,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] var err string switch T := rtyp.(type) { case *Named: - T.expand() + T.expand(nil) // spec: "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." diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 26796fc604..044544f1f9 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -51,7 +51,9 @@ func (m *substMap) lookup(tpar *TypeParam) Type { // subst is functional in the sense that it doesn't modify the incoming // type. If a substitution took place, the result type is different from // from the incoming type. -func (check *Checker) subst(pos syntax.Pos, typ Type, smap *substMap) Type { +// +// If the given typMap is nil and check is non-nil, check.typMap is used. +func (check *Checker) subst(pos syntax.Pos, typ Type, smap *substMap, typMap map[string]*Named) Type { if smap.empty() { return typ } @@ -68,16 +70,21 @@ func (check *Checker) subst(pos syntax.Pos, typ Type, smap *substMap) Type { var subst subster subst.pos = pos subst.smap = smap + if check != nil { subst.check = check - subst.typMap = check.typMap - } else { + if typMap == nil { + typMap = check.typMap + } + } + if typMap == nil { // If we don't have a *Checker and its global type map, // use a local version. Besides avoiding duplicate work, // the type map prevents infinite recursive substitution // for recursive types (example: type T[P any] *T[P]). - subst.typMap = make(map[string]*Named) + typMap = make(map[string]*Named) } + subst.typMap = typMap return subst.typ(typ) } @@ -234,14 +241,15 @@ func (subst *subster) typ(typ Type) Type { // create a new named type and populate typMap to avoid endless recursion tname := NewTypeName(subst.pos, t.obj.pkg, t.obj.name, nil) - named := subst.check.newNamed(tname, t, t.Underlying(), t.TParams(), t.methods) // method signatures are updated lazily + t.load() + named := subst.check.newNamed(tname, t.orig, t.underlying, t.TParams(), t.methods) // method signatures are updated lazily named.targs = new_targs subst.typMap[h] = named - t.expand() // must happen after typMap update to avoid infinite recursion + t.expand(subst.typMap) // must happen after typMap update to avoid infinite recursion // do the substitution dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, new_targs) - named.underlying = subst.typOrNil(t.Underlying()) + named.underlying = subst.typOrNil(t.underlying) dump(">>> underlying: %v", named.underlying) assert(named.underlying != nil) named.fromRHS = named.underlying // for cycle detection (Checker.validType) diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 637829613b..4b8642aa96 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -116,7 +116,7 @@ func asInterface(t Type) *Interface { func asNamed(t Type) *Named { e, _ := t.(*Named) if e != nil { - e.expand() + e.expand(nil) } return e } diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 6a9eacd31d..a53319c153 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -225,7 +225,7 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) { // Test case: type T[P any] *T[P] // TODO(gri) investigate if that's a bug or to be expected // (see also analogous comment in Checker.instantiate). - under = T.Underlying() + under = safeUnderlying(T) } if T == under { check.trace(e0.Pos(), "=> %s // %s", T, goTypeName(T)) @@ -422,9 +422,13 @@ func (check *Checker) typOrNil(e syntax.Expr) Type { } func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def *Named) Type { - base := check.genericType(x, true) - if base == Typ[Invalid] { - return base // error already reported + gtyp := check.genericType(x, true) + if gtyp == Typ[Invalid] { + return gtyp // error already reported + } + base, _ := gtyp.(*Named) + if base == nil { + panic(fmt.Sprintf("%v: cannot instantiate %v", x.Pos(), gtyp)) } // evaluate arguments @@ -440,7 +444,7 @@ func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def posList[i] = syntax.StartPos(arg) } - typ := check.InstantiateLazy(x.Pos(), base, targs, posList, true) + typ := check.instantiateLazy(x.Pos(), base, targs, posList, true) def.setUnderlying(typ) // make sure we check instantiation works at least once diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index ae81382fb0..28f9cf751c 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -432,8 +432,8 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { // return x.obj == y.obj // } if y, ok := y.(*Named); ok { - x.expand() - y.expand() + x.expand(nil) + y.expand(nil) // TODO(gri) This is not always correct: two types may have the same names // in the same package if one of them is nested in a function. // Extremely unlikely but we need an always correct solution. -- GitLab From 50f4ebbdd30f53272b5f42ab66c50939eade0a0e Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Wed, 11 Aug 2021 11:45:11 -0400 Subject: [PATCH 0670/2500] cmd/compile/internal/types2: define Identical for instances Instantiation of parameterized types may occur in other packages, so we need an intrinsic notion of type identity for instances. Add the natural definition: two instances are identical if their bases and type arguments are identical. Type unification was already considering type arguments, but has some inaccurate logic with respect to objects. This will be addressed in a follow-up CL. Change-Id: Ib2ce67c05de65eb302ee588cc40c89c60018da50 Reviewed-on: https://go-review.googlesource.com/c/go/+/341856 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/api_test.go | 25 +++++++++++++++++++ src/cmd/compile/internal/types2/predicates.go | 22 ++++++++++++++++ src/cmd/compile/internal/types2/unify.go | 5 ---- 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index dfa4de1175..be05d06fd0 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -1879,3 +1879,28 @@ func TestInstantiate(t *testing.T) { t.Fatalf("unexpected result type: %s points to %s", res, p) } } + +func TestInstanceIdentity(t *testing.T) { + imports := make(testImporter) + conf := Config{Importer: imports} + makePkg := func(src string) { + f, err := parseSrc("", src) + if err != nil { + t.Fatal(err) + } + name := f.PkgName.Value + pkg, err := conf.Check(name, []*syntax.File{f}, nil) + if err != nil { + t.Fatal(err) + } + imports[name] = pkg + } + makePkg(genericPkg + `lib; type T[P any] struct{}`) + makePkg(genericPkg + `a; import "generic_lib"; var A generic_lib.T[int]`) + makePkg(genericPkg + `b; import "generic_lib"; var B generic_lib.T[int]`) + a := imports["generic_a"].Scope().Lookup("A") + b := imports["generic_b"].Scope().Lookup("B") + if !Identical(a.Type(), b.Type()) { + t.Errorf("mismatching types: a.A: %s, b.B: %s", a.Type(), b.Type()) + } +} diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 070a0b3932..3c883e1ab5 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -304,6 +304,28 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { if y, ok := y.(*Named); ok { x.expand(nil) y.expand(nil) + + xargs := x.TArgs() + yargs := y.TArgs() + + if len(xargs) != len(yargs) { + return false + } + + if len(xargs) > 0 { + // Instances are identical if their original type and type arguments + // are identical. + if !Identical(x.orig, y.orig) { + return false + } + for i, xa := range xargs { + if !Identical(xa, yargs[i]) { + return false + } + } + return true + } + // TODO(gri) Why is x == y not sufficient? And if it is, // we can just return false here because x == y // is caught in the very beginning of this function. diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index 28f9cf751c..710fc51b53 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -426,11 +426,6 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { } case *Named: - // Two named types are identical if their type names originate - // in the same type declaration. - // if y, ok := y.(*Named); ok { - // return x.obj == y.obj - // } if y, ok := y.(*Named); ok { x.expand(nil) y.expand(nil) -- GitLab From 2d250043b4c5095f326ab72741d557fe74e4e3a6 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Wed, 11 Aug 2021 13:36:26 -0400 Subject: [PATCH 0671/2500] cmd/compile/internal/types2: simplify Named.under Remove some unnecessary logic from Named.under: - no need to have special handling for Typ[Invalid]: this is the same as other cases where the underlying type is resolved. - use Underlying() to get the loaded and expanded underlying - no need for special handling of the first iteration Change-Id: I2029711f51fa9eaaee11debadd55974a1376a980 Reviewed-on: https://go-review.googlesource.com/c/go/+/341857 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/named.go | 52 +++++++++--------------- 1 file changed, 19 insertions(+), 33 deletions(-) diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index b12e59b586..5967172675 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -166,18 +166,13 @@ func (t *Named) String() string { return TypeString(t, nil) } // is detected, the result is Typ[Invalid]. If a cycle is detected and // n0.check != nil, the cycle is reported. func (n0 *Named) under() Type { - n0.expand(nil) - - u := n0.load().underlying - - if u == Typ[Invalid] { - return u - } + u := n0.Underlying() // If the underlying type of a defined type is not a defined // (incl. instance) type, then that is the desired underlying // type. - switch u.(type) { + var n1 *Named + switch u1 := u.(type) { case nil: return Typ[Invalid] default: @@ -185,6 +180,7 @@ func (n0 *Named) under() Type { return u case *Named: // handled below + n1 = u1 } if n0.check == nil { @@ -194,43 +190,33 @@ func (n0 *Named) under() Type { // Invariant: after this point n0 as well as any named types in its // underlying chain should be set up when this function exits. check := n0.check + n := n0 - // If we can't expand u at this point, it is invalid. - n := asNamed(u) - if n == nil { - n0.underlying = Typ[Invalid] - return n0.underlying - } + seen := make(map[*Named]int) // types that need their underlying resolved + var path []Object // objects encountered, for cycle reporting - // Otherwise, follow the forward chain. - seen := map[*Named]int{n0: 0} - path := []Object{n0.obj} +loop: for { - u = n.load().underlying - if u == nil { - u = Typ[Invalid] - break - } - var n1 *Named - switch u1 := u.(type) { - case *Named: - u1.expand(nil) - n1 = u1 - } - if n1 == nil { - break // end of chain - } - seen[n] = len(seen) path = append(path, n.obj) n = n1 - if i, ok := seen[n]; ok { // cycle check.cycleError(path[i:]) u = Typ[Invalid] break } + u = n.Underlying() + switch u1 := u.(type) { + case nil: + u = Typ[Invalid] + break loop + default: + break loop + case *Named: + // Continue collecting *Named types in the chain. + n1 = u1 + } } for n := range seen { -- GitLab From 456759b24682a41e282f73855377ac4f341da191 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Wed, 11 Aug 2021 12:43:27 -0400 Subject: [PATCH 0672/2500] cmd/compile/internal/types2: use the orig object for Named.Obj Exposing a synthetic type name for instantiated types is problematic: there is no way to ensure that type instances are first created in the same type checking pass, and therefore no guarantee that their instantiation positions are the same. Even type checking a given package with different file ordering could result in different positions being associated with type instances. This is therefore an implementation detail that we should not expose. Keep the synthetic type name for accurate error reporting, but hide it in the API. Change-Id: I61f0e3ed322e97b157eb1ca316480f5719dcc174 Reviewed-on: https://go-review.googlesource.com/c/go/+/341858 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/named.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index 5967172675..ad29886f7d 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -15,7 +15,7 @@ import ( type Named struct { check *Checker info typeInfo // for cycle detection - obj *TypeName // corresponding declared object + obj *TypeName // corresponding declared object for declared types; placeholder for instantiated types orig *Named // original, uninstantiated type fromRHS Type // type (on RHS of declaration) this *Named type is derived from (for cycle reporting) underlying Type // possibly a *Named during setup; never a *Named once set up completely @@ -108,8 +108,11 @@ func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tpar return typ } -// Obj returns the type name for the named type t. -func (t *Named) Obj() *TypeName { return t.obj } +// Obj returns the type name for the declaration defining the named type t. For +// instantiated types, this is the type name of the base type. +func (t *Named) Obj() *TypeName { + return t.orig.obj // for non-instances this is the same as t.obj +} // Orig returns the original generic type an instantiated type is derived from. // If t is not an instantiated type, the result is t. -- GitLab From b2253c8041511fad5fdcf7514131f972f63a01a0 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Thu, 12 Aug 2021 15:03:45 -0400 Subject: [PATCH 0673/2500] cmd/compile/internal/types2: remove targs from substMap Now that we always capture targs when constructing an instance, we no longer need to pass them via the substMap. This simplifies the code and resolves a TODO. Change-Id: I592dccaeb89c7cc31ac037d919137bb762820365 Reviewed-on: https://go-review.googlesource.com/c/go/+/341859 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- .../compile/internal/types2/instantiate.go | 2 +- src/cmd/compile/internal/types2/subst.go | 85 ++++++++----------- 2 files changed, 35 insertions(+), 52 deletions(-) diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index a648a3c38c..fff2635456 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -152,7 +152,7 @@ func (check *Checker) verify(pos syntax.Pos, tparams []*TypeName, targs []Type, // parameter tpar (after any of its type parameters have been substituted through smap). // A suitable error is reported if the result is false. // TODO(gri) This should be a method of interfaces or type sets. -func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap *substMap) bool { +func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap substMap) bool { iface := tpar.iface() if iface.Empty() { return true // no type bound diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 044544f1f9..ed3fd654a0 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -9,38 +9,27 @@ package types2 import ( "bytes" "cmd/compile/internal/syntax" - "fmt" ) -type substMap struct { - // The targs field is currently needed for *Named type substitution. - // TODO(gri) rewrite that code, get rid of this field, and make this - // struct just the map (proj) - targs []Type - proj map[*TypeParam]Type -} +type substMap map[*TypeParam]Type // makeSubstMap creates a new substitution map mapping tpars[i] to targs[i]. // If targs[i] is nil, tpars[i] is not substituted. -func makeSubstMap(tpars []*TypeName, targs []Type) *substMap { +func makeSubstMap(tpars []*TypeName, targs []Type) substMap { assert(len(tpars) == len(targs)) - proj := make(map[*TypeParam]Type, len(tpars)) + proj := make(substMap, len(tpars)) for i, tpar := range tpars { proj[tpar.typ.(*TypeParam)] = targs[i] } - return &substMap{targs, proj} -} - -func (m *substMap) String() string { - return fmt.Sprintf("%s", m.proj) + return proj } -func (m *substMap) empty() bool { - return len(m.proj) == 0 +func (m substMap) empty() bool { + return len(m) == 0 } -func (m *substMap) lookup(tpar *TypeParam) Type { - if t := m.proj[tpar]; t != nil { +func (m substMap) lookup(tpar *TypeParam) Type { + if t := m[tpar]; t != nil { return t } return tpar @@ -53,7 +42,7 @@ func (m *substMap) lookup(tpar *TypeParam) Type { // from the incoming type. // // If the given typMap is nil and check is non-nil, check.typMap is used. -func (check *Checker) subst(pos syntax.Pos, typ Type, smap *substMap, typMap map[string]*Named) Type { +func (check *Checker) subst(pos syntax.Pos, typ Type, smap substMap, typMap map[string]*Named) Type { if smap.empty() { return typ } @@ -91,7 +80,7 @@ func (check *Checker) subst(pos syntax.Pos, typ Type, smap *substMap, typMap map type subster struct { pos syntax.Pos - smap *substMap + smap substMap check *Checker // nil if called via Instantiate typMap map[string]*Named } @@ -199,40 +188,34 @@ func (subst *subster) typ(typ Type) Type { return t // type is not parameterized } - var new_targs []Type - - if len(t.targs) > 0 { - // already instantiated - dump(">>> %s already instantiated", t) - assert(len(t.targs) == t.TParams().Len()) - // For each (existing) type argument targ, determine if it needs - // to be substituted; i.e., if it is or contains a type parameter - // that has a type argument for it. - for i, targ := range t.targs { - dump(">>> %d targ = %s", i, targ) - new_targ := subst.typ(targ) - if new_targ != targ { - dump(">>> substituted %d targ %s => %s", i, targ, new_targ) - if new_targs == nil { - new_targs = make([]Type, t.TParams().Len()) - copy(new_targs, t.targs) - } - new_targs[i] = new_targ + var newTArgs []Type + assert(len(t.targs) == t.TParams().Len()) + + // already instantiated + dump(">>> %s already instantiated", t) + // For each (existing) type argument targ, determine if it needs + // to be substituted; i.e., if it is or contains a type parameter + // that has a type argument for it. + for i, targ := range t.targs { + dump(">>> %d targ = %s", i, targ) + new_targ := subst.typ(targ) + if new_targ != targ { + dump(">>> substituted %d targ %s => %s", i, targ, new_targ) + if newTArgs == nil { + newTArgs = make([]Type, t.TParams().Len()) + copy(newTArgs, t.targs) } + newTArgs[i] = new_targ } + } - if new_targs == nil { - dump(">>> nothing to substitute in %s", t) - return t // nothing to substitute - } - } else { - // not yet instantiated - dump(">>> first instantiation of %s", t) - new_targs = subst.smap.targs + if newTArgs == nil { + dump(">>> nothing to substitute in %s", t) + return t // nothing to substitute } // before creating a new named type, check if we have this one already - h := instantiatedHash(t, new_targs) + h := instantiatedHash(t, newTArgs) dump(">>> new type hash: %s", h) if named, found := subst.typMap[h]; found { dump(">>> found %s", named) @@ -243,12 +226,12 @@ func (subst *subster) typ(typ Type) Type { tname := NewTypeName(subst.pos, t.obj.pkg, t.obj.name, nil) t.load() named := subst.check.newNamed(tname, t.orig, t.underlying, t.TParams(), t.methods) // method signatures are updated lazily - named.targs = new_targs + named.targs = newTArgs subst.typMap[h] = named t.expand(subst.typMap) // must happen after typMap update to avoid infinite recursion // do the substitution - dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, new_targs) + dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, newTArgs) named.underlying = subst.typOrNil(t.underlying) dump(">>> underlying: %v", named.underlying) assert(named.underlying != nil) -- GitLab From 49c688e45c9bb8782b3db4df9dcaf163a4965f6d Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Fri, 13 Aug 2021 11:16:50 -0400 Subject: [PATCH 0674/2500] cmd/compile/internal/types2: rename TypeParams to TParamList The 'TypeParams' name is too easily confused with the singular 'TypeParam', and does not say anything about what type of collection it is. We decided that TTuple was not great. TParamList seems OK for now, though perhaps a better name will emerge. Change-Id: I5eabdc91b1f666bb4c7ea8acdbebf7c372d19227 Reviewed-on: https://go-review.googlesource.com/c/go/+/341861 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/noder/writer.go | 4 ++-- src/cmd/compile/internal/types2/decl.go | 2 +- src/cmd/compile/internal/types2/named.go | 6 +++--- src/cmd/compile/internal/types2/signature.go | 8 ++++---- src/cmd/compile/internal/types2/typeparam.go | 14 +++++++------- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index b5028e7f69..d971bd0d16 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -646,7 +646,7 @@ func (w *writer) objDict(obj types2.Object, dict *writerDict) { assert(len(dict.funcs) == nfuncs) } -func (w *writer) typeParamNames(tparams *types2.TypeParams) { +func (w *writer) typeParamNames(tparams *types2.TParamList) { w.sync(syncTypeParamNames) ntparams := tparams.Len() @@ -1861,7 +1861,7 @@ func fieldIndex(info *types2.Info, str *types2.Struct, key *syntax.Name) int { } // objTypeParams returns the type parameters on the given object. -func objTypeParams(obj types2.Object) *types2.TypeParams { +func objTypeParams(obj types2.Object) *types2.TParamList { switch obj := obj.(type) { case *types2.Func: sig := obj.Type().(*types2.Signature) diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 24ec4cd029..aa9710788a 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -581,7 +581,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named } } -func (check *Checker) collectTypeParams(list []*syntax.Field) *TypeParams { +func (check *Checker) collectTypeParams(list []*syntax.Field) *TParamList { tparams := make([]*TypeName, len(list)) // Declare type parameters up-front. diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index ad29886f7d..3ce9c5b0c7 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -20,7 +20,7 @@ type Named struct { fromRHS Type // type (on RHS of declaration) this *Named type is derived from (for cycle reporting) underlying Type // possibly a *Named during setup; never a *Named once set up completely instance *instance // position information for lazy instantiation, or nil - tparams *TypeParams // type parameters, or nil + tparams *TParamList // type parameters, or nil targs []Type // type arguments (after instantiation), or nil methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily @@ -80,7 +80,7 @@ func (t *Named) load() *Named { } // newNamed is like NewNamed but with a *Checker receiver and additional orig argument. -func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams *TypeParams, methods []*Func) *Named { +func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams *TParamList, methods []*Func) *Named { typ := &Named{check: check, obj: obj, orig: orig, fromRHS: underlying, underlying: underlying, tparams: tparams, methods: methods} if typ.orig == nil { typ.orig = typ @@ -123,7 +123,7 @@ func (t *Named) Orig() *Named { return t.orig } // TParams returns the type parameters of the named type t, or nil. // The result is non-nil for an (originally) parameterized type even if it is instantiated. -func (t *Named) TParams() *TypeParams { return t.load().tparams } +func (t *Named) TParams() *TParamList { return t.load().tparams } // SetTParams sets the type parameters of the named type t. func (t *Named) SetTParams(tparams []*TypeName) { t.load().tparams = bindTParams(tparams) } diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index c4c209b357..e319e65211 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -19,8 +19,8 @@ type Signature struct { // and store it in the Func Object) because when type-checking a function // literal we call the general type checker which returns a general Type. // We then unpack the *Signature and use the scope for the literal body. - rparams *TypeParams // receiver type parameters from left to right, or nil - tparams *TypeParams // type parameters from left to right, or nil + rparams *TParamList // receiver type parameters from left to right, or nil + tparams *TParamList // type parameters from left to right, or nil scope *Scope // function scope, present for package-local signatures recv *Var // nil if not a method params *Tuple // (incoming) parameters from left to right; or nil @@ -54,13 +54,13 @@ func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature { func (s *Signature) Recv() *Var { return s.recv } // TParams returns the type parameters of signature s, or nil. -func (s *Signature) TParams() *TypeParams { return s.tparams } +func (s *Signature) TParams() *TParamList { return s.tparams } // SetTParams sets the type parameters of signature s. func (s *Signature) SetTParams(tparams []*TypeName) { s.tparams = bindTParams(tparams) } // RParams returns the receiver type parameters of signature s, or nil. -func (s *Signature) RParams() *TypeParams { return s.rparams } +func (s *Signature) RParams() *TParamList { return s.rparams } // SetRParams sets the receiver type params of signature s. func (s *Signature) SetRParams(rparams []*TypeName) { s.rparams = bindTParams(rparams) } diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index 4b4282efe0..f666fae7ed 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -83,28 +83,28 @@ func (t *TypeParam) SetConstraint(bound Type) { func (t *TypeParam) Underlying() Type { return t } func (t *TypeParam) String() string { return TypeString(t, nil) } -// TypeParams holds a list of type parameters bound to a type. -type TypeParams struct{ tparams []*TypeName } +// TParamList holds a list of type parameters bound to a type. +type TParamList struct{ tparams []*TypeName } // Len returns the number of type parameters in the list. // It is safe to call on a nil receiver. -func (tps *TypeParams) Len() int { +func (tps *TParamList) Len() int { return len(tps.list()) } // At returns the i'th type parameter in the list. -func (tps *TypeParams) At(i int) *TypeName { +func (tps *TParamList) At(i int) *TypeName { return tps.list()[i] } -func (tps *TypeParams) list() []*TypeName { +func (tps *TParamList) list() []*TypeName { if tps == nil { return nil } return tps.tparams } -func bindTParams(list []*TypeName) *TypeParams { +func bindTParams(list []*TypeName) *TParamList { if len(list) == 0 { return nil } @@ -115,7 +115,7 @@ func bindTParams(list []*TypeName) *TypeParams { } typ.index = i } - return &TypeParams{tparams: list} + return &TParamList{tparams: list} } // ---------------------------------------------------------------------------- -- GitLab From 0a0a160d4df488939892a1adaca6c530fb784cc8 Mon Sep 17 00:00:00 2001 From: Jeff Wentworth Date: Sat, 14 Aug 2021 09:46:32 +0000 Subject: [PATCH 0675/2500] sync/atomic: fix documentation for CompareAndSwap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #47699 The documentation for CompareAndSwap atomic/value incorrectly labelled the function as CompareAndSwapPointer. This PR fixes that. Change-Id: I6db08fdfe166570b775248fd24550f5d28e3434e GitHub-Last-Rev: 41f78707928f48c9cdac26b6a4f618d4284e1ca1 GitHub-Pull-Request: golang/go#47700 Reviewed-on: https://go-review.googlesource.com/c/go/+/342210 Reviewed-by: Keith Randall Reviewed-by: Daniel Martí Trust: Daniel Martí Run-TryBot: Daniel Martí TryBot-Result: Go Bot --- src/sync/atomic/value.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sync/atomic/value.go b/src/sync/atomic/value.go index 61f81d8fd3..3500cd22f4 100644 --- a/src/sync/atomic/value.go +++ b/src/sync/atomic/value.go @@ -126,7 +126,7 @@ func (v *Value) Swap(new interface{}) (old interface{}) { } } -// CompareAndSwapPointer executes the compare-and-swap operation for the Value. +// CompareAndSwap executes the compare-and-swap operation for the Value. // // All calls to CompareAndSwap for a given Value must use values of the same // concrete type. CompareAndSwap of an inconsistent type panics, as does -- GitLab From ff3469b1c21e241a8319f9e79412849819d7ecab Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sat, 14 Aug 2021 00:03:09 -0400 Subject: [PATCH 0676/2500] cmd/dist: remove tests using the typeparams build tag This stanza is no longer necessary now that the typeparams build tag is not used. Change-Id: I7bcc4a01e354e5130d50b00895a5b96c25c71502 Reviewed-on: https://go-review.googlesource.com/c/go/+/342153 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/dist/test.go | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index f40fa926df..a104b5c8f3 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -491,19 +491,6 @@ func (t *tester) registerTests() { }) } - // Test go/... cmd/gofmt with type parameters enabled. - if !t.compileOnly { - t.tests = append(t.tests, distTest{ - name: "tyepparams", - heading: "go/... and cmd/gofmt tests with tag typeparams", - fn: func(dt *distTest) error { - t.addCmd(dt, "src", t.goTest(), t.timeout(300), "-tags=typeparams", "go/...") - t.addCmd(dt, "src", t.goTest(), t.timeout(300), "-tags=typeparams", "cmd/gofmt") - return nil - }, - }) - } - if t.iOS() && !t.compileOnly { t.tests = append(t.tests, distTest{ name: "x509omitbundledroots", -- GitLab From 1162aae0ad7d7fefeebd1c8537c457eae76d43ec Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 13 Aug 2021 13:58:23 -0700 Subject: [PATCH 0677/2500] time/tzdata: update links in comment Change-Id: I141d29bb4adc957de5de1f8ed8867980fd3c8386 Reviewed-on: https://go-review.googlesource.com/c/go/+/342071 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Emmanuel Odeke --- src/time/tzdata/generate_zipdata.go | 4 ++-- src/time/tzdata/zipdata.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/time/tzdata/generate_zipdata.go b/src/time/tzdata/generate_zipdata.go index 64b5b1b22c..0869c8458c 100644 --- a/src/time/tzdata/generate_zipdata.go +++ b/src/time/tzdata/generate_zipdata.go @@ -31,8 +31,8 @@ const header = `// Copyright 2020 The Go Authors. All rights reserved. // For more information, see // https://www.iana.org/time-zones -// ftp://ftp.iana.org/tz/code/tz-link.htm -// http://tools.ietf.org/html/rfc6557 +// ftp://ftp.iana.org/tz/code/tz-link.html +// https://datatracker.ietf.org/doc/html/rfc6557 package tzdata diff --git a/src/time/tzdata/zipdata.go b/src/time/tzdata/zipdata.go index 03b59720e2..60c0784008 100644 --- a/src/time/tzdata/zipdata.go +++ b/src/time/tzdata/zipdata.go @@ -11,8 +11,8 @@ // For more information, see // https://www.iana.org/time-zones -// ftp://ftp.iana.org/tz/code/tz-link.htm -// http://tools.ietf.org/html/rfc6557 +// ftp://ftp.iana.org/tz/code/tz-link.html +// https://datatracker.ietf.org/doc/html/rfc6557 package tzdata -- GitLab From 48dfddbab3569798267798a5d8828bf35355eb9d Mon Sep 17 00:00:00 2001 From: 180909 <734461790@qq.com> Date: Sun, 15 Aug 2021 01:57:33 +0000 Subject: [PATCH 0678/2500] lib/time: fix RFC 6557 url Change-Id: I59406ee7dbab7b2a0404b62061af552b6b4ecf5f GitHub-Last-Rev: 7cad5ae9bac19fdffb072413095fe5b223c95eca GitHub-Pull-Request: golang/go#47696 Reviewed-on: https://go-review.googlesource.com/c/go/+/342209 Reviewed-by: Emmanuel Odeke Reviewed-by: Ian Lance Taylor Run-TryBot: Emmanuel Odeke TryBot-Result: Go Bot --- lib/time/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/time/README b/lib/time/README index edb8dccd26..0de06df13b 100644 --- a/lib/time/README +++ b/lib/time/README @@ -5,6 +5,6 @@ The IANA asserts that the database is in the public domain. For more information, see https://www.iana.org/time-zones ftp://ftp.iana.org/tz/code/tz-link.html -http://tools.ietf.org/html/rfc6557 +https://datatracker.ietf.org/doc/html/rfc6557 To rebuild the archive, read and run update.bash. -- GitLab From 6ed9463133daabcf11b259155c3f3348ae5a06af Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sun, 15 Aug 2021 11:46:33 -0700 Subject: [PATCH 0679/2500] cmd/compile/internal/syntax: better error message for index syntax error Fixes #47704. Change-Id: I1de9fd00baaa4b534c23f011ade54120f5153a9d Reviewed-on: https://go-review.googlesource.com/c/go/+/342369 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/syntax/parser.go | 6 +++++- .../internal/syntax/testdata/issue47704.src | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/cmd/compile/internal/syntax/testdata/issue47704.src diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index acffd84885..29f5c88d0f 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -1049,7 +1049,11 @@ loop: } // x[i:... - p.want(_Colon) + // For better error message, don't use p.want(_Colon) here (issue #47704). + if !p.got(_Colon) { + p.syntaxError("expecting : or ]") + p.advance(_Colon, _Rbrack) + } p.xnest++ t := new(SliceExpr) t.pos = pos diff --git a/src/cmd/compile/internal/syntax/testdata/issue47704.src b/src/cmd/compile/internal/syntax/testdata/issue47704.src new file mode 100644 index 0000000000..0156af7d8d --- /dev/null +++ b/src/cmd/compile/internal/syntax/testdata/issue47704.src @@ -0,0 +1,18 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +// error messages for parser in non-generic mode +func _() { + _ = m[] // ERROR expecting operand + _ = m[x,] // ERROR unexpected comma, expecting \: or \] + _ = m[x /* ERROR unexpected a */ a b c d] +} + +// test case from the issue +func f(m map[int]int) int { + return m[0 // ERROR expecting \: or \] + ] +} -- GitLab From 717894cf8024cfaad629f0e66a4b9bc123676be5 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sun, 15 Aug 2021 12:34:59 -0700 Subject: [PATCH 0680/2500] cmd/compile/internal/types2: better error message for index syntax error (follow-up) For #47704. Change-Id: I09e6f638df0cd456a20a3b68ab55c47bb5b1f555 Reviewed-on: https://go-review.googlesource.com/c/go/+/342370 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley TryBot-Result: Go Bot --- src/cmd/compile/internal/syntax/parser.go | 11 ++++++++--- .../internal/syntax/testdata/issue47704.go2 | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 src/cmd/compile/internal/syntax/testdata/issue47704.go2 diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index 29f5c88d0f..4fb6de10a8 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -1049,10 +1049,15 @@ loop: } // x[i:... - // For better error message, don't use p.want(_Colon) here (issue #47704). + // For better error message, don't simply use p.want(_Colon) here (issue #47704). if !p.got(_Colon) { - p.syntaxError("expecting : or ]") - p.advance(_Colon, _Rbrack) + if p.mode&AllowGenerics == 0 { + p.syntaxError("expecting : or ]") + p.advance(_Colon, _Rbrack) + } else { + p.syntaxError("expecting comma, : or ]") + p.advance(_Comma, _Colon, _Rbrack) + } } p.xnest++ t := new(SliceExpr) diff --git a/src/cmd/compile/internal/syntax/testdata/issue47704.go2 b/src/cmd/compile/internal/syntax/testdata/issue47704.go2 new file mode 100644 index 0000000000..4e65857f3b --- /dev/null +++ b/src/cmd/compile/internal/syntax/testdata/issue47704.go2 @@ -0,0 +1,18 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +// error messages for parser in generic mode +func _() { + _ = m[] // ERROR expecting operand + _ = m[x,] + _ = m[x /* ERROR unexpected a */ a b c d] +} + +// test case from the issue +func f(m map[int]int) int { + return m[0 // ERROR expecting comma, \: or \] + ] +} -- GitLab From 57c115e1f68a997ba8978d4a5abd6ccc954ae3dd Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Mon, 24 May 2021 10:06:36 -0700 Subject: [PATCH 0681/2500] crypto/sha{256,512}: unname result parameters for consistency Sum224 and Sum256 didn't look the same at: https://golang.org/pkg/crypto/sha256/ Now they match. Likewise with sha512's funcs. Per: https://github.com/golang/go/wiki/CodeReviewComments#named-result-parameters Change-Id: I6b88c8ef15141c78a6cddeb0960b3ad52db34244 Reviewed-on: https://go-review.googlesource.com/c/go/+/322329 Run-TryBot: Brad Fitzpatrick TryBot-Result: Go Bot Trust: Brad Fitzpatrick Trust: Katie Hockman Reviewed-by: Katie Hockman Reviewed-by: Ian Lance Taylor --- src/crypto/sha256/sha256.go | 6 +++--- src/crypto/sha512/sha512.go | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/crypto/sha256/sha256.go b/src/crypto/sha256/sha256.go index e1cccf65a6..659531dc71 100644 --- a/src/crypto/sha256/sha256.go +++ b/src/crypto/sha256/sha256.go @@ -259,12 +259,12 @@ func Sum256(data []byte) [Size]byte { } // Sum224 returns the SHA224 checksum of the data. -func Sum224(data []byte) (sum224 [Size224]byte) { +func Sum224(data []byte) [Size224]byte { var d digest d.is224 = true d.Reset() d.Write(data) sum := d.checkSum() - copy(sum224[:], sum[:Size224]) - return + ap := (*[Size224]byte)(sum[:]) + return *ap } diff --git a/src/crypto/sha512/sha512.go b/src/crypto/sha512/sha512.go index 9c143a2a28..d5715558c0 100644 --- a/src/crypto/sha512/sha512.go +++ b/src/crypto/sha512/sha512.go @@ -337,31 +337,31 @@ func Sum512(data []byte) [Size]byte { } // Sum384 returns the SHA384 checksum of the data. -func Sum384(data []byte) (sum384 [Size384]byte) { +func Sum384(data []byte) [Size384]byte { d := digest{function: crypto.SHA384} d.Reset() d.Write(data) sum := d.checkSum() - copy(sum384[:], sum[:Size384]) - return + ap := (*[Size384]byte)(sum[:]) + return *ap } // Sum512_224 returns the Sum512/224 checksum of the data. -func Sum512_224(data []byte) (sum224 [Size224]byte) { +func Sum512_224(data []byte) [Size224]byte { d := digest{function: crypto.SHA512_224} d.Reset() d.Write(data) sum := d.checkSum() - copy(sum224[:], sum[:Size224]) - return + ap := (*[Size224]byte)(sum[:]) + return *ap } // Sum512_256 returns the Sum512/256 checksum of the data. -func Sum512_256(data []byte) (sum256 [Size256]byte) { +func Sum512_256(data []byte) [Size256]byte { d := digest{function: crypto.SHA512_256} d.Reset() d.Write(data) sum := d.checkSum() - copy(sum256[:], sum[:Size256]) - return + ap := (*[Size256]byte)(sum[:]) + return *ap } -- GitLab From 7aa57a96872f07cdccfe9f7eedbbc86819a93554 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Tue, 13 Jul 2021 23:12:18 +0200 Subject: [PATCH 0682/2500] runtime: remove unused getrlimit on linux/riscv64 Follow CL 94775 and CL 93655 which removed the (commented-out) usage of this function on other platforms. Change-Id: I28e0569d8531d0c09f3caefa7c4eb54fb5bd8a33 Reviewed-on: https://go-review.googlesource.com/c/go/+/334429 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/runtime/sys_linux_riscv64.s | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/runtime/sys_linux_riscv64.s b/src/runtime/sys_linux_riscv64.s index 2389f1cc18..54b7a3f61c 100644 --- a/src/runtime/sys_linux_riscv64.s +++ b/src/runtime/sys_linux_riscv64.s @@ -25,7 +25,6 @@ #define SYS_fcntl 25 #define SYS_futex 98 #define SYS_getpid 172 -#define SYS_getrlimit 163 #define SYS_gettid 178 #define SYS_gettimeofday 169 #define SYS_kill 129 @@ -132,15 +131,6 @@ TEXT runtime·pipe2(SB),NOSPLIT|NOFRAME,$0-20 MOVW A0, errno+16(FP) RET -// func getrlimit(kind int32, limit unsafe.Pointer) int32 -TEXT runtime·getrlimit(SB),NOSPLIT|NOFRAME,$0-20 - MOVW kind+0(FP), A0 - MOV limit+8(FP), A1 - MOV $SYS_getrlimit, A7 - ECALL - MOVW A0, ret+16(FP) - RET - // func usleep(usec uint32) TEXT runtime·usleep(SB),NOSPLIT,$24-4 MOVWU usec+0(FP), A0 -- GitLab From 6a760d6c36675335eb1756cc2b3f711ec33aa2e2 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Tue, 18 May 2021 16:01:43 +1000 Subject: [PATCH 0683/2500] runtime: include pthread.h in defs_openbsd.go This is required now that defs_openbsd.go has pthread related references. Updates #36435 Change-Id: I73cdf23eef6aceea6f9b37b7702bdb3b560aa120 Reviewed-on: https://go-review.googlesource.com/c/go/+/334877 Trust: Joel Sing Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/defs_openbsd.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/runtime/defs_openbsd.go b/src/runtime/defs_openbsd.go index 8d323449d1..f818dc4453 100644 --- a/src/runtime/defs_openbsd.go +++ b/src/runtime/defs_openbsd.go @@ -26,6 +26,7 @@ package runtime #include #include #include +#include #include */ import "C" -- GitLab From 160d7972607d5c630c7cfd1b4b54f7c27c3387b1 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Sat, 29 May 2021 04:06:56 +1000 Subject: [PATCH 0684/2500] runtime: correct mips64 asmcgocall signal stack behaviour Do not switch to the g0 stack if we're already running on the signal stack, otherwise all kind of fun ensues. Updates #36435 Change-Id: I57f35d75b9ee4f92b997713b4cdd38ce881705e6 Reviewed-on: https://go-review.googlesource.com/c/go/+/334880 Trust: Joel Sing Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/asm_mips64x.s | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/runtime/asm_mips64x.s b/src/runtime/asm_mips64x.s index b2e2384c36..940a38a0d6 100644 --- a/src/runtime/asm_mips64x.s +++ b/src/runtime/asm_mips64x.s @@ -426,6 +426,8 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-20 // We get called to create new OS threads too, and those // come in on the m->g0 stack already. MOVV g_m(g), R5 + MOVV m_gsignal(R5), R6 + BEQ R6, g, g0 MOVV m_g0(R5), R6 BEQ R6, g, g0 -- GitLab From fcdc3c098cd016af9ba5e626bd4525575bb984f2 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Tue, 20 Jul 2021 17:29:15 +1000 Subject: [PATCH 0685/2500] runtime: make asmcgocall g0/gsignal checks consistent In asmcgocall() we need to switch to the g0 stack if we're not already on the g0 stack or the gsignal stack. The prefered way of doing this is to check gsignal first, then g0, since if we are going to switch to g0 we will need g0 handy (thus avoiding a second load). Rewrite/reorder 386 and amd64 to check gsignal first - this shaves a few assembly instructions off and makes the order consistent with arm, arm64, mips64 and ppc64. Add missing gsignal checks to mips, riscv64 and s390x. Change-Id: I1b027bf393c25e0c33e1d8eb80de67e4a0a3f561 Reviewed-on: https://go-review.googlesource.com/c/go/+/335869 Trust: Joel Sing Run-TryBot: Joel Sing TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/asm_386.s | 16 ++++++++-------- src/runtime/asm_amd64.s | 17 ++++++++--------- src/runtime/asm_arm.s | 3 ++- src/runtime/asm_arm64.s | 3 ++- src/runtime/asm_mips64x.s | 3 ++- src/runtime/asm_mipsx.s | 5 ++++- src/runtime/asm_ppc64x.s | 5 ++--- src/runtime/asm_riscv64.s | 5 ++++- src/runtime/asm_s390x.s | 11 +++++++---- 9 files changed, 39 insertions(+), 29 deletions(-) diff --git a/src/runtime/asm_386.s b/src/runtime/asm_386.s index 11c60309f4..571aa28a9e 100644 --- a/src/runtime/asm_386.s +++ b/src/runtime/asm_386.s @@ -633,18 +633,18 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-12 // Figure out if we need to switch to m->g0 stack. // We get called to create new OS threads too, and those - // come in on the m->g0 stack already. + // come in on the m->g0 stack already. Or we might already + // be on the m->gsignal stack. get_tls(CX) - MOVL g(CX), BP - CMPL BP, $0 - JEQ nosave // Don't even have a G yet. - MOVL g_m(BP), BP - MOVL m_g0(BP), SI MOVL g(CX), DI - CMPL SI, DI - JEQ noswitch + CMPL DI, $0 + JEQ nosave // Don't even have a G yet. + MOVL g_m(DI), BP CMPL DI, m_gsignal(BP) JEQ noswitch + MOVL m_g0(BP), SI + CMPL DI, SI + JEQ noswitch CALL gosave_systemstack_switch<>(SB) get_tls(CX) MOVL SI, g(CX) diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index 2083ecb53e..a6b321aa42 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -667,22 +667,21 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-20 // Figure out if we need to switch to m->g0 stack. // We get called to create new OS threads too, and those - // come in on the m->g0 stack already. + // come in on the m->g0 stack already. Or we might already + // be on the m->gsignal stack. get_tls(CX) - MOVQ g(CX), R8 - CMPQ R8, $0 - JEQ nosave - MOVQ g_m(R8), R8 - MOVQ m_g0(R8), SI MOVQ g(CX), DI - CMPQ SI, DI + CMPQ DI, $0 JEQ nosave + MOVQ g_m(DI), R8 MOVQ m_gsignal(R8), SI - CMPQ SI, DI + CMPQ DI, SI + JEQ nosave + MOVQ m_g0(R8), SI + CMPQ DI, SI JEQ nosave // Switch to system stack. - MOVQ m_g0(R8), SI CALL gosave_systemstack_switch<>(SB) MOVQ SI, g(CX) MOVQ (g_sched+gobuf_sp)(SI), SP diff --git a/src/runtime/asm_arm.s b/src/runtime/asm_arm.s index a1164781d2..b47184e36b 100644 --- a/src/runtime/asm_arm.s +++ b/src/runtime/asm_arm.s @@ -556,7 +556,8 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-12 // Figure out if we need to switch to m->g0 stack. // We get called to create new OS threads too, and those - // come in on the m->g0 stack already. + // come in on the m->g0 stack already. Or we might already + // be on the m->gsignal stack. MOVW g_m(g), R8 MOVW m_gsignal(R8), R3 CMP R3, g diff --git a/src/runtime/asm_arm64.s b/src/runtime/asm_arm64.s index e51ce2f831..8cbd17fa75 100644 --- a/src/runtime/asm_arm64.s +++ b/src/runtime/asm_arm64.s @@ -1027,7 +1027,8 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-20 // Figure out if we need to switch to m->g0 stack. // We get called to create new OS threads too, and those - // come in on the m->g0 stack already. + // come in on the m->g0 stack already. Or we might already + // be on the m->gsignal stack. MOVD g_m(g), R8 MOVD m_gsignal(R8), R3 CMP R3, g diff --git a/src/runtime/asm_mips64x.s b/src/runtime/asm_mips64x.s index 940a38a0d6..e0e5cbb704 100644 --- a/src/runtime/asm_mips64x.s +++ b/src/runtime/asm_mips64x.s @@ -424,7 +424,8 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-20 // Figure out if we need to switch to m->g0 stack. // We get called to create new OS threads too, and those - // come in on the m->g0 stack already. + // come in on the m->g0 stack already. Or we might already + // be on the m->gsignal stack. MOVV g_m(g), R5 MOVV m_gsignal(R5), R6 BEQ R6, g, g0 diff --git a/src/runtime/asm_mipsx.s b/src/runtime/asm_mipsx.s index 87a1344e8f..1b550719d1 100644 --- a/src/runtime/asm_mipsx.s +++ b/src/runtime/asm_mipsx.s @@ -413,8 +413,11 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-12 // Figure out if we need to switch to m->g0 stack. // We get called to create new OS threads too, and those - // come in on the m->g0 stack already. + // come in on the m->g0 stack already. Or we might already + // be on the m->gsignal stack. MOVW g_m(g), R5 + MOVW m_gsignal(R5), R6 + BEQ R6, g, g0 MOVW m_g0(R5), R6 BEQ R6, g, g0 diff --git a/src/runtime/asm_ppc64x.s b/src/runtime/asm_ppc64x.s index 5dc96c5947..7270abbdee 100644 --- a/src/runtime/asm_ppc64x.s +++ b/src/runtime/asm_ppc64x.s @@ -541,9 +541,8 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-20 // Figure out if we need to switch to m->g0 stack. // We get called to create new OS threads too, and those - // come in on the m->g0 stack already. - // Moreover, if it's called inside the signal handler, it must not switch - // to g0 as it can be in use by another syscall. + // come in on the m->g0 stack already. Or we might already + // be on the m->gsignal stack. MOVD g_m(g), R8 MOVD m_gsignal(R8), R6 CMP R6, g diff --git a/src/runtime/asm_riscv64.s b/src/runtime/asm_riscv64.s index 9927a817f7..d7ab90d1ab 100644 --- a/src/runtime/asm_riscv64.s +++ b/src/runtime/asm_riscv64.s @@ -310,8 +310,11 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-20 // Figure out if we need to switch to m->g0 stack. // We get called to create new OS threads too, and those - // come in on the m->g0 stack already. + // come in on the m->g0 stack already. Or we might already + // be on the m->gsignal stack. MOV g_m(g), X6 + MOV m_gsignal(X6), X7 + BEQ X7, g, g0 MOV m_g0(X6), X7 BEQ X7, g, g0 diff --git a/src/runtime/asm_s390x.s b/src/runtime/asm_s390x.s index d4110d563f..5894fe5783 100644 --- a/src/runtime/asm_s390x.s +++ b/src/runtime/asm_s390x.s @@ -513,12 +513,15 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-20 // Figure out if we need to switch to m->g0 stack. // We get called to create new OS threads too, and those - // come in on the m->g0 stack already. + // come in on the m->g0 stack already. Or we might already + // be on the m->gsignal stack. MOVD g_m(g), R6 - MOVD m_g0(R6), R6 - CMPBEQ R6, g, g0 + MOVD m_gsignal(R6), R7 + CMPBEQ R7, g, g0 + MOVD m_g0(R6), R7 + CMPBEQ R7, g, g0 BL gosave_systemstack_switch<>(SB) - MOVD R6, g + MOVD R7, g BL runtime·save_g(SB) MOVD (g_sched+gobuf_sp)(g), R15 -- GitLab From 3d679c6554d5b282154caa717567ad8353a8bc71 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Sun, 30 May 2021 01:46:19 +1000 Subject: [PATCH 0686/2500] syscall: use correct type for TIOCSPGRP/TIOCGPGRP These ioctls take a pid_t (generally a C integer aka int32) and not an int64 - we currently get away with this on little endian 64 bit platforms, since the bytes fall into the correct place, however this breaks on big endian 64 bit platforms (like openbsd/mips64). This is the same fix as CL 267605, however for libc based exec. Updates #36435 Change-Id: I01ae4905cba5e1f8725fa6cb8c35403c511534b2 Reviewed-on: https://go-review.googlesource.com/c/go/+/334881 Trust: Joel Sing Reviewed-by: Cherry Mui --- src/syscall/exec_libc2.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/syscall/exec_libc2.go b/src/syscall/exec_libc2.go index b999754c2e..bd98109d07 100644 --- a/src/syscall/exec_libc2.go +++ b/src/syscall/exec_libc2.go @@ -117,14 +117,15 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr } if sys.Foreground { - pgrp := sys.Pgid + // This should really be pid_t, however _C_int (aka int32) is + // generally equivalent. + pgrp := _C_int(sys.Pgid) if pgrp == 0 { r1, _, err1 = rawSyscall(abi.FuncPCABI0(libc_getpid_trampoline), 0, 0, 0) if err1 != 0 { goto childerror } - - pgrp = int(r1) + pgrp = _C_int(r1) } // Place process group in foreground. -- GitLab From 94002f6fcafb0e81ff9c5f12a28c21435534cb40 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sun, 15 Aug 2021 12:23:47 -0400 Subject: [PATCH 0687/2500] go/types: implement term lists This is a straightforward port of CL 339596 to go/types, differing only in the package declaration. Change-Id: If5bf8fd5667bee91b04fdb797702e6045d5fba7b Reviewed-on: https://go-review.googlesource.com/c/go/+/342330 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/termlist.go | 167 ++++++++++++++++++++ src/go/types/termlist_test.go | 278 ++++++++++++++++++++++++++++++++++ 2 files changed, 445 insertions(+) create mode 100644 src/go/types/termlist.go create mode 100644 src/go/types/termlist_test.go diff --git a/src/go/types/termlist.go b/src/go/types/termlist.go new file mode 100644 index 0000000000..1c534fc6a7 --- /dev/null +++ b/src/go/types/termlist.go @@ -0,0 +1,167 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +import "bytes" + +// A termlist represents the type set represented by the union +// t1 ∪ y2 ∪ ... tn of the type sets of the terms t1 to tn. +// A termlist is in normal form if all terms are disjoint. +// termlist operations don't require the operands to be in +// normal form. +type termlist []*term + +// topTermList represents the set of all types. +// It is in normal form. +var topTermlist = termlist{new(term)} + +// String prints the termlist exactly (without normalization). +func (xl termlist) String() string { + if len(xl) == 0 { + return "∅" + } + var buf bytes.Buffer + for i, x := range xl { + if i > 0 { + buf.WriteString(" ∪ ") + } + buf.WriteString(x.String()) + } + return buf.String() +} + +// isEmpty reports whether the termlist xl represents the empty set of types. +func (xl termlist) isEmpty() bool { + // If there's a non-nil term, the entire list is not empty. + // If the termlist is in normal form, this requires at most + // one iteration. + for _, x := range xl { + if x != nil { + return false + } + } + return true +} + +// isTop reports whether the termlist xl represents the set of all types. +func (xl termlist) isTop() bool { + // If there's a ⊤ (top) term, the entire list is ⊤ (top). + // If the termlist is in normal form, this requires at most + // one iteration. + for _, x := range xl { + if x != nil && x.typ == nil { + return true + } + } + return false +} + +// norm returns the normal form of xl. +func (xl termlist) norm() termlist { + // Quadratic algorithm, but good enough for now. + // TODO(gri) fix asymptotic performance + used := make([]bool, len(xl)) + var rl termlist + for i, xi := range xl { + if xi == nil || used[i] { + continue + } + for j := i + 1; j < len(xl); j++ { + xj := xl[j] + if xj == nil || used[j] { + continue + } + if u1, u2 := xi.union(xj); u2 == nil { + // If we encounter a ⊤ (top) term, the entire + // list is ⊤ (top). Exit early. + // (Note that this is not just an optimization; + // if we continue, we may end up with a ⊤ term + // and other terms and the result would not be + // in normal form.) + if u1.typ == nil { + return topTermlist + } + xi = u1 + used[j] = true // xj is now unioned into xi - ignore it in future iterations + } + } + rl = append(rl, xi) + } + return rl +} + +// If the type set represented by xl is specified by a single (non-⊤) term, +// structuralType returns that type. Otherwise it returns nil. +func (xl termlist) structuralType() Type { + if nl := xl.norm(); len(nl) == 1 { + return nl[0].typ // if nl.isTop() then typ is nil, which is ok + } + return nil +} + +// union returns the union xl ∪ yl. +func (xl termlist) union(yl termlist) termlist { + return append(xl, yl...).norm() +} + +// intersect returns the intersection xl ∩ yl. +func (xl termlist) intersect(yl termlist) termlist { + if xl.isEmpty() || yl.isEmpty() { + return nil + } + + // Quadratic algorithm, but good enough for now. + // TODO(gri) fix asymptotic performance + var rl termlist + for _, x := range xl { + for _, y := range yl { + if r := x.intersect(y); r != nil { + rl = append(rl, r) + } + } + } + return rl.norm() +} + +// equal reports whether xl and yl represent the same type set. +func (xl termlist) equal(yl termlist) bool { + // TODO(gri) this should be more efficient + return xl.subsetOf(yl) && yl.subsetOf(xl) +} + +// includes reports whether t ∈ xl. +func (xl termlist) includes(t Type) bool { + for _, x := range xl { + if x.includes(t) { + return true + } + } + return false +} + +// supersetOf reports whether y ⊆ xl. +func (xl termlist) supersetOf(y *term) bool { + for _, x := range xl { + if y.subsetOf(x) { + return true + } + } + return false +} + +// subsetOf reports whether xl ⊆ yl. +func (xl termlist) subsetOf(yl termlist) bool { + if yl.isEmpty() { + return xl.isEmpty() + } + + // each term x of xl must be a subset of yl + for _, x := range xl { + if !yl.supersetOf(x) { + return false // x is not a subset yl + } + } + return true +} diff --git a/src/go/types/termlist_test.go b/src/go/types/termlist_test.go new file mode 100644 index 0000000000..eeb820dfd2 --- /dev/null +++ b/src/go/types/termlist_test.go @@ -0,0 +1,278 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +import ( + "strings" + "testing" +) + +// maketl makes a term list from a string of the term list. +func maketl(s string) termlist { + s = strings.Replace(s, " ", "", -1) + names := strings.Split(s, "∪") + r := make(termlist, len(names)) + for i, n := range names { + r[i] = testTerm(n) + } + return r +} + +func TestTermlistTop(t *testing.T) { + if !topTermlist.isTop() { + t.Errorf("topTermlist is not top") + } +} + +func TestTermlistString(t *testing.T) { + for _, want := range []string{ + "∅", + "⊤", + "int", + "~int", + "∅ ∪ ∅", + "⊤ ∪ ⊤", + "∅ ∪ ⊤ ∪ int", + } { + if got := maketl(want).String(); got != want { + t.Errorf("(%v).String() == %v", want, got) + } + } +} + +func TestTermlistIsEmpty(t *testing.T) { + for test, want := range map[string]bool{ + "∅": true, + "∅ ∪ ∅": true, + "∅ ∪ ∅ ∪ ⊤": false, + "⊤": false, + "⊤ ∪ int": false, + } { + xl := maketl(test) + got := xl.isEmpty() + if got != want { + t.Errorf("(%v).isEmpty() == %v; want %v", test, got, want) + } + } +} + +func TestTermlistIsTop(t *testing.T) { + for test, want := range map[string]bool{ + "∅": false, + "∅ ∪ ∅": false, + "int ∪ ~string": false, + "∅ ∪ ∅ ∪ ⊤": true, + "⊤": true, + "⊤ ∪ int": true, + } { + xl := maketl(test) + got := xl.isTop() + if got != want { + t.Errorf("(%v).isTop() == %v; want %v", test, got, want) + } + } +} + +func TestTermlistNorm(t *testing.T) { + for _, test := range []struct { + xl, want string + }{ + {"∅", "∅"}, + {"∅ ∪ ∅", "∅"}, + {"∅ ∪ int", "int"}, + {"⊤ ∪ int", "⊤"}, + {"~int ∪ int", "~int"}, + {"int ∪ ~string ∪ int", "int ∪ ~string"}, + {"~int ∪ string ∪ ⊤ ∪ ~string ∪ int", "⊤"}, + } { + xl := maketl(test.xl) + got := maketl(test.xl).norm() + if got.String() != test.want { + t.Errorf("(%v).norm() = %v; want %v", xl, got, test.want) + } + } +} + +func TestTermlistStructuralType(t *testing.T) { + // helper to deal with nil types + tstring := func(typ Type) string { + if typ == nil { + return "nil" + } + return typ.String() + } + + for test, want := range map[string]string{ + "∅": "nil", + "⊤": "nil", + "int": "int", + "~int": "int", + "~int ∪ string": "nil", + "∅ ∪ int": "int", + "∅ ∪ ~int": "int", + "∅ ∪ ~int ∪ string": "nil", + } { + xl := maketl(test) + got := tstring(xl.structuralType()) + if got != want { + t.Errorf("(%v).structuralType() == %v; want %v", test, got, want) + } + } +} + +func TestTermlistUnion(t *testing.T) { + for _, test := range []struct { + xl, yl, want string + }{ + + {"∅", "∅", "∅"}, + {"∅", "⊤", "⊤"}, + {"∅", "int", "int"}, + {"⊤", "~int", "⊤"}, + {"int", "~int", "~int"}, + {"int", "string", "int ∪ string"}, + {"int ∪ string", "~string", "int ∪ ~string"}, + {"~int ∪ string", "~string ∪ int", "~int ∪ ~string"}, + {"~int ∪ string ∪ ∅", "~string ∪ int", "~int ∪ ~string"}, + {"~int ∪ string ∪ ⊤", "~string ∪ int", "⊤"}, + } { + xl := maketl(test.xl) + yl := maketl(test.yl) + got := xl.union(yl).String() + if got != test.want { + t.Errorf("(%v).union(%v) = %v; want %v", test.xl, test.yl, got, test.want) + } + } +} + +func TestTermlistIntersect(t *testing.T) { + for _, test := range []struct { + xl, yl, want string + }{ + + {"∅", "∅", "∅"}, + {"∅", "⊤", "∅"}, + {"∅", "int", "∅"}, + {"⊤", "~int", "~int"}, + {"int", "~int", "int"}, + {"int", "string", "∅"}, + {"int ∪ string", "~string", "string"}, + {"~int ∪ string", "~string ∪ int", "int ∪ string"}, + {"~int ∪ string ∪ ∅", "~string ∪ int", "int ∪ string"}, + {"~int ∪ string ∪ ⊤", "~string ∪ int", "int ∪ ~string"}, + } { + xl := maketl(test.xl) + yl := maketl(test.yl) + got := xl.intersect(yl).String() + if got != test.want { + t.Errorf("(%v).intersect(%v) = %v; want %v", test.xl, test.yl, got, test.want) + } + } +} + +func TestTermlistEqual(t *testing.T) { + for _, test := range []struct { + xl, yl string + want bool + }{ + {"∅", "∅", true}, + {"∅", "⊤", false}, + {"⊤", "⊤", true}, + {"⊤ ∪ int", "⊤", true}, + {"⊤ ∪ int", "string ∪ ⊤", true}, + {"int ∪ ~string", "string ∪ int", false}, + {"int ∪ ~string ∪ ∅", "string ∪ int ∪ ~string", true}, + } { + xl := maketl(test.xl) + yl := maketl(test.yl) + got := xl.equal(yl) + if got != test.want { + t.Errorf("(%v).equal(%v) = %v; want %v", test.xl, test.yl, got, test.want) + } + } +} + +func TestTermlistIncludes(t *testing.T) { + for _, test := range []struct { + xl, typ string + want bool + }{ + {"∅", "int", false}, + {"⊤", "int", true}, + {"~int", "int", true}, + {"int", "string", false}, + {"~int", "string", false}, + {"int ∪ string", "string", true}, + {"~int ∪ string", "int", true}, + {"~int ∪ string ∪ ∅", "string", true}, + {"~string ∪ ∅ ∪ ⊤", "int", true}, + } { + xl := maketl(test.xl) + yl := testTerm(test.typ).typ + got := xl.includes(yl) + if got != test.want { + t.Errorf("(%v).includes(%v) = %v; want %v", test.xl, yl, got, test.want) + } + } +} + +func TestTermlistSupersetOf(t *testing.T) { + for _, test := range []struct { + xl, typ string + want bool + }{ + {"∅", "∅", true}, + {"∅", "⊤", false}, + {"∅", "int", false}, + {"⊤", "∅", true}, + {"⊤", "⊤", true}, + {"⊤", "int", true}, + {"⊤", "~int", true}, + {"~int", "int", true}, + {"~int", "~int", true}, + {"int", "~int", false}, + {"int", "string", false}, + {"~int", "string", false}, + {"int ∪ string", "string", true}, + {"int ∪ string", "~string", false}, + {"~int ∪ string", "int", true}, + {"~int ∪ string ∪ ∅", "string", true}, + {"~string ∪ ∅ ∪ ⊤", "int", true}, + } { + xl := maketl(test.xl) + y := testTerm(test.typ) + got := xl.supersetOf(y) + if got != test.want { + t.Errorf("(%v).supersetOf(%v) = %v; want %v", test.xl, y, got, test.want) + } + } +} + +func TestTermlistSubsetOf(t *testing.T) { + for _, test := range []struct { + xl, yl string + want bool + }{ + {"∅", "∅", true}, + {"∅", "⊤", true}, + {"⊤", "∅", false}, + {"⊤", "⊤", true}, + {"int", "int ∪ string", true}, + {"~int", "int ∪ string", false}, + {"~int", "string ∪ string ∪ int ∪ ~int", true}, + {"int ∪ string", "string", false}, + {"int ∪ string", "string ∪ int", true}, + {"int ∪ ~string", "string ∪ int", false}, + {"int ∪ ~string", "string ∪ int ∪ ⊤", true}, + {"int ∪ ~string", "string ∪ int ∪ ∅ ∪ string", false}, + } { + xl := maketl(test.xl) + yl := maketl(test.yl) + got := xl.subsetOf(yl) + if got != test.want { + t.Errorf("(%v).subsetOf(%v) = %v; want %v", test.xl, test.yl, got, test.want) + } + } +} -- GitLab From d043c8ea89d27d2bcb05276b54dc9d5894e8fc2a Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sun, 15 Aug 2021 15:28:22 -0400 Subject: [PATCH 0688/2500] go/types: implement type sets with term lists This is a port of CL 338310 to go/types. It is superficially adjusted for different error reporting and AST APIs. It also fixes a bug in CL 338310 that only manifests in go/types (TestFixedbugs/issue39755.go2) due to go/types preserving untyped nil. In that CL, operand.go is checking if optype is a TypeParam, which can never be the case. A fix for types2 will be mailed in a separate CL. Change-Id: Icf3394e74baec536842267d99f7511d25ab32a8a Reviewed-on: https://go-review.googlesource.com/c/go/+/342331 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/builtins.go | 16 +- src/go/types/infer.go | 37 +--- src/go/types/instantiate.go | 24 +- src/go/types/interface.go | 34 +-- src/go/types/operand.go | 2 +- src/go/types/predicates.go | 12 +- src/go/types/sizeof_test.go | 4 +- src/go/types/stmt.go | 3 +- src/go/types/subst.go | 12 +- src/go/types/termlist.go | 2 +- src/go/types/testdata/check/tinference.go2 | 2 +- src/go/types/testdata/check/typeinst2.go2 | 8 +- src/go/types/testdata/check/typeparams.go2 | 65 +++--- .../types/testdata/examples/constraints.go2 | 41 +++- .../types/testdata/fixedbugs/issue41124.go2 | 10 +- src/go/types/type.go | 21 +- src/go/types/typeparam.go | 27 ++- src/go/types/typeset.go | 171 ++++++++++----- src/go/types/typestring.go | 25 ++- src/go/types/typexpr.go | 21 +- src/go/types/unify.go | 5 +- src/go/types/union.go | 205 ++++-------------- src/go/types/universe.go | 4 +- 23 files changed, 333 insertions(+), 418 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index c73d94658a..8a3fc14fea 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -145,7 +145,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b mode := invalid var typ Type var val constant.Value - switch typ = implicitArrayDeref(optype(x.typ)); t := typ.(type) { + switch typ = implicitArrayDeref(under(x.typ)); t := typ.(type) { case *Basic: if isString(t) && id == _Len { if x.mode == constant_ { @@ -179,9 +179,9 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b mode = value } - case *Union: + case *TypeParam: if t.underIs(func(t Type) bool { - switch t := t.(type) { + switch t := implicitArrayDeref(t).(type) { case *Basic: if isString(t) && id == _Len { return true @@ -826,10 +826,10 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { // type and collect possible result types at the same time. var rtypes []Type var tildes []bool - if !tp.iface().is(func(typ Type, tilde bool) bool { - if r := f(typ); r != nil { + if !tp.iface().typeSet().is(func(t *term) bool { + if r := f(t.typ); r != nil { rtypes = append(rtypes, r) - tildes = append(tildes, tilde) + tildes = append(tildes, t.tilde) return true } return false @@ -841,10 +841,8 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { // type param is placed in the current package so export/import // works as expected. tpar := NewTypeName(token.NoPos, check.pkg, "", nil) - ptyp := check.NewTypeParam(tpar, &emptyInterface) // assigns type to tpar as a side-effect + ptyp := check.NewTypeParam(tpar, NewInterfaceType(nil, []Type{newUnion(rtypes, tildes)})) // assigns type to tpar as a side-effect ptyp.index = tp.index - tsum := newUnion(rtypes, tildes) - ptyp.bound = &Interface{complete: true, tset: &_TypeSet{types: tsum}} return ptyp } diff --git a/src/go/types/infer.go b/src/go/types/infer.go index 6e70a103e7..eb0d75e46f 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -275,7 +275,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { }() switch t := typ.(type) { - case nil, *Basic: // TODO(gri) should nil be handled here? + case nil, *top, *Basic: // TODO(gri) should nil be handled here? break case *Array: @@ -302,9 +302,6 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { } } - case *Union: - return w.isParameterizedTermList(t.terms) - case *Signature: // t.tparams may not be nil if we are looking at a signature // of a generic function type (or an interface method) that is @@ -322,7 +319,9 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { return true } } - return w.isParameterized(tset.types) + return tset.is(func(t *term) bool { + return w.isParameterized(t.typ) + }) case *Map: return w.isParameterized(t.key) || w.isParameterized(t.elem) @@ -353,15 +352,6 @@ func (w *tpWalker) isParameterizedTypeList(list []Type) bool { return false } -func (w *tpWalker) isParameterizedTermList(list []*term) bool { - for _, t := range list { - if w.isParameterized(t.typ) { - return true - } - } - return false -} - // inferB returns the list of actual type arguments inferred from the type parameters' // bounds and an initial set of type arguments. If type inference is impossible because // unification fails, an error is reported if report is set to true, the resulting types @@ -389,7 +379,7 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty // Unify type parameters with their structural constraints, if any. for _, tpar := range tparams { typ := tpar.typ.(*TypeParam) - sbound := check.structuralType(typ.bound) + sbound := typ.structuralType() if sbound != nil { if !u.unify(typ, sbound) { if report { @@ -462,20 +452,3 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty return } - -// structuralType returns the structural type of a constraint, if any. -func (check *Checker) structuralType(constraint Type) Type { - if iface, _ := under(constraint).(*Interface); iface != nil { - types := iface.typeSet().types - if u, _ := types.(*Union); u != nil { - if u.NumTerms() == 1 { - // TODO(gri) do we need to respect tilde? - t, _ := u.Term(0) - return t - } - return nil - } - return types - } - return nil -} diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 6d56eb7ea2..6f10feb206 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -215,7 +215,7 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap } // targ's underlying type must also be one of the interface types listed, if any - if iface.typeSet().types == nil { + if !iface.typeSet().hasTerms() { return true // nothing to do } @@ -223,24 +223,22 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap // list of iface types (i.e., the targ type list must be a non-empty subset of the iface types). if targ := asTypeParam(targ); targ != nil { targBound := targ.iface() - if targBound.typeSet().types == nil { + if !targBound.typeSet().hasTerms() { check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ) return false } - return iface.is(func(typ Type, tilde bool) bool { - // TODO(gri) incorporate tilde information! - if !iface.isSatisfiedBy(typ) { - // TODO(gri) match this error message with the one below (or vice versa) - check.softErrorf(atPos(pos), 0, "%s does not satisfy %s (%s type constraint %s not found in %s)", targ, tpar.bound, targ, typ, iface.typeSet().types) - return false - } - return true - }) + if !targBound.typeSet().subsetOf(iface.typeSet()) { + // TODO(gri) need better error message + check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s", targ, tpar.bound) + return false + } + return true } // Otherwise, targ's type or underlying type must also be one of the interface types listed, if any. - if !iface.isSatisfiedBy(targ) { - check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s not found in %s)", targ, tpar.bound, targ, iface.typeSet().types) + if !iface.typeSet().includes(targ) { + // TODO(gri) better error message + check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s", targ, tpar.bound) return false } diff --git a/src/go/types/interface.go b/src/go/types/interface.go index d8f9671857..a5d19e8265 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -25,20 +25,7 @@ type Interface struct { } // typeSet returns the type set for interface t. -func (t *Interface) typeSet() *_TypeSet { return computeTypeSet(nil, token.NoPos, t) } - -// is reports whether interface t represents types that all satisfy f. -func (t *Interface) is(f func(Type, bool) bool) bool { - switch t := t.typeSet().types.(type) { - case nil, *top: - // TODO(gri) should settle on top or nil to represent this case - return false // we must have at least one type! (was bug) - case *Union: - return t.is(func(t *term) bool { return f(t.typ, t.tilde) }) - default: - return f(t, false) - } -} +func (t *Interface) typeSet() *_TypeSet { return computeInterfaceTypeSet(nil, token.NoPos, t) } // emptyInterface represents the empty (completed) interface var emptyInterface = Interface{complete: true, tset: &topTypeSet} @@ -117,23 +104,6 @@ func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() } // IsConstraint reports whether interface t is not just a method set. func (t *Interface) IsConstraint() bool { return !t.typeSet().IsMethodSet() } -// isSatisfiedBy reports whether interface t's type list is satisfied by the type typ. -// If the type list is empty (absent), typ trivially satisfies the interface. -// TODO(gri) This is not a great name. Eventually, we should have a more comprehensive -// "implements" predicate. -func (t *Interface) isSatisfiedBy(typ Type) bool { - t.Complete() - switch t := t.typeSet().types.(type) { - case nil: - return true // no type restrictions - case *Union: - r, _ := t.intersect(typ, false) - return r != nil - default: - return Identical(t, typ) - } -} - // Complete computes the interface's type set. It must be called by users of // NewInterfaceType and NewInterface after the interface's embedded types are // fully defined and before using the interface type in any way other than to @@ -268,7 +238,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d // Compute type set with a non-nil *Checker as soon as possible // to report any errors. Subsequent uses of type sets will use // this computed type set and won't need to pass in a *Checker. - check.later(func() { computeTypeSet(check, iface.Pos(), ityp) }) + check.later(func() { computeInterfaceTypeSet(check, iface.Pos(), ityp) }) } func flattenUnion(list []ast.Expr, x ast.Expr) []ast.Expr { diff --git a/src/go/types/operand.go b/src/go/types/operand.go index aea8bf5e7a..a54802defc 100644 --- a/src/go/types/operand.go +++ b/src/go/types/operand.go @@ -258,7 +258,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er // x is an untyped value representable by a value of type T. if isUntyped(Vu) { - if t, ok := Tu.(*Union); ok { + if t, _ := under(T).(*TypeParam); t != nil { return t.is(func(t *term) bool { // TODO(gri) this could probably be more efficient if t.tilde { diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 23924693fd..5a2c08322f 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -229,16 +229,6 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { identical(x.results, y.results, cmpTags, p) } - case *Union: - // Two union types are identical if they contain the same terms. - // The set (list) of types in a union type consists of unique - // types - each type appears exactly once. Thus, two union types - // must contain the same number of types to have chance of - // being equal. - if y, ok := y.(*Union); ok { - return identicalTerms(x.terms, y.terms) - } - case *Interface: // Two interface types are identical if they describe the same type sets. // With the existing implementation restriction, this simplifies to: @@ -250,7 +240,7 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { if y, ok := y.(*Interface); ok { xset := x.typeSet() yset := y.typeSet() - if !Identical(xset.types, yset.types) { + if !xset.terms.equal(yset.terms) { return false } a := xset.methods diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index 67a9b39558..403f2bbece 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -26,7 +26,7 @@ func TestSizeof(t *testing.T) { {Pointer{}, 8, 16}, {Tuple{}, 12, 24}, {Signature{}, 28, 56}, - {Union{}, 12, 24}, + {Union{}, 16, 32}, {Interface{}, 40, 80}, {Map{}, 16, 32}, {Chan{}, 12, 24}, @@ -48,7 +48,7 @@ func TestSizeof(t *testing.T) { // Misc {Scope{}, 44, 88}, {Package{}, 40, 80}, - {_TypeSet{}, 24, 48}, + {_TypeSet{}, 28, 56}, } for _, test := range tests { got := reflect.TypeOf(test.val).Size() diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index 0f0a2e4d9f..4c545efcf9 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -917,10 +917,11 @@ func rangeKeyVal(typ Type, wantKey, wantVal bool) (Type, Type, string) { case *Chan: var msg string if typ.dir == SendOnly { + // TODO(rfindley): this error message differs from types2. Reconcile this. msg = "send-only channel" } return typ.elem, Typ[Invalid], msg - case *Union: + case *TypeParam: first := true var key, val Type var msg string diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 322e30d357..a43c5b9f0b 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -148,12 +148,12 @@ func (subst *subster) typ(typ Type) Type { } case *Union: - terms, copied := subst.termList(t.terms) + terms, copied := subst.termlist(t.terms) if copied { - // TODO(gri) Remove duplicates that may have crept in after substitution - // (unlikely but possible). This matters for the Identical - // predicate on unions. - return &Union{terms} + // term list substitution may introduce duplicate terms (unlikely but possible). + // This is ok; lazy type set computation will determine the actual type set + // in normal form. + return &Union{terms, nil} } case *Interface: @@ -394,7 +394,7 @@ func (subst *subster) typeList(in []Type) (out []Type, copied bool) { return } -func (subst *subster) termList(in []*term) (out []*term, copied bool) { +func (subst *subster) termlist(in []*term) (out []*term, copied bool) { out = in for i, t := range in { if u := subst.typ(t.typ); u != t.typ { diff --git a/src/go/types/termlist.go b/src/go/types/termlist.go index 1c534fc6a7..044c6a9466 100644 --- a/src/go/types/termlist.go +++ b/src/go/types/termlist.go @@ -13,7 +13,7 @@ import "bytes" // normal form. type termlist []*term -// topTermList represents the set of all types. +// topTermlist represents the set of all types. // It is in normal form. var topTermlist = termlist{new(term)} diff --git a/src/go/types/testdata/check/tinference.go2 b/src/go/types/testdata/check/tinference.go2 index 44e8dc0059..aa9a054682 100644 --- a/src/go/types/testdata/check/tinference.go2 +++ b/src/go/types/testdata/check/tinference.go2 @@ -92,7 +92,7 @@ func FromStrings[T interface{}, PT Setter[T]](s []string) []T { result := make([]T, len(s)) for i, v := range s { // The type of &result[i] is *T which is in the type list - // of Setter2, so we can convert it to PT. + // of Setter, so we can convert it to PT. p := PT(&result[i]) // PT has a Set method. p.Set(v) diff --git a/src/go/types/testdata/check/typeinst2.go2 b/src/go/types/testdata/check/typeinst2.go2 index ab56ccafc9..f8369c31dd 100644 --- a/src/go/types/testdata/check/typeinst2.go2 +++ b/src/go/types/testdata/check/typeinst2.go2 @@ -164,13 +164,13 @@ type _ interface { // for them to be all in a single list, and we report the error // as well.) type _ interface { - ~int|~ /* ERROR duplicate term int */ int - ~int|int /* ERROR duplicate term int */ - int|int /* ERROR duplicate term int */ + ~int|~ /* ERROR overlapping terms ~int */ int + ~int|int /* ERROR overlapping terms int */ + int|int /* ERROR overlapping terms int */ } type _ interface { - ~struct{f int} | ~struct{g int} | ~ /* ERROR duplicate term */ struct{f int} + ~struct{f int} | ~struct{g int} | ~ /* ERROR overlapping terms */ struct {f int} } // Interface type lists can contain any type, incl. *Named types. diff --git a/src/go/types/testdata/check/typeparams.go2 b/src/go/types/testdata/check/typeparams.go2 index 77cd65d19a..7ed0a5e847 100644 --- a/src/go/types/testdata/check/typeparams.go2 +++ b/src/go/types/testdata/check/typeparams.go2 @@ -149,37 +149,40 @@ func _[T interface{}](x T) { for range x /* ERROR cannot range */ {} } -func _[T interface{ ~string | ~[]string }](x T) { - for range x {} - for i := range x { _ = i } - for i, _ := range x { _ = i } - for i, e := range x /* ERROR must have the same element type */ { _ = i } - for _, e := range x /* ERROR must have the same element type */ {} - var e rune - _ = e - for _, (e) = range x /* ERROR must have the same element type */ {} -} - - -func _[T interface{ ~string | ~[]rune | ~map[int]rune }](x T) { - for _, e := range x { _ = e } - for i, e := range x { _ = i; _ = e } -} - -func _[T interface{ ~string | ~[]rune | ~map[string]rune }](x T) { - for _, e := range x { _ = e } - for i, e := range x /* ERROR must have the same key type */ { _ = e } -} - -func _[T interface{ ~string | ~chan int }](x T) { - for range x {} - for i := range x { _ = i } - for i, _ := range x { _ = i } // TODO(gri) should get an error here: channels only return one value -} - -func _[T interface{ ~string | ~chan<-int }](x T) { - for i := range x /* ERROR send-only channel */ { _ = i } -} +// Disabled for now until we have clarified semantics of range. +// TODO(gri) fix this +// +// func _[T interface{ ~string | ~[]string }](x T) { +// for range x {} +// for i := range x { _ = i } +// for i, _ := range x { _ = i } +// for i, e := range x /* ERROR must have the same element type */ { _ = i } +// for _, e := range x /* ERROR must have the same element type */ {} +// var e rune +// _ = e +// for _, (e) = range x /* ERROR must have the same element type */ {} +// } +// +// +// func _[T interface{ ~string | ~[]rune | ~map[int]rune }](x T) { +// for _, e := range x { _ = e } +// for i, e := range x { _ = i; _ = e } +// } +// +// func _[T interface{ ~string | ~[]rune | ~map[string]rune }](x T) { +// for _, e := range x { _ = e } +// for i, e := range x /* ERROR must have the same key type */ { _ = e } +// } +// +// func _[T interface{ ~string | ~chan int }](x T) { +// for range x {} +// for i := range x { _ = i } +// for i, _ := range x { _ = i } // TODO(gri) should get an error here: channels only return one value +// } +// +// func _[T interface{ ~string | ~chan<-int }](x T) { +// for i := range x /* ERROR send-only channel */ { _ = i } +// } // type inference checks diff --git a/src/go/types/testdata/examples/constraints.go2 b/src/go/types/testdata/examples/constraints.go2 index 28aa19bb12..f40d18c63e 100644 --- a/src/go/types/testdata/examples/constraints.go2 +++ b/src/go/types/testdata/examples/constraints.go2 @@ -18,18 +18,25 @@ type ( } ) +type MyInt int + type ( // Arbitrary types may be embedded like interfaces. _ interface{int} _ interface{~int} // Types may be combined into a union. - _ interface{int|~string} + union interface{int|~string} - // Union terms must be unique independent of whether they are ~ or not. - _ interface{int|int /* ERROR duplicate term int */ } - _ interface{int|~ /* ERROR duplicate term int */ int } - _ interface{~int|~ /* ERROR duplicate term int */ int } + // Union terms must describe disjoint (non-overlapping) type sets. + _ interface{int|int /* ERROR overlapping terms int */ } + _ interface{int|~ /* ERROR overlapping terms ~int */ int } + _ interface{~int|~ /* ERROR overlapping terms ~int */ int } + _ interface{~int|MyInt /* ERROR overlapping terms p.MyInt and ~int */ } + _ interface{int|interface{}} + _ interface{int|~string|union} + _ interface{int|~string|interface{int}} + _ interface{union|union /* ERROR overlapping terms p.union and p.union */ } // For now we do not permit interfaces with methods in unions. _ interface{~ /* ERROR invalid use of ~ */ interface{}} @@ -45,6 +52,15 @@ type ( _ interface{~ /* ERROR invalid use of ~ */ bar } ) +// Stand-alone type parameters are not permitted as elements or terms in unions. +type ( + _[T interface{ *T } ] struct{} // ok + _[T interface{ int | *T } ] struct{} // ok + _[T interface{ T /* ERROR cannot embed a type parameter */ } ] struct{} + _[T interface{ ~T /* ERROR cannot embed a type parameter */ } ] struct{} + _[T interface{ int|T /* ERROR cannot embed a type parameter */ }] struct{} +) + // Multiple embedded union elements are intersected. The order in which they // appear in the interface doesn't matter since intersection is a symmetric // operation. @@ -58,3 +74,18 @@ func _[T interface{ ~int; myInt1|myInt2 }]() T { return T(0) } // Here the intersections are empty - there's no type that's in the type set of T. func _[T interface{ myInt1|myInt2; int }]() T { return T(0 /* ERROR cannot convert */ ) } func _[T interface{ int; myInt1|myInt2 }]() T { return T(0 /* ERROR cannot convert */ ) } + +// Union elements may be interfaces as long as they don't define +// any methods or embed comparable. + +type ( + Integer interface{ ~int|~int8|~int16|~int32|~int64 } + Unsigned interface{ ~uint|~uint8|~uint16|~uint32|~uint64 } + Floats interface{ ~float32|~float64 } + Complex interface{ ~complex64|~complex128 } + Number interface{ Integer|Unsigned|Floats|Complex } + Ordered interface{ Integer|Unsigned|Floats|~string } + + _ interface{ Number | error /* ERROR cannot use error in union */ } + _ interface{ Ordered | comparable /* ERROR cannot use comparable in union */ } +) diff --git a/src/go/types/testdata/fixedbugs/issue41124.go2 b/src/go/types/testdata/fixedbugs/issue41124.go2 index ab535049dd..60650432a4 100644 --- a/src/go/types/testdata/fixedbugs/issue41124.go2 +++ b/src/go/types/testdata/fixedbugs/issue41124.go2 @@ -47,7 +47,7 @@ type _ struct{ } type _ struct{ - I3 // ERROR interface contains type constraints + I3 // ERROR interface is .* comparable } // General composite types. @@ -59,19 +59,19 @@ type ( _ []I1 // ERROR interface is .* comparable _ []I2 // ERROR interface contains type constraints - _ *I3 // ERROR interface contains type constraints + _ *I3 // ERROR interface is .* comparable _ map[I1 /* ERROR interface is .* comparable */ ]I2 // ERROR interface contains type constraints - _ chan I3 // ERROR interface contains type constraints + _ chan I3 // ERROR interface is .* comparable _ func(I1 /* ERROR interface is .* comparable */ ) _ func() I2 // ERROR interface contains type constraints ) // Other cases. -var _ = [...]I3 /* ERROR interface contains type constraints */ {} +var _ = [...]I3 /* ERROR interface is .* comparable */ {} func _(x interface{}) { - _ = x.(I3 /* ERROR interface contains type constraints */ ) + _ = x.(I3 /* ERROR interface is .* comparable */ ) } type T1[_ any] struct{} diff --git a/src/go/types/type.go b/src/go/types/type.go index 5819dd290c..c042a819b8 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -44,28 +44,21 @@ func under(t Type) Type { // optype returns a type's operational type. Except for // type parameters, the operational type is the same // as the underlying type (as returned by under). For -// Type parameters, the operational type is determined -// by the corresponding type bound's type list. The -// result may be the bottom or top type, but it is never -// the incoming type parameter. +// Type parameters, the operational type is the structural +// type, if any; otherwise it's the top type. +// The result is never the incoming type parameter. func optype(typ Type) Type { if t := asTypeParam(typ); t != nil { + // TODO(gri) review accuracy of this comment // If the optype is typ, return the top type as we have // no information. It also prevents infinite recursion // via the asTypeParam converter function. This can happen // for a type parameter list of the form: // (type T interface { type T }). // See also issue #39680. - if a := t.iface().typeSet().types; a != nil && a != typ { - // If we have a union with a single entry, ignore - // any tilde because under(~t) == under(t). - if u, _ := a.(*Union); u != nil && u.NumTerms() == 1 { - a, _ = u.Term(0) - } - if a != typ { - // a != typ and a is a type parameter => under(a) != typ, so this is ok - return under(a) - } + if u := t.structuralType(); u != nil { + assert(u != typ) // "naked" type parameters cannot be embedded + return u } return theTop } diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index 33a516c209..cf80eaab38 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -69,7 +69,7 @@ func (t *TypeParam) Constraint() Type { if n, _ := t.bound.(*Named); n != nil { pos = n.obj.pos } - computeTypeSet(t.check, pos, iface) + computeInterfaceTypeSet(t.check, pos, iface) } return t.bound } @@ -82,14 +82,6 @@ func (t *TypeParam) SetConstraint(bound Type) { t.bound = bound } -// iface returns the constraint interface of t. -func (t *TypeParam) iface() *Interface { - if iface, _ := under(t.Constraint()).(*Interface); iface != nil { - return iface - } - return &emptyInterface -} - func (t *TypeParam) Underlying() Type { return t } func (t *TypeParam) String() string { return TypeString(t, nil) } @@ -131,6 +123,23 @@ func bindTParams(list []*TypeName) *TypeParams { // ---------------------------------------------------------------------------- // Implementation +// iface returns the constraint interface of t. +func (t *TypeParam) iface() *Interface { + if iface, _ := under(t.Constraint()).(*Interface); iface != nil { + return iface + } + return &emptyInterface +} + +// structuralType returns the structural type of the type parameter's constraint; or nil. +func (t *TypeParam) structuralType() Type { + return t.iface().typeSet().structuralType() +} + +func (t *TypeParam) is(f func(*term) bool) bool { + return t.iface().typeSet().is(f) +} + func (t *TypeParam) underIs(f func(Type) bool) bool { return t.iface().typeSet().underIs(f) } diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index 836f93047a..3caba05202 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -18,32 +18,32 @@ import ( type _TypeSet struct { comparable bool // if set, the interface is or embeds comparable // TODO(gri) consider using a set for the methods for faster lookup - methods []*Func // all methods of the interface; sorted by unique ID - types Type // typically a *Union; nil means no type restrictions + methods []*Func // all methods of the interface; sorted by unique ID + terms termlist // type terms of the type set } -// IsTop reports whether type set s is the top type set (corresponding to the empty interface). -func (s *_TypeSet) IsTop() bool { return !s.comparable && len(s.methods) == 0 && s.types == nil } +// IsEmpty reports whether type set s is the empty set. +func (s *_TypeSet) IsEmpty() bool { return s.terms.isEmpty() } + +// IsTop reports whether type set s is the set of all types (corresponding to the empty interface). +func (s *_TypeSet) IsTop() bool { return !s.comparable && len(s.methods) == 0 && s.terms.isTop() } + +// TODO(gri) IsMethodSet is not a great name for this predicate. Find a better one. // IsMethodSet reports whether the type set s is described by a single set of methods. -func (s *_TypeSet) IsMethodSet() bool { return !s.comparable && s.types == nil } +func (s *_TypeSet) IsMethodSet() bool { return !s.comparable && s.terms.isTop() } // IsComparable reports whether each type in the set is comparable. -// TODO(gri) this is not correct - there may be s.types values containing non-comparable types func (s *_TypeSet) IsComparable() bool { - if s.types == nil { + if s.terms.isTop() { return s.comparable } - tcomparable := s.underIs(func(u Type) bool { - return Comparable(u) + return s.is(func(t *term) bool { + return Comparable(t.typ) }) - if !s.comparable { - return tcomparable - } - return s.comparable && tcomparable } -// TODO(gri) IsTypeSet is not a great name. Find a better one. +// TODO(gri) IsTypeSet is not a great name for this predicate. Find a better one. // IsTypeSet reports whether the type set s is represented by a finite set of underlying types. func (s *_TypeSet) IsTypeSet() bool { @@ -64,15 +64,21 @@ func (s *_TypeSet) LookupMethod(pkg *Package, name string) (int, *Func) { } func (s *_TypeSet) String() string { - if s.IsTop() { + switch { + case s.IsEmpty(): + return "∅" + case s.IsTop(): return "⊤" } + hasMethods := len(s.methods) > 0 + hasTerms := s.hasTerms() + var buf bytes.Buffer buf.WriteByte('{') if s.comparable { buf.WriteString(" comparable") - if len(s.methods) > 0 || s.types != nil { + if hasMethods || hasTerms { buf.WriteByte(';') } } @@ -83,41 +89,77 @@ func (s *_TypeSet) String() string { buf.WriteByte(' ') buf.WriteString(m.String()) } - if len(s.methods) > 0 && s.types != nil { + if hasMethods && hasTerms { buf.WriteByte(';') } - if s.types != nil { - buf.WriteByte(' ') - writeType(&buf, s.types, nil, nil) + if hasTerms { + buf.WriteString(s.terms.String()) } + buf.WriteString(" }") // there was at least one method or term - buf.WriteString(" }") // there was a least one method or type return buf.String() } // ---------------------------------------------------------------------------- // Implementation -// underIs reports whether f returned true for the underlying types of the -// enumerable types in the type set s. If the type set comprises all types -// f is called once with the top type; if the type set is empty, the result -// is false. +func (s *_TypeSet) hasTerms() bool { return !s.terms.isTop() } +func (s *_TypeSet) structuralType() Type { return s.terms.structuralType() } +func (s *_TypeSet) includes(t Type) bool { return s.terms.includes(t) } +func (s1 *_TypeSet) subsetOf(s2 *_TypeSet) bool { return s1.terms.subsetOf(s2.terms) } + +// TODO(gri) TypeSet.is and TypeSet.underIs should probably also go into termlist.go + +var topTerm = term{false, theTop} + +func (s *_TypeSet) is(f func(*term) bool) bool { + if len(s.terms) == 0 { + return false + } + for _, t := range s.terms { + // Terms represent the top term with a nil type. + // The rest of the type checker uses the top type + // instead. Convert. + // TODO(gri) investigate if we can do without this + if t.typ == nil { + t = &topTerm + } + if !f(t) { + return false + } + } + return true +} + func (s *_TypeSet) underIs(f func(Type) bool) bool { - switch t := s.types.(type) { - case nil: - return f(theTop) - default: - return f(t) - case *Union: - return t.underIs(f) + if len(s.terms) == 0 { + return false } + for _, t := range s.terms { + // see corresponding comment in TypeSet.is + u := t.typ + if u == nil { + u = theTop + } + // t == under(t) for ~t terms + if !t.tilde { + u = under(u) + } + if debug { + assert(Identical(u, under(u))) + } + if !f(u) { + return false + } + } + return true } // topTypeSet may be used as type set for the empty interface. -var topTypeSet _TypeSet +var topTypeSet = _TypeSet{terms: topTermlist} -// computeTypeSet may be called with check == nil. -func computeTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_TypeSet { +// computeInterfaceTypeSet may be called with check == nil. +func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_TypeSet { if ityp.tset != nil { return ityp.tset } @@ -157,7 +199,7 @@ func computeTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_TypeSet { // have valid interfaces. Mark the interface as complete to avoid // infinite recursion if the validType check occurs later for some // reason. - ityp.tset = new(_TypeSet) // TODO(gri) is this sufficient? + ityp.tset = &_TypeSet{terms: topTermlist} // TODO(gri) is this sufficient? // Methods of embedded interfaces are collected unchanged; i.e., the identity // of a method I.m's Func Object of an interface I is the same as that of @@ -214,7 +256,7 @@ func computeTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_TypeSet { } // collect embedded elements - var allTypes Type + var allTerms = topTermlist for i, typ := range ityp.embeddeds { // The embedding position is nil for imported interfaces // and also for interface copies after substitution (but @@ -223,26 +265,22 @@ func computeTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_TypeSet { if ityp.embedPos != nil { pos = (*ityp.embedPos)[i] } - var types Type + var terms termlist switch t := under(typ).(type) { case *Interface: - tset := computeTypeSet(check, pos, t) + tset := computeInterfaceTypeSet(check, pos, t) if tset.comparable { ityp.tset.comparable = true } for _, m := range tset.methods { addMethod(pos, m, false) // use embedding position pos rather than m.pos - } - types = tset.types + terms = tset.terms case *Union: - // TODO(gri) combine with default case once we have - // converted all tests to new notation and we - // can report an error when we don't have an - // interface before go1.18. - types = typ + tset := computeUnionTypeSet(check, pos, t) + terms = tset.terms case *TypeParam: - // Embedding stand-alone type parameters is not permitted for now. + // Embedding stand-alone type parameters is not permitted. // This case is handled during union parsing. unreachable() default: @@ -253,9 +291,11 @@ func computeTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_TypeSet { check.errorf(atPos(pos), _InvalidIfaceEmbed, "%s is not an interface", typ) continue } - types = typ + terms = termlist{{false, typ}} } - allTypes = intersect(allTypes, types) + // The type set of an interface is the intersection + // of the type sets of all its elements. + allTerms = allTerms.intersect(terms) } ityp.embedPos = nil // not needed anymore (errors have been reported) @@ -272,7 +312,7 @@ func computeTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_TypeSet { sort.Sort(byUniqueMethodName(methods)) ityp.tset.methods = methods } - ityp.tset.types = allTypes + ityp.tset.terms = allTerms return ityp.tset } @@ -296,3 +336,34 @@ type byUniqueMethodName []*Func func (a byUniqueMethodName) Len() int { return len(a) } func (a byUniqueMethodName) Less(i, j int) bool { return a[i].Id() < a[j].Id() } func (a byUniqueMethodName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +// computeUnionTypeSet may be called with check == nil. +func computeUnionTypeSet(check *Checker, pos token.Pos, utyp *Union) *_TypeSet { + if utyp.tset != nil { + return utyp.tset + } + + // avoid infinite recursion (see also computeInterfaceTypeSet) + utyp.tset = new(_TypeSet) + + var allTerms termlist + for _, t := range utyp.terms { + var terms termlist + switch u := under(t.typ).(type) { + case *Interface: + terms = computeInterfaceTypeSet(check, pos, u).terms + case *TypeParam: + // A stand-alone type parameters is not permitted as union term. + // This case is handled during union parsing. + unreachable() + default: + terms = termlist{t} + } + // The type set of a union expression is the union + // of the type sets of each term. + allTerms = allTerms.union(terms) + } + utyp.tset.terms = allTerms + + return utyp.tset +} diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index c0c69624ec..5afa450c70 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -159,9 +159,10 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { writeSignature(buf, t, qf, visited) case *Union: - if t.IsEmpty() { - buf.WriteString("⊥") - break + // Unions only appear as (syntactic) embedded elements + // in interfaces and syntactically cannot be empty. + if t.NumTerms() == 0 { + panic("internal error: empty union") } for i, t := range t.terms { if i > 0 { @@ -199,13 +200,21 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { writeSignature(buf, m.typ.(*Signature), qf, visited) empty = false } - if !empty && tset.types != nil { + if !empty && tset.hasTerms() { buf.WriteString("; ") } - if tset.types != nil { - buf.WriteString("type ") - writeType(buf, tset.types, qf, visited) - } + first := true + tset.is(func(t *term) bool { + if !first { + buf.WriteByte('|') + } + first = false + if t.tilde { + buf.WriteByte('~') + } + writeType(buf, t.typ, qf, visited) + return true + }) } else { // print explicit interface methods and embedded types for i, m := range t.methods { diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index a812ba6519..03dd7c26c4 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -145,19 +145,18 @@ func (check *Checker) varType(e ast.Expr) Type { // ordinaryType reports an error if typ is an interface type containing // type lists or is (or embeds) the predeclared type comparable. func (check *Checker) ordinaryType(pos positioner, typ Type) { - // We don't want to call under() (via asInterface) or complete interfaces - // while we are in the middle of type-checking parameter declarations that - // might belong to interface methods. Delay this check to the end of - // type-checking. + // We don't want to call under() (via asInterface) or complete interfaces while we + // are in the middle of type-checking parameter declarations that might belong to + // interface methods. Delay this check to the end of type-checking. check.later(func() { if t := asInterface(typ); t != nil { - tset := computeTypeSet(check, pos.Pos(), t) // TODO(gri) is this the correct position? - if tset.types != nil { - check.softErrorf(pos, _Todo, "interface contains type constraints (%s)", tset.types) - return - } - if tset.IsComparable() { - check.softErrorf(pos, _Todo, "interface is (or embeds) comparable") + tset := computeInterfaceTypeSet(check, pos.Pos(), t) // TODO(gri) is this the correct position? + if !tset.IsMethodSet() { + if tset.comparable { + check.softErrorf(pos, _Todo, "interface is (or embeds) comparable") + } else { + check.softErrorf(pos, _Todo, "interface contains type constraints") + } } } }) diff --git a/src/go/types/unify.go b/src/go/types/unify.go index 90a5cf7c72..a94a5f35c6 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -358,9 +358,6 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { u.nify(x.results, y.results, p) } - case *Union: - panic("unimplemented: unification with type sets described by types") - case *Interface: // Two interface types are identical if they have the same set of methods with // the same names and identical function types. Lower-case method names from @@ -368,7 +365,7 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { if y, ok := y.(*Interface); ok { xset := x.typeSet() yset := y.typeSet() - if !Identical(xset.types, yset.types) { + if !xset.terms.equal(yset.terms) { return false } a := xset.methods diff --git a/src/go/types/union.go b/src/go/types/union.go index a56f9d29f3..7f38c01f40 100644 --- a/src/go/types/union.go +++ b/src/go/types/union.go @@ -12,14 +12,15 @@ import ( // ---------------------------------------------------------------------------- // API -// A Union represents a union of terms. +// A Union represents a union of terms embedded in an interface. type Union struct { - terms []*term + terms []*term // list of syntactical terms (not a canonicalized termlist) + tset *_TypeSet // type set described by this union, computed lazily } // NewUnion returns a new Union type with the given terms (types[i], tilde[i]). -// The lengths of both arguments must match. An empty union represents the set -// of no types. +// The lengths of both arguments must match. It is an error to create an empty +// union; they are syntactically not possible. func NewUnion(types []Type, tilde []bool) *Union { return newUnion(types, tilde) } func (u *Union) IsEmpty() bool { return len(u.terms) == 0 } @@ -32,12 +33,10 @@ func (u *Union) String() string { return TypeString(u, nil) } // ---------------------------------------------------------------------------- // Implementation -var emptyUnion = new(Union) - func newUnion(types []Type, tilde []bool) *Union { assert(len(types) == len(tilde)) if len(types) == 0 { - return emptyUnion + panic("empty union") } t := new(Union) t.terms = make([]*term, len(types)) @@ -47,52 +46,23 @@ func newUnion(types []Type, tilde []bool) *Union { return t } -// is reports whether f returns true for all terms of u. -func (u *Union) is(f func(*term) bool) bool { - if u.IsEmpty() { - return false - } - for _, t := range u.terms { - if !f(t) { - return false - } - } - return true -} - -// underIs reports whether f returned true for the underlying types of all terms of u. -func (u *Union) underIs(f func(Type) bool) bool { - if u.IsEmpty() { - return false - } - for _, t := range u.terms { - if !f(under(t.typ)) { - return false - } - } - return true -} - func parseUnion(check *Checker, tlist []ast.Expr) Type { - var types []Type - var tilde []bool + var terms []*term for _, x := range tlist { - t, d := parseTilde(check, x) - if len(tlist) == 1 && !d { - return t // single type + tilde, typ := parseTilde(check, x) + if len(tlist) == 1 && !tilde { + return typ // single type } - types = append(types, t) - tilde = append(tilde, d) + terms = append(terms, &term{tilde, typ}) } - // Ensure that each type is only present once in the type list. - // It's ok to do this check later because it's not a requirement - // for correctness of the code. + // Check validity of terms. + // Do this check later because it requires types to be set up. // Note: This is a quadratic algorithm, but unions tend to be short. check.later(func() { - for i, t := range types { - t := expand(t) - if t == Typ[Invalid] { + for i, t := range terms { + typ := expand(t.typ) + if typ == Typ[Invalid] { continue } @@ -108,16 +78,16 @@ func parseUnion(check *Checker, tlist []ast.Expr) Type { } } - u := under(t) + u := under(typ) f, _ := u.(*Interface) - if tilde[i] { + if t.tilde { if f != nil { - check.errorf(x, _Todo, "invalid use of ~ (%s is an interface)", t) + check.errorf(x, _Todo, "invalid use of ~ (%s is an interface)", typ) continue // don't report another error for t } - if !Identical(u, t) { - check.errorf(x, _Todo, "invalid use of ~ (underlying type of %s is %s)", t, u) + if !Identical(u, typ) { + check.errorf(x, _Todo, "invalid use of ~ (underlying type of %s is %s)", typ, u) continue // don't report another error for t } } @@ -130,19 +100,18 @@ func parseUnion(check *Checker, tlist []ast.Expr) Type { continue // don't report another error for t } - // Complain about duplicate entries a|a, but also a|~a, and ~a|~a. - // TODO(gri) We should also exclude myint|~int since myint is included in ~int. - if includes(types[:i], t) { - // TODO(rfindley) this currently doesn't print the ~ if present - check.softErrorf(atPos(pos), _Todo, "duplicate term %s in union element", t) + // Report overlapping (non-disjoint) terms such as + // a|a, a|~a, ~a|~a, and ~a|A (where under(A) == a). + if j := overlappingTerm(terms[:i], t); j >= 0 { + check.softErrorf(atPos(pos), _Todo, "overlapping terms %s and %s", t, terms[j]) } } }) - return newUnion(types, tilde) + return &Union{terms, nil} } -func parseTilde(check *Checker, x ast.Expr) (typ Type, tilde bool) { +func parseTilde(check *Checker, x ast.Expr) (tilde bool, typ Type) { if op, _ := x.(*ast.UnaryExpr); op != nil && op.Op == token.TILDE { x = op.X tilde = true @@ -156,116 +125,20 @@ func parseTilde(check *Checker, x ast.Expr) (typ Type, tilde bool) { return } -// intersect computes the intersection of the types x and y, -// A nil type stands for the set of all types; an empty union -// stands for the set of no types. -func intersect(x, y Type) (r Type) { - // If one of the types is nil (no restrictions) - // the result is the other type. - switch { - case x == nil: - return y - case y == nil: - return x - } - - // Compute the terms which are in both x and y. - // TODO(gri) This is not correct as it may not always compute - // the "largest" intersection. For instance, for - // x = myInt|~int, y = ~int - // we get the result myInt but we should get ~int. - xu, _ := x.(*Union) - yu, _ := y.(*Union) - switch { - case xu != nil && yu != nil: - return &Union{intersectTerms(xu.terms, yu.terms)} - - case xu != nil: - if r, _ := xu.intersect(y, false); r != nil { - return y - } - - case yu != nil: - if r, _ := yu.intersect(x, false); r != nil { - return x - } - - default: // xu == nil && yu == nil - if Identical(x, y) { - return x - } - } - - return emptyUnion -} - -// includes reports whether typ is in list. -func includes(list []Type, typ Type) bool { - for _, e := range list { - if Identical(typ, e) { - return true - } - } - return false -} - -// intersect computes the intersection of the union u and term (y, yt) -// and returns the intersection term, if any. Otherwise the result is -// (nil, false). -// TODO(gri) this needs to cleaned up/removed once we switch to lazy -// union type set computation. -func (u *Union) intersect(y Type, yt bool) (Type, bool) { - under_y := under(y) - for _, x := range u.terms { - xt := x.tilde - // determine which types xx, yy to compare - xx := x.typ - if yt { - xx = under(xx) - } - yy := y - if xt { - yy = under_y - } - if Identical(xx, yy) { - // T ∩ T = T - // T ∩ ~t = T - // ~t ∩ T = T - // ~t ∩ ~t = ~t - return xx, xt && yt - } - } - return nil, false -} - -func identicalTerms(list1, list2 []*term) bool { - if len(list1) != len(list2) { - return false - } - // Every term in list1 must be in list2. - // Quadratic algorithm, but probably good enough for now. - // TODO(gri) we need a fast quick type ID/hash for all types. -L: - for _, x := range list1 { - for _, y := range list2 { - if x.equal(y) { - continue L // x is in list2 +// overlappingTerm reports the index of the term x in terms which is +// overlapping (not disjoint) from y. The result is < 0 if there is no +// such term. +func overlappingTerm(terms []*term, y *term) int { + for i, x := range terms { + // disjoint requires non-nil, non-top arguments + if debug { + if x == nil || x.typ == nil || y == nil || y.typ == nil { + panic("internal error: empty or top union term") } } - return false - } - return true -} - -func intersectTerms(list1, list2 []*term) (list []*term) { - // Quadratic algorithm, but good enough for now. - // TODO(gri) fix asymptotic performance - for _, x := range list1 { - for _, y := range list2 { - if r := x.intersect(y); r != nil { - list = append(list, r) - } + if !x.disjoint(y) { + return i } } - return + return -1 } diff --git a/src/go/types/universe.go b/src/go/types/universe.go index 83c54c8cd3..7d48c5d748 100644 --- a/src/go/types/universe.go +++ b/src/go/types/universe.go @@ -90,7 +90,7 @@ func defPredeclaredTypes() { sig := NewSignature(nil, nil, NewTuple(res), false) err := NewFunc(token.NoPos, nil, "Error", sig) ityp := &Interface{obj, []*Func{err}, nil, nil, true, nil} - computeTypeSet(nil, token.NoPos, ityp) // prevent races due to lazy computation of tset + computeInterfaceTypeSet(nil, token.NoPos, ityp) // prevent races due to lazy computation of tset typ := NewNamed(obj, ityp, nil) sig.recv = NewVar(token.NoPos, nil, "", typ) def(obj) @@ -100,7 +100,7 @@ func defPredeclaredTypes() { { obj := NewTypeName(token.NoPos, nil, "comparable", nil) obj.setColor(black) - ityp := &Interface{obj, nil, nil, nil, true, &_TypeSet{true, nil, nil}} + ityp := &Interface{obj, nil, nil, nil, true, &_TypeSet{true, nil, topTermlist}} NewNamed(obj, ityp, nil) def(obj) } -- GitLab From c88e3ff6483615f980c8e4ee4d807a84cbaf4515 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sun, 15 Aug 2021 19:47:08 -0400 Subject: [PATCH 0689/2500] cmd/compile/internal/types2: use the underlying TypeParam in assignableTo In CL 338310, assignableTo was altered to walk the constituent types of TypeParams rather than Unions, but was not also adjusted to use under rather than optype. This manifested in the port to go/types. Change-Id: Ie057b96ce93cef204af88b536ea49344c9bc8f12 Reviewed-on: https://go-review.googlesource.com/c/go/+/342409 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/operand.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/types2/operand.go b/src/cmd/compile/internal/types2/operand.go index 8336451e9c..19326b8342 100644 --- a/src/cmd/compile/internal/types2/operand.go +++ b/src/cmd/compile/internal/types2/operand.go @@ -273,7 +273,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er // x is an untyped value representable by a value of type T. if isUntyped(Vu) { - if t, ok := Tu.(*TypeParam); ok { + if t, ok := under(T).(*TypeParam); ok { return t.is(func(t *term) bool { // TODO(gri) this could probably be more efficient if t.tilde { -- GitLab From 0b61dc4577c6958c852e99abf2c2a2cad2b186a2 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sun, 15 Aug 2021 20:32:29 -0400 Subject: [PATCH 0690/2500] go/types: remove unused gcCompatibilityMode flag (cleanup) This is a port of CL 339831 to go/types. gcCompatibilityMode is unused, and x/tools/go/types no longer exists, so delete it. Change-Id: I886d8c24b7aa6511934ac78549f07a88a18e950b Reviewed-on: https://go-review.googlesource.com/c/go/+/342429 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/typestring.go | 98 ++++++-------------------------------- 1 file changed, 14 insertions(+), 84 deletions(-) diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 5afa450c70..d77df435ac 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -40,27 +40,6 @@ func RelativeTo(pkg *Package) Qualifier { } } -// If gcCompatibilityMode is set, printing of types is modified -// to match the representation of some types in the gc compiler: -// -// - byte and rune lose their alias name and simply stand for -// uint8 and int32 respectively -// - embedded interfaces get flattened (the embedding info is lost, -// and certain recursive interface types cannot be printed anymore) -// -// This makes it easier to compare packages computed with the type- -// checker vs packages imported from gc export data. -// -// Caution: This flag affects all uses of WriteType, globally. -// It is only provided for testing in conjunction with -// gc-generated data. -// -// This flag is exported in the x/tools/go/types package. We don't -// need it at the moment in the std repo and so we don't export it -// anymore. We should eventually try to remove it altogether. -// TODO(gri) remove this -var gcCompatibilityMode bool - // TypeString returns the string representation of typ. // The Qualifier controls the printing of // package-level objects, and may be nil. @@ -108,15 +87,6 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { } } - if gcCompatibilityMode { - // forget the alias names - switch t.kind { - case Byte: - t = Typ[Uint8] - case Rune: - t = Typ[Int32] - } - } buf.WriteString(t.name) case *Array: @@ -175,66 +145,26 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { } case *Interface: - // We write the source-level methods and embedded types rather - // than the actual method set since resolved method signatures - // may have non-printable cycles if parameters have embedded - // interface types that (directly or indirectly) embed the - // current interface. For instance, consider the result type - // of m: - // - // type T interface{ - // m() interface{ T } - // } - // buf.WriteString("interface{") empty := true - if gcCompatibilityMode { - // print flattened interface - // (useful to compare against gc-generated interfaces) - tset := t.typeSet() - for i, m := range tset.methods { - if i > 0 { - buf.WriteString("; ") - } - buf.WriteString(m.name) - writeSignature(buf, m.typ.(*Signature), qf, visited) - empty = false - } - if !empty && tset.hasTerms() { + // print explicit interface methods and embedded types + for i, m := range t.methods { + if i > 0 { buf.WriteString("; ") } - first := true - tset.is(func(t *term) bool { - if !first { - buf.WriteByte('|') - } - first = false - if t.tilde { - buf.WriteByte('~') - } - writeType(buf, t.typ, qf, visited) - return true - }) - } else { - // print explicit interface methods and embedded types - for i, m := range t.methods { - if i > 0 { - buf.WriteString("; ") - } - buf.WriteString(m.name) - writeSignature(buf, m.typ.(*Signature), qf, visited) - empty = false - } - if !empty && len(t.embeddeds) > 0 { + buf.WriteString(m.name) + writeSignature(buf, m.typ.(*Signature), qf, visited) + empty = false + } + if !empty && len(t.embeddeds) > 0 { + buf.WriteString("; ") + } + for i, typ := range t.embeddeds { + if i > 0 { buf.WriteString("; ") } - for i, typ := range t.embeddeds { - if i > 0 { - buf.WriteString("; ") - } - writeType(buf, typ, qf, visited) - empty = false - } + writeType(buf, typ, qf, visited) + empty = false } // print /* incomplete */ if needed to satisfy existing tests // TODO(gri) get rid of this eventually -- GitLab From 11a1f37b076122ce6b669f1a5c7563a339087b17 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sun, 15 Aug 2021 20:38:37 -0400 Subject: [PATCH 0691/2500] go/types: remove TestIncompleteInterfaces (cleanup) This is a straightforward port of CL 339832 to go/types. Change-Id: Ibcb1b130ea474bbbfe9cb5138170e27b466313cf Reviewed-on: https://go-review.googlesource.com/c/go/+/342430 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/api_test.go | 7 +++++ src/go/types/typestring.go | 26 +++++---------- src/go/types/typestring_test.go | 56 --------------------------------- 3 files changed, 14 insertions(+), 75 deletions(-) diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index f138af5fbf..8e1565b95e 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -1546,6 +1546,13 @@ func F(){ } } +// newDefined creates a new defined type named T with the given underlying type. +// Helper function for use with TestIncompleteInterfaces only. +func newDefined(underlying Type) *Named { + tname := NewTypeName(token.NoPos, nil, "T", nil) + return NewNamed(tname, underlying, nil) +} + func TestConvertibleTo(t *testing.T) { for _, test := range []struct { v, t Type diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index d77df435ac..ae15e1503e 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -146,33 +146,21 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { case *Interface: buf.WriteString("interface{") - empty := true - // print explicit interface methods and embedded types - for i, m := range t.methods { - if i > 0 { + first := true + for _, m := range t.methods { + if !first { buf.WriteString("; ") } + first = false buf.WriteString(m.name) writeSignature(buf, m.typ.(*Signature), qf, visited) - empty = false - } - if !empty && len(t.embeddeds) > 0 { - buf.WriteString("; ") } - for i, typ := range t.embeddeds { - if i > 0 { + for _, typ := range t.embeddeds { + if !first { buf.WriteString("; ") } + first = false writeType(buf, typ, qf, visited) - empty = false - } - // print /* incomplete */ if needed to satisfy existing tests - // TODO(gri) get rid of this eventually - if debug && t.tset == nil { - if !empty { - buf.WriteByte(' ') - } - buf.WriteString("/* incomplete */") } buf.WriteByte('}') diff --git a/src/go/types/typestring_test.go b/src/go/types/typestring_test.go index f02c0d9c18..ddbb2884b6 100644 --- a/src/go/types/typestring_test.go +++ b/src/go/types/typestring_test.go @@ -144,62 +144,6 @@ func TestTypeString(t *testing.T) { } } -func TestIncompleteInterfaces(t *testing.T) { - if !Debug { - t.Skip("requires type checker to be compiled with debug = true") - } - - sig := NewSignature(nil, nil, nil, false) - m := NewFunc(token.NoPos, nil, "m", sig) - for _, test := range []struct { - typ *Interface - want string - }{ - {new(Interface), "interface{/* incomplete */}"}, - {new(Interface).Complete(), "interface{}"}, - - {NewInterface(nil, nil), "interface{}"}, - {NewInterface(nil, nil).Complete(), "interface{}"}, - {NewInterface([]*Func{}, nil), "interface{}"}, - {NewInterface([]*Func{}, nil).Complete(), "interface{}"}, - {NewInterface(nil, []*Named{}), "interface{}"}, - {NewInterface(nil, []*Named{}).Complete(), "interface{}"}, - {NewInterface([]*Func{m}, nil), "interface{m() /* incomplete */}"}, - {NewInterface([]*Func{m}, nil).Complete(), "interface{m()}"}, - {NewInterface(nil, []*Named{newDefined(new(Interface).Complete())}), "interface{T /* incomplete */}"}, - {NewInterface(nil, []*Named{newDefined(new(Interface).Complete())}).Complete(), "interface{T}"}, - {NewInterface(nil, []*Named{newDefined(NewInterface([]*Func{m}, nil))}), "interface{T /* incomplete */}"}, - {NewInterface(nil, []*Named{newDefined(NewInterface([]*Func{m}, nil).Complete())}), "interface{T /* incomplete */}"}, - {NewInterface(nil, []*Named{newDefined(NewInterface([]*Func{m}, nil).Complete())}).Complete(), "interface{T}"}, - - {NewInterfaceType(nil, nil), "interface{}"}, - {NewInterfaceType(nil, nil).Complete(), "interface{}"}, - {NewInterfaceType([]*Func{}, nil), "interface{}"}, - {NewInterfaceType([]*Func{}, nil).Complete(), "interface{}"}, - {NewInterfaceType(nil, []Type{}), "interface{}"}, - {NewInterfaceType(nil, []Type{}).Complete(), "interface{}"}, - {NewInterfaceType([]*Func{m}, nil), "interface{m() /* incomplete */}"}, - {NewInterfaceType([]*Func{m}, nil).Complete(), "interface{m()}"}, - {NewInterfaceType(nil, []Type{new(Interface).Complete()}), "interface{interface{} /* incomplete */}"}, - {NewInterfaceType(nil, []Type{new(Interface).Complete()}).Complete(), "interface{interface{}}"}, - {NewInterfaceType(nil, []Type{NewInterfaceType([]*Func{m}, nil)}), "interface{interface{m() /* incomplete */} /* incomplete */}"}, - {NewInterfaceType(nil, []Type{NewInterfaceType([]*Func{m}, nil).Complete()}), "interface{interface{m()} /* incomplete */}"}, - {NewInterfaceType(nil, []Type{NewInterfaceType([]*Func{m}, nil).Complete()}).Complete(), "interface{interface{m()}}"}, - } { - got := test.typ.String() - if got != test.want { - t.Errorf("got: %s, want: %s", got, test.want) - } - } -} - -// newDefined creates a new defined type named T with the given underlying type. -// Helper function for use with TestIncompleteInterfaces only. -func newDefined(underlying Type) *Named { - tname := NewTypeName(token.NoPos, nil, "T", nil) - return NewNamed(tname, underlying, nil) -} - func TestQualifiedTypeString(t *testing.T) { p, _ := pkgFor("p.go", "package p; type T int", nil) q, _ := pkgFor("q.go", "package q", nil) -- GitLab From a192ef8ac47679ca46a41fa190af1048e7008b2b Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sun, 15 Aug 2021 20:44:49 -0400 Subject: [PATCH 0692/2500] go/types: cleanup panic calls This is a port of CL 339969 to go/types. It differs slightly in errors.go, due to the differing API. Change-Id: Ie2bf84ebf312ea3872ee6706615dfc6169a32405 Reviewed-on: https://go-review.googlesource.com/c/go/+/342431 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/decl.go | 4 ++-- src/go/types/errors.go | 4 ++-- src/go/types/lookup.go | 4 ++-- src/go/types/named.go | 12 ++++++------ src/go/types/signature.go | 4 ++-- src/go/types/stmt.go | 2 +- src/go/types/typeparam.go | 4 ++-- src/go/types/typeset.go | 4 ++-- src/go/types/typestring.go | 6 +++--- src/go/types/union.go | 2 +- src/go/types/universe.go | 2 +- 11 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 831b1da589..6c305caff5 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -339,7 +339,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { // cycle detected for i, tn := range path { if t.obj.pkg != check.pkg { - panic("internal error: type cycle via package-external type") + panic("type cycle via package-external type") } if tn == t.obj { check.cycleError(path[i:]) @@ -347,7 +347,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { return t.info } } - panic("internal error: cycle start not found") + panic("cycle start not found") } return t.info } diff --git a/src/go/types/errors.go b/src/go/types/errors.go index 2263106417..7468626b98 100644 --- a/src/go/types/errors.go +++ b/src/go/types/errors.go @@ -68,7 +68,7 @@ func (check *Checker) sprintf(format string, args ...interface{}) string { case nil: arg = "" case operand: - panic("internal error: should always pass *operand") + panic("got operand instead of *operand") case *operand: arg = operandString(a, check.qualifier) case token.Pos: @@ -236,7 +236,7 @@ func (s atPos) Pos() token.Pos { func spanOf(at positioner) posSpan { switch x := at.(type) { case nil: - panic("internal error: nil") + panic("nil positioner") case posSpan: return x case ast.Node: diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index 7cab336dbe..28628058c2 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -320,7 +320,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, return m, f } if ftyp.TParams().Len() > 0 { - panic("internal error: method with type parameters") + panic("method with type parameters") } // If the methods have type parameters we don't care whether they @@ -372,7 +372,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, return m, f } if ftyp.TParams().Len() > 0 { - panic("internal error: method with type parameters") + panic("method with type parameters") } // If V is a (instantiated) generic type, its methods are still diff --git a/src/go/types/named.go b/src/go/types/named.go index f26b50aa81..020b9827e8 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -33,7 +33,7 @@ type Named struct { // The underlying type must not be a *Named. func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named { if _, ok := underlying.(*Named); ok { - panic("types.NewNamed: underlying type must not be *Named") + panic("underlying type must not be *Named") } return (*Checker)(nil).newNamed(obj, nil, underlying, nil, methods) } @@ -100,7 +100,7 @@ func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tpar check.later(func() { switch typ.under().(type) { case *Named: - panic("internal error: unexpanded underlying type") + panic("unexpanded underlying type") } typ.check = nil }) @@ -144,10 +144,10 @@ func (t *Named) Method(i int) *Func { return t.load().methods[i] } // SetUnderlying sets the underlying type and marks t as complete. func (t *Named) SetUnderlying(underlying Type) { if underlying == nil { - panic("types.Named.SetUnderlying: underlying type must not be nil") + panic("underlying type must not be nil") } if _, ok := underlying.(*Named); ok { - panic("types.Named.SetUnderlying: underlying type must not be *Named") + panic("underlying type must not be *Named") } t.load().underlying = underlying } @@ -195,7 +195,7 @@ func (n0 *Named) under() Type { } if n0.check == nil { - panic("internal error: Named.check == nil but type is incomplete") + panic("Named.check == nil but type is incomplete") } // Invariant: after this point n0 as well as any named types in its @@ -246,7 +246,7 @@ func (n0 *Named) under() Type { // Also, doing so would lead to a race condition (was issue #31749). // Do this check always, not just in debug mode (it's cheap). if n.obj.pkg != check.pkg { - panic("internal error: imported type with unresolved underlying type") + panic("imported type with unresolved underlying type") } n.underlying = u } diff --git a/src/go/types/signature.go b/src/go/types/signature.go index 5a69bb17b5..4624b54acb 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -38,10 +38,10 @@ func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature { if variadic { n := params.Len() if n == 0 { - panic("types.NewSignature: variadic function must have at least one parameter") + panic("variadic function must have at least one parameter") } if _, ok := params.At(n - 1).typ.(*Slice); !ok { - panic("types.NewSignature: variadic parameter must be of unnamed slice type") + panic("variadic parameter must be of unnamed slice type") } } return &Signature{recv: recv, params: params, results: results, variadic: variadic} diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index 4c545efcf9..29c189ec5d 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -15,7 +15,7 @@ import ( func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body *ast.BlockStmt, iota constant.Value) { if check.conf.IgnoreFuncBodies { - panic("internal error: function body not ignored") + panic("function body not ignored") } if trace { diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index cf80eaab38..ce8b4a7073 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -77,7 +77,7 @@ func (t *TypeParam) Constraint() Type { // SetConstraint sets the type constraint for t. func (t *TypeParam) SetConstraint(bound Type) { if bound == nil { - panic("types2.TypeParam.SetConstraint: bound must not be nil") + panic("nil constraint") } t.bound = bound } @@ -113,7 +113,7 @@ func bindTParams(list []*TypeName) *TypeParams { for i, tp := range list { typ := tp.Type().(*TypeParam) if typ.index >= 0 { - panic("internal error: type parameter bound more than once") + panic("type parameter bound more than once") } typ.index = i } diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index 3caba05202..307dae3aed 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -323,10 +323,10 @@ func sortMethods(list []*Func) { func assertSortedMethods(list []*Func) { if !debug { - panic("internal error: assertSortedMethods called outside debug mode") + panic("assertSortedMethods called outside debug mode") } if !sort.IsSorted(byUniqueMethodName(list)) { - panic("internal error: methods not sorted") + panic("methods not sorted") } } diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index ae15e1503e..975bba633a 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -132,7 +132,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { // Unions only appear as (syntactic) embedded elements // in interfaces and syntactically cannot be empty. if t.NumTerms() == 0 { - panic("internal error: empty union") + panic("empty union") } for i, t := range t.terms { if i > 0 { @@ -185,7 +185,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { case RecvOnly: s = "<-chan " default: - panic("unreachable") + unreachable() } buf.WriteString(s) if parens { @@ -332,7 +332,7 @@ func writeTuple(buf *bytes.Buffer, tup *Tuple, variadic bool, qf Qualifier, visi // special case: // append(s, "foo"...) leads to signature func([]byte, string...) if t := asBasic(typ); t == nil || t.kind != String { - panic("internal error: string type expected") + panic("expected string type") } writeType(buf, typ, qf, visited) buf.WriteString("...") diff --git a/src/go/types/union.go b/src/go/types/union.go index 7f38c01f40..5419ed821a 100644 --- a/src/go/types/union.go +++ b/src/go/types/union.go @@ -133,7 +133,7 @@ func overlappingTerm(terms []*term, y *term) int { // disjoint requires non-nil, non-top arguments if debug { if x == nil || x.typ == nil || y == nil || y.typ == nil { - panic("internal error: empty or top union term") + panic("empty or top union term") } } if !x.disjoint(y) { diff --git a/src/go/types/universe.go b/src/go/types/universe.go index 7d48c5d748..b8bf0a0db1 100644 --- a/src/go/types/universe.go +++ b/src/go/types/universe.go @@ -259,6 +259,6 @@ func def(obj Object) { } } if scope.Insert(obj) != nil { - panic("internal error: double declaration") + panic("double declaration of predeclared identifier") } } -- GitLab From 02f932e173c713333693993c509a663b9cb2bc8b Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sun, 15 Aug 2021 21:04:39 -0400 Subject: [PATCH 0693/2500] go/types: better names for things (cleanup) This is a port of CL 339891 to go/types. Change-Id: If4d9bbb3ace45bec0f40082dd42ed2dd249100ec Reviewed-on: https://go-review.googlesource.com/c/go/+/342432 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/instantiate.go | 2 +- src/go/types/interface.go | 2 +- src/go/types/termlist.go | 22 +++++----- src/go/types/termlist_test.go | 76 +++++++++++++++++------------------ src/go/types/typeset.go | 20 ++++----- src/go/types/typeterm.go | 31 +++++++------- src/go/types/typeterm_test.go | 42 +++++++++---------- src/go/types/universe.go | 2 +- 8 files changed, 97 insertions(+), 100 deletions(-) diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 6f10feb206..dc2b29a5f7 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -176,7 +176,7 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap // if iface is comparable, targ must be comparable // TODO(gri) the error messages needs to be better, here if iface.IsComparable() && !Comparable(targ) { - if tpar := asTypeParam(targ); tpar != nil && tpar.iface().typeSet().IsTop() { + if tpar := asTypeParam(targ); tpar != nil && tpar.iface().typeSet().IsAll() { check.softErrorf(atPos(pos), _Todo, "%s has no constraints", targ) return false } diff --git a/src/go/types/interface.go b/src/go/types/interface.go index a5d19e8265..510c123e97 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -96,7 +96,7 @@ func (t *Interface) NumMethods() int { return t.typeSet().NumMethods() } func (t *Interface) Method(i int) *Func { return t.typeSet().Method(i) } // Empty reports whether t is the empty interface. -func (t *Interface) Empty() bool { return t.typeSet().IsTop() } +func (t *Interface) Empty() bool { return t.typeSet().IsAll() } // IsComparable reports whether each type in interface t's type set is comparable. func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() } diff --git a/src/go/types/termlist.go b/src/go/types/termlist.go index 044c6a9466..99114cbf4c 100644 --- a/src/go/types/termlist.go +++ b/src/go/types/termlist.go @@ -13,9 +13,9 @@ import "bytes" // normal form. type termlist []*term -// topTermlist represents the set of all types. +// allTermlist represents the set of all types. // It is in normal form. -var topTermlist = termlist{new(term)} +var allTermlist = termlist{new(term)} // String prints the termlist exactly (without normalization). func (xl termlist) String() string { @@ -45,9 +45,9 @@ func (xl termlist) isEmpty() bool { return true } -// isTop reports whether the termlist xl represents the set of all types. -func (xl termlist) isTop() bool { - // If there's a ⊤ (top) term, the entire list is ⊤ (top). +// isAll reports whether the termlist xl represents the set of all types. +func (xl termlist) isAll() bool { + // If there's a 𝓤 term, the entire list is 𝓤. // If the termlist is in normal form, this requires at most // one iteration. for _, x := range xl { @@ -74,14 +74,14 @@ func (xl termlist) norm() termlist { continue } if u1, u2 := xi.union(xj); u2 == nil { - // If we encounter a ⊤ (top) term, the entire - // list is ⊤ (top). Exit early. + // If we encounter a 𝓤 term, the entire list is 𝓤. + // Exit early. // (Note that this is not just an optimization; - // if we continue, we may end up with a ⊤ term + // if we continue, we may end up with a 𝓤 term // and other terms and the result would not be // in normal form.) if u1.typ == nil { - return topTermlist + return allTermlist } xi = u1 used[j] = true // xj is now unioned into xi - ignore it in future iterations @@ -92,11 +92,11 @@ func (xl termlist) norm() termlist { return rl } -// If the type set represented by xl is specified by a single (non-⊤) term, +// If the type set represented by xl is specified by a single (non-𝓤) term, // structuralType returns that type. Otherwise it returns nil. func (xl termlist) structuralType() Type { if nl := xl.norm(); len(nl) == 1 { - return nl[0].typ // if nl.isTop() then typ is nil, which is ok + return nl[0].typ // if nl.isAll() then typ is nil, which is ok } return nil } diff --git a/src/go/types/termlist_test.go b/src/go/types/termlist_test.go index eeb820dfd2..92d49ffed8 100644 --- a/src/go/types/termlist_test.go +++ b/src/go/types/termlist_test.go @@ -21,7 +21,7 @@ func maketl(s string) termlist { } func TestTermlistTop(t *testing.T) { - if !topTermlist.isTop() { + if !allTermlist.isAll() { t.Errorf("topTermlist is not top") } } @@ -29,12 +29,12 @@ func TestTermlistTop(t *testing.T) { func TestTermlistString(t *testing.T) { for _, want := range []string{ "∅", - "⊤", + "𝓤", "int", "~int", "∅ ∪ ∅", - "⊤ ∪ ⊤", - "∅ ∪ ⊤ ∪ int", + "𝓤 ∪ 𝓤", + "∅ ∪ 𝓤 ∪ int", } { if got := maketl(want).String(); got != want { t.Errorf("(%v).String() == %v", want, got) @@ -46,9 +46,9 @@ func TestTermlistIsEmpty(t *testing.T) { for test, want := range map[string]bool{ "∅": true, "∅ ∪ ∅": true, - "∅ ∪ ∅ ∪ ⊤": false, - "⊤": false, - "⊤ ∪ int": false, + "∅ ∪ ∅ ∪ 𝓤": false, + "𝓤": false, + "𝓤 ∪ int": false, } { xl := maketl(test) got := xl.isEmpty() @@ -58,19 +58,19 @@ func TestTermlistIsEmpty(t *testing.T) { } } -func TestTermlistIsTop(t *testing.T) { +func TestTermlistIsAll(t *testing.T) { for test, want := range map[string]bool{ "∅": false, "∅ ∪ ∅": false, "int ∪ ~string": false, - "∅ ∪ ∅ ∪ ⊤": true, - "⊤": true, - "⊤ ∪ int": true, + "∅ ∪ ∅ ∪ 𝓤": true, + "𝓤": true, + "𝓤 ∪ int": true, } { xl := maketl(test) - got := xl.isTop() + got := xl.isAll() if got != want { - t.Errorf("(%v).isTop() == %v; want %v", test, got, want) + t.Errorf("(%v).isAll() == %v; want %v", test, got, want) } } } @@ -82,10 +82,10 @@ func TestTermlistNorm(t *testing.T) { {"∅", "∅"}, {"∅ ∪ ∅", "∅"}, {"∅ ∪ int", "int"}, - {"⊤ ∪ int", "⊤"}, + {"𝓤 ∪ int", "𝓤"}, {"~int ∪ int", "~int"}, {"int ∪ ~string ∪ int", "int ∪ ~string"}, - {"~int ∪ string ∪ ⊤ ∪ ~string ∪ int", "⊤"}, + {"~int ∪ string ∪ 𝓤 ∪ ~string ∪ int", "𝓤"}, } { xl := maketl(test.xl) got := maketl(test.xl).norm() @@ -106,7 +106,7 @@ func TestTermlistStructuralType(t *testing.T) { for test, want := range map[string]string{ "∅": "nil", - "⊤": "nil", + "𝓤": "nil", "int": "int", "~int": "int", "~int ∪ string": "nil", @@ -128,15 +128,15 @@ func TestTermlistUnion(t *testing.T) { }{ {"∅", "∅", "∅"}, - {"∅", "⊤", "⊤"}, + {"∅", "𝓤", "𝓤"}, {"∅", "int", "int"}, - {"⊤", "~int", "⊤"}, + {"𝓤", "~int", "𝓤"}, {"int", "~int", "~int"}, {"int", "string", "int ∪ string"}, {"int ∪ string", "~string", "int ∪ ~string"}, {"~int ∪ string", "~string ∪ int", "~int ∪ ~string"}, {"~int ∪ string ∪ ∅", "~string ∪ int", "~int ∪ ~string"}, - {"~int ∪ string ∪ ⊤", "~string ∪ int", "⊤"}, + {"~int ∪ string ∪ 𝓤", "~string ∪ int", "𝓤"}, } { xl := maketl(test.xl) yl := maketl(test.yl) @@ -153,15 +153,15 @@ func TestTermlistIntersect(t *testing.T) { }{ {"∅", "∅", "∅"}, - {"∅", "⊤", "∅"}, + {"∅", "𝓤", "∅"}, {"∅", "int", "∅"}, - {"⊤", "~int", "~int"}, + {"𝓤", "~int", "~int"}, {"int", "~int", "int"}, {"int", "string", "∅"}, {"int ∪ string", "~string", "string"}, {"~int ∪ string", "~string ∪ int", "int ∪ string"}, {"~int ∪ string ∪ ∅", "~string ∪ int", "int ∪ string"}, - {"~int ∪ string ∪ ⊤", "~string ∪ int", "int ∪ ~string"}, + {"~int ∪ string ∪ 𝓤", "~string ∪ int", "int ∪ ~string"}, } { xl := maketl(test.xl) yl := maketl(test.yl) @@ -178,10 +178,10 @@ func TestTermlistEqual(t *testing.T) { want bool }{ {"∅", "∅", true}, - {"∅", "⊤", false}, - {"⊤", "⊤", true}, - {"⊤ ∪ int", "⊤", true}, - {"⊤ ∪ int", "string ∪ ⊤", true}, + {"∅", "𝓤", false}, + {"𝓤", "𝓤", true}, + {"𝓤 ∪ int", "𝓤", true}, + {"𝓤 ∪ int", "string ∪ 𝓤", true}, {"int ∪ ~string", "string ∪ int", false}, {"int ∪ ~string ∪ ∅", "string ∪ int ∪ ~string", true}, } { @@ -200,14 +200,14 @@ func TestTermlistIncludes(t *testing.T) { want bool }{ {"∅", "int", false}, - {"⊤", "int", true}, + {"𝓤", "int", true}, {"~int", "int", true}, {"int", "string", false}, {"~int", "string", false}, {"int ∪ string", "string", true}, {"~int ∪ string", "int", true}, {"~int ∪ string ∪ ∅", "string", true}, - {"~string ∪ ∅ ∪ ⊤", "int", true}, + {"~string ∪ ∅ ∪ 𝓤", "int", true}, } { xl := maketl(test.xl) yl := testTerm(test.typ).typ @@ -224,12 +224,12 @@ func TestTermlistSupersetOf(t *testing.T) { want bool }{ {"∅", "∅", true}, - {"∅", "⊤", false}, + {"∅", "𝓤", false}, {"∅", "int", false}, - {"⊤", "∅", true}, - {"⊤", "⊤", true}, - {"⊤", "int", true}, - {"⊤", "~int", true}, + {"𝓤", "∅", true}, + {"𝓤", "𝓤", true}, + {"𝓤", "int", true}, + {"𝓤", "~int", true}, {"~int", "int", true}, {"~int", "~int", true}, {"int", "~int", false}, @@ -239,7 +239,7 @@ func TestTermlistSupersetOf(t *testing.T) { {"int ∪ string", "~string", false}, {"~int ∪ string", "int", true}, {"~int ∪ string ∪ ∅", "string", true}, - {"~string ∪ ∅ ∪ ⊤", "int", true}, + {"~string ∪ ∅ ∪ 𝓤", "int", true}, } { xl := maketl(test.xl) y := testTerm(test.typ) @@ -256,16 +256,16 @@ func TestTermlistSubsetOf(t *testing.T) { want bool }{ {"∅", "∅", true}, - {"∅", "⊤", true}, - {"⊤", "∅", false}, - {"⊤", "⊤", true}, + {"∅", "𝓤", true}, + {"𝓤", "∅", false}, + {"𝓤", "𝓤", true}, {"int", "int ∪ string", true}, {"~int", "int ∪ string", false}, {"~int", "string ∪ string ∪ int ∪ ~int", true}, {"int ∪ string", "string", false}, {"int ∪ string", "string ∪ int", true}, {"int ∪ ~string", "string ∪ int", false}, - {"int ∪ ~string", "string ∪ int ∪ ⊤", true}, + {"int ∪ ~string", "string ∪ int ∪ 𝓤", true}, {"int ∪ ~string", "string ∪ int ∪ ∅ ∪ string", false}, } { xl := maketl(test.xl) diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index 307dae3aed..f0fce50263 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -25,17 +25,17 @@ type _TypeSet struct { // IsEmpty reports whether type set s is the empty set. func (s *_TypeSet) IsEmpty() bool { return s.terms.isEmpty() } -// IsTop reports whether type set s is the set of all types (corresponding to the empty interface). -func (s *_TypeSet) IsTop() bool { return !s.comparable && len(s.methods) == 0 && s.terms.isTop() } +// IsAll reports whether type set s is the set of all types (corresponding to the empty interface). +func (s *_TypeSet) IsAll() bool { return !s.comparable && len(s.methods) == 0 && s.terms.isAll() } // TODO(gri) IsMethodSet is not a great name for this predicate. Find a better one. // IsMethodSet reports whether the type set s is described by a single set of methods. -func (s *_TypeSet) IsMethodSet() bool { return !s.comparable && s.terms.isTop() } +func (s *_TypeSet) IsMethodSet() bool { return !s.comparable && s.terms.isAll() } // IsComparable reports whether each type in the set is comparable. func (s *_TypeSet) IsComparable() bool { - if s.terms.isTop() { + if s.terms.isAll() { return s.comparable } return s.is(func(t *term) bool { @@ -67,8 +67,8 @@ func (s *_TypeSet) String() string { switch { case s.IsEmpty(): return "∅" - case s.IsTop(): - return "⊤" + case s.IsAll(): + return "𝓤" } hasMethods := len(s.methods) > 0 @@ -103,7 +103,7 @@ func (s *_TypeSet) String() string { // ---------------------------------------------------------------------------- // Implementation -func (s *_TypeSet) hasTerms() bool { return !s.terms.isTop() } +func (s *_TypeSet) hasTerms() bool { return !s.terms.isAll() } func (s *_TypeSet) structuralType() Type { return s.terms.structuralType() } func (s *_TypeSet) includes(t Type) bool { return s.terms.includes(t) } func (s1 *_TypeSet) subsetOf(s2 *_TypeSet) bool { return s1.terms.subsetOf(s2.terms) } @@ -156,7 +156,7 @@ func (s *_TypeSet) underIs(f func(Type) bool) bool { } // topTypeSet may be used as type set for the empty interface. -var topTypeSet = _TypeSet{terms: topTermlist} +var topTypeSet = _TypeSet{terms: allTermlist} // computeInterfaceTypeSet may be called with check == nil. func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_TypeSet { @@ -199,7 +199,7 @@ func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_T // have valid interfaces. Mark the interface as complete to avoid // infinite recursion if the validType check occurs later for some // reason. - ityp.tset = &_TypeSet{terms: topTermlist} // TODO(gri) is this sufficient? + ityp.tset = &_TypeSet{terms: allTermlist} // TODO(gri) is this sufficient? // Methods of embedded interfaces are collected unchanged; i.e., the identity // of a method I.m's Func Object of an interface I is the same as that of @@ -256,7 +256,7 @@ func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_T } // collect embedded elements - var allTerms = topTermlist + var allTerms = allTermlist for i, typ := range ityp.embeddeds { // The embedding position is nil for imported interfaces // and also for interface copies after substitution (but diff --git a/src/go/types/typeterm.go b/src/go/types/typeterm.go index dbd055a580..171e8f21b6 100644 --- a/src/go/types/typeterm.go +++ b/src/go/types/typeterm.go @@ -4,13 +4,10 @@ package types -// TODO(gri) use a different symbol instead of ⊤ for the set of all types -// (⊤ is hard to distinguish from T in some fonts) - // A term describes elementary type sets: // // ∅: (*term)(nil) == ∅ // set of no types (empty set) -// ⊤: &term{} == ⊤ // set of all types +// 𝓤: &term{} == 𝓤 // set of all types (𝓤niverse) // T: &term{false, T} == {T} // set of type T // ~t: &term{true, t} == {t' | under(t') == t} // set of types with underlying type t // @@ -24,7 +21,7 @@ func (x *term) String() string { case x == nil: return "∅" case x.typ == nil: - return "⊤" + return "𝓤" case x.tilde: return "~" + x.typ.String() default: @@ -41,7 +38,7 @@ func (x *term) equal(y *term) bool { case x.typ == nil || y.typ == nil: return x.typ == y.typ } - // ∅ ⊂ x, y ⊂ ⊤ + // ∅ ⊂ x, y ⊂ 𝓤 return x.tilde == y.tilde && Identical(x.typ, y.typ) } @@ -57,11 +54,11 @@ func (x *term) union(y *term) (_, _ *term) { case y == nil: return x, nil // x ∪ ∅ == x case x.typ == nil: - return x, nil // ⊤ ∪ y == ⊤ + return x, nil // 𝓤 ∪ y == 𝓤 case y.typ == nil: - return y, nil // x ∪ ⊤ == ⊤ + return y, nil // x ∪ 𝓤 == 𝓤 } - // ∅ ⊂ x, y ⊂ ⊤ + // ∅ ⊂ x, y ⊂ 𝓤 if x.disjoint(y) { return x, y // x ∪ y == (x, y) if x ∩ y == ∅ @@ -85,11 +82,11 @@ func (x *term) intersect(y *term) *term { case x == nil || y == nil: return nil // ∅ ∩ y == ∅ and ∩ ∅ == ∅ case x.typ == nil: - return y // ⊤ ∩ y == y + return y // 𝓤 ∩ y == y case y.typ == nil: - return x // x ∩ ⊤ == x + return x // x ∩ 𝓤 == x } - // ∅ ⊂ x, y ⊂ ⊤ + // ∅ ⊂ x, y ⊂ 𝓤 if x.disjoint(y) { return nil // x ∩ y == ∅ if x ∩ y == ∅ @@ -113,9 +110,9 @@ func (x *term) includes(t Type) bool { case x == nil: return false // t ∈ ∅ == false case x.typ == nil: - return true // t ∈ ⊤ == true + return true // t ∈ 𝓤 == true } - // ∅ ⊂ x ⊂ ⊤ + // ∅ ⊂ x ⊂ 𝓤 u := t if x.tilde { @@ -133,11 +130,11 @@ func (x *term) subsetOf(y *term) bool { case y == nil: return false // x ⊆ ∅ == false since x != ∅ case y.typ == nil: - return true // x ⊆ ⊤ == true + return true // x ⊆ 𝓤 == true case x.typ == nil: - return false // ⊤ ⊆ y == false since y != ⊤ + return false // 𝓤 ⊆ y == false since y != 𝓤 } - // ∅ ⊂ x, y ⊂ ⊤ + // ∅ ⊂ x, y ⊂ 𝓤 if x.disjoint(y) { return false // x ⊆ y == false if x ∩ y == ∅ diff --git a/src/go/types/typeterm_test.go b/src/go/types/typeterm_test.go index 391ff3e05f..26a679dd09 100644 --- a/src/go/types/typeterm_test.go +++ b/src/go/types/typeterm_test.go @@ -11,7 +11,7 @@ import ( var testTerms = map[string]*term{ "∅": nil, - "⊤": {}, + "𝓤": {}, "int": {false, Typ[Int]}, "~int": {true, Typ[Int]}, "string": {false, Typ[String]}, @@ -46,14 +46,14 @@ func testTerm(name string) *term { func TestTermEqual(t *testing.T) { for _, test := range []string{ "∅ ∅ T", - "⊤ ⊤ T", + "𝓤 𝓤 T", "int int T", "~int ~int T", - "∅ ⊤ F", + "∅ 𝓤 F", "∅ int F", "∅ ~int F", - "⊤ int F", - "⊤ ~int F", + "𝓤 int F", + "𝓤 ~int F", "int ~int F", } { args := split(test, 3) @@ -74,12 +74,12 @@ func TestTermEqual(t *testing.T) { func TestTermUnion(t *testing.T) { for _, test := range []string{ "∅ ∅ ∅ ∅", - "∅ ⊤ ⊤ ∅", + "∅ 𝓤 𝓤 ∅", "∅ int int ∅", "∅ ~int ~int ∅", - "⊤ ⊤ ⊤ ∅", - "⊤ int ⊤ ∅", - "⊤ ~int ⊤ ∅", + "𝓤 𝓤 𝓤 ∅", + "𝓤 int 𝓤 ∅", + "𝓤 ~int 𝓤 ∅", "int int int ∅", "int ~int ~int ∅", "int string int string", @@ -87,11 +87,11 @@ func TestTermUnion(t *testing.T) { "~int ~string ~int ~string", // union is symmetric, but the result order isn't - repeat symmetric cases explictly - "⊤ ∅ ⊤ ∅", + "𝓤 ∅ 𝓤 ∅", "int ∅ int ∅", "~int ∅ ~int ∅", - "int ⊤ ⊤ ∅", - "~int ⊤ ⊤ ∅", + "int 𝓤 𝓤 ∅", + "~int 𝓤 𝓤 ∅", "~int int ~int ∅", "string int string int", "~string int ~string int", @@ -111,12 +111,12 @@ func TestTermUnion(t *testing.T) { func TestTermIntersection(t *testing.T) { for _, test := range []string{ "∅ ∅ ∅", - "∅ ⊤ ∅", + "∅ 𝓤 ∅", "∅ int ∅", "∅ ~int ∅", - "⊤ ⊤ ⊤", - "⊤ int int", - "⊤ ~int ~int", + "𝓤 𝓤 𝓤", + "𝓤 int int", + "𝓤 ~int ~int", "int int int", "int ~int int", "int string ∅", @@ -141,7 +141,7 @@ func TestTermIntersection(t *testing.T) { func TestTermIncludes(t *testing.T) { for _, test := range []string{ "∅ int F", - "⊤ int T", + "𝓤 int T", "int int T", "~int int T", "string int F", @@ -160,14 +160,14 @@ func TestTermIncludes(t *testing.T) { func TestTermSubsetOf(t *testing.T) { for _, test := range []string{ "∅ ∅ T", - "⊤ ⊤ T", + "𝓤 𝓤 T", "int int T", "~int ~int T", - "∅ ⊤ T", + "∅ 𝓤 T", "∅ int T", "∅ ~int T", - "⊤ int F", - "⊤ ~int F", + "𝓤 int F", + "𝓤 ~int F", "int ~int T", } { args := split(test, 3) diff --git a/src/go/types/universe.go b/src/go/types/universe.go index b8bf0a0db1..a2acfb5f69 100644 --- a/src/go/types/universe.go +++ b/src/go/types/universe.go @@ -100,7 +100,7 @@ func defPredeclaredTypes() { { obj := NewTypeName(token.NoPos, nil, "comparable", nil) obj.setColor(black) - ityp := &Interface{obj, nil, nil, nil, true, &_TypeSet{true, nil, topTermlist}} + ityp := &Interface{obj, nil, nil, nil, true, &_TypeSet{true, nil, allTermlist}} NewNamed(obj, ityp, nil) def(obj) } -- GitLab From 7b7d7d7818dfc1db22930be9333e8cc9f8c7f68c Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sun, 15 Aug 2021 21:11:18 -0400 Subject: [PATCH 0694/2500] go/types: fix range over exprs of type parameter type This is a port of CL 339897 to go/types. In addition, an error message that was adjusted in CL 274974 is ported to go/types (CL 274974 was only considered necessary for compiler compatibility). Change-Id: Idfe44d759c925f9fed353a2d1898d3d4d8d85452 Reviewed-on: https://go-review.googlesource.com/c/go/+/342433 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/builtins.go | 8 +- src/go/types/stmt.go | 40 +----- src/go/types/testdata/check/typeparams.go2 | 137 ++++++++++++++++----- 3 files changed, 113 insertions(+), 72 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 8a3fc14fea..4ace1303a7 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -145,7 +145,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b mode := invalid var typ Type var val constant.Value - switch typ = implicitArrayDeref(under(x.typ)); t := typ.(type) { + switch typ = arrayPtrDeref(under(x.typ)); t := typ.(type) { case *Basic: if isString(t) && id == _Len { if x.mode == constant_ { @@ -181,7 +181,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b case *TypeParam: if t.underIs(func(t Type) bool { - switch t := implicitArrayDeref(t).(type) { + switch t := arrayPtrDeref(t).(type) { case *Basic: if isString(t) && id == _Len { return true @@ -866,10 +866,10 @@ func makeSig(res Type, args ...Type) *Signature { return &Signature{params: params, results: result} } -// implicitArrayDeref returns A if typ is of the form *A and A is an array; +// arrayPtrDeref returns A if typ is of the form *A and A is an array; // otherwise it returns typ. // -func implicitArrayDeref(typ Type) Type { +func arrayPtrDeref(typ Type) Type { if p, ok := typ.(*Pointer); ok { if a := asArray(p.base); a != nil { return a diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index 29c189ec5d..fd6eba2deb 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -783,9 +783,9 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { // determine key/value types var key, val Type if x.mode != invalid { + // Ranging over a type parameter is permitted if it has a structural type. typ := optype(x.typ) if _, ok := typ.(*Chan); ok && s.Value != nil { - // TODO(gri) this also needs to happen for channels in generic variables check.softErrorf(atPos(s.Value.Pos()), _InvalidIterVar, "range over %s permits only one iteration variable", &x) // ok to continue } @@ -899,7 +899,7 @@ func isVarName(x ast.Expr) bool { // variables are used or present; this matters if we range over a generic // type where not all keys or values are of the same type. func rangeKeyVal(typ Type, wantKey, wantVal bool) (Type, Type, string) { - switch typ := typ.(type) { + switch typ := arrayPtrDeref(typ).(type) { case *Basic: if isString(typ) { return Typ[Int], universeRune, "" // use 'rune' name @@ -908,45 +908,17 @@ func rangeKeyVal(typ Type, wantKey, wantVal bool) (Type, Type, string) { return Typ[Int], typ.elem, "" case *Slice: return Typ[Int], typ.elem, "" - case *Pointer: - if typ := asArray(typ.base); typ != nil { - return Typ[Int], typ.elem, "" - } case *Map: return typ.key, typ.elem, "" case *Chan: var msg string if typ.dir == SendOnly { - // TODO(rfindley): this error message differs from types2. Reconcile this. - msg = "send-only channel" + msg = "receive from send-only channel" } return typ.elem, Typ[Invalid], msg - case *TypeParam: - first := true - var key, val Type - var msg string - typ.underIs(func(t Type) bool { - k, v, m := rangeKeyVal(t, wantKey, wantVal) - if k == nil || m != "" { - key, val, msg = k, v, m - return false - } - if first { - key, val, msg = k, v, m - first = false - return true - } - if wantKey && !Identical(key, k) { - key, val, msg = nil, nil, "all possible values must have the same key type" - return false - } - if wantVal && !Identical(val, v) { - key, val, msg = nil, nil, "all possible values must have the same element type" - return false - } - return true - }) - return key, val, msg + case *top: + // we have a type parameter with no structural type + return nil, nil, "no structural type" } return nil, nil, "" } diff --git a/src/go/types/testdata/check/typeparams.go2 b/src/go/types/testdata/check/typeparams.go2 index 7ed0a5e847..5cd4730078 100644 --- a/src/go/types/testdata/check/typeparams.go2 +++ b/src/go/types/testdata/check/typeparams.go2 @@ -149,40 +149,109 @@ func _[T interface{}](x T) { for range x /* ERROR cannot range */ {} } -// Disabled for now until we have clarified semantics of range. -// TODO(gri) fix this -// -// func _[T interface{ ~string | ~[]string }](x T) { -// for range x {} -// for i := range x { _ = i } -// for i, _ := range x { _ = i } -// for i, e := range x /* ERROR must have the same element type */ { _ = i } -// for _, e := range x /* ERROR must have the same element type */ {} -// var e rune -// _ = e -// for _, (e) = range x /* ERROR must have the same element type */ {} -// } -// -// -// func _[T interface{ ~string | ~[]rune | ~map[int]rune }](x T) { -// for _, e := range x { _ = e } -// for i, e := range x { _ = i; _ = e } -// } -// -// func _[T interface{ ~string | ~[]rune | ~map[string]rune }](x T) { -// for _, e := range x { _ = e } -// for i, e := range x /* ERROR must have the same key type */ { _ = e } -// } -// -// func _[T interface{ ~string | ~chan int }](x T) { -// for range x {} -// for i := range x { _ = i } -// for i, _ := range x { _ = i } // TODO(gri) should get an error here: channels only return one value -// } -// -// func _[T interface{ ~string | ~chan<-int }](x T) { -// for i := range x /* ERROR send-only channel */ { _ = i } -// } +type myString string + +func _[ + B1 interface{ string }, + B2 interface{ string | myString }, + + C1 interface{ chan int }, + C2 interface{ chan int | <-chan int }, + C3 interface{ chan<- int }, + + S1 interface{ []int }, + S2 interface{ []int | [10]int }, + + A1 interface{ [10]int }, + A2 interface{ [10]int | []int }, + + P1 interface{ *[10]int }, + P2 interface{ *[10]int | *[]int }, + + M1 interface{ map[string]int }, + M2 interface{ map[string]int | map[string]string }, +]() { + var b0 string + for range b0 {} + for _ = range b0 {} + for _, _ = range b0 {} + + var b1 B1 + for range b1 {} + for _ = range b1 {} + for _, _ = range b1 {} + + var b2 B2 + for range b2 /* ERROR cannot range over b2 .* no structural type */ {} + + var c0 chan int + for range c0 {} + for _ = range c0 {} + for _, _ /* ERROR permits only one iteration variable */ = range c0 {} + + var c1 C1 + for range c1 {} + for _ = range c1 {} + for _, _ /* ERROR permits only one iteration variable */ = range c1 {} + + var c2 C2 + for range c2 /* ERROR cannot range over c2 .* no structural type */ {} + + var c3 C3 + for range c3 /* ERROR receive from send-only channel */ {} + + var s0 []int + for range s0 {} + for _ = range s0 {} + for _, _ = range s0 {} + + var s1 S1 + for range s1 {} + for _ = range s1 {} + for _, _ = range s1 {} + + var s2 S2 + for range s2 /* ERROR cannot range over s2 .* no structural type */ {} + + var a0 []int + for range a0 {} + for _ = range a0 {} + for _, _ = range a0 {} + + var a1 A1 + for range a1 {} + for _ = range a1 {} + for _, _ = range a1 {} + + var a2 A2 + for range a2 /* ERROR cannot range over a2 .* no structural type */ {} + + var p0 *[10]int + for range p0 {} + for _ = range p0 {} + for _, _ = range p0 {} + + var p1 P1 + for range p1 {} + for _ = range p1 {} + for _, _ = range p1 {} + + var p2 P2 + for range p2 /* ERROR cannot range over p2 .* no structural type */ {} + + var m0 map[string]int + for range m0 {} + for _ = range m0 {} + for _, _ = range m0 {} + + var m1 M1 + for range m1 {} + for _ = range m1 {} + for _, _ = range m1 {} + + var m2 M2 + for range m2 /* ERROR cannot range over m2 .* no structural type */ {} +} // type inference checks -- GitLab From efd206eb40a59e955c12653b1720026244e6c667 Mon Sep 17 00:00:00 2001 From: Meng Zhuo Date: Tue, 22 Jun 2021 11:20:03 +0000 Subject: [PATCH 0695/2500] cmd/compile: intrinsify Mul64 on riscv64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to RISCV instruction set manual v2.2 Sec 6.1 MULHU followed by MUL will be fused into one multiply by microarchitecture Benchstat on Hifive unmatched: name old time/op new time/op delta Hash8Bytes 245ns ± 3% 186ns ± 4% -23.99% (p=0.000 n=10+10) Hash320Bytes 1.94µs ± 1% 1.31µs ± 1% -32.38% (p=0.000 n=9+10) Hash1K 5.84µs ± 0% 3.84µs ± 0% -34.20% (p=0.000 n=10+9) Hash8K 45.3µs ± 0% 29.4µs ± 0% -35.04% (p=0.000 n=10+10) name old speed new speed delta Hash8Bytes 32.7MB/s ± 3% 43.0MB/s ± 4% +31.61% (p=0.000 n=10+10) Hash320Bytes 165MB/s ± 1% 244MB/s ± 1% +47.88% (p=0.000 n=9+10) Hash1K 175MB/s ± 0% 266MB/s ± 0% +51.98% (p=0.000 n=10+9) Hash8K 181MB/s ± 0% 279MB/s ± 0% +53.94% (p=0.000 n=10+10) Change-Id: I3561495d02a4a0ad8578e9b9819bf0a4eaca5d12 Reviewed-on: https://go-review.googlesource.com/c/go/+/329970 Reviewed-by: Joel Sing Run-TryBot: Joel Sing TryBot-Result: Go Bot Trust: Meng Zhuo --- src/cmd/compile/internal/riscv64/ssa.go | 15 +++++++++++++++ src/cmd/compile/internal/ssa/gen/RISCV64.rules | 1 + src/cmd/compile/internal/ssa/gen/RISCV64Ops.go | 3 +++ src/cmd/compile/internal/ssa/opGen.go | 16 ++++++++++++++++ src/cmd/compile/internal/ssa/rewriteRISCV64.go | 3 +++ src/cmd/compile/internal/ssagen/ssa.go | 6 +++--- test/codegen/mathbits.go | 1 + test/run.go | 1 + 8 files changed, 43 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/riscv64/ssa.go b/src/cmd/compile/internal/riscv64/ssa.go index 64a9b3b33b..c635d93b71 100644 --- a/src/cmd/compile/internal/riscv64/ssa.go +++ b/src/cmd/compile/internal/riscv64/ssa.go @@ -282,6 +282,21 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.Reg = r1 p.To.Type = obj.TYPE_REG p.To.Reg = r + case ssa.OpRISCV64LoweredMuluhilo: + r0 := v.Args[0].Reg() + r1 := v.Args[1].Reg() + p := s.Prog(riscv.AMULHU) + p.From.Type = obj.TYPE_REG + p.From.Reg = r1 + p.Reg = r0 + p.To.Type = obj.TYPE_REG + p.To.Reg = v.Reg0() + p1 := s.Prog(riscv.AMUL) + p1.From.Type = obj.TYPE_REG + p1.From.Reg = r1 + p1.Reg = r0 + p1.To.Type = obj.TYPE_REG + p1.To.Reg = v.Reg1() case ssa.OpRISCV64FSQRTS, ssa.OpRISCV64FNEGS, ssa.OpRISCV64FSQRTD, ssa.OpRISCV64FNEGD, ssa.OpRISCV64FMVSX, ssa.OpRISCV64FMVDX, ssa.OpRISCV64FCVTSW, ssa.OpRISCV64FCVTSL, ssa.OpRISCV64FCVTWS, ssa.OpRISCV64FCVTLS, diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64.rules b/src/cmd/compile/internal/ssa/gen/RISCV64.rules index 9cdd62edbe..b21ebe6abb 100644 --- a/src/cmd/compile/internal/ssa/gen/RISCV64.rules +++ b/src/cmd/compile/internal/ssa/gen/RISCV64.rules @@ -29,6 +29,7 @@ (Sub64F ...) => (FSUBD ...) (Mul64 ...) => (MUL ...) +(Mul64uhilo ...) => (LoweredMuluhilo ...) (Mul32 ...) => (MULW ...) (Mul16 x y) => (MULW (SignExt16to32 x) (SignExt16to32 y)) (Mul8 x y) => (MULW (SignExt8to32 x) (SignExt8to32 y)) diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go index 0774d4c654..cb9051f954 100644 --- a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go @@ -123,6 +123,7 @@ func init() { gp01 = regInfo{outputs: []regMask{gpMask}} gp11 = regInfo{inputs: []regMask{gpMask}, outputs: []regMask{gpMask}} gp21 = regInfo{inputs: []regMask{gpMask, gpMask}, outputs: []regMask{gpMask}} + gp22 = regInfo{inputs: []regMask{gpMask, gpMask}, outputs: []regMask{gpMask, gpMask}} gpload = regInfo{inputs: []regMask{gpspsbMask, 0}, outputs: []regMask{gpMask}} gp11sb = regInfo{inputs: []regMask{gpspsbMask}, outputs: []regMask{gpMask}} gpxchg = regInfo{inputs: []regMask{gpspsbgMask, gpgMask}, outputs: []regMask{gpMask}} @@ -157,6 +158,8 @@ func init() { {name: "MULW", argLength: 2, reg: gp21, asm: "MULW", commutative: true, typ: "Int32"}, {name: "MULH", argLength: 2, reg: gp21, asm: "MULH", commutative: true, typ: "Int64"}, {name: "MULHU", argLength: 2, reg: gp21, asm: "MULHU", commutative: true, typ: "UInt64"}, + {name: "LoweredMuluhilo", argLength: 2, reg: gp22, resultNotInArgs: true}, // arg0 * arg1, return (hi, lo) + {name: "DIV", argLength: 2, reg: gp21, asm: "DIV", typ: "Int64"}, // arg0 / arg1 {name: "DIVU", argLength: 2, reg: gp21, asm: "DIVU", typ: "UInt64"}, {name: "DIVW", argLength: 2, reg: gp21, asm: "DIVW", typ: "Int32"}, diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index df15c2edda..7893ce837e 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -2069,6 +2069,7 @@ const ( OpRISCV64MULW OpRISCV64MULH OpRISCV64MULHU + OpRISCV64LoweredMuluhilo OpRISCV64DIV OpRISCV64DIVU OpRISCV64DIVW @@ -27603,6 +27604,21 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "LoweredMuluhilo", + argLen: 2, + resultNotInArgs: true, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + }, + outputs: []outputInfo{ + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + }, + }, + }, { name: "DIV", argLen: 2, diff --git a/src/cmd/compile/internal/ssa/rewriteRISCV64.go b/src/cmd/compile/internal/ssa/rewriteRISCV64.go index 431fb1aaf6..f315c0d3a8 100644 --- a/src/cmd/compile/internal/ssa/rewriteRISCV64.go +++ b/src/cmd/compile/internal/ssa/rewriteRISCV64.go @@ -356,6 +356,9 @@ func rewriteValueRISCV64(v *Value) bool { case OpMul64F: v.Op = OpRISCV64FMULD return true + case OpMul64uhilo: + v.Op = OpRISCV64LoweredMuluhilo + return true case OpMul8: return rewriteValueRISCV64_OpMul8(v) case OpNeg16: diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index b0f2585e3a..237135d5c7 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -4505,9 +4505,9 @@ func InitTables() { func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return s.newValue2(ssa.OpMul64uhilo, types.NewTuple(types.Types[types.TUINT64], types.Types[types.TUINT64]), args[0], args[1]) }, - sys.AMD64, sys.ARM64, sys.PPC64, sys.S390X, sys.MIPS64) - alias("math/bits", "Mul", "math/bits", "Mul64", sys.ArchAMD64, sys.ArchARM64, sys.ArchPPC64, sys.ArchPPC64LE, sys.ArchS390X, sys.ArchMIPS64, sys.ArchMIPS64LE) - alias("runtime/internal/math", "Mul64", "math/bits", "Mul64", sys.ArchAMD64, sys.ArchARM64, sys.ArchPPC64, sys.ArchPPC64LE, sys.ArchS390X, sys.ArchMIPS64, sys.ArchMIPS64LE) + sys.AMD64, sys.ARM64, sys.PPC64, sys.S390X, sys.MIPS64, sys.RISCV64) + alias("math/bits", "Mul", "math/bits", "Mul64", sys.ArchAMD64, sys.ArchARM64, sys.ArchPPC64, sys.ArchPPC64LE, sys.ArchS390X, sys.ArchMIPS64, sys.ArchMIPS64LE, sys.ArchRISCV64) + alias("runtime/internal/math", "Mul64", "math/bits", "Mul64", sys.ArchAMD64, sys.ArchARM64, sys.ArchPPC64, sys.ArchPPC64LE, sys.ArchS390X, sys.ArchMIPS64, sys.ArchMIPS64LE, sys.ArchRISCV64) addF("math/bits", "Add64", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return s.newValue3(ssa.OpAdd64carry, types.NewTuple(types.Types[types.TUINT64], types.Types[types.TUINT64]), args[0], args[1], args[2]) diff --git a/test/codegen/mathbits.go b/test/codegen/mathbits.go index 03012eff5d..aecd84a78b 100644 --- a/test/codegen/mathbits.go +++ b/test/codegen/mathbits.go @@ -710,6 +710,7 @@ func Mul64(x, y uint64) (hi, lo uint64) { // ppc64le:"MULHDU","MULLD" // s390x:"MLGR" // mips64: "MULVU" + // riscv64:"MULHU","MUL" return bits.Mul64(x, y) } diff --git a/test/run.go b/test/run.go index 6296234d56..5d5adc3623 100644 --- a/test/run.go +++ b/test/run.go @@ -1756,6 +1756,7 @@ var ( "ppc64le": {"GOPPC64", "power8", "power9"}, "s390x": {}, "wasm": {}, + "riscv64": {}, } ) -- GitLab From b0fba64ef47cc22bed926821704f223f89a56b42 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sun, 15 Aug 2021 21:20:10 -0400 Subject: [PATCH 0696/2500] go/types: fix make with type parameter argument This is a port of CL 339899 to go/types. A test assertion is adjusted to place the 'not enough arguments' error on the ')'. Change-Id: Ia13eccc66586f9b84a8b99d462bb406d363a3288 Reviewed-on: https://go-review.googlesource.com/c/go/+/342434 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/builtins.go | 42 ++++--------- src/go/types/testdata/check/builtins.go2 | 79 +++++++++++------------- 2 files changed, 47 insertions(+), 74 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 4ace1303a7..ecf6568f80 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -481,39 +481,21 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b return } - min, max := -1, 10 - var valid func(t Type) bool - valid = func(t Type) bool { - var m int - switch t := under(t).(type) { - case *Slice: - m = 2 - case *Map, *Chan: - m = 1 - case *TypeParam: - return t.underIs(valid) - default: - return false - } - if m > min { - min = m - } - if m+1 < max { - max = m + 1 - } - return true - } - - if !valid(T) { + var min int // minimum number of arguments + switch optype(T).(type) { + case *Slice: + min = 2 + case *Map, *Chan: + min = 1 + case *top: + check.invalidArg(arg0, _InvalidMake, "cannot make %s; type parameter has no structural type", arg0) + return + default: check.invalidArg(arg0, _InvalidMake, "cannot make %s; type must be slice, map, or channel", arg0) return } - if nargs < min || max < nargs { - if min == max { - check.errorf(call, _WrongArgCount, "%v expects %d arguments; found %d", call, min, nargs) - } else { - check.errorf(call, _WrongArgCount, "%v expects %d or %d arguments; found %d", call, min, max, nargs) - } + if nargs < min || min+1 < nargs { + check.invalidOp(call, _WrongArgCount, "%v expects %d or %d arguments; found %d", call, min, min+1, nargs) return } diff --git a/src/go/types/testdata/check/builtins.go2 b/src/go/types/testdata/check/builtins.go2 index 3881090603..1c773cc70b 100644 --- a/src/go/types/testdata/check/builtins.go2 +++ b/src/go/types/testdata/check/builtins.go2 @@ -84,50 +84,41 @@ func _[T M4[K, V], K comparable, V any](m T) { // make -type Bmc interface { - ~map[rune]string | ~chan int -} - -type Bms interface { - ~map[string]int | ~[]int -} - -type Bcs interface { - ~chan bool | ~[]float64 -} - -type Bss interface { - ~[]int | ~[]string -} - -func _[T any]() { - _ = make(T /* ERROR invalid argument */) - _ = make(T /* ERROR invalid argument */, 10) - _ = make(T /* ERROR invalid argument */, 10, 20) -} - -func _[T Bmc]() { - _ = make(T) - _ = make(T, 10) - _ = make /* ERROR expects 1 or 2 arguments */ (T, 10, 20) -} - -func _[T Bms]() { - _ = make /* ERROR expects 2 arguments */ (T) - _ = make(T, 10) - _ = make /* ERROR expects 2 arguments */ (T, 10, 20) -} - -func _[T Bcs]() { - _ = make /* ERROR expects 2 arguments */ (T) - _ = make(T, 10) - _ = make /* ERROR expects 2 arguments */ (T, 10, 20) -} - -func _[T Bss]() { - _ = make /* ERROR expects 2 or 3 arguments */ (T) - _ = make(T, 10) - _ = make(T, 10, 20) +func _[ + S1 interface{ []int }, + S2 interface{ []int | chan int }, + + M1 interface{ map[string]int }, + M2 interface{ map[string]int | chan int }, + + C1 interface{ chan int }, + C2 interface{ chan int | chan string }, +]() { + type S0 []int + _ = make([]int, 10) + _ = make(S0, 10) + _ = make(S1, 10) + _ = make() /* ERROR not enough arguments */ + _ = make /* ERROR expects 2 or 3 arguments */ (S1) + _ = make(S1, 10, 20) + _ = make /* ERROR expects 2 or 3 arguments */ (S1, 10, 20, 30) + _ = make(S2 /* ERROR cannot make .* no structural type */ , 10) + + type M0 map[string]int + _ = make(map[string]int) + _ = make(M0) + _ = make(M1) + _ = make(M1, 10) + _ = make/* ERROR expects 1 or 2 arguments */(M1, 10, 20) + _ = make(M2 /* ERROR cannot make .* no structural type */ ) + + type C0 chan int + _ = make(chan int) + _ = make(C0) + _ = make(C1) + _ = make(C1, 10) + _ = make/* ERROR expects 1 or 2 arguments */(C1, 10, 20) + _ = make(C2 /* ERROR cannot make .* no structural type */ ) } // unsafe.Alignof -- GitLab From 11a43df461a7f3d2b72168fbe9f5b7dca09c2543 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sun, 15 Aug 2021 21:22:38 -0400 Subject: [PATCH 0697/2500] go/types: minor cleanup of writeTParamList This is a port of CL 339903 to go/types. Change-Id: Iaf5fe7321d907df4421128c66cf8c58129eaae8b Reviewed-on: https://go-review.googlesource.com/c/go/+/342435 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/infer.go | 2 +- src/go/types/typestring.go | 22 +++++++++++++--------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/go/types/infer.go b/src/go/types/infer.go index eb0d75e46f..ea1057fe07 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -82,7 +82,7 @@ func (check *Checker) infer(posn positioner, tparams []*TypeName, targs []Type, // Substitute type arguments for their respective type parameters in params, // if any. Note that nil targs entries are ignored by check.subst. - // TODO(gri) Can we avoid this (we're setting known type argumemts below, + // TODO(gri) Can we avoid this (we're setting known type arguments below, // but that doesn't impact the isParameterized check for now). if params.Len() > 0 { smap := makeSubstMap(tparams, targs) diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 975bba633a..fa29d75fe2 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -249,23 +249,27 @@ func writeTParamList(buf *bytes.Buffer, list []*TypeName, qf Qualifier, visited buf.WriteString("[") var prev Type for i, p := range list { - // TODO(rFindley) support 'any' sugar here. - var b Type = &emptyInterface - if t, _ := p.typ.(*TypeParam); t != nil && t.bound != nil { - b = t.bound + // Determine the type parameter and its constraint. + // list is expected to hold type parameter names, + // but don't crash if that's not the case. + tpar, _ := p.typ.(*TypeParam) + var bound Type + if tpar != nil { + bound = tpar.bound // should not be nil but we want to see it if it is } + if i > 0 { - if b != prev { - // type bound changed - write previous one before advancing + if bound != prev { + // bound changed - write previous one before advancing buf.WriteByte(' ') writeType(buf, prev, qf, visited) } buf.WriteString(", ") } - prev = b + prev = bound - if t, _ := p.typ.(*TypeParam); t != nil { - writeType(buf, t, qf, visited) + if tpar != nil { + writeType(buf, tpar, qf, visited) } else { buf.WriteString(p.name) } -- GitLab From c2b4ec8f49184e02ea4832b4e495f206d4fc4b88 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sun, 15 Aug 2021 21:28:30 -0400 Subject: [PATCH 0698/2500] go/types: add defined type to term/termlist tests This is a port of CL 339905 to go/types. Change-Id: I9afac9e84bde6f34bb65c7e3d726986d2c648a91 Reviewed-on: https://go-review.googlesource.com/c/go/+/342436 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/termlist_test.go | 53 +++++++++++++++++++++++++++++------ src/go/types/typeterm.go | 3 ++ src/go/types/typeterm_test.go | 37 +++++++++++++++++++++++- 3 files changed, 83 insertions(+), 10 deletions(-) diff --git a/src/go/types/termlist_test.go b/src/go/types/termlist_test.go index 92d49ffed8..ba0faff359 100644 --- a/src/go/types/termlist_test.go +++ b/src/go/types/termlist_test.go @@ -32,9 +32,11 @@ func TestTermlistString(t *testing.T) { "𝓤", "int", "~int", + "myInt", "∅ ∪ ∅", "𝓤 ∪ 𝓤", "∅ ∪ 𝓤 ∪ int", + "∅ ∪ 𝓤 ∪ int ∪ myInt", } { if got := maketl(want).String(); got != want { t.Errorf("(%v).String() == %v", want, got) @@ -44,11 +46,13 @@ func TestTermlistString(t *testing.T) { func TestTermlistIsEmpty(t *testing.T) { for test, want := range map[string]bool{ - "∅": true, - "∅ ∪ ∅": true, - "∅ ∪ ∅ ∪ 𝓤": false, - "𝓤": false, - "𝓤 ∪ int": false, + "∅": true, + "∅ ∪ ∅": true, + "∅ ∪ ∅ ∪ 𝓤": false, + "∅ ∪ ∅ ∪ myInt": false, + "𝓤": false, + "𝓤 ∪ int": false, + "𝓤 ∪ myInt ∪ ∅": false, } { xl := maketl(test) got := xl.isEmpty() @@ -63,9 +67,11 @@ func TestTermlistIsAll(t *testing.T) { "∅": false, "∅ ∪ ∅": false, "int ∪ ~string": false, + "~int ∪ myInt": false, "∅ ∪ ∅ ∪ 𝓤": true, "𝓤": true, "𝓤 ∪ int": true, + "myInt ∪ 𝓤": true, } { xl := maketl(test) got := xl.isAll() @@ -82,10 +88,15 @@ func TestTermlistNorm(t *testing.T) { {"∅", "∅"}, {"∅ ∪ ∅", "∅"}, {"∅ ∪ int", "int"}, + {"∅ ∪ myInt", "myInt"}, {"𝓤 ∪ int", "𝓤"}, + {"𝓤 ∪ myInt", "𝓤"}, + {"int ∪ myInt", "int ∪ myInt"}, {"~int ∪ int", "~int"}, + {"~int ∪ myInt", "~int"}, {"int ∪ ~string ∪ int", "int ∪ ~string"}, {"~int ∪ string ∪ 𝓤 ∪ ~string ∪ int", "𝓤"}, + {"~int ∪ string ∪ myInt ∪ ~string ∪ int", "~int ∪ ~string"}, } { xl := maketl(test.xl) got := maketl(test.xl).norm() @@ -108,8 +119,10 @@ func TestTermlistStructuralType(t *testing.T) { "∅": "nil", "𝓤": "nil", "int": "int", + "myInt": "myInt", "~int": "int", "~int ∪ string": "nil", + "~int ∪ myInt": "int", "∅ ∪ int": "int", "∅ ∪ ~int": "int", "∅ ∪ ~int ∪ string": "nil", @@ -133,10 +146,14 @@ func TestTermlistUnion(t *testing.T) { {"𝓤", "~int", "𝓤"}, {"int", "~int", "~int"}, {"int", "string", "int ∪ string"}, + {"int", "myInt", "int ∪ myInt"}, + {"~int", "myInt", "~int"}, {"int ∪ string", "~string", "int ∪ ~string"}, {"~int ∪ string", "~string ∪ int", "~int ∪ ~string"}, {"~int ∪ string ∪ ∅", "~string ∪ int", "~int ∪ ~string"}, + {"~int ∪ myInt ∪ ∅", "~string ∪ int", "~int ∪ ~string"}, {"~int ∪ string ∪ 𝓤", "~string ∪ int", "𝓤"}, + {"~int ∪ string ∪ myInt", "~string ∪ int", "~int ∪ ~string"}, } { xl := maketl(test.xl) yl := maketl(test.yl) @@ -155,13 +172,19 @@ func TestTermlistIntersect(t *testing.T) { {"∅", "∅", "∅"}, {"∅", "𝓤", "∅"}, {"∅", "int", "∅"}, + {"∅", "myInt", "∅"}, {"𝓤", "~int", "~int"}, + {"𝓤", "myInt", "myInt"}, {"int", "~int", "int"}, {"int", "string", "∅"}, + {"int", "myInt", "∅"}, + {"~int", "myInt", "myInt"}, {"int ∪ string", "~string", "string"}, {"~int ∪ string", "~string ∪ int", "int ∪ string"}, {"~int ∪ string ∪ ∅", "~string ∪ int", "int ∪ string"}, + {"~int ∪ myInt ∪ ∅", "~string ∪ int", "int"}, {"~int ∪ string ∪ 𝓤", "~string ∪ int", "int ∪ ~string"}, + {"~int ∪ string ∪ myInt", "~string ∪ int", "int ∪ string"}, } { xl := maketl(test.xl) yl := maketl(test.yl) @@ -182,7 +205,9 @@ func TestTermlistEqual(t *testing.T) { {"𝓤", "𝓤", true}, {"𝓤 ∪ int", "𝓤", true}, {"𝓤 ∪ int", "string ∪ 𝓤", true}, + {"𝓤 ∪ myInt", "string ∪ 𝓤", true}, {"int ∪ ~string", "string ∪ int", false}, + {"~int ∪ string", "string ∪ myInt", false}, {"int ∪ ~string ∪ ∅", "string ∪ int ∪ ~string", true}, } { xl := maketl(test.xl) @@ -204,10 +229,12 @@ func TestTermlistIncludes(t *testing.T) { {"~int", "int", true}, {"int", "string", false}, {"~int", "string", false}, + {"~int", "myInt", true}, {"int ∪ string", "string", true}, {"~int ∪ string", "int", true}, - {"~int ∪ string ∪ ∅", "string", true}, - {"~string ∪ ∅ ∪ 𝓤", "int", true}, + {"~int ∪ string", "myInt", true}, + {"~int ∪ myInt ∪ ∅", "myInt", true}, + {"myInt ∪ ∅ ∪ 𝓤", "int", true}, } { xl := maketl(test.xl) yl := testTerm(test.typ).typ @@ -230,16 +257,20 @@ func TestTermlistSupersetOf(t *testing.T) { {"𝓤", "𝓤", true}, {"𝓤", "int", true}, {"𝓤", "~int", true}, + {"𝓤", "myInt", true}, {"~int", "int", true}, {"~int", "~int", true}, + {"~int", "myInt", true}, {"int", "~int", false}, + {"myInt", "~int", false}, {"int", "string", false}, {"~int", "string", false}, {"int ∪ string", "string", true}, {"int ∪ string", "~string", false}, {"~int ∪ string", "int", true}, + {"~int ∪ string", "myInt", true}, {"~int ∪ string ∪ ∅", "string", true}, - {"~string ∪ ∅ ∪ 𝓤", "int", true}, + {"~string ∪ ∅ ∪ 𝓤", "myInt", true}, } { xl := maketl(test.xl) y := testTerm(test.typ) @@ -261,12 +292,16 @@ func TestTermlistSubsetOf(t *testing.T) { {"𝓤", "𝓤", true}, {"int", "int ∪ string", true}, {"~int", "int ∪ string", false}, + {"~int", "myInt ∪ string", false}, + {"myInt", "~int ∪ string", true}, {"~int", "string ∪ string ∪ int ∪ ~int", true}, + {"myInt", "string ∪ string ∪ ~int", true}, {"int ∪ string", "string", false}, {"int ∪ string", "string ∪ int", true}, {"int ∪ ~string", "string ∪ int", false}, - {"int ∪ ~string", "string ∪ int ∪ 𝓤", true}, + {"myInt ∪ ~string", "string ∪ int ∪ 𝓤", true}, {"int ∪ ~string", "string ∪ int ∪ ∅ ∪ string", false}, + {"int ∪ myInt", "string ∪ ~int ∪ ∅ ∪ string", true}, } { xl := maketl(test.xl) yl := maketl(test.yl) diff --git a/src/go/types/typeterm.go b/src/go/types/typeterm.go index 171e8f21b6..6b67821000 100644 --- a/src/go/types/typeterm.go +++ b/src/go/types/typeterm.go @@ -151,6 +151,9 @@ func (x *term) subsetOf(y *term) bool { // disjoint reports whether x ∩ y == ∅. // x.typ and y.typ must not be nil. func (x *term) disjoint(y *term) bool { + if debug && (x.typ == nil || y.typ == nil) { + panic("invalid argument(s)") + } ux := x.typ if y.tilde { ux = under(ux) diff --git a/src/go/types/typeterm_test.go b/src/go/types/typeterm_test.go index 26a679dd09..27f132a1d2 100644 --- a/src/go/types/typeterm_test.go +++ b/src/go/types/typeterm_test.go @@ -5,10 +5,16 @@ package types import ( + "go/token" "strings" "testing" ) +var myInt = func() Type { + tname := NewTypeName(token.NoPos, nil, "myInt", nil) + return NewNamed(tname, Typ[Int], nil) +}() + var testTerms = map[string]*term{ "∅": nil, "𝓤": {}, @@ -16,7 +22,7 @@ var testTerms = map[string]*term{ "~int": {true, Typ[Int]}, "string": {false, Typ[String]}, "~string": {true, Typ[String]}, - // TODO(gri) add a defined type + "myInt": {false, myInt}, } func TestTermString(t *testing.T) { @@ -49,12 +55,16 @@ func TestTermEqual(t *testing.T) { "𝓤 𝓤 T", "int int T", "~int ~int T", + "myInt myInt T", "∅ 𝓤 F", "∅ int F", "∅ ~int F", "𝓤 int F", "𝓤 ~int F", + "𝓤 myInt F", "int ~int F", + "int myInt F", + "~int myInt F", } { args := split(test, 3) x := testTerm(args[0]) @@ -77,25 +87,33 @@ func TestTermUnion(t *testing.T) { "∅ 𝓤 𝓤 ∅", "∅ int int ∅", "∅ ~int ~int ∅", + "∅ myInt myInt ∅", "𝓤 𝓤 𝓤 ∅", "𝓤 int 𝓤 ∅", "𝓤 ~int 𝓤 ∅", + "𝓤 myInt 𝓤 ∅", "int int int ∅", "int ~int ~int ∅", "int string int string", "int ~string int ~string", + "int myInt int myInt", "~int ~string ~int ~string", + "~int myInt ~int ∅", // union is symmetric, but the result order isn't - repeat symmetric cases explictly "𝓤 ∅ 𝓤 ∅", "int ∅ int ∅", "~int ∅ ~int ∅", + "myInt ∅ myInt ∅", "int 𝓤 𝓤 ∅", "~int 𝓤 𝓤 ∅", + "myInt 𝓤 𝓤 ∅", "~int int ~int ∅", "string int string int", "~string int ~string int", + "myInt int myInt int", "~string ~int ~string ~int", + "myInt ~int ~int ∅", } { args := split(test, 4) x := testTerm(args[0]) @@ -114,14 +132,18 @@ func TestTermIntersection(t *testing.T) { "∅ 𝓤 ∅", "∅ int ∅", "∅ ~int ∅", + "∅ myInt ∅", "𝓤 𝓤 𝓤", "𝓤 int int", "𝓤 ~int ~int", + "𝓤 myInt myInt", "int int int", "int ~int int", "int string ∅", "int ~string ∅", + "int string ∅", "~int ~string ∅", + "~int myInt myInt", } { args := split(test, 3) x := testTerm(args[0]) @@ -144,8 +166,10 @@ func TestTermIncludes(t *testing.T) { "𝓤 int T", "int int T", "~int int T", + "~int myInt T", "string int F", "~string int F", + "myInt int F", } { args := split(test, 3) x := testTerm(args[0]) @@ -163,12 +187,19 @@ func TestTermSubsetOf(t *testing.T) { "𝓤 𝓤 T", "int int T", "~int ~int T", + "myInt myInt T", "∅ 𝓤 T", "∅ int T", "∅ ~int T", + "∅ myInt T", "𝓤 int F", "𝓤 ~int F", + "𝓤 myInt F", "int ~int T", + "int myInt F", + "~int myInt F", + "myInt int F", + "myInt ~int T", } { args := split(test, 3) x := testTerm(args[0]) @@ -187,7 +218,11 @@ func TestTermDisjoint(t *testing.T) { "int ~int F", "int string T", "int ~string T", + "int myInt T", "~int ~string T", + "~int myInt F", + "string myInt T", + "~string myInt T", } { args := split(test, 3) x := testTerm(args[0]) -- GitLab From b9f135d98fe687616b1ca8f7477e72c74af72459 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sun, 15 Aug 2021 21:36:25 -0400 Subject: [PATCH 0699/2500] go/types: change types2.Union API to accept a list of Terms This is a straightforward port of CL 340250 to go/types. Change-Id: I8fc1c78833b5393fb39344fd248529df57870a72 Reviewed-on: https://go-review.googlesource.com/c/go/+/342437 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/builtins.go | 8 +++--- src/go/types/subst.go | 6 ++--- src/go/types/typeset.go | 2 +- src/go/types/typestring.go | 2 +- src/go/types/union.go | 50 +++++++++++++++++++------------------- 5 files changed, 33 insertions(+), 35 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index ecf6568f80..2099a92acb 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -806,12 +806,10 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { if tp := asTypeParam(x); tp != nil { // Test if t satisfies the requirements for the argument // type and collect possible result types at the same time. - var rtypes []Type - var tildes []bool + var terms []*Term if !tp.iface().typeSet().is(func(t *term) bool { if r := f(t.typ); r != nil { - rtypes = append(rtypes, r) - tildes = append(tildes, t.tilde) + terms = append(terms, NewTerm(t.tilde, r)) return true } return false @@ -823,7 +821,7 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { // type param is placed in the current package so export/import // works as expected. tpar := NewTypeName(token.NoPos, check.pkg, "", nil) - ptyp := check.NewTypeParam(tpar, NewInterfaceType(nil, []Type{newUnion(rtypes, tildes)})) // assigns type to tpar as a side-effect + ptyp := check.NewTypeParam(tpar, NewInterfaceType(nil, []Type{NewUnion(terms)})) // assigns type to tpar as a side-effect ptyp.index = tp.index return ptyp diff --git a/src/go/types/subst.go b/src/go/types/subst.go index a43c5b9f0b..b4519a1b5f 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -394,19 +394,19 @@ func (subst *subster) typeList(in []Type) (out []Type, copied bool) { return } -func (subst *subster) termlist(in []*term) (out []*term, copied bool) { +func (subst *subster) termlist(in []*Term) (out []*Term, copied bool) { out = in for i, t := range in { if u := subst.typ(t.typ); u != t.typ { if !copied { // first function that got substituted => allocate new out slice // and copy all functions - new := make([]*term, len(in)) + new := make([]*Term, len(in)) copy(new, out) out = new copied = true } - out[i] = &term{t.tilde, u} + out[i] = NewTerm(t.tilde, u) } } return diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index f0fce50263..fae5196e86 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -357,7 +357,7 @@ func computeUnionTypeSet(check *Checker, pos token.Pos, utyp *Union) *_TypeSet { // This case is handled during union parsing. unreachable() default: - terms = termlist{t} + terms = termlist{(*term)(t)} } // The type set of a union expression is the union // of the type sets of each term. diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index fa29d75fe2..c38cfd4290 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -131,7 +131,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { case *Union: // Unions only appear as (syntactic) embedded elements // in interfaces and syntactically cannot be empty. - if t.NumTerms() == 0 { + if t.Len() == 0 { panic("empty union") } for i, t := range t.terms { diff --git a/src/go/types/union.go b/src/go/types/union.go index 5419ed821a..6038b2db2e 100644 --- a/src/go/types/union.go +++ b/src/go/types/union.go @@ -14,46 +14,46 @@ import ( // A Union represents a union of terms embedded in an interface. type Union struct { - terms []*term // list of syntactical terms (not a canonicalized termlist) + terms []*Term // list of syntactical terms (not a canonicalized termlist) tset *_TypeSet // type set described by this union, computed lazily } -// NewUnion returns a new Union type with the given terms (types[i], tilde[i]). -// The lengths of both arguments must match. It is an error to create an empty -// union; they are syntactically not possible. -func NewUnion(types []Type, tilde []bool) *Union { return newUnion(types, tilde) } +// NewUnion returns a new Union type with the given terms. +// It is an error to create an empty union; they are syntactically not possible. +func NewUnion(terms []*Term) *Union { + if len(terms) == 0 { + panic("empty union") + } + return &Union{terms, nil} +} -func (u *Union) IsEmpty() bool { return len(u.terms) == 0 } -func (u *Union) NumTerms() int { return len(u.terms) } -func (u *Union) Term(i int) (Type, bool) { t := u.terms[i]; return t.typ, t.tilde } +func (u *Union) Len() int { return len(u.terms) } +func (u *Union) Term(i int) *Term { return u.terms[i] } func (u *Union) Underlying() Type { return u } func (u *Union) String() string { return TypeString(u, nil) } +// A Term represents a term in a Union. +type Term term + +// NewTerm returns a new union term. +func NewTerm(tilde bool, typ Type) *Term { return &Term{tilde, typ} } + +func (t *Term) Tilde() bool { return t.tilde } +func (t *Term) Type() Type { return t.typ } +func (t *Term) String() string { return (*term)(t).String() } + // ---------------------------------------------------------------------------- // Implementation -func newUnion(types []Type, tilde []bool) *Union { - assert(len(types) == len(tilde)) - if len(types) == 0 { - panic("empty union") - } - t := new(Union) - t.terms = make([]*term, len(types)) - for i, typ := range types { - t.terms[i] = &term{tilde[i], typ} - } - return t -} - func parseUnion(check *Checker, tlist []ast.Expr) Type { - var terms []*term + var terms []*Term for _, x := range tlist { tilde, typ := parseTilde(check, x) if len(tlist) == 1 && !tilde { return typ // single type } - terms = append(terms, &term{tilde, typ}) + terms = append(terms, NewTerm(tilde, typ)) } // Check validity of terms. @@ -128,7 +128,7 @@ func parseTilde(check *Checker, x ast.Expr) (tilde bool, typ Type) { // overlappingTerm reports the index of the term x in terms which is // overlapping (not disjoint) from y. The result is < 0 if there is no // such term. -func overlappingTerm(terms []*term, y *term) int { +func overlappingTerm(terms []*Term, y *Term) int { for i, x := range terms { // disjoint requires non-nil, non-top arguments if debug { @@ -136,7 +136,7 @@ func overlappingTerm(terms []*term, y *term) int { panic("empty or top union term") } } - if !x.disjoint(y) { + if !(*term)(x).disjoint((*term)(y)) { return i } } -- GitLab From fe489c86a7a65b6bcd25118e1a8919b9950af83f Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sun, 15 Aug 2021 21:43:12 -0400 Subject: [PATCH 0700/2500] go/types: limit termlist lengths This is a port of CL 340254 to go/types, with minor adjustments for errors and positions. Change-Id: I49ea1d1de8d6e27484f167b813267615d142d31c Reviewed-on: https://go-review.googlesource.com/c/go/+/342438 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/testdata/check/unions.go2 | 66 ++++++++++++++++++++++++++ src/go/types/typeset.go | 27 +++++++++-- src/go/types/typeset_test.go | 15 ++++++ src/go/types/union.go | 12 ++++- 4 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 src/go/types/testdata/check/unions.go2 create mode 100644 src/go/types/typeset_test.go diff --git a/src/go/types/testdata/check/unions.go2 b/src/go/types/testdata/check/unions.go2 new file mode 100644 index 0000000000..bcd7de6644 --- /dev/null +++ b/src/go/types/testdata/check/unions.go2 @@ -0,0 +1,66 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Check that overlong unions don't bog down type checking. +// Disallow them for now. + +package p + +type t int + +type ( + t00 t; t01 t; t02 t; t03 t; t04 t; t05 t; t06 t; t07 t; t08 t; t09 t + t10 t; t11 t; t12 t; t13 t; t14 t; t15 t; t16 t; t17 t; t18 t; t19 t + t20 t; t21 t; t22 t; t23 t; t24 t; t25 t; t26 t; t27 t; t28 t; t29 t + t30 t; t31 t; t32 t; t33 t; t34 t; t35 t; t36 t; t37 t; t38 t; t39 t + t40 t; t41 t; t42 t; t43 t; t44 t; t45 t; t46 t; t47 t; t48 t; t49 t + t50 t; t51 t; t52 t; t53 t; t54 t; t55 t; t56 t; t57 t; t58 t; t59 t + t60 t; t61 t; t62 t; t63 t; t64 t; t65 t; t66 t; t67 t; t68 t; t69 t + t70 t; t71 t; t72 t; t73 t; t74 t; t75 t; t76 t; t77 t; t78 t; t79 t + t80 t; t81 t; t82 t; t83 t; t84 t; t85 t; t86 t; t87 t; t88 t; t89 t + t90 t; t91 t; t92 t; t93 t; t94 t; t95 t; t96 t; t97 t; t98 t; t99 t +) + +type u99 interface { + t00|t01|t02|t03|t04|t05|t06|t07|t08|t09| + t10|t11|t12|t13|t14|t15|t16|t17|t18|t19| + t20|t21|t22|t23|t24|t25|t26|t27|t28|t29| + t30|t31|t32|t33|t34|t35|t36|t37|t38|t39| + t40|t41|t42|t43|t44|t45|t46|t47|t48|t49| + t50|t51|t52|t53|t54|t55|t56|t57|t58|t59| + t60|t61|t62|t63|t64|t65|t66|t67|t68|t69| + t70|t71|t72|t73|t74|t75|t76|t77|t78|t79| + t80|t81|t82|t83|t84|t85|t86|t87|t88|t89| + t90|t91|t92|t93|t94|t95|t96|t97|t98 +} + +type u100a interface { + u99|float32 +} + +type u100b interface { + u99|float64 +} + +type u101 interface { + t00|t01|t02|t03|t04|t05|t06|t07|t08|t09| + t10|t11|t12|t13|t14|t15|t16|t17|t18|t19| + t20|t21|t22|t23|t24|t25|t26|t27|t28|t29| + t30|t31|t32|t33|t34|t35|t36|t37|t38|t39| + t40|t41|t42|t43|t44|t45|t46|t47|t48|t49| + t50|t51|t52|t53|t54|t55|t56|t57|t58|t59| + t60|t61|t62|t63|t64|t65|t66|t67|t68|t69| + t70|t71|t72|t73|t74|t75|t76|t77|t78|t79| + t80|t81|t82|t83|t84|t85|t86|t87|t88|t89| + t90|t91|t92|t93|t94|t95|t96|t97|t98|t99| + int // ERROR cannot handle more than 100 union terms +} + +type u102 interface { + int /* ERROR cannot handle more than 100 union terms */ |string|u100a +} + +type u200 interface { + u100a /* ERROR cannot handle more than 100 union terms */ |u100b +} diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index fae5196e86..7bdc708d4c 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -266,9 +266,9 @@ func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_T pos = (*ityp.embedPos)[i] } var terms termlist - switch t := under(typ).(type) { + switch u := under(typ).(type) { case *Interface: - tset := computeInterfaceTypeSet(check, pos, t) + tset := computeInterfaceTypeSet(check, pos, u) if tset.comparable { ityp.tset.comparable = true } @@ -277,7 +277,10 @@ func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_T } terms = tset.terms case *Union: - tset := computeUnionTypeSet(check, pos, t) + tset := computeUnionTypeSet(check, pos, u) + if tset == &invalidTypeSet { + continue // ignore invalid unions + } terms = tset.terms case *TypeParam: // Embedding stand-alone type parameters is not permitted. @@ -295,6 +298,8 @@ func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_T } // The type set of an interface is the intersection // of the type sets of all its elements. + // Intersection cannot produce longer termlists and + // thus cannot overflow. allTerms = allTerms.intersect(terms) } ityp.embedPos = nil // not needed anymore (errors have been reported) @@ -337,7 +342,13 @@ func (a byUniqueMethodName) Len() int { return len(a) } func (a byUniqueMethodName) Less(i, j int) bool { return a[i].Id() < a[j].Id() } func (a byUniqueMethodName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +// invalidTypeSet is a singleton type set to signal an invalid type set +// due to an error. It's also a valid empty type set, so consumers of +// type sets may choose to ignore it. +var invalidTypeSet _TypeSet + // computeUnionTypeSet may be called with check == nil. +// The result is &invalidTypeSet if the union overflows. func computeUnionTypeSet(check *Checker, pos token.Pos, utyp *Union) *_TypeSet { if utyp.tset != nil { return utyp.tset @@ -357,11 +368,21 @@ func computeUnionTypeSet(check *Checker, pos token.Pos, utyp *Union) *_TypeSet { // This case is handled during union parsing. unreachable() default: + if t.typ == Typ[Invalid] { + continue + } terms = termlist{(*term)(t)} } // The type set of a union expression is the union // of the type sets of each term. allTerms = allTerms.union(terms) + if len(allTerms) > maxTermCount { + if check != nil { + check.errorf(atPos(pos), _Todo, "cannot handle more than %d union terms (implementation limitation)", maxTermCount) + } + utyp.tset = &invalidTypeSet + return utyp.tset + } } utyp.tset.terms = allTerms diff --git a/src/go/types/typeset_test.go b/src/go/types/typeset_test.go new file mode 100644 index 0000000000..4fd1aa247d --- /dev/null +++ b/src/go/types/typeset_test.go @@ -0,0 +1,15 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +import "testing" + +func TestInvalidTypeSet(t *testing.T) { + if !invalidTypeSet.IsEmpty() { + t.Error("invalidTypeSet is not empty") + } +} + +// TODO(gri) add more tests diff --git a/src/go/types/union.go b/src/go/types/union.go index 6038b2db2e..a0cf33c938 100644 --- a/src/go/types/union.go +++ b/src/go/types/union.go @@ -46,12 +46,22 @@ func (t *Term) String() string { return (*term)(t).String() } // ---------------------------------------------------------------------------- // Implementation +// Avoid excessive type-checking times due to quadratic termlist operations. +const maxTermCount = 100 + +// parseUnion parses the given list of type expressions tlist as a union of +// those expressions. The result is a Union type, or Typ[Invalid] for some +// errors. func parseUnion(check *Checker, tlist []ast.Expr) Type { var terms []*Term for _, x := range tlist { tilde, typ := parseTilde(check, x) if len(tlist) == 1 && !tilde { - return typ // single type + return typ // single type (optimization) + } + if len(terms) >= maxTermCount { + check.errorf(x, _Todo, "cannot handle more than %d union terms (implementation limitation)", maxTermCount) + return Typ[Invalid] } terms = append(terms, NewTerm(tilde, typ)) } -- GitLab From ea8298e2f5e9f17372e818ffbd4fab951857ec6a Mon Sep 17 00:00:00 2001 From: cuiweixie Date: Mon, 16 Aug 2021 14:49:45 +0000 Subject: [PATCH 0701/2500] cmd/compile/internal/ssa: delete unused code Fixes #46186 Change-Id: Idb0674079f9484593e07cca172dfbb19be0e594d GitHub-Last-Rev: 615fc5365510ff7a39af7569f05a0013b724d0c9 GitHub-Pull-Request: golang/go#46185 Reviewed-on: https://go-review.googlesource.com/c/go/+/320111 Reviewed-by: Ben Shi Reviewed-by: Keith Randall Trust: David Chase --- src/cmd/compile/internal/ssa/regalloc.go | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index 3b90b8769c..3d978e7ac8 100644 --- a/src/cmd/compile/internal/ssa/regalloc.go +++ b/src/cmd/compile/internal/ssa/regalloc.go @@ -1865,23 +1865,6 @@ func (s *regAllocState) regalloc(f *Func) { } func (s *regAllocState) placeSpills() { - f := s.f - - // Precompute some useful info. - phiRegs := make([]regMask, f.NumBlocks()) - for _, b := range s.visitOrder { - var m regMask - for _, v := range b.Values { - if v.Op != OpPhi { - break - } - if r, ok := f.getHome(v.ID).(*Register); ok { - m |= regMask(1) << uint(r.num) - } - } - phiRegs[b.ID] = m - } - mustBeFirst := func(op Op) bool { return op.isLoweredGetClosurePtr() || op == OpPhi || op == OpArgIntReg || op == OpArgFloatReg } -- GitLab From 5da2010840a3b4d99fcdccb7cdef0ffbd6e9a29f Mon Sep 17 00:00:00 2001 From: Carlos Amedee Date: Fri, 13 Aug 2021 14:42:49 -0400 Subject: [PATCH 0702/2500] doc: start draft of go1.18 release notes, move go1.17 to x/website This template is based on CL 295209 and previous ones like it. Continue to eagerly include often-used sections, and clarify that the TODO is about completing the section, or removing if it turns out not to be needed. Move the Go 1.17 release notes to x/website, since that's the new home for past Go release notes as of CL 291711. They're added to x/website in CL 342089. For #47694 Updates #44513 Change-Id: I24962eed800d1509bdf71b7d7f819a683eb96f8f Reviewed-on: https://go-review.googlesource.com/c/go/+/342070 Trust: Carlos Amedee Run-TryBot: Carlos Amedee Reviewed-by: Dmitri Shuralyov TryBot-Result: Go Bot --- doc/go1.17.html | 1240 ----------------------------------------------- doc/go1.18.html | 84 ++++ 2 files changed, 84 insertions(+), 1240 deletions(-) delete mode 100644 doc/go1.17.html create mode 100644 doc/go1.18.html diff --git a/doc/go1.17.html b/doc/go1.17.html deleted file mode 100644 index c1b5ab3f6f..0000000000 --- a/doc/go1.17.html +++ /dev/null @@ -1,1240 +0,0 @@ - - - - - - -

Introduction to Go 1.17

- -

- The latest Go release, version 1.17, arrives six months after Go 1.16. - Most of its changes are in the implementation of the toolchain, runtime, and libraries. - As always, the release maintains the Go 1 promise of compatibility. - We expect almost all Go programs to continue to compile and run as before. -

- -

Changes to the language

- -

- Go 1.17 includes three small enhancements to the language. -

- -
    -
  • - Conversions - from slice to array pointer: An expression s of - type []T may now be converted to array pointer type - *[N]T. If a is the result of such a - conversion, then corresponding indices that are in range refer to - the same underlying elements: &a[i] == &s[i] - for 0 <= i < N. The conversion panics if - len(s) is less than N. -
  • - -
  • - unsafe.Add: - unsafe.Add(ptr, len) adds len - to ptr and returns the updated pointer - unsafe.Pointer(uintptr(ptr) + uintptr(len)). -
  • - -
  • - unsafe.Slice: - For expression ptr of type *T, - unsafe.Slice(ptr, len) returns a slice of - type []T whose underlying array starts - at ptr and whose length and capacity - are len. -
  • -
- -

- The package unsafe enhancements were added to simplify writing code that conforms - to unsafe.Pointer's safety - rules, but the rules remain unchanged. In particular, existing - programs that correctly use unsafe.Pointer remain - valid, and new programs must still follow the rules when - using unsafe.Add or unsafe.Slice. -

- - -

- Note that the new conversion from slice to array pointer is the - first case in which a type conversion can panic at run time. - Analysis tools that assume type conversions can never panic - should be updated to consider this possibility. -

- -

Ports

- -

Darwin

- -

- As announced in the Go 1.16 release - notes, Go 1.17 requires macOS 10.13 High Sierra or later; support - for previous versions has been discontinued. -

- -

Windows

- -

- Go 1.17 adds support of 64-bit ARM architecture on Windows (the - windows/arm64 port). This port supports cgo. -

- -

OpenBSD

- -

- The 64-bit MIPS architecture on OpenBSD (the openbsd/mips64 - port) now supports cgo. -

- -

- In Go 1.16, on the 64-bit x86 and 64-bit ARM architectures on - OpenBSD (the openbsd/amd64 and openbsd/arm64 - ports) system calls are made through libc, instead - of directly using machine instructions. In Go 1.17, this is also - done on the 32-bit x86 and 32-bit ARM architectures on OpenBSD - (the openbsd/386 and openbsd/arm ports). - This ensures compatibility with OpenBSD 6.9 onwards, which require - system calls to be made through libc for non-static - Go binaries. -

- -

ARM64

- -

- Go programs now maintain stack frame pointers on the 64-bit ARM - architecture on all operating systems. Previously it maintained - stack frame pointers only on Linux, macOS, and iOS. -

- -

loong64 GOARCH value reserved

- -

- The main Go compiler does not yet support the LoongArch - architecture, but we've reserved the GOARCH value - "loong64". - This means that Go files named *_loong64.go will now - be ignored by Go - tools except when that GOARCH value is being used. -

- -

Tools

- -

Go command

- - -

Pruned module graphs in go 1.17 modules

- -

- If a module specifies go 1.17 or higher, the module - graph includes only the immediate dependencies of - other go 1.17 modules, not their full transitive - dependencies. (See Module graph pruning - for more detail.) -

- -

- For the go command to correctly resolve transitive imports using - the pruned module graph, the go.mod file for each module needs to - include more detail about the transitive dependencies relevant to that module. - If a module specifies go 1.17 or higher in its - go.mod file, its go.mod file now contains an - explicit require - directive for every module that provides a transitively-imported package. - (In previous versions, the go.mod file typically only included - explicit requirements for directly-imported packages.) -

- -

- Since the expanded go.mod file needed for module graph pruning - includes all of the dependencies needed to load the imports of any package in - the main module, if the main module specifies - go 1.17 or higher the go tool no longer - reads (or even downloads) go.mod files for dependencies if they - are not needed in order to complete the requested command. - (See Lazy loading.) -

- -

- Because the number of explicit requirements may be substantially larger in an - expanded Go 1.17 go.mod file, the newly-added requirements - on indirect dependencies in a go 1.17 - module are maintained in a separate require block from the block - containing direct dependencies. -

- -

- To facilitate the upgrade to Go 1.17 pruned module graphs, the - go mod tidy - subcommand now supports a -go flag to set or change - the go version in the go.mod file. To convert - the go.mod file for an existing module to Go 1.17 without - changing the selected versions of its dependencies, run: -

- -
-  go mod tidy -go=1.17
-
- -

- By default, go mod tidy verifies that - the selected versions of dependencies relevant to the main module are the same - versions that would be used by the prior Go release (Go 1.16 for a module that - specifies go 1.17), and preserves - the go.sum entries needed by that release even for dependencies - that are not normally needed by other commands. -

- -

- The -compat flag allows that version to be overridden to support - older (or only newer) versions, up to the version specified by - the go directive in the go.mod file. To tidy - a go 1.17 module for Go 1.17 only, without saving - checksums for (or checking for consistency with) Go 1.16: -

- -
-  go mod tidy -compat=1.17
-
- -

- Note that even if the main module is tidied with -compat=1.17, - users who require the module from a - go 1.16 or earlier module will still be able to - use it, provided that the packages use only compatible language and library - features. -

- -

- The go mod graph - subcommand also supports the -go flag, which causes it to report - the graph as seen by the indicated Go version, showing dependencies that may - otherwise be pruned out. -

- -

Module deprecation comments

- -

- Module authors may deprecate a module by adding a - // Deprecated: - comment to go.mod, then tagging a new version. - go get now prints a warning if a module needed to - build packages named on the command line is deprecated. go - list -m -u prints deprecations for all - dependencies (use -f or -json to show the full - message). The go command considers different major versions to - be distinct modules, so this mechanism may be used, for example, to provide - users with migration instructions for a new major version. -

- -

go get

- -

- The go get -insecure flag is - deprecated and has been removed. To permit the use of insecure schemes - when fetching dependencies, please use the GOINSECURE - environment variable. The -insecure flag also bypassed module - sum validation, use GOPRIVATE or GONOSUMDB if - you need that functionality. See go help - environment for details. -

- -

- go get prints a deprecation warning when installing - commands outside the main module (without the -d flag). - go install cmd@version should be used - instead to install a command at a specific version, using a suffix like - @latest or @v1.2.3. In Go 1.18, the -d - flag will always be enabled, and go get will only - be used to change dependencies in go.mod. -

- -

go.mod files missing go directives

- -

- If the main module's go.mod file does not contain - a go directive and - the go command cannot update the go.mod file, the - go command now assumes go 1.11 instead of the - current release. (go mod init has added - go directives automatically since - Go 1.12.) -

- -

- If a module dependency lacks an explicit go.mod file, or - its go.mod file does not contain - a go directive, - the go command now assumes go 1.16 for that - dependency instead of the current release. (Dependencies developed in GOPATH - mode may lack a go.mod file, and - the vendor/modules.txt has to date never recorded - the go versions indicated by dependencies' go.mod - files.) -

- -

vendor contents

- -

- If the main module specifies go 1.17 or higher, - go mod vendor - now annotates - vendor/modules.txt with the go version indicated by - each vendored module in its own go.mod file. The annotated - version is used when building the module's packages from vendored source code. -

- -

- If the main module specifies go 1.17 or higher, - go mod vendor now omits go.mod - and go.sum files for vendored dependencies, which can otherwise - interfere with the ability of the go command to identify the correct - module root when invoked within the vendor tree. -

- -

Password prompts

- -

- The go command by default now suppresses SSH password prompts and - Git Credential Manager prompts when fetching Git repositories using SSH, as it - already did previously for other Git password prompts. Users authenticating to - private Git repos with password-protected SSH may configure - an ssh-agent to enable the go command to use - password-protected SSH keys. -

- -

go mod download

- -

- When go mod download is invoked without - arguments, it will no longer save sums for downloaded module content to - go.sum. It may still make changes to go.mod and - go.sum needed to load the build list. This is the same as the - behavior in Go 1.15. To save sums for all modules, use go - mod download all. -

- -

//go:build lines

- -

- The go command now understands //go:build lines - and prefers them over // +build lines. The new syntax uses - boolean expressions, just like Go, and should be less error-prone. - As of this release, the new syntax is fully supported, and all Go files - should be updated to have both forms with the same meaning. To aid in - migration, gofmt now automatically - synchronizes the two forms. For more details on the syntax and migration plan, - see - https://golang.org/design/draft-gobuild. -

- -

go run

- -

- go run now accepts arguments with version suffixes - (for example, go run - example.com/cmd@v1.0.0). This causes go - run to build and run packages in module-aware mode, ignoring the - go.mod file in the current directory or any parent directory, if - there is one. This is useful for running executables without installing them or - without changing dependencies of the current module. -

- -

Gofmt

- -

- gofmt (and go fmt) now synchronizes - //go:build lines with // +build lines. If a file - only has // +build lines, they will be moved to the appropriate - location in the file, and matching //go:build lines will be - added. Otherwise, // +build lines will be overwritten based on - any existing //go:build lines. For more information, see - https://golang.org/design/draft-gobuild. -

- -

Vet

- -

New warning for mismatched //go:build and // +build lines

- -

- The vet tool now verifies that //go:build and - // +build lines are in the correct part of the file and - synchronized with each other. If they aren't, - gofmt can be used to fix them. For more - information, see - https://golang.org/design/draft-gobuild. -

- -

New warning for calling signal.Notify on unbuffered channels

- -

- The vet tool now warns about calls to signal.Notify - with incoming signals being sent to an unbuffered channel. Using an unbuffered channel - risks missing signals sent on them as signal.Notify does not block when - sending to a channel. For example: -

- -
-c := make(chan os.Signal)
-// signals are sent on c before the channel is read from.
-// This signal may be dropped as c is unbuffered.
-signal.Notify(c, os.Interrupt)
-
- -

- Users of signal.Notify should use channels with sufficient buffer space to keep up with the - expected signal rate. -

- -

New warnings for Is, As and Unwrap methods

- -

- The vet tool now warns about methods named As, Is or Unwrap - on types implementing the error interface that have a different signature than the - one expected by the errors package. The errors.{As,Is,Unwrap} functions - expect such methods to implement either Is(error) bool, - As(interface{}) bool, or Unwrap() error - respectively. The functions errors.{As,Is,Unwrap} will ignore methods with the same - names but a different signature. For example: -

- -
-type MyError struct { hint string }
-func (m MyError) Error() string { ... } // MyError implements error.
-func (MyError) Is(target interface{}) bool { ... } // target is interface{} instead of error.
-func Foo() bool {
-	x, y := MyError{"A"}, MyError{"B"}
-	return errors.Is(x, y) // returns false as x != y and MyError does not have an `Is(error) bool` function.
-}
-
- -

Cover

- -

- The cover tool now uses an optimized parser - from golang.org/x/tools/cover, which may be noticeably faster - when parsing large coverage profiles. -

- -

Compiler

- -

- Go 1.17 implements a new way of passing function arguments and results using - registers instead of the stack. - Benchmarks for a representative set of Go packages and programs show - performance improvements of about 5%, and a typical reduction in - binary size of about 2%. - This is currently enabled for Linux, macOS, and Windows on the - 64-bit x86 architecture (the linux/amd64, - darwin/amd64, and windows/amd64 ports). -

- -

- This change does not affect the functionality of any safe Go code - and is designed to have no impact on most assembly code. - It may affect code that violates - the unsafe.Pointer - rules when accessing function arguments, or that depends on - undocumented behavior involving comparing function code pointers. - To maintain compatibility with existing assembly functions, the - compiler generates adapter functions that convert between the new - register-based calling convention and the previous stack-based - calling convention. - These adapters are typically invisible to users, except that taking - the address of a Go function in assembly code or taking the address - of an assembly function in Go code - using reflect.ValueOf(fn).Pointer() - or unsafe.Pointer will now return the address of the - adapter. - Code that depends on the value of these code pointers may no longer - behave as expected. - Adapters also may cause a very small performance overhead in two - cases: calling an assembly function indirectly from Go via - a func value, and calling Go functions from assembly. -

- -

- The format of stack traces from the runtime (printed when an uncaught panic - occurs, or when runtime.Stack is called) is improved. Previously, - the function arguments were printed as hexadecimal words based on the memory - layout. Now each argument in the source code is printed separately, separated - by commas. Aggregate-typed (struct, array, string, slice, interface, and complex) - arguments are delimited by curly braces. A caveat is that the value of an - argument that only lives in a register and is not stored to memory may be - inaccurate. Function return values (which were usually inaccurate) are no longer - printed. -

- -

- Functions containing closures can now be inlined. - One effect of this change is that a function with a closure may - produce a distinct closure code pointer for each place that the - function is inlined. - Go function values are not directly comparable, but this change - could reveal bugs in code that uses reflect - or unsafe.Pointer to bypass this language restriction - and compare functions by code pointer. -

- - - -

- When the linker uses external linking mode, which is the default - when linking a program that uses cgo, and the linker is invoked - with a -I option, the option will now be passed to the - external linker as a -Wl,--dynamic-linker option. -

- -

Core library

- -

Cgo

- -

- The runtime/cgo package now provides a - new facility that allows to turn any Go values to a safe representation - that can be used to pass values between C and Go safely. See - runtime/cgo.Handle for more information. -

- -

URL query parsing

- - -

- The net/url and net/http packages used to accept - ";" (semicolon) as a setting separator in URL queries, in - addition to "&" (ampersand). Now, settings with non-percent-encoded - semicolons are rejected and net/http servers will log a warning to - Server.ErrorLog - when encountering one in a request URL. -

- -

- For example, before Go 1.17 the Query - method of the URL example?a=1;b=2&c=3 would have returned - map[a:[1] b:[2] c:[3]], while now it returns map[c:[3]]. -

- -

- When encountering such a query string, - URL.Query - and - Request.FormValue - ignore any settings that contain a semicolon, - ParseQuery - returns the remaining settings and an error, and - Request.ParseForm - and - Request.ParseMultipartForm - return an error but still set Request fields based on the - remaining settings. -

- -

- net/http users can restore the original behavior by using the new - AllowQuerySemicolons - handler wrapper. This will also suppress the ErrorLog warning. - Note that accepting semicolons as query separators can lead to security issues - if different systems interpret cache keys differently. - See issue 25192 for more information. -

- -

TLS strict ALPN

- - -

- When Config.NextProtos - is set, servers now enforce that there is an overlap between the configured - protocols and the ALPN protocols advertised by the client, if any. If there is - no mutually supported protocol, the connection is closed with the - no_application_protocol alert, as required by RFC 7301. This - helps mitigate the ALPACA cross-protocol attack. -

- -

- As an exception, when the value "h2" is included in the server's - Config.NextProtos, HTTP/1.1 clients will be allowed to connect as - if they didn't support ALPN. - See issue 46310 for more information. -

- -

Minor changes to the library

- -

- As always, there are various minor changes and updates to the library, - made with the Go 1 promise of compatibility - in mind. -

- -
archive/zip
-
-

- The new methods File.OpenRaw, Writer.CreateRaw, Writer.Copy provide support for cases where performance is a primary concern. -

-
-
- -
bufio
-
-

- The Writer.WriteRune method - now writes the replacement character U+FFFD for negative rune values, - as it does for other invalid runes. -

-
-
- -
bytes
-
-

- The Buffer.WriteRune method - now writes the replacement character U+FFFD for negative rune values, - as it does for other invalid runes. -

-
-
- -
compress/lzw
-
-

- The NewReader - function is guaranteed to return a value of the new - type Reader, - and similarly NewWriter - is guaranteed to return a value of the new - type Writer. - These new types both implement a Reset method - (Reader.Reset, - Writer.Reset) - that allows reuse of the Reader or Writer. -

-
-
- -
crypto/ed25519
-
-

- The crypto/ed25519 package has been rewritten, and all - operations are now approximately twice as fast on amd64 and arm64. - The observable behavior has not otherwise changed. -

-
-
- -
crypto/elliptic
-
-

- CurveParams - methods now automatically invoke faster and safer dedicated - implementations for known curves (P-224, P-256, and P-521) when - available. Note that this is a best-effort approach and applications - should avoid using the generic, not constant-time CurveParams - methods and instead use dedicated - Curve implementations - such as P256. -

- -

- The P521 curve - implementation has been rewritten using code generated by the - fiat-crypto project, - which is based on a formally-verified model of the arithmetic - operations. It is now constant-time and three times faster on amd64 and - arm64. The observable behavior has not otherwise changed. -

-
-
- -
crypto/rand
-
-

- The crypto/rand package now uses the getentropy - syscall on macOS and the getrandom syscall on Solaris, - Illumos, and DragonFlyBSD. -

-
-
- -
crypto/tls
-
-

- The new Conn.HandshakeContext - method allows the user to control cancellation of an in-progress TLS - handshake. The provided context is accessible from various callbacks through the new - ClientHelloInfo.Context and - CertificateRequestInfo.Context - methods. Canceling the context after the handshake has finished has no effect. -

- -

- Cipher suite ordering is now handled entirely by the - crypto/tls package. Currently, cipher suites are sorted based - on their security, performance, and hardware support taking into account - both the local and peer's hardware. The order of the - Config.CipherSuites - field is now ignored, as well as the - Config.PreferServerCipherSuites - field. Note that Config.CipherSuites still allows - applications to choose what TLS 1.0–1.2 cipher suites to enable. -

- -

- The 3DES cipher suites have been moved to - InsecureCipherSuites - due to fundamental block size-related - weakness. They are still enabled by default but only as a last resort, - thanks to the cipher suite ordering change above. -

- -

- Beginning in the next release, Go 1.18, the - Config.MinVersion - for crypto/tls clients will default to TLS 1.2, disabling TLS 1.0 - and TLS 1.1 by default. Applications will be able to override the change by - explicitly setting Config.MinVersion. - This will not affect crypto/tls servers. -

-
-
- -
crypto/x509
-
-

- CreateCertificate - now returns an error if the provided private key doesn't match the - parent's public key, if any. The resulting certificate would have failed - to verify. -

- -

- The temporary GODEBUG=x509ignoreCN=0 flag has been removed. -

- -

- ParseCertificate - has been rewritten, and now consumes ~70% fewer resources. The observable - behavior has not otherwise changed, except for error messages. -

- -

- On BSD systems, /etc/ssl/certs is now searched for trusted - roots. This adds support for the new system trusted certificate store in - FreeBSD 12.2+. -

- -

- Beginning in the next release, Go 1.18, crypto/x509 will - reject certificates signed with the SHA-1 hash function. This doesn't - apply to self-signed root certificates. Practical attacks against SHA-1 - have been demonstrated in 2017 and publicly - trusted Certificate Authorities have not issued SHA-1 certificates since 2015. -

-
-
- -
database/sql
-
-

- The DB.Close method now closes - the connector field if the type in this field implements the - io.Closer interface. -

- -

- The new - NullInt16 - and - NullByte - structs represent the int16 and byte values that may be null. These can be used as - destinations of the Scan method, - similar to NullString. -

-
-
- -
debug/elf
-
-

- The SHT_MIPS_ABIFLAGS - constant has been added. -

-
-
- -
encoding/binary
-
-

- binary.Uvarint will stop reading after 10 bytes to avoid - wasted computations. If more than 10 bytes are needed, the byte count returned is -11. -
- Previous Go versions could return larger negative counts when reading incorrectly encoded varints. -

-
-
- -
encoding/csv
-
-

- The new - Reader.FieldPos - method returns the line and column corresponding to the start of - a given field in the record most recently returned by - Read. -

-
-
- -
encoding/xml
-
-

- When a comment appears within a - Directive, it is now replaced - with a single space instead of being completely elided. -

- -

- Invalid element or attribute names with leading, trailing, or multiple - colons are now stored unmodified into the - Name.Local field. -

-
-
- -
flag
-
-

- Flag declarations now panic if an invalid name is specified. -

-
-
- -
go/build
-
-

- The new - Context.ToolTags - field holds the build tags appropriate to the current Go - toolchain configuration. -

-
-
- -
go/format
-
-

- The Source and - Node functions now - synchronize //go:build lines with // +build - lines. If a file only has // +build lines, they will be - moved to the appropriate location in the file, and matching - //go:build lines will be added. Otherwise, - // +build lines will be overwritten based on any existing - //go:build lines. For more information, see - https://golang.org/design/draft-gobuild. -

-
-
- -
go/parser
-
-

- The new SkipObjectResolution - Mode value instructs the parser not to resolve identifiers to - their declaration. This may improve parsing speed. -

-
-
- -
image
-
-

- The concrete image types (RGBA, Gray16 and so on) - now implement a new RGBA64Image - interface. The concrete types that previously implemented - draw.Image now also implement - draw.RGBA64Image, a - new interface in the image/draw package. -

-
-
- -
io/fs
-
-

- The new FileInfoToDirEntry function converts a FileInfo to a DirEntry. -

-
-
- -
math
-
-

- The math package now defines three more constants: MaxUint, MaxInt and MinInt. - For 32-bit systems their values are 2^32 - 1, 2^31 - 1 and -2^31, respectively. - For 64-bit systems their values are 2^64 - 1, 2^63 - 1 and -2^63, respectively. -

-
-
- -
mime
-
-

- On Unix systems, the table of MIME types is now read from the local system's - Shared MIME-info Database - when available. -

-
-
- -
mime/multipart
-
-

- Part.FileName - now applies - filepath.Base to the - return value. This mitigates potential path traversal vulnerabilities in - applications that accept multipart messages, such as net/http - servers that call - Request.FormFile. -

-
-
- -
net
-
-

- The new method IP.IsPrivate reports whether an address is - a private IPv4 address according to RFC 1918 - or a local IPv6 address according RFC 4193. -

- -

- The Go DNS resolver now only sends one DNS query when resolving an address for an IPv4-only or IPv6-only network, - rather than querying for both address families. -

- -

- The ErrClosed sentinel error and - ParseError error type now implement - the net.Error interface. -

- -

- The ParseIP and ParseCIDR - functions now reject IPv4 addresses which contain decimal components with leading zeros. - - These components were always interpreted as decimal, but some operating systems treat them as octal. - This mismatch could hypothetically lead to security issues if a Go application was used to validate IP addresses - which were then used in their original form with non-Go applications which interpreted components as octal. Generally, - it is advisable to always re-encode values after validation, which avoids this class of parser misalignment issues. -

-
-
- -
net/http
-
-

- The net/http package now uses the new - (*tls.Conn).HandshakeContext - with the Request context - when performing TLS handshakes in the client or server. -

- -

- Setting the Server - ReadTimeout or WriteTimeout fields to a negative value now indicates no timeout - rather than an immediate timeout. -

- -

- The ReadRequest function - now returns an error when the request has multiple Host headers. -

- -

- When producing a redirect to the cleaned version of a URL, - ServeMux now always - uses relative URLs in the Location header. Previously it - would echo the full URL of the request, which could lead to unintended - redirects if the client could be made to send an absolute request URL. -

- -

- When interpreting certain HTTP headers handled by net/http, - non-ASCII characters are now ignored or rejected. -

- -

- If - Request.ParseForm - returns an error when called by - Request.ParseMultipartForm, - the latter now continues populating - Request.MultipartForm - before returning it. -

-
-
- -
net/http/httptest
-
-

- ResponseRecorder.WriteHeader - now panics when the provided code is not a valid three-digit HTTP status code. - This matches the behavior of ResponseWriter - implementations in the net/http package. -

-
-
- -
net/url
-
-

- The new method Values.Has - reports whether a query parameter is set. -

-
-
- -
os
-
-

- The File.WriteString method - has been optimized to not make a copy of the input string. -

-
-
- -
reflect
-
-

- The new - Value.CanConvert - method reports whether a value can be converted to a type. - This may be used to avoid a panic when converting a slice to an - array pointer type if the slice is too short. - Previously it was sufficient to use - Type.ConvertibleTo - for this, but the newly permitted conversion from slice to array - pointer type can panic even if the types are convertible. -

- -

- The new - StructField.IsExported - and - Method.IsExported - methods report whether a struct field or type method is exported. - They provide a more readable alternative to checking whether PkgPath - is empty. -

- -

- The new VisibleFields function - returns all the visible fields in a struct type, including fields inside anonymous struct members. -

- -

- The ArrayOf function now panics when - called with a negative length. -

- -

- Checking the Type.ConvertibleTo method - is no longer sufficient to guarantee that a call to - Value.Convert will not panic. - It may panic when converting `[]T` to `*[N]T` if the slice's length is less than N. - See the language changes section above. -

-
-
- -
runtime/metrics
-
-

- New metrics were added that track total bytes and objects allocated and freed. - A new metric tracking the distribution of goroutine scheduling latencies was - also added. -

-
-
- -
runtime/pprof
-
-

- Block profiles are no longer biased to favor infrequent long events over - frequent short events. -

-
-
- -
strconv
-
-

- The strconv package now uses Ulf Adams's Ryū algorithm for formatting floating-point numbers. - This algorithm improves performance on most inputs and is more than 99% faster on worst-case inputs. -

- -

- The new QuotedPrefix function - returns the quoted string (as understood by - Unquote) - at the start of input. -

-
-
- -
strings
-
-

- The Builder.WriteRune method - now writes the replacement character U+FFFD for negative rune values, - as it does for other invalid runes. -

-
-
- -
sync/atomic
-
-

- atomic.Value now has Swap and - CompareAndSwap methods that provide - additional atomic operations. -

-
-
- -
syscall
-
-

-

- The GetQueuedCompletionStatus and - PostQueuedCompletionStatus - functions are now deprecated. These functions have incorrect signatures and are superseded by - equivalents in the golang.org/x/sys/windows package. -

- -

- On Unix-like systems, the process group of a child process is now set with signals blocked. - This avoids sending a SIGTTOU to the child when the parent is in a background process group. -

- -

- The Windows version of - SysProcAttr - has two new fields. AdditionalInheritedHandles is - a list of additional handles to be inherited by the new child - process. ParentProcess permits specifying the - parent process of the new process. - -

- The constant MSG_CMSG_CLOEXEC is now defined on - DragonFly and all OpenBSD systems (it was already defined on - some OpenBSD systems and all FreeBSD, NetBSD, and Linux systems). -

- -

- The constants SYS_WAIT6 and WEXITED - are now defined on NetBSD systems (SYS_WAIT6 was - already defined on DragonFly and FreeBSD systems; - WEXITED was already defined on Darwin, DragonFly, - FreeBSD, Linux, and Solaris systems). -

-
-
- -
testing
-
-

- Added a new testing flag -shuffle which controls the execution order of tests and benchmarks. -

-

- The new - T.Setenv - and B.Setenv - methods support setting an environment variable for the duration - of the test or benchmark. -

-
-
- -
text/template/parse
-
-

- The new SkipFuncCheck Mode - value changes the template parser to not verify that functions are defined. -

-
-
- -
time
-
-

- The Time type now has a - GoString method that - will return a more useful value for times when printed with the - %#v format specifier in the fmt package. -

- -

- The new Time.IsDST method can be used to check whether the time - is in Daylight Savings Time in its configured location. -

- -

- The new Time.UnixMilli and - Time.UnixMicro - methods return the number of milliseconds and microseconds elapsed since - January 1, 1970 UTC respectively. -
- The new UnixMilli and - UnixMicro functions - return the local Time corresponding to the given Unix time. -

- -

- The package now accepts comma "," as a separator for fractional seconds when parsing and formatting time. - For example, the following time layouts are now accepted: -

    -
  • 2006-01-02 15:04:05,999999999 -0700 MST
  • -
  • Mon Jan _2 15:04:05,000000 2006
  • -
  • Monday, January 2 15:04:05,000 2006
  • -
-

- -

- The new constant Layout - defines the reference time. -

-
-
- -
unicode
-
-

- The Is, - IsGraphic, - IsLetter, - IsLower, - IsMark, - IsNumber, - IsPrint, - IsPunct, - IsSpace, - IsSymbol, and - IsUpper functions - now return false on negative rune values, as they do for other invalid runes. -

-
-
diff --git a/doc/go1.18.html b/doc/go1.18.html new file mode 100644 index 0000000000..2dc4c1427d --- /dev/null +++ b/doc/go1.18.html @@ -0,0 +1,84 @@ + + + + + + +

DRAFT RELEASE NOTES — Introduction to Go 1.18

+ +

+ + Go 1.18 is not yet released. These are work-in-progress + release notes. Go 1.18 is expected to be released in February 2022. + +

+ +

Changes to the language

+ +

+ TODO: complete this section +

+ +

Ports

+ +

+ TODO: complete this section, or delete if not needed +

+ +

Tools

+ +

+ TODO: complete this section, or delete if not needed +

+ +

Go command

+ +

+ TODO: complete this section, or delete if not needed +

+ +

Runtime

+ +

+ TODO: complete this section, or delete if not needed +

+ +

Compiler

+ +

+ TODO: complete this section, or delete if not needed +

+ +

Linker

+ +

+ TODO: complete this section, or delete if not needed +

+ +

Core library

+ +

+ TODO: complete this section +

+ +

Minor changes to the library

+ +

+ As always, there are various minor changes and updates to the library, + made with the Go 1 promise of compatibility + in mind. +

+ +

+ TODO: complete this section +

-- GitLab From c92f5ee170e6f9c639f1ca684061a0cedde54108 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 12 May 2021 12:30:34 -0400 Subject: [PATCH 0703/2500] cmd/link: start at address 0 when external linking When external linking, we are creating an object file, instead of a executable. The absolute address is irrelevant. The external linker will set it up. Start at address 0. Change-Id: I3a2e0b8087b328d5c3144f29ca8ba6311aa39cba Reviewed-on: https://go-review.googlesource.com/c/go/+/319830 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/link/internal/ld/lib.go | 4 +++- src/cmd/link/internal/ld/pe.go | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 644faeb2fb..894e5afe63 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -697,7 +697,9 @@ func (ctxt *Link) linksetup() { Peinit(ctxt) } - if ctxt.HeadType == objabi.Hdarwin && ctxt.LinkMode == LinkExternal { + if ctxt.LinkMode == LinkExternal { + // When external linking, we are creating an object file. The + // absolute address is irrelevant. *FlagTextAddr = 0 } diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go index 8eb4231c3a..871bf8de2b 100644 --- a/src/cmd/link/internal/ld/pe.go +++ b/src/cmd/link/internal/ld/pe.go @@ -1061,6 +1061,8 @@ func Peinit(ctxt *Link) { // linker will honour that requirement. PESECTALIGN = 32 PEFILEALIGN = 0 + // We are creating an object file. The absolute address is irrelevant. + PEBASE = 0 } var sh [16]pe.SectionHeader32 -- GitLab From 5a401001417151649363a4b2fbd658f3f1957cba Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 13 Aug 2021 09:30:19 -0700 Subject: [PATCH 0704/2500] cmd/compile: fix dictionaries for nested closures Capturing dictionary closure variables is ok. Fixes #47684 Change-Id: I049c87117915e0c5a172b9665bfac2f91064b2d4 Reviewed-on: https://go-review.googlesource.com/c/go/+/342050 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/ir/name.go | 4 +++- test/typeparam/issue47684.go | 19 +++++++++++++++++++ test/typeparam/issue47684b.go | 23 +++++++++++++++++++++++ test/typeparam/issue47684c.go | 19 +++++++++++++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 test/typeparam/issue47684.go create mode 100644 test/typeparam/issue47684b.go create mode 100644 test/typeparam/issue47684c.go diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index a2eec05013..48fe572124 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -404,7 +404,9 @@ func CaptureName(pos src.XPos, fn *Func, n *Name) *Name { if n.Op() != ONAME || n.Curfn == nil { return n // okay to use directly } - if n.IsClosureVar() { + if n.IsClosureVar() && n.Sym().Name != ".dict" { + // Note: capturing dictionary closure variables is ok. This makes + // sure the generated code is correctly optimized. base.FatalfAt(pos, "misuse of CaptureName on closure variable: %v", n) } diff --git a/test/typeparam/issue47684.go b/test/typeparam/issue47684.go new file mode 100644 index 0000000000..2798b78ca8 --- /dev/null +++ b/test/typeparam/issue47684.go @@ -0,0 +1,19 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func f[G any]() int { + return func() int { + return func() int { + return 0 + }() + }() +} + +func main() { + f[int]() +} diff --git a/test/typeparam/issue47684b.go b/test/typeparam/issue47684b.go new file mode 100644 index 0000000000..c43ef8d169 --- /dev/null +++ b/test/typeparam/issue47684b.go @@ -0,0 +1,23 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func f[G any]() interface{} { + return func() interface{} { + return func() interface{} { + var x G + return x + }() + }() +} + +func main() { + x := f[int]() + if v, ok := x.(int); !ok || v != 0 { + panic("bad") + } +} diff --git a/test/typeparam/issue47684c.go b/test/typeparam/issue47684c.go new file mode 100644 index 0000000000..32f1b66087 --- /dev/null +++ b/test/typeparam/issue47684c.go @@ -0,0 +1,19 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func f[G any]() func()func()int { + return func() func()int { + return func() int { + return 0 + } + } +} + +func main() { + f[int]()()() +} -- GitLab From a0adf91d85bcb10fac394da063c8abc1c60d8eb2 Mon Sep 17 00:00:00 2001 From: Matt Layher Date: Mon, 9 Aug 2021 17:12:37 -0400 Subject: [PATCH 0705/2500] internal/syscall/unix: change Ioctl arg type to unsafe.Pointer on AIX Without this change, this code is technically in violation of the unsafe.Pointer rules since the conversion from unsafe.Pointer to uintptr has to happen when calling into the syscall6 assembly implementation. Change-Id: I4821f5bf9788c8fa2efeb041f811ed092e07ae74 Reviewed-on: https://go-review.googlesource.com/c/go/+/340949 Trust: Matt Layher Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/internal/syscall/unix/ioctl_aix.go | 2 +- src/net/interface_aix.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/internal/syscall/unix/ioctl_aix.go b/src/internal/syscall/unix/ioctl_aix.go index 19d56c36a1..d361533b5c 100644 --- a/src/internal/syscall/unix/ioctl_aix.go +++ b/src/internal/syscall/unix/ioctl_aix.go @@ -16,7 +16,7 @@ var libc_ioctl uintptr // Implemented in syscall/syscall_aix.go. func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno) -func Ioctl(fd int, cmd int, args uintptr) (err error) { +func Ioctl(fd int, cmd int, args unsafe.Pointer) (err error) { _, _, e1 := syscall6(uintptr(unsafe.Pointer(&libc_ioctl)), 3, uintptr(fd), uintptr(cmd), uintptr(args), 0, 0, 0) if e1 != 0 { err = e1 diff --git a/src/net/interface_aix.go b/src/net/interface_aix.go index 49f78c2abb..7ad45d1175 100644 --- a/src/net/interface_aix.go +++ b/src/net/interface_aix.go @@ -78,7 +78,7 @@ func interfaceTable(ifindex int) ([]Interface, error) { // Retrieve MTU ifr := &ifreq{} copy(ifr.Name[:], ifi.Name) - err = unix.Ioctl(sock, syscall.SIOCGIFMTU, uintptr(unsafe.Pointer(ifr))) + err = unix.Ioctl(sock, syscall.SIOCGIFMTU, unsafe.Pointer(ifr)) if err != nil { return nil, err } -- GitLab From 850768bbc9fd2d74a88233fa1f46791d08d1afc8 Mon Sep 17 00:00:00 2001 From: astraw99 Date: Mon, 16 Aug 2021 09:54:40 +0000 Subject: [PATCH 0706/2500] time: update current time comment In the time package, the ticker and timer both send current time to channel C, so this PR update the comment to understand them better. Change-Id: I99846a40bf8ef780bf0062dd84cf721b3b892a1b GitHub-Last-Rev: 535da54b8ebd25be22289699212364df0aa49c7f GitHub-Pull-Request: golang/go#47597 Reviewed-on: https://go-review.googlesource.com/c/go/+/340649 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Trust: Dmitri Shuralyov --- src/time/sleep.go | 6 +----- src/time/tick.go | 6 +++--- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/time/sleep.go b/src/time/sleep.go index 4f45799414..b467d1d589 100644 --- a/src/time/sleep.go +++ b/src/time/sleep.go @@ -139,12 +139,8 @@ func (t *Timer) Reset(d Duration) bool { return resetTimer(&t.r, w) } +// sendTime does a non-blocking send of the current time on c. func sendTime(c interface{}, seq uintptr) { - // Non-blocking send of time on c. - // Used in NewTimer, it cannot block anyway (buffer). - // Used in NewTicker, dropping sends on the floor is - // the desired behavior when the reader gets behind, - // because the sends are periodic. select { case c.(chan Time) <- Now(): default: diff --git a/src/time/tick.go b/src/time/tick.go index 81d2a43f28..f9522b0b75 100644 --- a/src/time/tick.go +++ b/src/time/tick.go @@ -14,9 +14,9 @@ type Ticker struct { } // NewTicker returns a new Ticker containing a channel that will send -// the time on the channel after each tick. The period of the ticks is -// specified by the duration argument. The ticker will adjust the time -// interval or drop ticks to make up for slow receivers. +// the current time on the channel after each tick. The period of the +// ticks is specified by the duration argument. The ticker will adjust +// the time interval or drop ticks to make up for slow receivers. // The duration d must be greater than zero; if not, NewTicker will // panic. Stop the ticker to release associated resources. func NewTicker(d Duration) *Ticker { -- GitLab From 5c7a460a1c108e5bf7a99817b86ebded7ce81812 Mon Sep 17 00:00:00 2001 From: Matt Layher Date: Wed, 21 Jul 2021 16:03:34 -0400 Subject: [PATCH 0707/2500] syscall: hoist Getsockname out of NetlinkRIB loops Calling Getsockname once to fetch the Pid field from the *SockaddrNetlink is necessary, but this data will remain static for the rest of the netlink socket's lifetime. Moving this call and type assertion outside of the inner loops will remove a number of unnecessary system calls. Change-Id: I7e7e81866af1a31fccdaaf7531efd6cc4cbb8926 Reviewed-on: https://go-review.googlesource.com/c/go/+/336369 Run-TryBot: Matt Layher TryBot-Result: Go Bot Trust: Matt Layher Reviewed-by: Tobias Klauser --- src/syscall/netlink_linux.go | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/syscall/netlink_linux.go b/src/syscall/netlink_linux.go index 0937ff797a..2d810705bf 100644 --- a/src/syscall/netlink_linux.go +++ b/src/syscall/netlink_linux.go @@ -55,14 +55,22 @@ func NetlinkRIB(proto, family int) ([]byte, error) { return nil, err } defer Close(s) - lsa := &SockaddrNetlink{Family: AF_NETLINK} - if err := Bind(s, lsa); err != nil { + sa := &SockaddrNetlink{Family: AF_NETLINK} + if err := Bind(s, sa); err != nil { return nil, err } wb := newNetlinkRouteRequest(proto, 1, family) - if err := Sendto(s, wb, 0, lsa); err != nil { + if err := Sendto(s, wb, 0, sa); err != nil { return nil, err } + lsa, err := Getsockname(s) + if err != nil { + return nil, err + } + lsanl, ok := lsa.(*SockaddrNetlink) + if !ok { + return nil, EINVAL + } var tab []byte rbNew := make([]byte, Getpagesize()) done: @@ -82,16 +90,7 @@ done: return nil, err } for _, m := range msgs { - lsa, err := Getsockname(s) - if err != nil { - return nil, err - } - switch v := lsa.(type) { - case *SockaddrNetlink: - if m.Header.Seq != 1 || m.Header.Pid != v.Pid { - return nil, EINVAL - } - default: + if m.Header.Seq != 1 || m.Header.Pid != lsanl.Pid { return nil, EINVAL } if m.Header.Type == NLMSG_DONE { -- GitLab From e61d1445ab2304e2d6e4711f8477061192d5942c Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Mon, 16 Aug 2021 02:15:28 +0700 Subject: [PATCH 0708/2500] cmd/compile: fix panic with dead hidden closures Currently, for hidden closures, we always push them to compile queue during typechecking. If the hidden closure is discarded from the outer function body during deadcode, any desugaring phase after deadcode won't be applied to the closure. Thus, some un-expected OPs are passed to downstream passes, which they can't handle, the compiler goes boom! To fix this, we keep track of discarded hidden closures during deadcode pass, and won't compile them then. Fixes #47712 Change-Id: I078717d5d1f4f2fa39cbaf610cfffbb042e70ceb Reviewed-on: https://go-review.googlesource.com/c/go/+/342350 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/deadcode/deadcode.go | 13 +++++++++++ src/cmd/compile/internal/gc/main.go | 4 ++++ src/cmd/compile/internal/ir/func.go | 3 +++ test/fixedbugs/issue47712.go | 23 +++++++++++++++++++ 4 files changed, 43 insertions(+) create mode 100644 test/fixedbugs/issue47712.go diff --git a/src/cmd/compile/internal/deadcode/deadcode.go b/src/cmd/compile/internal/deadcode/deadcode.go index 520203787f..3658c89912 100644 --- a/src/cmd/compile/internal/deadcode/deadcode.go +++ b/src/cmd/compile/internal/deadcode/deadcode.go @@ -38,6 +38,7 @@ func Func(fn *ir.Func) { } } + ir.VisitList(fn.Body, markHiddenClosureDead) fn.Body = []ir.Node{ir.NewBlockStmt(base.Pos, nil)} } @@ -62,9 +63,11 @@ func stmts(nn *ir.Nodes) { if ir.IsConst(n.Cond, constant.Bool) { var body ir.Nodes if ir.BoolVal(n.Cond) { + ir.VisitList(n.Else, markHiddenClosureDead) n.Else = ir.Nodes{} body = n.Body } else { + ir.VisitList(n.Body, markHiddenClosureDead) n.Body = ir.Nodes{} body = n.Else } @@ -150,3 +153,13 @@ func expr(n ir.Node) ir.Node { } return n } + +func markHiddenClosureDead(n ir.Node) { + if n.Op() != ir.OCLOSURE { + return + } + clo := n.(*ir.ClosureExpr) + if clo.Func.IsHiddenClosure() { + clo.Func.SetIsDeadcodeClosure(true) + } +} diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 6a373ce33d..9660ef9dd5 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -289,6 +289,10 @@ func Main(archInit func(*ssagen.ArchInfo)) { fcount := int64(0) for i := 0; i < len(typecheck.Target.Decls); i++ { if fn, ok := typecheck.Target.Decls[i].(*ir.Func); ok { + // Don't try compiling dead hidden closure. + if fn.IsDeadcodeClosure() { + continue + } enqueueFunc(fn) fcount++ } diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go index 269b6f14ec..18d0b023ad 100644 --- a/src/cmd/compile/internal/ir/func.go +++ b/src/cmd/compile/internal/ir/func.go @@ -196,6 +196,7 @@ const ( // true if closure inside a function; false if a simple function or a // closure in a global variable initialization funcIsHiddenClosure + funcIsDeadcodeClosure // true if closure is deadcode funcHasDefer // contains a defer statement funcNilCheckDisabled // disable nil checks when compiling this function funcInlinabilityChecked // inliner has already determined whether the function is inlinable @@ -216,6 +217,7 @@ func (f *Func) ABIWrapper() bool { return f.flags&funcABIWrapper ! func (f *Func) Needctxt() bool { return f.flags&funcNeedctxt != 0 } func (f *Func) ReflectMethod() bool { return f.flags&funcReflectMethod != 0 } func (f *Func) IsHiddenClosure() bool { return f.flags&funcIsHiddenClosure != 0 } +func (f *Func) IsDeadcodeClosure() bool { return f.flags&funcIsDeadcodeClosure != 0 } func (f *Func) HasDefer() bool { return f.flags&funcHasDefer != 0 } func (f *Func) NilCheckDisabled() bool { return f.flags&funcNilCheckDisabled != 0 } func (f *Func) InlinabilityChecked() bool { return f.flags&funcInlinabilityChecked != 0 } @@ -230,6 +232,7 @@ func (f *Func) SetABIWrapper(b bool) { f.flags.set(funcABIWrapper, func (f *Func) SetNeedctxt(b bool) { f.flags.set(funcNeedctxt, b) } func (f *Func) SetReflectMethod(b bool) { f.flags.set(funcReflectMethod, b) } func (f *Func) SetIsHiddenClosure(b bool) { f.flags.set(funcIsHiddenClosure, b) } +func (f *Func) SetIsDeadcodeClosure(b bool) { f.flags.set(funcIsDeadcodeClosure, b) } func (f *Func) SetHasDefer(b bool) { f.flags.set(funcHasDefer, b) } func (f *Func) SetNilCheckDisabled(b bool) { f.flags.set(funcNilCheckDisabled, b) } func (f *Func) SetInlinabilityChecked(b bool) { f.flags.set(funcInlinabilityChecked, b) } diff --git a/test/fixedbugs/issue47712.go b/test/fixedbugs/issue47712.go new file mode 100644 index 0000000000..81a2681592 --- /dev/null +++ b/test/fixedbugs/issue47712.go @@ -0,0 +1,23 @@ +// compile + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func f() { + if false { + defer func() { + _ = recover() + }() + } +} + +func g() { + for false { + defer func() { + _ = recover() + }() + } +} -- GitLab From fda8ee8b077dd8a5819cac7c52c3af1499a0674e Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sun, 15 Aug 2021 21:50:42 -0400 Subject: [PATCH 0709/2500] go/types: make Interface.Complete a no-op This is a partial port of CL 340255 to go/types. Of course we can't delete Interface.Complete, but make it a no-op. Completing interfaces is no longer necessary. Change-Id: Ida3c84cc94713f14a646c7682f5d4ae5339a0faa Reviewed-on: https://go-review.googlesource.com/c/go/+/342489 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/internal/gcimporter/iimport.go | 4 ---- src/go/types/interface.go | 18 ++++-------------- src/go/types/issues_test.go | 3 ++- 3 files changed, 6 insertions(+), 19 deletions(-) diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go index dbc9b3a83e..5f05e8c0ad 100644 --- a/src/go/internal/gcimporter/iimport.go +++ b/src/go/internal/gcimporter/iimport.go @@ -174,10 +174,6 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, dataRea p.doDecl(localpkg, name) } - for _, typ := range p.interfaceList { - typ.Complete() - } - // record all referenced packages as imports list := append(([]*types.Package)(nil), pkgList[1:]...) sort.Sort(byPath(list)) diff --git a/src/go/types/interface.go b/src/go/types/interface.go index 510c123e97..f4d560cb3e 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -104,22 +104,12 @@ func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() } // IsConstraint reports whether interface t is not just a method set. func (t *Interface) IsConstraint() bool { return !t.typeSet().IsMethodSet() } -// Complete computes the interface's type set. It must be called by users of -// NewInterfaceType and NewInterface after the interface's embedded types are -// fully defined and before using the interface type in any way other than to -// form other types. The interface must not contain duplicate methods or a -// panic occurs. Complete returns the receiver. +// Complete just returns its receiver. There's no other effect. // -// Deprecated: Type sets are now computed lazily, on demand; this function -// is only here for backward-compatibility. It does not have to -// be called explicitly anymore. +// Deprecated: Interfaces are now completed on demand; this function is only +// here for backward-compatibility. It does not have to be called explicitly +// anymore. func (t *Interface) Complete() *Interface { - // Some tests are still depending on the state change - // (string representation of an Interface not containing an - // /* incomplete */ marker) caused by the explicit Complete - // call, so we compute the type set eagerly here. - t.complete = true - t.typeSet() return t } diff --git a/src/go/types/issues_test.go b/src/go/types/issues_test.go index 51995af30a..618db13fb9 100644 --- a/src/go/types/issues_test.go +++ b/src/go/types/issues_test.go @@ -405,8 +405,9 @@ func TestIssue28282(t *testing.T) { // create type interface { error } et := Universe.Lookup("error").Type() it := NewInterfaceType(nil, []Type{et}) - it.Complete() // verify that after completing the interface, the embedded method remains unchanged + // (interfaces are "completed" lazily now, so the completion happens implicitly when + // accessing Method(0)) want := et.Underlying().(*Interface).Method(0) got := it.Method(0) if got != want { -- GitLab From 9ff61acbd76733ec065cb1185608aa5564f2685a Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 16 Aug 2021 09:36:49 -0400 Subject: [PATCH 0710/2500] go/types,types2: superficial changes to align types and types2 This CL contains an assortment of superficial fixes noticed while self-reviewing the most recent stack of ports. It also makes a couple adjustments to termlist_test.go, in both go/types and cmd/compile/internal/types2. Change-Id: I64c8cda5e1704e86ac11c6ffc86d55248f44ef79 Reviewed-on: https://go-review.googlesource.com/c/go/+/342490 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/termlist_test.go | 4 ++-- src/go/types/builtins.go | 1 - src/go/types/termlist_test.go | 6 +++--- src/go/types/typestring.go | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/cmd/compile/internal/types2/termlist_test.go b/src/cmd/compile/internal/types2/termlist_test.go index 2f3772ddeb..ed1330d26f 100644 --- a/src/cmd/compile/internal/types2/termlist_test.go +++ b/src/cmd/compile/internal/types2/termlist_test.go @@ -11,7 +11,7 @@ import ( // maketl makes a term list from a string of the term list. func maketl(s string) termlist { - s = strings.Replace(s, " ", "", -1) + s = strings.ReplaceAll(s, " ", "") names := strings.Split(s, "∪") r := make(termlist, len(names)) for i, n := range names { @@ -20,7 +20,7 @@ func maketl(s string) termlist { return r } -func TestTermlistTop(t *testing.T) { +func TestTermlistAll(t *testing.T) { if !allTermlist.isAll() { t.Errorf("allTermlist is not the set of all types") } diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 2099a92acb..a11f395947 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -848,7 +848,6 @@ func makeSig(res Type, args ...Type) *Signature { // arrayPtrDeref returns A if typ is of the form *A and A is an array; // otherwise it returns typ. -// func arrayPtrDeref(typ Type) Type { if p, ok := typ.(*Pointer); ok { if a := asArray(p.base); a != nil { diff --git a/src/go/types/termlist_test.go b/src/go/types/termlist_test.go index ba0faff359..d1fe28f728 100644 --- a/src/go/types/termlist_test.go +++ b/src/go/types/termlist_test.go @@ -11,7 +11,7 @@ import ( // maketl makes a term list from a string of the term list. func maketl(s string) termlist { - s = strings.Replace(s, " ", "", -1) + s = strings.ReplaceAll(s, " ", "") names := strings.Split(s, "∪") r := make(termlist, len(names)) for i, n := range names { @@ -20,9 +20,9 @@ func maketl(s string) termlist { return r } -func TestTermlistTop(t *testing.T) { +func TestTermlistAll(t *testing.T) { if !allTermlist.isAll() { - t.Errorf("topTermlist is not top") + t.Errorf("allTermlist is not the set of all types") } } diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index c38cfd4290..452c92f74d 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -86,7 +86,6 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { break } } - buf.WriteString(t.name) case *Array: @@ -147,6 +146,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { case *Interface: buf.WriteString("interface{") first := true + // print explicit interface methods and embedded types for _, m := range t.methods { if !first { buf.WriteString("; ") -- GitLab From aab1d1fcb9f7e77191085a192b2d0c061fd42df2 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 16 Aug 2021 10:49:10 -0400 Subject: [PATCH 0711/2500] go/types: expand is only required for *Named types This is a port of CL 340749 to go/types. Change-Id: I2af602d357486ee2f45b91c11c4b02ec6b58ed38 Reviewed-on: https://go-review.googlesource.com/c/go/+/342474 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/types/builtins.go | 2 +- src/go/types/expr.go | 1 - src/go/types/named.go | 9 --------- src/go/types/predicates.go | 6 ++---- src/go/types/signature.go | 2 +- src/go/types/type.go | 5 ++++- src/go/types/typexpr.go | 3 +-- src/go/types/unify.go | 6 ++---- src/go/types/union.go | 11 +++++------ 9 files changed, 16 insertions(+), 29 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index a11f395947..9c772d3844 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -47,7 +47,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b default: // make argument getter xlist, _ := check.exprList(call.Args, false) - arg = func(x *operand, i int) { *x = *xlist[i]; x.typ = expand(x.typ) } + arg = func(x *operand, i int) { *x = *xlist[i] } nargs = len(xlist) // evaluate first argument, if present if nargs > 0 { diff --git a/src/go/types/expr.go b/src/go/types/expr.go index c9a55aa871..5bb9b7c280 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -621,7 +621,6 @@ func (check *Checker) convertUntyped(x *operand, target Type) { // If x is a constant operand, the returned constant.Value will be the // representation of x in this context. func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, constant.Value, errorCode) { - target = expand(target) if x.mode == invalid || isTyped(x.typ) || target == Typ[Invalid] { return x.typ, nil, 0 } diff --git a/src/go/types/named.go b/src/go/types/named.go index 020b9827e8..791ab78778 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -285,12 +285,3 @@ func (n *Named) expand() { n.instance = nil } } - -// expand expands uninstantiated named types and leaves all other types alone. -// expand does not recurse. -func expand(typ Type) Type { - if t, _ := typ.(*Named); t != nil { - t.expand() - } - return typ -} diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 5a2c08322f..d7adca1d33 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -140,10 +140,6 @@ func (p *ifacePair) identical(q *ifacePair) bool { // For changes to this code the corresponding changes should be made to unifier.nify. func identical(x, y Type, cmpTags bool, p *ifacePair) bool { - // types must be expanded for comparison - x = expand(x) - y = expand(y) - if x == y { return true } @@ -306,6 +302,8 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { // Two named types are identical if their type names originate // in the same type declaration. if y, ok := y.(*Named); ok { + x.expand() + y.expand() // TODO(gri) Why is x == y not sufficient? And if it is, // we can just return false here because x == y // is caught in the very beginning of this function. diff --git a/src/go/types/signature.go b/src/go/types/signature.go index 4624b54acb..f0a9f011ea 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -198,7 +198,6 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast // TODO(gri) We should delay rtyp expansion to when we actually need the // receiver; thus all checks here should be delayed to later. rtyp, _ := deref(recv.typ) - rtyp = expand(rtyp) // spec: "The receiver type must be of the form T or *T where T is a type name." // (ignore invalid types - error was reported before) @@ -206,6 +205,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast var err string switch T := rtyp.(type) { case *Named: + T.expand() // spec: "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." diff --git a/src/go/types/type.go b/src/go/types/type.go index c042a819b8..87242ccf62 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -113,7 +113,10 @@ func asInterface(t Type) *Interface { } func asNamed(t Type) *Named { - e, _ := expand(t).(*Named) + e, _ := t.(*Named) + if e != nil { + e.expand() + } return e } diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 03dd7c26c4..f14fbe1877 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -435,8 +435,7 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named // make sure we check instantiation works at least once // and that the resulting type is valid check.later(func() { - t := expand(typ) - check.validType(t, nil) + check.validType(typ, nil) }) return typ diff --git a/src/go/types/unify.go b/src/go/types/unify.go index a94a5f35c6..0be4d3a62a 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -226,10 +226,6 @@ func (u *unifier) nifyEq(x, y Type, p *ifacePair) bool { // code the corresponding changes should be made here. // Must not be called directly from outside the unifier. func (u *unifier) nify(x, y Type, p *ifacePair) bool { - // types must be expanded for comparison - x = expand(x) - y = expand(y) - if !u.exact { // If exact unification is known to fail because we attempt to // match a type name against an unnamed type literal, consider @@ -433,6 +429,8 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { // return x.obj == y.obj // } if y, ok := y.(*Named); ok { + x.expand() + y.expand() // TODO(gri) This is not always correct: two types may have the same names // in the same package if one of them is nested in a function. // Extremely unlikely but we need an always correct solution. diff --git a/src/go/types/union.go b/src/go/types/union.go index a0cf33c938..1ba99adaca 100644 --- a/src/go/types/union.go +++ b/src/go/types/union.go @@ -71,8 +71,7 @@ func parseUnion(check *Checker, tlist []ast.Expr) Type { // Note: This is a quadratic algorithm, but unions tend to be short. check.later(func() { for i, t := range terms { - typ := expand(t.typ) - if typ == Typ[Invalid] { + if t.typ == Typ[Invalid] { continue } @@ -88,16 +87,16 @@ func parseUnion(check *Checker, tlist []ast.Expr) Type { } } - u := under(typ) + u := under(t.typ) f, _ := u.(*Interface) if t.tilde { if f != nil { - check.errorf(x, _Todo, "invalid use of ~ (%s is an interface)", typ) + check.errorf(x, _Todo, "invalid use of ~ (%s is an interface)", t.typ) continue // don't report another error for t } - if !Identical(u, typ) { - check.errorf(x, _Todo, "invalid use of ~ (underlying type of %s is %s)", typ, u) + if !Identical(u, t.typ) { + check.errorf(x, _Todo, "invalid use of ~ (underlying type of %s is %s)", t.typ, u) continue // don't report another error for t } } -- GitLab From 281ed619f87fb2d3758f9c378984a16f9d822401 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 16 Aug 2021 12:07:27 -0400 Subject: [PATCH 0712/2500] go/types: parameterized functions must have a body This is a port of CL 340911 to go/types. The new check differs slightly, due to go/ast storing type parameters on the function type, rather than declaration. The error was positioned on the function name for consistency with types2 (and because that's a better position). Change-Id: Icdfc76cd65fab215139180b710293a0d79709297 Reviewed-on: https://go-review.googlesource.com/c/go/+/342475 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/types/api_test.go | 32 +++++++------- src/go/types/decl.go | 4 ++ src/go/types/testdata/check/issues.go2 | 12 ++---- src/go/types/testdata/check/map2.go2 | 4 +- src/go/types/testdata/check/tinference.go2 | 8 ++-- src/go/types/testdata/check/typeinst2.go2 | 14 +++---- src/go/types/testdata/check/typeparams.go2 | 42 +++++++++---------- src/go/types/testdata/examples/functions.go2 | 28 +++++++------ src/go/types/testdata/examples/inference.go2 | 8 ++-- src/go/types/testdata/examples/types.go2 | 14 +++---- .../types/testdata/fixedbugs/issue39634.go2 | 6 +-- .../types/testdata/fixedbugs/issue39723.go2 | 2 +- .../types/testdata/fixedbugs/issue39725.go2 | 4 +- .../types/testdata/fixedbugs/issue39976.go2 | 2 +- .../types/testdata/fixedbugs/issue40038.go2 | 4 +- .../types/testdata/fixedbugs/issue40056.go2 | 2 +- .../types/testdata/fixedbugs/issue40684.go2 | 6 +-- .../types/testdata/fixedbugs/issue41124.go2 | 4 +- .../types/testdata/fixedbugs/issue47127.go2 | 10 ++--- .../types/testdata/fixedbugs/issue47411.go2 | 4 +- 20 files changed, 106 insertions(+), 104 deletions(-) diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index 8e1565b95e..cbb265d9c3 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -343,10 +343,10 @@ func TestTypesInfo(t *testing.T) { {broken + `x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string][-1]int`}, // parameterized functions - {genericPkg + `p0; func f[T any](T); var _ = f[int]`, `f`, `func[generic_p0.T₁ interface{}](generic_p0.T₁)`}, - {genericPkg + `p1; func f[T any](T); var _ = f[int]`, `f[int]`, `func(int)`}, - {genericPkg + `p2; func f[T any](T); func _() { f(42) }`, `f`, `func[generic_p2.T₁ interface{}](generic_p2.T₁)`}, - {genericPkg + `p3; func f[T any](T); func _() { f(42) }`, `f(42)`, `()`}, + {genericPkg + `p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[generic_p0.T₁ interface{}](generic_p0.T₁)`}, + {genericPkg + `p1; func f[T any](T) {}; var _ = f[int]`, `f[int]`, `func(int)`}, + {genericPkg + `p2; func f[T any](T) {}; func _() { f(42) }`, `f`, `func[generic_p2.T₁ interface{}](generic_p2.T₁)`}, + {genericPkg + `p3; func f[T any](T) {}; func _() { f(42) }`, `f(42)`, `()`}, // type parameters {genericPkg + `t0; type t[] int; var _ t`, `t`, `generic_t0.t`}, // t[] is a syntax error that is ignored in this test in favor of t @@ -405,64 +405,64 @@ func TestInferredInfo(t *testing.T) { targs []string sig string }{ - {genericPkg + `p0; func f[T any](T); func _() { f(42) }`, + {genericPkg + `p0; func f[T any](T) {}; func _() { f(42) }`, `f`, []string{`int`}, `func(int)`, }, - {genericPkg + `p1; func f[T any](T) T; func _() { f('@') }`, + {genericPkg + `p1; func f[T any](T) T { panic(0) }; func _() { f('@') }`, `f`, []string{`rune`}, `func(rune) rune`, }, - {genericPkg + `p2; func f[T any](...T) T; func _() { f(0i) }`, + {genericPkg + `p2; func f[T any](...T) T { panic(0) }; func _() { f(0i) }`, `f`, []string{`complex128`}, `func(...complex128) complex128`, }, - {genericPkg + `p3; func f[A, B, C any](A, *B, []C); func _() { f(1.2, new(string), []byte{}) }`, + {genericPkg + `p3; func f[A, B, C any](A, *B, []C) {}; func _() { f(1.2, new(string), []byte{}) }`, `f`, []string{`float64`, `string`, `byte`}, `func(float64, *string, []byte)`, }, - {genericPkg + `p4; func f[A, B any](A, *B, ...[]B); func _() { f(1.2, new(byte)) }`, + {genericPkg + `p4; func f[A, B any](A, *B, ...[]B) {}; func _() { f(1.2, new(byte)) }`, `f`, []string{`float64`, `byte`}, `func(float64, *byte, ...[]byte)`, }, - {genericPkg + `s1; func f[T any, P interface{~*T}](x T); func _(x string) { f(x) }`, + {genericPkg + `s1; func f[T any, P interface{~*T}](x T) {}; func _(x string) { f(x) }`, `f`, []string{`string`, `*string`}, `func(x string)`, }, - {genericPkg + `s2; func f[T any, P interface{~*T}](x []T); func _(x []int) { f(x) }`, + {genericPkg + `s2; func f[T any, P interface{~*T}](x []T) {}; func _(x []int) { f(x) }`, `f`, []string{`int`, `*int`}, `func(x []int)`, }, - {genericPkg + `s3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]](x []T); func _(x []int) { f(x) }`, + {genericPkg + `s3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]](x []T) {}; func _(x []int) { f(x) }`, `f`, []string{`int`, `chan<- int`}, `func(x []int)`, }, - {genericPkg + `s4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T); func _(x []int) { f(x) }`, + {genericPkg + `s4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T) {}; func _(x []int) { f(x) }`, `f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func(x []int)`, }, - {genericPkg + `t1; func f[T any, P interface{~*T}]() T; func _() { _ = f[string] }`, + {genericPkg + `t1; func f[T any, P interface{~*T}]() T { panic(0) }; func _() { _ = f[string] }`, `f`, []string{`string`, `*string`}, `func() string`, }, - {genericPkg + `t2; type C[T any] interface{~chan<- T}; func f[T any, P C[T]]() []T; func _() { _ = f[int] }`, + {genericPkg + `t2; type C[T any] interface{~chan<- T}; func f[T any, P C[T]]() []T { return nil }; func _() { _ = f[int] }`, `f`, []string{`int`, `chan<- int`}, `func() []int`, }, - {genericPkg + `t3; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T; func _() { _ = f[int] }`, + {genericPkg + `t3; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = f[int] }`, `f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func() []int`, diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 6c305caff5..c9865b0f47 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -774,6 +774,10 @@ func (check *Checker) funcDecl(obj *Func, decl *declInfo) { check.funcType(sig, fdecl.Recv, fdecl.Type) obj.color_ = saved + if fdecl.Type.TParams.NumFields() > 0 && fdecl.Body == nil { + check.softErrorf(fdecl.Name, _Todo, "parameterized function is missing function body") + } + // function body must be type-checked after global declarations // (functions implemented elsewhere have no body) if !check.conf.IgnoreFuncBodies && fdecl.Body != nil { diff --git a/src/go/types/testdata/check/issues.go2 b/src/go/types/testdata/check/issues.go2 index 6a1a10ad49..a994d73f66 100644 --- a/src/go/types/testdata/check/issues.go2 +++ b/src/go/types/testdata/check/issues.go2 @@ -40,13 +40,7 @@ func _[T interface{ m() }](x *T) { x.m /* ERROR x\.m undefined */ () } -// In a generic function body all method calls will be pointer method calls. -// If necessary, the function body will insert temporary variables, not seen -// by the user, in order to get an addressable variable to use to call the method. -// Thus, assume an argument type for a generic function to be the type of addressable -// values in the generic function when checking if the argument type satisfies the -// generic function's type bound. -func f2[_ interface{ m1(); m2() }]() +func f2[_ interface{ m1(); m2() }]() {} type T struct{} func (T) m1() @@ -239,7 +233,7 @@ func _[T interface{ ~func() }](f T) { type sliceOf[E any] interface{ ~[]E } -func append[T interface{}, S sliceOf[T], T2 interface{}](s S, t ...T2) S +func append[T interface{}, S sliceOf[T], T2 interface{}](s S, t ...T2) S { panic(0) } var f func() var cancelSlice []context.CancelFunc @@ -247,7 +241,7 @@ var _ = append[context.CancelFunc, []context.CancelFunc, context.CancelFunc](can // A generic function must be instantiated with a type, not a value. -func g[T any](T) T +func g[T any](T) T { panic(0) } var _ = g[int] var _ = g[nil /* ERROR is not a type */ ] diff --git a/src/go/types/testdata/check/map2.go2 b/src/go/types/testdata/check/map2.go2 index 2833445662..e13bf33fed 100644 --- a/src/go/types/testdata/check/map2.go2 +++ b/src/go/types/testdata/check/map2.go2 @@ -114,7 +114,7 @@ func (it *Iterator[K, V]) Next() (K, V, bool) { // chans -func chans_Ranger[T any]() (*chans_Sender[T], *chans_Receiver[T]) +func chans_Ranger[T any]() (*chans_Sender[T], *chans_Receiver[T]) { panic(0) } // A sender is used to send values to a Receiver. type chans_Sender[T any] struct { @@ -143,4 +143,4 @@ type chans_Receiver[T any] struct { func (r *chans_Receiver[T]) Next() (T, bool) { v, ok := <-r.values return v, ok -} \ No newline at end of file +} diff --git a/src/go/types/testdata/check/tinference.go2 b/src/go/types/testdata/check/tinference.go2 index aa9a054682..5bd2ba74e7 100644 --- a/src/go/types/testdata/check/tinference.go2 +++ b/src/go/types/testdata/check/tinference.go2 @@ -26,7 +26,7 @@ type any interface{} // f1(int(0), int(0)) // } -func f2[A any, B interface{~[]A}](A, B) +func f2[A any, B interface{~[]A}](A, B) {} func _() { f := f2[byte] f(byte(0), []byte{}) @@ -42,7 +42,7 @@ func _() { // f3(x, &x, &x) // } -func f4[A any, B interface{~[]C}, C interface{~*A}](A, B, C) +func f4[A any, B interface{~[]C}, C interface{~*A}](A, B, C) {} func _() { f := f4[int] var x int @@ -50,14 +50,14 @@ func _() { f4(x, []*int{}, &x) } -func f5[A interface{~struct{b B; c C}}, B any, C interface{~*B}](x B) A +func f5[A interface{~struct{b B; c C}}, B any, C interface{~*B}](x B) A { panic(0) } func _() { x := f5(1.2) var _ float64 = x.b var _ float64 = *x.c } -func f6[A any, B interface{~struct{f []A}}](B) A +func f6[A any, B interface{~struct{f []A}}](B) A { panic(0) } func _() { x := f6(struct{f []string}{}) var _ string = x diff --git a/src/go/types/testdata/check/typeinst2.go2 b/src/go/types/testdata/check/typeinst2.go2 index f8369c31dd..95c249d529 100644 --- a/src/go/types/testdata/check/typeinst2.go2 +++ b/src/go/types/testdata/check/typeinst2.go2 @@ -85,7 +85,7 @@ type NumericAbs[T any] interface { Abs() T } -func AbsDifference[T NumericAbs[T]](x T) +func AbsDifference[T NumericAbs[T]](x T) { panic(0) } type OrderedAbs[T any] T @@ -97,7 +97,7 @@ func OrderedAbsDifference[T any](x T) { // same code, reduced to essence -func g[P interface{ m() P }](x P) +func g[P interface{ m() P }](x P) { panic(0) } type T4[P any] P @@ -205,7 +205,7 @@ type I0 interface { E0 } -func f0[T I0]() +func f0[T I0]() {} var _ = f0[int] var _ = f0[bool] var _ = f0[string] @@ -216,7 +216,7 @@ type I01 interface { E1 } -func f01[T I01]() +func f01[T I01]() {} var _ = f01[int] var _ = f01[bool /* ERROR does not satisfy I0 */ ] var _ = f01[string] @@ -228,7 +228,7 @@ type I012 interface { E2 } -func f012[T I012]() +func f012[T I012]() {} var _ = f012[int /* ERROR does not satisfy I012 */ ] var _ = f012[bool /* ERROR does not satisfy I012 */ ] var _ = f012[string /* ERROR does not satisfy I012 */ ] @@ -239,7 +239,7 @@ type I12 interface { E2 } -func f12[T I12]() +func f12[T I12]() {} var _ = f12[int /* ERROR does not satisfy I12 */ ] var _ = f12[bool /* ERROR does not satisfy I12 */ ] var _ = f12[string /* ERROR does not satisfy I12 */ ] @@ -250,7 +250,7 @@ type I0_ interface { ~int } -func f0_[T I0_]() +func f0_[T I0_]() {} var _ = f0_[int] var _ = f0_[bool /* ERROR does not satisfy I0_ */ ] var _ = f0_[string /* ERROR does not satisfy I0_ */ ] diff --git a/src/go/types/testdata/check/typeparams.go2 b/src/go/types/testdata/check/typeparams.go2 index 5cd4730078..bd89d1ecad 100644 --- a/src/go/types/testdata/check/typeparams.go2 +++ b/src/go/types/testdata/check/typeparams.go2 @@ -15,9 +15,9 @@ func _[_ any /* ok here */ , _ interface{any /* ERROR constraint */ }](any /* ER func identity[T any](x T) T { return x } -func _[_ any](x int) int -func _[T any](T /* ERROR redeclared */ T)() -func _[T, T /* ERROR redeclared */ any]() +func _[_ any](x int) int { panic(0) } +func _[T any](T /* ERROR redeclared */ T)() {} +func _[T, T /* ERROR redeclared */ any]() {} // Constraints (incl. any) may be parenthesized. func _[_ (any)]() {} @@ -77,18 +77,18 @@ func new[T any]() *T { var _ = new /* ERROR cannot use generic function new */ var _ *int = new[int]() -func _[T any](map[T /* ERROR incomparable map key type T \(missing comparable constraint\) */]int) // w/o constraint we don't know if T is comparable +func _[T any](map[T /* ERROR incomparable map key type T \(missing comparable constraint\) */]int) {} // w/o constraint we don't know if T is comparable -func f1[T1 any](struct{T1 /* ERROR cannot be a .* type parameter */ }) int +func f1[T1 any](struct{T1 /* ERROR cannot be a .* type parameter */ }) int { panic(0) } var _ = f1[int](struct{T1}{}) type T1 = int -func f2[t1 any](struct{t1 /* ERROR cannot be a .* type parameter */ ; x float32}) int +func f2[t1 any](struct{t1 /* ERROR cannot be a .* type parameter */ ; x float32}) int { panic(0) } var _ = f2[t1](struct{t1; x float32}{}) type t1 = int -func f3[A, B, C any](A, struct{x B}, func(A, struct{x B}, *C)) int +func f3[A, B, C any](A, struct{x B}, func(A, struct{x B}, *C)) int { panic(0) } var _ = f3[int, rune, bool](1, struct{x rune}{}, nil) @@ -257,28 +257,28 @@ func _[ var _ = new /* ERROR cannot infer T */ () -func f4[A, B, C any](A, B) C +func f4[A, B, C any](A, B) C { panic(0) } var _ = f4 /* ERROR cannot infer C */ (1, 2) var _ = f4[int, float32, complex128](1, 2) -func f5[A, B, C any](A, []*B, struct{f []C}) int +func f5[A, B, C any](A, []*B, struct{f []C}) int { panic(0) } var _ = f5[int, float32, complex128](0, nil, struct{f []complex128}{}) var _ = f5 /* ERROR cannot infer */ (0, nil, struct{f []complex128}{}) var _ = f5(0, []*float32{new[float32]()}, struct{f []complex128}{}) -func f6[A any](A, []A) int +func f6[A any](A, []A) int { panic(0) } var _ = f6(0, nil) -func f6nil[A any](A) int +func f6nil[A any](A) int { panic(0) } var _ = f6nil /* ERROR cannot infer */ (nil) // type inference with variadic functions -func f7[T any](...T) T +func f7[T any](...T) T { panic(0) } var _ int = f7 /* ERROR cannot infer T */ () var _ int = f7(1) @@ -291,7 +291,7 @@ var _ = f7(float64(1), 2.3) var _ = f7(1, 2.3 /* ERROR does not match */ ) var _ = f7(1.2, 3 /* ERROR does not match */ ) -func f8[A, B any](A, B, ...B) int +func f8[A, B any](A, B, ...B) int { panic(0) } var _ = f8(1) /* ERROR not enough arguments */ var _ = f8(1, 2.3) @@ -317,7 +317,7 @@ func (T) m3[ /* ERROR methods cannot have type parameters */ P any]() {} type S1[P any] struct { f P } -func f9[P any](x S1[P]) +func f9[P any](x S1[P]) {} func _() { f9[int](S1[int]{42}) @@ -326,7 +326,7 @@ func _() { type S2[A, B, C any] struct{} -func f10[X, Y, Z any](a S2[X, int, Z], b S2[X, Y, bool]) +func f10[X, Y, Z any](a S2[X, int, Z], b S2[X, Y, bool]) {} func _[P any]() { f10[int, float32, string](S2[int, int, string]{}, S2[int, float32, bool]{}) @@ -337,7 +337,7 @@ func _[P any]() { // corner case for type inference // (was bug: after instanting f11, the type-checker didn't mark f11 as non-generic) -func f11[T any]() +func f11[T any]() {} func _() { f11[int]() @@ -345,7 +345,7 @@ func _() { // the previous example was extracted from -func f12[T interface{m() T}]() +func f12[T interface{m() T}]() {} type A[T any] T @@ -373,15 +373,15 @@ func _[T any] (x T) { type R0 struct{} -func (R0) _[ /* ERROR methods cannot have type parameters */ T any](x T) -func (R0 /* ERROR invalid receiver */ ) _[ /* ERROR methods cannot have type parameters */ R0 any]() // scope of type parameters starts at "func" +func (R0) _[ /* ERROR methods cannot have type parameters */ T any](x T) {} +func (R0 /* ERROR invalid receiver */ ) _[ /* ERROR methods cannot have type parameters */ R0 any]() {} // scope of type parameters starts at "func" type R1[A, B any] struct{} func (_ R1[A, B]) m0(A, B) -func (_ R1[A, B]) m1[ /* ERROR methods cannot have type parameters */ T any](A, B, T) T +func (_ R1[A, B]) m1[ /* ERROR methods cannot have type parameters */ T any](A, B, T) T { panic(0) } func (_ R1 /* ERROR not a generic type */ [R1, _]) _() -func (_ R1[A, B]) _[ /* ERROR methods cannot have type parameters */ A /* ERROR redeclared */ any](B) +func (_ R1[A, B]) _[ /* ERROR methods cannot have type parameters */ A /* ERROR redeclared */ any](B) {} func _() { var r R1[int, string] diff --git a/src/go/types/testdata/examples/functions.go2 b/src/go/types/testdata/examples/functions.go2 index 81b9d3456c..0af77267c5 100644 --- a/src/go/types/testdata/examples/functions.go2 +++ b/src/go/types/testdata/examples/functions.go2 @@ -66,7 +66,7 @@ var _ float64 = foo(42, []float64{1.0}, &s) // Type inference works in a straight-forward manner even // for variadic functions. -func variadic[A, B any](A, B, ...B) int +func variadic[A, B any](A, B, ...B) int { panic(0) } // var _ = variadic(1) // ERROR not enough arguments var _ = variadic(1, 2.3) @@ -118,9 +118,9 @@ func max[T interface{ ~int }](x ...T) T { // Thus even if a type can be inferred successfully, the function // call may not be valid. -func fboth[T any](chan T) -func frecv[T any](<-chan T) -func fsend[T any](chan<- T) +func fboth[T any](chan T) {} +func frecv[T any](<-chan T) {} +func fsend[T any](chan<- T) {} func _() { var both chan int @@ -140,9 +140,9 @@ func _() { fsend(send) } -func ffboth[T any](func(chan T)) -func ffrecv[T any](func(<-chan T)) -func ffsend[T any](func(chan<- T)) +func ffboth[T any](func(chan T)) {} +func ffrecv[T any](func(<-chan T)) {} +func ffsend[T any](func(chan<- T)) {} func _() { var both func(chan int) @@ -169,9 +169,9 @@ func _() { // assignment is permitted, parameter passing is permitted as well, // so type inference should be able to handle these cases well. -func g1[T any]([]T) -func g2[T any]([]T, T) -func g3[T any](*T, ...T) +func g1[T any]([]T) {} +func g2[T any]([]T, T) {} +func g3[T any](*T, ...T) {} func _() { type intSlize []int @@ -194,7 +194,7 @@ func _() { // Here's a realistic example. -func append[T any](s []T, t ...T) []T +func append[T any](s []T, t ...T) []T { panic(0) } func _() { var f func() @@ -207,8 +207,12 @@ func _() { // (that would indicate a slice type). Thus, generic functions cannot // have empty type parameter lists, either. This is a syntax error. -func h[] /* ERROR empty type parameter list */ () +func h[] /* ERROR empty type parameter list */ () {} func _() { h /* ERROR cannot index */ [] /* ERROR operand */ () } + +// Parameterized functions must have a function body. + +func _ /* ERROR missing function body */ [P any]() diff --git a/src/go/types/testdata/examples/inference.go2 b/src/go/types/testdata/examples/inference.go2 index 1142e569b4..9a2dcc47f2 100644 --- a/src/go/types/testdata/examples/inference.go2 +++ b/src/go/types/testdata/examples/inference.go2 @@ -10,7 +10,7 @@ type Ordered interface { ~int|~float64|~string } -func min[T Ordered](x, y T) T +func min[T Ordered](x, y T) T { panic(0) } func _() { // min can be called with explicit instantiation. @@ -37,7 +37,7 @@ func _() { _ = min("foo", "bar") } -func mixed[T1, T2, T3 any](T1, T2, T3) +func mixed[T1, T2, T3 any](T1, T2, T3) {} func _() { // mixed can be called with explicit instantiation. @@ -54,7 +54,7 @@ func _() { mixed[int, string](1.1 /* ERROR cannot use 1.1 */ , "", false) } -func related1[Slice interface{~[]Elem}, Elem any](s Slice, e Elem) +func related1[Slice interface{~[]Elem}, Elem any](s Slice, e Elem) {} func _() { // related1 can be called with explicit instantiation. @@ -78,7 +78,7 @@ func _() { related1(si, "foo" /* ERROR cannot use "foo" */ ) } -func related2[Elem any, Slice interface{~[]Elem}](e Elem, s Slice) +func related2[Elem any, Slice interface{~[]Elem}](e Elem, s Slice) {} func _() { // related2 can be called with explicit instantiation. diff --git a/src/go/types/testdata/examples/types.go2 b/src/go/types/testdata/examples/types.go2 index a7544f79ea..82f17a3263 100644 --- a/src/go/types/testdata/examples/types.go2 +++ b/src/go/types/testdata/examples/types.go2 @@ -222,15 +222,15 @@ type B0 interface {} type B1[_ any] interface{} type B2[_, _ any] interface{} -func _[T1 B0]() -func _[T1 B1[T1]]() -func _[T1 B2 /* ERROR cannot use generic type .* without instantiation */ ]() +func _[T1 B0]() {} +func _[T1 B1[T1]]() {} +func _[T1 B2 /* ERROR cannot use generic type .* without instantiation */ ]() {} -func _[T1, T2 B0]() -func _[T1 B1[T1], T2 B1[T2]]() -func _[T1, T2 B2 /* ERROR cannot use generic type .* without instantiation */ ]() +func _[T1, T2 B0]() {} +func _[T1 B1[T1], T2 B1[T2]]() {} +func _[T1, T2 B2 /* ERROR cannot use generic type .* without instantiation */ ]() {} -func _[T1 B0, T2 B1[T2]]() // here B1 applies to T2 +func _[T1 B0, T2 B1[T2]]() {} // here B1 applies to T2 // When the type argument is left away, the type bound is // instantiated for each type parameter with that type diff --git a/src/go/types/testdata/fixedbugs/issue39634.go2 b/src/go/types/testdata/fixedbugs/issue39634.go2 index aec404e294..f307ee9c9e 100644 --- a/src/go/types/testdata/fixedbugs/issue39634.go2 +++ b/src/go/types/testdata/fixedbugs/issue39634.go2 @@ -50,7 +50,7 @@ func (G15 /* ERROR generic type .* without instantiation */ ) p() // crash 16 type Foo16[T any] r16 /* ERROR not a type */ -func r16[T any]() Foo16[Foo16[T]] +func r16[T any]() Foo16[Foo16[T]] { panic(0) } // crash 17 type Y17 interface{ c() } @@ -58,7 +58,7 @@ type Z17 interface { c() Y17 Y17 /* ERROR duplicate method */ } -func F17[T Z17](T) +func F17[T Z17](T) {} // crash 18 type o18[T any] []func(_ o18[[]_ /* ERROR cannot use _ */ ]) @@ -88,5 +88,5 @@ type T26 = interface{ F26[ /* ERROR methods cannot have type parameters */ Z any func F26[Z any]() T26 { return F26[] /* ERROR operand */ } // crash 27 -func e27[T any]() interface{ x27 /* ERROR not a type */ } +func e27[T any]() interface{ x27 /* ERROR not a type */ } { panic(0) } func x27() { e27 /* ERROR cannot infer T */ () } diff --git a/src/go/types/testdata/fixedbugs/issue39723.go2 b/src/go/types/testdata/fixedbugs/issue39723.go2 index 367b3f1360..d5311ed3e7 100644 --- a/src/go/types/testdata/fixedbugs/issue39723.go2 +++ b/src/go/types/testdata/fixedbugs/issue39723.go2 @@ -6,4 +6,4 @@ package p // A constraint must be an interface; it cannot // be a type parameter, for instance. -func _[A interface{ ~int }, B A /* ERROR not an interface */ ]() +func _[A interface{ ~int }, B A /* ERROR not an interface */ ]() {} diff --git a/src/go/types/testdata/fixedbugs/issue39725.go2 b/src/go/types/testdata/fixedbugs/issue39725.go2 index e19b6770bf..62dc45a596 100644 --- a/src/go/types/testdata/fixedbugs/issue39725.go2 +++ b/src/go/types/testdata/fixedbugs/issue39725.go2 @@ -4,13 +4,13 @@ package p -func f1[T1, T2 any](T1, T2, struct{a T1; b T2}) +func f1[T1, T2 any](T1, T2, struct{a T1; b T2}) {} func _() { f1(42, string("foo"), struct /* ERROR does not match inferred type struct\{a int; b string\} */ {a, b int}{}) } // simplified test case from issue -func f2[T any](_ []T, _ func(T)) +func f2[T any](_ []T, _ func(T)) {} func _() { f2([]string{}, func /* ERROR does not match inferred type func\(string\) */ (f []byte) {}) } diff --git a/src/go/types/testdata/fixedbugs/issue39976.go2 b/src/go/types/testdata/fixedbugs/issue39976.go2 index 3db4eae012..d703da90a2 100644 --- a/src/go/types/testdata/fixedbugs/issue39976.go2 +++ b/src/go/types/testdata/fixedbugs/issue39976.go2 @@ -7,7 +7,7 @@ package p type policy[K, V any] interface{} type LRU[K, V any] struct{} -func NewCache[K, V any](p policy[K, V]) +func NewCache[K, V any](p policy[K, V]) {} func _() { var lru LRU[int, string] diff --git a/src/go/types/testdata/fixedbugs/issue40038.go2 b/src/go/types/testdata/fixedbugs/issue40038.go2 index 8948d61caa..5f81fcbfaa 100644 --- a/src/go/types/testdata/fixedbugs/issue40038.go2 +++ b/src/go/types/testdata/fixedbugs/issue40038.go2 @@ -8,8 +8,8 @@ type A[T any] int func (A[T]) m(A[T]) -func f[P interface{m(P)}]() +func f[P interface{m(P)}]() {} func _() { _ = f[A[int]] -} \ No newline at end of file +} diff --git a/src/go/types/testdata/fixedbugs/issue40056.go2 b/src/go/types/testdata/fixedbugs/issue40056.go2 index f587691e3d..66130c0a55 100644 --- a/src/go/types/testdata/fixedbugs/issue40056.go2 +++ b/src/go/types/testdata/fixedbugs/issue40056.go2 @@ -10,6 +10,6 @@ func _() { type S struct {} -func NewS[T any]() *S +func NewS[T any]() *S { panic(0) } func (_ *S /* ERROR S is not a generic type */ [T]) M() diff --git a/src/go/types/testdata/fixedbugs/issue40684.go2 b/src/go/types/testdata/fixedbugs/issue40684.go2 index 0269c3a62c..63a058d039 100644 --- a/src/go/types/testdata/fixedbugs/issue40684.go2 +++ b/src/go/types/testdata/fixedbugs/issue40684.go2 @@ -6,10 +6,10 @@ package p type T[_ any] int -func f[_ any]() -func g[_, _ any]() +func f[_ any]() {} +func g[_, _ any]() {} func _() { _ = f[T /* ERROR without instantiation */ ] _ = g[T /* ERROR without instantiation */ , T /* ERROR without instantiation */ ] -} \ No newline at end of file +} diff --git a/src/go/types/testdata/fixedbugs/issue41124.go2 b/src/go/types/testdata/fixedbugs/issue41124.go2 index 60650432a4..4642ab60fc 100644 --- a/src/go/types/testdata/fixedbugs/issue41124.go2 +++ b/src/go/types/testdata/fixedbugs/issue41124.go2 @@ -79,9 +79,9 @@ type T3[_, _, _ any] struct{} var _ T1[I2 /* ERROR interface contains type constraints */ ] var _ T3[int, I2 /* ERROR interface contains type constraints */ , float32] -func f1[_ any]() int +func f1[_ any]() int { panic(0) } var _ = f1[I2 /* ERROR interface contains type constraints */ ]() -func f3[_, _, _ any]() int +func f3[_, _, _ any]() int { panic(0) } var _ = f3[int, I2 /* ERROR interface contains type constraints */ , float32]() func _(x interface{}) { diff --git a/src/go/types/testdata/fixedbugs/issue47127.go2 b/src/go/types/testdata/fixedbugs/issue47127.go2 index 387c946957..108d600a38 100644 --- a/src/go/types/testdata/fixedbugs/issue47127.go2 +++ b/src/go/types/testdata/fixedbugs/issue47127.go2 @@ -30,8 +30,8 @@ func _[P any]() { ) } -func _[P any, Q interface{ *P | []P | chan P | map[string]P }]() -func _[P any, Q interface{ P /* ERROR "cannot embed a type parameter" */ }]() -func _[P any, Q interface{ ~P /* ERROR "cannot embed a type parameter" */ }]() -func _[P any, Q interface{ int | P /* ERROR "cannot embed a type parameter" */ }]() -func _[P any, Q interface{ int | ~P /* ERROR "cannot embed a type parameter" */ }]() +func _[P any, Q interface{ *P | []P | chan P | map[string]P }]() {} +func _[P any, Q interface{ P /* ERROR "cannot embed a type parameter" */ }]() {} +func _[P any, Q interface{ ~P /* ERROR "cannot embed a type parameter" */ }]() {} +func _[P any, Q interface{ int | P /* ERROR "cannot embed a type parameter" */ }]() {} +func _[P any, Q interface{ int | ~P /* ERROR "cannot embed a type parameter" */ }]() {} diff --git a/src/go/types/testdata/fixedbugs/issue47411.go2 b/src/go/types/testdata/fixedbugs/issue47411.go2 index 7326205863..2fc26d9e85 100644 --- a/src/go/types/testdata/fixedbugs/issue47411.go2 +++ b/src/go/types/testdata/fixedbugs/issue47411.go2 @@ -4,8 +4,8 @@ package p -func f[_ comparable]() -func g[_ interface{interface{comparable; ~int|~string}}]() +func f[_ comparable]() {} +func g[_ interface{interface{comparable; ~int|~string}}]() {} func _[P comparable, Q interface{ comparable; ~int|~string }, -- GitLab From 2460cf8602aa1830bf712bf70f7dc8882bbfa79c Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 16 Aug 2021 12:09:56 -0400 Subject: [PATCH 0713/2500] go/types: remove Named.SetTArgs This is a port of CL 341290 to go/types; SetTArgs is a potentially error-prone API. Change-Id: I484e62d71a0e09be1e19f8e63994912a88364eca Reviewed-on: https://go-review.googlesource.com/c/go/+/342476 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/types/named.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/go/types/named.go b/src/go/types/named.go index 791ab78778..208327929f 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -132,9 +132,6 @@ func (t *Named) NumTArgs() int { return len(t.targs) } // TArgs returns the i'th type argument of the named type t for 0 <= i < t.NumTArgs(). func (t *Named) TArg(i int) Type { return t.targs[i] } -// SetTArgs sets the type arguments of the named type t. -func (t *Named) SetTArgs(args []Type) { t.targs = args } - // NumMethods returns the number of explicit methods whose receiver is named type t. func (t *Named) NumMethods() int { return len(t.load().methods) } -- GitLab From ff36d11470b3b545ca953ba5e478fe8405860468 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 16 Aug 2021 12:42:27 -0400 Subject: [PATCH 0714/2500] go/types: merge Instantiate and InstantiateLazy This is a straightforward port of CL 341855 to go/types. Change-Id: I42a74df7a54f5d03aab31ad75dfeb3d1ba775354 Reviewed-on: https://go-review.googlesource.com/c/go/+/342477 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/types/api_test.go | 4 ++-- src/go/types/call.go | 4 ++-- src/go/types/decl.go | 5 +++-- src/go/types/expr.go | 2 +- src/go/types/infer.go | 6 +++--- src/go/types/instantiate.go | 28 +++++++++---------------- src/go/types/lookup.go | 4 ++-- src/go/types/named.go | 41 +++++++++++++++++++++++++++++-------- src/go/types/predicates.go | 4 ++-- src/go/types/signature.go | 4 ++-- src/go/types/subst.go | 22 +++++++++++++------- src/go/types/type.go | 2 +- src/go/types/typexpr.go | 14 ++++++++----- src/go/types/unify.go | 4 ++-- 14 files changed, 86 insertions(+), 58 deletions(-) diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index cbb265d9c3..52c9e5afe8 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -1857,7 +1857,7 @@ func TestInstantiate(t *testing.T) { res := check.Instantiate(token.NoPos, T, []Type{Typ[Int]}, nil, false) // instantiated type should point to itself - if res.Underlying().(*Pointer).Elem() != res { - t.Fatalf("unexpected result type: %s", res) + if p := res.Underlying().(*Pointer).Elem(); p != res { + t.Fatalf("unexpected result type: %s points to %s", res, p) } } diff --git a/src/go/types/call.go b/src/go/types/call.go index da2f319a4a..390e9cd892 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -341,7 +341,7 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type // need to compute it from the adjusted list; otherwise we can // simply use the result signature's parameter list. if adjusted { - sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(sig.TParams().list(), targs)).(*Tuple) + sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(sig.TParams().list(), targs), nil).(*Tuple) } else { sigParams = rsig.params } @@ -554,7 +554,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { // (If we modify m, some tests will fail; possibly because the m is in use.) // TODO(gri) investigate and provide a correct explanation here copy := *m - copy.typ = check.subst(e.Pos(), m.typ, makeSubstMap(sig.RParams().list(), targs)) + copy.typ = check.subst(e.Pos(), m.typ, makeSubstMap(sig.RParams().list(), targs), nil) obj = © } // TODO(gri) we also need to do substitution for parameterized interface methods diff --git a/src/go/types/decl.go b/src/go/types/decl.go index c9865b0f47..35aa5e2d5a 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -317,7 +317,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { } case *Named: - t.expand() + t.expand(check.typMap) // don't touch the type if it is from a different package or the Universe scope // (doing so would lead to a race condition - was issue #35049) if t.obj.pkg != check.pkg { @@ -711,7 +711,8 @@ func (check *Checker) collectMethods(obj *TypeName) { // and field names must be distinct." base := asNamed(obj.typ) // shouldn't fail but be conservative if base != nil { - if t, _ := base.Underlying().(*Struct); t != nil { + u := safeUnderlying(base) // base should be expanded, but use safeUnderlying to be conservative + if t, _ := u.(*Struct); t != nil { for _, fld := range t.fields { if fld.name != "_" { assert(mset.insert(fld) == nil) diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 5bb9b7c280..b0e2a27085 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -600,7 +600,7 @@ func (check *Checker) updateExprVal(x ast.Expr, val constant.Value) { func (check *Checker) convertUntyped(x *operand, target Type) { newType, val, code := check.implicitTypeAndValue(x, target) if code != 0 { - check.invalidConversion(code, x, target.Underlying()) + check.invalidConversion(code, x, safeUnderlying(target)) x.mode = invalid return } diff --git a/src/go/types/infer.go b/src/go/types/infer.go index ea1057fe07..57ec327d12 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -86,7 +86,7 @@ func (check *Checker) infer(posn positioner, tparams []*TypeName, targs []Type, // but that doesn't impact the isParameterized check for now). if params.Len() > 0 { smap := makeSubstMap(tparams, targs) - params = check.subst(token.NoPos, params, smap).(*Tuple) + params = check.subst(token.NoPos, params, smap, nil).(*Tuple) } // --- 2 --- @@ -127,7 +127,7 @@ func (check *Checker) infer(posn positioner, tparams []*TypeName, targs []Type, } smap := makeSubstMap(tparams, targs) // TODO(rFindley): pass a positioner here, rather than arg.Pos(). - inferred := check.subst(arg.Pos(), tpar, smap) + inferred := check.subst(arg.Pos(), tpar, smap, nil) if inferred != tpar { check.errorf(arg, _Todo, "%s %s of %s does not match inferred type %s for %s", kind, targ, arg.expr, inferred, tpar) } else { @@ -422,7 +422,7 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty n := 0 for _, index := range dirty { t0 := types[index] - if t1 := check.subst(token.NoPos, t0, smap); t1 != t0 { + if t1 := check.subst(token.NoPos, t0, smap, nil); t1 != t0 { types[index] = t1 dirty[n] = index n++ diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index dc2b29a5f7..189a35ab88 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -28,7 +28,7 @@ func (check *Checker) Instantiate(pos token.Pos, typ Type, targs []Type, posList var tparams []*TypeName switch t := typ.(type) { case *Named: - tparams = t.TParams().list() + return check.instantiateLazy(pos, t, targs, posList, verify) case *Signature: tparams = t.TParams().list() defer func() { @@ -54,14 +54,14 @@ func (check *Checker) Instantiate(pos token.Pos, typ Type, targs []Type, posList panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } - inst := check.instantiate(pos, typ, tparams, targs, posList) + inst := check.instantiate(pos, typ, tparams, targs, posList, nil) if verify && len(tparams) == len(targs) { check.verify(pos, tparams, targs, posList) } return inst } -func (check *Checker) instantiate(pos token.Pos, typ Type, tparams []*TypeName, targs []Type, posList []token.Pos) (res Type) { +func (check *Checker) instantiate(pos token.Pos, typ Type, tparams []*TypeName, targs []Type, posList []token.Pos, typMap map[string]*Named) (res Type) { // the number of supplied types must match the number of type parameters if len(targs) != len(tparams) { // TODO(gri) provide better error message @@ -82,7 +82,7 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, tparams []*TypeName, // Calling under() here may lead to endless instantiations. // Test case: type T[P any] T[P] // TODO(gri) investigate if that's a bug or to be expected. - under = res.Underlying() + under = safeUnderlying(res) } check.trace(pos, "=> %s (under = %s)", res, under) }() @@ -96,22 +96,14 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, tparams []*TypeName, return typ // nothing to do (minor optimization) } - smap := makeSubstMap(tparams, targs) - - return check.subst(pos, typ, smap) + return check.subst(pos, typ, makeSubstMap(tparams, targs), typMap) } -// InstantiateLazy is like Instantiate, but avoids actually -// instantiating the type until needed. typ must be a *Named -// type. -func (check *Checker) InstantiateLazy(pos token.Pos, typ Type, targs []Type, posList []token.Pos, verify bool) Type { - // Don't use asNamed here: we don't want to expand the base during lazy - // instantiation. - base := typ.(*Named) - if base == nil { - panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) - } +// instantiateLazy avoids actually instantiating the type until needed. typ +// must be a *Named type. +func (check *Checker) instantiateLazy(pos token.Pos, base *Named, targs []Type, posList []token.Pos, verify bool) Type { if verify && base.TParams().Len() == len(targs) { + // TODO: lift the nil check in verify to here. check.later(func() { check.verify(pos, base.tparams.list(), targs, posList) }) @@ -171,7 +163,7 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap // as the instantiated type; before we can use it for bounds checking we // need to instantiate it with the type arguments with which we instantiate // the parameterized type. - iface = check.subst(pos, iface, smap).(*Interface) + iface = check.subst(pos, iface, smap, nil).(*Interface) // if iface is comparable, targ must be comparable // TODO(gri) the error messages needs to be better, here diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index 28628058c2..186e421edb 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -48,7 +48,7 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o // pointer type but discard the result if it is a method since we would // not have found it for T (see also issue 8590). if t := asNamed(T); t != nil { - if p, _ := t.Underlying().(*Pointer); p != nil { + if p, _ := safeUnderlying(t).(*Pointer); p != nil { obj, index, indirect = lookupFieldOrMethod(p, false, pkg, name) if _, ok := obj.(*Func); ok { return nil, nil, false @@ -392,7 +392,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, if len(ftyp.RParams().list()) != len(Vn.targs) { return } - ftyp = check.subst(token.NoPos, ftyp, makeSubstMap(ftyp.RParams().list(), Vn.targs)).(*Signature) + ftyp = check.subst(token.NoPos, ftyp, makeSubstMap(ftyp.RParams().list(), Vn.targs), nil).(*Signature) } // If the methods have type parameters we don't care whether they diff --git a/src/go/types/named.go b/src/go/types/named.go index 208327929f..f738e8ffcc 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -157,7 +157,7 @@ func (t *Named) AddMethod(m *Func) { } } -func (t *Named) Underlying() Type { return t.load().underlying } +func (t *Named) Underlying() Type { return t.load().expand(nil).underlying } func (t *Named) String() string { return TypeString(t, nil) } // ---------------------------------------------------------------------------- @@ -170,9 +170,9 @@ func (t *Named) String() string { return TypeString(t, nil) } // is detected, the result is Typ[Invalid]. If a cycle is detected and // n0.check != nil, the cycle is reported. func (n0 *Named) under() Type { - n0.expand() + n0.expand(nil) - u := n0.Underlying() + u := n0.load().underlying if u == Typ[Invalid] { return u @@ -210,7 +210,7 @@ func (n0 *Named) under() Type { seen := map[*Named]int{n0: 0} path := []Object{n0.obj} for { - u = n.Underlying() + u = n.load().underlying if u == nil { u = Typ[Invalid] break @@ -218,7 +218,7 @@ func (n0 *Named) under() Type { var n1 *Named switch u1 := u.(type) { case *Named: - u1.expand() + u1.expand(nil) n1 = u1 } if n1 == nil { @@ -268,17 +268,40 @@ type instance struct { // expand ensures that the underlying type of n is instantiated. // The underlying type will be Typ[Invalid] if there was an error. -// TODO(rfindley): expand would be a better name for this method, but conflicts -// with the existing concept of lazy expansion. Need to reconcile this. -func (n *Named) expand() { +func (n *Named) expand(typMap map[string]*Named) *Named { if n.instance != nil { // n must be loaded before instantiation, in order to have accurate // tparams. This is done implicitly by the call to n.TParams, but making it // explicit is harmless: load is idempotent. n.load() - inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams().list(), n.targs, n.instance.posList) + if typMap == nil { + if n.check != nil { + typMap = n.check.typMap + } else { + // If we're instantiating lazily, we might be outside the scope of a + // type-checking pass. In that case we won't have a pre-existing + // typMap, but don't want to create a duplicate of the current instance + // in the process of expansion. + h := instantiatedHash(n.orig, n.targs) + typMap = map[string]*Named{h: n} + } + } + + inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams().list(), n.targs, n.instance.posList, typMap) n.underlying = inst n.fromRHS = inst n.instance = nil } + return n +} + +// safeUnderlying returns the underlying of typ without expanding instances, to +// avoid infinite recursion. +// +// TODO(rfindley): eliminate this function or give it a better name. +func safeUnderlying(typ Type) Type { + if t, _ := typ.(*Named); t != nil { + return t.load().underlying + } + return typ.Underlying() } diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index d7adca1d33..bd9e53d2bb 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -302,8 +302,8 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { // Two named types are identical if their type names originate // in the same type declaration. if y, ok := y.(*Named); ok { - x.expand() - y.expand() + x.expand(nil) + y.expand(nil) // TODO(gri) Why is x == y not sufficient? And if it is, // we can just return false here because x == y // is caught in the very beginning of this function. diff --git a/src/go/types/signature.go b/src/go/types/signature.go index f0a9f011ea..ffe612d9b7 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -148,7 +148,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast // TODO(gri) should we assume now that bounds always exist? // (no bound == empty interface) if bound != nil { - bound = check.subst(tname.pos, bound, smap) + bound = check.subst(tname.pos, bound, smap, nil) tname.typ.(*TypeParam).bound = bound } } @@ -205,7 +205,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast var err string switch T := rtyp.(type) { case *Named: - T.expand() + T.expand(nil) // spec: "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." diff --git a/src/go/types/subst.go b/src/go/types/subst.go index b4519a1b5f..0d3bcefb0b 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -54,7 +54,9 @@ func (m *substMap) lookup(tpar *TypeParam) Type { // subst is functional in the sense that it doesn't modify the incoming // type. If a substitution took place, the result type is different from // from the incoming type. -func (check *Checker) subst(pos token.Pos, typ Type, smap *substMap) Type { +// +// If the given typMap is nil and check is non-nil, check.typMap is used. +func (check *Checker) subst(pos token.Pos, typ Type, smap *substMap, typMap map[string]*Named) Type { if smap.empty() { return typ } @@ -71,16 +73,21 @@ func (check *Checker) subst(pos token.Pos, typ Type, smap *substMap) Type { var subst subster subst.pos = pos subst.smap = smap + if check != nil { subst.check = check - subst.typMap = check.typMap - } else { + if typMap == nil { + typMap = check.typMap + } + } + if typMap == nil { // If we don't have a *Checker and its global type map, // use a local version. Besides avoiding duplicate work, // the type map prevents infinite recursive substitution // for recursive types (example: type T[P any] *T[P]). - subst.typMap = make(map[string]*Named) + typMap = make(map[string]*Named) } + subst.typMap = typMap return subst.typ(typ) } @@ -241,14 +248,15 @@ func (subst *subster) typ(typ Type) Type { // create a new named type and populate typMap to avoid endless recursion tname := NewTypeName(subst.pos, t.obj.pkg, t.obj.name, nil) - named := subst.check.newNamed(tname, t, t.Underlying(), t.TParams(), t.methods) // method signatures are updated lazily + t.load() + named := subst.check.newNamed(tname, t.orig, t.underlying, t.TParams(), t.methods) // method signatures are updated lazily named.targs = newTargs subst.typMap[h] = named - t.expand() // must happen after typMap update to avoid infinite recursion + t.expand(subst.typMap) // must happen after typMap update to avoid infinite recursion // do the substitution dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, newTargs) - named.underlying = subst.typOrNil(t.Underlying()) + named.underlying = subst.typOrNil(t.underlying) dump(">>> underlying: %v", named.underlying) assert(named.underlying != nil) named.fromRHS = named.underlying // for cycle detection (Checker.validType) diff --git a/src/go/types/type.go b/src/go/types/type.go index 87242ccf62..3be42a1584 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -115,7 +115,7 @@ func asInterface(t Type) *Interface { func asNamed(t Type) *Named { e, _ := t.(*Named) if e != nil { - e.expand() + e.expand(nil) } return e } diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index f14fbe1877..8af6570072 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -223,7 +223,7 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) { // Test case: type T[P any] *T[P] // TODO(gri) investigate if that's a bug or to be expected // (see also analogous comment in Checker.instantiate). - under = T.Underlying() + under = safeUnderlying(T) } if T == under { check.trace(e0.Pos(), "=> %s // %s", T, goTypeName(T)) @@ -411,9 +411,13 @@ func (check *Checker) typeOrNil(e ast.Expr) Type { } func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named) Type { - base := check.genericType(x, true) - if base == Typ[Invalid] { - return base // error already reported + gtyp := check.genericType(x, true) + if gtyp == Typ[Invalid] { + return gtyp // error already reported + } + base, _ := gtyp.(*Named) + if base == nil { + panic(fmt.Sprintf("%v: cannot instantiate %v", x.Pos(), gtyp)) } // evaluate arguments @@ -429,7 +433,7 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named posList[i] = arg.Pos() } - typ := check.InstantiateLazy(x.Pos(), base, targs, posList, true) + typ := check.instantiateLazy(x.Pos(), base, targs, posList, true) def.setUnderlying(typ) // make sure we check instantiation works at least once diff --git a/src/go/types/unify.go b/src/go/types/unify.go index 0be4d3a62a..20cada2e69 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -429,8 +429,8 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { // return x.obj == y.obj // } if y, ok := y.(*Named); ok { - x.expand() - y.expand() + x.expand(nil) + y.expand(nil) // TODO(gri) This is not always correct: two types may have the same names // in the same package if one of them is nested in a function. // Extremely unlikely but we need an always correct solution. -- GitLab From 56a919f17f660af192855c1f7e9ede4876fefe9c Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 16 Aug 2021 13:15:47 -0400 Subject: [PATCH 0715/2500] go/types: define Identical for instances This is a port of CL 341856 to go/types. It is adjusted to use the NumTArgs/TArg API of go/types, which has not yet been ported to types2. Change-Id: I6faeec027f4ae08634267001f473263703e80c5b Reviewed-on: https://go-review.googlesource.com/c/go/+/342478 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/types/api_test.go | 26 ++++++++++++++++++++++++++ src/go/types/predicates.go | 24 ++++++++++++++++++++++++ src/go/types/unify.go | 5 ----- 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index 52c9e5afe8..1631215d15 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -1861,3 +1861,29 @@ func TestInstantiate(t *testing.T) { t.Fatalf("unexpected result type: %s points to %s", res, p) } } + +func TestInstanceIdentity(t *testing.T) { + imports := make(testImporter) + conf := Config{Importer: imports} + makePkg := func(src string) { + fset := token.NewFileSet() + f, err := parser.ParseFile(fset, "", src, 0) + if err != nil { + t.Fatal(err) + } + name := f.Name.Name + pkg, err := conf.Check(name, fset, []*ast.File{f}, nil) + if err != nil { + t.Fatal(err) + } + imports[name] = pkg + } + makePkg(genericPkg + `lib; type T[P any] struct{}`) + makePkg(genericPkg + `a; import "generic_lib"; var A generic_lib.T[int]`) + makePkg(genericPkg + `b; import "generic_lib"; var B generic_lib.T[int]`) + a := imports["generic_a"].Scope().Lookup("A") + b := imports["generic_b"].Scope().Lookup("B") + if !Identical(a.Type(), b.Type()) { + t.Errorf("mismatching types: a.A: %s, b.B: %s", a.Type(), b.Type()) + } +} diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index bd9e53d2bb..0945dac722 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -304,6 +304,30 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { if y, ok := y.(*Named); ok { x.expand(nil) y.expand(nil) + + // xargs := x.TArgs() + // yargs := y.TArgs() + + if x.NumTArgs() != y.NumTArgs() { + return false + } + + if nargs := x.NumTArgs(); nargs > 0 { + // Instances are identical if their original type and type arguments + // are identical. + if !Identical(x.orig, y.orig) { + return false + } + for i := 0; i < nargs; i++ { + xa := x.TArg(i) + ya := y.TArg(i) + if !Identical(xa, ya) { + return false + } + } + return true + } + // TODO(gri) Why is x == y not sufficient? And if it is, // we can just return false here because x == y // is caught in the very beginning of this function. diff --git a/src/go/types/unify.go b/src/go/types/unify.go index 20cada2e69..de87466fe8 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -423,11 +423,6 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { } case *Named: - // Two named types are identical if their type names originate - // in the same type declaration. - // if y, ok := y.(*Named); ok { - // return x.obj == y.obj - // } if y, ok := y.(*Named); ok { x.expand(nil) y.expand(nil) -- GitLab From d1ba047edfa6b904894fb3be1991df4300044699 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 16 Aug 2021 13:20:29 -0400 Subject: [PATCH 0716/2500] go/types: simplify Named.under This is a straighforward port of CL 341857 to go/types. Change-Id: I3407676232b595662c1470627771a13263703061 Reviewed-on: https://go-review.googlesource.com/c/go/+/342479 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/types/named.go | 52 ++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 33 deletions(-) diff --git a/src/go/types/named.go b/src/go/types/named.go index f738e8ffcc..1a8e6a9062 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -170,18 +170,13 @@ func (t *Named) String() string { return TypeString(t, nil) } // is detected, the result is Typ[Invalid]. If a cycle is detected and // n0.check != nil, the cycle is reported. func (n0 *Named) under() Type { - n0.expand(nil) - - u := n0.load().underlying - - if u == Typ[Invalid] { - return u - } + u := n0.Underlying() // If the underlying type of a defined type is not a defined // (incl. instance) type, then that is the desired underlying // type. - switch u.(type) { + var n1 *Named + switch u1 := u.(type) { case nil: return Typ[Invalid] default: @@ -189,6 +184,7 @@ func (n0 *Named) under() Type { return u case *Named: // handled below + n1 = u1 } if n0.check == nil { @@ -198,43 +194,33 @@ func (n0 *Named) under() Type { // Invariant: after this point n0 as well as any named types in its // underlying chain should be set up when this function exits. check := n0.check + n := n0 - // If we can't expand u at this point, it is invalid. - n := asNamed(u) - if n == nil { - n0.underlying = Typ[Invalid] - return n0.underlying - } + seen := make(map[*Named]int) // types that need their underlying resolved + var path []Object // objects encountered, for cycle reporting - // Otherwise, follow the forward chain. - seen := map[*Named]int{n0: 0} - path := []Object{n0.obj} +loop: for { - u = n.load().underlying - if u == nil { - u = Typ[Invalid] - break - } - var n1 *Named - switch u1 := u.(type) { - case *Named: - u1.expand(nil) - n1 = u1 - } - if n1 == nil { - break // end of chain - } - seen[n] = len(seen) path = append(path, n.obj) n = n1 - if i, ok := seen[n]; ok { // cycle check.cycleError(path[i:]) u = Typ[Invalid] break } + u = n.Underlying() + switch u1 := u.(type) { + case nil: + u = Typ[Invalid] + break loop + default: + break loop + case *Named: + // Continue collecting *Named types in the chain. + n1 = u1 + } } for n := range seen { -- GitLab From 631af58e2058677072e213aeea25e924ebf19fcf Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 16 Aug 2021 13:36:27 -0400 Subject: [PATCH 0717/2500] go/types: remove targs from substMap This is a straightforward port of CL 341859 to go/types. Change-Id: I5d2508f516b5cf4d8775c3a77cc8bed5d4bec338 Reviewed-on: https://go-review.googlesource.com/c/go/+/342480 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/types/instantiate.go | 2 +- src/go/types/subst.go | 86 +++++++++++++++---------------------- 2 files changed, 35 insertions(+), 53 deletions(-) diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 189a35ab88..8133067229 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -153,7 +153,7 @@ func (check *Checker) verify(pos token.Pos, tparams []*TypeName, targs []Type, p // parameter tpar (after any of its type parameters have been substituted through smap). // A suitable error is reported if the result is false. // TODO(gri) This should be a method of interfaces or type sets. -func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap *substMap) bool { +func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap substMap) bool { iface := tpar.iface() if iface.Empty() { return true // no type bound diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 0d3bcefb0b..da0578ff5c 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -8,42 +8,31 @@ package types import ( "bytes" - "fmt" "go/token" ) // TODO(rFindley) decide error codes for the errors in this file, and check // if error spans can be improved -type substMap struct { - // The targs field is currently needed for *Named type substitution. - // TODO(gri) rewrite that code, get rid of this field, and make this - // struct just the map (proj) - targs []Type - proj map[*TypeParam]Type -} +type substMap map[*TypeParam]Type // makeSubstMap creates a new substitution map mapping tpars[i] to targs[i]. // If targs[i] is nil, tpars[i] is not substituted. -func makeSubstMap(tpars []*TypeName, targs []Type) *substMap { +func makeSubstMap(tpars []*TypeName, targs []Type) substMap { assert(len(tpars) == len(targs)) - proj := make(map[*TypeParam]Type, len(tpars)) + proj := make(substMap, len(tpars)) for i, tpar := range tpars { proj[tpar.typ.(*TypeParam)] = targs[i] } - return &substMap{targs, proj} -} - -func (m *substMap) String() string { - return fmt.Sprintf("%s", m.proj) + return proj } -func (m *substMap) empty() bool { - return len(m.proj) == 0 +func (m substMap) empty() bool { + return len(m) == 0 } -func (m *substMap) lookup(tpar *TypeParam) Type { - if t := m.proj[tpar]; t != nil { +func (m substMap) lookup(tpar *TypeParam) Type { + if t := m[tpar]; t != nil { return t } return tpar @@ -56,7 +45,7 @@ func (m *substMap) lookup(tpar *TypeParam) Type { // from the incoming type. // // If the given typMap is nil and check is non-nil, check.typMap is used. -func (check *Checker) subst(pos token.Pos, typ Type, smap *substMap, typMap map[string]*Named) Type { +func (check *Checker) subst(pos token.Pos, typ Type, smap substMap, typMap map[string]*Named) Type { if smap.empty() { return typ } @@ -94,7 +83,7 @@ func (check *Checker) subst(pos token.Pos, typ Type, smap *substMap, typMap map[ type subster struct { pos token.Pos - smap *substMap + smap substMap check *Checker // nil if called via Instantiate typMap map[string]*Named } @@ -205,41 +194,34 @@ func (subst *subster) typ(typ Type) Type { return t // type is not parameterized } - var newTargs []Type - - if len(t.targs) > 0 { - // already instantiated - dump(">>> %s already instantiated", t) - assert(len(t.targs) == t.TParams().Len()) - // For each (existing) type argument targ, determine if it needs - // to be substituted; i.e., if it is or contains a type parameter - // that has a type argument for it. - for i, targ := range t.targs { - dump(">>> %d targ = %s", i, targ) - newTarg := subst.typ(targ) - if newTarg != targ { - dump(">>> substituted %d targ %s => %s", i, targ, newTarg) - if newTargs == nil { - newTargs = make([]Type, t.TParams().Len()) - copy(newTargs, t.targs) - } - newTargs[i] = newTarg + var newTArgs []Type + assert(len(t.targs) == t.TParams().Len()) + + // already instantiated + dump(">>> %s already instantiated", t) + // For each (existing) type argument targ, determine if it needs + // to be substituted; i.e., if it is or contains a type parameter + // that has a type argument for it. + for i, targ := range t.targs { + dump(">>> %d targ = %s", i, targ) + new_targ := subst.typ(targ) + if new_targ != targ { + dump(">>> substituted %d targ %s => %s", i, targ, new_targ) + if newTArgs == nil { + newTArgs = make([]Type, t.TParams().Len()) + copy(newTArgs, t.targs) } + newTArgs[i] = new_targ } + } - if newTargs == nil { - dump(">>> nothing to substitute in %s", t) - return t // nothing to substitute - } - } else { - // not yet instantiated - dump(">>> first instantiation of %s", t) - // TODO(rFindley) can we instead subst the tparam types here? - newTargs = subst.smap.targs + if newTArgs == nil { + dump(">>> nothing to substitute in %s", t) + return t // nothing to substitute } // before creating a new named type, check if we have this one already - h := instantiatedHash(t, newTargs) + h := instantiatedHash(t, newTArgs) dump(">>> new type hash: %s", h) if named, found := subst.typMap[h]; found { dump(">>> found %s", named) @@ -250,12 +232,12 @@ func (subst *subster) typ(typ Type) Type { tname := NewTypeName(subst.pos, t.obj.pkg, t.obj.name, nil) t.load() named := subst.check.newNamed(tname, t.orig, t.underlying, t.TParams(), t.methods) // method signatures are updated lazily - named.targs = newTargs + named.targs = newTArgs subst.typMap[h] = named t.expand(subst.typMap) // must happen after typMap update to avoid infinite recursion // do the substitution - dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, newTargs) + dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, newTArgs) named.underlying = subst.typOrNil(t.underlying) dump(">>> underlying: %v", named.underlying) assert(named.underlying != nil) -- GitLab From ddffe30a21c909314a7bab8815505b709e921c3c Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 16 Aug 2021 13:37:45 -0400 Subject: [PATCH 0718/2500] go/types: rename TypeParams to TParamList This is a straightforward port of CL 341861 to go/types. Change-Id: I4f21170eb2ea1e5395a6eba5132f34aa1d53bb20 Reviewed-on: https://go-review.googlesource.com/c/go/+/342481 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/decl.go | 2 +- src/go/types/named.go | 6 +++--- src/go/types/signature.go | 8 ++++---- src/go/types/typeparam.go | 14 +++++++------- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 35aa5e2d5a..c6505b63a1 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -631,7 +631,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { } } -func (check *Checker) collectTypeParams(list *ast.FieldList) *TypeParams { +func (check *Checker) collectTypeParams(list *ast.FieldList) *TParamList { var tparams []*TypeName // Declare type parameters up-front, with empty interface as type bound. // The scope of type parameters starts at the beginning of the type parameter diff --git a/src/go/types/named.go b/src/go/types/named.go index 1a8e6a9062..1841038fdb 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -20,7 +20,7 @@ type Named struct { fromRHS Type // type (on RHS of declaration) this *Named type is derived of (for cycle reporting) underlying Type // possibly a *Named during setup; never a *Named once set up completely instance *instance // syntactic information for lazy instantiation - tparams *TypeParams // type parameters, or nil + tparams *TParamList // type parameters, or nil targs []Type // type arguments (after instantiation), or nil methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily @@ -80,7 +80,7 @@ func (t *Named) load() *Named { } // newNamed is like NewNamed but with a *Checker receiver and additional orig argument. -func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams *TypeParams, methods []*Func) *Named { +func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams *TParamList, methods []*Func) *Named { typ := &Named{check: check, obj: obj, orig: orig, fromRHS: underlying, underlying: underlying, tparams: tparams, methods: methods} if typ.orig == nil { typ.orig = typ @@ -120,7 +120,7 @@ func (t *Named) _Orig() *Named { return t.orig } // TParams returns the type parameters of the named type t, or nil. // The result is non-nil for an (originally) parameterized type even if it is instantiated. -func (t *Named) TParams() *TypeParams { return t.load().tparams } +func (t *Named) TParams() *TParamList { return t.load().tparams } // SetTParams sets the type parameters of the named type t. func (t *Named) SetTParams(tparams []*TypeName) { t.load().tparams = bindTParams(tparams) } diff --git a/src/go/types/signature.go b/src/go/types/signature.go index ffe612d9b7..9bfb1683a7 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -21,8 +21,8 @@ type Signature struct { // and store it in the Func Object) because when type-checking a function // literal we call the general type checker which returns a general Type. // We then unpack the *Signature and use the scope for the literal body. - rparams *TypeParams // receiver type parameters from left to right, or nil - tparams *TypeParams // type parameters from left to right, or nil + rparams *TParamList // receiver type parameters from left to right, or nil + tparams *TParamList // type parameters from left to right, or nil scope *Scope // function scope, present for package-local signatures recv *Var // nil if not a method params *Tuple // (incoming) parameters from left to right; or nil @@ -56,13 +56,13 @@ func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature { func (s *Signature) Recv() *Var { return s.recv } // TParams returns the type parameters of signature s, or nil. -func (s *Signature) TParams() *TypeParams { return s.tparams } +func (s *Signature) TParams() *TParamList { return s.tparams } // SetTParams sets the type parameters of signature s. func (s *Signature) SetTParams(tparams []*TypeName) { s.tparams = bindTParams(tparams) } // RParams returns the receiver type parameters of signature s, or nil. -func (s *Signature) RParams() *TypeParams { return s.rparams } +func (s *Signature) RParams() *TParamList { return s.rparams } // SetRParams sets the receiver type params of signature s. func (s *Signature) SetRParams(rparams []*TypeName) { s.rparams = bindTParams(rparams) } diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index ce8b4a7073..6392504947 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -85,28 +85,28 @@ func (t *TypeParam) SetConstraint(bound Type) { func (t *TypeParam) Underlying() Type { return t } func (t *TypeParam) String() string { return TypeString(t, nil) } -// TypeParams holds a list of type parameters bound to a type. -type TypeParams struct{ tparams []*TypeName } +// TParamList holds a list of type parameters bound to a type. +type TParamList struct{ tparams []*TypeName } // Len returns the number of type parameters in the list. // It is safe to call on a nil receiver. -func (tps *TypeParams) Len() int { +func (tps *TParamList) Len() int { return len(tps.list()) } // At returns the i'th type parameter in the list. -func (tps *TypeParams) At(i int) *TypeName { +func (tps *TParamList) At(i int) *TypeName { return tps.list()[i] } -func (tps *TypeParams) list() []*TypeName { +func (tps *TParamList) list() []*TypeName { if tps == nil { return nil } return tps.tparams } -func bindTParams(list []*TypeName) *TypeParams { +func bindTParams(list []*TypeName) *TParamList { if len(list) == 0 { return nil } @@ -117,7 +117,7 @@ func bindTParams(list []*TypeName) *TypeParams { } typ.index = i } - return &TypeParams{tparams: list} + return &TParamList{tparams: list} } // ---------------------------------------------------------------------------- -- GitLab From d35035f84e5dbe4c740d3f338ba89b41a00e270e Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 16 Aug 2021 14:00:14 -0400 Subject: [PATCH 0719/2500] go/types: use the orig object for Named.Obj This is a port of CL 341858 to go/types. Change-Id: I9fba8941069aaacd641a19e3068de3a769e14e50 Reviewed-on: https://go-review.googlesource.com/c/go/+/342482 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/types/named.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/go/types/named.go b/src/go/types/named.go index 1841038fdb..90abd117e2 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -15,7 +15,7 @@ import ( type Named struct { check *Checker info typeInfo // for cycle detection - obj *TypeName // corresponding declared object + obj *TypeName // corresponding declared object for declared types; placeholder for instantiated types orig *Named // original, uninstantiated type fromRHS Type // type (on RHS of declaration) this *Named type is derived of (for cycle reporting) underlying Type // possibly a *Named during setup; never a *Named once set up completely @@ -108,8 +108,11 @@ func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tpar return typ } -// Obj returns the type name for the named type t. -func (t *Named) Obj() *TypeName { return t.obj } +// Obj returns the type name for the declaration defining the named type t. For +// instantiated types, this is the type name of the base type. +func (t *Named) Obj() *TypeName { + return t.orig.obj // for non-instances this is the same as t.obj +} // _Orig returns the original generic type an instantiated type is derived from. // If t is not an instantiated type, the result is t. -- GitLab From ec271687129dc8b263699b0b9d3abed71d8bd39d Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Mon, 16 Aug 2021 10:46:06 -0700 Subject: [PATCH 0720/2500] net/http: drop headers with invalid keys in Header.Write Don't let handlers inject unexpected headers by setting keys like: w.Header().Set("Evil: x\r\nSmuggle", y) Fixes #47711. Change-Id: I459ce1c79bc273a84230a0f5b665f81c46dbc672 Reviewed-on: https://go-review.googlesource.com/c/go/+/342530 Trust: Damien Neil Run-TryBot: Damien Neil Reviewed-by: Brad Fitzpatrick TryBot-Result: Go Bot --- src/net/http/header.go | 9 +++++++++ src/net/http/header_test.go | 13 +++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/net/http/header.go b/src/net/http/header.go index 4c72dcb2c8..cc9c28e3d0 100644 --- a/src/net/http/header.go +++ b/src/net/http/header.go @@ -13,6 +13,8 @@ import ( "strings" "sync" "time" + + "golang.org/x/net/http/httpguts" ) // A Header represents the key-value pairs in an HTTP header. @@ -192,6 +194,13 @@ func (h Header) writeSubset(w io.Writer, exclude map[string]bool, trace *httptra kvs, sorter := h.sortedKeyValues(exclude) var formattedVals []string for _, kv := range kvs { + if !httpguts.ValidHeaderFieldName(kv.key) { + // This could be an error. In the common case of + // writing reponse headers, however, we have no good + // way to provide the error back to the server + // handler, so just drop invalid headers instead. + continue + } for _, v := range kv.values { v = headerNewlineToSpace.Replace(v) v = textproto.TrimString(v) diff --git a/src/net/http/header_test.go b/src/net/http/header_test.go index 4789362919..57d16f51a5 100644 --- a/src/net/http/header_test.go +++ b/src/net/http/header_test.go @@ -89,6 +89,19 @@ var headerWriteTests = []struct { "k4: 4a\r\nk4: 4b\r\nk6: 6a\r\nk6: 6b\r\n" + "k7: 7a\r\nk7: 7b\r\nk8: 8a\r\nk8: 8b\r\nk9: 9a\r\nk9: 9b\r\n", }, + // Tests invalid characters in headers. + { + Header{ + "Content-Type": {"text/html; charset=UTF-8"}, + "NewlineInValue": {"1\r\nBar: 2"}, + "NewlineInKey\r\n": {"1"}, + "Colon:InKey": {"1"}, + "Evil: 1\r\nSmuggledValue": {"1"}, + }, + nil, + "Content-Type: text/html; charset=UTF-8\r\n" + + "NewlineInValue: 1 Bar: 2\r\n", + }, } func TestHeaderWrite(t *testing.T) { -- GitLab From 8d2066177dda53372469040e9bd18f836f121c58 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Wed, 28 Jul 2021 14:16:47 -0700 Subject: [PATCH 0721/2500] cmd/go/internal/modfetch/codehost: refactor gitRepo.loadRefs to be harder to misuse Previously, callers of loadRefs were expected to always call via gitRepo.refsOnce.Do and check r.refsErr. This hasn't always been the case. This change makes loadRefs cache its own result with r.refsOnce and return refs and refsErr. Callers can use it more like a normal function. CL 297950 is related. Previously, a commit like 0123456789ab could be resolved to a v0.0.0 pseudo-version when tags couldn't be fetched, but a shorter commit like 0123456 or a branch name like "master" couldn't be resolved the same way. With this change, tags must be fetched successfully ('git ls-remote' must succeed). For #42751 Change-Id: I49c9346e6c72609ee4f8b10cfe1f69781e78457e Reviewed-on: https://go-review.googlesource.com/c/go/+/338191 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/modfetch/codehost/git.go | 131 ++++++++++--------- 1 file changed, 69 insertions(+), 62 deletions(-) diff --git a/src/cmd/go/internal/modfetch/codehost/git.go b/src/cmd/go/internal/modfetch/codehost/git.go index 4d4964edf4..a782de56ff 100644 --- a/src/cmd/go/internal/modfetch/codehost/git.go +++ b/src/cmd/go/internal/modfetch/codehost/git.go @@ -170,59 +170,63 @@ func (r *gitRepo) loadLocalTags() { } // loadRefs loads heads and tags references from the remote into the map r.refs. -// Should only be called as r.refsOnce.Do(r.loadRefs). -func (r *gitRepo) loadRefs() { - // The git protocol sends all known refs and ls-remote filters them on the client side, - // so we might as well record both heads and tags in one shot. - // Most of the time we only care about tags but sometimes we care about heads too. - out, gitErr := Run(r.dir, "git", "ls-remote", "-q", r.remote) - if gitErr != nil { - if rerr, ok := gitErr.(*RunError); ok { - if bytes.Contains(rerr.Stderr, []byte("fatal: could not read Username")) { - rerr.HelpText = "Confirm the import path was entered correctly.\nIf this is a private repository, see https://golang.org/doc/faq#git_https for additional information." +// The result is cached in memory. +func (r *gitRepo) loadRefs() (map[string]string, error) { + r.refsOnce.Do(func() { + // The git protocol sends all known refs and ls-remote filters them on the client side, + // so we might as well record both heads and tags in one shot. + // Most of the time we only care about tags but sometimes we care about heads too. + out, gitErr := Run(r.dir, "git", "ls-remote", "-q", r.remote) + if gitErr != nil { + if rerr, ok := gitErr.(*RunError); ok { + if bytes.Contains(rerr.Stderr, []byte("fatal: could not read Username")) { + rerr.HelpText = "Confirm the import path was entered correctly.\nIf this is a private repository, see https://golang.org/doc/faq#git_https for additional information." + } } - } - // If the remote URL doesn't exist at all, ideally we should treat the whole - // repository as nonexistent by wrapping the error in a notExistError. - // For HTTP and HTTPS, that's easy to detect: we'll try to fetch the URL - // ourselves and see what code it serves. - if u, err := url.Parse(r.remoteURL); err == nil && (u.Scheme == "http" || u.Scheme == "https") { - if _, err := web.GetBytes(u); errors.Is(err, fs.ErrNotExist) { - gitErr = notExistError{gitErr} + // If the remote URL doesn't exist at all, ideally we should treat the whole + // repository as nonexistent by wrapping the error in a notExistError. + // For HTTP and HTTPS, that's easy to detect: we'll try to fetch the URL + // ourselves and see what code it serves. + if u, err := url.Parse(r.remoteURL); err == nil && (u.Scheme == "http" || u.Scheme == "https") { + if _, err := web.GetBytes(u); errors.Is(err, fs.ErrNotExist) { + gitErr = notExistError{gitErr} + } } - } - r.refsErr = gitErr - return - } - - r.refs = make(map[string]string) - for _, line := range strings.Split(string(out), "\n") { - f := strings.Fields(line) - if len(f) != 2 { - continue + r.refsErr = gitErr + return } - if f[1] == "HEAD" || strings.HasPrefix(f[1], "refs/heads/") || strings.HasPrefix(f[1], "refs/tags/") { - r.refs[f[1]] = f[0] + + refs := make(map[string]string) + for _, line := range strings.Split(string(out), "\n") { + f := strings.Fields(line) + if len(f) != 2 { + continue + } + if f[1] == "HEAD" || strings.HasPrefix(f[1], "refs/heads/") || strings.HasPrefix(f[1], "refs/tags/") { + refs[f[1]] = f[0] + } } - } - for ref, hash := range r.refs { - if strings.HasSuffix(ref, "^{}") { // record unwrapped annotated tag as value of tag - r.refs[strings.TrimSuffix(ref, "^{}")] = hash - delete(r.refs, ref) + for ref, hash := range refs { + if strings.HasSuffix(ref, "^{}") { // record unwrapped annotated tag as value of tag + refs[strings.TrimSuffix(ref, "^{}")] = hash + delete(refs, ref) + } } - } + r.refs = refs + }) + return r.refs, r.refsErr } func (r *gitRepo) Tags(prefix string) ([]string, error) { - r.refsOnce.Do(r.loadRefs) - if r.refsErr != nil { - return nil, r.refsErr + refs, err := r.loadRefs() + if err != nil { + return nil, err } tags := []string{} - for ref := range r.refs { + for ref := range refs { if !strings.HasPrefix(ref, "refs/tags/") { continue } @@ -237,14 +241,14 @@ func (r *gitRepo) Tags(prefix string) ([]string, error) { } func (r *gitRepo) Latest() (*RevInfo, error) { - r.refsOnce.Do(r.loadRefs) - if r.refsErr != nil { - return nil, r.refsErr + refs, err := r.loadRefs() + if err != nil { + return nil, err } - if r.refs["HEAD"] == "" { + if refs["HEAD"] == "" { return nil, ErrNoCommits } - return r.Stat(r.refs["HEAD"]) + return r.Stat(refs["HEAD"]) } // findRef finds some ref name for the given hash, @@ -252,8 +256,11 @@ func (r *gitRepo) Latest() (*RevInfo, error) { // There may be multiple ref names for a given hash, // in which case this returns some name - it doesn't matter which. func (r *gitRepo) findRef(hash string) (ref string, ok bool) { - r.refsOnce.Do(r.loadRefs) - for ref, h := range r.refs { + refs, err := r.loadRefs() + if err != nil { + return "", false + } + for ref, h := range refs { if h == hash { return ref, true } @@ -295,29 +302,32 @@ func (r *gitRepo) stat(rev string) (*RevInfo, error) { // Maybe rev is the name of a tag or branch on the remote server. // Or maybe it's the prefix of a hash of a named ref. // Try to resolve to both a ref (git name) and full (40-hex-digit) commit hash. - r.refsOnce.Do(r.loadRefs) + refs, err := r.loadRefs() + if err != nil { + return nil, err + } // loadRefs may return an error if git fails, for example segfaults, or // could not load a private repo, but defer checking to the else block // below, in case we already have the rev in question in the local cache. var ref, hash string - if r.refs["refs/tags/"+rev] != "" { + if refs["refs/tags/"+rev] != "" { ref = "refs/tags/" + rev - hash = r.refs[ref] + hash = refs[ref] // Keep rev as is: tags are assumed not to change meaning. - } else if r.refs["refs/heads/"+rev] != "" { + } else if refs["refs/heads/"+rev] != "" { ref = "refs/heads/" + rev - hash = r.refs[ref] + hash = refs[ref] rev = hash // Replace rev, because meaning of refs/heads/foo can change. - } else if rev == "HEAD" && r.refs["HEAD"] != "" { + } else if rev == "HEAD" && refs["HEAD"] != "" { ref = "HEAD" - hash = r.refs[ref] + hash = refs[ref] rev = hash // Replace rev, because meaning of HEAD can change. } else if len(rev) >= minHashDigits && len(rev) <= 40 && AllHex(rev) { // At the least, we have a hash prefix we can look up after the fetch below. // Maybe we can map it to a full hash using the known refs. prefix := rev // Check whether rev is prefix of known ref hash. - for k, h := range r.refs { + for k, h := range refs { if strings.HasPrefix(h, prefix) { if hash != "" && hash != h { // Hash is an ambiguous hash prefix. @@ -335,9 +345,6 @@ func (r *gitRepo) stat(rev string) (*RevInfo, error) { hash = rev } } else { - if r.refsErr != nil { - return nil, r.refsErr - } return nil, &UnknownRevisionError{Rev: rev} } @@ -535,12 +542,12 @@ func (r *gitRepo) ReadFileRevs(revs []string, file string, maxSize int64) (map[s // Build list of known remote refs that might help. var redo []string - r.refsOnce.Do(r.loadRefs) - if r.refsErr != nil { - return nil, r.refsErr + refs, err := r.loadRefs() + if err != nil { + return nil, err } for _, tag := range need { - if r.refs["refs/tags/"+tag] != "" { + if refs["refs/tags/"+tag] != "" { redo = append(redo, tag) } } -- GitLab From 446614182202a57b84c2742c8992c552e5fc7d3b Mon Sep 17 00:00:00 2001 From: 180909 <734461790@qq.com> Date: Mon, 16 Aug 2021 06:07:39 +0000 Subject: [PATCH 0722/2500] cmd/go: add document -json in testflag Fixes #47628 Change-Id: I2776fbc22d8a73ca7adc2cf7ad85669d57cc7eae GitHub-Last-Rev: 826907b0797cdc25f921117e2ee44fc0dc2d21c3 GitHub-Pull-Request: golang/go#47683 Reviewed-on: https://go-review.googlesource.com/c/go/+/341991 Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Jay Conrod Reviewed-by: Michael Matloob --- src/cmd/go/alldocs.go | 4 ++++ src/cmd/go/internal/test/test.go | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 7f88d3216c..f919699627 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -2658,6 +2658,10 @@ // -failfast // Do not start new tests after the first test failure. // +// -json +// Log verbose output and test results in JSON. This presents the +// same information as the -v flag in a machine-readable format. +// // -list regexp // List tests, benchmarks, or examples matching the regular expression. // No tests, benchmarks or examples will be run. This will only diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index aeba80eb68..ce8f226a96 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -242,6 +242,10 @@ control the execution of any test: -failfast Do not start new tests after the first test failure. + -json + Log verbose output and test results in JSON. This presents the + same information as the -v flag in a machine-readable format. + -list regexp List tests, benchmarks, or examples matching the regular expression. No tests, benchmarks or examples will be run. This will only -- GitLab From 41d991e4e1f3a9230cc3832a39dbf49ce9aa191f Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Wed, 14 Jul 2021 15:37:06 -0700 Subject: [PATCH 0723/2500] cmd/internal/str: add utilities for quoting and splitting args JoinAndQuoteFields does the inverse of SplitQuotedFields: it joins a list of arguments with spaces into one string, quoting arguments that contain spaces or quotes. QuotedStringListFlag uses SplitQuotedFields and JoinAndQuoteFields together to define new flags that accept lists of arguments. For golang/go#41400 Change-Id: I4986b753cb5e6fabb5b489bf26aedab889f853f5 Reviewed-on: https://go-review.googlesource.com/c/go/+/334731 Trust: Jay Conrod Trust: Michael Matloob Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills Reviewed-by: Michael Matloob Reviewed-on: https://go-review.googlesource.com/c/go/+/341935 --- src/cmd/internal/str/str.go | 72 +++++++++++++++++++++++++++ src/cmd/internal/str/str_test.go | 83 +++++++++++++++++++++++++++++++- 2 files changed, 154 insertions(+), 1 deletion(-) diff --git a/src/cmd/internal/str/str.go b/src/cmd/internal/str/str.go index 9106ebf74d..409cf8f7b4 100644 --- a/src/cmd/internal/str/str.go +++ b/src/cmd/internal/str/str.go @@ -7,7 +7,9 @@ package str import ( "bytes" + "flag" "fmt" + "strings" "unicode" "unicode/utf8" ) @@ -153,3 +155,73 @@ func SplitQuotedFields(s string) ([]string, error) { } return f, nil } + +// JoinAndQuoteFields joins a list of arguments into a string that can be parsed +// with SplitQuotedFields. Arguments are quoted only if necessary; arguments +// without spaces or quotes are kept as-is. No argument may contain both +// single and double quotes. +func JoinAndQuoteFields(args []string) (string, error) { + var buf []byte + for i, arg := range args { + if i > 0 { + buf = append(buf, ' ') + } + var sawSpace, sawSingleQuote, sawDoubleQuote bool + for _, c := range arg { + switch { + case c > unicode.MaxASCII: + continue + case isSpaceByte(byte(c)): + sawSpace = true + case c == '\'': + sawSingleQuote = true + case c == '"': + sawDoubleQuote = true + } + } + switch { + case !sawSpace && !sawSingleQuote && !sawDoubleQuote: + buf = append(buf, []byte(arg)...) + + case !sawSingleQuote: + buf = append(buf, '\'') + buf = append(buf, []byte(arg)...) + buf = append(buf, '\'') + + case !sawDoubleQuote: + buf = append(buf, '"') + buf = append(buf, []byte(arg)...) + buf = append(buf, '"') + + default: + return "", fmt.Errorf("argument %q contains both single and double quotes and cannot be quoted", arg) + } + } + return string(buf), nil +} + +// A QuotedStringListFlag parses a list of string arguments encoded with +// JoinAndQuoteFields. It is useful for flags like cmd/link's -extldflags. +type QuotedStringListFlag []string + +var _ flag.Value = (*QuotedStringListFlag)(nil) + +func (f *QuotedStringListFlag) Set(v string) error { + fs, err := SplitQuotedFields(v) + if err != nil { + return err + } + *f = fs[:len(fs):len(fs)] + return nil +} + +func (f *QuotedStringListFlag) String() string { + if f == nil { + return "" + } + s, err := JoinAndQuoteFields(*f) + if err != nil { + return strings.Join(*f, " ") + } + return s +} diff --git a/src/cmd/internal/str/str_test.go b/src/cmd/internal/str/str_test.go index 147ce1a63e..3609af6a06 100644 --- a/src/cmd/internal/str/str_test.go +++ b/src/cmd/internal/str/str_test.go @@ -4,7 +4,11 @@ package str -import "testing" +import ( + "reflect" + "strings" + "testing" +) var foldDupTests = []struct { list []string @@ -25,3 +29,80 @@ func TestFoldDup(t *testing.T) { } } } + +func TestSplitQuotedFields(t *testing.T) { + for _, test := range []struct { + name string + value string + want []string + wantErr string + }{ + {name: "empty", value: "", want: nil}, + {name: "space", value: " ", want: nil}, + {name: "one", value: "a", want: []string{"a"}}, + {name: "leading_space", value: " a", want: []string{"a"}}, + {name: "trailing_space", value: "a ", want: []string{"a"}}, + {name: "two", value: "a b", want: []string{"a", "b"}}, + {name: "two_multi_space", value: "a b", want: []string{"a", "b"}}, + {name: "two_tab", value: "a\tb", want: []string{"a", "b"}}, + {name: "two_newline", value: "a\nb", want: []string{"a", "b"}}, + {name: "quote_single", value: `'a b'`, want: []string{"a b"}}, + {name: "quote_double", value: `"a b"`, want: []string{"a b"}}, + {name: "quote_both", value: `'a '"b "`, want: []string{"a ", "b "}}, + {name: "quote_contains", value: `'a "'"'b"`, want: []string{`a "`, `'b`}}, + {name: "escape", value: `\'`, want: []string{`\'`}}, + {name: "quote_unclosed", value: `'a`, wantErr: "unterminated ' string"}, + } { + t.Run(test.name, func(t *testing.T) { + got, err := SplitQuotedFields(test.value) + if err != nil { + if test.wantErr == "" { + t.Fatalf("unexpected error: %v", err) + } else if errMsg := err.Error(); !strings.Contains(errMsg, test.wantErr) { + t.Fatalf("error %q does not contain %q", errMsg, test.wantErr) + } + return + } + if test.wantErr != "" { + t.Fatalf("unexpected success; wanted error containing %q", test.wantErr) + } + if !reflect.DeepEqual(got, test.want) { + t.Errorf("got %q; want %q", got, test.want) + } + }) + } +} + +func TestJoinAndQuoteFields(t *testing.T) { + for _, test := range []struct { + name string + args []string + want, wantErr string + }{ + {name: "empty", args: nil, want: ""}, + {name: "one", args: []string{"a"}, want: "a"}, + {name: "two", args: []string{"a", "b"}, want: "a b"}, + {name: "space", args: []string{"a ", "b"}, want: "'a ' b"}, + {name: "newline", args: []string{"a\n", "b"}, want: "'a\n' b"}, + {name: "quote", args: []string{`'a `, "b"}, want: `"'a " b`}, + {name: "unquoteable", args: []string{`'"`}, wantErr: "contains both single and double quotes and cannot be quoted"}, + } { + t.Run(test.name, func(t *testing.T) { + got, err := JoinAndQuoteFields(test.args) + if err != nil { + if test.wantErr == "" { + t.Fatalf("unexpected error: %v", err) + } else if errMsg := err.Error(); !strings.Contains(errMsg, test.wantErr) { + t.Fatalf("error %q does not contain %q", errMsg, test.wantErr) + } + return + } + if test.wantErr != "" { + t.Fatalf("unexpected success; wanted error containing %q", test.wantErr) + } + if got != test.want { + t.Errorf("got %s; want %s", got, test.want) + } + }) + } +} -- GitLab From 742dcba7bb953a96c9f3fcdeb32b1c03cbbd8d5e Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Wed, 14 Jul 2021 16:57:24 -0700 Subject: [PATCH 0724/2500] cmd: support space and quotes in CC and CXX The CC and CXX environment variables now support spaces and quotes (both double and single). This fixes two issues: first, if CC is a single path that contains spaces (like 'c:\Program Files\gcc\bin\gcc.exe'), that should now work if the space is quoted or escaped (#41400). Second, if CC or CXX has multiple arguments (like 'gcc -O2'), they are now split correctly, and the arguments are passed before other arguments when invoking the C compiler. Previously, strings.Fields was used to split arguments, and the arguments were placed later in the command line. (#43078). Fixes golang/go#41400 Fixes golang/go#43078 NOTE: This change also includes a fix (CL 341929) for a test that was broken by the original CL. Commit message for the fix is below. [dev.cmdgo] cmd/link: fix TestBuildForTvOS This test was broken in CL 334732 on darwin. The test invokes 'go build' with a CC containing the arguments -framework CoreFoundation. Previously, the go command split CC on whitespace, and inserted the arguments after the command line when running CC directly. Those arguments weren't passed to cgo though, so cgo ran CC without -framework CoreFoundation (or any of the other flags). In CL 334732, we pass CC through to cgo, and cgo splits arguments using str.SplitQuotedFields. So -framework CoreFoundation actually gets passed to the C compiler. It appears that -framework flags are only meant to be used in linking operations, so when cgo invokes clang with -E (run preprocessor only), clang emits an error that -framework is unused. This change fixes the test by moving -framework CoreFoundation out of CC and into CGO_LDFLAGS. Change-Id: I2d5d89ddb19c94adef65982a8137b01f037d5c11 Reviewed-on: https://go-review.googlesource.com/c/go/+/334732 Trust: Jay Conrod Trust: Michael Matloob Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Michael Matloob Reviewed-on: https://go-review.googlesource.com/c/go/+/341936 Reviewed-by: Bryan C. Mills --- src/cmd/cgo/gcc.go | 46 ++++++++++----- src/cmd/cgo/main.go | 8 +-- .../compile/internal/ssa/stmtlines_test.go | 7 ++- src/cmd/dist/buildtool.go | 1 + src/cmd/go/internal/envcmd/env.go | 34 +++++++---- src/cmd/go/internal/work/exec.go | 43 +++++--------- src/cmd/go/internal/work/gc.go | 37 +++++------- src/cmd/go/internal/work/init.go | 16 +++++- src/cmd/go/script_test.go | 1 + .../testdata/script/cgo_path_space_quote.txt | 56 +++++++++++++++++++ src/cmd/internal/dwarf/dwarf.go | 6 +- src/cmd/link/dwarf_test.go | 8 ++- src/cmd/link/internal/ld/lib.go | 39 ++++++++----- src/cmd/link/internal/ld/main.go | 7 ++- src/cmd/link/link_test.go | 4 +- 15 files changed, 209 insertions(+), 104 deletions(-) create mode 100644 src/cmd/go/testdata/script/cgo_path_space_quote.txt diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index a73e998877..92adb1ed9c 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -23,10 +23,13 @@ import ( "internal/xcoff" "math" "os" + "os/exec" "strconv" "strings" "unicode" "unicode/utf8" + + "cmd/internal/str" ) var debugDefine = flag.Bool("debug-define", false, "print relevant #defines") @@ -382,7 +385,7 @@ func (p *Package) guessKinds(f *File) []*Name { stderr = p.gccErrors(b.Bytes()) } if stderr == "" { - fatalf("%s produced no output\non input:\n%s", p.gccBaseCmd()[0], b.Bytes()) + fatalf("%s produced no output\non input:\n%s", gccBaseCmd[0], b.Bytes()) } completed := false @@ -457,7 +460,7 @@ func (p *Package) guessKinds(f *File) []*Name { } if !completed { - fatalf("%s did not produce error at completed:1\non input:\n%s\nfull error output:\n%s", p.gccBaseCmd()[0], b.Bytes(), stderr) + fatalf("%s did not produce error at completed:1\non input:\n%s\nfull error output:\n%s", gccBaseCmd[0], b.Bytes(), stderr) } for i, n := range names { @@ -488,7 +491,7 @@ func (p *Package) guessKinds(f *File) []*Name { // to users debugging preamble mistakes. See issue 8442. preambleErrors := p.gccErrors([]byte(f.Preamble)) if len(preambleErrors) > 0 { - error_(token.NoPos, "\n%s errors for preamble:\n%s", p.gccBaseCmd()[0], preambleErrors) + error_(token.NoPos, "\n%s errors for preamble:\n%s", gccBaseCmd[0], preambleErrors) } fatalf("unresolved names") @@ -1545,20 +1548,37 @@ func gofmtPos(n ast.Expr, pos token.Pos) string { return fmt.Sprintf("/*line :%d:%d*/%s", p.Line, p.Column, s) } -// gccBaseCmd returns the start of the compiler command line. +// checkGCCBaseCmd returns the start of the compiler command line. // It uses $CC if set, or else $GCC, or else the compiler recorded // during the initial build as defaultCC. // defaultCC is defined in zdefaultcc.go, written by cmd/dist. -func (p *Package) gccBaseCmd() []string { +// +// The compiler command line is split into arguments on whitespace. Quotes +// are understood, so arguments may contain whitespace. +// +// checkGCCBaseCmd confirms that the compiler exists in PATH, returning +// an error if it does not. +func checkGCCBaseCmd() ([]string, error) { // Use $CC if set, since that's what the build uses. - if ret := strings.Fields(os.Getenv("CC")); len(ret) > 0 { - return ret + value := os.Getenv("CC") + if value == "" { + // Try $GCC if set, since that's what we used to use. + value = os.Getenv("GCC") + } + if value == "" { + value = defaultCC(goos, goarch) + } + args, err := str.SplitQuotedFields(value) + if err != nil { + return nil, err + } + if len(args) == 0 { + return nil, errors.New("CC not set and no default found") } - // Try $GCC if set, since that's what we used to use. - if ret := strings.Fields(os.Getenv("GCC")); len(ret) > 0 { - return ret + if _, err := exec.LookPath(args[0]); err != nil { + return nil, fmt.Errorf("C compiler %q not found: %v", args[0], err) } - return strings.Fields(defaultCC(goos, goarch)) + return args[:len(args):len(args)], nil } // gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm". @@ -1604,7 +1624,7 @@ func gccTmp() string { // gccCmd returns the gcc command line to use for compiling // the input. func (p *Package) gccCmd() []string { - c := append(p.gccBaseCmd(), + c := append(gccBaseCmd, "-w", // no warnings "-Wno-error", // warnings are not errors "-o"+gccTmp(), // write object to tmp @@ -2005,7 +2025,7 @@ func (p *Package) gccDebug(stdin []byte, nnames int) (d *dwarf.Data, ints []int6 // #defines that gcc encountered while processing the input // and its included files. func (p *Package) gccDefines(stdin []byte) string { - base := append(p.gccBaseCmd(), "-E", "-dM", "-xc") + base := append(gccBaseCmd, "-E", "-dM", "-xc") base = append(base, p.gccMachine()...) stdout, _ := runGcc(stdin, append(append(base, p.GccOptions...), "-")) return stdout diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go index c6a0c525e6..14642b7576 100644 --- a/src/cmd/cgo/main.go +++ b/src/cmd/cgo/main.go @@ -21,7 +21,6 @@ import ( "io" "io/ioutil" "os" - "os/exec" "path/filepath" "reflect" "runtime" @@ -248,6 +247,7 @@ var importSyscall = flag.Bool("import_syscall", true, "import syscall in generat var trimpath = flag.String("trimpath", "", "applies supplied rewrites or trims prefixes to recorded source file paths") var goarch, goos, gomips, gomips64 string +var gccBaseCmd []string func main() { objabi.AddVersionFlag() // -V @@ -305,10 +305,10 @@ func main() { p := newPackage(args[:i]) // We need a C compiler to be available. Check this. - gccName := p.gccBaseCmd()[0] - _, err := exec.LookPath(gccName) + var err error + gccBaseCmd, err = checkGCCBaseCmd() if err != nil { - fatalf("C compiler %q not found: %v", gccName, err) + fatalf("%v", err) os.Exit(2) } diff --git a/src/cmd/compile/internal/ssa/stmtlines_test.go b/src/cmd/compile/internal/ssa/stmtlines_test.go index a510d0b3d0..843db8c07e 100644 --- a/src/cmd/compile/internal/ssa/stmtlines_test.go +++ b/src/cmd/compile/internal/ssa/stmtlines_test.go @@ -2,6 +2,7 @@ package ssa_test import ( cmddwarf "cmd/internal/dwarf" + "cmd/internal/str" "debug/dwarf" "debug/elf" "debug/macho" @@ -57,7 +58,11 @@ func TestStmtLines(t *testing.T) { if extld == "" { extld = "gcc" } - enabled, err := cmddwarf.IsDWARFEnabledOnAIXLd(extld) + extldArgs, err := str.SplitQuotedFields(extld) + if err != nil { + t.Fatal(err) + } + enabled, err := cmddwarf.IsDWARFEnabledOnAIXLd(extldArgs) if err != nil { t.Fatal(err) } diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go index 26b33e389f..320c62f850 100644 --- a/src/cmd/dist/buildtool.go +++ b/src/cmd/dist/buildtool.go @@ -47,6 +47,7 @@ var bootstrapDirs = []string{ "cmd/internal/objabi", "cmd/internal/pkgpath", "cmd/internal/src", + "cmd/internal/str", "cmd/internal/sys", "cmd/link", "cmd/link/internal/...", diff --git a/src/cmd/go/internal/envcmd/env.go b/src/cmd/go/internal/envcmd/env.go index 1553d26391..483ce2a4f5 100644 --- a/src/cmd/go/internal/envcmd/env.go +++ b/src/cmd/go/internal/envcmd/env.go @@ -26,6 +26,7 @@ import ( "cmd/go/internal/load" "cmd/go/internal/modload" "cmd/go/internal/work" + "cmd/internal/str" ) var CmdEnv = &base.Command{ @@ -104,13 +105,13 @@ func MkEnv() []cfg.EnvVar { env = append(env, cfg.EnvVar{Name: key, Value: val}) } - cc := cfg.DefaultCC(cfg.Goos, cfg.Goarch) - if env := strings.Fields(cfg.Getenv("CC")); len(env) > 0 { - cc = env[0] + cc := cfg.Getenv("CC") + if cc == "" { + cc = cfg.DefaultCC(cfg.Goos, cfg.Goarch) } - cxx := cfg.DefaultCXX(cfg.Goos, cfg.Goarch) - if env := strings.Fields(cfg.Getenv("CXX")); len(env) > 0 { - cxx = env[0] + cxx := cfg.Getenv("CXX") + if cxx == "" { + cxx = cfg.DefaultCXX(cfg.Goos, cfg.Goarch) } env = append(env, cfg.EnvVar{Name: "AR", Value: envOr("AR", "ar")}) env = append(env, cfg.EnvVar{Name: "CC", Value: cc}) @@ -457,10 +458,23 @@ func checkEnvWrite(key, val string) error { if !filepath.IsAbs(val) && val != "" { return fmt.Errorf("GOPATH entry is relative; must be absolute path: %q", val) } - // Make sure CC and CXX are absolute paths - case "CC", "CXX", "GOMODCACHE": - if !filepath.IsAbs(val) && val != "" && val != filepath.Base(val) { - return fmt.Errorf("%s entry is relative; must be absolute path: %q", key, val) + case "GOMODCACHE": + if !filepath.IsAbs(val) && val != "" { + return fmt.Errorf("GOMODCACHE entry is relative; must be absolute path: %q", val) + } + case "CC", "CXX": + if val == "" { + break + } + args, err := str.SplitQuotedFields(val) + if err != nil { + return fmt.Errorf("invalid %s: %v", key, err) + } + if len(args) == 0 { + return fmt.Errorf("%s entry cannot contain only space", key) + } + if !filepath.IsAbs(args[0]) && args[0] != filepath.Base(args[0]) { + return fmt.Errorf("%s entry is relative; must be absolute path: %q", key, args[0]) } } diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index 2aa099bf17..f7fae9fdd9 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -1487,6 +1487,8 @@ func (b *Builder) getPkgConfigFlags(p *load.Package) (cflags, ldflags []string, return nil, nil, errPrintedOutput } if len(out) > 0 { + // NOTE: we don't attempt to parse quotes and unescapes here. pkg-config + // is typically used within shell backticks, which treats quotes literally. ldflags = strings.Fields(string(out)) if err := checkLinkerFlags("LDFLAGS", "pkg-config --libs", ldflags); err != nil { return nil, nil, err @@ -2429,12 +2431,6 @@ func (b *Builder) gccld(a *Action, p *load.Package, objdir, outfile string, flag return err } -// Grab these before main helpfully overwrites them. -var ( - origCC = cfg.Getenv("CC") - origCXX = cfg.Getenv("CXX") -) - // gccCmd returns a gcc command line prefix // defaultCC is defined in zdefaultcc.go, written by cmd/dist. func (b *Builder) GccCmd(incdir, workdir string) []string { @@ -2454,40 +2450,23 @@ func (b *Builder) gfortranCmd(incdir, workdir string) []string { // ccExe returns the CC compiler setting without all the extra flags we add implicitly. func (b *Builder) ccExe() []string { - return b.compilerExe(origCC, cfg.DefaultCC(cfg.Goos, cfg.Goarch)) + return envList("CC", cfg.DefaultCC(cfg.Goos, cfg.Goarch)) } // cxxExe returns the CXX compiler setting without all the extra flags we add implicitly. func (b *Builder) cxxExe() []string { - return b.compilerExe(origCXX, cfg.DefaultCXX(cfg.Goos, cfg.Goarch)) + return envList("CXX", cfg.DefaultCXX(cfg.Goos, cfg.Goarch)) } // fcExe returns the FC compiler setting without all the extra flags we add implicitly. func (b *Builder) fcExe() []string { - return b.compilerExe(cfg.Getenv("FC"), "gfortran") -} - -// compilerExe returns the compiler to use given an -// environment variable setting (the value not the name) -// and a default. The resulting slice is usually just the name -// of the compiler but can have additional arguments if they -// were present in the environment value. -// For example if CC="gcc -DGOPHER" then the result is ["gcc", "-DGOPHER"]. -func (b *Builder) compilerExe(envValue string, def string) []string { - compiler := strings.Fields(envValue) - if len(compiler) == 0 { - compiler = strings.Fields(def) - } - return compiler + return envList("FC", "gfortran") } // compilerCmd returns a command line prefix for the given environment // variable and using the default command when the variable is empty. func (b *Builder) compilerCmd(compiler []string, incdir, workdir string) []string { - // NOTE: env.go's mkEnv knows that the first three - // strings returned are "gcc", "-I", incdir (and cuts them off). - a := []string{compiler[0], "-I", incdir} - a = append(a, compiler[1:]...) + a := append(compiler, "-I", incdir) // Definitely want -fPIC but on Windows gcc complains // "-fPIC ignored for target (all code is position independent)" @@ -2658,12 +2637,20 @@ func (b *Builder) gccArchArgs() []string { // envList returns the value of the given environment variable broken // into fields, using the default value when the variable is empty. +// +// The environment variable must be quoted correctly for +// str.SplitQuotedFields. This should be done before building +// anything, for example, in BuildInit. func envList(key, def string) []string { v := cfg.Getenv(key) if v == "" { v = def } - return strings.Fields(v) + args, err := str.SplitQuotedFields(v) + if err != nil { + panic(fmt.Sprintf("could not parse environment variable %s with value %q: %v", key, v, err)) + } + return args } // CFlags returns the flags to use when invoking the C, C++ or Fortran compilers, or cgo. diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go index 70ca5d69f8..74e14d0065 100644 --- a/src/cmd/go/internal/work/gc.go +++ b/src/cmd/go/internal/work/gc.go @@ -545,33 +545,18 @@ func packInternal(afile string, ofiles []string) error { } // setextld sets the appropriate linker flags for the specified compiler. -func setextld(ldflags []string, compiler []string) []string { +func setextld(ldflags []string, compiler []string) ([]string, error) { for _, f := range ldflags { if f == "-extld" || strings.HasPrefix(f, "-extld=") { // don't override -extld if supplied - return ldflags + return ldflags, nil } } - ldflags = append(ldflags, "-extld="+compiler[0]) - if len(compiler) > 1 { - extldflags := false - add := strings.Join(compiler[1:], " ") - for i, f := range ldflags { - if f == "-extldflags" && i+1 < len(ldflags) { - ldflags[i+1] = add + " " + ldflags[i+1] - extldflags = true - break - } else if strings.HasPrefix(f, "-extldflags=") { - ldflags[i] = "-extldflags=" + add + " " + ldflags[i][len("-extldflags="):] - extldflags = true - break - } - } - if !extldflags { - ldflags = append(ldflags, "-extldflags="+add) - } + joined, err := str.JoinAndQuoteFields(compiler) + if err != nil { + return nil, err } - return ldflags + return append(ldflags, "-extld="+joined), nil } // pluginPath computes the package path for a plugin main package. @@ -658,7 +643,10 @@ func (gcToolchain) ld(b *Builder, root *Action, out, importcfg, mainpkg string) } ldflags = append(ldflags, forcedLdflags...) ldflags = append(ldflags, root.Package.Internal.Ldflags...) - ldflags = setextld(ldflags, compiler) + ldflags, err := setextld(ldflags, compiler) + if err != nil { + return err + } // On OS X when using external linking to build a shared library, // the argument passed here to -o ends up recorded in the final @@ -702,7 +690,10 @@ func (gcToolchain) ldShared(b *Builder, root *Action, toplevelactions []*Action, } else { compiler = envList("CC", cfg.DefaultCC(cfg.Goos, cfg.Goarch)) } - ldflags = setextld(ldflags, compiler) + ldflags, err := setextld(ldflags, compiler) + if err != nil { + return err + } for _, d := range toplevelactions { if !strings.HasSuffix(d.Target, ".a") { // omit unsafe etc and actions for other shared libraries continue diff --git a/src/cmd/go/internal/work/init.go b/src/cmd/go/internal/work/init.go index 37a3e2d0ff..022137390f 100644 --- a/src/cmd/go/internal/work/init.go +++ b/src/cmd/go/internal/work/init.go @@ -11,6 +11,7 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/fsys" "cmd/go/internal/modload" + "cmd/internal/str" "cmd/internal/sys" "flag" "fmt" @@ -39,9 +40,18 @@ func BuildInit() { cfg.BuildPkgdir = p } - // Make sure CC and CXX are absolute paths - for _, key := range []string{"CC", "CXX"} { - if path := cfg.Getenv(key); !filepath.IsAbs(path) && path != "" && path != filepath.Base(path) { + // Make sure CC, CXX, and FC are absolute paths. + for _, key := range []string{"CC", "CXX", "FC"} { + value := cfg.Getenv(key) + args, err := str.SplitQuotedFields(value) + if err != nil { + base.Fatalf("go %s: %s environment variable could not be parsed: %v", flag.Args()[0], key, err) + } + if len(args) == 0 { + continue + } + path := args[0] + if !filepath.IsAbs(path) && path != filepath.Base(path) { base.Fatalf("go %s: %s environment variable is relative; must be absolute path: %s\n", flag.Args()[0], key, path) } } diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go index 9ca297e89b..8a7c77a46f 100644 --- a/src/cmd/go/script_test.go +++ b/src/cmd/go/script_test.go @@ -184,6 +184,7 @@ func (ts *testScript) setup() { "devnull=" + os.DevNull, "goversion=" + goVersion(ts), ":=" + string(os.PathListSeparator), + "/=" + string(os.PathSeparator), } if !testenv.HasExternalNetwork() { ts.env = append(ts.env, "TESTGONETWORK=panic", "TESTGOVCS=panic") diff --git a/src/cmd/go/testdata/script/cgo_path_space_quote.txt b/src/cmd/go/testdata/script/cgo_path_space_quote.txt new file mode 100644 index 0000000000..3b89bfb800 --- /dev/null +++ b/src/cmd/go/testdata/script/cgo_path_space_quote.txt @@ -0,0 +1,56 @@ +# This test checks that the CC environment variable may contain quotes and +# spaces. Arguments are normally split on spaces, tabs, newlines. If an +# argument contains these characters, the entire argument may be quoted +# with single or double quotes. This is the same as -gcflags and similar +# options. + +[short] skip +[!exec:clang] [!exec:gcc] skip + +env GOENV=$WORK/go.env +mkdir 'program files' +go build -o 'program files' './which cc/which cc.go' +[exec:clang] env CC='"'$PWD${/}program' 'files${/}which' 'cc"' 'clang +[!exec:clang] env CC='"'$PWD${/}program' 'files${/}which' 'cc"' 'gcc +go env CC +stdout 'program files[/\\]which cc" (clang|gcc)$' +go env -w CC=$CC +env CC= +go env CC +stdout 'program files[/\\]which cc" (clang|gcc)$' + +go run . + +-- go.mod -- +module test + +go 1.17 +-- which cc/which cc.go -- +package main + +import ( + "fmt" + "os" + "os/exec" +) + +func main() { + args := append([]string{"-DWRAPPER_WAS_USED=1"}, os.Args[2:]...) + cmd := exec.Command(os.Args[1], args...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} +-- hello.go -- +package main + +// int x = WRAPPER_WAS_USED; +import "C" +import "fmt" + +func main() { + fmt.Println(C.x) +} diff --git a/src/cmd/internal/dwarf/dwarf.go b/src/cmd/internal/dwarf/dwarf.go index 860c7d6c0d..4e163db020 100644 --- a/src/cmd/internal/dwarf/dwarf.go +++ b/src/cmd/internal/dwarf/dwarf.go @@ -1617,8 +1617,10 @@ func (s byChildIndex) Swap(i, j int) { s[i], s[j] = s[j], s[i] } // current extld. // AIX ld doesn't support DWARF with -bnoobjreorder with version // prior to 7.2.2. -func IsDWARFEnabledOnAIXLd(extld string) (bool, error) { - out, err := exec.Command(extld, "-Wl,-V").CombinedOutput() +func IsDWARFEnabledOnAIXLd(extld []string) (bool, error) { + name, args := extld[0], extld[1:] + args = append(args, "-Wl,-V") + out, err := exec.Command(name, args...).CombinedOutput() if err != nil { // The normal output should display ld version and // then fails because ".main" is not defined: diff --git a/src/cmd/link/dwarf_test.go b/src/cmd/link/dwarf_test.go index 3ca59bd47f..f7bbb014d9 100644 --- a/src/cmd/link/dwarf_test.go +++ b/src/cmd/link/dwarf_test.go @@ -8,6 +8,7 @@ import ( "bytes" cmddwarf "cmd/internal/dwarf" "cmd/internal/objfile" + "cmd/internal/str" "debug/dwarf" "internal/testenv" "os" @@ -67,8 +68,11 @@ func testDWARF(t *testing.T, buildmode string, expectDWARF bool, env ...string) if extld == "" { extld = "gcc" } - var err error - expectDWARF, err = cmddwarf.IsDWARFEnabledOnAIXLd(extld) + extldArgs, err := str.SplitQuotedFields(extld) + if err != nil { + t.Fatal(err) + } + expectDWARF, err = cmddwarf.IsDWARFEnabledOnAIXLd(extldArgs) if err != nil { t.Fatal(err) } diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 894e5afe63..494fea5e72 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -464,23 +464,24 @@ func loadinternal(ctxt *Link, name string) *sym.Library { } // extld returns the current external linker. -func (ctxt *Link) extld() string { - if *flagExtld == "" { - *flagExtld = "gcc" +func (ctxt *Link) extld() []string { + if len(flagExtld) == 0 { + flagExtld = []string{"gcc"} } - return *flagExtld + return flagExtld } // findLibPathCmd uses cmd command to find gcc library libname. // It returns library full path if found, or "none" if not found. func (ctxt *Link) findLibPathCmd(cmd, libname string) string { extld := ctxt.extld() - args := hostlinkArchArgs(ctxt.Arch) + name, args := extld[0], extld[1:] + args = append(args, hostlinkArchArgs(ctxt.Arch)...) args = append(args, cmd) if ctxt.Debugvlog != 0 { ctxt.Logf("%s %v\n", extld, args) } - out, err := exec.Command(extld, args...).Output() + out, err := exec.Command(name, args...).Output() if err != nil { if ctxt.Debugvlog != 0 { ctxt.Logf("not using a %s file because compiler failed\n%v\n%s\n", libname, err, out) @@ -1242,7 +1243,7 @@ func (ctxt *Link) hostlink() { } var argv []string - argv = append(argv, ctxt.extld()) + argv = append(argv, ctxt.extld()...) argv = append(argv, hostlinkArchArgs(ctxt.Arch)...) if *FlagS || debug_s { @@ -1403,7 +1404,9 @@ func (ctxt *Link) hostlink() { // If gold is not installed, gcc will silently switch // back to ld.bfd. So we parse the version information // and provide a useful error if gold is missing. - cmd := exec.Command(*flagExtld, "-fuse-ld=gold", "-Wl,--version") + name, args := flagExtld[0], flagExtld[1:] + args = append(args, "-fuse-ld=gold", "-Wl,--version") + cmd := exec.Command(name, args...) if out, err := cmd.CombinedOutput(); err == nil { if !bytes.Contains(out, []byte("GNU gold")) { log.Fatalf("ARM external linker must be gold (issue #15696), but is not: %s", out) @@ -1416,7 +1419,9 @@ func (ctxt *Link) hostlink() { altLinker = "bfd" // Provide a useful error if ld.bfd is missing. - cmd := exec.Command(*flagExtld, "-fuse-ld=bfd", "-Wl,--version") + name, args := flagExtld[0], flagExtld[1:] + args = append(args, "-fuse-ld=bfd", "-Wl,--version") + cmd := exec.Command(name, args...) if out, err := cmd.CombinedOutput(); err == nil { if !bytes.Contains(out, []byte("GNU ld")) { log.Fatalf("ARM64 external linker must be ld.bfd (issue #35197), please install devel/binutils") @@ -1484,10 +1489,11 @@ func (ctxt *Link) hostlink() { argv = append(argv, "/lib/crt0_64.o") extld := ctxt.extld() + name, args := extld[0], extld[1:] // Get starting files. getPathFile := func(file string) string { - args := []string{"-maix64", "--print-file-name=" + file} - out, err := exec.Command(extld, args...).CombinedOutput() + args := append(args, "-maix64", "--print-file-name="+file) + out, err := exec.Command(name, args...).CombinedOutput() if err != nil { log.Fatalf("running %s failed: %v\n%s", extld, err, out) } @@ -1569,14 +1575,18 @@ func (ctxt *Link) hostlink() { } } - for _, p := range strings.Fields(*flagExtldflags) { + for _, p := range flagExtldflags { argv = append(argv, p) checkStatic(p) } if ctxt.HeadType == objabi.Hwindows { // Determine which linker we're using. Add in the extldflags in // case used has specified "-fuse-ld=...". - cmd := exec.Command(*flagExtld, *flagExtldflags, "-Wl,--version") + extld := ctxt.extld() + name, args := extld[0], extld[1:] + args = append(args, flagExtldflags...) + args = append(args, "-Wl,--version") + cmd := exec.Command(name, args...) usingLLD := false if out, err := cmd.CombinedOutput(); err == nil { if bytes.Contains(out, []byte("LLD ")) { @@ -1720,8 +1730,7 @@ func linkerFlagSupported(arch *sys.Arch, linker, altLinker, flag string) bool { flags := hostlinkArchArgs(arch) keep := false skip := false - extldflags := strings.Fields(*flagExtldflags) - for _, f := range append(extldflags, ldflag...) { + for _, f := range append(flagExtldflags, ldflag...) { if keep { flags = append(flags, f) keep = false diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go index cba0e3d81f..33b03b5024 100644 --- a/src/cmd/link/internal/ld/main.go +++ b/src/cmd/link/internal/ld/main.go @@ -34,6 +34,7 @@ import ( "bufio" "cmd/internal/goobj" "cmd/internal/objabi" + "cmd/internal/str" "cmd/internal/sys" "cmd/link/internal/benchmark" "flag" @@ -53,6 +54,8 @@ var ( func init() { flag.Var(&rpath, "r", "set the ELF dynamic linker search `path` to dir1:dir2:...") + flag.Var(&flagExtld, "extld", "use `linker` when linking in external mode") + flag.Var(&flagExtldflags, "extldflags", "pass `flags` to external linker") } // Flags used by the linker. The exported flags are used by the architecture-specific packages. @@ -72,8 +75,8 @@ var ( flagLibGCC = flag.String("libgcc", "", "compiler support lib for internal linking; use \"none\" to disable") flagTmpdir = flag.String("tmpdir", "", "use `directory` for temporary files") - flagExtld = flag.String("extld", "", "use `linker` when linking in external mode") - flagExtldflags = flag.String("extldflags", "", "pass `flags` to external linker") + flagExtld str.QuotedStringListFlag + flagExtldflags str.QuotedStringListFlag flagExtar = flag.String("extar", "", "archive program for buildmode=c-archive") flagA = flag.Bool("a", false, "no-op (deprecated)") diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go index fed9c7bc3f..2b0b2dc4a1 100644 --- a/src/cmd/link/link_test.go +++ b/src/cmd/link/link_test.go @@ -282,8 +282,8 @@ func TestBuildForTvOS(t *testing.T) { "-isysroot", strings.TrimSpace(string(sdkPath)), "-mtvos-version-min=12.0", "-fembed-bitcode", - "-framework", "CoreFoundation", } + CGO_LDFLAGS := []string{"-framework", "CoreFoundation"} lib := filepath.Join("testdata", "testBuildFortvOS", "lib.go") tmpDir := t.TempDir() @@ -295,12 +295,14 @@ func TestBuildForTvOS(t *testing.T) { "GOARCH=arm64", "CC="+strings.Join(CC, " "), "CGO_CFLAGS=", // ensure CGO_CFLAGS does not contain any flags. Issue #35459 + "CGO_LDFLAGS="+strings.Join(CGO_LDFLAGS, " "), ) if out, err := cmd.CombinedOutput(); err != nil { t.Fatalf("%v: %v:\n%s", cmd.Args, err, out) } link := exec.Command(CC[0], CC[1:]...) + link.Args = append(link.Args, CGO_LDFLAGS...) link.Args = append(link.Args, "-o", filepath.Join(tmpDir, "a.out")) // Avoid writing to package directory. link.Args = append(link.Args, ar, filepath.Join("testdata", "testBuildFortvOS", "main.m")) if out, err := link.CombinedOutput(); err != nil { -- GitLab From 54ce8793a8932d81a45875d32a4cfdc520ee1c83 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Mon, 26 Jul 2021 10:39:38 -0700 Subject: [PATCH 0725/2500] cmd: update x/tools and remove copy of txtar golang.org/x/tools/txtar is the main location for this package. We don't need our own copy. For golang/go#47193 Change-Id: I480eb591f57a0d05b433a657653e2021e39354eb Reviewed-on: https://go-review.googlesource.com/c/go/+/337352 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills Reviewed-on: https://go-review.googlesource.com/c/go/+/341937 --- src/cmd/go/internal/fsys/fsys_test.go | 3 +- src/cmd/go/internal/txtar/archive_test.go | 67 ------------------- src/cmd/go/proxy_test.go | 2 +- src/cmd/go/script_test.go | 3 +- src/cmd/go/testdata/addmod.go | 2 +- src/cmd/go/testdata/savedir.go | 2 +- .../golang.org/x/tools}/txtar/archive.go | 6 +- src/cmd/vendor/modules.txt | 1 + 8 files changed, 11 insertions(+), 75 deletions(-) delete mode 100644 src/cmd/go/internal/txtar/archive_test.go rename src/cmd/{go/internal => vendor/golang.org/x/tools}/txtar/archive.go (96%) diff --git a/src/cmd/go/internal/fsys/fsys_test.go b/src/cmd/go/internal/fsys/fsys_test.go index 7f175c7031..c080c14987 100644 --- a/src/cmd/go/internal/fsys/fsys_test.go +++ b/src/cmd/go/internal/fsys/fsys_test.go @@ -1,7 +1,6 @@ package fsys import ( - "cmd/go/internal/txtar" "encoding/json" "errors" "fmt" @@ -12,6 +11,8 @@ import ( "path/filepath" "reflect" "testing" + + "golang.org/x/tools/txtar" ) // initOverlay resets the overlay state to reflect the config. diff --git a/src/cmd/go/internal/txtar/archive_test.go b/src/cmd/go/internal/txtar/archive_test.go deleted file mode 100644 index 3f734f6762..0000000000 --- a/src/cmd/go/internal/txtar/archive_test.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package txtar - -import ( - "bytes" - "fmt" - "reflect" - "testing" -) - -var tests = []struct { - name string - text string - parsed *Archive -}{ - { - name: "basic", - text: `comment1 -comment2 --- file1 -- -File 1 text. --- foo --- -More file 1 text. --- file 2 -- -File 2 text. --- empty -- --- noNL -- -hello world`, - parsed: &Archive{ - Comment: []byte("comment1\ncomment2\n"), - Files: []File{ - {"file1", []byte("File 1 text.\n-- foo ---\nMore file 1 text.\n")}, - {"file 2", []byte("File 2 text.\n")}, - {"empty", []byte{}}, - {"noNL", []byte("hello world\n")}, - }, - }, - }, -} - -func Test(t *testing.T) { - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - a := Parse([]byte(tt.text)) - if !reflect.DeepEqual(a, tt.parsed) { - t.Fatalf("Parse: wrong output:\nhave:\n%s\nwant:\n%s", shortArchive(a), shortArchive(tt.parsed)) - } - text := Format(a) - a = Parse(text) - if !reflect.DeepEqual(a, tt.parsed) { - t.Fatalf("Parse after Format: wrong output:\nhave:\n%s\nwant:\n%s", shortArchive(a), shortArchive(tt.parsed)) - } - }) - } -} - -func shortArchive(a *Archive) string { - var buf bytes.Buffer - fmt.Fprintf(&buf, "comment: %q\n", a.Comment) - for _, f := range a.Files { - fmt.Fprintf(&buf, "file %q: %q\n", f.Name, f.Data) - } - return buf.String() -} diff --git a/src/cmd/go/proxy_test.go b/src/cmd/go/proxy_test.go index 74bfecc08d..a387fe67db 100644 --- a/src/cmd/go/proxy_test.go +++ b/src/cmd/go/proxy_test.go @@ -25,12 +25,12 @@ import ( "cmd/go/internal/modfetch/codehost" "cmd/go/internal/par" - "cmd/go/internal/txtar" "golang.org/x/mod/module" "golang.org/x/mod/semver" "golang.org/x/mod/sumdb" "golang.org/x/mod/sumdb/dirhash" + "golang.org/x/tools/txtar" ) var ( diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go index 8a7c77a46f..3c5855bd6f 100644 --- a/src/cmd/go/script_test.go +++ b/src/cmd/go/script_test.go @@ -31,9 +31,10 @@ import ( "cmd/go/internal/imports" "cmd/go/internal/par" "cmd/go/internal/robustio" - "cmd/go/internal/txtar" "cmd/go/internal/work" "cmd/internal/sys" + + "golang.org/x/tools/txtar" ) var testSum = flag.String("testsum", "", `may be tidy, listm, or listall. If set, TestScript generates a go.sum file at the beginning of each test and updates test files if they pass.`) diff --git a/src/cmd/go/testdata/addmod.go b/src/cmd/go/testdata/addmod.go index 03869e68de..a1ace4ce59 100644 --- a/src/cmd/go/testdata/addmod.go +++ b/src/cmd/go/testdata/addmod.go @@ -29,7 +29,7 @@ import ( "path/filepath" "strings" - "cmd/go/internal/txtar" + "golang.org/x/tools/txtar" ) func usage() { diff --git a/src/cmd/go/testdata/savedir.go b/src/cmd/go/testdata/savedir.go index d469c31a91..6a8a232702 100644 --- a/src/cmd/go/testdata/savedir.go +++ b/src/cmd/go/testdata/savedir.go @@ -24,7 +24,7 @@ import ( "strings" "unicode/utf8" - "../internal/txtar" + "golang.org/x/tools/txtar" ) func usage() { diff --git a/src/cmd/go/internal/txtar/archive.go b/src/cmd/vendor/golang.org/x/tools/txtar/archive.go similarity index 96% rename from src/cmd/go/internal/txtar/archive.go rename to src/cmd/vendor/golang.org/x/tools/txtar/archive.go index 1796684877..214256617b 100644 --- a/src/cmd/go/internal/txtar/archive.go +++ b/src/cmd/vendor/golang.org/x/tools/txtar/archive.go @@ -34,7 +34,7 @@ package txtar import ( "bytes" "fmt" - "os" + "io/ioutil" "strings" ) @@ -66,7 +66,7 @@ func Format(a *Archive) []byte { // ParseFile parses the named file as an archive. func ParseFile(file string) (*Archive, error) { - data, err := os.ReadFile(file) + data, err := ioutil.ReadFile(file) if err != nil { return nil, err } @@ -121,7 +121,7 @@ func isMarker(data []byte) (name string, after []byte) { if i := bytes.IndexByte(data, '\n'); i >= 0 { data, after = data[:i], data[i+1:] } - if !bytes.HasSuffix(data, markerEnd) { + if !(bytes.HasSuffix(data, markerEnd) && len(data) >= len(marker)+len(markerEnd)) { return "", nil } return strings.TrimSpace(string(data[len(marker) : len(data)-len(markerEnd)])), after diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index c98bdcd344..1765e3e1fc 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -93,6 +93,7 @@ golang.org/x/tools/go/types/typeutil golang.org/x/tools/internal/analysisinternal golang.org/x/tools/internal/lsp/fuzzy golang.org/x/tools/internal/typeparams +golang.org/x/tools/txtar # golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 ## explicit; go 1.11 golang.org/x/xerrors -- GitLab From a05a7d49a9b7975d89bc5851cff55b64f64242c3 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 3 Aug 2021 14:51:46 -0700 Subject: [PATCH 0726/2500] cmd/go: address code review comments in test cgo_path_space_quote For CL 334732. Change-Id: I5cb88cd7d5e4edf6006bbaeb17723dac2cdf0fd5 Reviewed-on: https://go-review.googlesource.com/c/go/+/339590 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills Reviewed-on: https://go-review.googlesource.com/c/go/+/341938 --- src/cmd/go/testdata/script/cgo_path_space_quote.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cmd/go/testdata/script/cgo_path_space_quote.txt b/src/cmd/go/testdata/script/cgo_path_space_quote.txt index 3b89bfb800..9556101300 100644 --- a/src/cmd/go/testdata/script/cgo_path_space_quote.txt +++ b/src/cmd/go/testdata/script/cgo_path_space_quote.txt @@ -6,6 +6,7 @@ [short] skip [!exec:clang] [!exec:gcc] skip +[!cgo] skip env GOENV=$WORK/go.env mkdir 'program files' @@ -20,6 +21,7 @@ go env CC stdout 'program files[/\\]which cc" (clang|gcc)$' go run . +stdout 1 -- go.mod -- module test -- GitLab From 6406227d71d2de0bec944bfc1a6aaed90dbf9d0d Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Thu, 3 Jun 2021 16:57:54 +0200 Subject: [PATCH 0727/2500] runtime: skip sysmon workaround on NetBSD >= 9.2 Detect the NetBSD version in osinit and only enable the workaround for the kernel bug identified in #42515 for NetBSD versions older than 9.2. For #42515 For #46495 Change-Id: I808846c7f8e47e5f7cc0a2f869246f4bd90d8e22 Reviewed-on: https://go-review.googlesource.com/c/go/+/324472 Trust: Tobias Klauser Trust: Benny Siegert Run-TryBot: Tobias Klauser Reviewed-by: Michael Pratt Reviewed-by: Ian Lance Taylor TryBot-Result: Go Bot --- src/runtime/os_netbsd.go | 11 +++++++++++ src/runtime/proc.go | 6 +++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/runtime/os_netbsd.go b/src/runtime/os_netbsd.go index 2c20ee2173..0b95fa7a6e 100644 --- a/src/runtime/os_netbsd.go +++ b/src/runtime/os_netbsd.go @@ -101,6 +101,9 @@ var sigset_all = sigset{[4]uint32{^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0) // From NetBSD's const ( + _CTL_KERN = 1 + _KERN_OSREV = 3 + _CTL_HW = 6 _HW_NCPU = 3 _HW_PAGESIZE = 7 @@ -138,6 +141,13 @@ func getPageSize() uintptr { return 0 } +func getOSRev() int { + if osrev, ok := sysctlInt([]uint32{_CTL_KERN, _KERN_OSREV}); ok { + return int(osrev) + } + return 0 +} + //go:nosplit func semacreate(mp *m) { } @@ -252,6 +262,7 @@ func osinit() { if physPageSize == 0 { physPageSize = getPageSize() } + needSysmonWorkaround = getOSRev() < 902000000 // NetBSD 9.2 } var urandom_dev = []byte("/dev/urandom\x00") diff --git a/src/runtime/proc.go b/src/runtime/proc.go index cde1a11583..c2e43ef5c3 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -5229,6 +5229,10 @@ func checkdead() { // This is a variable for testing purposes. It normally doesn't change. var forcegcperiod int64 = 2 * 60 * 1e9 +// needSysmonWorkaround is true if the workaround for +// golang.org/issue/42515 is needed on NetBSD. +var needSysmonWorkaround bool = false + // Always runs without a P, so write barriers are not allowed. // //go:nowritebarrierrec @@ -5337,7 +5341,7 @@ func sysmon() { } } mDoFixup() - if GOOS == "netbsd" { + if GOOS == "netbsd" && needSysmonWorkaround { // netpoll is responsible for waiting for timer // expiration, so we typically don't have to worry // about starting an M to service timers. (Note that -- GitLab From c04a32e59a001f0490082619bbe6a36e1e23ef99 Mon Sep 17 00:00:00 2001 From: Andy Pan Date: Thu, 24 Jun 2021 12:50:14 +0800 Subject: [PATCH 0728/2500] net: avoid memory copy calling absDomainName Change-Id: I8ea9bec8bc33e29b8c265fbca40871bc23667144 Reviewed-on: https://go-review.googlesource.com/c/go/+/330470 Reviewed-by: Damien Neil Trust: Damien Neil Trust: Michael Knyszek Run-TryBot: Damien Neil TryBot-Result: Go Bot --- src/net/cgo_unix.go | 2 +- src/net/dnsclient.go | 16 +++++----------- src/net/hosts.go | 15 ++++++++------- src/net/hosts_test.go | 4 ++-- src/net/lookup_plan9.go | 10 +++++----- src/net/lookup_windows.go | 14 +++++++------- src/net/lookup_windows_test.go | 10 +++++----- src/net/parse.go | 10 ++++++++++ 8 files changed, 43 insertions(+), 38 deletions(-) diff --git a/src/net/cgo_unix.go b/src/net/cgo_unix.go index 2ea86e074f..5bf6fd84bc 100644 --- a/src/net/cgo_unix.go +++ b/src/net/cgo_unix.go @@ -323,7 +323,7 @@ func cgoLookupAddrPTR(addr string, sa *C.struct_sockaddr, salen C.socklen_t) (na break } } - return []string{absDomainName(b)}, nil + return []string{absDomainName(string(b))}, nil } func cgoReverseLookup(result chan<- reverseLookupResult, addr string, sa *C.struct_sockaddr, salen C.socklen_t) { diff --git a/src/net/dnsclient.go b/src/net/dnsclient.go index 1bbe39650b..3c1a12995a 100644 --- a/src/net/dnsclient.go +++ b/src/net/dnsclient.go @@ -5,6 +5,7 @@ package net import ( + "internal/bytealg" "internal/itoa" "sort" @@ -136,18 +137,11 @@ func isDomainName(s string) bool { // It's hard to tell so we settle on the heuristic that names without dots // (like "localhost" or "myhost") do not get trailing dots, but any other // names do. -func absDomainName(b []byte) string { - hasDots := false - for _, x := range b { - if x == '.' { - hasDots = true - break - } - } - if hasDots && b[len(b)-1] != '.' { - b = append(b, '.') +func absDomainName(s string) string { + if bytealg.IndexByteString(s, '.') != -1 && s[len(s)-1] != '.' { + s += "." } - return string(b) + return s } // An SRV represents a single DNS SRV record. diff --git a/src/net/hosts.go b/src/net/hosts.go index 5c560f3756..e604031920 100644 --- a/src/net/hosts.go +++ b/src/net/hosts.go @@ -82,10 +82,10 @@ func readHosts() { continue } for i := 1; i < len(f); i++ { - name := absDomainName([]byte(f[i])) + name := absDomainName(f[i]) h := []byte(f[i]) lowerASCIIBytes(h) - key := absDomainName(h) + key := absDomainName(string(h)) hs[key] = append(hs[key], addr) is[addr] = append(is[addr], name) } @@ -106,11 +106,12 @@ func lookupStaticHost(host string) []string { defer hosts.Unlock() readHosts() if len(hosts.byName) != 0 { - // TODO(jbd,bradfitz): avoid this alloc if host is already all lowercase? - // or linear scan the byName map if it's small enough? - lowerHost := []byte(host) - lowerASCIIBytes(lowerHost) - if ips, ok := hosts.byName[absDomainName(lowerHost)]; ok { + if hasUpperCase(host) { + lowerHost := []byte(host) + lowerASCIIBytes(lowerHost) + host = string(lowerHost) + } + if ips, ok := hosts.byName[absDomainName(host)]; ok { ipsCp := make([]string, len(ips)) copy(ipsCp, ips) return ipsCp diff --git a/src/net/hosts_test.go b/src/net/hosts_test.go index 19c43999f9..72919140e9 100644 --- a/src/net/hosts_test.go +++ b/src/net/hosts_test.go @@ -70,7 +70,7 @@ func TestLookupStaticHost(t *testing.T) { } func testStaticHost(t *testing.T, hostsPath string, ent staticHostEntry) { - ins := []string{ent.in, absDomainName([]byte(ent.in)), strings.ToLower(ent.in), strings.ToUpper(ent.in)} + ins := []string{ent.in, absDomainName(ent.in), strings.ToLower(ent.in), strings.ToUpper(ent.in)} for _, in := range ins { addrs := lookupStaticHost(in) if !reflect.DeepEqual(addrs, ent.out) { @@ -141,7 +141,7 @@ func TestLookupStaticAddr(t *testing.T) { func testStaticAddr(t *testing.T, hostsPath string, ent staticHostEntry) { hosts := lookupStaticAddr(ent.in) for i := range ent.out { - ent.out[i] = absDomainName([]byte(ent.out[i])) + ent.out[i] = absDomainName(ent.out[i]) } if !reflect.DeepEqual(hosts, ent.out) { t.Errorf("%s, lookupStaticAddr(%s) = %v; want %v", hostsPath, ent.in, hosts, ent.out) diff --git a/src/net/lookup_plan9.go b/src/net/lookup_plan9.go index 75c18b33ac..d43a03b778 100644 --- a/src/net/lookup_plan9.go +++ b/src/net/lookup_plan9.go @@ -262,8 +262,8 @@ func (*Resolver) lookupSRV(ctx context.Context, service, proto, name string) (cn if !(portOk && priorityOk && weightOk) { continue } - addrs = append(addrs, &SRV{absDomainName([]byte(f[5])), uint16(port), uint16(priority), uint16(weight)}) - cname = absDomainName([]byte(f[0])) + addrs = append(addrs, &SRV{absDomainName(f[5]), uint16(port), uint16(priority), uint16(weight)}) + cname = absDomainName(f[0]) } byPriorityWeight(addrs).sort() return @@ -280,7 +280,7 @@ func (*Resolver) lookupMX(ctx context.Context, name string) (mx []*MX, err error continue } if pref, _, ok := dtoi(f[2]); ok { - mx = append(mx, &MX{absDomainName([]byte(f[3])), uint16(pref)}) + mx = append(mx, &MX{absDomainName(f[3]), uint16(pref)}) } } byPref(mx).sort() @@ -297,7 +297,7 @@ func (*Resolver) lookupNS(ctx context.Context, name string) (ns []*NS, err error if len(f) < 3 { continue } - ns = append(ns, &NS{absDomainName([]byte(f[2]))}) + ns = append(ns, &NS{absDomainName(f[2])}) } return } @@ -329,7 +329,7 @@ func (*Resolver) lookupAddr(ctx context.Context, addr string) (name []string, er if len(f) < 3 { continue } - name = append(name, absDomainName([]byte(f[2]))) + name = append(name, absDomainName(f[2])) } return } diff --git a/src/net/lookup_windows.go b/src/net/lookup_windows.go index bb34a08133..27e5f86910 100644 --- a/src/net/lookup_windows.go +++ b/src/net/lookup_windows.go @@ -226,7 +226,7 @@ func (*Resolver) lookupCNAME(ctx context.Context, name string) (string, error) { // windows returns DNS_INFO_NO_RECORDS if there are no CNAME-s if errno, ok := e.(syscall.Errno); ok && errno == syscall.DNS_INFO_NO_RECORDS { // if there are no aliases, the canonical name is the input name - return absDomainName([]byte(name)), nil + return absDomainName(name), nil } if e != nil { return "", &DNSError{Err: winError("dnsquery", e).Error(), Name: name} @@ -235,7 +235,7 @@ func (*Resolver) lookupCNAME(ctx context.Context, name string) (string, error) { resolved := resolveCNAME(syscall.StringToUTF16Ptr(name), r) cname := windows.UTF16PtrToString(resolved) - return absDomainName([]byte(cname)), nil + return absDomainName(cname), nil } func (*Resolver) lookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) { @@ -258,10 +258,10 @@ func (*Resolver) lookupSRV(ctx context.Context, service, proto, name string) (st srvs := make([]*SRV, 0, 10) for _, p := range validRecs(r, syscall.DNS_TYPE_SRV, target) { v := (*syscall.DNSSRVData)(unsafe.Pointer(&p.Data[0])) - srvs = append(srvs, &SRV{absDomainName([]byte(syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Target))[:]))), v.Port, v.Priority, v.Weight}) + srvs = append(srvs, &SRV{absDomainName(syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Target))[:])), v.Port, v.Priority, v.Weight}) } byPriorityWeight(srvs).sort() - return absDomainName([]byte(target)), srvs, nil + return absDomainName(target), srvs, nil } func (*Resolver) lookupMX(ctx context.Context, name string) ([]*MX, error) { @@ -278,7 +278,7 @@ func (*Resolver) lookupMX(ctx context.Context, name string) ([]*MX, error) { mxs := make([]*MX, 0, 10) for _, p := range validRecs(r, syscall.DNS_TYPE_MX, name) { v := (*syscall.DNSMXData)(unsafe.Pointer(&p.Data[0])) - mxs = append(mxs, &MX{absDomainName([]byte(windows.UTF16PtrToString(v.NameExchange))), v.Preference}) + mxs = append(mxs, &MX{absDomainName(windows.UTF16PtrToString(v.NameExchange)), v.Preference}) } byPref(mxs).sort() return mxs, nil @@ -298,7 +298,7 @@ func (*Resolver) lookupNS(ctx context.Context, name string) ([]*NS, error) { nss := make([]*NS, 0, 10) for _, p := range validRecs(r, syscall.DNS_TYPE_NS, name) { v := (*syscall.DNSPTRData)(unsafe.Pointer(&p.Data[0])) - nss = append(nss, &NS{absDomainName([]byte(syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Host))[:])))}) + nss = append(nss, &NS{absDomainName(syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Host))[:]))}) } return nss, nil } @@ -344,7 +344,7 @@ func (*Resolver) lookupAddr(ctx context.Context, addr string) ([]string, error) ptrs := make([]string, 0, 10) for _, p := range validRecs(r, syscall.DNS_TYPE_PTR, arpa) { v := (*syscall.DNSPTRData)(unsafe.Pointer(&p.Data[0])) - ptrs = append(ptrs, absDomainName([]byte(windows.UTF16PtrToString(v.Host)))) + ptrs = append(ptrs, absDomainName(windows.UTF16PtrToString(v.Host))) } return ptrs, nil } diff --git a/src/net/lookup_windows_test.go b/src/net/lookup_windows_test.go index aa95501d02..f726ef0f34 100644 --- a/src/net/lookup_windows_test.go +++ b/src/net/lookup_windows_test.go @@ -220,14 +220,14 @@ func nslookupMX(name string) (mx []*MX, err error) { rx := regexp.MustCompile(`(?m)^([a-z0-9.\-]+)\s+mail exchanger\s*=\s*([0-9]+)\s*([a-z0-9.\-]+)$`) for _, ans := range rx.FindAllStringSubmatch(r, -1) { pref, _, _ := dtoi(ans[2]) - mx = append(mx, &MX{absDomainName([]byte(ans[3])), uint16(pref)}) + mx = append(mx, &MX{absDomainName(ans[3]), uint16(pref)}) } // windows nslookup syntax // gmail.com MX preference = 30, mail exchanger = alt3.gmail-smtp-in.l.google.com rx = regexp.MustCompile(`(?m)^([a-z0-9.\-]+)\s+MX preference\s*=\s*([0-9]+)\s*,\s*mail exchanger\s*=\s*([a-z0-9.\-]+)$`) for _, ans := range rx.FindAllStringSubmatch(r, -1) { pref, _, _ := dtoi(ans[2]) - mx = append(mx, &MX{absDomainName([]byte(ans[3])), uint16(pref)}) + mx = append(mx, &MX{absDomainName(ans[3]), uint16(pref)}) } return } @@ -241,7 +241,7 @@ func nslookupNS(name string) (ns []*NS, err error) { // golang.org nameserver = ns1.google.com. rx := regexp.MustCompile(`(?m)^([a-z0-9.\-]+)\s+nameserver\s*=\s*([a-z0-9.\-]+)$`) for _, ans := range rx.FindAllStringSubmatch(r, -1) { - ns = append(ns, &NS{absDomainName([]byte(ans[2]))}) + ns = append(ns, &NS{absDomainName(ans[2])}) } return } @@ -258,7 +258,7 @@ func nslookupCNAME(name string) (cname string, err error) { for _, ans := range rx.FindAllStringSubmatch(r, -1) { last = ans[2] } - return absDomainName([]byte(last)), nil + return absDomainName(last), nil } func nslookupTXT(name string) (txt []string, err error) { @@ -299,7 +299,7 @@ func lookupPTR(name string) (ptr []string, err error) { ptr = make([]string, 0, 10) rx := regexp.MustCompile(`(?m)^Pinging\s+([a-zA-Z0-9.\-]+)\s+\[.*$`) for _, ans := range rx.FindAllStringSubmatch(r, -1) { - ptr = append(ptr, absDomainName([]byte(ans[1]))) + ptr = append(ptr, absDomainName(ans[1])) } return } diff --git a/src/net/parse.go b/src/net/parse.go index 6c230ab63f..0d7cce12e6 100644 --- a/src/net/parse.go +++ b/src/net/parse.go @@ -208,6 +208,16 @@ func last(s string, b byte) int { return i } +// hasUpperCase tells whether the given string contains at least one upper-case. +func hasUpperCase(s string) bool { + for i := range s { + if 'A' <= s[i] && s[i] <= 'Z' { + return true + } + } + return false +} + // lowerASCIIBytes makes x ASCII lowercase in-place. func lowerASCIIBytes(x []byte) { for i, b := range x { -- GitLab From 213e157d3aad3fbb289d184a5cb4b18258162634 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 15 Jun 2021 16:01:25 -0700 Subject: [PATCH 0729/2500] testing/fstest: allow specifying file for "." in MapFS Prior to this commit, specifying a file for "." in MapFS created an invalid fs.FS and caused infinite recursion in fs.WalkDir. Fixes #46776 Change-Id: Ia9e4ae1125355a74dba9ee6b36451b7fda75a862 Reviewed-on: https://go-review.googlesource.com/c/go/+/328409 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/testing/fstest/mapfs.go | 4 +++- src/testing/fstest/mapfs_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/testing/fstest/mapfs.go b/src/testing/fstest/mapfs.go index 9fef2f4696..056ef133fa 100644 --- a/src/testing/fstest/mapfs.go +++ b/src/testing/fstest/mapfs.go @@ -66,7 +66,9 @@ func (fsys MapFS) Open(name string) (fs.File, error) { for fname, f := range fsys { i := strings.Index(fname, "/") if i < 0 { - list = append(list, mapFileInfo{fname, f}) + if fname != "." { + list = append(list, mapFileInfo{fname, f}) + } } else { need[fname[:i]] = true } diff --git a/src/testing/fstest/mapfs_test.go b/src/testing/fstest/mapfs_test.go index 2abedd6735..c8d29283b2 100644 --- a/src/testing/fstest/mapfs_test.go +++ b/src/testing/fstest/mapfs_test.go @@ -5,6 +5,9 @@ package fstest import ( + "fmt" + "io/fs" + "strings" "testing" ) @@ -17,3 +20,28 @@ func TestMapFS(t *testing.T) { t.Fatal(err) } } + +func TestMapFSChmodDot(t *testing.T) { + m := MapFS{ + "a/b.txt": &MapFile{Mode: 0666}, + ".": &MapFile{Mode: 0777 | fs.ModeDir}, + } + buf := new(strings.Builder) + fs.WalkDir(m, ".", func(path string, d fs.DirEntry, err error) error { + fi, err := d.Info() + if err != nil { + return err + } + fmt.Fprintf(buf, "%s: %v\n", path, fi.Mode()) + return nil + }) + want := ` +.: drwxrwxrwx +a: d--------- +a/b.txt: -rw-rw-rw- +`[1:] + got := buf.String() + if want != got { + t.Errorf("MapFS modes want:\n%s\ngot:\n%s\n", want, got) + } +} -- GitLab From df9c5d8f5dc96977dad865dc531d6c1e665ea1cb Mon Sep 17 00:00:00 2001 From: Hans Date: Fri, 30 Jul 2021 02:36:02 +0000 Subject: [PATCH 0730/2500] cmd/cgo: fix unused parameter warnings in generated _cgo_main.c Applying -Werror compiler option to request warnings is an usual way to discover potential errors. Go user may put a cgo directive in preamble: `// #cgo CFLAGS: -Werror=unused-parameter`. However, the directive also takes effect on the cgo generated files. I cleaned _cgo_main.c to help Go user only concentrate on warnings of their own file. Fixes #43639 Change-Id: I9112f02ae5226f2fc87a8650d19faee59cddd588 GitHub-Last-Rev: f09d172f979acfba855be8108e7d79ec2778c406 GitHub-Pull-Request: golang/go#46358 Reviewed-on: https://go-review.googlesource.com/c/go/+/322232 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Bryan C. Mills --- misc/cgo/test/testdata/issue43639.go | 9 +++++++++ misc/cgo/test/testdata/issue43639/a.go | 8 ++++++++ src/cmd/cgo/out.go | 8 ++++---- 3 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 misc/cgo/test/testdata/issue43639.go create mode 100644 misc/cgo/test/testdata/issue43639/a.go diff --git a/misc/cgo/test/testdata/issue43639.go b/misc/cgo/test/testdata/issue43639.go new file mode 100644 index 0000000000..e755fbd4bc --- /dev/null +++ b/misc/cgo/test/testdata/issue43639.go @@ -0,0 +1,9 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cgotest + +// Issue 43639: No runtime test needed, make sure package cgotest/issue43639 compiles well. + +import _ "cgotest/issue43639" diff --git a/misc/cgo/test/testdata/issue43639/a.go b/misc/cgo/test/testdata/issue43639/a.go new file mode 100644 index 0000000000..fe37d5e4b0 --- /dev/null +++ b/misc/cgo/test/testdata/issue43639/a.go @@ -0,0 +1,8 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package issue43639 + +// #cgo CFLAGS: -W -Wall -Werror +import "C" diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index 94152f4278..3badd73f79 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -59,9 +59,9 @@ func (p *Package) writeDefs() { // Write C main file for using gcc to resolve imports. fmt.Fprintf(fm, "int main() { return 0; }\n") if *importRuntimeCgo { - fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*), void *a, int c, __SIZE_TYPE__ ctxt) { }\n") + fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*) __attribute__((unused)), void *a __attribute__((unused)), int c __attribute__((unused)), __SIZE_TYPE__ ctxt __attribute__((unused))) { }\n") fmt.Fprintf(fm, "__SIZE_TYPE__ _cgo_wait_runtime_init_done(void) { return 0; }\n") - fmt.Fprintf(fm, "void _cgo_release_context(__SIZE_TYPE__ ctxt) { }\n") + fmt.Fprintf(fm, "void _cgo_release_context(__SIZE_TYPE__ ctxt __attribute__((unused))) { }\n") fmt.Fprintf(fm, "char* _cgo_topofstack(void) { return (char*)0; }\n") } else { // If we're not importing runtime/cgo, we *are* runtime/cgo, @@ -70,8 +70,8 @@ func (p *Package) writeDefs() { fmt.Fprintf(fm, "__SIZE_TYPE__ _cgo_wait_runtime_init_done(void);\n") fmt.Fprintf(fm, "void _cgo_release_context(__SIZE_TYPE__);\n") } - fmt.Fprintf(fm, "void _cgo_allocate(void *a, int c) { }\n") - fmt.Fprintf(fm, "void _cgo_panic(void *a, int c) { }\n") + fmt.Fprintf(fm, "void _cgo_allocate(void *a __attribute__((unused)), int c __attribute__((unused))) { }\n") + fmt.Fprintf(fm, "void _cgo_panic(void *a __attribute__((unused)), int c __attribute__((unused))) { }\n") fmt.Fprintf(fm, "void _cgo_reginit(void) { }\n") // Write second Go output: definitions of _C_xxx. -- GitLab From 8ff16c19909e5aecf51c6b993cba36ea51791f34 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 4 Aug 2021 19:41:19 -0400 Subject: [PATCH 0731/2500] runtime: accept restartable sequence pcdata values in isAsyncSafePoint If the pcdata value indicates a restartable sequence, it is okay to asynchronously preempt (and resume at the restart PC). Accept it in isAsyncSafePoint. Fixes #47530. Change-Id: I419225717c8eee5812f3235338262da5895aad0d Reviewed-on: https://go-review.googlesource.com/c/go/+/340011 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: Joel Sing Reviewed-by: Austin Clements --- src/runtime/preempt.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/preempt.go b/src/runtime/preempt.go index a38ab79398..334bac779e 100644 --- a/src/runtime/preempt.go +++ b/src/runtime/preempt.go @@ -399,7 +399,7 @@ func isAsyncSafePoint(gp *g, pc, sp, lr uintptr) (bool, uintptr) { return false, 0 } up, startpc := pcdatavalue2(f, _PCDATA_UnsafePoint, pc) - if up != _PCDATA_UnsafePointSafe { + if up == _PCDATA_UnsafePointUnsafe { // Unsafe-point marked by compiler. This includes // atomic sequences (e.g., write barrier) and nosplit // functions (except at calls). -- GitLab From d9349175ad13ab228d3224c4bff8e3e1b2936b42 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Wed, 26 May 2021 12:55:16 -0700 Subject: [PATCH 0732/2500] net: remove allocation from UDPConn.WriteTo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Duplicate some code to avoid an interface. name old time/op new time/op delta WriteToReadFromUDP-8 6.38µs ±20% 5.59µs ±10% -12.38% (p=0.001 n=10+9) name old alloc/op new alloc/op delta WriteToReadFromUDP-8 64.0B ± 0% 32.0B ± 0% -50.00% (p=0.000 n=10+10) name old allocs/op new allocs/op delta WriteToReadFromUDP-8 2.00 ± 0% 1.00 ± 0% -50.00% (p=0.000 n=10+10) Windows is temporarily stubbed out. Updates #43451 Change-Id: Ied15ff92268c652cf445836e0446025eaeb60cc9 Reviewed-on: https://go-review.googlesource.com/c/go/+/331489 Trust: Josh Bleecher Snyder Trust: Damien Neil Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Reviewed-by: Damien Neil --- api/next.txt | 52 ++++++++++++++++++++++ src/internal/poll/fd_unix.go | 52 ++++++++++++++++++++++ src/internal/poll/fd_windows.go | 10 +++++ src/net/fd_posix.go | 12 ++++++ src/net/ipsock_posix.go | 76 ++++++++++++++++++++------------- src/net/net_fake.go | 8 ++++ src/net/udpsock_posix.go | 20 +++++++-- src/syscall/net_js.go | 8 ++++ src/syscall/syscall_unix.go | 16 +++++++ 9 files changed, 220 insertions(+), 34 deletions(-) diff --git a/api/next.txt b/api/next.txt index e69de29bb2..8d2ee73f79 100644 --- a/api/next.txt +++ b/api/next.txt @@ -0,0 +1,52 @@ +pkg syscall (darwin-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (darwin-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (darwin-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (darwin-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (freebsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (freebsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (freebsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (freebsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (freebsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (freebsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (freebsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (freebsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (freebsd-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (freebsd-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (freebsd-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (freebsd-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (linux-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (linux-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (linux-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (linux-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (linux-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (linux-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (linux-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (linux-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (linux-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (linux-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (linux-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (linux-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (netbsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (netbsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (netbsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (netbsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (netbsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (netbsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (netbsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (netbsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (netbsd-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (netbsd-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (netbsd-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (netbsd-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (netbsd-arm64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (netbsd-arm64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (netbsd-arm64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (netbsd-arm64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (openbsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (openbsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (openbsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (openbsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (openbsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (openbsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (openbsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error +pkg syscall (openbsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error diff --git a/src/internal/poll/fd_unix.go b/src/internal/poll/fd_unix.go index 3b17cd22b0..51d15f6abc 100644 --- a/src/internal/poll/fd_unix.go +++ b/src/internal/poll/fd_unix.go @@ -327,6 +327,58 @@ func (fd *FD) Pwrite(p []byte, off int64) (int, error) { } } +// WriteToInet4 wraps the sendto network call for IPv4 addresses. +func (fd *FD) WriteToInet4(p []byte, sa syscall.SockaddrInet4) (int, error) { + if err := fd.writeLock(); err != nil { + return 0, err + } + defer fd.writeUnlock() + if err := fd.pd.prepareWrite(fd.isFile); err != nil { + return 0, err + } + for { + err := syscall.SendtoInet4(fd.Sysfd, p, 0, sa) + if err == syscall.EINTR { + continue + } + if err == syscall.EAGAIN && fd.pd.pollable() { + if err = fd.pd.waitWrite(fd.isFile); err == nil { + continue + } + } + if err != nil { + return 0, err + } + return len(p), nil + } +} + +// WriteToInet6 wraps the sendto network call for IPv6 addresses. +func (fd *FD) WriteToInet6(p []byte, sa syscall.SockaddrInet6) (int, error) { + if err := fd.writeLock(); err != nil { + return 0, err + } + defer fd.writeUnlock() + if err := fd.pd.prepareWrite(fd.isFile); err != nil { + return 0, err + } + for { + err := syscall.SendtoInet6(fd.Sysfd, p, 0, sa) + if err == syscall.EINTR { + continue + } + if err == syscall.EAGAIN && fd.pd.pollable() { + if err = fd.pd.waitWrite(fd.isFile); err == nil { + continue + } + } + if err != nil { + return 0, err + } + return len(p), nil + } +} + // WriteTo wraps the sendto network call. func (fd *FD) WriteTo(p []byte, sa syscall.Sockaddr) (int, error) { if err := fd.writeLock(); err != nil { diff --git a/src/internal/poll/fd_windows.go b/src/internal/poll/fd_windows.go index 4a5169527c..3dada32985 100644 --- a/src/internal/poll/fd_windows.go +++ b/src/internal/poll/fd_windows.go @@ -791,6 +791,16 @@ func (fd *FD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) { return ntotal, nil } +// WriteTo wraps the sendto network call for IPv4. +func (fd *FD) WriteToInet4(buf []byte, sa syscall.SockaddrInet4) (int, error) { + return fd.WriteTo(buf, &sa) +} + +// WriteTo wraps the sendto network call for IPv6. +func (fd *FD) WriteToInet6(buf []byte, sa syscall.SockaddrInet6) (int, error) { + return fd.WriteTo(buf, &sa) +} + // Call ConnectEx. This doesn't need any locking, since it is only // called when the descriptor is first created. This is here rather // than in the net package so that it can use fd.wop. diff --git a/src/net/fd_posix.go b/src/net/fd_posix.go index 4703ff33a1..a0675b2072 100644 --- a/src/net/fd_posix.go +++ b/src/net/fd_posix.go @@ -82,6 +82,18 @@ func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) { return n, wrapSyscallError(writeToSyscallName, err) } +func (fd *netFD) writeToInet4(p []byte, sa syscall.SockaddrInet4) (n int, err error) { + n, err = fd.pfd.WriteToInet4(p, sa) + runtime.KeepAlive(fd) + return n, wrapSyscallError(writeToSyscallName, err) +} + +func (fd *netFD) writeToInet6(p []byte, sa syscall.SockaddrInet6) (n int, err error) { + n, err = fd.pfd.WriteToInet6(p, sa) + runtime.KeepAlive(fd) + return n, wrapSyscallError(writeToSyscallName, err) +} + func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) { n, oobn, err = fd.pfd.WriteMsg(p, oob, sa) runtime.KeepAlive(fd) diff --git a/src/net/ipsock_posix.go b/src/net/ipsock_posix.go index c51c227401..50003ac446 100644 --- a/src/net/ipsock_posix.go +++ b/src/net/ipsock_posix.go @@ -142,42 +142,58 @@ func internetSocket(ctx context.Context, net string, laddr, raddr sockaddr, soty return socket(ctx, net, family, sotype, proto, ipv6only, laddr, raddr, ctrlFn) } +func ipToSockaddrInet4(ip IP, port int) (syscall.SockaddrInet4, error) { + if len(ip) == 0 { + ip = IPv4zero + } + ip4 := ip.To4() + if ip4 == nil { + return syscall.SockaddrInet4{}, &AddrError{Err: "non-IPv4 address", Addr: ip.String()} + } + sa := syscall.SockaddrInet4{Port: port} + copy(sa.Addr[:], ip4) + return sa, nil +} + +func ipToSockaddrInet6(ip IP, port int, zone string) (syscall.SockaddrInet6, error) { + // In general, an IP wildcard address, which is either + // "0.0.0.0" or "::", means the entire IP addressing + // space. For some historical reason, it is used to + // specify "any available address" on some operations + // of IP node. + // + // When the IP node supports IPv4-mapped IPv6 address, + // we allow a listener to listen to the wildcard + // address of both IP addressing spaces by specifying + // IPv6 wildcard address. + if len(ip) == 0 || ip.Equal(IPv4zero) { + ip = IPv6zero + } + // We accept any IPv6 address including IPv4-mapped + // IPv6 address. + ip6 := ip.To16() + if ip6 == nil { + return syscall.SockaddrInet6{}, &AddrError{Err: "non-IPv6 address", Addr: ip.String()} + } + sa := syscall.SockaddrInet6{Port: port, ZoneId: uint32(zoneCache.index(zone))} + copy(sa.Addr[:], ip6) + return sa, nil +} + func ipToSockaddr(family int, ip IP, port int, zone string) (syscall.Sockaddr, error) { switch family { case syscall.AF_INET: - if len(ip) == 0 { - ip = IPv4zero - } - ip4 := ip.To4() - if ip4 == nil { - return nil, &AddrError{Err: "non-IPv4 address", Addr: ip.String()} + sa, err := ipToSockaddrInet4(ip, port) + if err != nil { + return nil, err } - sa := &syscall.SockaddrInet4{Port: port} - copy(sa.Addr[:], ip4) - return sa, nil + return &sa, nil case syscall.AF_INET6: - // In general, an IP wildcard address, which is either - // "0.0.0.0" or "::", means the entire IP addressing - // space. For some historical reason, it is used to - // specify "any available address" on some operations - // of IP node. - // - // When the IP node supports IPv4-mapped IPv6 address, - // we allow a listener to listen to the wildcard - // address of both IP addressing spaces by specifying - // IPv6 wildcard address. - if len(ip) == 0 || ip.Equal(IPv4zero) { - ip = IPv6zero - } - // We accept any IPv6 address including IPv4-mapped - // IPv6 address. - ip6 := ip.To16() - if ip6 == nil { - return nil, &AddrError{Err: "non-IPv6 address", Addr: ip.String()} + sa, err := ipToSockaddrInet6(ip, port, zone) + if err != nil { + return nil, err } - sa := &syscall.SockaddrInet6{Port: port, ZoneId: uint32(zoneCache.index(zone))} - copy(sa.Addr[:], ip6) - return sa, nil + return &sa, nil } return nil, &AddrError{Err: "invalid address family", Addr: ip.String()} } diff --git a/src/net/net_fake.go b/src/net/net_fake.go index 74fc1da6fd..feb51968dd 100644 --- a/src/net/net_fake.go +++ b/src/net/net_fake.go @@ -276,6 +276,14 @@ func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) { return 0, syscall.ENOSYS } +func (fd *netFD) writeToInet4(p []byte, sa syscall.SockaddrInet4) (n int, err error) { + return 0, syscall.ENOSYS +} + +func (fd *netFD) writeToInet6(p []byte, sa syscall.SockaddrInet6) (n int, err error) { + return 0, syscall.ENOSYS +} + func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) { return 0, 0, syscall.ENOSYS } diff --git a/src/net/udpsock_posix.go b/src/net/udpsock_posix.go index 96fb373ce7..b71be09217 100644 --- a/src/net/udpsock_posix.go +++ b/src/net/udpsock_posix.go @@ -76,11 +76,23 @@ func (c *UDPConn) writeTo(b []byte, addr *UDPAddr) (int, error) { if addr == nil { return 0, errMissingAddress } - sa, err := addr.sockaddr(c.fd.family) - if err != nil { - return 0, err + + switch c.fd.family { + case syscall.AF_INET: + sa, err := ipToSockaddrInet4(addr.IP, addr.Port) + if err != nil { + return 0, err + } + return c.fd.writeToInet4(b, sa) + case syscall.AF_INET6: + sa, err := ipToSockaddrInet6(addr.IP, addr.Port, addr.Zone) + if err != nil { + return 0, err + } + return c.fd.writeToInet6(b, sa) + default: + return 0, &AddrError{Err: "invalid address family", Addr: addr.IP.String()} } - return c.fd.writeTo(b, sa) } func (c *UDPConn) writeMsg(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) { diff --git a/src/syscall/net_js.go b/src/syscall/net_js.go index ed462025bb..17799148bd 100644 --- a/src/syscall/net_js.go +++ b/src/syscall/net_js.go @@ -96,6 +96,14 @@ func Sendto(fd int, p []byte, flags int, to Sockaddr) error { return ENOSYS } +func SendtoInet4(fd int, p []byte, flags int, to SockaddrInet4) error { + return ENOSYS +} + +func SendtoInet6(fd int, p []byte, flags int, to SockaddrInet6) error { + return ENOSYS +} + func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn, recvflags int, from Sockaddr, err error) { return 0, 0, 0, nil, ENOSYS } diff --git a/src/syscall/syscall_unix.go b/src/syscall/syscall_unix.go index 5b405b99b4..60aeae14de 100644 --- a/src/syscall/syscall_unix.go +++ b/src/syscall/syscall_unix.go @@ -292,6 +292,22 @@ func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) { return } +func SendtoInet4(fd int, p []byte, flags int, to SockaddrInet4) (err error) { + ptr, n, err := to.sockaddr() + if err != nil { + return err + } + return sendto(fd, p, flags, ptr, n) +} + +func SendtoInet6(fd int, p []byte, flags int, to SockaddrInet6) (err error) { + ptr, n, err := to.sockaddr() + if err != nil { + return err + } + return sendto(fd, p, flags, ptr, n) +} + func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) { ptr, n, err := to.sockaddr() if err != nil { -- GitLab From 9c5eb16f6cba2b3d75f440dfec157183cc6d0f35 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Thu, 11 Feb 2021 19:34:22 -0800 Subject: [PATCH 0733/2500] net: reduce allocation size in ReadFromUDP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch to concrete types. Bring your own object to fill in. Allocate just enough for the IP byte slice. The allocation is now just 4 bytes for IPv4, which puts it in the tiny allocator, which is much faster. name old time/op new time/op delta WriteToReadFromUDP-8 13.7µs ± 1% 13.4µs ± 2% -2.49% (p=0.000 n=10+10) name old alloc/op new alloc/op delta WriteToReadFromUDP-8 32.0B ± 0% 4.0B ± 0% -87.50% (p=0.000 n=10+10) name old allocs/op new allocs/op delta WriteToReadFromUDP-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Windows is temporarily stubbed out. Updates #43451 Change-Id: Ief506f891b401d28715d22dce6ebda037941924e Reviewed-on: https://go-review.googlesource.com/c/go/+/331490 Trust: Josh Bleecher Snyder Trust: Damien Neil Run-TryBot: Josh Bleecher Snyder Run-TryBot: Damien Neil Reviewed-by: Damien Neil --- api/next.txt | 52 +++++++++++++++++++++++++++++++ src/internal/poll/fd_unix.go | 54 +++++++++++++++++++++++++++++++++ src/internal/poll/fd_windows.go | 18 +++++++++++ src/net/fd_posix.go | 11 +++++++ src/net/net_fake.go | 8 +++++ src/net/udpsock_posix.go | 26 +++++++++++----- src/syscall/net_js.go | 8 +++++ src/syscall/syscall_unix.go | 27 +++++++++++++++++ 8 files changed, 197 insertions(+), 7 deletions(-) diff --git a/api/next.txt b/api/next.txt index 8d2ee73f79..4dbaae3cf2 100644 --- a/api/next.txt +++ b/api/next.txt @@ -1,52 +1,104 @@ +pkg syscall (darwin-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (darwin-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (darwin-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (darwin-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (darwin-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (darwin-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (darwin-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (darwin-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (freebsd-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (freebsd-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (freebsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (freebsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (freebsd-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (freebsd-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (freebsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (freebsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (freebsd-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (freebsd-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (freebsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (freebsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (freebsd-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (freebsd-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (freebsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (freebsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (freebsd-arm), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (freebsd-arm), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (freebsd-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (freebsd-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (freebsd-arm-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (freebsd-arm-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (freebsd-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (freebsd-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (linux-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (linux-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (linux-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (linux-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (linux-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (linux-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (linux-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (linux-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (linux-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (linux-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (linux-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (linux-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (linux-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (linux-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (linux-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (linux-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (linux-arm), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (linux-arm), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (linux-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (linux-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (linux-arm-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (linux-arm-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (linux-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (linux-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (netbsd-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (netbsd-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (netbsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (netbsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (netbsd-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (netbsd-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (netbsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (netbsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (netbsd-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (netbsd-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (netbsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (netbsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (netbsd-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (netbsd-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (netbsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (netbsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (netbsd-arm), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (netbsd-arm), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (netbsd-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (netbsd-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (netbsd-arm-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (netbsd-arm-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (netbsd-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (netbsd-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (netbsd-arm64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (netbsd-arm64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (netbsd-arm64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (netbsd-arm64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (netbsd-arm64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (netbsd-arm64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (netbsd-arm64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (netbsd-arm64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (openbsd-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (openbsd-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (openbsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (openbsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (openbsd-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (openbsd-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (openbsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (openbsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (openbsd-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (openbsd-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (openbsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (openbsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (openbsd-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) +pkg syscall (openbsd-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (openbsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (openbsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error diff --git a/src/internal/poll/fd_unix.go b/src/internal/poll/fd_unix.go index 51d15f6abc..60b59df2e3 100644 --- a/src/internal/poll/fd_unix.go +++ b/src/internal/poll/fd_unix.go @@ -230,6 +230,60 @@ func (fd *FD) ReadFrom(p []byte) (int, syscall.Sockaddr, error) { } } +// ReadFrom wraps the recvfrom network call for IPv4. +func (fd *FD) ReadFromInet4(p []byte, from *syscall.SockaddrInet4) (int, error) { + if err := fd.readLock(); err != nil { + return 0, err + } + defer fd.readUnlock() + if err := fd.pd.prepareRead(fd.isFile); err != nil { + return 0, err + } + for { + n, err := syscall.RecvfromInet4(fd.Sysfd, p, 0, from) + if err != nil { + if err == syscall.EINTR { + continue + } + n = 0 + if err == syscall.EAGAIN && fd.pd.pollable() { + if err = fd.pd.waitRead(fd.isFile); err == nil { + continue + } + } + } + err = fd.eofError(n, err) + return n, err + } +} + +// ReadFrom wraps the recvfrom network call for IPv6. +func (fd *FD) ReadFromInet6(p []byte, from *syscall.SockaddrInet6) (int, error) { + if err := fd.readLock(); err != nil { + return 0, err + } + defer fd.readUnlock() + if err := fd.pd.prepareRead(fd.isFile); err != nil { + return 0, err + } + for { + n, err := syscall.RecvfromInet6(fd.Sysfd, p, 0, from) + if err != nil { + if err == syscall.EINTR { + continue + } + n = 0 + if err == syscall.EAGAIN && fd.pd.pollable() { + if err = fd.pd.waitRead(fd.isFile); err == nil { + continue + } + } + } + err = fd.eofError(n, err) + return n, err + } +} + // ReadMsg wraps the recvmsg network call. func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.Sockaddr, error) { if err := fd.readLock(); err != nil { diff --git a/src/internal/poll/fd_windows.go b/src/internal/poll/fd_windows.go index 3dada32985..14e8f4965b 100644 --- a/src/internal/poll/fd_windows.go +++ b/src/internal/poll/fd_windows.go @@ -593,6 +593,24 @@ func (fd *FD) ReadFrom(buf []byte) (int, syscall.Sockaddr, error) { return n, sa, nil } +// ReadFrom wraps the recvfrom network call for IPv4. +func (fd *FD) ReadFromInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) { + n, sa, err := fd.ReadFrom(buf) + if sa != nil { + *sa4 = *(sa.(*syscall.SockaddrInet4)) + } + return n, err +} + +// ReadFrom wraps the recvfrom network call for IPv6. +func (fd *FD) ReadFromInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) { + n, sa, err := fd.ReadFrom(buf) + if sa != nil { + *sa6 = *(sa.(*syscall.SockaddrInet6)) + } + return n, err +} + // Write implements io.Writer. func (fd *FD) Write(buf []byte) (int, error) { if err := fd.writeLock(); err != nil { diff --git a/src/net/fd_posix.go b/src/net/fd_posix.go index a0675b2072..38e5a8d61d 100644 --- a/src/net/fd_posix.go +++ b/src/net/fd_posix.go @@ -63,6 +63,17 @@ func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) { runtime.KeepAlive(fd) return n, sa, wrapSyscallError(readFromSyscallName, err) } +func (fd *netFD) readFromInet4(p []byte, from *syscall.SockaddrInet4) (n int, err error) { + n, err = fd.pfd.ReadFromInet4(p, from) + runtime.KeepAlive(fd) + return n, wrapSyscallError(readFromSyscallName, err) +} + +func (fd *netFD) readFromInet6(p []byte, from *syscall.SockaddrInet6) (n int, err error) { + n, err = fd.pfd.ReadFromInet6(p, from) + runtime.KeepAlive(fd) + return n, wrapSyscallError(readFromSyscallName, err) +} func (fd *netFD) readMsg(p []byte, oob []byte, flags int) (n, oobn, retflags int, sa syscall.Sockaddr, err error) { n, oobn, retflags, sa, err = fd.pfd.ReadMsg(p, oob, flags) diff --git a/src/net/net_fake.go b/src/net/net_fake.go index feb51968dd..48419be670 100644 --- a/src/net/net_fake.go +++ b/src/net/net_fake.go @@ -266,6 +266,14 @@ func sysSocket(family, sotype, proto int) (int, error) { func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) { return 0, nil, syscall.ENOSYS + +} +func (fd *netFD) readFromInet4(p []byte, sa *syscall.SockaddrInet4) (n int, err error) { + return 0, syscall.ENOSYS +} + +func (fd *netFD) readFromInet6(p []byte, sa *syscall.SockaddrInet6) (n int, err error) { + return 0, syscall.ENOSYS } func (fd *netFD) readMsg(p []byte, oob []byte, flags int) (n, oobn, retflags int, sa syscall.Sockaddr, err error) { diff --git a/src/net/udpsock_posix.go b/src/net/udpsock_posix.go index b71be09217..3a333ca243 100644 --- a/src/net/udpsock_posix.go +++ b/src/net/udpsock_posix.go @@ -44,13 +44,25 @@ func (a *UDPAddr) toLocal(net string) sockaddr { } func (c *UDPConn) readFrom(b []byte, addr *UDPAddr) (int, *UDPAddr, error) { - n, sa, err := c.fd.readFrom(b) - switch sa := sa.(type) { - case *syscall.SockaddrInet4: - *addr = UDPAddr{IP: sa.Addr[0:], Port: sa.Port} - case *syscall.SockaddrInet6: - *addr = UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneCache.name(int(sa.ZoneId))} - default: + var n int + var err error + switch c.fd.family { + case syscall.AF_INET: + var from syscall.SockaddrInet4 + n, err = c.fd.readFromInet4(b, &from) + if err == nil { + ip := from.Addr // copy from.Addr; ip escapes, so this line allocates 4 bytes + *addr = UDPAddr{IP: ip[:], Port: from.Port} + } + case syscall.AF_INET6: + var from syscall.SockaddrInet6 + n, err = c.fd.readFromInet6(b, &from) + if err == nil { + ip := from.Addr // copy from.Addr; ip escapes, so this line allocates 16 bytes + *addr = UDPAddr{IP: ip[:], Port: from.Port, Zone: zoneCache.name(int(from.ZoneId))} + } + } + if err != nil { // No sockaddr, so don't return UDPAddr. addr = nil } diff --git a/src/syscall/net_js.go b/src/syscall/net_js.go index 17799148bd..2998c2159c 100644 --- a/src/syscall/net_js.go +++ b/src/syscall/net_js.go @@ -92,6 +92,14 @@ func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) { return 0, nil, ENOSYS } +func RecvfromInet4(fd int, p []byte, flags int, from *SockaddrInet4) (n int, err error) { + return 0, ENOSYS +} + +func RecvfromInet6(fd int, p []byte, flags int, from *SockaddrInet6) (n int, err error) { + return 0, ENOSYS +} + func Sendto(fd int, p []byte, flags int, to Sockaddr) error { return ENOSYS } diff --git a/src/syscall/syscall_unix.go b/src/syscall/syscall_unix.go index 60aeae14de..101e39c7d0 100644 --- a/src/syscall/syscall_unix.go +++ b/src/syscall/syscall_unix.go @@ -292,6 +292,33 @@ func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) { return } +func RecvfromInet4(fd int, p []byte, flags int, from *SockaddrInet4) (n int, err error) { + var rsa RawSockaddrAny + var socklen _Socklen = SizeofSockaddrAny + if n, err = recvfrom(fd, p, flags, &rsa, &socklen); err != nil { + return + } + pp := (*RawSockaddrInet4)(unsafe.Pointer(&rsa)) + port := (*[2]byte)(unsafe.Pointer(&pp.Port)) + from.Port = int(port[0])<<8 + int(port[1]) + from.Addr = pp.Addr + return +} + +func RecvfromInet6(fd int, p []byte, flags int, from *SockaddrInet6) (n int, err error) { + var rsa RawSockaddrAny + var socklen _Socklen = SizeofSockaddrAny + if n, err = recvfrom(fd, p, flags, &rsa, &socklen); err != nil { + return + } + pp := (*RawSockaddrInet6)(unsafe.Pointer(&rsa)) + port := (*[2]byte)(unsafe.Pointer(&pp.Port)) + from.Port = int(port[0])<<8 + int(port[1]) + from.ZoneId = pp.Scope_id + from.Addr = pp.Addr + return +} + func SendtoInet4(fd int, p []byte, flags int, to SockaddrInet4) (err error) { ptr, n, err := to.sockaddr() if err != nil { -- GitLab From 2a193337164c8af8cba3d5c4ec0f36413c528bd8 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 28 Jun 2021 15:41:20 -0700 Subject: [PATCH 0734/2500] net: reduce allocations for UDP send/recv on Windows This brings the optimizations added in CLs 331489 and 331490 to Windows. Updates #43451 Change-Id: I75cf520050325d9eb5c2785d6d8677cc864fcac8 Reviewed-on: https://go-review.googlesource.com/c/go/+/331511 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Damien Neil --- api/next.txt | 4 ++ src/internal/poll/fd_windows.go | 90 +++++++++++++++++++++++++++++++-- src/syscall/syscall_windows.go | 32 ++++++++++++ 3 files changed, 122 insertions(+), 4 deletions(-) diff --git a/api/next.txt b/api/next.txt index 4dbaae3cf2..3eb7f3f797 100644 --- a/api/next.txt +++ b/api/next.txt @@ -102,3 +102,7 @@ pkg syscall (openbsd-amd64-cgo), func RecvfromInet4(int, []uint8, int, *Sockaddr pkg syscall (openbsd-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (openbsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error pkg syscall (openbsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error +pkg syscall (windows-386), func WSASendtoInet4(Handle, *WSABuf, uint32, *uint32, uint32, SockaddrInet4, *Overlapped, *uint8) error +pkg syscall (windows-386), func WSASendtoInet6(Handle, *WSABuf, uint32, *uint32, uint32, SockaddrInet6, *Overlapped, *uint8) error +pkg syscall (windows-amd64), func WSASendtoInet4(Handle, *WSABuf, uint32, *uint32, uint32, SockaddrInet4, *Overlapped, *uint8) error +pkg syscall (windows-amd64), func WSASendtoInet6(Handle, *WSABuf, uint32, *uint32, uint32, SockaddrInet6, *Overlapped, *uint8) error diff --git a/src/internal/poll/fd_windows.go b/src/internal/poll/fd_windows.go index 14e8f4965b..48fcdf306c 100644 --- a/src/internal/poll/fd_windows.go +++ b/src/internal/poll/fd_windows.go @@ -79,6 +79,8 @@ type operation struct { buf syscall.WSABuf msg windows.WSAMsg sa syscall.Sockaddr + sa4 syscall.SockaddrInet4 + sa6 syscall.SockaddrInet6 rsa *syscall.RawSockaddrAny rsan int32 handle syscall.Handle @@ -595,7 +597,30 @@ func (fd *FD) ReadFrom(buf []byte) (int, syscall.Sockaddr, error) { // ReadFrom wraps the recvfrom network call for IPv4. func (fd *FD) ReadFromInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) { - n, sa, err := fd.ReadFrom(buf) + if len(buf) == 0 { + return 0, nil + } + if len(buf) > maxRW { + buf = buf[:maxRW] + } + if err := fd.readLock(); err != nil { + return 0, err + } + defer fd.readUnlock() + o := &fd.rop + o.InitBuf(buf) + n, err := execIO(o, func(o *operation) error { + if o.rsa == nil { + o.rsa = new(syscall.RawSockaddrAny) + } + o.rsan = int32(unsafe.Sizeof(*o.rsa)) + return syscall.WSARecvFrom(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil) + }) + err = fd.eofError(n, err) + if err != nil { + return n, err + } + sa, _ := o.rsa.Sockaddr() if sa != nil { *sa4 = *(sa.(*syscall.SockaddrInet4)) } @@ -604,7 +629,30 @@ func (fd *FD) ReadFromInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) // ReadFrom wraps the recvfrom network call for IPv6. func (fd *FD) ReadFromInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) { - n, sa, err := fd.ReadFrom(buf) + if len(buf) == 0 { + return 0, nil + } + if len(buf) > maxRW { + buf = buf[:maxRW] + } + if err := fd.readLock(); err != nil { + return 0, err + } + defer fd.readUnlock() + o := &fd.rop + o.InitBuf(buf) + n, err := execIO(o, func(o *operation) error { + if o.rsa == nil { + o.rsa = new(syscall.RawSockaddrAny) + } + o.rsan = int32(unsafe.Sizeof(*o.rsa)) + return syscall.WSARecvFrom(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil) + }) + err = fd.eofError(n, err) + if err != nil { + return n, err + } + sa, _ := o.rsa.Sockaddr() if sa != nil { *sa6 = *(sa.(*syscall.SockaddrInet6)) } @@ -810,8 +858,42 @@ func (fd *FD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) { } // WriteTo wraps the sendto network call for IPv4. -func (fd *FD) WriteToInet4(buf []byte, sa syscall.SockaddrInet4) (int, error) { - return fd.WriteTo(buf, &sa) +func (fd *FD) WriteToInet4(buf []byte, sa4 syscall.SockaddrInet4) (int, error) { + if err := fd.writeLock(); err != nil { + return 0, err + } + defer fd.writeUnlock() + + if len(buf) == 0 { + // handle zero-byte payload + o := &fd.wop + o.InitBuf(buf) + o.sa4 = sa4 + n, err := execIO(o, func(o *operation) error { + return syscall.WSASendtoInet4(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa4, &o.o, nil) + }) + return n, err + } + + ntotal := 0 + for len(buf) > 0 { + b := buf + if len(b) > maxRW { + b = b[:maxRW] + } + o := &fd.wop + o.InitBuf(b) + o.sa4 = sa4 + n, err := execIO(o, func(o *operation) error { + return syscall.WSASendtoInet4(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa4, &o.o, nil) + }) + ntotal += int(n) + if err != nil { + return ntotal, err + } + buf = buf[n:] + } + return ntotal, nil } // WriteTo wraps the sendto network call for IPv6. diff --git a/src/syscall/syscall_windows.go b/src/syscall/syscall_windows.go index 660179ae9e..d4e51e541d 100644 --- a/src/syscall/syscall_windows.go +++ b/src/syscall/syscall_windows.go @@ -924,6 +924,38 @@ func WSASendto(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32 return err } +func WSASendtoInet4(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to SockaddrInet4, overlapped *Overlapped, croutine *byte) (err error) { + rsa, len, err := to.sockaddr() + if err != nil { + return err + } + r1, _, e1 := Syscall9(procWSASendTo.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(rsa)), uintptr(len), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) + if r1 == socket_error { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = EINVAL + } + } + return err +} + +func WSASendtoInet6(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to SockaddrInet6, overlapped *Overlapped, croutine *byte) (err error) { + rsa, len, err := to.sockaddr() + if err != nil { + return err + } + r1, _, e1 := Syscall9(procWSASendTo.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(rsa)), uintptr(len), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) + if r1 == socket_error { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = EINVAL + } + } + return err +} + func LoadGetAddrInfo() error { return procGetAddrInfoW.Find() } -- GitLab From 1951afc9193f8e197cb7dfaf6afed70ea02404cb Mon Sep 17 00:00:00 2001 From: Meng Zhuo Date: Sat, 31 Jul 2021 10:20:10 +0000 Subject: [PATCH 0735/2500] cmd/compile: lowered MulUintptr on riscv64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to RISCV instruction set manual v2.2 Sec 6.1 MULHU followed by MUL will be fused into one multiply by microarchitecture name old time/op new time/op delta MulUintptr/small 11.2ns ±24% 9.2ns ± 0% -17.54% (p=0.000 n=10+9) MulUintptr/large 15.9ns ± 0% 10.9ns ± 0% -31.55% (p=0.000 n=8+8) Change-Id: I3d152218f83948cbc5c576bda29dc86e9b4206ee Reviewed-on: https://go-review.googlesource.com/c/go/+/338753 Trust: Meng Zhuo Reviewed-by: Joel Sing --- src/cmd/compile/internal/riscv64/ssa.go | 21 +++++++++++++++++++ .../compile/internal/ssa/gen/RISCV64.rules | 1 + .../compile/internal/ssa/gen/RISCV64Ops.go | 1 + src/cmd/compile/internal/ssa/opGen.go | 16 ++++++++++++++ .../compile/internal/ssa/rewriteRISCV64.go | 3 +++ src/cmd/compile/internal/ssagen/ssa.go | 2 +- 6 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/riscv64/ssa.go b/src/cmd/compile/internal/riscv64/ssa.go index c635d93b71..d3cbb4ec24 100644 --- a/src/cmd/compile/internal/riscv64/ssa.go +++ b/src/cmd/compile/internal/riscv64/ssa.go @@ -297,6 +297,27 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p1.Reg = r0 p1.To.Type = obj.TYPE_REG p1.To.Reg = v.Reg1() + case ssa.OpRISCV64LoweredMuluover: + r0 := v.Args[0].Reg() + r1 := v.Args[1].Reg() + p := s.Prog(riscv.AMULHU) + p.From.Type = obj.TYPE_REG + p.From.Reg = r1 + p.Reg = r0 + p.To.Type = obj.TYPE_REG + p.To.Reg = v.Reg1() + p1 := s.Prog(riscv.AMUL) + p1.From.Type = obj.TYPE_REG + p1.From.Reg = r1 + p1.Reg = r0 + p1.To.Type = obj.TYPE_REG + p1.To.Reg = v.Reg0() + p2 := s.Prog(riscv.ASNEZ) + p2.From.Type = obj.TYPE_REG + p2.From.Reg = v.Reg1() + p2.To.Type = obj.TYPE_REG + p2.To.Reg = v.Reg1() + case ssa.OpRISCV64FSQRTS, ssa.OpRISCV64FNEGS, ssa.OpRISCV64FSQRTD, ssa.OpRISCV64FNEGD, ssa.OpRISCV64FMVSX, ssa.OpRISCV64FMVDX, ssa.OpRISCV64FCVTSW, ssa.OpRISCV64FCVTSL, ssa.OpRISCV64FCVTWS, ssa.OpRISCV64FCVTLS, diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64.rules b/src/cmd/compile/internal/ssa/gen/RISCV64.rules index b21ebe6abb..1acef2a273 100644 --- a/src/cmd/compile/internal/ssa/gen/RISCV64.rules +++ b/src/cmd/compile/internal/ssa/gen/RISCV64.rules @@ -30,6 +30,7 @@ (Mul64 ...) => (MUL ...) (Mul64uhilo ...) => (LoweredMuluhilo ...) +(Mul64uover ...) => (LoweredMuluover ...) (Mul32 ...) => (MULW ...) (Mul16 x y) => (MULW (SignExt16to32 x) (SignExt16to32 y)) (Mul8 x y) => (MULW (SignExt8to32 x) (SignExt8to32 y)) diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go index cb9051f954..d36daa8b83 100644 --- a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go @@ -159,6 +159,7 @@ func init() { {name: "MULH", argLength: 2, reg: gp21, asm: "MULH", commutative: true, typ: "Int64"}, {name: "MULHU", argLength: 2, reg: gp21, asm: "MULHU", commutative: true, typ: "UInt64"}, {name: "LoweredMuluhilo", argLength: 2, reg: gp22, resultNotInArgs: true}, // arg0 * arg1, return (hi, lo) + {name: "LoweredMuluover", argLength: 2, reg: gp22, resultNotInArgs: true}, // arg0 * arg1, return (64 bits of arg0*arg1, overflow) {name: "DIV", argLength: 2, reg: gp21, asm: "DIV", typ: "Int64"}, // arg0 / arg1 {name: "DIVU", argLength: 2, reg: gp21, asm: "DIVU", typ: "UInt64"}, diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 7893ce837e..8ce13abed3 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -2070,6 +2070,7 @@ const ( OpRISCV64MULH OpRISCV64MULHU OpRISCV64LoweredMuluhilo + OpRISCV64LoweredMuluover OpRISCV64DIV OpRISCV64DIVU OpRISCV64DIVW @@ -27619,6 +27620,21 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "LoweredMuluover", + argLen: 2, + resultNotInArgs: true, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + }, + outputs: []outputInfo{ + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + }, + }, + }, { name: "DIV", argLen: 2, diff --git a/src/cmd/compile/internal/ssa/rewriteRISCV64.go b/src/cmd/compile/internal/ssa/rewriteRISCV64.go index f315c0d3a8..e9f17206de 100644 --- a/src/cmd/compile/internal/ssa/rewriteRISCV64.go +++ b/src/cmd/compile/internal/ssa/rewriteRISCV64.go @@ -359,6 +359,9 @@ func rewriteValueRISCV64(v *Value) bool { case OpMul64uhilo: v.Op = OpRISCV64LoweredMuluhilo return true + case OpMul64uover: + v.Op = OpRISCV64LoweredMuluover + return true case OpMul8: return rewriteValueRISCV64_OpMul8(v) case OpNeg16: diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 237135d5c7..39d3b206ac 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -3779,7 +3779,7 @@ func InitTables() { } return s.newValue2(ssa.OpMul64uover, types.NewTuple(types.Types[types.TUINT], types.Types[types.TUINT]), args[0], args[1]) }, - sys.AMD64, sys.I386, sys.MIPS64) + sys.AMD64, sys.I386, sys.MIPS64, sys.RISCV64) add("runtime", "KeepAlive", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { data := s.newValue1(ssa.OpIData, s.f.Config.Types.BytePtr, args[0]) -- GitLab From a8d39f151d10209bca94c7533786dcc9c55c9517 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sun, 16 May 2021 00:08:42 +0700 Subject: [PATCH 0736/2500] src: simplify race.bash checking condition By using "uname -s -m" to get the OS name and hardware name, then using it to match supported platform in case command. Change-Id: I5161a29c6f3fe34dcda9e7bd477fa3b772b9e041 Reviewed-on: https://go-review.googlesource.com/c/go/+/320250 Trust: Cuong Manh Le Trust: Bryan C. Mills Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/race.bash | 39 ++++++++++----------------------------- 1 file changed, 10 insertions(+), 29 deletions(-) diff --git a/src/race.bash b/src/race.bash index 81fb4be606..f795ec9b7b 100755 --- a/src/race.bash +++ b/src/race.bash @@ -13,35 +13,16 @@ function usage { exit 1 } -case $(uname) in -"Darwin") - if [ $(uname -m) != "x86_64" ] && [ $(uname -m) != "arm64" ]; then - usage - fi - ;; -"Linux") - if [ $(uname -m) != "x86_64" ] && [ $(uname -m) != "ppc64le" ] && [ $(uname -m) != "aarch64" ]; then - usage - fi - ;; -"FreeBSD") - if [ $(uname -m) != "amd64" ]; then - usage - fi - ;; -"NetBSD") - if [ $(uname -m) != "amd64" ]; then - usage - fi - ;; -"OpenBSD") - if [ $(uname -m) != "amd64" ]; then - usage - fi - ;; -*) - usage - ;; +case $(uname -s -m) in + "Darwin x86_64") ;; + "Darwin arm64") ;; + "Linux x86_64") ;; + "Linux ppc64le") ;; + "Linux aarch64") ;; + "FreeBSD amd64") ;; + "NetBSD amd64") ;; + "OpenBSD amd64") ;; + *) usage ;; esac if [ ! -f make.bash ]; then -- GitLab From 91a935ea0f525c04016dd37c45143af942ffd3fc Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 16 Aug 2021 23:50:47 +0000 Subject: [PATCH 0737/2500] Revert "go/types: make Interface.Complete a no-op" This reverts commit fda8ee8b077dd8a5819cac7c52c3af1499a0674e. Reason for revert: Interface.Complete is still necessary for safe concurrency. For #47726 Change-Id: I8b924ca5f4af8c7d7e2b5a27bb03a5a5ed9b1d22 Reviewed-on: https://go-review.googlesource.com/c/go/+/342710 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/internal/gcimporter/iimport.go | 4 ++++ src/go/types/interface.go | 18 ++++++++++++++---- src/go/types/issues_test.go | 3 +-- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go index 5f05e8c0ad..dbc9b3a83e 100644 --- a/src/go/internal/gcimporter/iimport.go +++ b/src/go/internal/gcimporter/iimport.go @@ -174,6 +174,10 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, dataRea p.doDecl(localpkg, name) } + for _, typ := range p.interfaceList { + typ.Complete() + } + // record all referenced packages as imports list := append(([]*types.Package)(nil), pkgList[1:]...) sort.Sort(byPath(list)) diff --git a/src/go/types/interface.go b/src/go/types/interface.go index f4d560cb3e..510c123e97 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -104,12 +104,22 @@ func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() } // IsConstraint reports whether interface t is not just a method set. func (t *Interface) IsConstraint() bool { return !t.typeSet().IsMethodSet() } -// Complete just returns its receiver. There's no other effect. +// Complete computes the interface's type set. It must be called by users of +// NewInterfaceType and NewInterface after the interface's embedded types are +// fully defined and before using the interface type in any way other than to +// form other types. The interface must not contain duplicate methods or a +// panic occurs. Complete returns the receiver. // -// Deprecated: Interfaces are now completed on demand; this function is only -// here for backward-compatibility. It does not have to be called explicitly -// anymore. +// Deprecated: Type sets are now computed lazily, on demand; this function +// is only here for backward-compatibility. It does not have to +// be called explicitly anymore. func (t *Interface) Complete() *Interface { + // Some tests are still depending on the state change + // (string representation of an Interface not containing an + // /* incomplete */ marker) caused by the explicit Complete + // call, so we compute the type set eagerly here. + t.complete = true + t.typeSet() return t } diff --git a/src/go/types/issues_test.go b/src/go/types/issues_test.go index 618db13fb9..51995af30a 100644 --- a/src/go/types/issues_test.go +++ b/src/go/types/issues_test.go @@ -405,9 +405,8 @@ func TestIssue28282(t *testing.T) { // create type interface { error } et := Universe.Lookup("error").Type() it := NewInterfaceType(nil, []Type{et}) + it.Complete() // verify that after completing the interface, the embedded method remains unchanged - // (interfaces are "completed" lazily now, so the completion happens implicitly when - // accessing Method(0)) want := et.Underlying().(*Interface).Method(0) got := it.Method(0) if got != want { -- GitLab From 29ec74fb82328f4c005d556291ea687da7aad4b0 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 16 Aug 2021 20:13:25 -0400 Subject: [PATCH 0738/2500] go/types: check if the interface is already complete in Complete Once Interfaces have been completed they must never be written again, as they may be used concurrently. Avoid writing Interface.complete unnecessarily in Complete. Also, update documentation to reflect that Complete must be called before the Interface may be considered safe for concurrent use. For #47726 Change-Id: Ic9fd1395ab0dd6d3499f7a698dadf315abcddab8 Reviewed-on: https://go-review.googlesource.com/c/go/+/342749 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/interface.go | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/go/types/interface.go b/src/go/types/interface.go index 510c123e97..d27f8cfd4d 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -43,9 +43,12 @@ func NewInterface(methods []*Func, embeddeds []*Named) *Interface { return NewInterfaceType(methods, tnames) } -// NewInterfaceType returns a new interface for the given methods and embedded types. -// NewInterfaceType takes ownership of the provided methods and may modify their types -// by setting missing receivers. +// NewInterfaceType returns a new interface for the given methods and embedded +// types. NewInterfaceType takes ownership of the provided methods and may +// modify their types by setting missing receivers. +// +// To avoid race conditions, the interface's type set should be computed before +// concurrent use of the interface, by explicitly calling Complete. func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface { if len(methods) == 0 && len(embeddeds) == 0 { return &emptyInterface @@ -110,16 +113,12 @@ func (t *Interface) IsConstraint() bool { return !t.typeSet().IsMethodSet() } // form other types. The interface must not contain duplicate methods or a // panic occurs. Complete returns the receiver. // -// Deprecated: Type sets are now computed lazily, on demand; this function -// is only here for backward-compatibility. It does not have to -// be called explicitly anymore. +// Interface types that have been completed are safe for concurrent use. func (t *Interface) Complete() *Interface { - // Some tests are still depending on the state change - // (string representation of an Interface not containing an - // /* incomplete */ marker) caused by the explicit Complete - // call, so we compute the type set eagerly here. - t.complete = true - t.typeSet() + if !t.complete { + t.complete = true + } + t.typeSet() // checks if t.tset is already set return t } -- GitLab From d3deb2c359ec1d3b9fbfdfa224c0f03ecdde2c02 Mon Sep 17 00:00:00 2001 From: wangyuntao Date: Tue, 17 Aug 2021 03:24:15 +0000 Subject: [PATCH 0739/2500] cmd/compile: fix typos Change-Id: I88a3e69e232bf94296fe97621c5d395fc1296bbb GitHub-Last-Rev: f1cc29dc287eb02881fead0b815e1b45e23adfa4 GitHub-Pull-Request: golang/go#47482 Reviewed-on: https://go-review.googlesource.com/c/go/+/338751 Reviewed-by: Matthew Dempsky Trust: Josh Bleecher Snyder --- src/cmd/compile/internal/escape/graph.go | 2 +- src/cmd/compile/internal/ir/expr.go | 2 +- src/cmd/compile/internal/ir/stmt.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/escape/graph.go b/src/cmd/compile/internal/escape/graph.go index d3ae1da693..cc3d078add 100644 --- a/src/cmd/compile/internal/escape/graph.go +++ b/src/cmd/compile/internal/escape/graph.go @@ -117,7 +117,7 @@ func (l *location) isName(c ir.Class) bool { return l.n != nil && l.n.Op() == ir.ONAME && l.n.(*ir.Name).Class == c } -// An hole represents a context for evaluation a Go +// A hole represents a context for evaluation of a Go // expression. E.g., when evaluating p in "x = **p", we'd have a hole // with dst==x and derefs==2. type hole struct { diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index dc28483907..f526d987a7 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -275,7 +275,7 @@ func (n *ConvExpr) SetOp(op Op) { } } -// An IndexExpr is an index expression X[Y]. +// An IndexExpr is an index expression X[Index]. type IndexExpr struct { miniExpr X Node diff --git a/src/cmd/compile/internal/ir/stmt.go b/src/cmd/compile/internal/ir/stmt.go index 8115012f97..69a74b9fdd 100644 --- a/src/cmd/compile/internal/ir/stmt.go +++ b/src/cmd/compile/internal/ir/stmt.go @@ -244,7 +244,7 @@ func NewGoDeferStmt(pos src.XPos, op Op, call Node) *GoDeferStmt { return n } -// A IfStmt is a return statement: if Init; Cond { Then } else { Else }. +// An IfStmt is a return statement: if Init; Cond { Body } else { Else }. type IfStmt struct { miniStmt Cond Node -- GitLab From a304273d74b95c835ee08b641a17ce6bc591ddd3 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 16 Aug 2021 18:06:18 -0700 Subject: [PATCH 0740/2500] cmd/compile/internal/types2: allow composite literals of type parameter type Change-Id: Iaaa2a3b462da6b121f13a10595950a8502b5f271 Reviewed-on: https://go-review.googlesource.com/c/go/+/342690 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/expr.go | 2 +- .../types2/testdata/examples/types.go2 | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 6d8b423714..d108093dac 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -1214,7 +1214,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin goto Error } - switch utyp := under(base).(type) { + switch utyp := optype(base).(type) { case *Struct: if len(e.ElemList) == 0 { break diff --git a/src/cmd/compile/internal/types2/testdata/examples/types.go2 b/src/cmd/compile/internal/types2/testdata/examples/types.go2 index d662444ead..9ee014452c 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/types.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/types.go2 @@ -185,7 +185,7 @@ type _ struct { // } // It is not permitted to declare a local type whose underlying -// type is a type parameters not declared by that type declaration. +// type is a type parameter not declared by that type declaration. func _[T any]() { type _ T // ERROR cannot use function type parameter T as RHS in type declaration type _ [_ any] T // ERROR cannot use function type parameter T as RHS in type declaration @@ -287,3 +287,19 @@ func _[T interface{~int|~float64}]() { var _ T = 1 _ = T(0) } + +// It is possible to create composite literals of type parameter +// type as long as it's possible to create a composite literal +// of the structural type of the type parameter's constraint. +func _[P interface{ ~[]int }]() P { + return P{} + return P{1, 2, 3} +} + +func _[P interface{ ~[]E }, E interface{ map[string]P } ]() P { + x := P{} + return P{{}} + return P{E{}} + return P{E{"foo": x}} + return P{{"foo": x}, {}} +} -- GitLab From b7b790a71a86678f036b7d30a892c5f792c5092f Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Thu, 12 Aug 2021 17:08:49 -0700 Subject: [PATCH 0741/2500] cmd/compile: fix CONVIFACE case converting interface to empty interface We need an extra case in convertToDictionary. In the case of an operand which is an interface and converting to an empty interface, we don't want to get the run-time type from the dictionary (which would be the run-time type of the interface). We want to do a type-assert to the empty interface. Change-Id: I414247210168153151272fab198bfe82ad7b1567 Reviewed-on: https://go-review.googlesource.com/c/go/+/342009 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 5 +++ test/typeparam/issue47272.go | 55 +++++++++++++++++++++++ test/typeparam/issue47272.out | 2 + 3 files changed, 62 insertions(+) create mode 100644 test/typeparam/issue47272.go create mode 100644 test/typeparam/issue47272.out diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 6736f128e3..4ac37c362c 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1224,6 +1224,11 @@ func convertUsingDictionary(info *instInfo, dictParam *ir.Name, pos src.XPos, v } assert(ix >= 0) rt = getDictionaryEntry(pos, dictParam, ix, info.dictLen) + } else if v.Type().IsInterface() { + ta := ir.NewTypeAssertExpr(pos, v, nil) + ta.SetType(dst) + ta.SetTypecheck(1) + return ta } else { ix := findDictType(info, src) assert(ix >= 0) diff --git a/test/typeparam/issue47272.go b/test/typeparam/issue47272.go new file mode 100644 index 0000000000..6771cb9901 --- /dev/null +++ b/test/typeparam/issue47272.go @@ -0,0 +1,55 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "errors" + "fmt" +) + +type Option[T any] struct { + ok bool + val T +} + +func (o Option[T]) String() string { + if o.ok { + return fmt.Sprintf("Some(%v)", o.val) + } + return "None" +} + +func Some[T any](val T) Option[T] { return Option[T]{ok: true, val: val} } +func None[T any]() Option[T] { return Option[T]{ok: false} } + +type Result[T, E any] struct { + ok bool + val T + err E +} + +func (r Result[T, E]) String() string { + if r.ok { + return fmt.Sprintf("Ok(%v)", r.val) + } + return fmt.Sprintf("Err(%v)", r.err) +} + +func Ok[T, E any](val T) Result[T, E] { return Result[T, E]{ok: true, val: val} } +func Err[T, E any](err E) Result[T, E] { return Result[T, E]{ok: false, err: err} } + +func main() { + a := Some[int](1) + b := None[int]() + fmt.Println(a, b) + + x := Ok[int, error](1) + y := Err[int, error](errors.New("test")) + fmt.Println(x, y) + // fmt.Println(x) + _, _, _, _ = a, b, x, y +} diff --git a/test/typeparam/issue47272.out b/test/typeparam/issue47272.out new file mode 100644 index 0000000000..9c433faa97 --- /dev/null +++ b/test/typeparam/issue47272.out @@ -0,0 +1,2 @@ +Some(1) None +Ok(1) Err(test) -- GitLab From 4012fea822763ef3aa66dd949fa95b9f8d89450a Mon Sep 17 00:00:00 2001 From: Yasuhiro Matsumoto Date: Fri, 23 Jul 2021 22:28:26 +0900 Subject: [PATCH 0742/2500] all: fix typos Change-Id: I83180c472db8795803c1b9be3a33f35959e4dcc2 Reviewed-on: https://go-review.googlesource.com/c/go/+/336889 Reviewed-by: Rob Pike Reviewed-by: Austin Clements --- src/cmd/go/internal/modcmd/vendor.go | 2 +- .../example.com_split-incompatible_v2.0.0+incompatible.txt | 2 +- ...ample.com_split-incompatible_v2.1.0-pre+incompatible.txt | 2 +- src/cmd/go/testdata/script/mod_lazy_import_allmod.txt | 2 +- src/cmd/go/testdata/script/mod_tidy_compat.txt | 2 +- src/crypto/ed25519/internal/edwards25519/tables.go | 2 +- src/crypto/x509/parser.go | 6 +++--- src/math/sinh_s390x.s | 4 ++-- src/math/tan_s390x.s | 2 +- src/net/lookup.go | 2 +- src/reflect/value.go | 2 +- src/runtime/traceback.go | 2 +- src/strconv/ftoaryu.go | 2 +- test/typeparam/slices.go | 2 +- 14 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/cmd/go/internal/modcmd/vendor.go b/src/cmd/go/internal/modcmd/vendor.go index b133ba7ea9..4e01dfab1e 100644 --- a/src/cmd/go/internal/modcmd/vendor.go +++ b/src/cmd/go/internal/modcmd/vendor.go @@ -242,7 +242,7 @@ func vendorPkg(vdir, pkg string) { if err != nil { if errors.As(err, &noGoError) { return // No source files in this package are built. Skip embeds in ignored files. - } else if !errors.As(err, &multiplePackageError) { // multiplePackgeErrors are okay, but others are not. + } else if !errors.As(err, &multiplePackageError) { // multiplePackageErrors are OK, but others are not. base.Fatalf("internal error: failed to find embedded files of %s: %v\n", pkg, err) } } diff --git a/src/cmd/go/testdata/mod/example.com_split-incompatible_v2.0.0+incompatible.txt b/src/cmd/go/testdata/mod/example.com_split-incompatible_v2.0.0+incompatible.txt index 35c3f27710..00076d74fc 100644 --- a/src/cmd/go/testdata/mod/example.com_split-incompatible_v2.0.0+incompatible.txt +++ b/src/cmd/go/testdata/mod/example.com_split-incompatible_v2.0.0+incompatible.txt @@ -1,6 +1,6 @@ Written by hand. Test case for getting a package that has been moved to a nested module, -with a +incompatible verison (and thus no go.mod file) at the root module. +with a +incompatible version (and thus no go.mod file) at the root module. -- .mod -- module example.com/split-incompatible diff --git a/src/cmd/go/testdata/mod/example.com_split-incompatible_v2.1.0-pre+incompatible.txt b/src/cmd/go/testdata/mod/example.com_split-incompatible_v2.1.0-pre+incompatible.txt index 917fc0f559..bb1c1fecc9 100644 --- a/src/cmd/go/testdata/mod/example.com_split-incompatible_v2.1.0-pre+incompatible.txt +++ b/src/cmd/go/testdata/mod/example.com_split-incompatible_v2.1.0-pre+incompatible.txt @@ -1,6 +1,6 @@ Written by hand. Test case for getting a package that has been moved to a nested module, -with a +incompatible verison (and thus no go.mod file) at the root module. +with a +incompatible version (and thus no go.mod file) at the root module. -- .mod -- module example.com/split-incompatible diff --git a/src/cmd/go/testdata/script/mod_lazy_import_allmod.txt b/src/cmd/go/testdata/script/mod_lazy_import_allmod.txt index 97718c4513..60d4187b11 100644 --- a/src/cmd/go/testdata/script/mod_lazy_import_allmod.txt +++ b/src/cmd/go/testdata/script/mod_lazy_import_allmod.txt @@ -66,7 +66,7 @@ stdout '^b v0.1.0 ' ! stdout '^c ' # After adding a new direct import of b/y, -# the existing verison of b should be promoted to a root, +# the existing version of b should be promoted to a root, # bringing the version of c required by b into the build list. cp m.go.new m.go diff --git a/src/cmd/go/testdata/script/mod_tidy_compat.txt b/src/cmd/go/testdata/script/mod_tidy_compat.txt index e6edef5ee3..29cae17881 100644 --- a/src/cmd/go/testdata/script/mod_tidy_compat.txt +++ b/src/cmd/go/testdata/script/mod_tidy_compat.txt @@ -20,7 +20,7 @@ env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}' # + ---- example.net/lazy v0.1.0 ---- example.com/version v1.0.1 # # Go 1.17 avoids loading the go.mod file for example.com/version v1.0.1 -# (because it is lower than the verison explicitly required by m, +# (because it is lower than the version explicitly required by m, # and the module that requires it — m — specifies 'go 1.17'). # # That go.mod file happens not to affect the final 1.16 module graph anyway, diff --git a/src/crypto/ed25519/internal/edwards25519/tables.go b/src/crypto/ed25519/internal/edwards25519/tables.go index beec956bf7..5ca40f7bfa 100644 --- a/src/crypto/ed25519/internal/edwards25519/tables.go +++ b/src/crypto/ed25519/internal/edwards25519/tables.go @@ -40,7 +40,7 @@ func (v *projLookupTable) FromP3(q *Point) { for i := 0; i < 7; i++ { // Compute (i+1)*Q as Q + i*Q and convert to a ProjCached // This is needlessly complicated because the API has explicit - // recievers instead of creating stack objects and relying on RVO + // receivers instead of creating stack objects and relying on RVO v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.Add(q, &v.points[i]))) } } diff --git a/src/crypto/x509/parser.go b/src/crypto/x509/parser.go index f085162a4e..c2770f3f08 100644 --- a/src/crypto/x509/parser.go +++ b/src/crypto/x509/parser.go @@ -214,16 +214,16 @@ func parseValidity(der cryptobyte.String) (time.Time, time.Time, error) { func parseExtension(der cryptobyte.String) (pkix.Extension, error) { var ext pkix.Extension if !der.ReadASN1ObjectIdentifier(&ext.Id) { - return ext, errors.New("x509: malformed extention OID field") + return ext, errors.New("x509: malformed extension OID field") } if der.PeekASN1Tag(cryptobyte_asn1.BOOLEAN) { if !der.ReadASN1Boolean(&ext.Critical) { - return ext, errors.New("x509: malformed extention critical field") + return ext, errors.New("x509: malformed extension critical field") } } var val cryptobyte.String if !der.ReadASN1(&val, cryptobyte_asn1.OCTET_STRING) { - return ext, errors.New("x509: malformed extention value field") + return ext, errors.New("x509: malformed extension value field") } ext.Value = val return ext, nil diff --git a/src/math/sinh_s390x.s b/src/math/sinh_s390x.s index 73701f24f1..d684968a3a 100644 --- a/src/math/sinh_s390x.s +++ b/src/math/sinh_s390x.s @@ -56,11 +56,11 @@ GLOBL sinhe9<>+0(SB), RODATA, $8 TEXT ·sinhAsm(SB),NOSPLIT,$0-16 FMOVD x+0(FP), F0 - //specail case Sinh(±0) = ±0 + //special case Sinh(±0) = ±0 FMOVD $(0.0), F1 FCMPU F0, F1 BEQ sinhIsZero - //specail case Sinh(±Inf = ±Inf + //special case Sinh(±Inf) = ±Inf FMOVD $1.797693134862315708145274237317043567981e+308, F1 FCMPU F1, F0 BLEU sinhIsInf diff --git a/src/math/tan_s390x.s b/src/math/tan_s390x.s index b6e2295874..82267608b9 100644 --- a/src/math/tan_s390x.s +++ b/src/math/tan_s390x.s @@ -38,7 +38,7 @@ GLOBL ·tanxadd<> + 0(SB), RODATA, $8 TEXT ·tanAsm(SB), NOSPLIT, $0-16 FMOVD x+0(FP), F0 - //specail case Tan(±0) = ±0 + //special case Tan(±0) = ±0 FMOVD $(0.0), F1 FCMPU F0, F1 BEQ atanIsZero diff --git a/src/net/lookup.go b/src/net/lookup.go index d350ef7fc0..02beaca7e1 100644 --- a/src/net/lookup.go +++ b/src/net/lookup.go @@ -620,6 +620,6 @@ func (r *Resolver) LookupAddr(ctx context.Context, addr string) ([]string, error } // errMalformedDNSRecordsDetail is the DNSError detail which is returned when a Resolver.Lookup... -// method recieves DNS records which contain invalid DNS names. This may be returned alongside +// method receives DNS records which contain invalid DNS names. This may be returned alongside // results which have had the malformed records filtered out. var errMalformedDNSRecordsDetail = "DNS response contained records which contain invalid names" diff --git a/src/reflect/value.go b/src/reflect/value.go index b4b2d2e38b..e641a7957c 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -930,7 +930,7 @@ func callMethod(ctxt *methodValue, frame unsafe.Pointer, retValid *bool, regs *a // Deal with the receiver. It's guaranteed to only be one word in size. if st := methodABI.call.steps[0]; st.kind == abiStepStack { - // Only copy the reciever to the stack if the ABI says so. + // Only copy the receiver to the stack if the ABI says so. // Otherwise, it'll be in a register already. storeRcvr(rcvr, methodFrame) } else { diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go index addfa6faac..8c0979eec2 100644 --- a/src/runtime/traceback.go +++ b/src/runtime/traceback.go @@ -566,7 +566,7 @@ func printArgs(f funcInfo, argp unsafe.Pointer) { print1 := func(off, sz uint8) { x := readUnaligned64(add(argp, uintptr(off))) - // mask out irrelavant bits + // mask out irrelevant bits if sz < 8 { shift := 64 - sz*8 if goarch.BigEndian { diff --git a/src/strconv/ftoaryu.go b/src/strconv/ftoaryu.go index 1c61288b9f..f2e74bed17 100644 --- a/src/strconv/ftoaryu.go +++ b/src/strconv/ftoaryu.go @@ -291,7 +291,7 @@ func ryuFtoaShortest(d *decimalSlice, mant uint64, exp int, flt *floatInfo) { // Is it allowed to use 'du' as a result? // It is always allowed when it is truncated, but also // if it is exact and the original binary mantissa is even - // When disallowed, we can substract 1. + // When disallowed, we can subtract 1. uok := !du0 || fracu > 0 if du0 && fracu == 0 { uok = mant&1 == 0 diff --git a/test/typeparam/slices.go b/test/typeparam/slices.go index b5e8e0c606..4bdf10748e 100644 --- a/test/typeparam/slices.go +++ b/test/typeparam/slices.go @@ -60,7 +60,7 @@ func _Equal[Elem comparable](s1, s2 []Elem) bool { return true } -// _EqualFn reports whether two slices are equal using a comparision +// _EqualFn reports whether two slices are equal using a comparison // function on each element. func _EqualFn[Elem any](s1, s2 []Elem, eq func(Elem, Elem) bool) bool { if len(s1) != len(s2) { -- GitLab From 3001b0abf00d94c3d6b3a6fa343ef89bc060c4bb Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 15 Jun 2021 13:47:03 -0400 Subject: [PATCH 0743/2500] cmd/link: remove elfwritedynentsym elfwritedynentsym and elfWriteDynEntSym are identical. Change-Id: I893a9a65fdc496f98ba6e66c2bf1ed8dd52f52fd Reviewed-on: https://go-review.googlesource.com/c/go/+/342709 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/link/internal/ld/elf.go | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go index 81011638bc..ffc27d66b7 100644 --- a/src/cmd/link/internal/ld/elf.go +++ b/src/cmd/link/internal/ld/elf.go @@ -480,10 +480,6 @@ func Elfwritedynent(arch *sys.Arch, s *loader.SymbolBuilder, tag elf.DynTag, val } } -func elfwritedynentsym(ctxt *Link, s *loader.SymbolBuilder, tag elf.DynTag, t loader.Sym) { - Elfwritedynentsymplus(ctxt, s, tag, t, 0) -} - func Elfwritedynentsymplus(ctxt *Link, s *loader.SymbolBuilder, tag elf.DynTag, t loader.Sym, add int64) { if elf64 { s.AddUint64(ctxt.Arch, uint64(tag)) @@ -1472,24 +1468,24 @@ func (ctxt *Link) doelf() { /* * .dynamic table */ - elfwritedynentsym(ctxt, dynamic, elf.DT_HASH, hash.Sym()) + elfWriteDynEntSym(ctxt, dynamic, elf.DT_HASH, hash.Sym()) - elfwritedynentsym(ctxt, dynamic, elf.DT_SYMTAB, dynsym.Sym()) + elfWriteDynEntSym(ctxt, dynamic, elf.DT_SYMTAB, dynsym.Sym()) if elf64 { Elfwritedynent(ctxt.Arch, dynamic, elf.DT_SYMENT, ELF64SYMSIZE) } else { Elfwritedynent(ctxt.Arch, dynamic, elf.DT_SYMENT, ELF32SYMSIZE) } - elfwritedynentsym(ctxt, dynamic, elf.DT_STRTAB, dynstr.Sym()) + elfWriteDynEntSym(ctxt, dynamic, elf.DT_STRTAB, dynstr.Sym()) elfwritedynentsymsize(ctxt, dynamic, elf.DT_STRSZ, dynstr.Sym()) if elfRelType == ".rela" { rela := ldr.LookupOrCreateSym(".rela", 0) - elfwritedynentsym(ctxt, dynamic, elf.DT_RELA, rela) + elfWriteDynEntSym(ctxt, dynamic, elf.DT_RELA, rela) elfwritedynentsymsize(ctxt, dynamic, elf.DT_RELASZ, rela) Elfwritedynent(ctxt.Arch, dynamic, elf.DT_RELAENT, ELF64RELASIZE) } else { rel := ldr.LookupOrCreateSym(".rel", 0) - elfwritedynentsym(ctxt, dynamic, elf.DT_REL, rel) + elfWriteDynEntSym(ctxt, dynamic, elf.DT_REL, rel) elfwritedynentsymsize(ctxt, dynamic, elf.DT_RELSZ, rel) Elfwritedynent(ctxt.Arch, dynamic, elf.DT_RELENT, ELF32RELSIZE) } @@ -1499,9 +1495,9 @@ func (ctxt *Link) doelf() { } if ctxt.IsPPC64() { - elfwritedynentsym(ctxt, dynamic, elf.DT_PLTGOT, plt.Sym()) + elfWriteDynEntSym(ctxt, dynamic, elf.DT_PLTGOT, plt.Sym()) } else { - elfwritedynentsym(ctxt, dynamic, elf.DT_PLTGOT, gotplt.Sym()) + elfWriteDynEntSym(ctxt, dynamic, elf.DT_PLTGOT, gotplt.Sym()) } if ctxt.IsPPC64() { -- GitLab From cf12b0d1f96242eefbe64dbf449f30cce2756560 Mon Sep 17 00:00:00 2001 From: Leonard Wang Date: Tue, 20 Jul 2021 00:05:16 +0800 Subject: [PATCH 0744/2500] cmd/trace: use newTaskDesc to create taskDesc Change-Id: I9bec8e2c4a9e1b9aa2baf883504200b5674844f8 Reviewed-on: https://go-review.googlesource.com/c/go/+/335609 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Michael Knyszek Reviewed-by: Michael Pratt Trust: Michael Knyszek Trust: Michael Pratt --- src/cmd/trace/annotations.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/cmd/trace/annotations.go b/src/cmd/trace/annotations.go index 9b45457436..1c0dad56d8 100644 --- a/src/cmd/trace/annotations.go +++ b/src/cmd/trace/annotations.go @@ -407,10 +407,7 @@ func (tasks allTasks) task(taskID uint64) *taskDesc { return t } - t = &taskDesc{ - id: taskID, - goroutines: make(map[uint64]struct{}), - } + t = newTaskDesc(taskID) tasks[taskID] = t return t } -- GitLab From 9d9e3291faee4b01165247956e8555eb1bb291f1 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 17 Aug 2021 11:45:05 -0700 Subject: [PATCH 0745/2500] cmd/compile/internal/types2: fix method lookup for type-parameter based types Pointers to type parameters don't have methods, but pointers to defined types whose underlying types are type parameters may have methods. Fix the respective test. For #47747. Change-Id: I1de47be094ed9297f0e7782538011657c37c5adc Reviewed-on: https://go-review.googlesource.com/c/go/+/342990 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/lookup.go | 9 ++- .../types2/testdata/fixedbugs/issue47747.go2 | 68 +++++++++++++++++++ 2 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue47747.go2 diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index 3779d17b3d..668c5ff3ec 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -74,9 +74,12 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o typ, isPtr := deref(T) // *typ where typ is an interface or type parameter has no methods. - switch under(typ).(type) { - case *Interface, *TypeParam: - if isPtr { + if isPtr { + // don't look at under(typ) here - was bug (issue #47747) + if _, ok := typ.(*TypeParam); ok { + return + } + if _, ok := under(typ).(*Interface); ok { return } } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47747.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47747.go2 new file mode 100644 index 0000000000..af52056bef --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47747.go2 @@ -0,0 +1,68 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T1[P any] P + +func (T1[_]) m() {} + +func _[P any](x *T1[P]) { + // x.m exists because x is of type *T1 where T1 is a defined type + // (even though under(T1) is a type parameter) + x.m() +} + + +func _[P interface{ m() }](x P) { + x.m() + // (&x).m doesn't exist because &x is of type *P + // and pointers to type parameters don't have methods + (&x).m /* ERROR \*P has no field or method m */ () +} + + +type T2 interface{ m() } + +func _(x *T2) { + // x.m doesn't exists because x is of type *T2 + // and pointers to interfaces don't have methods + x.m /* ERROR \*T2 has no field or method m */() +} + +// Test case 1 from issue + +type Fooer1[t any] interface { + Foo(Barer[t]) +} +type Barer[t any] interface { + Bar(t) +} + +type Foo1[t any] t +type Bar[t any] t + +func (l Foo1[t]) Foo(v Barer[t]) { v.Bar(t(l)) } +func (b *Bar[t]) Bar(l t) { *b = Bar[t](l) } + +func _[t any](f Fooer1[t]) t { + var b Bar[t] + f.Foo(&b) + return t(b) +} + +// Test case 2 from issue + +type Fooer2[t any] interface { + Foo() +} + +type Foo2[t any] t + +func (f *Foo2[t]) Foo() {} + +func _[t any](v t) { + var f = Foo2[t](v) + _ = Fooer2[t](&f) +} -- GitLab From 0f85b0c0e1dc96a165645bf6da3693e8a3603ebc Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 17 Aug 2021 11:55:39 -0700 Subject: [PATCH 0746/2500] go/types: fix method lookup for type-parameter based types This is a clean port of CL 342990. Fixes #47747. Change-Id: I2e86fb8b70d42a220ac1ba25798d9e58227ba5f6 Reviewed-on: https://go-review.googlesource.com/c/go/+/342991 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/go/types/lookup.go | 9 ++- .../types/testdata/fixedbugs/issue47747.go2 | 68 +++++++++++++++++++ 2 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue47747.go2 diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index 186e421edb..20a24cab73 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -76,9 +76,12 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o typ, isPtr := deref(T) // *typ where typ is an interface or type parameter has no methods. - switch under(typ).(type) { - case *Interface, *TypeParam: - if isPtr { + if isPtr { + // don't look at under(typ) here - was bug (issue #47747) + if _, ok := typ.(*TypeParam); ok { + return + } + if _, ok := under(typ).(*Interface); ok { return } } diff --git a/src/go/types/testdata/fixedbugs/issue47747.go2 b/src/go/types/testdata/fixedbugs/issue47747.go2 new file mode 100644 index 0000000000..af52056bef --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue47747.go2 @@ -0,0 +1,68 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T1[P any] P + +func (T1[_]) m() {} + +func _[P any](x *T1[P]) { + // x.m exists because x is of type *T1 where T1 is a defined type + // (even though under(T1) is a type parameter) + x.m() +} + + +func _[P interface{ m() }](x P) { + x.m() + // (&x).m doesn't exist because &x is of type *P + // and pointers to type parameters don't have methods + (&x).m /* ERROR \*P has no field or method m */ () +} + + +type T2 interface{ m() } + +func _(x *T2) { + // x.m doesn't exists because x is of type *T2 + // and pointers to interfaces don't have methods + x.m /* ERROR \*T2 has no field or method m */() +} + +// Test case 1 from issue + +type Fooer1[t any] interface { + Foo(Barer[t]) +} +type Barer[t any] interface { + Bar(t) +} + +type Foo1[t any] t +type Bar[t any] t + +func (l Foo1[t]) Foo(v Barer[t]) { v.Bar(t(l)) } +func (b *Bar[t]) Bar(l t) { *b = Bar[t](l) } + +func _[t any](f Fooer1[t]) t { + var b Bar[t] + f.Foo(&b) + return t(b) +} + +// Test case 2 from issue + +type Fooer2[t any] interface { + Foo() +} + +type Foo2[t any] t + +func (f *Foo2[t]) Foo() {} + +func _[t any](v t) { + var f = Foo2[t](v) + _ = Fooer2[t](&f) +} -- GitLab From ace1730a417bf5cb1662407ef12013ca7e4e5f84 Mon Sep 17 00:00:00 2001 From: kezhao Date: Wed, 28 Jul 2021 02:06:10 +0000 Subject: [PATCH 0747/2500] cmd/go: go test flag -failfast should be cacheable Add failfast to cacheable list and update docs Fixes #47355 Change-Id: I75b371c45b80a3b179ff070b7b9d092a504380c0 GitHub-Last-Rev: abe61fd48c01fab4ef5ea5db013dcce4ead09c6f GitHub-Pull-Request: golang/go#47371 Reviewed-on: https://go-review.googlesource.com/c/go/+/337229 Reviewed-by: Jay Conrod Reviewed-by: Bryan C. Mills Run-TryBot: Jay Conrod TryBot-Result: Go Bot --- src/cmd/go/alldocs.go | 20 +++++++++--------- src/cmd/go/internal/test/test.go | 21 ++++++++++--------- .../go/testdata/script/test_cache_inputs.txt | 6 ++++++ 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index f919699627..ddf7bb5318 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -1446,16 +1446,16 @@ // The rule for a match in the cache is that the run involves the same // test binary and the flags on the command line come entirely from a // restricted set of 'cacheable' test flags, defined as -benchtime, -cpu, -// -list, -parallel, -run, -short, and -v. If a run of go test has any test -// or non-test flags outside this set, the result is not cached. To -// disable test caching, use any test flag or argument other than the -// cacheable flags. The idiomatic way to disable test caching explicitly -// is to use -count=1. Tests that open files within the package's source -// root (usually $GOPATH) or that consult environment variables only -// match future runs in which the files and environment variables are unchanged. -// A cached test result is treated as executing in no time at all, -// so a successful package test result will be cached and reused -// regardless of -timeout setting. +// -list, -parallel, -run, -short, -timeout, -failfast, and -v. +// If a run of go test has any test or non-test flags outside this set, +// the result is not cached. To disable test caching, use any test flag +// or argument other than the cacheable flags. The idiomatic way to disable +// test caching explicitly is to use -count=1. Tests that open files within +// the package's source root (usually $GOPATH) or that consult environment +// variables only match future runs in which the files and environment +// variables are unchanged. A cached test result is treated as executing +// in no time at all,so a successful package test result will be cached and +// reused regardless of -timeout setting. // // In addition to the build flags, the flags handled by 'go test' itself are: // diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index ce8f226a96..e8bf0e198e 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -119,16 +119,16 @@ elapsed time in the summary line. The rule for a match in the cache is that the run involves the same test binary and the flags on the command line come entirely from a restricted set of 'cacheable' test flags, defined as -benchtime, -cpu, --list, -parallel, -run, -short, and -v. If a run of go test has any test -or non-test flags outside this set, the result is not cached. To -disable test caching, use any test flag or argument other than the -cacheable flags. The idiomatic way to disable test caching explicitly -is to use -count=1. Tests that open files within the package's source -root (usually $GOPATH) or that consult environment variables only -match future runs in which the files and environment variables are unchanged. -A cached test result is treated as executing in no time at all, -so a successful package test result will be cached and reused -regardless of -timeout setting. +-list, -parallel, -run, -short, -timeout, -failfast, and -v. +If a run of go test has any test or non-test flags outside this set, +the result is not cached. To disable test caching, use any test flag +or argument other than the cacheable flags. The idiomatic way to disable +test caching explicitly is to use -count=1. Tests that open files within +the package's source root (usually $GOPATH) or that consult environment +variables only match future runs in which the files and environment +variables are unchanged. A cached test result is treated as executing +in no time at all,so a successful package test result will be cached and +reused regardless of -timeout setting. In addition to the build flags, the flags handled by 'go test' itself are: @@ -1351,6 +1351,7 @@ func (c *runCache) tryCacheWithID(b *work.Builder, a *work.Action, id string) bo "-test.run", "-test.short", "-test.timeout", + "-test.failfast", "-test.v": // These are cacheable. // Note that this list is documented above, diff --git a/src/cmd/go/testdata/script/test_cache_inputs.txt b/src/cmd/go/testdata/script/test_cache_inputs.txt index d694a30994..3705c700d1 100644 --- a/src/cmd/go/testdata/script/test_cache_inputs.txt +++ b/src/cmd/go/testdata/script/test_cache_inputs.txt @@ -108,6 +108,12 @@ go test testcache -run=Benchtime -bench=Benchtime -benchtime=1x go test testcache -run=Benchtime -bench=Benchtime -benchtime=1x ! stdout '\(cached\)' +# golang.org/issue/47355: that includes the `-failfast` argument. +go test testcache -run=TestOSArgs -failfast +! stdout '\(cached\)' +go test testcache -run=TestOSArgs -failfast +stdout '\(cached\)' + # Executables within GOROOT and GOPATH should affect caching, # even if the test does not stat them explicitly. -- GitLab From 3848488f0f9ea597e9fc69cfd8e942ea7cf35311 Mon Sep 17 00:00:00 2001 From: Colin Arnott Date: Sun, 18 Jul 2021 08:12:23 +0000 Subject: [PATCH 0748/2500] cmd/go/internal/test: add an all sentinel to -vet The vet flag either accepts a list of vets to run, or a distinguished value, off, to disable vet during test. By default only 100% reliable checks are run, thus there is no way to run all vets. This change adds another distinguished value, all, that runs every vet, by passing no flags. During development it was discovered that parsing of the -vet flag value is problematic, in that it accepts deprecated flags like -all. The root cause is detailed in #47309, but for now passing distinguished values (all, off) and anything else returns an error. Fixes #45963 Change-Id: I39fafb7d717dad51b507d560b3f6e604510a2881 Reviewed-on: https://go-review.googlesource.com/c/go/+/334873 Trust: Than McIntosh Trust: Jay Conrod Reviewed-by: Jay Conrod --- src/cmd/go/alldocs.go | 3 +- src/cmd/go/internal/test/test.go | 3 +- src/cmd/go/internal/test/testflag.go | 60 +++++++++++++++---------- src/cmd/go/testdata/script/test_vet.txt | 23 +++++++++- 4 files changed, 63 insertions(+), 26 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index ddf7bb5318..592ea4932e 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -1405,7 +1405,8 @@ // used. That subset is: 'atomic', 'bool', 'buildtags', 'errorsas', // 'ifaceassert', 'nilfunc', 'printf', and 'stringintconv'. You can see // the documentation for these and other vet tests via "go doc cmd/vet". -// To disable the running of go vet, use the -vet=off flag. +// To disable the running of go vet, use the -vet=off flag. To run all +// checks, use the -vet=all flag. // // All test output and summary lines are printed to the go command's // standard output, even if the test printed them to its own standard diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index e8bf0e198e..efebc12363 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -78,7 +78,8 @@ binary. Only a high-confidence subset of the default go vet checks are used. That subset is: 'atomic', 'bool', 'buildtags', 'errorsas', 'ifaceassert', 'nilfunc', 'printf', and 'stringintconv'. You can see the documentation for these and other vet tests via "go doc cmd/vet". -To disable the running of go vet, use the -vet=off flag. +To disable the running of go vet, use the -vet=off flag. To run all +checks, use the -vet=all flag. All test output and summary lines are printed to the go command's standard output, even if the test printed them to its own standard diff --git a/src/cmd/go/internal/test/testflag.go b/src/cmd/go/internal/test/testflag.go index 08f1efa2c0..45118cb638 100644 --- a/src/cmd/go/internal/test/testflag.go +++ b/src/cmd/go/internal/test/testflag.go @@ -5,6 +5,10 @@ package test import ( + "cmd/go/internal/base" + "cmd/go/internal/cfg" + "cmd/go/internal/cmdflag" + "cmd/go/internal/work" "errors" "flag" "fmt" @@ -13,11 +17,6 @@ import ( "strconv" "strings" "time" - - "cmd/go/internal/base" - "cmd/go/internal/cfg" - "cmd/go/internal/cmdflag" - "cmd/go/internal/work" ) //go:generate go run ./genflags.go @@ -134,6 +133,7 @@ type outputdirFlag struct { func (f *outputdirFlag) String() string { return f.abs } + func (f *outputdirFlag) Set(value string) (err error) { if value == "" { f.abs = "" @@ -142,6 +142,7 @@ func (f *outputdirFlag) Set(value string) (err error) { } return err } + func (f *outputdirFlag) getAbs() string { if f.abs == "" { return base.Cwd() @@ -150,8 +151,12 @@ func (f *outputdirFlag) getAbs() string { } // vetFlag implements the special parsing logic for the -vet flag: -// a comma-separated list, with a distinguished value "off" and -// a boolean tracking whether it was set explicitly. +// a comma-separated list, with distinguished values "all" and +// "off", plus a boolean tracking whether it was set explicitly. +// +// "all" is encoded as vetFlag{true, false, nil}, since it will +// pass no flags to the vet binary, and by default, it runs all +// analyzers. type vetFlag struct { explicit bool off bool @@ -159,7 +164,10 @@ type vetFlag struct { } func (f *vetFlag) String() string { - if f.off { + switch { + case !f.off && !f.explicit && len(f.flags) == 0: + return "all" + case f.off: return "off" } @@ -174,32 +182,38 @@ func (f *vetFlag) String() string { } func (f *vetFlag) Set(value string) error { - if value == "" { + switch { + case value == "": *f = vetFlag{flags: defaultVetFlags} return nil - } - - if value == "off" { - *f = vetFlag{ - explicit: true, - off: true, - } - return nil - } - - if strings.Contains(value, "=") { + case strings.Contains(value, "="): return fmt.Errorf("-vet argument cannot contain equal signs") - } - if strings.Contains(value, " ") { + case strings.Contains(value, " "): return fmt.Errorf("-vet argument is comma-separated list, cannot contain spaces") } *f = vetFlag{explicit: true} + var single string for _, arg := range strings.Split(value, ",") { - if arg == "" { + switch arg { + case "": return fmt.Errorf("-vet argument contains empty list element") + case "all": + single = arg + *f = vetFlag{explicit: true} + continue + case "off": + single = arg + *f = vetFlag{ + explicit: true, + off: true, + } + continue } f.flags = append(f.flags, "-"+arg) } + if len(f.flags) > 1 && single != "" { + return fmt.Errorf("-vet does not accept %q in a list with other analyzers", single) + } return nil } diff --git a/src/cmd/go/testdata/script/test_vet.txt b/src/cmd/go/testdata/script/test_vet.txt index 5af26b54f9..239a477a18 100644 --- a/src/cmd/go/testdata/script/test_vet.txt +++ b/src/cmd/go/testdata/script/test_vet.txt @@ -16,6 +16,11 @@ go test -vet=off p1.go ! stderr '[\\/]vet.*-shift' stdout '\[no test files\]' +# ensure all runs non-default vet +! go test -vet=all ./vetall/... +stderr 'using resp before checking for errors' + + # Test issue #22890 go test m/vetcycle stdout 'm/vetcycle.*\[no test files\]' @@ -46,11 +51,27 @@ func Test(t *testing.T) { -- p1.go -- package p -import "fmt" +import ( + "fmt" + "net/http" +) func F() { fmt.Printf("%d") // oops } +-- vetall/p.go -- +package p + +func F() { + resp, err := http.Head("example.com") + defer resp.Body.Close() + if err != nil { + panic(err) + } + // (defer statement belongs here) +} +-- vetall/p_test.go -- +package p -- vetcycle/p.go -- package p -- GitLab From a2a9a7b5132c7a0b1d4c297018d6072101456709 Mon Sep 17 00:00:00 2001 From: Paschalis Tsilias Date: Tue, 2 Feb 2021 15:25:21 +0200 Subject: [PATCH 0749/2500] cmd/go: make mod init disallow invalid major version suffixes This CL reuses the SplitPathVersion function from the module package to detect invalid major version suffixes and return a relevant error message along with a suggested fix. Fixes #44052 Fixes #46085 Change-Id: I6c06f31a134e864a1d9b6e00c048ca1c59b4365e Reviewed-on: https://go-review.googlesource.com/c/go/+/288712 Reviewed-by: Jay Conrod Trust: Jay Conrod Trust: Bryan C. Mills Run-TryBot: Jay Conrod TryBot-Result: Go Bot --- src/cmd/go/internal/modload/init.go | 60 ++++++++++++++ .../script/mod_init_invalid_major.txt | 82 +++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 src/cmd/go/testdata/script/mod_init_invalid_major.txt diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index d5f9d10422..862b007739 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -523,6 +523,13 @@ func CreateModFile(ctx context.Context, modPath string) { } } base.Fatalf("go: %v", err) + } else if _, _, ok := module.SplitPathVersion(modPath); !ok { + if strings.HasPrefix(modPath, "gopkg.in/") { + invalidMajorVersionMsg := fmt.Errorf("module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN:\n\tgo mod init %s", suggestGopkgIn(modPath)) + base.Fatalf(`go: invalid module path "%v": %v`, modPath, invalidMajorVersionMsg) + } + invalidMajorVersionMsg := fmt.Errorf("major version suffixes must be in the form of /vN and are only allowed for v2 or later:\n\tgo mod init %s", suggestModulePath(modPath)) + base.Fatalf(`go: invalid module path "%v": %v`, modPath, invalidMajorVersionMsg) } fmt.Fprintf(os.Stderr, "go: creating new go.mod: module %s\n", modPath) @@ -1197,3 +1204,56 @@ const ( func modkey(m module.Version) module.Version { return module.Version{Path: m.Path, Version: m.Version + "/go.mod"} } + +func suggestModulePath(path string) string { + var m string + + i := len(path) + for i > 0 && ('0' <= path[i-1] && path[i-1] <= '9' || path[i-1] == '.') { + i-- + } + url := path[:i] + url = strings.TrimSuffix(url, "/v") + url = strings.TrimSuffix(url, "/") + + f := func(c rune) bool { + return c > '9' || c < '0' + } + s := strings.FieldsFunc(path[i:], f) + if len(s) > 0 { + m = s[0] + } + m = strings.TrimLeft(m, "0") + if m == "" || m == "1" { + return url + "/v2" + } + + return url + "/v" + m +} + +func suggestGopkgIn(path string) string { + var m string + i := len(path) + for i > 0 && (('0' <= path[i-1] && path[i-1] <= '9') || (path[i-1] == '.')) { + i-- + } + url := path[:i] + url = strings.TrimSuffix(url, ".v") + url = strings.TrimSuffix(url, "/v") + url = strings.TrimSuffix(url, "/") + + f := func(c rune) bool { + return c > '9' || c < '0' + } + s := strings.FieldsFunc(path, f) + if len(s) > 0 { + m = s[0] + } + + m = strings.TrimLeft(m, "0") + + if m == "" { + return url + ".v1" + } + return url + ".v" + m +} diff --git a/src/cmd/go/testdata/script/mod_init_invalid_major.txt b/src/cmd/go/testdata/script/mod_init_invalid_major.txt new file mode 100644 index 0000000000..ae93e70d63 --- /dev/null +++ b/src/cmd/go/testdata/script/mod_init_invalid_major.txt @@ -0,0 +1,82 @@ +env GO111MODULE=on +env GOFLAGS=-mod=mod + +! go mod init example.com/user/repo/v0 +stderr '(?s)^go: invalid module path "example.com/user/repo/v0": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v2$' + +! go mod init example.com/user/repo/v02 +stderr '(?s)^go: invalid module path "example.com/user/repo/v02": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v2$' + +! go mod init example.com/user/repo/v023 +stderr '(?s)^go: invalid module path "example.com/user/repo/v023": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v23$' + +! go mod init example.com/user/repo/v1 +stderr '(?s)^go: invalid module path "example.com/user/repo/v1": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v2$' + +! go mod init example.com/user/repo/v2.0 +stderr '(?s)^go: invalid module path "example.com/user/repo/v2.0": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v2$' + +! go mod init example.com/user/repo/v2.1.4 +stderr '(?s)^go: invalid module path "example.com/user/repo/v2.1.4": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v2$' + +! go mod init example.com/user/repo/v3.5 +stderr '(?s)^go: invalid module path "example.com/user/repo/v3.5": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v3$' + +! go mod init example.com/user/repo/v4.1.4 +stderr '(?s)^go: invalid module path "example.com/user/repo/v4.1.4": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v4$' + +! go mod init example.com/user/repo/v.2.3 +stderr '(?s)^go: invalid module path "example.com/user/repo/v.2.3": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v2$' + +! go mod init example.com/user/repo/v.5.3 +stderr '(?s)^go: invalid module path "example.com/user/repo/v.5.3": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v5$' + +! go mod init gopkg.in/pkg +stderr '(?s)^go: invalid module path "gopkg.in/pkg": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/pkg.v1$' + +! go mod init gopkg.in/user/pkg +stderr '(?s)^go: invalid module path "gopkg.in/user/pkg": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v1$' + +! go mod init gopkg.in/user/pkg/v0 +stderr '(?s)^go: invalid module path "gopkg.in/user/pkg/v0": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v1$' + +! go mod init gopkg.in/user/pkg/v1 +stderr '(?s)^go: invalid module path "gopkg.in/user/pkg/v1": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v1$' + +! go mod init gopkg.in/user/pkg/v2 +stderr '(?s)^go: invalid module path "gopkg.in/user/pkg/v2": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v2$' + +! go mod init gopkg.in/user/pkg.v +stderr '(?s)^go: invalid module path "gopkg.in/user/pkg.v": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v1$' + +! go mod init gopkg.in/user/pkg.v0.1 +stderr '(?s)^go: invalid module path "gopkg.in/user/pkg.v0.1": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v1$' + +! go mod init gopkg.in/user/pkg.v.1 +stderr '(?s)^go: invalid module path "gopkg.in/user/pkg.v.1": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v1$' + +! go mod init gopkg.in/user/pkg.v01 +stderr '(?s)^go: invalid module path "gopkg.in/user/pkg.v01": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v1$' + +! go mod init gopkg.in/user/pkg.v.2.3 +stderr '(?s)^go: invalid module path "gopkg.in/user/pkg.v.2.3": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v2$' + +# module paths with a trailing dot are rejected as invalid import paths +! go mod init example.com/user/repo/v2. +stderr '(?s)^go: malformed module path "example.com/user/repo/v2.": trailing dot in path element$' + +! go mod init example.com/user/repo/v2.. +stderr '(?s)^go: malformed module path "example.com/user/repo/v2..": trailing dot in path element$' + +! go mod init gopkg.in/user/pkg.v.2. +stderr '(?s)^go: malformed module path "gopkg.in/user/pkg.v.2.": trailing dot in path element$' + +! go mod init gopkg.in/user/pkg.v.2.. +stderr '(?s)^go: malformed module path "gopkg.in/user/pkg.v.2..": trailing dot in path element$' + +# module paths with spaces are also rejected +! go mod init 'foo bar' +stderr '(?s)^go: malformed module path "foo bar": invalid char '' ''$' + +! go mod init 'foo bar baz' +stderr '(?s)^go: malformed module path "foo bar baz": invalid char '' ''$' -- GitLab From ddfcc02352feb9e15ff9aa423bb49bfb37d689a3 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 17 Aug 2021 17:21:03 -0400 Subject: [PATCH 0750/2500] cmd/link: do not use GO_LDSO when cross compile GO_LDSO is a setting that is set when the toolchain is build. It only makes sense to use it on the host platform. Do not use it when targetting a different platform. In the past it was not a problem as GO_LDSO was almost always unset. Now, with CL 301989 it is almost always set (maybe we want to revisit it). Fixes #47760. Change-Id: I2704b9968781f46e2d2f8624090db19689b1a32f Reviewed-on: https://go-review.googlesource.com/c/go/+/343010 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/cmd/link/internal/ld/elf.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go index ffc27d66b7..93f974c5e0 100644 --- a/src/cmd/link/internal/ld/elf.go +++ b/src/cmd/link/internal/ld/elf.go @@ -16,6 +16,7 @@ import ( "fmt" "internal/buildcfg" "path/filepath" + "runtime" "sort" "strings" ) @@ -1745,7 +1746,7 @@ func asmbElf(ctxt *Link) { sh.Flags = uint64(elf.SHF_ALLOC) sh.Addralign = 1 - if interpreter == "" && buildcfg.GO_LDSO != "" { + if interpreter == "" && buildcfg.GOOS == runtime.GOOS && buildcfg.GOARCH == runtime.GOARCH && buildcfg.GO_LDSO != "" { interpreter = buildcfg.GO_LDSO } -- GitLab From aef24d8f7db4fb895055e4543af958d7dc2eb8cc Mon Sep 17 00:00:00 2001 From: eric fang Date: Mon, 21 Jun 2021 03:04:42 +0000 Subject: [PATCH 0751/2500] cmd/internal/obj/arm64: fix the encoding error when operating with ZR Some arm64 instructions accept ZR as its destination register, such as MOVD, AND, ADD etc. although it doesn't seem to make much sense, but we should make sure the encoding is correct. However there exists some encoding mistakes in the current assembler, they are: 1, 'MOVD $1, ZR' is incorrectly encoded as 'MOVD $1, ZR' + '0x00000000'. 2, 'AND $1, R2, ZR' is incorrectly encoded as 'MOVD $1, R27' + 'AND R27, R2, ZR' + '0x00000000'. 3, 'AND $1, ZR' is incorrectly encoded as 'AND $1, ZR, RSP'. Obviously the first two encoding errors can cause SIGILL, and the third one will rewrite RSP. At the same time, I found some weird encodings but they don't cause errors. 4, 'MOVD $0x0001000100010001, ZR' is encoded as 'MOVW $1, ZR' + 'MOVKW $(1<<16), ZR'. 5, 'AND $0x0001000100010001, R2, ZR' is encoded as 'MOVD $1, R27' + 'MOVK $(1<<16), R27' + 'MOVK $(1<<32), R27'. Some of these issues also apply to 32-bit versions of these instructions. These problems are not very complicated, and are basically caused by the improper adaptation of the class of the constant to the entry in the optab. But the relationship between these constant classes is a bit complicated, so I don't know how to deal with issue 4 and 5, because they won't cause errors, so this CL didn't deal with them. This CL fixed the first three issues. Issue 1: before: 'MOVD $1, ZR' => 'MOVD $1, ZR' + '0x00000000'. after: 'MOVD $1, ZR' => 'MOVD $1, ZR'. Issue 2: before: 'AND $1, R2, ZR' => 'MOVD $1, R27' + 'AND R27, R2, ZR' + '0x00000000'. after: 'AND $1, R2, ZR' => 'ORR $1, ZR, R27' + 'AND R27, R2, ZR'. Issue 3: before: 'AND $1, ZR' => 'AND $1, ZR, RSP'. after: 'AND $1, ZR' => 'ORR $1, ZR, R27' + 'AND R27, ZR, ZR'. Change-Id: I3c889079229f847b863ad56c88966be12d947202 Reviewed-on: https://go-review.googlesource.com/c/go/+/329750 Reviewed-by: eric fang Reviewed-by: Cherry Mui Trust: eric fang Run-TryBot: eric fang TryBot-Result: Go Bot --- src/cmd/asm/internal/asm/testdata/arm64.s | 6 ++++-- .../asm/internal/asm/testdata/arm64error.s | 2 +- src/cmd/internal/obj/arm64/asm7.go | 21 ++++++++++++++----- src/cmd/internal/obj/arm64/obj7.go | 4 +++- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/arm64.s b/src/cmd/asm/internal/asm/testdata/arm64.s index d8a20edfc1..7b40ed24b4 100644 --- a/src/cmd/asm/internal/asm/testdata/arm64.s +++ b/src/cmd/asm/internal/asm/testdata/arm64.s @@ -334,6 +334,8 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8 EONW $0x6006000060060, R5 // EONW $1689262177517664, R5 // 1b0c8052db00a072a5003b4a ORNW $0x6006000060060, R5 // ORNW $1689262177517664, R5 // 1b0c8052db00a072a5003b2a BICSW $0x6006000060060, R5 // BICSW $1689262177517664, R5 // 1b0c8052db00a072a5003b6a + AND $1, ZR // fb0340b2ff031b8a + ANDW $1, ZR // fb030032ff031b0a // TODO: this could have better encoding ANDW $-1, R10 // 1b0080124a011b0a AND $8, R0, RSP // 1f007d92 @@ -369,9 +371,9 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8 MOVD $-1, R1 // 01008092 MOVD $0x210000, R0 // MOVD $2162688, R0 // 2004a0d2 MOVD $0xffffffffffffaaaa, R1 // MOVD $-21846, R1 // a1aa8a92 - MOVW $1, ZR + MOVW $1, ZR // 3f008052 MOVW $1, R1 - MOVD $1, ZR + MOVD $1, ZR // 3f0080d2 MOVD $1, R1 MOVK $1, R1 MOVD $0x1000100010001000, RSP // MOVD $1152939097061330944, RSP // ff8304b2 diff --git a/src/cmd/asm/internal/asm/testdata/arm64error.s b/src/cmd/asm/internal/asm/testdata/arm64error.s index cf57179e43..145074347f 100644 --- a/src/cmd/asm/internal/asm/testdata/arm64error.s +++ b/src/cmd/asm/internal/asm/testdata/arm64error.s @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. TEXT errors(SB),$0 - AND $1, RSP // ERROR "illegal combination" + AND $1, RSP // ERROR "illegal source register" ANDS $1, R0, RSP // ERROR "illegal combination" ADDSW R7->32, R14, R13 // ERROR "shift amount out of range 0 to 31" ADD R1.UXTB<<5, R2, R3 // ERROR "shift amount out of range 0 to 4" diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go index d99afa3d27..02687ab162 100644 --- a/src/cmd/internal/obj/arm64/asm7.go +++ b/src/cmd/internal/obj/arm64/asm7.go @@ -361,12 +361,12 @@ var optab = []Optab{ {AANDS, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0}, {ATST, C_REG, C_REG, C_NONE, C_NONE, 1, 4, 0, 0, 0}, {AAND, C_MBCON, C_REG, C_NONE, C_RSP, 53, 4, 0, 0, 0}, - {AAND, C_MBCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0}, + {AAND, C_MBCON, C_NONE, C_NONE, C_RSP, 53, 4, 0, 0, 0}, {AANDS, C_MBCON, C_REG, C_NONE, C_REG, 53, 4, 0, 0, 0}, {AANDS, C_MBCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0}, {ATST, C_MBCON, C_REG, C_NONE, C_NONE, 53, 4, 0, 0, 0}, {AAND, C_BITCON, C_REG, C_NONE, C_RSP, 53, 4, 0, 0, 0}, - {AAND, C_BITCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0}, + {AAND, C_BITCON, C_NONE, C_NONE, C_RSP, 53, 4, 0, 0, 0}, {AANDS, C_BITCON, C_REG, C_NONE, C_REG, 53, 4, 0, 0, 0}, {AANDS, C_BITCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0}, {ATST, C_BITCON, C_REG, C_NONE, C_NONE, 53, 4, 0, 0, 0}, @@ -404,6 +404,8 @@ var optab = []Optab{ /* TODO: MVN C_SHIFT */ /* MOVs that become MOVK/MOVN/MOVZ/ADD/SUB/OR */ + {AMOVW, C_MBCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0}, + {AMOVD, C_MBCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0}, {AMOVW, C_MOVCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0}, {AMOVD, C_MOVCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0}, {AMOVW, C_BITCON, C_NONE, C_NONE, C_RSP, 32, 4, 0, 0, 0}, @@ -2089,13 +2091,18 @@ func cmp(a int, b int) bool { return true } + case C_MBCON: + if b == C_ABCON0 { + return true + } + case C_BITCON: if b == C_ABCON0 || b == C_ABCON || b == C_MBCON { return true } case C_MOVCON: - if b == C_MBCON || b == C_ZCON || b == C_ADDCON0 || b == C_AMCON { + if b == C_MBCON || b == C_ZCON || b == C_ADDCON0 || b == C_ABCON0 || b == C_AMCON { return true } @@ -4198,6 +4205,10 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { if r == 0 { r = rt } + if r == REG_RSP { + c.ctxt.Diag("illegal source register: %v", p) + break + } mode := 64 v := uint64(p.From.Offset) switch p.As { @@ -7039,8 +7050,8 @@ func (c *ctxt7) omovlit(as obj.As, p *obj.Prog, a *obj.Addr, dr int) uint32 { // load a constant (MOVCON or BITCON) in a into rt func (c *ctxt7) omovconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int) (o1 uint32) { - if cls := oclass(a); cls == C_BITCON || cls == C_ABCON || cls == C_ABCON0 { - // or $bitcon, REGZERO, rt + if cls := oclass(a); (cls == C_BITCON || cls == C_ABCON || cls == C_ABCON0) && rt != REGZERO { + // or $bitcon, REGZERO, rt. rt can't be ZR. mode := 64 var as1 obj.As switch as { diff --git a/src/cmd/internal/obj/arm64/obj7.go b/src/cmd/internal/obj/arm64/obj7.go index 31b7c43245..a043d0972c 100644 --- a/src/cmd/internal/obj/arm64/obj7.go +++ b/src/cmd/internal/obj/arm64/obj7.go @@ -305,7 +305,9 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { // for both 32-bit and 64-bit. 32-bit ops will // zero the high 32-bit of the destination register // anyway. - if (isANDWop(p.As) || isADDWop(p.As) || p.As == AMOVW) && p.From.Type == obj.TYPE_CONST { + // For MOVW, the destination register can't be ZR, + // so don't bother rewriting it in this situation. + if (isANDWop(p.As) || isADDWop(p.As) || p.As == AMOVW && p.To.Reg != REGZERO) && p.From.Type == obj.TYPE_CONST { v := p.From.Offset & 0xffffffff p.From.Offset = v | v<<32 } -- GitLab From 8e18428e389c04f38c3b7e8f152d7f14077b7850 Mon Sep 17 00:00:00 2001 From: eric fang Date: Mon, 21 Jun 2021 08:17:35 +0000 Subject: [PATCH 0752/2500] cmd/internal/obj/arm64: don't use REGTMP when moving C_AACON2 to a register MOVD $C_AACON2(Rf), Rt is encoded as ADD $C_AACON2_high_12_bits, Rf, REGTMP + ADD $C_AACON2_low_12_bits, REGTMP, Rt. Actually REGTMP is not necessary here, we can use Rt directly, so it becomes ADD $C_AACON2_high_12_bits, Rf, Rt + ADD $C_AACON2_low_12_bits, Rt, Rt. Change-Id: I90b7718b5fb0ab9f3ea28511f42946a6bdccfef3 Reviewed-on: https://go-review.googlesource.com/c/go/+/329751 Reviewed-by: eric fang Reviewed-by: Cherry Mui Trust: eric fang Run-TryBot: eric fang --- src/cmd/asm/internal/asm/testdata/arm64.s | 8 ++++---- src/cmd/internal/obj/arm64/asm7.go | 8 +++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/arm64.s b/src/cmd/asm/internal/asm/testdata/arm64.s index 7b40ed24b4..a4b56b0696 100644 --- a/src/cmd/asm/internal/asm/testdata/arm64.s +++ b/src/cmd/asm/internal/asm/testdata/arm64.s @@ -388,10 +388,10 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8 VMOVQ $0x8040201008040202, $0x7040201008040201, V20 // VMOVQ $-9205322385119247870, $8088500183983456769, V20 // mov(to/from sp) - MOVD $0x1002(RSP), R1 // MOVD $4098(RSP), R1 // fb074091610b0091 - MOVD $0x1708(RSP), RSP // MOVD $5896(RSP), RSP // fb0740917f231c91 - MOVD $0x2001(R7), R1 // MOVD $8193(R7), R1 // fb08409161070091 - MOVD $0xffffff(R7), R1 // MOVD $16777215(R7), R1 // fbfc7f9161ff3f91 + MOVD $0x1002(RSP), R1 // MOVD $4098(RSP), R1 // e107409121080091 + MOVD $0x1708(RSP), RSP // MOVD $5896(RSP), RSP // ff074091ff231c91 + MOVD $0x2001(R7), R1 // MOVD $8193(R7), R1 // e108409121040091 + MOVD $0xffffff(R7), R1 // MOVD $16777215(R7), R1 // e1fc7f9121fc3f91 MOVD $-0x1(R7), R1 // MOVD $-1(R7), R1 // e10400d1 MOVD $-0x30(R7), R1 // MOVD $-48(R7), R1 // e1c000d1 MOVD $-0x708(R7), R1 // MOVD $-1800(R7), R1 // e1201cd1 diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go index 02687ab162..050add9aac 100644 --- a/src/cmd/internal/obj/arm64/asm7.go +++ b/src/cmd/internal/obj/arm64/asm7.go @@ -417,7 +417,7 @@ var optab = []Optab{ {AMOVK, C_VCON, C_NONE, C_NONE, C_REG, 33, 4, 0, 0, 0}, {AMOVD, C_AACON, C_NONE, C_NONE, C_RSP, 4, 4, REGFROM, 0, 0}, - {AMOVD, C_AACON2, C_NONE, C_NONE, C_RSP, 4, 8, REGFROM, 0, 0}, + {AMOVD, C_AACON2, C_NONE, C_NONE, C_RSP, 4, 8, REGFROM, NOTUSETMP, 0}, /* load long effective stack address (load int32 offset and add) */ {AMOVD, C_LACON, C_NONE, C_NONE, C_RSP, 34, 8, REGSP, LFROM, 0}, @@ -3306,8 +3306,10 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { } if int(o.size) == 8 { - o1 = c.oaddi(p, op, v&0xfff000, r, REGTMP) - o2 = c.oaddi(p, op, v&0x000fff, REGTMP, rt) + // NOTE: this case does not use REGTMP. If it ever does, + // remove the NOTUSETMP flag in optab. + o1 = c.oaddi(p, op, v&0xfff000, r, rt) + o2 = c.oaddi(p, op, v&0x000fff, rt, rt) break } -- GitLab From 946e2543f878929752da9d16575dd5e96ac78532 Mon Sep 17 00:00:00 2001 From: Meng Zhuo Date: Tue, 6 Jul 2021 07:17:07 +0000 Subject: [PATCH 0753/2500] runtime: use RDCYCLE for cputicks on riscv64 Use RDCYCLE instruction instead of RDTIME emulation Change-Id: Id7b3de42a36d2d1b163c39cc79870eee7c840ad5 Reviewed-on: https://go-review.googlesource.com/c/go/+/332954 Trust: Meng Zhuo Reviewed-by: Cherry Mui --- src/runtime/asm_riscv64.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/asm_riscv64.s b/src/runtime/asm_riscv64.s index d7ab90d1ab..531b46927c 100644 --- a/src/runtime/asm_riscv64.s +++ b/src/runtime/asm_riscv64.s @@ -81,7 +81,7 @@ TEXT setg_gcc<>(SB),NOSPLIT,$0-0 // func cputicks() int64 TEXT runtime·cputicks(SB),NOSPLIT,$0-8 - RDTIME A0 + RDCYCLE A0 MOV A0, ret+0(FP) RET -- GitLab From 8b471db71b95e9250f751f494a6a5359cb50d5cd Mon Sep 17 00:00:00 2001 From: Yasuhiro Matsumoto Date: Thu, 15 Jul 2021 23:53:47 +0900 Subject: [PATCH 0754/2500] path/filepath: change IsAbs to treat \\host\share as an absolute path Fixes #47123 Change-Id: I2226b8a9ea24cd88171acfbaffea2566309416de Reviewed-on: https://go-review.googlesource.com/c/go/+/334809 Trust: Alex Brainman Trust: Hajime Hoshi Reviewed-by: Alex Brainman --- src/path/filepath/path_test.go | 2 ++ src/path/filepath/path_windows.go | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/path/filepath/path_test.go b/src/path/filepath/path_test.go index bc5509b49c..55b27f1af8 100644 --- a/src/path/filepath/path_test.go +++ b/src/path/filepath/path_test.go @@ -791,6 +791,8 @@ var winisabstests = []IsAbsTest{ {`c:a\b`, false}, {`c:\a\b`, true}, {`c:/a/b`, true}, + {`\\host\share`, true}, + {`\\host\share\`, true}, {`\\host\share\foo`, true}, {`//host/share/foo/bar`, true}, } diff --git a/src/path/filepath/path_windows.go b/src/path/filepath/path_windows.go index 445c868e41..b4d8ac3301 100644 --- a/src/path/filepath/path_windows.go +++ b/src/path/filepath/path_windows.go @@ -45,6 +45,10 @@ func IsAbs(path string) (b bool) { if l == 0 { return false } + // If the volume name starts with a double slash, this is a UNC path. + if isSlash(path[0]) && isSlash(path[1]) { + return true + } path = path[l:] if path == "" { return false -- GitLab From 0c83e01e0c1df712002af8bded845fbca9677ffa Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 18 Aug 2021 09:03:44 +0200 Subject: [PATCH 0755/2500] cmd/go/testdata/script: fix test script added by CL 334873 CL 334873 added the net/http import to the wrong section in test_vet.txt. Correct this to fix the longtest builders. Change-Id: If28409ad1c2ed3bd3a2922fc20d5e534c30fa249 Reviewed-on: https://go-review.googlesource.com/c/go/+/343169 Trust: Tobias Klauser Trust: Jay Conrod Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/testdata/script/test_vet.txt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/cmd/go/testdata/script/test_vet.txt b/src/cmd/go/testdata/script/test_vet.txt index 239a477a18..2e0ae1956a 100644 --- a/src/cmd/go/testdata/script/test_vet.txt +++ b/src/cmd/go/testdata/script/test_vet.txt @@ -51,10 +51,7 @@ func Test(t *testing.T) { -- p1.go -- package p -import ( - "fmt" - "net/http" -) +import "fmt" func F() { fmt.Printf("%d") // oops @@ -62,6 +59,8 @@ func F() { -- vetall/p.go -- package p +import "net/http" + func F() { resp, err := http.Head("example.com") defer resp.Body.Close() -- GitLab From 4a0fd73eaded9f395b3e5025ab9e1c5c5f124143 Mon Sep 17 00:00:00 2001 From: Yuki Osaki Date: Wed, 18 Aug 2021 05:05:55 +0000 Subject: [PATCH 0756/2500] cmd/go/internal/work/exec: throw an error when buildP is negative MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed a problem where an error would not occur when a negative value was specified for the p flag. `go build -p=0` now should throw an error. this is my first pr to this project. If there's anything I'm missing, please let me know 🙏 Fixes #46686 Change-Id: I3b19773ef095fad0e0419100d317727c2268699a GitHub-Last-Rev: e5c57804d9995f5c858aa42d9de21b25de246eb5 GitHub-Pull-Request: golang/go#47360 Reviewed-on: https://go-review.googlesource.com/c/go/+/336751 Reviewed-by: Jay Conrod Trust: Jay Conrod Trust: Bryan C. Mills Run-TryBot: Jay Conrod TryBot-Result: Go Bot --- src/cmd/go/internal/work/init.go | 4 ++++ src/cmd/go/testdata/script/build_negative_p.txt | 5 +++++ 2 files changed, 9 insertions(+) create mode 100644 src/cmd/go/testdata/script/build_negative_p.txt diff --git a/src/cmd/go/internal/work/init.go b/src/cmd/go/internal/work/init.go index 022137390f..7acee3dd55 100644 --- a/src/cmd/go/internal/work/init.go +++ b/src/cmd/go/internal/work/init.go @@ -40,6 +40,10 @@ func BuildInit() { cfg.BuildPkgdir = p } + if cfg.BuildP <= 0 { + base.Fatalf("go: -p must be a positive integer: %v\n", cfg.BuildP) + } + // Make sure CC, CXX, and FC are absolute paths. for _, key := range []string{"CC", "CXX", "FC"} { value := cfg.Getenv(key) diff --git a/src/cmd/go/testdata/script/build_negative_p.txt b/src/cmd/go/testdata/script/build_negative_p.txt new file mode 100644 index 0000000000..9123907dc8 --- /dev/null +++ b/src/cmd/go/testdata/script/build_negative_p.txt @@ -0,0 +1,5 @@ +! go build -p=-1 example.go +stderr 'go: -p must be a positive integer: -1' + +-- example.go -- +package example \ No newline at end of file -- GitLab From 165ebd85a77db5f3454f38c6c3f1539f00cf2fef Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Fri, 13 Aug 2021 12:03:29 -0400 Subject: [PATCH 0757/2500] cmd/compile/internal/types2: clean up panics in instantiation Clean up a few issues related to panicking during invalid instantiation. - Panic early in instantiateLazy when check == nil and verify == true. Otherwise, we would panic at check.later. - Always panic when check == nil and verify == true, even if targs is of incorrect length. This is more consistent behavior. - Lift the check for len(posList) <= len(targs) out of Checker.instantiate. This is the only reason why posList is passed to that function, and doing this allows us to eliminate posList from instance. At this point instance is close to being unnecessary, so update a TODO to this effect. Change-Id: Id5f44cbb1a5897aef10ce2a573aa78acd7ae4026 Reviewed-on: https://go-review.googlesource.com/c/go/+/341862 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- .../compile/internal/types2/instantiate.go | 40 +++++++++++-------- src/cmd/compile/internal/types2/named.go | 9 ++--- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index fff2635456..d2383db35c 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -54,15 +54,18 @@ func (check *Checker) Instantiate(pos syntax.Pos, typ Type, targs []Type, posLis // only types and functions can be generic panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } + inst := check.instantiate(pos, typ, tparams, targs, nil) - inst := check.instantiate(pos, typ, tparams, targs, posList, nil) - if verify && len(tparams) == len(targs) { - check.verify(pos, tparams, targs, posList) + if verify { + assert(len(posList) <= len(targs)) + if len(tparams) == len(targs) { + check.verify(pos, tparams, targs, posList) + } } return inst } -func (check *Checker) instantiate(pos syntax.Pos, typ Type, tparams []*TypeName, targs []Type, posList []syntax.Pos, typMap map[string]*Named) (res Type) { +func (check *Checker) instantiate(pos syntax.Pos, typ Type, tparams []*TypeName, targs []Type, typMap map[string]*Named) (res Type) { // the number of supplied types must match the number of type parameters if len(targs) != len(tparams) { // TODO(gri) provide better error message @@ -89,8 +92,6 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, tparams []*TypeName, }() } - assert(len(posList) <= len(targs)) - if len(tparams) == 0 { return typ // nothing to do (minor optimization) } @@ -100,15 +101,21 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, tparams []*TypeName, // instantiateLazy avoids actually instantiating the type until needed. typ // must be a *Named type. -func (check *Checker) instantiateLazy(pos syntax.Pos, base *Named, targs []Type, posList []syntax.Pos, verify bool) Type { - if verify && base.TParams().Len() == len(targs) { - // TODO: lift the nil check in verify to here. - check.later(func() { - check.verify(pos, base.tparams.list(), targs, posList) - }) +func (check *Checker) instantiateLazy(pos syntax.Pos, orig *Named, targs []Type, posList []syntax.Pos, verify bool) Type { + if verify { + if check == nil { + // Provide a more useful panic instead of panicking at check.later below. + panic("cannot have nil Checker if verifying constraints") + } + assert(len(posList) <= len(targs)) + if orig.TParams().Len() == len(targs) { + check.later(func() { + check.verify(pos, orig.tparams.list(), targs, posList) + }) + } } - h := instantiatedHash(base, targs) + h := instantiatedHash(orig, targs) if check != nil { // typ may already have been instantiated with identical type arguments. In // that case, re-use the existing instance. @@ -117,10 +124,10 @@ func (check *Checker) instantiateLazy(pos syntax.Pos, base *Named, targs []Type, } } - tname := NewTypeName(pos, base.obj.pkg, base.obj.name, nil) - named := check.newNamed(tname, base, nil, nil, nil) // methods and tparams are set when named is loaded + tname := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil) + named := check.newNamed(tname, orig, nil, nil, nil) // methods and tparams are set when named is loaded named.targs = targs - named.instance = &instance{pos, posList} + named.instance = &instance{pos} if check != nil { check.typMap[h] = named } @@ -132,7 +139,6 @@ func (check *Checker) verify(pos syntax.Pos, tparams []*TypeName, targs []Type, if check == nil { panic("cannot have nil Checker if verifying constraints") } - smap := makeSubstMap(tparams, targs) for i, tname := range tparams { // best position for error reporting diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index 3ce9c5b0c7..97239414f6 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -244,11 +244,10 @@ func (n *Named) setUnderlying(typ Type) { // instance holds position information for use in lazy instantiation. // -// TODO(rfindley): come up with a better name for this type, now that its usage -// has changed. +// TODO(rfindley): instance is probably unnecessary now. See if it can be +// eliminated. type instance struct { - pos syntax.Pos // position of type instantiation; for error reporting only - posList []syntax.Pos // position of each targ; for error reporting only + pos syntax.Pos // position of type instantiation; for error reporting only } // expand ensures that the underlying type of n is instantiated. @@ -272,7 +271,7 @@ func (n *Named) expand(typMap map[string]*Named) *Named { } } - inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams().list(), n.targs, n.instance.posList, typMap) + inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams().list(), n.targs, typMap) n.underlying = inst n.fromRHS = inst n.instance = nil -- GitLab From 8f0578ef39a97c3a20032db799b97763e44274b0 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Fri, 13 Aug 2021 13:52:55 -0400 Subject: [PATCH 0758/2500] cmd/compile/internal/types2: consolidate verification logic Change an internal call of instantiateLazy to call Instantiate, so that we can consolidate the logic for invoking verification. This made verification of signatures lazy, which is not necessary but should be harmless. Change-Id: I2e59b04ac859e08c2e2910ded3c183093d1e34a7 Reviewed-on: https://go-review.googlesource.com/c/go/+/342149 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- .../compile/internal/types2/instantiate.go | 49 ++++++++++--------- src/cmd/compile/internal/types2/typexpr.go | 2 +- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index d2383db35c..ef92574a5c 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -26,12 +26,12 @@ import ( // instantiated. func (check *Checker) Instantiate(pos syntax.Pos, typ Type, targs []Type, posList []syntax.Pos, verify bool) (res Type) { // TODO(gri) What is better here: work with TypeParams, or work with TypeNames? - var tparams []*TypeName + var inst Type switch t := typ.(type) { case *Named: - return check.instantiateLazy(pos, t, targs, posList, verify) + inst = check.instantiateLazy(pos, t, targs) case *Signature: - tparams = t.TParams().list() + tparams := t.TParams().list() defer func() { // If we had an unexpected failure somewhere don't panic below when // asserting res.(*Signature). Check for *Signature in case Typ[Invalid] @@ -50,18 +50,35 @@ func (check *Checker) Instantiate(pos syntax.Pos, typ Type, targs []Type, posLis // anymore; we need to set tparams to nil. res.(*Signature).tparams = nil }() + inst = check.instantiate(pos, typ, tparams, targs, nil) default: // only types and functions can be generic panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } - inst := check.instantiate(pos, typ, tparams, targs, nil) if verify { - assert(len(posList) <= len(targs)) - if len(tparams) == len(targs) { - check.verify(pos, tparams, targs, posList) + if check == nil { + panic("cannot have nil Checker if verifying constraints") } + assert(len(posList) <= len(targs)) + check.later(func() { + // Collect tparams again because lazily loaded *Named types may not have + // had tparams set up above. + var tparams []*TypeName + switch t := typ.(type) { + case *Named: + tparams = t.TParams().list() + case *Signature: + tparams = t.TParams().list() + } + // Avoid duplicate errors; instantiate will have complained if tparams + // and targs do not have the same length. + if len(tparams) == len(targs) { + check.verify(pos, tparams, targs, posList) + } + }) } + return inst } @@ -101,20 +118,7 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, tparams []*TypeName, // instantiateLazy avoids actually instantiating the type until needed. typ // must be a *Named type. -func (check *Checker) instantiateLazy(pos syntax.Pos, orig *Named, targs []Type, posList []syntax.Pos, verify bool) Type { - if verify { - if check == nil { - // Provide a more useful panic instead of panicking at check.later below. - panic("cannot have nil Checker if verifying constraints") - } - assert(len(posList) <= len(targs)) - if orig.TParams().Len() == len(targs) { - check.later(func() { - check.verify(pos, orig.tparams.list(), targs, posList) - }) - } - } - +func (check *Checker) instantiateLazy(pos syntax.Pos, orig *Named, targs []Type) Type { h := instantiatedHash(orig, targs) if check != nil { // typ may already have been instantiated with identical type arguments. In @@ -136,9 +140,6 @@ func (check *Checker) instantiateLazy(pos syntax.Pos, orig *Named, targs []Type, } func (check *Checker) verify(pos syntax.Pos, tparams []*TypeName, targs []Type, posList []syntax.Pos) { - if check == nil { - panic("cannot have nil Checker if verifying constraints") - } smap := makeSubstMap(tparams, targs) for i, tname := range tparams { // best position for error reporting diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index a53319c153..4df8ab68a1 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -444,7 +444,7 @@ func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def posList[i] = syntax.StartPos(arg) } - typ := check.instantiateLazy(x.Pos(), base, targs, posList, true) + typ := check.Instantiate(x.Pos(), base, targs, posList, true) def.setUnderlying(typ) // make sure we check instantiation works at least once -- GitLab From c2bd9ee2dbec88d4fd1b21aefa21cd988d01b880 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 18 Aug 2021 13:10:04 -0700 Subject: [PATCH 0759/2500] cmd/compile: only sort methods/interfaces during export for -d=unifiedquirks These sorts are only important for 'toolstash -cmp' testing of unified IR against -G=0 mode, but they were added before I added -d=unifiedquirks to allow altering small "don't care" output details like this. This CL should help mitigate issues with #44195 until package objectpath is updated and deployed. Change-Id: Ia3dcf359481ff7abad5ddfca8e673fd2bb30ae01 Reviewed-on: https://go-review.googlesource.com/c/go/+/343390 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/typecheck/iexport.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 75b4931c31..75d6115783 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -578,7 +578,9 @@ func (p *iexporter) doDecl(n *ir.Name) { // Sort methods, for consistency with types2. methods := append([]*types.Field(nil), t.Methods().Slice()...) - sort.Sort(types.MethodsByName(methods)) + if base.Debug.UnifiedQuirks != 0 { + sort.Sort(types.MethodsByName(methods)) + } w.uint64(uint64(len(methods))) for _, m := range methods { @@ -978,8 +980,10 @@ func (w *exportWriter) doTyp(t *types.Type) { // Sort methods and embedded types, for consistency with types2. // Note: embedded types may be anonymous, and types2 sorts them // with sort.Stable too. - sort.Sort(types.MethodsByName(methods)) - sort.Stable(types.EmbeddedsByName(embeddeds)) + if base.Debug.UnifiedQuirks != 0 { + sort.Sort(types.MethodsByName(methods)) + sort.Stable(types.EmbeddedsByName(embeddeds)) + } w.startType(interfaceType) w.setPkg(t.Pkg(), true) -- GitLab From 805d38a3529918a708875b068ccee46a7edcead0 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Fri, 13 Aug 2021 15:03:14 -0400 Subject: [PATCH 0760/2500] cmd/compile/internal/types2: no need to validate substituted instances When substituting a type instance, we rely on the instance being expanded and do not call validType, so there is need to depend on subster.pos for error reporting or to use subst.check for creating the new Named type. Errors will be reported for the unsubstituted instance. This is a superficial change, but justifies some later simplification where we don't have access to pos or check. Change-Id: I1f3f12aa245d821512c6242ad829c940f20afae4 Reviewed-on: https://go-review.googlesource.com/c/go/+/342150 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/cmd/compile/internal/types2/subst.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index ed3fd654a0..2c0fc6e391 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -222,10 +222,15 @@ func (subst *subster) typ(typ Type) Type { return named } - // create a new named type and populate typMap to avoid endless recursion + // Create a new named type and populate typMap to avoid endless recursion. + // The position used here is irrelevant because validation only occurs on t + // (we don't call validType on named), but we use subst.pos to help with + // debugging. tname := NewTypeName(subst.pos, t.obj.pkg, t.obj.name, nil) t.load() - named := subst.check.newNamed(tname, t.orig, t.underlying, t.TParams(), t.methods) // method signatures are updated lazily + // It's ok to provide a nil *Checker because the newly created type + // doesn't need to be (lazily) expanded; it's expanded below. + named := (*Checker)(nil).newNamed(tname, t.orig, nil, t.tparams, t.methods) // t is loaded, so tparams and methods are available named.targs = newTArgs subst.typMap[h] = named t.expand(subst.typMap) // must happen after typMap update to avoid infinite recursion @@ -235,7 +240,7 @@ func (subst *subster) typ(typ Type) Type { named.underlying = subst.typOrNil(t.underlying) dump(">>> underlying: %v", named.underlying) assert(named.underlying != nil) - named.fromRHS = named.underlying // for cycle detection (Checker.validType) + named.fromRHS = named.underlying // for consistency, though no cycle detection is necessary return named -- GitLab From eda3de0f79f3008aed21c04df546efa2ace65683 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Fri, 13 Aug 2021 13:15:15 -0400 Subject: [PATCH 0761/2500] cmd/compile/internal/types2: change Checker.verify to return an error In preparation for upcoming API changes, change the internal API for verification of type arguments to return an error and argument index, and use this to lift up error reporting into Instantiate. Change-Id: I88b1e64dd9055c4c20c0db49c96c79c5da894450 Reviewed-on: https://go-review.googlesource.com/c/go/+/342151 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- .../compile/internal/types2/instantiate.go | 69 ++++++++++--------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index ef92574a5c..ab51d062c5 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -9,6 +9,7 @@ package types2 import ( "cmd/compile/internal/syntax" + "errors" "fmt" ) @@ -74,7 +75,14 @@ func (check *Checker) Instantiate(pos syntax.Pos, typ Type, targs []Type, posLis // Avoid duplicate errors; instantiate will have complained if tparams // and targs do not have the same length. if len(tparams) == len(targs) { - check.verify(pos, tparams, targs, posList) + if i, err := check.verify(pos, tparams, targs); err != nil { + // best position for error reporting + pos := pos + if i < len(posList) { + pos = posList[i] + } + check.softErrorf(pos, err.Error()) + } } }) } @@ -139,30 +147,36 @@ func (check *Checker) instantiateLazy(pos syntax.Pos, orig *Named, targs []Type) return named } -func (check *Checker) verify(pos syntax.Pos, tparams []*TypeName, targs []Type, posList []syntax.Pos) { +func (check *Checker) verify(pos syntax.Pos, tparams []*TypeName, targs []Type) (int, error) { smap := makeSubstMap(tparams, targs) for i, tname := range tparams { - // best position for error reporting - pos := pos - if i < len(posList) { - pos = posList[i] - } - // stop checking bounds after the first failure - if !check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap) { - break + if err := check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap); err != nil { + return i, err } } + return -1, nil } // satisfies reports whether the type argument targ satisfies the constraint of type parameter // parameter tpar (after any of its type parameters have been substituted through smap). // A suitable error is reported if the result is false. // TODO(gri) This should be a method of interfaces or type sets. -func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap substMap) bool { +func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap substMap) error { iface := tpar.iface() if iface.Empty() { - return true // no type bound + return nil // no type bound + } + + // TODO(rfindley): it would be great if users could pass in a qualifier here, + // rather than falling back to verbose qualification. Maybe this can be part + // of a the shared environment. + var qf Qualifier + if check != nil { + qf = check.qualifier + } + errorf := func(format string, args ...interface{}) error { + return errors.New(sprintf(qf, format, args...)) } // The type parameter bound is parameterized with the same type parameters @@ -175,11 +189,9 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap // TODO(gri) the error messages needs to be better, here if iface.IsComparable() && !Comparable(targ) { if tpar := asTypeParam(targ); tpar != nil && tpar.iface().typeSet().IsAll() { - check.softErrorf(pos, "%s has no constraints", targ) - return false + return errorf("%s has no constraints", targ) } - check.softErrorf(pos, "%s does not satisfy comparable", targ) - return false + return errorf("%s does not satisfy comparable", targ) } // targ must implement iface (methods) @@ -189,8 +201,7 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap // method set is empty. // TODO(gri) is this what we want? (spec question) if base, isPtr := deref(targ); isPtr && asTypeParam(base) != nil { - check.errorf(pos, "%s has no methods", targ) - return false + return errorf("%s has no methods", targ) } if m, wrong := check.missingMethod(targ, iface, true); m != nil { // TODO(gri) needs to print updated name to avoid major confusion in error message! @@ -200,20 +211,17 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap if wrong != nil { // TODO(gri) This can still report uninstantiated types which makes the error message // more difficult to read then necessary. - check.softErrorf(pos, - "%s does not satisfy %s: wrong method signature\n\tgot %s\n\twant %s", + return errorf("%s does not satisfy %s: wrong method signature\n\tgot %s\n\twant %s", targ, tpar.bound, wrong, m, ) - } else { - check.softErrorf(pos, "%s does not satisfy %s (missing method %s)", targ, tpar.bound, m.name) } - return false + return errorf("%s does not satisfy %s (missing method %s)", targ, tpar.bound, m.name) } } // targ's underlying type must also be one of the interface types listed, if any if !iface.typeSet().hasTerms() { - return true // nothing to do + return nil // nothing to do } // If targ is itself a type parameter, each of its possible types, but at least one, must be in the @@ -221,23 +229,20 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap if targ := asTypeParam(targ); targ != nil { targBound := targ.iface() if !targBound.typeSet().hasTerms() { - check.softErrorf(pos, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ) - return false + return errorf("%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ) } if !targBound.typeSet().subsetOf(iface.typeSet()) { // TODO(gri) need better error message - check.softErrorf(pos, "%s does not satisfy %s", targ, tpar.bound) - return false + return errorf("%s does not satisfy %s", targ, tpar.bound) } - return true + return nil } // Otherwise, targ's type or underlying type must also be one of the interface types listed, if any. if !iface.typeSet().includes(targ) { // TODO(gri) better error message - check.softErrorf(pos, "%s does not satisfy %s", targ, tpar.bound) - return false + return errorf("%s does not satisfy %s", targ, tpar.bound) } - return true + return nil } -- GitLab From 687f2acf6ae00226e8304e15f156f36e19ac971f Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 17 Aug 2021 10:40:44 -0700 Subject: [PATCH 0762/2500] cmd/compile: only use dictionaries for conversions to type parameters Conversions to regular concrete types should not be rewritten during stenciling. Fixes #47740 Change-Id: I2b45e22f962dcd2e18bd6cc876ebc0f850860822 Reviewed-on: https://go-review.googlesource.com/c/go/+/342989 Trust: Keith Randall Trust: Dan Scales Trust: Cuong Manh Le Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 3 ++ test/typeparam/issue47740.go | 37 +++++++++++++++++++++++ test/typeparam/issue47740.out | 2 ++ test/typeparam/issue47740b.go | 23 ++++++++++++++ 4 files changed, 65 insertions(+) create mode 100644 test/typeparam/issue47740.go create mode 100644 test/typeparam/issue47740.out create mode 100644 test/typeparam/issue47740b.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 4ac37c362c..19b8f63c4b 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1118,6 +1118,9 @@ func (subst *subster) node(n ir.Node) ir.Node { m = convertUsingDictionary(subst.info, subst.info.dictParam, m.Pos(), m.(*ir.ConvExpr).X, x, m.Type(), x.X.Type()) } case ir.ODOTTYPE, ir.ODOTTYPE2: + if !x.Type().HasTParam() { + break + } dt := m.(*ir.TypeAssertExpr) var rt ir.Node if dt.Type().IsInterface() || dt.X.Type().IsEmptyInterface() { diff --git a/test/typeparam/issue47740.go b/test/typeparam/issue47740.go new file mode 100644 index 0000000000..a8c6839de3 --- /dev/null +++ b/test/typeparam/issue47740.go @@ -0,0 +1,37 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "fmt" + +type Exp[Ty any] interface { + Eval() Ty +} + +type Lit[Ty any] Ty + +func (lit Lit[Ty]) Eval() Ty { return Ty(lit) } +func (lit Lit[Ty]) String() string { return fmt.Sprintf("(lit %v)", Ty(lit)) } + +type Eq[Ty any] struct { + a Exp[Ty] + b Exp[Ty] +} + +func (e Eq[Ty]) String() string { + return fmt.Sprintf("(eq %v %v)", e.a, e.b) +} + +var ( + e0 = Eq[int]{Lit[int](128), Lit[int](64)} + e1 = Eq[bool]{Lit[bool](true), Lit[bool](true)} +) + +func main() { + fmt.Printf("%v\n", e0) + fmt.Printf("%v\n", e1) +} diff --git a/test/typeparam/issue47740.out b/test/typeparam/issue47740.out new file mode 100644 index 0000000000..f23c310f66 --- /dev/null +++ b/test/typeparam/issue47740.out @@ -0,0 +1,2 @@ +(eq (lit 128) (lit 64)) +(eq (lit true) (lit true)) diff --git a/test/typeparam/issue47740b.go b/test/typeparam/issue47740b.go new file mode 100644 index 0000000000..2a91d35eb4 --- /dev/null +++ b/test/typeparam/issue47740b.go @@ -0,0 +1,23 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "reflect" + +type S[T any] struct { + a interface{} +} + +func (e S[T]) M() { + v := reflect.ValueOf(e.a) + _, _ = v.Interface().(int) +} + +func main() { + e := S[int]{0} + e.M() +} -- GitLab From 322879d5c9dc34975a42ac77fbef7b4a8b255e8a Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 18 Aug 2021 14:42:12 -0700 Subject: [PATCH 0763/2500] cmd/compile/internal/dwarfgen: use src.Pos.Rel{Filename,Line,Col} consistently It appears that this code predates golang.org/cl/96535, which added RelCol to support /*line*/ directives. Change-Id: Ib79cebc1be53af706e84e8799eeea81ef8c81c8b Reviewed-on: https://go-review.googlesource.com/c/go/+/343430 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/compile/internal/dwarfgen/dwarf.go | 6 +++--- src/cmd/compile/internal/dwarfgen/dwinl.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/dwarfgen/dwarf.go b/src/cmd/compile/internal/dwarfgen/dwarf.go index 0e22b61bc3..30472a9ebd 100644 --- a/src/cmd/compile/internal/dwarfgen/dwarf.go +++ b/src/cmd/compile/internal/dwarfgen/dwarf.go @@ -214,7 +214,7 @@ func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []*ir Type: base.Ctxt.Lookup(typename), DeclFile: declpos.RelFilename(), DeclLine: declpos.RelLine(), - DeclCol: declpos.Col(), + DeclCol: declpos.RelCol(), InlIndex: int32(inlIndex), ChildIndex: -1, }) @@ -371,7 +371,7 @@ func createSimpleVar(fnsym *obj.LSym, n *ir.Name) *dwarf.Var { Type: base.Ctxt.Lookup(typename), DeclFile: declpos.RelFilename(), DeclLine: declpos.RelLine(), - DeclCol: declpos.Col(), + DeclCol: declpos.RelCol(), InlIndex: int32(inlIndex), ChildIndex: -1, } @@ -475,7 +475,7 @@ func createComplexVar(fnsym *obj.LSym, fn *ir.Func, varID ssa.VarID) *dwarf.Var StackOffset: ssagen.StackOffset(debug.Slots[debug.VarSlots[varID][0]]), DeclFile: declpos.RelFilename(), DeclLine: declpos.RelLine(), - DeclCol: declpos.Col(), + DeclCol: declpos.RelCol(), InlIndex: int32(inlIndex), ChildIndex: -1, } diff --git a/src/cmd/compile/internal/dwarfgen/dwinl.go b/src/cmd/compile/internal/dwarfgen/dwinl.go index 8adb36fc88..c785e064a7 100644 --- a/src/cmd/compile/internal/dwarfgen/dwinl.go +++ b/src/cmd/compile/internal/dwarfgen/dwinl.go @@ -244,7 +244,7 @@ func makePreinlineDclMap(fnsym *obj.LSym) map[varPos]int { DeclName: unversion(n.Sym().Name), DeclFile: pos.RelFilename(), DeclLine: pos.RelLine(), - DeclCol: pos.Col(), + DeclCol: pos.RelCol(), } if _, found := m[vp]; found { // We can see collisions (variables with the same name/file/line/col) in obfuscated or machine-generated code -- see issue 44378 for an example. Skip duplicates in such cases, since it is unlikely that a human will be debugging such code. -- GitLab From c85695a117f1ec3b800ba14570876cfcd2075c1f Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 18 Aug 2021 14:36:45 -0700 Subject: [PATCH 0764/2500] cmd/compile: add support for //go:nointerface for -G=3 This is used within Google's internal code repo, so getting it working is a pre-req for enabling -G=3 by default. Change-Id: Icbc570948c852ca09cdb2a59f778140f620244b2 Reviewed-on: https://go-review.googlesource.com/c/go/+/343429 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/compile/internal/noder/decl.go | 11 +++++++++++ test/run.go | 2 -- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go index 429c8a14c8..cec31d87b7 100644 --- a/src/cmd/compile/internal/noder/decl.go +++ b/src/cmd/compile/internal/noder/decl.go @@ -97,6 +97,17 @@ func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) { if fn.Pragma&ir.Systemstack != 0 && fn.Pragma&ir.Nosplit != 0 { base.ErrorfAt(fn.Pos(), "go:nosplit and go:systemstack cannot be combined") } + if fn.Pragma&ir.Nointerface != 0 { + // Propagate //go:nointerface from Func.Pragma to Field.Nointerface. + // This is a bit roundabout, but this is the earliest point where we've + // processed the function's pragma flags, and we've also already created + // the Fields to represent the receiver's method set. + if recv := fn.Type().Recv(); recv != nil { + typ := types.ReceiverBaseType(recv.Type) + meth := typecheck.Lookdot1(fn, typecheck.Lookup(decl.Name.Value), typ, typ.Methods(), 0) + meth.SetNointerface(true) + } + } if decl.Name.Value == "init" && decl.Recv == nil { g.target.Inits = append(g.target.Inits, fn) diff --git a/test/run.go b/test/run.go index 5d5adc3623..f5971d2d15 100644 --- a/test/run.go +++ b/test/run.go @@ -2180,8 +2180,6 @@ var types2Failures32Bit = setOf( var g3Failures = setOf( "writebarrier.go", // correct diagnostics, but different lines (probably irgen's fault) - "fixedbugs/issue30862.go", // -G=3 doesn't handle //go:nointerface - "typeparam/nested.go", // -G=3 doesn't support function-local types with generics "typeparam/mdempsky/4.go", // -G=3 can't export functions with labeled breaks in loops -- GitLab From 740f7d73707fab5000791b71c2ab046e3e5544c7 Mon Sep 17 00:00:00 2001 From: Roger Peppe Date: Wed, 11 Aug 2021 12:50:34 +0100 Subject: [PATCH 0765/2500] archive/tar: unexport internal methods Many of the methods inside the archive/tar package don't need to be exported. Doing so sets a bad precedent that it's OK to export methods to indicate an internal public API. That's not a good idea in general, because exported methods increase cognitive load when reading code: the reader needs to consider whether the exported method might be used via some external interface or reflection. This CL should have no externally visible behaviour changes at all. Change-Id: I94a63de5e6a28e9ac8a283325217349ebce4f308 Reviewed-on: https://go-review.googlesource.com/c/go/+/341410 Reviewed-by: Joe Tsai Trust: Joe Tsai Trust: Michael Knyszek --- src/archive/tar/common.go | 38 ++++----- src/archive/tar/format.go | 138 ++++++++++++++++----------------- src/archive/tar/reader.go | 102 ++++++++++++------------ src/archive/tar/reader_test.go | 26 +++---- src/archive/tar/writer.go | 89 +++++++++++---------- src/archive/tar/writer_test.go | 14 ++-- 6 files changed, 206 insertions(+), 201 deletions(-) diff --git a/src/archive/tar/common.go b/src/archive/tar/common.go index c667cfc872..595de64725 100644 --- a/src/archive/tar/common.go +++ b/src/archive/tar/common.go @@ -316,10 +316,10 @@ func invertSparseEntries(src []sparseEntry, size int64) []sparseEntry { // fileState tracks the number of logical (includes sparse holes) and physical // (actual in tar archive) bytes remaining for the current file. // -// Invariant: LogicalRemaining >= PhysicalRemaining +// Invariant: logicalRemaining >= physicalRemaining type fileState interface { - LogicalRemaining() int64 - PhysicalRemaining() int64 + logicalRemaining() int64 + physicalRemaining() int64 } // allowedFormats determines which formats can be used. @@ -413,22 +413,22 @@ func (h Header) allowedFormats() (format Format, paxHdrs map[string]string, err // Check basic fields. var blk block - v7 := blk.V7() - ustar := blk.USTAR() - gnu := blk.GNU() - verifyString(h.Name, len(v7.Name()), "Name", paxPath) - verifyString(h.Linkname, len(v7.LinkName()), "Linkname", paxLinkpath) - verifyString(h.Uname, len(ustar.UserName()), "Uname", paxUname) - verifyString(h.Gname, len(ustar.GroupName()), "Gname", paxGname) - verifyNumeric(h.Mode, len(v7.Mode()), "Mode", paxNone) - verifyNumeric(int64(h.Uid), len(v7.UID()), "Uid", paxUid) - verifyNumeric(int64(h.Gid), len(v7.GID()), "Gid", paxGid) - verifyNumeric(h.Size, len(v7.Size()), "Size", paxSize) - verifyNumeric(h.Devmajor, len(ustar.DevMajor()), "Devmajor", paxNone) - verifyNumeric(h.Devminor, len(ustar.DevMinor()), "Devminor", paxNone) - verifyTime(h.ModTime, len(v7.ModTime()), "ModTime", paxMtime) - verifyTime(h.AccessTime, len(gnu.AccessTime()), "AccessTime", paxAtime) - verifyTime(h.ChangeTime, len(gnu.ChangeTime()), "ChangeTime", paxCtime) + v7 := blk.toV7() + ustar := blk.toUSTAR() + gnu := blk.toGNU() + verifyString(h.Name, len(v7.name()), "Name", paxPath) + verifyString(h.Linkname, len(v7.linkName()), "Linkname", paxLinkpath) + verifyString(h.Uname, len(ustar.userName()), "Uname", paxUname) + verifyString(h.Gname, len(ustar.groupName()), "Gname", paxGname) + verifyNumeric(h.Mode, len(v7.mode()), "Mode", paxNone) + verifyNumeric(int64(h.Uid), len(v7.uid()), "Uid", paxUid) + verifyNumeric(int64(h.Gid), len(v7.gid()), "Gid", paxGid) + verifyNumeric(h.Size, len(v7.size()), "Size", paxSize) + verifyNumeric(h.Devmajor, len(ustar.devMajor()), "Devmajor", paxNone) + verifyNumeric(h.Devminor, len(ustar.devMinor()), "Devminor", paxNone) + verifyTime(h.ModTime, len(v7.modTime()), "ModTime", paxMtime) + verifyTime(h.AccessTime, len(gnu.accessTime()), "AccessTime", paxAtime) + verifyTime(h.ChangeTime, len(gnu.changeTime()), "ChangeTime", paxCtime) // Check for header-only types. var whyOnlyPAX, whyOnlyGNU string diff --git a/src/archive/tar/format.go b/src/archive/tar/format.go index cfe24a5e1d..21b9d9d4db 100644 --- a/src/archive/tar/format.go +++ b/src/archive/tar/format.go @@ -156,28 +156,28 @@ var zeroBlock block type block [blockSize]byte // Convert block to any number of formats. -func (b *block) V7() *headerV7 { return (*headerV7)(b) } -func (b *block) GNU() *headerGNU { return (*headerGNU)(b) } -func (b *block) STAR() *headerSTAR { return (*headerSTAR)(b) } -func (b *block) USTAR() *headerUSTAR { return (*headerUSTAR)(b) } -func (b *block) Sparse() sparseArray { return sparseArray(b[:]) } +func (b *block) toV7() *headerV7 { return (*headerV7)(b) } +func (b *block) toGNU() *headerGNU { return (*headerGNU)(b) } +func (b *block) toSTAR() *headerSTAR { return (*headerSTAR)(b) } +func (b *block) toUSTAR() *headerUSTAR { return (*headerUSTAR)(b) } +func (b *block) toSparse() sparseArray { return sparseArray(b[:]) } // GetFormat checks that the block is a valid tar header based on the checksum. // It then attempts to guess the specific format based on magic values. // If the checksum fails, then FormatUnknown is returned. -func (b *block) GetFormat() Format { +func (b *block) getFormat() Format { // Verify checksum. var p parser - value := p.parseOctal(b.V7().Chksum()) - chksum1, chksum2 := b.ComputeChecksum() + value := p.parseOctal(b.toV7().chksum()) + chksum1, chksum2 := b.computeChecksum() if p.err != nil || (value != chksum1 && value != chksum2) { return FormatUnknown } // Guess the magic values. - magic := string(b.USTAR().Magic()) - version := string(b.USTAR().Version()) - trailer := string(b.STAR().Trailer()) + magic := string(b.toUSTAR().magic()) + version := string(b.toUSTAR().version()) + trailer := string(b.toSTAR().trailer()) switch { case magic == magicUSTAR && trailer == trailerSTAR: return formatSTAR @@ -190,23 +190,23 @@ func (b *block) GetFormat() Format { } } -// SetFormat writes the magic values necessary for specified format +// setFormat writes the magic values necessary for specified format // and then updates the checksum accordingly. -func (b *block) SetFormat(format Format) { +func (b *block) setFormat(format Format) { // Set the magic values. switch { case format.has(formatV7): // Do nothing. case format.has(FormatGNU): - copy(b.GNU().Magic(), magicGNU) - copy(b.GNU().Version(), versionGNU) + copy(b.toGNU().magic(), magicGNU) + copy(b.toGNU().version(), versionGNU) case format.has(formatSTAR): - copy(b.STAR().Magic(), magicUSTAR) - copy(b.STAR().Version(), versionUSTAR) - copy(b.STAR().Trailer(), trailerSTAR) + copy(b.toSTAR().magic(), magicUSTAR) + copy(b.toSTAR().version(), versionUSTAR) + copy(b.toSTAR().trailer(), trailerSTAR) case format.has(FormatUSTAR | FormatPAX): - copy(b.USTAR().Magic(), magicUSTAR) - copy(b.USTAR().Version(), versionUSTAR) + copy(b.toUSTAR().magic(), magicUSTAR) + copy(b.toUSTAR().version(), versionUSTAR) default: panic("invalid format") } @@ -214,17 +214,17 @@ func (b *block) SetFormat(format Format) { // Update checksum. // This field is special in that it is terminated by a NULL then space. var f formatter - field := b.V7().Chksum() - chksum, _ := b.ComputeChecksum() // Possible values are 256..128776 + field := b.toV7().chksum() + chksum, _ := b.computeChecksum() // Possible values are 256..128776 f.formatOctal(field[:7], chksum) // Never fails since 128776 < 262143 field[7] = ' ' } -// ComputeChecksum computes the checksum for the header block. +// computeChecksum computes the checksum for the header block. // POSIX specifies a sum of the unsigned byte values, but the Sun tar used // signed byte values. // We compute and return both. -func (b *block) ComputeChecksum() (unsigned, signed int64) { +func (b *block) computeChecksum() (unsigned, signed int64) { for i, c := range b { if 148 <= i && i < 156 { c = ' ' // Treat the checksum field itself as all spaces. @@ -236,68 +236,68 @@ func (b *block) ComputeChecksum() (unsigned, signed int64) { } // Reset clears the block with all zeros. -func (b *block) Reset() { +func (b *block) reset() { *b = block{} } type headerV7 [blockSize]byte -func (h *headerV7) Name() []byte { return h[000:][:100] } -func (h *headerV7) Mode() []byte { return h[100:][:8] } -func (h *headerV7) UID() []byte { return h[108:][:8] } -func (h *headerV7) GID() []byte { return h[116:][:8] } -func (h *headerV7) Size() []byte { return h[124:][:12] } -func (h *headerV7) ModTime() []byte { return h[136:][:12] } -func (h *headerV7) Chksum() []byte { return h[148:][:8] } -func (h *headerV7) TypeFlag() []byte { return h[156:][:1] } -func (h *headerV7) LinkName() []byte { return h[157:][:100] } +func (h *headerV7) name() []byte { return h[000:][:100] } +func (h *headerV7) mode() []byte { return h[100:][:8] } +func (h *headerV7) uid() []byte { return h[108:][:8] } +func (h *headerV7) gid() []byte { return h[116:][:8] } +func (h *headerV7) size() []byte { return h[124:][:12] } +func (h *headerV7) modTime() []byte { return h[136:][:12] } +func (h *headerV7) chksum() []byte { return h[148:][:8] } +func (h *headerV7) typeFlag() []byte { return h[156:][:1] } +func (h *headerV7) linkName() []byte { return h[157:][:100] } type headerGNU [blockSize]byte -func (h *headerGNU) V7() *headerV7 { return (*headerV7)(h) } -func (h *headerGNU) Magic() []byte { return h[257:][:6] } -func (h *headerGNU) Version() []byte { return h[263:][:2] } -func (h *headerGNU) UserName() []byte { return h[265:][:32] } -func (h *headerGNU) GroupName() []byte { return h[297:][:32] } -func (h *headerGNU) DevMajor() []byte { return h[329:][:8] } -func (h *headerGNU) DevMinor() []byte { return h[337:][:8] } -func (h *headerGNU) AccessTime() []byte { return h[345:][:12] } -func (h *headerGNU) ChangeTime() []byte { return h[357:][:12] } -func (h *headerGNU) Sparse() sparseArray { return sparseArray(h[386:][:24*4+1]) } -func (h *headerGNU) RealSize() []byte { return h[483:][:12] } +func (h *headerGNU) v7() *headerV7 { return (*headerV7)(h) } +func (h *headerGNU) magic() []byte { return h[257:][:6] } +func (h *headerGNU) version() []byte { return h[263:][:2] } +func (h *headerGNU) userName() []byte { return h[265:][:32] } +func (h *headerGNU) groupName() []byte { return h[297:][:32] } +func (h *headerGNU) devMajor() []byte { return h[329:][:8] } +func (h *headerGNU) devMinor() []byte { return h[337:][:8] } +func (h *headerGNU) accessTime() []byte { return h[345:][:12] } +func (h *headerGNU) changeTime() []byte { return h[357:][:12] } +func (h *headerGNU) sparse() sparseArray { return sparseArray(h[386:][:24*4+1]) } +func (h *headerGNU) realSize() []byte { return h[483:][:12] } type headerSTAR [blockSize]byte -func (h *headerSTAR) V7() *headerV7 { return (*headerV7)(h) } -func (h *headerSTAR) Magic() []byte { return h[257:][:6] } -func (h *headerSTAR) Version() []byte { return h[263:][:2] } -func (h *headerSTAR) UserName() []byte { return h[265:][:32] } -func (h *headerSTAR) GroupName() []byte { return h[297:][:32] } -func (h *headerSTAR) DevMajor() []byte { return h[329:][:8] } -func (h *headerSTAR) DevMinor() []byte { return h[337:][:8] } -func (h *headerSTAR) Prefix() []byte { return h[345:][:131] } -func (h *headerSTAR) AccessTime() []byte { return h[476:][:12] } -func (h *headerSTAR) ChangeTime() []byte { return h[488:][:12] } -func (h *headerSTAR) Trailer() []byte { return h[508:][:4] } +func (h *headerSTAR) v7() *headerV7 { return (*headerV7)(h) } +func (h *headerSTAR) magic() []byte { return h[257:][:6] } +func (h *headerSTAR) version() []byte { return h[263:][:2] } +func (h *headerSTAR) userName() []byte { return h[265:][:32] } +func (h *headerSTAR) groupName() []byte { return h[297:][:32] } +func (h *headerSTAR) devMajor() []byte { return h[329:][:8] } +func (h *headerSTAR) devMinor() []byte { return h[337:][:8] } +func (h *headerSTAR) prefix() []byte { return h[345:][:131] } +func (h *headerSTAR) accessTime() []byte { return h[476:][:12] } +func (h *headerSTAR) changeTime() []byte { return h[488:][:12] } +func (h *headerSTAR) trailer() []byte { return h[508:][:4] } type headerUSTAR [blockSize]byte -func (h *headerUSTAR) V7() *headerV7 { return (*headerV7)(h) } -func (h *headerUSTAR) Magic() []byte { return h[257:][:6] } -func (h *headerUSTAR) Version() []byte { return h[263:][:2] } -func (h *headerUSTAR) UserName() []byte { return h[265:][:32] } -func (h *headerUSTAR) GroupName() []byte { return h[297:][:32] } -func (h *headerUSTAR) DevMajor() []byte { return h[329:][:8] } -func (h *headerUSTAR) DevMinor() []byte { return h[337:][:8] } -func (h *headerUSTAR) Prefix() []byte { return h[345:][:155] } +func (h *headerUSTAR) v7() *headerV7 { return (*headerV7)(h) } +func (h *headerUSTAR) magic() []byte { return h[257:][:6] } +func (h *headerUSTAR) version() []byte { return h[263:][:2] } +func (h *headerUSTAR) userName() []byte { return h[265:][:32] } +func (h *headerUSTAR) groupName() []byte { return h[297:][:32] } +func (h *headerUSTAR) devMajor() []byte { return h[329:][:8] } +func (h *headerUSTAR) devMinor() []byte { return h[337:][:8] } +func (h *headerUSTAR) prefix() []byte { return h[345:][:155] } type sparseArray []byte -func (s sparseArray) Entry(i int) sparseElem { return sparseElem(s[i*24:]) } -func (s sparseArray) IsExtended() []byte { return s[24*s.MaxEntries():][:1] } -func (s sparseArray) MaxEntries() int { return len(s) / 24 } +func (s sparseArray) entry(i int) sparseElem { return sparseElem(s[i*24:]) } +func (s sparseArray) isExtended() []byte { return s[24*s.maxEntries():][:1] } +func (s sparseArray) maxEntries() int { return len(s) / 24 } type sparseElem []byte -func (s sparseElem) Offset() []byte { return s[00:][:12] } -func (s sparseElem) Length() []byte { return s[12:][:12] } +func (s sparseElem) offset() []byte { return s[00:][:12] } +func (s sparseElem) length() []byte { return s[12:][:12] } diff --git a/src/archive/tar/reader.go b/src/archive/tar/reader.go index 1b1d5b4689..4b11909bc9 100644 --- a/src/archive/tar/reader.go +++ b/src/archive/tar/reader.go @@ -65,7 +65,7 @@ func (tr *Reader) next() (*Header, error) { format := FormatUSTAR | FormatPAX | FormatGNU for { // Discard the remainder of the file and any padding. - if err := discard(tr.r, tr.curr.PhysicalRemaining()); err != nil { + if err := discard(tr.r, tr.curr.physicalRemaining()); err != nil { return nil, err } if _, err := tryReadFull(tr.r, tr.blk[:tr.pad]); err != nil { @@ -355,7 +355,7 @@ func (tr *Reader) readHeader() (*Header, *block, error) { } // Verify the header matches a known format. - format := tr.blk.GetFormat() + format := tr.blk.getFormat() if format == FormatUnknown { return nil, nil, ErrHeader } @@ -364,30 +364,30 @@ func (tr *Reader) readHeader() (*Header, *block, error) { hdr := new(Header) // Unpack the V7 header. - v7 := tr.blk.V7() - hdr.Typeflag = v7.TypeFlag()[0] - hdr.Name = p.parseString(v7.Name()) - hdr.Linkname = p.parseString(v7.LinkName()) - hdr.Size = p.parseNumeric(v7.Size()) - hdr.Mode = p.parseNumeric(v7.Mode()) - hdr.Uid = int(p.parseNumeric(v7.UID())) - hdr.Gid = int(p.parseNumeric(v7.GID())) - hdr.ModTime = time.Unix(p.parseNumeric(v7.ModTime()), 0) + v7 := tr.blk.toV7() + hdr.Typeflag = v7.typeFlag()[0] + hdr.Name = p.parseString(v7.name()) + hdr.Linkname = p.parseString(v7.linkName()) + hdr.Size = p.parseNumeric(v7.size()) + hdr.Mode = p.parseNumeric(v7.mode()) + hdr.Uid = int(p.parseNumeric(v7.uid())) + hdr.Gid = int(p.parseNumeric(v7.gid())) + hdr.ModTime = time.Unix(p.parseNumeric(v7.modTime()), 0) // Unpack format specific fields. if format > formatV7 { - ustar := tr.blk.USTAR() - hdr.Uname = p.parseString(ustar.UserName()) - hdr.Gname = p.parseString(ustar.GroupName()) - hdr.Devmajor = p.parseNumeric(ustar.DevMajor()) - hdr.Devminor = p.parseNumeric(ustar.DevMinor()) + ustar := tr.blk.toUSTAR() + hdr.Uname = p.parseString(ustar.userName()) + hdr.Gname = p.parseString(ustar.groupName()) + hdr.Devmajor = p.parseNumeric(ustar.devMajor()) + hdr.Devminor = p.parseNumeric(ustar.devMinor()) var prefix string switch { case format.has(FormatUSTAR | FormatPAX): hdr.Format = format - ustar := tr.blk.USTAR() - prefix = p.parseString(ustar.Prefix()) + ustar := tr.blk.toUSTAR() + prefix = p.parseString(ustar.prefix()) // For Format detection, check if block is properly formatted since // the parser is more liberal than what USTAR actually permits. @@ -396,23 +396,23 @@ func (tr *Reader) readHeader() (*Header, *block, error) { hdr.Format = FormatUnknown // Non-ASCII characters in block. } nul := func(b []byte) bool { return int(b[len(b)-1]) == 0 } - if !(nul(v7.Size()) && nul(v7.Mode()) && nul(v7.UID()) && nul(v7.GID()) && - nul(v7.ModTime()) && nul(ustar.DevMajor()) && nul(ustar.DevMinor())) { + if !(nul(v7.size()) && nul(v7.mode()) && nul(v7.uid()) && nul(v7.gid()) && + nul(v7.modTime()) && nul(ustar.devMajor()) && nul(ustar.devMinor())) { hdr.Format = FormatUnknown // Numeric fields must end in NUL } case format.has(formatSTAR): - star := tr.blk.STAR() - prefix = p.parseString(star.Prefix()) - hdr.AccessTime = time.Unix(p.parseNumeric(star.AccessTime()), 0) - hdr.ChangeTime = time.Unix(p.parseNumeric(star.ChangeTime()), 0) + star := tr.blk.toSTAR() + prefix = p.parseString(star.prefix()) + hdr.AccessTime = time.Unix(p.parseNumeric(star.accessTime()), 0) + hdr.ChangeTime = time.Unix(p.parseNumeric(star.changeTime()), 0) case format.has(FormatGNU): hdr.Format = format var p2 parser - gnu := tr.blk.GNU() - if b := gnu.AccessTime(); b[0] != 0 { + gnu := tr.blk.toGNU() + if b := gnu.accessTime(); b[0] != 0 { hdr.AccessTime = time.Unix(p2.parseNumeric(b), 0) } - if b := gnu.ChangeTime(); b[0] != 0 { + if b := gnu.changeTime(); b[0] != 0 { hdr.ChangeTime = time.Unix(p2.parseNumeric(b), 0) } @@ -439,8 +439,8 @@ func (tr *Reader) readHeader() (*Header, *block, error) { // See https://golang.org/issues/21005 if p2.err != nil { hdr.AccessTime, hdr.ChangeTime = time.Time{}, time.Time{} - ustar := tr.blk.USTAR() - if s := p.parseString(ustar.Prefix()); isASCII(s) { + ustar := tr.blk.toUSTAR() + if s := p.parseString(ustar.prefix()); isASCII(s) { prefix = s } hdr.Format = FormatUnknown // Buggy file is not GNU @@ -465,38 +465,38 @@ func (tr *Reader) readOldGNUSparseMap(hdr *Header, blk *block) (sparseDatas, err // Make sure that the input format is GNU. // Unfortunately, the STAR format also has a sparse header format that uses // the same type flag but has a completely different layout. - if blk.GetFormat() != FormatGNU { + if blk.getFormat() != FormatGNU { return nil, ErrHeader } hdr.Format.mayOnlyBe(FormatGNU) var p parser - hdr.Size = p.parseNumeric(blk.GNU().RealSize()) + hdr.Size = p.parseNumeric(blk.toGNU().realSize()) if p.err != nil { return nil, p.err } - s := blk.GNU().Sparse() - spd := make(sparseDatas, 0, s.MaxEntries()) + s := blk.toGNU().sparse() + spd := make(sparseDatas, 0, s.maxEntries()) for { - for i := 0; i < s.MaxEntries(); i++ { + for i := 0; i < s.maxEntries(); i++ { // This termination condition is identical to GNU and BSD tar. - if s.Entry(i).Offset()[0] == 0x00 { + if s.entry(i).offset()[0] == 0x00 { break // Don't return, need to process extended headers (even if empty) } - offset := p.parseNumeric(s.Entry(i).Offset()) - length := p.parseNumeric(s.Entry(i).Length()) + offset := p.parseNumeric(s.entry(i).offset()) + length := p.parseNumeric(s.entry(i).length()) if p.err != nil { return nil, p.err } spd = append(spd, sparseEntry{Offset: offset, Length: length}) } - if s.IsExtended()[0] > 0 { + if s.isExtended()[0] > 0 { // There are more entries. Read an extension header and parse its entries. if _, err := mustReadFull(tr.r, blk[:]); err != nil { return nil, err } - s = blk.Sparse() + s = blk.toSparse() continue } return spd, nil // Done @@ -678,11 +678,13 @@ func (fr *regFileReader) WriteTo(w io.Writer) (int64, error) { return io.Copy(w, struct{ io.Reader }{fr}) } -func (fr regFileReader) LogicalRemaining() int64 { +// logicalRemaining implements fileState.logicalRemaining. +func (fr regFileReader) logicalRemaining() int64 { return fr.nb } -func (fr regFileReader) PhysicalRemaining() int64 { +// logicalRemaining implements fileState.physicalRemaining. +func (fr regFileReader) physicalRemaining() int64 { return fr.nb } @@ -694,9 +696,9 @@ type sparseFileReader struct { } func (sr *sparseFileReader) Read(b []byte) (n int, err error) { - finished := int64(len(b)) >= sr.LogicalRemaining() + finished := int64(len(b)) >= sr.logicalRemaining() if finished { - b = b[:sr.LogicalRemaining()] + b = b[:sr.logicalRemaining()] } b0 := b @@ -724,7 +726,7 @@ func (sr *sparseFileReader) Read(b []byte) (n int, err error) { return n, errMissData // Less data in dense file than sparse file case err != nil: return n, err - case sr.LogicalRemaining() == 0 && sr.PhysicalRemaining() > 0: + case sr.logicalRemaining() == 0 && sr.physicalRemaining() > 0: return n, errUnrefData // More data in dense file than sparse file case finished: return n, io.EOF @@ -746,7 +748,7 @@ func (sr *sparseFileReader) WriteTo(w io.Writer) (n int64, err error) { var writeLastByte bool pos0 := sr.pos - for sr.LogicalRemaining() > 0 && !writeLastByte && err == nil { + for sr.logicalRemaining() > 0 && !writeLastByte && err == nil { var nf int64 // Size of fragment holeStart, holeEnd := sr.sp[0].Offset, sr.sp[0].endOffset() if sr.pos < holeStart { // In a data fragment @@ -754,7 +756,7 @@ func (sr *sparseFileReader) WriteTo(w io.Writer) (n int64, err error) { nf, err = io.CopyN(ws, sr.fr, nf) } else { // In a hole fragment nf = holeEnd - sr.pos - if sr.PhysicalRemaining() == 0 { + if sr.physicalRemaining() == 0 { writeLastByte = true nf-- } @@ -779,18 +781,18 @@ func (sr *sparseFileReader) WriteTo(w io.Writer) (n int64, err error) { return n, errMissData // Less data in dense file than sparse file case err != nil: return n, err - case sr.LogicalRemaining() == 0 && sr.PhysicalRemaining() > 0: + case sr.logicalRemaining() == 0 && sr.physicalRemaining() > 0: return n, errUnrefData // More data in dense file than sparse file default: return n, nil } } -func (sr sparseFileReader) LogicalRemaining() int64 { +func (sr sparseFileReader) logicalRemaining() int64 { return sr.sp[len(sr.sp)-1].endOffset() - sr.pos } -func (sr sparseFileReader) PhysicalRemaining() int64 { - return sr.fr.PhysicalRemaining() +func (sr sparseFileReader) physicalRemaining() int64 { + return sr.fr.physicalRemaining() } type zeroReader struct{} diff --git a/src/archive/tar/reader_test.go b/src/archive/tar/reader_test.go index 789ddc1bc0..c31a847ec3 100644 --- a/src/archive/tar/reader_test.go +++ b/src/archive/tar/reader_test.go @@ -1021,12 +1021,12 @@ func TestParsePAX(t *testing.T) { func TestReadOldGNUSparseMap(t *testing.T) { populateSparseMap := func(sa sparseArray, sps []string) []string { - for i := 0; len(sps) > 0 && i < sa.MaxEntries(); i++ { - copy(sa.Entry(i), sps[0]) + for i := 0; len(sps) > 0 && i < sa.maxEntries(); i++ { + copy(sa.entry(i), sps[0]) sps = sps[1:] } if len(sps) > 0 { - copy(sa.IsExtended(), "\x80") + copy(sa.isExtended(), "\x80") } return sps } @@ -1034,19 +1034,19 @@ func TestReadOldGNUSparseMap(t *testing.T) { makeInput := func(format Format, size string, sps ...string) (out []byte) { // Write the initial GNU header. var blk block - gnu := blk.GNU() - sparse := gnu.Sparse() - copy(gnu.RealSize(), size) + gnu := blk.toGNU() + sparse := gnu.sparse() + copy(gnu.realSize(), size) sps = populateSparseMap(sparse, sps) if format != FormatUnknown { - blk.SetFormat(format) + blk.setFormat(format) } out = append(out, blk[:]...) // Write extended sparse blocks. for len(sps) > 0 { var blk block - sps = populateSparseMap(blk.Sparse(), sps) + sps = populateSparseMap(blk.toSparse(), sps) out = append(out, blk[:]...) } return out @@ -1359,7 +1359,7 @@ func TestFileReader(t *testing.T) { wantCnt int64 wantErr error } - testRemaining struct { // LogicalRemaining() == wantLCnt, PhysicalRemaining() == wantPCnt + testRemaining struct { // logicalRemaining() == wantLCnt, physicalRemaining() == wantPCnt wantLCnt int64 wantPCnt int64 } @@ -1596,11 +1596,11 @@ func TestFileReader(t *testing.T) { t.Errorf("test %d.%d, expected %d more operations", i, j, len(f.ops)) } case testRemaining: - if got := fr.LogicalRemaining(); got != tf.wantLCnt { - t.Errorf("test %d.%d, LogicalRemaining() = %d, want %d", i, j, got, tf.wantLCnt) + if got := fr.logicalRemaining(); got != tf.wantLCnt { + t.Errorf("test %d.%d, logicalRemaining() = %d, want %d", i, j, got, tf.wantLCnt) } - if got := fr.PhysicalRemaining(); got != tf.wantPCnt { - t.Errorf("test %d.%d, PhysicalRemaining() = %d, want %d", i, j, got, tf.wantPCnt) + if got := fr.physicalRemaining(); got != tf.wantPCnt { + t.Errorf("test %d.%d, physicalRemaining() = %d, want %d", i, j, got, tf.wantPCnt) } default: t.Fatalf("test %d.%d, unknown test operation: %T", i, j, tf) diff --git a/src/archive/tar/writer.go b/src/archive/tar/writer.go index e80498d03e..3729f7e82c 100644 --- a/src/archive/tar/writer.go +++ b/src/archive/tar/writer.go @@ -50,7 +50,7 @@ func (tw *Writer) Flush() error { if tw.err != nil { return tw.err } - if nb := tw.curr.LogicalRemaining(); nb > 0 { + if nb := tw.curr.logicalRemaining(); nb > 0 { return fmt.Errorf("archive/tar: missed writing %d bytes", nb) } if _, tw.err = tw.w.Write(zeroBlock[:tw.pad]); tw.err != nil { @@ -117,8 +117,8 @@ func (tw *Writer) writeUSTARHeader(hdr *Header) error { // Pack the main header. var f formatter blk := tw.templateV7Plus(hdr, f.formatString, f.formatOctal) - f.formatString(blk.USTAR().Prefix(), namePrefix) - blk.SetFormat(FormatUSTAR) + f.formatString(blk.toUSTAR().prefix(), namePrefix) + blk.setFormat(FormatUSTAR) if f.err != nil { return f.err // Should never happen since header is validated } @@ -208,7 +208,7 @@ func (tw *Writer) writePAXHeader(hdr *Header, paxHdrs map[string]string) error { var f formatter // Ignore errors since they are expected fmtStr := func(b []byte, s string) { f.formatString(b, toASCII(s)) } blk := tw.templateV7Plus(hdr, fmtStr, f.formatOctal) - blk.SetFormat(FormatPAX) + blk.setFormat(FormatPAX) if err := tw.writeRawHeader(blk, hdr.Size, hdr.Typeflag); err != nil { return err } @@ -250,10 +250,10 @@ func (tw *Writer) writeGNUHeader(hdr *Header) error { var spb []byte blk := tw.templateV7Plus(hdr, f.formatString, f.formatNumeric) if !hdr.AccessTime.IsZero() { - f.formatNumeric(blk.GNU().AccessTime(), hdr.AccessTime.Unix()) + f.formatNumeric(blk.toGNU().accessTime(), hdr.AccessTime.Unix()) } if !hdr.ChangeTime.IsZero() { - f.formatNumeric(blk.GNU().ChangeTime(), hdr.ChangeTime.Unix()) + f.formatNumeric(blk.toGNU().changeTime(), hdr.ChangeTime.Unix()) } // TODO(dsnet): Re-enable this when adding sparse support. // See https://golang.org/issue/22735 @@ -293,7 +293,7 @@ func (tw *Writer) writeGNUHeader(hdr *Header) error { f.formatNumeric(blk.GNU().RealSize(), realSize) } */ - blk.SetFormat(FormatGNU) + blk.setFormat(FormatGNU) if err := tw.writeRawHeader(blk, hdr.Size, hdr.Typeflag); err != nil { return err } @@ -321,28 +321,28 @@ type ( // The block returned is only valid until the next call to // templateV7Plus or writeRawFile. func (tw *Writer) templateV7Plus(hdr *Header, fmtStr stringFormatter, fmtNum numberFormatter) *block { - tw.blk.Reset() + tw.blk.reset() modTime := hdr.ModTime if modTime.IsZero() { modTime = time.Unix(0, 0) } - v7 := tw.blk.V7() - v7.TypeFlag()[0] = hdr.Typeflag - fmtStr(v7.Name(), hdr.Name) - fmtStr(v7.LinkName(), hdr.Linkname) - fmtNum(v7.Mode(), hdr.Mode) - fmtNum(v7.UID(), int64(hdr.Uid)) - fmtNum(v7.GID(), int64(hdr.Gid)) - fmtNum(v7.Size(), hdr.Size) - fmtNum(v7.ModTime(), modTime.Unix()) + v7 := tw.blk.toV7() + v7.typeFlag()[0] = hdr.Typeflag + fmtStr(v7.name(), hdr.Name) + fmtStr(v7.linkName(), hdr.Linkname) + fmtNum(v7.mode(), hdr.Mode) + fmtNum(v7.uid(), int64(hdr.Uid)) + fmtNum(v7.gid(), int64(hdr.Gid)) + fmtNum(v7.size(), hdr.Size) + fmtNum(v7.modTime(), modTime.Unix()) - ustar := tw.blk.USTAR() - fmtStr(ustar.UserName(), hdr.Uname) - fmtStr(ustar.GroupName(), hdr.Gname) - fmtNum(ustar.DevMajor(), hdr.Devmajor) - fmtNum(ustar.DevMinor(), hdr.Devminor) + ustar := tw.blk.toUSTAR() + fmtStr(ustar.userName(), hdr.Uname) + fmtStr(ustar.groupName(), hdr.Gname) + fmtNum(ustar.devMajor(), hdr.Devmajor) + fmtNum(ustar.devMinor(), hdr.Devminor) return &tw.blk } @@ -351,7 +351,7 @@ func (tw *Writer) templateV7Plus(hdr *Header, fmtStr stringFormatter, fmtNum num // It uses format to encode the header format and will write data as the body. // It uses default values for all of the other fields (as BSD and GNU tar does). func (tw *Writer) writeRawFile(name, data string, flag byte, format Format) error { - tw.blk.Reset() + tw.blk.reset() // Best effort for the filename. name = toASCII(name) @@ -361,15 +361,15 @@ func (tw *Writer) writeRawFile(name, data string, flag byte, format Format) erro name = strings.TrimRight(name, "/") var f formatter - v7 := tw.blk.V7() - v7.TypeFlag()[0] = flag - f.formatString(v7.Name(), name) - f.formatOctal(v7.Mode(), 0) - f.formatOctal(v7.UID(), 0) - f.formatOctal(v7.GID(), 0) - f.formatOctal(v7.Size(), int64(len(data))) // Must be < 8GiB - f.formatOctal(v7.ModTime(), 0) - tw.blk.SetFormat(format) + v7 := tw.blk.toV7() + v7.typeFlag()[0] = flag + f.formatString(v7.name(), name) + f.formatOctal(v7.mode(), 0) + f.formatOctal(v7.uid(), 0) + f.formatOctal(v7.gid(), 0) + f.formatOctal(v7.size(), int64(len(data))) // Must be < 8GiB + f.formatOctal(v7.modTime(), 0) + tw.blk.setFormat(format) if f.err != nil { return f.err // Only occurs if size condition is violated } @@ -511,10 +511,13 @@ func (fw *regFileWriter) ReadFrom(r io.Reader) (int64, error) { return io.Copy(struct{ io.Writer }{fw}, r) } -func (fw regFileWriter) LogicalRemaining() int64 { +// logicalRemaining implements fileState.logicalRemaining. +func (fw regFileWriter) logicalRemaining() int64 { return fw.nb } -func (fw regFileWriter) PhysicalRemaining() int64 { + +// logicalRemaining implements fileState.physicalRemaining. +func (fw regFileWriter) physicalRemaining() int64 { return fw.nb } @@ -526,9 +529,9 @@ type sparseFileWriter struct { } func (sw *sparseFileWriter) Write(b []byte) (n int, err error) { - overwrite := int64(len(b)) > sw.LogicalRemaining() + overwrite := int64(len(b)) > sw.logicalRemaining() if overwrite { - b = b[:sw.LogicalRemaining()] + b = b[:sw.logicalRemaining()] } b0 := b @@ -556,7 +559,7 @@ func (sw *sparseFileWriter) Write(b []byte) (n int, err error) { return n, errMissData // Not possible; implies bug in validation logic case err != nil: return n, err - case sw.LogicalRemaining() == 0 && sw.PhysicalRemaining() > 0: + case sw.logicalRemaining() == 0 && sw.physicalRemaining() > 0: return n, errUnrefData // Not possible; implies bug in validation logic case overwrite: return n, ErrWriteTooLong @@ -578,12 +581,12 @@ func (sw *sparseFileWriter) ReadFrom(r io.Reader) (n int64, err error) { var readLastByte bool pos0 := sw.pos - for sw.LogicalRemaining() > 0 && !readLastByte && err == nil { + for sw.logicalRemaining() > 0 && !readLastByte && err == nil { var nf int64 // Size of fragment dataStart, dataEnd := sw.sp[0].Offset, sw.sp[0].endOffset() if sw.pos < dataStart { // In a hole fragment nf = dataStart - sw.pos - if sw.PhysicalRemaining() == 0 { + if sw.physicalRemaining() == 0 { readLastByte = true nf-- } @@ -613,18 +616,18 @@ func (sw *sparseFileWriter) ReadFrom(r io.Reader) (n int64, err error) { return n, errMissData // Not possible; implies bug in validation logic case err != nil: return n, err - case sw.LogicalRemaining() == 0 && sw.PhysicalRemaining() > 0: + case sw.logicalRemaining() == 0 && sw.physicalRemaining() > 0: return n, errUnrefData // Not possible; implies bug in validation logic default: return n, ensureEOF(rs) } } -func (sw sparseFileWriter) LogicalRemaining() int64 { +func (sw sparseFileWriter) logicalRemaining() int64 { return sw.sp[len(sw.sp)-1].endOffset() - sw.pos } -func (sw sparseFileWriter) PhysicalRemaining() int64 { - return sw.fw.PhysicalRemaining() +func (sw sparseFileWriter) physicalRemaining() int64 { + return sw.fw.physicalRemaining() } // zeroWriter may only be written with NULs, otherwise it returns errWriteHole. diff --git a/src/archive/tar/writer_test.go b/src/archive/tar/writer_test.go index a00f02d8fa..43f2f5976c 100644 --- a/src/archive/tar/writer_test.go +++ b/src/archive/tar/writer_test.go @@ -987,11 +987,11 @@ func TestIssue12594(t *testing.T) { // The prefix field should never appear in the GNU format. var blk block copy(blk[:], b.Bytes()) - prefix := string(blk.USTAR().Prefix()) + prefix := string(blk.toUSTAR().prefix()) if i := strings.IndexByte(prefix, 0); i >= 0 { prefix = prefix[:i] // Truncate at the NUL terminator } - if blk.GetFormat() == FormatGNU && len(prefix) > 0 && strings.HasPrefix(name, prefix) { + if blk.getFormat() == FormatGNU && len(prefix) > 0 && strings.HasPrefix(name, prefix) { t.Errorf("test %d, found prefix in GNU format: %s", i, prefix) } @@ -1029,7 +1029,7 @@ func TestFileWriter(t *testing.T) { wantCnt int64 wantErr error } - testRemaining struct { // LogicalRemaining() == wantLCnt, PhysicalRemaining() == wantPCnt + testRemaining struct { // logicalRemaining() == wantLCnt, physicalRemaining() == wantPCnt wantLCnt int64 wantPCnt int64 } @@ -1292,11 +1292,11 @@ func TestFileWriter(t *testing.T) { t.Errorf("test %d.%d, expected %d more operations", i, j, len(f.ops)) } case testRemaining: - if got := fw.LogicalRemaining(); got != tf.wantLCnt { - t.Errorf("test %d.%d, LogicalRemaining() = %d, want %d", i, j, got, tf.wantLCnt) + if got := fw.logicalRemaining(); got != tf.wantLCnt { + t.Errorf("test %d.%d, logicalRemaining() = %d, want %d", i, j, got, tf.wantLCnt) } - if got := fw.PhysicalRemaining(); got != tf.wantPCnt { - t.Errorf("test %d.%d, PhysicalRemaining() = %d, want %d", i, j, got, tf.wantPCnt) + if got := fw.physicalRemaining(); got != tf.wantPCnt { + t.Errorf("test %d.%d, physicalRemaining() = %d, want %d", i, j, got, tf.wantPCnt) } default: t.Fatalf("test %d.%d, unknown test operation: %T", i, j, tf) -- GitLab From 3bdc1799d6ce441d7a972faf1452e34b6dce0826 Mon Sep 17 00:00:00 2001 From: Roger Peppe Date: Wed, 11 Aug 2021 12:14:41 +0100 Subject: [PATCH 0766/2500] io: unexport internal methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The methods on the pipe type don't need to be exported. Doing so sets a bad precedent that it's OK to export methods to indicate an internal public API. That's not a good idea in general, because exported methods increase cognitive load when reading code: the reader needs to consider whether the exported method might be used via some external interface or reflection. Change-Id: Ib13f1b3f9fe0ff251628f31b776182a0953268ee Reviewed-on: https://go-review.googlesource.com/c/go/+/341409 Reviewed-by: Daniel Martí Reviewed-by: Joe Tsai Reviewed-by: Joe Tsai Trust: Daniel Martí --- src/io/pipe.go | 50 ++++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/src/io/pipe.go b/src/io/pipe.go index b5343bb6b7..2724e3f7ab 100644 --- a/src/io/pipe.go +++ b/src/io/pipe.go @@ -47,7 +47,7 @@ type pipe struct { werr onceError } -func (p *pipe) Read(b []byte) (n int, err error) { +func (p *pipe) read(b []byte) (n int, err error) { select { case <-p.done: return 0, p.readCloseError() @@ -64,15 +64,7 @@ func (p *pipe) Read(b []byte) (n int, err error) { } } -func (p *pipe) readCloseError() error { - rerr := p.rerr.Load() - if werr := p.werr.Load(); rerr == nil && werr != nil { - return werr - } - return ErrClosedPipe -} - -func (p *pipe) CloseRead(err error) error { +func (p *pipe) closeRead(err error) error { if err == nil { err = ErrClosedPipe } @@ -81,7 +73,7 @@ func (p *pipe) CloseRead(err error) error { return nil } -func (p *pipe) Write(b []byte) (n int, err error) { +func (p *pipe) write(b []byte) (n int, err error) { select { case <-p.done: return 0, p.writeCloseError() @@ -103,15 +95,7 @@ func (p *pipe) Write(b []byte) (n int, err error) { return n, nil } -func (p *pipe) writeCloseError() error { - werr := p.werr.Load() - if rerr := p.rerr.Load(); werr == nil && rerr != nil { - return rerr - } - return ErrClosedPipe -} - -func (p *pipe) CloseWrite(err error) error { +func (p *pipe) closeWrite(err error) error { if err == nil { err = EOF } @@ -120,6 +104,24 @@ func (p *pipe) CloseWrite(err error) error { return nil } +// readCloseError is considered internal to the pipe type. +func (p *pipe) readCloseError() error { + rerr := p.rerr.Load() + if werr := p.werr.Load(); rerr == nil && werr != nil { + return werr + } + return ErrClosedPipe +} + +// writeCloseError is considered internal to the pipe type. +func (p *pipe) writeCloseError() error { + werr := p.werr.Load() + if rerr := p.rerr.Load(); werr == nil && rerr != nil { + return rerr + } + return ErrClosedPipe +} + // A PipeReader is the read half of a pipe. type PipeReader struct { p *pipe @@ -131,7 +133,7 @@ type PipeReader struct { // If the write end is closed with an error, that error is // returned as err; otherwise err is EOF. func (r *PipeReader) Read(data []byte) (n int, err error) { - return r.p.Read(data) + return r.p.read(data) } // Close closes the reader; subsequent writes to the @@ -146,7 +148,7 @@ func (r *PipeReader) Close() error { // CloseWithError never overwrites the previous error if it exists // and always returns nil. func (r *PipeReader) CloseWithError(err error) error { - return r.p.CloseRead(err) + return r.p.closeRead(err) } // A PipeWriter is the write half of a pipe. @@ -160,7 +162,7 @@ type PipeWriter struct { // If the read end is closed with an error, that err is // returned as err; otherwise err is ErrClosedPipe. func (w *PipeWriter) Write(data []byte) (n int, err error) { - return w.p.Write(data) + return w.p.write(data) } // Close closes the writer; subsequent reads from the @@ -176,7 +178,7 @@ func (w *PipeWriter) Close() error { // CloseWithError never overwrites the previous error if it exists // and always returns nil. func (w *PipeWriter) CloseWithError(err error) error { - return w.p.CloseWrite(err) + return w.p.closeWrite(err) } // Pipe creates a synchronous in-memory pipe. -- GitLab From 69d8fbec7ab74b3b0f8b689a9a251bdf621936aa Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Fri, 13 Aug 2021 15:52:12 -0400 Subject: [PATCH 0767/2500] cmd/compile/internal/types2: return an error from Instantiate Change Instantiate to be a function (not a method) and return an error. Introduce an ArgumentError type to report information about which type argument led to an error during verification. This resolves a few concerns with the current API: - The Checker method set was previously just Files. It is somewhat odd to add an additional method for instantiation. Passing the checker as an argument seems cleaner. - pos, posList, and verify were bound together. In cases where no verification is required, the call site was somewhat cluttered. - Callers will likely want to access structured information about why type information is invalid, and also may not have access to position information. Returning an argument index solves both these problems; if callers want to associate errors with an argument position, they can do this via the resulting index. We may want to make the first argument an opaque environment rather than a Checker. Change-Id: I3bc56d205c13d832b538401a4c91d3917c041225 Reviewed-on: https://go-review.googlesource.com/c/go/+/342152 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/importer/iimport.go | 8 +- src/cmd/compile/internal/noder/reader2.go | 3 +- src/cmd/compile/internal/types2/api.go | 12 + src/cmd/compile/internal/types2/api_test.go | 39 ++- src/cmd/compile/internal/types2/call.go | 4 +- .../compile/internal/types2/instantiate.go | 225 ++++++++++-------- src/cmd/compile/internal/types2/named.go | 32 +-- src/cmd/compile/internal/types2/subst.go | 11 +- src/cmd/compile/internal/types2/typexpr.go | 2 +- 9 files changed, 207 insertions(+), 129 deletions(-) diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index a317dfc34a..ac5ec7c8f2 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -652,7 +652,9 @@ func (r *importReader) doType(base *types2.Named) types2.Type { if r.p.exportVersion < iexportVersionGenerics { errorf("unexpected instantiation type") } - pos := r.pos() + // pos does not matter for instances: they are positioned on the original + // type. + _ = r.pos() len := r.uint64() targs := make([]types2.Type, len) for i := range targs { @@ -661,8 +663,8 @@ func (r *importReader) doType(base *types2.Named) types2.Type { baseType := r.typ() // The imported instantiated type doesn't include any methods, so // we must always use the methods of the base (orig) type. - var check *types2.Checker // TODO provide a non-nil *Checker - t := check.Instantiate(pos, baseType, targs, nil, false) + // TODO provide a non-nil *Checker + t, _ := types2.Instantiate(nil, baseType, targs, false) return t case unionType: diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index 97ea4fcb76..22c742ab25 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -229,7 +229,8 @@ func (r *reader2) doTyp() (res types2.Type) { obj, targs := r.obj() name := obj.(*types2.TypeName) if len(targs) != 0 { - return r.p.check.Instantiate(syntax.Pos{}, name.Type(), targs, nil, false) + t, _ := types2.Instantiate(r.p.check, name.Type(), targs, false) + return t } return name.Type() diff --git a/src/cmd/compile/internal/types2/api.go b/src/cmd/compile/internal/types2/api.go index ae4fb6ad10..f268508825 100644 --- a/src/cmd/compile/internal/types2/api.go +++ b/src/cmd/compile/internal/types2/api.go @@ -55,6 +55,18 @@ func (err Error) FullError() string { return fmt.Sprintf("%s: %s", err.Pos, err.Full) } +// An ArgumentError holds an error that is associated with an argument. +type ArgumentError struct { + index int + error +} + +// Index returns the positional index of the argument associated with the +// error. +func (e ArgumentError) Index() int { + return e.index +} + // An Importer resolves import paths to Packages. // // CAUTION: This interface does not support the import of locally diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index be05d06fd0..d6a2eb4eb3 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -1871,8 +1871,10 @@ func TestInstantiate(t *testing.T) { // instantiation should succeed (no endless recursion) // even with a nil *Checker - var check *Checker - res := check.Instantiate(nopos, T, []Type{Typ[Int]}, nil, false) + res, err := Instantiate(nil, T, []Type{Typ[Int]}, false) + if err != nil { + t.Fatal(err) + } // instantiated type should point to itself if p := res.Underlying().(*Pointer).Elem(); p != res { @@ -1880,6 +1882,39 @@ func TestInstantiate(t *testing.T) { } } +func TestInstantiateErrors(t *testing.T) { + tests := []struct { + src string // by convention, T must be the type being instantiated + targs []Type + wantAt int // -1 indicates no error + }{ + {"type T[P interface{~string}] int", []Type{Typ[Int]}, 0}, + {"type T[P1 interface{int}, P2 interface{~string}] int", []Type{Typ[Int], Typ[Int]}, 1}, + {"type T[P1 any, P2 interface{~[]P1}] int", []Type{Typ[Int], NewSlice(Typ[String])}, 1}, + {"type T[P1 interface{~[]P2}, P2 any] int", []Type{NewSlice(Typ[String]), Typ[Int]}, 0}, + } + + for _, test := range tests { + src := genericPkg + "p; " + test.src + pkg, err := pkgFor(".", src, nil) + if err != nil { + t.Fatal(err) + } + + T := pkg.Scope().Lookup("T").Type().(*Named) + + _, err = Instantiate(nil, T, test.targs, true) + if err == nil { + t.Fatalf("Instantiate(%v, %v) returned nil error, want non-nil", T, test.targs) + } + + gotAt := err.(ArgumentError).Index() + if gotAt != test.wantAt { + t.Errorf("Instantate(%v, %v): error at index %d, want index %d", T, test.targs, gotAt, test.wantAt) + } + } +} + func TestInstanceIdentity(t *testing.T) { imports := make(testImporter) conf := Config{Importer: imports} diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 94bcc4870b..538fdc0fb7 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -56,7 +56,7 @@ func (check *Checker) funcInst(x *operand, inst *syntax.IndexExpr) { } // instantiate function signature - res := check.Instantiate(x.Pos(), sig, targs, poslist, true).(*Signature) + res := check.instantiate(x.Pos(), sig, targs, poslist).(*Signature) assert(res.TParams().Len() == 0) // signature is not generic anymore if inferred { check.recordInferred(inst, targs, res) @@ -326,7 +326,7 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T } // compute result signature - rsig = check.Instantiate(call.Pos(), sig, targs, nil, true).(*Signature) + rsig = check.instantiate(call.Pos(), sig, targs, nil).(*Signature) assert(rsig.TParams().Len() == 0) // signature is not generic anymore check.recordInferred(call, targs, rsig) diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index ab51d062c5..e0d889aa85 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -13,26 +13,124 @@ import ( "fmt" ) -// Instantiate instantiates the type typ with the given type arguments -// targs. To check type constraint satisfaction, verify must be set. -// pos and posList correspond to the instantiation and type argument -// positions respectively; posList may be nil or shorter than the number -// of type arguments provided. -// typ must be a *Named or a *Signature type, and its number of type -// parameters must match the number of provided type arguments. -// The receiver (check) may be nil if and only if verify is not set. -// The result is a new, instantiated (not generic) type of the same kind -// (either a *Named or a *Signature). -// Any methods attached to a *Named are simply copied; they are not -// instantiated. -func (check *Checker) Instantiate(pos syntax.Pos, typ Type, targs []Type, posList []syntax.Pos, verify bool) (res Type) { +// Instantiate instantiates the type typ with the given type arguments targs. +// typ must be a *Named or a *Signature type, and its number of type parameters +// must match the number of provided type arguments. The result is a new, +// instantiated (not parameterized) type of the same kind (either a *Named or a +// *Signature). Any methods attached to a *Named are simply copied; they are +// not instantiated. +// +// If check is non-nil, it will be used to de-dupe the instance against +// previous instances with the same identity. +// +// If verify is set and constraint satisfaction fails, the returned error may +// be of dynamic type ArgumentError indicating which type argument did not +// satisfy its corresponding type parameter constraint, and why. +// +// TODO(rfindley): change this function to also return an error if lengths of +// tparams and targs do not match. +func Instantiate(check *Checker, typ Type, targs []Type, validate bool) (Type, error) { + inst := check.instance(nopos, typ, targs) + + var err error + if validate { + var tparams []*TypeName + switch t := typ.(type) { + case *Named: + tparams = t.TParams().list() + case *Signature: + tparams = t.TParams().list() + } + if i, err := check.verify(nopos, tparams, targs); err != nil { + return inst, ArgumentError{i, err} + } + } + + return inst, err +} + +// instantiate creates an instance and defers verification of constraints to +// later in the type checking pass. For Named types the resulting instance will +// be unexpanded. +func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, posList []syntax.Pos) (res Type) { + if check != nil && check.conf.Trace { + check.trace(pos, "-- instantiating %s with %s", typ, typeListString(targs)) + check.indent++ + defer func() { + check.indent-- + var under Type + if res != nil { + // Calling under() here may lead to endless instantiations. + // Test case: type T[P any] T[P] + // TODO(gri) investigate if that's a bug or to be expected. + under = safeUnderlying(res) + } + check.trace(pos, "=> %s (under = %s)", res, under) + }() + } + + assert(check != nil) + inst := check.instance(pos, typ, targs) + + assert(len(posList) <= len(targs)) + check.later(func() { + // Collect tparams again because lazily loaded *Named types may not have + // had tparams set up above. + var tparams []*TypeName + switch t := typ.(type) { + case *Named: + tparams = t.TParams().list() + case *Signature: + tparams = t.TParams().list() + } + // Avoid duplicate errors; instantiate will have complained if tparams + // and targs do not have the same length. + if len(tparams) == len(targs) { + if i, err := check.verify(pos, tparams, targs); err != nil { + // best position for error reporting + pos := pos + if i < len(posList) { + pos = posList[i] + } + check.softErrorf(pos, err.Error()) + } + } + }) + return inst +} + +// instance creates a type or function instance using the given original type +// typ and arguments targs. For Named types the resulting instance will be +// unexpanded. +func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type) (res Type) { // TODO(gri) What is better here: work with TypeParams, or work with TypeNames? - var inst Type switch t := typ.(type) { case *Named: - inst = check.instantiateLazy(pos, t, targs) + h := instantiatedHash(t, targs) + if check != nil { + // typ may already have been instantiated with identical type arguments. In + // that case, re-use the existing instance. + if named := check.typMap[h]; named != nil { + return named + } + } + + tname := NewTypeName(pos, t.obj.pkg, t.obj.name, nil) + named := check.newNamed(tname, t, nil, nil, nil) // methods and tparams are set when named is loaded + named.targs = targs + named.instance = &instance{pos} + if check != nil { + check.typMap[h] = named + } + res = named case *Signature: - tparams := t.TParams().list() + tparams := t.TParams() + if !check.validateTArgLen(pos, tparams, targs) { + return Typ[Invalid] + } + if tparams.Len() == 0 { + return typ // nothing to do (minor optimization) + } defer func() { // If we had an unexpected failure somewhere don't panic below when // asserting res.(*Signature). Check for *Signature in case Typ[Invalid] @@ -51,100 +149,27 @@ func (check *Checker) Instantiate(pos syntax.Pos, typ Type, targs []Type, posLis // anymore; we need to set tparams to nil. res.(*Signature).tparams = nil }() - inst = check.instantiate(pos, typ, tparams, targs, nil) + res = check.subst(pos, typ, makeSubstMap(tparams.list(), targs), nil) default: // only types and functions can be generic panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } - - if verify { - if check == nil { - panic("cannot have nil Checker if verifying constraints") - } - assert(len(posList) <= len(targs)) - check.later(func() { - // Collect tparams again because lazily loaded *Named types may not have - // had tparams set up above. - var tparams []*TypeName - switch t := typ.(type) { - case *Named: - tparams = t.TParams().list() - case *Signature: - tparams = t.TParams().list() - } - // Avoid duplicate errors; instantiate will have complained if tparams - // and targs do not have the same length. - if len(tparams) == len(targs) { - if i, err := check.verify(pos, tparams, targs); err != nil { - // best position for error reporting - pos := pos - if i < len(posList) { - pos = posList[i] - } - check.softErrorf(pos, err.Error()) - } - } - }) - } - - return inst + return res } -func (check *Checker) instantiate(pos syntax.Pos, typ Type, tparams []*TypeName, targs []Type, typMap map[string]*Named) (res Type) { - // the number of supplied types must match the number of type parameters - if len(targs) != len(tparams) { +// validateTArgLen verifies that the length of targs and tparams matches, +// reporting an error if not. If validation fails and check is nil, +// validateTArgLen panics. +func (check *Checker) validateTArgLen(pos syntax.Pos, tparams *TParamList, targs []Type) bool { + if len(targs) != tparams.Len() { // TODO(gri) provide better error message if check != nil { - check.errorf(pos, "got %d arguments but %d type parameters", len(targs), len(tparams)) - return Typ[Invalid] - } - panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, len(targs), len(tparams))) - } - - if check != nil && check.conf.Trace { - check.trace(pos, "-- instantiating %s with %s", typ, typeListString(targs)) - check.indent++ - defer func() { - check.indent-- - var under Type - if res != nil { - // Calling under() here may lead to endless instantiations. - // Test case: type T[P any] T[P] - // TODO(gri) investigate if that's a bug or to be expected. - under = safeUnderlying(res) - } - check.trace(pos, "=> %s (under = %s)", res, under) - }() - } - - if len(tparams) == 0 { - return typ // nothing to do (minor optimization) - } - - return check.subst(pos, typ, makeSubstMap(tparams, targs), typMap) -} - -// instantiateLazy avoids actually instantiating the type until needed. typ -// must be a *Named type. -func (check *Checker) instantiateLazy(pos syntax.Pos, orig *Named, targs []Type) Type { - h := instantiatedHash(orig, targs) - if check != nil { - // typ may already have been instantiated with identical type arguments. In - // that case, re-use the existing instance. - if named := check.typMap[h]; named != nil { - return named + check.errorf(pos, "got %d arguments but %d type parameters", len(targs), tparams.Len()) + return false } + panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, len(targs), tparams.Len())) } - - tname := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil) - named := check.newNamed(tname, orig, nil, nil, nil) // methods and tparams are set when named is loaded - named.targs = targs - named.instance = &instance{pos} - if check != nil { - check.typMap[h] = named - } - - return named + return true } func (check *Checker) verify(pos syntax.Pos, tparams []*TypeName, targs []Type) (int, error) { diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index 97239414f6..87b5716f7c 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -258,22 +258,26 @@ func (n *Named) expand(typMap map[string]*Named) *Named { // tparams. This is done implicitly by the call to n.TParams, but making it // explicit is harmless: load is idempotent. n.load() - if typMap == nil { - if n.check != nil { - typMap = n.check.typMap - } else { - // If we're instantiating lazily, we might be outside the scope of a - // type-checking pass. In that case we won't have a pre-existing - // typMap, but don't want to create a duplicate of the current instance - // in the process of expansion. - h := instantiatedHash(n.orig, n.targs) - typMap = map[string]*Named{h: n} + var u Type + if n.check.validateTArgLen(n.instance.pos, n.tparams, n.targs) { + if typMap == nil { + if n.check != nil { + typMap = n.check.typMap + } else { + // If we're instantiating lazily, we might be outside the scope of a + // type-checking pass. In that case we won't have a pre-existing + // typMap, but don't want to create a duplicate of the current instance + // in the process of expansion. + h := instantiatedHash(n.orig, n.targs) + typMap = map[string]*Named{h: n} + } } + u = n.check.subst(n.instance.pos, n.orig.underlying, makeSubstMap(n.TParams().list(), n.targs), typMap) + } else { + u = Typ[Invalid] } - - inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams().list(), n.targs, typMap) - n.underlying = inst - n.fromRHS = inst + n.underlying = u + n.fromRHS = u n.instance = nil } return n diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 2c0fc6e391..edbbdb4758 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -35,13 +35,12 @@ func (m substMap) lookup(tpar *TypeParam) Type { return tpar } -// subst returns the type typ with its type parameters tpars replaced by -// the corresponding type arguments targs, recursively. -// subst is functional in the sense that it doesn't modify the incoming -// type. If a substitution took place, the result type is different from -// from the incoming type. +// subst returns the type typ with its type parameters tpars replaced by the +// corresponding type arguments targs, recursively. subst doesn't modify the +// incoming type. If a substitution took place, the result type is different +// from from the incoming type. // -// If the given typMap is nil and check is non-nil, check.typMap is used. +// If the given typMap is non-nil, it is used in lieu of check.typMap. func (check *Checker) subst(pos syntax.Pos, typ Type, smap substMap, typMap map[string]*Named) Type { if smap.empty() { return typ diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 4df8ab68a1..241c6d35fe 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -444,7 +444,7 @@ func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def posList[i] = syntax.StartPos(arg) } - typ := check.Instantiate(x.Pos(), base, targs, posList, true) + typ := check.instantiate(x.Pos(), base, targs, posList) def.setUnderlying(typ) // make sure we check instantiation works at least once -- GitLab From 9871726c72af7009aa73be33edfa06a8d9e5965e Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Wed, 18 Aug 2021 09:38:19 -0700 Subject: [PATCH 0768/2500] reflect: add test for invalid conversion Conversion between slices with different element types is not allowed. Previously (1.8 <= goversion <= 1.16), this conversion was allowed if the base types were from different packages and had identical names. Update #47785 Change-Id: I359de5b6fe3ff35bdbf9ab5a13902a0f820cac66 Reviewed-on: https://go-review.googlesource.com/c/go/+/343329 Trust: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/reflect/all_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index 5e5e4c1e60..df79f05807 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -7296,4 +7296,11 @@ func TestConvertibleTo(t *testing.T) { if t1.ConvertibleTo(t2) { t.Fatalf("(%s).ConvertibleTo(%s) = true, want false", t1, t2) } + + t3 := ValueOf([]example1.MyStruct{}).Type() + t4 := ValueOf([]example2.MyStruct{}).Type() + + if t3.ConvertibleTo(t4) { + t.Fatalf("(%s).ConvertibleTo(%s) = true, want false", t3, t4) + } } -- GitLab From 91e2e3b9030440713b59dcc7dd9deae71b18d9fc Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Tue, 8 Jun 2021 19:28:45 +0700 Subject: [PATCH 0769/2500] cmd/compile: prevent duplicated works in WriteRuntimeTypes While processing signatset, the entry is deleted immediately after being pushed to signatslice. Then calling writeType may add the same type to signatset again. That would add more works, though not a big impact to the performace, since when writeType is guarded by s.Siggen() check. Instead, we should keep the entry in signatset, so written type will never be added again. This change does not affect compiler performace, but help debugging issue like one in #46386 easier. Change-Id: Iddafe773885fa21cb7003ba27ddf9554fc3f297d Reviewed-on: https://go-review.googlesource.com/c/go/+/326029 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/reflectdata/reflect.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index b04e4d684f..3db6585894 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -39,8 +39,11 @@ func CountPTabs() int { // runtime interface and reflection data structures var ( - signatmu sync.Mutex // protects signatset and signatslice - signatset = make(map[*types.Type]struct{}) + // protects signatset and signatslice + signatmu sync.Mutex + // Tracking which types need runtime type descriptor + signatset = make(map[*types.Type]struct{}) + // Queue of types wait to be generated runtime type descriptor signatslice []*types.Type gcsymmu sync.Mutex // protects gcsymset and gcsymslice @@ -1248,7 +1251,6 @@ func WriteRuntimeTypes() { // Transfer entries to a slice and sort, for reproducible builds. for _, t := range signatslice { signats = append(signats, typeAndStr{t: t, short: types.TypeSymName(t), regular: t.String()}) - delete(signatset, t) } signatslice = signatslice[:0] sort.Sort(typesByString(signats)) -- GitLab From 0e598e7da42aea47b6b9d52c4292f202368d2f19 Mon Sep 17 00:00:00 2001 From: Changkun Ou Date: Thu, 22 Jul 2021 17:50:42 +0200 Subject: [PATCH 0770/2500] syscall: add SyscallN This CL adds a new syscall.SyscallN API. The proposal discussion also suggests the API should not only for Windows but other platforms. However, the existing API set already contain differences between platforms, hence the CL only implements the Windows platform. Moreover, although the API offers variadic parameters, the permitted parameters remains up to a limit, which is selected as 42, and arguably large enough. Fixes #46552 Change-Id: I66b49988a304d9fc178c7cd5de46d0b75e167a4f Reviewed-on: https://go-review.googlesource.com/c/go/+/336550 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Reviewed-by: Matthew Dempsky Trust: Matthew Dempsky Trust: Jason A. Donenfeld --- doc/go1.18.html | 17 ++++++ src/runtime/export_windows_test.go | 2 + src/runtime/sys_windows_amd64.s | 10 +--- src/runtime/syscall_windows.go | 85 ++++++++++++----------------- src/runtime/syscall_windows_test.go | 72 ++++++++++++++---------- src/syscall/dll_windows.go | 62 ++++++--------------- 6 files changed, 115 insertions(+), 133 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 2dc4c1427d..df4b56c49f 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -82,3 +82,20 @@ Do not send CLs removing the interior tags from such phrases.

TODO: complete this section

+ +
syscall
+
+

+ The new function SyscallN + has been introduced for Windows, allowing for calls with arbitrary number + of arguments. As results, + Syscall, + Syscall6, + Syscall9, + Syscall12, + Syscall15, and + Syscall18 are + deprecated in favor of SyscallN. +

+
+
\ No newline at end of file diff --git a/src/runtime/export_windows_test.go b/src/runtime/export_windows_test.go index 536b398fd7..d9cf753463 100644 --- a/src/runtime/export_windows_test.go +++ b/src/runtime/export_windows_test.go @@ -8,6 +8,8 @@ package runtime import "unsafe" +const MaxArgs = maxArgs + var ( TestingWER = &testingWER OsYield = osyield diff --git a/src/runtime/sys_windows_amd64.s b/src/runtime/sys_windows_amd64.s index 6cc5bba2b7..1e4c1d2b61 100644 --- a/src/runtime/sys_windows_amd64.s +++ b/src/runtime/sys_windows_amd64.s @@ -8,10 +8,6 @@ #include "time_windows.h" #include "cgo/abi_amd64.h" -// maxargs should be divisible by 2, as Windows stack -// must be kept 16-byte aligned on syscall entry. -#define maxargs 18 - // void runtime·asmstdcall(void *c); TEXT runtime·asmstdcall(SB),NOSPLIT|NOFRAME,$0 // asmcgocall will put first argument into CX. @@ -24,14 +20,14 @@ TEXT runtime·asmstdcall(SB),NOSPLIT|NOFRAME,$0 MOVQ 0x30(GS), DI MOVL $0, 0x68(DI) - SUBQ $(maxargs*8), SP // room for args + SUBQ $(const_maxArgs*8), SP // room for args // Fast version, do not store args on the stack. CMPL CX, $4 JLE loadregs // Check we have enough room for args. - CMPL CX, $maxargs + CMPL CX, $const_maxArgs JLE 2(PC) INT $3 // not enough room -> crash @@ -59,7 +55,7 @@ loadregs: // Call stdcall function. CALL AX - ADDQ $(maxargs*8), SP + ADDQ $(const_maxArgs*8), SP // Return result. POPQ CX diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go index e872d74e97..da181f2a8d 100644 --- a/src/runtime/syscall_windows.go +++ b/src/runtime/syscall_windows.go @@ -468,84 +468,69 @@ func syscall_getprocaddress(handle uintptr, procname *byte) (outhandle, err uint //go:linkname syscall_Syscall syscall.Syscall //go:nosplit -//go:cgo_unsafe_args func syscall_Syscall(fn, nargs, a1, a2, a3 uintptr) (r1, r2, err uintptr) { - lockOSThread() - defer unlockOSThread() - c := &getg().m.syscall - c.fn = fn - c.n = nargs - c.args = uintptr(noescape(unsafe.Pointer(&a1))) - cgocall(asmstdcallAddr, unsafe.Pointer(c)) - return c.r1, c.r2, c.err + return syscall_SyscallN(fn, a1, a2, a3) } //go:linkname syscall_Syscall6 syscall.Syscall6 //go:nosplit -//go:cgo_unsafe_args func syscall_Syscall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) { - lockOSThread() - defer unlockOSThread() - c := &getg().m.syscall - c.fn = fn - c.n = nargs - c.args = uintptr(noescape(unsafe.Pointer(&a1))) - cgocall(asmstdcallAddr, unsafe.Pointer(c)) - return c.r1, c.r2, c.err + return syscall_SyscallN(fn, a1, a2, a3, a4, a5, a6) } //go:linkname syscall_Syscall9 syscall.Syscall9 //go:nosplit -//go:cgo_unsafe_args func syscall_Syscall9(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) { - lockOSThread() - c := &getg().m.syscall - c.fn = fn - c.n = nargs - c.args = uintptr(noescape(unsafe.Pointer(&a1))) - cgocall(asmstdcallAddr, unsafe.Pointer(c)) - unlockOSThread() - return c.r1, c.r2, c.err + return syscall_SyscallN(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9) } //go:linkname syscall_Syscall12 syscall.Syscall12 //go:nosplit -//go:cgo_unsafe_args func syscall_Syscall12(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 uintptr) (r1, r2, err uintptr) { - lockOSThread() - c := &getg().m.syscall - c.fn = fn - c.n = nargs - c.args = uintptr(noescape(unsafe.Pointer(&a1))) - cgocall(asmstdcallAddr, unsafe.Pointer(c)) - unlockOSThread() - return c.r1, c.r2, c.err + return syscall_SyscallN(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) } //go:linkname syscall_Syscall15 syscall.Syscall15 //go:nosplit -//go:cgo_unsafe_args func syscall_Syscall15(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) { - lockOSThread() - c := &getg().m.syscall - c.fn = fn - c.n = nargs - c.args = uintptr(noescape(unsafe.Pointer(&a1))) - cgocall(asmstdcallAddr, unsafe.Pointer(c)) - unlockOSThread() - return c.r1, c.r2, c.err + return syscall_SyscallN(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) } //go:linkname syscall_Syscall18 syscall.Syscall18 //go:nosplit -//go:cgo_unsafe_args func syscall_Syscall18(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18 uintptr) (r1, r2, err uintptr) { + return syscall_SyscallN(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) +} + +// maxArgs should be divisible by 2, as Windows stack +// must be kept 16-byte aligned on syscall entry. +// +// Although it only permits maximum 42 parameters, it +// is arguably large enough. +const maxArgs = 42 + +//go:linkname syscall_SyscallN syscall.SyscallN +//go:nosplit +func syscall_SyscallN(trap uintptr, args ...uintptr) (r1, r2, err uintptr) { + nargs := len(args) + + // asmstdcall expects it can access the first 4 arguments + // to load them into registers. + var tmp [4]uintptr + switch { + case nargs < 4: + copy(tmp[:], args) + args = tmp[:] + case nargs > maxArgs: + panic("runtime: SyscallN has too many arguments") + } + lockOSThread() + defer unlockOSThread() c := &getg().m.syscall - c.fn = fn - c.n = nargs - c.args = uintptr(noescape(unsafe.Pointer(&a1))) + c.fn = trap + c.n = uintptr(nargs) + c.args = uintptr(noescape(unsafe.Pointer(&args[0]))) cgocall(asmstdcallAddr, unsafe.Pointer(c)) - unlockOSThread() return c.r1, c.r2, c.err } diff --git a/src/runtime/syscall_windows_test.go b/src/runtime/syscall_windows_test.go index e3f772ac4b..235c79f68f 100644 --- a/src/runtime/syscall_windows_test.go +++ b/src/runtime/syscall_windows_test.go @@ -759,7 +759,7 @@ uintptr_t cfunc(callback f, uintptr_t n) { } } -func TestSyscall18(t *testing.T) { +func TestSyscallN(t *testing.T) { if _, err := exec.LookPath("gcc"); err != nil { t.Skip("skipping test: gcc is missing") } @@ -767,40 +767,52 @@ func TestSyscall18(t *testing.T) { t.Skipf("skipping test: GOARCH=%s", runtime.GOARCH) } - const src = ` -#include -#include + for arglen := 0; arglen <= runtime.MaxArgs; arglen++ { + arglen := arglen + t.Run(fmt.Sprintf("arg-%d", arglen), func(t *testing.T) { + t.Parallel() + args := make([]string, arglen) + rets := make([]string, arglen+1) + params := make([]uintptr, arglen) + for i := range args { + args[i] = fmt.Sprintf("int a%d", i) + rets[i] = fmt.Sprintf("(a%d == %d)", i, i) + params[i] = uintptr(i) + } + rets[arglen] = "1" // for arglen == 0 -int cfunc( int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, - int a10, int a11, int a12, int a13, int a14, int a15, int a16, int a17, int a18) { - return 1; -} -` - tmpdir := t.TempDir() + src := fmt.Sprintf(` + #include + #include + int cfunc(%s) { return %s; }`, strings.Join(args, ", "), strings.Join(rets, " && ")) - srcname := "mydll.c" - err := os.WriteFile(filepath.Join(tmpdir, srcname), []byte(src), 0) - if err != nil { - t.Fatal(err) - } - outname := "mydll.dll" - cmd := exec.Command("gcc", "-shared", "-s", "-Werror", "-o", outname, srcname) - cmd.Dir = tmpdir - out, err := cmd.CombinedOutput() - if err != nil { - t.Fatalf("failed to build dll: %v - %v", err, string(out)) - } - dllpath := filepath.Join(tmpdir, outname) + tmpdir := t.TempDir() - dll := syscall.MustLoadDLL(dllpath) - defer dll.Release() + srcname := "mydll.c" + err := os.WriteFile(filepath.Join(tmpdir, srcname), []byte(src), 0) + if err != nil { + t.Fatal(err) + } + outname := "mydll.dll" + cmd := exec.Command("gcc", "-shared", "-s", "-Werror", "-o", outname, srcname) + cmd.Dir = tmpdir + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("failed to build dll: %v\n%s", err, out) + } + dllpath := filepath.Join(tmpdir, outname) - proc := dll.MustFindProc("cfunc") + dll := syscall.MustLoadDLL(dllpath) + defer dll.Release() - // proc.Call() will call Syscall18() internally. - r, _, err := proc.Call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18) - if r != 1 { - t.Errorf("got %d want 1 (err=%v)", r, err) + proc := dll.MustFindProc("cfunc") + + // proc.Call() will call SyscallN() internally. + r, _, err := proc.Call(params...) + if r != 1 { + t.Errorf("got %d want 1 (err=%v)", r, err) + } + }) } } diff --git a/src/syscall/dll_windows.go b/src/syscall/dll_windows.go index 16210ca5b5..34b481d6e6 100644 --- a/src/syscall/dll_windows.go +++ b/src/syscall/dll_windows.go @@ -5,7 +5,6 @@ package syscall import ( - "internal/itoa" "internal/syscall/windows/sysdll" "sync" "sync/atomic" @@ -25,12 +24,25 @@ func (e *DLLError) Unwrap() error { return e.Err } // Implemented in ../runtime/syscall_windows.go. +// Deprecated: Use SyscallN instead. func Syscall(trap, nargs, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) + +// Deprecated: Use SyscallN instead. func Syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) + +// Deprecated: Use SyscallN instead. func Syscall9(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) + +// Deprecated: Use SyscallN instead. func Syscall12(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 uintptr) (r1, r2 uintptr, err Errno) + +// Deprecated: Use SyscallN instead. func Syscall15(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2 uintptr, err Errno) + +// Deprecated: Use SyscallN instead. func Syscall18(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18 uintptr) (r1, r2 uintptr, err Errno) + +func SyscallN(trap uintptr, args ...uintptr) (r1, r2 uintptr, err Errno) func loadlibrary(filename *uint16) (handle uintptr, err Errno) func loadsystemlibrary(filename *uint16, absoluteFilepath *uint16) (handle uintptr, err Errno) func getprocaddress(handle uintptr, procname *uint8) (proc uintptr, err Errno) @@ -160,8 +172,7 @@ func (p *Proc) Addr() uintptr { //go:uintptrescapes -// Call executes procedure p with arguments a. It will panic if more than 18 arguments -// are supplied. +// Call executes procedure p with arguments a. // // The returned error is always non-nil, constructed from the result of GetLastError. // Callers must inspect the primary return value to decide whether an error occurred @@ -175,49 +186,8 @@ func (p *Proc) Addr() uintptr { // values are returned in r2. The return value for C type "float" is // math.Float32frombits(uint32(r2)). For C type "double", it is // math.Float64frombits(uint64(r2)). -func (p *Proc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) { - switch len(a) { - case 0: - return Syscall(p.Addr(), uintptr(len(a)), 0, 0, 0) - case 1: - return Syscall(p.Addr(), uintptr(len(a)), a[0], 0, 0) - case 2: - return Syscall(p.Addr(), uintptr(len(a)), a[0], a[1], 0) - case 3: - return Syscall(p.Addr(), uintptr(len(a)), a[0], a[1], a[2]) - case 4: - return Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], 0, 0) - case 5: - return Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], 0) - case 6: - return Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5]) - case 7: - return Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], 0, 0) - case 8: - return Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], 0) - case 9: - return Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]) - case 10: - return Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], 0, 0) - case 11: - return Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], 0) - case 12: - return Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11]) - case 13: - return Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], 0, 0) - case 14: - return Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], 0) - case 15: - return Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14]) - case 16: - return Syscall18(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], 0, 0) - case 17: - return Syscall18(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], a[16], 0) - case 18: - return Syscall18(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], a[16], a[17]) - default: - panic("Call " + p.Name + " with too many arguments " + itoa.Itoa(len(a)) + ".") - } +func (p *Proc) Call(a ...uintptr) (uintptr, uintptr, error) { + return SyscallN(p.Addr(), a...) } // A LazyDLL implements access to a single DLL. -- GitLab From 65074a40867d9c42a6b89f96b9eeef5a39234846 Mon Sep 17 00:00:00 2001 From: Manlio Perillo Date: Fri, 21 May 2021 22:21:09 +0200 Subject: [PATCH 0771/2500] cmd/dist: remove unused variables Remove the unused defaultcflags and defaultldflags variables. Reported by staticcheck. Change-Id: Icc42f2e670496dbe2ffb26abe25128d8e53e2a6d Reviewed-on: https://go-review.googlesource.com/c/go/+/321931 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Reviewed-by: Tobias Klauser --- src/cmd/dist/build.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go index bec17696f3..33a329e48b 100644 --- a/src/cmd/dist/build.go +++ b/src/cmd/dist/build.go @@ -48,8 +48,6 @@ var ( exe string defaultcc map[string]string defaultcxx map[string]string - defaultcflags string - defaultldflags string defaultpkgconfig string defaultldso string @@ -209,9 +207,6 @@ func xinit() { defaultcc = compilerEnv("CC", cc) defaultcxx = compilerEnv("CXX", cxx) - defaultcflags = os.Getenv("CFLAGS") - defaultldflags = os.Getenv("LDFLAGS") - b = os.Getenv("PKG_CONFIG") if b == "" { b = "pkg-config" -- GitLab From c92c2c9d625ff3957d1c9313183fd0fe8f26984e Mon Sep 17 00:00:00 2001 From: eric fang Date: Mon, 16 Aug 2021 07:25:29 +0000 Subject: [PATCH 0772/2500] cmd/internal/obj/arm64: disable the pre and post index formats for pseudo registers When using the FP or SP pseudo-register to load or store, pre-index and post-index formats are not supported because the RSP and pseudo registers are not allowed to be modified in this way. This CL deletes the related entries in optab and adds a few test cases. Change-Id: Ie30d27d0e7b959242f0e6298b950489669d07989 Reviewed-on: https://go-review.googlesource.com/c/go/+/342770 Reviewed-by: eric fang Reviewed-by: Cherry Mui Run-TryBot: eric fang Trust: Michael Knyszek --- .../asm/internal/asm/testdata/arm64error.s | 4 +++ src/cmd/internal/obj/arm64/asm7.go | 29 +++---------------- 2 files changed, 8 insertions(+), 25 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/arm64error.s b/src/cmd/asm/internal/asm/testdata/arm64error.s index 145074347f..8b12b16680 100644 --- a/src/cmd/asm/internal/asm/testdata/arm64error.s +++ b/src/cmd/asm/internal/asm/testdata/arm64error.s @@ -419,4 +419,8 @@ TEXT errors(SB),$0 ADD R1>>2, RSP, R3 // ERROR "illegal combination" ADDS R2<<3, R3, RSP // ERROR "unexpected SP reference" CMP R1<<5, RSP // ERROR "the left shift amount out of range 0 to 4" + MOVD.P y+8(FP), R1 // ERROR "illegal combination" + MOVD.W x-8(SP), R1 // ERROR "illegal combination" + LDP.P x+8(FP), (R0, R1) // ERROR "illegal combination" + LDP.W x+8(SP), (R0, R1) // ERROR "illegal combination" RET diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go index 050add9aac..8db25cf967 100644 --- a/src/cmd/internal/obj/arm64/asm7.go +++ b/src/cmd/internal/obj/arm64/asm7.go @@ -694,13 +694,12 @@ var optab = []Optab{ {AFMOVD, C_FREG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0}, /* pre/post-indexed/signed-offset load/store register pair - (unscaled, signed 10-bit quad-aligned and long offset) */ + (unscaled, signed 10-bit quad-aligned and long offset). + The pre/post-indexed format only supports OREG cases because + the RSP and pseudo registers are not allowed to be modified + in this way. */ {AFLDPQ, C_NQAUTO_16, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0}, - {AFLDPQ, C_NQAUTO_16, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE}, - {AFLDPQ, C_NQAUTO_16, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST}, {AFLDPQ, C_PQAUTO_16, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0}, - {AFLDPQ, C_PQAUTO_16, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE}, - {AFLDPQ, C_PQAUTO_16, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST}, {AFLDPQ, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0}, {AFLDPQ, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0}, {AFLDPQ, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, 0}, @@ -716,11 +715,7 @@ var optab = []Optab{ {AFLDPQ, C_ADDR, C_NONE, C_NONE, C_PAIR, 88, 12, 0, 0, 0}, {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NQAUTO_16, 67, 4, REGSP, 0, 0}, - {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NQAUTO_16, 67, 4, REGSP, 0, C_XPRE}, - {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NQAUTO_16, 67, 4, REGSP, 0, C_XPOST}, {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_PQAUTO_16, 67, 4, REGSP, 0, 0}, - {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_PQAUTO_16, 67, 4, REGSP, 0, C_XPRE}, - {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_PQAUTO_16, 67, 4, REGSP, 0, C_XPOST}, {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, 0}, {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 8, REGSP, 0, 0}, {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, 0}, @@ -736,11 +731,7 @@ var optab = []Optab{ {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_ADDR, 87, 12, 0, 0, 0}, {ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0}, - {ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE}, - {ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST}, {ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0}, - {ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE}, - {ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST}, {ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0}, {ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0}, {ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, 0}, @@ -756,11 +747,7 @@ var optab = []Optab{ {ALDP, C_ADDR, C_NONE, C_NONE, C_PAIR, 88, 12, 0, 0, 0}, {ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, 0}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, C_XPRE}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, C_XPOST}, {ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, 0}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, C_XPRE}, - {ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, C_XPOST}, {ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, 0}, {ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 8, REGSP, 0, 0}, {ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, 0}, @@ -777,11 +764,7 @@ var optab = []Optab{ // differ from LDP/STP for C_NSAUTO_4/C_PSAUTO_4/C_NSOREG_4/C_PSOREG_4 {ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0}, - {ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE}, - {ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST}, {ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0}, - {ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE}, - {ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST}, {ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0}, {ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0}, {ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, 0}, @@ -797,11 +780,7 @@ var optab = []Optab{ {ALDPW, C_ADDR, C_NONE, C_NONE, C_PAIR, 88, 12, 0, 0, 0}, {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, 0}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, C_XPRE}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, C_XPOST}, {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, 0}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, C_XPRE}, - {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, C_XPOST}, {ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, 0}, {ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 8, REGSP, 0, 0}, {ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, 0}, -- GitLab From e9e0d1ef704c4bba3927522be86937164a61100c Mon Sep 17 00:00:00 2001 From: eric fang Date: Mon, 16 Aug 2021 06:41:15 +0000 Subject: [PATCH 0773/2500] cmd/asm/internal/arch: adds the missing type check for arm64 SXTB extension Operands of memory type do not support SXTB extension. This CL adds this missing check. Change-Id: I1fa438dd314fc8aeb889637079cc67b538e83a89 Reviewed-on: https://go-review.googlesource.com/c/go/+/342769 Reviewed-by: eric fang Reviewed-by: Cherry Mui Run-TryBot: eric fang TryBot-Result: Go Bot Trust: Michael Knyszek --- src/cmd/asm/internal/arch/arm64.go | 31 +++++------------------------- 1 file changed, 5 insertions(+), 26 deletions(-) diff --git a/src/cmd/asm/internal/arch/arm64.go b/src/cmd/asm/internal/arch/arm64.go index 40d828a1fe..24689c5ab1 100644 --- a/src/cmd/asm/internal/arch/arm64.go +++ b/src/cmd/asm/internal/arch/arm64.go @@ -165,27 +165,21 @@ func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, i } } if reg <= arm64.REG_R31 && reg >= arm64.REG_R0 { + if !isAmount { + return errors.New("invalid register extension") + } switch ext { case "UXTB": - if !isAmount { - return errors.New("invalid register extension") - } if a.Type == obj.TYPE_MEM { return errors.New("invalid shift for the register offset addressing mode") } a.Reg = arm64.REG_UXTB + Rnum case "UXTH": - if !isAmount { - return errors.New("invalid register extension") - } if a.Type == obj.TYPE_MEM { return errors.New("invalid shift for the register offset addressing mode") } a.Reg = arm64.REG_UXTH + Rnum case "UXTW": - if !isAmount { - return errors.New("invalid register extension") - } // effective address of memory is a base register value and an offset register value. if a.Type == obj.TYPE_MEM { a.Index = arm64.REG_UXTW + Rnum @@ -193,48 +187,33 @@ func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, i a.Reg = arm64.REG_UXTW + Rnum } case "UXTX": - if !isAmount { - return errors.New("invalid register extension") - } if a.Type == obj.TYPE_MEM { return errors.New("invalid shift for the register offset addressing mode") } a.Reg = arm64.REG_UXTX + Rnum case "SXTB": - if !isAmount { - return errors.New("invalid register extension") + if a.Type == obj.TYPE_MEM { + return errors.New("invalid shift for the register offset addressing mode") } a.Reg = arm64.REG_SXTB + Rnum case "SXTH": - if !isAmount { - return errors.New("invalid register extension") - } if a.Type == obj.TYPE_MEM { return errors.New("invalid shift for the register offset addressing mode") } a.Reg = arm64.REG_SXTH + Rnum case "SXTW": - if !isAmount { - return errors.New("invalid register extension") - } if a.Type == obj.TYPE_MEM { a.Index = arm64.REG_SXTW + Rnum } else { a.Reg = arm64.REG_SXTW + Rnum } case "SXTX": - if !isAmount { - return errors.New("invalid register extension") - } if a.Type == obj.TYPE_MEM { a.Index = arm64.REG_SXTX + Rnum } else { a.Reg = arm64.REG_SXTX + Rnum } case "LSL": - if !isAmount { - return errors.New("invalid register extension") - } a.Index = arm64.REG_LSL + Rnum default: return errors.New("unsupported general register extension type: " + ext) -- GitLab From 303446395d8bfdd05da8c69f1f3f862e7e7a35db Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 19 Aug 2021 17:01:26 +0700 Subject: [PATCH 0774/2500] cmd/compile: use typeAndStr directly in signatslice Currently, we store *types.Type in signatslice, then convert it to typeAndStr during write runtime type process. Instead, we can just store typeAndStr directly in signatslice when adding type to signatset. Not a big win, but simplify the code a bit. Change-Id: Ie1c8cfa5141da32b6ec3ce5844ba150d2765fe90 Reviewed-on: https://go-review.googlesource.com/c/go/+/343529 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Keith Randall --- .../compile/internal/reflectdata/reflect.go | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 3db6585894..3ba8f52541 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -44,7 +44,7 @@ var ( // Tracking which types need runtime type descriptor signatset = make(map[*types.Type]struct{}) // Queue of types wait to be generated runtime type descriptor - signatslice []*types.Type + signatslice []typeAndStr gcsymmu sync.Mutex // protects gcsymset and gcsymslice gcsymset = make(map[*types.Type]struct{}) @@ -1238,21 +1238,16 @@ func NeedRuntimeType(t *types.Type) { } if _, ok := signatset[t]; !ok { signatset[t] = struct{}{} - signatslice = append(signatslice, t) + signatslice = append(signatslice, typeAndStr{t: t, short: types.TypeSymName(t), regular: t.String()}) } } func WriteRuntimeTypes() { - // Process signatset. Use a loop, as writeType adds - // entries to signatset while it is being processed. - signats := make([]typeAndStr, len(signatslice)) + // Process signatslice. Use a loop, as writeType adds + // entries to signatslice while it is being processed. for len(signatslice) > 0 { - signats = signats[:0] - // Transfer entries to a slice and sort, for reproducible builds. - for _, t := range signatslice { - signats = append(signats, typeAndStr{t: t, short: types.TypeSymName(t), regular: t.String()}) - } - signatslice = signatslice[:0] + signats := signatslice + // Sort for reproducible builds. sort.Sort(typesByString(signats)) for _, ts := range signats { t := ts.t @@ -1261,6 +1256,7 @@ func WriteRuntimeTypes() { writeType(types.NewPtr(t)) } } + signatslice = signatslice[len(signats):] } // Emit GC data symbols. -- GitLab From 700743137462471189f58ee85fe64754cd340322 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Thu, 19 Aug 2021 16:36:38 +0200 Subject: [PATCH 0775/2500] crypto/rand, internal/syscall/unix: don't use getentropy on iOS CL 302489 switched crypto/rand to use getentropy on darwin, however this function is not available on iOS. Enable getentropy only on macOS and disable it on iOS. Fixes #47812 Change-Id: Ib7ba5d77346aee87904bb93d60cacc845f5c0089 Reviewed-on: https://go-review.googlesource.com/c/go/+/343609 Trust: Tobias Klauser Run-TryBot: Tobias Klauser Reviewed-by: Brad Fitzpatrick Reviewed-by: Ian Lance Taylor TryBot-Result: Go Bot --- src/crypto/rand/rand_getentropy.go | 4 ++-- src/internal/syscall/unix/getentropy_darwin.go | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/crypto/rand/rand_getentropy.go b/src/crypto/rand/rand_getentropy.go index f82018a495..dd725372ad 100644 --- a/src/crypto/rand/rand_getentropy.go +++ b/src/crypto/rand/rand_getentropy.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build darwin || openbsd -// +build darwin openbsd +//go:build (darwin && !ios) || openbsd +// +build darwin,!ios openbsd package rand diff --git a/src/internal/syscall/unix/getentropy_darwin.go b/src/internal/syscall/unix/getentropy_darwin.go index e1a410a454..c75006bf8b 100644 --- a/src/internal/syscall/unix/getentropy_darwin.go +++ b/src/internal/syscall/unix/getentropy_darwin.go @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin && !ios +// +build darwin,!ios + package unix import ( -- GitLab From bacbc33439b124ffd7392c91a5f5d96eca8c0c0b Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Wed, 18 Aug 2021 11:49:29 -0700 Subject: [PATCH 0776/2500] archive/zip: prevent preallocation check from overflowing If the indicated directory size in the archive header is so large that subtracting it from the archive size overflows a uint64, the check that the indicated number of files in the archive can be effectively bypassed. Prevent this from happening by checking that the indicated directory size is less than the size of the archive. Thanks to the OSS-Fuzz project for discovering this issue and to Emmanuel Odeke for reporting it. Fixes #47801 Fixes CVE-2021-39293 Change-Id: Ifade26b98a40f3b37398ca86bd5252d12394dd24 Reviewed-on: https://go-review.googlesource.com/c/go/+/343434 Trust: Roland Shoemaker Run-TryBot: Roland Shoemaker TryBot-Result: Go Bot Reviewed-by: Russ Cox --- src/archive/zip/reader.go | 2 +- src/archive/zip/reader_test.go | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/archive/zip/reader.go b/src/archive/zip/reader.go index 2d53f4c723..c91a8d00e6 100644 --- a/src/archive/zip/reader.go +++ b/src/archive/zip/reader.go @@ -102,7 +102,7 @@ func (z *Reader) init(r io.ReaderAt, size int64) error { // indicate it contains up to 1 << 128 - 1 files. Since each file has a // header which will be _at least_ 30 bytes we can safely preallocate // if (data size / 30) >= end.directoryRecords. - if (uint64(size)-end.directorySize)/30 >= end.directoryRecords { + if end.directorySize < uint64(size) && (uint64(size)-end.directorySize)/30 >= end.directoryRecords { z.File = make([]*File, 0, end.directoryRecords) } z.Comment = end.comment diff --git a/src/archive/zip/reader_test.go b/src/archive/zip/reader_test.go index 37dafe6c8e..afb03ace24 100644 --- a/src/archive/zip/reader_test.go +++ b/src/archive/zip/reader_test.go @@ -1384,3 +1384,21 @@ func TestCVE202133196(t *testing.T) { t.Errorf("Archive has unexpected number of files, got %d, want 5", len(r.File)) } } + +func TestCVE202139293(t *testing.T) { + // directory size is so large, that the check in Reader.init + // overflows when subtracting from the archive size, causing + // the pre-allocation check to be bypassed. + data := []byte{ + 0x50, 0x4b, 0x06, 0x06, 0x05, 0x06, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x4b, + 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x4b, + 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x50, 0xfe, 0x00, 0xff, 0x00, 0x3a, 0x00, 0x00, 0x00, 0xff, + } + _, err := NewReader(bytes.NewReader(data), int64(len(data))) + if err != ErrFormat { + t.Fatalf("unexpected error, got: %v, want: %v", err, ErrFormat) + } +} -- GitLab From 4d00fcbc4303bca38ecfc1c8a07661089496c1ab Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 16 Aug 2021 15:59:08 -0400 Subject: [PATCH 0777/2500] go/types: clean up panics in instantiation This is a straightforward port of CL 341862 to go/types. Change-Id: I4214c08d2889e2daf40254385656c6beed79571d Reviewed-on: https://go-review.googlesource.com/c/go/+/342487 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer --- src/go/types/instantiate.go | 43 +++++++++++++++++++++---------------- src/go/types/named.go | 9 ++++---- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 8133067229..37184cb0ab 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -53,15 +53,18 @@ func (check *Checker) Instantiate(pos token.Pos, typ Type, targs []Type, posList // only types and functions can be generic panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } + inst := check.instantiate(pos, typ, tparams, targs, nil) - inst := check.instantiate(pos, typ, tparams, targs, posList, nil) - if verify && len(tparams) == len(targs) { - check.verify(pos, tparams, targs, posList) + if verify { + assert(len(posList) <= len(targs)) + if len(tparams) == len(targs) { + check.verify(pos, tparams, targs, posList) + } } return inst } -func (check *Checker) instantiate(pos token.Pos, typ Type, tparams []*TypeName, targs []Type, posList []token.Pos, typMap map[string]*Named) (res Type) { +func (check *Checker) instantiate(pos token.Pos, typ Type, tparams []*TypeName, targs []Type, typMap map[string]*Named) (res Type) { // the number of supplied types must match the number of type parameters if len(targs) != len(tparams) { // TODO(gri) provide better error message @@ -88,8 +91,6 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, tparams []*TypeName, }() } - assert(len(posList) <= len(targs)) - // TODO(gri) What is better here: work with TypeParams, or work with TypeNames? if len(tparams) == 0 { @@ -101,14 +102,21 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, tparams []*TypeName, // instantiateLazy avoids actually instantiating the type until needed. typ // must be a *Named type. -func (check *Checker) instantiateLazy(pos token.Pos, base *Named, targs []Type, posList []token.Pos, verify bool) Type { - if verify && base.TParams().Len() == len(targs) { - // TODO: lift the nil check in verify to here. - check.later(func() { - check.verify(pos, base.tparams.list(), targs, posList) - }) - } - h := instantiatedHash(base, targs) +func (check *Checker) instantiateLazy(pos token.Pos, orig *Named, targs []Type, posList []token.Pos, verify bool) Type { + if verify { + if check == nil { + // Provide a more useful panic instead of panicking at check.later below. + panic("cannot have nil Checker if verifying constraints") + } + assert(len(posList) <= len(targs)) + if orig.TParams().Len() == len(targs) { + check.later(func() { + check.verify(pos, orig.tparams.list(), targs, posList) + }) + } + } + + h := instantiatedHash(orig, targs) if check != nil { // typ may already have been instantiated with identical type arguments. In // that case, re-use the existing instance. @@ -117,10 +125,10 @@ func (check *Checker) instantiateLazy(pos token.Pos, base *Named, targs []Type, } } - tname := NewTypeName(pos, base.obj.pkg, base.obj.name, nil) - named := check.newNamed(tname, base, nil, nil, nil) // methods and tparams are set when named is loaded. + tname := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil) + named := check.newNamed(tname, orig, nil, nil, nil) // methods and tparams are set when named is loaded named.targs = targs - named.instance = &instance{pos, posList} + named.instance = &instance{pos} if check != nil { check.typMap[h] = named @@ -133,7 +141,6 @@ func (check *Checker) verify(pos token.Pos, tparams []*TypeName, targs []Type, p if check == nil { panic("cannot have nil Checker if verifying constraints") } - smap := makeSubstMap(tparams, targs) for i, tname := range tparams { // best position for error reporting diff --git a/src/go/types/named.go b/src/go/types/named.go index 90abd117e2..d621e5ef21 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -248,11 +248,10 @@ func (n *Named) setUnderlying(typ Type) { // instance holds position information for use in lazy instantiation. // -// TODO(rfindley): come up with a better name for this type, now that its usage -// has changed. +// TODO(rfindley): instance is probably unnecessary now. See if it can be +// eliminated. type instance struct { - pos token.Pos // position of type instantiation; for error reporting only - posList []token.Pos // position of each targ; for error reporting only + pos token.Pos // position of type instantiation; for error reporting only } // expand ensures that the underlying type of n is instantiated. @@ -276,7 +275,7 @@ func (n *Named) expand(typMap map[string]*Named) *Named { } } - inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams().list(), n.targs, n.instance.posList, typMap) + inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams().list(), n.targs, typMap) n.underlying = inst n.fromRHS = inst n.instance = nil -- GitLab From e49775e0579891479888a514c82cf6eea123763f Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 16 Aug 2021 16:01:42 -0400 Subject: [PATCH 0778/2500] go/types: consolidate verification logic This is a straightforward port of CL 342149 to go/types. Change-Id: I468c5154b7545b7816bb3f240b8db91e7a1fd3f6 Reviewed-on: https://go-review.googlesource.com/c/go/+/342488 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/instantiate.go | 49 +++++++++++++++++++------------------ src/go/types/typexpr.go | 2 +- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 37184cb0ab..eeb9b03050 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -25,12 +25,12 @@ import ( // Any methods attached to a *Named are simply copied; they are not // instantiated. func (check *Checker) Instantiate(pos token.Pos, typ Type, targs []Type, posList []token.Pos, verify bool) (res Type) { - var tparams []*TypeName + var inst Type switch t := typ.(type) { case *Named: - return check.instantiateLazy(pos, t, targs, posList, verify) + inst = check.instantiateLazy(pos, t, targs) case *Signature: - tparams = t.TParams().list() + tparams := t.TParams().list() defer func() { // If we had an unexpected failure somewhere don't panic below when // asserting res.(*Signature). Check for *Signature in case Typ[Invalid] @@ -49,18 +49,35 @@ func (check *Checker) Instantiate(pos token.Pos, typ Type, targs []Type, posList // anymore; we need to set tparams to nil. res.(*Signature).tparams = nil }() + inst = check.instantiate(pos, typ, tparams, targs, nil) default: // only types and functions can be generic panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } - inst := check.instantiate(pos, typ, tparams, targs, nil) if verify { - assert(len(posList) <= len(targs)) - if len(tparams) == len(targs) { - check.verify(pos, tparams, targs, posList) + if check == nil { + panic("cannot have nil Checker if verifying constraints") } + assert(len(posList) <= len(targs)) + check.later(func() { + // Collect tparams again because lazily loaded *Named types may not have + // had tparams set up above. + var tparams []*TypeName + switch t := typ.(type) { + case *Named: + tparams = t.TParams().list() + case *Signature: + tparams = t.TParams().list() + } + // Avoid duplicate errors; instantiate will have complained if tparams + // and targs do not have the same length. + if len(tparams) == len(targs) { + check.verify(pos, tparams, targs, posList) + } + }) } + return inst } @@ -102,20 +119,7 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, tparams []*TypeName, // instantiateLazy avoids actually instantiating the type until needed. typ // must be a *Named type. -func (check *Checker) instantiateLazy(pos token.Pos, orig *Named, targs []Type, posList []token.Pos, verify bool) Type { - if verify { - if check == nil { - // Provide a more useful panic instead of panicking at check.later below. - panic("cannot have nil Checker if verifying constraints") - } - assert(len(posList) <= len(targs)) - if orig.TParams().Len() == len(targs) { - check.later(func() { - check.verify(pos, orig.tparams.list(), targs, posList) - }) - } - } - +func (check *Checker) instantiateLazy(pos token.Pos, orig *Named, targs []Type) Type { h := instantiatedHash(orig, targs) if check != nil { // typ may already have been instantiated with identical type arguments. In @@ -138,9 +142,6 @@ func (check *Checker) instantiateLazy(pos token.Pos, orig *Named, targs []Type, } func (check *Checker) verify(pos token.Pos, tparams []*TypeName, targs []Type, posList []token.Pos) { - if check == nil { - panic("cannot have nil Checker if verifying constraints") - } smap := makeSubstMap(tparams, targs) for i, tname := range tparams { // best position for error reporting diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 8af6570072..def5871ce7 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -433,7 +433,7 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named posList[i] = arg.Pos() } - typ := check.instantiateLazy(x.Pos(), base, targs, posList, true) + typ := check.Instantiate(x.Pos(), base, targs, posList, true) def.setUnderlying(typ) // make sure we check instantiation works at least once -- GitLab From 30a423eb3934251286bb57954c9d9d4b2385815e Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 16 Aug 2021 16:03:59 -0400 Subject: [PATCH 0779/2500] go/types: no need to validate substituted instances This is a straightforward port of CL 342150 to go/types. Change-Id: I7363e4642ade7ab30ca822a2be71f4d2804cc4a9 Reviewed-on: https://go-review.googlesource.com/c/go/+/342669 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/subst.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/go/types/subst.go b/src/go/types/subst.go index da0578ff5c..e47d20774f 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -228,10 +228,15 @@ func (subst *subster) typ(typ Type) Type { return named } - // create a new named type and populate typMap to avoid endless recursion + // Create a new named type and populate typMap to avoid endless recursion. + // The position used here is irrelevant because validation only occurs on t + // (we don't call validType on named), but we use subst.pos to help with + // debugging. tname := NewTypeName(subst.pos, t.obj.pkg, t.obj.name, nil) t.load() - named := subst.check.newNamed(tname, t.orig, t.underlying, t.TParams(), t.methods) // method signatures are updated lazily + // It's ok to provide a nil *Checker because the newly created type + // doesn't need to be (lazily) expanded; it's expanded below. + named := (*Checker)(nil).newNamed(tname, t.orig, nil, t.tparams, t.methods) // t is loaded, so tparams and methods are available named.targs = newTArgs subst.typMap[h] = named t.expand(subst.typMap) // must happen after typMap update to avoid infinite recursion @@ -241,7 +246,7 @@ func (subst *subster) typ(typ Type) Type { named.underlying = subst.typOrNil(t.underlying) dump(">>> underlying: %v", named.underlying) assert(named.underlying != nil) - named.fromRHS = named.underlying // for cycle detection (Checker.validType) + named.fromRHS = named.underlying // for consistency, though no cycle detection is necessary return named -- GitLab From 0f252511272d340c3fa9d25acfcc9ff9d809cd7d Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 16 Aug 2021 16:15:09 -0400 Subject: [PATCH 0780/2500] go/types: change Checker.verify to return an error This is a port of CL 342151 to go/types, adjusted for errors and positions. Checker.sprintf was refactored to facilitate formatting error messages with a nil Checker. Change-Id: Ib2e5c942e55edaff7b5e77cf68a72bad70fea0b9 Reviewed-on: https://go-review.googlesource.com/c/go/+/342670 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/errors.go | 14 +++++--- src/go/types/instantiate.go | 69 ++++++++++++++++++++----------------- 2 files changed, 47 insertions(+), 36 deletions(-) diff --git a/src/go/types/errors.go b/src/go/types/errors.go index 7468626b98..933de93d85 100644 --- a/src/go/types/errors.go +++ b/src/go/types/errors.go @@ -63,6 +63,10 @@ func (check *Checker) markImports(pkg *Package) { } func (check *Checker) sprintf(format string, args ...interface{}) string { + return sprintf(check.fset, check.qualifier, format, args...) +} + +func sprintf(fset *token.FileSet, qf Qualifier, format string, args ...interface{}) string { for i, arg := range args { switch a := arg.(type) { case nil: @@ -70,15 +74,17 @@ func (check *Checker) sprintf(format string, args ...interface{}) string { case operand: panic("got operand instead of *operand") case *operand: - arg = operandString(a, check.qualifier) + arg = operandString(a, qf) case token.Pos: - arg = check.fset.Position(a).String() + if fset != nil { + arg = fset.Position(a).String() + } case ast.Expr: arg = ExprString(a) case Object: - arg = ObjectString(a, check.qualifier) + arg = ObjectString(a, qf) case Type: - arg = TypeString(a, check.qualifier) + arg = TypeString(a, qf) } args[i] = arg } diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index eeb9b03050..86e5e202c4 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -8,6 +8,7 @@ package types import ( + "errors" "fmt" "go/token" ) @@ -73,7 +74,14 @@ func (check *Checker) Instantiate(pos token.Pos, typ Type, targs []Type, posList // Avoid duplicate errors; instantiate will have complained if tparams // and targs do not have the same length. if len(tparams) == len(targs) { - check.verify(pos, tparams, targs, posList) + if i, err := check.verify(pos, tparams, targs); err != nil { + // best position for error reporting + pos := pos + if i < len(posList) { + pos = posList[i] + } + check.softErrorf(atPos(pos), _Todo, err.Error()) + } } }) } @@ -141,30 +149,36 @@ func (check *Checker) instantiateLazy(pos token.Pos, orig *Named, targs []Type) return named } -func (check *Checker) verify(pos token.Pos, tparams []*TypeName, targs []Type, posList []token.Pos) { +func (check *Checker) verify(pos token.Pos, tparams []*TypeName, targs []Type) (int, error) { smap := makeSubstMap(tparams, targs) for i, tname := range tparams { - // best position for error reporting - pos := pos - if i < len(posList) { - pos = posList[i] - } - // stop checking bounds after the first failure - if !check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap) { - break + if err := check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap); err != nil { + return i, err } } + return -1, nil } // satisfies reports whether the type argument targ satisfies the constraint of type parameter // parameter tpar (after any of its type parameters have been substituted through smap). // A suitable error is reported if the result is false. // TODO(gri) This should be a method of interfaces or type sets. -func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap substMap) bool { +func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap substMap) error { iface := tpar.iface() if iface.Empty() { - return true // no type bound + return nil // no type bound + } + + // TODO(rfindley): it would be great if users could pass in a qualifier here, + // rather than falling back to verbose qualification. Maybe this can be part + // of a the shared environment. + var qf Qualifier + if check != nil { + qf = check.qualifier + } + errorf := func(format string, args ...interface{}) error { + return errors.New(sprintf(nil, qf, format, args...)) } // The type parameter bound is parameterized with the same type parameters @@ -177,11 +191,9 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap // TODO(gri) the error messages needs to be better, here if iface.IsComparable() && !Comparable(targ) { if tpar := asTypeParam(targ); tpar != nil && tpar.iface().typeSet().IsAll() { - check.softErrorf(atPos(pos), _Todo, "%s has no constraints", targ) - return false + return errorf("%s has no constraints", targ) } - check.softErrorf(atPos(pos), _Todo, "%s does not satisfy comparable", targ) - return false + return errorf("%s does not satisfy comparable", targ) } // targ must implement iface (methods) @@ -191,8 +203,7 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap // method set is empty. // TODO(gri) is this what we want? (spec question) if base, isPtr := deref(targ); isPtr && asTypeParam(base) != nil { - check.errorf(atPos(pos), 0, "%s has no methods", targ) - return false + return errorf("%s has no methods", targ) } if m, wrong := check.missingMethod(targ, iface, true); m != nil { // TODO(gri) needs to print updated name to avoid major confusion in error message! @@ -203,20 +214,17 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap // TODO(gri) This can still report uninstantiated types which makes the error message // more difficult to read then necessary. // TODO(rFindley) should this use parentheses rather than ':' for qualification? - check.softErrorf(atPos(pos), _Todo, - "%s does not satisfy %s: wrong method signature\n\tgot %s\n\twant %s", + return errorf("%s does not satisfy %s: wrong method signature\n\tgot %s\n\twant %s", targ, tpar.bound, wrong, m, ) - } else { - check.softErrorf(atPos(pos), 0, "%s does not satisfy %s (missing method %s)", targ, tpar.bound, m.name) } - return false + return errorf("%s does not satisfy %s (missing method %s)", targ, tpar.bound, m.name) } } // targ's underlying type must also be one of the interface types listed, if any if !iface.typeSet().hasTerms() { - return true // nothing to do + return nil // nothing to do } // If targ is itself a type parameter, each of its possible types, but at least one, must be in the @@ -224,23 +232,20 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap if targ := asTypeParam(targ); targ != nil { targBound := targ.iface() if !targBound.typeSet().hasTerms() { - check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ) - return false + return errorf("%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ) } if !targBound.typeSet().subsetOf(iface.typeSet()) { // TODO(gri) need better error message - check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s", targ, tpar.bound) - return false + return errorf("%s does not satisfy %s", targ, tpar.bound) } - return true + return nil } // Otherwise, targ's type or underlying type must also be one of the interface types listed, if any. if !iface.typeSet().includes(targ) { // TODO(gri) better error message - check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s", targ, tpar.bound) - return false + return errorf("%s does not satisfy %s", targ, tpar.bound) } - return true + return nil } -- GitLab From 5045477be8961af1a5855d89e60483f4ccb624ac Mon Sep 17 00:00:00 2001 From: HuanCheng Date: Sat, 21 Aug 2021 00:26:26 +0800 Subject: [PATCH 0781/2500] net/http: fix typo in header.go Change-Id: Ia6df881badf9a704c7f56967404d37e230b88a09 Reviewed-on: https://go-review.googlesource.com/c/go/+/343969 Reviewed-by: Damien Neil Reviewed-by: Ian Lance Taylor Trust: Damien Neil --- src/net/http/header.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/http/header.go b/src/net/http/header.go index cc9c28e3d0..5c77cbb882 100644 --- a/src/net/http/header.go +++ b/src/net/http/header.go @@ -196,7 +196,7 @@ func (h Header) writeSubset(w io.Writer, exclude map[string]bool, trace *httptra for _, kv := range kvs { if !httpguts.ValidHeaderFieldName(kv.key) { // This could be an error. In the common case of - // writing reponse headers, however, we have no good + // writing response headers, however, we have no good // way to provide the error back to the server // handler, so just drop invalid headers instead. continue -- GitLab From ab9aaf46ee5585317b5c796d6fb7e31383385eeb Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 19 Aug 2021 15:52:53 -0700 Subject: [PATCH 0782/2500] cmd/compile/internal/syntax: add PosBase.Trimmed With types2, some syntax.PosBases need to be constructed from export data, which must only contain "trimmed" filenames (i.e., that they've already been made absolute and undergone -trimpath processing). However, it's not safe to apply trimming to a filename multiple times, and in general we can't distinguish trimmed from untrimmed filenames. This CL resolves this by adding a PosBase.Trimmed boolean so we can distinguish whether the associated filename has been trimmed yet. This is a bit hacky, but is the least bad solution I've come up with so far. This unblocks enabling -G=3 by default. Change-Id: I7383becfb704680a36f7603e3246af38b21f100b Reviewed-on: https://go-review.googlesource.com/c/go/+/343731 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Matthew Dempsky Trust: Dan Scales Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/importer/iimport.go | 2 +- src/cmd/compile/internal/noder/noder.go | 26 ++++++++++++++------ src/cmd/compile/internal/noder/posmap.go | 6 +++-- src/cmd/compile/internal/noder/reader.go | 7 +++--- src/cmd/compile/internal/noder/reader2.go | 5 ++-- src/cmd/compile/internal/noder/writer.go | 6 +---- src/cmd/compile/internal/syntax/parser.go | 4 ++- src/cmd/compile/internal/syntax/pos.go | 19 +++++++++++--- 8 files changed, 48 insertions(+), 27 deletions(-) diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index ac5ec7c8f2..4384e59c30 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -257,7 +257,7 @@ func (p *iimporter) posBaseAt(off uint64) *syntax.PosBase { return posBase } filename := p.stringAt(off) - posBase := syntax.NewFileBase(filename) + posBase := syntax.NewTrimmedFileBase(filename, true) p.posBaseCache[off] = posBase return posBase } diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index 6a2aacd3fe..2b67a91b3f 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -191,13 +191,23 @@ func (p *noder) errorAt(pos syntax.Pos, format string, args ...interface{}) { base.ErrorfAt(p.makeXPos(pos), format, args...) } -// TODO(gri) Can we eliminate fileh in favor of absFilename? -func fileh(name string) string { - return objabi.AbsFile("", name, base.Flag.TrimPath) -} - -func absFilename(name string) string { - return objabi.AbsFile(base.Ctxt.Pathname, name, base.Flag.TrimPath) +// trimFilename returns the "trimmed" filename of b, which is the +// absolute filename after applying -trimpath processing. This +// filename form is suitable for use in object files and export data. +// +// If b's filename has already been trimmed (i.e., because it was read +// in from an imported package's export data), then the filename is +// returned unchanged. +func trimFilename(b *syntax.PosBase) string { + filename := b.Filename() + if !b.Trimmed() { + dir := "" + if b.IsFileBase() { + dir = base.Ctxt.Pathname + } + filename = objabi.AbsFile(dir, filename, base.Flag.TrimPath) + } + return filename } // noder transforms package syntax's AST into a Node tree. @@ -1723,7 +1733,7 @@ func (p *noder) pragma(pos syntax.Pos, blankLine bool, text string, old syntax.P // (primarily misuse of linker flags), other files are not. // See golang.org/issue/23672. func isCgoGeneratedFile(pos syntax.Pos) bool { - return strings.HasPrefix(filepath.Base(filepath.Clean(fileh(pos.Base().Filename()))), "_cgo_") + return strings.HasPrefix(filepath.Base(trimFilename(pos.Base())), "_cgo_") } // safeArg reports whether arg is a "safe" command-line argument, diff --git a/src/cmd/compile/internal/noder/posmap.go b/src/cmd/compile/internal/noder/posmap.go index a6d3e2d7ef..f22628f845 100644 --- a/src/cmd/compile/internal/noder/posmap.go +++ b/src/cmd/compile/internal/noder/posmap.go @@ -45,8 +45,10 @@ func (m *posMap) makeSrcPosBase(b0 *syntax.PosBase) *src.PosBase { b1, ok := m.bases[b0] if !ok { fn := b0.Filename() + absfn := trimFilename(b0) + if b0.IsFileBase() { - b1 = src.NewFileBase(fn, absFilename(fn)) + b1 = src.NewFileBase(fn, absfn) } else { // line directive base p0 := b0.Pos() @@ -55,7 +57,7 @@ func (m *posMap) makeSrcPosBase(b0 *syntax.PosBase) *src.PosBase { panic("infinite recursion in makeSrcPosBase") } p1 := src.MakePos(m.makeSrcPosBase(p0b), p0.Line(), p0.Col()) - b1 = src.NewLinePragmaBase(p1, fn, fileh(fn), b0.Line(), b0.Col()) + b1 = src.NewLinePragmaBase(p1, fn, absfn, b0.Line(), b0.Col()) } if m.bases == nil { m.bases = make(map[*syntax.PosBase]*src.PosBase) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 5481812b18..985453a1bb 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -194,16 +194,15 @@ func (pr *pkgReader) posBaseIdx(idx int) *src.PosBase { r := pr.newReader(relocPosBase, idx, syncPosBase) var b *src.PosBase - fn := r.string() - absfn := r.string() + filename := r.string() if r.bool() { - b = src.NewFileBase(fn, absfn) + b = src.NewFileBase(filename, filename) } else { pos := r.pos0() line := r.uint() col := r.uint() - b = src.NewLinePragmaBase(pos, fn, absfn, line, col) + b = src.NewLinePragmaBase(pos, filename, filename, line, col) } pr.posBases[idx] = b diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index 22c742ab25..64c1612f70 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -109,15 +109,14 @@ func (pr *pkgReader2) posBaseIdx(idx int) *syntax.PosBase { var b *syntax.PosBase filename := r.string() - _ = r.string() // absolute file name if r.bool() { - b = syntax.NewFileBase(filename) + b = syntax.NewTrimmedFileBase(filename, true) } else { pos := r.pos() line := r.uint() col := r.uint() - b = syntax.NewLineBase(pos, filename, line, col) + b = syntax.NewLineBase(pos, filename, true, line, col) } pr.posBases[idx] = b diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index d971bd0d16..a33b24e50c 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -189,11 +189,7 @@ func (pw *pkgWriter) posBaseIdx(b *syntax.PosBase) int { w := pw.newWriter(relocPosBase, syncPosBase) w.p.posBasesIdx[b] = w.idx - // TODO(mdempsky): What exactly does "fileh" do anyway? Is writing - // out both of these strings really the right thing to do here? - fn := b.Filename() - w.string(fn) - w.string(fileh(fn)) + w.string(trimFilename(b)) if !w.bool(b.IsFileBase()) { w.pos(b) diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index 4fb6de10a8..c477ddd45d 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -146,11 +146,13 @@ func (p *parser) updateBase(pos Pos, tline, tcol uint, text string) { // If we have a column (//line filename:line:col form), // an empty filename means to use the previous filename. filename := text[:i-1] // lop off ":line" + trimmed := false if filename == "" && ok2 { filename = p.base.Filename() + trimmed = p.base.Trimmed() } - p.base = NewLineBase(pos, filename, line, col) + p.base = NewLineBase(pos, filename, trimmed, line, col) } func commentText(s string) string { diff --git a/src/cmd/compile/internal/syntax/pos.go b/src/cmd/compile/internal/syntax/pos.go index baebcc995c..1494c0989f 100644 --- a/src/cmd/compile/internal/syntax/pos.go +++ b/src/cmd/compile/internal/syntax/pos.go @@ -133,13 +133,19 @@ type PosBase struct { pos Pos filename string line, col uint32 + trimmed bool // whether -trimpath has been applied } // NewFileBase returns a new PosBase for the given filename. // A file PosBase's position is relative to itself, with the // position being filename:1:1. func NewFileBase(filename string) *PosBase { - base := &PosBase{MakePos(nil, linebase, colbase), filename, linebase, colbase} + return NewTrimmedFileBase(filename, false) +} + +// NewTrimmedFileBase is like NewFileBase, but allows specifying Trimmed. +func NewTrimmedFileBase(filename string, trimmed bool) *PosBase { + base := &PosBase{MakePos(nil, linebase, colbase), filename, linebase, colbase, trimmed} base.pos.base = base return base } @@ -149,8 +155,8 @@ func NewFileBase(filename string) *PosBase { // the comment containing the line directive. For a directive in a line comment, // that position is the beginning of the next line (i.e., the newline character // belongs to the line comment). -func NewLineBase(pos Pos, filename string, line, col uint) *PosBase { - return &PosBase{pos, filename, sat32(line), sat32(col)} +func NewLineBase(pos Pos, filename string, trimmed bool, line, col uint) *PosBase { + return &PosBase{pos, filename, sat32(line), sat32(col), trimmed} } func (base *PosBase) IsFileBase() bool { @@ -188,6 +194,13 @@ func (base *PosBase) Col() uint { return uint(base.col) } +func (base *PosBase) Trimmed() bool { + if base == nil { + return false + } + return base.trimmed +} + func sat32(x uint) uint32 { if x > PosMax { return PosMax -- GitLab From f67e31d643b1d23abc1f24ebfa50ef51519d1348 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 19 Aug 2021 21:02:49 +0700 Subject: [PATCH 0783/2500] test: enable regabi test on arm64 CL 324890 turned on register ABI by default on ARM64, causing neither live.go nor live_regabi.go is run on ARM64. This CL enables live_regabi.go test for ARM64. Change-Id: I0c483a38b761c5a6f1fa9a5b3324b5da64907e61 Reviewed-on: https://go-review.googlesource.com/c/go/+/343531 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- test/live_regabi.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/live_regabi.go b/test/live_regabi.go index 2883b83bae..aac9a7766c 100644 --- a/test/live_regabi.go +++ b/test/live_regabi.go @@ -1,5 +1,5 @@ // errorcheckwithauto -0 -l -live -wb=0 -d=ssa/insert_resched_checks/off -// +build amd64,goexperiment.regabiargs +// +build amd64,goexperiment.regabiargs arm64,goexperiment.regabiargs // Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style -- GitLab From f89b4c8d82c028d635eb8e685dd92dceb0027438 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Mon, 16 Aug 2021 15:09:05 -0700 Subject: [PATCH 0784/2500] [dev.fuzz] cmd/go: exclude additional packages from fuzzing instrumentation Counters in these packages are incremented by background goroutines for testing and internal/fuzz. They cause some inputs to seem "interesting" when they don't directly provide new coverage. Updates golang/go#46410 Change-Id: Ibe6bb3177f3b2ba23382a1693a4c6a576f94a423 Reviewed-on: https://go-review.googlesource.com/c/go/+/342993 Trust: Jay Conrod Run-TryBot: Jay Conrod Reviewed-by: Roland Shoemaker --- src/cmd/go/internal/test/test.go | 11 +++++++++-- src/cmd/go/testdata/script/test_fuzz_cache.txt | 18 +++++++++++++----- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 012a75123b..75345a8223 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -831,11 +831,18 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { fuzzFlags := work.FuzzInstrumentFlags() if testFuzz != "" && fuzzFlags != nil { // Don't instrument packages which may affect coverage guidance but are - // unlikely to be useful. + // unlikely to be useful. Most of these are used by the testing or + // internal/fuzz concurrently with fuzzing. var fuzzNoInstrument = map[string]bool{ - "testing": true, + "context": true, "internal/fuzz": true, + "reflect": true, "runtime": true, + "sync": true, + "sync/atomic": true, + "syscall": true, + "testing": true, + "time": true, } for _, p := range load.TestPackageList(ctx, pkgOpts, pkgs) { if fuzzNoInstrument[p.ImportPath] { diff --git a/src/cmd/go/testdata/script/test_fuzz_cache.txt b/src/cmd/go/testdata/script/test_fuzz_cache.txt index a6c9cafada..10e4c2926f 100644 --- a/src/cmd/go/testdata/script/test_fuzz_cache.txt +++ b/src/cmd/go/testdata/script/test_fuzz_cache.txt @@ -35,19 +35,27 @@ go 1.16 -- y_test.go -- package y -import "testing" +import ( + "io" + "testing" +) func FuzzY(f *testing.F) { f.Add([]byte("y")) - f.Fuzz(func(t *testing.T, b []byte) { Y(b) }) + f.Fuzz(func(t *testing.T, b []byte) { Y(io.Discard, b) }) } -- y.go -- package y -import "bytes" +import ( + "bytes" + "io" +) -func Y(b []byte) bool { - return bytes.Equal(b, []byte("y")) +func Y(w io.Writer, b []byte) { + if !bytes.Equal(b, []byte("y")) { + w.Write([]byte("not equal")) + } } -- empty/empty.go -- package empty -- GitLab From 835ff47c1680de81b93480f5184ac4034c45e417 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 20 Aug 2021 15:20:10 -0400 Subject: [PATCH 0785/2500] cmd/internal/buildid: reject empty id The loop that makes progress assumes that after matching an id you should advance len(id) bytes in the file. If id is the empty string, then it will match and advance 0 bytes repeatedly. 0-byte ids are not really build IDs, so just reject it outright. Fixes #47852. Change-Id: Ie44a3a51dec22e2f68fb72d54ead91be98000cfe Reviewed-on: https://go-review.googlesource.com/c/go/+/344049 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Michael Knyszek TryBot-Result: Go Bot --- src/cmd/internal/buildid/buildid_test.go | 8 ++++++++ src/cmd/internal/buildid/rewrite.go | 3 +++ 2 files changed, 11 insertions(+) diff --git a/src/cmd/internal/buildid/buildid_test.go b/src/cmd/internal/buildid/buildid_test.go index e832f9987e..4895a49e11 100644 --- a/src/cmd/internal/buildid/buildid_test.go +++ b/src/cmd/internal/buildid/buildid_test.go @@ -177,3 +177,11 @@ func TestExcludedReader(t *testing.T) { } } } + +func TestEmptyID(t *testing.T) { + r := strings.NewReader("aha!") + matches, hash, err := FindAndHash(r, "", 1000) + if matches != nil || hash != ([32]byte{}) || err == nil || !strings.Contains(err.Error(), "no id") { + t.Errorf("FindAndHash: want nil, [32]byte{}, no id specified, got %v, %v, %v", matches, hash, err) + } +} diff --git a/src/cmd/internal/buildid/rewrite.go b/src/cmd/internal/buildid/rewrite.go index a7928959c4..8814950db0 100644 --- a/src/cmd/internal/buildid/rewrite.go +++ b/src/cmd/internal/buildid/rewrite.go @@ -22,6 +22,9 @@ func FindAndHash(r io.Reader, id string, bufSize int) (matches []int64, hash [32 if bufSize == 0 { bufSize = 31 * 1024 // bufSize+little will likely fit in 32 kB } + if len(id) == 0 { + return nil, [32]byte{}, fmt.Errorf("buildid.FindAndHash: no id specified") + } if len(id) > bufSize { return nil, [32]byte{}, fmt.Errorf("buildid.FindAndHash: buffer too small") } -- GitLab From 97d17dc02398730822abba75a3d3ae26c0f3c0fd Mon Sep 17 00:00:00 2001 From: korzhao Date: Sat, 21 Aug 2021 02:51:51 +0800 Subject: [PATCH 0786/2500] test/typeparam: add a test case for issue46591 Fixes #46591 Change-Id: I4875092ecd7760b0cd487e793576ef7a9a569a0e Reviewed-on: https://go-review.googlesource.com/c/go/+/343970 Reviewed-by: Matthew Dempsky Reviewed-by: Robert Griesemer Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Run-TryBot: Robert Griesemer TryBot-Result: Go Bot --- test/typeparam/issue46591.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 test/typeparam/issue46591.go diff --git a/test/typeparam/issue46591.go b/test/typeparam/issue46591.go new file mode 100644 index 0000000000..e7b9fa2b48 --- /dev/null +++ b/test/typeparam/issue46591.go @@ -0,0 +1,22 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type T[_ any] struct{} + +var m = map[interface{}]int{ + T[struct{ int }]{}: 0, + T[struct { + int "x" + }]{}: 0, +} + +func main() { + if len(m) != 2 { + panic(len(m)) + } +} -- GitLab From c9912780ab3ecea3c685bfc8bec229c0d2b09317 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 19 Aug 2021 15:53:13 -0700 Subject: [PATCH 0787/2500] cmd/compile: enable -G=3 by default This CL changes cmd/compile's -G flag's default from 0 to 3, which enables use of the new types2 type checker and support for type parameters. The old type checker is still available with -gcflags=all=-G=0. The CL also updates the regress test harness to account for the change in default behavior (e.g., to expect known types2 changes/failures). However, the -G=0 mode is still being tested for now. Copy of CL 340914 by danscales@, minus the cmd/internal/objabi.AbsFile change (handled instead by CL 343731) and rebased to master branch. Updates #43651. Change-Id: I1f62d6c0a3ff245e15c5c0e8f3d922129fdd4f29 Reviewed-on: https://go-review.googlesource.com/c/go/+/343732 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/base/flag.go | 1 + test/run.go | 29 +++++++++++++++------------ test/typeparam/smoketest.go | 2 +- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/cmd/compile/internal/base/flag.go b/src/cmd/compile/internal/base/flag.go index b8b205f412..942659bcc0 100644 --- a/src/cmd/compile/internal/base/flag.go +++ b/src/cmd/compile/internal/base/flag.go @@ -140,6 +140,7 @@ type CmdFlags struct { // ParseFlags parses the command-line flags into Flag. func ParseFlags() { + Flag.G = 3 Flag.I = addImportDir Flag.LowerC = 1 diff --git a/test/run.go b/test/run.go index f5971d2d15..22e94b767c 100644 --- a/test/run.go +++ b/test/run.go @@ -32,6 +32,10 @@ import ( "unicode" ) +// CompilerDefaultGLevel is the -G level used by default when not overridden by a +// command-line flag +const CompilerDefaultGLevel = 3 + var ( verbose = flag.Bool("v", false, "verbose. if set, parallelism is set to 1.") keep = flag.Bool("k", false, "keep. keep temporary directory.") @@ -340,13 +344,18 @@ type test struct { } // initExpectFail initializes t.expectFail based on the build+test -// configuration. It should only be called for tests known to use -// types2. -func (t *test) initExpectFail() { +// configuration. +func (t *test) initExpectFail(hasGFlag bool) { if *force { return } + if t.glevel == 0 && !hasGFlag && !unifiedEnabled { + // tests should always pass when run w/o types2 (i.e., using the + // legacy typechecker, option -G=0). + return + } + failureSets := []map[string]bool{types2Failures} // Note: gccgo supports more 32-bit architectures than this, but @@ -581,14 +590,14 @@ func init() { checkShouldTest() } // over and over. func (t *test) goGcflags() string { flags := os.Getenv("GO_GCFLAGS") - if t.glevel != 0 { + if t.glevel != CompilerDefaultGLevel { flags = fmt.Sprintf("%s -G=%v", flags, t.glevel) } return "-gcflags=all=" + flags } func (t *test) goGcflagsIsEmpty() bool { - return "" == os.Getenv("GO_GCFLAGS") && t.glevel == 0 + return "" == os.Getenv("GO_GCFLAGS") && t.glevel == CompilerDefaultGLevel } var errTimeout = errors.New("command exceeded time limit") @@ -750,7 +759,7 @@ func (t *test) run() { } } - if hasGFlag && t.glevel != 0 { + if hasGFlag && t.glevel != CompilerDefaultGLevel { // test provides explicit -G flag already; don't run again if *verbose { fmt.Printf("excl\t%s\n", t.goFileName()) @@ -758,13 +767,7 @@ func (t *test) run() { return false } - if t.glevel == 0 && !hasGFlag && !unifiedEnabled { - // tests should always pass when run w/o types2 (i.e., using the - // legacy typechecker). - return true - } - - t.initExpectFail() + t.initExpectFail(hasGFlag) switch tool { case Build, Run: diff --git a/test/typeparam/smoketest.go b/test/typeparam/smoketest.go index 5243dc5c3c..f32b40062d 100644 --- a/test/typeparam/smoketest.go +++ b/test/typeparam/smoketest.go @@ -1,4 +1,4 @@ -// compile -G +// compile -G=1 // Copyright 2020 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style -- GitLab From e17439e0877d6ddb6881d9eb59758c27cc62f930 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 19 Aug 2021 21:35:57 -0700 Subject: [PATCH 0788/2500] go/types: don't override x.mode before using it Changing the mode of x before using the old value is clearly wrong. And x is not needed anymore afterward so besides being misplaced, the assignment is not needed in the first place. Tested manually as it's a bit complicated to set up a test. Needs to be back-ported to 1.17. Fixes #47777. Change-Id: I06f1fa9443eb98009b4276f566d557fd52f1d6d3 Reviewed-on: https://go-review.googlesource.com/c/go/+/343809 Trust: Robert Griesemer Reviewed-by: Matthew Dempsky --- src/go/types/call.go | 1 - 1 file changed, 1 deletion(-) diff --git a/src/go/types/call.go b/src/go/types/call.go index 390e9cd892..08ef2451bf 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -223,7 +223,6 @@ func (check *Checker) exprList(elist []ast.Expr, allowCommaOk bool) (xlist []*op // exactly one (possibly invalid or comma-ok) value xlist = []*operand{&x} if allowCommaOk && (x.mode == mapindex || x.mode == commaok || x.mode == commaerr) { - x.mode = value x2 := &operand{mode: value, expr: e, typ: Typ[UntypedBool]} if x.mode == commaerr { x2.typ = universeError -- GitLab From dcee007aad6cca16cec0383a394dd7db92cd6790 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Fri, 16 Jul 2021 02:36:52 +1000 Subject: [PATCH 0789/2500] cmd/compile: sort regalloc switch by architecture Also tweak comment for the arm64 case. Change-Id: I073405bd2acf901dcaaf33a034a84b6a09dd4a83 Reviewed-on: https://go-review.googlesource.com/c/go/+/334869 Trust: Joel Sing Reviewed-by: Meng Zhuo Reviewed-by: Cherry Mui --- src/cmd/compile/internal/ssa/regalloc.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index 3d978e7ac8..28fac6ccd0 100644 --- a/src/cmd/compile/internal/ssa/regalloc.go +++ b/src/cmd/compile/internal/ssa/regalloc.go @@ -620,20 +620,20 @@ func (s *regAllocState) init(f *Func) { } if s.f.Config.ctxt.Flag_dynlink { switch s.f.Config.arch { - case "amd64": - s.allocatable &^= 1 << 15 // R15 - case "arm": - s.allocatable &^= 1 << 9 // R9 - case "ppc64le": // R2 already reserved. - // nothing to do - case "arm64": - // nothing to do? case "386": // nothing to do. // Note that for Flag_shared (position independent code) // we do need to be careful, but that carefulness is hidden // in the rewrite rules so we always have a free register // available for global load/stores. See gen/386.rules (search for Flag_shared). + case "amd64": + s.allocatable &^= 1 << 15 // R15 + case "arm": + s.allocatable &^= 1 << 9 // R9 + case "arm64": + // nothing to do + case "ppc64le": // R2 already reserved. + // nothing to do case "s390x": s.allocatable &^= 1 << 11 // R11 default: -- GitLab From bcd146d398da2a873bb3f5a6e026c70b411a4486 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Tue, 17 Aug 2021 19:01:52 +1000 Subject: [PATCH 0790/2500] cmd/compile: convert branch with zero to more optimal branch zero on riscv64 Convert BLT and BGE with a zero valued constant to BGTZ/BLTZ/BLEZ/BGEZ as appropriate. Removes over 4,500 instructions from the go binary on riscv64. Change-Id: Icc266e968b126ba04863ec88529630a9dd44498b Reviewed-on: https://go-review.googlesource.com/c/go/+/342849 Trust: Joel Sing Reviewed-by: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot --- .../compile/internal/ssa/gen/RISCV64.rules | 6 ++- .../compile/internal/ssa/rewriteRISCV64.go | 46 +++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64.rules b/src/cmd/compile/internal/ssa/gen/RISCV64.rules index 1acef2a273..1414b2b34d 100644 --- a/src/cmd/compile/internal/ssa/gen/RISCV64.rules +++ b/src/cmd/compile/internal/ssa/gen/RISCV64.rules @@ -596,11 +596,15 @@ (BEQZ (SLTU x y) yes no) => (BGEU x y yes no) (BNEZ (SLTU x y) yes no) => (BLTU x y yes no) -// Convert branch with zero to BEQZ/BNEZ. +// Convert branch with zero to more optimal branch zero. (BEQ (MOVDconst [0]) cond yes no) => (BEQZ cond yes no) (BEQ cond (MOVDconst [0]) yes no) => (BEQZ cond yes no) (BNE (MOVDconst [0]) cond yes no) => (BNEZ cond yes no) (BNE cond (MOVDconst [0]) yes no) => (BNEZ cond yes no) +(BLT (MOVDconst [0]) cond yes no) => (BGTZ cond yes no) +(BLT cond (MOVDconst [0]) yes no) => (BLTZ cond yes no) +(BGE (MOVDconst [0]) cond yes no) => (BLEZ cond yes no) +(BGE cond (MOVDconst [0]) yes no) => (BGEZ cond yes no) // Store zero (MOVBstore [off] {sym} ptr (MOVDconst [0]) mem) => (MOVBstorezero [off] {sym} ptr mem) diff --git a/src/cmd/compile/internal/ssa/rewriteRISCV64.go b/src/cmd/compile/internal/ssa/rewriteRISCV64.go index e9f17206de..9323cda55d 100644 --- a/src/cmd/compile/internal/ssa/rewriteRISCV64.go +++ b/src/cmd/compile/internal/ssa/rewriteRISCV64.go @@ -6129,6 +6129,52 @@ func rewriteBlockRISCV64(b *Block) bool { b.resetWithControl2(BlockRISCV64BGEU, x, y) return true } + case BlockRISCV64BGE: + // match: (BGE (MOVDconst [0]) cond yes no) + // result: (BLEZ cond yes no) + for b.Controls[0].Op == OpRISCV64MOVDconst { + v_0 := b.Controls[0] + if auxIntToInt64(v_0.AuxInt) != 0 { + break + } + cond := b.Controls[1] + b.resetWithControl(BlockRISCV64BLEZ, cond) + return true + } + // match: (BGE cond (MOVDconst [0]) yes no) + // result: (BGEZ cond yes no) + for b.Controls[1].Op == OpRISCV64MOVDconst { + cond := b.Controls[0] + v_1 := b.Controls[1] + if auxIntToInt64(v_1.AuxInt) != 0 { + break + } + b.resetWithControl(BlockRISCV64BGEZ, cond) + return true + } + case BlockRISCV64BLT: + // match: (BLT (MOVDconst [0]) cond yes no) + // result: (BGTZ cond yes no) + for b.Controls[0].Op == OpRISCV64MOVDconst { + v_0 := b.Controls[0] + if auxIntToInt64(v_0.AuxInt) != 0 { + break + } + cond := b.Controls[1] + b.resetWithControl(BlockRISCV64BGTZ, cond) + return true + } + // match: (BLT cond (MOVDconst [0]) yes no) + // result: (BLTZ cond yes no) + for b.Controls[1].Op == OpRISCV64MOVDconst { + cond := b.Controls[0] + v_1 := b.Controls[1] + if auxIntToInt64(v_1.AuxInt) != 0 { + break + } + b.resetWithControl(BlockRISCV64BLTZ, cond) + return true + } case BlockRISCV64BNE: // match: (BNE (MOVDconst [0]) cond yes no) // result: (BNEZ cond yes no) -- GitLab From 8fff20ffebadfea2c5c3dd58f7007246f3408495 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Tue, 17 Aug 2021 19:09:33 +1000 Subject: [PATCH 0791/2500] cmd/compile: absorb NEG into branch when possible on riscv64 We can end up with this situation due to our equality tests being based on 'SEQZ (SUB x y)' - if x is a zero valued constant, 'SUB x y' can be converted to 'NEG x'. When used with a branch the SEQZ can be absorbed, leading to 'BNEZ (NEG x)' where the NEG is redundant. Removes around 1700 instructions from the go binary on riscv64. Change-Id: I947a080d8bf7d2d6378ab114172e2342ce2c51db Reviewed-on: https://go-review.googlesource.com/c/go/+/342850 Trust: Joel Sing Reviewed-by: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot --- .../compile/internal/ssa/gen/RISCV64.rules | 4 ++++ .../compile/internal/ssa/rewriteRISCV64.go | 24 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64.rules b/src/cmd/compile/internal/ssa/gen/RISCV64.rules index 1414b2b34d..4eb48e3928 100644 --- a/src/cmd/compile/internal/ssa/gen/RISCV64.rules +++ b/src/cmd/compile/internal/ssa/gen/RISCV64.rules @@ -588,6 +588,10 @@ (BNEZ (SEQZ x) yes no) => (BEQZ x yes no) (BNEZ (SNEZ x) yes no) => (BNEZ x yes no) +// Absorb NEG into branch when possible. +(BEQZ x:(NEG y) yes no) && x.Uses == 1 => (BEQZ y yes no) +(BNEZ x:(NEG y) yes no) && x.Uses == 1 => (BNEZ y yes no) + // Convert BEQZ/BNEZ into more optimal branch conditions. (BEQZ (SUB x y) yes no) => (BEQ x y yes no) (BNEZ (SUB x y) yes no) => (BNE x y yes no) diff --git a/src/cmd/compile/internal/ssa/rewriteRISCV64.go b/src/cmd/compile/internal/ssa/rewriteRISCV64.go index 9323cda55d..641be038db 100644 --- a/src/cmd/compile/internal/ssa/rewriteRISCV64.go +++ b/src/cmd/compile/internal/ssa/rewriteRISCV64.go @@ -6102,6 +6102,18 @@ func rewriteBlockRISCV64(b *Block) bool { b.resetWithControl(BlockRISCV64BEQZ, x) return true } + // match: (BEQZ x:(NEG y) yes no) + // cond: x.Uses == 1 + // result: (BEQZ y yes no) + for b.Controls[0].Op == OpRISCV64NEG { + x := b.Controls[0] + y := x.Args[0] + if !(x.Uses == 1) { + break + } + b.resetWithControl(BlockRISCV64BEQZ, y) + return true + } // match: (BEQZ (SUB x y) yes no) // result: (BEQ x y yes no) for b.Controls[0].Op == OpRISCV64SUB { @@ -6215,6 +6227,18 @@ func rewriteBlockRISCV64(b *Block) bool { b.resetWithControl(BlockRISCV64BNEZ, x) return true } + // match: (BNEZ x:(NEG y) yes no) + // cond: x.Uses == 1 + // result: (BNEZ y yes no) + for b.Controls[0].Op == OpRISCV64NEG { + x := b.Controls[0] + y := x.Args[0] + if !(x.Uses == 1) { + break + } + b.resetWithControl(BlockRISCV64BNEZ, y) + return true + } // match: (BNEZ (SUB x y) yes no) // result: (BNE x y yes no) for b.Controls[0].Op == OpRISCV64SUB { -- GitLab From 6e50991d2a38058d0824f8b086677fbe9774c9f9 Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Fri, 20 Aug 2021 12:50:02 -0700 Subject: [PATCH 0792/2500] strconv: reject surrogate halves in Unquote Unquote implements unescaping a "single-quoted, doubled-quoted, or backquoted Go string literal". Therefore, it should reject anything that the Go specification explicitly forbids. The section on "Rune literals" explicitly rejects rune values "above 0x10FFFF and surrogate halves". We properly checked for the previous condition, but were failing to check for the latter. In general, "r > utf8.MaxRune" is probably the wrong check, while !utf8.ValidRune(r) is the more correct check. We make changes to both UnquoteChar and appendEscapedRune to use the correct check. The change to appendEscapedRune is technically a noop since callers of that function already guarantee that the provided rune is valid. Fixes #47853 Change-Id: Ib8977e56b91943ec8ada821b8d217b5e9a66f950 Reviewed-on: https://go-review.googlesource.com/c/go/+/343877 Trust: Joe Tsai Run-TryBot: Joe Tsai TryBot-Result: Go Bot Reviewed-by: Rob Pike --- src/strconv/quote.go | 4 ++-- src/strconv/quote_test.go | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/strconv/quote.go b/src/strconv/quote.go index b3bbb1612b..d2814b92da 100644 --- a/src/strconv/quote.go +++ b/src/strconv/quote.go @@ -103,7 +103,7 @@ func appendEscapedRune(buf []byte, r rune, quote byte, ASCIIonly, graphicOnly bo buf = append(buf, `\x`...) buf = append(buf, lowerhex[byte(r)>>4]) buf = append(buf, lowerhex[byte(r)&0xF]) - case r > utf8.MaxRune: + case !utf8.ValidRune(r): r = 0xFFFD fallthrough case r < 0x10000: @@ -322,7 +322,7 @@ func UnquoteChar(s string, quote byte) (value rune, multibyte bool, tail string, value = v break } - if v > utf8.MaxRune { + if !utf8.ValidRune(v) { err = ErrSyntax return } diff --git a/src/strconv/quote_test.go b/src/strconv/quote_test.go index 4750be2740..81fc8f79e1 100644 --- a/src/strconv/quote_test.go +++ b/src/strconv/quote_test.go @@ -131,6 +131,7 @@ var quoterunetests = []quoteRuneTest{ {'\\', `'\\'`, `'\\'`, `'\\'`}, {0xFF, `'ÿ'`, `'\u00ff'`, `'ÿ'`}, {0x263a, `'☺'`, `'\u263a'`, `'☺'`}, + {0xdead, `'�'`, `'\ufffd'`, `'�'`}, {0xfffd, `'�'`, `'\ufffd'`, `'�'`}, {0x0010ffff, `'\U0010ffff'`, `'\U0010ffff'`, `'\U0010ffff'`}, {0x0010ffff + 1, `'�'`, `'\ufffd'`, `'�'`}, @@ -305,6 +306,8 @@ var misquoted = []string{ "\"\n\"", "\"\\n\n\"", "'\n'", + `"\udead"`, + `"\ud83d\ude4f"`, } func TestUnquote(t *testing.T) { -- GitLab From 96d816c5740f7576ed0f6346f70958ce9ef1e3b4 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Sat, 12 Dec 2020 16:46:01 +0100 Subject: [PATCH 0793/2500] runtime: fix buckHashSize duplication We have a constant for 179999, don't duplicate it. Change-Id: Iefb9c4746f6dda2e08b42e3c978963198469ee8c Reviewed-on: https://go-review.googlesource.com/c/go/+/277375 Reviewed-by: Keith Randall Run-TryBot: Keith Randall Run-TryBot: Michael Pratt TryBot-Result: Go Bot Trust: Michael Pratt --- src/runtime/mprof.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/mprof.go b/src/runtime/mprof.go index 0ba415ba5a..0e6043cf2a 100644 --- a/src/runtime/mprof.go +++ b/src/runtime/mprof.go @@ -142,7 +142,7 @@ var ( mbuckets *bucket // memory profile buckets bbuckets *bucket // blocking profile buckets xbuckets *bucket // mutex profile buckets - buckhash *[179999]*bucket + buckhash *[buckHashSize]*bucket bucketmem uintptr mProf struct { -- GitLab From bd6845965c298b250f8af577a24416de0661c53d Mon Sep 17 00:00:00 2001 From: Mostafa Solati Date: Mon, 8 Jun 2020 22:04:09 +0430 Subject: [PATCH 0794/2500] reflect: add example for FieldByIndex Change-Id: I539453e50ab85ec1b023bc9e329e6451c674e0c9 Reviewed-on: https://go-review.googlesource.com/c/go/+/236937 Reviewed-by: Emmanuel Odeke Reviewed-by: Ian Lance Taylor Run-TryBot: Emmanuel Odeke TryBot-Result: Go Bot --- src/reflect/example_test.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/reflect/example_test.go b/src/reflect/example_test.go index 23c08e4950..684bafd648 100644 --- a/src/reflect/example_test.go +++ b/src/reflect/example_test.go @@ -166,3 +166,31 @@ func ExampleStructOf() { // json: {"height":0.4,"age":2} // value: &{Height:1.5 Age:10} } + +func ExampleValue_FieldByIndex() { + // This example shows a case in which the name of a promoted field + // is hidden by another field: FieldByName will not work, so + // FieldByIndex must be used instead. + type user struct { + firstName string + lastName string + } + + type data struct { + user + firstName string + lastName string + } + + u := data{ + user: user{"Embedded John", "Embedded Doe"}, + firstName: "John", + lastName: "Doe", + } + + s := reflect.ValueOf(u).FieldByIndex([]int{0, 1}) + fmt.Println("embedded last name:", s) + + // Output: + // embedded last name: Embedded Doe +} -- GitLab From 6416bde023d897dcedc6d53bf0bf58821962f435 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Mon, 31 May 2021 00:18:54 +1000 Subject: [PATCH 0795/2500] runtime: use asmcgocall_no_g when calling sigprocmask on openbsd sigprocmask is called from sigsave, which is called from needm. As such, sigprocmask has to be able to run with no g. For some reason we do not currently trip this on current libc platforms, but we do hit it on openbsd/mips64 with external linking. Updates #36435 Change-Id: I4dfae924245c5f68cc012755d6485939014898a3 Reviewed-on: https://go-review.googlesource.com/c/go/+/334879 Trust: Joel Sing Reviewed-by: Ian Lance Taylor --- src/runtime/sys_openbsd2.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/runtime/sys_openbsd2.go b/src/runtime/sys_openbsd2.go index 190ee4716a..23e0b195fd 100644 --- a/src/runtime/sys_openbsd2.go +++ b/src/runtime/sys_openbsd2.go @@ -199,7 +199,9 @@ func sigaction_trampoline() //go:nosplit //go:cgo_unsafe_args func sigprocmask(how uint32, new *sigset, old *sigset) { - libcCall(unsafe.Pointer(abi.FuncPCABI0(sigprocmask_trampoline)), unsafe.Pointer(&how)) + // sigprocmask is called from sigsave, which is called from needm. + // As such, we have to be able to run with no g here. + asmcgocall_no_g(unsafe.Pointer(abi.FuncPCABI0(sigprocmask_trampoline)), unsafe.Pointer(&how)) } func sigprocmask_trampoline() -- GitLab From 19585826fa52d0580724be91f610db54727c74f0 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sun, 22 Aug 2021 12:11:02 -0700 Subject: [PATCH 0796/2500] math/big: clarified doc string for SetMantExp Fixes #47879. Change-Id: I35efb5fc65c4f1eb1b45918f95bbe1ff4039950e Reviewed-on: https://go-review.googlesource.com/c/go/+/344249 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Rob Pike --- src/math/big/float.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/math/big/float.go b/src/math/big/float.go index 42050e2c39..a8c91a6e54 100644 --- a/src/math/big/float.go +++ b/src/math/big/float.go @@ -304,7 +304,9 @@ func (z *Float) setExpAndRound(exp int64, sbit uint) { // SetMantExp sets z to mant × 2**exp and returns z. // The result z has the same precision and rounding mode // as mant. SetMantExp is an inverse of MantExp but does -// not require 0.5 <= |mant| < 1.0. Specifically: +// not require 0.5 <= |mant| < 1.0. Specifically, for a +// given x of type *Float, SetMantExp relates to MantExp +// as follows: // // mant := new(Float) // new(Float).SetMantExp(mant, x.MantExp(mant)).Cmp(x) == 0 -- GitLab From 5d0c2840dae019c722fec7f5a64f371a780e24fd Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sun, 22 Aug 2021 14:09:46 -0700 Subject: [PATCH 0797/2500] cmd/compile/internal/types2: report argument type for unsafe.OffsetOf Before parameterized types, unsafe.OffsetOf was always evaluating to a constant. With parameterized types, the result may be a run-time value, and unsafe.OffsetOf(x.f) is a call that is recorded. Also record the argument x.f. Fixes #47895. Change-Id: Ia3da25028d4865d7295ce7990c7216bffe9e7c72 Reviewed-on: https://go-review.googlesource.com/c/go/+/344252 Trust: Robert Griesemer Trust: Dan Scales Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/types2/api_test.go | 3 +++ src/cmd/compile/internal/types2/builtins.go | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index d6a2eb4eb3..3ed2799a84 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -346,6 +346,9 @@ func TestTypesInfo(t *testing.T) { // issue 45096 {genericPkg + `issue45096; func _[T interface{ ~int8 | ~int16 | ~int32 }](x T) { _ = x < 0 }`, `0`, `generic_issue45096.T₁`}, + + // issue 47895 + {`package p; import "unsafe"; type S struct { f int }; var s S; var _ = unsafe.Offsetof(s.f)`, `s.f`, `int`}, } for _, test := range tests { diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index da2dcf54aa..87295fe0e7 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -662,6 +662,15 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( // TODO(gri) Should we pass x.typ instead of base (and have indirect report if derefStructPtr indirected)? check.recordSelection(selx, FieldVal, base, obj, index, false) + // record the selector expression (was bug - issue #47895) + { + mode := value + if x.mode == variable || indirect { + mode = variable + } + check.record(&operand{mode, selx, obj.Type(), nil, 0}) + } + // The field offset is considered a variable even if the field is declared before // the part of the struct which is variable-sized. This makes both the rules // simpler and also permits (or at least doesn't prevent) a compiler from re- -- GitLab From 5d5e50c3db2ad15bef4ddc4e2f946d0628deda2d Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Tue, 22 Jun 2021 20:19:57 -0700 Subject: [PATCH 0798/2500] os/user: simplify test skip for plan9 There's no need to specifically check for runtime.GOOS as there's already a generic mechanism for that. Change-Id: I7125443ead456548bd503c5e71cd56e9eb30b446 Reviewed-on: https://go-review.googlesource.com/c/go/+/330750 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Reviewed-by: Tobias Klauser --- src/os/user/lookup_plan9.go | 1 + src/os/user/user_test.go | 8 -------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/os/user/lookup_plan9.go b/src/os/user/lookup_plan9.go index 33ae3a6adf..51caf55935 100644 --- a/src/os/user/lookup_plan9.go +++ b/src/os/user/lookup_plan9.go @@ -18,6 +18,7 @@ const ( ) func init() { + userImplemented = false groupImplemented = false } diff --git a/src/os/user/user_test.go b/src/os/user/user_test.go index 49920317be..1112c78c00 100644 --- a/src/os/user/user_test.go +++ b/src/os/user/user_test.go @@ -56,10 +56,6 @@ func compare(t *testing.T, want, got *User) { func TestLookup(t *testing.T) { checkUser(t) - if runtime.GOOS == "plan9" { - t.Skipf("Lookup not implemented on %q", runtime.GOOS) - } - want, err := Current() if err != nil { t.Fatalf("Current: %v", err) @@ -77,10 +73,6 @@ func TestLookup(t *testing.T) { func TestLookupId(t *testing.T) { checkUser(t) - if runtime.GOOS == "plan9" { - t.Skipf("LookupId not implemented on %q", runtime.GOOS) - } - want, err := Current() if err != nil { t.Fatalf("Current: %v", err) -- GitLab From 8fcc614360cac2c23aafeb2fdc637c72ff1d7dfd Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sun, 22 Aug 2021 14:55:12 -0700 Subject: [PATCH 0799/2500] cmd/compile/internal/types2: enable TestSelection API test This test was never fully ported from go/types. Implement a conversion function from syntax.Pos to string index so that the test can be enabled again. Also renamed the local variable syntax to segment to avoid confusion with the syntax package. Change-Id: I1b34e50ec138403798efb14c828545780f565507 Reviewed-on: https://go-review.googlesource.com/c/go/+/344253 Trust: Robert Griesemer Trust: Dan Scales Run-TryBot: Robert Griesemer Reviewed-by: Dan Scales --- src/cmd/compile/internal/types2/api_test.go | 46 +++++++++++---------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index 3ed2799a84..269b06f08a 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -17,10 +17,6 @@ import ( . "cmd/compile/internal/types2" ) -func unimplemented() { - panic("unimplemented") -} - // genericPkg is a source prefix for packages that contain generic code. const genericPkg = "package generic_" @@ -1168,8 +1164,6 @@ func (m testImporter) Import(path string) (*Package, error) { } func TestSelection(t *testing.T) { - t.Skip("requires fixes around source positions") - selections := make(map[*syntax.SelectorExpr]*Selection) imports := make(testImporter) @@ -1293,11 +1287,9 @@ func main() { for e, sel := range selections { _ = sel.String() // assertion: must not panic - unimplemented() - _ = e - // start := fset.Position(e.Pos()).Offset - // end := fset.Position(e.End()).Offset - // syntax := mainSrc[start:end] // (all SelectorExprs are in main, not lib) + start := indexFor(mainSrc, syntax.StartPos(e)) + end := indexFor(mainSrc, syntax.EndPos(e)) + segment := mainSrc[start:end] // (all SelectorExprs are in main, not lib) direct := "." if sel.Indirect() { @@ -1307,13 +1299,11 @@ func main() { sel.String(), fmt.Sprintf("%s%v", direct, sel.Index()), } - unimplemented() - _ = got - // want := wantOut[syntax] - // if want != got { - // t.Errorf("%s: got %q; want %q", syntax, got, want) - // } - // delete(wantOut, syntax) + want := wantOut[segment] + if want != got { + t.Errorf("%s: got %q; want %q", segment, got, want) + } + delete(wantOut, segment) // We must explicitly assert properties of the // Signature's receiver since it doesn't participate @@ -1323,17 +1313,29 @@ func main() { got := sig.Recv().Type() want := sel.Recv() if !Identical(got, want) { - unimplemented() - // t.Errorf("%s: Recv() = %s, want %s", syntax, got, want) + t.Errorf("%s: Recv() = %s, want %s", segment, got, want) } } else if sig != nil && sig.Recv() != nil { t.Errorf("%s: signature has receiver %s", sig, sig.Recv().Type()) } } // Assert that all wantOut entries were used exactly once. - for syntax := range wantOut { - t.Errorf("no syntax.Selection found with syntax %q", syntax) + for segment := range wantOut { + t.Errorf("no syntax.Selection found with syntax %q", segment) + } +} + +// indexFor returns the index into s corresponding to the position pos. +func indexFor(s string, pos syntax.Pos) int { + i, line := 0, 1 // string index and corresponding line + target := int(pos.Line()) + for line < target && i < len(s) { + if s[i] == '\n' { + line++ + } + i++ } + return i + int(pos.Col()-1) // columns are 1-based } func TestIssue8518(t *testing.T) { -- GitLab From 29d7e5472be79b77f39d81b697d44038179ba1a1 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sun, 22 Aug 2021 15:21:29 -0700 Subject: [PATCH 0800/2500] go/types: report argument type for unsafe.OffsetOf This is a clean port of CL 344252 to go/types. For #47895. Change-Id: I48cbb97ec28fcfb4fdf483594be9d29426c117ac Reviewed-on: https://go-review.googlesource.com/c/go/+/344254 Trust: Robert Griesemer Trust: Dan Scales Run-TryBot: Robert Griesemer Reviewed-by: Dan Scales --- src/go/types/api_test.go | 3 +++ src/go/types/builtins.go | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index 1631215d15..a49f2113b9 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -362,6 +362,9 @@ func TestTypesInfo(t *testing.T) { // issue 45096 {genericPkg + `issue45096; func _[T interface{ ~int8 | ~int16 | ~int32 }](x T) { _ = x < 0 }`, `0`, `generic_issue45096.T₁`}, + + // issue 47895 + {`package p; import "unsafe"; type S struct { f int }; var s S; var _ = unsafe.Offsetof(s.f)`, `s.f`, `int`}, } for _, test := range tests { diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 9c772d3844..698435bc20 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -671,6 +671,15 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // TODO(gri) Should we pass x.typ instead of base (and have indirect report if derefStructPtr indirected)? check.recordSelection(selx, FieldVal, base, obj, index, false) + // record the selector expression (was bug - issue #47895) + { + mode := value + if x.mode == variable || indirect { + mode = variable + } + check.record(&operand{mode, selx, obj.Type(), nil, 0}) + } + // The field offset is considered a variable even if the field is declared before // the part of the struct which is variable-sized. This makes both the rules // simpler and also permits (or at least doesn't prevent) a compiler from re- -- GitLab From 86ee89225aea2326fd50dbeb233cfc622413a4cf Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Tue, 17 Aug 2021 23:52:00 +0000 Subject: [PATCH 0801/2500] strings: smarter growth of temporal buffer and avoid copying on return MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The implementation for single strings had two optimization opportunities: 1. Grow the temporary buffer by known size before appending. 2. Avoid a full copy of the result since the underlying buffer won't be mutated afterward. Both things were leveraged by using a Builder instead of a byte slice. Relevant benchmark results: name old time/op new time/op delta SingleMatch-8 32.0µs ± 3% 26.1µs ± 3% -18.41% (p=0.000 n=9+10) name old speed new speed delta SingleMatch-8 469MB/s ± 3% 574MB/s ± 3% +22.56% (p=0.000 n=9+10) name old alloc/op new alloc/op delta SingleMatch-8 81.3kB ± 0% 49.0kB ± 0% -39.67% (p=0.000 n=10+10) name old allocs/op new allocs/op delta SingleMatch-8 19.0 ± 0% 11.0 ± 0% -42.11% (p=0.000 n=10+10) Change-Id: I23af56a15875206c0ff4ce29a51bec95fd48bb11 GitHub-Last-Rev: 403cfc3c2794b5da27792c51999417a2a052b365 GitHub-Pull-Request: golang/go#47766 Reviewed-on: https://go-review.googlesource.com/c/go/+/343089 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Robert Griesemer --- src/strings/replace.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/strings/replace.go b/src/strings/replace.go index e28d428879..ee728bb22b 100644 --- a/src/strings/replace.go +++ b/src/strings/replace.go @@ -387,7 +387,7 @@ func makeSingleStringReplacer(pattern string, value string) *singleStringReplace } func (r *singleStringReplacer) Replace(s string) string { - var buf []byte + var buf Builder i, matched := 0, false for { match := r.finder.next(s[i:]) @@ -395,15 +395,16 @@ func (r *singleStringReplacer) Replace(s string) string { break } matched = true - buf = append(buf, s[i:i+match]...) - buf = append(buf, r.value...) + buf.Grow(match + len(r.value)) + buf.WriteString(s[i : i+match]) + buf.WriteString(r.value) i += match + len(r.finder.pattern) } if !matched { return s } - buf = append(buf, s[i:]...) - return string(buf) + buf.WriteString(s[i:]) + return buf.String() } func (r *singleStringReplacer) WriteString(w io.Writer, s string) (n int, err error) { -- GitLab From 457418b47556520d73148a9a5672ee380bd0b5a4 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Mon, 23 Aug 2021 09:31:54 +0700 Subject: [PATCH 0802/2500] cmd/go: fix long test builders CL 343732 enabled -G=3 by default. The types2 typechecker uses slighly different error message format for language feature constraint. The old typechecker format: vendor/example.net/need117/need117.go:5:16: cannot convert s (type []byte) to type *[4]byte: conversion of slices to array pointers only supported as of -lang=go1.17 The new format: vendor/example.net/need117/need117.go:5:17: conversion of slices to array pointers only supported as of -lang=go1.17 caused the long test builders failed. This CL fixes the test by relaxing the regext pattern a bit, so it can match both the format. Change-Id: I1c4acaa9e34b6c08dccbbc3ce7a99d4cd79f748a Reviewed-on: https://go-review.googlesource.com/c/go/+/344212 Trust: Cuong Manh Le Trust: Robert Griesemer Run-TryBot: Cuong Manh Le Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/go/testdata/script/mod_vendor_goversion.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/go/testdata/script/mod_vendor_goversion.txt b/src/cmd/go/testdata/script/mod_vendor_goversion.txt index aa4cb41171..7f1966c8e8 100644 --- a/src/cmd/go/testdata/script/mod_vendor_goversion.txt +++ b/src/cmd/go/testdata/script/mod_vendor_goversion.txt @@ -26,7 +26,7 @@ go mod vendor ! grep 1.17 vendor/modules.txt ! go build example.net/need117 -stderr '^vendor[/\\]example\.net[/\\]need117[/\\]need117.go:5:18: .*\n\tconversion of slices to array pointers only supported as of -lang=go1\.17' +stderr '^vendor[/\\]example\.net[/\\]need117[/\\]need117.go:5:1[89]: .*conversion of slices to array pointers only supported as of -lang=go1\.17' ! grep 1.13 vendor/modules.txt go build example.net/bad114 -- GitLab From c1a14781eca85e9c705c782aa2071a5f9c23c09e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6hrmann?= Date: Sat, 24 Oct 2020 05:54:46 +0200 Subject: [PATCH 0803/2500] runtime: remove unused cpu architecture feature variables from binaries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On amd64 this reduces go binary sizes by 176 bytes due to not referencing internal/cpu.ARM64 and internal/cpu.ARM. Change-Id: I8e4f31e2b1939b05eec2148b44d7cff7e0aeb30e Reviewed-on: https://go-review.googlesource.com/c/go/+/344329 Trust: Martin Möhrmann Run-TryBot: Martin Möhrmann Reviewed-by: Tobias Klauser TryBot-Result: Go Bot --- src/runtime/proc.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index c2e43ef5c3..55023e3f9f 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -622,13 +622,18 @@ func cpuinit() { // Support cpu feature variables are used in code generated by the compiler // to guard execution of instructions that can not be assumed to be always supported. - x86HasPOPCNT = cpu.X86.HasPOPCNT - x86HasSSE41 = cpu.X86.HasSSE41 - x86HasFMA = cpu.X86.HasFMA + switch GOARCH { + case "386", "AMD64": + x86HasPOPCNT = cpu.X86.HasPOPCNT + x86HasSSE41 = cpu.X86.HasSSE41 + x86HasFMA = cpu.X86.HasFMA - armHasVFPv4 = cpu.ARM.HasVFPv4 + case "arm": + armHasVFPv4 = cpu.ARM.HasVFPv4 - arm64HasATOMICS = cpu.ARM64.HasATOMICS + case "arm64": + arm64HasATOMICS = cpu.ARM64.HasATOMICS + } } // The bootstrap sequence is: -- GitLab From c7e354d9d1975a3e55c8eb9e79c22106c4b770c4 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 16 Aug 2021 16:40:57 -0400 Subject: [PATCH 0804/2500] go/types: return an error from Instantiate This is a port of CL 342152 to go/types. Additionally, a panic was removed from interface substitution, which is a fix from CL 333155 that was previously missed. A check for a nil Checker was also removed from types2.instantiate, since check must not be nil in that method. Change-Id: I4ea6bdccbd50ea2008ee6d870f702bee5cdd5a8e Reviewed-on: https://go-review.googlesource.com/c/go/+/342671 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- .../compile/internal/types2/instantiate.go | 4 +- src/go/types/api.go | 12 + src/go/types/api_test.go | 39 ++- src/go/types/call.go | 4 +- src/go/types/instantiate.go | 229 ++++++++++-------- src/go/types/named.go | 32 +-- src/go/types/subst.go | 14 +- src/go/types/typexpr.go | 2 +- 8 files changed, 203 insertions(+), 133 deletions(-) diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index e0d889aa85..fdb8c40572 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -53,7 +53,8 @@ func Instantiate(check *Checker, typ Type, targs []Type, validate bool) (Type, e // later in the type checking pass. For Named types the resulting instance will // be unexpanded. func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, posList []syntax.Pos) (res Type) { - if check != nil && check.conf.Trace { + assert(check != nil) + if check.conf.Trace { check.trace(pos, "-- instantiating %s with %s", typ, typeListString(targs)) check.indent++ defer func() { @@ -69,7 +70,6 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, posLis }() } - assert(check != nil) inst := check.instance(pos, typ, targs) assert(len(posList) <= len(targs)) diff --git a/src/go/types/api.go b/src/go/types/api.go index 315f77f362..b8e772ada0 100644 --- a/src/go/types/api.go +++ b/src/go/types/api.go @@ -62,6 +62,18 @@ func (err Error) Error() string { return fmt.Sprintf("%s: %s", err.Fset.Position(err.Pos), err.Msg) } +// An ArgumentError holds an error associated with an argument index. +type ArgumentError struct { + index int + error +} + +// Index returns the positional index of the argument associated with the +// error. +func (e ArgumentError) Index() int { + return e.index +} + // An Importer resolves import paths to Packages. // // CAUTION: This interface does not support the import of locally diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index a49f2113b9..7a0419bfd5 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -1856,8 +1856,10 @@ func TestInstantiate(t *testing.T) { // instantiation should succeed (no endless recursion) // even with a nil *Checker - var check *Checker - res := check.Instantiate(token.NoPos, T, []Type{Typ[Int]}, nil, false) + res, err := Instantiate(nil, T, []Type{Typ[Int]}, false) + if err != nil { + t.Fatal(err) + } // instantiated type should point to itself if p := res.Underlying().(*Pointer).Elem(); p != res { @@ -1865,6 +1867,39 @@ func TestInstantiate(t *testing.T) { } } +func TestInstantiateErrors(t *testing.T) { + tests := []struct { + src string // by convention, T must be the type being instantiated + targs []Type + wantAt int // -1 indicates no error + }{ + {"type T[P interface{~string}] int", []Type{Typ[Int]}, 0}, + {"type T[P1 interface{int}, P2 interface{~string}] int", []Type{Typ[Int], Typ[Int]}, 1}, + {"type T[P1 any, P2 interface{~[]P1}] int", []Type{Typ[Int], NewSlice(Typ[String])}, 1}, + {"type T[P1 interface{~[]P2}, P2 any] int", []Type{NewSlice(Typ[String]), Typ[Int]}, 0}, + } + + for _, test := range tests { + src := genericPkg + "p; " + test.src + pkg, err := pkgFor(".", src, nil) + if err != nil { + t.Fatal(err) + } + + T := pkg.Scope().Lookup("T").Type().(*Named) + + _, err = Instantiate(nil, T, test.targs, true) + if err == nil { + t.Fatalf("Instantiate(%v, %v) returned nil error, want non-nil", T, test.targs) + } + + gotAt := err.(ArgumentError).Index() + if gotAt != test.wantAt { + t.Errorf("Instantate(%v, %v): error at index %d, want index %d", T, test.targs, gotAt, test.wantAt) + } + } +} + func TestInstanceIdentity(t *testing.T) { imports := make(testImporter) conf := Config{Importer: imports} diff --git a/src/go/types/call.go b/src/go/types/call.go index 08ef2451bf..87eeef444b 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -60,7 +60,7 @@ func (check *Checker) funcInst(x *operand, ix *typeparams.IndexExpr) { } // instantiate function signature - res := check.Instantiate(x.Pos(), sig, targs, poslist, true).(*Signature) + res := check.instantiate(x.Pos(), sig, targs, poslist).(*Signature) assert(res.TParams().Len() == 0) // signature is not generic anymore if inferred { check.recordInferred(ix.Orig, targs, res) @@ -332,7 +332,7 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type } // compute result signature - rsig = check.Instantiate(call.Pos(), sig, targs, nil, true).(*Signature) + rsig = check.instantiate(call.Pos(), sig, targs, nil).(*Signature) assert(rsig.TParams().Len() == 0) // signature is not generic anymore check.recordInferred(call, targs, rsig) diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 86e5e202c4..50341e064c 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -13,25 +13,124 @@ import ( "go/token" ) -// Instantiate instantiates the type typ with the given type arguments -// targs. To check type constraint satisfaction, verify must be set. -// pos and posList correspond to the instantiation and type argument -// positions respectively; posList may be nil or shorter than the number -// of type arguments provided. -// typ must be a *Named or a *Signature type, and its number of type -// parameters must match the number of provided type arguments. -// The receiver (check) may be nil if and only if verify is not set. -// The result is a new, instantiated (not generic) type of the same kind -// (either a *Named or a *Signature). -// Any methods attached to a *Named are simply copied; they are not -// instantiated. -func (check *Checker) Instantiate(pos token.Pos, typ Type, targs []Type, posList []token.Pos, verify bool) (res Type) { - var inst Type +// Instantiate instantiates the type typ with the given type arguments targs. +// typ must be a *Named or a *Signature type, and its number of type parameters +// must match the number of provided type arguments. The result is a new, +// instantiated (not parameterized) type of the same kind (either a *Named or a +// *Signature). Any methods attached to a *Named are simply copied; they are +// not instantiated. +// +// If check is non-nil, it will be used to de-dupe the instance against +// previous instances with the same identity. +// +// If verify is set and constraint satisfaction fails, the returned error may +// be of dynamic type ArgumentError indicating which type argument did not +// satisfy its corresponding type parameter constraint, and why. +// +// TODO(rfindley): change this function to also return an error if lengths of +// tparams and targs do not match. +func Instantiate(check *Checker, typ Type, targs []Type, validate bool) (Type, error) { + inst := check.instance(token.NoPos, typ, targs) + + var err error + if validate { + var tparams []*TypeName + switch t := typ.(type) { + case *Named: + tparams = t.TParams().list() + case *Signature: + tparams = t.TParams().list() + } + if i, err := check.verify(token.NoPos, tparams, targs); err != nil { + return inst, ArgumentError{i, err} + } + } + + return inst, err +} + +// instantiate creates an instance and defers verification of constraints to +// later in the type checking pass. For Named types the resulting instance will +// be unexpanded. +func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, posList []token.Pos) (res Type) { + assert(check != nil) + if trace { + check.trace(pos, "-- instantiating %s with %s", typ, typeListString(targs)) + check.indent++ + defer func() { + check.indent-- + var under Type + if res != nil { + // Calling under() here may lead to endless instantiations. + // Test case: type T[P any] T[P] + // TODO(gri) investigate if that's a bug or to be expected. + under = safeUnderlying(res) + } + check.trace(pos, "=> %s (under = %s)", res, under) + }() + } + + inst := check.instance(pos, typ, targs) + + assert(len(posList) <= len(targs)) + check.later(func() { + // Collect tparams again because lazily loaded *Named types may not have + // had tparams set up above. + var tparams []*TypeName + switch t := typ.(type) { + case *Named: + tparams = t.TParams().list() + case *Signature: + tparams = t.TParams().list() + } + // Avoid duplicate errors; instantiate will have complained if tparams + // and targs do not have the same length. + if len(tparams) == len(targs) { + if i, err := check.verify(pos, tparams, targs); err != nil { + // best position for error reporting + pos := pos + if i < len(posList) { + pos = posList[i] + } + check.softErrorf(atPos(pos), _Todo, err.Error()) + } + } + }) + return inst +} + +// instance creates a type or function instance using the given original type +// typ and arguments targs. For Named types the resulting instance will be +// unexpanded. +func (check *Checker) instance(pos token.Pos, typ Type, targs []Type) (res Type) { + // TODO(gri) What is better here: work with TypeParams, or work with TypeNames? switch t := typ.(type) { case *Named: - inst = check.instantiateLazy(pos, t, targs) + h := instantiatedHash(t, targs) + if check != nil { + // typ may already have been instantiated with identical type arguments. In + // that case, re-use the existing instance. + if named := check.typMap[h]; named != nil { + return named + } + } + + tname := NewTypeName(pos, t.obj.pkg, t.obj.name, nil) + named := check.newNamed(tname, t, nil, nil, nil) // methods and tparams are set when named is loaded + named.targs = targs + named.instance = &instance{pos} + if check != nil { + check.typMap[h] = named + } + res = named case *Signature: - tparams := t.TParams().list() + tparams := t.TParams() + if !check.validateTArgLen(pos, tparams, targs) { + return Typ[Invalid] + } + if tparams.Len() == 0 { + return typ // nothing to do (minor optimization) + } defer func() { // If we had an unexpected failure somewhere don't panic below when // asserting res.(*Signature). Check for *Signature in case Typ[Invalid] @@ -50,103 +149,27 @@ func (check *Checker) Instantiate(pos token.Pos, typ Type, targs []Type, posList // anymore; we need to set tparams to nil. res.(*Signature).tparams = nil }() - inst = check.instantiate(pos, typ, tparams, targs, nil) + res = check.subst(pos, typ, makeSubstMap(tparams.list(), targs), nil) default: // only types and functions can be generic panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } - - if verify { - if check == nil { - panic("cannot have nil Checker if verifying constraints") - } - assert(len(posList) <= len(targs)) - check.later(func() { - // Collect tparams again because lazily loaded *Named types may not have - // had tparams set up above. - var tparams []*TypeName - switch t := typ.(type) { - case *Named: - tparams = t.TParams().list() - case *Signature: - tparams = t.TParams().list() - } - // Avoid duplicate errors; instantiate will have complained if tparams - // and targs do not have the same length. - if len(tparams) == len(targs) { - if i, err := check.verify(pos, tparams, targs); err != nil { - // best position for error reporting - pos := pos - if i < len(posList) { - pos = posList[i] - } - check.softErrorf(atPos(pos), _Todo, err.Error()) - } - } - }) - } - - return inst + return res } -func (check *Checker) instantiate(pos token.Pos, typ Type, tparams []*TypeName, targs []Type, typMap map[string]*Named) (res Type) { - // the number of supplied types must match the number of type parameters - if len(targs) != len(tparams) { +// validateTArgLen verifies that the length of targs and tparams matches, +// reporting an error if not. If validation fails and check is nil, +// validateTArgLen panics. +func (check *Checker) validateTArgLen(pos token.Pos, tparams *TParamList, targs []Type) bool { + if len(targs) != tparams.Len() { // TODO(gri) provide better error message if check != nil { - check.errorf(atPos(pos), _Todo, "got %d arguments but %d type parameters", len(targs), len(tparams)) - return Typ[Invalid] + check.errorf(atPos(pos), _Todo, "got %d arguments but %d type parameters", len(targs), tparams.Len()) + return false } - panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, len(targs), len(tparams))) + panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, len(targs), tparams.Len())) } - - if check != nil && trace { - check.trace(pos, "-- instantiating %s with %s", typ, typeListString(targs)) - check.indent++ - defer func() { - check.indent-- - var under Type - if res != nil { - // Calling under() here may lead to endless instantiations. - // Test case: type T[P any] T[P] - // TODO(gri) investigate if that's a bug or to be expected. - under = safeUnderlying(res) - } - check.trace(pos, "=> %s (under = %s)", res, under) - }() - } - - // TODO(gri) What is better here: work with TypeParams, or work with TypeNames? - - if len(tparams) == 0 { - return typ // nothing to do (minor optimization) - } - - return check.subst(pos, typ, makeSubstMap(tparams, targs), typMap) -} - -// instantiateLazy avoids actually instantiating the type until needed. typ -// must be a *Named type. -func (check *Checker) instantiateLazy(pos token.Pos, orig *Named, targs []Type) Type { - h := instantiatedHash(orig, targs) - if check != nil { - // typ may already have been instantiated with identical type arguments. In - // that case, re-use the existing instance. - if named := check.typMap[h]; named != nil { - return named - } - } - - tname := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil) - named := check.newNamed(tname, orig, nil, nil, nil) // methods and tparams are set when named is loaded - named.targs = targs - named.instance = &instance{pos} - - if check != nil { - check.typMap[h] = named - } - - return named + return true } func (check *Checker) verify(pos token.Pos, tparams []*TypeName, targs []Type) (int, error) { diff --git a/src/go/types/named.go b/src/go/types/named.go index d621e5ef21..d547c47f8e 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -262,22 +262,26 @@ func (n *Named) expand(typMap map[string]*Named) *Named { // tparams. This is done implicitly by the call to n.TParams, but making it // explicit is harmless: load is idempotent. n.load() - if typMap == nil { - if n.check != nil { - typMap = n.check.typMap - } else { - // If we're instantiating lazily, we might be outside the scope of a - // type-checking pass. In that case we won't have a pre-existing - // typMap, but don't want to create a duplicate of the current instance - // in the process of expansion. - h := instantiatedHash(n.orig, n.targs) - typMap = map[string]*Named{h: n} + var u Type + if n.check.validateTArgLen(n.instance.pos, n.tparams, n.targs) { + if typMap == nil { + if n.check != nil { + typMap = n.check.typMap + } else { + // If we're instantiating lazily, we might be outside the scope of a + // type-checking pass. In that case we won't have a pre-existing + // typMap, but don't want to create a duplicate of the current instance + // in the process of expansion. + h := instantiatedHash(n.orig, n.targs) + typMap = map[string]*Named{h: n} + } } + u = n.check.subst(n.instance.pos, n.orig.underlying, makeSubstMap(n.TParams().list(), n.targs), typMap) + } else { + u = Typ[Invalid] } - - inst := n.check.instantiate(n.instance.pos, n.orig.underlying, n.TParams().list(), n.targs, typMap) - n.underlying = inst - n.fromRHS = inst + n.underlying = u + n.fromRHS = u n.instance = nil } return n diff --git a/src/go/types/subst.go b/src/go/types/subst.go index e47d20774f..72d5cac671 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -38,13 +38,12 @@ func (m substMap) lookup(tpar *TypeParam) Type { return tpar } -// subst returns the type typ with its type parameters tpars replaced by -// the corresponding type arguments targs, recursively. -// subst is functional in the sense that it doesn't modify the incoming -// type. If a substitution took place, the result type is different from -// from the incoming type. +// subst returns the type typ with its type parameters tpars replaced by the +// corresponding type arguments targs, recursively. subst is pure in the sense +// that it doesn't modify the incoming type. If a substitution took place, the +// result type is different from from the incoming type. // -// If the given typMap is nil and check is non-nil, check.typMap is used. +// If the given typMap is non-nil, it is used in lieu of check.typMap. func (check *Checker) subst(pos token.Pos, typ Type, smap substMap, typMap map[string]*Named) Type { if smap.empty() { return typ @@ -157,9 +156,6 @@ func (subst *subster) typ(typ Type) Type { embeddeds, ecopied := subst.typeList(t.embeddeds) if mcopied || ecopied { iface := &Interface{methods: methods, embeddeds: embeddeds, complete: t.complete} - if subst.check == nil { - panic("internal error: cannot instantiate interfaces yet") - } return iface } diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index def5871ce7..baa4e3c2d0 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -433,7 +433,7 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named posList[i] = arg.Pos() } - typ := check.Instantiate(x.Pos(), base, targs, posList, true) + typ := check.instantiate(x.Pos(), base, targs, posList) def.setUnderlying(typ) // make sure we check instantiation works at least once -- GitLab From baf2866956c2e03952383e19287a1e562cf09170 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 18 Aug 2021 13:22:38 -0400 Subject: [PATCH 0805/2500] go/types: move to an opaque environment for Instantiate To match the API proposal, switch the first argument to Instantiate to an opaque Environment handle, though for now this handle is unimplemented. Change-Id: I6207f0beafdf8497587abdad37db92f927db29b6 Reviewed-on: https://go-review.googlesource.com/c/go/+/343930 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/instantiate.go | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 50341e064c..8d7a9ecfb2 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -13,6 +13,19 @@ import ( "go/token" ) +// An Environment is an opaque type checking environment. It may be used to +// share identical type instances across type checked packages or calls to +// Instantiate. +// +// Currently, Environment is just a placeholder and has no effect on +// instantiation. +type Environment struct { + // Environment is currently un-implemented, because our instantiatedHash + // logic doesn't correctly handle Named type identity across multiple + // packages. + // TODO(rfindley): implement this. +} + // Instantiate instantiates the type typ with the given type arguments targs. // typ must be a *Named or a *Signature type, and its number of type parameters // must match the number of provided type arguments. The result is a new, @@ -20,8 +33,9 @@ import ( // *Signature). Any methods attached to a *Named are simply copied; they are // not instantiated. // -// If check is non-nil, it will be used to de-dupe the instance against -// previous instances with the same identity. +// If env is non-nil, it may be used to de-dupe the instance against previous +// instances with the same identity. This functionality is currently +// unimplemented. // // If verify is set and constraint satisfaction fails, the returned error may // be of dynamic type ArgumentError indicating which type argument did not @@ -29,8 +43,8 @@ import ( // // TODO(rfindley): change this function to also return an error if lengths of // tparams and targs do not match. -func Instantiate(check *Checker, typ Type, targs []Type, validate bool) (Type, error) { - inst := check.instance(token.NoPos, typ, targs) +func Instantiate(env *Environment, typ Type, targs []Type, validate bool) (Type, error) { + inst := (*Checker)(nil).instance(token.NoPos, typ, targs) var err error if validate { @@ -41,7 +55,7 @@ func Instantiate(check *Checker, typ Type, targs []Type, validate bool) (Type, e case *Signature: tparams = t.TParams().list() } - if i, err := check.verify(token.NoPos, tparams, targs); err != nil { + if i, err := (*Checker)(nil).verify(token.NoPos, tparams, targs); err != nil { return inst, ArgumentError{i, err} } } -- GitLab From 9fe5c7f12274fd4044457e863cbb8bc3ae751dcb Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 18 Aug 2021 13:22:58 -0400 Subject: [PATCH 0806/2500] go/types: add the TypeParam.Obj method Users should be able to access the type name associated with a type parameter. Change-Id: I495c3b4377f9d4807b1e78ad341e573d4d3c7bff Reviewed-on: https://go-review.googlesource.com/c/go/+/343931 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer --- src/go/types/typeparam.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index 6392504947..8d19d5db76 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -60,6 +60,9 @@ func (t *TypeParam) _SetId(id uint64) { t.id = id } +// Obj returns the type name for t. +func (t *TypeParam) Obj() *TypeName { return t.obj } + // Constraint returns the type constraint specified for t. func (t *TypeParam) Constraint() Type { // compute the type set if possible (we may not have an interface) -- GitLab From 2438660602677b1edf5e83a1ba4fdc5dfe9e9dcc Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Thu, 19 Aug 2021 13:31:36 -0400 Subject: [PATCH 0807/2500] go/types: use []*TypeParam rather than []*TypeName type param lists Making this change improves type safety slightly, and avoids many internal type assertions. Change-Id: I26519b0e57068e944e8243983ae90553d79e59c2 Reviewed-on: https://go-review.googlesource.com/c/go/+/343932 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/decl.go | 12 ++++++------ src/go/types/infer.go | 32 ++++++++++++++++---------------- src/go/types/instantiate.go | 10 +++++----- src/go/types/named.go | 4 ++-- src/go/types/object.go | 2 +- src/go/types/predicates.go | 4 ++-- src/go/types/signature.go | 16 ++++++++-------- src/go/types/subst.go | 4 ++-- src/go/types/typeparam.go | 11 +++++------ src/go/types/typestring.go | 7 +++---- src/go/types/unify.go | 14 +++++++------- 11 files changed, 57 insertions(+), 59 deletions(-) diff --git a/src/go/types/decl.go b/src/go/types/decl.go index c6505b63a1..8ebaf289f1 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -632,7 +632,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { } func (check *Checker) collectTypeParams(list *ast.FieldList) *TParamList { - var tparams []*TypeName + var tparams []*TypeParam // Declare type parameters up-front, with empty interface as type bound. // The scope of type parameters starts at the beginning of the type parameter // list (so we can have mutually recursive parameterized interfaces). @@ -648,7 +648,7 @@ func (check *Checker) collectTypeParams(list *ast.FieldList) *TParamList { } bound = check.boundType(f.Type) for i := range f.Names { - tparams[index+i].typ.(*TypeParam).bound = bound + tparams[index+i].bound = bound } next: @@ -658,11 +658,11 @@ func (check *Checker) collectTypeParams(list *ast.FieldList) *TParamList { return bindTParams(tparams) } -func (check *Checker) declareTypeParams(tparams []*TypeName, names []*ast.Ident) []*TypeName { +func (check *Checker) declareTypeParams(tparams []*TypeParam, names []*ast.Ident) []*TypeParam { for _, name := range names { - tpar := NewTypeName(name.Pos(), check.pkg, name.Name, nil) - check.NewTypeParam(tpar, &emptyInterface) // assigns type to tpar as a side-effect - check.declare(check.scope, name, tpar, check.scope.pos) // TODO(gri) check scope position + tname := NewTypeName(name.Pos(), check.pkg, name.Name, nil) + tpar := check.NewTypeParam(tname, &emptyInterface) // assigns type to tpar as a side-effect + check.declare(check.scope, name, tname, check.scope.pos) // TODO(gri) check scope position tparams = append(tparams, tpar) } diff --git a/src/go/types/infer.go b/src/go/types/infer.go index 57ec327d12..58456444ed 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -27,7 +27,7 @@ import ( // // Constraint type inference is used after each step to expand the set of type arguments. // -func (check *Checker) infer(posn positioner, tparams []*TypeName, targs []Type, params *Tuple, args []*operand, report bool) (result []Type) { +func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, params *Tuple, args []*operand, report bool) (result []Type) { if debug { defer func() { assert(result == nil || len(result) == len(tparams)) @@ -121,7 +121,7 @@ func (check *Checker) infer(posn positioner, tparams []*TypeName, targs []Type, } } if allFailed { - check.errorf(arg, _Todo, "%s %s of %s does not match %s (cannot infer %s)", kind, targ, arg.expr, tpar, typeNamesString(tparams)) + check.errorf(arg, _Todo, "%s %s of %s does not match %s (cannot infer %s)", kind, targ, arg.expr, tpar, typeParamsString(tparams)) return } } @@ -218,23 +218,23 @@ func (check *Checker) infer(posn positioner, tparams []*TypeName, targs []Type, assert(index >= 0 && targs[index] == nil) tpar := tparams[index] if report { - check.errorf(posn, _Todo, "cannot infer %s (%v) (%v)", tpar.name, tpar.pos, targs) + check.errorf(posn, _Todo, "cannot infer %s (%v) (%v)", tpar.obj.name, tpar.obj.pos, targs) } return nil } -// typeNamesString produces a string containing all the -// type names in list suitable for human consumption. -func typeNamesString(list []*TypeName) string { +// typeParamsString produces a string containing all the type parameter names +// in list suitable for human consumption. +func typeParamsString(list []*TypeParam) string { // common cases n := len(list) switch n { case 0: return "" case 1: - return list[0].name + return list[0].obj.name case 2: - return list[0].name + " and " + list[1].name + return list[0].obj.name + " and " + list[1].obj.name } // general case (n > 2) @@ -243,15 +243,15 @@ func typeNamesString(list []*TypeName) string { if i > 0 { b.WriteString(", ") } - b.WriteString(tname.name) + b.WriteString(tname.obj.name) } b.WriteString(", and ") - b.WriteString(list[n-1].name) + b.WriteString(list[n-1].obj.name) return b.String() } // IsParameterized reports whether typ contains any of the type parameters of tparams. -func isParameterized(tparams []*TypeName, typ Type) bool { +func isParameterized(tparams []*TypeParam, typ Type) bool { w := tpWalker{ seen: make(map[Type]bool), tparams: tparams, @@ -261,7 +261,7 @@ func isParameterized(tparams []*TypeName, typ Type) bool { type tpWalker struct { seen map[Type]bool - tparams []*TypeName + tparams []*TypeParam } func (w *tpWalker) isParameterized(typ Type) (res bool) { @@ -334,7 +334,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { case *TypeParam: // t must be one of w.tparams - return t.index < len(w.tparams) && w.tparams[t.index].typ == t + return t.index < len(w.tparams) && w.tparams[t.index] == t default: unreachable() @@ -360,7 +360,7 @@ func (w *tpWalker) isParameterizedTypeList(list []Type) bool { // first type argument in that list that couldn't be inferred (and thus is nil). If all // type arguments were inferred successfully, index is < 0. The number of type arguments // provided may be less than the number of type parameters, but there must be at least one. -func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (types []Type, index int) { +func (check *Checker) inferB(tparams []*TypeParam, targs []Type, report bool) (types []Type, index int) { assert(len(tparams) >= len(targs) && len(targs) > 0) // Setup bidirectional unification between those structural bounds @@ -378,12 +378,12 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty // Unify type parameters with their structural constraints, if any. for _, tpar := range tparams { - typ := tpar.typ.(*TypeParam) + typ := tpar sbound := typ.structuralType() if sbound != nil { if !u.unify(typ, sbound) { if report { - check.errorf(tpar, _Todo, "%s does not match %s", tpar, sbound) + check.errorf(tpar.obj, _Todo, "%s does not match %s", tpar.obj, sbound) } return nil, 0 } diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 8d7a9ecfb2..fb2fddfc0f 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -48,7 +48,7 @@ func Instantiate(env *Environment, typ Type, targs []Type, validate bool) (Type, var err error if validate { - var tparams []*TypeName + var tparams []*TypeParam switch t := typ.(type) { case *Named: tparams = t.TParams().list() @@ -90,7 +90,7 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, posList check.later(func() { // Collect tparams again because lazily loaded *Named types may not have // had tparams set up above. - var tparams []*TypeName + var tparams []*TypeParam switch t := typ.(type) { case *Named: tparams = t.TParams().list() @@ -186,11 +186,11 @@ func (check *Checker) validateTArgLen(pos token.Pos, tparams *TParamList, targs return true } -func (check *Checker) verify(pos token.Pos, tparams []*TypeName, targs []Type) (int, error) { +func (check *Checker) verify(pos token.Pos, tparams []*TypeParam, targs []Type) (int, error) { smap := makeSubstMap(tparams, targs) - for i, tname := range tparams { + for i, tpar := range tparams { // stop checking bounds after the first failure - if err := check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap); err != nil { + if err := check.satisfies(pos, targs[i], tpar, smap); err != nil { return i, err } } diff --git a/src/go/types/named.go b/src/go/types/named.go index d547c47f8e..105f34e1fb 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -24,7 +24,7 @@ type Named struct { targs []Type // type arguments (after instantiation), or nil methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily - resolve func(*Named) ([]*TypeName, Type, []*Func) + resolve func(*Named) ([]*TypeParam, Type, []*Func) once sync.Once } @@ -126,7 +126,7 @@ func (t *Named) _Orig() *Named { return t.orig } func (t *Named) TParams() *TParamList { return t.load().tparams } // SetTParams sets the type parameters of the named type t. -func (t *Named) SetTParams(tparams []*TypeName) { t.load().tparams = bindTParams(tparams) } +func (t *Named) SetTParams(tparams []*TypeParam) { t.load().tparams = bindTParams(tparams) } // NumTArgs returns the number of type arguments used to instantiate the named // type t, or 0 if t is not an instantiated type. diff --git a/src/go/types/object.go b/src/go/types/object.go index 7266623fbe..eb5df56d14 100644 --- a/src/go/types/object.go +++ b/src/go/types/object.go @@ -232,7 +232,7 @@ func NewTypeName(pos token.Pos, pkg *Package, name string, typ Type) *TypeName { // _NewTypeNameLazy returns a new defined type like NewTypeName, but it // lazily calls resolve to finish constructing the Named object. -func _NewTypeNameLazy(pos token.Pos, pkg *Package, name string, resolve func(named *Named) (tparams []*TypeName, underlying Type, methods []*Func)) *TypeName { +func _NewTypeNameLazy(pos token.Pos, pkg *Package, name string, resolve func(named *Named) (tparams []*TypeParam, underlying Type, methods []*Func)) *TypeName { obj := NewTypeName(pos, pkg, name, nil) NewNamed(obj, nil, nil).resolve = resolve return obj diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 0945dac722..027e30c1a1 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -351,13 +351,13 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { return false } -func identicalTParams(x, y []*TypeName, cmpTags bool, p *ifacePair) bool { +func identicalTParams(x, y []*TypeParam, cmpTags bool, p *ifacePair) bool { if len(x) != len(y) { return false } for i, x := range x { y := y[i] - if !identical(x.typ.(*TypeParam).bound, y.typ.(*TypeParam).bound, cmpTags, p) { + if !identical(x.bound, y.bound, cmpTags, p) { return false } } diff --git a/src/go/types/signature.go b/src/go/types/signature.go index 9bfb1683a7..d6c12cf3d9 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -59,13 +59,13 @@ func (s *Signature) Recv() *Var { return s.recv } func (s *Signature) TParams() *TParamList { return s.tparams } // SetTParams sets the type parameters of signature s. -func (s *Signature) SetTParams(tparams []*TypeName) { s.tparams = bindTParams(tparams) } +func (s *Signature) SetTParams(tparams []*TypeParam) { s.tparams = bindTParams(tparams) } // RParams returns the receiver type parameters of signature s, or nil. func (s *Signature) RParams() *TParamList { return s.rparams } // SetRParams sets the receiver type params of signature s. -func (s *Signature) SetRParams(rparams []*TypeName) { s.rparams = bindTParams(rparams) } +func (s *Signature) SetRParams(rparams []*TypeParam) { s.rparams = bindTParams(rparams) } // Params returns the parameters of signature s, or nil. func (s *Signature) Params() *Tuple { return s.params } @@ -121,7 +121,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast sig.rparams = bindTParams(check.declareTypeParams(nil, rparams)) // determine receiver type to get its type parameters // and the respective type parameter bounds - var recvTParams []*TypeName + var recvTParams []*TypeParam if rname != nil { // recv should be a Named type (otherwise an error is reported elsewhere) // Also: Don't report an error via genericType since it will be reported @@ -137,19 +137,19 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast // We have a list of *TypeNames but we need a list of Types. list := make([]Type, sig.RParams().Len()) for i, t := range sig.RParams().list() { - list[i] = t.typ + list[i] = t } smap := makeSubstMap(recvTParams, list) - for i, tname := range sig.RParams().list() { - bound := recvTParams[i].typ.(*TypeParam).bound + for i, tpar := range sig.RParams().list() { + bound := recvTParams[i].bound // bound is (possibly) parameterized in the context of the // receiver type declaration. Substitute parameters for the // current context. // TODO(gri) should we assume now that bounds always exist? // (no bound == empty interface) if bound != nil { - bound = check.subst(tname.pos, bound, smap, nil) - tname.typ.(*TypeParam).bound = bound + bound = check.subst(tpar.obj.pos, bound, smap, nil) + tpar.bound = bound } } } diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 72d5cac671..75f1ca5fab 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -18,11 +18,11 @@ type substMap map[*TypeParam]Type // makeSubstMap creates a new substitution map mapping tpars[i] to targs[i]. // If targs[i] is nil, tpars[i] is not substituted. -func makeSubstMap(tpars []*TypeName, targs []Type) substMap { +func makeSubstMap(tpars []*TypeParam, targs []Type) substMap { assert(len(tpars) == len(targs)) proj := make(substMap, len(tpars)) for i, tpar := range tpars { - proj[tpar.typ.(*TypeParam)] = targs[i] + proj[tpar] = targs[i] } return proj } diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index 8d19d5db76..49eda1b43a 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -89,7 +89,7 @@ func (t *TypeParam) Underlying() Type { return t } func (t *TypeParam) String() string { return TypeString(t, nil) } // TParamList holds a list of type parameters bound to a type. -type TParamList struct{ tparams []*TypeName } +type TParamList struct{ tparams []*TypeParam } // Len returns the number of type parameters in the list. // It is safe to call on a nil receiver. @@ -98,23 +98,22 @@ func (tps *TParamList) Len() int { } // At returns the i'th type parameter in the list. -func (tps *TParamList) At(i int) *TypeName { +func (tps *TParamList) At(i int) *TypeParam { return tps.list()[i] } -func (tps *TParamList) list() []*TypeName { +func (tps *TParamList) list() []*TypeParam { if tps == nil { return nil } return tps.tparams } -func bindTParams(list []*TypeName) *TParamList { +func bindTParams(list []*TypeParam) *TParamList { if len(list) == 0 { return nil } - for i, tp := range list { - typ := tp.Type().(*TypeParam) + for i, typ := range list { if typ.index >= 0 { panic("type parameter bound more than once") } diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 452c92f74d..41dde0e469 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -244,15 +244,14 @@ func writeTypeList(buf *bytes.Buffer, list []Type, qf Qualifier, visited []Type) } } -func writeTParamList(buf *bytes.Buffer, list []*TypeName, qf Qualifier, visited []Type) { +func writeTParamList(buf *bytes.Buffer, list []*TypeParam, qf Qualifier, visited []Type) { // TODO(rFindley) compare this with the corresponding implementation in types2 buf.WriteString("[") var prev Type - for i, p := range list { + for i, tpar := range list { // Determine the type parameter and its constraint. // list is expected to hold type parameter names, // but don't crash if that's not the case. - tpar, _ := p.typ.(*TypeParam) var bound Type if tpar != nil { bound = tpar.bound // should not be nil but we want to see it if it is @@ -271,7 +270,7 @@ func writeTParamList(buf *bytes.Buffer, list []*TypeName, qf Qualifier, visited if tpar != nil { writeType(buf, tpar, qf, visited) } else { - buf.WriteString(p.name) + buf.WriteString(tpar.obj.name) } } if prev != nil { diff --git a/src/go/types/unify.go b/src/go/types/unify.go index de87466fe8..8f5b23ce39 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -63,7 +63,7 @@ func (u *unifier) unify(x, y Type) bool { // A tparamsList describes a list of type parameters and the types inferred for them. type tparamsList struct { unifier *unifier - tparams []*TypeName + tparams []*TypeParam // For each tparams element, there is a corresponding type slot index in indices. // index < 0: unifier.types[-index-1] == nil // index == 0: no type slot allocated yet @@ -78,11 +78,11 @@ type tparamsList struct { func (d *tparamsList) String() string { var buf bytes.Buffer buf.WriteByte('[') - for i, tname := range d.tparams { + for i, tpar := range d.tparams { if i > 0 { buf.WriteString(", ") } - writeType(&buf, tname.typ, nil, nil) + writeType(&buf, tpar, nil, nil) buf.WriteString(": ") writeType(&buf, d.at(i), nil, nil) } @@ -93,13 +93,13 @@ func (d *tparamsList) String() string { // init initializes d with the given type parameters. // The type parameters must be in the order in which they appear in their declaration // (this ensures that the tparams indices match the respective type parameter index). -func (d *tparamsList) init(tparams []*TypeName) { +func (d *tparamsList) init(tparams []*TypeParam) { if len(tparams) == 0 { return } if debug { for i, tpar := range tparams { - assert(i == tpar.typ.(*TypeParam).index) + assert(i == tpar.index) } } d.tparams = tparams @@ -155,8 +155,8 @@ func (d *tparamsList) index(typ Type) int { // If tpar is a type parameter in list, tparamIndex returns the type parameter index. // Otherwise, the result is < 0. tpar must not be nil. -func tparamIndex(list []*TypeName, tpar *TypeParam) int { - if i := tpar.index; i < len(list) && list[i].typ == tpar { +func tparamIndex(list []*TypeParam, tpar *TypeParam) int { + if i := tpar.index; i < len(list) && list[i] == tpar { return i } return -1 -- GitLab From 7a6d64fed6e4122743aa204edd42a02e40ce9728 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Thu, 19 Aug 2021 14:06:08 -0400 Subject: [PATCH 0808/2500] go/types: use a TypeList type to hold type arguments This resolves an asymmetry between the TParams and TArgs APIs, and reduces the size of the Named struct at the cost of some additional nil checks. While at it, move TParamList and TypeList to a new file:typelists.go, and change TParamList to access the tparams slice directly in At. There is no reason to guard against a nil receiver, as accessing an index on the empty slice will panic anyway. Change-Id: I9b65247e06c697a57a4efe40c3390e0faff91441 Reviewed-on: https://go-review.googlesource.com/c/go/+/343933 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/infer.go | 2 +- src/go/types/instantiate.go | 12 ++++---- src/go/types/lookup.go | 4 +-- src/go/types/named.go | 18 +++++------ src/go/types/predicates.go | 12 ++++---- src/go/types/sizeof_test.go | 2 +- src/go/types/subst.go | 8 ++--- src/go/types/typelists.go | 61 +++++++++++++++++++++++++++++++++++++ src/go/types/typeparam.go | 34 --------------------- src/go/types/typestring.go | 2 +- src/go/types/unify.go | 10 ++++-- 11 files changed, 96 insertions(+), 69 deletions(-) create mode 100644 src/go/types/typelists.go diff --git a/src/go/types/infer.go b/src/go/types/infer.go index 58456444ed..e6417545e9 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -330,7 +330,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { return w.isParameterized(t.elem) case *Named: - return w.isParameterizedTypeList(t.targs) + return w.isParameterizedTypeList(t.targs.list()) case *TypeParam: // t must be one of w.tparams diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index fb2fddfc0f..3ee09b7e84 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -131,7 +131,7 @@ func (check *Checker) instance(pos token.Pos, typ Type, targs []Type) (res Type) tname := NewTypeName(pos, t.obj.pkg, t.obj.name, nil) named := check.newNamed(tname, t, nil, nil, nil) // methods and tparams are set when named is loaded - named.targs = targs + named.targs = &TypeList{targs} named.instance = &instance{pos} if check != nil { check.typMap[h] = named @@ -139,7 +139,7 @@ func (check *Checker) instance(pos token.Pos, typ Type, targs []Type) (res Type) res = named case *Signature: tparams := t.TParams() - if !check.validateTArgLen(pos, tparams, targs) { + if !check.validateTArgLen(pos, tparams.Len(), len(targs)) { return Typ[Invalid] } if tparams.Len() == 0 { @@ -174,14 +174,14 @@ func (check *Checker) instance(pos token.Pos, typ Type, targs []Type) (res Type) // validateTArgLen verifies that the length of targs and tparams matches, // reporting an error if not. If validation fails and check is nil, // validateTArgLen panics. -func (check *Checker) validateTArgLen(pos token.Pos, tparams *TParamList, targs []Type) bool { - if len(targs) != tparams.Len() { +func (check *Checker) validateTArgLen(pos token.Pos, ntparams, ntargs int) bool { + if ntargs != ntparams { // TODO(gri) provide better error message if check != nil { - check.errorf(atPos(pos), _Todo, "got %d arguments but %d type parameters", len(targs), tparams.Len()) + check.errorf(atPos(pos), _Todo, "got %d arguments but %d type parameters", ntargs, ntparams) return false } - panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, len(targs), tparams.Len())) + panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, ntargs, ntparams)) } return true } diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index 20a24cab73..862e59401d 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -392,10 +392,10 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // here. Exit early in this case to prevent an assertion // failure in makeSubstMap. // TODO(gri) Can we avoid this check by fixing the lengths? - if len(ftyp.RParams().list()) != len(Vn.targs) { + if len(ftyp.RParams().list()) != Vn.targs.Len() { return } - ftyp = check.subst(token.NoPos, ftyp, makeSubstMap(ftyp.RParams().list(), Vn.targs), nil).(*Signature) + ftyp = check.subst(token.NoPos, ftyp, makeSubstMap(ftyp.RParams().list(), Vn.targs.list()), nil).(*Signature) } // If the methods have type parameters we don't care whether they diff --git a/src/go/types/named.go b/src/go/types/named.go index 105f34e1fb..6bc33b9538 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -21,7 +21,7 @@ type Named struct { underlying Type // possibly a *Named during setup; never a *Named once set up completely instance *instance // syntactic information for lazy instantiation tparams *TParamList // type parameters, or nil - targs []Type // type arguments (after instantiation), or nil + targs *TypeList // type arguments (after instantiation), or nil methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily resolve func(*Named) ([]*TypeParam, Type, []*Func) @@ -46,7 +46,7 @@ func (t *Named) load() *Named { // underlying is set when t is expanded. // // By convention, a type instance is loaded iff its tparams are set. - if len(t.targs) > 0 && t.tparams == nil { + if t.targs.Len() > 0 && t.tparams == nil { t.orig.load() t.tparams = t.orig.tparams t.methods = t.orig.methods @@ -128,12 +128,8 @@ func (t *Named) TParams() *TParamList { return t.load().tparams } // SetTParams sets the type parameters of the named type t. func (t *Named) SetTParams(tparams []*TypeParam) { t.load().tparams = bindTParams(tparams) } -// NumTArgs returns the number of type arguments used to instantiate the named -// type t, or 0 if t is not an instantiated type. -func (t *Named) NumTArgs() int { return len(t.targs) } - -// TArgs returns the i'th type argument of the named type t for 0 <= i < t.NumTArgs(). -func (t *Named) TArg(i int) Type { return t.targs[i] } +// TArgs returns the type arguments used to instantiate the named type t. +func (t *Named) TArgs() *TypeList { return t.targs } // NumMethods returns the number of explicit methods whose receiver is named type t. func (t *Named) NumMethods() int { return len(t.load().methods) } @@ -263,7 +259,7 @@ func (n *Named) expand(typMap map[string]*Named) *Named { // explicit is harmless: load is idempotent. n.load() var u Type - if n.check.validateTArgLen(n.instance.pos, n.tparams, n.targs) { + if n.check.validateTArgLen(n.instance.pos, n.tparams.Len(), n.targs.Len()) { if typMap == nil { if n.check != nil { typMap = n.check.typMap @@ -272,11 +268,11 @@ func (n *Named) expand(typMap map[string]*Named) *Named { // type-checking pass. In that case we won't have a pre-existing // typMap, but don't want to create a duplicate of the current instance // in the process of expansion. - h := instantiatedHash(n.orig, n.targs) + h := instantiatedHash(n.orig, n.targs.list()) typMap = map[string]*Named{h: n} } } - u = n.check.subst(n.instance.pos, n.orig.underlying, makeSubstMap(n.TParams().list(), n.targs), typMap) + u = n.check.subst(n.instance.pos, n.orig.underlying, makeSubstMap(n.TParams().list(), n.targs.list()), typMap) } else { u = Typ[Invalid] } diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 027e30c1a1..2f4ef9dace 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -305,22 +305,22 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { x.expand(nil) y.expand(nil) - // xargs := x.TArgs() - // yargs := y.TArgs() + xargs := x.TArgs().list() + yargs := y.TArgs().list() - if x.NumTArgs() != y.NumTArgs() { + if len(xargs) != len(yargs) { return false } - if nargs := x.NumTArgs(); nargs > 0 { + if nargs := len(xargs); nargs > 0 { // Instances are identical if their original type and type arguments // are identical. if !Identical(x.orig, y.orig) { return false } for i := 0; i < nargs; i++ { - xa := x.TArg(i) - ya := y.TArg(i) + xa := xargs[i] + ya := yargs[i] if !Identical(xa, ya) { return false } diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index 403f2bbece..c2f5b3c333 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -30,7 +30,7 @@ func TestSizeof(t *testing.T) { {Interface{}, 40, 80}, {Map{}, 16, 32}, {Chan{}, 12, 24}, - {Named{}, 80, 152}, + {Named{}, 72, 136}, {TypeParam{}, 28, 48}, {term{}, 12, 24}, {top{}, 0, 0}, diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 75f1ca5fab..8b8d6fb82a 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -191,21 +191,21 @@ func (subst *subster) typ(typ Type) Type { } var newTArgs []Type - assert(len(t.targs) == t.TParams().Len()) + assert(t.targs.Len() == t.TParams().Len()) // already instantiated dump(">>> %s already instantiated", t) // For each (existing) type argument targ, determine if it needs // to be substituted; i.e., if it is or contains a type parameter // that has a type argument for it. - for i, targ := range t.targs { + for i, targ := range t.targs.list() { dump(">>> %d targ = %s", i, targ) new_targ := subst.typ(targ) if new_targ != targ { dump(">>> substituted %d targ %s => %s", i, targ, new_targ) if newTArgs == nil { newTArgs = make([]Type, t.TParams().Len()) - copy(newTArgs, t.targs) + copy(newTArgs, t.targs.list()) } newTArgs[i] = new_targ } @@ -233,7 +233,7 @@ func (subst *subster) typ(typ Type) Type { // It's ok to provide a nil *Checker because the newly created type // doesn't need to be (lazily) expanded; it's expanded below. named := (*Checker)(nil).newNamed(tname, t.orig, nil, t.tparams, t.methods) // t is loaded, so tparams and methods are available - named.targs = newTArgs + named.targs = &TypeList{newTArgs} subst.typMap[h] = named t.expand(subst.typMap) // must happen after typMap update to avoid infinite recursion diff --git a/src/go/types/typelists.go b/src/go/types/typelists.go new file mode 100644 index 0000000000..a8181404bf --- /dev/null +++ b/src/go/types/typelists.go @@ -0,0 +1,61 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +// TParamList holds a list of type parameters. +type TParamList struct{ tparams []*TypeParam } + +// Len returns the number of type parameters in the list. +// It is safe to call on a nil receiver. +func (l *TParamList) Len() int { return len(l.list()) } + +// At returns the i'th type parameter in the list. +func (l *TParamList) At(i int) *TypeParam { return l.tparams[i] } + +// list is for internal use where we expect a []*TypeParam. +// TODO(rfindley): list should probably be eliminated: we can pass around a +// TParamList instead. +func (l *TParamList) list() []*TypeParam { + if l == nil { + return nil + } + return l.tparams +} + +// TypeList holds a list of types. +type TypeList struct{ types []Type } + +// Len returns the number of types in the list. +// It is safe to call on a nil receiver. +func (l *TypeList) Len() int { return len(l.list()) } + +// At returns the i'th type in the list. +func (l *TypeList) At(i int) Type { return l.types[i] } + +// list is for internal use where we expect a []Type. +// TODO(rfindley): list should probably be eliminated: we can pass around a +// TypeList instead. +func (l *TypeList) list() []Type { + if l == nil { + return nil + } + return l.types +} + +// ---------------------------------------------------------------------------- +// Implementation + +func bindTParams(list []*TypeParam) *TParamList { + if len(list) == 0 { + return nil + } + for i, typ := range list { + if typ.index >= 0 { + panic("type parameter bound more than once") + } + typ.index = i + } + return &TParamList{tparams: list} +} diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index 49eda1b43a..b6952489ca 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -88,40 +88,6 @@ func (t *TypeParam) SetConstraint(bound Type) { func (t *TypeParam) Underlying() Type { return t } func (t *TypeParam) String() string { return TypeString(t, nil) } -// TParamList holds a list of type parameters bound to a type. -type TParamList struct{ tparams []*TypeParam } - -// Len returns the number of type parameters in the list. -// It is safe to call on a nil receiver. -func (tps *TParamList) Len() int { - return len(tps.list()) -} - -// At returns the i'th type parameter in the list. -func (tps *TParamList) At(i int) *TypeParam { - return tps.list()[i] -} - -func (tps *TParamList) list() []*TypeParam { - if tps == nil { - return nil - } - return tps.tparams -} - -func bindTParams(list []*TypeParam) *TParamList { - if len(list) == 0 { - return nil - } - for i, typ := range list { - if typ.index >= 0 { - panic("type parameter bound more than once") - } - typ.index = i - } - return &TParamList{tparams: list} -} - // ---------------------------------------------------------------------------- // Implementation diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 41dde0e469..cdc7ea9f51 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -204,7 +204,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { if t.targs != nil { // instantiated type buf.WriteByte('[') - writeTypeList(buf, t.targs, qf, visited) + writeTypeList(buf, t.targs.list(), qf, visited) buf.WriteByte(']') } else if t.TParams().Len() != 0 { // parameterized type diff --git a/src/go/types/unify.go b/src/go/types/unify.go index 8f5b23ce39..1720646db9 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -426,13 +426,17 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { if y, ok := y.(*Named); ok { x.expand(nil) y.expand(nil) + + xargs := x.targs.list() + yargs := y.targs.list() + // TODO(gri) This is not always correct: two types may have the same names // in the same package if one of them is nested in a function. // Extremely unlikely but we need an always correct solution. if x.obj.pkg == y.obj.pkg && x.obj.name == y.obj.name { - assert(len(x.targs) == len(y.targs)) - for i, x := range x.targs { - if !u.nify(x, y.targs[i], p) { + assert(len(xargs) == len(yargs)) + for i, x := range xargs { + if !u.nify(x, yargs[i], p) { return false } } -- GitLab From 4fbb5c8666eef0267704dd074763442efb2f7c4a Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Fri, 20 Aug 2021 10:19:12 -0400 Subject: [PATCH 0809/2500] go/types: use TypeList in the Inferred struct This is for consistency with how we report TArgs elsewhere, and in case we ever want to share an internal slice with inference reporting. Change-Id: Ia8b705a155f4f82bd8da8dc2457289810f875f5e Reviewed-on: https://go-review.googlesource.com/c/go/+/343934 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/api.go | 2 +- src/go/types/api_test.go | 9 +++++---- src/go/types/check.go | 4 ++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/go/types/api.go b/src/go/types/api.go index b8e772ada0..5beeff530c 100644 --- a/src/go/types/api.go +++ b/src/go/types/api.go @@ -363,7 +363,7 @@ func (tv TypeAndValue) HasOk() bool { // Inferred reports the Inferred type arguments and signature // for a parameterized function call that uses type inference. type Inferred struct { - TArgs []Type + TArgs *TypeList Sig *Signature } diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index 7a0419bfd5..1e7d6f2cfa 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -482,7 +482,7 @@ func TestInferredInfo(t *testing.T) { } // look for inferred type arguments and signature - var targs []Type + var targs *TypeList var sig *Signature for call, inf := range info.Inferred { var fun ast.Expr @@ -506,11 +506,12 @@ func TestInferredInfo(t *testing.T) { } // check that type arguments are correct - if len(targs) != len(test.targs) { - t.Errorf("package %s: got %d type arguments; want %d", name, len(targs), len(test.targs)) + if targs.Len() != len(test.targs) { + t.Errorf("package %s: got %d type arguments; want %d", name, targs.Len(), len(test.targs)) continue } - for i, targ := range targs { + for i := 0; i < targs.Len(); i++ { + targ := targs.At(i) if got := targ.String(); got != test.targs[i] { t.Errorf("package %s, %d. type argument: got %s; want %s", name, i, got, test.targs[i]) continue diff --git a/src/go/types/check.go b/src/go/types/check.go index b2d076dc68..909bf8d52d 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -406,8 +406,8 @@ func (check *Checker) recordCommaOkTypes(x ast.Expr, a [2]Type) { func (check *Checker) recordInferred(call ast.Expr, targs []Type, sig *Signature) { assert(call != nil) assert(sig != nil) - if m := check.Info.Inferred; m != nil { - m[call] = Inferred{targs, sig} + if m := check.Inferred; m != nil { + m[call] = Inferred{&TypeList{targs}, sig} } } -- GitLab From f1d8ea1da3ef814ea57b545fc967865640a868ab Mon Sep 17 00:00:00 2001 From: Lynn Boger Date: Fri, 20 Aug 2021 07:01:50 -0500 Subject: [PATCH 0810/2500] reflect: fix memmove for big endian cases with new ABI Some memmoves in reflect/value.go for copying arguments related to the new ABI were using the address of the target or source instead of using IntArgRegAddr or FloatArgRegAddr to adjust the address for big endian. This was found when testing patches for ppc64 and fixes the failures that were found. Change-Id: I119aa090a2a8eb859020ff1a1736107a6d0b76f1 Reviewed-on: https://go-review.googlesource.com/c/go/+/343869 Run-TryBot: Lynn Boger TryBot-Result: Go Bot Reviewed-by: Michael Knyszek Trust: Michael Knyszek Trust: Lynn Boger --- src/reflect/value.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/reflect/value.go b/src/reflect/value.go index e641a7957c..de01f13825 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -508,7 +508,7 @@ func (v Value) call(op string, in []Value) []Value { // Copy values to "integer registers." if v.flag&flagIndir != 0 { offset := add(v.ptr, st.offset, "precomputed value offset") - memmove(unsafe.Pointer(®Args.Ints[st.ireg]), offset, st.size) + memmove(regArgs.IntRegArgAddr(st.ireg, st.size), offset, st.size) } else { if st.kind == abiStepPointer { // Duplicate this pointer in the pointer area of the @@ -524,7 +524,7 @@ func (v Value) call(op string, in []Value) []Value { panic("attempted to copy pointer to FP register") } offset := add(v.ptr, st.offset, "precomputed value offset") - memmove(unsafe.Pointer(®Args.Floats[st.freg]), offset, st.size) + memmove(regArgs.FloatRegArgAddr(st.freg, st.size), offset, st.size) default: panic("unknown ABI part kind") } @@ -610,13 +610,13 @@ func (v Value) call(op string, in []Value) []Value { switch st.kind { case abiStepIntReg: offset := add(s, st.offset, "precomputed value offset") - memmove(offset, unsafe.Pointer(®Args.Ints[st.ireg]), st.size) + memmove(offset, regArgs.IntRegArgAddr(st.ireg, st.size), st.size) case abiStepPointer: s := add(s, st.offset, "precomputed value offset") *((*unsafe.Pointer)(s)) = regArgs.Ptrs[st.ireg] case abiStepFloatReg: offset := add(s, st.offset, "precomputed value offset") - memmove(offset, unsafe.Pointer(®Args.Floats[st.freg]), st.size) + memmove(offset, regArgs.FloatRegArgAddr(st.freg, st.size), st.size) case abiStepStack: panic("register-based return value has stack component") default: @@ -698,13 +698,13 @@ func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer, retValid *bool, regs switch st.kind { case abiStepIntReg: offset := add(v.ptr, st.offset, "precomputed value offset") - memmove(offset, unsafe.Pointer(®s.Ints[st.ireg]), st.size) + memmove(offset, regs.IntRegArgAddr(st.ireg, st.size), st.size) case abiStepPointer: s := add(v.ptr, st.offset, "precomputed value offset") *((*unsafe.Pointer)(s)) = regs.Ptrs[st.ireg] case abiStepFloatReg: offset := add(v.ptr, st.offset, "precomputed value offset") - memmove(offset, unsafe.Pointer(®s.Floats[st.freg]), st.size) + memmove(offset, regs.FloatRegArgAddr(st.freg, st.size), st.size) case abiStepStack: panic("register-based return value has stack component") default: @@ -784,7 +784,7 @@ func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer, retValid *bool, regs // Copy values to "integer registers." if v.flag&flagIndir != 0 { offset := add(v.ptr, st.offset, "precomputed value offset") - memmove(unsafe.Pointer(®s.Ints[st.ireg]), offset, st.size) + memmove(regs.IntRegArgAddr(st.ireg, st.size), offset, st.size) } else { // Only populate the Ints space on the return path. // This is safe because out is kept alive until the @@ -799,7 +799,7 @@ func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer, retValid *bool, regs panic("attempted to copy pointer to FP register") } offset := add(v.ptr, st.offset, "precomputed value offset") - memmove(unsafe.Pointer(®s.Floats[st.freg]), offset, st.size) + memmove(regs.FloatRegArgAddr(st.freg, st.size), offset, st.size) default: panic("unknown ABI part kind") } -- GitLab From f457ecc7f096c7e6b225003b583b989384ef0fcb Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sun, 22 Aug 2021 13:34:22 -0700 Subject: [PATCH 0811/2500] cmd/compile: fixing 15.go for -G=3 Required two changes: - avoid creating a closure in the case where the actual receiver of an embedded method is not generic even though the base operand of the selector is generic. This is similar to the test suggested by wayne zuo - I thought it was clear in buildClosure, and easier to comment. - Propagate //go:nointerface to base generic methods and then to instantiations. Change-Id: If30c834e4223c2639b7f7e74d44e6087aa9ccd76 Reviewed-on: https://go-review.googlesource.com/c/go/+/344251 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Wayne Zuo Reviewed-by: Matthew Dempsky Trust: Dan Scales --- src/cmd/compile/internal/noder/decl.go | 6 ++++++ src/cmd/compile/internal/noder/stencil.go | 8 ++++++++ test/run.go | 3 +-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go index cec31d87b7..6b55ce1453 100644 --- a/src/cmd/compile/internal/noder/decl.go +++ b/src/cmd/compile/internal/noder/decl.go @@ -104,6 +104,12 @@ func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) { // the Fields to represent the receiver's method set. if recv := fn.Type().Recv(); recv != nil { typ := types.ReceiverBaseType(recv.Type) + if typ.OrigSym != nil { + // For a generic method, we mark the methods on the + // base generic type, since those are the methods + // that will be stenciled. + typ = typ.OrigSym.Def.Type() + } meth := typecheck.Lookdot1(fn, typecheck.Lookup(decl.Name.Value), typ, typ.Methods(), 0) meth.SetNointerface(true) } diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 19b8f63c4b..e8eee5290e 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -304,6 +304,11 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { // of se.Selection, since that will be the type that actually has // the method. recv := deref(se.Selection.Type.Recv().Type) + if len(recv.RParams()) == 0 { + // The embedded type that actually has the method is not + // actually generic, so no need to build a closure. + return x + } baseType := recv.OrigSym.Def.Type() var gf *ir.Name for _, m := range baseType.Methods().Slice() { @@ -491,6 +496,9 @@ func (g *irgen) instantiateMethods() { baseSym := typ.OrigSym baseType := baseSym.Def.(*ir.Name).Type() for j, _ := range typ.Methods().Slice() { + if baseType.Methods().Slice()[j].Nointerface() { + typ.Methods().Slice()[j].SetNointerface(true) + } baseNname := baseType.Methods().Slice()[j].Nname.(*ir.Name) // Eagerly generate the instantiations and dictionaries that implement these methods. // We don't use the instantiations here, just generate them (and any diff --git a/test/run.go b/test/run.go index 22e94b767c..3759059c95 100644 --- a/test/run.go +++ b/test/run.go @@ -2185,8 +2185,7 @@ var g3Failures = setOf( "typeparam/nested.go", // -G=3 doesn't support function-local types with generics - "typeparam/mdempsky/4.go", // -G=3 can't export functions with labeled breaks in loops - "typeparam/mdempsky/15.go", // ICE in (*irgen).buildClosure + "typeparam/mdempsky/4.go", // -G=3 can't export functions with labeled breaks in loops ) var unifiedFailures = setOf( -- GitLab From aeec6dbfe009f371021bddba13e2eb18e5d1a469 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sun, 22 Aug 2021 12:07:14 +0700 Subject: [PATCH 0812/2500] spec: add example for method value in case of embedded method So it's clear to the reader that if "M" is a promoted method from embedded field "T", then "x.M" will be expanded to "x.T.M" during the evaluation of the method value. Fixes #47863 Change-Id: Id3b82127a2054584b6842c487f6e15c3102dc9fe Reviewed-on: https://go-review.googlesource.com/c/go/+/344209 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Rob Pike Reviewed-by: Matthew Dempsky --- doc/go_spec.html | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index fd5fee46eb..22b616134a 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,6 +1,6 @@ @@ -3000,6 +3000,18 @@ method value; the saved copy is then used as the receiver in any calls, which may be executed later.

+
+type S struct { *T }
+type T int
+func (t T) M() { print(t) }
+
+t := new(T)
+s := S{T: t}
+f := t.M                    // receiver *t is evaluated and stored in f
+g := s.M                    // receiver *(s.T) is evaluated and stored in g
+*t = 42                     // does not affect stored receivers in f and g
+
+

The type T may be an interface or non-interface type.

-- GitLab From 8486ced8b09f4425bfd85e09b021dc78f93aea08 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 20 Aug 2021 10:19:28 -0700 Subject: [PATCH 0813/2500] cmd/compile: copy captured dictionary var to local var When starting a closure that needs a dictionary, copy the closure variable to a local variable. This lets child closures capture that dictionary variable correctly. This is a better fix for #47684, which does not cause problems like #47723. Fixes #47723 Update #47684 Change-Id: Ib5d9ffc68a5142e28daa7d0d75683e7a35508540 Reviewed-on: https://go-review.googlesource.com/c/go/+/343871 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/ir/name.go | 4 +--- src/cmd/compile/internal/noder/stencil.go | 16 ++++++++++++++-- test/typeparam/issue47723.go | 23 +++++++++++++++++++++++ 3 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 test/typeparam/issue47723.go diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index 48fe572124..a2eec05013 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -404,9 +404,7 @@ func CaptureName(pos src.XPos, fn *Func, n *Name) *Name { if n.Op() != ONAME || n.Curfn == nil { return n // okay to use directly } - if n.IsClosureVar() && n.Sym().Name != ".dict" { - // Note: capturing dictionary closure variables is ok. This makes - // sure the generated code is correctly optimized. + if n.IsClosureVar() { base.FatalfAt(pos, "misuse of CaptureName on closure variable: %v", n) } diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index e8eee5290e..4ed1850597 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1087,13 +1087,25 @@ func (subst *subster) node(n ir.Node) ir.Node { ir.FinishCaptureNames(oldfn.Pos(), saveNewf, newfn) newfn.ClosureVars = append(newfn.ClosureVars, subst.namelist(oldfn.ClosureVars)...) + // Copy that closure variable to a local one. + // Note: this allows the dictionary to be captured by child closures. + // See issue 47723. + ldict := ir.NewNameAt(x.Pos(), subst.info.gf.Sym().Pkg.Lookup(".dict")) + typed(types.Types[types.TUINTPTR], ldict) + ldict.Class = ir.PAUTO + ldict.Curfn = newfn + newfn.Dcl = append(newfn.Dcl, ldict) + as := ir.NewAssignStmt(x.Pos(), ldict, cdict) + as.SetTypecheck(1) + newfn.Body.Append(as) + // Create inst info for the instantiated closure. The dict // param is the closure variable for the dictionary of the // outer function. Since the dictionary is shared, use the // same entries for startSubDict, dictLen, dictEntryMap. cinfo := &instInfo{ fun: newfn, - dictParam: cdict, + dictParam: ldict, gf: subst.info.gf, gfInfo: subst.info.gfInfo, startSubDict: subst.info.startSubDict, @@ -1110,7 +1122,7 @@ func (subst *subster) node(n ir.Node) ir.Node { outerinfo := subst.info subst.info = cinfo // Make sure type of closure function is set before doing body. - newfn.Body = subst.list(oldfn.Body) + newfn.Body.Append(subst.list(oldfn.Body)...) subst.info = outerinfo subst.newf = saveNewf ir.CurFunc = saveNewf diff --git a/test/typeparam/issue47723.go b/test/typeparam/issue47723.go new file mode 100644 index 0000000000..9ef60402b2 --- /dev/null +++ b/test/typeparam/issue47723.go @@ -0,0 +1,23 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func f[_ any]() int { + var a [1]int + _ = func() int { + return func() int { + return 0 + }() + }() + return a[func() int { + return 0 + }()] +} + +func main() { + f[int]() +} -- GitLab From 3081f817da8c194982596ddddf5d3ec321c859af Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 20 Aug 2021 16:15:53 -0700 Subject: [PATCH 0814/2500] cmd/compile: always remove receiver type from instantiated method values If a type T has a method foo, then var t T var i interface{} = t.foo The type of foo is a method type, but the type of t.foo should be a standard function type. Make sure we always do that conversion. Fixes #47775 Change-Id: I464ec792196b050aba1914e070a4ede34bfd0bfa Reviewed-on: https://go-review.googlesource.com/c/go/+/343881 Trust: Keith Randall Trust: Dan Scales Reviewed-by: Matthew Dempsky Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/transform.go | 6 +---- src/cmd/compile/internal/typecheck/dcl.go | 6 +++++ test/typeparam/issue47775.dir/b.go | 19 ++++++++++++++ test/typeparam/issue47775.dir/main.go | 11 ++++++++ test/typeparam/issue47775.go | 7 ++++++ test/typeparam/issue47775b.go | 28 +++++++++++++++++++++ 6 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 test/typeparam/issue47775.dir/b.go create mode 100644 test/typeparam/issue47775.dir/main.go create mode 100644 test/typeparam/issue47775.go create mode 100644 test/typeparam/issue47775b.go diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index e1eeb8e739..140bb33234 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -578,11 +578,7 @@ func transformDot(n *ir.SelectorExpr, isCall bool) ir.Node { if (n.Op() == ir.ODOTINTER || n.Op() == ir.ODOTMETH) && !isCall { n.SetOp(ir.OMETHVALUE) - if len(n.X.Type().RParams()) > 0 || n.X.Type().IsPtr() && len(n.X.Type().Elem().RParams()) > 0 { - // TODO: MethodValueWrapper needed for generics? - // Or did we successfully desugar all that at stencil time? - return n - } + // This converts a method type to a function type. See issue 47775. n.SetType(typecheck.NewMethodType(n.Type(), nil)) } return n diff --git a/src/cmd/compile/internal/typecheck/dcl.go b/src/cmd/compile/internal/typecheck/dcl.go index 11e20f0f07..472d8d2b8a 100644 --- a/src/cmd/compile/internal/typecheck/dcl.go +++ b/src/cmd/compile/internal/typecheck/dcl.go @@ -479,6 +479,12 @@ func autotmpname(n int) string { // f is method type, with receiver. // return function type, receiver as first argument (or not). func NewMethodType(sig *types.Type, recv *types.Type) *types.Type { + if sig.HasTParam() { + base.Fatalf("NewMethodType with type parameters in signature %+v", sig) + } + if recv != nil && recv.HasTParam() { + base.Fatalf("NewMethodType with type parameters in receiver %+v", recv) + } nrecvs := 0 if recv != nil { nrecvs++ diff --git a/test/typeparam/issue47775.dir/b.go b/test/typeparam/issue47775.dir/b.go new file mode 100644 index 0000000000..b6d7ba97c5 --- /dev/null +++ b/test/typeparam/issue47775.dir/b.go @@ -0,0 +1,19 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package b + +type C[T any] struct { +} + +func (c *C[T]) reset() { +} + +func New[T any]() { + c := &C[T]{} + z(c.reset) +} + +func z(interface{}) { +} diff --git a/test/typeparam/issue47775.dir/main.go b/test/typeparam/issue47775.dir/main.go new file mode 100644 index 0000000000..ed284ddfc6 --- /dev/null +++ b/test/typeparam/issue47775.dir/main.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "b" + +func main() { + b.New[int]() +} diff --git a/test/typeparam/issue47775.go b/test/typeparam/issue47775.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/issue47775.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored diff --git a/test/typeparam/issue47775b.go b/test/typeparam/issue47775b.go new file mode 100644 index 0000000000..6d3fc8df97 --- /dev/null +++ b/test/typeparam/issue47775b.go @@ -0,0 +1,28 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type C[T any] struct { +} + +func (c *C[T]) reset() { +} + +func New[T any]() { + c := &C[T]{} + i = c.reset + z(c.reset) +} + +var i interface{} + +func z(interface{}) { +} + +func main() { + New[int]() +} -- GitLab From 6b9e3f883e6820a1e94448ca81eba62341cd4836 Mon Sep 17 00:00:00 2001 From: zikaeroh Date: Thu, 29 Jul 2021 21:15:52 -0700 Subject: [PATCH 0815/2500] cmd/compile: don't emit write barriers for offsets of global addresses Currently, write barriers aren't emitted for global addresses, but they are emitted for addresses offset of global addresses. This CL changes IsGlobalAddr to recognize offsets of global addresses as globals too, removing write barriers for staticuint64s based addresses. The logic added is the same as used in IsStackAddr. Updates #37612 Change-Id: I537579f85b9ad02987d94f3ee0b4508b90097959 Reviewed-on: https://go-review.googlesource.com/c/go/+/342129 Reviewed-by: Keith Randall Reviewed-by: Cherry Mui Trust: Michael Knyszek Run-TryBot: Cherry Mui TryBot-Result: Go Bot --- src/cmd/compile/internal/ssa/writebarrier.go | 3 +++ test/writebarrier.go | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/cmd/compile/internal/ssa/writebarrier.go b/src/cmd/compile/internal/ssa/writebarrier.go index 419d91d0d3..d7510965f6 100644 --- a/src/cmd/compile/internal/ssa/writebarrier.go +++ b/src/cmd/compile/internal/ssa/writebarrier.go @@ -552,6 +552,9 @@ func IsStackAddr(v *Value) bool { // IsGlobalAddr reports whether v is known to be an address of a global (or nil). func IsGlobalAddr(v *Value) bool { + for v.Op == OpOffPtr || v.Op == OpAddPtr || v.Op == OpPtrIndex || v.Op == OpCopy { + v = v.Args[0] + } if v.Op == OpAddr && v.Args[0].Op == OpSB { return true // address of a global } diff --git a/test/writebarrier.go b/test/writebarrier.go index dbf0b6dde2..1b30fa509e 100644 --- a/test/writebarrier.go +++ b/test/writebarrier.go @@ -289,3 +289,17 @@ func f27(p *int) []interface{} { p, // ERROR "write barrier" } } + +var g28 [256]uint64 + +func f28() []interface{} { + return []interface{}{ + false, // no write barrier + true, // no write barrier + 0, // no write barrier + 1, // no write barrier + uint8(127), // no write barrier + int8(-4), // no write barrier + &g28[5], // no write barrier + } +} -- GitLab From 0a7f00ae239570d664488085f9c395919bc69066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6hrmann?= Date: Tue, 6 Jul 2021 21:45:02 +0200 Subject: [PATCH 0816/2500] cmd/compile: do not mark arrays used for map initialization noalg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Arrays marked noalg are created by the compiler to hold keys and values to initialize map literals. The ssa backend creates a pointer type for the array type when creating an OpAddr while processing the loop that initializes the map from the arrays. The pointer type does not inherit the noalg property but points to the noalg array type. This causes values created through reflect of types that should be equal to compare unequal because the noalg and alg type might be compared and these are not the same. A similar problem occurred in #32595 for argument arrays of defer structs. Created #47904 to track improve noalg handling to be able to reintroduce this optimization again. Fixes #47068 Change-Id: I87549342bd404b98d71a3c0f33e3c169e9d4efc8 Reviewed-on: https://go-review.googlesource.com/c/go/+/344349 Trust: Martin Möhrmann Run-TryBot: Martin Möhrmann TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/walk/complit.go | 4 ++-- test/fixedbugs/issue47068.dir/a.go | 15 +++++++++++++++ test/fixedbugs/issue47068.dir/b.go | 15 +++++++++++++++ test/fixedbugs/issue47068.dir/main.go | 15 +++++++++++++++ test/fixedbugs/issue47068.go | 7 +++++++ 5 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 test/fixedbugs/issue47068.dir/a.go create mode 100644 test/fixedbugs/issue47068.dir/b.go create mode 100644 test/fixedbugs/issue47068.dir/main.go create mode 100644 test/fixedbugs/issue47068.go diff --git a/src/cmd/compile/internal/walk/complit.go b/src/cmd/compile/internal/walk/complit.go index 6c6b4982a0..e8e941dd91 100644 --- a/src/cmd/compile/internal/walk/complit.go +++ b/src/cmd/compile/internal/walk/complit.go @@ -440,8 +440,8 @@ func maplit(n *ir.CompLitExpr, m ir.Node, init *ir.Nodes) { tk := types.NewArray(n.Type().Key(), int64(len(entries))) te := types.NewArray(n.Type().Elem(), int64(len(entries))) - tk.SetNoalg(true) - te.SetNoalg(true) + // TODO(#47904): mark tk and te NoAlg here once the + // compiler/linker can handle NoAlg types correctly. types.CalcSize(tk) types.CalcSize(te) diff --git a/test/fixedbugs/issue47068.dir/a.go b/test/fixedbugs/issue47068.dir/a.go new file mode 100644 index 0000000000..f7b780d459 --- /dev/null +++ b/test/fixedbugs/issue47068.dir/a.go @@ -0,0 +1,15 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +func A() { + var m map[int]int = map[int]int{ + 0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0, + 10: 0, 11: 0, 12: 0, 13: 0, 14: 0, 15: 0, 16: 0, 17: 0, 18: 0, 19: 0, + 20: 0, 21: 0, 22: 0, 23: 0, 24: 0, 25: 0, 26: 0, 27: 0, 28: 0, 29: 0} + if len(m) != 30 { + panic("unepexted map length") + } +} diff --git a/test/fixedbugs/issue47068.dir/b.go b/test/fixedbugs/issue47068.dir/b.go new file mode 100644 index 0000000000..d341a4a395 --- /dev/null +++ b/test/fixedbugs/issue47068.dir/b.go @@ -0,0 +1,15 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package b + +import "reflect" + +func B() { + t1 := reflect.TypeOf([30]int{}) + t2 := reflect.TypeOf(new([30]int)).Elem() + if t1 != t2 { + panic("[30]int types do not match") + } +} diff --git a/test/fixedbugs/issue47068.dir/main.go b/test/fixedbugs/issue47068.dir/main.go new file mode 100644 index 0000000000..16ef5b780b --- /dev/null +++ b/test/fixedbugs/issue47068.dir/main.go @@ -0,0 +1,15 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "a" + "b" +) + +func main() { + a.A() + b.B() +} diff --git a/test/fixedbugs/issue47068.go b/test/fixedbugs/issue47068.go new file mode 100644 index 0000000000..af6f134172 --- /dev/null +++ b/test/fixedbugs/issue47068.go @@ -0,0 +1,7 @@ +// rundir + +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From fa34678c67275a765a9b78443806c8144d88fe3d Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 23 Aug 2021 11:40:56 -0700 Subject: [PATCH 0817/2500] internal/buildcfg: change GOEXPERIMENT to always return non-empty string Rather than returning "", we now return "," (which is a no-op). This ensures that the returned string always overrides DefaultGOEXPERIMENT. This fixes a bootstrapping issue where GOROOT_BOOTSTRAP was built with "GOEXPERIMENT=fieldtrack ./make.bash". cmd/dist sets GOEXPERIMENT=none during bootstrapping, which was causing cmd/go to set GOEXPERIMENT="" when executing cmd/compile; but then cmd/compile ignores the environment variable (because it's empty) and instead uses DefaultGOEXPERIMENT. Fixes #47921. Change-Id: I657ff6cdfb294a94f6a2f58c306ceed7f104416b Reviewed-on: https://go-review.googlesource.com/c/go/+/344511 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Matthew Dempsky Reviewed-by: Heschi Kreinick --- src/internal/buildcfg/exp.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go index 384f2f96af..3844e4f021 100644 --- a/src/internal/buildcfg/exp.go +++ b/src/internal/buildcfg/exp.go @@ -158,7 +158,11 @@ func expList(exp, base *goexperiment.Flags, all bool) []string { // GOEXPERIMENT is exactly what a user would set on the command line // to get the set of enabled experiments. func GOEXPERIMENT() string { - return strings.Join(expList(&Experiment, &experimentBaseline, false), ",") + goexp := strings.Join(expList(&Experiment, &experimentBaseline, false), ",") + if goexp == "" && DefaultGOEXPERIMENT != "" { + goexp = "," // non-empty to override DefaultGOEXPERIMENT + } + return goexp } // EnabledExperiments returns a list of enabled experiments, as -- GitLab From 22540abf76a693bc9e4c550203d8ccbaa60c12e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6hrmann?= Date: Mon, 23 Aug 2021 13:53:22 +0200 Subject: [PATCH 0818/2500] runtime: use RDTSCP for instruction stream serialized read of TSC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To measure all instructions having been completed before reading the time stamp counter with RDTSC an instruction sequence that has instruction stream serializing properties which guarantee waiting until all previous instructions have been executed is needed. This does not necessary mean to wait for all stores to be globally visible. This CL aims to remove vendor specific logic for determining the instruction sequence with CPU feature flag checks that are CPU vendor independent. For intel LFENCE has the wanted properties at least since it was introduced together with SSE2 support. On AMD instruction stream serializing LFENCE is supported by setting an MSR C001_1029[1]=1 on AMD family 10h/12h/14h/15h/16h/17h processors. AMD family 0Fh/11h processors support LFENCE as serializing always. AMD plans support for this MSR and access to this bit for all future processors. Source: https://developer.amd.com/wp-content/resources/Managing-Speculation-on-AMD-Processors.pdf Reading the MSR to determine LFENCE properties is not always possible or reliable (hypervisors). The Linux kernel is relying on serializing LFENCE on AMD CPUs since a commit in July 2019: https://lkml.org/lkml/2019/7/22/295 and the MSR C001_1029 to enable serialization has been set by default with the Spectre v1 mitigations. Using an MFENCE on AMD is waiting on previous instructions having been executed but in addition also flushes store buffers. To align the serialization properties without runtime detection of CPU manufacturers we can use the newer RDTSCP instruction which waits until all previous instructions have been executed. RDTSCP is available on Intel since around 2008 and on AMD CPUs since around 2006. Support for RDTSCP can be checked independently of manufacturer by checking CPUID bits. Using RDTSCP is the default in Linux to read TSC in program order when the instruction is available. https://github.com/torvalds/linux/blob/e22ce8eb631bdc47a4a4ea7ecf4e4ba499db4f93/arch/x86/include/asm/msr.h#L231 Change-Id: Ifa841843b9abb2816f8f0754a163ebf01385306d Reviewed-on: https://go-review.googlesource.com/c/go/+/344429 Reviewed-by: Keith Randall Trust: Martin Möhrmann Run-TryBot: Martin Möhrmann TryBot-Result: Go Bot --- src/internal/cpu/cpu.go | 1 + src/internal/cpu/cpu_x86.go | 14 ++++++++++++++ src/runtime/asm_386.s | 37 +++++++++++++++++++++++++------------ src/runtime/asm_amd64.s | 30 +++++++++++++++++++----------- src/runtime/cpuflags.go | 9 +++++---- src/runtime/runtime2.go | 1 - 6 files changed, 64 insertions(+), 28 deletions(-) diff --git a/src/internal/cpu/cpu.go b/src/internal/cpu/cpu.go index dab5d068ef..a87d8a2314 100644 --- a/src/internal/cpu/cpu.go +++ b/src/internal/cpu/cpu.go @@ -36,6 +36,7 @@ var X86 struct { HasOSXSAVE bool HasPCLMULQDQ bool HasPOPCNT bool + HasRDTSCP bool HasSSE2 bool HasSSE3 bool HasSSSE3 bool diff --git a/src/internal/cpu/cpu_x86.go b/src/internal/cpu/cpu_x86.go index fd1217a05d..a3f1fb809a 100644 --- a/src/internal/cpu/cpu_x86.go +++ b/src/internal/cpu/cpu_x86.go @@ -37,6 +37,9 @@ const ( cpuid_BMI2 = 1 << 8 cpuid_ERMS = 1 << 9 cpuid_ADX = 1 << 19 + + // edx bits for CPUID 0x80000001 + cpuid_RDTSCP = 1 << 27 ) var maxExtendedFunctionInformation uint32 @@ -53,6 +56,7 @@ func doinit() { {Name: "fma", Feature: &X86.HasFMA}, {Name: "pclmulqdq", Feature: &X86.HasPCLMULQDQ}, {Name: "popcnt", Feature: &X86.HasPOPCNT}, + {Name: "rdtscp", Feature: &X86.HasRDTSCP}, {Name: "sse3", Feature: &X86.HasSSE3}, {Name: "sse41", Feature: &X86.HasSSE41}, {Name: "sse42", Feature: &X86.HasSSE42}, @@ -112,6 +116,16 @@ func doinit() { X86.HasBMI2 = isSet(ebx7, cpuid_BMI2) X86.HasERMS = isSet(ebx7, cpuid_ERMS) X86.HasADX = isSet(ebx7, cpuid_ADX) + + var maxExtendedInformation uint32 + maxExtendedInformation, _, _, _ = cpuid(0x80000000, 0) + + if maxExtendedInformation < 0x80000001 { + return + } + + _, _, _, edxExt1 := cpuid(0x80000001, 0) + X86.HasRDTSCP = isSet(edxExt1, cpuid_RDTSCP) } func isSet(hwc uint32, value uint32) bool { diff --git a/src/runtime/asm_386.s b/src/runtime/asm_386.s index 571aa28a9e..b711356822 100644 --- a/src/runtime/asm_386.s +++ b/src/runtime/asm_386.s @@ -137,9 +137,6 @@ has_cpuid: CMPL AX, $0 JE nocpuinfo - // Figure out how to serialize RDTSC. - // On Intel processors LFENCE is enough. AMD requires MFENCE. - // Don't know about the rest, so let's do MFENCE. CMPL BX, $0x756E6547 // "Genu" JNE notintel CMPL DX, $0x49656E69 // "ineI" @@ -147,7 +144,6 @@ has_cpuid: CMPL CX, $0x6C65746E // "ntel" JNE notintel MOVB $1, runtime·isIntel(SB) - MOVB $1, runtime·lfenceBeforeRdtsc(SB) notintel: // Load EAX=1 cpuid flags @@ -838,19 +834,36 @@ TEXT runtime·stackcheck(SB), NOSPLIT, $0-0 // func cputicks() int64 TEXT runtime·cputicks(SB),NOSPLIT,$0-8 + // LFENCE/MFENCE instruction support is dependent on SSE2. + // When no SSE2 support is present do not enforce any serialization + // since using CPUID to serialize the instruction stream is + // very costly. CMPB internal∕cpu·X86+const_offsetX86HasSSE2(SB), $1 - JNE done - CMPB runtime·lfenceBeforeRdtsc(SB), $1 - JNE mfence - LFENCE - JMP done -mfence: - MFENCE + JNE rdtsc + CMPB internal∕cpu·X86+const_offsetX86HasRDTSCP(SB), $1 + JNE fences + // Instruction stream serializing RDTSCP is supported. + // RDTSCP is supported by Intel Nehalem (2008) and + // AMD K8 Rev. F (2006) and newer. + RDTSCP done: - RDTSC MOVL AX, ret_lo+0(FP) MOVL DX, ret_hi+4(FP) RET +fences: + // MFENCE is instruction stream serializing and flushes the + // store buffers on AMD. The serialization semantics of LFENCE on AMD + // are dependent on MSR C001_1029 and CPU generation. + // LFENCE on Intel does wait for all previous instructions to have executed. + // Intel recommends MFENCE;LFENCE in its manuals before RDTSC to have all + // previous instructions executed and all previous loads and stores to globally visible. + // Using MFENCE;LFENCE here aligns the serializing properties without + // runtime detection of CPU manufacturer. + MFENCE + LFENCE +rdtsc: + RDTSC + JMP done TEXT ldt0setup<>(SB),NOSPLIT,$16-0 // set up ldt 7 to point at m0.tls diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index a6b321aa42..3ab6060ec0 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -103,9 +103,6 @@ TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0 CMPL AX, $0 JE nocpuinfo - // Figure out how to serialize RDTSC. - // On Intel processors LFENCE is enough. AMD requires MFENCE. - // Don't know about the rest, so let's do MFENCE. CMPL BX, $0x756E6547 // "Genu" JNE notintel CMPL DX, $0x49656E69 // "ineI" @@ -113,7 +110,6 @@ TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0 CMPL CX, $0x6C65746E // "ntel" JNE notintel MOVB $1, runtime·isIntel(SB) - MOVB $1, runtime·lfenceBeforeRdtsc(SB) notintel: // Load EAX=1 cpuid flags @@ -928,18 +924,30 @@ TEXT runtime·stackcheck(SB), NOSPLIT, $0-0 // func cputicks() int64 TEXT runtime·cputicks(SB),NOSPLIT,$0-0 - CMPB runtime·lfenceBeforeRdtsc(SB), $1 - JNE mfence - LFENCE - JMP done -mfence: - MFENCE + CMPB internal∕cpu·X86+const_offsetX86HasRDTSCP(SB), $1 + JNE fences + // Instruction stream serializing RDTSCP is supported. + // RDTSCP is supported by Intel Nehalem (2008) and + // AMD K8 Rev. F (2006) and newer. + RDTSCP done: - RDTSC SHLQ $32, DX ADDQ DX, AX MOVQ AX, ret+0(FP) RET +fences: + // MFENCE is instruction stream serializing and flushes the + // store buffers on AMD. The serialization semantics of LFENCE on AMD + // are dependent on MSR C001_1029 and CPU generation. + // LFENCE on Intel does wait for all previous instructions to have executed. + // Intel recommends MFENCE;LFENCE in its manuals before RDTSC to have all + // previous instructions executed and all previous loads and stores to globally visible. + // Using MFENCE;LFENCE here aligns the serializing properties without + // runtime detection of CPU manufacturer. + MFENCE + LFENCE + RDTSC + JMP done // func memhash(p unsafe.Pointer, h, s uintptr) uintptr // hash function using AES hardware instructions diff --git a/src/runtime/cpuflags.go b/src/runtime/cpuflags.go index 5104650c5d..c5291ce4ee 100644 --- a/src/runtime/cpuflags.go +++ b/src/runtime/cpuflags.go @@ -11,10 +11,11 @@ import ( // Offsets into internal/cpu records for use in assembly. const ( - offsetX86HasAVX = unsafe.Offsetof(cpu.X86.HasAVX) - offsetX86HasAVX2 = unsafe.Offsetof(cpu.X86.HasAVX2) - offsetX86HasERMS = unsafe.Offsetof(cpu.X86.HasERMS) - offsetX86HasSSE2 = unsafe.Offsetof(cpu.X86.HasSSE2) + offsetX86HasAVX = unsafe.Offsetof(cpu.X86.HasAVX) + offsetX86HasAVX2 = unsafe.Offsetof(cpu.X86.HasAVX2) + offsetX86HasERMS = unsafe.Offsetof(cpu.X86.HasERMS) + offsetX86HasRDTSCP = unsafe.Offsetof(cpu.X86.HasRDTSCP) + offsetX86HasSSE2 = unsafe.Offsetof(cpu.X86.HasSSE2) offsetARMHasIDIVA = unsafe.Offsetof(cpu.ARM.HasIDIVA) diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index e4e9ee50b8..271d57e5d0 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -1128,7 +1128,6 @@ var ( // Set on startup in asm_{386,amd64}.s processorVersionInfo uint32 isIntel bool - lfenceBeforeRdtsc bool goarm uint8 // set by cmd/link on arm systems ) -- GitLab From 7b6893d2d2f7ff22efdbc29c6729066be8857dfc Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Fri, 30 Jul 2021 15:55:31 -0700 Subject: [PATCH 0819/2500] [dev.fuzz] internal/fuzz: coarsen each coverage counter when taking a snapshot When taking a snapshot of coverage counters, round each counter down to the nearest power of 2. After coarsening, at most 1 bit per byte will be set. This lets the coordinator use a coverage array as a mask that distinguish between code that's executed many times for a given input and code that's executed once or a few times. For example, if a byte in this array has the value 12, it means the block has been executed at least 4 times and at least 8 times with different inputs. Also change the term "edge" to "bits" or just be more vague about how coverage is represented. Also add more code that may be "interesting" in test_fuzz_cache. Change-Id: I67bf2adb298fb8efd7680b069a476c27e5fdbdae Reviewed-on: https://go-review.googlesource.com/c/go/+/338829 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Roland Shoemaker --- src/internal/fuzz/coverage.go | 63 ++++++++++++++++++++++++++++++----- src/internal/fuzz/fuzz.go | 56 ++++++++++++++++--------------- src/internal/fuzz/worker.go | 24 ++++++------- 3 files changed, 95 insertions(+), 48 deletions(-) diff --git a/src/internal/fuzz/coverage.go b/src/internal/fuzz/coverage.go index bd1ff8690d..2468e70fa4 100644 --- a/src/internal/fuzz/coverage.go +++ b/src/internal/fuzz/coverage.go @@ -6,6 +6,7 @@ package fuzz import ( "internal/unsafeheader" + "math/bits" "unsafe" ) @@ -36,26 +37,70 @@ func ResetCoverage() { } // SnapshotCoverage copies the current counter values into coverageSnapshot, -// preserving them for later inspection. +// preserving them for later inspection. SnapshotCoverage also rounds each +// counter down to the nearest power of two. This lets the coordinator store +// multiple values for each counter by OR'ing them together. func SnapshotCoverage() { cov := coverage() - if coverageSnapshot == nil { - coverageSnapshot = make([]byte, len(cov)) + for i, b := range cov { + b |= b >> 1 + b |= b >> 2 + b |= b >> 4 + b -= b >> 1 + coverageSnapshot[i] = b } - copy(coverageSnapshot, cov) } -func countEdges(cov []byte) int { +// diffCoverage returns a set of bits set in snapshot but not in base. +// If there are no new bits set, diffCoverage returns nil. +func diffCoverage(base, snapshot []byte) []byte { + found := false + for i := range snapshot { + if snapshot[i]&^base[i] != 0 { + found = true + break + } + } + if !found { + return nil + } + diff := make([]byte, len(snapshot)) + for i := range diff { + diff[i] = snapshot[i] &^ base[i] + } + return diff +} + +// countNewCoverageBits returns the number of bits set in snapshot that are not +// set in base. +func countNewCoverageBits(base, snapshot []byte) int { n := 0 - for _, c := range cov { - if c > 0 { - n++ + for i := range snapshot { + n += bits.OnesCount8(snapshot[i] &^ base[i]) + } + return n +} + +// hasCoverageBit returns true if snapshot has at least one bit set that is +// also set in base. +func hasCoverageBit(base, snapshot []byte) bool { + for i := range snapshot { + if snapshot[i]&base[i] != 0 { + return true } } + return false +} + +func countBits(cov []byte) int { + n := 0 + for _, c := range cov { + n += bits.OnesCount8(c) + } return n } -var coverageSnapshot []byte +var coverageSnapshot = make([]byte, len(coverage())) // _counters and _ecounters mark the start and end, respectively, of where // the 8-bit coverage counters reside in memory. They're known to cmd/link, diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 673727e291..419faac5ac 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -14,6 +14,7 @@ import ( "fmt" "io" "io/ioutil" + "math/bits" "os" "path/filepath" "reflect" @@ -235,8 +236,8 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err stop(err) } } else if result.coverageData != nil { - newEdges := c.updateCoverage(result.coverageData) - if newEdges > 0 && !c.coverageOnlyRun() { + newBitCount := c.updateCoverage(result.coverageData) + if newBitCount > 0 && !c.coverageOnlyRun() { // Found an interesting value that expanded coverage. // This is not a crasher, but we should add it to the // on-disk corpus, and prioritize it for future fuzzing. @@ -255,13 +256,13 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err if printDebugInfo() { fmt.Fprintf( c.opts.Log, - "DEBUG new interesting input, elapsed: %s, id: %s, parent: %s, gen: %d, new edges: %d, total edges: %d, size: %d, exec time: %s\n", + "DEBUG new interesting input, elapsed: %s, id: %s, parent: %s, gen: %d, new bits: %d, total bits: %d, size: %d, exec time: %s\n", time.Since(c.startTime), result.entry.Name, result.entry.Parent, result.entry.Generation, - newEdges, - countEdges(c.coverageData), + newBitCount, + countBits(c.coverageMask), len(result.entry.Data), result.entryDuration, ) @@ -271,10 +272,10 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err if printDebugInfo() { fmt.Fprintf( c.opts.Log, - "DEBUG processed an initial input, elapsed: %s, id: %s, new edges: %d, size: %d, exec time: %s\n", + "DEBUG processed an initial input, elapsed: %s, id: %s, new bits: %d, size: %d, exec time: %s\n", time.Since(c.startTime), result.entry.Parent, - newEdges, + newBitCount, len(result.entry.Data), result.entryDuration, ) @@ -288,10 +289,10 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err if printDebugInfo() { fmt.Fprintf( c.opts.Log, - "DEBUG finished processing input corpus, elapsed: %s, entries: %d, initial coverage edges: %d\n", + "DEBUG finished processing input corpus, elapsed: %s, entries: %d, initial coverage bits: %d\n", time.Since(c.startTime), len(c.corpus.entries), - countEdges(c.coverageData), + countBits(c.coverageMask), ) } } @@ -494,7 +495,13 @@ type coordinator struct { // which corpus value to send next (or generates something new). corpusIndex int - coverageData []byte + // coverageMask aggregates coverage that was found for all inputs in the + // corpus. Each byte represents a single basic execution block. Each set bit + // within the byte indicates that an input has triggered that block at least + // 1 << n times, where n is the position of the bit in the byte. For example, a + // value of 12 indicates that separate inputs have triggered this block + // between 4-7 times and 8-15 times. + coverageMask []byte } func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { @@ -535,7 +542,7 @@ func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { c.covOnlyInputs = 0 } else { // Set c.coverageData to a clean []byte full of zeros. - c.coverageData = make([]byte, covSize) + c.coverageMask = make([]byte, covSize) } if c.covOnlyInputs > 0 { @@ -555,8 +562,6 @@ func (c *coordinator) updateStats(result fuzzResult) { } func (c *coordinator) logStats() { - // TODO(jayconrod,katiehockman): consider printing the amount of coverage - // that has been reached so far (perhaps a percentage of edges?) elapsed := time.Since(c.startTime) if c.coverageOnlyRun() { fmt.Fprintf(c.opts.Log, "gathering baseline coverage, elapsed: %.1fs, workers: %d, left: %d\n", elapsed.Seconds(), c.opts.Parallel, c.covOnlyInputs) @@ -578,8 +583,9 @@ func (c *coordinator) nextInput() (fuzzInput, bool) { input := fuzzInput{ entry: c.corpus.entries[c.corpusIndex], interestingCount: c.interestingCount, - coverageData: c.coverageData, + coverageData: make([]byte, len(c.coverageMask)), } + copy(input.coverageData, c.coverageMask) c.corpusIndex = (c.corpusIndex + 1) % (len(c.corpus.entries)) if c.coverageOnlyRun() { @@ -607,22 +613,20 @@ func (c *coordinator) coverageOnlyRun() bool { return c.covOnlyInputs > 0 } -// updateCoverage updates c.coverageData for all edges that have a higher -// counter value in newCoverage. It return true if a new edge was hit. +// updateCoverage sets bits in c.coverageData that are set in newCoverage. +// updateCoverage returns the number of newly set bits. See the comment on +// coverageMask for the format. func (c *coordinator) updateCoverage(newCoverage []byte) int { - if len(newCoverage) != len(c.coverageData) { - panic(fmt.Sprintf("num edges changed at runtime: %d, expected %d", len(newCoverage), len(c.coverageData))) + if len(newCoverage) != len(c.coverageMask) { + panic(fmt.Sprintf("number of coverage counters changed at runtime: %d, expected %d", len(newCoverage), len(c.coverageMask))) } - newEdges := 0 + newBitCount := 0 for i := range newCoverage { - if newCoverage[i] > c.coverageData[i] { - if c.coverageData[i] == 0 { - newEdges++ - } - c.coverageData[i] = newCoverage[i] - } + diff := newCoverage[i] &^ c.coverageMask[i] + newBitCount += bits.OnesCount8(diff) + c.coverageMask[i] |= newCoverage[i] } - return newEdges + return newBitCount } // readCache creates a combined corpus from seed values and values in the cache diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index e3029bcd66..de4f6b08b6 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -569,10 +569,10 @@ type workerServer struct { workerComm m *mutator - // coverageData is the local coverage data for the worker. It is + // coverageMask is the local coverage data for the worker. It is // periodically updated to reflect the data in the coordinator when new - // edges are hit. - coverageData []byte + // coverage is found. + coverageMask []byte // fuzzFn runs the worker's fuzz function on the given input and returns // an error if it finds a crasher (the process may also exit or crash). @@ -633,7 +633,7 @@ func (ws *workerServer) serve(ctx context.Context) error { // the crashing input with this information, since the PRNG is deterministic. func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzResponse) { if args.CoverageData != nil { - ws.coverageData = args.CoverageData + ws.coverageMask = args.CoverageData } start := time.Now() defer func() { resp.TotalDuration = time.Since(start) }() @@ -666,8 +666,8 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo return resp } - if cov := coverage(); len(cov) != len(ws.coverageData) { - panic(fmt.Sprintf("num edges changed at runtime: %d, expected %d", len(cov), len(ws.coverageData))) + if cov := coverage(); len(cov) != len(ws.coverageMask) { + panic(fmt.Sprintf("number of coverage counters changed at runtime: %d, expected %d", len(cov), len(ws.coverageMask))) } for { select { @@ -687,13 +687,11 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo } return resp } - for i := range coverageSnapshot { - if ws.coverageData[i] == 0 && coverageSnapshot[i] > ws.coverageData[i] { - // TODO(jayconrod,katie): minimize this. - resp.CoverageData = coverageSnapshot - resp.InterestingDuration = fDur - return resp - } + if countNewCoverageBits(ws.coverageMask, coverageSnapshot) > 0 { + // TODO(jayconrod,katie): minimize this. + resp.CoverageData = coverageSnapshot + resp.InterestingDuration = fDur + return resp } if args.Limit > 0 && mem.header().count == args.Limit { return resp -- GitLab From 8157960d7f4a89807c71b3427a0363a23fd43ca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6hrmann?= Date: Mon, 23 Aug 2021 11:34:51 +0200 Subject: [PATCH 0820/2500] all: replace runtime SSE2 detection with GO386 setting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When GO386=sse2 we can assume sse2 to be present without a runtime check. If GO386=softfloat is set we can avoid the usage of SSE2 even if detected. This might cause a memcpy, memclr and bytealg slowdown of Go binaries compiled with softfloat on machines that support SSE2. Such setups are rare and should use GO386=sse2 instead if performance matters. On targets that support SSE2 we avoid the runtime overhead of dynamic cpu feature dispatch. The removal of runtime sse2 checks also allows to simplify internal/cpu further by removing handling of the required feature option as a followup after this CL. Change-Id: I90a853a8853a405cb665497c6d1a86556947ba17 Reviewed-on: https://go-review.googlesource.com/c/go/+/344350 Trust: Martin Möhrmann Run-TryBot: Martin Möhrmann TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/go/internal/work/gc.go | 5 +++++ src/internal/bytealg/bytealg.go | 1 - src/internal/bytealg/compare_386.s | 5 +++-- src/internal/bytealg/equal_386.s | 5 +++-- src/internal/cpu/cpu.go | 1 - src/internal/cpu/cpu_386.go | 7 ------- src/internal/cpu/cpu_amd64.go | 7 ------- src/internal/cpu/cpu_x86.go | 6 +----- src/internal/cpu/cpu_x86_test.go | 18 ------------------ src/runtime/asm_386.s | 5 +++-- src/runtime/cpuflags.go | 1 - src/runtime/memclr_386.s | 5 +++-- src/runtime/memmove_386.s | 5 +++-- src/runtime/mkpreempt.go | 10 ++++++---- src/runtime/preempt_386.s | 10 ++++------ 15 files changed, 31 insertions(+), 60 deletions(-) delete mode 100644 src/internal/cpu/cpu_386.go delete mode 100644 src/internal/cpu/cpu_amd64.go diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go index 74e14d0065..eee8adca94 100644 --- a/src/cmd/go/internal/work/gc.go +++ b/src/cmd/go/internal/work/gc.go @@ -374,6 +374,11 @@ func asmArgs(a *Action, p *load.Package) []interface{} { args = append(args, "-compiling-runtime") } + if cfg.Goarch == "386" { + // Define GO386_value from cfg.GO386. + args = append(args, "-D", "GO386_"+cfg.GO386) + } + if cfg.Goarch == "mips" || cfg.Goarch == "mipsle" { // Define GOMIPS_value from cfg.GOMIPS. args = append(args, "-D", "GOMIPS_"+cfg.GOMIPS) diff --git a/src/internal/bytealg/bytealg.go b/src/internal/bytealg/bytealg.go index 6b2b540acc..ebebce75fe 100644 --- a/src/internal/bytealg/bytealg.go +++ b/src/internal/bytealg/bytealg.go @@ -11,7 +11,6 @@ import ( // Offsets into internal/cpu records for use in assembly. const ( - offsetX86HasSSE2 = unsafe.Offsetof(cpu.X86.HasSSE2) offsetX86HasSSE42 = unsafe.Offsetof(cpu.X86.HasSSE42) offsetX86HasAVX2 = unsafe.Offsetof(cpu.X86.HasAVX2) offsetX86HasPOPCNT = unsafe.Offsetof(cpu.X86.HasPOPCNT) diff --git a/src/internal/bytealg/compare_386.s b/src/internal/bytealg/compare_386.s index 0981983d20..27b660ccf7 100644 --- a/src/internal/bytealg/compare_386.s +++ b/src/internal/bytealg/compare_386.s @@ -36,8 +36,9 @@ TEXT cmpbody<>(SB),NOSPLIT,$0-0 JEQ allsame CMPL BP, $4 JB small - CMPB internal∕cpu·X86+const_offsetX86HasSSE2(SB), $1 - JNE mediumloop +#ifdef GO386_softfloat + JMP mediumloop +#endif largeloop: CMPL BP, $16 JB mediumloop diff --git a/src/internal/bytealg/equal_386.s b/src/internal/bytealg/equal_386.s index 87233635a9..58b3cbe3d0 100644 --- a/src/internal/bytealg/equal_386.s +++ b/src/internal/bytealg/equal_386.s @@ -43,8 +43,9 @@ TEXT memeqbody<>(SB),NOSPLIT,$0-0 hugeloop: CMPL BX, $64 JB bigloop - CMPB internal∕cpu·X86+const_offsetX86HasSSE2(SB), $1 - JNE bigloop +#ifdef GO386_softfloat + JMP bigloop +#endif MOVOU (SI), X0 MOVOU (DI), X1 MOVOU 16(SI), X2 diff --git a/src/internal/cpu/cpu.go b/src/internal/cpu/cpu.go index a87d8a2314..4f0c5d2896 100644 --- a/src/internal/cpu/cpu.go +++ b/src/internal/cpu/cpu.go @@ -37,7 +37,6 @@ var X86 struct { HasPCLMULQDQ bool HasPOPCNT bool HasRDTSCP bool - HasSSE2 bool HasSSE3 bool HasSSSE3 bool HasSSE41 bool diff --git a/src/internal/cpu/cpu_386.go b/src/internal/cpu/cpu_386.go deleted file mode 100644 index 561c81f808..0000000000 --- a/src/internal/cpu/cpu_386.go +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -const GOARCH = "386" diff --git a/src/internal/cpu/cpu_amd64.go b/src/internal/cpu/cpu_amd64.go deleted file mode 100644 index 9b0015362d..0000000000 --- a/src/internal/cpu/cpu_amd64.go +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -const GOARCH = "amd64" diff --git a/src/internal/cpu/cpu_x86.go b/src/internal/cpu/cpu_x86.go index a3f1fb809a..1582e832a4 100644 --- a/src/internal/cpu/cpu_x86.go +++ b/src/internal/cpu/cpu_x86.go @@ -61,9 +61,6 @@ func doinit() { {Name: "sse41", Feature: &X86.HasSSE41}, {Name: "sse42", Feature: &X86.HasSSE42}, {Name: "ssse3", Feature: &X86.HasSSSE3}, - - // These capabilities should always be enabled on amd64: - {Name: "sse2", Feature: &X86.HasSSE2, Required: GOARCH == "amd64"}, } maxID, _, _, _ := cpuid(0, 0) @@ -74,8 +71,7 @@ func doinit() { maxExtendedFunctionInformation, _, _, _ = cpuid(0x80000000, 0) - _, _, ecx1, edx1 := cpuid(1, 0) - X86.HasSSE2 = isSet(edx1, cpuid_SSE2) + _, _, ecx1, _ := cpuid(1, 0) X86.HasSSE3 = isSet(ecx1, cpuid_SSE3) X86.HasPCLMULQDQ = isSet(ecx1, cpuid_PCLMULQDQ) diff --git a/src/internal/cpu/cpu_x86_test.go b/src/internal/cpu/cpu_x86_test.go index e3e16cc161..de1c5fb3b0 100644 --- a/src/internal/cpu/cpu_x86_test.go +++ b/src/internal/cpu/cpu_x86_test.go @@ -10,7 +10,6 @@ package cpu_test import ( . "internal/cpu" "os" - "runtime" "testing" ) @@ -20,23 +19,6 @@ func TestX86ifAVX2hasAVX(t *testing.T) { } } -func TestDisableSSE2(t *testing.T) { - runDebugOptionsTest(t, "TestSSE2DebugOption", "cpu.sse2=off") -} - -func TestSSE2DebugOption(t *testing.T) { - MustHaveDebugOptionsSupport(t) - - if os.Getenv("GODEBUG") != "cpu.sse2=off" { - t.Skipf("skipping test: GODEBUG=cpu.sse2=off not set") - } - - want := runtime.GOARCH != "386" // SSE2 can only be disabled on 386. - if got := X86.HasSSE2; got != want { - t.Errorf("X86.HasSSE2 on %s expected %v, got %v", runtime.GOARCH, want, got) - } -} - func TestDisableSSE3(t *testing.T) { runDebugOptionsTest(t, "TestSSE3DebugOption", "cpu.sse3=off") } diff --git a/src/runtime/asm_386.s b/src/runtime/asm_386.s index b711356822..594cd5ed0d 100644 --- a/src/runtime/asm_386.s +++ b/src/runtime/asm_386.s @@ -838,8 +838,9 @@ TEXT runtime·cputicks(SB),NOSPLIT,$0-8 // When no SSE2 support is present do not enforce any serialization // since using CPUID to serialize the instruction stream is // very costly. - CMPB internal∕cpu·X86+const_offsetX86HasSSE2(SB), $1 - JNE rdtsc +#ifdef GO386_softfloat + JMP rdtsc // no fence instructions available +#endif CMPB internal∕cpu·X86+const_offsetX86HasRDTSCP(SB), $1 JNE fences // Instruction stream serializing RDTSCP is supported. diff --git a/src/runtime/cpuflags.go b/src/runtime/cpuflags.go index c5291ce4ee..bbe93c5bea 100644 --- a/src/runtime/cpuflags.go +++ b/src/runtime/cpuflags.go @@ -15,7 +15,6 @@ const ( offsetX86HasAVX2 = unsafe.Offsetof(cpu.X86.HasAVX2) offsetX86HasERMS = unsafe.Offsetof(cpu.X86.HasERMS) offsetX86HasRDTSCP = unsafe.Offsetof(cpu.X86.HasRDTSCP) - offsetX86HasSSE2 = unsafe.Offsetof(cpu.X86.HasSSE2) offsetARMHasIDIVA = unsafe.Offsetof(cpu.ARM.HasIDIVA) diff --git a/src/runtime/memclr_386.s b/src/runtime/memclr_386.s index 046c344119..2627792ced 100644 --- a/src/runtime/memclr_386.s +++ b/src/runtime/memclr_386.s @@ -30,8 +30,9 @@ tail: JBE _5through8 CMPL BX, $16 JBE _9through16 - CMPB internal∕cpu·X86+const_offsetX86HasSSE2(SB), $1 - JNE nosse2 +#ifdef GO386_softfloat + JMP nosse2 +#endif PXOR X0, X0 CMPL BX, $32 JBE _17through32 diff --git a/src/runtime/memmove_386.s b/src/runtime/memmove_386.s index 1a43a1f724..389ef88477 100644 --- a/src/runtime/memmove_386.s +++ b/src/runtime/memmove_386.s @@ -55,8 +55,9 @@ tail: JBE move_5through8 CMPL BX, $16 JBE move_9through16 - CMPB internal∕cpu·X86+const_offsetX86HasSSE2(SB), $1 - JNE nosse2 +#ifdef GO386_softfloat + JMP nosse2 +#endif CMPL BX, $32 JBE move_17through32 CMPL BX, $64 diff --git a/src/runtime/mkpreempt.go b/src/runtime/mkpreempt.go index f2b90307ca..d87446d036 100644 --- a/src/runtime/mkpreempt.go +++ b/src/runtime/mkpreempt.go @@ -200,6 +200,8 @@ func gen386() { l.add("MOVL", reg, 4) } + softfloat := "GO386_softfloat" + // Save SSE state only if supported. lSSE := layout{stack: l.stack, sp: "SP"} for i := 0; i < 8; i++ { @@ -209,13 +211,13 @@ func gen386() { p("ADJSP $%d", lSSE.stack) p("NOP SP") l.save() - p("CMPB internal∕cpu·X86+const_offsetX86HasSSE2(SB), $1\nJNE nosse") + p("#ifndef %s", softfloat) lSSE.save() - label("nosse:") + p("#endif") p("CALL ·asyncPreempt2(SB)") - p("CMPB internal∕cpu·X86+const_offsetX86HasSSE2(SB), $1\nJNE nosse2") + p("#ifndef %s", softfloat) lSSE.restore() - label("nosse2:") + p("#endif") l.restore() p("ADJSP $%d", -lSSE.stack) diff --git a/src/runtime/preempt_386.s b/src/runtime/preempt_386.s index c3a5fa1f36..d57bc3d37c 100644 --- a/src/runtime/preempt_386.s +++ b/src/runtime/preempt_386.s @@ -14,8 +14,7 @@ TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 MOVL BP, 16(SP) MOVL SI, 20(SP) MOVL DI, 24(SP) - CMPB internal∕cpu·X86+const_offsetX86HasSSE2(SB), $1 - JNE nosse + #ifndef GO386_softfloat MOVUPS X0, 28(SP) MOVUPS X1, 44(SP) MOVUPS X2, 60(SP) @@ -24,10 +23,9 @@ TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 MOVUPS X5, 108(SP) MOVUPS X6, 124(SP) MOVUPS X7, 140(SP) -nosse: + #endif CALL ·asyncPreempt2(SB) - CMPB internal∕cpu·X86+const_offsetX86HasSSE2(SB), $1 - JNE nosse2 + #ifndef GO386_softfloat MOVUPS 140(SP), X7 MOVUPS 124(SP), X6 MOVUPS 108(SP), X5 @@ -36,7 +34,7 @@ nosse: MOVUPS 60(SP), X2 MOVUPS 44(SP), X1 MOVUPS 28(SP), X0 -nosse2: + #endif MOVL 24(SP), DI MOVL 20(SP), SI MOVL 16(SP), BP -- GitLab From be1a6934776a3c7f636932918e756b44b6510214 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sun, 22 Aug 2021 11:50:58 -0700 Subject: [PATCH 0821/2500] cmd/compile: fixes for non-constant Sizeof/Alignof/Offsetof Includes Robert's suggested fix in validate.go to not fail on non-constant alignof/offsetof/sizeof calls. Further changes to wait on transforming these calls until stenciling time, when we can call EvalConst() to evaluate them once all the relevant types are known. Added a bunch of new tests for non-constant Sizeof/Alignof/Offsetof. Fixes #47716 Change-Id: I469af888eb9ce3a853124d919eda753971009b3e Reviewed-on: https://go-review.googlesource.com/c/go/+/344250 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Robert Griesemer Trust: Dan Scales --- src/cmd/compile/internal/noder/helpers.go | 10 ++- src/cmd/compile/internal/noder/stencil.go | 2 +- src/cmd/compile/internal/noder/transform.go | 5 +- src/cmd/compile/internal/noder/validate.go | 11 +++- src/cmd/compile/internal/typecheck/const.go | 4 +- test/typeparam/issue47716.go | 68 +++++++++++++++++++++ 6 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 test/typeparam/issue47716.go diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index b9dbd030af..9487e76336 100644 --- a/src/cmd/compile/internal/noder/helpers.go +++ b/src/cmd/compile/internal/noder/helpers.go @@ -138,10 +138,18 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) // until arg type known // OAPPEND: transformAppend requires that the arg is a slice // ODELETE: transformDelete requires that the arg is a map + // OALIGNOF, OSIZEOF: can be eval'ed to a constant until types known. switch fun.BuiltinOp { - case ir.OMAKE, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.ODELETE: + case ir.OMAKE, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.ODELETE, ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF: hasTParam := false for _, arg := range args { + if fun.BuiltinOp == ir.OOFFSETOF { + // It's the type of left operand of the + // selection that matters, not the type of + // the field itself (which is irrelevant for + // offsetof). + arg = arg.(*ir.SelectorExpr).X + } if arg.Type().HasTParam() { hasTParam = true break diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 4ed1850597..2d275d6a3b 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1037,7 +1037,7 @@ func (subst *subster) node(n ir.Node) ir.Node { name := call.X.Name() if name.BuiltinOp != ir.OXXX { switch name.BuiltinOp { - case ir.OMAKE, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.ODELETE: + case ir.OMAKE, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.ODELETE, ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF: // Transform these builtins now that we // know the type of the args. m = transformBuiltin(call) diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index 140bb33234..be8651d47b 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -811,7 +811,10 @@ func transformBuiltin(n *ir.CallExpr) ir.Node { return transformRealImag(u1.(*ir.UnaryExpr)) case ir.OPANIC: return transformPanic(u1.(*ir.UnaryExpr)) - case ir.OCLOSE, ir.ONEW, ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF: + case ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF: + // This corresponds to the EvalConst() call near end of typecheck(). + return typecheck.EvalConst(u1) + case ir.OCLOSE, ir.ONEW: // nothing more to do return u1 } diff --git a/src/cmd/compile/internal/noder/validate.go b/src/cmd/compile/internal/noder/validate.go index 68a059b96f..dcacae7480 100644 --- a/src/cmd/compile/internal/noder/validate.go +++ b/src/cmd/compile/internal/noder/validate.go @@ -81,7 +81,16 @@ func (g *irgen) validateBuiltin(name string, call *syntax.CallExpr) { // Check that types2+gcSizes calculates sizes the same // as cmd/compile does. - got, ok := constant.Int64Val(g.info.Types[call].Value) + tv := g.info.Types[call] + if !tv.IsValue() { + base.FatalfAt(g.pos(call), "expected a value") + } + + if tv.Value == nil { + break // unsafe op is not a constant, so no further validation + } + + got, ok := constant.Int64Val(tv.Value) if !ok { base.FatalfAt(g.pos(call), "expected int64 constant value") } diff --git a/src/cmd/compile/internal/typecheck/const.go b/src/cmd/compile/internal/typecheck/const.go index f8150d249a..c27cf0e646 100644 --- a/src/cmd/compile/internal/typecheck/const.go +++ b/src/cmd/compile/internal/typecheck/const.go @@ -881,7 +881,9 @@ func evalunsafe(n ir.Node) int64 { case ir.OOFFSETOF: // must be a selector. n := n.(*ir.UnaryExpr) - if n.X.Op() != ir.OXDOT { + // ODOT and ODOTPTR are allowed in case the OXDOT transformation has + // already happened (e.g. during -G=3 stenciling). + if n.X.Op() != ir.OXDOT && n.X.Op() != ir.ODOT && n.X.Op() != ir.ODOTPTR { base.Errorf("invalid expression %v", n) return 0 } diff --git a/test/typeparam/issue47716.go b/test/typeparam/issue47716.go new file mode 100644 index 0000000000..7f34fcb21f --- /dev/null +++ b/test/typeparam/issue47716.go @@ -0,0 +1,68 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + "unsafe" +) + +// size returns the size of type T +func size[T any](x T) uintptr { + return unsafe.Sizeof(x) +} + +// size returns the alignment of type T +func align[T any](x T) uintptr { + return unsafe.Alignof(x) +} + +type Tstruct[T any] struct { + f1 T + f2 int +} + +// offset returns the offset of field f2 in the generic type Tstruct +func (r *Tstruct[T]) offset() uintptr { + return unsafe.Offsetof(r.f2) +} + +func main() { + v1 := int(5) + if got, want := size(v1), unsafe.Sizeof(v1); got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } + if got, want := align(v1), unsafe.Alignof(v1); got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } + + v2 := "abc" + if got, want := size(v2), unsafe.Sizeof(v2); got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } + if got, want := align(v2), unsafe.Alignof(v2); got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } + + var v3 Tstruct[int] + if got, want := unsafe.Offsetof(v3.f2), unsafe.Sizeof(v1); got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } + + var v4 Tstruct[interface{}] + var v5 interface{} + if got, want := unsafe.Offsetof(v4.f2), unsafe.Sizeof(v5); got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } + + if got, want := v3.offset(), unsafe.Offsetof(v3.f2); got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } + if got, want := v4.offset(), unsafe.Offsetof(v4.f2); got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } +} -- GitLab From 8eeb1bff1d7107828b41af08e599c78fc36bab30 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 23 Aug 2021 15:45:10 -0700 Subject: [PATCH 0822/2500] cmd/compile: reuse same node for global dictionaries Change stencil.go:getDictionaryValue() and reflect.go:getDictionary() to reuse any existing name node that has been created for the needed global dictionary. Otherwise, these functions may set the Def on a specific dictionary sym to two different name nodes, which means the first node will not satisfy the invariant 'n.Sym().Def.(*ir.Name) == n' (which is the assertion in this issue). Fixes #47896 Change-Id: I1e7ae1efd077a83c7878b4342feb6d28d52476cc Reviewed-on: https://go-review.googlesource.com/c/go/+/344609 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 17 +++-- .../compile/internal/reflectdata/reflect.go | 17 +++-- test/typeparam/issue47896.go | 74 +++++++++++++++++++ 3 files changed, 96 insertions(+), 12 deletions(-) create mode 100644 test/typeparam/issue47896.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 2d275d6a3b..570dec9990 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1579,12 +1579,17 @@ func (g *irgen) finalizeSyms() { func (g *irgen) getDictionaryValue(gf *ir.Name, targs []*types.Type, isMeth bool) ir.Node { sym := g.getDictionarySym(gf, targs, isMeth) - // Make a node referencing the dictionary symbol. - n := typecheck.NewName(sym) - n.SetType(types.Types[types.TUINTPTR]) // should probably be [...]uintptr, but doesn't really matter - n.SetTypecheck(1) - n.Class = ir.PEXTERN - sym.Def = n + // Make (or reuse) a node referencing the dictionary symbol. + var n *ir.Name + if sym.Def != nil { + n = sym.Def.(*ir.Name) + } else { + n = typecheck.NewName(sym) + n.SetType(types.Types[types.TUINTPTR]) // should probably be [...]uintptr, but doesn't really matter + n.SetTypecheck(1) + n.Class = ir.PEXTERN + sym.Def = n + } // Return the address of the dictionary. np := typecheck.NodAddr(n) diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 3ba8f52541..a95c76ff26 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -2047,12 +2047,17 @@ func getDictionary(gf *types.Sym, targs []*types.Type) ir.Node { base.Fatalf("Dictionary should have already been generated: %s.%s", sym.Pkg.Path, sym.Name) } - // Make a node referencing the dictionary symbol. - n := typecheck.NewName(sym) - n.SetType(types.Types[types.TUINTPTR]) // should probably be [...]uintptr, but doesn't really matter - n.SetTypecheck(1) - n.Class = ir.PEXTERN - sym.Def = n + // Make (or reuse) a node referencing the dictionary symbol. + var n *ir.Name + if sym.Def != nil { + n = sym.Def.(*ir.Name) + } else { + n = typecheck.NewName(sym) + n.SetType(types.Types[types.TUINTPTR]) // should probably be [...]uintptr, but doesn't really matter + n.SetTypecheck(1) + n.Class = ir.PEXTERN + sym.Def = n + } // Return the address of the dictionary. np := typecheck.NodAddr(n) diff --git a/test/typeparam/issue47896.go b/test/typeparam/issue47896.go new file mode 100644 index 0000000000..1b2f265cc1 --- /dev/null +++ b/test/typeparam/issue47896.go @@ -0,0 +1,74 @@ +// compile -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "database/sql" +) + +// Collection generic interface which things can be added to. +type Collection[T any] interface { + Add(T) +} + +// Slice generic slice implementation of a Collection +type Slice[T any] []*T + +func (s *Slice[T]) Add(t *T) { + *s = append(*s, t) +} + +type Scanner interface { + Scan(...interface{}) error +} + +type Mapper[T any] func(s Scanner, t T) error + +type Repository[T any] struct { + db *sql.DB +} + +func (r *Repository[T]) scan(rows *sql.Rows, m Mapper[*T], c Collection[*T]) error { + for rows.Next() { + t := new(T) + if err := m(rows, t); err != nil { + return err + } + c.Add(t) + } + return rows.Err() +} + +func (r *Repository[T]) query(query string, m Mapper[*T], c Collection[*T]) error { + rows, err := r.db.Query(query) + if err != nil { + return err + } + if err := r.scan(rows, m, c); err != nil { + rows.Close() + return err + } + return rows.Close() +} + +type Actor struct { + ActorID uint16 + FirstName string + LastName string +} + +type ActorRepository struct { + r Repository[Actor] +} + +func (ActorRepository) scan(s Scanner, a *Actor) error { + return s.Scan(&a.ActorID, &a.FirstName, &a.LastName) +} + +func (r *ActorRepository) SelectAll(c Collection[*Actor]) error { + return r.r.query("SELECT `actor_id`, `first_name`, `last_name` FROM `actor` LIMIT 10", r.scan, c) +} -- GitLab From f98b6111eb8edda63a785db5678418b9eecbc5e9 Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Tue, 20 Jul 2021 17:17:14 +0000 Subject: [PATCH 0823/2500] go/token: match the implementation of index selection with sort.Search MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit name old time/op new time/op delta SearchInts-8 15.5ns ± 2% 13.7ns ± 4% -11.87% (p=0.008 n=5+5) (see CL 36332 for the original change to sort.Search) Change-Id: If452818185b92b8b3548b066f475e493d604ea29 GitHub-Last-Rev: 32dd3cffa6b54b332948ac6a2929458defd4838f GitHub-Pull-Request: golang/go#47293 Reviewed-on: https://go-review.googlesource.com/c/go/+/335809 Reviewed-by: Robert Griesemer Trust: Robert Griesemer Trust: Than McIntosh --- src/go/token/position.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/go/token/position.go b/src/go/token/position.go index 0d7982c670..ce4af03923 100644 --- a/src/go/token/position.go +++ b/src/go/token/position.go @@ -540,7 +540,7 @@ func searchInts(a []int, x int) int { // TODO(gri): Remove this when compilers have caught up. i, j := 0, len(a) for i < j { - h := i + (j-i)>>1 // avoid overflow when computing h + h := int(uint(i+j) >> 1) // avoid overflow when computing h // i ≤ h < j if a[h] <= x { i = h + 1 -- GitLab From d70c69d830f873473851e37b47ac4f35b5200273 Mon Sep 17 00:00:00 2001 From: korzhao Date: Thu, 12 Aug 2021 23:39:29 +0800 Subject: [PATCH 0824/2500] embed: document the maximum file size supported Fixes #47627 Change-Id: Ia1edfb6249863ab055fab68a35666bc2bdf21dcb Reviewed-on: https://go-review.googlesource.com/c/go/+/341689 Reviewed-by: Jay Conrod Trust: Michael Matloob --- src/cmd/compile/internal/staticdata/data.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/staticdata/data.go b/src/cmd/compile/internal/staticdata/data.go index abb0bba646..f25d8d8ec5 100644 --- a/src/cmd/compile/internal/staticdata/data.go +++ b/src/cmd/compile/internal/staticdata/data.go @@ -92,6 +92,10 @@ func StringSym(pos src.XPos, s string) (data *obj.LSym) { return symdata } +// maxFileSize is the maximum file size permitted by the linker +// (see issue #9862). +const maxFileSize = int64(2e9) + // fileStringSym returns a symbol for the contents and the size of file. // If readonly is true, the symbol shares storage with any literal string // or other file with the same content and is placed in a read-only section. @@ -133,12 +137,12 @@ func fileStringSym(pos src.XPos, file string, readonly bool, hash []byte) (*obj. } return sym, size, nil } - if size > 2e9 { + if size > maxFileSize { // ggloblsym takes an int32, // and probably the rest of the toolchain // can't handle such big symbols either. // See golang.org/issue/9862. - return nil, 0, fmt.Errorf("file too large") + return nil, 0, fmt.Errorf("file too large (%d bytes > %d bytes)", size, maxFileSize) } // File is too big to read and keep in memory. -- GitLab From bba460499c689de85e895fb2fac8ad3d09d4cd2c Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 23 Aug 2021 16:25:37 -0700 Subject: [PATCH 0825/2500] cmd/compile/internal/types2: don't export TypeSet For now don't export TypeSet in the interest of keeping the types2 API surface small(er). This is a clean port of CL 341289 from go/types. Change-Id: I50c747629f25472f2ec5ba59d7f543ee3c1c423b Reviewed-on: https://go-review.googlesource.com/c/go/+/344610 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky Reviewed-by: Dan Scales --- src/cmd/compile/internal/types2/interface.go | 4 +- .../compile/internal/types2/sizeof_test.go | 2 +- src/cmd/compile/internal/types2/typeset.go | 46 +++++++++---------- src/cmd/compile/internal/types2/union.go | 4 +- src/cmd/compile/internal/types2/universe.go | 2 +- 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index 2617f748de..ccd3de0a6e 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -17,11 +17,11 @@ type Interface struct { embedPos *[]syntax.Pos // positions of embedded elements; or nil (for error messages) - use pointer to save space complete bool // indicates that all fields (except for tset) are set up - tset *TypeSet // type set described by this interface, computed lazily + tset *_TypeSet // type set described by this interface, computed lazily } // typeSet returns the type set for interface t. -func (t *Interface) typeSet() *TypeSet { return computeInterfaceTypeSet(nil, nopos, t) } +func (t *Interface) typeSet() *_TypeSet { return computeInterfaceTypeSet(nil, nopos, t) } // emptyInterface represents the empty interface var emptyInterface = Interface{complete: true, tset: &topTypeSet} diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go index d2f53258f0..718d2d266a 100644 --- a/src/cmd/compile/internal/types2/sizeof_test.go +++ b/src/cmd/compile/internal/types2/sizeof_test.go @@ -49,7 +49,7 @@ func TestSizeof(t *testing.T) { // Misc {Scope{}, 60, 104}, {Package{}, 40, 80}, - {TypeSet{}, 28, 56}, + {_TypeSet{}, 28, 56}, } for _, test := range tests { diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index 5955bbe805..14596b68a3 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -14,8 +14,8 @@ import ( // ---------------------------------------------------------------------------- // API -// A TypeSet represents the type set of an interface. -type TypeSet struct { +// A _TypeSet represents the type set of an interface. +type _TypeSet struct { comparable bool // if set, the interface is or embeds comparable // TODO(gri) consider using a set for the methods for faster lookup methods []*Func // all methods of the interface; sorted by unique ID @@ -23,20 +23,20 @@ type TypeSet struct { } // IsEmpty reports whether type set s is the empty set. -func (s *TypeSet) IsEmpty() bool { return s.terms.isEmpty() } +func (s *_TypeSet) IsEmpty() bool { return s.terms.isEmpty() } // IsAll reports whether type set s is the set of all types (corresponding to the empty interface). -func (s *TypeSet) IsAll() bool { +func (s *_TypeSet) IsAll() bool { return !s.comparable && len(s.methods) == 0 && s.terms.isAll() } // TODO(gri) IsMethodSet is not a great name for this predicate. Find a better one. // IsMethodSet reports whether the type set s is described by a single set of methods. -func (s *TypeSet) IsMethodSet() bool { return !s.comparable && s.terms.isAll() } +func (s *_TypeSet) IsMethodSet() bool { return !s.comparable && s.terms.isAll() } // IsComparable reports whether each type in the set is comparable. -func (s *TypeSet) IsComparable() bool { +func (s *_TypeSet) IsComparable() bool { if s.terms.isAll() { return s.comparable } @@ -48,24 +48,24 @@ func (s *TypeSet) IsComparable() bool { // TODO(gri) IsTypeSet is not a great name for this predicate. Find a better one. // IsTypeSet reports whether the type set s is represented by a finite set of underlying types. -func (s *TypeSet) IsTypeSet() bool { +func (s *_TypeSet) IsTypeSet() bool { return !s.comparable && len(s.methods) == 0 } // NumMethods returns the number of methods available. -func (s *TypeSet) NumMethods() int { return len(s.methods) } +func (s *_TypeSet) NumMethods() int { return len(s.methods) } // Method returns the i'th method of type set s for 0 <= i < s.NumMethods(). // The methods are ordered by their unique ID. -func (s *TypeSet) Method(i int) *Func { return s.methods[i] } +func (s *_TypeSet) Method(i int) *Func { return s.methods[i] } // LookupMethod returns the index of and method with matching package and name, or (-1, nil). -func (s *TypeSet) LookupMethod(pkg *Package, name string) (int, *Func) { +func (s *_TypeSet) LookupMethod(pkg *Package, name string) (int, *Func) { // TODO(gri) s.methods is sorted - consider binary search return lookupMethod(s.methods, pkg, name) } -func (s *TypeSet) String() string { +func (s *_TypeSet) String() string { switch { case s.IsEmpty(): return "∅" @@ -105,16 +105,16 @@ func (s *TypeSet) String() string { // ---------------------------------------------------------------------------- // Implementation -func (s *TypeSet) hasTerms() bool { return !s.terms.isAll() } -func (s *TypeSet) structuralType() Type { return s.terms.structuralType() } -func (s *TypeSet) includes(t Type) bool { return s.terms.includes(t) } -func (s1 *TypeSet) subsetOf(s2 *TypeSet) bool { return s1.terms.subsetOf(s2.terms) } +func (s *_TypeSet) hasTerms() bool { return !s.terms.isAll() } +func (s *_TypeSet) structuralType() Type { return s.terms.structuralType() } +func (s *_TypeSet) includes(t Type) bool { return s.terms.includes(t) } +func (s1 *_TypeSet) subsetOf(s2 *_TypeSet) bool { return s1.terms.subsetOf(s2.terms) } // TODO(gri) TypeSet.is and TypeSet.underIs should probably also go into termlist.go var topTerm = term{false, theTop} -func (s *TypeSet) is(f func(*term) bool) bool { +func (s *_TypeSet) is(f func(*term) bool) bool { if len(s.terms) == 0 { return false } @@ -133,7 +133,7 @@ func (s *TypeSet) is(f func(*term) bool) bool { return true } -func (s *TypeSet) underIs(f func(Type) bool) bool { +func (s *_TypeSet) underIs(f func(Type) bool) bool { if len(s.terms) == 0 { return false } @@ -158,10 +158,10 @@ func (s *TypeSet) underIs(f func(Type) bool) bool { } // topTypeSet may be used as type set for the empty interface. -var topTypeSet = TypeSet{terms: allTermlist} +var topTypeSet = _TypeSet{terms: allTermlist} // computeInterfaceTypeSet may be called with check == nil. -func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *TypeSet { +func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_TypeSet { if ityp.tset != nil { return ityp.tset } @@ -197,7 +197,7 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *T // have valid interfaces. Mark the interface as complete to avoid // infinite recursion if the validType check occurs later for some // reason. - ityp.tset = &TypeSet{terms: allTermlist} // TODO(gri) is this sufficient? + ityp.tset = &_TypeSet{terms: allTermlist} // TODO(gri) is this sufficient? // Methods of embedded interfaces are collected unchanged; i.e., the identity // of a method I.m's Func Object of an interface I is the same as that of @@ -347,17 +347,17 @@ func (a byUniqueMethodName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } // invalidTypeSet is a singleton type set to signal an invalid type set // due to an error. It's also a valid empty type set, so consumers of // type sets may choose to ignore it. -var invalidTypeSet TypeSet +var invalidTypeSet _TypeSet // computeUnionTypeSet may be called with check == nil. // The result is &invalidTypeSet if the union overflows. -func computeUnionTypeSet(check *Checker, pos syntax.Pos, utyp *Union) *TypeSet { +func computeUnionTypeSet(check *Checker, pos syntax.Pos, utyp *Union) *_TypeSet { if utyp.tset != nil { return utyp.tset } // avoid infinite recursion (see also computeInterfaceTypeSet) - utyp.tset = new(TypeSet) + utyp.tset = new(_TypeSet) var allTerms termlist for _, t := range utyp.terms { diff --git a/src/cmd/compile/internal/types2/union.go b/src/cmd/compile/internal/types2/union.go index f61c37a6af..933e5a2951 100644 --- a/src/cmd/compile/internal/types2/union.go +++ b/src/cmd/compile/internal/types2/union.go @@ -11,8 +11,8 @@ import "cmd/compile/internal/syntax" // A Union represents a union of terms embedded in an interface. type Union struct { - terms []*Term // list of syntactical terms (not a canonicalized termlist) - tset *TypeSet // type set described by this union, computed lazily + terms []*Term // list of syntactical terms (not a canonicalized termlist) + tset *_TypeSet // type set described by this union, computed lazily } // NewUnion returns a new Union type with the given terms. diff --git a/src/cmd/compile/internal/types2/universe.go b/src/cmd/compile/internal/types2/universe.go index f14c079222..a615b4c876 100644 --- a/src/cmd/compile/internal/types2/universe.go +++ b/src/cmd/compile/internal/types2/universe.go @@ -99,7 +99,7 @@ func defPredeclaredTypes() { { obj := NewTypeName(nopos, nil, "comparable", nil) obj.setColor(black) - ityp := &Interface{obj, nil, nil, nil, true, &TypeSet{true, nil, allTermlist}} + ityp := &Interface{obj, nil, nil, nil, true, &_TypeSet{true, nil, allTermlist}} NewNamed(obj, ityp, nil) def(obj) } -- GitLab From bd9776357732eb3a3c635427bb3591e4cbc79cc5 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 23 Aug 2021 17:38:55 -0700 Subject: [PATCH 0826/2500] cmd/compile/internal/types2: use an opaque environment for Instantiate This is a port of CL 343930 from go/types, adjusted to work for the compiler: here Environment carries a *Checker, if available. Change-Id: I44544fad7da870fa0c02832baa6abd2909d50304 Reviewed-on: https://go-review.googlesource.com/c/go/+/344612 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/noder/reader2.go | 2 +- .../compile/internal/types2/instantiate.go | 26 ++++++++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index 64c1612f70..e72a6737ed 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -228,7 +228,7 @@ func (r *reader2) doTyp() (res types2.Type) { obj, targs := r.obj() name := obj.(*types2.TypeName) if len(targs) != 0 { - t, _ := types2.Instantiate(r.p.check, name.Type(), targs, false) + t, _ := types2.Instantiate(types2.NewEnvironment(r.p.check), name.Type(), targs, false) return t } return name.Type() diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index fdb8c40572..9d60021667 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -13,6 +13,21 @@ import ( "fmt" ) +// An Environment is an opaque type checking environment. It may be used to +// share identical type instances across type checked packages or calls to +// Instantiate. +type Environment struct { + // For now, Environment just hides a Checker. + // Eventually, we strive to remove the need for a checker. + check *Checker +} + +// NewEnvironment returns a new Environment, initialized with the given +// Checker, or nil. +func NewEnvironment(check *Checker) *Environment { + return &Environment{check} +} + // Instantiate instantiates the type typ with the given type arguments targs. // typ must be a *Named or a *Signature type, and its number of type parameters // must match the number of provided type arguments. The result is a new, @@ -20,8 +35,9 @@ import ( // *Signature). Any methods attached to a *Named are simply copied; they are // not instantiated. // -// If check is non-nil, it will be used to de-dupe the instance against -// previous instances with the same identity. +// If env is non-nil, it may be used to de-dupe the instance against previous +// instances with the same identity. This functionality is implemented for +// environments with non-nil Checkers. // // If verify is set and constraint satisfaction fails, the returned error may // be of dynamic type ArgumentError indicating which type argument did not @@ -29,7 +45,11 @@ import ( // // TODO(rfindley): change this function to also return an error if lengths of // tparams and targs do not match. -func Instantiate(check *Checker, typ Type, targs []Type, validate bool) (Type, error) { +func Instantiate(env *Environment, typ Type, targs []Type, validate bool) (Type, error) { + var check *Checker + if env != nil { + check = env.check + } inst := check.instance(nopos, typ, targs) var err error -- GitLab From 1ff0554b5318d5a39e2b26a9c84330e6aa47b1c6 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 23 Aug 2021 18:29:38 -0700 Subject: [PATCH 0827/2500] cmd/compile/internal/types2: use []*TypeParam rather than []*TypeName for type param lists This is a port of CL 343932 from go/types, with the necessary adjustments to the compiler. This change improves type safety slightly, avoids many internal type assertions, and simplifies some code paths. Change-Id: Ie9c4734814f49cd248927152d7b3264d3578428c Reviewed-on: https://go-review.googlesource.com/c/go/+/344614 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky Reviewed-by: Dan Scales --- src/cmd/compile/internal/importer/iimport.go | 14 ++++---- src/cmd/compile/internal/noder/decl.go | 2 +- src/cmd/compile/internal/noder/reader2.go | 11 +++---- .../internal/noder/syncmarker_string.go | 5 +-- src/cmd/compile/internal/noder/types.go | 4 +-- src/cmd/compile/internal/noder/writer.go | 6 ++-- src/cmd/compile/internal/types2/decl.go | 12 +++---- src/cmd/compile/internal/types2/infer.go | 32 +++++++++---------- .../compile/internal/types2/instantiate.go | 10 +++--- src/cmd/compile/internal/types2/named.go | 4 +-- src/cmd/compile/internal/types2/object.go | 2 +- src/cmd/compile/internal/types2/predicates.go | 4 +-- src/cmd/compile/internal/types2/signature.go | 18 +++++------ src/cmd/compile/internal/types2/subst.go | 4 +-- src/cmd/compile/internal/types2/typeparam.go | 11 +++---- src/cmd/compile/internal/types2/typestring.go | 7 ++-- src/cmd/compile/internal/types2/unify.go | 14 ++++---- 17 files changed, 79 insertions(+), 81 deletions(-) diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index 4384e59c30..a46971d0a7 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -309,7 +309,7 @@ func (r *importReader) obj(name string) { r.declare(types2.NewConst(pos, r.currPkg, name, typ, val)) case 'F', 'G': - var tparams []*types2.TypeName + var tparams []*types2.TypeParam if tag == 'G' { tparams = r.tparamList() } @@ -318,7 +318,7 @@ func (r *importReader) obj(name string) { r.declare(types2.NewFunc(pos, r.currPkg, name, sig)) case 'T', 'U': - var tparams []*types2.TypeName + var tparams []*types2.TypeParam if tag == 'U' { tparams = r.tparamList() } @@ -347,9 +347,9 @@ func (r *importReader) obj(name string) { // typeparams being used in the method sig/body). targs := baseType(msig.Recv().Type()).TArgs() if len(targs) > 0 { - rparams := make([]*types2.TypeName, len(targs)) + rparams := make([]*types2.TypeParam, len(targs)) for i, targ := range targs { - rparams[i] = types2.AsTypeParam(targ).Obj() + rparams[i] = types2.AsTypeParam(targ) } msig.SetRParams(rparams) } @@ -690,15 +690,15 @@ func (r *importReader) signature(recv *types2.Var) *types2.Signature { return types2.NewSignature(recv, params, results, variadic) } -func (r *importReader) tparamList() []*types2.TypeName { +func (r *importReader) tparamList() []*types2.TypeParam { n := r.uint64() if n == 0 { return nil } - xs := make([]*types2.TypeName, n) + xs := make([]*types2.TypeParam, n) for i := range xs { typ := r.typ() - xs[i] = types2.AsTypeParam(typ).Obj() + xs[i] = types2.AsTypeParam(typ) } return xs } diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go index 6b55ce1453..ffcfc103a6 100644 --- a/src/cmd/compile/internal/noder/decl.go +++ b/src/cmd/compile/internal/noder/decl.go @@ -191,7 +191,7 @@ func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) { if n := tparams.Len(); n > 0 { rparams := make([]*types.Type, n) for i := range rparams { - rparams[i] = g.typ(tparams.At(i).Type()) + rparams[i] = g.typ(tparams.At(i)) } // This will set hasTParam flag if any rparams are not concrete types. ntyp.SetRParams(rparams) diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index e72a6737ed..8f3f0a50e9 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -396,7 +396,7 @@ func (pr *pkgReader2) objIdx(idx int) (*types2.Package, string) { case objType: pos := r.pos() - return types2.NewTypeNameLazy(pos, objPkg, objName, func(named *types2.Named) (tparams []*types2.TypeName, underlying types2.Type, methods []*types2.Func) { + return types2.NewTypeNameLazy(pos, objPkg, objName, func(named *types2.Named) (tparams []*types2.TypeParam, underlying types2.Type, methods []*types2.Func) { tparams = r.typeParamNames() // TODO(mdempsky): Rewrite receiver types to underlying is an @@ -453,7 +453,7 @@ func (pr *pkgReader2) objDictIdx(idx int) *reader2Dict { return &dict } -func (r *reader2) typeParamNames() []*types2.TypeName { +func (r *reader2) typeParamNames() []*types2.TypeParam { r.sync(syncTypeParamNames) // Note: This code assumes it only processes objects without @@ -470,21 +470,20 @@ func (r *reader2) typeParamNames() []*types2.TypeName { // create all the TypeNames and TypeParams, then we construct and // set the bound type. - names := make([]*types2.TypeName, len(r.dict.bounds)) r.dict.tparams = make([]*types2.TypeParam, len(r.dict.bounds)) for i := range r.dict.bounds { pos := r.pos() pkg, name := r.localIdent() - names[i] = types2.NewTypeName(pos, pkg, name, nil) - r.dict.tparams[i] = r.p.check.NewTypeParam(names[i], nil) + tname := types2.NewTypeName(pos, pkg, name, nil) + r.dict.tparams[i] = r.p.check.NewTypeParam(tname, nil) } for i, bound := range r.dict.bounds { r.dict.tparams[i].SetConstraint(r.p.typIdx(bound, r.dict)) } - return names + return r.dict.tparams } func (r *reader2) method() *types2.Func { diff --git a/src/cmd/compile/internal/noder/syncmarker_string.go b/src/cmd/compile/internal/noder/syncmarker_string.go index 14747b7c10..655cafc950 100644 --- a/src/cmd/compile/internal/noder/syncmarker_string.go +++ b/src/cmd/compile/internal/noder/syncmarker_string.go @@ -140,11 +140,12 @@ func _() { _ = x[syncTypeParamNames-130] _ = x[syncTypeParamBounds-131] _ = x[syncImplicitTypes-132] + _ = x[syncObjectName-133] } -const _syncMarker_name = "NodeBoolInt64Uint64StringPosPkgSymSelectorKindTypeTypePkgSignatureParamOpObjectExprStmtDeclConstDeclFuncDeclTypeDeclVarDeclPragmaValueEOFMethodFuncBodyUseUseObjObjectIdxTypeIdxBOFEntryOpenScopeCloseScopeGlobalLocalDefineDefLocalUseLocalDefGlobalUseGlobalTypeParamsUseLabelDefLabelFuncLitCommonFuncBodyRefLinksymExtHackSetlinenoNameImportDeclDeclNamesDeclNameExprListExprsWrapnameTypeExprTypeExprOrNilChanDirParamsCloseAnotherScopeSumUnOpBinOpStructTypeInterfaceTypePacknameEmbeddedStmtsStmtsFallStmtFallBlockStmtIfStmtForStmtSwitchStmtRangeStmtCaseClauseCommClauseSelectStmtDeclsLabeledStmtCompLit1234NDefImplicitUseNameUseObjLocalAddLocalBothSignatureSetUnderlyingLinknameStmt1StmtsEndDeclareTopDeclsTopConstDeclTopFuncDeclTopTypeDeclTopVarDeclObject1AddBodyLabelFuncExtMethExtOptLabelScalarStmtDeclsDeclLocalObjLocalObjLocal1DeclareLocalPublicPrivateRelocsRelocUseRelocVarExtPkgDefTypeExtValCodeObjPosBaseLocalIdentTypeParamNamesTypeParamBoundsImplicitTypes" +const _syncMarker_name = "NodeBoolInt64Uint64StringPosPkgSymSelectorKindTypeTypePkgSignatureParamOpObjectExprStmtDeclConstDeclFuncDeclTypeDeclVarDeclPragmaValueEOFMethodFuncBodyUseUseObjObjectIdxTypeIdxBOFEntryOpenScopeCloseScopeGlobalLocalDefineDefLocalUseLocalDefGlobalUseGlobalTypeParamsUseLabelDefLabelFuncLitCommonFuncBodyRefLinksymExtHackSetlinenoNameImportDeclDeclNamesDeclNameExprListExprsWrapnameTypeExprTypeExprOrNilChanDirParamsCloseAnotherScopeSumUnOpBinOpStructTypeInterfaceTypePacknameEmbeddedStmtsStmtsFallStmtFallBlockStmtIfStmtForStmtSwitchStmtRangeStmtCaseClauseCommClauseSelectStmtDeclsLabeledStmtCompLit1234NDefImplicitUseNameUseObjLocalAddLocalBothSignatureSetUnderlyingLinknameStmt1StmtsEndDeclareTopDeclsTopConstDeclTopFuncDeclTopTypeDeclTopVarDeclObject1AddBodyLabelFuncExtMethExtOptLabelScalarStmtDeclsDeclLocalObjLocalObjLocal1DeclareLocalPublicPrivateRelocsRelocUseRelocVarExtPkgDefTypeExtValCodeObjPosBaseLocalIdentTypeParamNamesTypeParamBoundsImplicitTypesObjectName" -var _syncMarker_index = [...]uint16{0, 4, 8, 13, 19, 25, 28, 31, 34, 42, 46, 50, 57, 66, 71, 73, 79, 83, 87, 91, 100, 108, 116, 123, 129, 134, 137, 143, 151, 154, 160, 169, 176, 179, 184, 193, 203, 209, 214, 220, 228, 236, 245, 254, 264, 272, 280, 287, 297, 304, 314, 318, 327, 331, 341, 350, 358, 366, 371, 379, 387, 400, 407, 413, 430, 433, 437, 442, 452, 465, 473, 481, 486, 495, 503, 512, 518, 525, 535, 544, 554, 564, 574, 579, 590, 597, 598, 599, 600, 601, 602, 613, 620, 631, 639, 652, 665, 673, 678, 686, 693, 701, 713, 724, 735, 745, 752, 759, 764, 771, 778, 786, 792, 801, 810, 818, 827, 839, 845, 852, 858, 863, 871, 877, 883, 890, 893, 900, 907, 917, 931, 946, 959} +var _syncMarker_index = [...]uint16{0, 4, 8, 13, 19, 25, 28, 31, 34, 42, 46, 50, 57, 66, 71, 73, 79, 83, 87, 91, 100, 108, 116, 123, 129, 134, 137, 143, 151, 154, 160, 169, 176, 179, 184, 193, 203, 209, 214, 220, 228, 236, 245, 254, 264, 272, 280, 287, 297, 304, 314, 318, 327, 331, 341, 350, 358, 366, 371, 379, 387, 400, 407, 413, 430, 433, 437, 442, 452, 465, 473, 481, 486, 495, 503, 512, 518, 525, 535, 544, 554, 564, 574, 579, 590, 597, 598, 599, 600, 601, 602, 613, 620, 631, 639, 652, 665, 673, 678, 686, 693, 701, 713, 724, 735, 745, 752, 759, 764, 771, 778, 786, 792, 801, 810, 818, 827, 839, 845, 852, 858, 863, 871, 877, 883, 890, 893, 900, 907, 917, 931, 946, 959, 969} func (i syncMarker) String() string { i -= 1 diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index 8d596e599e..dd1fdcf96b 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -306,7 +306,7 @@ func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) { rparams := types2.AsSignature(m.Type()).RParams() tparams := make([]*types.Type, rparams.Len()) for i := range tparams { - tparams[i] = g.typ1(rparams.At(i).Type()) + tparams[i] = g.typ1(rparams.At(i)) } assert(len(tparams) == len(targs)) ts := typecheck.Tsubster{ @@ -338,7 +338,7 @@ func (g *irgen) signature(recv *types.Field, sig *types2.Signature) *types.Type tparams2 := sig.TParams() tparams := make([]*types.Field, tparams2.Len()) for i := range tparams { - tp := tparams2.At(i) + tp := tparams2.At(i).Obj() tparams[i] = types.NewField(g.pos(tp), g.sym(tp), g.typ1(tp.Type())) } diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index a33b24e50c..02df9a43de 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -618,7 +618,7 @@ func (w *writer) objDict(obj types2.Object, dict *writerDict) { ntparams := tparams.Len() w.len(ntparams) for i := 0; i < ntparams; i++ { - w.typ(tparams.At(i).Type().(*types2.TypeParam).Constraint()) + w.typ(tparams.At(i).Constraint()) } nderived := len(dict.derived) @@ -647,7 +647,7 @@ func (w *writer) typeParamNames(tparams *types2.TParamList) { ntparams := tparams.Len() for i := 0; i < ntparams; i++ { - tparam := tparams.At(i) + tparam := tparams.At(i).Obj() w.pos(tparam) w.localIdent(tparam) } @@ -1479,7 +1479,7 @@ func (c *declCollector) withTParams(obj types2.Object) *declCollector { copy := *c copy.implicits = copy.implicits[:len(copy.implicits):len(copy.implicits)] for i := 0; i < n; i++ { - copy.implicits = append(copy.implicits, tparams.At(i)) + copy.implicits = append(copy.implicits, tparams.At(i).Obj()) } return © } diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index aa9710788a..342e1090de 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -582,7 +582,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named } func (check *Checker) collectTypeParams(list []*syntax.Field) *TParamList { - tparams := make([]*TypeName, len(list)) + tparams := make([]*TypeParam, len(list)) // Declare type parameters up-front. // The scope of type parameters starts at the beginning of the type parameter @@ -599,16 +599,16 @@ func (check *Checker) collectTypeParams(list []*syntax.Field) *TParamList { if i == 0 || f.Type != list[i-1].Type { bound = check.boundType(f.Type) } - tparams[i].typ.(*TypeParam).bound = bound + tparams[i].bound = bound } return bindTParams(tparams) } -func (check *Checker) declareTypeParam(name *syntax.Name) *TypeName { - tpar := NewTypeName(name.Pos(), check.pkg, name.Value, nil) - check.NewTypeParam(tpar, nil) // assigns type to tpar as a side-effect - check.declare(check.scope, name, tpar, check.scope.pos) // TODO(gri) check scope position +func (check *Checker) declareTypeParam(name *syntax.Name) *TypeParam { + tname := NewTypeName(name.Pos(), check.pkg, name.Value, nil) + tpar := check.NewTypeParam(tname, nil) // assigns type to tname as a side-effect + check.declare(check.scope, name, tname, check.scope.pos) // TODO(gri) check scope position return tpar } diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index 7bf507471d..6e4fe502b6 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -28,7 +28,7 @@ const useConstraintTypeInference = true // // Constraint type inference is used after each step to expand the set of type arguments. // -func (check *Checker) infer(pos syntax.Pos, tparams []*TypeName, targs []Type, params *Tuple, args []*operand, report bool) (result []Type) { +func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, params *Tuple, args []*operand, report bool) (result []Type) { if debug { defer func() { assert(result == nil || len(result) == len(tparams)) @@ -122,7 +122,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeName, targs []Type, p } } if allFailed { - check.errorf(arg, "%s %s of %s does not match %s (cannot infer %s)", kind, targ, arg.expr, tpar, typeNamesString(tparams)) + check.errorf(arg, "%s %s of %s does not match %s (cannot infer %s)", kind, targ, arg.expr, tpar, typeParamsString(tparams)) return } } @@ -222,23 +222,23 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeName, targs []Type, p assert(targs != nil && index >= 0 && targs[index] == nil) tpar := tparams[index] if report { - check.errorf(pos, "cannot infer %s (%s) (%s)", tpar.name, tpar.pos, targs) + check.errorf(pos, "cannot infer %s (%s) (%s)", tpar.obj.name, tpar.obj.pos, targs) } return nil } -// typeNamesString produces a string containing all the -// type names in list suitable for human consumption. -func typeNamesString(list []*TypeName) string { +// typeParamsString produces a string of the type parameter names +// in list suitable for human consumption. +func typeParamsString(list []*TypeParam) string { // common cases n := len(list) switch n { case 0: return "" case 1: - return list[0].name + return list[0].obj.name case 2: - return list[0].name + " and " + list[1].name + return list[0].obj.name + " and " + list[1].obj.name } // general case (n > 2) @@ -248,15 +248,15 @@ func typeNamesString(list []*TypeName) string { if i > 0 { b.WriteString(", ") } - b.WriteString(tname.name) + b.WriteString(tname.obj.name) } b.WriteString(", and ") - b.WriteString(list[n-1].name) + b.WriteString(list[n-1].obj.name) return b.String() } // IsParameterized reports whether typ contains any of the type parameters of tparams. -func isParameterized(tparams []*TypeName, typ Type) bool { +func isParameterized(tparams []*TypeParam, typ Type) bool { w := tpWalker{ seen: make(map[Type]bool), tparams: tparams, @@ -266,7 +266,7 @@ func isParameterized(tparams []*TypeName, typ Type) bool { type tpWalker struct { seen map[Type]bool - tparams []*TypeName + tparams []*TypeParam } func (w *tpWalker) isParameterized(typ Type) (res bool) { @@ -339,7 +339,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { case *TypeParam: // t must be one of w.tparams - return t.index < len(w.tparams) && w.tparams[t.index].typ == t + return t.index < len(w.tparams) && w.tparams[t.index] == t default: unreachable() @@ -365,7 +365,7 @@ func (w *tpWalker) isParameterizedTypeList(list []Type) bool { // first type argument in that list that couldn't be inferred (and thus is nil). If all // type arguments were inferred successfully, index is < 0. The number of type arguments // provided may be less than the number of type parameters, but there must be at least one. -func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (types []Type, index int) { +func (check *Checker) inferB(tparams []*TypeParam, targs []Type, report bool) (types []Type, index int) { assert(len(tparams) >= len(targs) && len(targs) > 0) // Setup bidirectional unification between those structural bounds @@ -383,12 +383,12 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty // Unify type parameters with their structural constraints, if any. for _, tpar := range tparams { - typ := tpar.typ.(*TypeParam) + typ := tpar sbound := typ.structuralType() if sbound != nil { if !u.unify(typ, sbound) { if report { - check.errorf(tpar, "%s does not match %s", tpar, sbound) + check.errorf(tpar.obj, "%s does not match %s", tpar.obj, sbound) } return nil, 0 } diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 9d60021667..06cbcda58e 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -54,7 +54,7 @@ func Instantiate(env *Environment, typ Type, targs []Type, validate bool) (Type, var err error if validate { - var tparams []*TypeName + var tparams []*TypeParam switch t := typ.(type) { case *Named: tparams = t.TParams().list() @@ -96,7 +96,7 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, posLis check.later(func() { // Collect tparams again because lazily loaded *Named types may not have // had tparams set up above. - var tparams []*TypeName + var tparams []*TypeParam switch t := typ.(type) { case *Named: tparams = t.TParams().list() @@ -192,11 +192,11 @@ func (check *Checker) validateTArgLen(pos syntax.Pos, tparams *TParamList, targs return true } -func (check *Checker) verify(pos syntax.Pos, tparams []*TypeName, targs []Type) (int, error) { +func (check *Checker) verify(pos syntax.Pos, tparams []*TypeParam, targs []Type) (int, error) { smap := makeSubstMap(tparams, targs) - for i, tname := range tparams { + for i, tpar := range tparams { // stop checking bounds after the first failure - if err := check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap); err != nil { + if err := check.satisfies(pos, targs[i], tpar, smap); err != nil { return i, err } } diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index 87b5716f7c..db12b08e67 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -24,7 +24,7 @@ type Named struct { targs []Type // type arguments (after instantiation), or nil methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily - resolve func(*Named) ([]*TypeName, Type, []*Func) + resolve func(*Named) ([]*TypeParam, Type, []*Func) once sync.Once } @@ -126,7 +126,7 @@ func (t *Named) Orig() *Named { return t.orig } func (t *Named) TParams() *TParamList { return t.load().tparams } // SetTParams sets the type parameters of the named type t. -func (t *Named) SetTParams(tparams []*TypeName) { t.load().tparams = bindTParams(tparams) } +func (t *Named) SetTParams(tparams []*TypeParam) { t.load().tparams = bindTParams(tparams) } // TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated. func (t *Named) TArgs() []Type { return t.targs } diff --git a/src/cmd/compile/internal/types2/object.go b/src/cmd/compile/internal/types2/object.go index 8263ccae0c..c1466f24ed 100644 --- a/src/cmd/compile/internal/types2/object.go +++ b/src/cmd/compile/internal/types2/object.go @@ -278,7 +278,7 @@ func NewTypeName(pos syntax.Pos, pkg *Package, name string, typ Type) *TypeName // NewTypeNameLazy returns a new defined type like NewTypeName, but it // lazily calls resolve to finish constructing the Named object. -func NewTypeNameLazy(pos syntax.Pos, pkg *Package, name string, resolve func(named *Named) (tparams []*TypeName, underlying Type, methods []*Func)) *TypeName { +func NewTypeNameLazy(pos syntax.Pos, pkg *Package, name string, resolve func(named *Named) (tparams []*TypeParam, underlying Type, methods []*Func)) *TypeName { obj := NewTypeName(pos, pkg, name, nil) NewNamed(obj, nil, nil).resolve = resolve return obj diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 3c883e1ab5..ed62743f6d 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -349,13 +349,13 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { return false } -func identicalTParams(x, y []*TypeName, cmpTags bool, p *ifacePair) bool { +func identicalTParams(x, y []*TypeParam, cmpTags bool, p *ifacePair) bool { if len(x) != len(y) { return false } for i, x := range x { y := y[i] - if !identical(x.typ.(*TypeParam).bound, y.typ.(*TypeParam).bound, cmpTags, p) { + if !identical(x.bound, y.bound, cmpTags, p) { return false } } diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index e319e65211..f1bf60ae8e 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -57,13 +57,13 @@ func (s *Signature) Recv() *Var { return s.recv } func (s *Signature) TParams() *TParamList { return s.tparams } // SetTParams sets the type parameters of signature s. -func (s *Signature) SetTParams(tparams []*TypeName) { s.tparams = bindTParams(tparams) } +func (s *Signature) SetTParams(tparams []*TypeParam) { s.tparams = bindTParams(tparams) } // RParams returns the receiver type parameters of signature s, or nil. func (s *Signature) RParams() *TParamList { return s.rparams } // SetRParams sets the receiver type params of signature s. -func (s *Signature) SetRParams(rparams []*TypeName) { s.rparams = bindTParams(rparams) } +func (s *Signature) SetRParams(rparams []*TypeParam) { s.rparams = bindTParams(rparams) } // Params returns the parameters of signature s, or nil. func (s *Signature) Params() *Tuple { return s.params } @@ -119,14 +119,14 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] // blank identifiers were found => use rewritten receiver type recvTyp = isubst(recvPar.Type, smap) } - rlist := make([]*TypeName, len(rparams)) + rlist := make([]*TypeParam, len(rparams)) for i, rparam := range rparams { rlist[i] = check.declareTypeParam(rparam) } sig.rparams = bindTParams(rlist) // determine receiver type to get its type parameters // and the respective type parameter bounds - var recvTParams []*TypeName + var recvTParams []*TypeParam if rname != nil { // recv should be a Named type (otherwise an error is reported elsewhere) // Also: Don't report an error via genericType since it will be reported @@ -142,19 +142,19 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] // We have a list of *TypeNames but we need a list of Types. list := make([]Type, sig.RParams().Len()) for i, t := range sig.RParams().list() { - list[i] = t.typ + list[i] = t } smap := makeSubstMap(recvTParams, list) - for i, tname := range sig.RParams().list() { - bound := recvTParams[i].typ.(*TypeParam).bound + for i, tpar := range sig.RParams().list() { + bound := recvTParams[i].bound // bound is (possibly) parameterized in the context of the // receiver type declaration. Substitute parameters for the // current context. // TODO(gri) should we assume now that bounds always exist? // (no bound == empty interface) if bound != nil { - bound = check.subst(tname.pos, bound, smap, nil) - tname.typ.(*TypeParam).bound = bound + bound = check.subst(tpar.obj.pos, bound, smap, nil) + tpar.bound = bound } } } diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index edbbdb4758..467066cc69 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -15,11 +15,11 @@ type substMap map[*TypeParam]Type // makeSubstMap creates a new substitution map mapping tpars[i] to targs[i]. // If targs[i] is nil, tpars[i] is not substituted. -func makeSubstMap(tpars []*TypeName, targs []Type) substMap { +func makeSubstMap(tpars []*TypeParam, targs []Type) substMap { assert(len(tpars) == len(targs)) proj := make(substMap, len(tpars)) for i, tpar := range tpars { - proj[tpar.typ.(*TypeParam)] = targs[i] + proj[tpar] = targs[i] } return proj } diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index f666fae7ed..0d76dd1a6e 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -84,7 +84,7 @@ func (t *TypeParam) Underlying() Type { return t } func (t *TypeParam) String() string { return TypeString(t, nil) } // TParamList holds a list of type parameters bound to a type. -type TParamList struct{ tparams []*TypeName } +type TParamList struct{ tparams []*TypeParam } // Len returns the number of type parameters in the list. // It is safe to call on a nil receiver. @@ -93,23 +93,22 @@ func (tps *TParamList) Len() int { } // At returns the i'th type parameter in the list. -func (tps *TParamList) At(i int) *TypeName { +func (tps *TParamList) At(i int) *TypeParam { return tps.list()[i] } -func (tps *TParamList) list() []*TypeName { +func (tps *TParamList) list() []*TypeParam { if tps == nil { return nil } return tps.tparams } -func bindTParams(list []*TypeName) *TParamList { +func bindTParams(list []*TypeParam) *TParamList { if len(list) == 0 { return nil } - for i, tp := range list { - typ := tp.Type().(*TypeParam) + for i, typ := range list { if typ.index >= 0 { panic("type parameter bound more than once") } diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index cb7cf73a62..5759118c94 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -242,14 +242,13 @@ func writeTypeList(buf *bytes.Buffer, list []Type, qf Qualifier, visited []Type) } } -func writeTParamList(buf *bytes.Buffer, list []*TypeName, qf Qualifier, visited []Type) { +func writeTParamList(buf *bytes.Buffer, list []*TypeParam, qf Qualifier, visited []Type) { buf.WriteString("[") var prev Type - for i, p := range list { + for i, tpar := range list { // Determine the type parameter and its constraint. // list is expected to hold type parameter names, // but don't crash if that's not the case. - tpar, _ := p.typ.(*TypeParam) var bound Type if tpar != nil { bound = tpar.bound // should not be nil but we want to see it if it is @@ -268,7 +267,7 @@ func writeTParamList(buf *bytes.Buffer, list []*TypeName, qf Qualifier, visited if tpar != nil { writeType(buf, tpar, qf, visited) } else { - buf.WriteString(p.name) + buf.WriteString(tpar.obj.name) } } if prev != nil { diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index 710fc51b53..58f5c17e5f 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -62,7 +62,7 @@ func (u *unifier) unify(x, y Type) bool { // A tparamsList describes a list of type parameters and the types inferred for them. type tparamsList struct { unifier *unifier - tparams []*TypeName + tparams []*TypeParam // For each tparams element, there is a corresponding type slot index in indices. // index < 0: unifier.types[-index-1] == nil // index == 0: no type slot allocated yet @@ -77,11 +77,11 @@ type tparamsList struct { func (d *tparamsList) String() string { var buf bytes.Buffer buf.WriteByte('[') - for i, tname := range d.tparams { + for i, tpar := range d.tparams { if i > 0 { buf.WriteString(", ") } - writeType(&buf, tname.typ, nil, nil) + writeType(&buf, tpar, nil, nil) buf.WriteString(": ") writeType(&buf, d.at(i), nil, nil) } @@ -92,13 +92,13 @@ func (d *tparamsList) String() string { // init initializes d with the given type parameters. // The type parameters must be in the order in which they appear in their declaration // (this ensures that the tparams indices match the respective type parameter index). -func (d *tparamsList) init(tparams []*TypeName) { +func (d *tparamsList) init(tparams []*TypeParam) { if len(tparams) == 0 { return } if debug { for i, tpar := range tparams { - assert(i == tpar.typ.(*TypeParam).index) + assert(i == tpar.index) } } d.tparams = tparams @@ -158,8 +158,8 @@ func (d *tparamsList) index(typ Type) int { // If tpar is a type parameter in list, tparamIndex returns the type parameter index. // Otherwise, the result is < 0. tpar must not be nil. -func tparamIndex(list []*TypeName, tpar *TypeParam) int { - if i := tpar.index; i < len(list) && list[i].typ == tpar { +func tparamIndex(list []*TypeParam, tpar *TypeParam) int { + if i := tpar.index; i < len(list) && list[i] == tpar { return i } return -1 -- GitLab From b1cdf860dd5f517a2835c6bd48d12dad29ade1da Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 23 Aug 2021 20:43:57 -0700 Subject: [PATCH 0828/2500] cmd/compile/internal/types2: use a TypeList type to hold type arguments This is a port of CL 343933 from go/types with the necessary adjustments in the compiler. With this CL type parameters and type lists are now held in TParamList and TypeList data types which don't expose the internal representation. Change-Id: I6d60881b5db995dbc04ed3f4a96e8b5d41f83969 Reviewed-on: https://go-review.googlesource.com/c/go/+/344615 Trust: Robert Griesemer Reviewed-by: Matthew Dempsky Reviewed-by: Dan Scales --- src/cmd/compile/internal/importer/iimport.go | 8 +-- src/cmd/compile/internal/noder/expr.go | 8 +-- src/cmd/compile/internal/noder/types.go | 20 +++--- src/cmd/compile/internal/noder/writer.go | 16 ++--- src/cmd/compile/internal/types2/infer.go | 2 +- .../compile/internal/types2/instantiate.go | 12 ++-- src/cmd/compile/internal/types2/lookup.go | 4 +- src/cmd/compile/internal/types2/named.go | 14 ++-- src/cmd/compile/internal/types2/predicates.go | 4 +- .../compile/internal/types2/sizeof_test.go | 2 +- src/cmd/compile/internal/types2/subst.go | 8 +-- src/cmd/compile/internal/types2/typelists.go | 69 +++++++++++++++++++ src/cmd/compile/internal/types2/typeparam.go | 34 --------- src/cmd/compile/internal/types2/typestring.go | 2 +- src/cmd/compile/internal/types2/unify.go | 10 ++- 15 files changed, 128 insertions(+), 85 deletions(-) create mode 100644 src/cmd/compile/internal/types2/typelists.go diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index a46971d0a7..c303126ea6 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -346,10 +346,10 @@ func (r *importReader) obj(name string) { // rparams of the method (since those are the // typeparams being used in the method sig/body). targs := baseType(msig.Recv().Type()).TArgs() - if len(targs) > 0 { - rparams := make([]*types2.TypeParam, len(targs)) - for i, targ := range targs { - rparams[i] = types2.AsTypeParam(targ) + if targs.Len() > 0 { + rparams := make([]*types2.TypeParam, targs.Len()) + for i := range rparams { + rparams[i] = types2.AsTypeParam(targs.At(i)) } msig.SetRParams(rparams) } diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 3e3c352a32..cb20d645aa 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -360,9 +360,9 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto // selinfo.Targs() are the types used to // instantiate the type of receiver targs2 := getTargs(selinfo) - targs := make([]ir.Node, len(targs2)) - for i, targ2 := range targs2 { - targs[i] = ir.TypeNode(g.typ(targ2)) + targs := make([]ir.Node, targs2.Len()) + for i := range targs { + targs[i] = ir.TypeNode(g.typ(targs2.At(i))) } // Create function instantiation with the type @@ -386,7 +386,7 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto } // getTargs gets the targs associated with the receiver of a selected method -func getTargs(selinfo *types2.Selection) []types2.Type { +func getTargs(selinfo *types2.Selection) *types2.TypeList { r := deref2(selinfo.Recv()) n := types2.AsNamed(r) if n == nil { diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index dd1fdcf96b..541ed68ef3 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -66,10 +66,12 @@ func (g *irgen) typ1(typ types2.Type) *types.Type { // instTypeName2 creates a name for an instantiated type, base on the type args // (given as types2 types). -func instTypeName2(name string, targs []types2.Type) string { +func instTypeName2(name string, targs *types2.TypeList) string { b := bytes.NewBufferString(name) b.WriteByte('[') - for i, targ := range targs { + n := targs.Len() + for i := 0; i < n; i++ { + targ := targs.At(i) if i > 0 { b.WriteByte(',') } @@ -140,9 +142,10 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { // non-generic types used to instantiate this type. We'll // use these when instantiating the methods of the // instantiated type. - rparams := make([]*types.Type, len(typ.TArgs())) - for i, targ := range typ.TArgs() { - rparams[i] = g.typ1(targ) + targs := typ.TArgs() + rparams := make([]*types.Type, targs.Len()) + for i := range rparams { + rparams[i] = g.typ1(targs.At(i)) } ntyp.SetRParams(rparams) //fmt.Printf("Saw new type %v %v\n", instName, ntyp.HasTParam()) @@ -267,9 +270,10 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { // and for actually generating the methods for instantiated types. func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) { if typ.NumMethods() != 0 { - targs := make([]*types.Type, len(typ.TArgs())) - for i, targ := range typ.TArgs() { - targs[i] = g.typ1(targ) + targs2 := typ.TArgs() + targs := make([]*types.Type, targs2.Len()) + for i := range targs { + targs[i] = g.typ1(targs2.At(i)) } methods := make([]*types.Field, typ.NumMethods()) diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 02df9a43de..a6bd8b2426 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -299,7 +299,7 @@ func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo { // Type aliases can refer to uninstantiated generic types, so we // might see len(TParams) != 0 && len(TArgs) == 0 here. // TODO(mdempsky): Revisit after #46477 is resolved. - assert(typ.TParams().Len() == len(typ.TArgs()) || len(typ.TArgs()) == 0) + assert(typ.TParams().Len() == typ.TArgs().Len() || typ.TArgs().Len() == 0) // TODO(mdempsky): Why do we need to loop here? orig := typ @@ -441,10 +441,10 @@ func (w *writer) param(param *types2.Var) { // @@@ Objects -func (w *writer) obj(obj types2.Object, explicits []types2.Type) { - explicitInfos := make([]typeInfo, len(explicits)) - for i, explicit := range explicits { - explicitInfos[i] = w.p.typIdx(explicit, w.dict) +func (w *writer) obj(obj types2.Object, explicits *types2.TypeList) { + explicitInfos := make([]typeInfo, explicits.Len()) + for i := range explicitInfos { + explicitInfos[i] = w.p.typIdx(explicits.At(i), w.dict) } info := objInfo{idx: w.p.objIdx(obj), explicits: explicitInfos} @@ -1212,7 +1212,7 @@ func (w *writer) expr(expr syntax.Expr) { if obj != nil { if isGlobal(obj) { w.code(exprName) - w.obj(obj, targs) + w.obj(obj, types2.NewTypeList(targs)) return } @@ -1321,7 +1321,7 @@ func (w *writer) expr(expr syntax.Expr) { // As if w.expr(expr.Fun), but using inf.TArgs instead. w.code(exprName) - w.obj(obj, inf.TArgs) + w.obj(obj, types2.NewTypeList(inf.TArgs)) } else { w.expr(expr.Fun) } @@ -1711,7 +1711,7 @@ func (w *writer) pkgDecl(decl syntax.Decl) { // TODO(mdempsky): Revisit after #46477 is resolved. if name.IsAlias() { named, ok := name.Type().(*types2.Named) - if ok && named.TParams().Len() != 0 && len(named.TArgs()) == 0 { + if ok && named.TParams().Len() != 0 && named.TArgs().Len() == 0 { break } } diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index 6e4fe502b6..5badecc070 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -335,7 +335,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { return w.isParameterized(t.elem) case *Named: - return w.isParameterizedTypeList(t.targs) + return w.isParameterizedTypeList(t.targs.list()) case *TypeParam: // t must be one of w.tparams diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 06cbcda58e..8bea63ec86 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -137,7 +137,7 @@ func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type) (res Type tname := NewTypeName(pos, t.obj.pkg, t.obj.name, nil) named := check.newNamed(tname, t, nil, nil, nil) // methods and tparams are set when named is loaded - named.targs = targs + named.targs = NewTypeList(targs) named.instance = &instance{pos} if check != nil { check.typMap[h] = named @@ -145,7 +145,7 @@ func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type) (res Type res = named case *Signature: tparams := t.TParams() - if !check.validateTArgLen(pos, tparams, targs) { + if !check.validateTArgLen(pos, tparams.Len(), len(targs)) { return Typ[Invalid] } if tparams.Len() == 0 { @@ -180,14 +180,14 @@ func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type) (res Type // validateTArgLen verifies that the length of targs and tparams matches, // reporting an error if not. If validation fails and check is nil, // validateTArgLen panics. -func (check *Checker) validateTArgLen(pos syntax.Pos, tparams *TParamList, targs []Type) bool { - if len(targs) != tparams.Len() { +func (check *Checker) validateTArgLen(pos syntax.Pos, ntparams, ntargs int) bool { + if ntargs != ntparams { // TODO(gri) provide better error message if check != nil { - check.errorf(pos, "got %d arguments but %d type parameters", len(targs), tparams.Len()) + check.errorf(pos, "got %d arguments but %d type parameters", ntargs, ntparams) return false } - panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, len(targs), tparams.Len())) + panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, ntargs, ntparams)) } return true } diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index 668c5ff3ec..d0718e51e2 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -394,10 +394,10 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // here. Exit early in this case to prevent an assertion // failure in makeSubstMap. // TODO(gri) Can we avoid this check by fixing the lengths? - if len(ftyp.RParams().list()) != len(Vn.targs) { + if len(ftyp.RParams().list()) != Vn.targs.Len() { return } - ftyp = check.subst(nopos, ftyp, makeSubstMap(ftyp.RParams().list(), Vn.targs), nil).(*Signature) + ftyp = check.subst(nopos, ftyp, makeSubstMap(ftyp.RParams().list(), Vn.targs.list()), nil).(*Signature) } // If the methods have type parameters we don't care whether they diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index db12b08e67..a3a2595a22 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -21,7 +21,7 @@ type Named struct { underlying Type // possibly a *Named during setup; never a *Named once set up completely instance *instance // position information for lazy instantiation, or nil tparams *TParamList // type parameters, or nil - targs []Type // type arguments (after instantiation), or nil + targs *TypeList // type arguments (after instantiation), or nil methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily resolve func(*Named) ([]*TypeParam, Type, []*Func) @@ -46,7 +46,7 @@ func (t *Named) load() *Named { // underlying is set when t is expanded. // // By convention, a type instance is loaded iff its tparams are set. - if len(t.targs) > 0 && t.tparams == nil { + if t.targs.Len() > 0 && t.tparams == nil { t.orig.load() t.tparams = t.orig.tparams t.methods = t.orig.methods @@ -128,8 +128,8 @@ func (t *Named) TParams() *TParamList { return t.load().tparams } // SetTParams sets the type parameters of the named type t. func (t *Named) SetTParams(tparams []*TypeParam) { t.load().tparams = bindTParams(tparams) } -// TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated. -func (t *Named) TArgs() []Type { return t.targs } +// TArgs returns the type arguments used to instantiate the named type t. +func (t *Named) TArgs() *TypeList { return t.targs } // NumMethods returns the number of explicit methods whose receiver is named type t. func (t *Named) NumMethods() int { return len(t.load().methods) } @@ -259,7 +259,7 @@ func (n *Named) expand(typMap map[string]*Named) *Named { // explicit is harmless: load is idempotent. n.load() var u Type - if n.check.validateTArgLen(n.instance.pos, n.tparams, n.targs) { + if n.check.validateTArgLen(n.instance.pos, n.tparams.Len(), n.targs.Len()) { if typMap == nil { if n.check != nil { typMap = n.check.typMap @@ -268,11 +268,11 @@ func (n *Named) expand(typMap map[string]*Named) *Named { // type-checking pass. In that case we won't have a pre-existing // typMap, but don't want to create a duplicate of the current instance // in the process of expansion. - h := instantiatedHash(n.orig, n.targs) + h := instantiatedHash(n.orig, n.targs.list()) typMap = map[string]*Named{h: n} } } - u = n.check.subst(n.instance.pos, n.orig.underlying, makeSubstMap(n.TParams().list(), n.targs), typMap) + u = n.check.subst(n.instance.pos, n.orig.underlying, makeSubstMap(n.TParams().list(), n.targs.list()), typMap) } else { u = Typ[Invalid] } diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index ed62743f6d..3ccafef990 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -305,8 +305,8 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { x.expand(nil) y.expand(nil) - xargs := x.TArgs() - yargs := y.TArgs() + xargs := x.TArgs().list() + yargs := y.TArgs().list() if len(xargs) != len(yargs) { return false diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go index 718d2d266a..5be369d843 100644 --- a/src/cmd/compile/internal/types2/sizeof_test.go +++ b/src/cmd/compile/internal/types2/sizeof_test.go @@ -31,7 +31,7 @@ func TestSizeof(t *testing.T) { {Interface{}, 40, 80}, {Map{}, 16, 32}, {Chan{}, 12, 24}, - {Named{}, 80, 152}, + {Named{}, 72, 136}, {TypeParam{}, 28, 48}, {term{}, 12, 24}, {top{}, 0, 0}, diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 467066cc69..918e5f3043 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -188,21 +188,21 @@ func (subst *subster) typ(typ Type) Type { } var newTArgs []Type - assert(len(t.targs) == t.TParams().Len()) + assert(t.targs.Len() == t.TParams().Len()) // already instantiated dump(">>> %s already instantiated", t) // For each (existing) type argument targ, determine if it needs // to be substituted; i.e., if it is or contains a type parameter // that has a type argument for it. - for i, targ := range t.targs { + for i, targ := range t.targs.list() { dump(">>> %d targ = %s", i, targ) new_targ := subst.typ(targ) if new_targ != targ { dump(">>> substituted %d targ %s => %s", i, targ, new_targ) if newTArgs == nil { newTArgs = make([]Type, t.TParams().Len()) - copy(newTArgs, t.targs) + copy(newTArgs, t.targs.list()) } newTArgs[i] = new_targ } @@ -230,7 +230,7 @@ func (subst *subster) typ(typ Type) Type { // It's ok to provide a nil *Checker because the newly created type // doesn't need to be (lazily) expanded; it's expanded below. named := (*Checker)(nil).newNamed(tname, t.orig, nil, t.tparams, t.methods) // t is loaded, so tparams and methods are available - named.targs = newTArgs + named.targs = NewTypeList(newTArgs) subst.typMap[h] = named t.expand(subst.typMap) // must happen after typMap update to avoid infinite recursion diff --git a/src/cmd/compile/internal/types2/typelists.go b/src/cmd/compile/internal/types2/typelists.go new file mode 100644 index 0000000000..3258a5e9f8 --- /dev/null +++ b/src/cmd/compile/internal/types2/typelists.go @@ -0,0 +1,69 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types2 + +// TParamList holds a list of type parameters. +type TParamList struct{ tparams []*TypeParam } + +// Len returns the number of type parameters in the list. +// It is safe to call on a nil receiver. +func (l *TParamList) Len() int { return len(l.list()) } + +// At returns the i'th type parameter in the list. +func (l *TParamList) At(i int) *TypeParam { return l.tparams[i] } + +// list is for internal use where we expect a []*TypeParam. +// TODO(rfindley): list should probably be eliminated: we can pass around a +// TParamList instead. +func (l *TParamList) list() []*TypeParam { + if l == nil { + return nil + } + return l.tparams +} + +// TypeList holds a list of types. +type TypeList struct{ types []Type } + +// NewTypeList returns a new TypeList with the types in list. +func NewTypeList(list []Type) *TypeList { + if len(list) == 0 { + return nil + } + return &TypeList{list} +} + +// Len returns the number of types in the list. +// It is safe to call on a nil receiver. +func (l *TypeList) Len() int { return len(l.list()) } + +// At returns the i'th type in the list. +func (l *TypeList) At(i int) Type { return l.types[i] } + +// list is for internal use where we expect a []Type. +// TODO(rfindley): list should probably be eliminated: we can pass around a +// TypeList instead. +func (l *TypeList) list() []Type { + if l == nil { + return nil + } + return l.types +} + +// ---------------------------------------------------------------------------- +// Implementation + +func bindTParams(list []*TypeParam) *TParamList { + if len(list) == 0 { + return nil + } + for i, typ := range list { + if typ.index >= 0 { + panic("type parameter bound more than once") + } + typ.index = i + } + return &TParamList{tparams: list} +} diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index 0d76dd1a6e..445337fee8 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -83,40 +83,6 @@ func (t *TypeParam) SetConstraint(bound Type) { func (t *TypeParam) Underlying() Type { return t } func (t *TypeParam) String() string { return TypeString(t, nil) } -// TParamList holds a list of type parameters bound to a type. -type TParamList struct{ tparams []*TypeParam } - -// Len returns the number of type parameters in the list. -// It is safe to call on a nil receiver. -func (tps *TParamList) Len() int { - return len(tps.list()) -} - -// At returns the i'th type parameter in the list. -func (tps *TParamList) At(i int) *TypeParam { - return tps.list()[i] -} - -func (tps *TParamList) list() []*TypeParam { - if tps == nil { - return nil - } - return tps.tparams -} - -func bindTParams(list []*TypeParam) *TParamList { - if len(list) == 0 { - return nil - } - for i, typ := range list { - if typ.index >= 0 { - panic("type parameter bound more than once") - } - typ.index = i - } - return &TParamList{tparams: list} -} - // ---------------------------------------------------------------------------- // Implementation diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 5759118c94..2c34d036db 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -202,7 +202,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { if t.targs != nil { // instantiated type buf.WriteByte('[') - writeTypeList(buf, t.targs, qf, visited) + writeTypeList(buf, t.targs.list(), qf, visited) buf.WriteByte(']') } else if t.TParams().Len() != 0 { // parameterized type diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index 58f5c17e5f..d4fbebc11b 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -429,13 +429,17 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { if y, ok := y.(*Named); ok { x.expand(nil) y.expand(nil) + + xargs := x.targs.list() + yargs := y.targs.list() + // TODO(gri) This is not always correct: two types may have the same names // in the same package if one of them is nested in a function. // Extremely unlikely but we need an always correct solution. if x.obj.pkg == y.obj.pkg && x.obj.name == y.obj.name { - assert(len(x.targs) == len(y.targs)) - for i, x := range x.targs { - if !u.nify(x, y.targs[i], p) { + assert(len(xargs) == len(yargs)) + for i, x := range xargs { + if !u.nify(x, yargs[i], p) { return false } } -- GitLab From e6798795ff523b9b5df2514bffd8d5ce743c312e Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 23 Aug 2021 21:04:56 -0700 Subject: [PATCH 0829/2500] cmd/compile/internal/types2: use TypeList in the Inferred struct This is a port of CL 343934 from go/types with the necessary adjustments to the compiler. Change-Id: I810144e6e2eb2bc8fa0d34dc206403c993cbbe7a Reviewed-on: https://go-review.googlesource.com/c/go/+/344616 Trust: Robert Griesemer Reviewed-by: Matthew Dempsky Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/expr.go | 16 ++++++++-------- src/cmd/compile/internal/noder/writer.go | 13 +++++++------ src/cmd/compile/internal/types2/api.go | 2 +- src/cmd/compile/internal/types2/api_test.go | 9 +++++---- src/cmd/compile/internal/types2/check.go | 2 +- 5 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index cb20d645aa..2f004ba1a2 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -116,12 +116,12 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { // The key for the Inferred map is the CallExpr (if inferring // types required the function arguments) or the IndexExpr below // (if types could be inferred without the function arguments). - if inferred, ok := g.info.Inferred[expr]; ok && len(inferred.TArgs) > 0 { + if inferred, ok := g.info.Inferred[expr]; ok && inferred.TArgs.Len() > 0 { // This is the case where inferring types required the // types of the function arguments. - targs := make([]ir.Node, len(inferred.TArgs)) - for i, targ := range inferred.TArgs { - targs[i] = ir.TypeNode(g.typ(targ)) + targs := make([]ir.Node, inferred.TArgs.Len()) + for i := range targs { + targs[i] = ir.TypeNode(g.typ(inferred.TArgs.At(i))) } if fun.Op() == ir.OFUNCINST { // Replace explicit type args with the full list that @@ -149,13 +149,13 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { case *syntax.IndexExpr: var targs []ir.Node - if inferred, ok := g.info.Inferred[expr]; ok && len(inferred.TArgs) > 0 { + if inferred, ok := g.info.Inferred[expr]; ok && inferred.TArgs.Len() > 0 { // This is the partial type inference case where the types // can be inferred from other type arguments without using // the types of the function arguments. - targs = make([]ir.Node, len(inferred.TArgs)) - for i, targ := range inferred.TArgs { - targs[i] = ir.TypeNode(g.typ(targ)) + targs = make([]ir.Node, inferred.TArgs.Len()) + for i := range targs { + targs[i] = ir.TypeNode(g.typ(inferred.TArgs.At(i))) } } else if _, ok := expr.Index.(*syntax.ListExpr); ok { targs = g.exprList(expr.Index) diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index a6bd8b2426..1405c77161 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -1212,12 +1212,12 @@ func (w *writer) expr(expr syntax.Expr) { if obj != nil { if isGlobal(obj) { w.code(exprName) - w.obj(obj, types2.NewTypeList(targs)) + w.obj(obj, targs) return } obj := obj.(*types2.Var) - assert(len(targs) == 0) + assert(targs.Len() == 0) w.code(exprLocal) w.useLocal(expr.Pos(), obj) @@ -1321,7 +1321,7 @@ func (w *writer) expr(expr syntax.Expr) { // As if w.expr(expr.Fun), but using inf.TArgs instead. w.code(exprName) - w.obj(obj, types2.NewTypeList(inf.TArgs)) + w.obj(obj, inf.TArgs) } else { w.expr(expr.Fun) } @@ -1770,7 +1770,7 @@ func isGlobal(obj types2.Object) bool { // lookupObj returns the object that expr refers to, if any. If expr // is an explicit instantiation of a generic object, then the type // arguments are returned as well. -func lookupObj(info *types2.Info, expr syntax.Expr) (obj types2.Object, targs []types2.Type) { +func lookupObj(info *types2.Info, expr syntax.Expr) (obj types2.Object, targs *types2.TypeList) { if index, ok := expr.(*syntax.IndexExpr); ok { if inf, ok := info.Inferred[index]; ok { targs = inf.TArgs @@ -1785,13 +1785,14 @@ func lookupObj(info *types2.Info, expr syntax.Expr) (obj types2.Object, targs [] } } - targs = make([]types2.Type, len(args)) + list := make([]types2.Type, len(args)) for i, arg := range args { tv, ok := info.Types[arg] assert(ok) assert(tv.IsType()) - targs[i] = tv.Type + list[i] = tv.Type } + targs = types2.NewTypeList(list) } expr = index.X diff --git a/src/cmd/compile/internal/types2/api.go b/src/cmd/compile/internal/types2/api.go index f268508825..b2938b84da 100644 --- a/src/cmd/compile/internal/types2/api.go +++ b/src/cmd/compile/internal/types2/api.go @@ -373,7 +373,7 @@ func (tv TypeAndValue) HasOk() bool { // Inferred reports the inferred type arguments and signature // for a parameterized function call that uses type inference. type Inferred struct { - TArgs []Type + TArgs *TypeList Sig *Signature } diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index 269b06f08a..039a6c0e5e 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -500,7 +500,7 @@ func TestInferredInfo(t *testing.T) { } // look for inferred type arguments and signature - var targs []Type + var targs *TypeList var sig *Signature for call, inf := range info.Inferred { var fun syntax.Expr @@ -524,11 +524,12 @@ func TestInferredInfo(t *testing.T) { } // check that type arguments are correct - if len(targs) != len(test.targs) { - t.Errorf("package %s: got %d type arguments; want %d", name, len(targs), len(test.targs)) + if targs.Len() != len(test.targs) { + t.Errorf("package %s: got %d type arguments; want %d", name, targs.Len(), len(test.targs)) continue } - for i, targ := range targs { + for i := 0; i < targs.Len(); i++ { + targ := targs.At(i) if got := targ.String(); got != test.targs[i] { t.Errorf("package %s, %d. type argument: got %s; want %s", name, i, got, test.targs[i]) continue diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go index 6bc965c497..4226b4de82 100644 --- a/src/cmd/compile/internal/types2/check.go +++ b/src/cmd/compile/internal/types2/check.go @@ -416,7 +416,7 @@ func (check *Checker) recordInferred(call syntax.Expr, targs []Type, sig *Signat assert(call != nil) assert(sig != nil) if m := check.Inferred; m != nil { - m[call] = Inferred{targs, sig} + m[call] = Inferred{NewTypeList(targs), sig} } } -- GitLab From daa55b21d1e7707ed251336c851841bb0eca3021 Mon Sep 17 00:00:00 2001 From: crazycomputer Date: Sun, 22 Aug 2021 17:26:20 +0800 Subject: [PATCH 0830/2500] cmd/link: guarantee "section .debug_gdb_scripts" is always "$GOROOT/src/runtime/runtime-gdb.py". to guarantee the "section .debug_gdb_scripts" is always "$GOROOT/src/runtime/runtime-gdb.py" , a check for package name is needed when search "runtime/proc.go". Fixes #47881 Change-Id: Ib471314ca1a6777f625b488e5ae3790457540ef9 Reviewed-on: https://go-review.googlesource.com/c/go/+/344229 Run-TryBot: Than McIntosh TryBot-Result: Go Bot Reviewed-by: Than McIntosh Trust: Michael Knyszek --- src/cmd/link/internal/ld/dwarf.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go index c53d2408cb..98ab248e13 100644 --- a/src/cmd/link/internal/ld/dwarf.go +++ b/src/cmd/link/internal/ld/dwarf.go @@ -1190,7 +1190,7 @@ func (d *dwctxt) writeDirFileTables(unit *sym.CompilationUnit, lsu *loader.Symbo // We can't use something that may be dead-code // eliminated from a binary here. proc.go contains // main and the scheduler, so it's not going anywhere. - if i := strings.Index(name, "runtime/proc.go"); i >= 0 { + if i := strings.Index(name, "runtime/proc.go"); i >= 0 && unit.Lib.Pkg == "runtime" { d.dwmu.Lock() if gdbscript == "" { k := strings.Index(name, "runtime/proc.go") -- GitLab From 4a9f0cec2918c855a23d5581c0b1da95eb11dd17 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 24 Aug 2021 00:32:30 -0700 Subject: [PATCH 0831/2500] cmd/compile: change irgen to generate exprs/stmts after decls processed This CL changes irgen to wait until all top-level declarations have been processed before constructing any expressions or statements that reference them. This is the same approach that typecheck used. Mechanically, it splits varDecl and funcDecl (the two top-level declarations that can generate/contain code) into a part that runs immediately for constructing the ir.ONAME, and then a separate task that runs later to handle the code. It also adds an exprStmtOK flag to indicate when it's actually safe to start constructing (non-trivial) expressions and statements. Fixes #47928. Change-Id: I51942af6823aa561d341e2ffc1142948da025fa2 Reviewed-on: https://go-review.googlesource.com/c/go/+/344649 Trust: Matthew Dempsky Trust: Dan Scales Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/decl.go | 122 +++++++++++++----------- src/cmd/compile/internal/noder/expr.go | 2 + src/cmd/compile/internal/noder/irgen.go | 27 +++++- src/cmd/compile/internal/noder/stmt.go | 6 +- test/fixedbugs/issue47928.go | 21 ++++ 5 files changed, 120 insertions(+), 58 deletions(-) create mode 100644 test/fixedbugs/issue47928.go diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go index ffcfc103a6..b23dd47600 100644 --- a/src/cmd/compile/internal/noder/decl.go +++ b/src/cmd/compile/internal/noder/decl.go @@ -18,26 +18,24 @@ import ( // TODO(mdempsky): Skip blank declarations? Probably only safe // for declarations without pragmas. -func (g *irgen) decls(decls []syntax.Decl) []ir.Node { - var res ir.Nodes +func (g *irgen) decls(res *ir.Nodes, decls []syntax.Decl) { for _, decl := range decls { switch decl := decl.(type) { case *syntax.ConstDecl: - g.constDecl(&res, decl) + g.constDecl(res, decl) case *syntax.FuncDecl: - g.funcDecl(&res, decl) + g.funcDecl(res, decl) case *syntax.TypeDecl: if ir.CurFunc == nil { continue // already handled in irgen.generate } - g.typeDecl(&res, decl) + g.typeDecl(res, decl) case *syntax.VarDecl: - g.varDecl(&res, decl) + g.varDecl(res, decl) default: g.unhandled("declaration", decl) } } - return res } func (g *irgen) importDecl(p *noder, decl *syntax.ImportDecl) { @@ -119,23 +117,25 @@ func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) { g.target.Inits = append(g.target.Inits, fn) } - if fn.Type().HasTParam() { - g.topFuncIsGeneric = true - } - g.funcBody(fn, decl.Recv, decl.Type, decl.Body) - g.topFuncIsGeneric = false - if fn.Type().HasTParam() && fn.Body != nil { - // Set pointers to the dcls/body of a generic function/method in - // the Inl struct, so it is marked for export, is available for - // stenciling, and works with Inline_Flood(). - fn.Inl = &ir.Inline{ - Cost: 1, - Dcl: fn.Dcl, - Body: fn.Body, + g.later(func() { + if fn.Type().HasTParam() { + g.topFuncIsGeneric = true + } + g.funcBody(fn, decl.Recv, decl.Type, decl.Body) + g.topFuncIsGeneric = false + if fn.Type().HasTParam() && fn.Body != nil { + // Set pointers to the dcls/body of a generic function/method in + // the Inl struct, so it is marked for export, is available for + // stenciling, and works with Inline_Flood(). + fn.Inl = &ir.Inline{ + Cost: 1, + Dcl: fn.Dcl, + Body: fn.Body, + } } - } - out.Append(fn) + out.Append(fn) + }) } func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) { @@ -218,7 +218,6 @@ func (g *irgen) varDecl(out *ir.Nodes, decl *syntax.VarDecl) { for i, name := range decl.NameList { names[i], _ = g.def(name) } - values := g.exprList(decl.Values) if decl.Pragma != nil { pragma := decl.Pragma.(*pragmas) @@ -227,44 +226,57 @@ func (g *irgen) varDecl(out *ir.Nodes, decl *syntax.VarDecl) { g.reportUnused(pragma) } - var as2 *ir.AssignListStmt - if len(values) != 0 && len(names) != len(values) { - as2 = ir.NewAssignListStmt(pos, ir.OAS2, make([]ir.Node, len(names)), values) - } + do := func() { + values := g.exprList(decl.Values) - for i, name := range names { - if ir.CurFunc != nil { - out.Append(ir.NewDecl(pos, ir.ODCL, name)) + var as2 *ir.AssignListStmt + if len(values) != 0 && len(names) != len(values) { + as2 = ir.NewAssignListStmt(pos, ir.OAS2, make([]ir.Node, len(names)), values) } - if as2 != nil { - as2.Lhs[i] = name - name.Defn = as2 - } else { - as := ir.NewAssignStmt(pos, name, nil) - if len(values) != 0 { - as.Y = values[i] - name.Defn = as - } else if ir.CurFunc == nil { - name.Defn = as - } - lhs := []ir.Node{as.X} - rhs := []ir.Node{} - if as.Y != nil { - rhs = []ir.Node{as.Y} + + for i, name := range names { + if ir.CurFunc != nil { + out.Append(ir.NewDecl(pos, ir.ODCL, name)) } - transformAssign(as, lhs, rhs) - as.X = lhs[0] - if as.Y != nil { - as.Y = rhs[0] + if as2 != nil { + as2.Lhs[i] = name + name.Defn = as2 + } else { + as := ir.NewAssignStmt(pos, name, nil) + if len(values) != 0 { + as.Y = values[i] + name.Defn = as + } else if ir.CurFunc == nil { + name.Defn = as + } + lhs := []ir.Node{as.X} + rhs := []ir.Node{} + if as.Y != nil { + rhs = []ir.Node{as.Y} + } + transformAssign(as, lhs, rhs) + as.X = lhs[0] + if as.Y != nil { + as.Y = rhs[0] + } + as.SetTypecheck(1) + out.Append(as) } - as.SetTypecheck(1) - out.Append(as) + } + if as2 != nil { + transformAssign(as2, as2.Lhs, as2.Rhs) + as2.SetTypecheck(1) + out.Append(as2) } } - if as2 != nil { - transformAssign(as2, as2.Lhs, as2.Rhs) - as2.SetTypecheck(1) - out.Append(as2) + + // If we're within a function, we need to process the assignment + // part of the variable declaration right away. Otherwise, we leave + // it to be handled after all top-level declarations are processed. + if ir.CurFunc != nil { + do() + } else { + g.later(do) } } diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 2f004ba1a2..58637dca39 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -50,6 +50,8 @@ func (g *irgen) expr(expr syntax.Expr) ir.Node { base.FatalfAt(g.pos(expr), "unrecognized type-checker result") } + base.Assert(g.exprStmtOK) + // The gc backend expects all expressions to have a concrete type, and // types2 mostly satisfies this expectation already. But there are a few // cases where the Go spec doesn't require converting to concrete type, diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index 7bc8a6bcc3..29882eb773 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -141,6 +141,14 @@ type irgen struct { typs map[types2.Type]*types.Type marker dwarfgen.ScopeMarker + // laterFuncs records tasks that need to run after all declarations + // are processed. + laterFuncs []func() + + // exprStmtOK indicates whether it's safe to generate expressions or + // statements yet. + exprStmtOK bool + // Fully-instantiated generic types whose methods should be instantiated instTypeList []*types.Type @@ -165,6 +173,10 @@ type irgen struct { topFuncIsGeneric bool } +func (g *irgen) later(fn func()) { + g.laterFuncs = append(g.laterFuncs, fn) +} + type delayInfo struct { gf *ir.Name targs []*types.Type @@ -184,7 +196,7 @@ func (g *irgen) generate(noders []*noder) { // At this point, types2 has already handled name resolution and // type checking. We just need to map from its object and type // representations to those currently used by the rest of the - // compiler. This happens mostly in 3 passes. + // compiler. This happens in a few passes. // 1. Process all import declarations. We use the compiler's own // importer for this, rather than types2's gcimporter-derived one, @@ -233,7 +245,16 @@ Outer: // 3. Process all remaining declarations. for _, declList := range declLists { - g.target.Decls = append(g.target.Decls, g.decls(declList)...) + g.decls((*ir.Nodes)(&g.target.Decls), declList) + } + g.exprStmtOK = true + + // 4. Run any "later" tasks. Avoid using 'range' so that tasks can + // recursively queue further tasks. (Not currently utilized though.) + for len(g.laterFuncs) > 0 { + fn := g.laterFuncs[0] + g.laterFuncs = g.laterFuncs[1:] + fn() } if base.Flag.W > 1 { @@ -275,6 +296,8 @@ Outer: } } g.target.Decls = g.target.Decls[:j] + + base.Assertf(len(g.laterFuncs) == 0, "still have %d later funcs", len(g.laterFuncs)) } func (g *irgen) unhandled(what string, p poser) { diff --git a/src/cmd/compile/internal/noder/stmt.go b/src/cmd/compile/internal/noder/stmt.go index 1949f56095..fc1f5836ff 100644 --- a/src/cmd/compile/internal/noder/stmt.go +++ b/src/cmd/compile/internal/noder/stmt.go @@ -5,6 +5,7 @@ package noder import ( + "cmd/compile/internal/base" "cmd/compile/internal/ir" "cmd/compile/internal/syntax" "cmd/compile/internal/typecheck" @@ -27,6 +28,7 @@ func (g *irgen) stmts(stmts []syntax.Stmt) []ir.Node { } func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { + base.Assert(g.exprStmtOK) switch stmt := stmt.(type) { case nil, *syntax.EmptyStmt: return nil @@ -48,7 +50,9 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { n.SetTypecheck(1) return n case *syntax.DeclStmt: - return ir.NewBlockStmt(g.pos(stmt), g.decls(stmt.DeclList)) + n := ir.NewBlockStmt(g.pos(stmt), nil) + g.decls(&n.List, stmt.DeclList) + return n case *syntax.AssignStmt: if stmt.Op != 0 && stmt.Op != syntax.Def { diff --git a/test/fixedbugs/issue47928.go b/test/fixedbugs/issue47928.go new file mode 100644 index 0000000000..3bc291dd3f --- /dev/null +++ b/test/fixedbugs/issue47928.go @@ -0,0 +1,21 @@ +// run -goexperiment fieldtrack + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func main() { + var i interface{} = new(T) + if _, ok := i.(interface{ Bad() }); ok { + panic("FAIL") + } +} + +type T struct{ U } + +type U struct{} + +//go:nointerface +func (*U) Bad() {} -- GitLab From 5b64381155a779d5392f015e08111906c6e35738 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sun, 22 Aug 2021 08:58:24 -0700 Subject: [PATCH 0832/2500] cmd/compile: fix naming of types inside instantiations Issues 47713 and 47877 were both due to problems with the names used for instantiated functions/methods, which must be in sync with the names used by types2. - Switched to using NameString() for writing out type arguments in instantiation names. This ensures that we are always adding the package to type names even for the local package. Previously, we were explicitly adding the package name for local packages, but that doesn't handle the case when the local type is embedded inside a pointer or slice type. By switching to NameString(), we fix #47713. - types1 and types2 write out 'interface {' differently (vs. 'interface{') and we were already handling that. But we needed to add similar code to handle 'struct {' vs 'struct{'. This fixes issue #47877. While fixing these bugs, I also moved some duplicated code (which include some of the changes above) into a common function addTargs(). I also moved InstType() name to subr.go, and renamed: MakeInstName -> MakeFuncInstSym and MakeDictName -> MakeDictSym. Also removed a couple of ".inst..inst." prefix checks which are irrelvant now, since we don't add ".inst." anymore to function instantiations. Fixes #47713 Fixes #47877 Fixes #47922 Change-Id: I19e9a073451f3ababd8ec31b6608cd79ba8cba36 Reviewed-on: https://go-review.googlesource.com/c/go/+/344613 Trust: Dan Scales Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 4 +- .../compile/internal/reflectdata/reflect.go | 8 +-- src/cmd/compile/internal/typecheck/iimport.go | 29 +-------- src/cmd/compile/internal/typecheck/subr.go | 59 +++++++++++-------- test/typeparam/issue47713.go | 52 ++++++++++++++++ test/typeparam/issue47713.out | 1 + test/typeparam/issue47877.go | 23 ++++++++ 7 files changed, 115 insertions(+), 61 deletions(-) create mode 100644 test/typeparam/issue47713.go create mode 100644 test/typeparam/issue47713.out create mode 100644 test/typeparam/issue47877.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 570dec9990..602e88c102 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -590,7 +590,7 @@ func (g *irgen) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMeth shapes = s1 } - sym := typecheck.MakeInstName(nameNode.Sym(), shapes, isMeth) + sym := typecheck.MakeFuncInstSym(nameNode.Sym(), shapes, isMeth) info := g.instInfoMap[sym] if info == nil { // If instantiation doesn't exist yet, create it and add @@ -1372,7 +1372,7 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) } // Get a symbol representing the dictionary. - sym := typecheck.MakeDictName(gf.Sym(), targs, isMeth) + sym := typecheck.MakeDictSym(gf.Sym(), targs, isMeth) // Initialize the dictionary, if we haven't yet already. lsym := sym.Linksym() diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index a95c76ff26..9b9efe04a2 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -1897,10 +1897,6 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy } else { targs = rcvr.RParams() } - if strings.HasPrefix(ir.MethodSym(orig, method.Sym).Name, ".inst.") { - fmt.Printf("%s\n", ir.MethodSym(orig, method.Sym).Name) - panic("multiple .inst.") - } // The wrapper for an auto-generated pointer/non-pointer // receiver method should share the same dictionary as the // corresponding original (user-written) method. @@ -1929,7 +1925,7 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy } targs = targs2 - sym := typecheck.MakeInstName(ir.MethodSym(methodrcvr, method.Sym), targs, true) + sym := typecheck.MakeFuncInstSym(ir.MethodSym(methodrcvr, method.Sym), targs, true) if sym.Def == nil { // Currently we make sure that we have all the instantiations // we need by generating them all in ../noder/stencil.go:instantiateMethods @@ -2040,7 +2036,7 @@ func getDictionary(gf *types.Sym, targs []*types.Type) ir.Node { } } - sym := typecheck.MakeDictName(gf, targs, true) + sym := typecheck.MakeDictSym(gf, targs, true) // Initialize the dictionary, if we haven't yet already. if lsym := sym.Linksym(); len(lsym.P) == 0 { diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 2e3fdbc1bc..a1a3ac3e8a 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -8,7 +8,6 @@ package typecheck import ( - "bytes" "encoding/binary" "fmt" "go/constant" @@ -1751,32 +1750,6 @@ func builtinCall(pos src.XPos, op ir.Op) *ir.CallExpr { return ir.NewCallExpr(pos, ir.OCALL, ir.NewIdent(base.Pos, types.BuiltinPkg.Lookup(ir.OpNames[op])), nil) } -// InstTypeName creates a name for an instantiated type, based on the name of the -// generic type and the type args. -func InstTypeName(name string, targs []*types.Type) string { - b := bytes.NewBufferString(name) - b.WriteByte('[') - for i, targ := range targs { - if i > 0 { - b.WriteByte(',') - } - // WriteString() does not include the package name for the local - // package, but we want it to make sure type arguments (including - // type params) are uniquely specified. - if targ.Sym() != nil && targ.Sym().Pkg == types.LocalPkg { - b.WriteString(targ.Sym().Pkg.Name) - b.WriteByte('.') - } - // types1 uses "interface {" and types2 uses "interface{" - convert - // to consistent types2 format. - tstring := targ.String() - tstring = strings.Replace(tstring, "interface {", "interface{", -1) - b.WriteString(tstring) - } - b.WriteByte(']') - return b.String() -} - // NewIncompleteNamedType returns a TFORW type t with name specified by sym, such // that t.nod and sym.Def are set correctly. func NewIncompleteNamedType(pos src.XPos, sym *types.Sym) *types.Type { @@ -1879,7 +1852,7 @@ func substInstType(t *types.Type, baseType *types.Type, targs []*types.Type) { } t2 := msubst.Typ(f.Type) oldsym := f.Nname.Sym() - newsym := MakeInstName(oldsym, targs, true) + newsym := MakeFuncInstSym(oldsym, targs, true) var nname *ir.Name if newsym.Def != nil { nname = newsym.Def.(*ir.Name) diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index c7a3718b31..7ae10ef406 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -900,6 +900,35 @@ func TypesOf(x []ir.Node) []*types.Type { return r } +// addTargs writes out the targs to buffer b as a comma-separated list enclosed by +// brackets. +func addTargs(b *bytes.Buffer, targs []*types.Type) { + b.WriteByte('[') + for i, targ := range targs { + if i > 0 { + b.WriteByte(',') + } + // Use NameString(), which includes the package name for the local + // package, to make sure that type arguments (including type params), + // are uniquely specified. + tstring := targ.NameString() + // types1 uses "interface {" and types2 uses "interface{" - convert + // to consistent types2 format. Same for "struct {" + tstring = strings.Replace(tstring, "interface {", "interface{", -1) + tstring = strings.Replace(tstring, "struct {", "struct{", -1) + b.WriteString(tstring) + } + b.WriteString("]") +} + +// InstTypeName creates a name for an instantiated type, based on the name of the +// generic type and the type args. +func InstTypeName(name string, targs []*types.Type) string { + b := bytes.NewBufferString(name) + addTargs(b, targs) + return b.String() +} + // makeInstName1 returns the name of the generic function instantiated with the // given types, which can have type params or shapes, or be concrete types. name is // the name of the generic function or method. @@ -912,36 +941,16 @@ func makeInstName1(name string, targs []*types.Type, hasBrackets bool) string { } else { b.WriteString(name) } - b.WriteString("[") - for i, targ := range targs { - if i > 0 { - b.WriteString(",") - } - // WriteString() does not include the package name for the local - // package, but we want it for uniqueness. - if targ.Sym() != nil && targ.Sym().Pkg == types.LocalPkg { - b.WriteString(targ.Sym().Pkg.Name) - b.WriteByte('.') - } - // types1 uses "interface {" and types2 uses "interface{" - convert - // to consistent types2 format. - tstring := targ.String() - tstring = strings.Replace(tstring, "interface {", "interface{", -1) - b.WriteString(tstring) - } - b.WriteString("]") + addTargs(b, targs) if i >= 0 { i2 := strings.LastIndex(name[i:], "]") assert(i2 >= 0) b.WriteString(name[i+i2+1:]) } - if strings.HasPrefix(b.String(), ".inst..inst.") { - panic(fmt.Sprintf("multiple .inst. prefix in %s", b.String())) - } return b.String() } -// MakeInstName makes the unique name for a stenciled generic function or method, +// MakeFuncInstSym makes the unique sym for a stenciled generic function or method, // based on the name of the function fnsym and the targs. It replaces any // existing bracket type list in the name. MakeInstName asserts that fnsym has // brackets in its name if and only if hasBrackets is true. @@ -953,11 +962,11 @@ func makeInstName1(name string, targs []*types.Type, hasBrackets bool) string { // // The standard naming is something like: 'genFn[int,bool]' for functions and // '(*genType[int,bool]).methodName' for methods -func MakeInstName(gf *types.Sym, targs []*types.Type, hasBrackets bool) *types.Sym { +func MakeFuncInstSym(gf *types.Sym, targs []*types.Type, hasBrackets bool) *types.Sym { return gf.Pkg.Lookup(makeInstName1(gf.Name, targs, hasBrackets)) } -func MakeDictName(gf *types.Sym, targs []*types.Type, hasBrackets bool) *types.Sym { +func MakeDictSym(gf *types.Sym, targs []*types.Type, hasBrackets bool) *types.Sym { for _, targ := range targs { if targ.HasTParam() { fmt.Printf("FUNCTION %s\n", gf.Name) @@ -1222,7 +1231,7 @@ func (ts *Tsubster) Typ(t *types.Type) *types.Type { for i, f := range t.Methods().Slice() { t2 := ts.Typ(f.Type) oldsym := f.Nname.Sym() - newsym := MakeInstName(oldsym, ts.Targs, true) + newsym := MakeFuncInstSym(oldsym, ts.Targs, true) var nname *ir.Name if newsym.Def != nil { nname = newsym.Def.(*ir.Name) diff --git a/test/typeparam/issue47713.go b/test/typeparam/issue47713.go new file mode 100644 index 0000000000..a38eea19eb --- /dev/null +++ b/test/typeparam/issue47713.go @@ -0,0 +1,52 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "encoding" + "fmt" +) + +type Seralizable interface { + encoding.BinaryMarshaler + encoding.BinaryUnmarshaler +} + +type SerDeString string + +func (s *SerDeString) UnmarshalBinary(in []byte) error { + *s = SerDeString(in) + return nil +} + +func (s SerDeString) MarshalBinary() ([]byte, error) { + return []byte(s), nil +} + + +type GenericSerializable[T Seralizable] struct { + Key string + Value T +} + +func (g GenericSerializable[T]) Send() { + out, err := g.Value.MarshalBinary() + if err != nil { + panic("bad") + } + var newval SerDeString + newval.UnmarshalBinary(out) + fmt.Printf("Sent %s\n", newval) +} + +func main() { + val := SerDeString("asdf") + x := GenericSerializable[*SerDeString]{ + Value: &val, + } + x.Send() +} diff --git a/test/typeparam/issue47713.out b/test/typeparam/issue47713.out new file mode 100644 index 0000000000..a6e77197d8 --- /dev/null +++ b/test/typeparam/issue47713.out @@ -0,0 +1 @@ +Sent asdf diff --git a/test/typeparam/issue47877.go b/test/typeparam/issue47877.go new file mode 100644 index 0000000000..0a834590dd --- /dev/null +++ b/test/typeparam/issue47877.go @@ -0,0 +1,23 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type Map[K comparable, V any] struct { + m map[K]V +} + +func NewMap[K comparable, V any]() Map[K, V] { + return Map[K, V]{m: map[K]V{}} +} + +func (m Map[K, V]) Get(key K) V { + return m.m[key] +} + +func main() { + _ = NewMap[int, struct{}]() +} -- GitLab From c2f96e686fe9383711d23aea95a34a280fdd0e49 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 24 Aug 2021 10:21:16 -0700 Subject: [PATCH 0833/2500] cmd/compile: mark ODYNAMICDOTTYPE as an expression that can panic Fixes #47924 Change-Id: I4325b3c4ed9d369d9ea778478285436e1b2ab08a Reviewed-on: https://go-review.googlesource.com/c/go/+/344571 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/walk/walk.go | 2 +- test/typeparam/issue47924.go | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 test/typeparam/issue47924.go diff --git a/src/cmd/compile/internal/walk/walk.go b/src/cmd/compile/internal/walk/walk.go index 6551fe7a64..a9bbc9a54f 100644 --- a/src/cmd/compile/internal/walk/walk.go +++ b/src/cmd/compile/internal/walk/walk.go @@ -312,7 +312,7 @@ func mayCall(n ir.Node) bool { return true case ir.OINDEX, ir.OSLICE, ir.OSLICEARR, ir.OSLICE3, ir.OSLICE3ARR, ir.OSLICESTR, - ir.ODEREF, ir.ODOTPTR, ir.ODOTTYPE, ir.ODIV, ir.OMOD, ir.OSLICE2ARRPTR: + ir.ODEREF, ir.ODOTPTR, ir.ODOTTYPE, ir.ODYNAMICDOTTYPE, ir.ODIV, ir.OMOD, ir.OSLICE2ARRPTR: // These ops might panic, make sure they are done // before we start marshaling args for a call. See issue 16760. return true diff --git a/test/typeparam/issue47924.go b/test/typeparam/issue47924.go new file mode 100644 index 0000000000..1d1bab3bf9 --- /dev/null +++ b/test/typeparam/issue47924.go @@ -0,0 +1,15 @@ +// compile -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type Cache[K any] struct{} + +func (c Cache[K]) foo(x interface{}, f func(K) bool) { + f(x.(K)) +} + +var _ Cache[int] -- GitLab From 5d863f89fed8f0580294ada88f92f72f361c598f Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 24 Aug 2021 14:30:24 -0700 Subject: [PATCH 0834/2500] cmd/compile: simplify bad conversion check Now that we're using OCONVIDATA(x) everywhere we formerly used OIDATA(OCONVIFACE(x)), there should be no OCONVIFACE operations that take a shape type. Change-Id: I4fb056456c60481c6dfe7bc111fca6223567e6a8 Reviewed-on: https://go-review.googlesource.com/c/go/+/344577 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 602e88c102..18a0506036 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -732,21 +732,15 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes []*typ g.instTypeList = append(g.instTypeList, subst.ts.InstTypeList...) if doubleCheck { - okConvs := map[ir.Node]bool{} ir.Visit(newf, func(n ir.Node) { - if n.Op() == ir.OIDATA { - // IDATA(OCONVIFACE(x)) is ok, as we don't use the type of x. - // TODO: use some other op besides OCONVIFACE. ONEW might work - // (with appropriate direct vs. indirect interface cases). - okConvs[n.(*ir.UnaryExpr).X] = true + if n.Op() != ir.OCONVIFACE { + return } - if n.Op() == ir.OCONVIFACE && !okConvs[n] { - c := n.(*ir.ConvExpr) - if c.X.Type().HasShape() { - ir.Dump("BAD FUNCTION", newf) - ir.Dump("BAD CONVERSION", c) - base.Fatalf("converting shape type to interface") - } + c := n.(*ir.ConvExpr) + if c.X.Type().HasShape() { + ir.Dump("BAD FUNCTION", newf) + ir.Dump("BAD CONVERSION", c) + base.Fatalf("converting shape type to interface") } }) } -- GitLab From 54cdef1f101a7a15fa6412fbedf8b009a1f725a1 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 17 May 2021 12:31:11 -0700 Subject: [PATCH 0835/2500] reflect: add MapIter.SetKey and MapIter.SetValue These augment the existing MapIter.Key and MapIter.Value methods. The existing methods return new Values. Constructing these new Values often requires allocating. These methods allow the caller to bring their own storage. The naming is somewhat unfortunate, in that the spec uses the word "element" instead of "value", as do the reflect.Type methods. In a vacuum, MapIter.SetElem would be preferable. However, matching the existing methods is more important. Fixes #32424 Fixes #46131 Change-Id: I19c4d95c432f63dfe52cde96d2125abd021f24fa Reviewed-on: https://go-review.googlesource.com/c/go/+/320929 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder Reviewed-by: Keith Randall --- src/reflect/all_test.go | 41 +++++++++++++++++++++++++++ src/reflect/value.go | 62 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 99 insertions(+), 4 deletions(-) diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index df79f05807..40ac6a95fa 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -336,6 +336,47 @@ func TestSetValue(t *testing.T) { } } +func TestMapIterSet(t *testing.T) { + m := make(map[string]interface{}, len(valueTests)) + for _, tt := range valueTests { + m[tt.s] = tt.i + } + v := ValueOf(m) + + k := New(v.Type().Key()).Elem() + e := New(v.Type().Elem()).Elem() + + iter := v.MapRange() + for iter.Next() { + iter.SetKey(k) + iter.SetValue(e) + want := m[k.String()] + got := e.Interface() + if got != want { + t.Errorf("%q: want (%T) %v, got (%T) %v", k.String(), want, want, got, got) + } + if setkey, key := valueToString(k), valueToString(iter.Key()); setkey != key { + t.Errorf("MapIter.Key() = %q, MapIter.SetKey() = %q", key, setkey) + } + if setval, val := valueToString(e), valueToString(iter.Value()); setval != val { + t.Errorf("MapIter.Value() = %q, MapIter.SetValue() = %q", val, setval) + } + } + + got := int(testing.AllocsPerRun(10, func() { + iter := v.MapRange() + for iter.Next() { + iter.SetKey(k) + iter.SetValue(e) + } + })) + // Making a *MapIter and making an hiter both allocate. + // Those should be the only two allocations. + if got != 2 { + t.Errorf("wanted 2 allocs, got %d", got) + } +} + func TestCanSetField(t *testing.T) { type embed struct{ x, X int } type Embed struct{ x, X int } diff --git a/src/reflect/value.go b/src/reflect/value.go index de01f13825..a8274cc871 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -1578,13 +1578,40 @@ func (it *MapIter) Key() Value { if it.it == nil { panic("MapIter.Key called before Next") } - if mapiterkey(it.it) == nil { + iterkey := mapiterkey(it.it) + if iterkey == nil { panic("MapIter.Key called on exhausted iterator") } t := (*mapType)(unsafe.Pointer(it.m.typ)) ktype := t.key - return copyVal(ktype, it.m.flag.ro()|flag(ktype.Kind()), mapiterkey(it.it)) + return copyVal(ktype, it.m.flag.ro()|flag(ktype.Kind()), iterkey) +} + +// SetKey assigns dst to the key of the iterator's current map entry. +// It is equivalent to dst.Set(it.Key()), but it avoids allocating a new Value. +// As in Go, the key must be assignable to dst's type. +func (it *MapIter) SetKey(dst Value) { + if it.it == nil { + panic("MapIter.SetKey called before Next") + } + iterkey := mapiterkey(it.it) + if iterkey == nil { + panic("MapIter.SetKey called on exhausted iterator") + } + + dst.mustBeAssignable() + var target unsafe.Pointer + if dst.kind() == Interface { + target = dst.ptr + } + + t := (*mapType)(unsafe.Pointer(it.m.typ)) + ktype := t.key + + key := Value{ktype, iterkey, it.m.flag | flag(ktype.Kind())} + key = key.assignTo("reflect.MapIter.SetKey", dst.typ, target) + typedmemmove(dst.typ, dst.ptr, key.ptr) } // Value returns the value of the iterator's current map entry. @@ -1592,13 +1619,40 @@ func (it *MapIter) Value() Value { if it.it == nil { panic("MapIter.Value called before Next") } - if mapiterkey(it.it) == nil { + iterelem := mapiterelem(it.it) + if iterelem == nil { panic("MapIter.Value called on exhausted iterator") } t := (*mapType)(unsafe.Pointer(it.m.typ)) vtype := t.elem - return copyVal(vtype, it.m.flag.ro()|flag(vtype.Kind()), mapiterelem(it.it)) + return copyVal(vtype, it.m.flag.ro()|flag(vtype.Kind()), iterelem) +} + +// SetValue assigns dst to the value of the iterator's current map entry. +// It is equivalent to dst.Set(it.Value()), but it avoids allocating a new Value. +// As in Go, the value must be assignable to dst's type. +func (it *MapIter) SetValue(dst Value) { + if it.it == nil { + panic("MapIter.SetValue called before Next") + } + iterelem := mapiterelem(it.it) + if iterelem == nil { + panic("MapIter.SetValue called on exhausted iterator") + } + + dst.mustBeAssignable() + var target unsafe.Pointer + if dst.kind() == Interface { + target = dst.ptr + } + + t := (*mapType)(unsafe.Pointer(it.m.typ)) + vtype := t.elem + + elem := Value{vtype, iterelem, it.m.flag | flag(vtype.Kind())} + elem = elem.assignTo("reflect.MapIter.SetValue", dst.typ, target) + typedmemmove(dst.typ, dst.ptr, elem.ptr) } // Next advances the map iterator and reports whether there is another -- GitLab From de1c934b9709728b15cc821a055155ee13e1d0ab Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Fri, 20 Aug 2021 11:38:54 +0700 Subject: [PATCH 0836/2500] cmd/compile: fix checkptr false positive for (*[Big]T)(ptr)[:n:n] pattern The checkptr instrumentation is currently inserted before slice operation has validated that n <= Big. So instead of panic, checkptr have false positive throws. To fix this, just insert the checkptr instrumentation after the bound checking during SSA generation. Fixes #46938 Change-Id: I9dbf84441c711842ccc883f3654ca8766ac696d8 Reviewed-on: https://go-review.googlesource.com/c/go/+/343972 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/expr.go | 9 ++++---- src/cmd/compile/internal/ssagen/ssa.go | 3 +++ src/cmd/compile/internal/walk/convert.go | 13 +++++++++-- src/cmd/compile/internal/walk/expr.go | 2 +- test/fixedbugs/issue46938.go | 29 ++++++++++++++++++++++++ 5 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 test/fixedbugs/issue46938.go diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index f526d987a7..41de6bd61b 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -570,10 +570,11 @@ func (*SelectorExpr) CanBeNtype() {} // A SliceExpr is a slice expression X[Low:High] or X[Low:High:Max]. type SliceExpr struct { miniExpr - X Node - Low Node - High Node - Max Node + X Node + Low Node + High Node + Max Node + CheckPtrCall *CallExpr } func NewSliceExpr(pos src.XPos, op Op, x, low, high, max Node) *SliceExpr { diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 39d3b206ac..0a48f6b704 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -3090,6 +3090,9 @@ func (s *state) expr(n ir.Node) *ssa.Value { k = s.expr(n.Max) } p, l, c := s.slice(v, i, j, k, n.Bounded()) + if n.CheckPtrCall != nil { + s.stmt(n.CheckPtrCall) + } return s.newValue3(ssa.OpSliceMake, n.Type(), p, l, c) case ir.OSLICESTR: diff --git a/src/cmd/compile/internal/walk/convert.go b/src/cmd/compile/internal/walk/convert.go index 27a07ce4b6..f724ca7cae 100644 --- a/src/cmd/compile/internal/walk/convert.go +++ b/src/cmd/compile/internal/walk/convert.go @@ -413,11 +413,15 @@ func byteindex(n ir.Node) ir.Node { return n } -func walkCheckPtrAlignment(n *ir.ConvExpr, init *ir.Nodes, count ir.Node) ir.Node { +func walkCheckPtrAlignment(n *ir.ConvExpr, init *ir.Nodes, se *ir.SliceExpr) ir.Node { if !n.Type().IsPtr() { base.Fatalf("expected pointer type: %v", n.Type()) } elem := n.Type().Elem() + var count ir.Node + if se != nil { + count = se.Max + } if count != nil { if !elem.IsArray() { base.Fatalf("expected array type: %v", elem) @@ -435,7 +439,12 @@ func walkCheckPtrAlignment(n *ir.ConvExpr, init *ir.Nodes, count ir.Node) ir.Nod } n.X = cheapExpr(n.X, init) - init.Append(mkcall("checkptrAlignment", nil, init, typecheck.ConvNop(n.X, types.Types[types.TUNSAFEPTR]), reflectdata.TypePtr(elem), typecheck.Conv(count, types.Types[types.TUINTPTR]))) + checkPtrCall := mkcall("checkptrAlignment", nil, init, typecheck.ConvNop(n.X, types.Types[types.TUNSAFEPTR]), reflectdata.TypePtr(elem), typecheck.Conv(count, types.Types[types.TUINTPTR])) + if se != nil { + se.CheckPtrCall = checkPtrCall + } else { + init.Append(checkPtrCall) + } return n } diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go index 26e225440a..c04998137b 100644 --- a/src/cmd/compile/internal/walk/expr.go +++ b/src/cmd/compile/internal/walk/expr.go @@ -824,7 +824,7 @@ func walkSlice(n *ir.SliceExpr, init *ir.Nodes) ir.Node { n.High = walkExpr(n.High, init) n.Max = walkExpr(n.Max, init) if checkSlice { - n.X = walkCheckPtrAlignment(n.X.(*ir.ConvExpr), init, n.Max) + n.X = walkCheckPtrAlignment(n.X.(*ir.ConvExpr), init, n) } if n.Op().IsSlice3() { diff --git a/test/fixedbugs/issue46938.go b/test/fixedbugs/issue46938.go new file mode 100644 index 0000000000..87532d4769 --- /dev/null +++ b/test/fixedbugs/issue46938.go @@ -0,0 +1,29 @@ +// run -gcflags="-d=checkptr" + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "strings" + "unsafe" +) + +func main() { + defer func() { + err := recover() + if err == nil { + panic("expected panic") + } + if got := err.(error).Error(); !strings.Contains(got, "slice bounds out of range") { + panic("expected panic slice out of bound, got " + got) + } + }() + s := make([]int64, 100) + p := unsafe.Pointer(&s[0]) + n := 1000 + + _ = (*[10]int64)(p)[:n:n] +} -- GitLab From 41b99dab0f263bd3fe5c2592f1c40735dcaa016a Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Tue, 22 Jun 2021 20:26:31 -0700 Subject: [PATCH 0837/2500] os/user: don't skip TestLookupGroup if supported CL 37664 implemented this functionality, yet the tests were skipped. Introduce and use additional variable groupListImplemented to distinguish between these cases and enable TestLookupGroup for supported configurations (which looks like all but plan9). Change-Id: Iabaa7f08b4551dc67e67bdb6e715f15bb20d6218 Signed-off-by: Kir Kolyshkin Reviewed-on: https://go-review.googlesource.com/c/go/+/330751 Reviewed-by: Ian Lance Taylor Reviewed-by: Tobias Klauser --- src/os/user/lookup_plan9.go | 1 + src/os/user/lookup_stubs.go | 2 +- src/os/user/lookup_unix.go | 8 +++++--- src/os/user/user.go | 7 +++++-- src/os/user/user_test.go | 9 ++++++++- 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/os/user/lookup_plan9.go b/src/os/user/lookup_plan9.go index 51caf55935..07939363e7 100644 --- a/src/os/user/lookup_plan9.go +++ b/src/os/user/lookup_plan9.go @@ -20,6 +20,7 @@ const ( func init() { userImplemented = false groupImplemented = false + groupListImplemented = false } func current() (*User, error) { diff --git a/src/os/user/lookup_stubs.go b/src/os/user/lookup_stubs.go index c975a11964..d8e3d4866a 100644 --- a/src/os/user/lookup_stubs.go +++ b/src/os/user/lookup_stubs.go @@ -16,7 +16,7 @@ import ( ) func init() { - groupImplemented = false + groupListImplemented = false } func current() (*User, error) { diff --git a/src/os/user/lookup_unix.go b/src/os/user/lookup_unix.go index 97c611fad4..dffea4a885 100644 --- a/src/os/user/lookup_unix.go +++ b/src/os/user/lookup_unix.go @@ -18,13 +18,15 @@ import ( "strings" ) -const groupFile = "/etc/group" -const userFile = "/etc/passwd" +const ( + groupFile = "/etc/group" + userFile = "/etc/passwd" +) var colon = []byte{':'} func init() { - groupImplemented = false + groupListImplemented = false } // lineFunc returns a value, an error, or (nil, nil) to skip the row. diff --git a/src/os/user/user.go b/src/os/user/user.go index c1b8101c86..4e1b5b3407 100644 --- a/src/os/user/user.go +++ b/src/os/user/user.go @@ -20,9 +20,12 @@ import ( "strconv" ) +// These may be set to false in init() for a particular platform and/or +// build flags to let the tests know to skip tests of some features. var ( - userImplemented = true // set to false by lookup_stubs.go's init - groupImplemented = true // set to false by lookup_stubs.go's init + userImplemented = true + groupImplemented = true + groupListImplemented = true ) // User represents a user account. diff --git a/src/os/user/user_test.go b/src/os/user/user_test.go index 1112c78c00..d8a465edac 100644 --- a/src/os/user/user_test.go +++ b/src/os/user/user_test.go @@ -119,8 +119,15 @@ func TestLookupGroup(t *testing.T) { } } +func checkGroupList(t *testing.T) { + t.Helper() + if !groupListImplemented { + t.Skip("user: group list not implemented; skipping test") + } +} + func TestGroupIds(t *testing.T) { - checkGroup(t) + checkGroupList(t) if runtime.GOOS == "aix" { t.Skip("skipping GroupIds, see golang.org/issue/30563") } -- GitLab From d37b8dedf7f96d88c7280f6afadb09b100380f93 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sat, 21 Aug 2021 12:40:25 -0700 Subject: [PATCH 0838/2500] test: add test case that gofrontend miscompiled For #47771 Change-Id: I99dfdd48def756bde68445b50741afd6d86b6cf2 Reviewed-on: https://go-review.googlesource.com/c/go/+/344169 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- test/fixedbugs/issue47771.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 test/fixedbugs/issue47771.go diff --git a/test/fixedbugs/issue47771.go b/test/fixedbugs/issue47771.go new file mode 100644 index 0000000000..a434bffe4b --- /dev/null +++ b/test/fixedbugs/issue47771.go @@ -0,0 +1,19 @@ +// run + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// gofrontend miscompiled some cases of append(s, make(typ, ln)...). + +package main + +var g int + +func main() { + a := []*int{&g, &g, &g, &g} + a = append(a[:0], make([]*int, len(a) - 1)...) + if len(a) != 3 || a[0] != nil || a[1] != nil || a[2] != nil { + panic(a) + } +} -- GitLab From e1fcf8857e1b3e076cc3a6fad1860afe0d6c2ca6 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 20 Aug 2021 11:35:31 -0700 Subject: [PATCH 0839/2500] test: add test that caused gofrontend compiler crash Updates https://gcc.gnu.org/PR101994 Change-Id: I50dcb90e315792efd7d83b496034ad33b5f199e9 Reviewed-on: https://go-review.googlesource.com/c/go/+/343874 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- test/fixedbugs/gcc101994.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 test/fixedbugs/gcc101994.go diff --git a/test/fixedbugs/gcc101994.go b/test/fixedbugs/gcc101994.go new file mode 100644 index 0000000000..6e1e2b8075 --- /dev/null +++ b/test/fixedbugs/gcc101994.go @@ -0,0 +1,16 @@ +// compile + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// https://gcc.gnu.org/PR101994 +// gccgo compiler crash with zero-sized result. + +package p + +type Empty struct{} + +func F() (int, Empty) { + return 0, Empty{} +} -- GitLab From 099b819085e12ca45ac184cab5afb82538bec472 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 24 Aug 2021 15:34:52 -0700 Subject: [PATCH 0840/2500] cmd/compile: fix CheckSize() calculation for -G=3 and stencils Because the Align/Width of pointer types are always set when created, CalcSize() never descends past a pointer. Therefore, we need to do CheckSize() at every level when creating type. We need to do this for types creates by types2-to-types1 conversion and also by type substitution (mostly for stenciling). We also need to do Defer/ResumeCheckSize() at the top level in each of these cases to deal with potentially recursive types. These changes fix issue #47929 and also allow us to remove the special-case CheckSize() call that causes the problem for issue #47901. Fixes #47901 Fixes #47929 Change-Id: Icd8192431c145009cd6df2f4ade6db7da0f4dd3e Reviewed-on: https://go-review.googlesource.com/c/go/+/344829 Trust: Dan Scales Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/types.go | 24 +++++----- src/cmd/compile/internal/typecheck/subr.go | 52 ++++++++++++---------- test/typeparam/issue47901.go | 21 +++++++++ test/typeparam/issue47929.go | 29 ++++++++++++ 4 files changed, 88 insertions(+), 38 deletions(-) create mode 100644 test/typeparam/issue47901.go create mode 100644 test/typeparam/issue47929.go diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index 541ed68ef3..c9f7c2bbe4 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -30,21 +30,11 @@ func (g *irgen) pkg(pkg *types2.Package) *types.Pkg { // typ converts a types2.Type to a types.Type, including caching of previously // translated types. func (g *irgen) typ(typ types2.Type) *types.Type { + // Defer the CheckSize calls until we have fully-defined a + // (possibly-recursive) top-level type. + types.DeferCheckSize() res := g.typ1(typ) - - // Calculate the size for all concrete types seen by the frontend. The old - // typechecker calls CheckSize() a lot, and we want to eliminate calling - // it eventually, so we should do it here instead. We only call it for - // top-level types (i.e. we do it here rather in typ1), to make sure that - // recursive types have been fully constructed before we call CheckSize. - if res != nil && !res.IsUntyped() && !res.IsFuncArgStruct() && !res.HasTParam() { - types.CheckSize(res) - if res.IsPtr() { - // Pointers always have their size set, even though their element - // may not have its size set. - types.CheckSize(res.Elem()) - } - } + types.ResumeCheckSize() return res } @@ -59,6 +49,12 @@ func (g *irgen) typ1(typ types2.Type) *types.Type { res, ok := g.typs[typ] if !ok { res = g.typ0(typ) + // Calculate the size for all concrete types seen by the frontend. + // This is the replacement for the CheckSize() calls in the types1 + // typechecker. These will be deferred until the top-level g.typ(). + if res != nil && !res.IsUntyped() && !res.IsFuncArgStruct() && !res.HasTParam() { + types.CheckSize(res) + } g.typs[typ] = res } return res diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 7ae10ef406..b9cdcf10f2 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1003,6 +1003,15 @@ type Tsubster struct { // result is t; otherwise the result is a new type. It deals with recursive types // by using TFORW types and finding partially or fully created types via sym.Def. func (ts *Tsubster) Typ(t *types.Type) *types.Type { + // Defer the CheckSize calls until we have fully-defined + // (possibly-recursive) top-level type. + types.DeferCheckSize() + r := ts.typ1(t) + types.ResumeCheckSize() + return r +} + +func (ts *Tsubster) typ1(t *types.Type) *types.Type { if !t.HasTParam() && t.Kind() != types.TFUNC { // Note: function types need to be copied regardless, as the // types of closures may contain declarations that need @@ -1047,7 +1056,7 @@ func (ts *Tsubster) Typ(t *types.Type) *types.Type { // the tparam/targs mapping from subst. neededTargs = make([]*types.Type, len(t.RParams())) for i, rparam := range t.RParams() { - neededTargs[i] = ts.Typ(rparam) + neededTargs[i] = ts.typ1(rparam) if !types.Identical(neededTargs[i], rparam) { targsChanged = true } @@ -1085,26 +1094,26 @@ func (ts *Tsubster) Typ(t *types.Type) *types.Type { } // Substitute the underlying typeparam (e.g. T in P[T], see // the example describing type P[T] above). - newt = ts.Typ(t.Underlying()) + newt = ts.typ1(t.Underlying()) assert(newt != t) case types.TARRAY: elem := t.Elem() - newelem := ts.Typ(elem) + newelem := ts.typ1(elem) if newelem != elem || targsChanged { newt = types.NewArray(newelem, t.NumElem()) } case types.TPTR: elem := t.Elem() - newelem := ts.Typ(elem) + newelem := ts.typ1(elem) if newelem != elem || targsChanged { newt = types.NewPtr(newelem) } case types.TSLICE: elem := t.Elem() - newelem := ts.Typ(elem) + newelem := ts.typ1(elem) if newelem != elem || targsChanged { newt = types.NewSlice(newelem) } @@ -1159,22 +1168,17 @@ func (ts *Tsubster) Typ(t *types.Type) *types.Type { } case types.TMAP: - newkey := ts.Typ(t.Key()) - newval := ts.Typ(t.Elem()) + newkey := ts.typ1(t.Key()) + newval := ts.typ1(t.Elem()) if newkey != t.Key() || newval != t.Elem() || targsChanged { newt = types.NewMap(newkey, newval) } case types.TCHAN: elem := t.Elem() - newelem := ts.Typ(elem) + newelem := ts.typ1(elem) if newelem != elem || targsChanged { newt = types.NewChan(newelem, t.ChanDir()) - if !newt.HasTParam() { - // TODO(danscales): not sure why I have to do this - // only for channels..... - types.CheckSize(newt) - } } case types.TFORW: if ts.SubstForwFunc != nil { @@ -1194,7 +1198,7 @@ func (ts *Tsubster) Typ(t *types.Type) *types.Type { for i := 0; i < nt; i++ { term, tilde := t.Term(i) tildes[i] = tilde - newterms[i] = ts.Typ(term) + newterms[i] = ts.typ1(term) if newterms[i] != term { changed = true } @@ -1212,24 +1216,24 @@ func (ts *Tsubster) Typ(t *types.Type) *types.Type { return t } - if t.Sym() == nil && t.Kind() != types.TINTER { - // Not a named type or interface type, so there was no forwarding type - // and there are no methods to substitute. - assert(t.Methods().Len() == 0) - return newt - } - if forw != nil { forw.SetUnderlying(newt) newt = forw } + if !newt.HasTParam() { + // Calculate the size of any new types created. These will be + // deferred until the top-level ts.Typ() or g.typ() (if this is + // called from g.fillinMethods()). + types.CheckSize(newt) + } + if t.Kind() != types.TINTER && t.Methods().Len() > 0 { // Fill in the method info for the new type. var newfields []*types.Field newfields = make([]*types.Field, t.Methods().Len()) for i, f := range t.Methods().Slice() { - t2 := ts.Typ(f.Type) + t2 := ts.typ1(f.Type) oldsym := f.Nname.Sym() newsym := MakeFuncInstSym(oldsym, ts.Targs, true) var nname *ir.Name @@ -1272,7 +1276,7 @@ func (ts *Tsubster) tstruct(t *types.Type, force bool) *types.Type { newfields = make([]*types.Field, t.NumFields()) } for i, f := range t.Fields().Slice() { - t2 := ts.Typ(f.Type) + t2 := ts.typ1(f.Type) if (t2 != f.Type || f.Nname != nil) && newfields == nil { newfields = make([]*types.Field, t.NumFields()) for j := 0; j < i; j++ { @@ -1325,7 +1329,7 @@ func (ts *Tsubster) tinter(t *types.Type) *types.Type { } var newfields []*types.Field for i, f := range t.Methods().Slice() { - t2 := ts.Typ(f.Type) + t2 := ts.typ1(f.Type) if (t2 != f.Type || f.Nname != nil) && newfields == nil { newfields = make([]*types.Field, t.Methods().Len()) for j := 0; j < i; j++ { diff --git a/test/typeparam/issue47901.go b/test/typeparam/issue47901.go new file mode 100644 index 0000000000..cd07973011 --- /dev/null +++ b/test/typeparam/issue47901.go @@ -0,0 +1,21 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type Chan[T any] chan Chan[T] + +func (ch Chan[T]) recv() Chan[T] { + return <-ch +} + +func main() { + ch := Chan[int](make(chan Chan[int])) + go func() { + ch <- make(Chan[int]) + }() + ch.recv() +} diff --git a/test/typeparam/issue47929.go b/test/typeparam/issue47929.go new file mode 100644 index 0000000000..a5636f2c7b --- /dev/null +++ b/test/typeparam/issue47929.go @@ -0,0 +1,29 @@ +// compile -G=3 -p=p + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package v4 + +var sink interface{} + +//go:noinline +func Do(result, body interface{}) { + sink = &result +} + +func DataAction(result DataActionResponse, body DataActionRequest) { + Do(&result, body) +} + +type DataActionRequest struct { + Action *interface{} +} + +type DataActionResponse struct { + ValidationErrors *ValidationError +} + +type ValidationError struct { +} -- GitLab From 08d4cc20cad0e95b4e368c2f38268199f9c68548 Mon Sep 17 00:00:00 2001 From: wdvxdr Date: Mon, 23 Aug 2021 00:48:10 +0800 Subject: [PATCH 0841/2500] cmd/compile: fix stencil call expression. Fixes: #47878 Change-Id: I369350813726fd518b4eab2b98f43bf031a6dee6 Reviewed-on: https://go-review.googlesource.com/c/go/+/344210 Reviewed-by: Dan Scales Trust: Dan Scales Trust: Keith Randall Run-TryBot: Dan Scales TryBot-Result: Go Bot --- src/cmd/compile/internal/noder/stencil.go | 7 ++++ test/typeparam/issue47878.go | 46 +++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 test/typeparam/issue47878.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 18a0506036..b3ff4b8855 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1048,6 +1048,13 @@ func (subst *subster) node(n ir.Node) ir.Node { case ir.OCLOSURE: transformCall(call) + case ir.ODEREF, ir.OINDEX, ir.OINDEXMAP, ir.ORECV: + // Transform a call that was delayed because of the + // use of typeparam inside an expression that required + // a pointer dereference, array indexing, map indexing, + // or channel receive to compute function value. + transformCall(call) + case ir.OFUNCINST: // A call with an OFUNCINST will get transformed // in stencil() once we have created & attached the diff --git a/test/typeparam/issue47878.go b/test/typeparam/issue47878.go new file mode 100644 index 0000000000..cb1043a440 --- /dev/null +++ b/test/typeparam/issue47878.go @@ -0,0 +1,46 @@ +// compile -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type Src1[T any] func() Src1[T] + +func (s *Src1[T]) Next() { + *s = (*s)() +} + +type Src2[T any] []func() Src2[T] + +func (s Src2[T]) Next() { + _ = s[0]() +} + +type Src3[T comparable] map[T]func() Src3[T] + +func (s Src3[T]) Next() { + var a T + _ = s[a]() +} + +type Src4[T any] chan func() T + +func (s Src4[T]) Next() { + _ = (<-s)() +} + +func main() { + var src1 Src1[int] + src1.Next() + + var src2 Src2[int] + src2.Next() + + var src3 Src3[string] + src3.Next() + + var src4 Src4[int] + src4.Next() +} -- GitLab From 3b523caf4145c2d915c5ead69440f9b890634587 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Mon, 23 Aug 2021 14:51:39 -0400 Subject: [PATCH 0842/2500] [dev.cmdgo] cmd/go: clean up TODOWorkspaces instances Address some of the easier todos to address and remove the todos that have already been done and redundant todos. For #45713 Change-Id: I3fe4393168b10c6e005325258d9701713c92e9e4 Reviewed-on: https://go-review.googlesource.com/c/go/+/344491 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/modcmd/download.go | 2 +- src/cmd/go/internal/modcmd/initwork.go | 4 +- src/cmd/go/internal/modget/get.go | 20 +++++----- src/cmd/go/internal/modload/build.go | 1 - src/cmd/go/internal/modload/buildlist.go | 8 ++-- src/cmd/go/internal/modload/init.go | 48 +++++++++------------- src/cmd/go/internal/modload/load.go | 3 +- src/cmd/go/internal/modload/modfile.go | 2 +- src/cmd/go/internal/modload/query.go | 51 ++++++++++++++---------- 9 files changed, 70 insertions(+), 69 deletions(-) diff --git a/src/cmd/go/internal/modcmd/download.go b/src/cmd/go/internal/modcmd/download.go index 6a99cb01e1..ff56d05116 100644 --- a/src/cmd/go/internal/modcmd/download.go +++ b/src/cmd/go/internal/modcmd/download.go @@ -97,7 +97,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { modload.LoadModFile(ctx) // to fill MainModules if len(modload.MainModules.Versions()) != 1 { - panic(modload.TODOWorkspaces("TODO: multiple main modules not supported in Download")) + panic(modload.TODOWorkspaces("Support workspace mode in go mod download")) } mainModule := modload.MainModules.Versions()[0] diff --git a/src/cmd/go/internal/modcmd/initwork.go b/src/cmd/go/internal/modcmd/initwork.go index 30653503bc..4182aa071d 100644 --- a/src/cmd/go/internal/modcmd/initwork.go +++ b/src/cmd/go/internal/modcmd/initwork.go @@ -13,9 +13,9 @@ import ( "path/filepath" ) -var _ = modload.TODOWorkspaces("Add more documentation below.T hough this is" + +var _ = modload.TODOWorkspaces("Add more documentation below. Though this is" + "enough for those trying workspaces out, there should be more through" + - "documentation if the proposal is accepted.") + "documentation if the proposal is accepted and released.") var cmdInitwork = &base.Command{ UsageLine: "go mod initwork [moddirs]", diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index 3d831a14d8..37912ce833 100644 --- a/src/cmd/go/internal/modget/get.go +++ b/src/cmd/go/internal/modget/get.go @@ -690,7 +690,7 @@ func (r *resolver) queryNone(ctx context.Context, q *query) { // However, neither of those behaviors would be consistent with the // plain meaning of the query. To try to reduce confusion, reject the // query explicitly. - return errSet(&modload.QueryMatchesMainModuleError{MainModule: v, Pattern: q.pattern, Query: q.version}) + return errSet(&modload.QueryMatchesMainModulesError{MainModules: []module.Version{v}, Pattern: q.pattern, Query: q.version}) } return pathSet{mod: module.Version{Path: q.pattern, Version: "none"}} @@ -703,7 +703,7 @@ func (r *resolver) queryNone(ctx context.Context, q *query) { } q.pathOnce(curM.Path, func() pathSet { if modload.HasModRoot() && curM.Version == "" && modload.MainModules.Contains(curM.Path) { - return errSet(&modload.QueryMatchesMainModuleError{MainModule: curM, Pattern: q.pattern, Query: q.version}) + return errSet(&modload.QueryMatchesMainModulesError{MainModules: []module.Version{curM}, Pattern: q.pattern, Query: q.version}) } return pathSet{mod: module.Version{Path: curM.Path, Version: "none"}} }) @@ -805,10 +805,10 @@ func (r *resolver) queryWildcard(ctx context.Context, q *query) { if modload.MainModules.Contains(curM.Path) && !versionOkForMainModule(q.version) { if q.matchesPath(curM.Path) { - return errSet(&modload.QueryMatchesMainModuleError{ - MainModule: curM, - Pattern: q.pattern, - Query: q.version, + return errSet(&modload.QueryMatchesMainModulesError{ + MainModules: []module.Version{curM}, + Pattern: q.pattern, + Query: q.version, }) } @@ -1760,10 +1760,10 @@ func (r *resolver) resolve(q *query, m module.Version) { } if modload.MainModules.Contains(m.Path) && m.Version != "" { - reportError(q, &modload.QueryMatchesMainModuleError{ - MainModule: module.Version{Path: m.Path}, - Pattern: q.pattern, - Query: q.version, + reportError(q, &modload.QueryMatchesMainModulesError{ + MainModules: []module.Version{{Path: m.Path}}, + Pattern: q.pattern, + Query: q.version, }) return } diff --git a/src/cmd/go/internal/modload/build.go b/src/cmd/go/internal/modload/build.go index 73b51c117a..0efd84123a 100644 --- a/src/cmd/go/internal/modload/build.go +++ b/src/cmd/go/internal/modload/build.go @@ -218,7 +218,6 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li Version: m.Version, Main: true, } - _ = TODOWorkspaces("handle rawGoVersion here") if v, ok := rawGoVersion.Load(m); ok { info.GoVersion = v.(string) } else { diff --git a/src/cmd/go/internal/modload/buildlist.go b/src/cmd/go/internal/modload/buildlist.go index 9989bb5b2a..14379b4c3c 100644 --- a/src/cmd/go/internal/modload/buildlist.go +++ b/src/cmd/go/internal/modload/buildlist.go @@ -139,7 +139,7 @@ func (rs *Requirements) initVendor(vendorList []module.Version) { } if MainModules.Len() != 1 { - panic("There should be exactly one main moudle in Vendor mode.") + panic("There should be exactly one main module in Vendor mode.") } mainModule := MainModules.Versions()[0] @@ -284,8 +284,10 @@ func readModGraph(ctx context.Context, depth modDepth, roots []module.Version) ( ) for _, m := range MainModules.Versions() { // Require all roots from all main modules. - _ = TODOWorkspaces("This isn't the correct behavior. " + - "Fix this when the requirements struct is updated to reflect the struct of the module graph.") + _ = TODOWorkspaces("This flattens a level of the module graph, adding the dependencies " + + "of all main modules to a single requirements struct, and losing the information of which " + + "main module required which requirement. Rework the requirements struct and change this" + + "to reflect the structure of the main modules.") mg.g.Require(m, roots) } diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 896c61d19d..ab6733830f 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -123,8 +123,6 @@ func (mms *MainModuleSet) Contains(path string) bool { } func (mms *MainModuleSet) ModRoot(m module.Version) string { - _ = TODOWorkspaces(" Do we need the Init? The original modRoot calls it. Audit callers.") - Init() if mms == nil { return "" } @@ -143,8 +141,11 @@ func (mms *MainModuleSet) mustGetSingleMainModule() module.Version { panic("internal error: mustGetSingleMainModule called in context with no main modules") } if len(mms.versions) != 1 { - _ = TODOWorkspaces("Check if we're in workspace mode before returning the below error.") - panic("internal error: mustGetSingleMainModule called in workspace mode") + if inWorkspaceMode() { + panic("internal error: mustGetSingleMainModule called in workspace mode") + } else { + panic("internal error: multiple main modules present outside of workspace mode") + } } return mms.versions[0] } @@ -156,11 +157,7 @@ func (mms *MainModuleSet) GetSingleIndexOrNil() *modFileIndex { if len(mms.versions) == 0 { return nil } - if len(mms.versions) != 1 { - _ = TODOWorkspaces("Check if we're in workspace mode before returning the below error.") - panic("internal error: mustGetSingleMainModule called in workspace mode") - } - return mms.indices[mms.versions[0]] + return mms.indices[mms.mustGetSingleMainModule()] } func (mms *MainModuleSet) Index(m module.Version) *modFileIndex { @@ -363,7 +360,9 @@ func Init() { // We're in module mode. Set any global variables that need to be set. cfg.ModulesEnabled = true setDefaultBuildMod() - _ = TODOWorkspaces("ensure that buildmod is readonly") + _ = TODOWorkspaces("In workspace mode, mod will not be readonly for go mod download," + + "verify, graph, and why. Implement support for go mod download and add test cases" + + "to ensure verify, graph, and why work properly.") list := filepath.SplitList(cfg.BuildContext.GOPATH) if len(list) == 0 || list[0] == "" { base.Fatalf("missing $GOPATH") @@ -374,15 +373,14 @@ func Init() { } if inWorkspaceMode() { - _ = TODOWorkspaces("go.work.sum, and also allow modfetch to fall back to individual go.sums") - _ = TODOWorkspaces("replaces") var err error modRoots, err = loadWorkFile(workFilePath) if err != nil { base.Fatalf("reading go.work: %v", err) } + _ = TODOWorkspaces("Support falling back to individual module go.sum " + + "files for sums not in the workspace sum file.") modfetch.GoSumFile = workFilePath + ".sum" - // TODO(matloob) should workRoot just be workFile? } else if modRoots == nil { // We're in module mode, but not inside a module. // @@ -539,6 +537,7 @@ func (goModDirtyError) Error() string { var errGoModDirty error = goModDirtyError{} func loadWorkFile(path string) (modRoots []string, err error) { + _ = TODOWorkspaces("Clean up and write back the go.work file: add module paths for workspace modules.") workDir := filepath.Dir(path) workData, err := lockedfile.Read(path) if err != nil { @@ -661,8 +660,7 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { // We don't need to do anything for vendor or update the mod file so // return early. - _ = TODOWorkspaces("don't worry about commits for now, but eventually will want to update go.work files") - return rs, false + return rs, true } mainModule := MainModules.mustGetSingleMainModule() @@ -761,7 +759,7 @@ func CreateModFile(ctx context.Context, modPath string) { MainModules = makeMainModules([]module.Version{modFile.Module.Mod}, []string{modRoot}, []*modfile.File{modFile}, []*modFileIndex{nil}) addGoStmt(modFile, modFile.Module.Mod, LatestGoVersion()) // Add the go directive before converted module requirements. - convertedFrom, err := convertLegacyConfig(modFile, modPath) + convertedFrom, err := convertLegacyConfig(modFile, modRoot) if convertedFrom != "" { fmt.Fprintf(os.Stderr, "go: copying requirements from %s\n", base.ShortPath(convertedFrom)) } @@ -1037,7 +1035,7 @@ func mustHaveCompleteRequirements() bool { // convertLegacyConfig imports module requirements from a legacy vendoring // configuration file, if one is present. -func convertLegacyConfig(modFile *modfile.File, modPath string) (from string, err error) { +func convertLegacyConfig(modFile *modfile.File, modRoot string) (from string, err error) { noneSelected := func(path string) (version string) { return "none" } queryPackage := func(path, rev string) (module.Version, error) { pkgMods, modOnly, err := QueryPattern(context.Background(), path, rev, noneSelected, nil) @@ -1050,10 +1048,7 @@ func convertLegacyConfig(modFile *modfile.File, modPath string) (from string, er return modOnly.Mod, nil } for _, name := range altConfigs { - if len(modRoots) != 1 { - panic(TODOWorkspaces("what do do here?")) - } - cfg := filepath.Join(modRoots[0], name) + cfg := filepath.Join(modRoot, name) data, err := os.ReadFile(cfg) if err == nil { convert := modconv.Converters[name] @@ -1166,7 +1161,8 @@ func findWorkspaceFile(dir string) (root string) { break } if d == cfg.GOROOT { - _ = TODOWorkspaces("Address how go.work files interact with GOROOT") + _ = TODOWorkspaces("If we end up checking in a go.work file to GOROOT/src," + + "remove this case.") return "" // As a special case, don't cross GOROOT to find a go.work file. } dir = d @@ -1345,7 +1341,7 @@ func commitRequirements(ctx context.Context, goVersion string, rs *Requirements) // We aren't in a module, so we don't have anywhere to write a go.mod file. return } - mainModule := MainModules.Versions()[0] + mainModule := MainModules.mustGetSingleMainModule() modFilePath := modFilePath(MainModules.ModRoot(mainModule)) modFile := MainModules.ModFile(mainModule) @@ -1398,12 +1394,6 @@ func commitRequirements(ctx context.Context, goVersion string, rs *Requirements) base.Fatalf("go: %v", err) } defer func() { - if MainModules.Len() != 1 { - panic(TODOWorkspaces("There should be exactly one main module when committing reqs")) - } - - mainModule := MainModules.Versions()[0] - // At this point we have determined to make the go.mod file on disk equal to new. MainModules.SetIndex(mainModule, indexModFile(new, modFile, mainModule, false)) diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index cb5a2d7a35..c9004ff796 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -552,8 +552,7 @@ func resolveLocalPackage(ctx context.Context, dir string, rs *Requirements) (str // return an error. if len(mainModulePrefix) > len(pkgNotFoundLongestPrefix) { pkgNotFoundLongestPrefix = mainModulePrefix - pkgNotFoundErr = &PackageNotInModuleError{Mod: mainModule, Pattern: pkg} - + pkgNotFoundErr = &PackageNotInModuleError{MainModules: []module.Version{mainModule}, Pattern: pkg} } continue } diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index 664fc0f91b..09e9c67659 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -322,7 +322,7 @@ func replacement(mod module.Version, index *modFileIndex) (fromVersion string, t // If there is no replacement for mod, Replacement returns // a module.Version with Path == "". func Replacement(mod module.Version) (module.Version, string) { - _ = TODOWorkspaces("support replaces in the go.work file") + _ = TODOWorkspaces("Support replaces in the go.work file.") foundFrom, found, foundModRoot := "", module.Version{}, "" for _, v := range MainModules.Versions() { if index := MainModules.Index(v); index != nil { diff --git a/src/cmd/go/internal/modload/query.go b/src/cmd/go/internal/modload/query.go index 6d6bfe774c..82979fbda1 100644 --- a/src/cmd/go/internal/modload/query.go +++ b/src/cmd/go/internal/modload/query.go @@ -632,18 +632,16 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin if modOnly != nil { return nil, modOnly, nil } else if len(mainModuleMatches) != 0 { - _ = TODOWorkspaces("add multiple main modules to the error?") - return nil, nil, &QueryMatchesMainModuleError{ - MainModule: mainModuleMatches[0], - Pattern: pattern, - Query: query, + return nil, nil, &QueryMatchesMainModulesError{ + MainModules: mainModuleMatches, + Pattern: pattern, + Query: query, } } else { - _ = TODOWorkspaces("This should maybe be PackageNotInModule*s* error with the main modules that are prefixes of base") return nil, nil, &PackageNotInModuleError{ - Mod: MainModules.Versions()[0], - Query: query, - Pattern: pattern, + MainModules: mainModuleMatches, + Query: query, + Pattern: pattern, } } } @@ -695,7 +693,7 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin }) if len(mainModuleMatches) > 0 && len(results) == 0 && modOnly == nil && errors.Is(err, fs.ErrNotExist) { - return nil, nil, &QueryMatchesMainModuleError{ + return nil, nil, &QueryMatchesMainModulesError{ Pattern: pattern, Query: query, } @@ -893,6 +891,7 @@ func (e *WildcardInFirstElementError) Error() string { // code for the versions it knows about, and thus did not have the opportunity // to return a non-400 status code to suppress fallback. type PackageNotInModuleError struct { + MainModules []module.Version Mod module.Version Replacement module.Version Query string @@ -900,11 +899,15 @@ type PackageNotInModuleError struct { } func (e *PackageNotInModuleError) Error() string { - if MainModules.Contains(e.Mod.Path) { + if len(e.MainModules) > 0 { + prefix := "workspace modules do" + if len(e.MainModules) == 1 { + prefix = fmt.Sprintf("main module (%s) does", e.MainModules[0]) + } if strings.Contains(e.Pattern, "...") { - return fmt.Sprintf("main module (%s) does not contain packages matching %s", e.Mod.Path, e.Pattern) + return fmt.Sprintf("%s not contain packages matching %s", prefix, e.Pattern) } - return fmt.Sprintf("main module (%s) does not contain package %s", e.Mod.Path, e.Pattern) + return fmt.Sprintf("%s not contain package %s", prefix, e.Pattern) } found := "" @@ -1153,21 +1156,29 @@ func (rr *replacementRepo) replacementStat(v string) (*modfetch.RevInfo, error) return rev, nil } -// A QueryMatchesMainModuleError indicates that a query requests +// A QueryMatchesMainModulesError indicates that a query requests // a version of the main module that cannot be satisfied. // (The main module's version cannot be changed.) -type QueryMatchesMainModuleError struct { - MainModule module.Version - Pattern string - Query string +type QueryMatchesMainModulesError struct { + MainModules []module.Version + Pattern string + Query string } -func (e *QueryMatchesMainModuleError) Error() string { +func (e *QueryMatchesMainModulesError) Error() string { if MainModules.Contains(e.Pattern) { return fmt.Sprintf("can't request version %q of the main module (%s)", e.Query, e.Pattern) } - return fmt.Sprintf("can't request version %q of pattern %q that includes the main module (%s)", e.Query, e.Pattern, e.MainModule.Path) + plural := "" + mainModulePaths := make([]string, len(e.MainModules)) + for i := range e.MainModules { + mainModulePaths[i] = e.MainModules[i].Path + } + if len(e.MainModules) > 1 { + plural = "s" + } + return fmt.Sprintf("can't request version %q of pattern %q that includes the main module%s (%s)", e.Query, e.Pattern, plural, strings.Join(mainModulePaths, ", ")) } // A QueryUpgradesAllError indicates that a query requests -- GitLab From de23549a3967ade982d848a5b6ae3cb3fa0dba45 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Tue, 24 Aug 2021 12:37:15 -0400 Subject: [PATCH 0843/2500] [dev.cmdgo] cmd/go: fix calls to modFileGoVersion to pass in modFile Before this change, we were arbitrarily picking a module to get the Go version from in calls to modFileGoVersion. We now pass in the modFile to modFileGoVersion when we have the file. Most of the calls were to get the goVersion argument for commitRequirements, so now we have commitRequirements call modFileGoVersion on the modFile directly One of the calls to commitRequirements (when running go mod tidy with a different Go version) passed in a new go version to update the file to. Now, the modFile is updated before calling commitRequirements. For the remaining cases of modFileGoVersion, it's replaced by a call to the new (*MainModuleSet).GoVersion function, which either returns the go version on the workspace file (in workspace mode) or the version of the single go.mod file. Change-Id: Ie88c3ca76c7f29ffc4faa16bb76f6cb7eccb5029 Reviewed-on: https://go-review.googlesource.com/c/go/+/344749 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/modload/buildlist.go | 4 +- src/cmd/go/internal/modload/init.go | 76 +++++++++++++++--------- src/cmd/go/internal/modload/list.go | 2 +- src/cmd/go/internal/modload/load.go | 14 +++-- src/cmd/go/internal/modload/modfile.go | 8 +-- 5 files changed, 64 insertions(+), 40 deletions(-) diff --git a/src/cmd/go/internal/modload/buildlist.go b/src/cmd/go/internal/modload/buildlist.go index 14379b4c3c..94414278ab 100644 --- a/src/cmd/go/internal/modload/buildlist.go +++ b/src/cmd/go/internal/modload/buildlist.go @@ -461,7 +461,7 @@ func LoadModGraph(ctx context.Context, goVersion string) *ModuleGraph { base.Fatalf("go: %v", err) } - commitRequirements(ctx, modFileGoVersion(), rs) + commitRequirements(ctx, rs) return mg } @@ -527,7 +527,7 @@ func EditBuildList(ctx context.Context, add, mustSelect []module.Version) (chang if err != nil { return false, err } - commitRequirements(ctx, modFileGoVersion(), rs) + commitRequirements(ctx, rs) return changed, err } diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index ab6733830f..b845842a7f 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -59,8 +59,9 @@ var ( // roots are required but MainModules hasn't been initialized yet. Set to // the modRoots of the main modules. // modRoots != nil implies len(modRoots) > 0 - modRoots []string - gopath string + modRoots []string + gopath string + workFileGoVersion string ) // Variable set in InitWorkfile @@ -91,6 +92,8 @@ type MainModuleSet struct { modContainingCWD module.Version + workFileGoVersion string + indexMu sync.Mutex indices map[module.Version]*modFileIndex } @@ -190,6 +193,20 @@ func (mms *MainModuleSet) ModContainingCWD() module.Version { return mms.modContainingCWD } +// GoVersion returns the go version set on the single module, in module mode, +// or the go.work file in workspace mode. +func (mms *MainModuleSet) GoVersion() string { + if !inWorkspaceMode() { + return modFileGoVersion(mms.ModFile(mms.mustGetSingleMainModule())) + } + v := mms.workFileGoVersion + if v == "" { + // Fall back to 1.18 for go.work files. + v = "1.18" + } + return v +} + var MainModules *MainModuleSet type Root int @@ -374,7 +391,7 @@ func Init() { if inWorkspaceMode() { var err error - modRoots, err = loadWorkFile(workFilePath) + workFileGoVersion, modRoots, err = loadWorkFile(workFilePath) if err != nil { base.Fatalf("reading go.work: %v", err) } @@ -536,16 +553,19 @@ func (goModDirtyError) Error() string { var errGoModDirty error = goModDirtyError{} -func loadWorkFile(path string) (modRoots []string, err error) { +func loadWorkFile(path string) (goVersion string, modRoots []string, err error) { _ = TODOWorkspaces("Clean up and write back the go.work file: add module paths for workspace modules.") workDir := filepath.Dir(path) workData, err := lockedfile.Read(path) if err != nil { - return nil, err + return "", nil, err } wf, err := modfile.ParseWork(path, workData, nil) if err != nil { - return nil, err + return "", nil, err + } + if wf.Go != nil { + goVersion = wf.Go.Version } seen := map[string]bool{} for _, d := range wf.Directory { @@ -554,12 +574,12 @@ func loadWorkFile(path string) (modRoots []string, err error) { modRoot = filepath.Join(workDir, modRoot) } if seen[modRoot] { - return nil, fmt.Errorf("path %s appears multiple times in workspace", modRoot) + return "", nil, fmt.Errorf("path %s appears multiple times in workspace", modRoot) } seen[modRoot] = true modRoots = append(modRoots, modRoot) } - return modRoots, nil + return goVersion, modRoots, nil } // LoadModFile sets Target and, if there is a main module, parses the initial @@ -582,7 +602,7 @@ func loadWorkFile(path string) (modRoots []string, err error) { func LoadModFile(ctx context.Context) *Requirements { rs, needCommit := loadModFile(ctx) if needCommit { - commitRequirements(ctx, modFileGoVersion(), rs) + commitRequirements(ctx, rs) } return rs } @@ -602,7 +622,7 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { if len(modRoots) == 0 { _ = TODOWorkspaces("Instead of creating a fake module with an empty modroot, make MainModules.Len() == 0 mean that we're in module mode but not inside any module.") mainModule := module.Version{Path: "command-line-arguments"} - MainModules = makeMainModules([]module.Version{mainModule}, []string{""}, []*modfile.File{nil}, []*modFileIndex{nil}) + MainModules = makeMainModules([]module.Version{mainModule}, []string{""}, []*modfile.File{nil}, []*modFileIndex{nil}, "") goVersion := LatestGoVersion() rawGoVersion.Store(mainModule, goVersion) requirements = newRequirements(modDepthFromGoVersion(goVersion), nil, nil) @@ -652,7 +672,7 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { } } - MainModules = makeMainModules(mainModules, modRoots, modFiles, indices) + MainModules = makeMainModules(mainModules, modRoots, modFiles, indices, workFileGoVersion) setDefaultBuildMod() // possibly enable automatic vendoring rs = requirementsFromModFiles(ctx, modFiles) @@ -702,7 +722,7 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { } } } else { - rawGoVersion.Store(mainModule, modFileGoVersion()) + rawGoVersion.Store(mainModule, modFileGoVersion(MainModules.ModFile(mainModule))) } } @@ -756,7 +776,7 @@ func CreateModFile(ctx context.Context, modPath string) { fmt.Fprintf(os.Stderr, "go: creating new go.mod: module %s\n", modPath) modFile := new(modfile.File) modFile.AddModuleStmt(modPath) - MainModules = makeMainModules([]module.Version{modFile.Module.Mod}, []string{modRoot}, []*modfile.File{modFile}, []*modFileIndex{nil}) + MainModules = makeMainModules([]module.Version{modFile.Module.Mod}, []string{modRoot}, []*modfile.File{modFile}, []*modFileIndex{nil}, "") addGoStmt(modFile, modFile.Module.Mod, LatestGoVersion()) // Add the go directive before converted module requirements. convertedFrom, err := convertLegacyConfig(modFile, modRoot) @@ -772,7 +792,7 @@ func CreateModFile(ctx context.Context, modPath string) { if err != nil { base.Fatalf("go: %v", err) } - commitRequirements(ctx, modFileGoVersion(), rs) + commitRequirements(ctx, rs) // Suggest running 'go mod tidy' unless the project is empty. Even if we // imported all the correct requirements above, we're probably missing @@ -880,7 +900,7 @@ func AllowMissingModuleImports() { // makeMainModules creates a MainModuleSet and associated variables according to // the given main modules. -func makeMainModules(ms []module.Version, rootDirs []string, modFiles []*modfile.File, indices []*modFileIndex) *MainModuleSet { +func makeMainModules(ms []module.Version, rootDirs []string, modFiles []*modfile.File, indices []*modFileIndex, workFileGoVersion string) *MainModuleSet { for _, m := range ms { if m.Version != "" { panic("mainModulesCalled with module.Version with non empty Version field: " + fmt.Sprintf("%#v", m)) @@ -888,12 +908,13 @@ func makeMainModules(ms []module.Version, rootDirs []string, modFiles []*modfile } modRootContainingCWD := findModuleRoot(base.Cwd()) mainModules := &MainModuleSet{ - versions: ms[:len(ms):len(ms)], - inGorootSrc: map[module.Version]bool{}, - pathPrefix: map[module.Version]string{}, - modRoot: map[module.Version]string{}, - modFiles: map[module.Version]*modfile.File{}, - indices: map[module.Version]*modFileIndex{}, + versions: ms[:len(ms):len(ms)], + inGorootSrc: map[module.Version]bool{}, + pathPrefix: map[module.Version]string{}, + modRoot: map[module.Version]string{}, + modFiles: map[module.Version]*modfile.File{}, + indices: map[module.Version]*modFileIndex{}, + workFileGoVersion: workFileGoVersion, } for i, m := range ms { mainModules.pathPrefix[m] = m.Path @@ -958,7 +979,7 @@ func requirementsFromModFiles(ctx context.Context, modFiles []*modfile.File) *Re } } module.Sort(roots) - rs := newRequirements(modDepthFromGoVersion(modFileGoVersion()), roots, direct) + rs := newRequirements(modDepthFromGoVersion(MainModules.GoVersion()), roots, direct) return rs } @@ -1315,12 +1336,13 @@ func WriteGoMod(ctx context.Context) { if !allowWriteGoMod { panic("WriteGoMod called while disallowed") } - commitRequirements(ctx, modFileGoVersion(), LoadModFile(ctx)) + commitRequirements(ctx, LoadModFile(ctx)) } // commitRequirements writes sets the global requirements variable to rs and // writes its contents back to the go.mod file on disk. -func commitRequirements(ctx context.Context, goVersion string, rs *Requirements) { +// goVersion, if non-empty, is used to set the version on the go.mod file. +func commitRequirements(ctx context.Context, rs *Requirements) { requirements = rs if !allowWriteGoMod { @@ -1352,10 +1374,10 @@ func commitRequirements(ctx context.Context, goVersion string, rs *Requirements) Indirect: !rs.direct[m.Path], }) } - if goVersion != "" { - modFile.AddGoStmt(goVersion) + if modFile.Go == nil || modFile.Go.Version == "" { + modFile.AddGoStmt(modFileGoVersion(modFile)) } - if semver.Compare("v"+modFileGoVersion(), separateIndirectVersionV) < 0 { + if semver.Compare("v"+modFileGoVersion(modFile), separateIndirectVersionV) < 0 { modFile.SetRequire(list) } else { modFile.SetRequireSeparateIndirect(list) diff --git a/src/cmd/go/internal/modload/list.go b/src/cmd/go/internal/modload/list.go index 1862bef494..9c5018f340 100644 --- a/src/cmd/go/internal/modload/list.go +++ b/src/cmd/go/internal/modload/list.go @@ -72,7 +72,7 @@ func ListModules(ctx context.Context, args []string, mode ListMode) ([]*modinfo. } if err == nil { - commitRequirements(ctx, modFileGoVersion(), rs) + commitRequirements(ctx, rs) } return mods, err } diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index c9004ff796..efe6ad1319 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -407,11 +407,17 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma base.Fatalf("go: %v", err) } } + + // Update the go.mod file's Go version if necessary. + modFile := MainModules.ModFile(MainModules.mustGetSingleMainModule()) + if ld.GoVersion != "" { + modFile.AddGoStmt(ld.GoVersion) + } } // Success! Update go.mod and go.sum (if needed) and return the results. loaded = ld - commitRequirements(ctx, loaded.GoVersion, loaded.requirements) + commitRequirements(ctx, loaded.requirements) for _, pkg := range ld.pkgs { if !pkg.isTest() { @@ -678,7 +684,7 @@ func ImportFromFiles(ctx context.Context, gofiles []string) { return roots }, }) - commitRequirements(ctx, loaded.GoVersion, loaded.requirements) + commitRequirements(ctx, loaded.requirements) } // DirImportPath returns the effective import path for dir, @@ -960,7 +966,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader { } if ld.GoVersion == "" { - ld.GoVersion = modFileGoVersion() + ld.GoVersion = MainModules.GoVersion() if ld.Tidy && semver.Compare("v"+ld.GoVersion, "v"+LatestGoVersion()) > 0 { ld.errorf("go mod tidy: go.mod file indicates go %s, but maximum supported version is %s\n", ld.GoVersion, LatestGoVersion()) @@ -1836,7 +1842,7 @@ func (ld *loader) checkTidyCompatibility(ctx context.Context, rs *Requirements) fmt.Fprintln(os.Stderr) goFlag := "" - if ld.GoVersion != modFileGoVersion() { + if ld.GoVersion != MainModules.GoVersion() { goFlag = " -go=" + ld.GoVersion } diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index 09e9c67659..463869910c 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -57,12 +57,8 @@ const ( ) // modFileGoVersion returns the (non-empty) Go version at which the requirements -// in modFile are intepreted, or the latest Go version if modFile is nil. -func modFileGoVersion() string { - _ = TODOWorkspaces("this is obviously wrong.") - // Yes we're picking arbitrarily, we'll have to pass through the version - // we care about - modFile := MainModules.ModFile(MainModules.Versions()[0]) +// in modFile are interpreted, or the latest Go version if modFile is nil. +func modFileGoVersion(modFile *modfile.File) string { if modFile == nil { return LatestGoVersion() } -- GitLab From d2f002cb39bebdfac560282a43f3199c5d0903d7 Mon Sep 17 00:00:00 2001 From: korzhao Date: Sat, 21 Aug 2021 07:26:19 +0800 Subject: [PATCH 0844/2500] time/format: avoid growslice in time.String()/time.GoString() Pre-allocate the slice of buf with enough capacity to avoid growslice calls. benchmark old ns/op new ns/op delta BenchmarkTimeString-4 493 409 -17.12% BenchmarkTimeGoString-4 309 182 -41.30% benchmark old allocs new allocs delta BenchmarkTimeString-4 5 3 -40.00% BenchmarkTimeGoString-4 4 1 -75.00% benchmark old bytes new bytes delta BenchmarkTimeString-4 152 128 -15.79% BenchmarkTimeGoString-4 248 80 -67.74% Change-Id: I64eabe2ab0b3d4a846453c2e8e548a831d720b8c Reviewed-on: https://go-review.googlesource.com/c/go/+/343971 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Alexander Rakoczy --- src/time/format.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/time/format.go b/src/time/format.go index f4b4f48142..7ae89c557d 100644 --- a/src/time/format.go +++ b/src/time/format.go @@ -479,7 +479,7 @@ func (t Time) String() string { } m1, m2 := m2/1e9, m2%1e9 m0, m1 := m1/1e9, m1%1e9 - var buf []byte + buf := make([]byte, 0, 24) buf = append(buf, " m="...) buf = append(buf, sign) wid := 0 @@ -498,7 +498,8 @@ func (t Time) String() string { // GoString implements fmt.GoStringer and formats t to be printed in Go source // code. func (t Time) GoString() string { - buf := []byte("time.Date(") + buf := make([]byte, 0, 70) + buf = append(buf, "time.Date("...) buf = appendInt(buf, t.Year(), 0) month := t.Month() if January <= month && month <= December { -- GitLab From 4f2ebfe34be7453ab144d82558cc4e735a55d644 Mon Sep 17 00:00:00 2001 From: korzhao Date: Tue, 17 Aug 2021 19:34:40 +0800 Subject: [PATCH 0845/2500] cmd/compile: allow embed into any byte slice type Fixes #47735 Change-Id: Ia21ea9a67f36a3edfef1b299ae4f3b00c306cd68 Reviewed-on: https://go-review.googlesource.com/c/go/+/342851 Reviewed-by: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Alexander Rakoczy --- src/cmd/compile/internal/staticdata/embed.go | 2 +- src/embed/internal/embedtest/embed_test.go | 40 ++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/staticdata/embed.go b/src/cmd/compile/internal/staticdata/embed.go index 0730d346b2..627c98ba44 100644 --- a/src/cmd/compile/internal/staticdata/embed.go +++ b/src/cmd/compile/internal/staticdata/embed.go @@ -73,7 +73,7 @@ func embedKind(typ *types.Type) int { if typ.Kind() == types.TSTRING { return embedString } - if typ.Sym() == nil && typ.IsSlice() && typ.Elem().Kind() == types.TUINT8 { + if typ.IsSlice() && typ.Elem().Kind() == types.TUINT8 { return embedBytes } return embedUnknown diff --git a/src/embed/internal/embedtest/embed_test.go b/src/embed/internal/embedtest/embed_test.go index 2d50f5e01f..b41359f4c2 100644 --- a/src/embed/internal/embedtest/embed_test.go +++ b/src/embed/internal/embedtest/embed_test.go @@ -129,3 +129,43 @@ func TestUninitialized(t *testing.T) { t.Errorf("in uninitialized embed.FS, . is not a directory") } } + +var ( + //go:embed "testdata/hello.txt" + helloT []T + //go:embed "testdata/hello.txt" + helloUint8 []uint8 + //go:embed "testdata/hello.txt" + helloEUint8 []EmbedUint8 + //go:embed "testdata/hello.txt" + helloBytes EmbedBytes + //go:embed "testdata/hello.txt" + helloString EmbedString +) + +type T byte +type EmbedUint8 uint8 +type EmbedBytes []byte +type EmbedString string + +// golang.org/issue/47735 +func TestAliases(t *testing.T) { + all := testDirAll + want, e := all.ReadFile("testdata/hello.txt") + if e != nil { + t.Fatal("ReadFile:", e) + } + check := func(g interface{}) { + got := reflect.ValueOf(g) + for i := 0; i < got.Len(); i++ { + if byte(got.Index(i).Uint()) != want[i] { + t.Fatalf("got %v want %v", got.Bytes(), want) + } + } + } + check(helloT) + check(helloUint8) + check(helloEUint8) + check(helloBytes) + check(helloString) +} -- GitLab From 3d667671ad767d66bf792c5a8d623cb829f6366a Mon Sep 17 00:00:00 2001 From: korzhao Date: Wed, 25 Aug 2021 16:01:49 +0800 Subject: [PATCH 0846/2500] cmd/compile: fix function contains no TParam in generic function Fixes #47948 Change-Id: I446a9548265d195ae4d88aff6b1361474d1b6214 Reviewed-on: https://go-review.googlesource.com/c/go/+/344910 Trust: Alexander Rakoczy Trust: Dan Scales Run-TryBot: Alexander Rakoczy TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/typecheck/subr.go | 3 ++- test/typeparam/issue47948.go | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 test/typeparam/issue47948.go diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index b9cdcf10f2..8d05356543 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1051,7 +1051,8 @@ func (ts *Tsubster) typ1(t *types.Type) *types.Type { var targsChanged bool var forw *types.Type - if t.Sym() != nil { + if t.Sym() != nil && t.HasTParam() { + // Need to test for t.HasTParam() again because of special TFUNC case above. // Translate the type params for this type according to // the tparam/targs mapping from subst. neededTargs = make([]*types.Type, len(t.RParams())) diff --git a/test/typeparam/issue47948.go b/test/typeparam/issue47948.go new file mode 100644 index 0000000000..8e5df81f6d --- /dev/null +++ b/test/typeparam/issue47948.go @@ -0,0 +1,18 @@ +// compile -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type fun func() + +func F[T any]() { + _ = fun(func() { + + }) +} +func main() { + F[int]() +} -- GitLab From 5baf60d47245c792c50a349cd6b8586d23204895 Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Sat, 29 May 2021 19:11:37 -0700 Subject: [PATCH 0847/2500] bytes, strings: optimize Trim for single byte cutsets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using the latest version of all modules known by the module proxy, we determine that for all Trim usages (and related functionality): * 76.6% have cutsets of len=1, and * 13.4% have cutsets of len=2. Given that a vast majority of usages only have a cutset of len=1, we should more heavily optimize for that situation. Previously, there was some optimization for cutsets of len=1, but it's within the internal makeCutsetFunc function. This is sub-optimal as it incurs an allocation in makeCutsetFunc for the closure over that single byte. This CL removes special-casing of one-byte cutsets from makeCutsetFunc and instead distributes it directly in Trim, TrimRight, and TrimLeft. Whether we should distribute the entire ASCII cutset logic into Trim is a future CL that should be discussed and handled separately. The evidence for multibyte cutsets is not as obviously compelling. name old time/op new time/op delta bytes/TrimByte-4 84.1ns ± 2% 7.5ns ± 1% -91.10% (p=0.000 n=9+7) strings/TrimByte-4 86.2ns ± 3% 8.3ns ± 1% -90.33% (p=0.000 n=9+10) Fixes #46446 Change-Id: Ia0e31a8384c3ce111ae35465605bcec45df2ebec Reviewed-on: https://go-review.googlesource.com/c/go/+/323318 Trust: Joe Tsai Run-TryBot: Joe Tsai Reviewed-by: Brad Fitzpatrick TryBot-Result: Go Bot --- src/bytes/bytes.go | 28 +++++++++++++++++++++++----- src/bytes/bytes_test.go | 9 +++++++++ src/strings/strings.go | 28 +++++++++++++++++++++++----- src/strings/strings_test.go | 9 +++++++++ 4 files changed, 64 insertions(+), 10 deletions(-) diff --git a/src/bytes/bytes.go b/src/bytes/bytes.go index ce52649f13..cd859d086d 100644 --- a/src/bytes/bytes.go +++ b/src/bytes/bytes.go @@ -888,11 +888,6 @@ func (as *asciiSet) contains(c byte) bool { } func makeCutsetFunc(cutset string) func(r rune) bool { - if len(cutset) == 1 && cutset[0] < utf8.RuneSelf { - return func(r rune) bool { - return r == rune(cutset[0]) - } - } if as, isASCII := makeASCIISet(cutset); isASCII { return func(r rune) bool { return r < utf8.RuneSelf && as.contains(byte(r)) @@ -911,21 +906,44 @@ func makeCutsetFunc(cutset string) func(r rune) bool { // Trim returns a subslice of s by slicing off all leading and // trailing UTF-8-encoded code points contained in cutset. func Trim(s []byte, cutset string) []byte { + if len(cutset) == 1 && cutset[0] < utf8.RuneSelf { + return trimLeftByte(trimRightByte(s, cutset[0]), cutset[0]) + } return TrimFunc(s, makeCutsetFunc(cutset)) } // TrimLeft returns a subslice of s by slicing off all leading // UTF-8-encoded code points contained in cutset. func TrimLeft(s []byte, cutset string) []byte { + if len(cutset) == 1 && cutset[0] < utf8.RuneSelf { + return trimLeftByte(s, cutset[0]) + } return TrimLeftFunc(s, makeCutsetFunc(cutset)) } +func trimLeftByte(s []byte, c byte) []byte { + for len(s) > 0 && s[0] == c { + s = s[1:] + } + return s +} + // TrimRight returns a subslice of s by slicing off all trailing // UTF-8-encoded code points that are contained in cutset. func TrimRight(s []byte, cutset string) []byte { + if len(cutset) == 1 && cutset[0] < utf8.RuneSelf { + return trimRightByte(s, cutset[0]) + } return TrimRightFunc(s, makeCutsetFunc(cutset)) } +func trimRightByte(s []byte, c byte) []byte { + for len(s) > 0 && s[len(s)-1] == c { + s = s[:len(s)-1] + } + return s +} + // TrimSpace returns a subslice of s by slicing off all leading and // trailing white space, as defined by Unicode. func TrimSpace(s []byte) []byte { diff --git a/src/bytes/bytes_test.go b/src/bytes/bytes_test.go index 544ee46f90..850b2ed061 100644 --- a/src/bytes/bytes_test.go +++ b/src/bytes/bytes_test.go @@ -1251,7 +1251,9 @@ var trimTests = []TrimTest{ {"TrimLeft", "abba", "ab", ""}, {"TrimRight", "abba", "ab", ""}, {"TrimLeft", "abba", "a", "bba"}, + {"TrimLeft", "abba", "b", "abba"}, {"TrimRight", "abba", "a", "abb"}, + {"TrimRight", "abba", "b", "abba"}, {"Trim", "", "<>", "tag"}, {"Trim", "* listitem", " *", "listitem"}, {"Trim", `"quote"`, `"`, "quote"}, @@ -1963,6 +1965,13 @@ func BenchmarkTrimASCII(b *testing.B) { } } +func BenchmarkTrimByte(b *testing.B) { + x := []byte(" the quick brown fox ") + for i := 0; i < b.N; i++ { + Trim(x, " ") + } +} + func BenchmarkIndexPeriodic(b *testing.B) { key := []byte{1, 1} for _, skip := range [...]int{2, 4, 8, 16, 32, 64} { diff --git a/src/strings/strings.go b/src/strings/strings.go index b429735fea..0df8d2eb28 100644 --- a/src/strings/strings.go +++ b/src/strings/strings.go @@ -818,11 +818,6 @@ func (as *asciiSet) contains(c byte) bool { } func makeCutsetFunc(cutset string) func(rune) bool { - if len(cutset) == 1 && cutset[0] < utf8.RuneSelf { - return func(r rune) bool { - return r == rune(cutset[0]) - } - } if as, isASCII := makeASCIISet(cutset); isASCII { return func(r rune) bool { return r < utf8.RuneSelf && as.contains(byte(r)) @@ -837,6 +832,9 @@ func Trim(s, cutset string) string { if s == "" || cutset == "" { return s } + if len(cutset) == 1 && cutset[0] < utf8.RuneSelf { + return trimLeftByte(trimRightByte(s, cutset[0]), cutset[0]) + } return TrimFunc(s, makeCutsetFunc(cutset)) } @@ -848,9 +846,19 @@ func TrimLeft(s, cutset string) string { if s == "" || cutset == "" { return s } + if len(cutset) == 1 && cutset[0] < utf8.RuneSelf { + return trimLeftByte(s, cutset[0]) + } return TrimLeftFunc(s, makeCutsetFunc(cutset)) } +func trimLeftByte(s string, c byte) string { + for len(s) > 0 && s[0] == c { + s = s[1:] + } + return s +} + // TrimRight returns a slice of the string s, with all trailing // Unicode code points contained in cutset removed. // @@ -859,9 +867,19 @@ func TrimRight(s, cutset string) string { if s == "" || cutset == "" { return s } + if len(cutset) == 1 && cutset[0] < utf8.RuneSelf { + return trimRightByte(s, cutset[0]) + } return TrimRightFunc(s, makeCutsetFunc(cutset)) } +func trimRightByte(s string, c byte) string { + for len(s) > 0 && s[len(s)-1] == c { + s = s[:len(s)-1] + } + return s +} + // TrimSpace returns a slice of the string s, with all leading // and trailing white space removed, as defined by Unicode. func TrimSpace(s string) string { diff --git a/src/strings/strings_test.go b/src/strings/strings_test.go index 09e5b27cc3..edc6c20590 100644 --- a/src/strings/strings_test.go +++ b/src/strings/strings_test.go @@ -808,7 +808,9 @@ var trimTests = []struct { {"TrimLeft", "abba", "ab", ""}, {"TrimRight", "abba", "ab", ""}, {"TrimLeft", "abba", "a", "bba"}, + {"TrimLeft", "abba", "b", "abba"}, {"TrimRight", "abba", "a", "abb"}, + {"TrimRight", "abba", "b", "abba"}, {"Trim", "", "<>", "tag"}, {"Trim", "* listitem", " *", "listitem"}, {"Trim", `"quote"`, `"`, "quote"}, @@ -1860,6 +1862,13 @@ func BenchmarkTrimASCII(b *testing.B) { } } +func BenchmarkTrimByte(b *testing.B) { + x := " the quick brown fox " + for i := 0; i < b.N; i++ { + Trim(x, " ") + } +} + func BenchmarkIndexPeriodic(b *testing.B) { key := "aa" for _, skip := range [...]int{2, 4, 8, 16, 32, 64} { -- GitLab From 6cf1d5d0fa1049e2910d048ce2b6b5a97fe6edc4 Mon Sep 17 00:00:00 2001 From: Jake Ciolek Date: Wed, 25 Aug 2021 12:36:17 +0200 Subject: [PATCH 0848/2500] cmd/compile: generic SSA rules for simplifying 2 and 3 operand integer arithmetic expressions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This applies the following generic integer addition/subtraction transformations: x - (x + y) = -y (x - y) - x = -y y + (x - y) = x y + (z + (x - y) = x + z There's over 40 unique functions matching in Go. Hits 2 funcs in the runtime itself: runtime.stackfree() runtime.runqdrain() Go binary size reduced by 0.05% on Linux x86_64. StackCopy bench (perflocked Cascade Lake x86): name old time/op new time/op delta StackCopyPtr-8 87.3ms ± 1% 86.9ms ± 0% -0.45% (p=0.000 n=20+20) StackCopy-8 77.6ms ± 1% 77.0ms ± 0% -0.76% (p=0.000 n=20+20) StackCopyNoCache-8 2.28ms ± 2% 2.26ms ± 2% -0.93% (p=0.008 n=19+20) test/bench/go1 benchmarks (perflocked Cascade Lake x86): name old time/op new time/op delta BinaryTree17-8 1.88s ± 1% 1.88s ± 0% ~ (p=0.373 n=15+12) Fannkuch11-8 2.31s ± 0% 2.35s ± 0% +1.52% (p=0.000 n=15+14) FmtFprintfEmpty-8 26.6ns ± 0% 26.6ns ± 0% ~ (p=0.081 n=14+13) FmtFprintfString-8 48.6ns ± 0% 50.0ns ± 0% +2.86% (p=0.000 n=15+14) FmtFprintfInt-8 56.9ns ± 0% 54.8ns ± 0% -3.70% (p=0.000 n=15+15) FmtFprintfIntInt-8 90.4ns ± 0% 88.8ns ± 0% -1.78% (p=0.000 n=15+15) FmtFprintfPrefixedInt-8 104ns ± 0% 104ns ± 0% ~ (p=0.905 n=14+13) FmtFprintfFloat-8 148ns ± 0% 144ns ± 0% -2.19% (p=0.000 n=14+15) FmtManyArgs-8 389ns ± 0% 390ns ± 0% +0.35% (p=0.000 n=12+15) GobDecode-8 3.90ms ± 1% 3.88ms ± 0% -0.49% (p=0.000 n=15+14) GobEncode-8 2.73ms ± 0% 2.73ms ± 0% ~ (p=0.425 n=15+14) Gzip-8 169ms ± 0% 168ms ± 0% -0.52% (p=0.000 n=13+13) Gunzip-8 24.7ms ± 0% 24.8ms ± 0% +0.61% (p=0.000 n=15+15) HTTPClientServer-8 60.5µs ± 6% 60.4µs ± 7% ~ (p=0.595 n=15+15) JSONEncode-8 6.97ms ± 1% 6.93ms ± 0% -0.69% (p=0.000 n=14+14) JSONDecode-8 31.2ms ± 1% 30.8ms ± 1% -1.27% (p=0.000 n=14+14) Mandelbrot200-8 3.87ms ± 0% 3.87ms ± 0% ~ (p=0.652 n=15+14) GoParse-8 2.65ms ± 2% 2.64ms ± 1% ~ (p=0.202 n=15+15) RegexpMatchEasy0_32-8 45.1ns ± 0% 45.9ns ± 0% +1.68% (p=0.000 n=14+15) RegexpMatchEasy0_1K-8 140ns ± 0% 139ns ± 0% -0.44% (p=0.000 n=15+14) RegexpMatchEasy1_32-8 40.9ns ± 3% 40.5ns ± 0% -0.88% (p=0.000 n=15+13) RegexpMatchEasy1_1K-8 215ns ± 1% 220ns ± 1% +2.27% (p=0.000 n=15+15) RegexpMatchMedium_32-8 783ns ± 7% 738ns ± 0% ~ (p=0.361 n=15+15) RegexpMatchMedium_1K-8 24.1µs ± 6% 23.4µs ± 6% -2.94% (p=0.004 n=15+15) RegexpMatchHard_32-8 1.10µs ± 1% 1.09µs ± 1% -0.40% (p=0.006 n=15+14) RegexpMatchHard_1K-8 33.0µs ± 0% 33.0µs ± 0% ~ (p=0.535 n=12+14) Revcomp-8 354ms ± 0% 353ms ± 0% -0.23% (p=0.002 n=15+13) Template-8 42.0ms ± 1% 41.8ms ± 2% -0.37% (p=0.023 n=14+15) TimeParse-8 181ns ± 0% 180ns ± 1% -0.18% (p=0.014 n=12+13) TimeFormat-8 240ns ± 0% 242ns ± 1% +0.69% (p=0.000 n=12+15) [Geo mean] 35.2µs 35.1µs -0.43% name old speed new speed delta GobDecode-8 197MB/s ± 1% 198MB/s ± 0% +0.49% (p=0.000 n=15+14) GobEncode-8 281MB/s ± 0% 281MB/s ± 0% ~ (p=0.419 n=15+14) Gzip-8 115MB/s ± 0% 115MB/s ± 0% +0.52% (p=0.000 n=13+13) Gunzip-8 786MB/s ± 0% 781MB/s ± 0% -0.60% (p=0.000 n=15+15) JSONEncode-8 278MB/s ± 1% 280MB/s ± 0% +0.69% (p=0.000 n=14+14) JSONDecode-8 62.3MB/s ± 1% 63.1MB/s ± 1% +1.29% (p=0.000 n=14+14) GoParse-8 21.9MB/s ± 2% 22.0MB/s ± 1% ~ (p=0.205 n=15+15) RegexpMatchEasy0_32-8 709MB/s ± 0% 697MB/s ± 0% -1.65% (p=0.000 n=14+15) RegexpMatchEasy0_1K-8 7.34GB/s ± 0% 7.37GB/s ± 0% +0.43% (p=0.000 n=15+15) RegexpMatchEasy1_32-8 783MB/s ± 2% 790MB/s ± 0% +0.88% (p=0.000 n=15+13) RegexpMatchEasy1_1K-8 4.77GB/s ± 1% 4.66GB/s ± 1% -2.23% (p=0.000 n=15+15) RegexpMatchMedium_32-8 41.0MB/s ± 7% 43.3MB/s ± 0% ~ (p=0.360 n=15+15) RegexpMatchMedium_1K-8 42.5MB/s ± 6% 43.8MB/s ± 6% +3.07% (p=0.004 n=15+15) RegexpMatchHard_32-8 29.2MB/s ± 1% 29.3MB/s ± 1% +0.41% (p=0.006 n=15+14) RegexpMatchHard_1K-8 31.1MB/s ± 0% 31.1MB/s ± 0% ~ (p=0.495 n=12+14) Revcomp-8 718MB/s ± 0% 720MB/s ± 0% +0.23% (p=0.002 n=15+13) Template-8 46.3MB/s ± 1% 46.4MB/s ± 2% +0.38% (p=0.021 n=14+15) [Geo mean] 205MB/s 206MB/s +0.57% Change-Id: Ibd1afdf8b6c0b08087dcc3acd8f943637eb95ac0 Reviewed-on: https://go-review.googlesource.com/c/go/+/344930 Reviewed-by: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Trust: Josh Bleecher Snyder --- .../compile/internal/ssa/gen/generic.rules | 4 + .../compile/internal/ssa/rewritegeneric.go | 328 ++++++++++++++++++ test/codegen/arithmetic.go | 24 ++ 3 files changed, 356 insertions(+) diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules index 5cbc70cf41..e7ee3d0efd 100644 --- a/src/cmd/compile/internal/ssa/gen/generic.rules +++ b/src/cmd/compile/internal/ssa/gen/generic.rules @@ -590,6 +590,10 @@ // simplifications often used for lengths. e.g. len(s[i:i+5])==5 (Sub(64|32|16|8) (Add(64|32|16|8) x y) x) => y (Sub(64|32|16|8) (Add(64|32|16|8) x y) y) => x +(Sub(64|32|16|8) (Sub(64|32|16|8) x y) x) => (Neg(64|32|16|8) y) +(Sub(64|32|16|8) x (Add(64|32|16|8) x y)) => (Neg(64|32|16|8) y) +(Add(64|32|16|8) x (Sub(64|32|16|8) y x)) => y +(Add(64|32|16|8) x (Add(64|32|16|8) y (Sub(64|32|16|8) z x))) => (Add(64|32|16|8) y z) // basic phi simplifications (Phi (Const8 [c]) (Const8 [c])) => (Const8 [c]) diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index 52258201ca..e2f9e3ebba 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -533,6 +533,52 @@ func rewriteValuegeneric_OpAdd16(v *Value) bool { } break } + // match: (Add16 x (Sub16 y x)) + // result: y + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpSub16 { + continue + } + _ = v_1.Args[1] + y := v_1.Args[0] + if x != v_1.Args[1] { + continue + } + v.copyOf(y) + return true + } + break + } + // match: (Add16 x (Add16 y (Sub16 z x))) + // result: (Add16 y z) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpAdd16 { + continue + } + _ = v_1.Args[1] + v_1_0 := v_1.Args[0] + v_1_1 := v_1.Args[1] + for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 { + y := v_1_0 + if v_1_1.Op != OpSub16 { + continue + } + _ = v_1_1.Args[1] + z := v_1_1.Args[0] + if x != v_1_1.Args[1] { + continue + } + v.reset(OpAdd16) + v.AddArg2(y, z) + return true + } + } + break + } // match: (Add16 (Add16 i:(Const16 ) z) x) // cond: (z.Op != OpConst16 && x.Op != OpConst16) // result: (Add16 i (Add16 z x)) @@ -732,6 +778,52 @@ func rewriteValuegeneric_OpAdd32(v *Value) bool { } break } + // match: (Add32 x (Sub32 y x)) + // result: y + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpSub32 { + continue + } + _ = v_1.Args[1] + y := v_1.Args[0] + if x != v_1.Args[1] { + continue + } + v.copyOf(y) + return true + } + break + } + // match: (Add32 x (Add32 y (Sub32 z x))) + // result: (Add32 y z) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpAdd32 { + continue + } + _ = v_1.Args[1] + v_1_0 := v_1.Args[0] + v_1_1 := v_1.Args[1] + for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 { + y := v_1_0 + if v_1_1.Op != OpSub32 { + continue + } + _ = v_1_1.Args[1] + z := v_1_1.Args[0] + if x != v_1_1.Args[1] { + continue + } + v.reset(OpAdd32) + v.AddArg2(y, z) + return true + } + } + break + } // match: (Add32 (Add32 i:(Const32 ) z) x) // cond: (z.Op != OpConst32 && x.Op != OpConst32) // result: (Add32 i (Add32 z x)) @@ -958,6 +1050,52 @@ func rewriteValuegeneric_OpAdd64(v *Value) bool { } break } + // match: (Add64 x (Sub64 y x)) + // result: y + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpSub64 { + continue + } + _ = v_1.Args[1] + y := v_1.Args[0] + if x != v_1.Args[1] { + continue + } + v.copyOf(y) + return true + } + break + } + // match: (Add64 x (Add64 y (Sub64 z x))) + // result: (Add64 y z) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpAdd64 { + continue + } + _ = v_1.Args[1] + v_1_0 := v_1.Args[0] + v_1_1 := v_1.Args[1] + for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 { + y := v_1_0 + if v_1_1.Op != OpSub64 { + continue + } + _ = v_1_1.Args[1] + z := v_1_1.Args[0] + if x != v_1_1.Args[1] { + continue + } + v.reset(OpAdd64) + v.AddArg2(y, z) + return true + } + } + break + } // match: (Add64 (Add64 i:(Const64 ) z) x) // cond: (z.Op != OpConst64 && x.Op != OpConst64) // result: (Add64 i (Add64 z x)) @@ -1184,6 +1322,52 @@ func rewriteValuegeneric_OpAdd8(v *Value) bool { } break } + // match: (Add8 x (Sub8 y x)) + // result: y + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpSub8 { + continue + } + _ = v_1.Args[1] + y := v_1.Args[0] + if x != v_1.Args[1] { + continue + } + v.copyOf(y) + return true + } + break + } + // match: (Add8 x (Add8 y (Sub8 z x))) + // result: (Add8 y z) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpAdd8 { + continue + } + _ = v_1.Args[1] + v_1_0 := v_1.Args[0] + v_1_1 := v_1.Args[1] + for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 { + y := v_1_0 + if v_1_1.Op != OpSub8 { + continue + } + _ = v_1_1.Args[1] + z := v_1_1.Args[0] + if x != v_1_1.Args[1] { + continue + } + v.reset(OpAdd8) + v.AddArg2(y, z) + return true + } + } + break + } // match: (Add8 (Add8 i:(Const8 ) z) x) // cond: (z.Op != OpConst8 && x.Op != OpConst8) // result: (Add8 i (Add8 z x)) @@ -22590,6 +22774,42 @@ func rewriteValuegeneric_OpSub16(v *Value) bool { } break } + // match: (Sub16 (Sub16 x y) x) + // result: (Neg16 y) + for { + if v_0.Op != OpSub16 { + break + } + y := v_0.Args[1] + x := v_0.Args[0] + if x != v_1 { + break + } + v.reset(OpNeg16) + v.AddArg(y) + return true + } + // match: (Sub16 x (Add16 x y)) + // result: (Neg16 y) + for { + x := v_0 + if v_1.Op != OpAdd16 { + break + } + _ = v_1.Args[1] + v_1_0 := v_1.Args[0] + v_1_1 := v_1.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 { + if x != v_1_0 { + continue + } + y := v_1_1 + v.reset(OpNeg16) + v.AddArg(y) + return true + } + break + } // match: (Sub16 x (Sub16 i:(Const16 ) z)) // cond: (z.Op != OpConst16 && x.Op != OpConst16) // result: (Sub16 (Add16 x z) i) @@ -22869,6 +23089,42 @@ func rewriteValuegeneric_OpSub32(v *Value) bool { } break } + // match: (Sub32 (Sub32 x y) x) + // result: (Neg32 y) + for { + if v_0.Op != OpSub32 { + break + } + y := v_0.Args[1] + x := v_0.Args[0] + if x != v_1 { + break + } + v.reset(OpNeg32) + v.AddArg(y) + return true + } + // match: (Sub32 x (Add32 x y)) + // result: (Neg32 y) + for { + x := v_0 + if v_1.Op != OpAdd32 { + break + } + _ = v_1.Args[1] + v_1_0 := v_1.Args[0] + v_1_1 := v_1.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 { + if x != v_1_0 { + continue + } + y := v_1_1 + v.reset(OpNeg32) + v.AddArg(y) + return true + } + break + } // match: (Sub32 x (Sub32 i:(Const32 ) z)) // cond: (z.Op != OpConst32 && x.Op != OpConst32) // result: (Sub32 (Add32 x z) i) @@ -23172,6 +23428,42 @@ func rewriteValuegeneric_OpSub64(v *Value) bool { } break } + // match: (Sub64 (Sub64 x y) x) + // result: (Neg64 y) + for { + if v_0.Op != OpSub64 { + break + } + y := v_0.Args[1] + x := v_0.Args[0] + if x != v_1 { + break + } + v.reset(OpNeg64) + v.AddArg(y) + return true + } + // match: (Sub64 x (Add64 x y)) + // result: (Neg64 y) + for { + x := v_0 + if v_1.Op != OpAdd64 { + break + } + _ = v_1.Args[1] + v_1_0 := v_1.Args[0] + v_1_1 := v_1.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 { + if x != v_1_0 { + continue + } + y := v_1_1 + v.reset(OpNeg64) + v.AddArg(y) + return true + } + break + } // match: (Sub64 x (Sub64 i:(Const64 ) z)) // cond: (z.Op != OpConst64 && x.Op != OpConst64) // result: (Sub64 (Add64 x z) i) @@ -23475,6 +23767,42 @@ func rewriteValuegeneric_OpSub8(v *Value) bool { } break } + // match: (Sub8 (Sub8 x y) x) + // result: (Neg8 y) + for { + if v_0.Op != OpSub8 { + break + } + y := v_0.Args[1] + x := v_0.Args[0] + if x != v_1 { + break + } + v.reset(OpNeg8) + v.AddArg(y) + return true + } + // match: (Sub8 x (Add8 x y)) + // result: (Neg8 y) + for { + x := v_0 + if v_1.Op != OpAdd8 { + break + } + _ = v_1.Args[1] + v_1_0 := v_1.Args[0] + v_1_1 := v_1.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 { + if x != v_1_0 { + continue + } + y := v_1_1 + v.reset(OpNeg8) + v.AddArg(y) + return true + } + break + } // match: (Sub8 x (Sub8 i:(Const8 ) z)) // cond: (z.Op != OpConst8 && x.Op != OpConst8) // result: (Sub8 (Add8 x z) i) diff --git a/test/codegen/arithmetic.go b/test/codegen/arithmetic.go index eb0f338036..eb95416b6a 100644 --- a/test/codegen/arithmetic.go +++ b/test/codegen/arithmetic.go @@ -84,6 +84,30 @@ func NegAddFromConstNeg(a int) int { return c } +func SubSubNegSimplify(a, b int) int { + // amd64:"NEGQ" + r := (a - b) - a + return r +} + +func SubAddSimplify(a, b int) int { + // amd64:-"SUBQ",-"ADDQ" + r := a + (b - a) + return r +} + +func SubAddNegSimplify(a, b int) int { + // amd64:"NEGQ",-"ADDQ",-"SUBQ" + r := a - (b + a) + return r +} + +func AddAddSubSimplify(a, b, c int) int { + // amd64:-"SUBQ" + r := a + (b + (c - a)) + return r +} + // -------------------- // // Multiplication // // -------------------- // -- GitLab From 647bef6c59e201792688d88cdc50ea0c6a68990b Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 24 Aug 2021 09:28:43 -0700 Subject: [PATCH 0849/2500] go/types: implement NewTypeList and use it instead of composite literals Also, simplify a bit of code in predicates.go. This is a backport of changes in CL 344615 that were made in addition to the changes of the original CL 343933; it brings go/types in sync with types2. Change-Id: I14cd4d4704d29894d0fbb8d129744d65e332ad22 Reviewed-on: https://go-review.googlesource.com/c/go/+/344570 Trust: Robert Griesemer Trust: Dan Scales Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/go/types/check.go | 2 +- src/go/types/instantiate.go | 2 +- src/go/types/predicates.go | 8 +++----- src/go/types/subst.go | 2 +- src/go/types/typelists.go | 8 ++++++++ 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/go/types/check.go b/src/go/types/check.go index 909bf8d52d..ab3a388e9f 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -407,7 +407,7 @@ func (check *Checker) recordInferred(call ast.Expr, targs []Type, sig *Signature assert(call != nil) assert(sig != nil) if m := check.Inferred; m != nil { - m[call] = Inferred{&TypeList{targs}, sig} + m[call] = Inferred{NewTypeList(targs), sig} } } diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 3ee09b7e84..5f691d5246 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -131,7 +131,7 @@ func (check *Checker) instance(pos token.Pos, typ Type, targs []Type) (res Type) tname := NewTypeName(pos, t.obj.pkg, t.obj.name, nil) named := check.newNamed(tname, t, nil, nil, nil) // methods and tparams are set when named is loaded - named.targs = &TypeList{targs} + named.targs = NewTypeList(targs) named.instance = &instance{pos} if check != nil { check.typMap[h] = named diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 2f4ef9dace..d4055bb0cc 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -312,16 +312,14 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { return false } - if nargs := len(xargs); nargs > 0 { + if len(xargs) > 0 { // Instances are identical if their original type and type arguments // are identical. if !Identical(x.orig, y.orig) { return false } - for i := 0; i < nargs; i++ { - xa := xargs[i] - ya := yargs[i] - if !Identical(xa, ya) { + for i, xa := range xargs { + if !Identical(xa, yargs[i]) { return false } } diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 8b8d6fb82a..1c53cdaf2c 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -233,7 +233,7 @@ func (subst *subster) typ(typ Type) Type { // It's ok to provide a nil *Checker because the newly created type // doesn't need to be (lazily) expanded; it's expanded below. named := (*Checker)(nil).newNamed(tname, t.orig, nil, t.tparams, t.methods) // t is loaded, so tparams and methods are available - named.targs = &TypeList{newTArgs} + named.targs = NewTypeList(newTArgs) subst.typMap[h] = named t.expand(subst.typMap) // must happen after typMap update to avoid infinite recursion diff --git a/src/go/types/typelists.go b/src/go/types/typelists.go index a8181404bf..ef8ea1f32b 100644 --- a/src/go/types/typelists.go +++ b/src/go/types/typelists.go @@ -27,6 +27,14 @@ func (l *TParamList) list() []*TypeParam { // TypeList holds a list of types. type TypeList struct{ types []Type } +// NewTypeList returns a new TypeList with the types in list. +func NewTypeList(list []Type) *TypeList { + if len(list) == 0 { + return nil + } + return &TypeList{list} +} + // Len returns the number of types in the list. // It is safe to call on a nil receiver. func (l *TypeList) Len() int { return len(l.list()) } -- GitLab From 4158e88f64f34d1d0bab1d54be6be72a598ca41f Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 24 Aug 2021 12:23:28 -0700 Subject: [PATCH 0850/2500] cmd/compile/internal/syntax: fix position of type parameter field Change-Id: I8bca01b935301e7bd4efa55ed21921dbf31a75b9 Reviewed-on: https://go-review.googlesource.com/c/go/+/344575 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/syntax/parser.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index c477ddd45d..fd97279f9d 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -1840,7 +1840,11 @@ func (p *parser) paramDeclOrNil(name *Name) *Field { } f := new(Field) - f.pos = p.pos() + if name != nil { + f.pos = name.pos + } else { + f.pos = p.pos() + } if p.tok == _Name || name != nil { if name == nil { -- GitLab From bf0bc4122fd4b3a75c2f9c107895cd5e2f89b90e Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 24 Aug 2021 13:52:07 -0700 Subject: [PATCH 0851/2500] go/types, types2: don't re-evaluate context string for each function argument (optimization) Change-Id: Ie1b4d5b64350ea42484adea14df84cacd1d2653b Reviewed-on: https://go-review.googlesource.com/c/go/+/344576 Trust: Robert Griesemer Trust: Dan Scales Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/types2/call.go | 7 +++++-- src/go/types/call.go | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 538fdc0fb7..4bbc524856 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -341,8 +341,11 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T } // check arguments - for i, a := range args { - check.assignment(a, sigParams.vars[i].typ, check.sprintf("argument to %s", call.Fun)) + if len(args) > 0 { + context := check.sprintf("argument to %s", call.Fun) + for i, a := range args { + check.assignment(a, sigParams.vars[i].typ, context) + } } return diff --git a/src/go/types/call.go b/src/go/types/call.go index 87eeef444b..fdecafb781 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -347,8 +347,11 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type } // check arguments - for i, a := range args { - check.assignment(a, sigParams.vars[i].typ, check.sprintf("argument to %s", call.Fun)) + if len(args) > 0 { + context := check.sprintf("argument to %s", call.Fun) + for i, a := range args { + check.assignment(a, sigParams.vars[i].typ, context) + } } return -- GitLab From 4068fb6c2162b38db7912903ff12bafe9f5ca9bb Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 24 Aug 2021 18:07:42 -0700 Subject: [PATCH 0852/2500] cmd/compile: always accept 1.18 syntax but complain if not 1.18 This CL configures the parser to always accept 1.18 syntax (type parameters, type instantiations, interface elements), even when -lang is set to an earlier release. Instead, the type checker looks for 1.18 operations and complains if the language version is set to an earlier release. Doing these checks during type checking is necessary because it it is possible to write "generic" code using pre-1.18 syntax; for instance, an imported generic function may be implicitly instantiated (as in imported.Max(2, 3)), or an imported constraint interface may be embedded in an "ordinary" interface. Fixes #47818. Change-Id: I83ec302b3f4ba7196c0a4743c03670cfb901310d Reviewed-on: https://go-review.googlesource.com/c/go/+/344871 Trust: Robert Griesemer Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/noder/noder.go | 2 +- src/cmd/compile/internal/types2/call.go | 11 ++++ src/cmd/compile/internal/types2/decl.go | 23 +++++++- src/cmd/compile/internal/types2/resolver.go | 40 ++++++++----- src/cmd/compile/internal/types2/subst.go | 2 +- .../internal/types2/testdata/check/decls0.src | 2 +- .../internal/types2/testdata/check/issues.src | 6 +- .../internal/types2/testdata/check/main.go2 | 2 +- .../types2/testdata/check/typeparams.go2 | 4 +- .../types2/testdata/fixedbugs/issue47818.go2 | 59 +++++++++++++++++++ src/cmd/compile/internal/types2/typeset.go | 11 +++- src/cmd/compile/internal/types2/typexpr.go | 15 ++--- test/fixedbugs/issue10975.go | 2 +- 13 files changed, 142 insertions(+), 37 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2 diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index 2b67a91b3f..e1b485b2b3 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -35,7 +35,7 @@ func LoadPackage(filenames []string) { supportsGenerics := base.Flag.G != 0 || buildcfg.Experiment.Unified mode := syntax.CheckBranches - if supportsGenerics && types.AllowsGoVersion(types.LocalPkg, 1, 18) { + if supportsGenerics { mode |= syntax.AllowGenerics } diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 4bbc524856..0b062b4c94 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -15,6 +15,10 @@ import ( // funcInst type-checks a function instantiation inst and returns the result in x. // The operand x must be the evaluation of inst.X and its type must be a signature. func (check *Checker) funcInst(x *operand, inst *syntax.IndexExpr) { + if !check.allowVersion(check.pkg, 1, 18) { + check.softErrorf(inst.Pos(), "function instantiation requires go1.18 or later") + } + xlist := unpackExpr(inst.Index) targs := check.typeList(xlist) if targs == nil { @@ -318,6 +322,13 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T // infer type arguments and instantiate signature if necessary if sig.TParams().Len() > 0 { + if !check.allowVersion(check.pkg, 1, 18) { + if iexpr, _ := call.Fun.(*syntax.IndexExpr); iexpr != nil { + check.softErrorf(iexpr.Pos(), "function instantiation requires go1.18 or later") + } else { + check.softErrorf(call.Pos(), "implicit function instantiation requires go1.18 or later") + } + } // TODO(gri) provide position information for targs so we can feed // it to the instantiate call for better error reporting targs := check.infer(call.Pos(), sig.TParams().list(), targs, sigParams, args, true) diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 342e1090de..d7a33546aa 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -514,11 +514,26 @@ func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init syntax.Expr) { check.initVars(lhs, []syntax.Expr{init}, nopos) } +// isImportedConstraint reports whether typ is an imported type constraint. +func (check *Checker) isImportedConstraint(typ Type) bool { + named, _ := typ.(*Named) + if named == nil || named.obj.pkg == check.pkg || named.obj.pkg == nil { + return false + } + u, _ := named.under().(*Interface) + return u != nil && u.IsConstraint() +} + func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named) { assert(obj.typ == nil) + var rhs Type check.later(func() { check.validType(obj.typ, nil) + // If typ is local, an error was already reported where typ is specified/defined. + if check.isImportedConstraint(rhs) && !check.allowVersion(check.pkg, 1, 18) { + check.errorf(tdecl.Type.Pos(), "using type constraint %s requires go1.18 or later", rhs) + } }) alias := tdecl.Alias @@ -540,7 +555,8 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named } obj.typ = Typ[Invalid] - obj.typ = check.anyType(tdecl.Type) + rhs = check.anyType(tdecl.Type) + obj.typ = rhs return } @@ -555,8 +571,9 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named } // determine underlying type of named - named.fromRHS = check.definedType(tdecl.Type, named) - assert(named.fromRHS != nil) + rhs = check.definedType(tdecl.Type, named) + assert(rhs != nil) + named.fromRHS = rhs // The underlying type of named may be itself a named type that is // incomplete: // diff --git a/src/cmd/compile/internal/types2/resolver.go b/src/cmd/compile/internal/types2/resolver.go index 018a20cfb2..34fbc3d41b 100644 --- a/src/cmd/compile/internal/types2/resolver.go +++ b/src/cmd/compile/internal/types2/resolver.go @@ -412,52 +412,60 @@ func (check *Checker) collectObjects() { } case *syntax.TypeDecl: + if len(s.TParamList) != 0 && !check.allowVersion(pkg, 1, 18) { + check.softErrorf(s.TParamList[0], "type parameters require go1.18 or later") + } obj := NewTypeName(s.Name.Pos(), pkg, s.Name.Value, nil) check.declarePkgObj(s.Name, obj, &declInfo{file: fileScope, tdecl: s}) case *syntax.FuncDecl: - d := s // TODO(gri) get rid of this - name := d.Name.Value - obj := NewFunc(d.Name.Pos(), pkg, name, nil) - if d.Recv == nil { + name := s.Name.Value + obj := NewFunc(s.Name.Pos(), pkg, name, nil) + hasTParamError := false // avoid duplicate type parameter errors + if s.Recv == nil { // regular function if name == "init" || name == "main" && pkg.name == "main" { - if d.TParamList != nil { - check.softErrorf(d, "func %s must have no type parameters", name) + if len(s.TParamList) != 0 { + check.softErrorf(s.TParamList[0], "func %s must have no type parameters", name) + hasTParamError = true } - if t := d.Type; len(t.ParamList) != 0 || len(t.ResultList) != 0 { - check.softErrorf(d, "func %s must have no arguments and no return values", name) + if t := s.Type; len(t.ParamList) != 0 || len(t.ResultList) != 0 { + check.softErrorf(s, "func %s must have no arguments and no return values", name) } } // don't declare init functions in the package scope - they are invisible if name == "init" { obj.parent = pkg.scope - check.recordDef(d.Name, obj) + check.recordDef(s.Name, obj) // init functions must have a body - if d.Body == nil { + if s.Body == nil { // TODO(gri) make this error message consistent with the others above check.softErrorf(obj.pos, "missing function body") } } else { - check.declare(pkg.scope, d.Name, obj, nopos) + check.declare(pkg.scope, s.Name, obj, nopos) } } else { // method // d.Recv != nil - if !acceptMethodTypeParams && len(d.TParamList) != 0 { + if !acceptMethodTypeParams && len(s.TParamList) != 0 { //check.error(d.TParamList.Pos(), invalidAST + "method must have no type parameters") - check.error(d, invalidAST+"method must have no type parameters") + check.error(s.TParamList[0], invalidAST+"method must have no type parameters") + hasTParamError = true } - ptr, recv, _ := check.unpackRecv(d.Recv.Type, false) + ptr, recv, _ := check.unpackRecv(s.Recv.Type, false) // (Methods with invalid receiver cannot be associated to a type, and // methods with blank _ names are never found; no need to collect any // of them. They will still be type-checked with all the other functions.) if recv != nil && name != "_" { methods = append(methods, methodInfo{obj, ptr, recv}) } - check.recordDef(d.Name, obj) + check.recordDef(s.Name, obj) + } + if len(s.TParamList) != 0 && !check.allowVersion(pkg, 1, 18) && !hasTParamError { + check.softErrorf(s.TParamList[0], "type parameters require go1.18 or later") } - info := &declInfo{file: fileScope, fdecl: d} + info := &declInfo{file: fileScope, fdecl: s} // Methods are not package-level objects but we still track them in the // object map so that we can handle them like regular functions (if the // receiver is invalid); also we need their fdecl info when associating diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 918e5f3043..ff8dd13b6d 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -38,7 +38,7 @@ func (m substMap) lookup(tpar *TypeParam) Type { // subst returns the type typ with its type parameters tpars replaced by the // corresponding type arguments targs, recursively. subst doesn't modify the // incoming type. If a substitution took place, the result type is different -// from from the incoming type. +// from the incoming type. // // If the given typMap is non-nil, it is used in lieu of check.typMap. func (check *Checker) subst(pos syntax.Pos, typ Type, smap substMap, typMap map[string]*Named) Type { diff --git a/src/cmd/compile/internal/types2/testdata/check/decls0.src b/src/cmd/compile/internal/types2/testdata/check/decls0.src index f051a4f2ac..09e5d5c5ad 100644 --- a/src/cmd/compile/internal/types2/testdata/check/decls0.src +++ b/src/cmd/compile/internal/types2/testdata/check/decls0.src @@ -146,7 +146,7 @@ type ( m1(I5) } I6 interface { - S0 /* ERROR "not an interface" */ + S0 /* ERROR "non-interface type S0" */ } I7 interface { I1 diff --git a/src/cmd/compile/internal/types2/testdata/check/issues.src b/src/cmd/compile/internal/types2/testdata/check/issues.src index 692ed37ef4..d83a95af0e 100644 --- a/src/cmd/compile/internal/types2/testdata/check/issues.src +++ b/src/cmd/compile/internal/types2/testdata/check/issues.src @@ -79,11 +79,11 @@ func issue9473(a []int, b ...int) { // Check that embedding a non-interface type in an interface results in a good error message. func issue10979() { type _ interface { - int /* ERROR int is not an interface */ + int /* ERROR non-interface type int */ } type T struct{} type _ interface { - T /* ERROR T is not an interface */ + T /* ERROR non-interface type T */ } type _ interface { nosuchtype /* ERROR undeclared name: nosuchtype */ @@ -280,7 +280,7 @@ type issue25301b /* ERROR cycle */ = interface { } type issue25301c interface { - notE // ERROR struct\{\} is not an interface + notE // ERROR non-interface type struct\{\} } type notE = struct{} diff --git a/src/cmd/compile/internal/types2/testdata/check/main.go2 b/src/cmd/compile/internal/types2/testdata/check/main.go2 index b7ddeaa1a8..395e3bfec8 100644 --- a/src/cmd/compile/internal/types2/testdata/check/main.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/main.go2 @@ -4,4 +4,4 @@ package main -func /* ERROR "func main must have no type parameters" */ main[T any]() {} +func main [T /* ERROR "func main must have no type parameters" */ any]() {} diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 index 1ad80b1e1b..765d561f3b 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 @@ -304,8 +304,8 @@ var _ = f8[int, float64](0, 0, nil...) // test case for #18268 // init functions cannot have type parameters func init() {} -func init[/* ERROR func init must have no type parameters */ _ any]() {} -func init[/* ERROR func init must have no type parameters */ P any]() {} +func init[_ /* ERROR func init must have no type parameters */ any]() {} +func init[P /* ERROR func init must have no type parameters */ any]() {} type T struct {} diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2 new file mode 100644 index 0000000000..5334695b5e --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2 @@ -0,0 +1,59 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Parser accepts type parameters but the type checker +// needs to report any operations that are not permitted +// before Go 1.18. + +package go1_17 + +type T[P /* ERROR type parameters require go1\.18 or later */ any] struct{} + +// for init (and main, but we're not in package main) we should only get one error +func init[P /* ERROR func init must have no type parameters */ any]() {} +func main[P /* ERROR type parameters require go1\.18 or later */ any]() {} + +func f[P /* ERROR type parameters require go1\.18 or later */ any](x P) { + var _ T[ /* ERROR type instantiation requires go1\.18 or later */ int] + var _ (T[ /* ERROR type instantiation requires go1\.18 or later */ int]) + _ = T[ /* ERROR type instantiation requires go1\.18 or later */ int]{} + _ = T[ /* ERROR type instantiation requires go1\.18 or later */ int](struct{}{}) +} + +func (T[ /* ERROR type instantiation requires go1\.18 or later */ P]) g(x int) { + f[ /* ERROR function instantiation requires go1\.18 or later */ int](0) // explicit instantiation + (f[ /* ERROR function instantiation requires go1\.18 or later */ int])(0) // parentheses (different code path) + f( /* ERROR implicit function instantiation requires go1\.18 or later */ x) // implicit instantiation +} + +type C1 interface { + comparable // ERROR undeclared name: comparable \(requires version go1\.18 or later\) +} + +type C2 interface { + comparable // ERROR undeclared name: comparable \(requires version go1\.18 or later\) + int // ERROR embedding non-interface type int requires go1\.18 or later + ~ /* ERROR embedding interface element ~int requires go1\.18 or later */ int + int /* ERROR embedding interface element int\|~string requires go1\.18 or later */ | ~string +} + +type _ interface { + // errors for these were reported with their declaration + C1 + C2 +} + +type ( + _ comparable // ERROR undeclared name: comparable \(requires version go1\.18 or later\) + // errors for these were reported with their declaration + _ C1 + _ C2 + + _ = comparable // ERROR undeclared name: comparable \(requires version go1\.18 or later\) + // errors for these were reported with their declaration + _ = C1 + _ = C2 +) + +// TODO(gri) need test cases for imported constraint types (see also issue #47967) \ No newline at end of file diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index 14596b68a3..56f64ab405 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -271,6 +271,11 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_ switch u := under(typ).(type) { case *Interface: tset := computeInterfaceTypeSet(check, pos, u) + // If typ is local, an error was already reported where typ is specified/defined. + if check != nil && check.isImportedConstraint(typ) && !check.allowVersion(check.pkg, 1, 18) { + check.errorf(pos, "embedding constraint interface %s requires go1.18 or later", typ) + continue + } if tset.comparable { ityp.tset.comparable = true } @@ -279,6 +284,10 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_ } terms = tset.terms case *Union: + if check != nil && !check.allowVersion(check.pkg, 1, 18) { + check.errorf(pos, "embedding interface element %s requires go1.18 or later", u) + continue + } tset := computeUnionTypeSet(check, pos, u) if tset == &invalidTypeSet { continue // ignore invalid unions @@ -293,7 +302,7 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_ continue } if check != nil && !check.allowVersion(check.pkg, 1, 18) { - check.errorf(pos, "%s is not an interface", typ) + check.errorf(pos, "embedding non-interface type %s requires go1.18 or later", typ) continue } terms = termlist{{false, typ}} diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 241c6d35fe..f3e415e4c7 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -38,14 +38,12 @@ func (check *Checker) ident(x *operand, e *syntax.Name, def *Named, wantType boo } return case universeAny, universeComparable: + // complain if necessary but keep going if !check.allowVersion(check.pkg, 1, 18) { - check.errorf(e, "undeclared name: %s (requires version go1.18 or later)", e.Value) - return - } - // If we allow "any" for general use, this if-statement can be removed (issue #33232). - if obj == universeAny { - check.error(e, "cannot use any outside constraint position") - return + check.softErrorf(e, "undeclared name: %s (requires version go1.18 or later)", e.Value) + } else if obj == universeAny { + // If we allow "any" for general use, this if-statement can be removed (issue #33232). + check.softErrorf(e, "cannot use any outside constraint position") } } check.recordUse(e, obj) @@ -274,6 +272,9 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) { } case *syntax.IndexExpr: + if !check.allowVersion(check.pkg, 1, 18) { + check.softErrorf(e.Pos(), "type instantiation requires go1.18 or later") + } return check.instantiatedType(e.X, unpackExpr(e.Index), def) case *syntax.ParenExpr: diff --git a/test/fixedbugs/issue10975.go b/test/fixedbugs/issue10975.go index 876ea58ef9..a58ccce2db 100644 --- a/test/fixedbugs/issue10975.go +++ b/test/fixedbugs/issue10975.go @@ -10,7 +10,7 @@ package main type I interface { - int // ERROR "interface contains embedded non-interface|not an interface" + int // ERROR "interface contains embedded non-interface|embedding non-interface type" } func New() I { -- GitLab From 0ac64f6d700b56fa793d9304bec621cf4dde6fd6 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 24 Aug 2021 20:20:07 -0700 Subject: [PATCH 0853/2500] cmd/compile/internal/types2: rename IsMethodSet to IsConstraint (cleanup) Invert the boolean result to match the new name. Change-Id: Ide6c649ed8ac3a5d263640309960e61a005c886e Reviewed-on: https://go-review.googlesource.com/c/go/+/344872 Trust: Robert Griesemer Trust: Dan Scales Reviewed-by: Dan Scales --- src/cmd/compile/internal/types2/interface.go | 2 +- src/cmd/compile/internal/types2/typeset.go | 6 ++---- src/cmd/compile/internal/types2/typexpr.go | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index ccd3de0a6e..e57158d2d5 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -98,7 +98,7 @@ func (t *Interface) Empty() bool { return t.typeSet().IsAll() } func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() } // IsConstraint reports whether interface t is not just a method set. -func (t *Interface) IsConstraint() bool { return !t.typeSet().IsMethodSet() } +func (t *Interface) IsConstraint() bool { return t.typeSet().IsConstraint() } func (t *Interface) Underlying() Type { return t } func (t *Interface) String() string { return TypeString(t, nil) } diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index 56f64ab405..1673b9b4af 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -30,10 +30,8 @@ func (s *_TypeSet) IsAll() bool { return !s.comparable && len(s.methods) == 0 && s.terms.isAll() } -// TODO(gri) IsMethodSet is not a great name for this predicate. Find a better one. - -// IsMethodSet reports whether the type set s is described by a single set of methods. -func (s *_TypeSet) IsMethodSet() bool { return !s.comparable && s.terms.isAll() } +// IsConstraint reports whether type set s is not just a set of methods. +func (s *_TypeSet) IsConstraint() bool { return s.comparable || !s.terms.isAll() } // IsComparable reports whether each type in the set is comparable. func (s *_TypeSet) IsComparable() bool { diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index f3e415e4c7..6938648bbc 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -151,7 +151,7 @@ func (check *Checker) ordinaryType(pos syntax.Pos, typ Type) { check.later(func() { if t := asInterface(typ); t != nil { tset := computeInterfaceTypeSet(check, pos, t) // TODO(gri) is this the correct position? - if !tset.IsMethodSet() { + if tset.IsConstraint() { if tset.comparable { check.softErrorf(pos, "interface is (or embeds) comparable") } else { -- GitLab From 4f2620285d7ce1802aff3d1f85e5ab0168d57bf3 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 24 Aug 2021 21:12:06 -0700 Subject: [PATCH 0854/2500] cmd/compile/internal/types2: fix type set printing and add test Change-Id: I44ca1f889b041467d5febacaf6037cfd75859175 Reviewed-on: https://go-review.googlesource.com/c/go/+/344873 Trust: Robert Griesemer Trust: Dan Scales Reviewed-by: Dan Scales --- src/cmd/compile/internal/types2/typeset.go | 12 ++-- .../compile/internal/types2/typeset_test.go | 67 ++++++++++++++++++- 2 files changed, 71 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index 1673b9b4af..ae39f26e4f 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -77,26 +77,24 @@ func (s *_TypeSet) String() string { var buf bytes.Buffer buf.WriteByte('{') if s.comparable { - buf.WriteString(" comparable") + buf.WriteString("comparable") if hasMethods || hasTerms { - buf.WriteByte(';') + buf.WriteString("; ") } } for i, m := range s.methods { if i > 0 { - buf.WriteByte(';') + buf.WriteString("; ") } - buf.WriteByte(' ') buf.WriteString(m.String()) } if hasMethods && hasTerms { - buf.WriteByte(';') + buf.WriteString("; ") } if hasTerms { buf.WriteString(s.terms.String()) } - buf.WriteString(" }") // there was at least one method or term - + buf.WriteString("}") return buf.String() } diff --git a/src/cmd/compile/internal/types2/typeset_test.go b/src/cmd/compile/internal/types2/typeset_test.go index 0e14d523c8..7f7cc06db9 100644 --- a/src/cmd/compile/internal/types2/typeset_test.go +++ b/src/cmd/compile/internal/types2/typeset_test.go @@ -4,7 +4,11 @@ package types2 -import "testing" +import ( + "cmd/compile/internal/syntax" + "strings" + "testing" +) func TestInvalidTypeSet(t *testing.T) { if !invalidTypeSet.IsEmpty() { @@ -12,4 +16,65 @@ func TestInvalidTypeSet(t *testing.T) { } } +func TestTypeSetString(t *testing.T) { + for body, want := range map[string]string{ + "{}": "𝓤", + "{int}": "{int}", + "{~int}": "{~int}", + "{int|string}": "{int ∪ string}", + "{int; string}": "∅", + + "{comparable}": "{comparable}", + "{comparable; int}": "{comparable; int}", + "{~int; comparable}": "{comparable; ~int}", + "{int|string; comparable}": "{comparable; int ∪ string}", + "{comparable; int; string}": "∅", + + "{m()}": "{func (p.T).m()}", + "{m1(); m2() int }": "{func (p.T).m1(); func (p.T).m2() int}", + "{error}": "{func (error).Error() string}", + "{m(); comparable}": "{comparable; func (p.T).m()}", + "{m1(); comparable; m2() int }": "{comparable; func (p.T).m1(); func (p.T).m2() int}", + "{comparable; error}": "{comparable; func (error).Error() string}", + + "{m(); comparable; int|float32|string}": "{comparable; func (p.T).m(); int ∪ float32 ∪ string}", + "{m1(); int; m2(); comparable }": "{comparable; func (p.T).m1(); func (p.T).m2(); int}", + + "{E}; type E interface{}": "𝓤", + "{E}; type E interface{int;string}": "∅", + "{E}; type E interface{comparable}": "{comparable}", + } { + // parse + errh := func(error) {} // dummy error handler so that parsing continues in presence of errors + src := "package p; type T interface" + body + file, err := syntax.Parse(nil, strings.NewReader(src), errh, nil, syntax.AllowGenerics) + if err != nil { + t.Fatalf("%s: %v (invalid test case)", body, err) + } + + // type check + var conf Config + pkg, err := conf.Check(file.PkgName.Value, []*syntax.File{file}, nil) + if err != nil { + t.Fatalf("%s: %v (invalid test case)", body, err) + } + + // lookup T + obj := pkg.scope.Lookup("T") + if obj == nil { + t.Fatalf("%s: T not found (invalid test case)", body) + } + T, ok := under(obj.Type()).(*Interface) + if !ok { + t.Fatalf("%s: %v is not an interface (invalid test case)", body, obj) + } + + // verify test case + got := T.typeSet().String() + if got != want { + t.Errorf("%s: got %s; want %s", body, got, want) + } + } +} + // TODO(gri) add more tests -- GitLab From a6ff433d6a927e8ad8eaa6828127233296d12ce5 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 25 Aug 2021 14:56:01 +0700 Subject: [PATCH 0855/2500] cmd/go: pass -gcflags after other flags generated by the go command Otherwise, any gc flags set by user using "-gcflags" won't have effect. Fixes #47682 Change-Id: Icd365577cba1f64f6c7b8320d0c9019de9f062f6 Reviewed-on: https://go-review.googlesource.com/c/go/+/344909 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/work/gc.go | 24 +++++++++---------- .../testdata/script/build_gcflags_order.txt | 20 ++++++++++++++++ .../testdata/script/build_runtime_gcflags.txt | 2 +- .../go/testdata/script/gcflags_patterns.txt | 22 ++++++++--------- 4 files changed, 44 insertions(+), 24 deletions(-) create mode 100644 src/cmd/go/testdata/script/build_gcflags_order.txt diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go index eee8adca94..1cce5d4dd5 100644 --- a/src/cmd/go/internal/work/gc.go +++ b/src/cmd/go/internal/work/gc.go @@ -75,7 +75,7 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg } pkgpath := pkgPath(a) - gcargs := []string{"-p", pkgpath} + gcflags := []string{"-p", pkgpath} if p.Module != nil { v := p.Module.GoVersion if v == "" { @@ -94,11 +94,11 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg v = "1.16" } if allowedVersion(v) { - gcargs = append(gcargs, "-lang=go"+v) + gcflags = append(gcflags, "-lang=go"+v) } } if p.Standard { - gcargs = append(gcargs, "-std") + gcflags = append(gcflags, "-std") } _, compilingRuntime := runtimePackages[p.ImportPath] compilingRuntime = compilingRuntime && p.Standard @@ -106,7 +106,7 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg // runtime compiles with a special gc flag to check for // memory allocations that are invalid in the runtime package, // and to implement some special compiler pragmas. - gcargs = append(gcargs, "-+") + gcflags = append(gcflags, "-+") } // If we're giving the compiler the entire package (no C etc files), tell it that, @@ -125,25 +125,25 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg } } if extFiles == 0 { - gcargs = append(gcargs, "-complete") + gcflags = append(gcflags, "-complete") } if cfg.BuildContext.InstallSuffix != "" { - gcargs = append(gcargs, "-installsuffix", cfg.BuildContext.InstallSuffix) + gcflags = append(gcflags, "-installsuffix", cfg.BuildContext.InstallSuffix) } if a.buildID != "" { - gcargs = append(gcargs, "-buildid", a.buildID) + gcflags = append(gcflags, "-buildid", a.buildID) } if p.Internal.OmitDebug || cfg.Goos == "plan9" || cfg.Goarch == "wasm" { - gcargs = append(gcargs, "-dwarf=false") + gcflags = append(gcflags, "-dwarf=false") } if strings.HasPrefix(runtimeVersion, "go1") && !strings.Contains(os.Args[0], "go_bootstrap") { - gcargs = append(gcargs, "-goversion", runtimeVersion) + gcflags = append(gcflags, "-goversion", runtimeVersion) } if symabis != "" { - gcargs = append(gcargs, "-symabis", symabis) + gcflags = append(gcflags, "-symabis", symabis) } - gcflags := str.StringList(forcedGcflags, p.Internal.Gcflags) + gcflags = append(gcflags, str.StringList(forcedGcflags, p.Internal.Gcflags)...) if compilingRuntime { // Remove -N, if present. // It is not possible to build the runtime with no optimizations, @@ -157,7 +157,7 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg } } - args := []interface{}{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", a.trimpath(), gcflags, gcargs} + args := []interface{}{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", a.trimpath(), gcflags} if p.Internal.LocalPrefix != "" { // Workaround #43883. args = append(args, "-D", p.Internal.LocalPrefix) diff --git a/src/cmd/go/testdata/script/build_gcflags_order.txt b/src/cmd/go/testdata/script/build_gcflags_order.txt new file mode 100644 index 0000000000..0ffe1570f6 --- /dev/null +++ b/src/cmd/go/testdata/script/build_gcflags_order.txt @@ -0,0 +1,20 @@ +# Tests golang.org/issue/47682 +# Flags specified with -gcflags should appear after other flags generated by cmd/go. + +cd m +go build -n -gcflags=-lang=go1.17 +stderr ' -lang=go1.16.* -lang=go1.17' + +-- m/go.mod -- +module example.com + +go 1.16 + +-- m/main.go -- +package main + +func main() { + var s = []int{1, 2, 3} + var pa = (*[2]int)(s[1:]) + println(pa[1]) +} diff --git a/src/cmd/go/testdata/script/build_runtime_gcflags.txt b/src/cmd/go/testdata/script/build_runtime_gcflags.txt index da1b65f06c..c87e480911 100644 --- a/src/cmd/go/testdata/script/build_runtime_gcflags.txt +++ b/src/cmd/go/testdata/script/build_runtime_gcflags.txt @@ -8,4 +8,4 @@ mkdir $GOCACHE # Verify the standard library (specifically runtime/internal/atomic) can be # built with -gcflags when -n is given. See golang.org/issue/29346. go build -n -gcflags=all='-l' std -stderr 'compile.* -l .* runtime/internal/atomic' +stderr 'compile.* runtime/internal/atomic .* -l' diff --git a/src/cmd/go/testdata/script/gcflags_patterns.txt b/src/cmd/go/testdata/script/gcflags_patterns.txt index f23cecefd3..e9521c2fb2 100644 --- a/src/cmd/go/testdata/script/gcflags_patterns.txt +++ b/src/cmd/go/testdata/script/gcflags_patterns.txt @@ -7,28 +7,28 @@ env GOCACHE=$WORK/gocache # Looking for compile commands, so need a clean cache # -gcflags=-e applies to named packages, not dependencies go build -n -v -gcflags=-e z1 z2 -stderr 'compile.* -e.* -p z1' -stderr 'compile.* -e.* -p z2' +stderr 'compile.* -p z1.* -e' +stderr 'compile.* -p z2.* -e' stderr 'compile.* -p y' -! stderr 'compile.* -e.* -p [^z]' +! stderr 'compile.* -p [^z].* -e' # -gcflags can specify package=flags, and can be repeated; last match wins go build -n -v -gcflags=-e -gcflags=z1=-N z1 z2 -stderr 'compile.* -N.* -p z1' -! stderr 'compile.* -e.* -p z1' -! stderr 'compile.* -N.* -p z2' -stderr 'compile.* -e.* -p z2' +stderr 'compile.* -p z1.* -N' +! stderr 'compile.* -p z1.* -e' +! stderr 'compile.* -p z2.* -N' +stderr 'compile.* -p z2.* -e' stderr 'compile.* -p y' -! stderr 'compile.* -e.* -p [^z]' -! stderr 'compile.* -N.* -p [^z]' +! stderr 'compile.* -p [^z].* -e' +! stderr 'compile.* -p [^z].* -N' # -gcflags can have arbitrary spaces around the flags go build -n -v -gcflags=' z1 = -e ' z1 -stderr 'compile.* -e.* -p z1' +stderr 'compile.* -p z1.* -e' # -gcflags='all=-e' should apply to all packages, even with go test go test -c -n -gcflags='all=-e' z1 -stderr 'compile.* -e.* -p z3 ' +stderr 'compile.* -p z3.* -e ' # this particular -gcflags argument made the compiler crash ! go build -gcflags=-d=ssa/ z1 -- GitLab From 770df2e18df01e64f8770301b0d3a5d6bfa04027 Mon Sep 17 00:00:00 2001 From: vinckr Date: Thu, 26 Aug 2021 10:59:02 +0000 Subject: [PATCH 0856/2500] crypto/tls: fix typo in PreferServerCipherSuites comment Fixing a typo, Deprected -> Deprecated. Change-Id: Ie0ccc9a57ae6a935b4f67154ac097dba4c3832ec GitHub-Last-Rev: 57337cc1bfa771111f229e7b899fdfdad3b1655e GitHub-Pull-Request: golang/go#47745 Reviewed-on: https://go-review.googlesource.com/c/go/+/342791 Trust: Dmitri Shuralyov Reviewed-by: Filippo Valsorda --- src/crypto/tls/common.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go index d561e61707..610a5162dd 100644 --- a/src/crypto/tls/common.go +++ b/src/crypto/tls/common.go @@ -659,7 +659,7 @@ type Config struct { // cipher suite based on logic that takes into account inferred client // hardware, server hardware, and security. // - // Deprected: PreferServerCipherSuites is ignored. + // Deprecated: PreferServerCipherSuites is ignored. PreferServerCipherSuites bool // SessionTicketsDisabled may be set to true to disable session ticket and -- GitLab From d6bdae33e918f779e9e50c020d32042e569368e2 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 25 Aug 2021 18:13:28 -0700 Subject: [PATCH 0857/2500] cmd/compile/internal/types2: address some TODOs (cleanup) - Address some easy TODOs. - Remove some TODOs that are not correct anymore or are unimportent. - Simplify some code on the way. Change-Id: I4d20de3725b3a735022afe022cbc002b2798936d Reviewed-on: https://go-review.googlesource.com/c/go/+/345176 Trust: Robert Griesemer Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/types2/check_test.go | 3 -- src/cmd/compile/internal/types2/expr.go | 4 +- .../compile/internal/types2/hilbert_test.go | 3 +- .../compile/internal/types2/instantiate.go | 49 ++++++++----------- src/cmd/compile/internal/types2/named.go | 2 - src/cmd/compile/internal/types2/self_test.go | 7 +-- src/cmd/compile/internal/types2/signature.go | 7 +-- src/cmd/compile/internal/types2/stmt.go | 6 --- .../types2/testdata/check/tinference.go2 | 6 +-- src/cmd/compile/internal/types2/tuple.go | 2 - src/cmd/compile/internal/types2/type.go | 1 - src/cmd/compile/internal/types2/typestring.go | 1 + src/cmd/compile/internal/types2/unify.go | 3 -- 13 files changed, 27 insertions(+), 67 deletions(-) diff --git a/src/cmd/compile/internal/types2/check_test.go b/src/cmd/compile/internal/types2/check_test.go index 41b0c54702..bc68e76407 100644 --- a/src/cmd/compile/internal/types2/check_test.go +++ b/src/cmd/compile/internal/types2/check_test.go @@ -20,9 +20,6 @@ // _ = x /* ERROR "not declared" */ + 1 // } -// TODO(gri) Also collect strict mode errors of the form /* STRICT ... */ -// and test against strict mode. - package types2_test import ( diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index d108093dac..86a8444ee2 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -127,9 +127,7 @@ func (check *Checker) overflow(x *operand) { } // opName returns the name of an operation, or the empty string. -// For now, only operations that might overflow are handled. -// TODO(gri) Expand this to a general mechanism giving names to -// nodes? +// Only operations that might overflow are handled. func opName(e *syntax.Operation) string { op := int(e.Op) if e.Y == nil { diff --git a/src/cmd/compile/internal/types2/hilbert_test.go b/src/cmd/compile/internal/types2/hilbert_test.go index 9f9dad6b64..03fea4fe7c 100644 --- a/src/cmd/compile/internal/types2/hilbert_test.go +++ b/src/cmd/compile/internal/types2/hilbert_test.go @@ -29,8 +29,7 @@ func TestHilbert(t *testing.T) { } // parse source - // TODO(gri) get rid of []bytes to string conversion below - f, err := parseSrc("hilbert.go", string(src)) + f, err := syntax.Parse(syntax.NewFileBase("hilbert.go"), bytes.NewReader(src), nil, nil, 0) if err != nil { t.Fatal(err) } diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 8bea63ec86..b78ac3bea3 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -122,19 +122,17 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, posLis // instance creates a type or function instance using the given original type // typ and arguments targs. For Named types the resulting instance will be // unexpanded. -func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type) (res Type) { - // TODO(gri) What is better here: work with TypeParams, or work with TypeNames? +func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type) Type { switch t := typ.(type) { case *Named: h := instantiatedHash(t, targs) if check != nil { - // typ may already have been instantiated with identical type arguments. In - // that case, re-use the existing instance. + // typ may already have been instantiated with identical type arguments. + // In that case, re-use the existing instance. if named := check.typMap[h]; named != nil { return named } } - tname := NewTypeName(pos, t.obj.pkg, t.obj.name, nil) named := check.newNamed(tname, t, nil, nil, nil) // methods and tparams are set when named is loaded named.targs = NewTypeList(targs) @@ -142,7 +140,8 @@ func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type) (res Type if check != nil { check.typMap[h] = named } - res = named + return named + case *Signature: tparams := t.TParams() if !check.validateTArgLen(pos, tparams.Len(), len(targs)) { @@ -151,30 +150,22 @@ func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type) (res Type if tparams.Len() == 0 { return typ // nothing to do (minor optimization) } - defer func() { - // If we had an unexpected failure somewhere don't panic below when - // asserting res.(*Signature). Check for *Signature in case Typ[Invalid] - // is returned. - if _, ok := res.(*Signature); !ok { - return - } - // If the signature doesn't use its type parameters, subst - // will not make a copy. In that case, make a copy now (so - // we can set tparams to nil w/o causing side-effects). - if t == res { - copy := *t - res = © - } - // After instantiating a generic signature, it is not generic - // anymore; we need to set tparams to nil. - res.(*Signature).tparams = nil - }() - res = check.subst(pos, typ, makeSubstMap(tparams.list(), targs), nil) - default: - // only types and functions can be generic - panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) + sig := check.subst(pos, typ, makeSubstMap(tparams.list(), targs), nil).(*Signature) + // If the signature doesn't use its type parameters, subst + // will not make a copy. In that case, make a copy now (so + // we can set tparams to nil w/o causing side-effects). + if sig == t { + copy := *sig + sig = © + } + // After instantiating a generic signature, it is not generic + // anymore; we need to set tparams to nil. + sig.tparams = nil + return sig } - return res + + // only types and functions can be generic + panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } // validateTArgLen verifies that the length of targs and tparams matches, diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index a3a2595a22..ccb1f265be 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -9,8 +9,6 @@ import ( "sync" ) -// TODO(gri) Clean up Named struct below; specifically the fromRHS field (can we use underlying?). - // A Named represents a named (defined) type. type Named struct { check *Checker diff --git a/src/cmd/compile/internal/types2/self_test.go b/src/cmd/compile/internal/types2/self_test.go index 4722fec988..e0d2e1b07a 100644 --- a/src/cmd/compile/internal/types2/self_test.go +++ b/src/cmd/compile/internal/types2/self_test.go @@ -24,12 +24,7 @@ func TestSelf(t *testing.T) { conf := Config{Importer: defaultImporter()} _, err = conf.Check("cmd/compile/internal/types2", files, nil) if err != nil { - // Importing go/constant doesn't work in the - // build dashboard environment. Don't report an error - // for now so that the build remains green. - // TODO(gri) fix this - t.Log(err) // replace w/ t.Fatal eventually - return + t.Fatal(err) } } diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index f1bf60ae8e..d28e7b8944 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -150,12 +150,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] // bound is (possibly) parameterized in the context of the // receiver type declaration. Substitute parameters for the // current context. - // TODO(gri) should we assume now that bounds always exist? - // (no bound == empty interface) - if bound != nil { - bound = check.subst(tpar.obj.pos, bound, smap, nil) - tpar.bound = bound - } + tpar.bound = check.subst(tpar.obj.pos, bound, smap, nil) } } } diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index 7865c2d4f4..8cfdf92e67 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -52,11 +52,6 @@ func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body check.error(body.Rbrace, "missing return") } - // TODO(gri) Should we make it an error to declare generic functions - // where the type parameters are not used? - // 12/19/2018: Probably not - it can make sense to have an API with - // all functions uniformly sharing the same type parameters. - // spec: "Implementation restriction: A compiler may make it illegal to // declare a variable inside a function body if the variable is never used." check.usage(sig.scope) @@ -422,7 +417,6 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) { check.assignVar(lhs[0], &x) case *syntax.CallStmt: - // TODO(gri) get rid of this conversion to string kind := "go" if s.Tok == syntax.Defer { kind = "defer" diff --git a/src/cmd/compile/internal/types2/testdata/check/tinference.go2 b/src/cmd/compile/internal/types2/testdata/check/tinference.go2 index 0afb77c1e4..2409fef4ae 100644 --- a/src/cmd/compile/internal/types2/testdata/check/tinference.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/tinference.go2 @@ -15,7 +15,7 @@ type any interface{} // f("a", "b", "c", "d") // f0("a", "b", "c", "d") // } -// +// // func f1[A any, B interface{~A}](A, B) // func _() { // f := f1[int] @@ -60,9 +60,7 @@ func _() { var _ string = x } -// TODO(gri) Need to flag invalid recursive constraints. At the -// moment these cause infinite recursions and stack overflow. -// func f7[A interface{type B}, B interface{~A}]() +func f7[A interface{*B}, B interface{~*A}]() {} // More realistic examples diff --git a/src/cmd/compile/internal/types2/tuple.go b/src/cmd/compile/internal/types2/tuple.go index a3946beab5..1356aae0b0 100644 --- a/src/cmd/compile/internal/types2/tuple.go +++ b/src/cmd/compile/internal/types2/tuple.go @@ -16,8 +16,6 @@ func NewTuple(x ...*Var) *Tuple { if len(x) > 0 { return &Tuple{vars: x} } - // TODO(gri) Don't represent empty tuples with a (*Tuple)(nil) pointer; - // it's too subtle and causes problems. return nil } diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 4b8642aa96..ca5ecdc434 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -34,7 +34,6 @@ func (t *top) String() string { return TypeString(t, nil) } // under must only be called when a type is known // to be fully set up. func under(t Type) Type { - // TODO(gri) is this correct for *Union? if n := asNamed(t); n != nil { return n.under() } diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 2c34d036db..9980408593 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -279,6 +279,7 @@ func writeTParamList(buf *bytes.Buffer, list []*TypeParam, qf Qualifier, visited func writeTypeName(buf *bytes.Buffer, obj *TypeName, qf Qualifier) { if obj == nil { + assert(instanceHashing == 0) // we need an object for instance hashing buf.WriteString("") return } diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index d4fbebc11b..72542e7d2e 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -433,9 +433,6 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { xargs := x.targs.list() yargs := y.targs.list() - // TODO(gri) This is not always correct: two types may have the same names - // in the same package if one of them is nested in a function. - // Extremely unlikely but we need an always correct solution. if x.obj.pkg == y.obj.pkg && x.obj.name == y.obj.name { assert(len(xargs) == len(yargs)) for i, x := range xargs { -- GitLab From 166b691b652356074ea346157e8bbc13933380aa Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 25 Aug 2021 21:48:21 -0700 Subject: [PATCH 0858/2500] cmd/compile/internal/types2: remove need for instance (struct) instance was only used to hold the instantiation position for lazy instantiation (and encode the fact that we have a lazy instantiation). Just use a (pointer to a) syntax.Pos instead. We could use a syntax.Pos (no pointer) and rely on the fact that we have a known position (or fake position, if need be) to indicate lazy instantiation. But using a pointer leads to a smaller Named struct. Change-Id: I441a839a125f453ad6c501de1ce499b72a2f67a4 Reviewed-on: https://go-review.googlesource.com/c/go/+/345177 Trust: Robert Griesemer Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/types2/instantiate.go | 2 +- src/cmd/compile/internal/types2/named.go | 18 +++++------------- src/cmd/compile/internal/types2/typestring.go | 2 +- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index b78ac3bea3..f9cde24dfc 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -136,7 +136,7 @@ func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type) Type { tname := NewTypeName(pos, t.obj.pkg, t.obj.name, nil) named := check.newNamed(tname, t, nil, nil, nil) // methods and tparams are set when named is loaded named.targs = NewTypeList(targs) - named.instance = &instance{pos} + named.instPos = &pos if check != nil { check.typMap[h] = named } diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index ccb1f265be..b4074aa3dc 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -17,7 +17,7 @@ type Named struct { orig *Named // original, uninstantiated type fromRHS Type // type (on RHS of declaration) this *Named type is derived from (for cycle reporting) underlying Type // possibly a *Named during setup; never a *Named once set up completely - instance *instance // position information for lazy instantiation, or nil + instPos *syntax.Pos // position information for lazy instantiation, or nil tparams *TParamList // type parameters, or nil targs *TypeList // type arguments (after instantiation), or nil methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily @@ -240,24 +240,16 @@ func (n *Named) setUnderlying(typ Type) { } } -// instance holds position information for use in lazy instantiation. -// -// TODO(rfindley): instance is probably unnecessary now. See if it can be -// eliminated. -type instance struct { - pos syntax.Pos // position of type instantiation; for error reporting only -} - // expand ensures that the underlying type of n is instantiated. // The underlying type will be Typ[Invalid] if there was an error. func (n *Named) expand(typMap map[string]*Named) *Named { - if n.instance != nil { + if n.instPos != nil { // n must be loaded before instantiation, in order to have accurate // tparams. This is done implicitly by the call to n.TParams, but making it // explicit is harmless: load is idempotent. n.load() var u Type - if n.check.validateTArgLen(n.instance.pos, n.tparams.Len(), n.targs.Len()) { + if n.check.validateTArgLen(*n.instPos, n.tparams.Len(), n.targs.Len()) { if typMap == nil { if n.check != nil { typMap = n.check.typMap @@ -270,13 +262,13 @@ func (n *Named) expand(typMap map[string]*Named) *Named { typMap = map[string]*Named{h: n} } } - u = n.check.subst(n.instance.pos, n.orig.underlying, makeSubstMap(n.TParams().list(), n.targs.list()), typMap) + u = n.check.subst(*n.instPos, n.orig.underlying, makeSubstMap(n.TParams().list(), n.targs.list()), typMap) } else { u = Typ[Invalid] } n.underlying = u n.fromRHS = u - n.instance = nil + n.instPos = nil } return n } diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 9980408593..1775fc6677 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -195,7 +195,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { } case *Named: - if t.instance != nil { + if t.instPos != nil { buf.WriteByte(instanceMarker) } writeTypeName(buf, t.obj, qf) -- GitLab From 5e6a7e9b860d7c8f589eec3c123469ea8071689f Mon Sep 17 00:00:00 2001 From: Dan Kortschak Date: Mon, 23 Aug 2021 19:13:35 +0930 Subject: [PATCH 0859/2500] embed: remove reference to global variables in docs Refering to variable is both redundant since package scope is used, and incorrect since global variables are not described in the spec. Change-Id: Ib08a9f072fc800ee36549f758b68167d8f044878 Reviewed-on: https://go-review.googlesource.com/c/go/+/344214 Reviewed-by: Ian Lance Taylor Trust: Alexander Rakoczy Run-TryBot: Alexander Rakoczy TryBot-Result: Go Bot --- src/embed/embed.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/embed/embed.go b/src/embed/embed.go index 851cc216fc..5dcd7f227d 100644 --- a/src/embed/embed.go +++ b/src/embed/embed.go @@ -83,8 +83,7 @@ // // The //go:embed directive can be used with both exported and unexported variables, // depending on whether the package wants to make the data available to other packages. -// It can only be used with global variables at package scope, -// not with local variables. +// It can only be used with variables at package scope, not with local variables. // // Patterns must not match files outside the package's module, such as ‘.git/*’ or symbolic links. // Matches for empty directories are ignored. After that, each pattern in a //go:embed line -- GitLab From 1f8d4562debf8310910897ea85705cc067baa52d Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 26 Aug 2021 11:29:44 -0700 Subject: [PATCH 0860/2500] cmd/compile: change typecheck.iscmp into ir.Op.IsCmp Change-Id: If89089cbd79b7ff030d856df3a7e6b7862c0f4ec Reviewed-on: https://go-review.googlesource.com/c/go/+/345412 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: Cuong Manh Le TryBot-Result: Go Bot --- src/cmd/compile/internal/ir/node.go | 10 ++++++++++ src/cmd/compile/internal/noder/stencil.go | 2 +- src/cmd/compile/internal/typecheck/expr.go | 6 +----- src/cmd/compile/internal/typecheck/universe.go | 8 -------- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index f071cb78ce..8784f9ef99 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -334,6 +334,16 @@ const ( OEND ) +// IsCmp reports whether op is a comparison operation (==, !=, <, <=, +// >, or >=). +func (op Op) IsCmp() bool { + switch op { + case OEQ, ONE, OLT, OLE, OGT, OGE: + return true + } + return false +} + // Nodes is a pointer to a slice of *Node. // For fields that are not used in most nodes, this is used instead of // a slice to save space. diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index b3ff4b8855..0c6bb5100c 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -903,7 +903,7 @@ func (subst *subster) node(n ir.Node) ir.Node { ir.EditChildren(m, edit) m.SetTypecheck(1) - if typecheck.IsCmp(x.Op()) { + if x.Op().IsCmp() { transformCompare(m.(*ir.BinaryExpr)) } else { switch x.Op() { diff --git a/src/cmd/compile/internal/typecheck/expr.go b/src/cmd/compile/internal/typecheck/expr.go index 7e974dfda8..d83bc65bed 100644 --- a/src/cmd/compile/internal/typecheck/expr.go +++ b/src/cmd/compile/internal/typecheck/expr.go @@ -77,10 +77,6 @@ func tcShift(n, l, r ir.Node) (ir.Node, ir.Node, *types.Type) { return l, r, t } -func IsCmp(op ir.Op) bool { - return iscmp[op] -} - // tcArith typechecks operands of a binary arithmetic expression. // The result of tcArith MUST be assigned back to original operands, // t is the type of the expression, and should be set by the caller. e.g: @@ -96,7 +92,7 @@ func tcArith(n ir.Node, op ir.Op, l, r ir.Node) (ir.Node, ir.Node, *types.Type) t = r.Type() } aop := ir.OXXX - if iscmp[n.Op()] && t.Kind() != types.TIDEAL && !types.Identical(l.Type(), r.Type()) { + if n.Op().IsCmp() && t.Kind() != types.TIDEAL && !types.Identical(l.Type(), r.Type()) { // comparison is okay as long as one side is // assignable to the other. convert so they have // the same type. diff --git a/src/cmd/compile/internal/typecheck/universe.go b/src/cmd/compile/internal/typecheck/universe.go index 54f3c89c24..a7c84dc8d8 100644 --- a/src/cmd/compile/internal/typecheck/universe.go +++ b/src/cmd/compile/internal/typecheck/universe.go @@ -329,14 +329,6 @@ func InitUniverse() { // special okfor[ir.OCAP] = okforcap[:] okfor[ir.OLEN] = okforlen[:] - - // comparison - iscmp[ir.OLT] = true - iscmp[ir.OGT] = true - iscmp[ir.OGE] = true - iscmp[ir.OLE] = true - iscmp[ir.OEQ] = true - iscmp[ir.ONE] = true } func makeErrorInterface() *types.Type { -- GitLab From 3836983779a8f1f1a1b6dc629832e695dcacaf36 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 26 Aug 2021 11:46:24 -0700 Subject: [PATCH 0861/2500] cmd/compile/internal/types: unexport Type.Extra Not used outside of package types anymore. Let's keep it that. Change-Id: I69b464ac94edaacd219da4210f7b8618e2beaf70 Reviewed-on: https://go-review.googlesource.com/c/go/+/345413 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/types/fmt.go | 4 +- src/cmd/compile/internal/types/size.go | 2 +- src/cmd/compile/internal/types/type.go | 182 ++++++++++---------- src/cmd/compile/internal/types/type_test.go | 19 +- 4 files changed, 103 insertions(+), 104 deletions(-) diff --git a/src/cmd/compile/internal/types/fmt.go b/src/cmd/compile/internal/types/fmt.go index 0824f6d093..b1b8506400 100644 --- a/src/cmd/compile/internal/types/fmt.go +++ b/src/cmd/compile/internal/types/fmt.go @@ -298,7 +298,7 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type return } if t.Kind() == TSSA { - b.WriteString(t.Extra.(string)) + b.WriteString(t.extra.(string)) return } if t.Kind() == TTUPLE { @@ -309,7 +309,7 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type } if t.Kind() == TRESULTS { - tys := t.Extra.(*Results).Types + tys := t.extra.(*Results).Types for i, et := range tys { if i > 0 { b.WriteByte(',') diff --git a/src/cmd/compile/internal/types/size.go b/src/cmd/compile/internal/types/size.go index 89391ade68..34db0a0b0c 100644 --- a/src/cmd/compile/internal/types/size.go +++ b/src/cmd/compile/internal/types/size.go @@ -526,7 +526,7 @@ func CalcSize(t *Type) { w = calcStructOffset(t1, t1.Recvs(), 0, 0) w = calcStructOffset(t1, t1.Params(), w, RegSize) w = calcStructOffset(t1, t1.Results(), w, RegSize) - t1.Extra.(*Func).Argwid = w + t1.extra.(*Func).Argwid = w if w%int64(RegSize) != 0 { base.Warn("bad type %v %d\n", t1, w) } diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 875b0ba82f..975280753a 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -139,7 +139,7 @@ var ( // A Type represents a Go type. type Type struct { - // Extra contains extra etype-specific fields. + // extra contains extra etype-specific fields. // As an optimization, those etype-specific structs which contain exactly // one pointer-shaped field are stored as values rather than pointers when possible. // @@ -156,7 +156,7 @@ type Type struct { // TSLICE: Slice // TSSA: string // TTYPEPARAM: *Typeparam - Extra interface{} + extra interface{} // Width is the width of this Type in bytes. Width int64 // valid if Align > 0 @@ -325,11 +325,11 @@ var NoPkg *Pkg = nil func (t *Type) Pkg() *Pkg { switch t.kind { case TFUNC: - return t.Extra.(*Func).pkg + return t.extra.(*Func).pkg case TSTRUCT: - return t.Extra.(*Struct).pkg + return t.extra.(*Struct).pkg case TINTER: - return t.Extra.(*Interface).pkg + return t.extra.(*Interface).pkg default: base.Fatalf("Pkg: unexpected kind: %v", t) return nil @@ -349,7 +349,7 @@ type Map struct { // MapType returns t's extra map-specific fields. func (t *Type) MapType() *Map { t.wantEtype(TMAP) - return t.Extra.(*Map) + return t.extra.(*Map) } // Forward contains Type fields specific to forward types. @@ -361,7 +361,7 @@ type Forward struct { // ForwardType returns t's extra forward-type-specific fields. func (t *Type) ForwardType() *Forward { t.wantEtype(TFORW) - return t.Extra.(*Forward) + return t.extra.(*Forward) } // Func contains Type fields specific to func types. @@ -382,7 +382,7 @@ type Func struct { // FuncType returns t's extra func-specific fields. func (t *Type) FuncType() *Func { t.wantEtype(TFUNC) - return t.Extra.(*Func) + return t.extra.(*Func) } // StructType contains Type fields specific to struct types. @@ -411,7 +411,7 @@ const ( // StructType returns t's extra struct-specific fields. func (t *Type) StructType() *Struct { t.wantEtype(TSTRUCT) - return t.Extra.(*Struct) + return t.extra.(*Struct) } // Interface contains Type fields specific to interface types. @@ -455,7 +455,7 @@ type Chan struct { // ChanType returns t's extra channel-specific fields. func (t *Type) ChanType() *Chan { t.wantEtype(TCHAN) - return t.Extra.(*Chan) + return t.extra.(*Chan) } type Tuple struct { @@ -590,31 +590,31 @@ func New(et Kind) *Type { // TODO(josharian): lazily initialize some of these? switch t.kind { case TMAP: - t.Extra = new(Map) + t.extra = new(Map) case TFORW: - t.Extra = new(Forward) + t.extra = new(Forward) case TFUNC: - t.Extra = new(Func) + t.extra = new(Func) case TSTRUCT: - t.Extra = new(Struct) + t.extra = new(Struct) case TINTER: - t.Extra = new(Interface) + t.extra = new(Interface) case TPTR: - t.Extra = Ptr{} + t.extra = Ptr{} case TCHANARGS: - t.Extra = ChanArgs{} + t.extra = ChanArgs{} case TFUNCARGS: - t.Extra = FuncArgs{} + t.extra = FuncArgs{} case TCHAN: - t.Extra = new(Chan) + t.extra = new(Chan) case TTUPLE: - t.Extra = new(Tuple) + t.extra = new(Tuple) case TRESULTS: - t.Extra = new(Results) + t.extra = new(Results) case TTYPEPARAM: - t.Extra = new(Typeparam) + t.extra = new(Typeparam) case TUNION: - t.Extra = new(Union) + t.extra = new(Union) } return t } @@ -625,7 +625,7 @@ func NewArray(elem *Type, bound int64) *Type { base.Fatalf("NewArray: invalid bound %v", bound) } t := New(TARRAY) - t.Extra = &Array{Elem: elem, Bound: bound} + t.extra = &Array{Elem: elem, Bound: bound} t.SetNotInHeap(elem.NotInHeap()) if elem.HasTParam() { t.SetHasTParam(true) @@ -646,7 +646,7 @@ func NewSlice(elem *Type) *Type { } t := New(TSLICE) - t.Extra = Slice{Elem: elem} + t.extra = Slice{Elem: elem} elem.cache.slice = t if elem.HasTParam() { t.SetHasTParam(true) @@ -674,8 +674,8 @@ func NewChan(elem *Type, dir ChanDir) *Type { func NewTuple(t1, t2 *Type) *Type { t := New(TTUPLE) - t.Extra.(*Tuple).first = t1 - t.Extra.(*Tuple).second = t2 + t.extra.(*Tuple).first = t1 + t.extra.(*Tuple).second = t2 if t1.HasTParam() || t2.HasTParam() { t.SetHasTParam(true) } @@ -687,7 +687,7 @@ func NewTuple(t1, t2 *Type) *Type { func newResults(types []*Type) *Type { t := New(TRESULTS) - t.Extra.(*Results).Types = types + t.extra.(*Results).Types = types return t } @@ -700,7 +700,7 @@ func NewResults(types []*Type) *Type { func newSSA(name string) *Type { t := New(TSSA) - t.Extra = name + t.extra = name return t } @@ -747,7 +747,7 @@ func NewPtr(elem *Type) *Type { } t := New(TPTR) - t.Extra = Ptr{Elem: elem} + t.extra = Ptr{Elem: elem} t.Width = int64(PtrSize) t.Align = uint8(PtrSize) if NewPtrCacheEnabled { @@ -765,14 +765,14 @@ func NewPtr(elem *Type) *Type { // NewChanArgs returns a new TCHANARGS type for channel type c. func NewChanArgs(c *Type) *Type { t := New(TCHANARGS) - t.Extra = ChanArgs{T: c} + t.extra = ChanArgs{T: c} return t } // NewFuncArgs returns a new TFUNCARGS type for func type f. func NewFuncArgs(f *Type) *Type { t := New(TFUNCARGS) - t.Extra = FuncArgs{T: f} + t.extra = FuncArgs{T: f} return t } @@ -811,28 +811,28 @@ func SubstAny(t *Type, types *[]*Type) *Type { elem := SubstAny(t.Elem(), types) if elem != t.Elem() { t = t.copy() - t.Extra = Ptr{Elem: elem} + t.extra = Ptr{Elem: elem} } case TARRAY: elem := SubstAny(t.Elem(), types) if elem != t.Elem() { t = t.copy() - t.Extra.(*Array).Elem = elem + t.extra.(*Array).Elem = elem } case TSLICE: elem := SubstAny(t.Elem(), types) if elem != t.Elem() { t = t.copy() - t.Extra = Slice{Elem: elem} + t.extra = Slice{Elem: elem} } case TCHAN: elem := SubstAny(t.Elem(), types) if elem != t.Elem() { t = t.copy() - t.Extra.(*Chan).Elem = elem + t.extra.(*Chan).Elem = elem } case TMAP: @@ -840,8 +840,8 @@ func SubstAny(t *Type, types *[]*Type) *Type { elem := SubstAny(t.Elem(), types) if key != t.Key() || elem != t.Elem() { t = t.copy() - t.Extra.(*Map).Key = key - t.Extra.(*Map).Elem = elem + t.extra.(*Map).Key = key + t.extra.(*Map).Elem = elem } case TFUNC: @@ -882,26 +882,26 @@ func (t *Type) copy() *Type { // copy any *T Extra fields, to avoid aliasing switch t.kind { case TMAP: - x := *t.Extra.(*Map) - nt.Extra = &x + x := *t.extra.(*Map) + nt.extra = &x case TFORW: - x := *t.Extra.(*Forward) - nt.Extra = &x + x := *t.extra.(*Forward) + nt.extra = &x case TFUNC: - x := *t.Extra.(*Func) - nt.Extra = &x + x := *t.extra.(*Func) + nt.extra = &x case TSTRUCT: - x := *t.Extra.(*Struct) - nt.Extra = &x + x := *t.extra.(*Struct) + nt.extra = &x case TINTER: - x := *t.Extra.(*Interface) - nt.Extra = &x + x := *t.extra.(*Interface) + nt.extra = &x case TCHAN: - x := *t.Extra.(*Chan) - nt.Extra = &x + x := *t.extra.(*Chan) + nt.extra = &x case TARRAY: - x := *t.Extra.(*Array) - nt.Extra = &x + x := *t.extra.(*Array) + nt.extra = &x case TTYPEPARAM: base.Fatalf("typeparam types cannot be copied") case TTUPLE, TSSA, TRESULTS: @@ -970,7 +970,7 @@ var ParamsResults = [2]func(*Type) *Type{ // Key returns the key type of map type t. func (t *Type) Key() *Type { t.wantEtype(TMAP) - return t.Extra.(*Map).Key + return t.extra.(*Map).Key } // Elem returns the type of elements of t. @@ -978,15 +978,15 @@ func (t *Type) Key() *Type { func (t *Type) Elem() *Type { switch t.kind { case TPTR: - return t.Extra.(Ptr).Elem + return t.extra.(Ptr).Elem case TARRAY: - return t.Extra.(*Array).Elem + return t.extra.(*Array).Elem case TSLICE: - return t.Extra.(Slice).Elem + return t.extra.(Slice).Elem case TCHAN: - return t.Extra.(*Chan).Elem + return t.extra.(*Chan).Elem case TMAP: - return t.Extra.(*Map).Elem + return t.extra.(*Map).Elem } base.Fatalf("Type.Elem %s", t.kind) return nil @@ -995,18 +995,18 @@ func (t *Type) Elem() *Type { // ChanArgs returns the channel type for TCHANARGS type t. func (t *Type) ChanArgs() *Type { t.wantEtype(TCHANARGS) - return t.Extra.(ChanArgs).T + return t.extra.(ChanArgs).T } // FuncArgs returns the func type for TFUNCARGS type t. func (t *Type) FuncArgs() *Type { t.wantEtype(TFUNCARGS) - return t.Extra.(FuncArgs).T + return t.extra.(FuncArgs).T } // IsFuncArgStruct reports whether t is a struct representing function parameters or results. func (t *Type) IsFuncArgStruct() bool { - return t.kind == TSTRUCT && t.Extra.(*Struct).Funarg != FunargNone + return t.kind == TSTRUCT && t.extra.(*Struct).Funarg != FunargNone } // Methods returns a pointer to the base methods (excluding embedding) for type t. @@ -1037,7 +1037,7 @@ func (t *Type) SetAllMethods(fs []*Field) { // Fields returns the fields of struct type t. func (t *Type) Fields() *Fields { t.wantEtype(TSTRUCT) - return &t.Extra.(*Struct).fields + return &t.extra.(*Struct).fields } // Field returns the i'th field of struct type t. @@ -1091,7 +1091,7 @@ func (t *Type) WidthCalculated() bool { // It includes the receiver, parameters, and results. func (t *Type) ArgWidth() int64 { t.wantEtype(TFUNC) - return t.Extra.(*Func).Argwid + return t.extra.(*Func).Argwid } func (t *Type) Size() int64 { @@ -1234,8 +1234,8 @@ func (t *Type) cmp(x *Type) Cmp { return CMPeq case TSSA: - tname := t.Extra.(string) - xname := x.Extra.(string) + tname := t.extra.(string) + xname := x.extra.(string) // desire fast sorting, not pretty sorting. if len(tname) == len(xname) { if tname == xname { @@ -1252,16 +1252,16 @@ func (t *Type) cmp(x *Type) Cmp { return CMPlt case TTUPLE: - xtup := x.Extra.(*Tuple) - ttup := t.Extra.(*Tuple) + xtup := x.extra.(*Tuple) + ttup := t.extra.(*Tuple) if c := ttup.first.Compare(xtup.first); c != CMPeq { return c } return ttup.second.Compare(xtup.second) case TRESULTS: - xResults := x.Extra.(*Results) - tResults := t.Extra.(*Results) + xResults := x.extra.(*Results) + tResults := t.extra.(*Results) xl, tl := len(xResults.Types), len(tResults.Types) if tl != xl { if tl < xl { @@ -1548,7 +1548,7 @@ func (t *Type) PtrTo() *Type { func (t *Type) NumFields() int { if t.kind == TRESULTS { - return len(t.Extra.(*Results).Types) + return len(t.extra.(*Results).Types) } return t.Fields().Len() } @@ -1556,15 +1556,15 @@ func (t *Type) FieldType(i int) *Type { if t.kind == TTUPLE { switch i { case 0: - return t.Extra.(*Tuple).first + return t.extra.(*Tuple).first case 1: - return t.Extra.(*Tuple).second + return t.extra.(*Tuple).second default: panic("bad tuple index") } } if t.kind == TRESULTS { - return t.Extra.(*Results).Types[i] + return t.extra.(*Results).Types[i] } return t.Field(i).Type } @@ -1577,7 +1577,7 @@ func (t *Type) FieldName(i int) string { func (t *Type) NumElem() int64 { t.wantEtype(TARRAY) - return t.Extra.(*Array).Bound + return t.extra.(*Array).Bound } type componentsIncludeBlankFields bool @@ -1639,15 +1639,15 @@ func (t *Type) SoleComponent() *Type { // The direction will be one of Crecv, Csend, or Cboth. func (t *Type) ChanDir() ChanDir { t.wantEtype(TCHAN) - return t.Extra.(*Chan).Dir + return t.extra.(*Chan).Dir } func (t *Type) IsMemory() bool { - if t == TypeMem || t.kind == TTUPLE && t.Extra.(*Tuple).second == TypeMem { + if t == TypeMem || t.kind == TTUPLE && t.extra.(*Tuple).second == TypeMem { return true } if t.kind == TRESULTS { - if types := t.Extra.(*Results).Types; len(types) > 0 && types[len(types)-1] == TypeMem { + if types := t.extra.(*Results).Types; len(types) > 0 && types[len(types)-1] == TypeMem { return true } } @@ -1699,11 +1699,11 @@ func (t *Type) HasPointers() bool { return !t.Elem().NotInHeap() case TTUPLE: - ttup := t.Extra.(*Tuple) + ttup := t.extra.(*Tuple) return ttup.first.HasPointers() || ttup.second.HasPointers() case TRESULTS: - types := t.Extra.(*Results).Types + types := t.extra.(*Results).Types for _, et := range types { if et.HasPointers() { return true @@ -1781,7 +1781,7 @@ func (t *Type) SetUnderlying(underlying *Type) { // TODO(mdempsky): Fix Type rekinding. t.kind = underlying.kind - t.Extra = underlying.Extra + t.extra = underlying.extra t.Width = underlying.Width t.Align = underlying.Align t.underlying = underlying.underlying @@ -1865,7 +1865,7 @@ func NewInterface(pkg *Pkg, methods []*Field) *Type { if anyBroke(methods) { t.SetBroke(true) } - t.Extra.(*Interface).pkg = pkg + t.extra.(*Interface).pkg = pkg return t } @@ -1874,7 +1874,7 @@ func NewInterface(pkg *Pkg, methods []*Field) *Type { func NewTypeParam(sym *Sym, index int) *Type { t := New(TTYPEPARAM) t.sym = sym - t.Extra.(*Typeparam).index = index + t.extra.(*Typeparam).index = index t.SetHasTParam(true) return t } @@ -1882,25 +1882,25 @@ func NewTypeParam(sym *Sym, index int) *Type { // Index returns the index of the type param within its param list. func (t *Type) Index() int { t.wantEtype(TTYPEPARAM) - return t.Extra.(*Typeparam).index + return t.extra.(*Typeparam).index } // SetIndex sets the index of the type param within its param list. func (t *Type) SetIndex(i int) { t.wantEtype(TTYPEPARAM) - t.Extra.(*Typeparam).index = i + t.extra.(*Typeparam).index = i } // SetBound sets the bound of a typeparam. func (t *Type) SetBound(bound *Type) { t.wantEtype(TTYPEPARAM) - t.Extra.(*Typeparam).bound = bound + t.extra.(*Typeparam).bound = bound } // Bound returns the bound of a typeparam. func (t *Type) Bound() *Type { t.wantEtype(TTYPEPARAM) - return t.Extra.(*Typeparam).bound + return t.extra.(*Typeparam).bound } // NewUnion returns a new union with the specified set of terms (types). If @@ -1910,8 +1910,8 @@ func NewUnion(terms []*Type, tildes []bool) *Type { if len(terms) != len(tildes) { base.Fatalf("Mismatched terms and tildes for NewUnion") } - t.Extra.(*Union).terms = terms - t.Extra.(*Union).tildes = tildes + t.extra.(*Union).terms = terms + t.extra.(*Union).tildes = tildes nt := len(terms) for i := 0; i < nt; i++ { if terms[i].HasTParam() { @@ -1927,14 +1927,14 @@ func NewUnion(terms []*Type, tildes []bool) *Type { // NumTerms returns the number of terms in a union type. func (t *Type) NumTerms() int { t.wantEtype(TUNION) - return len(t.Extra.(*Union).terms) + return len(t.extra.(*Union).terms) } // Term returns ith term of a union type as (term, tilde). If tilde is true, term // represents ~T, rather than just T. func (t *Type) Term(i int) (*Type, bool) { t.wantEtype(TUNION) - u := t.Extra.(*Union) + u := t.extra.(*Union) return u.terms[i], u.tildes[i] } @@ -1995,7 +1995,7 @@ func NewStruct(pkg *Pkg, fields []*Field) *Type { if anyBroke(fields) { t.SetBroke(true) } - t.Extra.(*Struct).pkg = pkg + t.extra.(*Struct).pkg = pkg if fieldsHasTParam(fields) { t.SetHasTParam(true) } diff --git a/src/cmd/compile/internal/types/type_test.go b/src/cmd/compile/internal/types/type_test.go index fe3f380b21..1fd05b3f5e 100644 --- a/src/cmd/compile/internal/types/type_test.go +++ b/src/cmd/compile/internal/types/type_test.go @@ -2,26 +2,25 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package types_test +package types import ( - "cmd/compile/internal/types" "testing" ) func TestSSACompare(t *testing.T) { - a := []*types.Type{ - types.TypeInvalid, - types.TypeMem, - types.TypeFlags, - types.TypeVoid, - types.TypeInt128, + a := []*Type{ + TypeInvalid, + TypeMem, + TypeFlags, + TypeVoid, + TypeInt128, } for _, x := range a { for _, y := range a { c := x.Compare(y) - if x == y && c != types.CMPeq || x != y && c == types.CMPeq { - t.Errorf("%s compare %s == %d\n", x.Extra, y.Extra, c) + if x == y && c != CMPeq || x != y && c == CMPeq { + t.Errorf("%s compare %s == %d\n", x.extra, y.extra, c) } } } -- GitLab From eb6a07fcf99050c447097a8ff6358c484c0f8715 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 26 Aug 2021 12:05:45 -0700 Subject: [PATCH 0862/2500] cmd/compile: unexport Type.Vargen This field is only used outside of packages types in two places, and they follow the same pattern. So this CL creates a Type.Setvargen function that they can use instead, so that Type.Vargen can be unexported. A bit clumsy, but it works for now. Change-Id: I7b4f33fac635e2464df2fbc0607ab40902f6f09f Reviewed-on: https://go-review.googlesource.com/c/go/+/345469 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: Cuong Manh Le TryBot-Result: Go Bot --- src/cmd/compile/internal/noder/decl.go | 3 +-- .../compile/internal/typecheck/typecheck.go | 8 +----- src/cmd/compile/internal/types/fmt.go | 4 +-- src/cmd/compile/internal/types/type.go | 25 ++++++++++++++++--- 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go index b23dd47600..54a13b498b 100644 --- a/src/cmd/compile/internal/noder/decl.go +++ b/src/cmd/compile/internal/noder/decl.go @@ -154,8 +154,7 @@ func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) { name, obj := g.def(decl.Name) ntyp, otyp := name.Type(), obj.Type() if ir.CurFunc != nil { - typecheck.TypeGen++ - ntyp.Vargen = typecheck.TypeGen + ntyp.SetVargen() } pragmas := g.pragmaFlags(decl.Pragma, typePragmas) diff --git a/src/cmd/compile/internal/typecheck/typecheck.go b/src/cmd/compile/internal/typecheck/typecheck.go index db1b11c4cf..404af5b1b2 100644 --- a/src/cmd/compile/internal/typecheck/typecheck.go +++ b/src/cmd/compile/internal/typecheck/typecheck.go @@ -1736,11 +1736,6 @@ func CheckMapKeys() { mapqueue = nil } -// TypeGen tracks the number of function-scoped defined types that -// have been declared. It's used to generate unique linker symbols for -// their runtime type descriptors. -var TypeGen int32 - func typecheckdeftype(n *ir.Name) { if base.EnableTrace && base.Flag.LowerT { defer tracePrint("typecheckdeftype", n)(nil) @@ -1748,8 +1743,7 @@ func typecheckdeftype(n *ir.Name) { t := types.NewNamed(n) if n.Curfn != nil { - TypeGen++ - t.Vargen = TypeGen + t.SetVargen() } if n.Pragma()&ir.NotInHeap != 0 { diff --git a/src/cmd/compile/internal/types/fmt.go b/src/cmd/compile/internal/types/fmt.go index b1b8506400..74ebfad5bb 100644 --- a/src/cmd/compile/internal/types/fmt.go +++ b/src/cmd/compile/internal/types/fmt.go @@ -361,8 +361,8 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type // output too. It seems like it should, but that mode is currently // used in string representation used by reflection, which is // user-visible and doesn't expect this. - if mode == fmtTypeID && t.Vargen != 0 { - fmt.Fprintf(b, "·%d", t.Vargen) + if mode == fmtTypeID && t.vargen != 0 { + fmt.Fprintf(b, "·%d", t.vargen) } return } diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 975280753a..06348c5094 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -178,7 +178,7 @@ type Type struct { } sym *Sym // symbol containing name, for named types - Vargen int32 // unique name for OTYPE/ONAME + vargen int32 // unique name for OTYPE/ONAME kind Kind // kind of type Align uint8 // the required alignment of this type, in bytes (0 means Width and Align have not yet been computed) @@ -1221,8 +1221,8 @@ func (t *Type) cmp(x *Type) Cmp { if x.sym != nil { // Syms non-nil, if vargens match then equal. - if t.Vargen != x.Vargen { - return cmpForNe(t.Vargen < x.Vargen) + if t.vargen != x.vargen { + return cmpForNe(t.vargen < x.vargen) } return CMPeq } @@ -1768,6 +1768,25 @@ func (t *Type) Obj() Object { return nil } +// typeGen tracks the number of function-scoped defined types that +// have been declared. It's used to generate unique linker symbols for +// their runtime type descriptors. +var typeGen int32 + +// SetVargen assigns a unique generation number to type t, which must +// be a defined type declared within function scope. The generation +// number is used to distinguish it from other similarly spelled +// defined types from the same package. +// +// TODO(mdempsky): Come up with a better solution. +func (t *Type) SetVargen() { + base.Assertf(t.Sym() != nil, "SetVargen on anonymous type %v", t) + base.Assertf(t.vargen == 0, "type %v already has Vargen %v", t, t.vargen) + + typeGen++ + t.vargen = typeGen +} + // SetUnderlying sets the underlying type. SetUnderlying automatically updates any // types that were waiting for this type to be completed. func (t *Type) SetUnderlying(underlying *Type) { -- GitLab From c9e05fdcf7fd49e9b27f8bcb16347d17d04bc4e7 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 24 Aug 2021 17:35:51 -0700 Subject: [PATCH 0863/2500] cmd/compile: fix reference to generic type needed by crawler This problem happens when you create a new local type that uses an imported generic type (maybe just by instantiating it), and then that local type needed to be included as part of an export. In that case, the imported generic type is does not have a declaration in the local package, so it is not necessarily created in types1, so the crawler/export doesn't work. To fix this issue, we just need to add a call to g.obj() for the base generic type, to make sure that it will exist if needed later in the compilation or for the crawler during export. Fixes #47514 Change-Id: Ie756578f07ad0007de8a88ae909cf7534a22936e Reviewed-on: https://go-review.googlesource.com/c/go/+/345411 Reviewed-by: Keith Randall Trust: Dan Scales --- src/cmd/compile/internal/noder/types.go | 7 ++++++- test/typeparam/issue47514c.dir/a.go | 5 +++++ test/typeparam/issue47514c.dir/main.go | 10 ++++++++++ test/typeparam/issue47514c.go | 7 +++++++ 4 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 test/typeparam/issue47514c.dir/a.go create mode 100644 test/typeparam/issue47514c.dir/main.go create mode 100644 test/typeparam/issue47514c.go diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index c9f7c2bbe4..a5a90aacaa 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -118,9 +118,14 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { return s.Def.Type() } + // Make sure the base generic type exists in type1 (it may + // not yet if we are referecing an imported generic type, as + // opposed to a generic type declared in this package). + _ = g.obj(typ.Orig().Obj()) + // Create a forwarding type first and put it in the g.typs // map, in order to deal with recursive generic types - // (including via method signatures).. Set up the extra + // (including via method signatures). Set up the extra // ntyp information (Def, RParams, which may set // HasTParam) before translating the underlying type // itself, so we handle recursion correctly. diff --git a/test/typeparam/issue47514c.dir/a.go b/test/typeparam/issue47514c.dir/a.go new file mode 100644 index 0000000000..782b1d2a4f --- /dev/null +++ b/test/typeparam/issue47514c.dir/a.go @@ -0,0 +1,5 @@ +package a + +type Doer[T any] interface { + Do() T +} diff --git a/test/typeparam/issue47514c.dir/main.go b/test/typeparam/issue47514c.dir/main.go new file mode 100644 index 0000000000..bc1166f761 --- /dev/null +++ b/test/typeparam/issue47514c.dir/main.go @@ -0,0 +1,10 @@ +package main + +import "a" + +func Do[T any](doer a.Doer[T]) { + doer.Do() +} + +func main() { +} diff --git a/test/typeparam/issue47514c.go b/test/typeparam/issue47514c.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/issue47514c.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From 03db2c24136939416903b284a19905d97ceea40d Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 26 Aug 2021 11:56:52 -0700 Subject: [PATCH 0864/2500] cmd/compile/internal/types2: implement TypeList.String (debugging support) Change-Id: Iaa203def3dac94a7d5ff6120e89315c3d7977ee1 Reviewed-on: https://go-review.googlesource.com/c/go/+/345471 Trust: Robert Griesemer Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/types2/instantiate.go | 2 +- src/cmd/compile/internal/types2/subst.go | 6 ------ src/cmd/compile/internal/types2/typelists.go | 13 +++++++++++++ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index f9cde24dfc..4113d248b8 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -75,7 +75,7 @@ func Instantiate(env *Environment, typ Type, targs []Type, validate bool) (Type, func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, posList []syntax.Pos) (res Type) { assert(check != nil) if check.conf.Trace { - check.trace(pos, "-- instantiating %s with %s", typ, typeListString(targs)) + check.trace(pos, "-- instantiating %s with %s", typ, NewTypeList(targs)) check.indent++ defer func() { check.indent-- diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index ff8dd13b6d..7c33e7ade4 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -281,12 +281,6 @@ func instantiatedHash(typ *Named, targs []Type) string { return string(res[:i]) } -func typeListString(list []Type) string { - var buf bytes.Buffer - writeTypeList(&buf, list, nil, nil) - return buf.String() -} - // typOrNil is like typ but if the argument is nil it is replaced with Typ[Invalid]. // A nil type may appear in pathological cases such as type T[P any] []func(_ T([]_)) // where an array/slice element is accessed before it is set up. diff --git a/src/cmd/compile/internal/types2/typelists.go b/src/cmd/compile/internal/types2/typelists.go index 3258a5e9f8..c3befb077f 100644 --- a/src/cmd/compile/internal/types2/typelists.go +++ b/src/cmd/compile/internal/types2/typelists.go @@ -4,6 +4,8 @@ package types2 +import "bytes" + // TParamList holds a list of type parameters. type TParamList struct{ tparams []*TypeParam } @@ -52,6 +54,17 @@ func (l *TypeList) list() []Type { return l.types } +func (l *TypeList) String() string { + if l == nil || len(l.types) == 0 { + return "[]" + } + var buf bytes.Buffer + buf.WriteByte('[') + writeTypeList(&buf, l.types, nil, nil) + buf.WriteByte(']') + return buf.String() +} + // ---------------------------------------------------------------------------- // Implementation -- GitLab From af80af22b507ae23ae04372f30b98f7720c85f8a Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 26 Aug 2021 12:27:06 -0700 Subject: [PATCH 0865/2500] cmd/compile/internal/types2: do not declare new methods on instantiated types Report an error if an alias is used to declare a method on an instantiated type. Also, when resolving the receiver type, don't use asNamed to avoid premature expansion of the type. Fixes #47968. Change-Id: Ie5acc4cfb1944deaaeeaee98707f31e256f8ef5e Reviewed-on: https://go-review.googlesource.com/c/go/+/345472 Trust: Robert Griesemer Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/types2/signature.go | 8 ++++++- .../types2/testdata/fixedbugs/issue47968.go2 | 21 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue47968.go2 diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index d28e7b8944..ddad1f0311 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -132,7 +132,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] // Also: Don't report an error via genericType since it will be reported // again when we type-check the signature. // TODO(gri) maybe the receiver should be marked as invalid instead? - if recv := asNamed(check.genericType(rname, false)); recv != nil { + if recv, _ := check.genericType(rname, false).(*Named); recv != nil { recvTParams = recv.TParams().list() } } @@ -211,6 +211,12 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] switch T := rtyp.(type) { case *Named: T.expand(nil) + // The receiver type may be an instantiated type referred to + // by an alias (which cannot have receiver parameters for now). + if T.TArgs() != nil && sig.RParams() == nil { + check.errorf(recv.pos, "cannot define methods on instantiated type %s", recv.typ) + break + } // spec: "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." diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47968.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47968.go2 new file mode 100644 index 0000000000..bbbe6805f2 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47968.go2 @@ -0,0 +1,21 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T[P any] struct{} + +func (T[P]) m1() + +type A1 = T + +func (A1[P]) m2() {} + +type A2 = T[int] + +func (A2 /* ERROR cannot define methods on instantiated type T\[int\] */) m3() {} +func (_ /* ERROR cannot define methods on instantiated type T\[int\] */ A2) m4() {} + +func (T[int]) m5() {} // int is the type parameter name, not an instantiation +func (T[* /* ERROR must be an identifier */ int]) m6() {} // syntax error -- GitLab From 967a8017f7d41717335ee020e46e2c55c5c9e96e Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 26 Aug 2021 13:17:56 -0700 Subject: [PATCH 0866/2500] cmd/compile: move types init code into package types This moves the package types setup code from package typecheck into package types itself. This is a prereq for making types.Type more opaque, because some unit tests depend on being able to init the basic universal types. A few notable details of this CL: 1. Creating the builtin types requires being able to create the ir.Name/ir.OTYPE that represents it, but package types can't depend on package ir. So we add a callback function to handle creating the ir.Name. 2. This CL moves ir.Pkgs.Unsafe to types.UnsafePkg. Package unsafe is part of the language, not like the other ir.Pkgs packages that are purely implementation details. 3. This CL also moves typecheck.FakeRecv to types.FakeRecv, addressing an outstanding TODO. Change-Id: I64de04ce82fbcd1bb59f547e2eea3cda52d89429 Reviewed-on: https://go-review.googlesource.com/c/go/+/345474 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/gc/main.go | 2 +- src/cmd/compile/internal/ir/symtab.go | 1 - src/cmd/compile/internal/noder/import.go | 4 +- src/cmd/compile/internal/noder/noder.go | 2 +- src/cmd/compile/internal/noder/reader.go | 4 +- src/cmd/compile/internal/noder/types.go | 4 +- .../compile/internal/reflectdata/reflect.go | 2 +- src/cmd/compile/internal/typecheck/dcl.go | 7 - src/cmd/compile/internal/typecheck/iexport.go | 6 +- src/cmd/compile/internal/typecheck/iimport.go | 4 +- .../compile/internal/typecheck/universe.go | 144 +----------------- src/cmd/compile/internal/types/fmt.go | 3 + src/cmd/compile/internal/types/type.go | 4 + src/cmd/compile/internal/types/universe.go | 144 ++++++++++++++++++ 14 files changed, 171 insertions(+), 160 deletions(-) create mode 100644 src/cmd/compile/internal/types/universe.go diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 9660ef9dd5..8a365f8f6a 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -84,7 +84,7 @@ func Main(archInit func(*ssagen.ArchInfo)) { types.BuiltinPkg.Prefix = "go.builtin" // not go%2ebuiltin // pseudo-package, accessed by import "unsafe" - ir.Pkgs.Unsafe = types.NewPkg("unsafe", "unsafe") + types.UnsafePkg = types.NewPkg("unsafe", "unsafe") // Pseudo-package that contains the compiler's builtin // declarations for package runtime. These are declared in a diff --git a/src/cmd/compile/internal/ir/symtab.go b/src/cmd/compile/internal/ir/symtab.go index 61727fb1c4..1e8261810f 100644 --- a/src/cmd/compile/internal/ir/symtab.go +++ b/src/cmd/compile/internal/ir/symtab.go @@ -68,5 +68,4 @@ var Pkgs struct { Go *types.Pkg Itab *types.Pkg Runtime *types.Pkg - Unsafe *types.Pkg } diff --git a/src/cmd/compile/internal/noder/import.go b/src/cmd/compile/internal/noder/import.go index 48f0e48028..c26340c960 100644 --- a/src/cmd/compile/internal/noder/import.go +++ b/src/cmd/compile/internal/noder/import.go @@ -198,7 +198,7 @@ func importfile(decl *syntax.ImportDecl) *types.Pkg { return nil } - if pkg != ir.Pkgs.Unsafe && pkg.Height >= myheight { + if pkg != types.UnsafePkg && pkg.Height >= myheight { myheight = pkg.Height + 1 } return pkg @@ -231,7 +231,7 @@ func readImportFile(path string, target *ir.Package, check *types2.Checker, pack } if path == "unsafe" { - pkg1, pkg2 = ir.Pkgs.Unsafe, types2.Unsafe + pkg1, pkg2 = types.UnsafePkg, types2.Unsafe // TODO(mdempsky): Investigate if this actually matters. Why would // the linker or runtime care whether a package imported unsafe? diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index e1b485b2b3..61a7f8aad4 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -384,7 +384,7 @@ func (p *noder) importDecl(imp *syntax.ImportDecl) { return } - if ipkg == ir.Pkgs.Unsafe { + if ipkg == types.UnsafePkg { p.importedUnsafe = true } if ipkg.Path == "embed" { diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 985453a1bb..e7a9d9655b 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -428,7 +428,7 @@ func (r *reader) interfaceType() *types.Type { pos := r.pos() pkg, sym := r.selector() tpkg = pkg - mtyp := r.signature(pkg, typecheck.FakeRecv()) + mtyp := r.signature(pkg, types.FakeRecv()) methods[i] = types.NewField(pos, sym, mtyp) } for i := range embeddeds { @@ -540,7 +540,7 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node if tag == objStub { assert(!sym.IsBlank()) switch sym.Pkg { - case types.BuiltinPkg, ir.Pkgs.Unsafe: + case types.BuiltinPkg, types.UnsafePkg: return sym.Def.(ir.Node) } if pri, ok := objReader[sym]; ok { diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index a5a90aacaa..f5d91097f2 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -22,7 +22,7 @@ func (g *irgen) pkg(pkg *types2.Package) *types.Pkg { case g.self: return types.LocalPkg case types2.Unsafe: - return ir.Pkgs.Unsafe + return types.UnsafePkg } return types.NewPkg(pkg.Path(), pkg.Name()) } @@ -206,7 +206,7 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { methods := make([]*types.Field, typ.NumExplicitMethods()) for i := range methods { m := typ.ExplicitMethod(i) - mtyp := g.signature(typecheck.FakeRecv(), m.Type().(*types2.Signature)) + mtyp := g.signature(types.FakeRecv(), m.Type().(*types2.Signature)) methods[i] = types.NewField(g.pos(m), g.selector(m), mtyp) } diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 9b9efe04a2..deb806beac 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -1726,7 +1726,7 @@ func NeedEmit(typ *types.Type) bool { // Local defined type; our responsibility. return true - case base.Ctxt.Pkgpath == "runtime" && (sym.Pkg == types.BuiltinPkg || sym.Pkg == ir.Pkgs.Unsafe): + case base.Ctxt.Pkgpath == "runtime" && (sym.Pkg == types.BuiltinPkg || sym.Pkg == types.UnsafePkg): // Package runtime is responsible for including code for builtin // types (predeclared and package unsafe). return true diff --git a/src/cmd/compile/internal/typecheck/dcl.go b/src/cmd/compile/internal/typecheck/dcl.go index 472d8d2b8a..76fc6de621 100644 --- a/src/cmd/compile/internal/typecheck/dcl.go +++ b/src/cmd/compile/internal/typecheck/dcl.go @@ -314,13 +314,6 @@ func checkembeddedtype(t *types.Type) { } } -// TODO(mdempsky): Move to package types. -func FakeRecv() *types.Field { - return types.NewField(src.NoXPos, nil, types.FakeRecvType()) -} - -var fakeRecvField = FakeRecv - var funcStack []funcStackEnt // stack of previous values of ir.CurFunc/DeclContext type funcStackEnt struct { diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 75d6115783..82006c3245 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -430,7 +430,7 @@ func (p *iexporter) pushDecl(n *ir.Name) { } // Don't export predeclared declarations. - if n.Sym().Pkg == types.BuiltinPkg || n.Sym().Pkg == ir.Pkgs.Unsafe { + if n.Sym().Pkg == types.BuiltinPkg || n.Sym().Pkg == types.UnsafePkg { return } @@ -905,7 +905,7 @@ func (w *exportWriter) doTyp(t *types.Type) { // type orderedAbs[T any] T if t.IsTypeParam() && t.Underlying() == t { assert(base.Flag.G > 0) - if s.Pkg == types.BuiltinPkg || s.Pkg == ir.Pkgs.Unsafe { + if s.Pkg == types.BuiltinPkg || s.Pkg == types.UnsafePkg { base.Fatalf("builtin type missing from typIndex: %v", t) } // Write out the first use of a type param as a qualified ident. @@ -916,7 +916,7 @@ func (w *exportWriter) doTyp(t *types.Type) { } if s != nil { - if s.Pkg == types.BuiltinPkg || s.Pkg == ir.Pkgs.Unsafe { + if s.Pkg == types.BuiltinPkg || s.Pkg == types.UnsafePkg { base.Fatalf("builtin type missing from typIndex: %v", t) } diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index a1a3ac3e8a..87ad5d1c54 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -607,7 +607,7 @@ func (r *importReader) exoticType() *types.Type { case exoticTypeRecv: var rcvr *types.Field if r.bool() { // isFakeRecv - rcvr = fakeRecvField() + rcvr = types.FakeRecv() } else { rcvr = r.exoticParam() } @@ -793,7 +793,7 @@ func (r *importReader) typ1() *types.Type { for i := range methods { pos := r.pos() sym := r.selector() - typ := r.signature(fakeRecvField(), nil) + typ := r.signature(types.FakeRecv(), nil) methods[i] = types.NewField(pos, sym, typ) } diff --git a/src/cmd/compile/internal/typecheck/universe.go b/src/cmd/compile/internal/typecheck/universe.go index a7c84dc8d8..ebe338e2aa 100644 --- a/src/cmd/compile/internal/typecheck/universe.go +++ b/src/cmd/compile/internal/typecheck/universe.go @@ -29,37 +29,6 @@ var ( okforarith [types.NTYPE]bool ) -var basicTypes = [...]struct { - name string - etype types.Kind -}{ - {"int8", types.TINT8}, - {"int16", types.TINT16}, - {"int32", types.TINT32}, - {"int64", types.TINT64}, - {"uint8", types.TUINT8}, - {"uint16", types.TUINT16}, - {"uint32", types.TUINT32}, - {"uint64", types.TUINT64}, - {"float32", types.TFLOAT32}, - {"float64", types.TFLOAT64}, - {"complex64", types.TCOMPLEX64}, - {"complex128", types.TCOMPLEX128}, - {"bool", types.TBOOL}, - {"string", types.TSTRING}, -} - -var typedefs = [...]struct { - name string - etype types.Kind - sameas32 types.Kind - sameas64 types.Kind -}{ - {"int", types.TINT, types.TINT32, types.TINT64}, - {"uint", types.TUINT, types.TUINT32, types.TUINT64}, - {"uintptr", types.TUINTPTR, types.TUINT32, types.TUINT64}, -} - var builtinFuncs = [...]struct { name string op ir.Op @@ -94,86 +63,12 @@ var unsafeFuncs = [...]struct { // InitUniverse initializes the universe block. func InitUniverse() { - if types.PtrSize == 0 { - base.Fatalf("typeinit before betypeinit") - } - - types.SlicePtrOffset = 0 - types.SliceLenOffset = types.Rnd(types.SlicePtrOffset+int64(types.PtrSize), int64(types.PtrSize)) - types.SliceCapOffset = types.Rnd(types.SliceLenOffset+int64(types.PtrSize), int64(types.PtrSize)) - types.SliceSize = types.Rnd(types.SliceCapOffset+int64(types.PtrSize), int64(types.PtrSize)) - - // string is same as slice wo the cap - types.StringSize = types.Rnd(types.SliceLenOffset+int64(types.PtrSize), int64(types.PtrSize)) - - for et := types.Kind(0); et < types.NTYPE; et++ { - types.SimType[et] = et - } - - types.Types[types.TANY] = types.New(types.TANY) - types.Types[types.TINTER] = types.NewInterface(types.LocalPkg, nil) - - defBasic := func(kind types.Kind, pkg *types.Pkg, name string) *types.Type { - sym := pkg.Lookup(name) + types.InitTypes(func(sym *types.Sym, typ *types.Type) types.Object { n := ir.NewDeclNameAt(src.NoXPos, ir.OTYPE, sym) - t := types.NewBasic(kind, n) - n.SetType(t) + n.SetType(typ) sym.Def = n - if kind != types.TANY { - types.CalcSize(t) - } - return t - } - - for _, s := range &basicTypes { - types.Types[s.etype] = defBasic(s.etype, types.BuiltinPkg, s.name) - } - - for _, s := range &typedefs { - sameas := s.sameas32 - if types.PtrSize == 8 { - sameas = s.sameas64 - } - types.SimType[s.etype] = sameas - - types.Types[s.etype] = defBasic(s.etype, types.BuiltinPkg, s.name) - } - - // We create separate byte and rune types for better error messages - // rather than just creating type alias *types.Sym's for the uint8 and - // int32 types. Hence, (bytetype|runtype).Sym.isAlias() is false. - // TODO(gri) Should we get rid of this special case (at the cost - // of less informative error messages involving bytes and runes)? - // (Alternatively, we could introduce an OTALIAS node representing - // type aliases, albeit at the cost of having to deal with it everywhere). - types.ByteType = defBasic(types.TUINT8, types.BuiltinPkg, "byte") - types.RuneType = defBasic(types.TINT32, types.BuiltinPkg, "rune") - - // error type - s := types.BuiltinPkg.Lookup("error") - n := ir.NewDeclNameAt(src.NoXPos, ir.OTYPE, s) - types.ErrorType = types.NewNamed(n) - types.ErrorType.SetUnderlying(makeErrorInterface()) - n.SetType(types.ErrorType) - s.Def = n - types.CalcSize(types.ErrorType) - - // comparable type (interface) - s = types.BuiltinPkg.Lookup("comparable") - n = ir.NewDeclNameAt(src.NoXPos, ir.OTYPE, s) - types.ComparableType = types.NewNamed(n) - types.ComparableType.SetUnderlying(makeComparableInterface()) - n.SetType(types.ComparableType) - s.Def = n - types.CalcSize(types.ComparableType) - - types.Types[types.TUNSAFEPTR] = defBasic(types.TUNSAFEPTR, ir.Pkgs.Unsafe, "Pointer") - - // simple aliases - types.SimType[types.TMAP] = types.TPTR - types.SimType[types.TCHAN] = types.TPTR - types.SimType[types.TFUNC] = types.TPTR - types.SimType[types.TUNSAFEPTR] = types.TPTR + return n + }) for _, s := range &builtinFuncs { s2 := types.BuiltinPkg.Lookup(s.name) @@ -183,13 +78,13 @@ func InitUniverse() { } for _, s := range &unsafeFuncs { - s2 := ir.Pkgs.Unsafe.Lookup(s.name) + s2 := types.UnsafePkg.Lookup(s.name) def := NewName(s2) def.BuiltinOp = s.op s2.Def = def } - s = types.BuiltinPkg.Lookup("true") + s := types.BuiltinPkg.Lookup("true") s.Def = ir.NewConstAt(src.NoXPos, s, types.UntypedBool, constant.MakeBool(true)) s = types.BuiltinPkg.Lookup("false") @@ -219,19 +114,6 @@ func InitUniverse() { s = types.BuiltinPkg.Lookup("iota") s.Def = ir.NewIota(base.Pos, s) - for et := types.TINT8; et <= types.TUINT64; et++ { - types.IsInt[et] = true - } - types.IsInt[types.TINT] = true - types.IsInt[types.TUINT] = true - types.IsInt[types.TUINTPTR] = true - - types.IsFloat[types.TFLOAT32] = true - types.IsFloat[types.TFLOAT64] = true - - types.IsComplex[types.TCOMPLEX64] = true - types.IsComplex[types.TCOMPLEX128] = true - // initialize okfor for et := types.Kind(0); et < types.NTYPE; et++ { if types.IsInt[et] || et == types.TIDEAL { @@ -331,20 +213,6 @@ func InitUniverse() { okfor[ir.OLEN] = okforlen[:] } -func makeErrorInterface() *types.Type { - sig := types.NewSignature(types.NoPkg, fakeRecvField(), nil, nil, []*types.Field{ - types.NewField(src.NoXPos, nil, types.Types[types.TSTRING]), - }) - method := types.NewField(src.NoXPos, Lookup("Error"), sig) - return types.NewInterface(types.NoPkg, []*types.Field{method}) -} - -func makeComparableInterface() *types.Type { - sig := types.NewSignature(types.NoPkg, fakeRecvField(), nil, nil, nil) - method := types.NewField(src.NoXPos, Lookup("=="), sig) - return types.NewInterface(types.NoPkg, []*types.Field{method}) -} - // DeclareUniverse makes the universe block visible within the current package. func DeclareUniverse() { // Operationally, this is similar to a dot import of builtinpkg, except diff --git a/src/cmd/compile/internal/types/fmt.go b/src/cmd/compile/internal/types/fmt.go index 74ebfad5bb..2f81c7b2e1 100644 --- a/src/cmd/compile/internal/types/fmt.go +++ b/src/cmd/compile/internal/types/fmt.go @@ -23,6 +23,9 @@ var BuiltinPkg *Pkg // LocalPkg is the package being compiled. var LocalPkg *Pkg +// UnsafePkg is package unsafe. +var UnsafePkg *Pkg + // BlankSym is the blank (_) symbol. var BlankSym *Sym diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 06348c5094..e84e89fd15 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -1738,6 +1738,10 @@ func FakeRecvType() *Type { return recvType } +func FakeRecv() *Field { + return NewField(src.NoXPos, nil, FakeRecvType()) +} + var ( // TSSA types. HasPointers assumes these are pointer-free. TypeInvalid = newSSA("invalid") diff --git a/src/cmd/compile/internal/types/universe.go b/src/cmd/compile/internal/types/universe.go new file mode 100644 index 0000000000..abceecd15d --- /dev/null +++ b/src/cmd/compile/internal/types/universe.go @@ -0,0 +1,144 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +import ( + "cmd/compile/internal/base" + "cmd/internal/src" +) + +var basicTypes = [...]struct { + name string + etype Kind +}{ + {"int8", TINT8}, + {"int16", TINT16}, + {"int32", TINT32}, + {"int64", TINT64}, + {"uint8", TUINT8}, + {"uint16", TUINT16}, + {"uint32", TUINT32}, + {"uint64", TUINT64}, + {"float32", TFLOAT32}, + {"float64", TFLOAT64}, + {"complex64", TCOMPLEX64}, + {"complex128", TCOMPLEX128}, + {"bool", TBOOL}, + {"string", TSTRING}, +} + +var typedefs = [...]struct { + name string + etype Kind + sameas32 Kind + sameas64 Kind +}{ + {"int", TINT, TINT32, TINT64}, + {"uint", TUINT, TUINT32, TUINT64}, + {"uintptr", TUINTPTR, TUINT32, TUINT64}, +} + +func InitTypes(defTypeName func(sym *Sym, typ *Type) Object) { + if PtrSize == 0 { + base.Fatalf("typeinit before betypeinit") + } + + SlicePtrOffset = 0 + SliceLenOffset = Rnd(SlicePtrOffset+int64(PtrSize), int64(PtrSize)) + SliceCapOffset = Rnd(SliceLenOffset+int64(PtrSize), int64(PtrSize)) + SliceSize = Rnd(SliceCapOffset+int64(PtrSize), int64(PtrSize)) + + // string is same as slice wo the cap + StringSize = Rnd(SliceLenOffset+int64(PtrSize), int64(PtrSize)) + + for et := Kind(0); et < NTYPE; et++ { + SimType[et] = et + } + + Types[TANY] = New(TANY) + Types[TINTER] = NewInterface(LocalPkg, nil) + + defBasic := func(kind Kind, pkg *Pkg, name string) *Type { + typ := New(kind) + obj := defTypeName(pkg.Lookup(name), typ) + typ.sym = obj.Sym() + typ.nod = obj + if kind != TANY { + CheckSize(typ) + } + return typ + } + + for _, s := range &basicTypes { + Types[s.etype] = defBasic(s.etype, BuiltinPkg, s.name) + } + + for _, s := range &typedefs { + sameas := s.sameas32 + if PtrSize == 8 { + sameas = s.sameas64 + } + SimType[s.etype] = sameas + + Types[s.etype] = defBasic(s.etype, BuiltinPkg, s.name) + } + + // We create separate byte and rune types for better error messages + // rather than just creating type alias *Sym's for the uint8 and + // int32 Hence, (bytetype|runtype).Sym.isAlias() is false. + // TODO(gri) Should we get rid of this special case (at the cost + // of less informative error messages involving bytes and runes)? + // (Alternatively, we could introduce an OTALIAS node representing + // type aliases, albeit at the cost of having to deal with it everywhere). + ByteType = defBasic(TUINT8, BuiltinPkg, "byte") + RuneType = defBasic(TINT32, BuiltinPkg, "rune") + + // error type + DeferCheckSize() + ErrorType = defBasic(TFORW, BuiltinPkg, "error") + ErrorType.SetUnderlying(makeErrorInterface()) + ResumeCheckSize() + + // comparable type (interface) + DeferCheckSize() + ComparableType = defBasic(TFORW, BuiltinPkg, "comparable") + ComparableType.SetUnderlying(makeComparableInterface()) + ResumeCheckSize() + + Types[TUNSAFEPTR] = defBasic(TUNSAFEPTR, UnsafePkg, "Pointer") + + // simple aliases + SimType[TMAP] = TPTR + SimType[TCHAN] = TPTR + SimType[TFUNC] = TPTR + SimType[TUNSAFEPTR] = TPTR + + for et := TINT8; et <= TUINT64; et++ { + IsInt[et] = true + } + IsInt[TINT] = true + IsInt[TUINT] = true + IsInt[TUINTPTR] = true + + IsFloat[TFLOAT32] = true + IsFloat[TFLOAT64] = true + + IsComplex[TCOMPLEX64] = true + IsComplex[TCOMPLEX128] = true +} + +func makeErrorInterface() *Type { + sig := NewSignature(NoPkg, FakeRecv(), nil, nil, []*Field{ + NewField(src.NoXPos, nil, Types[TSTRING]), + }) + method := NewField(src.NoXPos, LocalPkg.Lookup("Error"), sig) + return NewInterface(NoPkg, []*Field{method}) +} + +func makeComparableInterface() *Type { + sig := NewSignature(NoPkg, FakeRecv(), nil, nil, nil) + method := NewField(src.NoXPos, LocalPkg.Lookup("=="), sig) + return NewInterface(NoPkg, []*Field{method}) +} -- GitLab From f153b6739b30c1e99f8646f2dafc77a92204f10d Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 26 Aug 2021 14:16:24 -0700 Subject: [PATCH 0867/2500] cmd/compile: use typecheck.InitUniverse in unit tests Rather than ad hoc setting up the universe, just initialize it properly. Change-Id: I18484b952321f55eb3e1e48fd383068a4ee75f66 Reviewed-on: https://go-review.googlesource.com/c/go/+/345475 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/cmd/compile/internal/ssa/export_test.go | 37 +++++---------------- 1 file changed, 9 insertions(+), 28 deletions(-) diff --git a/src/cmd/compile/internal/ssa/export_test.go b/src/cmd/compile/internal/ssa/export_test.go index 6d3c0f3ccb..c4e87ec7d0 100644 --- a/src/cmd/compile/internal/ssa/export_test.go +++ b/src/cmd/compile/internal/ssa/export_test.go @@ -5,14 +5,16 @@ package ssa import ( + "testing" + "cmd/compile/internal/ir" + "cmd/compile/internal/typecheck" "cmd/compile/internal/types" "cmd/internal/obj" "cmd/internal/obj/arm64" "cmd/internal/obj/s390x" "cmd/internal/obj/x86" "cmd/internal/src" - "testing" ) var CheckFunc = checkFunc @@ -104,33 +106,12 @@ func (d TestFrontend) MyImportPath() string { var testTypes Types func init() { - // Initialize just enough of the universe and the types package to make our tests function. - // TODO(josharian): move universe initialization to the types package, - // so this test setup can share it. - - for _, typ := range [...]struct { - width int64 - et types.Kind - }{ - {1, types.TINT8}, - {1, types.TUINT8}, - {1, types.TBOOL}, - {2, types.TINT16}, - {2, types.TUINT16}, - {4, types.TINT32}, - {4, types.TUINT32}, - {4, types.TFLOAT32}, - {4, types.TFLOAT64}, - {8, types.TUINT64}, - {8, types.TINT64}, - {8, types.TINT}, - {8, types.TUINTPTR}, - } { - t := types.New(typ.et) - t.Width = typ.width - t.Align = uint8(typ.width) - types.Types[typ.et] = t - } + // TODO(mdempsky): Push into types.InitUniverse or typecheck.InitUniverse. + types.PtrSize = 8 + types.RegSize = 8 + types.MaxWidth = 1 << 50 + + typecheck.InitUniverse() testTypes.SetTypPtrs() } -- GitLab From e7eee5e265440b0ed3b76093ccdfd776facc767a Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 26 Aug 2021 15:30:40 -0700 Subject: [PATCH 0868/2500] cmd/compile: remove ssagen/pgen_test.go This test was written in 2015, and hasn't had any meaningful changes to it since. However, it's very ad hoc and pokes into internals that it shouldn't, and it keeps getting in the way of more meaningful refactorings. It doesn't even catch bugs; e.g., it didn't catch that cmpstackvarlt wasn't asymmetric (CL 19778), and a bunch of its test cases are bogus because we never actually use it to sort ir.PFUNC nodes (assert added in this CL). The compiler is woefully lacking in unit tests like these, but I strongly feel this test is more of a hinderance than a help at the moment. Change-Id: I3ac7a3e533947aa95f325626c6eec13a43789f9d Reviewed-on: https://go-review.googlesource.com/c/go/+/345478 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/cmd/compile/internal/ssagen/pgen.go | 17 +- src/cmd/compile/internal/ssagen/pgen_test.go | 209 ------------------- 2 files changed, 16 insertions(+), 210 deletions(-) delete mode 100644 src/cmd/compile/internal/ssagen/pgen_test.go diff --git a/src/cmd/compile/internal/ssagen/pgen.go b/src/cmd/compile/internal/ssagen/pgen.go index 93157bfa11..0ddf11b426 100644 --- a/src/cmd/compile/internal/ssagen/pgen.go +++ b/src/cmd/compile/internal/ssagen/pgen.go @@ -75,7 +75,22 @@ func (s byStackVar) Swap(i, j int) { s[i], s[j] = s[j], s[i] } // allocate space. In particular, it excludes arguments and results, which are in // the callers frame. func needAlloc(n *ir.Name) bool { - return n.Class == ir.PAUTO || n.Class == ir.PPARAMOUT && n.IsOutputParamInRegisters() + if n.Op() != ir.ONAME { + base.FatalfAt(n.Pos(), "%v has unexpected Op %v", n, n.Op()) + } + + switch n.Class { + case ir.PAUTO: + return true + case ir.PPARAM: + return false + case ir.PPARAMOUT: + return n.IsOutputParamInRegisters() + + default: + base.FatalfAt(n.Pos(), "%v has unexpected Class %v", n, n.Class) + return false + } } func (s *ssafn) AllocFrame(f *ssa.Func) { diff --git a/src/cmd/compile/internal/ssagen/pgen_test.go b/src/cmd/compile/internal/ssagen/pgen_test.go deleted file mode 100644 index 69ed8ad74e..0000000000 --- a/src/cmd/compile/internal/ssagen/pgen_test.go +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ssagen - -import ( - "reflect" - "sort" - "testing" - - "cmd/compile/internal/ir" - "cmd/compile/internal/typecheck" - "cmd/compile/internal/types" - "cmd/internal/src" -) - -func typeWithoutPointers() *types.Type { - return types.NewStruct(types.NoPkg, []*types.Field{ - types.NewField(src.NoXPos, nil, types.New(types.TINT)), - }) -} - -func typeWithPointers() *types.Type { - return types.NewStruct(types.NoPkg, []*types.Field{ - types.NewField(src.NoXPos, nil, types.NewPtr(types.New(types.TINT))), - }) -} - -func markUsed(n *ir.Name) *ir.Name { - n.SetUsed(true) - return n -} - -func markNeedZero(n *ir.Name) *ir.Name { - n.SetNeedzero(true) - return n -} - -// Test all code paths for cmpstackvarlt. -func TestCmpstackvar(t *testing.T) { - nod := func(xoffset int64, t *types.Type, s *types.Sym, cl ir.Class) *ir.Name { - if s == nil { - s = &types.Sym{Name: "."} - } - n := typecheck.NewName(s) - n.SetType(t) - n.SetFrameOffset(xoffset) - n.Class = cl - return n - } - testdata := []struct { - a, b *ir.Name - lt bool - }{ - { - nod(0, nil, nil, ir.PAUTO), - nod(0, nil, nil, ir.PFUNC), - false, - }, - { - nod(0, nil, nil, ir.PFUNC), - nod(0, nil, nil, ir.PAUTO), - true, - }, - { - nod(0, nil, nil, ir.PFUNC), - nod(10, nil, nil, ir.PFUNC), - true, - }, - { - nod(20, nil, nil, ir.PFUNC), - nod(10, nil, nil, ir.PFUNC), - false, - }, - { - nod(10, nil, nil, ir.PFUNC), - nod(10, nil, nil, ir.PFUNC), - false, - }, - { - nod(10, nil, nil, ir.PPARAM), - nod(20, nil, nil, ir.PPARAMOUT), - true, - }, - { - nod(10, nil, nil, ir.PPARAMOUT), - nod(20, nil, nil, ir.PPARAM), - true, - }, - { - markUsed(nod(0, nil, nil, ir.PAUTO)), - nod(0, nil, nil, ir.PAUTO), - true, - }, - { - nod(0, nil, nil, ir.PAUTO), - markUsed(nod(0, nil, nil, ir.PAUTO)), - false, - }, - { - nod(0, typeWithoutPointers(), nil, ir.PAUTO), - nod(0, typeWithPointers(), nil, ir.PAUTO), - false, - }, - { - nod(0, typeWithPointers(), nil, ir.PAUTO), - nod(0, typeWithoutPointers(), nil, ir.PAUTO), - true, - }, - { - markNeedZero(nod(0, &types.Type{}, nil, ir.PAUTO)), - nod(0, &types.Type{}, nil, ir.PAUTO), - true, - }, - { - nod(0, &types.Type{}, nil, ir.PAUTO), - markNeedZero(nod(0, &types.Type{}, nil, ir.PAUTO)), - false, - }, - { - nod(0, &types.Type{Width: 1}, nil, ir.PAUTO), - nod(0, &types.Type{Width: 2}, nil, ir.PAUTO), - false, - }, - { - nod(0, &types.Type{Width: 2}, nil, ir.PAUTO), - nod(0, &types.Type{Width: 1}, nil, ir.PAUTO), - true, - }, - { - nod(0, &types.Type{}, &types.Sym{Name: "abc"}, ir.PAUTO), - nod(0, &types.Type{}, &types.Sym{Name: "xyz"}, ir.PAUTO), - true, - }, - { - nod(0, &types.Type{}, &types.Sym{Name: "abc"}, ir.PAUTO), - nod(0, &types.Type{}, &types.Sym{Name: "abc"}, ir.PAUTO), - false, - }, - { - nod(0, &types.Type{}, &types.Sym{Name: "xyz"}, ir.PAUTO), - nod(0, &types.Type{}, &types.Sym{Name: "abc"}, ir.PAUTO), - false, - }, - } - for _, d := range testdata { - got := cmpstackvarlt(d.a, d.b) - if got != d.lt { - t.Errorf("want %v < %v", d.a, d.b) - } - // If we expect a < b to be true, check that b < a is false. - if d.lt && cmpstackvarlt(d.b, d.a) { - t.Errorf("unexpected %v < %v", d.b, d.a) - } - } -} - -func TestStackvarSort(t *testing.T) { - nod := func(xoffset int64, t *types.Type, s *types.Sym, cl ir.Class) *ir.Name { - n := typecheck.NewName(s) - n.SetType(t) - n.SetFrameOffset(xoffset) - n.Class = cl - return n - } - inp := []*ir.Name{ - nod(0, &types.Type{}, &types.Sym{}, ir.PFUNC), - nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO), - nod(0, &types.Type{}, &types.Sym{}, ir.PFUNC), - nod(10, &types.Type{}, &types.Sym{}, ir.PFUNC), - nod(20, &types.Type{}, &types.Sym{}, ir.PFUNC), - markUsed(nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO)), - nod(0, typeWithoutPointers(), &types.Sym{}, ir.PAUTO), - nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO), - markNeedZero(nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO)), - nod(0, &types.Type{Width: 1}, &types.Sym{}, ir.PAUTO), - nod(0, &types.Type{Width: 2}, &types.Sym{}, ir.PAUTO), - nod(0, &types.Type{}, &types.Sym{Name: "abc"}, ir.PAUTO), - nod(0, &types.Type{}, &types.Sym{Name: "xyz"}, ir.PAUTO), - } - want := []*ir.Name{ - nod(0, &types.Type{}, &types.Sym{}, ir.PFUNC), - nod(0, &types.Type{}, &types.Sym{}, ir.PFUNC), - nod(10, &types.Type{}, &types.Sym{}, ir.PFUNC), - nod(20, &types.Type{}, &types.Sym{}, ir.PFUNC), - markUsed(nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO)), - markNeedZero(nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO)), - nod(0, &types.Type{Width: 2}, &types.Sym{}, ir.PAUTO), - nod(0, &types.Type{Width: 1}, &types.Sym{}, ir.PAUTO), - nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO), - nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO), - nod(0, &types.Type{}, &types.Sym{Name: "abc"}, ir.PAUTO), - nod(0, &types.Type{}, &types.Sym{Name: "xyz"}, ir.PAUTO), - nod(0, typeWithoutPointers(), &types.Sym{}, ir.PAUTO), - } - sort.Sort(byStackVar(inp)) - if !reflect.DeepEqual(want, inp) { - t.Error("sort failed") - for i := range inp { - g := inp[i] - w := want[i] - eq := reflect.DeepEqual(w, g) - if !eq { - t.Log(i, w, g) - } - } - } -} -- GitLab From 62f88b6dc8782cedf1a945e4992abda3bc0ad67d Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 26 Aug 2021 15:54:44 -0700 Subject: [PATCH 0869/2500] cmd/compile: add types.RecalcSize This is the only case where Align is assigned outside of package types. Rather than adding a SetAlign method, adding a RecalcSize function is a bit more descriptive. Change-Id: I1b3c01ebd0e41183665baa63c926592865bbbd0b Reviewed-on: https://go-review.googlesource.com/c/go/+/345479 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/cmd/compile/internal/noder/func.go | 3 +-- src/cmd/compile/internal/types/size.go | 8 ++++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/noder/func.go b/src/cmd/compile/internal/noder/func.go index 702138157c..6077b348a5 100644 --- a/src/cmd/compile/internal/noder/func.go +++ b/src/cmd/compile/internal/noder/func.go @@ -37,8 +37,7 @@ func (g *irgen) funcBody(fn *ir.Func, recv *syntax.Field, sig *syntax.FuncType, // calculated its size, including parameter offsets. Now that we've // created the parameter Names, force a recalculation to ensure // their offsets are correct. - typ.Align = 0 - types.CalcSize(typ) + types.RecalcSize(typ) if block != nil { typecheck.DeclContext = ir.PAUTO diff --git a/src/cmd/compile/internal/types/size.go b/src/cmd/compile/internal/types/size.go index 34db0a0b0c..2546f0e2d1 100644 --- a/src/cmd/compile/internal/types/size.go +++ b/src/cmd/compile/internal/types/size.go @@ -562,6 +562,14 @@ func CalcStructSize(s *Type) { s.Width = calcStructOffset(s, s, 0, 1) // sets align } +// RecalcSize is like CalcSize, but recalculates t's size even if it +// has already been calculated before. It does not recalculate other +// types. +func RecalcSize(t *Type) { + t.Align = 0 + CalcSize(t) +} + // when a type's width should be known, we call CheckSize // to compute it. during a declaration like // -- GitLab From c92759978372ffc354f83e08b1dd6fa496e9b545 Mon Sep 17 00:00:00 2001 From: wangyuntao Date: Fri, 16 Jul 2021 10:29:05 +0000 Subject: [PATCH 0870/2500] cmd/compile: eliminate repetitive code Change-Id: I02c8b65f7c1c1606c9964ab6c54d5ab5f1b444a5 GitHub-Last-Rev: 3d740b9ac129d38981ee295456d2d7f803a79b77 GitHub-Pull-Request: golang/go#47242 Reviewed-on: https://go-review.googlesource.com/c/go/+/334990 Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky Trust: Cuong Manh Le --- src/cmd/compile/internal/ir/scc.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/ir/scc.go b/src/cmd/compile/internal/ir/scc.go index 2cfceaa1f6..a42951c1dd 100644 --- a/src/cmd/compile/internal/ir/scc.go +++ b/src/cmd/compile/internal/ir/scc.go @@ -116,12 +116,11 @@ func (v *bottomUpVisitor) visit(n *Func) uint32 { var i int for i = len(v.stack) - 1; i >= 0; i-- { x := v.stack[i] + v.nodeID[x] = ^uint32(0) if x == n { break } - v.nodeID[x] = ^uint32(0) } - v.nodeID[n] = ^uint32(0) block := v.stack[i:] // Run escape analysis on this set of functions. v.stack = v.stack[:i] -- GitLab From d7e2e2ec2b2a11c2bfb98a27c03d0dccba62c4fb Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 18 Aug 2021 06:28:40 -0700 Subject: [PATCH 0871/2500] cmd/compile: delay fillinMethods to deal with mutually-recursive types We need to delay fillinMethods until we get to a top-level type, so we know all the TFORW types have been filled in, and we can do the substitutions required by fillinMethods. Fixes #47710 Change-Id: I298de7e7753ed31a2c2b1ff04f35177a8afc7a66 Reviewed-on: https://go-review.googlesource.com/c/go/+/345149 Trust: Dan Scales Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/irgen.go | 8 + src/cmd/compile/internal/noder/types.go | 150 ++++++++++-------- .../compile/internal/reflectdata/reflect.go | 2 +- test/typeparam/issue47710.go | 19 +++ 4 files changed, 112 insertions(+), 67 deletions(-) create mode 100644 test/typeparam/issue47710.go diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index 29882eb773..d53c254001 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -149,6 +149,9 @@ type irgen struct { // statements yet. exprStmtOK bool + // types which we need to finish, by doing g.fillinMethods. + typesToFinalize []*typeDelayInfo + // Fully-instantiated generic types whose methods should be instantiated instTypeList []*types.Type @@ -184,6 +187,11 @@ type delayInfo struct { off int } +type typeDelayInfo struct { + typ *types2.Named + ntyp *types.Type +} + func (g *irgen) generate(noders []*noder) { types.LocalPkg.Name = g.self.Name() types.LocalPkg.Height = g.self.Height() diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index f5d91097f2..e00a3a5da9 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -35,6 +35,16 @@ func (g *irgen) typ(typ types2.Type) *types.Type { types.DeferCheckSize() res := g.typ1(typ) types.ResumeCheckSize() + + // Finish up any types on typesToFinalize, now that we are at the top of a + // fully-defined (possibly recursive) type. fillinMethods could create more + // types to finalize. + for len(g.typesToFinalize) > 0 { + l := len(g.typesToFinalize) + info := g.typesToFinalize[l-1] + g.typesToFinalize = g.typesToFinalize[:l-1] + g.fillinMethods(info.typ, info.ntyp) + } return res } @@ -151,10 +161,19 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { ntyp.SetRParams(rparams) //fmt.Printf("Saw new type %v %v\n", instName, ntyp.HasTParam()) - ntyp.SetUnderlying(g.typ1(typ.Underlying())) - g.fillinMethods(typ, ntyp) // Save the symbol for the base generic type. ntyp.OrigSym = g.pkg(typ.Obj().Pkg()).Lookup(typ.Obj().Name()) + ntyp.SetUnderlying(g.typ1(typ.Underlying())) + if typ.NumMethods() != 0 { + // Save a delayed call to g.fillinMethods() (once + // potentially recursive types have been fully + // resolved). + g.typesToFinalize = append(g.typesToFinalize, + &typeDelayInfo{ + typ: typ, + ntyp: ntyp, + }) + } return ntyp } obj := g.obj(typ.Obj()) @@ -266,76 +285,75 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { } } -// fillinMethods fills in the method name nodes and types for a defined type. This -// is needed for later typechecking when looking up methods of instantiated types, -// and for actually generating the methods for instantiated types. +// fillinMethods fills in the method name nodes and types for a defined type with at +// least one method. This is needed for later typechecking when looking up methods of +// instantiated types, and for actually generating the methods for instantiated +// types. func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) { - if typ.NumMethods() != 0 { - targs2 := typ.TArgs() - targs := make([]*types.Type, targs2.Len()) - for i := range targs { - targs[i] = g.typ1(targs2.At(i)) - } + targs2 := typ.TArgs() + targs := make([]*types.Type, targs2.Len()) + for i := range targs { + targs[i] = g.typ1(targs2.At(i)) + } - methods := make([]*types.Field, typ.NumMethods()) - for i := range methods { - m := typ.Method(i) - recvType := deref2(types2.AsSignature(m.Type()).Recv().Type()) - var meth *ir.Name - if m.Pkg() != g.self { - // Imported methods cannot be loaded by name (what - // g.obj() does) - they must be loaded via their - // type. - meth = g.obj(recvType.(*types2.Named).Obj()).Type().Methods().Index(i).Nname.(*ir.Name) + methods := make([]*types.Field, typ.NumMethods()) + for i := range methods { + m := typ.Method(i) + recvType := deref2(types2.AsSignature(m.Type()).Recv().Type()) + var meth *ir.Name + if m.Pkg() != g.self { + // Imported methods cannot be loaded by name (what + // g.obj() does) - they must be loaded via their + // type. + meth = g.obj(recvType.(*types2.Named).Obj()).Type().Methods().Index(i).Nname.(*ir.Name) + } else { + meth = g.obj(m) + } + if recvType != types2.Type(typ) { + // Unfortunately, meth is the type of the method of the + // generic type, so we have to do a substitution to get + // the name/type of the method of the instantiated type, + // using m.Type().RParams() and typ.TArgs() + inst2 := instTypeName2("", typ.TArgs()) + name := meth.Sym().Name + i1 := strings.Index(name, "[") + i2 := strings.Index(name[i1:], "]") + assert(i1 >= 0 && i2 >= 0) + // Generate the name of the instantiated method. + name = name[0:i1] + inst2 + name[i1+i2+1:] + newsym := meth.Sym().Pkg.Lookup(name) + var meth2 *ir.Name + if newsym.Def != nil { + meth2 = newsym.Def.(*ir.Name) } else { - meth = g.obj(m) - } - if recvType != types2.Type(typ) { - // Unfortunately, meth is the type of the method of the - // generic type, so we have to do a substitution to get - // the name/type of the method of the instantiated type, - // using m.Type().RParams() and typ.TArgs() - inst2 := instTypeName2("", typ.TArgs()) - name := meth.Sym().Name - i1 := strings.Index(name, "[") - i2 := strings.Index(name[i1:], "]") - assert(i1 >= 0 && i2 >= 0) - // Generate the name of the instantiated method. - name = name[0:i1] + inst2 + name[i1+i2+1:] - newsym := meth.Sym().Pkg.Lookup(name) - var meth2 *ir.Name - if newsym.Def != nil { - meth2 = newsym.Def.(*ir.Name) - } else { - meth2 = ir.NewNameAt(meth.Pos(), newsym) - rparams := types2.AsSignature(m.Type()).RParams() - tparams := make([]*types.Type, rparams.Len()) - for i := range tparams { - tparams[i] = g.typ1(rparams.At(i)) - } - assert(len(tparams) == len(targs)) - ts := typecheck.Tsubster{ - Tparams: tparams, - Targs: targs, - } - // Do the substitution of the type - meth2.SetType(ts.Typ(meth.Type())) - // Add any new fully instantiated types - // seen during the substitution to - // g.instTypeList. - g.instTypeList = append(g.instTypeList, ts.InstTypeList...) - newsym.Def = meth2 + meth2 = ir.NewNameAt(meth.Pos(), newsym) + rparams := types2.AsSignature(m.Type()).RParams() + tparams := make([]*types.Type, rparams.Len()) + for i := range tparams { + tparams[i] = g.typ1(rparams.At(i)) } - meth = meth2 + assert(len(tparams) == len(targs)) + ts := typecheck.Tsubster{ + Tparams: tparams, + Targs: targs, + } + // Do the substitution of the type + meth2.SetType(ts.Typ(meth.Type())) + // Add any new fully instantiated types + // seen during the substitution to + // g.instTypeList. + g.instTypeList = append(g.instTypeList, ts.InstTypeList...) + newsym.Def = meth2 } - methods[i] = types.NewField(meth.Pos(), g.selector(m), meth.Type()) - methods[i].Nname = meth - } - ntyp.Methods().Set(methods) - if !ntyp.HasTParam() && !ntyp.HasShape() { - // Generate all the methods for a new fully-instantiated type. - g.instTypeList = append(g.instTypeList, ntyp) + meth = meth2 } + methods[i] = types.NewField(meth.Pos(), g.selector(m), meth.Type()) + methods[i].Nname = meth + } + ntyp.Methods().Set(methods) + if !ntyp.HasTParam() && !ntyp.HasShape() { + // Generate all the methods for a new fully-instantiated type. + g.instTypeList = append(g.instTypeList, ntyp) } } diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index deb806beac..ca48db03f5 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -927,7 +927,7 @@ func formalType(t *types.Type) *types.Type { func writeType(t *types.Type) *obj.LSym { t = formalType(t) - if t.IsUntyped() { + if t.IsUntyped() || t.HasTParam() { base.Fatalf("writeType %v", t) } diff --git a/test/typeparam/issue47710.go b/test/typeparam/issue47710.go new file mode 100644 index 0000000000..0882cb4137 --- /dev/null +++ b/test/typeparam/issue47710.go @@ -0,0 +1,19 @@ +// compile -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type FooType[t any] interface { + Foo(BarType[t]) +} +type BarType[t any] interface { + Int(IntType[t]) FooType[int] +} + +type IntType[t any] int + +func (n IntType[t]) Foo(BarType[t]) {} +func (n IntType[_]) String() {} -- GitLab From d350a6653252fe1f698ac00be99964fa31d06e89 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 26 Aug 2021 16:57:06 -0700 Subject: [PATCH 0872/2500] cmd/compile: eagerly CalcStructSize for synthetic ABI types The next CL is going to replace Type.Width with Type.Size(), but Type.Size() isn't safe to call concurrently. So this CL calls CalcStructSize, which *is* allowed to be used concurrently, but then it's the caller's responsibility to ensure it's called right after NewStruct. Change-Id: If9cd81650ccb3a867b4449af757375fa56227901 Reviewed-on: https://go-review.googlesource.com/c/go/+/345483 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/abi/abiutils.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cmd/compile/internal/abi/abiutils.go b/src/cmd/compile/internal/abi/abiutils.go index d657ddc867..24f34b8263 100644 --- a/src/cmd/compile/internal/abi/abiutils.go +++ b/src/cmd/compile/internal/abi/abiutils.go @@ -722,14 +722,17 @@ func setup() { types.NewField(nxp, fname("len"), ui), types.NewField(nxp, fname("cap"), ui), }) + types.CalcStructSize(synthSlice) synthString = types.NewStruct(types.NoPkg, []*types.Field{ types.NewField(nxp, fname("data"), unsp), types.NewField(nxp, fname("len"), ui), }) + types.CalcStructSize(synthString) synthIface = types.NewStruct(types.NoPkg, []*types.Field{ types.NewField(nxp, fname("f1"), unsp), types.NewField(nxp, fname("f2"), unsp), }) + types.CalcStructSize(synthIface) }) } -- GitLab From 2c60a99f723e779a39664b5f12cb41878fd4a700 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 26 Aug 2021 14:52:32 -0700 Subject: [PATCH 0873/2500] cmd/compile/internal/syntax: make valid type parameter list in presence of errors Make sure the parser fills in names and types for type parameter lists, even in the case of errors. While at it, adjust some of the test functions to accept generic code and report all syntax errors. Added offending source as test for types2. Fixes #47996. Change-Id: I449bcf5e2cb80fa2a24cdd3945f484bfca218a06 Reviewed-on: https://go-review.googlesource.com/c/go/+/345476 Trust: Robert Griesemer Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/syntax/dumper_test.go | 6 +----- src/cmd/compile/internal/syntax/parser.go | 5 +---- src/cmd/compile/internal/syntax/printer_test.go | 6 +----- .../internal/types2/testdata/fixedbugs/issue47996.go2 | 8 ++++++++ 4 files changed, 11 insertions(+), 14 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue47996.go2 diff --git a/src/cmd/compile/internal/syntax/dumper_test.go b/src/cmd/compile/internal/syntax/dumper_test.go index 22680dce78..033283a352 100644 --- a/src/cmd/compile/internal/syntax/dumper_test.go +++ b/src/cmd/compile/internal/syntax/dumper_test.go @@ -13,11 +13,7 @@ func TestDump(t *testing.T) { t.Skip("skipping test in short mode") } - // provide a no-op error handler so parsing doesn't stop after first error - ast, err := ParseFile(*src_, func(error) {}, nil, CheckBranches) - if err != nil { - t.Error(err) - } + ast, _ := ParseFile(*src_, func(err error) { t.Error(err) }, nil, CheckBranches|AllowGenerics) if ast != nil { Fdump(testOut(), ast) diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index fd97279f9d..3d1ca9d6d4 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -1924,7 +1924,7 @@ func (p *parser) paramList(name *Name, close token, requireNames bool) (list []* } // distribute parameter types (len(list) > 0) - if named == 0 { + if named == 0 && !requireNames { // all unnamed => found names are named types for _, par := range list { if typ := par.Name; typ != nil { @@ -1932,9 +1932,6 @@ func (p *parser) paramList(name *Name, close token, requireNames bool) (list []* par.Name = nil } } - if requireNames { - p.syntaxErrorAt(list[0].Type.Pos(), "type parameters must be named") - } } else if named != len(list) { // some named => all must have names and types var pos Pos // left-most error position (or unknown) diff --git a/src/cmd/compile/internal/syntax/printer_test.go b/src/cmd/compile/internal/syntax/printer_test.go index ec4b1de573..638e6d4a9d 100644 --- a/src/cmd/compile/internal/syntax/printer_test.go +++ b/src/cmd/compile/internal/syntax/printer_test.go @@ -18,11 +18,7 @@ func TestPrint(t *testing.T) { t.Skip("skipping test in short mode") } - // provide a no-op error handler so parsing doesn't stop after first error - ast, err := ParseFile(*src_, func(error) {}, nil, 0) - if err != nil { - t.Error(err) - } + ast, _ := ParseFile(*src_, func(err error) { t.Error(err) }, nil, AllowGenerics) if ast != nil { Fprint(testOut(), ast, LineForm) diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47996.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47996.go2 new file mode 100644 index 0000000000..56e90942ab --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47996.go2 @@ -0,0 +1,8 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +// don't crash +func T /* ERROR missing */ [P /* ERROR named */ ] m /* ERROR m */ () /* ERROR \) */ { /* ERROR { */ } /* ERROR } */ -- GitLab From 67f7e16bcce0a3e68bf92e233ea16c8a9d2ac07a Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Thu, 26 Aug 2021 20:26:32 -0700 Subject: [PATCH 0874/2500] encoding/gob: optimize decoding of []byte MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The reflect.Value.Slice method unfortunately allocates every time since it needs to place the slice header on the heap. This is silly since gob immediately stores the result back into slice. Instead, use the reflect.Value.SetLen method. DecodeBytesSlice 75.0µs ± 2% 35.2µs ± 6% -53.02% Change-Id: I3ca0529d01bf978f2b76e215f52d369f458951ef Reviewed-on: https://go-review.googlesource.com/c/go/+/345572 Trust: Joe Tsai Run-TryBot: Joe Tsai TryBot-Result: Go Bot Reviewed-by: Rob Pike --- src/encoding/gob/decode.go | 2 +- src/encoding/gob/timing_test.go | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/encoding/gob/decode.go b/src/encoding/gob/decode.go index d2f6c749b1..4ef9ef7243 100644 --- a/src/encoding/gob/decode.go +++ b/src/encoding/gob/decode.go @@ -376,7 +376,7 @@ func decUint8Slice(i *decInstr, state *decoderState, value reflect.Value) { if value.Cap() < n { value.Set(reflect.MakeSlice(value.Type(), n, n)) } else { - value.Set(value.Slice(0, n)) + value.SetLen(n) } if _, err := state.b.Read(value.Bytes()); err != nil { errorf("error decoding []byte: %s", err) diff --git a/src/encoding/gob/timing_test.go b/src/encoding/gob/timing_test.go index 3478bd247e..ceb21c4107 100644 --- a/src/encoding/gob/timing_test.go +++ b/src/encoding/gob/timing_test.go @@ -280,6 +280,14 @@ func BenchmarkDecodeStringSlice(b *testing.B) { benchmarkDecodeSlice(b, a) } +func BenchmarkDecodeBytesSlice(b *testing.B) { + a := make([][]byte, 1000) + for i := range a { + a[i] = []byte("now is the time") + } + benchmarkDecodeSlice(b, a) +} + func BenchmarkDecodeInterfaceSlice(b *testing.B) { a := make([]interface{}, 1000) for i := range a { -- GitLab From 39eb1cc3f4a7d620d3faae139f83e88e652f5d25 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Thu, 25 Jun 2020 20:21:31 -0400 Subject: [PATCH 0875/2500] crypto/x509: drop compatibility hack for expired COMODO intermediates The hack was there for a couple intermediates with only SGC EKUs that issued severAuth certificates. They now all expired, so we can drop it. https://crt.sh/?id=10066 https://crt.sh/?id=213 Change-Id: I46820024892b2f9918ce125bafbbaf9e6c5c58b3 Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/781225 Reviewed-on: https://go-review.googlesource.com/c/go/+/327809 Trust: Filippo Valsorda Run-TryBot: Filippo Valsorda TryBot-Result: Go Bot Reviewed-by: Roland Shoemaker --- src/crypto/x509/name_constraints_test.go | 14 ++-- src/crypto/x509/root_windows.go | 5 -- src/crypto/x509/verify.go | 8 -- src/crypto/x509/verify_test.go | 100 ----------------------- 4 files changed, 9 insertions(+), 118 deletions(-) diff --git a/src/crypto/x509/name_constraints_test.go b/src/crypto/x509/name_constraints_test.go index c59a7dc1a6..a6b5aa1ee6 100644 --- a/src/crypto/x509/name_constraints_test.go +++ b/src/crypto/x509/name_constraints_test.go @@ -1279,8 +1279,8 @@ var nameConstraintsTests = []nameConstraintsTest{ expectedError: "incompatible key usage", }, - // #67: in order to support COMODO chains, SGC key usages permit - // serverAuth and clientAuth. + // #67: SGC key usages used to permit serverAuth and clientAuth, + // but don't anymore. { roots: []constraintsSpec{ {}, @@ -1296,10 +1296,11 @@ var nameConstraintsTests = []nameConstraintsTest{ sans: []string{"dns:example.com"}, ekus: []string{"serverAuth", "clientAuth"}, }, + expectedError: "incompatible key usage", }, - // #68: in order to support COMODO chains, SGC key usages permit - // serverAuth and clientAuth. + // #68: SGC key usages used to permit serverAuth and clientAuth, + // but don't anymore. { roots: make([]constraintsSpec, 1), intermediates: [][]constraintsSpec{ @@ -1313,6 +1314,7 @@ var nameConstraintsTests = []nameConstraintsTest{ sans: []string{"dns:example.com"}, ekus: []string{"serverAuth", "clientAuth"}, }, + expectedError: "incompatible key usage", }, // #69: an empty DNS constraint should allow anything. @@ -1437,7 +1439,8 @@ var nameConstraintsTests = []nameConstraintsTest{ expectedError: "incompatible key usage", }, - // #76: However, MSSGC in a leaf should match a request for serverAuth. + // #76: MSSGC in a leaf used to match a request for serverAuth, but doesn't + // anymore. { roots: make([]constraintsSpec, 1), intermediates: [][]constraintsSpec{ @@ -1450,6 +1453,7 @@ var nameConstraintsTests = []nameConstraintsTest{ ekus: []string{"msSGC"}, }, requestedEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, + expectedError: "incompatible key usage", }, // An invalid DNS SAN should be detected only at validation time so diff --git a/src/crypto/x509/root_windows.go b/src/crypto/x509/root_windows.go index 1e9be80b7d..f77ea3a698 100644 --- a/src/crypto/x509/root_windows.go +++ b/src/crypto/x509/root_windows.go @@ -218,11 +218,6 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate if oid, ok := windowsExtKeyUsageOIDs[eku]; ok { oids = append(oids, &oid[0]) } - // Like the standard verifier, accept SGC EKUs as equivalent to ServerAuth. - if eku == ExtKeyUsageServerAuth { - oids = append(oids, &syscall.OID_SERVER_GATED_CRYPTO[0]) - oids = append(oids, &syscall.OID_SGC_NETSCAPE[0]) - } } if oids != nil { para.RequestedUsage.Type = syscall.USAGE_MATCH_TYPE_OR diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go index 9ef11466a4..8aff53afa1 100644 --- a/src/crypto/x509/verify.go +++ b/src/crypto/x509/verify.go @@ -1085,14 +1085,6 @@ NextCert: for _, usage := range cert.ExtKeyUsage { if requestedUsage == usage { continue NextRequestedUsage - } else if requestedUsage == ExtKeyUsageServerAuth && - (usage == ExtKeyUsageNetscapeServerGatedCrypto || - usage == ExtKeyUsageMicrosoftServerGatedCrypto) { - // In order to support COMODO - // certificate chains, we have to - // accept Netscape or Microsoft SGC - // usages as equal to ServerAuth. - continue NextRequestedUsage } } diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go index 9954a670da..df78abd77e 100644 --- a/src/crypto/x509/verify_test.go +++ b/src/crypto/x509/verify_test.go @@ -203,19 +203,6 @@ var verifyTests = []verifyTest{ {"CORPORATIVO FICTICIO ACTIVO", "EAEko Herri Administrazioen CA - CA AAPP Vascas (2)", "IZENPE S.A."}, }, }, - { - name: "SGCIntermediate", - leaf: megaLeaf, - intermediates: []string{comodoIntermediate1}, - roots: []string{comodoRoot}, - currentTime: 1360431182, - - // CryptoAPI can find alternative validation paths. - systemLax: true, - expectedChains: [][]string{ - {"mega.co.nz", "EssentialSSL CA", "COMODO Certification Authority"}, - }, - }, { // Check that a name constrained intermediate works even when // it lists multiple constraints. @@ -932,93 +919,6 @@ naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== -----END CERTIFICATE-----` -var megaLeaf = `-----BEGIN CERTIFICATE----- -MIIFOjCCBCKgAwIBAgIQWYE8Dup170kZ+k11Lg51OjANBgkqhkiG9w0BAQUFADBy -MQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYD -VQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDEYMBYGA1UE -AxMPRXNzZW50aWFsU1NMIENBMB4XDTEyMTIxNDAwMDAwMFoXDTE0MTIxNDIzNTk1 -OVowfzEhMB8GA1UECxMYRG9tYWluIENvbnRyb2wgVmFsaWRhdGVkMS4wLAYDVQQL -EyVIb3N0ZWQgYnkgSW5zdHJhIENvcnBvcmF0aW9uIFB0eS4gTFREMRUwEwYDVQQL -EwxFc3NlbnRpYWxTU0wxEzARBgNVBAMTCm1lZ2EuY28ubnowggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQDcxMCClae8BQIaJHBUIVttlLvhbK4XhXPk3RQ3 -G5XA6tLZMBQ33l3F9knYJ0YErXtr8IdfYoulRQFmKFMJl9GtWyg4cGQi2Rcr5VN5 -S5dA1vu4oyJBxE9fPELcK6Yz1vqaf+n6za+mYTiQYKggVdS8/s8hmNuXP9Zk1pIn -+q0pGsf8NAcSHMJgLqPQrTDw+zae4V03DvcYfNKjuno88d2226ld7MAmQZ7uRNsI -/CnkdelVs+akZsXf0szefSqMJlf08SY32t2jj4Ra7RApVYxOftD9nij/aLfuqOU6 -ow6IgIcIG2ZvXLZwK87c5fxL7UAsTTV+M1sVv8jA33V2oKLhAgMBAAGjggG9MIIB -uTAfBgNVHSMEGDAWgBTay+qtWwhdzP/8JlTOSeVVxjj0+DAdBgNVHQ4EFgQUmP9l -6zhyrZ06Qj4zogt+6LKFk4AwDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAw -NAYDVR0lBC0wKwYIKwYBBQUHAwEGCCsGAQUFBwMCBgorBgEEAYI3CgMDBglghkgB -hvhCBAEwTwYDVR0gBEgwRjA6BgsrBgEEAbIxAQICBzArMCkGCCsGAQUFBwIBFh1o -dHRwczovL3NlY3VyZS5jb21vZG8uY29tL0NQUzAIBgZngQwBAgEwOwYDVR0fBDQw -MjAwoC6gLIYqaHR0cDovL2NybC5jb21vZG9jYS5jb20vRXNzZW50aWFsU1NMQ0Eu -Y3JsMG4GCCsGAQUFBwEBBGIwYDA4BggrBgEFBQcwAoYsaHR0cDovL2NydC5jb21v -ZG9jYS5jb20vRXNzZW50aWFsU1NMQ0FfMi5jcnQwJAYIKwYBBQUHMAGGGGh0dHA6 -Ly9vY3NwLmNvbW9kb2NhLmNvbTAlBgNVHREEHjAcggptZWdhLmNvLm56gg53d3cu -bWVnYS5jby5uejANBgkqhkiG9w0BAQUFAAOCAQEAcYhrsPSvDuwihMOh0ZmRpbOE -Gw6LqKgLNTmaYUPQhzi2cyIjhUhNvugXQQlP5f0lp5j8cixmArafg1dTn4kQGgD3 -ivtuhBTgKO1VYB/VRoAt6Lmswg3YqyiS7JiLDZxjoV7KoS5xdiaINfHDUaBBY4ZH -j2BUlPniNBjCqXe/HndUTVUewlxbVps9FyCmH+C4o9DWzdGBzDpCkcmo5nM+cp7q -ZhTIFTvZfo3zGuBoyu8BzuopCJcFRm3cRiXkpI7iOMUIixO1szkJS6WpL1sKdT73 -UXp08U0LBqoqG130FbzEJBBV3ixbvY6BWMHoCWuaoF12KJnC5kHt2RoWAAgMXA== ------END CERTIFICATE-----` - -var comodoIntermediate1 = `-----BEGIN CERTIFICATE----- -MIIFAzCCA+ugAwIBAgIQGLLLuqME8aAPwfLzJkYqSjANBgkqhkiG9w0BAQUFADCB -gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G -A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV -BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw -MDBaFw0xOTEyMzEyMzU5NTlaMHIxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVh -dGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9E -TyBDQSBMaW1pdGVkMRgwFgYDVQQDEw9Fc3NlbnRpYWxTU0wgQ0EwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCt8AiwcsargxIxF3CJhakgEtSYau2A1NHf -5I5ZLdOWIY120j8YC0YZYwvHIPPlC92AGvFaoL0dds23Izp0XmEbdaqb1IX04XiR -0y3hr/yYLgbSeT1awB8hLRyuIVPGOqchfr7tZ291HRqfalsGs2rjsQuqag7nbWzD -ypWMN84hHzWQfdvaGlyoiBSyD8gSIF/F03/o4Tjg27z5H6Gq1huQByH6RSRQXScq -oChBRVt9vKCiL6qbfltTxfEFFld+Edc7tNkBdtzffRDPUanlOPJ7FAB1WfnwWdsX -Pvev5gItpHnBXaIcw5rIp6gLSApqLn8tl2X2xQScRMiZln5+pN0vAgMBAAGjggGD -MIIBfzAfBgNVHSMEGDAWgBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAdBgNVHQ4EFgQU -2svqrVsIXcz//CZUzknlVcY49PgwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQI -MAYBAf8CAQAwIAYDVR0lBBkwFwYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMD4GA1Ud -IAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwczovL3NlY3VyZS5jb21v -ZG8uY29tL0NQUzBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9kb2Nh -LmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDBsBggrBgEFBQcB -AQRgMF4wNgYIKwYBBQUHMAKGKmh0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NvbW9k -b1VUTlNHQ0NBLmNydDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2Eu -Y29tMA0GCSqGSIb3DQEBBQUAA4IBAQAtlzR6QDLqcJcvgTtLeRJ3rvuq1xqo2l/z -odueTZbLN3qo6u6bldudu+Ennv1F7Q5Slqz0J790qpL0pcRDAB8OtXj5isWMcL2a -ejGjKdBZa0wztSz4iw+SY1dWrCRnilsvKcKxudokxeRiDn55w/65g+onO7wdQ7Vu -F6r7yJiIatnyfKH2cboZT7g440LX8NqxwCPf3dfxp+0Jj1agq8MLy6SSgIGSH6lv -+Wwz3D5XxqfyH8wqfOQsTEZf6/Nh9yvENZ+NWPU6g0QO2JOsTGvMd/QDzczc4BxL -XSXaPV7Od4rhPsbXlM1wSTz/Dr0ISKvlUhQVnQ6cGodWaK2cCQBk ------END CERTIFICATE-----` - -var comodoRoot = `-----BEGIN CERTIFICATE----- -MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB -gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G -A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV -BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw -MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl -YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P -RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 -UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI -2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 -Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp -+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ -DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O -nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW -/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g -PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u -QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY -SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv -IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ -RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 -zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd -BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB -ZQ== ------END CERTIFICATE-----` - var nameConstraintsLeaf = `-----BEGIN CERTIFICATE----- MIIHMTCCBRmgAwIBAgIIIZaV/3ezOJkwDQYJKoZIhvcNAQEFBQAwgcsxCzAJBgNV BAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVyZzEj -- GitLab From 4f0dedca7141afafbc01be96097570de2da2bdcc Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 24 Aug 2021 14:50:05 -0700 Subject: [PATCH 0876/2500] cmd/compile: fix parameterized interfaces type I[T any] interface{} This is an interface, but it has a type parameter. We need to distinguish that from an interface that is not parameterized. That means when doing type substitution on an interface with parameters, we need to make a new one. Same for non-empty interfaces. Even if the type parameter is not used in any method, we sill need to make a new type. Similar case to tstruct, above. Change-Id: I23ad9f21d2c4ef675bf3f7d84899d9e4919d05e7 Reviewed-on: https://go-review.googlesource.com/c/go/+/344578 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/typecheck/subr.go | 15 ++++- test/typeparam/eface.go | 71 ++++++++++++++++++++++ 2 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 test/typeparam/eface.go diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 8d05356543..73f83f65e4 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1163,8 +1163,8 @@ func (ts *Tsubster) typ1(t *types.Type) *types.Type { } case types.TINTER: - newt = ts.tinter(t) - if newt == t && !targsChanged { + newt = ts.tinter(t, targsChanged) + if newt == t { newt = nil } @@ -1324,11 +1324,20 @@ func (ts *Tsubster) tstruct(t *types.Type, force bool) *types.Type { } // tinter substitutes type params in types of the methods of an interface type. -func (ts *Tsubster) tinter(t *types.Type) *types.Type { +func (ts *Tsubster) tinter(t *types.Type, force bool) *types.Type { if t.Methods().Len() == 0 { + if t.HasTParam() { + // For an empty interface, we need to return a new type, + // since it may now be fully instantiated (HasTParam + // becomes false). + return types.NewInterface(t.Pkg(), nil) + } return t } var newfields []*types.Field + if force { + newfields = make([]*types.Field, t.Methods().Len()) + } for i, f := range t.Methods().Slice() { t2 := ts.typ1(f.Type) if (t2 != f.Type || f.Nname != nil) && newfields == nil { diff --git a/test/typeparam/eface.go b/test/typeparam/eface.go new file mode 100644 index 0000000000..e8147ef081 --- /dev/null +++ b/test/typeparam/eface.go @@ -0,0 +1,71 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Make sure we handle instantiated empty interfaces. + +package main + +type E[T any] interface { +} + +//go:noinline +func f[T any](x E[T]) interface{} { + return x +} + +//go:noinline +func g[T any](x interface{}) E[T] { + return x +} + +type I[T any] interface { + foo() +} + +type myint int + +func (x myint) foo() {} + +//go:noinline +func h[T any](x I[T]) interface{ foo() } { + return x +} + +//go:noinline +func i[T any](x interface{ foo() }) I[T] { + return x +} + +func main() { + if f[int](1) != 1 { + println("test 1 failed") + } + if f[int](2) != (interface{})(2) { + println("test 2 failed") + } + if g[int](3) != 3 { + println("test 3 failed") + } + if g[int](4) != (E[int])(4) { + println("test 4 failed") + } + if h[int](myint(5)) != myint(5) { + // TODO: disabled + //println("test 5 failed") + } + if h[int](myint(6)) != interface{ foo() }(myint(6)) { + // TODO: disabled + //println("test 6 failed") + } + if i[int](myint(7)) != myint(7) { + // TODO: This happens to work, but not for the right reasons. + println("test 7 failed") + } + if i[int](myint(8)) != I[int](myint(8)) { + // TODO: disabled + //println("test 8 failed") + } +} -- GitLab From 6a35e075126f4f78d50f236856fc5ba759616ee7 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 24 Aug 2021 15:41:11 -0700 Subject: [PATCH 0877/2500] cmd/compile: fix stenciling of conversions between interfaces Conversions need to allow nil through. We do that using a CONVIFACE instead of a DOTTYPE. Also reorganize how nonempty interfaces are handled. For nonempty to empty, a simple CONVIFACE suffices. For nonempty to nonempty, we need to call the runtime to get the new itab. Use the entry from the dictionary to identify the target interface type (if parameterized). Fixes #47925 Change-Id: I4ffeed964318bb3e270b06f558e6ab9c5bfc7188 Reviewed-on: https://go-review.googlesource.com/c/go/+/344830 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 64 +++++++++++++++++------ test/typeparam/eface.go | 10 ++-- test/typeparam/issue47925.go | 20 +++++++ test/typeparam/issue47925b.go | 33 ++++++++++++ test/typeparam/issue47925c.go | 36 +++++++++++++ test/typeparam/issue47925d.go | 47 +++++++++++++++++ 6 files changed, 187 insertions(+), 23 deletions(-) create mode 100644 test/typeparam/issue47925.go create mode 100644 test/typeparam/issue47925b.go create mode 100644 test/typeparam/issue47925c.go create mode 100644 test/typeparam/issue47925d.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 0c6bb5100c..7b85a88830 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -737,7 +737,7 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes []*typ return } c := n.(*ir.ConvExpr) - if c.X.Type().HasShape() { + if c.X.Type().HasShape() && !c.X.Type().IsInterface() { ir.Dump("BAD FUNCTION", newf) ir.Dump("BAD CONVERSION", c) base.Fatalf("converting shape type to interface") @@ -1135,7 +1135,7 @@ func (subst *subster) node(n ir.Node) ir.Node { x := x.(*ir.ConvExpr) // Note: x's argument is still typed as a type parameter. // m's argument now has an instantiated type. - if x.X.Type().HasTParam() { + if x.X.Type().HasTParam() || (x.X.Type().IsInterface() && x.Type().HasTParam()) { m = convertUsingDictionary(subst.info, subst.info.dictParam, m.Pos(), m.(*ir.ConvExpr).X, x, m.Type(), x.X.Type()) } case ir.ODOTTYPE, ir.ODOTTYPE2: @@ -1231,9 +1231,52 @@ func findDictType(info *instInfo, t *types.Type) int { // CONVIFACE node or XDOT node (for a bound method call) that is causing the // conversion. func convertUsingDictionary(info *instInfo, dictParam *ir.Name, pos src.XPos, v ir.Node, gn ir.Node, dst, src *types.Type) ir.Node { - assert(src.HasTParam()) + assert(src.HasTParam() || src.IsInterface() && gn.Type().HasTParam()) assert(dst.IsInterface()) + if v.Type().IsInterface() { + // Converting from an interface. The shape-ness of the source doesn't really matter, as + // we'll be using the concrete type from the first interface word. + if dst.IsEmptyInterface() { + // Converting I2E. OCONVIFACE does that for us, and doesn't depend + // on what the empty interface was instantiated with. No dictionary entry needed. + v = ir.NewConvExpr(pos, ir.OCONVIFACE, dst, v) + v.SetTypecheck(1) + return v + } + gdst := gn.Type() // pre-stenciled destination type + if !gdst.HasTParam() { + // Regular OCONVIFACE works if the destination isn't parameterized. + v = ir.NewConvExpr(pos, ir.OCONVIFACE, dst, v) + v.SetTypecheck(1) + return v + } + + // We get the destination interface type from the dictionary and the concrete + // type from the argument's itab. Call runtime.convI2I to get the new itab. + tmp := typecheck.Temp(v.Type()) + as := ir.NewAssignStmt(pos, tmp, v) + as.SetTypecheck(1) + itab := ir.NewUnaryExpr(pos, ir.OITAB, tmp) + typed(types.Types[types.TUINTPTR].PtrTo(), itab) + idata := ir.NewUnaryExpr(pos, ir.OIDATA, tmp) + typed(types.Types[types.TUNSAFEPTR], idata) + + fn := typecheck.LookupRuntime("convI2I") + fn.SetTypecheck(1) + types.CalcSize(fn.Type()) + call := ir.NewCallExpr(pos, ir.OCALLFUNC, fn, nil) + typed(types.Types[types.TUINT8].PtrTo(), call) + ix := findDictType(info, gdst) + assert(ix >= 0) + inter := getDictionaryType(info, dictParam, pos, ix) + call.Args = []ir.Node{inter, itab} + i := ir.NewBinaryExpr(pos, ir.OEFACE, call, idata) + typed(dst, i) + i.PtrInit().Append(as) + return i + } + var rt ir.Node if !dst.IsEmptyInterface() { // We should have an itab entry in the dictionary. Using this itab @@ -1248,11 +1291,6 @@ func convertUsingDictionary(info *instInfo, dictParam *ir.Name, pos src.XPos, v } assert(ix >= 0) rt = getDictionaryEntry(pos, dictParam, ix, info.dictLen) - } else if v.Type().IsInterface() { - ta := ir.NewTypeAssertExpr(pos, v, nil) - ta.SetType(dst) - ta.SetTypecheck(1) - return ta } else { ix := findDictType(info, src) assert(ix >= 0) @@ -1261,19 +1299,13 @@ func convertUsingDictionary(info *instInfo, dictParam *ir.Name, pos src.XPos, v } // Figure out what the data field of the interface will be. - var data ir.Node - if v.Type().IsInterface() { - data = ir.NewUnaryExpr(pos, ir.OIDATA, v) - } else { - data = ir.NewConvExpr(pos, ir.OCONVIDATA, nil, v) - } + data := ir.NewConvExpr(pos, ir.OCONVIDATA, nil, v) typed(types.Types[types.TUNSAFEPTR], data) // Build an interface from the type and data parts. var i ir.Node = ir.NewBinaryExpr(pos, ir.OEFACE, rt, data) typed(dst, i) return i - } func (subst *subster) namelist(l []*ir.Name) []*ir.Name { @@ -1557,7 +1589,7 @@ func (g *irgen) finalizeSyms() { default: base.Fatalf("itab entry with unknown op %s", n.Op()) } - if srctype.IsInterface() { + if srctype.IsInterface() || dsttype.IsEmptyInterface() { // No itab is wanted if src type is an interface. We // will use a type assert instead. d.off = objw.Uintptr(lsym, d.off, 0) diff --git a/test/typeparam/eface.go b/test/typeparam/eface.go index e8147ef081..1421b7f49a 100644 --- a/test/typeparam/eface.go +++ b/test/typeparam/eface.go @@ -53,19 +53,15 @@ func main() { println("test 4 failed") } if h[int](myint(5)) != myint(5) { - // TODO: disabled - //println("test 5 failed") + println("test 5 failed") } if h[int](myint(6)) != interface{ foo() }(myint(6)) { - // TODO: disabled - //println("test 6 failed") + println("test 6 failed") } if i[int](myint(7)) != myint(7) { - // TODO: This happens to work, but not for the right reasons. println("test 7 failed") } if i[int](myint(8)) != I[int](myint(8)) { - // TODO: disabled - //println("test 8 failed") + println("test 8 failed") } } diff --git a/test/typeparam/issue47925.go b/test/typeparam/issue47925.go new file mode 100644 index 0000000000..1b0719338d --- /dev/null +++ b/test/typeparam/issue47925.go @@ -0,0 +1,20 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type myifacer[T any] interface{ do(T) error } + +type stuff[T any] struct{} + +func (s stuff[T]) run() interface{} { + var i myifacer[T] + return i +} + +func main() { + stuff[int]{}.run() +} diff --git a/test/typeparam/issue47925b.go b/test/typeparam/issue47925b.go new file mode 100644 index 0000000000..f4a99ecdaa --- /dev/null +++ b/test/typeparam/issue47925b.go @@ -0,0 +1,33 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type I[T any] interface { + foo() +} + +type E[T any] interface { +} + +//go:noinline +func f[T I[T]](x T) E[T] { + // contains a cast from nonempty to empty interface + return E[T](I[T](x)) +} + +type S struct { + x int +} + +func (s *S) foo() {} + +func main() { + i := f(&S{x: 7}) + if i.(*S).x != 7 { + panic("bad") + } +} diff --git a/test/typeparam/issue47925c.go b/test/typeparam/issue47925c.go new file mode 100644 index 0000000000..0ba23e6245 --- /dev/null +++ b/test/typeparam/issue47925c.go @@ -0,0 +1,36 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type I[T any] interface { + foo() +} + +type J[T any] interface { + foo() + bar() +} + +//go:noinline +func f[T J[T]](x T) I[T] { + // contains a cast between two nonempty interfaces + return I[T](J[T](x)) +} + +type S struct { + x int +} + +func (s *S) foo() {} +func (s *S) bar() {} + +func main() { + i := f(&S{x: 7}) + if i.(*S).x != 7 { + panic("bad") + } +} diff --git a/test/typeparam/issue47925d.go b/test/typeparam/issue47925d.go new file mode 100644 index 0000000000..231961bd13 --- /dev/null +++ b/test/typeparam/issue47925d.go @@ -0,0 +1,47 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type I[T any] interface { + foo() +} + +type J[T any] interface { + foo() + bar() +} + +//go:noinline +func f[T J[T]](x T, g func(T) T) I[T] { + // contains a cast between two nonempty interfaces + // Also make sure we don't evaluate g(x) twice. + return I[T](J[T](g(x))) +} + +type S struct { + x int +} + +func (s *S) foo() {} +func (s *S) bar() {} + +var cnt int + +func inc(s *S) *S { + cnt++ + return s +} + +func main() { + i := f(&S{x: 7}, inc) + if i.(*S).x != 7 { + panic("bad") + } + if cnt != 1 { + panic("multiple calls") + } +} -- GitLab From 94f2a03951ed1534ebd6b13392b87d8b8b807e20 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Fri, 27 Aug 2021 12:42:38 -0400 Subject: [PATCH 0878/2500] cmd: update requirement on golang.org/x/mod Commands run: go get golang.org/x/mod@master go mod vendor go mod tidy This change pulls in the x/mod on master. Before it was pulled in on the dev.cmdgo branch of x/mod, but now that the workspace changes have been pulled into x/mod, we can change the requirement back on to the main branch. Change-Id: I296799a87ecc08ba17c0722e955f000426b105ef Reviewed-on: https://go-review.googlesource.com/c/go/+/345390 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 +- .../vendor/golang.org/x/mod/module/module.go | 7 +- src/cmd/vendor/golang.org/x/mod/zip/zip.go | 130 +++++++++++++++++- src/cmd/vendor/modules.txt | 2 +- 5 files changed, 132 insertions(+), 13 deletions(-) diff --git a/src/cmd/go.mod b/src/cmd/go.mod index b12d1991b9..362d33445b 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -7,7 +7,7 @@ require ( github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 // indirect golang.org/x/arch v0.0.0-20210502124803-cbf565b21d1e golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e // indirect - golang.org/x/mod v0.4.3-0.20210723200715-e41a6a4f3b61 + golang.org/x/mod v0.5.1-0.20210827163434-4029241eb1d5 golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 // indirect golang.org/x/term v0.0.0-20210503060354-a79de5458b56 golang.org/x/tools v0.1.6-0.20210809225032-337cebd2c151 diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 1db50ca302..6e8b02d8dc 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -9,8 +9,8 @@ golang.org/x/arch v0.0.0-20210502124803-cbf565b21d1e h1:pv3V0NlNSh5Q6AX/StwGLBjc golang.org/x/arch v0.0.0-20210502124803-cbf565b21d1e/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e h1:8foAy0aoO5GkqCvAEJ4VC4P3zksTg4X4aJCDpZzmgQI= golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/mod v0.4.3-0.20210723200715-e41a6a4f3b61 h1:gQY3CVezomIImcWCpxp6Mhj+fXCOZ+gD8/88326LVqw= -golang.org/x/mod v0.4.3-0.20210723200715-e41a6a4f3b61/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.5.1-0.20210827163434-4029241eb1d5 h1:BJ9Nc92Yf5inqB18HHrMgflMJKHraE07Z29Vjc+Z/Mk= +golang.org/x/mod v0.5.1-0.20210827163434-4029241eb1d5/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 h1:yhBbb4IRs2HS9PPlAg6DMC6mUOKexJBNsLf4Z+6En1Q= golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/src/cmd/vendor/golang.org/x/mod/module/module.go b/src/cmd/vendor/golang.org/x/mod/module/module.go index ba97ac356e..89bd3ede27 100644 --- a/src/cmd/vendor/golang.org/x/mod/module/module.go +++ b/src/cmd/vendor/golang.org/x/mod/module/module.go @@ -286,12 +286,7 @@ func fileNameOK(r rune) bool { if '0' <= r && r <= '9' || 'A' <= r && r <= 'Z' || 'a' <= r && r <= 'z' { return true } - for i := 0; i < len(allowed); i++ { - if rune(allowed[i]) == r { - return true - } - } - return false + return strings.ContainsRune(allowed, r) } // It may be OK to add more ASCII punctuation here, but only carefully. // For example Windows disallows < > \, and macOS disallows :, so we must not allow those. diff --git a/src/cmd/vendor/golang.org/x/mod/zip/zip.go b/src/cmd/vendor/golang.org/x/mod/zip/zip.go index 5b401ad4d8..40606d6da5 100644 --- a/src/cmd/vendor/golang.org/x/mod/zip/zip.go +++ b/src/cmd/vendor/golang.org/x/mod/zip/zip.go @@ -53,6 +53,7 @@ import ( "io" "io/ioutil" "os" + "os/exec" "path" "path/filepath" "strings" @@ -192,8 +193,10 @@ func CheckFiles(files []File) (CheckedFiles, error) { } // checkFiles implements CheckFiles and also returns lists of valid files and -// their sizes, corresponding to cf.Valid. These lists are used in Crewate to -// avoid repeated calls to File.Lstat. +// their sizes, corresponding to cf.Valid. It omits files in submodules, files +// in vendored packages, symlinked files, and various other unwanted files. +// +// The lists returned are used in Create to avoid repeated calls to File.Lstat. func checkFiles(files []File) (cf CheckedFiles, validFiles []File, validSizes []int64) { errPaths := make(map[string]struct{}) addError := func(path string, omitted bool, err error) { @@ -254,10 +257,12 @@ func checkFiles(files []File) (cf CheckedFiles, validFiles []File, validSizes [] continue } if isVendoredPackage(p) { + // Skip files in vendored packages. addError(p, true, errVendored) continue } if inSubmodule(p) { + // Skip submodule files. addError(p, true, errSubmoduleFile) continue } @@ -551,7 +556,7 @@ func CreateFromDir(w io.Writer, m module.Version, dir string) (err error) { if zerr, ok := err.(*zipError); ok { zerr.path = dir } else if err != nil { - err = &zipError{verb: "create zip", path: dir, err: err} + err = &zipError{verb: "create zip from directory", path: dir, err: err} } }() @@ -563,6 +568,116 @@ func CreateFromDir(w io.Writer, m module.Version, dir string) (err error) { return Create(w, m, files) } +// CreateFromVCS creates a module zip file for module m from the contents of a +// VCS repository stored locally. The zip content is written to w. +// +// repo must be an absolute path to the base of the repository, such as +// "/Users/some-user/my-repo". +// +// revision is the revision of the repository to create the zip from. Examples +// include HEAD or SHA sums for git repositories. +// +// subdir must be the relative path from the base of the repository, such as +// "sub/dir". To create a zip from the base of the repository, pass an empty +// string. +func CreateFromVCS(w io.Writer, m module.Version, repo, revision, subdir string) (err error) { + defer func() { + if zerr, ok := err.(*zipError); ok { + zerr.path = repo + } else if err != nil { + err = &zipError{verb: "create zip from version control system", path: repo, err: err} + } + }() + + var filesToCreate []File + + switch { + case isGitRepo(repo): + files, err := filesInGitRepo(repo, revision, subdir) + if err != nil { + return err + } + + filesToCreate = files + default: + return fmt.Errorf("%q does not use a recognised version control system", repo) + } + + return Create(w, m, filesToCreate) +} + +// filterGitIgnored filters out any files that are git ignored in the directory. +func filesInGitRepo(dir, rev, subdir string) ([]File, error) { + stderr := bytes.Buffer{} + stdout := bytes.Buffer{} + + // Incredibly, git produces different archives depending on whether + // it is running on a Windows system or not, in an attempt to normalize + // text file line endings. Setting -c core.autocrlf=input means only + // translate files on the way into the repo, not on the way out (archive). + // The -c core.eol=lf should be unnecessary but set it anyway. + // + // Note: We use git archive to understand which files are actually included, + // ignoring things like .gitignore'd files. We could also use other + // techniques like git ls-files, but this approach most closely matches what + // the Go command does, which is beneficial. + // + // Note: some of this code copied from https://go.googlesource.com/go/+/refs/tags/go1.16.5/src/cmd/go/internal/modfetch/codehost/git.go#826. + cmd := exec.Command("git", "-c", "core.autocrlf=input", "-c", "core.eol=lf", "archive", "--format=zip", rev) + if subdir != "" { + cmd.Args = append(cmd.Args, subdir) + } + cmd.Dir = dir + cmd.Stdout = &stdout + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + return nil, fmt.Errorf("error running `git archive`: %w, %s", err, stderr.String()) + } + + rawReader := bytes.NewReader(stdout.Bytes()) + zipReader, err := zip.NewReader(rawReader, int64(stdout.Len())) + if err != nil { + return nil, err + } + + var fs []File + for _, zf := range zipReader.File { + if !strings.HasPrefix(zf.Name, subdir) || strings.HasSuffix(zf.Name, "/") { + continue + } + + n := strings.TrimPrefix(zf.Name, subdir) + if n == "" { + continue + } + n = strings.TrimPrefix(n, string(filepath.Separator)) + + fs = append(fs, zipFile{ + name: n, + f: zf, + }) + } + + return fs, nil +} + +// isGitRepo reports whether the given directory is a git repo. +func isGitRepo(dir string) bool { + stdout := &bytes.Buffer{} + cmd := exec.Command("git", "rev-parse", "--git-dir") + cmd.Dir = dir + cmd.Stdout = stdout + if err := cmd.Run(); err != nil { + return false + } + gitDir := strings.TrimSpace(string(stdout.Bytes())) + if !filepath.IsAbs(gitDir) { + gitDir = filepath.Join(dir, gitDir) + } + wantDir := filepath.Join(dir, ".git") + return wantDir == gitDir +} + type dirFile struct { filePath, slashPath string info os.FileInfo @@ -572,6 +687,15 @@ func (f dirFile) Path() string { return f.slashPath } func (f dirFile) Lstat() (os.FileInfo, error) { return f.info, nil } func (f dirFile) Open() (io.ReadCloser, error) { return os.Open(f.filePath) } +type zipFile struct { + name string + f *zip.File +} + +func (f zipFile) Path() string { return f.name } +func (f zipFile) Lstat() (os.FileInfo, error) { return f.f.FileInfo(), nil } +func (f zipFile) Open() (io.ReadCloser, error) { return f.f.Open() } + // isVendoredPackage attempts to report whether the given filename is contained // in a package whose import path contains (but does not end with) the component // "vendor". diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index eed06a9f50..4d48b87a87 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -28,7 +28,7 @@ golang.org/x/arch/x86/x86asm ## explicit; go 1.17 golang.org/x/crypto/ed25519 golang.org/x/crypto/ed25519/internal/edwards25519 -# golang.org/x/mod v0.4.3-0.20210723200715-e41a6a4f3b61 +# golang.org/x/mod v0.5.1-0.20210827163434-4029241eb1d5 ## explicit; go 1.17 golang.org/x/mod/internal/lazyregexp golang.org/x/mod/modfile -- GitLab From 72c003ef82ba7c997f49e187e953872bfcbf5263 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 26 Aug 2021 12:11:14 -0700 Subject: [PATCH 0879/2500] cmd/compile: unexport Type.Width and Type.Align [generated] [git-generate] cd src/cmd/compile/internal : Workaround rf issue with types2 tests. rm types2/*_test.go : Rewrite uses. First a type-safe rewrite, : then a second pass to fix unnecessary conversions. rf ' ex ./abi ./escape ./gc ./liveness ./noder ./reflectdata ./ssa ./ssagen ./staticinit ./typebits ./typecheck ./walk { import "cmd/compile/internal/types" var t *types.Type t.Width -> t.Size() t.Align -> uint8(t.Alignment()) } ex ./abi ./escape ./gc ./liveness ./noder ./reflectdata ./ssa ./ssagen ./staticinit ./typebits ./typecheck ./walk { import "cmd/compile/internal/types" var t *types.Type int64(uint8(t.Alignment())) -> t.Alignment() } ' : Rename fields to lower case. ( cd types rf ' mv Type.Width Type.width mv Type.Align Type.align ' ) : Revert types2 changes. git checkout HEAD^ types2 Change-Id: I42091faece104c4ef619d9d4d50514fd48c8f029 Reviewed-on: https://go-review.googlesource.com/c/go/+/345480 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/abi/abiutils.go | 20 ++--- src/cmd/compile/internal/escape/utils.go | 6 +- src/cmd/compile/internal/gc/export.go | 2 +- src/cmd/compile/internal/gc/obj.go | 2 +- src/cmd/compile/internal/liveness/plive.go | 4 +- src/cmd/compile/internal/noder/transform.go | 4 +- src/cmd/compile/internal/reflectdata/alg.go | 12 +-- .../compile/internal/reflectdata/reflect.go | 74 +++++++++---------- src/cmd/compile/internal/ssa/debug.go | 4 +- src/cmd/compile/internal/ssa/expand_calls.go | 38 +++++----- src/cmd/compile/internal/ssa/op.go | 4 +- src/cmd/compile/internal/ssa/rewrite.go | 6 +- src/cmd/compile/internal/ssagen/pgen.go | 8 +- src/cmd/compile/internal/ssagen/ssa.go | 10 +-- src/cmd/compile/internal/staticinit/sched.go | 14 ++-- src/cmd/compile/internal/typebits/typebits.go | 8 +- src/cmd/compile/internal/typecheck/const.go | 4 +- src/cmd/compile/internal/typecheck/expr.go | 4 +- src/cmd/compile/internal/types/alg.go | 2 +- src/cmd/compile/internal/types/size.go | 66 ++++++++--------- src/cmd/compile/internal/types/type.go | 24 +++--- src/cmd/compile/internal/walk/assign.go | 8 +- src/cmd/compile/internal/walk/builtin.go | 6 +- src/cmd/compile/internal/walk/compare.go | 26 +++---- src/cmd/compile/internal/walk/complit.go | 4 +- src/cmd/compile/internal/walk/convert.go | 8 +- src/cmd/compile/internal/walk/expr.go | 4 +- src/cmd/compile/internal/walk/order.go | 2 +- src/cmd/compile/internal/walk/range.go | 6 +- src/cmd/compile/internal/walk/walk.go | 2 +- 30 files changed, 191 insertions(+), 191 deletions(-) diff --git a/src/cmd/compile/internal/abi/abiutils.go b/src/cmd/compile/internal/abi/abiutils.go index 24f34b8263..4da4e9ca3a 100644 --- a/src/cmd/compile/internal/abi/abiutils.go +++ b/src/cmd/compile/internal/abi/abiutils.go @@ -144,7 +144,7 @@ func (pa *ABIParamAssignment) RegisterTypesAndOffsets() ([]*types.Type, []int64) } func appendParamTypes(rts []*types.Type, t *types.Type) []*types.Type { - w := t.Width + w := t.Size() if w == 0 { return rts } @@ -193,12 +193,12 @@ func appendParamTypes(rts []*types.Type, t *types.Type) []*types.Type { // to input offsets, and returns the longer slice and the next unused offset. func appendParamOffsets(offsets []int64, at int64, t *types.Type) ([]int64, int64) { at = align(at, t) - w := t.Width + w := t.Size() if w == 0 { return offsets, at } if t.IsScalar() || t.IsPtrShaped() { - if t.IsComplex() || int(t.Width) > types.RegSize { // complex and *int64 on 32-bit + if t.IsComplex() || int(t.Size()) > types.RegSize { // complex and *int64 on 32-bit s := w / 2 return append(offsets, at, at+s), at + w } else { @@ -214,7 +214,7 @@ func appendParamOffsets(offsets []int64, at int64, t *types.Type) ([]int64, int6 case types.TSTRUCT: for i, f := range t.FieldSlice() { offsets, at = appendParamOffsets(offsets, at, f.Type) - if f.Type.Width == 0 && i == t.NumFields()-1 { + if f.Type.Size() == 0 && i == t.NumFields()-1 { at++ // last field has zero width } } @@ -531,7 +531,7 @@ type assignState struct { // align returns a rounded up to t's alignment func align(a int64, t *types.Type) int64 { - return alignTo(a, int(t.Align)) + return alignTo(a, int(uint8(t.Alignment()))) } // alignTo returns a rounded up to t, where t must be 0 or a power of 2. @@ -546,7 +546,7 @@ func alignTo(a int64, t int) int64 { // specified type. func (state *assignState) stackSlot(t *types.Type) int64 { rv := align(state.stackOffset, t) - state.stackOffset = rv + t.Width + state.stackOffset = rv + t.Size() return rv } @@ -554,7 +554,7 @@ func (state *assignState) stackSlot(t *types.Type) int64 { // that we've just determined to be register-assignable. The number of registers // needed is assumed to be stored in state.pUsed. func (state *assignState) allocateRegs(regs []RegIndex, t *types.Type) []RegIndex { - if t.Width == 0 { + if t.Size() == 0 { return regs } ri := state.rUsed.intRegs @@ -647,7 +647,7 @@ func (state *assignState) floatUsed() int { // can register allocate, FALSE otherwise (and updates state // accordingly). func (state *assignState) regassignIntegral(t *types.Type) bool { - regsNeeded := int(types.Rnd(t.Width, int64(types.PtrSize)) / int64(types.PtrSize)) + regsNeeded := int(types.Rnd(t.Size(), int64(types.PtrSize)) / int64(types.PtrSize)) if t.IsComplex() { regsNeeded = 2 } @@ -767,10 +767,10 @@ func (state *assignState) regassign(pt *types.Type) bool { // ABIParamResultInfo held in 'state'. func (state *assignState) assignParamOrReturn(pt *types.Type, n types.Object, isReturn bool) ABIParamAssignment { state.pUsed = RegAmounts{} - if pt.Width == types.BADWIDTH { + if pt.Size() == types.BADWIDTH { base.Fatalf("should never happen") panic("unreachable") - } else if pt.Width == 0 { + } else if pt.Size() == 0 { return state.stackAllocate(pt, n) } else if state.regassign(pt) { return state.regAllocate(pt, n, isReturn) diff --git a/src/cmd/compile/internal/escape/utils.go b/src/cmd/compile/internal/escape/utils.go index 5f462ef570..2c6e9bcbeb 100644 --- a/src/cmd/compile/internal/escape/utils.go +++ b/src/cmd/compile/internal/escape/utils.go @@ -182,11 +182,11 @@ func HeapAllocReason(n ir.Node) string { } } - if n.Type().Width > ir.MaxStackVarSize { + if n.Type().Size() > ir.MaxStackVarSize { return "too large for stack" } - if (n.Op() == ir.ONEW || n.Op() == ir.OPTRLIT) && n.Type().Elem().Width > ir.MaxImplicitStackVarSize { + if (n.Op() == ir.ONEW || n.Op() == ir.OPTRLIT) && n.Type().Elem().Size() > ir.MaxImplicitStackVarSize { return "too large for stack" } @@ -206,7 +206,7 @@ func HeapAllocReason(n ir.Node) string { if !ir.IsSmallIntConst(r) { return "non-constant size" } - if t := n.Type(); t.Elem().Width != 0 && ir.Int64Val(r) > ir.MaxImplicitStackVarSize/t.Elem().Width { + if t := n.Type(); t.Elem().Size() != 0 && ir.Int64Val(r) > ir.MaxImplicitStackVarSize/t.Elem().Size() { return "too large for stack" } } diff --git a/src/cmd/compile/internal/gc/export.go b/src/cmd/compile/internal/gc/export.go index 9bf3c7240a..2eac7d03c2 100644 --- a/src/cmd/compile/internal/gc/export.go +++ b/src/cmd/compile/internal/gc/export.go @@ -38,7 +38,7 @@ func dumpasmhdr() { if !t.IsStruct() || t.StructType().Map != nil || t.IsFuncArgStruct() { break } - fmt.Fprintf(b, "#define %s__size %d\n", n.Sym().Name, int(t.Width)) + fmt.Fprintf(b, "#define %s__size %d\n", n.Sym().Name, int(t.Size())) for _, f := range t.Fields().Slice() { if !f.Sym.IsBlank() { fmt.Fprintf(b, "#define %s_%s %d\n", n.Sym().Name, f.Sym.Name, int(f.Offset)) diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go index c86bf5f084..aae7d03ebe 100644 --- a/src/cmd/compile/internal/gc/obj.go +++ b/src/cmd/compile/internal/gc/obj.go @@ -274,7 +274,7 @@ func ggloblnod(nam *ir.Name) { if nam.Type() != nil && !nam.Type().HasPointers() { flags |= obj.NOPTR } - base.Ctxt.Globl(s, nam.Type().Width, flags) + base.Ctxt.Globl(s, nam.Type().Size(), flags) if nam.LibfuzzerExtraCounter() { s.Type = objabi.SLIBFUZZER_EXTRA_COUNTER } diff --git a/src/cmd/compile/internal/liveness/plive.go b/src/cmd/compile/internal/liveness/plive.go index 2705eac4f7..1e9d5748cc 100644 --- a/src/cmd/compile/internal/liveness/plive.go +++ b/src/cmd/compile/internal/liveness/plive.go @@ -274,7 +274,7 @@ func (lv *liveness) valueEffects(v *ssa.Value) (int32, liveEffect) { } } - if n.Class == ir.PPARAM && !n.Addrtaken() && n.Type().Width > int64(types.PtrSize) { + if n.Class == ir.PPARAM && !n.Addrtaken() && n.Type().Size() > int64(types.PtrSize) { // Only aggregate-typed arguments that are not address-taken can be // partially live. lv.partLiveArgs[n] = true @@ -1444,7 +1444,7 @@ func (lv *liveness) emitStackObjects() *obj.LSym { off = objw.Uint32(x, off, uint32(frameOffset)) t := v.Type() - sz := t.Width + sz := t.Size() if sz != int64(int32(sz)) { base.Fatalf("stack object too big: %v of type %v, size %d", v, t, sz) } diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index be8651d47b..a27f511769 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -195,7 +195,7 @@ func transformCompare(n *ir.BinaryExpr) { aop, _ := typecheck.Assignop(lt, rt) if aop != ir.OXXX { types.CalcSize(lt) - if lt.HasTParam() || rt.IsInterface() == lt.IsInterface() || lt.Width >= 1<<16 { + if lt.HasTParam() || rt.IsInterface() == lt.IsInterface() || lt.Size() >= 1<<16 { l = ir.NewConvExpr(base.Pos, aop, rt, l) l.SetTypecheck(1) } @@ -208,7 +208,7 @@ func transformCompare(n *ir.BinaryExpr) { aop, _ := typecheck.Assignop(rt, lt) if aop != ir.OXXX { types.CalcSize(rt) - if rt.HasTParam() || rt.IsInterface() == lt.IsInterface() || rt.Width >= 1<<16 { + if rt.HasTParam() || rt.IsInterface() == lt.IsInterface() || rt.Size() >= 1<<16 { r = ir.NewConvExpr(base.Pos, aop, lt, r) r.SetTypecheck(1) } diff --git a/src/cmd/compile/internal/reflectdata/alg.go b/src/cmd/compile/internal/reflectdata/alg.go index 36ad389647..d000618bd6 100644 --- a/src/cmd/compile/internal/reflectdata/alg.go +++ b/src/cmd/compile/internal/reflectdata/alg.go @@ -48,12 +48,12 @@ func eqCanPanic(t *types.Type) bool { func AlgType(t *types.Type) types.AlgKind { a, _ := types.AlgType(t) if a == types.AMEM { - if t.Alignment() < int64(base.Ctxt.Arch.Alignment) && t.Alignment() < t.Width { + if t.Alignment() < int64(base.Ctxt.Arch.Alignment) && t.Alignment() < t.Size() { // For example, we can't treat [2]int16 as an int32 if int32s require // 4-byte alignment. See issue 46283. return a } - switch t.Width { + switch t.Size() { case 0: return types.AMEM0 case 1: @@ -110,7 +110,7 @@ func genhash(t *types.Type) *obj.LSym { // For other sizes of plain memory, we build a closure // that calls memhash_varlen. The size of the memory is // encoded in the first slot of the closure. - closure := TypeLinksymLookup(fmt.Sprintf(".hashfunc%d", t.Width)) + closure := TypeLinksymLookup(fmt.Sprintf(".hashfunc%d", t.Size())) if len(closure.P) > 0 { // already generated return closure } @@ -119,7 +119,7 @@ func genhash(t *types.Type) *obj.LSym { } ot := 0 ot = objw.SymPtr(closure, ot, memhashvarlen, 0) - ot = objw.Uintptr(closure, ot, uint64(t.Width)) // size encoded in closure + ot = objw.Uintptr(closure, ot, uint64(t.Size())) // size encoded in closure objw.Global(closure, int32(ot), obj.DUPOK|obj.RODATA) return closure case types.ASPECIAL: @@ -354,7 +354,7 @@ func geneq(t *types.Type) *obj.LSym { case types.AMEM: // make equality closure. The size of the type // is encoded in the closure. - closure := TypeLinksymLookup(fmt.Sprintf(".eqfunc%d", t.Width)) + closure := TypeLinksymLookup(fmt.Sprintf(".eqfunc%d", t.Size())) if len(closure.P) != 0 { return closure } @@ -363,7 +363,7 @@ func geneq(t *types.Type) *obj.LSym { } ot := 0 ot = objw.SymPtr(closure, ot, memequalvarlen, 0) - ot = objw.Uintptr(closure, ot, uint64(t.Width)) + ot = objw.Uintptr(closure, ot, uint64(t.Size())) objw.Global(closure, int32(ot), obj.DUPOK|obj.RODATA) return closure case types.ASPECIAL: diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index ca48db03f5..183ede789e 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -97,10 +97,10 @@ func MapBucketType(t *types.Type) *types.Type { elemtype := t.Elem() types.CalcSize(keytype) types.CalcSize(elemtype) - if keytype.Width > MAXKEYSIZE { + if keytype.Size() > MAXKEYSIZE { keytype = types.NewPtr(keytype) } - if elemtype.Width > MAXELEMSIZE { + if elemtype.Size() > MAXELEMSIZE { elemtype = types.NewPtr(elemtype) } @@ -145,46 +145,46 @@ func MapBucketType(t *types.Type) *types.Type { if BUCKETSIZE < 8 { base.Fatalf("bucket size too small for proper alignment") } - if keytype.Align > BUCKETSIZE { + if uint8(keytype.Alignment()) > BUCKETSIZE { base.Fatalf("key align too big for %v", t) } - if elemtype.Align > BUCKETSIZE { + if uint8(elemtype.Alignment()) > BUCKETSIZE { base.Fatalf("elem align too big for %v", t) } - if keytype.Width > MAXKEYSIZE { + if keytype.Size() > MAXKEYSIZE { base.Fatalf("key size to large for %v", t) } - if elemtype.Width > MAXELEMSIZE { + if elemtype.Size() > MAXELEMSIZE { base.Fatalf("elem size to large for %v", t) } - if t.Key().Width > MAXKEYSIZE && !keytype.IsPtr() { + if t.Key().Size() > MAXKEYSIZE && !keytype.IsPtr() { base.Fatalf("key indirect incorrect for %v", t) } - if t.Elem().Width > MAXELEMSIZE && !elemtype.IsPtr() { + if t.Elem().Size() > MAXELEMSIZE && !elemtype.IsPtr() { base.Fatalf("elem indirect incorrect for %v", t) } - if keytype.Width%int64(keytype.Align) != 0 { + if keytype.Size()%keytype.Alignment() != 0 { base.Fatalf("key size not a multiple of key align for %v", t) } - if elemtype.Width%int64(elemtype.Align) != 0 { + if elemtype.Size()%elemtype.Alignment() != 0 { base.Fatalf("elem size not a multiple of elem align for %v", t) } - if bucket.Align%keytype.Align != 0 { + if uint8(bucket.Alignment())%uint8(keytype.Alignment()) != 0 { base.Fatalf("bucket align not multiple of key align %v", t) } - if bucket.Align%elemtype.Align != 0 { + if uint8(bucket.Alignment())%uint8(elemtype.Alignment()) != 0 { base.Fatalf("bucket align not multiple of elem align %v", t) } - if keys.Offset%int64(keytype.Align) != 0 { + if keys.Offset%keytype.Alignment() != 0 { base.Fatalf("bad alignment of keys in bmap for %v", t) } - if elems.Offset%int64(elemtype.Align) != 0 { + if elems.Offset%elemtype.Alignment() != 0 { base.Fatalf("bad alignment of elems in bmap for %v", t) } // Double-check that overflow field is final memory in struct, // with no padding at end. - if overflow.Offset != bucket.Width-int64(types.PtrSize) { + if overflow.Offset != bucket.Size()-int64(types.PtrSize) { base.Fatalf("bad offset of overflow in bmap for %v", t) } @@ -234,8 +234,8 @@ func MapType(t *types.Type) *types.Type { // The size of hmap should be 48 bytes on 64 bit // and 28 bytes on 32 bit platforms. - if size := int64(8 + 5*types.PtrSize); hmap.Width != size { - base.Fatalf("hmap size not correct: got %d, want %d", hmap.Width, size) + if size := int64(8 + 5*types.PtrSize); hmap.Size() != size { + base.Fatalf("hmap size not correct: got %d, want %d", hmap.Size(), size) } t.MapType().Hmap = hmap @@ -294,8 +294,8 @@ func MapIterType(t *types.Type) *types.Type { hiter := types.NewStruct(types.NoPkg, fields) hiter.SetNoalg(true) types.CalcSize(hiter) - if hiter.Width != int64(12*types.PtrSize) { - base.Fatalf("hash_iter size not correct %d %d", hiter.Width, 12*types.PtrSize) + if hiter.Size() != int64(12*types.PtrSize) { + base.Fatalf("hash_iter size not correct %d %d", hiter.Size(), 12*types.PtrSize) } t.MapType().Hiter = hiter hiter.StructType().Map = t @@ -708,7 +708,7 @@ func dcommontype(lsym *obj.LSym, t *types.Type) int { // ptrToThis typeOff // } ot := 0 - ot = objw.Uintptr(lsym, ot, uint64(t.Width)) + ot = objw.Uintptr(lsym, ot, uint64(t.Size())) ot = objw.Uintptr(lsym, ot, uint64(ptrdata)) ot = objw.Uint32(lsym, ot, types.TypeHash(t)) @@ -745,16 +745,16 @@ func dcommontype(lsym *obj.LSym, t *types.Type) int { ot = objw.Uint8(lsym, ot, tflag) // runtime (and common sense) expects alignment to be a power of two. - i := int(t.Align) + i := int(uint8(t.Alignment())) if i == 0 { i = 1 } if i&(i-1) != 0 { - base.Fatalf("invalid alignment %d for %v", t.Align, t) + base.Fatalf("invalid alignment %d for %v", uint8(t.Alignment()), t) } - ot = objw.Uint8(lsym, ot, t.Align) // align - ot = objw.Uint8(lsym, ot, t.Align) // fieldAlign + ot = objw.Uint8(lsym, ot, uint8(t.Alignment())) // align + ot = objw.Uint8(lsym, ot, uint8(t.Alignment())) // fieldAlign i = kinds[t.Kind()] if types.IsDirectIface(t) { @@ -1090,20 +1090,20 @@ func writeType(t *types.Type) *obj.LSym { var flags uint32 // Note: flags must match maptype accessors in ../../../../runtime/type.go // and maptype builder in ../../../../reflect/type.go:MapOf. - if t.Key().Width > MAXKEYSIZE { + if t.Key().Size() > MAXKEYSIZE { ot = objw.Uint8(lsym, ot, uint8(types.PtrSize)) flags |= 1 // indirect key } else { - ot = objw.Uint8(lsym, ot, uint8(t.Key().Width)) + ot = objw.Uint8(lsym, ot, uint8(t.Key().Size())) } - if t.Elem().Width > MAXELEMSIZE { + if t.Elem().Size() > MAXELEMSIZE { ot = objw.Uint8(lsym, ot, uint8(types.PtrSize)) flags |= 2 // indirect value } else { - ot = objw.Uint8(lsym, ot, uint8(t.Elem().Width)) + ot = objw.Uint8(lsym, ot, uint8(t.Elem().Size())) } - ot = objw.Uint16(lsym, ot, uint16(MapBucketType(t).Width)) + ot = objw.Uint16(lsym, ot, uint16(MapBucketType(t).Size())) if types.IsReflexive(t.Key()) { flags |= 4 // reflexive key } @@ -1557,7 +1557,7 @@ func fillptrmask(t *types.Type, ptrmask []byte) { // For non-trivial arrays, the program describes the full t.Width size. func dgcprog(t *types.Type, write bool) (*obj.LSym, int64) { types.CalcSize(t) - if t.Width == types.BADWIDTH { + if t.Size() == types.BADWIDTH { base.Fatalf("dgcprog: %v badwidth", t) } lsym := TypeLinksymPrefix(".gcprog", t) @@ -1566,8 +1566,8 @@ func dgcprog(t *types.Type, write bool) (*obj.LSym, int64) { p.emit(t, 0) offset := p.w.BitIndex() * int64(types.PtrSize) p.end() - if ptrdata := types.PtrDataSize(t); offset < ptrdata || offset > t.Width { - base.Fatalf("dgcprog: %v: offset=%d but ptrdata=%d size=%d", t, offset, ptrdata, t.Width) + if ptrdata := types.PtrDataSize(t); offset < ptrdata || offset > t.Size() { + base.Fatalf("dgcprog: %v: offset=%d but ptrdata=%d size=%d", t, offset, ptrdata, t.Size()) } return lsym, offset } @@ -1616,7 +1616,7 @@ func (p *gcProg) emit(t *types.Type, offset int64) { if !t.HasPointers() { return } - if t.Width == int64(types.PtrSize) { + if t.Size() == int64(types.PtrSize) { p.w.Ptr(offset / int64(types.PtrSize)) return } @@ -1648,16 +1648,16 @@ func (p *gcProg) emit(t *types.Type, offset int64) { elem = elem.Elem() } - if !p.w.ShouldRepeat(elem.Width/int64(types.PtrSize), count) { + if !p.w.ShouldRepeat(elem.Size()/int64(types.PtrSize), count) { // Cheaper to just emit the bits. for i := int64(0); i < count; i++ { - p.emit(elem, offset+i*elem.Width) + p.emit(elem, offset+i*elem.Size()) } return } p.emit(elem, offset) - p.w.ZeroUntil((offset + elem.Width) / int64(types.PtrSize)) - p.w.Repeat(elem.Width/int64(types.PtrSize), count-1) + p.w.ZeroUntil((offset + elem.Size()) / int64(types.PtrSize)) + p.w.Repeat(elem.Size()/int64(types.PtrSize), count-1) case types.TSTRUCT: for _, t1 := range t.Fields().Slice() { diff --git a/src/cmd/compile/internal/ssa/debug.go b/src/cmd/compile/internal/ssa/debug.go index 8e2872363b..e78eb5c0e4 100644 --- a/src/cmd/compile/internal/ssa/debug.go +++ b/src/cmd/compile/internal/ssa/debug.go @@ -378,7 +378,7 @@ func (sc *slotCanonicalizer) lookup(ls LocalSlot) (SlKeyIdx, bool) { split, _ = sc.lookup(*ls.SplitOf) } k := slotKey{ - name: ls.N, offset: ls.Off, width: ls.Type.Width, + name: ls.N, offset: ls.Off, width: ls.Type.Size(), splitOf: split, splitOffset: ls.SplitOffset, } if idx, ok := sc.slmap[k]; ok { @@ -1649,7 +1649,7 @@ func BuildFuncDebugNoOptimized(ctxt *obj.Link, f *Func, loggingEnabled bool, sta } if len(inp.Registers) > 1 { list = append(list, dwarf.DW_OP_piece) - ts := rtypes[k].Width + ts := rtypes[k].Size() list = dwarf.AppendUleb128(list, uint64(ts)) if padding[k] > 0 { if loggingEnabled { diff --git a/src/cmd/compile/internal/ssa/expand_calls.go b/src/cmd/compile/internal/ssa/expand_calls.go index a8c6c26dad..eba36ce33b 100644 --- a/src/cmd/compile/internal/ssa/expand_calls.go +++ b/src/cmd/compile/internal/ssa/expand_calls.go @@ -534,8 +534,8 @@ func (x *expandState) rewriteSelect(leaf *Value, selector *Value, offset int64, locs = x.splitSlots(ls, ".real", 0, selector.Type) case OpComplexImag: - ls := x.rewriteSelect(leaf, selector.Args[0], offset+selector.Type.Width, regOffset+RO_complex_imag) // result is FloatNN, width of result is offset of imaginary part. - locs = x.splitSlots(ls, ".imag", selector.Type.Width, selector.Type) + ls := x.rewriteSelect(leaf, selector.Args[0], offset+selector.Type.Size(), regOffset+RO_complex_imag) // result is FloatNN, width of result is offset of imaginary part. + locs = x.splitSlots(ls, ".imag", selector.Type.Size(), selector.Type) case OpStringLen, OpSliceLen: ls := x.rewriteSelect(leaf, selector.Args[0], offset+x.ptrSize, regOffset+RO_slice_len) @@ -616,7 +616,7 @@ outer: } return path case types.TINT64, types.TUINT64: - if container.Width == x.regSize { + if container.Size() == x.regSize { return path } if offset == x.hiOffset { @@ -682,7 +682,7 @@ func (x *expandState) decomposeArg(pos src.XPos, b *Block, source, mem *Value, t for i := 0; i < len(rts); i++ { rt := rts[i] off := offs[i] - fmt.Printf("rt=%s, off=%d, rt.Width=%d, rt.Align=%d\n", rt.String(), off, rt.Width, rt.Align) + fmt.Printf("rt=%s, off=%d, rt.Width=%d, rt.Align=%d\n", rt.String(), off, rt.Size(), uint8(rt.Alignment())) } panic(fmt.Errorf("offset %d of requested register %d should be zero, source=%s", offs[loadRegOffset], loadRegOffset, source.LongString())) } @@ -694,7 +694,7 @@ func (x *expandState) decomposeArg(pos src.XPos, b *Block, source, mem *Value, t for i := loadRegOffset; i < last; i++ { rt := rts[i] off := offs[i] - w := x.commonArgs[selKey{source, off, rt.Width, rt}] + w := x.commonArgs[selKey{source, off, rt.Size(), rt}] if w == nil { w = x.newArgToMemOrRegs(source, w, off, i, rt, pos) suffix := x.pathTo(source.Type, rt, off) @@ -705,7 +705,7 @@ func (x *expandState) decomposeArg(pos src.XPos, b *Block, source, mem *Value, t if t.IsPtrShaped() { // Preserve the original store type. This ensures pointer type // properties aren't discarded (e.g, notinheap). - if rt.Width != t.Width || len(pa.Registers) != 1 || i != loadRegOffset { + if rt.Size() != t.Size() || len(pa.Registers) != 1 || i != loadRegOffset { b.Func.Fatalf("incompatible store type %v and %v, i=%d", t, rt, i) } rt = t @@ -736,7 +736,7 @@ func (x *expandState) decomposeArg(pos src.XPos, b *Block, source, mem *Value, t } return mem case types.TINT64, types.TUINT64: - if t.Width == x.regSize { + if t.Size() == x.regSize { break } tHi, tLo := x.intPairTypes(t.Kind()) @@ -810,7 +810,7 @@ func (x *expandState) decomposeLoad(pos src.XPos, b *Block, source, mem *Value, } return mem case types.TINT64, types.TUINT64: - if t.Width == x.regSize { + if t.Size() == x.regSize { break } tHi, tLo := x.intPairTypes(t.Kind()) @@ -842,7 +842,7 @@ func storeOneArg(x *expandState, pos src.XPos, b *Block, locs []*LocalSlot, suff x.Printf("storeOneArg(%s; %s; %s; aO=%d; sO=%d; lrO=%d; %s)\n", source.LongString(), mem.String(), t.String(), argOffset, storeOffset, loadRegOffset, storeRc.String()) } - w := x.commonArgs[selKey{source, argOffset, t.Width, t}] + w := x.commonArgs[selKey{source, argOffset, t.Size(), t}] if w == nil { w = x.newArgToMemOrRegs(source, w, argOffset, loadRegOffset, t, pos) x.splitSlotsIntoNames(locs, suffix, argOffset, t, w) @@ -923,7 +923,7 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, source, mem *Value, case OpComplexMake: tPart := x.typs.Float32 - wPart := t.Width / 2 + wPart := t.Size() / 2 if wPart == 8 { tPart = x.typs.Float64 } @@ -952,7 +952,7 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, source, mem *Value, switch t.Kind() { case types.TARRAY: elt := t.Elem() - if source.Type != t && t.NumElem() == 1 && elt.Width == t.Width && t.Width == x.regSize { + if source.Type != t && t.NumElem() == 1 && elt.Size() == t.Size() && t.Size() == x.regSize { t = removeTrivialWrapperTypes(t) // it could be a leaf type, but the "leaf" could be complex64 (for example) return x.storeArgOrLoad(pos, b, source, mem, t, storeOffset, loadRegOffset, storeRc) @@ -960,14 +960,14 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, source, mem *Value, eltRO := x.regWidth(elt) for i := int64(0); i < t.NumElem(); i++ { sel := source.Block.NewValue1I(pos, OpArraySelect, elt, i, source) - mem = x.storeArgOrLoad(pos, b, sel, mem, elt, storeOffset+i*elt.Width, loadRegOffset, storeRc.at(t, 0)) + mem = x.storeArgOrLoad(pos, b, sel, mem, elt, storeOffset+i*elt.Size(), loadRegOffset, storeRc.at(t, 0)) loadRegOffset += eltRO pos = pos.WithNotStmt() } return mem case types.TSTRUCT: - if source.Type != t && t.NumFields() == 1 && t.Field(0).Type.Width == t.Width && t.Width == x.regSize { + if source.Type != t && t.NumFields() == 1 && t.Field(0).Type.Size() == t.Size() && t.Size() == x.regSize { // This peculiar test deals with accesses to immediate interface data. // It works okay because everything is the same size. // Example code that triggers this can be found in go/constant/value.go, function ToComplex @@ -1001,7 +1001,7 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, source, mem *Value, return mem case types.TINT64, types.TUINT64: - if t.Width == x.regSize { + if t.Size() == x.regSize { break } tHi, tLo := x.intPairTypes(t.Kind()) @@ -1422,7 +1422,7 @@ func expandCalls(f *Func) { if typ.IsMemory() { continue // handled elsewhere, not an indexable result } - size := typ.Width + size := typ.Size() offset := int64(0) switch v.Op { case OpStructSelect: @@ -1534,7 +1534,7 @@ func expandCalls(f *Func) { case OpArgIntReg: i := v.AuxInt if w := IArg[i]; w != nil { - if w.Type.Width != v.Type.Width { + if w.Type.Size() != v.Type.Size() { f.Fatalf("incompatible OpArgIntReg [%d]: %s and %s", i, v.LongString(), w.LongString()) } if w.Type.IsUnsafePtr() && !v.Type.IsUnsafePtr() { @@ -1549,7 +1549,7 @@ func expandCalls(f *Func) { case OpArgFloatReg: i := v.AuxInt if w := FArg[i]; w != nil { - if w.Type.Width != v.Type.Width { + if w.Type.Size() != v.Type.Size() { f.Fatalf("incompatible OpArgFloatReg [%d]: %v and %v", i, v, w) } v.copyOf(w) @@ -1634,7 +1634,7 @@ func (x *expandState) rewriteArgToMemOrRegs(v *Value) *Value { } case 1: t := v.Type - key := selKey{v, 0, t.Width, t} + key := selKey{v, 0, t.Size(), t} w := x.commonArgs[key] if w != nil { v.copyOf(w) @@ -1665,7 +1665,7 @@ func (x *expandState) newArgToMemOrRegs(baseArg, toReplace *Value, offset int64, defer x.indent(-3) x.Printf("newArgToMemOrRegs(base=%s; toReplace=%s; t=%s; memOff=%d; regOff=%d)\n", baseArg.String(), toReplace.LongString(), t.String(), offset, regOffset) } - key := selKey{baseArg, offset, t.Width, t} + key := selKey{baseArg, offset, t.Size(), t} w := x.commonArgs[key] if w != nil { if toReplace != nil { diff --git a/src/cmd/compile/internal/ssa/op.go b/src/cmd/compile/internal/ssa/op.go index f09a08abcf..6f7b9fa8e9 100644 --- a/src/cmd/compile/internal/ssa/op.go +++ b/src/cmd/compile/internal/ssa/op.go @@ -254,13 +254,13 @@ func (a *AuxCall) TypeOfArg(which int64) *types.Type { // SizeOfResult returns the size of result which (indexed 0, 1, etc). func (a *AuxCall) SizeOfResult(which int64) int64 { - return a.TypeOfResult(which).Width + return a.TypeOfResult(which).Size() } // SizeOfArg returns the size of argument which (indexed 0, 1, etc). // If the call is to a method, the receiver is the first argument (i.e., index 0) func (a *AuxCall) SizeOfArg(which int64) int64 { - return a.TypeOfArg(which).Width + return a.TypeOfArg(which).Size() } // NResults returns the number of results diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index 115d563933..5d468768b6 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -1253,7 +1253,7 @@ func zeroUpper32Bits(x *Value, depth int) bool { OpAMD64SHLL, OpAMD64SHLLconst: return true case OpArg: - return x.Type.Width == 4 + return x.Type.Size() == 4 case OpPhi, OpSelect0, OpSelect1: // Phis can use each-other as an arguments, instead of tracking visited values, // just limit recursion depth. @@ -1277,7 +1277,7 @@ func zeroUpper48Bits(x *Value, depth int) bool { case OpAMD64MOVWQZX, OpAMD64MOVWload, OpAMD64MOVWloadidx1, OpAMD64MOVWloadidx2: return true case OpArg: - return x.Type.Width == 2 + return x.Type.Size() == 2 case OpPhi, OpSelect0, OpSelect1: // Phis can use each-other as an arguments, instead of tracking visited values, // just limit recursion depth. @@ -1301,7 +1301,7 @@ func zeroUpper56Bits(x *Value, depth int) bool { case OpAMD64MOVBQZX, OpAMD64MOVBload, OpAMD64MOVBloadidx1: return true case OpArg: - return x.Type.Width == 1 + return x.Type.Size() == 1 case OpPhi, OpSelect0, OpSelect1: // Phis can use each-other as an arguments, instead of tracking visited values, // just limit recursion depth. diff --git a/src/cmd/compile/internal/ssagen/pgen.go b/src/cmd/compile/internal/ssagen/pgen.go index 0ddf11b426..86d40e239d 100644 --- a/src/cmd/compile/internal/ssagen/pgen.go +++ b/src/cmd/compile/internal/ssagen/pgen.go @@ -57,8 +57,8 @@ func cmpstackvarlt(a, b *ir.Name) bool { return ap } - if a.Type().Width != b.Type().Width { - return a.Type().Width > b.Type().Width + if a.Type().Size() != b.Type().Size() { + return a.Type().Size() > b.Type().Size() } return a.Sym().Name < b.Sym().Name @@ -147,7 +147,7 @@ func (s *ssafn) AllocFrame(f *ssa.Func) { } types.CalcSize(n.Type()) - w := n.Type().Width + w := n.Type().Size() if w >= types.MaxWidth || w < 0 { base.Fatalf("bad width") } @@ -159,7 +159,7 @@ func (s *ssafn) AllocFrame(f *ssa.Func) { w = 1 } s.stksize += w - s.stksize = types.Rnd(s.stksize, int64(n.Type().Align)) + s.stksize = types.Rnd(s.stksize, n.Type().Alignment()) if n.Type().HasPointers() { s.stkptrsize = s.stksize lastHasPtr = true diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 0a48f6b704..77a350720f 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -2483,8 +2483,8 @@ func (s *state) expr(n ir.Node) *ssa.Value { types.CalcSize(from) types.CalcSize(to) - if from.Width != to.Width { - s.Fatalf("CONVNOP width mismatch %v (%d) -> %v (%d)\n", from, from.Width, to, to.Width) + if from.Size() != to.Size() { + s.Fatalf("CONVNOP width mismatch %v (%d) -> %v (%d)\n", from, from.Size(), to, to.Size()) return nil } if etypesign(from.Kind()) != etypesign(to.Kind()) { @@ -5262,7 +5262,7 @@ func (s *state) canSSAName(name *ir.Name) bool { // TypeOK reports whether variables of type t are SSA-able. func TypeOK(t *types.Type) bool { types.CalcSize(t) - if t.Width > int64(4*types.PtrSize) { + if t.Size() > int64(4*types.PtrSize) { // 4*Widthptr is an arbitrary constant. We want it // to be at least 3*Widthptr so slices can be registerized. // Too big and we'll introduce too much register pressure. @@ -5752,7 +5752,7 @@ func (s *state) slice(v, i, j, k *ssa.Value, bounded bool) (p, l, c *ssa.Value) // // Where mask(x) is 0 if x==0 and -1 if x>0 and stride is the width // of the element type. - stride := s.constInt(types.Types[types.TINT], ptr.Type.Elem().Width) + stride := s.constInt(types.Types[types.TINT], ptr.Type.Elem().Size()) // The delta is the number of bytes to offset ptr by. delta := s.newValue2(mulOp, types.Types[types.TINT], i, stride) @@ -5960,7 +5960,7 @@ func (s *state) referenceTypeBuiltin(n *ir.UnaryExpr, x *ssa.Value) *ssa.Value { s.vars[n] = s.load(lenType, x) case ir.OCAP: // capacity is stored in the second word for chan - sw := s.newValue1I(ssa.OpOffPtr, lenType.PtrTo(), lenType.Width, x) + sw := s.newValue1I(ssa.OpOffPtr, lenType.PtrTo(), lenType.Size(), x) s.vars[n] = s.load(lenType, sw) default: s.Fatalf("op must be OLEN or OCAP") diff --git a/src/cmd/compile/internal/staticinit/sched.go b/src/cmd/compile/internal/staticinit/sched.go index 9329a46989..636199de47 100644 --- a/src/cmd/compile/internal/staticinit/sched.go +++ b/src/cmd/compile/internal/staticinit/sched.go @@ -133,7 +133,7 @@ func (s *Schedule) staticcopy(l *ir.Name, loff int64, rn *ir.Name, typ *types.Ty if ir.IsZero(r) { return true } - staticdata.InitConst(l, loff, r, int(typ.Width)) + staticdata.InitConst(l, loff, r, int(typ.Size())) return true case ir.OADDR: @@ -165,7 +165,7 @@ func (s *Schedule) staticcopy(l *ir.Name, loff int64, rn *ir.Name, typ *types.Ty e := &p.E[i] typ := e.Expr.Type() if e.Expr.Op() == ir.OLITERAL || e.Expr.Op() == ir.ONIL { - staticdata.InitConst(l, loff+e.Xoffset, e.Expr, int(typ.Width)) + staticdata.InitConst(l, loff+e.Xoffset, e.Expr, int(typ.Size())) continue } x := e.Expr @@ -229,7 +229,7 @@ func (s *Schedule) StaticAssign(l *ir.Name, loff int64, r ir.Node, typ *types.Ty if ir.IsZero(r) { return true } - staticdata.InitConst(l, loff, r, int(typ.Width)) + staticdata.InitConst(l, loff, r, int(typ.Size())) return true case ir.OADDR: @@ -286,7 +286,7 @@ func (s *Schedule) StaticAssign(l *ir.Name, loff int64, r ir.Node, typ *types.Ty for i := range p.E { e := &p.E[i] if e.Expr.Op() == ir.OLITERAL || e.Expr.Op() == ir.ONIL { - staticdata.InitConst(l, loff+e.Xoffset, e.Expr, int(e.Expr.Type().Width)) + staticdata.InitConst(l, loff+e.Xoffset, e.Expr, int(e.Expr.Type().Size())) continue } ir.SetPos(e.Expr) @@ -392,7 +392,7 @@ func (s *Schedule) initplan(n ir.Node) { } a = kv.Value } - s.addvalue(p, k*n.Type().Elem().Width, a) + s.addvalue(p, k*n.Type().Elem().Size(), a) k++ } @@ -499,10 +499,10 @@ func StaticLoc(n ir.Node) (name *ir.Name, offset int64, ok bool) { } // Check for overflow. - if n.Type().Width != 0 && types.MaxWidth/n.Type().Width <= int64(l) { + if n.Type().Size() != 0 && types.MaxWidth/n.Type().Size() <= int64(l) { break } - offset += int64(l) * n.Type().Width + offset += int64(l) * n.Type().Size() return name, offset, true } diff --git a/src/cmd/compile/internal/typebits/typebits.go b/src/cmd/compile/internal/typebits/typebits.go index 1c1b077423..fddad6e7e8 100644 --- a/src/cmd/compile/internal/typebits/typebits.go +++ b/src/cmd/compile/internal/typebits/typebits.go @@ -14,8 +14,8 @@ import ( // the first run and then simply copied into bv at the correct offset // on future calls with the same type t. func Set(t *types.Type, off int64, bv bitvec.BitVec) { - if t.Align > 0 && off&int64(t.Align-1) != 0 { - base.Fatalf("typebits.Set: invalid initial alignment: type %v has alignment %d, but offset is %v", t, t.Align, off) + if uint8(t.Alignment()) > 0 && off&int64(uint8(t.Alignment())-1) != 0 { + base.Fatalf("typebits.Set: invalid initial alignment: type %v has alignment %d, but offset is %v", t, uint8(t.Alignment()), off) } if !t.HasPointers() { // Note: this case ensures that pointers to go:notinheap types @@ -67,13 +67,13 @@ func Set(t *types.Type, off int64, bv bitvec.BitVec) { case types.TARRAY: elt := t.Elem() - if elt.Width == 0 { + if elt.Size() == 0 { // Short-circuit for #20739. break } for i := int64(0); i < t.NumElem(); i++ { Set(elt, off, bv) - off += elt.Width + off += elt.Size() } case types.TSTRUCT: diff --git a/src/cmd/compile/internal/typecheck/const.go b/src/cmd/compile/internal/typecheck/const.go index c27cf0e646..fbe7c02c49 100644 --- a/src/cmd/compile/internal/typecheck/const.go +++ b/src/cmd/compile/internal/typecheck/const.go @@ -874,9 +874,9 @@ func evalunsafe(n ir.Node) int64 { } types.CalcSize(tr) if n.Op() == ir.OALIGNOF { - return int64(tr.Align) + return tr.Alignment() } - return tr.Width + return tr.Size() case ir.OOFFSETOF: // must be a selector. diff --git a/src/cmd/compile/internal/typecheck/expr.go b/src/cmd/compile/internal/typecheck/expr.go index d83bc65bed..9b74bf7a9d 100644 --- a/src/cmd/compile/internal/typecheck/expr.go +++ b/src/cmd/compile/internal/typecheck/expr.go @@ -110,7 +110,7 @@ func tcArith(n ir.Node, op ir.Op, l, r ir.Node) (ir.Node, ir.Node, *types.Type) } types.CalcSize(l.Type()) - if r.Type().IsInterface() == l.Type().IsInterface() || l.Type().Width >= 1<<16 { + if r.Type().IsInterface() == l.Type().IsInterface() || l.Type().Size() >= 1<<16 { l = ir.NewConvExpr(base.Pos, aop, r.Type(), l) l.SetTypecheck(1) } @@ -129,7 +129,7 @@ func tcArith(n ir.Node, op ir.Op, l, r ir.Node) (ir.Node, ir.Node, *types.Type) } types.CalcSize(r.Type()) - if r.Type().IsInterface() == l.Type().IsInterface() || r.Type().Width >= 1<<16 { + if r.Type().IsInterface() == l.Type().IsInterface() || r.Type().Size() >= 1<<16 { r = ir.NewConvExpr(base.Pos, aop, l.Type(), r) r.SetTypecheck(1) } diff --git a/src/cmd/compile/internal/types/alg.go b/src/cmd/compile/internal/types/alg.go index 2c2700f345..f5675c66b4 100644 --- a/src/cmd/compile/internal/types/alg.go +++ b/src/cmd/compile/internal/types/alg.go @@ -165,7 +165,7 @@ func IsPaddedField(t *Type, i int) bool { if !t.IsStruct() { base.Fatalf("IsPaddedField called non-struct %v", t) } - end := t.Width + end := t.width if i+1 < t.NumFields() { end = t.Field(i + 1).Offset } diff --git a/src/cmd/compile/internal/types/size.go b/src/cmd/compile/internal/types/size.go index 2546f0e2d1..aeeca90746 100644 --- a/src/cmd/compile/internal/types/size.go +++ b/src/cmd/compile/internal/types/size.go @@ -189,19 +189,19 @@ func calcStructOffset(errtype *Type, t *Type, o int64, flag int) int64 { } CalcSize(f.Type) - if int32(f.Type.Align) > maxalign { - maxalign = int32(f.Type.Align) + if int32(f.Type.align) > maxalign { + maxalign = int32(f.Type.align) } - if f.Type.Align > 0 { - o = Rnd(o, int64(f.Type.Align)) + if f.Type.align > 0 { + o = Rnd(o, int64(f.Type.align)) } if isStruct { // For receiver/args/results, do not set, it depends on ABI f.Offset = o } - w := f.Type.Width + w := f.Type.width if w < 0 { - base.Fatalf("invalid width %d", f.Type.Width) + base.Fatalf("invalid width %d", f.Type.width) } if w == 0 { lastzero = o @@ -231,10 +231,10 @@ func calcStructOffset(errtype *Type, t *Type, o int64, flag int) int64 { if flag != 0 { o = Rnd(o, int64(maxalign)) } - t.Align = uint8(maxalign) + t.align = uint8(maxalign) // type width only includes back to first field's offset - t.Width = o - starto + t.width = o - starto return o } @@ -350,10 +350,10 @@ func CalcSize(t *Type) { return } - if t.Width == -2 { + if t.width == -2 { reportTypeLoop(t) - t.Width = 0 - t.Align = 1 + t.width = 0 + t.align = 1 return } @@ -372,7 +372,7 @@ func CalcSize(t *Type) { // break infinite recursion if the broken recursive type // is referenced again - if t.Broke() && t.Width == 0 { + if t.Broke() && t.width == 0 { return } @@ -384,8 +384,8 @@ func CalcSize(t *Type) { base.Pos = pos } - t.Width = -2 - t.Align = 0 // 0 means use t.Width, below + t.width = -2 + t.align = 0 // 0 means use t.Width, below et := t.Kind() switch et { @@ -417,15 +417,15 @@ func CalcSize(t *Type) { case TINT64, TUINT64, TFLOAT64: w = 8 - t.Align = uint8(RegSize) + t.align = uint8(RegSize) case TCOMPLEX64: w = 8 - t.Align = 4 + t.align = 4 case TCOMPLEX128: w = 16 - t.Align = uint8(RegSize) + t.align = uint8(RegSize) case TPTR: w = int64(PtrSize) @@ -436,14 +436,14 @@ func CalcSize(t *Type) { case TINTER: // implemented as 2 pointers w = 2 * int64(PtrSize) - t.Align = uint8(PtrSize) + t.align = uint8(PtrSize) expandiface(t) case TUNION: // Always part of an interface for now, so size/align don't matter. // Pretend a union is represented like an interface. w = 2 * int64(PtrSize) - t.Align = uint8(PtrSize) + t.align = uint8(PtrSize) case TCHAN: // implemented as pointer w = int64(PtrSize) @@ -458,7 +458,7 @@ func CalcSize(t *Type) { case TCHANARGS: t1 := t.ChanArgs() CalcSize(t1) // just in case - if t1.Elem().Width >= 1<<16 { + if t1.Elem().width >= 1<<16 { base.ErrorfAt(typePos(t1), "channel element type too large (>64kB)") } w = 1 // anything will do @@ -481,7 +481,7 @@ func CalcSize(t *Type) { base.Fatalf("early CalcSize string") } w = StringSize - t.Align = uint8(PtrSize) + t.align = uint8(PtrSize) case TARRAY: if t.Elem() == nil { @@ -489,14 +489,14 @@ func CalcSize(t *Type) { } CalcSize(t.Elem()) - if t.Elem().Width != 0 { - cap := (uint64(MaxWidth) - 1) / uint64(t.Elem().Width) + if t.Elem().width != 0 { + cap := (uint64(MaxWidth) - 1) / uint64(t.Elem().width) if uint64(t.NumElem()) > cap { base.ErrorfAt(typePos(t), "type %L larger than address space", t) } } - w = t.NumElem() * t.Elem().Width - t.Align = t.Elem().Align + w = t.NumElem() * t.Elem().width + t.align = t.Elem().align case TSLICE: if t.Elem() == nil { @@ -504,7 +504,7 @@ func CalcSize(t *Type) { } w = SliceSize CheckSize(t.Elem()) - t.Align = uint8(PtrSize) + t.align = uint8(PtrSize) case TSTRUCT: if t.IsFuncArgStruct() { @@ -530,7 +530,7 @@ func CalcSize(t *Type) { if w%int64(RegSize) != 0 { base.Warn("bad type %v %d\n", t1, w) } - t.Align = 1 + t.align = 1 case TTYPEPARAM: // TODO(danscales) - remove when we eliminate the need @@ -542,12 +542,12 @@ func CalcSize(t *Type) { base.ErrorfAt(typePos(t), "type %v too large", t) } - t.Width = w - if t.Align == 0 { + t.width = w + if t.align == 0 { if w == 0 || w > 8 || w&(w-1) != 0 { base.Fatalf("invalid alignment for %v", t) } - t.Align = uint8(w) + t.align = uint8(w) } base.Pos = lno @@ -559,14 +559,14 @@ func CalcSize(t *Type) { // filling in s.Width and s.Align, // even if size calculation is otherwise disabled. func CalcStructSize(s *Type) { - s.Width = calcStructOffset(s, s, 0, 1) // sets align + s.width = calcStructOffset(s, s, 0, 1) // sets align } // RecalcSize is like CalcSize, but recalculates t's size even if it // has already been calculated before. It does not recalculate other // types. func RecalcSize(t *Type) { - t.Align = 0 + t.align = 0 CalcSize(t) } @@ -659,7 +659,7 @@ func PtrDataSize(t *Type) int64 { case TARRAY: // haspointers already eliminated t.NumElem() == 0. - return (t.NumElem()-1)*t.Elem().Width + PtrDataSize(t.Elem()) + return (t.NumElem()-1)*t.Elem().width + PtrDataSize(t.Elem()) case TSTRUCT: // Find the last field that has pointers. diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index e84e89fd15..7861effcb2 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -158,8 +158,8 @@ type Type struct { // TTYPEPARAM: *Typeparam extra interface{} - // Width is the width of this Type in bytes. - Width int64 // valid if Align > 0 + // width is the width of this Type in bytes. + width int64 // valid if Align > 0 // list of base methods (excluding embedding) methods Fields @@ -181,7 +181,7 @@ type Type struct { vargen int32 // unique name for OTYPE/ONAME kind Kind // kind of type - Align uint8 // the required alignment of this type, in bytes (0 means Width and Align have not yet been computed) + align uint8 // the required alignment of this type, in bytes (0 means Width and Align have not yet been computed) flags bitset8 @@ -521,7 +521,7 @@ func (f *Field) SetNointerface(b bool) { f.flags.set(fieldNointerface, b) } // End returns the offset of the first byte immediately after this field. func (f *Field) End() int64 { - return f.Offset + f.Type.Width + return f.Offset + f.Type.width } // IsMethod reports whether f represents a method rather than a struct field. @@ -584,7 +584,7 @@ func (f *Fields) Append(s ...*Field) { func New(et Kind) *Type { t := &Type{ kind: et, - Width: BADWIDTH, + width: BADWIDTH, } t.underlying = t // TODO(josharian): lazily initialize some of these? @@ -748,8 +748,8 @@ func NewPtr(elem *Type) *Type { t := New(TPTR) t.extra = Ptr{Elem: elem} - t.Width = int64(PtrSize) - t.Align = uint8(PtrSize) + t.width = int64(PtrSize) + t.align = uint8(PtrSize) if NewPtrCacheEnabled { elem.cache.ptr = t } @@ -1084,7 +1084,7 @@ func (t *Type) SetInterface(methods []*Field) { } func (t *Type) WidthCalculated() bool { - return t.Align > 0 + return t.align > 0 } // ArgWidth returns the total aligned argument size for a function. @@ -1102,12 +1102,12 @@ func (t *Type) Size() int64 { return 0 } CalcSize(t) - return t.Width + return t.width } func (t *Type) Alignment() int64 { CalcSize(t) - return int64(t.Align) + return int64(t.align) } func (t *Type) SimpleString() string { @@ -1805,8 +1805,8 @@ func (t *Type) SetUnderlying(underlying *Type) { // TODO(mdempsky): Fix Type rekinding. t.kind = underlying.kind t.extra = underlying.extra - t.Width = underlying.Width - t.Align = underlying.Align + t.width = underlying.width + t.align = underlying.align t.underlying = underlying.underlying if underlying.NotInHeap() { diff --git a/src/cmd/compile/internal/walk/assign.go b/src/cmd/compile/internal/walk/assign.go index d4c1aafdc1..9350c389c1 100644 --- a/src/cmd/compile/internal/walk/assign.go +++ b/src/cmd/compile/internal/walk/assign.go @@ -167,7 +167,7 @@ func walkAssignMapRead(init *ir.Nodes, n *ir.AssignListStmt) ir.Node { a := n.Lhs[0] var call *ir.CallExpr - if w := t.Elem().Width; w <= zeroValSize { + if w := t.Elem().Size(); w <= zeroValSize { fn := mapfn(mapaccess2[fast], t, false) call = mkcall1(fn, fn.Type().Results(), init, reflectdata.TypePtr(t), r.X, key) } else { @@ -533,7 +533,7 @@ func appendSlice(n *ir.CallExpr, init *ir.Nodes) ir.Node { fn := typecheck.LookupRuntime("slicecopy") fn = typecheck.SubstArgTypes(fn, ptr1.Type().Elem(), ptr2.Type().Elem()) - ncopy = mkcall1(fn, types.Types[types.TINT], &nodes, ptr1, len1, ptr2, len2, ir.NewInt(elemtype.Width)) + ncopy = mkcall1(fn, types.Types[types.TINT], &nodes, ptr1, len1, ptr2, len2, ir.NewInt(elemtype.Size())) } else { // memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T)) ix := ir.NewIndexExpr(base.Pos, s, ir.NewUnaryExpr(base.Pos, ir.OLEN, l1)) @@ -543,7 +543,7 @@ func appendSlice(n *ir.CallExpr, init *ir.Nodes) ir.Node { sptr := ir.NewUnaryExpr(base.Pos, ir.OSPTR, l2) nwid := cheapExpr(typecheck.Conv(ir.NewUnaryExpr(base.Pos, ir.OLEN, l2), types.Types[types.TUINTPTR]), &nodes) - nwid = ir.NewBinaryExpr(base.Pos, ir.OMUL, nwid, ir.NewInt(elemtype.Width)) + nwid = ir.NewBinaryExpr(base.Pos, ir.OMUL, nwid, ir.NewInt(elemtype.Size())) // instantiate func memmove(to *any, frm *any, length uintptr) fn := typecheck.LookupRuntime("memmove") @@ -690,7 +690,7 @@ func extendSlice(n *ir.CallExpr, init *ir.Nodes) ir.Node { hp := typecheck.ConvNop(typecheck.NodAddr(ix), types.Types[types.TUNSAFEPTR]) // hn := l2 * sizeof(elem(s)) - hn := typecheck.Conv(ir.NewBinaryExpr(base.Pos, ir.OMUL, l2, ir.NewInt(elemtype.Width)), types.Types[types.TUINTPTR]) + hn := typecheck.Conv(ir.NewBinaryExpr(base.Pos, ir.OMUL, l2, ir.NewInt(elemtype.Size())), types.Types[types.TUINTPTR]) clrname := "memclrNoHeapPointers" hasPointers := elemtype.HasPointers() diff --git a/src/cmd/compile/internal/walk/builtin.go b/src/cmd/compile/internal/walk/builtin.go index af4f8f4822..3c9ef636f8 100644 --- a/src/cmd/compile/internal/walk/builtin.go +++ b/src/cmd/compile/internal/walk/builtin.go @@ -158,7 +158,7 @@ func walkCopy(n *ir.BinaryExpr, init *ir.Nodes, runtimecall bool) ir.Node { fn := typecheck.LookupRuntime("slicecopy") fn = typecheck.SubstArgTypes(fn, ptrL.Type().Elem(), ptrR.Type().Elem()) - return mkcall1(fn, n.Type(), init, ptrL, lenL, ptrR, lenR, ir.NewInt(n.X.Type().Elem().Width)) + return mkcall1(fn, n.Type(), init, ptrL, lenL, ptrR, lenR, ir.NewInt(n.X.Type().Elem().Size())) } n.X = walkExpr(n.X, init) @@ -194,7 +194,7 @@ func walkCopy(n *ir.BinaryExpr, init *ir.Nodes, runtimecall bool) ir.Node { nwid := ir.Node(typecheck.Temp(types.Types[types.TUINTPTR])) setwid := ir.NewAssignStmt(base.Pos, nwid, typecheck.Conv(nlen, types.Types[types.TUINTPTR])) ne.Body.Append(setwid) - nwid = ir.NewBinaryExpr(base.Pos, ir.OMUL, nwid, ir.NewInt(nl.Type().Elem().Width)) + nwid = ir.NewBinaryExpr(base.Pos, ir.OMUL, nwid, ir.NewInt(nl.Type().Elem().Size())) call := mkcall1(fn, nil, init, nto, nfrm, nwid) ne.Body.Append(call) @@ -452,7 +452,7 @@ func walkMakeSliceCopy(n *ir.MakeExpr, init *ir.Nodes) ir.Node { // We do not check for overflow of len(to)*elem.Width here // since len(from) is an existing checked slice capacity // with same elem.Width for the from slice. - size := ir.NewBinaryExpr(base.Pos, ir.OMUL, typecheck.Conv(length, types.Types[types.TUINTPTR]), typecheck.Conv(ir.NewInt(t.Elem().Width), types.Types[types.TUINTPTR])) + size := ir.NewBinaryExpr(base.Pos, ir.OMUL, typecheck.Conv(length, types.Types[types.TUINTPTR]), typecheck.Conv(ir.NewInt(t.Elem().Size()), types.Types[types.TUINTPTR])) // instantiate mallocgc(size uintptr, typ *byte, needszero bool) unsafe.Pointer fn := typecheck.LookupRuntime("mallocgc") diff --git a/src/cmd/compile/internal/walk/compare.go b/src/cmd/compile/internal/walk/compare.go index b18615f61a..daebc47965 100644 --- a/src/cmd/compile/internal/walk/compare.go +++ b/src/cmd/compile/internal/walk/compare.go @@ -138,7 +138,7 @@ func walkCompare(n *ir.BinaryExpr, init *ir.Nodes) ir.Node { return n case types.TARRAY: // We can compare several elements at once with 2/4/8 byte integer compares - inline = t.NumElem() <= 1 || (types.IsSimple[t.Elem().Kind()] && (t.NumElem() <= 4 || t.Elem().Width*t.NumElem() <= maxcmpsize)) + inline = t.NumElem() <= 1 || (types.IsSimple[t.Elem().Kind()] && (t.NumElem() <= 4 || t.Elem().Size()*t.NumElem() <= maxcmpsize)) case types.TSTRUCT: inline = t.NumComponents(types.IgnoreBlankFields) <= 4 } @@ -164,7 +164,7 @@ func walkCompare(n *ir.BinaryExpr, init *ir.Nodes) ir.Node { call.Args.Append(typecheck.NodAddr(cmpl)) call.Args.Append(typecheck.NodAddr(cmpr)) if needsize { - call.Args.Append(ir.NewInt(t.Width)) + call.Args.Append(ir.NewInt(t.Size())) } res := ir.Node(call) if n.Op() != ir.OEQ { @@ -202,22 +202,22 @@ func walkCompare(n *ir.BinaryExpr, init *ir.Nodes) ir.Node { } } else { step := int64(1) - remains := t.NumElem() * t.Elem().Width - combine64bit := unalignedLoad && types.RegSize == 8 && t.Elem().Width <= 4 && t.Elem().IsInteger() - combine32bit := unalignedLoad && t.Elem().Width <= 2 && t.Elem().IsInteger() - combine16bit := unalignedLoad && t.Elem().Width == 1 && t.Elem().IsInteger() + remains := t.NumElem() * t.Elem().Size() + combine64bit := unalignedLoad && types.RegSize == 8 && t.Elem().Size() <= 4 && t.Elem().IsInteger() + combine32bit := unalignedLoad && t.Elem().Size() <= 2 && t.Elem().IsInteger() + combine16bit := unalignedLoad && t.Elem().Size() == 1 && t.Elem().IsInteger() for i := int64(0); remains > 0; { var convType *types.Type switch { case remains >= 8 && combine64bit: convType = types.Types[types.TINT64] - step = 8 / t.Elem().Width + step = 8 / t.Elem().Size() case remains >= 4 && combine32bit: convType = types.Types[types.TUINT32] - step = 4 / t.Elem().Width + step = 4 / t.Elem().Size() case remains >= 2 && combine16bit: convType = types.Types[types.TUINT16] - step = 2 / t.Elem().Width + step = 2 / t.Elem().Size() default: step = 1 } @@ -227,7 +227,7 @@ func walkCompare(n *ir.BinaryExpr, init *ir.Nodes) ir.Node { ir.NewIndexExpr(base.Pos, cmpr, ir.NewInt(i)), ) i++ - remains -= t.Elem().Width + remains -= t.Elem().Size() } else { elemType := t.Elem().ToUnsigned() cmplw := ir.Node(ir.NewIndexExpr(base.Pos, cmpl, ir.NewInt(i))) @@ -242,17 +242,17 @@ func walkCompare(n *ir.BinaryExpr, init *ir.Nodes) ir.Node { lb := ir.Node(ir.NewIndexExpr(base.Pos, cmpl, ir.NewInt(i+offset))) lb = typecheck.Conv(lb, elemType) lb = typecheck.Conv(lb, convType) - lb = ir.NewBinaryExpr(base.Pos, ir.OLSH, lb, ir.NewInt(8*t.Elem().Width*offset)) + lb = ir.NewBinaryExpr(base.Pos, ir.OLSH, lb, ir.NewInt(8*t.Elem().Size()*offset)) cmplw = ir.NewBinaryExpr(base.Pos, ir.OOR, cmplw, lb) rb := ir.Node(ir.NewIndexExpr(base.Pos, cmpr, ir.NewInt(i+offset))) rb = typecheck.Conv(rb, elemType) rb = typecheck.Conv(rb, convType) - rb = ir.NewBinaryExpr(base.Pos, ir.OLSH, rb, ir.NewInt(8*t.Elem().Width*offset)) + rb = ir.NewBinaryExpr(base.Pos, ir.OLSH, rb, ir.NewInt(8*t.Elem().Size()*offset)) cmprw = ir.NewBinaryExpr(base.Pos, ir.OOR, cmprw, rb) } compare(cmplw, cmprw) i += step - remains -= step * t.Elem().Width + remains -= step * t.Elem().Size() } } } diff --git a/src/cmd/compile/internal/walk/complit.go b/src/cmd/compile/internal/walk/complit.go index e8e941dd91..ad54fa7b96 100644 --- a/src/cmd/compile/internal/walk/complit.go +++ b/src/cmd/compile/internal/walk/complit.go @@ -277,7 +277,7 @@ func isSmallSliceLit(n *ir.CompLitExpr) bool { return false } - return n.Type().Elem().Width == 0 || n.Len <= ir.MaxSmallArraySize/n.Type().Elem().Width + return n.Type().Elem().Size() == 0 || n.Len <= ir.MaxSmallArraySize/n.Type().Elem().Size() } func slicelit(ctxt initContext, n *ir.CompLitExpr, var_ ir.Node, init *ir.Nodes) { @@ -650,7 +650,7 @@ func genAsStatic(as *ir.AssignStmt) { switch r := as.Y; r.Op() { case ir.OLITERAL: - staticdata.InitConst(name, offset, r, int(r.Type().Width)) + staticdata.InitConst(name, offset, r, int(r.Type().Size())) return case ir.OMETHEXPR: r := r.(*ir.SelectorExpr) diff --git a/src/cmd/compile/internal/walk/convert.go b/src/cmd/compile/internal/walk/convert.go index f724ca7cae..80a30d9455 100644 --- a/src/cmd/compile/internal/walk/convert.go +++ b/src/cmd/compile/internal/walk/convert.go @@ -145,7 +145,7 @@ func dataWord(n ir.Node, init *ir.Nodes, escapes bool) ir.Node { case n.Op() == ir.ONAME && n.(*ir.Name).Class == ir.PEXTERN && n.(*ir.Name).Readonly(): // n is a readonly global; use it directly. value = n - case !escapes && fromType.Width <= 1024: + case !escapes && fromType.Size() <= 1024: // n does not escape. Use a stack temporary initialized to n. value = typecheck.Temp(fromType) init.Append(typecheck.Stmt(ir.NewAssignStmt(base.Pos, value, n))) @@ -326,11 +326,11 @@ func dataWordFuncName(from *types.Type) (fnname string, argType *types.Type, nee base.Fatalf("can only handle non-interfaces") } switch { - case from.Size() == 2 && from.Align == 2: + case from.Size() == 2 && uint8(from.Alignment()) == 2: return "convT16", types.Types[types.TUINT16], false - case from.Size() == 4 && from.Align == 4 && !from.HasPointers(): + case from.Size() == 4 && uint8(from.Alignment()) == 4 && !from.HasPointers(): return "convT32", types.Types[types.TUINT32], false - case from.Size() == 8 && from.Align == types.Types[types.TUINT64].Align && !from.HasPointers(): + case from.Size() == 8 && uint8(from.Alignment()) == uint8(types.Types[types.TUINT64].Alignment()) && !from.HasPointers(): return "convT64", types.Types[types.TUINT64], false } if sc := from.SoleComponent(); sc != nil { diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go index c04998137b..ed2d68539d 100644 --- a/src/cmd/compile/internal/walk/expr.go +++ b/src/cmd/compile/internal/walk/expr.go @@ -767,7 +767,7 @@ func walkIndexMap(n *ir.IndexExpr, init *ir.Nodes) ir.Node { // m[k] is not the target of an assignment. fast := mapfast(t) key = mapKeyArg(fast, n, key) - if w := t.Elem().Width; w <= zeroValSize { + if w := t.Elem().Size(); w <= zeroValSize { call = mkcall1(mapfn(mapaccess1[fast], t, false), types.NewPtr(t.Elem()), init, reflectdata.TypePtr(t), map_, key) } else { z := reflectdata.ZeroAddr(w) @@ -873,7 +873,7 @@ func bounded(n ir.Node, max int64) bool { } sign := n.Type().IsSigned() - bits := int32(8 * n.Type().Width) + bits := int32(8 * n.Type().Size()) if ir.IsSmallIntConst(n) { v := ir.Int64Val(n) diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go index 6e336f565c..4de8858f26 100644 --- a/src/cmd/compile/internal/walk/order.go +++ b/src/cmd/compile/internal/walk/order.go @@ -297,7 +297,7 @@ func (o *orderState) mapKeyTemp(t *types.Type, n ir.Node) ir.Node { // Unsafe cast through memory. // We'll need to do a load with type kt. Create a temporary of type kt to // ensure sufficient alignment. nt may be under-aligned. - if kt.Align < nt.Align { + if uint8(kt.Alignment()) < uint8(nt.Alignment()) { base.Fatalf("mapKeyTemp: key type is not sufficiently aligned, kt=%v nt=%v", kt, nt) } tmp := o.newTemp(kt, true) diff --git a/src/cmd/compile/internal/walk/range.go b/src/cmd/compile/internal/walk/range.go index b1169fdae8..aa8c548963 100644 --- a/src/cmd/compile/internal/walk/range.go +++ b/src/cmd/compile/internal/walk/range.go @@ -112,7 +112,7 @@ func walkRange(nrange *ir.RangeStmt) ir.Node { } // for v1, v2 := range ha { body } - if cheapComputableIndex(t.Elem().Width) { + if cheapComputableIndex(t.Elem().Size()) { // v1, v2 = hv1, ha[hv1] tmp := ir.NewIndexExpr(base.Pos, ha, hv1) tmp.SetBounded(true) @@ -154,7 +154,7 @@ func walkRange(nrange *ir.RangeStmt) ir.Node { // This runs *after* the condition check, so we know // advancing the pointer is safe and won't go past the // end of the allocation. - as := ir.NewAssignStmt(base.Pos, hp, addptr(hp, t.Elem().Width)) + as := ir.NewAssignStmt(base.Pos, hp, addptr(hp, t.Elem().Size())) nfor.Late = []ir.Node{typecheck.Stmt(as)} case types.TMAP: @@ -408,7 +408,7 @@ func arrayClear(loop *ir.RangeStmt, v1, v2, a ir.Node) ir.Node { return nil } - elemsize := typecheck.RangeExprType(loop.X.Type()).Elem().Width + elemsize := typecheck.RangeExprType(loop.X.Type()).Elem().Size() if elemsize <= 0 || !ir.IsZero(stmt.Y) { return nil } diff --git a/src/cmd/compile/internal/walk/walk.go b/src/cmd/compile/internal/walk/walk.go index a9bbc9a54f..78cc2e69da 100644 --- a/src/cmd/compile/internal/walk/walk.go +++ b/src/cmd/compile/internal/walk/walk.go @@ -205,7 +205,7 @@ var mapdelete = mkmapnames("mapdelete", "") func mapfast(t *types.Type) int { // Check runtime/map.go:maxElemSize before changing. - if t.Elem().Width > 128 { + if t.Elem().Size() > 128 { return mapslow } switch reflectdata.AlgType(t.Key()) { -- GitLab From 68ecdc2c70544c303aa923139a5f16caf107d955 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 26 Aug 2021 17:48:01 -0700 Subject: [PATCH 0880/2500] cmd/compile/internal/types: add Type.OrigSym getter/setters Will be used in the next CL, so that Type.OrigSym can be unexported. Change-Id: I085f2a886abd419343c7ec7e4ae18c19de1fbbd4 Reviewed-on: https://go-review.googlesource.com/c/go/+/345484 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/types/type.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 7861effcb2..c7c8a53654 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -243,6 +243,11 @@ func (t *Type) Kind() Kind { return t.kind } func (t *Type) Sym() *Sym { return t.sym } func (t *Type) SetSym(sym *Sym) { t.sym = sym } +// OrigSym returns the name of the original generic type that t is an +// instantiation of, if any. +func (t *Type) OrigSym_() *Sym { return t.OrigSym } +func (t *Type) SetOrigSym(sym *Sym) { t.OrigSym = sym } + // Underlying returns the underlying type of type t. func (t *Type) Underlying() *Type { return t.underlying } -- GitLab From 82efc0540386dfaf78aaddfdb617ac90c7554f34 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 26 Aug 2021 17:48:12 -0700 Subject: [PATCH 0881/2500] cmd/compile: use Type.OrigSym getter/setters [generated] Automated CL to rewrite existing code to use OrigSym getters and setters. Afterwards, we also unexported OrigSym, and then rename the getter to OrigSym. [git-generate] cd src/cmd/compile/internal : Workaround rf issue with types2 tests. rm types2/*_test.go rf ' ex ./noder ./typecheck { import "cmd/compile/internal/types" var s *types.Sym var t *types.Type t.OrigSym = s -> t.SetOrigSym(s) t.OrigSym -> t.OrigSym_() } ' cd types rf ' mv Type.OrigSym Type.origSym mv Type.OrigSym_ Type.OrigSym ' : Revert types2 hack. cd ../types2 git checkout HEAD^ . Change-Id: I8eb17098613b1575df56b8189b1615823071d3d1 Reviewed-on: https://go-review.googlesource.com/c/go/+/345485 Run-TryBot: Matthew Dempsky Trust: Matthew Dempsky Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/noder/decl.go | 4 ++-- src/cmd/compile/internal/noder/stencil.go | 8 ++++---- src/cmd/compile/internal/noder/types.go | 2 +- src/cmd/compile/internal/typecheck/crawler.go | 4 ++-- src/cmd/compile/internal/typecheck/iexport.go | 4 ++-- src/cmd/compile/internal/typecheck/iimport.go | 10 +++++----- src/cmd/compile/internal/typecheck/subr.go | 4 ++-- src/cmd/compile/internal/types/type.go | 6 +++--- 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go index 54a13b498b..87a8667003 100644 --- a/src/cmd/compile/internal/noder/decl.go +++ b/src/cmd/compile/internal/noder/decl.go @@ -102,11 +102,11 @@ func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) { // the Fields to represent the receiver's method set. if recv := fn.Type().Recv(); recv != nil { typ := types.ReceiverBaseType(recv.Type) - if typ.OrigSym != nil { + if typ.OrigSym() != nil { // For a generic method, we mark the methods on the // base generic type, since those are the methods // that will be stenciled. - typ = typ.OrigSym.Def.Type() + typ = typ.OrigSym().Def.Type() } meth := typecheck.Lookdot1(fn, typecheck.Lookup(decl.Name.Value), typ, typ.Methods(), 0) meth.SetNointerface(true) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 7b85a88830..00c4676530 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -151,7 +151,7 @@ func (g *irgen) stencil() { targs := deref(meth.Type().Recv().Type).RParams() t := meth.X.Type() - baseSym := deref(t).OrigSym + baseSym := deref(t).OrigSym() baseType := baseSym.Def.(*ir.Name).Type() var gf *ir.Name for _, m := range baseType.Methods().Slice() { @@ -309,7 +309,7 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { // actually generic, so no need to build a closure. return x } - baseType := recv.OrigSym.Def.Type() + baseType := recv.OrigSym().Def.Type() var gf *ir.Name for _, m := range baseType.Methods().Slice() { if se.Sel == m.Sym { @@ -493,7 +493,7 @@ func (g *irgen) instantiateMethods() { typecheck.NeedRuntimeType(typ) // Lookup the method on the base generic type, since methods may // not be set on imported instantiated types. - baseSym := typ.OrigSym + baseSym := typ.OrigSym() baseType := baseSym.Def.(*ir.Name).Type() for j, _ := range typ.Methods().Slice() { if baseType.Methods().Slice()[j].Nointerface() { @@ -1465,7 +1465,7 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) // instantiated type, so we need a // sub-dictionary. targs := recvType.RParams() - genRecvType := recvType.OrigSym.Def.Type() + genRecvType := recvType.OrigSym().Def.Type() nameNode = typecheck.Lookdot1(call.X, se.Sel, genRecvType, genRecvType.Methods(), 1).Nname.(*ir.Name) sym = g.getDictionarySym(nameNode, targs, true) } else { diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index e00a3a5da9..c549dffc46 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -162,7 +162,7 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { //fmt.Printf("Saw new type %v %v\n", instName, ntyp.HasTParam()) // Save the symbol for the base generic type. - ntyp.OrigSym = g.pkg(typ.Obj().Pkg()).Lookup(typ.Obj().Name()) + ntyp.SetOrigSym(g.pkg(typ.Obj().Pkg()).Lookup(typ.Obj().Name())) ntyp.SetUnderlying(g.typ1(typ.Underlying())) if typ.NumMethods() != 0 { // Save a delayed call to g.fillinMethods() (once diff --git a/src/cmd/compile/internal/typecheck/crawler.go b/src/cmd/compile/internal/typecheck/crawler.go index 9a348b9f37..9e523c3d14 100644 --- a/src/cmd/compile/internal/typecheck/crawler.go +++ b/src/cmd/compile/internal/typecheck/crawler.go @@ -222,9 +222,9 @@ func (p *crawler) markInlBody(n *ir.Name) { // for export), so its methods will be available for inlining if needed. func (p *crawler) checkGenericType(t *types.Type) { if t != nil && t.HasTParam() { - if t.OrigSym != nil { + if t.OrigSym() != nil { // Convert to the base generic type. - t = t.OrigSym.Def.Type() + t = t.OrigSym().Def.Type() } p.markType(t) } diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 82006c3245..dbdf8eda35 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -878,7 +878,7 @@ func (w *exportWriter) startType(k itag) { func (w *exportWriter) doTyp(t *types.Type) { s := t.Sym() - if s != nil && t.OrigSym != nil { + if s != nil && t.OrigSym() != nil { assert(base.Flag.G > 0) // This is an instantiated type - could be a re-instantiation like // Value[T2] or a full instantiation like Value[int]. @@ -895,7 +895,7 @@ func (w *exportWriter) doTyp(t *types.Type) { // types or existing typeparams from the function/method header. w.typeList(t.RParams()) // Export a reference to the base type. - baseType := t.OrigSym.Def.(*ir.Name).Type() + baseType := t.OrigSym().Def.(*ir.Name).Type() w.typ(baseType) return } diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 87ad5d1c54..0dfc33db20 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -714,7 +714,7 @@ func (p *iimporter) typAt(off uint64) *types.Type { // No need to calc sizes for re-instantiated generic types, and // they are not necessarily resolved until the top-level type is // defined (because of recursive types). - if t.OrigSym == nil || !t.HasTParam() { + if t.OrigSym() == nil || !t.HasTParam() { types.CheckSize(t) } p.typCache[off] = t @@ -1395,7 +1395,7 @@ func (r *importReader) node() ir.Node { } else { genType := types.ReceiverBaseType(n1.X.Type()) if genType.IsInstantiatedGeneric() { - genType = genType.OrigSym.Def.Type() + genType = genType.OrigSym().Def.Type() } m = Lookdot1(n1, sel, genType, genType.Methods(), 1) } @@ -1778,7 +1778,7 @@ func Instantiate(pos src.XPos, baseType *types.Type, targs []*types.Type) *types t := NewIncompleteNamedType(baseType.Pos(), instSym) t.SetRParams(targs) - t.OrigSym = baseSym + t.SetOrigSym(baseSym) // baseType may still be TFORW or its methods may not be fully filled in // (since we are in the middle of importing it). So, delay call to @@ -1803,7 +1803,7 @@ func resumeDoInst() { for len(deferredInstStack) > 0 { t := deferredInstStack[0] deferredInstStack = deferredInstStack[1:] - substInstType(t, t.OrigSym.Def.(*ir.Name).Type(), t.RParams()) + substInstType(t, t.OrigSym().Def.(*ir.Name).Type(), t.RParams()) } } deferInst-- @@ -1814,7 +1814,7 @@ func resumeDoInst() { // during a type substitution for an instantiation. This is needed for // instantiations of mutually recursive types. func doInst(t *types.Type) *types.Type { - return Instantiate(t.Pos(), t.OrigSym.Def.(*ir.Name).Type(), t.RParams()) + return Instantiate(t.Pos(), t.OrigSym().Def.(*ir.Name).Type(), t.RParams()) } // substInstType completes the instantiation of a generic type by doing a diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 73f83f65e4..3ec2cc5d56 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1081,8 +1081,8 @@ func (ts *Tsubster) typ1(t *types.Type) *types.Type { forw.SetRParams(neededTargs) // Copy the OrigSym from the re-instantiated type (which is the sym of // the base generic type). - assert(t.OrigSym != nil) - forw.OrigSym = t.OrigSym + assert(t.OrigSym() != nil) + forw.SetOrigSym(t.OrigSym()) } var newt *types.Type diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index c7c8a53654..6f4bd0c114 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -198,7 +198,7 @@ type Type struct { // For an instantiated generic type, the symbol for the base generic type. // This backpointer is useful, because the base type is the type that has // the method bodies. - OrigSym *Sym + origSym *Sym } func (*Type) CanBeAnSSAAux() {} @@ -245,8 +245,8 @@ func (t *Type) SetSym(sym *Sym) { t.sym = sym } // OrigSym returns the name of the original generic type that t is an // instantiation of, if any. -func (t *Type) OrigSym_() *Sym { return t.OrigSym } -func (t *Type) SetOrigSym(sym *Sym) { t.OrigSym = sym } +func (t *Type) OrigSym() *Sym { return t.origSym } +func (t *Type) SetOrigSym(sym *Sym) { t.origSym = sym } // Underlying returns the underlying type of type t. func (t *Type) Underlying() *Type { return t.underlying } -- GitLab From a9377183d0f3ccd49631e2d927d55d91f2ab5ec6 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 26 Aug 2021 19:18:57 -0700 Subject: [PATCH 0882/2500] cmd/compile/internal/types: unexport New and NewBasic Now that the universe is fully initialized within package types, we can stop exporting New and NewBasic, which are only needed for that purpose. So this CL renames "New" to "newType" and "NewBasic" to "newBasic". This CL also moves the initialization of Types[TBLANK] and Types[TNIL] from typecheck.InitUniverse to types.InitTypes, which I missed in an earlier CL. And a use of "New(TSTRING)" in test/abiutils_test.go, which should just be "Types[TSTRING]" anyway. Change-Id: I1d83f93e27b88be289d4f3f6c16357a20f570460 Reviewed-on: https://go-review.googlesource.com/c/go/+/345487 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Matthew Dempsky Reviewed-by: Robert Griesemer --- .../compile/internal/test/abiutils_test.go | 2 +- .../compile/internal/typecheck/universe.go | 3 -- src/cmd/compile/internal/types/type.go | 52 +++++++++---------- src/cmd/compile/internal/types/universe.go | 7 ++- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/cmd/compile/internal/test/abiutils_test.go b/src/cmd/compile/internal/test/abiutils_test.go index 839546bcb8..f26cb89c6d 100644 --- a/src/cmd/compile/internal/test/abiutils_test.go +++ b/src/cmd/compile/internal/test/abiutils_test.go @@ -247,7 +247,7 @@ func TestABIUtilsSliceString(t *testing.T) { // p6 int64, p6 []intr32) (r1 string, r2 int64, r3 string, r4 []int32) i32 := types.Types[types.TINT32] sli32 := types.NewSlice(i32) - str := types.New(types.TSTRING) + str := types.Types[types.TSTRING] i8 := types.Types[types.TINT8] i64 := types.Types[types.TINT64] ft := mkFuncType(nil, []*types.Type{sli32, i8, sli32, i8, str, i8, i64, sli32}, diff --git a/src/cmd/compile/internal/typecheck/universe.go b/src/cmd/compile/internal/typecheck/universe.go index ebe338e2aa..0254d96e68 100644 --- a/src/cmd/compile/internal/typecheck/universe.go +++ b/src/cmd/compile/internal/typecheck/universe.go @@ -94,7 +94,6 @@ func InitUniverse() { types.BlankSym = s s.Block = -100 s.Def = NewName(s) - types.Types[types.TBLANK] = types.New(types.TBLANK) ir.AsNode(s.Def).SetType(types.Types[types.TBLANK]) ir.BlankNode = ir.AsNode(s.Def) ir.BlankNode.SetTypecheck(1) @@ -102,10 +101,8 @@ func InitUniverse() { s = types.BuiltinPkg.Lookup("_") s.Block = -100 s.Def = NewName(s) - types.Types[types.TBLANK] = types.New(types.TBLANK) ir.AsNode(s.Def).SetType(types.Types[types.TBLANK]) - types.Types[types.TNIL] = types.New(types.TNIL) s = types.BuiltinPkg.Lookup("nil") nnil := NodNil() nnil.(*ir.NilExpr).SetSym(s) diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 6f4bd0c114..6070e15868 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -127,14 +127,14 @@ var ( ComparableType *Type // Types to represent untyped string and boolean constants. - UntypedString = New(TSTRING) - UntypedBool = New(TBOOL) + UntypedString = newType(TSTRING) + UntypedBool = newType(TBOOL) // Types to represent untyped numeric constants. - UntypedInt = New(TIDEAL) - UntypedRune = New(TIDEAL) - UntypedFloat = New(TIDEAL) - UntypedComplex = New(TIDEAL) + UntypedInt = newType(TIDEAL) + UntypedRune = newType(TIDEAL) + UntypedFloat = newType(TIDEAL) + UntypedComplex = newType(TIDEAL) ) // A Type represents a Go type. @@ -586,7 +586,7 @@ func (f *Fields) Append(s ...*Field) { } // New returns a new Type of the specified kind. -func New(et Kind) *Type { +func newType(et Kind) *Type { t := &Type{ kind: et, width: BADWIDTH, @@ -629,7 +629,7 @@ func NewArray(elem *Type, bound int64) *Type { if bound < 0 { base.Fatalf("NewArray: invalid bound %v", bound) } - t := New(TARRAY) + t := newType(TARRAY) t.extra = &Array{Elem: elem, Bound: bound} t.SetNotInHeap(elem.NotInHeap()) if elem.HasTParam() { @@ -650,7 +650,7 @@ func NewSlice(elem *Type) *Type { return t } - t := New(TSLICE) + t := newType(TSLICE) t.extra = Slice{Elem: elem} elem.cache.slice = t if elem.HasTParam() { @@ -664,7 +664,7 @@ func NewSlice(elem *Type) *Type { // NewChan returns a new chan Type with direction dir. func NewChan(elem *Type, dir ChanDir) *Type { - t := New(TCHAN) + t := newType(TCHAN) ct := t.ChanType() ct.Elem = elem ct.Dir = dir @@ -678,7 +678,7 @@ func NewChan(elem *Type, dir ChanDir) *Type { } func NewTuple(t1, t2 *Type) *Type { - t := New(TTUPLE) + t := newType(TTUPLE) t.extra.(*Tuple).first = t1 t.extra.(*Tuple).second = t2 if t1.HasTParam() || t2.HasTParam() { @@ -691,7 +691,7 @@ func NewTuple(t1, t2 *Type) *Type { } func newResults(types []*Type) *Type { - t := New(TRESULTS) + t := newType(TRESULTS) t.extra.(*Results).Types = types return t } @@ -704,14 +704,14 @@ func NewResults(types []*Type) *Type { } func newSSA(name string) *Type { - t := New(TSSA) + t := newType(TSSA) t.extra = name return t } // NewMap returns a new map Type with key type k and element (aka value) type v. func NewMap(k, v *Type) *Type { - t := New(TMAP) + t := newType(TMAP) mt := t.MapType() mt.Key = k mt.Elem = v @@ -751,7 +751,7 @@ func NewPtr(elem *Type) *Type { return t } - t := New(TPTR) + t := newType(TPTR) t.extra = Ptr{Elem: elem} t.width = int64(PtrSize) t.align = uint8(PtrSize) @@ -769,14 +769,14 @@ func NewPtr(elem *Type) *Type { // NewChanArgs returns a new TCHANARGS type for channel type c. func NewChanArgs(c *Type) *Type { - t := New(TCHANARGS) + t := newType(TCHANARGS) t.extra = ChanArgs{T: c} return t } // NewFuncArgs returns a new TFUNCARGS type for func type f. func NewFuncArgs(f *Type) *Type { - t := New(TFUNCARGS) + t := newType(TFUNCARGS) t.extra = FuncArgs{T: f} return t } @@ -1738,7 +1738,7 @@ var recvType *Type // FakeRecvType returns the singleton type used for interface method receivers. func FakeRecvType() *Type { if recvType == nil { - recvType = NewPtr(New(TSTRUCT)) + recvType = NewPtr(newType(TSTRUCT)) } return recvType } @@ -1763,7 +1763,7 @@ var ( // maintained until the type is filled in, so those references can be updated when // the type is complete. func NewNamed(obj Object) *Type { - t := New(TFORW) + t := newType(TFORW) t.sym = obj.Sym() t.nod = obj return t @@ -1867,8 +1867,8 @@ func fieldsHasShape(fields []*Field) bool { } // NewBasic returns a new basic type of the given kind. -func NewBasic(kind Kind, obj Object) *Type { - t := New(kind) +func newBasic(kind Kind, obj Object) *Type { + t := newType(kind) t.sym = obj.Sym() t.nod = obj return t @@ -1877,7 +1877,7 @@ func NewBasic(kind Kind, obj Object) *Type { // NewInterface returns a new interface for the given methods and // embedded types. Embedded types are specified as fields with no Sym. func NewInterface(pkg *Pkg, methods []*Field) *Type { - t := New(TINTER) + t := newType(TINTER) t.SetInterface(methods) for _, f := range methods { // f.Type could be nil for a broken interface declaration @@ -1900,7 +1900,7 @@ func NewInterface(pkg *Pkg, methods []*Field) *Type { // NewTypeParam returns a new type param with the specified sym (package and name) // and specified index within the typeparam list. func NewTypeParam(sym *Sym, index int) *Type { - t := New(TTYPEPARAM) + t := newType(TTYPEPARAM) t.sym = sym t.extra.(*Typeparam).index = index t.SetHasTParam(true) @@ -1934,7 +1934,7 @@ func (t *Type) Bound() *Type { // NewUnion returns a new union with the specified set of terms (types). If // tildes[i] is true, then terms[i] represents ~T, rather than just T. func NewUnion(terms []*Type, tildes []bool) *Type { - t := New(TUNION) + t := newType(TUNION) if len(terms) != len(tildes) { base.Fatalf("Mismatched terms and tildes for NewUnion") } @@ -1982,7 +1982,7 @@ func NewSignature(pkg *Pkg, recv *Field, tparams, params, results []*Field) *Typ recvs = []*Field{recv} } - t := New(TFUNC) + t := newType(TFUNC) ft := t.FuncType() funargs := func(fields []*Field, funarg Funarg) *Type { @@ -2018,7 +2018,7 @@ func NewSignature(pkg *Pkg, recv *Field, tparams, params, results []*Field) *Typ // NewStruct returns a new struct with the given fields. func NewStruct(pkg *Pkg, fields []*Field) *Type { - t := New(TSTRUCT) + t := newType(TSTRUCT) t.SetFields(fields) if anyBroke(fields) { t.SetBroke(true) diff --git a/src/cmd/compile/internal/types/universe.go b/src/cmd/compile/internal/types/universe.go index abceecd15d..1291b0e0fa 100644 --- a/src/cmd/compile/internal/types/universe.go +++ b/src/cmd/compile/internal/types/universe.go @@ -57,11 +57,11 @@ func InitTypes(defTypeName func(sym *Sym, typ *Type) Object) { SimType[et] = et } - Types[TANY] = New(TANY) + Types[TANY] = newType(TANY) Types[TINTER] = NewInterface(LocalPkg, nil) defBasic := func(kind Kind, pkg *Pkg, name string) *Type { - typ := New(kind) + typ := newType(kind) obj := defTypeName(pkg.Lookup(name), typ) typ.sym = obj.Sym() typ.nod = obj @@ -109,6 +109,9 @@ func InitTypes(defTypeName func(sym *Sym, typ *Type) Object) { Types[TUNSAFEPTR] = defBasic(TUNSAFEPTR, UnsafePkg, "Pointer") + Types[TBLANK] = newType(TBLANK) + Types[TNIL] = newType(TNIL) + // simple aliases SimType[TMAP] = TPTR SimType[TCHAN] = TPTR -- GitLab From c81fa001a7b01be5ce9d2990e706f0ed2c1299e8 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 27 Aug 2021 17:14:00 -0700 Subject: [PATCH 0883/2500] cmd/compile/internal/types: simplify and optimize PtrDataSize The current implementation of PtrDataSize checks HasPointers each call, which could lead to exponential blow-up in handling (admittedly contrived) deeply nested structs. To avoid the duplicate recursion, this CL incorporates the HasPointers logic directly int PtrDataSize, and then re-defines HasPointers as simply "PtrDataSize(t) > 0". This CL also tightens up HasPointers/PtrDataSize to only be valid on actual Go types. Fortunately, there was only one instance where this wasn't already the case (escape analysis), and that's easily fixed with an extra check for untyped types. Change-Id: I0044bf9b558a88333aee2ccb137afb6cb4fea1db Reviewed-on: https://go-review.googlesource.com/c/go/+/345809 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/escape/expr.go | 2 +- src/cmd/compile/internal/types/size.go | 46 ++++++++++++++++--------- src/cmd/compile/internal/types/type.go | 38 +------------------- 3 files changed, 32 insertions(+), 54 deletions(-) diff --git a/src/cmd/compile/internal/escape/expr.go b/src/cmd/compile/internal/escape/expr.go index 62afb5b928..ced90a47bc 100644 --- a/src/cmd/compile/internal/escape/expr.go +++ b/src/cmd/compile/internal/escape/expr.go @@ -30,7 +30,7 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) { base.Pos = lno }() - if k.derefs >= 0 && !n.Type().HasPointers() { + if k.derefs >= 0 && !n.Type().IsUntyped() && !n.Type().HasPointers() { k.dst = &e.blankLoc } diff --git a/src/cmd/compile/internal/types/size.go b/src/cmd/compile/internal/types/size.go index aeeca90746..a47a26da74 100644 --- a/src/cmd/compile/internal/types/size.go +++ b/src/cmd/compile/internal/types/size.go @@ -630,17 +630,23 @@ func ResumeCheckSize() { // PtrDataSize returns the length in bytes of the prefix of t // containing pointer data. Anything after this offset is scalar data. +// +// PtrDataSize is only defined for actual Go types. It's an error to +// use it on compiler-internal types (e.g., TSSA, TRESULTS). func PtrDataSize(t *Type) int64 { - if !t.HasPointers() { + switch t.Kind() { + case TBOOL, TINT8, TUINT8, TINT16, TUINT16, TINT32, + TUINT32, TINT64, TUINT64, TINT, TUINT, + TUINTPTR, TCOMPLEX64, TCOMPLEX128, TFLOAT32, TFLOAT64: return 0 - } - switch t.Kind() { - case TPTR, - TUNSAFEPTR, - TFUNC, - TCHAN, - TMAP: + case TPTR: + if t.Elem().NotInHeap() { + return 0 + } + return int64(PtrSize) + + case TUNSAFEPTR, TFUNC, TCHAN, TMAP: return int64(PtrSize) case TSTRING: @@ -654,24 +660,32 @@ func PtrDataSize(t *Type) int64 { return 2 * int64(PtrSize) case TSLICE: + if t.Elem().NotInHeap() { + return 0 + } // struct { byte *array; uintgo len; uintgo cap; } return int64(PtrSize) case TARRAY: - // haspointers already eliminated t.NumElem() == 0. - return (t.NumElem()-1)*t.Elem().width + PtrDataSize(t.Elem()) + if t.NumElem() == 0 { + return 0 + } + // t.NumElem() > 0 + size := PtrDataSize(t.Elem()) + if size == 0 { + return 0 + } + return (t.NumElem()-1)*t.Elem().Size() + size case TSTRUCT: - // Find the last field that has pointers. - var lastPtrField *Field + // Find the last field that has pointers, if any. fs := t.Fields().Slice() for i := len(fs) - 1; i >= 0; i-- { - if fs[i].Type.HasPointers() { - lastPtrField = fs[i] - break + if size := PtrDataSize(fs[i].Type); size > 0 { + return fs[i].Offset + size } } - return lastPtrField.Offset + PtrDataSize(lastPtrField.Type) + return 0 default: base.Fatalf("PtrDataSize: unexpected type, %v", t) diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 6070e15868..dafd76c79a 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -1681,43 +1681,7 @@ func (t *Type) IsUntyped() bool { // HasPointers reports whether t contains a heap pointer. // Note that this function ignores pointers to go:notinheap types. func (t *Type) HasPointers() bool { - switch t.kind { - case TINT, TUINT, TINT8, TUINT8, TINT16, TUINT16, TINT32, TUINT32, TINT64, - TUINT64, TUINTPTR, TFLOAT32, TFLOAT64, TCOMPLEX64, TCOMPLEX128, TBOOL, TSSA: - return false - - case TARRAY: - if t.NumElem() == 0 { // empty array has no pointers - return false - } - return t.Elem().HasPointers() - - case TSTRUCT: - for _, t1 := range t.Fields().Slice() { - if t1.Type.HasPointers() { - return true - } - } - return false - - case TPTR, TSLICE: - return !t.Elem().NotInHeap() - - case TTUPLE: - ttup := t.extra.(*Tuple) - return ttup.first.HasPointers() || ttup.second.HasPointers() - - case TRESULTS: - types := t.extra.(*Results).Types - for _, et := range types { - if et.HasPointers() { - return true - } - } - return false - } - - return true + return PtrDataSize(t) > 0 } // Tie returns 'T' if t is a concrete type, -- GitLab From 5fb177163bccb66a39516542e4b9e127ec771c1f Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 27 Aug 2021 17:04:42 -0700 Subject: [PATCH 0884/2500] go/types, types2: types in type switch cases must be instantiated We already have a function that does all the right checks and it's called varType. The only reason it wasn't used for type switch cases was that we also have to accept the nil value. That was handled with typeOrNil. But that function (typeOrNil) was only used for this specific purpose and I long wished to get rid of it. It turns out that there's only one way to write the untyped value nil, which is to actually write "nil" (maybe with parentheses). So looking for that turned out to be simpler than using typeOrNil. The new code does exactly that, and now we can just use varType and delete typeOrNil. With this, there is now less code (excluding the test) and the code is simpler and more correct. Fixes #48008. Change-Id: I8f2d80e61ae663c886924909f22bbfa634e7779c Reviewed-on: https://go-review.googlesource.com/c/go/+/345790 Trust: Robert Griesemer Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/types2/stmt.go | 26 ++++++-- .../types2/testdata/fixedbugs/issue48008.go2 | 60 +++++++++++++++++++ src/cmd/compile/internal/types2/typexpr.go | 24 -------- src/go/types/stmt.go | 26 ++++++-- .../types/testdata/fixedbugs/issue48008.go2 | 60 +++++++++++++++++++ src/go/types/typexpr.go | 27 --------- 6 files changed, 160 insertions(+), 63 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue48008.go2 create mode 100644 src/go/types/testdata/fixedbugs/issue48008.go2 diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index 8cfdf92e67..3e2ac2e29e 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -264,15 +264,29 @@ L: } } +// isNil reports whether the expression e denotes the predeclared value nil. +func (check *Checker) isNil(e syntax.Expr) bool { + // The only way to express the nil value is by literally writing nil (possibly in parentheses). + if name, _ := unparen(e).(*syntax.Name); name != nil { + _, ok := check.lookup(name.Value).(*Nil) + return ok + } + return false +} + func (check *Checker) caseTypes(x *operand, xtyp *Interface, types []syntax.Expr, seen map[Type]syntax.Expr) (T Type) { + var dummy operand L: for _, e := range types { - T = check.typOrNil(e) - if T == Typ[Invalid] { - continue L - } - if T != nil { - check.ordinaryType(e.Pos(), T) + // The spec allows the value nil instead of a type. + if check.isNil(e) { + T = nil + check.expr(&dummy, e) // run e through expr so we get the usual Info recordings + } else { + T = check.varType(e) + if T == Typ[Invalid] { + continue L + } } // look for duplicate types // (quadratic algorithm, but type switches tend to be reasonably small) diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48008.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48008.go2 new file mode 100644 index 0000000000..5c9726875c --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48008.go2 @@ -0,0 +1,60 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T[P any] struct{} + +func _(x interface{}) { + switch x.(type) { + case nil: + case int: + + case T[int]: + case []T[int]: + case [10]T[int]: + case struct{T[int]}: + case *T[int]: + case func(T[int]): + case interface{m(T[int])}: + case map[T[int]] string: + case chan T[int]: + + case T /* ERROR cannot use generic type T\[P interface{}\] without instantiation */ : + case []T /* ERROR cannot use generic type */ : + case [10]T /* ERROR cannot use generic type */ : + case struct{T /* ERROR cannot use generic type */ }: + case *T /* ERROR cannot use generic type */ : + case func(T /* ERROR cannot use generic type */ ): + case interface{m(T /* ERROR cannot use generic type */ )}: + case map[T /* ERROR cannot use generic type */ ] string: + case chan T /* ERROR cannot use generic type */ : + + case T /* ERROR cannot use generic type */ , *T /* ERROR cannot use generic type */ : + } +} + +// Make sure a parenthesized nil is ok. + +func _(x interface{}) { + switch x.(type) { + case ((nil)), int: + } +} + +// Make sure we look for the predeclared nil. + +func _(x interface{}) { + type nil int + switch x.(type) { + case nil: // ok - this is the type nil + } +} + +func _(x interface{}) { + var nil int + switch x.(type) { + case nil /* ERROR not a type */ : // not ok - this is the variable nil + } +} diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 6938648bbc..33e7559cc9 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -398,30 +398,6 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) { return typ } -// typeOrNil type-checks the type expression (or nil value) e -// and returns the type of e, or nil. If e is a type, it must -// not be an (uninstantiated) generic type. -// If e is neither a type nor nil, typeOrNil returns Typ[Invalid]. -// TODO(gri) should we also disallow non-var types? -func (check *Checker) typOrNil(e syntax.Expr) Type { - var x operand - check.rawExpr(&x, e, nil) - switch x.mode { - case invalid: - // ignore - error reported before - case novalue: - check.errorf(&x, "%s used as type", &x) - case typexpr: - check.instantiatedOperand(&x) - return x.typ - case nilvalue: - return nil - default: - check.errorf(&x, "%s is not a type", &x) - } - return Typ[Invalid] -} - func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def *Named) Type { gtyp := check.genericType(x, true) if gtyp == Typ[Invalid] { diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index fd6eba2deb..056b21e3d2 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -276,15 +276,29 @@ L: } } +// isNil reports whether the expression e denotes the predeclared value nil. +func (check *Checker) isNil(e ast.Expr) bool { + // The only way to express the nil value is by literally writing nil (possibly in parentheses). + if name, _ := unparen(e).(*ast.Ident); name != nil { + _, ok := check.lookup(name.Name).(*Nil) + return ok + } + return false +} + func (check *Checker) caseTypes(x *operand, xtyp *Interface, types []ast.Expr, seen map[Type]ast.Expr) (T Type) { + var dummy operand L: for _, e := range types { - T = check.typeOrNil(e) - if T == Typ[Invalid] { - continue L - } - if T != nil { - check.ordinaryType(e, T) + // The spec allows the value nil instead of a type. + if check.isNil(e) { + T = nil + check.expr(&dummy, e) // run e through expr so we get the usual Info recordings + } else { + T = check.varType(e) + if T == Typ[Invalid] { + continue L + } } // look for duplicate types // (quadratic algorithm, but type switches tend to be reasonably small) diff --git a/src/go/types/testdata/fixedbugs/issue48008.go2 b/src/go/types/testdata/fixedbugs/issue48008.go2 new file mode 100644 index 0000000000..5c9726875c --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue48008.go2 @@ -0,0 +1,60 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T[P any] struct{} + +func _(x interface{}) { + switch x.(type) { + case nil: + case int: + + case T[int]: + case []T[int]: + case [10]T[int]: + case struct{T[int]}: + case *T[int]: + case func(T[int]): + case interface{m(T[int])}: + case map[T[int]] string: + case chan T[int]: + + case T /* ERROR cannot use generic type T\[P interface{}\] without instantiation */ : + case []T /* ERROR cannot use generic type */ : + case [10]T /* ERROR cannot use generic type */ : + case struct{T /* ERROR cannot use generic type */ }: + case *T /* ERROR cannot use generic type */ : + case func(T /* ERROR cannot use generic type */ ): + case interface{m(T /* ERROR cannot use generic type */ )}: + case map[T /* ERROR cannot use generic type */ ] string: + case chan T /* ERROR cannot use generic type */ : + + case T /* ERROR cannot use generic type */ , *T /* ERROR cannot use generic type */ : + } +} + +// Make sure a parenthesized nil is ok. + +func _(x interface{}) { + switch x.(type) { + case ((nil)), int: + } +} + +// Make sure we look for the predeclared nil. + +func _(x interface{}) { + type nil int + switch x.(type) { + case nil: // ok - this is the type nil + } +} + +func _(x interface{}) { + var nil int + switch x.(type) { + case nil /* ERROR not a type */ : // not ok - this is the variable nil + } +} diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index baa4e3c2d0..5c8a6b497d 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -383,33 +383,6 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) { return typ } -// typeOrNil type-checks the type expression (or nil value) e -// and returns the type of e, or nil. If e is a type, it must -// not be an (uninstantiated) generic type. -// If e is neither a type nor nil, typeOrNil returns Typ[Invalid]. -// TODO(gri) should we also disallow non-var types? -func (check *Checker) typeOrNil(e ast.Expr) Type { - var x operand - check.rawExpr(&x, e, nil) - switch x.mode { - case invalid: - // ignore - error reported before - case novalue: - check.errorf(&x, _NotAType, "%s used as type", &x) - case typexpr: - check.instantiatedOperand(&x) - return x.typ - case value: - if x.isNil() { - return nil - } - fallthrough - default: - check.errorf(&x, _NotAType, "%s is not a type", &x) - } - return Typ[Invalid] -} - func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named) Type { gtyp := check.genericType(x, true) if gtyp == Typ[Invalid] { -- GitLab From ef4cb2f776f1c7e861604d1b46ab8fcf2672f10d Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 27 Aug 2021 17:57:04 -0700 Subject: [PATCH 0885/2500] cmd/compile/internal/types: change NewNamed to use TypeObject Semantically, TypeObject is the interface that go/types.TypeName would implement, so we might as well use that instead of the more generic Object (analog to go/types.Object) for NewNamed. In practice, this doesn't really matter though, because we use *ir.Name for almost all Objects anyway. Also, remove VarObject: its last use was removed in CL 302071 (March 2021). Change-Id: I6e987ecd419105e09f74fc8d60cadb61bcbc751f Reviewed-on: https://go-review.googlesource.com/c/go/+/345810 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/cmd/compile/internal/types/type.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index dafd76c79a..f1fb93ad1b 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -27,12 +27,6 @@ type TypeObject interface { TypeDefn() *Type // for "type T Defn", returns Defn } -// A VarObject is an Object representing a function argument, variable, or struct field. -type VarObject interface { - Object - RecordFrameOffset(int64) // save frame offset -} - //go:generate stringer -type Kind -trimprefix T type.go // Kind describes a kind of type. @@ -1726,7 +1720,7 @@ var ( // type should be set later via SetUnderlying(). References to the type are // maintained until the type is filled in, so those references can be updated when // the type is complete. -func NewNamed(obj Object) *Type { +func NewNamed(obj TypeObject) *Type { t := newType(TFORW) t.sym = obj.Sym() t.nod = obj -- GitLab From f371b30f326b66e4c5c13c7ea51358a42c431752 Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Wed, 11 Aug 2021 23:51:09 -0700 Subject: [PATCH 0886/2500] unicode/utf8: add AppendRune MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AppendRune appends the UTF-8 encoding of a rune to a []byte. It is a generally more user friendly than EncodeRune. EncodeASCIIRune-4 2.35ns ± 2% EncodeJapaneseRune-4 4.60ns ± 2% AppendASCIIRune-4 0.30ns ± 3% AppendJapaneseRune-4 4.70ns ± 2% The ASCII case is written to be inlineable. Fixes #47609 Change-Id: If4f71eedffd2bd4ef0d7f960cb55b41c637eec54 Reviewed-on: https://go-review.googlesource.com/c/go/+/345571 Trust: Joe Tsai Reviewed-by: Rob Pike Run-TryBot: Rob Pike TryBot-Result: Go Bot --- src/cmd/compile/internal/test/inl_test.go | 1 + src/unicode/utf8/utf8.go | 26 +++++++++++++++++++++++ src/unicode/utf8/utf8_test.go | 25 ++++++++++++++++++++++ 3 files changed, 52 insertions(+) diff --git a/src/cmd/compile/internal/test/inl_test.go b/src/cmd/compile/internal/test/inl_test.go index bbdbe0c37c..4f20ec1bd1 100644 --- a/src/cmd/compile/internal/test/inl_test.go +++ b/src/cmd/compile/internal/test/inl_test.go @@ -122,6 +122,7 @@ func TestIntendedInlining(t *testing.T) { "FullRune", "FullRuneInString", "RuneLen", + "AppendRune", "ValidRune", }, "reflect": { diff --git a/src/unicode/utf8/utf8.go b/src/unicode/utf8/utf8.go index 557e8a7770..6938c7e6a7 100644 --- a/src/unicode/utf8/utf8.go +++ b/src/unicode/utf8/utf8.go @@ -369,6 +369,32 @@ func EncodeRune(p []byte, r rune) int { } } +// AppendRune appends the UTF-8 encoding of r to the end of p and +// returns the extended buffer. If the rune is out of range, +// it appends the encoding of RuneError. +func AppendRune(p []byte, r rune) []byte { + // This function is inlineable for fast handling of ASCII. + if uint32(r) <= rune1Max { + return append(p, byte(r)) + } + return appendRuneNonASCII(p, r) +} + +func appendRuneNonASCII(p []byte, r rune) []byte { + // Negative values are erroneous. Making it unsigned addresses the problem. + switch i := uint32(r); { + case i <= rune2Max: + return append(p, t2|byte(r>>6), tx|byte(r)&maskx) + case i > MaxRune, surrogateMin <= i && i <= surrogateMax: + r = RuneError + fallthrough + case i <= rune3Max: + return append(p, t3|byte(r>>12), tx|byte(r>>6)&maskx, tx|byte(r)&maskx) + default: + return append(p, t4|byte(r>>18), tx|byte(r>>12)&maskx, tx|byte(r>>6)&maskx, tx|byte(r)&maskx) + } +} + // RuneCount returns the number of runes in p. Erroneous and short // encodings are treated as single runes of width 1 byte. func RuneCount(p []byte) int { diff --git a/src/unicode/utf8/utf8_test.go b/src/unicode/utf8/utf8_test.go index eaf1b5ffee..a60040ecfd 100644 --- a/src/unicode/utf8/utf8_test.go +++ b/src/unicode/utf8/utf8_test.go @@ -127,6 +127,17 @@ func TestEncodeRune(t *testing.T) { } } +func TestAppendRune(t *testing.T) { + for _, m := range utf8map { + if buf := AppendRune(nil, m.r); string(buf) != m.str { + t.Errorf("AppendRune(nil, %#04x) = %s, want %s", m.r, buf, m.str) + } + if buf := AppendRune([]byte("init"), m.r); string(buf) != "init"+m.str { + t.Errorf("AppendRune(nil, %#04x) = %s, want %s", m.r, buf, "init"+m.str) + } + } +} + func TestDecodeRune(t *testing.T) { for _, m := range utf8map { b := []byte(m.str) @@ -583,6 +594,20 @@ func BenchmarkEncodeJapaneseRune(b *testing.B) { } } +func BenchmarkAppendASCIIRune(b *testing.B) { + buf := make([]byte, UTFMax) + for i := 0; i < b.N; i++ { + AppendRune(buf[:0], 'a') + } +} + +func BenchmarkAppendJapaneseRune(b *testing.B) { + buf := make([]byte, UTFMax) + for i := 0; i < b.N; i++ { + AppendRune(buf[:0], '本') + } +} + func BenchmarkDecodeASCIIRune(b *testing.B) { a := []byte{'a'} for i := 0; i < b.N; i++ { -- GitLab From 010817714e16b859211b50bde6ea7c804263146c Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sat, 28 Aug 2021 11:22:06 +0700 Subject: [PATCH 0887/2500] cmd/compile: ignore SliceExpr.CheckPtrCall for mknode CL 343972 added SliceExpr.CheckPtrCall field but forgot to add ignore tag for mknode. This CL adds the missing tag. Change-Id: Ib39bff3d456063bdc10fc17b4047b8392d373bf1 Reviewed-on: https://go-review.googlesource.com/c/go/+/345431 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le Reviewed-by: Matthew Dempsky TryBot-Result: Go Bot --- src/cmd/compile/internal/ir/expr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 41de6bd61b..baf0117409 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -574,7 +574,7 @@ type SliceExpr struct { Low Node High Node Max Node - CheckPtrCall *CallExpr + CheckPtrCall *CallExpr `mknode:"-"` } func NewSliceExpr(pos src.XPos, op Op, x, low, high, max Node) *SliceExpr { -- GitLab From 044550ab0ee28fe85b98600503c9f33642697d76 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sat, 28 Aug 2021 10:08:32 +0700 Subject: [PATCH 0888/2500] runtime: add test case for checkptr alignment with nested expression Discover while working on moving checkptr instrumentation from walk to SSA generation. Change-Id: I3f4a41fe4ad308b86c7c57d14b6ccc7c613e7f98 Reviewed-on: https://go-review.googlesource.com/c/go/+/345432 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/runtime/checkptr_test.go | 37 +++++++++++++++++++++++ src/runtime/testdata/testprog/checkptr.go | 8 +++++ 2 files changed, 45 insertions(+) diff --git a/src/runtime/checkptr_test.go b/src/runtime/checkptr_test.go index d5dd101adb..b3aea079c6 100644 --- a/src/runtime/checkptr_test.go +++ b/src/runtime/checkptr_test.go @@ -55,3 +55,40 @@ func TestCheckPtr(t *testing.T) { }) } } + +func TestCheckPtr2(t *testing.T) { + t.Parallel() + testenv.MustHaveGoRun(t) + + exe, err := buildTestProg(t, "testprog", "-gcflags=all=-d=checkptr=2") + if err != nil { + t.Fatal(err) + } + + testCases := []struct { + cmd string + want string + }{ + {"CheckPtrAlignmentNested", "fatal error: checkptr: converted pointer straddles multiple allocations\n"}, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.cmd, func(t *testing.T) { + t.Parallel() + got, err := testenv.CleanCmdEnv(exec.Command(exe, tc.cmd)).CombinedOutput() + if err != nil { + t.Log(err) + } + if tc.want == "" { + if len(got) > 0 { + t.Errorf("output:\n%s\nwant no output", got) + } + return + } + if !strings.HasPrefix(string(got), tc.want) { + t.Errorf("output:\n%s\n\nwant output starting with: %s", got, tc.want) + } + }) + } +} diff --git a/src/runtime/testdata/testprog/checkptr.go b/src/runtime/testdata/testprog/checkptr.go index 9c5561396e..b27e5f74f8 100644 --- a/src/runtime/testdata/testprog/checkptr.go +++ b/src/runtime/testdata/testprog/checkptr.go @@ -20,6 +20,7 @@ func init() { register("CheckPtrSmall", CheckPtrSmall) register("CheckPtrSliceOK", CheckPtrSliceOK) register("CheckPtrSliceFail", CheckPtrSliceFail) + register("CheckPtrAlignmentNested", CheckPtrAlignmentNested) } func CheckPtrAlignmentNoPtr() { @@ -96,3 +97,10 @@ func CheckPtrSliceFail() { sink2 = p sink2 = unsafe.Slice(p, 100) } + +func CheckPtrAlignmentNested() { + s := make([]int8, 100) + p := unsafe.Pointer(&s[0]) + n := 9 + _ = ((*[10]int8)(unsafe.Pointer((*[10]int64)(unsafe.Pointer(&p)))))[:n:n] +} -- GitLab From d7a43e89124044f0f468e656ec17a3cc86916b33 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 25 Aug 2021 17:12:27 -0700 Subject: [PATCH 0889/2500] cmd/compile: support type C comparable Support 'type C comparable' properly by using the same logic as for 'type T error', since ErrorType and ComparableType are entirely analogous. Added support for 'any' type as well, as requested by Robert. (For the future - we can't currently have 'any' anywhere other than in a constraint.) Fixes #47966 Change-Id: I68bd284ced9a8bfca7d2339cd576f3cb909b1b83 Reviewed-on: https://go-review.googlesource.com/c/go/+/345174 Trust: Dan Scales Trust: Robert Griesemer Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/typecheck/bexport.go | 3 +++ src/cmd/compile/internal/typecheck/iexport.go | 8 ++++++++ src/cmd/compile/internal/types/type.go | 2 ++ src/cmd/compile/internal/types/universe.go | 8 ++++++++ test/typeparam/issue47966.go | 9 +++++++++ test/typeparam/subdict.go | 4 +++- 6 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 test/typeparam/issue47966.go diff --git a/src/cmd/compile/internal/typecheck/bexport.go b/src/cmd/compile/internal/typecheck/bexport.go index cc7f91f937..352f7a96ad 100644 --- a/src/cmd/compile/internal/typecheck/bexport.go +++ b/src/cmd/compile/internal/typecheck/bexport.go @@ -99,6 +99,9 @@ func predeclared() []*types.Type { // comparable types.ComparableType, + + // any + types.AnyType, } } return predecl diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index dbdf8eda35..89eab4df16 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -566,6 +566,14 @@ func (p *iexporter) doDecl(n *ir.Name) { // for predeclared objects). underlying = types.ErrorType } + if underlying == types.ComparableType.Underlying() { + // Do same for ComparableType as for ErrorType. + underlying = types.ComparableType + } + if base.Flag.G > 0 && underlying == types.AnyType.Underlying() { + // Do same for AnyType as for ErrorType. + underlying = types.AnyType + } w.typ(underlying) t := n.Type() diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index f1fb93ad1b..60bb7b46fa 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -119,6 +119,8 @@ var ( ErrorType *Type // Predeclared comparable interface type. ComparableType *Type + // Predeclared any interface type. + AnyType *Type // Types to represent untyped string and boolean constants. UntypedString = newType(TSTRING) diff --git a/src/cmd/compile/internal/types/universe.go b/src/cmd/compile/internal/types/universe.go index 1291b0e0fa..8fa4b7cd20 100644 --- a/src/cmd/compile/internal/types/universe.go +++ b/src/cmd/compile/internal/types/universe.go @@ -107,6 +107,14 @@ func InitTypes(defTypeName func(sym *Sym, typ *Type) Object) { ComparableType.SetUnderlying(makeComparableInterface()) ResumeCheckSize() + // any type (interface) + if base.Flag.G > 0 { + DeferCheckSize() + AnyType = defBasic(TFORW, BuiltinPkg, "any") + AnyType.SetUnderlying(NewInterface(NoPkg, []*Field{})) + ResumeCheckSize() + } + Types[TUNSAFEPTR] = defBasic(TUNSAFEPTR, UnsafePkg, "Pointer") Types[TBLANK] = newType(TBLANK) diff --git a/test/typeparam/issue47966.go b/test/typeparam/issue47966.go new file mode 100644 index 0000000000..f431f7fc74 --- /dev/null +++ b/test/typeparam/issue47966.go @@ -0,0 +1,9 @@ +// compile -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type C comparable diff --git a/test/typeparam/subdict.go b/test/typeparam/subdict.go index b4e84baf8a..c519b4f51c 100644 --- a/test/typeparam/subdict.go +++ b/test/typeparam/subdict.go @@ -14,7 +14,9 @@ import ( "fmt" ) -type value[T comparable] struct { +type C comparable + +type value[T C] struct { val T } -- GitLab From 5afa5554289c91706ef6244b24ccf91181123b68 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sat, 28 Aug 2021 14:55:10 +0700 Subject: [PATCH 0890/2500] cmd/compile: fix wrong check for b.Controls in isBlockMultiValueExit b.Controls has type [2]*Value, thus len(b.Controls) > 0 is always true. The right check should be b.Controls[0] != nil, though, this is also always true, since when we always set control value for BlockRet and BlockRetJmp when state.exit is called. Though checkFunc also checks for nil control value of ret/retjmp, but it happens later after expand_calls pass, so better to be defensive here, just in case. Change-Id: Ie4a292a3494dfbf5e6d872cde498703023b84d00 Reviewed-on: https://go-review.googlesource.com/c/go/+/345433 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/ssa/expand_calls.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/ssa/expand_calls.go b/src/cmd/compile/internal/ssa/expand_calls.go index eba36ce33b..a1ce27cc4a 100644 --- a/src/cmd/compile/internal/ssa/expand_calls.go +++ b/src/cmd/compile/internal/ssa/expand_calls.go @@ -24,7 +24,7 @@ type selKey struct { type Abi1RO uint8 // An offset within a parameter's slice of register indices, for abi1. func isBlockMultiValueExit(b *Block) bool { - return (b.Kind == BlockRet || b.Kind == BlockRetJmp) && len(b.Controls) > 0 && b.Controls[0].Op == OpMakeResult + return (b.Kind == BlockRet || b.Kind == BlockRetJmp) && b.Controls[0] != nil && b.Controls[0].Op == OpMakeResult } func badVal(s string, v *Value) error { -- GitLab From 6df3aac4ae8d0ca695751ef828a500cd438b00f9 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sat, 28 Aug 2021 15:27:55 +0700 Subject: [PATCH 0891/2500] cmd/compile: fix offset-generator for storeOneLoad storeOneLoad decompose Load that is then stored, the offset value must be created on the same block with the Load to be dominated, otherwise, it's unsafe if one does not dominate the other. Fixes #48026 Change-Id: Iee5e6c5d3e1b09862afe4e65f7bcd771b4c57367 Reviewed-on: https://go-review.googlesource.com/c/go/+/345434 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/ssa/expand_calls.go | 2 +- test/fixedbugs/issue48026.go | 26 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 test/fixedbugs/issue48026.go diff --git a/src/cmd/compile/internal/ssa/expand_calls.go b/src/cmd/compile/internal/ssa/expand_calls.go index a1ce27cc4a..b37d3b8c9c 100644 --- a/src/cmd/compile/internal/ssa/expand_calls.go +++ b/src/cmd/compile/internal/ssa/expand_calls.go @@ -852,7 +852,7 @@ func storeOneArg(x *expandState, pos src.XPos, b *Block, locs []*LocalSlot, suff // storeOneLoad creates a decomposed (one step) load that is then stored. func storeOneLoad(x *expandState, pos src.XPos, b *Block, source, mem *Value, t *types.Type, offArg, offStore int64, loadRegOffset Abi1RO, storeRc registerCursor) *Value { - from := x.offsetFrom(b, source.Args[0], offArg, types.NewPtr(t)) + from := x.offsetFrom(source.Block, source.Args[0], offArg, types.NewPtr(t)) w := source.Block.NewValue2(source.Pos, OpLoad, t, from, mem) return x.storeArgOrLoad(pos, b, w, mem, t, offStore, loadRegOffset, storeRc) } diff --git a/test/fixedbugs/issue48026.go b/test/fixedbugs/issue48026.go new file mode 100644 index 0000000000..a693d33b45 --- /dev/null +++ b/test/fixedbugs/issue48026.go @@ -0,0 +1,26 @@ +// compile -d=ssa/check/on + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +var i int + +type t struct { + a, b, c, d, e int +} + +func f(p t, q int) int { + var a, b, c, d, e, f, g int + var h, i, j, k, l, m int + _, _, _, _, _, _, _ = a, b, c, d, e, f, g + _, _, _, _, _, _ = h, i, j, k, l, m + return 0 +} + +func g() int { + var v t + return f(v, 1< Date: Wed, 23 Jun 2021 20:01:33 -0700 Subject: [PATCH 0892/2500] os/user: simplify skipping listGroups test This is not implemented on AIX and Illumos, and we already have a mechanism to skip the test case -- let's use it. Change-Id: Idb1cc2d716cf6d0731e93dfc3aa7853b9edec41f Reviewed-on: https://go-review.googlesource.com/c/go/+/330752 Reviewed-by: Tobias Klauser Reviewed-by: Ian Lance Taylor Run-TryBot: Tobias Klauser TryBot-Result: Go Bot --- src/os/user/listgroups_aix.go | 6 ++++++ src/os/user/listgroups_illumos.go | 6 ++++++ src/os/user/user_test.go | 7 ------- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/os/user/listgroups_aix.go b/src/os/user/listgroups_aix.go index d2fdfdc6b1..fbc1deb03f 100644 --- a/src/os/user/listgroups_aix.go +++ b/src/os/user/listgroups_aix.go @@ -9,6 +9,12 @@ package user import "fmt" +// Not implemented on AIX, see golang.org/issue/30563. + +func init() { + groupListImplemented = false +} + func listGroups(u *User) ([]string, error) { return nil, fmt.Errorf("user: list groups for %s: not supported on AIX", u.Username) } diff --git a/src/os/user/listgroups_illumos.go b/src/os/user/listgroups_illumos.go index d25e0339b9..e783b26080 100644 --- a/src/os/user/listgroups_illumos.go +++ b/src/os/user/listgroups_illumos.go @@ -13,6 +13,12 @@ package user import "fmt" +// Not implemented on illumos, see golang.org/issue/14709. + +func init() { + groupListImplemented = false +} + func listGroups(u *User) ([]string, error) { return nil, fmt.Errorf("user: list groups for %s: not supported on illumos", u.Username) } diff --git a/src/os/user/user_test.go b/src/os/user/user_test.go index d8a465edac..80251749a7 100644 --- a/src/os/user/user_test.go +++ b/src/os/user/user_test.go @@ -5,7 +5,6 @@ package user import ( - "runtime" "testing" ) @@ -128,12 +127,6 @@ func checkGroupList(t *testing.T) { func TestGroupIds(t *testing.T) { checkGroupList(t) - if runtime.GOOS == "aix" { - t.Skip("skipping GroupIds, see golang.org/issue/30563") - } - if runtime.GOOS == "illumos" { - t.Skip("skipping GroupIds, see golang.org/issue/14709") - } user, err := Current() if err != nil { t.Fatalf("Current(): %v", err) -- GitLab From f29abccd8aaadf0297da3947909feca3c8ec31c9 Mon Sep 17 00:00:00 2001 From: wdvxdr Date: Thu, 26 Aug 2021 16:20:33 +0800 Subject: [PATCH 0893/2500] test: add test cases for issue47892. This issue has been fixed in https://golang.org/cl/345411 Fixes: #47892 Change-Id: I13dd3814650913da065e5f24a0c61d30adb0633a Reviewed-on: https://go-review.googlesource.com/c/go/+/345229 Reviewed-by: Dan Scales Trust: Dan Scales Trust: Keith Randall Trust: Alberto Donizetti Run-TryBot: Alberto Donizetti TryBot-Result: Go Bot --- test/typeparam/issue47892.dir/a.go | 17 +++++++++++++++ test/typeparam/issue47892.dir/main.go | 21 +++++++++++++++++++ test/typeparam/issue47892.go | 7 +++++++ test/typeparam/issue47892b.dir/a.go | 29 ++++++++++++++++++++++++++ test/typeparam/issue47892b.dir/main.go | 17 +++++++++++++++ test/typeparam/issue47892b.go | 7 +++++++ 6 files changed, 98 insertions(+) create mode 100644 test/typeparam/issue47892.dir/a.go create mode 100644 test/typeparam/issue47892.dir/main.go create mode 100644 test/typeparam/issue47892.go create mode 100644 test/typeparam/issue47892b.dir/a.go create mode 100644 test/typeparam/issue47892b.dir/main.go create mode 100644 test/typeparam/issue47892b.go diff --git a/test/typeparam/issue47892.dir/a.go b/test/typeparam/issue47892.dir/a.go new file mode 100644 index 0000000000..b63d604eeb --- /dev/null +++ b/test/typeparam/issue47892.dir/a.go @@ -0,0 +1,17 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type Index[T any] interface { + G() T +} + +type I1[T any] struct { + a T +} + +func (i *I1[T]) G() T { + return i.a +} diff --git a/test/typeparam/issue47892.dir/main.go b/test/typeparam/issue47892.dir/main.go new file mode 100644 index 0000000000..bd610d4ee6 --- /dev/null +++ b/test/typeparam/issue47892.dir/main.go @@ -0,0 +1,21 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "a" + +type Model[T any] struct { + index a.Index[T] +} + +func NewModel[T any](index a.Index[T]) Model[T] { + return Model[T]{ + index: index, + } +} + +func main() { + _ = NewModel[int]((*a.I1[int])(nil)) +} diff --git a/test/typeparam/issue47892.go b/test/typeparam/issue47892.go new file mode 100644 index 0000000000..572f680d3d --- /dev/null +++ b/test/typeparam/issue47892.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored \ No newline at end of file diff --git a/test/typeparam/issue47892b.dir/a.go b/test/typeparam/issue47892b.dir/a.go new file mode 100644 index 0000000000..5adb492578 --- /dev/null +++ b/test/typeparam/issue47892b.dir/a.go @@ -0,0 +1,29 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type T struct{ p *int64 } + +type i struct{} + +func G() *T { return &T{nil} } + +func (j i) F(a, b *T) *T { + n := *a.p + *b.p + return &T{&n} +} + +func (j i) G() *T { + return &T{} +} + +type I[Idx any] interface { + G() Idx + F(a, b Idx) Idx +} + +func Gen() I[*T] { + return i{} +} diff --git a/test/typeparam/issue47892b.dir/main.go b/test/typeparam/issue47892b.dir/main.go new file mode 100644 index 0000000000..70df4408af --- /dev/null +++ b/test/typeparam/issue47892b.dir/main.go @@ -0,0 +1,17 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "a" + +type S[Idx any] struct { + A string + B Idx +} + +type O[Idx any] struct { + A int + B a.I[Idx] +} diff --git a/test/typeparam/issue47892b.go b/test/typeparam/issue47892b.go new file mode 100644 index 0000000000..87b4ff46c1 --- /dev/null +++ b/test/typeparam/issue47892b.go @@ -0,0 +1,7 @@ +// compiledir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From a29d9aad7a4543498ff505b0a36d10c0f0153d3f Mon Sep 17 00:00:00 2001 From: citizen233 Date: Sun, 29 Aug 2021 21:45:35 +0800 Subject: [PATCH 0894/2500] test/typeparam/sliceimp.dir: fix typo in a.go Fixing a typo, comparision -> comparison Change-Id: I369f95c251f155bc6a9a6b86077bcf1ab245fc3f Reviewed-on: https://go-review.googlesource.com/c/go/+/345950 Reviewed-by: Alberto Donizetti Reviewed-by: Keith Randall Trust: Alberto Donizetti Trust: Keith Randall --- test/typeparam/sliceimp.dir/a.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/typeparam/sliceimp.dir/a.go b/test/typeparam/sliceimp.dir/a.go index da12e9f9fc..dbcfae8931 100644 --- a/test/typeparam/sliceimp.dir/a.go +++ b/test/typeparam/sliceimp.dir/a.go @@ -45,7 +45,7 @@ func Equal[Elem comparable](s1, s2 []Elem) bool { return true } -// EqualFn reports whether two slices are equal using a comparision +// EqualFn reports whether two slices are equal using a comparison // function on each element. func EqualFn[Elem any](s1, s2 []Elem, eq func(Elem, Elem) bool) bool { if len(s1) != len(s2) { -- GitLab From 21d0b306afc204d9b523a89914b6440dcc6d73cc Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 27 Aug 2021 22:53:48 -0700 Subject: [PATCH 0895/2500] cmd/compile/internal/types: remove unused Tie method Once upon a time, this was used by package walk to compute the "conv[TIE]2[TIE]" function names, etc.; but it seems like those callers have all changed to directly specializing on IsInterface and IsEmptyInterface instead. Change-Id: I629cdf076a09e7255ae293b8f879db0cdcf4de5b Reviewed-on: https://go-review.googlesource.com/c/go/+/345793 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/types/type.go | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 60bb7b46fa..c510a705f2 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -1680,19 +1680,6 @@ func (t *Type) HasPointers() bool { return PtrDataSize(t) > 0 } -// Tie returns 'T' if t is a concrete type, -// 'I' if t is an interface type, and 'E' if t is an empty interface type. -// It is used to build calls to the conv* and assert* runtime routines. -func (t *Type) Tie() byte { - if t.IsEmptyInterface() { - return 'E' - } - if t.IsInterface() { - return 'I' - } - return 'T' -} - var recvType *Type // FakeRecvType returns the singleton type used for interface method receivers. -- GitLab From 56c3856d529d72e280ad6b185f7927657de86c37 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 27 Aug 2021 22:59:26 -0700 Subject: [PATCH 0896/2500] cmd/compile/internal/types: unexport Type.widthCalculated It's not needed outside of package types anymore. Change-Id: Idadf915fc254920ca778b5f5f8de8a1300da1953 Reviewed-on: https://go-review.googlesource.com/c/go/+/345794 Trust: Matthew Dempsky Reviewed-by: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot --- src/cmd/compile/internal/types/size.go | 6 +++++- src/cmd/compile/internal/types/type.go | 6 +----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/types/size.go b/src/cmd/compile/internal/types/size.go index a47a26da74..0f3db06c1d 100644 --- a/src/cmd/compile/internal/types/size.go +++ b/src/cmd/compile/internal/types/size.go @@ -357,7 +357,7 @@ func CalcSize(t *Type) { return } - if t.WidthCalculated() { + if t.widthCalculated() { return } @@ -570,6 +570,10 @@ func RecalcSize(t *Type) { CalcSize(t) } +func (t *Type) widthCalculated() bool { + return t.align > 0 +} + // when a type's width should be known, we call CheckSize // to compute it. during a declaration like // diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index c510a705f2..8fb8fb377f 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -1060,7 +1060,7 @@ func (t *Type) SetFields(fields []*Field) { // Rather than try to track and invalidate those, // enforce that SetFields cannot be called once // t's width has been calculated. - if t.WidthCalculated() { + if t.widthCalculated() { base.Fatalf("SetFields of %v: width previously calculated", t) } t.wantEtype(TSTRUCT) @@ -1084,10 +1084,6 @@ func (t *Type) SetInterface(methods []*Field) { t.Methods().Set(methods) } -func (t *Type) WidthCalculated() bool { - return t.align > 0 -} - // ArgWidth returns the total aligned argument size for a function. // It includes the receiver, parameters, and results. func (t *Type) ArgWidth() int64 { -- GitLab From 7b38dd8e255710721b7d843cddbbb46f50267aa5 Mon Sep 17 00:00:00 2001 From: Koichi Shiraishi Date: Thu, 29 Jul 2021 04:22:47 +0900 Subject: [PATCH 0897/2500] runtime: remove unnecesarry newline on freeStackSpans Change-Id: I16a3241d8818c67922ddbf7830b8c2c5f317e1a7 Reviewed-on: https://go-review.googlesource.com/c/go/+/338209 Reviewed-by: Austin Clements Run-TryBot: Austin Clements Trust: Keith Randall --- src/runtime/stack.go | 1 - 1 file changed, 1 deletion(-) diff --git a/src/runtime/stack.go b/src/runtime/stack.go index 54ad66dca2..368ad6efa4 100644 --- a/src/runtime/stack.go +++ b/src/runtime/stack.go @@ -1198,7 +1198,6 @@ func shrinkstack(gp *g) { // freeStackSpans frees unused stack spans at the end of GC. func freeStackSpans() { - // Scan stack pools for empty stack spans. for order := range stackpool { lock(&stackpool[order].item.mu) -- GitLab From b602daea1b94a8a578bafdc6ef6336c07fe63300 Mon Sep 17 00:00:00 2001 From: korzhao Date: Mon, 30 Aug 2021 17:09:51 +0800 Subject: [PATCH 0898/2500] cmd/compile: fix error when revcType is ptr in selectorExpr Fixes #48056 Change-Id: I13ca4caadbabf02084f66ab28b4cf0c4a3705370 Reviewed-on: https://go-review.googlesource.com/c/go/+/346049 Reviewed-by: Dan Scales Trust: Dan Scales Trust: Keith Randall Run-TryBot: Dan Scales TryBot-Result: Go Bot --- src/cmd/compile/internal/noder/expr.go | 2 +- test/typeparam/issue48056.go | 27 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 test/typeparam/issue48056.go diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 58637dca39..0e5257d7cf 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -270,7 +270,7 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto if types2.AsInterface(recvType.Underlying()) != nil { fieldType := n.X.Type() for _, ix := range index[:len(index)-1] { - fieldType = fieldType.Field(ix).Type + fieldType = deref(fieldType).Field(ix).Type } if fieldType.Kind() == types.TTYPEPARAM { n.Selection = fieldType.Bound().AllMethods().Index(last) diff --git a/test/typeparam/issue48056.go b/test/typeparam/issue48056.go new file mode 100644 index 0000000000..8d1c3eff64 --- /dev/null +++ b/test/typeparam/issue48056.go @@ -0,0 +1,27 @@ +// compile -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type B[T any] interface { + Work() +} +type BImpl[T any] struct{} + +func (b *BImpl[T]) Work() { +} + +type A[T any] struct { + B[T] +} + +func f[T any]() { + s := &A[T]{ + &BImpl[T]{}, + } + // golang.org/issue/48056 + s.Work() +} -- GitLab From bdc1bef8a05d4524160d56a027f110257323033d Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Fri, 20 Aug 2021 14:38:09 -0700 Subject: [PATCH 0899/2500] cmd/go: ensure 'go get -u' can upgrade pruned (1.17+) modules Fixes #47768 Change-Id: I981a31ba4ff716570ac4c6f35b289fa480faa5bb Reviewed-on: https://go-review.googlesource.com/c/go/+/343879 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Michael Matloob Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/modload/edit.go | 1 + .../script/mod_get_lazy_upgrade_lazy.txt | 68 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 src/cmd/go/testdata/script/mod_get_lazy_upgrade_lazy.txt diff --git a/src/cmd/go/internal/modload/edit.go b/src/cmd/go/internal/modload/edit.go index 796721c90c..efc590c857 100644 --- a/src/cmd/go/internal/modload/edit.go +++ b/src/cmd/go/internal/modload/edit.go @@ -237,6 +237,7 @@ func raiseLimitsForUpgrades(ctx context.Context, maxVersion map[string]string, d continue } + allow(m) for _, r := range summary.require { allow(r) } diff --git a/src/cmd/go/testdata/script/mod_get_lazy_upgrade_lazy.txt b/src/cmd/go/testdata/script/mod_get_lazy_upgrade_lazy.txt new file mode 100644 index 0000000000..3dae383de1 --- /dev/null +++ b/src/cmd/go/testdata/script/mod_get_lazy_upgrade_lazy.txt @@ -0,0 +1,68 @@ +# Check that 'go get -u' will upgrade a dependency (direct or indirect) +# when the main module and the dependency are both lazy. +# Verifies #47768. + +# Check that go.mod is tidy, and an upgrade is available. +cp go.mod go.mod.orig +go mod tidy +cmp go.mod go.mod.orig + +go list -m -u example.com/lazyupgrade +stdout '^example.com/lazyupgrade v0.1.0 \[v0.1.1\] => ./lazyupgrade@v0.1.0$' + +# 'go get -u' on a package that directly imports the dependency should upgrade. +go get -u ./usedirect +go list -m example.com/lazyupgrade +stdout '^example.com/lazyupgrade v0.1.1 => ./lazyupgrade@v0.1.1$' +cp go.mod.orig go.mod + +# 'go get -u' on a package that indirectly imports the dependency should upgrade. +go get -u ./useindirect +go list -m example.com/lazyupgrade +stdout '^example.com/lazyupgrade v0.1.1 => ./lazyupgrade@v0.1.1$' + +-- go.mod -- +module use + +go 1.17 + +require ( + direct v0.0.0 + example.com/lazyupgrade v0.1.0 +) + +replace ( + direct => ./direct + example.com/lazyupgrade v0.1.0 => ./lazyupgrade@v0.1.0 + example.com/lazyupgrade v0.1.1 => ./lazyupgrade@v0.1.1 +) +-- usedirect/usedirect.go -- +package use + +import _ "example.com/lazyupgrade" +-- useindirect/useindirect.go -- +package use + +import _ "direct" +-- direct/go.mod -- +module direct + +go 1.17 + +require example.com/lazyupgrade v0.1.0 +-- direct/direct.go -- +package direct + +import _ "example.com/lazyupgrade" +-- lazyupgrade@v0.1.0/go.mod -- +module example.com/lazyupgrade + +go 1.17 +-- lazyupgrade@v0.1.0/lazyupgrade.go -- +package lazyupgrade +-- lazyupgrade@v0.1.1/go.mod -- +module example.com/lazyupgrade + +go 1.17 +-- lazyupgrade@v0.1.1/lazyupgrade.go -- +package lazyupgrade -- GitLab From 9da7ccab5888e15b675584b5b0eeb63e48baafa8 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 27 Aug 2021 14:26:31 -0400 Subject: [PATCH 0900/2500] cmd/go/internal/modload: remove go117EnableLazyLoading Updates #36460 Change-Id: I19f375f58f118e83a2615a29bbbb3853f059f0bb Reviewed-on: https://go-review.googlesource.com/c/go/+/345391 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/modload/init.go | 21 ++++++++++----------- src/cmd/go/internal/modload/modfile.go | 8 -------- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index b845842a7f..0843e1ad4d 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -709,17 +709,16 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { // cfg.CmdName directly here. if cfg.BuildMod == "mod" && cfg.CmdName != "mod graph" && cfg.CmdName != "mod why" { addGoStmt(MainModules.ModFile(mainModule), mainModule, LatestGoVersion()) - if go117EnableLazyLoading { - // We need to add a 'go' version to the go.mod file, but we must assume - // that its existing contents match something between Go 1.11 and 1.16. - // Go 1.11 through 1.16 have eager requirements, but the latest Go - // version uses lazy requirements instead — so we need to cnvert the - // requirements to be lazy. - var err error - rs, err = convertDepth(ctx, rs, lazy) - if err != nil { - base.Fatalf("go: %v", err) - } + + // We need to add a 'go' version to the go.mod file, but we must assume + // that its existing contents match something between Go 1.11 and 1.16. + // Go 1.11 through 1.16 have eager requirements, but the latest Go + // version uses lazy requirements instead — so we need to convert the + // requirements to be lazy. + var err error + rs, err = convertDepth(ctx, rs, lazy) + if err != nil { + base.Fatalf("go: %v", err) } } else { rawGoVersion.Store(mainModule, modFileGoVersion(MainModules.ModFile(mainModule))) diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index 463869910c..2606fe4425 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -45,11 +45,6 @@ const ( ) const ( - // go117EnableLazyLoading toggles whether lazy-loading code paths should be - // active. It will be removed once the lazy loading implementation is stable - // and well-tested. - go117EnableLazyLoading = true - // go1117LazyTODO is a constant that exists only until lazy loading is // implemented. Its use indicates a condition that will need to change if the // main module is lazy. @@ -103,9 +98,6 @@ const ( ) func modDepthFromGoVersion(goVersion string) modDepth { - if !go117EnableLazyLoading { - return eager - } if semver.Compare("v"+goVersion, lazyLoadingVersionV) < 0 { return eager } -- GitLab From af9009a989d69d3f5560dc7bd8ccf1574ea6a519 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 27 Aug 2021 15:08:02 -0400 Subject: [PATCH 0901/2500] cmd/go/internal/modload: remove go117LazyTODO Replace the last remaining use with a reference to #48024. Change-Id: I699711b4e42abe9c6d3512c28d2ee81a84e3263a Reviewed-on: https://go-review.googlesource.com/c/go/+/345392 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/modload/edit.go | 10 ++++------ src/cmd/go/internal/modload/modfile.go | 7 ------- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/src/cmd/go/internal/modload/edit.go b/src/cmd/go/internal/modload/edit.go index efc590c857..12a23468af 100644 --- a/src/cmd/go/internal/modload/edit.go +++ b/src/cmd/go/internal/modload/edit.go @@ -253,12 +253,10 @@ func raiseLimitsForUpgrades(ctx context.Context, maxVersion map[string]string, d // common versions among multiple upgrades. upgradeGraph, err := readModGraph(ctx, eager, eagerUpgrades) if err != nil { - if go117LazyTODO { - // Compute the requirement path from a module path in tryUpgrade to the - // error, and the requirement path (if any) from rs.rootModules to the - // tryUpgrade module path. Return a *mvs.BuildListError showing the - // concatenation of the paths (with an upgrade in the middle). - } + // Compute the requirement path from a module path in tryUpgrade to the + // error, and the requirement path (if any) from rs.rootModules to the + // tryUpgrade module path. Return a *mvs.BuildListError showing the + // concatenation of the paths (with an upgrade in the middle). return err } diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index 2606fe4425..d2b13fb89f 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -44,13 +44,6 @@ const ( separateIndirectVersionV = "v1.17" ) -const ( - // go1117LazyTODO is a constant that exists only until lazy loading is - // implemented. Its use indicates a condition that will need to change if the - // main module is lazy. - go117LazyTODO = false -) - // modFileGoVersion returns the (non-empty) Go version at which the requirements // in modFile are interpreted, or the latest Go version if modFile is nil. func modFileGoVersion(modFile *modfile.File) string { -- GitLab From 61120c634cde434b78d9fcfe53a53aade58ef6be Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 27 Aug 2021 15:07:15 -0400 Subject: [PATCH 0902/2500] cmd/go/internal/modload: use "pruned" instead of "lazy" to describe pruned module graphs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The level of support for pruning — not the lazy/eager loading behavior — is the more fundamental property, and what matters in terms of what invariants we need to maintain. If the main module supports pruned module graphs we load its dependencies lazily, and if it does not support pruned module graphs we load its dependencies eagerly. However, in principle we could also load the module graph lazily even in modules that do not support graph pruning — we would just be more likely to overlook inconsistent requirements introduced by hand-edits or bad VCS merges to the go.mod file. (After this change, a “lazy” module is just one in which we happen not to have loaded the module graph, and an “eager” one is one in which we happen to load the module graph more aggressively.) Updates #36460 For #47397 Change-Id: I0d2ffd21acc913f72ff56b59a6bdc539ebc3d377 Reviewed-on: https://go-review.googlesource.com/c/go/+/345393 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/modload/build.go | 2 +- src/cmd/go/internal/modload/buildlist.go | 217 +++++++++++---------- src/cmd/go/internal/modload/edit.go | 114 +++++------ src/cmd/go/internal/modload/import_test.go | 2 +- src/cmd/go/internal/modload/init.go | 26 +-- src/cmd/go/internal/modload/list.go | 4 +- src/cmd/go/internal/modload/load.go | 83 ++++---- src/cmd/go/internal/modload/modfile.go | 39 ++-- 8 files changed, 257 insertions(+), 230 deletions(-) diff --git a/src/cmd/go/internal/modload/build.go b/src/cmd/go/internal/modload/build.go index 0efd84123a..8a9792089b 100644 --- a/src/cmd/go/internal/modload/build.go +++ b/src/cmd/go/internal/modload/build.go @@ -80,7 +80,7 @@ func ModuleInfo(ctx context.Context, path string) *modinfo.ModulePublic { v string ok bool ) - if rs.depth == lazy { + if rs.pruning == pruned { v, ok = rs.rootSelected(path) } if !ok { diff --git a/src/cmd/go/internal/modload/buildlist.go b/src/cmd/go/internal/modload/buildlist.go index 94414278ab..777e29af10 100644 --- a/src/cmd/go/internal/modload/buildlist.go +++ b/src/cmd/go/internal/modload/buildlist.go @@ -30,14 +30,15 @@ func capVersionSlice(s []module.Version) []module.Version { // A Requirements represents a logically-immutable set of root module requirements. type Requirements struct { - // depth is the depth at which the requirement graph is computed. + // pruning is the pruning at which the requirement graph is computed. // - // If eager, the graph includes all transitive requirements regardless of depth. + // If unpruned, the graph includes all transitive requirements regardless + // of whether the requiring module supports pruning. // - // If lazy, the graph includes only the root modules, the explicit + // If pruned, the graph includes only the root modules, the explicit // requirements of those root modules, and the transitive requirements of only - // the *non-lazy* root modules. - depth modDepth + // the root modules that do not support pruning. + pruning modPruning // rootModules is the set of module versions explicitly required by the main // modules, sorted and capped to length. It may contain duplicates, and may @@ -97,7 +98,7 @@ var requirements *Requirements // // If vendoring is in effect, the caller must invoke initVendor on the returned // *Requirements before any other method. -func newRequirements(depth modDepth, rootModules []module.Version, direct map[string]bool) *Requirements { +func newRequirements(pruning modPruning, rootModules []module.Version, direct map[string]bool) *Requirements { for i, m := range rootModules { if m.Version == "" && MainModules.Contains(m.Path) { panic(fmt.Sprintf("newRequirements called with untrimmed build list: rootModules[%v] is a main module", i)) @@ -114,7 +115,7 @@ func newRequirements(depth modDepth, rootModules []module.Version, direct map[st } rs := &Requirements{ - depth: depth, + pruning: pruning, rootModules: capVersionSlice(rootModules), maxRootVersion: make(map[string]string, len(rootModules)), direct: direct, @@ -143,10 +144,10 @@ func (rs *Requirements) initVendor(vendorList []module.Version) { } mainModule := MainModules.Versions()[0] - if rs.depth == lazy { - // The roots of a lazy module should already include every module in the - // vendor list, because the vendored modules are the same as those - // maintained as roots by the lazy loading “import invariant”. + if rs.pruning == pruned { + // The roots of a pruned module should already include every module in the + // vendor list, because the vendored modules are the same as those needed + // for graph pruning. // // Just to be sure, we'll double-check that here. inconsistent := false @@ -161,8 +162,8 @@ func (rs *Requirements) initVendor(vendorList []module.Version) { } // Now we can treat the rest of the module graph as effectively “pruned - // out”, like a more aggressive version of lazy loading: in vendor mode, - // the root requirements *are* the complete module graph. + // out”, as though we are viewing the main module from outside: in vendor + // mode, the root requirements *are* the complete module graph. mg.g.Require(mainModule, rs.rootModules) } else { // The transitive requirements of the main module are not in general available @@ -219,7 +220,7 @@ func (rs *Requirements) hasRedundantRoot() bool { // returns a non-nil error of type *mvs.BuildListError. func (rs *Requirements) Graph(ctx context.Context) (*ModuleGraph, error) { rs.graphOnce.Do(func() { - mg, mgErr := readModGraph(ctx, rs.depth, rs.rootModules) + mg, mgErr := readModGraph(ctx, rs.pruning, rs.rootModules) rs.graph.Store(cachedGraph{mg, mgErr}) }) cached := rs.graph.Load().(cachedGraph) @@ -259,8 +260,16 @@ var readModGraphDebugOnce sync.Once // // Unlike LoadModGraph, readModGraph does not attempt to diagnose or update // inconsistent roots. -func readModGraph(ctx context.Context, depth modDepth, roots []module.Version) (*ModuleGraph, error) { - if depth == lazy { +func readModGraph(ctx context.Context, pruning modPruning, roots []module.Version) (*ModuleGraph, error) { + if pruning == pruned { + // Enable diagnostics for lazy module loading + // (https://golang.org/ref/mod#lazy-loading) only if the module graph is + // pruned. + // + // In unpruned modules,we load the module graph much more aggressively (in + // order to detect inconsistencies that wouldn't be feasible to spot-check), + // so it wouldn't be useful to log when that occurs (because it happens in + // normal operation all the time). readModGraphDebugOnce.Do(func() { for _, f := range strings.Split(os.Getenv("GODEBUG"), ",") { switch f { @@ -292,13 +301,13 @@ func readModGraph(ctx context.Context, depth modDepth, roots []module.Version) ( } var ( - loadQueue = par.NewQueue(runtime.GOMAXPROCS(0)) - loadingEager sync.Map // module.Version → nil; the set of modules that have been or are being loaded via eager roots + loadQueue = par.NewQueue(runtime.GOMAXPROCS(0)) + loadingUnpruned sync.Map // module.Version → nil; the set of modules that have been or are being loaded via roots that do not support pruning ) // loadOne synchronously loads the explicit requirements for module m. // It does not load the transitive requirements of m even if the go version in - // m's go.mod file indicates eager loading. + // m's go.mod file indicates that it supports graph pruning. loadOne := func(m module.Version) (*modFileSummary, error) { cached := mg.loadCache.Do(m, func() interface{} { summary, err := goModSummary(m) @@ -317,15 +326,15 @@ func readModGraph(ctx context.Context, depth modDepth, roots []module.Version) ( return cached.summary, cached.err } - var enqueue func(m module.Version, depth modDepth) - enqueue = func(m module.Version, depth modDepth) { + var enqueue func(m module.Version, pruning modPruning) + enqueue = func(m module.Version, pruning modPruning) { if m.Version == "none" { return } - if depth == eager { - if _, dup := loadingEager.LoadOrStore(m, nil); dup { - // m has already been enqueued for loading. Since eager loading may + if pruning == unpruned { + if _, dup := loadingUnpruned.LoadOrStore(m, nil); dup { + // m has already been enqueued for loading. Since unpruned loading may // follow cycles in the the requirement graph, we need to return early // to avoid making the load queue infinitely long. return @@ -338,21 +347,21 @@ func readModGraph(ctx context.Context, depth modDepth, roots []module.Version) ( return // findError will report the error later. } - // If the version in m's go.mod file implies eager loading, then we cannot - // assume that the explicit requirements of m (added by loadOne) are - // sufficient to build the packages it contains. We must load its full + // If the version in m's go.mod file does not support pruning, then we + // cannot assume that the explicit requirements of m (added by loadOne) + // are sufficient to build the packages it contains. We must load its full // transitive dependency graph to be sure that we see all relevant // dependencies. - if depth == eager || summary.depth == eager { + if pruning == unpruned || summary.pruning == unpruned { for _, r := range summary.require { - enqueue(r, eager) + enqueue(r, unpruned) } } }) } for _, m := range roots { - enqueue(m, depth) + enqueue(m, pruning) } <-loadQueue.Idle() @@ -363,8 +372,7 @@ func readModGraph(ctx context.Context, depth modDepth, roots []module.Version) ( } // RequiredBy returns the dependencies required by module m in the graph, -// or ok=false if module m's dependencies are not relevant (such as if they -// are pruned out by lazy loading). +// or ok=false if module m's dependencies are pruned out. // // The caller must not modify the returned slice, but may safely append to it // and may rely on it not to be modified. @@ -441,12 +449,12 @@ func LoadModGraph(ctx context.Context, goVersion string) *ModuleGraph { rs := LoadModFile(ctx) if goVersion != "" { - depth := modDepthFromGoVersion(goVersion) - if depth == eager && rs.depth != eager { + pruning := pruningForGoVersion(goVersion) + if pruning == unpruned && rs.pruning != unpruned { // Use newRequirements instead of convertDepth because convertDepth // also updates roots; here, we want to report the unmodified roots // even though they may seem inconsistent. - rs = newRequirements(eager, rs.rootModules, rs.direct) + rs = newRequirements(unpruned, rs.rootModules, rs.direct) } mg, err := rs.Graph(ctx) @@ -469,9 +477,8 @@ func LoadModGraph(ctx context.Context, goVersion string) *ModuleGraph { // // If the complete graph reveals that some root of rs is not actually the // selected version of its path, expandGraph computes a new set of roots that -// are consistent. (When lazy loading is implemented, this may result in -// upgrades to other modules due to requirements that were previously pruned -// out.) +// are consistent. (With a pruned module graph, this may result in upgrades to +// other modules due to requirements that were previously pruned out.) // // expandGraph returns the updated roots, along with the module graph loaded // from those roots and any error encountered while loading that graph. @@ -487,9 +494,9 @@ func expandGraph(ctx context.Context, rs *Requirements) (*Requirements, *ModuleG if !mg.allRootsSelected() { // The roots of rs are not consistent with the rest of the graph. Update - // them. In an eager module this is a no-op for the build list as a whole — + // them. In an unpruned module this is a no-op for the build list as a whole — // it just promotes what were previously transitive requirements to be - // roots — but in a lazy module it may pull in previously-irrelevant + // roots — but in a pruned module it may pull in previously-irrelevant // transitive dependencies. newRS, rsErr := updateRoots(ctx, rs.direct, rs, nil, nil, false) @@ -558,24 +565,25 @@ type Conflict struct { // tidyRoots trims the root dependencies to the minimal requirements needed to // both retain the same versions of all packages in pkgs and satisfy the -// lazy loading invariants (if applicable). +// graph-pruning invariants (if applicable). func tidyRoots(ctx context.Context, rs *Requirements, pkgs []*loadPkg) (*Requirements, error) { mainModule := MainModules.mustGetSingleMainModule() - if rs.depth == eager { - return tidyEagerRoots(ctx, mainModule, rs.direct, pkgs) + if rs.pruning == unpruned { + return tidyUnprunedRoots(ctx, mainModule, rs.direct, pkgs) } - return tidyLazyRoots(ctx, mainModule, rs.direct, pkgs) + return tidyPrunedRoots(ctx, mainModule, rs.direct, pkgs) } func updateRoots(ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version, rootsImported bool) (*Requirements, error) { - if rs.depth == eager { - return updateEagerRoots(ctx, direct, rs, add) + if rs.pruning == unpruned { + return updateUnprunedRoots(ctx, direct, rs, add) } - return updateLazyRoots(ctx, direct, rs, pkgs, add, rootsImported) + return updatePrunedRoots(ctx, direct, rs, pkgs, add, rootsImported) } -// tidyLazyRoots returns a minimal set of root requirements that maintains the -// "lazy loading" invariants of the go.mod file for the given packages: +// tidyPrunedRoots returns a minimal set of root requirements that maintains the +// invariants of the go.mod file needed to support graph pruning for the given +// packages: // // 1. For each package marked with pkgInAll, the module path that provided that // package is included as a root. @@ -589,7 +597,7 @@ func updateRoots(ctx context.Context, direct map[string]bool, rs *Requirements, // To ensure that the loading process eventually converges, the caller should // add any needed roots from the tidy root set (without removing existing untidy // roots) until the set of roots has converged. -func tidyLazyRoots(ctx context.Context, mainModule module.Version, direct map[string]bool, pkgs []*loadPkg) (*Requirements, error) { +func tidyPrunedRoots(ctx context.Context, mainModule module.Version, direct map[string]bool, pkgs []*loadPkg) (*Requirements, error) { var ( roots []module.Version pathIncluded = map[string]bool{mainModule.Path: true} @@ -620,7 +628,7 @@ func tidyLazyRoots(ctx context.Context, mainModule module.Version, direct map[st queued[pkg] = true } module.Sort(roots) - tidy := newRequirements(lazy, roots, direct) + tidy := newRequirements(pruned, roots, direct) for len(queue) > 0 { roots = tidy.rootModules @@ -656,7 +664,7 @@ func tidyLazyRoots(ctx context.Context, mainModule module.Version, direct map[st if len(roots) > len(tidy.rootModules) { module.Sort(roots) - tidy = newRequirements(lazy, roots, tidy.direct) + tidy = newRequirements(pruned, roots, tidy.direct) } } @@ -667,8 +675,8 @@ func tidyLazyRoots(ctx context.Context, mainModule module.Version, direct map[st return tidy, nil } -// updateLazyRoots returns a set of root requirements that maintains the “lazy -// loading” invariants of the go.mod file: +// updatePrunedRoots returns a set of root requirements that maintains the +// invariants of the go.mod file needed to support graph pruning: // // 1. The selected version of the module providing each package marked with // either pkgInAll or pkgIsRoot is included as a root. @@ -685,7 +693,7 @@ func tidyLazyRoots(ctx context.Context, mainModule module.Version, direct map[st // The packages in pkgs are assumed to have been loaded from either the roots of // rs or the modules selected in the graph of rs. // -// The above invariants together imply the “lazy loading” invariants for the +// The above invariants together imply the graph-pruning invariants for the // go.mod file: // // 1. (The import invariant.) Every module that provides a package transitively @@ -705,13 +713,13 @@ func tidyLazyRoots(ctx context.Context, mainModule module.Version, direct map[st // it requires explicitly. This invariant is left up to the caller, who must // not load packages from outside the module graph but may add roots to the // graph, but is facilited by (3). If the caller adds roots to the graph in -// order to resolve missing packages, then updateLazyRoots will retain them, +// order to resolve missing packages, then updatePrunedRoots will retain them, // the selected versions of those roots cannot regress, and they will // eventually be written back to the main module's go.mod file. // // (See https://golang.org/design/36460-lazy-module-loading#invariants for more // detail.) -func updateLazyRoots(ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version, rootsImported bool) (*Requirements, error) { +func updatePrunedRoots(ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version, rootsImported bool) (*Requirements, error) { roots := rs.rootModules rootsUpgraded := false @@ -732,11 +740,11 @@ func updateLazyRoots(ctx context.Context, direct map[string]bool, rs *Requiremen // pkg is transitively imported by a package or test in the main module. // We need to promote the module that maintains it to a root: if some // other module depends on the main module, and that other module also - // uses lazy loading, it will expect to find all of our transitive - // dependencies by reading just our go.mod file, not the go.mod files of - // everything we depend on. + // uses a pruned module graph, it will expect to find all of our + // transitive dependencies by reading just our go.mod file, not the go.mod + // files of everything we depend on. // - // (This is the “import invariant” that makes lazy loading possible.) + // (This is the “import invariant” that makes graph pruning possible.) case rootsImported && pkg.flags.has(pkgFromRoot): // pkg is a transitive dependency of some root, and we are treating the @@ -747,17 +755,18 @@ func updateLazyRoots(ctx context.Context, direct map[string]bool, rs *Requiremen // it matches a command-line argument.) We want future invocations of the // 'go' command — such as 'go test' on the same package — to continue to // use the same versions of its dependencies that we are using right now. - // So we need to bring this package's dependencies inside the lazy-loading - // horizon. + // So we need to bring this package's dependencies inside the pruned + // module graph. // // Making the module containing this package a root of the module graph - // does exactly that: if the module containing the package is lazy it - // should satisfy the import invariant itself, so all of its dependencies - // should be in its go.mod file, and if the module containing the package - // is eager then if we make it a root we will load all of its transitive - // dependencies into the module graph. + // does exactly that: if the module containing the package supports graph + // pruning then it should satisfy the import invariant itself, so all of + // its dependencies should be in its go.mod file, and if the module + // containing the package does not support pruning then if we make it a + // root we will load all of its (unpruned) transitive dependencies into + // the module graph. // - // (This is the “argument invariant” of lazy loading, and is important for + // (This is the “argument invariant”, and is important for // reproducibility.) default: @@ -824,14 +833,13 @@ func updateLazyRoots(ctx context.Context, direct map[string]bool, rs *Requiremen // requirements. if mustHaveCompleteRequirements() { // Our changes to the roots may have moved dependencies into or out of - // the lazy-loading horizon, which could in turn change the selected - // versions of other modules. (Unlike for eager modules, for lazy - // modules adding or removing an explicit root is a semantic change, not - // just a cosmetic one.) + // the graph-pruning horizon, which could in turn change the selected + // versions of other modules. (For pruned modules adding or removing an + // explicit root is a semantic change, not just a cosmetic one.) return rs, errGoModDirty } - rs = newRequirements(lazy, roots, direct) + rs = newRequirements(pruned, roots, direct) var err error mg, err = rs.Graph(ctx) if err != nil { @@ -846,7 +854,7 @@ func updateLazyRoots(ctx context.Context, direct map[string]bool, rs *Requiremen if rs.graph.Load() != nil { // We've already loaded the full module graph, which includes the // requirements of all of the root modules — even the transitive - // requirements, if they are eager! + // requirements, if they are unpruned! mg, _ = rs.Graph(ctx) } else if cfg.BuildMod == "vendor" { // We can't spot-check the requirements of other modules because we @@ -925,12 +933,12 @@ func updateLazyRoots(ctx context.Context, direct map[string]bool, rs *Requiremen } } - if rs.depth == lazy && reflect.DeepEqual(roots, rs.rootModules) && reflect.DeepEqual(direct, rs.direct) { - // The root set is unchanged and rs was already lazy, so keep rs to + if rs.pruning == pruned && reflect.DeepEqual(roots, rs.rootModules) && reflect.DeepEqual(direct, rs.direct) { + // The root set is unchanged and rs was already pruned, so keep rs to // preserve its cached ModuleGraph (if any). return rs, nil } - return newRequirements(lazy, roots, direct), nil + return newRequirements(pruned, roots, direct), nil } // spotCheckRoots reports whether the versions of the roots in rs satisfy the @@ -972,10 +980,10 @@ func spotCheckRoots(ctx context.Context, rs *Requirements, mods map[module.Versi return true } -// tidyEagerRoots returns a minimal set of root requirements that maintains the +// tidyUnprunedRoots returns a minimal set of root requirements that maintains the // selected version of every module that provided a package in pkgs, and // includes the selected version of every such module in direct as a root. -func tidyEagerRoots(ctx context.Context, mainModule module.Version, direct map[string]bool, pkgs []*loadPkg) (*Requirements, error) { +func tidyUnprunedRoots(ctx context.Context, mainModule module.Version, direct map[string]bool, pkgs []*loadPkg) (*Requirements, error) { var ( keep []module.Version keptPath = map[string]bool{} @@ -1002,10 +1010,10 @@ func tidyEagerRoots(ctx context.Context, mainModule module.Version, direct map[s if err != nil { return nil, err } - return newRequirements(eager, min, direct), nil + return newRequirements(unpruned, min, direct), nil } -// updateEagerRoots returns a set of root requirements that includes the selected +// updateUnprunedRoots returns a set of root requirements that includes the selected // version of every module path in direct as a root, and maintains the selected // version of every module selected in the graph of rs. // @@ -1019,7 +1027,7 @@ func tidyEagerRoots(ctx context.Context, mainModule module.Version, direct map[s // by a dependency in add. // 4. Every version in add is selected at its given version unless upgraded by // (the dependencies of) an existing root or another module in add. -func updateEagerRoots(ctx context.Context, direct map[string]bool, rs *Requirements, add []module.Version) (*Requirements, error) { +func updateUnprunedRoots(ctx context.Context, direct map[string]bool, rs *Requirements, add []module.Version) (*Requirements, error) { mg, err := rs.Graph(ctx) if err != nil { // We can't ignore errors in the module graph even if the user passed the -e @@ -1084,7 +1092,7 @@ func updateEagerRoots(ctx context.Context, direct map[string]bool, rs *Requireme // “The selected version of every module path in direct is included as a root.” // - // This is only for convenience and clarity for end users: in an eager module, + // This is only for convenience and clarity for end users: in an unpruned module, // the choice of explicit vs. implicit dependency has no impact on MVS // selection (for itself or any other module). keep := append(mg.BuildList()[MainModules.Len():], add...) @@ -1107,41 +1115,40 @@ func updateEagerRoots(ctx context.Context, direct map[string]bool, rs *Requireme if MainModules.Len() > 1 { module.Sort(roots) } - if rs.depth == eager && reflect.DeepEqual(roots, rs.rootModules) && reflect.DeepEqual(direct, rs.direct) { - // The root set is unchanged and rs was already eager, so keep rs to + if rs.pruning == unpruned && reflect.DeepEqual(roots, rs.rootModules) && reflect.DeepEqual(direct, rs.direct) { + // The root set is unchanged and rs was already unpruned, so keep rs to // preserve its cached ModuleGraph (if any). return rs, nil } - return newRequirements(eager, roots, direct), nil + return newRequirements(unpruned, roots, direct), nil } -// convertDepth returns a version of rs with the given depth. -// If rs already has the given depth, convertDepth returns rs unmodified. -func convertDepth(ctx context.Context, rs *Requirements, depth modDepth) (*Requirements, error) { - if rs.depth == depth { +// convertPruning returns a version of rs with the given pruning behavior. +// If rs already has the given pruning, convertPruning returns rs unmodified. +func convertPruning(ctx context.Context, rs *Requirements, pruning modPruning) (*Requirements, error) { + if rs.pruning == pruning { return rs, nil } - if depth == eager { - // We are converting a lazy module to an eager one. The roots of an eager - // module graph are a superset of the roots of a lazy graph, so we don't - // need to add any new roots — we just need to prune away the ones that are - // redundant given eager loading, which is exactly what updateEagerRoots - // does. - return updateEagerRoots(ctx, rs.direct, rs, nil) + if pruning == unpruned { + // We are converting a pruned module to an unpruned one. The roots of a + // ppruned module graph are a superset of the roots of an unpruned one, so + // we don't need to add any new roots — we just need to drop the ones that + // are redundant, which is exactly what updateUnprunedRoots does. + return updateUnprunedRoots(ctx, rs.direct, rs, nil) } - // We are converting an eager module to a lazy one. The module graph of an - // eager module includes the transitive dependencies of every module in the - // build list. + // We are converting an unpruned module to a pruned one. // - // Hey, we can express that as a lazy root set! “Include the transitive - // dependencies of every module in the build list” is exactly what happens in - // a lazy module if we promote every module in the build list to a root! + // An unpruned module graph includes the transitive dependencies of every + // module in the build list. As it turns out, we can express that as a pruned + // root set! “Include the transitive dependencies of every module in the build + // list” is exactly what happens in a pruned module if we promote every module + // in the build list to a root. mg, err := rs.Graph(ctx) if err != nil { return rs, err } - return newRequirements(lazy, mg.BuildList()[MainModules.Len():], rs.direct), nil + return newRequirements(pruned, mg.BuildList()[MainModules.Len():], rs.direct), nil } diff --git a/src/cmd/go/internal/modload/edit.go b/src/cmd/go/internal/modload/edit.go index 12a23468af..b99ac1242b 100644 --- a/src/cmd/go/internal/modload/edit.go +++ b/src/cmd/go/internal/modload/edit.go @@ -21,7 +21,7 @@ import ( // 2. Each module version in tryUpgrade is upgraded toward the indicated // version as far as can be done without violating (1). // -// 3. Each module version in rs.rootModules (or rs.graph, if rs.depth is eager) +// 3. Each module version in rs.rootModules (or rs.graph, if rs is unpruned) // is downgraded from its original version only to the extent needed to // satisfy (1), or upgraded only to the extent needed to satisfy (1) and // (2). @@ -69,10 +69,11 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel } var roots []module.Version - if rs.depth == eager { - // In an eager module, modules that provide packages imported by the main - // module may either be explicit roots or implicit transitive dependencies. - // We promote the modules in mustSelect to be explicit requirements. + if rs.pruning == unpruned { + // In a module without graph pruning, modules that provide packages imported + // by the main module may either be explicit roots or implicit transitive + // dependencies. We promote the modules in mustSelect to be explicit + // requirements. var rootPaths []string for _, m := range mustSelect { if !MainModules.Contains(m.Path) && m.Version != "none" { @@ -102,8 +103,8 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel return nil, false, err } } else { - // In a lazy module, every module that provides a package imported by the - // main module must be retained as a root. + // In a module with a pruned graph, every module that provides a package + // imported by the main module must be retained as a root. roots = mods if !changed { // Because the roots we just computed are unchanged, the entire graph must @@ -126,7 +127,7 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel direct[m.Path] = true } } - return newRequirements(rs.depth, roots, direct), changed, nil + return newRequirements(rs.pruning, roots, direct), changed, nil } // limiterForEdit returns a versionLimiter with its max versions set such that @@ -149,11 +150,12 @@ func limiterForEdit(ctx context.Context, rs *Requirements, tryUpgrade, mustSelec } } - if rs.depth == eager { - // Eager go.mod files don't indicate which transitive dependencies are - // actually relevant to the main module, so we have to assume that any module - // that could have provided any package — that is, any module whose selected - // version was not "none" — may be relevant. + if rs.pruning == unpruned { + // go.mod files that do not support graph pruning don't indicate which + // transitive dependencies are actually relevant to the main module, so we + // have to assume that any module that could have provided any package — + // that is, any module whose selected version was not "none" — may be + // relevant. for _, m := range mg.BuildList() { restrictTo(m) } @@ -175,7 +177,7 @@ func limiterForEdit(ctx context.Context, rs *Requirements, tryUpgrade, mustSelec } } - if err := raiseLimitsForUpgrades(ctx, maxVersion, rs.depth, tryUpgrade, mustSelect); err != nil { + if err := raiseLimitsForUpgrades(ctx, maxVersion, rs.pruning, tryUpgrade, mustSelect); err != nil { return nil, err } @@ -185,7 +187,7 @@ func limiterForEdit(ctx context.Context, rs *Requirements, tryUpgrade, mustSelec restrictTo(m) } - return newVersionLimiter(rs.depth, maxVersion), nil + return newVersionLimiter(rs.pruning, maxVersion), nil } // raiseLimitsForUpgrades increases the module versions in maxVersions to the @@ -195,12 +197,12 @@ func limiterForEdit(ctx context.Context, rs *Requirements, tryUpgrade, mustSelec // // Versions not present in maxVersion are unrestricted, and it is assumed that // they will not be promoted to root requirements (and thus will not contribute -// their own dependencies if the main module is lazy). +// their own dependencies if the main module supports graph pruning). // // These limits provide an upper bound on how far a module may be upgraded as // part of an incidental downgrade, if downgrades are needed in order to select // the versions in mustSelect. -func raiseLimitsForUpgrades(ctx context.Context, maxVersion map[string]string, depth modDepth, tryUpgrade []module.Version, mustSelect []module.Version) error { +func raiseLimitsForUpgrades(ctx context.Context, maxVersion map[string]string, pruning modPruning, tryUpgrade []module.Version, mustSelect []module.Version) error { // allow raises the limit for m.Path to at least m.Version. // If m.Path was already unrestricted, it remains unrestricted. allow := func(m module.Version) { @@ -213,9 +215,9 @@ func raiseLimitsForUpgrades(ctx context.Context, maxVersion map[string]string, d } } - var eagerUpgrades []module.Version - if depth == eager { - eagerUpgrades = tryUpgrade + var unprunedUpgrades []module.Version + if pruning == unpruned { + unprunedUpgrades = tryUpgrade } else { for _, m := range tryUpgrade { if MainModules.Contains(m.Path) { @@ -229,11 +231,11 @@ func raiseLimitsForUpgrades(ctx context.Context, maxVersion map[string]string, d if err != nil { return err } - if summary.depth == eager { - // For efficiency, we'll load all of the eager upgrades as one big + if summary.pruning == unpruned { + // For efficiency, we'll load all of the unpruned upgrades as one big // graph, rather than loading the (potentially-overlapping) subgraph for // each upgrade individually. - eagerUpgrades = append(eagerUpgrades, m) + unprunedUpgrades = append(unprunedUpgrades, m) continue } @@ -244,14 +246,14 @@ func raiseLimitsForUpgrades(ctx context.Context, maxVersion map[string]string, d } } - if len(eagerUpgrades) > 0 { - // Compute the max versions for eager upgrades all together. - // Since these modules are eager, we'll end up scanning all of their + if len(unprunedUpgrades) > 0 { + // Compute the max versions for unpruned upgrades all together. + // Since these modules are unpruned, we'll end up scanning all of their // transitive dependencies no matter which versions end up selected, // and since we have a large dependency graph to scan we might get // a significant benefit from not revisiting dependencies that are at // common versions among multiple upgrades. - upgradeGraph, err := readModGraph(ctx, eager, eagerUpgrades) + upgradeGraph, err := readModGraph(ctx, unpruned, unprunedUpgrades) if err != nil { // Compute the requirement path from a module path in tryUpgrade to the // error, and the requirement path (if any) from rs.rootModules to the @@ -268,7 +270,7 @@ func raiseLimitsForUpgrades(ctx context.Context, maxVersion map[string]string, d } if len(mustSelect) > 0 { - mustGraph, err := readModGraph(ctx, depth, mustSelect) + mustGraph, err := readModGraph(ctx, pruning, mustSelect) if err != nil { return err } @@ -300,7 +302,7 @@ func selectPotentiallyImportedModules(ctx context.Context, limiter *versionLimit } var initial []module.Version - if rs.depth == eager { + if rs.pruning == unpruned { mg, err := rs.Graph(ctx) if err != nil { return nil, false, err @@ -327,7 +329,7 @@ func selectPotentiallyImportedModules(ctx context.Context, limiter *versionLimit // downgraded module may require a higher (but still allowed) version of // another. The lower version may require extraneous dependencies that aren't // actually relevant, so we need to compute the actual selected versions. - mg, err := readModGraph(ctx, rs.depth, mods) + mg, err := readModGraph(ctx, rs.pruning, mods) if err != nil { return nil, false, err } @@ -349,16 +351,16 @@ func selectPotentiallyImportedModules(ctx context.Context, limiter *versionLimit // A versionLimiter tracks the versions that may be selected for each module // subject to constraints on the maximum versions of transitive dependencies. type versionLimiter struct { - // depth is the depth at which the dependencies of the modules passed to + // pruning is the pruning at which the dependencies of the modules passed to // Select and UpgradeToward are loaded. - depth modDepth + pruning modPruning // max maps each module path to the maximum version that may be selected for // that path. // // Paths with no entry are unrestricted, and we assume that they will not be // promoted to root dependencies (so will not contribute dependencies if the - // main module is lazy). + // main module supports graph pruning). max map[string]string // selected maps each module path to a version of that path (if known) whose @@ -410,16 +412,16 @@ func (dq dqState) isDisqualified() bool { // in the map are unrestricted. The limiter assumes that unrestricted paths will // not be promoted to root dependencies. // -// If depth is lazy, then if a module passed to UpgradeToward or Select is -// itself lazy, its unrestricted dependencies are skipped when scanning -// requirements. -func newVersionLimiter(depth modDepth, max map[string]string) *versionLimiter { +// If module graph pruning is in effect, then if a module passed to +// UpgradeToward or Select supports pruning, its unrestricted dependencies are +// skipped when scanning requirements. +func newVersionLimiter(pruning modPruning, max map[string]string) *versionLimiter { selected := make(map[string]string) for _, m := range MainModules.Versions() { selected[m.Path] = m.Version } return &versionLimiter{ - depth: depth, + pruning: pruning, max: max, selected: selected, dqReason: map[module.Version]dqState{}, @@ -430,8 +432,8 @@ func newVersionLimiter(depth modDepth, max map[string]string) *versionLimiter { // UpgradeToward attempts to upgrade the selected version of m.Path as close as // possible to m.Version without violating l's maximum version limits. // -// If depth is lazy and m itself is lazy, the the dependencies of unrestricted -// dependencies of m will not be followed. +// If module graph pruning is in effect and m itself supports pruning, the +// dependencies of unrestricted dependencies of m will not be followed. func (l *versionLimiter) UpgradeToward(ctx context.Context, m module.Version) error { selected, ok := l.selected[m.Path] if ok { @@ -443,7 +445,7 @@ func (l *versionLimiter) UpgradeToward(ctx context.Context, m module.Version) er selected = "none" } - if l.check(m, l.depth).isDisqualified() { + if l.check(m, l.pruning).isDisqualified() { candidates, err := versions(ctx, m.Path, CheckAllowed) if err != nil { // This is likely a transient error reaching the repository, @@ -460,7 +462,7 @@ func (l *versionLimiter) UpgradeToward(ctx context.Context, m module.Version) er }) candidates = candidates[:i] - for l.check(m, l.depth).isDisqualified() { + for l.check(m, l.pruning).isDisqualified() { n := len(candidates) if n == 0 || cmpVersion(selected, candidates[n-1]) >= 0 { // We couldn't find a suitable candidate above the already-selected version. @@ -477,7 +479,7 @@ func (l *versionLimiter) UpgradeToward(ctx context.Context, m module.Version) er // Select attempts to set the selected version of m.Path to exactly m.Version. func (l *versionLimiter) Select(m module.Version) (conflict module.Version, err error) { - dq := l.check(m, l.depth) + dq := l.check(m, l.pruning) if !dq.isDisqualified() { l.selected[m.Path] = m.Version } @@ -487,14 +489,14 @@ func (l *versionLimiter) Select(m module.Version) (conflict module.Version, err // check determines whether m (or its transitive dependencies) would violate l's // maximum version limits if added to the module requirement graph. // -// If depth is lazy and m itself is lazy, then the dependencies of unrestricted -// dependencies of m will not be followed. If the lazy loading invariants hold -// for the main module up to this point, the packages in those modules are at -// best only imported by tests of dependencies that are themselves loaded from -// outside modules. Although we would like to keep 'go test all' as reproducible -// as is feasible, we don't want to retain test dependencies that are only -// marginally relevant at best. -func (l *versionLimiter) check(m module.Version, depth modDepth) dqState { +// If pruning is in effect and m itself supports graph pruning, the dependencies +// of unrestricted dependencies of m will not be followed. If the graph-pruning +// invariants hold for the main module up to this point, the packages in those +// modules are at best only imported by tests of dependencies that are +// themselves loaded from outside modules. Although we would like to keep +// 'go test all' as reproducible as is feasible, we don't want to retain test +// dependencies that are only marginally relevant at best. +func (l *versionLimiter) check(m module.Version, pruning modPruning) dqState { if m.Version == "none" || m == MainModules.mustGetSingleMainModule() { // version "none" has no requirements, and the dependencies of Target are // tautological. @@ -525,20 +527,20 @@ func (l *versionLimiter) check(m module.Version, depth modDepth) dqState { return l.disqualify(m, dqState{err: err}) } - if summary.depth == eager { - depth = eager + if summary.pruning == unpruned { + pruning = unpruned } for _, r := range summary.require { - if depth == lazy { + if pruning == pruned { if _, restricted := l.max[r.Path]; !restricted { // r.Path is unrestricted, so we don't care at what version it is // selected. We assume that r.Path will not become a root dependency, so - // since m is lazy, r's dependencies won't be followed. + // since m supports pruning, r's dependencies won't be followed. continue } } - if dq := l.check(r, depth); dq.isDisqualified() { + if dq := l.check(r, pruning); dq.isDisqualified() { return l.disqualify(m, dq) } diff --git a/src/cmd/go/internal/modload/import_test.go b/src/cmd/go/internal/modload/import_test.go index 98145887e9..11310489ad 100644 --- a/src/cmd/go/internal/modload/import_test.go +++ b/src/cmd/go/internal/modload/import_test.go @@ -69,7 +69,7 @@ func TestQueryImport(t *testing.T) { RootMode = NoRoot ctx := context.Background() - rs := newRequirements(eager, nil, nil) + rs := newRequirements(unpruned, nil, nil) for _, tt := range importTests { t.Run(strings.ReplaceAll(tt.path, "/", "_"), func(t *testing.T) { diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 0843e1ad4d..bc155c7310 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -625,7 +625,7 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { MainModules = makeMainModules([]module.Version{mainModule}, []string{""}, []*modfile.File{nil}, []*modFileIndex{nil}, "") goVersion := LatestGoVersion() rawGoVersion.Store(mainModule, goVersion) - requirements = newRequirements(modDepthFromGoVersion(goVersion), nil, nil) + requirements = newRequirements(pruningForGoVersion(goVersion), nil, nil) return requirements, false } @@ -712,11 +712,11 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { // We need to add a 'go' version to the go.mod file, but we must assume // that its existing contents match something between Go 1.11 and 1.16. - // Go 1.11 through 1.16 have eager requirements, but the latest Go - // version uses lazy requirements instead — so we need to convert the - // requirements to be lazy. + // Go 1.11 through 1.16 do not support graph pruning, but the latest Go + // version uses a pruned module graph — so we need to convert the + // requirements to support pruning. var err error - rs, err = convertDepth(ctx, rs, lazy) + rs, err = convertPruning(ctx, rs, pruned) if err != nil { base.Fatalf("go: %v", err) } @@ -978,7 +978,7 @@ func requirementsFromModFiles(ctx context.Context, modFiles []*modfile.File) *Re } } module.Sort(roots) - rs := newRequirements(modDepthFromGoVersion(MainModules.GoVersion()), roots, direct) + rs := newRequirements(pruningForGoVersion(MainModules.GoVersion()), roots, direct) return rs } @@ -1485,12 +1485,13 @@ func keepSums(ctx context.Context, ld *loader, rs *Requirements, which whichSums continue } - if rs.depth == lazy && pkg.mod.Path != "" { + if rs.pruning == pruned && pkg.mod.Path != "" { if v, ok := rs.rootSelected(pkg.mod.Path); ok && v == pkg.mod.Version { - // pkg was loaded from a root module, and because the main module is - // lazy we do not check non-root modules for conflicts for packages - // that can be found in roots. So we only need the checksums for the - // root modules that may contain pkg, not all possible modules. + // pkg was loaded from a root module, and because the main module has + // a pruned module graph we do not check non-root modules for + // conflicts for packages that can be found in roots. So we only need + // the checksums for the root modules that may contain pkg, not all + // possible modules. for prefix := pkg.path; prefix != "."; prefix = path.Dir(prefix) { if v, ok := rs.rootSelected(prefix); ok && v != "none" { m := module.Version{Path: prefix, Version: v} @@ -1514,8 +1515,7 @@ func keepSums(ctx context.Context, ld *loader, rs *Requirements, which whichSums } if rs.graph.Load() == nil { - // The module graph was not loaded, possibly because the main module is lazy - // or possibly because we haven't needed to load the graph yet. + // We haven't needed to load the module graph so far. // Save sums for the root modules (or their replacements), but don't // incur the cost of loading the graph just to find and retain the sums. for _, m := range rs.rootModules { diff --git a/src/cmd/go/internal/modload/list.go b/src/cmd/go/internal/modload/list.go index 9c5018f340..ac10a42c5a 100644 --- a/src/cmd/go/internal/modload/list.go +++ b/src/cmd/go/internal/modload/list.go @@ -105,7 +105,7 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List path := arg[:i] vers := arg[i+1:] if vers == "upgrade" || vers == "patch" { - if _, ok := rs.rootSelected(path); !ok || rs.depth == eager { + if _, ok := rs.rootSelected(path); !ok || rs.pruning == unpruned { needFullGraph = true if !HasModRoot() { base.Fatalf("go: cannot match %q: %v", arg, ErrNoModRoot) @@ -114,7 +114,7 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List } continue } - if _, ok := rs.rootSelected(arg); !ok || rs.depth == eager { + if _, ok := rs.rootSelected(arg); !ok || rs.pruning == unpruned { needFullGraph = true if mode&ListVersions == 0 && !HasModRoot() { base.Fatalf("go: cannot match %q without -versions or an explicit version: %v", arg, ErrNoModRoot) diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index efe6ad1319..20c007a03a 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -40,9 +40,10 @@ package modload // - the main module specifies a go version ≤ 1.15, and the package is imported // by a *test of* another package in "all". // -// When we implement lazy loading, we will record the modules providing packages -// in "all" even when we are only loading individual packages, so we set the -// pkgInAll flag regardless of the whether the "all" pattern is a root. +// When graph pruning is in effect, we want to spot-check the graph-pruning +// invariants — which depend on which packages are known to be in "all" — even +// when we are only loading individual packages, so we set the pkgInAll flag +// regardless of the whether the "all" pattern is a root. // (This is necessary to maintain the “import invariant” described in // https://golang.org/design/36460-lazy-module-loading.) // @@ -367,7 +368,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma for _, m := range initialRS.rootModules { var unused bool - if ld.requirements.depth == eager { + if ld.requirements.pruning == unpruned { // m is unused if it was dropped from the module graph entirely. If it // was only demoted from direct to indirect, it may still be in use via // a transitive import. @@ -386,7 +387,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma } keep := keepSums(ctx, ld, ld.requirements, loadedZipSumsOnly) - if compatDepth := modDepthFromGoVersion(ld.TidyCompatibleVersion); compatDepth != ld.requirements.depth { + if compatDepth := pruningForGoVersion(ld.TidyCompatibleVersion); compatDepth != ld.requirements.pruning { compatRS := newRequirements(compatDepth, ld.requirements.rootModules, ld.requirements.direct) ld.checkTidyCompatibility(ctx, compatRS) @@ -622,7 +623,7 @@ func pathInModuleCache(ctx context.Context, dir string, rs *Requirements) string return path.Join(m.Path, filepath.ToSlash(sub)), true } - if rs.depth == lazy { + if rs.pruning == pruned { for _, m := range rs.rootModules { if v, _ := rs.rootSelected(m.Path); v != m.Version { continue // m is a root, but we have a higher root for the same path. @@ -635,9 +636,9 @@ func pathInModuleCache(ctx context.Context, dir string, rs *Requirements) string } } - // None of the roots contained dir, or we're in eager mode and want to load - // the full module graph more aggressively. Either way, check the full graph - // to see if the directory is a non-root dependency. + // None of the roots contained dir, or the graph is unpruned (so we don't want + // to distinguish between roots and transitive dependencies). Either way, + // check the full graph to see if the directory is a non-root dependency. // // If the roots are not consistent with the full module graph, the selected // versions of root modules may differ from what we already checked above. @@ -986,18 +987,26 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader { } if semver.Compare("v"+ld.GoVersion, narrowAllVersionV) < 0 && !ld.UseVendorAll { - // The module's go version explicitly predates the change in "all" for lazy - // loading, so continue to use the older interpretation. + // The module's go version explicitly predates the change in "all" for graph + // pruning, so continue to use the older interpretation. ld.allClosesOverTests = true } var err error - ld.requirements, err = convertDepth(ctx, ld.requirements, modDepthFromGoVersion(ld.GoVersion)) + ld.requirements, err = convertPruning(ctx, ld.requirements, pruningForGoVersion(ld.GoVersion)) if err != nil { ld.errorf("go: %v\n", err) } - if ld.requirements.depth == eager { + if ld.requirements.pruning == unpruned { + // If the module graph does not support pruning, we assume that we will need + // the full module graph in order to load package dependencies. + // + // This might not be strictly necessary, but it matches the historical + // behavior of the 'go' command and keeps the go.mod file more consistent in + // case of erroneous hand-edits — which are less likely to be detected by + // spot-checks in modules that do not maintain the expanded go.mod + // requirements needed for graph pruning. var err error ld.requirements, _, err = expandGraph(ctx, ld.requirements) if err != nil { @@ -1014,7 +1023,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader { // build list we're using. rootPkgs := ld.listRoots(ld.requirements) - if ld.requirements.depth == lazy && cfg.BuildMod == "mod" { + if ld.requirements.pruning == pruned && cfg.BuildMod == "mod" { // Before we start loading transitive imports of packages, locate all of // the root packages and promote their containing modules to root modules // dependencies. If their go.mod files are tidy (the common case) and the @@ -1125,11 +1134,11 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader { ld.errorf("go: %v\n", err) } - if ld.requirements.depth == lazy { + if ld.requirements.pruning == pruned { // We continuously add tidy roots to ld.requirements during loading, so at // this point the tidy roots should be a subset of the roots of // ld.requirements, ensuring that no new dependencies are brought inside - // the lazy-loading horizon. + // the graph-pruning horizon. // If that is not the case, there is a bug in the loading loop above. for _, m := range rs.rootModules { if v, ok := ld.requirements.rootSelected(m.Path); !ok || v != m.Version { @@ -1257,14 +1266,14 @@ func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err err var addRoots []module.Version if ld.Tidy { - // When we are tidying a lazy module, we may need to add roots to preserve - // the versions of indirect, test-only dependencies that are upgraded - // above or otherwise missing from the go.mod files of direct - // dependencies. (For example, the direct dependency might be a very + // When we are tidying a module with a pruned dependency graph, we may need + // to add roots to preserve the versions of indirect, test-only dependencies + // that are upgraded above or otherwise missing from the go.mod files of + // direct dependencies. (For example, the direct dependency might be a very // stable codebase that predates modules and thus lacks a go.mod file, or - // the author of the direct dependency may have forgotten to commit a - // change to the go.mod file, or may have made an erroneous hand-edit that - // causes it to be untidy.) + // the author of the direct dependency may have forgotten to commit a change + // to the go.mod file, or may have made an erroneous hand-edit that causes + // it to be untidy.) // // Promoting an indirect dependency to a root adds the next layer of its // dependencies to the module graph, which may increase the selected @@ -1571,7 +1580,8 @@ func (ld *loader) preloadRootModules(ctx context.Context, rootPkgs []string) (ch // module to a root to ensure that any other packages this package // imports are resolved from correct dependency versions. // - // (This is the “argument invariant” from the lazy loading design.) + // (This is the “argument invariant” from + // https://golang.org/design/36460-lazy-module-loading.) need := <-needc need[m] = true needc <- need @@ -1633,7 +1643,7 @@ func (ld *loader) load(ctx context.Context, pkg *loadPkg) { } var mg *ModuleGraph - if ld.requirements.depth == eager { + if ld.requirements.pruning == unpruned { var err error mg, err = ld.requirements.Graph(ctx) if err != nil { @@ -1961,9 +1971,10 @@ func (ld *loader) checkTidyCompatibility(ctx context.Context, rs *Requirements) case mismatch.err != nil: // pkg resolved successfully, but errors out using the requirements in rs. // - // This could occur because the import is provided by a single lazy root - // (and is thus unambiguous in lazy mode) and also one or more - // transitive dependencies (and is ambiguous in eager mode). + // This could occur because the import is provided by a single root (and + // is thus unambiguous in a main module with a pruned module graph) and + // also one or more transitive dependencies (and is ambiguous with an + // unpruned graph). // // It could also occur because some transitive dependency upgrades the // module that previously provided the package to a version that no @@ -2001,18 +2012,18 @@ func (ld *loader) checkTidyCompatibility(ctx context.Context, rs *Requirements) } case pkg.err != nil: - // pkg had an error in lazy mode (presumably suppressed with the -e flag), - // but not in eager mode. + // pkg had an error in with a pruned module graph (presumably suppressed + // with the -e flag), but the error went away using an unpruned graph. // - // This is possible, if, say, the import is unresolved in lazy mode + // This is possible, if, say, the import is unresolved in the pruned graph // (because the "latest" version of each candidate module either is - // unavailable or does not contain the package), but is resolved in - // eager mode due to a newer-than-latest dependency that is normally - // runed out of the module graph. + // unavailable or does not contain the package), but is resolved in the + // unpruned graph due to a newer-than-latest dependency that is normally + // pruned out. // // This could also occur if the source code for the module providing the - // package in lazy mode has a checksum error, but eager mode upgrades - // that module to a version with a correct checksum. + // package in the pruned graph has a checksum error, but the unpruned + // graph upgrades that module to a version with a correct checksum. // // pkg.err should have already been logged elsewhere — along with a // stack trace — so log only the import path and non-error info here. diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index d2b13fb89f..79ac1227ca 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -33,10 +33,13 @@ const ( // tests outside of the main module. narrowAllVersionV = "v1.16" - // lazyLoadingVersionV is the Go version (plus leading "v") at which a + // explicitIndirectVersionV is the Go version (plus leading "v") at which a // module's go.mod file is expected to list explicit requirements on every // module that provides any package transitively imported by that module. - lazyLoadingVersionV = "v1.17" + // + // Other indirect dependencies of such a module can be safely pruned out of + // the module graph; see https://golang.org/ref/mod#graph-pruning. + explicitIndirectVersionV = "v1.17" // separateIndirectVersionV is the Go version (plus leading "v") at which // "// indirect" dependencies are added in a block separate from the direct @@ -57,9 +60,9 @@ func modFileGoVersion(modFile *modfile.File) string { // has been erroneously hand-edited. // // The semantics of the go.mod file are more-or-less the same from Go 1.11 - // through Go 1.16, changing at 1.17 for lazy loading. So even though a - // go.mod file without a 'go' directive is theoretically a Go 1.11 file, - // scripts may assume that it ends up as a Go 1.16 module. + // through Go 1.16, changing at 1.17 to support module graph pruning. + // So even though a go.mod file without a 'go' directive is theoretically a + // Go 1.11 file, scripts may assume that it ends up as a Go 1.16 module. return "1.16" } return modFile.Go.Version @@ -82,19 +85,23 @@ type requireMeta struct { indirect bool } -// A modDepth indicates which dependencies should be loaded for a go.mod file. -type modDepth uint8 +// A modPruning indicates whether transitive dependencies of Go 1.17 dependencies +// are pruned out of the module subgraph rooted at a given module. +// (See https://golang.org/ref/mod#graph-pruning.) +type modPruning uint8 const ( - lazy modDepth = iota // load dependencies only as needed - eager // load all transitive dependencies eagerly + pruned modPruning = iota // transitive dependencies of modules at go 1.17 and higher are pruned out + unpruned // no transitive dependencies are pruned out ) -func modDepthFromGoVersion(goVersion string) modDepth { - if semver.Compare("v"+goVersion, lazyLoadingVersionV) < 0 { - return eager +func pruningForGoVersion(goVersion string) modPruning { + if semver.Compare("v"+goVersion, explicitIndirectVersionV) < 0 { + // The go.mod file does not duplicate relevant information about transitive + // dependencies, so they cannot be pruned out. + return unpruned } - return lazy + return pruned } // CheckAllowed returns an error equivalent to ErrDisallowed if m is excluded by @@ -468,7 +475,7 @@ var rawGoVersion sync.Map // map[module.Version]string type modFileSummary struct { module module.Version goVersion string - depth modDepth + pruning modPruning require []module.Version retract []retraction deprecated string @@ -620,9 +627,9 @@ func rawGoModSummary(m module.Version, replacedFrom string) (*modFileSummary, er if f.Go != nil && f.Go.Version != "" { rawGoVersion.LoadOrStore(m, f.Go.Version) summary.goVersion = f.Go.Version - summary.depth = modDepthFromGoVersion(f.Go.Version) + summary.pruning = pruningForGoVersion(f.Go.Version) } else { - summary.depth = eager + summary.pruning = unpruned } if len(f.Require) > 0 { summary.require = make([]module.Version, 0, len(f.Require)) -- GitLab From 5f0d821adda38b728592b9ee919c94013eb2ab5f Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sat, 28 Aug 2021 13:00:41 -0700 Subject: [PATCH 0903/2500] cmd/compile/internal/types2: use a typeWriter to write types (cleanup) Rather then passing through a buffer, qualified, and visited list to each helper function, maintain state in a typeWriter object and use methods on it. This cleans up this code quite a bit. Use a map ("seen") for cycle detection rather than a list. Move printing of [ and ] for type lists into the typeList method so that callers don't have to do it themselves. Change-Id: I1346373e979cb90710fbc073953aa51e2f6581f9 Reviewed-on: https://go-review.googlesource.com/c/go/+/345890 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/object.go | 2 +- src/cmd/compile/internal/types2/subst.go | 7 +- src/cmd/compile/internal/types2/typelists.go | 4 +- src/cmd/compile/internal/types2/typestring.go | 206 +++++++++--------- src/cmd/compile/internal/types2/unify.go | 13 +- 5 files changed, 119 insertions(+), 113 deletions(-) diff --git a/src/cmd/compile/internal/types2/object.go b/src/cmd/compile/internal/types2/object.go index c1466f24ed..a3f5f913aa 100644 --- a/src/cmd/compile/internal/types2/object.go +++ b/src/cmd/compile/internal/types2/object.go @@ -476,7 +476,7 @@ func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) { return } if named, _ := typ.(*Named); named != nil && named.TParams().Len() > 0 { - writeTParamList(buf, named.TParams().list(), qf, nil) + newTypeWriter(buf, qf).tParamList(named.TParams().list()) } if tname.IsAlias() { buf.WriteString(" =") diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 7c33e7ade4..f4891df664 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -259,10 +259,9 @@ func instantiatedHash(typ *Named, targs []Type) string { assert(instanceHashing == 0) instanceHashing++ var buf bytes.Buffer - writeTypeName(&buf, typ.obj, nil) - buf.WriteByte('[') - writeTypeList(&buf, targs, nil, nil) - buf.WriteByte(']') + w := newTypeWriter(&buf, nil) + w.typeName(typ.obj) + w.typeList(targs) instanceHashing-- // With respect to the represented type, whether a diff --git a/src/cmd/compile/internal/types2/typelists.go b/src/cmd/compile/internal/types2/typelists.go index c3befb077f..f313ea310e 100644 --- a/src/cmd/compile/internal/types2/typelists.go +++ b/src/cmd/compile/internal/types2/typelists.go @@ -59,9 +59,7 @@ func (l *TypeList) String() string { return "[]" } var buf bytes.Buffer - buf.WriteByte('[') - writeTypeList(&buf, l.types, nil, nil) - buf.WriteByte(']') + newTypeWriter(&buf, nil).typeList(l.types) return buf.String() } diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 1775fc6677..d02f38a6ac 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -52,79 +52,87 @@ func TypeString(typ Type, qf Qualifier) string { // The Qualifier controls the printing of // package-level objects, and may be nil. func WriteType(buf *bytes.Buffer, typ Type, qf Qualifier) { - writeType(buf, typ, qf, make([]Type, 0, 8)) + newTypeWriter(buf, qf).typ(typ) } -// instanceMarker is the prefix for an instantiated type -// in "non-evaluated" instance form. +// instanceMarker is the prefix for an instantiated type in unexpanded form. const instanceMarker = '#' -func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { - // Theoretically, this is a quadratic lookup algorithm, but in - // practice deeply nested composite types with unnamed component - // types are uncommon. This code is likely more efficient than - // using a map. - for _, t := range visited { - if t == typ { - fmt.Fprintf(buf, "○%T", goTypeName(typ)) // cycle to typ - return - } +type typeWriter struct { + buf *bytes.Buffer + seen map[Type]bool + qf Qualifier +} + +func newTypeWriter(buf *bytes.Buffer, qf Qualifier) *typeWriter { + return &typeWriter{buf, make(map[Type]bool), qf} +} + +func (w *typeWriter) byte(b byte) { w.buf.WriteByte(b) } +func (w *typeWriter) string(s string) { w.buf.WriteString(s) } +func (w *typeWriter) writef(format string, args ...interface{}) { fmt.Fprintf(w.buf, format, args...) } + +func (w *typeWriter) typ(typ Type) { + if w.seen[typ] { + w.writef("○%T", goTypeName(typ)) // cycle to typ + return } - visited = append(visited, typ) + w.seen[typ] = true + defer delete(w.seen, typ) switch t := typ.(type) { case nil: - buf.WriteString("") + w.string("") case *Basic: // exported basic types go into package unsafe // (currently this is just unsafe.Pointer) if isExported(t.name) { if obj, _ := Unsafe.scope.Lookup(t.name).(*TypeName); obj != nil { - writeTypeName(buf, obj, qf) + w.typeName(obj) break } } - buf.WriteString(t.name) + w.string(t.name) case *Array: - fmt.Fprintf(buf, "[%d]", t.len) - writeType(buf, t.elem, qf, visited) + w.writef("[%d]", t.len) + w.typ(t.elem) case *Slice: - buf.WriteString("[]") - writeType(buf, t.elem, qf, visited) + w.string("[]") + w.typ(t.elem) case *Struct: - buf.WriteString("struct{") + w.string("struct{") for i, f := range t.fields { if i > 0 { - buf.WriteString("; ") + w.string("; ") } // This doesn't do the right thing for embedded type // aliases where we should print the alias name, not // the aliased type (see issue #44410). if !f.embedded { - buf.WriteString(f.name) - buf.WriteByte(' ') + w.string(f.name) + w.byte(' ') } - writeType(buf, f.typ, qf, visited) + w.typ(f.typ) if tag := t.Tag(i); tag != "" { - fmt.Fprintf(buf, " %q", tag) + w.writef(" %q", tag) } } - buf.WriteByte('}') + w.byte('}') case *Pointer: - buf.WriteByte('*') - writeType(buf, t.base, qf, visited) + w.byte('*') + w.typ(t.base) case *Tuple: - writeTuple(buf, t, false, qf, visited) + w.tuple(t, false) case *Signature: - buf.WriteString("func") - writeSignature(buf, t, qf, visited) + w.string("func") + w.signature(t) case *Union: // Unions only appear as (syntactic) embedded elements @@ -134,39 +142,39 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { } for i, t := range t.terms { if i > 0 { - buf.WriteByte('|') + w.byte('|') } if t.tilde { - buf.WriteByte('~') + w.byte('~') } - writeType(buf, t.typ, qf, visited) + w.typ(t.typ) } case *Interface: - buf.WriteString("interface{") + w.string("interface{") first := true for _, m := range t.methods { if !first { - buf.WriteString("; ") + w.string("; ") } first = false - buf.WriteString(m.name) - writeSignature(buf, m.typ.(*Signature), qf, visited) + w.string(m.name) + w.signature(m.typ.(*Signature)) } for _, typ := range t.embeddeds { if !first { - buf.WriteString("; ") + w.string("; ") } first = false - writeType(buf, typ, qf, visited) + w.typ(typ) } - buf.WriteByte('}') + w.byte('}') case *Map: - buf.WriteString("map[") - writeType(buf, t.key, qf, visited) - buf.WriteByte(']') - writeType(buf, t.elem, qf, visited) + w.string("map[") + w.typ(t.key) + w.byte(']') + w.typ(t.elem) case *Chan: var s string @@ -185,28 +193,26 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { default: unreachable() } - buf.WriteString(s) + w.string(s) if parens { - buf.WriteByte('(') + w.byte('(') } - writeType(buf, t.elem, qf, visited) + w.typ(t.elem) if parens { - buf.WriteByte(')') + w.byte(')') } case *Named: if t.instPos != nil { - buf.WriteByte(instanceMarker) + w.byte(instanceMarker) } - writeTypeName(buf, t.obj, qf) + w.typeName(t.obj) if t.targs != nil { // instantiated type - buf.WriteByte('[') - writeTypeList(buf, t.targs.list(), qf, visited) - buf.WriteByte(']') + w.typeList(t.targs.list()) } else if t.TParams().Len() != 0 { // parameterized type - writeTParamList(buf, t.TParams().list(), qf, visited) + w.tParamList(t.TParams().list()) } case *TypeParam: @@ -217,33 +223,35 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { // we maybe need a separate function that won't be changed // for debugging purposes. if t.obj.pkg != nil { - writePackage(buf, t.obj.pkg, qf) + writePackage(w.buf, t.obj.pkg, w.qf) } s = t.obj.name } - buf.WriteString(s + subscript(t.id)) + w.string(s + subscript(t.id)) case *top: - buf.WriteString("⊤") + w.string("⊤") default: // For externally defined implementations of Type. // Note: In this case cycles won't be caught. - buf.WriteString(t.String()) + w.string(t.String()) } } -func writeTypeList(buf *bytes.Buffer, list []Type, qf Qualifier, visited []Type) { +func (w *typeWriter) typeList(list []Type) { + w.byte('[') for i, typ := range list { if i > 0 { - buf.WriteString(", ") + w.string(", ") } - writeType(buf, typ, qf, visited) + w.typ(typ) } + w.byte(']') } -func writeTParamList(buf *bytes.Buffer, list []*TypeParam, qf Qualifier, visited []Type) { - buf.WriteString("[") +func (w *typeWriter) tParamList(list []*TypeParam) { + w.byte('[') var prev Type for i, tpar := range list { // Determine the type parameter and its constraint. @@ -257,36 +265,36 @@ func writeTParamList(buf *bytes.Buffer, list []*TypeParam, qf Qualifier, visited if i > 0 { if bound != prev { // bound changed - write previous one before advancing - buf.WriteByte(' ') - writeType(buf, prev, qf, visited) + w.byte(' ') + w.typ(prev) } - buf.WriteString(", ") + w.string(", ") } prev = bound if tpar != nil { - writeType(buf, tpar, qf, visited) + w.typ(tpar) } else { - buf.WriteString(tpar.obj.name) + w.string(tpar.obj.name) } } if prev != nil { - buf.WriteByte(' ') - writeType(buf, prev, qf, visited) + w.byte(' ') + w.typ(prev) } - buf.WriteByte(']') + w.byte(']') } -func writeTypeName(buf *bytes.Buffer, obj *TypeName, qf Qualifier) { +func (w *typeWriter) typeName(obj *TypeName) { if obj == nil { assert(instanceHashing == 0) // we need an object for instance hashing - buf.WriteString("") + w.string("") return } if obj.pkg != nil { - writePackage(buf, obj.pkg, qf) + writePackage(w.buf, obj.pkg, w.qf) } - buf.WriteString(obj.name) + w.string(obj.name) if instanceHashing != 0 { // For local defined types, use the (original!) TypeName's scope @@ -298,7 +306,7 @@ func writeTypeName(buf *bytes.Buffer, obj *TypeName, qf Qualifier) { for typ.orig != typ { typ = typ.orig } - writeScopeNumbers(buf, typ.obj.parent) + w.writeScopeNumbers(typ.obj.parent) } } @@ -306,28 +314,28 @@ func writeTypeName(buf *bytes.Buffer, obj *TypeName, qf Qualifier) { // in the form ".i.j.k" where i, j, k, etc. stand for scope numbers. // If a scope is nil or has no parent (such as a package scope), nothing // is written. -func writeScopeNumbers(buf *bytes.Buffer, s *Scope) { +func (w *typeWriter) writeScopeNumbers(s *Scope) { if s != nil && s.number > 0 { - writeScopeNumbers(buf, s.parent) - fmt.Fprintf(buf, ".%d", s.number) + w.writeScopeNumbers(s.parent) + w.writef(".%d", s.number) } } -func writeTuple(buf *bytes.Buffer, tup *Tuple, variadic bool, qf Qualifier, visited []Type) { - buf.WriteByte('(') +func (w *typeWriter) tuple(tup *Tuple, variadic bool) { + w.byte('(') if tup != nil { for i, v := range tup.vars { if i > 0 { - buf.WriteString(", ") + w.string(", ") } if v.name != "" { - buf.WriteString(v.name) - buf.WriteByte(' ') + w.string(v.name) + w.byte(' ') } typ := v.typ if variadic && i == len(tup.vars)-1 { if s, ok := typ.(*Slice); ok { - buf.WriteString("...") + w.string("...") typ = s.elem } else { // special case: @@ -335,15 +343,15 @@ func writeTuple(buf *bytes.Buffer, tup *Tuple, variadic bool, qf Qualifier, visi if t := asBasic(typ); t == nil || t.kind != String { panic("expected string type") } - writeType(buf, typ, qf, visited) - buf.WriteString("...") + w.typ(typ) + w.string("...") continue } } - writeType(buf, typ, qf, visited) + w.typ(typ) } } - buf.WriteByte(')') + w.byte(')') } // WriteSignature writes the representation of the signature sig to buf, @@ -351,15 +359,15 @@ func writeTuple(buf *bytes.Buffer, tup *Tuple, variadic bool, qf Qualifier, visi // The Qualifier controls the printing of // package-level objects, and may be nil. func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) { - writeSignature(buf, sig, qf, make([]Type, 0, 8)) + newTypeWriter(buf, qf).signature(sig) } -func writeSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier, visited []Type) { +func (w *typeWriter) signature(sig *Signature) { if sig.TParams().Len() != 0 { - writeTParamList(buf, sig.TParams().list(), qf, visited) + w.tParamList(sig.TParams().list()) } - writeTuple(buf, sig.params, sig.variadic, qf, visited) + w.tuple(sig.params, sig.variadic) n := sig.results.Len() if n == 0 { @@ -367,15 +375,15 @@ func writeSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier, visited []T return } - buf.WriteByte(' ') + w.byte(' ') if n == 1 && sig.results.vars[0].name == "" { // single unnamed result - writeType(buf, sig.results.vars[0].typ, qf, visited) + w.typ(sig.results.vars[0].typ) return } // multiple or named result(s) - writeTuple(buf, sig.results, false, qf, visited) + w.tuple(sig.results, false) } // subscript returns the decimal (utf8) representation of x using subscript digits. diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index 72542e7d2e..9eb1f63090 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -76,16 +76,17 @@ type tparamsList struct { // String returns a string representation for a tparamsList. For debugging. func (d *tparamsList) String() string { var buf bytes.Buffer - buf.WriteByte('[') + w := newTypeWriter(&buf, nil) + w.byte('[') for i, tpar := range d.tparams { if i > 0 { - buf.WriteString(", ") + w.string(", ") } - writeType(&buf, tpar, nil, nil) - buf.WriteString(": ") - writeType(&buf, d.at(i), nil, nil) + w.typ(tpar) + w.string(": ") + w.typ(d.at(i)) } - buf.WriteByte(']') + w.byte(']') return buf.String() } -- GitLab From 8250141c9a506dee883b53473867b27e68ac10a4 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sat, 28 Aug 2021 17:11:51 -0700 Subject: [PATCH 0904/2500] cmd/compile/internal/types2: don't print instance markers for type hashes Since we know whether we are printing a type string used as instance hash, don't print instance markers, so that we don't need to remove them afterwards either. Change-Id: Ib01627b6da989ef89d51e734810a3377eb466925 Reviewed-on: https://go-review.googlesource.com/c/go/+/345891 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/subst.go | 19 +++++++------------ src/cmd/compile/internal/types2/typestring.go | 6 +++++- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index f4891df664..9a4db6fddb 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -256,28 +256,23 @@ func (subst *subster) typ(typ Type) Type { var instanceHashing = 0 func instantiatedHash(typ *Named, targs []Type) string { + var buf bytes.Buffer + assert(instanceHashing == 0) instanceHashing++ - var buf bytes.Buffer w := newTypeWriter(&buf, nil) w.typeName(typ.obj) w.typeList(targs) instanceHashing-- - // With respect to the represented type, whether a - // type is fully expanded or stored as instance - // does not matter - they are the same types. - // Remove the instanceMarkers printed for instances. - res := buf.Bytes() - i := 0 - for _, b := range res { - if b != instanceMarker { - res[i] = b - i++ + if debug { + // there should be no instance markers in type hashes + for _, b := range buf.Bytes() { + assert(b != instanceMarker) } } - return string(res[:i]) + return buf.String() } // typOrNil is like typ but if the argument is nil it is replaced with Typ[Invalid]. diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index d02f38a6ac..3b9981089e 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -203,7 +203,11 @@ func (w *typeWriter) typ(typ Type) { } case *Named: - if t.instPos != nil { + // Instance markers indicate unexpanded instantiated + // types. Write them to aid debugging, but don't write + // them when we need an instance hash: whether a type + // is fully expanded or not doesn't matter for identity. + if instanceHashing == 0 && t.instPos != nil { w.byte(instanceMarker) } w.typeName(t.obj) -- GitLab From 8f4c020660d4c8a7bab9a7363551d07176e638eb Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sun, 29 Aug 2021 06:49:28 -0700 Subject: [PATCH 0905/2500] cmd/compile: fix bug with Inferred targs We were using the type from the wrong Node (the partially filled-in FUNCINST) rather than the original function node - which is pointed to by the OFUNCINST)) to set the final fully-substituted type of the OFUNCINST. So fixed the node reference. Also, added check so we don't do any work at all if the OFUNCINST already has all type args filled in. Added few extra cases to the test file issue48030.go, to cover fully-specified type args, partially inferred type args, and fully inferred type args. Fixes #48030 Change-Id: If9e4f2e0514d68b9d241f30c423259133932b25b Reviewed-on: https://go-review.googlesource.com/c/go/+/346229 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/expr.go | 16 +++++++++------- test/typeparam/issue48030.go | 26 ++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 test/typeparam/issue48030.go diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 0e5257d7cf..863acf587d 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -126,13 +126,15 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { targs[i] = ir.TypeNode(g.typ(inferred.TArgs.At(i))) } if fun.Op() == ir.OFUNCINST { - // Replace explicit type args with the full list that - // includes the additional inferred type args. - // Substitute the type args for the type params in - // the generic function's type. - fun.(*ir.InstExpr).Targs = targs - newt := g.substType(fun.Type(), fun.Type().TParams(), targs) - typed(newt, fun) + if len(fun.(*ir.InstExpr).Targs) < len(targs) { + // Replace explicit type args with the full list that + // includes the additional inferred type args. + // Substitute the type args for the type params in + // the generic function's type. + fun.(*ir.InstExpr).Targs = targs + newt := g.substType(fun.(*ir.InstExpr).X.Type(), fun.(*ir.InstExpr).X.Type().TParams(), targs) + typed(newt, fun) + } } else { // Create a function instantiation here, given there // are only inferred type args (e.g. min(5,6), where diff --git a/test/typeparam/issue48030.go b/test/typeparam/issue48030.go new file mode 100644 index 0000000000..9fc4428841 --- /dev/null +++ b/test/typeparam/issue48030.go @@ -0,0 +1,26 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type Src[T any] func() Src[T] + +func Seq[T any]() Src[T] { + return nil +} + +func Seq2[T1 any, T2 any](v1 T1, v2 T2) Src[T2] { + return nil +} + +func main() { + // Type args fully supplied + Seq[int]() + // Partial inference of type args + Seq2[int](5, "abc") + // Full inference of type args + Seq2(5, "abc") +} -- GitLab From 86fa510d2456e20ceaa518f97f0c1c89d2ebd81c Mon Sep 17 00:00:00 2001 From: Quim Muntal Date: Sun, 29 Aug 2021 22:57:36 +0200 Subject: [PATCH 0906/2500] go/types, types2: types in method expressions must be instantiated Use varType instead of instantiatedOperand to check if the type of a method expressions is instantiated. This removes the last usage of instantiatedOperand, so it can be deleted. Fixes #48048 Change-Id: I2b219dafe2bba3603100bb8f25b8ff4e8ef53841 Reviewed-on: https://go-review.googlesource.com/c/go/+/345970 Trust: Robert Griesemer Trust: Matthew Dempsky Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/call.go | 12 +++--------- .../types2/testdata/fixedbugs/issue48048.go2 | 15 +++++++++++++++ src/go/types/call.go | 12 +++--------- src/go/types/testdata/fixedbugs/issue48048.go2 | 15 +++++++++++++++ 4 files changed, 36 insertions(+), 18 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue48048.go2 create mode 100644 src/go/types/testdata/fixedbugs/issue48048.go2 diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 0b062b4c94..954aa1de20 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -479,7 +479,9 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) { goto Error } - check.instantiatedOperand(x) + if x.mode == typexpr { + x.typ = check.varType(e.X) + } obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel) if obj == nil { @@ -718,11 +720,3 @@ func (check *Checker) useLHS(arg ...syntax.Expr) { } } } - -// instantiatedOperand reports an error of x is an uninstantiated (generic) type and sets x.typ to Typ[Invalid]. -func (check *Checker) instantiatedOperand(x *operand) { - if x.mode == typexpr && isGeneric(x.typ) { - check.errorf(x, "cannot use generic type %s without instantiation", x.typ) - x.typ = Typ[Invalid] - } -} diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48048.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48048.go2 new file mode 100644 index 0000000000..f401330621 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48048.go2 @@ -0,0 +1,15 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T[P any] struct{} + +func (T[_]) A() {} + +var _ = (T[int]).A +var _ = (*T[int]).A + +var _ = (T /* ERROR cannot use generic type */).A +var _ = (*T /* ERROR cannot use generic type */).A diff --git a/src/go/types/call.go b/src/go/types/call.go index fdecafb781..61534b6328 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -470,7 +470,9 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { goto Error } - check.instantiatedOperand(x) + if x.mode == typexpr { + x.typ = check.varType(e.X) + } obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel) if obj == nil { @@ -745,11 +747,3 @@ func (check *Checker) useLHS(arg ...ast.Expr) { } } } - -// instantiatedOperand reports an error of x is an uninstantiated (generic) type and sets x.typ to Typ[Invalid]. -func (check *Checker) instantiatedOperand(x *operand) { - if x.mode == typexpr && isGeneric(x.typ) { - check.errorf(x, _Todo, "cannot use generic type %s without instantiation", x.typ) - x.typ = Typ[Invalid] - } -} diff --git a/src/go/types/testdata/fixedbugs/issue48048.go2 b/src/go/types/testdata/fixedbugs/issue48048.go2 new file mode 100644 index 0000000000..f401330621 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue48048.go2 @@ -0,0 +1,15 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T[P any] struct{} + +func (T[_]) A() {} + +var _ = (T[int]).A +var _ = (*T[int]).A + +var _ = (T /* ERROR cannot use generic type */).A +var _ = (*T /* ERROR cannot use generic type */).A -- GitLab From 437362ccec8aeab03aaac63db188f7e8f9eed699 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 27 Aug 2021 20:50:31 -0700 Subject: [PATCH 0907/2500] cmd/compile/internal/types2: generalize instanceHash to accept any type, rename to typeHash Rename instanceHashing accordingly. Eventually, this will make it possible to use typeHash to detect multiple identical types in type switch cases and other places. Also fix some bugs: When creating a type hash, the name of function parameters must be ignored because they don't matter for type identity. And when printing a type name, don't assume its type is a *Named type; it could be a *Basic type as well. Finally, use a correctly qualified type string when reporting a duplicate type error in a type switch case rather than the (debugging) type string. Change-Id: Ida3873f6259b51847843b0e2d7e3aa2fcdc3a0c3 Reviewed-on: https://go-review.googlesource.com/c/go/+/345791 Trust: Robert Griesemer Reviewed-by: Robert Findley --- .../compile/internal/types2/instantiate.go | 2 +- src/cmd/compile/internal/types2/named.go | 2 +- src/cmd/compile/internal/types2/stmt.go | 43 ++++++++++++++++++- src/cmd/compile/internal/types2/subst.go | 28 ++++++++---- src/cmd/compile/internal/types2/typestring.go | 28 ++++++------ 5 files changed, 79 insertions(+), 24 deletions(-) diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 4113d248b8..c882699d1d 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -125,7 +125,7 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, posLis func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type) Type { switch t := typ.(type) { case *Named: - h := instantiatedHash(t, targs) + h := typeHash(t, targs) if check != nil { // typ may already have been instantiated with identical type arguments. // In that case, re-use the existing instance. diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index b4074aa3dc..a76e69fcf1 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -258,7 +258,7 @@ func (n *Named) expand(typMap map[string]*Named) *Named { // type-checking pass. In that case we won't have a pre-existing // typMap, but don't want to create a duplicate of the current instance // in the process of expansion. - h := instantiatedHash(n.orig, n.targs.list()) + h := typeHash(n.orig, n.targs.list()) typMap = map[string]*Named{h: n} } } diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index 3e2ac2e29e..2673e98c57 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -295,7 +295,7 @@ L: // talk about "case" rather than "type" because of nil case Ts := "nil" if T != nil { - Ts = T.String() + Ts = TypeString(T, check.qualifier) } var err error_ err.errorf(e, "duplicate case %s in type switch", Ts) @@ -312,6 +312,47 @@ L: return } +// TODO(gri) Once we are certain that typeHash is correct in all situations, use this version of caseTypes instead. +// (Currently it may be possible that different types have identical names and import paths due to ImporterFrom.) +// +// func (check *Checker) caseTypes(x *operand, xtyp *Interface, types []syntax.Expr, seen map[string]syntax.Expr) (T Type) { +// var dummy operand +// L: +// for _, e := range types { +// // The spec allows the value nil instead of a type. +// var hash string +// if check.isNil(e) { +// check.expr(&dummy, e) // run e through expr so we get the usual Info recordings +// T = nil +// hash = "" // avoid collision with a type named nil +// } else { +// T = check.varType(e) +// if T == Typ[Invalid] { +// continue L +// } +// hash = typeHash(T, nil) +// } +// // look for duplicate types +// if other := seen[hash]; other != nil { +// // talk about "case" rather than "type" because of nil case +// Ts := "nil" +// if T != nil { +// Ts = TypeString(T, check.qualifier) +// } +// var err error_ +// err.errorf(e, "duplicate case %s in type switch", Ts) +// err.errorf(other, "previous case") +// check.report(&err) +// continue L +// } +// seen[hash] = e +// if T != nil { +// check.typeAssertion(e.Pos(), x, xtyp, T) +// } +// } +// return +// } + // stmt typechecks statement s. func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) { // statements must end with the same top scope as they started with diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 9a4db6fddb..18a9e39300 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -214,7 +214,7 @@ func (subst *subster) typ(typ Type) Type { } // before creating a new named type, check if we have this one already - h := instantiatedHash(t, newTArgs) + h := typeHash(t, newTArgs) dump(">>> new type hash: %s", h) if named, found := subst.typMap[h]; found { dump(">>> found %s", named) @@ -253,17 +253,29 @@ func (subst *subster) typ(typ Type) Type { return typ } -var instanceHashing = 0 +var typeHashing = 0 -func instantiatedHash(typ *Named, targs []Type) string { +// typeHash returns a string representation of typ, which can be used as an exact +// type hash: types that are identical produce identical string representations. +// If typ is a *Named type and targs is not empty, typ is printed as if it were +// instantiated with targs. +func typeHash(typ Type, targs []Type) string { + assert(typ != nil) var buf bytes.Buffer - assert(instanceHashing == 0) - instanceHashing++ + assert(typeHashing == 0) + typeHashing++ w := newTypeWriter(&buf, nil) - w.typeName(typ.obj) - w.typeList(targs) - instanceHashing-- + if named, _ := typ.(*Named); named != nil && len(targs) > 0 { + // Don't use WriteType because we need to use the provided targs + // and not any targs that might already be with the *Named type. + w.typeName(named.obj) + w.typeList(targs) + } else { + assert(targs == nil) + w.typ(typ) + } + typeHashing-- if debug { // there should be no instance markers in type hashes diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 3b9981089e..2110b46498 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -207,7 +207,7 @@ func (w *typeWriter) typ(typ Type) { // types. Write them to aid debugging, but don't write // them when we need an instance hash: whether a type // is fully expanded or not doesn't matter for identity. - if instanceHashing == 0 && t.instPos != nil { + if typeHashing == 0 && t.instPos != nil { w.byte(instanceMarker) } w.typeName(t.obj) @@ -291,7 +291,7 @@ func (w *typeWriter) tParamList(list []*TypeParam) { func (w *typeWriter) typeName(obj *TypeName) { if obj == nil { - assert(instanceHashing == 0) // we need an object for instance hashing + assert(typeHashing == 0) // we need an object for type hashing w.string("") return } @@ -300,17 +300,18 @@ func (w *typeWriter) typeName(obj *TypeName) { } w.string(obj.name) - if instanceHashing != 0 { + if typeHashing != 0 { // For local defined types, use the (original!) TypeName's scope // numbers to disambiguate. - typ := obj.typ.(*Named) - // TODO(gri) Figure out why typ.orig != typ.orig.orig sometimes - // and whether the loop can iterate more than twice. - // (It seems somehow connected to instance types.) - for typ.orig != typ { - typ = typ.orig + if typ, _ := obj.typ.(*Named); typ != nil { + // TODO(gri) Figure out why typ.orig != typ.orig.orig sometimes + // and whether the loop can iterate more than twice. + // (It seems somehow connected to instance types.) + for typ.orig != typ { + typ = typ.orig + } + w.writeScopeNumbers(typ.obj.parent) } - w.writeScopeNumbers(typ.obj.parent) } } @@ -332,7 +333,8 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) { if i > 0 { w.string(", ") } - if v.name != "" { + // parameter names are ignored for type identity and thus type hashes + if typeHashing == 0 && v.name != "" { w.string(v.name) w.byte(' ') } @@ -380,8 +382,8 @@ func (w *typeWriter) signature(sig *Signature) { } w.byte(' ') - if n == 1 && sig.results.vars[0].name == "" { - // single unnamed result + if n == 1 && (typeHashing != 0 || sig.results.vars[0].name == "") { + // single unnamed result (if typeHashing, name must be ignored) w.typ(sig.results.vars[0].typ) return } -- GitLab From b06cfe9b25a9cd6ef6ff482b9cd08b2f709131b0 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sat, 28 Aug 2021 18:19:36 -0700 Subject: [PATCH 0908/2500] cmd/compile/internal/types2: eliminate typeHashing global variable Instead, keep track of hashing mode with a typeWriter field. Introduce a new constructor (newTypeHasher) to set the mode. Change-Id: Ie69cc0382532c75973794326be15c884b7fdcb76 Reviewed-on: https://go-review.googlesource.com/c/go/+/345929 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/subst.go | 13 ++++--------- src/cmd/compile/internal/types2/typestring.go | 19 ++++++++++++------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 18a9e39300..c67538d4f0 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -253,8 +253,6 @@ func (subst *subster) typ(typ Type) Type { return typ } -var typeHashing = 0 - // typeHash returns a string representation of typ, which can be used as an exact // type hash: types that are identical produce identical string representations. // If typ is a *Named type and targs is not empty, typ is printed as if it were @@ -263,19 +261,16 @@ func typeHash(typ Type, targs []Type) string { assert(typ != nil) var buf bytes.Buffer - assert(typeHashing == 0) - typeHashing++ - w := newTypeWriter(&buf, nil) + h := newTypeHasher(&buf) if named, _ := typ.(*Named); named != nil && len(targs) > 0 { // Don't use WriteType because we need to use the provided targs // and not any targs that might already be with the *Named type. - w.typeName(named.obj) - w.typeList(targs) + h.typeName(named.obj) + h.typeList(targs) } else { assert(targs == nil) - w.typ(typ) + h.typ(typ) } - typeHashing-- if debug { // there should be no instance markers in type hashes diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 2110b46498..3582d183a8 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -62,10 +62,15 @@ type typeWriter struct { buf *bytes.Buffer seen map[Type]bool qf Qualifier + hash bool } func newTypeWriter(buf *bytes.Buffer, qf Qualifier) *typeWriter { - return &typeWriter{buf, make(map[Type]bool), qf} + return &typeWriter{buf, make(map[Type]bool), qf, false} +} + +func newTypeHasher(buf *bytes.Buffer) *typeWriter { + return &typeWriter{buf, make(map[Type]bool), nil, true} } func (w *typeWriter) byte(b byte) { w.buf.WriteByte(b) } @@ -207,7 +212,7 @@ func (w *typeWriter) typ(typ Type) { // types. Write them to aid debugging, but don't write // them when we need an instance hash: whether a type // is fully expanded or not doesn't matter for identity. - if typeHashing == 0 && t.instPos != nil { + if !w.hash && t.instPos != nil { w.byte(instanceMarker) } w.typeName(t.obj) @@ -291,7 +296,7 @@ func (w *typeWriter) tParamList(list []*TypeParam) { func (w *typeWriter) typeName(obj *TypeName) { if obj == nil { - assert(typeHashing == 0) // we need an object for type hashing + assert(!w.hash) // we need an object for type hashing w.string("") return } @@ -300,7 +305,7 @@ func (w *typeWriter) typeName(obj *TypeName) { } w.string(obj.name) - if typeHashing != 0 { + if w.hash { // For local defined types, use the (original!) TypeName's scope // numbers to disambiguate. if typ, _ := obj.typ.(*Named); typ != nil { @@ -334,7 +339,7 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) { w.string(", ") } // parameter names are ignored for type identity and thus type hashes - if typeHashing == 0 && v.name != "" { + if !w.hash && v.name != "" { w.string(v.name) w.byte(' ') } @@ -382,8 +387,8 @@ func (w *typeWriter) signature(sig *Signature) { } w.byte(' ') - if n == 1 && (typeHashing != 0 || sig.results.vars[0].name == "") { - // single unnamed result (if typeHashing, name must be ignored) + if n == 1 && (w.hash || sig.results.vars[0].name == "") { + // single unnamed result (if type hashing, name must be ignored) w.typ(sig.results.vars[0].typ) return } -- GitLab From 3342aa5f51e1299e9d86307e2dbf429cd2aca987 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sun, 29 Aug 2021 10:57:06 -0700 Subject: [PATCH 0909/2500] cmd/compile/internal/types2: more systematic error handling in typeWriter When using a typeWriter for debugging/error message type strings, it shouldn't crash in the presence of type-checker internal bugs. But when a typeHasher is used, we don't want to silently ignore errors. Introduce an error method that panics in type hashing mode but prints an error value otherwise. Also fixed an incorrect 'if' statement in tParamList. Change-Id: I26c8b8e0b14396e91ad71bf903e36ce1ca55839e Reviewed-on: https://go-review.googlesource.com/c/go/+/346009 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/typestring.go | 82 +++++++++---------- 1 file changed, 40 insertions(+), 42 deletions(-) diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 3582d183a8..204e20c7ff 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -55,6 +55,14 @@ func WriteType(buf *bytes.Buffer, typ Type, qf Qualifier) { newTypeWriter(buf, qf).typ(typ) } +// WriteSignature writes the representation of the signature sig to buf, +// without a leading "func" keyword. +// The Qualifier controls the printing of +// package-level objects, and may be nil. +func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) { + newTypeWriter(buf, qf).signature(sig) +} + // instanceMarker is the prefix for an instantiated type in unexpanded form. const instanceMarker = '#' @@ -76,10 +84,16 @@ func newTypeHasher(buf *bytes.Buffer) *typeWriter { func (w *typeWriter) byte(b byte) { w.buf.WriteByte(b) } func (w *typeWriter) string(s string) { w.buf.WriteString(s) } func (w *typeWriter) writef(format string, args ...interface{}) { fmt.Fprintf(w.buf, format, args...) } +func (w *typeWriter) error(msg string) { + if w.hash { + panic(msg) + } + w.string("<" + msg + ">") +} func (w *typeWriter) typ(typ Type) { if w.seen[typ] { - w.writef("○%T", goTypeName(typ)) // cycle to typ + w.error("cycle to " + goTypeName(typ)) return } w.seen[typ] = true @@ -87,7 +101,7 @@ func (w *typeWriter) typ(typ Type) { switch t := typ.(type) { case nil: - w.string("") + w.error("nil") case *Basic: // exported basic types go into package unsafe @@ -143,7 +157,8 @@ func (w *typeWriter) typ(typ Type) { // Unions only appear as (syntactic) embedded elements // in interfaces and syntactically cannot be empty. if t.Len() == 0 { - panic("empty union") + w.error("empty union") + break } for i, t := range t.terms { if i > 0 { @@ -196,7 +211,8 @@ func (w *typeWriter) typ(typ Type) { case RecvOnly: s = "<-chan " default: - unreachable() + w.error("unknown channel direction") + break } w.string(s) if parens { @@ -225,21 +241,21 @@ func (w *typeWriter) typ(typ Type) { } case *TypeParam: - s := "?" - if t.obj != nil { - // Optionally write out package for typeparams (like Named). - // TODO(danscales): this is required for import/export, so - // we maybe need a separate function that won't be changed - // for debugging purposes. - if t.obj.pkg != nil { - writePackage(w.buf, t.obj.pkg, w.qf) - } - s = t.obj.name + if t.obj == nil { + w.error("unnamed type parameter") + break } - w.string(s + subscript(t.id)) + // Optionally write out package for typeparams (like Named). + // TODO(danscales): this is required for import/export, so + // we maybe need a separate function that won't be changed + // for debugging purposes. + if t.obj.pkg != nil { + writePackage(w.buf, t.obj.pkg, w.qf) + } + w.string(t.obj.name + subscript(t.id)) case *top: - w.string("⊤") + w.error("⊤") default: // For externally defined implementations of Type. @@ -266,26 +282,20 @@ func (w *typeWriter) tParamList(list []*TypeParam) { // Determine the type parameter and its constraint. // list is expected to hold type parameter names, // but don't crash if that's not the case. - var bound Type - if tpar != nil { - bound = tpar.bound // should not be nil but we want to see it if it is + if tpar == nil { + w.error("nil type parameter") + continue } - if i > 0 { - if bound != prev { + if tpar.bound != prev { // bound changed - write previous one before advancing w.byte(' ') w.typ(prev) } w.string(", ") } - prev = bound - - if tpar != nil { - w.typ(tpar) - } else { - w.string(tpar.obj.name) - } + prev = tpar.bound + w.typ(tpar) } if prev != nil { w.byte(' ') @@ -295,11 +305,6 @@ func (w *typeWriter) tParamList(list []*TypeParam) { } func (w *typeWriter) typeName(obj *TypeName) { - if obj == nil { - assert(!w.hash) // we need an object for type hashing - w.string("") - return - } if obj.pkg != nil { writePackage(w.buf, obj.pkg, w.qf) } @@ -352,7 +357,8 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) { // special case: // append(s, "foo"...) leads to signature func([]byte, string...) if t := asBasic(typ); t == nil || t.kind != String { - panic("expected string type") + w.error("expected string type") + continue } w.typ(typ) w.string("...") @@ -365,14 +371,6 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) { w.byte(')') } -// WriteSignature writes the representation of the signature sig to buf, -// without a leading "func" keyword. -// The Qualifier controls the printing of -// package-level objects, and may be nil. -func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) { - newTypeWriter(buf, qf).signature(sig) -} - func (w *typeWriter) signature(sig *Signature) { if sig.TParams().Len() != 0 { w.tParamList(sig.TParams().list()) -- GitLab From 7622e41c84fd9bb003a2d905b9f0545344842c3a Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 30 Aug 2021 17:40:45 -0400 Subject: [PATCH 0910/2500] go/types, types2: add a test for invalid import of "init" This error reporting code path did not have test coverage, and panics in 1.17 (filed as #48082). Add a test that would have reproduced the panic, for both go/types and cmd/compile/internal/types2. Change-Id: Icd5f54f8407e4ab57d432f44a129ecf6b2755feb Reviewed-on: https://go-review.googlesource.com/c/go/+/346309 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- .../internal/types2/testdata/fixedbugs/issue48082.src | 7 +++++++ src/go/types/testdata/fixedbugs/issue48082.src | 7 +++++++ 2 files changed, 14 insertions(+) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue48082.src create mode 100644 src/go/types/testdata/fixedbugs/issue48082.src diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48082.src b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48082.src new file mode 100644 index 0000000000..5395154978 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48082.src @@ -0,0 +1,7 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package issue48082 + +import "init" /* ERROR init must be a func */ /* ERROR could not import init */ diff --git a/src/go/types/testdata/fixedbugs/issue48082.src b/src/go/types/testdata/fixedbugs/issue48082.src new file mode 100644 index 0000000000..5395154978 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue48082.src @@ -0,0 +1,7 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package issue48082 + +import "init" /* ERROR init must be a func */ /* ERROR could not import init */ -- GitLab From d384ebde60a7e720f83fb10e6fa9cbf989a8866f Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 30 Aug 2021 16:00:53 +0200 Subject: [PATCH 0911/2500] net: enable multicast listener tests on solaris/illumos It seems everything is in place for these tests to pass on solaris and illumos, so enable them. Fixes #7399 Change-Id: If6defb651ef9c5059c1aeccbc4fc13a12a86b682 Reviewed-on: https://go-review.googlesource.com/c/go/+/346149 Trust: Tobias Klauser Trust: Damien Neil Run-TryBot: Tobias Klauser Run-TryBot: Damien Neil TryBot-Result: Go Bot Reviewed-by: Damien Neil --- src/net/listen_test.go | 4 ---- src/net/sockoptip_stub.go | 6 ------ 2 files changed, 10 deletions(-) diff --git a/src/net/listen_test.go b/src/net/listen_test.go index b1dce29ac2..50355de1ac 100644 --- a/src/net/listen_test.go +++ b/src/net/listen_test.go @@ -535,8 +535,6 @@ func TestIPv4MulticastListener(t *testing.T) { switch runtime.GOOS { case "android", "plan9": t.Skipf("not supported on %s", runtime.GOOS) - case "solaris", "illumos": - t.Skipf("not supported on solaris or illumos, see golang.org/issue/7399") } if !supportsIPv4() { t.Skip("IPv4 is not supported") @@ -610,8 +608,6 @@ func TestIPv6MulticastListener(t *testing.T) { switch runtime.GOOS { case "plan9": t.Skipf("not supported on %s", runtime.GOOS) - case "solaris", "illumos": - t.Skipf("not supported on solaris or illumos, see issue 7399") } if !supportsIPv6() { t.Skip("IPv6 is not supported") diff --git a/src/net/sockoptip_stub.go b/src/net/sockoptip_stub.go index 4175922cec..92349d88ba 100644 --- a/src/net/sockoptip_stub.go +++ b/src/net/sockoptip_stub.go @@ -10,31 +10,25 @@ package net import "syscall" func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error { - // See golang.org/issue/7399. return syscall.ENOPROTOOPT } func setIPv4MulticastLoopback(fd *netFD, v bool) error { - // See golang.org/issue/7399. return syscall.ENOPROTOOPT } func joinIPv4Group(fd *netFD, ifi *Interface, ip IP) error { - // See golang.org/issue/7399. return syscall.ENOPROTOOPT } func setIPv6MulticastInterface(fd *netFD, ifi *Interface) error { - // See golang.org/issue/7399. return syscall.ENOPROTOOPT } func setIPv6MulticastLoopback(fd *netFD, v bool) error { - // See golang.org/issue/7399. return syscall.ENOPROTOOPT } func joinIPv6Group(fd *netFD, ifi *Interface, ip IP) error { - // See golang.org/issue/7399. return syscall.ENOPROTOOPT } -- GitLab From f118d145a56be294e578fb20e0e2fdde2a92846d Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 30 Aug 2021 01:01:20 -0700 Subject: [PATCH 0912/2500] cmd/compile: make unified IR more selective about method wrappers This CL makes two changes to how unified IR emits method wrappers: 1. It no longer emits wrappers for defined types' underlying types. Previously, a declaration like `type T struct { U }` would emit wrappers for both `T` and `struct { U }`. Now they're only emitted for `T`. 2. It emits method value wrappers only when OMETHVALUE nodes are actually created, like how -G=0 works. Method values are relatively rare, aren't needed for runtime type descriptors (unlike method expression wrappers), and large projects end up spending a non-trivial amount of time compiling these unneeded wrappers. Change-Id: I21da97df3132ec12cc67debf62b5b2d282f481cf Reviewed-on: https://go-review.googlesource.com/c/go/+/346230 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/noder/reader.go | 149 ++++++++++++++--------- src/cmd/compile/internal/walk/closure.go | 4 + 2 files changed, 98 insertions(+), 55 deletions(-) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index e7a9d9655b..e874240bbc 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -295,7 +295,13 @@ func (r *reader) doPkg() *types.Pkg { // @@@ Types func (r *reader) typ() *types.Type { - return r.p.typIdx(r.typInfo(), r.dict) + return r.typWrapped(true) +} + +// typWrapped is like typ, but allows suppressing generation of +// unnecessary wrappers as a compile-time optimization. +func (r *reader) typWrapped(wrapped bool) *types.Type { + return r.p.typIdx(r.typInfo(), r.dict, wrapped) } func (r *reader) typInfo() typeInfo { @@ -306,7 +312,7 @@ func (r *reader) typInfo() typeInfo { return typeInfo{idx: r.reloc(relocType), derived: false} } -func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict) *types.Type { +func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict, wrapped bool) *types.Type { idx := info.idx var where **types.Type if info.derived { @@ -370,7 +376,13 @@ func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict) *types.Type { return prev } - *where = typ + if wrapped { + // Only cache if we're adding wrappers, so that other callers that + // find a cached type know it was wrapped. + *where = typ + + r.needWrapper(typ) + } if !typ.IsUntyped() { types.CheckSize(typ) @@ -438,7 +450,7 @@ func (r *reader) interfaceType() *types.Type { if len(fields) == 0 { return types.Types[types.TINTER] // empty interface } - return r.needWrapper(types.NewInterface(tpkg, fields)) + return types.NewInterface(tpkg, fields) } func (r *reader) structType() *types.Type { @@ -459,7 +471,7 @@ func (r *reader) structType() *types.Type { } fields[i] = f } - return r.needWrapper(types.NewStruct(tpkg, fields)) + return types.NewStruct(tpkg, fields) } func (r *reader) signature(tpkg *types.Pkg, recv *types.Field) *types.Type { @@ -507,7 +519,7 @@ func (r *reader) obj() ir.Node { fn := r.dict.funcs[idx] targs := make([]*types.Type, len(fn.explicits)) for i, targ := range fn.explicits { - targs[i] = r.p.typIdx(targ, r.dict) + targs[i] = r.p.typIdx(targ, r.dict, true) } obj = r.p.objIdx(fn.idx, nil, targs) @@ -625,7 +637,7 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node // We need to defer CheckSize until we've called SetUnderlying to // handle recursive types. types.DeferCheckSize() - typ.SetUnderlying(r.typ()) + typ.SetUnderlying(r.typWrapped(false)) types.ResumeCheckSize() methods := make([]*types.Field, r.len()) @@ -636,9 +648,7 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node typ.Methods().Set(methods) } - if !typ.IsPtr() { - r.needWrapper(typ) - } + r.needWrapper(typ) return name @@ -1537,7 +1547,19 @@ func (r *reader) expr() (res ir.Node) { x := r.expr() pos := r.pos() _, sym := r.selector() - return typecheck.Expr(ir.NewSelectorExpr(pos, ir.OXDOT, x, sym)) + n := typecheck.Expr(ir.NewSelectorExpr(pos, ir.OXDOT, x, sym)).(*ir.SelectorExpr) + if n.Op() == ir.OMETHVALUE { + wrapper := methodValueWrapper{ + rcvr: n.X.Type(), + method: n.Selection, + } + if r.importedDef() { + haveMethodValueWrappers = append(haveMethodValueWrappers, wrapper) + } else { + needMethodValueWrappers = append(needMethodValueWrappers, wrapper) + } + } + return n case exprIndex: x := r.expr() @@ -2128,11 +2150,36 @@ var needWrapperTypes []*types.Type // method wrappers, because we found the type in an imported package. var haveWrapperTypes []*types.Type -func (r *reader) needWrapper(typ *types.Type) *types.Type { +// needMethodValueWrappers lists methods for which we may need to +// generate method value wrappers. +var needMethodValueWrappers []methodValueWrapper + +// haveMethodValueWrappers lists methods for which we know we already +// have method value wrappers, because we found it in an imported +// package. +var haveMethodValueWrappers []methodValueWrapper + +type methodValueWrapper struct { + rcvr *types.Type + method *types.Field +} + +func (r *reader) needWrapper(typ *types.Type) { if typ.IsPtr() { - base.Fatalf("bad pointer type: %v", typ) + return + } + + // If a type was found in an imported package, then we can assume + // that package (or one of its transitive dependencies) already + // generated method wrappers for it. + if r.importedDef() { + haveWrapperTypes = append(haveWrapperTypes, typ) + } else { + needWrapperTypes = append(needWrapperTypes, typ) } +} +func (r *reader) importedDef() bool { // If a type was found in an imported package, then we can assume // that package (or one of its transitive dependencies) already // generated method wrappers for it. @@ -2144,13 +2191,7 @@ func (r *reader) needWrapper(typ *types.Type) *types.Type { // TODO(mdempsky): Distinguish when a generic function or type was // instantiated in an imported package so that we can add types to // haveWrapperTypes instead. - if r.p != localPkgReader && !r.hasTypeParams() { - haveWrapperTypes = append(haveWrapperTypes, typ) - } else { - needWrapperTypes = append(needWrapperTypes, typ) - } - - return typ + return r.p != localPkgReader && !r.hasTypeParams() } func (r *reader) wrapTypes(target *ir.Package) { @@ -2158,37 +2199,43 @@ func (r *reader) wrapTypes(target *ir.Package) { r.needWrapper(types.ErrorType) seen := make(map[string]*types.Type) - addType := func(typ *types.Type) bool { - if typ.Sym() != nil { - return true - } - - key := typ.LinkString() - if prev := seen[key]; prev != nil { - if !types.Identical(typ, prev) { - base.Fatalf("collision: types %v and %v have short string %q", typ, prev, key) - } - return false - } - - seen[key] = typ - return true - } for _, typ := range haveWrapperTypes { - addType(typ) + r.wrapType(typ, target, seen, false) } haveWrapperTypes = nil for _, typ := range needWrapperTypes { - if addType(typ) { - r.wrapType(typ, target) - } + r.wrapType(typ, target, seen, true) } needWrapperTypes = nil + + for _, wrapper := range haveMethodValueWrappers { + r.methodValueWrapper(wrapper.rcvr, wrapper.method, target, false) + } + haveMethodValueWrappers = nil + + for _, wrapper := range needMethodValueWrappers { + r.methodValueWrapper(wrapper.rcvr, wrapper.method, target, true) + } + needMethodValueWrappers = nil } -func (r *reader) wrapType(typ *types.Type, target *ir.Package) { +func (r *reader) wrapType(typ *types.Type, target *ir.Package, seen map[string]*types.Type, needed bool) { + key := typ.LinkString() + if prev := seen[key]; prev != nil { + if !types.Identical(typ, prev) { + base.Fatalf("collision: types %v and %v have link string %q", typ, prev, key) + } + return + } + seen[key] = typ + + if !needed { + // Only called to add to 'seen'. + return + } + if !typ.IsInterface() { typecheck.CalcMethods(typ) } @@ -2197,8 +2244,6 @@ func (r *reader) wrapType(typ *types.Type, target *ir.Package) { base.FatalfAt(meth.Pos, "invalid method: %v", meth) } - r.methodValueWrapper(typ, meth, target) - r.methodWrapper(0, typ, meth, target) // For non-interface types, we also want *T wrappers. @@ -2221,7 +2266,7 @@ func (r *reader) methodWrapper(derefs int, tbase *types.Type, method *types.Fiel } sym := ir.MethodSym(wrapper, method.Sym) - assert(!sym.Siggen()) + base.Assertf(!sym.Siggen(), "already generated wrapper %v", sym) sym.SetSiggen(true) wrappee := method.Type.Recv().Type @@ -2257,17 +2302,11 @@ func (r *reader) methodWrapper(derefs int, tbase *types.Type, method *types.Fiel r.finishWrapperFunc(fn, target) } -func (r *reader) methodValueWrapper(tbase *types.Type, method *types.Field, target *ir.Package) { - recvType := tbase - if !tbase.IsInterface() { - recvType = method.Type.Recv().Type - if !types.Identical(tbase, types.ReceiverBaseType(recvType)) { - return - } - } - +func (r *reader) methodValueWrapper(recvType *types.Type, method *types.Field, target *ir.Package, needed bool) { sym := ir.MethodSymSuffix(recvType, method.Sym, "-fm") - assert(!sym.Uniq()) + if sym.Uniq() { + return + } sym.SetUniq(true) // TODO(mdempsky): Use method.Pos instead? @@ -2279,7 +2318,7 @@ func (r *reader) methodValueWrapper(tbase *types.Type, method *types.Field, targ // Declare and initialize variable holding receiver. recv := ir.NewHiddenParam(pos, fn, typecheck.Lookup(".this"), recvType) - if !reflectdata.NeedEmit(tbase) { + if !needed { typecheck.Func(fn) return } diff --git a/src/cmd/compile/internal/walk/closure.go b/src/cmd/compile/internal/walk/closure.go index 902e01ef38..40535afa7a 100644 --- a/src/cmd/compile/internal/walk/closure.go +++ b/src/cmd/compile/internal/walk/closure.go @@ -218,6 +218,10 @@ func methodValueWrapper(dot *ir.SelectorExpr) *ir.Name { } sym.SetUniq(true) + if base.Debug.Unified != 0 && base.Debug.UnifiedQuirks == 0 { + base.FatalfAt(dot.Pos(), "missing wrapper for %v", meth) + } + savecurfn := ir.CurFunc saveLineNo := base.Pos ir.CurFunc = nil -- GitLab From 3920d6f2085559ae262d651b00bf8b29f953580a Mon Sep 17 00:00:00 2001 From: Andy Pan Date: Thu, 6 May 2021 09:04:03 +0800 Subject: [PATCH 0913/2500] runtime: eliminate the redundant for loop in runqget() Change-Id: If9b283bbef3ff12a64d34b07491aee3396852f05 Reviewed-on: https://go-review.googlesource.com/c/go/+/317509 Reviewed-by: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot Trust: Keith Randall --- src/runtime/proc.go | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 55023e3f9f..197441dfa7 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -5994,14 +5994,12 @@ func runqputbatch(pp *p, q *gQueue, qsize int) { // Executed only by the owner P. func runqget(_p_ *p) (gp *g, inheritTime bool) { // If there's a runnext, it's the next G to run. - for { - next := _p_.runnext - if next == 0 { - break - } - if _p_.runnext.cas(next, 0) { - return next.ptr(), true - } + next := _p_.runnext + // If the runnext is non-0 and the CAS fails, it could only have been stolen by another P, + // because other Ps can race to set runnext to 0, but only the current P can set it to non-0. + // Hence, there's no need to retry this CAS if it falls. + if next != 0 && _p_.runnext.cas(next, 0) { + return next.ptr(), true } for { -- GitLab From ded10d75a908b584331d01c9c0eaf1cfcb951cac Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 30 Aug 2021 17:18:07 -0700 Subject: [PATCH 0914/2500] cmd/compile/internal/types2: remove superfluous ordinaryType calls The value types in type assertions and type switches cannot be constraint types (if there are, an error was reported earlier), so there is no need to check again that they are not constraint types. This permits merging the ordinaryType call with varType, which is the only place where it's needed. Change-Id: I44a852377b3dddf53692f764e588801fb3d3c0a8 Reviewed-on: https://go-review.googlesource.com/c/go/+/346291 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/expr.go | 1 - src/cmd/compile/internal/types2/stmt.go | 1 - .../types2/testdata/fixedbugs/issue42758.go2 | 2 +- src/cmd/compile/internal/types2/typexpr.go | 13 +++++-------- 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 86a8444ee2..799874624d 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -1417,7 +1417,6 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin check.errorf(x, "%s is not an interface type", x) goto Error } - check.ordinaryType(x.Pos(), xtyp) // x.(type) expressions are encoded via TypeSwitchGuards if e.Type == nil { check.error(e, invalidAST+"invalid use of AssertExpr") diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index 2673e98c57..3231fbec93 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -751,7 +751,6 @@ func (check *Checker) typeSwitchStmt(inner stmtContext, s *syntax.SwitchStmt, gu check.errorf(&x, "%s is not an interface type", &x) return } - check.ordinaryType(x.Pos(), xtyp) check.multipleSwitchDefaults(s.Body) diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue42758.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue42758.go2 index bf0031f5d2..dd66e9648b 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue42758.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue42758.go2 @@ -28,6 +28,6 @@ func _[T constraint](x interface{}){ } func _(x constraint /* ERROR contains type constraints */ ) { - switch x /* ERROR contains type constraints */ .(type) { + switch x.(type) { // no need to report another error } } diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 33e7559cc9..73b143ce1b 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -134,22 +134,17 @@ func (check *Checker) typ(e syntax.Expr) Type { } // varType type-checks the type expression e and returns its type, or Typ[Invalid]. -// The type must not be an (uninstantiated) generic type and it must be ordinary -// (see ordinaryType). +// The type must not be an (uninstantiated) generic type and it must not be a +// constraint interface. func (check *Checker) varType(e syntax.Expr) Type { typ := check.definedType(e, nil) - check.ordinaryType(syntax.StartPos(e), typ) - return typ -} -// ordinaryType reports an error if typ is an interface type containing -// type lists or is (or embeds) the predeclared type comparable. -func (check *Checker) ordinaryType(pos syntax.Pos, typ Type) { // We don't want to call under() (via asInterface) or complete interfaces while we // are in the middle of type-checking parameter declarations that might belong to // interface methods. Delay this check to the end of type-checking. check.later(func() { if t := asInterface(typ); t != nil { + pos := syntax.StartPos(e) tset := computeInterfaceTypeSet(check, pos, t) // TODO(gri) is this the correct position? if tset.IsConstraint() { if tset.comparable { @@ -160,6 +155,8 @@ func (check *Checker) ordinaryType(pos syntax.Pos, typ Type) { } } }) + + return typ } // anyType type-checks the type expression e and returns its type, or Typ[Invalid]. -- GitLab From 605d1aaea26ef775369a3d1da6cf53f2a7b1e640 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 30 Aug 2021 18:07:54 -0700 Subject: [PATCH 0915/2500] go/types, types2: union terms must be instantiated Fixes #48083. Change-Id: I77899d3e6edc806dee770403b3c3c4e2974d0e50 Reviewed-on: https://go-review.googlesource.com/c/go/+/346293 Trust: Robert Griesemer Reviewed-by: Robert Findley --- .../internal/types2/testdata/fixedbugs/issue48083.go2 | 9 +++++++++ src/cmd/compile/internal/types2/union.go | 2 +- src/go/types/testdata/fixedbugs/issue48083.go2 | 9 +++++++++ src/go/types/union.go | 2 +- 4 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue48083.go2 create mode 100644 src/go/types/testdata/fixedbugs/issue48083.go2 diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48083.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48083.go2 new file mode 100644 index 0000000000..3dae51415d --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48083.go2 @@ -0,0 +1,9 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T[P any] struct{} + +type _ interface{ int | T /* ERROR cannot use generic type */ } \ No newline at end of file diff --git a/src/cmd/compile/internal/types2/union.go b/src/cmd/compile/internal/types2/union.go index 933e5a2951..d4c749a89b 100644 --- a/src/cmd/compile/internal/types2/union.go +++ b/src/cmd/compile/internal/types2/union.go @@ -122,7 +122,7 @@ func parseTilde(check *Checker, x syntax.Expr) (tilde bool, typ Type) { x = op.X tilde = true } - typ = check.anyType(x) + typ = check.typ(x) // embedding stand-alone type parameters is not permitted (issue #47127). if _, ok := under(typ).(*TypeParam); ok { check.error(x, "cannot embed a type parameter") diff --git a/src/go/types/testdata/fixedbugs/issue48083.go2 b/src/go/types/testdata/fixedbugs/issue48083.go2 new file mode 100644 index 0000000000..3dae51415d --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue48083.go2 @@ -0,0 +1,9 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T[P any] struct{} + +type _ interface{ int | T /* ERROR cannot use generic type */ } \ No newline at end of file diff --git a/src/go/types/union.go b/src/go/types/union.go index 1ba99adaca..f6b32b9e5d 100644 --- a/src/go/types/union.go +++ b/src/go/types/union.go @@ -125,7 +125,7 @@ func parseTilde(check *Checker, x ast.Expr) (tilde bool, typ Type) { x = op.X tilde = true } - typ = check.anyType(x) + typ = check.typ(x) // embedding stand-alone type parameters is not permitted (issue #47127). if _, ok := under(typ).(*TypeParam); ok { check.error(x, _Todo, "cannot embed a type parameter") -- GitLab From 68152359fdd45e8d51aaaec64075aad4ff8f68b2 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 30 Aug 2021 20:30:25 -0700 Subject: [PATCH 0916/2500] cmd/compile/internal/types2: disallow aliases for generic types The existing approach (alias name stands for generic type name) is an exception: it's the only place where a generic type could be used without explicit instantiation. The correct solution is currently under discussion (see proposal issue #46477). This CL requires that the RHS of an alias type declaration be an instantiated non-generic type. If #46477 is accepted, the implementation will require proper representation of alias types. Change-Id: Ie85b923213a64f39837e56e38e14757458272b93 Reviewed-on: https://go-review.googlesource.com/c/go/+/346294 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/decl.go | 2 +- .../types2/testdata/check/typeinst.go2 | 10 ++++++---- .../types2/testdata/fixedbugs/issue39768.go2 | 6 +++--- .../types2/testdata/fixedbugs/issue47968.go2 | 2 +- src/cmd/compile/internal/types2/typexpr.go | 18 ++++++------------ test/typeparam/aliasimp.dir/main.go | 13 ++++++++----- 6 files changed, 25 insertions(+), 26 deletions(-) diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index d7a33546aa..b61d282b14 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -555,7 +555,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named } obj.typ = Typ[Invalid] - rhs = check.anyType(tdecl.Type) + rhs = check.varType(tdecl.Type) obj.typ = rhs return } diff --git a/src/cmd/compile/internal/types2/testdata/check/typeinst.go2 b/src/cmd/compile/internal/types2/testdata/check/typeinst.go2 index 0d628cb9d0..3fab2cb9ad 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeinst.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeinst.go2 @@ -17,13 +17,15 @@ type T2[P any] struct { type List[P any] []P -// Alias type declarations cannot have type parameters. Syntax error. +// Alias type declarations cannot have type parameters. +// Issue #46477 proposses to change that. type A1[P any] = /* ERROR cannot be alias */ P -// But an alias may refer to a generic, uninstantiated type. -type A2 = List +// Pending clarification of #46477 we disallow aliases +// of generic types. +type A2 = List // ERROR cannot use generic type var _ A2[int] -var _ A2 /* ERROR without instantiation */ +var _ A2 type A3 = List[int] var _ A3 diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39768.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39768.go2 index abac141d7f..fb522733e0 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39768.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39768.go2 @@ -5,9 +5,9 @@ package p type T[P any] P -type A = T +type A = T // ERROR cannot use generic type var x A[int] -var _ A /* ERROR cannot use generic type */ +var _ A type B = T[int] var y B = x @@ -16,5 +16,5 @@ var _ B /* ERROR not a generic type */ [int] // test case from issue type Vector[T any] []T -type VectorAlias = Vector +type VectorAlias = Vector // ERROR cannot use generic type var v Vector[int] diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47968.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47968.go2 index bbbe6805f2..711e50a55a 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47968.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47968.go2 @@ -8,7 +8,7 @@ type T[P any] struct{} func (T[P]) m1() -type A1 = T +type A1 = T // ERROR cannot use generic type func (A1[P]) m2() {} diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 73b143ce1b..f3db3bbba9 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -38,12 +38,15 @@ func (check *Checker) ident(x *operand, e *syntax.Name, def *Named, wantType boo } return case universeAny, universeComparable: - // complain if necessary but keep going + // complain if necessary if !check.allowVersion(check.pkg, 1, 18) { - check.softErrorf(e, "undeclared name: %s (requires version go1.18 or later)", e.Value) - } else if obj == universeAny { + check.errorf(e, "undeclared name: %s (requires version go1.18 or later)", e.Value) + return // avoid follow-on errors + } + if obj == universeAny { // If we allow "any" for general use, this if-statement can be removed (issue #33232). check.softErrorf(e, "cannot use any outside constraint position") + // ok to continue } } check.recordUse(e, obj) @@ -159,15 +162,6 @@ func (check *Checker) varType(e syntax.Expr) Type { return typ } -// anyType type-checks the type expression e and returns its type, or Typ[Invalid]. -// The type may be generic or instantiated. -func (check *Checker) anyType(e syntax.Expr) Type { - typ := check.typInternal(e, nil) - assert(isTyped(typ)) - check.recordTypeAndValue(e, typexpr, typ, nil) - return typ -} - // definedType is like typ but also accepts a type name def. // If def != nil, e is the type specification for the defined type def, declared // in a type declaration, and def.underlying will be set to the type of e before diff --git a/test/typeparam/aliasimp.dir/main.go b/test/typeparam/aliasimp.dir/main.go index 221a6c758d..24ce95472f 100644 --- a/test/typeparam/aliasimp.dir/main.go +++ b/test/typeparam/aliasimp.dir/main.go @@ -10,16 +10,18 @@ type R[T any] struct { F T } -type S = R +// type S = R // disallowed for now type Sint = R[int] -type Simp = a.Rimp +// type Simp = a.Rimp // disallowed for now -type SimpString Simp[string] +// type SimpString Simp[string] // disallowed for now +type SimpString a.Rimp[string] func main() { - var s S[int] + // var s S[int] // disallowed for now + var s R[int] if s.F != 0 { panic(s.F) } @@ -27,7 +29,8 @@ func main() { if s2.F != 0 { panic(s2.F) } - var s3 Simp[string] + // var s3 Simp[string] // disallowed for now + var s3 a.Rimp[string] if s3.F != "" { panic(s3.F) } -- GitLab From f27d6a23b0b9d2cb41441a5dd2bd6d65dd94acf0 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 31 Aug 2021 09:31:56 -0700 Subject: [PATCH 0917/2500] cmd/compile: builtins may be in the unsafe package Now that unsafe.Sizeof and friends can operate on generic parameters, and evaluate to non-constants, we need to export/import them correctly. Fixes #48094 Change-Id: If3ebf77255385cd5462e13fb7ced8b157ba3cf5b Reviewed-on: https://go-review.googlesource.com/c/go/+/346469 Trust: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Robert Griesemer Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/typecheck/iexport.go | 1 + src/cmd/compile/internal/typecheck/iimport.go | 6 ++++- test/typeparam/issue48094.dir/a.go | 26 +++++++++++++++++++ test/typeparam/issue48094.dir/main.go | 20 ++++++++++++++ test/typeparam/issue48094.go | 7 +++++ 5 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 test/typeparam/issue48094.dir/a.go create mode 100644 test/typeparam/issue48094.dir/main.go create mode 100644 test/typeparam/issue48094.go diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 89eab4df16..f001017a86 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -1692,6 +1692,7 @@ func (w *exportWriter) expr(n ir.Node) { isBuiltin := n.BuiltinOp != ir.OXXX w.bool(isBuiltin) if isBuiltin { + w.bool(n.Sym().Pkg == types.UnsafePkg) w.string(n.Sym().Name) break } diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 0dfc33db20..45bf2563aa 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1269,7 +1269,11 @@ func (r *importReader) node() ir.Node { case ir.ONAME: isBuiltin := r.bool() if isBuiltin { - return types.BuiltinPkg.Lookup(r.string()).Def.(*ir.Name) + pkg := types.BuiltinPkg + if r.bool() { + pkg = types.UnsafePkg + } + return pkg.Lookup(r.string()).Def.(*ir.Name) } return r.localName() diff --git a/test/typeparam/issue48094.dir/a.go b/test/typeparam/issue48094.dir/a.go new file mode 100644 index 0000000000..dd8c16f3ae --- /dev/null +++ b/test/typeparam/issue48094.dir/a.go @@ -0,0 +1,26 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +import "unsafe" + +func F[T any]() uintptr { + var t T + return unsafe.Sizeof(t) +} + +func G[T any]() uintptr { + var t T + return unsafe.Alignof(t) +} + +//func H[T any]() uintptr { +// type S struct { +// a T +// b T +// } +// var s S +// return unsafe.Offsetof(s.b) +//} diff --git a/test/typeparam/issue48094.dir/main.go b/test/typeparam/issue48094.dir/main.go new file mode 100644 index 0000000000..eb1ddbe231 --- /dev/null +++ b/test/typeparam/issue48094.dir/main.go @@ -0,0 +1,20 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "a" + +func main() { + if a.F[int64]() != 8 { + panic("bad") + } + if a.G[int8]() != 1 { + panic("bad") + } + // TODO: enable once 47631 is fixed. + //if a.H[int64]() != 8 { + // panic("bad") + //} +} diff --git a/test/typeparam/issue48094.go b/test/typeparam/issue48094.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/issue48094.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From 144e0b1f6e282e434b2a18ac27c01127d929be81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6hrmann?= Date: Mon, 30 Aug 2021 22:42:17 +0200 Subject: [PATCH 0918/2500] cmd/compile: add MOVOstoreconst with offset folding on amd64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace MOVOstorezero with new MOVOstoreconst. MOVOstoreconst has similar address folding rules then other MOVstoreconst operations but only supports zero as store value. Currently only MOVO stores with zero values are generated. Using MOVOstoreconst with SymValAndOff aux has the advantage that we can just add one more MOVstoreconst variant to the existing rules. The main effect of this CL is converting 16 byte zeroing of a value on the stack from LEAQ+MOVUPS to just MOVUPS which reduces binary size. old: LEAQ 0x20(SP), DX MOVUPS X15, 0(DX) new: MOVUPS X15, 0x20(SP) file before after Δ % addr2line 3661568 3657472 -4096 -0.112% asm 4566432 4562336 -4096 -0.090% cgo 4305456 4301360 -4096 -0.095% compile 22878528 22874512 -4016 -0.018% cover 4517952 4513856 -4096 -0.091% link 6287248 6283152 -4096 -0.065% nm 3640768 3636672 -4096 -0.113% objdump 4010592 4006496 -4096 -0.102% pack 2188224 2184128 -4096 -0.187% pprof 13429504 13421312 -8192 -0.061% trace 10143968 10135776 -8192 -0.081% vet 6868864 6864768 -4096 -0.060% Change-Id: I08f5dd5ab9251448a4572d3ddd1e0c8cd417f5e3 Reviewed-on: https://go-review.googlesource.com/c/go/+/346249 Run-TryBot: Martin Möhrmann TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Martin Möhrmann --- src/cmd/compile/internal/amd64/ssa.go | 10 +- src/cmd/compile/internal/ssa/gen/AMD64.rules | 52 +++-- src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 36 ++-- src/cmd/compile/internal/ssa/opGen.go | 28 +-- src/cmd/compile/internal/ssa/rewriteAMD64.go | 215 ++++++++++++++----- 5 files changed, 235 insertions(+), 106 deletions(-) diff --git a/src/cmd/compile/internal/amd64/ssa.go b/src/cmd/compile/internal/amd64/ssa.go index 30dba057d0..fceb141ae9 100644 --- a/src/cmd/compile/internal/amd64/ssa.go +++ b/src/cmd/compile/internal/amd64/ssa.go @@ -822,7 +822,12 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.To.Type = obj.TYPE_MEM p.To.Reg = v.Args[0].Reg() ssagen.AddAux2(&p.To, v, sc.Off64()) - case ssa.OpAMD64MOVOstorezero: + case ssa.OpAMD64MOVOstoreconst: + sc := v.AuxValAndOff() + if sc.Val() != 0 { + v.Fatalf("MOVO for non zero constants not implemented: %s", v.LongString()) + } + if s.ABI != obj.ABIInternal { // zero X15 manually opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15) @@ -832,7 +837,8 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.From.Reg = x86.REG_X15 p.To.Type = obj.TYPE_MEM p.To.Reg = v.Args[0].Reg() - ssagen.AddAux(&p.To, v) + ssagen.AddAux2(&p.To, v, sc.Off64()) + case ssa.OpAMD64MOVQstoreconstidx1, ssa.OpAMD64MOVQstoreconstidx8, ssa.OpAMD64MOVLstoreconstidx1, ssa.OpAMD64MOVLstoreconstidx4, ssa.OpAMD64MOVWstoreconstidx1, ssa.OpAMD64MOVWstoreconstidx2, ssa.OpAMD64MOVBstoreconstidx1, ssa.OpAMD64ADDLconstmodifyidx1, ssa.OpAMD64ADDLconstmodifyidx4, ssa.OpAMD64ADDLconstmodifyidx8, ssa.OpAMD64ADDQconstmodifyidx1, ssa.OpAMD64ADDQconstmodifyidx8, ssa.OpAMD64ANDLconstmodifyidx1, ssa.OpAMD64ANDLconstmodifyidx4, ssa.OpAMD64ANDLconstmodifyidx8, ssa.OpAMD64ANDQconstmodifyidx1, ssa.OpAMD64ANDQconstmodifyidx8, diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 45c0238317..94fce2d4e5 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -362,26 +362,26 @@ // Adjust zeros to be a multiple of 16 bytes. (Zero [s] destptr mem) && s%16 != 0 && s > 16 && s%16 > 8 && config.useSSE => (Zero [s-s%16] (OffPtr destptr [s%16]) - (MOVOstorezero destptr mem)) + (MOVOstoreconst [makeValAndOff(0,0)] destptr mem)) (Zero [s] destptr mem) && s%16 != 0 && s > 16 && s%16 <= 8 && config.useSSE => (Zero [s-s%16] (OffPtr destptr [s%16]) - (MOVQstoreconst [makeValAndOff(0,0)] destptr mem)) + (MOVOstoreconst [makeValAndOff(0,0)] destptr mem)) (Zero [16] destptr mem) && config.useSSE => - (MOVOstorezero destptr mem) + (MOVOstoreconst [makeValAndOff(0,0)] destptr mem) (Zero [32] destptr mem) && config.useSSE => - (MOVOstorezero (OffPtr destptr [16]) - (MOVOstorezero destptr mem)) + (MOVOstoreconst [makeValAndOff(0,16)] destptr + (MOVOstoreconst [makeValAndOff(0,0)] destptr mem)) (Zero [48] destptr mem) && config.useSSE => - (MOVOstorezero (OffPtr destptr [32]) - (MOVOstorezero (OffPtr destptr [16]) - (MOVOstorezero destptr mem))) + (MOVOstoreconst [makeValAndOff(0,32)] destptr + (MOVOstoreconst [makeValAndOff(0,16)] destptr + (MOVOstoreconst [makeValAndOff(0,0)] destptr mem))) (Zero [64] destptr mem) && config.useSSE => - (MOVOstorezero (OffPtr destptr [48]) - (MOVOstorezero (OffPtr destptr [32]) - (MOVOstorezero (OffPtr destptr [16]) - (MOVOstorezero destptr mem)))) + (MOVOstoreconst [makeValAndOff(0,48)] destptr + (MOVOstoreconst [makeValAndOff(0,32)] destptr + (MOVOstoreconst [makeValAndOff(0,16)] destptr + (MOVOstoreconst [makeValAndOff(0,0)] destptr mem)))) // Medium zeroing uses a duff device. (Zero [s] destptr mem) @@ -1134,8 +1134,8 @@ (MOVBstoreconst [makeValAndOff(int32(int8(c)),off)] {sym} ptr mem) // Fold address offsets into constant stores. -(MOV(Q|L|W|B)storeconst [sc] {s} (ADDQconst [off] ptr) mem) && ValAndOff(sc).canAdd32(off) => - (MOV(Q|L|W|B)storeconst [ValAndOff(sc).addOffset32(off)] {s} ptr mem) +(MOV(Q|L|W|B|O)storeconst [sc] {s} (ADDQconst [off] ptr) mem) && ValAndOff(sc).canAdd32(off) => + (MOV(Q|L|W|B|O)storeconst [ValAndOff(sc).addOffset32(off)] {s} ptr mem) // We need to fold LEAQ into the MOVx ops so that the live variable analysis knows // what variables are being read/written by the ops. @@ -1145,8 +1145,8 @@ (MOV(Q|L|W|B|SS|SD|O)store [off1] {sym1} (LEAQ [off2] {sym2} base) val mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) => (MOV(Q|L|W|B|SS|SD|O)store [off1+off2] {mergeSym(sym1,sym2)} base val mem) -(MOV(Q|L|W|B)storeconst [sc] {sym1} (LEAQ [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd32(off) => - (MOV(Q|L|W|B)storeconst [ValAndOff(sc).addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem) +(MOV(Q|L|W|B|O)storeconst [sc] {sym1} (LEAQ [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd32(off) => + (MOV(Q|L|W|B|O)storeconst [ValAndOff(sc).addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem) (SET(L|G|B|A|LE|GE|BE|AE|EQ|NE)store [off1] {sym1} (LEAQ [off2] {sym2} base) val mem) && is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) => (SET(L|G|B|A|LE|GE|BE|AE|EQ|NE)store [off1+off2] {mergeSym(sym1,sym2)} base val mem) @@ -1897,14 +1897,22 @@ && a.Off() + 4 == c.Off() && clobber(x) => (MOVQstore [a.Off()] {s} p (MOVQconst [a.Val64()&0xffffffff | c.Val64()<<32]) mem) -(MOVQstoreconst [c] {s} p x:(MOVQstoreconst [c2] {s} p mem)) +(MOVQstoreconst [c] {s} p x:(MOVQstoreconst [a] {s} p mem)) + && config.useSSE + && x.Uses == 1 + && a.Off() + 8 == c.Off() + && a.Val() == 0 + && c.Val() == 0 + && clobber(x) + => (MOVOstoreconst [makeValAndOff(0,a.Off())] {s} p mem) +(MOVQstoreconst [a] {s} p x:(MOVQstoreconst [c] {s} p mem)) && config.useSSE && x.Uses == 1 - && c2.Off() + 8 == c.Off() + && a.Off() + 8 == c.Off() + && a.Val() == 0 && c.Val() == 0 - && c2.Val() == 0 && clobber(x) - => (MOVOstorezero [c2.Off()] {s} p mem) + => (MOVOstoreconst [makeValAndOff(0,a.Off())] {s} p mem) // Combine stores into larger (unaligned) stores. Little endian. (MOVBstore [i] {s} p (SHR(W|L|Q)const [8] w) x:(MOVBstore [i-1] {s} p w mem)) @@ -2031,6 +2039,8 @@ (MOVBstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) && canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) => (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) +(MOVOstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && sc.canAdd32(off) => + (MOVOstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem) (MOVQstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && sc.canAdd32(off) => (MOVQstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem) (MOVLstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && sc.canAdd32(off) => @@ -2056,6 +2066,8 @@ (MOVWstoreconst [sc.addOffset32(off)] {s} ptr mem) (MOVBstoreconst [sc] {s} (ADDLconst [off] ptr) mem) && sc.canAdd32(off) => (MOVBstoreconst [sc.addOffset32(off)] {s} ptr mem) +(MOVOstoreconst [sc] {s} (ADDLconst [off] ptr) mem) && sc.canAdd32(off) => + (MOVOstoreconst [sc.addOffset32(off)] {s} ptr mem) // Merge load and op // TODO: add indexed variants? diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index 67b3293903..1199d8075f 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -679,20 +679,19 @@ func init() { // Note: LEAx{1,2,4,8} must not have OpSB as either argument. // auxint+aux == add auxint and the offset of the symbol in aux (if any) to the effective address - {name: "MOVBload", argLength: 2, reg: gpload, asm: "MOVBLZX", aux: "SymOff", typ: "UInt8", faultOnNilArg0: true, symEffect: "Read"}, // load byte from arg0+auxint+aux. arg1=mem. Zero extend. - {name: "MOVBQSXload", argLength: 2, reg: gpload, asm: "MOVBQSX", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"}, // ditto, sign extend to int64 - {name: "MOVWload", argLength: 2, reg: gpload, asm: "MOVWLZX", aux: "SymOff", typ: "UInt16", faultOnNilArg0: true, symEffect: "Read"}, // load 2 bytes from arg0+auxint+aux. arg1=mem. Zero extend. - {name: "MOVWQSXload", argLength: 2, reg: gpload, asm: "MOVWQSX", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"}, // ditto, sign extend to int64 - {name: "MOVLload", argLength: 2, reg: gpload, asm: "MOVL", aux: "SymOff", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"}, // load 4 bytes from arg0+auxint+aux. arg1=mem. Zero extend. - {name: "MOVLQSXload", argLength: 2, reg: gpload, asm: "MOVLQSX", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"}, // ditto, sign extend to int64 - {name: "MOVQload", argLength: 2, reg: gpload, asm: "MOVQ", aux: "SymOff", typ: "UInt64", faultOnNilArg0: true, symEffect: "Read"}, // load 8 bytes from arg0+auxint+aux. arg1=mem - {name: "MOVBstore", argLength: 3, reg: gpstore, asm: "MOVB", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store byte in arg1 to arg0+auxint+aux. arg2=mem - {name: "MOVWstore", argLength: 3, reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 2 bytes in arg1 to arg0+auxint+aux. arg2=mem - {name: "MOVLstore", argLength: 3, reg: gpstore, asm: "MOVL", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes in arg1 to arg0+auxint+aux. arg2=mem - {name: "MOVQstore", argLength: 3, reg: gpstore, asm: "MOVQ", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes in arg1 to arg0+auxint+aux. arg2=mem - {name: "MOVOload", argLength: 2, reg: fpload, asm: "MOVUPS", aux: "SymOff", typ: "Int128", faultOnNilArg0: true, symEffect: "Read"}, // load 16 bytes from arg0+auxint+aux. arg1=mem - {name: "MOVOstore", argLength: 3, reg: fpstore, asm: "MOVUPS", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 16 bytes in arg1 to arg0+auxint+aux. arg2=mem - {name: "MOVOstorezero", argLength: 2, reg: regInfo{inputs: []regMask{gpspsb, 0}}, asm: "MOVUPS", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 16 bytes of zero to arg0+auxint+aux. arg1=mem + {name: "MOVBload", argLength: 2, reg: gpload, asm: "MOVBLZX", aux: "SymOff", typ: "UInt8", faultOnNilArg0: true, symEffect: "Read"}, // load byte from arg0+auxint+aux. arg1=mem. Zero extend. + {name: "MOVBQSXload", argLength: 2, reg: gpload, asm: "MOVBQSX", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"}, // ditto, sign extend to int64 + {name: "MOVWload", argLength: 2, reg: gpload, asm: "MOVWLZX", aux: "SymOff", typ: "UInt16", faultOnNilArg0: true, symEffect: "Read"}, // load 2 bytes from arg0+auxint+aux. arg1=mem. Zero extend. + {name: "MOVWQSXload", argLength: 2, reg: gpload, asm: "MOVWQSX", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"}, // ditto, sign extend to int64 + {name: "MOVLload", argLength: 2, reg: gpload, asm: "MOVL", aux: "SymOff", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"}, // load 4 bytes from arg0+auxint+aux. arg1=mem. Zero extend. + {name: "MOVLQSXload", argLength: 2, reg: gpload, asm: "MOVLQSX", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"}, // ditto, sign extend to int64 + {name: "MOVQload", argLength: 2, reg: gpload, asm: "MOVQ", aux: "SymOff", typ: "UInt64", faultOnNilArg0: true, symEffect: "Read"}, // load 8 bytes from arg0+auxint+aux. arg1=mem + {name: "MOVBstore", argLength: 3, reg: gpstore, asm: "MOVB", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store byte in arg1 to arg0+auxint+aux. arg2=mem + {name: "MOVWstore", argLength: 3, reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 2 bytes in arg1 to arg0+auxint+aux. arg2=mem + {name: "MOVLstore", argLength: 3, reg: gpstore, asm: "MOVL", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes in arg1 to arg0+auxint+aux. arg2=mem + {name: "MOVQstore", argLength: 3, reg: gpstore, asm: "MOVQ", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes in arg1 to arg0+auxint+aux. arg2=mem + {name: "MOVOload", argLength: 2, reg: fpload, asm: "MOVUPS", aux: "SymOff", typ: "Int128", faultOnNilArg0: true, symEffect: "Read"}, // load 16 bytes from arg0+auxint+aux. arg1=mem + {name: "MOVOstore", argLength: 3, reg: fpstore, asm: "MOVUPS", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 16 bytes in arg1 to arg0+auxint+aux. arg2=mem // indexed loads/stores {name: "MOVBloadidx1", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVBLZX", scale: 1, aux: "SymOff", typ: "UInt8", symEffect: "Read"}, // load a byte from arg0+arg1+auxint+aux. arg2=mem @@ -717,10 +716,11 @@ func init() { // For storeconst ops, the AuxInt field encodes both // the value to store and an address offset of the store. // Cast AuxInt to a ValAndOff to extract Val and Off fields. - {name: "MOVBstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVB", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store low byte of ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux. arg1=mem - {name: "MOVWstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVW", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store low 2 bytes of ... - {name: "MOVLstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVL", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store low 4 bytes of ... - {name: "MOVQstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVQ", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes of ... + {name: "MOVBstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVB", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store low byte of ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux. arg1=mem + {name: "MOVWstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVW", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store low 2 bytes of ... + {name: "MOVLstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVL", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store low 4 bytes of ... + {name: "MOVQstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVQ", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes of ... + {name: "MOVOstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVUPS", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 16 bytes of ... {name: "MOVBstoreconstidx1", argLength: 3, reg: gpstoreconstidx, commutative: true, asm: "MOVB", scale: 1, aux: "SymValAndOff", typ: "Mem", symEffect: "Write"}, // store low byte of ValAndOff(AuxInt).Val() to arg0+1*arg1+ValAndOff(AuxInt).Off()+aux. arg2=mem {name: "MOVWstoreconstidx1", argLength: 3, reg: gpstoreconstidx, commutative: true, asm: "MOVW", scale: 1, aux: "SymValAndOff", typ: "Mem", symEffect: "Write"}, // store low 2 bytes of ... arg1 ... diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 8ce13abed3..737afc6087 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -962,7 +962,6 @@ const ( OpAMD64MOVQstore OpAMD64MOVOload OpAMD64MOVOstore - OpAMD64MOVOstorezero OpAMD64MOVBloadidx1 OpAMD64MOVWloadidx1 OpAMD64MOVWloadidx2 @@ -983,6 +982,7 @@ const ( OpAMD64MOVWstoreconst OpAMD64MOVLstoreconst OpAMD64MOVQstoreconst + OpAMD64MOVOstoreconst OpAMD64MOVBstoreconstidx1 OpAMD64MOVWstoreconstidx1 OpAMD64MOVWstoreconstidx2 @@ -12625,19 +12625,6 @@ var opcodeTable = [...]opInfo{ }, }, }, - { - name: "MOVOstorezero", - auxType: auxSymOff, - argLen: 2, - faultOnNilArg0: true, - symEffect: SymWrite, - asm: x86.AMOVUPS, - reg: regInfo{ - inputs: []inputInfo{ - {0, 4295016447}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15 SB - }, - }, - }, { name: "MOVBloadidx1", auxType: auxSymOff, @@ -12954,6 +12941,19 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "MOVOstoreconst", + auxType: auxSymValAndOff, + argLen: 2, + faultOnNilArg0: true, + symEffect: SymWrite, + asm: x86.AMOVUPS, + reg: regInfo{ + inputs: []inputInfo{ + {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB + }, + }, + }, { name: "MOVBstoreconstidx1", auxType: auxSymValAndOff, diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 89d32c0657..2aa3786a7e 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -249,6 +249,8 @@ func rewriteValueAMD64(v *Value) bool { return rewriteValueAMD64_OpAMD64MOVOload(v) case OpAMD64MOVOstore: return rewriteValueAMD64_OpAMD64MOVOstore(v) + case OpAMD64MOVOstoreconst: + return rewriteValueAMD64_OpAMD64MOVOstoreconst(v) case OpAMD64MOVQatomicload: return rewriteValueAMD64_OpAMD64MOVQatomicload(v) case OpAMD64MOVQf2i: @@ -12544,6 +12546,97 @@ func rewriteValueAMD64_OpAMD64MOVOstore(v *Value) bool { } return false } +func rewriteValueAMD64_OpAMD64MOVOstoreconst(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] + // match: (MOVOstoreconst [sc] {s} (ADDQconst [off] ptr) mem) + // cond: ValAndOff(sc).canAdd32(off) + // result: (MOVOstoreconst [ValAndOff(sc).addOffset32(off)] {s} ptr mem) + for { + sc := auxIntToValAndOff(v.AuxInt) + s := auxToSym(v.Aux) + if v_0.Op != OpAMD64ADDQconst { + break + } + off := auxIntToInt32(v_0.AuxInt) + ptr := v_0.Args[0] + mem := v_1 + if !(ValAndOff(sc).canAdd32(off)) { + break + } + v.reset(OpAMD64MOVOstoreconst) + v.AuxInt = valAndOffToAuxInt(ValAndOff(sc).addOffset32(off)) + v.Aux = symToAux(s) + v.AddArg2(ptr, mem) + return true + } + // match: (MOVOstoreconst [sc] {sym1} (LEAQ [off] {sym2} ptr) mem) + // cond: canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd32(off) + // result: (MOVOstoreconst [ValAndOff(sc).addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem) + for { + sc := auxIntToValAndOff(v.AuxInt) + sym1 := auxToSym(v.Aux) + if v_0.Op != OpAMD64LEAQ { + break + } + off := auxIntToInt32(v_0.AuxInt) + sym2 := auxToSym(v_0.Aux) + ptr := v_0.Args[0] + mem := v_1 + if !(canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd32(off)) { + break + } + v.reset(OpAMD64MOVOstoreconst) + v.AuxInt = valAndOffToAuxInt(ValAndOff(sc).addOffset32(off)) + v.Aux = symToAux(mergeSym(sym1, sym2)) + v.AddArg2(ptr, mem) + return true + } + // match: (MOVOstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) + // cond: canMergeSym(sym1, sym2) && sc.canAdd32(off) + // result: (MOVOstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem) + for { + sc := auxIntToValAndOff(v.AuxInt) + sym1 := auxToSym(v.Aux) + if v_0.Op != OpAMD64LEAL { + break + } + off := auxIntToInt32(v_0.AuxInt) + sym2 := auxToSym(v_0.Aux) + ptr := v_0.Args[0] + mem := v_1 + if !(canMergeSym(sym1, sym2) && sc.canAdd32(off)) { + break + } + v.reset(OpAMD64MOVOstoreconst) + v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off)) + v.Aux = symToAux(mergeSym(sym1, sym2)) + v.AddArg2(ptr, mem) + return true + } + // match: (MOVOstoreconst [sc] {s} (ADDLconst [off] ptr) mem) + // cond: sc.canAdd32(off) + // result: (MOVOstoreconst [sc.addOffset32(off)] {s} ptr mem) + for { + sc := auxIntToValAndOff(v.AuxInt) + s := auxToSym(v.Aux) + if v_0.Op != OpAMD64ADDLconst { + break + } + off := auxIntToInt32(v_0.AuxInt) + ptr := v_0.Args[0] + mem := v_1 + if !(sc.canAdd32(off)) { + break + } + v.reset(OpAMD64MOVOstoreconst) + v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off)) + v.Aux = symToAux(s) + v.AddArg2(ptr, mem) + return true + } + return false +} func rewriteValueAMD64_OpAMD64MOVQatomicload(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -13331,9 +13424,9 @@ func rewriteValueAMD64_OpAMD64MOVQstoreconst(v *Value) bool { v.AddArg2(ptr, mem) return true } - // match: (MOVQstoreconst [c] {s} p x:(MOVQstoreconst [c2] {s} p mem)) - // cond: config.useSSE && x.Uses == 1 && c2.Off() + 8 == c.Off() && c.Val() == 0 && c2.Val() == 0 && clobber(x) - // result: (MOVOstorezero [c2.Off()] {s} p mem) + // match: (MOVQstoreconst [c] {s} p x:(MOVQstoreconst [a] {s} p mem)) + // cond: config.useSSE && x.Uses == 1 && a.Off() + 8 == c.Off() && a.Val() == 0 && c.Val() == 0 && clobber(x) + // result: (MOVOstoreconst [makeValAndOff(0,a.Off())] {s} p mem) for { c := auxIntToValAndOff(v.AuxInt) s := auxToSym(v.Aux) @@ -13342,16 +13435,41 @@ func rewriteValueAMD64_OpAMD64MOVQstoreconst(v *Value) bool { if x.Op != OpAMD64MOVQstoreconst { break } - c2 := auxIntToValAndOff(x.AuxInt) + a := auxIntToValAndOff(x.AuxInt) + if auxToSym(x.Aux) != s { + break + } + mem := x.Args[1] + if p != x.Args[0] || !(config.useSSE && x.Uses == 1 && a.Off()+8 == c.Off() && a.Val() == 0 && c.Val() == 0 && clobber(x)) { + break + } + v.reset(OpAMD64MOVOstoreconst) + v.AuxInt = valAndOffToAuxInt(makeValAndOff(0, a.Off())) + v.Aux = symToAux(s) + v.AddArg2(p, mem) + return true + } + // match: (MOVQstoreconst [a] {s} p x:(MOVQstoreconst [c] {s} p mem)) + // cond: config.useSSE && x.Uses == 1 && a.Off() + 8 == c.Off() && a.Val() == 0 && c.Val() == 0 && clobber(x) + // result: (MOVOstoreconst [makeValAndOff(0,a.Off())] {s} p mem) + for { + a := auxIntToValAndOff(v.AuxInt) + s := auxToSym(v.Aux) + p := v_0 + x := v_1 + if x.Op != OpAMD64MOVQstoreconst { + break + } + c := auxIntToValAndOff(x.AuxInt) if auxToSym(x.Aux) != s { break } mem := x.Args[1] - if p != x.Args[0] || !(config.useSSE && x.Uses == 1 && c2.Off()+8 == c.Off() && c.Val() == 0 && c2.Val() == 0 && clobber(x)) { + if p != x.Args[0] || !(config.useSSE && x.Uses == 1 && a.Off()+8 == c.Off() && a.Val() == 0 && c.Val() == 0 && clobber(x)) { break } - v.reset(OpAMD64MOVOstorezero) - v.AuxInt = int32ToAuxInt(c2.Off()) + v.reset(OpAMD64MOVOstoreconst) + v.AuxInt = valAndOffToAuxInt(makeValAndOff(0, a.Off())) v.Aux = symToAux(s) v.AddArg2(p, mem) return true @@ -33458,7 +33576,7 @@ func rewriteValueAMD64_OpZero(v *Value) bool { } // match: (Zero [s] destptr mem) // cond: s%16 != 0 && s > 16 && s%16 > 8 && config.useSSE - // result: (Zero [s-s%16] (OffPtr destptr [s%16]) (MOVOstorezero destptr mem)) + // result: (Zero [s-s%16] (OffPtr destptr [s%16]) (MOVOstoreconst [makeValAndOff(0,0)] destptr mem)) for { s := auxIntToInt64(v.AuxInt) destptr := v_0 @@ -33471,14 +33589,15 @@ func rewriteValueAMD64_OpZero(v *Value) bool { v0 := b.NewValue0(v.Pos, OpOffPtr, destptr.Type) v0.AuxInt = int64ToAuxInt(s % 16) v0.AddArg(destptr) - v1 := b.NewValue0(v.Pos, OpAMD64MOVOstorezero, types.TypeMem) + v1 := b.NewValue0(v.Pos, OpAMD64MOVOstoreconst, types.TypeMem) + v1.AuxInt = valAndOffToAuxInt(makeValAndOff(0, 0)) v1.AddArg2(destptr, mem) v.AddArg2(v0, v1) return true } // match: (Zero [s] destptr mem) // cond: s%16 != 0 && s > 16 && s%16 <= 8 && config.useSSE - // result: (Zero [s-s%16] (OffPtr destptr [s%16]) (MOVQstoreconst [makeValAndOff(0,0)] destptr mem)) + // result: (Zero [s-s%16] (OffPtr destptr [s%16]) (MOVOstoreconst [makeValAndOff(0,0)] destptr mem)) for { s := auxIntToInt64(v.AuxInt) destptr := v_0 @@ -33491,7 +33610,7 @@ func rewriteValueAMD64_OpZero(v *Value) bool { v0 := b.NewValue0(v.Pos, OpOffPtr, destptr.Type) v0.AuxInt = int64ToAuxInt(s % 16) v0.AddArg(destptr) - v1 := b.NewValue0(v.Pos, OpAMD64MOVQstoreconst, types.TypeMem) + v1 := b.NewValue0(v.Pos, OpAMD64MOVOstoreconst, types.TypeMem) v1.AuxInt = valAndOffToAuxInt(makeValAndOff(0, 0)) v1.AddArg2(destptr, mem) v.AddArg2(v0, v1) @@ -33499,7 +33618,7 @@ func rewriteValueAMD64_OpZero(v *Value) bool { } // match: (Zero [16] destptr mem) // cond: config.useSSE - // result: (MOVOstorezero destptr mem) + // result: (MOVOstoreconst [makeValAndOff(0,0)] destptr mem) for { if auxIntToInt64(v.AuxInt) != 16 { break @@ -33509,13 +33628,14 @@ func rewriteValueAMD64_OpZero(v *Value) bool { if !(config.useSSE) { break } - v.reset(OpAMD64MOVOstorezero) + v.reset(OpAMD64MOVOstoreconst) + v.AuxInt = valAndOffToAuxInt(makeValAndOff(0, 0)) v.AddArg2(destptr, mem) return true } // match: (Zero [32] destptr mem) // cond: config.useSSE - // result: (MOVOstorezero (OffPtr destptr [16]) (MOVOstorezero destptr mem)) + // result: (MOVOstoreconst [makeValAndOff(0,16)] destptr (MOVOstoreconst [makeValAndOff(0,0)] destptr mem)) for { if auxIntToInt64(v.AuxInt) != 32 { break @@ -33525,18 +33645,17 @@ func rewriteValueAMD64_OpZero(v *Value) bool { if !(config.useSSE) { break } - v.reset(OpAMD64MOVOstorezero) - v0 := b.NewValue0(v.Pos, OpOffPtr, destptr.Type) - v0.AuxInt = int64ToAuxInt(16) - v0.AddArg(destptr) - v1 := b.NewValue0(v.Pos, OpAMD64MOVOstorezero, types.TypeMem) - v1.AddArg2(destptr, mem) - v.AddArg2(v0, v1) + v.reset(OpAMD64MOVOstoreconst) + v.AuxInt = valAndOffToAuxInt(makeValAndOff(0, 16)) + v0 := b.NewValue0(v.Pos, OpAMD64MOVOstoreconst, types.TypeMem) + v0.AuxInt = valAndOffToAuxInt(makeValAndOff(0, 0)) + v0.AddArg2(destptr, mem) + v.AddArg2(destptr, v0) return true } // match: (Zero [48] destptr mem) // cond: config.useSSE - // result: (MOVOstorezero (OffPtr destptr [32]) (MOVOstorezero (OffPtr destptr [16]) (MOVOstorezero destptr mem))) + // result: (MOVOstoreconst [makeValAndOff(0,32)] destptr (MOVOstoreconst [makeValAndOff(0,16)] destptr (MOVOstoreconst [makeValAndOff(0,0)] destptr mem))) for { if auxIntToInt64(v.AuxInt) != 48 { break @@ -33546,23 +33665,20 @@ func rewriteValueAMD64_OpZero(v *Value) bool { if !(config.useSSE) { break } - v.reset(OpAMD64MOVOstorezero) - v0 := b.NewValue0(v.Pos, OpOffPtr, destptr.Type) - v0.AuxInt = int64ToAuxInt(32) - v0.AddArg(destptr) - v1 := b.NewValue0(v.Pos, OpAMD64MOVOstorezero, types.TypeMem) - v2 := b.NewValue0(v.Pos, OpOffPtr, destptr.Type) - v2.AuxInt = int64ToAuxInt(16) - v2.AddArg(destptr) - v3 := b.NewValue0(v.Pos, OpAMD64MOVOstorezero, types.TypeMem) - v3.AddArg2(destptr, mem) - v1.AddArg2(v2, v3) - v.AddArg2(v0, v1) + v.reset(OpAMD64MOVOstoreconst) + v.AuxInt = valAndOffToAuxInt(makeValAndOff(0, 32)) + v0 := b.NewValue0(v.Pos, OpAMD64MOVOstoreconst, types.TypeMem) + v0.AuxInt = valAndOffToAuxInt(makeValAndOff(0, 16)) + v1 := b.NewValue0(v.Pos, OpAMD64MOVOstoreconst, types.TypeMem) + v1.AuxInt = valAndOffToAuxInt(makeValAndOff(0, 0)) + v1.AddArg2(destptr, mem) + v0.AddArg2(destptr, v1) + v.AddArg2(destptr, v0) return true } // match: (Zero [64] destptr mem) // cond: config.useSSE - // result: (MOVOstorezero (OffPtr destptr [48]) (MOVOstorezero (OffPtr destptr [32]) (MOVOstorezero (OffPtr destptr [16]) (MOVOstorezero destptr mem)))) + // result: (MOVOstoreconst [makeValAndOff(0,48)] destptr (MOVOstoreconst [makeValAndOff(0,32)] destptr (MOVOstoreconst [makeValAndOff(0,16)] destptr (MOVOstoreconst [makeValAndOff(0,0)] destptr mem)))) for { if auxIntToInt64(v.AuxInt) != 64 { break @@ -33572,23 +33688,18 @@ func rewriteValueAMD64_OpZero(v *Value) bool { if !(config.useSSE) { break } - v.reset(OpAMD64MOVOstorezero) - v0 := b.NewValue0(v.Pos, OpOffPtr, destptr.Type) - v0.AuxInt = int64ToAuxInt(48) - v0.AddArg(destptr) - v1 := b.NewValue0(v.Pos, OpAMD64MOVOstorezero, types.TypeMem) - v2 := b.NewValue0(v.Pos, OpOffPtr, destptr.Type) - v2.AuxInt = int64ToAuxInt(32) - v2.AddArg(destptr) - v3 := b.NewValue0(v.Pos, OpAMD64MOVOstorezero, types.TypeMem) - v4 := b.NewValue0(v.Pos, OpOffPtr, destptr.Type) - v4.AuxInt = int64ToAuxInt(16) - v4.AddArg(destptr) - v5 := b.NewValue0(v.Pos, OpAMD64MOVOstorezero, types.TypeMem) - v5.AddArg2(destptr, mem) - v3.AddArg2(v4, v5) - v1.AddArg2(v2, v3) - v.AddArg2(v0, v1) + v.reset(OpAMD64MOVOstoreconst) + v.AuxInt = valAndOffToAuxInt(makeValAndOff(0, 48)) + v0 := b.NewValue0(v.Pos, OpAMD64MOVOstoreconst, types.TypeMem) + v0.AuxInt = valAndOffToAuxInt(makeValAndOff(0, 32)) + v1 := b.NewValue0(v.Pos, OpAMD64MOVOstoreconst, types.TypeMem) + v1.AuxInt = valAndOffToAuxInt(makeValAndOff(0, 16)) + v2 := b.NewValue0(v.Pos, OpAMD64MOVOstoreconst, types.TypeMem) + v2.AuxInt = valAndOffToAuxInt(makeValAndOff(0, 0)) + v2.AddArg2(destptr, mem) + v1.AddArg2(destptr, v2) + v0.AddArg2(destptr, v1) + v.AddArg2(destptr, v0) return true } // match: (Zero [s] destptr mem) -- GitLab From 37da45d05a50419b44dcb444d280af31e5344f8e Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Fri, 6 Aug 2021 16:15:48 -0700 Subject: [PATCH 0919/2500] [dev.fuzz] internal/fuzz: count -fuzzminimizetime toward -fuzztime Previously, when -fuzztime was given a number of executions like -fuzztime=100x, this was a count for each minimization independent of -fuzztime. Since there is no bound on the number of minimizations, this was not a meaningful limit. With this change, executions of the fuzz function during minimization count toward the -fuzztime global limit. Executions are further limited by -fuzzminimizetime. This change also counts executions during the coverage-only run and reports errors for those executions. There is no change when -fuzztime specifies a duration or when -fuzztime is not set. Change-Id: Ibcf1b1982f28b28f6625283aa03ce66d4de0a26d Reviewed-on: https://go-review.googlesource.com/c/go/+/342994 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- .../go/testdata/script/test_fuzz_deadline.txt | 2 +- .../go/testdata/script/test_fuzz_fuzztime.txt | 17 ++- .../go/testdata/script/test_fuzz_minimize.txt | 4 +- .../script/test_fuzz_mutate_crash.txt | 30 ++-- src/internal/fuzz/fuzz.go | 133 +++++++++++++----- src/internal/fuzz/worker.go | 49 ++++--- 6 files changed, 162 insertions(+), 73 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_deadline.txt b/src/cmd/go/testdata/script/test_fuzz_deadline.txt index f0826478ec..12f1054f61 100644 --- a/src/cmd/go/testdata/script/test_fuzz_deadline.txt +++ b/src/cmd/go/testdata/script/test_fuzz_deadline.txt @@ -14,7 +14,7 @@ go test -fuzz=FuzzDeadline -timeout=0 -fuzztime=1s -wantdeadline=false go test -fuzz=FuzzDeadline -timeout=0 -fuzztime=100x -wantdeadline=false -- go.mod -- -module fzz +module fuzz go 1.16 -- fuzz_deadline_test.go -- diff --git a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt index 617980e940..5eb8c86708 100644 --- a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt +++ b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt @@ -6,7 +6,7 @@ # There are no seed values, so 'go test' should finish quickly. go test -# Fuzzing should exit 0 when after fuzztime, even if timeout is short. +# Fuzzing should exit 0 after fuzztime, even if timeout is short. go test -timeout=10ms -fuzz=FuzzFast -fuzztime=5s # We should see the same behavior when invoking the test binary directly. @@ -21,9 +21,8 @@ exec ./fuzz.test$GOEXE -test.timeout=10ms -test.fuzz=FuzzFast -test.fuzztime=5s # We count the files to find the number of runs. mkdir count env GOCACHE=$WORK/tmp -go test -fuzz=FuzzCount -fuzztime=1000x -go run count_files.go -stdout '^1000$' +go test -fuzz=FuzzCount -fuzztime=1000x -fuzzminimizetime=1x +go run check_file_count.go 1000 -- go.mod -- module fuzz @@ -57,7 +56,7 @@ func FuzzCount(f *testing.F) { n++ }) } --- count_files.go -- +-- check_file_count.go -- // +build ignore package main @@ -65,6 +64,7 @@ package main import ( "fmt" "os" + "strconv" ) func main() { @@ -73,5 +73,10 @@ func main() { fmt.Fprintln(os.Stderr, err) os.Exit(1) } - fmt.Println(len(dir)) + got := len(dir) + want, _ := strconv.Atoi(os.Args[1]) + if got != want { + fmt.Fprintf(os.Stderr, "got %d files; want %d\n", got, want) + os.Exit(1) + } } diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize.txt b/src/cmd/go/testdata/script/test_fuzz_minimize.txt index 215ce04dbc..337059da3f 100644 --- a/src/cmd/go/testdata/script/test_fuzz_minimize.txt +++ b/src/cmd/go/testdata/script/test_fuzz_minimize.txt @@ -7,7 +7,7 @@ env GOCACHE=$WORK/gocache # Test that minimization is working for recoverable errors. -! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=100x -fuzzminimizetime=10000x minimizer_test.go +! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x minimizer_test.go ! stdout '^ok' stdout 'got the minimum size!' stdout 'contains a non-zero byte' @@ -21,7 +21,7 @@ go run check_testdata.go FuzzMinimizerRecoverable 50 rm testdata # Test that minimization is working for non-recoverable errors. -! go test -fuzz=FuzzMinimizerNonrecoverable -run=FuzzMinimizerNonrecoverable -fuzztime=100x -fuzzminimizetime=10000x minimizer_test.go +! go test -fuzz=FuzzMinimizerNonrecoverable -run=FuzzMinimizerNonrecoverable -fuzztime=10000x minimizer_test.go ! stdout '^ok' stdout 'found a crash, minimizing' stdout 'fuzzing process terminated unexpectedly while minimizing: exit status 99' diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt index cba91a99cf..92a52ccdea 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt @@ -13,7 +13,7 @@ go test # Running the fuzzer should find a crashing input quickly. -! go test -fuzz=FuzzWithBug -fuzztime=100x +! go test -fuzz=FuzzWithBug -fuzztime=100x -fuzzminimizetime=1000x stdout 'testdata[/\\]corpus[/\\]FuzzWithBug[/\\]' stdout 'this input caused a crash!' go run check_testdata.go FuzzWithBug @@ -24,78 +24,78 @@ go run check_testdata.go FuzzWithBug stdout 'testdata[/\\]corpus[/\\]FuzzWithBug[/\\][a-f0-9]{64}' stdout 'this input caused a crash!' -! go test -run=FuzzWithNilPanic -fuzz=FuzzWithNilPanic -fuzztime=100x +! go test -run=FuzzWithNilPanic -fuzz=FuzzWithNilPanic -fuzztime=100x -fuzzminimizetime=1000x stdout 'testdata[/\\]corpus[/\\]FuzzWithNilPanic[/\\]' stdout 'runtime.Goexit' go run check_testdata.go FuzzWithNilPanic -! go test -run=FuzzWithFail -fuzz=FuzzWithFail -fuzztime=100x +! go test -run=FuzzWithFail -fuzz=FuzzWithFail -fuzztime=100x -fuzzminimizetime=1000x stdout 'testdata[/\\]corpus[/\\]FuzzWithFail[/\\]' go run check_testdata.go FuzzWithFail -! go test -run=FuzzWithLogFail -fuzz=FuzzWithLogFail -fuzztime=100x +! go test -run=FuzzWithLogFail -fuzz=FuzzWithLogFail -fuzztime=100x -fuzzminimizetime=1000x stdout 'testdata[/\\]corpus[/\\]FuzzWithLogFail[/\\]' stdout 'logged something' go run check_testdata.go FuzzWithLogFail -! go test -run=FuzzWithErrorf -fuzz=FuzzWithErrorf -fuzztime=100x +! go test -run=FuzzWithErrorf -fuzz=FuzzWithErrorf -fuzztime=100x -fuzzminimizetime=1000x stdout 'testdata[/\\]corpus[/\\]FuzzWithErrorf[/\\]' stdout 'errorf was called here' go run check_testdata.go FuzzWithErrorf -! go test -run=FuzzWithFatalf -fuzz=FuzzWithFatalf -fuzztime=100x +! go test -run=FuzzWithFatalf -fuzz=FuzzWithFatalf -fuzztime=100x -fuzzminimizetime=1000x stdout 'testdata[/\\]corpus[/\\]FuzzWithFatalf[/\\]' stdout 'fatalf was called here' go run check_testdata.go FuzzWithFatalf -! go test -run=FuzzWithBadExit -fuzz=FuzzWithBadExit -fuzztime=100x +! go test -run=FuzzWithBadExit -fuzz=FuzzWithBadExit -fuzztime=100x -fuzzminimizetime=1000x stdout 'testdata[/\\]corpus[/\\]FuzzWithBadExit[/\\]' stdout 'unexpectedly' go run check_testdata.go FuzzWithBadExit # Running the fuzzer should find a crashing input quickly for fuzzing two types. -! go test -run=FuzzWithTwoTypes -fuzz=FuzzWithTwoTypes -fuzztime=100x +! go test -run=FuzzWithTwoTypes -fuzz=FuzzWithTwoTypes -fuzztime=100x -fuzzminimizetime=1000x stdout 'testdata[/\\]corpus[/\\]FuzzWithTwoTypes[/\\]' stdout 'these inputs caused a crash!' go run check_testdata.go FuzzWithTwoTypes # Running the fuzzer should find a crashing input quickly for an integer. -! go test -run=FuzzInt -fuzz=FuzzInt -fuzztime=100x +! go test -run=FuzzInt -fuzz=FuzzInt -fuzztime=100x -fuzzminimizetime=1000x stdout 'testdata[/\\]corpus[/\\]FuzzInt[/\\]' stdout 'this input caused a crash!' go run check_testdata.go FuzzInt -! go test -run=FuzzUint -fuzz=FuzzUint -fuzztime=100x +! go test -run=FuzzUint -fuzz=FuzzUint -fuzztime=100x -fuzzminimizetime=1000x stdout 'testdata[/\\]corpus[/\\]FuzzUint[/\\]' stdout 'this input caused a crash!' go run check_testdata.go FuzzUint # Running the fuzzer should find a crashing input quickly for a bool. -! go test -run=FuzzBool -fuzz=FuzzBool -fuzztime=100x +! go test -run=FuzzBool -fuzz=FuzzBool -fuzztime=100x -fuzzminimizetime=1000x stdout 'testdata[/\\]corpus[/\\]FuzzBool[/\\]' stdout 'this input caused a crash!' go run check_testdata.go FuzzBool # Running the fuzzer should find a crashing input quickly for a float. -! go test -run=FuzzFloat -fuzz=FuzzFloat -fuzztime=100x +! go test -run=FuzzFloat -fuzz=FuzzFloat -fuzztime=100x -fuzzminimizetime=1000x stdout 'testdata[/\\]corpus[/\\]FuzzFloat[/\\]' stdout 'this input caused a crash!' go run check_testdata.go FuzzFloat # Running the fuzzer should find a crashing input quickly for a byte. -! go test -run=FuzzByte -fuzz=FuzzByte -fuzztime=100x +! go test -run=FuzzByte -fuzz=FuzzByte -fuzztime=100x -fuzzminimizetime=1000x stdout 'testdata[/\\]corpus[/\\]FuzzByte[/\\]' stdout 'this input caused a crash!' go run check_testdata.go FuzzByte # Running the fuzzer should find a crashing input quickly for a rune. -! go test -run=FuzzRune -fuzz=FuzzRune -fuzztime=100x +! go test -run=FuzzRune -fuzz=FuzzRune -fuzztime=100x -fuzzminimizetime=1000x stdout 'testdata[/\\]corpus[/\\]FuzzRune[/\\]' stdout 'this input caused a crash!' go run check_testdata.go FuzzRune # Running the fuzzer should find a crashing input quickly for a string. -! go test -run=FuzzString -fuzz=FuzzString -fuzztime=100x +! go test -run=FuzzString -fuzz=FuzzString -fuzztime=100x -fuzzminimizetime=1000x stdout 'testdata[/\\]corpus[/\\]FuzzString[/\\]' stdout 'this input caused a crash!' go run check_testdata.go FuzzString diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 419faac5ac..b06ab146f7 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -45,7 +45,8 @@ type CoordinateFuzzingOpts struct { // MinimizeLimit is the maximum number of calls to the fuzz function to be // made while minimizing after finding a crash. If zero, there will be - // no limit. + // no limit. Calls to the fuzz function made when minimizing also count + // toward Limit. MinimizeLimit int64 // parallel is the number of worker processes to run in parallel. If zero, @@ -92,13 +93,6 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err // Don't start more workers than we need. opts.Parallel = int(opts.Limit) } - canMinimize := false - for _, t := range opts.Types { - if isMinimizable(t) { - canMinimize = true - break - } - } c, err := newCoordinator(opts) if err != nil { @@ -199,17 +193,19 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err } if result.crasherMsg != "" { - if canMinimize && !result.minimized { - // Found a crasher but haven't yet attempted to minimize it. - // Send it back to a worker for minimization. Disable inputC so - // other workers don't continue fuzzing. + if c.canMinimize() && !result.minimizeAttempted { if crashMinimizing { + // This crash is not minimized, and another crash is being minimized. + // Ignore this one and wait for the other one to finish. break } + // Found a crasher but haven't yet attempted to minimize it. + // Send it back to a worker for minimization. Disable inputC so + // other workers don't continue fuzzing. crashMinimizing = true inputC = nil fmt.Fprintf(c.opts.Log, "found a crash, minimizing...\n") - c.minimizeC <- result + c.minimizeC <- c.minimizeInputForResult(result) } else if !crashWritten { // Found a crasher that's either minimized or not minimizable. // Write to corpus and stop. @@ -402,9 +398,15 @@ type fuzzInput struct { // values from this starting point. entry CorpusEntry - // countRequested is the number of values to test. If non-zero, the worker - // will stop after testing this many values, if it hasn't already stopped. - countRequested int64 + // timeout is the time to spend fuzzing variations of this input, + // not including starting or cleaning up. + timeout time.Duration + + // limit is the maximum number of calls to the fuzz function the worker may + // make. The worker may make fewer calls, for example, if it finds an + // error early. If limit is zero, there is no limit on calls to the + // fuzz function. + limit int64 // coverageOnly indicates whether this input is for a coverage-only run. If // true, the input should not be fuzzed. @@ -425,16 +427,16 @@ type fuzzResult struct { // crasherMsg is an error message from a crash. It's "" if no crash was found. crasherMsg string - // minimized is true if a worker attempted to minimize entry. - // Minimization may not have actually been completed. - minimized bool + // minimizeAttempted is true if the worker attempted to minimize this input. + // The worker may or may not have succeeded. + minimizeAttempted bool // coverageData is set if the worker found new coverage. coverageData []byte - // countRequested is the number of values the coordinator asked the worker + // limit is the number of values the coordinator asked the worker // to test. 0 if there was no limit. - countRequested int64 + limit int64 // count is the number of values the worker actually tested. count int64 @@ -446,6 +448,25 @@ type fuzzResult struct { entryDuration time.Duration } +type fuzzMinimizeInput struct { + // entry is an interesting value or crasher to minimize. + entry CorpusEntry + + // crasherMsg is an error message from a crash. It's "" if no crash was found. + // If set, the worker will attempt to find a smaller input that also produces + // an error, though not necessarily the same error. + crasherMsg string + + // limit is the maximum number of calls to the fuzz function the worker may + // make. The worker may make fewer calls, for example, if it can't reproduce + // an error. If limit is zero, there is no limit on calls to the fuzz function. + limit int64 + + // timeout is the time to spend minimizing this input. + // A zero timeout means no limit. + timeout time.Duration +} + // coordinator holds channels that workers can use to communicate with // the coordinator. type coordinator struct { @@ -461,7 +482,7 @@ type coordinator struct { // minimizeC is sent values to minimize by the coordinator. Any worker may // receive values from this channel. Workers send results to resultC. - minimizeC chan fuzzResult + minimizeC chan fuzzMinimizeInput // resultC is sent results of fuzzing by workers. The coordinator // receives these. Multiple types of messages are allowed. @@ -482,8 +503,8 @@ type coordinator struct { // starting up or tearing down. duration time.Duration - // countWaiting is the number of values the coordinator is currently waiting - // for workers to fuzz. + // countWaiting is the number of fuzzing executions the coordinator is + // waiting on workers to complete. countWaiting int64 // corpus is a set of interesting values, including the seed corpus and @@ -495,6 +516,10 @@ type coordinator struct { // which corpus value to send next (or generates something new). corpusIndex int + // typesAreMinimizable is true if one or more of the types of fuzz function's + // parameters can be minimized. + typesAreMinimizable bool + // coverageMask aggregates coverage that was found for all inputs in the // corpus. Each byte represents a single basic execution block. Each set bit // within the byte indicates that an input has triggered that block at least @@ -530,11 +555,17 @@ func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { opts: opts, startTime: time.Now(), inputC: make(chan fuzzInput), - minimizeC: make(chan fuzzResult), + minimizeC: make(chan fuzzMinimizeInput), resultC: make(chan fuzzResult), corpus: corpus, covOnlyInputs: covOnlyInputs, } + for _, t := range opts.Types { + if isMinimizable(t) { + c.typesAreMinimizable = true + break + } + } covSize := len(coverage()) if covSize == 0 { @@ -555,9 +586,8 @@ func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { } func (c *coordinator) updateStats(result fuzzResult) { - // Adjust total stats. c.count += result.count - c.countWaiting -= result.countRequested + c.countWaiting -= result.limit c.duration += result.totalDuration } @@ -584,6 +614,7 @@ func (c *coordinator) nextInput() (fuzzInput, bool) { entry: c.corpus.entries[c.corpusIndex], interestingCount: c.interestingCount, coverageData: make([]byte, len(c.coverageMask)), + timeout: workerFuzzDuration, } copy(input.coverageData, c.coverageMask) c.corpusIndex = (c.corpusIndex + 1) % (len(c.corpus.entries)) @@ -596,19 +627,50 @@ func (c *coordinator) nextInput() (fuzzInput, bool) { } if c.opts.Limit > 0 { - input.countRequested = c.opts.Limit / int64(c.opts.Parallel) + input.limit = c.opts.Limit / int64(c.opts.Parallel) if c.opts.Limit%int64(c.opts.Parallel) > 0 { - input.countRequested++ + input.limit++ } remaining := c.opts.Limit - c.count - c.countWaiting - if input.countRequested > remaining { - input.countRequested = remaining + if input.limit > remaining { + input.limit = remaining } - c.countWaiting += input.countRequested + c.countWaiting += input.limit } return input, true } +// minimizeInputForResult returns an input for minimization based on the given +// fuzzing result that either caused a failure or expanded coverage. +func (c *coordinator) minimizeInputForResult(result fuzzResult) fuzzMinimizeInput { + input := fuzzMinimizeInput{ + entry: result.entry, + crasherMsg: result.crasherMsg, + } + input.limit = 0 + if c.opts.MinimizeTimeout > 0 { + input.timeout = c.opts.MinimizeTimeout + } + if c.opts.MinimizeLimit > 0 { + input.limit = c.opts.MinimizeLimit + } else if c.opts.Limit > 0 { + if result.crasherMsg != "" { + input.limit = c.opts.Limit + } else { + input.limit = c.opts.Limit / int64(c.opts.Parallel) + if c.opts.Limit%int64(c.opts.Parallel) > 0 { + input.limit++ + } + } + } + remaining := c.opts.Limit - c.count - c.countWaiting + if input.limit > remaining { + input.limit = remaining + } + c.countWaiting += input.limit + return input +} + func (c *coordinator) coverageOnlyRun() bool { return c.covOnlyInputs > 0 } @@ -629,6 +691,13 @@ func (c *coordinator) updateCoverage(newCoverage []byte) int { return newBitCount } +// canMinimize returns whether the coordinator should attempt to find smaller +// inputs that reproduce a crash or new coverage. +func (c *coordinator) canMinimize() bool { + return c.typesAreMinimizable && + (c.opts.Limit == 0 || c.count+c.countWaiting < c.opts.Limit) +} + // readCache creates a combined corpus from seed values and values in the cache // (in GOCACHE/fuzz). // diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index de4f6b08b6..290e09846b 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -151,7 +151,7 @@ func (w *worker) coordinate(ctx context.Context) error { case input := <-w.coordinator.inputC: // Received input from coordinator. - args := fuzzArgs{Limit: input.countRequested, Timeout: workerFuzzDuration, CoverageOnly: input.coverageOnly} + args := fuzzArgs{Limit: input.limit, Timeout: input.timeout, CoverageOnly: input.coverageOnly} if interestingCount < input.interestingCount { // The coordinator's coverage data has changed, so send the data // to the client. @@ -191,11 +191,11 @@ func (w *worker) coordinate(ctx context.Context) error { resp.Err = fmt.Sprintf("fuzzing process terminated unexpectedly: %v", w.waitErr) } result := fuzzResult{ - countRequested: input.countRequested, - count: resp.Count, - totalDuration: resp.TotalDuration, - entryDuration: resp.InterestingDuration, - entry: entry, + limit: input.limit, + count: resp.Count, + totalDuration: resp.TotalDuration, + entryDuration: resp.InterestingDuration, + entry: entry, } if resp.Err != "" { result.crasherMsg = resp.Err @@ -204,16 +204,20 @@ func (w *worker) coordinate(ctx context.Context) error { } w.coordinator.resultC <- result - case crasher := <-w.coordinator.minimizeC: + case input := <-w.coordinator.minimizeC: // Received input to minimize from coordinator. - minRes, err := w.minimize(ctx, crasher) + result, err := w.minimize(ctx, input) if err != nil { // Failed to minimize. Send back the original crash. fmt.Fprintln(w.coordinator.opts.Log, err) - minRes = crasher - minRes.minimized = true + result = fuzzResult{ + entry: input.entry, + crasherMsg: input.crasherMsg, + minimizeAttempted: true, + limit: input.limit, + } } - w.coordinator.resultC <- minRes + w.coordinator.resultC <- result } } } @@ -224,19 +228,23 @@ func (w *worker) coordinate(ctx context.Context) error { // // TODO: support minimizing inputs that expand coverage in a specific way, // for example, by ensuring that an input activates a specific set of counters. -func (w *worker) minimize(ctx context.Context, input fuzzResult) (min fuzzResult, err error) { +func (w *worker) minimize(ctx context.Context, input fuzzMinimizeInput) (min fuzzResult, err error) { if w.coordinator.opts.MinimizeTimeout != 0 { var cancel func() ctx, cancel = context.WithTimeout(ctx, w.coordinator.opts.MinimizeTimeout) defer cancel() } - min = input - min.minimized = true + min = fuzzResult{ + entry: input.entry, + crasherMsg: input.crasherMsg, + minimizeAttempted: true, + limit: input.limit, + } args := minimizeArgs{ - Limit: w.coordinator.opts.MinimizeLimit, - Timeout: w.coordinator.opts.MinimizeTimeout, + Limit: input.limit, + Timeout: input.timeout, } minEntry, resp, err := w.client.minimize(ctx, input.entry, args) if err != nil { @@ -660,7 +668,14 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo if args.CoverageOnly { fStart := time.Now() - ws.fuzzFn(CorpusEntry{Values: vals}) + err := ws.fuzzFn(CorpusEntry{Values: vals}) + if err != nil { + resp.Err = err.Error() + if resp.Err == "" { + resp.Err = "fuzz function failed with no output" + } + return resp + } resp.InterestingDuration = time.Since(fStart) resp.CoverageData = coverageSnapshot return resp -- GitLab From 03b8d403dc620050cf5a5ded9be6c89bcd388a70 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Fri, 27 Aug 2021 13:45:32 -0700 Subject: [PATCH 0920/2500] [dev.fuzz] internal/fuzz: count coverage-only runs toward -fuzztime When we start fuzzing, we gather baseline coverage by calling the fuzz function with each entry in the corpus (testdata, F.Add, and cache). These calls should count toward -fuzztime when it specifies a limited number of calls to the fuzz function. Change-Id: I3ff57b6d0b25e2e22bb4ce24b10f5112fb116311 Reviewed-on: https://go-review.googlesource.com/c/go/+/345769 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/internal/fuzz/worker.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 290e09846b..8a5c8696de 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -667,6 +667,7 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo } if args.CoverageOnly { + mem.header().count++ fStart := time.Now() err := ws.fuzzFn(CorpusEntry{Values: vals}) if err != nil { -- GitLab From 46121306d3ceb97a8bb2acb328d68426ad3aa805 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6hrmann?= Date: Tue, 31 Aug 2021 19:41:33 +0200 Subject: [PATCH 0921/2500] cmd/compile: remove folding of 32 bit pointer offsets on amd64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These rules were likely only used in the removed amd64p32 port. Passes toolstash -cmp. Change-Id: Ie626d1021bade7f7571d1bd5271fbe8676bb295e Reviewed-on: https://go-review.googlesource.com/c/go/+/346509 Trust: Martin Möhrmann Run-TryBot: Martin Möhrmann Reviewed-by: Keith Randall TryBot-Result: Go Bot --- src/cmd/compile/internal/ssa/gen/AMD64.rules | 48 -- src/cmd/compile/internal/ssa/rewriteAMD64.go | 567 ------------------- 2 files changed, 615 deletions(-) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 94fce2d4e5..54ed5f7ad1 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -2021,54 +2021,6 @@ && clobber(x1, x2, mem2) => (MOVQstore [i-4] {s} p (MOVQload [j-4] {s2} p2 mem) mem) -(MOVQload [off1] {sym1} (LEAL [off2] {sym2} base) mem) && canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) => - (MOVQload [off1+off2] {mergeSym(sym1,sym2)} base mem) -(MOVLload [off1] {sym1} (LEAL [off2] {sym2} base) mem) && canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) => - (MOVLload [off1+off2] {mergeSym(sym1,sym2)} base mem) -(MOVWload [off1] {sym1} (LEAL [off2] {sym2} base) mem) && canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) => - (MOVWload [off1+off2] {mergeSym(sym1,sym2)} base mem) -(MOVBload [off1] {sym1} (LEAL [off2] {sym2} base) mem) && canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) => - (MOVBload [off1+off2] {mergeSym(sym1,sym2)} base mem) - -(MOVQstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) && canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) => - (MOVQstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) -(MOVLstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) && canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) => - (MOVLstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) -(MOVWstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) && canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) => - (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) -(MOVBstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) && canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) => - (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) - -(MOVOstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && sc.canAdd32(off) => - (MOVOstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem) -(MOVQstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && sc.canAdd32(off) => - (MOVQstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem) -(MOVLstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && sc.canAdd32(off) => - (MOVLstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem) -(MOVWstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && sc.canAdd32(off) => - (MOVWstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem) -(MOVBstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && sc.canAdd32(off) => - (MOVBstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem) - -(MOVQload [off1] {sym} (ADDLconst [off2] ptr) mem) && is32Bit(int64(off1)+int64(off2)) => (MOVQload [off1+off2] {sym} ptr mem) -(MOVLload [off1] {sym} (ADDLconst [off2] ptr) mem) && is32Bit(int64(off1)+int64(off2)) => (MOVLload [off1+off2] {sym} ptr mem) -(MOVWload [off1] {sym} (ADDLconst [off2] ptr) mem) && is32Bit(int64(off1)+int64(off2)) => (MOVWload [off1+off2] {sym} ptr mem) -(MOVBload [off1] {sym} (ADDLconst [off2] ptr) mem) && is32Bit(int64(off1)+int64(off2)) => (MOVBload [off1+off2] {sym} ptr mem) -(MOVQstore [off1] {sym} (ADDLconst [off2] ptr) val mem) && is32Bit(int64(off1)+int64(off2)) => (MOVQstore [off1+off2] {sym} ptr val mem) -(MOVLstore [off1] {sym} (ADDLconst [off2] ptr) val mem) && is32Bit(int64(off1)+int64(off2)) => (MOVLstore [off1+off2] {sym} ptr val mem) -(MOVWstore [off1] {sym} (ADDLconst [off2] ptr) val mem) && is32Bit(int64(off1)+int64(off2)) => (MOVWstore [off1+off2] {sym} ptr val mem) -(MOVBstore [off1] {sym} (ADDLconst [off2] ptr) val mem) && is32Bit(int64(off1)+int64(off2)) => (MOVBstore [off1+off2] {sym} ptr val mem) -(MOVQstoreconst [sc] {s} (ADDLconst [off] ptr) mem) && sc.canAdd32(off) => - (MOVQstoreconst [sc.addOffset32(off)] {s} ptr mem) -(MOVLstoreconst [sc] {s} (ADDLconst [off] ptr) mem) && sc.canAdd32(off) => - (MOVLstoreconst [sc.addOffset32(off)] {s} ptr mem) -(MOVWstoreconst [sc] {s} (ADDLconst [off] ptr) mem) && sc.canAdd32(off) => - (MOVWstoreconst [sc.addOffset32(off)] {s} ptr mem) -(MOVBstoreconst [sc] {s} (ADDLconst [off] ptr) mem) && sc.canAdd32(off) => - (MOVBstoreconst [sc.addOffset32(off)] {s} ptr mem) -(MOVOstoreconst [sc] {s} (ADDLconst [off] ptr) mem) && sc.canAdd32(off) => - (MOVOstoreconst [sc.addOffset32(off)] {s} ptr mem) - // Merge load and op // TODO: add indexed variants? ((ADD|SUB|AND|OR|XOR)Q x l:(MOVQload [off] {sym} ptr mem)) && canMergeLoadClobber(v, l, x) && clobber(l) => ((ADD|SUB|AND|OR|XOR)Qload x [off] {sym} ptr mem) diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 2aa3786a7e..1db16318c8 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -9632,49 +9632,6 @@ func rewriteValueAMD64_OpAMD64MOVBload(v *Value) bool { v.AddArg2(base, mem) return true } - // match: (MOVBload [off1] {sym1} (LEAL [off2] {sym2} base) mem) - // cond: canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) - // result: (MOVBload [off1+off2] {mergeSym(sym1,sym2)} base mem) - for { - off1 := auxIntToInt32(v.AuxInt) - sym1 := auxToSym(v.Aux) - if v_0.Op != OpAMD64LEAL { - break - } - off2 := auxIntToInt32(v_0.AuxInt) - sym2 := auxToSym(v_0.Aux) - base := v_0.Args[0] - mem := v_1 - if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) { - break - } - v.reset(OpAMD64MOVBload) - v.AuxInt = int32ToAuxInt(off1 + off2) - v.Aux = symToAux(mergeSym(sym1, sym2)) - v.AddArg2(base, mem) - return true - } - // match: (MOVBload [off1] {sym} (ADDLconst [off2] ptr) mem) - // cond: is32Bit(int64(off1)+int64(off2)) - // result: (MOVBload [off1+off2] {sym} ptr mem) - for { - off1 := auxIntToInt32(v.AuxInt) - sym := auxToSym(v.Aux) - if v_0.Op != OpAMD64ADDLconst { - break - } - off2 := auxIntToInt32(v_0.AuxInt) - ptr := v_0.Args[0] - mem := v_1 - if !(is32Bit(int64(off1) + int64(off2))) { - break - } - v.reset(OpAMD64MOVBload) - v.AuxInt = int32ToAuxInt(off1 + off2) - v.Aux = symToAux(sym) - v.AddArg2(ptr, mem) - return true - } // match: (MOVBload [off] {sym} (SB) _) // cond: symIsRO(sym) // result: (MOVLconst [int32(read8(sym, int64(off)))]) @@ -10879,51 +10836,6 @@ func rewriteValueAMD64_OpAMD64MOVBstore(v *Value) bool { v.AddArg3(p, v0, mem) return true } - // match: (MOVBstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) - // cond: canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) - // result: (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) - for { - off1 := auxIntToInt32(v.AuxInt) - sym1 := auxToSym(v.Aux) - if v_0.Op != OpAMD64LEAL { - break - } - off2 := auxIntToInt32(v_0.AuxInt) - sym2 := auxToSym(v_0.Aux) - base := v_0.Args[0] - val := v_1 - mem := v_2 - if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) { - break - } - v.reset(OpAMD64MOVBstore) - v.AuxInt = int32ToAuxInt(off1 + off2) - v.Aux = symToAux(mergeSym(sym1, sym2)) - v.AddArg3(base, val, mem) - return true - } - // match: (MOVBstore [off1] {sym} (ADDLconst [off2] ptr) val mem) - // cond: is32Bit(int64(off1)+int64(off2)) - // result: (MOVBstore [off1+off2] {sym} ptr val mem) - for { - off1 := auxIntToInt32(v.AuxInt) - sym := auxToSym(v.Aux) - if v_0.Op != OpAMD64ADDLconst { - break - } - off2 := auxIntToInt32(v_0.AuxInt) - ptr := v_0.Args[0] - val := v_1 - mem := v_2 - if !(is32Bit(int64(off1) + int64(off2))) { - break - } - v.reset(OpAMD64MOVBstore) - v.AuxInt = int32ToAuxInt(off1 + off2) - v.Aux = symToAux(sym) - v.AddArg3(ptr, val, mem) - return true - } return false } func rewriteValueAMD64_OpAMD64MOVBstoreconst(v *Value) bool { @@ -11022,49 +10934,6 @@ func rewriteValueAMD64_OpAMD64MOVBstoreconst(v *Value) bool { v.AddArg2(p, mem) return true } - // match: (MOVBstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) - // cond: canMergeSym(sym1, sym2) && sc.canAdd32(off) - // result: (MOVBstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem) - for { - sc := auxIntToValAndOff(v.AuxInt) - sym1 := auxToSym(v.Aux) - if v_0.Op != OpAMD64LEAL { - break - } - off := auxIntToInt32(v_0.AuxInt) - sym2 := auxToSym(v_0.Aux) - ptr := v_0.Args[0] - mem := v_1 - if !(canMergeSym(sym1, sym2) && sc.canAdd32(off)) { - break - } - v.reset(OpAMD64MOVBstoreconst) - v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off)) - v.Aux = symToAux(mergeSym(sym1, sym2)) - v.AddArg2(ptr, mem) - return true - } - // match: (MOVBstoreconst [sc] {s} (ADDLconst [off] ptr) mem) - // cond: sc.canAdd32(off) - // result: (MOVBstoreconst [sc.addOffset32(off)] {s} ptr mem) - for { - sc := auxIntToValAndOff(v.AuxInt) - s := auxToSym(v.Aux) - if v_0.Op != OpAMD64ADDLconst { - break - } - off := auxIntToInt32(v_0.AuxInt) - ptr := v_0.Args[0] - mem := v_1 - if !(sc.canAdd32(off)) { - break - } - v.reset(OpAMD64MOVBstoreconst) - v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off)) - v.Aux = symToAux(s) - v.AddArg2(ptr, mem) - return true - } return false } func rewriteValueAMD64_OpAMD64MOVLQSX(v *Value) bool { @@ -11493,49 +11362,6 @@ func rewriteValueAMD64_OpAMD64MOVLload(v *Value) bool { v.AddArg2(base, mem) return true } - // match: (MOVLload [off1] {sym1} (LEAL [off2] {sym2} base) mem) - // cond: canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) - // result: (MOVLload [off1+off2] {mergeSym(sym1,sym2)} base mem) - for { - off1 := auxIntToInt32(v.AuxInt) - sym1 := auxToSym(v.Aux) - if v_0.Op != OpAMD64LEAL { - break - } - off2 := auxIntToInt32(v_0.AuxInt) - sym2 := auxToSym(v_0.Aux) - base := v_0.Args[0] - mem := v_1 - if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) { - break - } - v.reset(OpAMD64MOVLload) - v.AuxInt = int32ToAuxInt(off1 + off2) - v.Aux = symToAux(mergeSym(sym1, sym2)) - v.AddArg2(base, mem) - return true - } - // match: (MOVLload [off1] {sym} (ADDLconst [off2] ptr) mem) - // cond: is32Bit(int64(off1)+int64(off2)) - // result: (MOVLload [off1+off2] {sym} ptr mem) - for { - off1 := auxIntToInt32(v.AuxInt) - sym := auxToSym(v.Aux) - if v_0.Op != OpAMD64ADDLconst { - break - } - off2 := auxIntToInt32(v_0.AuxInt) - ptr := v_0.Args[0] - mem := v_1 - if !(is32Bit(int64(off1) + int64(off2))) { - break - } - v.reset(OpAMD64MOVLload) - v.AuxInt = int32ToAuxInt(off1 + off2) - v.Aux = symToAux(sym) - v.AddArg2(ptr, mem) - return true - } // match: (MOVLload [off] {sym} ptr (MOVSSstore [off] {sym} ptr val _)) // result: (MOVLf2i val) for { @@ -11837,51 +11663,6 @@ func rewriteValueAMD64_OpAMD64MOVLstore(v *Value) bool { v.AddArg3(p, v0, mem) return true } - // match: (MOVLstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) - // cond: canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) - // result: (MOVLstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) - for { - off1 := auxIntToInt32(v.AuxInt) - sym1 := auxToSym(v.Aux) - if v_0.Op != OpAMD64LEAL { - break - } - off2 := auxIntToInt32(v_0.AuxInt) - sym2 := auxToSym(v_0.Aux) - base := v_0.Args[0] - val := v_1 - mem := v_2 - if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) { - break - } - v.reset(OpAMD64MOVLstore) - v.AuxInt = int32ToAuxInt(off1 + off2) - v.Aux = symToAux(mergeSym(sym1, sym2)) - v.AddArg3(base, val, mem) - return true - } - // match: (MOVLstore [off1] {sym} (ADDLconst [off2] ptr) val mem) - // cond: is32Bit(int64(off1)+int64(off2)) - // result: (MOVLstore [off1+off2] {sym} ptr val mem) - for { - off1 := auxIntToInt32(v.AuxInt) - sym := auxToSym(v.Aux) - if v_0.Op != OpAMD64ADDLconst { - break - } - off2 := auxIntToInt32(v_0.AuxInt) - ptr := v_0.Args[0] - val := v_1 - mem := v_2 - if !(is32Bit(int64(off1) + int64(off2))) { - break - } - v.reset(OpAMD64MOVLstore) - v.AuxInt = int32ToAuxInt(off1 + off2) - v.Aux = symToAux(sym) - v.AddArg3(ptr, val, mem) - return true - } // match: (MOVLstore {sym} [off] ptr y:(ADDLload x [off] {sym} ptr mem) mem) // cond: y.Uses==1 && clobber(y) // result: (ADDLmodify [off] {sym} ptr x mem) @@ -12365,49 +12146,6 @@ func rewriteValueAMD64_OpAMD64MOVLstoreconst(v *Value) bool { v.AddArg3(p, v0, mem) return true } - // match: (MOVLstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) - // cond: canMergeSym(sym1, sym2) && sc.canAdd32(off) - // result: (MOVLstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem) - for { - sc := auxIntToValAndOff(v.AuxInt) - sym1 := auxToSym(v.Aux) - if v_0.Op != OpAMD64LEAL { - break - } - off := auxIntToInt32(v_0.AuxInt) - sym2 := auxToSym(v_0.Aux) - ptr := v_0.Args[0] - mem := v_1 - if !(canMergeSym(sym1, sym2) && sc.canAdd32(off)) { - break - } - v.reset(OpAMD64MOVLstoreconst) - v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off)) - v.Aux = symToAux(mergeSym(sym1, sym2)) - v.AddArg2(ptr, mem) - return true - } - // match: (MOVLstoreconst [sc] {s} (ADDLconst [off] ptr) mem) - // cond: sc.canAdd32(off) - // result: (MOVLstoreconst [sc.addOffset32(off)] {s} ptr mem) - for { - sc := auxIntToValAndOff(v.AuxInt) - s := auxToSym(v.Aux) - if v_0.Op != OpAMD64ADDLconst { - break - } - off := auxIntToInt32(v_0.AuxInt) - ptr := v_0.Args[0] - mem := v_1 - if !(sc.canAdd32(off)) { - break - } - v.reset(OpAMD64MOVLstoreconst) - v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off)) - v.Aux = symToAux(s) - v.AddArg2(ptr, mem) - return true - } return false } func rewriteValueAMD64_OpAMD64MOVOload(v *Value) bool { @@ -12592,49 +12330,6 @@ func rewriteValueAMD64_OpAMD64MOVOstoreconst(v *Value) bool { v.AddArg2(ptr, mem) return true } - // match: (MOVOstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) - // cond: canMergeSym(sym1, sym2) && sc.canAdd32(off) - // result: (MOVOstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem) - for { - sc := auxIntToValAndOff(v.AuxInt) - sym1 := auxToSym(v.Aux) - if v_0.Op != OpAMD64LEAL { - break - } - off := auxIntToInt32(v_0.AuxInt) - sym2 := auxToSym(v_0.Aux) - ptr := v_0.Args[0] - mem := v_1 - if !(canMergeSym(sym1, sym2) && sc.canAdd32(off)) { - break - } - v.reset(OpAMD64MOVOstoreconst) - v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off)) - v.Aux = symToAux(mergeSym(sym1, sym2)) - v.AddArg2(ptr, mem) - return true - } - // match: (MOVOstoreconst [sc] {s} (ADDLconst [off] ptr) mem) - // cond: sc.canAdd32(off) - // result: (MOVOstoreconst [sc.addOffset32(off)] {s} ptr mem) - for { - sc := auxIntToValAndOff(v.AuxInt) - s := auxToSym(v.Aux) - if v_0.Op != OpAMD64ADDLconst { - break - } - off := auxIntToInt32(v_0.AuxInt) - ptr := v_0.Args[0] - mem := v_1 - if !(sc.canAdd32(off)) { - break - } - v.reset(OpAMD64MOVOstoreconst) - v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off)) - v.Aux = symToAux(s) - v.AddArg2(ptr, mem) - return true - } return false } func rewriteValueAMD64_OpAMD64MOVQatomicload(v *Value) bool { @@ -12805,49 +12500,6 @@ func rewriteValueAMD64_OpAMD64MOVQload(v *Value) bool { v.AddArg2(base, mem) return true } - // match: (MOVQload [off1] {sym1} (LEAL [off2] {sym2} base) mem) - // cond: canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) - // result: (MOVQload [off1+off2] {mergeSym(sym1,sym2)} base mem) - for { - off1 := auxIntToInt32(v.AuxInt) - sym1 := auxToSym(v.Aux) - if v_0.Op != OpAMD64LEAL { - break - } - off2 := auxIntToInt32(v_0.AuxInt) - sym2 := auxToSym(v_0.Aux) - base := v_0.Args[0] - mem := v_1 - if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) { - break - } - v.reset(OpAMD64MOVQload) - v.AuxInt = int32ToAuxInt(off1 + off2) - v.Aux = symToAux(mergeSym(sym1, sym2)) - v.AddArg2(base, mem) - return true - } - // match: (MOVQload [off1] {sym} (ADDLconst [off2] ptr) mem) - // cond: is32Bit(int64(off1)+int64(off2)) - // result: (MOVQload [off1+off2] {sym} ptr mem) - for { - off1 := auxIntToInt32(v.AuxInt) - sym := auxToSym(v.Aux) - if v_0.Op != OpAMD64ADDLconst { - break - } - off2 := auxIntToInt32(v_0.AuxInt) - ptr := v_0.Args[0] - mem := v_1 - if !(is32Bit(int64(off1) + int64(off2))) { - break - } - v.reset(OpAMD64MOVQload) - v.AuxInt = int32ToAuxInt(off1 + off2) - v.Aux = symToAux(sym) - v.AddArg2(ptr, mem) - return true - } // match: (MOVQload [off] {sym} ptr (MOVSDstore [off] {sym} ptr val _)) // result: (MOVQf2i val) for { @@ -12950,51 +12602,6 @@ func rewriteValueAMD64_OpAMD64MOVQstore(v *Value) bool { v.AddArg3(base, val, mem) return true } - // match: (MOVQstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) - // cond: canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) - // result: (MOVQstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) - for { - off1 := auxIntToInt32(v.AuxInt) - sym1 := auxToSym(v.Aux) - if v_0.Op != OpAMD64LEAL { - break - } - off2 := auxIntToInt32(v_0.AuxInt) - sym2 := auxToSym(v_0.Aux) - base := v_0.Args[0] - val := v_1 - mem := v_2 - if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) { - break - } - v.reset(OpAMD64MOVQstore) - v.AuxInt = int32ToAuxInt(off1 + off2) - v.Aux = symToAux(mergeSym(sym1, sym2)) - v.AddArg3(base, val, mem) - return true - } - // match: (MOVQstore [off1] {sym} (ADDLconst [off2] ptr) val mem) - // cond: is32Bit(int64(off1)+int64(off2)) - // result: (MOVQstore [off1+off2] {sym} ptr val mem) - for { - off1 := auxIntToInt32(v.AuxInt) - sym := auxToSym(v.Aux) - if v_0.Op != OpAMD64ADDLconst { - break - } - off2 := auxIntToInt32(v_0.AuxInt) - ptr := v_0.Args[0] - val := v_1 - mem := v_2 - if !(is32Bit(int64(off1) + int64(off2))) { - break - } - v.reset(OpAMD64MOVQstore) - v.AuxInt = int32ToAuxInt(off1 + off2) - v.Aux = symToAux(sym) - v.AddArg3(ptr, val, mem) - return true - } // match: (MOVQstore {sym} [off] ptr y:(ADDQload x [off] {sym} ptr mem) mem) // cond: y.Uses==1 && clobber(y) // result: (ADDQmodify [off] {sym} ptr x mem) @@ -13474,49 +13081,6 @@ func rewriteValueAMD64_OpAMD64MOVQstoreconst(v *Value) bool { v.AddArg2(p, mem) return true } - // match: (MOVQstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) - // cond: canMergeSym(sym1, sym2) && sc.canAdd32(off) - // result: (MOVQstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem) - for { - sc := auxIntToValAndOff(v.AuxInt) - sym1 := auxToSym(v.Aux) - if v_0.Op != OpAMD64LEAL { - break - } - off := auxIntToInt32(v_0.AuxInt) - sym2 := auxToSym(v_0.Aux) - ptr := v_0.Args[0] - mem := v_1 - if !(canMergeSym(sym1, sym2) && sc.canAdd32(off)) { - break - } - v.reset(OpAMD64MOVQstoreconst) - v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off)) - v.Aux = symToAux(mergeSym(sym1, sym2)) - v.AddArg2(ptr, mem) - return true - } - // match: (MOVQstoreconst [sc] {s} (ADDLconst [off] ptr) mem) - // cond: sc.canAdd32(off) - // result: (MOVQstoreconst [sc.addOffset32(off)] {s} ptr mem) - for { - sc := auxIntToValAndOff(v.AuxInt) - s := auxToSym(v.Aux) - if v_0.Op != OpAMD64ADDLconst { - break - } - off := auxIntToInt32(v_0.AuxInt) - ptr := v_0.Args[0] - mem := v_1 - if !(sc.canAdd32(off)) { - break - } - v.reset(OpAMD64MOVQstoreconst) - v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off)) - v.Aux = symToAux(s) - v.AddArg2(ptr, mem) - return true - } return false } func rewriteValueAMD64_OpAMD64MOVSDload(v *Value) bool { @@ -14135,49 +13699,6 @@ func rewriteValueAMD64_OpAMD64MOVWload(v *Value) bool { v.AddArg2(base, mem) return true } - // match: (MOVWload [off1] {sym1} (LEAL [off2] {sym2} base) mem) - // cond: canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) - // result: (MOVWload [off1+off2] {mergeSym(sym1,sym2)} base mem) - for { - off1 := auxIntToInt32(v.AuxInt) - sym1 := auxToSym(v.Aux) - if v_0.Op != OpAMD64LEAL { - break - } - off2 := auxIntToInt32(v_0.AuxInt) - sym2 := auxToSym(v_0.Aux) - base := v_0.Args[0] - mem := v_1 - if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) { - break - } - v.reset(OpAMD64MOVWload) - v.AuxInt = int32ToAuxInt(off1 + off2) - v.Aux = symToAux(mergeSym(sym1, sym2)) - v.AddArg2(base, mem) - return true - } - // match: (MOVWload [off1] {sym} (ADDLconst [off2] ptr) mem) - // cond: is32Bit(int64(off1)+int64(off2)) - // result: (MOVWload [off1+off2] {sym} ptr mem) - for { - off1 := auxIntToInt32(v.AuxInt) - sym := auxToSym(v.Aux) - if v_0.Op != OpAMD64ADDLconst { - break - } - off2 := auxIntToInt32(v_0.AuxInt) - ptr := v_0.Args[0] - mem := v_1 - if !(is32Bit(int64(off1) + int64(off2))) { - break - } - v.reset(OpAMD64MOVWload) - v.AuxInt = int32ToAuxInt(off1 + off2) - v.Aux = symToAux(sym) - v.AddArg2(ptr, mem) - return true - } // match: (MOVWload [off] {sym} (SB) _) // cond: symIsRO(sym) // result: (MOVLconst [int32(read16(sym, int64(off), config.ctxt.Arch.ByteOrder))]) @@ -14571,51 +14092,6 @@ func rewriteValueAMD64_OpAMD64MOVWstore(v *Value) bool { v.AddArg3(p, v0, mem) return true } - // match: (MOVWstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) - // cond: canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2)) - // result: (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) - for { - off1 := auxIntToInt32(v.AuxInt) - sym1 := auxToSym(v.Aux) - if v_0.Op != OpAMD64LEAL { - break - } - off2 := auxIntToInt32(v_0.AuxInt) - sym2 := auxToSym(v_0.Aux) - base := v_0.Args[0] - val := v_1 - mem := v_2 - if !(canMergeSym(sym1, sym2) && is32Bit(int64(off1)+int64(off2))) { - break - } - v.reset(OpAMD64MOVWstore) - v.AuxInt = int32ToAuxInt(off1 + off2) - v.Aux = symToAux(mergeSym(sym1, sym2)) - v.AddArg3(base, val, mem) - return true - } - // match: (MOVWstore [off1] {sym} (ADDLconst [off2] ptr) val mem) - // cond: is32Bit(int64(off1)+int64(off2)) - // result: (MOVWstore [off1+off2] {sym} ptr val mem) - for { - off1 := auxIntToInt32(v.AuxInt) - sym := auxToSym(v.Aux) - if v_0.Op != OpAMD64ADDLconst { - break - } - off2 := auxIntToInt32(v_0.AuxInt) - ptr := v_0.Args[0] - val := v_1 - mem := v_2 - if !(is32Bit(int64(off1) + int64(off2))) { - break - } - v.reset(OpAMD64MOVWstore) - v.AuxInt = int32ToAuxInt(off1 + off2) - v.Aux = symToAux(sym) - v.AddArg3(ptr, val, mem) - return true - } return false } func rewriteValueAMD64_OpAMD64MOVWstoreconst(v *Value) bool { @@ -14714,49 +14190,6 @@ func rewriteValueAMD64_OpAMD64MOVWstoreconst(v *Value) bool { v.AddArg2(p, mem) return true } - // match: (MOVWstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) - // cond: canMergeSym(sym1, sym2) && sc.canAdd32(off) - // result: (MOVWstoreconst [sc.addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem) - for { - sc := auxIntToValAndOff(v.AuxInt) - sym1 := auxToSym(v.Aux) - if v_0.Op != OpAMD64LEAL { - break - } - off := auxIntToInt32(v_0.AuxInt) - sym2 := auxToSym(v_0.Aux) - ptr := v_0.Args[0] - mem := v_1 - if !(canMergeSym(sym1, sym2) && sc.canAdd32(off)) { - break - } - v.reset(OpAMD64MOVWstoreconst) - v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off)) - v.Aux = symToAux(mergeSym(sym1, sym2)) - v.AddArg2(ptr, mem) - return true - } - // match: (MOVWstoreconst [sc] {s} (ADDLconst [off] ptr) mem) - // cond: sc.canAdd32(off) - // result: (MOVWstoreconst [sc.addOffset32(off)] {s} ptr mem) - for { - sc := auxIntToValAndOff(v.AuxInt) - s := auxToSym(v.Aux) - if v_0.Op != OpAMD64ADDLconst { - break - } - off := auxIntToInt32(v_0.AuxInt) - ptr := v_0.Args[0] - mem := v_1 - if !(sc.canAdd32(off)) { - break - } - v.reset(OpAMD64MOVWstoreconst) - v.AuxInt = valAndOffToAuxInt(sc.addOffset32(off)) - v.Aux = symToAux(s) - v.AddArg2(ptr, mem) - return true - } return false } func rewriteValueAMD64_OpAMD64MULL(v *Value) bool { -- GitLab From 891470fbf767a09ac2b00cc58dbaf9ee2a67b09e Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Thu, 12 Aug 2021 18:39:24 -0700 Subject: [PATCH 0922/2500] cmd/compile: fix handling of Defn field during stenciling When the Defn field of a name node is not an ONAME (for a closure variable), then it points to a body node of the same function/closure. Therefore, we should not attempt to substitute it at the time we are substituting the local variables. Instead, we remember a mapping from the Defn node to the nodes that reference it, and update the Defn fields of the copied name nodes at the time that we create the new copy of the Defn node. Added some comments to the Defn field of ir.Name. Moved the Defn (and Outer code, for consistency) from namelist() to localvar(), since Defn needs to updated for all local variables, not just those in a closure. Fixed case where .Defn was not being set properly in noder2 for type switches. Fixed another case where the Defn field had to be updated during transformSelect() because the Defn node was being completely changed to a new node. Fixed some spacing in typeswitch2.go Fixes #47676 Fixes #48016 Change-Id: Iae70dd76575f4a647c1db79e1eba9bbe44bfc226 Reviewed-on: https://go-review.googlesource.com/c/go/+/346290 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/ir/name.go | 2 + src/cmd/compile/internal/noder/stencil.go | 45 ++++++++++++++++++--- src/cmd/compile/internal/noder/stmt.go | 2 + src/cmd/compile/internal/noder/transform.go | 13 ++++-- test/typeparam/issue47676.go | 23 +++++++++++ test/typeparam/issue48016.go | 35 ++++++++++++++++ test/typeparam/typeswitch2.go | 4 +- 7 files changed, 112 insertions(+), 12 deletions(-) create mode 100644 test/typeparam/issue47676.go create mode 100644 test/typeparam/issue48016.go diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index a2eec05013..9fb22378cd 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -51,6 +51,8 @@ type Name struct { // For a local variable (not param) or extern, the initializing assignment (OAS or OAS2). // For a closure var, the ONAME node of the outer captured variable. // For the case-local variables of a type switch, the type switch guard (OTYPESW). + // For a range variable, the range statement (ORANGE) + // For a recv variable in a case of a select statement, the receive assignment (OSELRECV2) // For the name of a function, points to corresponding Func node. Defn Node diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 00c4676530..cf3894e096 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -627,6 +627,9 @@ type subster struct { newf *ir.Func // Func node for the new stenciled function ts typecheck.Tsubster info *instInfo // Place to put extra info in the instantiation + + // Map from non-nil, non-ONAME node n to slice of all m, where m.Defn = n + defnMap map[ir.Node][]**ir.Name } // genericSubst returns a new function with name newsym. The function is an @@ -675,6 +678,7 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes []*typ Targs: shapes, Vars: make(map[*ir.Name]*ir.Name), }, + defnMap: make(map[ir.Node][]**ir.Name), } newf.Dcl = make([]*ir.Name, 0, len(gf.Dcl)+1) @@ -726,6 +730,10 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes []*typ // to many->1 shape to concrete mapping. // newf.Body.Prepend(subst.checkDictionary(dictionaryName, shapes)...) + if len(subst.defnMap) > 0 { + base.Fatalf("defnMap is not empty") + } + ir.CurFunc = savef // Add any new, fully instantiated types seen during the substitution to // g.instTypeList. @@ -764,6 +772,25 @@ func (subst *subster) localvar(name *ir.Name) *ir.Name { m.Func = name.Func subst.ts.Vars[name] = m m.SetTypecheck(1) + if name.Defn != nil { + if name.Defn.Op() == ir.ONAME { + // This is a closure variable, so its Defn is the outer + // captured variable, which has already been substituted. + m.Defn = subst.node(name.Defn) + } else { + // The other values of Defn are nodes in the body of the + // function, so just remember the mapping so we can set Defn + // properly in node() when we create the new body node. We + // always call localvar() on all the local variables before + // we substitute the body. + slice := subst.defnMap[name.Defn] + subst.defnMap[name.Defn] = append(slice, &m) + } + } + if name.Outer != nil { + m.Outer = subst.node(name.Outer).(*ir.Name) + } + return m } @@ -871,6 +898,18 @@ func (subst *subster) node(n ir.Node) ir.Node { } } m := ir.Copy(x) + + slice, ok := subst.defnMap[x] + if ok { + // We just copied a non-ONAME node which was the Defn value + // of a local variable. Set the Defn value of the copied + // local variable to this new Defn node. + for _, ptr := range slice { + (*ptr).Defn = m + } + delete(subst.defnMap, x) + } + if _, isExpr := m.(ir.Expr); isExpr { t := x.Type() if t == nil { @@ -1312,12 +1351,6 @@ func (subst *subster) namelist(l []*ir.Name) []*ir.Name { s := make([]*ir.Name, len(l)) for i, n := range l { s[i] = subst.localvar(n) - if n.Defn != nil { - s[i].Defn = subst.node(n.Defn) - } - if n.Outer != nil { - s[i].Outer = subst.node(n.Outer).(*ir.Name) - } } return s } diff --git a/src/cmd/compile/internal/noder/stmt.go b/src/cmd/compile/internal/noder/stmt.go index fc1f5836ff..eeb994d343 100644 --- a/src/cmd/compile/internal/noder/stmt.go +++ b/src/cmd/compile/internal/noder/stmt.go @@ -327,6 +327,8 @@ func (g *irgen) switchStmt(stmt *syntax.SwitchStmt) ir.Node { if obj, ok := g.info.Implicits[clause]; ok { cv = g.obj(obj) cv.SetPos(g.makeXPos(clause.Colon)) + assert(expr.Op() == ir.OTYPESW) + cv.Defn = expr } body[i] = ir.NewCaseStmt(g.pos(clause), g.exprList(clause.Cases), g.stmts(clause.Body)) body[i].Var = cv diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index a27f511769..180891b5b5 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -493,10 +493,15 @@ func transformSelect(sel *ir.SelectStmt) { if ncase.Comm != nil { n := ncase.Comm oselrecv2 := func(dst, recv ir.Node, def bool) { - n := ir.NewAssignListStmt(n.Pos(), ir.OSELRECV2, []ir.Node{dst, ir.BlankNode}, []ir.Node{recv}) - n.Def = def - n.SetTypecheck(1) - ncase.Comm = n + selrecv := ir.NewAssignListStmt(n.Pos(), ir.OSELRECV2, []ir.Node{dst, ir.BlankNode}, []ir.Node{recv}) + if dst.Op() == ir.ONAME && dst.(*ir.Name).Defn == n { + // Must fix Defn for dst, since we are + // completely changing the node. + dst.(*ir.Name).Defn = selrecv + } + selrecv.Def = def + selrecv.SetTypecheck(1) + ncase.Comm = selrecv } switch n.Op() { case ir.OAS: diff --git a/test/typeparam/issue47676.go b/test/typeparam/issue47676.go new file mode 100644 index 0000000000..1b01624ce0 --- /dev/null +++ b/test/typeparam/issue47676.go @@ -0,0 +1,23 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func main() { + d := diff([]int{}, func(int) string { + return "foo" + }) + d() +} + +func diff[T any](previous []T, uniqueKey func(T) string) func() { + return func() { + newJSON := map[string]T{} + for _, prev := range previous { + delete(newJSON, uniqueKey(prev)) + } + } +} diff --git a/test/typeparam/issue48016.go b/test/typeparam/issue48016.go new file mode 100644 index 0000000000..582751e884 --- /dev/null +++ b/test/typeparam/issue48016.go @@ -0,0 +1,35 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + "strconv" +) + +func test1[T any](fn func(T) int, v T) int { + fn1 := func() int { + var i interface{} = v + val := fn(i.(T)) + return val + } + return fn1() +} + +func main() { + want := 123 + got := test1(func(s string) int { + r, err := strconv.Atoi(s) + if err != nil { + return 0 + } + return r + }, "123") + if got != want { + panic(fmt.Sprintf("got %f, want %f", got, want)) + } +} diff --git a/test/typeparam/typeswitch2.go b/test/typeparam/typeswitch2.go index 913c56321c..0e434e1383 100644 --- a/test/typeparam/typeswitch2.go +++ b/test/typeparam/typeswitch2.go @@ -16,7 +16,7 @@ func f[T any](i interface{}) { println("int", x) case int32, int16: println("int32/int16", reflect.ValueOf(x).Int()) - case struct { a, b T }: + case struct{ a, b T }: println("struct{T,T}", x.a, x.b) default: println("other", reflect.ValueOf(x).Int()) @@ -26,6 +26,6 @@ func main() { f[float64](float64(6)) f[float64](int(7)) f[float64](int32(8)) - f[float64](struct{a, b float64}{a:1, b:2}) + f[float64](struct{ a, b float64 }{a: 1, b: 2}) f[float64](int8(9)) } -- GitLab From 18c288ef8b8a3e7d2c02d3bb4c06e9f7c006b9da Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Mon, 16 Aug 2021 16:16:51 -0700 Subject: [PATCH 0923/2500] [dev.fuzz] internal/fuzz: ensure crash is written if minimization interrupted If any error occurs when minimizing a crash, for example, the user presses ^C because minimization is taking too long, the coordinator will now write the unminimized crash to testdata. Change-Id: I0c754125781eb184846e496c728e0505a28639d9 Reviewed-on: https://go-review.googlesource.com/c/go/+/342995 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/internal/fuzz/fuzz.go | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index b06ab146f7..9a9a4564c2 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -133,6 +133,27 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err inputC = nil } + // Ensure that any crash we find is written to the corpus, even if an error + // or interruption occurs while minimizing it. + var crashMinimizing *fuzzResult + crashWritten := false + defer func() { + if crashMinimizing == nil || crashWritten { + return + } + fileName, werr := writeToCorpus(crashMinimizing.entry.Data, opts.CorpusDir) + if werr != nil { + err = fmt.Errorf("%w\n%v", err, werr) + return + } + if err == nil { + err = &crashError{ + name: filepath.Base(fileName), + err: errors.New(crashMinimizing.crasherMsg), + } + } + }() + // Start workers. // TODO(jayconrod): do we want to support fuzzing different binaries? dir := "" // same as self @@ -175,8 +196,6 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err statTicker := time.NewTicker(3 * time.Second) defer statTicker.Stop() defer c.logStats() - crashMinimizing := false - crashWritten := false for { select { @@ -194,7 +213,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err if result.crasherMsg != "" { if c.canMinimize() && !result.minimizeAttempted { - if crashMinimizing { + if crashMinimizing != nil { // This crash is not minimized, and another crash is being minimized. // Ignore this one and wait for the other one to finish. break @@ -202,7 +221,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err // Found a crasher but haven't yet attempted to minimize it. // Send it back to a worker for minimization. Disable inputC so // other workers don't continue fuzzing. - crashMinimizing = true + crashMinimizing = &result inputC = nil fmt.Fprintf(c.opts.Log, "found a crash, minimizing...\n") c.minimizeC <- c.minimizeInputForResult(result) @@ -304,7 +323,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err } } } - if inputC == nil && !crashMinimizing && !stopping && !c.coverageOnlyRun() { + if inputC == nil && crashMinimizing == nil && !stopping && !c.coverageOnlyRun() { // Re-enable inputC if it was disabled earlier because we hit the limit // on the number of inputs to fuzz (nextInput returned false). Workers // can do less work than requested, so after receiving a result above, -- GitLab From 37f5885f29068d869e161c4ee8ee17c3e1195cc8 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Mon, 16 Aug 2021 16:48:27 -0700 Subject: [PATCH 0924/2500] [dev.fuzz] internal/fuzz: fail minimization on non-reproducible crash workerServer.minimize now returns a response with Success = false when the fuzz function run with the original input does not produce an error. This may indicate flakiness. The coordinator still records a crash, but it will use the unminimized input with its original error message. When minimization of interesting inputs is supported, Success = false indicates that new coverage couldn't be reproduced, and the input will be discarded. Change-Id: I72c0e9808f0b0e5390dc7b64141cd0d653ee0af3 Reviewed-on: https://go-review.googlesource.com/c/go/+/342996 Trust: Jay Conrod Trust: Katie Hockman Reviewed-by: Katie Hockman --- .../go/testdata/script/test_fuzz_minimize.txt | 2 +- src/internal/fuzz/minimize_test.go | 51 +++++++++++++------ src/internal/fuzz/worker.go | 49 +++++++++--------- 3 files changed, 62 insertions(+), 40 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize.txt b/src/cmd/go/testdata/script/test_fuzz_minimize.txt index 337059da3f..473d63ebfa 100644 --- a/src/cmd/go/testdata/script/test_fuzz_minimize.txt +++ b/src/cmd/go/testdata/script/test_fuzz_minimize.txt @@ -24,7 +24,7 @@ rm testdata ! go test -fuzz=FuzzMinimizerNonrecoverable -run=FuzzMinimizerNonrecoverable -fuzztime=10000x minimizer_test.go ! stdout '^ok' stdout 'found a crash, minimizing' -stdout 'fuzzing process terminated unexpectedly while minimizing: exit status 99' +stdout 'fuzzing process terminated unexpectedly: exit status 99' stdout FAIL # Check that re-running the value causes a crash. diff --git a/src/internal/fuzz/minimize_test.go b/src/internal/fuzz/minimize_test.go index d786cf809e..bcb0572d19 100644 --- a/src/internal/fuzz/minimize_test.go +++ b/src/internal/fuzz/minimize_test.go @@ -16,12 +16,14 @@ import ( func TestMinimizeInput(t *testing.T) { type testcase struct { + name string fn func(CorpusEntry) error input []interface{} expected []interface{} } cases := []testcase{ { + name: "ones_byte", fn: func(e CorpusEntry) error { b := e.Values[0].([]byte) ones := 0 @@ -39,6 +41,7 @@ func TestMinimizeInput(t *testing.T) { expected: []interface{}{[]byte{1, 1, 1}}, }, { + name: "ones_string", fn: func(e CorpusEntry) error { b := e.Values[0].(string) ones := 0 @@ -56,6 +59,7 @@ func TestMinimizeInput(t *testing.T) { expected: []interface{}{"111"}, }, { + name: "int", fn: func(e CorpusEntry) error { i := e.Values[0].(int) if i > 100 { @@ -67,6 +71,7 @@ func TestMinimizeInput(t *testing.T) { expected: []interface{}{123}, }, { + name: "int8", fn: func(e CorpusEntry) error { i := e.Values[0].(int8) if i > 10 { @@ -78,6 +83,7 @@ func TestMinimizeInput(t *testing.T) { expected: []interface{}{int8(12)}, }, { + name: "int16", fn: func(e CorpusEntry) error { i := e.Values[0].(int16) if i > 10 { @@ -100,6 +106,7 @@ func TestMinimizeInput(t *testing.T) { expected: []interface{}{int32(21)}, }, { + name: "int32", fn: func(e CorpusEntry) error { i := e.Values[0].(uint) if i > 10 { @@ -111,6 +118,7 @@ func TestMinimizeInput(t *testing.T) { expected: []interface{}{uint(12)}, }, { + name: "uint8", fn: func(e CorpusEntry) error { i := e.Values[0].(uint8) if i > 10 { @@ -122,6 +130,7 @@ func TestMinimizeInput(t *testing.T) { expected: []interface{}{uint8(25)}, }, { + name: "uint16", fn: func(e CorpusEntry) error { i := e.Values[0].(uint16) if i > 10 { @@ -133,6 +142,7 @@ func TestMinimizeInput(t *testing.T) { expected: []interface{}{uint16(65)}, }, { + name: "uint32", fn: func(e CorpusEntry) error { i := e.Values[0].(uint32) if i > 10 { @@ -144,6 +154,7 @@ func TestMinimizeInput(t *testing.T) { expected: []interface{}{uint32(42)}, }, { + name: "float32", fn: func(e CorpusEntry) error { if i := e.Values[0].(float32); i == 1.23 { return nil @@ -154,6 +165,7 @@ func TestMinimizeInput(t *testing.T) { expected: []interface{}{float32(1.2)}, }, { + name: "float64", fn: func(e CorpusEntry) error { if i := e.Values[0].(float64); i == 1.23 { return nil @@ -168,6 +180,7 @@ func TestMinimizeInput(t *testing.T) { // If we are on a 64 bit platform add int64 and uint64 tests if v := int64(1<<63 - 1); int64(int(v)) == v { cases = append(cases, testcase{ + name: "int64", fn: func(e CorpusEntry) error { i := e.Values[0].(int64) if i > 10 { @@ -178,6 +191,7 @@ func TestMinimizeInput(t *testing.T) { input: []interface{}{int64(1<<63 - 1)}, expected: []interface{}{int64(92)}, }, testcase{ + name: "uint64", fn: func(e CorpusEntry) error { i := e.Values[0].(uint64) if i > 10 { @@ -191,20 +205,27 @@ func TestMinimizeInput(t *testing.T) { } for _, tc := range cases { - ws := &workerServer{ - fuzzFn: tc.fn, - } - count := int64(0) - vals := tc.input - err := ws.minimizeInput(context.Background(), vals, &count, 0) - if err == nil { - t.Error("minimizeInput didn't fail") - } - if expected := fmt.Sprintf("bad %v", tc.input[0]); err.Error() != expected { - t.Errorf("unexpected error: got %s, want %s", err, expected) - } - if !reflect.DeepEqual(vals, tc.expected) { - t.Errorf("unexpected results: got %v, want %v", vals, tc.expected) - } + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + ws := &workerServer{ + fuzzFn: tc.fn, + } + count := int64(0) + vals := tc.input + success, err := ws.minimizeInput(context.Background(), vals, &count, 0) + if !success { + t.Errorf("minimizeInput did not succeed") + } + if err == nil { + t.Error("minimizeInput didn't fail") + } + if expected := fmt.Sprintf("bad %v", tc.input[0]); err.Error() != expected { + t.Errorf("unexpected error: got %s, want %s", err, expected) + } + if !reflect.DeepEqual(vals, tc.expected) { + t.Errorf("unexpected results: got %v, want %v", vals, tc.expected) + } + }) } } diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 8a5c8696de..81c5157dab 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -196,11 +196,8 @@ func (w *worker) coordinate(ctx context.Context) error { totalDuration: resp.TotalDuration, entryDuration: resp.InterestingDuration, entry: entry, - } - if resp.Err != "" { - result.crasherMsg = resp.Err - } else if resp.CoverageData != nil { - result.coverageData = resp.CoverageData + crasherMsg: resp.Err, + coverageData: resp.CoverageData, } w.coordinator.resultC <- result @@ -208,14 +205,19 @@ func (w *worker) coordinate(ctx context.Context) error { // Received input to minimize from coordinator. result, err := w.minimize(ctx, input) if err != nil { - // Failed to minimize. Send back the original crash. - fmt.Fprintln(w.coordinator.opts.Log, err) + // Error minimizing. Send back the original input. If it didn't cause + // an error before, report it as causing an error now. + // TODO(fuzz): double-check this is handled correctly when + // implementing -keepfuzzing. result = fuzzResult{ entry: input.entry, crasherMsg: input.crasherMsg, minimizeAttempted: true, limit: input.limit, } + if result.crasherMsg == "" { + result.crasherMsg = err.Error() + } } w.coordinator.resultC <- result } @@ -223,11 +225,9 @@ func (w *worker) coordinate(ctx context.Context) error { } // minimize tells a worker process to attempt to find a smaller value that -// causes an error. minimize may restart the worker repeatedly if the error -// causes (or already caused) the worker process to terminate. -// -// TODO: support minimizing inputs that expand coverage in a specific way, -// for example, by ensuring that an input activates a specific set of counters. +// either causes an error (if we started minimizing because we found an input +// that causes an error) or preserves new coverage (if we started minimizing +// because we found an input that expands coverage). func (w *worker) minimize(ctx context.Context, input fuzzMinimizeInput) (min fuzzResult, err error) { if w.coordinator.opts.MinimizeTimeout != 0 { var cancel func() @@ -261,10 +261,10 @@ func (w *worker) minimize(ctx context.Context, input fuzzMinimizeInput) (min fuz return fuzzResult{}, fmt.Errorf("fuzzing process terminated unexpectedly while minimizing: %w", w.waitErr) } - if resp.Err == "" { - // Minimization did not find a smaller input that caused a crash. - return min, nil + if input.crasherMsg != "" && resp.Err == "" && !resp.Success { + return fuzzResult{}, fmt.Errorf("attempted to minimize but could not reproduce") } + min.crasherMsg = resp.Err min.count = resp.Count min.totalDuration = resp.Duration @@ -498,9 +498,11 @@ type minimizeArgs struct { // minimizeResponse contains results from workerServer.minimize. type minimizeResponse struct { - // Err is the error string caused by the value in shared memory. - // If Err is empty, minimize was unable to find any shorter values that - // caused errors, and the value in shared memory is the original value. + // Success is true if the worker found a smaller input, stored in shared + // memory, that was "interesting" for the same reason as the original input. + Success bool + + // Err is the error string caused by the value in shared memory, if any. Err string // Duration is the time spent minimizing, not including starting or cleaning up. @@ -734,7 +736,7 @@ func (ws *workerServer) minimize(ctx context.Context, args minimizeArgs) (resp m // Minimize the values in vals, then write to shared memory. We only write // to shared memory after completing minimization. If the worker terminates // unexpectedly before then, the coordinator will use the original input. - err = ws.minimizeInput(ctx, vals, &mem.header().count, args.Limit) + resp.Success, err = ws.minimizeInput(ctx, vals, &mem.header().count, args.Limit) writeToMem(vals, mem) if err != nil { resp.Err = err.Error() @@ -748,16 +750,15 @@ func (ws *workerServer) minimize(ctx context.Context, args minimizeArgs) (resp m // mem just in case an unrecoverable error occurs. It uses the context to // determine how long to run, stopping once closed. It returns the last error it // found. -func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, count *int64, limit int64) error { +func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, count *int64, limit int64) (success bool, retErr error) { shouldStop := func() bool { return ctx.Err() != nil || (limit > 0 && *count >= limit) } if shouldStop() { - return nil + return false, nil } var valI int - var retErr error tryMinimized := func(candidate interface{}) bool { prev := vals[valI] // Set vals[valI] to the candidate after it has been @@ -822,7 +823,7 @@ func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, c for valI = range vals { if shouldStop() { - return retErr + break } switch v := vals[valI].(type) { case bool: @@ -869,7 +870,7 @@ func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, c panic("unreachable") } } - return retErr + return retErr != nil, retErr } func writeToMem(vals []interface{}, mem *sharedMem) { -- GitLab From aed59d172ad532bd2eedcf78ba97fdd113d2dccd Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 31 Aug 2021 14:03:33 -0400 Subject: [PATCH 0925/2500] go/types: allow composite literals of type parameter type This is a port of CL 342690 to go/types. Change-Id: I27dcde237e400a84c3394a3579805014777830bc Reviewed-on: https://go-review.googlesource.com/c/go/+/346432 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/expr.go | 2 +- src/go/types/testdata/examples/types.go2 | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/go/types/expr.go b/src/go/types/expr.go index b0e2a27085..61d57cc4fa 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -1184,7 +1184,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { goto Error } - switch utyp := under(base).(type) { + switch utyp := optype(base).(type) { case *Struct: if len(e.Elts) == 0 { break diff --git a/src/go/types/testdata/examples/types.go2 b/src/go/types/testdata/examples/types.go2 index 82f17a3263..1aebb411c6 100644 --- a/src/go/types/testdata/examples/types.go2 +++ b/src/go/types/testdata/examples/types.go2 @@ -191,7 +191,7 @@ type _ struct { //} // It is not permitted to declare a local type whose underlying -// type is a type parameters not declared by that type declaration. +// type is a type parameter not declared by that type declaration. func _[T any]() { type _ T // ERROR cannot use function type parameter T as RHS in type declaration type _ [_ any] T // ERROR cannot use function type parameter T as RHS in type declaration @@ -294,3 +294,18 @@ func _[T interface {~int|~float64}]() { _ = T(0) } +// It is possible to create composite literals of type parameter +// type as long as it's possible to create a composite literal +// of the structural type of the type parameter's constraint. +func _[P interface{ ~[]int }]() P { + return P{} + return P{1, 2, 3} +} + +func _[P interface{ ~[]E }, E interface{ map[string]P } ]() P { + x := P{} + return P{{}} + return P{E{}} + return P{E{"foo": x}} + return P{{"foo": x}, {}} +} -- GitLab From b93581e47d358da9fc2d08032cd73797c2cb28a5 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 31 Aug 2021 14:41:29 -0400 Subject: [PATCH 0926/2500] go/types: add error reporting for 1.18 syntax if GoVersion is below 1.18 This is a port of CL 344871 to go/types. Unlike the compiler, go/parser is already always producing 1.18 syntax, so the effect of this CL is to add some additional errors when Config.GoVersion is below 1.18. This is a non-trivial port, both due to different error reporting APIs and due to interacting with declaration syntax nodes, which differ between go/ast and cmd/compile/internal/syntax. Change-Id: I8003a014e6eec5e554c24e9a6cfc0548ec534834 Reviewed-on: https://go-review.googlesource.com/c/go/+/346433 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/call.go | 13 ++++ src/go/types/decl.go | 23 +++++++- src/go/types/resolver.go | 14 ++++- src/go/types/subst.go | 2 +- src/go/types/testdata/check/decls0.src | 2 +- src/go/types/testdata/check/issues.src | 6 +- src/go/types/testdata/check/main.go2 | 2 +- src/go/types/testdata/check/typeparams.go2 | 4 +- .../types/testdata/fixedbugs/issue47818.go2 | 59 +++++++++++++++++++ src/go/types/typeset.go | 11 +++- src/go/types/typexpr.go | 15 ++--- 11 files changed, 129 insertions(+), 22 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue47818.go2 diff --git a/src/go/types/call.go b/src/go/types/call.go index 61534b6328..78c81e13e9 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -17,6 +17,10 @@ import ( // funcInst type-checks a function instantiation inst and returns the result in x. // The operand x must be the evaluation of inst.X and its type must be a signature. func (check *Checker) funcInst(x *operand, ix *typeparams.IndexExpr) { + if !check.allowVersion(check.pkg, 1, 18) { + check.softErrorf(inNode(ix.Orig, ix.Lbrack), _Todo, "function instantiation requires go1.18 or later") + } + targs := check.typeList(ix.Indices) if targs == nil { x.mode = invalid @@ -324,6 +328,15 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type // infer type arguments and instantiate signature if necessary if sig.TParams().Len() > 0 { + if !check.allowVersion(check.pkg, 1, 18) { + switch call.Fun.(type) { + case *ast.IndexExpr, *ast.MultiIndexExpr: + ix := typeparams.UnpackIndexExpr(call.Fun) + check.softErrorf(inNode(call.Fun, ix.Lbrack), _Todo, "function instantiation requires go1.18 or later") + default: + check.softErrorf(inNode(call, call.Lparen), _Todo, "implicit function instantiation requires go1.18 or later") + } + } // TODO(gri) provide position information for targs so we can feed // it to the instantiate call for better error reporting targs := check.infer(call, sig.TParams().list(), targs, sigParams, args, true) diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 8ebaf289f1..8222cb3fc3 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -567,11 +567,26 @@ func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init ast.Expr) { check.initVars(lhs, []ast.Expr{init}, token.NoPos) } +// isImportedConstraint reports whether typ is an imported type constraint. +func (check *Checker) isImportedConstraint(typ Type) bool { + named, _ := typ.(*Named) + if named == nil || named.obj.pkg == check.pkg || named.obj.pkg == nil { + return false + } + u, _ := named.under().(*Interface) + return u != nil && u.IsConstraint() +} + func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { assert(obj.typ == nil) + var rhs Type check.later(func() { check.validType(obj.typ, nil) + // If typ is local, an error was already reported where typ is specified/defined. + if check.isImportedConstraint(rhs) && !check.allowVersion(check.pkg, 1, 18) { + check.errorf(tdecl.Type, _Todo, "using type constraint %s requires go1.18 or later", rhs) + } }) alias := tdecl.Assign.IsValid() @@ -589,7 +604,8 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { } obj.typ = Typ[Invalid] - obj.typ = check.anyType(tdecl.Type) + rhs = check.anyType(tdecl.Type) + obj.typ = rhs return } @@ -604,8 +620,9 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { } // determine underlying type of named - named.fromRHS = check.definedType(tdecl.Type, named) - assert(named.fromRHS != nil) + rhs = check.definedType(tdecl.Type, named) + assert(rhs != nil) + named.fromRHS = rhs // The underlying type of named may be itself a named type that is // incomplete: diff --git a/src/go/types/resolver.go b/src/go/types/resolver.go index 5e58c3dcfd..fb7e0cc474 100644 --- a/src/go/types/resolver.go +++ b/src/go/types/resolver.go @@ -381,12 +381,15 @@ func (check *Checker) collectObjects() { check.declarePkgObj(name, obj, di) } case typeDecl: + if d.spec.TParams.NumFields() != 0 && !check.allowVersion(pkg, 1, 18) { + check.softErrorf(d.spec.TParams.List[0], _Todo, "type parameters require go1.18 or later") + } obj := NewTypeName(d.spec.Name.Pos(), pkg, d.spec.Name.Name, nil) check.declarePkgObj(d.spec.Name, obj, &declInfo{file: fileScope, tdecl: d.spec}) case funcDecl: - info := &declInfo{file: fileScope, fdecl: d.decl} name := d.decl.Name.Name obj := NewFunc(d.decl.Name.Pos(), pkg, name, nil) + hasTParamError := false // avoid duplicate type parameter errors if d.decl.Recv.NumFields() == 0 { // regular function if d.decl.Recv != nil { @@ -398,8 +401,9 @@ func (check *Checker) collectObjects() { if name == "main" { code = _InvalidMainDecl } - if tparams := typeparams.Get(d.decl.Type); tparams != nil { - check.softErrorf(tparams, code, "func %s must have no type parameters", name) + if d.decl.Type.TParams.NumFields() != 0 { + check.softErrorf(d.decl.Type.TParams.List[0], code, "func %s must have no type parameters", name) + hasTParamError = true } if t := d.decl.Type; t.Params.NumFields() != 0 || t.Results != nil { // TODO(rFindley) Should this be a hard error? @@ -435,6 +439,10 @@ func (check *Checker) collectObjects() { } check.recordDef(d.decl.Name, obj) } + if d.decl.Type.TParams.NumFields() != 0 && !check.allowVersion(pkg, 1, 18) && !hasTParamError { + check.softErrorf(d.decl.Type.TParams.List[0], _Todo, "type parameters require go1.18 or later") + } + info := &declInfo{file: fileScope, fdecl: d.decl} // Methods are not package-level objects but we still track them in the // object map so that we can handle them like regular functions (if the // receiver is invalid); also we need their fdecl info when associating diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 1c53cdaf2c..d3b1cad13a 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -41,7 +41,7 @@ func (m substMap) lookup(tpar *TypeParam) Type { // subst returns the type typ with its type parameters tpars replaced by the // corresponding type arguments targs, recursively. subst is pure in the sense // that it doesn't modify the incoming type. If a substitution took place, the -// result type is different from from the incoming type. +// result type is different from the incoming type. // // If the given typMap is non-nil, it is used in lieu of check.typMap. func (check *Checker) subst(pos token.Pos, typ Type, smap substMap, typMap map[string]*Named) Type { diff --git a/src/go/types/testdata/check/decls0.src b/src/go/types/testdata/check/decls0.src index 1224e46377..18f0d32e1b 100644 --- a/src/go/types/testdata/check/decls0.src +++ b/src/go/types/testdata/check/decls0.src @@ -146,7 +146,7 @@ type ( m1(I5) } I6 interface { - S0 /* ERROR "not an interface" */ + S0 /* ERROR "non-interface type S0" */ } I7 interface { I1 diff --git a/src/go/types/testdata/check/issues.src b/src/go/types/testdata/check/issues.src index ef1737331d..88ce452959 100644 --- a/src/go/types/testdata/check/issues.src +++ b/src/go/types/testdata/check/issues.src @@ -79,11 +79,11 @@ func issue9473(a []int, b ...int) { // Check that embedding a non-interface type in an interface results in a good error message. func issue10979() { type _ interface { - int /* ERROR int is not an interface */ + int /* ERROR non-interface type int */ } type T struct{} type _ interface { - T /* ERROR T is not an interface */ + T /* ERROR non-interface type T */ } type _ interface { nosuchtype /* ERROR undeclared name: nosuchtype */ @@ -280,7 +280,7 @@ type issue25301b /* ERROR cycle */ = interface { } type issue25301c interface { - notE // ERROR struct\{\} is not an interface + notE // ERROR non-interface type struct\{\} } type notE = struct{} diff --git a/src/go/types/testdata/check/main.go2 b/src/go/types/testdata/check/main.go2 index 65e9aa2962..fb567a07d0 100644 --- a/src/go/types/testdata/check/main.go2 +++ b/src/go/types/testdata/check/main.go2 @@ -4,4 +4,4 @@ package main -func main[ /* ERROR "func main must have no type parameters" */ T any]() {} +func main[T /* ERROR "func main must have no type parameters" */ any]() {} diff --git a/src/go/types/testdata/check/typeparams.go2 b/src/go/types/testdata/check/typeparams.go2 index bd89d1ecad..57b6d7a0ad 100644 --- a/src/go/types/testdata/check/typeparams.go2 +++ b/src/go/types/testdata/check/typeparams.go2 @@ -304,8 +304,8 @@ var _ = f8[int, float64](0, 0, nil...) // test case for #18268 // init functions cannot have type parameters func init() {} -func init[/* ERROR func init must have no type parameters */ _ any]() {} -func init[/* ERROR func init must have no type parameters */ P any]() {} +func init[_ /* ERROR func init must have no type parameters */ any]() {} +func init[P /* ERROR func init must have no type parameters */ any]() {} type T struct {} diff --git a/src/go/types/testdata/fixedbugs/issue47818.go2 b/src/go/types/testdata/fixedbugs/issue47818.go2 new file mode 100644 index 0000000000..68c6a94ed4 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue47818.go2 @@ -0,0 +1,59 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Parser accepts type parameters but the type checker +// needs to report any operations that are not permitted +// before Go 1.18. + +package go1_17 + +type T[P /* ERROR type parameters require go1\.18 or later */ any] struct{} + +// for init (and main, but we're not in package main) we should only get one error +func init[P /* ERROR func init must have no type parameters */ any]() {} +func main[P /* ERROR type parameters require go1\.18 or later */ any]() {} + +func f[P /* ERROR type parameters require go1\.18 or later */ any](x P) { + var _ T[ /* ERROR type instantiation requires go1\.18 or later */ int] + var _ (T[ /* ERROR type instantiation requires go1\.18 or later */ int]) + _ = T[ /* ERROR type instantiation requires go1\.18 or later */ int]{} + _ = T[ /* ERROR type instantiation requires go1\.18 or later */ int](struct{}{}) +} + +func (T[ /* ERROR type instantiation requires go1\.18 or later */ P]) g(x int) { + f[ /* ERROR function instantiation requires go1\.18 or later */ int](0) // explicit instantiation + (f[ /* ERROR function instantiation requires go1\.18 or later */ int])(0) // parentheses (different code path) + f( /* ERROR implicit function instantiation requires go1\.18 or later */ x) // implicit instantiation +} + +type C1 interface { + comparable // ERROR undeclared name: comparable \(requires version go1\.18 or later\) +} + +type C2 interface { + comparable // ERROR undeclared name: comparable \(requires version go1\.18 or later\) + int // ERROR embedding non-interface type int requires go1\.18 or later + ~ /* ERROR embedding interface element ~int requires go1\.18 or later */ int + int /* ERROR embedding interface element int\|~string requires go1\.18 or later */ | ~string +} + +type _ interface { + // errors for these were reported with their declaration + C1 + C2 +} + +type ( + _ comparable // ERROR undeclared name: comparable \(requires version go1\.18 or later\) + // errors for these were reported with their declaration + _ C1 + _ C2 + + _ = comparable // ERROR undeclared name: comparable \(requires version go1\.18 or later\) + // errors for these were reported with their declaration + _ = C1 + _ = C2 +) + +// TODO(gri) need test cases for imported constraint types (see also issue #47967) diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index 7bdc708d4c..fd9df4c010 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -269,6 +269,11 @@ func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_T switch u := under(typ).(type) { case *Interface: tset := computeInterfaceTypeSet(check, pos, u) + // If typ is local, an error was already reported where typ is specified/defined. + if check != nil && check.isImportedConstraint(typ) && !check.allowVersion(check.pkg, 1, 18) { + check.errorf(atPos(pos), _Todo, "embedding constraint interface %s requires go1.18 or later", typ) + continue + } if tset.comparable { ityp.tset.comparable = true } @@ -277,6 +282,10 @@ func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_T } terms = tset.terms case *Union: + if check != nil && !check.allowVersion(check.pkg, 1, 18) { + check.errorf(atPos(pos), _Todo, "embedding interface element %s requires go1.18 or later", u) + continue + } tset := computeUnionTypeSet(check, pos, u) if tset == &invalidTypeSet { continue // ignore invalid unions @@ -291,7 +300,7 @@ func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_T continue } if check != nil && !check.allowVersion(check.pkg, 1, 18) { - check.errorf(atPos(pos), _InvalidIfaceEmbed, "%s is not an interface", typ) + check.errorf(atPos(pos), _InvalidIfaceEmbed, "embedding non-interface type %s requires go1.18 or later", typ) continue } terms = termlist{{false, typ}} diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 5c8a6b497d..5a67982030 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -36,14 +36,12 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool) } return case universeAny, universeComparable: + // complain if necessary but keep going if !check.allowVersion(check.pkg, 1, 18) { - check.errorf(e, _UndeclaredName, "undeclared name: %s (requires version go1.18 or later)", e.Name) - return - } - // If we allow "any" for general use, this if-statement can be removed (issue #33232). - if obj == universeAny { - check.error(e, _Todo, "cannot use any outside constraint position") - return + check.softErrorf(e, _UndeclaredName, "undeclared name: %s (requires version go1.18 or later)", e.Name) + } else if obj == universeAny { + // If we allow "any" for general use, this if-statement can be removed (issue #33232). + check.softErrorf(e, _Todo, "cannot use any outside constraint position") } } check.recordUse(e, obj) @@ -273,6 +271,9 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) { case *ast.IndexExpr, *ast.MultiIndexExpr: ix := typeparams.UnpackIndexExpr(e) + if !check.allowVersion(check.pkg, 1, 18) { + check.softErrorf(inNode(e, ix.Lbrack), _Todo, "type instantiation requires go1.18 or later") + } // TODO(rfindley): type instantiation should require go1.18 return check.instantiatedType(ix.X, ix.Indices, def) -- GitLab From ae2b2dc01ac5a7e8ef3f5a78d65a7a85b2324118 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 31 Aug 2021 14:57:24 -0400 Subject: [PATCH 0927/2500] go/types: rename IsMethodSet to IsConstraint (cleanup) This is a port of CL 344872 to go/types. Change-Id: Id794f1fc3b86779ee32dbe5e656ffc747d44c3e2 Reviewed-on: https://go-review.googlesource.com/c/go/+/346434 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/interface.go | 2 +- src/go/types/typeset.go | 6 ++---- src/go/types/typexpr.go | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/go/types/interface.go b/src/go/types/interface.go index d27f8cfd4d..e9970ba101 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -105,7 +105,7 @@ func (t *Interface) Empty() bool { return t.typeSet().IsAll() } func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() } // IsConstraint reports whether interface t is not just a method set. -func (t *Interface) IsConstraint() bool { return !t.typeSet().IsMethodSet() } +func (t *Interface) IsConstraint() bool { return t.typeSet().IsConstraint() } // Complete computes the interface's type set. It must be called by users of // NewInterfaceType and NewInterface after the interface's embedded types are diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index fd9df4c010..293b6d0d44 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -28,10 +28,8 @@ func (s *_TypeSet) IsEmpty() bool { return s.terms.isEmpty() } // IsAll reports whether type set s is the set of all types (corresponding to the empty interface). func (s *_TypeSet) IsAll() bool { return !s.comparable && len(s.methods) == 0 && s.terms.isAll() } -// TODO(gri) IsMethodSet is not a great name for this predicate. Find a better one. - -// IsMethodSet reports whether the type set s is described by a single set of methods. -func (s *_TypeSet) IsMethodSet() bool { return !s.comparable && s.terms.isAll() } +// IsConstraint reports whether type set s is not just a set of methods. +func (s *_TypeSet) IsConstraint() bool { return s.comparable || !s.terms.isAll() } // IsComparable reports whether each type in the set is comparable. func (s *_TypeSet) IsComparable() bool { diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 5a67982030..a126241afa 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -149,7 +149,7 @@ func (check *Checker) ordinaryType(pos positioner, typ Type) { check.later(func() { if t := asInterface(typ); t != nil { tset := computeInterfaceTypeSet(check, pos.Pos(), t) // TODO(gri) is this the correct position? - if !tset.IsMethodSet() { + if tset.IsConstraint() { if tset.comparable { check.softErrorf(pos, _Todo, "interface is (or embeds) comparable") } else { -- GitLab From 78d0f8c870f9bc6e2f6dde22d3191e33be8d0c8f Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 31 Aug 2021 14:57:53 -0400 Subject: [PATCH 0928/2500] go/types: fix type set printing and add a test This is a port of CL 344873 to go/types. Change-Id: Iad41d6de166214178adf2123ac05023895f5208b Reviewed-on: https://go-review.googlesource.com/c/go/+/346435 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/types/typeset.go | 12 +++---- src/go/types/typeset_test.go | 68 +++++++++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 8 deletions(-) diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index 293b6d0d44..648d3c7bf3 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -75,26 +75,24 @@ func (s *_TypeSet) String() string { var buf bytes.Buffer buf.WriteByte('{') if s.comparable { - buf.WriteString(" comparable") + buf.WriteString("comparable") if hasMethods || hasTerms { - buf.WriteByte(';') + buf.WriteString("; ") } } for i, m := range s.methods { if i > 0 { - buf.WriteByte(';') + buf.WriteString("; ") } - buf.WriteByte(' ') buf.WriteString(m.String()) } if hasMethods && hasTerms { - buf.WriteByte(';') + buf.WriteString("; ") } if hasTerms { buf.WriteString(s.terms.String()) } - buf.WriteString(" }") // there was at least one method or term - + buf.WriteString("}") return buf.String() } diff --git a/src/go/types/typeset_test.go b/src/go/types/typeset_test.go index 4fd1aa247d..1c0eeceb8c 100644 --- a/src/go/types/typeset_test.go +++ b/src/go/types/typeset_test.go @@ -4,7 +4,12 @@ package types -import "testing" +import ( + "go/ast" + "go/parser" + "go/token" + "testing" +) func TestInvalidTypeSet(t *testing.T) { if !invalidTypeSet.IsEmpty() { @@ -12,4 +17,65 @@ func TestInvalidTypeSet(t *testing.T) { } } +func TestTypeSetString(t *testing.T) { + for body, want := range map[string]string{ + "{}": "𝓤", + "{int}": "{int}", + "{~int}": "{~int}", + "{int|string}": "{int ∪ string}", + "{int; string}": "∅", + + "{comparable}": "{comparable}", + "{comparable; int}": "{comparable; int}", + "{~int; comparable}": "{comparable; ~int}", + "{int|string; comparable}": "{comparable; int ∪ string}", + "{comparable; int; string}": "∅", + + "{m()}": "{func (p.T).m()}", + "{m1(); m2() int }": "{func (p.T).m1(); func (p.T).m2() int}", + "{error}": "{func (error).Error() string}", + "{m(); comparable}": "{comparable; func (p.T).m()}", + "{m1(); comparable; m2() int }": "{comparable; func (p.T).m1(); func (p.T).m2() int}", + "{comparable; error}": "{comparable; func (error).Error() string}", + + "{m(); comparable; int|float32|string}": "{comparable; func (p.T).m(); int ∪ float32 ∪ string}", + "{m1(); int; m2(); comparable }": "{comparable; func (p.T).m1(); func (p.T).m2(); int}", + + "{E}; type E interface{}": "𝓤", + "{E}; type E interface{int;string}": "∅", + "{E}; type E interface{comparable}": "{comparable}", + } { + // parse + src := "package p; type T interface" + body + fset := token.NewFileSet() + file, err := parser.ParseFile(fset, "p.go", src, parser.AllErrors) + if file == nil { + t.Fatalf("%s: %v (invalid test case)", body, err) + } + + // type check + var conf Config + pkg, err := conf.Check(file.Name.Name, fset, []*ast.File{file}, nil) + if err != nil { + t.Fatalf("%s: %v (invalid test case)", body, err) + } + + // lookup T + obj := pkg.scope.Lookup("T") + if obj == nil { + t.Fatalf("%s: T not found (invalid test case)", body) + } + T, ok := under(obj.Type()).(*Interface) + if !ok { + t.Fatalf("%s: %v is not an interface (invalid test case)", body, obj) + } + + // verify test case + got := T.typeSet().String() + if got != want { + t.Errorf("%s: got %s; want %s", body, got, want) + } + } +} + // TODO(gri) add more tests -- GitLab From 7637345b6ea00faf6c453a5f8128d8b548ee0a2c Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 31 Aug 2021 16:24:00 -0400 Subject: [PATCH 0929/2500] go/internal/typeparams: remove typeparams.{Get,Set} (cleanup) These helper functions are no longer necessary, now that type parameters are enabled; we can access type parameters directly. When considering the existence or non-existence of type parameters, we can either check whether node.TParams != nil, or whether node.TParams.NumFields() > 0. The heuristic I'm using for deciding between these checks is as follows: - For data access, just check node.TParams != nil. - For producing errors if type parameters exist, check NumFields() > 0. Change-Id: I6597536898e975564e9e8bf6a3a91bc798e0f110 Reviewed-on: https://go-review.googlesource.com/c/go/+/346549 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/internal/typeparams/typeparams.go | 23 ----------------------- src/go/parser/parser.go | 12 ++++++++---- src/go/parser/resolver.go | 12 ++++-------- src/go/printer/nodes.go | 9 ++++----- src/go/types/decl.go | 7 +++---- src/go/types/interface.go | 5 ++--- src/go/types/signature.go | 6 +++--- 7 files changed, 24 insertions(+), 50 deletions(-) diff --git a/src/go/internal/typeparams/typeparams.go b/src/go/internal/typeparams/typeparams.go index 3191654d4f..9bf4f7bf97 100644 --- a/src/go/internal/typeparams/typeparams.go +++ b/src/go/internal/typeparams/typeparams.go @@ -5,7 +5,6 @@ package typeparams import ( - "fmt" "go/ast" "go/token" ) @@ -54,25 +53,3 @@ func UnpackIndexExpr(n ast.Node) *IndexExpr { } return nil } - -func Get(n ast.Node) *ast.FieldList { - switch n := n.(type) { - case *ast.TypeSpec: - return n.TParams - case *ast.FuncType: - return n.TParams - default: - panic(fmt.Sprintf("node type %T has no type parameters", n)) - } -} - -func Set(n ast.Node, params *ast.FieldList) { - switch n := n.(type) { - case *ast.TypeSpec: - n.TParams = params - case *ast.FuncType: - n.TParams = params - default: - panic(fmt.Sprintf("node type %T has no type parameters", n)) - } -} diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go index bdc2ad308c..5a7becf6da 100644 --- a/src/go/parser/parser.go +++ b/src/go/parser/parser.go @@ -972,8 +972,12 @@ func (p *parser) parseMethodSpec() *ast.Field { _, params := p.parseParameters(false) results := p.parseResult() idents = []*ast.Ident{ident} - typ = &ast.FuncType{Func: token.NoPos, Params: params, Results: results} - typeparams.Set(typ, tparams) + typ = &ast.FuncType{ + Func: token.NoPos, + TParams: tparams, + Params: params, + Results: results, + } } else { // embedded instantiated type // TODO(rfindley) should resolve all identifiers in x. @@ -2505,7 +2509,7 @@ func (p *parser) parseValueSpec(doc *ast.CommentGroup, _ token.Pos, keyword toke func (p *parser) parseGenericType(spec *ast.TypeSpec, openPos token.Pos, name0 *ast.Ident, closeTok token.Token) { list := p.parseParameterList(name0, closeTok, p.parseParamDecl, true) closePos := p.expect(closeTok) - typeparams.Set(spec, &ast.FieldList{Opening: openPos, List: list, Closing: closePos}) + spec.TParams = &ast.FieldList{Opening: openPos, List: list, Closing: closePos} // Type alias cannot have type parameters. Accept them for robustness but complain. if p.tok == token.ASSIGN { p.error(p.pos, "generic type cannot be alias") @@ -2636,12 +2640,12 @@ func (p *parser) parseFuncDecl() *ast.FuncDecl { Name: ident, Type: &ast.FuncType{ Func: pos, + TParams: tparams, Params: params, Results: results, }, Body: body, } - typeparams.Set(decl.Type, tparams) return decl } diff --git a/src/go/parser/resolver.go b/src/go/parser/resolver.go index cf92c7e4f5..cfdb5e1193 100644 --- a/src/go/parser/resolver.go +++ b/src/go/parser/resolver.go @@ -7,7 +7,6 @@ package parser import ( "fmt" "go/ast" - "go/internal/typeparams" "go/token" ) @@ -455,10 +454,10 @@ func (r *resolver) Visit(node ast.Node) ast.Visitor { // at the identifier in the TypeSpec and ends at the end of the innermost // containing block. r.declare(spec, nil, r.topScope, ast.Typ, spec.Name) - if tparams := typeparams.Get(spec); tparams != nil { + if spec.TParams != nil { r.openScope(spec.Pos()) defer r.closeScope() - r.walkTParams(tparams) + r.walkTParams(spec.TParams) } ast.Walk(r, spec.Type) } @@ -474,8 +473,8 @@ func (r *resolver) Visit(node ast.Node) ast.Visitor { // Type parameters are walked normally: they can reference each other, and // can be referenced by normal parameters. - if tparams := typeparams.Get(n.Type); tparams != nil { - r.walkTParams(tparams) + if n.Type.TParams != nil { + r.walkTParams(n.Type.TParams) // TODO(rFindley): need to address receiver type parameters. } @@ -539,9 +538,6 @@ func (r *resolver) walkFieldList(list *ast.FieldList, kind ast.ObjKind) { // that they may be resolved in the constraint expressions held in the field // Type. func (r *resolver) walkTParams(list *ast.FieldList) { - if list == nil { - return - } r.declareList(list, ast.Typ) r.resolveList(list) } diff --git a/src/go/printer/nodes.go b/src/go/printer/nodes.go index 239fcbde1c..58887153f2 100644 --- a/src/go/printer/nodes.go +++ b/src/go/printer/nodes.go @@ -11,7 +11,6 @@ package printer import ( "bytes" "go/ast" - "go/internal/typeparams" "go/token" "math" "strconv" @@ -383,8 +382,8 @@ func (p *printer) parameters(fields *ast.FieldList, isTypeParam bool) { } func (p *printer) signature(sig *ast.FuncType) { - if tparams := typeparams.Get(sig); tparams != nil { - p.parameters(tparams, true) + if sig.TParams != nil { + p.parameters(sig.TParams, true) } if sig.Params != nil { p.parameters(sig.Params, false) @@ -1633,8 +1632,8 @@ func (p *printer) spec(spec ast.Spec, n int, doIndent bool) { case *ast.TypeSpec: p.setComment(s.Doc) p.expr(s.Name) - if tparams := typeparams.Get(s); tparams != nil { - p.parameters(tparams, true) + if s.TParams != nil { + p.parameters(s.TParams, true) } if n == 1 { p.print(blank) diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 8222cb3fc3..758ebf5d7f 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -8,7 +8,6 @@ import ( "fmt" "go/ast" "go/constant" - "go/internal/typeparams" "go/token" ) @@ -590,7 +589,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { }) alias := tdecl.Assign.IsValid() - if alias && typeparams.Get(tdecl) != nil { + if alias && tdecl.TParams.NumFields() != 0 { // The parser will ensure this but we may still get an invalid AST. // Complain and continue as regular type definition. check.error(atPos(tdecl.Assign), 0, "generic type cannot be alias") @@ -613,10 +612,10 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { named := check.newNamed(obj, nil, nil, nil, nil) def.setUnderlying(named) - if tparams := typeparams.Get(tdecl); tparams != nil { + if tdecl.TParams != nil { check.openScope(tdecl, "type parameters") defer check.closeScope() - named.tparams = check.collectTypeParams(tparams) + named.tparams = check.collectTypeParams(tdecl.TParams) } // determine underlying type of named diff --git a/src/go/types/interface.go b/src/go/types/interface.go index e9970ba101..ebd246da98 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -6,7 +6,6 @@ package types import ( "go/ast" - "go/internal/typeparams" "go/token" ) @@ -195,8 +194,8 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d // a receiver specification.) if sig.tparams != nil { var at positioner = f.Type - if tparams := typeparams.Get(f.Type); tparams != nil { - at = tparams + if ftyp, _ := f.Type.(*ast.FuncType); ftyp != nil && ftyp.TParams != nil { + at = ftyp.TParams } check.errorf(at, _Todo, "methods cannot have type parameters") } diff --git a/src/go/types/signature.go b/src/go/types/signature.go index d6c12cf3d9..d1d50b38c4 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -156,13 +156,13 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast } } - if tparams := typeparams.Get(ftyp); tparams != nil { - sig.tparams = check.collectTypeParams(tparams) + if ftyp.TParams != nil { + sig.tparams = check.collectTypeParams(ftyp.TParams) // Always type-check method type parameters but complain that they are not allowed. // (A separate check is needed when type-checking interface method signatures because // they don't have a receiver specification.) if recvPar != nil { - check.errorf(tparams, _Todo, "methods cannot have type parameters") + check.errorf(ftyp.TParams, _Todo, "methods cannot have type parameters") } } -- GitLab From bb0b511738713c7a8cc4c194e037a7ea852751ca Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Wed, 25 Aug 2021 13:03:30 -0700 Subject: [PATCH 0930/2500] cmd/compile: use right line number for conversion expression Use the position of the actual conversion operation instead of base.Pos. Fixes #47880 Change-Id: I56adc134e09cb7fd625adc0a847c1a6b3e254b1a Reviewed-on: https://go-review.googlesource.com/c/go/+/345095 Trust: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: David Chase --- src/cmd/compile/internal/walk/convert.go | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/internal/walk/convert.go b/src/cmd/compile/internal/walk/convert.go index 80a30d9455..d701d545de 100644 --- a/src/cmd/compile/internal/walk/convert.go +++ b/src/cmd/compile/internal/walk/convert.go @@ -14,6 +14,7 @@ import ( "cmd/compile/internal/ssagen" "cmd/compile/internal/typecheck" "cmd/compile/internal/types" + "cmd/internal/src" "cmd/internal/sys" ) @@ -58,7 +59,7 @@ func walkConvInterface(n *ir.ConvExpr, init *ir.Nodes) ir.Node { } else { typeWord = reflectdata.ITabAddr(fromType, toType) } - l := ir.NewBinaryExpr(base.Pos, ir.OEFACE, typeWord, dataWord(n.X, init, n.Esc() != ir.EscNone)) + l := ir.NewBinaryExpr(base.Pos, ir.OEFACE, typeWord, dataWord(n.Pos(), n.X, init, n.Esc() != ir.EscNone)) l.SetType(toType) l.SetTypecheck(n.Typecheck()) return l @@ -75,7 +76,7 @@ func walkConvInterface(n *ir.ConvExpr, init *ir.Nodes) ir.Node { itab := ir.NewUnaryExpr(base.Pos, ir.OITAB, c) itab.SetType(types.Types[types.TUINTPTR].PtrTo()) itab.SetTypecheck(1) - data := ir.NewUnaryExpr(base.Pos, ir.OIDATA, c) + data := ir.NewUnaryExpr(n.Pos(), ir.OIDATA, c) data.SetType(types.Types[types.TUINT8].PtrTo()) // Type is generic pointer - we're just passing it through. data.SetTypecheck(1) @@ -112,7 +113,7 @@ func walkConvInterface(n *ir.ConvExpr, init *ir.Nodes) ir.Node { // Returns the data word (the second word) used to represent n in an interface. // n must not be of interface type. // esc describes whether the result escapes. -func dataWord(n ir.Node, init *ir.Nodes, escapes bool) ir.Node { +func dataWord(pos src.XPos, n ir.Node, init *ir.Nodes, escapes bool) ir.Node { fromType := n.Type() // If it's a pointer, it is its own representation. @@ -184,16 +185,16 @@ func dataWord(n ir.Node, init *ir.Nodes, escapes bool) ir.Node { fromType.IsPtrShaped() && argType.IsPtrShaped(): // can directly convert (e.g. named type to underlying type, or one pointer to another) // TODO: never happens because pointers are directIface? - arg = ir.NewConvExpr(n.Pos(), ir.OCONVNOP, argType, n) + arg = ir.NewConvExpr(pos, ir.OCONVNOP, argType, n) case fromType.IsInteger() && argType.IsInteger(): // can directly convert (e.g. int32 to uint32) - arg = ir.NewConvExpr(n.Pos(), ir.OCONV, argType, n) + arg = ir.NewConvExpr(pos, ir.OCONV, argType, n) default: // unsafe cast through memory arg = copyExpr(n, fromType, init) var addr ir.Node = typecheck.NodAddr(arg) - addr = ir.NewConvExpr(n.Pos(), ir.OCONVNOP, argType.PtrTo(), addr) - arg = ir.NewStarExpr(n.Pos(), addr) + addr = ir.NewConvExpr(pos, ir.OCONVNOP, argType.PtrTo(), addr) + arg = ir.NewStarExpr(pos, addr) arg.SetType(argType) } args = []ir.Node{arg} @@ -206,7 +207,7 @@ func dataWord(n ir.Node, init *ir.Nodes, escapes bool) ir.Node { // walkConvIData walks an OCONVIDATA node. func walkConvIData(n *ir.ConvExpr, init *ir.Nodes) ir.Node { n.X = walkExpr(n.X, init) - return dataWord(n.X, init, n.Esc() != ir.EscNone) + return dataWord(n.Pos(), n.X, init, n.Esc() != ir.EscNone) } // walkBytesRunesToString walks an OBYTES2STR or ORUNES2STR node. -- GitLab From 1f83a8c16cf1e9141e081759fb0f6c6f2acb5fdc Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 31 Aug 2021 14:09:41 -0700 Subject: [PATCH 0931/2500] cmd/compile: use the zero value for results of impossible indexing type A [0]int var a A x := a[i] Use the zero value for x instead of the "impossible" value. That lets us at least compile code like this with -B, even though it can't possibly run correctly. Fixes #48092 Change-Id: Idad5cfab49e05f375c069b05addceed68a15299f Reviewed-on: https://go-review.googlesource.com/c/go/+/346589 Trust: Keith Randall Run-TryBot: Keith Randall Reviewed-by: David Chase TryBot-Result: Go Bot --- src/cmd/compile/internal/ssagen/ssa.go | 3 ++- test/fixedbugs/issue48092.go | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 test/fixedbugs/issue48092.go diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 77a350720f..a64901305f 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -3014,7 +3014,8 @@ func (s *state) expr(n ir.Node) *ssa.Value { z := s.constInt(types.Types[types.TINT], 0) s.boundsCheck(z, z, ssa.BoundsIndex, false) // The return value won't be live, return junk. - return s.newValue0(ssa.OpUnknown, n.Type()) + // But not quite junk, in case bounds checks are turned off. See issue 48092. + return s.zeroVal(n.Type()) } len := s.constInt(types.Types[types.TINT], bound) s.boundsCheck(i, len, ssa.BoundsIndex, n.Bounded()) // checks i == 0 diff --git a/test/fixedbugs/issue48092.go b/test/fixedbugs/issue48092.go new file mode 100644 index 0000000000..47b812c8d5 --- /dev/null +++ b/test/fixedbugs/issue48092.go @@ -0,0 +1,17 @@ +// compile -B + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Make sure that we can at least compile this code +// successfully with -B. We can't ever produce the right +// answer at runtime with -B, as the access must panic. + +package p + +type A [0]byte + +func (a *A) Get(i int) byte { + return a[i] +} -- GitLab From d15a75e070f3ba726645dc2857ba091f824ad2d2 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 31 Aug 2021 16:56:07 -0400 Subject: [PATCH 0932/2500] go/types: address some TODOs (cleanup) This is a port of CL 345176 to go/types, though not all TODOs were present in go/types. A TODO that still needs to be resolved was added back to types2. Change-Id: Icf79483c92d0bc1248de772c7044620f0f0a5c58 Reviewed-on: https://go-review.googlesource.com/c/go/+/346550 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/cmd/compile/internal/types2/unify.go | 3 ++ src/go/types/check_test.go | 3 -- src/go/types/expr.go | 4 +- src/go/types/instantiate.go | 43 ++++++++-------------- src/go/types/named.go | 2 - src/go/types/self_test.go | 7 +--- src/go/types/signature.go | 7 +--- src/go/types/stmt.go | 5 --- src/go/types/testdata/check/tinference.go2 | 4 +- src/go/types/tuple.go | 2 - src/go/types/type.go | 1 - 11 files changed, 23 insertions(+), 58 deletions(-) diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index 9eb1f63090..a1e5b3679b 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -434,6 +434,9 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { xargs := x.targs.list() yargs := y.targs.list() + // TODO(gri) This is not always correct: two types may have the same names + // in the same package if one of them is nested in a function. + // Extremely unlikely but we need an always correct solution. if x.obj.pkg == y.obj.pkg && x.obj.name == y.obj.name { assert(len(xargs) == len(yargs)) for i, x := range xargs { diff --git a/src/go/types/check_test.go b/src/go/types/check_test.go index 8c8452c9c6..e9df90c4ea 100644 --- a/src/go/types/check_test.go +++ b/src/go/types/check_test.go @@ -20,9 +20,6 @@ // _ = x /* ERROR "not declared" */ + 1 // } -// TODO(gri) Also collect strict mode errors of the form /* STRICT ... */ -// and test against strict mode. - package types_test import ( diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 61d57cc4fa..2a204cf5f6 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -114,9 +114,7 @@ func (check *Checker) overflow(x *operand, op token.Token, opPos token.Pos) { } // opName returns the name of an operation, or the empty string. -// For now, only operations that might overflow are handled. -// TODO(gri) Expand this to a general mechanism giving names to -// nodes? +// Only operations that might overflow are handled. func opName(e ast.Expr) string { switch e := e.(type) { case *ast.BinaryExpr: diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 5f691d5246..09c2ecf8b4 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -116,8 +116,7 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, posList // instance creates a type or function instance using the given original type // typ and arguments targs. For Named types the resulting instance will be // unexpanded. -func (check *Checker) instance(pos token.Pos, typ Type, targs []Type) (res Type) { - // TODO(gri) What is better here: work with TypeParams, or work with TypeNames? +func (check *Checker) instance(pos token.Pos, typ Type, targs []Type) Type { switch t := typ.(type) { case *Named: h := instantiatedHash(t, targs) @@ -128,7 +127,6 @@ func (check *Checker) instance(pos token.Pos, typ Type, targs []Type) (res Type) return named } } - tname := NewTypeName(pos, t.obj.pkg, t.obj.name, nil) named := check.newNamed(tname, t, nil, nil, nil) // methods and tparams are set when named is loaded named.targs = NewTypeList(targs) @@ -136,7 +134,7 @@ func (check *Checker) instance(pos token.Pos, typ Type, targs []Type) (res Type) if check != nil { check.typMap[h] = named } - res = named + return named case *Signature: tparams := t.TParams() if !check.validateTArgLen(pos, tparams.Len(), len(targs)) { @@ -145,30 +143,21 @@ func (check *Checker) instance(pos token.Pos, typ Type, targs []Type) (res Type) if tparams.Len() == 0 { return typ // nothing to do (minor optimization) } - defer func() { - // If we had an unexpected failure somewhere don't panic below when - // asserting res.(*Signature). Check for *Signature in case Typ[Invalid] - // is returned. - if _, ok := res.(*Signature); !ok { - return - } - // If the signature doesn't use its type parameters, subst - // will not make a copy. In that case, make a copy now (so - // we can set tparams to nil w/o causing side-effects). - if t == res { - copy := *t - res = © - } - // After instantiating a generic signature, it is not generic - // anymore; we need to set tparams to nil. - res.(*Signature).tparams = nil - }() - res = check.subst(pos, typ, makeSubstMap(tparams.list(), targs), nil) - default: - // only types and functions can be generic - panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) + sig := check.subst(pos, typ, makeSubstMap(tparams.list(), targs), nil).(*Signature) + // If the signature doesn't use its type parameters, subst + // will not make a copy. In that case, make a copy now (so + // we can set tparams to nil w/o causing side-effects). + if sig == t { + copy := *sig + sig = © + } + // After instantiating a generic signature, it is not generic + // anymore; we need to set tparams to nil. + sig.tparams = nil + return sig } - return res + // only types and functions can be generic + panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) } // validateTArgLen verifies that the length of targs and tparams matches, diff --git a/src/go/types/named.go b/src/go/types/named.go index 6bc33b9538..6f89922a41 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -9,8 +9,6 @@ import ( "sync" ) -// TODO(rfindley) Clean up Named struct below; specifically the fromRHS field (can we use underlying?). - // A Named represents a named (defined) type. type Named struct { check *Checker diff --git a/src/go/types/self_test.go b/src/go/types/self_test.go index 262dc7b97a..55436d3b62 100644 --- a/src/go/types/self_test.go +++ b/src/go/types/self_test.go @@ -27,12 +27,7 @@ func TestSelf(t *testing.T) { conf := Config{Importer: importer.Default()} _, err = conf.Check("go/types", fset, files, nil) if err != nil { - // Importing go/constant doesn't work in the - // build dashboard environment. Don't report an error - // for now so that the build remains green. - // TODO(gri) fix this - t.Log(err) // replace w/ t.Fatal eventually - return + t.Fatal(err) } } diff --git a/src/go/types/signature.go b/src/go/types/signature.go index d1d50b38c4..2e6ab4d88a 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -145,12 +145,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast // bound is (possibly) parameterized in the context of the // receiver type declaration. Substitute parameters for the // current context. - // TODO(gri) should we assume now that bounds always exist? - // (no bound == empty interface) - if bound != nil { - bound = check.subst(tpar.obj.pos, bound, smap, nil) - tpar.bound = bound - } + tpar.bound = check.subst(tpar.obj.pos, bound, smap, nil) } } } diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index 056b21e3d2..5ba57041bd 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -53,11 +53,6 @@ func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body check.error(atPos(body.Rbrace), _MissingReturn, "missing return") } - // TODO(gri) Should we make it an error to declare generic functions - // where the type parameters are not used? - // 12/19/2018: Probably not - it can make sense to have an API with - // all functions uniformly sharing the same type parameters. - // spec: "Implementation restriction: A compiler may make it illegal to // declare a variable inside a function body if the variable is never used." check.usage(sig.scope) diff --git a/src/go/types/testdata/check/tinference.go2 b/src/go/types/testdata/check/tinference.go2 index 5bd2ba74e7..28516ef639 100644 --- a/src/go/types/testdata/check/tinference.go2 +++ b/src/go/types/testdata/check/tinference.go2 @@ -63,9 +63,7 @@ func _() { var _ string = x } -// TODO(gri) Need to flag invalid recursive constraints. At the -// moment these cause infinite recursions and stack overflow. -// func f7[A interface{type B}, B interface{~A}]() +func f7[A interface{*B}, B interface{~*A}]() {} // More realistic examples diff --git a/src/go/types/tuple.go b/src/go/types/tuple.go index 16d28bc9a6..e85c5aa81b 100644 --- a/src/go/types/tuple.go +++ b/src/go/types/tuple.go @@ -16,8 +16,6 @@ func NewTuple(x ...*Var) *Tuple { if len(x) > 0 { return &Tuple{vars: x} } - // TODO(gri) Don't represent empty tuples with a (*Tuple)(nil) pointer; - // it's too subtle and causes problems. return nil } diff --git a/src/go/types/type.go b/src/go/types/type.go index 3be42a1584..b9634cf6f6 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -34,7 +34,6 @@ func (t *top) String() string { return TypeString(t, nil) } // under must only be called when a type is known // to be fully set up. func under(t Type) Type { - // TODO(gri) is this correct for *Union? if n := asNamed(t); n != nil { return n.under() } -- GitLab From 580987cd5884c21dc2411244e6c9f6fbf6f963a1 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 31 Aug 2021 17:00:59 -0400 Subject: [PATCH 0933/2500] go/types: remove need for the instance struct This is a port of CL 345177 to go/types. Change-Id: I79fcfbf5b28e9a7a2e66c81bc831e164a8da8bbb Reviewed-on: https://go-review.googlesource.com/c/go/+/346551 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/instantiate.go | 2 +- src/go/types/named.go | 18 +++++------------- src/go/types/typestring.go | 2 +- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 09c2ecf8b4..6f0b3571d1 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -130,7 +130,7 @@ func (check *Checker) instance(pos token.Pos, typ Type, targs []Type) Type { tname := NewTypeName(pos, t.obj.pkg, t.obj.name, nil) named := check.newNamed(tname, t, nil, nil, nil) // methods and tparams are set when named is loaded named.targs = NewTypeList(targs) - named.instance = &instance{pos} + named.instPos = &pos if check != nil { check.typMap[h] = named } diff --git a/src/go/types/named.go b/src/go/types/named.go index 6f89922a41..4ee76eb835 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -17,7 +17,7 @@ type Named struct { orig *Named // original, uninstantiated type fromRHS Type // type (on RHS of declaration) this *Named type is derived of (for cycle reporting) underlying Type // possibly a *Named during setup; never a *Named once set up completely - instance *instance // syntactic information for lazy instantiation + instPos *token.Pos // position information for lazy instantiation, or nil tparams *TParamList // type parameters, or nil targs *TypeList // type arguments (after instantiation), or nil methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily @@ -240,24 +240,16 @@ func (n *Named) setUnderlying(typ Type) { } } -// instance holds position information for use in lazy instantiation. -// -// TODO(rfindley): instance is probably unnecessary now. See if it can be -// eliminated. -type instance struct { - pos token.Pos // position of type instantiation; for error reporting only -} - // expand ensures that the underlying type of n is instantiated. // The underlying type will be Typ[Invalid] if there was an error. func (n *Named) expand(typMap map[string]*Named) *Named { - if n.instance != nil { + if n.instPos != nil { // n must be loaded before instantiation, in order to have accurate // tparams. This is done implicitly by the call to n.TParams, but making it // explicit is harmless: load is idempotent. n.load() var u Type - if n.check.validateTArgLen(n.instance.pos, n.tparams.Len(), n.targs.Len()) { + if n.check.validateTArgLen(*n.instPos, n.tparams.Len(), n.targs.Len()) { if typMap == nil { if n.check != nil { typMap = n.check.typMap @@ -270,13 +262,13 @@ func (n *Named) expand(typMap map[string]*Named) *Named { typMap = map[string]*Named{h: n} } } - u = n.check.subst(n.instance.pos, n.orig.underlying, makeSubstMap(n.TParams().list(), n.targs.list()), typMap) + u = n.check.subst(*n.instPos, n.orig.underlying, makeSubstMap(n.TParams().list(), n.targs.list()), typMap) } else { u = Typ[Invalid] } n.underlying = u n.fromRHS = u - n.instance = nil + n.instPos = nil } return n } diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index cdc7ea9f51..03f735f2fd 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -197,7 +197,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { } case *Named: - if t.instance != nil { + if t.instPos != nil { buf.WriteByte(instanceMarker) } writeTypeName(buf, t.obj, qf) -- GitLab From 5e9ba0b1bd62f1c4196173806aa69b567006056c Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 31 Aug 2021 17:04:10 -0400 Subject: [PATCH 0934/2500] go/types: implement TypeList.String (debugging support) This is a port of CL 345471 to go/types. Change-Id: Icad5fb8b3b4375182f420a51c80607b88696561e Reviewed-on: https://go-review.googlesource.com/c/go/+/346552 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/types/instantiate.go | 2 +- src/go/types/subst.go | 6 ------ src/go/types/typelists.go | 13 +++++++++++++ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 6f0b3571d1..fe4904f63a 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -69,7 +69,7 @@ func Instantiate(env *Environment, typ Type, targs []Type, validate bool) (Type, func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, posList []token.Pos) (res Type) { assert(check != nil) if trace { - check.trace(pos, "-- instantiating %s with %s", typ, typeListString(targs)) + check.trace(pos, "-- instantiating %s with %s", typ, NewTypeList(targs)) check.indent++ defer func() { check.indent-- diff --git a/src/go/types/subst.go b/src/go/types/subst.go index d3b1cad13a..3eea44a72a 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -284,12 +284,6 @@ func instantiatedHash(typ *Named, targs []Type) string { return string(res[:i]) } -func typeListString(list []Type) string { - var buf bytes.Buffer - writeTypeList(&buf, list, nil, nil) - return buf.String() -} - // typOrNil is like typ but if the argument is nil it is replaced with Typ[Invalid]. // A nil type may appear in pathological cases such as type T[P any] []func(_ T([]_)) // where an array/slice element is accessed before it is set up. diff --git a/src/go/types/typelists.go b/src/go/types/typelists.go index ef8ea1f32b..fc30139b76 100644 --- a/src/go/types/typelists.go +++ b/src/go/types/typelists.go @@ -4,6 +4,8 @@ package types +import "bytes" + // TParamList holds a list of type parameters. type TParamList struct{ tparams []*TypeParam } @@ -52,6 +54,17 @@ func (l *TypeList) list() []Type { return l.types } +func (l *TypeList) String() string { + if l == nil || len(l.types) == 0 { + return "[]" + } + var buf bytes.Buffer + buf.WriteByte('[') + writeTypeList(&buf, l.types, nil, nil) + buf.WriteByte(']') + return buf.String() +} + // ---------------------------------------------------------------------------- // Implementation -- GitLab From b2f09cd717169cbad41bfc614f0b70b13edbc74a Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 31 Aug 2021 17:09:47 -0400 Subject: [PATCH 0935/2500] go/types: do not declare new methods on instantiated types This is a port of CL 345472 to go/types. Change-Id: I0e2a88909ecebe9dea3325244153f5c74e4c3ce7 Reviewed-on: https://go-review.googlesource.com/c/go/+/346553 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/types/signature.go | 8 ++++++- .../types/testdata/fixedbugs/issue47968.go2 | 21 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/go/types/testdata/fixedbugs/issue47968.go2 diff --git a/src/go/types/signature.go b/src/go/types/signature.go index 2e6ab4d88a..54e2e3e1ea 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -127,7 +127,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast // Also: Don't report an error via genericType since it will be reported // again when we type-check the signature. // TODO(gri) maybe the receiver should be marked as invalid instead? - if recv := asNamed(check.genericType(rname, false)); recv != nil { + if recv, _ := check.genericType(rname, false).(*Named); recv != nil { recvTParams = recv.TParams().list() } } @@ -201,6 +201,12 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast switch T := rtyp.(type) { case *Named: T.expand(nil) + // The receiver type may be an instantiated type referred to + // by an alias (which cannot have receiver parameters for now). + if T.TArgs() != nil && sig.RParams() == nil { + check.errorf(atPos(recv.pos), _Todo, "cannot define methods on instantiated type %s", recv.typ) + break + } // spec: "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." diff --git a/src/go/types/testdata/fixedbugs/issue47968.go2 b/src/go/types/testdata/fixedbugs/issue47968.go2 new file mode 100644 index 0000000000..bbbe6805f2 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue47968.go2 @@ -0,0 +1,21 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T[P any] struct{} + +func (T[P]) m1() + +type A1 = T + +func (A1[P]) m2() {} + +type A2 = T[int] + +func (A2 /* ERROR cannot define methods on instantiated type T\[int\] */) m3() {} +func (_ /* ERROR cannot define methods on instantiated type T\[int\] */ A2) m4() {} + +func (T[int]) m5() {} // int is the type parameter name, not an instantiation +func (T[* /* ERROR must be an identifier */ int]) m6() {} // syntax error -- GitLab From 2d98a4b4bcd11f58356b183865f73e984294dbd3 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 31 Aug 2021 17:49:53 -0400 Subject: [PATCH 0936/2500] go/types: use a typeWriter to write types (cleanup) This is a port of CL 345890 to go/types. Change-Id: I98162deaf044b2194b05dc51e6948e227216fc4d Reviewed-on: https://go-review.googlesource.com/c/go/+/346554 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/types/object.go | 2 +- src/go/types/subst.go | 7 +- src/go/types/typelists.go | 4 +- src/go/types/typestring.go | 211 +++++++++++++++++++------------------ src/go/types/unify.go | 13 +-- 5 files changed, 121 insertions(+), 116 deletions(-) diff --git a/src/go/types/object.go b/src/go/types/object.go index eb5df56d14..64773e8896 100644 --- a/src/go/types/object.go +++ b/src/go/types/object.go @@ -430,7 +430,7 @@ func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) { return } if named, _ := typ.(*Named); named != nil && named.TParams().Len() > 0 { - writeTParamList(buf, named.TParams().list(), qf, nil) + newTypeWriter(buf, qf).tParamList(named.TParams().list()) } if tname.IsAlias() { buf.WriteString(" =") diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 3eea44a72a..4be489e266 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -262,10 +262,9 @@ func instantiatedHash(typ *Named, targs []Type) string { assert(instanceHashing == 0) instanceHashing++ var buf bytes.Buffer - writeTypeName(&buf, typ.obj, nil) - buf.WriteByte('[') - writeTypeList(&buf, targs, nil, nil) - buf.WriteByte(']') + w := newTypeWriter(&buf, nil) + w.typeName(typ.obj) + w.typeList(targs) instanceHashing-- // With respect to the represented type, whether a diff --git a/src/go/types/typelists.go b/src/go/types/typelists.go index fc30139b76..a21683fe87 100644 --- a/src/go/types/typelists.go +++ b/src/go/types/typelists.go @@ -59,9 +59,7 @@ func (l *TypeList) String() string { return "[]" } var buf bytes.Buffer - buf.WriteByte('[') - writeTypeList(&buf, l.types, nil, nil) - buf.WriteByte(']') + newTypeWriter(&buf, nil).typeList(l.types) return buf.String() } diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 03f735f2fd..45ed632335 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -53,79 +53,87 @@ func TypeString(typ Type, qf Qualifier) string { // The Qualifier controls the printing of // package-level objects, and may be nil. func WriteType(buf *bytes.Buffer, typ Type, qf Qualifier) { - writeType(buf, typ, qf, make([]Type, 0, 8)) + newTypeWriter(buf, qf).typ(typ) } -// instanceMarker is the prefix for an instantiated type -// in "non-evaluated" instance form. +// instanceMarker is the prefix for an instantiated type in unexpanded form. const instanceMarker = '#' -func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { - // Theoretically, this is a quadratic lookup algorithm, but in - // practice deeply nested composite types with unnamed component - // types are uncommon. This code is likely more efficient than - // using a map. - for _, t := range visited { - if t == typ { - fmt.Fprintf(buf, "○%T", goTypeName(typ)) // cycle to typ - return - } +type typeWriter struct { + buf *bytes.Buffer + seen map[Type]bool + qf Qualifier +} + +func newTypeWriter(buf *bytes.Buffer, qf Qualifier) *typeWriter { + return &typeWriter{buf, make(map[Type]bool), qf} +} + +func (w *typeWriter) byte(b byte) { w.buf.WriteByte(b) } +func (w *typeWriter) string(s string) { w.buf.WriteString(s) } +func (w *typeWriter) writef(format string, args ...interface{}) { fmt.Fprintf(w.buf, format, args...) } + +func (w *typeWriter) typ(typ Type) { + if w.seen[typ] { + w.writef("○%T", goTypeName(typ)) // cycle to typ + return } - visited = append(visited, typ) + w.seen[typ] = true + defer delete(w.seen, typ) switch t := typ.(type) { case nil: - buf.WriteString("") + w.string("") case *Basic: // exported basic types go into package unsafe // (currently this is just unsafe.Pointer) if token.IsExported(t.name) { if obj, _ := Unsafe.scope.Lookup(t.name).(*TypeName); obj != nil { - writeTypeName(buf, obj, qf) + w.typeName(obj) break } } - buf.WriteString(t.name) + w.string(t.name) case *Array: - fmt.Fprintf(buf, "[%d]", t.len) - writeType(buf, t.elem, qf, visited) + w.writef("[%d]", t.len) + w.typ(t.elem) case *Slice: - buf.WriteString("[]") - writeType(buf, t.elem, qf, visited) + w.string("[]") + w.typ(t.elem) case *Struct: - buf.WriteString("struct{") + w.string("struct{") for i, f := range t.fields { if i > 0 { - buf.WriteString("; ") + w.string("; ") } // This doesn't do the right thing for embedded type // aliases where we should print the alias name, not // the aliased type (see issue #44410). if !f.embedded { - buf.WriteString(f.name) - buf.WriteByte(' ') + w.string(f.name) + w.byte(' ') } - writeType(buf, f.typ, qf, visited) + w.typ(f.typ) if tag := t.Tag(i); tag != "" { - fmt.Fprintf(buf, " %q", tag) + w.writef(" %q", tag) } } - buf.WriteByte('}') + w.byte('}') case *Pointer: - buf.WriteByte('*') - writeType(buf, t.base, qf, visited) + w.byte('*') + w.typ(t.base) case *Tuple: - writeTuple(buf, t, false, qf, visited) + w.tuple(t, false) case *Signature: - buf.WriteString("func") - writeSignature(buf, t, qf, visited) + w.string("func") + w.signature(t) case *Union: // Unions only appear as (syntactic) embedded elements @@ -135,40 +143,39 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { } for i, t := range t.terms { if i > 0 { - buf.WriteByte('|') + w.byte('|') } if t.tilde { - buf.WriteByte('~') + w.byte('~') } - writeType(buf, t.typ, qf, visited) + w.typ(t.typ) } case *Interface: - buf.WriteString("interface{") + w.string("interface{") first := true - // print explicit interface methods and embedded types for _, m := range t.methods { if !first { - buf.WriteString("; ") + w.string("; ") } first = false - buf.WriteString(m.name) - writeSignature(buf, m.typ.(*Signature), qf, visited) + w.string(m.name) + w.signature(m.typ.(*Signature)) } for _, typ := range t.embeddeds { if !first { - buf.WriteString("; ") + w.string("; ") } first = false - writeType(buf, typ, qf, visited) + w.typ(typ) } - buf.WriteByte('}') + w.byte('}') case *Map: - buf.WriteString("map[") - writeType(buf, t.key, qf, visited) - buf.WriteByte(']') - writeType(buf, t.elem, qf, visited) + w.string("map[") + w.typ(t.key) + w.byte(']') + w.typ(t.elem) case *Chan: var s string @@ -187,66 +194,65 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { default: unreachable() } - buf.WriteString(s) + w.string(s) if parens { - buf.WriteByte('(') + w.byte('(') } - writeType(buf, t.elem, qf, visited) + w.typ(t.elem) if parens { - buf.WriteByte(')') + w.byte(')') } case *Named: if t.instPos != nil { - buf.WriteByte(instanceMarker) + w.byte(instanceMarker) } - writeTypeName(buf, t.obj, qf) + w.typeName(t.obj) if t.targs != nil { // instantiated type - buf.WriteByte('[') - writeTypeList(buf, t.targs.list(), qf, visited) - buf.WriteByte(']') + w.typeList(t.targs.list()) } else if t.TParams().Len() != 0 { // parameterized type - writeTParamList(buf, t.TParams().list(), qf, visited) + w.tParamList(t.TParams().list()) } case *TypeParam: s := "?" if t.obj != nil { // Optionally write out package for typeparams (like Named). - // TODO(rfindley): this is required for import/export, so + // TODO(danscales): this is required for import/export, so // we maybe need a separate function that won't be changed // for debugging purposes. if t.obj.pkg != nil { - writePackage(buf, t.obj.pkg, qf) + writePackage(w.buf, t.obj.pkg, w.qf) } s = t.obj.name } - buf.WriteString(s + subscript(t.id)) + w.string(s + subscript(t.id)) case *top: - buf.WriteString("⊤") + w.string("⊤") default: // For externally defined implementations of Type. // Note: In this case cycles won't be caught. - buf.WriteString(t.String()) + w.string(t.String()) } } -func writeTypeList(buf *bytes.Buffer, list []Type, qf Qualifier, visited []Type) { +func (w *typeWriter) typeList(list []Type) { + w.byte('[') for i, typ := range list { if i > 0 { - buf.WriteString(", ") + w.string(", ") } - writeType(buf, typ, qf, visited) + w.typ(typ) } + w.byte(']') } -func writeTParamList(buf *bytes.Buffer, list []*TypeParam, qf Qualifier, visited []Type) { - // TODO(rFindley) compare this with the corresponding implementation in types2 - buf.WriteString("[") +func (w *typeWriter) tParamList(list []*TypeParam) { + w.byte('[') var prev Type for i, tpar := range list { // Determine the type parameter and its constraint. @@ -260,35 +266,36 @@ func writeTParamList(buf *bytes.Buffer, list []*TypeParam, qf Qualifier, visited if i > 0 { if bound != prev { // bound changed - write previous one before advancing - buf.WriteByte(' ') - writeType(buf, prev, qf, visited) + w.byte(' ') + w.typ(prev) } - buf.WriteString(", ") + w.string(", ") } prev = bound if tpar != nil { - writeType(buf, tpar, qf, visited) + w.typ(tpar) } else { - buf.WriteString(tpar.obj.name) + w.string(tpar.obj.name) } } if prev != nil { - buf.WriteByte(' ') - writeType(buf, prev, qf, visited) + w.byte(' ') + w.typ(prev) } - buf.WriteByte(']') + w.byte(']') } -func writeTypeName(buf *bytes.Buffer, obj *TypeName, qf Qualifier) { +func (w *typeWriter) typeName(obj *TypeName) { if obj == nil { - buf.WriteString("") + assert(instanceHashing == 0) // we need an object for instance hashing + w.string("") return } if obj.pkg != nil { - writePackage(buf, obj.pkg, qf) + writePackage(w.buf, obj.pkg, w.qf) } - buf.WriteString(obj.name) + w.string(obj.name) if instanceHashing != 0 { // For local defined types, use the (original!) TypeName's scope @@ -300,7 +307,7 @@ func writeTypeName(buf *bytes.Buffer, obj *TypeName, qf Qualifier) { for typ.orig != typ { typ = typ.orig } - writeScopeNumbers(buf, typ.obj.parent) + w.writeScopeNumbers(typ.obj.parent) } } @@ -308,28 +315,28 @@ func writeTypeName(buf *bytes.Buffer, obj *TypeName, qf Qualifier) { // in the form ".i.j.k" where i, j, k, etc. stand for scope numbers. // If a scope is nil or has no parent (such as a package scope), nothing // is written. -func writeScopeNumbers(buf *bytes.Buffer, s *Scope) { +func (w *typeWriter) writeScopeNumbers(s *Scope) { if s != nil && s.number > 0 { - writeScopeNumbers(buf, s.parent) - fmt.Fprintf(buf, ".%d", s.number) + w.writeScopeNumbers(s.parent) + w.writef(".%d", s.number) } } -func writeTuple(buf *bytes.Buffer, tup *Tuple, variadic bool, qf Qualifier, visited []Type) { - buf.WriteByte('(') +func (w *typeWriter) tuple(tup *Tuple, variadic bool) { + w.byte('(') if tup != nil { for i, v := range tup.vars { if i > 0 { - buf.WriteString(", ") + w.string(", ") } if v.name != "" { - buf.WriteString(v.name) - buf.WriteByte(' ') + w.string(v.name) + w.byte(' ') } typ := v.typ if variadic && i == len(tup.vars)-1 { if s, ok := typ.(*Slice); ok { - buf.WriteString("...") + w.string("...") typ = s.elem } else { // special case: @@ -337,15 +344,15 @@ func writeTuple(buf *bytes.Buffer, tup *Tuple, variadic bool, qf Qualifier, visi if t := asBasic(typ); t == nil || t.kind != String { panic("expected string type") } - writeType(buf, typ, qf, visited) - buf.WriteString("...") + w.typ(typ) + w.string("...") continue } } - writeType(buf, typ, qf, visited) + w.typ(typ) } } - buf.WriteByte(')') + w.byte(')') } // WriteSignature writes the representation of the signature sig to buf, @@ -353,15 +360,15 @@ func writeTuple(buf *bytes.Buffer, tup *Tuple, variadic bool, qf Qualifier, visi // The Qualifier controls the printing of // package-level objects, and may be nil. func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) { - writeSignature(buf, sig, qf, make([]Type, 0, 8)) + newTypeWriter(buf, qf).signature(sig) } -func writeSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier, visited []Type) { +func (w *typeWriter) signature(sig *Signature) { if sig.TParams().Len() != 0 { - writeTParamList(buf, sig.TParams().list(), qf, visited) + w.tParamList(sig.TParams().list()) } - writeTuple(buf, sig.params, sig.variadic, qf, visited) + w.tuple(sig.params, sig.variadic) n := sig.results.Len() if n == 0 { @@ -369,15 +376,15 @@ func writeSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier, visited []T return } - buf.WriteByte(' ') + w.byte(' ') if n == 1 && sig.results.vars[0].name == "" { // single unnamed result - writeType(buf, sig.results.vars[0].typ, qf, visited) + w.typ(sig.results.vars[0].typ) return } // multiple or named result(s) - writeTuple(buf, sig.results, false, qf, visited) + w.tuple(sig.results, false) } // subscript returns the decimal (utf8) representation of x using subscript digits. diff --git a/src/go/types/unify.go b/src/go/types/unify.go index 1720646db9..ed769aafe8 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -77,16 +77,17 @@ type tparamsList struct { // String returns a string representation for a tparamsList. For debugging. func (d *tparamsList) String() string { var buf bytes.Buffer - buf.WriteByte('[') + w := newTypeWriter(&buf, nil) + w.byte('[') for i, tpar := range d.tparams { if i > 0 { - buf.WriteString(", ") + w.string(", ") } - writeType(&buf, tpar, nil, nil) - buf.WriteString(": ") - writeType(&buf, d.at(i), nil, nil) + w.typ(tpar) + w.string(": ") + w.typ(d.at(i)) } - buf.WriteByte(']') + w.byte(']') return buf.String() } -- GitLab From 3c8c9e1e443a0a49ae42836b82fb1290d42b7857 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 31 Aug 2021 17:59:05 -0400 Subject: [PATCH 0937/2500] go/types: don't print instance markers for type hashes This is a port of CL 345891 to go/types. Change-Id: I5abcb9c9c5110923a743f0c47d9b34b2baabab68 Reviewed-on: https://go-review.googlesource.com/c/go/+/346555 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/types/subst.go | 19 +++++++------------ src/go/types/typestring.go | 6 +++++- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 4be489e266..f1bdbc34bd 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -259,28 +259,23 @@ func (subst *subster) typ(typ Type) Type { var instanceHashing = 0 func instantiatedHash(typ *Named, targs []Type) string { + var buf bytes.Buffer + assert(instanceHashing == 0) instanceHashing++ - var buf bytes.Buffer w := newTypeWriter(&buf, nil) w.typeName(typ.obj) w.typeList(targs) instanceHashing-- - // With respect to the represented type, whether a - // type is fully expanded or stored as instance - // does not matter - they are the same types. - // Remove the instanceMarkers printed for instances. - res := buf.Bytes() - i := 0 - for _, b := range res { - if b != instanceMarker { - res[i] = b - i++ + if debug { + // there should be no instance markers in type hashes + for _, b := range buf.Bytes() { + assert(b != instanceMarker) } } - return string(res[:i]) + return buf.String() } // typOrNil is like typ but if the argument is nil it is replaced with Typ[Invalid]. diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 45ed632335..46e749c84a 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -204,7 +204,11 @@ func (w *typeWriter) typ(typ Type) { } case *Named: - if t.instPos != nil { + // Instance markers indicate unexpanded instantiated + // types. Write them to aid debugging, but don't write + // them when we need an instance hash: whether a type + // is fully expanded or not doesn't matter for identity. + if instanceHashing == 0 && t.instPos != nil { w.byte(instanceMarker) } w.typeName(t.obj) -- GitLab From 0df6df17e12d4cf8c2ed7c68ce8841a18f739f63 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 31 Aug 2021 18:12:15 -0400 Subject: [PATCH 0938/2500] go/types: generalize instanceHash to accept any type, rename to typeHash This is a port of CL 345791 to go/types. Change-Id: I673c22ad8b668f07aae4117555b1c0efb273fb78 Reviewed-on: https://go-review.googlesource.com/c/go/+/346556 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/types/instantiate.go | 2 +- src/go/types/named.go | 2 +- src/go/types/stmt.go | 43 ++++++++++++++++++++++++++++++++++++- src/go/types/subst.go | 28 +++++++++++++++++------- src/go/types/typestring.go | 28 +++++++++++++----------- 5 files changed, 79 insertions(+), 24 deletions(-) diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index fe4904f63a..e89f645c8f 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -119,7 +119,7 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, posList func (check *Checker) instance(pos token.Pos, typ Type, targs []Type) Type { switch t := typ.(type) { case *Named: - h := instantiatedHash(t, targs) + h := typeHash(t, targs) if check != nil { // typ may already have been instantiated with identical type arguments. In // that case, re-use the existing instance. diff --git a/src/go/types/named.go b/src/go/types/named.go index 4ee76eb835..4540956658 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -258,7 +258,7 @@ func (n *Named) expand(typMap map[string]*Named) *Named { // type-checking pass. In that case we won't have a pre-existing // typMap, but don't want to create a duplicate of the current instance // in the process of expansion. - h := instantiatedHash(n.orig, n.targs.list()) + h := typeHash(n.orig, n.targs.list()) typMap = map[string]*Named{h: n} } } diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index 5ba57041bd..e74862afef 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -302,7 +302,7 @@ L: // talk about "case" rather than "type" because of nil case Ts := "nil" if T != nil { - Ts = T.String() + Ts = TypeString(T, check.qualifier) } check.errorf(e, _DuplicateCase, "duplicate case %s in type switch", Ts) check.error(other, _DuplicateCase, "\tprevious case") // secondary error, \t indented @@ -317,6 +317,47 @@ L: return } +// TODO(gri) Once we are certain that typeHash is correct in all situations, use this version of caseTypes instead. +// (Currently it may be possible that different types have identical names and import paths due to ImporterFrom.) +// +// func (check *Checker) caseTypes(x *operand, xtyp *Interface, types []ast.Expr, seen map[string]ast.Expr) (T Type) { +// var dummy operand +// L: +// for _, e := range types { +// // The spec allows the value nil instead of a type. +// var hash string +// if check.isNil(e) { +// check.expr(&dummy, e) // run e through expr so we get the usual Info recordings +// T = nil +// hash = "" // avoid collision with a type named nil +// } else { +// T = check.varType(e) +// if T == Typ[Invalid] { +// continue L +// } +// hash = typeHash(T, nil) +// } +// // look for duplicate types +// if other := seen[hash]; other != nil { +// // talk about "case" rather than "type" because of nil case +// Ts := "nil" +// if T != nil { +// Ts = TypeString(T, check.qualifier) +// } +// var err error_ +// err.errorf(e, "duplicate case %s in type switch", Ts) +// err.errorf(other, "previous case") +// check.report(&err) +// continue L +// } +// seen[hash] = e +// if T != nil { +// check.typeAssertion(e.Pos(), x, xtyp, T) +// } +// } +// return +// } + // stmt typechecks statement s. func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { // statements must end with the same top scope as they started with diff --git a/src/go/types/subst.go b/src/go/types/subst.go index f1bdbc34bd..c811f8a4df 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -217,7 +217,7 @@ func (subst *subster) typ(typ Type) Type { } // before creating a new named type, check if we have this one already - h := instantiatedHash(t, newTArgs) + h := typeHash(t, newTArgs) dump(">>> new type hash: %s", h) if named, found := subst.typMap[h]; found { dump(">>> found %s", named) @@ -256,17 +256,29 @@ func (subst *subster) typ(typ Type) Type { return typ } -var instanceHashing = 0 +var typeHashing = 0 -func instantiatedHash(typ *Named, targs []Type) string { +// typeHash returns a string representation of typ, which can be used as an exact +// type hash: types that are identical produce identical string representations. +// If typ is a *Named type and targs is not empty, typ is printed as if it were +// instantiated with targs. +func typeHash(typ Type, targs []Type) string { + assert(typ != nil) var buf bytes.Buffer - assert(instanceHashing == 0) - instanceHashing++ + assert(typeHashing == 0) + typeHashing++ w := newTypeWriter(&buf, nil) - w.typeName(typ.obj) - w.typeList(targs) - instanceHashing-- + if named, _ := typ.(*Named); named != nil && len(targs) > 0 { + // Don't use WriteType because we need to use the provided targs + // and not any targs that might already be with the *Named type. + w.typeName(named.obj) + w.typeList(targs) + } else { + assert(targs == nil) + w.typ(typ) + } + typeHashing-- if debug { // there should be no instance markers in type hashes diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 46e749c84a..3841227044 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -208,7 +208,7 @@ func (w *typeWriter) typ(typ Type) { // types. Write them to aid debugging, but don't write // them when we need an instance hash: whether a type // is fully expanded or not doesn't matter for identity. - if instanceHashing == 0 && t.instPos != nil { + if typeHashing == 0 && t.instPos != nil { w.byte(instanceMarker) } w.typeName(t.obj) @@ -292,7 +292,7 @@ func (w *typeWriter) tParamList(list []*TypeParam) { func (w *typeWriter) typeName(obj *TypeName) { if obj == nil { - assert(instanceHashing == 0) // we need an object for instance hashing + assert(typeHashing == 0) // we need an object for type hashing w.string("") return } @@ -301,17 +301,18 @@ func (w *typeWriter) typeName(obj *TypeName) { } w.string(obj.name) - if instanceHashing != 0 { + if typeHashing != 0 { // For local defined types, use the (original!) TypeName's scope // numbers to disambiguate. - typ := obj.typ.(*Named) - // TODO(gri) Figure out why typ.orig != typ.orig.orig sometimes - // and whether the loop can iterate more than twice. - // (It seems somehow connected to instance types.) - for typ.orig != typ { - typ = typ.orig + if typ, _ := obj.typ.(*Named); typ != nil { + // TODO(gri) Figure out why typ.orig != typ.orig.orig sometimes + // and whether the loop can iterate more than twice. + // (It seems somehow connected to instance types.) + for typ.orig != typ { + typ = typ.orig + } + w.writeScopeNumbers(typ.obj.parent) } - w.writeScopeNumbers(typ.obj.parent) } } @@ -333,7 +334,8 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) { if i > 0 { w.string(", ") } - if v.name != "" { + // parameter names are ignored for type identity and thus type hashes + if typeHashing == 0 && v.name != "" { w.string(v.name) w.byte(' ') } @@ -381,8 +383,8 @@ func (w *typeWriter) signature(sig *Signature) { } w.byte(' ') - if n == 1 && sig.results.vars[0].name == "" { - // single unnamed result + if n == 1 && (typeHashing != 0 || sig.results.vars[0].name == "") { + // single unnamed result (if typeHashing, name must be ignored) w.typ(sig.results.vars[0].typ) return } -- GitLab From 5cd1b847dc6e2d70e503fb44e27d0ece261ebfff Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 31 Aug 2021 18:15:53 -0400 Subject: [PATCH 0939/2500] go/types: eliminate typeHashing global variable This is a port of CL 345929 to go/types. It is also a step toward making instantiation concurrency-safe. Also fix some whitespace in instantiate.go. Updates #47910 Change-Id: Icdeb227cb83eee15da6db90daab294c8c55db601 Reviewed-on: https://go-review.googlesource.com/c/go/+/346557 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/types/instantiate.go | 5 +++-- src/go/types/subst.go | 13 ++++--------- src/go/types/typestring.go | 19 ++++++++++++------- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index e89f645c8f..ec4c61cf62 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -121,8 +121,8 @@ func (check *Checker) instance(pos token.Pos, typ Type, targs []Type) Type { case *Named: h := typeHash(t, targs) if check != nil { - // typ may already have been instantiated with identical type arguments. In - // that case, re-use the existing instance. + // typ may already have been instantiated with identical type arguments. + // In that case, re-use the existing instance. if named := check.typMap[h]; named != nil { return named } @@ -135,6 +135,7 @@ func (check *Checker) instance(pos token.Pos, typ Type, targs []Type) Type { check.typMap[h] = named } return named + case *Signature: tparams := t.TParams() if !check.validateTArgLen(pos, tparams.Len(), len(targs)) { diff --git a/src/go/types/subst.go b/src/go/types/subst.go index c811f8a4df..fb77617d0c 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -256,8 +256,6 @@ func (subst *subster) typ(typ Type) Type { return typ } -var typeHashing = 0 - // typeHash returns a string representation of typ, which can be used as an exact // type hash: types that are identical produce identical string representations. // If typ is a *Named type and targs is not empty, typ is printed as if it were @@ -266,19 +264,16 @@ func typeHash(typ Type, targs []Type) string { assert(typ != nil) var buf bytes.Buffer - assert(typeHashing == 0) - typeHashing++ - w := newTypeWriter(&buf, nil) + h := newTypeHasher(&buf) if named, _ := typ.(*Named); named != nil && len(targs) > 0 { // Don't use WriteType because we need to use the provided targs // and not any targs that might already be with the *Named type. - w.typeName(named.obj) - w.typeList(targs) + h.typeName(named.obj) + h.typeList(targs) } else { assert(targs == nil) - w.typ(typ) + h.typ(typ) } - typeHashing-- if debug { // there should be no instance markers in type hashes diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 3841227044..3a6bb9aafc 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -63,10 +63,15 @@ type typeWriter struct { buf *bytes.Buffer seen map[Type]bool qf Qualifier + hash bool } func newTypeWriter(buf *bytes.Buffer, qf Qualifier) *typeWriter { - return &typeWriter{buf, make(map[Type]bool), qf} + return &typeWriter{buf, make(map[Type]bool), qf, false} +} + +func newTypeHasher(buf *bytes.Buffer) *typeWriter { + return &typeWriter{buf, make(map[Type]bool), nil, true} } func (w *typeWriter) byte(b byte) { w.buf.WriteByte(b) } @@ -208,7 +213,7 @@ func (w *typeWriter) typ(typ Type) { // types. Write them to aid debugging, but don't write // them when we need an instance hash: whether a type // is fully expanded or not doesn't matter for identity. - if typeHashing == 0 && t.instPos != nil { + if !w.hash && t.instPos != nil { w.byte(instanceMarker) } w.typeName(t.obj) @@ -292,7 +297,7 @@ func (w *typeWriter) tParamList(list []*TypeParam) { func (w *typeWriter) typeName(obj *TypeName) { if obj == nil { - assert(typeHashing == 0) // we need an object for type hashing + assert(!w.hash) // we need an object for type hashing w.string("") return } @@ -301,7 +306,7 @@ func (w *typeWriter) typeName(obj *TypeName) { } w.string(obj.name) - if typeHashing != 0 { + if w.hash { // For local defined types, use the (original!) TypeName's scope // numbers to disambiguate. if typ, _ := obj.typ.(*Named); typ != nil { @@ -335,7 +340,7 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) { w.string(", ") } // parameter names are ignored for type identity and thus type hashes - if typeHashing == 0 && v.name != "" { + if !w.hash && v.name != "" { w.string(v.name) w.byte(' ') } @@ -383,8 +388,8 @@ func (w *typeWriter) signature(sig *Signature) { } w.byte(' ') - if n == 1 && (typeHashing != 0 || sig.results.vars[0].name == "") { - // single unnamed result (if typeHashing, name must be ignored) + if n == 1 && (w.hash || sig.results.vars[0].name == "") { + // single unnamed result (if type hashing, name must be ignored) w.typ(sig.results.vars[0].typ) return } -- GitLab From 1a9807906df1d1cb9955dfda387b92e03375c0f0 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 31 Aug 2021 18:20:49 -0400 Subject: [PATCH 0940/2500] go/types: more systematic error handling in typeWriter This is a port of CL 346009 to go/types. An unnecessary break statement was removed from both the port and types2. Change-Id: I2cc1328a61100d4b01a2d26ac7bac9044440d579 Reviewed-on: https://go-review.googlesource.com/c/go/+/346558 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/cmd/compile/internal/types2/typestring.go | 1 - src/go/types/typestring.go | 81 +++++++++---------- 2 files changed, 39 insertions(+), 43 deletions(-) diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 204e20c7ff..da5de08758 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -212,7 +212,6 @@ func (w *typeWriter) typ(typ Type) { s = "<-chan " default: w.error("unknown channel direction") - break } w.string(s) if parens { diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 3a6bb9aafc..3d30ff98f3 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -56,6 +56,14 @@ func WriteType(buf *bytes.Buffer, typ Type, qf Qualifier) { newTypeWriter(buf, qf).typ(typ) } +// WriteSignature writes the representation of the signature sig to buf, +// without a leading "func" keyword. +// The Qualifier controls the printing of +// package-level objects, and may be nil. +func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) { + newTypeWriter(buf, qf).signature(sig) +} + // instanceMarker is the prefix for an instantiated type in unexpanded form. const instanceMarker = '#' @@ -77,10 +85,16 @@ func newTypeHasher(buf *bytes.Buffer) *typeWriter { func (w *typeWriter) byte(b byte) { w.buf.WriteByte(b) } func (w *typeWriter) string(s string) { w.buf.WriteString(s) } func (w *typeWriter) writef(format string, args ...interface{}) { fmt.Fprintf(w.buf, format, args...) } +func (w *typeWriter) error(msg string) { + if w.hash { + panic(msg) + } + w.string("<" + msg + ">") +} func (w *typeWriter) typ(typ Type) { if w.seen[typ] { - w.writef("○%T", goTypeName(typ)) // cycle to typ + w.error("cycle to " + goTypeName(typ)) return } w.seen[typ] = true @@ -88,7 +102,7 @@ func (w *typeWriter) typ(typ Type) { switch t := typ.(type) { case nil: - w.string("") + w.error("nil") case *Basic: // exported basic types go into package unsafe @@ -144,7 +158,8 @@ func (w *typeWriter) typ(typ Type) { // Unions only appear as (syntactic) embedded elements // in interfaces and syntactically cannot be empty. if t.Len() == 0 { - panic("empty union") + w.error("empty union") + break } for i, t := range t.terms { if i > 0 { @@ -197,7 +212,7 @@ func (w *typeWriter) typ(typ Type) { case RecvOnly: s = "<-chan " default: - unreachable() + w.error("unknown channel direction") } w.string(s) if parens { @@ -226,21 +241,21 @@ func (w *typeWriter) typ(typ Type) { } case *TypeParam: - s := "?" - if t.obj != nil { - // Optionally write out package for typeparams (like Named). - // TODO(danscales): this is required for import/export, so - // we maybe need a separate function that won't be changed - // for debugging purposes. - if t.obj.pkg != nil { - writePackage(w.buf, t.obj.pkg, w.qf) - } - s = t.obj.name + if t.obj == nil { + w.error("unnamed type parameter") + break } - w.string(s + subscript(t.id)) + // Optionally write out package for typeparams (like Named). + // TODO(danscales): this is required for import/export, so + // we maybe need a separate function that won't be changed + // for debugging purposes. + if t.obj.pkg != nil { + writePackage(w.buf, t.obj.pkg, w.qf) + } + w.string(t.obj.name + subscript(t.id)) case *top: - w.string("⊤") + w.error("⊤") default: // For externally defined implementations of Type. @@ -267,26 +282,20 @@ func (w *typeWriter) tParamList(list []*TypeParam) { // Determine the type parameter and its constraint. // list is expected to hold type parameter names, // but don't crash if that's not the case. - var bound Type - if tpar != nil { - bound = tpar.bound // should not be nil but we want to see it if it is + if tpar == nil { + w.error("nil type parameter") + continue } - if i > 0 { - if bound != prev { + if tpar.bound != prev { // bound changed - write previous one before advancing w.byte(' ') w.typ(prev) } w.string(", ") } - prev = bound - - if tpar != nil { - w.typ(tpar) - } else { - w.string(tpar.obj.name) - } + prev = tpar.bound + w.typ(tpar) } if prev != nil { w.byte(' ') @@ -296,11 +305,6 @@ func (w *typeWriter) tParamList(list []*TypeParam) { } func (w *typeWriter) typeName(obj *TypeName) { - if obj == nil { - assert(!w.hash) // we need an object for type hashing - w.string("") - return - } if obj.pkg != nil { writePackage(w.buf, obj.pkg, w.qf) } @@ -353,7 +357,8 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) { // special case: // append(s, "foo"...) leads to signature func([]byte, string...) if t := asBasic(typ); t == nil || t.kind != String { - panic("expected string type") + w.error("expected string type") + continue } w.typ(typ) w.string("...") @@ -366,14 +371,6 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) { w.byte(')') } -// WriteSignature writes the representation of the signature sig to buf, -// without a leading "func" keyword. -// The Qualifier controls the printing of -// package-level objects, and may be nil. -func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) { - newTypeWriter(buf, qf).signature(sig) -} - func (w *typeWriter) signature(sig *Signature) { if sig.TParams().Len() != 0 { w.tParamList(sig.TParams().list()) -- GitLab From 36ac2214fadc64f33f5e8c4076d123ba4e40a665 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 31 Aug 2021 18:26:16 -0400 Subject: [PATCH 0941/2500] go/types: remove superfluous ordinaryType calls This is a port of CL 346291 to go/types. Change-Id: I8f864aca5cdb4037bc27a81cde1597430b9a48db Reviewed-on: https://go-review.googlesource.com/c/go/+/346559 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/types/expr.go | 1 - src/go/types/stmt.go | 1 - .../types/testdata/fixedbugs/issue42758.go2 | 2 +- src/go/types/typexpr.go | 19 +++++++------------ 4 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 2a204cf5f6..e574156562 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -1386,7 +1386,6 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { check.invalidOp(x, _InvalidAssert, "%s is not an interface", x) goto Error } - check.ordinaryType(x, xtyp) // x.(type) expressions are handled explicitly in type switches if e.Type == nil { // Don't use invalidAST because this can occur in the AST produced by diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index e74862afef..e5830bfdd4 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -696,7 +696,6 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { check.errorf(&x, _InvalidTypeSwitch, "%s is not an interface", &x) return } - check.ordinaryType(&x, xtyp) check.multipleDefaults(s.Body.List) diff --git a/src/go/types/testdata/fixedbugs/issue42758.go2 b/src/go/types/testdata/fixedbugs/issue42758.go2 index bf0031f5d2..dd66e9648b 100644 --- a/src/go/types/testdata/fixedbugs/issue42758.go2 +++ b/src/go/types/testdata/fixedbugs/issue42758.go2 @@ -28,6 +28,6 @@ func _[T constraint](x interface{}){ } func _(x constraint /* ERROR contains type constraints */ ) { - switch x /* ERROR contains type constraints */ .(type) { + switch x.(type) { // no need to report another error } } diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index a126241afa..533f976f1d 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -132,32 +132,27 @@ func (check *Checker) typ(e ast.Expr) Type { } // varType type-checks the type expression e and returns its type, or Typ[Invalid]. -// The type must not be an (uninstantiated) generic type and it must be ordinary -// (see ordinaryType). +// The type must not be an (uninstantiated) generic type and it must not be a +// constraint interface. func (check *Checker) varType(e ast.Expr) Type { typ := check.definedType(e, nil) - check.ordinaryType(e, typ) - return typ -} - -// ordinaryType reports an error if typ is an interface type containing -// type lists or is (or embeds) the predeclared type comparable. -func (check *Checker) ordinaryType(pos positioner, typ Type) { // We don't want to call under() (via asInterface) or complete interfaces while we // are in the middle of type-checking parameter declarations that might belong to // interface methods. Delay this check to the end of type-checking. check.later(func() { if t := asInterface(typ); t != nil { - tset := computeInterfaceTypeSet(check, pos.Pos(), t) // TODO(gri) is this the correct position? + tset := computeInterfaceTypeSet(check, e.Pos(), t) // TODO(gri) is this the correct position? if tset.IsConstraint() { if tset.comparable { - check.softErrorf(pos, _Todo, "interface is (or embeds) comparable") + check.softErrorf(e, _Todo, "interface is (or embeds) comparable") } else { - check.softErrorf(pos, _Todo, "interface contains type constraints") + check.softErrorf(e, _Todo, "interface contains type constraints") } } } }) + + return typ } // anyType type-checks the type expression e and returns its type, or Typ[Invalid]. -- GitLab From f4e24599dd2fe81690c6dacceec1d9336bf24c60 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 31 Aug 2021 18:32:21 -0400 Subject: [PATCH 0942/2500] go/types: disallow aliases for generic types This is a port of CL 346294 to go/types. Change-Id: Ib70541a92e352c8df8123c8b82bb4eeedce3b89f Reviewed-on: https://go-review.googlesource.com/c/go/+/346560 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/types/decl.go | 2 +- src/go/types/testdata/check/typeinst.go2 | 10 ++++++---- src/go/types/testdata/fixedbugs/issue39768.go2 | 6 +++--- src/go/types/testdata/fixedbugs/issue47968.go2 | 2 +- src/go/types/typexpr.go | 18 ++++++------------ 5 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 758ebf5d7f..275d17c826 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -603,7 +603,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { } obj.typ = Typ[Invalid] - rhs = check.anyType(tdecl.Type) + rhs = check.varType(tdecl.Type) obj.typ = rhs return } diff --git a/src/go/types/testdata/check/typeinst.go2 b/src/go/types/testdata/check/typeinst.go2 index 069bd3bc16..4a8918ab86 100644 --- a/src/go/types/testdata/check/typeinst.go2 +++ b/src/go/types/testdata/check/typeinst.go2 @@ -17,13 +17,15 @@ type T2[P any] struct { type List[P any] []P -// Alias type declarations cannot have type parameters. Syntax error. +// Alias type declarations cannot have type parameters. +// Issue #46477 proposses to change that. type A1[P any] = /* ERROR cannot be alias */ P -// But an alias may refer to a generic, uninstantiated type. -type A2 = List +// Pending clarification of #46477 we disallow aliases +// of generic types. +type A2 = List // ERROR cannot use generic type var _ A2[int] -var _ A2 /* ERROR without instantiation */ +var _ A2 type A3 = List[int] var _ A3 diff --git a/src/go/types/testdata/fixedbugs/issue39768.go2 b/src/go/types/testdata/fixedbugs/issue39768.go2 index abac141d7f..fb522733e0 100644 --- a/src/go/types/testdata/fixedbugs/issue39768.go2 +++ b/src/go/types/testdata/fixedbugs/issue39768.go2 @@ -5,9 +5,9 @@ package p type T[P any] P -type A = T +type A = T // ERROR cannot use generic type var x A[int] -var _ A /* ERROR cannot use generic type */ +var _ A type B = T[int] var y B = x @@ -16,5 +16,5 @@ var _ B /* ERROR not a generic type */ [int] // test case from issue type Vector[T any] []T -type VectorAlias = Vector +type VectorAlias = Vector // ERROR cannot use generic type var v Vector[int] diff --git a/src/go/types/testdata/fixedbugs/issue47968.go2 b/src/go/types/testdata/fixedbugs/issue47968.go2 index bbbe6805f2..711e50a55a 100644 --- a/src/go/types/testdata/fixedbugs/issue47968.go2 +++ b/src/go/types/testdata/fixedbugs/issue47968.go2 @@ -8,7 +8,7 @@ type T[P any] struct{} func (T[P]) m1() -type A1 = T +type A1 = T // ERROR cannot use generic type func (A1[P]) m2() {} diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 533f976f1d..af56297144 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -36,12 +36,15 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool) } return case universeAny, universeComparable: - // complain if necessary but keep going + // complain if necessary if !check.allowVersion(check.pkg, 1, 18) { - check.softErrorf(e, _UndeclaredName, "undeclared name: %s (requires version go1.18 or later)", e.Name) - } else if obj == universeAny { + check.errorf(e, _UndeclaredName, "undeclared name: %s (requires version go1.18 or later)", e.Name) + return // avoid follow-on errors + } + if obj == universeAny { // If we allow "any" for general use, this if-statement can be removed (issue #33232). check.softErrorf(e, _Todo, "cannot use any outside constraint position") + // ok to continue } } check.recordUse(e, obj) @@ -155,15 +158,6 @@ func (check *Checker) varType(e ast.Expr) Type { return typ } -// anyType type-checks the type expression e and returns its type, or Typ[Invalid]. -// The type may be generic or instantiated. -func (check *Checker) anyType(e ast.Expr) Type { - typ := check.typInternal(e, nil) - assert(isTyped(typ)) - check.recordTypeAndValue(e, typexpr, typ, nil) - return typ -} - // definedType is like typ but also accepts a type name def. // If def != nil, e is the type specification for the defined type def, declared // in a type declaration, and def.underlying will be set to the type of e before -- GitLab From 62ba72b35321bd76de18aa8874b021ee02ab8a4e Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 1 Sep 2021 00:18:13 +0700 Subject: [PATCH 0943/2500] cmd/compile: fix method expression lookup during import CL 309831 fixed importing of method expressions, by re-using the same code already have for ODOTMETH. But that code does not work with embedded field. To fix this, we need to calculate all methods of the receiver base type of method expression, before looking up the selection. Fixes #48088 Change-Id: Ia244d36a3ed0f989735eb57becdfa70a81912f57 Reviewed-on: https://go-review.googlesource.com/c/go/+/346489 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/typecheck/iimport.go | 6 +++-- test/fixedbugs/issue48088.dir/a.go | 22 +++++++++++++++++++ test/fixedbugs/issue48088.dir/b.go | 11 ++++++++++ test/fixedbugs/issue48088.go | 7 ++++++ 4 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 test/fixedbugs/issue48088.dir/a.go create mode 100644 test/fixedbugs/issue48088.dir/b.go create mode 100644 test/fixedbugs/issue48088.go diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 45bf2563aa..7855702b02 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1408,12 +1408,14 @@ func (r *importReader) node() ir.Node { } case ir.ODOT, ir.ODOTPTR, ir.ODOTINTER: n.Selection = r.exoticField() - case ir.ODOTMETH, ir.OMETHVALUE, ir.OMETHEXPR: + case ir.OMETHEXPR: + n = typecheckMethodExpr(n).(*ir.SelectorExpr) + case ir.ODOTMETH, ir.OMETHVALUE: // These require a Lookup to link to the correct declaration. rcvrType := expr.Type() typ := n.Type() n.Selection = Lookdot(n, rcvrType, 1) - if op == ir.OMETHVALUE || op == ir.OMETHEXPR { + if op == ir.OMETHVALUE { // Lookdot clobbers the opcode and type, undo that. n.SetOp(op) n.SetType(typ) diff --git a/test/fixedbugs/issue48088.dir/a.go b/test/fixedbugs/issue48088.dir/a.go new file mode 100644 index 0000000000..2bb879d557 --- /dev/null +++ b/test/fixedbugs/issue48088.dir/a.go @@ -0,0 +1,22 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type T1 struct { + *T2 +} + +type T2 struct { +} + +func (t2 *T2) M() { +} + +func F() { + f(T1.M) +} + +func f(f func(T1)) { +} diff --git a/test/fixedbugs/issue48088.dir/b.go b/test/fixedbugs/issue48088.dir/b.go new file mode 100644 index 0000000000..221f2dde2a --- /dev/null +++ b/test/fixedbugs/issue48088.dir/b.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package b + +import "a" + +func F() { + a.F() +} diff --git a/test/fixedbugs/issue48088.go b/test/fixedbugs/issue48088.go new file mode 100644 index 0000000000..b83fbd7af1 --- /dev/null +++ b/test/fixedbugs/issue48088.go @@ -0,0 +1,7 @@ +// compiledir + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From 2dd7b770defc869edfcf610b9471fc4f580c3eb2 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 31 Aug 2021 19:06:46 -0700 Subject: [PATCH 0944/2500] cmd/compile: fix missing case for shape double-check function Missing case types.TUNSAFEPTR in parameterizedBy(). Also realized there was the same missing case in the type substituter (*Tsubster).Typ(). Fixes #48103 Change-Id: If71f1a6ef80932f0e2120d4c18b39a30189fd8fe Reviewed-on: https://go-review.googlesource.com/c/go/+/346669 Reviewed-by: Keith Randall Trust: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 2 +- src/cmd/compile/internal/typecheck/subr.go | 2 +- test/typeparam/issue48013.go | 39 ++++++++++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 test/typeparam/issue48013.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index cf3894e096..1717317925 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1917,7 +1917,7 @@ func parameterizedBy1(t *types.Type, params []*types.Type, visited map[*types.Ty case types.TINT, types.TINT8, types.TINT16, types.TINT32, types.TINT64, types.TUINT, types.TUINT8, types.TUINT16, types.TUINT32, types.TUINT64, - types.TUINTPTR, types.TBOOL, types.TSTRING, types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128: + types.TUINTPTR, types.TBOOL, types.TSTRING, types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128, types.TUNSAFEPTR: return true case types.TUNION: diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 3ec2cc5d56..541e1907c0 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1189,7 +1189,7 @@ func (ts *Tsubster) typ1(t *types.Type) *types.Type { } case types.TINT, types.TINT8, types.TINT16, types.TINT32, types.TINT64, types.TUINT, types.TUINT8, types.TUINT16, types.TUINT32, types.TUINT64, - types.TUINTPTR, types.TBOOL, types.TSTRING, types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128: + types.TUINTPTR, types.TBOOL, types.TSTRING, types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128, types.TUNSAFEPTR: newt = t.Underlying() case types.TUNION: nt := t.NumTerms() diff --git a/test/typeparam/issue48013.go b/test/typeparam/issue48013.go new file mode 100644 index 0000000000..179d9f44e9 --- /dev/null +++ b/test/typeparam/issue48013.go @@ -0,0 +1,39 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + "unsafe" +) + +type S[T any] struct { + val T +} + +// Test type substitution where base type is unsafe.Pointer +type U[T any] unsafe.Pointer + +func test[T any]() T { + var q U[T] + var v struct { + // Test derived type that contains an unsafe.Pointer + p unsafe.Pointer + val T + } + _ = q + return v.val +} + +func main() { + want := 0 + got := test[int]() + if got != want { + panic(fmt.Sprintf("got %f, want %f", got, want)) + } + +} -- GitLab From faf9c7d8fe9885a8d96de389f16bc4fdadb067a2 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 31 Aug 2021 14:53:53 -0700 Subject: [PATCH 0945/2500] cmd/compile: assign results of transformAssign back to source location Otherwise the modifications of transformAssign are dropped on the floor. Change-Id: Id40782564952ed53f9ade1dba4e85290c8522abc Reviewed-on: https://go-review.googlesource.com/c/go/+/346590 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 1717317925..7ba266a150 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -966,6 +966,7 @@ func (subst *subster) node(n ir.Node) ir.Node { // of zeroing assignment of a dcl (rhs[0] is nil). lhs, rhs := []ir.Node{as.X}, []ir.Node{as.Y} transformAssign(as, lhs, rhs) + as.X, as.Y = lhs[0], rhs[0] } case ir.OASOP: -- GitLab From 5a687eeaf186dd109e53860db15f8465b0456fc0 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Sat, 21 Aug 2021 18:40:20 +1000 Subject: [PATCH 0946/2500] cmd/asm,cmd/internal/obj/riscv: add more error tests for riscv64 assembly Add more error tests for riscv64 assembly. Also avoid a panic when one of these error conditions is hit. Change-Id: If5d913894facbd67f7d014eab745da77c8c66ab0 Reviewed-on: https://go-review.googlesource.com/c/go/+/344228 Trust: Joel Sing Run-TryBot: Joel Sing TryBot-Result: Go Bot Reviewed-by: Meng Zhuo --- src/cmd/asm/internal/asm/testdata/riscv64error.s | 12 ++++++++++++ src/cmd/internal/obj/riscv/obj.go | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/cmd/asm/internal/asm/testdata/riscv64error.s b/src/cmd/asm/internal/asm/testdata/riscv64error.s index fb43e68fc1..b09a1c7a8c 100644 --- a/src/cmd/asm/internal/asm/testdata/riscv64error.s +++ b/src/cmd/asm/internal/asm/testdata/riscv64error.s @@ -3,6 +3,14 @@ // license that can be found in the LICENSE file. TEXT errors(SB),$0 + MOV $errors(SB), (X5) // ERROR "unsupported addr MOV" + MOV $8(SP), (X5) // ERROR "unsupported addr MOV" + MOVB $8(SP), X5 // ERROR "unsupported addr MOV" + MOVH $8(SP), X5 // ERROR "unsupported addr MOV" + MOVW $8(SP), X5 // ERROR "unsupported addr MOV" + MOVF $8(SP), X5 // ERROR "unsupported addr MOV" + MOV $1234, 0(SP) // ERROR "constant load must target register" + MOV $1234, 8(SP) // ERROR "constant load must target register" MOV $0, 0(SP) // ERROR "constant load must target register" MOV $0, 8(SP) // ERROR "constant load must target register" MOV $1234, 0(SP) // ERROR "constant load must target register" @@ -11,4 +19,8 @@ TEXT errors(SB),$0 MOVH $1, X5 // ERROR "unsupported constant load" MOVW $1, X5 // ERROR "unsupported constant load" MOVF $1, X5 // ERROR "unsupported constant load" + MOVBU X5, (X6) // ERROR "unsupported unsigned store" + MOVHU X5, (X6) // ERROR "unsupported unsigned store" + MOVWU X5, (X6) // ERROR "unsupported unsigned store" + RET diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index a305edab4b..f89e13d81c 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -271,6 +271,7 @@ func rewriteMOV(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog) { switch p.As { case AMOVBU, AMOVHU, AMOVWU: ctxt.Diag("unsupported unsigned store at %v", p) + return } switch p.To.Name { case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE: @@ -1795,7 +1796,7 @@ func instructionsForProg(p *obj.Prog) []*instruction { case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD: // Handle register to register moves. if p.From.Type != obj.TYPE_REG || p.To.Type != obj.TYPE_REG { - break + return nil } switch p.As { case AMOV: // MOV Ra, Rb -> ADDI $0, Ra, Rb -- GitLab From 717f337d1d68299ca55a96e9fbb5168e8f7788f4 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Thu, 19 Aug 2021 04:06:55 +0000 Subject: [PATCH 0947/2500] cmd/asm: adjust riscv64 test data to avoid churn Rather than jumping and branching to a label (the offset for which changes when instructions are added or removed), use PC-relative offsets. This reduces unnecessary churn in the instruction encodings. Change-Id: I6816ce939eeabdf828039f59f4f29260eb1ac8da Reviewed-on: https://go-review.googlesource.com/c/go/+/344449 Trust: Joel Sing Run-TryBot: Joel Sing TryBot-Result: Go Bot Reviewed-by: Michael Munday --- src/cmd/asm/internal/asm/testdata/riscv64.s | 48 ++++++++++----------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/riscv64.s b/src/cmd/asm/internal/asm/testdata/riscv64.s index 77c0764c48..628a8d91cd 100644 --- a/src/cmd/asm/internal/asm/testdata/riscv64.s +++ b/src/cmd/asm/internal/asm/testdata/riscv64.s @@ -86,20 +86,15 @@ start: SRA $1, X5 // 93d21240 // 2.5: Control Transfer Instructions - - // These jumps and branches get printed as a jump or branch - // to 2 because they transfer control to the second instruction - // in the function (the first instruction being an invisible - // stack pointer adjustment). - JAL X5, start // JAL X5, 2 // eff25ff0 + JAL X5, 2(PC) // ef028000 JALR X6, (X5) // 67830200 JALR X6, 4(X5) // 67834200 - BEQ X5, X6, start // BEQ X5, X6, 2 // e38c62ee - BNE X5, X6, start // BNE X5, X6, 2 // e39a62ee - BLT X5, X6, start // BLT X5, X6, 2 // e3c862ee - BLTU X5, X6, start // BLTU X5, X6, 2 // e3e662ee - BGE X5, X6, start // BGE X5, X6, 2 // e3d462ee - BGEU X5, X6, start // BGEU X5, X6, 2 // e3f262ee + BEQ X5, X6, 2(PC) // 63846200 + BNE X5, X6, 2(PC) // 63946200 + BLT X5, X6, 2(PC) // 63c46200 + BLTU X5, X6, 2(PC) // 63e46200 + BGE X5, X6, 2(PC) // 63d46200 + BGEU X5, X6, 2(PC) // 63f46200 // 2.6: Load and Store Instructions LW (X5), X6 // 03a30200 @@ -325,10 +320,11 @@ start: NEGW X5 // bb025040 NEGW X5, X6 // 3b035040 - // These jumps can get printed as jumps to 2 because they go to the - // second instruction in the function (the first instruction is an - // invisible stack pointer adjustment). - JMP start // JMP 2 // 6ff01fc2 + // This jumps to the second instruction in the function (the + // first instruction is an invisible stack pointer adjustment). + JMP start // JMP 2 + + JMP 2(PC) // 6f008000 JMP (X5) // 67800200 JMP 4(X5) // 67804200 @@ -341,16 +337,16 @@ start: JMP asmtest(SB) // 970f0000 // Branch pseudo-instructions - BEQZ X5, start // BEQZ X5, 2 // e38202c0 - BGEZ X5, start // BGEZ X5, 2 // e3d002c0 - BGT X5, X6, start // BGT X5, X6, 2 // e34e53be - BGTU X5, X6, start // BGTU X5, X6, 2 // e36c53be - BGTZ X5, start // BGTZ X5, 2 // e34a50be - BLE X5, X6, start // BLE X5, X6, 2 // e35853be - BLEU X5, X6, start // BLEU X5, X6, 2 // e37653be - BLEZ X5, start // BLEZ X5, 2 // e35450be - BLTZ X5, start // BLTZ X5, 2 // e3c202be - BNEZ X5, start // BNEZ X5, 2 // e39002be + BEQZ X5, 2(PC) // 63840200 + BGEZ X5, 2(PC) // 63d40200 + BGT X5, X6, 2(PC) // 63445300 + BGTU X5, X6, 2(PC) // 63645300 + BGTZ X5, 2(PC) // 63445000 + BLE X5, X6, 2(PC) // 63545300 + BLEU X5, X6, 2(PC) // 63745300 + BLEZ X5, 2(PC) // 63545000 + BLTZ X5, 2(PC) // 63c40200 + BNEZ X5, 2(PC) // 63940200 // Set pseudo-instructions SEQZ X15, X15 // 93b71700 -- GitLab From 5670ff4ae593019c33b8095a6341deb657be34d7 Mon Sep 17 00:00:00 2001 From: korzhao Date: Mon, 16 Aug 2021 22:25:47 +0800 Subject: [PATCH 0948/2500] cmd/compile: fix conversions from TypeParam to interface If the TypeParam has all the methods of an interface, allow conversions from TypeParam to interface Fixes #47708 Change-Id: I40a82a31f6ea9354130dbe3bcfc83537094bf12c Reviewed-on: https://go-review.googlesource.com/c/go/+/342509 Reviewed-by: Dan Scales Reviewed-by: Robert Griesemer Trust: Dan Scales Trust: Keith Randall Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot --- src/cmd/compile/internal/typecheck/subr.go | 13 +++++-- test/typeparam/issue47708.go | 40 ++++++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 test/typeparam/issue47708.go diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 541e1907c0..4696b62cd2 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -740,9 +740,16 @@ func implements(t, iface *types.Type, m, samename **types.Field, ptr *int) bool if t.IsInterface() || t.IsTypeParam() { if t.IsTypeParam() { - // A typeparam satisfies an interface if its type bound - // has all the methods of that interface. - t = t.Bound() + // If t is a simple type parameter T, its type and underlying is the same. + // If t is a type definition:'type P[T any] T', its type is P[T] and its + // underlying is T. Therefore we use 't.Underlying() != t' to distinguish them. + if t.Underlying() != t { + CalcMethods(t) + } else { + // A typeparam satisfies an interface if its type bound + // has all the methods of that interface. + t = t.Bound() + } } i := 0 tms := t.AllMethods().Slice() diff --git a/test/typeparam/issue47708.go b/test/typeparam/issue47708.go new file mode 100644 index 0000000000..261d6efb61 --- /dev/null +++ b/test/typeparam/issue47708.go @@ -0,0 +1,40 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" +) + +type FooType[T any] interface { + Foo(BarType[T])string +} +type BarType[T any] interface { + Bar(FooType[T])string +} + +type Baz[T any] T +func (l Baz[T]) Foo(v BarType[T]) string { + return v.Bar(l) +} +type Bob[T any] T +func (l Bob[T]) Bar(v FooType[T]) string { + if v,ok := v.(Baz[T]);ok{ + return fmt.Sprintf("%v%v",v,l) + } + return "" +} + + +func main() { + var baz Baz[int] = 123 + var bob Bob[int] = 456 + + if got, want := baz.Foo(bob), "123456"; got != want { + panic(fmt.Sprintf("got %s want %s", got, want)) + } +} -- GitLab From 8f397bc1183b1094f8d0c702668b1e2b43dc8797 Mon Sep 17 00:00:00 2001 From: "Paul E. Murphy" Date: Tue, 9 Mar 2021 16:55:18 -0600 Subject: [PATCH 0949/2500] cmd/internal/obj/ppc64: improve long conditional branch fixup Improve the code which fixes up conditional branches which exceed the range of a single instruction by inserting one extra jump when possible instead of two. Change-Id: Ib0eb5b0f47f7d0e0ccd55471307a5f73fbda88a9 Reviewed-on: https://go-review.googlesource.com/c/go/+/342930 Run-TryBot: Paul Murphy TryBot-Result: Go Bot Reviewed-by: Lynn Boger Reviewed-by: Cherry Mui --- src/cmd/internal/obj/ppc64/a.out.go | 15 ++--- src/cmd/internal/obj/ppc64/asm9.go | 86 +++++++++++++++++++++++------ 2 files changed, 74 insertions(+), 27 deletions(-) diff --git a/src/cmd/internal/obj/ppc64/a.out.go b/src/cmd/internal/obj/ppc64/a.out.go index 428cac528a..e57beb3276 100644 --- a/src/cmd/internal/obj/ppc64/a.out.go +++ b/src/cmd/internal/obj/ppc64/a.out.go @@ -329,18 +329,13 @@ const ( BI_OVF = 3 ) -// Values for the BO field. Add the branch type to -// the likely bits, if a likely setting is known. -// If branch likely or unlikely is not known, don't set it. -// e.g. branch on cr+likely = 15 +// Common values for the BO field. const ( - BO_BCTR = 16 // branch on ctr value - BO_BCR = 12 // branch on cr value - BO_BCRBCTR = 8 // branch on ctr and cr value - BO_NOTBCR = 4 // branch on not cr value - BO_UNLIKELY = 2 // value for unlikely - BO_LIKELY = 3 // value for likely + BO_BCTR = 16 // decrement ctr, branch on ctr != 0 + BO_BCR = 12 // branch on cr value + BO_BCRBCTR = 8 // decrement ctr, branch on ctr != 0 and cr value + BO_NOTBCR = 4 // branch on not cr value ) // Bit settings from the CR diff --git a/src/cmd/internal/obj/ppc64/asm9.go b/src/cmd/internal/obj/ppc64/asm9.go index 316959f62d..e642413590 100644 --- a/src/cmd/internal/obj/ppc64/asm9.go +++ b/src/cmd/internal/obj/ppc64/asm9.go @@ -642,6 +642,7 @@ func span9(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { var otxt int64 var q *obj.Prog + var out [6]uint32 for bflag != 0 { bflag = 0 pc = 0 @@ -653,22 +654,74 @@ func span9(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { if (o.type_ == 16 || o.type_ == 17) && p.To.Target() != nil { otxt = p.To.Target().Pc - pc if otxt < -(1<<15)+10 || otxt >= (1<<15)-10 { - q = c.newprog() - q.Link = p.Link - p.Link = q - q.As = ABR - q.To.Type = obj.TYPE_BRANCH - q.To.SetTarget(p.To.Target()) - p.To.SetTarget(q) - q = c.newprog() - q.Link = p.Link - p.Link = q - q.As = ABR - q.To.Type = obj.TYPE_BRANCH - q.To.SetTarget(q.Link.Link) - - //addnop(p->link); - //addnop(p); + // Assemble the instruction with a target not too far to figure out BI and BO fields. + // If only the CTR or BI (the CR bit) are tested, the conditional branch can be inverted, + // and only one extra branch is needed to reach the target. + tgt := p.To.Target() + p.To.SetTarget(p.Link) + c.asmout(p, o, out[:]) + p.To.SetTarget(tgt) + + bo := int64(out[0]>>21) & 31 + bi := int16((out[0] >> 16) & 31) + invertible := false + + if bo&0x14 == 0x14 { + // A conditional branch that is unconditionally taken. This cannot be inverted. + } else if bo&0x10 == 0x10 { + // A branch based on the value of CTR. Invert the CTR comparison against zero bit. + bo ^= 0x2 + invertible = true + } else if bo&0x04 == 0x04 { + // A branch based on CR bit. Invert the BI comparison bit. + bo ^= 0x8 + invertible = true + } + + if invertible { + // Rewrite + // BC bo,...,far_away_target + // NEXT_INSN + // to: + // BC invert(bo),next_insn + // JMP far_away_target + // next_insn: + // NEXT_INSN + p.As = ABC + p.From = obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: bo} + q = c.newprog() + q.As = ABR + q.To.Type = obj.TYPE_BRANCH + q.To.SetTarget(p.To.Target()) + q.Link = p.Link + p.To.SetTarget(p.Link) + p.Link = q + p.Reg = bi // TODO: This is a hack since BI bits are not enumerated as registers + } else { + // Rewrite + // BC ...,far_away_target + // NEXT_INSN + // to + // BC ...,tmp + // JMP next_insn + // tmp: + // JMP far_away_target + // next_insn: + // NEXT_INSN + q = c.newprog() + q.Link = p.Link + p.Link = q + q.As = ABR + q.To.Type = obj.TYPE_BRANCH + q.To.SetTarget(p.To.Target()) + p.To.SetTarget(q) + q = c.newprog() + q.Link = p.Link + p.Link = q + q.As = ABR + q.To.Type = obj.TYPE_BRANCH + q.To.SetTarget(q.Link.Link) + } bflag = 1 } } @@ -706,7 +759,6 @@ func span9(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { bp := c.cursym.P var i int32 - var out [6]uint32 for p := c.cursym.Func().Text.Link; p != nil; p = p.Link { c.pc = p.Pc o = c.oplook(p) -- GitLab From 6c5f0282422043b913bb7908efb8849905777c8b Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 31 Aug 2021 13:21:11 -0700 Subject: [PATCH 0950/2500] cmd/compile/internal/pkginit: separate "init" and "inittask" logic This CL splits the creation of the "init" function responsible for executing package-scope variable initialization statemens from the creation of the "inittask" record that tells the runtime how to sequence all program-wide package initialization. Longer term, this is desirable because sorting variable initialization is already handled by types2 (with Info.InitOrder), so we might as well reuse that. As a more immediate impetus, for unified IR, I want to defer method wrapper generation until after inlining (to know which wrappers are needed). But the staticinit optimization used to decide whether to emit the inittask calls into reflectdata, which in turn tries to generate its own method wrappers. So separating the work allows to create the "init" function early and then emit "inittask" after inlining is done. Change-Id: Ice1d421f92feecaaeafdf7da6b9647c0f27e3571 Reviewed-on: https://go-review.googlesource.com/c/go/+/346629 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/gc/main.go | 20 ++-- src/cmd/compile/internal/pkginit/init.go | 103 ++++++++++++------ src/cmd/compile/internal/pkginit/initorder.go | 10 +- 3 files changed, 85 insertions(+), 48 deletions(-) diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 8a365f8f6a..0dbe47f653 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -195,18 +195,19 @@ func Main(archInit func(*ssagen.ArchInfo)) { // because it generates itabs for initializing global variables. ssagen.InitConfig() - // Build init task. - if initTask := pkginit.Task(); initTask != nil { - typecheck.Export(initTask) - } + // Create "init" function for package-scope variable initialization + // statements, if any. + // + // Note: This needs to happen early, before any optimizations. The + // Go spec defines a precise order than initialization should be + // carried out in, and even mundane optimizations like dead code + // removal can skew the results (e.g., #43444). + pkginit.MakeInit() // Stability quirk: sort top-level declarations, so we're not // sensitive to the order that functions are added. In particular, // the order that noder+typecheck add function closures is very // subtle, and not important to reproduce. - // - // Note: This needs to happen after pkginit.Task, otherwise it risks - // changing the order in which top-level variables are initialized. if base.Debug.UnifiedQuirks != 0 { s := typecheck.Target.Decls sort.SliceStable(s, func(i, j int) bool { @@ -253,6 +254,11 @@ func Main(archInit func(*ssagen.ArchInfo)) { } ir.CurFunc = nil + // Build init task, if needed. + if initTask := pkginit.Task(); initTask != nil { + typecheck.Export(initTask) + } + // Generate ABI wrappers. Must happen before escape analysis // and doesn't benefit from dead-coding or inlining. symABIs.GenABIWrappers() diff --git a/src/cmd/compile/internal/pkginit/init.go b/src/cmd/compile/internal/pkginit/init.go index 7cad262214..40f1408260 100644 --- a/src/cmd/compile/internal/pkginit/init.go +++ b/src/cmd/compile/internal/pkginit/init.go @@ -6,14 +6,62 @@ package pkginit import ( "cmd/compile/internal/base" - "cmd/compile/internal/deadcode" "cmd/compile/internal/ir" "cmd/compile/internal/objw" + "cmd/compile/internal/staticinit" "cmd/compile/internal/typecheck" "cmd/compile/internal/types" "cmd/internal/obj" + "cmd/internal/src" ) +// MakeInit creates a synthetic init function to handle any +// package-scope initialization statements. +// +// TODO(mdempsky): Move into noder, so that the types2-based frontends +// can use Info.InitOrder instead. +func MakeInit() { + nf := initOrder(typecheck.Target.Decls) + if len(nf) == 0 { + return + } + + // Make a function that contains all the initialization statements. + base.Pos = nf[0].Pos() // prolog/epilog gets line number of first init stmt + initializers := typecheck.Lookup("init") + fn := typecheck.DeclFunc(initializers, ir.NewFuncType(base.Pos, nil, nil, nil)) + for _, dcl := range typecheck.InitTodoFunc.Dcl { + dcl.Curfn = fn + } + fn.Dcl = append(fn.Dcl, typecheck.InitTodoFunc.Dcl...) + typecheck.InitTodoFunc.Dcl = nil + + // Suppress useless "can inline" diagnostics. + // Init functions are only called dynamically. + fn.SetInlinabilityChecked(true) + + fn.Body = nf + typecheck.FinishFuncBody() + + typecheck.Func(fn) + ir.WithFunc(fn, func() { + typecheck.Stmts(nf) + }) + typecheck.Target.Decls = append(typecheck.Target.Decls, fn) + + // Prepend to Inits, so it runs first, before any user-declared init + // functions. + typecheck.Target.Inits = append([]*ir.Func{fn}, typecheck.Target.Inits...) + + if typecheck.InitTodoFunc.Dcl != nil { + // We only generate temps using InitTodoFunc if there + // are package-scope initialization statements, so + // something's weird if we get here. + base.Fatalf("InitTodoFunc still has declarations") + } + typecheck.InitTodoFunc = nil +} + // Task makes and returns an initialization record for the package. // See runtime/proc.go:initTask for its layout. // The 3 tasks for initialization are: @@ -21,8 +69,6 @@ import ( // 2) Initialize all the variables that have initializers. // 3) Run any init functions. func Task() *ir.Name { - nf := initOrder(typecheck.Target.Decls) - var deps []*obj.LSym // initTask records for packages the current package depends on var fns []*obj.LSym // functions to call for package initialization @@ -38,39 +84,28 @@ func Task() *ir.Name { deps = append(deps, n.(*ir.Name).Linksym()) } - // Make a function that contains all the initialization statements. - if len(nf) > 0 { - base.Pos = nf[0].Pos() // prolog/epilog gets line number of first init stmt - initializers := typecheck.Lookup("init") - fn := typecheck.DeclFunc(initializers, ir.NewFuncType(base.Pos, nil, nil, nil)) - for _, dcl := range typecheck.InitTodoFunc.Dcl { - dcl.Curfn = fn - } - fn.Dcl = append(fn.Dcl, typecheck.InitTodoFunc.Dcl...) - typecheck.InitTodoFunc.Dcl = nil - - fn.Body = nf - typecheck.FinishFuncBody() - - typecheck.Func(fn) - ir.CurFunc = fn - typecheck.Stmts(nf) - ir.CurFunc = nil - typecheck.Target.Decls = append(typecheck.Target.Decls, fn) - fns = append(fns, fn.Linksym()) - } - if typecheck.InitTodoFunc.Dcl != nil { - // We only generate temps using InitTodoFunc if there - // are package-scope initialization statements, so - // something's weird if we get here. - base.Fatalf("InitTodoFunc still has declarations") - } - typecheck.InitTodoFunc = nil - // Record user init functions. for _, fn := range typecheck.Target.Inits { - // Must happen after initOrder; see #43444. - deadcode.Func(fn) + if fn.Sym().Name == "init" { + // Synthetic init function for initialization of package-scope + // variables. We can use staticinit to optimize away static + // assignments. + s := staticinit.Schedule{ + Plans: make(map[ir.Node]*staticinit.Plan), + Temps: make(map[ir.Node]*ir.Name), + } + for _, n := range fn.Body { + s.StaticInit(n) + } + fn.Body = s.Out + ir.WithFunc(fn, func() { + typecheck.Stmts(fn.Body) + }) + + if len(fn.Body) == 0 { + fn.Body = []ir.Node{ir.NewBlockStmt(src.NoXPos, nil)} + } + } // Skip init functions with empty bodies. if len(fn.Body) == 1 { diff --git a/src/cmd/compile/internal/pkginit/initorder.go b/src/cmd/compile/internal/pkginit/initorder.go index 0aad63a69f..a50975343f 100644 --- a/src/cmd/compile/internal/pkginit/initorder.go +++ b/src/cmd/compile/internal/pkginit/initorder.go @@ -11,7 +11,6 @@ import ( "cmd/compile/internal/base" "cmd/compile/internal/ir" - "cmd/compile/internal/staticinit" ) // Package initialization @@ -78,10 +77,7 @@ type InitOrder struct { // corresponding list of statements to include in the init() function // body. func initOrder(l []ir.Node) []ir.Node { - s := staticinit.Schedule{ - Plans: make(map[ir.Node]*staticinit.Plan), - Temps: make(map[ir.Node]*ir.Name), - } + var res ir.Nodes o := InitOrder{ blocking: make(map[ir.Node][]ir.Node), order: make(map[ir.Node]int), @@ -92,7 +88,7 @@ func initOrder(l []ir.Node) []ir.Node { switch n.Op() { case ir.OAS, ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV: o.processAssign(n) - o.flushReady(s.StaticInit) + o.flushReady(func(n ir.Node) { res.Append(n) }) case ir.ODCLCONST, ir.ODCLFUNC, ir.ODCLTYPE: // nop default: @@ -125,7 +121,7 @@ func initOrder(l []ir.Node) []ir.Node { base.Fatalf("expected empty map: %v", o.blocking) } - return s.Out + return res } func (o *InitOrder) processAssign(n ir.Node) { -- GitLab From 592ee433f5378e4b08f1fd8860be61b9bf20ca19 Mon Sep 17 00:00:00 2001 From: seifchen Date: Tue, 17 Aug 2021 23:54:33 +0000 Subject: [PATCH 0951/2500] spec: adjust example for consistency Change-Id: I5ff9078907b78f31aec42abf749a193b15bc5109 GitHub-Last-Rev: 1f96d84f203275a6012c19ec387bce091889d77d GitHub-Pull-Request: golang/go#47732 Reviewed-on: https://go-review.googlesource.com/c/go/+/342789 Reviewed-by: Robert Griesemer Trust: Cherry Mui --- doc/go_spec.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index 22b616134a..3e97974d6d 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -4350,7 +4350,7 @@ t0 := (*[0]string)(t) // t0 == nil t1 := (*[1]string)(t) // panics: len([1]string) > len(t) u := make([]byte, 0) -u0 = (*[0]byte)(u) // u0 != nil +u0 := (*[0]byte)(u) // u0 != nil

Constant expressions

-- GitLab From 711e1c8224f033ec1d95cdf84465b57b052e8948 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 1 Sep 2021 10:13:41 +0700 Subject: [PATCH 0952/2500] cmd/compile: fix irgen mis-handling invalid function declaration In -G=3 mode, irgen use its own generated IR, which is mis-handling of bodyless function and declared function with //go:noescape pragma. Fix this by adopting the same logic in noder.funcDecl, which minor change in linkname detection. Fixes #48097 Change-Id: Ibef921c1f75e071ca61685e0cb4543f2ee5efc7f Reviewed-on: https://go-review.googlesource.com/c/go/+/346470 Trust: Cuong Manh Le Trust: Dan Scales Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Cherry Mui Reviewed-by: Dan Scales Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/noder/decl.go | 4 ++++ src/cmd/compile/internal/noder/irgen.go | 22 ++++++++++++++----- .../compile/internal/types2/stdlib_test.go | 2 ++ src/go/types/stdlib_test.go | 1 + test/fixedbugs/issue48097.go | 12 ++++++++++ 5 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 test/fixedbugs/issue48097.go diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go index 87a8667003..de481fb5fc 100644 --- a/src/cmd/compile/internal/noder/decl.go +++ b/src/cmd/compile/internal/noder/decl.go @@ -113,6 +113,10 @@ func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) { } } + if decl.Body != nil && fn.Pragma&ir.Noescape != 0 { + base.ErrorfAt(fn.Pos(), "can only use //go:noescape with external func implementations") + } + if decl.Name.Value == "init" && decl.Recv == nil { g.target.Inits = append(g.target.Inits, fn) } diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index d53c254001..70f7991a8e 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -272,12 +272,6 @@ Outer: } } - // Check for unusual case where noder2 encounters a type error that types2 - // doesn't check for (e.g. notinheap incompatibility). - base.ExitIfErrors() - - typecheck.DeclareUniverse() - for _, p := range noders { // Process linkname and cgo pragmas. p.processPragmas() @@ -290,6 +284,22 @@ Outer: }) } + if base.Flag.Complete { + for _, n := range g.target.Decls { + if fn, ok := n.(*ir.Func); ok { + if fn.Body == nil && fn.Nname.Sym().Linkname == "" { + base.ErrorfAt(fn.Pos(), "missing function body") + } + } + } + } + + // Check for unusual case where noder2 encounters a type error that types2 + // doesn't check for (e.g. notinheap incompatibility). + base.ExitIfErrors() + + typecheck.DeclareUniverse() + // Create any needed stencils of generic functions g.stencil() diff --git a/src/cmd/compile/internal/types2/stdlib_test.go b/src/cmd/compile/internal/types2/stdlib_test.go index cde35c17b6..5bf2982418 100644 --- a/src/cmd/compile/internal/types2/stdlib_test.go +++ b/src/cmd/compile/internal/types2/stdlib_test.go @@ -192,6 +192,8 @@ func TestStdFixed(t *testing.T) { "issue20780.go", // types2 does not have constraints on stack size "issue42058a.go", // types2 does not have constraints on channel element size "issue42058b.go", // types2 does not have constraints on channel element size + "issue48097.go", // go/types doesn't check validity of //go:xxx directives, and non-init bodyless function + ) } diff --git a/src/go/types/stdlib_test.go b/src/go/types/stdlib_test.go index 3eb7519a91..12ed9a54f2 100644 --- a/src/go/types/stdlib_test.go +++ b/src/go/types/stdlib_test.go @@ -194,6 +194,7 @@ func TestStdFixed(t *testing.T) { "bug251.go", // issue #34333 which was exposed with fix for #34151 "issue42058a.go", // go/types does not have constraints on channel element size "issue42058b.go", // go/types does not have constraints on channel element size + "issue48097.go", // go/types doesn't check validity of //go:xxx directives, and non-init bodyless function ) } diff --git a/test/fixedbugs/issue48097.go b/test/fixedbugs/issue48097.go new file mode 100644 index 0000000000..b08c2a2f52 --- /dev/null +++ b/test/fixedbugs/issue48097.go @@ -0,0 +1,12 @@ +// errorcheck -complete + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func F() // ERROR "missing function body" + +//go:noescape +func f() {} // ERROR "can only use //go:noescape with external func implementations" -- GitLab From ea51e223c28babc530df475497de0be4579b5e86 Mon Sep 17 00:00:00 2001 From: Michael Munday Date: Wed, 17 Feb 2021 15:00:34 +0000 Subject: [PATCH 0953/2500] cmd/{asm,compile}: add fused multiply-add support on riscv64 Add support to the assembler for F[N]M{ADD,SUB}[SD] instructions. Argument order is: OP RS1, RS2, RS3, RD Also, add support for the FMA intrinsic to the compiler. Automatic FMA matching is left to a future CL. Change-Id: I47166c7393b2ab6bfc2e42aa8c1a8997c3a071b3 Reviewed-on: https://go-review.googlesource.com/c/go/+/293030 Trust: Michael Munday Run-TryBot: Michael Munday TryBot-Result: Go Bot Reviewed-by: Joel Sing --- src/cmd/asm/internal/asm/asm.go | 7 + src/cmd/asm/internal/asm/testdata/riscv64.s | 8 + src/cmd/compile/internal/riscv64/ssa.go | 13 +- .../compile/internal/ssa/gen/RISCV64.rules | 15 ++ .../compile/internal/ssa/gen/RISCV64Ops.go | 5 + src/cmd/compile/internal/ssa/opGen.go | 68 +++++++ .../compile/internal/ssa/rewriteRISCV64.go | 191 ++++++++++++++++++ src/cmd/compile/internal/ssagen/ssa.go | 2 +- src/cmd/internal/obj/riscv/obj.go | 104 ++++++++-- test/codegen/math.go | 16 ++ 10 files changed, 406 insertions(+), 23 deletions(-) diff --git a/src/cmd/asm/internal/asm/asm.go b/src/cmd/asm/internal/asm/asm.go index cf0d1550f9..d0cb6328f1 100644 --- a/src/cmd/asm/internal/asm/asm.go +++ b/src/cmd/asm/internal/asm/asm.go @@ -793,6 +793,13 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) { return } } + if p.arch.Family == sys.RISCV64 { + prog.From = a[0] + prog.Reg = p.getRegister(prog, op, &a[1]) + prog.SetRestArgs([]obj.Addr{a[2]}) + prog.To = a[3] + break + } if p.arch.Family == sys.S390X { if a[1].Type != obj.TYPE_REG { p.errorf("second operand must be a register in %s instruction", op) diff --git a/src/cmd/asm/internal/asm/testdata/riscv64.s b/src/cmd/asm/internal/asm/testdata/riscv64.s index 628a8d91cd..173c50f2e1 100644 --- a/src/cmd/asm/internal/asm/testdata/riscv64.s +++ b/src/cmd/asm/internal/asm/testdata/riscv64.s @@ -214,6 +214,10 @@ start: FMVSX X5, F0 // 538002f0 FMVXW F0, X5 // d30200e0 FMVWX X5, F0 // 538002f0 + FMADDS F1, F2, F3, F4 // 43822018 + FMSUBS F1, F2, F3, F4 // 47822018 + FNMSUBS F1, F2, F3, F4 // 4b822018 + FNMADDS F1, F2, F3, F4 // 4f822018 // 11.8: Single-Precision Floating-Point Compare Instructions FEQS F0, F1, X7 // d3a300a0 @@ -254,6 +258,10 @@ start: FSGNJXD F1, F0, F2 // 53211022 FMVXD F0, X5 // d30200e2 FMVDX X5, F0 // 538002f2 + FMADDD F1, F2, F3, F4 // 4382201a + FMSUBD F1, F2, F3, F4 // 4782201a + FNMSUBD F1, F2, F3, F4 // 4b82201a + FNMADDD F1, F2, F3, F4 // 4f82201a // 12.6: Double-Precision Floating-Point Classify Instruction FCLASSD F0, X5 // d31200e2 diff --git a/src/cmd/compile/internal/riscv64/ssa.go b/src/cmd/compile/internal/riscv64/ssa.go index d3cbb4ec24..30b6d96a89 100644 --- a/src/cmd/compile/internal/riscv64/ssa.go +++ b/src/cmd/compile/internal/riscv64/ssa.go @@ -317,7 +317,18 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p2.From.Reg = v.Reg1() p2.To.Type = obj.TYPE_REG p2.To.Reg = v.Reg1() - + case ssa.OpRISCV64FMADDD, ssa.OpRISCV64FMSUBD, ssa.OpRISCV64FNMADDD, ssa.OpRISCV64FNMSUBD: + r := v.Reg() + r1 := v.Args[0].Reg() + r2 := v.Args[1].Reg() + r3 := v.Args[2].Reg() + p := s.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_REG + p.From.Reg = r2 + p.Reg = r1 + p.SetRestArgs([]obj.Addr{{Type: obj.TYPE_REG, Reg: r3}}) + p.To.Type = obj.TYPE_REG + p.To.Reg = r case ssa.OpRISCV64FSQRTS, ssa.OpRISCV64FNEGS, ssa.OpRISCV64FSQRTD, ssa.OpRISCV64FNEGD, ssa.OpRISCV64FMVSX, ssa.OpRISCV64FMVDX, ssa.OpRISCV64FCVTSW, ssa.OpRISCV64FCVTSL, ssa.OpRISCV64FCVTWS, ssa.OpRISCV64FCVTLS, diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64.rules b/src/cmd/compile/internal/ssa/gen/RISCV64.rules index 4eb48e3928..b711550186 100644 --- a/src/cmd/compile/internal/ssa/gen/RISCV64.rules +++ b/src/cmd/compile/internal/ssa/gen/RISCV64.rules @@ -96,6 +96,8 @@ (Sqrt ...) => (FSQRTD ...) (Sqrt32 ...) => (FSQRTS ...) +(FMA ...) => (FMADDD ...) + // Sign and zero extension. (SignExt8to16 ...) => (MOVBreg ...) @@ -713,3 +715,16 @@ // Addition of zero. (ADDI [0] x) => x + +// Merge negation into fused multiply-add and multiply-subtract. +// +// Key: +// +// [+ -](x * y) [+ -] z. +// _ N A S +// D U +// D B +// +// Note: multiplication commutativity handled by rule generator. +(F(MADD|NMADD|MSUB|NMSUB)D neg:(FNEGD x) y z) && neg.Uses == 1 => (F(NMADD|MADD|NMSUB|MSUB)D x y z) +(F(MADD|NMADD|MSUB|NMSUB)D x y neg:(FNEGD z)) && neg.Uses == 1 => (F(MSUB|NMSUB|MADD|NMADD)D x y z) diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go index d36daa8b83..de189e4c60 100644 --- a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go @@ -132,6 +132,7 @@ func init() { fp11 = regInfo{inputs: []regMask{fpMask}, outputs: []regMask{fpMask}} fp21 = regInfo{inputs: []regMask{fpMask, fpMask}, outputs: []regMask{fpMask}} + fp31 = regInfo{inputs: []regMask{fpMask, fpMask, fpMask}, outputs: []regMask{fpMask}} gpfp = regInfo{inputs: []regMask{gpMask}, outputs: []regMask{fpMask}} fpgp = regInfo{inputs: []regMask{fpMask}, outputs: []regMask{gpMask}} fpstore = regInfo{inputs: []regMask{gpspsbMask, fpMask, 0}} @@ -425,6 +426,10 @@ func init() { {name: "FSUBD", argLength: 2, reg: fp21, asm: "FSUBD", commutative: false, typ: "Float64"}, // arg0 - arg1 {name: "FMULD", argLength: 2, reg: fp21, asm: "FMULD", commutative: true, typ: "Float64"}, // arg0 * arg1 {name: "FDIVD", argLength: 2, reg: fp21, asm: "FDIVD", commutative: false, typ: "Float64"}, // arg0 / arg1 + {name: "FMADDD", argLength: 3, reg: fp31, asm: "FMADDD", commutative: true, typ: "Float64"}, // (arg0 * arg1) + arg2 + {name: "FMSUBD", argLength: 3, reg: fp31, asm: "FMSUBD", commutative: true, typ: "Float64"}, // (arg0 * arg1) - arg2 + {name: "FNMADDD", argLength: 3, reg: fp31, asm: "FNMADDD", commutative: true, typ: "Float64"}, // -(arg0 * arg1) + arg2 + {name: "FNMSUBD", argLength: 3, reg: fp31, asm: "FNMSUBD", commutative: true, typ: "Float64"}, // -(arg0 * arg1) - arg2 {name: "FSQRTD", argLength: 1, reg: fp11, asm: "FSQRTD", typ: "Float64"}, // sqrt(arg0) {name: "FNEGD", argLength: 1, reg: fp11, asm: "FNEGD", typ: "Float64"}, // -arg0 {name: "FMVDX", argLength: 1, reg: gpfp, asm: "FMVDX", typ: "Float64"}, // reinterpret arg0 as float diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 737afc6087..672528aefe 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -2174,6 +2174,10 @@ const ( OpRISCV64FSUBD OpRISCV64FMULD OpRISCV64FDIVD + OpRISCV64FMADDD + OpRISCV64FMSUBD + OpRISCV64FNMADDD + OpRISCV64FNMSUBD OpRISCV64FSQRTD OpRISCV64FNEGD OpRISCV64FMVDX @@ -29054,6 +29058,70 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "FMADDD", + argLen: 3, + commutative: true, + asm: riscv.AFMADDD, + reg: regInfo{ + inputs: []inputInfo{ + {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + {2, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + }, + outputs: []outputInfo{ + {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + }, + }, + }, + { + name: "FMSUBD", + argLen: 3, + commutative: true, + asm: riscv.AFMSUBD, + reg: regInfo{ + inputs: []inputInfo{ + {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + {2, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + }, + outputs: []outputInfo{ + {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + }, + }, + }, + { + name: "FNMADDD", + argLen: 3, + commutative: true, + asm: riscv.AFNMADDD, + reg: regInfo{ + inputs: []inputInfo{ + {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + {2, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + }, + outputs: []outputInfo{ + {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + }, + }, + }, + { + name: "FNMSUBD", + argLen: 3, + commutative: true, + asm: riscv.AFNMSUBD, + reg: regInfo{ + inputs: []inputInfo{ + {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + {2, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + }, + outputs: []outputInfo{ + {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + }, + }, + }, { name: "FSQRTD", argLen: 1, diff --git a/src/cmd/compile/internal/ssa/rewriteRISCV64.go b/src/cmd/compile/internal/ssa/rewriteRISCV64.go index 641be038db..743ff50b0c 100644 --- a/src/cmd/compile/internal/ssa/rewriteRISCV64.go +++ b/src/cmd/compile/internal/ssa/rewriteRISCV64.go @@ -209,6 +209,9 @@ func rewriteValueRISCV64(v *Value) bool { return rewriteValueRISCV64_OpEqB(v) case OpEqPtr: return rewriteValueRISCV64_OpEqPtr(v) + case OpFMA: + v.Op = OpRISCV64FMADDD + return true case OpGetCallerPC: v.Op = OpRISCV64LoweredGetCallerPC return true @@ -432,6 +435,14 @@ func rewriteValueRISCV64(v *Value) bool { return rewriteValueRISCV64_OpRISCV64ADDI(v) case OpRISCV64AND: return rewriteValueRISCV64_OpRISCV64AND(v) + case OpRISCV64FMADDD: + return rewriteValueRISCV64_OpRISCV64FMADDD(v) + case OpRISCV64FMSUBD: + return rewriteValueRISCV64_OpRISCV64FMSUBD(v) + case OpRISCV64FNMADDD: + return rewriteValueRISCV64_OpRISCV64FNMADDD(v) + case OpRISCV64FNMSUBD: + return rewriteValueRISCV64_OpRISCV64FNMSUBD(v) case OpRISCV64MOVBUload: return rewriteValueRISCV64_OpRISCV64MOVBUload(v) case OpRISCV64MOVBUreg: @@ -2829,6 +2840,186 @@ func rewriteValueRISCV64_OpRISCV64AND(v *Value) bool { } return false } +func rewriteValueRISCV64_OpRISCV64FMADDD(v *Value) bool { + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] + // match: (FMADDD neg:(FNEGD x) y z) + // cond: neg.Uses == 1 + // result: (FNMADDD x y z) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + neg := v_0 + if neg.Op != OpRISCV64FNEGD { + continue + } + x := neg.Args[0] + y := v_1 + z := v_2 + if !(neg.Uses == 1) { + continue + } + v.reset(OpRISCV64FNMADDD) + v.AddArg3(x, y, z) + return true + } + break + } + // match: (FMADDD x y neg:(FNEGD z)) + // cond: neg.Uses == 1 + // result: (FMSUBD x y z) + for { + x := v_0 + y := v_1 + neg := v_2 + if neg.Op != OpRISCV64FNEGD { + break + } + z := neg.Args[0] + if !(neg.Uses == 1) { + break + } + v.reset(OpRISCV64FMSUBD) + v.AddArg3(x, y, z) + return true + } + return false +} +func rewriteValueRISCV64_OpRISCV64FMSUBD(v *Value) bool { + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] + // match: (FMSUBD neg:(FNEGD x) y z) + // cond: neg.Uses == 1 + // result: (FNMSUBD x y z) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + neg := v_0 + if neg.Op != OpRISCV64FNEGD { + continue + } + x := neg.Args[0] + y := v_1 + z := v_2 + if !(neg.Uses == 1) { + continue + } + v.reset(OpRISCV64FNMSUBD) + v.AddArg3(x, y, z) + return true + } + break + } + // match: (FMSUBD x y neg:(FNEGD z)) + // cond: neg.Uses == 1 + // result: (FMADDD x y z) + for { + x := v_0 + y := v_1 + neg := v_2 + if neg.Op != OpRISCV64FNEGD { + break + } + z := neg.Args[0] + if !(neg.Uses == 1) { + break + } + v.reset(OpRISCV64FMADDD) + v.AddArg3(x, y, z) + return true + } + return false +} +func rewriteValueRISCV64_OpRISCV64FNMADDD(v *Value) bool { + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] + // match: (FNMADDD neg:(FNEGD x) y z) + // cond: neg.Uses == 1 + // result: (FMADDD x y z) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + neg := v_0 + if neg.Op != OpRISCV64FNEGD { + continue + } + x := neg.Args[0] + y := v_1 + z := v_2 + if !(neg.Uses == 1) { + continue + } + v.reset(OpRISCV64FMADDD) + v.AddArg3(x, y, z) + return true + } + break + } + // match: (FNMADDD x y neg:(FNEGD z)) + // cond: neg.Uses == 1 + // result: (FNMSUBD x y z) + for { + x := v_0 + y := v_1 + neg := v_2 + if neg.Op != OpRISCV64FNEGD { + break + } + z := neg.Args[0] + if !(neg.Uses == 1) { + break + } + v.reset(OpRISCV64FNMSUBD) + v.AddArg3(x, y, z) + return true + } + return false +} +func rewriteValueRISCV64_OpRISCV64FNMSUBD(v *Value) bool { + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] + // match: (FNMSUBD neg:(FNEGD x) y z) + // cond: neg.Uses == 1 + // result: (FMSUBD x y z) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + neg := v_0 + if neg.Op != OpRISCV64FNEGD { + continue + } + x := neg.Args[0] + y := v_1 + z := v_2 + if !(neg.Uses == 1) { + continue + } + v.reset(OpRISCV64FMSUBD) + v.AddArg3(x, y, z) + return true + } + break + } + // match: (FNMSUBD x y neg:(FNEGD z)) + // cond: neg.Uses == 1 + // result: (FNMADDD x y z) + for { + x := v_0 + y := v_1 + neg := v_2 + if neg.Op != OpRISCV64FNEGD { + break + } + z := neg.Args[0] + if !(neg.Uses == 1) { + break + } + v.reset(OpRISCV64FNMADDD) + v.AddArg3(x, y, z) + return true + } + return false +} func rewriteValueRISCV64_OpRISCV64MOVBUload(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index a64901305f..176e6438dc 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -4168,7 +4168,7 @@ func InitTables() { func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return s.newValue3(ssa.OpFMA, types.Types[types.TFLOAT64], args[0], args[1], args[2]) }, - sys.ARM64, sys.PPC64, sys.S390X) + sys.ARM64, sys.PPC64, sys.RISCV64, sys.S390X) addF("math", "FMA", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { if !s.config.UseFMA { diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index f89e13d81c..73f62c007d 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -1214,60 +1214,77 @@ func validateRIII(ctxt *obj.Link, ins *instruction) { wantIntReg(ctxt, ins.as, "rd", ins.rd) wantIntReg(ctxt, ins.as, "rs1", ins.rs1) wantIntReg(ctxt, ins.as, "rs2", ins.rs2) + wantNoneReg(ctxt, ins.as, "rs3", ins.rs3) } func validateRFFF(ctxt *obj.Link, ins *instruction) { wantFloatReg(ctxt, ins.as, "rd", ins.rd) wantFloatReg(ctxt, ins.as, "rs1", ins.rs1) wantFloatReg(ctxt, ins.as, "rs2", ins.rs2) + wantNoneReg(ctxt, ins.as, "rs3", ins.rs3) +} + +func validateRFFFF(ctxt *obj.Link, ins *instruction) { + wantFloatReg(ctxt, ins.as, "rd", ins.rd) + wantFloatReg(ctxt, ins.as, "rs1", ins.rs1) + wantFloatReg(ctxt, ins.as, "rs2", ins.rs2) + wantFloatReg(ctxt, ins.as, "rs3", ins.rs3) } func validateRFFI(ctxt *obj.Link, ins *instruction) { wantIntReg(ctxt, ins.as, "rd", ins.rd) wantFloatReg(ctxt, ins.as, "rs1", ins.rs1) wantFloatReg(ctxt, ins.as, "rs2", ins.rs2) + wantNoneReg(ctxt, ins.as, "rs3", ins.rs3) } func validateRFI(ctxt *obj.Link, ins *instruction) { wantIntReg(ctxt, ins.as, "rd", ins.rd) wantNoneReg(ctxt, ins.as, "rs1", ins.rs1) wantFloatReg(ctxt, ins.as, "rs2", ins.rs2) + wantNoneReg(ctxt, ins.as, "rs3", ins.rs3) } func validateRIF(ctxt *obj.Link, ins *instruction) { wantFloatReg(ctxt, ins.as, "rd", ins.rd) wantNoneReg(ctxt, ins.as, "rs1", ins.rs1) wantIntReg(ctxt, ins.as, "rs2", ins.rs2) + wantNoneReg(ctxt, ins.as, "rs3", ins.rs3) } func validateRFF(ctxt *obj.Link, ins *instruction) { wantFloatReg(ctxt, ins.as, "rd", ins.rd) wantNoneReg(ctxt, ins.as, "rs1", ins.rs1) wantFloatReg(ctxt, ins.as, "rs2", ins.rs2) + wantNoneReg(ctxt, ins.as, "rs3", ins.rs3) } func validateII(ctxt *obj.Link, ins *instruction) { wantImmI(ctxt, ins.as, ins.imm, 12) wantIntReg(ctxt, ins.as, "rd", ins.rd) wantIntReg(ctxt, ins.as, "rs1", ins.rs1) + wantNoneReg(ctxt, ins.as, "rs3", ins.rs3) } func validateIF(ctxt *obj.Link, ins *instruction) { wantImmI(ctxt, ins.as, ins.imm, 12) wantFloatReg(ctxt, ins.as, "rd", ins.rd) wantIntReg(ctxt, ins.as, "rs1", ins.rs1) + wantNoneReg(ctxt, ins.as, "rs3", ins.rs3) } func validateSI(ctxt *obj.Link, ins *instruction) { wantImmI(ctxt, ins.as, ins.imm, 12) wantIntReg(ctxt, ins.as, "rd", ins.rd) wantIntReg(ctxt, ins.as, "rs1", ins.rs1) + wantNoneReg(ctxt, ins.as, "rs3", ins.rs3) } func validateSF(ctxt *obj.Link, ins *instruction) { wantImmI(ctxt, ins.as, ins.imm, 12) wantIntReg(ctxt, ins.as, "rd", ins.rd) wantFloatReg(ctxt, ins.as, "rs1", ins.rs1) + wantNoneReg(ctxt, ins.as, "rs3", ins.rs3) } func validateB(ctxt *obj.Link, ins *instruction) { @@ -1278,6 +1295,7 @@ func validateB(ctxt *obj.Link, ins *instruction) { wantNoneReg(ctxt, ins.as, "rd", ins.rd) wantIntReg(ctxt, ins.as, "rs1", ins.rs1) wantIntReg(ctxt, ins.as, "rs2", ins.rs2) + wantNoneReg(ctxt, ins.as, "rs3", ins.rs3) } func validateU(ctxt *obj.Link, ins *instruction) { @@ -1285,6 +1303,7 @@ func validateU(ctxt *obj.Link, ins *instruction) { wantIntReg(ctxt, ins.as, "rd", ins.rd) wantNoneReg(ctxt, ins.as, "rs1", ins.rs1) wantNoneReg(ctxt, ins.as, "rs2", ins.rs2) + wantNoneReg(ctxt, ins.as, "rs3", ins.rs3) } func validateJ(ctxt *obj.Link, ins *instruction) { @@ -1295,6 +1314,7 @@ func validateJ(ctxt *obj.Link, ins *instruction) { wantIntReg(ctxt, ins.as, "rd", ins.rd) wantNoneReg(ctxt, ins.as, "rs1", ins.rs1) wantNoneReg(ctxt, ins.as, "rs2", ins.rs2) + wantNoneReg(ctxt, ins.as, "rs3", ins.rs3) } func validateRaw(ctxt *obj.Link, ins *instruction) { @@ -1317,6 +1337,22 @@ func encodeR(as obj.As, rs1, rs2, rd, funct3, funct7 uint32) uint32 { return funct7<<25 | enc.funct7<<25 | enc.rs2<<20 | rs2<<20 | rs1<<15 | enc.funct3<<12 | funct3<<12 | rd<<7 | enc.opcode } +// encodeR4 encodes an R4-type RISC-V instruction. +func encodeR4(as obj.As, rs1, rs2, rs3, rd, funct3, funct2 uint32) uint32 { + enc := encode(as) + if enc == nil { + panic("encodeR4: could not encode instruction") + } + if enc.rs2 != 0 { + panic("encodeR4: instruction uses rs2") + } + funct2 |= enc.funct7 + if funct2&^3 != 0 { + panic("encodeR4: funct2 requires more than 2 bits") + } + return rs3<<27 | funct2<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | funct3<<12 | rd<<7 | enc.opcode +} + func encodeRIII(ins *instruction) uint32 { return encodeR(ins.as, regI(ins.rs1), regI(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7) } @@ -1325,6 +1361,10 @@ func encodeRFFF(ins *instruction) uint32 { return encodeR(ins.as, regF(ins.rs1), regF(ins.rs2), regF(ins.rd), ins.funct3, ins.funct7) } +func encodeRFFFF(ins *instruction) uint32 { + return encodeR4(ins.as, regF(ins.rs1), regF(ins.rs2), regF(ins.rs3), regF(ins.rd), ins.funct3, ins.funct7) +} + func encodeRFFI(ins *instruction) uint32 { return encodeR(ins.as, regF(ins.rs1), regF(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7) } @@ -1462,12 +1502,13 @@ var ( // integer register inputs and an integer register output; sFEncoding // indicates an S-type instruction with rs2 being a float register. - rIIIEncoding = encoding{encode: encodeRIII, validate: validateRIII, length: 4} - rFFFEncoding = encoding{encode: encodeRFFF, validate: validateRFFF, length: 4} - rFFIEncoding = encoding{encode: encodeRFFI, validate: validateRFFI, length: 4} - rFIEncoding = encoding{encode: encodeRFI, validate: validateRFI, length: 4} - rIFEncoding = encoding{encode: encodeRIF, validate: validateRIF, length: 4} - rFFEncoding = encoding{encode: encodeRFF, validate: validateRFF, length: 4} + rIIIEncoding = encoding{encode: encodeRIII, validate: validateRIII, length: 4} + rFFFEncoding = encoding{encode: encodeRFFF, validate: validateRFFF, length: 4} + rFFFFEncoding = encoding{encode: encodeRFFFF, validate: validateRFFFF, length: 4} + rFFIEncoding = encoding{encode: encodeRFFI, validate: validateRFFI, length: 4} + rFIEncoding = encoding{encode: encodeRFI, validate: validateRFI, length: 4} + rIFEncoding = encoding{encode: encodeRIF, validate: validateRIF, length: 4} + rFFEncoding = encoding{encode: encodeRFF, validate: validateRFF, length: 4} iIEncoding = encoding{encode: encodeII, validate: validateII, length: 4} iFEncoding = encoding{encode: encodeIF, validate: validateIF, length: 4} @@ -1609,13 +1650,17 @@ var encodings = [ALAST & obj.AMask]encoding{ AFSW & obj.AMask: sFEncoding, // 11.6: Single-Precision Floating-Point Computational Instructions - AFADDS & obj.AMask: rFFFEncoding, - AFSUBS & obj.AMask: rFFFEncoding, - AFMULS & obj.AMask: rFFFEncoding, - AFDIVS & obj.AMask: rFFFEncoding, - AFMINS & obj.AMask: rFFFEncoding, - AFMAXS & obj.AMask: rFFFEncoding, - AFSQRTS & obj.AMask: rFFFEncoding, + AFADDS & obj.AMask: rFFFEncoding, + AFSUBS & obj.AMask: rFFFEncoding, + AFMULS & obj.AMask: rFFFEncoding, + AFDIVS & obj.AMask: rFFFEncoding, + AFMINS & obj.AMask: rFFFEncoding, + AFMAXS & obj.AMask: rFFFEncoding, + AFSQRTS & obj.AMask: rFFFEncoding, + AFMADDS & obj.AMask: rFFFFEncoding, + AFMSUBS & obj.AMask: rFFFFEncoding, + AFNMSUBS & obj.AMask: rFFFFEncoding, + AFNMADDS & obj.AMask: rFFFFEncoding, // 11.7: Single-Precision Floating-Point Conversion and Move Instructions AFCVTWS & obj.AMask: rFIEncoding, @@ -1647,13 +1692,17 @@ var encodings = [ALAST & obj.AMask]encoding{ AFSD & obj.AMask: sFEncoding, // 12.4: Double-Precision Floating-Point Computational Instructions - AFADDD & obj.AMask: rFFFEncoding, - AFSUBD & obj.AMask: rFFFEncoding, - AFMULD & obj.AMask: rFFFEncoding, - AFDIVD & obj.AMask: rFFFEncoding, - AFMIND & obj.AMask: rFFFEncoding, - AFMAXD & obj.AMask: rFFFEncoding, - AFSQRTD & obj.AMask: rFFFEncoding, + AFADDD & obj.AMask: rFFFEncoding, + AFSUBD & obj.AMask: rFFFEncoding, + AFMULD & obj.AMask: rFFFEncoding, + AFDIVD & obj.AMask: rFFFEncoding, + AFMIND & obj.AMask: rFFFEncoding, + AFMAXD & obj.AMask: rFFFEncoding, + AFSQRTD & obj.AMask: rFFFEncoding, + AFMADDD & obj.AMask: rFFFFEncoding, + AFMSUBD & obj.AMask: rFFFFEncoding, + AFNMSUBD & obj.AMask: rFFFFEncoding, + AFNMADDD & obj.AMask: rFFFFEncoding, // 12.5: Double-Precision Floating-Point Conversion and Move Instructions AFCVTWD & obj.AMask: rFIEncoding, @@ -1719,9 +1768,10 @@ type instruction struct { rd uint32 // Destination register rs1 uint32 // Source register 1 rs2 uint32 // Source register 2 + rs3 uint32 // Source register 3 imm int64 // Immediate funct3 uint32 // Function 3 - funct7 uint32 // Function 7 + funct7 uint32 // Function 7 (or Function 2) } func (ins *instruction) encode() (uint32, error) { @@ -1762,6 +1812,12 @@ func instructionsForProg(p *obj.Prog) []*instruction { imm: p.From.Offset, } + if len(p.RestArgs) == 1 { + ins.rs3 = uint32(p.RestArgs[0].Reg) + } else if len(p.RestArgs) > 0 { + p.Ctxt.Diag("too many source registers") + } + inss := []*instruction{ins} switch ins.as { case AJAL, AJALR: @@ -1899,6 +1955,12 @@ func instructionsForProg(p *obj.Prog) []*instruction { ins.rs1 = uint32(p.From.Reg) ins.rs2 = REG_F0 + case AFMADDS, AFMSUBS, AFNMADDS, AFNMSUBS, + AFMADDD, AFMSUBD, AFNMADDD, AFNMSUBD: + // Swap the first two operands so that the operands are in the same + // order as they are in the specification: RS1, RS2, RS3, RD. + ins.rs1, ins.rs2 = ins.rs2, ins.rs1 + case ANEG, ANEGW: // NEG rs, rd -> SUB rs, X0, rd ins.as = ASUB diff --git a/test/codegen/math.go b/test/codegen/math.go index 04cb4e577d..cd573db7b3 100644 --- a/test/codegen/math.go +++ b/test/codegen/math.go @@ -125,9 +125,25 @@ func fma(x, y, z float64) float64 { // s390x:"FMADD" // ppc64:"FMADD" // ppc64le:"FMADD" + // riscv64:"FMADDD" return math.FMA(x, y, z) } +func fms(x, y, z float64) float64 { + // riscv64:"FMSUBD" + return math.FMA(x, y, -z) +} + +func fnma(x, y, z float64) float64 { + // riscv64:"FNMADDD" + return math.FMA(-x, y, z) +} + +func fnms(x, y, z float64) float64 { + // riscv64:"FNMSUBD" + return math.FMA(x, -y, -z) +} + func fromFloat64(f64 float64) uint64 { // amd64:"MOVQ\tX.*, [^X].*" // arm64:"FMOVD\tF.*, R.*" -- GitLab From 5e0f8edbdc071db5cc2d50878df3089477df2b27 Mon Sep 17 00:00:00 2001 From: Leonard Wang Date: Tue, 6 Jul 2021 23:39:29 +0800 Subject: [PATCH 0954/2500] cmd/compile: remove useless fcount Change-Id: Ibc23b43dc9a7fabb27d7991977b283459f3deae3 Reviewed-on: https://go-review.googlesource.com/c/go/+/333009 Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Keith Randall Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/noder/noder.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index 61a7f8aad4..2f18a2f231 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -154,7 +154,6 @@ func LoadPackage(filenames []string) { // Phase 3: Type check function bodies. // Don't use range--typecheck can add closures to Target.Decls. base.Timer.Start("fe", "typecheck", "func") - var fcount int64 for i := 0; i < len(typecheck.Target.Decls); i++ { if fn, ok := typecheck.Target.Decls[i].(*ir.Func); ok { if base.Flag.W > 1 { @@ -166,7 +165,6 @@ func LoadPackage(filenames []string) { s := fmt.Sprintf("\nafter typecheck %v", fn) ir.Dump(s, fn) } - fcount++ } } -- GitLab From 50f38d040532edde038c992ddbe978658556c51f Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 1 Sep 2021 11:53:36 -0700 Subject: [PATCH 0955/2500] cmd/compile: emit unified IR wrappers after inlining This CL delays unified IR's wrapper generation to after inlining. Change-Id: Idfe496663489d6b797a647eb17200c6322d0334a Reviewed-on: https://go-review.googlesource.com/c/go/+/347029 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/gc/main.go | 1 + src/cmd/compile/internal/noder/reader.go | 83 +++++++++++++---------- src/cmd/compile/internal/noder/unified.go | 5 -- 3 files changed, 47 insertions(+), 42 deletions(-) diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 0dbe47f653..8ddef6721f 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -245,6 +245,7 @@ func Main(archInit func(*ssagen.ArchInfo)) { if base.Flag.LowerL != 0 { inline.InlinePackage() } + noder.MakeWrappers(typecheck.Target) // must happen after inlining // Devirtualize. for _, n := range typecheck.Target.Decls { diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index e874240bbc..17ccb25e1d 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -149,7 +149,7 @@ type readerDict struct { funcsObj []ir.Node } -func (r *reader) setType(n ir.Node, typ *types.Type) { +func setType(n ir.Node, typ *types.Type) { n.SetType(typ) n.SetTypecheck(1) @@ -159,7 +159,7 @@ func (r *reader) setType(n ir.Node, typ *types.Type) { } } -func (r *reader) setValue(name *ir.Name, val constant.Value) { +func setValue(name *ir.Name, val constant.Value) { name.SetVal(val) name.Defn = nil } @@ -602,15 +602,15 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node case objAlias: name := do(ir.OTYPE, false) - r.setType(name, r.typ()) + setType(name, r.typ()) name.SetAlias(true) return name case objConst: name := do(ir.OLITERAL, false) typ, val := r.value() - r.setType(name, typ) - r.setValue(name, val) + setType(name, typ) + setValue(name, val) return name case objFunc: @@ -618,7 +618,7 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node sym = renameinit() } name := do(ir.ONAME, true) - r.setType(name, r.signature(sym.Pkg, nil)) + setType(name, r.signature(sym.Pkg, nil)) name.Func = ir.NewFunc(r.pos()) name.Func.Nname = name @@ -629,7 +629,7 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node case objType: name := do(ir.OTYPE, true) typ := types.NewNamed(name) - r.setType(name, typ) + setType(name, typ) // Important: We need to do this before SetUnderlying. r.ext.typeExt(name) @@ -654,7 +654,7 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node case objVar: name := do(ir.ONAME, false) - r.setType(name, r.typ()) + setType(name, r.typ()) r.ext.varExt(name) return name } @@ -754,7 +754,7 @@ func (r *reader) method() *types.Field { fnsym := sym fnsym = ir.MethodSym(recv.Type, fnsym) name := ir.NewNameAt(pos, fnsym) - r.setType(name, typ) + setType(name, typ) name.Func = ir.NewFunc(r.pos()) name.Func.Nname = name @@ -996,7 +996,7 @@ func (r *reader) funcarg(param *types.Field, sym *types.Sym, ctxt ir.Class) { } name := ir.NewNameAt(r.updatePos(param.Pos), sym) - r.setType(name, param.Type) + setType(name, param.Type) r.addLocal(name, ctxt) if r.inlCall == nil { @@ -1276,7 +1276,7 @@ func (r *reader) stmt1(tag codeStmt, out *ir.Nodes) ir.Node { name := ir.NewDeclNameAt(src.NoXPos, ir.OTYPE, ir.BlankNode.Sym()) name.SetAlias(true) - r.setType(name, types.Types[types.TINT]) + setType(name, types.Types[types.TINT]) n := ir.NewDecl(src.NoXPos, ir.ODCLTYPE, name) n.SetTypecheck(1) @@ -1297,7 +1297,7 @@ func (r *reader) assignList() ([]*ir.Name, []ir.Node) { name := ir.NewNameAt(pos, sym) lhs[i] = name names = append(names, name) - r.setType(name, typ) + setType(name, typ) r.addLocal(name, ir.PAUTO) continue } @@ -1438,7 +1438,7 @@ func (r *reader) switchStmt(label *types.Sym) ir.Node { typ := r.typ() name := ir.NewNameAt(pos, tswitch.Tag.Sym()) - r.setType(name, typ) + setType(name, typ) r.addLocal(name, ir.PAUTO) clause.Var = name name.Defn = tswitch @@ -1701,12 +1701,12 @@ func (r *reader) funcLit() ir.Node { clo := fn.OClosure ir.NameClosure(clo, r.curfn) - r.setType(fn.Nname, xtype2) + setType(fn.Nname, xtype2) if quirksMode() { fn.Nname.Ntype = ir.TypeNodeAt(typPos, xtype2) } typecheck.Func(fn) - r.setType(clo, fn.Type()) + setType(clo, fn.Type()) fn.ClosureVars = make([]*ir.Name, 0, r.len()) for len(fn.ClosureVars) < cap(fn.ClosureVars) { @@ -1910,7 +1910,7 @@ func InlineCall(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExp tmpfn.Closgen = callerfn.Closgen defer func() { callerfn.Closgen = tmpfn.Closgen }() - r.setType(tmpfn.Nname, fn.Type()) + setType(tmpfn.Nname, fn.Type()) r.curfn = tmpfn r.inlCaller = callerfn @@ -2098,7 +2098,7 @@ func expandInline(fn *ir.Func, pri pkgReaderIndex) { { r := pri.asReader(relocBody, syncFuncBody) - r.setType(tmpfn.Nname, fn.Type()) + setType(tmpfn.Nname, fn.Type()) // Don't change parameter's Sym/Nname fields. r.funarghack = true @@ -2194,34 +2194,39 @@ func (r *reader) importedDef() bool { return r.p != localPkgReader && !r.hasTypeParams() } -func (r *reader) wrapTypes(target *ir.Package) { +func MakeWrappers(target *ir.Package) { + // Only unified IR in non-quirks mode emits its own wrappers. + if base.Debug.Unified == 0 || quirksMode() { + return + } + // always generate a wrapper for error.Error (#29304) - r.needWrapper(types.ErrorType) + needWrapperTypes = append(needWrapperTypes, types.ErrorType) seen := make(map[string]*types.Type) for _, typ := range haveWrapperTypes { - r.wrapType(typ, target, seen, false) + wrapType(typ, target, seen, false) } haveWrapperTypes = nil for _, typ := range needWrapperTypes { - r.wrapType(typ, target, seen, true) + wrapType(typ, target, seen, true) } needWrapperTypes = nil for _, wrapper := range haveMethodValueWrappers { - r.methodValueWrapper(wrapper.rcvr, wrapper.method, target, false) + wrapMethodValue(wrapper.rcvr, wrapper.method, target, false) } haveMethodValueWrappers = nil for _, wrapper := range needMethodValueWrappers { - r.methodValueWrapper(wrapper.rcvr, wrapper.method, target, true) + wrapMethodValue(wrapper.rcvr, wrapper.method, target, true) } needMethodValueWrappers = nil } -func (r *reader) wrapType(typ *types.Type, target *ir.Package, seen map[string]*types.Type, needed bool) { +func wrapType(typ *types.Type, target *ir.Package, seen map[string]*types.Type, needed bool) { key := typ.LinkString() if prev := seen[key]; prev != nil { if !types.Identical(typ, prev) { @@ -2244,22 +2249,22 @@ func (r *reader) wrapType(typ *types.Type, target *ir.Package, seen map[string]* base.FatalfAt(meth.Pos, "invalid method: %v", meth) } - r.methodWrapper(0, typ, meth, target) + methodWrapper(0, typ, meth, target) // For non-interface types, we also want *T wrappers. if !typ.IsInterface() { - r.methodWrapper(1, typ, meth, target) + methodWrapper(1, typ, meth, target) // For not-in-heap types, *T is a scalar, not pointer shaped, // so the interface wrappers use **T. if typ.NotInHeap() { - r.methodWrapper(2, typ, meth, target) + methodWrapper(2, typ, meth, target) } } } } -func (r *reader) methodWrapper(derefs int, tbase *types.Type, method *types.Field, target *ir.Package) { +func methodWrapper(derefs int, tbase *types.Type, method *types.Field, target *ir.Package) { wrapper := tbase for i := 0; i < derefs; i++ { wrapper = types.NewPtr(wrapper) @@ -2279,7 +2284,7 @@ func (r *reader) methodWrapper(derefs int, tbase *types.Type, method *types.Fiel // TODO(mdempsky): Use method.Pos instead? pos := base.AutogeneratedPos - fn := r.newWrapperFunc(pos, sym, wrapper, method) + fn := newWrapperFunc(pos, sym, wrapper, method) var recv ir.Node = fn.Nname.Type().Recv().Nname.(*ir.Name) @@ -2299,10 +2304,10 @@ func (r *reader) methodWrapper(derefs int, tbase *types.Type, method *types.Fiel addTailCall(pos, fn, recv, method) - r.finishWrapperFunc(fn, target) + finishWrapperFunc(fn, target) } -func (r *reader) methodValueWrapper(recvType *types.Type, method *types.Field, target *ir.Package, needed bool) { +func wrapMethodValue(recvType *types.Type, method *types.Field, target *ir.Package, needed bool) { sym := ir.MethodSymSuffix(recvType, method.Sym, "-fm") if sym.Uniq() { return @@ -2312,7 +2317,7 @@ func (r *reader) methodValueWrapper(recvType *types.Type, method *types.Field, t // TODO(mdempsky): Use method.Pos instead? pos := base.AutogeneratedPos - fn := r.newWrapperFunc(pos, sym, nil, method) + fn := newWrapperFunc(pos, sym, nil, method) sym.Def = fn.Nname // Declare and initialize variable holding receiver. @@ -2325,10 +2330,10 @@ func (r *reader) methodValueWrapper(recvType *types.Type, method *types.Field, t addTailCall(pos, fn, recv, method) - r.finishWrapperFunc(fn, target) + finishWrapperFunc(fn, target) } -func (r *reader) newWrapperFunc(pos src.XPos, sym *types.Sym, wrapper *types.Type, method *types.Field) *ir.Func { +func newWrapperFunc(pos src.XPos, sym *types.Sym, wrapper *types.Type, method *types.Field) *ir.Func { fn := ir.NewFunc(pos) fn.SetDupok(true) // TODO(mdempsky): Leave unset for local, non-generic wrappers? @@ -2339,14 +2344,14 @@ func (r *reader) newWrapperFunc(pos src.XPos, sym *types.Sym, wrapper *types.Typ fn.Nname = name sig := newWrapperType(wrapper, method) - r.setType(name, sig) + setType(name, sig) // TODO(mdempsky): De-duplicate with similar logic in funcargs. defParams := func(class ir.Class, params *types.Type) { for _, param := range params.FieldSlice() { name := ir.NewNameAt(param.Pos, param.Sym) name.Class = class - r.setType(name, param.Type) + setType(name, param.Type) name.Curfn = fn fn.Dcl = append(fn.Dcl, name) @@ -2362,13 +2367,17 @@ func (r *reader) newWrapperFunc(pos src.XPos, sym *types.Sym, wrapper *types.Typ return fn } -func (r *reader) finishWrapperFunc(fn *ir.Func, target *ir.Package) { +func finishWrapperFunc(fn *ir.Func, target *ir.Package) { typecheck.Func(fn) ir.WithFunc(fn, func() { typecheck.Stmts(fn.Body) }) + // We generate wrappers after the global inlining pass, + // so we're responsible for applying inlining ourselves here. + inline.InlineCalls(fn) + target.Decls = append(target.Decls, fn) } diff --git a/src/cmd/compile/internal/noder/unified.go b/src/cmd/compile/internal/noder/unified.go index 9f80ca000d..bf63608bf1 100644 --- a/src/cmd/compile/internal/noder/unified.go +++ b/src/cmd/compile/internal/noder/unified.go @@ -138,11 +138,6 @@ func unified(noders []*noder) { } todoBodies = nil - if !quirksMode() { - // TODO(mdempsky): Investigate generating wrappers in quirks mode too. - r.wrapTypes(target) - } - // Check that nothing snuck past typechecking. for _, n := range target.Decls { if n.Typecheck() == 0 { -- GitLab From 88859f3cd80e03f695cba5462d959949ff9a5583 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 1 Sep 2021 12:42:35 -0700 Subject: [PATCH 0956/2500] cmd/compile: optimize unified IR handling of imported functions This CL skips reading of imported function bodies except from the local package or for inlining. Previously, we wasted a bunch of CPU and memory by reading in normal function bodies for all imported functions and methods. Change-Id: I0b3df3f4a3e2819117dac11a1f9e4526288c14d8 Reviewed-on: https://go-review.googlesource.com/c/go/+/347030 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/noder/reader.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 17ccb25e1d..204d25bce8 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -920,6 +920,12 @@ func (r *reader) addBody(fn *ir.Func) { pri := pkgReaderIndex{r.p, r.reloc(relocBody), r.dict} bodyReader[fn] = pri + if fn.Nname.Defn == nil { + // Don't read in function body for imported functions. + // See comment in funcExt. + return + } + if r.curfn == nil { todoBodies = append(todoBodies, fn) return -- GitLab From f0668e7c8cc2f26e16afa31dd43be774b1db65a5 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 24 Aug 2021 15:58:03 -0700 Subject: [PATCH 0957/2500] [dev.fuzz] cmd/go: stream output when fuzzing Previously, 'go test' streamed output when there were no package arguments or when benchmarking. This CL expands that to include fuzzing to ensure that coordinator progress messages are printed. This change tweaks tests and output a little bit: the output is slightly different depending on whether it was streamed or buffered in 'go test'. Fixes golang/go#47603 Change-Id: I387470062cf0620f5c7f214b6f54039c921912c4 Reviewed-on: https://go-review.googlesource.com/c/go/+/344831 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod Reviewed-by: Katie Hockman --- src/cmd/go/internal/test/test.go | 4 +- .../go/testdata/script/test_fuzz_match.txt | 14 ++--- src/testing/fuzz.go | 56 +++++++++---------- src/testing/testing.go | 8 ++- 4 files changed, 42 insertions(+), 40 deletions(-) diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 75345a8223..5bf4d79b5c 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -1206,10 +1206,10 @@ func (c *runCache) builderRunTest(b *work.Builder, ctx context.Context, a *work. } var buf bytes.Buffer - if len(pkgArgs) == 0 || (testBench != "") { + if len(pkgArgs) == 0 || testBench != "" || testFuzz != "" { // Stream test output (no buffering) when no package has // been given on the command line (implicit current directory) - // or when benchmarking. + // or when benchmarking or fuzzing. // No change to stdout. } else { // If we're only running a single package under test or if parallelism is diff --git a/src/cmd/go/testdata/script/test_fuzz_match.txt b/src/cmd/go/testdata/script/test_fuzz_match.txt index ab8bebf52c..9d4c5125d3 100644 --- a/src/cmd/go/testdata/script/test_fuzz_match.txt +++ b/src/cmd/go/testdata/script/test_fuzz_match.txt @@ -13,9 +13,9 @@ stdout '^ok' # Matches none for fuzzing but will run the fuzz target as a test. go test -fuzz ThisWillNotMatch -fuzztime 1x standalone_fuzz_test.go -! stdout '^ok.*\[no tests to run\]' +! stdout '^ok.*no tests to run' stdout '^ok' -stdout '\[no targets to fuzz\]' +stdout 'no targets to fuzz' [short] stop @@ -26,16 +26,16 @@ stdout '^ok' # Matches no fuzz targets. go test -run ThisWillNotMatch standalone_fuzz_test.go -stdout '^ok.*\[no tests to run\]' -! stdout '\[no targets to fuzz\]' +stdout '^ok.*no tests to run' +! stdout 'no targets to fuzz' # Matches more than one fuzz target for fuzzing. go test -fuzz Fuzz -fuzztime 1x multiple_fuzz_test.go # The tests should run, but not be fuzzed -! stdout '\[no tests to run\]' -! stdout '\[no targets to fuzz\]' +! stdout 'no tests to run' +! stdout 'no targets to fuzz' stdout ok -stdout '\[will not fuzz, -fuzz matches more than one target\]' +stdout 'will not fuzz, -fuzz matches more than one target' -- standalone_fuzz_test.go -- package standalone_fuzz diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 6f5cdcc389..4892d3f3e9 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -561,12 +561,12 @@ func runFuzzTargets(deps testDeps, fuzzTargets []InternalFuzzTarget, deadline ti // // If fuzzing is disabled (-test.fuzz is not set), runFuzzing // returns immediately. -func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran, ok bool) { +func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran bool, matched int, ok bool) { // TODO(katiehockman,jayconrod): Should we do something special to make sure // we don't print f.Log statements again with runFuzzing, since we already // would have printed them when we ran runFuzzTargets (ie. seed corpus run)? if len(fuzzTargets) == 0 || *matchFuzz == "" { - return false, true + return false, 0, true } m := newMatcher(deps.MatchString, *matchFuzz, "-test.fuzz") tctx := newTestContext(1, m) @@ -588,41 +588,39 @@ func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran, ok bool) root.chatty = newChattyPrinter(root.w) } var target *InternalFuzzTarget - var f *F + var targetName string for i := range fuzzTargets { - ft := &fuzzTargets[i] - testName, matched, _ := tctx.match.fullName(nil, ft.Name) - if !matched { + name, ok, _ := tctx.match.fullName(nil, fuzzTargets[i].Name) + if !ok { continue } - if target != nil { - fmt.Fprintln(os.Stderr, "testing: warning: -fuzz matches more than one target, won't fuzz") - return false, true - } - target = ft - f = &F{ - common: common{ - signal: make(chan bool), - barrier: nil, // T.Parallel has no effect when fuzzing. - name: testName, - parent: &root, - level: root.level + 1, - chatty: root.chatty, - }, - fuzzContext: fctx, - testContext: tctx, - } - f.w = indenter{&f.common} - } - if target == nil { - return false, true - } + matched++ + target = &fuzzTargets[i] + targetName = name + } + if matched != 1 { + return false, matched, true + } + + f := &F{ + common: common{ + signal: make(chan bool), + barrier: nil, // T.Parallel has no effect when fuzzing. + name: targetName, + parent: &root, + level: root.level + 1, + chatty: root.chatty, + }, + fuzzContext: fctx, + testContext: tctx, + } + f.w = indenter{&f.common} if f.chatty != nil { f.chatty.Updatef(f.name, "=== FUZZ %s\n", f.name) } go fRunner(f, target.Fn) <-f.signal - return f.ran, !f.failed + return f.ran, matched, !f.failed } // fRunner wraps a call to a fuzz target and ensures that cleanup functions are diff --git a/src/testing/testing.go b/src/testing/testing.go index 4bf5685a07..7f78a7caf8 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1618,9 +1618,13 @@ func (m *M) Run() (code int) { } } - fuzzingRan, fuzzingOk := runFuzzing(m.deps, m.fuzzTargets) + fuzzingRan, fuzzingMatched, fuzzingOk := runFuzzing(m.deps, m.fuzzTargets) if *matchFuzz != "" && !fuzzingRan { - fmt.Fprintln(os.Stderr, "testing: warning: no targets to fuzz") + if fuzzingMatched == 0 { + fmt.Fprintln(os.Stderr, "testing: warning: no targets to fuzz") + } else { + fmt.Fprintln(os.Stderr, "testing: warning: will not fuzz, -fuzz matches more than one target") + } } if !*isFuzzWorker && !fuzzingOk { fmt.Println("FAIL") -- GitLab From 0bfd6fcea6b7cefe200718dc3b318e1d13ee03ab Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Wed, 1 Sep 2021 12:07:08 -0700 Subject: [PATCH 0958/2500] all: update golang.org/x/net to pull in CL 346890 For #42777. Change-Id: I963db8c666e8bcf0fc4f390b359db6408a0f792b Reviewed-on: https://go-review.googlesource.com/c/go/+/347010 Trust: Damien Neil Run-TryBot: Damien Neil TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/go.mod | 2 +- src/go.sum | 4 +- src/net/http/h2_bundle.go | 183 +++++++++--------- src/vendor/golang.org/x/net/route/address.go | 4 + src/vendor/golang.org/x/net/route/message.go | 2 +- .../golang.org/x/net/route/sys_freebsd.go | 3 - src/vendor/modules.txt | 2 +- 7 files changed, 102 insertions(+), 98 deletions(-) diff --git a/src/go.mod b/src/go.mod index 1fb8cbfcbe..726d490668 100644 --- a/src/go.mod +++ b/src/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e - golang.org/x/net v0.0.0-20210510120150-4163338589ed + golang.org/x/net v0.0.0-20210825183410-e898025ed96a golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 // indirect golang.org/x/text v0.3.7-0.20210503195748-5c7c50ebbd4f // indirect ) diff --git a/src/go.sum b/src/go.sum index b3de6c526c..6e14cbcd7e 100644 --- a/src/go.sum +++ b/src/go.sum @@ -1,7 +1,7 @@ golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e h1:8foAy0aoO5GkqCvAEJ4VC4P3zksTg4X4aJCDpZzmgQI= golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I= -golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210825183410-e898025ed96a h1:bRuuGXV8wwSdGTB+CtJf+FjgO1APK1CoO39T4BN/XBw= +golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 h1:yhBbb4IRs2HS9PPlAg6DMC6mUOKexJBNsLf4Z+6En1Q= golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.7-0.20210503195748-5c7c50ebbd4f h1:yQJrRE0hDxDFmZLlRaw+3vusO4fwNHgHIjUOMO7bHYI= diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go index a948ff3eed..14f4d0e5fc 100644 --- a/src/net/http/h2_bundle.go +++ b/src/net/http/h2_bundle.go @@ -53,6 +53,10 @@ import ( "golang.org/x/net/idna" ) +// The HTTP protocols are defined in terms of ASCII, not Unicode. This file +// contains helper functions which may use Unicode-aware functions which would +// otherwise be unsafe and could introduce vulnerabilities if used improperly. + // asciiEqualFold is strings.EqualFold, ASCII only. It reports whether s and t // are equal, ASCII-case-insensitively. func http2asciiEqualFold(s, t string) bool { @@ -3915,16 +3919,12 @@ func http2ConfigureServer(s *Server, conf *http2Server) error { s.TLSConfig.PreferServerCipherSuites = true - haveNPN := false - for _, p := range s.TLSConfig.NextProtos { - if p == http2NextProtoTLS { - haveNPN = true - break - } - } - if !haveNPN { + if !http2strSliceContains(s.TLSConfig.NextProtos, http2NextProtoTLS) { s.TLSConfig.NextProtos = append(s.TLSConfig.NextProtos, http2NextProtoTLS) } + if !http2strSliceContains(s.TLSConfig.NextProtos, "http/1.1") { + s.TLSConfig.NextProtos = append(s.TLSConfig.NextProtos, "http/1.1") + } if s.TLSNextProto == nil { s.TLSNextProto = map[string]func(*Server, *tls.Conn, Handler){} @@ -4479,7 +4479,7 @@ func (sc *http2serverConn) serve() { }) sc.unackedSettings++ - // Each connection starts with intialWindowSize inflow tokens. + // Each connection starts with initialWindowSize inflow tokens. // If a higher value is configured, we add more tokens. if diff := sc.srv.initialConnRecvWindowSize() - http2initialWindowSize; diff > 0 { sc.sendWindowUpdate(nil, int(diff)) @@ -4519,6 +4519,15 @@ func (sc *http2serverConn) serve() { case res := <-sc.wroteFrameCh: sc.wroteFrame(res) case res := <-sc.readFrameCh: + // Process any written frames before reading new frames from the client since a + // written frame could have triggered a new stream to be started. + if sc.writingFrameAsync { + select { + case wroteRes := <-sc.wroteFrameCh: + sc.wroteFrame(wroteRes) + default: + } + } if !sc.processFrameFromReader(res) { return } @@ -6870,9 +6879,8 @@ type http2ClientConn struct { peerMaxHeaderListSize uint64 initialWindowSize uint32 - hbuf bytes.Buffer // HPACK encoder writes into this - henc *hpack.Encoder - freeBuf [][]byte + hbuf bytes.Buffer // HPACK encoder writes into this + henc *hpack.Encoder wmu sync.Mutex // held while writing; acquire AFTER mu if holding both werr error // first write error that has occurred @@ -6992,8 +7000,13 @@ func (cs *http2clientStream) abortRequestBodyWrite(err error) { } cc := cs.cc cc.mu.Lock() - cs.stopReqBody = err - cc.cond.Broadcast() + if cs.stopReqBody == nil { + cs.stopReqBody = err + if cs.req.Body != nil { + cs.req.Body.Close() + } + cc.cond.Broadcast() + } cc.mu.Unlock() } @@ -7520,46 +7533,6 @@ func (cc *http2ClientConn) closeForLostPing() error { return cc.closeForError(err) } -const http2maxAllocFrameSize = 512 << 10 - -// frameBuffer returns a scratch buffer suitable for writing DATA frames. -// They're capped at the min of the peer's max frame size or 512KB -// (kinda arbitrarily), but definitely capped so we don't allocate 4GB -// bufers. -func (cc *http2ClientConn) frameScratchBuffer() []byte { - cc.mu.Lock() - size := cc.maxFrameSize - if size > http2maxAllocFrameSize { - size = http2maxAllocFrameSize - } - for i, buf := range cc.freeBuf { - if len(buf) >= int(size) { - cc.freeBuf[i] = nil - cc.mu.Unlock() - return buf[:size] - } - } - cc.mu.Unlock() - return make([]byte, size) -} - -func (cc *http2ClientConn) putFrameScratchBuffer(buf []byte) { - cc.mu.Lock() - defer cc.mu.Unlock() - const maxBufs = 4 // arbitrary; 4 concurrent requests per conn? investigate. - if len(cc.freeBuf) < maxBufs { - cc.freeBuf = append(cc.freeBuf, buf) - return - } - for i, old := range cc.freeBuf { - if old == nil { - cc.freeBuf[i] = buf - return - } - } - // forget about it. -} - // errRequestCanceled is a copy of net/http's errRequestCanceled because it's not // exported. At least they'll be DeepEqual for h1-vs-h2 comparisons tests. var http2errRequestCanceled = errors.New("net/http: request canceled") @@ -7758,40 +7731,28 @@ func (cc *http2ClientConn) roundTrip(req *Request) (res *Response, gotErrAfterRe return res, false, nil } + handleError := func(err error) (*Response, bool, error) { + if !hasBody || bodyWritten { + cc.writeStreamReset(cs.ID, http2ErrCodeCancel, nil) + } else { + bodyWriter.cancel() + cs.abortRequestBodyWrite(http2errStopReqBodyWriteAndCancel) + <-bodyWriter.resc + } + cc.forgetStreamID(cs.ID) + return nil, cs.getStartedWrite(), err + } + for { select { case re := <-readLoopResCh: return handleReadLoopResponse(re) case <-respHeaderTimer: - if !hasBody || bodyWritten { - cc.writeStreamReset(cs.ID, http2ErrCodeCancel, nil) - } else { - bodyWriter.cancel() - cs.abortRequestBodyWrite(http2errStopReqBodyWriteAndCancel) - <-bodyWriter.resc - } - cc.forgetStreamID(cs.ID) - return nil, cs.getStartedWrite(), http2errTimeout + return handleError(http2errTimeout) case <-ctx.Done(): - if !hasBody || bodyWritten { - cc.writeStreamReset(cs.ID, http2ErrCodeCancel, nil) - } else { - bodyWriter.cancel() - cs.abortRequestBodyWrite(http2errStopReqBodyWriteAndCancel) - <-bodyWriter.resc - } - cc.forgetStreamID(cs.ID) - return nil, cs.getStartedWrite(), ctx.Err() + return handleError(ctx.Err()) case <-req.Cancel: - if !hasBody || bodyWritten { - cc.writeStreamReset(cs.ID, http2ErrCodeCancel, nil) - } else { - bodyWriter.cancel() - cs.abortRequestBodyWrite(http2errStopReqBodyWriteAndCancel) - <-bodyWriter.resc - } - cc.forgetStreamID(cs.ID) - return nil, cs.getStartedWrite(), http2errRequestCanceled + return handleError(http2errRequestCanceled) case <-cs.peerReset: // processResetStream already removed the // stream from the streams map; no need for @@ -7902,11 +7863,35 @@ var ( http2errReqBodyTooLong = errors.New("http2: request body larger than specified content length") ) +// frameScratchBufferLen returns the length of a buffer to use for +// outgoing request bodies to read/write to/from. +// +// It returns max(1, min(peer's advertised max frame size, +// Request.ContentLength+1, 512KB)). +func (cs *http2clientStream) frameScratchBufferLen(maxFrameSize int) int { + const max = 512 << 10 + n := int64(maxFrameSize) + if n > max { + n = max + } + if cl := http2actualContentLength(cs.req); cl != -1 && cl+1 < n { + // Add an extra byte past the declared content-length to + // give the caller's Request.Body io.Reader a chance to + // give us more bytes than they declared, so we can catch it + // early. + n = cl + 1 + } + if n < 1 { + return 1 + } + return int(n) // doesn't truncate; max is 512K +} + +var http2bufPool sync.Pool // of *[]byte + func (cs *http2clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) (err error) { cc := cs.cc sentEnd := false // whether we sent the final DATA frame w/ END_STREAM - buf := cc.frameScratchBuffer() - defer cc.putFrameScratchBuffer(buf) defer func() { http2traceWroteRequest(cs.trace, err) @@ -7914,7 +7899,13 @@ func (cs *http2clientStream) writeRequestBody(body io.Reader, bodyCloser io.Clos // Request.Body is closed by the Transport, // and in multiple cases: server replies <=299 and >299 // while still writing request body - cerr := bodyCloser.Close() + var cerr error + cc.mu.Lock() + if cs.stopReqBody == nil { + cs.stopReqBody = http2errStopReqBodyWrite + cerr = bodyCloser.Close() + } + cc.mu.Unlock() if err == nil { err = cerr } @@ -7925,9 +7916,24 @@ func (cs *http2clientStream) writeRequestBody(body io.Reader, bodyCloser io.Clos remainLen := http2actualContentLength(req) hasContentLen := remainLen != -1 + cc.mu.Lock() + maxFrameSize := int(cc.maxFrameSize) + cc.mu.Unlock() + + // Scratch buffer for reading into & writing from. + scratchLen := cs.frameScratchBufferLen(maxFrameSize) + var buf []byte + if bp, ok := http2bufPool.Get().(*[]byte); ok && len(*bp) >= scratchLen { + defer http2bufPool.Put(bp) + buf = *bp + } else { + buf = make([]byte, scratchLen) + defer http2bufPool.Put(&buf) + } + var sawEOF bool for !sawEOF { - n, err := body.Read(buf[:len(buf)-1]) + n, err := body.Read(buf[:len(buf)]) if hasContentLen { remainLen -= int64(n) if remainLen == 0 && err == nil { @@ -7938,8 +7944,9 @@ func (cs *http2clientStream) writeRequestBody(body io.Reader, bodyCloser io.Clos // to send the END_STREAM bit early, double-check that we're actually // at EOF. Subsequent reads should return (0, EOF) at this point. // If either value is different, we return an error in one of two ways below. + var scratch [1]byte var n1 int - n1, err = body.Read(buf[n:]) + n1, err = body.Read(scratch[:]) remainLen -= int64(n1) } if remainLen < 0 { @@ -8009,10 +8016,6 @@ func (cs *http2clientStream) writeRequestBody(body io.Reader, bodyCloser io.Clos } } - cc.mu.Lock() - maxFrameSize := int(cc.maxFrameSize) - cc.mu.Unlock() - cc.wmu.Lock() defer cc.wmu.Unlock() diff --git a/src/vendor/golang.org/x/net/route/address.go b/src/vendor/golang.org/x/net/route/address.go index 4f6ad968a2..1898ed0fad 100644 --- a/src/vendor/golang.org/x/net/route/address.go +++ b/src/vendor/golang.org/x/net/route/address.go @@ -422,5 +422,9 @@ func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) ( b = b[l:] } } + // The only remaining bytes in b should be alignment. + // However, under some circumstances DragonFly BSD appears to put + // more addresses in the message than are indicated in the address + // bitmask, so don't check for this. return as[:], nil } diff --git a/src/vendor/golang.org/x/net/route/message.go b/src/vendor/golang.org/x/net/route/message.go index d53bb7f9b1..456a8363fe 100644 --- a/src/vendor/golang.org/x/net/route/message.go +++ b/src/vendor/golang.org/x/net/route/message.go @@ -53,7 +53,7 @@ func ParseRIB(typ RIBType, b []byte) ([]Message, error) { if w, ok := wireFormats[int(b[3])]; !ok { nskips++ } else { - m, err := w.parse(typ, b) + m, err := w.parse(typ, b[:l]) if err != nil { return nil, err } diff --git a/src/vendor/golang.org/x/net/route/sys_freebsd.go b/src/vendor/golang.org/x/net/route/sys_freebsd.go index fe91be1249..3599601740 100644 --- a/src/vendor/golang.org/x/net/route/sys_freebsd.go +++ b/src/vendor/golang.org/x/net/route/sys_freebsd.go @@ -134,9 +134,6 @@ func probeRoutingStack() (int, map[int]*wireFormat) { } else { ifm.bodyOff = sizeofIfMsghdrFreeBSD11 } - if rel >= 1102000 { // see https://github.com/freebsd/freebsd/commit/027c7f4d66ff8d8c4a46c3665a5ee7d6d8462034#diff-ad4e5b7f1449ea3fc87bc97280de145b - align = wordSize - } } rtm.parse = rtm.parseRouteMessage ifm.parse = ifm.parseInterfaceMessage diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index ff01db5cdc..d50b8668fc 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -8,7 +8,7 @@ golang.org/x/crypto/curve25519 golang.org/x/crypto/hkdf golang.org/x/crypto/internal/subtle golang.org/x/crypto/poly1305 -# golang.org/x/net v0.0.0-20210510120150-4163338589ed +# golang.org/x/net v0.0.0-20210825183410-e898025ed96a ## explicit; go 1.17 golang.org/x/net/dns/dnsmessage golang.org/x/net/http/httpguts -- GitLab From 2872496ba528d658b68a9e66f46b2b722368a3bb Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 31 Aug 2021 17:43:18 -0700 Subject: [PATCH 0959/2500] cmd/compile/internal/types2: systematic detection of missing instantiation When type-checking expressions, detection of uninstantiated generic functions and types was somewhat ad-hoc. Add an extra parameter "allowGenerics" to rawExpr. If not set, the result operand cannot be generic. The only place where rawExpr is called with allowGenerics != false is from exprOrType, which passes an allowGenerics parameter through. The only place where exprOrType is called with allowGenerics == true is when handling index expressions and calls. Make sure that we only accept generic operands where expected, and check the other branches. As a result, a recently added varType call (CL 345970) can be removed again. This also fixes a bug where an error for a conversion to generic type was reported after the conversion (i.e., with the converted value, rather than the generic type). Added a test case for that. For #48048. Change-Id: I8576326f5fcfb58d78b3ce8572068aa32e66c568 Reviewed-on: https://go-review.googlesource.com/c/go/+/346471 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/builtins.go | 2 +- src/cmd/compile/internal/types2/call.go | 19 ++++--- src/cmd/compile/internal/types2/expr.go | 49 ++++++++++++++++--- src/cmd/compile/internal/types2/index.go | 10 +++- src/cmd/compile/internal/types2/stmt.go | 4 +- .../types2/testdata/examples/types.go2 | 1 + .../types2/testdata/fixedbugs/issue39634.go2 | 2 +- 7 files changed, 66 insertions(+), 21 deletions(-) diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 87295fe0e7..e3844d5163 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -763,7 +763,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( var t operand x1 := x for _, arg := range call.ArgList { - check.rawExpr(x1, arg, nil) // permit trace for types, e.g.: new(trace(T)) + check.rawExpr(x1, arg, nil, false) // permit trace for types, e.g.: new(trace(T)) check.dump("%v: %s", posFor(x1), x1) x1 = &t // use incoming x only for first argument } diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 954aa1de20..5bf17876c1 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -83,8 +83,9 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { x.expr = iexpr check.record(x) } else { - check.exprOrType(x, call.Fun) + check.exprOrType(x, call.Fun, true) } + // x.typ may be generic switch x.mode { case invalid: @@ -94,6 +95,10 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { case typexpr: // conversion + check.nonGeneric(x) + if x.mode == invalid { + return conversion + } T := x.typ x.mode = invalid switch n := len(call.ArgList); n { @@ -122,6 +127,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { return conversion case builtin: + // no need to check for non-genericity here id := x.id if !check.builtin(x, call, id) { x.mode = invalid @@ -135,6 +141,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { } // ordinary function/method call + // signature may be generic cgocall := x.mode == cgofunc sig := asSignature(x.typ) @@ -474,15 +481,11 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) { } } - check.exprOrType(x, e.X) + check.exprOrType(x, e.X, false) if x.mode == invalid { goto Error } - if x.mode == typexpr { - x.typ = check.varType(e.X) - } - obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel) if obj == nil { switch { @@ -683,7 +686,7 @@ func (check *Checker) use(arg ...syntax.Expr) { check.use(l.ElemList...) continue } - check.rawExpr(&x, e, nil) + check.rawExpr(&x, e, nil, false) } } @@ -714,7 +717,7 @@ func (check *Checker) useLHS(arg ...syntax.Expr) { } } } - check.rawExpr(&x, e, nil) + check.rawExpr(&x, e, nil, false) if v != nil { v.used = v_used // restore v.used } diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 799874624d..99204762bc 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -1085,8 +1085,10 @@ const ( // rawExpr typechecks expression e and initializes x with the expression // value or type. If an error occurred, x.mode is set to invalid. // If hint != nil, it is the type of a composite literal element. +// If allowGeneric is set, the operand type may be an uninstantiated +// parameterized type or function value. // -func (check *Checker) rawExpr(x *operand, e syntax.Expr, hint Type) exprKind { +func (check *Checker) rawExpr(x *operand, e syntax.Expr, hint Type, allowGeneric bool) exprKind { if check.conf.Trace { check.trace(e.Pos(), "expr %s", e) check.indent++ @@ -1097,11 +1099,40 @@ func (check *Checker) rawExpr(x *operand, e syntax.Expr, hint Type) exprKind { } kind := check.exprInternal(x, e, hint) + + if !allowGeneric { + check.nonGeneric(x) + } + check.record(x) return kind } +// If x is a generic function or type, nonGeneric reports an error and invalidates x.mode and x.typ. +// Otherwise it leaves x alone. +func (check *Checker) nonGeneric(x *operand) { + if x.mode == invalid || x.mode == novalue { + return + } + var what string + switch t := x.typ.(type) { + case *Named: + if isGeneric(t) { + what = "type" + } + case *Signature: + if t.tparams != nil { + what = "function" + } + } + if what != "" { + check.errorf(x.expr, "cannot use generic %s %s without instantiation", what, x.expr) + x.mode = invalid + x.typ = Typ[Invalid] + } +} + // exprInternal contains the core of type checking of expressions. // Must only be called by rawExpr. // @@ -1386,7 +1417,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin x.typ = typ case *syntax.ParenExpr: - kind := check.rawExpr(x, e.X, nil) + kind := check.rawExpr(x, e.X, nil, false) x.expr = e return kind @@ -1468,7 +1499,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin // unary expression if e.Op == syntax.Mul { // pointer indirection - check.exprOrType(x, e.X) + check.exprOrType(x, e.X, false) switch x.mode { case invalid: goto Error @@ -1595,14 +1626,14 @@ func (check *Checker) typeAssertion(pos syntax.Pos, x *operand, xtyp *Interface, // If an error occurred, x.mode is set to invalid. // func (check *Checker) expr(x *operand, e syntax.Expr) { - check.rawExpr(x, e, nil) + check.rawExpr(x, e, nil, false) check.exclude(x, 1<= 0 diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index 3231fbec93..e138c58123 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -170,7 +170,7 @@ func (check *Checker) closeScope() { func (check *Checker) suspendedCall(keyword string, call *syntax.CallExpr) { var x operand var msg string - switch check.rawExpr(&x, call, nil) { + switch check.rawExpr(&x, call, nil, false) { case conversion: msg = "requires function call, not conversion" case expression: @@ -386,7 +386,7 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) { // function and method calls and receive operations can appear // in statement context. Such statements may be parenthesized." var x operand - kind := check.rawExpr(&x, s.X, nil) + kind := check.rawExpr(&x, s.X, nil, false) var msg string switch x.mode { default: diff --git a/src/cmd/compile/internal/types2/testdata/examples/types.go2 b/src/cmd/compile/internal/types2/testdata/examples/types.go2 index 9ee014452c..97c9951ada 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/types.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/types.go2 @@ -102,6 +102,7 @@ func _() { // Generic types cannot be used without instantiation. var _ T // ERROR cannot use generic type T +var _ = T /* ERROR cannot use generic type T */ (0) // In type context, generic (parameterized) types cannot be parenthesized before // being instantiated. See also NOTES entry from 12/4/2019. diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 index 8d14f8acaf..8e6bd974e8 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 @@ -85,7 +85,7 @@ var x T25 /* ERROR without instantiation */ .m1 // crash 26 type T26 = interface{ F26[ /* ERROR cannot have type parameters */ Z any]() } -func F26[Z any]() T26 { return F26 /* ERROR without instantiation */ /* ERROR missing method */ [] /* ERROR operand */ } +func F26[Z any]() T26 { return F26 /* ERROR without instantiation */ [] /* ERROR operand */ } // crash 27 func e27[T any]() interface{ x27 /* ERROR not a type */ } { panic(0) } -- GitLab From df4c625d88859003df65bc5d528942ee6ba793a1 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 1 Sep 2021 17:01:26 -0700 Subject: [PATCH 0960/2500] cmd/compile: disable type list syntax for the compiler Add (temporary) syntax.AllowTypeLists mode to control the acceptance of type lists; the compiler doesn't set it, but existing syntax and types2 tests do so that the code remains exercised while it exists. Adjust various tests to use the type set notation. Change-Id: I798e607912552db6bfe38a7cd4324b74c6bf4d95 Reviewed-on: https://go-review.googlesource.com/c/go/+/347249 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/syntax/error_test.go | 2 +- src/cmd/compile/internal/syntax/parser.go | 11 +++++-- .../compile/internal/syntax/parser_test.go | 2 +- .../compile/internal/syntax/printer_test.go | 4 +-- src/cmd/compile/internal/syntax/syntax.go | 1 + src/cmd/compile/internal/types2/check_test.go | 2 +- test/typeparam/append.go | 2 +- test/typeparam/double.go | 2 +- test/typeparam/settable.go | 2 +- test/typeparam/typelist.go | 31 ++++++++++--------- 10 files changed, 34 insertions(+), 25 deletions(-) diff --git a/src/cmd/compile/internal/syntax/error_test.go b/src/cmd/compile/internal/syntax/error_test.go index e4bedf54fd..30e68ff1d9 100644 --- a/src/cmd/compile/internal/syntax/error_test.go +++ b/src/cmd/compile/internal/syntax/error_test.go @@ -130,7 +130,7 @@ func testSyntaxErrors(t *testing.T, filename string) { var mode Mode if strings.HasSuffix(filename, ".go2") { - mode = AllowGenerics + mode = AllowGenerics | AllowTypeLists } ParseFile(filename, func(err error) { e, ok := err.(Error) diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index 3d1ca9d6d4..e89796cb31 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -1448,7 +1448,7 @@ func (p *parser) interfaceType() *InterfaceType { case _Type: // TODO(gri) remove TypeList syntax if we accept #45346 - if p.mode&AllowGenerics != 0 { + if p.mode&AllowGenerics != 0 && p.mode&AllowTypeLists != 0 { type_ := NewName(p.pos(), "type") // cannot have a method named "type" p.next() if p.tok != _Semi && p.tok != _Rbrace { @@ -1484,8 +1484,13 @@ func (p *parser) interfaceType() *InterfaceType { } if p.mode&AllowGenerics != 0 { - p.syntaxError("expecting method, type list, or embedded element") - p.advance(_Semi, _Rbrace, _Type) // TODO(gri) remove _Type if we don't accept it anymore + if p.mode&AllowTypeLists != 0 { + p.syntaxError("expecting method, type list, or embedded element") + p.advance(_Semi, _Rbrace, _Type) + } else { + p.syntaxError("expecting method or embedded element") + p.advance(_Semi, _Rbrace) + } return false } diff --git a/src/cmd/compile/internal/syntax/parser_test.go b/src/cmd/compile/internal/syntax/parser_test.go index 340ca6bb6f..6afe109e1b 100644 --- a/src/cmd/compile/internal/syntax/parser_test.go +++ b/src/cmd/compile/internal/syntax/parser_test.go @@ -46,7 +46,7 @@ func TestParseGo2(t *testing.T) { for _, fi := range list { name := fi.Name() if !fi.IsDir() && !strings.HasPrefix(name, ".") { - ParseFile(filepath.Join(dir, name), func(err error) { t.Error(err) }, nil, AllowGenerics) + ParseFile(filepath.Join(dir, name), func(err error) { t.Error(err) }, nil, AllowGenerics|AllowTypeLists) } } } diff --git a/src/cmd/compile/internal/syntax/printer_test.go b/src/cmd/compile/internal/syntax/printer_test.go index 638e6d4a9d..d3469a2599 100644 --- a/src/cmd/compile/internal/syntax/printer_test.go +++ b/src/cmd/compile/internal/syntax/printer_test.go @@ -90,7 +90,7 @@ var stringTests = []string{ func TestPrintString(t *testing.T) { for _, want := range stringTests { - ast, err := Parse(nil, strings.NewReader(want), nil, nil, AllowGenerics) + ast, err := Parse(nil, strings.NewReader(want), nil, nil, AllowGenerics|AllowTypeLists) if err != nil { t.Error(err) continue @@ -210,7 +210,7 @@ var exprTests = [][2]string{ func TestShortString(t *testing.T) { for _, test := range exprTests { src := "package p; var _ = " + test[0] - ast, err := Parse(nil, strings.NewReader(src), nil, nil, AllowGenerics) + ast, err := Parse(nil, strings.NewReader(src), nil, nil, AllowGenerics|AllowTypeLists) if err != nil { t.Errorf("%s: %s", test[0], err) continue diff --git a/src/cmd/compile/internal/syntax/syntax.go b/src/cmd/compile/internal/syntax/syntax.go index f3d4c09ed5..08f450c94f 100644 --- a/src/cmd/compile/internal/syntax/syntax.go +++ b/src/cmd/compile/internal/syntax/syntax.go @@ -17,6 +17,7 @@ type Mode uint const ( CheckBranches Mode = 1 << iota // check correct use of labels, break, continue, and goto statements AllowGenerics + AllowTypeLists // requires AllowGenerics; remove once 1.18 is out ) // Error describes a syntax error. Error implements the error interface. diff --git a/src/cmd/compile/internal/types2/check_test.go b/src/cmd/compile/internal/types2/check_test.go index bc68e76407..26c8eba727 100644 --- a/src/cmd/compile/internal/types2/check_test.go +++ b/src/cmd/compile/internal/types2/check_test.go @@ -100,7 +100,7 @@ func testFiles(t *testing.T, filenames []string, colDelta uint, manual bool) { var mode syntax.Mode if strings.HasSuffix(filenames[0], ".go2") { - mode |= syntax.AllowGenerics + mode |= syntax.AllowGenerics | syntax.AllowTypeLists } // parse files and collect parser errors files, errlist := parseFiles(t, filenames, mode) diff --git a/test/typeparam/append.go b/test/typeparam/append.go index 8b9bc2039f..42b542ed78 100644 --- a/test/typeparam/append.go +++ b/test/typeparam/append.go @@ -9,7 +9,7 @@ package main type Recv <-chan int type sliceOf[E any] interface { - type []E + ~[]E } func _Append[S sliceOf[T], T any](s S, t ...T) S { diff --git a/test/typeparam/double.go b/test/typeparam/double.go index 6ddb6b2d08..3dbdd1b05e 100644 --- a/test/typeparam/double.go +++ b/test/typeparam/double.go @@ -19,7 +19,7 @@ type MySlice []int type MyFloatSlice []float64 type _SliceOf[E any] interface { - type []E + ~[]E } func _DoubleElems[S _SliceOf[E], E Number](s S) S { diff --git a/test/typeparam/settable.go b/test/typeparam/settable.go index 99455e93fa..412023b20a 100644 --- a/test/typeparam/settable.go +++ b/test/typeparam/settable.go @@ -15,7 +15,7 @@ import ( type Setter[B any] interface { Set(string) - type *B + ~*B } // Takes two type parameters where PT = *T diff --git a/test/typeparam/typelist.go b/test/typeparam/typelist.go index 5ba14261ab..8d6a228de5 100644 --- a/test/typeparam/typelist.go +++ b/test/typeparam/typelist.go @@ -6,23 +6,26 @@ // This file tests type lists & structural constraints. +// Note: This test has been adjusted to use the new +// type set notation rather than type lists. + package p // Assignability of an unnamed pointer type to a type parameter that // has a matching underlying type. -func _[T interface{}, PT interface{ type *T }](x T) PT { +func _[T interface{}, PT interface{ ~*T }](x T) PT { return &x } // Indexing of generic types containing type parameters in their type list: -func at[T interface{ type []E }, E any](x T, i int) E { +func at[T interface{ ~[]E }, E any](x T, i int) E { return x[i] } // A generic type inside a function acts like a named type. Its underlying // type is itself, its "operational type" is defined by the type list in // the tybe bound, if any. -func _[T interface{ type int }](x T) { +func _[T interface{ ~int }](x T) { type myint int var _ int = int(x) var _ T = 42 @@ -30,36 +33,36 @@ func _[T interface{ type int }](x T) { } // Indexing a generic type which has a structural contraints to be an array. -func _[T interface{ type [10]int }](x T) { +func _[T interface{ ~[10]int }](x T) { _ = x[9] // ok } // Dereference of a generic type which has a structural contraint to be a pointer. -func _[T interface{ type *int }](p T) int { +func _[T interface{ ~*int }](p T) int { return *p } // Channel send and receive on a generic type which has a structural constraint to // be a channel. -func _[T interface{ type chan int }](ch T) int { +func _[T interface{ ~chan int }](ch T) int { // This would deadlock if executed (but ok for a compile test) ch <- 0 return <-ch } // Calling of a generic type which has a structural constraint to be a function. -func _[T interface{ type func() }](f T) { +func _[T interface{ ~func() }](f T) { f() go f() } // Same, but function has a parameter and return value. -func _[T interface{ type func(string) int }](f T) int { +func _[T interface{ ~func(string) int }](f T) int { return f("hello") } // Map access of a generic type which has a structural constraint to be a map. -func _[V any, T interface{ type map[string]V }](p T) V { +func _[V any, T interface{ ~map[string]V }](p T) V { return p["test"] } @@ -85,7 +88,7 @@ func f1x() { } */ -func f2[A any, B interface{ type []A }](_ A, _ B) {} +func f2[A any, B interface{ ~[]A }](_ A, _ B) {} func f2x() { f := f2[byte] f(byte(0), []byte{}) @@ -105,7 +108,7 @@ func f3x() { } */ -func f4[A any, B interface{ type []C }, C interface{ type *A }](_ A, _ B, c C) {} +func f4[A any, B interface{ ~[]C }, C interface{ ~*A }](_ A, _ B, c C) {} func f4x() { f := f4[int] var x int @@ -114,18 +117,18 @@ func f4x() { } func f5[A interface { - type struct { + ~struct { b B c C } -}, B any, C interface{ type *B }](x B) A { panic(0) } +}, B any, C interface{ ~*B }](x B) A { panic(0) } func f5x() { x := f5(1.2) var _ float64 = x.b var _ float64 = *x.c } -func f6[A any, B interface{ type struct{ f []A } }](B) A { panic(0) } +func f6[A any, B interface{ ~struct{ f []A } }](B) A { panic(0) } func f6x() { x := f6(struct{ f []string }{}) var _ string = x -- GitLab From 1bd35fab05252450c3f67df18f9976fdaaa4dcf4 Mon Sep 17 00:00:00 2001 From: Meng Zhuo Date: Thu, 26 Aug 2021 09:32:38 +0800 Subject: [PATCH 0961/2500] runtime: use vDSO clock_gettime on linux/riscv64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Speed up nanotime1 and walltime on riscv64 with vDSO, just like the other vDSO-enabled targets. name old time/op new time/op delta Now 1.53µs ± 1% 1.05µs ± 3% -31.74% (p=0.000 n=10+10) NowUnixNano 1.54µs ± 0% 1.05µs ± 2% -31.91% (p=0.000 n=9+10) NowUnixMilli 1.56µs ± 1% 1.06µs ± 1% -31.73% (p=0.000 n=10+10) NowUnixMicro 1.56µs ± 1% 1.05µs ± 1% -32.80% (p=0.000 n=9+10) Change-Id: I69b3fe3cc57685a826c53b366c0992e8048399bb Reviewed-on: https://go-review.googlesource.com/c/go/+/328509 Trust: Meng Zhuo Run-TryBot: Meng Zhuo TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/os_linux_novdso.go | 4 +- src/runtime/signal_unix.go | 2 +- src/runtime/sys_linux_riscv64.s | 135 ++++++++++++++++++++++++++++-- src/runtime/vdso_elf64.go | 4 +- src/runtime/vdso_in_none.go | 4 +- src/runtime/vdso_linux.go | 4 +- src/runtime/vdso_linux_riscv64.go | 21 +++++ 7 files changed, 159 insertions(+), 15 deletions(-) create mode 100644 src/runtime/vdso_linux_riscv64.go diff --git a/src/runtime/os_linux_novdso.go b/src/runtime/os_linux_novdso.go index 8104f63627..7e93d2ba83 100644 --- a/src/runtime/os_linux_novdso.go +++ b/src/runtime/os_linux_novdso.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build linux && !386 && !amd64 && !arm && !arm64 && !mips64 && !mips64le && !ppc64 && !ppc64le -// +build linux,!386,!amd64,!arm,!arm64,!mips64,!mips64le,!ppc64,!ppc64le +//go:build linux && !386 && !amd64 && !arm && !arm64 && !mips64 && !mips64le && !ppc64 && !ppc64le && !riscv64 +// +build linux,!386,!amd64,!arm,!arm64,!mips64,!mips64le,!ppc64,!ppc64le,!riscv64 package runtime diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go index 8117582855..cab5c879d3 100644 --- a/src/runtime/signal_unix.go +++ b/src/runtime/signal_unix.go @@ -383,7 +383,7 @@ func preemptM(mp *m) { //go:nosplit func sigFetchG(c *sigctxt) *g { switch GOARCH { - case "arm", "arm64", "ppc64", "ppc64le": + case "arm", "arm64", "ppc64", "ppc64le", "riscv64": if !iscgo && inVDSOPage(c.sigpc()) { // When using cgo, we save the g on TLS and load it from there // in sigtramp. Just use that. diff --git a/src/runtime/sys_linux_riscv64.s b/src/runtime/sys_linux_riscv64.s index 54b7a3f61c..ebcdd56a45 100644 --- a/src/runtime/sys_linux_riscv64.s +++ b/src/runtime/sys_linux_riscv64.s @@ -10,6 +10,8 @@ #include "go_asm.h" #define AT_FDCWD -100 +#define CLOCK_REALTIME 0 +#define CLOCK_MONOTONIC 1 #define SYS_brk 214 #define SYS_clock_gettime 113 @@ -210,8 +212,68 @@ TEXT runtime·mincore(SB),NOSPLIT|NOFRAME,$0-28 RET // func walltime() (sec int64, nsec int32) -TEXT runtime·walltime(SB),NOSPLIT,$24-12 - MOV $0, A0 // CLOCK_REALTIME +TEXT runtime·walltime(SB),NOSPLIT,$40-12 + MOV $CLOCK_REALTIME, A0 + + MOV runtime·vdsoClockgettimeSym(SB), A7 + BEQZ A7, fallback + MOV X2, S2 // S2,S3,S4 is unchanged by C code + MOV g_m(g), S3 // S3 = m + + // Save the old values on stack for reentrant + MOV m_vdsoPC(S3), T0 + MOV T0, 24(X2) + MOV m_vdsoSP(S3), T0 + MOV T0, 32(X2) + + MOV RA, m_vdsoPC(S3) + MOV $ret-8(FP), T1 // caller's SP + MOV T1, m_vdsoSP(S3) + + MOV m_curg(S3), T1 + BNE g, T1, noswitch + + MOV m_g0(S3), T1 + MOV (g_sched+gobuf_sp)(T1), X2 + +noswitch: + ADDI $-24, X2 // Space for result + ANDI $~7, X2 // Align for C code + MOV $8(X2), A1 + + // Store g on gsignal's stack, see sys_linux_arm64.s for detail + MOVBU runtime·iscgo(SB), S4 + BNEZ S4, nosaveg + MOV m_gsignal(S3), S4 // g.m.gsignal + BEQZ S4, nosaveg + BEQ g, S4, nosaveg + MOV (g_stack+stack_lo)(S4), S4 // g.m.gsignal.stack.lo + MOV g, (S4) + + JALR RA, A7 + + MOV ZERO, (S4) + JMP finish + +nosaveg: + JALR RA, A7 + +finish: + MOV 8(X2), T0 // sec + MOV 16(X2), T1 // nsec + + MOV S2, X2 // restore stack + MOV 24(X2), A2 + MOV A2, m_vdsoPC(S3) + + MOV 32(X2), A3 + MOV A3, m_vdsoSP(S3) + + MOV T0, sec+0(FP) + MOVW T1, nsec+8(FP) + RET + +fallback: MOV $8(X2), A1 MOV $SYS_clock_gettime, A7 ECALL @@ -222,13 +284,62 @@ TEXT runtime·walltime(SB),NOSPLIT,$24-12 RET // func nanotime1() int64 -TEXT runtime·nanotime1(SB),NOSPLIT,$24-8 - MOV $1, A0 // CLOCK_MONOTONIC +TEXT runtime·nanotime1(SB),NOSPLIT,$40-8 + MOV $CLOCK_MONOTONIC, A0 + + MOV runtime·vdsoClockgettimeSym(SB), A7 + BEQZ A7, fallback + + MOV X2, S2 // S2 = RSP, S2 is unchanged by C code + MOV g_m(g), S3 // S3 = m + // Save the old values on stack for reentrant + MOV m_vdsoPC(S3), T0 + MOV T0, 24(X2) + MOV m_vdsoSP(S3), T0 + MOV T0, 32(X2) + + MOV RA, m_vdsoPC(S3) + MOV $ret-8(FP), T0 // caller's SP + MOV T0, m_vdsoSP(S3) + + MOV m_curg(S3), T1 + BNE g, T1, noswitch + + MOV m_g0(S3), T1 + MOV (g_sched+gobuf_sp)(T1), X2 + +noswitch: + ADDI $-24, X2 // Space for result + ANDI $~7, X2 // Align for C code MOV $8(X2), A1 - MOV $SYS_clock_gettime, A7 - ECALL + + // Store g on gsignal's stack, see sys_linux_arm64.s for detail + MOVBU runtime·iscgo(SB), S4 + BNEZ S4, nosaveg + MOV m_gsignal(S3), S4 // g.m.gsignal + BEQZ S4, nosaveg + BEQ g, S4, nosaveg + MOV (g_stack+stack_lo)(S4), S4 // g.m.gsignal.stack.lo + MOV g, (S4) + + JALR RA, A7 + + MOV ZERO, (S4) + JMP finish + +nosaveg: + JALR RA, A7 + +finish: MOV 8(X2), T0 // sec MOV 16(X2), T1 // nsec + // restore stack + MOV S2, X2 + MOV 24(X2), T2 + MOV T2, m_vdsoPC(S3) + + MOV 32(X2), T2 + MOV T2, m_vdsoSP(S3) // sec is in T0, nsec in T1 // return nsec in T0 MOV $1000000000, T2 @@ -237,6 +348,18 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$24-8 MOV T0, ret+0(FP) RET +fallback: + MOV $8(X2), A1 + MOV $SYS_clock_gettime, A7 + ECALL + MOV 8(X2), T0 // sec + MOV 16(X2), T1 // nsec + MOV $1000000000, T2 + MUL T2, T0 + ADD T1, T0 + MOV T0, ret+0(FP) + RET + // func rtsigprocmask(how int32, new, old *sigset, size int32) TEXT runtime·rtsigprocmask(SB),NOSPLIT|NOFRAME,$0-28 MOVW how+0(FP), A0 diff --git a/src/runtime/vdso_elf64.go b/src/runtime/vdso_elf64.go index 9923bd4697..aecc84dcfe 100644 --- a/src/runtime/vdso_elf64.go +++ b/src/runtime/vdso_elf64.go @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build linux && (amd64 || arm64 || mips64 || mips64le || ppc64 || ppc64le) +//go:build linux && (amd64 || arm64 || mips64 || mips64le || ppc64 || ppc64le || riscv64) // +build linux -// +build amd64 arm64 mips64 mips64le ppc64 ppc64le +// +build amd64 arm64 mips64 mips64le ppc64 ppc64le riscv64 package runtime diff --git a/src/runtime/vdso_in_none.go b/src/runtime/vdso_in_none.go index c66fbf8216..3e98b08b15 100644 --- a/src/runtime/vdso_in_none.go +++ b/src/runtime/vdso_in_none.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build (linux && !386 && !amd64 && !arm && !arm64 && !mips64 && !mips64le && !ppc64 && !ppc64le) || !linux -// +build linux,!386,!amd64,!arm,!arm64,!mips64,!mips64le,!ppc64,!ppc64le !linux +//go:build (linux && !386 && !amd64 && !arm && !arm64 && !mips64 && !mips64le && !ppc64 && !ppc64le && !riscv64) || !linux +// +build linux,!386,!amd64,!arm,!arm64,!mips64,!mips64le,!ppc64,!ppc64le,!riscv64 !linux package runtime diff --git a/src/runtime/vdso_linux.go b/src/runtime/vdso_linux.go index ae211f96b1..20c8db78be 100644 --- a/src/runtime/vdso_linux.go +++ b/src/runtime/vdso_linux.go @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build linux && (386 || amd64 || arm || arm64 || mips64 || mips64le || ppc64 || ppc64le) +//go:build linux && (386 || amd64 || arm || arm64 || mips64 || mips64le || ppc64 || ppc64le || riscv64) // +build linux -// +build 386 amd64 arm arm64 mips64 mips64le ppc64 ppc64le +// +build 386 amd64 arm arm64 mips64 mips64le ppc64 ppc64le riscv64 package runtime diff --git a/src/runtime/vdso_linux_riscv64.go b/src/runtime/vdso_linux_riscv64.go new file mode 100644 index 0000000000..f427124c3c --- /dev/null +++ b/src/runtime/vdso_linux_riscv64.go @@ -0,0 +1,21 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime + +const ( + // vdsoArrayMax is the byte-size of a maximally sized array on this architecture. + // See cmd/compile/internal/riscv64/galign.go arch.MAXWIDTH initialization. + vdsoArrayMax = 1<<50 - 1 +) + +// key and version at man 7 vdso : riscv +var vdsoLinuxVersion = vdsoVersionKey{"LINUX_4.15", 0xae77f75} + +var vdsoSymbolKeys = []vdsoSymbolKey{ + {"__vdso_clock_gettime", 0xd35ec75, 0x6e43a318, &vdsoClockgettimeSym}, +} + +// initialize to fall back to syscall +var vdsoClockgettimeSym uintptr = 0 -- GitLab From 9afbf82667a81827a805f39db51ff36bf0abc737 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 1 Sep 2021 19:58:31 +0700 Subject: [PATCH 0962/2500] cmd/compile: allow objStub from unsafe package CL 346469 added support for unsafe.Sizeof and friends to operate on generic parameters for compiler importer/exporter. This CL adds support for unified IR. Updates #48094 Change-Id: I63af1a7c3478f59b03ecc23229ac2254d3457868 Reviewed-on: https://go-review.googlesource.com/c/go/+/346769 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Keith Randall Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/noder/reader2.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index 8f3f0a50e9..a775ffda34 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -147,6 +147,10 @@ func (r *reader2) doPkg() *types2.Package { if path == "builtin" { return nil // universe } + if path == "unsafe" { + // TODO(mdempsky): This should be in r.p.imports. + return types2.Unsafe + } if path == "" { path = r.p.pkgPath } @@ -362,7 +366,7 @@ func (pr *pkgReader2) objIdx(idx int) (*types2.Package, string) { tag := codeObj(rname.code(syncCodeObj)) if tag == objStub { - assert(objPkg == nil) + assert(objPkg == nil || objPkg == types2.Unsafe) return objPkg, objName } -- GitLab From 3db4888a05fb15035d332a360cb610f2c05370ab Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 2 Sep 2021 10:42:43 +0700 Subject: [PATCH 0963/2500] cmd/compile: use types2.Unsafe to represent package unsafe in gcimports Followup todo in CL 346769. Change-Id: I6c870014523426d65d135da999f97a818a997237 Reviewed-on: https://go-review.googlesource.com/c/go/+/347270 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/noder/irgen.go | 2 +- src/cmd/compile/internal/noder/reader2.go | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index 70f7991a8e..fd29c51c8a 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -35,7 +35,7 @@ func checkFiles(noders []*noder) (posMap, *types2.Package, *types2.Info) { // typechecking importer := gcimports{ - packages: make(map[string]*types2.Package), + packages: map[string]*types2.Package{"unsafe": types2.Unsafe}, } conf := types2.Config{ GoVersion: base.Flag.Lang, diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index a775ffda34..cffa037236 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -147,10 +147,6 @@ func (r *reader2) doPkg() *types2.Package { if path == "builtin" { return nil // universe } - if path == "unsafe" { - // TODO(mdempsky): This should be in r.p.imports. - return types2.Unsafe - } if path == "" { path = r.p.pkgPath } -- GitLab From 1ae7ddc2350b2dd30e1f3ad877c3c70ef745111d Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 2 Sep 2021 11:06:27 +0700 Subject: [PATCH 0964/2500] test: always run test in unified IR mode regardless of explicit -G flag Currently, if a test explicitly specify -G flag, if that flag conflict with compiler default -G flag, the test will be skipped. That's the reason CL 346469 haven't fixed the unified IR stuff, but still make the unified builder passed. This CL makes run.go always run the test in unified IR mode, regardless of the explicit -G flag specified. Updates #48094 Change-Id: I959ecaff6aca07844f0ffcf36caa60cf0747e8ce Reviewed-on: https://go-review.googlesource.com/c/go/+/347271 Trust: Cuong Manh Le Trust: Keith Randall Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- test/run.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/run.go b/test/run.go index 3759059c95..ddce94d7cc 100644 --- a/test/run.go +++ b/test/run.go @@ -759,7 +759,8 @@ func (t *test) run() { } } - if hasGFlag && t.glevel != CompilerDefaultGLevel { + // In unified IR mode, run the test regardless of explicit -G flag. + if !unifiedEnabled && hasGFlag && t.glevel != CompilerDefaultGLevel { // test provides explicit -G flag already; don't run again if *verbose { fmt.Printf("excl\t%s\n", t.goFileName()) -- GitLab From 840b4292c9cd5472babf562d3b6eaf727926fd90 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 9 Jun 2021 14:26:36 +0700 Subject: [PATCH 0965/2500] src: emit warning when make.bash run with invalid GOROOT_BOOTSTRAP When setting an invalid GOROOT_BOOTSTRAP, make.bash try looking at env to find a valid go command and use that GOROOT instead. It's better if the script emit a warning, instead of silently change the GOROOT_BOOTSTRAP. Change-Id: I6038093d5e8c072da27bcae44b125f6774f809a7 Reviewed-on: https://go-review.googlesource.com/c/go/+/326030 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/make.bash | 2 ++ src/make.rc | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/make.bash b/src/make.bash index 7986125a06..9ff471d863 100755 --- a/src/make.bash +++ b/src/make.bash @@ -158,6 +158,8 @@ IFS=$'\n'; for go_exe in $(type -ap go); do if [ ! -x "$GOROOT_BOOTSTRAP/bin/go" ]; then goroot=$(GOROOT='' GOOS='' GOARCH='' "$go_exe" env GOROOT) if [ "$goroot" != "$GOROOT" ]; then + printf 'WARNING: %s does not exist, found %s from env\n' "$GOROOT_BOOTSTRAP/bin/go" "$go_exe" >&2 + printf 'WARNING: set %s as GOROOT_BOOTSTRAP\n' "$goroot" >&2 GOROOT_BOOTSTRAP=$goroot fi fi diff --git a/src/make.rc b/src/make.rc index 7bdc7dea1c..29d8c675db 100755 --- a/src/make.rc +++ b/src/make.rc @@ -58,6 +58,8 @@ for(p in $path){ if(go_exe = `{path=$p whatis go}){ goroot = `{GOROOT='' $go_exe env GOROOT} if(! ~ $goroot $GOROOT){ + echo 'WARNING: '$GOROOT_BOOTSTRAP'/bin/go does not exist, found '$go_exe' from env' >[1=2] + echo 'WARNING: set '$goroot' as GOROOT_BOOTSTRAP' >[1=2] GOROOT_BOOTSTRAP = $goroot } } -- GitLab From d13d62c49adca86f2101bc0b7d5a394197ece81b Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 1 Sep 2021 14:57:18 +0200 Subject: [PATCH 0966/2500] os, syscall: remove fallback to pipe syscall on Linux The minimum required Linux kernel version for Go 1.18 will be changed to 2.6.32, see #45964. The pipe2 syscall was added in 2.6.27, so the fallback to use the pipe syscall in os.Pipe and syscall.forkExecPipe on Linux can be removed. For #45964 Change-Id: I033a534f2b39e9bafc9980c9ce980e92f1e3a136 Reviewed-on: https://go-review.googlesource.com/c/go/+/346789 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/os/pipe_linux.go | 15 +-------------- src/syscall/exec_linux.go | 14 +------------- 2 files changed, 2 insertions(+), 27 deletions(-) diff --git a/src/os/pipe_linux.go b/src/os/pipe_linux.go index acd7b88e1d..52f4e21e7c 100644 --- a/src/os/pipe_linux.go +++ b/src/os/pipe_linux.go @@ -12,20 +12,7 @@ func Pipe() (r *File, w *File, err error) { var p [2]int e := syscall.Pipe2(p[0:], syscall.O_CLOEXEC) - // pipe2 was added in 2.6.27 and our minimum requirement is 2.6.23, so it - // might not be implemented. - if e == syscall.ENOSYS { - // See ../syscall/exec.go for description of lock. - syscall.ForkLock.RLock() - e = syscall.Pipe(p[0:]) - if e != nil { - syscall.ForkLock.RUnlock() - return nil, nil, NewSyscallError("pipe", e) - } - syscall.CloseOnExec(p[0]) - syscall.CloseOnExec(p[1]) - syscall.ForkLock.RUnlock() - } else if e != nil { + if e != nil { return nil, nil, NewSyscallError("pipe2", e) } diff --git a/src/syscall/exec_linux.go b/src/syscall/exec_linux.go index ccc0e39e30..68bce7559b 100644 --- a/src/syscall/exec_linux.go +++ b/src/syscall/exec_linux.go @@ -553,19 +553,7 @@ childerror: // Try to open a pipe with O_CLOEXEC set on both file descriptors. func forkExecPipe(p []int) (err error) { - err = Pipe2(p, O_CLOEXEC) - // pipe2 was added in 2.6.27 and our minimum requirement is 2.6.23, so it - // might not be implemented. - if err == ENOSYS { - if err = Pipe(p); err != nil { - return - } - if _, err = fcntl(p[0], F_SETFD, FD_CLOEXEC); err != nil { - return - } - _, err = fcntl(p[1], F_SETFD, FD_CLOEXEC) - } - return + return Pipe2(p, O_CLOEXEC) } func formatIDMappings(idMap []SysProcIDMap) []byte { -- GitLab From 17e9d148d3354f8da745e6533213ca5b348b719e Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 1 Sep 2021 15:24:01 +0200 Subject: [PATCH 0967/2500] syscall: drop fallback to utimes in UtimesNano on Linux The minimum required Linux kernel version for Go 1.18 will be changed to 2.6.32, see #45964. The current minimum required version is 2.6.23 and utimensat was added in 2.6.22, so the fallback isn't even necessary for the current minimum supported version. Remove the fallback to utimes. For #45964 Change-Id: I5536f6ea7a34944dd9165f1533c10692171fb0c5 Reviewed-on: https://go-review.googlesource.com/c/go/+/346790 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/syscall/syscall_linux.go | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go index dfce3d0a4b..a2dba54b97 100644 --- a/src/syscall/syscall_linux.go +++ b/src/syscall/syscall_linux.go @@ -204,18 +204,7 @@ func UtimesNano(path string, ts []Timespec) (err error) { if len(ts) != 2 { return EINVAL } - err = utimensat(_AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) - if err != ENOSYS { - return err - } - // If the utimensat syscall isn't available (utimensat was added to Linux - // in 2.6.22, Released, 8 July 2007) then fall back to utimes - var tv [2]Timeval - for i := 0; i < 2; i++ { - tv[i].Sec = ts[i].Sec - tv[i].Usec = ts[i].Nsec / 1000 - } - return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) + return utimensat(_AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) } func Futimesat(dirfd int, path string, tv []Timeval) (err error) { -- GitLab From 6705191e02d7e5e849a7877928003b797e0bc4f6 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 1 Sep 2021 15:50:27 +0200 Subject: [PATCH 0968/2500] syscall: drop fallback to accept in Accept on Linux The minimum required Linux kernel version for Go 1.18 will be changed to 2.6.32, see #45964. The current minimum required version is 2.6.23 and accept4 was added in 2.6.28, so the fallback to accept in Accept on Linux can be removed. For #45964 Change-Id: I78fc4e5b58417bbc540912c9dbf1b1b3db888fea Reviewed-on: https://go-review.googlesource.com/c/go/+/346849 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/syscall/syscall_linux.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go index a2dba54b97..6d428d58dd 100644 --- a/src/syscall/syscall_linux.go +++ b/src/syscall/syscall_linux.go @@ -542,11 +542,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { func Accept(fd int) (nfd int, sa Sockaddr, err error) { var rsa RawSockaddrAny var len _Socklen = SizeofSockaddrAny - // Try accept4 first for Android, then try accept for kernel older than 2.6.28 nfd, err = accept4(fd, &rsa, &len, 0) - if err == ENOSYS { - nfd, err = accept(fd, &rsa, &len) - } if err != nil { return } -- GitLab From 08e2519ded32a1a7d4e6056406c356b4496ca24a Mon Sep 17 00:00:00 2001 From: Leonard Wang Date: Sun, 29 Aug 2021 00:53:00 +0800 Subject: [PATCH 0969/2500] cmd/compile: workaround inlining of closures with range statements ORANGE is still not inlineable now. This CL is correct only when the range statement is statically dead, and thus not counted during the inline budget check. If we support range statements in inlining closures in the future, may require additional processing. Fixes #48033. Change-Id: I28f5755c28cfa27e41daef9eff2ae332059909bb Reviewed-on: https://go-review.googlesource.com/c/go/+/345436 Trust: Cherry Mui Reviewed-by: Keith Randall --- src/cmd/compile/internal/inline/inl.go | 2 ++ test/fixedbugs/issue48033.go | 40 ++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 test/fixedbugs/issue48033.go diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index 45a533fcaf..d50d8b3516 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -1061,6 +1061,8 @@ func (subst *inlsubst) clovar(n *ir.Name) *ir.Name { m.Defn = &subst.defnMarker case *ir.TypeSwitchGuard: // TODO(mdempsky): Set m.Defn properly. See discussion on #45743. + case *ir.RangeStmt: + // TODO: Set m.Defn properly if we support inlining range statement in the future. default: base.FatalfAt(n.Pos(), "unexpected Defn: %+v", defn) } diff --git a/test/fixedbugs/issue48033.go b/test/fixedbugs/issue48033.go new file mode 100644 index 0000000000..044b98c9bc --- /dev/null +++ b/test/fixedbugs/issue48033.go @@ -0,0 +1,40 @@ +// compile + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + "strings" +) + +type app struct { + Name string +} + +func bug() func() { + return func() { + + // the issue is this if true block + if true { + return + } + + var xx = []app{} + var gapp app + for _, app := range xx { + if strings.ToUpper("") == app.Name { + fmt.Printf("%v\n", app) + gapp = app + } + } + fmt.Println(gapp) + } +} + +func main() { + bug() +} -- GitLab From 69107e73cedb600187c5924247cdd0cf8f74070a Mon Sep 17 00:00:00 2001 From: Xargin Date: Wed, 28 Jul 2021 20:40:07 +0000 Subject: [PATCH 0970/2500] runtime: change 0 to pollNoError in netpollblock Change-Id: I95e91ff21420e396aef876e77bc4ccdc45ab40ca GitHub-Last-Rev: 8e6bd3f002b1c29fed8ce1bd344f7727e8580555 GitHub-Pull-Request: golang/go#47372 Reviewed-on: https://go-review.googlesource.com/c/go/+/337249 Reviewed-by: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot Trust: Cherry Mui --- src/runtime/netpoll.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/netpoll.go b/src/runtime/netpoll.go index 6c26fdbbeb..239371158f 100644 --- a/src/runtime/netpoll.go +++ b/src/runtime/netpoll.go @@ -441,7 +441,7 @@ func netpollblock(pd *pollDesc, mode int32, waitio bool) bool { // need to recheck error states after setting gpp to pdWait // this is necessary because runtime_pollUnblock/runtime_pollSetDeadline/deadlineimpl // do the opposite: store to closing/rd/wd, membarrier, load of rg/wg - if waitio || netpollcheckerr(pd, mode) == 0 { + if waitio || netpollcheckerr(pd, mode) == pollNoError { gopark(netpollblockcommit, unsafe.Pointer(gpp), waitReasonIOWait, traceEvGoBlockNet, 5) } // be careful to not lose concurrent pdReady notification -- GitLab From 90ed541149c781a96b86060a7618f73dcf347f28 Mon Sep 17 00:00:00 2001 From: Hans Date: Wed, 28 Jul 2021 05:57:25 +0000 Subject: [PATCH 0971/2500] runtime: ensure the fixalloc object size is valid Usually, fixalloc is used to allocate small, persistent and reuseable objects. The size is typically between range [sizeof(mlink), _FixAllocChunk]. It's rare for being out of the range. But if it did happen, we got a hard-to-discover memory corruption. This commit prevents that situation by limiting object's size. Change-Id: If6ef8b0831596464e0f55d09f79094b79ae08c66 GitHub-Last-Rev: cb8b1b01bbf452195f4f098d53cca74affc496ff GitHub-Pull-Request: golang/go#47395 Reviewed-on: https://go-review.googlesource.com/c/go/+/337429 Reviewed-by: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot Trust: Cherry Mui --- src/runtime/mfixalloc.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/runtime/mfixalloc.go b/src/runtime/mfixalloc.go index 293c16b38b..a81139a389 100644 --- a/src/runtime/mfixalloc.go +++ b/src/runtime/mfixalloc.go @@ -50,6 +50,13 @@ type mlink struct { // Initialize f to allocate objects of the given size, // using the allocator to obtain chunks of memory. func (f *fixalloc) init(size uintptr, first func(arg, p unsafe.Pointer), arg unsafe.Pointer, stat *sysMemStat) { + if size > _FixAllocChunk { + throw("runtime: fixalloc size too large") + } + if min := unsafe.Sizeof(mlink{}); size < min { + size = min + } + f.size = size f.first = first f.arg = arg -- GitLab From a35c5c98c0487f93d70b468483f2ca8e0d698bb7 Mon Sep 17 00:00:00 2001 From: Carlo Alberto Ferraris Date: Sun, 25 Jul 2021 23:15:15 +0000 Subject: [PATCH 0972/2500] runtime: constify a test variable Simple cleanup, no functionality change. Change-Id: I8eceda4496a396e0117a0a601186c653982fb004 GitHub-Last-Rev: 58defc575e5834a3685bbb8179fdee4afa8d8fc7 GitHub-Pull-Request: golang/go#47389 Reviewed-on: https://go-review.googlesource.com/c/go/+/337289 Reviewed-by: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot Trust: Cherry Mui --- src/runtime/export_test.go | 2 +- src/runtime/map_test.go | 2 +- src/runtime/stubs.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index e7279564e3..01fd1dbd97 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -198,7 +198,7 @@ func MemclrBytes(b []byte) { memclrNoHeapPointers(s.array, uintptr(s.len)) } -var HashLoad = &hashLoad +const HashLoad = hashLoad // entry point for testing func GostringW(w []uint16) (s string) { diff --git a/src/runtime/map_test.go b/src/runtime/map_test.go index 24556b4093..f78cad5a77 100644 --- a/src/runtime/map_test.go +++ b/src/runtime/map_test.go @@ -473,7 +473,7 @@ func TestMapNanGrowIterator(t *testing.T) { nan := math.NaN() const nBuckets = 16 // To fill nBuckets buckets takes LOAD * nBuckets keys. - nKeys := int(nBuckets * *runtime.HashLoad) + nKeys := int(nBuckets * runtime.HashLoad) // Get map to full point with nan keys. for i := 0; i < nKeys; i++ { diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go index 8a520d7839..c85b7d7330 100644 --- a/src/runtime/stubs.go +++ b/src/runtime/stubs.go @@ -119,7 +119,7 @@ func reflect_memmove(to, from unsafe.Pointer, n uintptr) { } // exported value for testing -var hashLoad = float32(loadFactorNum) / float32(loadFactorDen) +const hashLoad = float32(loadFactorNum) / float32(loadFactorDen) //go:nosplit func fastrand() uint32 { -- GitLab From 4591f49938aedbbac7a24225047984479abe72b8 Mon Sep 17 00:00:00 2001 From: Hans Date: Mon, 2 Aug 2021 05:43:29 +0000 Subject: [PATCH 0973/2500] runtime: do not alloc never used tail bytes in fixalloc Currently, the '_FixAllocChunk % fixalloc.size' tail bytes will never be used when allocing from persistentalloc. Wasted bytes on darwin/amd64: _FixAllocChunk % mheap_.spanalloc.size = 64 _FixAllocChunk % mheap_.cachealloc.size = 784 _FixAllocChunk % mheap_.specialfinalizeralloc.size = 16 _FixAllocChunk % mheap_.specialprofilealloc.size = 16 _FixAllocChunk % mheap_.specialReachableAlloc.size = 16 _FixAllocChunk % mheap_.arenaHintAlloc.size = 16 After this commit, fixalloc alloc '_FixAllocChunk / fixalloc.size' objects exactly with zero waste. Sizeof(fixalloc{}) is unchanged. Change-Id: Ifc551f5b7aa9d842fa559abbe532ffcfb4d3540c GitHub-Last-Rev: e08b4c66b82bc7be9d14fb7eb7580504d777481e GitHub-Pull-Request: golang/go#47439 Reviewed-on: https://go-review.googlesource.com/c/go/+/338090 Reviewed-by: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot Trust: Cherry Mui --- src/runtime/mfixalloc.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/runtime/mfixalloc.go b/src/runtime/mfixalloc.go index a81139a389..b701a09b40 100644 --- a/src/runtime/mfixalloc.go +++ b/src/runtime/mfixalloc.go @@ -30,7 +30,8 @@ type fixalloc struct { arg unsafe.Pointer list *mlink chunk uintptr // use uintptr instead of unsafe.Pointer to avoid write barriers - nchunk uint32 + nchunk uint32 // bytes remaining in current chunk + nalloc uint32 // size of new chunks in bytes inuse uintptr // in-use bytes now stat *sysMemStat zero bool // zero allocations @@ -63,6 +64,7 @@ func (f *fixalloc) init(size uintptr, first func(arg, p unsafe.Pointer), arg uns f.list = nil f.chunk = 0 f.nchunk = 0 + f.nalloc = uint32(_FixAllocChunk / size * size) // Round _FixAllocChunk down to an exact multiple of size to eliminate tail waste f.inuse = 0 f.stat = stat f.zero = true @@ -84,8 +86,8 @@ func (f *fixalloc) alloc() unsafe.Pointer { return v } if uintptr(f.nchunk) < f.size { - f.chunk = uintptr(persistentalloc(_FixAllocChunk, 0, f.stat)) - f.nchunk = _FixAllocChunk + f.chunk = uintptr(persistentalloc(uintptr(f.nalloc), 0, f.stat)) + f.nchunk = f.nalloc } v := unsafe.Pointer(f.chunk) -- GitLab From b8420baf4610e71f6893f7e8b1ad2b6aa94f3eef Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 1 Sep 2021 14:15:05 -0400 Subject: [PATCH 0974/2500] go/internal/gcimporter: add support for importing parameterized types Port the necessary logic to go/internal/gcimporter from cmd/compile/internal/importer/iimport.go to support type parameters. This is a partial port of several compiler CLs: at least CL 319930, CL 322609, CL 323029, CL 338192, CL 340251, and CL 340989. Because these ports were not interleaved with the corresponding go/types API changes, it is easier to just take the latest importer logic. Notably, the equivalent of types2.AsTypeParam is not used. It should be unnecessary. Updates #48101 Change-Id: I938bd8debc3f6a68a3ad8d44c61ef9c5038be7e5 Reviewed-on: https://go-review.googlesource.com/c/go/+/347069 Trust: Robert Findley Trust: Dan Scales Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Dan Scales Reviewed-by: Robert Griesemer --- src/go/internal/gcimporter/gcimporter_test.go | 1 - src/go/internal/gcimporter/iimport.go | 159 ++++++++++++++++-- 2 files changed, 144 insertions(+), 16 deletions(-) diff --git a/src/go/internal/gcimporter/gcimporter_test.go b/src/go/internal/gcimporter/gcimporter_test.go index 286b8a6347..3c76aafde3 100644 --- a/src/go/internal/gcimporter/gcimporter_test.go +++ b/src/go/internal/gcimporter/gcimporter_test.go @@ -138,7 +138,6 @@ func TestVersionHandling(t *testing.T) { skipSpecialPlatforms(t) // This package only handles gc export data. - // Disable test until we put in the new export version. if runtime.Compiler != "gc" { t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) } diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go index dbc9b3a83e..444cf3b0d4 100644 --- a/src/go/internal/gcimporter/iimport.go +++ b/src/go/internal/gcimporter/iimport.go @@ -51,6 +51,11 @@ const ( iexportVersionCurrent = iexportVersionGenerics ) +type ident struct { + pkg string + name string +} + const predeclReserved = 32 type itag uint64 @@ -68,6 +73,7 @@ const ( interfaceType typeParamType instType + unionType ) // iImportData imports a package from the serialized package data @@ -122,6 +128,9 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, dataRea declData: declData, pkgIndex: make(map[*types.Package]map[string]uint64), typCache: make(map[uint64]types.Type), + // Separate map for typeparams, keyed by their package and unique + // name (name with subscript). + tparamIndex: make(map[ident]types.Type), fake: fakeFileSet{ fset: fset, @@ -197,9 +206,10 @@ type iimporter struct { stringCache map[uint64]string pkgCache map[uint64]*types.Package - declData []byte - pkgIndex map[*types.Package]map[string]uint64 - typCache map[uint64]types.Type + declData []byte + pkgIndex map[*types.Package]map[string]uint64 + typCache map[uint64]types.Type + tparamIndex map[ident]types.Type fake fakeFileSet interfaceList []*types.Interface @@ -289,19 +299,28 @@ func (r *importReader) obj(name string) { r.declare(types.NewConst(pos, r.currPkg, name, typ, val)) - case 'F': + case 'F', 'G': + var tparams []*types.TypeParam + if tag == 'G' { + tparams = r.tparamList() + } sig := r.signature(nil) - + sig.SetTParams(tparams) r.declare(types.NewFunc(pos, r.currPkg, name, sig)) - case 'G': - errorf("unexpected parameterized function/method") - - case 'T': + case 'T', 'U': + var tparams []*types.TypeParam + if tag == 'U' { + tparams = r.tparamList() + } // Types can be recursive. We need to setup a stub // declaration before recursing. obj := types.NewTypeName(pos, r.currPkg, name, nil) named := types.NewNamed(obj, nil, nil) + // TODO(rfindley): guarding on tag == 'U' should not be necessary here. + if tag == 'U' { + named.SetTParams(tparams) + } r.declare(obj) underlying := r.p.typAt(r.uint64(), named).Underlying() @@ -314,12 +333,45 @@ func (r *importReader) obj(name string) { recv := r.param() msig := r.signature(recv) + // If the receiver has any targs, set those as the + // rparams of the method (since those are the + // typeparams being used in the method sig/body). + targs := baseType(msig.Recv().Type()).TArgs() + if targs.Len() > 0 { + rparams := make([]*types.TypeParam, targs.Len()) + for i := range rparams { + rparams[i], _ = targs.At(i).(*types.TypeParam) + } + msig.SetRParams(rparams) + } + named.AddMethod(types.NewFunc(mpos, r.currPkg, mname, msig)) } } - case 'U': - errorf("unexpected parameterized type") + case 'P': + // We need to "declare" a typeparam in order to have a name that + // can be referenced recursively (if needed) in the type param's + // bound. + if r.p.exportVersion < iexportVersionGenerics { + errorf("unexpected type param type") + } + name0, sub := parseSubscript(name) + tn := types.NewTypeName(pos, r.currPkg, name0, nil) + t := (*types.Checker)(nil).NewTypeParam(tn, nil) + if sub == 0 { + errorf("missing subscript") + } + + // TODO(rfindley): can we use a different, stable ID? + // t.SetId(sub) + + // To handle recursive references to the typeparam within its + // bound, save the partial type in tparamIndex before reading the bounds. + id := ident{r.currPkg.Name(), name} + r.p.tparamIndex[id] = t + + t.SetConstraint(r.typ()) case 'V': typ := r.typ() @@ -575,12 +627,47 @@ func (r *importReader) doType(base *types.Named) types.Type { return typ case typeParamType: - errorf("do not handle type param types yet") - return nil + if r.p.exportVersion < iexportVersionGenerics { + errorf("unexpected type param type") + } + pkg, name := r.qualifiedIdent() + id := ident{pkg.Name(), name} + if t, ok := r.p.tparamIndex[id]; ok { + // We're already in the process of importing this typeparam. + return t + } + // Otherwise, import the definition of the typeparam now. + r.p.doDecl(pkg, name) + return r.p.tparamIndex[id] case instType: - errorf("do not handle instantiated types yet") - return nil + if r.p.exportVersion < iexportVersionGenerics { + errorf("unexpected instantiation type") + } + // pos does not matter for instances: they are positioned on the original + // type. + _ = r.pos() + len := r.uint64() + targs := make([]types.Type, len) + for i := range targs { + targs[i] = r.typ() + } + baseType := r.typ() + // The imported instantiated type doesn't include any methods, so + // we must always use the methods of the base (orig) type. + // TODO provide a non-nil *Checker + t, _ := types.Instantiate(nil, baseType, targs, false) + return t + + case unionType: + if r.p.exportVersion < iexportVersionGenerics { + errorf("unexpected instantiation type") + } + terms := make([]*types.Term, r.uint64()) + for i := range terms { + terms[i] = types.NewTerm(r.bool(), r.typ()) + } + return types.NewUnion(terms) } } @@ -595,6 +682,18 @@ func (r *importReader) signature(recv *types.Var) *types.Signature { return types.NewSignature(recv, params, results, variadic) } +func (r *importReader) tparamList() []*types.TypeParam { + n := r.uint64() + if n == 0 { + return nil + } + xs := make([]*types.TypeParam, n) + for i := range xs { + xs[i], _ = r.typ().(*types.TypeParam) + } + return xs +} + func (r *importReader) paramList() *types.Tuple { xs := make([]*types.Var, r.uint64()) for i := range xs { @@ -637,3 +736,33 @@ func (r *importReader) byte() byte { } return x } + +func baseType(typ types.Type) *types.Named { + // pointer receivers are never types.Named types + if p, _ := typ.(*types.Pointer); p != nil { + typ = p.Elem() + } + // receiver base types are always (possibly generic) types.Named types + n, _ := typ.(*types.Named) + return n +} + +func parseSubscript(name string) (string, uint64) { + // Extract the subscript value from the type param name. We export + // and import the subscript value, so that all type params have + // unique names. + sub := uint64(0) + startsub := -1 + for i, r := range name { + if '₀' <= r && r < '₀'+10 { + if startsub == -1 { + startsub = i + } + sub = sub*10 + uint64(r-'₀') + } + } + if startsub >= 0 { + name = name[:startsub] + } + return name, sub +} -- GitLab From 4fb79569d2fb7a0eabc88729f400addb0162f21e Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 1 Sep 2021 16:51:17 -0400 Subject: [PATCH 0975/2500] go/internal/gcimporter: add import tests for type parameters Add a new test TestImportTypeparamTests that compiles and imports packages contained in test/typeparam, and compares the resulting package scope with the scope produced by type-checking directly. In the process, fix a bug in go/types affecting embedded instances with more than one type argument. This was uncovered by smoketest.go. To enable this new test it was easiest to move gcimporter_test.go to an external test, which required copying the pkgExts variable. Fixes #48101 Change-Id: Ie4d981bf463e886a8d141809805d184dbbf64607 Reviewed-on: https://go-review.googlesource.com/c/go/+/347070 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/internal/gcimporter/gcimporter_test.go | 133 +++++++++++++++++- src/go/types/struct.go | 2 + 2 files changed, 134 insertions(+), 1 deletion(-) diff --git a/src/go/internal/gcimporter/gcimporter_test.go b/src/go/internal/gcimporter/gcimporter_test.go index 3c76aafde3..9f4345d8f9 100644 --- a/src/go/internal/gcimporter/gcimporter_test.go +++ b/src/go/internal/gcimporter/gcimporter_test.go @@ -2,11 +2,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package gcimporter +package gcimporter_test import ( "bytes" "fmt" + "internal/goexperiment" "internal/testenv" "os" "os/exec" @@ -16,8 +17,13 @@ import ( "testing" "time" + "go/ast" + "go/importer" + "go/parser" "go/token" "go/types" + + . "go/internal/gcimporter" ) // skipSpecialPlatforms causes the test to be skipped for platforms where @@ -63,6 +69,8 @@ func testPath(t *testing.T, path, srcDir string) *types.Package { const maxTime = 30 * time.Second +var pkgExts = [...]string{".a", ".o"} // keep in sync with gcimporter.go + func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) { dirname := filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_"+runtime.GOARCH, dir) list, err := os.ReadDir(dirname) @@ -134,6 +142,129 @@ func TestImportTestdata(t *testing.T) { } } +func TestImportTypeparamTests(t *testing.T) { + // This test doesn't yet work with the unified export format. + if goexperiment.Unified { + t.Skip("unified export data format is currently unsupported") + } + + // This package only handles gc export data. + if runtime.Compiler != "gc" { + t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) + } + + tmpdir := mktmpdir(t) + defer os.RemoveAll(tmpdir) + + // Check go files in test/typeparam, except those that fail for a known + // reason. + rootDir := filepath.Join(runtime.GOROOT(), "test", "typeparam") + list, err := os.ReadDir(rootDir) + if err != nil { + t.Fatal(err) + } + + skip := map[string]string{ + "equal.go": "inconsistent embedded sorting", // TODO(rfindley): investigate this. + "nested.go": "fails to compile", // TODO(rfindley): investigate this. + } + + for _, entry := range list { + if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".go") { + // For now, only consider standalone go files. + continue + } + + t.Run(entry.Name(), func(t *testing.T) { + if reason, ok := skip[entry.Name()]; ok { + t.Skip(reason) + } + + filename := filepath.Join(rootDir, entry.Name()) + src, err := os.ReadFile(filename) + if err != nil { + t.Fatal(err) + } + if !bytes.HasPrefix(src, []byte("// run")) && !bytes.HasPrefix(src, []byte("// compile")) { + // We're bypassing the logic of run.go here, so be conservative about + // the files we consider in an attempt to make this test more robust to + // changes in test/typeparams. + t.Skipf("not detected as a run test") + } + + // Compile and import, and compare the resulting package with the package + // that was type-checked directly. + compile(t, rootDir, entry.Name(), filepath.Join(tmpdir, "testdata")) + pkgName := strings.TrimSuffix(entry.Name(), ".go") + imported := importPkg(t, "./testdata/"+pkgName, tmpdir) + checked := checkFile(t, filename, src) + + seen := make(map[string]bool) + for _, name := range imported.Scope().Names() { + if !token.IsExported(name) { + continue // ignore synthetic names like .inittask and .dict.* + } + seen[name] = true + + importedObj := imported.Scope().Lookup(name) + got := types.ObjectString(importedObj, types.RelativeTo(imported)) + got = sanitizeObjectString(got) + + checkedObj := checked.Scope().Lookup(name) + if checkedObj == nil { + t.Fatalf("imported object %q was not type-checked", name) + } + want := types.ObjectString(checkedObj, types.RelativeTo(checked)) + want = sanitizeObjectString(want) + + if got != want { + t.Errorf("imported %q as %q, want %q", name, got, want) + } + } + + for _, name := range checked.Scope().Names() { + if !token.IsExported(name) || seen[name] { + continue + } + t.Errorf("did not import object %q", name) + } + }) + } +} + +// sanitizeObjectString removes type parameter debugging markers from an object +// string, to normalize it for comparison. +// TODO(rfindley): this should not be necessary. +func sanitizeObjectString(s string) string { + var runes []rune + for _, r := range s { + if r == '#' { + continue // trim instance markers + } + if '₀' <= r && r < '₀'+10 { + continue // trim type parameter subscripts + } + runes = append(runes, r) + } + return string(runes) +} + +func checkFile(t *testing.T, filename string, src []byte) *types.Package { + fset := token.NewFileSet() + f, err := parser.ParseFile(fset, filename, src, 0) + if err != nil { + t.Fatal(err) + } + config := types.Config{ + Importer: importer.Default(), + } + pkg, err := config.Check("", fset, []*ast.File{f}, nil) + if err != nil { + t.Fatal(err) + } + return pkg +} + func TestVersionHandling(t *testing.T) { skipSpecialPlatforms(t) diff --git a/src/go/types/struct.go b/src/go/types/struct.go index 48b07346dc..f6e6f2a5e6 100644 --- a/src/go/types/struct.go +++ b/src/go/types/struct.go @@ -176,6 +176,8 @@ func embeddedFieldIdent(e ast.Expr) *ast.Ident { return e.Sel case *ast.IndexExpr: return embeddedFieldIdent(e.X) + case *ast.MultiIndexExpr: + return embeddedFieldIdent(e.X) } return nil // invalid embedded field } -- GitLab From 37d4532867b9c49f936cb8e394dec44d8985fe29 Mon Sep 17 00:00:00 2001 From: Ben Shi Date: Thu, 2 Sep 2021 00:06:42 +0000 Subject: [PATCH 0976/2500] cmd/internal/obj/riscv: simplify addition with constant This CL simplifies riscv addition (add r, imm) to (ADDI (ADDI r, imm/2), imm-imm/2) if imm is in specific ranges. (-4096 <= imm <= -2049 or 2048 <= imm <= 4094) There is little impact to the go1 benchmark, while the total size of pkg/linux_riscv64 decreased by about 11KB. Change-Id: I236eb8af3b83bb35ce9c0b318fc1d235e8ab9a4e GitHub-Last-Rev: a2f56a07635344a40d6b8a9571f236743122be34 GitHub-Pull-Request: golang/go#48110 Reviewed-on: https://go-review.googlesource.com/c/go/+/346689 Run-TryBot: Ben Shi TryBot-Result: Go Bot Reviewed-by: Joel Sing Reviewed-by: Cherry Mui Reviewed-by: Keith Randall Trust: Michael Munday --- src/cmd/internal/obj/riscv/obj.go | 21 +++++++++++++++++++++ test/codegen/arithmetic.go | 8 ++++++++ 2 files changed, 29 insertions(+) diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index 73f62c007d..6de967319c 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -774,6 +774,27 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { break // no need to split } + // Split into two additions if possible. + imm := q.From.Offset + const minInt12, maxInt12 = -(1 << 11), (1 << 11) - 1 + if q.As == AADDI && 2*minInt12 <= imm && imm <= 2*maxInt12 { + imm0, imm1 := imm/2, imm-imm/2 + // ADDI $(imm/2), REG, TO + p.Spadj = 0 // needed if TO is SP + p.As = AADDI + p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: imm0} + p.Reg = q.Reg + p.To = q.To + p = obj.Appendp(p, newprog) + // ADDI $(imm-imm/2), TO, TO + p.Spadj = q.Spadj + p.As = AADDI + p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: imm1} + p.Reg = q.To.Reg + p.To = q.To + break + } + p.As = ALUI p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: high} p.Reg = 0 diff --git a/test/codegen/arithmetic.go b/test/codegen/arithmetic.go index eb95416b6a..754c5c9bc9 100644 --- a/test/codegen/arithmetic.go +++ b/test/codegen/arithmetic.go @@ -575,3 +575,11 @@ func constantFold3(i, j int) int { r := (5 * i) * (6 * j) return r } + +func addConst(i int64) (int64, int64) { + // riscv64:`ADDI`,-`LUI` + a := i + 3001 + // riscv64:`LUI`,`ADDIW` + b := i + 5009 + return a, b +} -- GitLab From 014a9720f9526563ea5d9bff3d4d2d47b4e7752d Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Thu, 26 Aug 2021 15:59:36 -0400 Subject: [PATCH 0977/2500] cmd/link: avoid crash on undefined func sym with external linking Fix a buglet in relocation processing that crops up with external linking when you have an undefined function symbol that also has a prototype (as if it were being defined in assembly src). Fixes #47993. Change-Id: Ib655492a63b205ffdc124cfd0cb7f7b731571821 Reviewed-on: https://go-review.googlesource.com/c/go/+/345473 Trust: Than McIntosh Run-TryBot: Than McIntosh Reviewed-by: Austin Clements Reviewed-by: Cherry Mui Reviewed-by: Jeremy Faller --- .../testdata/script/link_external_undef.txt | 48 +++++++++++++++++++ src/cmd/link/internal/ld/data.go | 5 ++ 2 files changed, 53 insertions(+) create mode 100644 src/cmd/go/testdata/script/link_external_undef.txt diff --git a/src/cmd/go/testdata/script/link_external_undef.txt b/src/cmd/go/testdata/script/link_external_undef.txt new file mode 100644 index 0000000000..d86b3a374e --- /dev/null +++ b/src/cmd/go/testdata/script/link_external_undef.txt @@ -0,0 +1,48 @@ + +# Test case for issue 47993, in which the linker crashes +# on a bad input instead of issuing an error and exiting. + +# This test requires external linking, so use cgo as a proxy +[!cgo] skip + +! go build -ldflags='-linkmode=external' . +! stderr 'panic' +stderr '^.*unreachable sym in relocation.*' + +-- go.mod -- + +module issue47993 + +go 1.16 + +-- main.go -- + +package main + +type M struct { + b bool +} + +// Note the body-less func def here. This is what causes the problems. +func (m *M) run(fp func()) + +func doit(m *M) { + InAsm() + m.run(func() { + }) +} + +func main() { + m := &M{true} + doit(m) +} + +func InAsm() + +-- main.s -- + +// Add an assembly function so as to leave open the possibility +// that body-less functions in Go might be defined in assembly. + +// Currently we just need an empty file here. + diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 70fbb9dc4e..e0591c3959 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -436,6 +436,11 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) { if weak && !ldr.AttrReachable(rs) { continue } + if ldr.SymSect(rs) == nil { + st.err.Errorf(s, "unreachable sym in relocation: %s", ldr.SymName(rs)) + continue + } + // The method offset tables using this relocation expect the offset to be relative // to the start of the first text section, even if there are multiple. if ldr.SymSect(rs).Name == ".text" { -- GitLab From d8b156773c51e34af9792646ea283c292ba3b048 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Wed, 1 Sep 2021 19:59:20 -0400 Subject: [PATCH 0978/2500] all: update vendored golang.org/x/sys Ran the following commands inside std and cmd modules: go get -d golang.org/x/sys@f4d43177bf5e2ee98617956e417d0555d4b69c17 # master go mod tidy go mod vendor Followed by the following command in std module: go generate syscall internal/syscall/... For #36905. Change-Id: I53d6ba03246372b6f7abd5ac57dbb71715d6eb4a Reviewed-on: https://go-review.googlesource.com/c/go/+/347189 Run-TryBot: Dmitri Shuralyov TryBot-Result: Go Bot Reviewed-by: Carlos Amedee Trust: Dmitri Shuralyov --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 +- .../vendor/golang.org/x/sys/unix/README.md | 6 +- .../golang.org/x/sys/unix/asm_bsd_386.s | 4 +- .../golang.org/x/sys/unix/asm_bsd_arm.s | 4 +- .../golang.org/x/sys/unix/ifreq_linux.go | 149 ++++ .../golang.org/x/sys/unix/ioctl_linux.go | 78 +- .../vendor/golang.org/x/sys/unix/mkerrors.sh | 13 +- .../golang.org/x/sys/unix/syscall_darwin.go | 33 + .../golang.org/x/sys/unix/syscall_linux.go | 95 ++- .../x/sys/unix/syscall_linux_386.go | 8 +- .../x/sys/unix/syscall_linux_amd64.go | 4 + .../x/sys/unix/syscall_linux_arm.go | 8 +- .../x/sys/unix/syscall_linux_arm64.go | 8 +- .../x/sys/unix/syscall_linux_mips64x.go | 4 + .../x/sys/unix/syscall_linux_mipsx.go | 8 +- .../x/sys/unix/syscall_linux_ppc.go | 11 +- .../x/sys/unix/syscall_linux_ppc64x.go | 4 + .../x/sys/unix/syscall_linux_riscv64.go | 4 + .../x/sys/unix/syscall_linux_s390x.go | 4 + .../x/sys/unix/syscall_linux_sparc64.go | 4 + .../golang.org/x/sys/unix/syscall_solaris.go | 240 ++++++ .../golang.org/x/sys/unix/syscall_unix.go | 4 + .../x/sys/unix/zerrors_darwin_amd64.go | 6 + .../x/sys/unix/zerrors_darwin_arm64.go | 6 + .../x/sys/unix/zerrors_freebsd_386.go | 5 + .../x/sys/unix/zerrors_freebsd_amd64.go | 5 + .../x/sys/unix/zerrors_freebsd_arm.go | 5 + .../x/sys/unix/zerrors_freebsd_arm64.go | 5 + .../golang.org/x/sys/unix/zerrors_linux.go | 150 +++- .../x/sys/unix/zerrors_linux_386.go | 21 + .../x/sys/unix/zerrors_linux_amd64.go | 21 + .../x/sys/unix/zerrors_linux_arm.go | 21 + .../x/sys/unix/zerrors_linux_arm64.go | 21 + .../x/sys/unix/zerrors_linux_mips.go | 21 + .../x/sys/unix/zerrors_linux_mips64.go | 21 + .../x/sys/unix/zerrors_linux_mips64le.go | 21 + .../x/sys/unix/zerrors_linux_mipsle.go | 21 + .../x/sys/unix/zerrors_linux_ppc.go | 21 + .../x/sys/unix/zerrors_linux_ppc64.go | 21 + .../x/sys/unix/zerrors_linux_ppc64le.go | 21 + .../x/sys/unix/zerrors_linux_riscv64.go | 21 + .../x/sys/unix/zerrors_linux_s390x.go | 21 + .../x/sys/unix/zerrors_linux_sparc64.go | 21 + .../x/sys/unix/zerrors_openbsd_386.go | 3 + .../x/sys/unix/zerrors_openbsd_arm.go | 3 + .../golang.org/x/sys/unix/zsyscall_linux.go | 12 +- .../x/sys/unix/zsyscall_solaris_amd64.go | 72 +- .../x/sys/unix/zsysnum_linux_386.go | 5 + .../x/sys/unix/zsysnum_linux_amd64.go | 713 ++++++++-------- .../x/sys/unix/zsysnum_linux_arm.go | 4 + .../x/sys/unix/zsysnum_linux_arm64.go | 603 ++++++------- .../x/sys/unix/zsysnum_linux_mips.go | 4 + .../x/sys/unix/zsysnum_linux_mips64.go | 698 +++++++-------- .../x/sys/unix/zsysnum_linux_mips64le.go | 698 +++++++-------- .../x/sys/unix/zsysnum_linux_mipsle.go | 4 + .../x/sys/unix/zsysnum_linux_ppc.go | 4 + .../x/sys/unix/zsysnum_linux_ppc64.go | 796 +++++++++--------- .../x/sys/unix/zsysnum_linux_ppc64le.go | 796 +++++++++--------- .../x/sys/unix/zsysnum_linux_riscv64.go | 600 ++++++------- .../x/sys/unix/zsysnum_linux_s390x.go | 726 ++++++++-------- .../x/sys/unix/zsysnum_linux_sparc64.go | 754 ++++++++--------- .../x/sys/unix/ztypes_darwin_amd64.go | 104 +++ .../x/sys/unix/ztypes_darwin_arm64.go | 104 +++ .../x/sys/unix/ztypes_dragonfly_amd64.go | 3 + .../x/sys/unix/ztypes_freebsd_386.go | 5 +- .../x/sys/unix/ztypes_freebsd_amd64.go | 5 +- .../x/sys/unix/ztypes_freebsd_arm.go | 5 +- .../x/sys/unix/ztypes_freebsd_arm64.go | 5 +- .../golang.org/x/sys/unix/ztypes_linux.go | 195 ++++- .../golang.org/x/sys/unix/ztypes_linux_386.go | 23 +- .../x/sys/unix/ztypes_linux_amd64.go | 23 +- .../golang.org/x/sys/unix/ztypes_linux_arm.go | 23 +- .../x/sys/unix/ztypes_linux_arm64.go | 23 +- .../x/sys/unix/ztypes_linux_mips.go | 23 +- .../x/sys/unix/ztypes_linux_mips64.go | 23 +- .../x/sys/unix/ztypes_linux_mips64le.go | 23 +- .../x/sys/unix/ztypes_linux_mipsle.go | 23 +- .../golang.org/x/sys/unix/ztypes_linux_ppc.go | 23 +- .../x/sys/unix/ztypes_linux_ppc64.go | 23 +- .../x/sys/unix/ztypes_linux_ppc64le.go | 23 +- .../x/sys/unix/ztypes_linux_riscv64.go | 23 +- .../x/sys/unix/ztypes_linux_s390x.go | 23 +- .../x/sys/unix/ztypes_linux_sparc64.go | 23 +- .../x/sys/unix/ztypes_netbsd_386.go | 4 +- .../x/sys/unix/ztypes_netbsd_amd64.go | 4 +- .../x/sys/unix/ztypes_netbsd_arm.go | 4 +- .../x/sys/unix/ztypes_netbsd_arm64.go | 4 +- .../x/sys/unix/ztypes_openbsd_386.go | 4 +- .../x/sys/unix/ztypes_openbsd_amd64.go | 4 +- .../x/sys/unix/ztypes_openbsd_arm.go | 4 +- .../x/sys/unix/ztypes_openbsd_arm64.go | 4 +- .../x/sys/unix/ztypes_openbsd_mips64.go | 4 +- .../x/sys/unix/ztypes_solaris_amd64.go | 40 + .../golang.org/x/sys/windows/exec_windows.go | 81 +- .../x/sys/windows/security_windows.go | 1 + .../x/sys/windows/syscall_windows.go | 1 + .../golang.org/x/sys/windows/types_windows.go | 19 +- .../x/sys/windows/zsyscall_windows.go | 20 + src/cmd/vendor/modules.txt | 2 +- src/go.mod | 2 +- src/go.sum | 4 +- src/vendor/golang.org/x/sys/cpu/cpu.go | 1 + src/vendor/golang.org/x/sys/cpu/cpu_x86.go | 2 + src/vendor/modules.txt | 2 +- 105 files changed, 5284 insertions(+), 3345 deletions(-) create mode 100644 src/cmd/vendor/golang.org/x/sys/unix/ifreq_linux.go diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 362d33445b..d7b2a985ac 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -8,7 +8,7 @@ require ( golang.org/x/arch v0.0.0-20210502124803-cbf565b21d1e golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e // indirect golang.org/x/mod v0.5.1-0.20210827163434-4029241eb1d5 - golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 // indirect + golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e // indirect golang.org/x/term v0.0.0-20210503060354-a79de5458b56 golang.org/x/tools v0.1.6-0.20210809225032-337cebd2c151 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 6e8b02d8dc..6e39f6ff8e 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -12,8 +12,8 @@ golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e/go.mod h1:P+XmwS30IXTQdn5 golang.org/x/mod v0.5.1-0.20210827163434-4029241eb1d5 h1:BJ9Nc92Yf5inqB18HHrMgflMJKHraE07Z29Vjc+Z/Mk= golang.org/x/mod v0.5.1-0.20210827163434-4029241eb1d5/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 h1:yhBbb4IRs2HS9PPlAg6DMC6mUOKexJBNsLf4Z+6En1Q= -golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e h1:XMgFehsDnnLGtjvjOfqWSUzt0alpTR1RSEuznObga2c= +golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210503060354-a79de5458b56 h1:b8jxX3zqjpqb2LklXPzKSGJhzyxCOZSz8ncv8Nv+y7w= golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY= golang.org/x/tools v0.1.6-0.20210809225032-337cebd2c151 h1:jHjT6WuVKEMzjJgrS1+r1wk54oxwqumUnvtn0QZXyXE= diff --git a/src/cmd/vendor/golang.org/x/sys/unix/README.md b/src/cmd/vendor/golang.org/x/sys/unix/README.md index 579d2d7355..474efad0e0 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/README.md +++ b/src/cmd/vendor/golang.org/x/sys/unix/README.md @@ -76,7 +76,7 @@ arguments can be passed to the kernel. The third is for low-level use by the ForkExec wrapper. Unlike the first two, it does not call into the scheduler to let it know that a system call is running. -When porting Go to an new architecture/OS, this file must be implemented for +When porting Go to a new architecture/OS, this file must be implemented for each GOOS/GOARCH pair. ### mksysnum @@ -107,7 +107,7 @@ prototype can be exported (capitalized) or not. Adding a new syscall often just requires adding a new `//sys` function prototype with the desired arguments and a capitalized name so it is exported. However, if you want the interface to the syscall to be different, often one will make an -unexported `//sys` prototype, an then write a custom wrapper in +unexported `//sys` prototype, and then write a custom wrapper in `syscall_${GOOS}.go`. ### types files @@ -137,7 +137,7 @@ some `#if/#elif` macros in your include statements. This script is used to generate the system's various constants. This doesn't just include the error numbers and error strings, but also the signal numbers -an a wide variety of miscellaneous constants. The constants come from the list +and a wide variety of miscellaneous constants. The constants come from the list of include files in the `includes_${uname}` variable. A regex then picks out the desired `#define` statements, and generates the corresponding Go constants. The error numbers and strings are generated from `#include `, and the diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_bsd_386.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_bsd_386.s index 7f29275fa0..e0fcd9b3de 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_bsd_386.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_bsd_386.s @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build (darwin || freebsd || netbsd || openbsd) && gc -// +build darwin freebsd netbsd openbsd +//go:build (freebsd || netbsd || openbsd) && gc +// +build freebsd netbsd openbsd // +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_bsd_arm.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_bsd_arm.s index 98ebfad9d5..d702d4adc7 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_bsd_arm.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_bsd_arm.s @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build (darwin || freebsd || netbsd || openbsd) && gc -// +build darwin freebsd netbsd openbsd +//go:build (freebsd || netbsd || openbsd) && gc +// +build freebsd netbsd openbsd // +build gc #include "textflag.h" diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ifreq_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/ifreq_linux.go new file mode 100644 index 0000000000..934af313c3 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/sys/unix/ifreq_linux.go @@ -0,0 +1,149 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux +// +build linux + +package unix + +import ( + "bytes" + "unsafe" +) + +// Helpers for dealing with ifreq since it contains a union and thus requires a +// lot of unsafe.Pointer casts to use properly. + +// An Ifreq is a type-safe wrapper around the raw ifreq struct. An Ifreq +// contains an interface name and a union of arbitrary data which can be +// accessed using the Ifreq's methods. To create an Ifreq, use the NewIfreq +// function. +// +// Use the Name method to access the stored interface name. The union data +// fields can be get and set using the following methods: +// - Uint16/SetUint16: flags +// - Uint32/SetUint32: ifindex, metric, mtu +type Ifreq struct{ raw ifreq } + +// NewIfreq creates an Ifreq with the input network interface name after +// validating the name does not exceed IFNAMSIZ-1 (trailing NULL required) +// bytes. +func NewIfreq(name string) (*Ifreq, error) { + // Leave room for terminating NULL byte. + if len(name) >= IFNAMSIZ { + return nil, EINVAL + } + + var ifr ifreq + copy(ifr.Ifrn[:], name) + + return &Ifreq{raw: ifr}, nil +} + +// TODO(mdlayher): get/set methods for hardware address sockaddr, char array, etc. + +// Name returns the interface name associated with the Ifreq. +func (ifr *Ifreq) Name() string { + // BytePtrToString requires a NULL terminator or the program may crash. If + // one is not present, just return the empty string. + if !bytes.Contains(ifr.raw.Ifrn[:], []byte{0x00}) { + return "" + } + + return BytePtrToString(&ifr.raw.Ifrn[0]) +} + +// According to netdevice(7), only AF_INET addresses are returned for numerous +// sockaddr ioctls. For convenience, we expose these as Inet4Addr since the Port +// field and other data is always empty. + +// Inet4Addr returns the Ifreq union data from an embedded sockaddr as a C +// in_addr/Go []byte (4-byte IPv4 address) value. If the sockaddr family is not +// AF_INET, an error is returned. +func (ifr *Ifreq) Inet4Addr() ([]byte, error) { + raw := *(*RawSockaddrInet4)(unsafe.Pointer(&ifr.raw.Ifru[:SizeofSockaddrInet4][0])) + if raw.Family != AF_INET { + // Cannot safely interpret raw.Addr bytes as an IPv4 address. + return nil, EINVAL + } + + return raw.Addr[:], nil +} + +// SetInet4Addr sets a C in_addr/Go []byte (4-byte IPv4 address) value in an +// embedded sockaddr within the Ifreq's union data. v must be 4 bytes in length +// or an error will be returned. +func (ifr *Ifreq) SetInet4Addr(v []byte) error { + if len(v) != 4 { + return EINVAL + } + + var addr [4]byte + copy(addr[:], v) + + ifr.clear() + *(*RawSockaddrInet4)( + unsafe.Pointer(&ifr.raw.Ifru[:SizeofSockaddrInet4][0]), + ) = RawSockaddrInet4{ + // Always set IP family as ioctls would require it anyway. + Family: AF_INET, + Addr: addr, + } + + return nil +} + +// Uint16 returns the Ifreq union data as a C short/Go uint16 value. +func (ifr *Ifreq) Uint16() uint16 { + return *(*uint16)(unsafe.Pointer(&ifr.raw.Ifru[:2][0])) +} + +// SetUint16 sets a C short/Go uint16 value as the Ifreq's union data. +func (ifr *Ifreq) SetUint16(v uint16) { + ifr.clear() + *(*uint16)(unsafe.Pointer(&ifr.raw.Ifru[:2][0])) = v +} + +// Uint32 returns the Ifreq union data as a C int/Go uint32 value. +func (ifr *Ifreq) Uint32() uint32 { + return *(*uint32)(unsafe.Pointer(&ifr.raw.Ifru[:4][0])) +} + +// SetUint32 sets a C int/Go uint32 value as the Ifreq's union data. +func (ifr *Ifreq) SetUint32(v uint32) { + ifr.clear() + *(*uint32)(unsafe.Pointer(&ifr.raw.Ifru[:4][0])) = v +} + +// clear zeroes the ifreq's union field to prevent trailing garbage data from +// being sent to the kernel if an ifreq is reused. +func (ifr *Ifreq) clear() { + for i := range ifr.raw.Ifru { + ifr.raw.Ifru[i] = 0 + } +} + +// TODO(mdlayher): export as IfreqData? For now we can provide helpers such as +// IoctlGetEthtoolDrvinfo which use these APIs under the hood. + +// An ifreqData is an Ifreq which carries pointer data. To produce an ifreqData, +// use the Ifreq.withData method. +type ifreqData struct { + name [IFNAMSIZ]byte + // A type separate from ifreq is required in order to comply with the + // unsafe.Pointer rules since the "pointer-ness" of data would not be + // preserved if it were cast into the byte array of a raw ifreq. + data unsafe.Pointer + // Pad to the same size as ifreq. + _ [len(ifreq{}.Ifru) - SizeofPtr]byte +} + +// withData produces an ifreqData with the pointer p set for ioctls which require +// arbitrary pointer data. +func (ifr Ifreq) withData(p unsafe.Pointer) ifreqData { + return ifreqData{ + name: ifr.raw.Ifrn, + data: p, + } +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ioctl_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/ioctl_linux.go index 48773f730a..1dadead21e 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ioctl_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ioctl_linux.go @@ -5,7 +5,6 @@ package unix import ( - "runtime" "unsafe" ) @@ -22,56 +21,42 @@ func IoctlRetInt(fd int, req uint) (int, error) { func IoctlGetUint32(fd int, req uint) (uint32, error) { var value uint32 - err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) + err := ioctlPtr(fd, req, unsafe.Pointer(&value)) return value, err } func IoctlGetRTCTime(fd int) (*RTCTime, error) { var value RTCTime - err := ioctl(fd, RTC_RD_TIME, uintptr(unsafe.Pointer(&value))) + err := ioctlPtr(fd, RTC_RD_TIME, unsafe.Pointer(&value)) return &value, err } func IoctlSetRTCTime(fd int, value *RTCTime) error { - err := ioctl(fd, RTC_SET_TIME, uintptr(unsafe.Pointer(value))) - runtime.KeepAlive(value) - return err + return ioctlPtr(fd, RTC_SET_TIME, unsafe.Pointer(value)) } func IoctlGetRTCWkAlrm(fd int) (*RTCWkAlrm, error) { var value RTCWkAlrm - err := ioctl(fd, RTC_WKALM_RD, uintptr(unsafe.Pointer(&value))) + err := ioctlPtr(fd, RTC_WKALM_RD, unsafe.Pointer(&value)) return &value, err } func IoctlSetRTCWkAlrm(fd int, value *RTCWkAlrm) error { - err := ioctl(fd, RTC_WKALM_SET, uintptr(unsafe.Pointer(value))) - runtime.KeepAlive(value) - return err -} - -type ifreqEthtool struct { - name [IFNAMSIZ]byte - data unsafe.Pointer + return ioctlPtr(fd, RTC_WKALM_SET, unsafe.Pointer(value)) } // IoctlGetEthtoolDrvinfo fetches ethtool driver information for the network // device specified by ifname. func IoctlGetEthtoolDrvinfo(fd int, ifname string) (*EthtoolDrvinfo, error) { - // Leave room for terminating NULL byte. - if len(ifname) >= IFNAMSIZ { - return nil, EINVAL + ifr, err := NewIfreq(ifname) + if err != nil { + return nil, err } - value := EthtoolDrvinfo{ - Cmd: ETHTOOL_GDRVINFO, - } - ifreq := ifreqEthtool{ - data: unsafe.Pointer(&value), - } - copy(ifreq.name[:], ifname) - err := ioctl(fd, SIOCETHTOOL, uintptr(unsafe.Pointer(&ifreq))) - runtime.KeepAlive(ifreq) + value := EthtoolDrvinfo{Cmd: ETHTOOL_GDRVINFO} + ifrd := ifr.withData(unsafe.Pointer(&value)) + + err = ioctlIfreqData(fd, SIOCETHTOOL, &ifrd) return &value, err } @@ -80,7 +65,7 @@ func IoctlGetEthtoolDrvinfo(fd int, ifname string) (*EthtoolDrvinfo, error) { // https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html. func IoctlGetWatchdogInfo(fd int) (*WatchdogInfo, error) { var value WatchdogInfo - err := ioctl(fd, WDIOC_GETSUPPORT, uintptr(unsafe.Pointer(&value))) + err := ioctlPtr(fd, WDIOC_GETSUPPORT, unsafe.Pointer(&value)) return &value, err } @@ -88,6 +73,7 @@ func IoctlGetWatchdogInfo(fd int) (*WatchdogInfo, error) { // more information, see: // https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html. func IoctlWatchdogKeepalive(fd int) error { + // arg is ignored and not a pointer, so ioctl is fine instead of ioctlPtr. return ioctl(fd, WDIOC_KEEPALIVE, 0) } @@ -95,9 +81,7 @@ func IoctlWatchdogKeepalive(fd int) error { // range of data conveyed in value to the file associated with the file // descriptor destFd. See the ioctl_ficlonerange(2) man page for details. func IoctlFileCloneRange(destFd int, value *FileCloneRange) error { - err := ioctl(destFd, FICLONERANGE, uintptr(unsafe.Pointer(value))) - runtime.KeepAlive(value) - return err + return ioctlPtr(destFd, FICLONERANGE, unsafe.Pointer(value)) } // IoctlFileClone performs an FICLONE ioctl operation to clone the entire file @@ -148,7 +132,7 @@ func IoctlFileDedupeRange(srcFd int, value *FileDedupeRange) error { rawinfo.Reserved = value.Info[i].Reserved } - err := ioctl(srcFd, FIDEDUPERANGE, uintptr(unsafe.Pointer(&buf[0]))) + err := ioctlPtr(srcFd, FIDEDUPERANGE, unsafe.Pointer(&buf[0])) // Output for i := range value.Info { @@ -166,31 +150,47 @@ func IoctlFileDedupeRange(srcFd int, value *FileDedupeRange) error { } func IoctlHIDGetDesc(fd int, value *HIDRawReportDescriptor) error { - err := ioctl(fd, HIDIOCGRDESC, uintptr(unsafe.Pointer(value))) - runtime.KeepAlive(value) - return err + return ioctlPtr(fd, HIDIOCGRDESC, unsafe.Pointer(value)) } func IoctlHIDGetRawInfo(fd int) (*HIDRawDevInfo, error) { var value HIDRawDevInfo - err := ioctl(fd, HIDIOCGRAWINFO, uintptr(unsafe.Pointer(&value))) + err := ioctlPtr(fd, HIDIOCGRAWINFO, unsafe.Pointer(&value)) return &value, err } func IoctlHIDGetRawName(fd int) (string, error) { var value [_HIDIOCGRAWNAME_LEN]byte - err := ioctl(fd, _HIDIOCGRAWNAME, uintptr(unsafe.Pointer(&value[0]))) + err := ioctlPtr(fd, _HIDIOCGRAWNAME, unsafe.Pointer(&value[0])) return ByteSliceToString(value[:]), err } func IoctlHIDGetRawPhys(fd int) (string, error) { var value [_HIDIOCGRAWPHYS_LEN]byte - err := ioctl(fd, _HIDIOCGRAWPHYS, uintptr(unsafe.Pointer(&value[0]))) + err := ioctlPtr(fd, _HIDIOCGRAWPHYS, unsafe.Pointer(&value[0])) return ByteSliceToString(value[:]), err } func IoctlHIDGetRawUniq(fd int) (string, error) { var value [_HIDIOCGRAWUNIQ_LEN]byte - err := ioctl(fd, _HIDIOCGRAWUNIQ, uintptr(unsafe.Pointer(&value[0]))) + err := ioctlPtr(fd, _HIDIOCGRAWUNIQ, unsafe.Pointer(&value[0])) return ByteSliceToString(value[:]), err } + +// IoctlIfreq performs an ioctl using an Ifreq structure for input and/or +// output. See the netdevice(7) man page for details. +func IoctlIfreq(fd int, req uint, value *Ifreq) error { + // It is possible we will add more fields to *Ifreq itself later to prevent + // misuse, so pass the raw *ifreq directly. + return ioctlPtr(fd, req, unsafe.Pointer(&value.raw)) +} + +// TODO(mdlayher): export if and when IfreqData is exported. + +// ioctlIfreqData performs an ioctl using an ifreqData structure for input +// and/or output. See the netdevice(7) man page for details. +func ioctlIfreqData(fd int, req uint, value *ifreqData) error { + // The memory layout of IfreqData (type-safe) and ifreq (not type-safe) are + // identical so pass *IfreqData directly. + return ioctlPtr(fd, req, unsafe.Pointer(value)) +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh b/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh index 007358af8f..0bcb8c3226 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -217,8 +217,6 @@ struct ltchars { #include #include #include -#include -#include #include #include #include @@ -239,6 +237,7 @@ struct ltchars { #include #include #include +#include #include #include #include @@ -258,6 +257,7 @@ struct ltchars { #include #include +#include #include #if defined(__sparc__) @@ -500,7 +500,10 @@ ccflags="$@" $2 ~ /^LOCK_(SH|EX|NB|UN)$/ || $2 ~ /^LO_(KEY|NAME)_SIZE$/ || $2 ~ /^LOOP_(CLR|CTL|GET|SET)_/ || - $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL)_/ || + $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL|TCPOPT)_/ || + $2 ~ /^NFC_(GENL|PROTO|COMM|RF|SE|DIRECTION|LLCP|SOCKPROTO)_/ || + $2 ~ /^NFC_.*_(MAX)?SIZE$/ || + $2 ~ /^RAW_PAYLOAD_/ || $2 ~ /^TP_STATUS_/ || $2 ~ /^FALLOC_/ || $2 ~ /^ICMPV?6?_(FILTER|SEC)/ || @@ -558,6 +561,7 @@ ccflags="$@" $2 ~ /^KEYCTL_/ || $2 ~ /^PERF_/ || $2 ~ /^SECCOMP_MODE_/ || + $2 ~ /^SEEK_/ || $2 ~ /^SPLICE_/ || $2 ~ /^SYNC_FILE_RANGE_/ || $2 !~ /^AUDIT_RECORD_MAGIC/ && @@ -593,6 +597,9 @@ ccflags="$@" $2 == "HID_MAX_DESCRIPTOR_SIZE" || $2 ~ /^_?HIDIOC/ || $2 ~ /^BUS_(USB|HIL|BLUETOOTH|VIRTUAL)$/ || + $2 ~ /^MTD/ || + $2 ~ /^OTP/ || + $2 ~ /^MEM/ || $2 ~ /^BLK[A-Z]*(GET$|SET$|BUF$|PART$|SIZE)/ {printf("\t%s = C.%s\n", $2, $2)} $2 ~ /^__WCOREFLAG$/ {next} $2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go index 9945e5f965..23f6b57606 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go @@ -13,6 +13,7 @@ package unix import ( + "fmt" "runtime" "syscall" "unsafe" @@ -398,6 +399,38 @@ func GetsockoptXucred(fd, level, opt int) (*Xucred, error) { return x, err } +func SysctlKinfoProcSlice(name string) ([]KinfoProc, error) { + mib, err := sysctlmib(name) + if err != nil { + return nil, err + } + + // Find size. + n := uintptr(0) + if err := sysctl(mib, nil, &n, nil, 0); err != nil { + return nil, err + } + if n == 0 { + return nil, nil + } + if n%SizeofKinfoProc != 0 { + return nil, fmt.Errorf("sysctl() returned a size of %d, which is not a multiple of %d", n, SizeofKinfoProc) + } + + // Read into buffer of that size. + buf := make([]KinfoProc, n/SizeofKinfoProc) + if err := sysctl(mib, (*byte)(unsafe.Pointer(&buf[0])), &n, nil, 0); err != nil { + return nil, err + } + if n%SizeofKinfoProc != 0 { + return nil, fmt.Errorf("sysctl() returned a size of %d, which is not a multiple of %d", n, SizeofKinfoProc) + } + + // The actual call may return less than the original reported required + // size so ensure we deal with that. + return buf[:n/SizeofKinfoProc], nil +} + //sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) /* diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go index 2dd7c8e34a..2839435e3d 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -66,11 +66,18 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { return fchmodat(dirfd, path, mode) } -//sys ioctl(fd int, req uint, arg uintptr) (err error) +//sys ioctl(fd int, req uint, arg uintptr) (err error) = SYS_IOCTL +//sys ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) = SYS_IOCTL -// ioctl itself should not be exposed directly, but additional get/set -// functions for specific types are permissible. -// These are defined in ioctl.go and ioctl_linux.go. +// ioctl itself should not be exposed directly, but additional get/set functions +// for specific types are permissible. These are defined in ioctl.go and +// ioctl_linux.go. +// +// The third argument to ioctl is often a pointer but sometimes an integer. +// Callers should use ioctlPtr when the third argument is a pointer and ioctl +// when the third argument is an integer. +// +// TODO: some existing code incorrectly uses ioctl when it should use ioctlPtr. //sys Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) @@ -904,6 +911,46 @@ func (sa *SockaddrIUCV) sockaddr() (unsafe.Pointer, _Socklen, error) { return unsafe.Pointer(&sa.raw), SizeofSockaddrIUCV, nil } +type SockaddrNFC struct { + DeviceIdx uint32 + TargetIdx uint32 + NFCProtocol uint32 + raw RawSockaddrNFC +} + +func (sa *SockaddrNFC) sockaddr() (unsafe.Pointer, _Socklen, error) { + sa.raw.Sa_family = AF_NFC + sa.raw.Dev_idx = sa.DeviceIdx + sa.raw.Target_idx = sa.TargetIdx + sa.raw.Nfc_protocol = sa.NFCProtocol + return unsafe.Pointer(&sa.raw), SizeofSockaddrNFC, nil +} + +type SockaddrNFCLLCP struct { + DeviceIdx uint32 + TargetIdx uint32 + NFCProtocol uint32 + DestinationSAP uint8 + SourceSAP uint8 + ServiceName string + raw RawSockaddrNFCLLCP +} + +func (sa *SockaddrNFCLLCP) sockaddr() (unsafe.Pointer, _Socklen, error) { + sa.raw.Sa_family = AF_NFC + sa.raw.Dev_idx = sa.DeviceIdx + sa.raw.Target_idx = sa.TargetIdx + sa.raw.Nfc_protocol = sa.NFCProtocol + sa.raw.Dsap = sa.DestinationSAP + sa.raw.Ssap = sa.SourceSAP + if len(sa.ServiceName) > len(sa.raw.Service_name) { + return nil, 0, EINVAL + } + copy(sa.raw.Service_name[:], sa.ServiceName) + sa.raw.SetServiceNameLen(len(sa.ServiceName)) + return unsafe.Pointer(&sa.raw), SizeofSockaddrNFCLLCP, nil +} + var socketProtocol = func(fd int) (int, error) { return GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL) } @@ -1144,6 +1191,37 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { } return sa, nil } + case AF_NFC: + proto, err := socketProtocol(fd) + if err != nil { + return nil, err + } + switch proto { + case NFC_SOCKPROTO_RAW: + pp := (*RawSockaddrNFC)(unsafe.Pointer(rsa)) + sa := &SockaddrNFC{ + DeviceIdx: pp.Dev_idx, + TargetIdx: pp.Target_idx, + NFCProtocol: pp.Nfc_protocol, + } + return sa, nil + case NFC_SOCKPROTO_LLCP: + pp := (*RawSockaddrNFCLLCP)(unsafe.Pointer(rsa)) + if uint64(pp.Service_name_len) > uint64(len(pp.Service_name)) { + return nil, EINVAL + } + sa := &SockaddrNFCLLCP{ + DeviceIdx: pp.Dev_idx, + TargetIdx: pp.Target_idx, + NFCProtocol: pp.Nfc_protocol, + DestinationSAP: pp.Dsap, + SourceSAP: pp.Ssap, + ServiceName: string(pp.Service_name[:pp.Service_name_len]), + } + return sa, nil + default: + return nil, EINVAL + } } return nil, EAFNOSUPPORT } @@ -1277,6 +1355,13 @@ func SetsockoptTpacketReq3(fd, level, opt int, tp *TpacketReq3) error { return setsockopt(fd, level, opt, unsafe.Pointer(tp), unsafe.Sizeof(*tp)) } +func SetsockoptTCPRepairOpt(fd, level, opt int, o []TCPRepairOpt) (err error) { + if len(o) == 0 { + return EINVAL + } + return setsockopt(fd, level, opt, unsafe.Pointer(&o[0]), uintptr(SizeofTCPRepairOpt*len(o))) +} + // Keyctl Commands (http://man7.org/linux/man-pages/man2/keyctl.2.html) // KeyctlInt calls keyctl commands in which each argument is an int. @@ -1788,7 +1873,7 @@ func Getpgrp() (pid int) { //sys Nanosleep(time *Timespec, leftover *Timespec) (err error) //sys PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error) //sys PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT -//sysnb prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) = SYS_PRLIMIT64 +//sysnb Prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) = SYS_PRLIMIT64 //sys Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) //sys Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) = SYS_PSELECT6 //sys read(fd int, p []byte) (n int, err error) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_386.go index 7b52e5d8a4..91317d749a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_386.go @@ -105,7 +105,7 @@ const rlimInf32 = ^uint32(0) const rlimInf64 = ^uint64(0) func Getrlimit(resource int, rlim *Rlimit) (err error) { - err = prlimit(0, resource, nil, rlim) + err = Prlimit(0, resource, nil, rlim) if err != ENOSYS { return err } @@ -133,7 +133,7 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) { //sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT func Setrlimit(resource int, rlim *Rlimit) (err error) { - err = prlimit(0, resource, rlim, nil) + err = Prlimit(0, resource, rlim, nil) if err != ENOSYS { return err } @@ -378,6 +378,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint32(length) +} + //sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) func Poll(fds []PollFd, timeout int) (n int, err error) { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go index 28b7641152..85cd97da09 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go @@ -172,6 +172,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) +} + //sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) func Poll(fds []PollFd, timeout int) (n int, err error) { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm.go index 68877728ec..b961a620e9 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm.go @@ -184,7 +184,7 @@ const rlimInf32 = ^uint32(0) const rlimInf64 = ^uint64(0) func Getrlimit(resource int, rlim *Rlimit) (err error) { - err = prlimit(0, resource, nil, rlim) + err = Prlimit(0, resource, nil, rlim) if err != ENOSYS { return err } @@ -212,7 +212,7 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) { //sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT func Setrlimit(resource int, rlim *Rlimit) (err error) { - err = prlimit(0, resource, rlim, nil) + err = Prlimit(0, resource, rlim, nil) if err != ENOSYS { return err } @@ -256,6 +256,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint32(length) +} + //sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) func Poll(fds []PollFd, timeout int) (n int, err error) { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go index 7ed7034761..4b977ba44b 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go @@ -171,7 +171,7 @@ func Pipe2(p []int, flags int) (err error) { // Getrlimit prefers the prlimit64 system call. See issue 38604. func Getrlimit(resource int, rlim *Rlimit) error { - err := prlimit(0, resource, nil, rlim) + err := Prlimit(0, resource, nil, rlim) if err != ENOSYS { return err } @@ -180,7 +180,7 @@ func Getrlimit(resource int, rlim *Rlimit) error { // Setrlimit prefers the prlimit64 system call. See issue 38604. func Setrlimit(resource int, rlim *Rlimit) error { - err := prlimit(0, resource, rlim, nil) + err := Prlimit(0, resource, rlim, nil) if err != ENOSYS { return err } @@ -207,6 +207,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) +} + func InotifyInit() (fd int, err error) { return InotifyInit1(0) } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go index 06dec06fa1..27aee81d97 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go @@ -217,6 +217,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) +} + func InotifyInit() (fd int, err error) { return InotifyInit1(0) } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go index 8f0d0a5b59..21d74e2fbe 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go @@ -157,7 +157,7 @@ type rlimit32 struct { //sysnb getrlimit(resource int, rlim *rlimit32) (err error) = SYS_GETRLIMIT func Getrlimit(resource int, rlim *Rlimit) (err error) { - err = prlimit(0, resource, nil, rlim) + err = Prlimit(0, resource, nil, rlim) if err != ENOSYS { return err } @@ -185,7 +185,7 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) { //sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT func Setrlimit(resource int, rlim *Rlimit) (err error) { - err = prlimit(0, resource, rlim, nil) + err = Prlimit(0, resource, rlim, nil) if err != ENOSYS { return err } @@ -229,6 +229,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint32(length) +} + //sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) func Poll(fds []PollFd, timeout int) (n int, err error) { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go index 7e65e088d2..6f1fc581ed 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go @@ -3,8 +3,7 @@ // license that can be found in the LICENSE file. //go:build linux && ppc -// +build linux -// +build ppc +// +build linux,ppc package unix @@ -143,7 +142,7 @@ const rlimInf32 = ^uint32(0) const rlimInf64 = ^uint64(0) func Getrlimit(resource int, rlim *Rlimit) (err error) { - err = prlimit(0, resource, nil, rlim) + err = Prlimit(0, resource, nil, rlim) if err != ENOSYS { return err } @@ -171,7 +170,7 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) { //sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT func Setrlimit(resource int, rlim *Rlimit) (err error) { - err = prlimit(0, resource, rlim, nil) + err = Prlimit(0, resource, rlim, nil) if err != ENOSYS { return err } @@ -215,6 +214,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint32(length) +} + //sysnb pipe(p *[2]_C_int) (err error) func Pipe(p []int) (err error) { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go index 0b1f0d6da5..5259a5feaf 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go @@ -100,6 +100,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) +} + //sysnb pipe(p *[2]_C_int) (err error) func Pipe(p []int) (err error) { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go index ce9bcd3171..8ef821e5da 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go @@ -188,6 +188,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) +} + func InotifyInit() (fd int, err error) { return InotifyInit1(0) } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go index a1e45694b4..a1c0574b58 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go @@ -129,6 +129,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) +} + // Linux on s390x uses the old mmap interface, which requires arguments to be passed in a struct. // mmap2 also requires arguments to be passed in a struct; it is currently not exposed in . func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go index 49055a3cf5..de14b88983 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go @@ -116,6 +116,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) +} + //sysnb pipe(p *[2]_C_int) (err error) func Pipe(p []int) (err error) { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_solaris.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_solaris.go index 77fcde7c18..d2a6495c7e 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_solaris.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_solaris.go @@ -13,7 +13,10 @@ package unix import ( + "fmt" + "os" "runtime" + "sync" "syscall" "unsafe" ) @@ -744,3 +747,240 @@ func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, e func Munmap(b []byte) (err error) { return mapper.Munmap(b) } + +// Event Ports + +type fileObjCookie struct { + fobj *fileObj + cookie interface{} +} + +// EventPort provides a safe abstraction on top of Solaris/illumos Event Ports. +type EventPort struct { + port int + mu sync.Mutex + fds map[uintptr]interface{} + paths map[string]*fileObjCookie +} + +// PortEvent is an abstraction of the port_event C struct. +// Compare Source against PORT_SOURCE_FILE or PORT_SOURCE_FD +// to see if Path or Fd was the event source. The other will be +// uninitialized. +type PortEvent struct { + Cookie interface{} + Events int32 + Fd uintptr + Path string + Source uint16 + fobj *fileObj +} + +// NewEventPort creates a new EventPort including the +// underlying call to port_create(3c). +func NewEventPort() (*EventPort, error) { + port, err := port_create() + if err != nil { + return nil, err + } + e := &EventPort{ + port: port, + fds: make(map[uintptr]interface{}), + paths: make(map[string]*fileObjCookie), + } + return e, nil +} + +//sys port_create() (n int, err error) +//sys port_associate(port int, source int, object uintptr, events int, user *byte) (n int, err error) +//sys port_dissociate(port int, source int, object uintptr) (n int, err error) +//sys port_get(port int, pe *portEvent, timeout *Timespec) (n int, err error) +//sys port_getn(port int, pe *portEvent, max uint32, nget *uint32, timeout *Timespec) (n int, err error) + +// Close closes the event port. +func (e *EventPort) Close() error { + e.mu.Lock() + defer e.mu.Unlock() + e.fds = nil + e.paths = nil + return Close(e.port) +} + +// PathIsWatched checks to see if path is associated with this EventPort. +func (e *EventPort) PathIsWatched(path string) bool { + e.mu.Lock() + defer e.mu.Unlock() + _, found := e.paths[path] + return found +} + +// FdIsWatched checks to see if fd is associated with this EventPort. +func (e *EventPort) FdIsWatched(fd uintptr) bool { + e.mu.Lock() + defer e.mu.Unlock() + _, found := e.fds[fd] + return found +} + +// AssociatePath wraps port_associate(3c) for a filesystem path including +// creating the necessary file_obj from the provided stat information. +func (e *EventPort) AssociatePath(path string, stat os.FileInfo, events int, cookie interface{}) error { + e.mu.Lock() + defer e.mu.Unlock() + if _, found := e.paths[path]; found { + return fmt.Errorf("%v is already associated with this Event Port", path) + } + fobj, err := createFileObj(path, stat) + if err != nil { + return err + } + fCookie := &fileObjCookie{fobj, cookie} + _, err = port_associate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(fobj)), events, (*byte)(unsafe.Pointer(&fCookie.cookie))) + if err != nil { + return err + } + e.paths[path] = fCookie + return nil +} + +// DissociatePath wraps port_dissociate(3c) for a filesystem path. +func (e *EventPort) DissociatePath(path string) error { + e.mu.Lock() + defer e.mu.Unlock() + f, ok := e.paths[path] + if !ok { + return fmt.Errorf("%v is not associated with this Event Port", path) + } + _, err := port_dissociate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(f.fobj))) + if err != nil { + return err + } + delete(e.paths, path) + return nil +} + +// AssociateFd wraps calls to port_associate(3c) on file descriptors. +func (e *EventPort) AssociateFd(fd uintptr, events int, cookie interface{}) error { + e.mu.Lock() + defer e.mu.Unlock() + if _, found := e.fds[fd]; found { + return fmt.Errorf("%v is already associated with this Event Port", fd) + } + pcookie := &cookie + _, err := port_associate(e.port, PORT_SOURCE_FD, fd, events, (*byte)(unsafe.Pointer(pcookie))) + if err != nil { + return err + } + e.fds[fd] = pcookie + return nil +} + +// DissociateFd wraps calls to port_dissociate(3c) on file descriptors. +func (e *EventPort) DissociateFd(fd uintptr) error { + e.mu.Lock() + defer e.mu.Unlock() + _, ok := e.fds[fd] + if !ok { + return fmt.Errorf("%v is not associated with this Event Port", fd) + } + _, err := port_dissociate(e.port, PORT_SOURCE_FD, fd) + if err != nil { + return err + } + delete(e.fds, fd) + return nil +} + +func createFileObj(name string, stat os.FileInfo) (*fileObj, error) { + fobj := new(fileObj) + bs, err := ByteSliceFromString(name) + if err != nil { + return nil, err + } + fobj.Name = (*int8)(unsafe.Pointer(&bs[0])) + s := stat.Sys().(*syscall.Stat_t) + fobj.Atim.Sec = s.Atim.Sec + fobj.Atim.Nsec = s.Atim.Nsec + fobj.Mtim.Sec = s.Mtim.Sec + fobj.Mtim.Nsec = s.Mtim.Nsec + fobj.Ctim.Sec = s.Ctim.Sec + fobj.Ctim.Nsec = s.Ctim.Nsec + return fobj, nil +} + +// GetOne wraps port_get(3c) and returns a single PortEvent. +func (e *EventPort) GetOne(t *Timespec) (*PortEvent, error) { + pe := new(portEvent) + _, err := port_get(e.port, pe, t) + if err != nil { + return nil, err + } + p := new(PortEvent) + p.Events = pe.Events + p.Source = pe.Source + e.mu.Lock() + defer e.mu.Unlock() + switch pe.Source { + case PORT_SOURCE_FD: + p.Fd = uintptr(pe.Object) + cookie := (*interface{})(unsafe.Pointer(pe.User)) + p.Cookie = *cookie + delete(e.fds, p.Fd) + case PORT_SOURCE_FILE: + p.fobj = (*fileObj)(unsafe.Pointer(uintptr(pe.Object))) + p.Path = BytePtrToString((*byte)(unsafe.Pointer(p.fobj.Name))) + cookie := (*interface{})(unsafe.Pointer(pe.User)) + p.Cookie = *cookie + delete(e.paths, p.Path) + } + return p, nil +} + +// Pending wraps port_getn(3c) and returns how many events are pending. +func (e *EventPort) Pending() (int, error) { + var n uint32 = 0 + _, err := port_getn(e.port, nil, 0, &n, nil) + return int(n), err +} + +// Get wraps port_getn(3c) and fills a slice of PortEvent. +// It will block until either min events have been received +// or the timeout has been exceeded. It will return how many +// events were actually received along with any error information. +func (e *EventPort) Get(s []PortEvent, min int, timeout *Timespec) (int, error) { + if min == 0 { + return 0, fmt.Errorf("need to request at least one event or use Pending() instead") + } + if len(s) < min { + return 0, fmt.Errorf("len(s) (%d) is less than min events requested (%d)", len(s), min) + } + got := uint32(min) + max := uint32(len(s)) + var err error + ps := make([]portEvent, max, max) + _, err = port_getn(e.port, &ps[0], max, &got, timeout) + // got will be trustworthy with ETIME, but not any other error. + if err != nil && err != ETIME { + return 0, err + } + e.mu.Lock() + defer e.mu.Unlock() + for i := 0; i < int(got); i++ { + s[i].Events = ps[i].Events + s[i].Source = ps[i].Source + switch ps[i].Source { + case PORT_SOURCE_FD: + s[i].Fd = uintptr(ps[i].Object) + cookie := (*interface{})(unsafe.Pointer(ps[i].User)) + s[i].Cookie = *cookie + delete(e.fds, s[i].Fd) + case PORT_SOURCE_FILE: + s[i].fobj = (*fileObj)(unsafe.Pointer(uintptr(ps[i].Object))) + s[i].Path = BytePtrToString((*byte)(unsafe.Pointer(s[i].fobj.Name))) + cookie := (*interface{})(unsafe.Pointer(ps[i].User)) + s[i].Cookie = *cookie + delete(e.paths, s[i].Path) + } + } + return int(got), err +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_unix.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_unix.go index a7618ceb55..cf296a2433 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_unix.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_unix.go @@ -313,6 +313,10 @@ func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) { return } +func Send(s int, buf []byte, flags int) (err error) { + return sendto(s, buf, flags, nil, 0) +} + func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) { ptr, n, err := to.sockaddr() if err != nil { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go index 991996b609..a3a45fec59 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go @@ -1206,6 +1206,7 @@ const ( RTF_DONE = 0x40 RTF_DYNAMIC = 0x10 RTF_GATEWAY = 0x2 + RTF_GLOBAL = 0x40000000 RTF_HOST = 0x4 RTF_IFREF = 0x4000000 RTF_IFSCOPE = 0x1000000 @@ -1262,6 +1263,11 @@ const ( SCM_RIGHTS = 0x1 SCM_TIMESTAMP = 0x2 SCM_TIMESTAMP_MONOTONIC = 0x4 + SEEK_CUR = 0x1 + SEEK_DATA = 0x4 + SEEK_END = 0x2 + SEEK_HOLE = 0x3 + SEEK_SET = 0x0 SHUT_RD = 0x0 SHUT_RDWR = 0x2 SHUT_WR = 0x1 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go index e644eaf5e7..31009d7f05 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go @@ -1206,6 +1206,7 @@ const ( RTF_DONE = 0x40 RTF_DYNAMIC = 0x10 RTF_GATEWAY = 0x2 + RTF_GLOBAL = 0x40000000 RTF_HOST = 0x4 RTF_IFREF = 0x4000000 RTF_IFSCOPE = 0x1000000 @@ -1262,6 +1263,11 @@ const ( SCM_RIGHTS = 0x1 SCM_TIMESTAMP = 0x2 SCM_TIMESTAMP_MONOTONIC = 0x4 + SEEK_CUR = 0x1 + SEEK_DATA = 0x4 + SEEK_END = 0x2 + SEEK_HOLE = 0x3 + SEEK_SET = 0x0 SHUT_RD = 0x0 SHUT_RDWR = 0x2 SHUT_WR = 0x1 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go index 9c7c5e1654..440900112c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go @@ -1297,6 +1297,11 @@ const ( SCM_RIGHTS = 0x1 SCM_TIMESTAMP = 0x2 SCM_TIME_INFO = 0x7 + SEEK_CUR = 0x1 + SEEK_DATA = 0x3 + SEEK_END = 0x2 + SEEK_HOLE = 0x4 + SEEK_SET = 0x0 SHUT_RD = 0x0 SHUT_RDWR = 0x2 SHUT_WR = 0x1 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go index b265abb25f..64520d3122 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go @@ -1298,6 +1298,11 @@ const ( SCM_RIGHTS = 0x1 SCM_TIMESTAMP = 0x2 SCM_TIME_INFO = 0x7 + SEEK_CUR = 0x1 + SEEK_DATA = 0x3 + SEEK_END = 0x2 + SEEK_HOLE = 0x4 + SEEK_SET = 0x0 SHUT_RD = 0x0 SHUT_RDWR = 0x2 SHUT_WR = 0x1 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go index 3df99f285f..99e9a0e06e 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go @@ -1276,6 +1276,11 @@ const ( SCM_CREDS = 0x3 SCM_RIGHTS = 0x1 SCM_TIMESTAMP = 0x2 + SEEK_CUR = 0x1 + SEEK_DATA = 0x3 + SEEK_END = 0x2 + SEEK_HOLE = 0x4 + SEEK_SET = 0x0 SHUT_RD = 0x0 SHUT_RDWR = 0x2 SHUT_WR = 0x1 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go index 218d39906d..4c83771149 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go @@ -1298,6 +1298,11 @@ const ( SCM_RIGHTS = 0x1 SCM_TIMESTAMP = 0x2 SCM_TIME_INFO = 0x7 + SEEK_CUR = 0x1 + SEEK_DATA = 0x3 + SEEK_END = 0x2 + SEEK_HOLE = 0x4 + SEEK_SET = 0x0 SHUT_RD = 0x0 SHUT_RDWR = 0x2 SHUT_WR = 0x1 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go index 47572aaa69..8894c4af44 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -228,7 +228,11 @@ const ( BPF_OR = 0x40 BPF_PSEUDO_BTF_ID = 0x3 BPF_PSEUDO_CALL = 0x1 + BPF_PSEUDO_FUNC = 0x4 + BPF_PSEUDO_KFUNC_CALL = 0x2 BPF_PSEUDO_MAP_FD = 0x1 + BPF_PSEUDO_MAP_IDX = 0x5 + BPF_PSEUDO_MAP_IDX_VALUE = 0x6 BPF_PSEUDO_MAP_VALUE = 0x2 BPF_RET = 0x6 BPF_RSH = 0x70 @@ -475,6 +479,8 @@ const ( DM_LIST_VERSIONS = 0xc138fd0d DM_MAX_TYPE_NAME = 0x10 DM_NAME_LEN = 0x80 + DM_NAME_LIST_FLAG_DOESNT_HAVE_UUID = 0x2 + DM_NAME_LIST_FLAG_HAS_UUID = 0x1 DM_NOFLUSH_FLAG = 0x800 DM_PERSISTENT_DEV_FLAG = 0x8 DM_QUERY_INACTIVE_TABLE_FLAG = 0x1000 @@ -494,9 +500,9 @@ const ( DM_UUID_FLAG = 0x4000 DM_UUID_LEN = 0x81 DM_VERSION = 0xc138fd00 - DM_VERSION_EXTRA = "-ioctl (2021-02-01)" + DM_VERSION_EXTRA = "-ioctl (2021-03-22)" DM_VERSION_MAJOR = 0x4 - DM_VERSION_MINOR = 0x2c + DM_VERSION_MINOR = 0x2d DM_VERSION_PATCHLEVEL = 0x0 DT_BLK = 0x6 DT_CHR = 0x2 @@ -981,12 +987,6 @@ const ( HPFS_SUPER_MAGIC = 0xf995e849 HUGETLBFS_MAGIC = 0x958458f6 IBSHIFT = 0x10 - ICMPV6_FILTER = 0x1 - ICMPV6_FILTER_BLOCK = 0x1 - ICMPV6_FILTER_BLOCKOTHERS = 0x3 - ICMPV6_FILTER_PASS = 0x2 - ICMPV6_FILTER_PASSONLY = 0x4 - ICMP_FILTER = 0x1 ICRNL = 0x100 IFA_F_DADFAILED = 0x8 IFA_F_DEPRECATED = 0x20 @@ -1257,6 +1257,7 @@ const ( KEXEC_ARCH_PARISC = 0xf0000 KEXEC_ARCH_PPC = 0x140000 KEXEC_ARCH_PPC64 = 0x150000 + KEXEC_ARCH_RISCV = 0xf30000 KEXEC_ARCH_S390 = 0x160000 KEXEC_ARCH_SH = 0x2a0000 KEXEC_ARCH_X86_64 = 0x3e0000 @@ -1406,6 +1407,10 @@ const ( MCAST_LEAVE_SOURCE_GROUP = 0x2f MCAST_MSFILTER = 0x30 MCAST_UNBLOCK_SOURCE = 0x2c + MEMGETREGIONINFO = 0xc0104d08 + MEMREADOOB64 = 0xc0184d16 + MEMWRITE = 0xc0304d18 + MEMWRITEOOB64 = 0xc0184d15 MFD_ALLOW_SEALING = 0x2 MFD_CLOEXEC = 0x1 MFD_HUGETLB = 0x4 @@ -1494,7 +1499,35 @@ const ( MS_SYNCHRONOUS = 0x10 MS_UNBINDABLE = 0x20000 MS_VERBOSE = 0x8000 + MTD_ABSENT = 0x0 + MTD_BIT_WRITEABLE = 0x800 + MTD_CAP_NANDFLASH = 0x400 + MTD_CAP_NORFLASH = 0xc00 + MTD_CAP_NVRAM = 0x1c00 + MTD_CAP_RAM = 0x1c00 + MTD_CAP_ROM = 0x0 + MTD_DATAFLASH = 0x6 MTD_INODE_FS_MAGIC = 0x11307854 + MTD_MAX_ECCPOS_ENTRIES = 0x40 + MTD_MAX_OOBFREE_ENTRIES = 0x8 + MTD_MLCNANDFLASH = 0x8 + MTD_NANDECC_AUTOPLACE = 0x2 + MTD_NANDECC_AUTOPL_USR = 0x4 + MTD_NANDECC_OFF = 0x0 + MTD_NANDECC_PLACE = 0x1 + MTD_NANDECC_PLACEONLY = 0x3 + MTD_NANDFLASH = 0x4 + MTD_NORFLASH = 0x3 + MTD_NO_ERASE = 0x1000 + MTD_OTP_FACTORY = 0x1 + MTD_OTP_OFF = 0x0 + MTD_OTP_USER = 0x2 + MTD_POWERUP_LOCK = 0x2000 + MTD_RAM = 0x1 + MTD_ROM = 0x2 + MTD_SLC_ON_MLC_EMULATION = 0x4000 + MTD_UBIVOLUME = 0x7 + MTD_WRITEABLE = 0x400 NAME_MAX = 0xff NCP_SUPER_MAGIC = 0x564c NETLINK_ADD_MEMBERSHIP = 0x1 @@ -1534,6 +1567,59 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFC_ATR_REQ_GB_MAXSIZE = 0x30 + NFC_ATR_REQ_MAXSIZE = 0x40 + NFC_ATR_RES_GB_MAXSIZE = 0x2f + NFC_ATR_RES_MAXSIZE = 0x40 + NFC_COMM_ACTIVE = 0x0 + NFC_COMM_PASSIVE = 0x1 + NFC_DEVICE_NAME_MAXSIZE = 0x8 + NFC_DIRECTION_RX = 0x0 + NFC_DIRECTION_TX = 0x1 + NFC_FIRMWARE_NAME_MAXSIZE = 0x20 + NFC_GB_MAXSIZE = 0x30 + NFC_GENL_MCAST_EVENT_NAME = "events" + NFC_GENL_NAME = "nfc" + NFC_GENL_VERSION = 0x1 + NFC_HEADER_SIZE = 0x1 + NFC_ISO15693_UID_MAXSIZE = 0x8 + NFC_LLCP_MAX_SERVICE_NAME = 0x3f + NFC_LLCP_MIUX = 0x1 + NFC_LLCP_REMOTE_LTO = 0x3 + NFC_LLCP_REMOTE_MIU = 0x2 + NFC_LLCP_REMOTE_RW = 0x4 + NFC_LLCP_RW = 0x0 + NFC_NFCID1_MAXSIZE = 0xa + NFC_NFCID2_MAXSIZE = 0x8 + NFC_NFCID3_MAXSIZE = 0xa + NFC_PROTO_FELICA = 0x3 + NFC_PROTO_FELICA_MASK = 0x8 + NFC_PROTO_ISO14443 = 0x4 + NFC_PROTO_ISO14443_B = 0x6 + NFC_PROTO_ISO14443_B_MASK = 0x40 + NFC_PROTO_ISO14443_MASK = 0x10 + NFC_PROTO_ISO15693 = 0x7 + NFC_PROTO_ISO15693_MASK = 0x80 + NFC_PROTO_JEWEL = 0x1 + NFC_PROTO_JEWEL_MASK = 0x2 + NFC_PROTO_MAX = 0x8 + NFC_PROTO_MIFARE = 0x2 + NFC_PROTO_MIFARE_MASK = 0x4 + NFC_PROTO_NFC_DEP = 0x5 + NFC_PROTO_NFC_DEP_MASK = 0x20 + NFC_RAW_HEADER_SIZE = 0x2 + NFC_RF_INITIATOR = 0x0 + NFC_RF_NONE = 0x2 + NFC_RF_TARGET = 0x1 + NFC_SENSB_RES_MAXSIZE = 0xc + NFC_SENSF_RES_MAXSIZE = 0x12 + NFC_SE_DISABLED = 0x0 + NFC_SE_EMBEDDED = 0x2 + NFC_SE_ENABLED = 0x1 + NFC_SE_UICC = 0x1 + NFC_SOCKPROTO_LLCP = 0x1 + NFC_SOCKPROTO_MAX = 0x2 + NFC_SOCKPROTO_RAW = 0x0 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1551,11 +1637,12 @@ const ( NFNL_MSG_BATCH_END = 0x11 NFNL_NFA_NEST = 0x8000 NFNL_SUBSYS_ACCT = 0x7 - NFNL_SUBSYS_COUNT = 0xc + NFNL_SUBSYS_COUNT = 0xd NFNL_SUBSYS_CTHELPER = 0x9 NFNL_SUBSYS_CTNETLINK = 0x1 NFNL_SUBSYS_CTNETLINK_EXP = 0x2 NFNL_SUBSYS_CTNETLINK_TIMEOUT = 0x8 + NFNL_SUBSYS_HOOK = 0xc NFNL_SUBSYS_IPSET = 0x6 NFNL_SUBSYS_NFTABLES = 0xa NFNL_SUBSYS_NFT_COMPAT = 0xb @@ -1671,14 +1758,19 @@ const ( PERF_ATTR_SIZE_VER4 = 0x68 PERF_ATTR_SIZE_VER5 = 0x70 PERF_ATTR_SIZE_VER6 = 0x78 + PERF_ATTR_SIZE_VER7 = 0x80 PERF_AUX_FLAG_COLLISION = 0x8 + PERF_AUX_FLAG_CORESIGHT_FORMAT_CORESIGHT = 0x0 + PERF_AUX_FLAG_CORESIGHT_FORMAT_RAW = 0x100 PERF_AUX_FLAG_OVERWRITE = 0x2 PERF_AUX_FLAG_PARTIAL = 0x4 + PERF_AUX_FLAG_PMU_FORMAT_TYPE_MASK = 0xff00 PERF_AUX_FLAG_TRUNCATED = 0x1 PERF_FLAG_FD_CLOEXEC = 0x8 PERF_FLAG_FD_NO_GROUP = 0x1 PERF_FLAG_FD_OUTPUT = 0x2 PERF_FLAG_PID_CGROUP = 0x4 + PERF_HW_EVENT_MASK = 0xffffffff PERF_MAX_CONTEXTS_PER_STACK = 0x8 PERF_MAX_STACK_DEPTH = 0x7f PERF_MEM_BLK_ADDR = 0x4 @@ -1737,6 +1829,7 @@ const ( PERF_MEM_TLB_OS = 0x40 PERF_MEM_TLB_SHIFT = 0x1a PERF_MEM_TLB_WK = 0x20 + PERF_PMU_TYPE_SHIFT = 0x20 PERF_RECORD_KSYMBOL_FLAGS_UNREGISTER = 0x1 PERF_RECORD_MISC_COMM_EXEC = 0x2000 PERF_RECORD_MISC_CPUMODE_MASK = 0x7 @@ -1836,7 +1929,15 @@ const ( PR_PAC_APGAKEY = 0x10 PR_PAC_APIAKEY = 0x1 PR_PAC_APIBKEY = 0x2 + PR_PAC_GET_ENABLED_KEYS = 0x3d PR_PAC_RESET_KEYS = 0x36 + PR_PAC_SET_ENABLED_KEYS = 0x3c + PR_SCHED_CORE = 0x3e + PR_SCHED_CORE_CREATE = 0x1 + PR_SCHED_CORE_GET = 0x0 + PR_SCHED_CORE_MAX = 0x4 + PR_SCHED_CORE_SHARE_FROM = 0x3 + PR_SCHED_CORE_SHARE_TO = 0x2 PR_SET_CHILD_SUBREAPER = 0x24 PR_SET_DUMPABLE = 0x4 PR_SET_ENDIAN = 0x14 @@ -1918,6 +2019,7 @@ const ( PTRACE_GETREGSET = 0x4204 PTRACE_GETSIGINFO = 0x4202 PTRACE_GETSIGMASK = 0x420a + PTRACE_GET_RSEQ_CONFIGURATION = 0x420f PTRACE_GET_SYSCALL_INFO = 0x420e PTRACE_INTERRUPT = 0x4207 PTRACE_KILL = 0x8 @@ -1959,6 +2061,11 @@ const ( QNX4_SUPER_MAGIC = 0x2f QNX6_SUPER_MAGIC = 0x68191122 RAMFS_MAGIC = 0x858458f6 + RAW_PAYLOAD_DIGITAL = 0x3 + RAW_PAYLOAD_HCI = 0x2 + RAW_PAYLOAD_LLCP = 0x0 + RAW_PAYLOAD_NCI = 0x1 + RAW_PAYLOAD_PROPRIETARY = 0x4 RDTGROUP_SUPER_MAGIC = 0x7655821 REISERFS_SUPER_MAGIC = 0x52654973 RENAME_EXCHANGE = 0x2 @@ -2073,6 +2180,7 @@ const ( RTM_DELNEIGH = 0x1d RTM_DELNETCONF = 0x51 RTM_DELNEXTHOP = 0x69 + RTM_DELNEXTHOPBUCKET = 0x75 RTM_DELNSID = 0x59 RTM_DELQDISC = 0x25 RTM_DELROUTE = 0x19 @@ -2103,6 +2211,7 @@ const ( RTM_GETNEIGHTBL = 0x42 RTM_GETNETCONF = 0x52 RTM_GETNEXTHOP = 0x6a + RTM_GETNEXTHOPBUCKET = 0x76 RTM_GETNSID = 0x5a RTM_GETQDISC = 0x26 RTM_GETROUTE = 0x1a @@ -2111,7 +2220,7 @@ const ( RTM_GETTCLASS = 0x2a RTM_GETTFILTER = 0x2e RTM_GETVLAN = 0x72 - RTM_MAX = 0x73 + RTM_MAX = 0x77 RTM_NEWACTION = 0x30 RTM_NEWADDR = 0x14 RTM_NEWADDRLABEL = 0x48 @@ -2125,6 +2234,7 @@ const ( RTM_NEWNEIGHTBL = 0x40 RTM_NEWNETCONF = 0x50 RTM_NEWNEXTHOP = 0x68 + RTM_NEWNEXTHOPBUCKET = 0x74 RTM_NEWNSID = 0x58 RTM_NEWNVLAN = 0x70 RTM_NEWPREFIX = 0x34 @@ -2134,8 +2244,8 @@ const ( RTM_NEWSTATS = 0x5c RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c - RTM_NR_FAMILIES = 0x19 - RTM_NR_MSGTYPES = 0x64 + RTM_NR_FAMILIES = 0x1a + RTM_NR_MSGTYPES = 0x68 RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 @@ -2163,6 +2273,7 @@ const ( RTPROT_MROUTED = 0x11 RTPROT_MRT = 0xa RTPROT_NTK = 0xf + RTPROT_OPENR = 0x63 RTPROT_OSPF = 0xbc RTPROT_RA = 0x9 RTPROT_REDIRECT = 0x1 @@ -2193,7 +2304,14 @@ const ( SECCOMP_MODE_DISABLED = 0x0 SECCOMP_MODE_FILTER = 0x2 SECCOMP_MODE_STRICT = 0x1 + SECRETMEM_MAGIC = 0x5345434d SECURITYFS_MAGIC = 0x73636673 + SEEK_CUR = 0x1 + SEEK_DATA = 0x3 + SEEK_END = 0x2 + SEEK_HOLE = 0x4 + SEEK_MAX = 0x4 + SEEK_SET = 0x0 SELINUX_MAGIC = 0xf97cff8c SHUT_RD = 0x0 SHUT_RDWR = 0x2 @@ -2440,6 +2558,14 @@ const ( TCOFLUSH = 0x1 TCOOFF = 0x0 TCOON = 0x1 + TCPOPT_EOL = 0x0 + TCPOPT_MAXSEG = 0x2 + TCPOPT_NOP = 0x1 + TCPOPT_SACK = 0x5 + TCPOPT_SACK_PERMITTED = 0x4 + TCPOPT_TIMESTAMP = 0x8 + TCPOPT_TSTAMP_HDR = 0x101080a + TCPOPT_WINDOW = 0x3 TCP_CC_INFO = 0x1a TCP_CM_INQ = 0x24 TCP_CONGESTION = 0xd diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index e91a1a9579..697811a460 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -60,6 +60,8 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + ECCGETLAYOUT = 0x81484d11 + ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -123,6 +125,19 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x40084d02 + MEMERASE64 = 0x40104d14 + MEMGETBADBLOCK = 0x40084d0b + MEMGETINFO = 0x80204d01 + MEMGETOOBSEL = 0x80c84d0a + MEMGETREGIONCOUNT = 0x80044d07 + MEMISLOCKED = 0x80084d17 + MEMLOCK = 0x40084d05 + MEMREADOOB = 0xc00c4d04 + MEMSETBADBLOCK = 0x40084d0c + MEMUNLOCK = 0x40084d06 + MEMWRITEOOB = 0xc00c4d03 + MTDFILEMODE = 0x4d13 NFDBITS = 0x20 NLDLY = 0x100 NOFLSH = 0x80 @@ -132,6 +147,11 @@ const ( NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 + OTPERASE = 0x400c4d19 + OTPGETREGIONCOUNT = 0x40044d0e + OTPGETREGIONINFO = 0x400c4d0f + OTPLOCK = 0x800c4d10 + OTPSELECT = 0x80044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 @@ -289,6 +309,7 @@ const ( SO_MARK = 0x24 SO_MAX_PACING_RATE = 0x2f SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 SO_NOFCS = 0x2b SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index a9cbac6443..7d8d93bfc4 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -60,6 +60,8 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + ECCGETLAYOUT = 0x81484d11 + ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -123,6 +125,19 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x40084d02 + MEMERASE64 = 0x40104d14 + MEMGETBADBLOCK = 0x40084d0b + MEMGETINFO = 0x80204d01 + MEMGETOOBSEL = 0x80c84d0a + MEMGETREGIONCOUNT = 0x80044d07 + MEMISLOCKED = 0x80084d17 + MEMLOCK = 0x40084d05 + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x40084d0c + MEMUNLOCK = 0x40084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x4d13 NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 @@ -132,6 +147,11 @@ const ( NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 + OTPERASE = 0x400c4d19 + OTPGETREGIONCOUNT = 0x40044d0e + OTPGETREGIONINFO = 0x400c4d0f + OTPLOCK = 0x800c4d10 + OTPSELECT = 0x80044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 @@ -290,6 +310,7 @@ const ( SO_MARK = 0x24 SO_MAX_PACING_RATE = 0x2f SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 SO_NOFCS = 0x2b SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index d74f3c15a1..f707d50894 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -60,6 +60,8 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + ECCGETLAYOUT = 0x81484d11 + ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -121,6 +123,19 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x40084d02 + MEMERASE64 = 0x40104d14 + MEMGETBADBLOCK = 0x40084d0b + MEMGETINFO = 0x80204d01 + MEMGETOOBSEL = 0x80c84d0a + MEMGETREGIONCOUNT = 0x80044d07 + MEMISLOCKED = 0x80084d17 + MEMLOCK = 0x40084d05 + MEMREADOOB = 0xc00c4d04 + MEMSETBADBLOCK = 0x40084d0c + MEMUNLOCK = 0x40084d06 + MEMWRITEOOB = 0xc00c4d03 + MTDFILEMODE = 0x4d13 NFDBITS = 0x20 NLDLY = 0x100 NOFLSH = 0x80 @@ -130,6 +145,11 @@ const ( NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 + OTPERASE = 0x400c4d19 + OTPGETREGIONCOUNT = 0x40044d0e + OTPGETREGIONINFO = 0x400c4d0f + OTPLOCK = 0x800c4d10 + OTPSELECT = 0x80044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 @@ -296,6 +316,7 @@ const ( SO_MARK = 0x24 SO_MAX_PACING_RATE = 0x2f SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 SO_NOFCS = 0x2b SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index e1538995b4..3a67a9c852 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -60,6 +60,8 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + ECCGETLAYOUT = 0x81484d11 + ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -124,6 +126,19 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x40084d02 + MEMERASE64 = 0x40104d14 + MEMGETBADBLOCK = 0x40084d0b + MEMGETINFO = 0x80204d01 + MEMGETOOBSEL = 0x80c84d0a + MEMGETREGIONCOUNT = 0x80044d07 + MEMISLOCKED = 0x80084d17 + MEMLOCK = 0x40084d05 + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x40084d0c + MEMUNLOCK = 0x40084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x4d13 NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 @@ -133,6 +148,11 @@ const ( NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 + OTPERASE = 0x400c4d19 + OTPGETREGIONCOUNT = 0x40044d0e + OTPGETREGIONINFO = 0x400c4d0f + OTPLOCK = 0x800c4d10 + OTPSELECT = 0x80044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 @@ -286,6 +306,7 @@ const ( SO_MARK = 0x24 SO_MAX_PACING_RATE = 0x2f SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 SO_NOFCS = 0x2b SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index 5e8e71ff86..a7ccef56c5 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -60,6 +60,8 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + ECCGETLAYOUT = 0x41484d11 + ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -121,6 +123,19 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x80084d02 + MEMERASE64 = 0x80104d14 + MEMGETBADBLOCK = 0x80084d0b + MEMGETINFO = 0x40204d01 + MEMGETOOBSEL = 0x40c84d0a + MEMGETREGIONCOUNT = 0x40044d07 + MEMISLOCKED = 0x40084d17 + MEMLOCK = 0x80084d05 + MEMREADOOB = 0xc00c4d04 + MEMSETBADBLOCK = 0x80084d0c + MEMUNLOCK = 0x80084d06 + MEMWRITEOOB = 0xc00c4d03 + MTDFILEMODE = 0x20004d13 NFDBITS = 0x20 NLDLY = 0x100 NOFLSH = 0x80 @@ -130,6 +145,11 @@ const ( NS_GET_USERNS = 0x2000b701 OLCUC = 0x2 ONLCR = 0x4 + OTPERASE = 0x800c4d19 + OTPGETREGIONCOUNT = 0x80044d0e + OTPGETREGIONINFO = 0x800c4d0f + OTPLOCK = 0x400c4d10 + OTPSELECT = 0x40044d0d O_APPEND = 0x8 O_ASYNC = 0x1000 O_CLOEXEC = 0x80000 @@ -289,6 +309,7 @@ const ( SO_MARK = 0x24 SO_MAX_PACING_RATE = 0x2f SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 SO_NOFCS = 0x2b SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index e670ee1481..f7b7cec910 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -60,6 +60,8 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + ECCGETLAYOUT = 0x41484d11 + ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -121,6 +123,19 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x80084d02 + MEMERASE64 = 0x80104d14 + MEMGETBADBLOCK = 0x80084d0b + MEMGETINFO = 0x40204d01 + MEMGETOOBSEL = 0x40c84d0a + MEMGETREGIONCOUNT = 0x40044d07 + MEMISLOCKED = 0x40084d17 + MEMLOCK = 0x80084d05 + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x80084d0c + MEMUNLOCK = 0x80084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x20004d13 NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 @@ -130,6 +145,11 @@ const ( NS_GET_USERNS = 0x2000b701 OLCUC = 0x2 ONLCR = 0x4 + OTPERASE = 0x800c4d19 + OTPGETREGIONCOUNT = 0x80044d0e + OTPGETREGIONINFO = 0x800c4d0f + OTPLOCK = 0x400c4d10 + OTPSELECT = 0x40044d0d O_APPEND = 0x8 O_ASYNC = 0x1000 O_CLOEXEC = 0x80000 @@ -289,6 +309,7 @@ const ( SO_MARK = 0x24 SO_MAX_PACING_RATE = 0x2f SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 SO_NOFCS = 0x2b SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index dd11eacb81..4fcacf9584 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -60,6 +60,8 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + ECCGETLAYOUT = 0x41484d11 + ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -121,6 +123,19 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x80084d02 + MEMERASE64 = 0x80104d14 + MEMGETBADBLOCK = 0x80084d0b + MEMGETINFO = 0x40204d01 + MEMGETOOBSEL = 0x40c84d0a + MEMGETREGIONCOUNT = 0x40044d07 + MEMISLOCKED = 0x40084d17 + MEMLOCK = 0x80084d05 + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x80084d0c + MEMUNLOCK = 0x80084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x20004d13 NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 @@ -130,6 +145,11 @@ const ( NS_GET_USERNS = 0x2000b701 OLCUC = 0x2 ONLCR = 0x4 + OTPERASE = 0x800c4d19 + OTPGETREGIONCOUNT = 0x80044d0e + OTPGETREGIONINFO = 0x800c4d0f + OTPLOCK = 0x400c4d10 + OTPSELECT = 0x40044d0d O_APPEND = 0x8 O_ASYNC = 0x1000 O_CLOEXEC = 0x80000 @@ -289,6 +309,7 @@ const ( SO_MARK = 0x24 SO_MAX_PACING_RATE = 0x2f SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 SO_NOFCS = 0x2b SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index a0a5b22ae9..6f6c223a2c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -60,6 +60,8 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + ECCGETLAYOUT = 0x41484d11 + ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -121,6 +123,19 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x80084d02 + MEMERASE64 = 0x80104d14 + MEMGETBADBLOCK = 0x80084d0b + MEMGETINFO = 0x40204d01 + MEMGETOOBSEL = 0x40c84d0a + MEMGETREGIONCOUNT = 0x40044d07 + MEMISLOCKED = 0x40084d17 + MEMLOCK = 0x80084d05 + MEMREADOOB = 0xc00c4d04 + MEMSETBADBLOCK = 0x80084d0c + MEMUNLOCK = 0x80084d06 + MEMWRITEOOB = 0xc00c4d03 + MTDFILEMODE = 0x20004d13 NFDBITS = 0x20 NLDLY = 0x100 NOFLSH = 0x80 @@ -130,6 +145,11 @@ const ( NS_GET_USERNS = 0x2000b701 OLCUC = 0x2 ONLCR = 0x4 + OTPERASE = 0x800c4d19 + OTPGETREGIONCOUNT = 0x80044d0e + OTPGETREGIONINFO = 0x800c4d0f + OTPLOCK = 0x400c4d10 + OTPSELECT = 0x40044d0d O_APPEND = 0x8 O_ASYNC = 0x1000 O_CLOEXEC = 0x80000 @@ -289,6 +309,7 @@ const ( SO_MARK = 0x24 SO_MAX_PACING_RATE = 0x2f SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 SO_NOFCS = 0x2b SO_OOBINLINE = 0x100 SO_PASSCRED = 0x11 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go index d9530e5fbf..59e522bcf4 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go @@ -60,6 +60,8 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + ECCGETLAYOUT = 0x41484d11 + ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 ECHOE = 0x2 ECHOK = 0x4 @@ -121,6 +123,19 @@ const ( MCL_CURRENT = 0x2000 MCL_FUTURE = 0x4000 MCL_ONFAULT = 0x8000 + MEMERASE = 0x80084d02 + MEMERASE64 = 0x80104d14 + MEMGETBADBLOCK = 0x80084d0b + MEMGETINFO = 0x40204d01 + MEMGETOOBSEL = 0x40c84d0a + MEMGETREGIONCOUNT = 0x40044d07 + MEMISLOCKED = 0x40084d17 + MEMLOCK = 0x80084d05 + MEMREADOOB = 0xc00c4d04 + MEMSETBADBLOCK = 0x80084d0c + MEMUNLOCK = 0x80084d06 + MEMWRITEOOB = 0xc00c4d03 + MTDFILEMODE = 0x20004d13 NFDBITS = 0x20 NL2 = 0x200 NL3 = 0x300 @@ -132,6 +147,11 @@ const ( NS_GET_USERNS = 0x2000b701 OLCUC = 0x4 ONLCR = 0x2 + OTPERASE = 0x800c4d19 + OTPGETREGIONCOUNT = 0x80044d0e + OTPGETREGIONINFO = 0x800c4d0f + OTPLOCK = 0x400c4d10 + OTPSELECT = 0x40044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 @@ -344,6 +364,7 @@ const ( SO_MARK = 0x24 SO_MAX_PACING_RATE = 0x2f SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 SO_NOFCS = 0x2b SO_OOBINLINE = 0xa SO_PASSCRED = 0x14 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index e60102f6a9..d4264a0f73 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -60,6 +60,8 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + ECCGETLAYOUT = 0x41484d11 + ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 ECHOE = 0x2 ECHOK = 0x4 @@ -121,6 +123,19 @@ const ( MCL_CURRENT = 0x2000 MCL_FUTURE = 0x4000 MCL_ONFAULT = 0x8000 + MEMERASE = 0x80084d02 + MEMERASE64 = 0x80104d14 + MEMGETBADBLOCK = 0x80084d0b + MEMGETINFO = 0x40204d01 + MEMGETOOBSEL = 0x40c84d0a + MEMGETREGIONCOUNT = 0x40044d07 + MEMISLOCKED = 0x40084d17 + MEMLOCK = 0x80084d05 + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x80084d0c + MEMUNLOCK = 0x80084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x20004d13 NFDBITS = 0x40 NL2 = 0x200 NL3 = 0x300 @@ -132,6 +147,11 @@ const ( NS_GET_USERNS = 0x2000b701 OLCUC = 0x4 ONLCR = 0x2 + OTPERASE = 0x800c4d19 + OTPGETREGIONCOUNT = 0x80044d0e + OTPGETREGIONINFO = 0x800c4d0f + OTPLOCK = 0x400c4d10 + OTPSELECT = 0x40044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 @@ -348,6 +368,7 @@ const ( SO_MARK = 0x24 SO_MAX_PACING_RATE = 0x2f SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 SO_NOFCS = 0x2b SO_OOBINLINE = 0xa SO_PASSCRED = 0x14 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index 838ff4ea6d..21cbec1dd3 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -60,6 +60,8 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + ECCGETLAYOUT = 0x41484d11 + ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 ECHOE = 0x2 ECHOK = 0x4 @@ -121,6 +123,19 @@ const ( MCL_CURRENT = 0x2000 MCL_FUTURE = 0x4000 MCL_ONFAULT = 0x8000 + MEMERASE = 0x80084d02 + MEMERASE64 = 0x80104d14 + MEMGETBADBLOCK = 0x80084d0b + MEMGETINFO = 0x40204d01 + MEMGETOOBSEL = 0x40c84d0a + MEMGETREGIONCOUNT = 0x40044d07 + MEMISLOCKED = 0x40084d17 + MEMLOCK = 0x80084d05 + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x80084d0c + MEMUNLOCK = 0x80084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x20004d13 NFDBITS = 0x40 NL2 = 0x200 NL3 = 0x300 @@ -132,6 +147,11 @@ const ( NS_GET_USERNS = 0x2000b701 OLCUC = 0x4 ONLCR = 0x2 + OTPERASE = 0x800c4d19 + OTPGETREGIONCOUNT = 0x80044d0e + OTPGETREGIONINFO = 0x800c4d0f + OTPLOCK = 0x400c4d10 + OTPSELECT = 0x40044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 @@ -348,6 +368,7 @@ const ( SO_MARK = 0x24 SO_MAX_PACING_RATE = 0x2f SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 SO_NOFCS = 0x2b SO_OOBINLINE = 0xa SO_PASSCRED = 0x14 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go index 7cc98f09c3..9b05bf12fc 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -60,6 +60,8 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + ECCGETLAYOUT = 0x81484d11 + ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -121,6 +123,19 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x40084d02 + MEMERASE64 = 0x40104d14 + MEMGETBADBLOCK = 0x40084d0b + MEMGETINFO = 0x80204d01 + MEMGETOOBSEL = 0x80c84d0a + MEMGETREGIONCOUNT = 0x80044d07 + MEMISLOCKED = 0x80084d17 + MEMLOCK = 0x40084d05 + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x40084d0c + MEMUNLOCK = 0x40084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x4d13 NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 @@ -130,6 +145,11 @@ const ( NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 + OTPERASE = 0x400c4d19 + OTPGETREGIONCOUNT = 0x40044d0e + OTPGETREGIONINFO = 0x400c4d0f + OTPLOCK = 0x800c4d10 + OTPSELECT = 0x80044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 @@ -277,6 +297,7 @@ const ( SO_MARK = 0x24 SO_MAX_PACING_RATE = 0x2f SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 SO_NOFCS = 0x2b SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index 6d30e6fd84..bd82ace09a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -60,6 +60,8 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + ECCGETLAYOUT = 0x81484d11 + ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -121,6 +123,19 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x40084d02 + MEMERASE64 = 0x40104d14 + MEMGETBADBLOCK = 0x40084d0b + MEMGETINFO = 0x80204d01 + MEMGETOOBSEL = 0x80c84d0a + MEMGETREGIONCOUNT = 0x80044d07 + MEMISLOCKED = 0x80084d17 + MEMLOCK = 0x40084d05 + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x40084d0c + MEMUNLOCK = 0x40084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x4d13 NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 @@ -130,6 +145,11 @@ const ( NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 + OTPERASE = 0x400c4d19 + OTPGETREGIONCOUNT = 0x40044d0e + OTPGETREGIONINFO = 0x400c4d0f + OTPLOCK = 0x800c4d10 + OTPSELECT = 0x80044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 @@ -352,6 +372,7 @@ const ( SO_MARK = 0x24 SO_MAX_PACING_RATE = 0x2f SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 SO_NOFCS = 0x2b SO_OOBINLINE = 0xa SO_PASSCRED = 0x10 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go index d5e2dc94fa..1f8bded56b 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go @@ -63,6 +63,8 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + ECCGETLAYOUT = 0x41484d11 + ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -126,6 +128,19 @@ const ( MCL_CURRENT = 0x2000 MCL_FUTURE = 0x4000 MCL_ONFAULT = 0x8000 + MEMERASE = 0x80084d02 + MEMERASE64 = 0x80104d14 + MEMGETBADBLOCK = 0x80084d0b + MEMGETINFO = 0x40204d01 + MEMGETOOBSEL = 0x40c84d0a + MEMGETREGIONCOUNT = 0x40044d07 + MEMISLOCKED = 0x40084d17 + MEMLOCK = 0x80084d05 + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x80084d0c + MEMUNLOCK = 0x80084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x20004d13 NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 @@ -135,6 +150,11 @@ const ( NS_GET_USERNS = 0x2000b701 OLCUC = 0x2 ONLCR = 0x4 + OTPERASE = 0x800c4d19 + OTPGETREGIONCOUNT = 0x80044d0e + OTPGETREGIONINFO = 0x800c4d0f + OTPLOCK = 0x400c4d10 + OTPSELECT = 0x40044d0d O_APPEND = 0x8 O_ASYNC = 0x40 O_CLOEXEC = 0x400000 @@ -343,6 +363,7 @@ const ( SO_MARK = 0x22 SO_MAX_PACING_RATE = 0x31 SO_MEMINFO = 0x39 + SO_NETNS_COOKIE = 0x50 SO_NOFCS = 0x27 SO_OOBINLINE = 0x100 SO_PASSCRED = 0x2 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go index 593cc0feff..6d56edc05a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go @@ -1020,7 +1020,10 @@ const ( RLIMIT_CPU = 0x0 RLIMIT_DATA = 0x2 RLIMIT_FSIZE = 0x1 + RLIMIT_MEMLOCK = 0x6 RLIMIT_NOFILE = 0x8 + RLIMIT_NPROC = 0x7 + RLIMIT_RSS = 0x5 RLIMIT_STACK = 0x3 RLIM_INFINITY = 0x7fffffffffffffff RTAX_AUTHOR = 0x6 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go index a4e4c22314..aef6c08560 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go @@ -1020,7 +1020,10 @@ const ( RLIMIT_CPU = 0x0 RLIMIT_DATA = 0x2 RLIMIT_FSIZE = 0x1 + RLIMIT_MEMLOCK = 0x6 RLIMIT_NOFILE = 0x8 + RLIMIT_NPROC = 0x7 + RLIMIT_RSS = 0x5 RLIMIT_STACK = 0x3 RLIM_INFINITY = 0x7fffffffffffffff RTAX_AUTHOR = 0x6 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go index 7305cc915b..2dbe3da7a0 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go @@ -48,6 +48,16 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { + _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(oldpath) @@ -1201,7 +1211,7 @@ func PivotRoot(newroot string, putold string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) { +func Prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) { _, _, e1 := RawSyscall6(SYS_PRLIMIT64, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(newlimit)), uintptr(unsafe.Pointer(old)), 0, 0) if e1 != 0 { err = errnoErr(e1) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go index 4e18d5c99f..b5f926cee2 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go @@ -141,6 +141,11 @@ import ( //go:cgo_import_dynamic libc_getpeername getpeername "libsocket.so" //go:cgo_import_dynamic libc_setsockopt setsockopt "libsocket.so" //go:cgo_import_dynamic libc_recvfrom recvfrom "libsocket.so" +//go:cgo_import_dynamic libc_port_create port_create "libc.so" +//go:cgo_import_dynamic libc_port_associate port_associate "libc.so" +//go:cgo_import_dynamic libc_port_dissociate port_dissociate "libc.so" +//go:cgo_import_dynamic libc_port_get port_get "libc.so" +//go:cgo_import_dynamic libc_port_getn port_getn "libc.so" //go:linkname procpipe libc_pipe //go:linkname procpipe2 libc_pipe2 @@ -272,6 +277,11 @@ import ( //go:linkname procgetpeername libc_getpeername //go:linkname procsetsockopt libc_setsockopt //go:linkname procrecvfrom libc_recvfrom +//go:linkname procport_create libc_port_create +//go:linkname procport_associate libc_port_associate +//go:linkname procport_dissociate libc_port_dissociate +//go:linkname procport_get libc_port_get +//go:linkname procport_getn libc_port_getn var ( procpipe, @@ -403,7 +413,12 @@ var ( proc__xnet_getsockopt, procgetpeername, procsetsockopt, - procrecvfrom syscallFunc + procrecvfrom, + procport_create, + procport_associate, + procport_dissociate, + procport_get, + procport_getn syscallFunc ) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT @@ -1981,3 +1996,58 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func port_create() (n int, err error) { + r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procport_create)), 0, 0, 0, 0, 0, 0, 0) + n = int(r0) + if e1 != 0 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func port_associate(port int, source int, object uintptr, events int, user *byte) (n int, err error) { + r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procport_associate)), 5, uintptr(port), uintptr(source), uintptr(object), uintptr(events), uintptr(unsafe.Pointer(user)), 0) + n = int(r0) + if e1 != 0 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func port_dissociate(port int, source int, object uintptr) (n int, err error) { + r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procport_dissociate)), 3, uintptr(port), uintptr(source), uintptr(object), 0, 0, 0) + n = int(r0) + if e1 != 0 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func port_get(port int, pe *portEvent, timeout *Timespec) (n int, err error) { + r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procport_get)), 3, uintptr(port), uintptr(unsafe.Pointer(pe)), uintptr(unsafe.Pointer(timeout)), 0, 0, 0) + n = int(r0) + if e1 != 0 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func port_getn(port int, pe *portEvent, max uint32, nget *uint32, timeout *Timespec) (n int, err error) { + r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procport_getn)), 5, uintptr(port), uintptr(unsafe.Pointer(pe)), uintptr(max), uintptr(unsafe.Pointer(nget)), uintptr(unsafe.Pointer(timeout)), 0) + n = int(r0) + if e1 != 0 { + err = e1 + } + return +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go index fbc59b7fdd..aa7ce85d15 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go @@ -439,4 +439,9 @@ const ( SYS_PROCESS_MADVISE = 440 SYS_EPOLL_PWAIT2 = 441 SYS_MOUNT_SETATTR = 442 + SYS_QUOTACTL_FD = 443 + SYS_LANDLOCK_CREATE_RULESET = 444 + SYS_LANDLOCK_ADD_RULE = 445 + SYS_LANDLOCK_RESTRICT_SELF = 446 + SYS_MEMFD_SECRET = 447 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go index 04d16d771e..b830326386 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go @@ -7,358 +7,363 @@ package unix const ( - SYS_READ = 0 - SYS_WRITE = 1 - SYS_OPEN = 2 - SYS_CLOSE = 3 - SYS_STAT = 4 - SYS_FSTAT = 5 - SYS_LSTAT = 6 - SYS_POLL = 7 - SYS_LSEEK = 8 - SYS_MMAP = 9 - SYS_MPROTECT = 10 - SYS_MUNMAP = 11 - SYS_BRK = 12 - SYS_RT_SIGACTION = 13 - SYS_RT_SIGPROCMASK = 14 - SYS_RT_SIGRETURN = 15 - SYS_IOCTL = 16 - SYS_PREAD64 = 17 - SYS_PWRITE64 = 18 - SYS_READV = 19 - SYS_WRITEV = 20 - SYS_ACCESS = 21 - SYS_PIPE = 22 - SYS_SELECT = 23 - SYS_SCHED_YIELD = 24 - SYS_MREMAP = 25 - SYS_MSYNC = 26 - SYS_MINCORE = 27 - SYS_MADVISE = 28 - SYS_SHMGET = 29 - SYS_SHMAT = 30 - SYS_SHMCTL = 31 - SYS_DUP = 32 - SYS_DUP2 = 33 - SYS_PAUSE = 34 - SYS_NANOSLEEP = 35 - SYS_GETITIMER = 36 - SYS_ALARM = 37 - SYS_SETITIMER = 38 - SYS_GETPID = 39 - SYS_SENDFILE = 40 - SYS_SOCKET = 41 - SYS_CONNECT = 42 - SYS_ACCEPT = 43 - SYS_SENDTO = 44 - SYS_RECVFROM = 45 - SYS_SENDMSG = 46 - SYS_RECVMSG = 47 - SYS_SHUTDOWN = 48 - SYS_BIND = 49 - SYS_LISTEN = 50 - SYS_GETSOCKNAME = 51 - SYS_GETPEERNAME = 52 - SYS_SOCKETPAIR = 53 - SYS_SETSOCKOPT = 54 - SYS_GETSOCKOPT = 55 - SYS_CLONE = 56 - SYS_FORK = 57 - SYS_VFORK = 58 - SYS_EXECVE = 59 - SYS_EXIT = 60 - SYS_WAIT4 = 61 - SYS_KILL = 62 - SYS_UNAME = 63 - SYS_SEMGET = 64 - SYS_SEMOP = 65 - SYS_SEMCTL = 66 - SYS_SHMDT = 67 - SYS_MSGGET = 68 - SYS_MSGSND = 69 - SYS_MSGRCV = 70 - SYS_MSGCTL = 71 - SYS_FCNTL = 72 - SYS_FLOCK = 73 - SYS_FSYNC = 74 - SYS_FDATASYNC = 75 - SYS_TRUNCATE = 76 - SYS_FTRUNCATE = 77 - SYS_GETDENTS = 78 - SYS_GETCWD = 79 - SYS_CHDIR = 80 - SYS_FCHDIR = 81 - SYS_RENAME = 82 - SYS_MKDIR = 83 - SYS_RMDIR = 84 - SYS_CREAT = 85 - SYS_LINK = 86 - SYS_UNLINK = 87 - SYS_SYMLINK = 88 - SYS_READLINK = 89 - SYS_CHMOD = 90 - SYS_FCHMOD = 91 - SYS_CHOWN = 92 - SYS_FCHOWN = 93 - SYS_LCHOWN = 94 - SYS_UMASK = 95 - SYS_GETTIMEOFDAY = 96 - SYS_GETRLIMIT = 97 - SYS_GETRUSAGE = 98 - SYS_SYSINFO = 99 - SYS_TIMES = 100 - SYS_PTRACE = 101 - SYS_GETUID = 102 - SYS_SYSLOG = 103 - SYS_GETGID = 104 - SYS_SETUID = 105 - SYS_SETGID = 106 - SYS_GETEUID = 107 - SYS_GETEGID = 108 - SYS_SETPGID = 109 - SYS_GETPPID = 110 - SYS_GETPGRP = 111 - SYS_SETSID = 112 - SYS_SETREUID = 113 - SYS_SETREGID = 114 - SYS_GETGROUPS = 115 - SYS_SETGROUPS = 116 - SYS_SETRESUID = 117 - SYS_GETRESUID = 118 - SYS_SETRESGID = 119 - SYS_GETRESGID = 120 - SYS_GETPGID = 121 - SYS_SETFSUID = 122 - SYS_SETFSGID = 123 - SYS_GETSID = 124 - SYS_CAPGET = 125 - SYS_CAPSET = 126 - SYS_RT_SIGPENDING = 127 - SYS_RT_SIGTIMEDWAIT = 128 - SYS_RT_SIGQUEUEINFO = 129 - SYS_RT_SIGSUSPEND = 130 - SYS_SIGALTSTACK = 131 - SYS_UTIME = 132 - SYS_MKNOD = 133 - SYS_USELIB = 134 - SYS_PERSONALITY = 135 - SYS_USTAT = 136 - SYS_STATFS = 137 - SYS_FSTATFS = 138 - SYS_SYSFS = 139 - SYS_GETPRIORITY = 140 - SYS_SETPRIORITY = 141 - SYS_SCHED_SETPARAM = 142 - SYS_SCHED_GETPARAM = 143 - SYS_SCHED_SETSCHEDULER = 144 - SYS_SCHED_GETSCHEDULER = 145 - SYS_SCHED_GET_PRIORITY_MAX = 146 - SYS_SCHED_GET_PRIORITY_MIN = 147 - SYS_SCHED_RR_GET_INTERVAL = 148 - SYS_MLOCK = 149 - SYS_MUNLOCK = 150 - SYS_MLOCKALL = 151 - SYS_MUNLOCKALL = 152 - SYS_VHANGUP = 153 - SYS_MODIFY_LDT = 154 - SYS_PIVOT_ROOT = 155 - SYS__SYSCTL = 156 - SYS_PRCTL = 157 - SYS_ARCH_PRCTL = 158 - SYS_ADJTIMEX = 159 - SYS_SETRLIMIT = 160 - SYS_CHROOT = 161 - SYS_SYNC = 162 - SYS_ACCT = 163 - SYS_SETTIMEOFDAY = 164 - SYS_MOUNT = 165 - SYS_UMOUNT2 = 166 - SYS_SWAPON = 167 - SYS_SWAPOFF = 168 - SYS_REBOOT = 169 - SYS_SETHOSTNAME = 170 - SYS_SETDOMAINNAME = 171 - SYS_IOPL = 172 - SYS_IOPERM = 173 - SYS_CREATE_MODULE = 174 - SYS_INIT_MODULE = 175 - SYS_DELETE_MODULE = 176 - SYS_GET_KERNEL_SYMS = 177 - SYS_QUERY_MODULE = 178 - SYS_QUOTACTL = 179 - SYS_NFSSERVCTL = 180 - SYS_GETPMSG = 181 - SYS_PUTPMSG = 182 - SYS_AFS_SYSCALL = 183 - SYS_TUXCALL = 184 - SYS_SECURITY = 185 - SYS_GETTID = 186 - SYS_READAHEAD = 187 - SYS_SETXATTR = 188 - SYS_LSETXATTR = 189 - SYS_FSETXATTR = 190 - SYS_GETXATTR = 191 - SYS_LGETXATTR = 192 - SYS_FGETXATTR = 193 - SYS_LISTXATTR = 194 - SYS_LLISTXATTR = 195 - SYS_FLISTXATTR = 196 - SYS_REMOVEXATTR = 197 - SYS_LREMOVEXATTR = 198 - SYS_FREMOVEXATTR = 199 - SYS_TKILL = 200 - SYS_TIME = 201 - SYS_FUTEX = 202 - SYS_SCHED_SETAFFINITY = 203 - SYS_SCHED_GETAFFINITY = 204 - SYS_SET_THREAD_AREA = 205 - SYS_IO_SETUP = 206 - SYS_IO_DESTROY = 207 - SYS_IO_GETEVENTS = 208 - SYS_IO_SUBMIT = 209 - SYS_IO_CANCEL = 210 - SYS_GET_THREAD_AREA = 211 - SYS_LOOKUP_DCOOKIE = 212 - SYS_EPOLL_CREATE = 213 - SYS_EPOLL_CTL_OLD = 214 - SYS_EPOLL_WAIT_OLD = 215 - SYS_REMAP_FILE_PAGES = 216 - SYS_GETDENTS64 = 217 - SYS_SET_TID_ADDRESS = 218 - SYS_RESTART_SYSCALL = 219 - SYS_SEMTIMEDOP = 220 - SYS_FADVISE64 = 221 - SYS_TIMER_CREATE = 222 - SYS_TIMER_SETTIME = 223 - SYS_TIMER_GETTIME = 224 - SYS_TIMER_GETOVERRUN = 225 - SYS_TIMER_DELETE = 226 - SYS_CLOCK_SETTIME = 227 - SYS_CLOCK_GETTIME = 228 - SYS_CLOCK_GETRES = 229 - SYS_CLOCK_NANOSLEEP = 230 - SYS_EXIT_GROUP = 231 - SYS_EPOLL_WAIT = 232 - SYS_EPOLL_CTL = 233 - SYS_TGKILL = 234 - SYS_UTIMES = 235 - SYS_VSERVER = 236 - SYS_MBIND = 237 - SYS_SET_MEMPOLICY = 238 - SYS_GET_MEMPOLICY = 239 - SYS_MQ_OPEN = 240 - SYS_MQ_UNLINK = 241 - SYS_MQ_TIMEDSEND = 242 - SYS_MQ_TIMEDRECEIVE = 243 - SYS_MQ_NOTIFY = 244 - SYS_MQ_GETSETATTR = 245 - SYS_KEXEC_LOAD = 246 - SYS_WAITID = 247 - SYS_ADD_KEY = 248 - SYS_REQUEST_KEY = 249 - SYS_KEYCTL = 250 - SYS_IOPRIO_SET = 251 - SYS_IOPRIO_GET = 252 - SYS_INOTIFY_INIT = 253 - SYS_INOTIFY_ADD_WATCH = 254 - SYS_INOTIFY_RM_WATCH = 255 - SYS_MIGRATE_PAGES = 256 - SYS_OPENAT = 257 - SYS_MKDIRAT = 258 - SYS_MKNODAT = 259 - SYS_FCHOWNAT = 260 - SYS_FUTIMESAT = 261 - SYS_NEWFSTATAT = 262 - SYS_UNLINKAT = 263 - SYS_RENAMEAT = 264 - SYS_LINKAT = 265 - SYS_SYMLINKAT = 266 - SYS_READLINKAT = 267 - SYS_FCHMODAT = 268 - SYS_FACCESSAT = 269 - SYS_PSELECT6 = 270 - SYS_PPOLL = 271 - SYS_UNSHARE = 272 - SYS_SET_ROBUST_LIST = 273 - SYS_GET_ROBUST_LIST = 274 - SYS_SPLICE = 275 - SYS_TEE = 276 - SYS_SYNC_FILE_RANGE = 277 - SYS_VMSPLICE = 278 - SYS_MOVE_PAGES = 279 - SYS_UTIMENSAT = 280 - SYS_EPOLL_PWAIT = 281 - SYS_SIGNALFD = 282 - SYS_TIMERFD_CREATE = 283 - SYS_EVENTFD = 284 - SYS_FALLOCATE = 285 - SYS_TIMERFD_SETTIME = 286 - SYS_TIMERFD_GETTIME = 287 - SYS_ACCEPT4 = 288 - SYS_SIGNALFD4 = 289 - SYS_EVENTFD2 = 290 - SYS_EPOLL_CREATE1 = 291 - SYS_DUP3 = 292 - SYS_PIPE2 = 293 - SYS_INOTIFY_INIT1 = 294 - SYS_PREADV = 295 - SYS_PWRITEV = 296 - SYS_RT_TGSIGQUEUEINFO = 297 - SYS_PERF_EVENT_OPEN = 298 - SYS_RECVMMSG = 299 - SYS_FANOTIFY_INIT = 300 - SYS_FANOTIFY_MARK = 301 - SYS_PRLIMIT64 = 302 - SYS_NAME_TO_HANDLE_AT = 303 - SYS_OPEN_BY_HANDLE_AT = 304 - SYS_CLOCK_ADJTIME = 305 - SYS_SYNCFS = 306 - SYS_SENDMMSG = 307 - SYS_SETNS = 308 - SYS_GETCPU = 309 - SYS_PROCESS_VM_READV = 310 - SYS_PROCESS_VM_WRITEV = 311 - SYS_KCMP = 312 - SYS_FINIT_MODULE = 313 - SYS_SCHED_SETATTR = 314 - SYS_SCHED_GETATTR = 315 - SYS_RENAMEAT2 = 316 - SYS_SECCOMP = 317 - SYS_GETRANDOM = 318 - SYS_MEMFD_CREATE = 319 - SYS_KEXEC_FILE_LOAD = 320 - SYS_BPF = 321 - SYS_EXECVEAT = 322 - SYS_USERFAULTFD = 323 - SYS_MEMBARRIER = 324 - SYS_MLOCK2 = 325 - SYS_COPY_FILE_RANGE = 326 - SYS_PREADV2 = 327 - SYS_PWRITEV2 = 328 - SYS_PKEY_MPROTECT = 329 - SYS_PKEY_ALLOC = 330 - SYS_PKEY_FREE = 331 - SYS_STATX = 332 - SYS_IO_PGETEVENTS = 333 - SYS_RSEQ = 334 - SYS_PIDFD_SEND_SIGNAL = 424 - SYS_IO_URING_SETUP = 425 - SYS_IO_URING_ENTER = 426 - SYS_IO_URING_REGISTER = 427 - SYS_OPEN_TREE = 428 - SYS_MOVE_MOUNT = 429 - SYS_FSOPEN = 430 - SYS_FSCONFIG = 431 - SYS_FSMOUNT = 432 - SYS_FSPICK = 433 - SYS_PIDFD_OPEN = 434 - SYS_CLONE3 = 435 - SYS_CLOSE_RANGE = 436 - SYS_OPENAT2 = 437 - SYS_PIDFD_GETFD = 438 - SYS_FACCESSAT2 = 439 - SYS_PROCESS_MADVISE = 440 - SYS_EPOLL_PWAIT2 = 441 - SYS_MOUNT_SETATTR = 442 + SYS_READ = 0 + SYS_WRITE = 1 + SYS_OPEN = 2 + SYS_CLOSE = 3 + SYS_STAT = 4 + SYS_FSTAT = 5 + SYS_LSTAT = 6 + SYS_POLL = 7 + SYS_LSEEK = 8 + SYS_MMAP = 9 + SYS_MPROTECT = 10 + SYS_MUNMAP = 11 + SYS_BRK = 12 + SYS_RT_SIGACTION = 13 + SYS_RT_SIGPROCMASK = 14 + SYS_RT_SIGRETURN = 15 + SYS_IOCTL = 16 + SYS_PREAD64 = 17 + SYS_PWRITE64 = 18 + SYS_READV = 19 + SYS_WRITEV = 20 + SYS_ACCESS = 21 + SYS_PIPE = 22 + SYS_SELECT = 23 + SYS_SCHED_YIELD = 24 + SYS_MREMAP = 25 + SYS_MSYNC = 26 + SYS_MINCORE = 27 + SYS_MADVISE = 28 + SYS_SHMGET = 29 + SYS_SHMAT = 30 + SYS_SHMCTL = 31 + SYS_DUP = 32 + SYS_DUP2 = 33 + SYS_PAUSE = 34 + SYS_NANOSLEEP = 35 + SYS_GETITIMER = 36 + SYS_ALARM = 37 + SYS_SETITIMER = 38 + SYS_GETPID = 39 + SYS_SENDFILE = 40 + SYS_SOCKET = 41 + SYS_CONNECT = 42 + SYS_ACCEPT = 43 + SYS_SENDTO = 44 + SYS_RECVFROM = 45 + SYS_SENDMSG = 46 + SYS_RECVMSG = 47 + SYS_SHUTDOWN = 48 + SYS_BIND = 49 + SYS_LISTEN = 50 + SYS_GETSOCKNAME = 51 + SYS_GETPEERNAME = 52 + SYS_SOCKETPAIR = 53 + SYS_SETSOCKOPT = 54 + SYS_GETSOCKOPT = 55 + SYS_CLONE = 56 + SYS_FORK = 57 + SYS_VFORK = 58 + SYS_EXECVE = 59 + SYS_EXIT = 60 + SYS_WAIT4 = 61 + SYS_KILL = 62 + SYS_UNAME = 63 + SYS_SEMGET = 64 + SYS_SEMOP = 65 + SYS_SEMCTL = 66 + SYS_SHMDT = 67 + SYS_MSGGET = 68 + SYS_MSGSND = 69 + SYS_MSGRCV = 70 + SYS_MSGCTL = 71 + SYS_FCNTL = 72 + SYS_FLOCK = 73 + SYS_FSYNC = 74 + SYS_FDATASYNC = 75 + SYS_TRUNCATE = 76 + SYS_FTRUNCATE = 77 + SYS_GETDENTS = 78 + SYS_GETCWD = 79 + SYS_CHDIR = 80 + SYS_FCHDIR = 81 + SYS_RENAME = 82 + SYS_MKDIR = 83 + SYS_RMDIR = 84 + SYS_CREAT = 85 + SYS_LINK = 86 + SYS_UNLINK = 87 + SYS_SYMLINK = 88 + SYS_READLINK = 89 + SYS_CHMOD = 90 + SYS_FCHMOD = 91 + SYS_CHOWN = 92 + SYS_FCHOWN = 93 + SYS_LCHOWN = 94 + SYS_UMASK = 95 + SYS_GETTIMEOFDAY = 96 + SYS_GETRLIMIT = 97 + SYS_GETRUSAGE = 98 + SYS_SYSINFO = 99 + SYS_TIMES = 100 + SYS_PTRACE = 101 + SYS_GETUID = 102 + SYS_SYSLOG = 103 + SYS_GETGID = 104 + SYS_SETUID = 105 + SYS_SETGID = 106 + SYS_GETEUID = 107 + SYS_GETEGID = 108 + SYS_SETPGID = 109 + SYS_GETPPID = 110 + SYS_GETPGRP = 111 + SYS_SETSID = 112 + SYS_SETREUID = 113 + SYS_SETREGID = 114 + SYS_GETGROUPS = 115 + SYS_SETGROUPS = 116 + SYS_SETRESUID = 117 + SYS_GETRESUID = 118 + SYS_SETRESGID = 119 + SYS_GETRESGID = 120 + SYS_GETPGID = 121 + SYS_SETFSUID = 122 + SYS_SETFSGID = 123 + SYS_GETSID = 124 + SYS_CAPGET = 125 + SYS_CAPSET = 126 + SYS_RT_SIGPENDING = 127 + SYS_RT_SIGTIMEDWAIT = 128 + SYS_RT_SIGQUEUEINFO = 129 + SYS_RT_SIGSUSPEND = 130 + SYS_SIGALTSTACK = 131 + SYS_UTIME = 132 + SYS_MKNOD = 133 + SYS_USELIB = 134 + SYS_PERSONALITY = 135 + SYS_USTAT = 136 + SYS_STATFS = 137 + SYS_FSTATFS = 138 + SYS_SYSFS = 139 + SYS_GETPRIORITY = 140 + SYS_SETPRIORITY = 141 + SYS_SCHED_SETPARAM = 142 + SYS_SCHED_GETPARAM = 143 + SYS_SCHED_SETSCHEDULER = 144 + SYS_SCHED_GETSCHEDULER = 145 + SYS_SCHED_GET_PRIORITY_MAX = 146 + SYS_SCHED_GET_PRIORITY_MIN = 147 + SYS_SCHED_RR_GET_INTERVAL = 148 + SYS_MLOCK = 149 + SYS_MUNLOCK = 150 + SYS_MLOCKALL = 151 + SYS_MUNLOCKALL = 152 + SYS_VHANGUP = 153 + SYS_MODIFY_LDT = 154 + SYS_PIVOT_ROOT = 155 + SYS__SYSCTL = 156 + SYS_PRCTL = 157 + SYS_ARCH_PRCTL = 158 + SYS_ADJTIMEX = 159 + SYS_SETRLIMIT = 160 + SYS_CHROOT = 161 + SYS_SYNC = 162 + SYS_ACCT = 163 + SYS_SETTIMEOFDAY = 164 + SYS_MOUNT = 165 + SYS_UMOUNT2 = 166 + SYS_SWAPON = 167 + SYS_SWAPOFF = 168 + SYS_REBOOT = 169 + SYS_SETHOSTNAME = 170 + SYS_SETDOMAINNAME = 171 + SYS_IOPL = 172 + SYS_IOPERM = 173 + SYS_CREATE_MODULE = 174 + SYS_INIT_MODULE = 175 + SYS_DELETE_MODULE = 176 + SYS_GET_KERNEL_SYMS = 177 + SYS_QUERY_MODULE = 178 + SYS_QUOTACTL = 179 + SYS_NFSSERVCTL = 180 + SYS_GETPMSG = 181 + SYS_PUTPMSG = 182 + SYS_AFS_SYSCALL = 183 + SYS_TUXCALL = 184 + SYS_SECURITY = 185 + SYS_GETTID = 186 + SYS_READAHEAD = 187 + SYS_SETXATTR = 188 + SYS_LSETXATTR = 189 + SYS_FSETXATTR = 190 + SYS_GETXATTR = 191 + SYS_LGETXATTR = 192 + SYS_FGETXATTR = 193 + SYS_LISTXATTR = 194 + SYS_LLISTXATTR = 195 + SYS_FLISTXATTR = 196 + SYS_REMOVEXATTR = 197 + SYS_LREMOVEXATTR = 198 + SYS_FREMOVEXATTR = 199 + SYS_TKILL = 200 + SYS_TIME = 201 + SYS_FUTEX = 202 + SYS_SCHED_SETAFFINITY = 203 + SYS_SCHED_GETAFFINITY = 204 + SYS_SET_THREAD_AREA = 205 + SYS_IO_SETUP = 206 + SYS_IO_DESTROY = 207 + SYS_IO_GETEVENTS = 208 + SYS_IO_SUBMIT = 209 + SYS_IO_CANCEL = 210 + SYS_GET_THREAD_AREA = 211 + SYS_LOOKUP_DCOOKIE = 212 + SYS_EPOLL_CREATE = 213 + SYS_EPOLL_CTL_OLD = 214 + SYS_EPOLL_WAIT_OLD = 215 + SYS_REMAP_FILE_PAGES = 216 + SYS_GETDENTS64 = 217 + SYS_SET_TID_ADDRESS = 218 + SYS_RESTART_SYSCALL = 219 + SYS_SEMTIMEDOP = 220 + SYS_FADVISE64 = 221 + SYS_TIMER_CREATE = 222 + SYS_TIMER_SETTIME = 223 + SYS_TIMER_GETTIME = 224 + SYS_TIMER_GETOVERRUN = 225 + SYS_TIMER_DELETE = 226 + SYS_CLOCK_SETTIME = 227 + SYS_CLOCK_GETTIME = 228 + SYS_CLOCK_GETRES = 229 + SYS_CLOCK_NANOSLEEP = 230 + SYS_EXIT_GROUP = 231 + SYS_EPOLL_WAIT = 232 + SYS_EPOLL_CTL = 233 + SYS_TGKILL = 234 + SYS_UTIMES = 235 + SYS_VSERVER = 236 + SYS_MBIND = 237 + SYS_SET_MEMPOLICY = 238 + SYS_GET_MEMPOLICY = 239 + SYS_MQ_OPEN = 240 + SYS_MQ_UNLINK = 241 + SYS_MQ_TIMEDSEND = 242 + SYS_MQ_TIMEDRECEIVE = 243 + SYS_MQ_NOTIFY = 244 + SYS_MQ_GETSETATTR = 245 + SYS_KEXEC_LOAD = 246 + SYS_WAITID = 247 + SYS_ADD_KEY = 248 + SYS_REQUEST_KEY = 249 + SYS_KEYCTL = 250 + SYS_IOPRIO_SET = 251 + SYS_IOPRIO_GET = 252 + SYS_INOTIFY_INIT = 253 + SYS_INOTIFY_ADD_WATCH = 254 + SYS_INOTIFY_RM_WATCH = 255 + SYS_MIGRATE_PAGES = 256 + SYS_OPENAT = 257 + SYS_MKDIRAT = 258 + SYS_MKNODAT = 259 + SYS_FCHOWNAT = 260 + SYS_FUTIMESAT = 261 + SYS_NEWFSTATAT = 262 + SYS_UNLINKAT = 263 + SYS_RENAMEAT = 264 + SYS_LINKAT = 265 + SYS_SYMLINKAT = 266 + SYS_READLINKAT = 267 + SYS_FCHMODAT = 268 + SYS_FACCESSAT = 269 + SYS_PSELECT6 = 270 + SYS_PPOLL = 271 + SYS_UNSHARE = 272 + SYS_SET_ROBUST_LIST = 273 + SYS_GET_ROBUST_LIST = 274 + SYS_SPLICE = 275 + SYS_TEE = 276 + SYS_SYNC_FILE_RANGE = 277 + SYS_VMSPLICE = 278 + SYS_MOVE_PAGES = 279 + SYS_UTIMENSAT = 280 + SYS_EPOLL_PWAIT = 281 + SYS_SIGNALFD = 282 + SYS_TIMERFD_CREATE = 283 + SYS_EVENTFD = 284 + SYS_FALLOCATE = 285 + SYS_TIMERFD_SETTIME = 286 + SYS_TIMERFD_GETTIME = 287 + SYS_ACCEPT4 = 288 + SYS_SIGNALFD4 = 289 + SYS_EVENTFD2 = 290 + SYS_EPOLL_CREATE1 = 291 + SYS_DUP3 = 292 + SYS_PIPE2 = 293 + SYS_INOTIFY_INIT1 = 294 + SYS_PREADV = 295 + SYS_PWRITEV = 296 + SYS_RT_TGSIGQUEUEINFO = 297 + SYS_PERF_EVENT_OPEN = 298 + SYS_RECVMMSG = 299 + SYS_FANOTIFY_INIT = 300 + SYS_FANOTIFY_MARK = 301 + SYS_PRLIMIT64 = 302 + SYS_NAME_TO_HANDLE_AT = 303 + SYS_OPEN_BY_HANDLE_AT = 304 + SYS_CLOCK_ADJTIME = 305 + SYS_SYNCFS = 306 + SYS_SENDMMSG = 307 + SYS_SETNS = 308 + SYS_GETCPU = 309 + SYS_PROCESS_VM_READV = 310 + SYS_PROCESS_VM_WRITEV = 311 + SYS_KCMP = 312 + SYS_FINIT_MODULE = 313 + SYS_SCHED_SETATTR = 314 + SYS_SCHED_GETATTR = 315 + SYS_RENAMEAT2 = 316 + SYS_SECCOMP = 317 + SYS_GETRANDOM = 318 + SYS_MEMFD_CREATE = 319 + SYS_KEXEC_FILE_LOAD = 320 + SYS_BPF = 321 + SYS_EXECVEAT = 322 + SYS_USERFAULTFD = 323 + SYS_MEMBARRIER = 324 + SYS_MLOCK2 = 325 + SYS_COPY_FILE_RANGE = 326 + SYS_PREADV2 = 327 + SYS_PWRITEV2 = 328 + SYS_PKEY_MPROTECT = 329 + SYS_PKEY_ALLOC = 330 + SYS_PKEY_FREE = 331 + SYS_STATX = 332 + SYS_IO_PGETEVENTS = 333 + SYS_RSEQ = 334 + SYS_PIDFD_SEND_SIGNAL = 424 + SYS_IO_URING_SETUP = 425 + SYS_IO_URING_ENTER = 426 + SYS_IO_URING_REGISTER = 427 + SYS_OPEN_TREE = 428 + SYS_MOVE_MOUNT = 429 + SYS_FSOPEN = 430 + SYS_FSCONFIG = 431 + SYS_FSMOUNT = 432 + SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 + SYS_CLOSE_RANGE = 436 + SYS_OPENAT2 = 437 + SYS_PIDFD_GETFD = 438 + SYS_FACCESSAT2 = 439 + SYS_PROCESS_MADVISE = 440 + SYS_EPOLL_PWAIT2 = 441 + SYS_MOUNT_SETATTR = 442 + SYS_QUOTACTL_FD = 443 + SYS_LANDLOCK_CREATE_RULESET = 444 + SYS_LANDLOCK_ADD_RULE = 445 + SYS_LANDLOCK_RESTRICT_SELF = 446 + SYS_MEMFD_SECRET = 447 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go index 3b1c105137..d75f65a0aa 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go @@ -403,4 +403,8 @@ const ( SYS_PROCESS_MADVISE = 440 SYS_EPOLL_PWAIT2 = 441 SYS_MOUNT_SETATTR = 442 + SYS_QUOTACTL_FD = 443 + SYS_LANDLOCK_CREATE_RULESET = 444 + SYS_LANDLOCK_ADD_RULE = 445 + SYS_LANDLOCK_RESTRICT_SELF = 446 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go index 3198adcf77..8b02f09e9b 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go @@ -7,303 +7,308 @@ package unix const ( - SYS_IO_SETUP = 0 - SYS_IO_DESTROY = 1 - SYS_IO_SUBMIT = 2 - SYS_IO_CANCEL = 3 - SYS_IO_GETEVENTS = 4 - SYS_SETXATTR = 5 - SYS_LSETXATTR = 6 - SYS_FSETXATTR = 7 - SYS_GETXATTR = 8 - SYS_LGETXATTR = 9 - SYS_FGETXATTR = 10 - SYS_LISTXATTR = 11 - SYS_LLISTXATTR = 12 - SYS_FLISTXATTR = 13 - SYS_REMOVEXATTR = 14 - SYS_LREMOVEXATTR = 15 - SYS_FREMOVEXATTR = 16 - SYS_GETCWD = 17 - SYS_LOOKUP_DCOOKIE = 18 - SYS_EVENTFD2 = 19 - SYS_EPOLL_CREATE1 = 20 - SYS_EPOLL_CTL = 21 - SYS_EPOLL_PWAIT = 22 - SYS_DUP = 23 - SYS_DUP3 = 24 - SYS_FCNTL = 25 - SYS_INOTIFY_INIT1 = 26 - SYS_INOTIFY_ADD_WATCH = 27 - SYS_INOTIFY_RM_WATCH = 28 - SYS_IOCTL = 29 - SYS_IOPRIO_SET = 30 - SYS_IOPRIO_GET = 31 - SYS_FLOCK = 32 - SYS_MKNODAT = 33 - SYS_MKDIRAT = 34 - SYS_UNLINKAT = 35 - SYS_SYMLINKAT = 36 - SYS_LINKAT = 37 - SYS_RENAMEAT = 38 - SYS_UMOUNT2 = 39 - SYS_MOUNT = 40 - SYS_PIVOT_ROOT = 41 - SYS_NFSSERVCTL = 42 - SYS_STATFS = 43 - SYS_FSTATFS = 44 - SYS_TRUNCATE = 45 - SYS_FTRUNCATE = 46 - SYS_FALLOCATE = 47 - SYS_FACCESSAT = 48 - SYS_CHDIR = 49 - SYS_FCHDIR = 50 - SYS_CHROOT = 51 - SYS_FCHMOD = 52 - SYS_FCHMODAT = 53 - SYS_FCHOWNAT = 54 - SYS_FCHOWN = 55 - SYS_OPENAT = 56 - SYS_CLOSE = 57 - SYS_VHANGUP = 58 - SYS_PIPE2 = 59 - SYS_QUOTACTL = 60 - SYS_GETDENTS64 = 61 - SYS_LSEEK = 62 - SYS_READ = 63 - SYS_WRITE = 64 - SYS_READV = 65 - SYS_WRITEV = 66 - SYS_PREAD64 = 67 - SYS_PWRITE64 = 68 - SYS_PREADV = 69 - SYS_PWRITEV = 70 - SYS_SENDFILE = 71 - SYS_PSELECT6 = 72 - SYS_PPOLL = 73 - SYS_SIGNALFD4 = 74 - SYS_VMSPLICE = 75 - SYS_SPLICE = 76 - SYS_TEE = 77 - SYS_READLINKAT = 78 - SYS_FSTATAT = 79 - SYS_FSTAT = 80 - SYS_SYNC = 81 - SYS_FSYNC = 82 - SYS_FDATASYNC = 83 - SYS_SYNC_FILE_RANGE = 84 - SYS_TIMERFD_CREATE = 85 - SYS_TIMERFD_SETTIME = 86 - SYS_TIMERFD_GETTIME = 87 - SYS_UTIMENSAT = 88 - SYS_ACCT = 89 - SYS_CAPGET = 90 - SYS_CAPSET = 91 - SYS_PERSONALITY = 92 - SYS_EXIT = 93 - SYS_EXIT_GROUP = 94 - SYS_WAITID = 95 - SYS_SET_TID_ADDRESS = 96 - SYS_UNSHARE = 97 - SYS_FUTEX = 98 - SYS_SET_ROBUST_LIST = 99 - SYS_GET_ROBUST_LIST = 100 - SYS_NANOSLEEP = 101 - SYS_GETITIMER = 102 - SYS_SETITIMER = 103 - SYS_KEXEC_LOAD = 104 - SYS_INIT_MODULE = 105 - SYS_DELETE_MODULE = 106 - SYS_TIMER_CREATE = 107 - SYS_TIMER_GETTIME = 108 - SYS_TIMER_GETOVERRUN = 109 - SYS_TIMER_SETTIME = 110 - SYS_TIMER_DELETE = 111 - SYS_CLOCK_SETTIME = 112 - SYS_CLOCK_GETTIME = 113 - SYS_CLOCK_GETRES = 114 - SYS_CLOCK_NANOSLEEP = 115 - SYS_SYSLOG = 116 - SYS_PTRACE = 117 - SYS_SCHED_SETPARAM = 118 - SYS_SCHED_SETSCHEDULER = 119 - SYS_SCHED_GETSCHEDULER = 120 - SYS_SCHED_GETPARAM = 121 - SYS_SCHED_SETAFFINITY = 122 - SYS_SCHED_GETAFFINITY = 123 - SYS_SCHED_YIELD = 124 - SYS_SCHED_GET_PRIORITY_MAX = 125 - SYS_SCHED_GET_PRIORITY_MIN = 126 - SYS_SCHED_RR_GET_INTERVAL = 127 - SYS_RESTART_SYSCALL = 128 - SYS_KILL = 129 - SYS_TKILL = 130 - SYS_TGKILL = 131 - SYS_SIGALTSTACK = 132 - SYS_RT_SIGSUSPEND = 133 - SYS_RT_SIGACTION = 134 - SYS_RT_SIGPROCMASK = 135 - SYS_RT_SIGPENDING = 136 - SYS_RT_SIGTIMEDWAIT = 137 - SYS_RT_SIGQUEUEINFO = 138 - SYS_RT_SIGRETURN = 139 - SYS_SETPRIORITY = 140 - SYS_GETPRIORITY = 141 - SYS_REBOOT = 142 - SYS_SETREGID = 143 - SYS_SETGID = 144 - SYS_SETREUID = 145 - SYS_SETUID = 146 - SYS_SETRESUID = 147 - SYS_GETRESUID = 148 - SYS_SETRESGID = 149 - SYS_GETRESGID = 150 - SYS_SETFSUID = 151 - SYS_SETFSGID = 152 - SYS_TIMES = 153 - SYS_SETPGID = 154 - SYS_GETPGID = 155 - SYS_GETSID = 156 - SYS_SETSID = 157 - SYS_GETGROUPS = 158 - SYS_SETGROUPS = 159 - SYS_UNAME = 160 - SYS_SETHOSTNAME = 161 - SYS_SETDOMAINNAME = 162 - SYS_GETRLIMIT = 163 - SYS_SETRLIMIT = 164 - SYS_GETRUSAGE = 165 - SYS_UMASK = 166 - SYS_PRCTL = 167 - SYS_GETCPU = 168 - SYS_GETTIMEOFDAY = 169 - SYS_SETTIMEOFDAY = 170 - SYS_ADJTIMEX = 171 - SYS_GETPID = 172 - SYS_GETPPID = 173 - SYS_GETUID = 174 - SYS_GETEUID = 175 - SYS_GETGID = 176 - SYS_GETEGID = 177 - SYS_GETTID = 178 - SYS_SYSINFO = 179 - SYS_MQ_OPEN = 180 - SYS_MQ_UNLINK = 181 - SYS_MQ_TIMEDSEND = 182 - SYS_MQ_TIMEDRECEIVE = 183 - SYS_MQ_NOTIFY = 184 - SYS_MQ_GETSETATTR = 185 - SYS_MSGGET = 186 - SYS_MSGCTL = 187 - SYS_MSGRCV = 188 - SYS_MSGSND = 189 - SYS_SEMGET = 190 - SYS_SEMCTL = 191 - SYS_SEMTIMEDOP = 192 - SYS_SEMOP = 193 - SYS_SHMGET = 194 - SYS_SHMCTL = 195 - SYS_SHMAT = 196 - SYS_SHMDT = 197 - SYS_SOCKET = 198 - SYS_SOCKETPAIR = 199 - SYS_BIND = 200 - SYS_LISTEN = 201 - SYS_ACCEPT = 202 - SYS_CONNECT = 203 - SYS_GETSOCKNAME = 204 - SYS_GETPEERNAME = 205 - SYS_SENDTO = 206 - SYS_RECVFROM = 207 - SYS_SETSOCKOPT = 208 - SYS_GETSOCKOPT = 209 - SYS_SHUTDOWN = 210 - SYS_SENDMSG = 211 - SYS_RECVMSG = 212 - SYS_READAHEAD = 213 - SYS_BRK = 214 - SYS_MUNMAP = 215 - SYS_MREMAP = 216 - SYS_ADD_KEY = 217 - SYS_REQUEST_KEY = 218 - SYS_KEYCTL = 219 - SYS_CLONE = 220 - SYS_EXECVE = 221 - SYS_MMAP = 222 - SYS_FADVISE64 = 223 - SYS_SWAPON = 224 - SYS_SWAPOFF = 225 - SYS_MPROTECT = 226 - SYS_MSYNC = 227 - SYS_MLOCK = 228 - SYS_MUNLOCK = 229 - SYS_MLOCKALL = 230 - SYS_MUNLOCKALL = 231 - SYS_MINCORE = 232 - SYS_MADVISE = 233 - SYS_REMAP_FILE_PAGES = 234 - SYS_MBIND = 235 - SYS_GET_MEMPOLICY = 236 - SYS_SET_MEMPOLICY = 237 - SYS_MIGRATE_PAGES = 238 - SYS_MOVE_PAGES = 239 - SYS_RT_TGSIGQUEUEINFO = 240 - SYS_PERF_EVENT_OPEN = 241 - SYS_ACCEPT4 = 242 - SYS_RECVMMSG = 243 - SYS_ARCH_SPECIFIC_SYSCALL = 244 - SYS_WAIT4 = 260 - SYS_PRLIMIT64 = 261 - SYS_FANOTIFY_INIT = 262 - SYS_FANOTIFY_MARK = 263 - SYS_NAME_TO_HANDLE_AT = 264 - SYS_OPEN_BY_HANDLE_AT = 265 - SYS_CLOCK_ADJTIME = 266 - SYS_SYNCFS = 267 - SYS_SETNS = 268 - SYS_SENDMMSG = 269 - SYS_PROCESS_VM_READV = 270 - SYS_PROCESS_VM_WRITEV = 271 - SYS_KCMP = 272 - SYS_FINIT_MODULE = 273 - SYS_SCHED_SETATTR = 274 - SYS_SCHED_GETATTR = 275 - SYS_RENAMEAT2 = 276 - SYS_SECCOMP = 277 - SYS_GETRANDOM = 278 - SYS_MEMFD_CREATE = 279 - SYS_BPF = 280 - SYS_EXECVEAT = 281 - SYS_USERFAULTFD = 282 - SYS_MEMBARRIER = 283 - SYS_MLOCK2 = 284 - SYS_COPY_FILE_RANGE = 285 - SYS_PREADV2 = 286 - SYS_PWRITEV2 = 287 - SYS_PKEY_MPROTECT = 288 - SYS_PKEY_ALLOC = 289 - SYS_PKEY_FREE = 290 - SYS_STATX = 291 - SYS_IO_PGETEVENTS = 292 - SYS_RSEQ = 293 - SYS_KEXEC_FILE_LOAD = 294 - SYS_PIDFD_SEND_SIGNAL = 424 - SYS_IO_URING_SETUP = 425 - SYS_IO_URING_ENTER = 426 - SYS_IO_URING_REGISTER = 427 - SYS_OPEN_TREE = 428 - SYS_MOVE_MOUNT = 429 - SYS_FSOPEN = 430 - SYS_FSCONFIG = 431 - SYS_FSMOUNT = 432 - SYS_FSPICK = 433 - SYS_PIDFD_OPEN = 434 - SYS_CLONE3 = 435 - SYS_CLOSE_RANGE = 436 - SYS_OPENAT2 = 437 - SYS_PIDFD_GETFD = 438 - SYS_FACCESSAT2 = 439 - SYS_PROCESS_MADVISE = 440 - SYS_EPOLL_PWAIT2 = 441 - SYS_MOUNT_SETATTR = 442 + SYS_IO_SETUP = 0 + SYS_IO_DESTROY = 1 + SYS_IO_SUBMIT = 2 + SYS_IO_CANCEL = 3 + SYS_IO_GETEVENTS = 4 + SYS_SETXATTR = 5 + SYS_LSETXATTR = 6 + SYS_FSETXATTR = 7 + SYS_GETXATTR = 8 + SYS_LGETXATTR = 9 + SYS_FGETXATTR = 10 + SYS_LISTXATTR = 11 + SYS_LLISTXATTR = 12 + SYS_FLISTXATTR = 13 + SYS_REMOVEXATTR = 14 + SYS_LREMOVEXATTR = 15 + SYS_FREMOVEXATTR = 16 + SYS_GETCWD = 17 + SYS_LOOKUP_DCOOKIE = 18 + SYS_EVENTFD2 = 19 + SYS_EPOLL_CREATE1 = 20 + SYS_EPOLL_CTL = 21 + SYS_EPOLL_PWAIT = 22 + SYS_DUP = 23 + SYS_DUP3 = 24 + SYS_FCNTL = 25 + SYS_INOTIFY_INIT1 = 26 + SYS_INOTIFY_ADD_WATCH = 27 + SYS_INOTIFY_RM_WATCH = 28 + SYS_IOCTL = 29 + SYS_IOPRIO_SET = 30 + SYS_IOPRIO_GET = 31 + SYS_FLOCK = 32 + SYS_MKNODAT = 33 + SYS_MKDIRAT = 34 + SYS_UNLINKAT = 35 + SYS_SYMLINKAT = 36 + SYS_LINKAT = 37 + SYS_RENAMEAT = 38 + SYS_UMOUNT2 = 39 + SYS_MOUNT = 40 + SYS_PIVOT_ROOT = 41 + SYS_NFSSERVCTL = 42 + SYS_STATFS = 43 + SYS_FSTATFS = 44 + SYS_TRUNCATE = 45 + SYS_FTRUNCATE = 46 + SYS_FALLOCATE = 47 + SYS_FACCESSAT = 48 + SYS_CHDIR = 49 + SYS_FCHDIR = 50 + SYS_CHROOT = 51 + SYS_FCHMOD = 52 + SYS_FCHMODAT = 53 + SYS_FCHOWNAT = 54 + SYS_FCHOWN = 55 + SYS_OPENAT = 56 + SYS_CLOSE = 57 + SYS_VHANGUP = 58 + SYS_PIPE2 = 59 + SYS_QUOTACTL = 60 + SYS_GETDENTS64 = 61 + SYS_LSEEK = 62 + SYS_READ = 63 + SYS_WRITE = 64 + SYS_READV = 65 + SYS_WRITEV = 66 + SYS_PREAD64 = 67 + SYS_PWRITE64 = 68 + SYS_PREADV = 69 + SYS_PWRITEV = 70 + SYS_SENDFILE = 71 + SYS_PSELECT6 = 72 + SYS_PPOLL = 73 + SYS_SIGNALFD4 = 74 + SYS_VMSPLICE = 75 + SYS_SPLICE = 76 + SYS_TEE = 77 + SYS_READLINKAT = 78 + SYS_FSTATAT = 79 + SYS_FSTAT = 80 + SYS_SYNC = 81 + SYS_FSYNC = 82 + SYS_FDATASYNC = 83 + SYS_SYNC_FILE_RANGE = 84 + SYS_TIMERFD_CREATE = 85 + SYS_TIMERFD_SETTIME = 86 + SYS_TIMERFD_GETTIME = 87 + SYS_UTIMENSAT = 88 + SYS_ACCT = 89 + SYS_CAPGET = 90 + SYS_CAPSET = 91 + SYS_PERSONALITY = 92 + SYS_EXIT = 93 + SYS_EXIT_GROUP = 94 + SYS_WAITID = 95 + SYS_SET_TID_ADDRESS = 96 + SYS_UNSHARE = 97 + SYS_FUTEX = 98 + SYS_SET_ROBUST_LIST = 99 + SYS_GET_ROBUST_LIST = 100 + SYS_NANOSLEEP = 101 + SYS_GETITIMER = 102 + SYS_SETITIMER = 103 + SYS_KEXEC_LOAD = 104 + SYS_INIT_MODULE = 105 + SYS_DELETE_MODULE = 106 + SYS_TIMER_CREATE = 107 + SYS_TIMER_GETTIME = 108 + SYS_TIMER_GETOVERRUN = 109 + SYS_TIMER_SETTIME = 110 + SYS_TIMER_DELETE = 111 + SYS_CLOCK_SETTIME = 112 + SYS_CLOCK_GETTIME = 113 + SYS_CLOCK_GETRES = 114 + SYS_CLOCK_NANOSLEEP = 115 + SYS_SYSLOG = 116 + SYS_PTRACE = 117 + SYS_SCHED_SETPARAM = 118 + SYS_SCHED_SETSCHEDULER = 119 + SYS_SCHED_GETSCHEDULER = 120 + SYS_SCHED_GETPARAM = 121 + SYS_SCHED_SETAFFINITY = 122 + SYS_SCHED_GETAFFINITY = 123 + SYS_SCHED_YIELD = 124 + SYS_SCHED_GET_PRIORITY_MAX = 125 + SYS_SCHED_GET_PRIORITY_MIN = 126 + SYS_SCHED_RR_GET_INTERVAL = 127 + SYS_RESTART_SYSCALL = 128 + SYS_KILL = 129 + SYS_TKILL = 130 + SYS_TGKILL = 131 + SYS_SIGALTSTACK = 132 + SYS_RT_SIGSUSPEND = 133 + SYS_RT_SIGACTION = 134 + SYS_RT_SIGPROCMASK = 135 + SYS_RT_SIGPENDING = 136 + SYS_RT_SIGTIMEDWAIT = 137 + SYS_RT_SIGQUEUEINFO = 138 + SYS_RT_SIGRETURN = 139 + SYS_SETPRIORITY = 140 + SYS_GETPRIORITY = 141 + SYS_REBOOT = 142 + SYS_SETREGID = 143 + SYS_SETGID = 144 + SYS_SETREUID = 145 + SYS_SETUID = 146 + SYS_SETRESUID = 147 + SYS_GETRESUID = 148 + SYS_SETRESGID = 149 + SYS_GETRESGID = 150 + SYS_SETFSUID = 151 + SYS_SETFSGID = 152 + SYS_TIMES = 153 + SYS_SETPGID = 154 + SYS_GETPGID = 155 + SYS_GETSID = 156 + SYS_SETSID = 157 + SYS_GETGROUPS = 158 + SYS_SETGROUPS = 159 + SYS_UNAME = 160 + SYS_SETHOSTNAME = 161 + SYS_SETDOMAINNAME = 162 + SYS_GETRLIMIT = 163 + SYS_SETRLIMIT = 164 + SYS_GETRUSAGE = 165 + SYS_UMASK = 166 + SYS_PRCTL = 167 + SYS_GETCPU = 168 + SYS_GETTIMEOFDAY = 169 + SYS_SETTIMEOFDAY = 170 + SYS_ADJTIMEX = 171 + SYS_GETPID = 172 + SYS_GETPPID = 173 + SYS_GETUID = 174 + SYS_GETEUID = 175 + SYS_GETGID = 176 + SYS_GETEGID = 177 + SYS_GETTID = 178 + SYS_SYSINFO = 179 + SYS_MQ_OPEN = 180 + SYS_MQ_UNLINK = 181 + SYS_MQ_TIMEDSEND = 182 + SYS_MQ_TIMEDRECEIVE = 183 + SYS_MQ_NOTIFY = 184 + SYS_MQ_GETSETATTR = 185 + SYS_MSGGET = 186 + SYS_MSGCTL = 187 + SYS_MSGRCV = 188 + SYS_MSGSND = 189 + SYS_SEMGET = 190 + SYS_SEMCTL = 191 + SYS_SEMTIMEDOP = 192 + SYS_SEMOP = 193 + SYS_SHMGET = 194 + SYS_SHMCTL = 195 + SYS_SHMAT = 196 + SYS_SHMDT = 197 + SYS_SOCKET = 198 + SYS_SOCKETPAIR = 199 + SYS_BIND = 200 + SYS_LISTEN = 201 + SYS_ACCEPT = 202 + SYS_CONNECT = 203 + SYS_GETSOCKNAME = 204 + SYS_GETPEERNAME = 205 + SYS_SENDTO = 206 + SYS_RECVFROM = 207 + SYS_SETSOCKOPT = 208 + SYS_GETSOCKOPT = 209 + SYS_SHUTDOWN = 210 + SYS_SENDMSG = 211 + SYS_RECVMSG = 212 + SYS_READAHEAD = 213 + SYS_BRK = 214 + SYS_MUNMAP = 215 + SYS_MREMAP = 216 + SYS_ADD_KEY = 217 + SYS_REQUEST_KEY = 218 + SYS_KEYCTL = 219 + SYS_CLONE = 220 + SYS_EXECVE = 221 + SYS_MMAP = 222 + SYS_FADVISE64 = 223 + SYS_SWAPON = 224 + SYS_SWAPOFF = 225 + SYS_MPROTECT = 226 + SYS_MSYNC = 227 + SYS_MLOCK = 228 + SYS_MUNLOCK = 229 + SYS_MLOCKALL = 230 + SYS_MUNLOCKALL = 231 + SYS_MINCORE = 232 + SYS_MADVISE = 233 + SYS_REMAP_FILE_PAGES = 234 + SYS_MBIND = 235 + SYS_GET_MEMPOLICY = 236 + SYS_SET_MEMPOLICY = 237 + SYS_MIGRATE_PAGES = 238 + SYS_MOVE_PAGES = 239 + SYS_RT_TGSIGQUEUEINFO = 240 + SYS_PERF_EVENT_OPEN = 241 + SYS_ACCEPT4 = 242 + SYS_RECVMMSG = 243 + SYS_ARCH_SPECIFIC_SYSCALL = 244 + SYS_WAIT4 = 260 + SYS_PRLIMIT64 = 261 + SYS_FANOTIFY_INIT = 262 + SYS_FANOTIFY_MARK = 263 + SYS_NAME_TO_HANDLE_AT = 264 + SYS_OPEN_BY_HANDLE_AT = 265 + SYS_CLOCK_ADJTIME = 266 + SYS_SYNCFS = 267 + SYS_SETNS = 268 + SYS_SENDMMSG = 269 + SYS_PROCESS_VM_READV = 270 + SYS_PROCESS_VM_WRITEV = 271 + SYS_KCMP = 272 + SYS_FINIT_MODULE = 273 + SYS_SCHED_SETATTR = 274 + SYS_SCHED_GETATTR = 275 + SYS_RENAMEAT2 = 276 + SYS_SECCOMP = 277 + SYS_GETRANDOM = 278 + SYS_MEMFD_CREATE = 279 + SYS_BPF = 280 + SYS_EXECVEAT = 281 + SYS_USERFAULTFD = 282 + SYS_MEMBARRIER = 283 + SYS_MLOCK2 = 284 + SYS_COPY_FILE_RANGE = 285 + SYS_PREADV2 = 286 + SYS_PWRITEV2 = 287 + SYS_PKEY_MPROTECT = 288 + SYS_PKEY_ALLOC = 289 + SYS_PKEY_FREE = 290 + SYS_STATX = 291 + SYS_IO_PGETEVENTS = 292 + SYS_RSEQ = 293 + SYS_KEXEC_FILE_LOAD = 294 + SYS_PIDFD_SEND_SIGNAL = 424 + SYS_IO_URING_SETUP = 425 + SYS_IO_URING_ENTER = 426 + SYS_IO_URING_REGISTER = 427 + SYS_OPEN_TREE = 428 + SYS_MOVE_MOUNT = 429 + SYS_FSOPEN = 430 + SYS_FSCONFIG = 431 + SYS_FSMOUNT = 432 + SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 + SYS_CLOSE_RANGE = 436 + SYS_OPENAT2 = 437 + SYS_PIDFD_GETFD = 438 + SYS_FACCESSAT2 = 439 + SYS_PROCESS_MADVISE = 440 + SYS_EPOLL_PWAIT2 = 441 + SYS_MOUNT_SETATTR = 442 + SYS_QUOTACTL_FD = 443 + SYS_LANDLOCK_CREATE_RULESET = 444 + SYS_LANDLOCK_ADD_RULE = 445 + SYS_LANDLOCK_RESTRICT_SELF = 446 + SYS_MEMFD_SECRET = 447 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go index c877ec6e68..026695abb1 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go @@ -424,4 +424,8 @@ const ( SYS_PROCESS_MADVISE = 4440 SYS_EPOLL_PWAIT2 = 4441 SYS_MOUNT_SETATTR = 4442 + SYS_QUOTACTL_FD = 4443 + SYS_LANDLOCK_CREATE_RULESET = 4444 + SYS_LANDLOCK_ADD_RULE = 4445 + SYS_LANDLOCK_RESTRICT_SELF = 4446 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go index b5f2903729..7320ba9583 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go @@ -7,351 +7,355 @@ package unix const ( - SYS_READ = 5000 - SYS_WRITE = 5001 - SYS_OPEN = 5002 - SYS_CLOSE = 5003 - SYS_STAT = 5004 - SYS_FSTAT = 5005 - SYS_LSTAT = 5006 - SYS_POLL = 5007 - SYS_LSEEK = 5008 - SYS_MMAP = 5009 - SYS_MPROTECT = 5010 - SYS_MUNMAP = 5011 - SYS_BRK = 5012 - SYS_RT_SIGACTION = 5013 - SYS_RT_SIGPROCMASK = 5014 - SYS_IOCTL = 5015 - SYS_PREAD64 = 5016 - SYS_PWRITE64 = 5017 - SYS_READV = 5018 - SYS_WRITEV = 5019 - SYS_ACCESS = 5020 - SYS_PIPE = 5021 - SYS__NEWSELECT = 5022 - SYS_SCHED_YIELD = 5023 - SYS_MREMAP = 5024 - SYS_MSYNC = 5025 - SYS_MINCORE = 5026 - SYS_MADVISE = 5027 - SYS_SHMGET = 5028 - SYS_SHMAT = 5029 - SYS_SHMCTL = 5030 - SYS_DUP = 5031 - SYS_DUP2 = 5032 - SYS_PAUSE = 5033 - SYS_NANOSLEEP = 5034 - SYS_GETITIMER = 5035 - SYS_SETITIMER = 5036 - SYS_ALARM = 5037 - SYS_GETPID = 5038 - SYS_SENDFILE = 5039 - SYS_SOCKET = 5040 - SYS_CONNECT = 5041 - SYS_ACCEPT = 5042 - SYS_SENDTO = 5043 - SYS_RECVFROM = 5044 - SYS_SENDMSG = 5045 - SYS_RECVMSG = 5046 - SYS_SHUTDOWN = 5047 - SYS_BIND = 5048 - SYS_LISTEN = 5049 - SYS_GETSOCKNAME = 5050 - SYS_GETPEERNAME = 5051 - SYS_SOCKETPAIR = 5052 - SYS_SETSOCKOPT = 5053 - SYS_GETSOCKOPT = 5054 - SYS_CLONE = 5055 - SYS_FORK = 5056 - SYS_EXECVE = 5057 - SYS_EXIT = 5058 - SYS_WAIT4 = 5059 - SYS_KILL = 5060 - SYS_UNAME = 5061 - SYS_SEMGET = 5062 - SYS_SEMOP = 5063 - SYS_SEMCTL = 5064 - SYS_SHMDT = 5065 - SYS_MSGGET = 5066 - SYS_MSGSND = 5067 - SYS_MSGRCV = 5068 - SYS_MSGCTL = 5069 - SYS_FCNTL = 5070 - SYS_FLOCK = 5071 - SYS_FSYNC = 5072 - SYS_FDATASYNC = 5073 - SYS_TRUNCATE = 5074 - SYS_FTRUNCATE = 5075 - SYS_GETDENTS = 5076 - SYS_GETCWD = 5077 - SYS_CHDIR = 5078 - SYS_FCHDIR = 5079 - SYS_RENAME = 5080 - SYS_MKDIR = 5081 - SYS_RMDIR = 5082 - SYS_CREAT = 5083 - SYS_LINK = 5084 - SYS_UNLINK = 5085 - SYS_SYMLINK = 5086 - SYS_READLINK = 5087 - SYS_CHMOD = 5088 - SYS_FCHMOD = 5089 - SYS_CHOWN = 5090 - SYS_FCHOWN = 5091 - SYS_LCHOWN = 5092 - SYS_UMASK = 5093 - SYS_GETTIMEOFDAY = 5094 - SYS_GETRLIMIT = 5095 - SYS_GETRUSAGE = 5096 - SYS_SYSINFO = 5097 - SYS_TIMES = 5098 - SYS_PTRACE = 5099 - SYS_GETUID = 5100 - SYS_SYSLOG = 5101 - SYS_GETGID = 5102 - SYS_SETUID = 5103 - SYS_SETGID = 5104 - SYS_GETEUID = 5105 - SYS_GETEGID = 5106 - SYS_SETPGID = 5107 - SYS_GETPPID = 5108 - SYS_GETPGRP = 5109 - SYS_SETSID = 5110 - SYS_SETREUID = 5111 - SYS_SETREGID = 5112 - SYS_GETGROUPS = 5113 - SYS_SETGROUPS = 5114 - SYS_SETRESUID = 5115 - SYS_GETRESUID = 5116 - SYS_SETRESGID = 5117 - SYS_GETRESGID = 5118 - SYS_GETPGID = 5119 - SYS_SETFSUID = 5120 - SYS_SETFSGID = 5121 - SYS_GETSID = 5122 - SYS_CAPGET = 5123 - SYS_CAPSET = 5124 - SYS_RT_SIGPENDING = 5125 - SYS_RT_SIGTIMEDWAIT = 5126 - SYS_RT_SIGQUEUEINFO = 5127 - SYS_RT_SIGSUSPEND = 5128 - SYS_SIGALTSTACK = 5129 - SYS_UTIME = 5130 - SYS_MKNOD = 5131 - SYS_PERSONALITY = 5132 - SYS_USTAT = 5133 - SYS_STATFS = 5134 - SYS_FSTATFS = 5135 - SYS_SYSFS = 5136 - SYS_GETPRIORITY = 5137 - SYS_SETPRIORITY = 5138 - SYS_SCHED_SETPARAM = 5139 - SYS_SCHED_GETPARAM = 5140 - SYS_SCHED_SETSCHEDULER = 5141 - SYS_SCHED_GETSCHEDULER = 5142 - SYS_SCHED_GET_PRIORITY_MAX = 5143 - SYS_SCHED_GET_PRIORITY_MIN = 5144 - SYS_SCHED_RR_GET_INTERVAL = 5145 - SYS_MLOCK = 5146 - SYS_MUNLOCK = 5147 - SYS_MLOCKALL = 5148 - SYS_MUNLOCKALL = 5149 - SYS_VHANGUP = 5150 - SYS_PIVOT_ROOT = 5151 - SYS__SYSCTL = 5152 - SYS_PRCTL = 5153 - SYS_ADJTIMEX = 5154 - SYS_SETRLIMIT = 5155 - SYS_CHROOT = 5156 - SYS_SYNC = 5157 - SYS_ACCT = 5158 - SYS_SETTIMEOFDAY = 5159 - SYS_MOUNT = 5160 - SYS_UMOUNT2 = 5161 - SYS_SWAPON = 5162 - SYS_SWAPOFF = 5163 - SYS_REBOOT = 5164 - SYS_SETHOSTNAME = 5165 - SYS_SETDOMAINNAME = 5166 - SYS_CREATE_MODULE = 5167 - SYS_INIT_MODULE = 5168 - SYS_DELETE_MODULE = 5169 - SYS_GET_KERNEL_SYMS = 5170 - SYS_QUERY_MODULE = 5171 - SYS_QUOTACTL = 5172 - SYS_NFSSERVCTL = 5173 - SYS_GETPMSG = 5174 - SYS_PUTPMSG = 5175 - SYS_AFS_SYSCALL = 5176 - SYS_RESERVED177 = 5177 - SYS_GETTID = 5178 - SYS_READAHEAD = 5179 - SYS_SETXATTR = 5180 - SYS_LSETXATTR = 5181 - SYS_FSETXATTR = 5182 - SYS_GETXATTR = 5183 - SYS_LGETXATTR = 5184 - SYS_FGETXATTR = 5185 - SYS_LISTXATTR = 5186 - SYS_LLISTXATTR = 5187 - SYS_FLISTXATTR = 5188 - SYS_REMOVEXATTR = 5189 - SYS_LREMOVEXATTR = 5190 - SYS_FREMOVEXATTR = 5191 - SYS_TKILL = 5192 - SYS_RESERVED193 = 5193 - SYS_FUTEX = 5194 - SYS_SCHED_SETAFFINITY = 5195 - SYS_SCHED_GETAFFINITY = 5196 - SYS_CACHEFLUSH = 5197 - SYS_CACHECTL = 5198 - SYS_SYSMIPS = 5199 - SYS_IO_SETUP = 5200 - SYS_IO_DESTROY = 5201 - SYS_IO_GETEVENTS = 5202 - SYS_IO_SUBMIT = 5203 - SYS_IO_CANCEL = 5204 - SYS_EXIT_GROUP = 5205 - SYS_LOOKUP_DCOOKIE = 5206 - SYS_EPOLL_CREATE = 5207 - SYS_EPOLL_CTL = 5208 - SYS_EPOLL_WAIT = 5209 - SYS_REMAP_FILE_PAGES = 5210 - SYS_RT_SIGRETURN = 5211 - SYS_SET_TID_ADDRESS = 5212 - SYS_RESTART_SYSCALL = 5213 - SYS_SEMTIMEDOP = 5214 - SYS_FADVISE64 = 5215 - SYS_TIMER_CREATE = 5216 - SYS_TIMER_SETTIME = 5217 - SYS_TIMER_GETTIME = 5218 - SYS_TIMER_GETOVERRUN = 5219 - SYS_TIMER_DELETE = 5220 - SYS_CLOCK_SETTIME = 5221 - SYS_CLOCK_GETTIME = 5222 - SYS_CLOCK_GETRES = 5223 - SYS_CLOCK_NANOSLEEP = 5224 - SYS_TGKILL = 5225 - SYS_UTIMES = 5226 - SYS_MBIND = 5227 - SYS_GET_MEMPOLICY = 5228 - SYS_SET_MEMPOLICY = 5229 - SYS_MQ_OPEN = 5230 - SYS_MQ_UNLINK = 5231 - SYS_MQ_TIMEDSEND = 5232 - SYS_MQ_TIMEDRECEIVE = 5233 - SYS_MQ_NOTIFY = 5234 - SYS_MQ_GETSETATTR = 5235 - SYS_VSERVER = 5236 - SYS_WAITID = 5237 - SYS_ADD_KEY = 5239 - SYS_REQUEST_KEY = 5240 - SYS_KEYCTL = 5241 - SYS_SET_THREAD_AREA = 5242 - SYS_INOTIFY_INIT = 5243 - SYS_INOTIFY_ADD_WATCH = 5244 - SYS_INOTIFY_RM_WATCH = 5245 - SYS_MIGRATE_PAGES = 5246 - SYS_OPENAT = 5247 - SYS_MKDIRAT = 5248 - SYS_MKNODAT = 5249 - SYS_FCHOWNAT = 5250 - SYS_FUTIMESAT = 5251 - SYS_NEWFSTATAT = 5252 - SYS_UNLINKAT = 5253 - SYS_RENAMEAT = 5254 - SYS_LINKAT = 5255 - SYS_SYMLINKAT = 5256 - SYS_READLINKAT = 5257 - SYS_FCHMODAT = 5258 - SYS_FACCESSAT = 5259 - SYS_PSELECT6 = 5260 - SYS_PPOLL = 5261 - SYS_UNSHARE = 5262 - SYS_SPLICE = 5263 - SYS_SYNC_FILE_RANGE = 5264 - SYS_TEE = 5265 - SYS_VMSPLICE = 5266 - SYS_MOVE_PAGES = 5267 - SYS_SET_ROBUST_LIST = 5268 - SYS_GET_ROBUST_LIST = 5269 - SYS_KEXEC_LOAD = 5270 - SYS_GETCPU = 5271 - SYS_EPOLL_PWAIT = 5272 - SYS_IOPRIO_SET = 5273 - SYS_IOPRIO_GET = 5274 - SYS_UTIMENSAT = 5275 - SYS_SIGNALFD = 5276 - SYS_TIMERFD = 5277 - SYS_EVENTFD = 5278 - SYS_FALLOCATE = 5279 - SYS_TIMERFD_CREATE = 5280 - SYS_TIMERFD_GETTIME = 5281 - SYS_TIMERFD_SETTIME = 5282 - SYS_SIGNALFD4 = 5283 - SYS_EVENTFD2 = 5284 - SYS_EPOLL_CREATE1 = 5285 - SYS_DUP3 = 5286 - SYS_PIPE2 = 5287 - SYS_INOTIFY_INIT1 = 5288 - SYS_PREADV = 5289 - SYS_PWRITEV = 5290 - SYS_RT_TGSIGQUEUEINFO = 5291 - SYS_PERF_EVENT_OPEN = 5292 - SYS_ACCEPT4 = 5293 - SYS_RECVMMSG = 5294 - SYS_FANOTIFY_INIT = 5295 - SYS_FANOTIFY_MARK = 5296 - SYS_PRLIMIT64 = 5297 - SYS_NAME_TO_HANDLE_AT = 5298 - SYS_OPEN_BY_HANDLE_AT = 5299 - SYS_CLOCK_ADJTIME = 5300 - SYS_SYNCFS = 5301 - SYS_SENDMMSG = 5302 - SYS_SETNS = 5303 - SYS_PROCESS_VM_READV = 5304 - SYS_PROCESS_VM_WRITEV = 5305 - SYS_KCMP = 5306 - SYS_FINIT_MODULE = 5307 - SYS_GETDENTS64 = 5308 - SYS_SCHED_SETATTR = 5309 - SYS_SCHED_GETATTR = 5310 - SYS_RENAMEAT2 = 5311 - SYS_SECCOMP = 5312 - SYS_GETRANDOM = 5313 - SYS_MEMFD_CREATE = 5314 - SYS_BPF = 5315 - SYS_EXECVEAT = 5316 - SYS_USERFAULTFD = 5317 - SYS_MEMBARRIER = 5318 - SYS_MLOCK2 = 5319 - SYS_COPY_FILE_RANGE = 5320 - SYS_PREADV2 = 5321 - SYS_PWRITEV2 = 5322 - SYS_PKEY_MPROTECT = 5323 - SYS_PKEY_ALLOC = 5324 - SYS_PKEY_FREE = 5325 - SYS_STATX = 5326 - SYS_RSEQ = 5327 - SYS_IO_PGETEVENTS = 5328 - SYS_PIDFD_SEND_SIGNAL = 5424 - SYS_IO_URING_SETUP = 5425 - SYS_IO_URING_ENTER = 5426 - SYS_IO_URING_REGISTER = 5427 - SYS_OPEN_TREE = 5428 - SYS_MOVE_MOUNT = 5429 - SYS_FSOPEN = 5430 - SYS_FSCONFIG = 5431 - SYS_FSMOUNT = 5432 - SYS_FSPICK = 5433 - SYS_PIDFD_OPEN = 5434 - SYS_CLONE3 = 5435 - SYS_CLOSE_RANGE = 5436 - SYS_OPENAT2 = 5437 - SYS_PIDFD_GETFD = 5438 - SYS_FACCESSAT2 = 5439 - SYS_PROCESS_MADVISE = 5440 - SYS_EPOLL_PWAIT2 = 5441 - SYS_MOUNT_SETATTR = 5442 + SYS_READ = 5000 + SYS_WRITE = 5001 + SYS_OPEN = 5002 + SYS_CLOSE = 5003 + SYS_STAT = 5004 + SYS_FSTAT = 5005 + SYS_LSTAT = 5006 + SYS_POLL = 5007 + SYS_LSEEK = 5008 + SYS_MMAP = 5009 + SYS_MPROTECT = 5010 + SYS_MUNMAP = 5011 + SYS_BRK = 5012 + SYS_RT_SIGACTION = 5013 + SYS_RT_SIGPROCMASK = 5014 + SYS_IOCTL = 5015 + SYS_PREAD64 = 5016 + SYS_PWRITE64 = 5017 + SYS_READV = 5018 + SYS_WRITEV = 5019 + SYS_ACCESS = 5020 + SYS_PIPE = 5021 + SYS__NEWSELECT = 5022 + SYS_SCHED_YIELD = 5023 + SYS_MREMAP = 5024 + SYS_MSYNC = 5025 + SYS_MINCORE = 5026 + SYS_MADVISE = 5027 + SYS_SHMGET = 5028 + SYS_SHMAT = 5029 + SYS_SHMCTL = 5030 + SYS_DUP = 5031 + SYS_DUP2 = 5032 + SYS_PAUSE = 5033 + SYS_NANOSLEEP = 5034 + SYS_GETITIMER = 5035 + SYS_SETITIMER = 5036 + SYS_ALARM = 5037 + SYS_GETPID = 5038 + SYS_SENDFILE = 5039 + SYS_SOCKET = 5040 + SYS_CONNECT = 5041 + SYS_ACCEPT = 5042 + SYS_SENDTO = 5043 + SYS_RECVFROM = 5044 + SYS_SENDMSG = 5045 + SYS_RECVMSG = 5046 + SYS_SHUTDOWN = 5047 + SYS_BIND = 5048 + SYS_LISTEN = 5049 + SYS_GETSOCKNAME = 5050 + SYS_GETPEERNAME = 5051 + SYS_SOCKETPAIR = 5052 + SYS_SETSOCKOPT = 5053 + SYS_GETSOCKOPT = 5054 + SYS_CLONE = 5055 + SYS_FORK = 5056 + SYS_EXECVE = 5057 + SYS_EXIT = 5058 + SYS_WAIT4 = 5059 + SYS_KILL = 5060 + SYS_UNAME = 5061 + SYS_SEMGET = 5062 + SYS_SEMOP = 5063 + SYS_SEMCTL = 5064 + SYS_SHMDT = 5065 + SYS_MSGGET = 5066 + SYS_MSGSND = 5067 + SYS_MSGRCV = 5068 + SYS_MSGCTL = 5069 + SYS_FCNTL = 5070 + SYS_FLOCK = 5071 + SYS_FSYNC = 5072 + SYS_FDATASYNC = 5073 + SYS_TRUNCATE = 5074 + SYS_FTRUNCATE = 5075 + SYS_GETDENTS = 5076 + SYS_GETCWD = 5077 + SYS_CHDIR = 5078 + SYS_FCHDIR = 5079 + SYS_RENAME = 5080 + SYS_MKDIR = 5081 + SYS_RMDIR = 5082 + SYS_CREAT = 5083 + SYS_LINK = 5084 + SYS_UNLINK = 5085 + SYS_SYMLINK = 5086 + SYS_READLINK = 5087 + SYS_CHMOD = 5088 + SYS_FCHMOD = 5089 + SYS_CHOWN = 5090 + SYS_FCHOWN = 5091 + SYS_LCHOWN = 5092 + SYS_UMASK = 5093 + SYS_GETTIMEOFDAY = 5094 + SYS_GETRLIMIT = 5095 + SYS_GETRUSAGE = 5096 + SYS_SYSINFO = 5097 + SYS_TIMES = 5098 + SYS_PTRACE = 5099 + SYS_GETUID = 5100 + SYS_SYSLOG = 5101 + SYS_GETGID = 5102 + SYS_SETUID = 5103 + SYS_SETGID = 5104 + SYS_GETEUID = 5105 + SYS_GETEGID = 5106 + SYS_SETPGID = 5107 + SYS_GETPPID = 5108 + SYS_GETPGRP = 5109 + SYS_SETSID = 5110 + SYS_SETREUID = 5111 + SYS_SETREGID = 5112 + SYS_GETGROUPS = 5113 + SYS_SETGROUPS = 5114 + SYS_SETRESUID = 5115 + SYS_GETRESUID = 5116 + SYS_SETRESGID = 5117 + SYS_GETRESGID = 5118 + SYS_GETPGID = 5119 + SYS_SETFSUID = 5120 + SYS_SETFSGID = 5121 + SYS_GETSID = 5122 + SYS_CAPGET = 5123 + SYS_CAPSET = 5124 + SYS_RT_SIGPENDING = 5125 + SYS_RT_SIGTIMEDWAIT = 5126 + SYS_RT_SIGQUEUEINFO = 5127 + SYS_RT_SIGSUSPEND = 5128 + SYS_SIGALTSTACK = 5129 + SYS_UTIME = 5130 + SYS_MKNOD = 5131 + SYS_PERSONALITY = 5132 + SYS_USTAT = 5133 + SYS_STATFS = 5134 + SYS_FSTATFS = 5135 + SYS_SYSFS = 5136 + SYS_GETPRIORITY = 5137 + SYS_SETPRIORITY = 5138 + SYS_SCHED_SETPARAM = 5139 + SYS_SCHED_GETPARAM = 5140 + SYS_SCHED_SETSCHEDULER = 5141 + SYS_SCHED_GETSCHEDULER = 5142 + SYS_SCHED_GET_PRIORITY_MAX = 5143 + SYS_SCHED_GET_PRIORITY_MIN = 5144 + SYS_SCHED_RR_GET_INTERVAL = 5145 + SYS_MLOCK = 5146 + SYS_MUNLOCK = 5147 + SYS_MLOCKALL = 5148 + SYS_MUNLOCKALL = 5149 + SYS_VHANGUP = 5150 + SYS_PIVOT_ROOT = 5151 + SYS__SYSCTL = 5152 + SYS_PRCTL = 5153 + SYS_ADJTIMEX = 5154 + SYS_SETRLIMIT = 5155 + SYS_CHROOT = 5156 + SYS_SYNC = 5157 + SYS_ACCT = 5158 + SYS_SETTIMEOFDAY = 5159 + SYS_MOUNT = 5160 + SYS_UMOUNT2 = 5161 + SYS_SWAPON = 5162 + SYS_SWAPOFF = 5163 + SYS_REBOOT = 5164 + SYS_SETHOSTNAME = 5165 + SYS_SETDOMAINNAME = 5166 + SYS_CREATE_MODULE = 5167 + SYS_INIT_MODULE = 5168 + SYS_DELETE_MODULE = 5169 + SYS_GET_KERNEL_SYMS = 5170 + SYS_QUERY_MODULE = 5171 + SYS_QUOTACTL = 5172 + SYS_NFSSERVCTL = 5173 + SYS_GETPMSG = 5174 + SYS_PUTPMSG = 5175 + SYS_AFS_SYSCALL = 5176 + SYS_RESERVED177 = 5177 + SYS_GETTID = 5178 + SYS_READAHEAD = 5179 + SYS_SETXATTR = 5180 + SYS_LSETXATTR = 5181 + SYS_FSETXATTR = 5182 + SYS_GETXATTR = 5183 + SYS_LGETXATTR = 5184 + SYS_FGETXATTR = 5185 + SYS_LISTXATTR = 5186 + SYS_LLISTXATTR = 5187 + SYS_FLISTXATTR = 5188 + SYS_REMOVEXATTR = 5189 + SYS_LREMOVEXATTR = 5190 + SYS_FREMOVEXATTR = 5191 + SYS_TKILL = 5192 + SYS_RESERVED193 = 5193 + SYS_FUTEX = 5194 + SYS_SCHED_SETAFFINITY = 5195 + SYS_SCHED_GETAFFINITY = 5196 + SYS_CACHEFLUSH = 5197 + SYS_CACHECTL = 5198 + SYS_SYSMIPS = 5199 + SYS_IO_SETUP = 5200 + SYS_IO_DESTROY = 5201 + SYS_IO_GETEVENTS = 5202 + SYS_IO_SUBMIT = 5203 + SYS_IO_CANCEL = 5204 + SYS_EXIT_GROUP = 5205 + SYS_LOOKUP_DCOOKIE = 5206 + SYS_EPOLL_CREATE = 5207 + SYS_EPOLL_CTL = 5208 + SYS_EPOLL_WAIT = 5209 + SYS_REMAP_FILE_PAGES = 5210 + SYS_RT_SIGRETURN = 5211 + SYS_SET_TID_ADDRESS = 5212 + SYS_RESTART_SYSCALL = 5213 + SYS_SEMTIMEDOP = 5214 + SYS_FADVISE64 = 5215 + SYS_TIMER_CREATE = 5216 + SYS_TIMER_SETTIME = 5217 + SYS_TIMER_GETTIME = 5218 + SYS_TIMER_GETOVERRUN = 5219 + SYS_TIMER_DELETE = 5220 + SYS_CLOCK_SETTIME = 5221 + SYS_CLOCK_GETTIME = 5222 + SYS_CLOCK_GETRES = 5223 + SYS_CLOCK_NANOSLEEP = 5224 + SYS_TGKILL = 5225 + SYS_UTIMES = 5226 + SYS_MBIND = 5227 + SYS_GET_MEMPOLICY = 5228 + SYS_SET_MEMPOLICY = 5229 + SYS_MQ_OPEN = 5230 + SYS_MQ_UNLINK = 5231 + SYS_MQ_TIMEDSEND = 5232 + SYS_MQ_TIMEDRECEIVE = 5233 + SYS_MQ_NOTIFY = 5234 + SYS_MQ_GETSETATTR = 5235 + SYS_VSERVER = 5236 + SYS_WAITID = 5237 + SYS_ADD_KEY = 5239 + SYS_REQUEST_KEY = 5240 + SYS_KEYCTL = 5241 + SYS_SET_THREAD_AREA = 5242 + SYS_INOTIFY_INIT = 5243 + SYS_INOTIFY_ADD_WATCH = 5244 + SYS_INOTIFY_RM_WATCH = 5245 + SYS_MIGRATE_PAGES = 5246 + SYS_OPENAT = 5247 + SYS_MKDIRAT = 5248 + SYS_MKNODAT = 5249 + SYS_FCHOWNAT = 5250 + SYS_FUTIMESAT = 5251 + SYS_NEWFSTATAT = 5252 + SYS_UNLINKAT = 5253 + SYS_RENAMEAT = 5254 + SYS_LINKAT = 5255 + SYS_SYMLINKAT = 5256 + SYS_READLINKAT = 5257 + SYS_FCHMODAT = 5258 + SYS_FACCESSAT = 5259 + SYS_PSELECT6 = 5260 + SYS_PPOLL = 5261 + SYS_UNSHARE = 5262 + SYS_SPLICE = 5263 + SYS_SYNC_FILE_RANGE = 5264 + SYS_TEE = 5265 + SYS_VMSPLICE = 5266 + SYS_MOVE_PAGES = 5267 + SYS_SET_ROBUST_LIST = 5268 + SYS_GET_ROBUST_LIST = 5269 + SYS_KEXEC_LOAD = 5270 + SYS_GETCPU = 5271 + SYS_EPOLL_PWAIT = 5272 + SYS_IOPRIO_SET = 5273 + SYS_IOPRIO_GET = 5274 + SYS_UTIMENSAT = 5275 + SYS_SIGNALFD = 5276 + SYS_TIMERFD = 5277 + SYS_EVENTFD = 5278 + SYS_FALLOCATE = 5279 + SYS_TIMERFD_CREATE = 5280 + SYS_TIMERFD_GETTIME = 5281 + SYS_TIMERFD_SETTIME = 5282 + SYS_SIGNALFD4 = 5283 + SYS_EVENTFD2 = 5284 + SYS_EPOLL_CREATE1 = 5285 + SYS_DUP3 = 5286 + SYS_PIPE2 = 5287 + SYS_INOTIFY_INIT1 = 5288 + SYS_PREADV = 5289 + SYS_PWRITEV = 5290 + SYS_RT_TGSIGQUEUEINFO = 5291 + SYS_PERF_EVENT_OPEN = 5292 + SYS_ACCEPT4 = 5293 + SYS_RECVMMSG = 5294 + SYS_FANOTIFY_INIT = 5295 + SYS_FANOTIFY_MARK = 5296 + SYS_PRLIMIT64 = 5297 + SYS_NAME_TO_HANDLE_AT = 5298 + SYS_OPEN_BY_HANDLE_AT = 5299 + SYS_CLOCK_ADJTIME = 5300 + SYS_SYNCFS = 5301 + SYS_SENDMMSG = 5302 + SYS_SETNS = 5303 + SYS_PROCESS_VM_READV = 5304 + SYS_PROCESS_VM_WRITEV = 5305 + SYS_KCMP = 5306 + SYS_FINIT_MODULE = 5307 + SYS_GETDENTS64 = 5308 + SYS_SCHED_SETATTR = 5309 + SYS_SCHED_GETATTR = 5310 + SYS_RENAMEAT2 = 5311 + SYS_SECCOMP = 5312 + SYS_GETRANDOM = 5313 + SYS_MEMFD_CREATE = 5314 + SYS_BPF = 5315 + SYS_EXECVEAT = 5316 + SYS_USERFAULTFD = 5317 + SYS_MEMBARRIER = 5318 + SYS_MLOCK2 = 5319 + SYS_COPY_FILE_RANGE = 5320 + SYS_PREADV2 = 5321 + SYS_PWRITEV2 = 5322 + SYS_PKEY_MPROTECT = 5323 + SYS_PKEY_ALLOC = 5324 + SYS_PKEY_FREE = 5325 + SYS_STATX = 5326 + SYS_RSEQ = 5327 + SYS_IO_PGETEVENTS = 5328 + SYS_PIDFD_SEND_SIGNAL = 5424 + SYS_IO_URING_SETUP = 5425 + SYS_IO_URING_ENTER = 5426 + SYS_IO_URING_REGISTER = 5427 + SYS_OPEN_TREE = 5428 + SYS_MOVE_MOUNT = 5429 + SYS_FSOPEN = 5430 + SYS_FSCONFIG = 5431 + SYS_FSMOUNT = 5432 + SYS_FSPICK = 5433 + SYS_PIDFD_OPEN = 5434 + SYS_CLONE3 = 5435 + SYS_CLOSE_RANGE = 5436 + SYS_OPENAT2 = 5437 + SYS_PIDFD_GETFD = 5438 + SYS_FACCESSAT2 = 5439 + SYS_PROCESS_MADVISE = 5440 + SYS_EPOLL_PWAIT2 = 5441 + SYS_MOUNT_SETATTR = 5442 + SYS_QUOTACTL_FD = 5443 + SYS_LANDLOCK_CREATE_RULESET = 5444 + SYS_LANDLOCK_ADD_RULE = 5445 + SYS_LANDLOCK_RESTRICT_SELF = 5446 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go index 46077689ab..45082dd67f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go @@ -7,351 +7,355 @@ package unix const ( - SYS_READ = 5000 - SYS_WRITE = 5001 - SYS_OPEN = 5002 - SYS_CLOSE = 5003 - SYS_STAT = 5004 - SYS_FSTAT = 5005 - SYS_LSTAT = 5006 - SYS_POLL = 5007 - SYS_LSEEK = 5008 - SYS_MMAP = 5009 - SYS_MPROTECT = 5010 - SYS_MUNMAP = 5011 - SYS_BRK = 5012 - SYS_RT_SIGACTION = 5013 - SYS_RT_SIGPROCMASK = 5014 - SYS_IOCTL = 5015 - SYS_PREAD64 = 5016 - SYS_PWRITE64 = 5017 - SYS_READV = 5018 - SYS_WRITEV = 5019 - SYS_ACCESS = 5020 - SYS_PIPE = 5021 - SYS__NEWSELECT = 5022 - SYS_SCHED_YIELD = 5023 - SYS_MREMAP = 5024 - SYS_MSYNC = 5025 - SYS_MINCORE = 5026 - SYS_MADVISE = 5027 - SYS_SHMGET = 5028 - SYS_SHMAT = 5029 - SYS_SHMCTL = 5030 - SYS_DUP = 5031 - SYS_DUP2 = 5032 - SYS_PAUSE = 5033 - SYS_NANOSLEEP = 5034 - SYS_GETITIMER = 5035 - SYS_SETITIMER = 5036 - SYS_ALARM = 5037 - SYS_GETPID = 5038 - SYS_SENDFILE = 5039 - SYS_SOCKET = 5040 - SYS_CONNECT = 5041 - SYS_ACCEPT = 5042 - SYS_SENDTO = 5043 - SYS_RECVFROM = 5044 - SYS_SENDMSG = 5045 - SYS_RECVMSG = 5046 - SYS_SHUTDOWN = 5047 - SYS_BIND = 5048 - SYS_LISTEN = 5049 - SYS_GETSOCKNAME = 5050 - SYS_GETPEERNAME = 5051 - SYS_SOCKETPAIR = 5052 - SYS_SETSOCKOPT = 5053 - SYS_GETSOCKOPT = 5054 - SYS_CLONE = 5055 - SYS_FORK = 5056 - SYS_EXECVE = 5057 - SYS_EXIT = 5058 - SYS_WAIT4 = 5059 - SYS_KILL = 5060 - SYS_UNAME = 5061 - SYS_SEMGET = 5062 - SYS_SEMOP = 5063 - SYS_SEMCTL = 5064 - SYS_SHMDT = 5065 - SYS_MSGGET = 5066 - SYS_MSGSND = 5067 - SYS_MSGRCV = 5068 - SYS_MSGCTL = 5069 - SYS_FCNTL = 5070 - SYS_FLOCK = 5071 - SYS_FSYNC = 5072 - SYS_FDATASYNC = 5073 - SYS_TRUNCATE = 5074 - SYS_FTRUNCATE = 5075 - SYS_GETDENTS = 5076 - SYS_GETCWD = 5077 - SYS_CHDIR = 5078 - SYS_FCHDIR = 5079 - SYS_RENAME = 5080 - SYS_MKDIR = 5081 - SYS_RMDIR = 5082 - SYS_CREAT = 5083 - SYS_LINK = 5084 - SYS_UNLINK = 5085 - SYS_SYMLINK = 5086 - SYS_READLINK = 5087 - SYS_CHMOD = 5088 - SYS_FCHMOD = 5089 - SYS_CHOWN = 5090 - SYS_FCHOWN = 5091 - SYS_LCHOWN = 5092 - SYS_UMASK = 5093 - SYS_GETTIMEOFDAY = 5094 - SYS_GETRLIMIT = 5095 - SYS_GETRUSAGE = 5096 - SYS_SYSINFO = 5097 - SYS_TIMES = 5098 - SYS_PTRACE = 5099 - SYS_GETUID = 5100 - SYS_SYSLOG = 5101 - SYS_GETGID = 5102 - SYS_SETUID = 5103 - SYS_SETGID = 5104 - SYS_GETEUID = 5105 - SYS_GETEGID = 5106 - SYS_SETPGID = 5107 - SYS_GETPPID = 5108 - SYS_GETPGRP = 5109 - SYS_SETSID = 5110 - SYS_SETREUID = 5111 - SYS_SETREGID = 5112 - SYS_GETGROUPS = 5113 - SYS_SETGROUPS = 5114 - SYS_SETRESUID = 5115 - SYS_GETRESUID = 5116 - SYS_SETRESGID = 5117 - SYS_GETRESGID = 5118 - SYS_GETPGID = 5119 - SYS_SETFSUID = 5120 - SYS_SETFSGID = 5121 - SYS_GETSID = 5122 - SYS_CAPGET = 5123 - SYS_CAPSET = 5124 - SYS_RT_SIGPENDING = 5125 - SYS_RT_SIGTIMEDWAIT = 5126 - SYS_RT_SIGQUEUEINFO = 5127 - SYS_RT_SIGSUSPEND = 5128 - SYS_SIGALTSTACK = 5129 - SYS_UTIME = 5130 - SYS_MKNOD = 5131 - SYS_PERSONALITY = 5132 - SYS_USTAT = 5133 - SYS_STATFS = 5134 - SYS_FSTATFS = 5135 - SYS_SYSFS = 5136 - SYS_GETPRIORITY = 5137 - SYS_SETPRIORITY = 5138 - SYS_SCHED_SETPARAM = 5139 - SYS_SCHED_GETPARAM = 5140 - SYS_SCHED_SETSCHEDULER = 5141 - SYS_SCHED_GETSCHEDULER = 5142 - SYS_SCHED_GET_PRIORITY_MAX = 5143 - SYS_SCHED_GET_PRIORITY_MIN = 5144 - SYS_SCHED_RR_GET_INTERVAL = 5145 - SYS_MLOCK = 5146 - SYS_MUNLOCK = 5147 - SYS_MLOCKALL = 5148 - SYS_MUNLOCKALL = 5149 - SYS_VHANGUP = 5150 - SYS_PIVOT_ROOT = 5151 - SYS__SYSCTL = 5152 - SYS_PRCTL = 5153 - SYS_ADJTIMEX = 5154 - SYS_SETRLIMIT = 5155 - SYS_CHROOT = 5156 - SYS_SYNC = 5157 - SYS_ACCT = 5158 - SYS_SETTIMEOFDAY = 5159 - SYS_MOUNT = 5160 - SYS_UMOUNT2 = 5161 - SYS_SWAPON = 5162 - SYS_SWAPOFF = 5163 - SYS_REBOOT = 5164 - SYS_SETHOSTNAME = 5165 - SYS_SETDOMAINNAME = 5166 - SYS_CREATE_MODULE = 5167 - SYS_INIT_MODULE = 5168 - SYS_DELETE_MODULE = 5169 - SYS_GET_KERNEL_SYMS = 5170 - SYS_QUERY_MODULE = 5171 - SYS_QUOTACTL = 5172 - SYS_NFSSERVCTL = 5173 - SYS_GETPMSG = 5174 - SYS_PUTPMSG = 5175 - SYS_AFS_SYSCALL = 5176 - SYS_RESERVED177 = 5177 - SYS_GETTID = 5178 - SYS_READAHEAD = 5179 - SYS_SETXATTR = 5180 - SYS_LSETXATTR = 5181 - SYS_FSETXATTR = 5182 - SYS_GETXATTR = 5183 - SYS_LGETXATTR = 5184 - SYS_FGETXATTR = 5185 - SYS_LISTXATTR = 5186 - SYS_LLISTXATTR = 5187 - SYS_FLISTXATTR = 5188 - SYS_REMOVEXATTR = 5189 - SYS_LREMOVEXATTR = 5190 - SYS_FREMOVEXATTR = 5191 - SYS_TKILL = 5192 - SYS_RESERVED193 = 5193 - SYS_FUTEX = 5194 - SYS_SCHED_SETAFFINITY = 5195 - SYS_SCHED_GETAFFINITY = 5196 - SYS_CACHEFLUSH = 5197 - SYS_CACHECTL = 5198 - SYS_SYSMIPS = 5199 - SYS_IO_SETUP = 5200 - SYS_IO_DESTROY = 5201 - SYS_IO_GETEVENTS = 5202 - SYS_IO_SUBMIT = 5203 - SYS_IO_CANCEL = 5204 - SYS_EXIT_GROUP = 5205 - SYS_LOOKUP_DCOOKIE = 5206 - SYS_EPOLL_CREATE = 5207 - SYS_EPOLL_CTL = 5208 - SYS_EPOLL_WAIT = 5209 - SYS_REMAP_FILE_PAGES = 5210 - SYS_RT_SIGRETURN = 5211 - SYS_SET_TID_ADDRESS = 5212 - SYS_RESTART_SYSCALL = 5213 - SYS_SEMTIMEDOP = 5214 - SYS_FADVISE64 = 5215 - SYS_TIMER_CREATE = 5216 - SYS_TIMER_SETTIME = 5217 - SYS_TIMER_GETTIME = 5218 - SYS_TIMER_GETOVERRUN = 5219 - SYS_TIMER_DELETE = 5220 - SYS_CLOCK_SETTIME = 5221 - SYS_CLOCK_GETTIME = 5222 - SYS_CLOCK_GETRES = 5223 - SYS_CLOCK_NANOSLEEP = 5224 - SYS_TGKILL = 5225 - SYS_UTIMES = 5226 - SYS_MBIND = 5227 - SYS_GET_MEMPOLICY = 5228 - SYS_SET_MEMPOLICY = 5229 - SYS_MQ_OPEN = 5230 - SYS_MQ_UNLINK = 5231 - SYS_MQ_TIMEDSEND = 5232 - SYS_MQ_TIMEDRECEIVE = 5233 - SYS_MQ_NOTIFY = 5234 - SYS_MQ_GETSETATTR = 5235 - SYS_VSERVER = 5236 - SYS_WAITID = 5237 - SYS_ADD_KEY = 5239 - SYS_REQUEST_KEY = 5240 - SYS_KEYCTL = 5241 - SYS_SET_THREAD_AREA = 5242 - SYS_INOTIFY_INIT = 5243 - SYS_INOTIFY_ADD_WATCH = 5244 - SYS_INOTIFY_RM_WATCH = 5245 - SYS_MIGRATE_PAGES = 5246 - SYS_OPENAT = 5247 - SYS_MKDIRAT = 5248 - SYS_MKNODAT = 5249 - SYS_FCHOWNAT = 5250 - SYS_FUTIMESAT = 5251 - SYS_NEWFSTATAT = 5252 - SYS_UNLINKAT = 5253 - SYS_RENAMEAT = 5254 - SYS_LINKAT = 5255 - SYS_SYMLINKAT = 5256 - SYS_READLINKAT = 5257 - SYS_FCHMODAT = 5258 - SYS_FACCESSAT = 5259 - SYS_PSELECT6 = 5260 - SYS_PPOLL = 5261 - SYS_UNSHARE = 5262 - SYS_SPLICE = 5263 - SYS_SYNC_FILE_RANGE = 5264 - SYS_TEE = 5265 - SYS_VMSPLICE = 5266 - SYS_MOVE_PAGES = 5267 - SYS_SET_ROBUST_LIST = 5268 - SYS_GET_ROBUST_LIST = 5269 - SYS_KEXEC_LOAD = 5270 - SYS_GETCPU = 5271 - SYS_EPOLL_PWAIT = 5272 - SYS_IOPRIO_SET = 5273 - SYS_IOPRIO_GET = 5274 - SYS_UTIMENSAT = 5275 - SYS_SIGNALFD = 5276 - SYS_TIMERFD = 5277 - SYS_EVENTFD = 5278 - SYS_FALLOCATE = 5279 - SYS_TIMERFD_CREATE = 5280 - SYS_TIMERFD_GETTIME = 5281 - SYS_TIMERFD_SETTIME = 5282 - SYS_SIGNALFD4 = 5283 - SYS_EVENTFD2 = 5284 - SYS_EPOLL_CREATE1 = 5285 - SYS_DUP3 = 5286 - SYS_PIPE2 = 5287 - SYS_INOTIFY_INIT1 = 5288 - SYS_PREADV = 5289 - SYS_PWRITEV = 5290 - SYS_RT_TGSIGQUEUEINFO = 5291 - SYS_PERF_EVENT_OPEN = 5292 - SYS_ACCEPT4 = 5293 - SYS_RECVMMSG = 5294 - SYS_FANOTIFY_INIT = 5295 - SYS_FANOTIFY_MARK = 5296 - SYS_PRLIMIT64 = 5297 - SYS_NAME_TO_HANDLE_AT = 5298 - SYS_OPEN_BY_HANDLE_AT = 5299 - SYS_CLOCK_ADJTIME = 5300 - SYS_SYNCFS = 5301 - SYS_SENDMMSG = 5302 - SYS_SETNS = 5303 - SYS_PROCESS_VM_READV = 5304 - SYS_PROCESS_VM_WRITEV = 5305 - SYS_KCMP = 5306 - SYS_FINIT_MODULE = 5307 - SYS_GETDENTS64 = 5308 - SYS_SCHED_SETATTR = 5309 - SYS_SCHED_GETATTR = 5310 - SYS_RENAMEAT2 = 5311 - SYS_SECCOMP = 5312 - SYS_GETRANDOM = 5313 - SYS_MEMFD_CREATE = 5314 - SYS_BPF = 5315 - SYS_EXECVEAT = 5316 - SYS_USERFAULTFD = 5317 - SYS_MEMBARRIER = 5318 - SYS_MLOCK2 = 5319 - SYS_COPY_FILE_RANGE = 5320 - SYS_PREADV2 = 5321 - SYS_PWRITEV2 = 5322 - SYS_PKEY_MPROTECT = 5323 - SYS_PKEY_ALLOC = 5324 - SYS_PKEY_FREE = 5325 - SYS_STATX = 5326 - SYS_RSEQ = 5327 - SYS_IO_PGETEVENTS = 5328 - SYS_PIDFD_SEND_SIGNAL = 5424 - SYS_IO_URING_SETUP = 5425 - SYS_IO_URING_ENTER = 5426 - SYS_IO_URING_REGISTER = 5427 - SYS_OPEN_TREE = 5428 - SYS_MOVE_MOUNT = 5429 - SYS_FSOPEN = 5430 - SYS_FSCONFIG = 5431 - SYS_FSMOUNT = 5432 - SYS_FSPICK = 5433 - SYS_PIDFD_OPEN = 5434 - SYS_CLONE3 = 5435 - SYS_CLOSE_RANGE = 5436 - SYS_OPENAT2 = 5437 - SYS_PIDFD_GETFD = 5438 - SYS_FACCESSAT2 = 5439 - SYS_PROCESS_MADVISE = 5440 - SYS_EPOLL_PWAIT2 = 5441 - SYS_MOUNT_SETATTR = 5442 + SYS_READ = 5000 + SYS_WRITE = 5001 + SYS_OPEN = 5002 + SYS_CLOSE = 5003 + SYS_STAT = 5004 + SYS_FSTAT = 5005 + SYS_LSTAT = 5006 + SYS_POLL = 5007 + SYS_LSEEK = 5008 + SYS_MMAP = 5009 + SYS_MPROTECT = 5010 + SYS_MUNMAP = 5011 + SYS_BRK = 5012 + SYS_RT_SIGACTION = 5013 + SYS_RT_SIGPROCMASK = 5014 + SYS_IOCTL = 5015 + SYS_PREAD64 = 5016 + SYS_PWRITE64 = 5017 + SYS_READV = 5018 + SYS_WRITEV = 5019 + SYS_ACCESS = 5020 + SYS_PIPE = 5021 + SYS__NEWSELECT = 5022 + SYS_SCHED_YIELD = 5023 + SYS_MREMAP = 5024 + SYS_MSYNC = 5025 + SYS_MINCORE = 5026 + SYS_MADVISE = 5027 + SYS_SHMGET = 5028 + SYS_SHMAT = 5029 + SYS_SHMCTL = 5030 + SYS_DUP = 5031 + SYS_DUP2 = 5032 + SYS_PAUSE = 5033 + SYS_NANOSLEEP = 5034 + SYS_GETITIMER = 5035 + SYS_SETITIMER = 5036 + SYS_ALARM = 5037 + SYS_GETPID = 5038 + SYS_SENDFILE = 5039 + SYS_SOCKET = 5040 + SYS_CONNECT = 5041 + SYS_ACCEPT = 5042 + SYS_SENDTO = 5043 + SYS_RECVFROM = 5044 + SYS_SENDMSG = 5045 + SYS_RECVMSG = 5046 + SYS_SHUTDOWN = 5047 + SYS_BIND = 5048 + SYS_LISTEN = 5049 + SYS_GETSOCKNAME = 5050 + SYS_GETPEERNAME = 5051 + SYS_SOCKETPAIR = 5052 + SYS_SETSOCKOPT = 5053 + SYS_GETSOCKOPT = 5054 + SYS_CLONE = 5055 + SYS_FORK = 5056 + SYS_EXECVE = 5057 + SYS_EXIT = 5058 + SYS_WAIT4 = 5059 + SYS_KILL = 5060 + SYS_UNAME = 5061 + SYS_SEMGET = 5062 + SYS_SEMOP = 5063 + SYS_SEMCTL = 5064 + SYS_SHMDT = 5065 + SYS_MSGGET = 5066 + SYS_MSGSND = 5067 + SYS_MSGRCV = 5068 + SYS_MSGCTL = 5069 + SYS_FCNTL = 5070 + SYS_FLOCK = 5071 + SYS_FSYNC = 5072 + SYS_FDATASYNC = 5073 + SYS_TRUNCATE = 5074 + SYS_FTRUNCATE = 5075 + SYS_GETDENTS = 5076 + SYS_GETCWD = 5077 + SYS_CHDIR = 5078 + SYS_FCHDIR = 5079 + SYS_RENAME = 5080 + SYS_MKDIR = 5081 + SYS_RMDIR = 5082 + SYS_CREAT = 5083 + SYS_LINK = 5084 + SYS_UNLINK = 5085 + SYS_SYMLINK = 5086 + SYS_READLINK = 5087 + SYS_CHMOD = 5088 + SYS_FCHMOD = 5089 + SYS_CHOWN = 5090 + SYS_FCHOWN = 5091 + SYS_LCHOWN = 5092 + SYS_UMASK = 5093 + SYS_GETTIMEOFDAY = 5094 + SYS_GETRLIMIT = 5095 + SYS_GETRUSAGE = 5096 + SYS_SYSINFO = 5097 + SYS_TIMES = 5098 + SYS_PTRACE = 5099 + SYS_GETUID = 5100 + SYS_SYSLOG = 5101 + SYS_GETGID = 5102 + SYS_SETUID = 5103 + SYS_SETGID = 5104 + SYS_GETEUID = 5105 + SYS_GETEGID = 5106 + SYS_SETPGID = 5107 + SYS_GETPPID = 5108 + SYS_GETPGRP = 5109 + SYS_SETSID = 5110 + SYS_SETREUID = 5111 + SYS_SETREGID = 5112 + SYS_GETGROUPS = 5113 + SYS_SETGROUPS = 5114 + SYS_SETRESUID = 5115 + SYS_GETRESUID = 5116 + SYS_SETRESGID = 5117 + SYS_GETRESGID = 5118 + SYS_GETPGID = 5119 + SYS_SETFSUID = 5120 + SYS_SETFSGID = 5121 + SYS_GETSID = 5122 + SYS_CAPGET = 5123 + SYS_CAPSET = 5124 + SYS_RT_SIGPENDING = 5125 + SYS_RT_SIGTIMEDWAIT = 5126 + SYS_RT_SIGQUEUEINFO = 5127 + SYS_RT_SIGSUSPEND = 5128 + SYS_SIGALTSTACK = 5129 + SYS_UTIME = 5130 + SYS_MKNOD = 5131 + SYS_PERSONALITY = 5132 + SYS_USTAT = 5133 + SYS_STATFS = 5134 + SYS_FSTATFS = 5135 + SYS_SYSFS = 5136 + SYS_GETPRIORITY = 5137 + SYS_SETPRIORITY = 5138 + SYS_SCHED_SETPARAM = 5139 + SYS_SCHED_GETPARAM = 5140 + SYS_SCHED_SETSCHEDULER = 5141 + SYS_SCHED_GETSCHEDULER = 5142 + SYS_SCHED_GET_PRIORITY_MAX = 5143 + SYS_SCHED_GET_PRIORITY_MIN = 5144 + SYS_SCHED_RR_GET_INTERVAL = 5145 + SYS_MLOCK = 5146 + SYS_MUNLOCK = 5147 + SYS_MLOCKALL = 5148 + SYS_MUNLOCKALL = 5149 + SYS_VHANGUP = 5150 + SYS_PIVOT_ROOT = 5151 + SYS__SYSCTL = 5152 + SYS_PRCTL = 5153 + SYS_ADJTIMEX = 5154 + SYS_SETRLIMIT = 5155 + SYS_CHROOT = 5156 + SYS_SYNC = 5157 + SYS_ACCT = 5158 + SYS_SETTIMEOFDAY = 5159 + SYS_MOUNT = 5160 + SYS_UMOUNT2 = 5161 + SYS_SWAPON = 5162 + SYS_SWAPOFF = 5163 + SYS_REBOOT = 5164 + SYS_SETHOSTNAME = 5165 + SYS_SETDOMAINNAME = 5166 + SYS_CREATE_MODULE = 5167 + SYS_INIT_MODULE = 5168 + SYS_DELETE_MODULE = 5169 + SYS_GET_KERNEL_SYMS = 5170 + SYS_QUERY_MODULE = 5171 + SYS_QUOTACTL = 5172 + SYS_NFSSERVCTL = 5173 + SYS_GETPMSG = 5174 + SYS_PUTPMSG = 5175 + SYS_AFS_SYSCALL = 5176 + SYS_RESERVED177 = 5177 + SYS_GETTID = 5178 + SYS_READAHEAD = 5179 + SYS_SETXATTR = 5180 + SYS_LSETXATTR = 5181 + SYS_FSETXATTR = 5182 + SYS_GETXATTR = 5183 + SYS_LGETXATTR = 5184 + SYS_FGETXATTR = 5185 + SYS_LISTXATTR = 5186 + SYS_LLISTXATTR = 5187 + SYS_FLISTXATTR = 5188 + SYS_REMOVEXATTR = 5189 + SYS_LREMOVEXATTR = 5190 + SYS_FREMOVEXATTR = 5191 + SYS_TKILL = 5192 + SYS_RESERVED193 = 5193 + SYS_FUTEX = 5194 + SYS_SCHED_SETAFFINITY = 5195 + SYS_SCHED_GETAFFINITY = 5196 + SYS_CACHEFLUSH = 5197 + SYS_CACHECTL = 5198 + SYS_SYSMIPS = 5199 + SYS_IO_SETUP = 5200 + SYS_IO_DESTROY = 5201 + SYS_IO_GETEVENTS = 5202 + SYS_IO_SUBMIT = 5203 + SYS_IO_CANCEL = 5204 + SYS_EXIT_GROUP = 5205 + SYS_LOOKUP_DCOOKIE = 5206 + SYS_EPOLL_CREATE = 5207 + SYS_EPOLL_CTL = 5208 + SYS_EPOLL_WAIT = 5209 + SYS_REMAP_FILE_PAGES = 5210 + SYS_RT_SIGRETURN = 5211 + SYS_SET_TID_ADDRESS = 5212 + SYS_RESTART_SYSCALL = 5213 + SYS_SEMTIMEDOP = 5214 + SYS_FADVISE64 = 5215 + SYS_TIMER_CREATE = 5216 + SYS_TIMER_SETTIME = 5217 + SYS_TIMER_GETTIME = 5218 + SYS_TIMER_GETOVERRUN = 5219 + SYS_TIMER_DELETE = 5220 + SYS_CLOCK_SETTIME = 5221 + SYS_CLOCK_GETTIME = 5222 + SYS_CLOCK_GETRES = 5223 + SYS_CLOCK_NANOSLEEP = 5224 + SYS_TGKILL = 5225 + SYS_UTIMES = 5226 + SYS_MBIND = 5227 + SYS_GET_MEMPOLICY = 5228 + SYS_SET_MEMPOLICY = 5229 + SYS_MQ_OPEN = 5230 + SYS_MQ_UNLINK = 5231 + SYS_MQ_TIMEDSEND = 5232 + SYS_MQ_TIMEDRECEIVE = 5233 + SYS_MQ_NOTIFY = 5234 + SYS_MQ_GETSETATTR = 5235 + SYS_VSERVER = 5236 + SYS_WAITID = 5237 + SYS_ADD_KEY = 5239 + SYS_REQUEST_KEY = 5240 + SYS_KEYCTL = 5241 + SYS_SET_THREAD_AREA = 5242 + SYS_INOTIFY_INIT = 5243 + SYS_INOTIFY_ADD_WATCH = 5244 + SYS_INOTIFY_RM_WATCH = 5245 + SYS_MIGRATE_PAGES = 5246 + SYS_OPENAT = 5247 + SYS_MKDIRAT = 5248 + SYS_MKNODAT = 5249 + SYS_FCHOWNAT = 5250 + SYS_FUTIMESAT = 5251 + SYS_NEWFSTATAT = 5252 + SYS_UNLINKAT = 5253 + SYS_RENAMEAT = 5254 + SYS_LINKAT = 5255 + SYS_SYMLINKAT = 5256 + SYS_READLINKAT = 5257 + SYS_FCHMODAT = 5258 + SYS_FACCESSAT = 5259 + SYS_PSELECT6 = 5260 + SYS_PPOLL = 5261 + SYS_UNSHARE = 5262 + SYS_SPLICE = 5263 + SYS_SYNC_FILE_RANGE = 5264 + SYS_TEE = 5265 + SYS_VMSPLICE = 5266 + SYS_MOVE_PAGES = 5267 + SYS_SET_ROBUST_LIST = 5268 + SYS_GET_ROBUST_LIST = 5269 + SYS_KEXEC_LOAD = 5270 + SYS_GETCPU = 5271 + SYS_EPOLL_PWAIT = 5272 + SYS_IOPRIO_SET = 5273 + SYS_IOPRIO_GET = 5274 + SYS_UTIMENSAT = 5275 + SYS_SIGNALFD = 5276 + SYS_TIMERFD = 5277 + SYS_EVENTFD = 5278 + SYS_FALLOCATE = 5279 + SYS_TIMERFD_CREATE = 5280 + SYS_TIMERFD_GETTIME = 5281 + SYS_TIMERFD_SETTIME = 5282 + SYS_SIGNALFD4 = 5283 + SYS_EVENTFD2 = 5284 + SYS_EPOLL_CREATE1 = 5285 + SYS_DUP3 = 5286 + SYS_PIPE2 = 5287 + SYS_INOTIFY_INIT1 = 5288 + SYS_PREADV = 5289 + SYS_PWRITEV = 5290 + SYS_RT_TGSIGQUEUEINFO = 5291 + SYS_PERF_EVENT_OPEN = 5292 + SYS_ACCEPT4 = 5293 + SYS_RECVMMSG = 5294 + SYS_FANOTIFY_INIT = 5295 + SYS_FANOTIFY_MARK = 5296 + SYS_PRLIMIT64 = 5297 + SYS_NAME_TO_HANDLE_AT = 5298 + SYS_OPEN_BY_HANDLE_AT = 5299 + SYS_CLOCK_ADJTIME = 5300 + SYS_SYNCFS = 5301 + SYS_SENDMMSG = 5302 + SYS_SETNS = 5303 + SYS_PROCESS_VM_READV = 5304 + SYS_PROCESS_VM_WRITEV = 5305 + SYS_KCMP = 5306 + SYS_FINIT_MODULE = 5307 + SYS_GETDENTS64 = 5308 + SYS_SCHED_SETATTR = 5309 + SYS_SCHED_GETATTR = 5310 + SYS_RENAMEAT2 = 5311 + SYS_SECCOMP = 5312 + SYS_GETRANDOM = 5313 + SYS_MEMFD_CREATE = 5314 + SYS_BPF = 5315 + SYS_EXECVEAT = 5316 + SYS_USERFAULTFD = 5317 + SYS_MEMBARRIER = 5318 + SYS_MLOCK2 = 5319 + SYS_COPY_FILE_RANGE = 5320 + SYS_PREADV2 = 5321 + SYS_PWRITEV2 = 5322 + SYS_PKEY_MPROTECT = 5323 + SYS_PKEY_ALLOC = 5324 + SYS_PKEY_FREE = 5325 + SYS_STATX = 5326 + SYS_RSEQ = 5327 + SYS_IO_PGETEVENTS = 5328 + SYS_PIDFD_SEND_SIGNAL = 5424 + SYS_IO_URING_SETUP = 5425 + SYS_IO_URING_ENTER = 5426 + SYS_IO_URING_REGISTER = 5427 + SYS_OPEN_TREE = 5428 + SYS_MOVE_MOUNT = 5429 + SYS_FSOPEN = 5430 + SYS_FSCONFIG = 5431 + SYS_FSMOUNT = 5432 + SYS_FSPICK = 5433 + SYS_PIDFD_OPEN = 5434 + SYS_CLONE3 = 5435 + SYS_CLOSE_RANGE = 5436 + SYS_OPENAT2 = 5437 + SYS_PIDFD_GETFD = 5438 + SYS_FACCESSAT2 = 5439 + SYS_PROCESS_MADVISE = 5440 + SYS_EPOLL_PWAIT2 = 5441 + SYS_MOUNT_SETATTR = 5442 + SYS_QUOTACTL_FD = 5443 + SYS_LANDLOCK_CREATE_RULESET = 5444 + SYS_LANDLOCK_ADD_RULE = 5445 + SYS_LANDLOCK_RESTRICT_SELF = 5446 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go index 80e6696b39..570a857a56 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go @@ -424,4 +424,8 @@ const ( SYS_PROCESS_MADVISE = 4440 SYS_EPOLL_PWAIT2 = 4441 SYS_MOUNT_SETATTR = 4442 + SYS_QUOTACTL_FD = 4443 + SYS_LANDLOCK_CREATE_RULESET = 4444 + SYS_LANDLOCK_ADD_RULE = 4445 + SYS_LANDLOCK_RESTRICT_SELF = 4446 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go index b9d697ffb1..638498d62e 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go @@ -431,4 +431,8 @@ const ( SYS_PROCESS_MADVISE = 440 SYS_EPOLL_PWAIT2 = 441 SYS_MOUNT_SETATTR = 442 + SYS_QUOTACTL_FD = 443 + SYS_LANDLOCK_CREATE_RULESET = 444 + SYS_LANDLOCK_ADD_RULE = 445 + SYS_LANDLOCK_RESTRICT_SELF = 446 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go index 08edc54d35..702beebfef 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go @@ -7,400 +7,404 @@ package unix const ( - SYS_RESTART_SYSCALL = 0 - SYS_EXIT = 1 - SYS_FORK = 2 - SYS_READ = 3 - SYS_WRITE = 4 - SYS_OPEN = 5 - SYS_CLOSE = 6 - SYS_WAITPID = 7 - SYS_CREAT = 8 - SYS_LINK = 9 - SYS_UNLINK = 10 - SYS_EXECVE = 11 - SYS_CHDIR = 12 - SYS_TIME = 13 - SYS_MKNOD = 14 - SYS_CHMOD = 15 - SYS_LCHOWN = 16 - SYS_BREAK = 17 - SYS_OLDSTAT = 18 - SYS_LSEEK = 19 - SYS_GETPID = 20 - SYS_MOUNT = 21 - SYS_UMOUNT = 22 - SYS_SETUID = 23 - SYS_GETUID = 24 - SYS_STIME = 25 - SYS_PTRACE = 26 - SYS_ALARM = 27 - SYS_OLDFSTAT = 28 - SYS_PAUSE = 29 - SYS_UTIME = 30 - SYS_STTY = 31 - SYS_GTTY = 32 - SYS_ACCESS = 33 - SYS_NICE = 34 - SYS_FTIME = 35 - SYS_SYNC = 36 - SYS_KILL = 37 - SYS_RENAME = 38 - SYS_MKDIR = 39 - SYS_RMDIR = 40 - SYS_DUP = 41 - SYS_PIPE = 42 - SYS_TIMES = 43 - SYS_PROF = 44 - SYS_BRK = 45 - SYS_SETGID = 46 - SYS_GETGID = 47 - SYS_SIGNAL = 48 - SYS_GETEUID = 49 - SYS_GETEGID = 50 - SYS_ACCT = 51 - SYS_UMOUNT2 = 52 - SYS_LOCK = 53 - SYS_IOCTL = 54 - SYS_FCNTL = 55 - SYS_MPX = 56 - SYS_SETPGID = 57 - SYS_ULIMIT = 58 - SYS_OLDOLDUNAME = 59 - SYS_UMASK = 60 - SYS_CHROOT = 61 - SYS_USTAT = 62 - SYS_DUP2 = 63 - SYS_GETPPID = 64 - SYS_GETPGRP = 65 - SYS_SETSID = 66 - SYS_SIGACTION = 67 - SYS_SGETMASK = 68 - SYS_SSETMASK = 69 - SYS_SETREUID = 70 - SYS_SETREGID = 71 - SYS_SIGSUSPEND = 72 - SYS_SIGPENDING = 73 - SYS_SETHOSTNAME = 74 - SYS_SETRLIMIT = 75 - SYS_GETRLIMIT = 76 - SYS_GETRUSAGE = 77 - SYS_GETTIMEOFDAY = 78 - SYS_SETTIMEOFDAY = 79 - SYS_GETGROUPS = 80 - SYS_SETGROUPS = 81 - SYS_SELECT = 82 - SYS_SYMLINK = 83 - SYS_OLDLSTAT = 84 - SYS_READLINK = 85 - SYS_USELIB = 86 - SYS_SWAPON = 87 - SYS_REBOOT = 88 - SYS_READDIR = 89 - SYS_MMAP = 90 - SYS_MUNMAP = 91 - SYS_TRUNCATE = 92 - SYS_FTRUNCATE = 93 - SYS_FCHMOD = 94 - SYS_FCHOWN = 95 - SYS_GETPRIORITY = 96 - SYS_SETPRIORITY = 97 - SYS_PROFIL = 98 - SYS_STATFS = 99 - SYS_FSTATFS = 100 - SYS_IOPERM = 101 - SYS_SOCKETCALL = 102 - SYS_SYSLOG = 103 - SYS_SETITIMER = 104 - SYS_GETITIMER = 105 - SYS_STAT = 106 - SYS_LSTAT = 107 - SYS_FSTAT = 108 - SYS_OLDUNAME = 109 - SYS_IOPL = 110 - SYS_VHANGUP = 111 - SYS_IDLE = 112 - SYS_VM86 = 113 - SYS_WAIT4 = 114 - SYS_SWAPOFF = 115 - SYS_SYSINFO = 116 - SYS_IPC = 117 - SYS_FSYNC = 118 - SYS_SIGRETURN = 119 - SYS_CLONE = 120 - SYS_SETDOMAINNAME = 121 - SYS_UNAME = 122 - SYS_MODIFY_LDT = 123 - SYS_ADJTIMEX = 124 - SYS_MPROTECT = 125 - SYS_SIGPROCMASK = 126 - SYS_CREATE_MODULE = 127 - SYS_INIT_MODULE = 128 - SYS_DELETE_MODULE = 129 - SYS_GET_KERNEL_SYMS = 130 - SYS_QUOTACTL = 131 - SYS_GETPGID = 132 - SYS_FCHDIR = 133 - SYS_BDFLUSH = 134 - SYS_SYSFS = 135 - SYS_PERSONALITY = 136 - SYS_AFS_SYSCALL = 137 - SYS_SETFSUID = 138 - SYS_SETFSGID = 139 - SYS__LLSEEK = 140 - SYS_GETDENTS = 141 - SYS__NEWSELECT = 142 - SYS_FLOCK = 143 - SYS_MSYNC = 144 - SYS_READV = 145 - SYS_WRITEV = 146 - SYS_GETSID = 147 - SYS_FDATASYNC = 148 - SYS__SYSCTL = 149 - SYS_MLOCK = 150 - SYS_MUNLOCK = 151 - SYS_MLOCKALL = 152 - SYS_MUNLOCKALL = 153 - SYS_SCHED_SETPARAM = 154 - SYS_SCHED_GETPARAM = 155 - SYS_SCHED_SETSCHEDULER = 156 - SYS_SCHED_GETSCHEDULER = 157 - SYS_SCHED_YIELD = 158 - SYS_SCHED_GET_PRIORITY_MAX = 159 - SYS_SCHED_GET_PRIORITY_MIN = 160 - SYS_SCHED_RR_GET_INTERVAL = 161 - SYS_NANOSLEEP = 162 - SYS_MREMAP = 163 - SYS_SETRESUID = 164 - SYS_GETRESUID = 165 - SYS_QUERY_MODULE = 166 - SYS_POLL = 167 - SYS_NFSSERVCTL = 168 - SYS_SETRESGID = 169 - SYS_GETRESGID = 170 - SYS_PRCTL = 171 - SYS_RT_SIGRETURN = 172 - SYS_RT_SIGACTION = 173 - SYS_RT_SIGPROCMASK = 174 - SYS_RT_SIGPENDING = 175 - SYS_RT_SIGTIMEDWAIT = 176 - SYS_RT_SIGQUEUEINFO = 177 - SYS_RT_SIGSUSPEND = 178 - SYS_PREAD64 = 179 - SYS_PWRITE64 = 180 - SYS_CHOWN = 181 - SYS_GETCWD = 182 - SYS_CAPGET = 183 - SYS_CAPSET = 184 - SYS_SIGALTSTACK = 185 - SYS_SENDFILE = 186 - SYS_GETPMSG = 187 - SYS_PUTPMSG = 188 - SYS_VFORK = 189 - SYS_UGETRLIMIT = 190 - SYS_READAHEAD = 191 - SYS_PCICONFIG_READ = 198 - SYS_PCICONFIG_WRITE = 199 - SYS_PCICONFIG_IOBASE = 200 - SYS_MULTIPLEXER = 201 - SYS_GETDENTS64 = 202 - SYS_PIVOT_ROOT = 203 - SYS_MADVISE = 205 - SYS_MINCORE = 206 - SYS_GETTID = 207 - SYS_TKILL = 208 - SYS_SETXATTR = 209 - SYS_LSETXATTR = 210 - SYS_FSETXATTR = 211 - SYS_GETXATTR = 212 - SYS_LGETXATTR = 213 - SYS_FGETXATTR = 214 - SYS_LISTXATTR = 215 - SYS_LLISTXATTR = 216 - SYS_FLISTXATTR = 217 - SYS_REMOVEXATTR = 218 - SYS_LREMOVEXATTR = 219 - SYS_FREMOVEXATTR = 220 - SYS_FUTEX = 221 - SYS_SCHED_SETAFFINITY = 222 - SYS_SCHED_GETAFFINITY = 223 - SYS_TUXCALL = 225 - SYS_IO_SETUP = 227 - SYS_IO_DESTROY = 228 - SYS_IO_GETEVENTS = 229 - SYS_IO_SUBMIT = 230 - SYS_IO_CANCEL = 231 - SYS_SET_TID_ADDRESS = 232 - SYS_FADVISE64 = 233 - SYS_EXIT_GROUP = 234 - SYS_LOOKUP_DCOOKIE = 235 - SYS_EPOLL_CREATE = 236 - SYS_EPOLL_CTL = 237 - SYS_EPOLL_WAIT = 238 - SYS_REMAP_FILE_PAGES = 239 - SYS_TIMER_CREATE = 240 - SYS_TIMER_SETTIME = 241 - SYS_TIMER_GETTIME = 242 - SYS_TIMER_GETOVERRUN = 243 - SYS_TIMER_DELETE = 244 - SYS_CLOCK_SETTIME = 245 - SYS_CLOCK_GETTIME = 246 - SYS_CLOCK_GETRES = 247 - SYS_CLOCK_NANOSLEEP = 248 - SYS_SWAPCONTEXT = 249 - SYS_TGKILL = 250 - SYS_UTIMES = 251 - SYS_STATFS64 = 252 - SYS_FSTATFS64 = 253 - SYS_RTAS = 255 - SYS_SYS_DEBUG_SETCONTEXT = 256 - SYS_MIGRATE_PAGES = 258 - SYS_MBIND = 259 - SYS_GET_MEMPOLICY = 260 - SYS_SET_MEMPOLICY = 261 - SYS_MQ_OPEN = 262 - SYS_MQ_UNLINK = 263 - SYS_MQ_TIMEDSEND = 264 - SYS_MQ_TIMEDRECEIVE = 265 - SYS_MQ_NOTIFY = 266 - SYS_MQ_GETSETATTR = 267 - SYS_KEXEC_LOAD = 268 - SYS_ADD_KEY = 269 - SYS_REQUEST_KEY = 270 - SYS_KEYCTL = 271 - SYS_WAITID = 272 - SYS_IOPRIO_SET = 273 - SYS_IOPRIO_GET = 274 - SYS_INOTIFY_INIT = 275 - SYS_INOTIFY_ADD_WATCH = 276 - SYS_INOTIFY_RM_WATCH = 277 - SYS_SPU_RUN = 278 - SYS_SPU_CREATE = 279 - SYS_PSELECT6 = 280 - SYS_PPOLL = 281 - SYS_UNSHARE = 282 - SYS_SPLICE = 283 - SYS_TEE = 284 - SYS_VMSPLICE = 285 - SYS_OPENAT = 286 - SYS_MKDIRAT = 287 - SYS_MKNODAT = 288 - SYS_FCHOWNAT = 289 - SYS_FUTIMESAT = 290 - SYS_NEWFSTATAT = 291 - SYS_UNLINKAT = 292 - SYS_RENAMEAT = 293 - SYS_LINKAT = 294 - SYS_SYMLINKAT = 295 - SYS_READLINKAT = 296 - SYS_FCHMODAT = 297 - SYS_FACCESSAT = 298 - SYS_GET_ROBUST_LIST = 299 - SYS_SET_ROBUST_LIST = 300 - SYS_MOVE_PAGES = 301 - SYS_GETCPU = 302 - SYS_EPOLL_PWAIT = 303 - SYS_UTIMENSAT = 304 - SYS_SIGNALFD = 305 - SYS_TIMERFD_CREATE = 306 - SYS_EVENTFD = 307 - SYS_SYNC_FILE_RANGE2 = 308 - SYS_FALLOCATE = 309 - SYS_SUBPAGE_PROT = 310 - SYS_TIMERFD_SETTIME = 311 - SYS_TIMERFD_GETTIME = 312 - SYS_SIGNALFD4 = 313 - SYS_EVENTFD2 = 314 - SYS_EPOLL_CREATE1 = 315 - SYS_DUP3 = 316 - SYS_PIPE2 = 317 - SYS_INOTIFY_INIT1 = 318 - SYS_PERF_EVENT_OPEN = 319 - SYS_PREADV = 320 - SYS_PWRITEV = 321 - SYS_RT_TGSIGQUEUEINFO = 322 - SYS_FANOTIFY_INIT = 323 - SYS_FANOTIFY_MARK = 324 - SYS_PRLIMIT64 = 325 - SYS_SOCKET = 326 - SYS_BIND = 327 - SYS_CONNECT = 328 - SYS_LISTEN = 329 - SYS_ACCEPT = 330 - SYS_GETSOCKNAME = 331 - SYS_GETPEERNAME = 332 - SYS_SOCKETPAIR = 333 - SYS_SEND = 334 - SYS_SENDTO = 335 - SYS_RECV = 336 - SYS_RECVFROM = 337 - SYS_SHUTDOWN = 338 - SYS_SETSOCKOPT = 339 - SYS_GETSOCKOPT = 340 - SYS_SENDMSG = 341 - SYS_RECVMSG = 342 - SYS_RECVMMSG = 343 - SYS_ACCEPT4 = 344 - SYS_NAME_TO_HANDLE_AT = 345 - SYS_OPEN_BY_HANDLE_AT = 346 - SYS_CLOCK_ADJTIME = 347 - SYS_SYNCFS = 348 - SYS_SENDMMSG = 349 - SYS_SETNS = 350 - SYS_PROCESS_VM_READV = 351 - SYS_PROCESS_VM_WRITEV = 352 - SYS_FINIT_MODULE = 353 - SYS_KCMP = 354 - SYS_SCHED_SETATTR = 355 - SYS_SCHED_GETATTR = 356 - SYS_RENAMEAT2 = 357 - SYS_SECCOMP = 358 - SYS_GETRANDOM = 359 - SYS_MEMFD_CREATE = 360 - SYS_BPF = 361 - SYS_EXECVEAT = 362 - SYS_SWITCH_ENDIAN = 363 - SYS_USERFAULTFD = 364 - SYS_MEMBARRIER = 365 - SYS_MLOCK2 = 378 - SYS_COPY_FILE_RANGE = 379 - SYS_PREADV2 = 380 - SYS_PWRITEV2 = 381 - SYS_KEXEC_FILE_LOAD = 382 - SYS_STATX = 383 - SYS_PKEY_ALLOC = 384 - SYS_PKEY_FREE = 385 - SYS_PKEY_MPROTECT = 386 - SYS_RSEQ = 387 - SYS_IO_PGETEVENTS = 388 - SYS_SEMTIMEDOP = 392 - SYS_SEMGET = 393 - SYS_SEMCTL = 394 - SYS_SHMGET = 395 - SYS_SHMCTL = 396 - SYS_SHMAT = 397 - SYS_SHMDT = 398 - SYS_MSGGET = 399 - SYS_MSGSND = 400 - SYS_MSGRCV = 401 - SYS_MSGCTL = 402 - SYS_PIDFD_SEND_SIGNAL = 424 - SYS_IO_URING_SETUP = 425 - SYS_IO_URING_ENTER = 426 - SYS_IO_URING_REGISTER = 427 - SYS_OPEN_TREE = 428 - SYS_MOVE_MOUNT = 429 - SYS_FSOPEN = 430 - SYS_FSCONFIG = 431 - SYS_FSMOUNT = 432 - SYS_FSPICK = 433 - SYS_PIDFD_OPEN = 434 - SYS_CLONE3 = 435 - SYS_CLOSE_RANGE = 436 - SYS_OPENAT2 = 437 - SYS_PIDFD_GETFD = 438 - SYS_FACCESSAT2 = 439 - SYS_PROCESS_MADVISE = 440 - SYS_EPOLL_PWAIT2 = 441 - SYS_MOUNT_SETATTR = 442 + SYS_RESTART_SYSCALL = 0 + SYS_EXIT = 1 + SYS_FORK = 2 + SYS_READ = 3 + SYS_WRITE = 4 + SYS_OPEN = 5 + SYS_CLOSE = 6 + SYS_WAITPID = 7 + SYS_CREAT = 8 + SYS_LINK = 9 + SYS_UNLINK = 10 + SYS_EXECVE = 11 + SYS_CHDIR = 12 + SYS_TIME = 13 + SYS_MKNOD = 14 + SYS_CHMOD = 15 + SYS_LCHOWN = 16 + SYS_BREAK = 17 + SYS_OLDSTAT = 18 + SYS_LSEEK = 19 + SYS_GETPID = 20 + SYS_MOUNT = 21 + SYS_UMOUNT = 22 + SYS_SETUID = 23 + SYS_GETUID = 24 + SYS_STIME = 25 + SYS_PTRACE = 26 + SYS_ALARM = 27 + SYS_OLDFSTAT = 28 + SYS_PAUSE = 29 + SYS_UTIME = 30 + SYS_STTY = 31 + SYS_GTTY = 32 + SYS_ACCESS = 33 + SYS_NICE = 34 + SYS_FTIME = 35 + SYS_SYNC = 36 + SYS_KILL = 37 + SYS_RENAME = 38 + SYS_MKDIR = 39 + SYS_RMDIR = 40 + SYS_DUP = 41 + SYS_PIPE = 42 + SYS_TIMES = 43 + SYS_PROF = 44 + SYS_BRK = 45 + SYS_SETGID = 46 + SYS_GETGID = 47 + SYS_SIGNAL = 48 + SYS_GETEUID = 49 + SYS_GETEGID = 50 + SYS_ACCT = 51 + SYS_UMOUNT2 = 52 + SYS_LOCK = 53 + SYS_IOCTL = 54 + SYS_FCNTL = 55 + SYS_MPX = 56 + SYS_SETPGID = 57 + SYS_ULIMIT = 58 + SYS_OLDOLDUNAME = 59 + SYS_UMASK = 60 + SYS_CHROOT = 61 + SYS_USTAT = 62 + SYS_DUP2 = 63 + SYS_GETPPID = 64 + SYS_GETPGRP = 65 + SYS_SETSID = 66 + SYS_SIGACTION = 67 + SYS_SGETMASK = 68 + SYS_SSETMASK = 69 + SYS_SETREUID = 70 + SYS_SETREGID = 71 + SYS_SIGSUSPEND = 72 + SYS_SIGPENDING = 73 + SYS_SETHOSTNAME = 74 + SYS_SETRLIMIT = 75 + SYS_GETRLIMIT = 76 + SYS_GETRUSAGE = 77 + SYS_GETTIMEOFDAY = 78 + SYS_SETTIMEOFDAY = 79 + SYS_GETGROUPS = 80 + SYS_SETGROUPS = 81 + SYS_SELECT = 82 + SYS_SYMLINK = 83 + SYS_OLDLSTAT = 84 + SYS_READLINK = 85 + SYS_USELIB = 86 + SYS_SWAPON = 87 + SYS_REBOOT = 88 + SYS_READDIR = 89 + SYS_MMAP = 90 + SYS_MUNMAP = 91 + SYS_TRUNCATE = 92 + SYS_FTRUNCATE = 93 + SYS_FCHMOD = 94 + SYS_FCHOWN = 95 + SYS_GETPRIORITY = 96 + SYS_SETPRIORITY = 97 + SYS_PROFIL = 98 + SYS_STATFS = 99 + SYS_FSTATFS = 100 + SYS_IOPERM = 101 + SYS_SOCKETCALL = 102 + SYS_SYSLOG = 103 + SYS_SETITIMER = 104 + SYS_GETITIMER = 105 + SYS_STAT = 106 + SYS_LSTAT = 107 + SYS_FSTAT = 108 + SYS_OLDUNAME = 109 + SYS_IOPL = 110 + SYS_VHANGUP = 111 + SYS_IDLE = 112 + SYS_VM86 = 113 + SYS_WAIT4 = 114 + SYS_SWAPOFF = 115 + SYS_SYSINFO = 116 + SYS_IPC = 117 + SYS_FSYNC = 118 + SYS_SIGRETURN = 119 + SYS_CLONE = 120 + SYS_SETDOMAINNAME = 121 + SYS_UNAME = 122 + SYS_MODIFY_LDT = 123 + SYS_ADJTIMEX = 124 + SYS_MPROTECT = 125 + SYS_SIGPROCMASK = 126 + SYS_CREATE_MODULE = 127 + SYS_INIT_MODULE = 128 + SYS_DELETE_MODULE = 129 + SYS_GET_KERNEL_SYMS = 130 + SYS_QUOTACTL = 131 + SYS_GETPGID = 132 + SYS_FCHDIR = 133 + SYS_BDFLUSH = 134 + SYS_SYSFS = 135 + SYS_PERSONALITY = 136 + SYS_AFS_SYSCALL = 137 + SYS_SETFSUID = 138 + SYS_SETFSGID = 139 + SYS__LLSEEK = 140 + SYS_GETDENTS = 141 + SYS__NEWSELECT = 142 + SYS_FLOCK = 143 + SYS_MSYNC = 144 + SYS_READV = 145 + SYS_WRITEV = 146 + SYS_GETSID = 147 + SYS_FDATASYNC = 148 + SYS__SYSCTL = 149 + SYS_MLOCK = 150 + SYS_MUNLOCK = 151 + SYS_MLOCKALL = 152 + SYS_MUNLOCKALL = 153 + SYS_SCHED_SETPARAM = 154 + SYS_SCHED_GETPARAM = 155 + SYS_SCHED_SETSCHEDULER = 156 + SYS_SCHED_GETSCHEDULER = 157 + SYS_SCHED_YIELD = 158 + SYS_SCHED_GET_PRIORITY_MAX = 159 + SYS_SCHED_GET_PRIORITY_MIN = 160 + SYS_SCHED_RR_GET_INTERVAL = 161 + SYS_NANOSLEEP = 162 + SYS_MREMAP = 163 + SYS_SETRESUID = 164 + SYS_GETRESUID = 165 + SYS_QUERY_MODULE = 166 + SYS_POLL = 167 + SYS_NFSSERVCTL = 168 + SYS_SETRESGID = 169 + SYS_GETRESGID = 170 + SYS_PRCTL = 171 + SYS_RT_SIGRETURN = 172 + SYS_RT_SIGACTION = 173 + SYS_RT_SIGPROCMASK = 174 + SYS_RT_SIGPENDING = 175 + SYS_RT_SIGTIMEDWAIT = 176 + SYS_RT_SIGQUEUEINFO = 177 + SYS_RT_SIGSUSPEND = 178 + SYS_PREAD64 = 179 + SYS_PWRITE64 = 180 + SYS_CHOWN = 181 + SYS_GETCWD = 182 + SYS_CAPGET = 183 + SYS_CAPSET = 184 + SYS_SIGALTSTACK = 185 + SYS_SENDFILE = 186 + SYS_GETPMSG = 187 + SYS_PUTPMSG = 188 + SYS_VFORK = 189 + SYS_UGETRLIMIT = 190 + SYS_READAHEAD = 191 + SYS_PCICONFIG_READ = 198 + SYS_PCICONFIG_WRITE = 199 + SYS_PCICONFIG_IOBASE = 200 + SYS_MULTIPLEXER = 201 + SYS_GETDENTS64 = 202 + SYS_PIVOT_ROOT = 203 + SYS_MADVISE = 205 + SYS_MINCORE = 206 + SYS_GETTID = 207 + SYS_TKILL = 208 + SYS_SETXATTR = 209 + SYS_LSETXATTR = 210 + SYS_FSETXATTR = 211 + SYS_GETXATTR = 212 + SYS_LGETXATTR = 213 + SYS_FGETXATTR = 214 + SYS_LISTXATTR = 215 + SYS_LLISTXATTR = 216 + SYS_FLISTXATTR = 217 + SYS_REMOVEXATTR = 218 + SYS_LREMOVEXATTR = 219 + SYS_FREMOVEXATTR = 220 + SYS_FUTEX = 221 + SYS_SCHED_SETAFFINITY = 222 + SYS_SCHED_GETAFFINITY = 223 + SYS_TUXCALL = 225 + SYS_IO_SETUP = 227 + SYS_IO_DESTROY = 228 + SYS_IO_GETEVENTS = 229 + SYS_IO_SUBMIT = 230 + SYS_IO_CANCEL = 231 + SYS_SET_TID_ADDRESS = 232 + SYS_FADVISE64 = 233 + SYS_EXIT_GROUP = 234 + SYS_LOOKUP_DCOOKIE = 235 + SYS_EPOLL_CREATE = 236 + SYS_EPOLL_CTL = 237 + SYS_EPOLL_WAIT = 238 + SYS_REMAP_FILE_PAGES = 239 + SYS_TIMER_CREATE = 240 + SYS_TIMER_SETTIME = 241 + SYS_TIMER_GETTIME = 242 + SYS_TIMER_GETOVERRUN = 243 + SYS_TIMER_DELETE = 244 + SYS_CLOCK_SETTIME = 245 + SYS_CLOCK_GETTIME = 246 + SYS_CLOCK_GETRES = 247 + SYS_CLOCK_NANOSLEEP = 248 + SYS_SWAPCONTEXT = 249 + SYS_TGKILL = 250 + SYS_UTIMES = 251 + SYS_STATFS64 = 252 + SYS_FSTATFS64 = 253 + SYS_RTAS = 255 + SYS_SYS_DEBUG_SETCONTEXT = 256 + SYS_MIGRATE_PAGES = 258 + SYS_MBIND = 259 + SYS_GET_MEMPOLICY = 260 + SYS_SET_MEMPOLICY = 261 + SYS_MQ_OPEN = 262 + SYS_MQ_UNLINK = 263 + SYS_MQ_TIMEDSEND = 264 + SYS_MQ_TIMEDRECEIVE = 265 + SYS_MQ_NOTIFY = 266 + SYS_MQ_GETSETATTR = 267 + SYS_KEXEC_LOAD = 268 + SYS_ADD_KEY = 269 + SYS_REQUEST_KEY = 270 + SYS_KEYCTL = 271 + SYS_WAITID = 272 + SYS_IOPRIO_SET = 273 + SYS_IOPRIO_GET = 274 + SYS_INOTIFY_INIT = 275 + SYS_INOTIFY_ADD_WATCH = 276 + SYS_INOTIFY_RM_WATCH = 277 + SYS_SPU_RUN = 278 + SYS_SPU_CREATE = 279 + SYS_PSELECT6 = 280 + SYS_PPOLL = 281 + SYS_UNSHARE = 282 + SYS_SPLICE = 283 + SYS_TEE = 284 + SYS_VMSPLICE = 285 + SYS_OPENAT = 286 + SYS_MKDIRAT = 287 + SYS_MKNODAT = 288 + SYS_FCHOWNAT = 289 + SYS_FUTIMESAT = 290 + SYS_NEWFSTATAT = 291 + SYS_UNLINKAT = 292 + SYS_RENAMEAT = 293 + SYS_LINKAT = 294 + SYS_SYMLINKAT = 295 + SYS_READLINKAT = 296 + SYS_FCHMODAT = 297 + SYS_FACCESSAT = 298 + SYS_GET_ROBUST_LIST = 299 + SYS_SET_ROBUST_LIST = 300 + SYS_MOVE_PAGES = 301 + SYS_GETCPU = 302 + SYS_EPOLL_PWAIT = 303 + SYS_UTIMENSAT = 304 + SYS_SIGNALFD = 305 + SYS_TIMERFD_CREATE = 306 + SYS_EVENTFD = 307 + SYS_SYNC_FILE_RANGE2 = 308 + SYS_FALLOCATE = 309 + SYS_SUBPAGE_PROT = 310 + SYS_TIMERFD_SETTIME = 311 + SYS_TIMERFD_GETTIME = 312 + SYS_SIGNALFD4 = 313 + SYS_EVENTFD2 = 314 + SYS_EPOLL_CREATE1 = 315 + SYS_DUP3 = 316 + SYS_PIPE2 = 317 + SYS_INOTIFY_INIT1 = 318 + SYS_PERF_EVENT_OPEN = 319 + SYS_PREADV = 320 + SYS_PWRITEV = 321 + SYS_RT_TGSIGQUEUEINFO = 322 + SYS_FANOTIFY_INIT = 323 + SYS_FANOTIFY_MARK = 324 + SYS_PRLIMIT64 = 325 + SYS_SOCKET = 326 + SYS_BIND = 327 + SYS_CONNECT = 328 + SYS_LISTEN = 329 + SYS_ACCEPT = 330 + SYS_GETSOCKNAME = 331 + SYS_GETPEERNAME = 332 + SYS_SOCKETPAIR = 333 + SYS_SEND = 334 + SYS_SENDTO = 335 + SYS_RECV = 336 + SYS_RECVFROM = 337 + SYS_SHUTDOWN = 338 + SYS_SETSOCKOPT = 339 + SYS_GETSOCKOPT = 340 + SYS_SENDMSG = 341 + SYS_RECVMSG = 342 + SYS_RECVMMSG = 343 + SYS_ACCEPT4 = 344 + SYS_NAME_TO_HANDLE_AT = 345 + SYS_OPEN_BY_HANDLE_AT = 346 + SYS_CLOCK_ADJTIME = 347 + SYS_SYNCFS = 348 + SYS_SENDMMSG = 349 + SYS_SETNS = 350 + SYS_PROCESS_VM_READV = 351 + SYS_PROCESS_VM_WRITEV = 352 + SYS_FINIT_MODULE = 353 + SYS_KCMP = 354 + SYS_SCHED_SETATTR = 355 + SYS_SCHED_GETATTR = 356 + SYS_RENAMEAT2 = 357 + SYS_SECCOMP = 358 + SYS_GETRANDOM = 359 + SYS_MEMFD_CREATE = 360 + SYS_BPF = 361 + SYS_EXECVEAT = 362 + SYS_SWITCH_ENDIAN = 363 + SYS_USERFAULTFD = 364 + SYS_MEMBARRIER = 365 + SYS_MLOCK2 = 378 + SYS_COPY_FILE_RANGE = 379 + SYS_PREADV2 = 380 + SYS_PWRITEV2 = 381 + SYS_KEXEC_FILE_LOAD = 382 + SYS_STATX = 383 + SYS_PKEY_ALLOC = 384 + SYS_PKEY_FREE = 385 + SYS_PKEY_MPROTECT = 386 + SYS_RSEQ = 387 + SYS_IO_PGETEVENTS = 388 + SYS_SEMTIMEDOP = 392 + SYS_SEMGET = 393 + SYS_SEMCTL = 394 + SYS_SHMGET = 395 + SYS_SHMCTL = 396 + SYS_SHMAT = 397 + SYS_SHMDT = 398 + SYS_MSGGET = 399 + SYS_MSGSND = 400 + SYS_MSGRCV = 401 + SYS_MSGCTL = 402 + SYS_PIDFD_SEND_SIGNAL = 424 + SYS_IO_URING_SETUP = 425 + SYS_IO_URING_ENTER = 426 + SYS_IO_URING_REGISTER = 427 + SYS_OPEN_TREE = 428 + SYS_MOVE_MOUNT = 429 + SYS_FSOPEN = 430 + SYS_FSCONFIG = 431 + SYS_FSMOUNT = 432 + SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 + SYS_CLOSE_RANGE = 436 + SYS_OPENAT2 = 437 + SYS_PIDFD_GETFD = 438 + SYS_FACCESSAT2 = 439 + SYS_PROCESS_MADVISE = 440 + SYS_EPOLL_PWAIT2 = 441 + SYS_MOUNT_SETATTR = 442 + SYS_QUOTACTL_FD = 443 + SYS_LANDLOCK_CREATE_RULESET = 444 + SYS_LANDLOCK_ADD_RULE = 445 + SYS_LANDLOCK_RESTRICT_SELF = 446 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go index 33b33b0834..bfc87ea444 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go @@ -7,400 +7,404 @@ package unix const ( - SYS_RESTART_SYSCALL = 0 - SYS_EXIT = 1 - SYS_FORK = 2 - SYS_READ = 3 - SYS_WRITE = 4 - SYS_OPEN = 5 - SYS_CLOSE = 6 - SYS_WAITPID = 7 - SYS_CREAT = 8 - SYS_LINK = 9 - SYS_UNLINK = 10 - SYS_EXECVE = 11 - SYS_CHDIR = 12 - SYS_TIME = 13 - SYS_MKNOD = 14 - SYS_CHMOD = 15 - SYS_LCHOWN = 16 - SYS_BREAK = 17 - SYS_OLDSTAT = 18 - SYS_LSEEK = 19 - SYS_GETPID = 20 - SYS_MOUNT = 21 - SYS_UMOUNT = 22 - SYS_SETUID = 23 - SYS_GETUID = 24 - SYS_STIME = 25 - SYS_PTRACE = 26 - SYS_ALARM = 27 - SYS_OLDFSTAT = 28 - SYS_PAUSE = 29 - SYS_UTIME = 30 - SYS_STTY = 31 - SYS_GTTY = 32 - SYS_ACCESS = 33 - SYS_NICE = 34 - SYS_FTIME = 35 - SYS_SYNC = 36 - SYS_KILL = 37 - SYS_RENAME = 38 - SYS_MKDIR = 39 - SYS_RMDIR = 40 - SYS_DUP = 41 - SYS_PIPE = 42 - SYS_TIMES = 43 - SYS_PROF = 44 - SYS_BRK = 45 - SYS_SETGID = 46 - SYS_GETGID = 47 - SYS_SIGNAL = 48 - SYS_GETEUID = 49 - SYS_GETEGID = 50 - SYS_ACCT = 51 - SYS_UMOUNT2 = 52 - SYS_LOCK = 53 - SYS_IOCTL = 54 - SYS_FCNTL = 55 - SYS_MPX = 56 - SYS_SETPGID = 57 - SYS_ULIMIT = 58 - SYS_OLDOLDUNAME = 59 - SYS_UMASK = 60 - SYS_CHROOT = 61 - SYS_USTAT = 62 - SYS_DUP2 = 63 - SYS_GETPPID = 64 - SYS_GETPGRP = 65 - SYS_SETSID = 66 - SYS_SIGACTION = 67 - SYS_SGETMASK = 68 - SYS_SSETMASK = 69 - SYS_SETREUID = 70 - SYS_SETREGID = 71 - SYS_SIGSUSPEND = 72 - SYS_SIGPENDING = 73 - SYS_SETHOSTNAME = 74 - SYS_SETRLIMIT = 75 - SYS_GETRLIMIT = 76 - SYS_GETRUSAGE = 77 - SYS_GETTIMEOFDAY = 78 - SYS_SETTIMEOFDAY = 79 - SYS_GETGROUPS = 80 - SYS_SETGROUPS = 81 - SYS_SELECT = 82 - SYS_SYMLINK = 83 - SYS_OLDLSTAT = 84 - SYS_READLINK = 85 - SYS_USELIB = 86 - SYS_SWAPON = 87 - SYS_REBOOT = 88 - SYS_READDIR = 89 - SYS_MMAP = 90 - SYS_MUNMAP = 91 - SYS_TRUNCATE = 92 - SYS_FTRUNCATE = 93 - SYS_FCHMOD = 94 - SYS_FCHOWN = 95 - SYS_GETPRIORITY = 96 - SYS_SETPRIORITY = 97 - SYS_PROFIL = 98 - SYS_STATFS = 99 - SYS_FSTATFS = 100 - SYS_IOPERM = 101 - SYS_SOCKETCALL = 102 - SYS_SYSLOG = 103 - SYS_SETITIMER = 104 - SYS_GETITIMER = 105 - SYS_STAT = 106 - SYS_LSTAT = 107 - SYS_FSTAT = 108 - SYS_OLDUNAME = 109 - SYS_IOPL = 110 - SYS_VHANGUP = 111 - SYS_IDLE = 112 - SYS_VM86 = 113 - SYS_WAIT4 = 114 - SYS_SWAPOFF = 115 - SYS_SYSINFO = 116 - SYS_IPC = 117 - SYS_FSYNC = 118 - SYS_SIGRETURN = 119 - SYS_CLONE = 120 - SYS_SETDOMAINNAME = 121 - SYS_UNAME = 122 - SYS_MODIFY_LDT = 123 - SYS_ADJTIMEX = 124 - SYS_MPROTECT = 125 - SYS_SIGPROCMASK = 126 - SYS_CREATE_MODULE = 127 - SYS_INIT_MODULE = 128 - SYS_DELETE_MODULE = 129 - SYS_GET_KERNEL_SYMS = 130 - SYS_QUOTACTL = 131 - SYS_GETPGID = 132 - SYS_FCHDIR = 133 - SYS_BDFLUSH = 134 - SYS_SYSFS = 135 - SYS_PERSONALITY = 136 - SYS_AFS_SYSCALL = 137 - SYS_SETFSUID = 138 - SYS_SETFSGID = 139 - SYS__LLSEEK = 140 - SYS_GETDENTS = 141 - SYS__NEWSELECT = 142 - SYS_FLOCK = 143 - SYS_MSYNC = 144 - SYS_READV = 145 - SYS_WRITEV = 146 - SYS_GETSID = 147 - SYS_FDATASYNC = 148 - SYS__SYSCTL = 149 - SYS_MLOCK = 150 - SYS_MUNLOCK = 151 - SYS_MLOCKALL = 152 - SYS_MUNLOCKALL = 153 - SYS_SCHED_SETPARAM = 154 - SYS_SCHED_GETPARAM = 155 - SYS_SCHED_SETSCHEDULER = 156 - SYS_SCHED_GETSCHEDULER = 157 - SYS_SCHED_YIELD = 158 - SYS_SCHED_GET_PRIORITY_MAX = 159 - SYS_SCHED_GET_PRIORITY_MIN = 160 - SYS_SCHED_RR_GET_INTERVAL = 161 - SYS_NANOSLEEP = 162 - SYS_MREMAP = 163 - SYS_SETRESUID = 164 - SYS_GETRESUID = 165 - SYS_QUERY_MODULE = 166 - SYS_POLL = 167 - SYS_NFSSERVCTL = 168 - SYS_SETRESGID = 169 - SYS_GETRESGID = 170 - SYS_PRCTL = 171 - SYS_RT_SIGRETURN = 172 - SYS_RT_SIGACTION = 173 - SYS_RT_SIGPROCMASK = 174 - SYS_RT_SIGPENDING = 175 - SYS_RT_SIGTIMEDWAIT = 176 - SYS_RT_SIGQUEUEINFO = 177 - SYS_RT_SIGSUSPEND = 178 - SYS_PREAD64 = 179 - SYS_PWRITE64 = 180 - SYS_CHOWN = 181 - SYS_GETCWD = 182 - SYS_CAPGET = 183 - SYS_CAPSET = 184 - SYS_SIGALTSTACK = 185 - SYS_SENDFILE = 186 - SYS_GETPMSG = 187 - SYS_PUTPMSG = 188 - SYS_VFORK = 189 - SYS_UGETRLIMIT = 190 - SYS_READAHEAD = 191 - SYS_PCICONFIG_READ = 198 - SYS_PCICONFIG_WRITE = 199 - SYS_PCICONFIG_IOBASE = 200 - SYS_MULTIPLEXER = 201 - SYS_GETDENTS64 = 202 - SYS_PIVOT_ROOT = 203 - SYS_MADVISE = 205 - SYS_MINCORE = 206 - SYS_GETTID = 207 - SYS_TKILL = 208 - SYS_SETXATTR = 209 - SYS_LSETXATTR = 210 - SYS_FSETXATTR = 211 - SYS_GETXATTR = 212 - SYS_LGETXATTR = 213 - SYS_FGETXATTR = 214 - SYS_LISTXATTR = 215 - SYS_LLISTXATTR = 216 - SYS_FLISTXATTR = 217 - SYS_REMOVEXATTR = 218 - SYS_LREMOVEXATTR = 219 - SYS_FREMOVEXATTR = 220 - SYS_FUTEX = 221 - SYS_SCHED_SETAFFINITY = 222 - SYS_SCHED_GETAFFINITY = 223 - SYS_TUXCALL = 225 - SYS_IO_SETUP = 227 - SYS_IO_DESTROY = 228 - SYS_IO_GETEVENTS = 229 - SYS_IO_SUBMIT = 230 - SYS_IO_CANCEL = 231 - SYS_SET_TID_ADDRESS = 232 - SYS_FADVISE64 = 233 - SYS_EXIT_GROUP = 234 - SYS_LOOKUP_DCOOKIE = 235 - SYS_EPOLL_CREATE = 236 - SYS_EPOLL_CTL = 237 - SYS_EPOLL_WAIT = 238 - SYS_REMAP_FILE_PAGES = 239 - SYS_TIMER_CREATE = 240 - SYS_TIMER_SETTIME = 241 - SYS_TIMER_GETTIME = 242 - SYS_TIMER_GETOVERRUN = 243 - SYS_TIMER_DELETE = 244 - SYS_CLOCK_SETTIME = 245 - SYS_CLOCK_GETTIME = 246 - SYS_CLOCK_GETRES = 247 - SYS_CLOCK_NANOSLEEP = 248 - SYS_SWAPCONTEXT = 249 - SYS_TGKILL = 250 - SYS_UTIMES = 251 - SYS_STATFS64 = 252 - SYS_FSTATFS64 = 253 - SYS_RTAS = 255 - SYS_SYS_DEBUG_SETCONTEXT = 256 - SYS_MIGRATE_PAGES = 258 - SYS_MBIND = 259 - SYS_GET_MEMPOLICY = 260 - SYS_SET_MEMPOLICY = 261 - SYS_MQ_OPEN = 262 - SYS_MQ_UNLINK = 263 - SYS_MQ_TIMEDSEND = 264 - SYS_MQ_TIMEDRECEIVE = 265 - SYS_MQ_NOTIFY = 266 - SYS_MQ_GETSETATTR = 267 - SYS_KEXEC_LOAD = 268 - SYS_ADD_KEY = 269 - SYS_REQUEST_KEY = 270 - SYS_KEYCTL = 271 - SYS_WAITID = 272 - SYS_IOPRIO_SET = 273 - SYS_IOPRIO_GET = 274 - SYS_INOTIFY_INIT = 275 - SYS_INOTIFY_ADD_WATCH = 276 - SYS_INOTIFY_RM_WATCH = 277 - SYS_SPU_RUN = 278 - SYS_SPU_CREATE = 279 - SYS_PSELECT6 = 280 - SYS_PPOLL = 281 - SYS_UNSHARE = 282 - SYS_SPLICE = 283 - SYS_TEE = 284 - SYS_VMSPLICE = 285 - SYS_OPENAT = 286 - SYS_MKDIRAT = 287 - SYS_MKNODAT = 288 - SYS_FCHOWNAT = 289 - SYS_FUTIMESAT = 290 - SYS_NEWFSTATAT = 291 - SYS_UNLINKAT = 292 - SYS_RENAMEAT = 293 - SYS_LINKAT = 294 - SYS_SYMLINKAT = 295 - SYS_READLINKAT = 296 - SYS_FCHMODAT = 297 - SYS_FACCESSAT = 298 - SYS_GET_ROBUST_LIST = 299 - SYS_SET_ROBUST_LIST = 300 - SYS_MOVE_PAGES = 301 - SYS_GETCPU = 302 - SYS_EPOLL_PWAIT = 303 - SYS_UTIMENSAT = 304 - SYS_SIGNALFD = 305 - SYS_TIMERFD_CREATE = 306 - SYS_EVENTFD = 307 - SYS_SYNC_FILE_RANGE2 = 308 - SYS_FALLOCATE = 309 - SYS_SUBPAGE_PROT = 310 - SYS_TIMERFD_SETTIME = 311 - SYS_TIMERFD_GETTIME = 312 - SYS_SIGNALFD4 = 313 - SYS_EVENTFD2 = 314 - SYS_EPOLL_CREATE1 = 315 - SYS_DUP3 = 316 - SYS_PIPE2 = 317 - SYS_INOTIFY_INIT1 = 318 - SYS_PERF_EVENT_OPEN = 319 - SYS_PREADV = 320 - SYS_PWRITEV = 321 - SYS_RT_TGSIGQUEUEINFO = 322 - SYS_FANOTIFY_INIT = 323 - SYS_FANOTIFY_MARK = 324 - SYS_PRLIMIT64 = 325 - SYS_SOCKET = 326 - SYS_BIND = 327 - SYS_CONNECT = 328 - SYS_LISTEN = 329 - SYS_ACCEPT = 330 - SYS_GETSOCKNAME = 331 - SYS_GETPEERNAME = 332 - SYS_SOCKETPAIR = 333 - SYS_SEND = 334 - SYS_SENDTO = 335 - SYS_RECV = 336 - SYS_RECVFROM = 337 - SYS_SHUTDOWN = 338 - SYS_SETSOCKOPT = 339 - SYS_GETSOCKOPT = 340 - SYS_SENDMSG = 341 - SYS_RECVMSG = 342 - SYS_RECVMMSG = 343 - SYS_ACCEPT4 = 344 - SYS_NAME_TO_HANDLE_AT = 345 - SYS_OPEN_BY_HANDLE_AT = 346 - SYS_CLOCK_ADJTIME = 347 - SYS_SYNCFS = 348 - SYS_SENDMMSG = 349 - SYS_SETNS = 350 - SYS_PROCESS_VM_READV = 351 - SYS_PROCESS_VM_WRITEV = 352 - SYS_FINIT_MODULE = 353 - SYS_KCMP = 354 - SYS_SCHED_SETATTR = 355 - SYS_SCHED_GETATTR = 356 - SYS_RENAMEAT2 = 357 - SYS_SECCOMP = 358 - SYS_GETRANDOM = 359 - SYS_MEMFD_CREATE = 360 - SYS_BPF = 361 - SYS_EXECVEAT = 362 - SYS_SWITCH_ENDIAN = 363 - SYS_USERFAULTFD = 364 - SYS_MEMBARRIER = 365 - SYS_MLOCK2 = 378 - SYS_COPY_FILE_RANGE = 379 - SYS_PREADV2 = 380 - SYS_PWRITEV2 = 381 - SYS_KEXEC_FILE_LOAD = 382 - SYS_STATX = 383 - SYS_PKEY_ALLOC = 384 - SYS_PKEY_FREE = 385 - SYS_PKEY_MPROTECT = 386 - SYS_RSEQ = 387 - SYS_IO_PGETEVENTS = 388 - SYS_SEMTIMEDOP = 392 - SYS_SEMGET = 393 - SYS_SEMCTL = 394 - SYS_SHMGET = 395 - SYS_SHMCTL = 396 - SYS_SHMAT = 397 - SYS_SHMDT = 398 - SYS_MSGGET = 399 - SYS_MSGSND = 400 - SYS_MSGRCV = 401 - SYS_MSGCTL = 402 - SYS_PIDFD_SEND_SIGNAL = 424 - SYS_IO_URING_SETUP = 425 - SYS_IO_URING_ENTER = 426 - SYS_IO_URING_REGISTER = 427 - SYS_OPEN_TREE = 428 - SYS_MOVE_MOUNT = 429 - SYS_FSOPEN = 430 - SYS_FSCONFIG = 431 - SYS_FSMOUNT = 432 - SYS_FSPICK = 433 - SYS_PIDFD_OPEN = 434 - SYS_CLONE3 = 435 - SYS_CLOSE_RANGE = 436 - SYS_OPENAT2 = 437 - SYS_PIDFD_GETFD = 438 - SYS_FACCESSAT2 = 439 - SYS_PROCESS_MADVISE = 440 - SYS_EPOLL_PWAIT2 = 441 - SYS_MOUNT_SETATTR = 442 + SYS_RESTART_SYSCALL = 0 + SYS_EXIT = 1 + SYS_FORK = 2 + SYS_READ = 3 + SYS_WRITE = 4 + SYS_OPEN = 5 + SYS_CLOSE = 6 + SYS_WAITPID = 7 + SYS_CREAT = 8 + SYS_LINK = 9 + SYS_UNLINK = 10 + SYS_EXECVE = 11 + SYS_CHDIR = 12 + SYS_TIME = 13 + SYS_MKNOD = 14 + SYS_CHMOD = 15 + SYS_LCHOWN = 16 + SYS_BREAK = 17 + SYS_OLDSTAT = 18 + SYS_LSEEK = 19 + SYS_GETPID = 20 + SYS_MOUNT = 21 + SYS_UMOUNT = 22 + SYS_SETUID = 23 + SYS_GETUID = 24 + SYS_STIME = 25 + SYS_PTRACE = 26 + SYS_ALARM = 27 + SYS_OLDFSTAT = 28 + SYS_PAUSE = 29 + SYS_UTIME = 30 + SYS_STTY = 31 + SYS_GTTY = 32 + SYS_ACCESS = 33 + SYS_NICE = 34 + SYS_FTIME = 35 + SYS_SYNC = 36 + SYS_KILL = 37 + SYS_RENAME = 38 + SYS_MKDIR = 39 + SYS_RMDIR = 40 + SYS_DUP = 41 + SYS_PIPE = 42 + SYS_TIMES = 43 + SYS_PROF = 44 + SYS_BRK = 45 + SYS_SETGID = 46 + SYS_GETGID = 47 + SYS_SIGNAL = 48 + SYS_GETEUID = 49 + SYS_GETEGID = 50 + SYS_ACCT = 51 + SYS_UMOUNT2 = 52 + SYS_LOCK = 53 + SYS_IOCTL = 54 + SYS_FCNTL = 55 + SYS_MPX = 56 + SYS_SETPGID = 57 + SYS_ULIMIT = 58 + SYS_OLDOLDUNAME = 59 + SYS_UMASK = 60 + SYS_CHROOT = 61 + SYS_USTAT = 62 + SYS_DUP2 = 63 + SYS_GETPPID = 64 + SYS_GETPGRP = 65 + SYS_SETSID = 66 + SYS_SIGACTION = 67 + SYS_SGETMASK = 68 + SYS_SSETMASK = 69 + SYS_SETREUID = 70 + SYS_SETREGID = 71 + SYS_SIGSUSPEND = 72 + SYS_SIGPENDING = 73 + SYS_SETHOSTNAME = 74 + SYS_SETRLIMIT = 75 + SYS_GETRLIMIT = 76 + SYS_GETRUSAGE = 77 + SYS_GETTIMEOFDAY = 78 + SYS_SETTIMEOFDAY = 79 + SYS_GETGROUPS = 80 + SYS_SETGROUPS = 81 + SYS_SELECT = 82 + SYS_SYMLINK = 83 + SYS_OLDLSTAT = 84 + SYS_READLINK = 85 + SYS_USELIB = 86 + SYS_SWAPON = 87 + SYS_REBOOT = 88 + SYS_READDIR = 89 + SYS_MMAP = 90 + SYS_MUNMAP = 91 + SYS_TRUNCATE = 92 + SYS_FTRUNCATE = 93 + SYS_FCHMOD = 94 + SYS_FCHOWN = 95 + SYS_GETPRIORITY = 96 + SYS_SETPRIORITY = 97 + SYS_PROFIL = 98 + SYS_STATFS = 99 + SYS_FSTATFS = 100 + SYS_IOPERM = 101 + SYS_SOCKETCALL = 102 + SYS_SYSLOG = 103 + SYS_SETITIMER = 104 + SYS_GETITIMER = 105 + SYS_STAT = 106 + SYS_LSTAT = 107 + SYS_FSTAT = 108 + SYS_OLDUNAME = 109 + SYS_IOPL = 110 + SYS_VHANGUP = 111 + SYS_IDLE = 112 + SYS_VM86 = 113 + SYS_WAIT4 = 114 + SYS_SWAPOFF = 115 + SYS_SYSINFO = 116 + SYS_IPC = 117 + SYS_FSYNC = 118 + SYS_SIGRETURN = 119 + SYS_CLONE = 120 + SYS_SETDOMAINNAME = 121 + SYS_UNAME = 122 + SYS_MODIFY_LDT = 123 + SYS_ADJTIMEX = 124 + SYS_MPROTECT = 125 + SYS_SIGPROCMASK = 126 + SYS_CREATE_MODULE = 127 + SYS_INIT_MODULE = 128 + SYS_DELETE_MODULE = 129 + SYS_GET_KERNEL_SYMS = 130 + SYS_QUOTACTL = 131 + SYS_GETPGID = 132 + SYS_FCHDIR = 133 + SYS_BDFLUSH = 134 + SYS_SYSFS = 135 + SYS_PERSONALITY = 136 + SYS_AFS_SYSCALL = 137 + SYS_SETFSUID = 138 + SYS_SETFSGID = 139 + SYS__LLSEEK = 140 + SYS_GETDENTS = 141 + SYS__NEWSELECT = 142 + SYS_FLOCK = 143 + SYS_MSYNC = 144 + SYS_READV = 145 + SYS_WRITEV = 146 + SYS_GETSID = 147 + SYS_FDATASYNC = 148 + SYS__SYSCTL = 149 + SYS_MLOCK = 150 + SYS_MUNLOCK = 151 + SYS_MLOCKALL = 152 + SYS_MUNLOCKALL = 153 + SYS_SCHED_SETPARAM = 154 + SYS_SCHED_GETPARAM = 155 + SYS_SCHED_SETSCHEDULER = 156 + SYS_SCHED_GETSCHEDULER = 157 + SYS_SCHED_YIELD = 158 + SYS_SCHED_GET_PRIORITY_MAX = 159 + SYS_SCHED_GET_PRIORITY_MIN = 160 + SYS_SCHED_RR_GET_INTERVAL = 161 + SYS_NANOSLEEP = 162 + SYS_MREMAP = 163 + SYS_SETRESUID = 164 + SYS_GETRESUID = 165 + SYS_QUERY_MODULE = 166 + SYS_POLL = 167 + SYS_NFSSERVCTL = 168 + SYS_SETRESGID = 169 + SYS_GETRESGID = 170 + SYS_PRCTL = 171 + SYS_RT_SIGRETURN = 172 + SYS_RT_SIGACTION = 173 + SYS_RT_SIGPROCMASK = 174 + SYS_RT_SIGPENDING = 175 + SYS_RT_SIGTIMEDWAIT = 176 + SYS_RT_SIGQUEUEINFO = 177 + SYS_RT_SIGSUSPEND = 178 + SYS_PREAD64 = 179 + SYS_PWRITE64 = 180 + SYS_CHOWN = 181 + SYS_GETCWD = 182 + SYS_CAPGET = 183 + SYS_CAPSET = 184 + SYS_SIGALTSTACK = 185 + SYS_SENDFILE = 186 + SYS_GETPMSG = 187 + SYS_PUTPMSG = 188 + SYS_VFORK = 189 + SYS_UGETRLIMIT = 190 + SYS_READAHEAD = 191 + SYS_PCICONFIG_READ = 198 + SYS_PCICONFIG_WRITE = 199 + SYS_PCICONFIG_IOBASE = 200 + SYS_MULTIPLEXER = 201 + SYS_GETDENTS64 = 202 + SYS_PIVOT_ROOT = 203 + SYS_MADVISE = 205 + SYS_MINCORE = 206 + SYS_GETTID = 207 + SYS_TKILL = 208 + SYS_SETXATTR = 209 + SYS_LSETXATTR = 210 + SYS_FSETXATTR = 211 + SYS_GETXATTR = 212 + SYS_LGETXATTR = 213 + SYS_FGETXATTR = 214 + SYS_LISTXATTR = 215 + SYS_LLISTXATTR = 216 + SYS_FLISTXATTR = 217 + SYS_REMOVEXATTR = 218 + SYS_LREMOVEXATTR = 219 + SYS_FREMOVEXATTR = 220 + SYS_FUTEX = 221 + SYS_SCHED_SETAFFINITY = 222 + SYS_SCHED_GETAFFINITY = 223 + SYS_TUXCALL = 225 + SYS_IO_SETUP = 227 + SYS_IO_DESTROY = 228 + SYS_IO_GETEVENTS = 229 + SYS_IO_SUBMIT = 230 + SYS_IO_CANCEL = 231 + SYS_SET_TID_ADDRESS = 232 + SYS_FADVISE64 = 233 + SYS_EXIT_GROUP = 234 + SYS_LOOKUP_DCOOKIE = 235 + SYS_EPOLL_CREATE = 236 + SYS_EPOLL_CTL = 237 + SYS_EPOLL_WAIT = 238 + SYS_REMAP_FILE_PAGES = 239 + SYS_TIMER_CREATE = 240 + SYS_TIMER_SETTIME = 241 + SYS_TIMER_GETTIME = 242 + SYS_TIMER_GETOVERRUN = 243 + SYS_TIMER_DELETE = 244 + SYS_CLOCK_SETTIME = 245 + SYS_CLOCK_GETTIME = 246 + SYS_CLOCK_GETRES = 247 + SYS_CLOCK_NANOSLEEP = 248 + SYS_SWAPCONTEXT = 249 + SYS_TGKILL = 250 + SYS_UTIMES = 251 + SYS_STATFS64 = 252 + SYS_FSTATFS64 = 253 + SYS_RTAS = 255 + SYS_SYS_DEBUG_SETCONTEXT = 256 + SYS_MIGRATE_PAGES = 258 + SYS_MBIND = 259 + SYS_GET_MEMPOLICY = 260 + SYS_SET_MEMPOLICY = 261 + SYS_MQ_OPEN = 262 + SYS_MQ_UNLINK = 263 + SYS_MQ_TIMEDSEND = 264 + SYS_MQ_TIMEDRECEIVE = 265 + SYS_MQ_NOTIFY = 266 + SYS_MQ_GETSETATTR = 267 + SYS_KEXEC_LOAD = 268 + SYS_ADD_KEY = 269 + SYS_REQUEST_KEY = 270 + SYS_KEYCTL = 271 + SYS_WAITID = 272 + SYS_IOPRIO_SET = 273 + SYS_IOPRIO_GET = 274 + SYS_INOTIFY_INIT = 275 + SYS_INOTIFY_ADD_WATCH = 276 + SYS_INOTIFY_RM_WATCH = 277 + SYS_SPU_RUN = 278 + SYS_SPU_CREATE = 279 + SYS_PSELECT6 = 280 + SYS_PPOLL = 281 + SYS_UNSHARE = 282 + SYS_SPLICE = 283 + SYS_TEE = 284 + SYS_VMSPLICE = 285 + SYS_OPENAT = 286 + SYS_MKDIRAT = 287 + SYS_MKNODAT = 288 + SYS_FCHOWNAT = 289 + SYS_FUTIMESAT = 290 + SYS_NEWFSTATAT = 291 + SYS_UNLINKAT = 292 + SYS_RENAMEAT = 293 + SYS_LINKAT = 294 + SYS_SYMLINKAT = 295 + SYS_READLINKAT = 296 + SYS_FCHMODAT = 297 + SYS_FACCESSAT = 298 + SYS_GET_ROBUST_LIST = 299 + SYS_SET_ROBUST_LIST = 300 + SYS_MOVE_PAGES = 301 + SYS_GETCPU = 302 + SYS_EPOLL_PWAIT = 303 + SYS_UTIMENSAT = 304 + SYS_SIGNALFD = 305 + SYS_TIMERFD_CREATE = 306 + SYS_EVENTFD = 307 + SYS_SYNC_FILE_RANGE2 = 308 + SYS_FALLOCATE = 309 + SYS_SUBPAGE_PROT = 310 + SYS_TIMERFD_SETTIME = 311 + SYS_TIMERFD_GETTIME = 312 + SYS_SIGNALFD4 = 313 + SYS_EVENTFD2 = 314 + SYS_EPOLL_CREATE1 = 315 + SYS_DUP3 = 316 + SYS_PIPE2 = 317 + SYS_INOTIFY_INIT1 = 318 + SYS_PERF_EVENT_OPEN = 319 + SYS_PREADV = 320 + SYS_PWRITEV = 321 + SYS_RT_TGSIGQUEUEINFO = 322 + SYS_FANOTIFY_INIT = 323 + SYS_FANOTIFY_MARK = 324 + SYS_PRLIMIT64 = 325 + SYS_SOCKET = 326 + SYS_BIND = 327 + SYS_CONNECT = 328 + SYS_LISTEN = 329 + SYS_ACCEPT = 330 + SYS_GETSOCKNAME = 331 + SYS_GETPEERNAME = 332 + SYS_SOCKETPAIR = 333 + SYS_SEND = 334 + SYS_SENDTO = 335 + SYS_RECV = 336 + SYS_RECVFROM = 337 + SYS_SHUTDOWN = 338 + SYS_SETSOCKOPT = 339 + SYS_GETSOCKOPT = 340 + SYS_SENDMSG = 341 + SYS_RECVMSG = 342 + SYS_RECVMMSG = 343 + SYS_ACCEPT4 = 344 + SYS_NAME_TO_HANDLE_AT = 345 + SYS_OPEN_BY_HANDLE_AT = 346 + SYS_CLOCK_ADJTIME = 347 + SYS_SYNCFS = 348 + SYS_SENDMMSG = 349 + SYS_SETNS = 350 + SYS_PROCESS_VM_READV = 351 + SYS_PROCESS_VM_WRITEV = 352 + SYS_FINIT_MODULE = 353 + SYS_KCMP = 354 + SYS_SCHED_SETATTR = 355 + SYS_SCHED_GETATTR = 356 + SYS_RENAMEAT2 = 357 + SYS_SECCOMP = 358 + SYS_GETRANDOM = 359 + SYS_MEMFD_CREATE = 360 + SYS_BPF = 361 + SYS_EXECVEAT = 362 + SYS_SWITCH_ENDIAN = 363 + SYS_USERFAULTFD = 364 + SYS_MEMBARRIER = 365 + SYS_MLOCK2 = 378 + SYS_COPY_FILE_RANGE = 379 + SYS_PREADV2 = 380 + SYS_PWRITEV2 = 381 + SYS_KEXEC_FILE_LOAD = 382 + SYS_STATX = 383 + SYS_PKEY_ALLOC = 384 + SYS_PKEY_FREE = 385 + SYS_PKEY_MPROTECT = 386 + SYS_RSEQ = 387 + SYS_IO_PGETEVENTS = 388 + SYS_SEMTIMEDOP = 392 + SYS_SEMGET = 393 + SYS_SEMCTL = 394 + SYS_SHMGET = 395 + SYS_SHMCTL = 396 + SYS_SHMAT = 397 + SYS_SHMDT = 398 + SYS_MSGGET = 399 + SYS_MSGSND = 400 + SYS_MSGRCV = 401 + SYS_MSGCTL = 402 + SYS_PIDFD_SEND_SIGNAL = 424 + SYS_IO_URING_SETUP = 425 + SYS_IO_URING_ENTER = 426 + SYS_IO_URING_REGISTER = 427 + SYS_OPEN_TREE = 428 + SYS_MOVE_MOUNT = 429 + SYS_FSOPEN = 430 + SYS_FSCONFIG = 431 + SYS_FSMOUNT = 432 + SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 + SYS_CLOSE_RANGE = 436 + SYS_OPENAT2 = 437 + SYS_PIDFD_GETFD = 438 + SYS_FACCESSAT2 = 439 + SYS_PROCESS_MADVISE = 440 + SYS_EPOLL_PWAIT2 = 441 + SYS_MOUNT_SETATTR = 442 + SYS_QUOTACTL_FD = 443 + SYS_LANDLOCK_CREATE_RULESET = 444 + SYS_LANDLOCK_ADD_RULE = 445 + SYS_LANDLOCK_RESTRICT_SELF = 446 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go index 66c8a8e09e..a390e147d3 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go @@ -7,302 +7,306 @@ package unix const ( - SYS_IO_SETUP = 0 - SYS_IO_DESTROY = 1 - SYS_IO_SUBMIT = 2 - SYS_IO_CANCEL = 3 - SYS_IO_GETEVENTS = 4 - SYS_SETXATTR = 5 - SYS_LSETXATTR = 6 - SYS_FSETXATTR = 7 - SYS_GETXATTR = 8 - SYS_LGETXATTR = 9 - SYS_FGETXATTR = 10 - SYS_LISTXATTR = 11 - SYS_LLISTXATTR = 12 - SYS_FLISTXATTR = 13 - SYS_REMOVEXATTR = 14 - SYS_LREMOVEXATTR = 15 - SYS_FREMOVEXATTR = 16 - SYS_GETCWD = 17 - SYS_LOOKUP_DCOOKIE = 18 - SYS_EVENTFD2 = 19 - SYS_EPOLL_CREATE1 = 20 - SYS_EPOLL_CTL = 21 - SYS_EPOLL_PWAIT = 22 - SYS_DUP = 23 - SYS_DUP3 = 24 - SYS_FCNTL = 25 - SYS_INOTIFY_INIT1 = 26 - SYS_INOTIFY_ADD_WATCH = 27 - SYS_INOTIFY_RM_WATCH = 28 - SYS_IOCTL = 29 - SYS_IOPRIO_SET = 30 - SYS_IOPRIO_GET = 31 - SYS_FLOCK = 32 - SYS_MKNODAT = 33 - SYS_MKDIRAT = 34 - SYS_UNLINKAT = 35 - SYS_SYMLINKAT = 36 - SYS_LINKAT = 37 - SYS_UMOUNT2 = 39 - SYS_MOUNT = 40 - SYS_PIVOT_ROOT = 41 - SYS_NFSSERVCTL = 42 - SYS_STATFS = 43 - SYS_FSTATFS = 44 - SYS_TRUNCATE = 45 - SYS_FTRUNCATE = 46 - SYS_FALLOCATE = 47 - SYS_FACCESSAT = 48 - SYS_CHDIR = 49 - SYS_FCHDIR = 50 - SYS_CHROOT = 51 - SYS_FCHMOD = 52 - SYS_FCHMODAT = 53 - SYS_FCHOWNAT = 54 - SYS_FCHOWN = 55 - SYS_OPENAT = 56 - SYS_CLOSE = 57 - SYS_VHANGUP = 58 - SYS_PIPE2 = 59 - SYS_QUOTACTL = 60 - SYS_GETDENTS64 = 61 - SYS_LSEEK = 62 - SYS_READ = 63 - SYS_WRITE = 64 - SYS_READV = 65 - SYS_WRITEV = 66 - SYS_PREAD64 = 67 - SYS_PWRITE64 = 68 - SYS_PREADV = 69 - SYS_PWRITEV = 70 - SYS_SENDFILE = 71 - SYS_PSELECT6 = 72 - SYS_PPOLL = 73 - SYS_SIGNALFD4 = 74 - SYS_VMSPLICE = 75 - SYS_SPLICE = 76 - SYS_TEE = 77 - SYS_READLINKAT = 78 - SYS_FSTATAT = 79 - SYS_FSTAT = 80 - SYS_SYNC = 81 - SYS_FSYNC = 82 - SYS_FDATASYNC = 83 - SYS_SYNC_FILE_RANGE = 84 - SYS_TIMERFD_CREATE = 85 - SYS_TIMERFD_SETTIME = 86 - SYS_TIMERFD_GETTIME = 87 - SYS_UTIMENSAT = 88 - SYS_ACCT = 89 - SYS_CAPGET = 90 - SYS_CAPSET = 91 - SYS_PERSONALITY = 92 - SYS_EXIT = 93 - SYS_EXIT_GROUP = 94 - SYS_WAITID = 95 - SYS_SET_TID_ADDRESS = 96 - SYS_UNSHARE = 97 - SYS_FUTEX = 98 - SYS_SET_ROBUST_LIST = 99 - SYS_GET_ROBUST_LIST = 100 - SYS_NANOSLEEP = 101 - SYS_GETITIMER = 102 - SYS_SETITIMER = 103 - SYS_KEXEC_LOAD = 104 - SYS_INIT_MODULE = 105 - SYS_DELETE_MODULE = 106 - SYS_TIMER_CREATE = 107 - SYS_TIMER_GETTIME = 108 - SYS_TIMER_GETOVERRUN = 109 - SYS_TIMER_SETTIME = 110 - SYS_TIMER_DELETE = 111 - SYS_CLOCK_SETTIME = 112 - SYS_CLOCK_GETTIME = 113 - SYS_CLOCK_GETRES = 114 - SYS_CLOCK_NANOSLEEP = 115 - SYS_SYSLOG = 116 - SYS_PTRACE = 117 - SYS_SCHED_SETPARAM = 118 - SYS_SCHED_SETSCHEDULER = 119 - SYS_SCHED_GETSCHEDULER = 120 - SYS_SCHED_GETPARAM = 121 - SYS_SCHED_SETAFFINITY = 122 - SYS_SCHED_GETAFFINITY = 123 - SYS_SCHED_YIELD = 124 - SYS_SCHED_GET_PRIORITY_MAX = 125 - SYS_SCHED_GET_PRIORITY_MIN = 126 - SYS_SCHED_RR_GET_INTERVAL = 127 - SYS_RESTART_SYSCALL = 128 - SYS_KILL = 129 - SYS_TKILL = 130 - SYS_TGKILL = 131 - SYS_SIGALTSTACK = 132 - SYS_RT_SIGSUSPEND = 133 - SYS_RT_SIGACTION = 134 - SYS_RT_SIGPROCMASK = 135 - SYS_RT_SIGPENDING = 136 - SYS_RT_SIGTIMEDWAIT = 137 - SYS_RT_SIGQUEUEINFO = 138 - SYS_RT_SIGRETURN = 139 - SYS_SETPRIORITY = 140 - SYS_GETPRIORITY = 141 - SYS_REBOOT = 142 - SYS_SETREGID = 143 - SYS_SETGID = 144 - SYS_SETREUID = 145 - SYS_SETUID = 146 - SYS_SETRESUID = 147 - SYS_GETRESUID = 148 - SYS_SETRESGID = 149 - SYS_GETRESGID = 150 - SYS_SETFSUID = 151 - SYS_SETFSGID = 152 - SYS_TIMES = 153 - SYS_SETPGID = 154 - SYS_GETPGID = 155 - SYS_GETSID = 156 - SYS_SETSID = 157 - SYS_GETGROUPS = 158 - SYS_SETGROUPS = 159 - SYS_UNAME = 160 - SYS_SETHOSTNAME = 161 - SYS_SETDOMAINNAME = 162 - SYS_GETRLIMIT = 163 - SYS_SETRLIMIT = 164 - SYS_GETRUSAGE = 165 - SYS_UMASK = 166 - SYS_PRCTL = 167 - SYS_GETCPU = 168 - SYS_GETTIMEOFDAY = 169 - SYS_SETTIMEOFDAY = 170 - SYS_ADJTIMEX = 171 - SYS_GETPID = 172 - SYS_GETPPID = 173 - SYS_GETUID = 174 - SYS_GETEUID = 175 - SYS_GETGID = 176 - SYS_GETEGID = 177 - SYS_GETTID = 178 - SYS_SYSINFO = 179 - SYS_MQ_OPEN = 180 - SYS_MQ_UNLINK = 181 - SYS_MQ_TIMEDSEND = 182 - SYS_MQ_TIMEDRECEIVE = 183 - SYS_MQ_NOTIFY = 184 - SYS_MQ_GETSETATTR = 185 - SYS_MSGGET = 186 - SYS_MSGCTL = 187 - SYS_MSGRCV = 188 - SYS_MSGSND = 189 - SYS_SEMGET = 190 - SYS_SEMCTL = 191 - SYS_SEMTIMEDOP = 192 - SYS_SEMOP = 193 - SYS_SHMGET = 194 - SYS_SHMCTL = 195 - SYS_SHMAT = 196 - SYS_SHMDT = 197 - SYS_SOCKET = 198 - SYS_SOCKETPAIR = 199 - SYS_BIND = 200 - SYS_LISTEN = 201 - SYS_ACCEPT = 202 - SYS_CONNECT = 203 - SYS_GETSOCKNAME = 204 - SYS_GETPEERNAME = 205 - SYS_SENDTO = 206 - SYS_RECVFROM = 207 - SYS_SETSOCKOPT = 208 - SYS_GETSOCKOPT = 209 - SYS_SHUTDOWN = 210 - SYS_SENDMSG = 211 - SYS_RECVMSG = 212 - SYS_READAHEAD = 213 - SYS_BRK = 214 - SYS_MUNMAP = 215 - SYS_MREMAP = 216 - SYS_ADD_KEY = 217 - SYS_REQUEST_KEY = 218 - SYS_KEYCTL = 219 - SYS_CLONE = 220 - SYS_EXECVE = 221 - SYS_MMAP = 222 - SYS_FADVISE64 = 223 - SYS_SWAPON = 224 - SYS_SWAPOFF = 225 - SYS_MPROTECT = 226 - SYS_MSYNC = 227 - SYS_MLOCK = 228 - SYS_MUNLOCK = 229 - SYS_MLOCKALL = 230 - SYS_MUNLOCKALL = 231 - SYS_MINCORE = 232 - SYS_MADVISE = 233 - SYS_REMAP_FILE_PAGES = 234 - SYS_MBIND = 235 - SYS_GET_MEMPOLICY = 236 - SYS_SET_MEMPOLICY = 237 - SYS_MIGRATE_PAGES = 238 - SYS_MOVE_PAGES = 239 - SYS_RT_TGSIGQUEUEINFO = 240 - SYS_PERF_EVENT_OPEN = 241 - SYS_ACCEPT4 = 242 - SYS_RECVMMSG = 243 - SYS_ARCH_SPECIFIC_SYSCALL = 244 - SYS_WAIT4 = 260 - SYS_PRLIMIT64 = 261 - SYS_FANOTIFY_INIT = 262 - SYS_FANOTIFY_MARK = 263 - SYS_NAME_TO_HANDLE_AT = 264 - SYS_OPEN_BY_HANDLE_AT = 265 - SYS_CLOCK_ADJTIME = 266 - SYS_SYNCFS = 267 - SYS_SETNS = 268 - SYS_SENDMMSG = 269 - SYS_PROCESS_VM_READV = 270 - SYS_PROCESS_VM_WRITEV = 271 - SYS_KCMP = 272 - SYS_FINIT_MODULE = 273 - SYS_SCHED_SETATTR = 274 - SYS_SCHED_GETATTR = 275 - SYS_RENAMEAT2 = 276 - SYS_SECCOMP = 277 - SYS_GETRANDOM = 278 - SYS_MEMFD_CREATE = 279 - SYS_BPF = 280 - SYS_EXECVEAT = 281 - SYS_USERFAULTFD = 282 - SYS_MEMBARRIER = 283 - SYS_MLOCK2 = 284 - SYS_COPY_FILE_RANGE = 285 - SYS_PREADV2 = 286 - SYS_PWRITEV2 = 287 - SYS_PKEY_MPROTECT = 288 - SYS_PKEY_ALLOC = 289 - SYS_PKEY_FREE = 290 - SYS_STATX = 291 - SYS_IO_PGETEVENTS = 292 - SYS_RSEQ = 293 - SYS_KEXEC_FILE_LOAD = 294 - SYS_PIDFD_SEND_SIGNAL = 424 - SYS_IO_URING_SETUP = 425 - SYS_IO_URING_ENTER = 426 - SYS_IO_URING_REGISTER = 427 - SYS_OPEN_TREE = 428 - SYS_MOVE_MOUNT = 429 - SYS_FSOPEN = 430 - SYS_FSCONFIG = 431 - SYS_FSMOUNT = 432 - SYS_FSPICK = 433 - SYS_PIDFD_OPEN = 434 - SYS_CLONE3 = 435 - SYS_CLOSE_RANGE = 436 - SYS_OPENAT2 = 437 - SYS_PIDFD_GETFD = 438 - SYS_FACCESSAT2 = 439 - SYS_PROCESS_MADVISE = 440 - SYS_EPOLL_PWAIT2 = 441 - SYS_MOUNT_SETATTR = 442 + SYS_IO_SETUP = 0 + SYS_IO_DESTROY = 1 + SYS_IO_SUBMIT = 2 + SYS_IO_CANCEL = 3 + SYS_IO_GETEVENTS = 4 + SYS_SETXATTR = 5 + SYS_LSETXATTR = 6 + SYS_FSETXATTR = 7 + SYS_GETXATTR = 8 + SYS_LGETXATTR = 9 + SYS_FGETXATTR = 10 + SYS_LISTXATTR = 11 + SYS_LLISTXATTR = 12 + SYS_FLISTXATTR = 13 + SYS_REMOVEXATTR = 14 + SYS_LREMOVEXATTR = 15 + SYS_FREMOVEXATTR = 16 + SYS_GETCWD = 17 + SYS_LOOKUP_DCOOKIE = 18 + SYS_EVENTFD2 = 19 + SYS_EPOLL_CREATE1 = 20 + SYS_EPOLL_CTL = 21 + SYS_EPOLL_PWAIT = 22 + SYS_DUP = 23 + SYS_DUP3 = 24 + SYS_FCNTL = 25 + SYS_INOTIFY_INIT1 = 26 + SYS_INOTIFY_ADD_WATCH = 27 + SYS_INOTIFY_RM_WATCH = 28 + SYS_IOCTL = 29 + SYS_IOPRIO_SET = 30 + SYS_IOPRIO_GET = 31 + SYS_FLOCK = 32 + SYS_MKNODAT = 33 + SYS_MKDIRAT = 34 + SYS_UNLINKAT = 35 + SYS_SYMLINKAT = 36 + SYS_LINKAT = 37 + SYS_UMOUNT2 = 39 + SYS_MOUNT = 40 + SYS_PIVOT_ROOT = 41 + SYS_NFSSERVCTL = 42 + SYS_STATFS = 43 + SYS_FSTATFS = 44 + SYS_TRUNCATE = 45 + SYS_FTRUNCATE = 46 + SYS_FALLOCATE = 47 + SYS_FACCESSAT = 48 + SYS_CHDIR = 49 + SYS_FCHDIR = 50 + SYS_CHROOT = 51 + SYS_FCHMOD = 52 + SYS_FCHMODAT = 53 + SYS_FCHOWNAT = 54 + SYS_FCHOWN = 55 + SYS_OPENAT = 56 + SYS_CLOSE = 57 + SYS_VHANGUP = 58 + SYS_PIPE2 = 59 + SYS_QUOTACTL = 60 + SYS_GETDENTS64 = 61 + SYS_LSEEK = 62 + SYS_READ = 63 + SYS_WRITE = 64 + SYS_READV = 65 + SYS_WRITEV = 66 + SYS_PREAD64 = 67 + SYS_PWRITE64 = 68 + SYS_PREADV = 69 + SYS_PWRITEV = 70 + SYS_SENDFILE = 71 + SYS_PSELECT6 = 72 + SYS_PPOLL = 73 + SYS_SIGNALFD4 = 74 + SYS_VMSPLICE = 75 + SYS_SPLICE = 76 + SYS_TEE = 77 + SYS_READLINKAT = 78 + SYS_FSTATAT = 79 + SYS_FSTAT = 80 + SYS_SYNC = 81 + SYS_FSYNC = 82 + SYS_FDATASYNC = 83 + SYS_SYNC_FILE_RANGE = 84 + SYS_TIMERFD_CREATE = 85 + SYS_TIMERFD_SETTIME = 86 + SYS_TIMERFD_GETTIME = 87 + SYS_UTIMENSAT = 88 + SYS_ACCT = 89 + SYS_CAPGET = 90 + SYS_CAPSET = 91 + SYS_PERSONALITY = 92 + SYS_EXIT = 93 + SYS_EXIT_GROUP = 94 + SYS_WAITID = 95 + SYS_SET_TID_ADDRESS = 96 + SYS_UNSHARE = 97 + SYS_FUTEX = 98 + SYS_SET_ROBUST_LIST = 99 + SYS_GET_ROBUST_LIST = 100 + SYS_NANOSLEEP = 101 + SYS_GETITIMER = 102 + SYS_SETITIMER = 103 + SYS_KEXEC_LOAD = 104 + SYS_INIT_MODULE = 105 + SYS_DELETE_MODULE = 106 + SYS_TIMER_CREATE = 107 + SYS_TIMER_GETTIME = 108 + SYS_TIMER_GETOVERRUN = 109 + SYS_TIMER_SETTIME = 110 + SYS_TIMER_DELETE = 111 + SYS_CLOCK_SETTIME = 112 + SYS_CLOCK_GETTIME = 113 + SYS_CLOCK_GETRES = 114 + SYS_CLOCK_NANOSLEEP = 115 + SYS_SYSLOG = 116 + SYS_PTRACE = 117 + SYS_SCHED_SETPARAM = 118 + SYS_SCHED_SETSCHEDULER = 119 + SYS_SCHED_GETSCHEDULER = 120 + SYS_SCHED_GETPARAM = 121 + SYS_SCHED_SETAFFINITY = 122 + SYS_SCHED_GETAFFINITY = 123 + SYS_SCHED_YIELD = 124 + SYS_SCHED_GET_PRIORITY_MAX = 125 + SYS_SCHED_GET_PRIORITY_MIN = 126 + SYS_SCHED_RR_GET_INTERVAL = 127 + SYS_RESTART_SYSCALL = 128 + SYS_KILL = 129 + SYS_TKILL = 130 + SYS_TGKILL = 131 + SYS_SIGALTSTACK = 132 + SYS_RT_SIGSUSPEND = 133 + SYS_RT_SIGACTION = 134 + SYS_RT_SIGPROCMASK = 135 + SYS_RT_SIGPENDING = 136 + SYS_RT_SIGTIMEDWAIT = 137 + SYS_RT_SIGQUEUEINFO = 138 + SYS_RT_SIGRETURN = 139 + SYS_SETPRIORITY = 140 + SYS_GETPRIORITY = 141 + SYS_REBOOT = 142 + SYS_SETREGID = 143 + SYS_SETGID = 144 + SYS_SETREUID = 145 + SYS_SETUID = 146 + SYS_SETRESUID = 147 + SYS_GETRESUID = 148 + SYS_SETRESGID = 149 + SYS_GETRESGID = 150 + SYS_SETFSUID = 151 + SYS_SETFSGID = 152 + SYS_TIMES = 153 + SYS_SETPGID = 154 + SYS_GETPGID = 155 + SYS_GETSID = 156 + SYS_SETSID = 157 + SYS_GETGROUPS = 158 + SYS_SETGROUPS = 159 + SYS_UNAME = 160 + SYS_SETHOSTNAME = 161 + SYS_SETDOMAINNAME = 162 + SYS_GETRLIMIT = 163 + SYS_SETRLIMIT = 164 + SYS_GETRUSAGE = 165 + SYS_UMASK = 166 + SYS_PRCTL = 167 + SYS_GETCPU = 168 + SYS_GETTIMEOFDAY = 169 + SYS_SETTIMEOFDAY = 170 + SYS_ADJTIMEX = 171 + SYS_GETPID = 172 + SYS_GETPPID = 173 + SYS_GETUID = 174 + SYS_GETEUID = 175 + SYS_GETGID = 176 + SYS_GETEGID = 177 + SYS_GETTID = 178 + SYS_SYSINFO = 179 + SYS_MQ_OPEN = 180 + SYS_MQ_UNLINK = 181 + SYS_MQ_TIMEDSEND = 182 + SYS_MQ_TIMEDRECEIVE = 183 + SYS_MQ_NOTIFY = 184 + SYS_MQ_GETSETATTR = 185 + SYS_MSGGET = 186 + SYS_MSGCTL = 187 + SYS_MSGRCV = 188 + SYS_MSGSND = 189 + SYS_SEMGET = 190 + SYS_SEMCTL = 191 + SYS_SEMTIMEDOP = 192 + SYS_SEMOP = 193 + SYS_SHMGET = 194 + SYS_SHMCTL = 195 + SYS_SHMAT = 196 + SYS_SHMDT = 197 + SYS_SOCKET = 198 + SYS_SOCKETPAIR = 199 + SYS_BIND = 200 + SYS_LISTEN = 201 + SYS_ACCEPT = 202 + SYS_CONNECT = 203 + SYS_GETSOCKNAME = 204 + SYS_GETPEERNAME = 205 + SYS_SENDTO = 206 + SYS_RECVFROM = 207 + SYS_SETSOCKOPT = 208 + SYS_GETSOCKOPT = 209 + SYS_SHUTDOWN = 210 + SYS_SENDMSG = 211 + SYS_RECVMSG = 212 + SYS_READAHEAD = 213 + SYS_BRK = 214 + SYS_MUNMAP = 215 + SYS_MREMAP = 216 + SYS_ADD_KEY = 217 + SYS_REQUEST_KEY = 218 + SYS_KEYCTL = 219 + SYS_CLONE = 220 + SYS_EXECVE = 221 + SYS_MMAP = 222 + SYS_FADVISE64 = 223 + SYS_SWAPON = 224 + SYS_SWAPOFF = 225 + SYS_MPROTECT = 226 + SYS_MSYNC = 227 + SYS_MLOCK = 228 + SYS_MUNLOCK = 229 + SYS_MLOCKALL = 230 + SYS_MUNLOCKALL = 231 + SYS_MINCORE = 232 + SYS_MADVISE = 233 + SYS_REMAP_FILE_PAGES = 234 + SYS_MBIND = 235 + SYS_GET_MEMPOLICY = 236 + SYS_SET_MEMPOLICY = 237 + SYS_MIGRATE_PAGES = 238 + SYS_MOVE_PAGES = 239 + SYS_RT_TGSIGQUEUEINFO = 240 + SYS_PERF_EVENT_OPEN = 241 + SYS_ACCEPT4 = 242 + SYS_RECVMMSG = 243 + SYS_ARCH_SPECIFIC_SYSCALL = 244 + SYS_WAIT4 = 260 + SYS_PRLIMIT64 = 261 + SYS_FANOTIFY_INIT = 262 + SYS_FANOTIFY_MARK = 263 + SYS_NAME_TO_HANDLE_AT = 264 + SYS_OPEN_BY_HANDLE_AT = 265 + SYS_CLOCK_ADJTIME = 266 + SYS_SYNCFS = 267 + SYS_SETNS = 268 + SYS_SENDMMSG = 269 + SYS_PROCESS_VM_READV = 270 + SYS_PROCESS_VM_WRITEV = 271 + SYS_KCMP = 272 + SYS_FINIT_MODULE = 273 + SYS_SCHED_SETATTR = 274 + SYS_SCHED_GETATTR = 275 + SYS_RENAMEAT2 = 276 + SYS_SECCOMP = 277 + SYS_GETRANDOM = 278 + SYS_MEMFD_CREATE = 279 + SYS_BPF = 280 + SYS_EXECVEAT = 281 + SYS_USERFAULTFD = 282 + SYS_MEMBARRIER = 283 + SYS_MLOCK2 = 284 + SYS_COPY_FILE_RANGE = 285 + SYS_PREADV2 = 286 + SYS_PWRITEV2 = 287 + SYS_PKEY_MPROTECT = 288 + SYS_PKEY_ALLOC = 289 + SYS_PKEY_FREE = 290 + SYS_STATX = 291 + SYS_IO_PGETEVENTS = 292 + SYS_RSEQ = 293 + SYS_KEXEC_FILE_LOAD = 294 + SYS_PIDFD_SEND_SIGNAL = 424 + SYS_IO_URING_SETUP = 425 + SYS_IO_URING_ENTER = 426 + SYS_IO_URING_REGISTER = 427 + SYS_OPEN_TREE = 428 + SYS_MOVE_MOUNT = 429 + SYS_FSOPEN = 430 + SYS_FSCONFIG = 431 + SYS_FSMOUNT = 432 + SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 + SYS_CLOSE_RANGE = 436 + SYS_OPENAT2 = 437 + SYS_PIDFD_GETFD = 438 + SYS_FACCESSAT2 = 439 + SYS_PROCESS_MADVISE = 440 + SYS_EPOLL_PWAIT2 = 441 + SYS_MOUNT_SETATTR = 442 + SYS_QUOTACTL_FD = 443 + SYS_LANDLOCK_CREATE_RULESET = 444 + SYS_LANDLOCK_ADD_RULE = 445 + SYS_LANDLOCK_RESTRICT_SELF = 446 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go index aea5760cea..3e791e6cd2 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go @@ -7,365 +7,369 @@ package unix const ( - SYS_EXIT = 1 - SYS_FORK = 2 - SYS_READ = 3 - SYS_WRITE = 4 - SYS_OPEN = 5 - SYS_CLOSE = 6 - SYS_RESTART_SYSCALL = 7 - SYS_CREAT = 8 - SYS_LINK = 9 - SYS_UNLINK = 10 - SYS_EXECVE = 11 - SYS_CHDIR = 12 - SYS_MKNOD = 14 - SYS_CHMOD = 15 - SYS_LSEEK = 19 - SYS_GETPID = 20 - SYS_MOUNT = 21 - SYS_UMOUNT = 22 - SYS_PTRACE = 26 - SYS_ALARM = 27 - SYS_PAUSE = 29 - SYS_UTIME = 30 - SYS_ACCESS = 33 - SYS_NICE = 34 - SYS_SYNC = 36 - SYS_KILL = 37 - SYS_RENAME = 38 - SYS_MKDIR = 39 - SYS_RMDIR = 40 - SYS_DUP = 41 - SYS_PIPE = 42 - SYS_TIMES = 43 - SYS_BRK = 45 - SYS_SIGNAL = 48 - SYS_ACCT = 51 - SYS_UMOUNT2 = 52 - SYS_IOCTL = 54 - SYS_FCNTL = 55 - SYS_SETPGID = 57 - SYS_UMASK = 60 - SYS_CHROOT = 61 - SYS_USTAT = 62 - SYS_DUP2 = 63 - SYS_GETPPID = 64 - SYS_GETPGRP = 65 - SYS_SETSID = 66 - SYS_SIGACTION = 67 - SYS_SIGSUSPEND = 72 - SYS_SIGPENDING = 73 - SYS_SETHOSTNAME = 74 - SYS_SETRLIMIT = 75 - SYS_GETRUSAGE = 77 - SYS_GETTIMEOFDAY = 78 - SYS_SETTIMEOFDAY = 79 - SYS_SYMLINK = 83 - SYS_READLINK = 85 - SYS_USELIB = 86 - SYS_SWAPON = 87 - SYS_REBOOT = 88 - SYS_READDIR = 89 - SYS_MMAP = 90 - SYS_MUNMAP = 91 - SYS_TRUNCATE = 92 - SYS_FTRUNCATE = 93 - SYS_FCHMOD = 94 - SYS_GETPRIORITY = 96 - SYS_SETPRIORITY = 97 - SYS_STATFS = 99 - SYS_FSTATFS = 100 - SYS_SOCKETCALL = 102 - SYS_SYSLOG = 103 - SYS_SETITIMER = 104 - SYS_GETITIMER = 105 - SYS_STAT = 106 - SYS_LSTAT = 107 - SYS_FSTAT = 108 - SYS_LOOKUP_DCOOKIE = 110 - SYS_VHANGUP = 111 - SYS_IDLE = 112 - SYS_WAIT4 = 114 - SYS_SWAPOFF = 115 - SYS_SYSINFO = 116 - SYS_IPC = 117 - SYS_FSYNC = 118 - SYS_SIGRETURN = 119 - SYS_CLONE = 120 - SYS_SETDOMAINNAME = 121 - SYS_UNAME = 122 - SYS_ADJTIMEX = 124 - SYS_MPROTECT = 125 - SYS_SIGPROCMASK = 126 - SYS_CREATE_MODULE = 127 - SYS_INIT_MODULE = 128 - SYS_DELETE_MODULE = 129 - SYS_GET_KERNEL_SYMS = 130 - SYS_QUOTACTL = 131 - SYS_GETPGID = 132 - SYS_FCHDIR = 133 - SYS_BDFLUSH = 134 - SYS_SYSFS = 135 - SYS_PERSONALITY = 136 - SYS_AFS_SYSCALL = 137 - SYS_GETDENTS = 141 - SYS_SELECT = 142 - SYS_FLOCK = 143 - SYS_MSYNC = 144 - SYS_READV = 145 - SYS_WRITEV = 146 - SYS_GETSID = 147 - SYS_FDATASYNC = 148 - SYS__SYSCTL = 149 - SYS_MLOCK = 150 - SYS_MUNLOCK = 151 - SYS_MLOCKALL = 152 - SYS_MUNLOCKALL = 153 - SYS_SCHED_SETPARAM = 154 - SYS_SCHED_GETPARAM = 155 - SYS_SCHED_SETSCHEDULER = 156 - SYS_SCHED_GETSCHEDULER = 157 - SYS_SCHED_YIELD = 158 - SYS_SCHED_GET_PRIORITY_MAX = 159 - SYS_SCHED_GET_PRIORITY_MIN = 160 - SYS_SCHED_RR_GET_INTERVAL = 161 - SYS_NANOSLEEP = 162 - SYS_MREMAP = 163 - SYS_QUERY_MODULE = 167 - SYS_POLL = 168 - SYS_NFSSERVCTL = 169 - SYS_PRCTL = 172 - SYS_RT_SIGRETURN = 173 - SYS_RT_SIGACTION = 174 - SYS_RT_SIGPROCMASK = 175 - SYS_RT_SIGPENDING = 176 - SYS_RT_SIGTIMEDWAIT = 177 - SYS_RT_SIGQUEUEINFO = 178 - SYS_RT_SIGSUSPEND = 179 - SYS_PREAD64 = 180 - SYS_PWRITE64 = 181 - SYS_GETCWD = 183 - SYS_CAPGET = 184 - SYS_CAPSET = 185 - SYS_SIGALTSTACK = 186 - SYS_SENDFILE = 187 - SYS_GETPMSG = 188 - SYS_PUTPMSG = 189 - SYS_VFORK = 190 - SYS_GETRLIMIT = 191 - SYS_LCHOWN = 198 - SYS_GETUID = 199 - SYS_GETGID = 200 - SYS_GETEUID = 201 - SYS_GETEGID = 202 - SYS_SETREUID = 203 - SYS_SETREGID = 204 - SYS_GETGROUPS = 205 - SYS_SETGROUPS = 206 - SYS_FCHOWN = 207 - SYS_SETRESUID = 208 - SYS_GETRESUID = 209 - SYS_SETRESGID = 210 - SYS_GETRESGID = 211 - SYS_CHOWN = 212 - SYS_SETUID = 213 - SYS_SETGID = 214 - SYS_SETFSUID = 215 - SYS_SETFSGID = 216 - SYS_PIVOT_ROOT = 217 - SYS_MINCORE = 218 - SYS_MADVISE = 219 - SYS_GETDENTS64 = 220 - SYS_READAHEAD = 222 - SYS_SETXATTR = 224 - SYS_LSETXATTR = 225 - SYS_FSETXATTR = 226 - SYS_GETXATTR = 227 - SYS_LGETXATTR = 228 - SYS_FGETXATTR = 229 - SYS_LISTXATTR = 230 - SYS_LLISTXATTR = 231 - SYS_FLISTXATTR = 232 - SYS_REMOVEXATTR = 233 - SYS_LREMOVEXATTR = 234 - SYS_FREMOVEXATTR = 235 - SYS_GETTID = 236 - SYS_TKILL = 237 - SYS_FUTEX = 238 - SYS_SCHED_SETAFFINITY = 239 - SYS_SCHED_GETAFFINITY = 240 - SYS_TGKILL = 241 - SYS_IO_SETUP = 243 - SYS_IO_DESTROY = 244 - SYS_IO_GETEVENTS = 245 - SYS_IO_SUBMIT = 246 - SYS_IO_CANCEL = 247 - SYS_EXIT_GROUP = 248 - SYS_EPOLL_CREATE = 249 - SYS_EPOLL_CTL = 250 - SYS_EPOLL_WAIT = 251 - SYS_SET_TID_ADDRESS = 252 - SYS_FADVISE64 = 253 - SYS_TIMER_CREATE = 254 - SYS_TIMER_SETTIME = 255 - SYS_TIMER_GETTIME = 256 - SYS_TIMER_GETOVERRUN = 257 - SYS_TIMER_DELETE = 258 - SYS_CLOCK_SETTIME = 259 - SYS_CLOCK_GETTIME = 260 - SYS_CLOCK_GETRES = 261 - SYS_CLOCK_NANOSLEEP = 262 - SYS_STATFS64 = 265 - SYS_FSTATFS64 = 266 - SYS_REMAP_FILE_PAGES = 267 - SYS_MBIND = 268 - SYS_GET_MEMPOLICY = 269 - SYS_SET_MEMPOLICY = 270 - SYS_MQ_OPEN = 271 - SYS_MQ_UNLINK = 272 - SYS_MQ_TIMEDSEND = 273 - SYS_MQ_TIMEDRECEIVE = 274 - SYS_MQ_NOTIFY = 275 - SYS_MQ_GETSETATTR = 276 - SYS_KEXEC_LOAD = 277 - SYS_ADD_KEY = 278 - SYS_REQUEST_KEY = 279 - SYS_KEYCTL = 280 - SYS_WAITID = 281 - SYS_IOPRIO_SET = 282 - SYS_IOPRIO_GET = 283 - SYS_INOTIFY_INIT = 284 - SYS_INOTIFY_ADD_WATCH = 285 - SYS_INOTIFY_RM_WATCH = 286 - SYS_MIGRATE_PAGES = 287 - SYS_OPENAT = 288 - SYS_MKDIRAT = 289 - SYS_MKNODAT = 290 - SYS_FCHOWNAT = 291 - SYS_FUTIMESAT = 292 - SYS_NEWFSTATAT = 293 - SYS_UNLINKAT = 294 - SYS_RENAMEAT = 295 - SYS_LINKAT = 296 - SYS_SYMLINKAT = 297 - SYS_READLINKAT = 298 - SYS_FCHMODAT = 299 - SYS_FACCESSAT = 300 - SYS_PSELECT6 = 301 - SYS_PPOLL = 302 - SYS_UNSHARE = 303 - SYS_SET_ROBUST_LIST = 304 - SYS_GET_ROBUST_LIST = 305 - SYS_SPLICE = 306 - SYS_SYNC_FILE_RANGE = 307 - SYS_TEE = 308 - SYS_VMSPLICE = 309 - SYS_MOVE_PAGES = 310 - SYS_GETCPU = 311 - SYS_EPOLL_PWAIT = 312 - SYS_UTIMES = 313 - SYS_FALLOCATE = 314 - SYS_UTIMENSAT = 315 - SYS_SIGNALFD = 316 - SYS_TIMERFD = 317 - SYS_EVENTFD = 318 - SYS_TIMERFD_CREATE = 319 - SYS_TIMERFD_SETTIME = 320 - SYS_TIMERFD_GETTIME = 321 - SYS_SIGNALFD4 = 322 - SYS_EVENTFD2 = 323 - SYS_INOTIFY_INIT1 = 324 - SYS_PIPE2 = 325 - SYS_DUP3 = 326 - SYS_EPOLL_CREATE1 = 327 - SYS_PREADV = 328 - SYS_PWRITEV = 329 - SYS_RT_TGSIGQUEUEINFO = 330 - SYS_PERF_EVENT_OPEN = 331 - SYS_FANOTIFY_INIT = 332 - SYS_FANOTIFY_MARK = 333 - SYS_PRLIMIT64 = 334 - SYS_NAME_TO_HANDLE_AT = 335 - SYS_OPEN_BY_HANDLE_AT = 336 - SYS_CLOCK_ADJTIME = 337 - SYS_SYNCFS = 338 - SYS_SETNS = 339 - SYS_PROCESS_VM_READV = 340 - SYS_PROCESS_VM_WRITEV = 341 - SYS_S390_RUNTIME_INSTR = 342 - SYS_KCMP = 343 - SYS_FINIT_MODULE = 344 - SYS_SCHED_SETATTR = 345 - SYS_SCHED_GETATTR = 346 - SYS_RENAMEAT2 = 347 - SYS_SECCOMP = 348 - SYS_GETRANDOM = 349 - SYS_MEMFD_CREATE = 350 - SYS_BPF = 351 - SYS_S390_PCI_MMIO_WRITE = 352 - SYS_S390_PCI_MMIO_READ = 353 - SYS_EXECVEAT = 354 - SYS_USERFAULTFD = 355 - SYS_MEMBARRIER = 356 - SYS_RECVMMSG = 357 - SYS_SENDMMSG = 358 - SYS_SOCKET = 359 - SYS_SOCKETPAIR = 360 - SYS_BIND = 361 - SYS_CONNECT = 362 - SYS_LISTEN = 363 - SYS_ACCEPT4 = 364 - SYS_GETSOCKOPT = 365 - SYS_SETSOCKOPT = 366 - SYS_GETSOCKNAME = 367 - SYS_GETPEERNAME = 368 - SYS_SENDTO = 369 - SYS_SENDMSG = 370 - SYS_RECVFROM = 371 - SYS_RECVMSG = 372 - SYS_SHUTDOWN = 373 - SYS_MLOCK2 = 374 - SYS_COPY_FILE_RANGE = 375 - SYS_PREADV2 = 376 - SYS_PWRITEV2 = 377 - SYS_S390_GUARDED_STORAGE = 378 - SYS_STATX = 379 - SYS_S390_STHYI = 380 - SYS_KEXEC_FILE_LOAD = 381 - SYS_IO_PGETEVENTS = 382 - SYS_RSEQ = 383 - SYS_PKEY_MPROTECT = 384 - SYS_PKEY_ALLOC = 385 - SYS_PKEY_FREE = 386 - SYS_SEMTIMEDOP = 392 - SYS_SEMGET = 393 - SYS_SEMCTL = 394 - SYS_SHMGET = 395 - SYS_SHMCTL = 396 - SYS_SHMAT = 397 - SYS_SHMDT = 398 - SYS_MSGGET = 399 - SYS_MSGSND = 400 - SYS_MSGRCV = 401 - SYS_MSGCTL = 402 - SYS_PIDFD_SEND_SIGNAL = 424 - SYS_IO_URING_SETUP = 425 - SYS_IO_URING_ENTER = 426 - SYS_IO_URING_REGISTER = 427 - SYS_OPEN_TREE = 428 - SYS_MOVE_MOUNT = 429 - SYS_FSOPEN = 430 - SYS_FSCONFIG = 431 - SYS_FSMOUNT = 432 - SYS_FSPICK = 433 - SYS_PIDFD_OPEN = 434 - SYS_CLONE3 = 435 - SYS_CLOSE_RANGE = 436 - SYS_OPENAT2 = 437 - SYS_PIDFD_GETFD = 438 - SYS_FACCESSAT2 = 439 - SYS_PROCESS_MADVISE = 440 - SYS_EPOLL_PWAIT2 = 441 - SYS_MOUNT_SETATTR = 442 + SYS_EXIT = 1 + SYS_FORK = 2 + SYS_READ = 3 + SYS_WRITE = 4 + SYS_OPEN = 5 + SYS_CLOSE = 6 + SYS_RESTART_SYSCALL = 7 + SYS_CREAT = 8 + SYS_LINK = 9 + SYS_UNLINK = 10 + SYS_EXECVE = 11 + SYS_CHDIR = 12 + SYS_MKNOD = 14 + SYS_CHMOD = 15 + SYS_LSEEK = 19 + SYS_GETPID = 20 + SYS_MOUNT = 21 + SYS_UMOUNT = 22 + SYS_PTRACE = 26 + SYS_ALARM = 27 + SYS_PAUSE = 29 + SYS_UTIME = 30 + SYS_ACCESS = 33 + SYS_NICE = 34 + SYS_SYNC = 36 + SYS_KILL = 37 + SYS_RENAME = 38 + SYS_MKDIR = 39 + SYS_RMDIR = 40 + SYS_DUP = 41 + SYS_PIPE = 42 + SYS_TIMES = 43 + SYS_BRK = 45 + SYS_SIGNAL = 48 + SYS_ACCT = 51 + SYS_UMOUNT2 = 52 + SYS_IOCTL = 54 + SYS_FCNTL = 55 + SYS_SETPGID = 57 + SYS_UMASK = 60 + SYS_CHROOT = 61 + SYS_USTAT = 62 + SYS_DUP2 = 63 + SYS_GETPPID = 64 + SYS_GETPGRP = 65 + SYS_SETSID = 66 + SYS_SIGACTION = 67 + SYS_SIGSUSPEND = 72 + SYS_SIGPENDING = 73 + SYS_SETHOSTNAME = 74 + SYS_SETRLIMIT = 75 + SYS_GETRUSAGE = 77 + SYS_GETTIMEOFDAY = 78 + SYS_SETTIMEOFDAY = 79 + SYS_SYMLINK = 83 + SYS_READLINK = 85 + SYS_USELIB = 86 + SYS_SWAPON = 87 + SYS_REBOOT = 88 + SYS_READDIR = 89 + SYS_MMAP = 90 + SYS_MUNMAP = 91 + SYS_TRUNCATE = 92 + SYS_FTRUNCATE = 93 + SYS_FCHMOD = 94 + SYS_GETPRIORITY = 96 + SYS_SETPRIORITY = 97 + SYS_STATFS = 99 + SYS_FSTATFS = 100 + SYS_SOCKETCALL = 102 + SYS_SYSLOG = 103 + SYS_SETITIMER = 104 + SYS_GETITIMER = 105 + SYS_STAT = 106 + SYS_LSTAT = 107 + SYS_FSTAT = 108 + SYS_LOOKUP_DCOOKIE = 110 + SYS_VHANGUP = 111 + SYS_IDLE = 112 + SYS_WAIT4 = 114 + SYS_SWAPOFF = 115 + SYS_SYSINFO = 116 + SYS_IPC = 117 + SYS_FSYNC = 118 + SYS_SIGRETURN = 119 + SYS_CLONE = 120 + SYS_SETDOMAINNAME = 121 + SYS_UNAME = 122 + SYS_ADJTIMEX = 124 + SYS_MPROTECT = 125 + SYS_SIGPROCMASK = 126 + SYS_CREATE_MODULE = 127 + SYS_INIT_MODULE = 128 + SYS_DELETE_MODULE = 129 + SYS_GET_KERNEL_SYMS = 130 + SYS_QUOTACTL = 131 + SYS_GETPGID = 132 + SYS_FCHDIR = 133 + SYS_BDFLUSH = 134 + SYS_SYSFS = 135 + SYS_PERSONALITY = 136 + SYS_AFS_SYSCALL = 137 + SYS_GETDENTS = 141 + SYS_SELECT = 142 + SYS_FLOCK = 143 + SYS_MSYNC = 144 + SYS_READV = 145 + SYS_WRITEV = 146 + SYS_GETSID = 147 + SYS_FDATASYNC = 148 + SYS__SYSCTL = 149 + SYS_MLOCK = 150 + SYS_MUNLOCK = 151 + SYS_MLOCKALL = 152 + SYS_MUNLOCKALL = 153 + SYS_SCHED_SETPARAM = 154 + SYS_SCHED_GETPARAM = 155 + SYS_SCHED_SETSCHEDULER = 156 + SYS_SCHED_GETSCHEDULER = 157 + SYS_SCHED_YIELD = 158 + SYS_SCHED_GET_PRIORITY_MAX = 159 + SYS_SCHED_GET_PRIORITY_MIN = 160 + SYS_SCHED_RR_GET_INTERVAL = 161 + SYS_NANOSLEEP = 162 + SYS_MREMAP = 163 + SYS_QUERY_MODULE = 167 + SYS_POLL = 168 + SYS_NFSSERVCTL = 169 + SYS_PRCTL = 172 + SYS_RT_SIGRETURN = 173 + SYS_RT_SIGACTION = 174 + SYS_RT_SIGPROCMASK = 175 + SYS_RT_SIGPENDING = 176 + SYS_RT_SIGTIMEDWAIT = 177 + SYS_RT_SIGQUEUEINFO = 178 + SYS_RT_SIGSUSPEND = 179 + SYS_PREAD64 = 180 + SYS_PWRITE64 = 181 + SYS_GETCWD = 183 + SYS_CAPGET = 184 + SYS_CAPSET = 185 + SYS_SIGALTSTACK = 186 + SYS_SENDFILE = 187 + SYS_GETPMSG = 188 + SYS_PUTPMSG = 189 + SYS_VFORK = 190 + SYS_GETRLIMIT = 191 + SYS_LCHOWN = 198 + SYS_GETUID = 199 + SYS_GETGID = 200 + SYS_GETEUID = 201 + SYS_GETEGID = 202 + SYS_SETREUID = 203 + SYS_SETREGID = 204 + SYS_GETGROUPS = 205 + SYS_SETGROUPS = 206 + SYS_FCHOWN = 207 + SYS_SETRESUID = 208 + SYS_GETRESUID = 209 + SYS_SETRESGID = 210 + SYS_GETRESGID = 211 + SYS_CHOWN = 212 + SYS_SETUID = 213 + SYS_SETGID = 214 + SYS_SETFSUID = 215 + SYS_SETFSGID = 216 + SYS_PIVOT_ROOT = 217 + SYS_MINCORE = 218 + SYS_MADVISE = 219 + SYS_GETDENTS64 = 220 + SYS_READAHEAD = 222 + SYS_SETXATTR = 224 + SYS_LSETXATTR = 225 + SYS_FSETXATTR = 226 + SYS_GETXATTR = 227 + SYS_LGETXATTR = 228 + SYS_FGETXATTR = 229 + SYS_LISTXATTR = 230 + SYS_LLISTXATTR = 231 + SYS_FLISTXATTR = 232 + SYS_REMOVEXATTR = 233 + SYS_LREMOVEXATTR = 234 + SYS_FREMOVEXATTR = 235 + SYS_GETTID = 236 + SYS_TKILL = 237 + SYS_FUTEX = 238 + SYS_SCHED_SETAFFINITY = 239 + SYS_SCHED_GETAFFINITY = 240 + SYS_TGKILL = 241 + SYS_IO_SETUP = 243 + SYS_IO_DESTROY = 244 + SYS_IO_GETEVENTS = 245 + SYS_IO_SUBMIT = 246 + SYS_IO_CANCEL = 247 + SYS_EXIT_GROUP = 248 + SYS_EPOLL_CREATE = 249 + SYS_EPOLL_CTL = 250 + SYS_EPOLL_WAIT = 251 + SYS_SET_TID_ADDRESS = 252 + SYS_FADVISE64 = 253 + SYS_TIMER_CREATE = 254 + SYS_TIMER_SETTIME = 255 + SYS_TIMER_GETTIME = 256 + SYS_TIMER_GETOVERRUN = 257 + SYS_TIMER_DELETE = 258 + SYS_CLOCK_SETTIME = 259 + SYS_CLOCK_GETTIME = 260 + SYS_CLOCK_GETRES = 261 + SYS_CLOCK_NANOSLEEP = 262 + SYS_STATFS64 = 265 + SYS_FSTATFS64 = 266 + SYS_REMAP_FILE_PAGES = 267 + SYS_MBIND = 268 + SYS_GET_MEMPOLICY = 269 + SYS_SET_MEMPOLICY = 270 + SYS_MQ_OPEN = 271 + SYS_MQ_UNLINK = 272 + SYS_MQ_TIMEDSEND = 273 + SYS_MQ_TIMEDRECEIVE = 274 + SYS_MQ_NOTIFY = 275 + SYS_MQ_GETSETATTR = 276 + SYS_KEXEC_LOAD = 277 + SYS_ADD_KEY = 278 + SYS_REQUEST_KEY = 279 + SYS_KEYCTL = 280 + SYS_WAITID = 281 + SYS_IOPRIO_SET = 282 + SYS_IOPRIO_GET = 283 + SYS_INOTIFY_INIT = 284 + SYS_INOTIFY_ADD_WATCH = 285 + SYS_INOTIFY_RM_WATCH = 286 + SYS_MIGRATE_PAGES = 287 + SYS_OPENAT = 288 + SYS_MKDIRAT = 289 + SYS_MKNODAT = 290 + SYS_FCHOWNAT = 291 + SYS_FUTIMESAT = 292 + SYS_NEWFSTATAT = 293 + SYS_UNLINKAT = 294 + SYS_RENAMEAT = 295 + SYS_LINKAT = 296 + SYS_SYMLINKAT = 297 + SYS_READLINKAT = 298 + SYS_FCHMODAT = 299 + SYS_FACCESSAT = 300 + SYS_PSELECT6 = 301 + SYS_PPOLL = 302 + SYS_UNSHARE = 303 + SYS_SET_ROBUST_LIST = 304 + SYS_GET_ROBUST_LIST = 305 + SYS_SPLICE = 306 + SYS_SYNC_FILE_RANGE = 307 + SYS_TEE = 308 + SYS_VMSPLICE = 309 + SYS_MOVE_PAGES = 310 + SYS_GETCPU = 311 + SYS_EPOLL_PWAIT = 312 + SYS_UTIMES = 313 + SYS_FALLOCATE = 314 + SYS_UTIMENSAT = 315 + SYS_SIGNALFD = 316 + SYS_TIMERFD = 317 + SYS_EVENTFD = 318 + SYS_TIMERFD_CREATE = 319 + SYS_TIMERFD_SETTIME = 320 + SYS_TIMERFD_GETTIME = 321 + SYS_SIGNALFD4 = 322 + SYS_EVENTFD2 = 323 + SYS_INOTIFY_INIT1 = 324 + SYS_PIPE2 = 325 + SYS_DUP3 = 326 + SYS_EPOLL_CREATE1 = 327 + SYS_PREADV = 328 + SYS_PWRITEV = 329 + SYS_RT_TGSIGQUEUEINFO = 330 + SYS_PERF_EVENT_OPEN = 331 + SYS_FANOTIFY_INIT = 332 + SYS_FANOTIFY_MARK = 333 + SYS_PRLIMIT64 = 334 + SYS_NAME_TO_HANDLE_AT = 335 + SYS_OPEN_BY_HANDLE_AT = 336 + SYS_CLOCK_ADJTIME = 337 + SYS_SYNCFS = 338 + SYS_SETNS = 339 + SYS_PROCESS_VM_READV = 340 + SYS_PROCESS_VM_WRITEV = 341 + SYS_S390_RUNTIME_INSTR = 342 + SYS_KCMP = 343 + SYS_FINIT_MODULE = 344 + SYS_SCHED_SETATTR = 345 + SYS_SCHED_GETATTR = 346 + SYS_RENAMEAT2 = 347 + SYS_SECCOMP = 348 + SYS_GETRANDOM = 349 + SYS_MEMFD_CREATE = 350 + SYS_BPF = 351 + SYS_S390_PCI_MMIO_WRITE = 352 + SYS_S390_PCI_MMIO_READ = 353 + SYS_EXECVEAT = 354 + SYS_USERFAULTFD = 355 + SYS_MEMBARRIER = 356 + SYS_RECVMMSG = 357 + SYS_SENDMMSG = 358 + SYS_SOCKET = 359 + SYS_SOCKETPAIR = 360 + SYS_BIND = 361 + SYS_CONNECT = 362 + SYS_LISTEN = 363 + SYS_ACCEPT4 = 364 + SYS_GETSOCKOPT = 365 + SYS_SETSOCKOPT = 366 + SYS_GETSOCKNAME = 367 + SYS_GETPEERNAME = 368 + SYS_SENDTO = 369 + SYS_SENDMSG = 370 + SYS_RECVFROM = 371 + SYS_RECVMSG = 372 + SYS_SHUTDOWN = 373 + SYS_MLOCK2 = 374 + SYS_COPY_FILE_RANGE = 375 + SYS_PREADV2 = 376 + SYS_PWRITEV2 = 377 + SYS_S390_GUARDED_STORAGE = 378 + SYS_STATX = 379 + SYS_S390_STHYI = 380 + SYS_KEXEC_FILE_LOAD = 381 + SYS_IO_PGETEVENTS = 382 + SYS_RSEQ = 383 + SYS_PKEY_MPROTECT = 384 + SYS_PKEY_ALLOC = 385 + SYS_PKEY_FREE = 386 + SYS_SEMTIMEDOP = 392 + SYS_SEMGET = 393 + SYS_SEMCTL = 394 + SYS_SHMGET = 395 + SYS_SHMCTL = 396 + SYS_SHMAT = 397 + SYS_SHMDT = 398 + SYS_MSGGET = 399 + SYS_MSGSND = 400 + SYS_MSGRCV = 401 + SYS_MSGCTL = 402 + SYS_PIDFD_SEND_SIGNAL = 424 + SYS_IO_URING_SETUP = 425 + SYS_IO_URING_ENTER = 426 + SYS_IO_URING_REGISTER = 427 + SYS_OPEN_TREE = 428 + SYS_MOVE_MOUNT = 429 + SYS_FSOPEN = 430 + SYS_FSCONFIG = 431 + SYS_FSMOUNT = 432 + SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLONE3 = 435 + SYS_CLOSE_RANGE = 436 + SYS_OPENAT2 = 437 + SYS_PIDFD_GETFD = 438 + SYS_FACCESSAT2 = 439 + SYS_PROCESS_MADVISE = 440 + SYS_EPOLL_PWAIT2 = 441 + SYS_MOUNT_SETATTR = 442 + SYS_QUOTACTL_FD = 443 + SYS_LANDLOCK_CREATE_RULESET = 444 + SYS_LANDLOCK_ADD_RULE = 445 + SYS_LANDLOCK_RESTRICT_SELF = 446 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go index 488ca848d1..78802a5cf7 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go @@ -7,379 +7,383 @@ package unix const ( - SYS_RESTART_SYSCALL = 0 - SYS_EXIT = 1 - SYS_FORK = 2 - SYS_READ = 3 - SYS_WRITE = 4 - SYS_OPEN = 5 - SYS_CLOSE = 6 - SYS_WAIT4 = 7 - SYS_CREAT = 8 - SYS_LINK = 9 - SYS_UNLINK = 10 - SYS_EXECV = 11 - SYS_CHDIR = 12 - SYS_CHOWN = 13 - SYS_MKNOD = 14 - SYS_CHMOD = 15 - SYS_LCHOWN = 16 - SYS_BRK = 17 - SYS_PERFCTR = 18 - SYS_LSEEK = 19 - SYS_GETPID = 20 - SYS_CAPGET = 21 - SYS_CAPSET = 22 - SYS_SETUID = 23 - SYS_GETUID = 24 - SYS_VMSPLICE = 25 - SYS_PTRACE = 26 - SYS_ALARM = 27 - SYS_SIGALTSTACK = 28 - SYS_PAUSE = 29 - SYS_UTIME = 30 - SYS_ACCESS = 33 - SYS_NICE = 34 - SYS_SYNC = 36 - SYS_KILL = 37 - SYS_STAT = 38 - SYS_SENDFILE = 39 - SYS_LSTAT = 40 - SYS_DUP = 41 - SYS_PIPE = 42 - SYS_TIMES = 43 - SYS_UMOUNT2 = 45 - SYS_SETGID = 46 - SYS_GETGID = 47 - SYS_SIGNAL = 48 - SYS_GETEUID = 49 - SYS_GETEGID = 50 - SYS_ACCT = 51 - SYS_MEMORY_ORDERING = 52 - SYS_IOCTL = 54 - SYS_REBOOT = 55 - SYS_SYMLINK = 57 - SYS_READLINK = 58 - SYS_EXECVE = 59 - SYS_UMASK = 60 - SYS_CHROOT = 61 - SYS_FSTAT = 62 - SYS_FSTAT64 = 63 - SYS_GETPAGESIZE = 64 - SYS_MSYNC = 65 - SYS_VFORK = 66 - SYS_PREAD64 = 67 - SYS_PWRITE64 = 68 - SYS_MMAP = 71 - SYS_MUNMAP = 73 - SYS_MPROTECT = 74 - SYS_MADVISE = 75 - SYS_VHANGUP = 76 - SYS_MINCORE = 78 - SYS_GETGROUPS = 79 - SYS_SETGROUPS = 80 - SYS_GETPGRP = 81 - SYS_SETITIMER = 83 - SYS_SWAPON = 85 - SYS_GETITIMER = 86 - SYS_SETHOSTNAME = 88 - SYS_DUP2 = 90 - SYS_FCNTL = 92 - SYS_SELECT = 93 - SYS_FSYNC = 95 - SYS_SETPRIORITY = 96 - SYS_SOCKET = 97 - SYS_CONNECT = 98 - SYS_ACCEPT = 99 - SYS_GETPRIORITY = 100 - SYS_RT_SIGRETURN = 101 - SYS_RT_SIGACTION = 102 - SYS_RT_SIGPROCMASK = 103 - SYS_RT_SIGPENDING = 104 - SYS_RT_SIGTIMEDWAIT = 105 - SYS_RT_SIGQUEUEINFO = 106 - SYS_RT_SIGSUSPEND = 107 - SYS_SETRESUID = 108 - SYS_GETRESUID = 109 - SYS_SETRESGID = 110 - SYS_GETRESGID = 111 - SYS_RECVMSG = 113 - SYS_SENDMSG = 114 - SYS_GETTIMEOFDAY = 116 - SYS_GETRUSAGE = 117 - SYS_GETSOCKOPT = 118 - SYS_GETCWD = 119 - SYS_READV = 120 - SYS_WRITEV = 121 - SYS_SETTIMEOFDAY = 122 - SYS_FCHOWN = 123 - SYS_FCHMOD = 124 - SYS_RECVFROM = 125 - SYS_SETREUID = 126 - SYS_SETREGID = 127 - SYS_RENAME = 128 - SYS_TRUNCATE = 129 - SYS_FTRUNCATE = 130 - SYS_FLOCK = 131 - SYS_LSTAT64 = 132 - SYS_SENDTO = 133 - SYS_SHUTDOWN = 134 - SYS_SOCKETPAIR = 135 - SYS_MKDIR = 136 - SYS_RMDIR = 137 - SYS_UTIMES = 138 - SYS_STAT64 = 139 - SYS_SENDFILE64 = 140 - SYS_GETPEERNAME = 141 - SYS_FUTEX = 142 - SYS_GETTID = 143 - SYS_GETRLIMIT = 144 - SYS_SETRLIMIT = 145 - SYS_PIVOT_ROOT = 146 - SYS_PRCTL = 147 - SYS_PCICONFIG_READ = 148 - SYS_PCICONFIG_WRITE = 149 - SYS_GETSOCKNAME = 150 - SYS_INOTIFY_INIT = 151 - SYS_INOTIFY_ADD_WATCH = 152 - SYS_POLL = 153 - SYS_GETDENTS64 = 154 - SYS_INOTIFY_RM_WATCH = 156 - SYS_STATFS = 157 - SYS_FSTATFS = 158 - SYS_UMOUNT = 159 - SYS_SCHED_SET_AFFINITY = 160 - SYS_SCHED_GET_AFFINITY = 161 - SYS_GETDOMAINNAME = 162 - SYS_SETDOMAINNAME = 163 - SYS_UTRAP_INSTALL = 164 - SYS_QUOTACTL = 165 - SYS_SET_TID_ADDRESS = 166 - SYS_MOUNT = 167 - SYS_USTAT = 168 - SYS_SETXATTR = 169 - SYS_LSETXATTR = 170 - SYS_FSETXATTR = 171 - SYS_GETXATTR = 172 - SYS_LGETXATTR = 173 - SYS_GETDENTS = 174 - SYS_SETSID = 175 - SYS_FCHDIR = 176 - SYS_FGETXATTR = 177 - SYS_LISTXATTR = 178 - SYS_LLISTXATTR = 179 - SYS_FLISTXATTR = 180 - SYS_REMOVEXATTR = 181 - SYS_LREMOVEXATTR = 182 - SYS_SIGPENDING = 183 - SYS_QUERY_MODULE = 184 - SYS_SETPGID = 185 - SYS_FREMOVEXATTR = 186 - SYS_TKILL = 187 - SYS_EXIT_GROUP = 188 - SYS_UNAME = 189 - SYS_INIT_MODULE = 190 - SYS_PERSONALITY = 191 - SYS_REMAP_FILE_PAGES = 192 - SYS_EPOLL_CREATE = 193 - SYS_EPOLL_CTL = 194 - SYS_EPOLL_WAIT = 195 - SYS_IOPRIO_SET = 196 - SYS_GETPPID = 197 - SYS_SIGACTION = 198 - SYS_SGETMASK = 199 - SYS_SSETMASK = 200 - SYS_SIGSUSPEND = 201 - SYS_OLDLSTAT = 202 - SYS_USELIB = 203 - SYS_READDIR = 204 - SYS_READAHEAD = 205 - SYS_SOCKETCALL = 206 - SYS_SYSLOG = 207 - SYS_LOOKUP_DCOOKIE = 208 - SYS_FADVISE64 = 209 - SYS_FADVISE64_64 = 210 - SYS_TGKILL = 211 - SYS_WAITPID = 212 - SYS_SWAPOFF = 213 - SYS_SYSINFO = 214 - SYS_IPC = 215 - SYS_SIGRETURN = 216 - SYS_CLONE = 217 - SYS_IOPRIO_GET = 218 - SYS_ADJTIMEX = 219 - SYS_SIGPROCMASK = 220 - SYS_CREATE_MODULE = 221 - SYS_DELETE_MODULE = 222 - SYS_GET_KERNEL_SYMS = 223 - SYS_GETPGID = 224 - SYS_BDFLUSH = 225 - SYS_SYSFS = 226 - SYS_AFS_SYSCALL = 227 - SYS_SETFSUID = 228 - SYS_SETFSGID = 229 - SYS__NEWSELECT = 230 - SYS_SPLICE = 232 - SYS_STIME = 233 - SYS_STATFS64 = 234 - SYS_FSTATFS64 = 235 - SYS__LLSEEK = 236 - SYS_MLOCK = 237 - SYS_MUNLOCK = 238 - SYS_MLOCKALL = 239 - SYS_MUNLOCKALL = 240 - SYS_SCHED_SETPARAM = 241 - SYS_SCHED_GETPARAM = 242 - SYS_SCHED_SETSCHEDULER = 243 - SYS_SCHED_GETSCHEDULER = 244 - SYS_SCHED_YIELD = 245 - SYS_SCHED_GET_PRIORITY_MAX = 246 - SYS_SCHED_GET_PRIORITY_MIN = 247 - SYS_SCHED_RR_GET_INTERVAL = 248 - SYS_NANOSLEEP = 249 - SYS_MREMAP = 250 - SYS__SYSCTL = 251 - SYS_GETSID = 252 - SYS_FDATASYNC = 253 - SYS_NFSSERVCTL = 254 - SYS_SYNC_FILE_RANGE = 255 - SYS_CLOCK_SETTIME = 256 - SYS_CLOCK_GETTIME = 257 - SYS_CLOCK_GETRES = 258 - SYS_CLOCK_NANOSLEEP = 259 - SYS_SCHED_GETAFFINITY = 260 - SYS_SCHED_SETAFFINITY = 261 - SYS_TIMER_SETTIME = 262 - SYS_TIMER_GETTIME = 263 - SYS_TIMER_GETOVERRUN = 264 - SYS_TIMER_DELETE = 265 - SYS_TIMER_CREATE = 266 - SYS_VSERVER = 267 - SYS_IO_SETUP = 268 - SYS_IO_DESTROY = 269 - SYS_IO_SUBMIT = 270 - SYS_IO_CANCEL = 271 - SYS_IO_GETEVENTS = 272 - SYS_MQ_OPEN = 273 - SYS_MQ_UNLINK = 274 - SYS_MQ_TIMEDSEND = 275 - SYS_MQ_TIMEDRECEIVE = 276 - SYS_MQ_NOTIFY = 277 - SYS_MQ_GETSETATTR = 278 - SYS_WAITID = 279 - SYS_TEE = 280 - SYS_ADD_KEY = 281 - SYS_REQUEST_KEY = 282 - SYS_KEYCTL = 283 - SYS_OPENAT = 284 - SYS_MKDIRAT = 285 - SYS_MKNODAT = 286 - SYS_FCHOWNAT = 287 - SYS_FUTIMESAT = 288 - SYS_FSTATAT64 = 289 - SYS_UNLINKAT = 290 - SYS_RENAMEAT = 291 - SYS_LINKAT = 292 - SYS_SYMLINKAT = 293 - SYS_READLINKAT = 294 - SYS_FCHMODAT = 295 - SYS_FACCESSAT = 296 - SYS_PSELECT6 = 297 - SYS_PPOLL = 298 - SYS_UNSHARE = 299 - SYS_SET_ROBUST_LIST = 300 - SYS_GET_ROBUST_LIST = 301 - SYS_MIGRATE_PAGES = 302 - SYS_MBIND = 303 - SYS_GET_MEMPOLICY = 304 - SYS_SET_MEMPOLICY = 305 - SYS_KEXEC_LOAD = 306 - SYS_MOVE_PAGES = 307 - SYS_GETCPU = 308 - SYS_EPOLL_PWAIT = 309 - SYS_UTIMENSAT = 310 - SYS_SIGNALFD = 311 - SYS_TIMERFD_CREATE = 312 - SYS_EVENTFD = 313 - SYS_FALLOCATE = 314 - SYS_TIMERFD_SETTIME = 315 - SYS_TIMERFD_GETTIME = 316 - SYS_SIGNALFD4 = 317 - SYS_EVENTFD2 = 318 - SYS_EPOLL_CREATE1 = 319 - SYS_DUP3 = 320 - SYS_PIPE2 = 321 - SYS_INOTIFY_INIT1 = 322 - SYS_ACCEPT4 = 323 - SYS_PREADV = 324 - SYS_PWRITEV = 325 - SYS_RT_TGSIGQUEUEINFO = 326 - SYS_PERF_EVENT_OPEN = 327 - SYS_RECVMMSG = 328 - SYS_FANOTIFY_INIT = 329 - SYS_FANOTIFY_MARK = 330 - SYS_PRLIMIT64 = 331 - SYS_NAME_TO_HANDLE_AT = 332 - SYS_OPEN_BY_HANDLE_AT = 333 - SYS_CLOCK_ADJTIME = 334 - SYS_SYNCFS = 335 - SYS_SENDMMSG = 336 - SYS_SETNS = 337 - SYS_PROCESS_VM_READV = 338 - SYS_PROCESS_VM_WRITEV = 339 - SYS_KERN_FEATURES = 340 - SYS_KCMP = 341 - SYS_FINIT_MODULE = 342 - SYS_SCHED_SETATTR = 343 - SYS_SCHED_GETATTR = 344 - SYS_RENAMEAT2 = 345 - SYS_SECCOMP = 346 - SYS_GETRANDOM = 347 - SYS_MEMFD_CREATE = 348 - SYS_BPF = 349 - SYS_EXECVEAT = 350 - SYS_MEMBARRIER = 351 - SYS_USERFAULTFD = 352 - SYS_BIND = 353 - SYS_LISTEN = 354 - SYS_SETSOCKOPT = 355 - SYS_MLOCK2 = 356 - SYS_COPY_FILE_RANGE = 357 - SYS_PREADV2 = 358 - SYS_PWRITEV2 = 359 - SYS_STATX = 360 - SYS_IO_PGETEVENTS = 361 - SYS_PKEY_MPROTECT = 362 - SYS_PKEY_ALLOC = 363 - SYS_PKEY_FREE = 364 - SYS_RSEQ = 365 - SYS_SEMTIMEDOP = 392 - SYS_SEMGET = 393 - SYS_SEMCTL = 394 - SYS_SHMGET = 395 - SYS_SHMCTL = 396 - SYS_SHMAT = 397 - SYS_SHMDT = 398 - SYS_MSGGET = 399 - SYS_MSGSND = 400 - SYS_MSGRCV = 401 - SYS_MSGCTL = 402 - SYS_PIDFD_SEND_SIGNAL = 424 - SYS_IO_URING_SETUP = 425 - SYS_IO_URING_ENTER = 426 - SYS_IO_URING_REGISTER = 427 - SYS_OPEN_TREE = 428 - SYS_MOVE_MOUNT = 429 - SYS_FSOPEN = 430 - SYS_FSCONFIG = 431 - SYS_FSMOUNT = 432 - SYS_FSPICK = 433 - SYS_PIDFD_OPEN = 434 - SYS_CLOSE_RANGE = 436 - SYS_OPENAT2 = 437 - SYS_PIDFD_GETFD = 438 - SYS_FACCESSAT2 = 439 - SYS_PROCESS_MADVISE = 440 - SYS_EPOLL_PWAIT2 = 441 - SYS_MOUNT_SETATTR = 442 + SYS_RESTART_SYSCALL = 0 + SYS_EXIT = 1 + SYS_FORK = 2 + SYS_READ = 3 + SYS_WRITE = 4 + SYS_OPEN = 5 + SYS_CLOSE = 6 + SYS_WAIT4 = 7 + SYS_CREAT = 8 + SYS_LINK = 9 + SYS_UNLINK = 10 + SYS_EXECV = 11 + SYS_CHDIR = 12 + SYS_CHOWN = 13 + SYS_MKNOD = 14 + SYS_CHMOD = 15 + SYS_LCHOWN = 16 + SYS_BRK = 17 + SYS_PERFCTR = 18 + SYS_LSEEK = 19 + SYS_GETPID = 20 + SYS_CAPGET = 21 + SYS_CAPSET = 22 + SYS_SETUID = 23 + SYS_GETUID = 24 + SYS_VMSPLICE = 25 + SYS_PTRACE = 26 + SYS_ALARM = 27 + SYS_SIGALTSTACK = 28 + SYS_PAUSE = 29 + SYS_UTIME = 30 + SYS_ACCESS = 33 + SYS_NICE = 34 + SYS_SYNC = 36 + SYS_KILL = 37 + SYS_STAT = 38 + SYS_SENDFILE = 39 + SYS_LSTAT = 40 + SYS_DUP = 41 + SYS_PIPE = 42 + SYS_TIMES = 43 + SYS_UMOUNT2 = 45 + SYS_SETGID = 46 + SYS_GETGID = 47 + SYS_SIGNAL = 48 + SYS_GETEUID = 49 + SYS_GETEGID = 50 + SYS_ACCT = 51 + SYS_MEMORY_ORDERING = 52 + SYS_IOCTL = 54 + SYS_REBOOT = 55 + SYS_SYMLINK = 57 + SYS_READLINK = 58 + SYS_EXECVE = 59 + SYS_UMASK = 60 + SYS_CHROOT = 61 + SYS_FSTAT = 62 + SYS_FSTAT64 = 63 + SYS_GETPAGESIZE = 64 + SYS_MSYNC = 65 + SYS_VFORK = 66 + SYS_PREAD64 = 67 + SYS_PWRITE64 = 68 + SYS_MMAP = 71 + SYS_MUNMAP = 73 + SYS_MPROTECT = 74 + SYS_MADVISE = 75 + SYS_VHANGUP = 76 + SYS_MINCORE = 78 + SYS_GETGROUPS = 79 + SYS_SETGROUPS = 80 + SYS_GETPGRP = 81 + SYS_SETITIMER = 83 + SYS_SWAPON = 85 + SYS_GETITIMER = 86 + SYS_SETHOSTNAME = 88 + SYS_DUP2 = 90 + SYS_FCNTL = 92 + SYS_SELECT = 93 + SYS_FSYNC = 95 + SYS_SETPRIORITY = 96 + SYS_SOCKET = 97 + SYS_CONNECT = 98 + SYS_ACCEPT = 99 + SYS_GETPRIORITY = 100 + SYS_RT_SIGRETURN = 101 + SYS_RT_SIGACTION = 102 + SYS_RT_SIGPROCMASK = 103 + SYS_RT_SIGPENDING = 104 + SYS_RT_SIGTIMEDWAIT = 105 + SYS_RT_SIGQUEUEINFO = 106 + SYS_RT_SIGSUSPEND = 107 + SYS_SETRESUID = 108 + SYS_GETRESUID = 109 + SYS_SETRESGID = 110 + SYS_GETRESGID = 111 + SYS_RECVMSG = 113 + SYS_SENDMSG = 114 + SYS_GETTIMEOFDAY = 116 + SYS_GETRUSAGE = 117 + SYS_GETSOCKOPT = 118 + SYS_GETCWD = 119 + SYS_READV = 120 + SYS_WRITEV = 121 + SYS_SETTIMEOFDAY = 122 + SYS_FCHOWN = 123 + SYS_FCHMOD = 124 + SYS_RECVFROM = 125 + SYS_SETREUID = 126 + SYS_SETREGID = 127 + SYS_RENAME = 128 + SYS_TRUNCATE = 129 + SYS_FTRUNCATE = 130 + SYS_FLOCK = 131 + SYS_LSTAT64 = 132 + SYS_SENDTO = 133 + SYS_SHUTDOWN = 134 + SYS_SOCKETPAIR = 135 + SYS_MKDIR = 136 + SYS_RMDIR = 137 + SYS_UTIMES = 138 + SYS_STAT64 = 139 + SYS_SENDFILE64 = 140 + SYS_GETPEERNAME = 141 + SYS_FUTEX = 142 + SYS_GETTID = 143 + SYS_GETRLIMIT = 144 + SYS_SETRLIMIT = 145 + SYS_PIVOT_ROOT = 146 + SYS_PRCTL = 147 + SYS_PCICONFIG_READ = 148 + SYS_PCICONFIG_WRITE = 149 + SYS_GETSOCKNAME = 150 + SYS_INOTIFY_INIT = 151 + SYS_INOTIFY_ADD_WATCH = 152 + SYS_POLL = 153 + SYS_GETDENTS64 = 154 + SYS_INOTIFY_RM_WATCH = 156 + SYS_STATFS = 157 + SYS_FSTATFS = 158 + SYS_UMOUNT = 159 + SYS_SCHED_SET_AFFINITY = 160 + SYS_SCHED_GET_AFFINITY = 161 + SYS_GETDOMAINNAME = 162 + SYS_SETDOMAINNAME = 163 + SYS_UTRAP_INSTALL = 164 + SYS_QUOTACTL = 165 + SYS_SET_TID_ADDRESS = 166 + SYS_MOUNT = 167 + SYS_USTAT = 168 + SYS_SETXATTR = 169 + SYS_LSETXATTR = 170 + SYS_FSETXATTR = 171 + SYS_GETXATTR = 172 + SYS_LGETXATTR = 173 + SYS_GETDENTS = 174 + SYS_SETSID = 175 + SYS_FCHDIR = 176 + SYS_FGETXATTR = 177 + SYS_LISTXATTR = 178 + SYS_LLISTXATTR = 179 + SYS_FLISTXATTR = 180 + SYS_REMOVEXATTR = 181 + SYS_LREMOVEXATTR = 182 + SYS_SIGPENDING = 183 + SYS_QUERY_MODULE = 184 + SYS_SETPGID = 185 + SYS_FREMOVEXATTR = 186 + SYS_TKILL = 187 + SYS_EXIT_GROUP = 188 + SYS_UNAME = 189 + SYS_INIT_MODULE = 190 + SYS_PERSONALITY = 191 + SYS_REMAP_FILE_PAGES = 192 + SYS_EPOLL_CREATE = 193 + SYS_EPOLL_CTL = 194 + SYS_EPOLL_WAIT = 195 + SYS_IOPRIO_SET = 196 + SYS_GETPPID = 197 + SYS_SIGACTION = 198 + SYS_SGETMASK = 199 + SYS_SSETMASK = 200 + SYS_SIGSUSPEND = 201 + SYS_OLDLSTAT = 202 + SYS_USELIB = 203 + SYS_READDIR = 204 + SYS_READAHEAD = 205 + SYS_SOCKETCALL = 206 + SYS_SYSLOG = 207 + SYS_LOOKUP_DCOOKIE = 208 + SYS_FADVISE64 = 209 + SYS_FADVISE64_64 = 210 + SYS_TGKILL = 211 + SYS_WAITPID = 212 + SYS_SWAPOFF = 213 + SYS_SYSINFO = 214 + SYS_IPC = 215 + SYS_SIGRETURN = 216 + SYS_CLONE = 217 + SYS_IOPRIO_GET = 218 + SYS_ADJTIMEX = 219 + SYS_SIGPROCMASK = 220 + SYS_CREATE_MODULE = 221 + SYS_DELETE_MODULE = 222 + SYS_GET_KERNEL_SYMS = 223 + SYS_GETPGID = 224 + SYS_BDFLUSH = 225 + SYS_SYSFS = 226 + SYS_AFS_SYSCALL = 227 + SYS_SETFSUID = 228 + SYS_SETFSGID = 229 + SYS__NEWSELECT = 230 + SYS_SPLICE = 232 + SYS_STIME = 233 + SYS_STATFS64 = 234 + SYS_FSTATFS64 = 235 + SYS__LLSEEK = 236 + SYS_MLOCK = 237 + SYS_MUNLOCK = 238 + SYS_MLOCKALL = 239 + SYS_MUNLOCKALL = 240 + SYS_SCHED_SETPARAM = 241 + SYS_SCHED_GETPARAM = 242 + SYS_SCHED_SETSCHEDULER = 243 + SYS_SCHED_GETSCHEDULER = 244 + SYS_SCHED_YIELD = 245 + SYS_SCHED_GET_PRIORITY_MAX = 246 + SYS_SCHED_GET_PRIORITY_MIN = 247 + SYS_SCHED_RR_GET_INTERVAL = 248 + SYS_NANOSLEEP = 249 + SYS_MREMAP = 250 + SYS__SYSCTL = 251 + SYS_GETSID = 252 + SYS_FDATASYNC = 253 + SYS_NFSSERVCTL = 254 + SYS_SYNC_FILE_RANGE = 255 + SYS_CLOCK_SETTIME = 256 + SYS_CLOCK_GETTIME = 257 + SYS_CLOCK_GETRES = 258 + SYS_CLOCK_NANOSLEEP = 259 + SYS_SCHED_GETAFFINITY = 260 + SYS_SCHED_SETAFFINITY = 261 + SYS_TIMER_SETTIME = 262 + SYS_TIMER_GETTIME = 263 + SYS_TIMER_GETOVERRUN = 264 + SYS_TIMER_DELETE = 265 + SYS_TIMER_CREATE = 266 + SYS_VSERVER = 267 + SYS_IO_SETUP = 268 + SYS_IO_DESTROY = 269 + SYS_IO_SUBMIT = 270 + SYS_IO_CANCEL = 271 + SYS_IO_GETEVENTS = 272 + SYS_MQ_OPEN = 273 + SYS_MQ_UNLINK = 274 + SYS_MQ_TIMEDSEND = 275 + SYS_MQ_TIMEDRECEIVE = 276 + SYS_MQ_NOTIFY = 277 + SYS_MQ_GETSETATTR = 278 + SYS_WAITID = 279 + SYS_TEE = 280 + SYS_ADD_KEY = 281 + SYS_REQUEST_KEY = 282 + SYS_KEYCTL = 283 + SYS_OPENAT = 284 + SYS_MKDIRAT = 285 + SYS_MKNODAT = 286 + SYS_FCHOWNAT = 287 + SYS_FUTIMESAT = 288 + SYS_FSTATAT64 = 289 + SYS_UNLINKAT = 290 + SYS_RENAMEAT = 291 + SYS_LINKAT = 292 + SYS_SYMLINKAT = 293 + SYS_READLINKAT = 294 + SYS_FCHMODAT = 295 + SYS_FACCESSAT = 296 + SYS_PSELECT6 = 297 + SYS_PPOLL = 298 + SYS_UNSHARE = 299 + SYS_SET_ROBUST_LIST = 300 + SYS_GET_ROBUST_LIST = 301 + SYS_MIGRATE_PAGES = 302 + SYS_MBIND = 303 + SYS_GET_MEMPOLICY = 304 + SYS_SET_MEMPOLICY = 305 + SYS_KEXEC_LOAD = 306 + SYS_MOVE_PAGES = 307 + SYS_GETCPU = 308 + SYS_EPOLL_PWAIT = 309 + SYS_UTIMENSAT = 310 + SYS_SIGNALFD = 311 + SYS_TIMERFD_CREATE = 312 + SYS_EVENTFD = 313 + SYS_FALLOCATE = 314 + SYS_TIMERFD_SETTIME = 315 + SYS_TIMERFD_GETTIME = 316 + SYS_SIGNALFD4 = 317 + SYS_EVENTFD2 = 318 + SYS_EPOLL_CREATE1 = 319 + SYS_DUP3 = 320 + SYS_PIPE2 = 321 + SYS_INOTIFY_INIT1 = 322 + SYS_ACCEPT4 = 323 + SYS_PREADV = 324 + SYS_PWRITEV = 325 + SYS_RT_TGSIGQUEUEINFO = 326 + SYS_PERF_EVENT_OPEN = 327 + SYS_RECVMMSG = 328 + SYS_FANOTIFY_INIT = 329 + SYS_FANOTIFY_MARK = 330 + SYS_PRLIMIT64 = 331 + SYS_NAME_TO_HANDLE_AT = 332 + SYS_OPEN_BY_HANDLE_AT = 333 + SYS_CLOCK_ADJTIME = 334 + SYS_SYNCFS = 335 + SYS_SENDMMSG = 336 + SYS_SETNS = 337 + SYS_PROCESS_VM_READV = 338 + SYS_PROCESS_VM_WRITEV = 339 + SYS_KERN_FEATURES = 340 + SYS_KCMP = 341 + SYS_FINIT_MODULE = 342 + SYS_SCHED_SETATTR = 343 + SYS_SCHED_GETATTR = 344 + SYS_RENAMEAT2 = 345 + SYS_SECCOMP = 346 + SYS_GETRANDOM = 347 + SYS_MEMFD_CREATE = 348 + SYS_BPF = 349 + SYS_EXECVEAT = 350 + SYS_MEMBARRIER = 351 + SYS_USERFAULTFD = 352 + SYS_BIND = 353 + SYS_LISTEN = 354 + SYS_SETSOCKOPT = 355 + SYS_MLOCK2 = 356 + SYS_COPY_FILE_RANGE = 357 + SYS_PREADV2 = 358 + SYS_PWRITEV2 = 359 + SYS_STATX = 360 + SYS_IO_PGETEVENTS = 361 + SYS_PKEY_MPROTECT = 362 + SYS_PKEY_ALLOC = 363 + SYS_PKEY_FREE = 364 + SYS_RSEQ = 365 + SYS_SEMTIMEDOP = 392 + SYS_SEMGET = 393 + SYS_SEMCTL = 394 + SYS_SHMGET = 395 + SYS_SHMCTL = 396 + SYS_SHMAT = 397 + SYS_SHMDT = 398 + SYS_MSGGET = 399 + SYS_MSGSND = 400 + SYS_MSGRCV = 401 + SYS_MSGCTL = 402 + SYS_PIDFD_SEND_SIGNAL = 424 + SYS_IO_URING_SETUP = 425 + SYS_IO_URING_ENTER = 426 + SYS_IO_URING_REGISTER = 427 + SYS_OPEN_TREE = 428 + SYS_MOVE_MOUNT = 429 + SYS_FSOPEN = 430 + SYS_FSCONFIG = 431 + SYS_FSMOUNT = 432 + SYS_FSPICK = 433 + SYS_PIDFD_OPEN = 434 + SYS_CLOSE_RANGE = 436 + SYS_OPENAT2 = 437 + SYS_PIDFD_GETFD = 438 + SYS_FACCESSAT2 = 439 + SYS_PROCESS_MADVISE = 440 + SYS_EPOLL_PWAIT2 = 441 + SYS_MOUNT_SETATTR = 442 + SYS_QUOTACTL_FD = 443 + SYS_LANDLOCK_CREATE_RULESET = 444 + SYS_LANDLOCK_ADD_RULE = 445 + SYS_LANDLOCK_RESTRICT_SELF = 446 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go index 2673e6c590..4c8dc0ba2e 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go @@ -535,3 +535,107 @@ type CtlInfo struct { Id uint32 Name [96]byte } + +const SizeofKinfoProc = 0x288 + +type Eproc struct { + Paddr uintptr + Sess uintptr + Pcred Pcred + Ucred Ucred + Vm Vmspace + Ppid int32 + Pgid int32 + Jobc int16 + Tdev int32 + Tpgid int32 + Tsess uintptr + Wmesg [8]int8 + Xsize int32 + Xrssize int16 + Xccount int16 + Xswrss int16 + Flag int32 + Login [12]int8 + Spare [4]int32 + _ [4]byte +} + +type ExternProc struct { + P_starttime Timeval + P_vmspace *Vmspace + P_sigacts uintptr + P_flag int32 + P_stat int8 + P_pid int32 + P_oppid int32 + P_dupfd int32 + User_stack *int8 + Exit_thread *byte + P_debugger int32 + Sigwait int32 + P_estcpu uint32 + P_cpticks int32 + P_pctcpu uint32 + P_wchan *byte + P_wmesg *int8 + P_swtime uint32 + P_slptime uint32 + P_realtimer Itimerval + P_rtime Timeval + P_uticks uint64 + P_sticks uint64 + P_iticks uint64 + P_traceflag int32 + P_tracep uintptr + P_siglist int32 + P_textvp uintptr + P_holdcnt int32 + P_sigmask uint32 + P_sigignore uint32 + P_sigcatch uint32 + P_priority uint8 + P_usrpri uint8 + P_nice int8 + P_comm [17]int8 + P_pgrp uintptr + P_addr uintptr + P_xstat uint16 + P_acflag uint16 + P_ru *Rusage +} + +type Itimerval struct { + Interval Timeval + Value Timeval +} + +type KinfoProc struct { + Proc ExternProc + Eproc Eproc +} + +type Vmspace struct { + Dummy int32 + Dummy2 *int8 + Dummy3 [5]int32 + Dummy4 [3]*int8 +} + +type Pcred struct { + Pc_lock [72]int8 + Pc_ucred uintptr + P_ruid uint32 + P_svuid uint32 + P_rgid uint32 + P_svgid uint32 + P_refcnt int32 + _ [4]byte +} + +type Ucred struct { + Ref int32 + Uid uint32 + Ngroups int16 + Groups [16]uint32 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go index 1465cbcffe..96f0e6ae2a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go @@ -535,3 +535,107 @@ type CtlInfo struct { Id uint32 Name [96]byte } + +const SizeofKinfoProc = 0x288 + +type Eproc struct { + Paddr uintptr + Sess uintptr + Pcred Pcred + Ucred Ucred + Vm Vmspace + Ppid int32 + Pgid int32 + Jobc int16 + Tdev int32 + Tpgid int32 + Tsess uintptr + Wmesg [8]int8 + Xsize int32 + Xrssize int16 + Xccount int16 + Xswrss int16 + Flag int32 + Login [12]int8 + Spare [4]int32 + _ [4]byte +} + +type ExternProc struct { + P_starttime Timeval + P_vmspace *Vmspace + P_sigacts uintptr + P_flag int32 + P_stat int8 + P_pid int32 + P_oppid int32 + P_dupfd int32 + User_stack *int8 + Exit_thread *byte + P_debugger int32 + Sigwait int32 + P_estcpu uint32 + P_cpticks int32 + P_pctcpu uint32 + P_wchan *byte + P_wmesg *int8 + P_swtime uint32 + P_slptime uint32 + P_realtimer Itimerval + P_rtime Timeval + P_uticks uint64 + P_sticks uint64 + P_iticks uint64 + P_traceflag int32 + P_tracep uintptr + P_siglist int32 + P_textvp uintptr + P_holdcnt int32 + P_sigmask uint32 + P_sigignore uint32 + P_sigcatch uint32 + P_priority uint8 + P_usrpri uint8 + P_nice int8 + P_comm [17]int8 + P_pgrp uintptr + P_addr uintptr + P_xstat uint16 + P_acflag uint16 + P_ru *Rusage +} + +type Itimerval struct { + Interval Timeval + Value Timeval +} + +type KinfoProc struct { + Proc ExternProc + Eproc Eproc +} + +type Vmspace struct { + Dummy int32 + Dummy2 *int8 + Dummy3 [5]int32 + Dummy4 [3]*int8 +} + +type Pcred struct { + Pc_lock [72]int8 + Pc_ucred uintptr + P_ruid uint32 + P_svuid uint32 + P_rgid uint32 + P_svgid uint32 + P_refcnt int32 + _ [4]byte +} + +type Ucred struct { + Ref int32 + Uid uint32 + Ngroups int16 + Groups [16]uint32 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go index 1d049d7a12..d0ba8e9b86 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go @@ -431,6 +431,9 @@ type Winsize struct { const ( AT_FDCWD = 0xfffafdcd AT_SYMLINK_NOFOLLOW = 0x1 + AT_REMOVEDIR = 0x2 + AT_EACCESS = 0x4 + AT_SYMLINK_FOLLOW = 0x8 ) type PollFd struct { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go index c51bc88ffd..1f99c024af 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go @@ -672,9 +672,10 @@ type Winsize struct { const ( AT_FDCWD = -0x64 - AT_REMOVEDIR = 0x800 - AT_SYMLINK_FOLLOW = 0x400 + AT_EACCESS = 0x100 AT_SYMLINK_NOFOLLOW = 0x200 + AT_SYMLINK_FOLLOW = 0x400 + AT_REMOVEDIR = 0x800 ) type PollFd struct { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go index 395b691871..ddf0305a5d 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go @@ -675,9 +675,10 @@ type Winsize struct { const ( AT_FDCWD = -0x64 - AT_REMOVEDIR = 0x800 - AT_SYMLINK_FOLLOW = 0x400 + AT_EACCESS = 0x100 AT_SYMLINK_NOFOLLOW = 0x200 + AT_SYMLINK_FOLLOW = 0x400 + AT_REMOVEDIR = 0x800 ) type PollFd struct { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go index d3f9d2541b..dce0a5c80c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go @@ -656,9 +656,10 @@ type Winsize struct { const ( AT_FDCWD = -0x64 - AT_REMOVEDIR = 0x800 - AT_SYMLINK_FOLLOW = 0x400 + AT_EACCESS = 0x100 AT_SYMLINK_NOFOLLOW = 0x200 + AT_SYMLINK_FOLLOW = 0x400 + AT_REMOVEDIR = 0x800 ) type PollFd struct { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go index 434d6e8e83..e232447025 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go @@ -653,9 +653,10 @@ type Winsize struct { const ( AT_FDCWD = -0x64 - AT_REMOVEDIR = 0x800 - AT_SYMLINK_FOLLOW = 0x400 + AT_EACCESS = 0x100 AT_SYMLINK_NOFOLLOW = 0x200 + AT_SYMLINK_FOLLOW = 0x400 + AT_REMOVEDIR = 0x800 ) type PollFd struct { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go index 087323591e..4b73bb3b63 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -351,6 +351,13 @@ type RawSockaddrIUCV struct { Name [8]int8 } +type RawSockaddrNFC struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 +} + type _Socklen uint32 type Linger struct { @@ -445,6 +452,11 @@ type CanFilter struct { Mask uint32 } +type TCPRepairOpt struct { + Code uint32 + Val uint32 +} + const ( SizeofSockaddrInet4 = 0x10 SizeofSockaddrInet6 = 0x1c @@ -464,6 +476,7 @@ const ( SizeofSockaddrL2TPIP = 0x10 SizeofSockaddrL2TPIP6 = 0x20 SizeofSockaddrIUCV = 0x20 + SizeofSockaddrNFC = 0x10 SizeofLinger = 0x8 SizeofIPMreq = 0x8 SizeofIPMreqn = 0xc @@ -476,6 +489,7 @@ const ( SizeofUcred = 0xc SizeofTCPInfo = 0x68 SizeofCanFilter = 0x8 + SizeofTCPRepairOpt = 0x8 ) const ( @@ -673,6 +687,16 @@ type NdMsg struct { Type uint8 } +const ( + ICMP_FILTER = 0x1 + + ICMPV6_FILTER = 0x1 + ICMPV6_FILTER_BLOCK = 0x1 + ICMPV6_FILTER_BLOCKOTHERS = 0x3 + ICMPV6_FILTER_PASS = 0x2 + ICMPV6_FILTER_PASSONLY = 0x4 +) + const ( SizeofSockFilter = 0x8 ) @@ -993,7 +1017,7 @@ const ( PERF_COUNT_SW_EMULATION_FAULTS = 0x8 PERF_COUNT_SW_DUMMY = 0x9 PERF_COUNT_SW_BPF_OUTPUT = 0xa - PERF_COUNT_SW_MAX = 0xb + PERF_COUNT_SW_MAX = 0xc PERF_SAMPLE_IP = 0x1 PERF_SAMPLE_TID = 0x2 PERF_SAMPLE_TIME = 0x4 @@ -1765,6 +1789,8 @@ const ( NFPROTO_NUMPROTO = 0xd ) +const SO_ORIGINAL_DST = 0x50 + type Nfgenmsg struct { Nfgen_family uint8 Version uint8 @@ -2330,8 +2356,8 @@ const ( SOF_TIMESTAMPING_OPT_PKTINFO = 0x2000 SOF_TIMESTAMPING_OPT_TX_SWHW = 0x4000 - SOF_TIMESTAMPING_LAST = 0x4000 - SOF_TIMESTAMPING_MASK = 0x7fff + SOF_TIMESTAMPING_LAST = 0x8000 + SOF_TIMESTAMPING_MASK = 0xffff SCM_TSTAMP_SND = 0x0 SCM_TSTAMP_SCHED = 0x1 @@ -2907,7 +2933,7 @@ const ( DEVLINK_CMD_TRAP_POLICER_NEW = 0x47 DEVLINK_CMD_TRAP_POLICER_DEL = 0x48 DEVLINK_CMD_HEALTH_REPORTER_TEST = 0x49 - DEVLINK_CMD_MAX = 0x49 + DEVLINK_CMD_MAX = 0x4d DEVLINK_PORT_TYPE_NOTSET = 0x0 DEVLINK_PORT_TYPE_AUTO = 0x1 DEVLINK_PORT_TYPE_ETH = 0x2 @@ -3130,7 +3156,7 @@ const ( DEVLINK_ATTR_RELOAD_ACTION_INFO = 0xa2 DEVLINK_ATTR_RELOAD_ACTION_STATS = 0xa3 DEVLINK_ATTR_PORT_PCI_SF_NUMBER = 0xa4 - DEVLINK_ATTR_MAX = 0xa4 + DEVLINK_ATTR_MAX = 0xa9 DEVLINK_DPIPE_FIELD_MAPPING_TYPE_NONE = 0x0 DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX = 0x1 DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT = 0x0 @@ -3426,7 +3452,7 @@ const ( ETHTOOL_MSG_CABLE_TEST_ACT = 0x1a ETHTOOL_MSG_CABLE_TEST_TDR_ACT = 0x1b ETHTOOL_MSG_TUNNEL_INFO_GET = 0x1c - ETHTOOL_MSG_USER_MAX = 0x1c + ETHTOOL_MSG_USER_MAX = 0x21 ETHTOOL_MSG_KERNEL_NONE = 0x0 ETHTOOL_MSG_STRSET_GET_REPLY = 0x1 ETHTOOL_MSG_LINKINFO_GET_REPLY = 0x2 @@ -3457,7 +3483,7 @@ const ( ETHTOOL_MSG_CABLE_TEST_NTF = 0x1b ETHTOOL_MSG_CABLE_TEST_TDR_NTF = 0x1c ETHTOOL_MSG_TUNNEL_INFO_GET_REPLY = 0x1d - ETHTOOL_MSG_KERNEL_MAX = 0x1d + ETHTOOL_MSG_KERNEL_MAX = 0x22 ETHTOOL_A_HEADER_UNSPEC = 0x0 ETHTOOL_A_HEADER_DEV_INDEX = 0x1 ETHTOOL_A_HEADER_DEV_NAME = 0x2 @@ -3742,3 +3768,158 @@ const ( NLMSGERR_ATTR_OFFS = 0x2 NLMSGERR_ATTR_COOKIE = 0x3 ) + +type ( + EraseInfo struct { + Start uint32 + Length uint32 + } + EraseInfo64 struct { + Start uint64 + Length uint64 + } + MtdOobBuf struct { + Start uint32 + Length uint32 + Ptr *uint8 + } + MtdOobBuf64 struct { + Start uint64 + Pad uint32 + Length uint32 + Ptr uint64 + } + MtdWriteReq struct { + Start uint64 + Len uint64 + Ooblen uint64 + Data uint64 + Oob uint64 + Mode uint8 + _ [7]uint8 + } + MtdInfo struct { + Type uint8 + Flags uint32 + Size uint32 + Erasesize uint32 + Writesize uint32 + Oobsize uint32 + _ uint64 + } + RegionInfo struct { + Offset uint32 + Erasesize uint32 + Numblocks uint32 + Regionindex uint32 + } + OtpInfo struct { + Start uint32 + Length uint32 + Locked uint32 + } + NandOobinfo struct { + Useecc uint32 + Eccbytes uint32 + Oobfree [8][2]uint32 + Eccpos [32]uint32 + } + NandOobfree struct { + Offset uint32 + Length uint32 + } + NandEcclayout struct { + Eccbytes uint32 + Eccpos [64]uint32 + Oobavail uint32 + Oobfree [8]NandOobfree + } + MtdEccStats struct { + Corrected uint32 + Failed uint32 + Badblocks uint32 + Bbtblocks uint32 + } +) + +const ( + MTD_OPS_PLACE_OOB = 0x0 + MTD_OPS_AUTO_OOB = 0x1 + MTD_OPS_RAW = 0x2 +) + +const ( + MTD_FILE_MODE_NORMAL = 0x0 + MTD_FILE_MODE_OTP_FACTORY = 0x1 + MTD_FILE_MODE_OTP_USER = 0x2 + MTD_FILE_MODE_RAW = 0x3 +) + +const ( + NFC_CMD_UNSPEC = 0x0 + NFC_CMD_GET_DEVICE = 0x1 + NFC_CMD_DEV_UP = 0x2 + NFC_CMD_DEV_DOWN = 0x3 + NFC_CMD_DEP_LINK_UP = 0x4 + NFC_CMD_DEP_LINK_DOWN = 0x5 + NFC_CMD_START_POLL = 0x6 + NFC_CMD_STOP_POLL = 0x7 + NFC_CMD_GET_TARGET = 0x8 + NFC_EVENT_TARGETS_FOUND = 0x9 + NFC_EVENT_DEVICE_ADDED = 0xa + NFC_EVENT_DEVICE_REMOVED = 0xb + NFC_EVENT_TARGET_LOST = 0xc + NFC_EVENT_TM_ACTIVATED = 0xd + NFC_EVENT_TM_DEACTIVATED = 0xe + NFC_CMD_LLC_GET_PARAMS = 0xf + NFC_CMD_LLC_SET_PARAMS = 0x10 + NFC_CMD_ENABLE_SE = 0x11 + NFC_CMD_DISABLE_SE = 0x12 + NFC_CMD_LLC_SDREQ = 0x13 + NFC_EVENT_LLC_SDRES = 0x14 + NFC_CMD_FW_DOWNLOAD = 0x15 + NFC_EVENT_SE_ADDED = 0x16 + NFC_EVENT_SE_REMOVED = 0x17 + NFC_EVENT_SE_CONNECTIVITY = 0x18 + NFC_EVENT_SE_TRANSACTION = 0x19 + NFC_CMD_GET_SE = 0x1a + NFC_CMD_SE_IO = 0x1b + NFC_CMD_ACTIVATE_TARGET = 0x1c + NFC_CMD_VENDOR = 0x1d + NFC_CMD_DEACTIVATE_TARGET = 0x1e + NFC_ATTR_UNSPEC = 0x0 + NFC_ATTR_DEVICE_INDEX = 0x1 + NFC_ATTR_DEVICE_NAME = 0x2 + NFC_ATTR_PROTOCOLS = 0x3 + NFC_ATTR_TARGET_INDEX = 0x4 + NFC_ATTR_TARGET_SENS_RES = 0x5 + NFC_ATTR_TARGET_SEL_RES = 0x6 + NFC_ATTR_TARGET_NFCID1 = 0x7 + NFC_ATTR_TARGET_SENSB_RES = 0x8 + NFC_ATTR_TARGET_SENSF_RES = 0x9 + NFC_ATTR_COMM_MODE = 0xa + NFC_ATTR_RF_MODE = 0xb + NFC_ATTR_DEVICE_POWERED = 0xc + NFC_ATTR_IM_PROTOCOLS = 0xd + NFC_ATTR_TM_PROTOCOLS = 0xe + NFC_ATTR_LLC_PARAM_LTO = 0xf + NFC_ATTR_LLC_PARAM_RW = 0x10 + NFC_ATTR_LLC_PARAM_MIUX = 0x11 + NFC_ATTR_SE = 0x12 + NFC_ATTR_LLC_SDP = 0x13 + NFC_ATTR_FIRMWARE_NAME = 0x14 + NFC_ATTR_SE_INDEX = 0x15 + NFC_ATTR_SE_TYPE = 0x16 + NFC_ATTR_SE_AID = 0x17 + NFC_ATTR_FIRMWARE_DOWNLOAD_STATUS = 0x18 + NFC_ATTR_SE_APDU = 0x19 + NFC_ATTR_TARGET_ISO15693_DSFID = 0x1a + NFC_ATTR_TARGET_ISO15693_UID = 0x1b + NFC_ATTR_SE_PARAMS = 0x1c + NFC_ATTR_VENDOR_ID = 0x1d + NFC_ATTR_VENDOR_SUBCMD = 0x1e + NFC_ATTR_VENDOR_DATA = 0x1f + NFC_SDP_ATTR_UNSPEC = 0x0 + NFC_SDP_ATTR_URI = 0x1 + NFC_SDP_ATTR_SAP = 0x2 +) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index 4d4d283de5..72f2e96f32 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -128,6 +128,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint32 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -159,10 +170,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [16]byte +} + const ( - SizeofIovec = 0x8 - SizeofMsghdr = 0x1c - SizeofCmsghdr = 0xc + SizeofSockaddrNFCLLCP = 0x58 + SizeofIovec = 0x8 + SizeofMsghdr = 0x1c + SizeofCmsghdr = 0xc ) const ( diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index 8a2eed5ec4..d5f018d13d 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -130,6 +130,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -162,10 +173,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [24]byte +} + const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index 94b34add64..675446d936 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -134,6 +134,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint32 +} + type RawSockaddr struct { Family uint16 Data [14]uint8 @@ -165,10 +176,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [16]byte +} + const ( - SizeofIovec = 0x8 - SizeofMsghdr = 0x1c - SizeofCmsghdr = 0xc + SizeofSockaddrNFCLLCP = 0x58 + SizeofIovec = 0x8 + SizeofMsghdr = 0x1c + SizeofCmsghdr = 0xc ) const ( diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index 2143de4d59..711d0711cd 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -131,6 +131,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -163,10 +174,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [24]byte +} + const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index a40216eee6..c1131c7411 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -133,6 +133,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint32 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -164,10 +175,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [16]byte +} + const ( - SizeofIovec = 0x8 - SizeofMsghdr = 0x1c - SizeofCmsghdr = 0xc + SizeofSockaddrNFCLLCP = 0x58 + SizeofIovec = 0x8 + SizeofMsghdr = 0x1c + SizeofCmsghdr = 0xc ) const ( diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index e834b069fd..91d5574ff9 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -131,6 +131,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -163,10 +174,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [24]byte +} + const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index e31083b048..5d721497b7 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -131,6 +131,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -163,10 +174,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [24]byte +} + const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index 42811f7fb5..a5addd06aa 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -133,6 +133,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint32 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -164,10 +175,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [16]byte +} + const ( - SizeofIovec = 0x8 - SizeofMsghdr = 0x1c - SizeofCmsghdr = 0xc + SizeofSockaddrNFCLLCP = 0x58 + SizeofIovec = 0x8 + SizeofMsghdr = 0x1c + SizeofCmsghdr = 0xc ) const ( diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go index af7a72017e..bb6b03dfcb 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go @@ -134,6 +134,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint32 +} + type RawSockaddr struct { Family uint16 Data [14]uint8 @@ -165,10 +176,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [16]byte +} + const ( - SizeofIovec = 0x8 - SizeofMsghdr = 0x1c - SizeofCmsghdr = 0xc + SizeofSockaddrNFCLLCP = 0x58 + SizeofIovec = 0x8 + SizeofMsghdr = 0x1c + SizeofCmsghdr = 0xc ) const ( diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index 2a3afbaef9..7637243b7b 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -132,6 +132,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]uint8 @@ -164,10 +175,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [24]byte +} + const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index c0de30a658..a1a28e525f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -132,6 +132,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]uint8 @@ -164,10 +175,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [24]byte +} + const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go index 74faf2e91f..e0a8a13622 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -131,6 +131,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]uint8 @@ -163,10 +174,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [24]byte +} + const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index 9a8f0c2c6a..21d6e56c70 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -130,6 +130,17 @@ const ( FADV_NOREUSE = 0x7 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -162,10 +173,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [24]byte +} + const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go index 72cdda75bd..0531e98f64 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -134,6 +134,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -166,10 +177,16 @@ type Cmsghdr struct { Type int32 } +type ifreq struct { + Ifrn [16]byte + Ifru [24]byte +} + const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_netbsd_386.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_netbsd_386.go index b10e73abf9..2fd2060e61 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_netbsd_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_netbsd_386.go @@ -445,8 +445,10 @@ type Ptmget struct { const ( AT_FDCWD = -0x64 - AT_SYMLINK_FOLLOW = 0x400 + AT_EACCESS = 0x100 AT_SYMLINK_NOFOLLOW = 0x200 + AT_SYMLINK_FOLLOW = 0x400 + AT_REMOVEDIR = 0x800 ) type PollFd struct { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_netbsd_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_netbsd_amd64.go index 28ed6d55ae..6a5a1a8ae5 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_netbsd_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_netbsd_amd64.go @@ -453,8 +453,10 @@ type Ptmget struct { const ( AT_FDCWD = -0x64 - AT_SYMLINK_FOLLOW = 0x400 + AT_EACCESS = 0x100 AT_SYMLINK_NOFOLLOW = 0x200 + AT_SYMLINK_FOLLOW = 0x400 + AT_REMOVEDIR = 0x800 ) type PollFd struct { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm.go index 4ba196ebe5..84cc8d01e6 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm.go @@ -450,8 +450,10 @@ type Ptmget struct { const ( AT_FDCWD = -0x64 - AT_SYMLINK_FOLLOW = 0x400 + AT_EACCESS = 0x100 AT_SYMLINK_NOFOLLOW = 0x200 + AT_SYMLINK_FOLLOW = 0x400 + AT_REMOVEDIR = 0x800 ) type PollFd struct { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm64.go index dd642bd9c8..c844e7096f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm64.go @@ -453,8 +453,10 @@ type Ptmget struct { const ( AT_FDCWD = -0x64 - AT_SYMLINK_FOLLOW = 0x400 + AT_EACCESS = 0x100 AT_SYMLINK_NOFOLLOW = 0x200 + AT_SYMLINK_FOLLOW = 0x400 + AT_REMOVEDIR = 0x800 ) type PollFd struct { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go index 1fdb0e5fa5..2a8b1e6f73 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go @@ -438,8 +438,10 @@ type Winsize struct { const ( AT_FDCWD = -0x64 - AT_SYMLINK_FOLLOW = 0x4 + AT_EACCESS = 0x1 AT_SYMLINK_NOFOLLOW = 0x2 + AT_SYMLINK_FOLLOW = 0x4 + AT_REMOVEDIR = 0x8 ) type PollFd struct { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go index e2fc93c7c0..b1759cf705 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go @@ -438,8 +438,10 @@ type Winsize struct { const ( AT_FDCWD = -0x64 - AT_SYMLINK_FOLLOW = 0x4 + AT_EACCESS = 0x1 AT_SYMLINK_NOFOLLOW = 0x2 + AT_SYMLINK_FOLLOW = 0x4 + AT_REMOVEDIR = 0x8 ) type PollFd struct { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go index 8d34b5a2fc..e807de2065 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go @@ -439,8 +439,10 @@ type Winsize struct { const ( AT_FDCWD = -0x64 - AT_SYMLINK_FOLLOW = 0x4 + AT_EACCESS = 0x1 AT_SYMLINK_NOFOLLOW = 0x2 + AT_SYMLINK_FOLLOW = 0x4 + AT_REMOVEDIR = 0x8 ) type PollFd struct { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go index ea8f1a0d9b..ff3aecaee4 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go @@ -432,8 +432,10 @@ type Winsize struct { const ( AT_FDCWD = -0x64 - AT_SYMLINK_FOLLOW = 0x4 + AT_EACCESS = 0x1 AT_SYMLINK_NOFOLLOW = 0x2 + AT_SYMLINK_FOLLOW = 0x4 + AT_REMOVEDIR = 0x8 ) type PollFd struct { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go index ec6e8bc3f1..9ecda69174 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go @@ -432,8 +432,10 @@ type Winsize struct { const ( AT_FDCWD = -0x64 - AT_SYMLINK_FOLLOW = 0x4 + AT_EACCESS = 0x1 AT_SYMLINK_NOFOLLOW = 0x2 + AT_SYMLINK_FOLLOW = 0x4 + AT_REMOVEDIR = 0x8 ) type PollFd struct { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go index 85effef9c1..ad4aad2796 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go @@ -440,3 +440,43 @@ const ( POLLWRBAND = 0x100 POLLWRNORM = 0x4 ) + +type fileObj struct { + Atim Timespec + Mtim Timespec + Ctim Timespec + Pad [3]uint64 + Name *int8 +} + +type portEvent struct { + Events int32 + Source uint16 + Pad uint16 + Object uint64 + User *byte +} + +const ( + PORT_SOURCE_AIO = 0x1 + PORT_SOURCE_TIMER = 0x2 + PORT_SOURCE_USER = 0x3 + PORT_SOURCE_FD = 0x4 + PORT_SOURCE_ALERT = 0x5 + PORT_SOURCE_MQ = 0x6 + PORT_SOURCE_FILE = 0x7 + PORT_ALERT_SET = 0x1 + PORT_ALERT_UPDATE = 0x2 + PORT_ALERT_INVALID = 0x3 + FILE_ACCESS = 0x1 + FILE_MODIFIED = 0x2 + FILE_ATTRIB = 0x4 + FILE_TRUNC = 0x100000 + FILE_NOFOLLOW = 0x10000000 + FILE_DELETE = 0x10 + FILE_RENAME_TO = 0x20 + FILE_RENAME_FROM = 0x40 + UNMOUNTED = 0x20000000 + MOUNTEDOVER = 0x40000000 + FILE_EXCEPTION = 0x60000070 +) diff --git a/src/cmd/vendor/golang.org/x/sys/windows/exec_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/exec_windows.go index 9eb1fb633a..7a11e83b7e 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/exec_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/exec_windows.go @@ -9,6 +9,8 @@ package windows import ( errorspkg "errors" "unsafe" + + "golang.org/x/sys/internal/unsafeheader" ) // EscapeArg rewrites command line argument s as prescribed @@ -78,6 +80,40 @@ func EscapeArg(s string) string { return string(qs[:j]) } +// ComposeCommandLine escapes and joins the given arguments suitable for use as a Windows command line, +// in CreateProcess's CommandLine argument, CreateService/ChangeServiceConfig's BinaryPathName argument, +// or any program that uses CommandLineToArgv. +func ComposeCommandLine(args []string) string { + var commandLine string + for i := range args { + if i > 0 { + commandLine += " " + } + commandLine += EscapeArg(args[i]) + } + return commandLine +} + +// DecomposeCommandLine breaks apart its argument command line into unescaped parts using CommandLineToArgv, +// as gathered from GetCommandLine, QUERY_SERVICE_CONFIG's BinaryPathName argument, or elsewhere that +// command lines are passed around. +func DecomposeCommandLine(commandLine string) ([]string, error) { + if len(commandLine) == 0 { + return []string{}, nil + } + var argc int32 + argv, err := CommandLineToArgv(StringToUTF16Ptr(commandLine), &argc) + if err != nil { + return nil, err + } + defer LocalFree(Handle(unsafe.Pointer(argv))) + var args []string + for _, v := range (*argv)[:argc] { + args = append(args, UTF16ToString((*v)[:])) + } + return args, nil +} + func CloseOnExec(fd Handle) { SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0) } @@ -101,8 +137,8 @@ func FullPath(name string) (path string, err error) { } } -// NewProcThreadAttributeList allocates a new ProcThreadAttributeList, with the requested maximum number of attributes. -func NewProcThreadAttributeList(maxAttrCount uint32) (*ProcThreadAttributeList, error) { +// NewProcThreadAttributeList allocates a new ProcThreadAttributeListContainer, with the requested maximum number of attributes. +func NewProcThreadAttributeList(maxAttrCount uint32) (*ProcThreadAttributeListContainer, error) { var size uintptr err := initializeProcThreadAttributeList(nil, maxAttrCount, 0, &size) if err != ERROR_INSUFFICIENT_BUFFER { @@ -111,10 +147,9 @@ func NewProcThreadAttributeList(maxAttrCount uint32) (*ProcThreadAttributeList, } return nil, err } - const psize = unsafe.Sizeof(uintptr(0)) // size is guaranteed to be ≥1 by InitializeProcThreadAttributeList. - al := (*ProcThreadAttributeList)(unsafe.Pointer(&make([]unsafe.Pointer, (size+psize-1)/psize)[0])) - err = initializeProcThreadAttributeList(al, maxAttrCount, 0, &size) + al := &ProcThreadAttributeListContainer{data: (*ProcThreadAttributeList)(unsafe.Pointer(&make([]byte, size)[0]))} + err = initializeProcThreadAttributeList(al.data, maxAttrCount, 0, &size) if err != nil { return nil, err } @@ -122,11 +157,39 @@ func NewProcThreadAttributeList(maxAttrCount uint32) (*ProcThreadAttributeList, } // Update modifies the ProcThreadAttributeList using UpdateProcThreadAttribute. -func (al *ProcThreadAttributeList) Update(attribute uintptr, flags uint32, value unsafe.Pointer, size uintptr, prevValue unsafe.Pointer, returnedSize *uintptr) error { - return updateProcThreadAttribute(al, flags, attribute, value, size, prevValue, returnedSize) +// Note that the value passed to this function will be copied into memory +// allocated by LocalAlloc, the contents of which should not contain any +// Go-managed pointers, even if the passed value itself is a Go-managed +// pointer. +func (al *ProcThreadAttributeListContainer) Update(attribute uintptr, value unsafe.Pointer, size uintptr) error { + alloc, err := LocalAlloc(LMEM_FIXED, uint32(size)) + if err != nil { + return err + } + var src, dst []byte + hdr := (*unsafeheader.Slice)(unsafe.Pointer(&src)) + hdr.Data = value + hdr.Cap = int(size) + hdr.Len = int(size) + hdr = (*unsafeheader.Slice)(unsafe.Pointer(&dst)) + hdr.Data = unsafe.Pointer(alloc) + hdr.Cap = int(size) + hdr.Len = int(size) + copy(dst, src) + al.heapAllocations = append(al.heapAllocations, alloc) + return updateProcThreadAttribute(al.data, 0, attribute, unsafe.Pointer(alloc), size, nil, nil) } // Delete frees ProcThreadAttributeList's resources. -func (al *ProcThreadAttributeList) Delete() { - deleteProcThreadAttributeList(al) +func (al *ProcThreadAttributeListContainer) Delete() { + deleteProcThreadAttributeList(al.data) + for i := range al.heapAllocations { + LocalFree(Handle(al.heapAllocations[i])) + } + al.heapAllocations = nil +} + +// List returns the actual ProcThreadAttributeList to be passed to StartupInfoEx. +func (al *ProcThreadAttributeListContainer) List() *ProcThreadAttributeList { + return al.data } diff --git a/src/cmd/vendor/golang.org/x/sys/windows/security_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/security_windows.go index 111c10d3a7..d414ef13be 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/security_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/security_windows.go @@ -889,6 +889,7 @@ type WTS_SESSION_INFO struct { //sys WTSQueryUserToken(session uint32, token *Token) (err error) = wtsapi32.WTSQueryUserToken //sys WTSEnumerateSessions(handle Handle, reserved uint32, version uint32, sessions **WTS_SESSION_INFO, count *uint32) (err error) = wtsapi32.WTSEnumerateSessionsW //sys WTSFreeMemory(ptr uintptr) = wtsapi32.WTSFreeMemory +//sys WTSGetActiveConsoleSessionId() (sessionID uint32) type ACL struct { aclRevision byte diff --git a/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go index bb6aaf89e4..1215b2ae20 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go @@ -220,6 +220,7 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys CancelIo(s Handle) (err error) //sys CancelIoEx(s Handle, o *Overlapped) (err error) //sys CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) = CreateProcessW +//sys CreateProcessAsUser(token Token, appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) = advapi32.CreateProcessAsUserW //sys initializeProcThreadAttributeList(attrlist *ProcThreadAttributeList, attrcount uint32, flags uint32, size *uintptr) (err error) = InitializeProcThreadAttributeList //sys deleteProcThreadAttributeList(attrlist *ProcThreadAttributeList) = DeleteProcThreadAttributeList //sys updateProcThreadAttribute(attrlist *ProcThreadAttributeList, flags uint32, attr uintptr, value unsafe.Pointer, size uintptr, prevvalue unsafe.Pointer, returnedsize *uintptr) (err error) = UpdateProcThreadAttribute diff --git a/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go index 23fe18ecef..17f03312df 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go @@ -680,7 +680,7 @@ const ( WTD_CHOICE_CERT = 5 WTD_STATEACTION_IGNORE = 0x00000000 - WTD_STATEACTION_VERIFY = 0x00000010 + WTD_STATEACTION_VERIFY = 0x00000001 WTD_STATEACTION_CLOSE = 0x00000002 WTD_STATEACTION_AUTO_CACHE = 0x00000003 WTD_STATEACTION_AUTO_CACHE_FLUSH = 0x00000004 @@ -909,14 +909,15 @@ type StartupInfoEx struct { // ProcThreadAttributeList is a placeholder type to represent a PROC_THREAD_ATTRIBUTE_LIST. // -// To create a *ProcThreadAttributeList, use NewProcThreadAttributeList, and -// free its memory using ProcThreadAttributeList.Delete. -type ProcThreadAttributeList struct { - // This is of type unsafe.Pointer, not of type byte or uintptr, because - // the contents of it is mostly a list of pointers, and in most cases, - // that's a list of pointers to Go-allocated objects. In order to keep - // the GC from collecting these objects, we declare this as unsafe.Pointer. - _ [1]unsafe.Pointer +// To create a *ProcThreadAttributeList, use NewProcThreadAttributeList, update +// it with ProcThreadAttributeListContainer.Update, free its memory using +// ProcThreadAttributeListContainer.Delete, and access the list itself using +// ProcThreadAttributeListContainer.List. +type ProcThreadAttributeList struct{} + +type ProcThreadAttributeListContainer struct { + data *ProcThreadAttributeList + heapAllocations []uintptr } type ProcessInformation struct { diff --git a/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go index 559bc845c9..2083ec376e 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go @@ -69,6 +69,7 @@ var ( procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW") procConvertStringSidToSidW = modadvapi32.NewProc("ConvertStringSidToSidW") procCopySid = modadvapi32.NewProc("CopySid") + procCreateProcessAsUserW = modadvapi32.NewProc("CreateProcessAsUserW") procCreateServiceW = modadvapi32.NewProc("CreateServiceW") procCreateWellKnownSid = modadvapi32.NewProc("CreateWellKnownSid") procCryptAcquireContextW = modadvapi32.NewProc("CryptAcquireContextW") @@ -345,6 +346,7 @@ var ( procVirtualLock = modkernel32.NewProc("VirtualLock") procVirtualProtect = modkernel32.NewProc("VirtualProtect") procVirtualUnlock = modkernel32.NewProc("VirtualUnlock") + procWTSGetActiveConsoleSessionId = modkernel32.NewProc("WTSGetActiveConsoleSessionId") procWaitForMultipleObjects = modkernel32.NewProc("WaitForMultipleObjects") procWaitForSingleObject = modkernel32.NewProc("WaitForSingleObject") procWriteConsoleW = modkernel32.NewProc("WriteConsoleW") @@ -553,6 +555,18 @@ func CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) { return } +func CreateProcessAsUser(token Token, appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) { + var _p0 uint32 + if inheritHandles { + _p0 = 1 + } + r1, _, e1 := syscall.Syscall12(procCreateProcessAsUserW.Addr(), 11, uintptr(token), uintptr(unsafe.Pointer(appName)), uintptr(unsafe.Pointer(commandLine)), uintptr(unsafe.Pointer(procSecurity)), uintptr(unsafe.Pointer(threadSecurity)), uintptr(_p0), uintptr(creationFlags), uintptr(unsafe.Pointer(env)), uintptr(unsafe.Pointer(currentDir)), uintptr(unsafe.Pointer(startupInfo)), uintptr(unsafe.Pointer(outProcInfo)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func CreateService(mgr Handle, serviceName *uint16, displayName *uint16, access uint32, srvType uint32, startType uint32, errCtl uint32, pathName *uint16, loadOrderGroup *uint16, tagId *uint32, dependencies *uint16, serviceStartName *uint16, password *uint16) (handle Handle, err error) { r0, _, e1 := syscall.Syscall15(procCreateServiceW.Addr(), 13, uintptr(mgr), uintptr(unsafe.Pointer(serviceName)), uintptr(unsafe.Pointer(displayName)), uintptr(access), uintptr(srvType), uintptr(startType), uintptr(errCtl), uintptr(unsafe.Pointer(pathName)), uintptr(unsafe.Pointer(loadOrderGroup)), uintptr(unsafe.Pointer(tagId)), uintptr(unsafe.Pointer(dependencies)), uintptr(unsafe.Pointer(serviceStartName)), uintptr(unsafe.Pointer(password)), 0, 0) handle = Handle(r0) @@ -2979,6 +2993,12 @@ func VirtualUnlock(addr uintptr, length uintptr) (err error) { return } +func WTSGetActiveConsoleSessionId() (sessionID uint32) { + r0, _, _ := syscall.Syscall(procWTSGetActiveConsoleSessionId.Addr(), 0, 0, 0, 0) + sessionID = uint32(r0) + return +} + func waitForMultipleObjects(count uint32, handles uintptr, waitAll bool, waitMilliseconds uint32) (event uint32, err error) { var _p0 uint32 if waitAll { diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 4d48b87a87..59ea550f55 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -39,7 +39,7 @@ golang.org/x/mod/sumdb/dirhash golang.org/x/mod/sumdb/note golang.org/x/mod/sumdb/tlog golang.org/x/mod/zip -# golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 +# golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e ## explicit; go 1.17 golang.org/x/sys/internal/unsafeheader golang.org/x/sys/plan9 diff --git a/src/go.mod b/src/go.mod index 726d490668..08c5a18c1d 100644 --- a/src/go.mod +++ b/src/go.mod @@ -5,6 +5,6 @@ go 1.18 require ( golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e golang.org/x/net v0.0.0-20210825183410-e898025ed96a - golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 // indirect + golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e // indirect golang.org/x/text v0.3.7-0.20210503195748-5c7c50ebbd4f // indirect ) diff --git a/src/go.sum b/src/go.sum index 6e14cbcd7e..e7997591da 100644 --- a/src/go.sum +++ b/src/go.sum @@ -2,7 +2,7 @@ golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e h1:8foAy0aoO5GkqCvAEJ4VC4 golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/net v0.0.0-20210825183410-e898025ed96a h1:bRuuGXV8wwSdGTB+CtJf+FjgO1APK1CoO39T4BN/XBw= golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 h1:yhBbb4IRs2HS9PPlAg6DMC6mUOKexJBNsLf4Z+6En1Q= -golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e h1:XMgFehsDnnLGtjvjOfqWSUzt0alpTR1RSEuznObga2c= +golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.7-0.20210503195748-5c7c50ebbd4f h1:yQJrRE0hDxDFmZLlRaw+3vusO4fwNHgHIjUOMO7bHYI= golang.org/x/text v0.3.7-0.20210503195748-5c7c50ebbd4f/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= diff --git a/src/vendor/golang.org/x/sys/cpu/cpu.go b/src/vendor/golang.org/x/sys/cpu/cpu.go index abbec2d44b..b56886f261 100644 --- a/src/vendor/golang.org/x/sys/cpu/cpu.go +++ b/src/vendor/golang.org/x/sys/cpu/cpu.go @@ -56,6 +56,7 @@ var X86 struct { HasAVX512BF16 bool // Advanced vector extension 512 BFloat16 Instructions HasBMI1 bool // Bit manipulation instruction set 1 HasBMI2 bool // Bit manipulation instruction set 2 + HasCX16 bool // Compare and exchange 16 Bytes HasERMS bool // Enhanced REP for MOVSB and STOSB HasFMA bool // Fused-multiply-add instructions HasOSXSAVE bool // OS supports XSAVE/XRESTOR for saving/restoring XMM registers. diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_x86.go b/src/vendor/golang.org/x/sys/cpu/cpu_x86.go index 54ca4667fb..5ea287b7ec 100644 --- a/src/vendor/golang.org/x/sys/cpu/cpu_x86.go +++ b/src/vendor/golang.org/x/sys/cpu/cpu_x86.go @@ -39,6 +39,7 @@ func initOptions() { {Name: "avx512bf16", Feature: &X86.HasAVX512BF16}, {Name: "bmi1", Feature: &X86.HasBMI1}, {Name: "bmi2", Feature: &X86.HasBMI2}, + {Name: "cx16", Feature: &X86.HasCX16}, {Name: "erms", Feature: &X86.HasERMS}, {Name: "fma", Feature: &X86.HasFMA}, {Name: "osxsave", Feature: &X86.HasOSXSAVE}, @@ -73,6 +74,7 @@ func archInit() { X86.HasPCLMULQDQ = isSet(1, ecx1) X86.HasSSSE3 = isSet(9, ecx1) X86.HasFMA = isSet(12, ecx1) + X86.HasCX16 = isSet(13, ecx1) X86.HasSSE41 = isSet(19, ecx1) X86.HasSSE42 = isSet(20, ecx1) X86.HasPOPCNT = isSet(23, ecx1) diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index d50b8668fc..8307072942 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -18,7 +18,7 @@ golang.org/x/net/idna golang.org/x/net/lif golang.org/x/net/nettest golang.org/x/net/route -# golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 +# golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e ## explicit; go 1.17 golang.org/x/sys/cpu # golang.org/x/text v0.3.7-0.20210503195748-5c7c50ebbd4f -- GitLab From 782aa42255163559c5e1c4c2d98c8f28da8cf96b Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Wed, 1 Sep 2021 08:33:42 -0700 Subject: [PATCH 0979/2500] cmd/link: mark stacks as non-executable on freebsd Fixes #48112 Change-Id: I673a5fe61171e5ba3d8ce58daac79391fb4758f9 Reviewed-on: https://go-review.googlesource.com/c/go/+/346872 Trust: Keith Randall Run-TryBot: Keith Randall Reviewed-by: Cherry Mui TryBot-Result: Go Bot --- src/cmd/link/internal/ld/elf.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go index 93f974c5e0..fb75c761a1 100644 --- a/src/cmd/link/internal/ld/elf.go +++ b/src/cmd/link/internal/ld/elf.go @@ -2025,6 +2025,11 @@ func asmbElf(ctxt *Link) { ph := newElfPhdr() ph.Type = elf.PT_SUNWSTACK ph.Flags = elf.PF_W + elf.PF_R + } else if ctxt.HeadType == objabi.Hfreebsd { + ph := newElfPhdr() + ph.Type = elf.PT_GNU_STACK + ph.Flags = elf.PF_W + elf.PF_R + ph.Align = uint64(ctxt.Arch.RegSize) } elfobj: -- GitLab From d01388b04f391ac0c9872729920ebbdb0e4e6861 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Thu, 2 Sep 2021 11:27:12 -0400 Subject: [PATCH 0980/2500] all: update vendored golang.org/x/crypto Ran the following commands inside std and cmd modules: go get -d golang.org/x/crypto@32db794688a5a24a23a43f2a984cecd5b3d8da58 # master go mod tidy go mod vendor Also add the new golang.org/x/crypto/curve25519/internal/field package (it was created in x/crypto CL 315269) to TestDependencies in go/build. Position it next to its upstream copy, since its required dependencies are expected to be identical. For #36905. Change-Id: I589499cd7176c9b4b8758e59025653d19b58130e Reviewed-on: https://go-review.googlesource.com/c/go/+/347190 Trust: Dmitri Shuralyov Run-TryBot: Dmitri Shuralyov TryBot-Result: Go Bot Reviewed-by: Carlos Amedee --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 +- src/cmd/vendor/modules.txt | 2 +- src/go.mod | 2 +- src/go.sum | 4 +- src/go/build/deps_test.go | 2 +- .../x/crypto/chacha20/chacha_arm64.s | 1 + .../x/crypto/chacha20/chacha_ppc64le.s | 1 + .../x/crypto/chacha20/chacha_s390x.s | 1 + .../chacha20poly1305/chacha20poly1305_amd64.s | 1 + .../x/crypto/curve25519/curve25519.go | 52 +- .../x/crypto/curve25519/curve25519_amd64.go | 241 --- .../x/crypto/curve25519/curve25519_amd64.s | 1793 ----------------- .../x/crypto/curve25519/curve25519_generic.go | 828 -------- .../x/crypto/curve25519/curve25519_noasm.go | 12 - .../x/crypto/curve25519/internal/field/README | 7 + .../x/crypto/curve25519/internal/field/fe.go | 416 ++++ .../curve25519/internal/field/fe_amd64.go | 13 + .../curve25519/internal/field/fe_amd64.s | 379 ++++ .../internal/field/fe_amd64_noasm.go | 12 + .../curve25519/internal/field/fe_arm64.go | 16 + .../curve25519/internal/field/fe_arm64.s | 43 + .../internal/field/fe_arm64_noasm.go | 12 + .../curve25519/internal/field/fe_generic.go | 264 +++ .../curve25519/internal/field/sync.checkpoint | 1 + .../crypto/curve25519/internal/field/sync.sh | 19 + .../golang.org/x/crypto/poly1305/sum_amd64.s | 1 + .../x/crypto/poly1305/sum_ppc64le.s | 1 + .../golang.org/x/crypto/poly1305/sum_s390x.s | 1 + src/vendor/modules.txt | 3 +- 30 files changed, 1250 insertions(+), 2884 deletions(-) delete mode 100644 src/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.go delete mode 100644 src/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.s delete mode 100644 src/vendor/golang.org/x/crypto/curve25519/curve25519_generic.go delete mode 100644 src/vendor/golang.org/x/crypto/curve25519/curve25519_noasm.go create mode 100644 src/vendor/golang.org/x/crypto/curve25519/internal/field/README create mode 100644 src/vendor/golang.org/x/crypto/curve25519/internal/field/fe.go create mode 100644 src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go create mode 100644 src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s create mode 100644 src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go create mode 100644 src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go create mode 100644 src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s create mode 100644 src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go create mode 100644 src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_generic.go create mode 100644 src/vendor/golang.org/x/crypto/curve25519/internal/field/sync.checkpoint create mode 100644 src/vendor/golang.org/x/crypto/curve25519/internal/field/sync.sh diff --git a/src/cmd/go.mod b/src/cmd/go.mod index d7b2a985ac..68c3a6c992 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -6,7 +6,7 @@ require ( github.com/google/pprof v0.0.0-20210506205249-923b5ab0fc1a github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 // indirect golang.org/x/arch v0.0.0-20210502124803-cbf565b21d1e - golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e // indirect + golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect golang.org/x/mod v0.5.1-0.20210827163434-4029241eb1d5 golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e // indirect golang.org/x/term v0.0.0-20210503060354-a79de5458b56 diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 6e39f6ff8e..c6b1927eb8 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -7,8 +7,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 h1:mV02weK github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= golang.org/x/arch v0.0.0-20210502124803-cbf565b21d1e h1:pv3V0NlNSh5Q6AX/StwGLBjcLS7UN4m4Gq+V+uSecqM= golang.org/x/arch v0.0.0-20210502124803-cbf565b21d1e/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e h1:8foAy0aoO5GkqCvAEJ4VC4P3zksTg4X4aJCDpZzmgQI= -golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/mod v0.5.1-0.20210827163434-4029241eb1d5 h1:BJ9Nc92Yf5inqB18HHrMgflMJKHraE07Z29Vjc+Z/Mk= golang.org/x/mod v0.5.1-0.20210827163434-4029241eb1d5/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 59ea550f55..10c4b3ad21 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -24,7 +24,7 @@ golang.org/x/arch/arm/armasm golang.org/x/arch/arm64/arm64asm golang.org/x/arch/ppc64/ppc64asm golang.org/x/arch/x86/x86asm -# golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e +# golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 ## explicit; go 1.17 golang.org/x/crypto/ed25519 golang.org/x/crypto/ed25519/internal/edwards25519 diff --git a/src/go.mod b/src/go.mod index 08c5a18c1d..3c45b8b073 100644 --- a/src/go.mod +++ b/src/go.mod @@ -3,7 +3,7 @@ module std go 1.18 require ( - golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e + golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 golang.org/x/net v0.0.0-20210825183410-e898025ed96a golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e // indirect golang.org/x/text v0.3.7-0.20210503195748-5c7c50ebbd4f // indirect diff --git a/src/go.sum b/src/go.sum index e7997591da..c8ecc70460 100644 --- a/src/go.sum +++ b/src/go.sum @@ -1,5 +1,5 @@ -golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e h1:8foAy0aoO5GkqCvAEJ4VC4P3zksTg4X4aJCDpZzmgQI= -golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/net v0.0.0-20210825183410-e898025ed96a h1:bRuuGXV8wwSdGTB+CtJf+FjgO1APK1CoO39T4BN/XBw= golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e h1:XMgFehsDnnLGtjvjOfqWSUzt0alpTR1RSEuznObga2c= diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 80f8e1a00d..cbc77cfe72 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -395,7 +395,7 @@ var depsRules = ` < crypto/subtle < crypto/internal/subtle < crypto/elliptic/internal/fiat - < crypto/ed25519/internal/edwards25519/field + < crypto/ed25519/internal/edwards25519/field, golang.org/x/crypto/curve25519/internal/field < crypto/ed25519/internal/edwards25519 < crypto/cipher < crypto/aes, crypto/des, crypto/hmac, crypto/md5, crypto/rc4, diff --git a/src/vendor/golang.org/x/crypto/chacha20/chacha_arm64.s b/src/vendor/golang.org/x/crypto/chacha20/chacha_arm64.s index 8fb49a13e3..63cae9e6f0 100644 --- a/src/vendor/golang.org/x/crypto/chacha20/chacha_arm64.s +++ b/src/vendor/golang.org/x/crypto/chacha20/chacha_arm64.s @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build go1.11 && gc && !purego // +build go1.11,gc,!purego #include "textflag.h" diff --git a/src/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s b/src/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s index 3dad4b2fa2..5c0fed26f8 100644 --- a/src/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s +++ b/src/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s @@ -19,6 +19,7 @@ // The differences in this and the original implementation are // due to the calling conventions and initialization of constants. +//go:build gc && !purego // +build gc,!purego #include "textflag.h" diff --git a/src/vendor/golang.org/x/crypto/chacha20/chacha_s390x.s b/src/vendor/golang.org/x/crypto/chacha20/chacha_s390x.s index 818161189b..f3ef5a019d 100644 --- a/src/vendor/golang.org/x/crypto/chacha20/chacha_s390x.s +++ b/src/vendor/golang.org/x/crypto/chacha20/chacha_s390x.s @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build gc && !purego // +build gc,!purego #include "go_asm.h" diff --git a/src/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s b/src/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s index 55226b0e6c..867c181a14 100644 --- a/src/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s +++ b/src/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s @@ -4,6 +4,7 @@ // This file was originally from https://golang.org/cl/24717 by Vlad Krasnov of CloudFlare. +//go:build gc && !purego // +build gc,!purego #include "textflag.h" diff --git a/src/vendor/golang.org/x/crypto/curve25519/curve25519.go b/src/vendor/golang.org/x/crypto/curve25519/curve25519.go index 4b9a655d1b..cda3fdd354 100644 --- a/src/vendor/golang.org/x/crypto/curve25519/curve25519.go +++ b/src/vendor/golang.org/x/crypto/curve25519/curve25519.go @@ -10,6 +10,8 @@ package curve25519 // import "golang.org/x/crypto/curve25519" import ( "crypto/subtle" "fmt" + + "golang.org/x/crypto/curve25519/internal/field" ) // ScalarMult sets dst to the product scalar * point. @@ -18,7 +20,55 @@ import ( // zeroes, irrespective of the scalar. Instead, use the X25519 function, which // will return an error. func ScalarMult(dst, scalar, point *[32]byte) { - scalarMult(dst, scalar, point) + var e [32]byte + + copy(e[:], scalar[:]) + e[0] &= 248 + e[31] &= 127 + e[31] |= 64 + + var x1, x2, z2, x3, z3, tmp0, tmp1 field.Element + x1.SetBytes(point[:]) + x2.One() + x3.Set(&x1) + z3.One() + + swap := 0 + for pos := 254; pos >= 0; pos-- { + b := e[pos/8] >> uint(pos&7) + b &= 1 + swap ^= int(b) + x2.Swap(&x3, swap) + z2.Swap(&z3, swap) + swap = int(b) + + tmp0.Subtract(&x3, &z3) + tmp1.Subtract(&x2, &z2) + x2.Add(&x2, &z2) + z2.Add(&x3, &z3) + z3.Multiply(&tmp0, &x2) + z2.Multiply(&z2, &tmp1) + tmp0.Square(&tmp1) + tmp1.Square(&x2) + x3.Add(&z3, &z2) + z2.Subtract(&z3, &z2) + x2.Multiply(&tmp1, &tmp0) + tmp1.Subtract(&tmp1, &tmp0) + z2.Square(&z2) + + z3.Mult32(&tmp1, 121666) + x3.Square(&x3) + tmp0.Add(&tmp0, &z3) + z3.Multiply(&x1, &z2) + z2.Multiply(&tmp1, &tmp0) + } + + x2.Swap(&x3, swap) + z2.Swap(&z3, swap) + + z2.Invert(&z2) + x2.Multiply(&x2, &z2) + copy(dst[:], x2.Bytes()) } // ScalarBaseMult sets dst to the product scalar * base where base is the diff --git a/src/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.go b/src/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.go deleted file mode 100644 index 84858480df..0000000000 --- a/src/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.go +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build amd64 && gc && !purego -// +build amd64,gc,!purego - -package curve25519 - -// These functions are implemented in the .s files. The names of the functions -// in the rest of the file are also taken from the SUPERCOP sources to help -// people following along. - -//go:noescape - -func cswap(inout *[5]uint64, v uint64) - -//go:noescape - -func ladderstep(inout *[5][5]uint64) - -//go:noescape - -func freeze(inout *[5]uint64) - -//go:noescape - -func mul(dest, a, b *[5]uint64) - -//go:noescape - -func square(out, in *[5]uint64) - -// mladder uses a Montgomery ladder to calculate (xr/zr) *= s. -func mladder(xr, zr *[5]uint64, s *[32]byte) { - var work [5][5]uint64 - - work[0] = *xr - setint(&work[1], 1) - setint(&work[2], 0) - work[3] = *xr - setint(&work[4], 1) - - j := uint(6) - var prevbit byte - - for i := 31; i >= 0; i-- { - for j < 8 { - bit := ((*s)[i] >> j) & 1 - swap := bit ^ prevbit - prevbit = bit - cswap(&work[1], uint64(swap)) - ladderstep(&work) - j-- - } - j = 7 - } - - *xr = work[1] - *zr = work[2] -} - -func scalarMult(out, in, base *[32]byte) { - var e [32]byte - copy(e[:], (*in)[:]) - e[0] &= 248 - e[31] &= 127 - e[31] |= 64 - - var t, z [5]uint64 - unpack(&t, base) - mladder(&t, &z, &e) - invert(&z, &z) - mul(&t, &t, &z) - pack(out, &t) -} - -func setint(r *[5]uint64, v uint64) { - r[0] = v - r[1] = 0 - r[2] = 0 - r[3] = 0 - r[4] = 0 -} - -// unpack sets r = x where r consists of 5, 51-bit limbs in little-endian -// order. -func unpack(r *[5]uint64, x *[32]byte) { - r[0] = uint64(x[0]) | - uint64(x[1])<<8 | - uint64(x[2])<<16 | - uint64(x[3])<<24 | - uint64(x[4])<<32 | - uint64(x[5])<<40 | - uint64(x[6]&7)<<48 - - r[1] = uint64(x[6])>>3 | - uint64(x[7])<<5 | - uint64(x[8])<<13 | - uint64(x[9])<<21 | - uint64(x[10])<<29 | - uint64(x[11])<<37 | - uint64(x[12]&63)<<45 - - r[2] = uint64(x[12])>>6 | - uint64(x[13])<<2 | - uint64(x[14])<<10 | - uint64(x[15])<<18 | - uint64(x[16])<<26 | - uint64(x[17])<<34 | - uint64(x[18])<<42 | - uint64(x[19]&1)<<50 - - r[3] = uint64(x[19])>>1 | - uint64(x[20])<<7 | - uint64(x[21])<<15 | - uint64(x[22])<<23 | - uint64(x[23])<<31 | - uint64(x[24])<<39 | - uint64(x[25]&15)<<47 - - r[4] = uint64(x[25])>>4 | - uint64(x[26])<<4 | - uint64(x[27])<<12 | - uint64(x[28])<<20 | - uint64(x[29])<<28 | - uint64(x[30])<<36 | - uint64(x[31]&127)<<44 -} - -// pack sets out = x where out is the usual, little-endian form of the 5, -// 51-bit limbs in x. -func pack(out *[32]byte, x *[5]uint64) { - t := *x - freeze(&t) - - out[0] = byte(t[0]) - out[1] = byte(t[0] >> 8) - out[2] = byte(t[0] >> 16) - out[3] = byte(t[0] >> 24) - out[4] = byte(t[0] >> 32) - out[5] = byte(t[0] >> 40) - out[6] = byte(t[0] >> 48) - - out[6] ^= byte(t[1]<<3) & 0xf8 - out[7] = byte(t[1] >> 5) - out[8] = byte(t[1] >> 13) - out[9] = byte(t[1] >> 21) - out[10] = byte(t[1] >> 29) - out[11] = byte(t[1] >> 37) - out[12] = byte(t[1] >> 45) - - out[12] ^= byte(t[2]<<6) & 0xc0 - out[13] = byte(t[2] >> 2) - out[14] = byte(t[2] >> 10) - out[15] = byte(t[2] >> 18) - out[16] = byte(t[2] >> 26) - out[17] = byte(t[2] >> 34) - out[18] = byte(t[2] >> 42) - out[19] = byte(t[2] >> 50) - - out[19] ^= byte(t[3]<<1) & 0xfe - out[20] = byte(t[3] >> 7) - out[21] = byte(t[3] >> 15) - out[22] = byte(t[3] >> 23) - out[23] = byte(t[3] >> 31) - out[24] = byte(t[3] >> 39) - out[25] = byte(t[3] >> 47) - - out[25] ^= byte(t[4]<<4) & 0xf0 - out[26] = byte(t[4] >> 4) - out[27] = byte(t[4] >> 12) - out[28] = byte(t[4] >> 20) - out[29] = byte(t[4] >> 28) - out[30] = byte(t[4] >> 36) - out[31] = byte(t[4] >> 44) -} - -// invert calculates r = x^-1 mod p using Fermat's little theorem. -func invert(r *[5]uint64, x *[5]uint64) { - var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t [5]uint64 - - square(&z2, x) /* 2 */ - square(&t, &z2) /* 4 */ - square(&t, &t) /* 8 */ - mul(&z9, &t, x) /* 9 */ - mul(&z11, &z9, &z2) /* 11 */ - square(&t, &z11) /* 22 */ - mul(&z2_5_0, &t, &z9) /* 2^5 - 2^0 = 31 */ - - square(&t, &z2_5_0) /* 2^6 - 2^1 */ - for i := 1; i < 5; i++ { /* 2^20 - 2^10 */ - square(&t, &t) - } - mul(&z2_10_0, &t, &z2_5_0) /* 2^10 - 2^0 */ - - square(&t, &z2_10_0) /* 2^11 - 2^1 */ - for i := 1; i < 10; i++ { /* 2^20 - 2^10 */ - square(&t, &t) - } - mul(&z2_20_0, &t, &z2_10_0) /* 2^20 - 2^0 */ - - square(&t, &z2_20_0) /* 2^21 - 2^1 */ - for i := 1; i < 20; i++ { /* 2^40 - 2^20 */ - square(&t, &t) - } - mul(&t, &t, &z2_20_0) /* 2^40 - 2^0 */ - - square(&t, &t) /* 2^41 - 2^1 */ - for i := 1; i < 10; i++ { /* 2^50 - 2^10 */ - square(&t, &t) - } - mul(&z2_50_0, &t, &z2_10_0) /* 2^50 - 2^0 */ - - square(&t, &z2_50_0) /* 2^51 - 2^1 */ - for i := 1; i < 50; i++ { /* 2^100 - 2^50 */ - square(&t, &t) - } - mul(&z2_100_0, &t, &z2_50_0) /* 2^100 - 2^0 */ - - square(&t, &z2_100_0) /* 2^101 - 2^1 */ - for i := 1; i < 100; i++ { /* 2^200 - 2^100 */ - square(&t, &t) - } - mul(&t, &t, &z2_100_0) /* 2^200 - 2^0 */ - - square(&t, &t) /* 2^201 - 2^1 */ - for i := 1; i < 50; i++ { /* 2^250 - 2^50 */ - square(&t, &t) - } - mul(&t, &t, &z2_50_0) /* 2^250 - 2^0 */ - - square(&t, &t) /* 2^251 - 2^1 */ - square(&t, &t) /* 2^252 - 2^2 */ - square(&t, &t) /* 2^253 - 2^3 */ - - square(&t, &t) /* 2^254 - 2^4 */ - - square(&t, &t) /* 2^255 - 2^5 */ - mul(r, &t, &z11) /* 2^255 - 21 */ -} diff --git a/src/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.s b/src/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.s deleted file mode 100644 index 6c53380926..0000000000 --- a/src/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.s +++ /dev/null @@ -1,1793 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This code was translated into a form compatible with 6a from the public -// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html - -// +build amd64,gc,!purego - -#define REDMASK51 0x0007FFFFFFFFFFFF - -// These constants cannot be encoded in non-MOVQ immediates. -// We access them directly from memory instead. - -DATA ·_121666_213(SB)/8, $996687872 -GLOBL ·_121666_213(SB), 8, $8 - -DATA ·_2P0(SB)/8, $0xFFFFFFFFFFFDA -GLOBL ·_2P0(SB), 8, $8 - -DATA ·_2P1234(SB)/8, $0xFFFFFFFFFFFFE -GLOBL ·_2P1234(SB), 8, $8 - -// func freeze(inout *[5]uint64) -TEXT ·freeze(SB),7,$0-8 - MOVQ inout+0(FP), DI - - MOVQ 0(DI),SI - MOVQ 8(DI),DX - MOVQ 16(DI),CX - MOVQ 24(DI),R8 - MOVQ 32(DI),R9 - MOVQ $REDMASK51,AX - MOVQ AX,R10 - SUBQ $18,R10 - MOVQ $3,R11 -REDUCELOOP: - MOVQ SI,R12 - SHRQ $51,R12 - ANDQ AX,SI - ADDQ R12,DX - MOVQ DX,R12 - SHRQ $51,R12 - ANDQ AX,DX - ADDQ R12,CX - MOVQ CX,R12 - SHRQ $51,R12 - ANDQ AX,CX - ADDQ R12,R8 - MOVQ R8,R12 - SHRQ $51,R12 - ANDQ AX,R8 - ADDQ R12,R9 - MOVQ R9,R12 - SHRQ $51,R12 - ANDQ AX,R9 - IMUL3Q $19,R12,R12 - ADDQ R12,SI - SUBQ $1,R11 - JA REDUCELOOP - MOVQ $1,R12 - CMPQ R10,SI - CMOVQLT R11,R12 - CMPQ AX,DX - CMOVQNE R11,R12 - CMPQ AX,CX - CMOVQNE R11,R12 - CMPQ AX,R8 - CMOVQNE R11,R12 - CMPQ AX,R9 - CMOVQNE R11,R12 - NEGQ R12 - ANDQ R12,AX - ANDQ R12,R10 - SUBQ R10,SI - SUBQ AX,DX - SUBQ AX,CX - SUBQ AX,R8 - SUBQ AX,R9 - MOVQ SI,0(DI) - MOVQ DX,8(DI) - MOVQ CX,16(DI) - MOVQ R8,24(DI) - MOVQ R9,32(DI) - RET - -// func ladderstep(inout *[5][5]uint64) -TEXT ·ladderstep(SB),0,$296-8 - MOVQ inout+0(FP),DI - - MOVQ 40(DI),SI - MOVQ 48(DI),DX - MOVQ 56(DI),CX - MOVQ 64(DI),R8 - MOVQ 72(DI),R9 - MOVQ SI,AX - MOVQ DX,R10 - MOVQ CX,R11 - MOVQ R8,R12 - MOVQ R9,R13 - ADDQ ·_2P0(SB),AX - ADDQ ·_2P1234(SB),R10 - ADDQ ·_2P1234(SB),R11 - ADDQ ·_2P1234(SB),R12 - ADDQ ·_2P1234(SB),R13 - ADDQ 80(DI),SI - ADDQ 88(DI),DX - ADDQ 96(DI),CX - ADDQ 104(DI),R8 - ADDQ 112(DI),R9 - SUBQ 80(DI),AX - SUBQ 88(DI),R10 - SUBQ 96(DI),R11 - SUBQ 104(DI),R12 - SUBQ 112(DI),R13 - MOVQ SI,0(SP) - MOVQ DX,8(SP) - MOVQ CX,16(SP) - MOVQ R8,24(SP) - MOVQ R9,32(SP) - MOVQ AX,40(SP) - MOVQ R10,48(SP) - MOVQ R11,56(SP) - MOVQ R12,64(SP) - MOVQ R13,72(SP) - MOVQ 40(SP),AX - MULQ 40(SP) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 40(SP),AX - SHLQ $1,AX - MULQ 48(SP) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 40(SP),AX - SHLQ $1,AX - MULQ 56(SP) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 40(SP),AX - SHLQ $1,AX - MULQ 64(SP) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 40(SP),AX - SHLQ $1,AX - MULQ 72(SP) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 48(SP),AX - MULQ 48(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 48(SP),AX - SHLQ $1,AX - MULQ 56(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 48(SP),AX - SHLQ $1,AX - MULQ 64(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 48(SP),DX - IMUL3Q $38,DX,AX - MULQ 72(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 56(SP),AX - MULQ 56(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 56(SP),DX - IMUL3Q $38,DX,AX - MULQ 64(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 56(SP),DX - IMUL3Q $38,DX,AX - MULQ 72(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 64(SP),DX - IMUL3Q $19,DX,AX - MULQ 64(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 64(SP),DX - IMUL3Q $38,DX,AX - MULQ 72(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 72(SP),DX - IMUL3Q $19,DX,AX - MULQ 72(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - ANDQ DX,SI - MOVQ CX,R8 - SHRQ $51,CX - ADDQ R10,CX - ANDQ DX,R8 - MOVQ CX,R9 - SHRQ $51,CX - ADDQ R12,CX - ANDQ DX,R9 - MOVQ CX,AX - SHRQ $51,CX - ADDQ R14,CX - ANDQ DX,AX - MOVQ CX,R10 - SHRQ $51,CX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,80(SP) - MOVQ R8,88(SP) - MOVQ R9,96(SP) - MOVQ AX,104(SP) - MOVQ R10,112(SP) - MOVQ 0(SP),AX - MULQ 0(SP) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 0(SP),AX - SHLQ $1,AX - MULQ 8(SP) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 0(SP),AX - SHLQ $1,AX - MULQ 16(SP) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 0(SP),AX - SHLQ $1,AX - MULQ 24(SP) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 0(SP),AX - SHLQ $1,AX - MULQ 32(SP) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 8(SP),AX - MULQ 8(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 8(SP),AX - SHLQ $1,AX - MULQ 16(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 8(SP),AX - SHLQ $1,AX - MULQ 24(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 8(SP),DX - IMUL3Q $38,DX,AX - MULQ 32(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 16(SP),AX - MULQ 16(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 16(SP),DX - IMUL3Q $38,DX,AX - MULQ 24(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 16(SP),DX - IMUL3Q $38,DX,AX - MULQ 32(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 24(SP),DX - IMUL3Q $19,DX,AX - MULQ 24(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 24(SP),DX - IMUL3Q $38,DX,AX - MULQ 32(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 32(SP),DX - IMUL3Q $19,DX,AX - MULQ 32(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - ANDQ DX,SI - MOVQ CX,R8 - SHRQ $51,CX - ADDQ R10,CX - ANDQ DX,R8 - MOVQ CX,R9 - SHRQ $51,CX - ADDQ R12,CX - ANDQ DX,R9 - MOVQ CX,AX - SHRQ $51,CX - ADDQ R14,CX - ANDQ DX,AX - MOVQ CX,R10 - SHRQ $51,CX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,120(SP) - MOVQ R8,128(SP) - MOVQ R9,136(SP) - MOVQ AX,144(SP) - MOVQ R10,152(SP) - MOVQ SI,SI - MOVQ R8,DX - MOVQ R9,CX - MOVQ AX,R8 - MOVQ R10,R9 - ADDQ ·_2P0(SB),SI - ADDQ ·_2P1234(SB),DX - ADDQ ·_2P1234(SB),CX - ADDQ ·_2P1234(SB),R8 - ADDQ ·_2P1234(SB),R9 - SUBQ 80(SP),SI - SUBQ 88(SP),DX - SUBQ 96(SP),CX - SUBQ 104(SP),R8 - SUBQ 112(SP),R9 - MOVQ SI,160(SP) - MOVQ DX,168(SP) - MOVQ CX,176(SP) - MOVQ R8,184(SP) - MOVQ R9,192(SP) - MOVQ 120(DI),SI - MOVQ 128(DI),DX - MOVQ 136(DI),CX - MOVQ 144(DI),R8 - MOVQ 152(DI),R9 - MOVQ SI,AX - MOVQ DX,R10 - MOVQ CX,R11 - MOVQ R8,R12 - MOVQ R9,R13 - ADDQ ·_2P0(SB),AX - ADDQ ·_2P1234(SB),R10 - ADDQ ·_2P1234(SB),R11 - ADDQ ·_2P1234(SB),R12 - ADDQ ·_2P1234(SB),R13 - ADDQ 160(DI),SI - ADDQ 168(DI),DX - ADDQ 176(DI),CX - ADDQ 184(DI),R8 - ADDQ 192(DI),R9 - SUBQ 160(DI),AX - SUBQ 168(DI),R10 - SUBQ 176(DI),R11 - SUBQ 184(DI),R12 - SUBQ 192(DI),R13 - MOVQ SI,200(SP) - MOVQ DX,208(SP) - MOVQ CX,216(SP) - MOVQ R8,224(SP) - MOVQ R9,232(SP) - MOVQ AX,240(SP) - MOVQ R10,248(SP) - MOVQ R11,256(SP) - MOVQ R12,264(SP) - MOVQ R13,272(SP) - MOVQ 224(SP),SI - IMUL3Q $19,SI,AX - MOVQ AX,280(SP) - MULQ 56(SP) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 232(SP),DX - IMUL3Q $19,DX,AX - MOVQ AX,288(SP) - MULQ 48(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 200(SP),AX - MULQ 40(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 200(SP),AX - MULQ 48(SP) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 200(SP),AX - MULQ 56(SP) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 200(SP),AX - MULQ 64(SP) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 200(SP),AX - MULQ 72(SP) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 208(SP),AX - MULQ 40(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 208(SP),AX - MULQ 48(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 208(SP),AX - MULQ 56(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 208(SP),AX - MULQ 64(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 208(SP),DX - IMUL3Q $19,DX,AX - MULQ 72(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 216(SP),AX - MULQ 40(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 216(SP),AX - MULQ 48(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 216(SP),AX - MULQ 56(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 216(SP),DX - IMUL3Q $19,DX,AX - MULQ 64(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 216(SP),DX - IMUL3Q $19,DX,AX - MULQ 72(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 224(SP),AX - MULQ 40(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 224(SP),AX - MULQ 48(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 280(SP),AX - MULQ 64(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 280(SP),AX - MULQ 72(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 232(SP),AX - MULQ 40(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 288(SP),AX - MULQ 56(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 288(SP),AX - MULQ 64(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 288(SP),AX - MULQ 72(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - MOVQ CX,R8 - SHRQ $51,CX - ANDQ DX,SI - ADDQ R10,CX - MOVQ CX,R9 - SHRQ $51,CX - ANDQ DX,R8 - ADDQ R12,CX - MOVQ CX,AX - SHRQ $51,CX - ANDQ DX,R9 - ADDQ R14,CX - MOVQ CX,R10 - SHRQ $51,CX - ANDQ DX,AX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,40(SP) - MOVQ R8,48(SP) - MOVQ R9,56(SP) - MOVQ AX,64(SP) - MOVQ R10,72(SP) - MOVQ 264(SP),SI - IMUL3Q $19,SI,AX - MOVQ AX,200(SP) - MULQ 16(SP) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 272(SP),DX - IMUL3Q $19,DX,AX - MOVQ AX,208(SP) - MULQ 8(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 240(SP),AX - MULQ 0(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 240(SP),AX - MULQ 8(SP) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 240(SP),AX - MULQ 16(SP) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 240(SP),AX - MULQ 24(SP) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 240(SP),AX - MULQ 32(SP) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 248(SP),AX - MULQ 0(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 248(SP),AX - MULQ 8(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 248(SP),AX - MULQ 16(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 248(SP),AX - MULQ 24(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 248(SP),DX - IMUL3Q $19,DX,AX - MULQ 32(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 256(SP),AX - MULQ 0(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 256(SP),AX - MULQ 8(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 256(SP),AX - MULQ 16(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 256(SP),DX - IMUL3Q $19,DX,AX - MULQ 24(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 256(SP),DX - IMUL3Q $19,DX,AX - MULQ 32(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 264(SP),AX - MULQ 0(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 264(SP),AX - MULQ 8(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 200(SP),AX - MULQ 24(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 200(SP),AX - MULQ 32(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 272(SP),AX - MULQ 0(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 208(SP),AX - MULQ 16(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 208(SP),AX - MULQ 24(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 208(SP),AX - MULQ 32(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - MOVQ CX,R8 - SHRQ $51,CX - ANDQ DX,SI - ADDQ R10,CX - MOVQ CX,R9 - SHRQ $51,CX - ANDQ DX,R8 - ADDQ R12,CX - MOVQ CX,AX - SHRQ $51,CX - ANDQ DX,R9 - ADDQ R14,CX - MOVQ CX,R10 - SHRQ $51,CX - ANDQ DX,AX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,DX - MOVQ R8,CX - MOVQ R9,R11 - MOVQ AX,R12 - MOVQ R10,R13 - ADDQ ·_2P0(SB),DX - ADDQ ·_2P1234(SB),CX - ADDQ ·_2P1234(SB),R11 - ADDQ ·_2P1234(SB),R12 - ADDQ ·_2P1234(SB),R13 - ADDQ 40(SP),SI - ADDQ 48(SP),R8 - ADDQ 56(SP),R9 - ADDQ 64(SP),AX - ADDQ 72(SP),R10 - SUBQ 40(SP),DX - SUBQ 48(SP),CX - SUBQ 56(SP),R11 - SUBQ 64(SP),R12 - SUBQ 72(SP),R13 - MOVQ SI,120(DI) - MOVQ R8,128(DI) - MOVQ R9,136(DI) - MOVQ AX,144(DI) - MOVQ R10,152(DI) - MOVQ DX,160(DI) - MOVQ CX,168(DI) - MOVQ R11,176(DI) - MOVQ R12,184(DI) - MOVQ R13,192(DI) - MOVQ 120(DI),AX - MULQ 120(DI) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 120(DI),AX - SHLQ $1,AX - MULQ 128(DI) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 120(DI),AX - SHLQ $1,AX - MULQ 136(DI) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 120(DI),AX - SHLQ $1,AX - MULQ 144(DI) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 120(DI),AX - SHLQ $1,AX - MULQ 152(DI) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 128(DI),AX - MULQ 128(DI) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 128(DI),AX - SHLQ $1,AX - MULQ 136(DI) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 128(DI),AX - SHLQ $1,AX - MULQ 144(DI) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 128(DI),DX - IMUL3Q $38,DX,AX - MULQ 152(DI) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 136(DI),AX - MULQ 136(DI) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 136(DI),DX - IMUL3Q $38,DX,AX - MULQ 144(DI) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 136(DI),DX - IMUL3Q $38,DX,AX - MULQ 152(DI) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 144(DI),DX - IMUL3Q $19,DX,AX - MULQ 144(DI) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 144(DI),DX - IMUL3Q $38,DX,AX - MULQ 152(DI) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 152(DI),DX - IMUL3Q $19,DX,AX - MULQ 152(DI) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - ANDQ DX,SI - MOVQ CX,R8 - SHRQ $51,CX - ADDQ R10,CX - ANDQ DX,R8 - MOVQ CX,R9 - SHRQ $51,CX - ADDQ R12,CX - ANDQ DX,R9 - MOVQ CX,AX - SHRQ $51,CX - ADDQ R14,CX - ANDQ DX,AX - MOVQ CX,R10 - SHRQ $51,CX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,120(DI) - MOVQ R8,128(DI) - MOVQ R9,136(DI) - MOVQ AX,144(DI) - MOVQ R10,152(DI) - MOVQ 160(DI),AX - MULQ 160(DI) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 160(DI),AX - SHLQ $1,AX - MULQ 168(DI) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 160(DI),AX - SHLQ $1,AX - MULQ 176(DI) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 160(DI),AX - SHLQ $1,AX - MULQ 184(DI) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 160(DI),AX - SHLQ $1,AX - MULQ 192(DI) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 168(DI),AX - MULQ 168(DI) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 168(DI),AX - SHLQ $1,AX - MULQ 176(DI) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 168(DI),AX - SHLQ $1,AX - MULQ 184(DI) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 168(DI),DX - IMUL3Q $38,DX,AX - MULQ 192(DI) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 176(DI),AX - MULQ 176(DI) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 176(DI),DX - IMUL3Q $38,DX,AX - MULQ 184(DI) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 176(DI),DX - IMUL3Q $38,DX,AX - MULQ 192(DI) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 184(DI),DX - IMUL3Q $19,DX,AX - MULQ 184(DI) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 184(DI),DX - IMUL3Q $38,DX,AX - MULQ 192(DI) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 192(DI),DX - IMUL3Q $19,DX,AX - MULQ 192(DI) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - ANDQ DX,SI - MOVQ CX,R8 - SHRQ $51,CX - ADDQ R10,CX - ANDQ DX,R8 - MOVQ CX,R9 - SHRQ $51,CX - ADDQ R12,CX - ANDQ DX,R9 - MOVQ CX,AX - SHRQ $51,CX - ADDQ R14,CX - ANDQ DX,AX - MOVQ CX,R10 - SHRQ $51,CX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,160(DI) - MOVQ R8,168(DI) - MOVQ R9,176(DI) - MOVQ AX,184(DI) - MOVQ R10,192(DI) - MOVQ 184(DI),SI - IMUL3Q $19,SI,AX - MOVQ AX,0(SP) - MULQ 16(DI) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 192(DI),DX - IMUL3Q $19,DX,AX - MOVQ AX,8(SP) - MULQ 8(DI) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 160(DI),AX - MULQ 0(DI) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 160(DI),AX - MULQ 8(DI) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 160(DI),AX - MULQ 16(DI) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 160(DI),AX - MULQ 24(DI) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 160(DI),AX - MULQ 32(DI) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 168(DI),AX - MULQ 0(DI) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 168(DI),AX - MULQ 8(DI) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 168(DI),AX - MULQ 16(DI) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 168(DI),AX - MULQ 24(DI) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 168(DI),DX - IMUL3Q $19,DX,AX - MULQ 32(DI) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 176(DI),AX - MULQ 0(DI) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 176(DI),AX - MULQ 8(DI) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 176(DI),AX - MULQ 16(DI) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 176(DI),DX - IMUL3Q $19,DX,AX - MULQ 24(DI) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 176(DI),DX - IMUL3Q $19,DX,AX - MULQ 32(DI) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 184(DI),AX - MULQ 0(DI) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 184(DI),AX - MULQ 8(DI) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 0(SP),AX - MULQ 24(DI) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 0(SP),AX - MULQ 32(DI) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 192(DI),AX - MULQ 0(DI) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 8(SP),AX - MULQ 16(DI) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 8(SP),AX - MULQ 24(DI) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 8(SP),AX - MULQ 32(DI) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - MOVQ CX,R8 - SHRQ $51,CX - ANDQ DX,SI - ADDQ R10,CX - MOVQ CX,R9 - SHRQ $51,CX - ANDQ DX,R8 - ADDQ R12,CX - MOVQ CX,AX - SHRQ $51,CX - ANDQ DX,R9 - ADDQ R14,CX - MOVQ CX,R10 - SHRQ $51,CX - ANDQ DX,AX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,160(DI) - MOVQ R8,168(DI) - MOVQ R9,176(DI) - MOVQ AX,184(DI) - MOVQ R10,192(DI) - MOVQ 144(SP),SI - IMUL3Q $19,SI,AX - MOVQ AX,0(SP) - MULQ 96(SP) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 152(SP),DX - IMUL3Q $19,DX,AX - MOVQ AX,8(SP) - MULQ 88(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 120(SP),AX - MULQ 80(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 120(SP),AX - MULQ 88(SP) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 120(SP),AX - MULQ 96(SP) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 120(SP),AX - MULQ 104(SP) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 120(SP),AX - MULQ 112(SP) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 128(SP),AX - MULQ 80(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 128(SP),AX - MULQ 88(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 128(SP),AX - MULQ 96(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 128(SP),AX - MULQ 104(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 128(SP),DX - IMUL3Q $19,DX,AX - MULQ 112(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 136(SP),AX - MULQ 80(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 136(SP),AX - MULQ 88(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 136(SP),AX - MULQ 96(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 136(SP),DX - IMUL3Q $19,DX,AX - MULQ 104(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 136(SP),DX - IMUL3Q $19,DX,AX - MULQ 112(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 144(SP),AX - MULQ 80(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 144(SP),AX - MULQ 88(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 0(SP),AX - MULQ 104(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 0(SP),AX - MULQ 112(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 152(SP),AX - MULQ 80(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 8(SP),AX - MULQ 96(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 8(SP),AX - MULQ 104(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 8(SP),AX - MULQ 112(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - MOVQ CX,R8 - SHRQ $51,CX - ANDQ DX,SI - ADDQ R10,CX - MOVQ CX,R9 - SHRQ $51,CX - ANDQ DX,R8 - ADDQ R12,CX - MOVQ CX,AX - SHRQ $51,CX - ANDQ DX,R9 - ADDQ R14,CX - MOVQ CX,R10 - SHRQ $51,CX - ANDQ DX,AX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,40(DI) - MOVQ R8,48(DI) - MOVQ R9,56(DI) - MOVQ AX,64(DI) - MOVQ R10,72(DI) - MOVQ 160(SP),AX - MULQ ·_121666_213(SB) - SHRQ $13,AX - MOVQ AX,SI - MOVQ DX,CX - MOVQ 168(SP),AX - MULQ ·_121666_213(SB) - SHRQ $13,AX - ADDQ AX,CX - MOVQ DX,R8 - MOVQ 176(SP),AX - MULQ ·_121666_213(SB) - SHRQ $13,AX - ADDQ AX,R8 - MOVQ DX,R9 - MOVQ 184(SP),AX - MULQ ·_121666_213(SB) - SHRQ $13,AX - ADDQ AX,R9 - MOVQ DX,R10 - MOVQ 192(SP),AX - MULQ ·_121666_213(SB) - SHRQ $13,AX - ADDQ AX,R10 - IMUL3Q $19,DX,DX - ADDQ DX,SI - ADDQ 80(SP),SI - ADDQ 88(SP),CX - ADDQ 96(SP),R8 - ADDQ 104(SP),R9 - ADDQ 112(SP),R10 - MOVQ SI,80(DI) - MOVQ CX,88(DI) - MOVQ R8,96(DI) - MOVQ R9,104(DI) - MOVQ R10,112(DI) - MOVQ 104(DI),SI - IMUL3Q $19,SI,AX - MOVQ AX,0(SP) - MULQ 176(SP) - MOVQ AX,SI - MOVQ DX,CX - MOVQ 112(DI),DX - IMUL3Q $19,DX,AX - MOVQ AX,8(SP) - MULQ 168(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 80(DI),AX - MULQ 160(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 80(DI),AX - MULQ 168(SP) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 80(DI),AX - MULQ 176(SP) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 80(DI),AX - MULQ 184(SP) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 80(DI),AX - MULQ 192(SP) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 88(DI),AX - MULQ 160(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 88(DI),AX - MULQ 168(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 88(DI),AX - MULQ 176(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 88(DI),AX - MULQ 184(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 88(DI),DX - IMUL3Q $19,DX,AX - MULQ 192(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 96(DI),AX - MULQ 160(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 96(DI),AX - MULQ 168(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 96(DI),AX - MULQ 176(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 96(DI),DX - IMUL3Q $19,DX,AX - MULQ 184(SP) - ADDQ AX,SI - ADCQ DX,CX - MOVQ 96(DI),DX - IMUL3Q $19,DX,AX - MULQ 192(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 104(DI),AX - MULQ 160(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 104(DI),AX - MULQ 168(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 0(SP),AX - MULQ 184(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 0(SP),AX - MULQ 192(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 112(DI),AX - MULQ 160(SP) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 8(SP),AX - MULQ 176(SP) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 8(SP),AX - MULQ 184(SP) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 8(SP),AX - MULQ 192(SP) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ $REDMASK51,DX - SHLQ $13,SI,CX - ANDQ DX,SI - SHLQ $13,R8,R9 - ANDQ DX,R8 - ADDQ CX,R8 - SHLQ $13,R10,R11 - ANDQ DX,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ DX,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ DX,R14 - ADDQ R13,R14 - IMUL3Q $19,R15,CX - ADDQ CX,SI - MOVQ SI,CX - SHRQ $51,CX - ADDQ R8,CX - MOVQ CX,R8 - SHRQ $51,CX - ANDQ DX,SI - ADDQ R10,CX - MOVQ CX,R9 - SHRQ $51,CX - ANDQ DX,R8 - ADDQ R12,CX - MOVQ CX,AX - SHRQ $51,CX - ANDQ DX,R9 - ADDQ R14,CX - MOVQ CX,R10 - SHRQ $51,CX - ANDQ DX,AX - IMUL3Q $19,CX,CX - ADDQ CX,SI - ANDQ DX,R10 - MOVQ SI,80(DI) - MOVQ R8,88(DI) - MOVQ R9,96(DI) - MOVQ AX,104(DI) - MOVQ R10,112(DI) - RET - -// func cswap(inout *[4][5]uint64, v uint64) -TEXT ·cswap(SB),7,$0 - MOVQ inout+0(FP),DI - MOVQ v+8(FP),SI - - SUBQ $1, SI - NOTQ SI - MOVQ SI, X15 - PSHUFD $0x44, X15, X15 - - MOVOU 0(DI), X0 - MOVOU 16(DI), X2 - MOVOU 32(DI), X4 - MOVOU 48(DI), X6 - MOVOU 64(DI), X8 - MOVOU 80(DI), X1 - MOVOU 96(DI), X3 - MOVOU 112(DI), X5 - MOVOU 128(DI), X7 - MOVOU 144(DI), X9 - - MOVO X1, X10 - MOVO X3, X11 - MOVO X5, X12 - MOVO X7, X13 - MOVO X9, X14 - - PXOR X0, X10 - PXOR X2, X11 - PXOR X4, X12 - PXOR X6, X13 - PXOR X8, X14 - PAND X15, X10 - PAND X15, X11 - PAND X15, X12 - PAND X15, X13 - PAND X15, X14 - PXOR X10, X0 - PXOR X10, X1 - PXOR X11, X2 - PXOR X11, X3 - PXOR X12, X4 - PXOR X12, X5 - PXOR X13, X6 - PXOR X13, X7 - PXOR X14, X8 - PXOR X14, X9 - - MOVOU X0, 0(DI) - MOVOU X2, 16(DI) - MOVOU X4, 32(DI) - MOVOU X6, 48(DI) - MOVOU X8, 64(DI) - MOVOU X1, 80(DI) - MOVOU X3, 96(DI) - MOVOU X5, 112(DI) - MOVOU X7, 128(DI) - MOVOU X9, 144(DI) - RET - -// func mul(dest, a, b *[5]uint64) -TEXT ·mul(SB),0,$16-24 - MOVQ dest+0(FP), DI - MOVQ a+8(FP), SI - MOVQ b+16(FP), DX - - MOVQ DX,CX - MOVQ 24(SI),DX - IMUL3Q $19,DX,AX - MOVQ AX,0(SP) - MULQ 16(CX) - MOVQ AX,R8 - MOVQ DX,R9 - MOVQ 32(SI),DX - IMUL3Q $19,DX,AX - MOVQ AX,8(SP) - MULQ 8(CX) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 0(SI),AX - MULQ 0(CX) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 0(SI),AX - MULQ 8(CX) - MOVQ AX,R10 - MOVQ DX,R11 - MOVQ 0(SI),AX - MULQ 16(CX) - MOVQ AX,R12 - MOVQ DX,R13 - MOVQ 0(SI),AX - MULQ 24(CX) - MOVQ AX,R14 - MOVQ DX,R15 - MOVQ 0(SI),AX - MULQ 32(CX) - MOVQ AX,BX - MOVQ DX,BP - MOVQ 8(SI),AX - MULQ 0(CX) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 8(SI),AX - MULQ 8(CX) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 8(SI),AX - MULQ 16(CX) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 8(SI),AX - MULQ 24(CX) - ADDQ AX,BX - ADCQ DX,BP - MOVQ 8(SI),DX - IMUL3Q $19,DX,AX - MULQ 32(CX) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 16(SI),AX - MULQ 0(CX) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 16(SI),AX - MULQ 8(CX) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 16(SI),AX - MULQ 16(CX) - ADDQ AX,BX - ADCQ DX,BP - MOVQ 16(SI),DX - IMUL3Q $19,DX,AX - MULQ 24(CX) - ADDQ AX,R8 - ADCQ DX,R9 - MOVQ 16(SI),DX - IMUL3Q $19,DX,AX - MULQ 32(CX) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 24(SI),AX - MULQ 0(CX) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ 24(SI),AX - MULQ 8(CX) - ADDQ AX,BX - ADCQ DX,BP - MOVQ 0(SP),AX - MULQ 24(CX) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 0(SP),AX - MULQ 32(CX) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 32(SI),AX - MULQ 0(CX) - ADDQ AX,BX - ADCQ DX,BP - MOVQ 8(SP),AX - MULQ 16(CX) - ADDQ AX,R10 - ADCQ DX,R11 - MOVQ 8(SP),AX - MULQ 24(CX) - ADDQ AX,R12 - ADCQ DX,R13 - MOVQ 8(SP),AX - MULQ 32(CX) - ADDQ AX,R14 - ADCQ DX,R15 - MOVQ $REDMASK51,SI - SHLQ $13,R8,R9 - ANDQ SI,R8 - SHLQ $13,R10,R11 - ANDQ SI,R10 - ADDQ R9,R10 - SHLQ $13,R12,R13 - ANDQ SI,R12 - ADDQ R11,R12 - SHLQ $13,R14,R15 - ANDQ SI,R14 - ADDQ R13,R14 - SHLQ $13,BX,BP - ANDQ SI,BX - ADDQ R15,BX - IMUL3Q $19,BP,DX - ADDQ DX,R8 - MOVQ R8,DX - SHRQ $51,DX - ADDQ R10,DX - MOVQ DX,CX - SHRQ $51,DX - ANDQ SI,R8 - ADDQ R12,DX - MOVQ DX,R9 - SHRQ $51,DX - ANDQ SI,CX - ADDQ R14,DX - MOVQ DX,AX - SHRQ $51,DX - ANDQ SI,R9 - ADDQ BX,DX - MOVQ DX,R10 - SHRQ $51,DX - ANDQ SI,AX - IMUL3Q $19,DX,DX - ADDQ DX,R8 - ANDQ SI,R10 - MOVQ R8,0(DI) - MOVQ CX,8(DI) - MOVQ R9,16(DI) - MOVQ AX,24(DI) - MOVQ R10,32(DI) - RET - -// func square(out, in *[5]uint64) -TEXT ·square(SB),7,$0-16 - MOVQ out+0(FP), DI - MOVQ in+8(FP), SI - - MOVQ 0(SI),AX - MULQ 0(SI) - MOVQ AX,CX - MOVQ DX,R8 - MOVQ 0(SI),AX - SHLQ $1,AX - MULQ 8(SI) - MOVQ AX,R9 - MOVQ DX,R10 - MOVQ 0(SI),AX - SHLQ $1,AX - MULQ 16(SI) - MOVQ AX,R11 - MOVQ DX,R12 - MOVQ 0(SI),AX - SHLQ $1,AX - MULQ 24(SI) - MOVQ AX,R13 - MOVQ DX,R14 - MOVQ 0(SI),AX - SHLQ $1,AX - MULQ 32(SI) - MOVQ AX,R15 - MOVQ DX,BX - MOVQ 8(SI),AX - MULQ 8(SI) - ADDQ AX,R11 - ADCQ DX,R12 - MOVQ 8(SI),AX - SHLQ $1,AX - MULQ 16(SI) - ADDQ AX,R13 - ADCQ DX,R14 - MOVQ 8(SI),AX - SHLQ $1,AX - MULQ 24(SI) - ADDQ AX,R15 - ADCQ DX,BX - MOVQ 8(SI),DX - IMUL3Q $38,DX,AX - MULQ 32(SI) - ADDQ AX,CX - ADCQ DX,R8 - MOVQ 16(SI),AX - MULQ 16(SI) - ADDQ AX,R15 - ADCQ DX,BX - MOVQ 16(SI),DX - IMUL3Q $38,DX,AX - MULQ 24(SI) - ADDQ AX,CX - ADCQ DX,R8 - MOVQ 16(SI),DX - IMUL3Q $38,DX,AX - MULQ 32(SI) - ADDQ AX,R9 - ADCQ DX,R10 - MOVQ 24(SI),DX - IMUL3Q $19,DX,AX - MULQ 24(SI) - ADDQ AX,R9 - ADCQ DX,R10 - MOVQ 24(SI),DX - IMUL3Q $38,DX,AX - MULQ 32(SI) - ADDQ AX,R11 - ADCQ DX,R12 - MOVQ 32(SI),DX - IMUL3Q $19,DX,AX - MULQ 32(SI) - ADDQ AX,R13 - ADCQ DX,R14 - MOVQ $REDMASK51,SI - SHLQ $13,CX,R8 - ANDQ SI,CX - SHLQ $13,R9,R10 - ANDQ SI,R9 - ADDQ R8,R9 - SHLQ $13,R11,R12 - ANDQ SI,R11 - ADDQ R10,R11 - SHLQ $13,R13,R14 - ANDQ SI,R13 - ADDQ R12,R13 - SHLQ $13,R15,BX - ANDQ SI,R15 - ADDQ R14,R15 - IMUL3Q $19,BX,DX - ADDQ DX,CX - MOVQ CX,DX - SHRQ $51,DX - ADDQ R9,DX - ANDQ SI,CX - MOVQ DX,R8 - SHRQ $51,DX - ADDQ R11,DX - ANDQ SI,R8 - MOVQ DX,R9 - SHRQ $51,DX - ADDQ R13,DX - ANDQ SI,R9 - MOVQ DX,AX - SHRQ $51,DX - ADDQ R15,DX - ANDQ SI,AX - MOVQ DX,R10 - SHRQ $51,DX - IMUL3Q $19,DX,DX - ADDQ DX,CX - ANDQ SI,R10 - MOVQ CX,0(DI) - MOVQ R8,8(DI) - MOVQ R9,16(DI) - MOVQ AX,24(DI) - MOVQ R10,32(DI) - RET diff --git a/src/vendor/golang.org/x/crypto/curve25519/curve25519_generic.go b/src/vendor/golang.org/x/crypto/curve25519/curve25519_generic.go deleted file mode 100644 index c43b13fc83..0000000000 --- a/src/vendor/golang.org/x/crypto/curve25519/curve25519_generic.go +++ /dev/null @@ -1,828 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package curve25519 - -import "encoding/binary" - -// This code is a port of the public domain, "ref10" implementation of -// curve25519 from SUPERCOP 20130419 by D. J. Bernstein. - -// fieldElement represents an element of the field GF(2^255 - 19). An element -// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77 -// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on -// context. -type fieldElement [10]int32 - -func feZero(fe *fieldElement) { - for i := range fe { - fe[i] = 0 - } -} - -func feOne(fe *fieldElement) { - feZero(fe) - fe[0] = 1 -} - -func feAdd(dst, a, b *fieldElement) { - for i := range dst { - dst[i] = a[i] + b[i] - } -} - -func feSub(dst, a, b *fieldElement) { - for i := range dst { - dst[i] = a[i] - b[i] - } -} - -func feCopy(dst, src *fieldElement) { - for i := range dst { - dst[i] = src[i] - } -} - -// feCSwap replaces (f,g) with (g,f) if b == 1; replaces (f,g) with (f,g) if b == 0. -// -// Preconditions: b in {0,1}. -func feCSwap(f, g *fieldElement, b int32) { - b = -b - for i := range f { - t := b & (f[i] ^ g[i]) - f[i] ^= t - g[i] ^= t - } -} - -// load3 reads a 24-bit, little-endian value from in. -func load3(in []byte) int64 { - var r int64 - r = int64(in[0]) - r |= int64(in[1]) << 8 - r |= int64(in[2]) << 16 - return r -} - -// load4 reads a 32-bit, little-endian value from in. -func load4(in []byte) int64 { - return int64(binary.LittleEndian.Uint32(in)) -} - -func feFromBytes(dst *fieldElement, src *[32]byte) { - h0 := load4(src[:]) - h1 := load3(src[4:]) << 6 - h2 := load3(src[7:]) << 5 - h3 := load3(src[10:]) << 3 - h4 := load3(src[13:]) << 2 - h5 := load4(src[16:]) - h6 := load3(src[20:]) << 7 - h7 := load3(src[23:]) << 5 - h8 := load3(src[26:]) << 4 - h9 := (load3(src[29:]) & 0x7fffff) << 2 - - var carry [10]int64 - carry[9] = (h9 + 1<<24) >> 25 - h0 += carry[9] * 19 - h9 -= carry[9] << 25 - carry[1] = (h1 + 1<<24) >> 25 - h2 += carry[1] - h1 -= carry[1] << 25 - carry[3] = (h3 + 1<<24) >> 25 - h4 += carry[3] - h3 -= carry[3] << 25 - carry[5] = (h5 + 1<<24) >> 25 - h6 += carry[5] - h5 -= carry[5] << 25 - carry[7] = (h7 + 1<<24) >> 25 - h8 += carry[7] - h7 -= carry[7] << 25 - - carry[0] = (h0 + 1<<25) >> 26 - h1 += carry[0] - h0 -= carry[0] << 26 - carry[2] = (h2 + 1<<25) >> 26 - h3 += carry[2] - h2 -= carry[2] << 26 - carry[4] = (h4 + 1<<25) >> 26 - h5 += carry[4] - h4 -= carry[4] << 26 - carry[6] = (h6 + 1<<25) >> 26 - h7 += carry[6] - h6 -= carry[6] << 26 - carry[8] = (h8 + 1<<25) >> 26 - h9 += carry[8] - h8 -= carry[8] << 26 - - dst[0] = int32(h0) - dst[1] = int32(h1) - dst[2] = int32(h2) - dst[3] = int32(h3) - dst[4] = int32(h4) - dst[5] = int32(h5) - dst[6] = int32(h6) - dst[7] = int32(h7) - dst[8] = int32(h8) - dst[9] = int32(h9) -} - -// feToBytes marshals h to s. -// Preconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -// -// Write p=2^255-19; q=floor(h/p). -// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). -// -// Proof: -// Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. -// Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4. -// -// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). -// Then 0> 25 - q = (h[0] + q) >> 26 - q = (h[1] + q) >> 25 - q = (h[2] + q) >> 26 - q = (h[3] + q) >> 25 - q = (h[4] + q) >> 26 - q = (h[5] + q) >> 25 - q = (h[6] + q) >> 26 - q = (h[7] + q) >> 25 - q = (h[8] + q) >> 26 - q = (h[9] + q) >> 25 - - // Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. - h[0] += 19 * q - // Goal: Output h-2^255 q, which is between 0 and 2^255-20. - - carry[0] = h[0] >> 26 - h[1] += carry[0] - h[0] -= carry[0] << 26 - carry[1] = h[1] >> 25 - h[2] += carry[1] - h[1] -= carry[1] << 25 - carry[2] = h[2] >> 26 - h[3] += carry[2] - h[2] -= carry[2] << 26 - carry[3] = h[3] >> 25 - h[4] += carry[3] - h[3] -= carry[3] << 25 - carry[4] = h[4] >> 26 - h[5] += carry[4] - h[4] -= carry[4] << 26 - carry[5] = h[5] >> 25 - h[6] += carry[5] - h[5] -= carry[5] << 25 - carry[6] = h[6] >> 26 - h[7] += carry[6] - h[6] -= carry[6] << 26 - carry[7] = h[7] >> 25 - h[8] += carry[7] - h[7] -= carry[7] << 25 - carry[8] = h[8] >> 26 - h[9] += carry[8] - h[8] -= carry[8] << 26 - carry[9] = h[9] >> 25 - h[9] -= carry[9] << 25 - // h10 = carry9 - - // Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. - // Have h[0]+...+2^230 h[9] between 0 and 2^255-1; - // evidently 2^255 h10-2^255 q = 0. - // Goal: Output h[0]+...+2^230 h[9]. - - s[0] = byte(h[0] >> 0) - s[1] = byte(h[0] >> 8) - s[2] = byte(h[0] >> 16) - s[3] = byte((h[0] >> 24) | (h[1] << 2)) - s[4] = byte(h[1] >> 6) - s[5] = byte(h[1] >> 14) - s[6] = byte((h[1] >> 22) | (h[2] << 3)) - s[7] = byte(h[2] >> 5) - s[8] = byte(h[2] >> 13) - s[9] = byte((h[2] >> 21) | (h[3] << 5)) - s[10] = byte(h[3] >> 3) - s[11] = byte(h[3] >> 11) - s[12] = byte((h[3] >> 19) | (h[4] << 6)) - s[13] = byte(h[4] >> 2) - s[14] = byte(h[4] >> 10) - s[15] = byte(h[4] >> 18) - s[16] = byte(h[5] >> 0) - s[17] = byte(h[5] >> 8) - s[18] = byte(h[5] >> 16) - s[19] = byte((h[5] >> 24) | (h[6] << 1)) - s[20] = byte(h[6] >> 7) - s[21] = byte(h[6] >> 15) - s[22] = byte((h[6] >> 23) | (h[7] << 3)) - s[23] = byte(h[7] >> 5) - s[24] = byte(h[7] >> 13) - s[25] = byte((h[7] >> 21) | (h[8] << 4)) - s[26] = byte(h[8] >> 4) - s[27] = byte(h[8] >> 12) - s[28] = byte((h[8] >> 20) | (h[9] << 6)) - s[29] = byte(h[9] >> 2) - s[30] = byte(h[9] >> 10) - s[31] = byte(h[9] >> 18) -} - -// feMul calculates h = f * g -// Can overlap h with f or g. -// -// Preconditions: -// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -// |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -// -// Postconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -// -// Notes on implementation strategy: -// -// Using schoolbook multiplication. -// Karatsuba would save a little in some cost models. -// -// Most multiplications by 2 and 19 are 32-bit precomputations; -// cheaper than 64-bit postcomputations. -// -// There is one remaining multiplication by 19 in the carry chain; -// one *19 precomputation can be merged into this, -// but the resulting data flow is considerably less clean. -// -// There are 12 carries below. -// 10 of them are 2-way parallelizable and vectorizable. -// Can get away with 11 carries, but then data flow is much deeper. -// -// With tighter constraints on inputs can squeeze carries into int32. -func feMul(h, f, g *fieldElement) { - f0 := f[0] - f1 := f[1] - f2 := f[2] - f3 := f[3] - f4 := f[4] - f5 := f[5] - f6 := f[6] - f7 := f[7] - f8 := f[8] - f9 := f[9] - g0 := g[0] - g1 := g[1] - g2 := g[2] - g3 := g[3] - g4 := g[4] - g5 := g[5] - g6 := g[6] - g7 := g[7] - g8 := g[8] - g9 := g[9] - g1_19 := 19 * g1 // 1.4*2^29 - g2_19 := 19 * g2 // 1.4*2^30; still ok - g3_19 := 19 * g3 - g4_19 := 19 * g4 - g5_19 := 19 * g5 - g6_19 := 19 * g6 - g7_19 := 19 * g7 - g8_19 := 19 * g8 - g9_19 := 19 * g9 - f1_2 := 2 * f1 - f3_2 := 2 * f3 - f5_2 := 2 * f5 - f7_2 := 2 * f7 - f9_2 := 2 * f9 - f0g0 := int64(f0) * int64(g0) - f0g1 := int64(f0) * int64(g1) - f0g2 := int64(f0) * int64(g2) - f0g3 := int64(f0) * int64(g3) - f0g4 := int64(f0) * int64(g4) - f0g5 := int64(f0) * int64(g5) - f0g6 := int64(f0) * int64(g6) - f0g7 := int64(f0) * int64(g7) - f0g8 := int64(f0) * int64(g8) - f0g9 := int64(f0) * int64(g9) - f1g0 := int64(f1) * int64(g0) - f1g1_2 := int64(f1_2) * int64(g1) - f1g2 := int64(f1) * int64(g2) - f1g3_2 := int64(f1_2) * int64(g3) - f1g4 := int64(f1) * int64(g4) - f1g5_2 := int64(f1_2) * int64(g5) - f1g6 := int64(f1) * int64(g6) - f1g7_2 := int64(f1_2) * int64(g7) - f1g8 := int64(f1) * int64(g8) - f1g9_38 := int64(f1_2) * int64(g9_19) - f2g0 := int64(f2) * int64(g0) - f2g1 := int64(f2) * int64(g1) - f2g2 := int64(f2) * int64(g2) - f2g3 := int64(f2) * int64(g3) - f2g4 := int64(f2) * int64(g4) - f2g5 := int64(f2) * int64(g5) - f2g6 := int64(f2) * int64(g6) - f2g7 := int64(f2) * int64(g7) - f2g8_19 := int64(f2) * int64(g8_19) - f2g9_19 := int64(f2) * int64(g9_19) - f3g0 := int64(f3) * int64(g0) - f3g1_2 := int64(f3_2) * int64(g1) - f3g2 := int64(f3) * int64(g2) - f3g3_2 := int64(f3_2) * int64(g3) - f3g4 := int64(f3) * int64(g4) - f3g5_2 := int64(f3_2) * int64(g5) - f3g6 := int64(f3) * int64(g6) - f3g7_38 := int64(f3_2) * int64(g7_19) - f3g8_19 := int64(f3) * int64(g8_19) - f3g9_38 := int64(f3_2) * int64(g9_19) - f4g0 := int64(f4) * int64(g0) - f4g1 := int64(f4) * int64(g1) - f4g2 := int64(f4) * int64(g2) - f4g3 := int64(f4) * int64(g3) - f4g4 := int64(f4) * int64(g4) - f4g5 := int64(f4) * int64(g5) - f4g6_19 := int64(f4) * int64(g6_19) - f4g7_19 := int64(f4) * int64(g7_19) - f4g8_19 := int64(f4) * int64(g8_19) - f4g9_19 := int64(f4) * int64(g9_19) - f5g0 := int64(f5) * int64(g0) - f5g1_2 := int64(f5_2) * int64(g1) - f5g2 := int64(f5) * int64(g2) - f5g3_2 := int64(f5_2) * int64(g3) - f5g4 := int64(f5) * int64(g4) - f5g5_38 := int64(f5_2) * int64(g5_19) - f5g6_19 := int64(f5) * int64(g6_19) - f5g7_38 := int64(f5_2) * int64(g7_19) - f5g8_19 := int64(f5) * int64(g8_19) - f5g9_38 := int64(f5_2) * int64(g9_19) - f6g0 := int64(f6) * int64(g0) - f6g1 := int64(f6) * int64(g1) - f6g2 := int64(f6) * int64(g2) - f6g3 := int64(f6) * int64(g3) - f6g4_19 := int64(f6) * int64(g4_19) - f6g5_19 := int64(f6) * int64(g5_19) - f6g6_19 := int64(f6) * int64(g6_19) - f6g7_19 := int64(f6) * int64(g7_19) - f6g8_19 := int64(f6) * int64(g8_19) - f6g9_19 := int64(f6) * int64(g9_19) - f7g0 := int64(f7) * int64(g0) - f7g1_2 := int64(f7_2) * int64(g1) - f7g2 := int64(f7) * int64(g2) - f7g3_38 := int64(f7_2) * int64(g3_19) - f7g4_19 := int64(f7) * int64(g4_19) - f7g5_38 := int64(f7_2) * int64(g5_19) - f7g6_19 := int64(f7) * int64(g6_19) - f7g7_38 := int64(f7_2) * int64(g7_19) - f7g8_19 := int64(f7) * int64(g8_19) - f7g9_38 := int64(f7_2) * int64(g9_19) - f8g0 := int64(f8) * int64(g0) - f8g1 := int64(f8) * int64(g1) - f8g2_19 := int64(f8) * int64(g2_19) - f8g3_19 := int64(f8) * int64(g3_19) - f8g4_19 := int64(f8) * int64(g4_19) - f8g5_19 := int64(f8) * int64(g5_19) - f8g6_19 := int64(f8) * int64(g6_19) - f8g7_19 := int64(f8) * int64(g7_19) - f8g8_19 := int64(f8) * int64(g8_19) - f8g9_19 := int64(f8) * int64(g9_19) - f9g0 := int64(f9) * int64(g0) - f9g1_38 := int64(f9_2) * int64(g1_19) - f9g2_19 := int64(f9) * int64(g2_19) - f9g3_38 := int64(f9_2) * int64(g3_19) - f9g4_19 := int64(f9) * int64(g4_19) - f9g5_38 := int64(f9_2) * int64(g5_19) - f9g6_19 := int64(f9) * int64(g6_19) - f9g7_38 := int64(f9_2) * int64(g7_19) - f9g8_19 := int64(f9) * int64(g8_19) - f9g9_38 := int64(f9_2) * int64(g9_19) - h0 := f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38 - h1 := f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19 - h2 := f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38 - h3 := f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19 - h4 := f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38 - h5 := f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19 - h6 := f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38 - h7 := f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19 - h8 := f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38 - h9 := f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0 - var carry [10]int64 - - // |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38)) - // i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8 - // |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19)) - // i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9 - - carry[0] = (h0 + (1 << 25)) >> 26 - h1 += carry[0] - h0 -= carry[0] << 26 - carry[4] = (h4 + (1 << 25)) >> 26 - h5 += carry[4] - h4 -= carry[4] << 26 - // |h0| <= 2^25 - // |h4| <= 2^25 - // |h1| <= 1.51*2^58 - // |h5| <= 1.51*2^58 - - carry[1] = (h1 + (1 << 24)) >> 25 - h2 += carry[1] - h1 -= carry[1] << 25 - carry[5] = (h5 + (1 << 24)) >> 25 - h6 += carry[5] - h5 -= carry[5] << 25 - // |h1| <= 2^24; from now on fits into int32 - // |h5| <= 2^24; from now on fits into int32 - // |h2| <= 1.21*2^59 - // |h6| <= 1.21*2^59 - - carry[2] = (h2 + (1 << 25)) >> 26 - h3 += carry[2] - h2 -= carry[2] << 26 - carry[6] = (h6 + (1 << 25)) >> 26 - h7 += carry[6] - h6 -= carry[6] << 26 - // |h2| <= 2^25; from now on fits into int32 unchanged - // |h6| <= 2^25; from now on fits into int32 unchanged - // |h3| <= 1.51*2^58 - // |h7| <= 1.51*2^58 - - carry[3] = (h3 + (1 << 24)) >> 25 - h4 += carry[3] - h3 -= carry[3] << 25 - carry[7] = (h7 + (1 << 24)) >> 25 - h8 += carry[7] - h7 -= carry[7] << 25 - // |h3| <= 2^24; from now on fits into int32 unchanged - // |h7| <= 2^24; from now on fits into int32 unchanged - // |h4| <= 1.52*2^33 - // |h8| <= 1.52*2^33 - - carry[4] = (h4 + (1 << 25)) >> 26 - h5 += carry[4] - h4 -= carry[4] << 26 - carry[8] = (h8 + (1 << 25)) >> 26 - h9 += carry[8] - h8 -= carry[8] << 26 - // |h4| <= 2^25; from now on fits into int32 unchanged - // |h8| <= 2^25; from now on fits into int32 unchanged - // |h5| <= 1.01*2^24 - // |h9| <= 1.51*2^58 - - carry[9] = (h9 + (1 << 24)) >> 25 - h0 += carry[9] * 19 - h9 -= carry[9] << 25 - // |h9| <= 2^24; from now on fits into int32 unchanged - // |h0| <= 1.8*2^37 - - carry[0] = (h0 + (1 << 25)) >> 26 - h1 += carry[0] - h0 -= carry[0] << 26 - // |h0| <= 2^25; from now on fits into int32 unchanged - // |h1| <= 1.01*2^24 - - h[0] = int32(h0) - h[1] = int32(h1) - h[2] = int32(h2) - h[3] = int32(h3) - h[4] = int32(h4) - h[5] = int32(h5) - h[6] = int32(h6) - h[7] = int32(h7) - h[8] = int32(h8) - h[9] = int32(h9) -} - -// feSquare calculates h = f*f. Can overlap h with f. -// -// Preconditions: -// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -// -// Postconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -func feSquare(h, f *fieldElement) { - f0 := f[0] - f1 := f[1] - f2 := f[2] - f3 := f[3] - f4 := f[4] - f5 := f[5] - f6 := f[6] - f7 := f[7] - f8 := f[8] - f9 := f[9] - f0_2 := 2 * f0 - f1_2 := 2 * f1 - f2_2 := 2 * f2 - f3_2 := 2 * f3 - f4_2 := 2 * f4 - f5_2 := 2 * f5 - f6_2 := 2 * f6 - f7_2 := 2 * f7 - f5_38 := 38 * f5 // 1.31*2^30 - f6_19 := 19 * f6 // 1.31*2^30 - f7_38 := 38 * f7 // 1.31*2^30 - f8_19 := 19 * f8 // 1.31*2^30 - f9_38 := 38 * f9 // 1.31*2^30 - f0f0 := int64(f0) * int64(f0) - f0f1_2 := int64(f0_2) * int64(f1) - f0f2_2 := int64(f0_2) * int64(f2) - f0f3_2 := int64(f0_2) * int64(f3) - f0f4_2 := int64(f0_2) * int64(f4) - f0f5_2 := int64(f0_2) * int64(f5) - f0f6_2 := int64(f0_2) * int64(f6) - f0f7_2 := int64(f0_2) * int64(f7) - f0f8_2 := int64(f0_2) * int64(f8) - f0f9_2 := int64(f0_2) * int64(f9) - f1f1_2 := int64(f1_2) * int64(f1) - f1f2_2 := int64(f1_2) * int64(f2) - f1f3_4 := int64(f1_2) * int64(f3_2) - f1f4_2 := int64(f1_2) * int64(f4) - f1f5_4 := int64(f1_2) * int64(f5_2) - f1f6_2 := int64(f1_2) * int64(f6) - f1f7_4 := int64(f1_2) * int64(f7_2) - f1f8_2 := int64(f1_2) * int64(f8) - f1f9_76 := int64(f1_2) * int64(f9_38) - f2f2 := int64(f2) * int64(f2) - f2f3_2 := int64(f2_2) * int64(f3) - f2f4_2 := int64(f2_2) * int64(f4) - f2f5_2 := int64(f2_2) * int64(f5) - f2f6_2 := int64(f2_2) * int64(f6) - f2f7_2 := int64(f2_2) * int64(f7) - f2f8_38 := int64(f2_2) * int64(f8_19) - f2f9_38 := int64(f2) * int64(f9_38) - f3f3_2 := int64(f3_2) * int64(f3) - f3f4_2 := int64(f3_2) * int64(f4) - f3f5_4 := int64(f3_2) * int64(f5_2) - f3f6_2 := int64(f3_2) * int64(f6) - f3f7_76 := int64(f3_2) * int64(f7_38) - f3f8_38 := int64(f3_2) * int64(f8_19) - f3f9_76 := int64(f3_2) * int64(f9_38) - f4f4 := int64(f4) * int64(f4) - f4f5_2 := int64(f4_2) * int64(f5) - f4f6_38 := int64(f4_2) * int64(f6_19) - f4f7_38 := int64(f4) * int64(f7_38) - f4f8_38 := int64(f4_2) * int64(f8_19) - f4f9_38 := int64(f4) * int64(f9_38) - f5f5_38 := int64(f5) * int64(f5_38) - f5f6_38 := int64(f5_2) * int64(f6_19) - f5f7_76 := int64(f5_2) * int64(f7_38) - f5f8_38 := int64(f5_2) * int64(f8_19) - f5f9_76 := int64(f5_2) * int64(f9_38) - f6f6_19 := int64(f6) * int64(f6_19) - f6f7_38 := int64(f6) * int64(f7_38) - f6f8_38 := int64(f6_2) * int64(f8_19) - f6f9_38 := int64(f6) * int64(f9_38) - f7f7_38 := int64(f7) * int64(f7_38) - f7f8_38 := int64(f7_2) * int64(f8_19) - f7f9_76 := int64(f7_2) * int64(f9_38) - f8f8_19 := int64(f8) * int64(f8_19) - f8f9_38 := int64(f8) * int64(f9_38) - f9f9_38 := int64(f9) * int64(f9_38) - h0 := f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38 - h1 := f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38 - h2 := f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19 - h3 := f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38 - h4 := f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38 - h5 := f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38 - h6 := f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19 - h7 := f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38 - h8 := f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38 - h9 := f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2 - var carry [10]int64 - - carry[0] = (h0 + (1 << 25)) >> 26 - h1 += carry[0] - h0 -= carry[0] << 26 - carry[4] = (h4 + (1 << 25)) >> 26 - h5 += carry[4] - h4 -= carry[4] << 26 - - carry[1] = (h1 + (1 << 24)) >> 25 - h2 += carry[1] - h1 -= carry[1] << 25 - carry[5] = (h5 + (1 << 24)) >> 25 - h6 += carry[5] - h5 -= carry[5] << 25 - - carry[2] = (h2 + (1 << 25)) >> 26 - h3 += carry[2] - h2 -= carry[2] << 26 - carry[6] = (h6 + (1 << 25)) >> 26 - h7 += carry[6] - h6 -= carry[6] << 26 - - carry[3] = (h3 + (1 << 24)) >> 25 - h4 += carry[3] - h3 -= carry[3] << 25 - carry[7] = (h7 + (1 << 24)) >> 25 - h8 += carry[7] - h7 -= carry[7] << 25 - - carry[4] = (h4 + (1 << 25)) >> 26 - h5 += carry[4] - h4 -= carry[4] << 26 - carry[8] = (h8 + (1 << 25)) >> 26 - h9 += carry[8] - h8 -= carry[8] << 26 - - carry[9] = (h9 + (1 << 24)) >> 25 - h0 += carry[9] * 19 - h9 -= carry[9] << 25 - - carry[0] = (h0 + (1 << 25)) >> 26 - h1 += carry[0] - h0 -= carry[0] << 26 - - h[0] = int32(h0) - h[1] = int32(h1) - h[2] = int32(h2) - h[3] = int32(h3) - h[4] = int32(h4) - h[5] = int32(h5) - h[6] = int32(h6) - h[7] = int32(h7) - h[8] = int32(h8) - h[9] = int32(h9) -} - -// feMul121666 calculates h = f * 121666. Can overlap h with f. -// -// Preconditions: -// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -// -// Postconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -func feMul121666(h, f *fieldElement) { - h0 := int64(f[0]) * 121666 - h1 := int64(f[1]) * 121666 - h2 := int64(f[2]) * 121666 - h3 := int64(f[3]) * 121666 - h4 := int64(f[4]) * 121666 - h5 := int64(f[5]) * 121666 - h6 := int64(f[6]) * 121666 - h7 := int64(f[7]) * 121666 - h8 := int64(f[8]) * 121666 - h9 := int64(f[9]) * 121666 - var carry [10]int64 - - carry[9] = (h9 + (1 << 24)) >> 25 - h0 += carry[9] * 19 - h9 -= carry[9] << 25 - carry[1] = (h1 + (1 << 24)) >> 25 - h2 += carry[1] - h1 -= carry[1] << 25 - carry[3] = (h3 + (1 << 24)) >> 25 - h4 += carry[3] - h3 -= carry[3] << 25 - carry[5] = (h5 + (1 << 24)) >> 25 - h6 += carry[5] - h5 -= carry[5] << 25 - carry[7] = (h7 + (1 << 24)) >> 25 - h8 += carry[7] - h7 -= carry[7] << 25 - - carry[0] = (h0 + (1 << 25)) >> 26 - h1 += carry[0] - h0 -= carry[0] << 26 - carry[2] = (h2 + (1 << 25)) >> 26 - h3 += carry[2] - h2 -= carry[2] << 26 - carry[4] = (h4 + (1 << 25)) >> 26 - h5 += carry[4] - h4 -= carry[4] << 26 - carry[6] = (h6 + (1 << 25)) >> 26 - h7 += carry[6] - h6 -= carry[6] << 26 - carry[8] = (h8 + (1 << 25)) >> 26 - h9 += carry[8] - h8 -= carry[8] << 26 - - h[0] = int32(h0) - h[1] = int32(h1) - h[2] = int32(h2) - h[3] = int32(h3) - h[4] = int32(h4) - h[5] = int32(h5) - h[6] = int32(h6) - h[7] = int32(h7) - h[8] = int32(h8) - h[9] = int32(h9) -} - -// feInvert sets out = z^-1. -func feInvert(out, z *fieldElement) { - var t0, t1, t2, t3 fieldElement - var i int - - feSquare(&t0, z) - for i = 1; i < 1; i++ { - feSquare(&t0, &t0) - } - feSquare(&t1, &t0) - for i = 1; i < 2; i++ { - feSquare(&t1, &t1) - } - feMul(&t1, z, &t1) - feMul(&t0, &t0, &t1) - feSquare(&t2, &t0) - for i = 1; i < 1; i++ { - feSquare(&t2, &t2) - } - feMul(&t1, &t1, &t2) - feSquare(&t2, &t1) - for i = 1; i < 5; i++ { - feSquare(&t2, &t2) - } - feMul(&t1, &t2, &t1) - feSquare(&t2, &t1) - for i = 1; i < 10; i++ { - feSquare(&t2, &t2) - } - feMul(&t2, &t2, &t1) - feSquare(&t3, &t2) - for i = 1; i < 20; i++ { - feSquare(&t3, &t3) - } - feMul(&t2, &t3, &t2) - feSquare(&t2, &t2) - for i = 1; i < 10; i++ { - feSquare(&t2, &t2) - } - feMul(&t1, &t2, &t1) - feSquare(&t2, &t1) - for i = 1; i < 50; i++ { - feSquare(&t2, &t2) - } - feMul(&t2, &t2, &t1) - feSquare(&t3, &t2) - for i = 1; i < 100; i++ { - feSquare(&t3, &t3) - } - feMul(&t2, &t3, &t2) - feSquare(&t2, &t2) - for i = 1; i < 50; i++ { - feSquare(&t2, &t2) - } - feMul(&t1, &t2, &t1) - feSquare(&t1, &t1) - for i = 1; i < 5; i++ { - feSquare(&t1, &t1) - } - feMul(out, &t1, &t0) -} - -func scalarMultGeneric(out, in, base *[32]byte) { - var e [32]byte - - copy(e[:], in[:]) - e[0] &= 248 - e[31] &= 127 - e[31] |= 64 - - var x1, x2, z2, x3, z3, tmp0, tmp1 fieldElement - feFromBytes(&x1, base) - feOne(&x2) - feCopy(&x3, &x1) - feOne(&z3) - - swap := int32(0) - for pos := 254; pos >= 0; pos-- { - b := e[pos/8] >> uint(pos&7) - b &= 1 - swap ^= int32(b) - feCSwap(&x2, &x3, swap) - feCSwap(&z2, &z3, swap) - swap = int32(b) - - feSub(&tmp0, &x3, &z3) - feSub(&tmp1, &x2, &z2) - feAdd(&x2, &x2, &z2) - feAdd(&z2, &x3, &z3) - feMul(&z3, &tmp0, &x2) - feMul(&z2, &z2, &tmp1) - feSquare(&tmp0, &tmp1) - feSquare(&tmp1, &x2) - feAdd(&x3, &z3, &z2) - feSub(&z2, &z3, &z2) - feMul(&x2, &tmp1, &tmp0) - feSub(&tmp1, &tmp1, &tmp0) - feSquare(&z2, &z2) - feMul121666(&z3, &tmp1) - feSquare(&x3, &x3) - feAdd(&tmp0, &tmp0, &z3) - feMul(&z3, &x1, &z2) - feMul(&z2, &tmp1, &tmp0) - } - - feCSwap(&x2, &x3, swap) - feCSwap(&z2, &z3, swap) - - feInvert(&z2, &z2) - feMul(&x2, &x2, &z2) - feToBytes(out, &x2) -} diff --git a/src/vendor/golang.org/x/crypto/curve25519/curve25519_noasm.go b/src/vendor/golang.org/x/crypto/curve25519/curve25519_noasm.go deleted file mode 100644 index 259728af7d..0000000000 --- a/src/vendor/golang.org/x/crypto/curve25519/curve25519_noasm.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !amd64 || !gc || purego -// +build !amd64 !gc purego - -package curve25519 - -func scalarMult(out, in, base *[32]byte) { - scalarMultGeneric(out, in, base) -} diff --git a/src/vendor/golang.org/x/crypto/curve25519/internal/field/README b/src/vendor/golang.org/x/crypto/curve25519/internal/field/README new file mode 100644 index 0000000000..e25bca7dc8 --- /dev/null +++ b/src/vendor/golang.org/x/crypto/curve25519/internal/field/README @@ -0,0 +1,7 @@ +This package is kept in sync with crypto/ed25519/internal/edwards25519/field in +the standard library. + +If there are any changes in the standard library that need to be synced to this +package, run sync.sh. It will not overwrite any local changes made since the +previous sync, so it's ok to land changes in this package first, and then sync +to the standard library later. diff --git a/src/vendor/golang.org/x/crypto/curve25519/internal/field/fe.go b/src/vendor/golang.org/x/crypto/curve25519/internal/field/fe.go new file mode 100644 index 0000000000..ca841ad99e --- /dev/null +++ b/src/vendor/golang.org/x/crypto/curve25519/internal/field/fe.go @@ -0,0 +1,416 @@ +// Copyright (c) 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package field implements fast arithmetic modulo 2^255-19. +package field + +import ( + "crypto/subtle" + "encoding/binary" + "math/bits" +) + +// Element represents an element of the field GF(2^255-19). Note that this +// is not a cryptographically secure group, and should only be used to interact +// with edwards25519.Point coordinates. +// +// This type works similarly to math/big.Int, and all arguments and receivers +// are allowed to alias. +// +// The zero value is a valid zero element. +type Element struct { + // An element t represents the integer + // t.l0 + t.l1*2^51 + t.l2*2^102 + t.l3*2^153 + t.l4*2^204 + // + // Between operations, all limbs are expected to be lower than 2^52. + l0 uint64 + l1 uint64 + l2 uint64 + l3 uint64 + l4 uint64 +} + +const maskLow51Bits uint64 = (1 << 51) - 1 + +var feZero = &Element{0, 0, 0, 0, 0} + +// Zero sets v = 0, and returns v. +func (v *Element) Zero() *Element { + *v = *feZero + return v +} + +var feOne = &Element{1, 0, 0, 0, 0} + +// One sets v = 1, and returns v. +func (v *Element) One() *Element { + *v = *feOne + return v +} + +// reduce reduces v modulo 2^255 - 19 and returns it. +func (v *Element) reduce() *Element { + v.carryPropagate() + + // After the light reduction we now have a field element representation + // v < 2^255 + 2^13 * 19, but need v < 2^255 - 19. + + // If v >= 2^255 - 19, then v + 19 >= 2^255, which would overflow 2^255 - 1, + // generating a carry. That is, c will be 0 if v < 2^255 - 19, and 1 otherwise. + c := (v.l0 + 19) >> 51 + c = (v.l1 + c) >> 51 + c = (v.l2 + c) >> 51 + c = (v.l3 + c) >> 51 + c = (v.l4 + c) >> 51 + + // If v < 2^255 - 19 and c = 0, this will be a no-op. Otherwise, it's + // effectively applying the reduction identity to the carry. + v.l0 += 19 * c + + v.l1 += v.l0 >> 51 + v.l0 = v.l0 & maskLow51Bits + v.l2 += v.l1 >> 51 + v.l1 = v.l1 & maskLow51Bits + v.l3 += v.l2 >> 51 + v.l2 = v.l2 & maskLow51Bits + v.l4 += v.l3 >> 51 + v.l3 = v.l3 & maskLow51Bits + // no additional carry + v.l4 = v.l4 & maskLow51Bits + + return v +} + +// Add sets v = a + b, and returns v. +func (v *Element) Add(a, b *Element) *Element { + v.l0 = a.l0 + b.l0 + v.l1 = a.l1 + b.l1 + v.l2 = a.l2 + b.l2 + v.l3 = a.l3 + b.l3 + v.l4 = a.l4 + b.l4 + // Using the generic implementation here is actually faster than the + // assembly. Probably because the body of this function is so simple that + // the compiler can figure out better optimizations by inlining the carry + // propagation. TODO + return v.carryPropagateGeneric() +} + +// Subtract sets v = a - b, and returns v. +func (v *Element) Subtract(a, b *Element) *Element { + // We first add 2 * p, to guarantee the subtraction won't underflow, and + // then subtract b (which can be up to 2^255 + 2^13 * 19). + v.l0 = (a.l0 + 0xFFFFFFFFFFFDA) - b.l0 + v.l1 = (a.l1 + 0xFFFFFFFFFFFFE) - b.l1 + v.l2 = (a.l2 + 0xFFFFFFFFFFFFE) - b.l2 + v.l3 = (a.l3 + 0xFFFFFFFFFFFFE) - b.l3 + v.l4 = (a.l4 + 0xFFFFFFFFFFFFE) - b.l4 + return v.carryPropagate() +} + +// Negate sets v = -a, and returns v. +func (v *Element) Negate(a *Element) *Element { + return v.Subtract(feZero, a) +} + +// Invert sets v = 1/z mod p, and returns v. +// +// If z == 0, Invert returns v = 0. +func (v *Element) Invert(z *Element) *Element { + // Inversion is implemented as exponentiation with exponent p − 2. It uses the + // same sequence of 255 squarings and 11 multiplications as [Curve25519]. + var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t Element + + z2.Square(z) // 2 + t.Square(&z2) // 4 + t.Square(&t) // 8 + z9.Multiply(&t, z) // 9 + z11.Multiply(&z9, &z2) // 11 + t.Square(&z11) // 22 + z2_5_0.Multiply(&t, &z9) // 31 = 2^5 - 2^0 + + t.Square(&z2_5_0) // 2^6 - 2^1 + for i := 0; i < 4; i++ { + t.Square(&t) // 2^10 - 2^5 + } + z2_10_0.Multiply(&t, &z2_5_0) // 2^10 - 2^0 + + t.Square(&z2_10_0) // 2^11 - 2^1 + for i := 0; i < 9; i++ { + t.Square(&t) // 2^20 - 2^10 + } + z2_20_0.Multiply(&t, &z2_10_0) // 2^20 - 2^0 + + t.Square(&z2_20_0) // 2^21 - 2^1 + for i := 0; i < 19; i++ { + t.Square(&t) // 2^40 - 2^20 + } + t.Multiply(&t, &z2_20_0) // 2^40 - 2^0 + + t.Square(&t) // 2^41 - 2^1 + for i := 0; i < 9; i++ { + t.Square(&t) // 2^50 - 2^10 + } + z2_50_0.Multiply(&t, &z2_10_0) // 2^50 - 2^0 + + t.Square(&z2_50_0) // 2^51 - 2^1 + for i := 0; i < 49; i++ { + t.Square(&t) // 2^100 - 2^50 + } + z2_100_0.Multiply(&t, &z2_50_0) // 2^100 - 2^0 + + t.Square(&z2_100_0) // 2^101 - 2^1 + for i := 0; i < 99; i++ { + t.Square(&t) // 2^200 - 2^100 + } + t.Multiply(&t, &z2_100_0) // 2^200 - 2^0 + + t.Square(&t) // 2^201 - 2^1 + for i := 0; i < 49; i++ { + t.Square(&t) // 2^250 - 2^50 + } + t.Multiply(&t, &z2_50_0) // 2^250 - 2^0 + + t.Square(&t) // 2^251 - 2^1 + t.Square(&t) // 2^252 - 2^2 + t.Square(&t) // 2^253 - 2^3 + t.Square(&t) // 2^254 - 2^4 + t.Square(&t) // 2^255 - 2^5 + + return v.Multiply(&t, &z11) // 2^255 - 21 +} + +// Set sets v = a, and returns v. +func (v *Element) Set(a *Element) *Element { + *v = *a + return v +} + +// SetBytes sets v to x, which must be a 32-byte little-endian encoding. +// +// Consistent with RFC 7748, the most significant bit (the high bit of the +// last byte) is ignored, and non-canonical values (2^255-19 through 2^255-1) +// are accepted. Note that this is laxer than specified by RFC 8032. +func (v *Element) SetBytes(x []byte) *Element { + if len(x) != 32 { + panic("edwards25519: invalid field element input size") + } + + // Bits 0:51 (bytes 0:8, bits 0:64, shift 0, mask 51). + v.l0 = binary.LittleEndian.Uint64(x[0:8]) + v.l0 &= maskLow51Bits + // Bits 51:102 (bytes 6:14, bits 48:112, shift 3, mask 51). + v.l1 = binary.LittleEndian.Uint64(x[6:14]) >> 3 + v.l1 &= maskLow51Bits + // Bits 102:153 (bytes 12:20, bits 96:160, shift 6, mask 51). + v.l2 = binary.LittleEndian.Uint64(x[12:20]) >> 6 + v.l2 &= maskLow51Bits + // Bits 153:204 (bytes 19:27, bits 152:216, shift 1, mask 51). + v.l3 = binary.LittleEndian.Uint64(x[19:27]) >> 1 + v.l3 &= maskLow51Bits + // Bits 204:251 (bytes 24:32, bits 192:256, shift 12, mask 51). + // Note: not bytes 25:33, shift 4, to avoid overread. + v.l4 = binary.LittleEndian.Uint64(x[24:32]) >> 12 + v.l4 &= maskLow51Bits + + return v +} + +// Bytes returns the canonical 32-byte little-endian encoding of v. +func (v *Element) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var out [32]byte + return v.bytes(&out) +} + +func (v *Element) bytes(out *[32]byte) []byte { + t := *v + t.reduce() + + var buf [8]byte + for i, l := range [5]uint64{t.l0, t.l1, t.l2, t.l3, t.l4} { + bitsOffset := i * 51 + binary.LittleEndian.PutUint64(buf[:], l<= len(out) { + break + } + out[off] |= bb + } + } + + return out[:] +} + +// Equal returns 1 if v and u are equal, and 0 otherwise. +func (v *Element) Equal(u *Element) int { + sa, sv := u.Bytes(), v.Bytes() + return subtle.ConstantTimeCompare(sa, sv) +} + +// mask64Bits returns 0xffffffff if cond is 1, and 0 otherwise. +func mask64Bits(cond int) uint64 { return ^(uint64(cond) - 1) } + +// Select sets v to a if cond == 1, and to b if cond == 0. +func (v *Element) Select(a, b *Element, cond int) *Element { + m := mask64Bits(cond) + v.l0 = (m & a.l0) | (^m & b.l0) + v.l1 = (m & a.l1) | (^m & b.l1) + v.l2 = (m & a.l2) | (^m & b.l2) + v.l3 = (m & a.l3) | (^m & b.l3) + v.l4 = (m & a.l4) | (^m & b.l4) + return v +} + +// Swap swaps v and u if cond == 1 or leaves them unchanged if cond == 0, and returns v. +func (v *Element) Swap(u *Element, cond int) { + m := mask64Bits(cond) + t := m & (v.l0 ^ u.l0) + v.l0 ^= t + u.l0 ^= t + t = m & (v.l1 ^ u.l1) + v.l1 ^= t + u.l1 ^= t + t = m & (v.l2 ^ u.l2) + v.l2 ^= t + u.l2 ^= t + t = m & (v.l3 ^ u.l3) + v.l3 ^= t + u.l3 ^= t + t = m & (v.l4 ^ u.l4) + v.l4 ^= t + u.l4 ^= t +} + +// IsNegative returns 1 if v is negative, and 0 otherwise. +func (v *Element) IsNegative() int { + return int(v.Bytes()[0] & 1) +} + +// Absolute sets v to |u|, and returns v. +func (v *Element) Absolute(u *Element) *Element { + return v.Select(new(Element).Negate(u), u, u.IsNegative()) +} + +// Multiply sets v = x * y, and returns v. +func (v *Element) Multiply(x, y *Element) *Element { + feMul(v, x, y) + return v +} + +// Square sets v = x * x, and returns v. +func (v *Element) Square(x *Element) *Element { + feSquare(v, x) + return v +} + +// Mult32 sets v = x * y, and returns v. +func (v *Element) Mult32(x *Element, y uint32) *Element { + x0lo, x0hi := mul51(x.l0, y) + x1lo, x1hi := mul51(x.l1, y) + x2lo, x2hi := mul51(x.l2, y) + x3lo, x3hi := mul51(x.l3, y) + x4lo, x4hi := mul51(x.l4, y) + v.l0 = x0lo + 19*x4hi // carried over per the reduction identity + v.l1 = x1lo + x0hi + v.l2 = x2lo + x1hi + v.l3 = x3lo + x2hi + v.l4 = x4lo + x3hi + // The hi portions are going to be only 32 bits, plus any previous excess, + // so we can skip the carry propagation. + return v +} + +// mul51 returns lo + hi * 2⁵¹ = a * b. +func mul51(a uint64, b uint32) (lo uint64, hi uint64) { + mh, ml := bits.Mul64(a, uint64(b)) + lo = ml & maskLow51Bits + hi = (mh << 13) | (ml >> 51) + return +} + +// Pow22523 set v = x^((p-5)/8), and returns v. (p-5)/8 is 2^252-3. +func (v *Element) Pow22523(x *Element) *Element { + var t0, t1, t2 Element + + t0.Square(x) // x^2 + t1.Square(&t0) // x^4 + t1.Square(&t1) // x^8 + t1.Multiply(x, &t1) // x^9 + t0.Multiply(&t0, &t1) // x^11 + t0.Square(&t0) // x^22 + t0.Multiply(&t1, &t0) // x^31 + t1.Square(&t0) // x^62 + for i := 1; i < 5; i++ { // x^992 + t1.Square(&t1) + } + t0.Multiply(&t1, &t0) // x^1023 -> 1023 = 2^10 - 1 + t1.Square(&t0) // 2^11 - 2 + for i := 1; i < 10; i++ { // 2^20 - 2^10 + t1.Square(&t1) + } + t1.Multiply(&t1, &t0) // 2^20 - 1 + t2.Square(&t1) // 2^21 - 2 + for i := 1; i < 20; i++ { // 2^40 - 2^20 + t2.Square(&t2) + } + t1.Multiply(&t2, &t1) // 2^40 - 1 + t1.Square(&t1) // 2^41 - 2 + for i := 1; i < 10; i++ { // 2^50 - 2^10 + t1.Square(&t1) + } + t0.Multiply(&t1, &t0) // 2^50 - 1 + t1.Square(&t0) // 2^51 - 2 + for i := 1; i < 50; i++ { // 2^100 - 2^50 + t1.Square(&t1) + } + t1.Multiply(&t1, &t0) // 2^100 - 1 + t2.Square(&t1) // 2^101 - 2 + for i := 1; i < 100; i++ { // 2^200 - 2^100 + t2.Square(&t2) + } + t1.Multiply(&t2, &t1) // 2^200 - 1 + t1.Square(&t1) // 2^201 - 2 + for i := 1; i < 50; i++ { // 2^250 - 2^50 + t1.Square(&t1) + } + t0.Multiply(&t1, &t0) // 2^250 - 1 + t0.Square(&t0) // 2^251 - 2 + t0.Square(&t0) // 2^252 - 4 + return v.Multiply(&t0, x) // 2^252 - 3 -> x^(2^252-3) +} + +// sqrtM1 is 2^((p-1)/4), which squared is equal to -1 by Euler's Criterion. +var sqrtM1 = &Element{1718705420411056, 234908883556509, + 2233514472574048, 2117202627021982, 765476049583133} + +// SqrtRatio sets r to the non-negative square root of the ratio of u and v. +// +// If u/v is square, SqrtRatio returns r and 1. If u/v is not square, SqrtRatio +// sets r according to Section 4.3 of draft-irtf-cfrg-ristretto255-decaf448-00, +// and returns r and 0. +func (r *Element) SqrtRatio(u, v *Element) (rr *Element, wasSquare int) { + var a, b Element + + // r = (u * v3) * (u * v7)^((p-5)/8) + v2 := a.Square(v) + uv3 := b.Multiply(u, b.Multiply(v2, v)) + uv7 := a.Multiply(uv3, a.Square(v2)) + r.Multiply(uv3, r.Pow22523(uv7)) + + check := a.Multiply(v, a.Square(r)) // check = v * r^2 + + uNeg := b.Negate(u) + correctSignSqrt := check.Equal(u) + flippedSignSqrt := check.Equal(uNeg) + flippedSignSqrtI := check.Equal(uNeg.Multiply(uNeg, sqrtM1)) + + rPrime := b.Multiply(r, sqrtM1) // r_prime = SQRT_M1 * r + // r = CT_SELECT(r_prime IF flipped_sign_sqrt | flipped_sign_sqrt_i ELSE r) + r.Select(rPrime, r, flippedSignSqrt|flippedSignSqrtI) + + r.Absolute(r) // Choose the nonnegative square root. + return r, correctSignSqrt | flippedSignSqrt +} diff --git a/src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go b/src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go new file mode 100644 index 0000000000..44dc8e8caf --- /dev/null +++ b/src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go @@ -0,0 +1,13 @@ +// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT. + +// +build amd64,gc,!purego + +package field + +// feMul sets out = a * b. It works like feMulGeneric. +//go:noescape +func feMul(out *Element, a *Element, b *Element) + +// feSquare sets out = a * a. It works like feSquareGeneric. +//go:noescape +func feSquare(out *Element, a *Element) diff --git a/src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s b/src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s new file mode 100644 index 0000000000..293f013c94 --- /dev/null +++ b/src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s @@ -0,0 +1,379 @@ +// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT. + +//go:build amd64 && gc && !purego +// +build amd64,gc,!purego + +#include "textflag.h" + +// func feMul(out *Element, a *Element, b *Element) +TEXT ·feMul(SB), NOSPLIT, $0-24 + MOVQ a+8(FP), CX + MOVQ b+16(FP), BX + + // r0 = a0×b0 + MOVQ (CX), AX + MULQ (BX) + MOVQ AX, DI + MOVQ DX, SI + + // r0 += 19×a1×b4 + MOVQ 8(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 32(BX) + ADDQ AX, DI + ADCQ DX, SI + + // r0 += 19×a2×b3 + MOVQ 16(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 24(BX) + ADDQ AX, DI + ADCQ DX, SI + + // r0 += 19×a3×b2 + MOVQ 24(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 16(BX) + ADDQ AX, DI + ADCQ DX, SI + + // r0 += 19×a4×b1 + MOVQ 32(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 8(BX) + ADDQ AX, DI + ADCQ DX, SI + + // r1 = a0×b1 + MOVQ (CX), AX + MULQ 8(BX) + MOVQ AX, R9 + MOVQ DX, R8 + + // r1 += a1×b0 + MOVQ 8(CX), AX + MULQ (BX) + ADDQ AX, R9 + ADCQ DX, R8 + + // r1 += 19×a2×b4 + MOVQ 16(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 32(BX) + ADDQ AX, R9 + ADCQ DX, R8 + + // r1 += 19×a3×b3 + MOVQ 24(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 24(BX) + ADDQ AX, R9 + ADCQ DX, R8 + + // r1 += 19×a4×b2 + MOVQ 32(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 16(BX) + ADDQ AX, R9 + ADCQ DX, R8 + + // r2 = a0×b2 + MOVQ (CX), AX + MULQ 16(BX) + MOVQ AX, R11 + MOVQ DX, R10 + + // r2 += a1×b1 + MOVQ 8(CX), AX + MULQ 8(BX) + ADDQ AX, R11 + ADCQ DX, R10 + + // r2 += a2×b0 + MOVQ 16(CX), AX + MULQ (BX) + ADDQ AX, R11 + ADCQ DX, R10 + + // r2 += 19×a3×b4 + MOVQ 24(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 32(BX) + ADDQ AX, R11 + ADCQ DX, R10 + + // r2 += 19×a4×b3 + MOVQ 32(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 24(BX) + ADDQ AX, R11 + ADCQ DX, R10 + + // r3 = a0×b3 + MOVQ (CX), AX + MULQ 24(BX) + MOVQ AX, R13 + MOVQ DX, R12 + + // r3 += a1×b2 + MOVQ 8(CX), AX + MULQ 16(BX) + ADDQ AX, R13 + ADCQ DX, R12 + + // r3 += a2×b1 + MOVQ 16(CX), AX + MULQ 8(BX) + ADDQ AX, R13 + ADCQ DX, R12 + + // r3 += a3×b0 + MOVQ 24(CX), AX + MULQ (BX) + ADDQ AX, R13 + ADCQ DX, R12 + + // r3 += 19×a4×b4 + MOVQ 32(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 32(BX) + ADDQ AX, R13 + ADCQ DX, R12 + + // r4 = a0×b4 + MOVQ (CX), AX + MULQ 32(BX) + MOVQ AX, R15 + MOVQ DX, R14 + + // r4 += a1×b3 + MOVQ 8(CX), AX + MULQ 24(BX) + ADDQ AX, R15 + ADCQ DX, R14 + + // r4 += a2×b2 + MOVQ 16(CX), AX + MULQ 16(BX) + ADDQ AX, R15 + ADCQ DX, R14 + + // r4 += a3×b1 + MOVQ 24(CX), AX + MULQ 8(BX) + ADDQ AX, R15 + ADCQ DX, R14 + + // r4 += a4×b0 + MOVQ 32(CX), AX + MULQ (BX) + ADDQ AX, R15 + ADCQ DX, R14 + + // First reduction chain + MOVQ $0x0007ffffffffffff, AX + SHLQ $0x0d, DI, SI + SHLQ $0x0d, R9, R8 + SHLQ $0x0d, R11, R10 + SHLQ $0x0d, R13, R12 + SHLQ $0x0d, R15, R14 + ANDQ AX, DI + IMUL3Q $0x13, R14, R14 + ADDQ R14, DI + ANDQ AX, R9 + ADDQ SI, R9 + ANDQ AX, R11 + ADDQ R8, R11 + ANDQ AX, R13 + ADDQ R10, R13 + ANDQ AX, R15 + ADDQ R12, R15 + + // Second reduction chain (carryPropagate) + MOVQ DI, SI + SHRQ $0x33, SI + MOVQ R9, R8 + SHRQ $0x33, R8 + MOVQ R11, R10 + SHRQ $0x33, R10 + MOVQ R13, R12 + SHRQ $0x33, R12 + MOVQ R15, R14 + SHRQ $0x33, R14 + ANDQ AX, DI + IMUL3Q $0x13, R14, R14 + ADDQ R14, DI + ANDQ AX, R9 + ADDQ SI, R9 + ANDQ AX, R11 + ADDQ R8, R11 + ANDQ AX, R13 + ADDQ R10, R13 + ANDQ AX, R15 + ADDQ R12, R15 + + // Store output + MOVQ out+0(FP), AX + MOVQ DI, (AX) + MOVQ R9, 8(AX) + MOVQ R11, 16(AX) + MOVQ R13, 24(AX) + MOVQ R15, 32(AX) + RET + +// func feSquare(out *Element, a *Element) +TEXT ·feSquare(SB), NOSPLIT, $0-16 + MOVQ a+8(FP), CX + + // r0 = l0×l0 + MOVQ (CX), AX + MULQ (CX) + MOVQ AX, SI + MOVQ DX, BX + + // r0 += 38×l1×l4 + MOVQ 8(CX), AX + IMUL3Q $0x26, AX, AX + MULQ 32(CX) + ADDQ AX, SI + ADCQ DX, BX + + // r0 += 38×l2×l3 + MOVQ 16(CX), AX + IMUL3Q $0x26, AX, AX + MULQ 24(CX) + ADDQ AX, SI + ADCQ DX, BX + + // r1 = 2×l0×l1 + MOVQ (CX), AX + SHLQ $0x01, AX + MULQ 8(CX) + MOVQ AX, R8 + MOVQ DX, DI + + // r1 += 38×l2×l4 + MOVQ 16(CX), AX + IMUL3Q $0x26, AX, AX + MULQ 32(CX) + ADDQ AX, R8 + ADCQ DX, DI + + // r1 += 19×l3×l3 + MOVQ 24(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 24(CX) + ADDQ AX, R8 + ADCQ DX, DI + + // r2 = 2×l0×l2 + MOVQ (CX), AX + SHLQ $0x01, AX + MULQ 16(CX) + MOVQ AX, R10 + MOVQ DX, R9 + + // r2 += l1×l1 + MOVQ 8(CX), AX + MULQ 8(CX) + ADDQ AX, R10 + ADCQ DX, R9 + + // r2 += 38×l3×l4 + MOVQ 24(CX), AX + IMUL3Q $0x26, AX, AX + MULQ 32(CX) + ADDQ AX, R10 + ADCQ DX, R9 + + // r3 = 2×l0×l3 + MOVQ (CX), AX + SHLQ $0x01, AX + MULQ 24(CX) + MOVQ AX, R12 + MOVQ DX, R11 + + // r3 += 2×l1×l2 + MOVQ 8(CX), AX + IMUL3Q $0x02, AX, AX + MULQ 16(CX) + ADDQ AX, R12 + ADCQ DX, R11 + + // r3 += 19×l4×l4 + MOVQ 32(CX), AX + IMUL3Q $0x13, AX, AX + MULQ 32(CX) + ADDQ AX, R12 + ADCQ DX, R11 + + // r4 = 2×l0×l4 + MOVQ (CX), AX + SHLQ $0x01, AX + MULQ 32(CX) + MOVQ AX, R14 + MOVQ DX, R13 + + // r4 += 2×l1×l3 + MOVQ 8(CX), AX + IMUL3Q $0x02, AX, AX + MULQ 24(CX) + ADDQ AX, R14 + ADCQ DX, R13 + + // r4 += l2×l2 + MOVQ 16(CX), AX + MULQ 16(CX) + ADDQ AX, R14 + ADCQ DX, R13 + + // First reduction chain + MOVQ $0x0007ffffffffffff, AX + SHLQ $0x0d, SI, BX + SHLQ $0x0d, R8, DI + SHLQ $0x0d, R10, R9 + SHLQ $0x0d, R12, R11 + SHLQ $0x0d, R14, R13 + ANDQ AX, SI + IMUL3Q $0x13, R13, R13 + ADDQ R13, SI + ANDQ AX, R8 + ADDQ BX, R8 + ANDQ AX, R10 + ADDQ DI, R10 + ANDQ AX, R12 + ADDQ R9, R12 + ANDQ AX, R14 + ADDQ R11, R14 + + // Second reduction chain (carryPropagate) + MOVQ SI, BX + SHRQ $0x33, BX + MOVQ R8, DI + SHRQ $0x33, DI + MOVQ R10, R9 + SHRQ $0x33, R9 + MOVQ R12, R11 + SHRQ $0x33, R11 + MOVQ R14, R13 + SHRQ $0x33, R13 + ANDQ AX, SI + IMUL3Q $0x13, R13, R13 + ADDQ R13, SI + ANDQ AX, R8 + ADDQ BX, R8 + ANDQ AX, R10 + ADDQ DI, R10 + ANDQ AX, R12 + ADDQ R9, R12 + ANDQ AX, R14 + ADDQ R11, R14 + + // Store output + MOVQ out+0(FP), AX + MOVQ SI, (AX) + MOVQ R8, 8(AX) + MOVQ R10, 16(AX) + MOVQ R12, 24(AX) + MOVQ R14, 32(AX) + RET diff --git a/src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go b/src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go new file mode 100644 index 0000000000..ddb6c9b8f7 --- /dev/null +++ b/src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go @@ -0,0 +1,12 @@ +// Copyright (c) 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !amd64 || !gc || purego +// +build !amd64 !gc purego + +package field + +func feMul(v, x, y *Element) { feMulGeneric(v, x, y) } + +func feSquare(v, x *Element) { feSquareGeneric(v, x) } diff --git a/src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go b/src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go new file mode 100644 index 0000000000..af459ef515 --- /dev/null +++ b/src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go @@ -0,0 +1,16 @@ +// Copyright (c) 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build arm64 && gc && !purego +// +build arm64,gc,!purego + +package field + +//go:noescape +func carryPropagate(v *Element) + +func (v *Element) carryPropagate() *Element { + carryPropagate(v) + return v +} diff --git a/src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s b/src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s new file mode 100644 index 0000000000..5c91e45892 --- /dev/null +++ b/src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s @@ -0,0 +1,43 @@ +// Copyright (c) 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build arm64 && gc && !purego +// +build arm64,gc,!purego + +#include "textflag.h" + +// carryPropagate works exactly like carryPropagateGeneric and uses the +// same AND, ADD, and LSR+MADD instructions emitted by the compiler, but +// avoids loading R0-R4 twice and uses LDP and STP. +// +// See https://golang.org/issues/43145 for the main compiler issue. +// +// func carryPropagate(v *Element) +TEXT ·carryPropagate(SB),NOFRAME|NOSPLIT,$0-8 + MOVD v+0(FP), R20 + + LDP 0(R20), (R0, R1) + LDP 16(R20), (R2, R3) + MOVD 32(R20), R4 + + AND $0x7ffffffffffff, R0, R10 + AND $0x7ffffffffffff, R1, R11 + AND $0x7ffffffffffff, R2, R12 + AND $0x7ffffffffffff, R3, R13 + AND $0x7ffffffffffff, R4, R14 + + ADD R0>>51, R11, R11 + ADD R1>>51, R12, R12 + ADD R2>>51, R13, R13 + ADD R3>>51, R14, R14 + // R4>>51 * 19 + R10 -> R10 + LSR $51, R4, R21 + MOVD $19, R22 + MADD R22, R10, R21, R10 + + STP (R10, R11), 0(R20) + STP (R12, R13), 16(R20) + MOVD R14, 32(R20) + + RET diff --git a/src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go b/src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go new file mode 100644 index 0000000000..234a5b2e5d --- /dev/null +++ b/src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go @@ -0,0 +1,12 @@ +// Copyright (c) 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !arm64 || !gc || purego +// +build !arm64 !gc purego + +package field + +func (v *Element) carryPropagate() *Element { + return v.carryPropagateGeneric() +} diff --git a/src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_generic.go b/src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_generic.go new file mode 100644 index 0000000000..7b5b78cbd6 --- /dev/null +++ b/src/vendor/golang.org/x/crypto/curve25519/internal/field/fe_generic.go @@ -0,0 +1,264 @@ +// Copyright (c) 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package field + +import "math/bits" + +// uint128 holds a 128-bit number as two 64-bit limbs, for use with the +// bits.Mul64 and bits.Add64 intrinsics. +type uint128 struct { + lo, hi uint64 +} + +// mul64 returns a * b. +func mul64(a, b uint64) uint128 { + hi, lo := bits.Mul64(a, b) + return uint128{lo, hi} +} + +// addMul64 returns v + a * b. +func addMul64(v uint128, a, b uint64) uint128 { + hi, lo := bits.Mul64(a, b) + lo, c := bits.Add64(lo, v.lo, 0) + hi, _ = bits.Add64(hi, v.hi, c) + return uint128{lo, hi} +} + +// shiftRightBy51 returns a >> 51. a is assumed to be at most 115 bits. +func shiftRightBy51(a uint128) uint64 { + return (a.hi << (64 - 51)) | (a.lo >> 51) +} + +func feMulGeneric(v, a, b *Element) { + a0 := a.l0 + a1 := a.l1 + a2 := a.l2 + a3 := a.l3 + a4 := a.l4 + + b0 := b.l0 + b1 := b.l1 + b2 := b.l2 + b3 := b.l3 + b4 := b.l4 + + // Limb multiplication works like pen-and-paper columnar multiplication, but + // with 51-bit limbs instead of digits. + // + // a4 a3 a2 a1 a0 x + // b4 b3 b2 b1 b0 = + // ------------------------ + // a4b0 a3b0 a2b0 a1b0 a0b0 + + // a4b1 a3b1 a2b1 a1b1 a0b1 + + // a4b2 a3b2 a2b2 a1b2 a0b2 + + // a4b3 a3b3 a2b3 a1b3 a0b3 + + // a4b4 a3b4 a2b4 a1b4 a0b4 = + // ---------------------------------------------- + // r8 r7 r6 r5 r4 r3 r2 r1 r0 + // + // We can then use the reduction identity (a * 2²⁵⁵ + b = a * 19 + b) to + // reduce the limbs that would overflow 255 bits. r5 * 2²⁵⁵ becomes 19 * r5, + // r6 * 2³⁰⁶ becomes 19 * r6 * 2⁵¹, etc. + // + // Reduction can be carried out simultaneously to multiplication. For + // example, we do not compute r5: whenever the result of a multiplication + // belongs to r5, like a1b4, we multiply it by 19 and add the result to r0. + // + // a4b0 a3b0 a2b0 a1b0 a0b0 + + // a3b1 a2b1 a1b1 a0b1 19×a4b1 + + // a2b2 a1b2 a0b2 19×a4b2 19×a3b2 + + // a1b3 a0b3 19×a4b3 19×a3b3 19×a2b3 + + // a0b4 19×a4b4 19×a3b4 19×a2b4 19×a1b4 = + // -------------------------------------- + // r4 r3 r2 r1 r0 + // + // Finally we add up the columns into wide, overlapping limbs. + + a1_19 := a1 * 19 + a2_19 := a2 * 19 + a3_19 := a3 * 19 + a4_19 := a4 * 19 + + // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1) + r0 := mul64(a0, b0) + r0 = addMul64(r0, a1_19, b4) + r0 = addMul64(r0, a2_19, b3) + r0 = addMul64(r0, a3_19, b2) + r0 = addMul64(r0, a4_19, b1) + + // r1 = a0×b1 + a1×b0 + 19×(a2×b4 + a3×b3 + a4×b2) + r1 := mul64(a0, b1) + r1 = addMul64(r1, a1, b0) + r1 = addMul64(r1, a2_19, b4) + r1 = addMul64(r1, a3_19, b3) + r1 = addMul64(r1, a4_19, b2) + + // r2 = a0×b2 + a1×b1 + a2×b0 + 19×(a3×b4 + a4×b3) + r2 := mul64(a0, b2) + r2 = addMul64(r2, a1, b1) + r2 = addMul64(r2, a2, b0) + r2 = addMul64(r2, a3_19, b4) + r2 = addMul64(r2, a4_19, b3) + + // r3 = a0×b3 + a1×b2 + a2×b1 + a3×b0 + 19×a4×b4 + r3 := mul64(a0, b3) + r3 = addMul64(r3, a1, b2) + r3 = addMul64(r3, a2, b1) + r3 = addMul64(r3, a3, b0) + r3 = addMul64(r3, a4_19, b4) + + // r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0 + r4 := mul64(a0, b4) + r4 = addMul64(r4, a1, b3) + r4 = addMul64(r4, a2, b2) + r4 = addMul64(r4, a3, b1) + r4 = addMul64(r4, a4, b0) + + // After the multiplication, we need to reduce (carry) the five coefficients + // to obtain a result with limbs that are at most slightly larger than 2⁵¹, + // to respect the Element invariant. + // + // Overall, the reduction works the same as carryPropagate, except with + // wider inputs: we take the carry for each coefficient by shifting it right + // by 51, and add it to the limb above it. The top carry is multiplied by 19 + // according to the reduction identity and added to the lowest limb. + // + // The largest coefficient (r0) will be at most 111 bits, which guarantees + // that all carries are at most 111 - 51 = 60 bits, which fits in a uint64. + // + // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1) + // r0 < 2⁵²×2⁵² + 19×(2⁵²×2⁵² + 2⁵²×2⁵² + 2⁵²×2⁵² + 2⁵²×2⁵²) + // r0 < (1 + 19 × 4) × 2⁵² × 2⁵² + // r0 < 2⁷ × 2⁵² × 2⁵² + // r0 < 2¹¹¹ + // + // Moreover, the top coefficient (r4) is at most 107 bits, so c4 is at most + // 56 bits, and c4 * 19 is at most 61 bits, which again fits in a uint64 and + // allows us to easily apply the reduction identity. + // + // r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0 + // r4 < 5 × 2⁵² × 2⁵² + // r4 < 2¹⁰⁷ + // + + c0 := shiftRightBy51(r0) + c1 := shiftRightBy51(r1) + c2 := shiftRightBy51(r2) + c3 := shiftRightBy51(r3) + c4 := shiftRightBy51(r4) + + rr0 := r0.lo&maskLow51Bits + c4*19 + rr1 := r1.lo&maskLow51Bits + c0 + rr2 := r2.lo&maskLow51Bits + c1 + rr3 := r3.lo&maskLow51Bits + c2 + rr4 := r4.lo&maskLow51Bits + c3 + + // Now all coefficients fit into 64-bit registers but are still too large to + // be passed around as a Element. We therefore do one last carry chain, + // where the carries will be small enough to fit in the wiggle room above 2⁵¹. + *v = Element{rr0, rr1, rr2, rr3, rr4} + v.carryPropagate() +} + +func feSquareGeneric(v, a *Element) { + l0 := a.l0 + l1 := a.l1 + l2 := a.l2 + l3 := a.l3 + l4 := a.l4 + + // Squaring works precisely like multiplication above, but thanks to its + // symmetry we get to group a few terms together. + // + // l4 l3 l2 l1 l0 x + // l4 l3 l2 l1 l0 = + // ------------------------ + // l4l0 l3l0 l2l0 l1l0 l0l0 + + // l4l1 l3l1 l2l1 l1l1 l0l1 + + // l4l2 l3l2 l2l2 l1l2 l0l2 + + // l4l3 l3l3 l2l3 l1l3 l0l3 + + // l4l4 l3l4 l2l4 l1l4 l0l4 = + // ---------------------------------------------- + // r8 r7 r6 r5 r4 r3 r2 r1 r0 + // + // l4l0 l3l0 l2l0 l1l0 l0l0 + + // l3l1 l2l1 l1l1 l0l1 19×l4l1 + + // l2l2 l1l2 l0l2 19×l4l2 19×l3l2 + + // l1l3 l0l3 19×l4l3 19×l3l3 19×l2l3 + + // l0l4 19×l4l4 19×l3l4 19×l2l4 19×l1l4 = + // -------------------------------------- + // r4 r3 r2 r1 r0 + // + // With precomputed 2×, 19×, and 2×19× terms, we can compute each limb with + // only three Mul64 and four Add64, instead of five and eight. + + l0_2 := l0 * 2 + l1_2 := l1 * 2 + + l1_38 := l1 * 38 + l2_38 := l2 * 38 + l3_38 := l3 * 38 + + l3_19 := l3 * 19 + l4_19 := l4 * 19 + + // r0 = l0×l0 + 19×(l1×l4 + l2×l3 + l3×l2 + l4×l1) = l0×l0 + 19×2×(l1×l4 + l2×l3) + r0 := mul64(l0, l0) + r0 = addMul64(r0, l1_38, l4) + r0 = addMul64(r0, l2_38, l3) + + // r1 = l0×l1 + l1×l0 + 19×(l2×l4 + l3×l3 + l4×l2) = 2×l0×l1 + 19×2×l2×l4 + 19×l3×l3 + r1 := mul64(l0_2, l1) + r1 = addMul64(r1, l2_38, l4) + r1 = addMul64(r1, l3_19, l3) + + // r2 = l0×l2 + l1×l1 + l2×l0 + 19×(l3×l4 + l4×l3) = 2×l0×l2 + l1×l1 + 19×2×l3×l4 + r2 := mul64(l0_2, l2) + r2 = addMul64(r2, l1, l1) + r2 = addMul64(r2, l3_38, l4) + + // r3 = l0×l3 + l1×l2 + l2×l1 + l3×l0 + 19×l4×l4 = 2×l0×l3 + 2×l1×l2 + 19×l4×l4 + r3 := mul64(l0_2, l3) + r3 = addMul64(r3, l1_2, l2) + r3 = addMul64(r3, l4_19, l4) + + // r4 = l0×l4 + l1×l3 + l2×l2 + l3×l1 + l4×l0 = 2×l0×l4 + 2×l1×l3 + l2×l2 + r4 := mul64(l0_2, l4) + r4 = addMul64(r4, l1_2, l3) + r4 = addMul64(r4, l2, l2) + + c0 := shiftRightBy51(r0) + c1 := shiftRightBy51(r1) + c2 := shiftRightBy51(r2) + c3 := shiftRightBy51(r3) + c4 := shiftRightBy51(r4) + + rr0 := r0.lo&maskLow51Bits + c4*19 + rr1 := r1.lo&maskLow51Bits + c0 + rr2 := r2.lo&maskLow51Bits + c1 + rr3 := r3.lo&maskLow51Bits + c2 + rr4 := r4.lo&maskLow51Bits + c3 + + *v = Element{rr0, rr1, rr2, rr3, rr4} + v.carryPropagate() +} + +// carryPropagate brings the limbs below 52 bits by applying the reduction +// identity (a * 2²⁵⁵ + b = a * 19 + b) to the l4 carry. TODO inline +func (v *Element) carryPropagateGeneric() *Element { + c0 := v.l0 >> 51 + c1 := v.l1 >> 51 + c2 := v.l2 >> 51 + c3 := v.l3 >> 51 + c4 := v.l4 >> 51 + + v.l0 = v.l0&maskLow51Bits + c4*19 + v.l1 = v.l1&maskLow51Bits + c0 + v.l2 = v.l2&maskLow51Bits + c1 + v.l3 = v.l3&maskLow51Bits + c2 + v.l4 = v.l4&maskLow51Bits + c3 + + return v +} diff --git a/src/vendor/golang.org/x/crypto/curve25519/internal/field/sync.checkpoint b/src/vendor/golang.org/x/crypto/curve25519/internal/field/sync.checkpoint new file mode 100644 index 0000000000..e3685f95ca --- /dev/null +++ b/src/vendor/golang.org/x/crypto/curve25519/internal/field/sync.checkpoint @@ -0,0 +1 @@ +b0c49ae9f59d233526f8934262c5bbbe14d4358d diff --git a/src/vendor/golang.org/x/crypto/curve25519/internal/field/sync.sh b/src/vendor/golang.org/x/crypto/curve25519/internal/field/sync.sh new file mode 100644 index 0000000000..1ba22a8b4c --- /dev/null +++ b/src/vendor/golang.org/x/crypto/curve25519/internal/field/sync.sh @@ -0,0 +1,19 @@ +#! /bin/bash +set -euo pipefail + +cd "$(git rev-parse --show-toplevel)" + +STD_PATH=src/crypto/ed25519/internal/edwards25519/field +LOCAL_PATH=curve25519/internal/field +LAST_SYNC_REF=$(cat $LOCAL_PATH/sync.checkpoint) + +git fetch https://go.googlesource.com/go master + +if git diff --quiet $LAST_SYNC_REF:$STD_PATH FETCH_HEAD:$STD_PATH; then + echo "No changes." +else + NEW_REF=$(git rev-parse FETCH_HEAD | tee $LOCAL_PATH/sync.checkpoint) + echo "Applying changes from $LAST_SYNC_REF to $NEW_REF..." + git diff $LAST_SYNC_REF:$STD_PATH FETCH_HEAD:$STD_PATH | \ + git apply -3 --directory=$LOCAL_PATH +fi diff --git a/src/vendor/golang.org/x/crypto/poly1305/sum_amd64.s b/src/vendor/golang.org/x/crypto/poly1305/sum_amd64.s index 2cb0373140..1d74f0f881 100644 --- a/src/vendor/golang.org/x/crypto/poly1305/sum_amd64.s +++ b/src/vendor/golang.org/x/crypto/poly1305/sum_amd64.s @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build gc && !purego // +build gc,!purego #include "textflag.h" diff --git a/src/vendor/golang.org/x/crypto/poly1305/sum_ppc64le.s b/src/vendor/golang.org/x/crypto/poly1305/sum_ppc64le.s index 3cede539dc..58422aad23 100644 --- a/src/vendor/golang.org/x/crypto/poly1305/sum_ppc64le.s +++ b/src/vendor/golang.org/x/crypto/poly1305/sum_ppc64le.s @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build gc && !purego // +build gc,!purego #include "textflag.h" diff --git a/src/vendor/golang.org/x/crypto/poly1305/sum_s390x.s b/src/vendor/golang.org/x/crypto/poly1305/sum_s390x.s index bdd882c606..69c64f8421 100644 --- a/src/vendor/golang.org/x/crypto/poly1305/sum_s390x.s +++ b/src/vendor/golang.org/x/crypto/poly1305/sum_s390x.s @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build gc && !purego // +build gc,!purego #include "textflag.h" diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index 8307072942..0ba3def242 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -1,10 +1,11 @@ -# golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e +# golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 ## explicit; go 1.17 golang.org/x/crypto/chacha20 golang.org/x/crypto/chacha20poly1305 golang.org/x/crypto/cryptobyte golang.org/x/crypto/cryptobyte/asn1 golang.org/x/crypto/curve25519 +golang.org/x/crypto/curve25519/internal/field golang.org/x/crypto/hkdf golang.org/x/crypto/internal/subtle golang.org/x/crypto/poly1305 -- GitLab From 08588e60362bbd2f71235ed8e6d2a55bb42908fa Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Thu, 2 Sep 2021 10:36:37 -0400 Subject: [PATCH 0981/2500] go/internal/gcimporter: always call SetTParams, even if empty This resolves an outstanding TODO to be consistent about calling SetTParams. Done in both go/internal/gcimporter and cmd/compile/internal/importer. Change-Id: Ief642efe016f02bab1bab960f6731a0ac0a8ad28 Reviewed-on: https://go-review.googlesource.com/c/go/+/347389 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/importer/iimport.go | 4 +--- src/go/internal/gcimporter/iimport.go | 5 +---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index c303126ea6..38cb8db235 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -327,9 +327,7 @@ func (r *importReader) obj(name string) { // declaration before recursing. obj := types2.NewTypeName(pos, r.currPkg, name, nil) named := types2.NewNamed(obj, nil, nil) - if tag == 'U' { - named.SetTParams(tparams) - } + named.SetTParams(tparams) r.declare(obj) underlying := r.p.typAt(r.uint64(), named).Underlying() diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go index 444cf3b0d4..3571941d04 100644 --- a/src/go/internal/gcimporter/iimport.go +++ b/src/go/internal/gcimporter/iimport.go @@ -317,10 +317,7 @@ func (r *importReader) obj(name string) { // declaration before recursing. obj := types.NewTypeName(pos, r.currPkg, name, nil) named := types.NewNamed(obj, nil, nil) - // TODO(rfindley): guarding on tag == 'U' should not be necessary here. - if tag == 'U' { - named.SetTParams(tparams) - } + named.SetTParams(tparams) r.declare(obj) underlying := r.p.typAt(r.uint64(), named).Underlying() -- GitLab From ead3fe0dbac8f59a7199dddd4e092cac2d73aa65 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Wed, 1 Sep 2021 20:04:30 -0400 Subject: [PATCH 0982/2500] all: update vendored dependencies for Go 1.18 Go 1.18 development is well underway. This is a time to update all golang.org/x/... module versions that contribute packages to the std and cmd modules in the standard library to latest master versions. gotip $ updatestd -goroot=$(pwd) -branch=master > go version go version devel go1.18-2872496ba5 Wed Sep 1 23:41:53 2021 +0000 darwin/amd64 > go env GOROOT /Users/dmitshur/gotip > go version -m /Users/dmitshur/go/bin/bundle /Users/dmitshur/go/bin/bundle: go1.17 path golang.org/x/tools/cmd/bundle mod golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= dep golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= dep golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= dep golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= skipping github.com/chzyer/logex (out of scope, it's not a golang.org/x dependency) skipping github.com/chzyer/readline (out of scope, it's not a golang.org/x dependency) skipping github.com/chzyer/test (out of scope, it's not a golang.org/x dependency) skipping github.com/google/pprof (out of scope, it's not a golang.org/x dependency) skipping github.com/ianlancetaylor/demangle (out of scope, it's not a golang.org/x dependency) skipping github.com/yuin/goldmark (out of scope, it's not a golang.org/x dependency) skipping golang.org/x/tools (temporarily out of scope due to golang.org/issue/48124) skipping rsc.io/pdf (out of scope, it's not a golang.org/x dependency) updating module cmd in /Users/dmitshur/gotip/src/cmd > go mod edit -go=1.18 > go get -d golang.org/x/arch@ebb09ed340f18f7e2a2200f1adf792992c448346 golang.org/x/crypto@32db794688a5a24a23a43f2a984cecd5b3d8da58 golang.org/x/mod@1b1db11ec8f43eeafa9418698423dc637655ff0c golang.org/x/net@e898025ed96aa6d08e98132b8dca210e9e7a0cd2 golang.org/x/sync@036812b2e83c0ddf193dd5a34e034151da389d09 golang.org/x/sys@f4d43177bf5e2ee98617956e417d0555d4b69c17 golang.org/x/term@6886f2dfbf5b25f595b4fe4279c49956e867c59b golang.org/x/text@383b2e75a7a4198c42f8f87833eefb772868a56f golang.org/x/xerrors@5ec99f83aff198f5fbd629d6c8d8eb38a04218ca go get: upgraded golang.org/x/arch v0.0.0-20210502124803-cbf565b21d1e => v0.0.0-20210901143047-ebb09ed340f1 go get: upgraded golang.org/x/mod v0.5.1-0.20210827163434-4029241eb1d5 => v0.5.1-0.20210830214625-1b1db11ec8f4 go get: upgraded golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 => v0.0.0-20210825183410-e898025ed96a go get: upgraded golang.org/x/term v0.0.0-20210503060354-a79de5458b56 => v0.0.0-20210615171337-6886f2dfbf5b go get: upgraded golang.org/x/text v0.3.3 => v0.3.7 > go mod tidy > go mod vendor skipping golang.org/x/tools (temporarily out of scope due to golang.org/issue/48124) updating module std in /Users/dmitshur/gotip/src > go mod edit -go=1.18 > go get -d golang.org/x/crypto@32db794688a5a24a23a43f2a984cecd5b3d8da58 golang.org/x/net@e898025ed96aa6d08e98132b8dca210e9e7a0cd2 golang.org/x/sys@f4d43177bf5e2ee98617956e417d0555d4b69c17 golang.org/x/term@6886f2dfbf5b25f595b4fe4279c49956e867c59b golang.org/x/text@383b2e75a7a4198c42f8f87833eefb772868a56f go get: upgraded golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 => v0.0.0-20210615171337-6886f2dfbf5b go get: upgraded golang.org/x/text v0.3.7-0.20210503195748-5c7c50ebbd4f => v0.3.7 > go mod tidy > go mod vendor updating bundles in /Users/dmitshur/gotip/src > go generate -run=bundle std cmd The x/tools module will be updated in a following CL, after issue #48124 is resolved. The module in GOROOT/src/crypto/ed25519/internal/edwards25519/field/_asm directory is not updated in this CL. For #36905. Change-Id: I728000e8465c0fbf6976629e6da42cc4f9be20fc Reviewed-on: https://go-review.googlesource.com/c/go/+/347191 Run-TryBot: Dmitri Shuralyov TryBot-Result: Go Bot Reviewed-by: Carlos Amedee Trust: Dmitri Shuralyov --- src/cmd/go.mod | 6 ++-- src/cmd/go.sum | 12 ++++---- .../x/arch/arm64/arm64asm/plan9x.go | 2 +- src/cmd/vendor/golang.org/x/mod/zip/zip.go | 29 ++++++++++++++----- src/cmd/vendor/modules.txt | 6 ++-- src/go.mod | 2 +- src/go.sum | 4 +-- src/vendor/modules.txt | 2 +- 8 files changed, 38 insertions(+), 25 deletions(-) diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 68c3a6c992..4e0fa0bd74 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -5,11 +5,11 @@ go 1.18 require ( github.com/google/pprof v0.0.0-20210506205249-923b5ab0fc1a github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 // indirect - golang.org/x/arch v0.0.0-20210502124803-cbf565b21d1e + golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1 golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect - golang.org/x/mod v0.5.1-0.20210827163434-4029241eb1d5 + golang.org/x/mod v0.5.1-0.20210830214625-1b1db11ec8f4 golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e // indirect - golang.org/x/term v0.0.0-20210503060354-a79de5458b56 + golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b golang.org/x/tools v0.1.6-0.20210809225032-337cebd2c151 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index c6b1927eb8..dab06fdf7d 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -5,17 +5,17 @@ github.com/google/pprof v0.0.0-20210506205249-923b5ab0fc1a h1:jmAp/2PZAScNd62lTD github.com/google/pprof v0.0.0-20210506205249-923b5ab0fc1a/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 h1:mV02weKRL81bEnm8A0HT1/CAelMQDBuQIfLw8n+d6xI= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -golang.org/x/arch v0.0.0-20210502124803-cbf565b21d1e h1:pv3V0NlNSh5Q6AX/StwGLBjcLS7UN4m4Gq+V+uSecqM= -golang.org/x/arch v0.0.0-20210502124803-cbf565b21d1e/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1 h1:MwxAfiDvuwX8Nnnc6iRDhzyMyyc2tz5tYyCP/pZcPCg= +golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/mod v0.5.1-0.20210827163434-4029241eb1d5 h1:BJ9Nc92Yf5inqB18HHrMgflMJKHraE07Z29Vjc+Z/Mk= -golang.org/x/mod v0.5.1-0.20210827163434-4029241eb1d5/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.5.1-0.20210830214625-1b1db11ec8f4 h1:7Qds88gNaRx0Dz/1wOwXlR7asekh1B1u26wEwN6FcEI= +golang.org/x/mod v0.5.1-0.20210830214625-1b1db11ec8f4/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e h1:XMgFehsDnnLGtjvjOfqWSUzt0alpTR1RSEuznObga2c= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20210503060354-a79de5458b56 h1:b8jxX3zqjpqb2LklXPzKSGJhzyxCOZSz8ncv8Nv+y7w= -golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY= +golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE= +golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/tools v0.1.6-0.20210809225032-337cebd2c151 h1:jHjT6WuVKEMzjJgrS1+r1wk54oxwqumUnvtn0QZXyXE= golang.org/x/tools v0.1.6-0.20210809225032-337cebd2c151/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= diff --git a/src/cmd/vendor/golang.org/x/arch/arm64/arm64asm/plan9x.go b/src/cmd/vendor/golang.org/x/arch/arm64/arm64asm/plan9x.go index 3aaf0b2a30..f4eef8c0a7 100644 --- a/src/cmd/vendor/golang.org/x/arch/arm64/arm64asm/plan9x.go +++ b/src/cmd/vendor/golang.org/x/arch/arm64/arm64asm/plan9x.go @@ -500,7 +500,7 @@ SHA256SU0 SHA256SU1 `) -// floating point instrcutions without "F" prefix. +// floating point instructions without "F" prefix. var fOpsWithoutFPrefix = map[Op]bool{ LDP: true, STP: true, diff --git a/src/cmd/vendor/golang.org/x/mod/zip/zip.go b/src/cmd/vendor/golang.org/x/mod/zip/zip.go index 40606d6da5..ca0f7ad42f 100644 --- a/src/cmd/vendor/golang.org/x/mod/zip/zip.go +++ b/src/cmd/vendor/golang.org/x/mod/zip/zip.go @@ -571,8 +571,8 @@ func CreateFromDir(w io.Writer, m module.Version, dir string) (err error) { // CreateFromVCS creates a module zip file for module m from the contents of a // VCS repository stored locally. The zip content is written to w. // -// repo must be an absolute path to the base of the repository, such as -// "/Users/some-user/my-repo". +// repoRoot must be an absolute path to the base of the repository, such as +// "/Users/some-user/some-repo". // // revision is the revision of the repository to create the zip from. Examples // include HEAD or SHA sums for git repositories. @@ -580,32 +580,45 @@ func CreateFromDir(w io.Writer, m module.Version, dir string) (err error) { // subdir must be the relative path from the base of the repository, such as // "sub/dir". To create a zip from the base of the repository, pass an empty // string. -func CreateFromVCS(w io.Writer, m module.Version, repo, revision, subdir string) (err error) { +// +// If CreateFromVCS returns ErrUnrecognizedVCS, consider falling back to +// CreateFromDir. +func CreateFromVCS(w io.Writer, m module.Version, repoRoot, revision, subdir string) (err error) { defer func() { if zerr, ok := err.(*zipError); ok { - zerr.path = repo + zerr.path = repoRoot } else if err != nil { - err = &zipError{verb: "create zip from version control system", path: repo, err: err} + err = &zipError{verb: "create zip from version control system", path: repoRoot, err: err} } }() var filesToCreate []File switch { - case isGitRepo(repo): - files, err := filesInGitRepo(repo, revision, subdir) + case isGitRepo(repoRoot): + files, err := filesInGitRepo(repoRoot, revision, subdir) if err != nil { return err } filesToCreate = files default: - return fmt.Errorf("%q does not use a recognised version control system", repo) + return &UnrecognizedVCSError{RepoRoot: repoRoot} } return Create(w, m, filesToCreate) } +// UnrecognizedVCSError indicates that no recognized version control system was +// found in the given directory. +type UnrecognizedVCSError struct { + RepoRoot string +} + +func (e *UnrecognizedVCSError) Error() string { + return fmt.Sprintf("could not find a recognized version control system at %q", e.RepoRoot) +} + // filterGitIgnored filters out any files that are git ignored in the directory. func filesInGitRepo(dir, rev, subdir string) ([]File, error) { stderr := bytes.Buffer{} diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 10c4b3ad21..ec75599d09 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -18,7 +18,7 @@ github.com/google/pprof/third_party/svgpan # github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 ## explicit github.com/ianlancetaylor/demangle -# golang.org/x/arch v0.0.0-20210502124803-cbf565b21d1e +# golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1 ## explicit; go 1.17 golang.org/x/arch/arm/armasm golang.org/x/arch/arm64/arm64asm @@ -28,7 +28,7 @@ golang.org/x/arch/x86/x86asm ## explicit; go 1.17 golang.org/x/crypto/ed25519 golang.org/x/crypto/ed25519/internal/edwards25519 -# golang.org/x/mod v0.5.1-0.20210827163434-4029241eb1d5 +# golang.org/x/mod v0.5.1-0.20210830214625-1b1db11ec8f4 ## explicit; go 1.17 golang.org/x/mod/internal/lazyregexp golang.org/x/mod/modfile @@ -45,7 +45,7 @@ golang.org/x/sys/internal/unsafeheader golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows -# golang.org/x/term v0.0.0-20210503060354-a79de5458b56 +# golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b ## explicit; go 1.17 golang.org/x/term # golang.org/x/tools v0.1.6-0.20210809225032-337cebd2c151 diff --git a/src/go.mod b/src/go.mod index 3c45b8b073..a4a6c4f05d 100644 --- a/src/go.mod +++ b/src/go.mod @@ -6,5 +6,5 @@ require ( golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 golang.org/x/net v0.0.0-20210825183410-e898025ed96a golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e // indirect - golang.org/x/text v0.3.7-0.20210503195748-5c7c50ebbd4f // indirect + golang.org/x/text v0.3.7 // indirect ) diff --git a/src/go.sum b/src/go.sum index c8ecc70460..1c419b90ba 100644 --- a/src/go.sum +++ b/src/go.sum @@ -4,5 +4,5 @@ golang.org/x/net v0.0.0-20210825183410-e898025ed96a h1:bRuuGXV8wwSdGTB+CtJf+FjgO golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e h1:XMgFehsDnnLGtjvjOfqWSUzt0alpTR1RSEuznObga2c= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.3.7-0.20210503195748-5c7c50ebbd4f h1:yQJrRE0hDxDFmZLlRaw+3vusO4fwNHgHIjUOMO7bHYI= -golang.org/x/text v0.3.7-0.20210503195748-5c7c50ebbd4f/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index 0ba3def242..3dc867957e 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -22,7 +22,7 @@ golang.org/x/net/route # golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e ## explicit; go 1.17 golang.org/x/sys/cpu -# golang.org/x/text v0.3.7-0.20210503195748-5c7c50ebbd4f +# golang.org/x/text v0.3.7 ## explicit; go 1.17 golang.org/x/text/secure/bidirule golang.org/x/text/transform -- GitLab From 2a463a22cee8ddbd4801acd2ef34eefa551a718a Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Mon, 21 Jun 2021 20:23:36 -0700 Subject: [PATCH 0983/2500] net/http: close request body after recovering from a handler panic When recovering from a panic in a HTTP handler, close the request body before closing the *conn, ensuring that the *conn's bufio.Reader is safe to recycle. Fixes #46866. Change-Id: I3fe304592e3b423a0970727d68bc1229c3752939 Reviewed-on: https://go-review.googlesource.com/c/go/+/329922 Trust: Damien Neil Run-TryBot: Damien Neil TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/net/http/server.go | 10 ++++++++++ src/net/http/transport_test.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/net/http/server.go b/src/net/http/server.go index 5b113cff97..4d0ce5619f 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -1794,6 +1794,7 @@ func isCommonNetReadError(err error) bool { func (c *conn) serve(ctx context.Context) { c.remoteAddr = c.rwc.RemoteAddr().String() ctx = context.WithValue(ctx, LocalAddrContextKey, c.rwc.LocalAddr()) + var inFlightResponse *response defer func() { if err := recover(); err != nil && err != ErrAbortHandler { const size = 64 << 10 @@ -1801,7 +1802,14 @@ func (c *conn) serve(ctx context.Context) { buf = buf[:runtime.Stack(buf, false)] c.server.logf("http: panic serving %v: %v\n%s", c.remoteAddr, err, buf) } + if inFlightResponse != nil { + inFlightResponse.cancelCtx() + } if !c.hijacked() { + if inFlightResponse != nil { + inFlightResponse.conn.r.abortPendingRead() + inFlightResponse.reqBody.Close() + } c.close() c.setState(c.rwc, StateClosed, runHooks) } @@ -1926,7 +1934,9 @@ func (c *conn) serve(ctx context.Context) { // in parallel even if their responses need to be serialized. // But we're not going to implement HTTP pipelining because it // was never deployed in the wild and the answer is HTTP/2. + inFlightResponse = w serverHandler{c.server}.ServeHTTP(w, w.req) + inFlightResponse = nil w.cancelCtx() if c.hijacked() { return diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go index eeaa492644..0cdd946de4 100644 --- a/src/net/http/transport_test.go +++ b/src/net/http/transport_test.go @@ -6512,3 +6512,32 @@ func TestCancelRequestWhenSharingConnection(t *testing.T) { close(r2c) wg.Wait() } + +func TestHandlerAbortRacesBodyRead(t *testing.T) { + setParallel(t) + defer afterTest(t) + + ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) { + go io.Copy(io.Discard, req.Body) + panic(ErrAbortHandler) + })) + defer ts.Close() + + var wg sync.WaitGroup + for i := 0; i < 2; i++ { + wg.Add(1) + go func() { + defer wg.Done() + for j := 0; j < 10; j++ { + const reqLen = 6 * 1024 * 1024 + req, _ := NewRequest("POST", ts.URL, &io.LimitedReader{R: neverEnding('x'), N: reqLen}) + req.ContentLength = reqLen + resp, _ := ts.Client().Transport.RoundTrip(req) + if resp != nil { + resp.Body.Close() + } + } + }() + } + wg.Wait() +} -- GitLab From acc2957bc9873ab7e65942045830a3dc0592eda2 Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Thu, 5 Aug 2021 19:26:21 -0700 Subject: [PATCH 0984/2500] net/http: fix hang in probing for a zero-length request body Fix a hang that occurs when making a request and all of the following apply: * The request method is one of GET, HEAD, DELETE, OPTIONS, PROPFIND, or SEARCH. * The Request.Body is non-nil. * The content length is not set, or is set to -1. * Transfer-Encoding: chunked is not set. * The request body does not respond to a read within 200ms. In this case, we give up on probing for a zero-length body and send the request while the probe completes in the background. Fix a bug in the io.Reader wrapping the in-flight probe: It should return io.EOF after the probe completes, but does not. Fixes #47568. Change-Id: I7f9188c96e1210055df68424081af927006e4816 Reviewed-on: https://go-review.googlesource.com/c/go/+/340256 Trust: Damien Neil Run-TryBot: Damien Neil TryBot-Result: Go Bot Reviewed-by: Ingo Oeser Reviewed-by: Brad Fitzpatrick --- src/net/http/client_test.go | 44 +++++++++++++++++++++++++++++++++++++ src/net/http/transfer.go | 4 ++++ 2 files changed, 48 insertions(+) diff --git a/src/net/http/client_test.go b/src/net/http/client_test.go index 01d605c351..05ed2268b5 100644 --- a/src/net/http/client_test.go +++ b/src/net/http/client_test.go @@ -2082,3 +2082,47 @@ func (b *issue40382Body) Close() error { } return nil } + +func TestProbeZeroLengthBody(t *testing.T) { + setParallel(t) + defer afterTest(t) + reqc := make(chan struct{}) + cst := newClientServerTest(t, false, HandlerFunc(func(w ResponseWriter, r *Request) { + close(reqc) + if _, err := io.Copy(w, r.Body); err != nil { + t.Errorf("error copying request body: %v", err) + } + })) + defer cst.close() + + bodyr, bodyw := io.Pipe() + var gotBody string + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + req, _ := NewRequest("GET", cst.ts.URL, bodyr) + res, err := cst.c.Do(req) + b, err := io.ReadAll(res.Body) + if err != nil { + t.Error(err) + } + gotBody = string(b) + }() + + select { + case <-reqc: + // Request should be sent after trying to probe the request body for 200ms. + case <-time.After(60 * time.Second): + t.Errorf("request not sent after 60s") + } + + // Write the request body and wait for the request to complete. + const content = "body" + bodyw.Write([]byte(content)) + bodyw.Close() + wg.Wait() + if gotBody != content { + t.Fatalf("server got body %q, want %q", gotBody, content) + } +} diff --git a/src/net/http/transfer.go b/src/net/http/transfer.go index 85c2e5a360..5ff89cc17f 100644 --- a/src/net/http/transfer.go +++ b/src/net/http/transfer.go @@ -212,6 +212,7 @@ func (t *transferWriter) probeRequestBody() { rres.b = buf[0] } t.ByteReadCh <- rres + close(t.ByteReadCh) }(t.Body) timer := time.NewTimer(200 * time.Millisecond) select { @@ -1072,6 +1073,9 @@ func (fr finishAsyncByteRead) Read(p []byte) (n int, err error) { if n == 1 { p[0] = rres.b } + if err == nil { + err = io.EOF + } return } -- GitLab From 7609b5070174905478ba33876679c9b592367a5c Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Thu, 2 Sep 2021 10:50:42 -0400 Subject: [PATCH 0985/2500] go/types: systematic detection of missing instantiation This is a port of CL 346471 to go/types. Additionally, CheckExpr was updated for the new API to explicitly allow generic expressions. The error messages in issue39634.go2 are different because go/parser produces an IndexExpr with BadExpr index value, for backward compatibility. Change-Id: I725926de183a016381513fe0e750d1280688ce29 Reviewed-on: https://go-review.googlesource.com/c/go/+/347391 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/builtins.go | 2 +- src/go/types/call.go | 19 ++++--- src/go/types/eval.go | 11 +++-- src/go/types/expr.go | 49 ++++++++++++++++--- src/go/types/index.go | 10 +++- src/go/types/stmt.go | 4 +- src/go/types/testdata/examples/types.go2 | 1 + .../types/testdata/fixedbugs/issue39634.go2 | 3 ++ 8 files changed, 74 insertions(+), 25 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 698435bc20..ecf7b89275 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -772,7 +772,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b var t operand x1 := x for _, arg := range call.Args { - check.rawExpr(x1, arg, nil) // permit trace for types, e.g.: new(trace(T)) + check.rawExpr(x1, arg, nil, false) // permit trace for types, e.g.: new(trace(T)) check.dump("%v: %s", x1.Pos(), x1) x1 = &t // use incoming x only for first argument } diff --git a/src/go/types/call.go b/src/go/types/call.go index 78c81e13e9..8a80cbbd87 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -89,8 +89,9 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { check.record(x) } else { - check.exprOrType(x, call.Fun) + check.exprOrType(x, call.Fun, true) } + // x.typ map be generic switch x.mode { case invalid: @@ -100,6 +101,10 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { case typexpr: // conversion + check.nonGeneric(x) + if x.mode == invalid { + return conversion + } T := x.typ x.mode = invalid switch n := len(call.Args); n { @@ -128,6 +133,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { return conversion case builtin: + // no need to check for non-genericity here id := x.id if !check.builtin(x, call, id) { x.mode = invalid @@ -141,6 +147,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { } // ordinary function/method call + // signature may be generic cgocall := x.mode == cgofunc sig := asSignature(x.typ) @@ -478,15 +485,11 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { } } - check.exprOrType(x, e.X) + check.exprOrType(x, e.X, false) if x.mode == invalid { goto Error } - if x.mode == typexpr { - x.typ = check.varType(e.X) - } - obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel) if obj == nil { switch { @@ -722,7 +725,7 @@ func (check *Checker) use(arg ...ast.Expr) { // The nil check below is necessary since certain AST fields // may legally be nil (e.g., the ast.SliceExpr.High field). if e != nil { - check.rawExpr(&x, e, nil) + check.rawExpr(&x, e, nil, false) } } } @@ -754,7 +757,7 @@ func (check *Checker) useLHS(arg ...ast.Expr) { } } } - check.rawExpr(&x, e, nil) + check.rawExpr(&x, e, nil, false) if v != nil { v.used = v_used // restore v.used } diff --git a/src/go/types/eval.go b/src/go/types/eval.go index 51259604c9..c8bb005eb6 100644 --- a/src/go/types/eval.go +++ b/src/go/types/eval.go @@ -35,9 +35,10 @@ func Eval(fset *token.FileSet, pkg *Package, pos token.Pos, expr string) (_ Type return info.Types[node], err } -// CheckExpr type checks the expression expr as if it had appeared at -// position pos of package pkg. Type information about the expression -// is recorded in info. +// CheckExpr type checks the expression expr as if it had appeared at position +// pos of package pkg. Type information about the expression is recorded in +// info. The expression may be an uninstantiated parameterized function or +// type. // // If pkg == nil, the Universe scope is used and the provided // position pos is ignored. If pkg != nil, and pos is invalid, @@ -91,8 +92,8 @@ func CheckExpr(fset *token.FileSet, pkg *Package, pos token.Pos, expr ast.Expr, // evaluate node var x operand - check.rawExpr(&x, expr, nil) - check.processDelayed(0) // incl. all functions + check.rawExpr(&x, expr, nil, true) // allow generic expressions + check.processDelayed(0) // incl. all functions check.recordUntyped() return nil diff --git a/src/go/types/expr.go b/src/go/types/expr.go index e574156562..5ca4edebcb 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -1059,8 +1059,10 @@ const ( // rawExpr typechecks expression e and initializes x with the expression // value or type. If an error occurred, x.mode is set to invalid. // If hint != nil, it is the type of a composite literal element. +// If allowGeneric is set, the operand type may be an uninstantiated +// parameterized type or function value. // -func (check *Checker) rawExpr(x *operand, e ast.Expr, hint Type) exprKind { +func (check *Checker) rawExpr(x *operand, e ast.Expr, hint Type, allowGeneric bool) exprKind { if trace { check.trace(e.Pos(), "expr %s", e) check.indent++ @@ -1071,11 +1073,40 @@ func (check *Checker) rawExpr(x *operand, e ast.Expr, hint Type) exprKind { } kind := check.exprInternal(x, e, hint) + + if !allowGeneric { + check.nonGeneric(x) + } + check.record(x) return kind } +// If x is a generic function or type, nonGeneric reports an error and invalidates x.mode and x.typ. +// Otherwise it leaves x alone. +func (check *Checker) nonGeneric(x *operand) { + if x.mode == invalid || x.mode == novalue { + return + } + var what string + switch t := x.typ.(type) { + case *Named: + if isGeneric(t) { + what = "type" + } + case *Signature: + if t.tparams != nil { + what = "function" + } + } + if what != "" { + check.errorf(x.expr, _Todo, "cannot use generic %s %s without instantiation", what, x.expr) + x.mode = invalid + x.typ = Typ[Invalid] + } +} + // exprInternal contains the core of type checking of expressions. // Must only be called by rawExpr. // @@ -1354,7 +1385,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { x.typ = typ case *ast.ParenExpr: - kind := check.rawExpr(x, e.X, nil) + kind := check.rawExpr(x, e.X, nil, false) x.expr = e return kind @@ -1405,7 +1436,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { return check.callExpr(x, e) case *ast.StarExpr: - check.exprOrType(x, e.X) + check.exprOrType(x, e.X, false) switch x.mode { case invalid: goto Error @@ -1525,14 +1556,14 @@ func (check *Checker) typeAssertion(at positioner, x *operand, xtyp *Interface, // If an error occurred, x.mode is set to invalid. // func (check *Checker) expr(x *operand, e ast.Expr) { - check.rawExpr(x, e, nil) + check.rawExpr(x, e, nil, false) check.exclude(x, 1<= 0 switch typ := under(x.typ).(type) { diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index e5830bfdd4..92542597c5 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -174,7 +174,7 @@ func (check *Checker) suspendedCall(keyword string, call *ast.CallExpr) { var x operand var msg string var code errorCode - switch check.rawExpr(&x, call, nil) { + switch check.rawExpr(&x, call, nil, false) { case conversion: msg = "requires function call, not conversion" code = _InvalidDefer @@ -391,7 +391,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { // function and method calls and receive operations can appear // in statement context. Such statements may be parenthesized." var x operand - kind := check.rawExpr(&x, s.X, nil) + kind := check.rawExpr(&x, s.X, nil, false) var msg string var code errorCode switch x.mode { diff --git a/src/go/types/testdata/examples/types.go2 b/src/go/types/testdata/examples/types.go2 index 1aebb411c6..6f6f95e781 100644 --- a/src/go/types/testdata/examples/types.go2 +++ b/src/go/types/testdata/examples/types.go2 @@ -102,6 +102,7 @@ func _() { // Generic types cannot be used without instantiation. var _ T // ERROR cannot use generic type T +var _ = T /* ERROR cannot use generic type T */ (0) // In type context, generic (parameterized) types cannot be parenthesized before // being instantiated. See also NOTES entry from 12/4/2019. diff --git a/src/go/types/testdata/fixedbugs/issue39634.go2 b/src/go/types/testdata/fixedbugs/issue39634.go2 index f307ee9c9e..c46d38f8c4 100644 --- a/src/go/types/testdata/fixedbugs/issue39634.go2 +++ b/src/go/types/testdata/fixedbugs/issue39634.go2 @@ -85,6 +85,9 @@ var x T25 /* ERROR without instantiation */ .m1 // crash 26 type T26 = interface{ F26[ /* ERROR methods cannot have type parameters */ Z any]() } +// The error messages on the line below differ from types2 because for backward +// compatibility go/parser must produce an IndexExpr with BadExpr index for the +// expression F26[]. func F26[Z any]() T26 { return F26[] /* ERROR operand */ } // crash 27 -- GitLab From 5bc273aca54391177ad3f43a54d22021deb99114 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 17 Aug 2021 13:25:12 -0700 Subject: [PATCH 0986/2500] [dev.fuzz] internal/fuzz: minimize inputs that expand coverage When a fuzz worker discovers an input that activates coverage counters that weren't previously activated, it sends that input back to the coordinator, as before. If the coordinator also finds that input provides new coverage (that is, some other input hasn't won the race), the coordinator now sends the input back to workers for minimization. The minimization procedure now supports minimizing these interesting inputs. It attempts to find smaller inputs that preserve at least one new coverage bit. If minimization succeeds, the coordinator adds the smaller input to the corpus instead of the original. If minimization fails, the coordinator adds the original input. If minimization finds that the original input didn't provide new coverage after all (for example, a counter was activated by an unrelated background goroutine and was considered flaky), the input is ignored and not recorded. Change-Id: I81d98d6ec28abb0ac2a476f73480ceeaff674c08 Reviewed-on: https://go-review.googlesource.com/c/go/+/342997 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- .../script/test_fuzz_minimize_interesting.txt | 112 +++++++ src/internal/fuzz/fuzz.go | 301 +++++++++++------- src/internal/fuzz/minimize.go | 16 +- src/internal/fuzz/minimize_test.go | 26 +- src/internal/fuzz/queue.go | 71 +++++ src/internal/fuzz/queue_test.go | 58 ++++ src/internal/fuzz/worker.go | 162 +++++++--- 7 files changed, 580 insertions(+), 166 deletions(-) create mode 100644 src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt create mode 100644 src/internal/fuzz/queue.go create mode 100644 src/internal/fuzz/queue_test.go diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt b/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt new file mode 100644 index 0000000000..5e1d90d8d9 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt @@ -0,0 +1,112 @@ +# TODO(jayconrod): support shared memory on more platforms. +[!darwin] [!linux] [!windows] skip + +# Instrumentation only supported on 64-bit architectures. +[!amd64] [!arm64] skip + +# Test that when an interesting value is discovered (one that expands coverage), +# the fuzzing engine minimizes it before writing it to the cache. +# +# The program below starts with a seed value of length 100, but more coverage +# will be found for any value other than the seed. We should end with a value +# in the cache of length 1 (the minimizer currently does not produce empty +# strings). check_cache.go confirms that. +# +# We would like to verify that ALL values in the cache were minimized to a +# length of 1, but this isn't always possible when new coverage is found in +# functions called by testing or internal/fuzz in the background. + +go test -c -fuzz=. # Build using shared build cache for speed. +env GOCACHE=$WORK/gocache +exec ./fuzz.test$GOEXE -test.fuzzcachedir=$GOCACHE/fuzz -test.fuzz=. -test.fuzztime=1000x +go run check_cache.go $GOCACHE/fuzz/FuzzMin + +-- go.mod -- +module fuzz + +go 1.17 +-- fuzz_test.go -- +package fuzz + +import ( + "bytes" + "testing" +) + +func FuzzMin(f *testing.F) { + seed := bytes.Repeat([]byte("a"), 20) + f.Add(seed) + f.Fuzz(func(t *testing.T, buf []byte) { + if bytes.Equal(buf, seed) { + return + } + if n := sum(buf); n < 0 { + t.Error("sum cannot be negative") + } + }) +} + +func sum(buf []byte) int { + n := 0 + for _, b := range buf { + n += int(b) + } + return n +} +-- check_cache.go -- +//go:build ignore +// +build ignore + +// check_cache.go checks that each file in the cached corpus has a []byte +// of length at most 1. This verifies that at least one cached input is minimized. +package main + +import ( + "bytes" + "fmt" + "os" + "path/filepath" + "regexp" + "strconv" +) + +func main() { + dir := os.Args[1] + ents, err := os.ReadDir(dir) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + for _, ent := range ents { + name := filepath.Join(dir, ent.Name()) + if good, err := checkCacheFile(name); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } else if good { + os.Exit(0) + } + } + fmt.Fprintln(os.Stderr, "no cached inputs were minimized") + os.Exit(1) +} + +func checkCacheFile(name string) (good bool, err error) { + data, err := os.ReadFile(name) + if err != nil { + return false, err + } + for _, line := range bytes.Split(data, []byte("\n")) { + m := valRe.FindSubmatch(line) + if m == nil { + continue + } + if s, err := strconv.Unquote(string(m[1])); err != nil { + return false, err + } else if len(s) <= 1 { + return true, nil + } + } + return false, nil +} + +var valRe = regexp.MustCompile(`^\[\]byte\(([^)]+)\)$`) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 9a9a4564c2..7213a08d50 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -109,7 +109,6 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err fuzzCtx, cancelWorkers := context.WithCancel(ctx) defer cancelWorkers() doneC := ctx.Done() - inputC := c.inputC // stop is called when a worker encounters a fatal error. var fuzzErr error @@ -130,7 +129,6 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err stopping = true cancelWorkers() doneC = nil - inputC = nil } // Ensure that any crash we find is written to the corpus, even if an error @@ -189,21 +187,37 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err // Do not return until all workers have terminated. We avoid a deadlock by // receiving messages from workers even after ctx is cancelled. activeWorkers := len(workers) - input, ok := c.nextInput() - if !ok { - panic("no input") - } statTicker := time.NewTicker(3 * time.Second) defer statTicker.Stop() defer c.logStats() for { + var inputC chan fuzzInput + input, ok := c.peekInput() + if ok && crashMinimizing == nil && !stopping { + inputC = c.inputC + } + + var minimizeC chan fuzzMinimizeInput + minimizeInput, ok := c.peekMinimizeInput() + if ok && !stopping { + minimizeC = c.minimizeC + } + select { case <-doneC: // Interrupted, cancelled, or timed out. // stop sets doneC to nil so we don't busy wait here. stop(ctx.Err()) + case err := <-errC: + // A worker terminated, possibly after encountering a fatal error. + stop(err) + activeWorkers-- + if activeWorkers == 0 { + return fuzzErr + } + case result := <-c.resultC: // Received response from worker. c.updateStats(result) @@ -222,9 +236,8 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err // Send it back to a worker for minimization. Disable inputC so // other workers don't continue fuzzing. crashMinimizing = &result - inputC = nil fmt.Fprintf(c.opts.Log, "found a crash, minimizing...\n") - c.minimizeC <- c.minimizeInputForResult(result) + c.queueForMinimization(result, nil) } else if !crashWritten { // Found a crasher that's either minimized or not minimizable. // Write to corpus and stop. @@ -251,53 +264,23 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err stop(err) } } else if result.coverageData != nil { - newBitCount := c.updateCoverage(result.coverageData) - if newBitCount > 0 && !c.coverageOnlyRun() { - // Found an interesting value that expanded coverage. - // This is not a crasher, but we should add it to the - // on-disk corpus, and prioritize it for future fuzzing. - // TODO(jayconrod, katiehockman): Prioritize fuzzing these - // values which expanded coverage, perhaps based on the - // number of new edges that this result expanded. - // TODO(jayconrod, katiehockman): Don't write a value that's already - // in the corpus. - c.interestingCount++ - c.corpus.entries = append(c.corpus.entries, result.entry) - if opts.CacheDir != "" { - if _, err := writeToCorpus(result.entry.Data, opts.CacheDir); err != nil { - stop(err) - } - } - if printDebugInfo() { - fmt.Fprintf( - c.opts.Log, - "DEBUG new interesting input, elapsed: %s, id: %s, parent: %s, gen: %d, new bits: %d, total bits: %d, size: %d, exec time: %s\n", - time.Since(c.startTime), - result.entry.Name, - result.entry.Parent, - result.entry.Generation, - newBitCount, - countBits(c.coverageMask), - len(result.entry.Data), - result.entryDuration, - ) - } - } else if c.coverageOnlyRun() { - c.covOnlyInputs-- + if c.coverageOnlyRun() { if printDebugInfo() { fmt.Fprintf( c.opts.Log, "DEBUG processed an initial input, elapsed: %s, id: %s, new bits: %d, size: %d, exec time: %s\n", time.Since(c.startTime), result.entry.Parent, - newBitCount, + countBits(diffCoverage(c.coverageMask, result.coverageData)), len(result.entry.Data), result.entryDuration, ) } + c.updateCoverage(result.coverageData) + c.covOnlyInputs-- if c.covOnlyInputs == 0 { // The coordinator has finished getting a baseline for - // coverage. Tell all of the workers to inialize their + // coverage. Tell all of the workers to initialize their // baseline coverage data (by setting interestingCount // to 0). c.interestingCount = 0 @@ -311,6 +294,45 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err ) } } + } else if keepCoverage := diffCoverage(c.coverageMask, result.coverageData); keepCoverage != nil { + // Found a value that expanded coverage. + // It's not a crasher, but we may want to add it to the on-disk + // corpus and prioritize it for future fuzzing. + // TODO(jayconrod, katiehockman): Prioritize fuzzing these + // values which expanded coverage, perhaps based on the + // number of new edges that this result expanded. + // TODO(jayconrod, katiehockman): Don't write a value that's already + // in the corpus. + if printDebugInfo() { + fmt.Fprintf( + c.opts.Log, + "DEBUG new interesting input, elapsed: %s, id: %s, parent: %s, gen: %d, new bits: %d, total bits: %d, size: %d, exec time: %s\n", + time.Since(c.startTime), + result.entry.Name, + result.entry.Parent, + result.entry.Generation, + countBits(keepCoverage), + countBits(c.coverageMask), + len(result.entry.Data), + result.entryDuration, + ) + } + if !result.minimizeAttempted && crashMinimizing == nil && c.canMinimize() { + // Send back to workers to find a smaller value that preserves + // at least one new coverage bit. + c.queueForMinimization(result, keepCoverage) + } else { + // Update the coordinator's coverage mask and save the value. + if opts.CacheDir != "" { + if _, err := writeToCorpus(result.entry.Data, opts.CacheDir); err != nil { + stop(err) + } + } + c.updateCoverage(keepCoverage) + c.corpus.entries = append(c.corpus.entries, result.entry) + c.inputQueue.enqueue(result.entry) + c.interestingCount++ + } } else { if printDebugInfo() { fmt.Fprintf( @@ -323,35 +345,14 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err } } } - if inputC == nil && crashMinimizing == nil && !stopping && !c.coverageOnlyRun() { - // Re-enable inputC if it was disabled earlier because we hit the limit - // on the number of inputs to fuzz (nextInput returned false). Workers - // can do less work than requested, so after receiving a result above, - // we might be below the limit now. - if input, ok = c.nextInput(); ok { - inputC = c.inputC - } - } - - case err := <-errC: - // A worker terminated, possibly after encountering a fatal error. - stop(err) - activeWorkers-- - if activeWorkers == 0 { - return fuzzErr - } case inputC <- input: - // Send the next input to any worker. - if c.corpusIndex == 0 && c.coverageOnlyRun() { - // The coordinator is currently trying to run all of the corpus - // entries to gather baseline coverage data, and all of the - // inputs have been passed to inputC. Block any more inputs from - // being passed to the workers for now. - inputC = nil - } else if input, ok = c.nextInput(); !ok { - inputC = nil - } + // Sent the next input to a worker. + c.sentInput(input) + + case minimizeC <- minimizeInput: + // Sent the next input for minimization to a worker. + c.sentMinimizeInput(minimizeInput) case <-statTicker.C: c.logStats() @@ -484,6 +485,12 @@ type fuzzMinimizeInput struct { // timeout is the time to spend minimizing this input. // A zero timeout means no limit. timeout time.Duration + + // keepCoverage is a set of coverage bits that entry found that were not in + // the coordinator's combined set. When minimizing, the worker should find an + // input that preserves at least one of these bits. keepCoverage is nil for + // crashing inputs. + keepCoverage []byte } // coordinator holds channels that workers can use to communicate with @@ -515,7 +522,8 @@ type coordinator struct { interestingCount int64 // covOnlyInputs is the number of entries in the corpus which still need to - // be sent to a worker to gather baseline coverage data. + // be received from workers when gathering baseline coverage. + // See coverageOnlyRun. covOnlyInputs int // duration is the time spent fuzzing inside workers, not counting time @@ -530,15 +538,20 @@ type coordinator struct { // generated values that workers reported as interesting. corpus corpus - // corpusIndex is the next value to send to workers. - // TODO(jayconrod,katiehockman): need a scheduling algorithm that chooses - // which corpus value to send next (or generates something new). - corpusIndex int - // typesAreMinimizable is true if one or more of the types of fuzz function's // parameters can be minimized. typesAreMinimizable bool + // inputQueue is a queue of inputs that workers should try fuzzing. This is + // initially populated from the seed corpus and cached inputs. More inputs + // may be added as new coverage is discovered. + inputQueue queue + + // minimizeQueue is a queue of inputs that caused errors or exposed new + // coverage. Workers should attempt to find smaller inputs that do the + // same thing. + minimizeQueue queue + // coverageMask aggregates coverage that was found for all inputs in the // corpus. Each byte represents a single basic execution block. Each set bit // within the byte indicates that an input has triggered that block at least @@ -559,7 +572,6 @@ func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { if err != nil { return nil, err } - covOnlyInputs := len(corpus.entries) if len(corpus.entries) == 0 { var vals []interface{} for _, t := range opts.Types { @@ -571,13 +583,12 @@ func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { corpus.entries = append(corpus.entries, CorpusEntry{Name: name, Data: data, Values: vals}) } c := &coordinator{ - opts: opts, - startTime: time.Now(), - inputC: make(chan fuzzInput), - minimizeC: make(chan fuzzMinimizeInput), - resultC: make(chan fuzzResult), - corpus: corpus, - covOnlyInputs: covOnlyInputs, + opts: opts, + startTime: time.Now(), + inputC: make(chan fuzzInput), + minimizeC: make(chan fuzzMinimizeInput), + resultC: make(chan fuzzResult), + corpus: corpus, } for _, t := range opts.Types { if isMinimizable(t) { @@ -588,17 +599,23 @@ func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { covSize := len(coverage()) if covSize == 0 { + // TODO: improve this warning. This condition happens if the binary was + // built without fuzzing instrumtation (e.g., with 'go test -c'), so the + // warning may not be true. fmt.Fprintf(c.opts.Log, "warning: coverage-guided fuzzing is not supported on this platform\n") c.covOnlyInputs = 0 } else { // Set c.coverageData to a clean []byte full of zeros. c.coverageMask = make([]byte, covSize) - } - - if c.covOnlyInputs > 0 { - // Set c.interestingCount to -1 so the workers know when the coverage - // run is finished and can update their local coverage data. - c.interestingCount = -1 + c.covOnlyInputs = len(c.corpus.entries) + for _, e := range c.corpus.entries { + c.inputQueue.enqueue(e) + } + if c.covOnlyInputs > 0 { + // Set c.interestingCount to -1 so the workers know when the coverage + // run is finished and can update their local coverage data. + c.interestingCount = -1 + } } return c, nil @@ -620,28 +637,47 @@ func (c *coordinator) logStats() { } } -// nextInput returns the next value that should be sent to workers. +// peekInput returns the next value that should be sent to workers. // If the number of executions is limited, the returned value includes -// a limit for one worker. If there are no executions left, nextInput returns +// a limit for one worker. If there are no executions left, peekInput returns // a zero value and false. -func (c *coordinator) nextInput() (fuzzInput, bool) { +// +// peekInput doesn't actually remove the input from the queue. The caller +// must call sentInput after sending the input. +// +// If the input queue is empty and the coverage-only run has completed, +// queue refills it from the corpus. +func (c *coordinator) peekInput() (fuzzInput, bool) { if c.opts.Limit > 0 && c.count+c.countWaiting >= c.opts.Limit { - // Workers already testing all requested inputs. + // Already making the maximum number of calls to the fuzz function. + // Don't send more inputs right now. return fuzzInput{}, false } + if c.inputQueue.len == 0 { + if c.covOnlyInputs > 0 { + // Wait for coverage-only run to finish before sending more inputs. + return fuzzInput{}, false + } + c.refillInputQueue() + } + + entry, ok := c.inputQueue.peek() + if !ok { + panic("input queue empty after refill") + } input := fuzzInput{ - entry: c.corpus.entries[c.corpusIndex], + entry: entry.(CorpusEntry), interestingCount: c.interestingCount, coverageData: make([]byte, len(c.coverageMask)), timeout: workerFuzzDuration, } copy(input.coverageData, c.coverageMask) - c.corpusIndex = (c.corpusIndex + 1) % (len(c.corpus.entries)) if c.coverageOnlyRun() { - // This is a coverage-only run, so this input shouldn't be fuzzed, - // and shouldn't be included in the count of generated values. + // This is a coverage-only run, so this input shouldn't be fuzzed. + // It should count toward the limit set by -fuzztime though. input.coverageOnly = true + input.limit = 1 return input, true } @@ -654,26 +690,60 @@ func (c *coordinator) nextInput() (fuzzInput, bool) { if input.limit > remaining { input.limit = remaining } - c.countWaiting += input.limit } return input, true } -// minimizeInputForResult returns an input for minimization based on the given -// fuzzing result that either caused a failure or expanded coverage. -func (c *coordinator) minimizeInputForResult(result fuzzResult) fuzzMinimizeInput { +// sentInput updates internal counters after an input is sent to c.inputC. +func (c *coordinator) sentInput(input fuzzInput) { + c.inputQueue.dequeue() + c.countWaiting += input.limit +} + +// refillInputQueue refills the input queue from the corpus after it becomes +// empty. +func (c *coordinator) refillInputQueue() { + for _, e := range c.corpus.entries { + c.inputQueue.enqueue(e) + } +} + +// queueForMinimization creates a fuzzMinimizeInput from result and adds it +// to the minimization queue to be sent to workers. +func (c *coordinator) queueForMinimization(result fuzzResult, keepCoverage []byte) { + if result.crasherMsg != "" { + c.minimizeQueue.clear() + } + input := fuzzMinimizeInput{ - entry: result.entry, - crasherMsg: result.crasherMsg, + entry: result.entry, + crasherMsg: result.crasherMsg, + keepCoverage: keepCoverage, } - input.limit = 0 + c.minimizeQueue.enqueue(input) +} + +// peekMinimizeInput returns the next input that should be sent to workers for +// minimization. +func (c *coordinator) peekMinimizeInput() (fuzzMinimizeInput, bool) { + if c.opts.Limit > 0 && c.count+c.countWaiting >= c.opts.Limit { + // Already making the maximum number of calls to the fuzz function. + // Don't send more inputs right now. + return fuzzMinimizeInput{}, false + } + v, ok := c.minimizeQueue.peek() + if !ok { + return fuzzMinimizeInput{}, false + } + input := v.(fuzzMinimizeInput) + if c.opts.MinimizeTimeout > 0 { input.timeout = c.opts.MinimizeTimeout } if c.opts.MinimizeLimit > 0 { input.limit = c.opts.MinimizeLimit } else if c.opts.Limit > 0 { - if result.crasherMsg != "" { + if input.crasherMsg != "" { input.limit = c.opts.Limit } else { input.limit = c.opts.Limit / int64(c.opts.Parallel) @@ -686,10 +756,27 @@ func (c *coordinator) minimizeInputForResult(result fuzzResult) fuzzMinimizeInpu if input.limit > remaining { input.limit = remaining } + return input, true +} + +// sentMinimizeInput removes an input from the minimization queue after it's +// sent to minimizeC. +func (c *coordinator) sentMinimizeInput(input fuzzMinimizeInput) { + c.minimizeQueue.dequeue() c.countWaiting += input.limit - return input } +// coverageOnlyRun returns true while the coordinator is gathering baseline +// coverage data for entries in the corpus. +// +// The coordinator starts in this phase. It doesn't store coverage data in the +// cache with each input because that data would be invalid when counter +// offsets in the test binary change. +// +// When gathering coverage, the coordinator sends each entry to a worker to +// gather coverage for that entry only, without fuzzing or minimizing. This +// phase ends when all workers have finished, and the coordinator has a combined +// coverage map. func (c *coordinator) coverageOnlyRun() bool { return c.covOnlyInputs > 0 } diff --git a/src/internal/fuzz/minimize.go b/src/internal/fuzz/minimize.go index 5164c34845..b3cdd6a11b 100644 --- a/src/internal/fuzz/minimize.go +++ b/src/internal/fuzz/minimize.go @@ -18,7 +18,7 @@ func isMinimizable(t reflect.Type) bool { return false } -func minimizeBytes(v []byte, stillCrashes func(interface{}) bool, shouldStop func() bool) { +func minimizeBytes(v []byte, try func(interface{}) bool, shouldStop func() bool) { // First, try to cut the tail. for n := 1024; n != 0; n /= 2 { for len(v) > n { @@ -26,7 +26,7 @@ func minimizeBytes(v []byte, stillCrashes func(interface{}) bool, shouldStop fun return } candidate := v[:len(v)-n] - if !stillCrashes(candidate) { + if !try(candidate) { break } // Set v to the new value to continue iterating. @@ -43,7 +43,7 @@ func minimizeBytes(v []byte, stillCrashes func(interface{}) bool, shouldStop fun candidate := tmp[:len(v)-1] copy(candidate[:i], v[:i]) copy(candidate[i:], v[i+1:]) - if !stillCrashes(candidate) { + if !try(candidate) { continue } // Update v to delete the value at index i. @@ -63,7 +63,7 @@ func minimizeBytes(v []byte, stillCrashes func(interface{}) bool, shouldStop fun } candidate := tmp[:len(v)-j+i] copy(candidate[i:], v[j:]) - if !stillCrashes(candidate) { + if !try(candidate) { continue } // Update v and reset the loop with the new length. @@ -76,7 +76,7 @@ func minimizeBytes(v []byte, stillCrashes func(interface{}) bool, shouldStop fun return } -func minimizeInteger(v uint, stillCrashes func(interface{}) bool, shouldStop func() bool) { +func minimizeInteger(v uint, try func(interface{}) bool, shouldStop func() bool) { // TODO(rolandshoemaker): another approach could be either unsetting/setting all bits // (depending on signed-ness), or rotating bits? When operating on cast signed integers // this would probably be more complex though. @@ -88,12 +88,12 @@ func minimizeInteger(v uint, stillCrashes func(interface{}) bool, shouldStop fun // advancing the loop, since there is nothing after this check, // and we don't return early because a smaller value could // re-trigger the crash. - stillCrashes(v) + try(v) } return } -func minimizeFloat(v float64, stillCrashes func(interface{}) bool, shouldStop func() bool) { +func minimizeFloat(v float64, try func(interface{}) bool, shouldStop func() bool) { if math.IsNaN(v) { return } @@ -103,7 +103,7 @@ func minimizeFloat(v float64, stillCrashes func(interface{}) bool, shouldStop fu return } minimized = float64(int(v*div)) / div - if !stillCrashes(minimized) { + if !try(minimized) { // Since we are searching from least precision -> highest precision we // can return early since we've already found the smallest value return diff --git a/src/internal/fuzz/minimize_test.go b/src/internal/fuzz/minimize_test.go index bcb0572d19..fa84d2da63 100644 --- a/src/internal/fuzz/minimize_test.go +++ b/src/internal/fuzz/minimize_test.go @@ -9,6 +9,7 @@ package fuzz import ( "context" + "errors" "fmt" "reflect" "testing" @@ -213,7 +214,7 @@ func TestMinimizeInput(t *testing.T) { } count := int64(0) vals := tc.input - success, err := ws.minimizeInput(context.Background(), vals, &count, 0) + success, err := ws.minimizeInput(context.Background(), vals, &count, 0, nil) if !success { t.Errorf("minimizeInput did not succeed") } @@ -229,3 +230,26 @@ func TestMinimizeInput(t *testing.T) { }) } } + +// TestMinimizeInputCoverageError checks that if we're minimizing an interesting +// input (one that we don't expect to cause an error), and the fuzz function +// returns an error, minimizing fails, and we return the error quickly. +func TestMinimizeInputCoverageError(t *testing.T) { + errOhNo := errors.New("ohno") + ws := &workerServer{fuzzFn: func(e CorpusEntry) error { + return errOhNo + }} + keepCoverage := make([]byte, len(coverageSnapshot)) + count := int64(0) + vals := []interface{}{[]byte(nil)} + success, err := ws.minimizeInput(context.Background(), vals, &count, 0, keepCoverage) + if success { + t.Error("unexpected success") + } + if err != errOhNo { + t.Errorf("unexpected error: %v", err) + } + if count != 1 { + t.Errorf("count: got %d, want 1", count) + } +} diff --git a/src/internal/fuzz/queue.go b/src/internal/fuzz/queue.go new file mode 100644 index 0000000000..cf67a28ba7 --- /dev/null +++ b/src/internal/fuzz/queue.go @@ -0,0 +1,71 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fuzz + +// queue holds a growable sequence of inputs for fuzzing and minimization. +// +// For now, this is a simple ring buffer +// (https://en.wikipedia.org/wiki/Circular_buffer). +// +// TODO(golang.org/issue/46224): use a priotization algorithm based on input +// size, previous duration, coverage, and any other metrics that seem useful. +type queue struct { + // elems holds a ring buffer. + // The queue is empty when begin = end. + // The queue is full (until grow is called) when end = begin + N - 1 (mod N) + // where N = cap(elems). + elems []interface{} + head, len int +} + +func (q *queue) cap() int { + return len(q.elems) +} + +func (q *queue) grow() { + oldCap := q.cap() + newCap := oldCap * 2 + if newCap == 0 { + newCap = 8 + } + newElems := make([]interface{}, newCap) + oldLen := q.len + for i := 0; i < oldLen; i++ { + newElems[i] = q.elems[(q.head+i)%oldCap] + } + q.elems = newElems + q.head = 0 +} + +func (q *queue) enqueue(e interface{}) { + if q.len+1 > q.cap() { + q.grow() + } + i := (q.head + q.len) % q.cap() + q.elems[i] = e + q.len++ +} + +func (q *queue) dequeue() (interface{}, bool) { + if q.len == 0 { + return nil, false + } + e := q.elems[q.head] + q.elems[q.head] = nil + q.head = (q.head + 1) % q.cap() + q.len-- + return e, true +} + +func (q *queue) peek() (interface{}, bool) { + if q.len == 0 { + return nil, false + } + return q.elems[q.head], true +} + +func (q *queue) clear() { + *q = queue{} +} diff --git a/src/internal/fuzz/queue_test.go b/src/internal/fuzz/queue_test.go new file mode 100644 index 0000000000..3b179afb57 --- /dev/null +++ b/src/internal/fuzz/queue_test.go @@ -0,0 +1,58 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fuzz + +import "testing" + +func TestQueue(t *testing.T) { + // Zero valued queue should have 0 length and capacity. + var q queue + if n := q.len; n != 0 { + t.Fatalf("empty queue has len %d; want 0", n) + } + if n := q.cap(); n != 0 { + t.Fatalf("empty queue has cap %d; want 0", n) + } + + // As we add elements, len should grow. + N := 32 + for i := 0; i < N; i++ { + q.enqueue(i) + if n := q.len; n != i+1 { + t.Fatalf("after adding %d elements, queue has len %d", i, n) + } + if v, ok := q.peek(); !ok { + t.Fatalf("couldn't peek after adding %d elements", i) + } else if v.(int) != 0 { + t.Fatalf("after adding %d elements, peek is %d; want 0", i, v) + } + } + + // As we remove and add elements, len should shrink and grow. + // We should also remove elements in the same order they were added. + want := 0 + for _, r := range []int{1, 2, 3, 5, 8, 13, 21} { + s := make([]int, 0, r) + for i := 0; i < r; i++ { + if got, ok := q.dequeue(); !ok { + t.Fatalf("after removing %d of %d elements, could not dequeue", i+1, r) + } else if got != want { + t.Fatalf("after removing %d of %d elements, got %d; want %d", i+1, r, got, want) + } else { + s = append(s, got.(int)) + } + want = (want + 1) % N + if n := q.len; n != N-i-1 { + t.Fatalf("after removing %d of %d elements, len is %d; want %d", i+1, r, n, N-i-1) + } + } + for i, v := range s { + q.enqueue(v) + if n := q.len; n != N-r+i+1 { + t.Fatalf("after adding back %d of %d elements, len is %d; want %d", i+1, r, n, n-r+i+1) + } + } + } +} diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 81c5157dab..67ec3c762b 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -207,7 +207,7 @@ func (w *worker) coordinate(ctx context.Context) error { if err != nil { // Error minimizing. Send back the original input. If it didn't cause // an error before, report it as causing an error now. - // TODO(fuzz): double-check this is handled correctly when + // TODO: double-check this is handled correctly when // implementing -keepfuzzing. result = fuzzResult{ entry: input.entry, @@ -235,18 +235,12 @@ func (w *worker) minimize(ctx context.Context, input fuzzMinimizeInput) (min fuz defer cancel() } - min = fuzzResult{ - entry: input.entry, - crasherMsg: input.crasherMsg, - minimizeAttempted: true, - limit: input.limit, - } - args := minimizeArgs{ - Limit: input.limit, - Timeout: input.timeout, + Limit: input.limit, + Timeout: input.timeout, + KeepCoverage: input.keepCoverage, } - minEntry, resp, err := w.client.minimize(ctx, input.entry, args) + entry, resp, err := w.client.minimize(ctx, input.entry, args) if err != nil { // Error communicating with worker. w.stop() @@ -256,7 +250,13 @@ func (w *worker) minimize(ctx context.Context, input fuzzMinimizeInput) (min fuz // will return without error. An error here indicates the worker // may not have been in a good state, but the error won't be meaningful // to the user. Just return the original crasher without logging anything. - return min, nil + return fuzzResult{ + entry: input.entry, + crasherMsg: input.crasherMsg, + coverageData: input.keepCoverage, + minimizeAttempted: true, + limit: input.limit, + }, nil } return fuzzResult{}, fmt.Errorf("fuzzing process terminated unexpectedly while minimizing: %w", w.waitErr) } @@ -265,11 +265,15 @@ func (w *worker) minimize(ctx context.Context, input fuzzMinimizeInput) (min fuz return fuzzResult{}, fmt.Errorf("attempted to minimize but could not reproduce") } - min.crasherMsg = resp.Err - min.count = resp.Count - min.totalDuration = resp.Duration - min.entry = minEntry - return min, nil + return fuzzResult{ + entry: entry, + crasherMsg: resp.Err, + coverageData: resp.CoverageData, + minimizeAttempted: true, + limit: input.limit, + count: resp.Count, + totalDuration: resp.Duration, + }, nil } func (w *worker) isRunning() bool { @@ -470,7 +474,11 @@ func RunFuzzWorker(ctx context.Context, fn func(CorpusEntry) error) error { if err != nil { return err } - srv := &workerServer{workerComm: comm, fuzzFn: fn, m: newMutator()} + srv := &workerServer{ + workerComm: comm, + fuzzFn: fn, + m: newMutator(), + } return srv.serve(ctx) } @@ -494,17 +502,30 @@ type minimizeArgs struct { // Limit is the maximum number of values to test, without spending more time // than Duration. 0 indicates no limit. Limit int64 + + // KeepCoverage is a set of coverage counters the worker should attempt to + // keep in minimized values. When provided, the worker will reject inputs that + // don't cause at least one of these bits to be set. + KeepCoverage []byte } // minimizeResponse contains results from workerServer.minimize. type minimizeResponse struct { // Success is true if the worker found a smaller input, stored in shared // memory, that was "interesting" for the same reason as the original input. + // If minimizeArgs.KeepCoverage was set, the minimized input preserved at + // least one coverage bit and did not cause an error. Otherwise, the + // minimized input caused some error, recorded in Err. Success bool // Err is the error string caused by the value in shared memory, if any. Err string + // CoverageData is the set of coverage bits activated by the minimized value + // in shared memory. When set, it contains at least one bit from KeepCoverage. + // CoverageData will be nil if Err is set or if minimization failed. + CoverageData []byte + // Duration is the time spent minimizing, not including starting or cleaning up. Duration time.Duration @@ -643,6 +664,9 @@ func (ws *workerServer) serve(ctx context.Context) error { // the crashing input with this information, since the PRNG is deterministic. func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzResponse) { if args.CoverageData != nil { + if ws.coverageMask != nil && len(args.CoverageData) != len(ws.coverageMask) { + panic(fmt.Sprintf("unexpected size for CoverageData: got %d, expected %d", len(args.CoverageData), len(ws.coverageMask))) + } ws.coverageMask = args.CoverageData } start := time.Now() @@ -668,50 +692,64 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo panic(err) } - if args.CoverageOnly { + shouldStop := func() bool { + return args.Limit > 0 && mem.header().count >= args.Limit + } + fuzzOnce := func(entry CorpusEntry) (dur time.Duration, cov []byte, errMsg string) { mem.header().count++ - fStart := time.Now() - err := ws.fuzzFn(CorpusEntry{Values: vals}) + start := time.Now() + err := ws.fuzzFn(entry) + dur = time.Since(start) if err != nil { - resp.Err = err.Error() - if resp.Err == "" { - resp.Err = "fuzz function failed with no output" + errMsg = err.Error() + if errMsg == "" { + errMsg = "fuzz function failed with no input" } + return dur, nil, errMsg + } + if ws.coverageMask != nil && countNewCoverageBits(ws.coverageMask, coverageSnapshot) > 0 { + return dur, coverageSnapshot, "" + } + return dur, nil, "" + } + + if args.CoverageOnly { + dur, _, errMsg := fuzzOnce(CorpusEntry{Values: vals}) + if errMsg != "" { + resp.Err = errMsg return resp } - resp.InterestingDuration = time.Since(fStart) + resp.InterestingDuration = dur resp.CoverageData = coverageSnapshot return resp } - if cov := coverage(); len(cov) != len(ws.coverageMask) { - panic(fmt.Sprintf("number of coverage counters changed at runtime: %d, expected %d", len(cov), len(ws.coverageMask))) - } for { select { case <-ctx.Done(): return resp default: - mem.header().count++ ws.m.mutate(vals, cap(mem.valueRef())) - fStart := time.Now() - err := ws.fuzzFn(CorpusEntry{Values: vals}) - fDur := time.Since(fStart) - if err != nil { - resp.Err = err.Error() - if resp.Err == "" { - resp.Err = "fuzz function failed with no output" - } + entry := CorpusEntry{Values: vals} + dur, cov, errMsg := fuzzOnce(entry) + if errMsg != "" { + resp.Err = errMsg return resp } - if countNewCoverageBits(ws.coverageMask, coverageSnapshot) > 0 { - // TODO(jayconrod,katie): minimize this. - resp.CoverageData = coverageSnapshot - resp.InterestingDuration = fDur - return resp + if cov != nil { + // Found new coverage. Before reporting to the coordinator, + // run the same values once more to deflake. + if !shouldStop() { + dur, cov, errMsg = fuzzOnce(entry) + } + if cov != nil { + resp.CoverageData = cov + resp.InterestingDuration = dur + return resp + } } - if args.Limit > 0 && mem.header().count == args.Limit { + if shouldStop() { return resp } } @@ -736,10 +774,12 @@ func (ws *workerServer) minimize(ctx context.Context, args minimizeArgs) (resp m // Minimize the values in vals, then write to shared memory. We only write // to shared memory after completing minimization. If the worker terminates // unexpectedly before then, the coordinator will use the original input. - resp.Success, err = ws.minimizeInput(ctx, vals, &mem.header().count, args.Limit) + resp.Success, err = ws.minimizeInput(ctx, vals, &mem.header().count, args.Limit, args.KeepCoverage) writeToMem(vals, mem) if err != nil { resp.Err = err.Error() + } else if resp.Success { + resp.CoverageData = coverageSnapshot } return resp } @@ -748,17 +788,36 @@ func (ws *workerServer) minimize(ctx context.Context, args minimizeArgs) (resp m // vals, ensuring that each minimization still causes an error in fuzzFn. Before // every call to fuzzFn, it marshals the new vals and writes it to the provided // mem just in case an unrecoverable error occurs. It uses the context to -// determine how long to run, stopping once closed. It returns the last error it -// found. -func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, count *int64, limit int64) (success bool, retErr error) { +// determine how long to run, stopping once closed. It returns a bool +// indicating whether minimization was successful and an error if one was found. +func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, count *int64, limit int64, keepCoverage []byte) (success bool, retErr error) { + wantError := keepCoverage == nil shouldStop := func() bool { - return ctx.Err() != nil || (limit > 0 && *count >= limit) + return ctx.Err() != nil || + (limit > 0 && *count >= limit) || + (retErr != nil && !wantError) } if shouldStop() { return false, nil } + // Check that the original value preserves coverage or causes an error. + // If not, then whatever caused us to think the value was interesting may + // have been a flake, and we can't minimize it. + *count++ + if retErr = ws.fuzzFn(CorpusEntry{Values: vals}); retErr == nil && wantError { + return false, nil + } else if retErr != nil && !wantError { + return false, retErr + } else if keepCoverage != nil && !hasCoverageBit(keepCoverage, coverageSnapshot) { + return false, nil + } + var valI int + // tryMinimized runs the fuzz function with candidate replacing the value + // at index valI. tryMinimized returns whether the input with candidate is + // interesting for the same reason as the original input: it returns + // an error if one was expected, or it preserves coverage. tryMinimized := func(candidate interface{}) bool { prev := vals[valI] // Set vals[valI] to the candidate after it has been @@ -811,12 +870,15 @@ func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, c default: panic("impossible") } + *count++ err := ws.fuzzFn(CorpusEntry{Values: vals}) if err != nil { retErr = err + return wantError + } + if keepCoverage != nil && hasCoverageBit(keepCoverage, coverageSnapshot) { return true } - *count++ vals[valI] = prev return false } @@ -870,7 +932,7 @@ func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, c panic("unreachable") } } - return retErr != nil, retErr + return (wantError || retErr == nil), retErr } func writeToMem(vals []interface{}, mem *sharedMem) { -- GitLab From 9633195ae1e1a545c24eb71202c5c5f8965d2c4a Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Fri, 3 Sep 2021 02:00:01 +0700 Subject: [PATCH 0987/2500] src: do not emit warning when GOROOT_BOOTSTRAP is unset Fixes #48155 Change-Id: I610a20d3af55035bb0b1047509361b204253801e Reviewed-on: https://go-review.googlesource.com/c/go/+/347273 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/make.bash | 7 +++++-- src/make.rc | 11 ++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/make.bash b/src/make.bash index 9ff471d863..3310692a18 100755 --- a/src/make.bash +++ b/src/make.bash @@ -152,14 +152,17 @@ if [ "$1" = "-v" ]; then shift fi +goroot_bootstrap_set=${GOROOT_BOOTSTRAP+"true"} export GOROOT_BOOTSTRAP=${GOROOT_BOOTSTRAP:-$HOME/go1.4} export GOROOT="$(cd .. && pwd)" IFS=$'\n'; for go_exe in $(type -ap go); do if [ ! -x "$GOROOT_BOOTSTRAP/bin/go" ]; then goroot=$(GOROOT='' GOOS='' GOARCH='' "$go_exe" env GOROOT) if [ "$goroot" != "$GOROOT" ]; then - printf 'WARNING: %s does not exist, found %s from env\n' "$GOROOT_BOOTSTRAP/bin/go" "$go_exe" >&2 - printf 'WARNING: set %s as GOROOT_BOOTSTRAP\n' "$goroot" >&2 + if [ "$goroot_bootstrap_set" = "true" ]; then + printf 'WARNING: %s does not exist, found %s from env\n' "$GOROOT_BOOTSTRAP/bin/go" "$go_exe" >&2 + printf 'WARNING: set %s as GOROOT_BOOTSTRAP\n' "$goroot" >&2 + fi GOROOT_BOOTSTRAP=$goroot fi fi diff --git a/src/make.rc b/src/make.rc index 29d8c675db..ba8c5db2d9 100755 --- a/src/make.rc +++ b/src/make.rc @@ -51,15 +51,20 @@ GOENV=off GOFLAGS=() GO111MODULE=() GOROOT = `{cd .. && pwd} -if(! ~ $#GOROOT_BOOTSTRAP 1) +goroot_bootstrap_set = 'true' +if(! ~ $#GOROOT_BOOTSTRAP 1){ + goroot_bootstrap_set = 'false' GOROOT_BOOTSTRAP = $home/go1.4 +} for(p in $path){ if(! test -x $GOROOT_BOOTSTRAP/bin/go){ if(go_exe = `{path=$p whatis go}){ goroot = `{GOROOT='' $go_exe env GOROOT} if(! ~ $goroot $GOROOT){ - echo 'WARNING: '$GOROOT_BOOTSTRAP'/bin/go does not exist, found '$go_exe' from env' >[1=2] - echo 'WARNING: set '$goroot' as GOROOT_BOOTSTRAP' >[1=2] + if(~ $goroot_bootstrap_set 'true'){ + echo 'WARNING: '$GOROOT_BOOTSTRAP'/bin/go does not exist, found '$go_exe' from env' >[1=2] + echo 'WARNING: set '$goroot' as GOROOT_BOOTSTRAP' >[1=2] + } GOROOT_BOOTSTRAP = $goroot } } -- GitLab From 58244eee01e58c383f501207afd9cb90ec060602 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 2 Sep 2021 12:14:47 -0700 Subject: [PATCH 0988/2500] test: only test -G=3 by default -G=0 is in maintenance mode, so limit testing it to the longtest builders. Change-Id: Ie8a01866b506183d0201f2a3730377cfa663da80 Reviewed-on: https://go-review.googlesource.com/c/go/+/347298 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: Cherry Mui TryBot-Result: Go Bot --- test/run.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/run.go b/test/run.go index ddce94d7cc..76621d9242 100644 --- a/test/run.go +++ b/test/run.go @@ -85,12 +85,12 @@ var unifiedEnabled, defaultGLevels = func() (bool, string) { // won't need to disable tests for it anymore anyway. enabled := strings.Contains(","+env.GOEXPERIMENT+",", ",unified,") - // Normal test runs should test with both -G=0 and -G=3 for types2 - // coverage. But the unified experiment always uses types2, so - // testing with -G=3 is redundant. - glevels := "0,3" - if enabled { - glevels = "0" + // Test both -G=0 and -G=3 on the longtest builders, to make sure we + // don't accidentally break -G=0 mode until we're ready to remove it + // completely. But elsewhere, testing -G=3 alone should be enough. + glevels := "3" + if strings.Contains(os.Getenv("GO_BUILDER_NAME"), "longtest") { + glevels = "0,3" } return enabled, glevels -- GitLab From a8aa6cfa6d41a1be17bf8d35c490f693935f81ac Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 30 Jul 2021 13:12:27 -0400 Subject: [PATCH 0989/2500] cmd/compile: correct a comment in uint64Tofloat We only do z>>1 once (as it should be). Remove the extra one in the comment. Change-Id: I6fea05fe697de07e160bd686697377babcb3e4c1 Reviewed-on: https://go-review.googlesource.com/c/go/+/347400 Trust: Cherry Mui Reviewed-by: David Chase --- src/cmd/compile/internal/ssagen/ssa.go | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 176e6438dc..c86501b88b 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -5808,7 +5808,6 @@ func (s *state) uint64Tofloat(cvttab *u642fcvtTab, n ir.Node, x *ssa.Value, ft, // } else { // y = uintX(x) ; y = x & 1 // z = uintX(x) ; z = z >> 1 - // z = z >> 1 // z = z | y // result = floatY(z) // result = result + result -- GitLab From 065f3808156c92d957fc1ad2a2a37e147ee628f4 Mon Sep 17 00:00:00 2001 From: Joe Sylve Date: Thu, 2 Sep 2021 19:09:15 +0000 Subject: [PATCH 0990/2500] debug/dwarf: check for DWARFv4 AttrDataBitOffset value AttrBitOffset is deprecated (but reserved) in DWARFv4. This fix adds logic to check the new AttrDataBitOffset attribute if AttrBitOffset attribute is not present. Fixes #46784 Change-Id: I7406dcaa4c98e95df72361fd4462c39e6be8879d GitHub-Last-Rev: 5aa10d04910a09538320b4de8fbd8a1f5fd8c17d GitHub-Pull-Request: golang/go#46790 Reviewed-on: https://go-review.googlesource.com/c/go/+/328709 Run-TryBot: Than McIntosh TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Michael Knyszek --- src/debug/dwarf/testdata/typedef.c | 1 + src/debug/dwarf/testdata/typedef.macho4 | Bin 0 -> 6220 bytes src/debug/dwarf/type.go | 9 ++++- src/debug/dwarf/type_test.go | 51 ++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 src/debug/dwarf/testdata/typedef.macho4 diff --git a/src/debug/dwarf/testdata/typedef.c b/src/debug/dwarf/testdata/typedef.c index 4780a0b2ba..3e7e008621 100644 --- a/src/debug/dwarf/testdata/typedef.c +++ b/src/debug/dwarf/testdata/typedef.c @@ -8,6 +8,7 @@ gcc -gdwarf-2 -m64 -c typedef.c && gcc -gdwarf-2 -m64 -o typedef.elf typedef.o OS X Mach-O: gcc -gdwarf-2 -m64 -c typedef.c -o typedef.macho +gcc -gdwarf-4 -m64 -c typedef.c -o typedef.macho4 */ #include diff --git a/src/debug/dwarf/testdata/typedef.macho4 b/src/debug/dwarf/testdata/typedef.macho4 new file mode 100644 index 0000000000000000000000000000000000000000..093ff37ea1802b31805e711e5acf4c3eb8d3f7b5 GIT binary patch literal 6220 zcmX^A>+L^w1_nlE1_lO31_lNe1_lNT5TU>T29gX63_C!QU>+thSr8%?0n)?3zyRa3 zGcYiKFgHY+AwIq&wW0*dVPIg0j}LK;2tn{+EPf~hWFFK=hzJWq1B3w~Vi;H%6PSb&F!M6=((*w<@$snUX+X{K zVg<=EFf>5v526eVq7Wgh<`tI|fo0LnD`Eo+Gju`2_7oR{k3^!Gmsn7clNz6wn44M* z4nI`){o#b@)PU*=;e+szNT>`%Bt9NuUVc(mGDrm7eJVU4Q3eJT2*pq%0A(O3tmc8; zSCE*DZk`94c?*a%ucWd7tABH#=CwfM^$0=plJj#55|c~fOY_Pz^HSpDeOwS;VPN*N9LX3ey zgn@zKg*XF43IkXLLjcrl7zIl5AS?_MAb}3`=zMB;;JE7_ke=AXjDn1+e8Q~Ed`&fc z@9X&l#HINJ8HLyw7??~LnE5<~?Io?at+|;b7#NuO89ap<7+Ay@JcXJ0K%xu`tfpWw zHWdbDK09u1ZUzQ+HLwVWD5Iyax+DVwCo7oGCCUimaf>p5C?1eUd4(C7`M6mj2J!KN zZ3A&ExEUDu5nNvGY;Fby0fc}BD+7ZdBO}NyLW&HY!sgrz48kA>aC6&nGcbsNjpYWJ z#K0gbj%0@z3nR$o+)z1j4F+aD8D0hk2|WgommMS^z5@A~fq}t|6;kFhFmQl^nt_Kw zpMinFl7WF?1}Nkh7#J2qX%Gb})tJsPFfh1-qSlTRltMw`49q^DvOAoCf#D)ZhL1Uh zfq{WFk%57M?Fop*!t{cHfuR;8XOE<-iGhKExgDf+5(5Ln8;~?V^K?+rJqM)qFNk1d zVq#=q*a4DrK+?Jwr0WF8Y(@qKMgcY+Mg|5}4kl4X1_qFgjE+cZUxL(r0i{TgT0u5N zMg|6UCME+$1_l9;h!c`pkO3?Tj0_CMAQ>SJkRLcfDml$T0mSCV$iTqD!WIIeIGCat z85n{=3Z0RRhyckYGcqv5fngC?PX+OI0e$;ie%V%kYTqN85j4;-uU=Re!DDlcNF)(;AGD`EQGchoL(gdRn1HTp% z0|UqiMp;G$evt7XA2Q0ZDDvqsF)(Zf>6GW-b75j&I0j-Xa0o=e#1%al83aMfh4zC= z5(Z%dCI$u$cEL+b3=Ci)4F)zZCU8oKW@2D?2h#6}9VY zAPa<<85kH<7?8|oWMHabVqh=odOLZh) zYA`Y&e5uL8fbf|X0|V1UCI*J7APc;aESLqdU@0>L!&Hz3hGL*}J|E;$Mji3xAR+Np zObiT6;%k{07^=lLFflMRG|XD|YW-tI1}0GWJp&o&gJj@qkb&Qr85p*MbQ_BtWCA69 z6FyJ?i?c8=Fq$&(U0`Bh0BbbkU|>513PdKRt4s_G#vplLB*Q@MGZtqS28Np;!)!zz zGchnoFk14xU}9h>04cU&;Cl;abAT-=1&Lb=FffDkv4Nt2or8&snSo&&vM?}Mf%J+p zKZ5Ihi_j~;6wM4Su^AWxko59_N4>**`c!uK+55q$b$K8!la(lFa~B31aGp7N-^!>u2Ss>K7L!>!;^~DR4tp zKczgeC{4d4wYVfDu_Tcp(TJfWzM!NizAQf{u_QAmH9j-1gaL#TjT50#$@zK3CGp7_ ziA4-xBGH7QBt9oUFP#BID1a54GL*!Z7H8xal`xd%6=$aBrKTuAxQS*ACGlycdC4G? z=D*+h@a#VaVm@Ea63{d;Q zY`AN{yhKZw{<8ec6qsg)L_-5~agaPiqM;$WILKa*QSmAHCB+PhhM@4vt&A@&DJo4a zVL-6TG8rluDjBL6;^Q5If*d2`gFT~M<3l0?T;t;z5{rrwD!C5P~KbxXRqb%sd8&?N25MV_+Dr_H zhCZmc1FfcHHict{%3sgO* zt_1PrL4nJ_zyNABf%v~+>Orjt1_lN@kRSsC1E^&JVm<^BpynY|9uy8BEuc0DNQxa? z)iW@F3tN!6pz@f3fdSMC0?BU$5ey6rpcV;;X$e&is#-z(2B>>LH6w_B5z2?96Ob6l zKJ;|*|NsC0q^JR<88rq-zXoI;$Qn?3V`gAwU;*`kK&@R+ixt$YWnf@{r8`hn0!nir z`#@%hF)%QI#yzAM7#O4(7#QRj7#KiupuV9Z0|SF9C=41pxMx2s-v%P4P)4 z$Mg=}3A10j{_2M)fo1bH1T*yR4cWWMLi6s~)y6a5uk}-iw*ARlzR7Rbjx%@cd23!T zSbqAapy@QPM6p>lSLe>F31&@DzRV>bBfwL(Wo`A<-yDpwl}i{I7`8)Or>_|q82&Lr z+JY)f3=HN>3=E*gSuCh+z{J4N%*4PjjfsI_B@+X~9wr8c^Gpm3kC+%3zJgjh%nS_D z%nS^m+TM|wfgyyMfgzolfuV|-fuWa~fnfnN1H)!!28LtI3=B7!85rI$Gcf#TW?&Fv zVPH^Yfs7$}voJ8ku`n|4yacI6#_RM z85kHqZAqvQs6PcVYYqc^UUvO%7$gL0>_UaW9S#Nt22j%% zsu9#}0I34?B*Z}l1|)lcgh2fnsEr^EAR$l-8Y%>C-7+vRfSS8dvmn~xo#-#f5F82An`g6nR+Qbq;_AqECMZ&3Nez`zF@-4I}4;JX7Eo8{X8 z%8LvPe5IgzgMon$v4eDxxJOZNiAay7k$glh$0wloz?aP8XB2YeP=z|f7 z9|Y0I%mI}LmG8*%pmql`-xEzeXmAi&-Wp9FROchhYof`6>I!6eKQwtzTL)PlG){=j zH%C(s4F|Y?Ky?tZdQcid=7ai4$b5!)aMLV4(a Date: Wed, 25 Aug 2021 13:31:19 -0700 Subject: [PATCH 0991/2500] [dev.fuzz] internal/fuzz: don't store corpus in memory Instead of holding all corpus data/values in memory, only store seed inputs added via F.Add in memory, and only load corpus entries which are written to disk when we need them. This should significantly reduce the memory required by the coordinator process. Additionally only load the corpus in the coordinator process, since the worker has no need for it. Fixes #46669. Change-Id: Ic3b0c5e929fdb3e2877b963e6b0fa14e140c1e1d Reviewed-on: https://go-review.googlesource.com/c/go/+/345096 Trust: Roland Shoemaker Run-TryBot: Roland Shoemaker TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/internal/fuzz/fuzz.go | 59 ++++++++++++++++++++++--------------- src/internal/fuzz/worker.go | 21 +++++++------ src/testing/fuzz.go | 34 ++++++++++++++------- 3 files changed, 71 insertions(+), 43 deletions(-) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 7213a08d50..722933a0bf 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -254,7 +254,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err c.opts.Log, "DEBUG new crasher, elapsed: %s, id: %s, parent: %s, gen: %d, size: %d, exec time: %s\n", time.Since(c.startTime), - result.entry.Name, + fileName, result.entry.Parent, result.entry.Generation, len(result.entry.Data), @@ -303,35 +303,39 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err // number of new edges that this result expanded. // TODO(jayconrod, katiehockman): Don't write a value that's already // in the corpus. - if printDebugInfo() { - fmt.Fprintf( - c.opts.Log, - "DEBUG new interesting input, elapsed: %s, id: %s, parent: %s, gen: %d, new bits: %d, total bits: %d, size: %d, exec time: %s\n", - time.Since(c.startTime), - result.entry.Name, - result.entry.Parent, - result.entry.Generation, - countBits(keepCoverage), - countBits(c.coverageMask), - len(result.entry.Data), - result.entryDuration, - ) - } if !result.minimizeAttempted && crashMinimizing == nil && c.canMinimize() { // Send back to workers to find a smaller value that preserves // at least one new coverage bit. c.queueForMinimization(result, keepCoverage) } else { // Update the coordinator's coverage mask and save the value. + inputSize := len(result.entry.Data) if opts.CacheDir != "" { - if _, err := writeToCorpus(result.entry.Data, opts.CacheDir); err != nil { + filename, err := writeToCorpus(result.entry.Data, opts.CacheDir) + if err != nil { stop(err) } + result.entry.Data = nil + result.entry.Name = filename } c.updateCoverage(keepCoverage) c.corpus.entries = append(c.corpus.entries, result.entry) c.inputQueue.enqueue(result.entry) c.interestingCount++ + if printDebugInfo() { + fmt.Fprintf( + c.opts.Log, + "DEBUG new interesting input, elapsed: %s, id: %s, parent: %s, gen: %d, new bits: %d, total bits: %d, size: %d, exec time: %s\n", + time.Since(c.startTime), + result.entry.Name, + result.entry.Parent, + result.entry.Generation, + countBits(keepCoverage), + countBits(c.coverageMask), + inputSize, + result.entryDuration, + ) + } } } else { if printDebugInfo() { @@ -393,18 +397,17 @@ type corpus struct { // packages, but testing can't import this package directly, and we don't want // to export this type from testing. Instead, we use the same struct type and // use a type alias (not a defined type) for convenience. -// -// TODO: split marshalled and unmarshalled types. In most places, we only need -// one or the other. type CorpusEntry = struct { Parent string // Name is the name of the corpus file, if the entry was loaded from the // seed corpus. It can be used with -run. For entries added with f.Add and - // entries generated by the mutator, Name is empty. + // entries generated by the mutator, Name is empty and Data is populated. Name string - // Data is the raw data loaded from a corpus file. + // Data is the raw input data. Data should only be populated for initial + // seed values added with f.Add. For on-disk corpus files, Data will + // be nil. Data []byte // Values is the unmarshaled values from a corpus file. @@ -413,6 +416,16 @@ type CorpusEntry = struct { Generation int } +// Data returns the raw input bytes, either from the data struct field, +// or from disk. +func CorpusEntryData(ce CorpusEntry) ([]byte, error) { + if ce.Data != nil { + return ce.Data, nil + } + + return os.ReadFile(ce.Name) +} + type fuzzInput struct { // entry is the value to test initially. The worker will randomly mutate // values from this starting point. @@ -580,7 +593,7 @@ func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { data := marshalCorpusFile(vals...) h := sha256.Sum256(data) name := fmt.Sprintf("%x", h[:4]) - corpus.entries = append(corpus.entries, CorpusEntry{Name: name, Data: data, Values: vals}) + corpus.entries = append(corpus.entries, CorpusEntry{Name: name, Data: data}) } c := &coordinator{ opts: opts, @@ -875,7 +888,7 @@ func ReadCorpus(dir string, types []reflect.Type) ([]CorpusEntry, error) { errs = append(errs, fmt.Errorf("%q: %v", filename, err)) continue } - corpus = append(corpus, CorpusEntry{Name: filename, Data: data, Values: vals}) + corpus = append(corpus, CorpusEntry{Name: filename, Values: vals}) } if len(errs) > 0 { return corpus, &MalformedCorpusError{errs: errs} diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 67ec3c762b..2f5704094e 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -1002,7 +1002,11 @@ func (wc *workerClient) minimize(ctx context.Context, entryIn CorpusEntry, args return CorpusEntry{}, minimizeResponse{}, errSharedMemClosed } mem.header().count = 0 - mem.setValue(entryIn.Data) + inp, err := CorpusEntryData(entryIn) + if err != nil { + return CorpusEntry{}, minimizeResponse{}, err + } + mem.setValue(inp) wc.memMu <- mem defer func() { wc.memMu <- mem }() @@ -1013,10 +1017,6 @@ func (wc *workerClient) minimize(ctx context.Context, entryIn CorpusEntry, args return CorpusEntry{}, minimizeResponse{}, errSharedMemClosed } entryOut.Data = mem.valueCopy() - entryOut.Values, err = unmarshalCorpusFile(entryOut.Data) - if err != nil { - panic(fmt.Sprintf("workerClient.minimize unmarshaling minimized value: %v", err)) - } resp.Count = mem.header().count return entryOut, resp, callErr @@ -1032,7 +1032,11 @@ func (wc *workerClient) fuzz(ctx context.Context, entryIn CorpusEntry, args fuzz return CorpusEntry{}, fuzzResponse{}, errSharedMemClosed } mem.header().count = 0 - mem.setValue(entryIn.Data) + inp, err := CorpusEntryData(entryIn) + if err != nil { + return CorpusEntry{}, fuzzResponse{}, err + } + mem.setValue(inp) wc.memMu <- mem c := call{Fuzz: &args} @@ -1044,10 +1048,10 @@ func (wc *workerClient) fuzz(ctx context.Context, entryIn CorpusEntry, args fuzz defer func() { wc.memMu <- mem }() resp.Count = mem.header().count - if !bytes.Equal(entryIn.Data, mem.valueRef()) { + if !bytes.Equal(inp, mem.valueRef()) { panic("workerServer.fuzz modified input") } - valuesOut, err := unmarshalCorpusFile(entryIn.Data) + valuesOut, err := unmarshalCorpusFile(inp) if err != nil { panic(fmt.Sprintf("unmarshaling fuzz input value after call: %v", err)) } @@ -1063,7 +1067,6 @@ func (wc *workerClient) fuzz(ctx context.Context, entryIn CorpusEntry, args fuzz Name: name, Parent: entryIn.Name, Data: dataOut, - Values: valuesOut, Generation: entryIn.Generation + 1, } diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 4892d3f3e9..e567f7d9f4 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -305,21 +305,33 @@ func (f *F) Fuzz(ff interface{}) { types = append(types, t) } - // Check the corpus provided by f.Add - for _, c := range f.corpus { - if err := f.fuzzContext.checkCorpus(c.Values, types); err != nil { - // TODO: Is there a way to save which line number is associated - // with the f.Add call that failed? + // Only load the corpus if we need it + if f.fuzzContext.runFuzzWorker == nil { + // Check the corpus provided by f.Add + for _, c := range f.corpus { + if err := f.fuzzContext.checkCorpus(c.Values, types); err != nil { + // TODO: Is there a way to save which line number is associated + // with the f.Add call that failed? + f.Fatal(err) + } + } + + // Load seed corpus + c, err := f.fuzzContext.readCorpus(filepath.Join(corpusDir, f.name), types) + if err != nil { f.Fatal(err) } - } - // Load seed corpus - c, err := f.fuzzContext.readCorpus(filepath.Join(corpusDir, f.name), types) - if err != nil { - f.Fatal(err) + // If this is the coordinator process, zero the values, since we don't need to hold + // onto them. + if f.fuzzContext.coordinateFuzzing != nil { + for i := range c { + c[i].Values = nil + } + } + + f.corpus = append(f.corpus, c...) } - f.corpus = append(f.corpus, c...) // run calls fn on a given input, as a subtest with its own T. // run is analogous to T.Run. The test filtering and cleanup works similarly. -- GitLab From 9f69a44308f4f9cbdae68925202dfef2027a7d20 Mon Sep 17 00:00:00 2001 From: Nigel Tao Date: Thu, 5 Aug 2021 16:11:28 +1000 Subject: [PATCH 0992/2500] image/draw: add RGBA64Image fast path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit name old time/op new time/op delta GenericOver-4 15.0ms ± 1% 2.9ms ± 1% -80.56% (p=0.008 n=5+5) GenericMaskOver-4 7.82ms ± 4% 1.69ms ± 2% -78.38% (p=0.008 n=5+5) GenericSrc-4 6.13ms ± 3% 1.66ms ± 1% -72.90% (p=0.008 n=5+5) GenericMaskSrc-4 11.5ms ± 1% 2.0ms ± 0% -82.77% (p=0.008 n=5+5) Updates #44808. Change-Id: I131cf6fad01708540390a8012d8f2a21e849fe9d Reviewed-on: https://go-review.googlesource.com/c/go/+/340049 Reviewed-by: Dmitri Shuralyov Trust: Nigel Tao --- doc/go1.18.html | 13 +++ src/image/draw/draw.go | 81 ++++++++++++++- src/image/draw/draw_test.go | 201 ++++++++++++++++++++++++++++++++---- 3 files changed, 272 insertions(+), 23 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index df4b56c49f..911bb712f7 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -83,6 +83,19 @@ Do not send CLs removing the interior tags from such phrases. TODO: complete this section

+
image/draw
+
+

+ The Draw and DrawMask fallback implementations + (used when the arguments are not the most common image types) are now + faster when those arguments implement the optional + draw.RGBA64Image + and image.RGBA64Image + interfaces that were added in Go 1.17. +

+
+
+
syscall

diff --git a/src/image/draw/draw.go b/src/image/draw/draw.go index 13f6668293..4431028201 100644 --- a/src/image/draw/draw.go +++ b/src/image/draw/draw.go @@ -119,7 +119,8 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas return } - // Fast paths for special cases. If none of them apply, then we fall back to a general but slow implementation. + // Fast paths for special cases. If none of them apply, then we fall back + // to general but slower implementations. switch dst0 := dst.(type) { case *image.RGBA: if op == Over { @@ -219,6 +220,84 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas y0, y1, dy = y1-1, y0-1, -1 } + // Try the draw.RGBA64Image and image.RGBA64Image interfaces, part of the + // standard library since Go 1.17. These are like the draw.Image and + // image.Image interfaces but they can avoid allocations from converting + // concrete color types to the color.Color interface type. + + if dst0, _ := dst.(RGBA64Image); dst0 != nil { + if src0, _ := src.(image.RGBA64Image); src0 != nil { + if mask == nil { + sy := sp.Y + y0 - r.Min.Y + my := mp.Y + y0 - r.Min.Y + for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy { + sx := sp.X + x0 - r.Min.X + mx := mp.X + x0 - r.Min.X + for x := x0; x != x1; x, sx, mx = x+dx, sx+dx, mx+dx { + if op == Src { + dst0.SetRGBA64(x, y, src0.RGBA64At(sx, sy)) + } else { + srgba := src0.RGBA64At(sx, sy) + a := m - uint32(srgba.A) + drgba := dst0.RGBA64At(x, y) + dst0.SetRGBA64(x, y, color.RGBA64{ + R: uint16((uint32(drgba.R)*a)/m) + srgba.R, + G: uint16((uint32(drgba.G)*a)/m) + srgba.G, + B: uint16((uint32(drgba.B)*a)/m) + srgba.B, + A: uint16((uint32(drgba.A)*a)/m) + srgba.A, + }) + } + } + } + return + + } else if mask0, _ := mask.(image.RGBA64Image); mask0 != nil { + sy := sp.Y + y0 - r.Min.Y + my := mp.Y + y0 - r.Min.Y + for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy { + sx := sp.X + x0 - r.Min.X + mx := mp.X + x0 - r.Min.X + for x := x0; x != x1; x, sx, mx = x+dx, sx+dx, mx+dx { + ma := uint32(mask0.RGBA64At(mx, my).A) + switch { + case ma == 0: + if op == Over { + // No-op. + } else { + dst0.SetRGBA64(x, y, color.RGBA64{}) + } + case ma == m && op == Src: + dst0.SetRGBA64(x, y, src0.RGBA64At(sx, sy)) + default: + srgba := src0.RGBA64At(sx, sy) + if op == Over { + drgba := dst0.RGBA64At(x, y) + a := m - (uint32(srgba.A) * ma / m) + dst0.SetRGBA64(x, y, color.RGBA64{ + R: uint16((uint32(drgba.R)*a + uint32(srgba.R)*ma) / m), + G: uint16((uint32(drgba.G)*a + uint32(srgba.G)*ma) / m), + B: uint16((uint32(drgba.B)*a + uint32(srgba.B)*ma) / m), + A: uint16((uint32(drgba.A)*a + uint32(srgba.A)*ma) / m), + }) + } else { + dst0.SetRGBA64(x, y, color.RGBA64{ + R: uint16(uint32(srgba.R) * ma / m), + G: uint16(uint32(srgba.G) * ma / m), + B: uint16(uint32(srgba.B) * ma / m), + A: uint16(uint32(srgba.A) * ma / m), + }) + } + } + } + } + return + } + } + } + + // If none of the faster code paths above apply, use the draw.Image and + // image.Image interfaces, part of the standard library since Go 1.0. + var out color.RGBA64 sy := sp.Y + y0 - r.Min.Y my := mp.Y + y0 - r.Min.Y diff --git a/src/image/draw/draw_test.go b/src/image/draw/draw_test.go index 9c5a118400..ea383a0172 100644 --- a/src/image/draw/draw_test.go +++ b/src/image/draw/draw_test.go @@ -13,6 +13,138 @@ import ( "testing/quick" ) +// slowestRGBA is a draw.Image like image.RGBA but it is a different type and +// therefore does not trigger the draw.go fastest code paths. +// +// Unlike slowerRGBA, it does not implement the draw.RGBA64Image interface. +type slowestRGBA struct { + Pix []uint8 + Stride int + Rect image.Rectangle +} + +func (p *slowestRGBA) ColorModel() color.Model { return color.RGBAModel } + +func (p *slowestRGBA) Bounds() image.Rectangle { return p.Rect } + +func (p *slowestRGBA) At(x, y int) color.Color { + return p.RGBA64At(x, y) +} + +func (p *slowestRGBA) RGBA64At(x, y int) color.RGBA64 { + if !(image.Point{x, y}.In(p.Rect)) { + return color.RGBA64{} + } + i := p.PixOffset(x, y) + s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857 + r := uint16(s[0]) + g := uint16(s[1]) + b := uint16(s[2]) + a := uint16(s[3]) + return color.RGBA64{ + (r << 8) | r, + (g << 8) | g, + (b << 8) | b, + (a << 8) | a, + } +} + +func (p *slowestRGBA) Set(x, y int, c color.Color) { + if !(image.Point{x, y}.In(p.Rect)) { + return + } + i := p.PixOffset(x, y) + c1 := color.RGBAModel.Convert(c).(color.RGBA) + s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857 + s[0] = c1.R + s[1] = c1.G + s[2] = c1.B + s[3] = c1.A +} + +func (p *slowestRGBA) PixOffset(x, y int) int { + return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4 +} + +func init() { + var p interface{} = (*slowestRGBA)(nil) + if _, ok := p.(RGBA64Image); ok { + panic("slowestRGBA should not be an RGBA64Image") + } +} + +// slowerRGBA is a draw.Image like image.RGBA but it is a different type and +// therefore does not trigger the draw.go fastest code paths. +// +// Unlike slowestRGBA, it still implements the draw.RGBA64Image interface. +type slowerRGBA struct { + Pix []uint8 + Stride int + Rect image.Rectangle +} + +func (p *slowerRGBA) ColorModel() color.Model { return color.RGBAModel } + +func (p *slowerRGBA) Bounds() image.Rectangle { return p.Rect } + +func (p *slowerRGBA) At(x, y int) color.Color { + return p.RGBA64At(x, y) +} + +func (p *slowerRGBA) RGBA64At(x, y int) color.RGBA64 { + if !(image.Point{x, y}.In(p.Rect)) { + return color.RGBA64{} + } + i := p.PixOffset(x, y) + s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857 + r := uint16(s[0]) + g := uint16(s[1]) + b := uint16(s[2]) + a := uint16(s[3]) + return color.RGBA64{ + (r << 8) | r, + (g << 8) | g, + (b << 8) | b, + (a << 8) | a, + } +} + +func (p *slowerRGBA) Set(x, y int, c color.Color) { + if !(image.Point{x, y}.In(p.Rect)) { + return + } + i := p.PixOffset(x, y) + c1 := color.RGBAModel.Convert(c).(color.RGBA) + s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857 + s[0] = c1.R + s[1] = c1.G + s[2] = c1.B + s[3] = c1.A +} + +func (p *slowerRGBA) SetRGBA64(x, y int, c color.RGBA64) { + if !(image.Point{x, y}.In(p.Rect)) { + return + } + i := p.PixOffset(x, y) + s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857 + s[0] = uint8(c.R >> 8) + s[1] = uint8(c.G >> 8) + s[2] = uint8(c.B >> 8) + s[3] = uint8(c.A >> 8) +} + +func (p *slowerRGBA) PixOffset(x, y int) int { + return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4 +} + +func init() { + var p interface{} = (*slowerRGBA)(nil) + if _, ok := p.(RGBA64Image); !ok { + panic("slowerRGBA should be an RGBA64Image") + } +} + func eq(c0, c1 color.Color) bool { r0, g0, b0, a0 := c0.RGBA() r1, g1, b1, a1 := c1.RGBA() @@ -260,30 +392,55 @@ func TestDraw(t *testing.T) { for _, r := range rr { loop: for _, test := range drawTests { - dst := hgradRed(255).(*image.RGBA).SubImage(r).(Image) - // Draw the (src, mask, op) onto a copy of dst using a slow but obviously correct implementation. - golden := makeGolden(dst, image.Rect(0, 0, 16, 16), test.src, image.ZP, test.mask, image.ZP, test.op) - b := dst.Bounds() - if !b.Eq(golden.Bounds()) { - t.Errorf("draw %v %s: bounds %v versus %v", r, test.desc, dst.Bounds(), golden.Bounds()) - continue - } - // Draw the same combination onto the actual dst using the optimized DrawMask implementation. - DrawMask(dst, image.Rect(0, 0, 16, 16), test.src, image.ZP, test.mask, image.ZP, test.op) - if image.Pt(8, 8).In(r) { - // Check that the resultant pixel at (8, 8) matches what we expect - // (the expected value can be verified by hand). - if !eq(dst.At(8, 8), test.expected) { - t.Errorf("draw %v %s: at (8, 8) %v versus %v", r, test.desc, dst.At(8, 8), test.expected) + for i := 0; i < 3; i++ { + dst := hgradRed(255).(*image.RGBA).SubImage(r).(Image) + // For i != 0, substitute a different-typed dst that will take + // us off the fastest code paths. We should still get the same + // result, in terms of final pixel RGBA values. + switch i { + case 1: + d := dst.(*image.RGBA) + dst = &slowerRGBA{ + Pix: d.Pix, + Stride: d.Stride, + Rect: d.Rect, + } + case 2: + d := dst.(*image.RGBA) + dst = &slowestRGBA{ + Pix: d.Pix, + Stride: d.Stride, + Rect: d.Rect, + } + } + + // Draw the (src, mask, op) onto a copy of dst using a slow but obviously correct implementation. + golden := makeGolden(dst, image.Rect(0, 0, 16, 16), test.src, image.ZP, test.mask, image.ZP, test.op) + b := dst.Bounds() + if !b.Eq(golden.Bounds()) { + t.Errorf("draw %v %s on %T: bounds %v versus %v", + r, test.desc, dst, dst.Bounds(), golden.Bounds()) continue } - } - // Check that the resultant dst image matches the golden output. - for y := b.Min.Y; y < b.Max.Y; y++ { - for x := b.Min.X; x < b.Max.X; x++ { - if !eq(dst.At(x, y), golden.At(x, y)) { - t.Errorf("draw %v %s: at (%d, %d), %v versus golden %v", r, test.desc, x, y, dst.At(x, y), golden.At(x, y)) - continue loop + // Draw the same combination onto the actual dst using the optimized DrawMask implementation. + DrawMask(dst, image.Rect(0, 0, 16, 16), test.src, image.ZP, test.mask, image.ZP, test.op) + if image.Pt(8, 8).In(r) { + // Check that the resultant pixel at (8, 8) matches what we expect + // (the expected value can be verified by hand). + if !eq(dst.At(8, 8), test.expected) { + t.Errorf("draw %v %s on %T: at (8, 8) %v versus %v", + r, test.desc, dst, dst.At(8, 8), test.expected) + continue + } + } + // Check that the resultant dst image matches the golden output. + for y := b.Min.Y; y < b.Max.Y; y++ { + for x := b.Min.X; x < b.Max.X; x++ { + if !eq(dst.At(x, y), golden.At(x, y)) { + t.Errorf("draw %v %s on %T: at (%d, %d), %v versus golden %v", + r, test.desc, dst, x, y, dst.At(x, y), golden.At(x, y)) + continue loop + } } } } -- GitLab From 17910ed4ff5a3cb3dcf4367d4af23ad5a7fe5809 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 11 Aug 2021 10:54:39 -0700 Subject: [PATCH 0993/2500] refect: rename Ptr Kind to Pointer (but keep Ptr) reflect.Ptr didn't match reflect.UnsafePointer or unsafe.Pointer so rename it to reflect.Pointer. Keep reflect.Ptr for compatibility. Likewise with PtrTo. Change to use it in std will come in a subsequent CL. Fixes #47651 Change-Id: I5d4abe2b2fe10948bd68bb12c557165bedffbcba Reviewed-on: https://go-review.googlesource.com/c/go/+/341333 Run-TryBot: Brad Fitzpatrick TryBot-Result: Go Bot Trust: Brad Fitzpatrick Reviewed-by: Joe Tsai Reviewed-by: Robert Griesemer --- src/internal/reflectlite/type.go | 4 ++- src/internal/reflectlite/value.go | 8 ++--- src/reflect/type.go | 50 +++++++++++++++++++------------ 3 files changed, 38 insertions(+), 24 deletions(-) diff --git a/src/internal/reflectlite/type.go b/src/internal/reflectlite/type.go index b1899b0191..fdf1584a27 100644 --- a/src/internal/reflectlite/type.go +++ b/src/internal/reflectlite/type.go @@ -100,13 +100,15 @@ const ( Func Interface Map - Ptr + Pointer Slice String Struct UnsafePointer ) +const Ptr = Pointer + // tflag is used by an rtype to signal what extra type information is // available in the memory directly following the rtype value. // diff --git a/src/internal/reflectlite/value.go b/src/internal/reflectlite/value.go index 136273842c..0734069255 100644 --- a/src/internal/reflectlite/value.go +++ b/src/internal/reflectlite/value.go @@ -87,7 +87,7 @@ func (f flag) ro() flag { } // pointer returns the underlying pointer represented by v. -// v.Kind() must be Ptr, Map, Chan, Func, or UnsafePointer +// v.Kind() must be Pointer, Map, Chan, Func, or UnsafePointer func (v Value) pointer() unsafe.Pointer { if v.typ.size != goarch.PtrSize || !v.typ.pointers() { panic("can't call pointer on a non-pointer Value") @@ -220,7 +220,7 @@ func (v Value) CanSet() bool { // Elem returns the value that the interface v contains // or that the pointer v points to. -// It panics if v's Kind is not Interface or Ptr. +// It panics if v's Kind is not Interface or Pointer. // It returns the zero Value if v is nil. func (v Value) Elem() Value { k := v.kind() @@ -239,7 +239,7 @@ func (v Value) Elem() Value { x.flag |= v.flag.ro() } return x - case Ptr: + case Pointer: ptr := v.ptr if v.flag&flagIndir != 0 { ptr = *(*unsafe.Pointer)(ptr) @@ -288,7 +288,7 @@ func valueInterface(v Value) interface{} { func (v Value) IsNil() bool { k := v.kind() switch k { - case Chan, Func, Map, Ptr, UnsafePointer: + case Chan, Func, Map, Pointer, UnsafePointer: // if v.flag&flagMethod != 0 { // return false // } diff --git a/src/reflect/type.go b/src/reflect/type.go index 278426da09..1d637d134e 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -126,7 +126,7 @@ type Type interface { // Chan: ChanDir, Elem // Func: In, NumIn, Out, NumOut, IsVariadic. // Map: Key, Elem - // Ptr: Elem + // Pointer: Elem // Slice: Elem // Struct: Field, FieldByIndex, FieldByName, FieldByNameFunc, NumField @@ -154,7 +154,7 @@ type Type interface { IsVariadic() bool // Elem returns a type's element type. - // It panics if the type's Kind is not Array, Chan, Map, Ptr, or Slice. + // It panics if the type's Kind is not Array, Chan, Map, Pointer, or Slice. Elem() Type // Field returns a struct type's i'th field. @@ -261,13 +261,18 @@ const ( Func Interface Map - Ptr + Pointer Slice String Struct UnsafePointer ) +// Ptr is the old name for the Pointer kind. +// +// Deprecated: use the new spelling, Pointer. +const Ptr = Pointer + // tflag is used by an rtype to signal what extra type information is // available in the memory directly following the rtype value. // @@ -658,7 +663,7 @@ var kindNames = []string{ Func: "func", Interface: "interface", Map: "map", - Ptr: "ptr", + Pointer: "ptr", Slice: "slice", String: "string", Struct: "struct", @@ -741,7 +746,7 @@ func (t *rtype) uncommon() *uncommonType { switch t.Kind() { case Struct: return &(*structTypeUncommon)(unsafe.Pointer(t)).u - case Ptr: + case Pointer: type u struct { ptrType u uncommonType @@ -945,7 +950,7 @@ func (t *rtype) Elem() Type { case Map: tt := (*mapType)(unsafe.Pointer(t)) return toType(tt.elem) - case Ptr: + case Pointer: tt := (*ptrType)(unsafe.Pointer(t)) return toType(tt.elem) case Slice: @@ -1265,7 +1270,7 @@ func (t *structType) FieldByIndex(index []int) (f StructField) { for i, x := range index { if i > 0 { ft := f.Type - if ft.Kind() == Ptr && ft.Elem().Kind() == Struct { + if ft.Kind() == Pointer && ft.Elem().Kind() == Struct { ft = ft.Elem() } f.Type = ft @@ -1336,7 +1341,7 @@ func (t *structType) FieldByNameFunc(match func(string) bool) (result StructFiel if f.embedded() { // Embedded field of type T or *T. ntyp = f.typ - if ntyp.Kind() == Ptr { + if ntyp.Kind() == Pointer { ntyp = ntyp.Elem().common() } } @@ -1416,12 +1421,19 @@ func TypeOf(i interface{}) Type { return toType(eface.typ) } -// ptrMap is the cache for PtrTo. +// ptrMap is the cache for PointerTo. var ptrMap sync.Map // map[*rtype]*ptrType // PtrTo returns the pointer type with element t. // For example, if t represents type Foo, PtrTo(t) represents *Foo. -func PtrTo(t Type) Type { +// +// Deprecated: use PointerTo. PtrTo is the old spelling. +// The two functions behaves identically. +func PtrTo(t Type) Type { return PointerTo(t) } + +// PointerTo returns the pointer type with element t. +// For example, if t represents type Foo, PointerTo(t) represents *Foo. +func PointerTo(t Type) Type { return t.(*rtype).ptrTo() } @@ -1695,7 +1707,7 @@ func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool { case Map: return haveIdenticalType(T.Key(), V.Key(), cmpTags) && haveIdenticalType(T.Elem(), V.Elem(), cmpTags) - case Ptr, Slice: + case Pointer, Slice: return haveIdenticalType(T.Elem(), V.Elem(), cmpTags) case Struct: @@ -2136,7 +2148,7 @@ func funcStr(ft *funcType) string { // That is, x == x for all values x of type t. func isReflexive(t *rtype) bool { switch t.Kind() { - case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, Chan, Ptr, String, UnsafePointer: + case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, Chan, Pointer, String, UnsafePointer: return true case Float32, Float64, Complex64, Complex128, Interface: return false @@ -2160,7 +2172,7 @@ func isReflexive(t *rtype) bool { // needKeyUpdate reports whether map overwrites require the key to be copied. func needKeyUpdate(t *rtype) bool { switch t.Kind() { - case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, Chan, Ptr, UnsafePointer: + case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, Chan, Pointer, UnsafePointer: return false case Float32, Float64, Complex64, Complex128, Interface, String: // Float keys can be updated from +0 to -0. @@ -2217,10 +2229,10 @@ const ( func bucketOf(ktyp, etyp *rtype) *rtype { if ktyp.size > maxKeySize { - ktyp = PtrTo(ktyp).(*rtype) + ktyp = PointerTo(ktyp).(*rtype) } if etyp.size > maxValSize { - etyp = PtrTo(etyp).(*rtype) + etyp = PointerTo(etyp).(*rtype) } // Prepare GC data if any. @@ -2458,10 +2470,10 @@ func StructOf(fields []StructField) Type { repr = append(repr, (" " + name)...) if f.embedded() { // Embedded field - if f.typ.Kind() == Ptr { + if f.typ.Kind() == Pointer { // Embedded ** and *interface{} are illegal elem := ft.Elem() - if k := elem.Kind(); k == Ptr || k == Interface { + if k := elem.Kind(); k == Pointer || k == Interface { panic("reflect.StructOf: illegal embedded field type " + ft.String()) } } @@ -2526,7 +2538,7 @@ func StructOf(fields []StructField) Type { tfn: resolveReflectText(unsafe.Pointer(&tfn)), }) } - case Ptr: + case Pointer: ptr := (*ptrType)(unsafe.Pointer(ft)) if unt := ptr.uncommon(); unt != nil { if i > 0 && unt.mcount > 0 { @@ -3123,7 +3135,7 @@ func addTypeBits(bv *bitVector, offset uintptr, t *rtype) { } switch Kind(t.kind & kindMask) { - case Chan, Func, Map, Ptr, Slice, String, UnsafePointer: + case Chan, Func, Map, Pointer, Slice, String, UnsafePointer: // 1 pointer at start of representation for bv.n < uint32(offset/uintptr(goarch.PtrSize)) { bv.append(0) -- GitLab From ab7c904bf2bb883b83001d8bb188d1809d74eee6 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Tue, 24 Aug 2021 01:01:06 +1000 Subject: [PATCH 0994/2500] cmd/internal/obj/riscv: factor out instructions for MOV pseudo-instructions This factors out the machine instruction generation for MOV pseudo-instructions, which will simplify further changes. Change-Id: Ic0d2c3ae9e0881f7894af50ed45e93b0e4961632 Reviewed-on: https://go-review.googlesource.com/c/go/+/344461 Trust: Joel Sing Trust: Meng Zhuo Run-TryBot: Joel Sing TryBot-Result: Go Bot Reviewed-by: Meng Zhuo Reviewed-by: Cherry Mui --- src/cmd/internal/obj/riscv/obj.go | 103 +++++++++++++++++++----------- 1 file changed, 65 insertions(+), 38 deletions(-) diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index 6de967319c..f602183e04 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -1823,8 +1823,8 @@ func (ins *instruction) validate(ctxt *obj.Link) { enc.validate(ctxt, ins) } -// instructionsForProg returns the machine instructions for an *obj.Prog. -func instructionsForProg(p *obj.Prog) []*instruction { +// instructionForProg returns the default *obj.Prog to instruction mapping. +func instructionForProg(p *obj.Prog) *instruction { ins := &instruction{ as: p.As, rd: uint32(p.To.Reg), @@ -1832,49 +1832,21 @@ func instructionsForProg(p *obj.Prog) []*instruction { rs2: uint32(p.From.Reg), imm: p.From.Offset, } - if len(p.RestArgs) == 1 { ins.rs3 = uint32(p.RestArgs[0].Reg) - } else if len(p.RestArgs) > 0 { - p.Ctxt.Diag("too many source registers") } + return ins +} +// instructionsForMOV returns the machine instructions for an *obj.Prog that +// uses a MOV pseudo-instruction. +func instructionsForMOV(p *obj.Prog) []*instruction { + ins := instructionForProg(p) inss := []*instruction{ins} - switch ins.as { - case AJAL, AJALR: - ins.rd, ins.rs1, ins.rs2 = uint32(p.From.Reg), uint32(p.To.Reg), obj.REG_NONE - ins.imm = p.To.Offset - case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ: - switch ins.as { - case ABEQZ: - ins.as, ins.rs1, ins.rs2 = ABEQ, REG_ZERO, uint32(p.From.Reg) - case ABGEZ: - ins.as, ins.rs1, ins.rs2 = ABGE, REG_ZERO, uint32(p.From.Reg) - case ABGT: - ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), uint32(p.Reg) - case ABGTU: - ins.as, ins.rs1, ins.rs2 = ABLTU, uint32(p.From.Reg), uint32(p.Reg) - case ABGTZ: - ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), REG_ZERO - case ABLE: - ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), uint32(p.Reg) - case ABLEU: - ins.as, ins.rs1, ins.rs2 = ABGEU, uint32(p.From.Reg), uint32(p.Reg) - case ABLEZ: - ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), REG_ZERO - case ABLTZ: - ins.as, ins.rs1, ins.rs2 = ABLT, REG_ZERO, uint32(p.From.Reg) - case ABNEZ: - ins.as, ins.rs1, ins.rs2 = ABNE, REG_ZERO, uint32(p.From.Reg) - } - ins.imm = p.To.Offset - - case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD: + switch { + case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG: // Handle register to register moves. - if p.From.Type != obj.TYPE_REG || p.To.Type != obj.TYPE_REG { - return nil - } switch p.As { case AMOV: // MOV Ra, Rb -> ADDI $0, Ra, Rb ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, uint32(p.From.Reg), obj.REG_NONE, 0 @@ -1908,6 +1880,61 @@ func instructionsForProg(p *obj.Prog) []*instruction { inss = append(inss, ins2) } + default: + // If we get here with a MOV pseudo-instruction it is going to + // remain unhandled. For now we trust rewriteMOV to catch these. + switch p.As { + case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD: + return nil + } + } + + return inss +} + +// instructionsForProg returns the machine instructions for an *obj.Prog. +func instructionsForProg(p *obj.Prog) []*instruction { + ins := instructionForProg(p) + inss := []*instruction{ins} + + if len(p.RestArgs) > 1 { + p.Ctxt.Diag("too many source registers") + return nil + } + + switch ins.as { + case AJAL, AJALR: + ins.rd, ins.rs1, ins.rs2 = uint32(p.From.Reg), uint32(p.To.Reg), obj.REG_NONE + ins.imm = p.To.Offset + + case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ: + switch ins.as { + case ABEQZ: + ins.as, ins.rs1, ins.rs2 = ABEQ, REG_ZERO, uint32(p.From.Reg) + case ABGEZ: + ins.as, ins.rs1, ins.rs2 = ABGE, REG_ZERO, uint32(p.From.Reg) + case ABGT: + ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), uint32(p.Reg) + case ABGTU: + ins.as, ins.rs1, ins.rs2 = ABLTU, uint32(p.From.Reg), uint32(p.Reg) + case ABGTZ: + ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), REG_ZERO + case ABLE: + ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), uint32(p.Reg) + case ABLEU: + ins.as, ins.rs1, ins.rs2 = ABGEU, uint32(p.From.Reg), uint32(p.Reg) + case ABLEZ: + ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), REG_ZERO + case ABLTZ: + ins.as, ins.rs1, ins.rs2 = ABLT, REG_ZERO, uint32(p.From.Reg) + case ABNEZ: + ins.as, ins.rs1, ins.rs2 = ABNE, REG_ZERO, uint32(p.From.Reg) + } + ins.imm = p.To.Offset + + case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD: + return instructionsForMOV(p) + case ALW, ALWU, ALH, ALHU, ALB, ALBU, ALD, AFLW, AFLD: if p.From.Type != obj.TYPE_MEM { p.Ctxt.Diag("%v requires memory for source", p) -- GitLab From 52aef05498a9e84ede16fb7ce46a2a252af05479 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Fri, 3 Sep 2021 11:18:16 +0700 Subject: [PATCH 0995/2500] go/ast: clarify when Ident.Obj is nil Fixes #48141 Change-Id: Id20b7801d31456ffd74301ed0fd84788b8982fb1 Reviewed-on: https://go-review.googlesource.com/c/go/+/347530 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le Reviewed-by: Robert Findley TryBot-Result: Go Bot --- src/go/ast/ast.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/go/ast/ast.go b/src/go/ast/ast.go index b0f1330564..f6abb2d175 100644 --- a/src/go/ast/ast.go +++ b/src/go/ast/ast.go @@ -290,7 +290,7 @@ type ( Ident struct { NamePos token.Pos // identifier position Name string // identifier name - Obj *Object // denoted object; or nil + Obj *Object // denoted object; or nil if the referenced declaration is not found in the parsed scope } // An Ellipsis node stands for the "..." type in a -- GitLab From 9c56a64673d2f458e28c603f95b4efb5d39beef2 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Thu, 2 Sep 2021 14:38:58 -0700 Subject: [PATCH 0996/2500] [dev.fuzz] internal/fuzz: maintain debug info during minimization Change-Id: I70c0229e43dfe37f70b9c79c2e6fe88d7b8d7bd0 Reviewed-on: https://go-review.googlesource.com/c/go/+/347231 Trust: Roland Shoemaker Run-TryBot: Roland Shoemaker TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/internal/fuzz/fuzz.go | 3 ++- src/internal/fuzz/worker.go | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 722933a0bf..5b940e4929 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -341,10 +341,11 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err if printDebugInfo() { fmt.Fprintf( c.opts.Log, - "DEBUG worker reported interesting input that doesn't expand coverage, elapsed: %s, id: %s, parent: %s\n", + "DEBUG worker reported interesting input that doesn't expand coverage, elapsed: %s, id: %s, parent: %s, minimized: %t\n", time.Since(c.startTime), result.entry.Name, result.entry.Parent, + result.minimizeAttempted, ) } } diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 2f5704094e..32b13662c8 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -1017,6 +1017,11 @@ func (wc *workerClient) minimize(ctx context.Context, entryIn CorpusEntry, args return CorpusEntry{}, minimizeResponse{}, errSharedMemClosed } entryOut.Data = mem.valueCopy() + h := sha256.Sum256(entryOut.Data) + name := fmt.Sprintf("%x", h[:4]) + entryOut.Name = name + entryOut.Parent = entryIn.Parent + entryOut.Generation = entryIn.Generation resp.Count = mem.header().count return entryOut, resp, callErr -- GitLab From 04d8d249600bf7b350454175c521e0c251785956 Mon Sep 17 00:00:00 2001 From: rhysd Date: Tue, 13 Jul 2021 23:05:17 +0900 Subject: [PATCH 0997/2500] misc/wasm: enable ECMAScript strict mode Current wasm_exec.js does not enable ECMAScript strict mode. But it is recommended to be enabled because it 1. eliminates some ECMAScript silent errors by changing them to throw errors 2. fixes mistakes that make it difficult for JavaScript engines to perform optimizations 3. prohibits some syntax likely to be defined in future versions of ECMAScript This commit enables ECMAScript strict mode in wasm_exec.js following the transition guide: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode/Transitioning_to_strict_mode Fixes #47116 Change-Id: Ib8ffceee37e9127698fb51304241f1e429efe83e Reviewed-on: https://go-review.googlesource.com/c/go/+/334269 Reviewed-by: Richard Musiol Reviewed-by: Cherry Mui Trust: Richard Musiol Run-TryBot: Cherry Mui TryBot-Result: Go Bot --- misc/wasm/wasm_exec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/misc/wasm/wasm_exec.js b/misc/wasm/wasm_exec.js index 231185a123..22b19fbe80 100644 --- a/misc/wasm/wasm_exec.js +++ b/misc/wasm/wasm_exec.js @@ -1,6 +1,7 @@ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +"use strict"; (() => { // Map multiple JavaScript environments to a single common API, -- GitLab From d9244f8b641e8f60ab4b6edd976f1762606649e3 Mon Sep 17 00:00:00 2001 From: Tim King Date: Fri, 3 Sep 2021 20:27:35 +0000 Subject: [PATCH 0998/2500] Revert "go/ast: clarify when Ident.Obj is nil" This reverts commit 52aef05498a9e84ede16fb7ce46a2a252af05479. Reason for revert: After discussion on CL 347530, it is not clear this is an improvement to the documentation. Updates #48141 Change-Id: I5f3d9995c5f5666b92602c4b8ec393673baa73fc Reviewed-on: https://go-review.googlesource.com/c/go/+/347592 Trust: Cherry Mui Trust: Robert Findley Reviewed-by: Robert Findley --- src/go/ast/ast.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/go/ast/ast.go b/src/go/ast/ast.go index f6abb2d175..b0f1330564 100644 --- a/src/go/ast/ast.go +++ b/src/go/ast/ast.go @@ -290,7 +290,7 @@ type ( Ident struct { NamePos token.Pos // identifier position Name string // identifier name - Obj *Object // denoted object; or nil if the referenced declaration is not found in the parsed scope + Obj *Object // denoted object; or nil } // An Ellipsis node stands for the "..." type in a -- GitLab From 4957976b1a1f67ba872cc281b9ae25d59f6e003d Mon Sep 17 00:00:00 2001 From: Tao Qingyun Date: Thu, 1 Jul 2021 00:22:51 +0000 Subject: [PATCH 0999/2500] cmd/link: make npkgsyms meaningful npkgsyms always equals 1 currently. Change-Id: Ie88bc273beaace12ec7432054ca7c151396e8e35 GitHub-Last-Rev: c5d3b12b88ddcdc6011f97787fd7c0e94c7df20e GitHub-Pull-Request: golang/go#46988 Reviewed-on: https://go-review.googlesource.com/c/go/+/331929 Reviewed-by: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Trust: Dmitri Shuralyov --- src/cmd/link/internal/loader/loader.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index 9d5319c312..f144e00f37 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -2209,7 +2209,6 @@ func (l *Loader) LoadSyms(arch *sys.Arch) { // Index 0 is invalid for symbols. l.objSyms = make([]objSym, 1, symSize) - l.npkgsyms = l.NSym() st := loadState{ l: l, hashed64Syms: make(map[uint64]symAndSize, hashed64Size), @@ -2219,6 +2218,7 @@ func (l *Loader) LoadSyms(arch *sys.Arch) { for _, o := range l.objs[goObjStart:] { st.preloadSyms(o.r, pkgDef) } + l.npkgsyms = l.NSym() for _, o := range l.objs[goObjStart:] { st.preloadSyms(o.r, hashed64Def) st.preloadSyms(o.r, hashedDef) -- GitLab From 9cb5716f009ea71564a9ee84d653d7a76adf9926 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Tue, 17 Aug 2021 18:45:11 +0000 Subject: [PATCH 1000/2500] cmd/internal/obj/riscv: avoid obj.Prog rewriting for constant loads Rather than rewriting the obj.Prog for a MOV pseudo-instruction targeting a constant to register load, generate the appropriate machine instruction sequence directly. Change-Id: I38e62f282b39be2a0a241f32280d306558d49b44 Reviewed-on: https://go-review.googlesource.com/c/go/+/344450 Trust: Joel Sing Reviewed-by: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot --- src/cmd/asm/internal/asm/testdata/riscv64.s | 2 + src/cmd/internal/obj/riscv/obj.go | 52 +++++++++------------ 2 files changed, 24 insertions(+), 30 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/riscv64.s b/src/cmd/asm/internal/asm/testdata/riscv64.s index 173c50f2e1..b22d1a7e37 100644 --- a/src/cmd/asm/internal/asm/testdata/riscv64.s +++ b/src/cmd/asm/internal/asm/testdata/riscv64.s @@ -282,6 +282,8 @@ start: MOV X5, X6 // 13830200 MOV $2047, X5 // 9b02f07f MOV $-2048, X5 // 9b020080 + MOV $2048, X5 // b71200009b820280 + MOV $-2049, X5 // b7f2ffff9b82f27f // Converted to load of symbol. MOV $4294967296, X5 // 97020000 diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index f602183e04..3ccd489573 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -305,42 +305,12 @@ func rewriteMOV(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog) { } case obj.TYPE_CONST: - // MOV $c, R - // If c is small enough, convert to: - // ADD $c, ZERO, R - // If not, convert to: - // LUI top20bits(c), R - // ADD bottom12bits(c), R, R if p.As != AMOV { ctxt.Diag("%v: unsupported constant load", p) } if p.To.Type != obj.TYPE_REG { ctxt.Diag("%v: constant load must target register", p) } - off := p.From.Offset - to := p.To - - low, high, err := Split32BitImmediate(off) - if err != nil { - ctxt.Diag("%v: constant %d too large: %v", p, off, err) - } - - // LUI is only necessary if the offset doesn't fit in 12-bits. - needLUI := high != 0 - if needLUI { - p.As = ALUI - p.To = to - // Pass top 20 bits to LUI. - p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: high} - p = obj.Appendp(p, newprog) - } - p.As = AADDIW - p.To = to - p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: low} - p.Reg = REG_ZERO - if needLUI { - p.Reg = to.Reg - } case obj.TYPE_ADDR: // MOV $sym+off(SP/SB), R if p.To.Type != obj.TYPE_REG || p.As != AMOV { @@ -1845,6 +1815,28 @@ func instructionsForMOV(p *obj.Prog) []*instruction { inss := []*instruction{ins} switch { + case p.From.Type == obj.TYPE_CONST && p.To.Type == obj.TYPE_REG: + // Handle constant to register moves. + low, high, err := Split32BitImmediate(ins.imm) + if err != nil { + p.Ctxt.Diag("%v: constant %d too large: %v", p, ins.imm, err) + return nil + } + + // MOV $c, R -> ADD $c, ZERO, R + ins.as, ins.rs1, ins.rs2, ins.imm = AADDIW, REG_ZERO, obj.REG_NONE, low + + // LUI is only necessary if the constant does not fit in 12 bits. + if high == 0 { + break + } + + // LUI top20bits(c), R + // ADD bottom12bits(c), R, R + insLUI := &instruction{as: ALUI, rd: ins.rd, imm: high} + ins.rs1 = ins.rd + inss = []*instruction{insLUI, ins} + case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG: // Handle register to register moves. switch p.As { -- GitLab From 8a01010c26a6be4ee94917360749c8f618d68079 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Wed, 18 Aug 2021 18:14:52 +0000 Subject: [PATCH 1001/2500] cmd/internal/obj/riscv: avoid obj.Prog rewriting for load instructions Rather than rewriting the obj.Prog for a load instruction, generate the appropriate machine instruction sequence directly. Change-Id: Iba656dbf2dff2bce02aa221d9a5cad7b7c4630d8 Reviewed-on: https://go-review.googlesource.com/c/go/+/344451 Trust: Joel Sing Reviewed-by: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot --- src/cmd/internal/obj/riscv/cpu.go | 8 ++- src/cmd/internal/obj/riscv/obj.go | 90 +++++++++++++++++-------------- 2 files changed, 55 insertions(+), 43 deletions(-) diff --git a/src/cmd/internal/obj/riscv/cpu.go b/src/cmd/internal/obj/riscv/cpu.go index b1324b62a0..1519dc1a63 100644 --- a/src/cmd/internal/obj/riscv/cpu.go +++ b/src/cmd/internal/obj/riscv/cpu.go @@ -256,15 +256,19 @@ var RISCV64DWARFRegisters = map[int16]int16{ // Prog.Mark flags. const ( + // USES_REG_TMP indicates that a machine instruction generated from the + // corresponding *obj.Prog uses the temporary register. + USES_REG_TMP = 1 << iota + // NEED_PCREL_ITYPE_RELOC is set on AUIPC instructions to indicate that // it is the first instruction in an AUIPC + I-type pair that needs a // R_RISCV_PCREL_ITYPE relocation. - NEED_PCREL_ITYPE_RELOC = 1 << 0 + NEED_PCREL_ITYPE_RELOC // NEED_PCREL_STYPE_RELOC is set on AUIPC instructions to indicate that // it is the first instruction in an AUIPC + S-type pair that needs a // R_RISCV_PCREL_STYPE relocation. - NEED_PCREL_STYPE_RELOC = 1 << 1 + NEED_PCREL_STYPE_RELOC ) // RISC-V mnemonics, as defined in the "opcodes" and "opcodes-pseudo" files diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index 3ccd489573..3d304c1b42 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -795,38 +795,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { p.Reg = q.Reg p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP} - // $imm, REG, TO (load $imm+(REG), TO) - case ALD, ALB, ALH, ALW, ALBU, ALHU, ALWU, AFLW, AFLD: - low, high, err := Split32BitImmediate(p.From.Offset) - if err != nil { - ctxt.Diag("%v: constant %d too large", p, p.From.Offset) - } - if high == 0 { - break // no need to split - } - q := *p - - // LUI $high, TMP - // ADD TMP, REG, TMP - // $low, TMP, TO - p.As = ALUI - p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: high} - p.Reg = 0 - p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP} - p.Spadj = 0 // needed if TO is SP - p = obj.Appendp(p, newprog) - - p.As = AADD - p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP} - p.Reg = q.From.Reg - p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP} - p = obj.Appendp(p, newprog) - - p.As = q.As - p.To = q.To - p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_TMP, Offset: low} - p.Reg = obj.REG_NONE - // $imm, REG, TO (store $imm+(TO), REG) case ASD, ASB, ASH, ASW, AFSW, AFSD: low, high, err := Split32BitImmediate(p.To.Offset) @@ -1793,6 +1761,10 @@ func (ins *instruction) validate(ctxt *obj.Link) { enc.validate(ctxt, ins) } +func (ins *instruction) usesRegTmp() bool { + return ins.rd == REG_TMP || ins.rs1 == REG_TMP || ins.rs2 == REG_TMP +} + // instructionForProg returns the default *obj.Prog to instruction mapping. func instructionForProg(p *obj.Prog) *instruction { ins := &instruction{ @@ -1808,6 +1780,43 @@ func instructionForProg(p *obj.Prog) *instruction { return ins } +func instructionsForLoad(p *obj.Prog) []*instruction { + if p.From.Type != obj.TYPE_MEM { + p.Ctxt.Diag("%v requires memory for source", p) + return nil + } + + switch p.As { + case ALD, ALB, ALH, ALW, ALBU, ALHU, ALWU, AFLW, AFLD: + default: + p.Ctxt.Diag("%v: unknown load instruction %v", p, p.As) + return nil + } + + // $imm, REG, TO (load $imm+(REG), TO) + ins := instructionForProg(p) + ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE + ins.imm = p.From.Offset + + low, high, err := Split32BitImmediate(ins.imm) + if err != nil { + p.Ctxt.Diag("%v: constant %d too large", p, ins.imm) + return nil + } + if high == 0 { + return []*instruction{ins} + } + + // LUI $high, TMP + // ADD TMP, REG, TMP + // $low, TMP, TO + insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high} + insADD := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: ins.rs1} + ins.rs1, ins.imm = REG_TMP, low + + return []*instruction{insLUI, insADD, ins} +} + // instructionsForMOV returns the machine instructions for an *obj.Prog that // uses a MOV pseudo-instruction. func instructionsForMOV(p *obj.Prog) []*instruction { @@ -1928,12 +1937,7 @@ func instructionsForProg(p *obj.Prog) []*instruction { return instructionsForMOV(p) case ALW, ALWU, ALH, ALHU, ALB, ALBU, ALD, AFLW, AFLD: - if p.From.Type != obj.TYPE_MEM { - p.Ctxt.Diag("%v requires memory for source", p) - return nil - } - ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE - ins.imm = p.From.Offset + return instructionsForLoad(p) case ASW, ASH, ASB, ASD, AFSW, AFSD: if p.To.Type != obj.TYPE_MEM { @@ -2104,9 +2108,13 @@ func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { for _, ins := range instructionsForProg(p) { ic, err := ins.encode() - if err == nil { - symcode = append(symcode, ic) + if err != nil { + break + } + if ins.usesRegTmp() { + p.Mark |= USES_REG_TMP } + symcode = append(symcode, ic) } } cursym.Size = int64(4 * len(symcode)) @@ -2120,7 +2128,7 @@ func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { } func isUnsafePoint(p *obj.Prog) bool { - return p.From.Reg == REG_TMP || p.To.Reg == REG_TMP || p.Reg == REG_TMP + return p.Mark&USES_REG_TMP == USES_REG_TMP || p.From.Reg == REG_TMP || p.To.Reg == REG_TMP || p.Reg == REG_TMP } var LinkRISCV64 = obj.LinkArch{ -- GitLab From 0b66310924ace48c15a3140843576d5b069762de Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Thu, 19 Aug 2021 05:33:01 +0000 Subject: [PATCH 1002/2500] cmd/internal/obj/riscv: avoid obj.Prog rewriting for store instructions Rather than rewriting the obj.Prog for a store instruction, generate the appropriate machine instruction sequence directly. Change-Id: I026250ca3d249a1013243948a4e567b708b72d0c Reviewed-on: https://go-review.googlesource.com/c/go/+/344452 Trust: Joel Sing Reviewed-by: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot --- src/cmd/internal/obj/riscv/obj.go | 75 ++++++++++++++++--------------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index 3d304c1b42..2ae3d7f301 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -794,37 +794,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { p.To = q.To p.Reg = q.Reg p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP} - - // $imm, REG, TO (store $imm+(TO), REG) - case ASD, ASB, ASH, ASW, AFSW, AFSD: - low, high, err := Split32BitImmediate(p.To.Offset) - if err != nil { - ctxt.Diag("%v: constant %d too large", p, p.To.Offset) - } - if high == 0 { - break // no need to split - } - q := *p - - // LUI $high, TMP - // ADD TMP, TO, TMP - // $low, REG, TMP - p.As = ALUI - p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: high} - p.Reg = 0 - p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP} - p.Spadj = 0 // needed if TO is SP - p = obj.Appendp(p, newprog) - - p.As = AADD - p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP} - p.Reg = q.To.Reg - p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP} - p = obj.Appendp(p, newprog) - - p.As = q.As - p.From = obj.Addr{Type: obj.TYPE_REG, Reg: q.From.Reg, Offset: 0} - p.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_TMP, Offset: low} } } @@ -1817,6 +1786,43 @@ func instructionsForLoad(p *obj.Prog) []*instruction { return []*instruction{insLUI, insADD, ins} } +func instructionsForStore(p *obj.Prog) []*instruction { + if p.To.Type != obj.TYPE_MEM { + p.Ctxt.Diag("%v requires memory for destination", p) + return nil + } + + switch p.As { + case ASW, ASH, ASB, ASD, AFSW, AFSD: + default: + p.Ctxt.Diag("%v: unknown store instruction %v", p, p.As) + return nil + } + + // $imm, REG, TO (store $imm+(TO), REG) + ins := instructionForProg(p) + ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE + ins.imm = p.To.Offset + + low, high, err := Split32BitImmediate(ins.imm) + if err != nil { + p.Ctxt.Diag("%v: constant %d too large", p, ins.imm) + return nil + } + if high == 0 { + return []*instruction{ins} + } + + // LUI $high, TMP + // ADD TMP, TO, TMP + // $low, REG, TMP + insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high} + insADD := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: ins.rd} + ins.rd, ins.imm = REG_TMP, low + + return []*instruction{insLUI, insADD, ins} +} + // instructionsForMOV returns the machine instructions for an *obj.Prog that // uses a MOV pseudo-instruction. func instructionsForMOV(p *obj.Prog) []*instruction { @@ -1940,12 +1946,7 @@ func instructionsForProg(p *obj.Prog) []*instruction { return instructionsForLoad(p) case ASW, ASH, ASB, ASD, AFSW, AFSD: - if p.To.Type != obj.TYPE_MEM { - p.Ctxt.Diag("%v requires memory for destination", p) - return nil - } - ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE - ins.imm = p.To.Offset + return instructionsForStore(p) case ALRW, ALRD: // Set aq to use acquire access ordering, which matches Go's memory requirements. -- GitLab From 5ec298d7b07c4a51149f57dece41f0e9c0d701c4 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Fri, 19 Mar 2021 14:09:59 +0000 Subject: [PATCH 1003/2500] cmd/internal/obj/riscv: avoid obj.Prog rewriting for memory loads Rather than rewriting the obj.Prog for a MOV pseudo-instruction targeting a memory to register load, generate the appropriate machine instruction sequence directly. Change-Id: I4c7292ba00f576ec71d4842b6ff27a8ce6db0650 Reviewed-on: https://go-review.googlesource.com/c/go/+/344454 Trust: Joel Sing Reviewed-by: Cherry Mui --- src/cmd/asm/internal/asm/testdata/riscv64.s | 4 +- src/cmd/internal/obj/riscv/obj.go | 67 ++++++++++++--------- 2 files changed, 39 insertions(+), 32 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/riscv64.s b/src/cmd/asm/internal/asm/testdata/riscv64.s index b22d1a7e37..6f37a940c7 100644 --- a/src/cmd/asm/internal/asm/testdata/riscv64.s +++ b/src/cmd/asm/internal/asm/testdata/riscv64.s @@ -285,8 +285,8 @@ start: MOV $2048, X5 // b71200009b820280 MOV $-2049, X5 // b7f2ffff9b82f27f - // Converted to load of symbol. - MOV $4294967296, X5 // 97020000 + // Converted to load of symbol (AUIPC + LD) + MOV $4294967296, X5 // 9702000083b20200 MOV (X5), X6 // 03b30200 MOV 4(X5), X6 // 03b34200 diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index 2ae3d7f301..88ffeee51f 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -227,32 +227,15 @@ func rewriteMOV(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog) { } switch p.From.Type { - case obj.TYPE_MEM: // MOV c(Rs), Rd -> L $c, Rs, Rd + case obj.TYPE_MEM: switch p.From.Name { case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE: if p.To.Type != obj.TYPE_REG { - ctxt.Diag("unsupported load at %v", p) + ctxt.Diag("unsupported load for %v", p) } - p.As = movToLoad(p.As) - p.From.Reg = addrToReg(p.From) case obj.NAME_EXTERN, obj.NAME_STATIC: - // AUIPC $off_hi, R - // L $off_lo, R - as := p.As - to := p.To - - p.As = AAUIPC p.Mark |= NEED_PCREL_ITYPE_RELOC - p.SetFrom3(obj.Addr{Type: obj.TYPE_CONST, Offset: p.From.Offset, Sym: p.From.Sym}) - p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: 0} - p.Reg = 0 - p.To = obj.Addr{Type: obj.TYPE_REG, Reg: to.Reg} - p = obj.Appendp(p, newprog) - - p.As = movToLoad(as) - p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: to.Reg, Offset: 0} - p.To = to default: ctxt.Diag("unsupported name %d for %v", p.From.Name, p) @@ -1749,22 +1732,25 @@ func instructionForProg(p *obj.Prog) *instruction { return ins } -func instructionsForLoad(p *obj.Prog) []*instruction { +// instructionsForLoad returns the machine instructions for a load. The load +// instruction is specified by as and the base/source register is specified +// by rs, instead of the obj.Prog. +func instructionsForLoad(p *obj.Prog, as obj.As, rs int16) []*instruction { if p.From.Type != obj.TYPE_MEM { p.Ctxt.Diag("%v requires memory for source", p) return nil } - switch p.As { + switch as { case ALD, ALB, ALH, ALW, ALBU, ALHU, ALWU, AFLW, AFLD: default: - p.Ctxt.Diag("%v: unknown load instruction %v", p, p.As) + p.Ctxt.Diag("%v: unknown load instruction %v", p, as) return nil } // $imm, REG, TO (load $imm+(REG), TO) ins := instructionForProg(p) - ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE + ins.as, ins.rs1, ins.rs2 = as, uint32(rs), obj.REG_NONE ins.imm = p.From.Offset low, high, err := Split32BitImmediate(ins.imm) @@ -1887,6 +1873,21 @@ func instructionsForMOV(p *obj.Prog) []*instruction { inss = append(inss, ins2) } + case p.From.Type == obj.TYPE_MEM && p.To.Type == obj.TYPE_REG: + // Memory to register loads. + switch p.From.Name { + case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE: + // MOV c(Rs), Rd -> L $c, Rs, Rd + inss = instructionsForLoad(p, movToLoad(p.As), addrToReg(p.From)) + + case obj.NAME_EXTERN, obj.NAME_STATIC: + // AUIPC $off_hi, Rd + // L $off_lo, Rd, Rd + insAUIPC := &instruction{as: AAUIPC, rd: ins.rd} + ins.as, ins.rs1, ins.rs2, ins.imm = movToLoad(p.As), ins.rd, obj.REG_NONE, 0 + inss = []*instruction{insAUIPC, ins} + } + default: // If we get here with a MOV pseudo-instruction it is going to // remain unhandled. For now we trust rewriteMOV to catch these. @@ -1943,7 +1944,7 @@ func instructionsForProg(p *obj.Prog) []*instruction { return instructionsForMOV(p) case ALW, ALWU, ALH, ALHU, ALB, ALBU, ALD, AFLW, AFLD: - return instructionsForLoad(p) + return instructionsForLoad(p, ins.as, p.From.Reg) case ASW, ASH, ASB, ASD, AFSW, AFSD: return instructionsForStore(p) @@ -2073,22 +2074,28 @@ func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { rel.Add = p.To.Offset rel.Type = objabi.R_CALLRISCV } - case AAUIPC: + + case AAUIPC, AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD: + var addr *obj.Addr var rt objabi.RelocType if p.Mark&NEED_PCREL_ITYPE_RELOC == NEED_PCREL_ITYPE_RELOC { rt = objabi.R_RISCV_PCREL_ITYPE + addr = &p.From } else if p.Mark&NEED_PCREL_STYPE_RELOC == NEED_PCREL_STYPE_RELOC { rt = objabi.R_RISCV_PCREL_STYPE + addr = &p.To } else { break } - if p.Link == nil { - ctxt.Diag("AUIPC needing PC-relative reloc missing following instruction") - break + if p.As == AAUIPC { + if p.Link == nil { + ctxt.Diag("AUIPC needing PC-relative reloc missing following instruction") + break + } + addr = &p.RestArgs[0].Addr } - addr := p.RestArgs[0] if addr.Sym == nil { - ctxt.Diag("AUIPC needing PC-relative reloc missing symbol") + ctxt.Diag("PC-relative relocation missing symbol") break } if addr.Sym.Type == objabi.STLSBSS { -- GitLab From ba66d62b688d50f4e89b724d1c5b48bb05f8b117 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Tue, 17 Aug 2021 18:25:05 +0000 Subject: [PATCH 1004/2500] cmd/internal/obj/riscv: avoid obj.Prog rewriting for memory stores Rather than rewriting the obj.Prog for a MOV pseudo-instruction targeting a register to memory stores, generate the appropriate machine instruction sequence directly. Change-Id: I6eac8637e1fcb48c04d9f331cac7ae5d8cc54092 Reviewed-on: https://go-review.googlesource.com/c/go/+/344455 Trust: Joel Sing Reviewed-by: Cherry Mui --- src/cmd/internal/obj/riscv/obj.go | 52 +++++++++++++++++-------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index 88ffeee51f..ba806fca49 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -250,7 +250,7 @@ func rewriteMOV(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog) { ctxt.Diag("unsupported register-register move at %v", p) } - case obj.TYPE_MEM: // MOV Rs, c(Rd) -> S $c, Rs, Rd + case obj.TYPE_MEM: switch p.As { case AMOVBU, AMOVHU, AMOVWU: ctxt.Diag("unsupported unsigned store at %v", p) @@ -258,26 +258,9 @@ func rewriteMOV(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog) { } switch p.To.Name { case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE: - p.As = movToStore(p.As) - p.To.Reg = addrToReg(p.To) case obj.NAME_EXTERN, obj.NAME_STATIC: - // AUIPC $off_hi, TMP - // S $off_lo, TMP, R - as := p.As - from := p.From - - p.As = AAUIPC p.Mark |= NEED_PCREL_STYPE_RELOC - p.SetFrom3(obj.Addr{Type: obj.TYPE_CONST, Offset: p.To.Offset, Sym: p.To.Sym}) - p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: 0} - p.Reg = 0 - p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP} - p = obj.Appendp(p, newprog) - - p.As = movToStore(as) - p.From = from - p.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_TMP, Offset: 0} default: ctxt.Diag("unsupported name %d for %v", p.From.Name, p) @@ -1772,22 +1755,25 @@ func instructionsForLoad(p *obj.Prog, as obj.As, rs int16) []*instruction { return []*instruction{insLUI, insADD, ins} } -func instructionsForStore(p *obj.Prog) []*instruction { +// instructionsForStore returns the machine instructions for a store. The store +// instruction is specified by as and the target/source register is specified +// by rd, instead of the obj.Prog. +func instructionsForStore(p *obj.Prog, as obj.As, rd int16) []*instruction { if p.To.Type != obj.TYPE_MEM { p.Ctxt.Diag("%v requires memory for destination", p) return nil } - switch p.As { + switch as { case ASW, ASH, ASB, ASD, AFSW, AFSD: default: - p.Ctxt.Diag("%v: unknown store instruction %v", p, p.As) + p.Ctxt.Diag("%v: unknown store instruction %v", p, as) return nil } // $imm, REG, TO (store $imm+(TO), REG) ins := instructionForProg(p) - ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE + ins.as, ins.rd, ins.rs1, ins.rs2 = as, uint32(rd), uint32(p.From.Reg), obj.REG_NONE ins.imm = p.To.Offset low, high, err := Split32BitImmediate(ins.imm) @@ -1888,6 +1874,26 @@ func instructionsForMOV(p *obj.Prog) []*instruction { inss = []*instruction{insAUIPC, ins} } + case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM: + // Register to memory stores. + switch p.As { + case AMOVBU, AMOVHU, AMOVWU: + // rewriteMOV should have already added an error for these. + return nil + } + switch p.To.Name { + case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE: + // MOV Rs, c(Rd) -> S $c, Rs, Rd + inss = instructionsForStore(p, movToStore(p.As), addrToReg(p.To)) + + case obj.NAME_EXTERN, obj.NAME_STATIC: + // AUIPC $off_hi, Rtmp + // S $off_lo, Rtmp, Rd + insAUIPC := &instruction{as: AAUIPC, rd: REG_TMP} + ins.as, ins.rd, ins.rs1, ins.rs2, ins.imm = movToStore(p.As), REG_TMP, uint32(p.From.Reg), obj.REG_NONE, 0 + inss = []*instruction{insAUIPC, ins} + } + default: // If we get here with a MOV pseudo-instruction it is going to // remain unhandled. For now we trust rewriteMOV to catch these. @@ -1947,7 +1953,7 @@ func instructionsForProg(p *obj.Prog) []*instruction { return instructionsForLoad(p, ins.as, p.From.Reg) case ASW, ASH, ASB, ASD, AFSW, AFSD: - return instructionsForStore(p) + return instructionsForStore(p, ins.as, p.To.Reg) case ALRW, ALRD: // Set aq to use acquire access ordering, which matches Go's memory requirements. -- GitLab From 5c224ec92102d7803c03ed2b482a68fad91b954b Mon Sep 17 00:00:00 2001 From: korzhao Date: Mon, 2 Aug 2021 16:53:25 +0000 Subject: [PATCH 1005/2500] database/sql: improve the documentation of Conn.Raw Fixes #47500 Change-Id: Ibd44e4db15ea45bb53a6651a6567edfe6104d3d6 GitHub-Last-Rev: 61b8abbc28908fc807af7188e19089ac454b4817 GitHub-Pull-Request: golang/go#47503 Reviewed-on: https://go-review.googlesource.com/c/go/+/338970 Reviewed-by: Daniel Theophanes Trust: Cherry Mui --- src/database/sql/sql.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/database/sql/sql.go b/src/database/sql/sql.go index 68fb392e0d..b40b5c8fe4 100644 --- a/src/database/sql/sql.go +++ b/src/database/sql/sql.go @@ -2002,8 +2002,8 @@ func (c *Conn) PrepareContext(ctx context.Context, query string) (*Stmt, error) // Raw executes f exposing the underlying driver connection for the // duration of f. The driverConn must not be used outside of f. // -// Once f returns and err is nil, the Conn will continue to be usable -// until Conn.Close is called. +// Once f returns and err is not equal to driver.ErrBadConn, the Conn will +// continue to be usable until Conn.Close is called. func (c *Conn) Raw(f func(driverConn interface{}) error) (err error) { var dc *driverConn var release releaseConn -- GitLab From 2d90df91a8ef00e20d8244c3c39fb0c22c382161 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Thu, 19 Aug 2021 08:35:12 +0000 Subject: [PATCH 1006/2500] cmd/internal/obj/riscv: avoid obj.Prog rewriting for immediate splitting Rather than rewriting the obj.Prog for a immediate instructions that need splitting, generate the appropriate machine instruction sequence directly. Change-Id: Ie90f0e2a98f97a29281e445c4c3b0c47b793ef4d Reviewed-on: https://go-review.googlesource.com/c/go/+/344453 Trust: Joel Sing Reviewed-by: Cherry Mui --- src/cmd/asm/internal/asm/testdata/riscv64.s | 19 +++- src/cmd/internal/obj/riscv/obj.go | 115 ++++++++------------ 2 files changed, 62 insertions(+), 72 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/riscv64.s b/src/cmd/asm/internal/asm/testdata/riscv64.s index 6f37a940c7..5a209ac17e 100644 --- a/src/cmd/asm/internal/asm/testdata/riscv64.s +++ b/src/cmd/asm/internal/asm/testdata/riscv64.s @@ -10,20 +10,35 @@ start: // 2.4: Integer Computational Instructions - ADDI $2047, X5, X6 // 1383f27f - ADDI $-2048, X5, X6 // 13830280 ADDI $2047, X5 // 9382f27f ADDI $-2048, X5 // 93820280 + ADDI $2048, X5 // 9382024093820240 + ADDI $-2049, X5 // 938202c09382f2bf + ADDI $4094, X5 // 9382f27f9382f27f + ADDI $-4096, X5 // 9382028093820280 + ADDI $4095, X5 // b71f00009b8fffffb382f201 + ADDI $-4097, X5 // b7ffffff9b8fffffb382f201 + ADDI $2047, X5, X6 // 1383f27f + ADDI $-2048, X5, X6 // 13830280 + ADDI $2048, X5, X6 // 1383024013030340 + ADDI $-2049, X5, X6 // 138302c01303f3bf + ADDI $4094, X5, X6 // 1383f27f1303f37f + ADDI $-4096, X5, X6 // 1383028013030380 + ADDI $4095, X5, X6 // b71f00009b8fffff3383f201 + ADDI $-4097, X5, X6 // b7ffffff9b8fffff3383f201 SLTI $55, X5, X7 // 93a37203 SLTIU $55, X5, X7 // 93b37203 ANDI $1, X5, X6 // 13f31200 ANDI $1, X5 // 93f21200 + ANDI $2048, X5 // b71f00009b8f0f80b3f2f201 ORI $1, X5, X6 // 13e31200 ORI $1, X5 // 93e21200 + ORI $2048, X5 // b71f00009b8f0f80b3e2f201 XORI $1, X5, X6 // 13c31200 XORI $1, X5 // 93c21200 + XORI $2048, X5 // b71f00009b8f0f80b3c2f201 SLLI $1, X5, X6 // 13931200 SLLI $1, X5 // 93921200 diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index ba806fca49..d0574edc41 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -693,76 +693,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { } } - // Split immediates larger than 12-bits. - for p := cursym.Func().Text; p != nil; p = p.Link { - switch p.As { - // $imm, REG, TO - case AADDI, AANDI, AORI, AXORI: - // LUI $high, TMP - // ADDI $low, TMP, TMP - // TMP, REG, TO - q := *p - low, high, err := Split32BitImmediate(p.From.Offset) - if err != nil { - ctxt.Diag("%v: constant %d too large", p, p.From.Offset, err) - } - if high == 0 { - break // no need to split - } - - // Split into two additions if possible. - imm := q.From.Offset - const minInt12, maxInt12 = -(1 << 11), (1 << 11) - 1 - if q.As == AADDI && 2*minInt12 <= imm && imm <= 2*maxInt12 { - imm0, imm1 := imm/2, imm-imm/2 - // ADDI $(imm/2), REG, TO - p.Spadj = 0 // needed if TO is SP - p.As = AADDI - p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: imm0} - p.Reg = q.Reg - p.To = q.To - p = obj.Appendp(p, newprog) - // ADDI $(imm-imm/2), TO, TO - p.Spadj = q.Spadj - p.As = AADDI - p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: imm1} - p.Reg = q.To.Reg - p.To = q.To - break - } - - p.As = ALUI - p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: high} - p.Reg = 0 - p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP} - p.Spadj = 0 // needed if TO is SP - p = obj.Appendp(p, newprog) - - p.As = AADDIW - p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: low} - p.Reg = REG_TMP - p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP} - p = obj.Appendp(p, newprog) - - switch q.As { - case AADDI: - p.As = AADD - case AANDI: - p.As = AAND - case AORI: - p.As = AOR - case AXORI: - p.As = AXOR - default: - ctxt.Diag("unsupported instruction %v for splitting", q) - } - p.Spadj = q.Spadj - p.To = q.To - p.Reg = q.Reg - p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP} - } - } - // Compute instruction addresses. Once we do that, we need to check for // overextended jumps and branches. Within each iteration, Pc differences // are always lower bounds (since the program gets monotonically longer, @@ -1960,6 +1890,51 @@ func instructionsForProg(p *obj.Prog) []*instruction { ins.funct7 = 2 ins.rs1, ins.rs2 = uint32(p.From.Reg), REG_ZERO + case AADDI, AANDI, AORI, AXORI: + // $imm, REG, TO + low, high, err := Split32BitImmediate(ins.imm) + if err != nil { + p.Ctxt.Diag("%v: constant %d too large", p, ins.imm, err) + return nil + } + if high == 0 { + break + } + + // Split into two additions if possible. + if ins.as == AADDI && ins.imm >= -(1<<12) && ins.imm < 1<<12-1 { + imm0 := ins.imm / 2 + imm1 := ins.imm - imm0 + + // ADDI $(imm/2), REG, TO + // ADDI $(imm-imm/2), TO, TO + ins.imm = imm0 + insADDI := &instruction{as: AADDI, rd: ins.rd, rs1: ins.rd, imm: imm1} + inss = append(inss, insADDI) + break + } + + // LUI $high, TMP + // ADDI $low, TMP, TMP + // TMP, REG, TO + insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high} + insADDIW := &instruction{as: AADDIW, rd: REG_TMP, rs1: REG_TMP, imm: low} + switch ins.as { + case AADDI: + ins.as = AADD + case AANDI: + ins.as = AAND + case AORI: + ins.as = AOR + case AXORI: + ins.as = AXOR + default: + p.Ctxt.Diag("unsupported instruction %v for splitting", p) + return nil + } + ins.rs2 = REG_TMP + inss = []*instruction{insLUI, insADDIW, ins} + case ASCW, ASCD, AAMOSWAPW, AAMOSWAPD, AAMOADDW, AAMOADDD, AAMOANDW, AAMOANDD, AAMOORW, AAMOORD, AAMOXORW, AAMOXORD, AAMOMINW, AAMOMIND, AAMOMINUW, AAMOMINUD, AAMOMAXW, AAMOMAXD, AAMOMAXUW, AAMOMAXUD: // Set aq to use acquire access ordering, which matches Go's memory requirements. -- GitLab From 37e9c1d6fe453458a203595277147ae713650a3a Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Fri, 20 Aug 2021 17:04:35 +0000 Subject: [PATCH 1007/2500] cmd/internal/obj/riscv: avoid obj.Prog rewriting for address to register loads Rather than rewriting the obj.Prog for a MOV pseudo-instruction targeting an address to register load, generate the appropriate machine instruction sequence directly. Change-Id: I507195b6d24ff3253eadcc807ddbe27dca97d220 Reviewed-on: https://go-review.googlesource.com/c/go/+/344456 Trust: Joel Sing Reviewed-by: Cherry Mui --- src/cmd/internal/obj/riscv/obj.go | 149 ++++++++++++++++-------------- 1 file changed, 79 insertions(+), 70 deletions(-) diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index d0574edc41..b4aded3768 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -278,39 +278,15 @@ func rewriteMOV(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog) { ctxt.Diag("%v: constant load must target register", p) } - case obj.TYPE_ADDR: // MOV $sym+off(SP/SB), R + case obj.TYPE_ADDR: if p.To.Type != obj.TYPE_REG || p.As != AMOV { ctxt.Diag("unsupported addr MOV at %v", p) } switch p.From.Name { - case obj.NAME_EXTERN, obj.NAME_STATIC: - // AUIPC $off_hi, R - // ADDI $off_lo, R - to := p.To + case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE: - p.As = AAUIPC + case obj.NAME_EXTERN, obj.NAME_STATIC: p.Mark |= NEED_PCREL_ITYPE_RELOC - p.SetFrom3(obj.Addr{Type: obj.TYPE_CONST, Offset: p.From.Offset, Sym: p.From.Sym}) - p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: 0} - p.Reg = 0 - p.To = to - p = obj.Appendp(p, newprog) - - p.As = AADDI - p.From = obj.Addr{Type: obj.TYPE_CONST} - p.Reg = to.Reg - p.To = to - - case obj.NAME_PARAM, obj.NAME_AUTO: - p.As = AADDI - p.Reg = REG_SP - p.From.Type = obj.TYPE_CONST - - case obj.NAME_NONE: - p.As = AADDI - p.Reg = p.From.Reg - p.From.Type = obj.TYPE_CONST - p.From.Reg = 0 default: ctxt.Diag("bad addr MOV from name %v at %v", p.From.Name, p) @@ -1645,6 +1621,57 @@ func instructionForProg(p *obj.Prog) *instruction { return ins } +// instructionsForOpImmediate returns the machine instructions for a immedate +// operand. The instruction is specified by as and the source register is +// specified by rs, instead of the obj.Prog. +func instructionsForOpImmediate(p *obj.Prog, as obj.As, rs int16) []*instruction { + // $imm, REG, TO + ins := instructionForProg(p) + ins.as, ins.rs1 = as, uint32(rs) + + low, high, err := Split32BitImmediate(ins.imm) + if err != nil { + p.Ctxt.Diag("%v: constant %d too large", p, ins.imm, err) + return nil + } + if high == 0 { + return []*instruction{ins} + } + + // Split into two additions, if possible. + if ins.as == AADDI && ins.imm >= -(1<<12) && ins.imm < 1<<12-1 { + imm0 := ins.imm / 2 + imm1 := ins.imm - imm0 + + // ADDI $(imm/2), REG, TO + // ADDI $(imm-imm/2), TO, TO + ins.imm = imm0 + insADDI := &instruction{as: AADDI, rd: ins.rd, rs1: ins.rd, imm: imm1} + return []*instruction{ins, insADDI} + } + + // LUI $high, TMP + // ADDI $low, TMP, TMP + // TMP, REG, TO + insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high} + insADDIW := &instruction{as: AADDIW, rd: REG_TMP, rs1: REG_TMP, imm: low} + switch ins.as { + case AADDI: + ins.as = AADD + case AANDI: + ins.as = AAND + case AORI: + ins.as = AOR + case AXORI: + ins.as = AXOR + default: + p.Ctxt.Diag("unsupported immediate instruction %v for splitting", p) + return nil + } + ins.rs2 = REG_TMP + return []*instruction{insLUI, insADDIW, ins} +} + // instructionsForLoad returns the machine instructions for a load. The load // instruction is specified by as and the base/source register is specified // by rs, instead of the obj.Prog. @@ -1797,6 +1824,9 @@ func instructionsForMOV(p *obj.Prog) []*instruction { inss = instructionsForLoad(p, movToLoad(p.As), addrToReg(p.From)) case obj.NAME_EXTERN, obj.NAME_STATIC: + // Note that the values for $off_hi and $off_lo are currently + // zero and will be assigned during relocation. + // // AUIPC $off_hi, Rd // L $off_lo, Rd, Rd insAUIPC := &instruction{as: AAUIPC, rd: ins.rd} @@ -1817,6 +1847,9 @@ func instructionsForMOV(p *obj.Prog) []*instruction { inss = instructionsForStore(p, movToStore(p.As), addrToReg(p.To)) case obj.NAME_EXTERN, obj.NAME_STATIC: + // Note that the values for $off_hi and $off_lo are currently + // zero and will be assigned during relocation. + // // AUIPC $off_hi, Rtmp // S $off_lo, Rtmp, Rd insAUIPC := &instruction{as: AAUIPC, rd: REG_TMP} @@ -1824,6 +1857,24 @@ func instructionsForMOV(p *obj.Prog) []*instruction { inss = []*instruction{insAUIPC, ins} } + case p.From.Type == obj.TYPE_ADDR && p.To.Type == obj.TYPE_REG: + // MOV $sym+off(SP/SB), R + + switch p.From.Name { + case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE: + inss = instructionsForOpImmediate(p, AADDI, addrToReg(p.From)) + + case obj.NAME_EXTERN, obj.NAME_STATIC: + // Note that the values for $off_hi and $off_lo are currently + // zero and will be assigned during relocation. + // + // AUIPC $off_hi, R + // ADDI $off_lo, R + insAUIPC := &instruction{as: AAUIPC, rd: ins.rd} + ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, ins.rd, obj.REG_NONE, 0 + inss = []*instruction{insAUIPC, ins} + } + default: // If we get here with a MOV pseudo-instruction it is going to // remain unhandled. For now we trust rewriteMOV to catch these. @@ -1891,49 +1942,7 @@ func instructionsForProg(p *obj.Prog) []*instruction { ins.rs1, ins.rs2 = uint32(p.From.Reg), REG_ZERO case AADDI, AANDI, AORI, AXORI: - // $imm, REG, TO - low, high, err := Split32BitImmediate(ins.imm) - if err != nil { - p.Ctxt.Diag("%v: constant %d too large", p, ins.imm, err) - return nil - } - if high == 0 { - break - } - - // Split into two additions if possible. - if ins.as == AADDI && ins.imm >= -(1<<12) && ins.imm < 1<<12-1 { - imm0 := ins.imm / 2 - imm1 := ins.imm - imm0 - - // ADDI $(imm/2), REG, TO - // ADDI $(imm-imm/2), TO, TO - ins.imm = imm0 - insADDI := &instruction{as: AADDI, rd: ins.rd, rs1: ins.rd, imm: imm1} - inss = append(inss, insADDI) - break - } - - // LUI $high, TMP - // ADDI $low, TMP, TMP - // TMP, REG, TO - insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high} - insADDIW := &instruction{as: AADDIW, rd: REG_TMP, rs1: REG_TMP, imm: low} - switch ins.as { - case AADDI: - ins.as = AADD - case AANDI: - ins.as = AAND - case AORI: - ins.as = AOR - case AXORI: - ins.as = AXOR - default: - p.Ctxt.Diag("unsupported instruction %v for splitting", p) - return nil - } - ins.rs2 = REG_TMP - inss = []*instruction{insLUI, insADDIW, ins} + inss = instructionsForOpImmediate(p, ins.as, p.Reg) case ASCW, ASCD, AAMOSWAPW, AAMOSWAPD, AAMOADDW, AAMOADDD, AAMOANDW, AAMOANDD, AAMOORW, AAMOORD, AAMOXORW, AAMOXORD, AAMOMINW, AAMOMIND, AAMOMINUW, AAMOMINUD, AAMOMAXW, AAMOMAXD, AAMOMAXUW, AAMOMAXUD: -- GitLab From 28dae3defb06fb18aaadce5269e928e8ca3769e1 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Mon, 9 Aug 2021 08:14:04 +0000 Subject: [PATCH 1008/2500] cmd/internal/obj/riscv: improve code generation for loading of constants Loading of constants that are 12 bits or smaller is currently performed using a single ADDIW instruction, while constants between 13 bits and 32 bits are loaded using a LUI+ADDIW pair. Instead, use a single ADDI instruction for the 12 bits or smaller case - this translates to the LI pseudo-instruction, making objdump more readable and giving: 11c7c: fff00293 li t0,-1 11c80: 00000313 li t1,0 Rather than: 11c7c: fff0029b addiw t0,zero,-1 11c80: 0000031b sext.w t1,zero In the case where a constant exceeds 12 bits, an LUI instruction is required, however if the lower 12 bits are zero, the ADDIW instruction can be omitted. The same applies to the case where immediate splitting is performed for other immediate instructions. This removes around 900 instructions from the Go binary. Change-Id: Id6c77774b3b429fa525da018a6926b85df838a2f Reviewed-on: https://go-review.googlesource.com/c/go/+/344457 Trust: Joel Sing Run-TryBot: Joel Sing TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/asm/internal/asm/testdata/riscv64.s | 8 ++++++-- src/cmd/internal/obj/riscv/obj.go | 12 +++++++++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/riscv64.s b/src/cmd/asm/internal/asm/testdata/riscv64.s index 5a209ac17e..1977d92f62 100644 --- a/src/cmd/asm/internal/asm/testdata/riscv64.s +++ b/src/cmd/asm/internal/asm/testdata/riscv64.s @@ -295,10 +295,14 @@ start: // MOV pseudo-instructions MOV X5, X6 // 13830200 - MOV $2047, X5 // 9b02f07f - MOV $-2048, X5 // 9b020080 + MOV $2047, X5 // 9302f07f + MOV $-2048, X5 // 93020080 MOV $2048, X5 // b71200009b820280 MOV $-2049, X5 // b7f2ffff9b82f27f + MOV $4096, X5 // b7120000 + MOV $2147479552, X5 // b7f2ff7f + MOV $2147483647, X5 // b70200809b82f2ff + MOV $-2147483647, X5 // b70200809b821200 // Converted to load of symbol (AUIPC + LD) MOV $4294967296, X5 // 9702000083b20200 diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index b4aded3768..1140542739 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -1669,6 +1669,9 @@ func instructionsForOpImmediate(p *obj.Prog, as obj.As, rs int16) []*instruction return nil } ins.rs2 = REG_TMP + if low == 0 { + return []*instruction{insLUI, ins} + } return []*instruction{insLUI, insADDIW, ins} } @@ -1768,7 +1771,7 @@ func instructionsForMOV(p *obj.Prog) []*instruction { } // MOV $c, R -> ADD $c, ZERO, R - ins.as, ins.rs1, ins.rs2, ins.imm = AADDIW, REG_ZERO, obj.REG_NONE, low + ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, REG_ZERO, obj.REG_NONE, low // LUI is only necessary if the constant does not fit in 12 bits. if high == 0 { @@ -1778,8 +1781,11 @@ func instructionsForMOV(p *obj.Prog) []*instruction { // LUI top20bits(c), R // ADD bottom12bits(c), R, R insLUI := &instruction{as: ALUI, rd: ins.rd, imm: high} - ins.rs1 = ins.rd - inss = []*instruction{insLUI, ins} + inss = []*instruction{insLUI} + if low != 0 { + ins.as, ins.rs1 = AADDIW, ins.rd + inss = append(inss, ins) + } case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG: // Handle register to register moves. -- GitLab From 9133245be7365c23fcd60e3bb60ebb614970cdab Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 2 Sep 2021 16:43:29 -0700 Subject: [PATCH 1009/2500] cmd/compile/internal/types2: detect constraint type inference cycles See the detailed explanations in the code. Fixes #48136. Change-Id: I1667aabfbbff97967913b080c77e7ec04ea82feb Reviewed-on: https://go-review.googlesource.com/c/go/+/347300 Trust: Robert Griesemer Trust: Cuong Manh Le Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/infer.go | 124 ++++++++++++++++++ .../types2/testdata/fixedbugs/issue48136.go2 | 36 +++++ 2 files changed, 160 insertions(+) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue48136.go2 diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index 5badecc070..bb7270b346 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -9,6 +9,7 @@ package types2 import ( "bytes" "cmd/compile/internal/syntax" + "fmt" ) const useConstraintTypeInference = true @@ -409,6 +410,34 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type, report bool) (t } } + // The data structure of each (provided or inferred) type represents a graph, where + // each node corresponds to a type and each (directed) vertice points to a component + // type. The substitution process described above repeatedly replaces type parameter + // nodes in these graphs with the graphs of the types the type parameters stand for, + // which creates a new (possibly bigger) graph for each type. + // The substitution process will not stop if the replacement graph for a type parameter + // also contains that type parameter. + // For instance, for [A interface{ *A }], without any type argument provided for A, + // unification produces the type list [*A]. Substituting A in *A with the value for + // A will lead to infinite expansion by producing [**A], [****A], [********A], etc., + // because the graph A -> *A has a cycle through A. + // Generally, cycles may occur across multiple type parameters and inferred types + // (for instance, consider [P interface{ *Q }, Q interface{ func(P) }]). + // We eliminate cycles by walking the graphs for all type parameters. If a cycle + // through a type parameter is detected, cycleFinder nils out the respectice type + // which kills the cycle; this also means that the respective type could not be + // inferred. + // + // TODO(gri) If useful, we could report the respective cycle as an error. We don't + // do this now because type inference will fail anyway, and furthermore, + // constraints with cycles of this kind cannot currently be satisfied by + // any user-suplied type. But should that change, reporting an error + // would be wrong. + w := cycleFinder{tparams, types, make(map[Type]bool)} + for _, t := range tparams { + w.typ(t) // t != nil + } + // dirty tracks the indices of all types that may still contain type parameters. // We know that nil type entries and entries corresponding to provided (non-nil) // type arguments are clean, so exclude them from the start. @@ -457,3 +486,98 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type, report bool) (t return } + +type cycleFinder struct { + tparams []*TypeParam + types []Type + seen map[Type]bool +} + +func (w *cycleFinder) typ(typ Type) { + if w.seen[typ] { + // We have seen typ before. If it is one of the type parameters + // in tparams, iterative substitution will lead to infinite expansion. + // Nil out the corresponding type which effectively kills the cycle. + if tpar, _ := typ.(*TypeParam); tpar != nil { + if i := tparamIndex(w.tparams, tpar); i >= 0 { + // cycle through tpar + w.types[i] = nil + } + } + // If we don't have one of our type parameters, the cycle is due + // to an ordinary recursive type and we can just stop walking it. + return + } + w.seen[typ] = true + defer delete(w.seen, typ) + + switch t := typ.(type) { + case *Basic, *top: + // nothing to do + + case *Array: + w.typ(t.elem) + + case *Slice: + w.typ(t.elem) + + case *Struct: + w.varList(t.fields) + + case *Pointer: + w.typ(t.base) + + // case *Tuple: + // This case should not occur because tuples only appear + // in signatures where they are handled explicitly. + + case *Signature: + // There are no "method types" so we should never see a recv. + assert(t.recv == nil) + if t.params != nil { + w.varList(t.params.vars) + } + if t.results != nil { + w.varList(t.results.vars) + } + + case *Union: + for _, t := range t.terms { + w.typ(t.typ) + } + + case *Interface: + for _, m := range t.methods { + w.typ(m.typ) + } + for _, t := range t.embeddeds { + w.typ(t) + } + + case *Map: + w.typ(t.key) + w.typ(t.elem) + + case *Chan: + w.typ(t.elem) + + case *Named: + for _, tpar := range t.TArgs().list() { + w.typ(tpar) + } + + case *TypeParam: + if i := tparamIndex(w.tparams, t); i >= 0 && w.types[i] != nil { + w.typ(w.types[i]) + } + + default: + panic(fmt.Sprintf("unexpected %T", typ)) + } +} + +func (w *cycleFinder) varList(list []*Var) { + for _, v := range list { + w.typ(v.typ) + } +} diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48136.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48136.go2 new file mode 100644 index 0000000000..0ab92df40f --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48136.go2 @@ -0,0 +1,36 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func f1[P interface{ *P }]() {} +func f2[P interface{ func(P) }]() {} +func f3[P, Q interface{ func(Q) P }]() {} +func f4[P interface{ *Q }, Q interface{ func(P) }]() {} +func f5[P interface{ func(P) }]() {} +func f6[P interface { *Tree[P] }, Q any ]() {} + +func _() { + f1( /* ERROR cannot infer P */ ) + f2( /* ERROR cannot infer P */ ) + f3( /* ERROR cannot infer P */ ) + f4( /* ERROR cannot infer P */ ) + f5( /* ERROR cannot infer P */ ) + f6( /* ERROR cannot infer P */ ) +} + +type Tree[P any] struct { + left, right *Tree[P] + data P +} + +// test case from issue + +func foo[Src interface { func() Src }]() Src { + return foo[Src] +} + +func _() { + foo( /* ERROR cannot infer Src */ ) +} -- GitLab From 1b2d794ca3ba60c2dbc958a271662784a7122739 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Thu, 20 May 2021 09:57:04 -0700 Subject: [PATCH 1010/2500] reflect: allocate hiter as part of MapIter This reduces the number of allocations per reflect map iteration from two to one. For #46293 Change-Id: Ibcff5f42fc512e637b6e460bad4518e7ac83d4c3 Reviewed-on: https://go-review.googlesource.com/c/go/+/321889 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Reviewed-by: Keith Randall --- src/reflect/all_test.go | 7 ++-- src/reflect/value.go | 73 +++++++++++++++++++++++++++-------------- src/runtime/map.go | 10 +++--- 3 files changed, 56 insertions(+), 34 deletions(-) diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index 40ac6a95fa..6cb603cb16 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -370,10 +370,9 @@ func TestMapIterSet(t *testing.T) { iter.SetValue(e) } })) - // Making a *MapIter and making an hiter both allocate. - // Those should be the only two allocations. - if got != 2 { - t.Errorf("wanted 2 allocs, got %d", got) + // Making a *MapIter allocates. This should be the only allocation. + if got != 1 { + t.Errorf("wanted 1 alloc, got %d", got) } } diff --git a/src/reflect/value.go b/src/reflect/value.go index a8274cc871..1a61cb897c 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -1549,11 +1549,12 @@ func (v Value) MapKeys() []Value { if m != nil { mlen = maplen(m) } - it := mapiterinit(v.typ, m) + var it hiter + mapiterinit(v.typ, m, &it) a := make([]Value, mlen) var i int for i = 0; i < len(a); i++ { - key := mapiterkey(it) + key := mapiterkey(&it) if key == nil { // Someone deleted an entry from the map since we // called maplen above. It's a data race, but nothing @@ -1561,24 +1562,50 @@ func (v Value) MapKeys() []Value { break } a[i] = copyVal(keyType, fl, key) - mapiternext(it) + mapiternext(&it) } return a[:i] } +// hiter's structure matches runtime.hiter's structure. +// Having a clone here allows us to embed a map iterator +// inside type MapIter so that MapIters can be re-used +// without doing any allocations. +type hiter struct { + key unsafe.Pointer + elem unsafe.Pointer + t unsafe.Pointer + h unsafe.Pointer + buckets unsafe.Pointer + bptr unsafe.Pointer + overflow *[]unsafe.Pointer + oldoverflow *[]unsafe.Pointer + startBucket uintptr + offset uint8 + wrapped bool + B uint8 + i uint8 + bucket uintptr + checkBucket uintptr +} + +func (h hiter) initialized() bool { + return h.t != nil +} + // A MapIter is an iterator for ranging over a map. // See Value.MapRange. type MapIter struct { - m Value - it unsafe.Pointer + m Value + hiter hiter } // Key returns the key of the iterator's current map entry. func (it *MapIter) Key() Value { - if it.it == nil { + if !it.hiter.initialized() { panic("MapIter.Key called before Next") } - iterkey := mapiterkey(it.it) + iterkey := mapiterkey(&it.hiter) if iterkey == nil { panic("MapIter.Key called on exhausted iterator") } @@ -1592,10 +1619,10 @@ func (it *MapIter) Key() Value { // It is equivalent to dst.Set(it.Key()), but it avoids allocating a new Value. // As in Go, the key must be assignable to dst's type. func (it *MapIter) SetKey(dst Value) { - if it.it == nil { + if !it.hiter.initialized() { panic("MapIter.SetKey called before Next") } - iterkey := mapiterkey(it.it) + iterkey := mapiterkey(&it.hiter) if iterkey == nil { panic("MapIter.SetKey called on exhausted iterator") } @@ -1616,10 +1643,10 @@ func (it *MapIter) SetKey(dst Value) { // Value returns the value of the iterator's current map entry. func (it *MapIter) Value() Value { - if it.it == nil { + if !it.hiter.initialized() { panic("MapIter.Value called before Next") } - iterelem := mapiterelem(it.it) + iterelem := mapiterelem(&it.hiter) if iterelem == nil { panic("MapIter.Value called on exhausted iterator") } @@ -1633,10 +1660,10 @@ func (it *MapIter) Value() Value { // It is equivalent to dst.Set(it.Value()), but it avoids allocating a new Value. // As in Go, the value must be assignable to dst's type. func (it *MapIter) SetValue(dst Value) { - if it.it == nil { + if !it.hiter.initialized() { panic("MapIter.SetValue called before Next") } - iterelem := mapiterelem(it.it) + iterelem := mapiterelem(&it.hiter) if iterelem == nil { panic("MapIter.SetValue called on exhausted iterator") } @@ -1659,15 +1686,15 @@ func (it *MapIter) SetValue(dst Value) { // entry. It returns false when the iterator is exhausted; subsequent // calls to Key, Value, or Next will panic. func (it *MapIter) Next() bool { - if it.it == nil { - it.it = mapiterinit(it.m.typ, it.m.pointer()) + if !it.hiter.initialized() { + mapiterinit(it.m.typ, it.m.pointer(), &it.hiter) } else { - if mapiterkey(it.it) == nil { + if mapiterkey(&it.hiter) == nil { panic("MapIter.Next called on exhausted iterator") } - mapiternext(it.it) + mapiternext(&it.hiter) } - return mapiterkey(it.it) != nil + return mapiterkey(&it.hiter) != nil } // MapRange returns a range iterator for a map. @@ -3216,19 +3243,17 @@ func mapassign(t *rtype, m unsafe.Pointer, key, val unsafe.Pointer) //go:noescape func mapdelete(t *rtype, m unsafe.Pointer, key unsafe.Pointer) -// m escapes into the return value, but the caller of mapiterinit -// doesn't let the return value escape. //go:noescape -func mapiterinit(t *rtype, m unsafe.Pointer) unsafe.Pointer +func mapiterinit(t *rtype, m unsafe.Pointer, it *hiter) //go:noescape -func mapiterkey(it unsafe.Pointer) (key unsafe.Pointer) +func mapiterkey(it *hiter) (key unsafe.Pointer) //go:noescape -func mapiterelem(it unsafe.Pointer) (elem unsafe.Pointer) +func mapiterelem(it *hiter) (elem unsafe.Pointer) //go:noescape -func mapiternext(it unsafe.Pointer) +func mapiternext(it *hiter) //go:noescape func maplen(m unsafe.Pointer) int diff --git a/src/runtime/map.go b/src/runtime/map.go index 0cad1a354d..59b803d629 100644 --- a/src/runtime/map.go +++ b/src/runtime/map.go @@ -160,8 +160,8 @@ type bmap struct { } // A hash iteration structure. -// If you modify hiter, also change cmd/compile/internal/reflectdata/reflect.go to indicate -// the layout of this structure. +// If you modify hiter, also change cmd/compile/internal/reflectdata/reflect.go +// and reflect/value.go to match the layout of this structure. type hiter struct { key unsafe.Pointer // Must be in first position. Write nil to indicate iteration end (see cmd/compile/internal/walk/range.go). elem unsafe.Pointer // Must be in second position (see cmd/compile/internal/walk/range.go). @@ -806,6 +806,7 @@ func mapiterinit(t *maptype, h *hmap, it *hiter) { racereadpc(unsafe.Pointer(h), callerpc, abi.FuncPCABIInternal(mapiterinit)) } + it.t = t if h == nil || h.count == 0 { return } @@ -813,7 +814,6 @@ func mapiterinit(t *maptype, h *hmap, it *hiter) { if unsafe.Sizeof(hiter{})/goarch.PtrSize != 12 { throw("hash_iter size incorrect") // see cmd/compile/internal/reflectdata/reflect.go } - it.t = t it.h = h // grab snapshot of bucket state @@ -1336,10 +1336,8 @@ func reflect_mapdelete(t *maptype, h *hmap, key unsafe.Pointer) { } //go:linkname reflect_mapiterinit reflect.mapiterinit -func reflect_mapiterinit(t *maptype, h *hmap) *hiter { - it := new(hiter) +func reflect_mapiterinit(t *maptype, h *hmap, it *hiter) { mapiterinit(t, h, it) - return it } //go:linkname reflect_mapiternext reflect.mapiternext -- GitLab From 7619a4528d506277f44e8d4b70366b5b5633b40f Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Fri, 21 May 2021 09:35:46 -0700 Subject: [PATCH 1011/2500] reflect: improve panic when MapIter has no associated map Value it := new(reflect.MapIter) it.Next() This generates a nil pointer dereference panic from reflect.Value.pointer. Generate a clearer panic. For #46293 Change-Id: I32a22c797e1ba3a7b4e70b38ceb4dedb44d264fa Reviewed-on: https://go-review.googlesource.com/c/go/+/321890 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Keith Randall Reviewed-by: Brad Fitzpatrick --- src/reflect/value.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/reflect/value.go b/src/reflect/value.go index 1a61cb897c..90f31bae0a 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -1686,6 +1686,9 @@ func (it *MapIter) SetValue(dst Value) { // entry. It returns false when the iterator is exhausted; subsequent // calls to Key, Value, or Next will panic. func (it *MapIter) Next() bool { + if !it.m.IsValid() { + panic("MapIter.Next called on an iterator that does not have an associated map Value") + } if !it.hiter.initialized() { mapiterinit(it.m.typ, it.m.pointer(), &it.hiter) } else { -- GitLab From 43b05173a219e19697c2f9c6d98cf4d8667b7ca5 Mon Sep 17 00:00:00 2001 From: fanzha02 Date: Mon, 6 Sep 2021 11:06:16 +0800 Subject: [PATCH 1012/2500] cmd/compile: merge zero/sign extensions with UBFX/SBFX on arm64 The UBFX and SBFX already zero/sign extend the result. Further zero/sign extensions are thus unnecessary as long as they leave the top bits unaltered. This patch absorbs zero/sign extensions into UBFX/SBFX. Add the related test cases. Change-Id: I7c4516c8b52d677f77bf3aaedab87c4a28056ec0 Reviewed-on: https://go-review.googlesource.com/c/go/+/265039 Trust: fannie zhang Trust: Keith Randall Run-TryBot: fannie zhang TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/compile/internal/ssa/gen/ARM64.rules | 9 ++ src/cmd/compile/internal/ssa/rewriteARM64.go | 102 +++++++++++++++++++ test/codegen/bitfield.go | 16 +++ 3 files changed, 127 insertions(+) diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index 530e48bcb2..3b8f8fa457 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -1834,6 +1834,10 @@ (SRAconst [rc] (MOVWreg x)) && rc < 32 => (SBFX [armBFAuxInt(rc, 32-rc)] x) (SRAconst [rc] (MOVHreg x)) && rc < 16 => (SBFX [armBFAuxInt(rc, 16-rc)] x) (SRAconst [rc] (MOVBreg x)) && rc < 8 => (SBFX [armBFAuxInt(rc, 8-rc)] x) +// merge sbfx and sign-extension into sbfx +(MOVWreg (SBFX [bfc] x)) && bfc.getARM64BFwidth() <= 32 => (SBFX [bfc] x) +(MOVHreg (SBFX [bfc] x)) && bfc.getARM64BFwidth() <= 16 => (SBFX [bfc] x) +(MOVBreg (SBFX [bfc] x)) && bfc.getARM64BFwidth() <= 8 => (SBFX [bfc] x) // sbfiz/sbfx combinations: merge shifts into bitfield ops (SRAconst [sc] (SBFIZ [bfc] x)) && sc < bfc.getARM64BFlsb() @@ -1880,6 +1884,11 @@ // (x << lc) >> rc (SRLconst [rc] (SLLconst [lc] x)) && lc < rc => (UBFX [armBFAuxInt(rc-lc, 64-rc)] x) +// merge ubfx and zerso-extension into ubfx +(MOVWUreg (UBFX [bfc] x)) && bfc.getARM64BFwidth() <= 32 => (UBFX [bfc] x) +(MOVHUreg (UBFX [bfc] x)) && bfc.getARM64BFwidth() <= 16 => (UBFX [bfc] x) +(MOVBUreg (UBFX [bfc] x)) && bfc.getARM64BFwidth() <= 8 => (UBFX [bfc] x) + // ubfiz/ubfx combinations: merge shifts into bitfield ops (SRLconst [sc] (UBFX [bfc] x)) && sc < bfc.getARM64BFwidth() => (UBFX [armBFAuxInt(bfc.getARM64BFlsb()+sc, bfc.getARM64BFwidth()-sc)] x) diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index f7840c5503..0d5265e011 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -7187,6 +7187,23 @@ func rewriteValueARM64_OpARM64MOVBUreg(v *Value) bool { v.AddArg(x) return true } + // match: (MOVBUreg (UBFX [bfc] x)) + // cond: bfc.getARM64BFwidth() <= 8 + // result: (UBFX [bfc] x) + for { + if v_0.Op != OpARM64UBFX { + break + } + bfc := auxIntToArm64BitField(v_0.AuxInt) + x := v_0.Args[0] + if !(bfc.getARM64BFwidth() <= 8) { + break + } + v.reset(OpARM64UBFX) + v.AuxInt = arm64BitFieldToAuxInt(bfc) + v.AddArg(x) + return true + } return false } func rewriteValueARM64_OpARM64MOVBload(v *Value) bool { @@ -7401,6 +7418,23 @@ func rewriteValueARM64_OpARM64MOVBreg(v *Value) bool { v.AddArg(x) return true } + // match: (MOVBreg (SBFX [bfc] x)) + // cond: bfc.getARM64BFwidth() <= 8 + // result: (SBFX [bfc] x) + for { + if v_0.Op != OpARM64SBFX { + break + } + bfc := auxIntToArm64BitField(v_0.AuxInt) + x := v_0.Args[0] + if !(bfc.getARM64BFwidth() <= 8) { + break + } + v.reset(OpARM64SBFX) + v.AuxInt = arm64BitFieldToAuxInt(bfc) + v.AddArg(x) + return true + } return false } func rewriteValueARM64_OpARM64MOVBstore(v *Value) bool { @@ -10699,6 +10733,23 @@ func rewriteValueARM64_OpARM64MOVHUreg(v *Value) bool { v.AddArg(x) return true } + // match: (MOVHUreg (UBFX [bfc] x)) + // cond: bfc.getARM64BFwidth() <= 16 + // result: (UBFX [bfc] x) + for { + if v_0.Op != OpARM64UBFX { + break + } + bfc := auxIntToArm64BitField(v_0.AuxInt) + x := v_0.Args[0] + if !(bfc.getARM64BFwidth() <= 16) { + break + } + v.reset(OpARM64UBFX) + v.AuxInt = arm64BitFieldToAuxInt(bfc) + v.AddArg(x) + return true + } return false } func rewriteValueARM64_OpARM64MOVHload(v *Value) bool { @@ -11096,6 +11147,23 @@ func rewriteValueARM64_OpARM64MOVHreg(v *Value) bool { v.AddArg(x) return true } + // match: (MOVHreg (SBFX [bfc] x)) + // cond: bfc.getARM64BFwidth() <= 16 + // result: (SBFX [bfc] x) + for { + if v_0.Op != OpARM64SBFX { + break + } + bfc := auxIntToArm64BitField(v_0.AuxInt) + x := v_0.Args[0] + if !(bfc.getARM64BFwidth() <= 16) { + break + } + v.reset(OpARM64SBFX) + v.AuxInt = arm64BitFieldToAuxInt(bfc) + v.AddArg(x) + return true + } return false } func rewriteValueARM64_OpARM64MOVHstore(v *Value) bool { @@ -12811,6 +12879,23 @@ func rewriteValueARM64_OpARM64MOVWUreg(v *Value) bool { v.AddArg(x) return true } + // match: (MOVWUreg (UBFX [bfc] x)) + // cond: bfc.getARM64BFwidth() <= 32 + // result: (UBFX [bfc] x) + for { + if v_0.Op != OpARM64UBFX { + break + } + bfc := auxIntToArm64BitField(v_0.AuxInt) + x := v_0.Args[0] + if !(bfc.getARM64BFwidth() <= 32) { + break + } + v.reset(OpARM64UBFX) + v.AuxInt = arm64BitFieldToAuxInt(bfc) + v.AddArg(x) + return true + } return false } func rewriteValueARM64_OpARM64MOVWload(v *Value) bool { @@ -13266,6 +13351,23 @@ func rewriteValueARM64_OpARM64MOVWreg(v *Value) bool { v.AddArg(x) return true } + // match: (MOVWreg (SBFX [bfc] x)) + // cond: bfc.getARM64BFwidth() <= 32 + // result: (SBFX [bfc] x) + for { + if v_0.Op != OpARM64SBFX { + break + } + bfc := auxIntToArm64BitField(v_0.AuxInt) + x := v_0.Args[0] + if !(bfc.getARM64BFwidth() <= 32) { + break + } + v.reset(OpARM64SBFX) + v.AuxInt = arm64BitFieldToAuxInt(bfc) + v.AddArg(x) + return true + } return false } func rewriteValueARM64_OpARM64MOVWstore(v *Value) bool { diff --git a/test/codegen/bitfield.go b/test/codegen/bitfield.go index 0fe6799ec1..6c66e3ab6d 100644 --- a/test/codegen/bitfield.go +++ b/test/codegen/bitfield.go @@ -124,6 +124,12 @@ func sbfx6(x int32) int32 { return (x << 3) >> 4 // arm64:"SBFX\t[$]1, R[0-9]+, [$]28",-"LSL",-"ASR" } +// merge sbfx and sign-extension into sbfx. +func sbfx7(x int32) int64 { + c := x + 5 + return int64(c >> 20) // arm64"SBFX\t[$]20, R[0-9]+, [$]12",-"MOVW\tR[0-9]+, R[0-9]+" +} + // ubfiz func ubfiz1(x uint64) uint64 { // arm64:"UBFIZ\t[$]3, R[0-9]+, [$]12",-"LSL",-"AND" @@ -237,6 +243,16 @@ func ubfx11(x uint64) uint64 { return ((x & 0xfffff) << 3) >> 4 } +// merge ubfx and zero-extension into ubfx. +func ubfx12(x uint64) bool { + midr := x + 10 + part_num := uint16((midr >> 4) & 0xfff) + if part_num == 0xd0c { // arm64:"UBFX\t[$]4, R[0-9]+, [$]12",-"MOVHU\tR[0-9]+, R[0-9]+" + return true + } + return false +} + // Check that we don't emit comparisons for constant shifts. //go:nosplit func shift_no_cmp(x int) int { -- GitLab From 7b69ddc171938b8321a535dd79b8ca2ba56ac72d Mon Sep 17 00:00:00 2001 From: fanzha02 Date: Mon, 6 Sep 2021 11:15:30 +0800 Subject: [PATCH 1013/2500] cmd/compile: merge sign extension and shift into SBFIZ This patch adds some rules to rewrite "(LeftShift (SignExtend x) lc)" expression as "SBFIZ". Add the test cases. Change-Id: I294c4ba09712eeb02c7a952447bb006780f1e60d Reviewed-on: https://go-review.googlesource.com/c/go/+/267602 Trust: fannie zhang Trust: Cherry Mui Run-TryBot: fannie zhang TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/ssa/gen/ARM64.rules | 4 ++ src/cmd/compile/internal/ssa/rewriteARM64.go | 39 ++++++++++++++++++++ test/codegen/bitfield.go | 12 ++++++ 3 files changed, 55 insertions(+) diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index 3b8f8fa457..b44c8b826b 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -1827,6 +1827,10 @@ (MOVWreg (SLLconst [lc] x)) && lc < 32 => (SBFIZ [armBFAuxInt(lc, 32-lc)] x) (MOVHreg (SLLconst [lc] x)) && lc < 16 => (SBFIZ [armBFAuxInt(lc, 16-lc)] x) (MOVBreg (SLLconst [lc] x)) && lc < 8 => (SBFIZ [armBFAuxInt(lc, 8-lc)] x) +// int64(x) << lc +(SLLconst [lc] (MOVWreg x)) => (SBFIZ [armBFAuxInt(lc, min(32, 64-lc))] x) +(SLLconst [lc] (MOVHreg x)) => (SBFIZ [armBFAuxInt(lc, min(16, 64-lc))] x) +(SLLconst [lc] (MOVBreg x)) => (SBFIZ [armBFAuxInt(lc, min(8, 64-lc))] x) // sbfx // (x << lc) >> rc diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index 0d5265e011..f9175e92fd 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -20087,6 +20087,45 @@ func rewriteValueARM64_OpARM64SLLconst(v *Value) bool { v.AddArg(x) return true } + // match: (SLLconst [lc] (MOVWreg x)) + // result: (SBFIZ [armBFAuxInt(lc, min(32, 64-lc))] x) + for { + lc := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64MOVWreg { + break + } + x := v_0.Args[0] + v.reset(OpARM64SBFIZ) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(lc, min(32, 64-lc))) + v.AddArg(x) + return true + } + // match: (SLLconst [lc] (MOVHreg x)) + // result: (SBFIZ [armBFAuxInt(lc, min(16, 64-lc))] x) + for { + lc := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64MOVHreg { + break + } + x := v_0.Args[0] + v.reset(OpARM64SBFIZ) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(lc, min(16, 64-lc))) + v.AddArg(x) + return true + } + // match: (SLLconst [lc] (MOVBreg x)) + // result: (SBFIZ [armBFAuxInt(lc, min(8, 64-lc))] x) + for { + lc := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64MOVBreg { + break + } + x := v_0.Args[0] + v.reset(OpARM64SBFIZ) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(lc, min(8, 64-lc))) + v.AddArg(x) + return true + } // match: (SLLconst [sc] (ANDconst [ac] x)) // cond: isARM64BFMask(sc, ac, 0) // result: (UBFIZ [armBFAuxInt(sc, arm64BFWidth(ac, 0))] x) diff --git a/test/codegen/bitfield.go b/test/codegen/bitfield.go index 6c66e3ab6d..d4ffbad85d 100644 --- a/test/codegen/bitfield.go +++ b/test/codegen/bitfield.go @@ -99,6 +99,18 @@ func sbfiz5(x int32) int32 { return (x << 4) >> 3 } +func sbfiz5(x int32) int64 { + return int64(x+1) << 40 // arm64:"SBFIZ\t[$]40, R[0-9]+, [$]24",-"LSL" +} + +func sbfiz6(x int16) int64 { + return int64(x+1) << 3 // arm64:"SBFIZ\t[$]3, R[0-9]+, [$]16",-"LSL" +} + +func sbfiz7(x int8) int64 { + return int64(x+1) << 62 // arm64:"SBFIZ\t[$]62, R[0-9]+, [$]2",-"LSL" +} + // sbfx func sbfx1(x int64) int64 { return (x << 3) >> 4 // arm64:"SBFX\t[$]1, R[0-9]+, [$]60",-"LSL",-"ASR" -- GitLab From c7f09eeb1397e177508c8761c469dd377ce390cf Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Sun, 20 Jun 2021 12:59:45 +0800 Subject: [PATCH 1014/2500] cmd/internal/sys: declare loong64 arch Updates #46229 Change-Id: Icb736f2440443e9245872b091d13e5bdfb6cb01a Reviewed-on: https://go-review.googlesource.com/c/go/+/339009 Reviewed-by: Meng Zhuo Reviewed-by: Cherry Mui Trust: Meng Zhuo Trust: Michael Knyszek Run-TryBot: Meng Zhuo TryBot-Result: Go Bot --- src/cmd/internal/sys/arch.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/cmd/internal/sys/arch.go b/src/cmd/internal/sys/arch.go index a3e39768b6..e7063fde89 100644 --- a/src/cmd/internal/sys/arch.go +++ b/src/cmd/internal/sys/arch.go @@ -22,6 +22,7 @@ const ( RISCV64 S390X Wasm + Loong64 ) // Arch represents an individual architecture. @@ -189,6 +190,16 @@ var ArchWasm = &Arch{ Alignment: 1, } +var ArchLoong64 = &Arch{ + Name: "loong64", + Family: Loong64, + ByteOrder: binary.LittleEndian, + PtrSize: 8, + RegSize: 8, + MinLC: 4, + Alignment: 8, // Unaligned accesses are not guaranteed to be fast +} + var Archs = [...]*Arch{ Arch386, ArchAMD64, @@ -203,4 +214,5 @@ var Archs = [...]*Arch{ ArchRISCV64, ArchS390X, ArchWasm, + ArchLoong64, } -- GitLab From ecfff58fb8c3aabbce7b15c850210485c1f09d61 Mon Sep 17 00:00:00 2001 From: korzhao Date: Sun, 29 Aug 2021 14:36:20 +0800 Subject: [PATCH 1015/2500] cmd/compile: fix delay transformation in *subster.node() Add OCALL, OCALLFUNC, OCALLMETH, OCALLINTER, ODYNAMICDOTTYPE transformations to the CALL check switch statement. Fixes #48042 Change-Id: Ied93efd979c5b2c56b72fad26fccfd9f887361d3 Reviewed-on: https://go-review.googlesource.com/c/go/+/345949 Trust: Keith Randall Trust: Dan Scales Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 3 + test/typeparam/issue48042.go | 77 +++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 test/typeparam/issue48042.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 7ba266a150..3b15ac2c97 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1095,6 +1095,9 @@ func (subst *subster) node(n ir.Node) ir.Node { // or channel receive to compute function value. transformCall(call) + case ir.OCALL, ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER, ir.ODYNAMICDOTTYPE: + transformCall(call) + case ir.OFUNCINST: // A call with an OFUNCINST will get transformed // in stencil() once we have created & attached the diff --git a/test/typeparam/issue48042.go b/test/typeparam/issue48042.go new file mode 100644 index 0000000000..db5de3d8fa --- /dev/null +++ b/test/typeparam/issue48042.go @@ -0,0 +1,77 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + "reflect" +) + +type G[T any] interface { + g() func()(*T) +} +type Foo[T any] struct { + +} +// OCALL +func (l *Foo[T]) f1() (*T) { + return g[T]()() +} +// OCALLFUNC +func (l *Foo[T]) f2() (*T) { + var f = g[T] + return f()() +} +// OCALLMETH +func (l *Foo[T]) f3() (*T) { + return l.g()() +} +// OCALLINTER +func (l *Foo[T]) f4() (*T) { + var g G[T] = l + return g.g()() +} +// ODYNAMICDOTTYPE +func (l *Foo[T]) f5() (*T) { + var x interface{} + x = g[T] + return x.(func()func()(*T))()() +} +func (l *Foo[T]) g() func() (*T) { + return func() (*T) { + t := new(T) + reflect.ValueOf(t).Elem().SetInt(100) + return t + } +} +func g[T any]() func() (*T) { + return func() (*T) { + t := new(T) + reflect.ValueOf(t).Elem().SetInt(100) + return t + } +} + +func main() { + foo := Foo[int]{} + // Make sure the function conversion is correct + if n := *(foo.f1()) ; n != 100{ + panic(fmt.Sprintf("%v",n)) + } + if n := *(foo.f2()) ; n != 100{ + panic(fmt.Sprintf("%v",n)) + } + if n := *(foo.f3()) ; n != 100{ + panic(fmt.Sprintf("%v",n)) + } + if n := *(foo.f4()) ; n != 100{ + panic(fmt.Sprintf("%v",n)) + } + if n := *(foo.f5()) ; n != 100{ + panic(fmt.Sprintf("%v",n)) + } +} \ No newline at end of file -- GitLab From 20a71c9a1d7e0d246dfad2c2a2057c954324217d Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Mon, 6 Sep 2021 15:17:11 +0800 Subject: [PATCH 1016/2500] cmd/internal/sys: fix placement of loong64 definition In rebasing the patch series up to CL 339015, the branches were messed up by me, and changes from v3 to v4 of CL 339009 was lost. Fix the ordering to restore alphabetical order per original review. Change-Id: I8e57c96e996c4f962cab684a9d305a8dbdeea43b Reviewed-on: https://go-review.googlesource.com/c/go/+/347731 Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Meng Zhuo --- src/cmd/internal/sys/arch.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/cmd/internal/sys/arch.go b/src/cmd/internal/sys/arch.go index e7063fde89..4b2b4c38a0 100644 --- a/src/cmd/internal/sys/arch.go +++ b/src/cmd/internal/sys/arch.go @@ -16,13 +16,13 @@ const ( ARM ARM64 I386 + Loong64 MIPS MIPS64 PPC64 RISCV64 S390X Wasm - Loong64 ) // Arch represents an individual architecture. @@ -100,6 +100,16 @@ var ArchARM64 = &Arch{ Alignment: 1, } +var ArchLoong64 = &Arch{ + Name: "loong64", + Family: Loong64, + ByteOrder: binary.LittleEndian, + PtrSize: 8, + RegSize: 8, + MinLC: 4, + Alignment: 8, // Unaligned accesses are not guaranteed to be fast +} + var ArchMIPS = &Arch{ Name: "mips", Family: MIPS, @@ -190,21 +200,12 @@ var ArchWasm = &Arch{ Alignment: 1, } -var ArchLoong64 = &Arch{ - Name: "loong64", - Family: Loong64, - ByteOrder: binary.LittleEndian, - PtrSize: 8, - RegSize: 8, - MinLC: 4, - Alignment: 8, // Unaligned accesses are not guaranteed to be fast -} - var Archs = [...]*Arch{ Arch386, ArchAMD64, ArchARM, ArchARM64, + ArchLoong64, ArchMIPS, ArchMIPSLE, ArchMIPS64, @@ -214,5 +215,4 @@ var Archs = [...]*Arch{ ArchRISCV64, ArchS390X, ArchWasm, - ArchLoong64, } -- GitLab From a1938435d6361dcbc93a15ce0ace28748a45b85d Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 6 Sep 2021 19:02:34 +0200 Subject: [PATCH 1017/2500] syscall: use dup3 in forkAndExecInChild1 on all Linux platforms The minimum required Linux kernel version for Go 1.18 will be changed to 2.6.32, see #45964. The dup3 syscall was added in 2.6.27, so the fallback to use the dup2 syscall in forkAndExecInChild1 on some platforms can be removed. For #45964 Change-Id: I8e04d7b5b2488990a061a080ed64ea303ad048b8 Reviewed-on: https://go-review.googlesource.com/c/go/+/347350 Trust: Tobias Klauser Run-TryBot: Tobias Klauser Reviewed-by: Ian Lance Taylor TryBot-Result: Go Bot --- src/syscall/exec_linux.go | 18 +++--------------- src/syscall/syscall_dup2_linux.go | 11 ----------- src/syscall/syscall_dup3_linux.go | 10 ---------- 3 files changed, 3 insertions(+), 36 deletions(-) delete mode 100644 src/syscall/syscall_dup2_linux.go delete mode 100644 src/syscall/syscall_dup3_linux.go diff --git a/src/syscall/exec_linux.go b/src/syscall/exec_linux.go index 68bce7559b..dfc5228545 100644 --- a/src/syscall/exec_linux.go +++ b/src/syscall/exec_linux.go @@ -448,13 +448,7 @@ func forkAndExecInChild1(argv0 *byte, argv, envv []*byte, chroot, dir *byte, att // so that pass 2 won't stomp on an fd it needs later. if pipe < nextfd { _, _, err1 = RawSyscall(SYS_DUP3, uintptr(pipe), uintptr(nextfd), O_CLOEXEC) - if _SYS_dup != SYS_DUP3 && err1 == ENOSYS { - _, _, err1 = RawSyscall(_SYS_dup, uintptr(pipe), uintptr(nextfd), 0) - if err1 != 0 { - goto childerror - } - RawSyscall(fcntl64Syscall, uintptr(nextfd), F_SETFD, FD_CLOEXEC) - } else if err1 != 0 { + if err1 != 0 { goto childerror } pipe = nextfd @@ -466,13 +460,7 @@ func forkAndExecInChild1(argv0 *byte, argv, envv []*byte, chroot, dir *byte, att nextfd++ } _, _, err1 = RawSyscall(SYS_DUP3, uintptr(fd[i]), uintptr(nextfd), O_CLOEXEC) - if _SYS_dup != SYS_DUP3 && err1 == ENOSYS { - _, _, err1 = RawSyscall(_SYS_dup, uintptr(fd[i]), uintptr(nextfd), 0) - if err1 != 0 { - goto childerror - } - RawSyscall(fcntl64Syscall, uintptr(nextfd), F_SETFD, FD_CLOEXEC) - } else if err1 != 0 { + if err1 != 0 { goto childerror } fd[i] = nextfd @@ -497,7 +485,7 @@ func forkAndExecInChild1(argv0 *byte, argv, envv []*byte, chroot, dir *byte, att } // The new fd is created NOT close-on-exec, // which is exactly what we want. - _, _, err1 = RawSyscall(_SYS_dup, uintptr(fd[i]), uintptr(i), 0) + _, _, err1 = RawSyscall(SYS_DUP3, uintptr(fd[i]), uintptr(i), 0) if err1 != 0 { goto childerror } diff --git a/src/syscall/syscall_dup2_linux.go b/src/syscall/syscall_dup2_linux.go deleted file mode 100644 index 351a96edc1..0000000000 --- a/src/syscall/syscall_dup2_linux.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !android && (386 || amd64 || arm || mips || mipsle || mips64 || mips64le || ppc64 || ppc64le || s390x) -// +build !android -// +build 386 amd64 arm mips mipsle mips64 mips64le ppc64 ppc64le s390x - -package syscall - -const _SYS_dup = SYS_DUP2 diff --git a/src/syscall/syscall_dup3_linux.go b/src/syscall/syscall_dup3_linux.go deleted file mode 100644 index 66ec67b0ab..0000000000 --- a/src/syscall/syscall_dup3_linux.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build android || arm64 || riscv64 -// +build android arm64 riscv64 - -package syscall - -const _SYS_dup = SYS_DUP3 -- GitLab From 6226020c2f713e4545c73d56dc05676b642c9bc7 Mon Sep 17 00:00:00 2001 From: korzhao Date: Mon, 6 Sep 2021 21:08:05 +0800 Subject: [PATCH 1018/2500] cmd/compile: make sure that the names created for instantiated type are the same Now we have two functions that create names for instantiated types. They are inconsistent when dealing with byte/rune type. This CL makes instTypeName2 reuse the code of typecheck.InstTypeName Fixes #48198 Change-Id: I4c216b532cba6618ef9b63fd0b76e8f1c0ed7a75 Reviewed-on: https://go-review.googlesource.com/c/go/+/347491 Reviewed-by: Dan Scales Trust: Dan Scales Trust: Keith Randall Run-TryBot: Dan Scales TryBot-Result: Go Bot --- src/cmd/compile/internal/noder/types.go | 32 ++++++------------------- test/typeparam/issue48198.go | 22 +++++++++++++++++ 2 files changed, 29 insertions(+), 25 deletions(-) create mode 100644 test/typeparam/issue48198.go diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index c549dffc46..b70d8d198e 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -5,7 +5,6 @@ package noder import ( - "bytes" "cmd/compile/internal/base" "cmd/compile/internal/ir" "cmd/compile/internal/typecheck" @@ -72,29 +71,12 @@ func (g *irgen) typ1(typ types2.Type) *types.Type { // instTypeName2 creates a name for an instantiated type, base on the type args // (given as types2 types). -func instTypeName2(name string, targs *types2.TypeList) string { - b := bytes.NewBufferString(name) - b.WriteByte('[') - n := targs.Len() - for i := 0; i < n; i++ { - targ := targs.At(i) - if i > 0 { - b.WriteByte(',') - } - // Include package names for all types, including typeparams, to - // make sure type arguments are uniquely specified. - tname := types2.TypeString(targ, - func(pkg *types2.Package) string { return pkg.Name() }) - if strings.Index(tname, ", ") >= 0 { - // types2.TypeString puts spaces after a comma in a type - // list, but we don't want spaces in our actual type names - // and method/function names derived from them. - tname = strings.Replace(tname, ", ", ",", -1) - } - b.WriteString(tname) +func (g *irgen) instTypeName2(name string, targs *types2.TypeList) string { + rparams := make([]*types.Type, targs.Len()) + for i := range rparams { + rparams[i] = g.typ(targs.At(i)) } - b.WriteByte(']') - return b.String() + return typecheck.InstTypeName(name, rparams) } // typ0 converts a types2.Type to a types.Type, but doesn't do the caching check @@ -119,7 +101,7 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { // // When converted to types.Type, typ has a unique name, // based on the names of the type arguments. - instName := instTypeName2(typ.Obj().Name(), typ.TArgs()) + instName := g.instTypeName2(typ.Obj().Name(), typ.TArgs()) s := g.pkg(typ.Obj().Pkg()).Lookup(instName) if s.Def != nil { // We have already encountered this instantiation. @@ -314,7 +296,7 @@ func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) { // generic type, so we have to do a substitution to get // the name/type of the method of the instantiated type, // using m.Type().RParams() and typ.TArgs() - inst2 := instTypeName2("", typ.TArgs()) + inst2 := g.instTypeName2("", typ.TArgs()) name := meth.Sym().Name i1 := strings.Index(name, "[") i2 := strings.Index(name[i1:], "]") diff --git a/test/typeparam/issue48198.go b/test/typeparam/issue48198.go new file mode 100644 index 0000000000..1d7e44e0c4 --- /dev/null +++ b/test/typeparam/issue48198.go @@ -0,0 +1,22 @@ +// compile -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +package p + +type Foo[T any] struct { +} + +func (foo Foo[T]) Get() { +} + +var( + _ = Foo[byte]{} + _ = Foo[[]byte]{} + _ = Foo[map[byte]rune]{} + + _ = Foo[rune]{} + _ = Foo[[]rune]{} + _ = Foo[map[rune]byte]{} +) -- GitLab From 21de6bc463e52af01bcbfda478e2cb221e982e41 Mon Sep 17 00:00:00 2001 From: wdvxdr Date: Mon, 30 Aug 2021 22:26:54 +0800 Subject: [PATCH 1019/2500] cmd/compile: simplify less with non-negative number and constant 0 or 1 The most common cases: len(s) > 0 len(s) < 1 and they can be simplified to: len(s) != 0 len(s) == 0 Fixes #48054 Change-Id: I16e5b0cffcfab62a4acc2a09977a6cd3543dd000 Reviewed-on: https://go-review.googlesource.com/c/go/+/346050 Reviewed-by: Keith Randall Reviewed-by: Cherry Mui --- .../compile/internal/ssa/gen/generic.rules | 3 + .../compile/internal/ssa/rewritegeneric.go | 160 ++++++++++++++++++ test/codegen/issue48054.go | 31 ++++ 3 files changed, 194 insertions(+) create mode 100644 test/codegen/issue48054.go diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules index e7ee3d0efd..40db1a6ee8 100644 --- a/src/cmd/compile/internal/ssa/gen/generic.rules +++ b/src/cmd/compile/internal/ssa/gen/generic.rules @@ -500,6 +500,9 @@ (Leq32 (Const32 [0]) (Rsh32Ux64 _ (Const64 [c]))) && c > 0 => (ConstBool [true]) (Leq64 (Const64 [0]) (Rsh64Ux64 _ (Const64 [c]))) && c > 0 => (ConstBool [true]) +(Less(64|32|16|8) (Const(64|32|16|8) [0]) x) && isNonNegative(x) => (Neq(64|32|16|8) (Const(64|32|16|8) [0]) x) +(Less(64|32|16|8) x (Const(64|32|16|8) [1])) && isNonNegative(x) => (Eq(64|32|16|8) (Const(64|32|16|8) [0]) x) + // constant floating point comparisons (Eq32F (Const32F [c]) (Const32F [d])) => (ConstBool [c == d]) (Eq64F (Const64F [c]) (Const64F [d])) => (ConstBool [c == d]) diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index e2f9e3ebba..a6757e0d10 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -10083,6 +10083,7 @@ func rewriteValuegeneric_OpLeq8U(v *Value) bool { func rewriteValuegeneric_OpLess16(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] + b := v.Block // match: (Less16 (Const16 [c]) (Const16 [d])) // result: (ConstBool [c < d]) for { @@ -10098,6 +10099,45 @@ func rewriteValuegeneric_OpLess16(v *Value) bool { v.AuxInt = boolToAuxInt(c < d) return true } + // match: (Less16 (Const16 [0]) x) + // cond: isNonNegative(x) + // result: (Neq16 (Const16 [0]) x) + for { + if v_0.Op != OpConst16 { + break + } + t := v_0.Type + if auxIntToInt16(v_0.AuxInt) != 0 { + break + } + x := v_1 + if !(isNonNegative(x)) { + break + } + v.reset(OpNeq16) + v0 := b.NewValue0(v.Pos, OpConst16, t) + v0.AuxInt = int16ToAuxInt(0) + v.AddArg2(v0, x) + return true + } + // match: (Less16 x (Const16 [1])) + // cond: isNonNegative(x) + // result: (Eq16 (Const16 [0]) x) + for { + x := v_0 + if v_1.Op != OpConst16 { + break + } + t := v_1.Type + if auxIntToInt16(v_1.AuxInt) != 1 || !(isNonNegative(x)) { + break + } + v.reset(OpEq16) + v0 := b.NewValue0(v.Pos, OpConst16, t) + v0.AuxInt = int16ToAuxInt(0) + v.AddArg2(v0, x) + return true + } return false } func rewriteValuegeneric_OpLess16U(v *Value) bool { @@ -10133,6 +10173,7 @@ func rewriteValuegeneric_OpLess16U(v *Value) bool { func rewriteValuegeneric_OpLess32(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] + b := v.Block // match: (Less32 (Const32 [c]) (Const32 [d])) // result: (ConstBool [c < d]) for { @@ -10148,6 +10189,45 @@ func rewriteValuegeneric_OpLess32(v *Value) bool { v.AuxInt = boolToAuxInt(c < d) return true } + // match: (Less32 (Const32 [0]) x) + // cond: isNonNegative(x) + // result: (Neq32 (Const32 [0]) x) + for { + if v_0.Op != OpConst32 { + break + } + t := v_0.Type + if auxIntToInt32(v_0.AuxInt) != 0 { + break + } + x := v_1 + if !(isNonNegative(x)) { + break + } + v.reset(OpNeq32) + v0 := b.NewValue0(v.Pos, OpConst32, t) + v0.AuxInt = int32ToAuxInt(0) + v.AddArg2(v0, x) + return true + } + // match: (Less32 x (Const32 [1])) + // cond: isNonNegative(x) + // result: (Eq32 (Const32 [0]) x) + for { + x := v_0 + if v_1.Op != OpConst32 { + break + } + t := v_1.Type + if auxIntToInt32(v_1.AuxInt) != 1 || !(isNonNegative(x)) { + break + } + v.reset(OpEq32) + v0 := b.NewValue0(v.Pos, OpConst32, t) + v0.AuxInt = int32ToAuxInt(0) + v.AddArg2(v0, x) + return true + } return false } func rewriteValuegeneric_OpLess32F(v *Value) bool { @@ -10203,6 +10283,7 @@ func rewriteValuegeneric_OpLess32U(v *Value) bool { func rewriteValuegeneric_OpLess64(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] + b := v.Block // match: (Less64 (Const64 [c]) (Const64 [d])) // result: (ConstBool [c < d]) for { @@ -10218,6 +10299,45 @@ func rewriteValuegeneric_OpLess64(v *Value) bool { v.AuxInt = boolToAuxInt(c < d) return true } + // match: (Less64 (Const64 [0]) x) + // cond: isNonNegative(x) + // result: (Neq64 (Const64 [0]) x) + for { + if v_0.Op != OpConst64 { + break + } + t := v_0.Type + if auxIntToInt64(v_0.AuxInt) != 0 { + break + } + x := v_1 + if !(isNonNegative(x)) { + break + } + v.reset(OpNeq64) + v0 := b.NewValue0(v.Pos, OpConst64, t) + v0.AuxInt = int64ToAuxInt(0) + v.AddArg2(v0, x) + return true + } + // match: (Less64 x (Const64 [1])) + // cond: isNonNegative(x) + // result: (Eq64 (Const64 [0]) x) + for { + x := v_0 + if v_1.Op != OpConst64 { + break + } + t := v_1.Type + if auxIntToInt64(v_1.AuxInt) != 1 || !(isNonNegative(x)) { + break + } + v.reset(OpEq64) + v0 := b.NewValue0(v.Pos, OpConst64, t) + v0.AuxInt = int64ToAuxInt(0) + v.AddArg2(v0, x) + return true + } return false } func rewriteValuegeneric_OpLess64F(v *Value) bool { @@ -10273,6 +10393,7 @@ func rewriteValuegeneric_OpLess64U(v *Value) bool { func rewriteValuegeneric_OpLess8(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] + b := v.Block // match: (Less8 (Const8 [c]) (Const8 [d])) // result: (ConstBool [c < d]) for { @@ -10288,6 +10409,45 @@ func rewriteValuegeneric_OpLess8(v *Value) bool { v.AuxInt = boolToAuxInt(c < d) return true } + // match: (Less8 (Const8 [0]) x) + // cond: isNonNegative(x) + // result: (Neq8 (Const8 [0]) x) + for { + if v_0.Op != OpConst8 { + break + } + t := v_0.Type + if auxIntToInt8(v_0.AuxInt) != 0 { + break + } + x := v_1 + if !(isNonNegative(x)) { + break + } + v.reset(OpNeq8) + v0 := b.NewValue0(v.Pos, OpConst8, t) + v0.AuxInt = int8ToAuxInt(0) + v.AddArg2(v0, x) + return true + } + // match: (Less8 x (Const8 [1])) + // cond: isNonNegative(x) + // result: (Eq8 (Const8 [0]) x) + for { + x := v_0 + if v_1.Op != OpConst8 { + break + } + t := v_1.Type + if auxIntToInt8(v_1.AuxInt) != 1 || !(isNonNegative(x)) { + break + } + v.reset(OpEq8) + v0 := b.NewValue0(v.Pos, OpConst8, t) + v0.AuxInt = int8ToAuxInt(0) + v.AddArg2(v0, x) + return true + } return false } func rewriteValuegeneric_OpLess8U(v *Value) bool { diff --git a/test/codegen/issue48054.go b/test/codegen/issue48054.go new file mode 100644 index 0000000000..6ef37e9452 --- /dev/null +++ b/test/codegen/issue48054.go @@ -0,0 +1,31 @@ +// asmcheck + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func a(n string) bool { + // arm64:"CBZ" + if len(n) > 0 { + return true + } + return false +} + +func a2(n []int) bool { + // arm64:"CBZ" + if len(n) > 0 { + return true + } + return false +} + +func a3(n []int) bool { + // amd64:"TESTQ" + if len(n) < 1 { + return true + } + return false +} -- GitLab From bca8c6ffa2dd19d49685531650ea6553262837e3 Mon Sep 17 00:00:00 2001 From: Vyacheslav Pachkov Date: Mon, 23 Aug 2021 08:40:32 +0000 Subject: [PATCH 1020/2500] cmd/link: resolve magic value in gdbscript section generation According to the .debug_gdb_scripts section specification [https://sourceware.org/gdb/onlinedocs/gdb/dotdebug_005fgdb_005fscripts-section.html], each entry begins with a non-null prefix byte that specifies the kind of entry. This commit resolves a question about magic byte and replaces a hardcoded value with a meaningful constant "GdbScriptPythonFileId" inside writegdbscript function. Change-Id: I456c742bcb539a5853b9e2a6811033f35c37e7d4 GitHub-Last-Rev: 2f1c4cb9eec582a6e381fa866738aa17278005c2 GitHub-Pull-Request: golang/go#47646 Reviewed-on: https://go-review.googlesource.com/c/go/+/341391 Run-TryBot: Than McIntosh TryBot-Result: Go Bot Reviewed-by: Cherry Mui Reviewed-by: Than McIntosh --- src/cmd/link/internal/ld/dwarf.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go index 98ab248e13..70138d37ff 100644 --- a/src/cmd/link/internal/ld/dwarf.go +++ b/src/cmd/link/internal/ld/dwarf.go @@ -187,6 +187,16 @@ func isDwarf64(ctxt *Link) bool { return ctxt.HeadType == objabi.Haix } +// https://sourceware.org/gdb/onlinedocs/gdb/dotdebug_005fgdb_005fscripts-section.html +// Each entry inside .debug_gdb_scripts section begins with a non-null prefix +// byte that specifies the kind of entry. The following entries are supported: +const ( + GdbScriptPythonFileId = 1 + GdbScriptSchemeFileId = 3 + GdbScriptPythonTextId = 4 + GdbScriptSchemeTextId = 6 +) + var gdbscript string // dwarfSecInfo holds information about a DWARF output section, @@ -1618,7 +1628,7 @@ func (d *dwctxt) writegdbscript() dwarfSecInfo { gs := d.ldr.CreateSymForUpdate(".debug_gdb_scripts", 0) gs.SetType(sym.SDWARFSECT) - gs.AddUint8(1) // magic 1 byte? + gs.AddUint8(GdbScriptPythonFileId) gs.Addstring(gdbscript) return dwarfSecInfo{syms: []loader.Sym{gs.Sym()}} } -- GitLab From 2a4845257fea627da8b30444a498576ea90b5401 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sun, 5 Sep 2021 20:50:54 +0700 Subject: [PATCH 1021/2500] cmd/compile: fix deadlock in (*Named).load For lazy import resolution, there's reentrancy issue with (*Named).load method, when "t.resolve(t)" can lead us to the same named type, thus (*Named).load is called recursively, causing the deadlock. The main problem is that when instantinate a type, we calculate the type hashing, including TParams. Calling t.TParams().Len() triggers the reentrancy call to "(*Named).load". To fix this, just not checking TParams().Len() if we are hashing. Updates #48185 Change-Id: Ie34842d7b10fad5d11fbcf75bb1c64a89deac6b8 Reviewed-on: https://go-review.googlesource.com/c/go/+/347534 Trust: Cuong Manh Le Trust: Robert Griesemer Run-TryBot: Cuong Manh Le Reviewed-by: Matthew Dempsky Reviewed-by: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/cmd/compile/internal/types2/typestring.go | 2 +- test/typeparam/issue48185a.dir/p.go | 19 +++++++++++++++++++ test/typeparam/issue48185a.dir/p_test.go | 11 +++++++++++ test/typeparam/issue48185a.go | 7 +++++++ 4 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 test/typeparam/issue48185a.dir/p.go create mode 100644 test/typeparam/issue48185a.dir/p_test.go create mode 100644 test/typeparam/issue48185a.go diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index da5de08758..6083955306 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -234,7 +234,7 @@ func (w *typeWriter) typ(typ Type) { if t.targs != nil { // instantiated type w.typeList(t.targs.list()) - } else if t.TParams().Len() != 0 { + } else if !w.hash && t.TParams().Len() != 0 { // For type hashing, don't need to format the TParams // parameterized type w.tParamList(t.TParams().list()) } diff --git a/test/typeparam/issue48185a.dir/p.go b/test/typeparam/issue48185a.dir/p.go new file mode 100644 index 0000000000..176c7f4de5 --- /dev/null +++ b/test/typeparam/issue48185a.dir/p.go @@ -0,0 +1,19 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type MarshalOptions struct { + Marshalers *Marshalers +} + +type Encoder struct {} + +type Marshalers = marshalers[MarshalOptions, Encoder] + +type marshalers[Options, Coder any] struct{} + +func MarshalFuncV1[T any](fn func(T) ([]byte, error)) *Marshalers { + return &Marshalers{} +} diff --git a/test/typeparam/issue48185a.dir/p_test.go b/test/typeparam/issue48185a.dir/p_test.go new file mode 100644 index 0000000000..52c87a7e29 --- /dev/null +++ b/test/typeparam/issue48185a.dir/p_test.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "p" + +func main() { + _ = p.MarshalFuncV1[int](func(int) ([]byte, error) { return nil, nil }) +} diff --git a/test/typeparam/issue48185a.go b/test/typeparam/issue48185a.go new file mode 100644 index 0000000000..40df49f83b --- /dev/null +++ b/test/typeparam/issue48185a.go @@ -0,0 +1,7 @@ +// rundir + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From 81188661f1fd51f67dfff40c451d4e878b533a66 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 8 Sep 2021 00:33:32 +0700 Subject: [PATCH 1022/2500] go/types: do not format TParams when hashing This is a port of CL 347534 to go/types. Change-Id: I2b15a29992c430e34592d110be16d7b2b10521a9 Reviewed-on: https://go-review.googlesource.com/c/go/+/348029 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le Reviewed-by: Robert Findley TryBot-Result: Go Bot --- src/go/types/typestring.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 3d30ff98f3..c5f0354aea 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -235,7 +235,7 @@ func (w *typeWriter) typ(typ Type) { if t.targs != nil { // instantiated type w.typeList(t.targs.list()) - } else if t.TParams().Len() != 0 { + } else if !w.hash && t.TParams().Len() != 0 { // For type hashing, don't need to format the TParams // parameterized type w.tParamList(t.TParams().list()) } -- GitLab From e581ec07eed006e7a54306457ff8d9931b2aae7c Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 7 Sep 2021 10:51:14 -0700 Subject: [PATCH 1023/2500] cmd/compile: fix lazy loading in reader2 Calling reader2.obj fully loads the referenced object, which is necessary in general; but for reading the package index, we just need to setup the name->index mapping. This CL adds this, so that lazy loading works as intended. Change-Id: Ie51d59e2247d99b46f9dc69fba7ce89e2584b7c4 Reviewed-on: https://go-review.googlesource.com/c/go/+/348011 Trust: Matthew Dempsky Trust: Cuong Manh Le Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/noder/reader2.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index cffa037236..296d84289c 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -43,7 +43,12 @@ func readPackage2(check *types2.Checker, imports map[string]*types2.Package, inp r.bool() // has init for i, n := 0, r.len(); i < n; i++ { - r.obj() + // As if r.obj(), but avoiding the Scope.Lookup call, + // to avoid eager loading of imports. + r.sync(syncObject) + assert(!r.bool()) + r.p.objIdx(r.reloc(relocObj)) + assert(r.len() == 0) } r.sync(syncEOF) -- GitLab From 66401719143692f1b892fb47aaef286f885395c9 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 7 Sep 2021 07:46:27 -0700 Subject: [PATCH 1024/2500] cmd/compile: fix type substituter to copy Funarg value for structs We were missing copying the Funarg value when substituting for a struct type. Change-Id: Id0c2d9e55fb15987acb9edba6f74cf57cfd3417e Reviewed-on: https://go-review.googlesource.com/c/go/+/347913 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Dan Scales --- src/cmd/compile/internal/typecheck/subr.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 4696b62cd2..d0ae529596 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1229,7 +1229,7 @@ func (ts *Tsubster) typ1(t *types.Type) *types.Type { newt = forw } - if !newt.HasTParam() { + if !newt.HasTParam() && !newt.IsFuncArgStruct() { // Calculate the size of any new types created. These will be // deferred until the top-level ts.Typ() or g.typ() (if this is // called from g.fillinMethods()). @@ -1324,7 +1324,9 @@ func (ts *Tsubster) tstruct(t *types.Type, force bool) *types.Type { } } if newfields != nil { - return types.NewStruct(t.Pkg(), newfields) + news := types.NewStruct(t.Pkg(), newfields) + news.StructType().Funarg = t.StructType().Funarg + return news } return t -- GitLab From 903958d2f506decf92a1bfd63dfbecadf8375735 Mon Sep 17 00:00:00 2001 From: korzhao Date: Wed, 4 Aug 2021 02:47:57 +0000 Subject: [PATCH 1025/2500] encoding/gob: marshal maps using reflect.Value.MapRange golang.org/cl/33572 added a map iterator. use the reflect.Value.MapRange to fix map keys that contain a NaN Fixes #24075 Change-Id: I0214d6f26c2041797703e48eac16404f189d6982 GitHub-Last-Rev: 5c01e117f4451dbaec657d02d006905df1d0055d GitHub-Pull-Request: golang/go#47476 Reviewed-on: https://go-review.googlesource.com/c/go/+/338609 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Rob Pike --- src/encoding/gob/encode.go | 10 +++---- src/encoding/gob/encoder_test.go | 50 ++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/src/encoding/gob/encode.go b/src/encoding/gob/encode.go index 8f8f170c16..f1f5f3862d 100644 --- a/src/encoding/gob/encode.go +++ b/src/encoding/gob/encode.go @@ -368,11 +368,11 @@ func (enc *Encoder) encodeMap(b *encBuffer, mv reflect.Value, keyOp, elemOp encO state := enc.newEncoderState(b) state.fieldnum = -1 state.sendZero = true - keys := mv.MapKeys() - state.encodeUint(uint64(len(keys))) - for _, key := range keys { - encodeReflectValue(state, key, keyOp, keyIndir) - encodeReflectValue(state, mv.MapIndex(key), elemOp, elemIndir) + state.encodeUint(uint64(mv.Len())) + mi := mv.MapRange() + for mi.Next() { + encodeReflectValue(state, mi.Key(), keyOp, keyIndir) + encodeReflectValue(state, mi.Value(), elemOp, elemIndir) } enc.freeEncoderState(state) } diff --git a/src/encoding/gob/encoder_test.go b/src/encoding/gob/encoder_test.go index 6183646f60..6d50b82573 100644 --- a/src/encoding/gob/encoder_test.go +++ b/src/encoding/gob/encoder_test.go @@ -9,7 +9,9 @@ import ( "encoding/hex" "fmt" "io" + "math" "reflect" + "sort" "strings" "testing" ) @@ -1152,3 +1154,51 @@ func TestDecodeErrorMultipleTypes(t *testing.T) { t.Errorf("decode: expected duplicate type error, got %s", err.Error()) } } + +// Issue 24075 +func TestMarshalFloatMap(t *testing.T) { + nan1 := math.NaN() + nan2 := math.Float64frombits(math.Float64bits(nan1) ^ 1) // A different NaN in the same class. + + in := map[float64]string{ + nan1: "a", + nan1: "b", + nan2: "c", + } + + var b bytes.Buffer + enc := NewEncoder(&b) + if err := enc.Encode(in); err != nil { + t.Errorf("Encode : %v", err) + } + + out := map[float64]string{} + dec := NewDecoder(&b) + if err := dec.Decode(&out); err != nil { + t.Fatalf("Decode : %v", err) + } + + type mapEntry struct { + keyBits uint64 + value string + } + readMap := func(m map[float64]string) (entries []mapEntry) { + for k, v := range m { + entries = append(entries, mapEntry{math.Float64bits(k), v}) + } + sort.Slice(entries, func(i, j int) bool { + ei, ej := entries[i], entries[j] + if ei.keyBits != ej.keyBits { + return ei.keyBits < ej.keyBits + } + return ei.value < ej.value + }) + return entries + } + + got := readMap(out) + want := readMap(in) + if !reflect.DeepEqual(got, want) { + t.Fatalf("\nEncode: %v\nDecode: %v", want, got) + } +} -- GitLab From d92101f452e10680ad4c8af2d5ad40d940b59214 Mon Sep 17 00:00:00 2001 From: zikaeroh Date: Tue, 7 Sep 2021 00:38:40 -0700 Subject: [PATCH 1026/2500] cmd/compile: resolve TODO in inl.go If the condition is a bool constant, there's no need to walk both branches. Passes toolstash -cmp. Change-Id: I4ee5e3553ce07c2213efba0d33d869b4a1b57783 Reviewed-on: https://go-review.googlesource.com/c/go/+/347911 Reviewed-by: Matthew Dempsky Trust: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot --- src/cmd/compile/internal/inline/inl.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index d50d8b3516..073373144d 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -398,10 +398,14 @@ func (v *hairyVisitor) doNode(n ir.Node) bool { n := n.(*ir.IfStmt) if ir.IsConst(n.Cond, constant.Bool) { // This if and the condition cost nothing. - // TODO(rsc): It seems strange that we visit the dead branch. - return doList(n.Init(), v.do) || - doList(n.Body, v.do) || - doList(n.Else, v.do) + if doList(n.Init(), v.do) { + return true + } + if ir.BoolVal(n.Cond) { + return doList(n.Body, v.do) + } else { + return doList(n.Else, v.do) + } } case ir.ONAME: -- GitLab From 23f4f0db682fad0c8d61a5b5cdbdbad4cf1cd41f Mon Sep 17 00:00:00 2001 From: Ruslan Andreev Date: Tue, 15 Jun 2021 14:04:30 +0000 Subject: [PATCH 1027/2500] cmd/compile: add prefetch intrinsic support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This CL provide new intrinsics to emit prefetch instructions for AMD64 and ARM64 platforms: Prefetch - prefetches data from memory address to cache; PrefetchStreamed - prefetches data from memory address, with a hint that this data is being streamed. This patch also provides prefetch calls pointed by RSC inside scanobject and greyobject of GC mark logic. Performance results provided by Michael: https://perf.golang.org/search?q=upload:20210901.9 Benchmark parameters: tree2 -heapsize=1000000000 -cpus=8 tree -n=18 parser peano Benchmarks AMD64 (Xeon - Cascade Lake): name old time/op new time/op delta Tree2-8 36.1ms ± 6% 33.4ms ± 5% -7.65% (p=0.000 n=9+9) Tree-8 326ms ± 1% 324ms ± 1% -0.44% (p=0.006 n=9+10) Parser-8 2.75s ± 1% 2.71s ± 1% -1.47% (p=0.008 n=5+5) Peano-8 63.1ms ± 1% 63.0ms ± 1% ~ (p=0.730 n=9+9) [Geo mean] 213ms 207ms -2.45% Benchmarks ARM64 (Kunpeng 920): name old time/op new time/op delta Tree2-8 50.3ms ± 8% 44.1ms ± 5% -12.24% (p=0.000 n=10+9) Tree-8 494ms ± 1% 493ms ± 1% ~ (p=0.684 n=10+10) Parser-8 3.99s ± 1% 3.93s ± 1% -1.37% (p=0.016 n=5+5) Peano-8 84.4ms ± 0% 84.1ms ± 1% ~ (p=0.068 n=8+10) [Geo mean] 302ms 291ms -3.67% Change-Id: I43e10bc2f9512dc49d7631dd8843a79036fa43d0 Reviewed-on: https://go-review.googlesource.com/c/go/+/328289 Reviewed-by: Austin Clements Reviewed-by: Cherry Mui Run-TryBot: Austin Clements TryBot-Result: Go Bot --- src/cmd/compile/internal/amd64/ssa.go | 4 ++ src/cmd/compile/internal/arm64/ssa.go | 6 +++ src/cmd/compile/internal/ssa/gen/AMD64.rules | 4 ++ src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 7 +++ src/cmd/compile/internal/ssa/gen/ARM64.rules | 4 ++ src/cmd/compile/internal/ssa/gen/ARM64Ops.go | 5 ++ .../compile/internal/ssa/gen/genericOps.go | 4 ++ src/cmd/compile/internal/ssa/opGen.go | 51 +++++++++++++++++++ src/cmd/compile/internal/ssa/rewriteAMD64.go | 6 +++ src/cmd/compile/internal/ssa/rewriteARM64.go | 32 ++++++++++++ src/cmd/compile/internal/ssagen/ssa.go | 15 ++++++ src/cmd/internal/obj/arm64/obj7.go | 8 ++- src/runtime/internal/sys/intrinsics_common.go | 15 ++++++ src/runtime/mgcmark.go | 25 +++++---- 14 files changed, 174 insertions(+), 12 deletions(-) diff --git a/src/cmd/compile/internal/amd64/ssa.go b/src/cmd/compile/internal/amd64/ssa.go index fceb141ae9..fc547ebba0 100644 --- a/src/cmd/compile/internal/amd64/ssa.go +++ b/src/cmd/compile/internal/amd64/ssa.go @@ -1231,6 +1231,10 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.To.Type = obj.TYPE_MEM p.To.Reg = v.Args[0].Reg() ssagen.AddAux(&p.To, v) + case ssa.OpAMD64PrefetchT0, ssa.OpAMD64PrefetchNTA: + p := s.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_MEM + p.From.Reg = v.Args[0].Reg() case ssa.OpClobber: p := s.Prog(x86.AMOVL) p.From.Type = obj.TYPE_CONST diff --git a/src/cmd/compile/internal/arm64/ssa.go b/src/cmd/compile/internal/arm64/ssa.go index c3319f9491..b985246117 100644 --- a/src/cmd/compile/internal/arm64/ssa.go +++ b/src/cmd/compile/internal/arm64/ssa.go @@ -1095,6 +1095,12 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.From.Reg = condBits[v.Op] p.To.Type = obj.TYPE_REG p.To.Reg = v.Reg() + case ssa.OpARM64PRFM: + p := s.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_MEM + p.From.Reg = v.Args[0].Reg() + p.To.Type = obj.TYPE_CONST + p.To.Offset = v.AuxInt case ssa.OpARM64LoweredGetClosurePtr: // Closure pointer is R26 (arm64.REGCTXT). ssagen.CheckLoweredGetClosurePtr(v) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 54ed5f7ad1..5b127c98e7 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -2199,3 +2199,7 @@ && isInlinableMemmove(dst, src, sz, config) && clobber(call) => (Move [sz] dst src mem) + +// Prefetch instructions +(PrefetchCache ...) => (PrefetchT0 ...) +(PrefetchCacheStreamed ...) => (PrefetchNTA ...) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index 1199d8075f..52ea7ac5e0 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -169,6 +169,8 @@ func init() { fpstore = regInfo{inputs: []regMask{gpspsb, fp, 0}} fpstoreidx = regInfo{inputs: []regMask{gpspsb, gpsp, fp, 0}} + + prefreg = regInfo{inputs: []regMask{gpspsbg}} ) var AMD64ops = []opData{ @@ -900,6 +902,11 @@ func init() { {name: "ANDLlock", argLength: 3, reg: gpstore, asm: "ANDL", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "RdWr"}, // *(arg0+auxint+aux) &= arg1 {name: "ORBlock", argLength: 3, reg: gpstore, asm: "ORB", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "RdWr"}, // *(arg0+auxint+aux) |= arg1 {name: "ORLlock", argLength: 3, reg: gpstore, asm: "ORL", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "RdWr"}, // *(arg0+auxint+aux) |= arg1 + + // Prefetch instructions + // Do prefetch arg0 address. arg0=addr, arg1=memory. Instruction variant selects locality hint + {name: "PrefetchT0", argLength: 2, reg: prefreg, asm: "PREFETCHT0", hasSideEffects: true}, + {name: "PrefetchNTA", argLength: 2, reg: prefreg, asm: "PREFETCHNTA", hasSideEffects: true}, } var AMD64blocks = []blockData{ diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index b44c8b826b..ca9d4a4f01 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -2873,6 +2873,10 @@ (MOVWUload [off] {sym} (SB) _) && symIsRO(sym) => (MOVDconst [int64(read32(sym, int64(off), config.ctxt.Arch.ByteOrder))]) (MOVDload [off] {sym} (SB) _) && symIsRO(sym) => (MOVDconst [int64(read64(sym, int64(off), config.ctxt.Arch.ByteOrder))]) +// Prefetch instructions (aux is option: 0 - PLDL1KEEP; 1 - PLDL1STRM) +(PrefetchCache addr mem) => (PRFM [0] addr mem) +(PrefetchCacheStreamed addr mem) => (PRFM [1] addr mem) + // Arch-specific inlining for small or disjoint runtime.memmove (SelectN [0] call:(CALLstatic {sym} s1:(MOVDstore _ (MOVDconst [sz]) s2:(MOVDstore _ src s3:(MOVDstore {t} _ dst mem))))) && sz >= 0 diff --git a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go index 5de0b5f020..acfb2880c2 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go @@ -175,6 +175,7 @@ func init() { fpstore = regInfo{inputs: []regMask{gpspsbg, fp}} fpstore2 = regInfo{inputs: []regMask{gpspsbg, gpg, fp}} readflags = regInfo{inputs: nil, outputs: []regMask{gp}} + prefreg = regInfo{inputs: []regMask{gpspsbg}} ) ops := []opData{ // binary ops @@ -729,6 +730,10 @@ func init() { {name: "LoweredPanicBoundsA", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r2, r3}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in generic.go). {name: "LoweredPanicBoundsB", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r1, r2}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in generic.go). {name: "LoweredPanicBoundsC", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r0, r1}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in generic.go). + + // Prefetch instruction + // Do prefetch arg0 address with option aux. arg0=addr, arg1=memory, aux=option. + {name: "PRFM", argLength: 2, aux: "Int64", reg: prefreg, asm: "PRFM", hasSideEffects: true}, } blocks := []blockData{ diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index 9f6664386c..c183aedf2d 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -618,6 +618,10 @@ var genericOps = []opData{ // Clobber experiment op {name: "Clobber", argLength: 0, typ: "Void", aux: "SymOff", symEffect: "None"}, // write an invalid pointer value to the given pointer slot of a stack variable {name: "ClobberReg", argLength: 0, typ: "Void"}, // clobber a register + + // Prefetch instruction + {name: "PrefetchCache", argLength: 2, hasSideEffects: true}, // Do prefetch arg0 to cache. arg0=addr, arg1=memory. + {name: "PrefetchCacheStreamed", argLength: 2, hasSideEffects: true}, // Do non-temporal or streamed prefetch arg0 to cache. arg0=addr, arg1=memory. } // kind controls successors implicit exit diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 672528aefe..573559db70 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -1029,6 +1029,8 @@ const ( OpAMD64ANDLlock OpAMD64ORBlock OpAMD64ORLlock + OpAMD64PrefetchT0 + OpAMD64PrefetchNTA OpARMADD OpARMADDconst @@ -1610,6 +1612,7 @@ const ( OpARM64LoweredPanicBoundsA OpARM64LoweredPanicBoundsB OpARM64LoweredPanicBoundsC + OpARM64PRFM OpMIPSADD OpMIPSADDconst @@ -2918,6 +2921,8 @@ const ( OpAtomicOr32Variant OpClobber OpClobberReg + OpPrefetchCache + OpPrefetchCacheStreamed ) var opcodeTable = [...]opInfo{ @@ -13559,6 +13564,28 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "PrefetchT0", + argLen: 2, + hasSideEffects: true, + asm: x86.APREFETCHT0, + reg: regInfo{ + inputs: []inputInfo{ + {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB + }, + }, + }, + { + name: "PrefetchNTA", + argLen: 2, + hasSideEffects: true, + asm: x86.APREFETCHNTA, + reg: regInfo{ + inputs: []inputInfo{ + {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB + }, + }, + }, { name: "ADD", @@ -21451,6 +21478,18 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "PRFM", + auxType: auxInt64, + argLen: 2, + hasSideEffects: true, + asm: arm64.APRFM, + reg: regInfo{ + inputs: []inputInfo{ + {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB + }, + }, + }, { name: "ADD", @@ -36313,6 +36352,18 @@ var opcodeTable = [...]opInfo{ argLen: 0, generic: true, }, + { + name: "PrefetchCache", + argLen: 2, + hasSideEffects: true, + generic: true, + }, + { + name: "PrefetchCacheStreamed", + argLen: 2, + hasSideEffects: true, + generic: true, + }, } func (o Op) Asm() obj.As { return opcodeTable[o].asm } diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 1db16318c8..aa9293e347 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -951,6 +951,12 @@ func rewriteValueAMD64(v *Value) bool { return true case OpPopCount8: return rewriteValueAMD64_OpPopCount8(v) + case OpPrefetchCache: + v.Op = OpAMD64PrefetchT0 + return true + case OpPrefetchCacheStreamed: + v.Op = OpAMD64PrefetchNTA + return true case OpRotateLeft16: v.Op = OpAMD64ROLW return true diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index f9175e92fd..c62ff73c59 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -896,6 +896,10 @@ func rewriteValueARM64(v *Value) bool { return rewriteValueARM64_OpPopCount32(v) case OpPopCount64: return rewriteValueARM64_OpPopCount64(v) + case OpPrefetchCache: + return rewriteValueARM64_OpPrefetchCache(v) + case OpPrefetchCacheStreamed: + return rewriteValueARM64_OpPrefetchCacheStreamed(v) case OpRotateLeft16: return rewriteValueARM64_OpRotateLeft16(v) case OpRotateLeft32: @@ -25092,6 +25096,34 @@ func rewriteValueARM64_OpPopCount64(v *Value) bool { return true } } +func rewriteValueARM64_OpPrefetchCache(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] + // match: (PrefetchCache addr mem) + // result: (PRFM [0] addr mem) + for { + addr := v_0 + mem := v_1 + v.reset(OpARM64PRFM) + v.AuxInt = int64ToAuxInt(0) + v.AddArg2(addr, mem) + return true + } +} +func rewriteValueARM64_OpPrefetchCacheStreamed(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] + // match: (PrefetchCacheStreamed addr mem) + // result: (PRFM [1] addr mem) + for { + addr := v_0 + mem := v_1 + v.reset(OpARM64PRFM) + v.AuxInt = int64ToAuxInt(1) + v.AddArg2(addr, mem) + return true + } +} func rewriteValueARM64_OpRotateLeft16(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index c86501b88b..1d5a872b1b 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -3831,6 +3831,21 @@ func InitTables() { }, sys.AMD64, sys.ARM64, sys.ARM, sys.S390X) + /****** Prefetch ******/ + makePrefetchFunc := func(op ssa.Op) func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { + return func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { + s.vars[memVar] = s.newValue2(op, types.TypeMem, args[0], s.mem()) + return nil + } + } + + // Make Prefetch intrinsics for supported platforms + // On the unsupported platforms stub function will be eliminated + addF("runtime/internal/sys", "Prefetch", makePrefetchFunc(ssa.OpPrefetchCache), + sys.AMD64, sys.ARM64) + addF("runtime/internal/sys", "PrefetchStreamed", makePrefetchFunc(ssa.OpPrefetchCacheStreamed), + sys.AMD64, sys.ARM64) + /******** runtime/internal/atomic ********/ addF("runtime/internal/atomic", "Load", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { diff --git a/src/cmd/internal/obj/arm64/obj7.go b/src/cmd/internal/obj/arm64/obj7.go index a043d0972c..ae8deede3a 100644 --- a/src/cmd/internal/obj/arm64/obj7.go +++ b/src/cmd/internal/obj/arm64/obj7.go @@ -51,6 +51,12 @@ var complements = []obj.As{ ACMNW: ACMPW, } +// noZRreplace is the set of instructions for which $0 in the To operand +// should NOT be replaced with REGZERO. +var noZRreplace = map[obj.As]bool{ + APRFM: true, +} + func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { // MOV g_stackguard(g), RT1 p = obj.Appendp(p, c.newprog) @@ -226,7 +232,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { p.From.Type = obj.TYPE_REG p.From.Reg = REGZERO } - if p.To.Type == obj.TYPE_CONST && p.To.Offset == 0 { + if p.To.Type == obj.TYPE_CONST && p.To.Offset == 0 && !noZRreplace[p.As] { p.To.Type = obj.TYPE_REG p.To.Reg = REGZERO } diff --git a/src/runtime/internal/sys/intrinsics_common.go b/src/runtime/internal/sys/intrinsics_common.go index 818d75ecc5..48d9759ca9 100644 --- a/src/runtime/internal/sys/intrinsics_common.go +++ b/src/runtime/internal/sys/intrinsics_common.go @@ -141,3 +141,18 @@ func TrailingZeros8(x uint8) int { func Len8(x uint8) int { return int(len8tab[x]) } + +// Prefetch prefetches data from memory addr to cache +// +// AMD64: Produce PREFETCHT0 instruction +// +// ARM64: Produce PRFM instruction with PLDL1KEEP option +func Prefetch(addr uintptr) {} + +// PrefetchStreamed prefetches data from memory addr, with a hint that this data is being streamed. +// That is, it is likely to be accessed very soon, but only once. If possible, this will avoid polluting the cache. +// +// AMD64: Produce PREFETCHNTA instruction +// +// ARM64: Produce PRFM instruction with PLDL1STRM option +func PrefetchStreamed(addr uintptr) {} diff --git a/src/runtime/mgcmark.go b/src/runtime/mgcmark.go index 874d910720..64f1c79c36 100644 --- a/src/runtime/mgcmark.go +++ b/src/runtime/mgcmark.go @@ -9,6 +9,7 @@ package runtime import ( "internal/goarch" "runtime/internal/atomic" + "runtime/internal/sys" "unsafe" ) @@ -1104,11 +1105,6 @@ func gcDrainN(gcw *gcWork, scanWork int64) int64 { gcw.balance() } - // This might be a good place to add prefetch code... - // if(wbuf.nobj > 4) { - // PREFETCH(wbuf->obj[wbuf.nobj - 3]; - // } - // b := gcw.tryGetFast() if b == 0 { b = gcw.tryGet() @@ -1135,6 +1131,7 @@ func gcDrainN(gcw *gcWork, scanWork int64) int64 { // No heap or root jobs. break } + scanobject(b, gcw) // Flush background scan work credit. @@ -1199,6 +1196,12 @@ func scanblock(b0, n0 uintptr, ptrmask *uint8, gcw *gcWork, stk *stackScanState) // //go:nowritebarrier func scanobject(b uintptr, gcw *gcWork) { + // Prefetch object before we scan it. + // + // This will overlap fetching the beginning of the object with initial + // setup before we start scanning the object. + sys.Prefetch(b) + // Find the bits for b and the size of the object at b. // // b is either the beginning of an object, in which case this @@ -1437,12 +1440,12 @@ func greyobject(obj, base, off uintptr, span *mspan, gcw *gcWork, objIndex uintp } } - // Queue the obj for scanning. The PREFETCH(obj) logic has been removed but - // seems like a nice optimization that can be added back in. - // There needs to be time between the PREFETCH and the use. - // Previously we put the obj in an 8 element buffer that is drained at a rate - // to give the PREFETCH time to do its work. - // Use of PREFETCHNTA might be more appropriate than PREFETCH + // We're adding obj to P's local workbuf, so it's likely + // this object will be processed soon by the same P. + // Even if the workbuf gets flushed, there will likely still be + // some benefit on platforms with inclusive shared caches. + sys.Prefetch(obj) + // Queue the obj for scanning. if !gcw.putFast(obj) { gcw.put(obj) } -- GitLab From 80783558b06741beaf41dbd198013fe3a13c9ad2 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 6 Sep 2021 16:25:43 -0700 Subject: [PATCH 1028/2500] cmd/compile: make sure imported instantiated types have their methods created We should be putting a newly instantiated imported type in Instantiate/doInst onto the instTypeList, so its methods/dictionaries are instantiated. To do this, we needed a more general way to add a type to instTypeList, so add NeedInstType(), analogous to NeedRuntimeType(). This has the extra advantage that now all types created by the type substituter are added to instTypeList without any extra code, which was easy to forget. doInst() now correctly calls NeedInstType(). This is a bit aggressive, since a fully instantiated type in a generic function/method may never be used, if the generic method is never instantiated in the local package. But it should be fairly uncommon for a generic method to mention a fully instantiated type (but it does happen in this bug). Fixes both cases mentioned in the bug. Fixed #48185 Change-Id: I19b5012dfac17e306c8005f8595a648b0ab280d0 Reviewed-on: https://go-review.googlesource.com/c/go/+/347909 Trust: Dan Scales Trust: Cuong Manh Le Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/expr.go | 1 - src/cmd/compile/internal/noder/irgen.go | 3 - src/cmd/compile/internal/noder/stencil.go | 68 +++++++++---------- src/cmd/compile/internal/noder/types.go | 6 +- src/cmd/compile/internal/typecheck/iimport.go | 4 ++ src/cmd/compile/internal/typecheck/subr.go | 21 +++++- test/typeparam/issue48185b.dir/a.go | 37 ++++++++++ test/typeparam/issue48185b.dir/main.go | 18 +++++ test/typeparam/issue48185b.go | 7 ++ 9 files changed, 118 insertions(+), 47 deletions(-) create mode 100644 test/typeparam/issue48185b.dir/a.go create mode 100644 test/typeparam/issue48185b.dir/main.go create mode 100644 test/typeparam/issue48185b.go diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 863acf587d..7dbbc88f8f 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -237,7 +237,6 @@ func (g *irgen) substType(typ *types.Type, tparams *types.Type, targs []ir.Node) Targs: targs1, } newt := ts.Typ(typ) - g.instTypeList = append(g.instTypeList, ts.InstTypeList...) return newt } diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index fd29c51c8a..a67b3994da 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -152,9 +152,6 @@ type irgen struct { // types which we need to finish, by doing g.fillinMethods. typesToFinalize []*typeDelayInfo - // Fully-instantiated generic types whose methods should be instantiated - instTypeList []*types.Type - dnum int // for generating unique dictionary variables // Map from generic function to information about its type params, derived diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 3b15ac2c97..1c22fc2ac0 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -481,39 +481,43 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { } // instantiateMethods instantiates all the methods (and associated dictionaries) of -// all fully-instantiated generic types that have been added to g.instTypeList. +// all fully-instantiated generic types that have been added to typecheck.instTypeList. +// It continues until no more types are added to typecheck.instTypeList. func (g *irgen) instantiateMethods() { - for i := 0; i < len(g.instTypeList); i++ { - typ := g.instTypeList[i] - assert(!typ.HasShape()) - // Mark runtime type as needed, since this ensures that the - // compiler puts out the needed DWARF symbols, when this - // instantiated type has a different package from the local - // package. - typecheck.NeedRuntimeType(typ) - // Lookup the method on the base generic type, since methods may - // not be set on imported instantiated types. - baseSym := typ.OrigSym() - baseType := baseSym.Def.(*ir.Name).Type() - for j, _ := range typ.Methods().Slice() { - if baseType.Methods().Slice()[j].Nointerface() { - typ.Methods().Slice()[j].SetNointerface(true) + for { + instTypeList := typecheck.GetInstTypeList() + if len(instTypeList) == 0 { + break + } + for _, typ := range instTypeList { + assert(!typ.HasShape()) + // Mark runtime type as needed, since this ensures that the + // compiler puts out the needed DWARF symbols, when this + // instantiated type has a different package from the local + // package. + typecheck.NeedRuntimeType(typ) + // Lookup the method on the base generic type, since methods may + // not be set on imported instantiated types. + baseSym := typ.OrigSym() + baseType := baseSym.Def.(*ir.Name).Type() + for j, _ := range typ.Methods().Slice() { + if baseType.Methods().Slice()[j].Nointerface() { + typ.Methods().Slice()[j].SetNointerface(true) + } + baseNname := baseType.Methods().Slice()[j].Nname.(*ir.Name) + // Eagerly generate the instantiations and dictionaries that implement these methods. + // We don't use the instantiations here, just generate them (and any + // further instantiations those generate, etc.). + // Note that we don't set the Func for any methods on instantiated + // types. Their signatures don't match so that would be confusing. + // Direct method calls go directly to the instantiations, implemented above. + // Indirect method calls use wrappers generated in reflectcall. Those wrappers + // will use these instantiations if they are needed (for interface tables or reflection). + _ = g.getInstantiation(baseNname, typ.RParams(), true) + _ = g.getDictionarySym(baseNname, typ.RParams(), true) } - baseNname := baseType.Methods().Slice()[j].Nname.(*ir.Name) - // Eagerly generate the instantiations and dictionaries that implement these methods. - // We don't use the instantiations here, just generate them (and any - // further instantiations those generate, etc.). - // Note that we don't set the Func for any methods on instantiated - // types. Their signatures don't match so that would be confusing. - // Direct method calls go directly to the instantiations, implemented above. - // Indirect method calls use wrappers generated in reflectcall. Those wrappers - // will use these instantiations if they are needed (for interface tables or reflection). - _ = g.getInstantiation(baseNname, typ.RParams(), true) - _ = g.getDictionarySym(baseNname, typ.RParams(), true) } } - g.instTypeList = nil - } // getInstNameNode returns the name node for the method or function being instantiated, and a bool which is true if a method is being instantiated. @@ -735,9 +739,6 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes []*typ } ir.CurFunc = savef - // Add any new, fully instantiated types seen during the substitution to - // g.instTypeList. - g.instTypeList = append(g.instTypeList, subst.ts.InstTypeList...) if doubleCheck { ir.Visit(newf, func(n ir.Node) { @@ -1573,7 +1574,6 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) off: off, } g.dictSymsToFinalize = append(g.dictSymsToFinalize, delay) - g.instTypeList = append(g.instTypeList, subst.InstTypeList...) return sym } @@ -1640,8 +1640,6 @@ func (g *irgen) finalizeSyms() { objw.Global(lsym, int32(d.off), obj.DUPOK|obj.RODATA) infoPrint("=== Finalized dictionary %s\n", d.sym.Name) - - g.instTypeList = append(g.instTypeList, subst.InstTypeList...) } g.dictSymsToFinalize = nil } diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index b70d8d198e..5c9aafe490 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -321,10 +321,6 @@ func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) { } // Do the substitution of the type meth2.SetType(ts.Typ(meth.Type())) - // Add any new fully instantiated types - // seen during the substitution to - // g.instTypeList. - g.instTypeList = append(g.instTypeList, ts.InstTypeList...) newsym.Def = meth2 } meth = meth2 @@ -335,7 +331,7 @@ func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) { ntyp.Methods().Set(methods) if !ntyp.HasTParam() && !ntyp.HasShape() { // Generate all the methods for a new fully-instantiated type. - g.instTypeList = append(g.instTypeList, ntyp) + typecheck.NeedInstType(ntyp) } } diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 7855702b02..fd208bff9a 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1871,4 +1871,8 @@ func substInstType(t *types.Type, baseType *types.Type, targs []*types.Type) { newfields[i].Nname = nname } t.Methods().Set(newfields) + if !t.HasTParam() && t.Kind() != types.TINTER && t.Methods().Len() > 0 { + // Generate all the methods for a new fully-instantiated type. + NeedInstType(t) + } } diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index d0ae529596..34f20879f1 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -992,6 +992,22 @@ func assert(p bool) { base.Assert(p) } +// List of newly fully-instantiated types who should have their methods generated. +var instTypeList []*types.Type + +// NeedInstType adds a new fully-instantied type to instTypeList. +func NeedInstType(t *types.Type) { + instTypeList = append(instTypeList, t) +} + +// GetInstTypeList returns the current contents of instTypeList, and sets +// instTypeList to nil. +func GetInstTypeList() []*types.Type { + r := instTypeList + instTypeList = nil + return r +} + // General type substituter, for replacing typeparams with type args. type Tsubster struct { Tparams []*types.Type @@ -999,8 +1015,6 @@ type Tsubster struct { // If non-nil, the substitution map from name nodes in the generic function to the // name nodes in the new stenciled function. Vars map[*ir.Name]*ir.Name - // New fully-instantiated generic types whose methods should be instantiated. - InstTypeList []*types.Type // If non-nil, function to substitute an incomplete (TFORW) type. SubstForwFunc func(*types.Type) *types.Type } @@ -1258,7 +1272,8 @@ func (ts *Tsubster) typ1(t *types.Type) *types.Type { newt.Methods().Set(newfields) if !newt.HasTParam() && !newt.HasShape() { // Generate all the methods for a new fully-instantiated type. - ts.InstTypeList = append(ts.InstTypeList, newt) + + NeedInstType(newt) } } return newt diff --git a/test/typeparam/issue48185b.dir/a.go b/test/typeparam/issue48185b.dir/a.go new file mode 100644 index 0000000000..9aed60cfae --- /dev/null +++ b/test/typeparam/issue48185b.dir/a.go @@ -0,0 +1,37 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +import ( + "reflect" + "sync" +) + +type addressableValue struct{ reflect.Value } + +type arshalers[Options, Coder any] struct { + fncVals []typedArshaler[Options, Coder] + fncCache sync.Map // map[reflect.Type]unmarshaler +} +type typedArshaler[Options, Coder any] struct { + typ reflect.Type + fnc func(Options, *Coder, addressableValue) error +} + +type UnmarshalOptions1 struct { + // Unmarshalers is a list of type-specific unmarshalers to use. + Unmarshalers *arshalers[UnmarshalOptions1, Decoder1] +} + +type Decoder1 struct { +} + +func (a *arshalers[Options, Coder]) lookup(fnc func(Options, *Coder, addressableValue) error, t reflect.Type) func(Options, *Coder, addressableValue) error { + return fnc +} + +func UnmarshalFuncV2[T any](fn func(UnmarshalOptions1, *Decoder1, T) error) *arshalers[UnmarshalOptions1, Decoder1] { + return &arshalers[UnmarshalOptions1, Decoder1]{} +} diff --git a/test/typeparam/issue48185b.dir/main.go b/test/typeparam/issue48185b.dir/main.go new file mode 100644 index 0000000000..978e6ae585 --- /dev/null +++ b/test/typeparam/issue48185b.dir/main.go @@ -0,0 +1,18 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "a" + "fmt" +) + +func main() { + _ = a.UnmarshalOptions1{ + Unmarshalers: a.UnmarshalFuncV2(func(opts a.UnmarshalOptions1, dec *a.Decoder1, val *interface{}) (err error) { + return fmt.Errorf("error") + }), + } +} diff --git a/test/typeparam/issue48185b.go b/test/typeparam/issue48185b.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/issue48185b.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From dcf3545774a8b2bc639f8da14dec2526b8ca9caf Mon Sep 17 00:00:00 2001 From: korzhao Date: Fri, 3 Sep 2021 15:55:16 +0800 Subject: [PATCH 1029/2500] encoding/gob: optimize decoding of slice MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In CL 345572, we used the reflect.Value.SetLen method to avoid extra memory allocation for reflect.Value.Slice. This also applies to function decodeSlice name old time/op new time/op delta DecodeStringsSlice-12 96.5µs ±12% 63.0µs ± 8% -34.68% (p=0.000 n=9+10) name old alloc/op new alloc/op delta DecodeStringsSlice-12 89.3kB ± 0% 65.3kB ± 0% -26.89% (p=0.000 n=10+10) name old allocs/op new allocs/op delta DecodeStringsSlice-12 3.18k ± 0% 2.18k ± 0% -31.47% (p=0.000 n=10+10) Change-Id: Ifdb43716cc90a265962dec022704a5571f447fd8 Reviewed-on: https://go-review.googlesource.com/c/go/+/347533 Reviewed-by: Joe Tsai Reviewed-by: Rob Pike Trust: Joe Tsai Run-TryBot: Joe Tsai TryBot-Result: Go Bot --- src/encoding/gob/decode.go | 2 +- src/encoding/gob/timing_test.go | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/encoding/gob/decode.go b/src/encoding/gob/decode.go index 4ef9ef7243..f92556f8ab 100644 --- a/src/encoding/gob/decode.go +++ b/src/encoding/gob/decode.go @@ -625,7 +625,7 @@ func (dec *Decoder) decodeSlice(state *decoderState, value reflect.Value, elemOp if value.Cap() < n { value.Set(reflect.MakeSlice(typ, n, n)) } else { - value.Set(value.Slice(0, n)) + value.SetLen(n) } dec.decodeArrayHelper(state, value, elemOp, n, ovfl, helper) } diff --git a/src/encoding/gob/timing_test.go b/src/encoding/gob/timing_test.go index ceb21c4107..516aeea92c 100644 --- a/src/encoding/gob/timing_test.go +++ b/src/encoding/gob/timing_test.go @@ -279,7 +279,13 @@ func BenchmarkDecodeStringSlice(b *testing.B) { } benchmarkDecodeSlice(b, a) } - +func BenchmarkDecodeStringsSlice(b *testing.B) { + a := make([][]string, 1000) + for i := range a { + a[i] = []string{"now is the time"} + } + benchmarkDecodeSlice(b, a) +} func BenchmarkDecodeBytesSlice(b *testing.B) { a := make([][]byte, 1000) for i := range a { -- GitLab From a9a01a3fbdf70e7a9d914fe0b9b5ab1199fd74fe Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 7 Sep 2021 10:54:17 -0700 Subject: [PATCH 1030/2500] cmd/compile: remove now-unneeded SetHasTParam() for cached ptr element We had code in NewPtr() to set the HasTParam/HasShape flag as needed for the cached ptr element if it wasn't set correctly based on its Elem. This was causing the race mentioned in the issue. But that setting code is no longer needed, as long as we call SetRParams() soon after calling NewIncompleteNamedType(), before creating/translating the underlying type (which we do). The HasTParam/HasShape attribute can only come from setting of rparams or a direct typeparam/shape somewhere in the underlying type, both of which don't depend on recursion, etc. (as long as the rparams are set early). Added a check that HasTParam/HasShape are set correctly for the cached pointer/slice elems in NewPtr() and NewSlice(). Fixes #48191 Change-Id: Ide7d82efb77ae97901e75b2e6c65bd1bfc25e0ee Reviewed-on: https://go-review.googlesource.com/c/go/+/348089 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/typecheck/iimport.go | 5 +- src/cmd/compile/internal/types/type.go | 13 +- test/typeparam/issue48191.go | 269 ++++++++++++++++++ 3 files changed, 278 insertions(+), 9 deletions(-) create mode 100644 test/typeparam/issue48191.go diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index fd208bff9a..8bc098c2bd 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1757,7 +1757,10 @@ func builtinCall(pos src.XPos, op ir.Op) *ir.CallExpr { } // NewIncompleteNamedType returns a TFORW type t with name specified by sym, such -// that t.nod and sym.Def are set correctly. +// that t.nod and sym.Def are set correctly. If there are any RParams for the type, +// they should be set soon after creating the TFORW type, before creating the +// underlying type. That ensures that the HasTParam and HasShape flags will be set +// properly, in case this type is part of some mutually recursive type. func NewIncompleteNamedType(pos src.XPos, sym *types.Sym) *types.Type { name := ir.NewDeclNameAt(pos, ir.OTYPE, sym) forw := types.NewNamed(name) diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 8fb8fb377f..eb70f7b9b4 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -643,6 +643,9 @@ func NewSlice(elem *Type) *Type { if t.Elem() != elem { base.Fatalf("elem mismatch") } + if elem.HasTParam() != t.HasTParam() || elem.HasShape() != t.HasShape() { + base.Fatalf("Incorrect HasTParam/HasShape flag for cached slice type") + } return t } @@ -735,14 +738,8 @@ func NewPtr(elem *Type) *Type { if t.Elem() != elem { base.Fatalf("NewPtr: elem mismatch") } - if elem.HasTParam() { - // Extra check when reusing the cache, since the elem - // might have still been undetermined (i.e. a TFORW type) - // when this entry was cached. - t.SetHasTParam(true) - } - if elem.HasShape() { - t.SetHasShape(true) + if elem.HasTParam() != t.HasTParam() || elem.HasShape() != t.HasShape() { + base.Fatalf("Incorrect HasTParam/HasShape flag for cached pointer type") } return t } diff --git a/test/typeparam/issue48191.go b/test/typeparam/issue48191.go new file mode 100644 index 0000000000..967004dd1a --- /dev/null +++ b/test/typeparam/issue48191.go @@ -0,0 +1,269 @@ +// compile -c=2 -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type I1 interface { + int8 | int16 | int32 | int64 | int | uint +} +type I2 interface{ float32 | float64 } +type I3 interface{ string } + +func F[G1 I1, G2 I2, G3 I3]() { + var m0 map[G2]rune + var ch0, ch1 chan bool + var ast0, ast1 []struct{ s0 G3 } + var ai64_2 []int64 + var m1, m2, m3 map[bool]map[int]struct { + m0 map[G2]byte + s1 G3 + } + var i8_0, i8_1 G1 + var i16_0 int16 + var am3, am4 []map[float64]map[G2]*func(*byte, map[uint]int64, G3, struct{}) G2 + var pi64_0, pi64_1 *int64 + var i, i1, i2 int + var as5, as6, as7 []G3 + var ch2, ch3, ch4 chan uint + var m4, m5, m6 map[G1]chan bool + + if func(G2, int32) byte { + return m1[false][30].m0[G2(28.6)] * m3[func(bool, uint) bool { + return false + }(false, uint(94))][31].m0[G2(185.0)] * m1[(true || true) && (false && false)][51-i2].m0[G2(278.6)] + }(G2(672.5), int32(35)) < m3[<-m5[func(int64, int64) G1 { + return i8_1 + }(*pi64_0, int64(50))]][15&i1^i2^i2].m0[G2(895.3)] || (func(int64, uint) uint { + return uint(94) + }(int64(30), uint(95))&^<-ch2^<-ch4)&<-ch2^<-ch4 == <-ch2 { + var f0 float64 + var pf2 *float64 + var ch5, ch6 chan int16 + var fnc0 func(*int64, G2, struct { + i8_0 G1 + m1 map[float64]bool + i64_2 int64 + }, map[byte]func(G2, float64, *uint, float64) struct{}) complex128 = func(p0 *int64, p1 G2, p2 struct { + i8_0 G1 + m1 map[float64]bool + i64_2 int64 + }, p3 map[byte]func(G2, float64, *uint, float64) struct{}) complex128 { + p0 = pi64_1 + m5 = map[G1]chan bool{(p2.i8_0 + i8_1 + i8_1 ^ i8_1) * p2.i8_0 / p2.i8_0: m4[p2.i8_0>><-ch2]} + return (2.65i - 31.18i) * func(byte, byte) complex128 { + return 13.12i - 32.90i + (44.15i - 70.53i - (87.16i*92.67i + (24.18i - 9.13i))) + (func(G1, int16) complex128 { + return 55.80i + }(G1(30), int16(80)) + 8.48i*79.18i + (37.30i*73.81i + (21.01i - 76.30i)) + func(G3, G2) complex128 { + return 35.58i + }(G3("2JYizeFiEMvXLkUR"), p1)*(81.59i-21.76i)) + }(m1[<-m5[G1(37)*i8_1<= '4'&'\uab3e'>>uint(83) && (<-m6[G1(24)%i8_0] && <-ch1)][i].s1 + i = len([]G3{ast1[2].s0}) + i16_0 = <-ch6 / i16_0 & <-ch6 + i = (i1^i|i2|i2)/i + i + m6 = m4 + am3 = am3 + m1[G2(869.6) == G2(i2)] = m2[func(float64, rune) byte { + return func(G3, byte) byte { + return byte(42) + }(G3("8iDnlygG194xl"), byte(89)) + }(*pf2, '\u9cf4')/m1[func(G3, float64) bool { + return false + }(G3("6MbwBSHYzr9t0zD"), 774.4)][76].m0[G2(508.0)]/m2[<-m4[i8_0]][92&^i2].m0[G2(807.0)] > m3[(int32(39)|int32(i2))&^int32(i2) < int32(i2)][89*i1&i2].m0[G2(327.5)]] + m2[<-m4[func(G1, complex128) G1 { + return i8_1 + }(i8_0, 35.01i)] && <-m4[func(int, G1) G1 { + return G1(0) + }(10, G1(70))*i8_1&i8_1>><-ch2] || fnc0(pi64_0, G2(689.5), struct { + i8_0 G1 + m1 map[float64]bool + i64_2 int64 + }{(G1(78)*i8_1 - i8_1) / i8_1, map[float64]bool{499.2: <-m6[G1(88)^i8_0]}, int64(83) &^ ai64_2[33] & *pi64_1 * ai64_2[i1]}, map[byte]func(G2, float64, *uint, float64) struct { + }{m1[len(G3("bNIJZq")+G3("Fri5pn1MsZzYtsaV7b")) >= i][i^i1].m0[G2(691.7)]: nil}) != 71.77i-34.84i] = map[int]struct { + m0 map[G2]byte + s1 G3 + }{((18+i2)&^i2%i2 ^ i) / i: m3[(G2(267.1)*G2(i1) > G2(i2) || (false || true || (true || false))) && func(int32, int64) bool { + return <-ch0 + }(int32(63), ai64_2[61&^i1&i2])][i|i^i1]} + i2 = 90 - i1 + _, _, _, _, _, _, _, _ = f0, pf2, ch5, ch6, fnc0, m7, ch7, fnc1 + } else { + var m7 map[G1]chan uint + var ch5, ch6, ch7 chan G3 + var i32_0, i32_1 int32 + var m8, m9, m10 map[bool]struct { + } + pi64_1 = pi64_0 + m6[func(G3, G2) G1 { + return (G1(35) | i8_0) << i8_1 / i8_1 &^ i8_1 / i8_1 + }(G3("YBiKg"), G2(122.6))] = make(chan bool) + ast0 = ast0 + i8_1 = (((G1(10)+i8_1)&i8_0+i8_0)&i8_0&i8_1 ^ i8_1) & i8_1 + am4 = am3 + i32_1 = int32(10) &^ i32_0 + m8[func(float64, G3) bool { + return func(rune, int16) bool { + return (G2(267.0)*G2(i2) == G2(i) || func(G2, G3) bool { + return <-ch0 + }(G2(53.3), <-ch5)) && func(G2, G1) int32 { + return int32(63) + }(G2(804.8), G1(2))-i32_0 < i32_1 + }('\xbd', i16_0) + }(370.9, ast0[len([]complex128{})+i-i2].s0) && (G2(245.0)-G2(i1) == G2(i1) || byte(17)&m2[false][26].m0[G2(628.5)] > m3[false][55].m0[G2(608.8)] || func(G1, G1) bool { + return true + }(G1(24), G1(2)) || (<-m5[G1(38)] || <-ch1) && func(int32, int) bool { + return false && true + }(int32(6), i1) && '\x26'&'\x27'|func(G2, G3) rune { + return '\x13' + }(G2(229.6), G3("ys1msVeg61uSImCDkRG3C")) <= 'V'>>uint(88)-('\xbe'+'\uafd4')) == (53.04i == 37.22i)] = m8[func(byte, int64) bool { + return <-ch1 + }(m3[false && false][96].m0[G2(147.6)], *pi64_0) && 643.5 > float64(i1) && (<-ch0 && <-ch1)] + i8_1 = func(byte, uint) G1 { + return G1(68) + }(m2[<-ch1 || <-m5[G1(96)+i8_0] || func(bool, int32) bool { + return func(int, byte) bool { + return m1[true][89].s1 <= G3("2ZMnHGOMQnyHSbJ") + }(i2, m2[<-m6[G1(47)]][94].m0[G2(981.3)]) + }(<-m4[G1(0)&^i8_0&i8_0], i32_0)][i2%i&^i].m0[func(complex128, rune) G2 { + return G2(93.1) * G2(i2) + }(4.63i, m0[G2(975.8)])], uint(21)) + _, _, _, _, _, _, _, _, _ = m7, ch5, ch6, ch7, i32_0, i32_1, m8, m9, m10 + } + + if *pi64_0>><-ch3 <= *pi64_0 || func(bool, int32) int32 { + return (int32(69)&^int32(i2) + int32(i2)) * int32(i2) + }(true, int32(49))^int32(i2) >= int32(i) { + var ai8_8, ai8_9 []G1 + var pi2, pi3, pi4 *int + var pi8_5, pi8_6 *G1 + var i64_0, i64_1 int64 + m1[754.8*float64(i2) != float64(i) && 6.26i == 69.99i] = map[int]struct { + m0 map[G2]byte + s1 G3 + }{len([]G2{G2(935.9) / G2(i2), func(int64, G2) G2 { + return G2(720.5) + }(int64(36), G2(349.7))})&*pi2 + i2 - i1: m1[(uint(29) >= <-ch4 || int64(45)+ai64_2[18] >= *pi64_1) == (func(G2, G2) bool { + return <-m5[G1(25)] + }(G2(447.2), G2(946.6)) || func(int, int16) bool { + return true + }(40, int16(41)) && byte(51) >= m2[true][13].m0[G2(6.6)])][*pi3]} + am4 = []map[float64]map[G2]*func(*byte, map[uint]int64, G3, struct { + }) G2{am4[i2%*pi3]} + pi2 = &i2 + pi64_0 = pi64_1 + ai8_8[*pi3] = *pi8_5&ai8_9[(*pi4+*pi3)%*pi3] ^ ai8_8[90+i2|*pi4] + ai64_2 = []int64{} + m4 = m4 + pi2 = &i1 + pi3 = &i2 + _, _, _, _, _, _, _, _, _ = ai8_8, ai8_9, pi2, pi3, pi4, pi8_5, pi8_6, i64_0, i64_1 + } + + if (true || false || int32(68) > int32(i1) || <-m5[G1(11)-i8_0] && true) && func(int, float64) bool { + return <-m5[(G1(83)-i8_1)&^i8_1] + }(i1, 886.6) || func(byte, int) bool { + return 401.0/float64(i1)/float64(i1)-float64(i) == float64(i2) + }(m1[(G1(85)^i8_1)&^i8_1 <= i8_1][72].m0[G2(617.4)], i1) || (<-m6[(G1(3)|i8_0)>><-ch2%i8_0|i8_0] || <-ch0) { + var ch5 chan map[byte]complex128 + var fnc0 func(int32, *map[rune]complex128) complex128 + var c0 complex128 + var st0, st1, st2 struct { + } + var au8 []uint + var st3, st4, st5 struct { + ph0 *G2 + st1 struct { + m0 map[rune]complex128 + pch1 *chan int64 + m2 map[bool]byte + st3 struct { + ch0 chan func(map[G1]*struct { + pm0 *map[bool]int64 + h1 G2 + }, struct { + u0 uint + }, uint, float64) *struct { + ch0 chan map[int16]G2 + } + i1 int + ch2 chan complex128 + } + } + pm2 *map[int64]struct { + s0 G3 + pi1 *int + st2 struct { + m0 map[int]map[rune]int64 + r1 rune + } + } + } + var am9, am10, am11 []map[uint]int64 + m1[G3("E")+(*st4.pm2)[*pi64_0+<-*st3.st1.pch1].s0 < (*st4.pm2)[int64(46)].s0+(G3("4Jsp3pv0x")+G3("MTKt98c")+(G3("E6Nxqpl70")+G3("eXhhxb")))+(G3("siISQNeBXoQIHwGB")+G3("CzocwLRWIUD")+(G3("cDWy3E3qpeJOmw1wP9wZ")+G3("S3ZRONdtB7K1LBC"))+func(G1, uint) G3 { + return m2[false][74].s1 + }(G1(9), uint(26)))+func(G2, int) G3 { + return G3("WzncXvaqK4zPn") + }(G2(291.6), i)+(ast1[(40^i1+i1)&^st4.st1.st3.i1].s0+func(byte, int64) G3 { + return m2[207.7 == float64(i2) && (false || false)][i2].s1 + }(byte(34), am11[25][func(int32, float64) uint { + return uint(77) + }(int32(29), 403.1)]))] = map[int]struct { + m0 map[G2]byte + s1 G3 + }{st3.st1.st3.i1: m2[<-m4[i8_1]][st5.st1.st3.i1-st3.st1.st3.i1-i2]} + st1 = struct { + }{} + pi64_0 = pi64_1 + m4 = m6 + as7 = as7 + m6[(i8_0+i8_0)&^i8_1&^i8_1] = m5[G1(96)^i8_1] + st2 = struct { + }{} + st1 = struct { + }{} + am10 = []map[uint]int64{am9[len((*st4.pm2)[int64(65)].s0)+i], am11[st4.st1.st3.i1%st4.st1.st3.i1^i1]} + i2 = st5.st1.st3.i1*i - st5.st1.st3.i1 + _, _, _, _, _, _, _, _, _, _, _, _, _ = ch5, fnc0, c0, st0, st1, st2, au8, st3, st4, st5, am9, am10, am11 + } + +} + +func main() { + F[int16, float32, string]() +} -- GitLab From 07f623063ddf8216b03a4a17a27110d330e80c7e Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Fri, 21 May 2021 09:43:58 -0700 Subject: [PATCH 1031/2500] reflect: add MapIter.Reset This allows callers to do (amortized) allocation-free iteration over many maps. Fixes #46293 Change-Id: I3aa6134dd00da35b508bd1e3b487332a871a3673 Reviewed-on: https://go-review.googlesource.com/c/go/+/321891 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Reviewed-by: Keith Randall --- src/reflect/all_test.go | 66 +++++++++++++++++++++++++++++++++++++++++ src/reflect/value.go | 12 ++++++++ 2 files changed, 78 insertions(+) diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index 6cb603cb16..01ce8b0c43 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -7223,6 +7223,72 @@ func TestMapIterNilMap(t *testing.T) { } } +func TestMapIterReset(t *testing.T) { + iter := new(MapIter) + + // Use of zero iterator should panic. + func() { + defer func() { recover() }() + iter.Next() + t.Error("Next did not panic") + }() + + // Reset to new Map should work. + m := map[string]int{"one": 1, "two": 2, "three": 3} + iter.Reset(ValueOf(m)) + if got, want := iterateToString(iter), `[one: 1, three: 3, two: 2]`; got != want { + t.Errorf("iterator returned %s (after sorting), want %s", got, want) + } + + // Reset to Zero value should work, but iterating over it should panic. + iter.Reset(Value{}) + func() { + defer func() { recover() }() + iter.Next() + t.Error("Next did not panic") + }() + + // Reset to a different Map with different types should work. + m2 := map[int]string{1: "one", 2: "two", 3: "three"} + iter.Reset(ValueOf(m2)) + if got, want := iterateToString(iter), `[1: one, 2: two, 3: three]`; got != want { + t.Errorf("iterator returned %s (after sorting), want %s", got, want) + } + + // Check that Reset, Next, and SetKey/SetValue play nicely together. + m3 := map[uint64]uint64{ + 1 << 0: 1 << 1, + 1 << 1: 1 << 2, + 1 << 2: 1 << 3, + } + kv := New(TypeOf(uint64(0))).Elem() + for i := 0; i < 5; i++ { + var seenk, seenv uint64 + iter.Reset(ValueOf(m3)) + for iter.Next() { + iter.SetKey(kv) + seenk ^= kv.Uint() + iter.SetValue(kv) + seenv ^= kv.Uint() + } + if seenk != 0b111 { + t.Errorf("iteration yielded keys %b, want %b", seenk, 0b111) + } + if seenv != 0b1110 { + t.Errorf("iteration yielded values %b, want %b", seenv, 0b1110) + } + } + + // Reset should not allocate. + n := int(testing.AllocsPerRun(10, func() { + iter.Reset(ValueOf(m2)) + iter.Reset(Value{}) + })) + if n > 0 { + t.Errorf("MapIter.Reset allocated %d times", n) + } +} + func TestMapIterSafety(t *testing.T) { // Using a zero MapIter causes a panic, but not a crash. func() { diff --git a/src/reflect/value.go b/src/reflect/value.go index 90f31bae0a..39c3c0f06e 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -1700,6 +1700,18 @@ func (it *MapIter) Next() bool { return mapiterkey(&it.hiter) != nil } +// Reset modifies it to iterate over v. +// It panics if v's Kind is not Map and v is not the zero Value. +// Reset(Value{}) causes it to not to refer to any map, +// which may allow the previously iterated-over map to be garbage collected. +func (it *MapIter) Reset(v Value) { + if v.IsValid() { + v.mustBe(Map) + } + it.m = v + it.hiter = hiter{} +} + // MapRange returns a range iterator for a map. // It panics if v's Kind is not Map. // -- GitLab From b5e33a50fe600314752b866980a9b2498f23a326 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Sat, 4 Sep 2021 14:55:57 -0700 Subject: [PATCH 1032/2500] reflect: rename MapIter method receiver variable from it to iter This is easier to use in documentation. Adjust the existing documentation that worked around the unfortunate name. Change-Id: Ia4b7793ab94dfd7fb3968ee983be56cc38c30ec3 Reviewed-on: https://go-review.googlesource.com/c/go/+/347769 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/reflect/value.go | 78 ++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/src/reflect/value.go b/src/reflect/value.go index 39c3c0f06e..3c2172135e 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -1600,29 +1600,29 @@ type MapIter struct { hiter hiter } -// Key returns the key of the iterator's current map entry. -func (it *MapIter) Key() Value { - if !it.hiter.initialized() { +// Key returns the key of iter's current map entry. +func (iter *MapIter) Key() Value { + if !iter.hiter.initialized() { panic("MapIter.Key called before Next") } - iterkey := mapiterkey(&it.hiter) + iterkey := mapiterkey(&iter.hiter) if iterkey == nil { panic("MapIter.Key called on exhausted iterator") } - t := (*mapType)(unsafe.Pointer(it.m.typ)) + t := (*mapType)(unsafe.Pointer(iter.m.typ)) ktype := t.key - return copyVal(ktype, it.m.flag.ro()|flag(ktype.Kind()), iterkey) + return copyVal(ktype, iter.m.flag.ro()|flag(ktype.Kind()), iterkey) } -// SetKey assigns dst to the key of the iterator's current map entry. -// It is equivalent to dst.Set(it.Key()), but it avoids allocating a new Value. +// SetKey assigns dst to the key of iter's current map entry. +// It is equivalent to dst.Set(i.Key()), but it avoids allocating a new Value. // As in Go, the key must be assignable to dst's type. -func (it *MapIter) SetKey(dst Value) { - if !it.hiter.initialized() { +func (iter *MapIter) SetKey(dst Value) { + if !iter.hiter.initialized() { panic("MapIter.SetKey called before Next") } - iterkey := mapiterkey(&it.hiter) + iterkey := mapiterkey(&iter.hiter) if iterkey == nil { panic("MapIter.SetKey called on exhausted iterator") } @@ -1633,37 +1633,37 @@ func (it *MapIter) SetKey(dst Value) { target = dst.ptr } - t := (*mapType)(unsafe.Pointer(it.m.typ)) + t := (*mapType)(unsafe.Pointer(iter.m.typ)) ktype := t.key - key := Value{ktype, iterkey, it.m.flag | flag(ktype.Kind())} + key := Value{ktype, iterkey, iter.m.flag | flag(ktype.Kind())} key = key.assignTo("reflect.MapIter.SetKey", dst.typ, target) typedmemmove(dst.typ, dst.ptr, key.ptr) } -// Value returns the value of the iterator's current map entry. -func (it *MapIter) Value() Value { - if !it.hiter.initialized() { +// Value returns the value of iter's current map entry. +func (iter *MapIter) Value() Value { + if !iter.hiter.initialized() { panic("MapIter.Value called before Next") } - iterelem := mapiterelem(&it.hiter) + iterelem := mapiterelem(&iter.hiter) if iterelem == nil { panic("MapIter.Value called on exhausted iterator") } - t := (*mapType)(unsafe.Pointer(it.m.typ)) + t := (*mapType)(unsafe.Pointer(iter.m.typ)) vtype := t.elem - return copyVal(vtype, it.m.flag.ro()|flag(vtype.Kind()), iterelem) + return copyVal(vtype, iter.m.flag.ro()|flag(vtype.Kind()), iterelem) } -// SetValue assigns dst to the value of the iterator's current map entry. -// It is equivalent to dst.Set(it.Value()), but it avoids allocating a new Value. +// SetValue assigns dst to the value of iter's current map entry. +// It is equivalent to dst.Set(i.Value()), but it avoids allocating a new Value. // As in Go, the value must be assignable to dst's type. -func (it *MapIter) SetValue(dst Value) { - if !it.hiter.initialized() { +func (iter *MapIter) SetValue(dst Value) { + if !iter.hiter.initialized() { panic("MapIter.SetValue called before Next") } - iterelem := mapiterelem(&it.hiter) + iterelem := mapiterelem(&iter.hiter) if iterelem == nil { panic("MapIter.SetValue called on exhausted iterator") } @@ -1674,42 +1674,42 @@ func (it *MapIter) SetValue(dst Value) { target = dst.ptr } - t := (*mapType)(unsafe.Pointer(it.m.typ)) + t := (*mapType)(unsafe.Pointer(iter.m.typ)) vtype := t.elem - elem := Value{vtype, iterelem, it.m.flag | flag(vtype.Kind())} + elem := Value{vtype, iterelem, iter.m.flag | flag(vtype.Kind())} elem = elem.assignTo("reflect.MapIter.SetValue", dst.typ, target) typedmemmove(dst.typ, dst.ptr, elem.ptr) } // Next advances the map iterator and reports whether there is another -// entry. It returns false when the iterator is exhausted; subsequent +// entry. It returns false when iter is exhausted; subsequent // calls to Key, Value, or Next will panic. -func (it *MapIter) Next() bool { - if !it.m.IsValid() { +func (iter *MapIter) Next() bool { + if !iter.m.IsValid() { panic("MapIter.Next called on an iterator that does not have an associated map Value") } - if !it.hiter.initialized() { - mapiterinit(it.m.typ, it.m.pointer(), &it.hiter) + if !iter.hiter.initialized() { + mapiterinit(iter.m.typ, iter.m.pointer(), &iter.hiter) } else { - if mapiterkey(&it.hiter) == nil { + if mapiterkey(&iter.hiter) == nil { panic("MapIter.Next called on exhausted iterator") } - mapiternext(&it.hiter) + mapiternext(&iter.hiter) } - return mapiterkey(&it.hiter) != nil + return mapiterkey(&iter.hiter) != nil } -// Reset modifies it to iterate over v. +// Reset modifies iter to iterate over v. // It panics if v's Kind is not Map and v is not the zero Value. -// Reset(Value{}) causes it to not to refer to any map, +// Reset(Value{}) causes iter to not to refer to any map, // which may allow the previously iterated-over map to be garbage collected. -func (it *MapIter) Reset(v Value) { +func (iter *MapIter) Reset(v Value) { if v.IsValid() { v.mustBe(Map) } - it.m = v - it.hiter = hiter{} + iter.m = v + iter.hiter = hiter{} } // MapRange returns a range iterator for a map. -- GitLab From b606739be6758615658188c8a6453256eaeccf35 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 7 Sep 2021 15:13:51 -0700 Subject: [PATCH 1033/2500] reflect: add test for passing float32 signaling NaNs Update #40724 Change-Id: I110cdb7c4a2c5db6b85ca951143430555261abf3 Reviewed-on: https://go-review.googlesource.com/c/go/+/348017 Trust: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/reflect/abi_test.go | 25 +++++++++++++++++++++++++ src/reflect/all_test.go | 3 ++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/reflect/abi_test.go b/src/reflect/abi_test.go index 2b247d1d79..873febbad2 100644 --- a/src/reflect/abi_test.go +++ b/src/reflect/abi_test.go @@ -9,6 +9,7 @@ package reflect_test import ( "internal/abi" + "math" "math/rand" "reflect" "runtime" @@ -962,3 +963,27 @@ func genValue(t *testing.T, typ reflect.Type, r *rand.Rand) reflect.Value { } return v } + +func TestSignalingNaNArgument(t *testing.T) { + v := reflect.ValueOf(func(x float32) { + // make sure x is a signaling NaN. + u := math.Float32bits(x) + if u != snan { + t.Fatalf("signaling NaN not correct: %x\n", u) + } + }) + v.Call([]reflect.Value{reflect.ValueOf(math.Float32frombits(snan))}) +} + +func TestSignalingNaNReturn(t *testing.T) { + v := reflect.ValueOf(func() float32 { + return math.Float32frombits(snan) + }) + var x float32 + reflect.ValueOf(&x).Elem().Set(v.Call(nil)[0]) + // make sure x is a signaling NaN. + u := math.Float32bits(x) + if u != snan { + t.Fatalf("signaling NaN not correct: %x\n", u) + } +} diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index 01ce8b0c43..eb3ddcb3e4 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -4428,8 +4428,9 @@ func TestConvertPanic(t *testing.T) { var gFloat32 float32 +const snan uint32 = 0x7f800001 + func TestConvertNaNs(t *testing.T) { - const snan uint32 = 0x7f800001 type myFloat32 float32 x := V(myFloat32(math.Float32frombits(snan))) y := x.Convert(TypeOf(float32(0))) -- GitLab From 3fff213ac24dc3b9b92c8a1f5f18ec0c97bac4c0 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 31 Aug 2021 08:01:44 -0700 Subject: [PATCH 1034/2500] cmd/compile: add CONVIFACE nodes needed in generic code due to assignments Added new function earlyTransformAssign() to add needed CONVIFACE nodes due to assignments in generic functions. Fixes #48049 Change-Id: I7cd9cee6ecf34ed2ef0743d1b17645b9f520fa00 Reviewed-on: https://go-review.googlesource.com/c/go/+/347914 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stmt.go | 3 ++ src/cmd/compile/internal/noder/transform.go | 53 +++++++++++++++++++++ test/typeparam/issue48049.go | 33 +++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 test/typeparam/issue48049.go diff --git a/src/cmd/compile/internal/noder/stmt.go b/src/cmd/compile/internal/noder/stmt.go index eeb994d343..146761c23f 100644 --- a/src/cmd/compile/internal/noder/stmt.go +++ b/src/cmd/compile/internal/noder/stmt.go @@ -101,6 +101,8 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { n.Def = initDefn(n, names) if delay { + earlyTransformAssign(n, lhs, rhs) + n.X, n.Y = lhs[0], rhs[0] n.SetTypecheck(3) return n } @@ -115,6 +117,7 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { n := ir.NewAssignListStmt(g.pos(stmt), ir.OAS2, lhs, rhs) n.Def = initDefn(n, names) if delay { + earlyTransformAssign(n, lhs, rhs) n.SetTypecheck(3) return n } diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index 180891b5b5..b278f3db09 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -365,6 +365,59 @@ assignOK: } } +// Version of transformAssign that can run on generic code that adds CONVIFACE calls +// as needed (and rewrites multi-value calls). +func earlyTransformAssign(stmt ir.Node, lhs, rhs []ir.Node) { + cr := len(rhs) + if len(rhs) == 1 { + if rtyp := rhs[0].Type(); rtyp != nil && rtyp.IsFuncArgStruct() { + cr = rtyp.NumFields() + } + } + + // x,y,z = f() + _, isCallExpr := rhs[0].(*ir.CallExpr) + if isCallExpr && cr > len(rhs) { + stmt := stmt.(*ir.AssignListStmt) + stmt.SetOp(ir.OAS2FUNC) + r := rhs[0].(*ir.CallExpr) + rtyp := r.Type() + + mismatched := false + failed := false + for i := range lhs { + result := rtyp.Field(i).Type + + if lhs[i].Type() == nil || result == nil { + failed = true + } else if lhs[i] != ir.BlankNode && !types.Identical(lhs[i].Type(), result) { + mismatched = true + } + } + if mismatched && !failed { + typecheck.RewriteMultiValueCall(stmt, r) + } + return + } + + // x, ok = y + if len(lhs) != len(rhs) { + assert(len(lhs) == 2 && len(rhs) == 1) + // TODO(danscales): deal with case where x or ok is an interface + // type. We want to add CONVIFACE now, but that is tricky, because + // the rhs may be AS2MAPR, AS2RECV, etc. which has two result values, + // and that is not rewritten until the order phase (o.stmt, as2ok). + return + } + + // Check for interface conversion on each assignment + for i, r := range rhs { + if lhs[i].Type() != nil && lhs[i].Type().IsInterface() { + rhs[i] = assignconvfn(r, lhs[i].Type()) + } + } +} + // Corresponds to typecheck.typecheckargs. Really just deals with multi-value calls. func transformArgs(n ir.InitNode) { var list []ir.Node diff --git a/test/typeparam/issue48049.go b/test/typeparam/issue48049.go new file mode 100644 index 0000000000..3a005142df --- /dev/null +++ b/test/typeparam/issue48049.go @@ -0,0 +1,33 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func main() { + Gooer2[byte]() +} + +type Fooer[T any] interface { + Foo(p T) +} + +type fooer1[T any] struct{} + +func (fooer1[T]) Foo(T) {} + +type fooer2[T any] struct { + r []Fooer[T] +} + +//go:noinline +func (mr fooer2[T]) Foo(p T) { + mr.r[0] = fooer1[T]{} + return +} + +func Gooer2[T any]() Fooer[T] { + return fooer2[T]{} +} -- GitLab From 963218cc9c331931c5886f2eb7199e6d0c362e93 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 7 Sep 2021 16:10:31 -0700 Subject: [PATCH 1035/2500] reflect: correct typoo in comment Change-Id: Ic3c69906a8afde63278f173df0427b1c460c9f3e Reviewed-on: https://go-review.googlesource.com/c/go/+/348189 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Brad Fitzpatrick TryBot-Result: Go Bot --- src/reflect/type.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/reflect/type.go b/src/reflect/type.go index 1d637d134e..afb802e641 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -1428,7 +1428,7 @@ var ptrMap sync.Map // map[*rtype]*ptrType // For example, if t represents type Foo, PtrTo(t) represents *Foo. // // Deprecated: use PointerTo. PtrTo is the old spelling. -// The two functions behaves identically. +// The two functions behave identically. func PtrTo(t Type) Type { return PointerTo(t) } // PointerTo returns the pointer type with element t. -- GitLab From bab79dd3627a9c5d4b43ac3f3c2eba4a1f04b813 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 7 Sep 2021 16:24:49 -0700 Subject: [PATCH 1036/2500] reflect: add back signaling NaN test I was a little too agressive in CL 258957 (removing 387 support) in removing a signaling NaN test that should probably still exist. I should have just removed the 387 skip, not the entire test. Change-Id: I97ca53f190eb0de00e43b96629b2cae677e7dacb Reviewed-on: https://go-review.googlesource.com/c/go/+/348209 Trust: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/reflect/all_test.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index eb3ddcb3e4..293d036f67 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -4431,6 +4431,14 @@ var gFloat32 float32 const snan uint32 = 0x7f800001 func TestConvertNaNs(t *testing.T) { + // Test to see if a store followed by a load of a signaling NaN + // maintains the signaling bit. (This used to fail on the 387 port.) + gFloat32 = math.Float32frombits(snan) + runtime.Gosched() // make sure we don't optimize the store/load away + if got := math.Float32bits(gFloat32); got != snan { + t.Errorf("store/load of sNaN not faithful, got %x want %x", got, snan) + } + // Test reflect's conversion between float32s. See issue 36400. type myFloat32 float32 x := V(myFloat32(math.Float32frombits(snan))) y := x.Convert(TypeOf(float32(0))) -- GitLab From f5bdbf311c3c28fd7cdb8ce31b272deb3feb6f64 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Sat, 21 Aug 2021 04:30:29 +0000 Subject: [PATCH 1037/2500] cmd/internal/obj/riscv: simplify rewriteMOV Rewrite and simplify the rewriteMOV function in preparation for eliminating it entirely. Improve some error messages in the process. Change-Id: Id9a77be5174d46cc23651930c2e9068ee6555690 Reviewed-on: https://go-review.googlesource.com/c/go/+/344458 Trust: Joel Sing Reviewed-by: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot --- .../asm/internal/asm/testdata/riscv64error.s | 12 ++-- src/cmd/internal/obj/riscv/obj.go | 66 +++++++------------ 2 files changed, 30 insertions(+), 48 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/riscv64error.s b/src/cmd/asm/internal/asm/testdata/riscv64error.s index b09a1c7a8c..238552565b 100644 --- a/src/cmd/asm/internal/asm/testdata/riscv64error.s +++ b/src/cmd/asm/internal/asm/testdata/riscv64error.s @@ -3,12 +3,12 @@ // license that can be found in the LICENSE file. TEXT errors(SB),$0 - MOV $errors(SB), (X5) // ERROR "unsupported addr MOV" - MOV $8(SP), (X5) // ERROR "unsupported addr MOV" - MOVB $8(SP), X5 // ERROR "unsupported addr MOV" - MOVH $8(SP), X5 // ERROR "unsupported addr MOV" - MOVW $8(SP), X5 // ERROR "unsupported addr MOV" - MOVF $8(SP), X5 // ERROR "unsupported addr MOV" + MOV $errors(SB), (X5) // ERROR "address load must target register" + MOV $8(SP), (X5) // ERROR "address load must target register" + MOVB $8(SP), X5 // ERROR "unsupported address load" + MOVH $8(SP), X5 // ERROR "unsupported address load" + MOVW $8(SP), X5 // ERROR "unsupported address load" + MOVF $8(SP), X5 // ERROR "unsupported address load" MOV $1234, 0(SP) // ERROR "constant load must target register" MOV $1234, 8(SP) // ERROR "constant load must target register" MOV $0, 0(SP) // ERROR "constant load must target register" diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index 1140542739..443f761ad9 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -226,51 +226,32 @@ func rewriteMOV(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog) { panic(fmt.Sprintf("%+v is not a MOV pseudo-instruction", p.As)) } - switch p.From.Type { - case obj.TYPE_MEM: - switch p.From.Name { - case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE: - if p.To.Type != obj.TYPE_REG { - ctxt.Diag("unsupported load for %v", p) - } + switch { + case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG: + case p.From.Type == obj.TYPE_MEM && p.To.Type == obj.TYPE_REG: + switch p.From.Name { + case obj.NAME_AUTO, obj.NAME_NONE, obj.NAME_PARAM: case obj.NAME_EXTERN, obj.NAME_STATIC: p.Mark |= NEED_PCREL_ITYPE_RELOC - default: ctxt.Diag("unsupported name %d for %v", p.From.Name, p) } - case obj.TYPE_REG: - switch p.To.Type { - case obj.TYPE_REG: - switch p.As { - case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD: - default: - ctxt.Diag("unsupported register-register move at %v", p) - } - - case obj.TYPE_MEM: - switch p.As { - case AMOVBU, AMOVHU, AMOVWU: - ctxt.Diag("unsupported unsigned store at %v", p) - return - } - switch p.To.Name { - case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE: - - case obj.NAME_EXTERN, obj.NAME_STATIC: - p.Mark |= NEED_PCREL_STYPE_RELOC - - default: - ctxt.Diag("unsupported name %d for %v", p.From.Name, p) - } - + case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM: + switch p.As { + case AMOVBU, AMOVHU, AMOVWU: + ctxt.Diag("unsupported unsigned store at %v", p) + } + switch p.To.Name { + case obj.NAME_AUTO, obj.NAME_NONE, obj.NAME_PARAM: + case obj.NAME_EXTERN, obj.NAME_STATIC: + p.Mark |= NEED_PCREL_STYPE_RELOC default: - ctxt.Diag("unsupported MOV at %v", p) + ctxt.Diag("unsupported name %d for %v", p.From.Name, p) } - case obj.TYPE_CONST: + case p.From.Type == obj.TYPE_CONST: if p.As != AMOV { ctxt.Diag("%v: unsupported constant load", p) } @@ -278,18 +259,19 @@ func rewriteMOV(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog) { ctxt.Diag("%v: constant load must target register", p) } - case obj.TYPE_ADDR: - if p.To.Type != obj.TYPE_REG || p.As != AMOV { - ctxt.Diag("unsupported addr MOV at %v", p) + case p.From.Type == obj.TYPE_ADDR: + if p.As != AMOV { + ctxt.Diag("%v: unsupported address load", p) + } + if p.To.Type != obj.TYPE_REG { + ctxt.Diag("%v: address load must target register", p) } switch p.From.Name { - case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE: - + case obj.NAME_AUTO, obj.NAME_NONE, obj.NAME_PARAM: case obj.NAME_EXTERN, obj.NAME_STATIC: p.Mark |= NEED_PCREL_ITYPE_RELOC - default: - ctxt.Diag("bad addr MOV from name %v at %v", p.From.Name, p) + ctxt.Diag("unsupported name %d for %v", p.From.Name, p) } default: -- GitLab From da790cccc5da9486e5f45360a3b1b76a1a0aeaea Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Sat, 21 Aug 2021 09:06:25 +0000 Subject: [PATCH 1038/2500] cmd/internal/obj/riscv: absorb rewriteMOV into instruction generation Replace the now poorly named rewriteMOV function with a markRelocs function, absorbing the MOV validation into the instruction generation code. Change-Id: I6ae94553f7f300862c40310343ef0be8f44a4b0f Reviewed-on: https://go-review.googlesource.com/c/go/+/344459 Trust: Joel Sing Reviewed-by: Cherry Mui --- src/cmd/internal/obj/riscv/obj.go | 122 +++++++++++++----------------- 1 file changed, 52 insertions(+), 70 deletions(-) diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index 443f761ad9..fd5026f25b 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -218,64 +218,28 @@ func movToStore(mnemonic obj.As) obj.As { } } -// rewriteMOV rewrites MOV pseudo-instructions. -func rewriteMOV(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog) { +// markRelocs marks an obj.Prog that specifies a MOV pseudo-instruction and +// requires relocation. +func markRelocs(p *obj.Prog) { switch p.As { case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD: - default: - panic(fmt.Sprintf("%+v is not a MOV pseudo-instruction", p.As)) - } - - switch { - case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG: - - case p.From.Type == obj.TYPE_MEM && p.To.Type == obj.TYPE_REG: - switch p.From.Name { - case obj.NAME_AUTO, obj.NAME_NONE, obj.NAME_PARAM: - case obj.NAME_EXTERN, obj.NAME_STATIC: - p.Mark |= NEED_PCREL_ITYPE_RELOC - default: - ctxt.Diag("unsupported name %d for %v", p.From.Name, p) - } - - case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM: - switch p.As { - case AMOVBU, AMOVHU, AMOVWU: - ctxt.Diag("unsupported unsigned store at %v", p) - } - switch p.To.Name { - case obj.NAME_AUTO, obj.NAME_NONE, obj.NAME_PARAM: - case obj.NAME_EXTERN, obj.NAME_STATIC: - p.Mark |= NEED_PCREL_STYPE_RELOC - default: - ctxt.Diag("unsupported name %d for %v", p.From.Name, p) - } - - case p.From.Type == obj.TYPE_CONST: - if p.As != AMOV { - ctxt.Diag("%v: unsupported constant load", p) - } - if p.To.Type != obj.TYPE_REG { - ctxt.Diag("%v: constant load must target register", p) - } - - case p.From.Type == obj.TYPE_ADDR: - if p.As != AMOV { - ctxt.Diag("%v: unsupported address load", p) - } - if p.To.Type != obj.TYPE_REG { - ctxt.Diag("%v: address load must target register", p) - } - switch p.From.Name { - case obj.NAME_AUTO, obj.NAME_NONE, obj.NAME_PARAM: - case obj.NAME_EXTERN, obj.NAME_STATIC: - p.Mark |= NEED_PCREL_ITYPE_RELOC - default: - ctxt.Diag("unsupported name %d for %v", p.From.Name, p) + switch { + case p.From.Type == obj.TYPE_ADDR && p.To.Type == obj.TYPE_REG: + switch p.From.Name { + case obj.NAME_EXTERN, obj.NAME_STATIC: + p.Mark |= NEED_PCREL_ITYPE_RELOC + } + case p.From.Type == obj.TYPE_MEM && p.To.Type == obj.TYPE_REG: + switch p.From.Name { + case obj.NAME_EXTERN, obj.NAME_STATIC: + p.Mark |= NEED_PCREL_ITYPE_RELOC + } + case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM: + switch p.To.Name { + case obj.NAME_EXTERN, obj.NAME_STATIC: + p.Mark |= NEED_PCREL_STYPE_RELOC + } } - - default: - ctxt.Diag("unsupported MOV at %v", p) } } @@ -641,14 +605,8 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { } } - // Rewrite MOV pseudo-instructions. This cannot be done in - // progedit, as SP offsets need to be applied before we split - // up some of the Addrs. for p := cursym.Func().Text; p != nil; p = p.Link { - switch p.As { - case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD: - rewriteMOV(ctxt, newprog, p) - } + markRelocs(p) } // Compute instruction addresses. Once we do that, we need to check for @@ -1746,6 +1704,11 @@ func instructionsForMOV(p *obj.Prog) []*instruction { switch { case p.From.Type == obj.TYPE_CONST && p.To.Type == obj.TYPE_REG: // Handle constant to register moves. + if p.As != AMOV { + p.Ctxt.Diag("%v: unsupported constant load", p) + return nil + } + low, high, err := Split32BitImmediate(ins.imm) if err != nil { p.Ctxt.Diag("%v: constant %d too large: %v", p, ins.imm, err) @@ -1769,6 +1732,10 @@ func instructionsForMOV(p *obj.Prog) []*instruction { inss = append(inss, ins) } + case p.From.Type == obj.TYPE_CONST && p.To.Type != obj.TYPE_REG: + p.Ctxt.Diag("%v: constant load must target register", p) + return nil + case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG: // Handle register to register moves. switch p.As { @@ -1820,13 +1787,17 @@ func instructionsForMOV(p *obj.Prog) []*instruction { insAUIPC := &instruction{as: AAUIPC, rd: ins.rd} ins.as, ins.rs1, ins.rs2, ins.imm = movToLoad(p.As), ins.rd, obj.REG_NONE, 0 inss = []*instruction{insAUIPC, ins} + + default: + p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p) + return nil } case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM: // Register to memory stores. switch p.As { case AMOVBU, AMOVHU, AMOVWU: - // rewriteMOV should have already added an error for these. + p.Ctxt.Diag("%v: unsupported unsigned store", p) return nil } switch p.To.Name { @@ -1843,11 +1814,18 @@ func instructionsForMOV(p *obj.Prog) []*instruction { insAUIPC := &instruction{as: AAUIPC, rd: REG_TMP} ins.as, ins.rd, ins.rs1, ins.rs2, ins.imm = movToStore(p.As), REG_TMP, uint32(p.From.Reg), obj.REG_NONE, 0 inss = []*instruction{insAUIPC, ins} + + default: + p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p) + return nil } case p.From.Type == obj.TYPE_ADDR && p.To.Type == obj.TYPE_REG: // MOV $sym+off(SP/SB), R - + if p.As != AMOV { + p.Ctxt.Diag("%v: unsupported address load", p) + return nil + } switch p.From.Name { case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE: inss = instructionsForOpImmediate(p, AADDI, addrToReg(p.From)) @@ -1861,15 +1839,19 @@ func instructionsForMOV(p *obj.Prog) []*instruction { insAUIPC := &instruction{as: AAUIPC, rd: ins.rd} ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, ins.rd, obj.REG_NONE, 0 inss = []*instruction{insAUIPC, ins} - } - default: - // If we get here with a MOV pseudo-instruction it is going to - // remain unhandled. For now we trust rewriteMOV to catch these. - switch p.As { - case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD: + default: + p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p) return nil } + + case p.From.Type == obj.TYPE_ADDR && p.To.Type != obj.TYPE_REG: + p.Ctxt.Diag("%v: address load must target register", p) + return nil + + default: + p.Ctxt.Diag("%v: unsupported MOV", p) + return nil } return inss -- GitLab From f030043e37c4038e8a169feaf814ccbe3ae55cda Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Mon, 23 Aug 2021 21:32:30 +1000 Subject: [PATCH 1039/2500] cmd/internal/obj/riscv: simplify machine code output Use cursym.WriteInt rather than building up a slice of bytes and then writing them out via PutUint32. This also allows for variable instruction sizes, which will be needed when support for compressed (2 byte length) instructions is added. Change-Id: I17c9ffa52d27c91a24e161317e3db28e224804ae Reviewed-on: https://go-review.googlesource.com/c/go/+/344460 Trust: Joel Sing Reviewed-by: Cherry Mui --- src/cmd/internal/obj/riscv/obj.go | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index fd5026f25b..b1a1831966 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -2019,7 +2019,6 @@ func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ctxt.Retpoline = false // don't keep printing } - var symcode []uint32 for p := cursym.Func().Text; p != nil; p = p.Link { switch p.As { case AJALR: @@ -2074,23 +2073,17 @@ func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { rel.Type = rt } + offset := p.Pc for _, ins := range instructionsForProg(p) { - ic, err := ins.encode() - if err != nil { - break + if ic, err := ins.encode(); err == nil { + cursym.WriteInt(ctxt, offset, ins.length(), int64(ic)) + offset += int64(ins.length()) } if ins.usesRegTmp() { p.Mark |= USES_REG_TMP } - symcode = append(symcode, ic) } } - cursym.Size = int64(4 * len(symcode)) - - cursym.Grow(cursym.Size) - for p, i := cursym.P, 0; i < len(symcode); p, i = p[4:], i+1 { - ctxt.Arch.ByteOrder.PutUint32(p, symcode[i]) - } obj.MarkUnsafePoints(ctxt, cursym.Func().Text, newprog, isUnsafePoint, nil) } -- GitLab From c50d811c7aa0de05e8c4b73c218ffb13f92b8573 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Wed, 25 Aug 2021 20:08:37 +1000 Subject: [PATCH 1040/2500] cmd/interna/obj/riscv: use obj.REG_NONE rather than 0 No functional change, but makes the code consistent and more readable. Change-Id: I33db681fe0ed501842755f27b6e7843cdc8877cd Reviewed-on: https://go-review.googlesource.com/c/go/+/345049 Trust: Joel Sing Trust: Meng Zhuo Reviewed-by: Cherry Mui Reviewed-by: Meng Zhuo --- src/cmd/internal/obj/riscv/obj.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index b1a1831966..c5e68fedec 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -51,7 +51,7 @@ func jalrToSym(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, lr int16) *ob p.Mark |= NEED_PCREL_ITYPE_RELOC p.SetFrom3(obj.Addr{Type: obj.TYPE_CONST, Offset: to.Offset, Sym: to.Sym}) p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: 0} - p.Reg = 0 + p.Reg = obj.REG_NONE p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP} p = obj.Appendp(p, newprog) @@ -59,7 +59,7 @@ func jalrToSym(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, lr int16) *ob p.As = AJALR p.From.Type = obj.TYPE_REG p.From.Reg = lr - p.Reg = 0 + p.Reg = obj.REG_NONE p.To.Type = obj.TYPE_REG p.To.Reg = REG_TMP p.To.Sym = to.Sym @@ -72,7 +72,7 @@ func jalrToSym(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, lr int16) *ob func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { // Expand binary instructions to ternary ones. - if p.Reg == 0 { + if p.Reg == obj.REG_NONE { switch p.As { case AADDI, ASLTI, ASLTIU, AANDI, AORI, AXORI, ASLLI, ASRLI, ASRAI, AADD, AAND, AOR, AXOR, ASLL, ASRL, ASUB, ASRA, @@ -154,7 +154,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { case AMOV: // Put >32-bit constants in memory and load them. - if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE && p.From.Reg == 0 && int64(int32(p.From.Offset)) != p.From.Offset { + if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE && p.From.Reg == obj.REG_NONE && int64(int32(p.From.Offset)) != p.From.Offset { p.From.Type = obj.TYPE_MEM p.From.Sym = ctxt.Int64Sym(p.From.Offset) p.From.Name = obj.NAME_EXTERN @@ -449,7 +449,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ldpanic.As = AMOV ldpanic.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REGG, Offset: 4 * int64(ctxt.Arch.PtrSize)} // G.panic - ldpanic.Reg = 0 + ldpanic.Reg = obj.REG_NONE ldpanic.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X11} bneadj := obj.Appendp(ldpanic, newprog) @@ -469,7 +469,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { getargp := obj.Appendp(last, newprog) getargp.As = AMOV getargp.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_X11, Offset: 0} // Panic.argp - getargp.Reg = 0 + getargp.Reg = obj.REG_NONE getargp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X12} bneadj.To.SetTarget(getargp) @@ -496,7 +496,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { setargp := obj.Appendp(adjargp, newprog) setargp.As = AMOV setargp.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X12} - setargp.Reg = 0 + setargp.Reg = obj.REG_NONE setargp.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_X11, Offset: 0} // Panic.argp godone := obj.Appendp(setargp, newprog) @@ -570,7 +570,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { } else { p.As = AJALR p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO} - p.Reg = 0 + p.Reg = obj.REG_NONE p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR} } @@ -658,7 +658,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { p.As = AAUIPC p.From = obj.Addr{Type: obj.TYPE_BRANCH, Sym: p.From.Sym} p.From.SetTarget(p.To.Target()) - p.Reg = 0 + p.Reg = obj.REG_NONE p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP} rescan = true -- GitLab From 50c69cc3a9dfe4f268eebcf3dcbf7f3a93635842 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Thu, 26 Aug 2021 01:15:23 +1000 Subject: [PATCH 1041/2500] cmd/link/internal/riscv64,cmd/internal/obj/riscv: make error messages consistent Be consistent with both style/wording and formatting of error messages. Change-Id: I23013d904333a67a8f17dd364bb5015f54f419c0 Reviewed-on: https://go-review.googlesource.com/c/go/+/345050 Trust: Joel Sing Reviewed-by: Cherry Mui --- src/cmd/internal/obj/riscv/obj.go | 16 ++++++++-------- src/cmd/link/internal/riscv64/asm.go | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index c5e68fedec..fafde64062 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -830,10 +830,10 @@ func signExtend(val int64, bit uint) int64 { // generate a full 32-bit constant. func Split32BitImmediate(imm int64) (low, high int64, err error) { if !immIFits(imm, 32) { - return 0, 0, fmt.Errorf("immediate does not fit in 32-bits: %d", imm) + return 0, 0, fmt.Errorf("immediate does not fit in 32 bits: %d", imm) } - // Nothing special needs to be done if the immediate fits in 12-bits. + // Nothing special needs to be done if the immediate fits in 12 bits. if immIFits(imm, 12) { return imm, 0, nil } @@ -906,14 +906,14 @@ func immIFits(x int64, nbits uint) bool { // immI extracts the signed integer of the specified size from an immediate. func immI(as obj.As, imm int64, nbits uint) uint32 { if !immIFits(imm, nbits) { - panic(fmt.Sprintf("%v\tsigned immediate %d cannot fit in %d bits", as, imm, nbits)) + panic(fmt.Sprintf("%v: signed immediate %d cannot fit in %d bits", as, imm, nbits)) } return uint32(imm) } func wantImmI(ctxt *obj.Link, as obj.As, imm int64, nbits uint) { if !immIFits(imm, nbits) { - ctxt.Diag("%v\tsigned immediate cannot be larger than %d bits but got %d", as, nbits, imm) + ctxt.Diag("%v: signed immediate %d cannot be larger than %d bits", as, imm, nbits) } } @@ -923,13 +923,13 @@ func wantReg(ctxt *obj.Link, as obj.As, pos string, descr string, r, min, max ui if r != obj.REG_NONE { suffix = fmt.Sprintf(" but got non-%s register %s", descr, RegName(int(r))) } - ctxt.Diag("%v\texpected %s register in %s position%s", as, descr, pos, suffix) + ctxt.Diag("%v: expected %s register in %s position%s", as, descr, pos, suffix) } } func wantNoneReg(ctxt *obj.Link, as obj.As, pos string, r uint32) { if r != obj.REG_NONE { - ctxt.Diag("%v\texpected no register in %s but got register %s", as, pos, RegName(int(r))) + ctxt.Diag("%v: expected no register in %s but got register %s", as, pos, RegName(int(r))) } } @@ -946,7 +946,7 @@ func wantFloatReg(ctxt *obj.Link, as obj.As, pos string, r uint32) { // wantEvenOffset checks that the offset is a multiple of two. func wantEvenOffset(ctxt *obj.Link, as obj.As, offset int64) { if offset%1 != 0 { - ctxt.Diag("%v\tjump offset %v must be even", as, offset) + ctxt.Diag("%v: jump offset %d must be a multiple of two", as, offset) } } @@ -1061,7 +1061,7 @@ func validateRaw(ctxt *obj.Link, ins *instruction) { // Treat the raw value specially as a 32-bit unsigned integer. // Nobody wants to enter negative machine code. if ins.imm < 0 || 1<<32 <= ins.imm { - ctxt.Diag("%v\timmediate in raw position cannot be larger than 32 bits but got %d", ins.as, ins.imm) + ctxt.Diag("%v: immediate %d in raw position cannot be larger than 32 bits", ins.as, ins.imm) } } diff --git a/src/cmd/link/internal/riscv64/asm.go b/src/cmd/link/internal/riscv64/asm.go index 6eace617dc..57a3c34836 100644 --- a/src/cmd/link/internal/riscv64/asm.go +++ b/src/cmd/link/internal/riscv64/asm.go @@ -192,7 +192,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade // Generate AUIPC and second instruction immediates. low, high, err := riscv.Split32BitImmediate(off) if err != nil { - ldr.Errorf(s, "R_RISCV_PCREL_ relocation does not fit in 32-bits: %d", off) + ldr.Errorf(s, "R_RISCV_PCREL_ relocation does not fit in 32 bits: %d", off) } auipcImm, err := riscv.EncodeUImmediate(high) -- GitLab From 9295723079f21d5ff6282e8bd59fd3175341ebc2 Mon Sep 17 00:00:00 2001 From: "Paul E. Murphy" Date: Tue, 23 Mar 2021 15:52:49 -0500 Subject: [PATCH 1042/2500] cmd/link: rework .TOC. handling for ppc64le Setup .TOC. to point to the same place for all objects. Today, the linker assumes all call relocations can use the local function entry point of imported object files. This requires a consistent pointer across all objects. This intentionally computes the .TOC. pointer in all linking configurations. In some cases the .TOC. is not used today (e.g linking position-dependent go only code). It is harmless and simple to compute in all cases, so just do it for easier maintenance. Notably, .TOC. is used in some cases when static linking is requested on ppc64le/linux: * Position-independent C code using a PC-rel relocation against .TOC.. cgo generated C object files are usually compiled PIC even if the go binary itself is not. * Anything which causes PLT stub generation. The stubs always generate a .TOC. relative relocation. * The race detector. Today, this links in an externally compiled archive which contains position-independent object files. Similarly, position-independent linking is always punted to the external linker on ppc64 today. Updates #21961 Fixes #15409 Change-Id: Ifd8294b9249e16ba8b92eaf876d15d162f9c61fd Reviewed-on: https://go-review.googlesource.com/c/go/+/304458 Reviewed-by: Cherry Mui Trust: Lynn Boger --- src/cmd/link/internal/ld/data.go | 34 +++++++++++++++++------------ src/cmd/link/internal/ld/lib.go | 11 ++-------- src/cmd/link/internal/sym/symbol.go | 1 + 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index e0591c3959..43a0e06e90 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -1710,21 +1710,9 @@ func (state *dodataState) allocateDataSections(ctxt *Link) { } ldr := ctxt.loader - // .got (and .toc on ppc64) + // .got if len(state.data[sym.SELFGOT]) > 0 { - sect := state.allocateNamedSectionAndAssignSyms(&Segdata, ".got", sym.SELFGOT, sym.SDATA, 06) - if ctxt.IsPPC64() { - for _, s := range state.data[sym.SELFGOT] { - // Resolve .TOC. symbol for this object file (ppc64) - - toc := ldr.Lookup(".TOC.", int(ldr.SymVersion(s))) - if toc != 0 { - ldr.SetSymSect(toc, sect) - ldr.AddInteriorSym(s, toc) - ldr.SetSymValue(toc, 0x8000) - } - } - } + state.allocateNamedSectionAndAssignSyms(&Segdata, ".got", sym.SELFGOT, sym.SDATA, 06) } /* pointer-free data */ @@ -2690,6 +2678,24 @@ func (ctxt *Link) address() []*sym.Segment { ldr.SetSymSect(ldr.Lookup("_end", 0), ldr.SymSect(end)) } + if ctxt.IsPPC64() && ctxt.IsElf() { + // Resolve .TOC. symbols for all objects. Only one TOC region is supported. If a + // GOT section is present, compute it as suggested by the ELFv2 ABI. Otherwise, + // choose a similar offset from the start of the data segment. + tocAddr := int64(Segdata.Vaddr) + 0x8000 + if gotAddr := ldr.SymValue(ctxt.GOT); gotAddr != 0 { + tocAddr = gotAddr + 0x8000 + } + for i, _ := range ctxt.DotTOC { + if i >= sym.SymVerABICount && i < sym.SymVerStatic { // these versions are not used currently + continue + } + if toc := ldr.Lookup(".TOC.", i); toc != 0 { + ldr.SetSymValue(toc, tocAddr) + } + } + } + return order } diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 494fea5e72..cf70374b16 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -149,16 +149,9 @@ func (ctxt *Link) setArchSyms() { if ctxt.IsPPC64() { ctxt.mkArchSym("TOC", 0, &ctxt.TOC) - // NB: note the +2 below for DotTOC2 compared to the +1 for - // DocTOC. This is because loadlibfull() creates an additional - // syms version during conversion of loader.Sym symbols to - // *sym.Symbol symbols. Symbols that are assigned this final - // version are not going to have TOC references, so it should - // be ok for them to inherit an invalid .TOC. symbol. - // TODO: revisit the +2, now that loadlibfull is gone. - ctxt.DotTOC = make([]loader.Sym, ctxt.MaxVersion()+2) + ctxt.DotTOC = make([]loader.Sym, ctxt.MaxVersion()+1) for i := 0; i <= ctxt.MaxVersion(); i++ { - if i >= 2 && i < sym.SymVerStatic { // these versions are not used currently + if i >= sym.SymVerABICount && i < sym.SymVerStatic { // these versions are not used currently continue } ctxt.mkArchSymVec(".TOC.", i, ctxt.DotTOC) diff --git a/src/cmd/link/internal/sym/symbol.go b/src/cmd/link/internal/sym/symbol.go index 70cf36a87e..4687aa53bb 100644 --- a/src/cmd/link/internal/sym/symbol.go +++ b/src/cmd/link/internal/sym/symbol.go @@ -11,6 +11,7 @@ import ( const ( SymVerABI0 = 0 SymVerABIInternal = 1 + SymVerABICount = 2 // Number of internal ABIs SymVerStatic = 10 // Minimum version used by static (file-local) syms ) -- GitLab From 64bdad2011c7450d5f7dd90f992acb057a25a5c2 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Wed, 8 Sep 2021 09:58:45 -0400 Subject: [PATCH 1043/2500] all: update vendored golang.org/x/tools Now that issue #48124 is resolved, ran the following commands inside the cmd module: go get -d golang.org/x/tools@36045662144327e4475f9d356f49ab32ce730049 # main branch go mod tidy go mod vendor For #36905. Updates #48124. Change-Id: I9dc736c2c5256f7d9e80fd9c52c6725ecf0b8001 Reviewed-on: https://go-review.googlesource.com/c/go/+/348409 Trust: Dmitri Shuralyov Trust: Alexander Rakoczy Run-TryBot: Dmitri Shuralyov TryBot-Result: Go Bot Reviewed-by: Alexander Rakoczy --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 +-- .../tools/go/analysis/passes/printf/printf.go | 7 ++-- .../testinggoroutine/testinggoroutine.go | 30 +++++++++++++++-- .../x/tools/internal/typeparams/typeparams.go | 33 +++++++++++++++---- src/cmd/vendor/modules.txt | 2 +- 6 files changed, 60 insertions(+), 18 deletions(-) diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 4e0fa0bd74..c7b3b02c3b 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -10,6 +10,6 @@ require ( golang.org/x/mod v0.5.1-0.20210830214625-1b1db11ec8f4 golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e // indirect golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b - golang.org/x/tools v0.1.6-0.20210809225032-337cebd2c151 + golang.org/x/tools v0.1.6-0.20210904010709-360456621443 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index dab06fdf7d..987c236b02 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -16,7 +16,7 @@ golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e h1:XMgFehsDnnLGtjvjOfqWSUzt0 golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/tools v0.1.6-0.20210809225032-337cebd2c151 h1:jHjT6WuVKEMzjJgrS1+r1wk54oxwqumUnvtn0QZXyXE= -golang.org/x/tools v0.1.6-0.20210809225032-337cebd2c151/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.6-0.20210904010709-360456621443 h1:7JswviZfk9Rtd4NOelZtuLUdkHdruludwWkfOE6sdZk= +golang.org/x/tools v0.1.6-0.20210904010709-360456621443/go.mod h1:YD9qOF0M9xpSpdWTBbzEl5e/RnCefISl8E5Noe10jFM= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go index 6589478af0..de0369a428 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go @@ -490,7 +490,7 @@ func printfNameAndKind(pass *analysis.Pass, call *ast.CallExpr) (fn *types.Func, _, ok = isPrint[strings.ToLower(fn.Name())] } if ok { - if fn.Name() == "Errorf" { + if fn.FullName() == "fmt.Errorf" { kind = KindErrorf } else if strings.HasSuffix(fn.Name(), "f") { kind = KindPrintf @@ -590,12 +590,9 @@ func checkPrintf(pass *analysis.Pass, kind Kind, call *ast.CallExpr, fn *types.F } if state.verb == 'w' { switch kind { - case KindNone, KindPrint: + case KindNone, KindPrint, KindPrintf: pass.Reportf(call.Pos(), "%s does not support error-wrapping directive %%w", state.name) return - case KindPrintf: - pass.Reportf(call.Pos(), "%s call has error-wrapping directive %%w, which is only supported for functions backed by fmt.Errorf", state.name) - return } if anyW { pass.Reportf(call.Pos(), "%s call has more than one error-wrapping directive %%w", state.name) diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine/testinggoroutine.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine/testinggoroutine.go index d2b9a5640d..ce05a56cca 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine/testinggoroutine.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine/testinggoroutine.go @@ -119,11 +119,33 @@ func typeIsTestingDotTOrB(expr ast.Expr) (string, bool) { return varTypeName, ok } +// goStmtFunc returns the ast.Node of a call expression +// that was invoked as a go statement. Currently, only +// function literals declared in the same function, and +// static calls within the same package are supported. +func goStmtFun(goStmt *ast.GoStmt) ast.Node { + switch goStmt.Call.Fun.(type) { + case *ast.Ident: + id := goStmt.Call.Fun.(*ast.Ident) + // TODO(cuonglm): improve this once golang/go#48141 resolved. + if id.Obj == nil { + break + } + if funDecl, ok := id.Obj.Decl.(ast.Node); ok { + return funDecl + } + case *ast.FuncLit: + return goStmt.Call.Fun + } + return goStmt.Call +} + // checkGoStmt traverses the goroutine and checks for the // use of the forbidden *testing.(B, T) methods. func checkGoStmt(pass *analysis.Pass, goStmt *ast.GoStmt) { + fn := goStmtFun(goStmt) // Otherwise examine the goroutine to check for the forbidden methods. - ast.Inspect(goStmt, func(n ast.Node) bool { + ast.Inspect(fn, func(n ast.Node) bool { selExpr, ok := n.(*ast.SelectorExpr) if !ok { return true @@ -147,7 +169,11 @@ func checkGoStmt(pass *analysis.Pass, goStmt *ast.GoStmt) { return true } if typeName, ok := typeIsTestingDotTOrB(field.Type); ok { - pass.ReportRangef(selExpr, "call to (*%s).%s from a non-test goroutine", typeName, selExpr.Sel) + var fnRange analysis.Range = goStmt + if _, ok := fn.(*ast.FuncLit); ok { + fnRange = selExpr + } + pass.ReportRangef(fnRange, "call to (*%s).%s from a non-test goroutine", typeName, selExpr.Sel) } return true }) diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams.go index be6b0525f6..d459b32cb3 100644 --- a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams.go +++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams.go @@ -78,20 +78,31 @@ func ForNamed(named *types.Named) []*types.TypeName { return tparamsSlice(named.TParams()) } -func tparamsSlice(tparams *types.TypeParams) []*types.TypeName { - if tparams.Len() == 0 { +func tparamsSlice(tparams *types.TParamList) []*types.TypeName { + length := tparams.Len() + if length == 0 { return nil } - result := make([]*types.TypeName, tparams.Len()) - for i := 0; i < tparams.Len(); i++ { - result[i] = tparams.At(i) + + result := make([]*types.TypeName, length) + for i := 0; i < length; i++ { + result[i] = tparams.At(i).Obj() } + return result } // NamedTArgs extracts the (possibly empty) type argument list from named. func NamedTArgs(named *types.Named) []types.Type { - return named.TArgs() + targs := named.TArgs() + numArgs := targs.Len() + + typs := make([]types.Type, numArgs) + for i := 0; i < numArgs; i++ { + typs[i] = targs.At(i) + } + + return typs } // InitInferred initializes info to record inferred type information. @@ -111,5 +122,13 @@ func GetInferred(info *types.Info, e ast.Expr) ([]types.Type, *types.Signature) return nil, nil } inf := info.Inferred[e] - return inf.TArgs, inf.Sig + + length := inf.TArgs.Len() + + typs := make([]types.Type, length) + for i := 0; i < length; i++ { + typs[i] = inf.TArgs.At(i) + } + + return typs, inf.Sig } diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index ec75599d09..8a6497b5f2 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -48,7 +48,7 @@ golang.org/x/sys/windows # golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b ## explicit; go 1.17 golang.org/x/term -# golang.org/x/tools v0.1.6-0.20210809225032-337cebd2c151 +# golang.org/x/tools v0.1.6-0.20210904010709-360456621443 ## explicit; go 1.17 golang.org/x/tools/cover golang.org/x/tools/go/analysis -- GitLab From fdc2072420d28b761e30dd02e7ed6118cda33f4f Mon Sep 17 00:00:00 2001 From: Michael Munday Date: Wed, 8 Sep 2021 13:57:07 +0000 Subject: [PATCH 1044/2500] test/codegen: remove broken riscv64 test This test is not executed by default (see #48247) and does not actually pass. It was added in CL 346689. The code generation changes made in that CL only change how instructions are assembled, they do not actually affect the output of the compiler. This test is unfortunately therefore invalid and will never pass. Updates #48247. Change-Id: I0c807e4a111336e5a097fe4e3af2805f9932a87f Reviewed-on: https://go-review.googlesource.com/c/go/+/348390 Trust: Michael Munday Run-TryBot: Michael Munday Reviewed-by: Cherry Mui TryBot-Result: Go Bot --- test/codegen/arithmetic.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/test/codegen/arithmetic.go b/test/codegen/arithmetic.go index 754c5c9bc9..eb95416b6a 100644 --- a/test/codegen/arithmetic.go +++ b/test/codegen/arithmetic.go @@ -575,11 +575,3 @@ func constantFold3(i, j int) int { r := (5 * i) * (6 * j) return r } - -func addConst(i int64) (int64, int64) { - // riscv64:`ADDI`,-`LUI` - a := i + 3001 - // riscv64:`LUI`,`ADDIW` - b := i + 5009 - return a, b -} -- GitLab From 1da64686f85da38af13c4ee186f261343455c697 Mon Sep 17 00:00:00 2001 From: Michael Munday Date: Wed, 8 Sep 2021 14:07:12 +0000 Subject: [PATCH 1045/2500] test/codegen: fix compilation of bitfield tests The codegen tests are currently skipped (see #48247) and the bitfield tests do not actually compile due to a duplicate function name (sbfiz5) added in CL 267602. Renaming the function fixes the issue. Updates #48247. Change-Id: I626fd5ef13732dc358e73ace9ddcc4cbb6ae5b21 Reviewed-on: https://go-review.googlesource.com/c/go/+/348391 Trust: Michael Munday Run-TryBot: Michael Munday TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- test/codegen/bitfield.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/codegen/bitfield.go b/test/codegen/bitfield.go index d4ffbad85d..3ed9cfe603 100644 --- a/test/codegen/bitfield.go +++ b/test/codegen/bitfield.go @@ -99,10 +99,6 @@ func sbfiz5(x int32) int32 { return (x << 4) >> 3 } -func sbfiz5(x int32) int64 { - return int64(x+1) << 40 // arm64:"SBFIZ\t[$]40, R[0-9]+, [$]24",-"LSL" -} - func sbfiz6(x int16) int64 { return int64(x+1) << 3 // arm64:"SBFIZ\t[$]3, R[0-9]+, [$]16",-"LSL" } @@ -111,6 +107,10 @@ func sbfiz7(x int8) int64 { return int64(x+1) << 62 // arm64:"SBFIZ\t[$]62, R[0-9]+, [$]2",-"LSL" } +func sbfiz8(x int32) int64 { + return int64(x+1) << 40 // arm64:"SBFIZ\t[$]40, R[0-9]+, [$]24",-"LSL" +} + // sbfx func sbfx1(x int64) int64 { return (x << 3) >> 4 // arm64:"SBFX\t[$]1, R[0-9]+, [$]60",-"LSL",-"ASR" -- GitLab From 8214257347b16a03464ace16bbcf6346fc784a3e Mon Sep 17 00:00:00 2001 From: Michael Munday Date: Wed, 8 Sep 2021 14:14:53 +0000 Subject: [PATCH 1046/2500] test/codegen: fix package name for test case The codegen tests are currently skipped (see #48247). The test added in CL 346050 did not compile because it was in the main package but did not contain a main function. Changing the package to 'codegen' fixes the issue. Updates #48247. Change-Id: I0a0eaca8e6a7d7b335606d2c76a204ac0c12e6d5 Reviewed-on: https://go-review.googlesource.com/c/go/+/348392 Trust: Michael Munday Run-TryBot: Michael Munday Reviewed-by: Cherry Mui TryBot-Result: Go Bot --- test/codegen/issue48054.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/codegen/issue48054.go b/test/codegen/issue48054.go index 6ef37e9452..1f3a041044 100644 --- a/test/codegen/issue48054.go +++ b/test/codegen/issue48054.go @@ -4,7 +4,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package main +package codegen func a(n string) bool { // arm64:"CBZ" -- GitLab From 9581d891ab8c88bbf9e5b5142926fbca653551e6 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Wed, 8 Sep 2021 10:51:06 -0400 Subject: [PATCH 1047/2500] cmd/pprof: update vendored github.com/google/pprof Pull in the latest published version of github.com/google/pprof that is available at this time in the Go 1.18 development cycle. Done with: go get -d github.com/google/pprof@latest go mod tidy go mod vendor For #36905. Change-Id: Ib25aa38365ec70a0bed2a8a6527e5823ab9f9ded Reviewed-on: https://go-review.googlesource.com/c/go/+/348410 Trust: Dmitri Shuralyov Run-TryBot: Dmitri Shuralyov TryBot-Result: Go Bot Reviewed-by: Michael Pratt --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 +- .../internal/binutils/addr2liner_llvm.go | 2 +- .../pprof/internal/binutils/binutils.go | 97 +++++++++---------- .../google/pprof/internal/driver/webhtml.go | 10 ++ .../google/pprof/internal/driver/webui.go | 5 + .../google/pprof/internal/elfexec/elfexec.go | 96 ++++++++++-------- .../google/pprof/internal/report/report.go | 9 ++ .../google/pprof/internal/report/source.go | 9 +- src/cmd/vendor/modules.txt | 2 +- 10 files changed, 134 insertions(+), 102 deletions(-) diff --git a/src/cmd/go.mod b/src/cmd/go.mod index c7b3b02c3b..05a118d812 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -3,7 +3,7 @@ module cmd go 1.18 require ( - github.com/google/pprof v0.0.0-20210506205249-923b5ab0fc1a + github.com/google/pprof v0.0.0-20210827144239-02619b876842 github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 // indirect golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1 golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 987c236b02..eebb44c053 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -1,8 +1,8 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/google/pprof v0.0.0-20210506205249-923b5ab0fc1a h1:jmAp/2PZAScNd62lTD3Mcb0Ey9FvIIJtLohPhtxZJ+Q= -github.com/google/pprof v0.0.0-20210506205249-923b5ab0fc1a/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210827144239-02619b876842 h1:JCrt5MIE1fHQtdy1825HwJ45oVQaqHE6lgssRhjcg/o= +github.com/google/pprof v0.0.0-20210827144239-02619b876842/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 h1:mV02weKRL81bEnm8A0HT1/CAelMQDBuQIfLw8n+d6xI= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1 h1:MwxAfiDvuwX8Nnnc6iRDhzyMyyc2tz5tYyCP/pZcPCg= diff --git a/src/cmd/vendor/github.com/google/pprof/internal/binutils/addr2liner_llvm.go b/src/cmd/vendor/github.com/google/pprof/internal/binutils/addr2liner_llvm.go index 24c48e649b..844c7a475d 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/binutils/addr2liner_llvm.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/binutils/addr2liner_llvm.go @@ -76,7 +76,7 @@ func newLLVMSymbolizer(cmd, file string, base uint64, isData bool) (*llvmSymboli } j := &llvmSymbolizerJob{ - cmd: exec.Command(cmd, "-inlining", "-demangle=false"), + cmd: exec.Command(cmd, "--inlining", "-demangle=false"), symType: "CODE", } if isData { diff --git a/src/cmd/vendor/github.com/google/pprof/internal/binutils/binutils.go b/src/cmd/vendor/github.com/google/pprof/internal/binutils/binutils.go index 5ed8a1f9f1..e920eeb2fa 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/binutils/binutils.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/binutils/binutils.go @@ -525,6 +525,47 @@ type elfMapping struct { stextOffset *uint64 } +// findProgramHeader returns the program segment that matches the current +// mapping and the given address, or an error if it cannot find a unique program +// header. +func (m *elfMapping) findProgramHeader(ef *elf.File, addr uint64) (*elf.ProgHeader, error) { + // For user space executables, we try to find the actual program segment that + // is associated with the given mapping. Skip this search if limit <= start. + // We cannot use just a check on the start address of the mapping to tell if + // it's a kernel / .ko module mapping, because with quipper address remapping + // enabled, the address would be in the lower half of the address space. + + if m.stextOffset != nil || m.start >= m.limit || m.limit >= (uint64(1)<<63) { + // For the kernel, find the program segment that includes the .text section. + return elfexec.FindTextProgHeader(ef), nil + } + + // Fetch all the loadable segments. + var phdrs []elf.ProgHeader + for i := range ef.Progs { + if ef.Progs[i].Type == elf.PT_LOAD { + phdrs = append(phdrs, ef.Progs[i].ProgHeader) + } + } + // Some ELF files don't contain any loadable program segments, e.g. .ko + // kernel modules. It's not an error to have no header in such cases. + if len(phdrs) == 0 { + return nil, nil + } + // Get all program headers associated with the mapping. + headers := elfexec.ProgramHeadersForMapping(phdrs, m.offset, m.limit-m.start) + if len(headers) == 0 { + return nil, errors.New("no program header matches mapping info") + } + if len(headers) == 1 { + return headers[0], nil + } + + // Use the file offset corresponding to the address to symbolize, to narrow + // down the header. + return elfexec.HeaderForFileOffset(headers, addr-m.start+m.offset) +} + // file implements the binutils.ObjFile interface. type file struct { b *binrep @@ -555,27 +596,9 @@ func (f *file) computeBase(addr uint64) error { } defer ef.Close() - var ph *elf.ProgHeader - // For user space executables, find the actual program segment that is - // associated with the given mapping. Skip this search if limit <= start. - // We cannot use just a check on the start address of the mapping to tell if - // it's a kernel / .ko module mapping, because with quipper address remapping - // enabled, the address would be in the lower half of the address space. - if f.m.stextOffset == nil && f.m.start < f.m.limit && f.m.limit < (uint64(1)<<63) { - // Get all program headers associated with the mapping. - headers, hasLoadables := elfexec.ProgramHeadersForMapping(ef, f.m.offset, f.m.limit-f.m.start) - - // Some ELF files don't contain any loadable program segments, e.g. .ko - // kernel modules. It's not an error to have no header in such cases. - if hasLoadables { - ph, err = matchUniqueHeader(headers, addr-f.m.start+f.m.offset) - if err != nil { - return fmt.Errorf("failed to find program header for file %q, ELF mapping %#v, address %x: %v", f.name, *f.m, addr, err) - } - } - } else { - // For the kernel, find the program segment that includes the .text section. - ph = elfexec.FindTextProgHeader(ef) + ph, err := f.m.findProgramHeader(ef, addr) + if err != nil { + return fmt.Errorf("failed to find program header for file %q, ELF mapping %#v, address %x: %v", f.name, *f.m, addr, err) } base, err := elfexec.GetBase(&ef.FileHeader, ph, f.m.stextOffset, f.m.start, f.m.limit, f.m.offset) @@ -587,38 +610,6 @@ func (f *file) computeBase(addr uint64) error { return nil } -// matchUniqueHeader attempts to identify a unique header from the given list, -// using the given file offset to disambiguate between multiple segments. It -// returns an error if the header list is empty or if it cannot identify a -// unique header. -func matchUniqueHeader(headers []*elf.ProgHeader, fileOffset uint64) (*elf.ProgHeader, error) { - if len(headers) == 0 { - return nil, errors.New("no program header matches mapping info") - } - if len(headers) == 1 { - // Don't use the file offset if we already have a single header. - return headers[0], nil - } - // We have multiple input segments. Attempt to identify a unique one - // based on the given file offset. - var ph *elf.ProgHeader - for _, h := range headers { - if fileOffset >= h.Off && fileOffset < h.Off+h.Memsz { - if ph != nil { - // Assuming no other bugs, this can only happen if we have two or - // more small program segments that fit on the same page, and a - // segment other than the last one includes uninitialized data. - return nil, fmt.Errorf("found second program header (%#v) that matches file offset %x, first program header is %#v. Does first program segment contain uninitialized data?", *h, fileOffset, *ph) - } - ph = h - } - } - if ph == nil { - return nil, fmt.Errorf("no program header matches file offset %x", fileOffset) - } - return ph, nil -} - func (f *file) Name() string { return f.name } diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/webhtml.go b/src/cmd/vendor/github.com/google/pprof/internal/driver/webhtml.go index b8e8b50b94..b9c73271b8 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/driver/webhtml.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/webhtml.go @@ -132,6 +132,10 @@ a { align-items: center; justify-content: center; } +.menu-name a { + text-decoration: none; + color: #212121; +} .submenu { display: none; z-index: 1; @@ -370,6 +374,12 @@ table tr td { +

+
diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/webui.go b/src/cmd/vendor/github.com/google/pprof/internal/driver/webui.go index 52dc68809c..0f3e8bf93c 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/driver/webui.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/webui.go @@ -127,6 +127,11 @@ func serveWebInterface(hostport string, p *profile.Profile, o *plugin.Options, d "/flamegraph": http.HandlerFunc(ui.flamegraph), "/saveconfig": http.HandlerFunc(ui.saveConfig), "/deleteconfig": http.HandlerFunc(ui.deleteConfig), + "/download": http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + w.Header().Set("Content-Type", "application/vnd.google.protobuf+gzip") + w.Header().Set("Content-Disposition", "attachment;filename=profile.pb.gz") + p.Write(w) + }), }, } diff --git a/src/cmd/vendor/github.com/google/pprof/internal/elfexec/elfexec.go b/src/cmd/vendor/github.com/google/pprof/internal/elfexec/elfexec.go index 2638b2db2d..4f11645185 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/elfexec/elfexec.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/elfexec/elfexec.go @@ -284,10 +284,16 @@ func FindTextProgHeader(f *elf.File) *elf.ProgHeader { return nil } -// ProgramHeadersForMapping returns the loadable program segment headers that -// are fully contained in the runtime mapping with file offset pgoff and memory -// size memsz, and if the binary includes any loadable segments. -func ProgramHeadersForMapping(f *elf.File, pgoff, memsz uint64) ([]*elf.ProgHeader, bool) { +// ProgramHeadersForMapping returns the program segment headers that overlap +// the runtime mapping with file offset mapOff and memory size mapSz. We skip +// over segments zero file size because their file offset values are unreliable. +// Even if overlapping, a segment is not selected if its aligned file offset is +// greater than the mapping file offset, or if the mapping includes the last +// page of the segment, but not the full segment and the mapping includes +// additional pages after the segment end. +// The function returns a slice of pointers to the headers in the input +// slice, which are valid only while phdrs is not modified or discarded. +func ProgramHeadersForMapping(phdrs []elf.ProgHeader, mapOff, mapSz uint64) []*elf.ProgHeader { const ( // pageSize defines the virtual memory page size used by the loader. This // value is dependent on the memory management unit of the CPU. The page @@ -298,57 +304,61 @@ func ProgramHeadersForMapping(f *elf.File, pgoff, memsz uint64) ([]*elf.ProgHead // specified in the ELF file header. pageSize = 4096 pageOffsetMask = pageSize - 1 - pageMask = ^uint64(pageOffsetMask) ) + mapLimit := mapOff + mapSz var headers []*elf.ProgHeader - hasLoadables := false - for _, p := range f.Progs { - // The segment must be fully included in the mapping. - if p.Type == elf.PT_LOAD && pgoff <= p.Off && p.Off+p.Memsz <= pgoff+memsz { - alignedOffset := uint64(0) + for i := range phdrs { + p := &phdrs[i] + // Skip over segments with zero file size. Their file offsets can have + // arbitrary values, see b/195427553. + if p.Filesz == 0 { + continue + } + segLimit := p.Off + p.Memsz + // The segment must overlap the mapping. + if p.Type == elf.PT_LOAD && mapOff < segLimit && p.Off < mapLimit { + // If the mapping offset is strictly less than the page aligned segment + // offset, then this mapping comes from a different segment, fixes + // b/179920361. + alignedSegOffset := uint64(0) if p.Off > (p.Vaddr & pageOffsetMask) { - alignedOffset = p.Off - (p.Vaddr & pageOffsetMask) + alignedSegOffset = p.Off - (p.Vaddr & pageOffsetMask) } - if alignedOffset <= pgoff { - headers = append(headers, &p.ProgHeader) + if mapOff < alignedSegOffset { + continue } + // If the mapping starts in the middle of the segment, it covers less than + // one page of the segment, and it extends at least one page past the + // segment, then this mapping comes from a different segment. + if mapOff > p.Off && (segLimit < mapOff+pageSize) && (mapLimit >= segLimit+pageSize) { + continue + } + headers = append(headers, p) } - if p.Type == elf.PT_LOAD { - hasLoadables = true - } - } - if len(headers) < 2 { - return headers, hasLoadables - } - - // If we have more than one matching segments, try a strict check on the - // segment memory size. We use a heuristic to compute the minimum mapping size - // required for a segment, assuming mappings are page aligned. - // The memory size based heuristic makes sense only if the mapping size is a - // multiple of page size. - if memsz%pageSize != 0 { - return headers, hasLoadables } + return headers +} - // Return all found headers if we cannot narrow the selection to a single - // program segment. +// HeaderForFileOffset attempts to identify a unique program header that +// includes the given file offset. It returns an error if it cannot identify a +// unique header. +func HeaderForFileOffset(headers []*elf.ProgHeader, fileOffset uint64) (*elf.ProgHeader, error) { var ph *elf.ProgHeader for _, h := range headers { - wantSize := (h.Vaddr+h.Memsz+pageSize-1)&pageMask - (h.Vaddr & pageMask) - if wantSize != memsz { - continue - } - if ph != nil { - // Found a second program header matching, so return all previously - // identified headers. - return headers, hasLoadables + if fileOffset >= h.Off && fileOffset < h.Off+h.Memsz { + if ph != nil { + // Assuming no other bugs, this can only happen if we have two or + // more small program segments that fit on the same page, and a + // segment other than the last one includes uninitialized data, or + // if the debug binary used for symbolization is stripped of some + // sections, so segment file sizes are smaller than memory sizes. + return nil, fmt.Errorf("found second program header (%#v) that matches file offset %x, first program header is %#v. Is this a stripped binary, or does the first program segment contain uninitialized data?", *h, fileOffset, *ph) + } + ph = h } - ph = h } if ph == nil { - // No matching header for the strict check. Return all previously identified - // headers. - return headers, hasLoadables + return nil, fmt.Errorf("no program header matches file offset %x", fileOffset) } - return []*elf.ProgHeader{ph}, hasLoadables + return ph, nil } diff --git a/src/cmd/vendor/github.com/google/pprof/internal/report/report.go b/src/cmd/vendor/github.com/google/pprof/internal/report/report.go index 4a86554880..e2fb00314c 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/report/report.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/report/report.go @@ -432,6 +432,10 @@ func PrintAssembly(w io.Writer, rpt *Report, obj plugin.ObjTool, maxFuncs int) e } } + if len(syms) == 0 { + return fmt.Errorf("no matches found for regexp: %s", o.Symbol) + } + // Correlate the symbols from the binary with the profile samples. for _, s := range syms { sns := symNodes[s] @@ -1054,6 +1058,7 @@ func printTree(w io.Writer, rpt *Report) error { var flatSum int64 rx := rpt.options.Symbol + matched := 0 for _, n := range g.Nodes { name, flat, cum := n.Info.PrintableName(), n.FlatValue(), n.CumValue() @@ -1061,6 +1066,7 @@ func printTree(w io.Writer, rpt *Report) error { if rx != nil && !rx.MatchString(name) { continue } + matched++ fmt.Fprintln(w, separator) // Print incoming edges. @@ -1098,6 +1104,9 @@ func printTree(w io.Writer, rpt *Report) error { if len(g.Nodes) > 0 { fmt.Fprintln(w, separator) } + if rx != nil && matched == 0 { + return fmt.Errorf("no matches found for regexp: %s", rx) + } return nil } diff --git a/src/cmd/vendor/github.com/google/pprof/internal/report/source.go b/src/cmd/vendor/github.com/google/pprof/internal/report/source.go index 54245e5f9e..33d04c591d 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/report/source.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/report/source.go @@ -58,6 +58,10 @@ func printSource(w io.Writer, rpt *Report) error { } functions.Sort(graph.NameOrder) + if len(functionNodes) == 0 { + return fmt.Errorf("no matches found for regexp: %s", o.Symbol) + } + sourcePath := o.SourcePath if sourcePath == "" { wd, err := os.Getwd() @@ -206,6 +210,9 @@ func PrintWebList(w io.Writer, rpt *Report, obj plugin.ObjTool, maxFiles int) er sourcePath = wd } sp := newSourcePrinter(rpt, obj, sourcePath) + if len(sp.interest) == 0 { + return fmt.Errorf("no matches found for regexp: %s", rpt.options.Symbol) + } sp.print(w, maxFiles, rpt) sp.close() return nil @@ -299,7 +306,7 @@ func newSourcePrinter(rpt *Report, obj plugin.ObjTool, sourcePath string) *sourc continue } - // Seach in inlined stack for a match. + // Search in inlined stack for a match. matchFile := (loc.Mapping != nil && sp.sym.MatchString(loc.Mapping.File)) for j, line := range loc.Line { if (j == 0 && matchFile) || matches(line) { diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 8a6497b5f2..966ba1358e 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -1,4 +1,4 @@ -# github.com/google/pprof v0.0.0-20210506205249-923b5ab0fc1a +# github.com/google/pprof v0.0.0-20210827144239-02619b876842 ## explicit; go 1.14 github.com/google/pprof/driver github.com/google/pprof/internal/binutils -- GitLab From 73a062c3e765aa953a84b128aa765a607b2df083 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 7 Sep 2021 13:58:49 -0700 Subject: [PATCH 1048/2500] cmd/compile/internal/types2: handle recursive type parameter constraints Check type constraints after the respective type parameter list has been associated with a parameterized type so that recursive type parameter constraints "see" a parameterized type. Fixes #45550. Fixes #47796. Change-Id: Iac74610ca017a78013820624230c857395506aff Reviewed-on: https://go-review.googlesource.com/c/go/+/348090 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/decl.go | 19 ++++++++--- src/cmd/compile/internal/types2/signature.go | 2 +- .../types2/testdata/fixedbugs/issue45550.go2 | 10 ++++++ .../types2/testdata/fixedbugs/issue47796.go2 | 33 +++++++++++++++++++ 4 files changed, 58 insertions(+), 6 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue45550.go2 create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue47796.go2 diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index b61d282b14..278ee76bfa 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -567,7 +567,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named if tdecl.TParamList != nil { check.openScope(tdecl, "type parameters") defer check.closeScope() - named.tparams = check.collectTypeParams(tdecl.TParamList) + check.collectTypeParams(&named.tparams, tdecl.TParamList) } // determine underlying type of named @@ -598,7 +598,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named } } -func (check *Checker) collectTypeParams(list []*syntax.Field) *TParamList { +func (check *Checker) collectTypeParams(dst **TParamList, list []*syntax.Field) { tparams := make([]*TypeParam, len(list)) // Declare type parameters up-front. @@ -608,6 +608,11 @@ func (check *Checker) collectTypeParams(list []*syntax.Field) *TParamList { tparams[i] = check.declareTypeParam(f.Name) } + // Set the type parameters before collecting the type constraints because + // the parameterized type may be used by the constraints (issue #47887). + // Example: type T[P T[P]] interface{} + *dst = bindTParams(tparams) + var bound Type for i, f := range list { // Optimization: Re-use the previous type bound if it hasn't changed. @@ -618,13 +623,17 @@ func (check *Checker) collectTypeParams(list []*syntax.Field) *TParamList { } tparams[i].bound = bound } - - return bindTParams(tparams) } func (check *Checker) declareTypeParam(name *syntax.Name) *TypeParam { + // Use Typ[Invalid] for the type constraint to ensure that a type + // is present even if the actual constraint has not been assigned + // yet. + // TODO(gri) Need to systematically review all uses of type parameter + // constraints to make sure we don't rely on them if they + // are not properly set yet. tname := NewTypeName(name.Pos(), check.pkg, name.Value, nil) - tpar := check.NewTypeParam(tname, nil) // assigns type to tname as a side-effect + tpar := check.NewTypeParam(tname, Typ[Invalid]) // assigns type to tname as a side-effect check.declare(check.scope, name, tname, check.scope.pos) // TODO(gri) check scope position return tpar } diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index ddad1f0311..a7d0db624c 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -157,7 +157,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] } if tparams != nil { - sig.tparams = check.collectTypeParams(tparams) + check.collectTypeParams(&sig.tparams, tparams) // Always type-check method type parameters but complain if they are not enabled. // (A separate check is needed when type-checking interface method signatures because // they don't have a receiver specification.) diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45550.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45550.go2 new file mode 100644 index 0000000000..c3e9e34b87 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45550.go2 @@ -0,0 +1,10 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type Builder[T interface{ struct{ Builder[T] } }] struct{} +type myBuilder struct { + Builder[myBuilder /* ERROR myBuilder does not satisfy */] +} diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47796.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47796.go2 new file mode 100644 index 0000000000..9c10683e22 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47796.go2 @@ -0,0 +1,33 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +// parameterized types with self-recursive constraints +type ( + T1[P T1[P]] interface{} + T2[P, Q T2[P, Q]] interface{} + T3[P T2[P, Q], Q interface{ ~string }] interface{} + + T4a[P T4a[P]] interface{ ~int } + T4b[P T4b[int]] interface{ ~int } + T4c[P T4c[string /* ERROR string does not satisfy T4c\[string\] */]] interface{ ~int } + + // mutually recursive constraints + T5[P T6[P]] interface{ int } + T6[P T5[P]] interface{ int } +) + +// verify that constraints are checked as expected +var ( + _ T1[int] + _ T2[int, string] + _ T3[int, string] +) + +// test case from issue + +type Eq[a Eq[a]] interface { + Equal(that a) bool +} -- GitLab From 054710ce46d5613db8e861eff49cd9cb3e3d0589 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 7 Sep 2021 15:13:24 -0700 Subject: [PATCH 1049/2500] cmd/compile/internal/types2: reduce number of delayed functions (optimization) Rather than create and delay execution of a closure for each type parameter in a type parameter list, just create one per type parameter list. While at it, inline the small amount of code for getting the type constraint and remove the respective function. Change-Id: I49a00ff0a7b7e43eb53992dd7dbfac25ff23b42c Reviewed-on: https://go-review.googlesource.com/c/go/+/348018 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/decl.go | 36 +++++++++++-------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 278ee76bfa..cd97080824 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -619,10 +619,25 @@ func (check *Checker) collectTypeParams(dst **TParamList, list []*syntax.Field) // This also preserves the grouped output of type parameter lists // when printing type strings. if i == 0 || f.Type != list[i-1].Type { - bound = check.boundType(f.Type) + // The predeclared identifier "any" is visible only as a type bound in a type parameter list. + // If we allow "any" for general use, this if-statement can be removed (issue #33232). + if name, _ := unparen(f.Type).(*syntax.Name); name != nil && name.Value == "any" && check.lookup("any") == universeAny { + bound = universeAny.Type() + } else { + bound = check.typ(f.Type) + } } tparams[i].bound = bound } + + check.later(func() { + for i, tpar := range tparams { + u := under(tpar.bound) + if _, ok := u.(*Interface); !ok && u != Typ[Invalid] { + check.errorf(list[i].Type, "%s is not an interface", tpar.bound) + } + } + }) } func (check *Checker) declareTypeParam(name *syntax.Name) *TypeParam { @@ -638,25 +653,6 @@ func (check *Checker) declareTypeParam(name *syntax.Name) *TypeParam { return tpar } -// boundType type-checks the type expression e and returns its type, or Typ[Invalid]. -// The type must be an interface, including the predeclared type "any". -func (check *Checker) boundType(e syntax.Expr) Type { - // The predeclared identifier "any" is visible only as a type bound in a type parameter list. - // If we allow "any" for general use, this if-statement can be removed (issue #33232). - if name, _ := unparen(e).(*syntax.Name); name != nil && name.Value == "any" && check.lookup("any") == universeAny { - return universeAny.Type() - } - - bound := check.typ(e) - check.later(func() { - u := under(bound) - if _, ok := u.(*Interface); !ok && u != Typ[Invalid] { - check.errorf(e, "%s is not an interface", bound) - } - }) - return bound -} - func (check *Checker) collectMethods(obj *TypeName) { // get associated methods // (Checker.collectObjects only collects methods with non-blank names; -- GitLab From 409434d62364cb362f0f17d0c7769dc680b2da99 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 2 Sep 2021 11:23:20 -0400 Subject: [PATCH 1050/2500] cmd/go/internal/modload: scan dependencies of root paths when raising version limits in editRequirements Fixes #47979 Change-Id: I1d9d854cda1378e20c70e6c6789b77e42e467ca7 Reviewed-on: https://go-review.googlesource.com/c/go/+/347290 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/modload/edit.go | 93 +++++++++++--- .../go/testdata/script/mod_get_issue47979.txt | 117 ++++++++++++++++++ 2 files changed, 195 insertions(+), 15 deletions(-) create mode 100644 src/cmd/go/testdata/script/mod_get_issue47979.txt diff --git a/src/cmd/go/internal/modload/edit.go b/src/cmd/go/internal/modload/edit.go index b99ac1242b..023983caed 100644 --- a/src/cmd/go/internal/modload/edit.go +++ b/src/cmd/go/internal/modload/edit.go @@ -192,8 +192,8 @@ func limiterForEdit(ctx context.Context, rs *Requirements, tryUpgrade, mustSelec // raiseLimitsForUpgrades increases the module versions in maxVersions to the // versions that would be needed to allow each of the modules in tryUpgrade -// (individually) and all of the modules in mustSelect (simultaneously) to be -// added as roots. +// (individually or in any combination) and all of the modules in mustSelect +// (simultaneously) to be added as roots. // // Versions not present in maxVersion are unrestricted, and it is assumed that // they will not be promoted to root requirements (and thus will not contribute @@ -215,18 +215,42 @@ func raiseLimitsForUpgrades(ctx context.Context, maxVersion map[string]string, p } } - var unprunedUpgrades []module.Version + var ( + unprunedUpgrades []module.Version + isPrunedRootPath map[string]bool + ) if pruning == unpruned { unprunedUpgrades = tryUpgrade } else { + isPrunedRootPath = make(map[string]bool, len(maxVersion)) + for p := range maxVersion { + isPrunedRootPath[p] = true + } for _, m := range tryUpgrade { + isPrunedRootPath[m.Path] = true + } + for _, m := range mustSelect { + isPrunedRootPath[m.Path] = true + } + + allowedRoot := map[module.Version]bool{} + + var allowRoot func(m module.Version) error + allowRoot = func(m module.Version) error { + if allowedRoot[m] { + return nil + } + allowedRoot[m] = true + if MainModules.Contains(m.Path) { - // The main module versions are already considered to be higher than any possible m, so we - // won't be upgrading to it anyway and there is no point scanning its - // dependencies. - continue + // The main module versions are already considered to be higher than any + // possible m, so m cannot be selected as a root and there is no point + // scanning its dependencies. + return nil } + allow(m) + summary, err := goModSummary(m) if err != nil { return err @@ -236,13 +260,27 @@ func raiseLimitsForUpgrades(ctx context.Context, maxVersion map[string]string, p // graph, rather than loading the (potentially-overlapping) subgraph for // each upgrade individually. unprunedUpgrades = append(unprunedUpgrades, m) - continue + return nil } - - allow(m) for _, r := range summary.require { - allow(r) + if isPrunedRootPath[r.Path] { + // r could become a root as the result of an upgrade or downgrade, + // in which case its dependencies will not be pruned out. + // We need to allow those dependencies to be upgraded too. + if err := allowRoot(r); err != nil { + return err + } + } else { + // r will not become a root, so its dependencies don't matter. + // Allow only r itself. + allow(r) + } } + return nil + } + + for _, m := range tryUpgrade { + allowRoot(m) } } @@ -269,16 +307,41 @@ func raiseLimitsForUpgrades(ctx context.Context, maxVersion map[string]string, p } } - if len(mustSelect) > 0 { - mustGraph, err := readModGraph(ctx, pruning, mustSelect) + // Explicitly allow any (transitive) upgrades implied by mustSelect. + nextRoots := append([]module.Version(nil), mustSelect...) + for nextRoots != nil { + module.Sort(nextRoots) + rs := newRequirements(pruning, nextRoots, nil) + nextRoots = nil + + rs, mustGraph, err := expandGraph(ctx, rs) if err != nil { return err } for _, r := range mustGraph.BuildList() { - // Some module in mustSelect requires r, so we must allow at least r.Version - // unless it conflicts with an entry in mustSelect. + // Some module in mustSelect requires r, so we must allow at least + // r.Version (unless it conflicts with another entry in mustSelect, in + // which case we will error out either way). allow(r) + + if isPrunedRootPath[r.Path] { + if v, ok := rs.rootSelected(r.Path); ok && r.Version == v { + // r is already a root, so its requirements are already included in + // the build list. + continue + } + + // The dependencies in mustSelect may upgrade (or downgrade) an existing + // root to match r, which will remain as a root. However, since r is not + // a root of rs, its dependencies have been pruned out of this build + // list. We need to add it back explicitly so that we allow any + // transitive upgrades that r will pull in. + if nextRoots == nil { + nextRoots = rs.rootModules // already capped + } + nextRoots = append(nextRoots, r) + } } } diff --git a/src/cmd/go/testdata/script/mod_get_issue47979.txt b/src/cmd/go/testdata/script/mod_get_issue47979.txt new file mode 100644 index 0000000000..f5d4304ab2 --- /dev/null +++ b/src/cmd/go/testdata/script/mod_get_issue47979.txt @@ -0,0 +1,117 @@ +# Regression test for https://golang.org/issue/47979: +# +# An argument to 'go get' that results in an upgrade to a different existing +# root should be allowed, and should not panic the 'go' command. + +cp go.mod go.mod.orig + + +# Transitive upgrades from upgraded roots should not prevent +# 'go get -u' from performing upgrades. + +cp go.mod.orig go.mod +go get -u -d . +cmp go.mod go.mod.want + + +# 'go get' of a specific version should allow upgrades of +# every dependency (transitively) required by that version, +# including dependencies that are pulled into the module +# graph by upgrading other root requirements +# (in this case, example.net/indirect). + +cp go.mod.orig go.mod +go get -d example.net/a@v0.2.0 +cmp go.mod go.mod.want + + +-- go.mod -- +module golang.org/issue47979 + +go 1.17 + +replace ( + example.net/a v0.1.0 => ./a1 + example.net/a v0.2.0 => ./a2 + example.net/indirect v0.1.0 => ./indirect1 + example.net/indirect v0.2.0 => ./indirect2 + example.net/other v0.1.0 => ./other + example.net/other v0.2.0 => ./other +) + +require ( + example.net/a v0.1.0 + example.net/other v0.1.0 +) + +require example.net/indirect v0.1.0 // indirect +-- go.mod.want -- +module golang.org/issue47979 + +go 1.17 + +replace ( + example.net/a v0.1.0 => ./a1 + example.net/a v0.2.0 => ./a2 + example.net/indirect v0.1.0 => ./indirect1 + example.net/indirect v0.2.0 => ./indirect2 + example.net/other v0.1.0 => ./other + example.net/other v0.2.0 => ./other +) + +require ( + example.net/a v0.2.0 + example.net/other v0.2.0 +) + +require example.net/indirect v0.2.0 // indirect +-- issue.go -- +package issue + +import _ "example.net/a" +-- useother/useother.go -- +package useother + +import _ "example.net/other" +-- a1/go.mod -- +module example.net/a + +go 1.17 + +require example.net/indirect v0.1.0 +-- a1/a.go -- +package a +-- a2/go.mod -- +module example.net/a + +go 1.17 + +require example.net/indirect v0.2.0 +-- a2/a.go -- +package a + +import "example.net/indirect" +-- indirect1/go.mod -- +module example.net/indirect + +go 1.17 + +require example.net/other v0.1.0 +-- indirect1/indirect.go -- +package indirect +-- indirect2/go.mod -- +module example.net/indirect + +go 1.17 + +require example.net/other v0.2.0 +-- indirect2/indirect.go -- +package indirect + +import "example.net/other" +-- other/go.mod -- +module example.net/other + +go 1.17 +-- other/other.go -- +package other -- GitLab From a1a6540bf1c38c2c8ad7fced983d2e3206ab1d2b Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Thu, 2 Sep 2021 18:39:58 -0400 Subject: [PATCH 1051/2500] go/types: implement deduplication of instances using the Environment Implement deduplication of type instances via the Environment by recording a map of unique IDs for *Named types. This avoids an issue with the existing type hash, where qualified names alone were not sufficient to differentiate two *Named types that have the same fully qualified name but which are distinct pointers. It also allows us to drop the scope accounting for local types. A subtle bug is also fixed in subst.go, where the instance t was passed to typeHash rather than t.orig. Change-Id: I85639ccc1c9bfee470babd2fc85375484c8ed0b9 Reviewed-on: https://go-review.googlesource.com/c/go/+/344390 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/check.go | 4 +- src/go/types/decl.go | 2 +- src/go/types/environment.go | 56 +++++++++++++++++++++++++ src/go/types/instantiate.go | 38 +++++++---------- src/go/types/instantiate_test.go | 72 ++++++++++++++++++++++++++++++++ src/go/types/named.go | 22 ++++++---- src/go/types/subst.go | 44 +++++++++---------- src/go/types/typestring.go | 55 ++++++++++-------------- 8 files changed, 203 insertions(+), 90 deletions(-) create mode 100644 src/go/types/environment.go create mode 100644 src/go/types/instantiate_test.go diff --git a/src/go/types/check.go b/src/go/types/check.go index ab3a388e9f..0383a58c64 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -89,7 +89,7 @@ type Checker struct { nextID uint64 // unique Id for type parameters (first valid Id is 1) objMap map[Object]*declInfo // maps package-level objects and (non-interface) methods to declaration info impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package - typMap map[string]*Named // maps an instantiated named type hash to a *Named type + env *Environment // for deduplicating identical instances // pkgPathMap maps package names to the set of distinct import paths we've // seen for that name, anywhere in the import graph. It is used for @@ -192,7 +192,7 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch version: version, objMap: make(map[Object]*declInfo), impMap: make(map[importKey]*Package), - typMap: make(map[string]*Named), + env: NewEnvironment(), } } diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 275d17c826..80f8f2f429 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -316,7 +316,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { } case *Named: - t.expand(check.typMap) + t.expand(check.env) // don't touch the type if it is from a different package or the Universe scope // (doing so would lead to a race condition - was issue #35049) if t.obj.pkg != check.pkg { diff --git a/src/go/types/environment.go b/src/go/types/environment.go new file mode 100644 index 0000000000..f8c14c87bf --- /dev/null +++ b/src/go/types/environment.go @@ -0,0 +1,56 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +import "sync" + +// An Environment is an opaque type checking environment. It may be used to +// share identical type instances across type-checked packages or calls to +// Instantiate. +// +// It is safe for concurrent use. +type Environment struct { + mu sync.Mutex + typeMap map[string]*Named // type hash -> instance + nextID int // next unique ID + seen map[*Named]int // assigned unique IDs +} + +// NewEnvironment creates a new Environment. +func NewEnvironment() *Environment { + return &Environment{ + typeMap: make(map[string]*Named), + seen: make(map[*Named]int), + } +} + +// TODO(rfindley): move Environment.typeHash here. + +// typeForHash returns the recorded type for the type hash h, if it exists. +// If no type exists for h and n is non-nil, n is recorded for h. +func (env *Environment) typeForHash(h string, n *Named) *Named { + env.mu.Lock() + defer env.mu.Unlock() + if existing := env.typeMap[h]; existing != nil { + return existing + } + if n != nil { + env.typeMap[h] = n + } + return n +} + +// idForType returns a unique ID for the pointer n. +func (env *Environment) idForType(n *Named) int { + env.mu.Lock() + defer env.mu.Unlock() + id, ok := env.seen[n] + if !ok { + id = env.nextID + env.seen[n] = id + env.nextID++ + } + return id +} diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index ec4c61cf62..256a0ed79b 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -13,19 +13,6 @@ import ( "go/token" ) -// An Environment is an opaque type checking environment. It may be used to -// share identical type instances across type checked packages or calls to -// Instantiate. -// -// Currently, Environment is just a placeholder and has no effect on -// instantiation. -type Environment struct { - // Environment is currently un-implemented, because our instantiatedHash - // logic doesn't correctly handle Named type identity across multiple - // packages. - // TODO(rfindley): implement this. -} - // Instantiate instantiates the type typ with the given type arguments targs. // typ must be a *Named or a *Signature type, and its number of type parameters // must match the number of provided type arguments. The result is a new, @@ -44,7 +31,7 @@ type Environment struct { // TODO(rfindley): change this function to also return an error if lengths of // tparams and targs do not match. func Instantiate(env *Environment, typ Type, targs []Type, validate bool) (Type, error) { - inst := (*Checker)(nil).instance(token.NoPos, typ, targs) + inst := (*Checker)(nil).instance(token.NoPos, typ, targs, env) var err error if validate { @@ -84,7 +71,7 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, posList }() } - inst := check.instance(pos, typ, targs) + inst := check.instance(pos, typ, targs, check.env) assert(len(posList) <= len(targs)) check.later(func() { @@ -116,14 +103,15 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, posList // instance creates a type or function instance using the given original type // typ and arguments targs. For Named types the resulting instance will be // unexpanded. -func (check *Checker) instance(pos token.Pos, typ Type, targs []Type) Type { +func (check *Checker) instance(pos token.Pos, typ Type, targs []Type, env *Environment) Type { switch t := typ.(type) { case *Named: - h := typeHash(t, targs) - if check != nil { - // typ may already have been instantiated with identical type arguments. - // In that case, re-use the existing instance. - if named := check.typMap[h]; named != nil { + var h string + if env != nil { + h = env.typeHash(t, targs) + // typ may already have been instantiated with identical type arguments. In + // that case, re-use the existing instance. + if named := env.typeForHash(h, nil); named != nil { return named } } @@ -131,8 +119,10 @@ func (check *Checker) instance(pos token.Pos, typ Type, targs []Type) Type { named := check.newNamed(tname, t, nil, nil, nil) // methods and tparams are set when named is loaded named.targs = NewTypeList(targs) named.instPos = &pos - if check != nil { - check.typMap[h] = named + if env != nil { + // It's possible that we've lost a race to add named to the environment. + // In this case, use whichever instance is recorded in the environment. + named = env.typeForHash(h, named) } return named @@ -144,7 +134,7 @@ func (check *Checker) instance(pos token.Pos, typ Type, targs []Type) Type { if tparams.Len() == 0 { return typ // nothing to do (minor optimization) } - sig := check.subst(pos, typ, makeSubstMap(tparams.list(), targs), nil).(*Signature) + sig := check.subst(pos, typ, makeSubstMap(tparams.list(), targs), env).(*Signature) // If the signature doesn't use its type parameters, subst // will not make a copy. In that case, make a copy now (so // we can set tparams to nil w/o causing side-effects). diff --git a/src/go/types/instantiate_test.go b/src/go/types/instantiate_test.go new file mode 100644 index 0000000000..0b09bfebe3 --- /dev/null +++ b/src/go/types/instantiate_test.go @@ -0,0 +1,72 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types_test + +import ( + . "go/types" + "testing" +) + +func TestInstantiateEquality(t *testing.T) { + const src = genericPkg + "p; type T[P any] int" + + pkg, err := pkgFor(".", src, nil) + if err != nil { + t.Fatal(err) + } + + T := pkg.Scope().Lookup("T").Type().(*Named) + + // Instantiating the same type twice should result in pointer-equivalent + // instances. + env := NewEnvironment() + res1, err := Instantiate(env, T, []Type{Typ[Int]}, false) + if err != nil { + t.Fatal(err) + } + res2, err := Instantiate(env, T, []Type{Typ[Int]}, false) + if err != nil { + t.Fatal(err) + } + + if res1 != res2 { + t.Errorf("first instance (%s) not pointer-equivalent to second instance (%s)", res1, res2) + } +} + +func TestInstantiateNonEquality(t *testing.T) { + const src = genericPkg + "p; type T[P any] int" + + pkg1, err := pkgFor(".", src, nil) + if err != nil { + t.Fatal(err) + } + pkg2, err := pkgFor(".", src, nil) + if err != nil { + t.Fatal(err) + } + + // We consider T1 and T2 to be distinct types, so their instances should not + // be deduplicated by the environment. + T1 := pkg1.Scope().Lookup("T").Type().(*Named) + T2 := pkg2.Scope().Lookup("T").Type().(*Named) + + env := NewEnvironment() + res1, err := Instantiate(env, T1, []Type{Typ[Int]}, false) + if err != nil { + t.Fatal(err) + } + res2, err := Instantiate(env, T2, []Type{Typ[Int]}, false) + if err != nil { + t.Fatal(err) + } + + if res1 == res2 { + t.Errorf("instance from pkg1 (%s) is pointer-equivalent to instance from pkg2 (%s)", res1, res2) + } + if Identical(res1, res2) { + t.Errorf("instance from pkg1 (%s) is identical to instance from pkg2 (%s)", res1, res2) + } +} diff --git a/src/go/types/named.go b/src/go/types/named.go index 4540956658..c9ef70d7ad 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -242,7 +242,7 @@ func (n *Named) setUnderlying(typ Type) { // expand ensures that the underlying type of n is instantiated. // The underlying type will be Typ[Invalid] if there was an error. -func (n *Named) expand(typMap map[string]*Named) *Named { +func (n *Named) expand(env *Environment) *Named { if n.instPos != nil { // n must be loaded before instantiation, in order to have accurate // tparams. This is done implicitly by the call to n.TParams, but making it @@ -250,19 +250,25 @@ func (n *Named) expand(typMap map[string]*Named) *Named { n.load() var u Type if n.check.validateTArgLen(*n.instPos, n.tparams.Len(), n.targs.Len()) { - if typMap == nil { + // TODO(rfindley): handling an optional Checker and Environment here (and + // in subst) feels overly complicated. Can we simplify? + if env == nil { if n.check != nil { - typMap = n.check.typMap + env = n.check.env } else { // If we're instantiating lazily, we might be outside the scope of a // type-checking pass. In that case we won't have a pre-existing - // typMap, but don't want to create a duplicate of the current instance - // in the process of expansion. - h := typeHash(n.orig, n.targs.list()) - typMap = map[string]*Named{h: n} + // environment, but don't want to create a duplicate of the current + // instance in the process of expansion. + env = NewEnvironment() } + h := env.typeHash(n.orig, n.targs.list()) + // add the instance to the environment to avoid infinite recursion. + // addInstance may return a different, existing instance, but we + // shouldn't return that instance from expand. + env.typeForHash(h, n) } - u = n.check.subst(*n.instPos, n.orig.underlying, makeSubstMap(n.TParams().list(), n.targs.list()), typMap) + u = n.check.subst(*n.instPos, n.orig.underlying, makeSubstMap(n.TParams().list(), n.targs.list()), env) } else { u = Typ[Invalid] } diff --git a/src/go/types/subst.go b/src/go/types/subst.go index fb77617d0c..d0ef07652f 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -43,8 +43,8 @@ func (m substMap) lookup(tpar *TypeParam) Type { // that it doesn't modify the incoming type. If a substitution took place, the // result type is different from the incoming type. // -// If the given typMap is non-nil, it is used in lieu of check.typMap. -func (check *Checker) subst(pos token.Pos, typ Type, smap substMap, typMap map[string]*Named) Type { +// If the given environment is non-nil, it is used in lieu of check.env. +func (check *Checker) subst(pos token.Pos, typ Type, smap substMap, env *Environment) Type { if smap.empty() { return typ } @@ -64,27 +64,27 @@ func (check *Checker) subst(pos token.Pos, typ Type, smap substMap, typMap map[s if check != nil { subst.check = check - if typMap == nil { - typMap = check.typMap + if env == nil { + env = check.env } } - if typMap == nil { + if env == nil { // If we don't have a *Checker and its global type map, // use a local version. Besides avoiding duplicate work, // the type map prevents infinite recursive substitution // for recursive types (example: type T[P any] *T[P]). - typMap = make(map[string]*Named) + env = NewEnvironment() } - subst.typMap = typMap + subst.env = env return subst.typ(typ) } type subster struct { - pos token.Pos - smap substMap - check *Checker // nil if called via Instantiate - typMap map[string]*Named + pos token.Pos + smap substMap + check *Checker // nil if called via Instantiate + env *Environment } func (subst *subster) typ(typ Type) Type { @@ -217,25 +217,25 @@ func (subst *subster) typ(typ Type) Type { } // before creating a new named type, check if we have this one already - h := typeHash(t, newTArgs) + h := subst.env.typeHash(t.orig, newTArgs) dump(">>> new type hash: %s", h) - if named, found := subst.typMap[h]; found { + if named := subst.env.typeForHash(h, nil); named != nil { dump(">>> found %s", named) return named } - // Create a new named type and populate typMap to avoid endless recursion. - // The position used here is irrelevant because validation only occurs on t - // (we don't call validType on named), but we use subst.pos to help with - // debugging. + // Create a new named type and populate the environment to avoid endless + // recursion. The position used here is irrelevant because validation only + // occurs on t (we don't call validType on named), but we use subst.pos to + // help with debugging. tname := NewTypeName(subst.pos, t.obj.pkg, t.obj.name, nil) t.load() // It's ok to provide a nil *Checker because the newly created type // doesn't need to be (lazily) expanded; it's expanded below. named := (*Checker)(nil).newNamed(tname, t.orig, nil, t.tparams, t.methods) // t is loaded, so tparams and methods are available named.targs = NewTypeList(newTArgs) - subst.typMap[h] = named - t.expand(subst.typMap) // must happen after typMap update to avoid infinite recursion + subst.env.typeForHash(h, named) + t.expand(subst.env) // must happen after env update to avoid infinite recursion // do the substitution dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, newTArgs) @@ -260,14 +260,16 @@ func (subst *subster) typ(typ Type) Type { // type hash: types that are identical produce identical string representations. // If typ is a *Named type and targs is not empty, typ is printed as if it were // instantiated with targs. -func typeHash(typ Type, targs []Type) string { +func (env *Environment) typeHash(typ Type, targs []Type) string { + assert(env != nil) assert(typ != nil) var buf bytes.Buffer - h := newTypeHasher(&buf) + h := newTypeHasher(&buf, env) if named, _ := typ.(*Named); named != nil && len(targs) > 0 { // Don't use WriteType because we need to use the provided targs // and not any targs that might already be with the *Named type. + h.typePrefix(named) h.typeName(named.obj) h.typeList(targs) } else { diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index c5f0354aea..362b44a2c2 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -10,6 +10,7 @@ import ( "bytes" "fmt" "go/token" + "strconv" "unicode/utf8" ) @@ -71,22 +72,23 @@ type typeWriter struct { buf *bytes.Buffer seen map[Type]bool qf Qualifier - hash bool + env *Environment // if non-nil, we are type hashing } func newTypeWriter(buf *bytes.Buffer, qf Qualifier) *typeWriter { - return &typeWriter{buf, make(map[Type]bool), qf, false} + return &typeWriter{buf, make(map[Type]bool), qf, nil} } -func newTypeHasher(buf *bytes.Buffer) *typeWriter { - return &typeWriter{buf, make(map[Type]bool), nil, true} +func newTypeHasher(buf *bytes.Buffer, env *Environment) *typeWriter { + assert(env != nil) + return &typeWriter{buf, make(map[Type]bool), nil, env} } func (w *typeWriter) byte(b byte) { w.buf.WriteByte(b) } func (w *typeWriter) string(s string) { w.buf.WriteString(s) } func (w *typeWriter) writef(format string, args ...interface{}) { fmt.Fprintf(w.buf, format, args...) } func (w *typeWriter) error(msg string) { - if w.hash { + if w.env != nil { panic(msg) } w.string("<" + msg + ">") @@ -228,14 +230,15 @@ func (w *typeWriter) typ(typ Type) { // types. Write them to aid debugging, but don't write // them when we need an instance hash: whether a type // is fully expanded or not doesn't matter for identity. - if !w.hash && t.instPos != nil { + if w.env == nil && t.instPos != nil { w.byte(instanceMarker) } + w.typePrefix(t) w.typeName(t.obj) if t.targs != nil { // instantiated type w.typeList(t.targs.list()) - } else if !w.hash && t.TParams().Len() != 0 { // For type hashing, don't need to format the TParams + } else if w.env == nil && t.TParams().Len() != 0 { // For type hashing, don't need to format the TParams // parameterized type w.tParamList(t.TParams().list()) } @@ -264,6 +267,15 @@ func (w *typeWriter) typ(typ Type) { } } +// If w.env is non-nil, typePrefix writes a unique prefix for the named type t +// based on the types already observed by w.env. If w.env is nil, it does +// nothing. +func (w *typeWriter) typePrefix(t *Named) { + if w.env != nil { + w.string(strconv.Itoa(w.env.idForType(t))) + } +} + func (w *typeWriter) typeList(list []Type) { w.byte('[') for i, typ := range list { @@ -309,31 +321,6 @@ func (w *typeWriter) typeName(obj *TypeName) { writePackage(w.buf, obj.pkg, w.qf) } w.string(obj.name) - - if w.hash { - // For local defined types, use the (original!) TypeName's scope - // numbers to disambiguate. - if typ, _ := obj.typ.(*Named); typ != nil { - // TODO(gri) Figure out why typ.orig != typ.orig.orig sometimes - // and whether the loop can iterate more than twice. - // (It seems somehow connected to instance types.) - for typ.orig != typ { - typ = typ.orig - } - w.writeScopeNumbers(typ.obj.parent) - } - } -} - -// writeScopeNumbers writes the number sequence for this scope to buf -// in the form ".i.j.k" where i, j, k, etc. stand for scope numbers. -// If a scope is nil or has no parent (such as a package scope), nothing -// is written. -func (w *typeWriter) writeScopeNumbers(s *Scope) { - if s != nil && s.number > 0 { - w.writeScopeNumbers(s.parent) - w.writef(".%d", s.number) - } } func (w *typeWriter) tuple(tup *Tuple, variadic bool) { @@ -344,7 +331,7 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) { w.string(", ") } // parameter names are ignored for type identity and thus type hashes - if !w.hash && v.name != "" { + if w.env == nil && v.name != "" { w.string(v.name) w.byte(' ') } @@ -385,7 +372,7 @@ func (w *typeWriter) signature(sig *Signature) { } w.byte(' ') - if n == 1 && (w.hash || sig.results.vars[0].name == "") { + if n == 1 && (w.env != nil || sig.results.vars[0].name == "") { // single unnamed result (if type hashing, name must be ignored) w.typ(sig.results.vars[0].typ) return -- GitLab From cb9ccd494b778577d01cd6053b8288fc6d665de7 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Fri, 3 Sep 2021 11:17:37 -0400 Subject: [PATCH 1052/2500] go/types: move typeHash to environment.go This is a pure code move, with no other changes. Change-Id: Id31f1f960d3208dc614556de89bf39b7ca77df3a Reviewed-on: https://go-review.googlesource.com/c/go/+/347560 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/environment.go | 36 ++++++++++++++++++++++++++++++++++-- src/go/types/subst.go | 36 +----------------------------------- 2 files changed, 35 insertions(+), 37 deletions(-) diff --git a/src/go/types/environment.go b/src/go/types/environment.go index f8c14c87bf..93383efe1a 100644 --- a/src/go/types/environment.go +++ b/src/go/types/environment.go @@ -4,7 +4,10 @@ package types -import "sync" +import ( + "bytes" + "sync" +) // An Environment is an opaque type checking environment. It may be used to // share identical type instances across type-checked packages or calls to @@ -26,7 +29,36 @@ func NewEnvironment() *Environment { } } -// TODO(rfindley): move Environment.typeHash here. +// typeHash returns a string representation of typ, which can be used as an exact +// type hash: types that are identical produce identical string representations. +// If typ is a *Named type and targs is not empty, typ is printed as if it were +// instantiated with targs. +func (env *Environment) typeHash(typ Type, targs []Type) string { + assert(env != nil) + assert(typ != nil) + var buf bytes.Buffer + + h := newTypeHasher(&buf, env) + if named, _ := typ.(*Named); named != nil && len(targs) > 0 { + // Don't use WriteType because we need to use the provided targs + // and not any targs that might already be with the *Named type. + h.typePrefix(named) + h.typeName(named.obj) + h.typeList(targs) + } else { + assert(targs == nil) + h.typ(typ) + } + + if debug { + // there should be no instance markers in type hashes + for _, b := range buf.Bytes() { + assert(b != instanceMarker) + } + } + + return buf.String() +} // typeForHash returns the recorded type for the type hash h, if it exists. // If no type exists for h and n is non-nil, n is recorded for h. diff --git a/src/go/types/subst.go b/src/go/types/subst.go index d0ef07652f..452ea5f75f 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -6,10 +6,7 @@ package types -import ( - "bytes" - "go/token" -) +import "go/token" // TODO(rFindley) decide error codes for the errors in this file, and check // if error spans can be improved @@ -256,37 +253,6 @@ func (subst *subster) typ(typ Type) Type { return typ } -// typeHash returns a string representation of typ, which can be used as an exact -// type hash: types that are identical produce identical string representations. -// If typ is a *Named type and targs is not empty, typ is printed as if it were -// instantiated with targs. -func (env *Environment) typeHash(typ Type, targs []Type) string { - assert(env != nil) - assert(typ != nil) - var buf bytes.Buffer - - h := newTypeHasher(&buf, env) - if named, _ := typ.(*Named); named != nil && len(targs) > 0 { - // Don't use WriteType because we need to use the provided targs - // and not any targs that might already be with the *Named type. - h.typePrefix(named) - h.typeName(named.obj) - h.typeList(targs) - } else { - assert(targs == nil) - h.typ(typ) - } - - if debug { - // there should be no instance markers in type hashes - for _, b := range buf.Bytes() { - assert(b != instanceMarker) - } - } - - return buf.String() -} - // typOrNil is like typ but if the argument is nil it is replaced with Typ[Invalid]. // A nil type may appear in pathological cases such as type T[P any] []func(_ T([]_)) // where an array/slice element is accessed before it is set up. -- GitLab From 38c2e08cbd2c863869f31754ee62b0c6dcaccd54 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Fri, 3 Sep 2021 11:22:18 -0400 Subject: [PATCH 1053/2500] go/types: move NewTypeParam off of Checker This aligns with the API proposal. Change-Id: I9967a317196392ffa5ddbe5391d7aba5f6e7bad2 Reviewed-on: https://go-review.googlesource.com/c/go/+/347561 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/internal/gcimporter/iimport.go | 2 +- src/go/types/builtins.go | 2 +- src/go/types/decl.go | 2 +- src/go/types/typeparam.go | 10 +++++++--- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go index 3571941d04..96c2bb3f2c 100644 --- a/src/go/internal/gcimporter/iimport.go +++ b/src/go/internal/gcimporter/iimport.go @@ -355,7 +355,7 @@ func (r *importReader) obj(name string) { } name0, sub := parseSubscript(name) tn := types.NewTypeName(pos, r.currPkg, name0, nil) - t := (*types.Checker)(nil).NewTypeParam(tn, nil) + t := types.NewTypeParam(tn, nil) if sub == 0 { errorf("missing subscript") } diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index ecf7b89275..d805e46666 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -830,7 +830,7 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { // type param is placed in the current package so export/import // works as expected. tpar := NewTypeName(token.NoPos, check.pkg, "", nil) - ptyp := check.NewTypeParam(tpar, NewInterfaceType(nil, []Type{NewUnion(terms)})) // assigns type to tpar as a side-effect + ptyp := check.newTypeParam(tpar, NewInterfaceType(nil, []Type{NewUnion(terms)})) // assigns type to tpar as a side-effect ptyp.index = tp.index return ptyp diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 80f8f2f429..b48081f0b1 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -677,7 +677,7 @@ func (check *Checker) collectTypeParams(list *ast.FieldList) *TParamList { func (check *Checker) declareTypeParams(tparams []*TypeParam, names []*ast.Ident) []*TypeParam { for _, name := range names { tname := NewTypeName(name.Pos(), check.pkg, name.Name, nil) - tpar := check.NewTypeParam(tname, &emptyInterface) // assigns type to tpar as a side-effect + tpar := check.newTypeParam(tname, &emptyInterface) // assigns type to tpar as a side-effect check.declare(check.scope, name, tname, check.scope.pos) // TODO(gri) check scope position tparams = append(tparams, tpar) } diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index b6952489ca..29d44f4cb2 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -32,15 +32,19 @@ type TypeParam struct { // or Signature type by calling SetTParams. Setting a type parameter on more // than one type will result in a panic. // -// The bound argument can be nil, and set later via SetBound. -func (check *Checker) NewTypeParam(obj *TypeName, bound Type) *TypeParam { +// The bound argument can be nil, and set later via SetConstraint. +func NewTypeParam(obj *TypeName, constraint Type) *TypeParam { + return (*Checker)(nil).newTypeParam(obj, constraint) +} + +func (check *Checker) newTypeParam(obj *TypeName, constraint Type) *TypeParam { // Always increment lastID, even if it is not used. id := nextID() if check != nil { check.nextID++ id = check.nextID } - typ := &TypeParam{check: check, id: id, obj: obj, index: -1, bound: bound} + typ := &TypeParam{check: check, id: id, obj: obj, index: -1, bound: constraint} if obj.typ == nil { obj.typ = typ } -- GitLab From 12eb7331b9e220d73ecfba0281e60cf0f5285e18 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 8 Sep 2021 11:46:58 -0400 Subject: [PATCH 1054/2500] go/ast: rename TParams fields to TypeParams As discussed in the ast proposal (#47781), there's not really a strong reason to avoid spelling out 'Type'. Change-Id: I0ba1bf03b112ea60509a78a89a050a302779d9d0 Reviewed-on: https://go-review.googlesource.com/c/go/+/348375 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/ast/ast.go | 20 ++++++++++---------- src/go/ast/walk.go | 8 ++++---- src/go/parser/parser.go | 18 +++++++++--------- src/go/parser/resolver.go | 10 +++++----- src/go/printer/nodes.go | 8 ++++---- src/go/types/decl.go | 8 ++++---- src/go/types/interface.go | 4 ++-- src/go/types/resolver.go | 12 ++++++------ src/go/types/signature.go | 6 +++--- 9 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/go/ast/ast.go b/src/go/ast/ast.go index b0f1330564..f9223e4f91 100644 --- a/src/go/ast/ast.go +++ b/src/go/ast/ast.go @@ -451,10 +451,10 @@ type ( // A FuncType node represents a function type. FuncType struct { - Func token.Pos // position of "func" keyword (token.NoPos if there is no "func") - TParams *FieldList // type parameters; or nil - Params *FieldList // (incoming) parameters; non-nil - Results *FieldList // (outgoing) results; or nil + Func token.Pos // position of "func" keyword (token.NoPos if there is no "func") + TypeParams *FieldList // type parameters; or nil + Params *FieldList // (incoming) parameters; non-nil + Results *FieldList // (outgoing) results; or nil } // An InterfaceType node represents an interface type. @@ -915,12 +915,12 @@ type ( // A TypeSpec node represents a type declaration (TypeSpec production). TypeSpec struct { - Doc *CommentGroup // associated documentation; or nil - Name *Ident // type name - TParams *FieldList // type parameters; or nil - Assign token.Pos // position of '=', if any - Type Expr // *Ident, *ParenExpr, *SelectorExpr, *StarExpr, or any of the *XxxTypes - Comment *CommentGroup // line comments; or nil + Doc *CommentGroup // associated documentation; or nil + Name *Ident // type name + TypeParams *FieldList // type parameters; or nil + Assign token.Pos // position of '=', if any + Type Expr // *Ident, *ParenExpr, *SelectorExpr, *StarExpr, or any of the *XxxTypes + Comment *CommentGroup // line comments; or nil } ) diff --git a/src/go/ast/walk.go b/src/go/ast/walk.go index c8abc40972..530735e76f 100644 --- a/src/go/ast/walk.go +++ b/src/go/ast/walk.go @@ -169,8 +169,8 @@ func Walk(v Visitor, node Node) { Walk(v, n.Fields) case *FuncType: - if n.TParams != nil { - Walk(v, n.TParams) + if n.TypeParams != nil { + Walk(v, n.TypeParams) } if n.Params != nil { Walk(v, n.Params) @@ -326,8 +326,8 @@ func Walk(v Visitor, node Node) { Walk(v, n.Doc) } Walk(v, n.Name) - if n.TParams != nil { - Walk(v, n.TParams) + if n.TypeParams != nil { + Walk(v, n.TypeParams) } Walk(v, n.Type) if n.Comment != nil { diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go index 5a7becf6da..5c0af8d3b8 100644 --- a/src/go/parser/parser.go +++ b/src/go/parser/parser.go @@ -973,10 +973,10 @@ func (p *parser) parseMethodSpec() *ast.Field { results := p.parseResult() idents = []*ast.Ident{ident} typ = &ast.FuncType{ - Func: token.NoPos, - TParams: tparams, - Params: params, - Results: results, + Func: token.NoPos, + TypeParams: tparams, + Params: params, + Results: results, } } else { // embedded instantiated type @@ -2509,7 +2509,7 @@ func (p *parser) parseValueSpec(doc *ast.CommentGroup, _ token.Pos, keyword toke func (p *parser) parseGenericType(spec *ast.TypeSpec, openPos token.Pos, name0 *ast.Ident, closeTok token.Token) { list := p.parseParameterList(name0, closeTok, p.parseParamDecl, true) closePos := p.expect(closeTok) - spec.TParams = &ast.FieldList{Opening: openPos, List: list, Closing: closePos} + spec.TypeParams = &ast.FieldList{Opening: openPos, List: list, Closing: closePos} // Type alias cannot have type parameters. Accept them for robustness but complain. if p.tok == token.ASSIGN { p.error(p.pos, "generic type cannot be alias") @@ -2639,10 +2639,10 @@ func (p *parser) parseFuncDecl() *ast.FuncDecl { Recv: recv, Name: ident, Type: &ast.FuncType{ - Func: pos, - TParams: tparams, - Params: params, - Results: results, + Func: pos, + TypeParams: tparams, + Params: params, + Results: results, }, Body: body, } diff --git a/src/go/parser/resolver.go b/src/go/parser/resolver.go index cfdb5e1193..527f1691bd 100644 --- a/src/go/parser/resolver.go +++ b/src/go/parser/resolver.go @@ -454,10 +454,10 @@ func (r *resolver) Visit(node ast.Node) ast.Visitor { // at the identifier in the TypeSpec and ends at the end of the innermost // containing block. r.declare(spec, nil, r.topScope, ast.Typ, spec.Name) - if spec.TParams != nil { + if spec.TypeParams != nil { r.openScope(spec.Pos()) defer r.closeScope() - r.walkTParams(spec.TParams) + r.walkTParams(spec.TypeParams) } ast.Walk(r, spec.Type) } @@ -473,8 +473,8 @@ func (r *resolver) Visit(node ast.Node) ast.Visitor { // Type parameters are walked normally: they can reference each other, and // can be referenced by normal parameters. - if n.Type.TParams != nil { - r.walkTParams(n.Type.TParams) + if n.Type.TypeParams != nil { + r.walkTParams(n.Type.TypeParams) // TODO(rFindley): need to address receiver type parameters. } @@ -499,7 +499,7 @@ func (r *resolver) Visit(node ast.Node) ast.Visitor { } func (r *resolver) walkFuncType(typ *ast.FuncType) { - // typ.TParams must be walked separately for FuncDecls. + // typ.TypeParams must be walked separately for FuncDecls. r.resolveList(typ.Params) r.resolveList(typ.Results) r.declareList(typ.Params, ast.Var) diff --git a/src/go/printer/nodes.go b/src/go/printer/nodes.go index 58887153f2..9ce0115426 100644 --- a/src/go/printer/nodes.go +++ b/src/go/printer/nodes.go @@ -382,8 +382,8 @@ func (p *printer) parameters(fields *ast.FieldList, isTypeParam bool) { } func (p *printer) signature(sig *ast.FuncType) { - if sig.TParams != nil { - p.parameters(sig.TParams, true) + if sig.TypeParams != nil { + p.parameters(sig.TypeParams, true) } if sig.Params != nil { p.parameters(sig.Params, false) @@ -1632,8 +1632,8 @@ func (p *printer) spec(spec ast.Spec, n int, doIndent bool) { case *ast.TypeSpec: p.setComment(s.Doc) p.expr(s.Name) - if s.TParams != nil { - p.parameters(s.TParams, true) + if s.TypeParams != nil { + p.parameters(s.TypeParams, true) } if n == 1 { p.print(blank) diff --git a/src/go/types/decl.go b/src/go/types/decl.go index b48081f0b1..6dac807c75 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -589,7 +589,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { }) alias := tdecl.Assign.IsValid() - if alias && tdecl.TParams.NumFields() != 0 { + if alias && tdecl.TypeParams.NumFields() != 0 { // The parser will ensure this but we may still get an invalid AST. // Complain and continue as regular type definition. check.error(atPos(tdecl.Assign), 0, "generic type cannot be alias") @@ -612,10 +612,10 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { named := check.newNamed(obj, nil, nil, nil, nil) def.setUnderlying(named) - if tdecl.TParams != nil { + if tdecl.TypeParams != nil { check.openScope(tdecl, "type parameters") defer check.closeScope() - named.tparams = check.collectTypeParams(tdecl.TParams) + named.tparams = check.collectTypeParams(tdecl.TypeParams) } // determine underlying type of named @@ -791,7 +791,7 @@ func (check *Checker) funcDecl(obj *Func, decl *declInfo) { check.funcType(sig, fdecl.Recv, fdecl.Type) obj.color_ = saved - if fdecl.Type.TParams.NumFields() > 0 && fdecl.Body == nil { + if fdecl.Type.TypeParams.NumFields() > 0 && fdecl.Body == nil { check.softErrorf(fdecl.Name, _Todo, "parameterized function is missing function body") } diff --git a/src/go/types/interface.go b/src/go/types/interface.go index ebd246da98..2211e37c59 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -194,8 +194,8 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d // a receiver specification.) if sig.tparams != nil { var at positioner = f.Type - if ftyp, _ := f.Type.(*ast.FuncType); ftyp != nil && ftyp.TParams != nil { - at = ftyp.TParams + if ftyp, _ := f.Type.(*ast.FuncType); ftyp != nil && ftyp.TypeParams != nil { + at = ftyp.TypeParams } check.errorf(at, _Todo, "methods cannot have type parameters") } diff --git a/src/go/types/resolver.go b/src/go/types/resolver.go index fb7e0cc474..b04a673ab7 100644 --- a/src/go/types/resolver.go +++ b/src/go/types/resolver.go @@ -381,8 +381,8 @@ func (check *Checker) collectObjects() { check.declarePkgObj(name, obj, di) } case typeDecl: - if d.spec.TParams.NumFields() != 0 && !check.allowVersion(pkg, 1, 18) { - check.softErrorf(d.spec.TParams.List[0], _Todo, "type parameters require go1.18 or later") + if d.spec.TypeParams.NumFields() != 0 && !check.allowVersion(pkg, 1, 18) { + check.softErrorf(d.spec.TypeParams.List[0], _Todo, "type parameters require go1.18 or later") } obj := NewTypeName(d.spec.Name.Pos(), pkg, d.spec.Name.Name, nil) check.declarePkgObj(d.spec.Name, obj, &declInfo{file: fileScope, tdecl: d.spec}) @@ -401,8 +401,8 @@ func (check *Checker) collectObjects() { if name == "main" { code = _InvalidMainDecl } - if d.decl.Type.TParams.NumFields() != 0 { - check.softErrorf(d.decl.Type.TParams.List[0], code, "func %s must have no type parameters", name) + if d.decl.Type.TypeParams.NumFields() != 0 { + check.softErrorf(d.decl.Type.TypeParams.List[0], code, "func %s must have no type parameters", name) hasTParamError = true } if t := d.decl.Type; t.Params.NumFields() != 0 || t.Results != nil { @@ -439,8 +439,8 @@ func (check *Checker) collectObjects() { } check.recordDef(d.decl.Name, obj) } - if d.decl.Type.TParams.NumFields() != 0 && !check.allowVersion(pkg, 1, 18) && !hasTParamError { - check.softErrorf(d.decl.Type.TParams.List[0], _Todo, "type parameters require go1.18 or later") + if d.decl.Type.TypeParams.NumFields() != 0 && !check.allowVersion(pkg, 1, 18) && !hasTParamError { + check.softErrorf(d.decl.Type.TypeParams.List[0], _Todo, "type parameters require go1.18 or later") } info := &declInfo{file: fileScope, fdecl: d.decl} // Methods are not package-level objects but we still track them in the diff --git a/src/go/types/signature.go b/src/go/types/signature.go index 54e2e3e1ea..6b3cf72704 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -151,13 +151,13 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast } } - if ftyp.TParams != nil { - sig.tparams = check.collectTypeParams(ftyp.TParams) + if ftyp.TypeParams != nil { + sig.tparams = check.collectTypeParams(ftyp.TypeParams) // Always type-check method type parameters but complain that they are not allowed. // (A separate check is needed when type-checking interface method signatures because // they don't have a receiver specification.) if recvPar != nil { - check.errorf(ftyp.TParams, _Todo, "methods cannot have type parameters") + check.errorf(ftyp.TypeParams, _Todo, "methods cannot have type parameters") } } -- GitLab From d419f9c6124557e0bf08e00d7848e3e518ac4cbd Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 8 Sep 2021 11:57:04 -0400 Subject: [PATCH 1055/2500] go/types: spell out 'Type' in type parameter APIs As discussed on the go/types proposal (#47916), we should spell out the word 'Type', rather than using 'T'. Change-Id: I5f51255eedc07fea61f909b7ecb3093a7fab765e Reviewed-on: https://go-review.googlesource.com/c/go/+/348376 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/internal/gcimporter/iimport.go | 6 ++-- src/go/types/api_test.go | 2 +- src/go/types/assignments.go | 2 +- src/go/types/call.go | 18 ++++++------ src/go/types/decl.go | 4 +-- src/go/types/index.go | 2 +- src/go/types/instantiate.go | 10 +++---- src/go/types/lookup.go | 12 ++++---- src/go/types/named.go | 42 +++++++++++++-------------- src/go/types/object.go | 4 +-- src/go/types/predicates.go | 8 ++--- src/go/types/signature.go | 28 +++++++++--------- src/go/types/subst.go | 6 ++-- src/go/types/typelists.go | 16 +++++----- src/go/types/typeparam.go | 2 +- src/go/types/typestring.go | 8 ++--- 16 files changed, 85 insertions(+), 85 deletions(-) diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go index 96c2bb3f2c..1fe139da17 100644 --- a/src/go/internal/gcimporter/iimport.go +++ b/src/go/internal/gcimporter/iimport.go @@ -305,7 +305,7 @@ func (r *importReader) obj(name string) { tparams = r.tparamList() } sig := r.signature(nil) - sig.SetTParams(tparams) + sig.SetTypeParams(tparams) r.declare(types.NewFunc(pos, r.currPkg, name, sig)) case 'T', 'U': @@ -317,7 +317,7 @@ func (r *importReader) obj(name string) { // declaration before recursing. obj := types.NewTypeName(pos, r.currPkg, name, nil) named := types.NewNamed(obj, nil, nil) - named.SetTParams(tparams) + named.SetTypeParams(tparams) r.declare(obj) underlying := r.p.typAt(r.uint64(), named).Underlying() @@ -333,7 +333,7 @@ func (r *importReader) obj(name string) { // If the receiver has any targs, set those as the // rparams of the method (since those are the // typeparams being used in the method sig/body). - targs := baseType(msig.Recv().Type()).TArgs() + targs := baseType(msig.Recv().Type()).TypeArgs() if targs.Len() > 0 { rparams := make([]*types.TypeParam, targs.Len()) for i := range rparams { diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index 1e7d6f2cfa..49c054bd7d 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -1851,7 +1851,7 @@ func TestInstantiate(t *testing.T) { // type T should have one type parameter T := pkg.Scope().Lookup("T").Type().(*Named) - if n := T.TParams().Len(); n != 1 { + if n := T.TypeParams().Len(); n != 1 { t.Fatalf("expected 1 type parameter; found %d", n) } diff --git a/src/go/types/assignments.go b/src/go/types/assignments.go index 595f426e10..c46a97f2e2 100644 --- a/src/go/types/assignments.go +++ b/src/go/types/assignments.go @@ -71,7 +71,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { } // A generic (non-instantiated) function value cannot be assigned to a variable. - if sig := asSignature(x.typ); sig != nil && sig.TParams().Len() > 0 { + if sig := asSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { check.errorf(x, _Todo, "cannot use generic function %s without instantiation in %s", x, context) } diff --git a/src/go/types/call.go b/src/go/types/call.go index 8a80cbbd87..39cd67c5f3 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -31,7 +31,7 @@ func (check *Checker) funcInst(x *operand, ix *typeparams.IndexExpr) { // check number of type arguments (got) vs number of type parameters (want) sig := x.typ.(*Signature) - got, want := len(targs), sig.TParams().Len() + got, want := len(targs), sig.TypeParams().Len() if got > want { check.errorf(ix.Indices[got-1], _Todo, "got %d type arguments but want %d", got, want) x.mode = invalid @@ -43,7 +43,7 @@ func (check *Checker) funcInst(x *operand, ix *typeparams.IndexExpr) { inferred := false if got < want { - targs = check.infer(ix.Orig, sig.TParams().list(), targs, nil, nil, true) + targs = check.infer(ix.Orig, sig.TypeParams().list(), targs, nil, nil, true) if targs == nil { // error was already reported x.mode = invalid @@ -65,7 +65,7 @@ func (check *Checker) funcInst(x *operand, ix *typeparams.IndexExpr) { // instantiate function signature res := check.instantiate(x.Pos(), sig, targs, poslist).(*Signature) - assert(res.TParams().Len() == 0) // signature is not generic anymore + assert(res.TypeParams().Len() == 0) // signature is not generic anymore if inferred { check.recordInferred(ix.Orig, targs, res) } @@ -171,7 +171,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { assert(len(targs) == len(ix.Indices)) // check number of type arguments (got) vs number of type parameters (want) - got, want := len(targs), sig.TParams().Len() + got, want := len(targs), sig.TypeParams().Len() if got > want { check.errorf(ix.Indices[want], _Todo, "got %d type arguments but want %d", got, want) check.use(call.Args...) @@ -205,7 +205,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { // if type inference failed, a parametrized result must be invalidated // (operands cannot have a parametrized type) - if x.mode == value && sig.TParams().Len() > 0 && isParameterized(sig.TParams().list(), x.typ) { + if x.mode == value && sig.TypeParams().Len() > 0 && isParameterized(sig.TypeParams().list(), x.typ) { x.mode = invalid } @@ -334,7 +334,7 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type } // infer type arguments and instantiate signature if necessary - if sig.TParams().Len() > 0 { + if sig.TypeParams().Len() > 0 { if !check.allowVersion(check.pkg, 1, 18) { switch call.Fun.(type) { case *ast.IndexExpr, *ast.MultiIndexExpr: @@ -346,21 +346,21 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type } // TODO(gri) provide position information for targs so we can feed // it to the instantiate call for better error reporting - targs := check.infer(call, sig.TParams().list(), targs, sigParams, args, true) + targs := check.infer(call, sig.TypeParams().list(), targs, sigParams, args, true) if targs == nil { return // error already reported } // compute result signature rsig = check.instantiate(call.Pos(), sig, targs, nil).(*Signature) - assert(rsig.TParams().Len() == 0) // signature is not generic anymore + assert(rsig.TypeParams().Len() == 0) // signature is not generic anymore check.recordInferred(call, targs, rsig) // Optimization: Only if the parameter list was adjusted do we // need to compute it from the adjusted list; otherwise we can // simply use the result signature's parameter list. if adjusted { - sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(sig.TParams().list(), targs), nil).(*Tuple) + sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(sig.TypeParams().list(), targs), nil).(*Tuple) } else { sigParams = rsig.params } diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 6dac807c75..d132d30b9d 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -641,13 +641,13 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { named.underlying = under(named) // If the RHS is a type parameter, it must be from this type declaration. - if tpar, _ := named.underlying.(*TypeParam); tpar != nil && tparamIndex(named.TParams().list(), tpar) < 0 { + if tpar, _ := named.underlying.(*TypeParam); tpar != nil && tparamIndex(named.TypeParams().list(), tpar) < 0 { check.errorf(tdecl.Type, _Todo, "cannot use function type parameter %s as RHS in type declaration", tpar) named.underlying = Typ[Invalid] } } -func (check *Checker) collectTypeParams(list *ast.FieldList) *TParamList { +func (check *Checker) collectTypeParams(list *ast.FieldList) *TypeParamList { var tparams []*TypeParam // Declare type parameters up-front, with empty interface as type bound. // The scope of type parameters starts at the beginning of the type parameter diff --git a/src/go/types/index.go b/src/go/types/index.go index 6b8fcc3880..ca04072f7a 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -35,7 +35,7 @@ func (check *Checker) indexExpr(x *operand, e *typeparams.IndexExpr) (isFuncInst return false case value: - if sig := asSignature(x.typ); sig != nil && sig.TParams().Len() > 0 { + if sig := asSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { // function instantiation return true } diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 256a0ed79b..040877829c 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -38,9 +38,9 @@ func Instantiate(env *Environment, typ Type, targs []Type, validate bool) (Type, var tparams []*TypeParam switch t := typ.(type) { case *Named: - tparams = t.TParams().list() + tparams = t.TypeParams().list() case *Signature: - tparams = t.TParams().list() + tparams = t.TypeParams().list() } if i, err := (*Checker)(nil).verify(token.NoPos, tparams, targs); err != nil { return inst, ArgumentError{i, err} @@ -80,9 +80,9 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, posList var tparams []*TypeParam switch t := typ.(type) { case *Named: - tparams = t.TParams().list() + tparams = t.TypeParams().list() case *Signature: - tparams = t.TParams().list() + tparams = t.TypeParams().list() } // Avoid duplicate errors; instantiate will have complained if tparams // and targs do not have the same length. @@ -127,7 +127,7 @@ func (check *Checker) instance(pos token.Pos, typ Type, targs []Type, env *Envir return named case *Signature: - tparams := t.TParams() + tparams := t.TypeParams() if !check.validateTArgLen(pos, tparams.Len(), len(targs)) { return Typ[Invalid] } diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index 862e59401d..f5bdd31a6f 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -319,10 +319,10 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // both methods must have the same number of type parameters ftyp := f.typ.(*Signature) mtyp := m.typ.(*Signature) - if ftyp.TParams().Len() != mtyp.TParams().Len() { + if ftyp.TypeParams().Len() != mtyp.TypeParams().Len() { return m, f } - if ftyp.TParams().Len() > 0 { + if ftyp.TypeParams().Len() > 0 { panic("method with type parameters") } @@ -332,7 +332,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // TODO(gri) is this always correct? what about type bounds? // (Alternative is to rename/subst type parameters and compare.) u := newUnifier(true) - u.x.init(ftyp.TParams().list()) + u.x.init(ftyp.TypeParams().list()) if !u.unify(ftyp, mtyp) { return m, f } @@ -371,10 +371,10 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // both methods must have the same number of type parameters ftyp := f.typ.(*Signature) mtyp := m.typ.(*Signature) - if ftyp.TParams().Len() != mtyp.TParams().Len() { + if ftyp.TypeParams().Len() != mtyp.TypeParams().Len() { return m, f } - if ftyp.TParams().Len() > 0 { + if ftyp.TypeParams().Len() > 0 { panic("method with type parameters") } @@ -385,7 +385,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // In order to compare the signatures, substitute the receiver // type parameters of ftyp with V's instantiation type arguments. // This lazily instantiates the signature of method f. - if Vn != nil && Vn.TParams().Len() > 0 { + if Vn != nil && Vn.TypeParams().Len() > 0 { // Be careful: The number of type arguments may not match // the number of receiver parameters. If so, an error was // reported earlier but the length discrepancy is still diff --git a/src/go/types/named.go b/src/go/types/named.go index c9ef70d7ad..51c4a236da 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -12,15 +12,15 @@ import ( // A Named represents a named (defined) type. type Named struct { check *Checker - info typeInfo // for cycle detection - obj *TypeName // corresponding declared object for declared types; placeholder for instantiated types - orig *Named // original, uninstantiated type - fromRHS Type // type (on RHS of declaration) this *Named type is derived of (for cycle reporting) - underlying Type // possibly a *Named during setup; never a *Named once set up completely - instPos *token.Pos // position information for lazy instantiation, or nil - tparams *TParamList // type parameters, or nil - targs *TypeList // type arguments (after instantiation), or nil - methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily + info typeInfo // for cycle detection + obj *TypeName // corresponding declared object for declared types; placeholder for instantiated types + orig *Named // original, uninstantiated type + fromRHS Type // type (on RHS of declaration) this *Named type is derived of (for cycle reporting) + underlying Type // possibly a *Named during setup; never a *Named once set up completely + instPos *token.Pos // position information for lazy instantiation, or nil + tparams *TypeParamList // type parameters, or nil + targs *TypeList // type arguments (after instantiation), or nil + methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily resolve func(*Named) ([]*TypeParam, Type, []*Func) once sync.Once @@ -58,10 +58,10 @@ func (t *Named) load() *Named { // (necessary because types2 expects the receiver type for methods // on defined interface types to be the Named rather than the // underlying Interface), maybe it should just handle calling - // SetTParams, SetUnderlying, and AddMethod instead? Those + // SetTypeParams, SetUnderlying, and AddMethod instead? Those // methods would need to support reentrant calls though. It would // also make the API more future-proof towards further extensions - // (like SetTParams). + // (like SetTypeParams). tparams, underlying, methods := t.resolve(t) @@ -78,7 +78,7 @@ func (t *Named) load() *Named { } // newNamed is like NewNamed but with a *Checker receiver and additional orig argument. -func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams *TParamList, methods []*Func) *Named { +func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams *TypeParamList, methods []*Func) *Named { typ := &Named{check: check, obj: obj, orig: orig, fromRHS: underlying, underlying: underlying, tparams: tparams, methods: methods} if typ.orig == nil { typ.orig = typ @@ -119,15 +119,15 @@ func (t *Named) _Orig() *Named { return t.orig } // TODO(gri) Come up with a better representation and API to distinguish // between parameterized instantiated and non-instantiated types. -// TParams returns the type parameters of the named type t, or nil. +// TypeParams returns the type parameters of the named type t, or nil. // The result is non-nil for an (originally) parameterized type even if it is instantiated. -func (t *Named) TParams() *TParamList { return t.load().tparams } +func (t *Named) TypeParams() *TypeParamList { return t.load().tparams } -// SetTParams sets the type parameters of the named type t. -func (t *Named) SetTParams(tparams []*TypeParam) { t.load().tparams = bindTParams(tparams) } +// SetTypeParams sets the type parameters of the named type t. +func (t *Named) SetTypeParams(tparams []*TypeParam) { t.load().tparams = bindTParams(tparams) } -// TArgs returns the type arguments used to instantiate the named type t. -func (t *Named) TArgs() *TypeList { return t.targs } +// TypeArgs returns the type arguments used to instantiate the named type t. +func (t *Named) TypeArgs() *TypeList { return t.targs } // NumMethods returns the number of explicit methods whose receiver is named type t. func (t *Named) NumMethods() int { return len(t.load().methods) } @@ -245,8 +245,8 @@ func (n *Named) setUnderlying(typ Type) { func (n *Named) expand(env *Environment) *Named { if n.instPos != nil { // n must be loaded before instantiation, in order to have accurate - // tparams. This is done implicitly by the call to n.TParams, but making it - // explicit is harmless: load is idempotent. + // tparams. This is done implicitly by the call to n.TypeParams, but making + // it explicit is harmless: load is idempotent. n.load() var u Type if n.check.validateTArgLen(*n.instPos, n.tparams.Len(), n.targs.Len()) { @@ -268,7 +268,7 @@ func (n *Named) expand(env *Environment) *Named { // shouldn't return that instance from expand. env.typeForHash(h, n) } - u = n.check.subst(*n.instPos, n.orig.underlying, makeSubstMap(n.TParams().list(), n.targs.list()), env) + u = n.check.subst(*n.instPos, n.orig.underlying, makeSubstMap(n.TypeParams().list(), n.targs.list()), env) } else { u = Typ[Invalid] } diff --git a/src/go/types/object.go b/src/go/types/object.go index 64773e8896..b25fffdf5c 100644 --- a/src/go/types/object.go +++ b/src/go/types/object.go @@ -429,8 +429,8 @@ func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) { if _, ok := typ.(*Basic); ok { return } - if named, _ := typ.(*Named); named != nil && named.TParams().Len() > 0 { - newTypeWriter(buf, qf).tParamList(named.TParams().list()) + if named, _ := typ.(*Named); named != nil && named.TypeParams().Len() > 0 { + newTypeWriter(buf, qf).tParamList(named.TypeParams().list()) } if tname.IsAlias() { buf.WriteString(" =") diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index d4055bb0cc..73d240241e 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -21,7 +21,7 @@ func isNamed(typ Type) bool { func isGeneric(typ Type) bool { // A parameterized type is only instantiated if it doesn't have an instantiation already. named, _ := typ.(*Named) - return named != nil && named.obj != nil && named.targs == nil && named.TParams() != nil + return named != nil && named.obj != nil && named.targs == nil && named.TypeParams() != nil } func is(typ Type, what BasicInfo) bool { @@ -220,7 +220,7 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { // parameter names. if y, ok := y.(*Signature); ok { return x.variadic == y.variadic && - identicalTParams(x.TParams().list(), y.TParams().list(), cmpTags, p) && + identicalTParams(x.TypeParams().list(), y.TypeParams().list(), cmpTags, p) && identical(x.params, y.params, cmpTags, p) && identical(x.results, y.results, cmpTags, p) } @@ -305,8 +305,8 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { x.expand(nil) y.expand(nil) - xargs := x.TArgs().list() - yargs := y.TArgs().list() + xargs := x.TypeArgs().list() + yargs := y.TypeArgs().list() if len(xargs) != len(yargs) { return false diff --git a/src/go/types/signature.go b/src/go/types/signature.go index 6b3cf72704..0561947901 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -21,13 +21,13 @@ type Signature struct { // and store it in the Func Object) because when type-checking a function // literal we call the general type checker which returns a general Type. // We then unpack the *Signature and use the scope for the literal body. - rparams *TParamList // receiver type parameters from left to right, or nil - tparams *TParamList // type parameters from left to right, or nil - scope *Scope // function scope, present for package-local signatures - recv *Var // nil if not a method - params *Tuple // (incoming) parameters from left to right; or nil - results *Tuple // (outgoing) results from left to right; or nil - variadic bool // true if the last parameter's type is of the form ...T (or string, for append built-in only) + rparams *TypeParamList // receiver type parameters from left to right, or nil + tparams *TypeParamList // type parameters from left to right, or nil + scope *Scope // function scope, present for package-local signatures + recv *Var // nil if not a method + params *Tuple // (incoming) parameters from left to right; or nil + results *Tuple // (outgoing) results from left to right; or nil + variadic bool // true if the last parameter's type is of the form ...T (or string, for append built-in only) } // NewSignature returns a new function type for the given receiver, parameters, @@ -55,14 +55,14 @@ func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature { // contain methods whose receiver type is a different interface. func (s *Signature) Recv() *Var { return s.recv } -// TParams returns the type parameters of signature s, or nil. -func (s *Signature) TParams() *TParamList { return s.tparams } +// TypeParams returns the type parameters of signature s, or nil. +func (s *Signature) TypeParams() *TypeParamList { return s.tparams } -// SetTParams sets the type parameters of signature s. -func (s *Signature) SetTParams(tparams []*TypeParam) { s.tparams = bindTParams(tparams) } +// SetTypeParams sets the type parameters of signature s. +func (s *Signature) SetTypeParams(tparams []*TypeParam) { s.tparams = bindTParams(tparams) } // RParams returns the receiver type parameters of signature s, or nil. -func (s *Signature) RParams() *TParamList { return s.rparams } +func (s *Signature) RParams() *TypeParamList { return s.rparams } // SetRParams sets the receiver type params of signature s. func (s *Signature) SetRParams(rparams []*TypeParam) { s.rparams = bindTParams(rparams) } @@ -128,7 +128,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast // again when we type-check the signature. // TODO(gri) maybe the receiver should be marked as invalid instead? if recv, _ := check.genericType(rname, false).(*Named); recv != nil { - recvTParams = recv.TParams().list() + recvTParams = recv.TypeParams().list() } } // provide type parameter bounds @@ -203,7 +203,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast T.expand(nil) // The receiver type may be an instantiated type referred to // by an alias (which cannot have receiver parameters for now). - if T.TArgs() != nil && sig.RParams() == nil { + if T.TypeArgs() != nil && sig.RParams() == nil { check.errorf(atPos(recv.pos), _Todo, "cannot define methods on instantiated type %s", recv.typ) break } diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 452ea5f75f..4f9d76d598 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -182,13 +182,13 @@ func (subst *subster) typ(typ Type) Type { } } - if t.TParams().Len() == 0 { + if t.TypeParams().Len() == 0 { dump(">>> %s is not parameterized", t) return t // type is not parameterized } var newTArgs []Type - assert(t.targs.Len() == t.TParams().Len()) + assert(t.targs.Len() == t.TypeParams().Len()) // already instantiated dump(">>> %s already instantiated", t) @@ -201,7 +201,7 @@ func (subst *subster) typ(typ Type) Type { if new_targ != targ { dump(">>> substituted %d targ %s => %s", i, targ, new_targ) if newTArgs == nil { - newTArgs = make([]Type, t.TParams().Len()) + newTArgs = make([]Type, t.TypeParams().Len()) copy(newTArgs, t.targs.list()) } newTArgs[i] = new_targ diff --git a/src/go/types/typelists.go b/src/go/types/typelists.go index a21683fe87..ba74b8d45a 100644 --- a/src/go/types/typelists.go +++ b/src/go/types/typelists.go @@ -6,20 +6,20 @@ package types import "bytes" -// TParamList holds a list of type parameters. -type TParamList struct{ tparams []*TypeParam } +// TypeParamList holds a list of type parameters. +type TypeParamList struct{ tparams []*TypeParam } // Len returns the number of type parameters in the list. // It is safe to call on a nil receiver. -func (l *TParamList) Len() int { return len(l.list()) } +func (l *TypeParamList) Len() int { return len(l.list()) } // At returns the i'th type parameter in the list. -func (l *TParamList) At(i int) *TypeParam { return l.tparams[i] } +func (l *TypeParamList) At(i int) *TypeParam { return l.tparams[i] } // list is for internal use where we expect a []*TypeParam. // TODO(rfindley): list should probably be eliminated: we can pass around a -// TParamList instead. -func (l *TParamList) list() []*TypeParam { +// TypeParamList instead. +func (l *TypeParamList) list() []*TypeParam { if l == nil { return nil } @@ -66,7 +66,7 @@ func (l *TypeList) String() string { // ---------------------------------------------------------------------------- // Implementation -func bindTParams(list []*TypeParam) *TParamList { +func bindTParams(list []*TypeParam) *TypeParamList { if len(list) == 0 { return nil } @@ -76,5 +76,5 @@ func bindTParams(list []*TypeParam) *TParamList { } typ.index = i } - return &TParamList{tparams: list} + return &TypeParamList{tparams: list} } diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index 29d44f4cb2..a0f2a3acd0 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -29,7 +29,7 @@ type TypeParam struct { } // NewTypeParam returns a new TypeParam. Type parameters may be set on a Named -// or Signature type by calling SetTParams. Setting a type parameter on more +// or Signature type by calling SetTypeParams. Setting a type parameter on more // than one type will result in a panic. // // The bound argument can be nil, and set later via SetConstraint. diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 362b44a2c2..7e971c0325 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -238,9 +238,9 @@ func (w *typeWriter) typ(typ Type) { if t.targs != nil { // instantiated type w.typeList(t.targs.list()) - } else if w.env == nil && t.TParams().Len() != 0 { // For type hashing, don't need to format the TParams + } else if w.env == nil && t.TypeParams().Len() != 0 { // For type hashing, don't need to format the TypeParams // parameterized type - w.tParamList(t.TParams().list()) + w.tParamList(t.TypeParams().list()) } case *TypeParam: @@ -359,8 +359,8 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) { } func (w *typeWriter) signature(sig *Signature) { - if sig.TParams().Len() != 0 { - w.tParamList(sig.TParams().list()) + if sig.TypeParams().Len() != 0 { + w.tParamList(sig.TypeParams().list()) } w.tuple(sig.params, sig.variadic) -- GitLab From c8d4fe2adc556317f75c2ebad195568ad5ff9644 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 8 Sep 2021 09:58:44 -0400 Subject: [PATCH 1056/2500] go/types: temporarily pin the Checker to Interface during checking While type checking expressions involving interface types, it is possible that their type set is used before delayed actions are processed. As a result, computeInterfaceTypeSet is called with a nil checker, and errors in the interface type definition result in panics (see #48234). To avoid the panics, store a *Checker on Interface for use in between checking of the interface type expression and processing of delayed actions. Fixes #48234 Change-Id: I5509bc1c01b55edac52446b9e075fbe8fcc01874 Reviewed-on: https://go-review.googlesource.com/c/go/+/348371 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/interface.go | 15 ++++++++++++--- src/go/types/sizeof_test.go | 2 +- src/go/types/testdata/fixedbugs/issue48234.go2 | 10 ++++++++++ src/go/types/universe.go | 4 ++-- 4 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue48234.go2 diff --git a/src/go/types/interface.go b/src/go/types/interface.go index 2211e37c59..c67aca7a20 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -14,6 +14,7 @@ import ( // An Interface represents an interface type. type Interface struct { + check *Checker // for error reporting; nil once type set is computed obj *TypeName // type name object defining this interface; or nil (for better error messages) methods []*Func // ordered list of explicitly declared methods embeddeds []Type // ordered list of explicitly embedded elements @@ -24,7 +25,7 @@ type Interface struct { } // typeSet returns the type set for interface t. -func (t *Interface) typeSet() *_TypeSet { return computeInterfaceTypeSet(nil, token.NoPos, t) } +func (t *Interface) typeSet() *_TypeSet { return computeInterfaceTypeSet(t.check, token.NoPos, t) } // emptyInterface represents the empty (completed) interface var emptyInterface = Interface{complete: true, tset: &topTypeSet} @@ -220,7 +221,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d } // All methods and embedded elements for this interface are collected; - // i.e., this interface is may be used in a type set computation. + // i.e., this interface may be used in a type set computation. ityp.complete = true if len(ityp.methods) == 0 && len(ityp.embeddeds) == 0 { @@ -236,7 +237,15 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d // Compute type set with a non-nil *Checker as soon as possible // to report any errors. Subsequent uses of type sets will use // this computed type set and won't need to pass in a *Checker. - check.later(func() { computeInterfaceTypeSet(check, iface.Pos(), ityp) }) + // + // Pin the checker to the interface type in the interim, in case the type set + // must be used before delayed funcs are processed (see issue #48234). + // TODO(rfindley): clean up use of *Checker with computeInterfaceTypeSet + ityp.check = check + check.later(func() { + computeInterfaceTypeSet(check, iface.Pos(), ityp) + ityp.check = nil + }) } func flattenUnion(list []ast.Expr, x ast.Expr) []ast.Expr { diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index c2f5b3c333..f64f732884 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -27,7 +27,7 @@ func TestSizeof(t *testing.T) { {Tuple{}, 12, 24}, {Signature{}, 28, 56}, {Union{}, 16, 32}, - {Interface{}, 40, 80}, + {Interface{}, 44, 88}, {Map{}, 16, 32}, {Chan{}, 12, 24}, {Named{}, 72, 136}, diff --git a/src/go/types/testdata/fixedbugs/issue48234.go2 b/src/go/types/testdata/fixedbugs/issue48234.go2 new file mode 100644 index 0000000000..e069930c42 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue48234.go2 @@ -0,0 +1,10 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +var _ = interface{ + m() + m /* ERROR "duplicate method" */ () +}(nil) diff --git a/src/go/types/universe.go b/src/go/types/universe.go index a2acfb5f69..6045c61c30 100644 --- a/src/go/types/universe.go +++ b/src/go/types/universe.go @@ -89,7 +89,7 @@ func defPredeclaredTypes() { res := NewVar(token.NoPos, nil, "", Typ[String]) sig := NewSignature(nil, nil, NewTuple(res), false) err := NewFunc(token.NoPos, nil, "Error", sig) - ityp := &Interface{obj, []*Func{err}, nil, nil, true, nil} + ityp := &Interface{nil, obj, []*Func{err}, nil, nil, true, nil} computeInterfaceTypeSet(nil, token.NoPos, ityp) // prevent races due to lazy computation of tset typ := NewNamed(obj, ityp, nil) sig.recv = NewVar(token.NoPos, nil, "", typ) @@ -100,7 +100,7 @@ func defPredeclaredTypes() { { obj := NewTypeName(token.NoPos, nil, "comparable", nil) obj.setColor(black) - ityp := &Interface{obj, nil, nil, nil, true, &_TypeSet{true, nil, allTermlist}} + ityp := &Interface{nil, obj, nil, nil, nil, true, &_TypeSet{true, nil, allTermlist}} NewNamed(obj, ityp, nil) def(obj) } -- GitLab From 37c9552e065fb4331d8cba84c12392806f1ecbbe Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Fri, 3 Sep 2021 13:33:37 -0400 Subject: [PATCH 1057/2500] cmd/go: improve the creation and editing of go.work files This change changes go.work files so that directory paths are clearly distinguished from module paths by either being rooted absolute paths or starting with '.' or '..' path elements if they are relative paths. go mod initwork now checks that the go.work file doesn't already exist before creating it, and gomod initwork and gomod editwork look up the module path corresponding to a directory and write it to the directory directive's comment. For #45713 Change-Id: I6983779059b7de6fc83d359280ceffb263f6b641 Reviewed-on: https://go-review.googlesource.com/c/go/+/347591 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/modcmd/editwork.go | 11 +++++-- src/cmd/go/internal/modload/init.go | 39 +++++++++-------------- src/cmd/go/internal/modload/modfile.go | 40 ++++++++++++++++++++++++ src/cmd/go/testdata/script/work.txt | 3 ++ src/cmd/go/testdata/script/work_edit.txt | 30 ++++++++++-------- 5 files changed, 83 insertions(+), 40 deletions(-) diff --git a/src/cmd/go/internal/modcmd/editwork.go b/src/cmd/go/internal/modcmd/editwork.go index f05d9245e7..29895b1620 100644 --- a/src/cmd/go/internal/modcmd/editwork.go +++ b/src/cmd/go/internal/modcmd/editwork.go @@ -15,6 +15,7 @@ import ( "encoding/json" "errors" "os" + "path/filepath" "strings" "golang.org/x/mod/modfile" @@ -191,7 +192,13 @@ func runEditwork(ctx context.Context, cmd *base.Command, args []string) { // flagEditworkDirectory implements the -directory flag. func flagEditworkDirectory(arg string) { workedits = append(workedits, func(f *modfile.WorkFile) { - if err := f.AddDirectory(arg, ""); err != nil { + _, mf, err := modload.ReadModFile(filepath.Join(arg, "go.mod"), nil) + modulePath := "" + if err == nil { + modulePath = mf.Module.Mod.Path + } + f.AddDirectory(modload.ToDirectoryPath(arg), modulePath) + if err := f.AddDirectory(modload.ToDirectoryPath(arg), ""); err != nil { base.Fatalf("go mod: -directory=%s: %v", arg, err) } }) @@ -200,7 +207,7 @@ func flagEditworkDirectory(arg string) { // flagEditworkDropDirectory implements the -dropdirectory flag. func flagEditworkDropDirectory(arg string) { workedits = append(workedits, func(f *modfile.WorkFile) { - if err := f.DropDirectory(arg); err != nil { + if err := f.DropDirectory(modload.ToDirectoryPath(arg)); err != nil { base.Fatalf("go mod: -dropdirectory=%s: %v", arg, err) } }) diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index bc155c7310..a1016ec5a3 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -634,29 +634,10 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { var indices []*modFileIndex for _, modroot := range modRoots { gomod := modFilePath(modroot) - var data []byte - var err error - if gomodActual, ok := fsys.OverlayPath(gomod); ok { - // Don't lock go.mod if it's part of the overlay. - // On Plan 9, locking requires chmod, and we don't want to modify any file - // in the overlay. See #44700. - data, err = os.ReadFile(gomodActual) - } else { - data, err = lockedfile.Read(gomodActual) - } - if err != nil { - base.Fatalf("go: %v", err) - } - var fixed bool - f, err := modfile.Parse(gomod, data, fixVersion(ctx, &fixed)) + data, f, err := ReadModFile(gomod, fixVersion(ctx, &fixed)) if err != nil { - // Errors returned by modfile.Parse begin with file:line. - base.Fatalf("go: errors parsing go.mod:\n%s\n", err) - } - if f.Module == nil { - // No module declaration. Must add module path. - base.Fatalf("go: no module declaration in go.mod. To specify the module path:\n\tgo mod edit -module=example.com/mod") + base.Fatalf("go: %v", err) } modFiles = append(modFiles, f) @@ -819,7 +800,9 @@ func CreateModFile(ctx context.Context, modPath string) { // CreateWorkFile initializes a new workspace by creating a go.work file. func CreateWorkFile(ctx context.Context, workFile string, modDirs []string) { - _ = TODOWorkspaces("Report an error if the file already exists.") + if _, err := fsys.Stat(workFile); err == nil { + base.Fatalf("go: %s already exists", workFile) + } goV := LatestGoVersion() // Use current Go version by default workF := new(modfile.WorkFile) @@ -827,12 +810,18 @@ func CreateWorkFile(ctx context.Context, workFile string, modDirs []string) { workF.AddGoStmt(goV) for _, dir := range modDirs { - _ = TODOWorkspaces("Add the module path of the module.") - workF.AddDirectory(dir, "") + _, f, err := ReadModFile(filepath.Join(dir, "go.mod"), nil) + if err != nil { + if os.IsNotExist(err) { + base.Fatalf("go: creating workspace file: no go.mod file exists in directory %v", dir) + } + base.Fatalf("go: error parsing go.mod in directory %s: %v", dir, err) + } + workF.AddDirectory(ToDirectoryPath(dir), f.Module.Mod.Path) } data := modfile.Format(workF.Syntax) - lockedfile.Write(workFile, bytes.NewReader(data), 0644) + lockedfile.Write(workFile, bytes.NewReader(data), 0666) } // fixVersion returns a modfile.VersionFixer implemented using the Query function. diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index 79ac1227ca..bf05e92ba2 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -47,6 +47,34 @@ const ( separateIndirectVersionV = "v1.17" ) +// ReadModFile reads and parses the mod file at gomod. ReadModFile properly applies the +// overlay, locks the file while reading, and applies fix, if applicable. +func ReadModFile(gomod string, fix modfile.VersionFixer) (data []byte, f *modfile.File, err error) { + if gomodActual, ok := fsys.OverlayPath(gomod); ok { + // Don't lock go.mod if it's part of the overlay. + // On Plan 9, locking requires chmod, and we don't want to modify any file + // in the overlay. See #44700. + data, err = os.ReadFile(gomodActual) + } else { + data, err = lockedfile.Read(gomodActual) + } + if err != nil { + return nil, nil, err + } + + f, err = modfile.Parse(gomod, data, fix) + if err != nil { + // Errors returned by modfile.Parse begin with file:line. + return nil, nil, fmt.Errorf("errors parsing go.mod:\n%s\n", err) + } + if f.Module == nil { + // No module declaration. Must add module path. + return nil, nil, errors.New("no module declaration in go.mod. To specify the module path:\n\tgo mod edit -module=example.com/mod") + } + + return data, f, err +} + // modFileGoVersion returns the (non-empty) Go version at which the requirements // in modFile are interpreted, or the latest Go version if modFile is nil. func modFileGoVersion(modFile *modfile.File) string { @@ -739,3 +767,15 @@ func queryLatestVersionIgnoringRetractions(ctx context.Context, path string) (la } var latestVersionIgnoringRetractionsCache par.Cache // path → queryLatestVersionIgnoringRetractions result + +// ToDirectoryPath adds a prefix if necessary so that path in unambiguously +// an absolute path or a relative path starting with a '.' or '..' +// path component. +func ToDirectoryPath(path string) string { + if modfile.IsDirectoryPath(path) { + return path + } + // The path is not a relative path or an absolute path, so make it relative + // to the current directory. + return "./" + filepath.ToSlash(filepath.Clean(path)) +} diff --git a/src/cmd/go/testdata/script/work.txt b/src/cmd/go/testdata/script/work.txt index 529c1c0bfd..657cd060cc 100644 --- a/src/cmd/go/testdata/script/work.txt +++ b/src/cmd/go/testdata/script/work.txt @@ -1,3 +1,6 @@ +! go mod initwork doesnotexist +stderr 'go: creating workspace file: no go.mod file exists in directory doesnotexist' + go mod initwork ./a ./b cmp go.work go.work.want diff --git a/src/cmd/go/testdata/script/work_edit.txt b/src/cmd/go/testdata/script/work_edit.txt index 0de4069865..001ac7f65c 100644 --- a/src/cmd/go/testdata/script/work_edit.txt +++ b/src/cmd/go/testdata/script/work_edit.txt @@ -33,32 +33,36 @@ cmp stdout go.work.want_json go mod editwork -print -fmt -workfile unformatted cmp stdout formatted +-- m/go.mod -- +module m + +go 1.18 -- go.work.want_initial -- go 1.18 -directory m +directory ./m -- go.work.want_directory_n -- go 1.18 directory ( - m - n + ./m + ./n ) -- go.work.want_go_118 -- go 1.18 directory ( - m - n + ./m + ./n ) -- go.work.want_dropdirectory_m -- go 1.18 -directory n +directory ./n -- go.work.want_add_replaces -- go 1.18 -directory n +directory ./n replace ( x.1 v1.3.0 => y.1 v1.4.0 @@ -69,9 +73,9 @@ go 1.18 directory ( ../a + ./c + ./n /b - c - n ) replace ( @@ -83,7 +87,7 @@ go 1.18 directory ( ../a - c + ./c ) replace ( @@ -95,7 +99,7 @@ go 1.18 directory ( ../a - c + ./c ) replace x.1 v1.3.0 => y.1 v1.4.0 @@ -104,7 +108,7 @@ go 1.19 directory ( ../a - b + ./b ) replace x.1 v1.4.0 => ../z @@ -116,7 +120,7 @@ replace x.1 v1.4.0 => ../z "DiskPath": "../a" }, { - "DiskPath": "b" + "DiskPath": "./b" } ], "Replace": [ -- GitLab From 65f0d24f73fa5386bf921393cbd26bb8f9cead03 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Fri, 3 Sep 2021 18:11:00 -0400 Subject: [PATCH 1058/2500] cmd/go: print offending -mod value in workspace mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Workspace mode only allows -mod to be set to 'readonly'. When returning the error for other values of -mod, specify the the value in the error so it's easier to see what's going on when the go command is invoked through another tool. For #45713, #48186 Change-Id: I3ba206a71c7a20c18aeccfa48f3c9dc935a180a4 Reviewed-on: https://go-review.googlesource.com/c/go/+/347593 Trust: Michael Matloob Trust: Daniel Martí Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Jay Conrod Reviewed-by: Daniel Martí Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/modload/init.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index a1016ec5a3..a855e6c851 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -976,9 +976,9 @@ func requirementsFromModFiles(ctx context.Context, modFiles []*modfile.File) *Re func setDefaultBuildMod() { if cfg.BuildModExplicit { if inWorkspaceMode() && cfg.BuildMod != "readonly" { - base.Fatalf("go: -mod may only be set to readonly when in workspace mode." + - "\n\tRemove the -mod flag to use the default readonly value," + - "\n\tor set -workfile=off to disable workspace mode.") + base.Fatalf("go: -mod may only be set to readonly when in workspace mode, but it is set to %q"+ + "\n\tRemove the -mod flag to use the default readonly value,"+ + "\n\tor set -workfile=off to disable workspace mode.", cfg.BuildMod) } // Don't override an explicit '-mod=' argument. return -- GitLab From e9674e553ce941c1c0558892852d299a35fa2178 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Wed, 8 Sep 2021 14:06:52 -0400 Subject: [PATCH 1059/2500] [dev.fuzz] internal/fuzz: fix panic when marshaling data The coordinator needs to marshal data that was provided via f.Add. However, it was also attempting to marshal data that was in testdata, which was not needed, and was causing a panic. This change fixes this. Fixes golang/go#48228 Change-Id: I1256c5a287b5a09d2f8cca59beb0f0fc06cc3554 Reviewed-on: https://go-review.googlesource.com/c/go/+/348381 Trust: Katie Hockman Run-TryBot: Katie Hockman Reviewed-by: Jay Conrod --- src/cmd/go/testdata/script/test_fuzz.txt | 23 +++++++++++++++++++++++ src/internal/fuzz/fuzz.go | 4 ++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt index d3c7b4d55f..a25f0fba3f 100644 --- a/src/cmd/go/testdata/script/test_fuzz.txt +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -160,6 +160,21 @@ stdout ok ! stdout FAIL ! stdout 'fatal here' +# Test pass with testdata and f.Add seed corpus +go test -run FuzzPassString corpustesting/fuzz_testdata_corpus_test.go +stdout ok +! stdout FAIL + +# Fuzzing pass with testdata and f.Add seed corpus (skip running tests first) +go test -run=None -fuzz=FuzzPassString corpustesting/fuzz_testdata_corpus_test.go -fuzztime=10x +stdout ok +! stdout FAIL + +# Fuzzing pass with testdata and f.Add seed corpus +go test -run=FuzzPassString -fuzz=FuzzPassString corpustesting/fuzz_testdata_corpus_test.go -fuzztime=10x +stdout ok +! stdout FAIL + # Test panic with malformed seed corpus ! go test -run FuzzFail corpustesting/fuzz_testdata_corpus_test.go ! stdout ^ok @@ -413,6 +428,11 @@ func FuzzPass(f *testing.F) { fuzzFn(f) } +func FuzzPassString(f *testing.F) { + f.Add("some seed corpus") + f.Fuzz(func(*testing.T, string) {}) +} + func FuzzPanic(f *testing.F) { f.Fuzz(func(t *testing.T, b []byte) {}) } @@ -431,6 +451,9 @@ go test fuzz v1 -- corpustesting/testdata/corpus/FuzzPass/1 -- go test fuzz v1 []byte("00000") +-- corpustesting/testdata/corpus/FuzzPassString/1 -- +go test fuzz v1 +string("hello") -- corpustesting/testdata/corpus/FuzzPanic/1 -- malformed -- corpustesting/testdata/corpus/FuzzInNestedDir/anotherdir/1 -- diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 5b940e4929..f36569b4cc 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -576,9 +576,9 @@ type coordinator struct { } func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { - // Make sure all of the seed corpus has marshalled data. + // Make sure all of the seed corpus given by f.Add has marshalled data. for i := range opts.Seed { - if opts.Seed[i].Data == nil { + if opts.Seed[i].Data == nil && opts.Seed[i].Values != nil { opts.Seed[i].Data = marshalCorpusFile(opts.Seed[i].Values...) } } -- GitLab From f4f137a1434725f652f924a57a5ae51c9a477d03 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Thu, 2 Sep 2021 14:57:43 -0700 Subject: [PATCH 1060/2500] [dev.fuzz] internal/fuzz: only reconstruct inputs when needed on RPC return If the fuzz RPC finds no error and no new coverage, there's no point in reconstructing the last value. If the minimize RPC does not succeed in minimizing, either because the error can't be reproduced, or new coverage can't be reproduced, or a new error is found with the input, don't marshal or unmarshal the input. Just use the original. Change-Id: I3b0f89b8656a2b36066d82efefac0fff4a61fbee Reviewed-on: https://go-review.googlesource.com/c/go/+/347233 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/internal/fuzz/worker.go | 66 +++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 32b13662c8..344c1b45b7 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -775,7 +775,9 @@ func (ws *workerServer) minimize(ctx context.Context, args minimizeArgs) (resp m // to shared memory after completing minimization. If the worker terminates // unexpectedly before then, the coordinator will use the original input. resp.Success, err = ws.minimizeInput(ctx, vals, &mem.header().count, args.Limit, args.KeepCoverage) - writeToMem(vals, mem) + if resp.Success { + writeToMem(vals, mem) + } if err != nil { resp.Err = err.Error() } else if resp.Success { @@ -1008,7 +1010,6 @@ func (wc *workerClient) minimize(ctx context.Context, entryIn CorpusEntry, args } mem.setValue(inp) wc.memMu <- mem - defer func() { wc.memMu <- mem }() c := call{Minimize: &args} callErr := wc.callLocked(ctx, c, &resp) @@ -1016,13 +1017,24 @@ func (wc *workerClient) minimize(ctx context.Context, entryIn CorpusEntry, args if !ok { return CorpusEntry{}, minimizeResponse{}, errSharedMemClosed } - entryOut.Data = mem.valueCopy() - h := sha256.Sum256(entryOut.Data) - name := fmt.Sprintf("%x", h[:4]) - entryOut.Name = name - entryOut.Parent = entryIn.Parent - entryOut.Generation = entryIn.Generation + defer func() { wc.memMu <- mem }() resp.Count = mem.header().count + if resp.Success { + entryOut.Data = mem.valueCopy() + entryOut.Values, err = unmarshalCorpusFile(entryOut.Data) + h := sha256.Sum256(entryOut.Data) + name := fmt.Sprintf("%x", h[:4]) + entryOut.Name = name + entryOut.Parent = entryIn.Parent + entryOut.Generation = entryIn.Generation + if err != nil { + panic(fmt.Sprintf("workerClient.minimize unmarshaling minimized value: %v", err)) + } + } else { + // Did not minimize, but the original input may still be interesting, + // for example, if there was an error. + entryOut = entryIn + } return entryOut, resp, callErr } @@ -1056,23 +1068,27 @@ func (wc *workerClient) fuzz(ctx context.Context, entryIn CorpusEntry, args fuzz if !bytes.Equal(inp, mem.valueRef()) { panic("workerServer.fuzz modified input") } - valuesOut, err := unmarshalCorpusFile(inp) - if err != nil { - panic(fmt.Sprintf("unmarshaling fuzz input value after call: %v", err)) - } - wc.m.r.restore(mem.header().randState, mem.header().randInc) - for i := int64(0); i < mem.header().count; i++ { - wc.m.mutate(valuesOut, cap(mem.valueRef())) - } - dataOut := marshalCorpusFile(valuesOut...) - - h := sha256.Sum256(dataOut) - name := fmt.Sprintf("%x", h[:4]) - entryOut = CorpusEntry{ - Name: name, - Parent: entryIn.Name, - Data: dataOut, - Generation: entryIn.Generation + 1, + needEntryOut := callErr != nil || resp.Err != "" || + (!args.CoverageOnly && resp.CoverageData != nil) + if needEntryOut { + valuesOut, err := unmarshalCorpusFile(inp) + if err != nil { + panic(fmt.Sprintf("unmarshaling fuzz input value after call: %v", err)) + } + wc.m.r.restore(mem.header().randState, mem.header().randInc) + for i := int64(0); i < mem.header().count; i++ { + wc.m.mutate(valuesOut, cap(mem.valueRef())) + } + dataOut := marshalCorpusFile(valuesOut...) + + h := sha256.Sum256(dataOut) + name := fmt.Sprintf("%x", h[:4]) + entryOut = CorpusEntry{ + Name: name, + Parent: entryIn.Name, + Data: dataOut, + Generation: entryIn.Generation + 1, + } } return entryOut, resp, callErr -- GitLab From 0406d3a8e5301bd5fd697018e6e8fbb9c75eeb42 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 8 Sep 2021 15:51:10 -0400 Subject: [PATCH 1061/2500] go/ast: rename MultiIndexExpr to IndexListExpr As discussed in #47781, IndexListExpr is one character shorter and has the advantage of being next to IndexExpr in documentation. Updates #47781 Change-Id: I709d5c1a79b4f9aebcd6445e4ab0cd6dae45bab7 Reviewed-on: https://go-review.googlesource.com/c/go/+/348609 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/ast/ast.go | 10 +++++----- src/go/ast/walk.go | 2 +- src/go/internal/typeparams/typeparams.go | 13 ++++++------- src/go/parser/parser.go | 4 ++-- src/go/printer/nodes.go | 2 +- src/go/types/call.go | 2 +- src/go/types/expr.go | 2 +- src/go/types/exprstring.go | 2 +- src/go/types/resolver.go | 2 +- src/go/types/signature.go | 2 +- src/go/types/struct.go | 2 +- src/go/types/typexpr.go | 2 +- 12 files changed, 22 insertions(+), 23 deletions(-) diff --git a/src/go/ast/ast.go b/src/go/ast/ast.go index f9223e4f91..70d0912f67 100644 --- a/src/go/ast/ast.go +++ b/src/go/ast/ast.go @@ -344,9 +344,9 @@ type ( Rbrack token.Pos // position of "]" } - // A MultiIndexExpr node represents an expression followed by multiple + // An IndexListExpr node represents an expression followed by multiple // indices. - MultiIndexExpr struct { + IndexListExpr struct { X Expr // expression Lbrack token.Pos // position of "[" Indices []Expr // index expressions @@ -496,7 +496,7 @@ func (x *CompositeLit) Pos() token.Pos { func (x *ParenExpr) Pos() token.Pos { return x.Lparen } func (x *SelectorExpr) Pos() token.Pos { return x.X.Pos() } func (x *IndexExpr) Pos() token.Pos { return x.X.Pos() } -func (x *MultiIndexExpr) Pos() token.Pos { return x.X.Pos() } +func (x *IndexListExpr) Pos() token.Pos { return x.X.Pos() } func (x *SliceExpr) Pos() token.Pos { return x.X.Pos() } func (x *TypeAssertExpr) Pos() token.Pos { return x.X.Pos() } func (x *CallExpr) Pos() token.Pos { return x.Fun.Pos() } @@ -530,7 +530,7 @@ func (x *CompositeLit) End() token.Pos { return x.Rbrace + 1 } func (x *ParenExpr) End() token.Pos { return x.Rparen + 1 } func (x *SelectorExpr) End() token.Pos { return x.Sel.End() } func (x *IndexExpr) End() token.Pos { return x.Rbrack + 1 } -func (x *MultiIndexExpr) End() token.Pos { return x.Rbrack + 1 } +func (x *IndexListExpr) End() token.Pos { return x.Rbrack + 1 } func (x *SliceExpr) End() token.Pos { return x.Rbrack + 1 } func (x *TypeAssertExpr) End() token.Pos { return x.Rparen + 1 } func (x *CallExpr) End() token.Pos { return x.Rparen + 1 } @@ -562,7 +562,7 @@ func (*CompositeLit) exprNode() {} func (*ParenExpr) exprNode() {} func (*SelectorExpr) exprNode() {} func (*IndexExpr) exprNode() {} -func (*MultiIndexExpr) exprNode() {} +func (*IndexListExpr) exprNode() {} func (*SliceExpr) exprNode() {} func (*TypeAssertExpr) exprNode() {} func (*CallExpr) exprNode() {} diff --git a/src/go/ast/walk.go b/src/go/ast/walk.go index 530735e76f..308662f633 100644 --- a/src/go/ast/walk.go +++ b/src/go/ast/walk.go @@ -116,7 +116,7 @@ func Walk(v Visitor, node Node) { Walk(v, n.X) Walk(v, n.Index) - case *MultiIndexExpr: + case *IndexListExpr: Walk(v, n.X) for _, index := range n.Indices { Walk(v, index) diff --git a/src/go/internal/typeparams/typeparams.go b/src/go/internal/typeparams/typeparams.go index 9bf4f7bf97..3f84f2f0d0 100644 --- a/src/go/internal/typeparams/typeparams.go +++ b/src/go/internal/typeparams/typeparams.go @@ -21,7 +21,7 @@ func PackIndexExpr(x ast.Expr, lbrack token.Pos, exprs []ast.Expr, rbrack token. Rbrack: rbrack, } default: - return &ast.MultiIndexExpr{ + return &ast.IndexListExpr{ X: x, Lbrack: lbrack, Indices: exprs, @@ -30,25 +30,24 @@ func PackIndexExpr(x ast.Expr, lbrack token.Pos, exprs []ast.Expr, rbrack token. } } -// IndexExpr wraps an ast.IndexExpr or ast.MultiIndexExpr into the -// MultiIndexExpr interface. +// IndexExpr wraps an ast.IndexExpr or ast.IndexListExpr. // // Orig holds the original ast.Expr from which this IndexExpr was derived. type IndexExpr struct { - Orig ast.Expr // the wrapped expr, which may be distinct from MultiIndexExpr below. - *ast.MultiIndexExpr + Orig ast.Expr // the wrapped expr, which may be distinct from the IndexListExpr below. + *ast.IndexListExpr } func UnpackIndexExpr(n ast.Node) *IndexExpr { switch e := n.(type) { case *ast.IndexExpr: - return &IndexExpr{e, &ast.MultiIndexExpr{ + return &IndexExpr{e, &ast.IndexListExpr{ X: e.X, Lbrack: e.Lbrack, Indices: []ast.Expr{e.Index}, Rbrack: e.Rbrack, }} - case *ast.MultiIndexExpr: + case *ast.IndexListExpr: return &IndexExpr{e, e} } return nil diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go index 5c0af8d3b8..049515656c 100644 --- a/src/go/parser/parser.go +++ b/src/go/parser/parser.go @@ -1570,7 +1570,7 @@ func (p *parser) checkExpr(x ast.Expr) ast.Expr { panic("unreachable") case *ast.SelectorExpr: case *ast.IndexExpr: - case *ast.MultiIndexExpr: + case *ast.IndexListExpr: case *ast.SliceExpr: case *ast.TypeAssertExpr: // If t.Type == nil we have a type assertion of the form @@ -1660,7 +1660,7 @@ func (p *parser) parsePrimaryExpr() (x ast.Expr) { return } // x is possibly a composite literal type - case *ast.IndexExpr, *ast.MultiIndexExpr: + case *ast.IndexExpr, *ast.IndexListExpr: if p.exprLev < 0 { return } diff --git a/src/go/printer/nodes.go b/src/go/printer/nodes.go index 9ce0115426..053a8ef174 100644 --- a/src/go/printer/nodes.go +++ b/src/go/printer/nodes.go @@ -873,7 +873,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) { p.expr0(x.Index, depth+1) p.print(x.Rbrack, token.RBRACK) - case *ast.MultiIndexExpr: + case *ast.IndexListExpr: // TODO(gri): as for IndexExpr, should treat [] like parentheses and undo // one level of depth p.expr1(x.X, token.HighestPrec, 1) diff --git a/src/go/types/call.go b/src/go/types/call.go index 39cd67c5f3..3710756c29 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -337,7 +337,7 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type if sig.TypeParams().Len() > 0 { if !check.allowVersion(check.pkg, 1, 18) { switch call.Fun.(type) { - case *ast.IndexExpr, *ast.MultiIndexExpr: + case *ast.IndexExpr, *ast.IndexListExpr: ix := typeparams.UnpackIndexExpr(call.Fun) check.softErrorf(inNode(call.Fun, ix.Lbrack), _Todo, "function instantiation requires go1.18 or later") default: diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 5ca4edebcb..007205a9fb 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -1392,7 +1392,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { case *ast.SelectorExpr: check.selector(x, e) - case *ast.IndexExpr, *ast.MultiIndexExpr: + case *ast.IndexExpr, *ast.IndexListExpr: ix := typeparams.UnpackIndexExpr(e) if check.indexExpr(x, ix) { check.funcInst(x, ix) diff --git a/src/go/types/exprstring.go b/src/go/types/exprstring.go index aee8a5ba5f..06e7a9dcb4 100644 --- a/src/go/types/exprstring.go +++ b/src/go/types/exprstring.go @@ -67,7 +67,7 @@ func WriteExpr(buf *bytes.Buffer, x ast.Expr) { buf.WriteByte('.') buf.WriteString(x.Sel.Name) - case *ast.IndexExpr, *ast.MultiIndexExpr: + case *ast.IndexExpr, *ast.IndexListExpr: ix := typeparams.UnpackIndexExpr(x) WriteExpr(buf, ix.X) buf.WriteByte('[') diff --git a/src/go/types/resolver.go b/src/go/types/resolver.go index b04a673ab7..486c09220b 100644 --- a/src/go/types/resolver.go +++ b/src/go/types/resolver.go @@ -513,7 +513,7 @@ L: // unpack receiver type // unpack type parameters, if any switch rtyp.(type) { - case *ast.IndexExpr, *ast.MultiIndexExpr: + case *ast.IndexExpr, *ast.IndexListExpr: ix := typeparams.UnpackIndexExpr(rtyp) rtyp = ix.X if unpackParams { diff --git a/src/go/types/signature.go b/src/go/types/signature.go index 0561947901..88ea07d5d3 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -326,7 +326,7 @@ func isubst(x ast.Expr, smap map[*ast.Ident]*ast.Ident) ast.Expr { new.X = X return &new } - case *ast.IndexExpr, *ast.MultiIndexExpr: + case *ast.IndexExpr, *ast.IndexListExpr: ix := typeparams.UnpackIndexExpr(x) var newIndexes []ast.Expr for i, index := range ix.Indices { diff --git a/src/go/types/struct.go b/src/go/types/struct.go index f6e6f2a5e6..24a2435ff7 100644 --- a/src/go/types/struct.go +++ b/src/go/types/struct.go @@ -176,7 +176,7 @@ func embeddedFieldIdent(e ast.Expr) *ast.Ident { return e.Sel case *ast.IndexExpr: return embeddedFieldIdent(e.X) - case *ast.MultiIndexExpr: + case *ast.IndexListExpr: return embeddedFieldIdent(e.X) } return nil // invalid embedded field diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index af56297144..6b4a3538b6 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -258,7 +258,7 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) { check.errorf(&x, _NotAType, "%s is not a type", &x) } - case *ast.IndexExpr, *ast.MultiIndexExpr: + case *ast.IndexExpr, *ast.IndexListExpr: ix := typeparams.UnpackIndexExpr(e) if !check.allowVersion(check.pkg, 1, 18) { check.softErrorf(inNode(e, ix.Lbrack), _Todo, "type instantiation requires go1.18 or later") -- GitLab From 30e9bfbcefb9492d66bd56ea7df6d6426ae8a711 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 8 Sep 2021 13:30:36 -0700 Subject: [PATCH 1062/2500] cmd/compile/internal/types2: implement deduplication of instances using the Environment This is a port of CL 344390 with adjustments to names to make it work for types2. Change-Id: I05c33d9858f973adfbf48d8a1faaf377280f6985 Reviewed-on: https://go-review.googlesource.com/c/go/+/348572 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/noder/reader2.go | 4 +- src/cmd/compile/internal/types2/check.go | 4 +- src/cmd/compile/internal/types2/decl.go | 2 +- .../compile/internal/types2/environment.go | 54 ++++++++++++++++ .../compile/internal/types2/instantiate.go | 46 +++++--------- .../internal/types2/instantiate_test.go | 62 +++++++++++++++++++ src/cmd/compile/internal/types2/named.go | 22 ++++--- src/cmd/compile/internal/types2/subst.go | 44 ++++++------- src/cmd/compile/internal/types2/typestring.go | 55 +++++++--------- 9 files changed, 195 insertions(+), 98 deletions(-) create mode 100644 src/cmd/compile/internal/types2/environment.go create mode 100644 src/cmd/compile/internal/types2/instantiate_test.go diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index 296d84289c..6c0d9c8c9d 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -233,7 +233,9 @@ func (r *reader2) doTyp() (res types2.Type) { obj, targs := r.obj() name := obj.(*types2.TypeName) if len(targs) != 0 { - t, _ := types2.Instantiate(types2.NewEnvironment(r.p.check), name.Type(), targs, false) + // TODO(mdempsky) should use a single shared environment here + // (before, this used a shared checker) + t, _ := types2.Instantiate(types2.NewEnvironment(), name.Type(), targs, false) return t } return name.Type() diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go index 4226b4de82..c7b45d86d1 100644 --- a/src/cmd/compile/internal/types2/check.go +++ b/src/cmd/compile/internal/types2/check.go @@ -86,7 +86,7 @@ type Checker struct { nextID uint64 // unique Id for type parameters (first valid Id is 1) objMap map[Object]*declInfo // maps package-level objects and (non-interface) methods to declaration info impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package - typMap map[string]*Named // maps an instantiated named type hash to a *Named type + env *Environment // for deduplicating identical instances // pkgPathMap maps package names to the set of distinct import paths we've // seen for that name, anywhere in the import graph. It is used for @@ -188,7 +188,7 @@ func NewChecker(conf *Config, pkg *Package, info *Info) *Checker { version: version, objMap: make(map[Object]*declInfo), impMap: make(map[importKey]*Package), - typMap: make(map[string]*Named), + env: NewEnvironment(), } } diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index cd97080824..1d46b004b6 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -317,7 +317,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { } case *Named: - t.expand(check.typMap) + t.expand(check.env) // don't touch the type if it is from a different package or the Universe scope // (doing so would lead to a race condition - was issue #35049) diff --git a/src/cmd/compile/internal/types2/environment.go b/src/cmd/compile/internal/types2/environment.go new file mode 100644 index 0000000000..070cf34243 --- /dev/null +++ b/src/cmd/compile/internal/types2/environment.go @@ -0,0 +1,54 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +package types2 + +import "sync" + +// An Environment is an opaque type checking environment. It may be used to +// share identical type instances across type-checked packages or calls to +// Instantiate. +// +// It is safe for concurrent use. +type Environment struct { + mu sync.Mutex + typeMap map[string]*Named // type hash -> instance + nextID int // next unique ID + seen map[*Named]int // assigned unique IDs +} + +// NewEnvironment creates a new Environment. +func NewEnvironment() *Environment { + return &Environment{ + typeMap: make(map[string]*Named), + seen: make(map[*Named]int), + } +} + +// TODO(rfindley): move Environment.typeHash here. +// typeForHash returns the recorded type for the type hash h, if it exists. +// If no type exists for h and n is non-nil, n is recorded for h. +func (env *Environment) typeForHash(h string, n *Named) *Named { + env.mu.Lock() + defer env.mu.Unlock() + if existing := env.typeMap[h]; existing != nil { + return existing + } + if n != nil { + env.typeMap[h] = n + } + return n +} + +// idForType returns a unique ID for the pointer n. +func (env *Environment) idForType(n *Named) int { + env.mu.Lock() + defer env.mu.Unlock() + id, ok := env.seen[n] + if !ok { + id = env.nextID + env.seen[n] = id + env.nextID++ + } + return id +} diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index c882699d1d..d1e981acc4 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -13,21 +13,6 @@ import ( "fmt" ) -// An Environment is an opaque type checking environment. It may be used to -// share identical type instances across type checked packages or calls to -// Instantiate. -type Environment struct { - // For now, Environment just hides a Checker. - // Eventually, we strive to remove the need for a checker. - check *Checker -} - -// NewEnvironment returns a new Environment, initialized with the given -// Checker, or nil. -func NewEnvironment(check *Checker) *Environment { - return &Environment{check} -} - // Instantiate instantiates the type typ with the given type arguments targs. // typ must be a *Named or a *Signature type, and its number of type parameters // must match the number of provided type arguments. The result is a new, @@ -46,11 +31,7 @@ func NewEnvironment(check *Checker) *Environment { // TODO(rfindley): change this function to also return an error if lengths of // tparams and targs do not match. func Instantiate(env *Environment, typ Type, targs []Type, validate bool) (Type, error) { - var check *Checker - if env != nil { - check = env.check - } - inst := check.instance(nopos, typ, targs) + inst := (*Checker)(nil).instance(nopos, typ, targs, env) var err error if validate { @@ -61,7 +42,7 @@ func Instantiate(env *Environment, typ Type, targs []Type, validate bool) (Type, case *Signature: tparams = t.TParams().list() } - if i, err := check.verify(nopos, tparams, targs); err != nil { + if i, err := (*Checker)(nil).verify(nopos, tparams, targs); err != nil { return inst, ArgumentError{i, err} } } @@ -90,7 +71,7 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, posLis }() } - inst := check.instance(pos, typ, targs) + inst := check.instance(pos, typ, targs, check.env) assert(len(posList) <= len(targs)) check.later(func() { @@ -122,14 +103,15 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, posLis // instance creates a type or function instance using the given original type // typ and arguments targs. For Named types the resulting instance will be // unexpanded. -func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type) Type { +func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type, env *Environment) Type { switch t := typ.(type) { case *Named: - h := typeHash(t, targs) - if check != nil { - // typ may already have been instantiated with identical type arguments. - // In that case, re-use the existing instance. - if named := check.typMap[h]; named != nil { + var h string + if env != nil { + h = env.typeHash(t, targs) + // typ may already have been instantiated with identical type arguments. In + // that case, re-use the existing instance. + if named := env.typeForHash(h, nil); named != nil { return named } } @@ -137,8 +119,10 @@ func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type) Type { named := check.newNamed(tname, t, nil, nil, nil) // methods and tparams are set when named is loaded named.targs = NewTypeList(targs) named.instPos = &pos - if check != nil { - check.typMap[h] = named + if env != nil { + // It's possible that we've lost a race to add named to the environment. + // In this case, use whichever instance is recorded in the environment. + named = env.typeForHash(h, named) } return named @@ -150,7 +134,7 @@ func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type) Type { if tparams.Len() == 0 { return typ // nothing to do (minor optimization) } - sig := check.subst(pos, typ, makeSubstMap(tparams.list(), targs), nil).(*Signature) + sig := check.subst(pos, typ, makeSubstMap(tparams.list(), targs), env).(*Signature) // If the signature doesn't use its type parameters, subst // will not make a copy. In that case, make a copy now (so // we can set tparams to nil w/o causing side-effects). diff --git a/src/cmd/compile/internal/types2/instantiate_test.go b/src/cmd/compile/internal/types2/instantiate_test.go new file mode 100644 index 0000000000..69a26491cb --- /dev/null +++ b/src/cmd/compile/internal/types2/instantiate_test.go @@ -0,0 +1,62 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +package types2_test + +import ( + . "cmd/compile/internal/types2" + "testing" +) + +func TestInstantiateEquality(t *testing.T) { + const src = genericPkg + "p; type T[P any] int" + pkg, err := pkgFor(".", src, nil) + if err != nil { + t.Fatal(err) + } + T := pkg.Scope().Lookup("T").Type().(*Named) + // Instantiating the same type twice should result in pointer-equivalent + // instances. + env := NewEnvironment() + res1, err := Instantiate(env, T, []Type{Typ[Int]}, false) + if err != nil { + t.Fatal(err) + } + res2, err := Instantiate(env, T, []Type{Typ[Int]}, false) + if err != nil { + t.Fatal(err) + } + if res1 != res2 { + t.Errorf("first instance (%s) not pointer-equivalent to second instance (%s)", res1, res2) + } +} +func TestInstantiateNonEquality(t *testing.T) { + const src = genericPkg + "p; type T[P any] int" + pkg1, err := pkgFor(".", src, nil) + if err != nil { + t.Fatal(err) + } + pkg2, err := pkgFor(".", src, nil) + if err != nil { + t.Fatal(err) + } + // We consider T1 and T2 to be distinct types, so their instances should not + // be deduplicated by the environment. + T1 := pkg1.Scope().Lookup("T").Type().(*Named) + T2 := pkg2.Scope().Lookup("T").Type().(*Named) + env := NewEnvironment() + res1, err := Instantiate(env, T1, []Type{Typ[Int]}, false) + if err != nil { + t.Fatal(err) + } + res2, err := Instantiate(env, T2, []Type{Typ[Int]}, false) + if err != nil { + t.Fatal(err) + } + if res1 == res2 { + t.Errorf("instance from pkg1 (%s) is pointer-equivalent to instance from pkg2 (%s)", res1, res2) + } + if Identical(res1, res2) { + t.Errorf("instance from pkg1 (%s) is identical to instance from pkg2 (%s)", res1, res2) + } +} diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index a76e69fcf1..c096c1b30b 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -242,7 +242,7 @@ func (n *Named) setUnderlying(typ Type) { // expand ensures that the underlying type of n is instantiated. // The underlying type will be Typ[Invalid] if there was an error. -func (n *Named) expand(typMap map[string]*Named) *Named { +func (n *Named) expand(env *Environment) *Named { if n.instPos != nil { // n must be loaded before instantiation, in order to have accurate // tparams. This is done implicitly by the call to n.TParams, but making it @@ -250,19 +250,25 @@ func (n *Named) expand(typMap map[string]*Named) *Named { n.load() var u Type if n.check.validateTArgLen(*n.instPos, n.tparams.Len(), n.targs.Len()) { - if typMap == nil { + // TODO(rfindley): handling an optional Checker and Environment here (and + // in subst) feels overly complicated. Can we simplify? + if env == nil { if n.check != nil { - typMap = n.check.typMap + env = n.check.env } else { // If we're instantiating lazily, we might be outside the scope of a // type-checking pass. In that case we won't have a pre-existing - // typMap, but don't want to create a duplicate of the current instance - // in the process of expansion. - h := typeHash(n.orig, n.targs.list()) - typMap = map[string]*Named{h: n} + // environment, but don't want to create a duplicate of the current + // instance in the process of expansion. + env = NewEnvironment() } + h := env.typeHash(n.orig, n.targs.list()) + // add the instance to the environment to avoid infinite recursion. + // addInstance may return a different, existing instance, but we + // shouldn't return that instance from expand. + env.typeForHash(h, n) } - u = n.check.subst(*n.instPos, n.orig.underlying, makeSubstMap(n.TParams().list(), n.targs.list()), typMap) + u = n.check.subst(*n.instPos, n.orig.underlying, makeSubstMap(n.TParams().list(), n.targs.list()), env) } else { u = Typ[Invalid] } diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index c67538d4f0..f86555594d 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -40,8 +40,8 @@ func (m substMap) lookup(tpar *TypeParam) Type { // incoming type. If a substitution took place, the result type is different // from the incoming type. // -// If the given typMap is non-nil, it is used in lieu of check.typMap. -func (check *Checker) subst(pos syntax.Pos, typ Type, smap substMap, typMap map[string]*Named) Type { +// If the given environment is non-nil, it is used in lieu of check.env. +func (check *Checker) subst(pos syntax.Pos, typ Type, smap substMap, env *Environment) Type { if smap.empty() { return typ } @@ -61,27 +61,27 @@ func (check *Checker) subst(pos syntax.Pos, typ Type, smap substMap, typMap map[ if check != nil { subst.check = check - if typMap == nil { - typMap = check.typMap + if env == nil { + env = check.env } } - if typMap == nil { + if env == nil { // If we don't have a *Checker and its global type map, // use a local version. Besides avoiding duplicate work, // the type map prevents infinite recursive substitution // for recursive types (example: type T[P any] *T[P]). - typMap = make(map[string]*Named) + env = NewEnvironment() } - subst.typMap = typMap + subst.env = env return subst.typ(typ) } type subster struct { - pos syntax.Pos - smap substMap - check *Checker // nil if called via Instantiate - typMap map[string]*Named + pos syntax.Pos + smap substMap + check *Checker // nil if called via Instantiate + env *Environment } func (subst *subster) typ(typ Type) Type { @@ -214,25 +214,25 @@ func (subst *subster) typ(typ Type) Type { } // before creating a new named type, check if we have this one already - h := typeHash(t, newTArgs) + h := subst.env.typeHash(t.orig, newTArgs) dump(">>> new type hash: %s", h) - if named, found := subst.typMap[h]; found { + if named := subst.env.typeForHash(h, nil); named != nil { dump(">>> found %s", named) return named } - // Create a new named type and populate typMap to avoid endless recursion. - // The position used here is irrelevant because validation only occurs on t - // (we don't call validType on named), but we use subst.pos to help with - // debugging. + // Create a new named type and populate the environment to avoid endless + // recursion. The position used here is irrelevant because validation only + // occurs on t (we don't call validType on named), but we use subst.pos to + // help with debugging. tname := NewTypeName(subst.pos, t.obj.pkg, t.obj.name, nil) t.load() // It's ok to provide a nil *Checker because the newly created type // doesn't need to be (lazily) expanded; it's expanded below. named := (*Checker)(nil).newNamed(tname, t.orig, nil, t.tparams, t.methods) // t is loaded, so tparams and methods are available named.targs = NewTypeList(newTArgs) - subst.typMap[h] = named - t.expand(subst.typMap) // must happen after typMap update to avoid infinite recursion + subst.env.typeForHash(h, named) + t.expand(subst.env) // must happen after env update to avoid infinite recursion // do the substitution dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, newTArgs) @@ -257,14 +257,16 @@ func (subst *subster) typ(typ Type) Type { // type hash: types that are identical produce identical string representations. // If typ is a *Named type and targs is not empty, typ is printed as if it were // instantiated with targs. -func typeHash(typ Type, targs []Type) string { +func (env *Environment) typeHash(typ Type, targs []Type) string { + assert(env != nil) assert(typ != nil) var buf bytes.Buffer - h := newTypeHasher(&buf) + h := newTypeHasher(&buf, env) if named, _ := typ.(*Named); named != nil && len(targs) > 0 { // Don't use WriteType because we need to use the provided targs // and not any targs that might already be with the *Named type. + h.typePrefix(named) h.typeName(named.obj) h.typeList(targs) } else { diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 6083955306..23fd788fbe 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -9,6 +9,7 @@ package types2 import ( "bytes" "fmt" + "strconv" "unicode/utf8" ) @@ -70,22 +71,23 @@ type typeWriter struct { buf *bytes.Buffer seen map[Type]bool qf Qualifier - hash bool + env *Environment // if non-nil, we are type hashing } func newTypeWriter(buf *bytes.Buffer, qf Qualifier) *typeWriter { - return &typeWriter{buf, make(map[Type]bool), qf, false} + return &typeWriter{buf, make(map[Type]bool), qf, nil} } -func newTypeHasher(buf *bytes.Buffer) *typeWriter { - return &typeWriter{buf, make(map[Type]bool), nil, true} +func newTypeHasher(buf *bytes.Buffer, env *Environment) *typeWriter { + assert(env != nil) + return &typeWriter{buf, make(map[Type]bool), nil, env} } func (w *typeWriter) byte(b byte) { w.buf.WriteByte(b) } func (w *typeWriter) string(s string) { w.buf.WriteString(s) } func (w *typeWriter) writef(format string, args ...interface{}) { fmt.Fprintf(w.buf, format, args...) } func (w *typeWriter) error(msg string) { - if w.hash { + if w.env != nil { panic(msg) } w.string("<" + msg + ">") @@ -227,14 +229,15 @@ func (w *typeWriter) typ(typ Type) { // types. Write them to aid debugging, but don't write // them when we need an instance hash: whether a type // is fully expanded or not doesn't matter for identity. - if !w.hash && t.instPos != nil { + if w.env == nil && t.instPos != nil { w.byte(instanceMarker) } + w.typePrefix(t) w.typeName(t.obj) if t.targs != nil { // instantiated type w.typeList(t.targs.list()) - } else if !w.hash && t.TParams().Len() != 0 { // For type hashing, don't need to format the TParams + } else if w.env == nil && t.TParams().Len() != 0 { // For type hashing, don't need to format the TParams // parameterized type w.tParamList(t.TParams().list()) } @@ -263,6 +266,15 @@ func (w *typeWriter) typ(typ Type) { } } +// If w.env is non-nil, typePrefix writes a unique prefix for the named type t +// based on the types already observed by w.env. If w.env is nil, it does +// nothing. +func (w *typeWriter) typePrefix(t *Named) { + if w.env != nil { + w.string(strconv.Itoa(w.env.idForType(t))) + } +} + func (w *typeWriter) typeList(list []Type) { w.byte('[') for i, typ := range list { @@ -308,31 +320,6 @@ func (w *typeWriter) typeName(obj *TypeName) { writePackage(w.buf, obj.pkg, w.qf) } w.string(obj.name) - - if w.hash { - // For local defined types, use the (original!) TypeName's scope - // numbers to disambiguate. - if typ, _ := obj.typ.(*Named); typ != nil { - // TODO(gri) Figure out why typ.orig != typ.orig.orig sometimes - // and whether the loop can iterate more than twice. - // (It seems somehow connected to instance types.) - for typ.orig != typ { - typ = typ.orig - } - w.writeScopeNumbers(typ.obj.parent) - } - } -} - -// writeScopeNumbers writes the number sequence for this scope to buf -// in the form ".i.j.k" where i, j, k, etc. stand for scope numbers. -// If a scope is nil or has no parent (such as a package scope), nothing -// is written. -func (w *typeWriter) writeScopeNumbers(s *Scope) { - if s != nil && s.number > 0 { - w.writeScopeNumbers(s.parent) - w.writef(".%d", s.number) - } } func (w *typeWriter) tuple(tup *Tuple, variadic bool) { @@ -343,7 +330,7 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) { w.string(", ") } // parameter names are ignored for type identity and thus type hashes - if !w.hash && v.name != "" { + if w.env == nil && v.name != "" { w.string(v.name) w.byte(' ') } @@ -384,7 +371,7 @@ func (w *typeWriter) signature(sig *Signature) { } w.byte(' ') - if n == 1 && (w.hash || sig.results.vars[0].name == "") { + if n == 1 && (w.env != nil || sig.results.vars[0].name == "") { // single unnamed result (if type hashing, name must be ignored) w.typ(sig.results.vars[0].typ) return -- GitLab From ccc927b8f6550cb638e78fd63eebf422fc3c3d8a Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 8 Sep 2021 13:37:34 -0700 Subject: [PATCH 1063/2500] cmd/compile/internal/types2: move typeHash to environment.go This is a clean port of CL 347560. Change-Id: I0d56f5a818df1a66e603415d5198d909b0aef228 Reviewed-on: https://go-review.googlesource.com/c/go/+/348573 Trust: Robert Griesemer Reviewed-by: Robert Findley --- .../compile/internal/types2/environment.go | 37 ++++++++++++++++++- src/cmd/compile/internal/types2/subst.go | 36 +----------------- 2 files changed, 36 insertions(+), 37 deletions(-) diff --git a/src/cmd/compile/internal/types2/environment.go b/src/cmd/compile/internal/types2/environment.go index 070cf34243..816139bbb4 100644 --- a/src/cmd/compile/internal/types2/environment.go +++ b/src/cmd/compile/internal/types2/environment.go @@ -3,7 +3,10 @@ // license that can be found in the LICENSE file. package types2 -import "sync" +import ( + "bytes" + "sync" +) // An Environment is an opaque type checking environment. It may be used to // share identical type instances across type-checked packages or calls to @@ -25,7 +28,37 @@ func NewEnvironment() *Environment { } } -// TODO(rfindley): move Environment.typeHash here. +// typeHash returns a string representation of typ, which can be used as an exact +// type hash: types that are identical produce identical string representations. +// If typ is a *Named type and targs is not empty, typ is printed as if it were +// instantiated with targs. +func (env *Environment) typeHash(typ Type, targs []Type) string { + assert(env != nil) + assert(typ != nil) + var buf bytes.Buffer + + h := newTypeHasher(&buf, env) + if named, _ := typ.(*Named); named != nil && len(targs) > 0 { + // Don't use WriteType because we need to use the provided targs + // and not any targs that might already be with the *Named type. + h.typePrefix(named) + h.typeName(named.obj) + h.typeList(targs) + } else { + assert(targs == nil) + h.typ(typ) + } + + if debug { + // there should be no instance markers in type hashes + for _, b := range buf.Bytes() { + assert(b != instanceMarker) + } + } + + return buf.String() +} + // typeForHash returns the recorded type for the type hash h, if it exists. // If no type exists for h and n is non-nil, n is recorded for h. func (env *Environment) typeForHash(h string, n *Named) *Named { diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index f86555594d..2032305fab 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -6,10 +6,7 @@ package types2 -import ( - "bytes" - "cmd/compile/internal/syntax" -) +import "cmd/compile/internal/syntax" type substMap map[*TypeParam]Type @@ -253,37 +250,6 @@ func (subst *subster) typ(typ Type) Type { return typ } -// typeHash returns a string representation of typ, which can be used as an exact -// type hash: types that are identical produce identical string representations. -// If typ is a *Named type and targs is not empty, typ is printed as if it were -// instantiated with targs. -func (env *Environment) typeHash(typ Type, targs []Type) string { - assert(env != nil) - assert(typ != nil) - var buf bytes.Buffer - - h := newTypeHasher(&buf, env) - if named, _ := typ.(*Named); named != nil && len(targs) > 0 { - // Don't use WriteType because we need to use the provided targs - // and not any targs that might already be with the *Named type. - h.typePrefix(named) - h.typeName(named.obj) - h.typeList(targs) - } else { - assert(targs == nil) - h.typ(typ) - } - - if debug { - // there should be no instance markers in type hashes - for _, b := range buf.Bytes() { - assert(b != instanceMarker) - } - } - - return buf.String() -} - // typOrNil is like typ but if the argument is nil it is replaced with Typ[Invalid]. // A nil type may appear in pathological cases such as type T[P any] []func(_ T([]_)) // where an array/slice element is accessed before it is set up. -- GitLab From 47f3e1e02c8737fd06397d957506f3724737cae0 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 8 Sep 2021 13:45:16 -0700 Subject: [PATCH 1064/2500] cmd/compile/internal/types2: move NewTypeParam off of Checker This is a port of CL 347561. A comment was corrected both in types2 and go/types, and the compiler adjusted for the updated NewTypeParameter function. Change-Id: I4381f0dd8e43228e1d037c5d997d421b7838f905 Reviewed-on: https://go-review.googlesource.com/c/go/+/348574 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/importer/iimport.go | 2 +- src/cmd/compile/internal/noder/reader2.go | 2 +- src/cmd/compile/internal/types2/builtins.go | 2 +- src/cmd/compile/internal/types2/decl.go | 2 +- src/cmd/compile/internal/types2/typeparam.go | 10 +++++++--- src/go/types/typeparam.go | 2 +- 6 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index 38cb8db235..646cad60d9 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -365,7 +365,7 @@ func (r *importReader) obj(name string) { } name0, sub := parseSubscript(name) tn := types2.NewTypeName(pos, r.currPkg, name0, nil) - t := (*types2.Checker)(nil).NewTypeParam(tn, nil) + t := types2.NewTypeParam(tn, nil) if sub == 0 { errorf("missing subscript") } diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index 6c0d9c8c9d..a5e925b3db 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -483,7 +483,7 @@ func (r *reader2) typeParamNames() []*types2.TypeParam { pkg, name := r.localIdent() tname := types2.NewTypeName(pos, pkg, name, nil) - r.dict.tparams[i] = r.p.check.NewTypeParam(tname, nil) + r.dict.tparams[i] = types2.NewTypeParam(tname, nil) } for i, bound := range r.dict.bounds { diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index e3844d5163..3b8d85859a 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -826,7 +826,7 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { // type param is placed in the current package so export/import // works as expected. tpar := NewTypeName(nopos, check.pkg, "", nil) - ptyp := check.NewTypeParam(tpar, NewInterfaceType(nil, []Type{NewUnion(terms)})) // assigns type to tpar as a side-effect + ptyp := check.newTypeParam(tpar, NewInterfaceType(nil, []Type{NewUnion(terms)})) // assigns type to tpar as a side-effect ptyp.index = tp.index return ptyp diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 1d46b004b6..5be4a9f804 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -648,7 +648,7 @@ func (check *Checker) declareTypeParam(name *syntax.Name) *TypeParam { // constraints to make sure we don't rely on them if they // are not properly set yet. tname := NewTypeName(name.Pos(), check.pkg, name.Value, nil) - tpar := check.NewTypeParam(tname, Typ[Invalid]) // assigns type to tname as a side-effect + tpar := check.newTypeParam(tname, Typ[Invalid]) // assigns type to tname as a side-effect check.declare(check.scope, name, tname, check.scope.pos) // TODO(gri) check scope position return tpar } diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index 445337fee8..e7181281af 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -32,15 +32,19 @@ func (t *TypeParam) Obj() *TypeName { return t.obj } // or Signature type by calling SetTParams. Setting a type parameter on more // than one type will result in a panic. // -// The bound argument can be nil, and set later via SetBound. -func (check *Checker) NewTypeParam(obj *TypeName, bound Type) *TypeParam { +// The constraint argument can be nil, and set later via SetConstraint. +func NewTypeParam(obj *TypeName, constraint Type) *TypeParam { + return (*Checker)(nil).newTypeParam(obj, constraint) +} + +func (check *Checker) newTypeParam(obj *TypeName, constraint Type) *TypeParam { // Always increment lastID, even if it is not used. id := nextID() if check != nil { check.nextID++ id = check.nextID } - typ := &TypeParam{check: check, id: id, obj: obj, index: -1, bound: bound} + typ := &TypeParam{check: check, id: id, obj: obj, index: -1, bound: constraint} if obj.typ == nil { obj.typ = typ } diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index a0f2a3acd0..150ad079a8 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -32,7 +32,7 @@ type TypeParam struct { // or Signature type by calling SetTypeParams. Setting a type parameter on more // than one type will result in a panic. // -// The bound argument can be nil, and set later via SetConstraint. +// The constraint argument can be nil, and set later via SetConstraint. func NewTypeParam(obj *TypeName, constraint Type) *TypeParam { return (*Checker)(nil).newTypeParam(obj, constraint) } -- GitLab From b61e1ed863886743598c6f816b0740f3768b50f6 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 8 Sep 2021 13:52:46 -0700 Subject: [PATCH 1065/2500] cmd/compile/internal/types2: temporarily pin the Checker to Interface during checking This is a clean port of CL 348371. Change-Id: I3a61a5a8928279bc783ef16739f7607de3b6ecf3 Reviewed-on: https://go-review.googlesource.com/c/go/+/348575 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/interface.go | 15 ++++++++++++--- src/cmd/compile/internal/types2/sizeof_test.go | 2 +- .../types2/testdata/fixedbugs/issue48234.go2 | 10 ++++++++++ src/cmd/compile/internal/types2/universe.go | 4 ++-- 4 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue48234.go2 diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index e57158d2d5..340df51524 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -11,6 +11,7 @@ import "cmd/compile/internal/syntax" // An Interface represents an interface type. type Interface struct { + check *Checker // for error reporting; nil once type set is computed obj *TypeName // corresponding declared object; or nil (for better error messages) methods []*Func // ordered list of explicitly declared methods embeddeds []Type // ordered list of explicitly embedded elements @@ -21,7 +22,7 @@ type Interface struct { } // typeSet returns the type set for interface t. -func (t *Interface) typeSet() *_TypeSet { return computeInterfaceTypeSet(nil, nopos, t) } +func (t *Interface) typeSet() *_TypeSet { return computeInterfaceTypeSet(t.check, nopos, t) } // emptyInterface represents the empty interface var emptyInterface = Interface{complete: true, tset: &topTypeSet} @@ -198,7 +199,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType } // All methods and embedded elements for this interface are collected; - // i.e., this interface is may be used in a type set computation. + // i.e., this interface may be used in a type set computation. ityp.complete = true if len(ityp.methods) == 0 && len(ityp.embeddeds) == 0 { @@ -214,7 +215,15 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType // Compute type set with a non-nil *Checker as soon as possible // to report any errors. Subsequent uses of type sets will use // this computed type set and won't need to pass in a *Checker. - check.later(func() { computeInterfaceTypeSet(check, iface.Pos(), ityp) }) + // + // Pin the checker to the interface type in the interim, in case the type set + // must be used before delayed funcs are processed (see issue #48234). + // TODO(rfindley): clean up use of *Checker with computeInterfaceTypeSet + ityp.check = check + check.later(func() { + computeInterfaceTypeSet(check, iface.Pos(), ityp) + ityp.check = nil + }) } func flattenUnion(list []syntax.Expr, x syntax.Expr) []syntax.Expr { diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go index 5be369d843..bbaca8e0aa 100644 --- a/src/cmd/compile/internal/types2/sizeof_test.go +++ b/src/cmd/compile/internal/types2/sizeof_test.go @@ -28,7 +28,7 @@ func TestSizeof(t *testing.T) { {Tuple{}, 12, 24}, {Signature{}, 28, 56}, {Union{}, 16, 32}, - {Interface{}, 40, 80}, + {Interface{}, 44, 88}, {Map{}, 16, 32}, {Chan{}, 12, 24}, {Named{}, 72, 136}, diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48234.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48234.go2 new file mode 100644 index 0000000000..e069930c42 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48234.go2 @@ -0,0 +1,10 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +var _ = interface{ + m() + m /* ERROR "duplicate method" */ () +}(nil) diff --git a/src/cmd/compile/internal/types2/universe.go b/src/cmd/compile/internal/types2/universe.go index a615b4c876..af3ab97325 100644 --- a/src/cmd/compile/internal/types2/universe.go +++ b/src/cmd/compile/internal/types2/universe.go @@ -88,7 +88,7 @@ func defPredeclaredTypes() { res := NewVar(nopos, nil, "", Typ[String]) sig := NewSignature(nil, nil, NewTuple(res), false) err := NewFunc(nopos, nil, "Error", sig) - ityp := &Interface{obj, []*Func{err}, nil, nil, true, nil} + ityp := &Interface{nil, obj, []*Func{err}, nil, nil, true, nil} computeInterfaceTypeSet(nil, nopos, ityp) // prevent races due to lazy computation of tset typ := NewNamed(obj, ityp, nil) sig.recv = NewVar(nopos, nil, "", typ) @@ -99,7 +99,7 @@ func defPredeclaredTypes() { { obj := NewTypeName(nopos, nil, "comparable", nil) obj.setColor(black) - ityp := &Interface{obj, nil, nil, nil, true, &_TypeSet{true, nil, allTermlist}} + ityp := &Interface{nil, obj, nil, nil, nil, true, &_TypeSet{true, nil, allTermlist}} NewNamed(obj, ityp, nil) def(obj) } -- GitLab From bff39cf6cb5bbe1575fdd95682c991ef35e97289 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Sat, 4 Sep 2021 19:29:08 -0700 Subject: [PATCH 1066/2500] cmd/compile: add automated rewrite cycle detection A common bug during development is to introduce rewrite rule cycles. This is annoying because it takes a while to notice that make.bash is a bit too slow this time, and to remember why. And then you have to manually arrange to debug. Make this all easier by automating it. Detect cycles, and when we detect one, print the sequence of rewrite rules that occur within a single cycle before crashing. Change-Id: I8dadda13990ab925a81940d4833c9e5243368435 Reviewed-on: https://go-review.googlesource.com/c/go/+/347829 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/compile/internal/ssa/html.go | 2 +- src/cmd/compile/internal/ssa/print.go | 32 +++++++++++++++++++------ src/cmd/compile/internal/ssa/rewrite.go | 26 ++++++++++++++++++++ 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/internal/ssa/html.go b/src/cmd/compile/internal/ssa/html.go index 4d191199fb..6fd898636c 100644 --- a/src/cmd/compile/internal/ssa/html.go +++ b/src/cmd/compile/internal/ssa/html.go @@ -1221,7 +1221,7 @@ func (p htmlFuncPrinter) startBlock(b *Block, reachable bool) { } } -func (p htmlFuncPrinter) endBlock(b *Block) { +func (p htmlFuncPrinter) endBlock(b *Block, reachable bool) { if len(b.Values) > 0 { // end list of values io.WriteString(p.w, "") io.WriteString(p.w, "") diff --git a/src/cmd/compile/internal/ssa/print.go b/src/cmd/compile/internal/ssa/print.go index d917183c70..81c64a7692 100644 --- a/src/cmd/compile/internal/ssa/print.go +++ b/src/cmd/compile/internal/ssa/print.go @@ -17,22 +17,30 @@ func printFunc(f *Func) { func hashFunc(f *Func) []byte { h := sha256.New() - p := stringFuncPrinter{w: h} + p := stringFuncPrinter{w: h, printDead: true} fprintFunc(p, f) return h.Sum(nil) } func (f *Func) String() string { var buf bytes.Buffer - p := stringFuncPrinter{w: &buf} + p := stringFuncPrinter{w: &buf, printDead: true} fprintFunc(p, f) return buf.String() } +// rewriteHash returns a hash of f suitable for detecting rewrite cycles. +func (f *Func) rewriteHash() string { + h := sha256.New() + p := stringFuncPrinter{w: h, printDead: false} + fprintFunc(p, f) + return fmt.Sprintf("%x", h.Sum(nil)) +} + type funcPrinter interface { header(f *Func) startBlock(b *Block, reachable bool) - endBlock(b *Block) + endBlock(b *Block, reachable bool) value(v *Value, live bool) startDepCycle() endDepCycle() @@ -40,7 +48,8 @@ type funcPrinter interface { } type stringFuncPrinter struct { - w io.Writer + w io.Writer + printDead bool } func (p stringFuncPrinter) header(f *Func) { @@ -50,6 +59,9 @@ func (p stringFuncPrinter) header(f *Func) { } func (p stringFuncPrinter) startBlock(b *Block, reachable bool) { + if !p.printDead && !reachable { + return + } fmt.Fprintf(p.w, " b%d:", b.ID) if len(b.Preds) > 0 { io.WriteString(p.w, " <-") @@ -64,11 +76,17 @@ func (p stringFuncPrinter) startBlock(b *Block, reachable bool) { io.WriteString(p.w, "\n") } -func (p stringFuncPrinter) endBlock(b *Block) { +func (p stringFuncPrinter) endBlock(b *Block, reachable bool) { + if !p.printDead && !reachable { + return + } fmt.Fprintln(p.w, " "+b.LongString()) } func (p stringFuncPrinter) value(v *Value, live bool) { + if !p.printDead && !live { + return + } fmt.Fprint(p.w, " ") //fmt.Fprint(p.w, v.Block.Func.fe.Pos(v.Pos)) //fmt.Fprint(p.w, ": ") @@ -103,7 +121,7 @@ func fprintFunc(p funcPrinter, f *Func) { p.value(v, live[v.ID]) printed[v.ID] = true } - p.endBlock(b) + p.endBlock(b, reachable[b.ID]) continue } @@ -151,7 +169,7 @@ func fprintFunc(p funcPrinter, f *Func) { } } - p.endBlock(b) + p.endBlock(b, reachable[b.ID]) } for _, name := range f.Names { p.named(*name, f.NamedValues[*name]) diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index 5d468768b6..a997050ee2 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -36,6 +36,8 @@ func applyRewrite(f *Func, rb blockRewriter, rv valueRewriter, deadcode deadValu if debug > 1 { fmt.Printf("%s: rewriting for %s\n", f.pass.name, f.Name) } + var iters int + var states map[string]bool for { change := false for _, b := range f.Blocks { @@ -146,6 +148,30 @@ func applyRewrite(f *Func, rb blockRewriter, rv valueRewriter, deadcode deadValu if !change { break } + iters++ + if iters > 1000 || debug >= 2 { + // We've done a suspiciously large number of rewrites (or we're in debug mode). + // As of Sep 2021, 90% of rewrites complete in 4 iterations or fewer + // and the maximum value encountered during make.bash is 12. + // Start checking for cycles. (This is too expensive to do routinely.) + if states == nil { + states = make(map[string]bool) + } + h := f.rewriteHash() + if _, ok := states[h]; ok { + // We've found a cycle. + // To diagnose it, set debug to 2 and start again, + // so that we'll print all rules applied until we complete another cycle. + // If debug is already >= 2, we've already done that, so it's time to crash. + if debug < 2 { + debug = 2 + states = make(map[string]bool) + } else { + f.Fatalf("rewrite cycle detected") + } + } + states[h] = true + } } // remove clobbered values for _, b := range f.Blocks { -- GitLab From f5f8a911d8425995c61ed836584b4f3ad0e4c8fc Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 8 Sep 2021 15:22:20 -0700 Subject: [PATCH 1067/2500] cmd/compile/internal/types2: spell out 'Type' in type parameter APIs This is a port of CL 348376 with the necessary adjustments in the compiler. Change-Id: Ib11ee841b194746ff231ee493aa56bf9b3a4a67f Reviewed-on: https://go-review.googlesource.com/c/go/+/348577 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/importer/iimport.go | 6 +-- src/cmd/compile/internal/noder/decl.go | 2 +- src/cmd/compile/internal/noder/expr.go | 4 +- src/cmd/compile/internal/noder/reader2.go | 2 +- src/cmd/compile/internal/noder/types.go | 12 +++--- src/cmd/compile/internal/noder/writer.go | 28 ++++++------- src/cmd/compile/internal/types2/api_test.go | 2 +- .../compile/internal/types2/assignments.go | 2 +- src/cmd/compile/internal/types2/call.go | 18 ++++---- src/cmd/compile/internal/types2/decl.go | 4 +- src/cmd/compile/internal/types2/index.go | 2 +- src/cmd/compile/internal/types2/infer.go | 2 +- .../compile/internal/types2/instantiate.go | 10 ++--- src/cmd/compile/internal/types2/lookup.go | 16 +++---- src/cmd/compile/internal/types2/named.go | 42 +++++++++---------- src/cmd/compile/internal/types2/object.go | 4 +- src/cmd/compile/internal/types2/predicates.go | 8 ++-- src/cmd/compile/internal/types2/signature.go | 28 ++++++------- src/cmd/compile/internal/types2/subst.go | 6 +-- src/cmd/compile/internal/types2/typelists.go | 16 +++---- src/cmd/compile/internal/types2/typeparam.go | 2 +- src/cmd/compile/internal/types2/typestring.go | 8 ++-- 22 files changed, 112 insertions(+), 112 deletions(-) diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index 646cad60d9..8fdd879705 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -314,7 +314,7 @@ func (r *importReader) obj(name string) { tparams = r.tparamList() } sig := r.signature(nil) - sig.SetTParams(tparams) + sig.SetTypeParams(tparams) r.declare(types2.NewFunc(pos, r.currPkg, name, sig)) case 'T', 'U': @@ -327,7 +327,7 @@ func (r *importReader) obj(name string) { // declaration before recursing. obj := types2.NewTypeName(pos, r.currPkg, name, nil) named := types2.NewNamed(obj, nil, nil) - named.SetTParams(tparams) + named.SetTypeParams(tparams) r.declare(obj) underlying := r.p.typAt(r.uint64(), named).Underlying() @@ -343,7 +343,7 @@ func (r *importReader) obj(name string) { // If the receiver has any targs, set those as the // rparams of the method (since those are the // typeparams being used in the method sig/body). - targs := baseType(msig.Recv().Type()).TArgs() + targs := baseType(msig.Recv().Type()).TypeArgs() if targs.Len() > 0 { rparams := make([]*types2.TypeParam, targs.Len()) for i := range rparams { diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go index de481fb5fc..c9ab31f203 100644 --- a/src/cmd/compile/internal/noder/decl.go +++ b/src/cmd/compile/internal/noder/decl.go @@ -190,7 +190,7 @@ func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) { // object to new type pragmas.] ntyp.SetUnderlying(g.typeExpr(decl.Type)) - tparams := otyp.(*types2.Named).TParams() + tparams := otyp.(*types2.Named).TypeParams() if n := tparams.Len(); n > 0 { rparams := make([]*types.Type, n) for i := range rparams { diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 7dbbc88f8f..5eeafddae2 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -344,7 +344,7 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto if wantPtr { recvType2Base = types2.AsPointer(recvType2).Elem() } - if types2.AsNamed(recvType2Base).TParams().Len() > 0 { + if types2.AsNamed(recvType2Base).TypeParams().Len() > 0 { // recvType2 is the original generic type that is // instantiated for this method call. // selinfo.Recv() is the instantiated type @@ -395,7 +395,7 @@ func getTargs(selinfo *types2.Selection) *types2.TypeList { if n == nil { base.Fatalf("Incorrect type for selinfo %v", selinfo) } - return n.TArgs() + return n.TypeArgs() } func (g *irgen) exprList(expr syntax.Expr) []ir.Node { diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index a5e925b3db..3886d571b5 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -397,7 +397,7 @@ func (pr *pkgReader2) objIdx(idx int) (*types2.Package, string) { pos := r.pos() tparams := r.typeParamNames() sig := r.signature(nil) - sig.SetTParams(tparams) + sig.SetTypeParams(tparams) return types2.NewFunc(pos, objPkg, objName, sig) case objType: diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index 5c9aafe490..b0b9c1592a 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -91,7 +91,7 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { // since that is the only use of a generic type that doesn't // involve instantiation. We just translate the named type in the // normal way below using g.obj(). - if typ.TParams() != nil && typ.TArgs() != nil { + if typ.TypeParams() != nil && typ.TypeArgs() != nil { // typ is an instantiation of a defined (named) generic type. // This instantiation should also be a defined (named) type. // types2 gives us the substituted type in t.Underlying() @@ -101,7 +101,7 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { // // When converted to types.Type, typ has a unique name, // based on the names of the type arguments. - instName := g.instTypeName2(typ.Obj().Name(), typ.TArgs()) + instName := g.instTypeName2(typ.Obj().Name(), typ.TypeArgs()) s := g.pkg(typ.Obj().Pkg()).Lookup(instName) if s.Def != nil { // We have already encountered this instantiation. @@ -135,7 +135,7 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { // non-generic types used to instantiate this type. We'll // use these when instantiating the methods of the // instantiated type. - targs := typ.TArgs() + targs := typ.TypeArgs() rparams := make([]*types.Type, targs.Len()) for i := range rparams { rparams[i] = g.typ1(targs.At(i)) @@ -272,7 +272,7 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { // instantiated types, and for actually generating the methods for instantiated // types. func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) { - targs2 := typ.TArgs() + targs2 := typ.TypeArgs() targs := make([]*types.Type, targs2.Len()) for i := range targs { targs[i] = g.typ1(targs2.At(i)) @@ -296,7 +296,7 @@ func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) { // generic type, so we have to do a substitution to get // the name/type of the method of the instantiated type, // using m.Type().RParams() and typ.TArgs() - inst2 := g.instTypeName2("", typ.TArgs()) + inst2 := g.instTypeName2("", typ.TypeArgs()) name := meth.Sym().Name i1 := strings.Index(name, "[") i2 := strings.Index(name[i1:], "]") @@ -336,7 +336,7 @@ func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) { } func (g *irgen) signature(recv *types.Field, sig *types2.Signature) *types.Type { - tparams2 := sig.TParams() + tparams2 := sig.TypeParams() tparams := make([]*types.Field, tparams2.Len()) for i := range tparams { tp := tparams2.At(i).Obj() diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 1405c77161..d1e5605739 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -299,16 +299,16 @@ func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo { // Type aliases can refer to uninstantiated generic types, so we // might see len(TParams) != 0 && len(TArgs) == 0 here. // TODO(mdempsky): Revisit after #46477 is resolved. - assert(typ.TParams().Len() == typ.TArgs().Len() || typ.TArgs().Len() == 0) + assert(typ.TypeParams().Len() == typ.TypeArgs().Len() || typ.TypeArgs().Len() == 0) // TODO(mdempsky): Why do we need to loop here? orig := typ - for orig.TArgs() != nil { + for orig.TypeArgs() != nil { orig = orig.Orig() } w.code(typeNamed) - w.obj(orig.Obj(), typ.TArgs()) + w.obj(orig.Obj(), typ.TypeArgs()) case *types2.TypeParam: index := func() int { @@ -345,7 +345,7 @@ func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo { w.typ(typ.Elem()) case *types2.Signature: - assert(typ.TParams() == nil) + assert(typ.TypeParams() == nil) w.code(typeSignature) w.signature(typ) @@ -405,7 +405,7 @@ func (w *writer) interfaceType(typ *types2.Interface) { for i := 0; i < typ.NumExplicitMethods(); i++ { m := typ.ExplicitMethod(i) sig := m.Type().(*types2.Signature) - assert(sig.TParams() == nil) + assert(sig.TypeParams() == nil) w.pos(m) w.selector(m) @@ -551,7 +551,7 @@ func (w *writer) doObj(obj types2.Object) codeObj { sig := obj.Type().(*types2.Signature) w.pos(obj) - w.typeParamNames(sig.TParams()) + w.typeParamNames(sig.TypeParams()) w.signature(sig) w.pos(decl) w.ext.funcExt(obj) @@ -568,10 +568,10 @@ func (w *writer) doObj(obj types2.Object) codeObj { } named := obj.Type().(*types2.Named) - assert(named.TArgs() == nil) + assert(named.TypeArgs() == nil) w.pos(obj) - w.typeParamNames(named.TParams()) + w.typeParamNames(named.TypeParams()) w.ext.typeExt(obj) w.typExpr(decl.Type) @@ -642,7 +642,7 @@ func (w *writer) objDict(obj types2.Object, dict *writerDict) { assert(len(dict.funcs) == nfuncs) } -func (w *writer) typeParamNames(tparams *types2.TParamList) { +func (w *writer) typeParamNames(tparams *types2.TypeParamList) { w.sync(syncTypeParamNames) ntparams := tparams.Len() @@ -1677,7 +1677,7 @@ func (w *writer) pkgDecl(decl syntax.Decl) { obj := w.p.info.Defs[decl.Name].(*types2.Func) sig := obj.Type().(*types2.Signature) - if sig.RParams() != nil || sig.TParams() != nil { + if sig.RParams() != nil || sig.TypeParams() != nil { break // skip generic functions } @@ -1711,7 +1711,7 @@ func (w *writer) pkgDecl(decl syntax.Decl) { // TODO(mdempsky): Revisit after #46477 is resolved. if name.IsAlias() { named, ok := name.Type().(*types2.Named) - if ok && named.TParams().Len() != 0 && named.TArgs().Len() == 0 { + if ok && named.TypeParams().Len() != 0 && named.TypeArgs().Len() == 0 { break } } @@ -1858,17 +1858,17 @@ func fieldIndex(info *types2.Info, str *types2.Struct, key *syntax.Name) int { } // objTypeParams returns the type parameters on the given object. -func objTypeParams(obj types2.Object) *types2.TParamList { +func objTypeParams(obj types2.Object) *types2.TypeParamList { switch obj := obj.(type) { case *types2.Func: sig := obj.Type().(*types2.Signature) if sig.Recv() != nil { return sig.RParams() } - return sig.TParams() + return sig.TypeParams() case *types2.TypeName: if !obj.IsAlias() { - return obj.Type().(*types2.Named).TParams() + return obj.Type().(*types2.Named).TypeParams() } } return nil diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index 039a6c0e5e..3ec0d78a23 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -1871,7 +1871,7 @@ func TestInstantiate(t *testing.T) { // type T should have one type parameter T := pkg.Scope().Lookup("T").Type().(*Named) - if n := T.TParams().Len(); n != 1 { + if n := T.TypeParams().Len(); n != 1 { t.Fatalf("expected 1 type parameter; found %d", n) } diff --git a/src/cmd/compile/internal/types2/assignments.go b/src/cmd/compile/internal/types2/assignments.go index 6184fc2ea5..29d63cf819 100644 --- a/src/cmd/compile/internal/types2/assignments.go +++ b/src/cmd/compile/internal/types2/assignments.go @@ -68,7 +68,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { // x.typ is typed // A generic (non-instantiated) function value cannot be assigned to a variable. - if sig := asSignature(x.typ); sig != nil && sig.TParams().Len() > 0 { + if sig := asSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { check.errorf(x, "cannot use generic function %s without instantiation in %s", x, context) } diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 5bf17876c1..f6aaa461b9 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -30,7 +30,7 @@ func (check *Checker) funcInst(x *operand, inst *syntax.IndexExpr) { // check number of type arguments (got) vs number of type parameters (want) sig := x.typ.(*Signature) - got, want := len(targs), sig.TParams().Len() + got, want := len(targs), sig.TypeParams().Len() if !useConstraintTypeInference && got != want || got > want { check.errorf(xlist[got-1], "got %d type arguments but want %d", got, want) x.mode = invalid @@ -41,7 +41,7 @@ func (check *Checker) funcInst(x *operand, inst *syntax.IndexExpr) { // if we don't have enough type arguments, try type inference inferred := false if got < want { - targs = check.infer(inst.Pos(), sig.TParams().list(), targs, nil, nil, true) + targs = check.infer(inst.Pos(), sig.TypeParams().list(), targs, nil, nil, true) if targs == nil { // error was already reported x.mode = invalid @@ -61,7 +61,7 @@ func (check *Checker) funcInst(x *operand, inst *syntax.IndexExpr) { // instantiate function signature res := check.instantiate(x.Pos(), sig, targs, poslist).(*Signature) - assert(res.TParams().Len() == 0) // signature is not generic anymore + assert(res.TypeParams().Len() == 0) // signature is not generic anymore if inferred { check.recordInferred(inst, targs, res) } @@ -166,7 +166,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { assert(len(targs) == len(xlist)) // check number of type arguments (got) vs number of type parameters (want) - got, want := len(targs), sig.TParams().Len() + got, want := len(targs), sig.TypeParams().Len() if got > want { check.errorf(xlist[want], "got %d type arguments but want %d", got, want) check.use(call.ArgList...) @@ -200,7 +200,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { // if type inference failed, a parametrized result must be invalidated // (operands cannot have a parametrized type) - if x.mode == value && sig.TParams().Len() > 0 && isParameterized(sig.TParams().list(), x.typ) { + if x.mode == value && sig.TypeParams().Len() > 0 && isParameterized(sig.TypeParams().list(), x.typ) { x.mode = invalid } @@ -328,7 +328,7 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T } // infer type arguments and instantiate signature if necessary - if sig.TParams().Len() > 0 { + if sig.TypeParams().Len() > 0 { if !check.allowVersion(check.pkg, 1, 18) { if iexpr, _ := call.Fun.(*syntax.IndexExpr); iexpr != nil { check.softErrorf(iexpr.Pos(), "function instantiation requires go1.18 or later") @@ -338,21 +338,21 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T } // TODO(gri) provide position information for targs so we can feed // it to the instantiate call for better error reporting - targs := check.infer(call.Pos(), sig.TParams().list(), targs, sigParams, args, true) + targs := check.infer(call.Pos(), sig.TypeParams().list(), targs, sigParams, args, true) if targs == nil { return // error already reported } // compute result signature rsig = check.instantiate(call.Pos(), sig, targs, nil).(*Signature) - assert(rsig.TParams().Len() == 0) // signature is not generic anymore + assert(rsig.TypeParams().Len() == 0) // signature is not generic anymore check.recordInferred(call, targs, rsig) // Optimization: Only if the parameter list was adjusted do we // need to compute it from the adjusted list; otherwise we can // simply use the result signature's parameter list. if adjusted { - sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(sig.TParams().list(), targs), nil).(*Tuple) + sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(sig.TypeParams().list(), targs), nil).(*Tuple) } else { sigParams = rsig.params } diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 5be4a9f804..4181be9fa8 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -592,13 +592,13 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named named.underlying = under(named) // If the RHS is a type parameter, it must be from this type declaration. - if tpar, _ := named.underlying.(*TypeParam); tpar != nil && tparamIndex(named.TParams().list(), tpar) < 0 { + if tpar, _ := named.underlying.(*TypeParam); tpar != nil && tparamIndex(named.TypeParams().list(), tpar) < 0 { check.errorf(tdecl.Type, "cannot use function type parameter %s as RHS in type declaration", tpar) named.underlying = Typ[Invalid] } } -func (check *Checker) collectTypeParams(dst **TParamList, list []*syntax.Field) { +func (check *Checker) collectTypeParams(dst **TypeParamList, list []*syntax.Field) { tparams := make([]*TypeParam, len(list)) // Declare type parameters up-front. diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index febfd21ea3..848a70dea8 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -34,7 +34,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo return false case value: - if sig := asSignature(x.typ); sig != nil && sig.TParams().Len() > 0 { + if sig := asSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { // function instantiation return true } diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index bb7270b346..c2a8155dc7 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -562,7 +562,7 @@ func (w *cycleFinder) typ(typ Type) { w.typ(t.elem) case *Named: - for _, tpar := range t.TArgs().list() { + for _, tpar := range t.TypeArgs().list() { w.typ(tpar) } diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index d1e981acc4..3ea21f921b 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -38,9 +38,9 @@ func Instantiate(env *Environment, typ Type, targs []Type, validate bool) (Type, var tparams []*TypeParam switch t := typ.(type) { case *Named: - tparams = t.TParams().list() + tparams = t.TypeParams().list() case *Signature: - tparams = t.TParams().list() + tparams = t.TypeParams().list() } if i, err := (*Checker)(nil).verify(nopos, tparams, targs); err != nil { return inst, ArgumentError{i, err} @@ -80,9 +80,9 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, posLis var tparams []*TypeParam switch t := typ.(type) { case *Named: - tparams = t.TParams().list() + tparams = t.TypeParams().list() case *Signature: - tparams = t.TParams().list() + tparams = t.TypeParams().list() } // Avoid duplicate errors; instantiate will have complained if tparams // and targs do not have the same length. @@ -127,7 +127,7 @@ func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type, env *Envi return named case *Signature: - tparams := t.TParams() + tparams := t.TypeParams() if !check.validateTArgLen(pos, tparams.Len(), len(targs)) { return Typ[Invalid] } diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index d0718e51e2..67cdc1e68a 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -321,10 +321,10 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // both methods must have the same number of type parameters ftyp := f.typ.(*Signature) mtyp := m.typ.(*Signature) - if ftyp.TParams().Len() != mtyp.TParams().Len() { + if ftyp.TypeParams().Len() != mtyp.TypeParams().Len() { return m, f } - if !acceptMethodTypeParams && ftyp.TParams().Len() > 0 { + if !acceptMethodTypeParams && ftyp.TypeParams().Len() > 0 { panic("method with type parameters") } @@ -334,7 +334,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // TODO(gri) is this always correct? what about type bounds? // (Alternative is to rename/subst type parameters and compare.) u := newUnifier(true) - u.x.init(ftyp.TParams().list()) + u.x.init(ftyp.TypeParams().list()) if !u.unify(ftyp, mtyp) { return m, f } @@ -373,10 +373,10 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // both methods must have the same number of type parameters ftyp := f.typ.(*Signature) mtyp := m.typ.(*Signature) - if ftyp.TParams().Len() != mtyp.TParams().Len() { + if ftyp.TypeParams().Len() != mtyp.TypeParams().Len() { return m, f } - if !acceptMethodTypeParams && ftyp.TParams().Len() > 0 { + if !acceptMethodTypeParams && ftyp.TypeParams().Len() > 0 { panic("method with type parameters") } @@ -387,7 +387,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // In order to compare the signatures, substitute the receiver // type parameters of ftyp with V's instantiation type arguments. // This lazily instantiates the signature of method f. - if Vn != nil && Vn.TParams().Len() > 0 { + if Vn != nil && Vn.TypeParams().Len() > 0 { // Be careful: The number of type arguments may not match // the number of receiver parameters. If so, an error was // reported earlier but the length discrepancy is still @@ -406,7 +406,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // TODO(gri) is this always correct? what about type bounds? // (Alternative is to rename/subst type parameters and compare.) u := newUnifier(true) - if ftyp.TParams().Len() > 0 { + if ftyp.TypeParams().Len() > 0 { // We reach here only if we accept method type parameters. // In this case, unification must consider any receiver // and method type parameters as "free" type parameters. @@ -416,7 +416,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // unimplemented call so that we test this code if we // enable method type parameters. unimplemented() - u.x.init(append(ftyp.RParams().list(), ftyp.TParams().list()...)) + u.x.init(append(ftyp.RParams().list(), ftyp.TypeParams().list()...)) } else { u.x.init(ftyp.RParams().list()) } diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index c096c1b30b..eb1ecd9595 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -12,15 +12,15 @@ import ( // A Named represents a named (defined) type. type Named struct { check *Checker - info typeInfo // for cycle detection - obj *TypeName // corresponding declared object for declared types; placeholder for instantiated types - orig *Named // original, uninstantiated type - fromRHS Type // type (on RHS of declaration) this *Named type is derived from (for cycle reporting) - underlying Type // possibly a *Named during setup; never a *Named once set up completely - instPos *syntax.Pos // position information for lazy instantiation, or nil - tparams *TParamList // type parameters, or nil - targs *TypeList // type arguments (after instantiation), or nil - methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily + info typeInfo // for cycle detection + obj *TypeName // corresponding declared object for declared types; placeholder for instantiated types + orig *Named // original, uninstantiated type + fromRHS Type // type (on RHS of declaration) this *Named type is derived from (for cycle reporting) + underlying Type // possibly a *Named during setup; never a *Named once set up completely + instPos *syntax.Pos // position information for lazy instantiation, or nil + tparams *TypeParamList // type parameters, or nil + targs *TypeList // type arguments (after instantiation), or nil + methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily resolve func(*Named) ([]*TypeParam, Type, []*Func) once sync.Once @@ -58,10 +58,10 @@ func (t *Named) load() *Named { // (necessary because types2 expects the receiver type for methods // on defined interface types to be the Named rather than the // underlying Interface), maybe it should just handle calling - // SetTParams, SetUnderlying, and AddMethod instead? Those + // SetTypeParams, SetUnderlying, and AddMethod instead? Those // methods would need to support reentrant calls though. It would // also make the API more future-proof towards further extensions - // (like SetTParams). + // (like SetTypeParams). tparams, underlying, methods := t.resolve(t) @@ -78,7 +78,7 @@ func (t *Named) load() *Named { } // newNamed is like NewNamed but with a *Checker receiver and additional orig argument. -func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams *TParamList, methods []*Func) *Named { +func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams *TypeParamList, methods []*Func) *Named { typ := &Named{check: check, obj: obj, orig: orig, fromRHS: underlying, underlying: underlying, tparams: tparams, methods: methods} if typ.orig == nil { typ.orig = typ @@ -119,15 +119,15 @@ func (t *Named) Orig() *Named { return t.orig } // TODO(gri) Come up with a better representation and API to distinguish // between parameterized instantiated and non-instantiated types. -// TParams returns the type parameters of the named type t, or nil. +// TypeParams returns the type parameters of the named type t, or nil. // The result is non-nil for an (originally) parameterized type even if it is instantiated. -func (t *Named) TParams() *TParamList { return t.load().tparams } +func (t *Named) TypeParams() *TypeParamList { return t.load().tparams } -// SetTParams sets the type parameters of the named type t. -func (t *Named) SetTParams(tparams []*TypeParam) { t.load().tparams = bindTParams(tparams) } +// SetTypeParams sets the type parameters of the named type t. +func (t *Named) SetTypeParams(tparams []*TypeParam) { t.load().tparams = bindTParams(tparams) } -// TArgs returns the type arguments used to instantiate the named type t. -func (t *Named) TArgs() *TypeList { return t.targs } +// TypeArgs returns the type arguments used to instantiate the named type t. +func (t *Named) TypeArgs() *TypeList { return t.targs } // NumMethods returns the number of explicit methods whose receiver is named type t. func (t *Named) NumMethods() int { return len(t.load().methods) } @@ -245,8 +245,8 @@ func (n *Named) setUnderlying(typ Type) { func (n *Named) expand(env *Environment) *Named { if n.instPos != nil { // n must be loaded before instantiation, in order to have accurate - // tparams. This is done implicitly by the call to n.TParams, but making it - // explicit is harmless: load is idempotent. + // tparams. This is done implicitly by the call to n.TypeParams, but making + // it explicit is harmless: load is idempotent. n.load() var u Type if n.check.validateTArgLen(*n.instPos, n.tparams.Len(), n.targs.Len()) { @@ -268,7 +268,7 @@ func (n *Named) expand(env *Environment) *Named { // shouldn't return that instance from expand. env.typeForHash(h, n) } - u = n.check.subst(*n.instPos, n.orig.underlying, makeSubstMap(n.TParams().list(), n.targs.list()), env) + u = n.check.subst(*n.instPos, n.orig.underlying, makeSubstMap(n.TypeParams().list(), n.targs.list()), env) } else { u = Typ[Invalid] } diff --git a/src/cmd/compile/internal/types2/object.go b/src/cmd/compile/internal/types2/object.go index a3f5f913aa..9bc2e285ce 100644 --- a/src/cmd/compile/internal/types2/object.go +++ b/src/cmd/compile/internal/types2/object.go @@ -475,8 +475,8 @@ func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) { if _, ok := typ.(*Basic); ok { return } - if named, _ := typ.(*Named); named != nil && named.TParams().Len() > 0 { - newTypeWriter(buf, qf).tParamList(named.TParams().list()) + if named, _ := typ.(*Named); named != nil && named.TypeParams().Len() > 0 { + newTypeWriter(buf, qf).tParamList(named.TypeParams().list()) } if tname.IsAlias() { buf.WriteString(" =") diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 3ccafef990..473d22675f 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -21,7 +21,7 @@ func isNamed(typ Type) bool { func isGeneric(typ Type) bool { // A parameterized type is only instantiated if it doesn't have an instantiation already. named, _ := typ.(*Named) - return named != nil && named.obj != nil && named.targs == nil && named.TParams() != nil + return named != nil && named.obj != nil && named.targs == nil && named.TypeParams() != nil } func is(typ Type, what BasicInfo) bool { @@ -220,7 +220,7 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { // parameter names. if y, ok := y.(*Signature); ok { return x.variadic == y.variadic && - identicalTParams(x.TParams().list(), y.TParams().list(), cmpTags, p) && + identicalTParams(x.TypeParams().list(), y.TypeParams().list(), cmpTags, p) && identical(x.params, y.params, cmpTags, p) && identical(x.results, y.results, cmpTags, p) } @@ -305,8 +305,8 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { x.expand(nil) y.expand(nil) - xargs := x.TArgs().list() - yargs := y.TArgs().list() + xargs := x.TypeArgs().list() + yargs := y.TypeArgs().list() if len(xargs) != len(yargs) { return false diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index a7d0db624c..eeaf1acbd6 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -19,13 +19,13 @@ type Signature struct { // and store it in the Func Object) because when type-checking a function // literal we call the general type checker which returns a general Type. // We then unpack the *Signature and use the scope for the literal body. - rparams *TParamList // receiver type parameters from left to right, or nil - tparams *TParamList // type parameters from left to right, or nil - scope *Scope // function scope, present for package-local signatures - recv *Var // nil if not a method - params *Tuple // (incoming) parameters from left to right; or nil - results *Tuple // (outgoing) results from left to right; or nil - variadic bool // true if the last parameter's type is of the form ...T (or string, for append built-in only) + rparams *TypeParamList // receiver type parameters from left to right, or nil + tparams *TypeParamList // type parameters from left to right, or nil + scope *Scope // function scope, present for package-local signatures + recv *Var // nil if not a method + params *Tuple // (incoming) parameters from left to right; or nil + results *Tuple // (outgoing) results from left to right; or nil + variadic bool // true if the last parameter's type is of the form ...T (or string, for append built-in only) } // NewSignature returns a new function type for the given receiver, parameters, @@ -53,14 +53,14 @@ func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature { // contain methods whose receiver type is a different interface. func (s *Signature) Recv() *Var { return s.recv } -// TParams returns the type parameters of signature s, or nil. -func (s *Signature) TParams() *TParamList { return s.tparams } +// TypeParams returns the type parameters of signature s, or nil. +func (s *Signature) TypeParams() *TypeParamList { return s.tparams } -// SetTParams sets the type parameters of signature s. -func (s *Signature) SetTParams(tparams []*TypeParam) { s.tparams = bindTParams(tparams) } +// SetTypeParams sets the type parameters of signature s. +func (s *Signature) SetTypeParams(tparams []*TypeParam) { s.tparams = bindTParams(tparams) } // RParams returns the receiver type parameters of signature s, or nil. -func (s *Signature) RParams() *TParamList { return s.rparams } +func (s *Signature) RParams() *TypeParamList { return s.rparams } // SetRParams sets the receiver type params of signature s. func (s *Signature) SetRParams(rparams []*TypeParam) { s.rparams = bindTParams(rparams) } @@ -133,7 +133,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] // again when we type-check the signature. // TODO(gri) maybe the receiver should be marked as invalid instead? if recv, _ := check.genericType(rname, false).(*Named); recv != nil { - recvTParams = recv.TParams().list() + recvTParams = recv.TypeParams().list() } } // provide type parameter bounds @@ -213,7 +213,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] T.expand(nil) // The receiver type may be an instantiated type referred to // by an alias (which cannot have receiver parameters for now). - if T.TArgs() != nil && sig.RParams() == nil { + if T.TypeArgs() != nil && sig.RParams() == nil { check.errorf(recv.pos, "cannot define methods on instantiated type %s", recv.typ) break } diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 2032305fab..752e107e11 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -179,13 +179,13 @@ func (subst *subster) typ(typ Type) Type { } } - if t.TParams().Len() == 0 { + if t.TypeParams().Len() == 0 { dump(">>> %s is not parameterized", t) return t // type is not parameterized } var newTArgs []Type - assert(t.targs.Len() == t.TParams().Len()) + assert(t.targs.Len() == t.TypeParams().Len()) // already instantiated dump(">>> %s already instantiated", t) @@ -198,7 +198,7 @@ func (subst *subster) typ(typ Type) Type { if new_targ != targ { dump(">>> substituted %d targ %s => %s", i, targ, new_targ) if newTArgs == nil { - newTArgs = make([]Type, t.TParams().Len()) + newTArgs = make([]Type, t.TypeParams().Len()) copy(newTArgs, t.targs.list()) } newTArgs[i] = new_targ diff --git a/src/cmd/compile/internal/types2/typelists.go b/src/cmd/compile/internal/types2/typelists.go index f313ea310e..ababe85909 100644 --- a/src/cmd/compile/internal/types2/typelists.go +++ b/src/cmd/compile/internal/types2/typelists.go @@ -6,20 +6,20 @@ package types2 import "bytes" -// TParamList holds a list of type parameters. -type TParamList struct{ tparams []*TypeParam } +// TypeParamList holds a list of type parameters. +type TypeParamList struct{ tparams []*TypeParam } // Len returns the number of type parameters in the list. // It is safe to call on a nil receiver. -func (l *TParamList) Len() int { return len(l.list()) } +func (l *TypeParamList) Len() int { return len(l.list()) } // At returns the i'th type parameter in the list. -func (l *TParamList) At(i int) *TypeParam { return l.tparams[i] } +func (l *TypeParamList) At(i int) *TypeParam { return l.tparams[i] } // list is for internal use where we expect a []*TypeParam. // TODO(rfindley): list should probably be eliminated: we can pass around a -// TParamList instead. -func (l *TParamList) list() []*TypeParam { +// TypeParamList instead. +func (l *TypeParamList) list() []*TypeParam { if l == nil { return nil } @@ -66,7 +66,7 @@ func (l *TypeList) String() string { // ---------------------------------------------------------------------------- // Implementation -func bindTParams(list []*TypeParam) *TParamList { +func bindTParams(list []*TypeParam) *TypeParamList { if len(list) == 0 { return nil } @@ -76,5 +76,5 @@ func bindTParams(list []*TypeParam) *TParamList { } typ.index = i } - return &TParamList{tparams: list} + return &TypeParamList{tparams: list} } diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index e7181281af..505596f571 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -29,7 +29,7 @@ type TypeParam struct { func (t *TypeParam) Obj() *TypeName { return t.obj } // NewTypeParam returns a new TypeParam. Type parameters may be set on a Named -// or Signature type by calling SetTParams. Setting a type parameter on more +// or Signature type by calling SetTypeParams. Setting a type parameter on more // than one type will result in a panic. // // The constraint argument can be nil, and set later via SetConstraint. diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 23fd788fbe..39ba278d53 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -237,9 +237,9 @@ func (w *typeWriter) typ(typ Type) { if t.targs != nil { // instantiated type w.typeList(t.targs.list()) - } else if w.env == nil && t.TParams().Len() != 0 { // For type hashing, don't need to format the TParams + } else if w.env == nil && t.TypeParams().Len() != 0 { // For type hashing, don't need to format the TParams // parameterized type - w.tParamList(t.TParams().list()) + w.tParamList(t.TypeParams().list()) } case *TypeParam: @@ -358,8 +358,8 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) { } func (w *typeWriter) signature(sig *Signature) { - if sig.TParams().Len() != 0 { - w.tParamList(sig.TParams().list()) + if sig.TypeParams().Len() != 0 { + w.tParamList(sig.TypeParams().list()) } w.tuple(sig.params, sig.variadic) -- GitLab From a1f6208e56436281ce5e26ad745f8fc3f7a9b280 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 8 Sep 2021 16:03:57 -0700 Subject: [PATCH 1068/2500] go/types, types2: add Environment to Config Port to types2 and adjust compiler accordingly. Change-Id: I2e72b151ef834977dca64cb2e62cedcac4e46062 Reviewed-on: https://go-review.googlesource.com/c/go/+/348578 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Matthew Dempsky Reviewed-by: Robert Findley TryBot-Result: Go Bot --- src/cmd/compile/internal/noder/import.go | 10 +++++----- src/cmd/compile/internal/noder/irgen.go | 7 ++++--- src/cmd/compile/internal/noder/reader2.go | 10 ++++------ src/cmd/compile/internal/noder/unified.go | 4 ++-- src/cmd/compile/internal/types2/api.go | 5 +++++ src/cmd/compile/internal/types2/check.go | 7 +++++-- src/cmd/compile/internal/types2/decl.go | 2 +- src/cmd/compile/internal/types2/instantiate.go | 2 +- src/cmd/compile/internal/types2/named.go | 2 +- src/cmd/compile/internal/types2/subst.go | 2 +- src/go/types/api.go | 5 +++++ src/go/types/check.go | 7 +++++-- src/go/types/decl.go | 2 +- src/go/types/instantiate.go | 2 +- src/go/types/named.go | 2 +- src/go/types/subst.go | 2 +- 16 files changed, 43 insertions(+), 28 deletions(-) diff --git a/src/cmd/compile/internal/noder/import.go b/src/cmd/compile/internal/noder/import.go index c26340c960..f13f8ca7f5 100644 --- a/src/cmd/compile/internal/noder/import.go +++ b/src/cmd/compile/internal/noder/import.go @@ -43,12 +43,12 @@ var haveLegacyImports = false // for an imported package by overloading writeNewExportFunc, then // that payload will be mapped into memory and passed to // newReadImportFunc. -var newReadImportFunc = func(data string, pkg1 *types.Pkg, check *types2.Checker, packages map[string]*types2.Package) (pkg2 *types2.Package, err error) { +var newReadImportFunc = func(data string, pkg1 *types.Pkg, env *types2.Environment, packages map[string]*types2.Package) (pkg2 *types2.Package, err error) { panic("unexpected new export data payload") } type gcimports struct { - check *types2.Checker + env *types2.Environment packages map[string]*types2.Package } @@ -61,7 +61,7 @@ func (m *gcimports) ImportFrom(path, srcDir string, mode types2.ImportMode) (*ty panic("mode must be 0") } - _, pkg, err := readImportFile(path, typecheck.Target, m.check, m.packages) + _, pkg, err := readImportFile(path, typecheck.Target, m.env, m.packages) return pkg, err } @@ -224,7 +224,7 @@ func parseImportPath(pathLit *syntax.BasicLit) (string, error) { // readImportFile reads the import file for the given package path and // returns its types.Pkg representation. If packages is non-nil, the // types2.Package representation is also returned. -func readImportFile(path string, target *ir.Package, check *types2.Checker, packages map[string]*types2.Package) (pkg1 *types.Pkg, pkg2 *types2.Package, err error) { +func readImportFile(path string, target *ir.Package, env *types2.Environment, packages map[string]*types2.Package) (pkg1 *types.Pkg, pkg2 *types2.Package, err error) { path, err = resolveImportPath(path) if err != nil { return @@ -279,7 +279,7 @@ func readImportFile(path string, target *ir.Package, check *types2.Checker, pack return } - pkg2, err = newReadImportFunc(data, pkg1, check, packages) + pkg2, err = newReadImportFunc(data, pkg1, env, packages) } else { // We only have old data. Oh well, fall back to the legacy importers. haveLegacyImports = true diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index a67b3994da..414875615f 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -34,10 +34,13 @@ func checkFiles(noders []*noder) (posMap, *types2.Package, *types2.Info) { } // typechecking + env := types2.NewEnvironment() importer := gcimports{ + env: env, packages: map[string]*types2.Package{"unsafe": types2.Unsafe}, } conf := types2.Config{ + Environment: env, GoVersion: base.Flag.Lang, IgnoreLabels: true, // parser already checked via syntax.CheckBranches mode CompilerErrorMessages: true, // use error strings matching existing compiler errors @@ -60,9 +63,7 @@ func checkFiles(noders []*noder) (posMap, *types2.Package, *types2.Info) { // expand as needed } - pkg := types2.NewPackage(base.Ctxt.Pkgpath, "") - importer.check = types2.NewChecker(&conf, pkg, info) - err := importer.check.Files(files) + pkg, err := conf.Check(base.Ctxt.Pkgpath, files, info) base.ExitIfErrors() if err != nil { diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index 3886d571b5..6e2d1f2e76 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -18,7 +18,7 @@ import ( type pkgReader2 struct { pkgDecoder - check *types2.Checker + env *types2.Environment imports map[string]*types2.Package posBases []*syntax.PosBase @@ -26,11 +26,11 @@ type pkgReader2 struct { typs []types2.Type } -func readPackage2(check *types2.Checker, imports map[string]*types2.Package, input pkgDecoder) *types2.Package { +func readPackage2(env *types2.Environment, imports map[string]*types2.Package, input pkgDecoder) *types2.Package { pr := pkgReader2{ pkgDecoder: input, - check: check, + env: env, imports: imports, posBases: make([]*syntax.PosBase, input.numElems(relocPosBase)), @@ -233,9 +233,7 @@ func (r *reader2) doTyp() (res types2.Type) { obj, targs := r.obj() name := obj.(*types2.TypeName) if len(targs) != 0 { - // TODO(mdempsky) should use a single shared environment here - // (before, this used a shared checker) - t, _ := types2.Instantiate(types2.NewEnvironment(), name.Type(), targs, false) + t, _ := types2.Instantiate(r.p.env, name.Type(), targs, false) return t } return name.Type() diff --git a/src/cmd/compile/internal/noder/unified.go b/src/cmd/compile/internal/noder/unified.go index bf63608bf1..02f64d00ac 100644 --- a/src/cmd/compile/internal/noder/unified.go +++ b/src/cmd/compile/internal/noder/unified.go @@ -78,12 +78,12 @@ func unified(noders []*noder) { base.Errorf("cannot use -G and -d=quirksmode together") } - newReadImportFunc = func(data string, pkg1 *types.Pkg, check *types2.Checker, packages map[string]*types2.Package) (pkg2 *types2.Package, err error) { + newReadImportFunc = func(data string, pkg1 *types.Pkg, env *types2.Environment, packages map[string]*types2.Package) (pkg2 *types2.Package, err error) { pr := newPkgDecoder(pkg1.Path, data) // Read package descriptors for both types2 and compiler backend. readPackage(newPkgReader(pr), pkg1) - pkg2 = readPackage2(check, packages, pr) + pkg2 = readPackage2(env, packages, pr) return } diff --git a/src/cmd/compile/internal/types2/api.go b/src/cmd/compile/internal/types2/api.go index b2938b84da..6914e6c89f 100644 --- a/src/cmd/compile/internal/types2/api.go +++ b/src/cmd/compile/internal/types2/api.go @@ -108,6 +108,11 @@ type ImporterFrom interface { // A Config specifies the configuration for type checking. // The zero value for Config is a ready-to-use default configuration. type Config struct { + // Environment is the environment used for resolving global + // identifiers. If nil, the type checker will initialize this + // field with a newly created environment. + Environment *Environment + // GoVersion describes the accepted Go language version. The string // must follow the format "go%d.%d" (e.g. "go1.12") or ist must be // empty; an empty string indicates the latest language version. diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go index c7b45d86d1..24a05e6b37 100644 --- a/src/cmd/compile/internal/types2/check.go +++ b/src/cmd/compile/internal/types2/check.go @@ -86,7 +86,6 @@ type Checker struct { nextID uint64 // unique Id for type parameters (first valid Id is 1) objMap map[Object]*declInfo // maps package-level objects and (non-interface) methods to declaration info impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package - env *Environment // for deduplicating identical instances // pkgPathMap maps package names to the set of distinct import paths we've // seen for that name, anywhere in the import graph. It is used for @@ -171,6 +170,11 @@ func NewChecker(conf *Config, pkg *Package, info *Info) *Checker { conf = new(Config) } + // make sure we have an environment + if conf.Environment == nil { + conf.Environment = NewEnvironment() + } + // make sure we have an info struct if info == nil { info = new(Info) @@ -188,7 +192,6 @@ func NewChecker(conf *Config, pkg *Package, info *Info) *Checker { version: version, objMap: make(map[Object]*declInfo), impMap: make(map[importKey]*Package), - env: NewEnvironment(), } } diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 4181be9fa8..905c21426c 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -317,7 +317,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { } case *Named: - t.expand(check.env) + t.expand(check.conf.Environment) // don't touch the type if it is from a different package or the Universe scope // (doing so would lead to a race condition - was issue #35049) diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 3ea21f921b..469ceea5c4 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -71,7 +71,7 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, posLis }() } - inst := check.instance(pos, typ, targs, check.env) + inst := check.instance(pos, typ, targs, check.conf.Environment) assert(len(posList) <= len(targs)) check.later(func() { diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index eb1ecd9595..99410aedfb 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -254,7 +254,7 @@ func (n *Named) expand(env *Environment) *Named { // in subst) feels overly complicated. Can we simplify? if env == nil { if n.check != nil { - env = n.check.env + env = n.check.conf.Environment } else { // If we're instantiating lazily, we might be outside the scope of a // type-checking pass. In that case we won't have a pre-existing diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 752e107e11..4627dd3c5b 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -59,7 +59,7 @@ func (check *Checker) subst(pos syntax.Pos, typ Type, smap substMap, env *Enviro if check != nil { subst.check = check if env == nil { - env = check.env + env = check.conf.Environment } } if env == nil { diff --git a/src/go/types/api.go b/src/go/types/api.go index 5beeff530c..ebc3a01266 100644 --- a/src/go/types/api.go +++ b/src/go/types/api.go @@ -115,6 +115,11 @@ type ImporterFrom interface { // A Config specifies the configuration for type checking. // The zero value for Config is a ready-to-use default configuration. type Config struct { + // Environment is the environment used for resolving global + // identifiers. If nil, the type checker will initialize this + // field with a newly created environment. + Environment *Environment + // GoVersion describes the accepted Go language version. The string // must follow the format "go%d.%d" (e.g. "go1.12") or it must be // empty; an empty string indicates the latest language version. diff --git a/src/go/types/check.go b/src/go/types/check.go index 0383a58c64..63f4cbd4a0 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -89,7 +89,6 @@ type Checker struct { nextID uint64 // unique Id for type parameters (first valid Id is 1) objMap map[Object]*declInfo // maps package-level objects and (non-interface) methods to declaration info impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package - env *Environment // for deduplicating identical instances // pkgPathMap maps package names to the set of distinct import paths we've // seen for that name, anywhere in the import graph. It is used for @@ -174,6 +173,11 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch conf = new(Config) } + // make sure we have an environment + if conf.Environment == nil { + conf.Environment = NewEnvironment() + } + // make sure we have an info struct if info == nil { info = new(Info) @@ -192,7 +196,6 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch version: version, objMap: make(map[Object]*declInfo), impMap: make(map[importKey]*Package), - env: NewEnvironment(), } } diff --git a/src/go/types/decl.go b/src/go/types/decl.go index d132d30b9d..f679c33a94 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -316,7 +316,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { } case *Named: - t.expand(check.env) + t.expand(check.conf.Environment) // don't touch the type if it is from a different package or the Universe scope // (doing so would lead to a race condition - was issue #35049) if t.obj.pkg != check.pkg { diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 040877829c..50be07b8fd 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -71,7 +71,7 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, posList }() } - inst := check.instance(pos, typ, targs, check.env) + inst := check.instance(pos, typ, targs, check.conf.Environment) assert(len(posList) <= len(targs)) check.later(func() { diff --git a/src/go/types/named.go b/src/go/types/named.go index 51c4a236da..74681ab2d4 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -254,7 +254,7 @@ func (n *Named) expand(env *Environment) *Named { // in subst) feels overly complicated. Can we simplify? if env == nil { if n.check != nil { - env = n.check.env + env = n.check.conf.Environment } else { // If we're instantiating lazily, we might be outside the scope of a // type-checking pass. In that case we won't have a pre-existing diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 4f9d76d598..07fe6a6b6e 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -62,7 +62,7 @@ func (check *Checker) subst(pos token.Pos, typ Type, smap substMap, env *Environ if check != nil { subst.check = check if env == nil { - env = check.env + env = check.conf.Environment } } if env == nil { -- GitLab From e30a09013b24853cbe6d3d3a919e639df0bdf41c Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 8 Sep 2021 15:59:11 -0700 Subject: [PATCH 1069/2500] cmd/compile: extrapolate $GOROOT in unified IR This ensures that diagnostics for files within $GOROOT continue to be reported using their full filepath, rather than the abbreviated filepath. Notably, this is necessary for test/run.go, which has tests that expect to see the full filepath. Updates #48247. Change-Id: I440e2c6dd6109ca059d81cee49e476bba805d703 Reviewed-on: https://go-review.googlesource.com/c/go/+/348670 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/cmd/compile/internal/noder/reader.go | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 204d25bce8..b3cb10dadb 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -10,6 +10,7 @@ import ( "bytes" "fmt" "go/constant" + "internal/buildcfg" "strings" "cmd/compile/internal/base" @@ -194,15 +195,32 @@ func (pr *pkgReader) posBaseIdx(idx int) *src.PosBase { r := pr.newReader(relocPosBase, idx, syncPosBase) var b *src.PosBase - filename := r.string() + absFilename := r.string() + filename := absFilename + + // For build artifact stability, the export data format only + // contains the "absolute" filename as returned by objabi.AbsFile. + // However, some tests (e.g., test/run.go's asmcheck tests) expect + // to see the full, original filename printed out. Re-expanding + // "$GOROOT" to buildcfg.GOROOT is a close-enough approximation to + // satisfy this. + // + // TODO(mdempsky): De-duplicate this logic with similar logic in + // cmd/link/internal/ld's expandGoroot. However, this will probably + // require being more consistent about when we use native vs UNIX + // file paths. + const dollarGOROOT = "$GOROOT" + if strings.HasPrefix(filename, dollarGOROOT) { + filename = buildcfg.GOROOT + filename[len(dollarGOROOT):] + } if r.bool() { - b = src.NewFileBase(filename, filename) + b = src.NewFileBase(filename, absFilename) } else { pos := r.pos0() line := r.uint() col := r.uint() - b = src.NewLinePragmaBase(pos, filename, filename, line, col) + b = src.NewLinePragmaBase(pos, filename, absFilename, line, col) } pr.posBases[idx] = b -- GitLab From 4c52eac49b7e3f2a107419583012e5251ccbfde9 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 7 Sep 2021 13:23:08 -0700 Subject: [PATCH 1070/2500] cmd/compile: simplify value coding for unified IR In indexed export, values are always exported along with their type and are encoded in a type-sensitive manner, because this matches how cmd/compile handled constants internally. However, go/types intentionally differs from this, decoupling type from value representation. As unified IR strives to be more go/types-centric, it makes sense to embrace this and make values a more first-class encoding. Change-Id: If21d849c4f610358bd776d5665469d180bcd5f6e Reviewed-on: https://go-review.googlesource.com/c/go/+/348014 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/noder/decoder.go | 3 ++- src/cmd/compile/internal/noder/encoder.go | 3 ++- src/cmd/compile/internal/noder/reader.go | 12 ++++-------- src/cmd/compile/internal/noder/reader2.go | 10 ++-------- src/cmd/compile/internal/noder/writer.go | 12 ++++-------- 5 files changed, 14 insertions(+), 26 deletions(-) diff --git a/src/cmd/compile/internal/noder/decoder.go b/src/cmd/compile/internal/noder/decoder.go index 3dc61c6a69..2c18727420 100644 --- a/src/cmd/compile/internal/noder/decoder.go +++ b/src/cmd/compile/internal/noder/decoder.go @@ -255,7 +255,8 @@ func (r *decoder) strings() []string { return res } -func (r *decoder) rawValue() constant.Value { +func (r *decoder) value() constant.Value { + r.sync(syncValue) isComplex := r.bool() val := r.scalar() if isComplex { diff --git a/src/cmd/compile/internal/noder/encoder.go b/src/cmd/compile/internal/noder/encoder.go index d8ab0f6255..b07b3a4a48 100644 --- a/src/cmd/compile/internal/noder/encoder.go +++ b/src/cmd/compile/internal/noder/encoder.go @@ -237,7 +237,8 @@ func (w *encoder) strings(ss []string) { } } -func (w *encoder) rawValue(val constant.Value) { +func (w *encoder) value(val constant.Value) { + w.sync(syncValue) if w.bool(val.Kind() == constant.Complex) { w.scalar(constant.Real(val)) w.scalar(constant.Imag(val)) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index b3cb10dadb..e235dd5792 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -626,7 +626,8 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node case objConst: name := do(ir.OLITERAL, false) - typ, val := r.value() + typ := r.typ() + val := FixValue(typ, r.value()) setType(name, typ) setValue(name, val) return name @@ -755,12 +756,6 @@ func (r *reader) typeParamNames() { } } -func (r *reader) value() (*types.Type, constant.Value) { - r.sync(syncValue) - typ := r.typ() - return typ, FixValue(typ, r.rawValue()) -} - func (r *reader) method() *types.Field { r.sync(syncMethod) pos := r.pos() @@ -1556,7 +1551,8 @@ func (r *reader) expr() (res ir.Node) { case exprConst: pos := r.pos() - typ, val := r.value() + typ := r.typ() + val := FixValue(typ, r.value()) op := r.op() orig := r.string() return typecheck.Expr(OrigConst(pos, typ, val, op, orig)) diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index 6e2d1f2e76..0cfde24b58 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -7,8 +7,6 @@ package noder import ( - "go/constant" - "cmd/compile/internal/base" "cmd/compile/internal/syntax" "cmd/compile/internal/types2" @@ -388,7 +386,8 @@ func (pr *pkgReader2) objIdx(idx int) (*types2.Package, string) { case objConst: pos := r.pos() - typ, val := r.value() + typ := r.typ() + val := r.value() return types2.NewConst(pos, objPkg, objName, typ, val) case objFunc: @@ -428,11 +427,6 @@ func (pr *pkgReader2) objIdx(idx int) (*types2.Package, string) { return objPkg, objName } -func (r *reader2) value() (types2.Type, constant.Value) { - r.sync(syncValue) - return r.typ(), r.rawValue() -} - func (pr *pkgReader2) objDictIdx(idx int) *reader2Dict { r := pr.newReader(relocObjDict, idx, syncObject1) diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index d1e5605739..694035b73f 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -542,7 +542,8 @@ func (w *writer) doObj(obj types2.Object) codeObj { case *types2.Const: w.pos(obj) - w.value(obj.Type(), obj.Val()) + w.typ(obj.Type()) + w.value(obj.Val()) return objConst case *types2.Func: @@ -598,12 +599,6 @@ func (w *writer) typExpr(expr syntax.Expr) { w.typ(tv.Type) } -func (w *writer) value(typ types2.Type, val constant.Value) { - w.sync(syncValue) - w.typ(typ) - w.rawValue(val) -} - // objDict writes the dictionary needed for reading the given object. func (w *writer) objDict(obj types2.Object, dict *writerDict) { // TODO(mdempsky): Split objDict into multiple entries? reader.go @@ -1199,7 +1194,8 @@ func (w *writer) expr(expr syntax.Expr) { w.code(exprConst) w.pos(pos) - w.value(tv.Type, tv.Value) + w.typ(tv.Type) + w.value(tv.Value) // TODO(mdempsky): These details are only important for backend // diagnostics. Explore writing them out separately. -- GitLab From 42563f89d7093ab22e1ac42351e66c4d03e0c80e Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 7 Sep 2021 17:24:50 -0700 Subject: [PATCH 1071/2500] cmd/compile: remove 'ext' fields from unified IR reader/writer types This is a vestigial artifact of how I initially split apart the public and private data for objects. But now objects are split into more parts, and it's proven easier to just keep them as separate variables. So it's time to cleanup the initial public/private code to follow the same approach. Change-Id: I3976b19fb433cbe21d299d3799ec616f9e59561e Reviewed-on: https://go-review.googlesource.com/c/go/+/348412 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/noder/reader.go | 18 ++++++------- src/cmd/compile/internal/noder/unified.go | 2 -- src/cmd/compile/internal/noder/writer.go | 32 +++++++++-------------- 3 files changed, 20 insertions(+), 32 deletions(-) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index e235dd5792..57e8476099 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -79,8 +79,6 @@ type reader struct { p *pkgReader - ext *reader - dict *readerDict // TODO(mdempsky): The state below is all specific to reading @@ -586,10 +584,10 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node dict := pr.objDictIdx(sym, idx, implicits, explicits) r := pr.newReader(relocObj, idx, syncObject1) - r.ext = pr.newReader(relocObjExt, idx, syncObject1) + rext := pr.newReader(relocObjExt, idx, syncObject1) r.dict = dict - r.ext.dict = dict + rext.dict = dict sym = r.mangle(sym) if !sym.IsBlank() && sym.Def != nil { @@ -642,7 +640,7 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node name.Func = ir.NewFunc(r.pos()) name.Func.Nname = name - r.ext.funcExt(name) + rext.funcExt(name) return name case objType: @@ -651,7 +649,7 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node setType(name, typ) // Important: We need to do this before SetUnderlying. - r.ext.typeExt(name) + rext.typeExt(name) // We need to defer CheckSize until we've called SetUnderlying to // handle recursive types. @@ -661,7 +659,7 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node methods := make([]*types.Field, r.len()) for i := range methods { - methods[i] = r.method() + methods[i] = r.method(rext) } if len(methods) != 0 { typ.Methods().Set(methods) @@ -674,7 +672,7 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node case objVar: name := do(ir.ONAME, false) setType(name, r.typ()) - r.ext.varExt(name) + rext.varExt(name) return name } } @@ -756,7 +754,7 @@ func (r *reader) typeParamNames() { } } -func (r *reader) method() *types.Field { +func (r *reader) method(rext *reader) *types.Field { r.sync(syncMethod) pos := r.pos() pkg, sym := r.selector() @@ -772,7 +770,7 @@ func (r *reader) method() *types.Field { name.Func = ir.NewFunc(r.pos()) name.Func.Nname = name - r.ext.funcExt(name) + rext.funcExt(name) meth := types.NewField(name.Func.Pos(), sym, typ) meth.Nname = name diff --git a/src/cmd/compile/internal/noder/unified.go b/src/cmd/compile/internal/noder/unified.go index 02f64d00ac..eff2eeaeff 100644 --- a/src/cmd/compile/internal/noder/unified.go +++ b/src/cmd/compile/internal/noder/unified.go @@ -106,7 +106,6 @@ func unified(noders []*noder) { readPackage(localPkgReader, types.LocalPkg) r := localPkgReader.newReader(relocMeta, privateRootIdx, syncPrivate) - r.ext = r r.pkgInit(types.LocalPkg, target) // Type-check any top-level assignments. We ignore non-assignments @@ -190,7 +189,6 @@ func writePkgStub(noders []*noder) string { { w := privateRootWriter - w.ext = w w.pkgInit(noders) w.flush() } diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 694035b73f..e1413da1d8 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -75,14 +75,6 @@ type writer struct { encoder - // For writing out object descriptions, ext points to the extension - // writer for where we can write the compiler's private extension - // details for the object. - // - // TODO(mdempsky): This is a little hacky, but works easiest with - // the way things are currently. - ext *writer - // TODO(mdempsky): We should be able to prune localsIdx whenever a // scope closes, and then maybe we can just use the same map for // storing the TypeParams too (as their TypeName instead). @@ -504,21 +496,21 @@ func (pw *pkgWriter) objIdx(obj types2.Object) int { } w := pw.newWriter(relocObj, syncObject1) - w.ext = pw.newWriter(relocObjExt, syncObject1) + wext := pw.newWriter(relocObjExt, syncObject1) wname := pw.newWriter(relocName, syncObject1) wdict := pw.newWriter(relocObjDict, syncObject1) pw.globalsIdx[obj] = w.idx // break cycles - assert(w.ext.idx == w.idx) + assert(wext.idx == w.idx) assert(wname.idx == w.idx) assert(wdict.idx == w.idx) w.dict = dict - w.ext.dict = dict + wext.dict = dict - code := w.doObj(obj) + code := w.doObj(wext, obj) w.flush() - w.ext.flush() + wext.flush() wname.qualifiedIdent(obj) wname.code(code) @@ -530,7 +522,7 @@ func (pw *pkgWriter) objIdx(obj types2.Object) int { return w.idx } -func (w *writer) doObj(obj types2.Object) codeObj { +func (w *writer) doObj(wext *writer, obj types2.Object) codeObj { if obj.Pkg() != w.p.curpkg { return objStub } @@ -555,7 +547,7 @@ func (w *writer) doObj(obj types2.Object) codeObj { w.typeParamNames(sig.TypeParams()) w.signature(sig) w.pos(decl) - w.ext.funcExt(obj) + wext.funcExt(obj) return objFunc case *types2.TypeName: @@ -573,12 +565,12 @@ func (w *writer) doObj(obj types2.Object) codeObj { w.pos(obj) w.typeParamNames(named.TypeParams()) - w.ext.typeExt(obj) + wext.typeExt(obj) w.typExpr(decl.Type) w.len(named.NumMethods()) for i := 0; i < named.NumMethods(); i++ { - w.method(named.Method(i)) + w.method(wext, named.Method(i)) } return objType @@ -586,7 +578,7 @@ func (w *writer) doObj(obj types2.Object) codeObj { case *types2.Var: w.pos(obj) w.typ(obj.Type()) - w.ext.varExt(obj) + wext.varExt(obj) return objVar } } @@ -648,7 +640,7 @@ func (w *writer) typeParamNames(tparams *types2.TypeParamList) { } } -func (w *writer) method(meth *types2.Func) { +func (w *writer) method(wext *writer, meth *types2.Func) { decl, ok := w.p.funDecls[meth] assert(ok) sig := meth.Type().(*types2.Signature) @@ -661,7 +653,7 @@ func (w *writer) method(meth *types2.Func) { w.signature(sig) w.pos(decl) // XXX: Hack to workaround linker limitations. - w.ext.funcExt(meth) + wext.funcExt(meth) } // qualifiedIdent writes out the name of an object declared at package -- GitLab From 9cbc76bdf90752e21a2b3f05944552e1373ab433 Mon Sep 17 00:00:00 2001 From: fanzha02 Date: Tue, 24 Aug 2021 12:46:54 +0800 Subject: [PATCH 1072/2500] cmd/internal/obj/arm64: add checks for incorrect use of REGTMP register The current assembler uses REGTMP as a temporary destination register, when optimizing one instruction into a multi-instruction sequence. But in some cases, when the source register is REGTMP, this behavior is incorrect. For example: ADD $0x1234567, R27, R3 The current assembler encodes it into MOVD $17767, R27 MOVK $(291<<16), R27 ADD R27, R27, R3 It is illegal to overwrite R27. This CL adds the related checks. Add test cases. Change-Id: I0af373d9fd23d8f067c093778dd4cc76748faf38 Reviewed-on: https://go-review.googlesource.com/c/go/+/344689 Reviewed-by: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Trust: fannie zhang --- .../asm/internal/asm/testdata/arm64error.s | 21 ++++++++++++------- src/cmd/internal/obj/arm64/asm7.go | 21 +++++++++++++++++++ 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/arm64error.s b/src/cmd/asm/internal/asm/testdata/arm64error.s index 8b12b16680..7b006432c0 100644 --- a/src/cmd/asm/internal/asm/testdata/arm64error.s +++ b/src/cmd/asm/internal/asm/testdata/arm64error.s @@ -406,12 +406,12 @@ TEXT errors(SB),$0 VBIF V0.D2, V1.D2, V2.D2 // ERROR "invalid arrangement" VUADDW V9.B8, V12.H8, V14.B8 // ERROR "invalid arrangement" VUADDW2 V9.B8, V12.S4, V14.S4 // ERROR "operand mismatch" - VUMAX V1.D2, V2.D2, V3.D2 // ERROR "invalid arrangement" - VUMIN V1.D2, V2.D2, V3.D2 // ERROR "invalid arrangement" + VUMAX V1.D2, V2.D2, V3.D2 // ERROR "invalid arrangement" + VUMIN V1.D2, V2.D2, V3.D2 // ERROR "invalid arrangement" VUMAX V1.B8, V2.B8, V3.B16 // ERROR "operand mismatch" VUMIN V1.H4, V2.S4, V3.H4 // ERROR "operand mismatch" VSLI $64, V7.D2, V8.D2 // ERROR "shift out of range" - VUSRA $0, V7.D2, V8.D2 // ERROR "shift out of range" + VUSRA $0, V7.D2, V8.D2 // ERROR "shift out of range" CASPD (R3, R4), (R2), (R8, R9) // ERROR "source register pair must start from even register" CASPD (R2, R3), (R2), (R9, R10) // ERROR "destination register pair must start from even register" CASPD (R2, R4), (R2), (R8, R9) // ERROR "source register pair must be contiguous" @@ -419,8 +419,15 @@ TEXT errors(SB),$0 ADD R1>>2, RSP, R3 // ERROR "illegal combination" ADDS R2<<3, R3, RSP // ERROR "unexpected SP reference" CMP R1<<5, RSP // ERROR "the left shift amount out of range 0 to 4" - MOVD.P y+8(FP), R1 // ERROR "illegal combination" - MOVD.W x-8(SP), R1 // ERROR "illegal combination" - LDP.P x+8(FP), (R0, R1) // ERROR "illegal combination" - LDP.W x+8(SP), (R0, R1) // ERROR "illegal combination" + MOVD.P y+8(FP), R1 // ERROR "illegal combination" + MOVD.W x-8(SP), R1 // ERROR "illegal combination" + LDP.P x+8(FP), (R0, R1) // ERROR "illegal combination" + LDP.W x+8(SP), (R0, R1) // ERROR "illegal combination" + ADD $0x1234567, R27, R3 // ERROR "cannot use REGTMP as source" + ADD $0x3fffffffc000, R27, R5 // ERROR "cannot use REGTMP as source" + AND $0x22220000, R27, R4 // ERROR "cannot use REGTMP as source" + ANDW $0x6006000060060, R27, R5 // ERROR "cannot use REGTMP as source" + STP (R3, R4), 0x1234567(R27) // ERROR "REGTMP used in large offset store" + LDP 0x1234567(R27), (R3, R4) // ERROR "REGTMP used in large offset load" + STP (R26, R27), 700(R2) // ERROR "cannot use REGTMP as source" RET diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go index 8db25cf967..5d6caaed5f 100644 --- a/src/cmd/internal/obj/arm64/asm7.go +++ b/src/cmd/internal/obj/arm64/asm7.go @@ -3407,6 +3407,9 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { o4 = os[3] case 13: /* addop $vcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */ + if p.Reg == REGTMP { + c.ctxt.Diag("cannot use REGTMP as source: %v\n", p) + } if p.To.Reg == REG_RSP && isADDSop(p.As) { c.ctxt.Diag("illegal destination register: %v\n", p) } @@ -3724,6 +3727,9 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { o1 |= (uint32(r&31) << 5) | uint32(rt&31) case 28: /* logop $vcon, [R], R (64 bit literal) */ + if p.Reg == REGTMP { + c.ctxt.Diag("cannot use REGTMP as source: %v\n", p) + } o := uint32(0) num := uint8(0) cls := oclass(&p.From) @@ -4354,6 +4360,9 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { /* reloc ops */ case 64: /* movT R,addr -> adrp + add + movT R, (REGTMP) */ + if p.From.Reg == REGTMP { + c.ctxt.Diag("cannot use REGTMP as source: %v\n", p) + } o1 = ADR(1, 0, REGTMP) o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 rel := obj.Addrel(c.cursym) @@ -4585,6 +4594,9 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { // add Rtmp, R, Rtmp // ldp (Rtmp), (R1, R2) r := int(p.From.Reg) + if r == REGTMP { + c.ctxt.Diag("REGTMP used in large offset load: %v", p) + } if r == obj.REG_NONE { r = int(o.param) } @@ -4601,6 +4613,9 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { case 76: // add $O, R, Rtmp or sub $O, R, Rtmp // stp (R1, R2), (Rtmp) + if p.From.Reg == REGTMP || p.From.Offset == REGTMP { + c.ctxt.Diag("cannot use REGTMP as source: %v", p) + } r := int(p.To.Reg) if r == obj.REG_NONE { r = int(o.param) @@ -4628,6 +4643,9 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { // add Rtmp, R, Rtmp // stp (R1, R2), (Rtmp) r := int(p.To.Reg) + if r == REGTMP || p.From.Reg == REGTMP || p.From.Offset == REGTMP { + c.ctxt.Diag("REGTMP used in large offset store: %v", p) + } if r == obj.REG_NONE { r = int(o.param) } @@ -4933,6 +4951,9 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { o1 |= (uint32(Q&1) << 30) | (uint32((r>>5)&7) << 16) | (uint32(r&0x1f) << 5) | uint32(rt&31) case 87: /* stp (r,r), addr(SB) -> adrp + add + stp */ + if p.From.Reg == REGTMP || p.From.Offset == REGTMP { + c.ctxt.Diag("cannot use REGTMP as source: %v", p) + } o1 = ADR(1, 0, REGTMP) o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31 rel := obj.Addrel(c.cursym) -- GitLab From 8fad81cd6294776c63a3e9a5820f196949974861 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sat, 28 Aug 2021 16:40:34 +0700 Subject: [PATCH 1073/2500] cmd/compile: fold handling OCONV logic to separate function So next CL can re-use the logic to perform checkptr instrumentation. Change-Id: I3241e9c3c84da04db71fd1d4fd83cb76b2e18521 Reviewed-on: https://go-review.googlesource.com/c/go/+/345435 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ssagen/ssa.go | 338 +++++++++++++------------ 1 file changed, 170 insertions(+), 168 deletions(-) diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 1d5a872b1b..dd19a254f8 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -2323,6 +2323,175 @@ func (s *state) ssaShiftOp(op ir.Op, t *types.Type, u *types.Type) ssa.Op { return x } +func (s *state) conv(n ir.Node, v *ssa.Value, ft, tt *types.Type) *ssa.Value { + if ft.IsBoolean() && tt.IsKind(types.TUINT8) { + // Bool -> uint8 is generated internally when indexing into runtime.staticbyte. + return s.newValue1(ssa.OpCopy, tt, v) + } + if ft.IsInteger() && tt.IsInteger() { + var op ssa.Op + if tt.Size() == ft.Size() { + op = ssa.OpCopy + } else if tt.Size() < ft.Size() { + // truncation + switch 10*ft.Size() + tt.Size() { + case 21: + op = ssa.OpTrunc16to8 + case 41: + op = ssa.OpTrunc32to8 + case 42: + op = ssa.OpTrunc32to16 + case 81: + op = ssa.OpTrunc64to8 + case 82: + op = ssa.OpTrunc64to16 + case 84: + op = ssa.OpTrunc64to32 + default: + s.Fatalf("weird integer truncation %v -> %v", ft, tt) + } + } else if ft.IsSigned() { + // sign extension + switch 10*ft.Size() + tt.Size() { + case 12: + op = ssa.OpSignExt8to16 + case 14: + op = ssa.OpSignExt8to32 + case 18: + op = ssa.OpSignExt8to64 + case 24: + op = ssa.OpSignExt16to32 + case 28: + op = ssa.OpSignExt16to64 + case 48: + op = ssa.OpSignExt32to64 + default: + s.Fatalf("bad integer sign extension %v -> %v", ft, tt) + } + } else { + // zero extension + switch 10*ft.Size() + tt.Size() { + case 12: + op = ssa.OpZeroExt8to16 + case 14: + op = ssa.OpZeroExt8to32 + case 18: + op = ssa.OpZeroExt8to64 + case 24: + op = ssa.OpZeroExt16to32 + case 28: + op = ssa.OpZeroExt16to64 + case 48: + op = ssa.OpZeroExt32to64 + default: + s.Fatalf("weird integer sign extension %v -> %v", ft, tt) + } + } + return s.newValue1(op, tt, v) + } + + if ft.IsFloat() || tt.IsFloat() { + conv, ok := fpConvOpToSSA[twoTypes{s.concreteEtype(ft), s.concreteEtype(tt)}] + if s.config.RegSize == 4 && Arch.LinkArch.Family != sys.MIPS && !s.softFloat { + if conv1, ok1 := fpConvOpToSSA32[twoTypes{s.concreteEtype(ft), s.concreteEtype(tt)}]; ok1 { + conv = conv1 + } + } + if Arch.LinkArch.Family == sys.ARM64 || Arch.LinkArch.Family == sys.Wasm || Arch.LinkArch.Family == sys.S390X || s.softFloat { + if conv1, ok1 := uint64fpConvOpToSSA[twoTypes{s.concreteEtype(ft), s.concreteEtype(tt)}]; ok1 { + conv = conv1 + } + } + + if Arch.LinkArch.Family == sys.MIPS && !s.softFloat { + if ft.Size() == 4 && ft.IsInteger() && !ft.IsSigned() { + // tt is float32 or float64, and ft is also unsigned + if tt.Size() == 4 { + return s.uint32Tofloat32(n, v, ft, tt) + } + if tt.Size() == 8 { + return s.uint32Tofloat64(n, v, ft, tt) + } + } else if tt.Size() == 4 && tt.IsInteger() && !tt.IsSigned() { + // ft is float32 or float64, and tt is unsigned integer + if ft.Size() == 4 { + return s.float32ToUint32(n, v, ft, tt) + } + if ft.Size() == 8 { + return s.float64ToUint32(n, v, ft, tt) + } + } + } + + if !ok { + s.Fatalf("weird float conversion %v -> %v", ft, tt) + } + op1, op2, it := conv.op1, conv.op2, conv.intermediateType + + if op1 != ssa.OpInvalid && op2 != ssa.OpInvalid { + // normal case, not tripping over unsigned 64 + if op1 == ssa.OpCopy { + if op2 == ssa.OpCopy { + return v + } + return s.newValueOrSfCall1(op2, tt, v) + } + if op2 == ssa.OpCopy { + return s.newValueOrSfCall1(op1, tt, v) + } + return s.newValueOrSfCall1(op2, tt, s.newValueOrSfCall1(op1, types.Types[it], v)) + } + // Tricky 64-bit unsigned cases. + if ft.IsInteger() { + // tt is float32 or float64, and ft is also unsigned + if tt.Size() == 4 { + return s.uint64Tofloat32(n, v, ft, tt) + } + if tt.Size() == 8 { + return s.uint64Tofloat64(n, v, ft, tt) + } + s.Fatalf("weird unsigned integer to float conversion %v -> %v", ft, tt) + } + // ft is float32 or float64, and tt is unsigned integer + if ft.Size() == 4 { + return s.float32ToUint64(n, v, ft, tt) + } + if ft.Size() == 8 { + return s.float64ToUint64(n, v, ft, tt) + } + s.Fatalf("weird float to unsigned integer conversion %v -> %v", ft, tt) + return nil + } + + if ft.IsComplex() && tt.IsComplex() { + var op ssa.Op + if ft.Size() == tt.Size() { + switch ft.Size() { + case 8: + op = ssa.OpRound32F + case 16: + op = ssa.OpRound64F + default: + s.Fatalf("weird complex conversion %v -> %v", ft, tt) + } + } else if ft.Size() == 8 && tt.Size() == 16 { + op = ssa.OpCvt32Fto64F + } else if ft.Size() == 16 && tt.Size() == 8 { + op = ssa.OpCvt64Fto32F + } else { + s.Fatalf("weird complex conversion %v -> %v", ft, tt) + } + ftp := types.FloatForComplex(ft) + ttp := types.FloatForComplex(tt) + return s.newValue2(ssa.OpComplexMake, tt, + s.newValueOrSfCall1(op, ttp, s.newValue1(ssa.OpComplexReal, ftp, v)), + s.newValueOrSfCall1(op, ttp, s.newValue1(ssa.OpComplexImag, ftp, v))) + } + + s.Fatalf("unhandled OCONV %s -> %s", ft.Kind(), tt.Kind()) + return nil +} + // expr converts the expression n to ssa, adds it to s and returns the ssa result. func (s *state) expr(n ir.Node) *ssa.Value { if ir.HasUniquePos(n) { @@ -2510,174 +2679,7 @@ func (s *state) expr(n ir.Node) *ssa.Value { case ir.OCONV: n := n.(*ir.ConvExpr) x := s.expr(n.X) - ft := n.X.Type() // from type - tt := n.Type() // to type - if ft.IsBoolean() && tt.IsKind(types.TUINT8) { - // Bool -> uint8 is generated internally when indexing into runtime.staticbyte. - return s.newValue1(ssa.OpCopy, n.Type(), x) - } - if ft.IsInteger() && tt.IsInteger() { - var op ssa.Op - if tt.Size() == ft.Size() { - op = ssa.OpCopy - } else if tt.Size() < ft.Size() { - // truncation - switch 10*ft.Size() + tt.Size() { - case 21: - op = ssa.OpTrunc16to8 - case 41: - op = ssa.OpTrunc32to8 - case 42: - op = ssa.OpTrunc32to16 - case 81: - op = ssa.OpTrunc64to8 - case 82: - op = ssa.OpTrunc64to16 - case 84: - op = ssa.OpTrunc64to32 - default: - s.Fatalf("weird integer truncation %v -> %v", ft, tt) - } - } else if ft.IsSigned() { - // sign extension - switch 10*ft.Size() + tt.Size() { - case 12: - op = ssa.OpSignExt8to16 - case 14: - op = ssa.OpSignExt8to32 - case 18: - op = ssa.OpSignExt8to64 - case 24: - op = ssa.OpSignExt16to32 - case 28: - op = ssa.OpSignExt16to64 - case 48: - op = ssa.OpSignExt32to64 - default: - s.Fatalf("bad integer sign extension %v -> %v", ft, tt) - } - } else { - // zero extension - switch 10*ft.Size() + tt.Size() { - case 12: - op = ssa.OpZeroExt8to16 - case 14: - op = ssa.OpZeroExt8to32 - case 18: - op = ssa.OpZeroExt8to64 - case 24: - op = ssa.OpZeroExt16to32 - case 28: - op = ssa.OpZeroExt16to64 - case 48: - op = ssa.OpZeroExt32to64 - default: - s.Fatalf("weird integer sign extension %v -> %v", ft, tt) - } - } - return s.newValue1(op, n.Type(), x) - } - - if ft.IsFloat() || tt.IsFloat() { - conv, ok := fpConvOpToSSA[twoTypes{s.concreteEtype(ft), s.concreteEtype(tt)}] - if s.config.RegSize == 4 && Arch.LinkArch.Family != sys.MIPS && !s.softFloat { - if conv1, ok1 := fpConvOpToSSA32[twoTypes{s.concreteEtype(ft), s.concreteEtype(tt)}]; ok1 { - conv = conv1 - } - } - if Arch.LinkArch.Family == sys.ARM64 || Arch.LinkArch.Family == sys.Wasm || Arch.LinkArch.Family == sys.S390X || s.softFloat { - if conv1, ok1 := uint64fpConvOpToSSA[twoTypes{s.concreteEtype(ft), s.concreteEtype(tt)}]; ok1 { - conv = conv1 - } - } - - if Arch.LinkArch.Family == sys.MIPS && !s.softFloat { - if ft.Size() == 4 && ft.IsInteger() && !ft.IsSigned() { - // tt is float32 or float64, and ft is also unsigned - if tt.Size() == 4 { - return s.uint32Tofloat32(n, x, ft, tt) - } - if tt.Size() == 8 { - return s.uint32Tofloat64(n, x, ft, tt) - } - } else if tt.Size() == 4 && tt.IsInteger() && !tt.IsSigned() { - // ft is float32 or float64, and tt is unsigned integer - if ft.Size() == 4 { - return s.float32ToUint32(n, x, ft, tt) - } - if ft.Size() == 8 { - return s.float64ToUint32(n, x, ft, tt) - } - } - } - - if !ok { - s.Fatalf("weird float conversion %v -> %v", ft, tt) - } - op1, op2, it := conv.op1, conv.op2, conv.intermediateType - - if op1 != ssa.OpInvalid && op2 != ssa.OpInvalid { - // normal case, not tripping over unsigned 64 - if op1 == ssa.OpCopy { - if op2 == ssa.OpCopy { - return x - } - return s.newValueOrSfCall1(op2, n.Type(), x) - } - if op2 == ssa.OpCopy { - return s.newValueOrSfCall1(op1, n.Type(), x) - } - return s.newValueOrSfCall1(op2, n.Type(), s.newValueOrSfCall1(op1, types.Types[it], x)) - } - // Tricky 64-bit unsigned cases. - if ft.IsInteger() { - // tt is float32 or float64, and ft is also unsigned - if tt.Size() == 4 { - return s.uint64Tofloat32(n, x, ft, tt) - } - if tt.Size() == 8 { - return s.uint64Tofloat64(n, x, ft, tt) - } - s.Fatalf("weird unsigned integer to float conversion %v -> %v", ft, tt) - } - // ft is float32 or float64, and tt is unsigned integer - if ft.Size() == 4 { - return s.float32ToUint64(n, x, ft, tt) - } - if ft.Size() == 8 { - return s.float64ToUint64(n, x, ft, tt) - } - s.Fatalf("weird float to unsigned integer conversion %v -> %v", ft, tt) - return nil - } - - if ft.IsComplex() && tt.IsComplex() { - var op ssa.Op - if ft.Size() == tt.Size() { - switch ft.Size() { - case 8: - op = ssa.OpRound32F - case 16: - op = ssa.OpRound64F - default: - s.Fatalf("weird complex conversion %v -> %v", ft, tt) - } - } else if ft.Size() == 8 && tt.Size() == 16 { - op = ssa.OpCvt32Fto64F - } else if ft.Size() == 16 && tt.Size() == 8 { - op = ssa.OpCvt64Fto32F - } else { - s.Fatalf("weird complex conversion %v -> %v", ft, tt) - } - ftp := types.FloatForComplex(ft) - ttp := types.FloatForComplex(tt) - return s.newValue2(ssa.OpComplexMake, tt, - s.newValueOrSfCall1(op, ttp, s.newValue1(ssa.OpComplexReal, ftp, x)), - s.newValueOrSfCall1(op, ttp, s.newValue1(ssa.OpComplexImag, ftp, x))) - } - - s.Fatalf("unhandled OCONV %s -> %s", n.X.Type().Kind(), n.Type().Kind()) - return nil + return s.conv(n, x, n.X.Type(), n.Type()) case ir.ODOTTYPE: n := n.(*ir.TypeAssertExpr) -- GitLab From d62866ef793872779c9011161e51b9c805fcb73d Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Fri, 27 Aug 2021 20:07:00 +0700 Subject: [PATCH 1074/2500] cmd/compile: move checkptr alignment to SSA generation This is followup of CL 343972, moving the checkptr alignment instrumentation during SSA generation instead of walk. Change-Id: I29b2953e4eb8631277fe2e0f44b9d987dd7a69f9 Reviewed-on: https://go-review.googlesource.com/c/go/+/345430 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/expr.go | 9 ++-- src/cmd/compile/internal/ir/symtab.go | 55 ++++++++++++------------ src/cmd/compile/internal/ssagen/ssa.go | 51 +++++++++++++++++++--- src/cmd/compile/internal/walk/convert.go | 38 ---------------- src/cmd/compile/internal/walk/expr.go | 13 +----- 5 files changed, 77 insertions(+), 89 deletions(-) diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index baf0117409..f526d987a7 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -570,11 +570,10 @@ func (*SelectorExpr) CanBeNtype() {} // A SliceExpr is a slice expression X[Low:High] or X[Low:High:Max]. type SliceExpr struct { miniExpr - X Node - Low Node - High Node - Max Node - CheckPtrCall *CallExpr `mknode:"-"` + X Node + Low Node + High Node + Max Node } func NewSliceExpr(pos src.XPos, op Op, x, low, high, max Node) *SliceExpr { diff --git a/src/cmd/compile/internal/ir/symtab.go b/src/cmd/compile/internal/ir/symtab.go index 1e8261810f..1435e4313e 100644 --- a/src/cmd/compile/internal/ir/symtab.go +++ b/src/cmd/compile/internal/ir/symtab.go @@ -11,33 +11,34 @@ import ( // Syms holds known symbols. var Syms struct { - AssertE2I *obj.LSym - AssertE2I2 *obj.LSym - AssertI2I *obj.LSym - AssertI2I2 *obj.LSym - Deferproc *obj.LSym - DeferprocStack *obj.LSym - Deferreturn *obj.LSym - Duffcopy *obj.LSym - Duffzero *obj.LSym - GCWriteBarrier *obj.LSym - Goschedguarded *obj.LSym - Growslice *obj.LSym - Msanread *obj.LSym - Msanwrite *obj.LSym - Msanmove *obj.LSym - Newobject *obj.LSym - Newproc *obj.LSym - Panicdivide *obj.LSym - Panicshift *obj.LSym - PanicdottypeE *obj.LSym - PanicdottypeI *obj.LSym - Panicnildottype *obj.LSym - Panicoverflow *obj.LSym - Raceread *obj.LSym - Racereadrange *obj.LSym - Racewrite *obj.LSym - Racewriterange *obj.LSym + AssertE2I *obj.LSym + AssertE2I2 *obj.LSym + AssertI2I *obj.LSym + AssertI2I2 *obj.LSym + CheckPtrAlignment *obj.LSym + Deferproc *obj.LSym + DeferprocStack *obj.LSym + Deferreturn *obj.LSym + Duffcopy *obj.LSym + Duffzero *obj.LSym + GCWriteBarrier *obj.LSym + Goschedguarded *obj.LSym + Growslice *obj.LSym + Msanread *obj.LSym + Msanwrite *obj.LSym + Msanmove *obj.LSym + Newobject *obj.LSym + Newproc *obj.LSym + Panicdivide *obj.LSym + Panicshift *obj.LSym + PanicdottypeE *obj.LSym + PanicdottypeI *obj.LSym + Panicnildottype *obj.LSym + Panicoverflow *obj.LSym + Raceread *obj.LSym + Racereadrange *obj.LSym + Racewrite *obj.LSym + Racewriterange *obj.LSym // Wasm SigPanic *obj.LSym Staticuint64s *obj.LSym diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index dd19a254f8..11bca89fd8 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -96,6 +96,7 @@ func InitConfig() { ir.Syms.AssertE2I2 = typecheck.LookupRuntimeFunc("assertE2I2") ir.Syms.AssertI2I = typecheck.LookupRuntimeFunc("assertI2I") ir.Syms.AssertI2I2 = typecheck.LookupRuntimeFunc("assertI2I2") + ir.Syms.CheckPtrAlignment = typecheck.LookupRuntimeFunc("checkptrAlignment") ir.Syms.Deferproc = typecheck.LookupRuntimeFunc("deferproc") ir.Syms.DeferprocStack = typecheck.LookupRuntimeFunc("deferprocStack") ir.Syms.Deferreturn = typecheck.LookupRuntimeFunc("deferreturn") @@ -366,6 +367,7 @@ func buildssa(fn *ir.Func, worker int) *ssa.Func { if fn.Pragma&ir.CgoUnsafeArgs != 0 { s.cgoUnsafeArgs = true } + s.checkPtrEnabled = ir.ShouldCheckPtr(fn, 1) fe := ssafn{ curfn: fn, @@ -709,6 +711,31 @@ func (s *state) newObject(typ *types.Type) *ssa.Value { return s.rtcall(ir.Syms.Newobject, true, []*types.Type{types.NewPtr(typ)}, s.reflectType(typ))[0] } +func (s *state) checkPtrAlignment(n *ir.ConvExpr, v *ssa.Value, count *ssa.Value) { + if !n.Type().IsPtr() { + s.Fatalf("expected pointer type: %v", n.Type()) + } + elem := n.Type().Elem() + if count != nil { + if !elem.IsArray() { + s.Fatalf("expected array type: %v", elem) + } + elem = elem.Elem() + } + size := elem.Size() + // Casting from larger type to smaller one is ok, so for smallest type, do nothing. + if elem.Alignment() == 1 && (size == 0 || size == 1 || count == nil) { + return + } + if count == nil { + count = s.constInt(types.Types[types.TUINTPTR], 1) + } + if count.Type.Size() != s.config.PtrSize { + s.Fatalf("expected count fit to an uintptr size, have: %d, want: %d", count.Type.Size(), s.config.PtrSize) + } + s.rtcall(ir.Syms.CheckPtrAlignment, true, nil, v, s.reflectType(elem), count) +} + // reflectType returns an SSA value representing a pointer to typ's // reflection type descriptor. func (s *state) reflectType(typ *types.Type) *ssa.Value { @@ -861,10 +888,11 @@ type state struct { // Used to deduplicate panic calls. panics map[funcLine]*ssa.Block - cgoUnsafeArgs bool - hasdefer bool // whether the function contains a defer statement - softFloat bool - hasOpenDefers bool // whether we are doing open-coded defers + cgoUnsafeArgs bool + hasdefer bool // whether the function contains a defer statement + softFloat bool + hasOpenDefers bool // whether we are doing open-coded defers + checkPtrEnabled bool // whether to insert checkptr instrumentation // If doing open-coded defers, list of info about the defer calls in // scanning order. Hence, at exit we should run these defers in reverse @@ -2494,6 +2522,10 @@ func (s *state) conv(n ir.Node, v *ssa.Value, ft, tt *types.Type) *ssa.Value { // expr converts the expression n to ssa, adds it to s and returns the ssa result. func (s *state) expr(n ir.Node) *ssa.Value { + return s.exprCheckPtr(n, true) +} + +func (s *state) exprCheckPtr(n ir.Node, checkPtrOK bool) *ssa.Value { if ir.HasUniquePos(n) { // ONAMEs and named OLITERALs have the line number // of the decl, not the use. See issue 14742. @@ -2641,6 +2673,9 @@ func (s *state) expr(n ir.Node) *ssa.Value { // unsafe.Pointer <--> *T if to.IsUnsafePtr() && from.IsPtrShaped() || from.IsUnsafePtr() && to.IsPtrShaped() { + if s.checkPtrEnabled && checkPtrOK && to.IsPtr() && from.IsUnsafePtr() { + s.checkPtrAlignment(n, v, nil) + } return v } @@ -3081,7 +3116,8 @@ func (s *state) expr(n ir.Node) *ssa.Value { case ir.OSLICE, ir.OSLICEARR, ir.OSLICE3, ir.OSLICE3ARR: n := n.(*ir.SliceExpr) - v := s.expr(n.X) + check := s.checkPtrEnabled && n.Op() == ir.OSLICE3ARR && n.X.Op() == ir.OCONVNOP && n.X.(*ir.ConvExpr).X.Type().IsUnsafePtr() + v := s.exprCheckPtr(n.X, !check) var i, j, k *ssa.Value if n.Low != nil { i = s.expr(n.Low) @@ -3093,8 +3129,9 @@ func (s *state) expr(n ir.Node) *ssa.Value { k = s.expr(n.Max) } p, l, c := s.slice(v, i, j, k, n.Bounded()) - if n.CheckPtrCall != nil { - s.stmt(n.CheckPtrCall) + if check { + // Emit checkptr instrumentation after bound check to prevent false positive, see #46938. + s.checkPtrAlignment(n.X.(*ir.ConvExpr), v, s.conv(n.Max, k, k.Type, types.Types[types.TUINTPTR])) } return s.newValue3(ssa.OpSliceMake, n.Type(), p, l, c) diff --git a/src/cmd/compile/internal/walk/convert.go b/src/cmd/compile/internal/walk/convert.go index d701d545de..5d69fc3868 100644 --- a/src/cmd/compile/internal/walk/convert.go +++ b/src/cmd/compile/internal/walk/convert.go @@ -25,9 +25,6 @@ func walkConv(n *ir.ConvExpr, init *ir.Nodes) ir.Node { return n.X } if n.Op() == ir.OCONVNOP && ir.ShouldCheckPtr(ir.CurFunc, 1) { - if n.Type().IsPtr() && n.X.Type().IsUnsafePtr() { // unsafe.Pointer to *T - return walkCheckPtrAlignment(n, init, nil) - } if n.Type().IsUnsafePtr() && n.X.Type().IsUintptr() { // uintptr to unsafe.Pointer return walkCheckPtrArithmetic(n, init) } @@ -414,41 +411,6 @@ func byteindex(n ir.Node) ir.Node { return n } -func walkCheckPtrAlignment(n *ir.ConvExpr, init *ir.Nodes, se *ir.SliceExpr) ir.Node { - if !n.Type().IsPtr() { - base.Fatalf("expected pointer type: %v", n.Type()) - } - elem := n.Type().Elem() - var count ir.Node - if se != nil { - count = se.Max - } - if count != nil { - if !elem.IsArray() { - base.Fatalf("expected array type: %v", elem) - } - elem = elem.Elem() - } - - size := elem.Size() - if elem.Alignment() == 1 && (size == 0 || size == 1 && count == nil) { - return n - } - - if count == nil { - count = ir.NewInt(1) - } - - n.X = cheapExpr(n.X, init) - checkPtrCall := mkcall("checkptrAlignment", nil, init, typecheck.ConvNop(n.X, types.Types[types.TUNSAFEPTR]), reflectdata.TypePtr(elem), typecheck.Conv(count, types.Types[types.TUINTPTR])) - if se != nil { - se.CheckPtrCall = checkPtrCall - } else { - init.Append(checkPtrCall) - } - return n -} - func walkCheckPtrArithmetic(n *ir.ConvExpr, init *ir.Nodes) ir.Node { // Calling cheapExpr(n, init) below leads to a recursive call to // walkExpr, which leads us back here again. Use n.Checkptr to diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go index ed2d68539d..e5bf6cf0b5 100644 --- a/src/cmd/compile/internal/walk/expr.go +++ b/src/cmd/compile/internal/walk/expr.go @@ -807,15 +807,7 @@ func walkSend(n *ir.SendStmt, init *ir.Nodes) ir.Node { // walkSlice walks an OSLICE, OSLICEARR, OSLICESTR, OSLICE3, or OSLICE3ARR node. func walkSlice(n *ir.SliceExpr, init *ir.Nodes) ir.Node { - - checkSlice := ir.ShouldCheckPtr(ir.CurFunc, 1) && n.Op() == ir.OSLICE3ARR && n.X.Op() == ir.OCONVNOP && n.X.(*ir.ConvExpr).X.Type().IsUnsafePtr() - if checkSlice { - conv := n.X.(*ir.ConvExpr) - conv.X = walkExpr(conv.X, init) - } else { - n.X = walkExpr(n.X, init) - } - + n.X = walkExpr(n.X, init) n.Low = walkExpr(n.Low, init) if n.Low != nil && ir.IsZero(n.Low) { // Reduce x[0:j] to x[:j] and x[0:j:k] to x[:j:k]. @@ -823,9 +815,6 @@ func walkSlice(n *ir.SliceExpr, init *ir.Nodes) ir.Node { } n.High = walkExpr(n.High, init) n.Max = walkExpr(n.Max, init) - if checkSlice { - n.X = walkCheckPtrAlignment(n.X.(*ir.ConvExpr), init, n) - } if n.Op().IsSlice3() { if n.Max != nil && n.Max.Op() == ir.OCAP && ir.SameSafeExpr(n.X, n.Max.(*ir.UnaryExpr).X) { -- GitLab From 2481f6e367a56207b6c873180e0db9bc4f2b6365 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 9 Sep 2021 01:11:26 +0700 Subject: [PATCH 1075/2500] cmd/compile: fix wrong instantiated type for embedded receiver In case of embedded field, if the receiver was fully instantiated, we must use its instantiated type, instead of passing the type params of the base receiver. Fixes #47797 Fixes #48253 Change-Id: I97613e7e669a72605137e82406f7bf5fbb629378 Reviewed-on: https://go-review.googlesource.com/c/go/+/348549 Trust: Cuong Manh Le Trust: Dan Scales Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/expr.go | 18 +++----------- test/typeparam/issue47797.go | 22 +++++++++++++++++ test/typeparam/issue48253.go | 34 ++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 15 deletions(-) create mode 100644 test/typeparam/issue47797.go create mode 100644 test/typeparam/issue48253.go diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 5eeafddae2..045f028e1a 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -360,12 +360,10 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto n.(*ir.SelectorExpr).Selection.Nname = method typed(method.Type(), n) - // selinfo.Targs() are the types used to - // instantiate the type of receiver - targs2 := getTargs(selinfo) - targs := make([]ir.Node, targs2.Len()) + xt := deref(x.Type()) + targs := make([]ir.Node, len(xt.RParams())) for i := range targs { - targs[i] = ir.TypeNode(g.typ(targs2.At(i))) + targs[i] = ir.TypeNode(xt.RParams()[i]) } // Create function instantiation with the type @@ -388,16 +386,6 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto return n } -// getTargs gets the targs associated with the receiver of a selected method -func getTargs(selinfo *types2.Selection) *types2.TypeList { - r := deref2(selinfo.Recv()) - n := types2.AsNamed(r) - if n == nil { - base.Fatalf("Incorrect type for selinfo %v", selinfo) - } - return n.TypeArgs() -} - func (g *irgen) exprList(expr syntax.Expr) []ir.Node { return g.exprs(unpackListExpr(expr)) } diff --git a/test/typeparam/issue47797.go b/test/typeparam/issue47797.go new file mode 100644 index 0000000000..3e80d3c7a9 --- /dev/null +++ b/test/typeparam/issue47797.go @@ -0,0 +1,22 @@ +// compile -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type Foo[T any] struct { + Val T +} + +func (f Foo[T]) Bat() {} + +type Bar struct { + Foo[int] +} + +func foo() { + var b Bar + b.Bat() +} diff --git a/test/typeparam/issue48253.go b/test/typeparam/issue48253.go new file mode 100644 index 0000000000..7bd0234e57 --- /dev/null +++ b/test/typeparam/issue48253.go @@ -0,0 +1,34 @@ +// run -gcflags="-G=3" + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "reflect" +) + +type A[T any] struct { + B[int] +} + +type B[T any] struct { +} + +func (b B[T]) Bat() { + t := new(T) + if tt := reflect.TypeOf(t); tt.Kind() != reflect.Pointer || tt.Elem().Kind() != reflect.Int { + panic("unexpected type, want: *int, got: "+tt.String()) + } +} + +type Foo struct { + A[string] +} +func main() { + Foo{}.A.Bat() + Foo{}.A.B.Bat() + Foo{}.Bat() +} -- GitLab From 6edc57983a39b3cb911ea88b75a7ad39664383ec Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 8 Sep 2021 16:21:33 -0700 Subject: [PATCH 1076/2500] internal/poll: report open fds when TestSplicePipePool fails For #48066 Change-Id: I1152a1c15756df35b71b27d3e7025d97da9e70b0 Reviewed-on: https://go-review.googlesource.com/c/go/+/348579 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Emmanuel Odeke --- src/internal/poll/splice_linux_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/internal/poll/splice_linux_test.go b/src/internal/poll/splice_linux_test.go index 280468c7e7..deac5c3759 100644 --- a/src/internal/poll/splice_linux_test.go +++ b/src/internal/poll/splice_linux_test.go @@ -67,6 +67,13 @@ func TestSplicePipePool(t *testing.T) { } select { case <-expiredTime.C: + t.Logf("descriptors to check: %v", fds) + for _, fd := range fds { + _, _, errno := syscall.Syscall(unix.FcntlSyscall, uintptr(fd), syscall.F_GETPIPE_SZ, 0) + if errno == 0 { + t.Errorf("descriptor %d still open", fd) + } + } t.Fatal("at least one pipe is still open") default: } -- GitLab From 376a079762bf8db387510d50ed718ec1259d1b7c Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Fri, 3 Sep 2021 10:49:32 +0700 Subject: [PATCH 1077/2500] cmd/compile: fix unified IR panic when expanding nested inline function When reading body of inlining function, which has another inlined function in the body, the reader still add this inlined function to todoBodies, which it shouldn't because the inlined function was read already. To fix this, introduce new flag to signal that we are done construting all functions in todoBodies, thus the addBody shouldn't add anything to todoBodies then. Updates #48094 Change-Id: I45105dd518f0a7b69c6dcbaf23b957623f271203 Reviewed-on: https://go-review.googlesource.com/c/go/+/347529 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/noder/reader.go | 7 ++++++- src/cmd/compile/internal/noder/unified.go | 1 + test/typeparam/issue48094b.dir/a.go | 8 ++++++++ test/typeparam/issue48094b.dir/b.go | 9 +++++++++ test/typeparam/issue48094b.go | 7 +++++++ 5 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 test/typeparam/issue48094b.dir/a.go create mode 100644 test/typeparam/issue48094b.dir/b.go create mode 100644 test/typeparam/issue48094b.go diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 57e8476099..48f4368113 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -927,6 +927,11 @@ var bodyReader = map[*ir.Func]pkgReaderIndex{} // constructed. var todoBodies []*ir.Func +// todoBodiesDone signals that we constructed all function in todoBodies. +// This is necessary to prevent reader.addBody adds thing to todoBodies +// when nested inlining happens. +var todoBodiesDone = false + func (r *reader) addBody(fn *ir.Func) { pri := pkgReaderIndex{r.p, r.reloc(relocBody), r.dict} bodyReader[fn] = pri @@ -937,7 +942,7 @@ func (r *reader) addBody(fn *ir.Func) { return } - if r.curfn == nil { + if r.curfn == nil && !todoBodiesDone { todoBodies = append(todoBodies, fn) return } diff --git a/src/cmd/compile/internal/noder/unified.go b/src/cmd/compile/internal/noder/unified.go index eff2eeaeff..3d4650a01f 100644 --- a/src/cmd/compile/internal/noder/unified.go +++ b/src/cmd/compile/internal/noder/unified.go @@ -136,6 +136,7 @@ func unified(noders []*noder) { } } todoBodies = nil + todoBodiesDone = true // Check that nothing snuck past typechecking. for _, n := range target.Decls { diff --git a/test/typeparam/issue48094b.dir/a.go b/test/typeparam/issue48094b.dir/a.go new file mode 100644 index 0000000000..a113a224f7 --- /dev/null +++ b/test/typeparam/issue48094b.dir/a.go @@ -0,0 +1,8 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +func F() { G(0) } +func G[T any](t T) {} diff --git a/test/typeparam/issue48094b.dir/b.go b/test/typeparam/issue48094b.dir/b.go new file mode 100644 index 0000000000..242b34aa31 --- /dev/null +++ b/test/typeparam/issue48094b.dir/b.go @@ -0,0 +1,9 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package b + +import "./a" + +func H() { a.F() } diff --git a/test/typeparam/issue48094b.go b/test/typeparam/issue48094b.go new file mode 100644 index 0000000000..b83fbd7af1 --- /dev/null +++ b/test/typeparam/issue48094b.go @@ -0,0 +1,7 @@ +// compiledir + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From c84f3a4004076b0e3dcef0a17573d85eb90ef5fc Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 8 Sep 2021 10:41:56 +0200 Subject: [PATCH 1078/2500] syscall: drop fallback to pipe in Pipe on linux/arm Follow-up for CL 346789 The minimum required Linux kernel version for Go 1.18 will be changed to 2.6.32, see #45964. The pipe2 syscall was added in 2.6.27, so the fallback to use pipe in Pipe on linux/arm can be removed. For #45964 Change-Id: I8b18244ca1f849f10e90565b4fef80ce777fef69 Reviewed-on: https://go-review.googlesource.com/c/go/+/347349 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/syscall/syscall_linux_arm.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/syscall/syscall_linux_arm.go b/src/syscall/syscall_linux_arm.go index e887cf788f..fffa4b29b9 100644 --- a/src/syscall/syscall_linux_arm.go +++ b/src/syscall/syscall_linux_arm.go @@ -29,11 +29,7 @@ func Pipe(p []int) (err error) { return EINVAL } var pp [2]_C_int - // Try pipe2 first for Android O, then try pipe for kernel 2.6.23. err = pipe2(&pp, 0) - if err == ENOSYS { - err = pipe(&pp) - } p[0] = int(pp[0]) p[1] = int(pp[1]) return -- GitLab From b86e8dd0f3a27bc9577690523c9feeb25593bec7 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Thu, 9 Sep 2021 10:10:54 +0200 Subject: [PATCH 1079/2500] test/typeparam: fix issue48094b test build CL 347529 broke the longtest builders due to missing -G=3 flag when compiling the added test. Change-Id: I73007801dd6871a8cf3554e957d247f5f56fd641 Reviewed-on: https://go-review.googlesource.com/c/go/+/348330 Trust: Tobias Klauser Trust: Cuong Manh Le Reviewed-by: Cuong Manh Le Run-TryBot: Tobias Klauser TryBot-Result: Go Bot --- test/typeparam/issue48094b.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/typeparam/issue48094b.go b/test/typeparam/issue48094b.go index b83fbd7af1..87b4ff46c1 100644 --- a/test/typeparam/issue48094b.go +++ b/test/typeparam/issue48094b.go @@ -1,4 +1,4 @@ -// compiledir +// compiledir -G=3 // Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style -- GitLab From 9e1eea6f8b0d0266c481df5bc3c808defeaa6f44 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 8 Sep 2021 18:16:36 -0400 Subject: [PATCH 1080/2500] go/types: detect constraint type inference cycles This is a port of CL 347300 to go/types. The test was adjusted to match the differing error positioning in go/types: errors are placed on the ast.CallExpr.Fun, rather than the Lparen. Change-Id: I3dee5d7d75bae18817cc1f04ab0d357d3a6a8198 Reviewed-on: https://go-review.googlesource.com/c/go/+/348689 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/infer.go | 124 ++++++++++++++++++ .../types/testdata/fixedbugs/issue48136.go2 | 36 +++++ 2 files changed, 160 insertions(+) create mode 100644 src/go/types/testdata/fixedbugs/issue48136.go2 diff --git a/src/go/types/infer.go b/src/go/types/infer.go index e6417545e9..7314a614d0 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -8,6 +8,7 @@ package types import ( + "fmt" "go/token" "strings" ) @@ -404,6 +405,34 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type, report bool) (t } } + // The data structure of each (provided or inferred) type represents a graph, where + // each node corresponds to a type and each (directed) vertice points to a component + // type. The substitution process described above repeatedly replaces type parameter + // nodes in these graphs with the graphs of the types the type parameters stand for, + // which creates a new (possibly bigger) graph for each type. + // The substitution process will not stop if the replacement graph for a type parameter + // also contains that type parameter. + // For instance, for [A interface{ *A }], without any type argument provided for A, + // unification produces the type list [*A]. Substituting A in *A with the value for + // A will lead to infinite expansion by producing [**A], [****A], [********A], etc., + // because the graph A -> *A has a cycle through A. + // Generally, cycles may occur across multiple type parameters and inferred types + // (for instance, consider [P interface{ *Q }, Q interface{ func(P) }]). + // We eliminate cycles by walking the graphs for all type parameters. If a cycle + // through a type parameter is detected, cycleFinder nils out the respectice type + // which kills the cycle; this also means that the respective type could not be + // inferred. + // + // TODO(gri) If useful, we could report the respective cycle as an error. We don't + // do this now because type inference will fail anyway, and furthermore, + // constraints with cycles of this kind cannot currently be satisfied by + // any user-suplied type. But should that change, reporting an error + // would be wrong. + w := cycleFinder{tparams, types, make(map[Type]bool)} + for _, t := range tparams { + w.typ(t) // t != nil + } + // dirty tracks the indices of all types that may still contain type parameters. // We know that nil type entries and entries corresponding to provided (non-nil) // type arguments are clean, so exclude them from the start. @@ -452,3 +481,98 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type, report bool) (t return } + +type cycleFinder struct { + tparams []*TypeParam + types []Type + seen map[Type]bool +} + +func (w *cycleFinder) typ(typ Type) { + if w.seen[typ] { + // We have seen typ before. If it is one of the type parameters + // in tparams, iterative substitution will lead to infinite expansion. + // Nil out the corresponding type which effectively kills the cycle. + if tpar, _ := typ.(*TypeParam); tpar != nil { + if i := tparamIndex(w.tparams, tpar); i >= 0 { + // cycle through tpar + w.types[i] = nil + } + } + // If we don't have one of our type parameters, the cycle is due + // to an ordinary recursive type and we can just stop walking it. + return + } + w.seen[typ] = true + defer delete(w.seen, typ) + + switch t := typ.(type) { + case *Basic, *top: + // nothing to do + + case *Array: + w.typ(t.elem) + + case *Slice: + w.typ(t.elem) + + case *Struct: + w.varList(t.fields) + + case *Pointer: + w.typ(t.base) + + // case *Tuple: + // This case should not occur because tuples only appear + // in signatures where they are handled explicitly. + + case *Signature: + // There are no "method types" so we should never see a recv. + assert(t.recv == nil) + if t.params != nil { + w.varList(t.params.vars) + } + if t.results != nil { + w.varList(t.results.vars) + } + + case *Union: + for _, t := range t.terms { + w.typ(t.typ) + } + + case *Interface: + for _, m := range t.methods { + w.typ(m.typ) + } + for _, t := range t.embeddeds { + w.typ(t) + } + + case *Map: + w.typ(t.key) + w.typ(t.elem) + + case *Chan: + w.typ(t.elem) + + case *Named: + for _, tpar := range t.TypeArgs().list() { + w.typ(tpar) + } + + case *TypeParam: + if i := tparamIndex(w.tparams, t); i >= 0 && w.types[i] != nil { + w.typ(w.types[i]) + } + + default: + panic(fmt.Sprintf("unexpected %T", typ)) + } +} + +func (w *cycleFinder) varList(list []*Var) { + for _, v := range list { + w.typ(v.typ) + } +} diff --git a/src/go/types/testdata/fixedbugs/issue48136.go2 b/src/go/types/testdata/fixedbugs/issue48136.go2 new file mode 100644 index 0000000000..b87f84ae64 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue48136.go2 @@ -0,0 +1,36 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func f1[P interface{ *P }]() {} +func f2[P interface{ func(P) }]() {} +func f3[P, Q interface{ func(Q) P }]() {} +func f4[P interface{ *Q }, Q interface{ func(P) }]() {} +func f5[P interface{ func(P) }]() {} +func f6[P interface { *Tree[P] }, Q any ]() {} + +func _() { + f1 /* ERROR cannot infer P */ () + f2 /* ERROR cannot infer P */ () + f3 /* ERROR cannot infer P */ () + f4 /* ERROR cannot infer P */ () + f5 /* ERROR cannot infer P */ () + f6 /* ERROR cannot infer P */ () +} + +type Tree[P any] struct { + left, right *Tree[P] + data P +} + +// test case from issue + +func foo[Src interface { func() Src }]() Src { + return foo[Src] +} + +func _() { + foo /* ERROR cannot infer Src */ () +} -- GitLab From d2a77f1c76dcc960d8548fa47ec29fcb1b2e5833 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 8 Sep 2021 18:27:31 -0400 Subject: [PATCH 1081/2500] go/types: handle recursive type parameter constraints This is a port of CL 348090 to go/types. Notably, unlike in types2, declareTypeParams was previously setting the default constraint to the empty interface, not nil, because this was missed in CL 335034 (no changes were made to declareTypeParams). This CL fixes this discrepancy. Change-Id: I0fa54a660ba14c6cbefa81a27ab7eb193df3be20 Reviewed-on: https://go-review.googlesource.com/c/go/+/348690 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/decl.go | 19 ++++++++--- src/go/types/signature.go | 2 +- .../types/testdata/fixedbugs/issue45550.go2 | 10 ++++++ .../types/testdata/fixedbugs/issue47796.go2 | 33 +++++++++++++++++++ 4 files changed, 58 insertions(+), 6 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue45550.go2 create mode 100644 src/go/types/testdata/fixedbugs/issue47796.go2 diff --git a/src/go/types/decl.go b/src/go/types/decl.go index f679c33a94..8ebe7c6f5b 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -615,7 +615,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { if tdecl.TypeParams != nil { check.openScope(tdecl, "type parameters") defer check.closeScope() - named.tparams = check.collectTypeParams(tdecl.TypeParams) + check.collectTypeParams(&named.tparams, tdecl.TypeParams) } // determine underlying type of named @@ -647,7 +647,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { } } -func (check *Checker) collectTypeParams(list *ast.FieldList) *TypeParamList { +func (check *Checker) collectTypeParams(dst **TypeParamList, list *ast.FieldList) { var tparams []*TypeParam // Declare type parameters up-front, with empty interface as type bound. // The scope of type parameters starts at the beginning of the type parameter @@ -656,6 +656,11 @@ func (check *Checker) collectTypeParams(list *ast.FieldList) *TypeParamList { tparams = check.declareTypeParams(tparams, f.Names) } + // Set the type parameters before collecting the type constraints because + // the parameterized type may be used by the constraints (issue #47887). + // Example: type T[P T[P]] interface{} + *dst = bindTParams(tparams) + index := 0 var bound Type for _, f := range list.List { @@ -670,14 +675,18 @@ func (check *Checker) collectTypeParams(list *ast.FieldList) *TypeParamList { next: index += len(f.Names) } - - return bindTParams(tparams) } func (check *Checker) declareTypeParams(tparams []*TypeParam, names []*ast.Ident) []*TypeParam { + // Use Typ[Invalid] for the type constraint to ensure that a type + // is present even if the actual constraint has not been assigned + // yet. + // TODO(gri) Need to systematically review all uses of type parameter + // constraints to make sure we don't rely on them if they + // are not properly set yet. for _, name := range names { tname := NewTypeName(name.Pos(), check.pkg, name.Name, nil) - tpar := check.newTypeParam(tname, &emptyInterface) // assigns type to tpar as a side-effect + tpar := check.newTypeParam(tname, Typ[Invalid]) // assigns type to tpar as a side-effect check.declare(check.scope, name, tname, check.scope.pos) // TODO(gri) check scope position tparams = append(tparams, tpar) } diff --git a/src/go/types/signature.go b/src/go/types/signature.go index 88ea07d5d3..ec2030a689 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -152,7 +152,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast } if ftyp.TypeParams != nil { - sig.tparams = check.collectTypeParams(ftyp.TypeParams) + check.collectTypeParams(&sig.tparams, ftyp.TypeParams) // Always type-check method type parameters but complain that they are not allowed. // (A separate check is needed when type-checking interface method signatures because // they don't have a receiver specification.) diff --git a/src/go/types/testdata/fixedbugs/issue45550.go2 b/src/go/types/testdata/fixedbugs/issue45550.go2 new file mode 100644 index 0000000000..c3e9e34b87 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue45550.go2 @@ -0,0 +1,10 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type Builder[T interface{ struct{ Builder[T] } }] struct{} +type myBuilder struct { + Builder[myBuilder /* ERROR myBuilder does not satisfy */] +} diff --git a/src/go/types/testdata/fixedbugs/issue47796.go2 b/src/go/types/testdata/fixedbugs/issue47796.go2 new file mode 100644 index 0000000000..9c10683e22 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue47796.go2 @@ -0,0 +1,33 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +// parameterized types with self-recursive constraints +type ( + T1[P T1[P]] interface{} + T2[P, Q T2[P, Q]] interface{} + T3[P T2[P, Q], Q interface{ ~string }] interface{} + + T4a[P T4a[P]] interface{ ~int } + T4b[P T4b[int]] interface{ ~int } + T4c[P T4c[string /* ERROR string does not satisfy T4c\[string\] */]] interface{ ~int } + + // mutually recursive constraints + T5[P T6[P]] interface{ int } + T6[P T5[P]] interface{ int } +) + +// verify that constraints are checked as expected +var ( + _ T1[int] + _ T2[int, string] + _ T3[int, string] +) + +// test case from issue + +type Eq[a Eq[a]] interface { + Equal(that a) bool +} -- GitLab From 66f0d35f7145ca8d4e45b04292f44831d6610b3b Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 8 Sep 2021 19:03:37 -0400 Subject: [PATCH 1082/2500] go/types: reduce number of delayed functions This is a port of CL 348018 to go/types. It differs from that CL due to the way that field lists are represented in go/ast. Change-Id: Ib5a0243b44d0bf9e95d039f624c668f8c329f8fa Reviewed-on: https://go-review.googlesource.com/c/go/+/348691 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/decl.go | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 8ebe7c6f5b..c1506f6dbd 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -663,11 +663,21 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list *ast.FieldList index := 0 var bound Type + var bounds []Type + var posns []positioner // bound positions for _, f := range list.List { if f.Type == nil { goto next } - bound = check.boundType(f.Type) + // The predeclared identifier "any" is visible only as a type bound in a type parameter list. + // If we allow "any" for general use, this if-statement can be removed (issue #33232). + if name, _ := unparen(f.Type).(*ast.Ident); name != nil && name.Name == "any" && check.lookup("any") == universeAny { + bound = universeAny.Type() + } else { + bound = check.typ(f.Type) + } + bounds = append(bounds, bound) + posns = append(posns, f.Type) for i := range f.Names { tparams[index+i].bound = bound } @@ -675,6 +685,15 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list *ast.FieldList next: index += len(f.Names) } + + check.later(func() { + for i, bound := range bounds { + u := under(bound) + if _, ok := u.(*Interface); !ok && u != Typ[Invalid] { + check.errorf(posns[i], _Todo, "%s is not an interface", bound) + } + } + }) } func (check *Checker) declareTypeParams(tparams []*TypeParam, names []*ast.Ident) []*TypeParam { @@ -698,25 +717,6 @@ func (check *Checker) declareTypeParams(tparams []*TypeParam, names []*ast.Ident return tparams } -// boundType type-checks the type expression e and returns its type, or Typ[Invalid]. -// The type must be an interface, including the predeclared type "any". -func (check *Checker) boundType(e ast.Expr) Type { - // The predeclared identifier "any" is visible only as a type bound in a type parameter list. - // If we allow "any" for general use, this if-statement can be removed (issue #33232). - if name, _ := unparen(e).(*ast.Ident); name != nil && name.Name == "any" && check.lookup("any") == universeAny { - return universeAny.Type() - } - - bound := check.typ(e) - check.later(func() { - u := under(bound) - if _, ok := u.(*Interface); !ok && u != Typ[Invalid] { - check.errorf(e, _Todo, "%s is not an interface", bound) - } - }) - return bound -} - func (check *Checker) collectMethods(obj *TypeName) { // get associated methods // (Checker.collectObjects only collects methods with non-blank names; -- GitLab From a295b3cec80b048048bf51a0462764dc337ca6ef Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 8 Sep 2021 14:03:53 -0700 Subject: [PATCH 1083/2500] test: re-enable AsmCheck tests for types2-based frontends run.go has logic for being able to run tests with various -G flags, but not all test types (in particular, "asmcheck" tests) support configuring non-default -G levels. The intention was that these tests would continue running in the default mode (at the time -G=0), but at some point it seems like we accidentally disabled them all together (if it ever worked correctly in the first place). Fixes #48247. Change-Id: I13917cb0012cbe522d29b23b888de6136872ead4 Reviewed-on: https://go-review.googlesource.com/c/go/+/348671 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Michael Munday --- test/run.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/run.go b/test/run.go index 76621d9242..790b54bfd2 100644 --- a/test/run.go +++ b/test/run.go @@ -780,11 +780,13 @@ func (t *test) run() { } default: - // we don't know how to add -G for this test yet - if *verbose { - fmt.Printf("excl\t%s\n", t.goFileName()) + if t.glevel != CompilerDefaultGLevel { + // we don't know how to add -G for this test yet + if *verbose { + fmt.Printf("excl\t%s\n", t.goFileName()) + } + return false } - return false } return true -- GitLab From 19457a58e565ff5b480c3806fe02fbc7ccdf32f0 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 9 Sep 2021 08:09:57 -0700 Subject: [PATCH 1084/2500] cmd/compile: stenciled conversions might be NOPs A generic conversion might be required for when converting T->interface{}. When stenciled with T=interface{}, then that conversion doesn't need to do anything. Fixes #48276 Change-Id: Ife65d01c99fbd0895cb7eec79df9e93e752b1fa5 Reviewed-on: https://go-review.googlesource.com/c/go/+/348736 Trust: Keith Randall Run-TryBot: Keith Randall Reviewed-by: Cuong Manh Le TryBot-Result: Go Bot --- src/cmd/compile/internal/noder/stencil.go | 6 ++++++ test/typeparam/issue48276a.go | 19 +++++++++++++++++++ test/typeparam/issue48276a.out | 1 + test/typeparam/issue48276b.go | 15 +++++++++++++++ 4 files changed, 41 insertions(+) create mode 100644 test/typeparam/issue48276a.go create mode 100644 test/typeparam/issue48276a.out create mode 100644 test/typeparam/issue48276b.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 1c22fc2ac0..a524ddc2a0 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1177,6 +1177,12 @@ func (subst *subster) node(n ir.Node) ir.Node { case ir.OCONVIFACE: x := x.(*ir.ConvExpr) + if m.Type().IsEmptyInterface() && m.(*ir.ConvExpr).X.Type().IsEmptyInterface() { + // Was T->interface{}, after stenciling it is now interface{}->interface{}. + // No longer need the conversion. See issue 48276. + m.(*ir.ConvExpr).SetOp(ir.OCONVNOP) + break + } // Note: x's argument is still typed as a type parameter. // m's argument now has an instantiated type. if x.X.Type().HasTParam() || (x.X.Type().IsInterface() && x.Type().HasTParam()) { diff --git a/test/typeparam/issue48276a.go b/test/typeparam/issue48276a.go new file mode 100644 index 0000000000..060ac3eb7f --- /dev/null +++ b/test/typeparam/issue48276a.go @@ -0,0 +1,19 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "fmt" + +func main() { + IsZero[interface{}]("") +} + +func IsZero[T comparable](val T) bool { + var zero T + fmt.Printf("%v:%v\n", zero, val) + return val != zero +} diff --git a/test/typeparam/issue48276a.out b/test/typeparam/issue48276a.out new file mode 100644 index 0000000000..7e8a8a9a2e --- /dev/null +++ b/test/typeparam/issue48276a.out @@ -0,0 +1 @@ +: diff --git a/test/typeparam/issue48276b.go b/test/typeparam/issue48276b.go new file mode 100644 index 0000000000..67c3e3d9f5 --- /dev/null +++ b/test/typeparam/issue48276b.go @@ -0,0 +1,15 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func main() { + f[interface{}](nil) +} + +func f[T any](x T) { + var _ interface{} = x +} -- GitLab From a53e3d5f885ca7a0df1cd6cf65faa5b63a802dce Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Fri, 6 Aug 2021 10:33:08 -0700 Subject: [PATCH 1085/2500] net: deprecate (net.Error).Temporary Fixes #45729. Change-Id: I819dd0cc79fc23baac46cafd78bb80f5133c992b Reviewed-on: https://go-review.googlesource.com/c/go/+/340261 Trust: Damien Neil Trust: Bryan C. Mills Run-TryBot: Damien Neil TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/net/net.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/net/net.go b/src/net/net.go index a7c65fff79..ab6aeaac2f 100644 --- a/src/net/net.go +++ b/src/net/net.go @@ -396,8 +396,12 @@ type Listener interface { // An Error represents a network error. type Error interface { error - Timeout() bool // Is the error a timeout? - Temporary() bool // Is the error temporary? + Timeout() bool // Is the error a timeout? + + // Deprecated: Temporary errors are not well-defined. + // Most "temporary" errors are timeouts, and the few exceptions are surprising. + // Do not use this method. + Temporary() bool } // Various errors contained in OpError. -- GitLab From ea434450c26431332c4cc376996e2b917fd09873 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Fri, 3 Sep 2021 21:35:59 +0000 Subject: [PATCH 1086/2500] reflect: add hooks for dealing with narrow width floats Currently on amd64 and arm64, float32 values just live in the bottom 32 bits of the register, so reflect simply places them there in a RegArgs for reflectcall to load them. This works fine because both of these platforms don't care what the upper 32 bits are, and have instructions to operate on float32 values specifically that we use. In sum, the representation of the float32 in memory is identical to that of the representation in a register. On other platforms, however, the representation of FP values differ depending on whether they're in memory or in a register. For instance, on ppc64, all floating point values get promoted to a float64 when loaded to a register (i.e. there's only one set of FP instructions). As another example, on riscv64, narrow-width floats in registers need to be NaN-boxed. What all this means is that for supporting the register ABI on these platforms, reflect needs to do a little extra work to ensure that the representation of FP values in a RegArgs matches the representation it takes on in a register. For this purpose, this change abstracts away the action of storing values into a RegArgs a little bit and adds a platform-specific hook which currently does nothing but copy the value. For #40724. Change-Id: I65dcc7d86d5602a584f86026ac204564617f4c5a Reviewed-on: https://go-review.googlesource.com/c/go/+/347566 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/internal/abi/abi.go | 28 ++++++--------------- src/reflect/abi.go | 42 +++++++++++++++++++++++++++++++ src/reflect/float32reg_generic.go | 21 ++++++++++++++++ src/reflect/value.go | 24 +++++++++--------- 4 files changed, 83 insertions(+), 32 deletions(-) create mode 100644 src/reflect/float32reg_generic.go diff --git a/src/internal/abi/abi.go b/src/internal/abi/abi.go index eadff248d9..46dc593bd7 100644 --- a/src/internal/abi/abi.go +++ b/src/internal/abi/abi.go @@ -19,6 +19,14 @@ import ( // when it may not be safe to keep them only in the integer // register space otherwise. type RegArgs struct { + // Values in these slots should be precisely the bit-by-bit + // representation of how they would appear in a register. + // + // This means that on big endian arches, integer values should + // be in the top bits of the slot. Floats are usually just + // directly represented, but some architectures treat narrow + // width floating point values specially (e.g. they're promoted + // first, or they need to be NaN-boxed). Ints [IntArgRegs]uintptr // untyped integer registers Floats [FloatArgRegs]uint64 // untyped float registers @@ -56,26 +64,6 @@ func (r *RegArgs) IntRegArgAddr(reg int, argSize uintptr) unsafe.Pointer { return unsafe.Pointer(uintptr(unsafe.Pointer(&r.Ints[reg])) + offset) } -// FloatRegArgAddr returns a pointer inside of r.Floats[reg] that is appropriately -// offset for an argument of size argSize. -// -// argSize must be non-zero, fit in a register, and a power-of-two. -// -// This method is a helper for dealing with the endianness of different CPU -// architectures, since sub-word-sized arguments in big endian architectures -// need to be "aligned" to the upper edge of the register to be interpreted -// by the CPU correctly. -func (r *RegArgs) FloatRegArgAddr(reg int, argSize uintptr) unsafe.Pointer { - if argSize > EffectiveFloatRegSize || argSize == 0 || argSize&(argSize-1) != 0 { - panic("invalid argSize") - } - offset := uintptr(0) - if goarch.BigEndian { - offset = EffectiveFloatRegSize - argSize - } - return unsafe.Pointer(uintptr(unsafe.Pointer(&r.Floats[reg])) + offset) -} - // IntArgRegBitmap is a bitmap large enough to hold one bit per // integer argument/return register. type IntArgRegBitmap [(IntArgRegs + 7) / 8]uint8 diff --git a/src/reflect/abi.go b/src/reflect/abi.go index 9ddde3ae57..2ce7ca2615 100644 --- a/src/reflect/abi.go +++ b/src/reflect/abi.go @@ -467,3 +467,45 @@ func newAbiDesc(t *funcType, rcvr *rtype) abiDesc { out.stackBytes -= retOffset return abiDesc{in, out, stackCallArgsSize, retOffset, spill, stackPtrs, inRegPtrs, outRegPtrs} } + +// intFromReg loads an argSize sized integer from reg and places it at to. +// +// argSize must be non-zero, fit in a register, and a power-of-two. +func intFromReg(r *abi.RegArgs, reg int, argSize uintptr, to unsafe.Pointer) { + memmove(to, r.IntRegArgAddr(reg, argSize), argSize) +} + +// intToReg loads an argSize sized integer and stores it into reg. +// +// argSize must be non-zero, fit in a register, and a power-of-two. +func intToReg(r *abi.RegArgs, reg int, argSize uintptr, from unsafe.Pointer) { + memmove(r.IntRegArgAddr(reg, argSize), from, argSize) +} + +// floatFromReg loads a float value from its register representation in r. +// +// argSize must be 4 or 8. +func floatFromReg(r *abi.RegArgs, reg int, argSize uintptr, to unsafe.Pointer) { + switch argSize { + case 4: + *(*float32)(to) = archFloat32FromReg(r.Floats[reg]) + case 8: + *(*float64)(to) = *(*float64)(unsafe.Pointer(&r.Floats[reg])) + default: + panic("bad argSize") + } +} + +// floatToReg stores a float value in its register representation in r. +// +// argSize must be either 4 or 8. +func floatToReg(r *abi.RegArgs, reg int, argSize uintptr, from unsafe.Pointer) { + switch argSize { + case 4: + r.Floats[reg] = archFloat32ToReg(*(*float32)(from)) + case 8: + r.Floats[reg] = *(*uint64)(from) + default: + panic("bad argSize") + } +} diff --git a/src/reflect/float32reg_generic.go b/src/reflect/float32reg_generic.go new file mode 100644 index 0000000000..381d458057 --- /dev/null +++ b/src/reflect/float32reg_generic.go @@ -0,0 +1,21 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package reflect + +import "unsafe" + +// This file implements a straightforward conversion of a float32 +// value into its representation in a register. This conversion +// applies for amd64 and arm64. It is also chosen for the case of +// zero argument registers, but is not used. + +func archFloat32FromReg(reg uint64) float32 { + i := uint32(reg) + return *(*float32)(unsafe.Pointer(&i)) +} + +func archFloat32ToReg(val float32) uint64 { + return uint64(*(*uint32)(unsafe.Pointer(&val))) +} diff --git a/src/reflect/value.go b/src/reflect/value.go index 3c2172135e..bf29d1bb3a 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -508,7 +508,7 @@ func (v Value) call(op string, in []Value) []Value { // Copy values to "integer registers." if v.flag&flagIndir != 0 { offset := add(v.ptr, st.offset, "precomputed value offset") - memmove(regArgs.IntRegArgAddr(st.ireg, st.size), offset, st.size) + intToReg(®Args, st.ireg, st.size, offset) } else { if st.kind == abiStepPointer { // Duplicate this pointer in the pointer area of the @@ -524,7 +524,7 @@ func (v Value) call(op string, in []Value) []Value { panic("attempted to copy pointer to FP register") } offset := add(v.ptr, st.offset, "precomputed value offset") - memmove(regArgs.FloatRegArgAddr(st.freg, st.size), offset, st.size) + floatToReg(®Args, st.freg, st.size, offset) default: panic("unknown ABI part kind") } @@ -610,13 +610,13 @@ func (v Value) call(op string, in []Value) []Value { switch st.kind { case abiStepIntReg: offset := add(s, st.offset, "precomputed value offset") - memmove(offset, regArgs.IntRegArgAddr(st.ireg, st.size), st.size) + intFromReg(®Args, st.ireg, st.size, offset) case abiStepPointer: s := add(s, st.offset, "precomputed value offset") *((*unsafe.Pointer)(s)) = regArgs.Ptrs[st.ireg] case abiStepFloatReg: offset := add(s, st.offset, "precomputed value offset") - memmove(offset, regArgs.FloatRegArgAddr(st.freg, st.size), st.size) + floatFromReg(®Args, st.freg, st.size, offset) case abiStepStack: panic("register-based return value has stack component") default: @@ -698,13 +698,13 @@ func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer, retValid *bool, regs switch st.kind { case abiStepIntReg: offset := add(v.ptr, st.offset, "precomputed value offset") - memmove(offset, regs.IntRegArgAddr(st.ireg, st.size), st.size) + intFromReg(regs, st.ireg, st.size, offset) case abiStepPointer: s := add(v.ptr, st.offset, "precomputed value offset") *((*unsafe.Pointer)(s)) = regs.Ptrs[st.ireg] case abiStepFloatReg: offset := add(v.ptr, st.offset, "precomputed value offset") - memmove(offset, regs.FloatRegArgAddr(st.freg, st.size), st.size) + floatFromReg(regs, st.freg, st.size, offset) case abiStepStack: panic("register-based return value has stack component") default: @@ -784,7 +784,7 @@ func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer, retValid *bool, regs // Copy values to "integer registers." if v.flag&flagIndir != 0 { offset := add(v.ptr, st.offset, "precomputed value offset") - memmove(regs.IntRegArgAddr(st.ireg, st.size), offset, st.size) + intToReg(regs, st.ireg, st.size, offset) } else { // Only populate the Ints space on the return path. // This is safe because out is kept alive until the @@ -799,7 +799,7 @@ func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer, retValid *bool, regs panic("attempted to copy pointer to FP register") } offset := add(v.ptr, st.offset, "precomputed value offset") - memmove(regs.FloatRegArgAddr(st.freg, st.size), offset, st.size) + floatToReg(regs, st.freg, st.size, offset) default: panic("unknown ABI part kind") } @@ -982,9 +982,9 @@ func callMethod(ctxt *methodValue, frame unsafe.Pointer, retValid *bool, regs *a methodRegs.Ptrs[mStep.ireg] = *(*unsafe.Pointer)(from) fallthrough // We need to make sure this ends up in Ints, too. case abiStepIntReg: - memmove(methodRegs.IntRegArgAddr(mStep.ireg, mStep.size), from, mStep.size) + intToReg(&methodRegs, mStep.ireg, mStep.size, from) case abiStepFloatReg: - memmove(methodRegs.FloatRegArgAddr(mStep.freg, mStep.size), from, mStep.size) + floatToReg(&methodRegs, mStep.freg, mStep.size, from) default: panic("unexpected method step") } @@ -1000,9 +1000,9 @@ func callMethod(ctxt *methodValue, frame unsafe.Pointer, retValid *bool, regs *a // Do the pointer copy directly so we get a write barrier. *(*unsafe.Pointer)(to) = valueRegs.Ptrs[vStep.ireg] case abiStepIntReg: - memmove(to, valueRegs.IntRegArgAddr(vStep.ireg, vStep.size), vStep.size) + intFromReg(valueRegs, vStep.ireg, vStep.size, to) case abiStepFloatReg: - memmove(to, valueRegs.FloatRegArgAddr(vStep.freg, vStep.size), vStep.size) + floatFromReg(valueRegs, vStep.freg, vStep.size, to) default: panic("unexpected value step") } -- GitLab From f9271e4f853eacded38fd6d626948e035cfd608c Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Thu, 9 Sep 2021 09:26:40 -0400 Subject: [PATCH 1087/2500] go/types, types2: rename RParams -> RecvTypeParams To be consistent with CL 348376, spell out 'RecvTypeParams' in go/types and types2 API. Updates #47916 Change-Id: If8b3fd4274ccb944bd0ff04d7007e94e5fba61c1 Reviewed-on: https://go-review.googlesource.com/c/go/+/348810 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/importer/iimport.go | 2 +- src/cmd/compile/internal/noder/reader2.go | 2 +- src/cmd/compile/internal/noder/types.go | 2 +- src/cmd/compile/internal/noder/writer.go | 6 +++--- src/cmd/compile/internal/types2/call.go | 6 +++--- src/cmd/compile/internal/types2/lookup.go | 8 ++++---- src/cmd/compile/internal/types2/signature.go | 18 +++++++++--------- src/go/internal/gcimporter/iimport.go | 2 +- src/go/types/call.go | 6 +++--- src/go/types/lookup.go | 6 +++--- src/go/types/signature.go | 18 +++++++++--------- 11 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index 8fdd879705..b61b1e97fb 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -349,7 +349,7 @@ func (r *importReader) obj(name string) { for i := range rparams { rparams[i] = types2.AsTypeParam(targs.At(i)) } - msig.SetRParams(rparams) + msig.SetRecvTypeParams(rparams) } named.AddMethod(types2.NewFunc(mpos, r.currPkg, mname, msig)) diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index 0cfde24b58..dcd9a65f40 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -492,7 +492,7 @@ func (r *reader2) method() *types2.Func { rparams := r.typeParamNames() sig := r.signature(r.param()) - sig.SetRParams(rparams) + sig.SetRecvTypeParams(rparams) _ = r.pos() // TODO(mdempsky): Remove; this is a hacker for linker.go. return types2.NewFunc(pos, pkg, name, sig) diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index b0b9c1592a..03fb96c48b 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -309,7 +309,7 @@ func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) { meth2 = newsym.Def.(*ir.Name) } else { meth2 = ir.NewNameAt(meth.Pos(), newsym) - rparams := types2.AsSignature(m.Type()).RParams() + rparams := types2.AsSignature(m.Type()).RecvTypeParams() tparams := make([]*types.Type, rparams.Len()) for i := range tparams { tparams[i] = g.typ1(rparams.At(i)) diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index e1413da1d8..6a66bea239 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -648,7 +648,7 @@ func (w *writer) method(wext *writer, meth *types2.Func) { w.sync(syncMethod) w.pos(meth) w.selector(meth) - w.typeParamNames(sig.RParams()) + w.typeParamNames(sig.RecvTypeParams()) w.param(sig.Recv()) w.signature(sig) @@ -1665,7 +1665,7 @@ func (w *writer) pkgDecl(decl syntax.Decl) { obj := w.p.info.Defs[decl.Name].(*types2.Func) sig := obj.Type().(*types2.Signature) - if sig.RParams() != nil || sig.TypeParams() != nil { + if sig.RecvTypeParams() != nil || sig.TypeParams() != nil { break // skip generic functions } @@ -1851,7 +1851,7 @@ func objTypeParams(obj types2.Object) *types2.TypeParamList { case *types2.Func: sig := obj.Type().(*types2.Signature) if sig.Recv() != nil { - return sig.RParams() + return sig.RecvTypeParams() } return sig.TypeParams() case *types2.TypeName: diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index f6aaa461b9..ba3bb475a3 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -535,7 +535,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) { // the signature accordingly. // TODO(gri) factor this code out sig := m.typ.(*Signature) - if sig.RParams().Len() > 0 { + if sig.RecvTypeParams().Len() > 0 { // For inference to work, we must use the receiver type // matching the receiver in the actual method declaration. // If the method is embedded, the matching receiver is the @@ -564,7 +564,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) { // the receiver type arguments here, the receiver must be be otherwise invalid // and an error has been reported elsewhere. arg := operand{mode: variable, expr: x.expr, typ: recv} - targs := check.infer(m.pos, sig.RParams().list(), nil, NewTuple(sig.recv), []*operand{&arg}, false /* no error reporting */) + targs := check.infer(m.pos, sig.RecvTypeParams().list(), nil, NewTuple(sig.recv), []*operand{&arg}, false /* no error reporting */) //check.dump("### inferred targs = %s", targs) if targs == nil { // We may reach here if there were other errors (see issue #40056). @@ -574,7 +574,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) { // (If we modify m, some tests will fail; possibly because the m is in use.) // TODO(gri) investigate and provide a correct explanation here copy := *m - copy.typ = check.subst(e.Pos(), m.typ, makeSubstMap(sig.RParams().list(), targs), nil) + copy.typ = check.subst(e.Pos(), m.typ, makeSubstMap(sig.RecvTypeParams().list(), targs), nil) obj = © } // TODO(gri) we also need to do substitution for parameterized interface methods diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index 67cdc1e68a..81bac7b6ff 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -394,10 +394,10 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // here. Exit early in this case to prevent an assertion // failure in makeSubstMap. // TODO(gri) Can we avoid this check by fixing the lengths? - if len(ftyp.RParams().list()) != Vn.targs.Len() { + if len(ftyp.RecvTypeParams().list()) != Vn.targs.Len() { return } - ftyp = check.subst(nopos, ftyp, makeSubstMap(ftyp.RParams().list(), Vn.targs.list()), nil).(*Signature) + ftyp = check.subst(nopos, ftyp, makeSubstMap(ftyp.RecvTypeParams().list(), Vn.targs.list()), nil).(*Signature) } // If the methods have type parameters we don't care whether they @@ -416,9 +416,9 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // unimplemented call so that we test this code if we // enable method type parameters. unimplemented() - u.x.init(append(ftyp.RParams().list(), ftyp.TypeParams().list()...)) + u.x.init(append(ftyp.RecvTypeParams().list(), ftyp.TypeParams().list()...)) } else { - u.x.init(ftyp.RParams().list()) + u.x.init(ftyp.RecvTypeParams().list()) } if !u.unify(ftyp, mtyp) { return m, f diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index eeaf1acbd6..009ac77012 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -59,11 +59,11 @@ func (s *Signature) TypeParams() *TypeParamList { return s.tparams } // SetTypeParams sets the type parameters of signature s. func (s *Signature) SetTypeParams(tparams []*TypeParam) { s.tparams = bindTParams(tparams) } -// RParams returns the receiver type parameters of signature s, or nil. -func (s *Signature) RParams() *TypeParamList { return s.rparams } +// RecvTypeParams returns the receiver type parameters of signature s, or nil. +func (s *Signature) RecvTypeParams() *TypeParamList { return s.rparams } -// SetRParams sets the receiver type params of signature s. -func (s *Signature) SetRParams(rparams []*TypeParam) { s.rparams = bindTParams(rparams) } +// SetRecvTypeParams sets the receiver type params of signature s. +func (s *Signature) SetRecvTypeParams(rparams []*TypeParam) { s.rparams = bindTParams(rparams) } // Params returns the parameters of signature s, or nil. func (s *Signature) Params() *Tuple { return s.params } @@ -138,14 +138,14 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] } // provide type parameter bounds // - only do this if we have the right number (otherwise an error is reported elsewhere) - if sig.RParams().Len() == len(recvTParams) { + if sig.RecvTypeParams().Len() == len(recvTParams) { // We have a list of *TypeNames but we need a list of Types. - list := make([]Type, sig.RParams().Len()) - for i, t := range sig.RParams().list() { + list := make([]Type, sig.RecvTypeParams().Len()) + for i, t := range sig.RecvTypeParams().list() { list[i] = t } smap := makeSubstMap(recvTParams, list) - for i, tpar := range sig.RParams().list() { + for i, tpar := range sig.RecvTypeParams().list() { bound := recvTParams[i].bound // bound is (possibly) parameterized in the context of the // receiver type declaration. Substitute parameters for the @@ -213,7 +213,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] T.expand(nil) // The receiver type may be an instantiated type referred to // by an alias (which cannot have receiver parameters for now). - if T.TypeArgs() != nil && sig.RParams() == nil { + if T.TypeArgs() != nil && sig.RecvTypeParams() == nil { check.errorf(recv.pos, "cannot define methods on instantiated type %s", recv.typ) break } diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go index 1fe139da17..039fc6a61b 100644 --- a/src/go/internal/gcimporter/iimport.go +++ b/src/go/internal/gcimporter/iimport.go @@ -339,7 +339,7 @@ func (r *importReader) obj(name string) { for i := range rparams { rparams[i], _ = targs.At(i).(*types.TypeParam) } - msig.SetRParams(rparams) + msig.SetRecvTypeParams(rparams) } named.AddMethod(types.NewFunc(mpos, r.currPkg, mname, msig)) diff --git a/src/go/types/call.go b/src/go/types/call.go index 3710756c29..4de5fed46e 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -537,7 +537,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { // the signature accordingly. // TODO(gri) factor this code out sig := m.typ.(*Signature) - if sig.RParams().Len() > 0 { + if sig.RecvTypeParams().Len() > 0 { // For inference to work, we must use the receiver type // matching the receiver in the actual method declaration. // If the method is embedded, the matching receiver is the @@ -565,7 +565,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { // the receiver type arguments here, the receiver must be be otherwise invalid // and an error has been reported elsewhere. arg := operand{mode: variable, expr: x.expr, typ: recv} - targs := check.infer(m, sig.RParams().list(), nil, NewTuple(sig.recv), []*operand{&arg}, false /* no error reporting */) + targs := check.infer(m, sig.RecvTypeParams().list(), nil, NewTuple(sig.recv), []*operand{&arg}, false /* no error reporting */) if targs == nil { // We may reach here if there were other errors (see issue #40056). goto Error @@ -574,7 +574,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { // (If we modify m, some tests will fail; possibly because the m is in use.) // TODO(gri) investigate and provide a correct explanation here copy := *m - copy.typ = check.subst(e.Pos(), m.typ, makeSubstMap(sig.RParams().list(), targs), nil) + copy.typ = check.subst(e.Pos(), m.typ, makeSubstMap(sig.RecvTypeParams().list(), targs), nil) obj = © } // TODO(gri) we also need to do substitution for parameterized interface methods diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index f5bdd31a6f..4664a0b33b 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -392,10 +392,10 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // here. Exit early in this case to prevent an assertion // failure in makeSubstMap. // TODO(gri) Can we avoid this check by fixing the lengths? - if len(ftyp.RParams().list()) != Vn.targs.Len() { + if len(ftyp.RecvTypeParams().list()) != Vn.targs.Len() { return } - ftyp = check.subst(token.NoPos, ftyp, makeSubstMap(ftyp.RParams().list(), Vn.targs.list()), nil).(*Signature) + ftyp = check.subst(token.NoPos, ftyp, makeSubstMap(ftyp.RecvTypeParams().list(), Vn.targs.list()), nil).(*Signature) } // If the methods have type parameters we don't care whether they @@ -404,7 +404,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // TODO(gri) is this always correct? what about type bounds? // (Alternative is to rename/subst type parameters and compare.) u := newUnifier(true) - u.x.init(ftyp.RParams().list()) + u.x.init(ftyp.RecvTypeParams().list()) if !u.unify(ftyp, mtyp) { return m, f } diff --git a/src/go/types/signature.go b/src/go/types/signature.go index ec2030a689..37811828ee 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -61,11 +61,11 @@ func (s *Signature) TypeParams() *TypeParamList { return s.tparams } // SetTypeParams sets the type parameters of signature s. func (s *Signature) SetTypeParams(tparams []*TypeParam) { s.tparams = bindTParams(tparams) } -// RParams returns the receiver type parameters of signature s, or nil. -func (s *Signature) RParams() *TypeParamList { return s.rparams } +// RecvTypeParams returns the receiver type parameters of signature s, or nil. +func (s *Signature) RecvTypeParams() *TypeParamList { return s.rparams } -// SetRParams sets the receiver type params of signature s. -func (s *Signature) SetRParams(rparams []*TypeParam) { s.rparams = bindTParams(rparams) } +// SetRecvTypeParams sets the receiver type params of signature s. +func (s *Signature) SetRecvTypeParams(rparams []*TypeParam) { s.rparams = bindTParams(rparams) } // Params returns the parameters of signature s, or nil. func (s *Signature) Params() *Tuple { return s.params } @@ -133,14 +133,14 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast } // provide type parameter bounds // - only do this if we have the right number (otherwise an error is reported elsewhere) - if sig.RParams().Len() == len(recvTParams) { + if sig.RecvTypeParams().Len() == len(recvTParams) { // We have a list of *TypeNames but we need a list of Types. - list := make([]Type, sig.RParams().Len()) - for i, t := range sig.RParams().list() { + list := make([]Type, sig.RecvTypeParams().Len()) + for i, t := range sig.RecvTypeParams().list() { list[i] = t } smap := makeSubstMap(recvTParams, list) - for i, tpar := range sig.RParams().list() { + for i, tpar := range sig.RecvTypeParams().list() { bound := recvTParams[i].bound // bound is (possibly) parameterized in the context of the // receiver type declaration. Substitute parameters for the @@ -203,7 +203,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast T.expand(nil) // The receiver type may be an instantiated type referred to // by an alias (which cannot have receiver parameters for now). - if T.TypeArgs() != nil && sig.RParams() == nil { + if T.TypeArgs() != nil && sig.RecvTypeParams() == nil { check.errorf(atPos(recv.pos), _Todo, "cannot define methods on instantiated type %s", recv.typ) break } -- GitLab From 7c648e2acb31363ea128b754503343cf2c82ba6f Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Thu, 9 Sep 2021 11:02:30 -0400 Subject: [PATCH 1088/2500] [dev.fuzz] internal/fuzz: avoid incorrect bytes modification during minimization During minimization, the "canonical inputs" (vals) are updated as viable minimized values are found. Previously, these bytes could be changed later during minimization. This patch updates the minimization code to revert the bytes back when a candidate doesn't pass the minimization checks. Another approach was in CL 340630 which would make a new allocation each time a candidate was attempted. This will get very expensive very quickly, as minimization can run several thousand times for every new crash and every newly discovered interesting input. Credit to Steven Johnstone (steven.james.johnstone@gmail.com) for the "single_bytes" test which was added to minimize_test.go. Fixes golang/go#47587 Change-Id: Ibd12f73458ed812bab7d3f1d4118854a54fc4d0a Reviewed-on: https://go-review.googlesource.com/c/go/+/348610 Trust: Katie Hockman Trust: Jay Conrod Run-TryBot: Katie Hockman Reviewed-by: Jay Conrod --- src/internal/fuzz/minimize.go | 13 +++++++---- src/internal/fuzz/minimize_test.go | 37 +++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/internal/fuzz/minimize.go b/src/internal/fuzz/minimize.go index b3cdd6a11b..974df369ee 100644 --- a/src/internal/fuzz/minimize.go +++ b/src/internal/fuzz/minimize.go @@ -19,6 +19,14 @@ func isMinimizable(t reflect.Type) bool { } func minimizeBytes(v []byte, try func(interface{}) bool, shouldStop func() bool) { + tmp := make([]byte, len(v)) + // If minimization was successful at any point during minimizeBytes, + // then the vals slice in (*workerServer).minimizeInput will point to + // tmp. Since tmp is altered while making new candidates, we need to + // make sure that it is equal to the correct value, v, before exiting + // this function. + defer copy(tmp, v) + // First, try to cut the tail. for n := 1024; n != 0; n /= 2 { for len(v) > n { @@ -35,7 +43,6 @@ func minimizeBytes(v []byte, try func(interface{}) bool, shouldStop func() bool) } // Then, try to remove each individual byte. - tmp := make([]byte, len(v)) for i := 0; i < len(v)-1; i++ { if shouldStop() { return @@ -72,8 +79,6 @@ func minimizeBytes(v []byte, try func(interface{}) bool, shouldStop func() bool) j = len(v) } } - - return } func minimizeInteger(v uint, try func(interface{}) bool, shouldStop func() bool) { @@ -90,7 +95,6 @@ func minimizeInteger(v uint, try func(interface{}) bool, shouldStop func() bool) // re-trigger the crash. try(v) } - return } func minimizeFloat(v float64, try func(interface{}) bool, shouldStop func() bool) { @@ -109,5 +113,4 @@ func minimizeFloat(v float64, try func(interface{}) bool, shouldStop func() bool return } } - return } diff --git a/src/internal/fuzz/minimize_test.go b/src/internal/fuzz/minimize_test.go index fa84d2da63..410b78310b 100644 --- a/src/internal/fuzz/minimize_test.go +++ b/src/internal/fuzz/minimize_test.go @@ -8,6 +8,7 @@ package fuzz import ( + "bytes" "context" "errors" "fmt" @@ -41,6 +42,36 @@ func TestMinimizeInput(t *testing.T) { input: []interface{}{[]byte{0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, expected: []interface{}{[]byte{1, 1, 1}}, }, + { + name: "single_bytes", + fn: func(e CorpusEntry) error { + b := e.Values[0].([]byte) + if len(b) < 2 { + return nil + } + if len(b) == 2 && b[0] == 1 && b[1] == 2 { + return nil + } + return fmt.Errorf("bad %v", e.Values[0]) + }, + input: []interface{}{[]byte{1, 2, 3, 4, 5}}, + expected: []interface{}{[]byte{2, 3}}, + }, + { + name: "set_of_bytes", + fn: func(e CorpusEntry) error { + b := e.Values[0].([]byte) + if len(b) < 3 { + return nil + } + if bytes.Equal(b, []byte{0, 1, 2, 3, 4, 5}) || bytes.Equal(b, []byte{0, 4, 5}) { + return fmt.Errorf("bad %v", e.Values[0]) + } + return nil + }, + input: []interface{}{[]byte{0, 1, 2, 3, 4, 5}}, + expected: []interface{}{[]byte{0, 4, 5}}, + }, { name: "ones_string", fn: func(e CorpusEntry) error { @@ -219,10 +250,10 @@ func TestMinimizeInput(t *testing.T) { t.Errorf("minimizeInput did not succeed") } if err == nil { - t.Error("minimizeInput didn't fail") + t.Fatal("minimizeInput didn't provide an error") } - if expected := fmt.Sprintf("bad %v", tc.input[0]); err.Error() != expected { - t.Errorf("unexpected error: got %s, want %s", err, expected) + if expected := fmt.Sprintf("bad %v", tc.expected[0]); err.Error() != expected { + t.Errorf("unexpected error: got %q, want %q", err, expected) } if !reflect.DeepEqual(vals, tc.expected) { t.Errorf("unexpected results: got %v, want %v", vals, tc.expected) -- GitLab From b9e1a24581b6282ee930a50bbe498d24ef77f486 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 8 Sep 2021 08:41:54 -0700 Subject: [PATCH 1089/2500] cmd/compile: fix case where init info of OAS node is dropped When an OAS node is converted to an OSELRECV2 node in tcSelect(), the possible DCL node in the Init field was being dropped, since a completely new node was being created and the Init field was not set. I don't expect n.Init() to be set for the ORECV case, but the code now deals with that too. Fixed bug in both tcSelect() and transformSelect(). Fixes #48289 Change-Id: I09918a70f7cbaa4aa9a17546169f908a8787df15 Reviewed-on: https://go-review.googlesource.com/c/go/+/348569 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le Reviewed-by: Matthew Dempsky Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/noder/transform.go | 1 + src/cmd/compile/internal/typecheck/stmt.go | 9 ++++--- test/fixedbugs/issue48289.go | 28 +++++++++++++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 test/fixedbugs/issue48289.go diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index b278f3db09..8173bfc747 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -554,6 +554,7 @@ func transformSelect(sel *ir.SelectStmt) { } selrecv.Def = def selrecv.SetTypecheck(1) + selrecv.SetInit(n.Init()) ncase.Comm = selrecv } switch n.Op() { diff --git a/src/cmd/compile/internal/typecheck/stmt.go b/src/cmd/compile/internal/typecheck/stmt.go index c322d490e5..9a02c1752c 100644 --- a/src/cmd/compile/internal/typecheck/stmt.go +++ b/src/cmd/compile/internal/typecheck/stmt.go @@ -395,10 +395,11 @@ func tcSelect(sel *ir.SelectStmt) { n := Stmt(ncase.Comm) ncase.Comm = n oselrecv2 := func(dst, recv ir.Node, def bool) { - n := ir.NewAssignListStmt(n.Pos(), ir.OSELRECV2, []ir.Node{dst, ir.BlankNode}, []ir.Node{recv}) - n.Def = def - n.SetTypecheck(1) - ncase.Comm = n + selrecv := ir.NewAssignListStmt(n.Pos(), ir.OSELRECV2, []ir.Node{dst, ir.BlankNode}, []ir.Node{recv}) + selrecv.Def = def + selrecv.SetTypecheck(1) + selrecv.SetInit(n.Init()) + ncase.Comm = selrecv } switch n.Op() { default: diff --git a/test/fixedbugs/issue48289.go b/test/fixedbugs/issue48289.go new file mode 100644 index 0000000000..94dbeee34c --- /dev/null +++ b/test/fixedbugs/issue48289.go @@ -0,0 +1,28 @@ +// run + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "fmt" + +func main() { + ch := make(chan int, 1) + + var ptrs [2]*int + for i := range ptrs { + ch <- i + select { + case x := <-ch: + ptrs[i] = &x + } + } + + for i, ptr := range ptrs { + if *ptr != i { + panic(fmt.Sprintf("got *ptr %d, want %d", *ptr, i)) + } + } +} -- GitLab From fb84e99eb76615f63fc2d6bc93c244a84d6e9c22 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 9 Sep 2021 11:17:39 -0700 Subject: [PATCH 1090/2500] test: add compiler regress tests for #46461 gri@ reports that types2 now correctly handles when type parameters recursively refer back to the parameterized type, so we might as well add tests to exercise that. Unified IR also correctly handles importing and exporting these types, but -G=3 currently does not. Updates #46461. Change-Id: I272102aa08c40c980b9aeeca9f834291dfbbcc3e Reviewed-on: https://go-review.googlesource.com/c/go/+/348738 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/internal/gcimporter/gcimporter_test.go | 2 ++ test/run.go | 2 ++ test/typeparam/issue46461.go | 13 +++++++++++++ test/typeparam/issue46461b.dir/a.go | 7 +++++++ test/typeparam/issue46461b.dir/b.go | 11 +++++++++++ test/typeparam/issue46461b.go | 7 +++++++ 6 files changed, 42 insertions(+) create mode 100644 test/typeparam/issue46461.go create mode 100644 test/typeparam/issue46461b.dir/a.go create mode 100644 test/typeparam/issue46461b.dir/b.go create mode 100644 test/typeparam/issue46461b.go diff --git a/src/go/internal/gcimporter/gcimporter_test.go b/src/go/internal/gcimporter/gcimporter_test.go index 9f4345d8f9..478534daf2 100644 --- a/src/go/internal/gcimporter/gcimporter_test.go +++ b/src/go/internal/gcimporter/gcimporter_test.go @@ -167,6 +167,8 @@ func TestImportTypeparamTests(t *testing.T) { skip := map[string]string{ "equal.go": "inconsistent embedded sorting", // TODO(rfindley): investigate this. "nested.go": "fails to compile", // TODO(rfindley): investigate this. + + "issue46461.go": "known issue with type parameter constraints referring back to parameterized type", } for _, entry := range list { diff --git a/test/run.go b/test/run.go index 790b54bfd2..d2b7b88768 100644 --- a/test/run.go +++ b/test/run.go @@ -2188,6 +2188,8 @@ var g3Failures = setOf( "typeparam/nested.go", // -G=3 doesn't support function-local types with generics + "typeparam/issue46461b.go", // -G=3 fails when type parameters refer back to the parameterized type itself + "typeparam/mdempsky/4.go", // -G=3 can't export functions with labeled breaks in loops ) diff --git a/test/typeparam/issue46461.go b/test/typeparam/issue46461.go new file mode 100644 index 0000000000..2c54a6ba28 --- /dev/null +++ b/test/typeparam/issue46461.go @@ -0,0 +1,13 @@ +// compile -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T[U interface{ M() T[U] }] int + +type X int + +func (X) M() T[X] { return 0 } diff --git a/test/typeparam/issue46461b.dir/a.go b/test/typeparam/issue46461b.dir/a.go new file mode 100644 index 0000000000..0d53b3e204 --- /dev/null +++ b/test/typeparam/issue46461b.dir/a.go @@ -0,0 +1,7 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type T[U interface{ M() T[U] }] int diff --git a/test/typeparam/issue46461b.dir/b.go b/test/typeparam/issue46461b.dir/b.go new file mode 100644 index 0000000000..3393a375c2 --- /dev/null +++ b/test/typeparam/issue46461b.dir/b.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package b + +import "./a" + +type X int + +func (X) M() a.T[X] { return 0 } diff --git a/test/typeparam/issue46461b.go b/test/typeparam/issue46461b.go new file mode 100644 index 0000000000..87b4ff46c1 --- /dev/null +++ b/test/typeparam/issue46461b.go @@ -0,0 +1,7 @@ +// compiledir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From 2c4f389c0298a37f1f3c000ad8b87e65d46c757f Mon Sep 17 00:00:00 2001 From: "Paul E. Murphy" Date: Tue, 23 Mar 2021 16:17:00 -0500 Subject: [PATCH 1091/2500] cmd/link: enable internal linker in more cases for ppc64le The internal linker is capable of linking the ppc64le linux race detector and approved cgo packages. Likewise, ppc64/linux and ppc64/aix do not support the race detector. Thus, extra code to enforce external linking when using the race detector on ppc64/ppc64le can be removed entirely. Fixes #21961 Change-Id: I10db14f65ee616ee3291e17409e8333e3af7d4df Reviewed-on: https://go-review.googlesource.com/c/go/+/304459 Run-TryBot: Paul Murphy TryBot-Result: Go Bot Trust: Lynn Boger Reviewed-by: Cherry Mui --- src/cmd/dist/test.go | 5 ----- src/cmd/link/internal/ld/config.go | 12 ++++-------- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index a104b5c8f3..dd4e96ec21 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -984,11 +984,6 @@ func (t *tester) internalLink() bool { // linkmode=internal fails on dragonfly since errno is a TLS relocation. return false } - if gohostarch == "ppc64le" { - // linkmode=internal fails on ppc64le because cmd/link doesn't - // handle the TOC correctly (issue 15409). - return false - } if goos == "android" { return false } diff --git a/src/cmd/link/internal/ld/config.go b/src/cmd/link/internal/ld/config.go index 20f1d0b8c1..4045c97dd7 100644 --- a/src/cmd/link/internal/ld/config.go +++ b/src/cmd/link/internal/ld/config.go @@ -195,8 +195,7 @@ func mustLinkExternal(ctxt *Link) (res bool, reason string) { // Internally linking cgo is incomplete on some architectures. // https://golang.org/issue/14449 - // https://golang.org/issue/21961 - if iscgo && ctxt.Arch.InFamily(sys.MIPS64, sys.MIPS, sys.PPC64, sys.RISCV64) { + if iscgo && ctxt.Arch.InFamily(sys.MIPS64, sys.MIPS, sys.RISCV64) { return true, buildcfg.GOARCH + " does not support internal cgo" } if iscgo && (buildcfg.GOOS == "android" || buildcfg.GOOS == "dragonfly") { @@ -209,12 +208,9 @@ func mustLinkExternal(ctxt *Link) (res bool, reason string) { // windows/arm64 internal linking is not implemented. return true, buildcfg.GOOS + "/" + buildcfg.GOARCH + " does not support internal cgo" } - - // When the race flag is set, the LLVM tsan relocatable file is linked - // into the final binary, which means external linking is required because - // internal linking does not support it. - if *flagRace && ctxt.Arch.InFamily(sys.PPC64) { - return true, "race on " + buildcfg.GOARCH + if iscgo && ctxt.Arch == sys.ArchPPC64 { + // Big Endian PPC64 cgo internal linking is not implemented for aix or linux. + return true, buildcfg.GOOS + " does not support internal cgo" } // Some build modes require work the internal linker cannot do (yet). -- GitLab From c981874a5a87605b446b3a56abba9907d17e8493 Mon Sep 17 00:00:00 2001 From: korzhao Date: Thu, 9 Sep 2021 21:51:43 +0800 Subject: [PATCH 1092/2500] cmd/compile: fix implement for closure in a global assignment If closure in a global assignment and has a method receiver. We should assign receiver as a global variable, not a local variable. Fixes #48225 Change-Id: I8f65dd6e8baf66a5eff24028d28ad0a594091add Reviewed-on: https://go-review.googlesource.com/c/go/+/348512 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Dan Scales Reviewed-by: Keith Randall Trust: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 12 ++++++-- test/typeparam/issue48225.go | 37 +++++++++++++++++++++++ 2 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 test/typeparam/issue48225.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index a524ddc2a0..5069db9fe1 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -396,13 +396,19 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { if rcvrValue != nil { rcvrVar = ir.NewNameAt(pos, typecheck.LookupNum(".rcvr", g.dnum)) g.dnum++ - rcvrVar.Class = ir.PAUTO typed(rcvrValue.Type(), rcvrVar) - rcvrVar.Curfn = outer rcvrAssign = ir.NewAssignStmt(pos, rcvrVar, rcvrValue) rcvrAssign.SetTypecheck(1) rcvrVar.Defn = rcvrAssign - outer.Dcl = append(outer.Dcl, rcvrVar) + if outer == nil { + rcvrVar.Class = ir.PEXTERN + g.target.Decls = append(g.target.Decls, rcvrAssign) + g.target.Externs = append(g.target.Externs, rcvrVar) + } else { + rcvrVar.Class = ir.PAUTO + rcvrVar.Curfn = outer + outer.Dcl = append(outer.Dcl, rcvrVar) + } } // Build body of closure. This involves just calling the wrapped function directly diff --git a/test/typeparam/issue48225.go b/test/typeparam/issue48225.go new file mode 100644 index 0000000000..887ffd8a84 --- /dev/null +++ b/test/typeparam/issue48225.go @@ -0,0 +1,37 @@ +// run -gcflags="-G=3" + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "reflect" + +type Foo[T any] struct { + val int +} + +func (foo Foo[T]) Get() *T { + if foo.val != 1 { + panic("bad val field in Foo receiver") + } + return new(T) +} + +var ( + newInt = Foo[int]{val: 1}.Get + newString = Foo[string]{val: 1}.Get +) + +func main() { + i := newInt() + s := newString() + + if t := reflect.TypeOf(i).String(); t != "*int" { + panic(t) + } + if t := reflect.TypeOf(s).String(); t != "*string" { + panic(t) + } +} -- GitLab From e1c3f2158fe3129fb44cc92423cfa41e7b6d472c Mon Sep 17 00:00:00 2001 From: korzhao Date: Sun, 29 Aug 2021 05:21:17 +0800 Subject: [PATCH 1093/2500] time: propagate "," separator for fractional seconds into Format In CL 300996 that fixed issue #6189, we made Parse recognize "," as a separator for fractional seconds. However, we didn't modify Format to propagate the separator verbatim from Parse. Without this change, we break prior functionality that relied on a comma being used in Format. Fixes #48037 Change-Id: I6565a25e8657ca3747a58b25acba58f27cdcddc0 Reviewed-on: https://go-review.googlesource.com/c/go/+/345438 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Reviewed-by: Emmanuel Odeke Trust: Cherry Mui --- src/time/format.go | 50 ++++++++++++++++++++++++++++++++--------- src/time/format_test.go | 20 +++++++++++++++++ 2 files changed, 59 insertions(+), 11 deletions(-) diff --git a/src/time/format.go b/src/time/format.go index 7ae89c557d..c2bffb8ff6 100644 --- a/src/time/format.go +++ b/src/time/format.go @@ -146,10 +146,11 @@ const ( stdFracSecond0 // ".0", ".00", ... , trailing zeros included stdFracSecond9 // ".9", ".99", ..., trailing zeros omitted - stdNeedDate = 1 << 8 // need month, day, year - stdNeedClock = 2 << 8 // need hour, minute, second - stdArgShift = 16 // extra argument in high bits, above low stdArgShift - stdMask = 1<> stdArgShift) & 0xfff +} + +func separator(std int) byte { + if (std >> stdSeparatorShift) == 0 { + return '.' + } + return ',' +} + // formatNano appends a fractional second, as nanoseconds, to b // and returns the result. -func formatNano(b []byte, nanosec uint, n int, trim bool) []byte { +func formatNano(b []byte, nanosec uint, std int) []byte { + var ( + n = digitsLen(std) + separator = separator(std) + trim = std&stdMask == stdFracSecond9 + ) u := nanosec var buf [9]byte for start := len(buf); start > 0; { @@ -452,7 +480,7 @@ func formatNano(b []byte, nanosec uint, n int, trim bool) []byte { return b } } - b = append(b, '.') + b = append(b, separator) return append(b, buf[:n]...) } @@ -733,7 +761,7 @@ func (t Time) AppendFormat(b []byte, layout string) []byte { b = appendInt(b, zone/60, 2) b = appendInt(b, zone%60, 2) case stdFracSecond0, stdFracSecond9: - b = formatNano(b, uint(t.Nanosecond()), std>>stdArgShift, std&stdMask == stdFracSecond9) + b = formatNano(b, uint(t.Nanosecond()), std) } } return b @@ -1165,7 +1193,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error) case stdFracSecond0: // stdFracSecond0 requires the exact number of digits as specified in // the layout. - ndigit := 1 + (std >> stdArgShift) + ndigit := 1 + digitsLen(std) if len(value) < ndigit { err = errBad break diff --git a/src/time/format_test.go b/src/time/format_test.go index 1af41e2dfb..93cbcf9401 100644 --- a/src/time/format_test.go +++ b/src/time/format_test.go @@ -832,3 +832,23 @@ func TestQuote(t *testing.T) { } } + +// Issue 48037 +func TestFormatFractionalSecondSeparators(t *testing.T) { + tests := []struct { + s, want string + }{ + {`15:04:05.000`, `21:00:57.012`}, + {`15:04:05.999`, `21:00:57.012`}, + {`15:04:05,000`, `21:00:57,012`}, + {`15:04:05,999`, `21:00:57,012`}, + } + + // The numeric time represents Thu Feb 4 21:00:57.012345600 PST 2009 + time := Unix(0, 1233810057012345600) + for _, tt := range tests { + if q := time.Format(tt.s); q != tt.want { + t.Errorf("Format(%q) = got %q, want %q", tt.s, q, tt.want) + } + } +} -- GitLab From 73483df406af39e6c244fd2fb90b41c4cfecd51e Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 8 Sep 2021 21:30:01 -0700 Subject: [PATCH 1094/2500] cmd/compile/internal/syntax: better error message for missing type constraint For #43527. Change-Id: I8c706e68572286d5675383eb2dfd75b5618b646b Reviewed-on: https://go-review.googlesource.com/c/go/+/348730 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/syntax/parser.go | 22 +++++++++++++----- .../internal/syntax/testdata/issue43527.go2 | 23 +++++++++++++++++++ .../internal/syntax/testdata/tparams.go2 | 8 +++---- .../types2/testdata/fixedbugs/issue47996.go2 | 2 +- 4 files changed, 44 insertions(+), 11 deletions(-) create mode 100644 src/cmd/compile/internal/syntax/testdata/issue43527.go2 diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index e89796cb31..c836a21c2f 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -1908,8 +1908,9 @@ func (p *parser) paramList(name *Name, close token, requireNames bool) (list []* defer p.trace("paramList")() } - var named int // number of parameters that have an explicit name and type/bound - p.list(_Comma, close, func() bool { + var named int // number of parameters that have an explicit name and type + var typed int // number of parameters that have an explicit type + end := p.list(_Comma, close, func() bool { par := p.paramDeclOrNil(name) name = nil // 1st name was consumed if present if par != nil { @@ -1919,6 +1920,9 @@ func (p *parser) paramList(name *Name, close token, requireNames bool) (list []* if par.Name != nil && par.Type != nil { named++ } + if par.Type != nil { + typed++ + } list = append(list, par) } return false @@ -1939,10 +1943,11 @@ func (p *parser) paramList(name *Name, close token, requireNames bool) (list []* } } else if named != len(list) { // some named => all must have names and types - var pos Pos // left-most error position (or unknown) - var typ Expr + var pos Pos // left-most error position (or unknown) + var typ Expr // current type (from right to left) for i := len(list) - 1; i >= 0; i-- { - if par := list[i]; par.Type != nil { + par := list[i] + if par.Type != nil { typ = par.Type if par.Name == nil { pos = typ.Pos() @@ -1961,7 +1966,12 @@ func (p *parser) paramList(name *Name, close token, requireNames bool) (list []* if pos.IsKnown() { var msg string if requireNames { - msg = "type parameters must be named" + if named == typed { + pos = end // position error at closing ] + msg = "missing type constraint" + } else { + msg = "type parameters must be named" + } } else { msg = "mixed named and unnamed parameters" } diff --git a/src/cmd/compile/internal/syntax/testdata/issue43527.go2 b/src/cmd/compile/internal/syntax/testdata/issue43527.go2 new file mode 100644 index 0000000000..dd2c9b1272 --- /dev/null +++ b/src/cmd/compile/internal/syntax/testdata/issue43527.go2 @@ -0,0 +1,23 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type ( + // 0 and 1-element []-lists are syntactically valid + _[A, B /* ERROR missing type constraint */ ] int + _[A, /* ERROR type parameters must be named */ interface{}] int + _[A, B, C /* ERROR missing type constraint */ ] int + _[A B, C /* ERROR missing type constraint */ ] int + _[A B, /* ERROR type parameters must be named */ interface{}] int + _[A B, /* ERROR type parameters must be named */ interface{}, C D] int + _[A B, /* ERROR type parameters must be named */ interface{}, C, D] int + _[A B, /* ERROR type parameters must be named */ interface{}, C, interface{}] int + _[A B, C interface{}, D, /* ERROR type parameters must be named */ interface{}] int +) + +// function type parameters use the same parsing routine - just have a couple of tests + +func _[A, B /* ERROR missing type constraint */ ]() {} +func _[A, /* ERROR type parameters must be named */ interface{}]() {} diff --git a/src/cmd/compile/internal/syntax/testdata/tparams.go2 b/src/cmd/compile/internal/syntax/testdata/tparams.go2 index 42031c3277..8e47ff5ed8 100644 --- a/src/cmd/compile/internal/syntax/testdata/tparams.go2 +++ b/src/cmd/compile/internal/syntax/testdata/tparams.go2 @@ -4,8 +4,8 @@ package p -type t[ /* ERROR type parameters must be named */ a, b] struct{} -type t[a t, b t, /* ERROR type parameters must be named */ c] struct{} +type t[a, b /* ERROR missing type constraint */ ] struct{} +type t[a t, b t, c /* ERROR missing type constraint */ ] struct{} type t struct { t [n]byte t[a] @@ -18,5 +18,5 @@ type t interface { } func f[ /* ERROR empty type parameter list */ ]() -func f[ /* ERROR type parameters must be named */ a, b]() -func f[a t, b t, /* ERROR type parameters must be named */ c]() +func f[a, b /* ERROR missing type constraint */ ]() +func f[a t, b t, c /* ERROR missing type constraint */ ]() diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47996.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47996.go2 index 56e90942ab..2c4b6610fe 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47996.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47996.go2 @@ -5,4 +5,4 @@ package p // don't crash -func T /* ERROR missing */ [P /* ERROR named */ ] m /* ERROR m */ () /* ERROR \) */ { /* ERROR { */ } /* ERROR } */ +func T /* ERROR missing */ [P] /* ERROR missing */ m /* ERROR unexpected */ () /* ERROR \) */ { /* ERROR { */ } /* ERROR } */ -- GitLab From 426ff3746fb2ebb777e32572b6eda5e19263ace9 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 9 Sep 2021 14:04:43 -0700 Subject: [PATCH 1095/2500] cmd/cgo, runtime/cgo: avoid GCC/clang conversion warnings Add explicit conversions to avoid warnings from -Wsign-conversion and -Wshorten-64-to-32. Also avoid runtime errors from -fsanitize=undefined. Fixes #48121 Change-Id: I29dc8d976884fc42826392c10f1e1759bb1a3989 Reviewed-on: https://go-review.googlesource.com/c/go/+/348739 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/cgo/out.go | 4 ++-- src/runtime/cgo/gcc_sigaction.c | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index 3badd73f79..ee989b95e5 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -1458,10 +1458,10 @@ const gccProlog = ` (have a negative array count) and an inscrutable error will come out of the compiler and hopefully mention "name". */ -#define __cgo_compile_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1]; +#define __cgo_compile_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2UL+1UL]; /* Check at compile time that the sizes we use match our expectations. */ -#define __cgo_size_assert(t, n) __cgo_compile_assert_eq(sizeof(t), n, _cgo_sizeof_##t##_is_not_##n) +#define __cgo_size_assert(t, n) __cgo_compile_assert_eq(sizeof(t), (size_t)n, _cgo_sizeof_##t##_is_not_##n) __cgo_size_assert(char, 1) __cgo_size_assert(short, 2) diff --git a/src/runtime/cgo/gcc_sigaction.c b/src/runtime/cgo/gcc_sigaction.c index dd283151f1..fcf1e50740 100644 --- a/src/runtime/cgo/gcc_sigaction.c +++ b/src/runtime/cgo/gcc_sigaction.c @@ -49,13 +49,13 @@ x_cgo_sigaction(intptr_t signum, const go_sigaction_t *goact, go_sigaction_t *ol sigemptyset(&act.sa_mask); for (i = 0; i < 8 * sizeof(goact->mask); i++) { if (goact->mask & ((uint64_t)(1)<flags & ~SA_RESTORER; + act.sa_flags = (int)(goact->flags & ~(uint64_t)SA_RESTORER); } - ret = sigaction(signum, goact ? &act : NULL, oldgoact ? &oldact : NULL); + ret = sigaction((int)signum, goact ? &act : NULL, oldgoact ? &oldact : NULL); if (ret == -1) { // runtime.rt_sigaction expects _cgo_sigaction to return errno on error. _cgo_tsan_release(); @@ -70,11 +70,11 @@ x_cgo_sigaction(intptr_t signum, const go_sigaction_t *goact, go_sigaction_t *ol } oldgoact->mask = 0; for (i = 0; i < 8 * sizeof(oldgoact->mask); i++) { - if (sigismember(&oldact.sa_mask, i+1) == 1) { + if (sigismember(&oldact.sa_mask, (int)(i+1)) == 1) { oldgoact->mask |= (uint64_t)(1)<flags = oldact.sa_flags; + oldgoact->flags = (uint64_t)oldact.sa_flags; } _cgo_tsan_release(); -- GitLab From 1a708bcf1d17171056a42ec1597ca8848c854d2a Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 9 Sep 2021 14:42:42 -0700 Subject: [PATCH 1096/2500] cmd/compile: don't crash while reporting invalid alias cycle Add a missing nil check in the formatting code for expression nodes. Matches the nil checks in the same code. Fixes #48301. Change-Id: Ia9bfd3535254a94996ee190b544d95e15433d252 Reviewed-on: https://go-review.googlesource.com/c/go/+/348740 Trust: Robert Griesemer Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/fmt.go | 2 +- test/fixedbugs/issue48301.go | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 test/fixedbugs/issue48301.go diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index d19fe453ef..22fbf39975 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -559,7 +559,7 @@ func exprFmt(n Node, s fmt.State, prec int) { } nprec := OpPrec[n.Op()] - if n.Op() == OTYPE && n.Type().IsPtr() { + if n.Op() == OTYPE && n.Type() != nil && n.Type().IsPtr() { nprec = OpPrec[ODEREF] } diff --git a/test/fixedbugs/issue48301.go b/test/fixedbugs/issue48301.go new file mode 100644 index 0000000000..46fe779a42 --- /dev/null +++ b/test/fixedbugs/issue48301.go @@ -0,0 +1,13 @@ +// errorcheck -G=0 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Don't crash while reporting the error. + +package p + +func _() { + type T = T // ERROR "T uses T" +} -- GitLab From b32209d22d0418594bd60af152b0f2c90c677941 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 9 Sep 2021 15:55:05 -0700 Subject: [PATCH 1097/2500] cmd/compile: fix test case for unified IR (fix build) For #48301. Change-Id: Ie5f57dcce86773c06c5140abf13a6cfff79eb323 Reviewed-on: https://go-review.googlesource.com/c/go/+/348743 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Matthew Dempsky TryBot-Result: Go Bot --- test/fixedbugs/issue48301.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fixedbugs/issue48301.go b/test/fixedbugs/issue48301.go index 46fe779a42..1ff9ffb9a0 100644 --- a/test/fixedbugs/issue48301.go +++ b/test/fixedbugs/issue48301.go @@ -9,5 +9,5 @@ package p func _() { - type T = T // ERROR "T uses T" + type T = T // ERROR "T uses T|invalid recursive type T" } -- GitLab From 2091bd3f26e5143bd050833b3558893e1bc34625 Mon Sep 17 00:00:00 2001 From: fanzha02 Date: Wed, 21 Oct 2020 18:51:42 +0800 Subject: [PATCH 1098/2500] cmd/compile: simiplify arm64 bitfield optimizations In some rewrite rules for arm64 bitfield optimizations, the bitfield lsb value and the bitfield width value are related to datasize, some of them use datasize directly to check the bitfield lsb value is valid, to get the bitfiled width value, but some of them call isARM64BFMask() and arm64BFWidth() functions. In order to be consistent, this patch changes them all to use datasize. Besides, this patch sorts the codegen test cases. Run the "toolstash-check -all" command and find one inconsistent code is as the following. new: src/math/fma.go:104 BEQ 247 master: src/math/fma.go:104 BEQ 248 The above inconsistence is due to this patch changing the range of the field lsb value in "UBFIZ" optimization rules from "lc+(32|16|8)<64" to "lc<64", so that the following code is generated as "UBFIZ". The logical of changed code is still correct. The code of src/math/fma.go:160: const uvinf = 0x7FF0000000000000 func FMA(a, b uint32) float64 { ps := a+b return Float64frombits(uint64(ps)<<63 | uvinf) } The new assembly code: TEXT "".FMA(SB), LEAF|NOFRAME|ABIInternal, $0-16 MOVWU "".a(FP), R0 MOVWU "".b+4(FP), R1 ADD R1, R0, R0 UBFIZ $63, R0, $1, R0 ORR $9218868437227405312, R0, R0 MOVD R0, "".~r2+8(FP) RET (R30) The master assembly code: TEXT "".FMA(SB), LEAF|NOFRAME|ABIInternal, $0-16 MOVWU "".a(FP), R0 MOVWU "".b+4(FP), R1 ADD R1, R0, R0 MOVWU R0, R0 LSL $63, R0, R0 ORR $9218868437227405312, R0, R0 MOVD R0, "".~r2+8(FP) RET (R30) Change-Id: I9061104adfdfd3384d0525327ae1e5c8b0df5c35 Reviewed-on: https://go-review.googlesource.com/c/go/+/265038 Trust: fannie zhang Run-TryBot: fannie zhang TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/compile/internal/ssa/gen/ARM64.rules | 47 ++--- src/cmd/compile/internal/ssa/rewrite.go | 2 +- src/cmd/compile/internal/ssa/rewriteARM64.go | 196 +++++++++---------- test/codegen/bitfield.go | 144 +++++++++----- 4 files changed, 218 insertions(+), 171 deletions(-) diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index ca9d4a4f01..d99487c31b 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -1824,6 +1824,7 @@ // sbfiz // (x << lc) >> rc (SRAconst [rc] (SLLconst [lc] x)) && lc > rc => (SBFIZ [armBFAuxInt(lc-rc, 64-lc)] x) +// int64(x << lc) (MOVWreg (SLLconst [lc] x)) && lc < 32 => (SBFIZ [armBFAuxInt(lc, 32-lc)] x) (MOVHreg (SLLconst [lc] x)) && lc < 16 => (SBFIZ [armBFAuxInt(lc, 16-lc)] x) (MOVBreg (SLLconst [lc] x)) && lc < 8 => (SBFIZ [armBFAuxInt(lc, 8-lc)] x) @@ -1835,6 +1836,7 @@ // sbfx // (x << lc) >> rc (SRAconst [rc] (SLLconst [lc] x)) && lc <= rc => (SBFX [armBFAuxInt(rc-lc, 64-rc)] x) +// int64(x) >> rc (SRAconst [rc] (MOVWreg x)) && rc < 32 => (SBFX [armBFAuxInt(rc, 32-rc)] x) (SRAconst [rc] (MOVHreg x)) && rc < 16 => (SBFX [armBFAuxInt(rc, 16-rc)] x) (SRAconst [rc] (MOVBreg x)) && rc < 8 => (SBFX [armBFAuxInt(rc, 8-rc)] x) @@ -1851,42 +1853,43 @@ => (SBFX [armBFAuxInt(sc-bfc.getARM64BFlsb(), bfc.getARM64BFlsb()+bfc.getARM64BFwidth()-sc)] x) // ubfiz +// (x << lc) >> rc +(SRLconst [rc] (SLLconst [lc] x)) && lc > rc => (UBFIZ [armBFAuxInt(lc-rc, 64-lc)] x) +// uint64(x) << lc +(SLLconst [lc] (MOVWUreg x)) => (UBFIZ [armBFAuxInt(lc, min(32, 64-lc))] x) +(SLLconst [lc] (MOVHUreg x)) => (UBFIZ [armBFAuxInt(lc, min(16, 64-lc))] x) +(SLLconst [lc] (MOVBUreg x)) => (UBFIZ [armBFAuxInt(lc, min(8, 64-lc))] x) +// uint64(x << lc) +(MOVWUreg (SLLconst [lc] x)) && lc < 32 => (UBFIZ [armBFAuxInt(lc, 32-lc)] x) +(MOVHUreg (SLLconst [lc] x)) && lc < 16 => (UBFIZ [armBFAuxInt(lc, 16-lc)] x) +(MOVBUreg (SLLconst [lc] x)) && lc < 8 => (UBFIZ [armBFAuxInt(lc, 8-lc)] x) + +// merge ANDconst into ubfiz // (x & ac) << sc (SLLconst [sc] (ANDconst [ac] x)) && isARM64BFMask(sc, ac, 0) => (UBFIZ [armBFAuxInt(sc, arm64BFWidth(ac, 0))] x) -(SLLconst [sc] (MOVWUreg x)) && isARM64BFMask(sc, 1<<32-1, 0) => (UBFIZ [armBFAuxInt(sc, 32)] x) -(SLLconst [sc] (MOVHUreg x)) && isARM64BFMask(sc, 1<<16-1, 0) => (UBFIZ [armBFAuxInt(sc, 16)] x) -(SLLconst [sc] (MOVBUreg x)) && isARM64BFMask(sc, 1<<8-1, 0) => (UBFIZ [armBFAuxInt(sc, 8)] x) // (x << sc) & ac (ANDconst [ac] (SLLconst [sc] x)) && isARM64BFMask(sc, ac, sc) => (UBFIZ [armBFAuxInt(sc, arm64BFWidth(ac, sc))] x) -(MOVWUreg (SLLconst [sc] x)) && isARM64BFMask(sc, 1<<32-1, sc) - => (UBFIZ [armBFAuxInt(sc, arm64BFWidth(1<<32-1, sc))] x) -(MOVHUreg (SLLconst [sc] x)) && isARM64BFMask(sc, 1<<16-1, sc) - => (UBFIZ [armBFAuxInt(sc, arm64BFWidth(1<<16-1, sc))] x) -(MOVBUreg (SLLconst [sc] x)) && isARM64BFMask(sc, 1<<8-1, sc) - => (UBFIZ [armBFAuxInt(sc, arm64BFWidth(1<<8-1, sc))] x) -// (x << lc) >> rc -(SRLconst [rc] (SLLconst [lc] x)) && lc > rc => (UBFIZ [armBFAuxInt(lc-rc, 64-lc)] x) // ubfx +// (x << lc) >> rc +(SRLconst [rc] (SLLconst [lc] x)) && lc < rc => (UBFX [armBFAuxInt(rc-lc, 64-rc)] x) +// uint64(x) >> rc +(SRLconst [rc] (MOVWUreg x)) && rc < 32 => (UBFX [armBFAuxInt(rc, 32-rc)] x) +(SRLconst [rc] (MOVHUreg x)) && rc < 16 => (UBFX [armBFAuxInt(rc, 16-rc)] x) +(SRLconst [rc] (MOVBUreg x)) && rc < 8 => (UBFX [armBFAuxInt(rc, 8-rc)] x) +// uint64(x >> rc) +(MOVWUreg (SRLconst [rc] x)) && rc < 32 => (UBFX [armBFAuxInt(rc, 32)] x) +(MOVHUreg (SRLconst [rc] x)) && rc < 16 => (UBFX [armBFAuxInt(rc, 16)] x) +(MOVBUreg (SRLconst [rc] x)) && rc < 8 => (UBFX [armBFAuxInt(rc, 8)] x) +// merge ANDconst into ubfx // (x >> sc) & ac (ANDconst [ac] (SRLconst [sc] x)) && isARM64BFMask(sc, ac, 0) => (UBFX [armBFAuxInt(sc, arm64BFWidth(ac, 0))] x) -(MOVWUreg (SRLconst [sc] x)) && isARM64BFMask(sc, 1<<32-1, 0) => (UBFX [armBFAuxInt(sc, 32)] x) -(MOVHUreg (SRLconst [sc] x)) && isARM64BFMask(sc, 1<<16-1, 0) => (UBFX [armBFAuxInt(sc, 16)] x) -(MOVBUreg (SRLconst [sc] x)) && isARM64BFMask(sc, 1<<8-1, 0) => (UBFX [armBFAuxInt(sc, 8)] x) // (x & ac) >> sc (SRLconst [sc] (ANDconst [ac] x)) && isARM64BFMask(sc, ac, sc) => (UBFX [armBFAuxInt(sc, arm64BFWidth(ac, sc))] x) -(SRLconst [sc] (MOVWUreg x)) && isARM64BFMask(sc, 1<<32-1, sc) - => (UBFX [armBFAuxInt(sc, arm64BFWidth(1<<32-1, sc))] x) -(SRLconst [sc] (MOVHUreg x)) && isARM64BFMask(sc, 1<<16-1, sc) - => (UBFX [armBFAuxInt(sc, arm64BFWidth(1<<16-1, sc))] x) -(SRLconst [sc] (MOVBUreg x)) && isARM64BFMask(sc, 1<<8-1, sc) - => (UBFX [armBFAuxInt(sc, arm64BFWidth(1<<8-1, sc))] x) -// (x << lc) >> rc -(SRLconst [rc] (SLLconst [lc] x)) && lc < rc => (UBFX [armBFAuxInt(rc-lc, 64-rc)] x) // merge ubfx and zerso-extension into ubfx (MOVWUreg (UBFX [bfc] x)) && bfc.getARM64BFwidth() <= 32 => (UBFX [bfc] x) diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index a997050ee2..162d42773a 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -1572,7 +1572,7 @@ func armBFAuxInt(lsb, width int64) arm64BitField { if lsb < 0 || lsb > 63 { panic("ARM(64) bit field lsb constant out of range") } - if width < 1 || width > 64 { + if width < 1 || lsb+width > 64 { panic("ARM(64) bit field width constant out of range") } return arm64BitField(width | lsb<<8) diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index c62ff73c59..83dd771436 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -7157,37 +7157,37 @@ func rewriteValueARM64_OpARM64MOVBUreg(v *Value) bool { v.AuxInt = int64ToAuxInt(0) return true } - // match: (MOVBUreg (SLLconst [sc] x)) - // cond: isARM64BFMask(sc, 1<<8-1, sc) - // result: (UBFIZ [armBFAuxInt(sc, arm64BFWidth(1<<8-1, sc))] x) + // match: (MOVBUreg (SLLconst [lc] x)) + // cond: lc < 8 + // result: (UBFIZ [armBFAuxInt(lc, 8-lc)] x) for { if v_0.Op != OpARM64SLLconst { break } - sc := auxIntToInt64(v_0.AuxInt) + lc := auxIntToInt64(v_0.AuxInt) x := v_0.Args[0] - if !(isARM64BFMask(sc, 1<<8-1, sc)) { + if !(lc < 8) { break } v.reset(OpARM64UBFIZ) - v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, arm64BFWidth(1<<8-1, sc))) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(lc, 8-lc)) v.AddArg(x) return true } - // match: (MOVBUreg (SRLconst [sc] x)) - // cond: isARM64BFMask(sc, 1<<8-1, 0) - // result: (UBFX [armBFAuxInt(sc, 8)] x) + // match: (MOVBUreg (SRLconst [rc] x)) + // cond: rc < 8 + // result: (UBFX [armBFAuxInt(rc, 8)] x) for { if v_0.Op != OpARM64SRLconst { break } - sc := auxIntToInt64(v_0.AuxInt) + rc := auxIntToInt64(v_0.AuxInt) x := v_0.Args[0] - if !(isARM64BFMask(sc, 1<<8-1, 0)) { + if !(rc < 8) { break } v.reset(OpARM64UBFX) - v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, 8)) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(rc, 8)) v.AddArg(x) return true } @@ -10703,37 +10703,37 @@ func rewriteValueARM64_OpARM64MOVHUreg(v *Value) bool { v.AuxInt = int64ToAuxInt(0) return true } - // match: (MOVHUreg (SLLconst [sc] x)) - // cond: isARM64BFMask(sc, 1<<16-1, sc) - // result: (UBFIZ [armBFAuxInt(sc, arm64BFWidth(1<<16-1, sc))] x) + // match: (MOVHUreg (SLLconst [lc] x)) + // cond: lc < 16 + // result: (UBFIZ [armBFAuxInt(lc, 16-lc)] x) for { if v_0.Op != OpARM64SLLconst { break } - sc := auxIntToInt64(v_0.AuxInt) + lc := auxIntToInt64(v_0.AuxInt) x := v_0.Args[0] - if !(isARM64BFMask(sc, 1<<16-1, sc)) { + if !(lc < 16) { break } v.reset(OpARM64UBFIZ) - v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, arm64BFWidth(1<<16-1, sc))) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(lc, 16-lc)) v.AddArg(x) return true } - // match: (MOVHUreg (SRLconst [sc] x)) - // cond: isARM64BFMask(sc, 1<<16-1, 0) - // result: (UBFX [armBFAuxInt(sc, 16)] x) + // match: (MOVHUreg (SRLconst [rc] x)) + // cond: rc < 16 + // result: (UBFX [armBFAuxInt(rc, 16)] x) for { if v_0.Op != OpARM64SRLconst { break } - sc := auxIntToInt64(v_0.AuxInt) + rc := auxIntToInt64(v_0.AuxInt) x := v_0.Args[0] - if !(isARM64BFMask(sc, 1<<16-1, 0)) { + if !(rc < 16) { break } v.reset(OpARM64UBFX) - v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, 16)) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(rc, 16)) v.AddArg(x) return true } @@ -12849,37 +12849,37 @@ func rewriteValueARM64_OpARM64MOVWUreg(v *Value) bool { v.AuxInt = int64ToAuxInt(0) return true } - // match: (MOVWUreg (SLLconst [sc] x)) - // cond: isARM64BFMask(sc, 1<<32-1, sc) - // result: (UBFIZ [armBFAuxInt(sc, arm64BFWidth(1<<32-1, sc))] x) + // match: (MOVWUreg (SLLconst [lc] x)) + // cond: lc < 32 + // result: (UBFIZ [armBFAuxInt(lc, 32-lc)] x) for { if v_0.Op != OpARM64SLLconst { break } - sc := auxIntToInt64(v_0.AuxInt) + lc := auxIntToInt64(v_0.AuxInt) x := v_0.Args[0] - if !(isARM64BFMask(sc, 1<<32-1, sc)) { + if !(lc < 32) { break } v.reset(OpARM64UBFIZ) - v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, arm64BFWidth(1<<32-1, sc))) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(lc, 32-lc)) v.AddArg(x) return true } - // match: (MOVWUreg (SRLconst [sc] x)) - // cond: isARM64BFMask(sc, 1<<32-1, 0) - // result: (UBFX [armBFAuxInt(sc, 32)] x) + // match: (MOVWUreg (SRLconst [rc] x)) + // cond: rc < 32 + // result: (UBFX [armBFAuxInt(rc, 32)] x) for { if v_0.Op != OpARM64SRLconst { break } - sc := auxIntToInt64(v_0.AuxInt) + rc := auxIntToInt64(v_0.AuxInt) x := v_0.Args[0] - if !(isARM64BFMask(sc, 1<<32-1, 0)) { + if !(rc < 32) { break } v.reset(OpARM64UBFX) - v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, 32)) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(rc, 32)) v.AddArg(x) return true } @@ -20130,72 +20130,60 @@ func rewriteValueARM64_OpARM64SLLconst(v *Value) bool { v.AddArg(x) return true } - // match: (SLLconst [sc] (ANDconst [ac] x)) - // cond: isARM64BFMask(sc, ac, 0) - // result: (UBFIZ [armBFAuxInt(sc, arm64BFWidth(ac, 0))] x) + // match: (SLLconst [lc] (MOVWUreg x)) + // result: (UBFIZ [armBFAuxInt(lc, min(32, 64-lc))] x) for { - sc := auxIntToInt64(v.AuxInt) - if v_0.Op != OpARM64ANDconst { + lc := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64MOVWUreg { break } - ac := auxIntToInt64(v_0.AuxInt) x := v_0.Args[0] - if !(isARM64BFMask(sc, ac, 0)) { - break - } v.reset(OpARM64UBFIZ) - v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, arm64BFWidth(ac, 0))) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(lc, min(32, 64-lc))) v.AddArg(x) return true } - // match: (SLLconst [sc] (MOVWUreg x)) - // cond: isARM64BFMask(sc, 1<<32-1, 0) - // result: (UBFIZ [armBFAuxInt(sc, 32)] x) + // match: (SLLconst [lc] (MOVHUreg x)) + // result: (UBFIZ [armBFAuxInt(lc, min(16, 64-lc))] x) for { - sc := auxIntToInt64(v.AuxInt) - if v_0.Op != OpARM64MOVWUreg { + lc := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64MOVHUreg { break } x := v_0.Args[0] - if !(isARM64BFMask(sc, 1<<32-1, 0)) { - break - } v.reset(OpARM64UBFIZ) - v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, 32)) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(lc, min(16, 64-lc))) v.AddArg(x) return true } - // match: (SLLconst [sc] (MOVHUreg x)) - // cond: isARM64BFMask(sc, 1<<16-1, 0) - // result: (UBFIZ [armBFAuxInt(sc, 16)] x) + // match: (SLLconst [lc] (MOVBUreg x)) + // result: (UBFIZ [armBFAuxInt(lc, min(8, 64-lc))] x) for { - sc := auxIntToInt64(v.AuxInt) - if v_0.Op != OpARM64MOVHUreg { + lc := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64MOVBUreg { break } x := v_0.Args[0] - if !(isARM64BFMask(sc, 1<<16-1, 0)) { - break - } v.reset(OpARM64UBFIZ) - v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, 16)) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(lc, min(8, 64-lc))) v.AddArg(x) return true } - // match: (SLLconst [sc] (MOVBUreg x)) - // cond: isARM64BFMask(sc, 1<<8-1, 0) - // result: (UBFIZ [armBFAuxInt(sc, 8)] x) + // match: (SLLconst [sc] (ANDconst [ac] x)) + // cond: isARM64BFMask(sc, ac, 0) + // result: (UBFIZ [armBFAuxInt(sc, arm64BFWidth(ac, 0))] x) for { sc := auxIntToInt64(v.AuxInt) - if v_0.Op != OpARM64MOVBUreg { + if v_0.Op != OpARM64ANDconst { break } + ac := auxIntToInt64(v_0.AuxInt) x := v_0.Args[0] - if !(isARM64BFMask(sc, 1<<8-1, 0)) { + if !(isARM64BFMask(sc, ac, 0)) { break } v.reset(OpARM64UBFIZ) - v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, 8)) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, arm64BFWidth(ac, 0))) v.AddArg(x) return true } @@ -20488,90 +20476,90 @@ func rewriteValueARM64_OpARM64SRLconst(v *Value) bool { v.AddArg(x) return true } - // match: (SRLconst [sc] (ANDconst [ac] x)) - // cond: isARM64BFMask(sc, ac, sc) - // result: (UBFX [armBFAuxInt(sc, arm64BFWidth(ac, sc))] x) + // match: (SRLconst [rc] (SLLconst [lc] x)) + // cond: lc < rc + // result: (UBFX [armBFAuxInt(rc-lc, 64-rc)] x) for { - sc := auxIntToInt64(v.AuxInt) - if v_0.Op != OpARM64ANDconst { + rc := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64SLLconst { break } - ac := auxIntToInt64(v_0.AuxInt) + lc := auxIntToInt64(v_0.AuxInt) x := v_0.Args[0] - if !(isARM64BFMask(sc, ac, sc)) { + if !(lc < rc) { break } v.reset(OpARM64UBFX) - v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, arm64BFWidth(ac, sc))) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(rc-lc, 64-rc)) v.AddArg(x) return true } - // match: (SRLconst [sc] (MOVWUreg x)) - // cond: isARM64BFMask(sc, 1<<32-1, sc) - // result: (UBFX [armBFAuxInt(sc, arm64BFWidth(1<<32-1, sc))] x) + // match: (SRLconst [rc] (MOVWUreg x)) + // cond: rc < 32 + // result: (UBFX [armBFAuxInt(rc, 32-rc)] x) for { - sc := auxIntToInt64(v.AuxInt) + rc := auxIntToInt64(v.AuxInt) if v_0.Op != OpARM64MOVWUreg { break } x := v_0.Args[0] - if !(isARM64BFMask(sc, 1<<32-1, sc)) { + if !(rc < 32) { break } v.reset(OpARM64UBFX) - v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, arm64BFWidth(1<<32-1, sc))) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(rc, 32-rc)) v.AddArg(x) return true } - // match: (SRLconst [sc] (MOVHUreg x)) - // cond: isARM64BFMask(sc, 1<<16-1, sc) - // result: (UBFX [armBFAuxInt(sc, arm64BFWidth(1<<16-1, sc))] x) + // match: (SRLconst [rc] (MOVHUreg x)) + // cond: rc < 16 + // result: (UBFX [armBFAuxInt(rc, 16-rc)] x) for { - sc := auxIntToInt64(v.AuxInt) + rc := auxIntToInt64(v.AuxInt) if v_0.Op != OpARM64MOVHUreg { break } x := v_0.Args[0] - if !(isARM64BFMask(sc, 1<<16-1, sc)) { + if !(rc < 16) { break } v.reset(OpARM64UBFX) - v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, arm64BFWidth(1<<16-1, sc))) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(rc, 16-rc)) v.AddArg(x) return true } - // match: (SRLconst [sc] (MOVBUreg x)) - // cond: isARM64BFMask(sc, 1<<8-1, sc) - // result: (UBFX [armBFAuxInt(sc, arm64BFWidth(1<<8-1, sc))] x) + // match: (SRLconst [rc] (MOVBUreg x)) + // cond: rc < 8 + // result: (UBFX [armBFAuxInt(rc, 8-rc)] x) for { - sc := auxIntToInt64(v.AuxInt) + rc := auxIntToInt64(v.AuxInt) if v_0.Op != OpARM64MOVBUreg { break } x := v_0.Args[0] - if !(isARM64BFMask(sc, 1<<8-1, sc)) { + if !(rc < 8) { break } v.reset(OpARM64UBFX) - v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, arm64BFWidth(1<<8-1, sc))) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(rc, 8-rc)) v.AddArg(x) return true } - // match: (SRLconst [rc] (SLLconst [lc] x)) - // cond: lc < rc - // result: (UBFX [armBFAuxInt(rc-lc, 64-rc)] x) + // match: (SRLconst [sc] (ANDconst [ac] x)) + // cond: isARM64BFMask(sc, ac, sc) + // result: (UBFX [armBFAuxInt(sc, arm64BFWidth(ac, sc))] x) for { - rc := auxIntToInt64(v.AuxInt) - if v_0.Op != OpARM64SLLconst { + sc := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64ANDconst { break } - lc := auxIntToInt64(v_0.AuxInt) + ac := auxIntToInt64(v_0.AuxInt) x := v_0.Args[0] - if !(lc < rc) { + if !(isARM64BFMask(sc, ac, sc)) { break } v.reset(OpARM64UBFX) - v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(rc-lc, 64-rc)) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(sc, arm64BFWidth(ac, sc))) v.AddArg(x) return true } diff --git a/test/codegen/bitfield.go b/test/codegen/bitfield.go index 3ed9cfe603..8327da6cf8 100644 --- a/test/codegen/bitfield.go +++ b/test/codegen/bitfield.go @@ -77,11 +77,13 @@ func bfxil2(x, y uint64) uint64 { } // sbfiz +// merge shifts into sbfiz: (x << lc) >> rc && lc > rc. func sbfiz1(x int64) int64 { // arm64:"SBFIZ\t[$]1, R[0-9]+, [$]60",-"LSL",-"ASR" return (x << 4) >> 3 } +// merge shift and sign-extension into sbfiz. func sbfiz2(x int32) int64 { return int64(x << 3) // arm64:"SBFIZ\t[$]3, R[0-9]+, [$]29",-"LSL" } @@ -94,6 +96,8 @@ func sbfiz4(x int8) int64 { return int64(x << 3) // arm64:"SBFIZ\t[$]3, R[0-9]+, [$]5",-"LSL" } +// sbfiz combinations. +// merge shift with sbfiz into sbfiz. func sbfiz5(x int32) int32 { // arm64:"SBFIZ\t[$]1, R[0-9]+, [$]28",-"LSL",-"ASR" return (x << 4) >> 3 @@ -112,6 +116,7 @@ func sbfiz8(x int32) int64 { } // sbfx +// merge shifts into sbfx: (x << lc) >> rc && lc <= rc. func sbfx1(x int64) int64 { return (x << 3) >> 4 // arm64:"SBFX\t[$]1, R[0-9]+, [$]60",-"LSL",-"ASR" } @@ -120,6 +125,7 @@ func sbfx2(x int64) int64 { return (x << 60) >> 60 // arm64:"SBFX\tZR, R[0-9]+, [$]4",-"LSL",-"ASR" } +// merge shift and sign-extension into sbfx. func sbfx3(x int32) int64 { return int64(x) >> 3 // arm64:"SBFX\t[$]3, R[0-9]+, [$]29",-"ASR" } @@ -132,131 +138,181 @@ func sbfx5(x int8) int64 { return int64(x) >> 3 // arm64:"SBFX\t[$]3, R[0-9]+, [$]5",-"ASR" } -func sbfx6(x int32) int32 { +func sbfx6(x int32) int64 { + return int64(x >> 30) // arm64:"SBFX\t[$]30, R[0-9]+, [$]2" +} + +func sbfx7(x int16) int64 { + return int64(x >> 10) // arm64:"SBFX\t[$]10, R[0-9]+, [$]6" +} + +func sbfx8(x int8) int64 { + return int64(x >> 5) // arm64:"SBFX\t[$]5, R[0-9]+, [$]3" +} + +// sbfx combinations. +// merge shifts with sbfiz into sbfx. +func sbfx9(x int32) int32 { return (x << 3) >> 4 // arm64:"SBFX\t[$]1, R[0-9]+, [$]28",-"LSL",-"ASR" } // merge sbfx and sign-extension into sbfx. -func sbfx7(x int32) int64 { +func sbfx10(x int32) int64 { c := x + 5 return int64(c >> 20) // arm64"SBFX\t[$]20, R[0-9]+, [$]12",-"MOVW\tR[0-9]+, R[0-9]+" } // ubfiz +// merge shifts into ubfiz: (x<>rc && lc>rc func ubfiz1(x uint64) uint64 { - // arm64:"UBFIZ\t[$]3, R[0-9]+, [$]12",-"LSL",-"AND" - // s390x:"RISBGZ\t[$]49, [$]60, [$]3,",-"SLD",-"AND" - return (x & 0xfff) << 3 -} - -func ubfiz2(x uint64) uint64 { - // arm64:"UBFIZ\t[$]4, R[0-9]+, [$]12",-"LSL",-"AND" - // s390x:"RISBGZ\t[$]48, [$]59, [$]4,",-"SLD",-"AND" - return (x << 4) & 0xfff0 + // arm64:"UBFIZ\t[$]1, R[0-9]+, [$]60",-"LSL",-"LSR" + // s390x:"RISBGZ\t[$]3, [$]62, [$]1, ",-"SLD",-"SRD" + return (x << 4) >> 3 } -func ubfiz3(x uint32) uint64 { +// merge shift and zero-extension into ubfiz. +func ubfiz2(x uint32) uint64 { return uint64(x+1) << 3 // arm64:"UBFIZ\t[$]3, R[0-9]+, [$]32",-"LSL" } -func ubfiz4(x uint16) uint64 { +func ubfiz3(x uint16) uint64 { return uint64(x+1) << 3 // arm64:"UBFIZ\t[$]3, R[0-9]+, [$]16",-"LSL" } -func ubfiz5(x uint8) uint64 { +func ubfiz4(x uint8) uint64 { return uint64(x+1) << 3 // arm64:"UBFIZ\t[$]3, R[0-9]+, [$]8",-"LSL" } -func ubfiz6(x uint64) uint64 { - // arm64:"UBFIZ\t[$]1, R[0-9]+, [$]60",-"LSL",-"LSR" - // s390x:"RISBGZ\t[$]3, [$]62, [$]1, ",-"SLD",-"SRD" - return (x << 4) >> 3 +func ubfiz5(x uint8) uint64 { + return uint64(x) << 60 // arm64:"UBFIZ\t[$]60, R[0-9]+, [$]4",-"LSL" +} + +func ubfiz6(x uint32) uint64 { + return uint64(x << 30) // arm64:"UBFIZ\t[$]30, R[0-9]+, [$]2", +} + +func ubfiz7(x uint16) uint64 { + return uint64(x << 10) // arm64:"UBFIZ\t[$]10, R[0-9]+, [$]6", +} + +func ubfiz8(x uint8) uint64 { + return uint64(x << 7) // arm64:"UBFIZ\t[$]7, R[0-9]+, [$]1", +} + +// merge ANDconst into ubfiz. +func ubfiz9(x uint64) uint64 { + // arm64:"UBFIZ\t[$]3, R[0-9]+, [$]12",-"LSL",-"AND" + // s390x:"RISBGZ\t[$]49, [$]60, [$]3,",-"SLD",-"AND" + return (x & 0xfff) << 3 +} + +func ubfiz10(x uint64) uint64 { + // arm64:"UBFIZ\t[$]4, R[0-9]+, [$]12",-"LSL",-"AND" + // s390x:"RISBGZ\t[$]48, [$]59, [$]4,",-"SLD",-"AND" + return (x << 4) & 0xfff0 } -func ubfiz7(x uint32) uint32 { +// ubfiz combinations +func ubfiz11(x uint32) uint32 { // arm64:"UBFIZ\t[$]1, R[0-9]+, [$]28",-"LSL",-"LSR" return (x << 4) >> 3 } -func ubfiz8(x uint64) uint64 { +func ubfiz12(x uint64) uint64 { // arm64:"UBFIZ\t[$]1, R[0-9]+, [$]20",-"LSL",-"LSR" // s390x:"RISBGZ\t[$]43, [$]62, [$]1, ",-"SLD",-"SRD",-"AND" return ((x & 0xfffff) << 4) >> 3 } -func ubfiz9(x uint64) uint64 { +func ubfiz13(x uint64) uint64 { // arm64:"UBFIZ\t[$]5, R[0-9]+, [$]13",-"LSL",-"LSR",-"AND" return ((x << 3) & 0xffff) << 2 } -func ubfiz10(x uint64) uint64 { +func ubfiz14(x uint64) uint64 { // arm64:"UBFIZ\t[$]7, R[0-9]+, [$]12",-"LSL",-"LSR",-"AND" // s390x:"RISBGZ\t[$]45, [$]56, [$]7, ",-"SLD",-"SRD",-"AND" return ((x << 5) & (0xfff << 5)) << 2 } // ubfx +// merge shifts into ubfx: (x<>rc && lc> 25) & 1023 -} - -func ubfx2(x uint64) uint64 { - // arm64:"UBFX\t[$]4, R[0-9]+, [$]8",-"LSR",-"AND" - // s390x:"RISBGZ\t[$]56, [$]63, [$]60, ",-"SRD",-"AND" - return (x & 0x0ff0) >> 4 + // arm64:"UBFX\t[$]1, R[0-9]+, [$]62",-"LSL",-"LSR" + // s390x:"RISBGZ\t[$]2, [$]63, [$]63,",-"SLD",-"SRD" + return (x << 1) >> 2 } -func ubfx3(x uint32) uint64 { +// merge shift and zero-extension into ubfx. +func ubfx2(x uint32) uint64 { return uint64(x >> 15) // arm64:"UBFX\t[$]15, R[0-9]+, [$]17",-"LSR" } -func ubfx4(x uint16) uint64 { +func ubfx3(x uint16) uint64 { return uint64(x >> 9) // arm64:"UBFX\t[$]9, R[0-9]+, [$]7",-"LSR" } -func ubfx5(x uint8) uint64 { +func ubfx4(x uint8) uint64 { return uint64(x >> 3) // arm64:"UBFX\t[$]3, R[0-9]+, [$]5",-"LSR" } -func ubfx6(x uint64) uint64 { - // arm64:"UBFX\t[$]1, R[0-9]+, [$]62",-"LSL",-"LSR" - // s390x:"RISBGZ\t[$]2, [$]63, [$]63,",-"SLD",-"SRD" - return (x << 1) >> 2 +func ubfx5(x uint32) uint64 { + return uint64(x) >> 30 // arm64:"UBFX\t[$]30, R[0-9]+, [$]2" +} + +func ubfx6(x uint16) uint64 { + return uint64(x) >> 10 // arm64:"UBFX\t[$]10, R[0-9]+, [$]6" +} + +func ubfx7(x uint8) uint64 { + return uint64(x) >> 3 // arm64:"UBFX\t[$]3, R[0-9]+, [$]5" +} + +// merge ANDconst into ubfx. +func ubfx8(x uint64) uint64 { + // arm64:"UBFX\t[$]25, R[0-9]+, [$]10",-"LSR",-"AND" + // s390x:"RISBGZ\t[$]54, [$]63, [$]39, ",-"SRD",-"AND" + return (x >> 25) & 1023 } -func ubfx7(x uint32) uint32 { +func ubfx9(x uint64) uint64 { + // arm64:"UBFX\t[$]4, R[0-9]+, [$]8",-"LSR",-"AND" + // s390x:"RISBGZ\t[$]56, [$]63, [$]60, ",-"SRD",-"AND" + return (x & 0x0ff0) >> 4 +} + +// ubfx combinations. +func ubfx10(x uint32) uint32 { // arm64:"UBFX\t[$]1, R[0-9]+, [$]30",-"LSL",-"LSR" return (x << 1) >> 2 } -func ubfx8(x uint64) uint64 { +func ubfx11(x uint64) uint64 { // arm64:"UBFX\t[$]1, R[0-9]+, [$]12",-"LSL",-"LSR",-"AND" // s390x:"RISBGZ\t[$]52, [$]63, [$]63,",-"SLD",-"SRD",-"AND" return ((x << 1) >> 2) & 0xfff } -func ubfx9(x uint64) uint64 { +func ubfx12(x uint64) uint64 { // arm64:"UBFX\t[$]4, R[0-9]+, [$]11",-"LSL",-"LSR",-"AND" // s390x:"RISBGZ\t[$]53, [$]63, [$]60, ",-"SLD",-"SRD",-"AND" return ((x >> 3) & 0xfff) >> 1 } -func ubfx10(x uint64) uint64 { +func ubfx13(x uint64) uint64 { // arm64:"UBFX\t[$]5, R[0-9]+, [$]56",-"LSL",-"LSR" // s390x:"RISBGZ\t[$]8, [$]63, [$]59, ",-"SLD",-"SRD" return ((x >> 2) << 5) >> 8 } -func ubfx11(x uint64) uint64 { +func ubfx14(x uint64) uint64 { // arm64:"UBFX\t[$]1, R[0-9]+, [$]19",-"LSL",-"LSR" // s390x:"RISBGZ\t[$]45, [$]63, [$]63, ",-"SLD",-"SRD",-"AND" return ((x & 0xfffff) << 3) >> 4 } // merge ubfx and zero-extension into ubfx. -func ubfx12(x uint64) bool { +func ubfx15(x uint64) bool { midr := x + 10 part_num := uint16((midr >> 4) & 0xfff) if part_num == 0xd0c { // arm64:"UBFX\t[$]4, R[0-9]+, [$]12",-"MOVHU\tR[0-9]+, R[0-9]+" -- GitLab From c69f5c0d7632381dfc6dc78f0af4f54e7673176d Mon Sep 17 00:00:00 2001 From: Michael Munday Date: Thu, 9 Sep 2021 23:47:14 +0100 Subject: [PATCH 1099/2500] cmd/compile: add support for Abs and Copysign intrinsics on riscv64 Also, add the FABSS and FABSD pseudo instructions to the assembler. The compiler could use FSGNJX[SD] directly but there doesn't seem to be much advantage to doing so and the pseudo instructions are easier to understand. Change-Id: Ie8825b8aa8773c69cc4f07a32ef04abf4061d80d Reviewed-on: https://go-review.googlesource.com/c/go/+/348989 Trust: Michael Munday Run-TryBot: Michael Munday TryBot-Result: Go Bot Reviewed-by: Joel Sing --- src/cmd/asm/internal/asm/testdata/riscv64.s | 2 ++ src/cmd/compile/internal/riscv64/ssa.go | 5 ++-- .../compile/internal/ssa/gen/RISCV64.rules | 4 +++ .../compile/internal/ssa/gen/RISCV64Ops.go | 2 ++ src/cmd/compile/internal/ssa/opGen.go | 29 +++++++++++++++++++ .../compile/internal/ssa/rewriteRISCV64.go | 6 ++++ src/cmd/compile/internal/ssagen/ssa.go | 4 +-- src/cmd/internal/obj/riscv/anames.go | 2 ++ src/cmd/internal/obj/riscv/cpu.go | 2 ++ src/cmd/internal/obj/riscv/obj.go | 10 +++++++ test/codegen/math.go | 4 +++ 11 files changed, 66 insertions(+), 4 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/riscv64.s b/src/cmd/asm/internal/asm/testdata/riscv64.s index 1977d92f62..64b94a2a04 100644 --- a/src/cmd/asm/internal/asm/testdata/riscv64.s +++ b/src/cmd/asm/internal/asm/testdata/riscv64.s @@ -382,10 +382,12 @@ start: SNEZ X15, X15 // b337f000 // F extension + FABSS F0, F1 // d3200020 FNEGS F0, F1 // d3100020 FNES F0, F1, X7 // d3a300a093c31300 // D extension + FABSD F0, F1 // d3200022 FNEGD F0, F1 // d3100022 FNED F0, F1, X5 // d3a200a293c21200 FLTD F0, F1, X5 // d39200a2 diff --git a/src/cmd/compile/internal/riscv64/ssa.go b/src/cmd/compile/internal/riscv64/ssa.go index 30b6d96a89..e400ca1ffe 100644 --- a/src/cmd/compile/internal/riscv64/ssa.go +++ b/src/cmd/compile/internal/riscv64/ssa.go @@ -272,7 +272,8 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { ssa.OpRISCV64FADDS, ssa.OpRISCV64FSUBS, ssa.OpRISCV64FMULS, ssa.OpRISCV64FDIVS, ssa.OpRISCV64FEQS, ssa.OpRISCV64FNES, ssa.OpRISCV64FLTS, ssa.OpRISCV64FLES, ssa.OpRISCV64FADDD, ssa.OpRISCV64FSUBD, ssa.OpRISCV64FMULD, ssa.OpRISCV64FDIVD, - ssa.OpRISCV64FEQD, ssa.OpRISCV64FNED, ssa.OpRISCV64FLTD, ssa.OpRISCV64FLED: + ssa.OpRISCV64FEQD, ssa.OpRISCV64FNED, ssa.OpRISCV64FLTD, ssa.OpRISCV64FLED, + ssa.OpRISCV64FSGNJD: r := v.Reg() r1 := v.Args[0].Reg() r2 := v.Args[1].Reg() @@ -329,7 +330,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.SetRestArgs([]obj.Addr{{Type: obj.TYPE_REG, Reg: r3}}) p.To.Type = obj.TYPE_REG p.To.Reg = r - case ssa.OpRISCV64FSQRTS, ssa.OpRISCV64FNEGS, ssa.OpRISCV64FSQRTD, ssa.OpRISCV64FNEGD, + case ssa.OpRISCV64FSQRTS, ssa.OpRISCV64FNEGS, ssa.OpRISCV64FABSD, ssa.OpRISCV64FSQRTD, ssa.OpRISCV64FNEGD, ssa.OpRISCV64FMVSX, ssa.OpRISCV64FMVDX, ssa.OpRISCV64FCVTSW, ssa.OpRISCV64FCVTSL, ssa.OpRISCV64FCVTWS, ssa.OpRISCV64FCVTLS, ssa.OpRISCV64FCVTDW, ssa.OpRISCV64FCVTDL, ssa.OpRISCV64FCVTWD, ssa.OpRISCV64FCVTLD, ssa.OpRISCV64FCVTDS, ssa.OpRISCV64FCVTSD, diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64.rules b/src/cmd/compile/internal/ssa/gen/RISCV64.rules index b711550186..aa7c452d05 100644 --- a/src/cmd/compile/internal/ssa/gen/RISCV64.rules +++ b/src/cmd/compile/internal/ssa/gen/RISCV64.rules @@ -96,6 +96,10 @@ (Sqrt ...) => (FSQRTD ...) (Sqrt32 ...) => (FSQRTS ...) +(Copysign ...) => (FSGNJD ...) + +(Abs ...) => (FABSD ...) + (FMA ...) => (FMADDD ...) // Sign and zero extension. diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go index de189e4c60..ac1bcd2a06 100644 --- a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go @@ -432,6 +432,8 @@ func init() { {name: "FNMSUBD", argLength: 3, reg: fp31, asm: "FNMSUBD", commutative: true, typ: "Float64"}, // -(arg0 * arg1) - arg2 {name: "FSQRTD", argLength: 1, reg: fp11, asm: "FSQRTD", typ: "Float64"}, // sqrt(arg0) {name: "FNEGD", argLength: 1, reg: fp11, asm: "FNEGD", typ: "Float64"}, // -arg0 + {name: "FABSD", argLength: 1, reg: fp11, asm: "FABSD", typ: "Float64"}, // abs(arg0) + {name: "FSGNJD", argLength: 2, reg: fp21, asm: "FSGNJD", typ: "Float64"}, // copy sign of arg1 to arg0 {name: "FMVDX", argLength: 1, reg: gpfp, asm: "FMVDX", typ: "Float64"}, // reinterpret arg0 as float {name: "FCVTDW", argLength: 1, reg: gpfp, asm: "FCVTDW", typ: "Float64"}, // float64(low 32 bits of arg0) {name: "FCVTDL", argLength: 1, reg: gpfp, asm: "FCVTDL", typ: "Float64"}, // float64(arg0) diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 573559db70..1ca99c1ba9 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -2183,6 +2183,8 @@ const ( OpRISCV64FNMSUBD OpRISCV64FSQRTD OpRISCV64FNEGD + OpRISCV64FABSD + OpRISCV64FSGNJD OpRISCV64FMVDX OpRISCV64FCVTDW OpRISCV64FCVTDL @@ -29187,6 +29189,33 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "FABSD", + argLen: 1, + asm: riscv.AFABSD, + reg: regInfo{ + inputs: []inputInfo{ + {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + }, + outputs: []outputInfo{ + {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + }, + }, + }, + { + name: "FSGNJD", + argLen: 2, + asm: riscv.AFSGNJD, + reg: regInfo{ + inputs: []inputInfo{ + {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + }, + outputs: []outputInfo{ + {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + }, + }, + }, { name: "FMVDX", argLen: 1, diff --git a/src/cmd/compile/internal/ssa/rewriteRISCV64.go b/src/cmd/compile/internal/ssa/rewriteRISCV64.go index 743ff50b0c..3a277ca369 100644 --- a/src/cmd/compile/internal/ssa/rewriteRISCV64.go +++ b/src/cmd/compile/internal/ssa/rewriteRISCV64.go @@ -8,6 +8,9 @@ import "cmd/compile/internal/types" func rewriteValueRISCV64(v *Value) bool { switch v.Op { + case OpAbs: + v.Op = OpRISCV64FABSD + return true case OpAdd16: v.Op = OpRISCV64ADD return true @@ -134,6 +137,9 @@ func rewriteValueRISCV64(v *Value) bool { case OpConvert: v.Op = OpRISCV64MOVconvert return true + case OpCopysign: + v.Op = OpRISCV64FSGNJD + return true case OpCvt32Fto32: v.Op = OpRISCV64FCVTWS return true diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 11bca89fd8..1e7eda94fc 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -4212,12 +4212,12 @@ func InitTables() { func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return s.newValue1(ssa.OpAbs, types.Types[types.TFLOAT64], args[0]) }, - sys.ARM64, sys.ARM, sys.PPC64, sys.Wasm) + sys.ARM64, sys.ARM, sys.PPC64, sys.RISCV64, sys.Wasm) addF("math", "Copysign", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return s.newValue2(ssa.OpCopysign, types.Types[types.TFLOAT64], args[0], args[1]) }, - sys.PPC64, sys.Wasm) + sys.PPC64, sys.RISCV64, sys.Wasm) addF("math", "FMA", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return s.newValue3(ssa.OpFMA, types.Types[types.TFLOAT64], args[0], args[1], args[2]) diff --git a/src/cmd/internal/obj/riscv/anames.go b/src/cmd/internal/obj/riscv/anames.go index 6581bb3402..d2a3674ebe 100644 --- a/src/cmd/internal/obj/riscv/anames.go +++ b/src/cmd/internal/obj/riscv/anames.go @@ -236,6 +236,8 @@ var Anames = []string{ "BLEZ", "BLTZ", "BNEZ", + "FABSD", + "FABSS", "FNEGD", "FNEGS", "FNED", diff --git a/src/cmd/internal/obj/riscv/cpu.go b/src/cmd/internal/obj/riscv/cpu.go index 1519dc1a63..a258367ae9 100644 --- a/src/cmd/internal/obj/riscv/cpu.go +++ b/src/cmd/internal/obj/riscv/cpu.go @@ -590,6 +590,8 @@ const ( ABLEZ ABLTZ ABNEZ + AFABSD + AFABSS AFNEGD AFNEGS AFNED diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index fafde64062..62d44d8a3f 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -1998,6 +1998,16 @@ func instructionsForProg(p *obj.Prog) []*instruction { ins.as = ASLTU ins.rs1 = REG_ZERO + case AFABSS: + // FABSS rs, rd -> FSGNJXS rs, rs, rd + ins.as = AFSGNJXS + ins.rs1 = uint32(p.From.Reg) + + case AFABSD: + // FABSD rs, rd -> FSGNJXD rs, rs, rd + ins.as = AFSGNJXD + ins.rs1 = uint32(p.From.Reg) + case AFNEGS: // FNEGS rs, rd -> FSGNJNS rs, rs, rd ins.as = AFSGNJNS diff --git a/test/codegen/math.go b/test/codegen/math.go index cd573db7b3..df2ebd79e1 100644 --- a/test/codegen/math.go +++ b/test/codegen/math.go @@ -73,6 +73,7 @@ func abs(x, y float64) { // s390x:"LPDFR\t",-"MOVD\t" (no integer load/store) // ppc64:"FABS\t" // ppc64le:"FABS\t" + // riscv64:"FABSD\t" // wasm:"F64Abs" // arm/6:"ABSD\t" sink64[0] = math.Abs(x) @@ -96,6 +97,7 @@ func copysign(a, b, c float64) { // s390x:"CPSDR",-"MOVD" (no integer load/store) // ppc64:"FCPSGN" // ppc64le:"FCPSGN" + // riscv64:"FSGNJD" // wasm:"F64Copysign" sink64[0] = math.Copysign(a, b) @@ -103,6 +105,7 @@ func copysign(a, b, c float64) { // s390x:"LNDFR\t",-"MOVD\t" (no integer load/store) // ppc64:"FCPSGN" // ppc64le:"FCPSGN" + // riscv64:"FSGNJD" // arm64:"ORR", -"AND" sink64[1] = math.Copysign(c, -1) @@ -115,6 +118,7 @@ func copysign(a, b, c float64) { // s390x:"CPSDR\t",-"MOVD\t" (no integer load/store) // ppc64:"FCPSGN" // ppc64le:"FCPSGN" + // riscv64:"FSGNJD" sink64[3] = math.Copysign(-1, c) } -- GitLab From 90c5660616d7f006ca62adfec49310bf40e3b354 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Mon, 26 Apr 2021 22:32:21 +0900 Subject: [PATCH 1100/2500] embed: guarantee the returned file of FS.Open implements io.Seeker Fixes golang/go#45745 Change-Id: Ib49a9605a38074f544a5d28116862e191cea8c0f Reviewed-on: https://go-review.googlesource.com/c/go/+/313352 Run-TryBot: Hajime Hoshi TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Than McIntosh --- src/embed/embed.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/embed/embed.go b/src/embed/embed.go index 5dcd7f227d..f87cc5b963 100644 --- a/src/embed/embed.go +++ b/src/embed/embed.go @@ -291,6 +291,8 @@ func (f FS) readDir(dir string) []file { } // Open opens the named file for reading and returns it as an fs.File. +// +// The returned file implements io.Seeker when the file is not a directory. func (f FS) Open(name string) (fs.File, error) { file := f.lookup(name) if file == nil { @@ -338,6 +340,10 @@ type openFile struct { offset int64 // current read offset } +var ( + _ io.Seeker = (*openFile)(nil) +) + func (f *openFile) Close() error { return nil } func (f *openFile) Stat() (fs.FileInfo, error) { return f.f, nil } -- GitLab From 96ab854ab03f6a21c676c2a7aa9c4ad933892a42 Mon Sep 17 00:00:00 2001 From: Zheng Xu Date: Wed, 1 Sep 2021 13:48:48 +0800 Subject: [PATCH 1101/2500] cmd/compile/internal: better AST line highlight in ssa.html We tend to set div class with the line number in HTML AST nodes. So that the AST nodes can be highlighted with corresponding source and ssa ir. The pure AST text dump is created first. And then it is parsed and written to the HTML file. CL 275785 changed the format of the line information in AST node dump, which makes the HTMLWriter fail to parse the line information. This CL updates the code in HTMLWriter to align with the format of AST node dump. Fix #48133 Change-Id: I2b56fc5e3e9771456d91f22caf23a427c235eb12 Reviewed-on: https://go-review.googlesource.com/c/go/+/347269 Reviewed-by: Cherry Mui Trust: Than McIntosh --- src/cmd/compile/internal/ir/fmt.go | 1 + src/cmd/compile/internal/ssa/html.go | 15 ++++++--------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index 22fbf39975..a99cb5ed98 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -1147,6 +1147,7 @@ func dumpNodeHeader(w io.Writer, n Node) { } // TODO(mdempsky): Print line pragma details too. file := filepath.Base(pos.Filename()) + // Note: this output will be parsed by ssa/html.go:(*HTMLWriter).WriteAST. Keep in sync. fmt.Fprintf(w, "%s:%d:%d", file, pos.Line(), pos.Col()) } } diff --git a/src/cmd/compile/internal/ssa/html.go b/src/cmd/compile/internal/ssa/html.go index 6fd898636c..d9a78b3962 100644 --- a/src/cmd/compile/internal/ssa/html.go +++ b/src/cmd/compile/internal/ssa/html.go @@ -903,15 +903,12 @@ func (w *HTMLWriter) WriteAST(phase string, buf *bytes.Buffer) { if strings.HasPrefix(l, "buildssa") { escaped = fmt.Sprintf("%v", l) } else { - // Parse the line number from the format l(123). - idx := strings.Index(l, " l(") - if idx != -1 { - subl := l[idx+3:] - idxEnd := strings.Index(subl, ")") - if idxEnd != -1 { - if _, err := strconv.Atoi(subl[:idxEnd]); err == nil { - lineNo = subl[:idxEnd] - } + // Parse the line number from the format file:line:col. + // See the implementation in ir/fmt.go:dumpNodeHeader. + sl := strings.Split(l, ":") + if len(sl) >= 3 { + if _, err := strconv.Atoi(sl[len(sl)-2]); err == nil { + lineNo = sl[len(sl)-2] } } escaped = html.EscapeString(l) -- GitLab From 213d9f9a3893eeed1fe1fe5e9e216da33f4d75c4 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Fri, 10 Sep 2021 09:49:03 -0400 Subject: [PATCH 1102/2500] [dev.fuzz] internal/fuzz: improve warning message when not instrumented Change-Id: I005f66c965014b699de7e22750f417b28a32c03f Reviewed-on: https://go-review.googlesource.com/c/go/+/349052 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/internal/fuzz/fuzz.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index f36569b4cc..6c07da2dbe 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -613,11 +613,7 @@ func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { covSize := len(coverage()) if covSize == 0 { - // TODO: improve this warning. This condition happens if the binary was - // built without fuzzing instrumtation (e.g., with 'go test -c'), so the - // warning may not be true. - fmt.Fprintf(c.opts.Log, "warning: coverage-guided fuzzing is not supported on this platform\n") - c.covOnlyInputs = 0 + fmt.Fprintf(c.opts.Log, "warning: the test binary was not built with coverage instrumentation, so fuzzing will run without coverage guidance and may be inefficient\n") } else { // Set c.coverageData to a clean []byte full of zeros. c.coverageMask = make([]byte, covSize) -- GitLab From b38e853d04ffc00732474e2e90ffad24f5c6a462 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Fri, 10 Sep 2021 10:00:00 -0400 Subject: [PATCH 1103/2500] [dev.fuzz] testing: move corpus from testdata/corpus to testdata/fuzz Fixes golang/go#48128 Change-Id: I04deb17226ff5d5dfcbe408fe089f400d4d3836f Reviewed-on: https://go-review.googlesource.com/c/go/+/349053 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/testdata/script/test_fuzz.txt | 12 +++---- .../go/testdata/script/test_fuzz_fuzztime.txt | 2 +- .../go/testdata/script/test_fuzz_minimize.txt | 4 +-- .../script/test_fuzz_mutate_crash.txt | 34 +++++++++---------- .../script/test_fuzz_non_crash_signal.txt | 2 +- .../go/testdata/script/test_fuzz_parallel.txt | 2 +- src/testing/fuzz.go | 4 +-- 7 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt index a25f0fba3f..3f825c1bc3 100644 --- a/src/cmd/go/testdata/script/test_fuzz.txt +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -445,20 +445,20 @@ func FuzzWrongType(f *testing.F) { f.Fuzz(func(t *testing.T, b []byte) {}) } --- corpustesting/testdata/corpus/FuzzFail/1 -- +-- corpustesting/testdata/fuzz/FuzzFail/1 -- go test fuzz v1 []byte("12345") --- corpustesting/testdata/corpus/FuzzPass/1 -- +-- corpustesting/testdata/fuzz/FuzzPass/1 -- go test fuzz v1 []byte("00000") --- corpustesting/testdata/corpus/FuzzPassString/1 -- +-- corpustesting/testdata/fuzz/FuzzPassString/1 -- go test fuzz v1 string("hello") --- corpustesting/testdata/corpus/FuzzPanic/1 -- +-- corpustesting/testdata/fuzz/FuzzPanic/1 -- malformed --- corpustesting/testdata/corpus/FuzzInNestedDir/anotherdir/1 -- +-- corpustesting/testdata/fuzz/FuzzInNestedDir/anotherdir/1 -- go test fuzz v1 []byte("12345") --- corpustesting/testdata/corpus/FuzzWrongType/1 -- +-- corpustesting/testdata/fuzz/FuzzWrongType/1 -- go test fuzz v1 int("00000") \ No newline at end of file diff --git a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt index 5eb8c86708..7d644b4d13 100644 --- a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt +++ b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt @@ -14,7 +14,7 @@ go test -c exec ./fuzz.test$GOEXE -test.timeout=10ms -test.fuzz=FuzzFast -test.fuzztime=5s -test.parallel=1 -test.fuzzcachedir=$WORK/cache # Timeout should not cause inputs to be written as crashers. -! exists testdata/corpus +! exists testdata/fuzz # When we use fuzztime with an "x" suffix, it runs a specific number of times. # This fuzz function creates a file with a unique name ($pid.$count) on each run. diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize.txt b/src/cmd/go/testdata/script/test_fuzz_minimize.txt index 473d63ebfa..002aca009b 100644 --- a/src/cmd/go/testdata/script/test_fuzz_minimize.txt +++ b/src/cmd/go/testdata/script/test_fuzz_minimize.txt @@ -39,7 +39,7 @@ go clean -fuzzcache # crash will still be logged and written to testdata. ! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=100x -fuzzminimizetime=1x minimizer_test.go ! stdout '^ok' -stdout 'testdata[/\\]corpus[/\\]FuzzMinimizerRecoverable[/\\]' +stdout 'testdata[/\\]fuzz[/\\]FuzzMinimizerRecoverable[/\\]' ! stdout 'got the minimum size!' # it shouldn't have had enough time to minimize it stdout FAIL @@ -121,7 +121,7 @@ func main() { } // Open the file in testdata (there should only be one) - dir := fmt.Sprintf("testdata/corpus/%s", target) + dir := fmt.Sprintf("testdata/fuzz/%s", target) files, err := ioutil.ReadDir(dir) if err != nil { fmt.Fprintln(os.Stderr, err) diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt index 92a52ccdea..1b8b79b3dd 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt @@ -14,89 +14,89 @@ go test # Running the fuzzer should find a crashing input quickly. ! go test -fuzz=FuzzWithBug -fuzztime=100x -fuzzminimizetime=1000x -stdout 'testdata[/\\]corpus[/\\]FuzzWithBug[/\\]' +stdout 'testdata[/\\]fuzz[/\\]FuzzWithBug[/\\]' stdout 'this input caused a crash!' go run check_testdata.go FuzzWithBug # Now, the failing bytes should have been added to the seed corpus for # the target, and should fail when run without fuzzing. ! go test -stdout 'testdata[/\\]corpus[/\\]FuzzWithBug[/\\][a-f0-9]{64}' +stdout 'testdata[/\\]fuzz[/\\]FuzzWithBug[/\\][a-f0-9]{64}' stdout 'this input caused a crash!' ! go test -run=FuzzWithNilPanic -fuzz=FuzzWithNilPanic -fuzztime=100x -fuzzminimizetime=1000x -stdout 'testdata[/\\]corpus[/\\]FuzzWithNilPanic[/\\]' +stdout 'testdata[/\\]fuzz[/\\]FuzzWithNilPanic[/\\]' stdout 'runtime.Goexit' go run check_testdata.go FuzzWithNilPanic ! go test -run=FuzzWithFail -fuzz=FuzzWithFail -fuzztime=100x -fuzzminimizetime=1000x -stdout 'testdata[/\\]corpus[/\\]FuzzWithFail[/\\]' +stdout 'testdata[/\\]fuzz[/\\]FuzzWithFail[/\\]' go run check_testdata.go FuzzWithFail ! go test -run=FuzzWithLogFail -fuzz=FuzzWithLogFail -fuzztime=100x -fuzzminimizetime=1000x -stdout 'testdata[/\\]corpus[/\\]FuzzWithLogFail[/\\]' +stdout 'testdata[/\\]fuzz[/\\]FuzzWithLogFail[/\\]' stdout 'logged something' go run check_testdata.go FuzzWithLogFail ! go test -run=FuzzWithErrorf -fuzz=FuzzWithErrorf -fuzztime=100x -fuzzminimizetime=1000x -stdout 'testdata[/\\]corpus[/\\]FuzzWithErrorf[/\\]' +stdout 'testdata[/\\]fuzz[/\\]FuzzWithErrorf[/\\]' stdout 'errorf was called here' go run check_testdata.go FuzzWithErrorf ! go test -run=FuzzWithFatalf -fuzz=FuzzWithFatalf -fuzztime=100x -fuzzminimizetime=1000x -stdout 'testdata[/\\]corpus[/\\]FuzzWithFatalf[/\\]' +stdout 'testdata[/\\]fuzz[/\\]FuzzWithFatalf[/\\]' stdout 'fatalf was called here' go run check_testdata.go FuzzWithFatalf ! go test -run=FuzzWithBadExit -fuzz=FuzzWithBadExit -fuzztime=100x -fuzzminimizetime=1000x -stdout 'testdata[/\\]corpus[/\\]FuzzWithBadExit[/\\]' +stdout 'testdata[/\\]fuzz[/\\]FuzzWithBadExit[/\\]' stdout 'unexpectedly' go run check_testdata.go FuzzWithBadExit # Running the fuzzer should find a crashing input quickly for fuzzing two types. ! go test -run=FuzzWithTwoTypes -fuzz=FuzzWithTwoTypes -fuzztime=100x -fuzzminimizetime=1000x -stdout 'testdata[/\\]corpus[/\\]FuzzWithTwoTypes[/\\]' +stdout 'testdata[/\\]fuzz[/\\]FuzzWithTwoTypes[/\\]' stdout 'these inputs caused a crash!' go run check_testdata.go FuzzWithTwoTypes # Running the fuzzer should find a crashing input quickly for an integer. ! go test -run=FuzzInt -fuzz=FuzzInt -fuzztime=100x -fuzzminimizetime=1000x -stdout 'testdata[/\\]corpus[/\\]FuzzInt[/\\]' +stdout 'testdata[/\\]fuzz[/\\]FuzzInt[/\\]' stdout 'this input caused a crash!' go run check_testdata.go FuzzInt ! go test -run=FuzzUint -fuzz=FuzzUint -fuzztime=100x -fuzzminimizetime=1000x -stdout 'testdata[/\\]corpus[/\\]FuzzUint[/\\]' +stdout 'testdata[/\\]fuzz[/\\]FuzzUint[/\\]' stdout 'this input caused a crash!' go run check_testdata.go FuzzUint # Running the fuzzer should find a crashing input quickly for a bool. ! go test -run=FuzzBool -fuzz=FuzzBool -fuzztime=100x -fuzzminimizetime=1000x -stdout 'testdata[/\\]corpus[/\\]FuzzBool[/\\]' +stdout 'testdata[/\\]fuzz[/\\]FuzzBool[/\\]' stdout 'this input caused a crash!' go run check_testdata.go FuzzBool # Running the fuzzer should find a crashing input quickly for a float. ! go test -run=FuzzFloat -fuzz=FuzzFloat -fuzztime=100x -fuzzminimizetime=1000x -stdout 'testdata[/\\]corpus[/\\]FuzzFloat[/\\]' +stdout 'testdata[/\\]fuzz[/\\]FuzzFloat[/\\]' stdout 'this input caused a crash!' go run check_testdata.go FuzzFloat # Running the fuzzer should find a crashing input quickly for a byte. ! go test -run=FuzzByte -fuzz=FuzzByte -fuzztime=100x -fuzzminimizetime=1000x -stdout 'testdata[/\\]corpus[/\\]FuzzByte[/\\]' +stdout 'testdata[/\\]fuzz[/\\]FuzzByte[/\\]' stdout 'this input caused a crash!' go run check_testdata.go FuzzByte # Running the fuzzer should find a crashing input quickly for a rune. ! go test -run=FuzzRune -fuzz=FuzzRune -fuzztime=100x -fuzzminimizetime=1000x -stdout 'testdata[/\\]corpus[/\\]FuzzRune[/\\]' +stdout 'testdata[/\\]fuzz[/\\]FuzzRune[/\\]' stdout 'this input caused a crash!' go run check_testdata.go FuzzRune # Running the fuzzer should find a crashing input quickly for a string. ! go test -run=FuzzString -fuzz=FuzzString -fuzztime=100x -fuzzminimizetime=1000x -stdout 'testdata[/\\]corpus[/\\]FuzzString[/\\]' +stdout 'testdata[/\\]fuzz[/\\]FuzzString[/\\]' stdout 'this input caused a crash!' go run check_testdata.go FuzzString @@ -263,7 +263,7 @@ import ( func main() { target := os.Args[1] - dir := filepath.Join("testdata/corpus", target) + dir := filepath.Join("testdata/fuzz", target) files, err := ioutil.ReadDir(dir) if err != nil { diff --git a/src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt b/src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt index a67bf63c0b..1568757de7 100644 --- a/src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt +++ b/src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt @@ -15,7 +15,7 @@ stdout 'fuzzing process terminated by unexpected signal; no crash will be record # FuzzCrash sends itself a signal that looks like a crash. # We should save a crasher. ! go test -fuzz=FuzzCrash -exists testdata/corpus/FuzzCrash +exists testdata/fuzz/FuzzCrash stdout 'fuzzing process terminated unexpectedly' -- go.mod -- diff --git a/src/cmd/go/testdata/script/test_fuzz_parallel.txt b/src/cmd/go/testdata/script/test_fuzz_parallel.txt index d9f6cc720b..a49f30a27f 100644 --- a/src/cmd/go/testdata/script/test_fuzz_parallel.txt +++ b/src/cmd/go/testdata/script/test_fuzz_parallel.txt @@ -13,7 +13,7 @@ go test -run=FuzzSeed # TODO(jayconrod): check for the string "after T.Parallel". It's not printed # by 'go test', so we can't distinguish that crasher from some other panic. ! go test -run=FuzzMutate -fuzz=FuzzMutate -exists testdata/corpus/FuzzMutate +exists testdata/fuzz/FuzzMutate -- go.mod -- module fuzz_parallel diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index e567f7d9f4..975aa87eab 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -34,7 +34,7 @@ var ( // corpusDir is the parent directory of the target's seed corpus within // the package. - corpusDir = "testdata/corpus" + corpusDir = "testdata/fuzz" ) // fuzzWorkerExitCode is used as an exit code by fuzz worker processes after an internal error. @@ -419,7 +419,7 @@ func (f *F) Fuzz(ff interface{}) { fmt.Fprintf(f.w, "%v\n", err) if crashErr, ok := err.(fuzzCrashError); ok { crashName := crashErr.CrashName() - fmt.Fprintf(f.w, "Crash written to %s\n", filepath.Join("testdata/corpus", f.name, crashName)) + fmt.Fprintf(f.w, "Crash written to %s\n", filepath.Join(corpusDir, f.name, crashName)) fmt.Fprintf(f.w, "To re-run:\ngo test %s -run=%s/%s\n", f.fuzzContext.importPath(), f.name, crashName) } } -- GitLab From da1aa650536b188c4dce287003a6f46b0dc4bdd5 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 9 Sep 2021 15:43:19 -0700 Subject: [PATCH 1104/2500] cmd/compile/internal/syntax: correct follow token for type parameter lists When parsing a type parameter declaration, parts of the code still expected a ) as closing token. Use the correct follow token ) or ] depending on parameter list kind. Also, consistently use tokstring (not tok.String()) for user-facing (error) messages. Follow-up on comment in CL 348730. For #43527. Change-Id: Ib1d4feb526771a1668a54c3bb7a671f6c8a65940 Reviewed-on: https://go-review.googlesource.com/c/go/+/348742 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/syntax/parser.go | 14 ++++++++------ .../compile/internal/syntax/testdata/tparams.go2 | 2 ++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index c836a21c2f..82cb06b180 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -276,7 +276,9 @@ func (p *parser) syntaxErrorAt(pos Pos, msg string) { } // tokstring returns the English word for selected punctuation tokens -// for more readable error messages. +// for more readable error messages. Use tokstring (not tok.String()) +// for user-facing (error) messages; use tok.String() for debugging +// output. func tokstring(tok token) string { switch tok { case _Comma: @@ -1839,7 +1841,7 @@ func (p *parser) embeddedTerm() Expr { } // ParameterDecl = [ IdentifierList ] [ "..." ] Type . -func (p *parser) paramDeclOrNil(name *Name) *Field { +func (p *parser) paramDeclOrNil(name *Name, follow token) *Field { if trace { defer p.trace("paramDecl")() } @@ -1893,8 +1895,8 @@ func (p *parser) paramDeclOrNil(name *Name) *Field { return f } - p.syntaxError("expecting )") - p.advance(_Comma, _Rparen) + p.syntaxError("expecting " + tokstring(follow)) + p.advance(_Comma, follow) return nil } @@ -1911,7 +1913,7 @@ func (p *parser) paramList(name *Name, close token, requireNames bool) (list []* var named int // number of parameters that have an explicit name and type var typed int // number of parameters that have an explicit type end := p.list(_Comma, close, func() bool { - par := p.paramDeclOrNil(name) + par := p.paramDeclOrNil(name, close) name = nil // 1st name was consumed if present if par != nil { if debug && par.Name == nil && par.Type == nil { @@ -2211,7 +2213,7 @@ func (p *parser) header(keyword token) (init SimpleStmt, cond Expr, post SimpleS if p.tok != _Semi { // accept potential varDecl but complain if p.got(_Var) { - p.syntaxError(fmt.Sprintf("var declaration not allowed in %s initializer", keyword.String())) + p.syntaxError(fmt.Sprintf("var declaration not allowed in %s initializer", tokstring(keyword))) } init = p.simpleStmt(nil, keyword) // If we have a range clause, we are done (can only happen for keyword == _For). diff --git a/src/cmd/compile/internal/syntax/testdata/tparams.go2 b/src/cmd/compile/internal/syntax/testdata/tparams.go2 index 8e47ff5ed8..80e155bfe0 100644 --- a/src/cmd/compile/internal/syntax/testdata/tparams.go2 +++ b/src/cmd/compile/internal/syntax/testdata/tparams.go2 @@ -20,3 +20,5 @@ type t interface { func f[ /* ERROR empty type parameter list */ ]() func f[a, b /* ERROR missing type constraint */ ]() func f[a t, b t, c /* ERROR missing type constraint */ ]() + +func f[a b, /* ERROR expecting ] */ 0] () -- GitLab From 5a94a90d84cc65a04ab44737baa406023e9b2001 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 8 Sep 2021 22:08:14 -0700 Subject: [PATCH 1105/2500] cmd/compile/internal/types2: better error message for invalid array decls Fixes #43527. Change-Id: I988a4d49f2f54b4b1741688fb52a55bf313d39e1 Reviewed-on: https://go-review.googlesource.com/c/go/+/348731 Trust: Robert Griesemer Reviewed-by: Robert Findley --- .../types2/testdata/fixedbugs/issue43527.go2 | 16 ++++++++++++++++ src/cmd/compile/internal/types2/typexpr.go | 10 ++++++++++ src/go/types/testdata/fixedbugs/issue43527.go2 | 16 ++++++++++++++++ src/go/types/typexpr.go | 10 ++++++++++ 4 files changed, 52 insertions(+) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue43527.go2 create mode 100644 src/go/types/testdata/fixedbugs/issue43527.go2 diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43527.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43527.go2 new file mode 100644 index 0000000000..e4bcee51fe --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43527.go2 @@ -0,0 +1,16 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +const L = 10 + +type ( + _ [L]struct{} + _ [A /* ERROR undeclared name A for array length */ ]struct{} + _ [B /* ERROR not an expression */ ]struct{} + _[A any] struct{} + + B int +) diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index f3db3bbba9..5aacb94a60 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -428,6 +428,14 @@ func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def // and returns the constant length >= 0, or a value < 0 // to indicate an error (and thus an unknown length). func (check *Checker) arrayLength(e syntax.Expr) int64 { + // If e is an undeclared identifier, the array declaration might be an + // attempt at a parameterized type declaration with missing constraint. + // Provide a better error message than just "undeclared name: X". + if name, _ := e.(*syntax.Name); name != nil && check.lookup(name.Value) == nil { + check.errorf(name, "undeclared name %s for array length", name.Value) + return -1 + } + var x operand check.expr(&x, e) if x.mode != constant_ { @@ -436,6 +444,7 @@ func (check *Checker) arrayLength(e syntax.Expr) int64 { } return -1 } + if isUntyped(x.typ) || isInteger(x.typ) { if val := constant.ToInt(x.val); val.Kind() == constant.Int { if representableConst(val, check, Typ[Int], nil) { @@ -447,6 +456,7 @@ func (check *Checker) arrayLength(e syntax.Expr) int64 { } } } + check.errorf(&x, "array length %s must be integer", &x) return -1 } diff --git a/src/go/types/testdata/fixedbugs/issue43527.go2 b/src/go/types/testdata/fixedbugs/issue43527.go2 new file mode 100644 index 0000000000..e4bcee51fe --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue43527.go2 @@ -0,0 +1,16 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +const L = 10 + +type ( + _ [L]struct{} + _ [A /* ERROR undeclared name A for array length */ ]struct{} + _ [B /* ERROR not an expression */ ]struct{} + _[A any] struct{} + + B int +) diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 6b4a3538b6..0143f53009 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -412,6 +412,14 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named // and returns the constant length >= 0, or a value < 0 // to indicate an error (and thus an unknown length). func (check *Checker) arrayLength(e ast.Expr) int64 { + // If e is an undeclared identifier, the array declaration might be an + // attempt at a parameterized type declaration with missing constraint. + // Provide a better error message than just "undeclared name: X". + if name, _ := e.(*ast.Ident); name != nil && check.lookup(name.Name) == nil { + check.errorf(name, _InvalidArrayLen, "undeclared name %s for array length", name.Name) + return -1 + } + var x operand check.expr(&x, e) if x.mode != constant_ { @@ -420,6 +428,7 @@ func (check *Checker) arrayLength(e ast.Expr) int64 { } return -1 } + if isUntyped(x.typ) || isInteger(x.typ) { if val := constant.ToInt(x.val); val.Kind() == constant.Int { if representableConst(val, check, Typ[Int], nil) { @@ -431,6 +440,7 @@ func (check *Checker) arrayLength(e ast.Expr) int64 { } } } + check.errorf(&x, _InvalidArrayLen, "array length %s must be integer", &x) return -1 } -- GitLab From 025308fe084264538f49924b3f52d8d6b6359658 Mon Sep 17 00:00:00 2001 From: Ethan Reesor Date: Fri, 20 Aug 2021 18:57:45 -0500 Subject: [PATCH 1106/2500] testing: increase alternation precedence Updates handling of go test flags -run and -bench to give alternation precendence over the / delimiter. Currently, `A/B|C/D` is effectively `A/(B|C)/D` - with this change, it changes to effectively `(A/B)|(C/D)`. Fixes #39904 Change-Id: Iebe5efd8d91c72eed6351bd63b4689b0fcb0ed0f Reviewed-on: https://go-review.googlesource.com/c/go/+/343883 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Than McIntosh --- src/testing/match.go | 108 ++++++++++++++++++++++++++++++-------- src/testing/match_test.go | 29 +++++++--- 2 files changed, 110 insertions(+), 27 deletions(-) diff --git a/src/testing/match.go b/src/testing/match.go index b18c6e7f38..d97e415765 100644 --- a/src/testing/match.go +++ b/src/testing/match.go @@ -14,34 +14,45 @@ import ( // matcher sanitizes, uniques, and filters names of subtests and subbenchmarks. type matcher struct { - filter []string + filter filterMatch matchFunc func(pat, str string) (bool, error) mu sync.Mutex subNames map[string]int64 } +type filterMatch interface { + // matches checks the name against the receiver's pattern strings using the + // given match function. + matches(name []string, matchString func(pat, str string) (bool, error)) (ok, partial bool) + + // verify checks that the receiver's pattern strings are valid filters by + // calling the given match function. + verify(name string, matchString func(pat, str string) (bool, error)) error +} + +// simpleMatch matches a test name if all of the pattern strings match in +// sequence. +type simpleMatch []string + +// alternationMatch matches a test name if one of the alternations match. +type alternationMatch []filterMatch + // TODO: fix test_main to avoid race and improve caching, also allowing to // eliminate this Mutex. var matchMutex sync.Mutex func newMatcher(matchString func(pat, str string) (bool, error), patterns, name string) *matcher { - var filter []string + var impl filterMatch if patterns != "" { - filter = splitRegexp(patterns) - for i, s := range filter { - filter[i] = rewrite(s) - } - // Verify filters before doing any processing. - for i, s := range filter { - if _, err := matchString(s, "non-empty"); err != nil { - fmt.Fprintf(os.Stderr, "testing: invalid regexp for element %d of %s (%q): %s\n", i, name, s, err) - os.Exit(1) - } + impl = splitRegexp(patterns) + if err := impl.verify(name, matchString); err != nil { + fmt.Fprintf(os.Stderr, "testing: invalid regexp for %s\n", err) + os.Exit(1) } } return &matcher{ - filter: filter, + filter: impl, matchFunc: matchString, subNames: map[string]int64{}, } @@ -60,22 +71,63 @@ func (m *matcher) fullName(c *common, subname string) (name string, ok, partial matchMutex.Lock() defer matchMutex.Unlock() + if m.filter == nil { + return name, true, false + } + // We check the full array of paths each time to allow for the case that // a pattern contains a '/'. elem := strings.Split(name, "/") - for i, s := range elem { - if i >= len(m.filter) { + ok, partial = m.filter.matches(elem, m.matchFunc) + return name, ok, partial +} + +func (m simpleMatch) matches(name []string, matchString func(pat, str string) (bool, error)) (ok, partial bool) { + for i, s := range name { + if i >= len(m) { break } - if ok, _ := m.matchFunc(m.filter[i], s); !ok { - return name, false, false + if ok, _ := matchString(m[i], s); !ok { + return false, false + } + } + return true, len(name) < len(m) +} + +func (m simpleMatch) verify(name string, matchString func(pat, str string) (bool, error)) error { + for i, s := range m { + m[i] = rewrite(s) + } + // Verify filters before doing any processing. + for i, s := range m { + if _, err := matchString(s, "non-empty"); err != nil { + return fmt.Errorf("element %d of %s (%q): %s", i, name, s, err) + } + } + return nil +} + +func (m alternationMatch) matches(name []string, matchString func(pat, str string) (bool, error)) (ok, partial bool) { + for _, m := range m { + if ok, partial = m.matches(name, matchString); ok { + return ok, partial + } + } + return false, false +} + +func (m alternationMatch) verify(name string, matchString func(pat, str string) (bool, error)) error { + for i, m := range m { + if err := m.verify(name, matchString); err != nil { + return fmt.Errorf("alternation %d of %s", i, err) } } - return name, true, len(elem) < len(m.filter) + return nil } -func splitRegexp(s string) []string { - a := make([]string, 0, strings.Count(s, "/")) +func splitRegexp(s string) filterMatch { + a := make(simpleMatch, 0, strings.Count(s, "/")) + b := make(alternationMatch, 0, strings.Count(s, "|")) cs := 0 cp := 0 for i := 0; i < len(s); { @@ -103,10 +155,24 @@ func splitRegexp(s string) []string { i = 0 continue } + case '|': + if cs == 0 && cp == 0 { + a = append(a, s[:i]) + s = s[i+1:] + i = 0 + b = append(b, a) + a = make(simpleMatch, 0, len(a)) + continue + } } i++ } - return append(a, s) + + a = append(a, s) + if len(b) == 0 { + return a + } + return append(b, a) } // unique creates a unique name for the given parent and subname by affixing it diff --git a/src/testing/match_test.go b/src/testing/match_test.go index 8c09dc660f..9ceadbb31d 100644 --- a/src/testing/match_test.go +++ b/src/testing/match_test.go @@ -5,8 +5,10 @@ package testing import ( + "fmt" "reflect" "regexp" + "strings" "unicode" ) @@ -25,10 +27,11 @@ func TestIsSpace(t *T) { } func TestSplitRegexp(t *T) { - res := func(s ...string) []string { return s } + res := func(s ...string) filterMatch { return simpleMatch(s) } + alt := func(m ...filterMatch) filterMatch { return alternationMatch(m) } testCases := []struct { pattern string - result []string + result filterMatch }{ // Correct patterns // If a regexp pattern is correct, all split regexps need to be correct @@ -49,6 +52,8 @@ func TestSplitRegexp(t *T) { {`([)/][(])`, res(`([)/][(])`)}, {"[(]/[)]", res("[(]", "[)]")}, + {"A/B|C/D", alt(res("A", "B"), res("C", "D"))}, + // Faulty patterns // Errors in original should produce at least one faulty regexp in results. {")/", res(")/")}, @@ -71,10 +76,8 @@ func TestSplitRegexp(t *T) { // needs to have an error as well. if _, err := regexp.Compile(tc.pattern); err != nil { ok := true - for _, re := range a { - if _, err := regexp.Compile(re); err != nil { - ok = false - } + if err := a.verify("", regexp.MatchString); err != nil { + ok = false } if ok { t.Errorf("%s: expected error in any of %q", tc.pattern, a) @@ -113,6 +116,10 @@ func TestMatcher(t *T) { {"TestFoo/", "TestBar", "x", false, false}, {"TestFoo/bar/baz", "TestBar", "x/bar/baz", false, false}, + {"A/B|C/D", "TestA", "B", true, false}, + {"A/B|C/D", "TestC", "D", true, false}, + {"A/B|C/D", "TestA", "C", false, false}, + // subtests only {"", "TestFoo", "x", true, false}, {"/", "TestFoo", "x", true, false}, @@ -184,3 +191,13 @@ func TestNaming(t *T) { } } } + +// GoString returns a string that is more readable than the default, which makes +// it easier to read test errors. +func (m alternationMatch) GoString() string { + s := make([]string, len(m)) + for i, m := range m { + s[i] = fmt.Sprintf("%#v", m) + } + return fmt.Sprintf("(%s)", strings.Join(s, " | ")) +} -- GitLab From 5a4b9f9494bad1091f2f9cb777aed54293b647d3 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Wed, 14 Jul 2021 13:21:11 -0700 Subject: [PATCH 1107/2500] time: reference -tags=timetzdata in testing panic This will spare anyone who hits it having to search for the workaround. Change-Id: Iff0d449212f2675ac78e30ae5ffc8efb4d924088 Reviewed-on: https://go-review.googlesource.com/c/go/+/334611 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/time/internal_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/time/internal_test.go b/src/time/internal_test.go index 87a4208b05..2c75e449d3 100644 --- a/src/time/internal_test.go +++ b/src/time/internal_test.go @@ -12,7 +12,7 @@ func init() { func initTestingZone() { z, err := loadLocation("America/Los_Angeles", zoneSources[len(zoneSources)-1:]) if err != nil { - panic("cannot load America/Los_Angeles for testing: " + err.Error()) + panic("cannot load America/Los_Angeles for testing: " + err.Error() + "; you may want to use -tags=timetzdata") } z.name = "Local" localLoc = *z -- GitLab From 1bf2cd1291b5287045d3efd975870897fa03ac1f Mon Sep 17 00:00:00 2001 From: Florin Papa Date: Thu, 6 May 2021 17:17:59 -0700 Subject: [PATCH 1108/2500] debug/elf: retain original error message when getSymbols fails. The original error is currently discarded, and that makes it difficult to know what failed, in case we want to retry only certain errors. Change-Id: Id7e927ec242464249c4dfa5cda0f264adef3c898 Reviewed-on: https://go-review.googlesource.com/c/go/+/317851 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Than McIntosh --- src/debug/elf/file.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/debug/elf/file.go b/src/debug/elf/file.go index b25d8209e3..e265796ddc 100644 --- a/src/debug/elf/file.go +++ b/src/debug/elf/file.go @@ -494,7 +494,7 @@ func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) { data, err := symtabSection.Data() if err != nil { - return nil, nil, errors.New("cannot load symbol section") + return nil, nil, fmt.Errorf("cannot load symbol section: %w", err) } symtab := bytes.NewReader(data) if symtab.Len()%Sym32Size != 0 { @@ -503,7 +503,7 @@ func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) { strdata, err := f.stringTable(symtabSection.Link) if err != nil { - return nil, nil, errors.New("cannot load string table section") + return nil, nil, fmt.Errorf("cannot load string table section: %w", err) } // The first entry is all zeros. @@ -537,7 +537,7 @@ func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, error) { data, err := symtabSection.Data() if err != nil { - return nil, nil, errors.New("cannot load symbol section") + return nil, nil, fmt.Errorf("cannot load symbol section: %w", err) } symtab := bytes.NewReader(data) if symtab.Len()%Sym64Size != 0 { @@ -546,7 +546,7 @@ func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, error) { strdata, err := f.stringTable(symtabSection.Link) if err != nil { - return nil, nil, errors.New("cannot load string table section") + return nil, nil, fmt.Errorf("cannot load string table section: %w", err) } // The first entry is all zeros. -- GitLab From cf2fe5d6f12f075f265ba067869fc5f0e3b23ff0 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Mon, 2 Aug 2021 00:56:25 +0800 Subject: [PATCH 1109/2500] doc/asm: fix HTML markup Change-Id: I33bde4835d3b83fafd55beea483f6236c4c62840 Reviewed-on: https://go-review.googlesource.com/c/go/+/338990 Reviewed-by: Ian Lance Taylor Trust: Than McIntosh --- doc/asm.html | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/asm.html b/doc/asm.html index 51f85eb948..f7787a4076 100644 --- a/doc/asm.html +++ b/doc/asm.html @@ -125,8 +125,8 @@ it is a distinct program, so there are some differences. One is in constant evaluation. Constant expressions in the assembler are parsed using Go's operator precedence, not the C-like precedence of the original. -Thus 3&1<<2 is 4, not 0—it parses as (3&1)<<2 -not 3&(1<<2). +Thus 3&1<<2 is 4, not 0—it parses as (3&1)<<2 +not 3&(1<<2). Also, constants are always evaluated as 64-bit unsigned integers. Thus -2 is not the integer value minus two, but the unsigned 64-bit integer with the same bit pattern. @@ -914,8 +914,6 @@ This assembler is used by GOARCH values ppc64 and ppc64le. Reference: Go PPC64 Assembly Instructions Reference Manual

- -

IBM z/Architecture, a.k.a. s390x

-- GitLab From 363f2f3df99f3edd15609cc6bea2a2c6f423ce2c Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Fri, 10 Sep 2021 13:16:32 -0400 Subject: [PATCH 1110/2500] [dev.fuzz] testing: allow -fuzzminimizetime to be 0 Fixes golang/go#48321 Change-Id: I1547379eb7a703f7f3c4594d27833eb3587796a0 Reviewed-on: https://go-review.googlesource.com/c/go/+/349089 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- .../go/testdata/script/test_fuzz_minimize.txt | 26 +++++++++++++++++++ src/testing/benchmark.go | 9 ++++--- src/testing/fuzz.go | 2 +- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize.txt b/src/cmd/go/testdata/script/test_fuzz_minimize.txt index 002aca009b..ea1ee76474 100644 --- a/src/cmd/go/testdata/script/test_fuzz_minimize.txt +++ b/src/cmd/go/testdata/script/test_fuzz_minimize.txt @@ -6,6 +6,32 @@ # We clean the fuzz cache during this test. Don't clean the user's cache. env GOCACHE=$WORK/gocache +# Test that fuzzminimizetime can be zero seconds +! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x -fuzzminimizetime=0s minimizer_test.go +! stdout '^ok' +stdout 'contains a non-zero byte' +stdout FAIL + +# Test that fuzzminimizetime can be zero times +! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x -fuzzminimizetime=0x minimizer_test.go +! stdout '^ok' +stdout 'contains a non-zero byte' +stdout FAIL + +# Test that fuzzminimizetime cannot be negative seconds +! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x -fuzzminimizetime=-1ms minimizer_test.go +! stdout '^ok' +! stdout 'contains a non-zero byte' +stdout 'invalid duration' +stdout FAIL + +# Test that fuzzminimizetime cannot be negative times +! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x -fuzzminimizetime=-1x minimizer_test.go +! stdout '^ok' +! stdout 'contains a non-zero byte' +stdout 'invalid count' +stdout FAIL + # Test that minimization is working for recoverable errors. ! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x minimizer_test.go ! stdout '^ok' diff --git a/src/testing/benchmark.go b/src/testing/benchmark.go index c8571a5f5a..30fa106dd4 100644 --- a/src/testing/benchmark.go +++ b/src/testing/benchmark.go @@ -36,8 +36,9 @@ var ( ) type durationOrCountFlag struct { - d time.Duration - n int + d time.Duration + n int + allowZero bool } func (f *durationOrCountFlag) String() string { @@ -50,14 +51,14 @@ func (f *durationOrCountFlag) String() string { func (f *durationOrCountFlag) Set(s string) error { if strings.HasSuffix(s, "x") { n, err := strconv.ParseInt(s[:len(s)-1], 10, 0) - if err != nil || n <= 0 { + if err != nil || n < 0 || (!f.allowZero && n == 0) { return fmt.Errorf("invalid count") } *f = durationOrCountFlag{n: int(n)} return nil } d, err := time.ParseDuration(s) - if err != nil || d <= 0 { + if err != nil || d < 0 || (!f.allowZero && d == 0) { return fmt.Errorf("invalid duration") } *f = durationOrCountFlag{d: d} diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 975aa87eab..d94ec35dc7 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -28,7 +28,7 @@ func initFuzzFlags() { var ( matchFuzz *string fuzzDuration durationOrCountFlag - minimizeDuration = durationOrCountFlag{d: 60 * time.Second} + minimizeDuration = durationOrCountFlag{d: 60 * time.Second, allowZero: true} fuzzCacheDir *string isFuzzWorker *bool -- GitLab From d106089fa6aa69cc1b547c68ca19d84f28062c71 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Fri, 10 Sep 2021 11:05:29 -0400 Subject: [PATCH 1111/2500] [dev.fuzz] internal/fuzz: write a newline to the end of a corpus file If someone manually adds/alters a corpus file to add extra spacing or remove the final newline, the file can still be decoded. However, this change ensures that the fuzzing engine correctly writes the final newline. Fixes golang/go#48130 Change-Id: Ib5556d4a6e4e0bfd9bc2edab357b7c25bedfd176 Reviewed-on: https://go-review.googlesource.com/c/go/+/349055 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- .../go/testdata/script/test_fuzz_minimize.txt | 3 +++ src/internal/fuzz/encoding.go | 12 +++++------ src/internal/fuzz/encoding_test.go | 20 +++++++++++++------ 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize.txt b/src/cmd/go/testdata/script/test_fuzz_minimize.txt index ea1ee76474..dac11231ef 100644 --- a/src/cmd/go/testdata/script/test_fuzz_minimize.txt +++ b/src/cmd/go/testdata/script/test_fuzz_minimize.txt @@ -163,6 +163,9 @@ func main() { os.Exit(1) } + // Trim the newline at the end of the file + got = bytes.TrimSpace(got) + // Make sure that there were exactly 100 bytes written to the corpus entry prefix := []byte("[]byte(") i := bytes.Index(got, prefix) diff --git a/src/internal/fuzz/encoding.go b/src/internal/fuzz/encoding.go index c2f7d22b75..d3f24c3e6c 100644 --- a/src/internal/fuzz/encoding.go +++ b/src/internal/fuzz/encoding.go @@ -22,21 +22,21 @@ func marshalCorpusFile(vals ...interface{}) []byte { if len(vals) == 0 { panic("must have at least one value to marshal") } - b := bytes.NewBuffer([]byte(encVersion1)) + b := bytes.NewBuffer([]byte(encVersion1 + "\n")) // TODO(katiehockman): keep uint8 and int32 encoding where applicable, // instead of changing to byte and rune respectively. for _, val := range vals { switch t := val.(type) { case int, int8, int16, int64, uint, uint16, uint32, uint64, float32, float64, bool: - fmt.Fprintf(b, "\n%T(%v)", t, t) + fmt.Fprintf(b, "%T(%v)\n", t, t) case string: - fmt.Fprintf(b, "\nstring(%q)", t) + fmt.Fprintf(b, "string(%q)\n", t) case rune: // int32 - fmt.Fprintf(b, "\nrune(%q)", t) + fmt.Fprintf(b, "rune(%q)\n", t) case byte: // uint8 - fmt.Fprintf(b, "\nbyte(%q)", t) + fmt.Fprintf(b, "byte(%q)\n", t) case []byte: // []uint8 - fmt.Fprintf(b, "\n[]byte(%q)", t) + fmt.Fprintf(b, "[]byte(%q)\n", t) default: panic(fmt.Sprintf("unsupported type: %T", t)) } diff --git a/src/internal/fuzz/encoding_test.go b/src/internal/fuzz/encoding_test.go index 314f82a995..b429d429c6 100644 --- a/src/internal/fuzz/encoding_test.go +++ b/src/internal/fuzz/encoding_test.go @@ -66,16 +66,21 @@ byte('☃')`, }, { in: `go test fuzz v1 +string("has final newline") +`, + ok: true, // has final newline + }, + { + in: `go test fuzz v1 string("extra") []byte("spacing") `, - ok: true, + ok: true, // extra spaces in the final newline }, { in: `go test fuzz v1 float64(0) -float32(0) -`, +float32(0)`, ok: true, // will be an integer literal since there is no decimal }, { @@ -114,9 +119,12 @@ float32(2.5)`, if err != nil { t.Fatalf("marshal unexpected error: %v", err) } - want := strings.TrimSpace(test.in) - if want != string(newB) { - t.Errorf("values changed after unmarshal then marshal\nbefore: %q\nafter: %q", want, newB) + if newB[len(newB)-1] != '\n' { + t.Error("didn't write final newline to corpus file") + } + before, after := strings.TrimSpace(test.in), strings.TrimSpace(string(newB)) + if before != after { + t.Errorf("values changed after unmarshal then marshal\nbefore: %q\nafter: %q", before, after) } }) } -- GitLab From 17f62c0ac3de14c3dbff77b706f86dfb7dc820c7 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Fri, 10 Sep 2021 15:25:30 -0400 Subject: [PATCH 1112/2500] [dev.fuzz] internal/fuzz: fix bug for -fuzzminimizetime of zero Updates golang/go#48321 Change-Id: Ib35388f17580f1244a6eae4e5879f8329b6b44ce Reviewed-on: https://go-review.googlesource.com/c/go/+/349090 Trust: Katie Hockman Run-TryBot: Katie Hockman Reviewed-by: Jay Conrod --- .../go/testdata/script/test_fuzz_minimize.txt | 42 +++++++++++++------ src/internal/fuzz/fuzz.go | 32 ++++++++------ 2 files changed, 49 insertions(+), 25 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize.txt b/src/cmd/go/testdata/script/test_fuzz_minimize.txt index dac11231ef..c180890a9b 100644 --- a/src/cmd/go/testdata/script/test_fuzz_minimize.txt +++ b/src/cmd/go/testdata/script/test_fuzz_minimize.txt @@ -6,18 +6,6 @@ # We clean the fuzz cache during this test. Don't clean the user's cache. env GOCACHE=$WORK/gocache -# Test that fuzzminimizetime can be zero seconds -! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x -fuzzminimizetime=0s minimizer_test.go -! stdout '^ok' -stdout 'contains a non-zero byte' -stdout FAIL - -# Test that fuzzminimizetime can be zero times -! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x -fuzzminimizetime=0x minimizer_test.go -! stdout '^ok' -stdout 'contains a non-zero byte' -stdout FAIL - # Test that fuzzminimizetime cannot be negative seconds ! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x -fuzzminimizetime=-1ms minimizer_test.go ! stdout '^ok' @@ -32,6 +20,20 @@ stdout FAIL stdout 'invalid count' stdout FAIL +# Test that fuzzminimizetime can be zero seconds, and minimization is disabled +! go test -fuzz=FuzzMinimizeZeroDurationSet -run=FuzzMinimizeZeroDurationSet -fuzztime=10000x -fuzzminimizetime=0s minimizer_test.go +! stdout '^ok' +! stdout 'found a crash, minimizing...' +stdout 'there was an Error' +stdout FAIL + +# Test that fuzzminimizetime can be zero times, and minimization is disabled +! go test -fuzz=FuzzMinimizeZeroLimitSet -run=FuzzMinimizeZeroLimitSet -fuzztime=10000x -fuzzminimizetime=0x minimizer_test.go +! stdout '^ok' +! stdout 'found a crash, minimizing...' +stdout 'there was an Error' +stdout FAIL + # Test that minimization is working for recoverable errors. ! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x minimizer_test.go ! stdout '^ok' @@ -87,6 +89,22 @@ import ( "testing" ) +func FuzzMinimizeZeroDurationSet(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + if len(b) > 5 { + t.Errorf("there was an Error") + } + }) +} + +func FuzzMinimizeZeroLimitSet(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + if len(b) > 5 { + t.Errorf("there was an Error") + } + }) +} + func FuzzMinimizerRecoverable(f *testing.F) { f.Add(make([]byte, 100)) f.Fuzz(func(t *testing.T, b []byte) { diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 6c07da2dbe..c19ea35f23 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -40,13 +40,16 @@ type CoordinateFuzzingOpts struct { Limit int64 // MinimizeTimeout is the amount of wall clock time to spend minimizing - // after discovering a crasher. If zero, there will be no time limit. + // after discovering a crasher. If zero, there will be no time limit. If + // MinimizeTimeout and MinimizeLimit are both zero, then minimization will + // be disabled. MinimizeTimeout time.Duration // MinimizeLimit is the maximum number of calls to the fuzz function to be - // made while minimizing after finding a crash. If zero, there will be - // no limit. Calls to the fuzz function made when minimizing also count - // toward Limit. + // made while minimizing after finding a crash. If zero, there will be no + // limit. Calls to the fuzz function made when minimizing also count toward + // Limit. If MinimizeTimeout and MinimizeLimit are both zero, then + // minimization will be disabled. MinimizeLimit int64 // parallel is the number of worker processes to run in parallel. If zero, @@ -552,9 +555,10 @@ type coordinator struct { // generated values that workers reported as interesting. corpus corpus - // typesAreMinimizable is true if one or more of the types of fuzz function's - // parameters can be minimized. - typesAreMinimizable bool + // minimizationAllowed is true if one or more of the types of fuzz + // function's parameters can be minimized, and either the limit or duration + // for minimization is non-zero. + minimizationAllowed bool // inputQueue is a queue of inputs that workers should try fuzzing. This is // initially populated from the seed corpus and cached inputs. More inputs @@ -604,10 +608,12 @@ func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { resultC: make(chan fuzzResult), corpus: corpus, } - for _, t := range opts.Types { - if isMinimizable(t) { - c.typesAreMinimizable = true - break + if opts.MinimizeLimit > 0 || opts.MinimizeTimeout > 0 { + for _, t := range opts.Types { + if isMinimizable(t) { + c.minimizationAllowed = true + break + } } } @@ -736,7 +742,7 @@ func (c *coordinator) queueForMinimization(result fuzzResult, keepCoverage []byt // peekMinimizeInput returns the next input that should be sent to workers for // minimization. func (c *coordinator) peekMinimizeInput() (fuzzMinimizeInput, bool) { - if c.opts.Limit > 0 && c.count+c.countWaiting >= c.opts.Limit { + if !c.canMinimize() { // Already making the maximum number of calls to the fuzz function. // Don't send more inputs right now. return fuzzMinimizeInput{}, false @@ -810,7 +816,7 @@ func (c *coordinator) updateCoverage(newCoverage []byte) int { // canMinimize returns whether the coordinator should attempt to find smaller // inputs that reproduce a crash or new coverage. func (c *coordinator) canMinimize() bool { - return c.typesAreMinimizable && + return c.minimizationAllowed && (c.opts.Limit == 0 || c.count+c.countWaiting < c.opts.Limit) } -- GitLab From c8dfa306babb91e88f8ba25329b3ef8aa11944e1 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Fri, 10 Sep 2021 10:45:47 -0700 Subject: [PATCH 1113/2500] [dev.fuzz] testing: F.Setenv plus various fixes and revisions I spent some time looking through all the changes we've made to testing and cmd/go/... on the dev.fuzz branch. CL 348469 shows those differences. This CL fixes comments, TODOs, and simplifies code in a few places. It also implements F.Setenv. Change-Id: I6fd7ef5fbd0bb6055e38d56cb42bddcf6f4ffdaf Reviewed-on: https://go-review.googlesource.com/c/go/+/349109 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/cmd/go/internal/cfg/cfg.go | 2 +- .../go/testdata/script/test_fuzz_setenv.txt | 45 ++++++ src/testing/fuzz.go | 150 ++++++++++-------- src/testing/testing.go | 51 +++--- 4 files changed, 160 insertions(+), 88 deletions(-) create mode 100644 src/cmd/go/testdata/script/test_fuzz_setenv.txt diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go index 7b6c429f42..ac2c70fa60 100644 --- a/src/cmd/go/internal/cfg/cfg.go +++ b/src/cmd/go/internal/cfg/cfg.go @@ -61,7 +61,7 @@ var ( func defaultContext() build.Context { ctxt := build.Default - // TODO(b/187972950): remove this tag before merging to master. + // TODO(#47037): remove this tag before merging to master. ctxt.BuildTags = []string{"gofuzzbeta"} ctxt.JoinPath = filepath.Join // back door to say "do not use go command" diff --git a/src/cmd/go/testdata/script/test_fuzz_setenv.txt b/src/cmd/go/testdata/script/test_fuzz_setenv.txt new file mode 100644 index 0000000000..9738697a91 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_setenv.txt @@ -0,0 +1,45 @@ +[short] skip +[!darwin] [!linux] [!windows] skip + +go test -fuzz=FuzzA -fuzztime=100x fuzz_setenv_test.go + +-- fuzz_setenv_test.go -- +package fuzz + +import ( + "flag" + "os" + "testing" +) + +func FuzzA(f *testing.F) { + if s := os.Getenv("TEST_FUZZ_SETENV_A"); isWorker() && s == "" { + f.Fatal("environment variable not set") + } else if !isWorker() && s != "" { + f.Fatal("environment variable already set") + } + f.Setenv("TEST_FUZZ_SETENV_A", "A") + if os.Getenv("TEST_FUZZ_SETENV_A") == "" { + f.Fatal("Setenv did not set environment variable") + } + f.Fuzz(func(*testing.T, []byte) {}) +} + +func FuzzB(f *testing.F) { + if os.Getenv("TEST_FUZZ_SETENV_A") != "" { + f.Fatal("environment variable not cleared after FuzzA") + } + f.Skip() +} + +func isWorker() bool { + f := flag.Lookup("test.fuzzworker") + if f == nil { + return false + } + get, ok := f.Value.(flag.Getter) + if !ok { + return false + } + return get.Get() == interface{}(true) +} diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index d94ec35dc7..65c3437ed4 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -49,22 +49,35 @@ type InternalFuzzTarget struct { Fn func(f *F) } -// F is a type passed to fuzz targets for fuzz testing. +// F is a type passed to fuzz targets. +// +// A fuzz target may add seed corpus entries using F.Add or by storing files in +// the testdata/fuzz/ directory. The fuzz target must then +// call F.Fuzz once to provide a fuzz function. See the testing package +// documentation for an example, and see the F.Fuzz and F.Add method +// documentation for details. type F struct { common fuzzContext *fuzzContext testContext *testContext - inFuzzFn bool // set to true when fuzz function is running - corpus []corpusEntry // corpus is the in-memory corpus - result FuzzResult // result is the result of running the fuzz target - fuzzCalled bool + + // inFuzzFn is true when the fuzz function is running. Most F methods cannot + // be called when inFuzzFn is true. + inFuzzFn bool + + // corpus is a set of seed corpus entries, added with F.Add and loaded + // from testdata. + corpus []corpusEntry + + result FuzzResult + fuzzCalled bool } var _ TB = (*F)(nil) // corpusEntry is an alias to the same type as internal/fuzz.CorpusEntry. // We use a type alias because we don't want to export this type, and we can't -// importing internal/fuzz from testing. +// import internal/fuzz from testing. type corpusEntry = struct { Parent string Name string @@ -73,9 +86,9 @@ type corpusEntry = struct { Generation int } -// Cleanup registers a function to be called when the test and all its -// subtests complete. Cleanup functions will be called in last added, -// first called order. +// Cleanup registers a function to be called after the fuzz function has been +// called on all seed corpus entries, and after fuzzing completes (if enabled). +// Cleanup functions will be called in last added, first called order. func (f *F) Cleanup(fn func()) { if f.inFuzzFn { panic("testing: f.Cleanup was called inside the f.Fuzz function, use t.Cleanup instead") @@ -114,9 +127,9 @@ func (f *F) Fail() { // FailNow marks the function as having failed and stops its execution // by calling runtime.Goexit (which then runs all deferred calls in the // current goroutine). -// Execution will continue at the next test or benchmark. +// Execution will continue at the next test, benchmark, or fuzz function. // FailNow must be called from the goroutine running the -// test or benchmark function, not from other goroutines +// fuzz target, not from other goroutines // created during the test. Calling FailNow does not stop // those other goroutines. func (f *F) FailNow() { @@ -173,9 +186,18 @@ func (f *F) Helper() { } } -// Setenv is not supported since fuzzing runs in parallel. +// Setenv calls os.Setenv(key, value) and uses Cleanup to restore the +// environment variable to its original value after the test. +// +// When fuzzing is enabled, the fuzzing engine spawns worker processes running +// the test binary. Each worker process inherits the environment of the parent +// process, including environment variables set with F.Setenv. func (f *F) Setenv(key, value string) { - panic("testing: f.Setenv is not supported") + if f.inFuzzFn { + panic("testing: f.Setenv was called inside the f.Fuzz function, use t.Setenv instead") + } + f.common.Helper() + f.common.Setenv(key, value) } // Skip is equivalent to Log followed by SkipNow. @@ -305,26 +327,27 @@ func (f *F) Fuzz(ff interface{}) { types = append(types, t) } - // Only load the corpus if we need it - if f.fuzzContext.runFuzzWorker == nil { - // Check the corpus provided by f.Add + // Load the testdata seed corpus. Check types of entries in the testdata + // corpus and entries declared with F.Add. + // + // Don't load the seed corpus if this is a worker process; we won't use it. + if f.fuzzContext.mode != fuzzWorker { for _, c := range f.corpus { - if err := f.fuzzContext.checkCorpus(c.Values, types); err != nil { - // TODO: Is there a way to save which line number is associated - // with the f.Add call that failed? + if err := f.fuzzContext.deps.CheckCorpus(c.Values, types); err != nil { + // TODO(#48302): Report the source location of the F.Add call. f.Fatal(err) } } // Load seed corpus - c, err := f.fuzzContext.readCorpus(filepath.Join(corpusDir, f.name), types) + c, err := f.fuzzContext.deps.ReadCorpus(filepath.Join(corpusDir, f.name), types) if err != nil { f.Fatal(err) } - // If this is the coordinator process, zero the values, since we don't need to hold - // onto them. - if f.fuzzContext.coordinateFuzzing != nil { + // If this is the coordinator process, zero the values, since we don't need + // to hold onto them. + if f.fuzzContext.mode == fuzzCoordinator { for i := range c { c[i].Values = nil } @@ -336,8 +359,6 @@ func (f *F) Fuzz(ff interface{}) { // run calls fn on a given input, as a subtest with its own T. // run is analogous to T.Run. The test filtering and cleanup works similarly. // fn is called in its own goroutine. - // - // TODO(jayconrod,katiehockman): dedupe testdata corpus with entries from f.Add run := func(e corpusEntry) error { if e.Values == nil { // Every code path should have already unmarshaled Data into Values. @@ -372,7 +393,8 @@ func (f *F) Fuzz(ff interface{}) { } t.w = indenter{&t.common} if t.chatty != nil { - t.chatty.Updatef(t.name, "=== RUN %s\n", t.name) + // TODO(#48132): adjust this to work with test2json. + t.chatty.Updatef(t.name, "=== RUN %s\n", t.name) } f.inFuzzFn = true go tRunner(t, func(t *T) { @@ -384,8 +406,8 @@ func (f *F) Fuzz(ff interface{}) { // make sure it is called right before the tRunner function exits, // regardless of whether it was executed cleanly, panicked, or if the // fuzzFn called t.Fatal. - defer f.fuzzContext.snapshotCoverage() - f.fuzzContext.resetCoverage() + defer f.fuzzContext.deps.SnapshotCoverage() + f.fuzzContext.deps.ResetCoverage() fn.Call(args) }) <-t.signal @@ -396,14 +418,14 @@ func (f *F) Fuzz(ff interface{}) { return nil } - switch { - case f.fuzzContext.coordinateFuzzing != nil: + switch f.fuzzContext.mode { + case fuzzCoordinator: // Fuzzing is enabled, and this is the test process started by 'go test'. // Act as the coordinator process, and coordinate workers to perform the // actual fuzzing. corpusTargetDir := filepath.Join(corpusDir, f.name) cacheTargetDir := filepath.Join(*fuzzCacheDir, f.name) - err := f.fuzzContext.coordinateFuzzing( + err := f.fuzzContext.deps.CoordinateFuzzing( fuzzDuration.d, int64(fuzzDuration.n), minimizeDuration.d, @@ -420,16 +442,16 @@ func (f *F) Fuzz(ff interface{}) { if crashErr, ok := err.(fuzzCrashError); ok { crashName := crashErr.CrashName() fmt.Fprintf(f.w, "Crash written to %s\n", filepath.Join(corpusDir, f.name, crashName)) - fmt.Fprintf(f.w, "To re-run:\ngo test %s -run=%s/%s\n", f.fuzzContext.importPath(), f.name, crashName) + fmt.Fprintf(f.w, "To re-run:\ngo test %s -run=%s/%s\n", f.fuzzContext.deps.ImportPath(), f.name, crashName) } } // TODO(jayconrod,katiehockman): Aggregate statistics across workers // and add to FuzzResult (ie. time taken, num iterations) - case f.fuzzContext.runFuzzWorker != nil: + case fuzzWorker: // Fuzzing is enabled, and this is a worker process. Follow instructions // from the coordinator. - if err := f.fuzzContext.runFuzzWorker(run); err != nil { + if err := f.fuzzContext.deps.RunFuzzWorker(run); err != nil { // Internal errors are marked with f.Fail; user code may call this too, before F.Fuzz. // The worker will exit with fuzzWorkerExitCode, indicating this is a failure // (and 'go test' should exit non-zero) but a crasher should not be recorded. @@ -503,17 +525,20 @@ type fuzzCrashError interface { CrashName() string } -// fuzzContext holds all fields that are common to all fuzz targets. +// fuzzContext holds fields common to all fuzz targets. type fuzzContext struct { - importPath func() string - coordinateFuzzing func(time.Duration, int64, time.Duration, int64, int, []corpusEntry, []reflect.Type, string, string) error - runFuzzWorker func(func(corpusEntry) error) error - readCorpus func(string, []reflect.Type) ([]corpusEntry, error) - checkCorpus func(vals []interface{}, types []reflect.Type) error - resetCoverage func() - snapshotCoverage func() + deps testDeps + mode fuzzMode } +type fuzzMode uint8 + +const ( + seedCorpusOnly fuzzMode = iota + fuzzCoordinator + fuzzWorker +) + // runFuzzTargets runs the fuzz targets matching the pattern for -run. This will // only run the f.Fuzz function for each seed corpus without using the fuzzing // engine to generate or mutate inputs. @@ -525,13 +550,7 @@ func runFuzzTargets(deps testDeps, fuzzTargets []InternalFuzzTarget, deadline ti m := newMatcher(deps.MatchString, *match, "-test.run") tctx := newTestContext(*parallel, m) tctx.deadline = deadline - fctx := &fuzzContext{ - importPath: deps.ImportPath, - readCorpus: deps.ReadCorpus, - checkCorpus: deps.CheckCorpus, - resetCoverage: deps.ResetCoverage, - snapshotCoverage: deps.SnapshotCoverage, - } + fctx := &fuzzContext{deps: deps, mode: seedCorpusOnly} root := common{w: os.Stdout} // gather output in one place if Verbose() { root.chatty = newChattyPrinter(root.w) @@ -558,7 +577,8 @@ func runFuzzTargets(deps testDeps, fuzzTargets []InternalFuzzTarget, deadline ti } f.w = indenter{&f.common} if f.chatty != nil { - f.chatty.Updatef(f.name, "=== RUN %s\n", f.name) + // TODO(#48132): adjust this to work with test2json. + f.chatty.Updatef(f.name, "=== RUN %s\n", f.name) } go fRunner(f, ft.Fn) @@ -583,18 +603,14 @@ func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran bool, matc m := newMatcher(deps.MatchString, *matchFuzz, "-test.fuzz") tctx := newTestContext(1, m) fctx := &fuzzContext{ - importPath: deps.ImportPath, - readCorpus: deps.ReadCorpus, - checkCorpus: deps.CheckCorpus, - resetCoverage: deps.ResetCoverage, - snapshotCoverage: deps.SnapshotCoverage, + deps: deps, } root := common{w: os.Stdout} if *isFuzzWorker { root.w = io.Discard - fctx.runFuzzWorker = deps.RunFuzzWorker + fctx.mode = fuzzWorker } else { - fctx.coordinateFuzzing = deps.CoordinateFuzzing + fctx.mode = fuzzCoordinator } if Verbose() && !*isFuzzWorker { root.chatty = newChattyPrinter(root.w) @@ -628,6 +644,7 @@ func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran bool, matc } f.w = indenter{&f.common} if f.chatty != nil { + // TODO(#48132): adjust this to work with test2json. f.chatty.Updatef(f.name, "=== FUZZ %s\n", f.name) } go fRunner(f, target.Fn) @@ -637,9 +654,9 @@ func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran bool, matc // fRunner wraps a call to a fuzz target and ensures that cleanup functions are // called and status flags are set. fRunner should be called in its own -// goroutine. To wait for its completion, receive f.signal. +// goroutine. To wait for its completion, receive from f.signal. // -// fRunner is analogous with tRunner, which wraps subtests started with T.Run. +// fRunner is analogous to tRunner, which wraps subtests started with T.Run. // Tests and fuzz targets work a little differently, so for now, these functions // aren't consolidated. In particular, because there are no F.Run and F.Parallel // methods, i.e., no fuzz sub-targets or parallel fuzz targets, a few @@ -651,11 +668,11 @@ func fRunner(f *F, fn func(*F)) { // t.signal, indicating the fuzz target is done. defer func() { // Detect whether the fuzz target panicked or called runtime.Goexit without - // calling F.Fuzz, F.Fail, or F.Skip. If it did, panic (possibly replacing - // a nil panic value). Nothing should recover after fRunner unwinds, - // so this should crash the process with a stack. Unfortunately, recovering - // here adds stack frames, but the location of the original panic should - // still be clear. + // calling F.Fuzz, F.Fail, or F.Skip. If it did, panic (possibly replacing a + // nil panic value). Nothing should recover after fRunner unwinds, so this + // should crash the process and print stack. Unfortunately, recovering here + // adds stack frames, but the location of the original panic should still be + // clear. if f.Failed() { atomic.AddUint32(&numFailed, 1) } @@ -708,8 +725,9 @@ func fRunner(f *F, fn func(*F)) { f.duration += time.Since(f.start) if len(f.sub) > 0 { - // Run parallel inputs. - // Release the parallel subtests. + // Unblock inputs that called T.Parallel while running the seed corpus. + // T.Parallel has no effect while fuzzing, so this only affects fuzz + // targets run as normal tests. close(f.barrier) // Wait for the subtests to complete. for _, sub := range f.sub { diff --git a/src/testing/testing.go b/src/testing/testing.go index be21d643fd..5e66a0610b 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -143,8 +143,11 @@ // https://golang.org/cmd/go/#hdr-Testing_flags. // // For a description of fuzzing, see golang.org/s/draft-fuzzing-design. +// TODO(#48255): write and link to documentation that will be helpful to users +// who are unfamiliar with fuzzing. // // A sample fuzz target looks like this: +// // func FuzzBytesCmp(f *testing.F) { // f.Fuzz(func(t *testing.T, a, b []byte) { // if bytes.HasPrefix(a, b) && !bytes.Contains(a, b) { @@ -582,8 +585,6 @@ func (c *common) frameSkip(skip int) runtime.Frame { // and inserts the final newline if needed and indentation spaces for formatting. // This function must be called with c.mu held. func (c *common) decorate(s string, skip int) string { - // TODO(jayconrod,katiehockman): Consider refactoring the logging logic. - // If more helper PCs have been added since we last did the conversion if c.helperNames == nil { c.helperNames = make(map[string]struct{}) for pc := range c.helperPCs { @@ -663,11 +664,8 @@ func (c *common) flushToParent(testName, format string, args ...interface{}) { // isFuzzing returns whether the current context, or any of the parent contexts, // are a fuzzing target func (c *common) isFuzzing() bool { - if c.fuzzing { - return true - } - for parent := c.parent; parent != nil; parent = parent.parent { - if parent.fuzzing { + for com := c; com != nil; com = com.parent { + if com.fuzzing { return true } } @@ -1228,10 +1226,25 @@ func tRunner(t *T, fn func(t *T)) { t.Errorf("race detected during execution of test") } - // If the test panicked, print any test output before dying. + // Check if the test panicked or Goexited inappropriately. + // + // If this happens in a normal test, print output but continue panicking. + // tRunner is called in its own goroutine, so this terminates the process. + // + // If this happens while fuzzing, recover from the panic and treat it like a + // normal failure. It's important that the process keeps running in order to + // find short inputs that cause panics. err := recover() signal := true + if err != nil && t.isFuzzing() { + t.Errorf("panic: %s\n%s\n", err, string(debug.Stack())) + t.mu.Lock() + t.finished = true + t.mu.Unlock() + err = nil + } + t.mu.RLock() finished := t.finished t.mu.RUnlock() @@ -1249,15 +1262,15 @@ func tRunner(t *T, fn func(t *T)) { } } } + // Use a deferred call to ensure that we report that the test is // complete even if a cleanup function calls t.FailNow. See issue 41355. didPanic := false defer func() { - isFuzzing := t.common.isFuzzing() - if didPanic && !isFuzzing { + if didPanic { return } - if err != nil && !isFuzzing { + if err != nil { panic(err) } // Only report that the test is complete if it doesn't panic, @@ -1283,12 +1296,6 @@ func tRunner(t *T, fn func(t *T)) { } } didPanic = true - if t.common.fuzzing { - for root := &t.common; root.parent != nil; root = root.parent { - fmt.Fprintf(root.parent.w, "panic: %s\n%s\n", err, string(debug.Stack())) - } - return - } panic(err) } if err != nil { @@ -1325,7 +1332,7 @@ func tRunner(t *T, fn func(t *T)) { t.report() // Report after all subtests have finished. // Do not lock t.done to allow race detector to detect race in case - // the user does not appropriately synchronizes a goroutine. + // the user does not appropriately synchronize a goroutine. t.done = true if t.parent != nil && atomic.LoadInt32(&t.hasSub) == 0 { t.setRan() @@ -1571,7 +1578,7 @@ func (m *M) Run() (code int) { return } if *matchFuzz != "" && *fuzzCacheDir == "" { - fmt.Fprintln(os.Stderr, "testing: internal error: -test.fuzzcachedir must be set if -test.fuzz is set") + fmt.Fprintln(os.Stderr, "testing: -test.fuzzcachedir must be set if -test.fuzz is set") flag.Usage() m.exitCode = 2 return @@ -1606,9 +1613,11 @@ func (m *M) Run() (code int) { m.before() defer m.after() + + // Run tests, examples, and benchmarks unless this is a fuzz worker process. + // Workers start after this is done by their parent process, and they should + // not repeat this work. if !*isFuzzWorker { - // The fuzzing coordinator will already run all tests, examples, - // and benchmarks. Don't make the workers do redundant work. deadline := m.startAlarm() haveExamples = len(m.examples) > 0 testRan, testOk := runTests(m.deps.MatchString, m.tests, deadline) -- GitLab From a50225a0dc1e83449a76b80b2fbed77af516483c Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Wed, 4 Aug 2021 00:57:07 -0700 Subject: [PATCH 1114/2500] bufio: make Reader.Reset and Writer.Reset work on the zero value For batch allocation reasons, it would be useful to nest a bufio.Reader or bufio.Writer in a struct as a value, rather than a pointer. When the Reset method is called, have it use the default buffer size if the buffer is nil. Fixes #45374 Change-Id: I80df18a13575431428a42ed150a1579de1282637 Reviewed-on: https://go-review.googlesource.com/c/go/+/345570 Trust: Joe Tsai Run-TryBot: Joe Tsai TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/bufio/bufio.go | 10 ++++++++++ src/bufio/bufio_test.go | 25 ++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/bufio/bufio.go b/src/bufio/bufio.go index ec928e7ad6..391ecf46b3 100644 --- a/src/bufio/bufio.go +++ b/src/bufio/bufio.go @@ -68,7 +68,12 @@ func (b *Reader) Size() int { return len(b.buf) } // Reset discards any buffered data, resets all state, and switches // the buffered reader to read from r. +// Calling Reset on the zero value of Reader initializes the internal buffer +// to the default size. func (b *Reader) Reset(r io.Reader) { + if b.buf == nil { + b.buf = make([]byte, defaultBufSize) + } b.reset(b.buf, r) } @@ -590,7 +595,12 @@ func (b *Writer) Size() int { return len(b.buf) } // Reset discards any unflushed buffered data, clears any error, and // resets b to write its output to w. +// Calling Reset on the zero value of Writer initializes the internal buffer +// to the default size. func (b *Writer) Reset(w io.Writer) { + if b.buf == nil { + b.buf = make([]byte, defaultBufSize) + } b.err = nil b.n = 0 b.wr = w diff --git a/src/bufio/bufio_test.go b/src/bufio/bufio_test.go index ebcc711db9..eb5136c9ea 100644 --- a/src/bufio/bufio_test.go +++ b/src/bufio/bufio_test.go @@ -1312,6 +1312,7 @@ func TestReaderReset(t *testing.T) { if string(buf) != "foo" { t.Errorf("buf = %q; want foo", buf) } + r.Reset(strings.NewReader("bar bar")) all, err := io.ReadAll(r) if err != nil { @@ -1320,12 +1321,23 @@ func TestReaderReset(t *testing.T) { if string(all) != "bar bar" { t.Errorf("ReadAll = %q; want bar bar", all) } + + *r = Reader{} // zero out the Reader + r.Reset(strings.NewReader("bar bar")) + all, err = io.ReadAll(r) + if err != nil { + t.Fatal(err) + } + if string(all) != "bar bar" { + t.Errorf("ReadAll = %q; want bar bar", all) + } } func TestWriterReset(t *testing.T) { - var buf1, buf2 bytes.Buffer + var buf1, buf2, buf3 bytes.Buffer w := NewWriter(&buf1) w.WriteString("foo") + w.Reset(&buf2) // and not flushed w.WriteString("bar") w.Flush() @@ -1335,6 +1347,17 @@ func TestWriterReset(t *testing.T) { if buf2.String() != "bar" { t.Errorf("buf2 = %q; want bar", buf2.String()) } + + *w = Writer{} // zero out the Writer + w.Reset(&buf3) // and not flushed + w.WriteString("bar") + w.Flush() + if buf1.String() != "" { + t.Errorf("buf1 = %q; want empty", buf1.String()) + } + if buf3.String() != "bar" { + t.Errorf("buf3 = %q; want bar", buf3.String()) + } } func TestReaderDiscard(t *testing.T) { -- GitLab From 23832ba2e2fb396cda1dacf3e8afcb38ec36dcba Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Thu, 26 Aug 2021 19:13:22 -0700 Subject: [PATCH 1115/2500] reflect: optimize for maps with string keys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Over 80% of all Go map types use a string as the key. The Go runtime already has a specialized implementation for such maps in runtime/map_faststr.go. However, the Go reflection implementation has not historically made use of that implementation. This CL plumbs the appropriate logic to be accessible from Go reflection so that it can benefit as well. name old time/op new time/op delta Map/StringKeys/MapIndex-4 4.65us ± 5% 2.95us ± 3% -36.50% (p=0.016 n=4+5) Map/StringKeys/SetMapIndex-4 7.47us ± 5% 5.27us ± 2% -29.40% (p=0.008 n=5+5) Map/Uint64Keys/MapIndex-4 3.79us ± 3% 3.75us ± 2% ~ (p=0.548 n=5+5) Map/Uint64Keys/SetMapIndex-4 6.13us ± 3% 6.09us ± 1% ~ (p=0.746 n=5+5) Change-Id: I5495d48948d8caf2d004a03ae1820ab5f8729670 Reviewed-on: https://go-review.googlesource.com/c/go/+/345486 Trust: Joe Tsai Run-TryBot: Joe Tsai TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/reflect/all_test.go | 47 +++++++++++++++++++++++++++++++++++++++++ src/reflect/value.go | 46 ++++++++++++++++++++++++++++++++++------ src/runtime/map.go | 21 ++++++++++++++++++ 3 files changed, 108 insertions(+), 6 deletions(-) diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index 293d036f67..e92f71135c 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -7050,6 +7050,53 @@ func BenchmarkNew(b *testing.B) { }) } +func BenchmarkMap(b *testing.B) { + type V *int + value := ValueOf((V)(nil)) + stringKeys := []string{} + mapOfStrings := map[string]V{} + uint64Keys := []uint64{} + mapOfUint64s := map[uint64]V{} + for i := 0; i < 100; i++ { + stringKey := fmt.Sprintf("key%d", i) + stringKeys = append(stringKeys, stringKey) + mapOfStrings[stringKey] = nil + + uint64Key := uint64(i) + uint64Keys = append(uint64Keys, uint64Key) + mapOfUint64s[uint64Key] = nil + } + + tests := []struct { + label string + m, keys, value Value + }{ + {"StringKeys", ValueOf(mapOfStrings), ValueOf(stringKeys), value}, + {"Uint64Keys", ValueOf(mapOfUint64s), ValueOf(uint64Keys), value}, + } + + for _, tt := range tests { + b.Run(tt.label, func(b *testing.B) { + b.Run("MapIndex", func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + for j := tt.keys.Len() - 1; j >= 0; j-- { + tt.m.MapIndex(tt.keys.Index(j)) + } + } + }) + b.Run("SetMapIndex", func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + for j := tt.keys.Len() - 1; j >= 0; j-- { + tt.m.SetMapIndex(tt.keys.Index(j), tt.value) + } + } + }) + }) + } +} + func TestSwapper(t *testing.T) { type I int var a, b, c I diff --git a/src/reflect/value.go b/src/reflect/value.go index bf29d1bb3a..6e9aaabe8a 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -1515,15 +1515,21 @@ func (v Value) MapIndex(key Value) Value { // considered unexported. This is consistent with the // behavior for structs, which allow read but not write // of unexported fields. - key = key.assignTo("reflect.Value.MapIndex", tt.key, nil) - var k unsafe.Pointer - if key.flag&flagIndir != 0 { - k = key.ptr + var e unsafe.Pointer + if key.kind() == String && tt.key.Kind() == String { + k := *(*string)(key.ptr) + e = mapaccess_faststr(v.typ, v.pointer(), k) } else { - k = unsafe.Pointer(&key.ptr) + key = key.assignTo("reflect.Value.MapIndex", tt.key, nil) + var k unsafe.Pointer + if key.flag&flagIndir != 0 { + k = key.ptr + } else { + k = unsafe.Pointer(&key.ptr) + } + e = mapaccess(v.typ, v.pointer(), k) } - e := mapaccess(v.typ, v.pointer(), k) if e == nil { return Value{} } @@ -2121,6 +2127,25 @@ func (v Value) SetMapIndex(key, elem Value) { v.mustBeExported() key.mustBeExported() tt := (*mapType)(unsafe.Pointer(v.typ)) + + if key.kind() == String && tt.key.Kind() == String { + k := *(*string)(key.ptr) + if elem.typ == nil { + mapdelete_faststr(v.typ, v.pointer(), k) + return + } + elem.mustBeExported() + elem = elem.assignTo("reflect.Value.SetMapIndex", tt.elem, nil) + var e unsafe.Pointer + if elem.flag&flagIndir != 0 { + e = elem.ptr + } else { + e = unsafe.Pointer(&elem.ptr) + } + mapassign_faststr(v.typ, v.pointer(), k, e) + return + } + key = key.assignTo("reflect.Value.SetMapIndex", tt.key, nil) var k unsafe.Pointer if key.flag&flagIndir != 0 { @@ -3252,12 +3277,21 @@ func makemap(t *rtype, cap int) (m unsafe.Pointer) //go:noescape func mapaccess(t *rtype, m unsafe.Pointer, key unsafe.Pointer) (val unsafe.Pointer) +//go:noescape +func mapaccess_faststr(t *rtype, m unsafe.Pointer, key string) (val unsafe.Pointer) + //go:noescape func mapassign(t *rtype, m unsafe.Pointer, key, val unsafe.Pointer) +//go:noescape +func mapassign_faststr(t *rtype, m unsafe.Pointer, key string, val unsafe.Pointer) + //go:noescape func mapdelete(t *rtype, m unsafe.Pointer, key unsafe.Pointer) +//go:noescape +func mapdelete_faststr(t *rtype, m unsafe.Pointer, key string) + //go:noescape func mapiterinit(t *rtype, m unsafe.Pointer, it *hiter) diff --git a/src/runtime/map.go b/src/runtime/map.go index 59b803d629..985c297cd4 100644 --- a/src/runtime/map.go +++ b/src/runtime/map.go @@ -1324,17 +1324,38 @@ func reflect_mapaccess(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer { return elem } +//go:linkname reflect_mapaccess_faststr reflect.mapaccess_faststr +func reflect_mapaccess_faststr(t *maptype, h *hmap, key string) unsafe.Pointer { + elem, ok := mapaccess2_faststr(t, h, key) + if !ok { + // reflect wants nil for a missing element + elem = nil + } + return elem +} + //go:linkname reflect_mapassign reflect.mapassign func reflect_mapassign(t *maptype, h *hmap, key unsafe.Pointer, elem unsafe.Pointer) { p := mapassign(t, h, key) typedmemmove(t.elem, p, elem) } +//go:linkname reflect_mapassign_faststr reflect.mapassign_faststr +func reflect_mapassign_faststr(t *maptype, h *hmap, key string, elem unsafe.Pointer) { + p := mapassign_faststr(t, h, key) + typedmemmove(t.elem, p, elem) +} + //go:linkname reflect_mapdelete reflect.mapdelete func reflect_mapdelete(t *maptype, h *hmap, key unsafe.Pointer) { mapdelete(t, h, key) } +//go:linkname reflect_mapdelete_faststr reflect.mapdelete_faststr +func reflect_mapdelete_faststr(t *maptype, h *hmap, key string) { + mapdelete_faststr(t, h, key) +} + //go:linkname reflect_mapiterinit reflect.mapiterinit func reflect_mapiterinit(t *maptype, h *hmap, it *hiter) { mapiterinit(t, h, it) -- GitLab From 0d8a4bfc962a606584be0a76ed708f86b44164c7 Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Wed, 4 Aug 2021 01:22:45 -0700 Subject: [PATCH 1116/2500] bufio: add Writer.AvailableBuffer This adds a new Writer.AvailableBuffer method that returns an empty buffer with a possibly non-empty capacity for use with append-like APIs. The typical usage pattern is something like: b := bw.AvailableBuffer() b = appendValue(b, v) bw.Write(b) It allows logic combining append-like APIs with bufio.Writer to avoid needing to allocate and manage buffers themselves and allows the append-like APIs to directly write into the buffer for a bufio.Writer. Fixes #47527 Change-Id: I9cd169f3f8e8c7cd40818caf3daf1944c826fc66 Reviewed-on: https://go-review.googlesource.com/c/go/+/345569 Trust: Joe Tsai Run-TryBot: Joe Tsai TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/bufio/bufio.go | 8 ++++++++ src/bufio/bufio_test.go | 33 +++++++++++++++++++++++++++++++++ src/bufio/example_test.go | 12 ++++++++++++ 3 files changed, 53 insertions(+) diff --git a/src/bufio/bufio.go b/src/bufio/bufio.go index 391ecf46b3..506b84f6ba 100644 --- a/src/bufio/bufio.go +++ b/src/bufio/bufio.go @@ -633,6 +633,14 @@ func (b *Writer) Flush() error { // Available returns how many bytes are unused in the buffer. func (b *Writer) Available() int { return len(b.buf) - b.n } +// AvailableBuffer returns an empty buffer with b.Available() capacity. +// This buffer is intended to be appended to and +// passed to an immediately succeeding Write call. +// The buffer is only valid until the next write operation on b. +func (b *Writer) AvailableBuffer() []byte { + return b.buf[b.n:][:0] +} + // Buffered returns the number of bytes that have been written into the current buffer. func (b *Writer) Buffered() int { return b.n } diff --git a/src/bufio/bufio_test.go b/src/bufio/bufio_test.go index eb5136c9ea..04a810c206 100644 --- a/src/bufio/bufio_test.go +++ b/src/bufio/bufio_test.go @@ -10,6 +10,8 @@ import ( "errors" "fmt" "io" + "math/rand" + "strconv" "strings" "testing" "testing/iotest" @@ -608,6 +610,37 @@ func TestWriter(t *testing.T) { } } +func TestWriterAppend(t *testing.T) { + got := new(bytes.Buffer) + var want []byte + rn := rand.New(rand.NewSource(0)) + w := NewWriterSize(got, 64) + for i := 0; i < 100; i++ { + // Obtain a buffer to append to. + b := w.AvailableBuffer() + if w.Available() != cap(b) { + t.Fatalf("Available() = %v, want %v", w.Available(), cap(b)) + } + + // While not recommended, it is valid to append to a shifted buffer. + // This forces Write to copy the the input. + if rn.Intn(8) == 0 && cap(b) > 0 { + b = b[1:1:cap(b)] + } + + // Append a random integer of varying width. + n := int64(rn.Intn(1 << rn.Intn(30))) + want = append(strconv.AppendInt(want, n, 10), ' ') + b = append(strconv.AppendInt(b, n, 10), ' ') + w.Write(b) + } + w.Flush() + + if !bytes.Equal(got.Bytes(), want) { + t.Errorf("output mismatch:\ngot %s\nwant %s", got.Bytes(), want) + } +} + // Check that write errors are returned properly. type errorWriterTest struct { diff --git a/src/bufio/example_test.go b/src/bufio/example_test.go index 8885d40549..a864d11012 100644 --- a/src/bufio/example_test.go +++ b/src/bufio/example_test.go @@ -20,6 +20,18 @@ func ExampleWriter() { // Output: Hello, world! } +func ExampleWriter_AvailableBuffer() { + w := bufio.NewWriter(os.Stdout) + for _, i := range []int64{1, 2, 3, 4} { + b := w.AvailableBuffer() + b = strconv.AppendInt(b, i, 10) + b = append(b, ' ') + w.Write(b) + } + w.Flush() + // Output: 1 2 3 4 +} + // The simplest use of a Scanner, to read standard input as a set of lines. func ExampleScanner_lines() { scanner := bufio.NewScanner(os.Stdin) -- GitLab From ad97d204f02c1f9ad0433e9178d6ce0f3fdb1f9f Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Thu, 9 Sep 2021 18:41:30 -0400 Subject: [PATCH 1117/2500] go/types: remove some unnecessary loading/expansion of Named types For Identical an u.nify, only type arguments and pointer identity is needed. Change-Id: Id4018d2a53044fa20fd26d28890f28b37b6d6d70 Reviewed-on: https://go-review.googlesource.com/c/go/+/349409 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/predicates.go | 3 --- src/go/types/unify.go | 3 --- 2 files changed, 6 deletions(-) diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 73d240241e..9aa565b68a 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -302,9 +302,6 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { // Two named types are identical if their type names originate // in the same type declaration. if y, ok := y.(*Named); ok { - x.expand(nil) - y.expand(nil) - xargs := x.TypeArgs().list() yargs := y.TypeArgs().list() diff --git a/src/go/types/unify.go b/src/go/types/unify.go index ed769aafe8..6d10f71a90 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -425,9 +425,6 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { case *Named: if y, ok := y.(*Named); ok { - x.expand(nil) - y.expand(nil) - xargs := x.targs.list() yargs := y.targs.list() -- GitLab From c3b217a0e5f032cadf4595884dad839e169c902c Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Mon, 13 Sep 2021 09:16:39 -0700 Subject: [PATCH 1118/2500] cmd/go: document 'go install cmd@version' ignores vendor directories For #48332 Change-Id: I708eb3e8f3f386f03210b7117d9ab8b0be2125bb Reviewed-on: https://go-review.googlesource.com/c/go/+/349591 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/alldocs.go | 7 +++++-- src/cmd/go/internal/work/build.go | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 425aa831d8..b7e8212795 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -702,14 +702,17 @@ // // - All arguments must refer to packages in the same module at the same version. // +// - Package path arguments must refer to main packages. Pattern arguments +// will only match main packages. +// // - No module is considered the "main" module. If the module containing // packages named on the command line has a go.mod file, it must not contain // directives (replace and exclude) that would cause it to be interpreted // differently than if it were the main module. The module must not require // a higher version of itself. // -// - Package path arguments must refer to main packages. Pattern arguments -// will only match main packages. +// - Vendor directories are not used in any module. (Vendor directories are not +// included in the module zip files downloaded by 'go install'.) // // If the arguments don't have version suffixes, "go install" may run in // module-aware mode or GOPATH mode, depending on the GO111MODULE environment diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go index c51dd398c2..3d7c778a7d 100644 --- a/src/cmd/go/internal/work/build.go +++ b/src/cmd/go/internal/work/build.go @@ -496,14 +496,17 @@ allowed, even if they refer to the same version. - All arguments must refer to packages in the same module at the same version. +- Package path arguments must refer to main packages. Pattern arguments +will only match main packages. + - No module is considered the "main" module. If the module containing packages named on the command line has a go.mod file, it must not contain directives (replace and exclude) that would cause it to be interpreted differently than if it were the main module. The module must not require a higher version of itself. -- Package path arguments must refer to main packages. Pattern arguments -will only match main packages. +- Vendor directories are not used in any module. (Vendor directories are not +included in the module zip files downloaded by 'go install'.) If the arguments don't have version suffixes, "go install" may run in module-aware mode or GOPATH mode, depending on the GO111MODULE environment -- GitLab From bced369a50acf50358f52e5c9c0a30d8bdb707ef Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Thu, 1 Jul 2021 09:27:46 -0400 Subject: [PATCH 1119/2500] cmd/link: minor code cleanup in dwarf gen Minor code cleanup to get rid of a few unused parameters and return values in the linker's dwarf generation code. No functional changes. Change-Id: I1a68ebe0f08d8d32ca7adfdd2fb9db573a4fd5f5 Reviewed-on: https://go-review.googlesource.com/c/go/+/332070 Trust: Than McIntosh Reviewed-by: Cherry Mui Run-TryBot: Than McIntosh TryBot-Result: Go Bot --- src/cmd/link/internal/ld/dwarf.go | 133 ++++++++++++++---------------- 1 file changed, 62 insertions(+), 71 deletions(-) diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go index 70138d37ff..839609339f 100644 --- a/src/cmd/link/internal/ld/dwarf.go +++ b/src/cmd/link/internal/ld/dwarf.go @@ -67,20 +67,6 @@ type dwctxt struct { dwmu *sync.Mutex } -func newdwctxt(linkctxt *Link, forTypeGen bool) dwctxt { - d := dwctxt{ - linkctxt: linkctxt, - ldr: linkctxt.loader, - arch: linkctxt.Arch, - tmap: make(map[string]loader.Sym), - tdmap: make(map[loader.Sym]loader.Sym), - rtmap: make(map[loader.Sym]loader.Sym), - } - d.typeRuntimeEface = d.lookupOrDiag("type.runtime.eface") - d.typeRuntimeIface = d.lookupOrDiag("type.runtime.iface") - return d -} - // dwSym wraps a loader.Sym; this type is meant to obey the interface // rules for dwarf.Sym from the cmd/internal/dwarf package. DwDie and // DwAttr objects contain references to symbols via this type. @@ -249,7 +235,7 @@ var dwtypes dwarf.DWDie // up all attrs in a single large table, then store indices into the // table in the DIE. This would allow us to common up storage for // attributes that are shared by many DIEs (ex: byte size of N). -func newattr(die *dwarf.DWDie, attr uint16, cls int, value int64, data interface{}) *dwarf.DWAttr { +func newattr(die *dwarf.DWDie, attr uint16, cls int, value int64, data interface{}) { a := new(dwarf.DWAttr) a.Link = die.Attr die.Attr = a @@ -257,7 +243,6 @@ func newattr(die *dwarf.DWDie, attr uint16, cls int, value int64, data interface a.Cls = uint8(cls) a.Value = value a.Data = data - return a } // Each DIE (except the root ones) has at least 1 attribute: its @@ -290,7 +275,7 @@ func getattr(die *dwarf.DWDie, attr uint16) *dwarf.DWAttr { // The compiler does create nameless DWARF DIEs (ex: concrete subprogram // instance). // FIXME: it would be more efficient to bulk-allocate DIEs. -func (d *dwctxt) newdie(parent *dwarf.DWDie, abbrev int, name string, version int) *dwarf.DWDie { +func (d *dwctxt) newdie(parent *dwarf.DWDie, abbrev int, name string) *dwarf.DWDie { die := new(dwarf.DWDie) die.Abbrev = abbrev die.Link = parent.Child @@ -298,10 +283,9 @@ func (d *dwctxt) newdie(parent *dwarf.DWDie, abbrev int, name string, version in newattr(die, dwarf.DW_AT_name, dwarf.DW_CLS_STRING, int64(len(name)), name) - // Sanity check: all DIEs created in the linker should have a non-empty - // name and be version zero. - if name == "" || version != 0 { - panic("nameless or version non-zero DWARF DIE") + // Sanity check: all DIEs created in the linker should be named. + if name == "" { + panic("nameless DWARF DIE") } var st sym.SymKind @@ -321,7 +305,7 @@ func (d *dwctxt) newdie(parent *dwarf.DWDie, abbrev int, name string, version in // this also includes loose ends such as STRUCT_FIELD. st = sym.SDWARFTYPE } - ds := d.ldr.LookupOrCreateSym(dwarf.InfoPrefix+name, version) + ds := d.ldr.LookupOrCreateSym(dwarf.InfoPrefix+name, 0) dsu := d.ldr.MakeSymbolUpdater(ds) dsu.SetType(st) d.ldr.SetAttrNotInSymbolTable(ds, true) @@ -397,22 +381,20 @@ func (d *dwctxt) mustFind(name string) loader.Sym { return r } -func (d *dwctxt) adddwarfref(sb *loader.SymbolBuilder, t loader.Sym, size int) int64 { - var result int64 +func (d *dwctxt) adddwarfref(sb *loader.SymbolBuilder, t loader.Sym, size int) { switch size { default: d.linkctxt.Errorf(sb.Sym(), "invalid size %d in adddwarfref\n", size) case d.arch.PtrSize, 4: } - result = sb.AddSymRef(d.arch, t, 0, objabi.R_DWARFSECREF, size) - return result + sb.AddSymRef(d.arch, t, 0, objabi.R_DWARFSECREF, size) } -func (d *dwctxt) newrefattr(die *dwarf.DWDie, attr uint16, ref loader.Sym) *dwarf.DWAttr { +func (d *dwctxt) newrefattr(die *dwarf.DWDie, attr uint16, ref loader.Sym) { if ref == 0 { - return nil + return } - return newattr(die, attr, dwarf.DW_CLS_REFERENCE, 0, dwSym(ref)) + newattr(die, attr, dwarf.DW_CLS_REFERENCE, 0, dwSym(ref)) } func (d *dwctxt) dtolsym(s dwarf.Sym) loader.Sym { @@ -481,7 +463,7 @@ func (d *dwctxt) lookupOrDiag(n string) loader.Sym { return symIdx } -func (d *dwctxt) dotypedef(parent *dwarf.DWDie, gotype loader.Sym, name string, def *dwarf.DWDie) *dwarf.DWDie { +func (d *dwctxt) dotypedef(parent *dwarf.DWDie, name string, def *dwarf.DWDie) *dwarf.DWDie { // Only emit typedefs for real names. if strings.HasPrefix(name, "map[") { return nil @@ -513,7 +495,7 @@ func (d *dwctxt) dotypedef(parent *dwarf.DWDie, gotype loader.Sym, name string, // so that future lookups will find the typedef instead // of the real definition. This hooks the typedef into any // circular definition loops, so that gdb can understand them. - die := d.newdie(parent, dwarf.DW_ABRV_TYPEDECL, name, 0) + die := d.newdie(parent, dwarf.DW_ABRV_TYPEDECL, name) d.newrefattr(die, dwarf.DW_AT_type, tds) @@ -558,7 +540,7 @@ func (d *dwctxt) newtype(gotype loader.Sym) *dwarf.DWDie { var die, typedefdie *dwarf.DWDie switch kind { case objabi.KindBool: - die = d.newdie(&dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0) + die = d.newdie(&dwtypes, dwarf.DW_ABRV_BASETYPE, name) newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_boolean, 0) newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) @@ -567,7 +549,7 @@ func (d *dwctxt) newtype(gotype loader.Sym) *dwarf.DWDie { objabi.KindInt16, objabi.KindInt32, objabi.KindInt64: - die = d.newdie(&dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0) + die = d.newdie(&dwtypes, dwarf.DW_ABRV_BASETYPE, name) newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_signed, 0) newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) @@ -577,29 +559,29 @@ func (d *dwctxt) newtype(gotype loader.Sym) *dwarf.DWDie { objabi.KindUint32, objabi.KindUint64, objabi.KindUintptr: - die = d.newdie(&dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0) + die = d.newdie(&dwtypes, dwarf.DW_ABRV_BASETYPE, name) newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_unsigned, 0) newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) case objabi.KindFloat32, objabi.KindFloat64: - die = d.newdie(&dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0) + die = d.newdie(&dwtypes, dwarf.DW_ABRV_BASETYPE, name) newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_float, 0) newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) case objabi.KindComplex64, objabi.KindComplex128: - die = d.newdie(&dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0) + die = d.newdie(&dwtypes, dwarf.DW_ABRV_BASETYPE, name) newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_complex_float, 0) newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) case objabi.KindArray: - die = d.newdie(&dwtypes, dwarf.DW_ABRV_ARRAYTYPE, name, 0) - typedefdie = d.dotypedef(&dwtypes, gotype, name, die) + die = d.newdie(&dwtypes, dwarf.DW_ABRV_ARRAYTYPE, name) + typedefdie = d.dotypedef(&dwtypes, name, die) newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) s := decodetypeArrayElem(d.ldr, d.arch, gotype) d.newrefattr(die, dwarf.DW_AT_type, d.defgotype(s)) - fld := d.newdie(die, dwarf.DW_ABRV_ARRAYRANGE, "range", 0) + fld := d.newdie(die, dwarf.DW_ABRV_ARRAYRANGE, "range") // use actual length not upper bound; correct for 0-length arrays. newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, decodetypeArrayLen(d.ldr, d.arch, gotype), 0) @@ -607,7 +589,7 @@ func (d *dwctxt) newtype(gotype loader.Sym) *dwarf.DWDie { d.newrefattr(fld, dwarf.DW_AT_type, d.uintptrInfoSym) case objabi.KindChan: - die = d.newdie(&dwtypes, dwarf.DW_ABRV_CHANTYPE, name, 0) + die = d.newdie(&dwtypes, dwarf.DW_ABRV_CHANTYPE, name) s := decodetypeChanElem(d.ldr, d.arch, gotype) d.newrefattr(die, dwarf.DW_AT_go_elem, d.defgotype(s)) // Save elem type for synthesizechantypes. We could synthesize here @@ -615,9 +597,9 @@ func (d *dwctxt) newtype(gotype loader.Sym) *dwarf.DWDie { d.newrefattr(die, dwarf.DW_AT_type, s) case objabi.KindFunc: - die = d.newdie(&dwtypes, dwarf.DW_ABRV_FUNCTYPE, name, 0) + die = d.newdie(&dwtypes, dwarf.DW_ABRV_FUNCTYPE, name) newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) - typedefdie = d.dotypedef(&dwtypes, gotype, name, die) + typedefdie = d.dotypedef(&dwtypes, name, die) data := d.ldr.Data(gotype) // FIXME: add caching or reuse reloc slice. relocs := d.ldr.Relocs(gotype) @@ -625,24 +607,24 @@ func (d *dwctxt) newtype(gotype loader.Sym) *dwarf.DWDie { for i := 0; i < nfields; i++ { s := decodetypeFuncInType(d.ldr, d.arch, gotype, &relocs, i) sn := d.ldr.SymName(s) - fld := d.newdie(die, dwarf.DW_ABRV_FUNCTYPEPARAM, sn[5:], 0) + fld := d.newdie(die, dwarf.DW_ABRV_FUNCTYPEPARAM, sn[5:]) d.newrefattr(fld, dwarf.DW_AT_type, d.defgotype(s)) } if decodetypeFuncDotdotdot(d.arch, data) { - d.newdie(die, dwarf.DW_ABRV_DOTDOTDOT, "...", 0) + d.newdie(die, dwarf.DW_ABRV_DOTDOTDOT, "...") } nfields = decodetypeFuncOutCount(d.arch, data) for i := 0; i < nfields; i++ { s := decodetypeFuncOutType(d.ldr, d.arch, gotype, &relocs, i) sn := d.ldr.SymName(s) - fld := d.newdie(die, dwarf.DW_ABRV_FUNCTYPEPARAM, sn[5:], 0) + fld := d.newdie(die, dwarf.DW_ABRV_FUNCTYPEPARAM, sn[5:]) d.newrefattr(fld, dwarf.DW_AT_type, d.defptrto(d.defgotype(s))) } case objabi.KindInterface: - die = d.newdie(&dwtypes, dwarf.DW_ABRV_IFACETYPE, name, 0) - typedefdie = d.dotypedef(&dwtypes, gotype, name, die) + die = d.newdie(&dwtypes, dwarf.DW_ABRV_IFACETYPE, name) + typedefdie = d.dotypedef(&dwtypes, name, die) data := d.ldr.Data(gotype) nfields := int(decodetypeIfaceMethodCount(d.arch, data)) var s loader.Sym @@ -654,7 +636,7 @@ func (d *dwctxt) newtype(gotype loader.Sym) *dwarf.DWDie { d.newrefattr(die, dwarf.DW_AT_type, d.defgotype(s)) case objabi.KindMap: - die = d.newdie(&dwtypes, dwarf.DW_ABRV_MAPTYPE, name, 0) + die = d.newdie(&dwtypes, dwarf.DW_ABRV_MAPTYPE, name) s := decodetypeMapKey(d.ldr, d.arch, gotype) d.newrefattr(die, dwarf.DW_AT_go_key, d.defgotype(s)) s = decodetypeMapValue(d.ldr, d.arch, gotype) @@ -664,26 +646,26 @@ func (d *dwctxt) newtype(gotype loader.Sym) *dwarf.DWDie { d.newrefattr(die, dwarf.DW_AT_type, gotype) case objabi.KindPtr: - die = d.newdie(&dwtypes, dwarf.DW_ABRV_PTRTYPE, name, 0) - typedefdie = d.dotypedef(&dwtypes, gotype, name, die) + die = d.newdie(&dwtypes, dwarf.DW_ABRV_PTRTYPE, name) + typedefdie = d.dotypedef(&dwtypes, name, die) s := decodetypePtrElem(d.ldr, d.arch, gotype) d.newrefattr(die, dwarf.DW_AT_type, d.defgotype(s)) case objabi.KindSlice: - die = d.newdie(&dwtypes, dwarf.DW_ABRV_SLICETYPE, name, 0) - typedefdie = d.dotypedef(&dwtypes, gotype, name, die) + die = d.newdie(&dwtypes, dwarf.DW_ABRV_SLICETYPE, name) + typedefdie = d.dotypedef(&dwtypes, name, die) newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) s := decodetypeArrayElem(d.ldr, d.arch, gotype) elem := d.defgotype(s) d.newrefattr(die, dwarf.DW_AT_go_elem, elem) case objabi.KindString: - die = d.newdie(&dwtypes, dwarf.DW_ABRV_STRINGTYPE, name, 0) + die = d.newdie(&dwtypes, dwarf.DW_ABRV_STRINGTYPE, name) newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) case objabi.KindStruct: - die = d.newdie(&dwtypes, dwarf.DW_ABRV_STRUCTTYPE, name, 0) - typedefdie = d.dotypedef(&dwtypes, gotype, name, die) + die = d.newdie(&dwtypes, dwarf.DW_ABRV_STRUCTTYPE, name) + typedefdie = d.dotypedef(&dwtypes, name, die) newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0) nfields := decodetypeStructFieldCount(d.ldr, d.arch, gotype) for i := 0; i < nfields; i++ { @@ -693,7 +675,7 @@ func (d *dwctxt) newtype(gotype loader.Sym) *dwarf.DWDie { sn := d.ldr.SymName(s) f = sn[5:] // skip "type." } - fld := d.newdie(die, dwarf.DW_ABRV_STRUCTFIELD, f, 0) + fld := d.newdie(die, dwarf.DW_ABRV_STRUCTFIELD, f) d.newrefattr(fld, dwarf.DW_AT_type, d.defgotype(s)) offsetAnon := decodetypeStructFieldOffsAnon(d.ldr, d.arch, gotype, i) newmemberoffsetattr(fld, int32(offsetAnon>>1)) @@ -703,11 +685,11 @@ func (d *dwctxt) newtype(gotype loader.Sym) *dwarf.DWDie { } case objabi.KindUnsafePointer: - die = d.newdie(&dwtypes, dwarf.DW_ABRV_BARE_PTRTYPE, name, 0) + die = d.newdie(&dwtypes, dwarf.DW_ABRV_BARE_PTRTYPE, name) default: d.linkctxt.Errorf(gotype, "dwarf: definition of unknown kind %d", kind) - die = d.newdie(&dwtypes, dwarf.DW_ABRV_TYPEDECL, name, 0) + die = d.newdie(&dwtypes, dwarf.DW_ABRV_TYPEDECL, name) d.newrefattr(die, dwarf.DW_AT_type, d.mustFind("")) } @@ -754,7 +736,7 @@ func (d *dwctxt) defptrto(dwtype loader.Sym) loader.Sym { return die } - pdie := d.newdie(&dwtypes, dwarf.DW_ABRV_PTRTYPE, ptrname, 0) + pdie := d.newdie(&dwtypes, dwarf.DW_ABRV_PTRTYPE, ptrname) d.newrefattr(pdie, dwarf.DW_AT_type, dwtype) // The DWARF info synthesizes pointer types that don't exist at the @@ -782,7 +764,7 @@ func (d *dwctxt) copychildrenexcept(ctxt *Link, dst *dwarf.DWDie, src *dwarf.DWD if src == except { continue } - c := d.newdie(dst, src.Abbrev, getattr(src, dwarf.DW_AT_name).Data.(string), 0) + c := d.newdie(dst, src.Abbrev, getattr(src, dwarf.DW_AT_name).Data.(string)) for a := src.Attr; a != nil; a = a.Link { newattr(c, a.Atr, int(a.Cls), a.Value, a.Data) } @@ -877,7 +859,7 @@ func (d *dwctxt) mkinternaltype(ctxt *Link, abbrev int, typename, keyname, valna if s != 0 && d.ldr.SymType(s) == sym.SDWARFTYPE { return s } - die := d.newdie(&dwtypes, abbrev, name, 0) + die := d.newdie(&dwtypes, abbrev, name) f(die) return d.dtolsym(die.Sym) } @@ -922,7 +904,7 @@ func (d *dwctxt) synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) { t = d.defptrto(keytype) } d.newrefattr(dwhk, dwarf.DW_AT_type, t) - fld := d.newdie(dwhk, dwarf.DW_ABRV_ARRAYRANGE, "size", 0) + fld := d.newdie(dwhk, dwarf.DW_ABRV_ARRAYRANGE, "size") newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, BucketSize, 0) d.newrefattr(fld, dwarf.DW_AT_type, d.uintptrInfoSym) }) @@ -936,7 +918,7 @@ func (d *dwctxt) synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) { t = d.defptrto(valtype) } d.newrefattr(dwhv, dwarf.DW_AT_type, t) - fld := d.newdie(dwhv, dwarf.DW_ABRV_ARRAYRANGE, "size", 0) + fld := d.newdie(dwhv, dwarf.DW_ABRV_ARRAYRANGE, "size") newattr(fld, dwarf.DW_AT_count, dwarf.DW_CLS_CONSTANT, BucketSize, 0) d.newrefattr(fld, dwarf.DW_AT_type, d.uintptrInfoSym) }) @@ -947,17 +929,17 @@ func (d *dwctxt) synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) { // bucket. "data" will be replaced with keys/values below. d.copychildrenexcept(ctxt, dwhb, bucket, findchild(bucket, "data")) - fld := d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "keys", 0) + fld := d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "keys") d.newrefattr(fld, dwarf.DW_AT_type, dwhks) newmemberoffsetattr(fld, BucketSize) - fld = d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "values", 0) + fld = d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "values") d.newrefattr(fld, dwarf.DW_AT_type, dwhvs) newmemberoffsetattr(fld, BucketSize+BucketSize*int32(keysize)) - fld = d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "overflow", 0) + fld = d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "overflow") d.newrefattr(fld, dwarf.DW_AT_type, d.defptrto(d.dtolsym(dwhb.Sym))) newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize))) if d.arch.RegSize > d.arch.PtrSize { - fld = d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "pad", 0) + fld = d.newdie(dwhb, dwarf.DW_ABRV_STRUCTFIELD, "pad") d.newrefattr(fld, dwarf.DW_AT_type, d.uintptrInfoSym) newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize))+int32(d.arch.PtrSize)) } @@ -1672,7 +1654,7 @@ func dwarfEnabled(ctxt *Link) bool { // newly created builtin type DIE 'typeDie'. func (d *dwctxt) mkBuiltinType(ctxt *Link, abrv int, tname string) *dwarf.DWDie { // create type DIE - die := d.newdie(&dwtypes, abrv, tname, 0) + die := d.newdie(&dwtypes, abrv, tname) // Look up type symbol. gotype := d.lookupOrDiag("type." + tname) @@ -1765,7 +1747,16 @@ func dwarfGenerateDebugInfo(ctxt *Link) { return } - d := newdwctxt(ctxt, true) + d := &dwctxt{ + linkctxt: ctxt, + ldr: ctxt.loader, + arch: ctxt.Arch, + tmap: make(map[string]loader.Sym), + tdmap: make(map[loader.Sym]loader.Sym), + rtmap: make(map[loader.Sym]loader.Sym), + } + d.typeRuntimeEface = d.lookupOrDiag("type.runtime.eface") + d.typeRuntimeIface = d.lookupOrDiag("type.runtime.iface") if ctxt.HeadType == objabi.Haix { // Initial map used to store package size for each DWARF section. @@ -1776,7 +1767,7 @@ func dwarfGenerateDebugInfo(ctxt *Link) { newattr(&dwtypes, dwarf.DW_AT_name, dwarf.DW_CLS_STRING, int64(len("dwtypes")), "dwtypes") // Unspecified type. There are no references to this in the symbol table. - d.newdie(&dwtypes, dwarf.DW_ABRV_NULLTYPE, "", 0) + d.newdie(&dwtypes, dwarf.DW_ABRV_NULLTYPE, "") // Some types that must exist to define other ones (uintptr in particular // is needed for array size) @@ -1841,7 +1832,7 @@ func dwarfGenerateDebugInfo(ctxt *Link) { if len(unit.Textp) == 0 { cuabrv = dwarf.DW_ABRV_COMPUNIT_TEXTLESS } - unit.DWInfo = d.newdie(&dwroot, cuabrv, unit.Lib.Pkg, 0) + unit.DWInfo = d.newdie(&dwroot, cuabrv, unit.Lib.Pkg) newattr(unit.DWInfo, dwarf.DW_AT_language, dwarf.DW_CLS_CONSTANT, int64(dwarf.DW_LANG_Go), 0) // OS X linker requires compilation dir or absolute path in comp unit name to output debug info. compDir := getCompilationDir() -- GitLab From e74e363a6b3e71ec5a49a3aae8c2523abb72faa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6hrmann?= Date: Sat, 28 Aug 2021 17:54:10 +0200 Subject: [PATCH 1120/2500] strings: add Clone function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new strings.Clone function copies the input string without the returned cloned string referencing the input strings memory. goarch: amd64 cpu: Intel(R) Core(TM) i5-1038NG7 CPU @ 2.00GHz name time/op Clone-8 24.2ns ± 2% name alloc/op Clone-8 48.0B ± 0% name allocs/op Clone-8 1.00 ± 0% Update #45038 Fixes #40200 Change-Id: Id9116c21c14328ec3931ef9a67a2e4f30ff301f9 Reviewed-on: https://go-review.googlesource.com/c/go/+/345849 Trust: Martin Möhrmann Run-TryBot: Martin Möhrmann TryBot-Result: Go Bot Reviewed-by: Joe Tsai Reviewed-by: Ian Lance Taylor --- src/strings/clone.go | 23 ++++++++++++++++++++++ src/strings/clone_test.go | 40 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 src/strings/clone.go create mode 100644 src/strings/clone_test.go diff --git a/src/strings/clone.go b/src/strings/clone.go new file mode 100644 index 0000000000..6097c6cc88 --- /dev/null +++ b/src/strings/clone.go @@ -0,0 +1,23 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package strings + +import ( + "unsafe" +) + +// Clone returns a fresh copy of s. +// It guarantees to make a copy of s into a new allocation, +// which can be important when retaining only a small substring +// of a much larger string. Using Clone can help such programs +// use less memory. Of course, since using Clone makes a copy, +// overuse of Clone can make programs use more memory. +// Clone should typically be used only rarely, and only when +// profiling indicates that it is needed. +func Clone(s string) string { + b := make([]byte, len(s)) + copy(b, s) + return *(*string)(unsafe.Pointer(&b)) +} diff --git a/src/strings/clone_test.go b/src/strings/clone_test.go new file mode 100644 index 0000000000..5396771047 --- /dev/null +++ b/src/strings/clone_test.go @@ -0,0 +1,40 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file.ß + +package strings_test + +import ( + "reflect" + "strings" + "testing" + "unsafe" +) + +func TestClone(t *testing.T) { + var cloneTests = []string{ + "", + "short", + strings.Repeat("a", 42), + } + for _, input := range cloneTests { + clone := strings.Clone(input) + if clone != input { + t.Errorf("Clone(%q) = %q; want %q", input, clone, input) + } + + inputHeader := (*reflect.StringHeader)(unsafe.Pointer(&input)) + cloneHeader := (*reflect.StringHeader)(unsafe.Pointer(&clone)) + if inputHeader.Data == cloneHeader.Data { + t.Errorf("Clone(%q) return value should not reference inputs backing memory.", input) + } + } +} + +func BenchmarkClone(b *testing.B) { + var str = strings.Repeat("a", 42) + b.ReportAllocs() + for i := 0; i < b.N; i++ { + stringSink = strings.Clone(str) + } +} -- GitLab From c8a58f29dcb2b4f38ca4fcf4d2a2a80f606c9573 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Wed, 8 Sep 2021 17:28:09 -0400 Subject: [PATCH 1121/2500] cmd/go: add test to check for a potential workspace loading issue This test checks that we load the same graph regardless of the path to the requested module in the workspace. We currently don't. This will be fixed in a future change that redoes workspace mode's usage of the Requirements structure. For #45713 Change-Id: Id02cbb60a38619d840dbf1e70173ce853c0c167a Reviewed-on: https://go-review.googlesource.com/c/go/+/348649 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/testdata/script/work_prune.txt | 104 ++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/cmd/go/testdata/script/work_prune.txt diff --git a/src/cmd/go/testdata/script/work_prune.txt b/src/cmd/go/testdata/script/work_prune.txt new file mode 100644 index 0000000000..7347b312ee --- /dev/null +++ b/src/cmd/go/testdata/script/work_prune.txt @@ -0,0 +1,104 @@ +# This test makes sure workspace mode's handling of the module graph +# is compatible with module pruning. The graph we load from either of +# the workspace modules should be the same, even if their graphs +# don't overlap. +# +# This is the module graph in the test: +# +# example.com/a -> example.com/b v1.0.0 -> example.com/q v1.1.0 +# example.com/p -> example.com/q v1.0.0 +# +# If we didn't load the whole graph and didn't load the dependencies of b +# when loading p, we would end up loading q v1.0.0, rather than v1.1.0, +# which is selected by MVS. +# TODO(#48331): We currently load the wrong version of q. Fix this. + +go list -m -f '{{.Version}}' example.com/q +stdout '^v1.0.0$' # TODO(#48331): This should be 1.1.0. Fix this. + +-- go.work -- +go 1.18 + +directory ( + ./a + ./p +) +-- a/go.mod -- +module example.com/a + +go 1.18 + +require example.com/b v1.0.0 + +replace example.com/b v1.0.0 => ../b +-- a/foo.go -- +package main + +import "example.com/b" + +func main() { + b.B() +} +-- b/go.mod -- +module example.com/b + +go 1.18 + +require example.com/q v1.1.0 + +replace example.com/q v1.0.0 => ../q1_0_0 +replace example.com/q v1.1.0 => ../q1_1_0 +-- b/b.go -- +package b + +func B() { +} +-- b/b_test.go -- +package b + +import "example.com/q" + +func TestB() { + q.PrintVersion +} +-- p/go.mod -- +module example.com/p + +go 1.18 + +require example.com/q v1.0.0 + +replace example.com/q v1.0.0 => ../q1_0_0 +replace example.com/q v1.1.0 => ../q1_1_0 +-- p/main.go -- +package main + +import "example.com/q" + +func main() { + q.PrintVersion() +} +-- q1_0_0/go.mod -- +module example.com/q + +go 1.18 +-- q1_0_0/q.go -- +package q + +import "fmt" + +func PrintVersion() { + fmt.Println("version 1.0.0") +} +-- q1_1_0/go.mod -- +module example.com/q + +go 1.18 +-- q1_1_0/q.go -- +package q + +import "fmt" + +func PrintVersion() { + fmt.Println("version 1.1.0") +} -- GitLab From ac40c9872f6e8ef095dcc6ee556236782eee4f76 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Mon, 13 Sep 2021 09:17:22 -0700 Subject: [PATCH 1122/2500] reflect: fix _faststr optimization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CL 345486 introduced an optimization to reflect's map accesses which is not quite correct. We can't use the optimized code if the value type is >128 bytes. See cmd/compile/internal/walk/walk.go:mapfast Fixes #48357 Change-Id: I8e3c7858693083dd4393a8de48ca5fa47bab66f2 Reviewed-on: https://go-review.googlesource.com/c/go/+/349593 Trust: Keith Randall Trust: Joe Tsai Trust: Josh Bleecher Snyder Trust: Martin Möhrmann Run-TryBot: Keith Randall Run-TryBot: Joe Tsai Reviewed-by: Joe Tsai Reviewed-by: Josh Bleecher Snyder Reviewed-by: Martin Möhrmann TryBot-Result: Go Bot --- src/reflect/value.go | 4 ++-- test/fixedbugs/issue48357.go | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 test/fixedbugs/issue48357.go diff --git a/src/reflect/value.go b/src/reflect/value.go index 6e9aaabe8a..bc48a76ce6 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -1517,7 +1517,7 @@ func (v Value) MapIndex(key Value) Value { // of unexported fields. var e unsafe.Pointer - if key.kind() == String && tt.key.Kind() == String { + if key.kind() == String && tt.key.Kind() == String && tt.elem.size <= maxValSize { k := *(*string)(key.ptr) e = mapaccess_faststr(v.typ, v.pointer(), k) } else { @@ -2128,7 +2128,7 @@ func (v Value) SetMapIndex(key, elem Value) { key.mustBeExported() tt := (*mapType)(unsafe.Pointer(v.typ)) - if key.kind() == String && tt.key.Kind() == String { + if key.kind() == String && tt.key.Kind() == String && tt.elem.size <= maxValSize { k := *(*string)(key.ptr) if elem.typ == nil { mapdelete_faststr(v.typ, v.pointer(), k) diff --git a/test/fixedbugs/issue48357.go b/test/fixedbugs/issue48357.go new file mode 100644 index 0000000000..5b39fc43d4 --- /dev/null +++ b/test/fixedbugs/issue48357.go @@ -0,0 +1,20 @@ +// run + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "reflect" + +type T [129]byte + +func main() { + m := map[string]T{} + v := reflect.ValueOf(m) + v.SetMapIndex(reflect.ValueOf("a"), reflect.ValueOf(T{})) + g = m["a"] +} + +var g T -- GitLab From a0c409cbc82ea9999a03fa0bfe6d9a8953e780e0 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Fri, 7 May 2021 18:39:36 -0700 Subject: [PATCH 1123/2500] reflect: add fast paths for common, simple Kinds to DeepEqual MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Though the normal equality check suffices, it allocates. Handle common, simple kinds without allocating. For some real world types compared with DeepEqual in the Tailscale code base, the impact of these changes: name old time/op new time/op delta HostInfoEqual-8 25.9µs ± 0% 14.4µs ± 0% -44.32% (p=0.008 n=5+5) name old alloc/op new alloc/op delta HostInfoEqual-8 18.8kB ± 0% 12.6kB ± 0% -32.58% (p=0.008 n=5+5) name old allocs/op new allocs/op delta HostInfoEqual-8 548 ± 0% 90 ± 0% -83.58% (p=0.008 n=5+5) For the benchmarks added in this commit: name old time/op new time/op delta DeepEqual/int8-8 40.1ns ± 4% 31.3ns ± 4% -21.79% (p=0.000 n=19+20) DeepEqual/[]int8-8 169ns ± 1% 123ns ± 1% -27.05% (p=0.000 n=17+18) DeepEqual/int16-8 39.9ns ± 2% 30.8ns ± 4% -22.81% (p=0.000 n=17+20) DeepEqual/[]int16-8 172ns ± 0% 122ns ± 1% -28.91% (p=0.000 n=17+18) DeepEqual/int32-8 40.4ns ± 3% 31.1ns ± 4% -23.07% (p=0.000 n=20+20) DeepEqual/[]int32-8 180ns ± 1% 124ns ± 1% -31.06% (p=0.000 n=20+18) DeepEqual/int64-8 40.1ns ± 2% 31.4ns ± 4% -21.82% (p=0.000 n=20+20) DeepEqual/[]int64-8 180ns ± 1% 124ns ± 1% -31.47% (p=0.000 n=16+19) DeepEqual/int-8 40.1ns ± 4% 30.9ns ± 3% -22.88% (p=0.000 n=20+18) DeepEqual/[]int-8 180ns ± 0% 123ns ± 2% -31.59% (p=0.000 n=19+20) DeepEqual/uint8-8 39.8ns ± 3% 31.9ns ± 5% -19.72% (p=0.000 n=20+20) DeepEqual/[]uint8-8 168ns ± 1% 114ns ± 1% -32.48% (p=0.000 n=18+19) DeepEqual/uint16-8 40.3ns ± 4% 31.4ns ± 6% -22.14% (p=0.000 n=20+20) DeepEqual/[]uint16-8 173ns ± 1% 124ns ± 1% -28.20% (p=0.000 n=20+16) DeepEqual/uint32-8 40.1ns ± 3% 30.7ns ± 3% -23.48% (p=0.000 n=20+20) DeepEqual/[]uint32-8 180ns ± 1% 123ns ± 1% -31.56% (p=0.000 n=20+18) DeepEqual/uint64-8 40.0ns ± 4% 31.3ns ± 4% -21.80% (p=0.000 n=19+19) DeepEqual/[]uint64-8 180ns ± 1% 124ns ± 0% -31.45% (p=0.000 n=18+18) DeepEqual/uint-8 39.8ns ± 3% 31.1ns ± 4% -21.95% (p=0.000 n=19+20) DeepEqual/[]uint-8 181ns ± 1% 122ns ± 1% -32.33% (p=0.000 n=17+20) DeepEqual/uintptr-8 40.3ns ± 3% 31.2ns ± 3% -22.66% (p=0.000 n=20+18) DeepEqual/[]uintptr-8 181ns ± 1% 124ns ± 1% -31.46% (p=0.000 n=19+16) DeepEqual/float32-8 40.3ns ± 2% 31.2ns ± 3% -22.52% (p=0.000 n=16+20) DeepEqual/[]float32-8 180ns ± 1% 122ns ± 1% -32.18% (p=0.000 n=17+17) DeepEqual/float64-8 40.6ns ± 3% 30.9ns ± 5% -23.91% (p=0.000 n=19+20) DeepEqual/[]float64-8 182ns ± 2% 121ns ± 1% -33.33% (p=0.000 n=18+20) DeepEqual/complex64-8 43.0ns ±11% 32.1ns ± 5% -25.33% (p=0.000 n=20+18) DeepEqual/[]complex64-8 182ns ± 1% 122ns ± 2% -32.60% (p=0.000 n=18+19) DeepEqual/complex128-8 42.4ns ± 4% 34.2ns ± 3% -19.35% (p=0.000 n=20+19) DeepEqual/[]complex128-8 197ns ± 1% 122ns ± 1% -38.01% (p=0.000 n=19+19) DeepEqual/bool-8 40.3ns ± 3% 32.9ns ± 5% -18.33% (p=0.000 n=20+20) DeepEqual/[]bool-8 169ns ± 1% 124ns ± 1% -26.90% (p=0.000 n=18+19) DeepEqual/string-8 41.4ns ± 3% 33.7ns ± 5% -18.50% (p=0.000 n=19+20) DeepEqual/[]string-8 216ns ± 0% 128ns ± 1% -41.05% (p=0.000 n=19+17) DeepEqual/[]uint8#01-8 507ns ± 1% 112ns ± 2% -77.92% (p=0.000 n=20+20) DeepEqual/[][]uint8-8 613ns ± 1% 210ns ± 1% -65.76% (p=0.000 n=18+19) DeepEqual/[6]uint8-8 228ns ± 1% 162ns ± 1% -29.00% (p=0.000 n=20+19) DeepEqual/[][6]uint8-8 546ns ± 2% 269ns ± 1% -50.72% (p=0.000 n=20+19) name old alloc/op new alloc/op delta DeepEqual/int8-8 0.00B 0.00B ~ (all equal) DeepEqual/[]int8-8 2.00B ± 0% 0.00B -100.00% (p=0.000 n=20+20) DeepEqual/int16-8 0.00B 0.00B ~ (all equal) DeepEqual/[]int16-8 4.00B ± 0% 0.00B -100.00% (p=0.000 n=20+20) DeepEqual/int32-8 0.00B 0.00B ~ (all equal) DeepEqual/[]int32-8 8.00B ± 0% 0.00B -100.00% (p=0.000 n=20+20) DeepEqual/int64-8 0.00B 0.00B ~ (all equal) DeepEqual/[]int64-8 16.0B ± 0% 0.0B -100.00% (p=0.000 n=20+20) DeepEqual/int-8 0.00B 0.00B ~ (all equal) DeepEqual/[]int-8 16.0B ± 0% 0.0B -100.00% (p=0.000 n=20+20) DeepEqual/uint8-8 0.00B 0.00B ~ (all equal) DeepEqual/[]uint8-8 2.00B ± 0% 0.00B -100.00% (p=0.000 n=20+20) DeepEqual/uint16-8 0.00B 0.00B ~ (all equal) DeepEqual/[]uint16-8 4.00B ± 0% 0.00B -100.00% (p=0.000 n=20+20) DeepEqual/uint32-8 0.00B 0.00B ~ (all equal) DeepEqual/[]uint32-8 8.00B ± 0% 0.00B -100.00% (p=0.000 n=20+20) DeepEqual/uint64-8 0.00B 0.00B ~ (all equal) DeepEqual/[]uint64-8 16.0B ± 0% 0.0B -100.00% (p=0.000 n=20+20) DeepEqual/uint-8 0.00B 0.00B ~ (all equal) DeepEqual/[]uint-8 16.0B ± 0% 0.0B -100.00% (p=0.000 n=20+20) DeepEqual/uintptr-8 0.00B 0.00B ~ (all equal) DeepEqual/[]uintptr-8 16.0B ± 0% 0.0B -100.00% (p=0.000 n=20+20) DeepEqual/float32-8 0.00B 0.00B ~ (all equal) DeepEqual/[]float32-8 8.00B ± 0% 0.00B -100.00% (p=0.000 n=20+20) DeepEqual/float64-8 0.00B 0.00B ~ (all equal) DeepEqual/[]float64-8 16.0B ± 0% 0.0B -100.00% (p=0.000 n=20+20) DeepEqual/complex64-8 0.00B 0.00B ~ (all equal) DeepEqual/[]complex64-8 16.0B ± 0% 0.0B -100.00% (p=0.000 n=20+20) DeepEqual/complex128-8 0.00B 0.00B ~ (all equal) DeepEqual/[]complex128-8 32.0B ± 0% 0.0B -100.00% (p=0.000 n=20+20) DeepEqual/bool-8 0.00B 0.00B ~ (all equal) DeepEqual/[]bool-8 2.00B ± 0% 0.00B -100.00% (p=0.000 n=20+20) DeepEqual/string-8 0.00B 0.00B ~ (all equal) DeepEqual/[]string-8 32.0B ± 0% 0.0B -100.00% (p=0.000 n=20+20) DeepEqual/[]uint8#01-8 12.0B ± 0% 0.0B -100.00% (p=0.000 n=20+20) DeepEqual/[][]uint8-8 12.0B ± 0% 0.0B -100.00% (p=0.000 n=20+20) DeepEqual/[6]uint8-8 0.00B 0.00B ~ (all equal) DeepEqual/[][6]uint8-8 12.0B ± 0% 0.0B -100.00% (p=0.000 n=20+20) name old allocs/op new allocs/op delta DeepEqual/int8-8 0.00 0.00 ~ (all equal) DeepEqual/[]int8-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=20+20) DeepEqual/int16-8 0.00 0.00 ~ (all equal) DeepEqual/[]int16-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=20+20) DeepEqual/int32-8 0.00 0.00 ~ (all equal) DeepEqual/[]int32-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=20+20) DeepEqual/int64-8 0.00 0.00 ~ (all equal) DeepEqual/[]int64-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=20+20) DeepEqual/int-8 0.00 0.00 ~ (all equal) DeepEqual/[]int-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=20+20) DeepEqual/uint8-8 0.00 0.00 ~ (all equal) DeepEqual/[]uint8-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=20+20) DeepEqual/uint16-8 0.00 0.00 ~ (all equal) DeepEqual/[]uint16-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=20+20) DeepEqual/uint32-8 0.00 0.00 ~ (all equal) DeepEqual/[]uint32-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=20+20) DeepEqual/uint64-8 0.00 0.00 ~ (all equal) DeepEqual/[]uint64-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=20+20) DeepEqual/uint-8 0.00 0.00 ~ (all equal) DeepEqual/[]uint-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=20+20) DeepEqual/uintptr-8 0.00 0.00 ~ (all equal) DeepEqual/[]uintptr-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=20+20) DeepEqual/float32-8 0.00 0.00 ~ (all equal) DeepEqual/[]float32-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=20+20) DeepEqual/float64-8 0.00 0.00 ~ (all equal) DeepEqual/[]float64-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=20+20) DeepEqual/complex64-8 0.00 0.00 ~ (all equal) DeepEqual/[]complex64-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=20+20) DeepEqual/complex128-8 0.00 0.00 ~ (all equal) DeepEqual/[]complex128-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=20+20) DeepEqual/bool-8 0.00 0.00 ~ (all equal) DeepEqual/[]bool-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=20+20) DeepEqual/string-8 0.00 0.00 ~ (all equal) DeepEqual/[]string-8 2.00 ± 0% 0.00 -100.00% (p=0.000 n=20+20) DeepEqual/[]uint8#01-8 12.0 ± 0% 0.0 -100.00% (p=0.000 n=20+20) DeepEqual/[][]uint8-8 12.0 ± 0% 0.0 -100.00% (p=0.000 n=20+20) DeepEqual/[6]uint8-8 0.00 0.00 ~ (all equal) DeepEqual/[][6]uint8-8 12.0 ± 0% 0.0 -100.00% (p=0.000 n=20+20) Change-Id: Ic21f0e2305f2cf5e6674c81b9ca609120b3006d9 Reviewed-on: https://go-review.googlesource.com/c/go/+/318169 Trust: Josh Bleecher Snyder Trust: Joe Tsai Run-TryBot: Josh Bleecher Snyder Run-TryBot: Joe Tsai TryBot-Result: Go Bot Reviewed-by: Joe Tsai --- src/reflect/all_test.go | 82 ++++++++++++++++++++++++++++++++++++++++ src/reflect/deepequal.go | 21 +++++++++- 2 files changed, 102 insertions(+), 1 deletion(-) diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index e92f71135c..5b147082bb 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -905,6 +905,9 @@ var deepEqualTests = []DeepEqualTest{ {error(nil), error(nil), true}, {map[int]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, true}, {fn1, fn2, true}, + {[]byte{1, 2, 3}, []byte{1, 2, 3}, true}, + {[]MyByte{1, 2, 3}, []MyByte{1, 2, 3}, true}, + {MyBytes{1, 2, 3}, MyBytes{1, 2, 3}, true}, // Inequalities {1, 2, false}, @@ -950,6 +953,9 @@ var deepEqualTests = []DeepEqualTest{ {&[3]interface{}{1, 2, 4}, &[3]interface{}{1, 2, "s"}, false}, {Basic{1, 0.5}, NotBasic{1, 0.5}, false}, {map[uint]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, false}, + {[]byte{1, 2, 3}, []MyByte{1, 2, 3}, false}, + {[]MyByte{1, 2, 3}, MyBytes{1, 2, 3}, false}, + {[]byte{1, 2, 3}, MyBytes{1, 2, 3}, false}, // Possible loops. {&loop1, &loop1, true}, @@ -1049,6 +1055,82 @@ func TestDeepEqualUnexportedMap(t *testing.T) { } } +var deepEqualPerfTests = []struct { + x, y interface{} +}{ + {x: int8(99), y: int8(99)}, + {x: []int8{99}, y: []int8{99}}, + {x: int16(99), y: int16(99)}, + {x: []int16{99}, y: []int16{99}}, + {x: int32(99), y: int32(99)}, + {x: []int32{99}, y: []int32{99}}, + {x: int64(99), y: int64(99)}, + {x: []int64{99}, y: []int64{99}}, + {x: int(999999), y: int(999999)}, + {x: []int{999999}, y: []int{999999}}, + + {x: uint8(99), y: uint8(99)}, + {x: []uint8{99}, y: []uint8{99}}, + {x: uint16(99), y: uint16(99)}, + {x: []uint16{99}, y: []uint16{99}}, + {x: uint32(99), y: uint32(99)}, + {x: []uint32{99}, y: []uint32{99}}, + {x: uint64(99), y: uint64(99)}, + {x: []uint64{99}, y: []uint64{99}}, + {x: uint(999999), y: uint(999999)}, + {x: []uint{999999}, y: []uint{999999}}, + {x: uintptr(999999), y: uintptr(999999)}, + {x: []uintptr{999999}, y: []uintptr{999999}}, + + {x: float32(1.414), y: float32(1.414)}, + {x: []float32{1.414}, y: []float32{1.414}}, + {x: float64(1.414), y: float64(1.414)}, + {x: []float64{1.414}, y: []float64{1.414}}, + + {x: complex64(1.414), y: complex64(1.414)}, + {x: []complex64{1.414}, y: []complex64{1.414}}, + {x: complex128(1.414), y: complex128(1.414)}, + {x: []complex128{1.414}, y: []complex128{1.414}}, + + {x: true, y: true}, + {x: []bool{true}, y: []bool{true}}, + + {x: "abcdef", y: "abcdef"}, + {x: []string{"abcdef"}, y: []string{"abcdef"}}, + + {x: []byte("abcdef"), y: []byte("abcdef")}, + {x: [][]byte{[]byte("abcdef")}, y: [][]byte{[]byte("abcdef")}}, + + {x: [6]byte{'a', 'b', 'c', 'a', 'b', 'c'}, y: [6]byte{'a', 'b', 'c', 'a', 'b', 'c'}}, + {x: [][6]byte{[6]byte{'a', 'b', 'c', 'a', 'b', 'c'}}, y: [][6]byte{[6]byte{'a', 'b', 'c', 'a', 'b', 'c'}}}, +} + +func TestDeepEqualAllocs(t *testing.T) { + for _, tt := range deepEqualPerfTests { + t.Run(ValueOf(tt.x).Type().String(), func(t *testing.T) { + got := testing.AllocsPerRun(100, func() { + if !DeepEqual(tt.x, tt.y) { + t.Errorf("DeepEqual(%v, %v)=false", tt.x, tt.y) + } + }) + if int(got) != 0 { + t.Errorf("DeepEqual(%v, %v) allocated %d times", tt.x, tt.y, int(got)) + } + }) + } +} + +func BenchmarkDeepEqual(b *testing.B) { + for _, bb := range deepEqualPerfTests { + b.Run(ValueOf(bb.x).Type().String(), func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + sink = DeepEqual(bb.x, bb.y) + } + }) + } +} + func check2ndField(x interface{}, offs uintptr, t *testing.T) { s := ValueOf(x) f := s.Type().Field(1) diff --git a/src/reflect/deepequal.go b/src/reflect/deepequal.go index d951d8d999..94174dec04 100644 --- a/src/reflect/deepequal.go +++ b/src/reflect/deepequal.go @@ -6,7 +6,10 @@ package reflect -import "unsafe" +import ( + "internal/bytealg" + "unsafe" +) // During deepValueEqual, must keep track of checks that are // in progress. The comparison algorithm assumes that all @@ -102,6 +105,10 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool) bool { if v1.Pointer() == v2.Pointer() { return true } + // Special case for []byte, which is common. + if v1.Type().Elem().Kind() == Uint8 { + return bytealg.Equal(v1.Bytes(), v2.Bytes()) + } for i := 0; i < v1.Len(); i++ { if !deepValueEqual(v1.Index(i), v2.Index(i), visited) { return false @@ -149,6 +156,18 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool) bool { } // Can't do better than this: return false + case Int, Int8, Int16, Int32, Int64: + return v1.Int() == v2.Int() + case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr: + return v1.Uint() == v2.Uint() + case String: + return v1.String() == v2.String() + case Bool: + return v1.Bool() == v2.Bool() + case Float32, Float64: + return v1.Float() == v2.Float() + case Complex64, Complex128: + return v1.Complex() == v2.Complex() default: // Normal equality suffices return valueInterface(v1, false) == valueInterface(v2, false) -- GitLab From f93a63addbbca69d7817c8993a88511ec31424cd Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 13 Sep 2021 12:49:08 -0700 Subject: [PATCH 1124/2500] reflect: add a floating point section to DeepEqual tests The floating point tests were all added into the Inequalities section, instead of separated into Equalities vs Inequalities. Rather than separate them, add a new floating point section. Change-Id: I3713a5aff5850dcc0caf68a754633d695a03ded9 Reviewed-on: https://go-review.googlesource.com/c/go/+/349612 Trust: Josh Bleecher Snyder Trust: Joe Tsai Run-TryBot: Josh Bleecher Snyder Run-TryBot: Joe Tsai Reviewed-by: Joe Tsai TryBot-Result: Go Bot --- src/reflect/all_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index 5b147082bb..22885c548f 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -928,6 +928,9 @@ var deepEqualTests = []DeepEqualTest{ {fn1, fn3, false}, {fn3, fn3, false}, {[][]int{{1}}, [][]int{{2}}, false}, + {&structWithSelfPtr{p: &structWithSelfPtr{s: "a"}}, &structWithSelfPtr{p: &structWithSelfPtr{s: "b"}}, false}, + + // Fun with floating point. {math.NaN(), math.NaN(), false}, {&[1]float64{math.NaN()}, &[1]float64{math.NaN()}, false}, {&[1]float64{math.NaN()}, self{}, true}, @@ -935,7 +938,6 @@ var deepEqualTests = []DeepEqualTest{ {[]float64{math.NaN()}, self{}, true}, {map[float64]float64{math.NaN(): 1}, map[float64]float64{1: 2}, false}, {map[float64]float64{math.NaN(): 1}, self{}, true}, - {&structWithSelfPtr{p: &structWithSelfPtr{s: "a"}}, &structWithSelfPtr{p: &structWithSelfPtr{s: "b"}}, false}, // Nil vs empty: not the same. {[]int{}, []int(nil), false}, -- GitLab From 81a4fe6fd29a427c613038260ea12c5374cc5894 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 13 Sep 2021 17:26:03 +0200 Subject: [PATCH 1125/2500] cmd/link/internal/ld: re-enable DWARF tests on solaris/illumos It looks like these are fixed on current tip after CL 84655 marked them to be skipped. Fixes #23168 Change-Id: I0020e6da1042f723eb54186ef0fe925df5326230 Reviewed-on: https://go-review.googlesource.com/c/go/+/349250 Trust: Tobias Klauser Run-TryBot: Tobias Klauser Reviewed-by: Cherry Mui Reviewed-by: Than McIntosh TryBot-Result: Go Bot --- src/cmd/link/internal/ld/dwarf_test.go | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/cmd/link/internal/ld/dwarf_test.go b/src/cmd/link/internal/ld/dwarf_test.go index 543dd5caac..0aeaa7565c 100644 --- a/src/cmd/link/internal/ld/dwarf_test.go +++ b/src/cmd/link/internal/ld/dwarf_test.go @@ -614,9 +614,6 @@ func TestInlinedRoutineRecords(t *testing.T) { if runtime.GOOS == "plan9" { t.Skip("skipping on plan9; no DWARF symbol table in executables") } - if runtime.GOOS == "solaris" || runtime.GOOS == "illumos" { - t.Skip("skipping on solaris, illumos, pending resolution of issue #23168") - } t.Parallel() @@ -851,9 +848,6 @@ func TestAbstractOriginSanity(t *testing.T) { if runtime.GOOS == "plan9" { t.Skip("skipping on plan9; no DWARF symbol table in executables") } - if runtime.GOOS == "solaris" || runtime.GOOS == "illumos" { - t.Skip("skipping on solaris, illumos, pending resolution of issue #23168") - } if wd, err := os.Getwd(); err == nil { gopathdir := filepath.Join(wd, "testdata", "httptest") @@ -869,9 +863,6 @@ func TestAbstractOriginSanityIssue25459(t *testing.T) { if runtime.GOOS == "plan9" { t.Skip("skipping on plan9; no DWARF symbol table in executables") } - if runtime.GOOS == "solaris" || runtime.GOOS == "illumos" { - t.Skip("skipping on solaris, illumos, pending resolution of issue #23168") - } if runtime.GOARCH != "amd64" && runtime.GOARCH != "386" { t.Skip("skipping on not-amd64 not-386; location lists not supported") } @@ -890,9 +881,6 @@ func TestAbstractOriginSanityIssue26237(t *testing.T) { if runtime.GOOS == "plan9" { t.Skip("skipping on plan9; no DWARF symbol table in executables") } - if runtime.GOOS == "solaris" || runtime.GOOS == "illumos" { - t.Skip("skipping on solaris, illumos, pending resolution of issue #23168") - } if wd, err := os.Getwd(); err == nil { gopathdir := filepath.Join(wd, "testdata", "issue26237") abstractOriginSanity(t, gopathdir, DefaultOpt) -- GitLab From 960d036f8f7387de9b06fde6601af43ecaa650e6 Mon Sep 17 00:00:00 2001 From: Hossein Zolfi Date: Mon, 13 Sep 2021 19:16:28 +0000 Subject: [PATCH 1126/2500] cmd/go: add missing parenthesis in a call to "PrintVersion" For #45713 Change-Id: I16e548e6c10e58da815d08897f4ba5d71eeb17e4 GitHub-Last-Rev: 4a0c5d0cdaba94e5950effdcb0ef6b736c9556d1 GitHub-Pull-Request: golang/go#48360 Reviewed-on: https://go-review.googlesource.com/c/go/+/349599 Reviewed-by: Bryan C. Mills Trust: Bryan C. Mills Trust: Jay Conrod Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot --- src/cmd/go/testdata/script/work_prune.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/go/testdata/script/work_prune.txt b/src/cmd/go/testdata/script/work_prune.txt index 7347b312ee..f0fb073c4b 100644 --- a/src/cmd/go/testdata/script/work_prune.txt +++ b/src/cmd/go/testdata/script/work_prune.txt @@ -59,7 +59,7 @@ package b import "example.com/q" func TestB() { - q.PrintVersion + q.PrintVersion() } -- p/go.mod -- module example.com/p -- GitLab From 42057e9848d40fc6181cd7a68fd788c652772b8d Mon Sep 17 00:00:00 2001 From: korzhao Date: Sat, 11 Sep 2021 01:14:54 +0800 Subject: [PATCH 1127/2500] cmd/compile: save the note of fields when translating struct Fixes #48317 Change-Id: I756ae6253022870071004332dd8f49169307f7e6 Reviewed-on: https://go-review.googlesource.com/c/go/+/349013 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Reviewed-by: Dan Scales Trust: Dan Scales --- src/cmd/compile/internal/typecheck/subr.go | 1 + test/typeparam/issue48317.go | 38 ++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 test/typeparam/issue48317.go diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 34f20879f1..5323872eaf 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1312,6 +1312,7 @@ func (ts *Tsubster) tstruct(t *types.Type, force bool) *types.Type { // the type param, not the instantiated type). newfields[i] = types.NewField(f.Pos, f.Sym, t2) newfields[i].Embedded = f.Embedded + newfields[i].Note = f.Note if f.IsDDD() { newfields[i].SetIsDDD(true) } diff --git a/test/typeparam/issue48317.go b/test/typeparam/issue48317.go new file mode 100644 index 0000000000..c8f088dc7a --- /dev/null +++ b/test/typeparam/issue48317.go @@ -0,0 +1,38 @@ +// run -gcflags="-G=3" + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "encoding/json" +) + +type A[T any] struct { + F1 string `json:"t1"` + F2 T `json:"t2"` + B B `json:"t3"` +} + +type B struct { + F4 int `json:"t4"` +} + +func a[T any]() { + data := `{"t1":"1","t2":2,"t3":{"t4":4}}` + a1 := A[T]{} + if err := json.Unmarshal([]byte(data), &a1); err != nil { + panic(err) + } + if bytes, err := json.Marshal(&a1); err != nil { + panic(err) + } else if string(bytes) != data { + panic(string(bytes)) + } +} + +func main() { + a[int]() +} -- GitLab From 9a58aa267e3686c86d3e5bf1d14117a2a127838c Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 10 Sep 2021 17:06:43 -0700 Subject: [PATCH 1128/2500] spec: fix prose about terminating statements CL 85215 added prose to provide some minimal intuition for the definition of a "terminating statement". While the original definition was perfectly fine, the added prose was actually incorrect: If the terminating statement is a goto, it might jump to a labeled statement following that goto in the same block (it could be the very next statement), and thus a terminating statement does not in fact "prevent execution of all statements that lexically appear after it in the same block". Rather than explaining the special case for gotos with targets that are lexically following the goto in the same block, this CL opts for a simpler approach. Thanks to @3bodar (Github) for finding this. Fixes #48323. Change-Id: I8031346250341d038938a1ce6a75d3e687d32c37 Reviewed-on: https://go-review.googlesource.com/c/go/+/349172 Trust: Robert Griesemer Trust: Emmanuel Odeke Reviewed-by: Matthew Dempsky Reviewed-by: Emmanuel Odeke Reviewed-by: Rob Pike Reviewed-by: Ian Lance Taylor --- doc/go_spec.html | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index 3e97974d6d..6cc0b796b9 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,6 +1,6 @@ @@ -4561,9 +4561,8 @@ SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecStmt | Assignment | S

Terminating statements

-A terminating statement prevents execution of all statements that lexically -appear after it in the same block. The following statements -are terminating: +A terminating statement interrupts the regular flow of control in +a block. The following statements are terminating:

    -- GitLab From 146e8d4994052ee4a58bec7e2cf37e568ce1e4e5 Mon Sep 17 00:00:00 2001 From: Nevkontakte Date: Mon, 13 Sep 2021 22:40:30 +0000 Subject: [PATCH 1129/2500] reflect: use Value.Len instead of conversion to slice header This change is functionally equivalent, but reduces reliance on unsafe features. This would allow GopherJS to avoid an additional patch to the standard library we'd have to maintain in order to remain compatible with Go 1.17+. Change-Id: I4f113db0c572ec0b81ebfecf5a137145f6c8c41d GitHub-Last-Rev: 94ebb393bac93579b6455555822691c0d69e2d42 GitHub-Pull-Request: golang/go#48346 Reviewed-on: https://go-review.googlesource.com/c/go/+/349469 Reviewed-by: Keith Randall Reviewed-by: Ian Lance Taylor Trust: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot --- src/reflect/value.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/reflect/value.go b/src/reflect/value.go index bc48a76ce6..33b81d7209 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -2940,8 +2940,7 @@ func (v Value) CanConvert(t Type) bool { // from slice to pointer-to-array. if vt.Kind() == Slice && t.Kind() == Ptr && t.Elem().Kind() == Array { n := t.Elem().Len() - h := (*unsafeheader.Slice)(v.ptr) - if n > h.Len { + if n > v.Len() { return false } } @@ -3208,10 +3207,10 @@ func cvtStringRunes(v Value, t Type) Value { // convertOp: []T -> *[N]T func cvtSliceArrayPtr(v Value, t Type) Value { n := t.Elem().Len() - h := (*unsafeheader.Slice)(v.ptr) - if n > h.Len { - panic("reflect: cannot convert slice with length " + itoa.Itoa(h.Len) + " to pointer to array with length " + itoa.Itoa(n)) + if n > v.Len() { + panic("reflect: cannot convert slice with length " + itoa.Itoa(v.Len()) + " to pointer to array with length " + itoa.Itoa(n)) } + h := (*unsafeheader.Slice)(v.ptr) return Value{t.common(), h.Data, v.flag&^(flagIndir|flagAddr|flagKindMask) | flag(Ptr)} } -- GitLab From 71adc658deddc46a30bf690d37716d16cfccced7 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 29 Apr 2021 19:08:54 -0700 Subject: [PATCH 1130/2500] runtime: change time.now to ABIInternal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reduces the number of instructions executed for time.now by nine, by eliminating the wrapper. Somehow BenchmarkNow is 0.2ns slower. On the other hand BenchmarkNowUnixNano is 0.8ns faster. name old time/op new time/op delta AfterFunc-12 66.7µs ± 4% 67.3µs ± 2% ~ (p=0.573 n=20+18) After-12 97.6µs ± 4% 97.4µs ± 4% ~ (p=0.758 n=20+20) Stop-12 66.7µs ±12% 64.8µs ±10% ~ (p=0.072 n=20+20) SimultaneousAfterFunc-12 109µs ± 0% 110µs ± 1% +1.47% (p=0.000 n=17+20) StartStop-12 31.9µs ±15% 32.7µs ±14% ~ (p=0.799 n=20+20) Reset-12 3.67µs ± 2% 3.68µs ± 2% ~ (p=0.132 n=20+20) Sleep-12 132µs ± 2% 133µs ± 2% +0.70% (p=0.035 n=20+19) Ticker-12 32.4µs ± 1% 32.3µs ± 2% ~ (p=0.270 n=20+19) TickerReset-12 3.71µs ± 2% 3.74µs ± 2% +0.89% (p=0.012 n=20+20) TickerResetNaive-12 65.7µs ±10% 67.2µs ±10% ~ (p=0.174 n=20+20) Now-12 29.6ns ± 1% 29.8ns ± 0% +0.78% (p=0.000 n=17+17) NowUnixNano-12 31.1ns ± 1% 30.3ns ± 0% -2.69% (p=0.000 n=19+18) NowUnixMilli-12 30.9ns ± 0% 31.1ns ± 0% +0.90% (p=0.000 n=18+20) NowUnixMicro-12 30.9ns ± 0% 31.1ns ± 1% +0.68% (p=0.000 n=20+18) Format-12 304ns ± 1% 301ns ± 2% -0.81% (p=0.004 n=18+19) FormatNow-12 187ns ± 2% 185ns ± 2% -0.90% (p=0.036 n=20+18) MarshalJSON-12 267ns ± 3% 265ns ± 3% -1.00% (p=0.004 n=18+18) MarshalText-12 267ns ± 2% 265ns ± 3% -0.87% (p=0.038 n=19+20) Parse-12 150ns ± 1% 149ns ± 1% -0.83% (p=0.000 n=18+20) ParseDuration-12 79.6ns ± 0% 80.1ns ± 1% +0.61% (p=0.000 n=20+20) Hour-12 4.42ns ± 1% 4.45ns ± 0% +0.83% (p=0.000 n=20+20) Second-12 4.42ns ± 0% 4.42ns ± 1% ~ (p=0.075 n=18+20) Year-12 11.1ns ± 1% 11.1ns ± 1% ~ (p=0.489 n=20+19) Day-12 14.8ns ± 1% 14.8ns ± 0% ~ (p=0.616 n=20+18) ISOWeek-12 17.2ns ± 1% 17.2ns ± 0% ~ (p=0.179 n=20+19) name old avg-late-ns new avg-late-ns delta ParallelTimerLatency-12 380k ± 4% 379k ± 3% ~ (p=0.879 n=20+19) StaggeredTickerLatency/work-dur=300µs/tickers-per-P=1-12 137k ± 3% 137k ± 2% ~ (p=0.261 n=19+18) StaggeredTickerLatency/work-dur=300µs/tickers-per-P=2-12 106k ±16% 95k ± 8% -9.76% (p=0.003 n=19+20) StaggeredTickerLatency/work-dur=300µs/tickers-per-P=3-12 88.6k ±22% 74.6k ± 3% -15.78% (p=0.000 n=19+20) StaggeredTickerLatency/work-dur=300µs/tickers-per-P=4-12 76.1k ±18% 70.8k ± 5% -7.04% (p=0.020 n=20+20) StaggeredTickerLatency/work-dur=300µs/tickers-per-P=5-12 67.3k ±27% 65.6k ±13% ~ (p=0.211 n=16+18) StaggeredTickerLatency/work-dur=300µs/tickers-per-P=6-12 59.5k ±24% 57.3k ±32% ~ (p=0.607 n=19+20) StaggeredTickerLatency/work-dur=300µs/tickers-per-P=7-12 41.8k ±34% 46.2k ±33% +10.54% (p=0.039 n=17+20) StaggeredTickerLatency/work-dur=300µs/tickers-per-P=8-12 57.5k ±37% 65.6k ±46% ~ (p=0.283 n=17+20) StaggeredTickerLatency/work-dur=300µs/tickers-per-P=9-12 118k ±60% 136k ±59% ~ (p=0.169 n=19+18) StaggeredTickerLatency/work-dur=300µs/tickers-per-P=10-12 3.66M ±236% 2.55M ±36% ~ (p=0.158 n=16+20) StaggeredTickerLatency/work-dur=2ms/tickers-per-P=1-12 81.7k ± 4% 80.7k ± 5% ~ (p=0.107 n=20+19) name old max-late-ns new max-late-ns delta ParallelTimerLatency-12 5.88M ±124% 7.28M ±183% ~ (p=0.640 n=20+20) StaggeredTickerLatency/work-dur=300µs/tickers-per-P=1-12 384k ±17% 371k ±11% ~ (p=0.540 n=17+17) StaggeredTickerLatency/work-dur=300µs/tickers-per-P=2-12 503k ±180% 373k ±19% ~ (p=0.057 n=17+18) StaggeredTickerLatency/work-dur=300µs/tickers-per-P=3-12 519k ±129% 340k ±17% -34.47% (p=0.000 n=18+19) StaggeredTickerLatency/work-dur=300µs/tickers-per-P=4-12 491k ±141% 341k ±26% -30.52% (p=0.015 n=18+17) StaggeredTickerLatency/work-dur=300µs/tickers-per-P=5-12 457k ±123% 405k ±48% ~ (p=0.786 n=17+17) StaggeredTickerLatency/work-dur=300µs/tickers-per-P=6-12 491k ±85% 502k ±74% ~ (p=0.916 n=18+19) StaggeredTickerLatency/work-dur=300µs/tickers-per-P=7-12 572k ±100% 574k ±65% ~ (p=0.858 n=18+17) StaggeredTickerLatency/work-dur=300µs/tickers-per-P=8-12 1.95M ±205% 1.65M ±155% ~ (p=0.641 n=18+19) StaggeredTickerLatency/work-dur=300µs/tickers-per-P=9-12 7.77M ±104% 8.72M ±103% ~ (p=0.512 n=20+20) StaggeredTickerLatency/work-dur=300µs/tickers-per-P=10-12 29.5M ±187% 18.5M ±43% ~ (p=0.186 n=18+20) StaggeredTickerLatency/work-dur=2ms/tickers-per-P=1-12 981k ±14% 1033k ±12% +5.30% (p=0.048 n=20+18) Change-Id: Ie794a932a929b46053a6c3020b67d640b98d2335 Reviewed-on: https://go-review.googlesource.com/c/go/+/315369 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/runtime/time_linux_amd64.s | 37 +++++++++++++++++----------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/runtime/time_linux_amd64.s b/src/runtime/time_linux_amd64.s index c88e92bd0c..67cfdd8fdf 100644 --- a/src/runtime/time_linux_amd64.s +++ b/src/runtime/time_linux_amd64.s @@ -12,14 +12,11 @@ #define SYS_clock_gettime 228 // func time.now() (sec int64, nsec int32, mono int64) -TEXT time·now(SB),NOSPLIT,$16-24 +TEXT time·now(SB),NOSPLIT,$16-24 MOVQ SP, R12 // Save old SP; R12 unchanged by C code. MOVQ g_m(R14), BX // BX unchanged by C code. - // Store CLOCK_REALTIME results directly to return space. - LEAQ sec+0(FP), SI - // Set vdsoPC and vdsoSP for SIGPROF traceback. // Save the old values on stack and restore them on exit, // so this function is reentrant. @@ -28,9 +25,10 @@ TEXT time·now(SB),NOSPLIT,$16-24 MOVQ CX, 0(SP) MOVQ DX, 8(SP) - MOVQ -8(SI), CX // Sets CX to function return address. + LEAQ sec+0(FP), DX + MOVQ -8(DX), CX // Sets CX to function return address. MOVQ CX, m_vdsoPC(BX) - MOVQ SI, m_vdsoSP(BX) + MOVQ DX, m_vdsoSP(BX) CMPQ R14, m_curg(BX) // Only switch if on curg. JNE noswitch @@ -39,10 +37,11 @@ TEXT time·now(SB),NOSPLIT,$16-24 MOVQ (g_sched+gobuf_sp)(DX), SP // Set SP to g0 stack noswitch: - SUBQ $16, SP // Space for monotonic time results + SUBQ $32, SP // Space for two time results ANDQ $~15, SP // Align for C code MOVL $0, DI // CLOCK_REALTIME + LEAQ 16(SP), SI MOVQ runtime·vdsoClockgettimeSym(SB), AX CMPQ AX, $0 JEQ fallback @@ -54,25 +53,27 @@ noswitch: CALL AX ret: - MOVQ 0(SP), AX // sec - MOVQ 8(SP), DX // nsec + MOVQ 16(SP), AX // realtime sec + MOVQ 24(SP), DI // realtime nsec (moved to BX below) + MOVQ 0(SP), CX // monotonic sec + IMULQ $1000000000, CX + MOVQ 8(SP), DX // monotonic nsec MOVQ R12, SP // Restore real SP + // Restore vdsoPC, vdsoSP // We don't worry about being signaled between the two stores. // If we are not in a signal handler, we'll restore vdsoSP to 0, // and no one will care about vdsoPC. If we are in a signal handler, // we cannot receive another signal. - MOVQ 8(SP), CX - MOVQ CX, m_vdsoSP(BX) - MOVQ 0(SP), CX - MOVQ CX, m_vdsoPC(BX) + MOVQ 8(SP), SI + MOVQ SI, m_vdsoSP(BX) + MOVQ 0(SP), SI + MOVQ SI, m_vdsoPC(BX) - // sec is in AX, nsec in DX - // return nsec in AX - IMULQ $1000000000, AX - ADDQ DX, AX - MOVQ AX, mono+16(FP) + // set result registers; AX is already correct + MOVQ DI, BX + ADDQ DX, CX RET fallback: -- GitLab From 4a4221e8187189adcc6463d2d96fe2e8da290132 Mon Sep 17 00:00:00 2001 From: Alexander Melentyev Date: Sat, 11 Sep 2021 06:59:17 +0000 Subject: [PATCH 1131/2500] all: remove some unused code Change-Id: I519b8021fa79dccc5c0ee79134547491116fc4cc GitHub-Last-Rev: 48869f5434c1255d33c3a14714747509235c94df GitHub-Pull-Request: golang/go#48071 Reviewed-on: https://go-review.googlesource.com/c/go/+/346231 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Keith Randall --- src/database/sql/convert_test.go | 3 --- src/time/time.go | 1 - 2 files changed, 4 deletions(-) diff --git a/src/database/sql/convert_test.go b/src/database/sql/convert_test.go index 2668a5ed5e..400da7ea57 100644 --- a/src/database/sql/convert_test.go +++ b/src/database/sql/convert_test.go @@ -51,9 +51,6 @@ var ( scanbytes []byte scanraw RawBytes scanint int - scanint8 int8 - scanint16 int16 - scanint32 int32 scanuint8 uint8 scanuint16 uint16 scanbool bool diff --git a/src/time/time.go b/src/time/time.go index 4ecc3d82dc..1919ebbc2c 100644 --- a/src/time/time.go +++ b/src/time/time.go @@ -425,7 +425,6 @@ const ( internalToUnix int64 = -unixToInternal wallToInternal int64 = (1884*365 + 1884/4 - 1884/100 + 1884/400) * secondsPerDay - internalToWall int64 = -wallToInternal ) // IsZero reports whether t represents the zero time instant, -- GitLab From b8c802b1161528fcf8ba78b1dff5720dd5b4eb9f Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Fri, 10 Sep 2021 07:44:02 +0700 Subject: [PATCH 1132/2500] cmd/compile: prevent importReader reading type parameter twice The importReader always reads type parameter before declaring type stub declaration. Thus, for recursive type, the type parameter is going to be read twice, cause the bound more than once error. To fix this, only read the type parameter after declaring stub obj, thus r.doDecl can see the type was already inserted and terminate the recursive call earlier. Fixes #48280 Change-Id: I272e2f214f739fb8ec71a8628ba297477e1b7755 Reviewed-on: https://go-review.googlesource.com/c/go/+/349009 Trust: Cuong Manh Le Trust: Dan Scales Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/importer/iimport.go | 12 ++++++------ test/typeparam/issue48280.dir/a.go | 11 +++++++++++ test/typeparam/issue48280.dir/main.go | 11 +++++++++++ test/typeparam/issue48280.go | 7 +++++++ 4 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 test/typeparam/issue48280.dir/a.go create mode 100644 test/typeparam/issue48280.dir/main.go create mode 100644 test/typeparam/issue48280.go diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index b61b1e97fb..7f7143dcfe 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -318,17 +318,17 @@ func (r *importReader) obj(name string) { r.declare(types2.NewFunc(pos, r.currPkg, name, sig)) case 'T', 'U': - var tparams []*types2.TypeParam - if tag == 'U' { - tparams = r.tparamList() - } - // Types can be recursive. We need to setup a stub // declaration before recursing. obj := types2.NewTypeName(pos, r.currPkg, name, nil) named := types2.NewNamed(obj, nil, nil) - named.SetTypeParams(tparams) + // Declare obj before calling r.tparamList, so the new type name is recognized + // if used in the constraint of one of its own typeparams (see #48280). r.declare(obj) + if tag == 'U' { + tparams := r.tparamList() + named.SetTypeParams(tparams) + } underlying := r.p.typAt(r.uint64(), named).Underlying() named.SetUnderlying(underlying) diff --git a/test/typeparam/issue48280.dir/a.go b/test/typeparam/issue48280.dir/a.go new file mode 100644 index 0000000000..17859e6aa9 --- /dev/null +++ b/test/typeparam/issue48280.dir/a.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type I[T I[T]] interface { + F() T +} + +type S struct{} diff --git a/test/typeparam/issue48280.dir/main.go b/test/typeparam/issue48280.dir/main.go new file mode 100644 index 0000000000..b9981c6f61 --- /dev/null +++ b/test/typeparam/issue48280.dir/main.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "a" + +func main() { + _ = a.S{} +} diff --git a/test/typeparam/issue48280.go b/test/typeparam/issue48280.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/issue48280.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From 2953cd00836323112846b21f60fa1d68aa0f9a77 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Fri, 10 Sep 2021 08:20:28 +0700 Subject: [PATCH 1133/2500] go/internal/gcimporter: prevent importReader reading type parameter twice This is port of CL 349009 to go/internal/gcimporter. Updates #48280 Change-Id: I7d40d8b67333538ca58fe012535d54e891d0ed16 Reviewed-on: https://go-review.googlesource.com/c/go/+/349010 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/go/internal/gcimporter/iimport.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go index 039fc6a61b..56f6418d5e 100644 --- a/src/go/internal/gcimporter/iimport.go +++ b/src/go/internal/gcimporter/iimport.go @@ -284,6 +284,8 @@ type importReader struct { prevColumn int64 } +// obj reads import declaration for an object. It may not read +// the entire declaration, e.g, for recursive type. func (r *importReader) obj(name string) { tag := r.byte() pos := r.pos() @@ -309,16 +311,17 @@ func (r *importReader) obj(name string) { r.declare(types.NewFunc(pos, r.currPkg, name, sig)) case 'T', 'U': - var tparams []*types.TypeParam - if tag == 'U' { - tparams = r.tparamList() - } // Types can be recursive. We need to setup a stub // declaration before recursing. obj := types.NewTypeName(pos, r.currPkg, name, nil) named := types.NewNamed(obj, nil, nil) - named.SetTypeParams(tparams) + // Declare obj before calling r.tparamList, so the new type name is recognized + // if used in the constraint of one of its own typeparams (see #48280). r.declare(obj) + if tag == 'U' { + tparams := r.tparamList() + named.SetTypeParams(tparams) + } underlying := r.p.typAt(r.uint64(), named).Underlying() named.SetUnderlying(underlying) -- GitLab From ee91bb83198f61aa8f26c3100ca7558d302c0a98 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Fri, 10 Sep 2021 08:34:03 +0700 Subject: [PATCH 1134/2500] cmd/compile: prevent typecheck importer reading type parameter twice This is a port of CL 349009 to typecheck importer. Fixes #48306 Change-Id: Iec3f078089346bd85f0ab739896e079940325011 Reviewed-on: https://go-review.googlesource.com/c/go/+/349011 Trust: Cuong Manh Le Trust: Dan Scales Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/typecheck/iimport.go | 6 +----- src/go/internal/gcimporter/gcimporter_test.go | 2 -- test/run.go | 2 -- test/typeparam/issue48306.dir/a.go | 9 +++++++++ test/typeparam/issue48306.dir/main.go | 15 +++++++++++++++ test/typeparam/issue48306.go | 7 +++++++ 6 files changed, 32 insertions(+), 9 deletions(-) create mode 100644 test/typeparam/issue48306.dir/a.go create mode 100644 test/typeparam/issue48306.dir/main.go create mode 100644 test/typeparam/issue48306.go diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 8bc098c2bd..6eec94a984 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -316,16 +316,12 @@ func (r *importReader) doDecl(sym *types.Sym) *ir.Name { return n case 'T', 'U': - var rparams []*types.Type - if tag == 'U' { - rparams = r.typeList() - } - // Types can be recursive. We need to setup a stub // declaration before recursing. n := importtype(pos, sym) t := n.Type() if tag == 'U' { + rparams := r.typeList() t.SetRParams(rparams) } diff --git a/src/go/internal/gcimporter/gcimporter_test.go b/src/go/internal/gcimporter/gcimporter_test.go index 478534daf2..9f4345d8f9 100644 --- a/src/go/internal/gcimporter/gcimporter_test.go +++ b/src/go/internal/gcimporter/gcimporter_test.go @@ -167,8 +167,6 @@ func TestImportTypeparamTests(t *testing.T) { skip := map[string]string{ "equal.go": "inconsistent embedded sorting", // TODO(rfindley): investigate this. "nested.go": "fails to compile", // TODO(rfindley): investigate this. - - "issue46461.go": "known issue with type parameter constraints referring back to parameterized type", } for _, entry := range list { diff --git a/test/run.go b/test/run.go index d2b7b88768..790b54bfd2 100644 --- a/test/run.go +++ b/test/run.go @@ -2188,8 +2188,6 @@ var g3Failures = setOf( "typeparam/nested.go", // -G=3 doesn't support function-local types with generics - "typeparam/issue46461b.go", // -G=3 fails when type parameters refer back to the parameterized type itself - "typeparam/mdempsky/4.go", // -G=3 can't export functions with labeled breaks in loops ) diff --git a/test/typeparam/issue48306.dir/a.go b/test/typeparam/issue48306.dir/a.go new file mode 100644 index 0000000000..739750b20b --- /dev/null +++ b/test/typeparam/issue48306.dir/a.go @@ -0,0 +1,9 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type I[T I[T]] interface { + F() T +} diff --git a/test/typeparam/issue48306.dir/main.go b/test/typeparam/issue48306.dir/main.go new file mode 100644 index 0000000000..5d602fe07c --- /dev/null +++ b/test/typeparam/issue48306.dir/main.go @@ -0,0 +1,15 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "a" + +type S struct{} + +func (*S) F() *S { return nil } + +func main() { + var _ a.I[*S] = &S{} +} diff --git a/test/typeparam/issue48306.go b/test/typeparam/issue48306.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/issue48306.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From b3c6de9dcd9a7258615dea7ca0dcd00878f9027d Mon Sep 17 00:00:00 2001 From: "Paul E. Murphy" Date: Tue, 9 Mar 2021 16:55:31 -0600 Subject: [PATCH 1135/2500] cmd/internal/obj/ppc64: allow VR register arguments to VS registers Likewise, reorder register numbers such that extended mnemonics which use FPR arguments can be transparently encoded as a VSR argument for the move to/from VSR class of instructions. Specifically, ensure the following holds for all FPx and VRx constants: FPRx & 63 == x, and VRx & 63 == x + 32. This simplifies encoding machine instructions, and likewise helps ppc64 assembly writers to avoid hokey workarounds when switching from vector to vector-scalar register notation. Notably, many VSX instructions are limited to vector operands due to encoding restrictions. Secondly, this explicitly rejects dubious usages of the m[tf]vsr family of instructions which had previously been accepted. * Reject two GPR arguments for non-MTVSRDD opcodes. These have no defined behavior today, and may set RFU bits. e.g MTVSRD R1, R2, VS1 * Reject FPR destinations for MTVSRDD, and only accept with two GPR arguments. This copies two GPR values into either half of a VSR. e.g MTVSRDD R1, R2, F1 MTVSRDD R1, F1 Change-Id: If13dd88c3791d1892dbd18ef0e34675a5285fff9 Reviewed-on: https://go-review.googlesource.com/c/go/+/342929 Run-TryBot: Paul Murphy TryBot-Result: Go Bot Trust: Lynn Boger Reviewed-by: Cherry Mui --- src/cmd/asm/internal/asm/testdata/ppc64.s | 15 ++++ src/cmd/internal/obj/ppc64/a.out.go | 10 +-- src/cmd/internal/obj/ppc64/asm9.go | 85 +++++++---------------- src/cmd/internal/obj/ppc64/asm_test.go | 41 +++++++++++ 4 files changed, 87 insertions(+), 64 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/ppc64.s b/src/cmd/asm/internal/asm/testdata/ppc64.s index b6c0aa5035..28ceb621cb 100644 --- a/src/cmd/asm/internal/asm/testdata/ppc64.s +++ b/src/cmd/asm/internal/asm/testdata/ppc64.s @@ -649,6 +649,8 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0 LXVB16X (R3)(R4), VS1 // 7c241ed8 LXVW4X (R3)(R4), VS1 // 7c241e18 LXV 16(R3), VS1 // f4230011 + LXV 16(R3), VS33 // f4230019 + LXV 16(R3), V1 // f4230019 LXVL R3, R4, VS1 // 7c23221a LXVLL R3, R4, VS1 // 7c23225a LXVX R3, R4, VS1 // 7c232218 @@ -668,8 +670,13 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0 MTFPRD R3, F0 // 7c030166 MFVRD V0, R3 // 7c030067 MFVSRLD VS63,R4 // 7fe40267 + MFVSRLD V31,R4 // 7fe40267 MFVSRWZ VS33,R4 // 7c2400e7 + MFVSRWZ V1,R4 // 7c2400e7 MTVSRD R3, VS1 // 7c230166 + MTVSRDD R3, R4, VS1 // 7c232366 + MTVSRDD R3, R4, VS33 // 7c232367 + MTVSRDD R3, R4, V1 // 7c232367 MTVRD R3, V13 // 7da30167 MTVSRWA R4, VS31 // 7fe401a6 MTVSRWS R4, VS32 // 7c040327 @@ -678,6 +685,8 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0 XXBRW VS1, VS2 // f04f0f6c XXBRH VS2, VS3 // f067176c XXLAND VS1, VS2, VS3 // f0611410 + XXLAND V1, V2, V3 // f0611417 + XXLAND VS33, VS34, VS35 // f0611417 XXLANDC VS1, VS2, VS3 // f0611450 XXLEQV VS0, VS1, VS2 // f0400dd0 XXLNAND VS0, VS1, VS2 // f0400d90 @@ -687,11 +696,17 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0 XXLORQ VS1, VS2, VS3 // f0611490 XXLXOR VS1, VS2, VS3 // f06114d0 XXSEL VS1, VS2, VS3, VS4 // f08110f0 + XXSEL VS33, VS34, VS35, VS36 // f08110ff + XXSEL V1, V2, V3, V4 // f08110ff XXMRGHW VS1, VS2, VS3 // f0611090 XXMRGLW VS1, VS2, VS3 // f0611190 XXSPLTW VS1, $1, VS2 // f0410a90 + XXSPLTW VS33, $1, VS34 // f0410a93 + XXSPLTW V1, $1, V2 // f0410a93 XXPERM VS1, VS2, VS3 // f06110d0 XXSLDWI VS1, VS2, $1, VS3 // f0611110 + XXSLDWI V1, V2, $1, V3 // f0611117 + XXSLDWI VS33, VS34, $1, VS35 // f0611117 XSCVDPSP VS1, VS2 // f0400c24 XVCVDPSP VS1, VS2 // f0400e24 XSCVSXDDP VS1, VS2 // f0400de0 diff --git a/src/cmd/internal/obj/ppc64/a.out.go b/src/cmd/internal/obj/ppc64/a.out.go index e57beb3276..dda24a0b96 100644 --- a/src/cmd/internal/obj/ppc64/a.out.go +++ b/src/cmd/internal/obj/ppc64/a.out.go @@ -79,8 +79,10 @@ const ( REG_R30 REG_R31 - /* F0=4128 ... F31=4159 */ - REG_F0 + /* Align FPR and VSR vectors such that when masked with 0x3F they produce + an equivalent VSX register. */ + /* F0=4160 ... F31=4191 */ + REG_F0 = obj.RBasePPC64 + iota + 32 REG_F1 REG_F2 REG_F3 @@ -113,7 +115,7 @@ const ( REG_F30 REG_F31 - /* V0=4160 ... V31=4191 */ + /* V0=4192 ... V31=4223 */ REG_V0 REG_V1 REG_V2 @@ -147,7 +149,7 @@ const ( REG_V30 REG_V31 - /* VS0=4192 ... VS63=4255 */ + /* VS0=4224 ... VS63=4287 */ REG_VS0 REG_VS1 REG_VS2 diff --git a/src/cmd/internal/obj/ppc64/asm9.go b/src/cmd/internal/obj/ppc64/asm9.go index e642413590..1d92c4866f 100644 --- a/src/cmd/internal/obj/ppc64/asm9.go +++ b/src/cmd/internal/obj/ppc64/asm9.go @@ -428,15 +428,13 @@ var optab = []Optab{ {as: ASTXSIWX, a1: C_VSREG, a6: C_SOREG, type_: 86, size: 4}, /* vsx scalar as integer store, xx1-form */ /* VSX move from VSR */ - {as: AMFVSRD, a1: C_VSREG, a6: C_REG, type_: 88, size: 4}, /* vsx move from vsr, xx1-form */ + {as: AMFVSRD, a1: C_VSREG, a6: C_REG, type_: 88, size: 4}, {as: AMFVSRD, a1: C_FREG, a6: C_REG, type_: 88, size: 4}, - {as: AMFVSRD, a1: C_VREG, a6: C_REG, type_: 88, size: 4}, /* VSX move to VSR */ - {as: AMTVSRD, a1: C_REG, a6: C_VSREG, type_: 88, size: 4}, /* vsx move to vsr, xx1-form */ - {as: AMTVSRD, a1: C_REG, a2: C_REG, a6: C_VSREG, type_: 88, size: 4}, - {as: AMTVSRD, a1: C_REG, a6: C_FREG, type_: 88, size: 4}, - {as: AMTVSRD, a1: C_REG, a6: C_VREG, type_: 88, size: 4}, + {as: AMTVSRD, a1: C_REG, a6: C_VSREG, type_: 104, size: 4}, + {as: AMTVSRD, a1: C_REG, a6: C_FREG, type_: 104, size: 4}, + {as: AMTVSRDD, a1: C_REG, a2: C_REG, a6: C_VSREG, type_: 104, size: 4}, /* VSX logical */ {as: AXXLAND, a1: C_VSREG, a2: C_VSREG, a6: C_VSREG, type_: 90, size: 4}, /* vsx and, xx3-form */ @@ -1036,13 +1034,14 @@ func (c *ctxt9) oplook(p *obj.Prog) *Optab { // c.ctxt.Logf("oplook %v %d %d %d %d\n", p, a1, a2, a3, a4, a5, a6) ops := oprange[p.As&obj.AMask] c1 := &xcmp[a1] + c2 := &xcmp[a2] c3 := &xcmp[a3] c4 := &xcmp[a4] c5 := &xcmp[a5] c6 := &xcmp[a6] for i := range ops { op := &ops[i] - if int(op.a2) == a2 && c1[op.a1] && c3[op.a3] && c4[op.a4] && c5[op.a5] && c6[op.a6] { + if c1[op.a1] && c2[op.a2] && c3[op.a3] && c4[op.a4] && c5[op.a5] && c6[op.a6] { p.Optab = uint16(cap(optab) - cap(ops) + i + 1) return op } @@ -1116,6 +1115,12 @@ func cmp(a int, b int) bool { return r0iszero != 0 /*TypeKind(100016)*/ } + case C_VSREG: + /* Allow any VR argument as a VSR operand. */ + if b == C_VREG { + return true + } + case C_ANY: return true } @@ -1594,7 +1599,6 @@ func buildop(ctxt *obj.Link) { opset(AMTVRD, r0) opset(AMTVSRWA, r0) opset(AMTVSRWZ, r0) - opset(AMTVSRDD, r0) opset(AMTVSRWS, r0) case AXXLAND: /* xxland, xxlandc, xxleqv, xxlnand */ @@ -1977,6 +1981,7 @@ func buildop(ctxt *obj.Link) { ACMPEQB, AECIWX, ACLRLSLWI, + AMTVSRDD, obj.ANOP, obj.ATEXT, obj.AUNDEF, @@ -2075,50 +2080,32 @@ func AOP_IR(op uint32, d uint32, simm uint32) uint32 { } /* XX1-form 3-register operands, 1 VSR operand */ -func AOP_XX1(op uint32, d uint32, a uint32, b uint32) uint32 { - /* For the XX-form encodings, we need the VSX register number to be exactly */ - /* between 0-63, so we can properly set the rightmost bits. */ - r := d - REG_VS0 +func AOP_XX1(op uint32, r uint32, a uint32, b uint32) uint32 { return op | (r&31)<<21 | (a&31)<<16 | (b&31)<<11 | (r&32)>>5 } /* XX2-form 3-register operands, 2 VSR operands */ -func AOP_XX2(op uint32, d uint32, a uint32, b uint32) uint32 { - xt := d - REG_VS0 - xb := b - REG_VS0 +func AOP_XX2(op uint32, xt uint32, a uint32, xb uint32) uint32 { return op | (xt&31)<<21 | (a&3)<<16 | (xb&31)<<11 | (xb&32)>>4 | (xt&32)>>5 } /* XX3-form 3 VSR operands */ -func AOP_XX3(op uint32, d uint32, a uint32, b uint32) uint32 { - xt := d - REG_VS0 - xa := a - REG_VS0 - xb := b - REG_VS0 +func AOP_XX3(op uint32, xt uint32, xa uint32, xb uint32) uint32 { return op | (xt&31)<<21 | (xa&31)<<16 | (xb&31)<<11 | (xa&32)>>3 | (xb&32)>>4 | (xt&32)>>5 } /* XX3-form 3 VSR operands + immediate */ -func AOP_XX3I(op uint32, d uint32, a uint32, b uint32, c uint32) uint32 { - xt := d - REG_VS0 - xa := a - REG_VS0 - xb := b - REG_VS0 +func AOP_XX3I(op uint32, xt uint32, xa uint32, xb uint32, c uint32) uint32 { return op | (xt&31)<<21 | (xa&31)<<16 | (xb&31)<<11 | (c&3)<<8 | (xa&32)>>3 | (xb&32)>>4 | (xt&32)>>5 } /* XX4-form, 4 VSR operands */ -func AOP_XX4(op uint32, d uint32, a uint32, b uint32, c uint32) uint32 { - xt := d - REG_VS0 - xa := a - REG_VS0 - xb := b - REG_VS0 - xc := c - REG_VS0 +func AOP_XX4(op uint32, xt uint32, xa uint32, xb uint32, xc uint32) uint32 { return op | (xt&31)<<21 | (xa&31)<<16 | (xb&31)<<11 | (xc&31)<<6 | (xc&32)>>2 | (xa&32)>>3 | (xb&32)>>4 | (xt&32)>>5 } /* DQ-form, VSR register, register + offset operands */ -func AOP_DQ(op uint32, d uint32, a uint32, b uint32) uint32 { - /* For the DQ-form encodings, we need the VSX register number to be exactly */ - /* between 0-63, so we can properly set the SX bit. */ - r := d - REG_VS0 +func AOP_DQ(op uint32, xt uint32, a uint32, b uint32) uint32 { /* The EA for this instruction form is (RA) + DQ << 4, where DQ is a 12-bit signed integer. */ /* In order to match the output of the GNU objdump (and make the usage in Go asm easier), the */ /* instruction is called using the sign extended value (i.e. a valid offset would be -32752 or 32752, */ @@ -2126,7 +2113,7 @@ func AOP_DQ(op uint32, d uint32, a uint32, b uint32) uint32 { /* bits 0 to 3 in 'dq' need to be zero, otherwise this will generate an illegal instruction. */ /* If in doubt how this instruction form is encoded, refer to ISA 3.0b, pages 492 and 507. */ dq := b >> 4 - return op | (r&31)<<21 | (a&31)<<16 | (dq&4095)<<4 | (r&32)>>2 + return op | (xt&31)<<21 | (a&31)<<16 | (dq&4095)<<4 | (xt&32)>>2 } /* Z23-form, 3-register operands + CY field */ @@ -3586,33 +3573,8 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) { /* 3-register operand order: (RB)(RA*1), XT */ o1 = AOP_XX1(c.oploadx(p.As), uint32(p.To.Reg), uint32(p.From.Index), uint32(p.From.Reg)) - case 88: /* VSX instructions, XX1-form */ - /* reg reg none OR reg reg reg */ - /* 3-register operand order: RA, RB, XT */ - /* 2-register operand order: XS, RA or RA, XT */ - xt := int32(p.To.Reg) - xs := int32(p.From.Reg) - /* We need to treat the special case of extended mnemonics that may have a FREG/VREG as an argument */ - if REG_V0 <= xt && xt <= REG_V31 { - /* Convert V0-V31 to VS32-VS63 */ - xt = xt + 64 - o1 = AOP_XX1(c.oprrr(p.As), uint32(xt), uint32(p.From.Reg), uint32(p.Reg)) - } else if REG_F0 <= xt && xt <= REG_F31 { - /* Convert F0-F31 to VS0-VS31 */ - xt = xt + 64 - o1 = AOP_XX1(c.oprrr(p.As), uint32(xt), uint32(p.From.Reg), uint32(p.Reg)) - } else if REG_VS0 <= xt && xt <= REG_VS63 { - o1 = AOP_XX1(c.oprrr(p.As), uint32(xt), uint32(p.From.Reg), uint32(p.Reg)) - } else if REG_V0 <= xs && xs <= REG_V31 { - /* Likewise for XS */ - xs = xs + 64 - o1 = AOP_XX1(c.oprrr(p.As), uint32(xs), uint32(p.To.Reg), uint32(p.Reg)) - } else if REG_F0 <= xs && xs <= REG_F31 { - xs = xs + 64 - o1 = AOP_XX1(c.oprrr(p.As), uint32(xs), uint32(p.To.Reg), uint32(p.Reg)) - } else if REG_VS0 <= xs && xs <= REG_VS63 { - o1 = AOP_XX1(c.oprrr(p.As), uint32(xs), uint32(p.To.Reg), uint32(p.Reg)) - } + case 88: /* VSX mfvsr* instructions, XX1-form XS,RA */ + o1 = AOP_XX1(c.oprrr(p.As), uint32(p.From.Reg), uint32(p.To.Reg), uint32(p.Reg)) case 89: /* VSX instructions, XX2-form */ /* reg none reg OR reg imm reg */ @@ -3743,6 +3705,9 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) { mb := uint32(c.regoff(&p.RestArgs[0].Addr)) me := uint32(c.regoff(&p.RestArgs[1].Addr)) o1 = OP_RLW(c.oprrr(p.As), uint32(p.To.Reg), uint32(p.Reg), uint32(p.From.Reg), mb, me) + + case 104: /* VSX mtvsr* instructions, XX1-form RA,RB,XT */ + o1 = AOP_XX1(c.oprrr(p.As), uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg)) } out[0] = o1 diff --git a/src/cmd/internal/obj/ppc64/asm_test.go b/src/cmd/internal/obj/ppc64/asm_test.go index 70dabc2017..b851d3c86b 100644 --- a/src/cmd/internal/obj/ppc64/asm_test.go +++ b/src/cmd/internal/obj/ppc64/asm_test.go @@ -107,3 +107,44 @@ func TestPCalign(t *testing.T) { t.Errorf("Invalid alignment not detected for PCALIGN\n") } } + +// Verify register constants are correctly aligned. Much of the ppc64 assembler assumes masking out significant +// bits will produce a valid register number: +// REG_Rx & 31 == x +// REG_Fx & 31 == x +// REG_Vx & 31 == x +// REG_VSx & 63 == x +// REG_SPRx & 1023 == x +// REG_CRx & 7 == x +// +// VR and FPR disjointly overlap VSR, interpreting as VSR registers should produce the correctly overlapped VSR. +// REG_FPx & 63 == x +// REG_Vx & 63 == x + 32 +func TestRegValueAlignment(t *testing.T) { + tstFunc := func(rstart, rend, msk, rout int) { + for i := rstart; i <= rend; i++ { + if i&msk != rout { + t.Errorf("%v is not aligned to 0x%X (expected %d, got %d)\n", rconv(i), msk, rout, rstart&msk) + } + rout++ + } + } + var testType = []struct { + rstart int + rend int + msk int + rout int + }{ + {REG_VS0, REG_VS63, 63, 0}, + {REG_R0, REG_R31, 31, 0}, + {REG_F0, REG_F31, 31, 0}, + {REG_V0, REG_V31, 31, 0}, + {REG_V0, REG_V31, 63, 32}, + {REG_F0, REG_F31, 63, 0}, + {REG_SPR0, REG_SPR0 + 1023, 1023, 0}, + {REG_CR0, REG_CR7, 7, 0}, + } + for _, t := range testType { + tstFunc(t.rstart, t.rend, t.msk, t.rout) + } +} -- GitLab From 8699425b5527e24dc184d61d949d7f6db37c0c5c Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Tue, 14 Sep 2021 08:56:54 +0200 Subject: [PATCH 1136/2500] syscall: remove use of IN_KUBERNETES in test CL 201737 dropped the use of IN_KUBERNETES in tests, but it looks like it did not catch all occurrences. For #12815 For #34956 Change-Id: I72b89bfb850ba2890e9e6aa39b87167291ab7e9f Reviewed-on: https://go-review.googlesource.com/c/go/+/349789 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/syscall/exec_linux_test.go | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/syscall/exec_linux_test.go b/src/syscall/exec_linux_test.go index 85b59ad00d..1555318eda 100644 --- a/src/syscall/exec_linux_test.go +++ b/src/syscall/exec_linux_test.go @@ -111,14 +111,6 @@ func checkUserNS(t *testing.T) { t.Skip("kernel doesn't support user namespaces") } } - - // When running under the Go continuous build, skip tests for - // now when under Kubernetes. (where things are root but not quite) - // Both of these are our own environment variables. - // See Issue 12815. - if os.Getenv("GO_BUILDER_NAME") != "" && os.Getenv("IN_KUBERNETES") == "1" { - t.Skip("skipping test on Kubernetes-based builders; see Issue 12815") - } } func whoamiCmd(t *testing.T, uid, gid int, setgroups bool) *exec.Cmd { @@ -201,14 +193,6 @@ func TestUnshare(t *testing.T) { t.Skip("kernel prohibits unshare in unprivileged process, unless using user namespace") } - // When running under the Go continuous build, skip tests for - // now when under Kubernetes. (where things are root but not quite) - // Both of these are our own environment variables. - // See Issue 12815. - if os.Getenv("GO_BUILDER_NAME") != "" && os.Getenv("IN_KUBERNETES") == "1" { - t.Skip("skipping test on Kubernetes-based builders; see Issue 12815") - } - path := "/proc/net/dev" if _, err := os.Stat(path); err != nil { if os.IsNotExist(err) { -- GitLab From 181e8cde301cd8205489e746334174fee7290c9b Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Tue, 14 Sep 2021 10:36:29 +0700 Subject: [PATCH 1137/2500] go/internal/gcimporter: remove outdated comment CL 349010 ported the fix from CL 349009, but forgot to remove the outdated comment from old solution. This CL removes that one. Change-Id: Ia401295e9d0984f4a088ddce5db09d306bfd89b6 Reviewed-on: https://go-review.googlesource.com/c/go/+/349729 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/go/internal/gcimporter/iimport.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go index 56f6418d5e..d9174d470b 100644 --- a/src/go/internal/gcimporter/iimport.go +++ b/src/go/internal/gcimporter/iimport.go @@ -284,8 +284,6 @@ type importReader struct { prevColumn int64 } -// obj reads import declaration for an object. It may not read -// the entire declaration, e.g, for recursive type. func (r *importReader) obj(name string) { tag := r.byte() pos := r.pos() -- GitLab From b2c04f0d48234765ce37bbb178bd174f3857929a Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Wed, 4 Aug 2021 16:07:47 -0400 Subject: [PATCH 1138/2500] runtime: avoid loop variable capture in test In TestSegv, the t.Run closure captures the loop variable 'test'. Since the subtest calls t.Parallel, the parent test is allowed to keep running, changing the loop variable and thus changing the value of 'test' in the subtest. Change-Id: I021ddc50304de08a341e6ffe486aa54e573d3b94 Reviewed-on: https://go-review.googlesource.com/c/go/+/339911 Trust: Michael Pratt Run-TryBot: Michael Pratt TryBot-Result: Go Bot Reviewed-by: Austin Clements Reviewed-by: Cherry Mui --- src/runtime/crash_cgo_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go index 5729942cee..ce7bed920f 100644 --- a/src/runtime/crash_cgo_test.go +++ b/src/runtime/crash_cgo_test.go @@ -591,6 +591,7 @@ func TestSegv(t *testing.T) { } for _, test := range []string{"Segv", "SegvInCgo"} { + test := test t.Run(test, func(t *testing.T) { t.Parallel() got := runTestProg(t, "testprogcgo", test) -- GitLab From 3a72175cdcbfb64cca5968be52ac964f69d3a44a Mon Sep 17 00:00:00 2001 From: wdvxdr Date: Fri, 10 Sep 2021 20:56:29 +0800 Subject: [PATCH 1139/2500] cmd/compile: fix test/typeparam/mdempsky/4.go for -G=3 Change-Id: I894ee000561a3c6afede8df697b1bce4576ceef0 Reviewed-on: https://go-review.googlesource.com/c/go/+/349012 Reviewed-by: Dan Scales Trust: Dan Scales Trust: Keith Randall --- src/cmd/compile/internal/typecheck/iimport.go | 22 ++++++++++++++++--- test/run.go | 2 -- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 6eec94a984..b3a0eb8871 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1166,10 +1166,26 @@ func (r *importReader) stmtList() []ir.Node { if n.Op() == ir.OBLOCK { n := n.(*ir.BlockStmt) list = append(list, n.List...) - } else { - list = append(list, n) + continue } - + if len(list) > 0 { + // check for an optional label that can only immediately + // precede a for/range/select/switch statement. + if last := list[len(list)-1]; last.Op() == ir.OLABEL { + label := last.(*ir.LabelStmt).Label + switch n.Op() { + case ir.OFOR: + n.(*ir.ForStmt).Label = label + case ir.ORANGE: + n.(*ir.RangeStmt).Label = label + case ir.OSELECT: + n.(*ir.SelectStmt).Label = label + case ir.OSWITCH: + n.(*ir.SwitchStmt).Label = label + } + } + } + list = append(list, n) } return list } diff --git a/test/run.go b/test/run.go index 790b54bfd2..3fb87af397 100644 --- a/test/run.go +++ b/test/run.go @@ -2187,8 +2187,6 @@ var g3Failures = setOf( "writebarrier.go", // correct diagnostics, but different lines (probably irgen's fault) "typeparam/nested.go", // -G=3 doesn't support function-local types with generics - - "typeparam/mdempsky/4.go", // -G=3 can't export functions with labeled breaks in loops ) var unifiedFailures = setOf( -- GitLab From 137543bb93e15286b54d58d17d51e609ed49339a Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 14 Sep 2021 08:39:08 -0700 Subject: [PATCH 1140/2500] cmd/compile: set IsShape based on type being in the Shapes pkg Move ShapePkg to types, and change types.NewNamed to automatically set IsShape/HasShape if a type is in the shapes pkg. This means that imported shape types will automatically have the correct IsShape/HasShape flags, even though we are not explicitly exporting/importing those flags. Updates #48337 Change-Id: I8b6131a663205f73f395943c9d0c8bdb2a213401 Reviewed-on: https://go-review.googlesource.com/c/go/+/349869 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Dan Scales --- src/cmd/compile/internal/typecheck/subr.go | 10 ++++++--- src/cmd/compile/internal/types/type.go | 6 ++++++ test/typeparam/issue48337b.dir/a.go | 25 ++++++++++++++++++++++ test/typeparam/issue48337b.dir/main.go | 11 ++++++++++ test/typeparam/issue48337b.go | 7 ++++++ 5 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 test/typeparam/issue48337b.dir/a.go create mode 100644 test/typeparam/issue48337b.dir/main.go create mode 100644 test/typeparam/issue48337b.go diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 5323872eaf..5854e3c458 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1414,9 +1414,15 @@ func Shapify(t *types.Type) *types.Type { return s } - sym := shapePkg.Lookup(u.LinkString()) + sym := types.ShapePkg.Lookup(u.LinkString()) + if sym.Def != nil { + // Use any existing type with the same name + shaped[u] = sym.Def.Type() + return shaped[u] + } name := ir.NewDeclNameAt(u.Pos(), ir.OTYPE, sym) s := types.NewNamed(name) + sym.Def = name s.SetUnderlying(u) s.SetIsShape(true) s.SetHasShape(true) @@ -1427,5 +1433,3 @@ func Shapify(t *types.Type) *types.Type { } var shaped = map[*types.Type]*types.Type{} - -var shapePkg = types.NewPkg(".shape", ".shape") diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index eb70f7b9b4..392c54ba79 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -1706,6 +1706,10 @@ func NewNamed(obj TypeObject) *Type { t := newType(TFORW) t.sym = obj.Sym() t.nod = obj + if t.sym.Pkg == ShapePkg { + t.SetIsShape(true) + t.SetHasShape(true) + } return t } @@ -2182,3 +2186,5 @@ var ( ) var SimType [NTYPE]Kind + +var ShapePkg = NewPkg(".shape", ".shape") diff --git a/test/typeparam/issue48337b.dir/a.go b/test/typeparam/issue48337b.dir/a.go new file mode 100644 index 0000000000..a3c2e88a2f --- /dev/null +++ b/test/typeparam/issue48337b.dir/a.go @@ -0,0 +1,25 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type Container[T any] struct { + X T +} + +func NewContainer[T any](x T) *Container[T] { + return &Container[T]{x} +} + +type MetaContainer struct { + C *Container[Value] +} + +type Value struct{} + +func NewMetaContainer() *MetaContainer { + c := NewContainer(Value{}) + // c := &Container[Value]{Value{}} // <-- this works + return &MetaContainer{c} +} diff --git a/test/typeparam/issue48337b.dir/main.go b/test/typeparam/issue48337b.dir/main.go new file mode 100644 index 0000000000..0b2814cbc0 --- /dev/null +++ b/test/typeparam/issue48337b.dir/main.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "a" + +func main() { + a.NewMetaContainer() +} diff --git a/test/typeparam/issue48337b.go b/test/typeparam/issue48337b.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/issue48337b.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From 2933c451a06ee0f97a698d1383cfbda988374137 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Fri, 10 Sep 2021 10:23:23 -0400 Subject: [PATCH 1141/2500] go/types: merge Named type loading and expansion Named type expansion and loading were conceptually similar: a mechanism for lazily resolving type information in a concurrency-safe manner. Unify them into a 'resolve' method, that delegates to a resolver func to produce type parameters, underlying, and methods. By leveraging the sync.Once field on Named for instance expansion, we get closer to making instance expansion concurrency-safe, and remove the requirement that instPos guard instantiation. This will be cleaned up in a follow-up CL. This also fixes #47887 by causing substituted type instances to be expanded (in the old code, this could be fixed by setting instPos when substituting). For #47910 Fixes #47887 Change-Id: Ifc52a420dde76e3a46ce494fea9bd289bc8aca4c Reviewed-on: https://go-review.googlesource.com/c/go/+/349410 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/decl.go | 4 +- src/go/types/instantiate.go | 3 +- src/go/types/lookup.go | 2 +- src/go/types/named.go | 114 +++++++----------- src/go/types/object.go | 16 ++- src/go/types/signature.go | 2 +- src/go/types/subst.go | 39 +++--- .../types/testdata/fixedbugs/issue47887.go2 | 28 +++++ src/go/types/type.go | 2 +- 9 files changed, 114 insertions(+), 96 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue47887.go2 diff --git a/src/go/types/decl.go b/src/go/types/decl.go index c1506f6dbd..7f157f528a 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -316,7 +316,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { } case *Named: - t.expand(check.conf.Environment) + t.resolve(check.conf.Environment) // don't touch the type if it is from a different package or the Universe scope // (doing so would lead to a race condition - was issue #35049) if t.obj.pkg != check.pkg { @@ -773,7 +773,7 @@ func (check *Checker) collectMethods(obj *TypeName) { } if base != nil { - base.load() // TODO(mdempsky): Probably unnecessary. + base.resolve(nil) // TODO(mdempsky): Probably unnecessary. base.methods = append(base.methods, m) } } diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 50be07b8fd..b74f0db466 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -116,9 +116,10 @@ func (check *Checker) instance(pos token.Pos, typ Type, targs []Type, env *Envir } } tname := NewTypeName(pos, t.obj.pkg, t.obj.name, nil) - named := check.newNamed(tname, t, nil, nil, nil) // methods and tparams are set when named is loaded + named := check.newNamed(tname, t, nil, nil, nil) // methods and tparams are set when named is resolved named.targs = NewTypeList(targs) named.instPos = &pos + named.resolver = expandNamed if env != nil { // It's possible that we've lost a race to add named to the environment. // In this case, use whichever instance is recorded in the environment. diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index 4664a0b33b..cc7f24d97b 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -124,7 +124,7 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o seen[named] = true // look for a matching attached method - named.load() + named.resolve(nil) if i, m := lookupMethod(named.methods, pkg, name); m != nil { // potential match // caution: method may not have a proper signature yet diff --git a/src/go/types/named.go b/src/go/types/named.go index 74681ab2d4..fd9e1f4461 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -22,8 +22,9 @@ type Named struct { targs *TypeList // type arguments (after instantiation), or nil methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily - resolve func(*Named) ([]*TypeParam, Type, []*Func) - once sync.Once + // resolver may be provided to lazily resolve type parameters, underlying, and methods. + resolver func(*Environment, *Named) (tparams *TypeParamList, underlying Type, methods []*Func) + once sync.Once // ensures that tparams, underlying, and methods are resolved before accessing } // NewNamed returns a new named type for the given type name, underlying type, and associated methods. @@ -36,43 +37,22 @@ func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named { return (*Checker)(nil).newNamed(obj, nil, underlying, nil, methods) } -func (t *Named) load() *Named { - // If t is an instantiated type, it derives its methods and tparams from its - // base type. Since we expect type parameters and methods to be set after a - // call to load, we must load the base and copy here. - // - // underlying is set when t is expanded. - // - // By convention, a type instance is loaded iff its tparams are set. - if t.targs.Len() > 0 && t.tparams == nil { - t.orig.load() - t.tparams = t.orig.tparams - t.methods = t.orig.methods - } - if t.resolve == nil { +func (t *Named) resolve(env *Environment) *Named { + if t.resolver == nil { return t } t.once.Do(func() { - // TODO(mdempsky): Since we're passing t to resolve anyway + // TODO(mdempsky): Since we're passing t to the resolver anyway // (necessary because types2 expects the receiver type for methods // on defined interface types to be the Named rather than the // underlying Interface), maybe it should just handle calling // SetTypeParams, SetUnderlying, and AddMethod instead? Those - // methods would need to support reentrant calls though. It would + // methods would need to support reentrant calls though. It would // also make the API more future-proof towards further extensions // (like SetTypeParams). - - tparams, underlying, methods := t.resolve(t) - - switch underlying.(type) { - case nil, *Named: - panic("invalid underlying type") - } - - t.tparams = bindTParams(tparams) - t.underlying = underlying - t.methods = methods + t.tparams, t.underlying, t.methods = t.resolver(env, t) + t.fromRHS = t.underlying // for cycle detection }) return t } @@ -121,19 +101,19 @@ func (t *Named) _Orig() *Named { return t.orig } // TypeParams returns the type parameters of the named type t, or nil. // The result is non-nil for an (originally) parameterized type even if it is instantiated. -func (t *Named) TypeParams() *TypeParamList { return t.load().tparams } +func (t *Named) TypeParams() *TypeParamList { return t.resolve(nil).tparams } // SetTypeParams sets the type parameters of the named type t. -func (t *Named) SetTypeParams(tparams []*TypeParam) { t.load().tparams = bindTParams(tparams) } +func (t *Named) SetTypeParams(tparams []*TypeParam) { t.resolve(nil).tparams = bindTParams(tparams) } // TypeArgs returns the type arguments used to instantiate the named type t. func (t *Named) TypeArgs() *TypeList { return t.targs } // NumMethods returns the number of explicit methods whose receiver is named type t. -func (t *Named) NumMethods() int { return len(t.load().methods) } +func (t *Named) NumMethods() int { return len(t.resolve(nil).methods) } // Method returns the i'th method of named type t for 0 <= i < t.NumMethods(). -func (t *Named) Method(i int) *Func { return t.load().methods[i] } +func (t *Named) Method(i int) *Func { return t.resolve(nil).methods[i] } // SetUnderlying sets the underlying type and marks t as complete. func (t *Named) SetUnderlying(underlying Type) { @@ -143,18 +123,18 @@ func (t *Named) SetUnderlying(underlying Type) { if _, ok := underlying.(*Named); ok { panic("underlying type must not be *Named") } - t.load().underlying = underlying + t.resolve(nil).underlying = underlying } // AddMethod adds method m unless it is already in the method list. func (t *Named) AddMethod(m *Func) { - t.load() + t.resolve(nil) if i, _ := lookupMethod(t.methods, m.pkg, m.name); i < 0 { t.methods = append(t.methods, m) } } -func (t *Named) Underlying() Type { return t.load().expand(nil).underlying } +func (t *Named) Underlying() Type { return t.resolve(nil).underlying } func (t *Named) String() string { return TypeString(t, nil) } // ---------------------------------------------------------------------------- @@ -240,43 +220,37 @@ func (n *Named) setUnderlying(typ Type) { } } -// expand ensures that the underlying type of n is instantiated. +// expandNamed ensures that the underlying type of n is instantiated. // The underlying type will be Typ[Invalid] if there was an error. -func (n *Named) expand(env *Environment) *Named { - if n.instPos != nil { - // n must be loaded before instantiation, in order to have accurate - // tparams. This is done implicitly by the call to n.TypeParams, but making - // it explicit is harmless: load is idempotent. - n.load() - var u Type - if n.check.validateTArgLen(*n.instPos, n.tparams.Len(), n.targs.Len()) { - // TODO(rfindley): handling an optional Checker and Environment here (and - // in subst) feels overly complicated. Can we simplify? - if env == nil { - if n.check != nil { - env = n.check.conf.Environment - } else { - // If we're instantiating lazily, we might be outside the scope of a - // type-checking pass. In that case we won't have a pre-existing - // environment, but don't want to create a duplicate of the current - // instance in the process of expansion. - env = NewEnvironment() - } - h := env.typeHash(n.orig, n.targs.list()) - // add the instance to the environment to avoid infinite recursion. - // addInstance may return a different, existing instance, but we - // shouldn't return that instance from expand. - env.typeForHash(h, n) +func expandNamed(env *Environment, n *Named) (*TypeParamList, Type, []*Func) { + n.orig.resolve(env) + + var u Type + if n.check.validateTArgLen(*n.instPos, n.orig.tparams.Len(), n.targs.Len()) { + // TODO(rfindley): handling an optional Checker and Environment here (and + // in subst) feels overly complicated. Can we simplify? + if env == nil { + if n.check != nil { + env = n.check.conf.Environment + } else { + // If we're instantiating lazily, we might be outside the scope of a + // type-checking pass. In that case we won't have a pre-existing + // environment, but don't want to create a duplicate of the current + // instance in the process of expansion. + env = NewEnvironment() } - u = n.check.subst(*n.instPos, n.orig.underlying, makeSubstMap(n.TypeParams().list(), n.targs.list()), env) - } else { - u = Typ[Invalid] + h := env.typeHash(n.orig, n.targs.list()) + // add the instance to the environment to avoid infinite recursion. + // addInstance may return a different, existing instance, but we + // shouldn't return that instance from expand. + env.typeForHash(h, n) } - n.underlying = u - n.fromRHS = u - n.instPos = nil + u = n.check.subst(*n.instPos, n.orig.underlying, makeSubstMap(n.orig.tparams.list(), n.targs.list()), env) + } else { + u = Typ[Invalid] } - return n + n.instPos = nil + return n.orig.tparams, u, n.orig.methods } // safeUnderlying returns the underlying of typ without expanding instances, to @@ -285,7 +259,7 @@ func (n *Named) expand(env *Environment) *Named { // TODO(rfindley): eliminate this function or give it a better name. func safeUnderlying(typ Type) Type { if t, _ := typ.(*Named); t != nil { - return t.load().underlying + return t.resolve(nil).underlying } return typ.Underlying() } diff --git a/src/go/types/object.go b/src/go/types/object.go index b25fffdf5c..7f6f8a2550 100644 --- a/src/go/types/object.go +++ b/src/go/types/object.go @@ -232,9 +232,21 @@ func NewTypeName(pos token.Pos, pkg *Package, name string, typ Type) *TypeName { // _NewTypeNameLazy returns a new defined type like NewTypeName, but it // lazily calls resolve to finish constructing the Named object. -func _NewTypeNameLazy(pos token.Pos, pkg *Package, name string, resolve func(named *Named) (tparams []*TypeParam, underlying Type, methods []*Func)) *TypeName { +func _NewTypeNameLazy(pos token.Pos, pkg *Package, name string, load func(named *Named) (tparams []*TypeParam, underlying Type, methods []*Func)) *TypeName { obj := NewTypeName(pos, pkg, name, nil) - NewNamed(obj, nil, nil).resolve = resolve + + resolve := func(_ *Environment, t *Named) (*TypeParamList, Type, []*Func) { + tparams, underlying, methods := load(t) + + switch underlying.(type) { + case nil, *Named: + panic(fmt.Sprintf("invalid underlying type %T", t.underlying)) + } + + return bindTParams(tparams), underlying, methods + } + + NewNamed(obj, nil, nil).resolver = resolve return obj } diff --git a/src/go/types/signature.go b/src/go/types/signature.go index 37811828ee..bf6c775b89 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -200,7 +200,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast var err string switch T := rtyp.(type) { case *Named: - T.expand(nil) + T.resolve(check.conf.Environment) // The receiver type may be an instantiated type referred to // by an alias (which cannot have receiver parameters for now). if T.TypeArgs() != nil && sig.RecvTypeParams() == nil { diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 07fe6a6b6e..d9dab10e00 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -182,13 +182,19 @@ func (subst *subster) typ(typ Type) Type { } } - if t.TypeParams().Len() == 0 { + // subst is called by expandNamed, so in this function we need to be + // careful not to call any methods that would cause t to be expanded: doing + // so would result in deadlock. + // + // So we call t.orig.TypeParams() rather than t.TypeParams() here and + // below. + if t.orig.TypeParams().Len() == 0 { dump(">>> %s is not parameterized", t) return t // type is not parameterized } var newTArgs []Type - assert(t.targs.Len() == t.TypeParams().Len()) + assert(t.targs.Len() == t.orig.TypeParams().Len()) // already instantiated dump(">>> %s already instantiated", t) @@ -201,7 +207,7 @@ func (subst *subster) typ(typ Type) Type { if new_targ != targ { dump(">>> substituted %d targ %s => %s", i, targ, new_targ) if newTArgs == nil { - newTArgs = make([]Type, t.TypeParams().Len()) + newTArgs = make([]Type, t.orig.TypeParams().Len()) copy(newTArgs, t.targs.list()) } newTArgs[i] = new_targ @@ -221,25 +227,22 @@ func (subst *subster) typ(typ Type) Type { return named } - // Create a new named type and populate the environment to avoid endless + t.orig.resolve(subst.env) + // Create a new instance and populate the environment to avoid endless // recursion. The position used here is irrelevant because validation only // occurs on t (we don't call validType on named), but we use subst.pos to // help with debugging. - tname := NewTypeName(subst.pos, t.obj.pkg, t.obj.name, nil) - t.load() - // It's ok to provide a nil *Checker because the newly created type - // doesn't need to be (lazily) expanded; it's expanded below. - named := (*Checker)(nil).newNamed(tname, t.orig, nil, t.tparams, t.methods) // t is loaded, so tparams and methods are available - named.targs = NewTypeList(newTArgs) - subst.env.typeForHash(h, named) - t.expand(subst.env) // must happen after env update to avoid infinite recursion - - // do the substitution - dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, newTArgs) - named.underlying = subst.typOrNil(t.underlying) - dump(">>> underlying: %v", named.underlying) + named := subst.check.instance(subst.pos, t.orig, newTArgs, subst.env).(*Named) + // TODO(rfindley): we probably don't need to resolve here. Investigate if + // this can be removed. + named.resolve(subst.env) assert(named.underlying != nil) - named.fromRHS = named.underlying // for consistency, though no cycle detection is necessary + + // Note that if we were to expose substitution more generally (not just in + // the context of a declaration), we'd have to substitute in + // named.underlying as well. + // + // But this is unnecessary for now. return named diff --git a/src/go/types/testdata/fixedbugs/issue47887.go2 b/src/go/types/testdata/fixedbugs/issue47887.go2 new file mode 100644 index 0000000000..4c4fc2fda8 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue47887.go2 @@ -0,0 +1,28 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type Fooer[t any] interface { + foo(Barer[t]) +} +type Barer[t any] interface { + bar(Bazer[t]) +} +type Bazer[t any] interface { + Fooer[t] + baz(t) +} + +type Int int + +func (n Int) baz(int) {} +func (n Int) foo(b Barer[int]) { b.bar(n) } + +type F[t any] interface { f(G[t]) } +type G[t any] interface { g(H[t]) } +type H[t any] interface { F[t] } + +type T struct{} +func (n T) f(b G[T]) { b.g(n) } diff --git a/src/go/types/type.go b/src/go/types/type.go index b9634cf6f6..31149cfd36 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -114,7 +114,7 @@ func asInterface(t Type) *Interface { func asNamed(t Type) *Named { e, _ := t.(*Named) if e != nil { - e.expand(nil) + e.resolve(nil) } return e } -- GitLab From bf26e43d0f9a6c9d43c206877917e66f0fc24a19 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Fri, 10 Sep 2021 15:12:57 -0400 Subject: [PATCH 1142/2500] go/types: eliminate Named.instPos We no longer need to use the nilness of Named.instPos to signal whether instance expansion has occurred, so remove it from the Named struct by instead closing over the instantiation position in the resolver. This means we cannot print instance markers for unexpanded instances: instances may escape the type checking pass without being fully expanded, and we can not check whether they have been expanded in a concurrency-safe way without introducing a more heavy-weight syncronization mechanism. With this change, instantiation should be concurrency safe, modulo bugs of course as we have little test coverage of concurrency (see #47729). Fixes #47910 Change-Id: Ifeef6df296f00105579554b333a44d08aae113c9 Reviewed-on: https://go-review.googlesource.com/c/go/+/349411 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/internal/gcimporter/gcimporter_test.go | 3 --- src/go/types/environment.go | 7 ------- src/go/types/errors.go | 2 +- src/go/types/errors_test.go | 1 - src/go/types/instantiate.go | 5 +++-- src/go/types/named.go | 8 +++----- src/go/types/sizeof_test.go | 2 +- src/go/types/subst.go | 3 --- src/go/types/typestring.go | 10 ---------- 9 files changed, 8 insertions(+), 33 deletions(-) diff --git a/src/go/internal/gcimporter/gcimporter_test.go b/src/go/internal/gcimporter/gcimporter_test.go index 9f4345d8f9..3a9ed79df6 100644 --- a/src/go/internal/gcimporter/gcimporter_test.go +++ b/src/go/internal/gcimporter/gcimporter_test.go @@ -238,9 +238,6 @@ func TestImportTypeparamTests(t *testing.T) { func sanitizeObjectString(s string) string { var runes []rune for _, r := range s { - if r == '#' { - continue // trim instance markers - } if '₀' <= r && r < '₀'+10 { continue // trim type parameter subscripts } diff --git a/src/go/types/environment.go b/src/go/types/environment.go index 93383efe1a..61fc3c5348 100644 --- a/src/go/types/environment.go +++ b/src/go/types/environment.go @@ -50,13 +50,6 @@ func (env *Environment) typeHash(typ Type, targs []Type) string { h.typ(typ) } - if debug { - // there should be no instance markers in type hashes - for _, b := range buf.Bytes() { - assert(b != instanceMarker) - } - } - return buf.String() } diff --git a/src/go/types/errors.go b/src/go/types/errors.go index 933de93d85..2d48fe14da 100644 --- a/src/go/types/errors.go +++ b/src/go/types/errors.go @@ -265,7 +265,7 @@ func stripAnnotations(s string) string { var b strings.Builder for _, r := range s { // strip #'s and subscript digits - if r != instanceMarker && !('₀' <= r && r < '₀'+10) { // '₀' == U+2080 + if r < '₀' || '₀'+10 <= r { // '₀' == U+2080 b.WriteRune(r) } } diff --git a/src/go/types/errors_test.go b/src/go/types/errors_test.go index fdbe07cae0..942a9fdd4c 100644 --- a/src/go/types/errors_test.go +++ b/src/go/types/errors_test.go @@ -15,7 +15,6 @@ func TestStripAnnotations(t *testing.T) { {"foo", "foo"}, {"foo₀", "foo"}, {"foo(T₀)", "foo(T)"}, - {"#foo(T₀)", "foo(T)"}, } { got := stripAnnotations(test.in) if got != test.want { diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index b74f0db466..b178d1eb3f 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -118,8 +118,9 @@ func (check *Checker) instance(pos token.Pos, typ Type, targs []Type, env *Envir tname := NewTypeName(pos, t.obj.pkg, t.obj.name, nil) named := check.newNamed(tname, t, nil, nil, nil) // methods and tparams are set when named is resolved named.targs = NewTypeList(targs) - named.instPos = &pos - named.resolver = expandNamed + named.resolver = func(env *Environment, n *Named) (*TypeParamList, Type, []*Func) { + return expandNamed(env, n, pos) + } if env != nil { // It's possible that we've lost a race to add named to the environment. // In this case, use whichever instance is recorded in the environment. diff --git a/src/go/types/named.go b/src/go/types/named.go index fd9e1f4461..943d52f0fe 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -17,7 +17,6 @@ type Named struct { orig *Named // original, uninstantiated type fromRHS Type // type (on RHS of declaration) this *Named type is derived of (for cycle reporting) underlying Type // possibly a *Named during setup; never a *Named once set up completely - instPos *token.Pos // position information for lazy instantiation, or nil tparams *TypeParamList // type parameters, or nil targs *TypeList // type arguments (after instantiation), or nil methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily @@ -222,11 +221,11 @@ func (n *Named) setUnderlying(typ Type) { // expandNamed ensures that the underlying type of n is instantiated. // The underlying type will be Typ[Invalid] if there was an error. -func expandNamed(env *Environment, n *Named) (*TypeParamList, Type, []*Func) { +func expandNamed(env *Environment, n *Named, instPos token.Pos) (*TypeParamList, Type, []*Func) { n.orig.resolve(env) var u Type - if n.check.validateTArgLen(*n.instPos, n.orig.tparams.Len(), n.targs.Len()) { + if n.check.validateTArgLen(instPos, n.orig.tparams.Len(), n.targs.Len()) { // TODO(rfindley): handling an optional Checker and Environment here (and // in subst) feels overly complicated. Can we simplify? if env == nil { @@ -245,11 +244,10 @@ func expandNamed(env *Environment, n *Named) (*TypeParamList, Type, []*Func) { // shouldn't return that instance from expand. env.typeForHash(h, n) } - u = n.check.subst(*n.instPos, n.orig.underlying, makeSubstMap(n.orig.tparams.list(), n.targs.list()), env) + u = n.check.subst(instPos, n.orig.underlying, makeSubstMap(n.orig.tparams.list(), n.targs.list()), env) } else { u = Typ[Invalid] } - n.instPos = nil return n.orig.tparams, u, n.orig.methods } diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index f64f732884..f418e037a9 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -30,7 +30,7 @@ func TestSizeof(t *testing.T) { {Interface{}, 44, 88}, {Map{}, 16, 32}, {Chan{}, 12, 24}, - {Named{}, 72, 136}, + {Named{}, 68, 128}, {TypeParam{}, 28, 48}, {term{}, 12, 24}, {top{}, 0, 0}, diff --git a/src/go/types/subst.go b/src/go/types/subst.go index d9dab10e00..a063dd0a07 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -8,9 +8,6 @@ package types import "go/token" -// TODO(rFindley) decide error codes for the errors in this file, and check -// if error spans can be improved - type substMap map[*TypeParam]Type // makeSubstMap creates a new substitution map mapping tpars[i] to targs[i]. diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 7e971c0325..eadc50a754 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -65,9 +65,6 @@ func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) { newTypeWriter(buf, qf).signature(sig) } -// instanceMarker is the prefix for an instantiated type in unexpanded form. -const instanceMarker = '#' - type typeWriter struct { buf *bytes.Buffer seen map[Type]bool @@ -226,13 +223,6 @@ func (w *typeWriter) typ(typ Type) { } case *Named: - // Instance markers indicate unexpanded instantiated - // types. Write them to aid debugging, but don't write - // them when we need an instance hash: whether a type - // is fully expanded or not doesn't matter for identity. - if w.env == nil && t.instPos != nil { - w.byte(instanceMarker) - } w.typePrefix(t) w.typeName(t.obj) if t.targs != nil { -- GitLab From a0f3129466744d22746b93e65ff3714f1507b6a3 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Fri, 10 Sep 2021 16:28:01 -0400 Subject: [PATCH 1143/2500] go/types: instantiate methods when instantiating Named types In the API proposal we decided that instantiation must also instantiate methods. This CL does that, and eliminates the special handling for lazy instantiation in lookupMethod. It is possible that we expand an instance before all method signatures have been type-checked, so for simplicity we introduce a new flag on Func, 'isIncompleteMethod', which controls whether we must fully substitute methods before using them. We could avoid this flag by using some convention for the structure of an incomplete method (such as the receiver has no position), but in practice using a flag was cleaner and didn't increase the size of the Func struct. Updates #47916 Change-Id: I352baa6664cd07f61b06924744382897805f9d29 Reviewed-on: https://go-review.googlesource.com/c/go/+/349412 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/call.go | 48 ------------------- src/go/types/decl.go | 6 +++ src/go/types/infer.go | 1 + src/go/types/instantiate_test.go | 39 ++++++++++++++++ src/go/types/lookup.go | 24 ---------- src/go/types/named.go | 79 +++++++++++++++++++++++++++----- src/go/types/object.go | 5 +- src/go/types/sizeof_test.go | 2 +- src/go/types/subst.go | 4 +- 9 files changed, 119 insertions(+), 89 deletions(-) diff --git a/src/go/types/call.go b/src/go/types/call.go index 4de5fed46e..4d14e31730 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -532,54 +532,6 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { // methods may not have a fully set up signature yet if m, _ := obj.(*Func); m != nil { check.objDecl(m, nil) - // If m has a parameterized receiver type, infer the type arguments from - // the actual receiver provided and then substitute the type parameters in - // the signature accordingly. - // TODO(gri) factor this code out - sig := m.typ.(*Signature) - if sig.RecvTypeParams().Len() > 0 { - // For inference to work, we must use the receiver type - // matching the receiver in the actual method declaration. - // If the method is embedded, the matching receiver is the - // embedded struct or interface that declared the method. - // Traverse the embedding to find that type (issue #44688). - recv := x.typ - for i := 0; i < len(index)-1; i++ { - // The embedded type is either a struct or a pointer to - // a struct except for the last one (which we don't need). - recv = asStruct(derefStructPtr(recv)).Field(index[i]).typ - } - - // The method may have a pointer receiver, but the actually provided receiver - // may be a (hopefully addressable) non-pointer value, or vice versa. Here we - // only care about inferring receiver type parameters; to make the inference - // work, match up pointer-ness of receiver and argument. - if ptrRecv := isPointer(sig.recv.typ); ptrRecv != isPointer(recv) { - if ptrRecv { - recv = NewPointer(recv) - } else { - recv = recv.(*Pointer).base - } - } - // Disable reporting of errors during inference below. If we're unable to infer - // the receiver type arguments here, the receiver must be be otherwise invalid - // and an error has been reported elsewhere. - arg := operand{mode: variable, expr: x.expr, typ: recv} - targs := check.infer(m, sig.RecvTypeParams().list(), nil, NewTuple(sig.recv), []*operand{&arg}, false /* no error reporting */) - if targs == nil { - // We may reach here if there were other errors (see issue #40056). - goto Error - } - // Don't modify m. Instead - for now - make a copy of m and use that instead. - // (If we modify m, some tests will fail; possibly because the m is in use.) - // TODO(gri) investigate and provide a correct explanation here - copy := *m - copy.typ = check.subst(e.Pos(), m.typ, makeSubstMap(sig.RecvTypeParams().list(), targs), nil) - obj = © - } - // TODO(gri) we also need to do substitution for parameterized interface methods - // (this breaks code in testdata/linalg.go2 at the moment) - // 12/20/2019: Is this TODO still correct? } if x.mode == typexpr { diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 7f157f528a..0fdcfa8023 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -65,6 +65,12 @@ func (check *Checker) objDecl(obj Object, def *Named) { }() } + // Funcs with m.instRecv set have not yet be completed. Complete them now + // so that they have a type when objDecl exits. + if m, _ := obj.(*Func); m != nil && m.instRecv != nil { + check.completeMethod(check.conf.Environment, m) + } + // Checking the declaration of obj means inferring its type // (and possibly its value, for constants). // An object's type (and thus the object) may be in one of diff --git a/src/go/types/infer.go b/src/go/types/infer.go index 7314a614d0..18c5119177 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -28,6 +28,7 @@ import ( // // Constraint type inference is used after each step to expand the set of type arguments. // +// TODO(rfindley): remove the report parameter: is no longer needed. func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, params *Tuple, args []*operand, report bool) (result []Type) { if debug { defer func() { diff --git a/src/go/types/instantiate_test.go b/src/go/types/instantiate_test.go index 0b09bfebe3..851800e76d 100644 --- a/src/go/types/instantiate_test.go +++ b/src/go/types/instantiate_test.go @@ -70,3 +70,42 @@ func TestInstantiateNonEquality(t *testing.T) { t.Errorf("instance from pkg1 (%s) is identical to instance from pkg2 (%s)", res1, res2) } } + +func TestMethodInstantiation(t *testing.T) { + const prefix = genericPkg + `p + +type T[P any] struct{} + +var X T[int] + +` + tests := []struct { + decl string + want string + }{ + {"func (r T[P]) m() P", "func (T[int]).m() int"}, + {"func (r T[P]) m(P)", "func (T[int]).m(int)"}, + {"func (r T[P]) m() func() P", "func (T[int]).m() func() int"}, + {"func (r T[P]) m() T[P]", "func (T[int]).m() T[int]"}, + {"func (r T[P]) m(T[P])", "func (T[int]).m(T[int])"}, + {"func (r T[P]) m(T[P], P, string)", "func (T[int]).m(T[int], int, string)"}, + {"func (r T[P]) m(T[P], T[string], T[int])", "func (T[int]).m(T[int], T[string], T[int])"}, + } + + for _, test := range tests { + src := prefix + test.decl + pkg, err := pkgFor(".", src, nil) + if err != nil { + t.Fatal(err) + } + typ := pkg.Scope().Lookup("X").Type().(*Named) + obj, _, _ := LookupFieldOrMethod(typ, false, pkg, "m") + m, _ := obj.(*Func) + if m == nil { + t.Fatalf(`LookupFieldOrMethod(%s, "m") = %v, want func m`, typ, obj) + } + if got := ObjectString(m, RelativeTo(pkg)); got != test.want { + t.Errorf("instantiated %q, want %q", got, test.want) + } + } +} diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index cc7f24d97b..a270159499 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -6,8 +6,6 @@ package types -import "go/token" - // Internal use of LookupFieldOrMethod: If the obj result is a method // associated with a concrete (non-interface) type, the method's signature // may not be fully set up. Call Checker.objDecl(obj, nil) before accessing @@ -342,8 +340,6 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, } // A concrete type implements T if it implements all methods of T. - Vd, _ := deref(V) - Vn := asNamed(Vd) for _, m := range T.typeSet().methods { // TODO(gri) should this be calling lookupFieldOrMethod instead (and why not)? obj, _, _ := lookupFieldOrMethod(V, false, m.pkg, m.name) @@ -378,26 +374,6 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, panic("method with type parameters") } - // If V is a (instantiated) generic type, its methods are still - // parameterized using the original (declaration) receiver type - // parameters (subst simply copies the existing method list, it - // does not instantiate the methods). - // In order to compare the signatures, substitute the receiver - // type parameters of ftyp with V's instantiation type arguments. - // This lazily instantiates the signature of method f. - if Vn != nil && Vn.TypeParams().Len() > 0 { - // Be careful: The number of type arguments may not match - // the number of receiver parameters. If so, an error was - // reported earlier but the length discrepancy is still - // here. Exit early in this case to prevent an assertion - // failure in makeSubstMap. - // TODO(gri) Can we avoid this check by fixing the lengths? - if len(ftyp.RecvTypeParams().list()) != Vn.targs.Len() { - return - } - ftyp = check.subst(token.NoPos, ftyp, makeSubstMap(ftyp.RecvTypeParams().list(), Vn.targs.list()), nil).(*Signature) - } - // If the methods have type parameters we don't care whether they // are the same or not, as long as they match up. Use unification // to see if they can be made to match. diff --git a/src/go/types/named.go b/src/go/types/named.go index 943d52f0fe..66ae012379 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -221,16 +221,17 @@ func (n *Named) setUnderlying(typ Type) { // expandNamed ensures that the underlying type of n is instantiated. // The underlying type will be Typ[Invalid] if there was an error. -func expandNamed(env *Environment, n *Named, instPos token.Pos) (*TypeParamList, Type, []*Func) { +func expandNamed(env *Environment, n *Named, instPos token.Pos) (tparams *TypeParamList, underlying Type, methods []*Func) { n.orig.resolve(env) - var u Type - if n.check.validateTArgLen(instPos, n.orig.tparams.Len(), n.targs.Len()) { + check := n.check + + if check.validateTArgLen(instPos, n.orig.tparams.Len(), n.targs.Len()) { // TODO(rfindley): handling an optional Checker and Environment here (and // in subst) feels overly complicated. Can we simplify? if env == nil { - if n.check != nil { - env = n.check.conf.Environment + if check != nil { + env = check.conf.Environment } else { // If we're instantiating lazily, we might be outside the scope of a // type-checking pass. In that case we won't have a pre-existing @@ -239,16 +240,72 @@ func expandNamed(env *Environment, n *Named, instPos token.Pos) (*TypeParamList, env = NewEnvironment() } h := env.typeHash(n.orig, n.targs.list()) - // add the instance to the environment to avoid infinite recursion. - // addInstance may return a different, existing instance, but we - // shouldn't return that instance from expand. + // ensure that an instance is recorded for h to avoid infinite recursion. env.typeForHash(h, n) } - u = n.check.subst(instPos, n.orig.underlying, makeSubstMap(n.orig.tparams.list(), n.targs.list()), env) + smap := makeSubstMap(n.orig.tparams.list(), n.targs.list()) + underlying = n.check.subst(instPos, n.orig.underlying, smap, env) + for i := 0; i < n.orig.NumMethods(); i++ { + origm := n.orig.Method(i) + + // During type checking origm may not have a fully set up type, so defer + // instantiation of its signature until later. + m := NewFunc(origm.pos, origm.pkg, origm.name, nil) + m.hasPtrRecv = origm.hasPtrRecv + // Setting instRecv here allows us to complete later (we need the + // instRecv to get targs and the original method). + m.instRecv = n + + methods = append(methods, m) + } + } else { + underlying = Typ[Invalid] + } + + // Methods should not escape the type checker API without being completed. If + // we're in the context of a type checking pass, we need to defer this until + // later (not all methods may have types). + completeMethods := func() { + for _, m := range methods { + if m.instRecv != nil { + check.completeMethod(env, m) + } + } + } + if check != nil { + check.later(completeMethods) } else { - u = Typ[Invalid] + completeMethods() } - return n.orig.tparams, u, n.orig.methods + + return n.orig.tparams, underlying, methods +} + +func (check *Checker) completeMethod(env *Environment, m *Func) { + assert(m.instRecv != nil) + rtyp := m.instRecv + m.instRecv = nil + m.setColor(black) + + assert(rtyp.TypeArgs().Len() > 0) + + // Look up the original method. + _, orig := lookupMethod(rtyp.orig.methods, rtyp.obj.pkg, m.name) + assert(orig != nil) + if check != nil { + check.objDecl(orig, nil) + } + origSig := orig.typ.(*Signature) + if origSig.RecvTypeParams().Len() != rtyp.targs.Len() { + m.typ = origSig // or new(Signature), but we can't use Typ[Invalid]: Funcs must have Signature type + return // error reported elsewhere + } + + smap := makeSubstMap(origSig.RecvTypeParams().list(), rtyp.targs.list()) + sig := check.subst(orig.pos, origSig, smap, env).(*Signature) + sig.recv = NewParam(origSig.recv.pos, origSig.recv.pkg, origSig.recv.name, rtyp) + + m.typ = sig } // safeUnderlying returns the underlying of typ without expanding instances, to diff --git a/src/go/types/object.go b/src/go/types/object.go index 7f6f8a2550..454b714458 100644 --- a/src/go/types/object.go +++ b/src/go/types/object.go @@ -317,7 +317,8 @@ func (*Var) isDependency() {} // a variable may be a dependency of an initializa // An abstract method may belong to many interfaces due to embedding. type Func struct { object - hasPtrRecv bool // only valid for methods that don't have a type yet + instRecv *Named // if non-nil, the receiver type for an incomplete instance method + hasPtrRecv bool // only valid for methods that don't have a type yet } // NewFunc returns a new function with the given signature, representing @@ -328,7 +329,7 @@ func NewFunc(pos token.Pos, pkg *Package, name string, sig *Signature) *Func { if sig != nil { typ = sig } - return &Func{object{nil, pos, pkg, name, typ, 0, colorFor(typ), token.NoPos}, false} + return &Func{object{nil, pos, pkg, name, typ, 0, colorFor(typ), token.NoPos}, nil, false} } // FullName returns the package- or receiver-type-qualified name of diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index f418e037a9..0e3c0064a0 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -40,7 +40,7 @@ func TestSizeof(t *testing.T) { {Const{}, 48, 88}, {TypeName{}, 40, 72}, {Var{}, 44, 80}, - {Func{}, 44, 80}, + {Func{}, 48, 88}, {Label{}, 44, 80}, {Builtin{}, 44, 80}, {Nil{}, 40, 72}, diff --git a/src/go/types/subst.go b/src/go/types/subst.go index a063dd0a07..3491541dcb 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -70,7 +70,6 @@ func (check *Checker) subst(pos token.Pos, typ Type, smap substMap, env *Environ env = NewEnvironment() } subst.env = env - return subst.typ(typ) } @@ -125,8 +124,7 @@ func (subst *subster) typ(typ Type) Type { if recv != t.recv || params != t.params || results != t.results { return &Signature{ rparams: t.rparams, - // TODO(rFindley) why can't we nil out tparams here, rather than in - // instantiate above? + // TODO(rFindley) why can't we nil out tparams here, rather than in instantiate? tparams: t.tparams, scope: t.scope, recv: recv, -- GitLab From cb4e1de0213c836983d1b441386c53e1a66e1b0a Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sat, 11 Sep 2021 23:06:41 -0400 Subject: [PATCH 1144/2500] go/types: minor cleanup of instantiation This CL addresses a couple TODOs related to instantiation: - factor out resolving the best environment - don't eagerly resolve substituted instances Change-Id: I4a5de7ea7939b6f272991071f591d622dec04b53 Reviewed-on: https://go-review.googlesource.com/c/go/+/349429 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/named.go | 38 ++++++++++++++++++++++---------------- src/go/types/subst.go | 31 +++++++------------------------ 2 files changed, 29 insertions(+), 40 deletions(-) diff --git a/src/go/types/named.go b/src/go/types/named.go index 66ae012379..00fde16445 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -219,6 +219,21 @@ func (n *Named) setUnderlying(typ Type) { } } +// bestEnv returns the best available environment. In order of preference: +// - the given env, if non-nil +// - the Checker env, if check is non-nil +// - a new environment +func (check *Checker) bestEnv(env *Environment) *Environment { + if env != nil { + return env + } + if check != nil { + assert(check.conf.Environment != nil) + return check.conf.Environment + } + return NewEnvironment() +} + // expandNamed ensures that the underlying type of n is instantiated. // The underlying type will be Typ[Invalid] if there was an error. func expandNamed(env *Environment, n *Named, instPos token.Pos) (tparams *TypeParamList, underlying Type, methods []*Func) { @@ -227,24 +242,15 @@ func expandNamed(env *Environment, n *Named, instPos token.Pos) (tparams *TypePa check := n.check if check.validateTArgLen(instPos, n.orig.tparams.Len(), n.targs.Len()) { - // TODO(rfindley): handling an optional Checker and Environment here (and - // in subst) feels overly complicated. Can we simplify? - if env == nil { - if check != nil { - env = check.conf.Environment - } else { - // If we're instantiating lazily, we might be outside the scope of a - // type-checking pass. In that case we won't have a pre-existing - // environment, but don't want to create a duplicate of the current - // instance in the process of expansion. - env = NewEnvironment() - } - h := env.typeHash(n.orig, n.targs.list()) - // ensure that an instance is recorded for h to avoid infinite recursion. - env.typeForHash(h, n) - } + // We must always have an env, to avoid infinite recursion. + env = check.bestEnv(env) + h := env.typeHash(n.orig, n.targs.list()) + // ensure that an instance is recorded for h to avoid infinite recursion. + env.typeForHash(h, n) + smap := makeSubstMap(n.orig.tparams.list(), n.targs.list()) underlying = n.check.subst(instPos, n.orig.underlying, smap, env) + for i := 0; i < n.orig.NumMethods(); i++ { origm := n.orig.Method(i) diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 3491541dcb..16aafd622e 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -52,24 +52,12 @@ func (check *Checker) subst(pos token.Pos, typ Type, smap substMap, env *Environ } // general case - var subst subster - subst.pos = pos - subst.smap = smap - - if check != nil { - subst.check = check - if env == nil { - env = check.conf.Environment - } - } - if env == nil { - // If we don't have a *Checker and its global type map, - // use a local version. Besides avoiding duplicate work, - // the type map prevents infinite recursive substitution - // for recursive types (example: type T[P any] *T[P]). - env = NewEnvironment() + subst := subster{ + pos: pos, + smap: smap, + check: check, + env: check.bestEnv(env), } - subst.env = env return subst.typ(typ) } @@ -227,11 +215,8 @@ func (subst *subster) typ(typ Type) Type { // recursion. The position used here is irrelevant because validation only // occurs on t (we don't call validType on named), but we use subst.pos to // help with debugging. - named := subst.check.instance(subst.pos, t.orig, newTArgs, subst.env).(*Named) - // TODO(rfindley): we probably don't need to resolve here. Investigate if - // this can be removed. - named.resolve(subst.env) - assert(named.underlying != nil) + t.orig.resolve(subst.env) + return subst.check.instance(subst.pos, t.orig, newTArgs, subst.env) // Note that if we were to expose substitution more generally (not just in // the context of a declaration), we'd have to substitute in @@ -239,8 +224,6 @@ func (subst *subster) typ(typ Type) Type { // // But this is unnecessary for now. - return named - case *TypeParam: return subst.smap.lookup(t) -- GitLab From 0bb40b08c4884952d7facce3135ff9e50847763f Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sun, 12 Sep 2021 14:33:04 -0400 Subject: [PATCH 1145/2500] go/types: implement Identical for *Union types This aligns with the API proposal (#47916). Change-Id: I732e5b107e729718ed37e053ad3f434993a97ecd Reviewed-on: https://go-review.googlesource.com/c/go/+/349413 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/api_test.go | 42 ++++++++++++++++++++++++++++++++++++++ src/go/types/predicates.go | 9 ++++++++ 2 files changed, 51 insertions(+) diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index 49c054bd7d..4472748685 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -1621,6 +1621,48 @@ func TestIdentical_issue15173(t *testing.T) { } } +func TestIdenticalUnions(t *testing.T) { + tname := NewTypeName(token.NoPos, nil, "myInt", nil) + myInt := NewNamed(tname, Typ[Int], nil) + tmap := map[string]*Term{ + "int": NewTerm(false, Typ[Int]), + "~int": NewTerm(true, Typ[Int]), + "string": NewTerm(false, Typ[String]), + "~string": NewTerm(true, Typ[String]), + "myInt": NewTerm(false, myInt), + } + makeUnion := func(s string) *Union { + parts := strings.Split(s, "|") + var terms []*Term + for _, p := range parts { + term := tmap[p] + if term == nil { + t.Fatalf("missing term %q", p) + } + terms = append(terms, term) + } + return NewUnion(terms) + } + for _, test := range []struct { + x, y string + want bool + }{ + // These tests are just sanity checks. The tests for type sets and + // interfaces provide much more test coverage. + {"int|~int", "~int", true}, + {"myInt|~int", "~int", true}, + {"int|string", "string|int", true}, + {"int|int|string", "string|int", true}, + {"myInt|string", "int|string", false}, + } { + x := makeUnion(test.x) + y := makeUnion(test.y) + if got := Identical(x, y); got != test.want { + t.Errorf("Identical(%v, %v) = %t", test.x, test.y, got) + } + } +} + func TestIssue15305(t *testing.T) { const src = "package p; func f() int16; var _ = f(undef)" fset := token.NewFileSet() diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 9aa565b68a..a5d4be9bcc 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -6,6 +6,8 @@ package types +import "go/token" + // isNamed reports whether typ has a name. // isNamed may be called with types that are not fully set up. func isNamed(typ Type) bool { @@ -225,6 +227,13 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { identical(x.results, y.results, cmpTags, p) } + case *Union: + if y, _ := y.(*Union); y != nil { + xset := computeUnionTypeSet(nil, token.NoPos, x) + yset := computeUnionTypeSet(nil, token.NoPos, y) + return xset.terms.equal(yset.terms) + } + case *Interface: // Two interface types are identical if they describe the same type sets. // With the existing implementation restriction, this simplifies to: -- GitLab From c7f2f51fed15b410dea5f608420858b401887d0a Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Mon, 13 Sep 2021 10:58:25 -0700 Subject: [PATCH 1146/2500] cmd/go: remove subcommand prefix from error messages For example, errors that started before with "go mod download: " now start with "go: " instead. Previously, we had a mix of errors with and without subcommand prefixes, even in packages like modload that ostensibly aren't tied to any specific command. This change makes usage more consistent, which makes refactoring much easier. These prefixes didn't add useful information: the user should know the subcommand they just ran. But see CL 347152 for an attempt at making the opposite change: always printing the subcommand prefix. Note that there are a number of errors that don't start with "go: " or any subcommand prefix. This CL doesn't affect those. Change-Id: I16430d8c39ea3f4d0870f55a5205f06fb21943c0 Reviewed-on: https://go-review.googlesource.com/c/go/+/349597 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/base/tool.go | 2 +- src/cmd/go/internal/bug/bug.go | 2 +- src/cmd/go/internal/clean/clean.go | 16 +++--- src/cmd/go/internal/envcmd/env.go | 32 ++++++------ src/cmd/go/internal/get/get.go | 10 ++-- src/cmd/go/internal/list/list.go | 10 ++-- src/cmd/go/internal/modcmd/download.go | 10 ++-- src/cmd/go/internal/modcmd/edit.go | 50 +++++++++---------- src/cmd/go/internal/modcmd/editwork.go | 26 +++++----- src/cmd/go/internal/modcmd/graph.go | 2 +- src/cmd/go/internal/modcmd/init.go | 2 +- src/cmd/go/internal/modcmd/tidy.go | 2 +- src/cmd/go/internal/modcmd/vendor.go | 34 ++++++------- src/cmd/go/internal/modcmd/verify.go | 2 +- src/cmd/go/internal/modcmd/why.go | 4 +- src/cmd/go/internal/modget/get.go | 34 ++++++------- src/cmd/go/internal/modget/query.go | 8 +-- src/cmd/go/internal/modload/load.go | 6 +-- src/cmd/go/internal/run/run.go | 12 ++--- src/cmd/go/internal/test/test.go | 2 +- src/cmd/go/internal/test/testflag.go | 2 +- src/cmd/go/internal/tool/tool.go | 6 +-- src/cmd/go/internal/version/version.go | 10 +++- src/cmd/go/internal/vet/vet.go | 2 +- src/cmd/go/internal/vet/vetflag.go | 4 +- src/cmd/go/internal/work/action.go | 4 +- src/cmd/go/internal/work/build.go | 26 +++++----- src/cmd/go/internal/work/init.go | 15 +++--- .../go/testdata/script/build_i_deprecate.txt | 6 +-- src/cmd/go/testdata/script/env_unset.txt | 6 +-- src/cmd/go/testdata/script/env_write.txt | 18 +++---- src/cmd/go/testdata/script/get_go_file.txt | 12 ++--- .../get_insecure_no_longer_supported.txt | 4 +- src/cmd/go/testdata/script/gopath_install.txt | 2 +- src/cmd/go/testdata/script/gopath_local.txt | 4 +- src/cmd/go/testdata/script/govcs.txt | 26 +++++----- src/cmd/go/testdata/script/list_shadow.txt | 2 +- src/cmd/go/testdata/script/mod_bad_domain.txt | 2 +- src/cmd/go/testdata/script/mod_dot.txt | 6 +-- src/cmd/go/testdata/script/mod_download.txt | 10 ++-- src/cmd/go/testdata/script/mod_edit.txt | 10 ++-- .../go/testdata/script/mod_get_changes.txt | 12 ++--- .../script/mod_get_deprecate_install.txt | 4 +- .../go/testdata/script/mod_get_downgrade.txt | 4 +- .../script/mod_get_downgrade_missing.txt | 2 +- .../go/testdata/script/mod_get_go_file.txt | 10 ++-- src/cmd/go/testdata/script/mod_get_main.txt | 14 +++--- .../go/testdata/script/mod_get_newcycle.txt | 2 +- src/cmd/go/testdata/script/mod_get_nopkgs.txt | 4 +- src/cmd/go/testdata/script/mod_get_patch.txt | 6 +-- .../go/testdata/script/mod_get_patchcycle.txt | 2 +- .../go/testdata/script/mod_get_patchmod.txt | 2 +- .../go/testdata/script/mod_get_patterns.txt | 4 +- .../go/testdata/script/mod_get_pkgtags.txt | 4 +- .../testdata/script/mod_get_private_vcs.txt | 2 +- .../go/testdata/script/mod_get_replaced.txt | 2 +- src/cmd/go/testdata/script/mod_get_split.txt | 2 +- src/cmd/go/testdata/script/mod_get_svn.txt | 2 +- src/cmd/go/testdata/script/mod_get_wild.txt | 2 +- .../go/testdata/script/mod_getmode_vendor.txt | 6 +-- src/cmd/go/testdata/script/mod_gonoproxy.txt | 4 +- .../script/mod_install_pkg_version.txt | 22 ++++---- .../go/testdata/script/mod_invalid_path.txt | 2 +- .../testdata/script/mod_invalid_path_plus.txt | 2 +- .../testdata/script/mod_invalid_version.txt | 32 ++++++------ src/cmd/go/testdata/script/mod_list.txt | 4 +- src/cmd/go/testdata/script/mod_list_sums.txt | 2 +- .../script/mod_list_update_nolatest.txt | 2 +- .../go/testdata/script/mod_load_badchain.txt | 6 +-- src/cmd/go/testdata/script/mod_outside.txt | 6 +-- .../testdata/script/mod_prefer_compatible.txt | 2 +- .../go/testdata/script/mod_proxy_invalid.txt | 4 +- src/cmd/go/testdata/script/mod_query.txt | 2 +- .../go/testdata/script/mod_query_empty.txt | 4 +- .../go/testdata/script/mod_query_exclude.txt | 2 +- src/cmd/go/testdata/script/mod_query_main.txt | 10 ++-- .../testdata/script/mod_replace_gopkgin.txt | 2 +- .../script/mod_retract_fix_version.txt | 2 +- .../script/mod_retract_pseudo_base.txt | 2 +- .../go/testdata/script/mod_run_nonmain.txt | 2 +- .../testdata/script/mod_run_pkg_version.txt | 6 +-- .../go/testdata/script/mod_sum_readonly.txt | 6 +-- src/cmd/go/testdata/script/mod_sumdb.txt | 2 +- .../testdata/script/mod_sumdb_file_path.txt | 2 +- .../go/testdata/script/mod_tidy_compat.txt | 2 +- .../script/mod_tidy_compat_ambiguous.txt | 2 +- .../go/testdata/script/mod_tidy_too_new.txt | 4 +- .../go/testdata/script/mod_upgrade_patch.txt | 6 +-- src/cmd/go/testdata/script/mod_vendor.txt | 6 +-- .../go/testdata/script/mod_vendor_auto.txt | 8 +-- .../go/testdata/script/mod_vendor_embed.txt | 4 +- src/cmd/go/testdata/script/run_wildcard.txt | 2 +- src/cmd/go/testdata/script/test_flag.txt | 6 +-- .../go/testdata/script/test_race_install.txt | 2 +- 94 files changed, 353 insertions(+), 348 deletions(-) diff --git a/src/cmd/go/internal/base/tool.go b/src/cmd/go/internal/base/tool.go index d0da65e03c..f927016965 100644 --- a/src/cmd/go/internal/base/tool.go +++ b/src/cmd/go/internal/base/tool.go @@ -36,7 +36,7 @@ func Tool(toolName string) string { } // Give a nice message if there is no tool with that name. if _, err := os.Stat(toolPath); err != nil { - fmt.Fprintf(os.Stderr, "go tool: no such tool %q\n", toolName) + fmt.Fprintf(os.Stderr, "go: no such tool %q\n", toolName) SetExitStatus(2) Exit() } diff --git a/src/cmd/go/internal/bug/bug.go b/src/cmd/go/internal/bug/bug.go index 307527c695..a81ca7d8c3 100644 --- a/src/cmd/go/internal/bug/bug.go +++ b/src/cmd/go/internal/bug/bug.go @@ -40,7 +40,7 @@ func init() { func runBug(ctx context.Context, cmd *base.Command, args []string) { if len(args) > 0 { - base.Fatalf("go bug: bug takes no arguments") + base.Fatalf("go: bug takes no arguments") } var buf bytes.Buffer buf.WriteString(bugHeader) diff --git a/src/cmd/go/internal/clean/clean.go b/src/cmd/go/internal/clean/clean.go index fd4cb20559..1089211f0c 100644 --- a/src/cmd/go/internal/clean/clean.go +++ b/src/cmd/go/internal/clean/clean.go @@ -144,7 +144,7 @@ func runClean(ctx context.Context, cmd *base.Command, args []string) { // This also mimics what os.RemoveAll(dir) would do. if err := os.RemoveAll(d); err != nil && !printedErrors { printedErrors = true - base.Errorf("go clean -cache: %v", err) + base.Errorf("go: %v", err) } } } @@ -157,7 +157,7 @@ func runClean(ctx context.Context, cmd *base.Command, args []string) { if !cfg.BuildN { if err := os.RemoveAll(logFile); err != nil && !printedErrors { printedErrors = true - base.Errorf("go clean -cache: %v", err) + base.Errorf("go: %v", err) } } } @@ -187,7 +187,7 @@ func runClean(ctx context.Context, cmd *base.Command, args []string) { } if err != nil { if _, statErr := os.Stat(dir); !os.IsNotExist(statErr) { - base.Errorf("go clean -testcache: %v", err) + base.Errorf("go: %v", err) } } } @@ -195,14 +195,14 @@ func runClean(ctx context.Context, cmd *base.Command, args []string) { if cleanModcache { if cfg.GOMODCACHE == "" { - base.Fatalf("go clean -modcache: no module cache") + base.Fatalf("go: cannot clean -modcache without a module cache") } if cfg.BuildN || cfg.BuildX { b.Showcmd("", "rm -rf %s", cfg.GOMODCACHE) } if !cfg.BuildN { if err := modfetch.RemoveAll(cfg.GOMODCACHE); err != nil { - base.Errorf("go clean -modcache: %v", err) + base.Errorf("go: %v", err) } } } @@ -245,7 +245,7 @@ func clean(p *load.Package) { } dirs, err := os.ReadDir(p.Dir) if err != nil { - base.Errorf("go clean %s: %v", p.Dir, err) + base.Errorf("go: %s: %v", p.Dir, err) return } @@ -334,7 +334,7 @@ func clean(p *load.Package) { } } if err := os.RemoveAll(filepath.Join(p.Dir, name)); err != nil { - base.Errorf("go clean: %v", err) + base.Errorf("go: %v", err) } } continue @@ -386,5 +386,5 @@ func removeFile(f string) { return } } - base.Errorf("go clean: %v", err) + base.Errorf("go: %v", err) } diff --git a/src/cmd/go/internal/envcmd/env.go b/src/cmd/go/internal/envcmd/env.go index d23d539141..1eb773407e 100644 --- a/src/cmd/go/internal/envcmd/env.go +++ b/src/cmd/go/internal/envcmd/env.go @@ -193,13 +193,13 @@ func argKey(arg string) string { func runEnv(ctx context.Context, cmd *base.Command, args []string) { if *envJson && *envU { - base.Fatalf("go env: cannot use -json with -u") + base.Fatalf("go: cannot use -json with -u") } if *envJson && *envW { - base.Fatalf("go env: cannot use -json with -w") + base.Fatalf("go: cannot use -json with -w") } if *envU && *envW { - base.Fatalf("go env: cannot use -u with -w") + base.Fatalf("go: cannot use -u with -w") } // Handle 'go env -w' and 'go env -u' before calling buildcfg.Check, @@ -277,7 +277,7 @@ func runEnv(ctx context.Context, cmd *base.Command, args []string) { func runEnvW(args []string) { // Process and sanity-check command line. if len(args) == 0 { - base.Fatalf("go env -w: no KEY=VALUE arguments given") + base.Fatalf("go: no KEY=VALUE arguments given") } osEnv := make(map[string]string) for _, e := range cfg.OrigEnv { @@ -289,14 +289,14 @@ func runEnvW(args []string) { for _, arg := range args { i := strings.Index(arg, "=") if i < 0 { - base.Fatalf("go env -w: arguments must be KEY=VALUE: invalid argument: %s", arg) + base.Fatalf("go: arguments must be KEY=VALUE: invalid argument: %s", arg) } key, val := arg[:i], arg[i+1:] if err := checkEnvWrite(key, val); err != nil { - base.Fatalf("go env -w: %v", err) + base.Fatalf("go: %v", err) } if _, ok := add[key]; ok { - base.Fatalf("go env -w: multiple values for key: %s", key) + base.Fatalf("go: multiple values for key: %s", key) } add[key] = val if osVal := osEnv[key]; osVal != "" && osVal != val { @@ -305,13 +305,13 @@ func runEnvW(args []string) { } if err := checkBuildConfig(add, nil); err != nil { - base.Fatalf("go env -w: %v", err) + base.Fatalf("go: %v", err) } gotmp, okGOTMP := add["GOTMPDIR"] if okGOTMP { if !filepath.IsAbs(gotmp) && gotmp != "" { - base.Fatalf("go env -w: GOTMPDIR must be an absolute path") + base.Fatalf("go: GOTMPDIR must be an absolute path") } } @@ -321,18 +321,18 @@ func runEnvW(args []string) { func runEnvU(args []string) { // Process and sanity-check command line. if len(args) == 0 { - base.Fatalf("go env -u: no arguments given") + base.Fatalf("go: 'go env -u' requires an argument") } del := make(map[string]bool) for _, arg := range args { if err := checkEnvWrite(arg, ""); err != nil { - base.Fatalf("go env -u: %v", err) + base.Fatalf("go: %v", err) } del[arg] = true } if err := checkBuildConfig(nil, del); err != nil { - base.Fatalf("go env -u: %v", err) + base.Fatalf("go: %v", err) } updateEnvFile(nil, del) @@ -416,7 +416,7 @@ func printEnvAsJSON(env []cfg.EnvVar) { enc := json.NewEncoder(os.Stdout) enc.SetIndent("", "\t") if err := enc.Encode(m); err != nil { - base.Fatalf("go env -json: %s", err) + base.Fatalf("go: %s", err) } } @@ -494,11 +494,11 @@ func checkEnvWrite(key, val string) error { func updateEnvFile(add map[string]string, del map[string]bool) { file, err := cfg.EnvFile() if file == "" { - base.Fatalf("go env: cannot find go env config: %v", err) + base.Fatalf("go: cannot find go env config: %v", err) } data, err := os.ReadFile(file) if err != nil && (!os.IsNotExist(err) || len(add) == 0) { - base.Fatalf("go env: reading go env config: %v", err) + base.Fatalf("go: reading go env config: %v", err) } lines := strings.SplitAfter(string(data), "\n") @@ -556,7 +556,7 @@ func updateEnvFile(add map[string]string, del map[string]bool) { os.MkdirAll(filepath.Dir(file), 0777) err = os.WriteFile(file, data, 0666) if err != nil { - base.Fatalf("go env: writing go env config: %v", err) + base.Fatalf("go: writing go env config: %v", err) } } } diff --git a/src/cmd/go/internal/get/get.go b/src/cmd/go/internal/get/get.go index 075594b271..b79d3ba86f 100644 --- a/src/cmd/go/internal/get/get.go +++ b/src/cmd/go/internal/get/get.go @@ -114,16 +114,16 @@ func init() { func runGet(ctx context.Context, cmd *base.Command, args []string) { if cfg.ModulesEnabled { // Should not happen: main.go should install the separate module-enabled get code. - base.Fatalf("go get: modules not implemented") + base.Fatalf("go: modules not implemented") } work.BuildInit() if *getF && !*getU { - base.Fatalf("go get: cannot use -f flag without -u") + base.Fatalf("go: cannot use -f flag without -u") } if *getInsecure { - base.Fatalf("go get: -insecure flag is no longer supported; use GOINSECURE instead") + base.Fatalf("go: -insecure flag is no longer supported; use GOINSECURE instead") } // Disable any prompting for passwords by Git itself. @@ -214,11 +214,11 @@ func downloadPaths(patterns []string) []string { // if the argument has no slash or refers to an existing file. if strings.HasSuffix(arg, ".go") { if !strings.Contains(arg, "/") { - base.Errorf("go get %s: arguments must be package or module paths", arg) + base.Errorf("go: %s: arguments must be package or module paths", arg) continue } if fi, err := os.Stat(arg); err == nil && !fi.IsDir() { - base.Errorf("go get: %s exists as a file, but 'go get' requires package arguments", arg) + base.Errorf("go: %s exists as a file, but 'go get' requires package arguments", arg) } } } diff --git a/src/cmd/go/internal/list/list.go b/src/cmd/go/internal/list/list.go index 704d61e7c1..821e622abb 100644 --- a/src/cmd/go/internal/list/list.go +++ b/src/cmd/go/internal/list/list.go @@ -427,12 +427,12 @@ func runList(ctx context.Context, cmd *base.Command, args []string) { } if modload.Init(); !modload.Enabled() { - base.Fatalf("go list -m: not using modules") + base.Fatalf("go: list -m cannot be used with GO111MODULE=off") } modload.LoadModFile(ctx) // Sets cfg.BuildMod as a side-effect. if cfg.BuildMod == "vendor" { - const actionDisabledFormat = "go list -m: can't %s using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)" + const actionDisabledFormat = "go: can't %s using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)" if *listVersions { base.Fatalf(actionDisabledFormat, "determine available versions") @@ -471,11 +471,11 @@ func runList(ctx context.Context, cmd *base.Command, args []string) { if !*listE { for _, m := range mods { if m.Error != nil { - base.Errorf("go list -m: %v", m.Error.Err) + base.Errorf("go: %v", m.Error.Err) } } if err != nil { - base.Errorf("go list -m: %v", err) + base.Errorf("go: %v", err) } base.ExitIfErrors() } @@ -711,7 +711,7 @@ func runList(ctx context.Context, cmd *base.Command, args []string) { } rmods, err := modload.ListModules(ctx, args, mode) if err != nil && !*listE { - base.Errorf("go list -retracted: %v", err) + base.Errorf("go: %v", err) } for i, arg := range args { rmod := rmods[i] diff --git a/src/cmd/go/internal/modcmd/download.go b/src/cmd/go/internal/modcmd/download.go index ff56d05116..0f64785656 100644 --- a/src/cmd/go/internal/modcmd/download.go +++ b/src/cmd/go/internal/modcmd/download.go @@ -87,7 +87,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { // Check whether modules are enabled and whether we're in a module. modload.ForceUseModules = true if !modload.HasModRoot() && len(args) == 0 { - base.Fatalf("go mod download: no modules specified (see 'go help mod download')") + base.Fatalf("go: no modules specified (see 'go help mod download')") } haveExplicitArgs := len(args) > 0 if !haveExplicitArgs { @@ -106,7 +106,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { for _, arg := range args { switch arg { case mainModule.Path, targetAtUpgrade, targetAtPatch: - os.Stderr.WriteString("go mod download: skipping argument " + arg + " that resolves to the main module\n") + os.Stderr.WriteString("go: skipping download of " + arg + " that resolves to the main module\n") } } } @@ -192,7 +192,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { for _, m := range mods { b, err := json.MarshalIndent(m, "", "\t") if err != nil { - base.Fatalf("go mod download: %v", err) + base.Fatalf("go: %v", err) } os.Stdout.Write(append(b, '\n')) if m.Error != "" { @@ -202,7 +202,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { } else { for _, m := range mods { if m.Error != "" { - base.Errorf("go mod download: %v", m.Error) + base.Errorf("go: %v", m.Error) } } base.ExitIfErrors() @@ -222,6 +222,6 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { // (after we've written the checksums for the modules that were downloaded // successfully). if infosErr != nil { - base.Errorf("go mod download: %v", infosErr) + base.Errorf("go: %v", infosErr) } } diff --git a/src/cmd/go/internal/modcmd/edit.go b/src/cmd/go/internal/modcmd/edit.go index bb3d521092..e5182a9590 100644 --- a/src/cmd/go/internal/modcmd/edit.go +++ b/src/cmd/go/internal/modcmd/edit.go @@ -171,15 +171,15 @@ func runEdit(ctx context.Context, cmd *base.Command, args []string) { len(edits) > 0 if !anyFlags { - base.Fatalf("go mod edit: no flags specified (see 'go help mod edit').") + base.Fatalf("go: no flags specified (see 'go help mod edit').") } if *editJSON && *editPrint { - base.Fatalf("go mod edit: cannot use both -json and -print") + base.Fatalf("go: cannot use both -json and -print") } if len(args) > 1 { - base.Fatalf("go mod edit: too many arguments") + base.Fatalf("go: too many arguments") } var gomod string if len(args) == 1 { @@ -190,7 +190,7 @@ func runEdit(ctx context.Context, cmd *base.Command, args []string) { if *editModule != "" { if err := module.CheckImportPath(*editModule); err != nil { - base.Fatalf("go mod: invalid -module: %v", err) + base.Fatalf("go: invalid -module: %v", err) } } @@ -264,15 +264,15 @@ func runEdit(ctx context.Context, cmd *base.Command, args []string) { func parsePathVersion(flag, arg string) (path, version string) { i := strings.Index(arg, "@") if i < 0 { - base.Fatalf("go mod: -%s=%s: need path@version", flag, arg) + base.Fatalf("go: -%s=%s: need path@version", flag, arg) } path, version = strings.TrimSpace(arg[:i]), strings.TrimSpace(arg[i+1:]) if err := module.CheckImportPath(path); err != nil { - base.Fatalf("go mod: -%s=%s: invalid path: %v", flag, arg, err) + base.Fatalf("go: -%s=%s: invalid path: %v", flag, arg, err) } if !allowedVersionArg(version) { - base.Fatalf("go mod: -%s=%s: invalid version %q", flag, arg, version) + base.Fatalf("go: -%s=%s: invalid version %q", flag, arg, version) } return path, version @@ -281,11 +281,11 @@ func parsePathVersion(flag, arg string) (path, version string) { // parsePath parses -flag=arg expecting arg to be path (not path@version). func parsePath(flag, arg string) (path string) { if strings.Contains(arg, "@") { - base.Fatalf("go mod: -%s=%s: need just path, not path@version", flag, arg) + base.Fatalf("go: -%s=%s: need just path, not path@version", flag, arg) } path = arg if err := module.CheckImportPath(path); err != nil { - base.Fatalf("go mod: -%s=%s: invalid path: %v", flag, arg, err) + base.Fatalf("go: -%s=%s: invalid path: %v", flag, arg, err) } return path } @@ -350,7 +350,7 @@ func flagRequire(arg string) { path, version := parsePathVersion("require", arg) edits = append(edits, func(f *modfile.File) { if err := f.AddRequire(path, version); err != nil { - base.Fatalf("go mod: -require=%s: %v", arg, err) + base.Fatalf("go: -require=%s: %v", arg, err) } }) } @@ -360,7 +360,7 @@ func flagDropRequire(arg string) { path := parsePath("droprequire", arg) edits = append(edits, func(f *modfile.File) { if err := f.DropRequire(path); err != nil { - base.Fatalf("go mod: -droprequire=%s: %v", arg, err) + base.Fatalf("go: -droprequire=%s: %v", arg, err) } }) } @@ -370,7 +370,7 @@ func flagExclude(arg string) { path, version := parsePathVersion("exclude", arg) edits = append(edits, func(f *modfile.File) { if err := f.AddExclude(path, version); err != nil { - base.Fatalf("go mod: -exclude=%s: %v", arg, err) + base.Fatalf("go: -exclude=%s: %v", arg, err) } }) } @@ -380,7 +380,7 @@ func flagDropExclude(arg string) { path, version := parsePathVersion("dropexclude", arg) edits = append(edits, func(f *modfile.File) { if err := f.DropExclude(path, version); err != nil { - base.Fatalf("go mod: -dropexclude=%s: %v", arg, err) + base.Fatalf("go: -dropexclude=%s: %v", arg, err) } }) } @@ -389,27 +389,27 @@ func flagDropExclude(arg string) { func flagReplace(arg string) { var i int if i = strings.Index(arg, "="); i < 0 { - base.Fatalf("go mod: -replace=%s: need old[@v]=new[@w] (missing =)", arg) + base.Fatalf("go: -replace=%s: need old[@v]=new[@w] (missing =)", arg) } old, new := strings.TrimSpace(arg[:i]), strings.TrimSpace(arg[i+1:]) if strings.HasPrefix(new, ">") { - base.Fatalf("go mod: -replace=%s: separator between old and new is =, not =>", arg) + base.Fatalf("go: -replace=%s: separator between old and new is =, not =>", arg) } oldPath, oldVersion, err := parsePathVersionOptional("old", old, false) if err != nil { - base.Fatalf("go mod: -replace=%s: %v", arg, err) + base.Fatalf("go: -replace=%s: %v", arg, err) } newPath, newVersion, err := parsePathVersionOptional("new", new, true) if err != nil { - base.Fatalf("go mod: -replace=%s: %v", arg, err) + base.Fatalf("go: -replace=%s: %v", arg, err) } if newPath == new && !modfile.IsDirectoryPath(new) { - base.Fatalf("go mod: -replace=%s: unversioned new path must be local directory", arg) + base.Fatalf("go: -replace=%s: unversioned new path must be local directory", arg) } edits = append(edits, func(f *modfile.File) { if err := f.AddReplace(oldPath, oldVersion, newPath, newVersion); err != nil { - base.Fatalf("go mod: -replace=%s: %v", arg, err) + base.Fatalf("go: -replace=%s: %v", arg, err) } }) } @@ -418,11 +418,11 @@ func flagReplace(arg string) { func flagDropReplace(arg string) { path, version, err := parsePathVersionOptional("old", arg, true) if err != nil { - base.Fatalf("go mod: -dropreplace=%s: %v", arg, err) + base.Fatalf("go: -dropreplace=%s: %v", arg, err) } edits = append(edits, func(f *modfile.File) { if err := f.DropReplace(path, version); err != nil { - base.Fatalf("go mod: -dropreplace=%s: %v", arg, err) + base.Fatalf("go: -dropreplace=%s: %v", arg, err) } }) } @@ -431,11 +431,11 @@ func flagDropReplace(arg string) { func flagRetract(arg string) { vi, err := parseVersionInterval(arg) if err != nil { - base.Fatalf("go mod: -retract=%s: %v", arg, err) + base.Fatalf("go: -retract=%s: %v", arg, err) } edits = append(edits, func(f *modfile.File) { if err := f.AddRetract(vi, ""); err != nil { - base.Fatalf("go mod: -retract=%s: %v", arg, err) + base.Fatalf("go: -retract=%s: %v", arg, err) } }) } @@ -444,11 +444,11 @@ func flagRetract(arg string) { func flagDropRetract(arg string) { vi, err := parseVersionInterval(arg) if err != nil { - base.Fatalf("go mod: -dropretract=%s: %v", arg, err) + base.Fatalf("go: -dropretract=%s: %v", arg, err) } edits = append(edits, func(f *modfile.File) { if err := f.DropRetract(vi); err != nil { - base.Fatalf("go mod: -dropretract=%s: %v", arg, err) + base.Fatalf("go: -dropretract=%s: %v", arg, err) } }) } diff --git a/src/cmd/go/internal/modcmd/editwork.go b/src/cmd/go/internal/modcmd/editwork.go index 29895b1620..235c655387 100644 --- a/src/cmd/go/internal/modcmd/editwork.go +++ b/src/cmd/go/internal/modcmd/editwork.go @@ -118,15 +118,15 @@ func runEditwork(ctx context.Context, cmd *base.Command, args []string) { len(workedits) > 0 if !anyFlags { - base.Fatalf("go mod edit: no flags specified (see 'go help mod edit').") + base.Fatalf("go: no flags specified (see 'go help mod edit').") } if *editworkJSON && *editworkPrint { - base.Fatalf("go mod edit: cannot use both -json and -print") + base.Fatalf("go: cannot use both -json and -print") } if len(args) > 1 { - base.Fatalf("go mod edit: too many arguments") + base.Fatalf("go: 'go mod editwork' accepts at most one argument") } var gowork string if len(args) == 1 { @@ -199,7 +199,7 @@ func flagEditworkDirectory(arg string) { } f.AddDirectory(modload.ToDirectoryPath(arg), modulePath) if err := f.AddDirectory(modload.ToDirectoryPath(arg), ""); err != nil { - base.Fatalf("go mod: -directory=%s: %v", arg, err) + base.Fatalf("go: -directory=%s: %v", arg, err) } }) } @@ -208,7 +208,7 @@ func flagEditworkDirectory(arg string) { func flagEditworkDropDirectory(arg string) { workedits = append(workedits, func(f *modfile.WorkFile) { if err := f.DropDirectory(modload.ToDirectoryPath(arg)); err != nil { - base.Fatalf("go mod: -dropdirectory=%s: %v", arg, err) + base.Fatalf("go: -dropdirectory=%s: %v", arg, err) } }) } @@ -217,27 +217,27 @@ func flagEditworkDropDirectory(arg string) { func flagEditworkReplace(arg string) { var i int if i = strings.Index(arg, "="); i < 0 { - base.Fatalf("go mod: -replace=%s: need old[@v]=new[@w] (missing =)", arg) + base.Fatalf("go: -replace=%s: need old[@v]=new[@w] (missing =)", arg) } old, new := strings.TrimSpace(arg[:i]), strings.TrimSpace(arg[i+1:]) if strings.HasPrefix(new, ">") { - base.Fatalf("go mod: -replace=%s: separator between old and new is =, not =>", arg) + base.Fatalf("go: -replace=%s: separator between old and new is =, not =>", arg) } oldPath, oldVersion, err := parsePathVersionOptional("old", old, false) if err != nil { - base.Fatalf("go mod: -replace=%s: %v", arg, err) + base.Fatalf("go: -replace=%s: %v", arg, err) } newPath, newVersion, err := parsePathVersionOptional("new", new, true) if err != nil { - base.Fatalf("go mod: -replace=%s: %v", arg, err) + base.Fatalf("go: -replace=%s: %v", arg, err) } if newPath == new && !modfile.IsDirectoryPath(new) { - base.Fatalf("go mod: -replace=%s: unversioned new path must be local directory", arg) + base.Fatalf("go: -replace=%s: unversioned new path must be local directory", arg) } workedits = append(workedits, func(f *modfile.WorkFile) { if err := f.AddReplace(oldPath, oldVersion, newPath, newVersion); err != nil { - base.Fatalf("go mod: -replace=%s: %v", arg, err) + base.Fatalf("go: -replace=%s: %v", arg, err) } }) } @@ -246,11 +246,11 @@ func flagEditworkReplace(arg string) { func flagEditworkDropReplace(arg string) { path, version, err := parsePathVersionOptional("old", arg, true) if err != nil { - base.Fatalf("go mod: -dropreplace=%s: %v", arg, err) + base.Fatalf("go: -dropreplace=%s: %v", arg, err) } workedits = append(workedits, func(f *modfile.WorkFile) { if err := f.DropReplace(path, version); err != nil { - base.Fatalf("go mod: -dropreplace=%s: %v", arg, err) + base.Fatalf("go: -dropreplace=%s: %v", arg, err) } }) } diff --git a/src/cmd/go/internal/modcmd/graph.go b/src/cmd/go/internal/modcmd/graph.go index 2cbabae044..9b6aa1fb14 100644 --- a/src/cmd/go/internal/modcmd/graph.go +++ b/src/cmd/go/internal/modcmd/graph.go @@ -49,7 +49,7 @@ func runGraph(ctx context.Context, cmd *base.Command, args []string) { modload.InitWorkfile() if len(args) > 0 { - base.Fatalf("go mod graph: graph takes no arguments") + base.Fatalf("go: 'go mod graph' accepts no arguments") } modload.ForceUseModules = true modload.RootMode = modload.NeedRoot diff --git a/src/cmd/go/internal/modcmd/init.go b/src/cmd/go/internal/modcmd/init.go index 958c3066ac..bc4620a2a8 100644 --- a/src/cmd/go/internal/modcmd/init.go +++ b/src/cmd/go/internal/modcmd/init.go @@ -39,7 +39,7 @@ func init() { func runInit(ctx context.Context, cmd *base.Command, args []string) { if len(args) > 1 { - base.Fatalf("go mod init: too many arguments") + base.Fatalf("go: 'go mod init' accepts at most one argument") } var modPath string if len(args) == 1 { diff --git a/src/cmd/go/internal/modcmd/tidy.go b/src/cmd/go/internal/modcmd/tidy.go index fe25507e94..57d303a13c 100644 --- a/src/cmd/go/internal/modcmd/tidy.go +++ b/src/cmd/go/internal/modcmd/tidy.go @@ -95,7 +95,7 @@ func (f *goVersionFlag) Set(s string) error { func runTidy(ctx context.Context, cmd *base.Command, args []string) { if len(args) > 0 { - base.Fatalf("go mod tidy: no arguments allowed") + base.Fatalf("go: 'go mod tidy' accepts no arguments") } // Tidy aims to make 'go test' reproducible for any package in 'all', so we diff --git a/src/cmd/go/internal/modcmd/vendor.go b/src/cmd/go/internal/modcmd/vendor.go index 1effcea1a0..92348b8897 100644 --- a/src/cmd/go/internal/modcmd/vendor.go +++ b/src/cmd/go/internal/modcmd/vendor.go @@ -59,7 +59,7 @@ func init() { func runVendor(ctx context.Context, cmd *base.Command, args []string) { if len(args) != 0 { - base.Fatalf("go mod vendor: vendor takes no arguments") + base.Fatalf("go: 'go mod vendor' accepts no arguments") } modload.ForceUseModules = true modload.RootMode = modload.NeedRoot @@ -76,7 +76,7 @@ func runVendor(ctx context.Context, cmd *base.Command, args []string) { vdir := filepath.Join(modload.VendorDir()) if err := os.RemoveAll(vdir); err != nil { - base.Fatalf("go mod vendor: %v", err) + base.Fatalf("go: %v", err) } modpkgs := make(map[module.Version][]string) @@ -178,11 +178,11 @@ func runVendor(ctx context.Context, cmd *base.Command, args []string) { } if err := os.MkdirAll(vdir, 0777); err != nil { - base.Fatalf("go mod vendor: %v", err) + base.Fatalf("go: %v", err) } if err := os.WriteFile(filepath.Join(vdir, "modules.txt"), buf.Bytes(), 0666); err != nil { - base.Fatalf("go mod vendor: %v", err) + base.Fatalf("go: %v", err) } } @@ -250,7 +250,7 @@ func vendorPkg(vdir, pkg string) { embedPatterns := str.StringList(bp.EmbedPatterns, bp.TestEmbedPatterns, bp.XTestEmbedPatterns) embeds, err := load.ResolveEmbed(bp.Dir, embedPatterns) if err != nil { - base.Fatalf("go mod vendor: %v", err) + base.Fatalf("go: %v", err) } for _, embed := range embeds { embedDst := filepath.Join(dst, embed) @@ -261,21 +261,21 @@ func vendorPkg(vdir, pkg string) { // Copy the file as is done by copyDir below. r, err := os.Open(filepath.Join(src, embed)) if err != nil { - base.Fatalf("go mod vendor: %v", err) + base.Fatalf("go: %v", err) } if err := os.MkdirAll(filepath.Dir(embedDst), 0777); err != nil { - base.Fatalf("go mod vendor: %v", err) + base.Fatalf("go: %v", err) } w, err := os.Create(embedDst) if err != nil { - base.Fatalf("go mod vendor: %v", err) + base.Fatalf("go: %v", err) } if _, err := io.Copy(w, r); err != nil { - base.Fatalf("go mod vendor: %v", err) + base.Fatalf("go: %v", err) } r.Close() if err := w.Close(); err != nil { - base.Fatalf("go mod vendor: %v", err) + base.Fatalf("go: %v", err) } } } @@ -354,7 +354,7 @@ func matchPotentialSourceFile(dir string, info fs.DirEntry) bool { if strings.HasSuffix(info.Name(), ".go") { f, err := fsys.Open(filepath.Join(dir, info.Name())) if err != nil { - base.Fatalf("go mod vendor: %v", err) + base.Fatalf("go: %v", err) } defer f.Close() @@ -376,10 +376,10 @@ func matchPotentialSourceFile(dir string, info fs.DirEntry) bool { func copyDir(dst, src string, match func(dir string, info fs.DirEntry) bool, copiedFiles map[string]bool) { files, err := os.ReadDir(src) if err != nil { - base.Fatalf("go mod vendor: %v", err) + base.Fatalf("go: %v", err) } if err := os.MkdirAll(dst, 0777); err != nil { - base.Fatalf("go mod vendor: %v", err) + base.Fatalf("go: %v", err) } for _, file := range files { if file.IsDir() || !file.Type().IsRegular() || !match(src, file) { @@ -388,20 +388,20 @@ func copyDir(dst, src string, match func(dir string, info fs.DirEntry) bool, cop copiedFiles[file.Name()] = true r, err := os.Open(filepath.Join(src, file.Name())) if err != nil { - base.Fatalf("go mod vendor: %v", err) + base.Fatalf("go: %v", err) } dstPath := filepath.Join(dst, file.Name()) copiedFiles[dstPath] = true w, err := os.Create(dstPath) if err != nil { - base.Fatalf("go mod vendor: %v", err) + base.Fatalf("go: %v", err) } if _, err := io.Copy(w, r); err != nil { - base.Fatalf("go mod vendor: %v", err) + base.Fatalf("go: %v", err) } r.Close() if err := w.Close(); err != nil { - base.Fatalf("go mod vendor: %v", err) + base.Fatalf("go: %v", err) } } } diff --git a/src/cmd/go/internal/modcmd/verify.go b/src/cmd/go/internal/modcmd/verify.go index 14c4d76bc3..3f0c005d5d 100644 --- a/src/cmd/go/internal/modcmd/verify.go +++ b/src/cmd/go/internal/modcmd/verify.go @@ -47,7 +47,7 @@ func runVerify(ctx context.Context, cmd *base.Command, args []string) { if len(args) != 0 { // NOTE(rsc): Could take a module pattern. - base.Fatalf("go mod verify: verify takes no arguments") + base.Fatalf("go: verify takes no arguments") } modload.ForceUseModules = true modload.RootMode = modload.NeedRoot diff --git a/src/cmd/go/internal/modcmd/why.go b/src/cmd/go/internal/modcmd/why.go index eef5fa5ae8..ed5e9d7f1a 100644 --- a/src/cmd/go/internal/modcmd/why.go +++ b/src/cmd/go/internal/modcmd/why.go @@ -80,13 +80,13 @@ func runWhy(ctx context.Context, cmd *base.Command, args []string) { if *whyM { for _, arg := range args { if strings.Contains(arg, "@") { - base.Fatalf("go mod why: module query not allowed") + base.Fatalf("go: %s: 'go mod why' requires a module path, not a version query", arg) } } mods, err := modload.ListModules(ctx, args, 0) if err != nil { - base.Fatalf("go mod why: %v", err) + base.Fatalf("go: %v", err) } byModule := make(map[module.Version][]string) diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index 37912ce833..db07624e38 100644 --- a/src/cmd/go/internal/modget/get.go +++ b/src/cmd/go/internal/modget/get.go @@ -263,19 +263,19 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { case "", "upgrade", "patch": // ok default: - base.Fatalf("go get: unknown upgrade flag -u=%s", getU.rawVersion) + base.Fatalf("go: unknown upgrade flag -u=%s", getU.rawVersion) } if *getF { - fmt.Fprintf(os.Stderr, "go get: -f flag is a no-op when using modules\n") + fmt.Fprintf(os.Stderr, "go: -f flag is a no-op when using modules\n") } if *getFix { - fmt.Fprintf(os.Stderr, "go get: -fix flag is a no-op when using modules\n") + fmt.Fprintf(os.Stderr, "go: -fix flag is a no-op when using modules\n") } if *getM { - base.Fatalf("go get: -m flag is no longer supported; consider -d to skip building packages") + base.Fatalf("go: -m flag is no longer supported; consider -d to skip building packages") } if *getInsecure { - base.Fatalf("go get: -insecure flag is no longer supported; use GOINSECURE instead") + base.Fatalf("go: -insecure flag is no longer supported; use GOINSECURE instead") } // Do not allow any updating of go.mod until we've applied @@ -397,7 +397,7 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { } } if haveExternalExe { - fmt.Fprint(os.Stderr, "go get: installing executables with 'go get' in module mode is deprecated.") + fmt.Fprint(os.Stderr, "go: installing executables with 'go get' in module mode is deprecated.") var altMsg string if modload.HasModRoot() { altMsg = ` @@ -442,7 +442,7 @@ func parseArgs(ctx context.Context, rawArgs []string) []*query { for _, arg := range search.CleanPatterns(rawArgs) { q, err := newQuery(arg) if err != nil { - base.Errorf("go get: %v", err) + base.Errorf("go: %v", err) continue } @@ -457,11 +457,11 @@ func parseArgs(ctx context.Context, rawArgs []string) []*query { // if the argument has no version and either has no slash or refers to an existing file. if strings.HasSuffix(q.raw, ".go") && q.rawVersion == "" { if !strings.Contains(q.raw, "/") { - base.Errorf("go get %s: arguments must be package or module paths", q.raw) + base.Errorf("go: %s: arguments must be package or module paths", q.raw) continue } if fi, err := os.Stat(q.raw); err == nil && !fi.IsDir() { - base.Errorf("go get: %s exists as a file, but 'go get' requires package arguments", q.raw) + base.Errorf("go: %s exists as a file, but 'go get' requires package arguments", q.raw) continue } } @@ -743,7 +743,7 @@ func (r *resolver) performLocalQueries(ctx context.Context) { if len(match.Pkgs) == 0 { if q.raw == "" || q.raw == "." { - return errSet(fmt.Errorf("no package in current directory")) + return errSet(fmt.Errorf("no package to get in current directory")) } if !q.isWildcard() { modload.MustHaveModRoot() @@ -1342,7 +1342,7 @@ func (r *resolver) applyUpgrades(ctx context.Context, upgrades []pathSet) (chang var tentative []module.Version for _, cs := range upgrades { if cs.err != nil { - base.Errorf("go get: %v", cs.err) + base.Errorf("go: %v", cs.err) continue } @@ -1735,13 +1735,13 @@ func (r *resolver) reportChanges(oldReqs, newReqs []module.Version) { }) for _, c := range sortedChanges { if c.old == "" { - fmt.Fprintf(os.Stderr, "go get: added %s %s\n", c.path, c.new) + fmt.Fprintf(os.Stderr, "go: added %s %s\n", c.path, c.new) } else if c.new == "none" || c.new == "" { - fmt.Fprintf(os.Stderr, "go get: removed %s %s\n", c.path, c.old) + fmt.Fprintf(os.Stderr, "go: removed %s %s\n", c.path, c.old) } else if semver.Compare(c.new, c.old) > 0 { - fmt.Fprintf(os.Stderr, "go get: upgraded %s %s => %s\n", c.path, c.old, c.new) + fmt.Fprintf(os.Stderr, "go: upgraded %s %s => %s\n", c.path, c.old, c.new) } else { - fmt.Fprintf(os.Stderr, "go get: downgraded %s %s => %s\n", c.path, c.old, c.new) + fmt.Fprintf(os.Stderr, "go: downgraded %s %s => %s\n", c.path, c.old, c.new) } } @@ -1800,7 +1800,7 @@ func (r *resolver) updateBuildList(ctx context.Context, additions []module.Versi if err != nil { var constraint *modload.ConstraintError if !errors.As(err, &constraint) { - base.Errorf("go get: %v", err) + base.Errorf("go: %v", err) return false } @@ -1812,7 +1812,7 @@ func (r *resolver) updateBuildList(ctx context.Context, additions []module.Versi return rv.reason.ResolvedString(module.Version{Path: m.Path, Version: rv.version}) } for _, c := range constraint.Conflicts { - base.Errorf("go get: %v requires %v, not %v", reason(c.Source), c.Dep, reason(c.Constraint)) + base.Errorf("go: %v requires %v, not %v", reason(c.Source), c.Dep, reason(c.Constraint)) } return false } diff --git a/src/cmd/go/internal/modget/query.go b/src/cmd/go/internal/modget/query.go index 76041906f2..d7341e7813 100644 --- a/src/cmd/go/internal/modget/query.go +++ b/src/cmd/go/internal/modget/query.go @@ -284,21 +284,21 @@ func reportError(q *query, err error) { patternRE := regexp.MustCompile("(?m)(?:[ \t(\"`]|^)" + regexp.QuoteMeta(q.pattern) + "(?:[ @:;)\"`]|$)") if patternRE.MatchString(errStr) { if q.rawVersion == "" { - base.Errorf("go get: %s", errStr) + base.Errorf("go: %s", errStr) return } versionRE := regexp.MustCompile("(?m)(?:[ @(\"`]|^)" + regexp.QuoteMeta(q.version) + "(?:[ :;)\"`]|$)") if versionRE.MatchString(errStr) { - base.Errorf("go get: %s", errStr) + base.Errorf("go: %s", errStr) return } } if qs := q.String(); qs != "" { - base.Errorf("go get %s: %s", qs, errStr) + base.Errorf("go: %s: %s", qs, errStr) } else { - base.Errorf("go get: %s", errStr) + base.Errorf("go: %s", errStr) } } diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index 20c007a03a..40e6b50ed4 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -970,7 +970,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader { ld.GoVersion = MainModules.GoVersion() if ld.Tidy && semver.Compare("v"+ld.GoVersion, "v"+LatestGoVersion()) > 0 { - ld.errorf("go mod tidy: go.mod file indicates go %s, but maximum supported version is %s\n", ld.GoVersion, LatestGoVersion()) + ld.errorf("go: go.mod file indicates go %s, but maximum version supported by tidy is %s\n", ld.GoVersion, LatestGoVersion()) base.ExitIfErrors() } } @@ -1142,7 +1142,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader { // If that is not the case, there is a bug in the loading loop above. for _, m := range rs.rootModules { if v, ok := ld.requirements.rootSelected(m.Path); !ok || v != m.Version { - ld.errorf("go mod tidy: internal error: a requirement on %v is needed but was not added during package loading\n", m) + ld.errorf("go: internal error: a requirement on %v is needed but was not added during package loading\n", m) base.ExitIfErrors() } } @@ -1884,7 +1884,7 @@ func (ld *loader) checkTidyCompatibility(ctx context.Context, rs *Requirements) mg, err := rs.Graph(ctx) if err != nil { - ld.errorf("go mod tidy: error loading go %s module graph: %v\n", ld.TidyCompatibleVersion, err) + ld.errorf("go: error loading go %s module graph: %v\n", ld.TidyCompatibleVersion, err) suggestFixes() return } diff --git a/src/cmd/go/internal/run/run.go b/src/cmd/go/internal/run/run.go index 931fdcef8f..11e2c81b9a 100644 --- a/src/cmd/go/internal/run/run.go +++ b/src/cmd/go/internal/run/run.go @@ -103,7 +103,7 @@ func runRun(ctx context.Context, cmd *base.Command, args []string) { if strings.HasSuffix(file, "_test.go") { // GoFilesPackage is going to assign this to TestGoFiles. // Reject since it won't be part of the build. - base.Fatalf("go run: cannot run *_test.go files (%s)", file) + base.Fatalf("go: cannot run *_test.go files (%s)", file) } } p = load.GoFilesPackage(ctx, pkgOpts, files) @@ -114,26 +114,26 @@ func runRun(ctx context.Context, cmd *base.Command, args []string) { var err error pkgs, err = load.PackagesAndErrorsOutsideModule(ctx, pkgOpts, args[:1]) if err != nil { - base.Fatalf("go run: %v", err) + base.Fatalf("go: %v", err) } } else { pkgs = load.PackagesAndErrors(ctx, pkgOpts, args[:1]) } if len(pkgs) == 0 { - base.Fatalf("go run: no packages loaded from %s", arg) + base.Fatalf("go: no packages loaded from %s", arg) } if len(pkgs) > 1 { var names []string for _, p := range pkgs { names = append(names, p.ImportPath) } - base.Fatalf("go run: pattern %s matches multiple packages:\n\t%s", arg, strings.Join(names, "\n\t")) + base.Fatalf("go: pattern %s matches multiple packages:\n\t%s", arg, strings.Join(names, "\n\t")) } p = pkgs[0] i++ } else { - base.Fatalf("go run: no go files listed") + base.Fatalf("go: no go files listed") } cmdArgs := args[i:] load.CheckPackageErrors([]*load.Package{p}) @@ -154,7 +154,7 @@ func runRun(ctx context.Context, cmd *base.Command, args []string) { if !cfg.BuildContext.CgoEnabled { hint = " (cgo is disabled)" } - base.Fatalf("go run: no suitable source files%s", hint) + base.Fatalf("go: no suitable source files%s", hint) } p.Internal.ExeName = src[:len(src)-len(".go")] } else { diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index d65f54f2bd..198afbf4c3 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -656,7 +656,7 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { b.Init() if cfg.BuildI { - fmt.Fprint(os.Stderr, "go test: -i flag is deprecated\n") + fmt.Fprint(os.Stderr, "go: -i flag is deprecated\n") cfg.BuildV = testV deps := make(map[string]bool) diff --git a/src/cmd/go/internal/test/testflag.go b/src/cmd/go/internal/test/testflag.go index 97a9ef38b9..e0a3e010fa 100644 --- a/src/cmd/go/internal/test/testflag.go +++ b/src/cmd/go/internal/test/testflag.go @@ -384,7 +384,7 @@ func testFlags(args []string) (packageNames, passToTest []string) { if !testC { buildFlag = "-i" } - fmt.Fprintf(os.Stderr, "go test: unknown flag %s cannot be used with %s\n", firstUnknownFlag, buildFlag) + fmt.Fprintf(os.Stderr, "go: unknown flag %s cannot be used with %s\n", firstUnknownFlag, buildFlag) exitWithUsage() } diff --git a/src/cmd/go/internal/tool/tool.go b/src/cmd/go/internal/tool/tool.go index 95c90ea7c8..4fe4c2baed 100644 --- a/src/cmd/go/internal/tool/tool.go +++ b/src/cmd/go/internal/tool/tool.go @@ -61,7 +61,7 @@ func runTool(ctx context.Context, cmd *base.Command, args []string) { switch { case 'a' <= c && c <= 'z', '0' <= c && c <= '9', c == '_': default: - fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\n", toolName) + fmt.Fprintf(os.Stderr, "go: bad tool name %q\n", toolName) base.SetExitStatus(2) return } @@ -117,14 +117,14 @@ func runTool(ctx context.Context, cmd *base.Command, args []string) { func listTools() { f, err := os.Open(base.ToolDir) if err != nil { - fmt.Fprintf(os.Stderr, "go tool: no tool directory: %s\n", err) + fmt.Fprintf(os.Stderr, "go: no tool directory: %s\n", err) base.SetExitStatus(2) return } defer f.Close() names, err := f.Readdirnames(-1) if err != nil { - fmt.Fprintf(os.Stderr, "go tool: can't read directory: %s\n", err) + fmt.Fprintf(os.Stderr, "go: can't read tool directory: %s\n", err) base.SetExitStatus(2) return } diff --git a/src/cmd/go/internal/version/version.go b/src/cmd/go/internal/version/version.go index 58cbd32e78..e885933ac3 100644 --- a/src/cmd/go/internal/version/version.go +++ b/src/cmd/go/internal/version/version.go @@ -62,8 +62,14 @@ func runVersion(ctx context.Context, cmd *base.Command, args []string) { // a reasonable use case. For example, imagine GOFLAGS=-v to // turn "verbose mode" on for all Go commands, which should not // break "go version". - if (!base.InGOFLAGS("-m") && *versionM) || (!base.InGOFLAGS("-v") && *versionV) { - fmt.Fprintf(os.Stderr, "go version: flags can only be used with arguments\n") + var argOnlyFlag string + if !base.InGOFLAGS("-m") && *versionM { + argOnlyFlag = "-m" + } else if !base.InGOFLAGS("-v") && *versionV { + argOnlyFlag = "-v" + } + if argOnlyFlag != "" { + fmt.Fprintf(os.Stderr, "go: 'go version' only accepts %s flag with arguments\n", argOnlyFlag) base.SetExitStatus(2) return } diff --git a/src/cmd/go/internal/vet/vet.go b/src/cmd/go/internal/vet/vet.go index 1d419dddb9..88b3c570a0 100644 --- a/src/cmd/go/internal/vet/vet.go +++ b/src/cmd/go/internal/vet/vet.go @@ -103,7 +103,7 @@ func runVet(ctx context.Context, cmd *base.Command, args []string) { continue } if len(ptest.GoFiles) == 0 && len(ptest.CgoFiles) == 0 && pxtest == nil { - base.Errorf("go vet %s: no Go files in %s", p.ImportPath, p.Dir) + base.Errorf("go: can't vet %s: no Go files in %s", p.ImportPath, p.Dir) continue } if len(ptest.GoFiles) > 0 || len(ptest.CgoFiles) > 0 { diff --git a/src/cmd/go/internal/vet/vetflag.go b/src/cmd/go/internal/vet/vetflag.go index b5b3c462ff..3551a5997c 100644 --- a/src/cmd/go/internal/vet/vetflag.go +++ b/src/cmd/go/internal/vet/vetflag.go @@ -82,7 +82,7 @@ func vetFlags(args []string) (passToVet, packageNames []string) { vetcmd := exec.Command(tool, "-flags") vetcmd.Stdout = out if err := vetcmd.Run(); err != nil { - fmt.Fprintf(os.Stderr, "go vet: can't execute %s -flags: %v\n", tool, err) + fmt.Fprintf(os.Stderr, "go: can't execute %s -flags: %v\n", tool, err) base.SetExitStatus(2) base.Exit() } @@ -92,7 +92,7 @@ func vetFlags(args []string) (passToVet, packageNames []string) { Usage string } if err := json.Unmarshal(out.Bytes(), &analysisFlags); err != nil { - fmt.Fprintf(os.Stderr, "go vet: can't unmarshal JSON from %s -flags: %v", tool, err) + fmt.Fprintf(os.Stderr, "go: can't unmarshal JSON from %s -flags: %v", tool, err) base.SetExitStatus(2) base.Exit() } diff --git a/src/cmd/go/internal/work/action.go b/src/cmd/go/internal/work/action.go index 69940cb001..6f5ac1364c 100644 --- a/src/cmd/go/internal/work/action.go +++ b/src/cmd/go/internal/work/action.go @@ -294,14 +294,14 @@ func (b *Builder) Init() { } if err := CheckGOOSARCHPair(cfg.Goos, cfg.Goarch); err != nil { - fmt.Fprintf(os.Stderr, "cmd/go: %v\n", err) + fmt.Fprintf(os.Stderr, "go: %v\n", err) base.SetExitStatus(2) base.Exit() } for _, tag := range cfg.BuildContext.BuildTags { if strings.Contains(tag, ",") { - fmt.Fprintf(os.Stderr, "cmd/go: -tags space-separated list contains comma\n") + fmt.Fprintf(os.Stderr, "go: -tags space-separated list contains comma\n") base.SetExitStatus(2) base.Exit() } diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go index 3d7c778a7d..e5d7f4a8fd 100644 --- a/src/cmd/go/internal/work/build.go +++ b/src/cmd/go/internal/work/build.go @@ -406,7 +406,7 @@ func runBuild(ctx context.Context, cmd *base.Command, args []string) { depMode := ModeBuild if cfg.BuildI { depMode = ModeInstall - fmt.Fprint(os.Stderr, "go build: -i flag is deprecated\n") + fmt.Fprint(os.Stderr, "go: -i flag is deprecated\n") } pkgs = omitTestOnly(pkgsFilter(pkgs)) @@ -425,7 +425,7 @@ func runBuild(ctx context.Context, cmd *base.Command, args []string) { strings.HasSuffix(cfg.BuildO, "/") || strings.HasSuffix(cfg.BuildO, string(os.PathSeparator)) { if !explicitO { - base.Fatalf("go build: build output %q already exists and is a directory", cfg.BuildO) + base.Fatalf("go: build output %q already exists and is a directory", cfg.BuildO) } a := &Action{Mode: "go build"} for _, p := range pkgs { @@ -440,13 +440,13 @@ func runBuild(ctx context.Context, cmd *base.Command, args []string) { a.Deps = append(a.Deps, b.AutoAction(ModeInstall, depMode, p)) } if len(a.Deps) == 0 { - base.Fatalf("go build: no main packages to build") + base.Fatalf("go: no main packages to build") } b.Do(ctx, a) return } if len(pkgs) > 1 { - base.Fatalf("go build: cannot write multiple packages to non-directory %s", cfg.BuildO) + base.Fatalf("go: cannot write multiple packages to non-directory %s", cfg.BuildO) } else if len(pkgs) == 0 { base.Fatalf("no packages to build") } @@ -593,7 +593,7 @@ func runInstall(ctx context.Context, cmd *base.Command, args []string) { for _, arg := range args { if strings.Contains(arg, "@") && !build.IsLocalImport(arg) && !filepath.IsAbs(arg) { if cfg.BuildI { - fmt.Fprint(os.Stderr, "go install: -i flag is deprecated\n") + fmt.Fprint(os.Stderr, "go: -i flag is deprecated\n") } installOutsideModule(ctx, args) return @@ -621,7 +621,7 @@ func runInstall(ctx context.Context, cmd *base.Command, args []string) { latestArgs[i] = args[i] + "@latest" } hint := strings.Join(latestArgs, " ") - base.Fatalf("go install: version is required when current directory is not in a module\n\tTry 'go install %s' to install the latest version", hint) + base.Fatalf("go: 'go install' requires a version when current directory is not in a module\n\tTry 'go install %s' to install the latest version", hint) } } load.CheckPackageErrors(pkgs) @@ -634,7 +634,7 @@ func runInstall(ctx context.Context, cmd *base.Command, args []string) { } } if !allGoroot { - fmt.Fprint(os.Stderr, "go install: -i flag is deprecated\n") + fmt.Fprintf(os.Stderr, "go: -i flag is deprecated\n") } } @@ -680,14 +680,14 @@ func InstallPackages(ctx context.Context, patterns []string, pkgs []*load.Packag case p.Name != "main" && p.Module != nil: // Non-executables have no target (except the cache) when building with modules. case p.Internal.GobinSubdir: - base.Errorf("go %s: cannot install cross-compiled binaries when GOBIN is set", cfg.CmdName) + base.Errorf("go: cannot install cross-compiled binaries when GOBIN is set") case p.Internal.CmdlineFiles: - base.Errorf("go %s: no install location for .go files listed on command line (GOBIN not set)", cfg.CmdName) + base.Errorf("go: no install location for .go files listed on command line (GOBIN not set)") case p.ConflictDir != "": - base.Errorf("go %s: no install location for %s: hidden by %s", cfg.CmdName, p.Dir, p.ConflictDir) + base.Errorf("go: no install location for %s: hidden by %s", p.Dir, p.ConflictDir) default: - base.Errorf("go %s: no install location for directory %s outside GOPATH\n"+ - "\tFor more details see: 'go help gopath'", cfg.CmdName, p.Dir) + base.Errorf("go: no install location for directory %s outside GOPATH\n"+ + "\tFor more details see: 'go help gopath'", p.Dir) } } } @@ -782,7 +782,7 @@ func installOutsideModule(ctx context.Context, args []string) { pkgOpts := load.PackageOpts{MainOnly: true} pkgs, err := load.PackagesAndErrorsOutsideModule(ctx, pkgOpts, args) if err != nil { - base.Fatalf("go install: %v", err) + base.Fatalf("go: %v", err) } load.CheckPackageErrors(pkgs) patterns := make([]string, len(args)) diff --git a/src/cmd/go/internal/work/init.go b/src/cmd/go/internal/work/init.go index 7acee3dd55..7aa8dfe55f 100644 --- a/src/cmd/go/internal/work/init.go +++ b/src/cmd/go/internal/work/init.go @@ -13,7 +13,6 @@ import ( "cmd/go/internal/modload" "cmd/internal/str" "cmd/internal/sys" - "flag" "fmt" "os" "path/filepath" @@ -33,7 +32,7 @@ func BuildInit() { if cfg.BuildPkgdir != "" && !filepath.IsAbs(cfg.BuildPkgdir) { p, err := filepath.Abs(cfg.BuildPkgdir) if err != nil { - fmt.Fprintf(os.Stderr, "go %s: evaluating -pkgdir: %v\n", flag.Args()[0], err) + fmt.Fprintf(os.Stderr, "go: evaluating -pkgdir: %v\n", err) base.SetExitStatus(2) base.Exit() } @@ -49,14 +48,14 @@ func BuildInit() { value := cfg.Getenv(key) args, err := str.SplitQuotedFields(value) if err != nil { - base.Fatalf("go %s: %s environment variable could not be parsed: %v", flag.Args()[0], key, err) + base.Fatalf("go: %s environment variable could not be parsed: %v", key, err) } if len(args) == 0 { continue } path := args[0] if !filepath.IsAbs(path) && path != filepath.Base(path) { - base.Fatalf("go %s: %s environment variable is relative; must be absolute path: %s\n", flag.Args()[0], key, path) + base.Fatalf("go: %s environment variable is relative; must be absolute path: %s\n", key, path) } } } @@ -66,7 +65,7 @@ func instrumentInit() { return } if cfg.BuildRace && cfg.BuildMSan { - fmt.Fprintf(os.Stderr, "go %s: may not use -race and -msan simultaneously\n", flag.Args()[0]) + fmt.Fprintf(os.Stderr, "go: may not use -race and -msan simultaneously\n") base.SetExitStatus(2) base.Exit() } @@ -77,7 +76,7 @@ func instrumentInit() { } if cfg.BuildRace { if !sys.RaceDetectorSupported(cfg.Goos, cfg.Goarch) { - fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, linux/ppc64le, linux/arm64, freebsd/amd64, netbsd/amd64, darwin/amd64, darwin/arm64, and windows/amd64\n", flag.Args()[0]) + fmt.Fprintf(os.Stderr, "go: -race is only supported on linux/amd64, linux/ppc64le, linux/arm64, freebsd/amd64, netbsd/amd64, darwin/amd64, darwin/arm64, and windows/amd64\n") base.SetExitStatus(2) base.Exit() } @@ -95,9 +94,9 @@ func instrumentInit() { if !cfg.BuildContext.CgoEnabled { if runtime.GOOS != cfg.Goos || runtime.GOARCH != cfg.Goarch { - fmt.Fprintf(os.Stderr, "go %s: %s requires cgo\n", flag.Args()[0], modeFlag) + fmt.Fprintf(os.Stderr, "go: %s requires cgo\n", modeFlag) } else { - fmt.Fprintf(os.Stderr, "go %s: %s requires cgo; enable cgo by setting CGO_ENABLED=1\n", flag.Args()[0], modeFlag) + fmt.Fprintf(os.Stderr, "go: %s requires cgo; enable cgo by setting CGO_ENABLED=1\n", modeFlag) } base.SetExitStatus(2) diff --git a/src/cmd/go/testdata/script/build_i_deprecate.txt b/src/cmd/go/testdata/script/build_i_deprecate.txt index 71356e5321..5c17995669 100644 --- a/src/cmd/go/testdata/script/build_i_deprecate.txt +++ b/src/cmd/go/testdata/script/build_i_deprecate.txt @@ -2,13 +2,13 @@ # TODO(golang.org/issue/41696): remove the -i flag after Go 1.16, and this test. go build -n -i -stderr '^go build: -i flag is deprecated$' +stderr '^go: -i flag is deprecated$' go install -n -i -stderr '^go install: -i flag is deprecated$' +stderr '^go: -i flag is deprecated$' go test -n -i -stderr '^go test: -i flag is deprecated$' +stderr '^go: -i flag is deprecated$' # 'go clean -i' should not print a deprecation warning. diff --git a/src/cmd/go/testdata/script/env_unset.txt b/src/cmd/go/testdata/script/env_unset.txt index 4e0f249509..22bc845c37 100644 --- a/src/cmd/go/testdata/script/env_unset.txt +++ b/src/cmd/go/testdata/script/env_unset.txt @@ -12,13 +12,13 @@ stderr '^go(\.exe)?: unknown GOEXPERIMENT badexp$' go env -u GOEXPERIMENT ! go env -stderr '^cmd/go: unsupported GOOS/GOARCH pair bados/badarch$' +stderr '^go: unsupported GOOS/GOARCH pair bados/badarch$' ! go env -u GOOS -stderr '^go env -u: unsupported GOOS/GOARCH pair \w+/badarch$' +stderr '^go: unsupported GOOS/GOARCH pair \w+/badarch$' ! go env -u GOARCH -stderr '^go env -u: unsupported GOOS/GOARCH pair bados/\w+$' +stderr '^go: unsupported GOOS/GOARCH pair bados/\w+$' go env -u GOOS GOARCH diff --git a/src/cmd/go/testdata/script/env_write.txt b/src/cmd/go/testdata/script/env_write.txt index b5e9739167..132947c623 100644 --- a/src/cmd/go/testdata/script/env_write.txt +++ b/src/cmd/go/testdata/script/env_write.txt @@ -30,9 +30,9 @@ go env # checking errors ! go env -w -stderr 'go env -w: no KEY=VALUE arguments given' +stderr 'go: no KEY=VALUE arguments given' ! go env -u -stderr 'go env -u: no arguments given' +stderr 'go: ''go env -u'' requires an argument' # go env -w changes default setting env root= @@ -111,7 +111,7 @@ stderr 'GOPATH entry is relative; must be absolute path' # go env -w rejects invalid GOTMPDIR values ! go env -w GOTMPDIR=x -stderr 'go env -w: GOTMPDIR must be an absolute path' +stderr 'go: GOTMPDIR must be an absolute path' # go env -w should accept absolute GOTMPDIR value # and should not create it @@ -134,24 +134,24 @@ stdout ^$ go env -w CC=clang [!windows] ! go env -w CC=./clang [!windows] ! go env -w CC=bin/clang -[!windows] stderr 'go env -w: CC entry is relative; must be absolute path' +[!windows] stderr 'go: CC entry is relative; must be absolute path' [windows] go env -w CC=$WORK\bin\clang [windows] ! go env -w CC=.\clang [windows] ! go env -w CC=bin\clang -[windows] stderr 'go env -w: CC entry is relative; must be absolute path' +[windows] stderr 'go: CC entry is relative; must be absolute path' # go env -w rejects relative CXX values [!windows] go env -w CC=/usr/bin/cpp go env -w CXX=cpp [!windows] ! go env -w CXX=./cpp [!windows] ! go env -w CXX=bin/cpp -[!windows] stderr 'go env -w: CXX entry is relative; must be absolute path' +[!windows] stderr 'go: CXX entry is relative; must be absolute path' [windows] go env -w CXX=$WORK\bin\cpp [windows] ! go env -w CXX=.\cpp [windows] ! go env -w CXX=bin\cpp -[windows] stderr 'go env -w: CXX entry is relative; must be absolute path' +[windows] stderr 'go: CXX entry is relative; must be absolute path' # go env -w/-u checks validity of GOOS/ARCH combinations env GOOS= @@ -176,9 +176,9 @@ stderr 'unsupported GOOS/GOARCH.*windows/mips$' # go env -w should reject relative paths in GOMODCACHE environment. ! go env -w GOMODCACHE=~/test -stderr 'go env -w: GOMODCACHE entry is relative; must be absolute path: "~/test"' +stderr 'go: GOMODCACHE entry is relative; must be absolute path: "~/test"' ! go env -w GOMODCACHE=./test -stderr 'go env -w: GOMODCACHE entry is relative; must be absolute path: "./test"' +stderr 'go: GOMODCACHE entry is relative; must be absolute path: "./test"' # go env -w checks validity of GOEXPERIMENT env GOEXPERIMENT= diff --git a/src/cmd/go/testdata/script/get_go_file.txt b/src/cmd/go/testdata/script/get_go_file.txt index bed8720987..f6d0de4d06 100644 --- a/src/cmd/go/testdata/script/get_go_file.txt +++ b/src/cmd/go/testdata/script/get_go_file.txt @@ -9,15 +9,15 @@ go get -d test # argument has .go suffix, is a file and exists ! go get -d test.go -stderr 'go get test.go: arguments must be package or module paths' +stderr 'go: test.go: arguments must be package or module paths' # argument has .go suffix, doesn't exist and has no slashes ! go get -d test_missing.go -stderr 'go get test_missing.go: arguments must be package or module paths' +stderr 'go: test_missing.go: arguments must be package or module paths' # argument has .go suffix, is a file and exists in sub-directory ! go get -d test/test.go -stderr 'go get: test/test.go exists as a file, but ''go get'' requires package arguments' +stderr 'go: test/test.go exists as a file, but ''go get'' requires package arguments' # argument has .go suffix, doesn't exist and has slashes ! go get -d test/test_missing.go @@ -27,19 +27,19 @@ stderr 'go get: test/test.go exists as a file, but ''go get'' requires package a # argument has .go suffix, is a symlink and exists [symlink] symlink test_sym.go -> test.go [symlink] ! go get -d test_sym.go -[symlink] stderr 'go get test_sym.go: arguments must be package or module paths' +[symlink] stderr 'go: test_sym.go: arguments must be package or module paths' [symlink] rm test_sym.go # argument has .go suffix, is a symlink and exists in sub-directory [symlink] symlink test/test_sym.go -> test.go [symlink] ! go get -d test/test_sym.go -[symlink] stderr 'go get: test/test_sym.go exists as a file, but ''go get'' requires package arguments' +[symlink] stderr 'go: test/test_sym.go exists as a file, but ''go get'' requires package arguments' [symlink] rm test_sym.go # argument has .go suffix, is a directory and exists mkdir test_dir.go ! go get -d test_dir.go -stderr 'go get test_dir.go: arguments must be package or module paths' +stderr 'go: test_dir.go: arguments must be package or module paths' rm test_dir.go # argument has .go suffix, is a directory and exists in sub-directory diff --git a/src/cmd/go/testdata/script/get_insecure_no_longer_supported.txt b/src/cmd/go/testdata/script/get_insecure_no_longer_supported.txt index 2517664dd0..00bf32fc78 100644 --- a/src/cmd/go/testdata/script/get_insecure_no_longer_supported.txt +++ b/src/cmd/go/testdata/script/get_insecure_no_longer_supported.txt @@ -3,11 +3,11 @@ env GO111MODULE=off # GOPATH: Fetch with insecure, should error ! go get -insecure test -stderr 'go get: -insecure flag is no longer supported; use GOINSECURE instead' +stderr 'go: -insecure flag is no longer supported; use GOINSECURE instead' # Modules: Set up env GO111MODULE=on # Modules: Fetch with insecure, should error ! go get -insecure test -stderr 'go get: -insecure flag is no longer supported; use GOINSECURE instead' +stderr 'go: -insecure flag is no longer supported; use GOINSECURE instead' diff --git a/src/cmd/go/testdata/script/gopath_install.txt b/src/cmd/go/testdata/script/gopath_install.txt index 4b42fc593f..6c572eae61 100644 --- a/src/cmd/go/testdata/script/gopath_install.txt +++ b/src/cmd/go/testdata/script/gopath_install.txt @@ -26,7 +26,7 @@ cd .. env GOPATH= # reset to default ($HOME/go, which does not exist) env GOBIN= ! go install go-cmd-test/helloworld.go -stderr '^go install: no install location for \.go files listed on command line \(GOBIN not set\)$' +stderr '^go: no install location for \.go files listed on command line \(GOBIN not set\)$' # With $GOBIN set, should install there. env GOBIN=$WORK/bin1 diff --git a/src/cmd/go/testdata/script/gopath_local.txt b/src/cmd/go/testdata/script/gopath_local.txt index 7ee1f83471..54beaca5e8 100644 --- a/src/cmd/go/testdata/script/gopath_local.txt +++ b/src/cmd/go/testdata/script/gopath_local.txt @@ -22,7 +22,7 @@ stdout '^sub\.Hello' # Explicit source files listed on the command line should not install without # GOBIN set, since individual source files aren't part of the containing GOPATH. ! go install testdata/local/easy.go -stderr '^go install: no install location for \.go files listed on command line \(GOBIN not set\)$' +stderr '^go: no install location for \.go files listed on command line \(GOBIN not set\)$' [windows] stop # Windows does not allow the ridiculous directory name we're about to use. @@ -58,7 +58,7 @@ stdout '^sub\.Hello' # Explicit source files listed on the command line should not install without # GOBIN set, since individual source files aren't part of the containing GOPATH. ! go install testdata/$BAD_DIR_NAME/easy.go -stderr '^go install: no install location for \.go files listed on command line \(GOBIN not set\)$' +stderr '^go: no install location for \.go files listed on command line \(GOBIN not set\)$' -- testdata/local/easy.go -- package main diff --git a/src/cmd/go/testdata/script/govcs.txt b/src/cmd/go/testdata/script/govcs.txt index 4180d7da6a..e8dd791267 100644 --- a/src/cmd/go/testdata/script/govcs.txt +++ b/src/cmd/go/testdata/script/govcs.txt @@ -5,40 +5,40 @@ env GOPROXY=direct # GOVCS stops go get env GOVCS='*:none' ! go get github.com/google/go-cmp -stderr '^go get: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$' +stderr '^go: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$' env GOPRIVATE='github.com/google' ! go get github.com/google/go-cmp -stderr '^go get: GOVCS disallows using git for private github.com/google/go-cmp; see ''go help vcs''$' +stderr '^go: GOVCS disallows using git for private github.com/google/go-cmp; see ''go help vcs''$' # public pattern works env GOPRIVATE='github.com/google' env GOVCS='public:all,private:none' ! go get github.com/google/go-cmp -stderr '^go get: GOVCS disallows using git for private github.com/google/go-cmp; see ''go help vcs''$' +stderr '^go: GOVCS disallows using git for private github.com/google/go-cmp; see ''go help vcs''$' # private pattern works env GOPRIVATE='hubgit.com/google' env GOVCS='private:all,public:none' ! go get github.com/google/go-cmp -stderr '^go get: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$' +stderr '^go: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$' # other patterns work (for more patterns, see TestGOVCS) env GOPRIVATE= env GOVCS='github.com:svn|hg' ! go get github.com/google/go-cmp -stderr '^go get: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$' +stderr '^go: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$' env GOVCS='github.com/google/go-cmp/inner:git,github.com:svn|hg' ! go get github.com/google/go-cmp -stderr '^go get: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$' +stderr '^go: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$' # bad patterns are reported (for more bad patterns, see TestGOVCSErrors) env GOVCS='git' ! go get github.com/google/go-cmp -stderr '^go get github.com/google/go-cmp: malformed entry in GOVCS \(missing colon\): "git"$' +stderr '^go: github.com/google/go-cmp: malformed entry in GOVCS \(missing colon\): "git"$' env GOVCS=github.com:hg,github.com:git ! go get github.com/google/go-cmp -stderr '^go get github.com/google/go-cmp: unreachable pattern in GOVCS: "github.com:git" after "github.com:hg"$' +stderr '^go: github.com/google/go-cmp: unreachable pattern in GOVCS: "github.com:git" after "github.com:hg"$' # bad GOVCS patterns do not stop commands that do not need to check VCS go list @@ -50,19 +50,19 @@ env GOPROXY=direct env GOPRIVATE= env GOVCS= ! go get rsc.io/nonexist.svn/hello -stderr '^go get rsc.io/nonexist.svn/hello: GOVCS disallows using svn for public rsc.io/nonexist.svn; see ''go help vcs''$' +stderr '^go: rsc.io/nonexist.svn/hello: GOVCS disallows using svn for public rsc.io/nonexist.svn; see ''go help vcs''$' # fossil is disallowed by default env GOPRIVATE= env GOVCS= ! go get rsc.io/nonexist.fossil/hello -stderr '^go get rsc.io/nonexist.fossil/hello: GOVCS disallows using fossil for public rsc.io/nonexist.fossil; see ''go help vcs''$' +stderr '^go: rsc.io/nonexist.fossil/hello: GOVCS disallows using fossil for public rsc.io/nonexist.fossil; see ''go help vcs''$' # bzr is disallowed by default env GOPRIVATE= env GOVCS= ! go get rsc.io/nonexist.bzr/hello -stderr '^go get rsc.io/nonexist.bzr/hello: GOVCS disallows using bzr for public rsc.io/nonexist.bzr; see ''go help vcs''$' +stderr '^go: rsc.io/nonexist.bzr/hello: GOVCS disallows using bzr for public rsc.io/nonexist.bzr; see ''go help vcs''$' # git is OK by default env GOVCS= @@ -77,12 +77,12 @@ env GONOSUMDB='*' # git can be disallowed env GOVCS=public:hg ! go get rsc.io/nonexist.git/hello -stderr '^go get rsc.io/nonexist.git/hello: GOVCS disallows using git for public rsc.io/nonexist.git; see ''go help vcs''$' +stderr '^go: rsc.io/nonexist.git/hello: GOVCS disallows using git for public rsc.io/nonexist.git; see ''go help vcs''$' # hg can be disallowed env GOVCS=public:git ! go get rsc.io/nonexist.hg/hello -stderr '^go get rsc.io/nonexist.hg/hello: GOVCS disallows using hg for public rsc.io/nonexist.hg; see ''go help vcs''$' +stderr '^go: rsc.io/nonexist.hg/hello: GOVCS disallows using hg for public rsc.io/nonexist.hg; see ''go help vcs''$' # Repeat in GOPATH mode. Error texts slightly different. diff --git a/src/cmd/go/testdata/script/list_shadow.txt b/src/cmd/go/testdata/script/list_shadow.txt index 7b24d9367a..660508de9f 100644 --- a/src/cmd/go/testdata/script/list_shadow.txt +++ b/src/cmd/go/testdata/script/list_shadow.txt @@ -15,7 +15,7 @@ stdout '^\(.*gopath(\\|/)src(\\|/)shadow(\\|/)root2(\\|/)src(\\|/)foo\) \('$WORK # The error for go install should mention the conflicting directory. ! go install -n ./shadow/root2/src/foo -stderr 'go install: no install location for '$WORK'(\\|/)?gopath(\\|/)src(\\|/)shadow(\\|/)root2(\\|/)src(\\|/)foo: hidden by '$WORK'(\\|/)?gopath(\\|/)src(\\|/)shadow(\\|/)root1(\\|/)src(\\|/)foo' +stderr 'go: no install location for '$WORK'(\\|/)?gopath(\\|/)src(\\|/)shadow(\\|/)root2(\\|/)src(\\|/)foo: hidden by '$WORK'(\\|/)?gopath(\\|/)src(\\|/)shadow(\\|/)root1(\\|/)src(\\|/)foo' -- shadow/root1/src/foo/foo.go -- package foo diff --git a/src/cmd/go/testdata/script/mod_bad_domain.txt b/src/cmd/go/testdata/script/mod_bad_domain.txt index 7a270d0f07..ed6a8c656d 100644 --- a/src/cmd/go/testdata/script/mod_bad_domain.txt +++ b/src/cmd/go/testdata/script/mod_bad_domain.txt @@ -2,7 +2,7 @@ env GO111MODULE=on # explicit get should report errors about bad names ! go get appengine -stderr '^go get: malformed module path "appengine": missing dot in first path element$' +stderr '^go: malformed module path "appengine": missing dot in first path element$' ! go get x/y.z stderr 'malformed module path "x/y.z": missing dot in first path element' diff --git a/src/cmd/go/testdata/script/mod_dot.txt b/src/cmd/go/testdata/script/mod_dot.txt index ca8d5c6cc2..cb60e988b6 100644 --- a/src/cmd/go/testdata/script/mod_dot.txt +++ b/src/cmd/go/testdata/script/mod_dot.txt @@ -5,11 +5,11 @@ env GO111MODULE=on # to resolve an external module. cd dir ! go get -stderr '^go get: no package in current directory$' +stderr '^go: no package to get in current directory$' ! go get . -stderr '^go get \.: no package in current directory$' +stderr '^go: .: no package to get in current directory$' ! go get ./subdir -stderr '^go get: \.[/\\]subdir \('$WORK'[/\\]gopath[/\\]src[/\\]dir[/\\]subdir\) is not a package in module rooted at '$WORK'[/\\]gopath[/\\]src[/\\]dir$' +stderr '^go: \.[/\\]subdir \('$WORK'[/\\]gopath[/\\]src[/\\]dir[/\\]subdir\) is not a package in module rooted at '$WORK'[/\\]gopath[/\\]src[/\\]dir$' ! go list ! stderr 'cannot find module providing package' stderr '^no Go files in '$WORK'[/\\]gopath[/\\]src[/\\]dir$' diff --git a/src/cmd/go/testdata/script/mod_download.txt b/src/cmd/go/testdata/script/mod_download.txt index c2b72b2a02..89e58a2cfd 100644 --- a/src/cmd/go/testdata/script/mod_download.txt +++ b/src/cmd/go/testdata/script/mod_download.txt @@ -93,19 +93,19 @@ exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.1.zip # download reports errors encountered when locating modules ! go mod download bad/path -stderr '^go mod download: module bad/path: not a known dependency$' +stderr '^go: module bad/path: not a known dependency$' ! go mod download bad/path@latest -stderr '^go mod download: bad/path@latest: malformed module path "bad/path": missing dot in first path element$' +stderr '^go: bad/path@latest: malformed module path "bad/path": missing dot in first path element$' ! go mod download rsc.io/quote@v1.999.999 -stderr '^go mod download: rsc.io/quote@v1.999.999: reading .*/v1.999.999.info: 404 Not Found$' +stderr '^go: rsc.io/quote@v1.999.999: reading .*/v1.999.999.info: 404 Not Found$' ! go mod download -json bad/path stdout '^\t"Error": "module bad/path: not a known dependency"' # download main module produces a warning or error go mod download m -stderr '^go mod download: skipping argument m that resolves to the main module\n' +stderr '^go: skipping download of m that resolves to the main module\n' ! go mod download m@latest -stderr '^go mod download: m@latest: malformed module path "m": missing dot in first path element$' +stderr '^go: m@latest: malformed module path "m": missing dot in first path element$' # download without arguments updates go.mod and go.sum after loading the # build list, but does not save sums for downloaded zips. diff --git a/src/cmd/go/testdata/script/mod_edit.txt b/src/cmd/go/testdata/script/mod_edit.txt index 5aa5ca1ffc..ebc032a73c 100644 --- a/src/cmd/go/testdata/script/mod_edit.txt +++ b/src/cmd/go/testdata/script/mod_edit.txt @@ -23,18 +23,18 @@ cmpenv go.mod $WORK/go.mod.edit2 # -exclude and -retract reject invalid versions. ! go mod edit -exclude=example.com/m@bad -stderr '^go mod: -exclude=example.com/m@bad: version "bad" invalid: must be of the form v1.2.3$' +stderr '^go: -exclude=example.com/m@bad: version "bad" invalid: must be of the form v1.2.3$' ! go mod edit -retract=bad -stderr '^go mod: -retract=bad: version "bad" invalid: must be of the form v1.2.3$' +stderr '^go: -retract=bad: version "bad" invalid: must be of the form v1.2.3$' ! go mod edit -exclude=example.com/m@v2.0.0 -stderr '^go mod: -exclude=example.com/m@v2\.0\.0: version "v2\.0\.0" invalid: should be v2\.0\.0\+incompatible \(or module example\.com/m/v2\)$' +stderr '^go: -exclude=example.com/m@v2\.0\.0: version "v2\.0\.0" invalid: should be v2\.0\.0\+incompatible \(or module example\.com/m/v2\)$' ! go mod edit -exclude=example.com/m/v2@v1.0.0 -stderr '^go mod: -exclude=example.com/m/v2@v1\.0\.0: version "v1\.0\.0" invalid: should be v2, not v1$' +stderr '^go: -exclude=example.com/m/v2@v1\.0\.0: version "v1\.0\.0" invalid: should be v2, not v1$' ! go mod edit -exclude=gopkg.in/example.v1@v2.0.0 -stderr '^go mod: -exclude=gopkg\.in/example\.v1@v2\.0\.0: version "v2\.0\.0" invalid: should be v1, not v2$' +stderr '^go: -exclude=gopkg\.in/example\.v1@v2\.0\.0: version "v2\.0\.0" invalid: should be v1, not v2$' cmpenv go.mod $WORK/go.mod.edit2 diff --git a/src/cmd/go/testdata/script/mod_get_changes.txt b/src/cmd/go/testdata/script/mod_get_changes.txt index 3287b2a609..2829111fe5 100644 --- a/src/cmd/go/testdata/script/mod_get_changes.txt +++ b/src/cmd/go/testdata/script/mod_get_changes.txt @@ -4,8 +4,8 @@ go list -m all ! stdout golang.org/x/text go get -d rsc.io/quote@v1.5.2 -stderr '^go get: added rsc.io/quote v1.5.2$' -stderr '^go get: upgraded rsc.io/sampler v1.0.0 => v1.3.0$' +stderr '^go: added rsc.io/quote v1.5.2$' +stderr '^go: upgraded rsc.io/sampler v1.0.0 => v1.3.0$' ! stderr '^go get.*golang.org/x/text' go list -m all stdout golang.org/x/text @@ -15,8 +15,8 @@ cmp go.mod go.mod.upgrade # and for changed explicit dependencies. 'go get' does not print messages # for changed indirect dependencies. go get -d rsc.io/sampler@none -stderr '^go get: downgraded rsc.io/quote v1.5.2 => v1.3.0$' -stderr '^go get: removed rsc.io/sampler v1.3.0$' +stderr '^go: downgraded rsc.io/quote v1.5.2 => v1.3.0$' +stderr '^go: removed rsc.io/sampler v1.3.0$' ! stderr '^go get.*golang.org/x/text' cmp go.mod go.mod.downgrade @@ -24,8 +24,8 @@ cmp go.mod go.mod.downgrade # for explicit dependencies removed as a consequence. cp go.mod.usequote go.mod go get -d rsc.io/quote@v1.5.1 -stderr '^go get: downgraded rsc.io/quote v1.5.2 => v1.5.1$' -stderr '^go get: removed usequote v0.0.0$' +stderr '^go: downgraded rsc.io/quote v1.5.2 => v1.5.1$' +stderr '^go: removed usequote v0.0.0$' -- go.mod -- module m diff --git a/src/cmd/go/testdata/script/mod_get_deprecate_install.txt b/src/cmd/go/testdata/script/mod_get_deprecate_install.txt index 63cd27a42d..e8142afee9 100644 --- a/src/cmd/go/testdata/script/mod_get_deprecate_install.txt +++ b/src/cmd/go/testdata/script/mod_get_deprecate_install.txt @@ -4,7 +4,7 @@ env GO111MODULE=on # 'go get' outside a module with an executable prints a deprecation message. go get example.com/cmd/a -stderr '^go get: installing executables with ''go get'' in module mode is deprecated.$' +stderr '^go: installing executables with ''go get'' in module mode is deprecated.$' stderr 'Use ''go install pkg@version'' instead.' cp go.mod.orig go.mod @@ -18,7 +18,7 @@ cp go.mod.orig go.mod # 'go get' inside a module with an executable prints a different # deprecation message. go get example.com/cmd/a -stderr '^go get: installing executables with ''go get'' in module mode is deprecated.$' +stderr '^go: installing executables with ''go get'' in module mode is deprecated.$' stderr 'To adjust and download dependencies of the current module, use ''go get -d''' cp go.mod.orig go.mod diff --git a/src/cmd/go/testdata/script/mod_get_downgrade.txt b/src/cmd/go/testdata/script/mod_get_downgrade.txt index c26c5e1c21..685bde7efd 100644 --- a/src/cmd/go/testdata/script/mod_get_downgrade.txt +++ b/src/cmd/go/testdata/script/mod_get_downgrade.txt @@ -20,8 +20,8 @@ stdout 'rsc.io/quote v1.5.1' stdout 'rsc.io/sampler v1.3.0' ! go get -d rsc.io/sampler@v1.0.0 rsc.io/quote@v1.5.2 golang.org/x/text@none -stderr -count=1 '^go get:' -stderr '^go get: rsc.io/quote@v1.5.2 requires rsc.io/sampler@v1.3.0, not rsc.io/sampler@v1.0.0$' +! stderr add|remove|upgrad|downgrad +stderr '^go: rsc.io/quote@v1.5.2 requires rsc.io/sampler@v1.3.0, not rsc.io/sampler@v1.0.0$' go list -m all stdout 'rsc.io/quote v1.5.1' diff --git a/src/cmd/go/testdata/script/mod_get_downgrade_missing.txt b/src/cmd/go/testdata/script/mod_get_downgrade_missing.txt index 5b768faeb1..2068cae755 100644 --- a/src/cmd/go/testdata/script/mod_get_downgrade_missing.txt +++ b/src/cmd/go/testdata/script/mod_get_downgrade_missing.txt @@ -5,7 +5,7 @@ cp go.mod go.mod.orig # rather than a "matched no packages" warning. ! go get -d example.net/pkgadded@v1.1.0 example.net/pkgadded/subpkg/... -stderr '^go get: example.net/pkgadded@v1.1.0 conflicts with example.net/pkgadded/subpkg/...@upgrade \(v1.2.0\)$' +stderr '^go: example.net/pkgadded@v1.1.0 conflicts with example.net/pkgadded/subpkg/...@upgrade \(v1.2.0\)$' ! stderr 'matched no packages' cmp go.mod.orig go.mod diff --git a/src/cmd/go/testdata/script/mod_get_go_file.txt b/src/cmd/go/testdata/script/mod_get_go_file.txt index 0c7b5dc11c..35a77a9d83 100644 --- a/src/cmd/go/testdata/script/mod_get_go_file.txt +++ b/src/cmd/go/testdata/script/mod_get_go_file.txt @@ -17,7 +17,7 @@ env GO111MODULE=on # argument has .go suffix, is a file and exists ! go get test.go -stderr 'go get test.go: arguments must be package or module paths' +stderr 'go: test.go: arguments must be package or module paths' # argument has .go suffix, doesn't exist and has no slashes ! go get test_missing.go @@ -25,7 +25,7 @@ stderr 'arguments must be package or module paths' # argument has .go suffix, is a file and exists in sub-directory ! go get test/test.go -stderr 'go get: test/test.go exists as a file, but ''go get'' requires package arguments' +stderr 'go: test/test.go exists as a file, but ''go get'' requires package arguments' # argument has .go suffix, doesn't exist and has slashes ! go get test/test_missing.go @@ -35,19 +35,19 @@ stderr 'go get: test/test.go exists as a file, but ''go get'' requires package a # argument has .go suffix, is a symlink and exists [symlink] symlink test_sym.go -> test.go [symlink] ! go get test_sym.go -[symlink] stderr 'go get test_sym.go: arguments must be package or module paths' +[symlink] stderr 'go: test_sym.go: arguments must be package or module paths' [symlink] rm test_sym.go # argument has .go suffix, is a symlink and exists in sub-directory [symlink] symlink test/test_sym.go -> test.go [symlink] ! go get test/test_sym.go -[symlink] stderr 'go get: test/test_sym.go exists as a file, but ''go get'' requires package arguments' +[symlink] stderr 'go: test/test_sym.go exists as a file, but ''go get'' requires package arguments' [symlink] rm test_sym.go # argument has .go suffix, is a directory and exists mkdir test_dir.go ! go get test_dir.go -stderr 'go get test_dir.go: arguments must be package or module paths' +stderr 'go: test_dir.go: arguments must be package or module paths' rm test_dir.go # argument has .go suffix, is a directory and exists in sub-directory diff --git a/src/cmd/go/testdata/script/mod_get_main.txt b/src/cmd/go/testdata/script/mod_get_main.txt index 50b2fee9ae..5c9b762543 100644 --- a/src/cmd/go/testdata/script/mod_get_main.txt +++ b/src/cmd/go/testdata/script/mod_get_main.txt @@ -3,13 +3,13 @@ cp go.mod.orig go.mod # relative and absolute paths must be within the main module. ! go get -d .. -stderr '^go get: \.\. \('$WORK'[/\\]gopath\) is not within module rooted at '$WORK'[/\\]gopath[/\\]src$' +stderr '^go: \.\. \('$WORK'[/\\]gopath\) is not within module rooted at '$WORK'[/\\]gopath[/\\]src$' ! go get -d $WORK -stderr '^go get: '$WORK' is not within module rooted at '$WORK'[/\\]gopath[/\\]src$' +stderr '^go: '$WORK' is not within module rooted at '$WORK'[/\\]gopath[/\\]src$' ! go get -d ../... -stderr '^go get: \.\./\.\.\. \('$WORK'[/\\]gopath([/\\]...)?\) is not within module rooted at '$WORK'[/\\]gopath[/\\]src$' +stderr '^go: \.\./\.\.\. \('$WORK'[/\\]gopath([/\\]...)?\) is not within module rooted at '$WORK'[/\\]gopath[/\\]src$' ! go get -d $WORK/... -stderr '^go get: '$WORK'[/\\]\.\.\. is not within module rooted at '$WORK'[/\\]gopath[/\\]src$' +stderr '^go: '$WORK'[/\\]\.\.\. is not within module rooted at '$WORK'[/\\]gopath[/\\]src$' # @patch and @latest within the main module refer to the current version. # The main module won't be upgraded, but missing dependencies will be added. @@ -31,15 +31,15 @@ grep 'rsc.io/quote v1.5.1' go.mod # The main module cannot be updated to a specific version. ! go get -d rsc.io@v0.1.0 -stderr '^go get: can''t request version "v0.1.0" of the main module \(rsc.io\)$' +stderr '^go: can''t request version "v0.1.0" of the main module \(rsc.io\)$' # A package in the main module can't be upgraded either. ! go get -d rsc.io/x@v0.1.0 -stderr '^go get: package rsc.io/x is in the main module, so can''t request version v0.1.0$' +stderr '^go: package rsc.io/x is in the main module, so can''t request version v0.1.0$' # Nor can a pattern matching packages in the main module. ! go get -d rsc.io/x/...@latest -stderr '^go get: pattern rsc.io/x/... matches package rsc.io/x in the main module, so can''t request version latest$' +stderr '^go: pattern rsc.io/x/... matches package rsc.io/x in the main module, so can''t request version latest$' -- go.mod.orig -- module rsc.io diff --git a/src/cmd/go/testdata/script/mod_get_newcycle.txt b/src/cmd/go/testdata/script/mod_get_newcycle.txt index f71620c1bc..18dc650361 100644 --- a/src/cmd/go/testdata/script/mod_get_newcycle.txt +++ b/src/cmd/go/testdata/script/mod_get_newcycle.txt @@ -11,4 +11,4 @@ go mod init m cmp stderr stderr-expected -- stderr-expected -- -go get: example.com/newcycle/a@v1.0.0 requires example.com/newcycle/a@v1.0.1, not example.com/newcycle/a@v1.0.0 +go: example.com/newcycle/a@v1.0.0 requires example.com/newcycle/a@v1.0.1, not example.com/newcycle/a@v1.0.0 diff --git a/src/cmd/go/testdata/script/mod_get_nopkgs.txt b/src/cmd/go/testdata/script/mod_get_nopkgs.txt index 078e71a041..2711f93498 100644 --- a/src/cmd/go/testdata/script/mod_get_nopkgs.txt +++ b/src/cmd/go/testdata/script/mod_get_nopkgs.txt @@ -16,7 +16,7 @@ go get -d example.net/emptysubdir/... # control case ! go get -d example.net/emptysubdir/subdir/... ! stderr 'matched no packages' -stderr '^go get example\.net/emptysubdir/subdir/\.\.\.: module example\.net/emptysubdir/subdir: reading http://.*: 404 Not Found\n\tserver response: 404 page not found\n\z' +stderr '^go: example\.net/emptysubdir/subdir/\.\.\.: module example\.net/emptysubdir/subdir: reading http://.*: 404 Not Found\n\tserver response: 404 page not found\n\z' # It doesn't make sense to 'go get' a path in the standard library, # since the standard library necessarily can't have unresolved imports. @@ -27,7 +27,7 @@ stderr '^go get example\.net/emptysubdir/subdir/\.\.\.: module example\.net/empt # which isn't ideal either. ! go get -d builtin/... # in GOROOT/src, but contains no packages -stderr '^go get builtin/...: malformed module path "builtin": missing dot in first path element$' +stderr '^go: builtin/...: malformed module path "builtin": missing dot in first path element$' -- go.mod -- module example.net/emptysubdir diff --git a/src/cmd/go/testdata/script/mod_get_patch.txt b/src/cmd/go/testdata/script/mod_get_patch.txt index 053ef62147..5957a360b0 100644 --- a/src/cmd/go/testdata/script/mod_get_patch.txt +++ b/src/cmd/go/testdata/script/mod_get_patch.txt @@ -8,7 +8,7 @@ cp go.mod go.mod.orig # at the start of 'go get', not the version after applying other changes. ! go get -d example.net/a@v0.2.0 example.net/b@patch -stderr '^go get: example.net/a@v0.2.0 requires example.net/b@v0.2.0, not example.net/b@patch \(v0.1.1\)$' +stderr '^go: example.net/a@v0.2.0 requires example.net/b@v0.2.0, not example.net/b@patch \(v0.1.1\)$' cmp go.mod go.mod.orig @@ -19,7 +19,7 @@ cmp go.mod go.mod.orig # TODO(#42360): Reconsider the change in defaults. ! go get -d -u=patch example.net/a@v0.2.0 example.net/b -stderr '^go get: example.net/a@v0.2.0 requires example.net/b@v0.2.0, not example.net/b@patch \(v0.1.1\)$' +stderr '^go: example.net/a@v0.2.0 requires example.net/b@v0.2.0, not example.net/b@patch \(v0.1.1\)$' cmp go.mod go.mod.orig @@ -38,7 +38,7 @@ stdout '^example.net/b v0.2.1 ' cp go.mod.orig go.mod ! go get -u=patch all -stderr '^go get: example.net/a@v0.1.1 \(matching all@patch\) requires example.net/b@v0.2.0, not example.net/b@v0.1.1 \(matching all@patch\)$' +stderr '^go: example.net/a@v0.1.1 \(matching all@patch\) requires example.net/b@v0.2.0, not example.net/b@v0.1.1 \(matching all@patch\)$' cmp go.mod go.mod.orig diff --git a/src/cmd/go/testdata/script/mod_get_patchcycle.txt b/src/cmd/go/testdata/script/mod_get_patchcycle.txt index d1db56f935..6600109d2d 100644 --- a/src/cmd/go/testdata/script/mod_get_patchcycle.txt +++ b/src/cmd/go/testdata/script/mod_get_patchcycle.txt @@ -6,7 +6,7 @@ # (It used to print v0.1.1 but then silently upgrade to v0.2.0.) ! go get example.net/a@patch -stderr '^go get: example.net/a@patch \(v0.1.1\) requires example.net/a@v0.2.0, not example.net/a@patch \(v0.1.1\)$' # TODO: A mention of b v0.1.0 would be nice. +stderr '^go: example.net/a@patch \(v0.1.1\) requires example.net/a@v0.2.0, not example.net/a@patch \(v0.1.1\)$' # TODO: A mention of b v0.1.0 would be nice. -- go.mod -- module example diff --git a/src/cmd/go/testdata/script/mod_get_patchmod.txt b/src/cmd/go/testdata/script/mod_get_patchmod.txt index e39d13a0f4..bc1859edc2 100644 --- a/src/cmd/go/testdata/script/mod_get_patchmod.txt +++ b/src/cmd/go/testdata/script/mod_get_patchmod.txt @@ -16,7 +16,7 @@ cp go.mod go.mod.orig # not upgraded to the latest patch of the new transitive dependency. ! go get -d example.net/pkgremoved@patch example.net/other@v0.1.0 -stderr '^go get: example.net/other@v0.1.0 requires example.net/pkgremoved@v0.2.0, not example.net/pkgremoved@patch \(v0.1.1\)$' +stderr '^go: example.net/other@v0.1.0 requires example.net/pkgremoved@v0.2.0, not example.net/pkgremoved@patch \(v0.1.1\)$' cmp go.mod.orig go.mod diff --git a/src/cmd/go/testdata/script/mod_get_patterns.txt b/src/cmd/go/testdata/script/mod_get_patterns.txt index aee4374dc8..3b5ab43339 100644 --- a/src/cmd/go/testdata/script/mod_get_patterns.txt +++ b/src/cmd/go/testdata/script/mod_get_patterns.txt @@ -10,11 +10,11 @@ grep 'require rsc.io/quote' go.mod cp go.mod.orig go.mod ! go get -d rsc.io/quote/x... -stderr 'go get: module rsc.io/quote@upgrade found \(v1.5.2\), but does not contain packages matching rsc.io/quote/x...' +stderr 'go: module rsc.io/quote@upgrade found \(v1.5.2\), but does not contain packages matching rsc.io/quote/x...' ! grep 'require rsc.io/quote' go.mod ! go get -d rsc.io/quote/x/... -stderr 'go get: module rsc.io/quote@upgrade found \(v1.5.2\), but does not contain packages matching rsc.io/quote/x/...' +stderr 'go: module rsc.io/quote@upgrade found \(v1.5.2\), but does not contain packages matching rsc.io/quote/x/...' ! grep 'require rsc.io/quote' go.mod # If a pattern matches no packages within a module, the module should not diff --git a/src/cmd/go/testdata/script/mod_get_pkgtags.txt b/src/cmd/go/testdata/script/mod_get_pkgtags.txt index 0c79ec71b7..2e2ab72032 100644 --- a/src/cmd/go/testdata/script/mod_get_pkgtags.txt +++ b/src/cmd/go/testdata/script/mod_get_pkgtags.txt @@ -59,7 +59,7 @@ stderr '^example.net/testonly tested by\n\texample.net/testonly\.test imports\n\ # but fail for a non-package subdirectory of a module. ! go get -d example.net/missing/subdir@v0.1.0 -stderr '^go get: module example.net/missing@v0.1.0 found \(replaced by ./missing\), but does not contain package example.net/missing/subdir$' +stderr '^go: module example.net/missing@v0.1.0 found \(replaced by ./missing\), but does not contain package example.net/missing/subdir$' go get -d example.net/missing@v0.1.0 @@ -68,7 +68,7 @@ go get -d example.net/missing@v0.1.0 # module is already present in the build list. ! go get -d example.net/missing/subdir@v0.1.0 -stderr '^go get: module example.net/missing@v0.1.0 found \(replaced by ./missing\), but does not contain package example.net/missing/subdir$' +stderr '^go: module example.net/missing@v0.1.0 found \(replaced by ./missing\), but does not contain package example.net/missing/subdir$' -- go.mod -- diff --git a/src/cmd/go/testdata/script/mod_get_private_vcs.txt b/src/cmd/go/testdata/script/mod_get_private_vcs.txt index 75c776a7fa..c8862f42f9 100644 --- a/src/cmd/go/testdata/script/mod_get_private_vcs.txt +++ b/src/cmd/go/testdata/script/mod_get_private_vcs.txt @@ -13,7 +13,7 @@ stderr 'If this is a private repository, see https://golang.org/doc/faq#git_http # Fetching a nonexistent commit should return an "unknown revision" # error message. ! go get github.com/golang/term@86186f3aba07ed0212cfb944f3398997d2d07c6b -stderr '^go get: github.com/golang/term@86186f3aba07ed0212cfb944f3398997d2d07c6b: invalid version: unknown revision 86186f3aba07ed0212cfb944f3398997d2d07c6b$' +stderr '^go: github.com/golang/term@86186f3aba07ed0212cfb944f3398997d2d07c6b: invalid version: unknown revision 86186f3aba07ed0212cfb944f3398997d2d07c6b$' ! stdout . ! go get github.com/golang/nonexist@master diff --git a/src/cmd/go/testdata/script/mod_get_replaced.txt b/src/cmd/go/testdata/script/mod_get_replaced.txt index d97f3f1a40..ab21bd57fa 100644 --- a/src/cmd/go/testdata/script/mod_get_replaced.txt +++ b/src/cmd/go/testdata/script/mod_get_replaced.txt @@ -82,7 +82,7 @@ cp go.mod.orig go.mod ! go list example stderr '^package example is not in GOROOT \(.*\)$' ! go get -d example -stderr '^go get: malformed module path "example": missing dot in first path element$' +stderr '^go: malformed module path "example": missing dot in first path element$' go mod edit -replace example@v0.1.0=./example diff --git a/src/cmd/go/testdata/script/mod_get_split.txt b/src/cmd/go/testdata/script/mod_get_split.txt index f4e7661f9b..2fb88ab2da 100644 --- a/src/cmd/go/testdata/script/mod_get_split.txt +++ b/src/cmd/go/testdata/script/mod_get_split.txt @@ -55,7 +55,7 @@ stderr '^example.net/split/nested: ambiguous import: found package example.net/s # TODO(#27899): Should we instead upgrade or downgrade to an arbirary version? ! go get -d example.net/split/nested/...@v0.1.0 -stderr '^go get: example.net/split/nested/\.\.\.@v0.1.0 matches packages in example.net/split@v0.2.0 but not example.net/split@v0.1.0: specify a different version for module example.net/split$' +stderr '^go: example.net/split/nested/\.\.\.@v0.1.0 matches packages in example.net/split@v0.2.0 but not example.net/split@v0.1.0: specify a different version for module example.net/split$' cmp go.mod go.mod.orig diff --git a/src/cmd/go/testdata/script/mod_get_svn.txt b/src/cmd/go/testdata/script/mod_get_svn.txt index 3817fce9b6..4d6b94ae5b 100644 --- a/src/cmd/go/testdata/script/mod_get_svn.txt +++ b/src/cmd/go/testdata/script/mod_get_svn.txt @@ -27,7 +27,7 @@ exists $GOPATH/bin/hello.svn$GOEXE # reasonable message instead of a panic. ! go get -d vcs-test.golang.org/svn/nonexistent.svn ! stderr panic -stderr 'go get vcs-test.golang.org/svn/nonexistent.svn: no matching versions for query "upgrade"' +stderr 'go: vcs-test.golang.org/svn/nonexistent.svn: no matching versions for query "upgrade"' -- go.mod -- module golang/go/issues/28943/main diff --git a/src/cmd/go/testdata/script/mod_get_wild.txt b/src/cmd/go/testdata/script/mod_get_wild.txt index 78c645c6b9..b88f268a1d 100644 --- a/src/cmd/go/testdata/script/mod_get_wild.txt +++ b/src/cmd/go/testdata/script/mod_get_wild.txt @@ -12,7 +12,7 @@ stdout '^example.net/a v0.1.0 ' # from attempting to resolve a new module whose path is a prefix of the pattern. ! go get -d -u=patch example.../b@upgrade -stderr '^go get: no modules to query for example\.\.\./b@upgrade because first path element contains a wildcard$' +stderr '^go: no modules to query for example\.\.\./b@upgrade because first path element contains a wildcard$' # Patching . causes a patch to example.net/a, which introduces a new match diff --git a/src/cmd/go/testdata/script/mod_getmode_vendor.txt b/src/cmd/go/testdata/script/mod_getmode_vendor.txt index 00070c03b5..a4e23ac9d0 100644 --- a/src/cmd/go/testdata/script/mod_getmode_vendor.txt +++ b/src/cmd/go/testdata/script/mod_getmode_vendor.txt @@ -11,16 +11,16 @@ stdout '^rsc.io/quote v1.5.1 .*vendor[\\/]rsc.io[\\/]quote$' stdout '^golang.org/x/text v0.0.0.* .*vendor[\\/]golang.org[\\/]x[\\/]text[\\/]language$' ! go list -mod=vendor -m rsc.io/quote@latest -stderr 'go list -m: rsc.io/quote@latest: cannot query module due to -mod=vendor' +stderr 'go: rsc.io/quote@latest: cannot query module due to -mod=vendor' ! go get -mod=vendor -u stderr 'flag provided but not defined: -mod' # Since we don't have a complete module graph, 'go list -m' queries # that require the complete graph should fail with a useful error. ! go list -mod=vendor -m all -stderr 'go list -m: can''t compute ''all'' using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)' +stderr 'go: can''t compute ''all'' using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)' ! go list -mod=vendor -m ... -stderr 'go list -m: can''t match module patterns using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)' +stderr 'go: can''t match module patterns using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)' -- go.mod -- module x diff --git a/src/cmd/go/testdata/script/mod_gonoproxy.txt b/src/cmd/go/testdata/script/mod_gonoproxy.txt index 204786969f..190940030c 100644 --- a/src/cmd/go/testdata/script/mod_gonoproxy.txt +++ b/src/cmd/go/testdata/script/mod_gonoproxy.txt @@ -27,13 +27,13 @@ stdout '^golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c$' # When GOPROXY is not empty but contains no entries, an error should be reported. env GOPROXY=',' ! go get -d golang.org/x/text -stderr '^go get golang.org/x/text: GOPROXY list is not the empty string, but contains no entries$' +stderr '^go: golang.org/x/text: GOPROXY list is not the empty string, but contains no entries$' # When GOPROXY=off, fetching modules not matched by GONOPROXY fails. env GONOPROXY=*/fortune env GOPROXY=off ! go get -d golang.org/x/text -stderr '^go get golang.org/x/text: module lookup disabled by GOPROXY=off$' +stderr '^go: golang.org/x/text: module lookup disabled by GOPROXY=off$' # GONOPROXY bypasses proxy [!net] skip diff --git a/src/cmd/go/testdata/script/mod_install_pkg_version.txt b/src/cmd/go/testdata/script/mod_install_pkg_version.txt index fd02392af1..1ee68e7ad8 100644 --- a/src/cmd/go/testdata/script/mod_install_pkg_version.txt +++ b/src/cmd/go/testdata/script/mod_install_pkg_version.txt @@ -16,7 +16,7 @@ env GO111MODULE=auto cd m cp go.mod go.mod.orig ! go list -m all -stderr '^go list -m: example.com/cmd@v1.1.0-doesnotexist: missing go.sum entry; to add it:\n\tgo mod download example.com/cmd$' +stderr '^go: example.com/cmd@v1.1.0-doesnotexist: missing go.sum entry; to add it:\n\tgo mod download example.com/cmd$' go install example.com/cmd/a@latest cmp go.mod go.mod.orig exists $GOPATH/bin/a$GOEXE @@ -81,15 +81,15 @@ env GO111MODULE=auto # 'go install pkg@version' reports errors for meta packages, std packages, # and directories. ! go install std@v1.0.0 -stderr '^go install: std@v1.0.0: argument must be a package path, not a meta-package$' +stderr '^go: std@v1.0.0: argument must be a package path, not a meta-package$' ! go install fmt@v1.0.0 -stderr '^go install: fmt@v1.0.0: argument must not be a package in the standard library$' +stderr '^go: fmt@v1.0.0: argument must not be a package in the standard library$' ! go install example.com//cmd/a@v1.0.0 -stderr '^go install: example.com//cmd/a@v1.0.0: argument must be a clean package path$' +stderr '^go: example.com//cmd/a@v1.0.0: argument must be a clean package path$' ! go install example.com/cmd/a@v1.0.0 ./x@v1.0.0 -stderr '^go install: ./x@v1.0.0: argument must be a package path, not a relative path$' +stderr '^go: ./x@v1.0.0: argument must be a package path, not a relative path$' ! go install example.com/cmd/a@v1.0.0 $GOPATH/src/x@v1.0.0 -stderr '^go install: '$WORK'[/\\]gopath/src/x@v1.0.0: argument must be a package path, not an absolute path$' +stderr '^go: '$WORK'[/\\]gopath/src/x@v1.0.0: argument must be a package path, not an absolute path$' ! go install example.com/cmd/a@v1.0.0 cmd/...@v1.0.0 stderr '^package cmd/go not provided by module example.com/cmd@v1.0.0$' @@ -106,7 +106,7 @@ stdout '^example.com/cmd v1.0.0$' env GO111MODULE=auto ! go install example.com/cmd/a@v1.0.0 example.com/cmd/b@latest -stderr '^go install: example.com/cmd/b@latest: all arguments must have the same version \(@v1.0.0\)$' +stderr '^go: example.com/cmd/b@latest: all arguments must have the same version \(@v1.0.0\)$' # 'go install pkg@version' should report an error if the arguments are in @@ -137,7 +137,7 @@ rm $GOPATH/bin # If a wildcard matches no packages, we should see a warning. ! go install example.com/cmd/nomatch...@v1.0.0 -stderr '^go install: example.com/cmd/nomatch\.\.\.@v1.0.0: module example.com/cmd@v1.0.0 found, but does not contain packages matching example.com/cmd/nomatch\.\.\.$' +stderr '^go: example.com/cmd/nomatch\.\.\.@v1.0.0: module example.com/cmd@v1.0.0 found, but does not contain packages matching example.com/cmd/nomatch\.\.\.$' go install example.com/cmd/a@v1.0.0 example.com/cmd/nomatch...@v1.0.0 stderr '^go: warning: "example.com/cmd/nomatch\.\.\." matched no packages$' @@ -159,7 +159,7 @@ cmp stderr exclude-err # 'go install pkg@version' should report an error if the module requires a # higher version of itself. ! go install example.com/cmd/a@v1.0.0-newerself -stderr '^go install: example.com/cmd/a@v1.0.0-newerself: version constraints conflict:\n\texample.com/cmd@v1.0.0-newerself requires example.com/cmd@v1.0.0, but example.com/cmd@v1.0.0-newerself is requested$' +stderr '^go: example.com/cmd/a@v1.0.0-newerself: version constraints conflict:\n\texample.com/cmd@v1.0.0-newerself requires example.com/cmd@v1.0.0, but example.com/cmd@v1.0.0-newerself is requested$' # 'go install pkg@version' will only match a retracted version if it's @@ -192,12 +192,12 @@ package main func main() {} -- replace-err -- -go install: example.com/cmd/a@v1.0.0-replace (in example.com/cmd@v1.0.0-replace): +go: example.com/cmd/a@v1.0.0-replace (in example.com/cmd@v1.0.0-replace): The go.mod file for the module providing named packages contains one or more replace directives. It must not contain directives that would cause it to be interpreted differently than if it were the main module. -- exclude-err -- -go install: example.com/cmd/a@v1.0.0-exclude (in example.com/cmd@v1.0.0-exclude): +go: example.com/cmd/a@v1.0.0-exclude (in example.com/cmd@v1.0.0-exclude): The go.mod file for the module providing named packages contains one or more exclude directives. It must not contain directives that would cause it to be interpreted differently than if it were the main module. diff --git a/src/cmd/go/testdata/script/mod_invalid_path.txt b/src/cmd/go/testdata/script/mod_invalid_path.txt index 333a3ffa35..766e9c0909 100644 --- a/src/cmd/go/testdata/script/mod_invalid_path.txt +++ b/src/cmd/go/testdata/script/mod_invalid_path.txt @@ -29,7 +29,7 @@ stdout '^example.com/dotname/.dot$' go list ./use stdout '^example.com/dotname/use$' ! go list -m example.com/dotname/.dot@latest -stderr '^go list -m: example.com/dotname/.dot@latest: malformed module path "example.com/dotname/.dot": leading dot in path element$' +stderr '^go: example.com/dotname/.dot@latest: malformed module path "example.com/dotname/.dot": leading dot in path element$' go get -d example.com/dotname/.dot go get -d example.com/dotname/use go mod tidy diff --git a/src/cmd/go/testdata/script/mod_invalid_path_plus.txt b/src/cmd/go/testdata/script/mod_invalid_path_plus.txt index 51dbf93688..6a29eb8ce0 100644 --- a/src/cmd/go/testdata/script/mod_invalid_path_plus.txt +++ b/src/cmd/go/testdata/script/mod_invalid_path_plus.txt @@ -9,7 +9,7 @@ go list example.net/cmd/x++ # 'go list -m' rejects module paths with pluses. ! go list -versions -m 'example.net/bad++' -stderr '^go list -m: malformed module path "example.net/bad\+\+": invalid char ''\+''$' +stderr '^go: malformed module path "example.net/bad\+\+": invalid char ''\+''$' # 'go get' accepts package paths with pluses. cp go.mod.orig go.mod diff --git a/src/cmd/go/testdata/script/mod_invalid_version.txt b/src/cmd/go/testdata/script/mod_invalid_version.txt index 6846a792a5..31b25f757e 100644 --- a/src/cmd/go/testdata/script/mod_invalid_version.txt +++ b/src/cmd/go/testdata/script/mod_invalid_version.txt @@ -19,7 +19,7 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text@14c0d48ead0c cd outside ! go list -m golang.org/x/text -stderr 'go list -m: example.com@v0.0.0 \(replaced by \./\.\.\): parsing ..[/\\]go.mod: '$WORK'[/\\]gopath[/\\]src[/\\]go.mod:5: require golang.org/x/text: version "14c0d48ead0c" invalid: must be of the form v1.2.3' +stderr 'go: example.com@v0.0.0 \(replaced by \./\.\.\): parsing ..[/\\]go.mod: '$WORK'[/\\]gopath[/\\]src[/\\]go.mod:5: require golang.org/x/text: version "14c0d48ead0c" invalid: must be of the form v1.2.3' cd .. go list -m golang.org/x/text stdout 'golang.org/x/text v0.1.1-0.20170915032832-14c0d48ead0c' @@ -30,7 +30,7 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text/unicode@v0.0.0-20170915032832-14c0d48ead0c cd outside ! go list -m golang.org/x/text -stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text/unicode@v0.0.0-20170915032832-14c0d48ead0c: invalid version: missing golang.org/x/text/unicode/go.mod at revision 14c0d48ead0c' +stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text/unicode@v0.0.0-20170915032832-14c0d48ead0c: invalid version: missing golang.org/x/text/unicode/go.mod at revision 14c0d48ead0c' cd .. ! go list -m golang.org/x/text stderr 'golang.org/x/text/unicode@v0.0.0-20170915032832-14c0d48ead0c: invalid version: missing golang.org/x/text/unicode/go.mod at revision 14c0d48ead0c' @@ -47,7 +47,7 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v2.1.1-0.20170915032832-14c0d48ead0c cd outside ! go list -m golang.org/x/text -stderr 'go list -m: example.com@v0.0.0 \(replaced by \./\.\.\): parsing ..[/\\]go.mod: '$WORK'[/\\]gopath[/\\]src[/\\]go.mod:5: require golang.org/x/text: version "v2.1.1-0.20170915032832-14c0d48ead0c" invalid: should be v0 or v1, not v2' +stderr 'go: example.com@v0.0.0 \(replaced by \./\.\.\): parsing ..[/\\]go.mod: '$WORK'[/\\]gopath[/\\]src[/\\]go.mod:5: require golang.org/x/text: version "v2.1.1-0.20170915032832-14c0d48ead0c" invalid: should be v0 or v1, not v2' cd .. ! go list -m golang.org/x/text stderr $WORK'[/\\]gopath[/\\]src[/\\]go.mod:5: require golang.org/x/text: version "v2.1.1-0.20170915032832-14c0d48ead0c" invalid: should be v0 or v1, not v2' @@ -57,7 +57,7 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0 cd outside ! go list -m golang.org/x/text -stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0: invalid pseudo-version: revision is shorter than canonical \(14c0d48ead0c\)' +stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0: invalid pseudo-version: revision is shorter than canonical \(14c0d48ead0c\)' cd .. ! go list -m golang.org/x/text stderr 'golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0: invalid pseudo-version: revision is shorter than canonical \(14c0d48ead0c\)' @@ -67,7 +67,7 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0cd47e3104ada247d91be04afc7a5a cd outside ! go list -m golang.org/x/text -stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0cd47e3104ada247d91be04afc7a5a: invalid pseudo-version: revision is longer than canonical \(14c0d48ead0c\)' +stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0cd47e3104ada247d91be04afc7a5a: invalid pseudo-version: revision is longer than canonical \(14c0d48ead0c\)' cd .. ! go list -m golang.org/x/text stderr 'golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0cd47e3104ada247d91be04afc7a5a: invalid pseudo-version: revision is longer than canonical \(14c0d48ead0c\)' @@ -77,7 +77,7 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c cd outside ! go list -m golang.org/x/text -stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(expected 20170915032832\)' +stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(expected 20170915032832\)' cd .. ! go list -m golang.org/x/text stderr 'golang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(expected 20170915032832\)' @@ -87,7 +87,7 @@ stderr 'golang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-v go mod edit -replace golang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c=golang.org/x/text@14c0d48ead0c cd outside ! go list -m golang.org/x/text -stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(expected 20170915032832\)' +stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(expected 20170915032832\)' cd .. go list -m golang.org/x/text stdout 'golang.org/x/text v0.1.1-0.20190915032832-14c0d48ead0c => golang.org/x/text v0.1.1-0.20170915032832-14c0d48ead0c' @@ -97,7 +97,7 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v1.999.999-0.20170915032832-14c0d48ead0c cd outside ! go list -m golang.org/x/text -stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v1.999.999-0.20170915032832-14c0d48ead0c: invalid pseudo-version: preceding tag \(v1.999.998\) not found' +stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v1.999.999-0.20170915032832-14c0d48ead0c: invalid pseudo-version: preceding tag \(v1.999.998\) not found' cd .. ! go list -m golang.org/x/text stderr 'golang.org/x/text@v1.999.999-0.20170915032832-14c0d48ead0c: invalid pseudo-version: preceding tag \(v1.999.998\) not found' @@ -109,7 +109,7 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v1.0.0-20170915032832-14c0d48ead0c cd outside ! go list -m golang.org/x/text -stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v1.0.0-20170915032832-14c0d48ead0c: invalid pseudo-version: major version without preceding tag must be v0, not v1' +stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v1.0.0-20170915032832-14c0d48ead0c: invalid pseudo-version: major version without preceding tag must be v0, not v1' cd .. ! go list -m golang.org/x/text stderr 'golang.org/x/text@v1.0.0-20170915032832-14c0d48ead0c: invalid pseudo-version: major version without preceding tag must be v0, not v1' @@ -120,7 +120,7 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c cd outside ! go list -m golang.org/x/text -stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c: invalid pseudo-version: version before v0.0.0 would have negative patch number' +stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c: invalid pseudo-version: version before v0.0.0 would have negative patch number' cd .. ! go list -m golang.org/x/text stderr 'golang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c: invalid pseudo-version: version before v0.0.0 would have negative patch number' @@ -130,7 +130,7 @@ stderr 'golang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c: invalid pseudo-v go mod edit -replace golang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c=golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c cd outside ! go list -m golang.org/x/text -stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c: invalid pseudo-version: version before v0.0.0 would have negative patch number' +stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c: invalid pseudo-version: version before v0.0.0 would have negative patch number' cd .. go list -m golang.org/x/text stdout 'golang.org/x/text v0.0.0-0.20170915032832-14c0d48ead0c => golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c' @@ -153,7 +153,7 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v0.2.1-0.20170915032832-14c0d48ead0c cd outside ! go list -m golang.org/x/text -stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.2.1-0.20170915032832-14c0d48ead0c: invalid pseudo-version: revision 14c0d48ead0c is not a descendent of preceding tag \(v0.2.0\)' +stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.2.1-0.20170915032832-14c0d48ead0c: invalid pseudo-version: revision 14c0d48ead0c is not a descendent of preceding tag \(v0.2.0\)' cd .. ! go list -m golang.org/x/text stderr 'golang.org/x/text@v0.2.1-0.20170915032832-14c0d48ead0c: invalid pseudo-version: revision 14c0d48ead0c is not a descendent of preceding tag \(v0.2.0\)' @@ -163,7 +163,7 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v0.2.1-0.20171213102548-c4d099d611ac cd outside ! go list -m golang.org/x/text -stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.2.1-0.20171213102548-c4d099d611ac: invalid pseudo-version: tag \(v0.2.0\) found on revision c4d099d611ac is already canonical, so should not be replaced with a pseudo-version derived from that tag' +stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.2.1-0.20171213102548-c4d099d611ac: invalid pseudo-version: tag \(v0.2.0\) found on revision c4d099d611ac is already canonical, so should not be replaced with a pseudo-version derived from that tag' cd .. ! go list -m golang.org/x/text stderr 'golang.org/x/text@v0.2.1-0.20171213102548-c4d099d611ac: invalid pseudo-version: tag \(v0.2.0\) found on revision c4d099d611ac is already canonical, so should not be replaced with a pseudo-version derived from that tag' @@ -173,7 +173,7 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0c+incompatible cd outside ! go list -m golang.org/x/text -stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0c\+incompatible: invalid version: \+incompatible suffix not allowed: major version v0 is compatible' +stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0c\+incompatible: invalid version: \+incompatible suffix not allowed: major version v0 is compatible' cd .. ! go list -m golang.org/x/text stderr 'golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0c\+incompatible: invalid version: \+incompatible suffix not allowed: major version v0 is compatible' @@ -194,7 +194,7 @@ cp go.mod.orig go.mod go mod edit -require github.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d+incompatible cd outside ! go list -m github.com/pierrec/lz4 -stderr 'go list -m: example.com@v0.0.0 requires\n\tgithub.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required' +stderr 'go: example.com@v0.0.0 requires\n\tgithub.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required' cd .. ! go list -m github.com/pierrec/lz4 stderr 'github.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required' @@ -222,7 +222,7 @@ stdout 'github.com/pierrec/lz4 v2.0.5\+incompatible' # not resolve to a pseudo-version with a different major version. cp go.mod.orig go.mod ! go get -d github.com/pierrec/lz4@v2.0.8 -stderr 'go get: github.com/pierrec/lz4@v2.0.8: invalid version: module contains a go.mod file, so major version must be compatible: should be v0 or v1, not v2' +stderr 'go: github.com/pierrec/lz4@v2.0.8: invalid version: module contains a go.mod file, so major version must be compatible: should be v0 or v1, not v2' # An invalid +incompatible suffix for a canonical version should error out, # not resolve to a pseudo-version. diff --git a/src/cmd/go/testdata/script/mod_list.txt b/src/cmd/go/testdata/script/mod_list.txt index 239c7caa4a..06316cc335 100644 --- a/src/cmd/go/testdata/script/mod_list.txt +++ b/src/cmd/go/testdata/script/mod_list.txt @@ -39,8 +39,8 @@ stdout '^module nonexist: not a known dependency$' stdout '^module rsc.io/quote/buggy: not a known dependency$' ! go list -m nonexist rsc.io/quote/buggy -stderr '^go list -m: module nonexist: not a known dependency' -stderr '^go list -m: module rsc.io/quote/buggy: not a known dependency' +stderr '^go: module nonexist: not a known dependency' +stderr '^go: module rsc.io/quote/buggy: not a known dependency' # Module loader does not interfere with list -e (golang.org/issue/24149). go list -e -f '{{.Error.Err}}' database diff --git a/src/cmd/go/testdata/script/mod_list_sums.txt b/src/cmd/go/testdata/script/mod_list_sums.txt index 86c528f829..6c2f57c2b2 100644 --- a/src/cmd/go/testdata/script/mod_list_sums.txt +++ b/src/cmd/go/testdata/script/mod_list_sums.txt @@ -29,4 +29,4 @@ stderr '^go: updates to go.sum needed, disabled by -mod=readonly$' # # TODO(#41297): This should not be an error either. ! go list -m -mod=readonly -versions rsc.io/sampler -stderr '^go list -m: rsc\.io/quote@v1\.5\.1: missing go\.sum entry; to add it:\n\tgo mod download rsc\.io/quote$' +stderr '^go: rsc\.io/quote@v1\.5\.1: missing go\.sum entry; to add it:\n\tgo mod download rsc\.io/quote$' diff --git a/src/cmd/go/testdata/script/mod_list_update_nolatest.txt b/src/cmd/go/testdata/script/mod_list_update_nolatest.txt index c6bbbb04ec..7eebe266db 100644 --- a/src/cmd/go/testdata/script/mod_list_update_nolatest.txt +++ b/src/cmd/go/testdata/script/mod_list_update_nolatest.txt @@ -26,7 +26,7 @@ stdout '^example.com/nolatest v0.0.0$' # If proxy returns an invalid response, we should see an error. env GOPROXY=$testproxy/invalid ! go list -m -u example.com/nolatest -stderr '^go list -m: loading module retractions for example.com/nolatest@v0.0.0: invalid response from proxy "[^"]*": invalid character ''i'' looking for beginning of value$' +stderr '^go: loading module retractions for example.com/nolatest@v0.0.0: invalid response from proxy "[^"]*": invalid character ''i'' looking for beginning of value$' -- go.mod -- module m diff --git a/src/cmd/go/testdata/script/mod_load_badchain.txt b/src/cmd/go/testdata/script/mod_load_badchain.txt index eb464ab0d3..0c4e5e1714 100644 --- a/src/cmd/go/testdata/script/mod_load_badchain.txt +++ b/src/cmd/go/testdata/script/mod_load_badchain.txt @@ -69,17 +69,17 @@ import ( func Test(t *testing.T) {} -- update-main-expected -- -go get: example.com/badchain/c@v1.1.0: parsing go.mod: +go: example.com/badchain/c@v1.1.0: parsing go.mod: module declares its path as: badchain.example.com/c but was required as: example.com/badchain/c -- update-a-expected -- -go get: example.com/badchain/a@v1.1.0 requires +go: example.com/badchain/a@v1.1.0 requires example.com/badchain/b@v1.1.0 requires example.com/badchain/c@v1.1.0: parsing go.mod: module declares its path as: badchain.example.com/c but was required as: example.com/badchain/c -- list-expected -- -go list -m: example.com/badchain/a@v1.1.0 requires +go: example.com/badchain/a@v1.1.0 requires example.com/badchain/b@v1.1.0 requires example.com/badchain/c@v1.1.0: parsing go.mod: module declares its path as: badchain.example.com/c diff --git a/src/cmd/go/testdata/script/mod_outside.txt b/src/cmd/go/testdata/script/mod_outside.txt index 3b4559405a..6da6314b79 100644 --- a/src/cmd/go/testdata/script/mod_outside.txt +++ b/src/cmd/go/testdata/script/mod_outside.txt @@ -135,12 +135,12 @@ stderr '^go: go.mod file not found in current directory or any parent directory; # 'go get -u all' upgrades the transitive import graph of the main module, # which is empty. ! go get -u all -stderr '^go get: cannot match "all": go.mod file not found in current directory or any parent directory; see ''go help modules''$' +stderr '^go: cannot match "all": go.mod file not found in current directory or any parent directory; see ''go help modules''$' # 'go get' should check the proposed module graph for consistency, # even though we won't write it anywhere. ! go get -d example.com/printversion@v1.0.0 example.com/version@none -stderr '^go get: example.com/printversion@v1.0.0 requires example.com/version@v1.0.0, not example.com/version@none$' +stderr '^go: example.com/printversion@v1.0.0 requires example.com/version@v1.0.0, not example.com/version@none$' # 'go get -d' should download and extract the source code needed to build the requested version. rm -r $GOPATH/pkg/mod/example.com @@ -196,7 +196,7 @@ exists $GOPATH/bin/printversion$GOEXE # 'go install' should fail if a package argument must be resolved to a module. ! go install example.com/printversion -stderr '^go install: version is required when current directory is not in a module\n\tTry ''go install example.com/printversion@latest'' to install the latest version$' +stderr '^go: ''go install'' requires a version when current directory is not in a module\n\tTry ''go install example.com/printversion@latest'' to install the latest version$' # 'go install' should fail if a source file imports a package that must be # resolved to a module. diff --git a/src/cmd/go/testdata/script/mod_prefer_compatible.txt b/src/cmd/go/testdata/script/mod_prefer_compatible.txt index 1b408c3e9e..8e88997a3c 100644 --- a/src/cmd/go/testdata/script/mod_prefer_compatible.txt +++ b/src/cmd/go/testdata/script/mod_prefer_compatible.txt @@ -24,7 +24,7 @@ go list -m github.com/russross/blackfriday@upgrade stdout '^github.com/russross/blackfriday v1\.' ! go list -m github.com/russross/blackfriday@patch -stderr '^go list -m: github.com/russross/blackfriday@patch: can''t query version "patch" of module github.com/russross/blackfriday: no existing version is required$' +stderr '^go: github.com/russross/blackfriday@patch: can''t query version "patch" of module github.com/russross/blackfriday: no existing version is required$' # If we're fetching directly from version control, ignored +incompatible # versions should also be omitted by 'go list'. diff --git a/src/cmd/go/testdata/script/mod_proxy_invalid.txt b/src/cmd/go/testdata/script/mod_proxy_invalid.txt index 6427cc1527..63980b839e 100644 --- a/src/cmd/go/testdata/script/mod_proxy_invalid.txt +++ b/src/cmd/go/testdata/script/mod_proxy_invalid.txt @@ -2,7 +2,7 @@ env GO111MODULE=on env GOPROXY=$GOPROXY/invalid ! go list -m rsc.io/quote@latest -stderr '^go list -m: module rsc.io/quote: invalid response from proxy "'$GOPROXY'": invalid character ''i'' looking for beginning of value$' +stderr '^go: module rsc.io/quote: invalid response from proxy "'$GOPROXY'": invalid character ''i'' looking for beginning of value$' ! go list -m rsc.io/quote@1.5.2 -stderr '^go list -m: rsc.io/quote@1.5.2: invalid version: invalid response from proxy "'$GOPROXY'": invalid character ''i'' looking for beginning of value$' +stderr '^go: rsc.io/quote@1.5.2: invalid version: invalid response from proxy "'$GOPROXY'": invalid character ''i'' looking for beginning of value$' diff --git a/src/cmd/go/testdata/script/mod_query.txt b/src/cmd/go/testdata/script/mod_query.txt index a75f86ed7c..3758732504 100644 --- a/src/cmd/go/testdata/script/mod_query.txt +++ b/src/cmd/go/testdata/script/mod_query.txt @@ -25,7 +25,7 @@ go list -m rsc.io/quote@v1.5.3 -stderr 'go list -m: module rsc.io/quote: no matching versions for query ">v1.5.3"' +stderr 'go: module rsc.io/quote: no matching versions for query ">v1.5.3"' go list -m -e -f '{{.Error.Err}}' rsc.io/quote@>v1.5.3 stdout 'no matching versions for query ">v1.5.3"' diff --git a/src/cmd/go/testdata/script/mod_query_empty.txt b/src/cmd/go/testdata/script/mod_query_empty.txt index f8b6e3e97e..af0871173e 100644 --- a/src/cmd/go/testdata/script/mod_query_empty.txt +++ b/src/cmd/go/testdata/script/mod_query_empty.txt @@ -8,7 +8,7 @@ go mod download example.com/join@v1.1.0 env GOPROXY=file:///$WORK/badproxy cp go.mod.orig go.mod ! go get -d example.com/join/subpkg -stderr 'go get: example.com/join/subpkg@v0.0.0-20190624000000-123456abcdef: .*' +stderr 'go: example.com/join/subpkg@v0.0.0-20190624000000-123456abcdef: .*' # If @v/list is empty, the 'go' command should still try to resolve # other module paths. @@ -40,7 +40,7 @@ env GOPROXY=file:///$WORK/gatekeeper chmod 0000 $WORK/gatekeeper/example.com/join/subpkg/@latest cp go.mod.orig go.mod ! go get -d example.com/join/subpkg -stderr 'go get: module example.com/join/subpkg: (invalid response from proxy ".+": invalid character .+|reading file://.*/gatekeeper/example.com/join/subpkg/@latest: .+)' +stderr 'go: module example.com/join/subpkg: (invalid response from proxy ".+": invalid character .+|reading file://.*/gatekeeper/example.com/join/subpkg/@latest: .+)' -- go.mod.orig -- module example.com/othermodule diff --git a/src/cmd/go/testdata/script/mod_query_exclude.txt b/src/cmd/go/testdata/script/mod_query_exclude.txt index b001969411..8eae42dec6 100644 --- a/src/cmd/go/testdata/script/mod_query_exclude.txt +++ b/src/cmd/go/testdata/script/mod_query_exclude.txt @@ -19,7 +19,7 @@ stdout '^rsc.io/quote v1.5.1$' # get excluded version cp go.exclude.mod go.exclude.mod.orig ! go get -modfile=go.exclude.mod -d rsc.io/quote@v1.5.0 -stderr '^go get: rsc.io/quote@v1.5.0: excluded by go.mod$' +stderr '^go: rsc.io/quote@v1.5.0: excluded by go.mod$' # get non-excluded version cp go.exclude.mod.orig go.exclude.mod diff --git a/src/cmd/go/testdata/script/mod_query_main.txt b/src/cmd/go/testdata/script/mod_query_main.txt index 39e5841a9c..2a2fa42318 100644 --- a/src/cmd/go/testdata/script/mod_query_main.txt +++ b/src/cmd/go/testdata/script/mod_query_main.txt @@ -6,9 +6,9 @@ go mod download rsc.io/quote@latest # 'go mod download' will not download @upgrade or @patch, since they always # resolve to the main module. go mod download rsc.io/quote@upgrade -stderr '^go mod download: skipping argument rsc.io/quote@upgrade that resolves to the main module$' +stderr '^go: skipping download of rsc.io/quote@upgrade that resolves to the main module$' go mod download rsc.io/quote@patch -stderr '^go mod download: skipping argument rsc.io/quote@patch that resolves to the main module$' +stderr '^go: skipping download of rsc.io/quote@patch that resolves to the main module$' # 'go list -m' can show a version of the main module. go list -m rsc.io/quote@5d9f230b @@ -31,11 +31,11 @@ stdout '^rsc.io/quote$' # 'go get' will not attempt to upgrade the main module to any specific version. # See also: mod_get_main.txt. ! go get rsc.io/quote@5d9f230b -stderr '^go get: can''t request version "5d9f230b" of the main module \(rsc.io/quote\)$' +stderr '^go: can''t request version "5d9f230b" of the main module \(rsc.io/quote\)$' ! go get rsc.io/quote@v1.5.2 -stderr '^go get: can''t request version "v1.5.2" of the main module \(rsc.io/quote\)$' +stderr '^go: can''t request version "v1.5.2" of the main module \(rsc.io/quote\)$' ! go get rsc.io/quote@latest -stderr '^go get: can''t request version "latest" of the main module \(rsc.io/quote\)$' +stderr '^go: can''t request version "latest" of the main module \(rsc.io/quote\)$' -- go.mod -- module rsc.io/quote diff --git a/src/cmd/go/testdata/script/mod_replace_gopkgin.txt b/src/cmd/go/testdata/script/mod_replace_gopkgin.txt index d24f37b788..df752d9716 100644 --- a/src/cmd/go/testdata/script/mod_replace_gopkgin.txt +++ b/src/cmd/go/testdata/script/mod_replace_gopkgin.txt @@ -35,7 +35,7 @@ go list -m gopkg.in/src-d/go-git.v4 # A mismatched gopkg.in path should not be able to replace a different major version. cd ../3-to-gomod-4 ! go list -m gopkg.in/src-d/go-git.v3 -stderr '^go list -m: gopkg\.in/src-d/go-git\.v3@v3\.2\.0 \(replaced by gopkg\.in/src-d/go-git\.v3@v3\.0\.0-20190801152248-0d1a009cbb60\): version "v3\.0\.0-20190801152248-0d1a009cbb60" invalid: go\.mod has non-\.\.\.\.v3 module path "gopkg\.in/src-d/go-git\.v4" at revision 0d1a009cbb60$' +stderr '^go: gopkg\.in/src-d/go-git\.v3@v3\.2\.0 \(replaced by gopkg\.in/src-d/go-git\.v3@v3\.0\.0-20190801152248-0d1a009cbb60\): version "v3\.0\.0-20190801152248-0d1a009cbb60" invalid: go\.mod has non-\.\.\.\.v3 module path "gopkg\.in/src-d/go-git\.v4" at revision 0d1a009cbb60$' -- 4-to-4/go.mod -- module golang.org/issue/34254 diff --git a/src/cmd/go/testdata/script/mod_retract_fix_version.txt b/src/cmd/go/testdata/script/mod_retract_fix_version.txt index e45758b627..9ae49f53ab 100644 --- a/src/cmd/go/testdata/script/mod_retract_fix_version.txt +++ b/src/cmd/go/testdata/script/mod_retract_fix_version.txt @@ -15,7 +15,7 @@ cmp go.mod go.mod.want # If a retracted version doesn't match the module's major version suffx, # an error should be reported. ! go mod edit -retract=v3.0.1 -stderr '^go mod: -retract=v3.0.1: version "v3.0.1" invalid: should be v2, not v3$' +stderr '^go: -retract=v3.0.1: version "v3.0.1" invalid: should be v2, not v3$' cp go.mod.mismatch-v2 go.mod ! go list -m all stderr 'go.mod:3: retract rsc.io/quote/v2: version "v3.0.1" invalid: should be v2, not v3$' diff --git a/src/cmd/go/testdata/script/mod_retract_pseudo_base.txt b/src/cmd/go/testdata/script/mod_retract_pseudo_base.txt index eb00e8405c..d1a5e1236a 100644 --- a/src/cmd/go/testdata/script/mod_retract_pseudo_base.txt +++ b/src/cmd/go/testdata/script/mod_retract_pseudo_base.txt @@ -29,7 +29,7 @@ go list -m vcs-test.golang.org/git/retract-pseudo.git stdout '^vcs-test.golang.org/git/retract-pseudo.git v1.0.1-0.20201009173747-713affd19d7b$' ! go get -d vcs-test.golang.org/git/retract-pseudo.git@v1.0.1-0.20201009173747-64c061ed4371 -stderr '^go get: vcs-test.golang.org/git/retract-pseudo.git@v1.0.1-0.20201009173747-64c061ed4371: invalid pseudo-version: tag \(v1.0.0\) found on revision 64c061ed4371 is already canonical, so should not be replaced with a pseudo-version derived from that tag$' +stderr '^go: vcs-test.golang.org/git/retract-pseudo.git@v1.0.1-0.20201009173747-64c061ed4371: invalid pseudo-version: tag \(v1.0.0\) found on revision 64c061ed4371 is already canonical, so should not be replaced with a pseudo-version derived from that tag$' -- retract-pseudo.sh -- #!/bin/bash diff --git a/src/cmd/go/testdata/script/mod_run_nonmain.txt b/src/cmd/go/testdata/script/mod_run_nonmain.txt index 036755d2d1..8435fc05b4 100644 --- a/src/cmd/go/testdata/script/mod_run_nonmain.txt +++ b/src/cmd/go/testdata/script/mod_run_nonmain.txt @@ -7,7 +7,7 @@ stderr '^package example.net/nonmain is not a main package$' ! go run ./... stderr '^go: warning: "\./\.\.\." matched only non-main packages$' -stderr '^go run: no packages loaded from \./\.\.\.$' +stderr '^go: no packages loaded from \./\.\.\.$' -- go.mod -- module example.net/nonmain diff --git a/src/cmd/go/testdata/script/mod_run_pkg_version.txt b/src/cmd/go/testdata/script/mod_run_pkg_version.txt index e921fab508..c3a218d553 100644 --- a/src/cmd/go/testdata/script/mod_run_pkg_version.txt +++ b/src/cmd/go/testdata/script/mod_run_pkg_version.txt @@ -21,7 +21,7 @@ env GO111MODULE=on cd m cp go.mod go.mod.orig ! go list -m all -stderr '^go list -m: example.com/cmd@v1.1.0-doesnotexist: missing go.sum entry; to add it:\n\tgo mod download example.com/cmd$' +stderr '^go: example.com/cmd@v1.1.0-doesnotexist: missing go.sum entry; to add it:\n\tgo mod download example.com/cmd$' go run example.com/cmd/a@v1.0.0 stdout '^a@v1.0.0$' cmp go.mod go.mod.orig @@ -92,12 +92,12 @@ package main func main() {} -- replace-err -- -go run: example.com/cmd/a@v1.0.0-replace (in example.com/cmd@v1.0.0-replace): +go: example.com/cmd/a@v1.0.0-replace (in example.com/cmd@v1.0.0-replace): The go.mod file for the module providing named packages contains one or more replace directives. It must not contain directives that would cause it to be interpreted differently than if it were the main module. -- exclude-err -- -go run: example.com/cmd/a@v1.0.0-exclude (in example.com/cmd@v1.0.0-exclude): +go: example.com/cmd/a@v1.0.0-exclude (in example.com/cmd@v1.0.0-exclude): The go.mod file for the module providing named packages contains one or more exclude directives. It must not contain directives that would cause it to be interpreted differently than if it were the main module. diff --git a/src/cmd/go/testdata/script/mod_sum_readonly.txt b/src/cmd/go/testdata/script/mod_sum_readonly.txt index 113f13ea39..57c5bbeefd 100644 --- a/src/cmd/go/testdata/script/mod_sum_readonly.txt +++ b/src/cmd/go/testdata/script/mod_sum_readonly.txt @@ -4,7 +4,7 @@ env GO111MODULE=on # When a sum is needed to load the build list, we get an error for the # specific module. The .mod file is not downloaded, and go.sum is not written. ! go list -m all -stderr '^go list -m: rsc.io/quote@v1.5.2: missing go.sum entry; to add it:\n\tgo mod download rsc.io/quote$' +stderr '^go: rsc.io/quote@v1.5.2: missing go.sum entry; to add it:\n\tgo mod download rsc.io/quote$' ! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod ! exists go.sum @@ -12,7 +12,7 @@ stderr '^go list -m: rsc.io/quote@v1.5.2: missing go.sum entry; to add it:\n\tgo # we should see the same error. cp go.sum.h2only go.sum ! go list -m all -stderr '^go list -m: rsc.io/quote@v1.5.2: missing go.sum entry; to add it:\n\tgo mod download rsc.io/quote$' +stderr '^go: rsc.io/quote@v1.5.2: missing go.sum entry; to add it:\n\tgo mod download rsc.io/quote$' ! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod cmp go.sum go.sum.h2only rm go.sum @@ -21,7 +21,7 @@ rm go.sum cp go.mod go.mod.orig go mod edit -replace rsc.io/quote@v1.5.2=rsc.io/quote@v1.5.1 ! go list -m all -stderr '^go list -m: rsc.io/quote@v1.5.2 \(replaced by rsc.io/quote@v1.5.1\): missing go.sum entry; to add it:\n\tgo mod download rsc.io/quote$' +stderr '^go: rsc.io/quote@v1.5.2 \(replaced by rsc.io/quote@v1.5.1\): missing go.sum entry; to add it:\n\tgo mod download rsc.io/quote$' ! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.1.mod ! exists go.sum cp go.mod.orig go.mod diff --git a/src/cmd/go/testdata/script/mod_sumdb.txt b/src/cmd/go/testdata/script/mod_sumdb.txt index fa3483c5cb..dd791be1d4 100644 --- a/src/cmd/go/testdata/script/mod_sumdb.txt +++ b/src/cmd/go/testdata/script/mod_sumdb.txt @@ -9,7 +9,7 @@ env dbname=localhost.localdev/sumdb cp go.mod.orig go.mod env GOSUMDB=$sumdb' '$proxy/sumdb-wrong ! go get -d rsc.io/quote -stderr 'go get: rsc.io/quote@v1.5.2: verifying module: checksum mismatch' +stderr 'go: rsc.io/quote@v1.5.2: verifying module: checksum mismatch' stderr 'downloaded: h1:3fEy' stderr 'localhost.localdev/sumdb: h1:wrong' stderr 'SECURITY ERROR\nThis download does NOT match the one reported by the checksum server.' diff --git a/src/cmd/go/testdata/script/mod_sumdb_file_path.txt b/src/cmd/go/testdata/script/mod_sumdb_file_path.txt index 22fcbf3de8..575c7c4817 100644 --- a/src/cmd/go/testdata/script/mod_sumdb_file_path.txt +++ b/src/cmd/go/testdata/script/mod_sumdb_file_path.txt @@ -13,7 +13,7 @@ env GOPATH=$WORK/gopath1 [windows] env GOPROXY=file:///$WORK/sumproxy,https://proxy.golang.org [!windows] env GOPROXY=file://$WORK/sumproxy,https://proxy.golang.org ! go get -d golang.org/x/text@v0.3.2 -stderr '^go get: golang.org/x/text@v0.3.2: verifying module: golang.org/x/text@v0.3.2: reading file://.*/sumdb/sum.golang.org/lookup/golang.org/x/text@v0.3.2: (no such file or directory|.*cannot find the path specified.*)' +stderr '^go: golang.org/x/text@v0.3.2: verifying module: golang.org/x/text@v0.3.2: reading file://.*/sumdb/sum.golang.org/lookup/golang.org/x/text@v0.3.2: (no such file or directory|.*cannot find the path specified.*)' # If the proxy does not claim to support the database, # checksum verification should fall through to the next proxy, diff --git a/src/cmd/go/testdata/script/mod_tidy_compat.txt b/src/cmd/go/testdata/script/mod_tidy_compat.txt index 29cae17881..18b297da60 100644 --- a/src/cmd/go/testdata/script/mod_tidy_compat.txt +++ b/src/cmd/go/testdata/script/mod_tidy_compat.txt @@ -50,7 +50,7 @@ cmp stdout m_all.txt go mod edit -go=1.16 ! go list -m all -stderr '^go list -m: example.net/lazy@v0.1.0 requires\n\texample.com/version@v1.0.1: missing go.sum entry; to add it:\n\tgo mod download example.com/version$' +stderr '^go: example.net/lazy@v0.1.0 requires\n\texample.com/version@v1.0.1: missing go.sum entry; to add it:\n\tgo mod download example.com/version$' -- go.mod -- diff --git a/src/cmd/go/testdata/script/mod_tidy_compat_ambiguous.txt b/src/cmd/go/testdata/script/mod_tidy_compat_ambiguous.txt index c544cb7413..44bc58cc6c 100644 --- a/src/cmd/go/testdata/script/mod_tidy_compat_ambiguous.txt +++ b/src/cmd/go/testdata/script/mod_tidy_compat_ambiguous.txt @@ -62,7 +62,7 @@ cmp stdout all-m.txt go mod edit -go=1.16 ! go list -m all -stderr '^go list -m: example\.net/indirect@v0\.1\.0 requires\n\texample\.net/ambiguous@v0\.1\.0: missing go\.sum entry; to add it:\n\tgo mod download example\.net/ambiguous\n' +stderr '^go: example\.net/indirect@v0\.1\.0 requires\n\texample\.net/ambiguous@v0\.1\.0: missing go\.sum entry; to add it:\n\tgo mod download example\.net/ambiguous\n' -- go.mod -- diff --git a/src/cmd/go/testdata/script/mod_tidy_too_new.txt b/src/cmd/go/testdata/script/mod_tidy_too_new.txt index b9c53b510d..8c34a997c9 100644 --- a/src/cmd/go/testdata/script/mod_tidy_too_new.txt +++ b/src/cmd/go/testdata/script/mod_tidy_too_new.txt @@ -9,7 +9,7 @@ cp go.mod go.mod.orig # would look like. ! go mod tidy -stderr 'go mod tidy: go.mod file indicates go 2000.0, but maximum supported version is '$goversion'$' +stderr 'go: go.mod file indicates go 2000.0, but maximum version supported by tidy is '$goversion'$' cmp go.mod go.mod.orig @@ -18,7 +18,7 @@ cmp go.mod go.mod.orig cp go.mod.orig go.mod go mod tidy -e -stderr 'go mod tidy: go.mod file indicates go 2000.0, but maximum supported version is '$goversion'$' +stderr 'go: go.mod file indicates go 2000.0, but maximum version supported by tidy is '$goversion'$' cmp go.mod go.mod.tidy diff --git a/src/cmd/go/testdata/script/mod_upgrade_patch.txt b/src/cmd/go/testdata/script/mod_upgrade_patch.txt index 8b34f8bf27..b8c178c75e 100644 --- a/src/cmd/go/testdata/script/mod_upgrade_patch.txt +++ b/src/cmd/go/testdata/script/mod_upgrade_patch.txt @@ -11,7 +11,7 @@ stdout '^patch.example.com/indirect v1.0.0' # @patch should be rejected for modules not already in the build list. ! go get -d patch.example.com/depofdirectpatch@patch -stderr '^go get: can''t query version "patch" of module patch.example.com/depofdirectpatch: no existing version is required$' +stderr '^go: can''t query version "patch" of module patch.example.com/depofdirectpatch: no existing version is required$' cmp go.mod.orig go.mod # get -u=patch, with no arguments, should patch-update all dependencies @@ -38,7 +38,7 @@ cp go.mod.orig go.mod go mod edit -droprequire=patch.example.com/direct cp go.mod go.mod.dropped ! go get -d all@patch -stderr '^go get all@patch: can''t query version "patch" of module patch.example.com/direct: no existing version is required$' +stderr '^go: all@patch: can''t query version "patch" of module patch.example.com/direct: no existing version is required$' cmp go.mod.dropped go.mod # Requesting the direct dependency with -u=patch but without an explicit version @@ -86,7 +86,7 @@ stdout '^patch.example.com/indirect v1.0.1' # Standard library packages cannot be upgraded explicitly. cp go.mod.orig go.mod ! go get cmd/vet@patch -stderr 'go get: can''t request explicit version "patch" of standard library package cmd/vet$' +stderr 'go: can''t request explicit version "patch" of standard library package cmd/vet$' # However, standard-library packages without explicit versions are fine. go get -d -u=patch -d cmd/go diff --git a/src/cmd/go/testdata/script/mod_vendor.txt b/src/cmd/go/testdata/script/mod_vendor.txt index 2622916f61..4eb80c2332 100644 --- a/src/cmd/go/testdata/script/mod_vendor.txt +++ b/src/cmd/go/testdata/script/mod_vendor.txt @@ -40,15 +40,15 @@ stdout '^v1.0.0 $' # -mod=vendor should cause 'go list' flags that look up versions to fail. ! go list -mod=vendor -versions -m x -stderr '^go list -m: can''t determine available versions using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)$' +stderr '^go: can''t determine available versions using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)$' ! go list -mod=vendor -u -m x -stderr '^go list -m: can''t determine available upgrades using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)$' +stderr '^go: can''t determine available upgrades using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)$' # 'go list -mod=vendor -m' on a transitive dependency that does not # provide vendored packages should give a helpful error rather than # 'not a known dependency'. ! go list -mod=vendor -f '{{.Version}} {{.Dir}}' -m diamondright -stderr 'go list -m: module diamondright: can''t resolve module using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)' +stderr 'go: module diamondright: can''t resolve module using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)' # 'go list -mod=mod' should report packages outside the import graph, # but 'go list -mod=vendor' should error out for them. diff --git a/src/cmd/go/testdata/script/mod_vendor_auto.txt b/src/cmd/go/testdata/script/mod_vendor_auto.txt index b0ea907206..96db5c1600 100644 --- a/src/cmd/go/testdata/script/mod_vendor_auto.txt +++ b/src/cmd/go/testdata/script/mod_vendor_auto.txt @@ -17,10 +17,10 @@ stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]printversion$' stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]version$' ! go list -m all -stderr 'go list -m: can''t compute ''all'' using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)' +stderr 'go: can''t compute ''all'' using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)' ! go list -m -f '{{.Dir}}' all -stderr 'go list -m: can''t compute ''all'' using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)' +stderr 'go: can''t compute ''all'' using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)' # An explicit -mod=mod should force the vendor directory to be ignored. env GOFLAGS=-mod=mod @@ -105,10 +105,10 @@ stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]version$' # ...but 'go list -m' should continue to fail, this time without # referring to a -mod default that the user didn't set. ! go list -m all -stderr 'go list -m: can''t compute ''all'' using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)' +stderr 'go: can''t compute ''all'' using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)' ! go list -m -f '{{.Dir}}' all -stderr 'go list -m: can''t compute ''all'' using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)' +stderr 'go: can''t compute ''all'' using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)' # 'go mod init' should work if there is already a GOPATH-mode vendor directory diff --git a/src/cmd/go/testdata/script/mod_vendor_embed.txt b/src/cmd/go/testdata/script/mod_vendor_embed.txt index be114159a1..b14fd99156 100644 --- a/src/cmd/go/testdata/script/mod_vendor_embed.txt +++ b/src/cmd/go/testdata/script/mod_vendor_embed.txt @@ -6,11 +6,11 @@ cmp vendor/example.com/a/subdir/test/xtest/embed.txt a/subdir/test/xtest/embed.t cd broken_no_matching_files ! go mod vendor -stderr 'go mod vendor: pattern foo.txt: no matching files found' +stderr 'go: pattern foo.txt: no matching files found' cd ../broken_bad_pattern ! go mod vendor -stderr 'go mod vendor: pattern ../foo.txt: invalid pattern syntax' +stderr 'go: pattern ../foo.txt: invalid pattern syntax' # matchPotentialSourceFile prunes out tests and unbuilt code. # Make sure that they are vendored if they are embedded files. diff --git a/src/cmd/go/testdata/script/run_wildcard.txt b/src/cmd/go/testdata/script/run_wildcard.txt index 72036d1d8d..3e7e7b7e42 100644 --- a/src/cmd/go/testdata/script/run_wildcard.txt +++ b/src/cmd/go/testdata/script/run_wildcard.txt @@ -4,4 +4,4 @@ env GO111MODULE=off # go run x/... should not panic when directory x doesn't exist. ! go run nonexistent/... -stderr '^go run: no packages loaded from nonexistent/...$' +stderr '^go: no packages loaded from nonexistent/...$' diff --git a/src/cmd/go/testdata/script/test_flag.txt b/src/cmd/go/testdata/script/test_flag.txt index 0142b3f308..d168cfe6a8 100644 --- a/src/cmd/go/testdata/script/test_flag.txt +++ b/src/cmd/go/testdata/script/test_flag.txt @@ -9,13 +9,13 @@ go test -count=1 -custom -args -v=7 # However, it should be an error to use custom flags when -i or -c are used, # since we know for sure that no test binary will run at all. ! go test -i -custom -stderr '^go test: unknown flag -custom cannot be used with -i$' +stderr '^go: unknown flag -custom cannot be used with -i$' ! go test -c -custom -stderr '^go test: unknown flag -custom cannot be used with -c$' +stderr '^go: unknown flag -custom cannot be used with -c$' # The same should apply even if -c or -i come after a custom flag. ! go test -custom -c -stderr '^go test: unknown flag -custom cannot be used with -c$' +stderr '^go: unknown flag -custom cannot be used with -c$' -- go.mod -- module m diff --git a/src/cmd/go/testdata/script/test_race_install.txt b/src/cmd/go/testdata/script/test_race_install.txt index 8b1f343a32..a1d47a7dd3 100644 --- a/src/cmd/go/testdata/script/test_race_install.txt +++ b/src/cmd/go/testdata/script/test_race_install.txt @@ -15,4 +15,4 @@ go 1.16 -- pkg/pkg.go -- package p -- stderr.txt -- -go test: -i flag is deprecated +go: -i flag is deprecated -- GitLab From 2da3375e9b4980e368a8641f54cc53c4af4d1a12 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 20 Aug 2021 16:55:04 -0700 Subject: [PATCH 1147/2500] runtime: in adjustTimers back up as far as necessary When the adjustTimers function removed a timer it assumed it was sufficient to continue the heap traversal at that position. However, in some cases a timer will be moved to an earlier position in the heap. If that timer is timerModifiedEarlier, that can leave timerModifiedEarliest not correctly representing the earlier such timer. Fix the problem by restarting the heap traversal at the earliest changed position. Fixes #47762 Change-Id: I152bbe62793ee40a680baf49967bcb89b1f94764 Reviewed-on: https://go-review.googlesource.com/c/go/+/343882 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/runtime/time.go | 30 ++++++++++++------- src/time/sleep_test.go | 67 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 10 deletions(-) diff --git a/src/runtime/time.go b/src/runtime/time.go index ad267c3365..46e9a8c2ab 100644 --- a/src/runtime/time.go +++ b/src/runtime/time.go @@ -367,9 +367,9 @@ func deltimer(t *timer) bool { // dodeltimer removes timer i from the current P's heap. // We are locked on the P when this is called. -// It reports whether it saw no problems due to races. +// It returns the smallest changed index in pp.timers. // The caller must have locked the timers for pp. -func dodeltimer(pp *p, i int) { +func dodeltimer(pp *p, i int) int { if t := pp.timers[i]; t.pp.ptr() != pp { throw("dodeltimer: wrong P") } else { @@ -381,16 +381,18 @@ func dodeltimer(pp *p, i int) { } pp.timers[last] = nil pp.timers = pp.timers[:last] + smallestChanged := i if i != last { // Moving to i may have moved the last timer to a new parent, // so sift up to preserve the heap guarantee. - siftupTimer(pp.timers, i) + smallestChanged = siftupTimer(pp.timers, i) siftdownTimer(pp.timers, i) } if i == 0 { updateTimer0When(pp) } atomic.Xadd(&pp.numTimers, -1) + return smallestChanged } // dodeltimer0 removes timer 0 from the current P's heap. @@ -675,13 +677,14 @@ func adjusttimers(pp *p, now int64) { switch s := atomic.Load(&t.status); s { case timerDeleted: if atomic.Cas(&t.status, s, timerRemoving) { - dodeltimer(pp, i) + changed := dodeltimer(pp, i) if !atomic.Cas(&t.status, timerRemoving, timerRemoved) { badTimer() } atomic.Xadd(&pp.deletedTimers, -1) - // Look at this heap position again. - i-- + // Go back to the earliest changed heap entry. + // "- 1" because the loop will add 1. + i = changed - 1 } case timerModifiedEarlier, timerModifiedLater: if atomic.Cas(&t.status, s, timerMoving) { @@ -691,10 +694,11 @@ func adjusttimers(pp *p, now int64) { // We don't add it back yet because the // heap manipulation could cause our // loop to skip some other timer. - dodeltimer(pp, i) + changed := dodeltimer(pp, i) moved = append(moved, t) - // Look at this heap position again. - i-- + // Go back to the earliest changed heap entry. + // "- 1" because the loop will add 1. + i = changed - 1 } case timerNoStatus, timerRunning, timerRemoving, timerRemoved, timerMoving: badTimer() @@ -1044,7 +1048,10 @@ func timeSleepUntil() (int64, *p) { // "panic holding locks" message. Instead, we panic while not // holding a lock. -func siftupTimer(t []*timer, i int) { +// siftupTimer puts the timer at position i in the right place +// in the heap by moving it up toward the top of the heap. +// It returns the smallest changed index. +func siftupTimer(t []*timer, i int) int { if i >= len(t) { badTimer() } @@ -1064,8 +1071,11 @@ func siftupTimer(t []*timer, i int) { if tmp != t[i] { t[i] = tmp } + return i } +// siftdownTimer puts the timer at position i in the right place +// in the heap by moving it down toward the bottom of the heap. func siftdownTimer(t []*timer, i int) { n := len(t) if i >= n { diff --git a/src/time/sleep_test.go b/src/time/sleep_test.go index e0172bf5e0..c48e704eb7 100644 --- a/src/time/sleep_test.go +++ b/src/time/sleep_test.go @@ -7,6 +7,7 @@ package time_test import ( "errors" "fmt" + "math/rand" "runtime" "strings" "sync" @@ -561,6 +562,72 @@ func TestTimerModifiedEarlier(t *testing.T) { } } +// Test that rapidly moving timers earlier and later doesn't cause +// some of the sleep times to be lost. +// Issue 47762 +func TestAdjustTimers(t *testing.T) { + var rnd = rand.New(rand.NewSource(Now().UnixNano())) + + timers := make([]*Timer, 100) + states := make([]int, len(timers)) + indices := rnd.Perm(len(timers)) + + for len(indices) != 0 { + var ii = rnd.Intn(len(indices)) + var i = indices[ii] + + var timer = timers[i] + var state = states[i] + states[i]++ + + switch state { + case 0: + timers[i] = NewTimer(0) + case 1: + <-timer.C // Timer is now idle. + + // Reset to various long durations, which we'll cancel. + case 2: + if timer.Reset(1 * Minute) { + panic("shouldn't be active (1)") + } + case 4: + if timer.Reset(3 * Minute) { + panic("shouldn't be active (3)") + } + case 6: + if timer.Reset(2 * Minute) { + panic("shouldn't be active (2)") + } + + // Stop and drain a long-duration timer. + case 3, 5, 7: + if !timer.Stop() { + t.Logf("timer %d state %d Stop returned false", i, state) + <-timer.C + } + + // Start a short-duration timer we expect to select without blocking. + case 8: + if timer.Reset(0) { + t.Fatal("timer.Reset returned true") + } + case 9: + now := Now() + <-timer.C + dur := Since(now) + if dur > 750*Millisecond { + t.Errorf("timer %d took %v to complete", i, dur) + } + + // Timer is done. Swap with tail and remove. + case 10: + indices[ii] = indices[len(indices)-1] + indices = indices[:len(indices)-1] + } + } +} + // Benchmark timer latency when the thread that creates the timer is busy with // other work and the timers must be serviced by other threads. // https://golang.org/issue/38860 -- GitLab From 9fc28892cb88dd4c7b0552137b97c1692c23e46b Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 14 Sep 2021 13:09:19 -0700 Subject: [PATCH 1148/2500] cmd/compile/internal/types2: export TypeHash, return value without blanks Change the typeWriter to produce blank-free hashes where easily possible if used as a type hasher, and replace remaining blanks with '#' is needed. Exported Environment.TypeHash for use by the compiler. Change-Id: Icbd364c207f9c139a7a1844bb695512a0c56a4e4 Reviewed-on: https://go-review.googlesource.com/c/go/+/349990 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- .../compile/internal/types2/environment.go | 9 ++-- .../compile/internal/types2/instantiate.go | 2 +- src/cmd/compile/internal/types2/named.go | 2 +- src/cmd/compile/internal/types2/subst.go | 2 +- src/cmd/compile/internal/types2/typestring.go | 46 +++++++++++++------ 5 files changed, 41 insertions(+), 20 deletions(-) diff --git a/src/cmd/compile/internal/types2/environment.go b/src/cmd/compile/internal/types2/environment.go index 816139bbb4..5ef8855a1b 100644 --- a/src/cmd/compile/internal/types2/environment.go +++ b/src/cmd/compile/internal/types2/environment.go @@ -5,6 +5,7 @@ package types2 import ( "bytes" + "strings" "sync" ) @@ -28,11 +29,11 @@ func NewEnvironment() *Environment { } } -// typeHash returns a string representation of typ, which can be used as an exact +// TypeHash returns a string representation of typ, which can be used as an exact // type hash: types that are identical produce identical string representations. // If typ is a *Named type and targs is not empty, typ is printed as if it were -// instantiated with targs. -func (env *Environment) typeHash(typ Type, targs []Type) string { +// instantiated with targs. The result is guaranteed to not contain blanks (" "). +func (env *Environment) TypeHash(typ Type, targs []Type) string { assert(env != nil) assert(typ != nil) var buf bytes.Buffer @@ -56,7 +57,7 @@ func (env *Environment) typeHash(typ Type, targs []Type) string { } } - return buf.String() + return strings.Replace(buf.String(), " ", "#", -1) // ReplaceAll is not available in Go1.4 } // typeForHash returns the recorded type for the type hash h, if it exists. diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 469ceea5c4..fdb87e75f6 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -108,7 +108,7 @@ func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type, env *Envi case *Named: var h string if env != nil { - h = env.typeHash(t, targs) + h = env.TypeHash(t, targs) // typ may already have been instantiated with identical type arguments. In // that case, re-use the existing instance. if named := env.typeForHash(h, nil); named != nil { diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index 99410aedfb..46487d1cae 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -262,7 +262,7 @@ func (n *Named) expand(env *Environment) *Named { // instance in the process of expansion. env = NewEnvironment() } - h := env.typeHash(n.orig, n.targs.list()) + h := env.TypeHash(n.orig, n.targs.list()) // add the instance to the environment to avoid infinite recursion. // addInstance may return a different, existing instance, but we // shouldn't return that instance from expand. diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 4627dd3c5b..8d96494af0 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -211,7 +211,7 @@ func (subst *subster) typ(typ Type) Type { } // before creating a new named type, check if we have this one already - h := subst.env.typeHash(t.orig, newTArgs) + h := subst.env.TypeHash(t.orig, newTArgs) dump(">>> new type hash: %s", h) if named := subst.env.typeForHash(h, nil); named != nil { dump(">>> found %s", named) diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 39ba278d53..71da37c3a1 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -8,7 +8,6 @@ package types2 import ( "bytes" - "fmt" "strconv" "unicode/utf8" ) @@ -83,14 +82,29 @@ func newTypeHasher(buf *bytes.Buffer, env *Environment) *typeWriter { return &typeWriter{buf, make(map[Type]bool), nil, env} } -func (w *typeWriter) byte(b byte) { w.buf.WriteByte(b) } -func (w *typeWriter) string(s string) { w.buf.WriteString(s) } -func (w *typeWriter) writef(format string, args ...interface{}) { fmt.Fprintf(w.buf, format, args...) } +func (w *typeWriter) byte(b byte) { + if w.env != nil { + if b == ' ' { + b = '#' + } + w.buf.WriteByte(b) + return + } + w.buf.WriteByte(b) + if b == ',' || b == ';' { + w.buf.WriteByte(' ') + } +} + +func (w *typeWriter) string(s string) { + w.buf.WriteString(s) +} + func (w *typeWriter) error(msg string) { if w.env != nil { panic(msg) } - w.string("<" + msg + ">") + w.buf.WriteString("<" + msg + ">") } func (w *typeWriter) typ(typ Type) { @@ -117,7 +131,9 @@ func (w *typeWriter) typ(typ Type) { w.string(t.name) case *Array: - w.writef("[%d]", t.len) + w.byte('[') + w.string(strconv.FormatInt(t.len, 10)) + w.byte(']') w.typ(t.elem) case *Slice: @@ -128,7 +144,7 @@ func (w *typeWriter) typ(typ Type) { w.string("struct{") for i, f := range t.fields { if i > 0 { - w.string("; ") + w.byte(';') } // This doesn't do the right thing for embedded type // aliases where we should print the alias name, not @@ -139,7 +155,11 @@ func (w *typeWriter) typ(typ Type) { } w.typ(f.typ) if tag := t.Tag(i); tag != "" { - w.writef(" %q", tag) + w.byte(' ') + // TODO(gri) If tag contains blanks, replacing them with '#' + // in Environment.TypeHash may produce another tag + // accidentally. + w.string(strconv.Quote(tag)) } } w.byte('}') @@ -177,7 +197,7 @@ func (w *typeWriter) typ(typ Type) { first := true for _, m := range t.methods { if !first { - w.string("; ") + w.byte(';') } first = false w.string(m.name) @@ -185,7 +205,7 @@ func (w *typeWriter) typ(typ Type) { } for _, typ := range t.embeddeds { if !first { - w.string("; ") + w.byte(';') } first = false w.typ(typ) @@ -279,7 +299,7 @@ func (w *typeWriter) typeList(list []Type) { w.byte('[') for i, typ := range list { if i > 0 { - w.string(", ") + w.byte(',') } w.typ(typ) } @@ -303,7 +323,7 @@ func (w *typeWriter) tParamList(list []*TypeParam) { w.byte(' ') w.typ(prev) } - w.string(", ") + w.byte(',') } prev = tpar.bound w.typ(tpar) @@ -327,7 +347,7 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) { if tup != nil { for i, v := range tup.vars { if i > 0 { - w.string(", ") + w.byte(',') } // parameter names are ignored for type identity and thus type hashes if w.env == nil && v.name != "" { -- GitLab From b26d325cb1fda20129deaef6e6a666efdc8f0140 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 14 Sep 2021 13:18:40 -0700 Subject: [PATCH 1149/2500] cmd/compile/internal/types2: remove some unnecessary loading/expansion of Named types This is a clean port of CL 349409 from go/types to types2. Change-Id: I2deb9ce46e6dcda736fda2169912c02163930d7d Reviewed-on: https://go-review.googlesource.com/c/go/+/349991 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/predicates.go | 3 --- src/cmd/compile/internal/types2/unify.go | 3 --- 2 files changed, 6 deletions(-) diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 473d22675f..aa797fccc7 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -302,9 +302,6 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { // Two named types are identical if their type names originate // in the same type declaration. if y, ok := y.(*Named); ok { - x.expand(nil) - y.expand(nil) - xargs := x.TypeArgs().list() yargs := y.TypeArgs().list() diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index a1e5b3679b..bb69f0d27b 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -428,9 +428,6 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { case *Named: if y, ok := y.(*Named); ok { - x.expand(nil) - y.expand(nil) - xargs := x.targs.list() yargs := y.targs.list() -- GitLab From 738cebb1747335c182af64614041ceb2b2303f74 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 14 Sep 2021 13:23:37 -0700 Subject: [PATCH 1150/2500] cmd/compile/internal/types2: implement Identical for *Union types This is a clean port of CL 349413 from go/types to types2. Change-Id: I18bad5e29b1e719b30a73fb2aa32fe252538496e Reviewed-on: https://go-review.googlesource.com/c/go/+/349992 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/api_test.go | 42 +++++++++++++++++++ src/cmd/compile/internal/types2/predicates.go | 7 ++++ 2 files changed, 49 insertions(+) diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index 3ec0d78a23..5a20738631 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -1645,6 +1645,48 @@ func TestIdentical_issue15173(t *testing.T) { } } +func TestIdenticalUnions(t *testing.T) { + tname := NewTypeName(nopos, nil, "myInt", nil) + myInt := NewNamed(tname, Typ[Int], nil) + tmap := map[string]*Term{ + "int": NewTerm(false, Typ[Int]), + "~int": NewTerm(true, Typ[Int]), + "string": NewTerm(false, Typ[String]), + "~string": NewTerm(true, Typ[String]), + "myInt": NewTerm(false, myInt), + } + makeUnion := func(s string) *Union { + parts := strings.Split(s, "|") + var terms []*Term + for _, p := range parts { + term := tmap[p] + if term == nil { + t.Fatalf("missing term %q", p) + } + terms = append(terms, term) + } + return NewUnion(terms) + } + for _, test := range []struct { + x, y string + want bool + }{ + // These tests are just sanity checks. The tests for type sets and + // interfaces provide much more test coverage. + {"int|~int", "~int", true}, + {"myInt|~int", "~int", true}, + {"int|string", "string|int", true}, + {"int|int|string", "string|int", true}, + {"myInt|string", "int|string", false}, + } { + x := makeUnion(test.x) + y := makeUnion(test.y) + if got := Identical(x, y); got != test.want { + t.Errorf("Identical(%v, %v) = %t", test.x, test.y, got) + } + } +} + func TestIssue15305(t *testing.T) { const src = "package p; func f() int16; var _ = f(undef)" f, err := parseSrc("issue15305.go", src) diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index aa797fccc7..74ad3da72c 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -225,6 +225,13 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { identical(x.results, y.results, cmpTags, p) } + case *Union: + if y, _ := y.(*Union); y != nil { + xset := computeUnionTypeSet(nil, nopos, x) + yset := computeUnionTypeSet(nil, nopos, y) + return xset.terms.equal(yset.terms) + } + case *Interface: // Two interface types are identical if they describe the same type sets. // With the existing implementation restriction, this simplifies to: -- GitLab From 3100f54f209b9dc3c277e028d70850c975a2de54 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 14 Sep 2021 17:02:30 -0700 Subject: [PATCH 1151/2500] cmd/compile/internal/types2: merge Named type loading and expansion Clean port of CL 349410 from go/types to types2 with 2 adjustments: using syntax.Pos instead of token.Pos, and using TypeHash instead of typeHash. Fixes #47887. Change-Id: Ifd8495e4187b5e30aaf80702768d82aad5e10cf4 Reviewed-on: https://go-review.googlesource.com/c/go/+/349995 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/decl.go | 4 +- .../compile/internal/types2/instantiate.go | 3 +- src/cmd/compile/internal/types2/lookup.go | 2 +- src/cmd/compile/internal/types2/named.go | 114 +++++++----------- src/cmd/compile/internal/types2/object.go | 16 ++- src/cmd/compile/internal/types2/signature.go | 2 +- src/cmd/compile/internal/types2/subst.go | 39 +++--- .../types2/testdata/fixedbugs/issue47887.go2 | 28 +++++ src/cmd/compile/internal/types2/type.go | 2 +- 9 files changed, 114 insertions(+), 96 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue47887.go2 diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 905c21426c..26e050511e 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -317,7 +317,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { } case *Named: - t.expand(check.conf.Environment) + t.resolve(check.conf.Environment) // don't touch the type if it is from a different package or the Universe scope // (doing so would lead to a race condition - was issue #35049) @@ -715,7 +715,7 @@ func (check *Checker) collectMethods(obj *TypeName) { } if base != nil { - base.load() // TODO(mdempsky): Probably unnecessary. + base.resolve(nil) // TODO(mdempsky): Probably unnecessary. base.methods = append(base.methods, m) } } diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index fdb87e75f6..5a6a13a107 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -116,9 +116,10 @@ func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type, env *Envi } } tname := NewTypeName(pos, t.obj.pkg, t.obj.name, nil) - named := check.newNamed(tname, t, nil, nil, nil) // methods and tparams are set when named is loaded + named := check.newNamed(tname, t, nil, nil, nil) // methods and tparams are set when named is resolved named.targs = NewTypeList(targs) named.instPos = &pos + named.resolver = expandNamed if env != nil { // It's possible that we've lost a race to add named to the environment. // In this case, use whichever instance is recorded in the environment. diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index 81bac7b6ff..0e7a2b70e2 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -122,7 +122,7 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o seen[named] = true // look for a matching attached method - named.load() + named.resolve(nil) if i, m := lookupMethod(named.methods, pkg, name); m != nil { // potential match // caution: method may not have a proper signature yet diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index 46487d1cae..7883b7347b 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -22,8 +22,9 @@ type Named struct { targs *TypeList // type arguments (after instantiation), or nil methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily - resolve func(*Named) ([]*TypeParam, Type, []*Func) - once sync.Once + // resolver may be provided to lazily resolve type parameters, underlying, and methods. + resolver func(*Environment, *Named) (tparams *TypeParamList, underlying Type, methods []*Func) + once sync.Once // ensures that tparams, underlying, and methods are resolved before accessing } // NewNamed returns a new named type for the given type name, underlying type, and associated methods. @@ -36,43 +37,22 @@ func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named { return (*Checker)(nil).newNamed(obj, nil, underlying, nil, methods) } -func (t *Named) load() *Named { - // If t is an instantiated type, it derives its methods and tparams from its - // base type. Since we expect type parameters and methods to be set after a - // call to load, we must load the base and copy here. - // - // underlying is set when t is expanded. - // - // By convention, a type instance is loaded iff its tparams are set. - if t.targs.Len() > 0 && t.tparams == nil { - t.orig.load() - t.tparams = t.orig.tparams - t.methods = t.orig.methods - } - if t.resolve == nil { +func (t *Named) resolve(env *Environment) *Named { + if t.resolver == nil { return t } t.once.Do(func() { - // TODO(mdempsky): Since we're passing t to resolve anyway + // TODO(mdempsky): Since we're passing t to the resolver anyway // (necessary because types2 expects the receiver type for methods // on defined interface types to be the Named rather than the // underlying Interface), maybe it should just handle calling // SetTypeParams, SetUnderlying, and AddMethod instead? Those - // methods would need to support reentrant calls though. It would + // methods would need to support reentrant calls though. It would // also make the API more future-proof towards further extensions // (like SetTypeParams). - - tparams, underlying, methods := t.resolve(t) - - switch underlying.(type) { - case nil, *Named: - panic("invalid underlying type") - } - - t.tparams = bindTParams(tparams) - t.underlying = underlying - t.methods = methods + t.tparams, t.underlying, t.methods = t.resolver(env, t) + t.fromRHS = t.underlying // for cycle detection }) return t } @@ -121,19 +101,19 @@ func (t *Named) Orig() *Named { return t.orig } // TypeParams returns the type parameters of the named type t, or nil. // The result is non-nil for an (originally) parameterized type even if it is instantiated. -func (t *Named) TypeParams() *TypeParamList { return t.load().tparams } +func (t *Named) TypeParams() *TypeParamList { return t.resolve(nil).tparams } // SetTypeParams sets the type parameters of the named type t. -func (t *Named) SetTypeParams(tparams []*TypeParam) { t.load().tparams = bindTParams(tparams) } +func (t *Named) SetTypeParams(tparams []*TypeParam) { t.resolve(nil).tparams = bindTParams(tparams) } // TypeArgs returns the type arguments used to instantiate the named type t. func (t *Named) TypeArgs() *TypeList { return t.targs } // NumMethods returns the number of explicit methods whose receiver is named type t. -func (t *Named) NumMethods() int { return len(t.load().methods) } +func (t *Named) NumMethods() int { return len(t.resolve(nil).methods) } // Method returns the i'th method of named type t for 0 <= i < t.NumMethods(). -func (t *Named) Method(i int) *Func { return t.load().methods[i] } +func (t *Named) Method(i int) *Func { return t.resolve(nil).methods[i] } // SetUnderlying sets the underlying type and marks t as complete. func (t *Named) SetUnderlying(underlying Type) { @@ -143,18 +123,18 @@ func (t *Named) SetUnderlying(underlying Type) { if _, ok := underlying.(*Named); ok { panic("underlying type must not be *Named") } - t.load().underlying = underlying + t.resolve(nil).underlying = underlying } // AddMethod adds method m unless it is already in the method list. func (t *Named) AddMethod(m *Func) { - t.load() + t.resolve(nil) if i, _ := lookupMethod(t.methods, m.pkg, m.name); i < 0 { t.methods = append(t.methods, m) } } -func (t *Named) Underlying() Type { return t.load().expand(nil).underlying } +func (t *Named) Underlying() Type { return t.resolve(nil).underlying } func (t *Named) String() string { return TypeString(t, nil) } // ---------------------------------------------------------------------------- @@ -240,43 +220,37 @@ func (n *Named) setUnderlying(typ Type) { } } -// expand ensures that the underlying type of n is instantiated. +// expandNamed ensures that the underlying type of n is instantiated. // The underlying type will be Typ[Invalid] if there was an error. -func (n *Named) expand(env *Environment) *Named { - if n.instPos != nil { - // n must be loaded before instantiation, in order to have accurate - // tparams. This is done implicitly by the call to n.TypeParams, but making - // it explicit is harmless: load is idempotent. - n.load() - var u Type - if n.check.validateTArgLen(*n.instPos, n.tparams.Len(), n.targs.Len()) { - // TODO(rfindley): handling an optional Checker and Environment here (and - // in subst) feels overly complicated. Can we simplify? - if env == nil { - if n.check != nil { - env = n.check.conf.Environment - } else { - // If we're instantiating lazily, we might be outside the scope of a - // type-checking pass. In that case we won't have a pre-existing - // environment, but don't want to create a duplicate of the current - // instance in the process of expansion. - env = NewEnvironment() - } - h := env.TypeHash(n.orig, n.targs.list()) - // add the instance to the environment to avoid infinite recursion. - // addInstance may return a different, existing instance, but we - // shouldn't return that instance from expand. - env.typeForHash(h, n) +func expandNamed(env *Environment, n *Named) (*TypeParamList, Type, []*Func) { + n.orig.resolve(env) + + var u Type + if n.check.validateTArgLen(*n.instPos, n.orig.tparams.Len(), n.targs.Len()) { + // TODO(rfindley): handling an optional Checker and Environment here (and + // in subst) feels overly complicated. Can we simplify? + if env == nil { + if n.check != nil { + env = n.check.conf.Environment + } else { + // If we're instantiating lazily, we might be outside the scope of a + // type-checking pass. In that case we won't have a pre-existing + // environment, but don't want to create a duplicate of the current + // instance in the process of expansion. + env = NewEnvironment() } - u = n.check.subst(*n.instPos, n.orig.underlying, makeSubstMap(n.TypeParams().list(), n.targs.list()), env) - } else { - u = Typ[Invalid] + h := env.TypeHash(n.orig, n.targs.list()) + // add the instance to the environment to avoid infinite recursion. + // addInstance may return a different, existing instance, but we + // shouldn't return that instance from expand. + env.typeForHash(h, n) } - n.underlying = u - n.fromRHS = u - n.instPos = nil + u = n.check.subst(*n.instPos, n.orig.underlying, makeSubstMap(n.orig.tparams.list(), n.targs.list()), env) + } else { + u = Typ[Invalid] } - return n + n.instPos = nil + return n.orig.tparams, u, n.orig.methods } // safeUnderlying returns the underlying of typ without expanding instances, to @@ -285,7 +259,7 @@ func (n *Named) expand(env *Environment) *Named { // TODO(rfindley): eliminate this function or give it a better name. func safeUnderlying(typ Type) Type { if t, _ := typ.(*Named); t != nil { - return t.load().underlying + return t.resolve(nil).underlying } return typ.Underlying() } diff --git a/src/cmd/compile/internal/types2/object.go b/src/cmd/compile/internal/types2/object.go index 9bc2e285ce..540cb3f44f 100644 --- a/src/cmd/compile/internal/types2/object.go +++ b/src/cmd/compile/internal/types2/object.go @@ -278,9 +278,21 @@ func NewTypeName(pos syntax.Pos, pkg *Package, name string, typ Type) *TypeName // NewTypeNameLazy returns a new defined type like NewTypeName, but it // lazily calls resolve to finish constructing the Named object. -func NewTypeNameLazy(pos syntax.Pos, pkg *Package, name string, resolve func(named *Named) (tparams []*TypeParam, underlying Type, methods []*Func)) *TypeName { +func NewTypeNameLazy(pos syntax.Pos, pkg *Package, name string, load func(named *Named) (tparams []*TypeParam, underlying Type, methods []*Func)) *TypeName { obj := NewTypeName(pos, pkg, name, nil) - NewNamed(obj, nil, nil).resolve = resolve + + resolve := func(_ *Environment, t *Named) (*TypeParamList, Type, []*Func) { + tparams, underlying, methods := load(t) + + switch underlying.(type) { + case nil, *Named: + panic(fmt.Sprintf("invalid underlying type %T", t.underlying)) + } + + return bindTParams(tparams), underlying, methods + } + + NewNamed(obj, nil, nil).resolver = resolve return obj } diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index 009ac77012..e3186f5eed 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -210,7 +210,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] var err string switch T := rtyp.(type) { case *Named: - T.expand(nil) + T.resolve(check.conf.Environment) // The receiver type may be an instantiated type referred to // by an alias (which cannot have receiver parameters for now). if T.TypeArgs() != nil && sig.RecvTypeParams() == nil { diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 8d96494af0..87c1d7872b 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -179,13 +179,19 @@ func (subst *subster) typ(typ Type) Type { } } - if t.TypeParams().Len() == 0 { + // subst is called by expandNamed, so in this function we need to be + // careful not to call any methods that would cause t to be expanded: doing + // so would result in deadlock. + // + // So we call t.orig.TypeParams() rather than t.TypeParams() here and + // below. + if t.orig.TypeParams().Len() == 0 { dump(">>> %s is not parameterized", t) return t // type is not parameterized } var newTArgs []Type - assert(t.targs.Len() == t.TypeParams().Len()) + assert(t.targs.Len() == t.orig.TypeParams().Len()) // already instantiated dump(">>> %s already instantiated", t) @@ -198,7 +204,7 @@ func (subst *subster) typ(typ Type) Type { if new_targ != targ { dump(">>> substituted %d targ %s => %s", i, targ, new_targ) if newTArgs == nil { - newTArgs = make([]Type, t.TypeParams().Len()) + newTArgs = make([]Type, t.orig.TypeParams().Len()) copy(newTArgs, t.targs.list()) } newTArgs[i] = new_targ @@ -218,25 +224,22 @@ func (subst *subster) typ(typ Type) Type { return named } - // Create a new named type and populate the environment to avoid endless + t.orig.resolve(subst.env) + // Create a new instance and populate the environment to avoid endless // recursion. The position used here is irrelevant because validation only // occurs on t (we don't call validType on named), but we use subst.pos to // help with debugging. - tname := NewTypeName(subst.pos, t.obj.pkg, t.obj.name, nil) - t.load() - // It's ok to provide a nil *Checker because the newly created type - // doesn't need to be (lazily) expanded; it's expanded below. - named := (*Checker)(nil).newNamed(tname, t.orig, nil, t.tparams, t.methods) // t is loaded, so tparams and methods are available - named.targs = NewTypeList(newTArgs) - subst.env.typeForHash(h, named) - t.expand(subst.env) // must happen after env update to avoid infinite recursion - - // do the substitution - dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, newTArgs) - named.underlying = subst.typOrNil(t.underlying) - dump(">>> underlying: %v", named.underlying) + named := subst.check.instance(subst.pos, t.orig, newTArgs, subst.env).(*Named) + // TODO(rfindley): we probably don't need to resolve here. Investigate if + // this can be removed. + named.resolve(subst.env) assert(named.underlying != nil) - named.fromRHS = named.underlying // for consistency, though no cycle detection is necessary + + // Note that if we were to expose substitution more generally (not just in + // the context of a declaration), we'd have to substitute in + // named.underlying as well. + // + // But this is unnecessary for now. return named diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47887.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47887.go2 new file mode 100644 index 0000000000..4c4fc2fda8 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47887.go2 @@ -0,0 +1,28 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type Fooer[t any] interface { + foo(Barer[t]) +} +type Barer[t any] interface { + bar(Bazer[t]) +} +type Bazer[t any] interface { + Fooer[t] + baz(t) +} + +type Int int + +func (n Int) baz(int) {} +func (n Int) foo(b Barer[int]) { b.bar(n) } + +type F[t any] interface { f(G[t]) } +type G[t any] interface { g(H[t]) } +type H[t any] interface { F[t] } + +type T struct{} +func (n T) f(b G[T]) { b.g(n) } diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index ca5ecdc434..400d6f7128 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -115,7 +115,7 @@ func asInterface(t Type) *Interface { func asNamed(t Type) *Named { e, _ := t.(*Named) if e != nil { - e.expand(nil) + e.resolve(nil) } return e } -- GitLab From 4847c47cb8a93b56e1df8c249700e25f527d4ba3 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 14 Sep 2021 17:13:32 -0700 Subject: [PATCH 1152/2500] cmd/compile/internal/types2: eliminate Named.instPos This is a clean port of CL 349411 from go/types to types2. Change-Id: Id5fa04c53f286dad263d7ba7911cb49eebf47b0e Reviewed-on: https://go-review.googlesource.com/c/go/+/350030 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/environment.go | 7 ------- src/cmd/compile/internal/types2/errors.go | 2 +- src/cmd/compile/internal/types2/errors_test.go | 1 - src/cmd/compile/internal/types2/instantiate.go | 5 +++-- src/cmd/compile/internal/types2/named.go | 8 +++----- src/cmd/compile/internal/types2/sizeof_test.go | 2 +- src/cmd/compile/internal/types2/typestring.go | 10 ---------- 7 files changed, 8 insertions(+), 27 deletions(-) diff --git a/src/cmd/compile/internal/types2/environment.go b/src/cmd/compile/internal/types2/environment.go index 5ef8855a1b..fe9a3099fe 100644 --- a/src/cmd/compile/internal/types2/environment.go +++ b/src/cmd/compile/internal/types2/environment.go @@ -50,13 +50,6 @@ func (env *Environment) TypeHash(typ Type, targs []Type) string { h.typ(typ) } - if debug { - // there should be no instance markers in type hashes - for _, b := range buf.Bytes() { - assert(b != instanceMarker) - } - } - return strings.Replace(buf.String(), " ", "#", -1) // ReplaceAll is not available in Go1.4 } diff --git a/src/cmd/compile/internal/types2/errors.go b/src/cmd/compile/internal/types2/errors.go index a68273271b..ea43fab178 100644 --- a/src/cmd/compile/internal/types2/errors.go +++ b/src/cmd/compile/internal/types2/errors.go @@ -246,7 +246,7 @@ func stripAnnotations(s string) string { var b bytes.Buffer for _, r := range s { // strip #'s and subscript digits - if r != instanceMarker && !('₀' <= r && r < '₀'+10) { // '₀' == U+2080 + if r < '₀' || '₀'+10 <= r { // '₀' == U+2080 b.WriteRune(r) } } diff --git a/src/cmd/compile/internal/types2/errors_test.go b/src/cmd/compile/internal/types2/errors_test.go index e1f0e83fc9..72a2ce3655 100644 --- a/src/cmd/compile/internal/types2/errors_test.go +++ b/src/cmd/compile/internal/types2/errors_test.go @@ -35,7 +35,6 @@ func TestStripAnnotations(t *testing.T) { {"foo", "foo"}, {"foo₀", "foo"}, {"foo(T₀)", "foo(T)"}, - {"#foo(T₀)", "foo(T)"}, } { got := stripAnnotations(test.in) if got != test.want { diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 5a6a13a107..7a9279943c 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -118,8 +118,9 @@ func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type, env *Envi tname := NewTypeName(pos, t.obj.pkg, t.obj.name, nil) named := check.newNamed(tname, t, nil, nil, nil) // methods and tparams are set when named is resolved named.targs = NewTypeList(targs) - named.instPos = &pos - named.resolver = expandNamed + named.resolver = func(env *Environment, n *Named) (*TypeParamList, Type, []*Func) { + return expandNamed(env, n, pos) + } if env != nil { // It's possible that we've lost a race to add named to the environment. // In this case, use whichever instance is recorded in the environment. diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index 7883b7347b..c844012e39 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -17,7 +17,6 @@ type Named struct { orig *Named // original, uninstantiated type fromRHS Type // type (on RHS of declaration) this *Named type is derived from (for cycle reporting) underlying Type // possibly a *Named during setup; never a *Named once set up completely - instPos *syntax.Pos // position information for lazy instantiation, or nil tparams *TypeParamList // type parameters, or nil targs *TypeList // type arguments (after instantiation), or nil methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily @@ -222,11 +221,11 @@ func (n *Named) setUnderlying(typ Type) { // expandNamed ensures that the underlying type of n is instantiated. // The underlying type will be Typ[Invalid] if there was an error. -func expandNamed(env *Environment, n *Named) (*TypeParamList, Type, []*Func) { +func expandNamed(env *Environment, n *Named, instPos syntax.Pos) (*TypeParamList, Type, []*Func) { n.orig.resolve(env) var u Type - if n.check.validateTArgLen(*n.instPos, n.orig.tparams.Len(), n.targs.Len()) { + if n.check.validateTArgLen(instPos, n.orig.tparams.Len(), n.targs.Len()) { // TODO(rfindley): handling an optional Checker and Environment here (and // in subst) feels overly complicated. Can we simplify? if env == nil { @@ -245,11 +244,10 @@ func expandNamed(env *Environment, n *Named) (*TypeParamList, Type, []*Func) { // shouldn't return that instance from expand. env.typeForHash(h, n) } - u = n.check.subst(*n.instPos, n.orig.underlying, makeSubstMap(n.orig.tparams.list(), n.targs.list()), env) + u = n.check.subst(instPos, n.orig.underlying, makeSubstMap(n.orig.tparams.list(), n.targs.list()), env) } else { u = Typ[Invalid] } - n.instPos = nil return n.orig.tparams, u, n.orig.methods } diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go index bbaca8e0aa..a7f1185fa8 100644 --- a/src/cmd/compile/internal/types2/sizeof_test.go +++ b/src/cmd/compile/internal/types2/sizeof_test.go @@ -31,7 +31,7 @@ func TestSizeof(t *testing.T) { {Interface{}, 44, 88}, {Map{}, 16, 32}, {Chan{}, 12, 24}, - {Named{}, 72, 136}, + {Named{}, 68, 128}, {TypeParam{}, 28, 48}, {term{}, 12, 24}, {top{}, 0, 0}, diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 71da37c3a1..bdafcf883d 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -63,9 +63,6 @@ func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) { newTypeWriter(buf, qf).signature(sig) } -// instanceMarker is the prefix for an instantiated type in unexpanded form. -const instanceMarker = '#' - type typeWriter struct { buf *bytes.Buffer seen map[Type]bool @@ -245,13 +242,6 @@ func (w *typeWriter) typ(typ Type) { } case *Named: - // Instance markers indicate unexpanded instantiated - // types. Write them to aid debugging, but don't write - // them when we need an instance hash: whether a type - // is fully expanded or not doesn't matter for identity. - if w.env == nil && t.instPos != nil { - w.byte(instanceMarker) - } w.typePrefix(t) w.typeName(t.obj) if t.targs != nil { -- GitLab From e4dfd788e66f4a44825598dd3cb6ca9626369228 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 14 Sep 2021 20:40:09 -0400 Subject: [PATCH 1153/2500] go/internal/gcimporter,cmd/compile: minor clean-up in iimport.go Make two superficial fixes to iimport.go: rename instType to instanceType (suggested in CL 349949), and fix a stale comment. Done in both go/internal/gcimporter and cmd/compile/internal/importer. Change-Id: Idfdda11a59b036a35824bbb1c101cba3652aeff4 Reviewed-on: https://go-review.googlesource.com/c/go/+/350031 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/importer/iimport.go | 6 +++--- src/go/internal/gcimporter/iimport.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index 7f7143dcfe..a92720d52e 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -72,7 +72,7 @@ const ( structType interfaceType typeParamType - instType + instanceType unionType ) @@ -646,7 +646,7 @@ func (r *importReader) doType(base *types2.Named) types2.Type { r.p.doDecl(pkg, name) return r.p.tparamIndex[id] - case instType: + case instanceType: if r.p.exportVersion < iexportVersionGenerics { errorf("unexpected instantiation type") } @@ -661,7 +661,7 @@ func (r *importReader) doType(base *types2.Named) types2.Type { baseType := r.typ() // The imported instantiated type doesn't include any methods, so // we must always use the methods of the base (orig) type. - // TODO provide a non-nil *Checker + // TODO provide a non-nil *Environment t, _ := types2.Instantiate(nil, baseType, targs, false) return t diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go index d9174d470b..f570aab2bf 100644 --- a/src/go/internal/gcimporter/iimport.go +++ b/src/go/internal/gcimporter/iimport.go @@ -72,7 +72,7 @@ const ( structType interfaceType typeParamType - instType + instanceType unionType ) @@ -638,7 +638,7 @@ func (r *importReader) doType(base *types.Named) types.Type { r.p.doDecl(pkg, name) return r.p.tparamIndex[id] - case instType: + case instanceType: if r.p.exportVersion < iexportVersionGenerics { errorf("unexpected instantiation type") } @@ -653,7 +653,7 @@ func (r *importReader) doType(base *types.Named) types.Type { baseType := r.typ() // The imported instantiated type doesn't include any methods, so // we must always use the methods of the base (orig) type. - // TODO provide a non-nil *Checker + // TODO provide a non-nil *Environment t, _ := types.Instantiate(nil, baseType, targs, false) return t -- GitLab From 5b48fca1fad44d22105f64be725514020432a2c1 Mon Sep 17 00:00:00 2001 From: Alessandro Arzilli Date: Fri, 3 Sep 2021 15:04:52 +0200 Subject: [PATCH 1154/2500] cmd/compile: mark wrapper functions with DW_AT_trampoline Change DWARF generation to tag wrapper functions with the "DW_AT_trampoline attribute". The intent is that debuggers can pick up on this attr so as to skip through the wrapper to the eventual target. DWARF standard allows for a couple of different possible variants of the trampoline attr; this is the simplest variant (all it tells the debugger is that the function is a wrapper, doesn't include a reference to the wrapper routine). This implementation keys off the WRAPPER LSym attribute, which is set for method wrappers, ABI wrappers, and a selected set of runtime assembly routines (ex: "runtime.call32"). Change-Id: Ib53e1bc56c02b86ca3ac5e7da1a541ec262726cf Reviewed-on: https://go-review.googlesource.com/c/go/+/347352 Reviewed-by: Than McIntosh Run-TryBot: Than McIntosh TryBot-Result: Go Bot Trust: Jeremy Faller --- src/cmd/internal/dwarf/dwarf.go | 61 +++++++++++++++++++++++++++------ src/cmd/internal/obj/dwarf.go | 4 +-- 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/cmd/internal/dwarf/dwarf.go b/src/cmd/internal/dwarf/dwarf.go index 4e163db020..69aafaf986 100644 --- a/src/cmd/internal/dwarf/dwarf.go +++ b/src/cmd/internal/dwarf/dwarf.go @@ -325,8 +325,10 @@ const ( DW_ABRV_COMPUNIT DW_ABRV_COMPUNIT_TEXTLESS DW_ABRV_FUNCTION + DW_ABRV_WRAPPER DW_ABRV_FUNCTION_ABSTRACT DW_ABRV_FUNCTION_CONCRETE + DW_ABRV_WRAPPER_CONCRETE DW_ABRV_INLINED_SUBROUTINE DW_ABRV_INLINED_SUBROUTINE_RANGES DW_ABRV_VARIABLE @@ -455,6 +457,19 @@ var abbrevs = [DW_NABRV]dwAbbrev{ }, }, + /* WRAPPER */ + { + DW_TAG_subprogram, + DW_CHILDREN_yes, + []dwAttrForm{ + {DW_AT_name, DW_FORM_string}, + {DW_AT_low_pc, DW_FORM_addr}, + {DW_AT_high_pc, DW_FORM_addr}, + {DW_AT_frame_base, DW_FORM_block1}, + {DW_AT_trampoline, DW_FORM_flag}, + }, + }, + /* FUNCTION_ABSTRACT */ { DW_TAG_subprogram, @@ -478,6 +493,19 @@ var abbrevs = [DW_NABRV]dwAbbrev{ }, }, + /* WRAPPER_CONCRETE */ + { + DW_TAG_subprogram, + DW_CHILDREN_yes, + []dwAttrForm{ + {DW_AT_abstract_origin, DW_FORM_ref_addr}, + {DW_AT_low_pc, DW_FORM_addr}, + {DW_AT_high_pc, DW_FORM_addr}, + {DW_AT_frame_base, DW_FORM_block1}, + {DW_AT_trampoline, DW_FORM_flag}, + }, + }, + /* INLINED_SUBROUTINE */ { DW_TAG_inlined_subroutine, @@ -1329,11 +1357,14 @@ func putInlinedFunc(ctxt Context, s *FnState, callIdx int) error { // for the function (which holds location-independent attributes such // as name, type), then the remainder of the attributes are specific // to this instance (location, frame base, etc). -func PutConcreteFunc(ctxt Context, s *FnState) error { +func PutConcreteFunc(ctxt Context, s *FnState, isWrapper bool) error { if logDwarf { ctxt.Logf("PutConcreteFunc(%v)\n", s.Info) } abbrev := DW_ABRV_FUNCTION_CONCRETE + if isWrapper { + abbrev = DW_ABRV_WRAPPER_CONCRETE + } Uleb128put(ctxt, s.Info, int64(abbrev)) // Abstract origin. @@ -1346,6 +1377,10 @@ func PutConcreteFunc(ctxt Context, s *FnState) error { // cfa / frame base putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa}) + if isWrapper { + putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, int64(1), 0) + } + // Scopes if err := putPrunedScopes(ctxt, s, abbrev); err != nil { return err @@ -1368,11 +1403,14 @@ func PutConcreteFunc(ctxt Context, s *FnState) error { // when its containing package was compiled (hence there is no need to // emit an abstract version for it to use as a base for inlined // routine records). -func PutDefaultFunc(ctxt Context, s *FnState) error { +func PutDefaultFunc(ctxt Context, s *FnState, isWrapper bool) error { if logDwarf { ctxt.Logf("PutDefaultFunc(%v)\n", s.Info) } abbrev := DW_ABRV_FUNCTION + if isWrapper { + abbrev = DW_ABRV_WRAPPER + } Uleb128put(ctxt, s.Info, int64(abbrev)) // Expand '"".' to import path. @@ -1385,13 +1423,16 @@ func PutDefaultFunc(ctxt Context, s *FnState) error { putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, 0, s.StartPC) putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, s.Size, s.StartPC) putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa}) - ctxt.AddFileRef(s.Info, s.Filesym) - - var ev int64 - if s.External { - ev = 1 + if isWrapper { + putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, int64(1), 0) + } else { + ctxt.AddFileRef(s.Info, s.Filesym) + var ev int64 + if s.External { + ev = 1 + } + putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0) } - putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0) // Scopes if err := putPrunedScopes(ctxt, s, abbrev); err != nil { @@ -1489,10 +1530,10 @@ func determineVarAbbrev(v *Var, fnabbrev int) (int, bool, bool) { // Determine whether to use a concrete variable or regular variable DIE. concrete := true switch fnabbrev { - case DW_ABRV_FUNCTION: + case DW_ABRV_FUNCTION, DW_ABRV_WRAPPER: concrete = false break - case DW_ABRV_FUNCTION_CONCRETE: + case DW_ABRV_FUNCTION_CONCRETE, DW_ABRV_WRAPPER_CONCRETE: // If we're emitting a concrete subprogram DIE and the variable // in question is not part of the corresponding abstract function DIE, // then use the default (non-concrete) abbrev for this param. diff --git a/src/cmd/internal/obj/dwarf.go b/src/cmd/internal/obj/dwarf.go index 6dd53ffd12..29e367aa4c 100644 --- a/src/cmd/internal/obj/dwarf.go +++ b/src/cmd/internal/obj/dwarf.go @@ -378,9 +378,9 @@ func (ctxt *Link) populateDWARF(curfn interface{}, s *LSym, myimportpath string) if err != nil { ctxt.Diag("emitting DWARF for %s failed: %v", s.Name, err) } - err = dwarf.PutConcreteFunc(dwctxt, fnstate) + err = dwarf.PutConcreteFunc(dwctxt, fnstate, s.Wrapper()) } else { - err = dwarf.PutDefaultFunc(dwctxt, fnstate) + err = dwarf.PutDefaultFunc(dwctxt, fnstate, s.Wrapper()) } if err != nil { ctxt.Diag("emitting DWARF for %s failed: %v", s.Name, err) -- GitLab From 72bb8185b5fb2fe84ee7cfdc8e9605f2c81b32fe Mon Sep 17 00:00:00 2001 From: Alessandro Arzilli Date: Wed, 25 Aug 2021 10:08:07 +0200 Subject: [PATCH 1155/2500] cmd/compile: emit DWARF info about dictionary entries When emitting the DIE of the instantiation of a generic function also emit one DW_TAG_typedef_type entry for each dictionary entry in use, referencing the shape type and having a custom attribute containing the index inside the dictionary. When emitting the DIE of variables that have an instantiated parametric type, instead of referencing the shape type directly go through the DW_TAG_typedef_type entry emitted for the dictionary entry describing the real type of the variable. Change-Id: Ia45d157ecd4c25e2b60300469e43bbb27a663582 Reviewed-on: https://go-review.googlesource.com/c/go/+/344929 Run-TryBot: Alessandro Arzilli Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Dan Scales Reviewed-by: Than McIntosh Trust: Dan Scales Trust: Jeremy Faller --- src/cmd/compile/internal/dwarfgen/dwarf.go | 3 + src/cmd/compile/internal/ir/name.go | 1 + src/cmd/compile/internal/noder/stencil.go | 18 +++-- src/cmd/internal/dwarf/dwarf.go | 67 ++++++++++++++++- src/cmd/link/internal/ld/dwarf_test.go | 84 ++++++++++++++++++++++ 5 files changed, 168 insertions(+), 5 deletions(-) diff --git a/src/cmd/compile/internal/dwarfgen/dwarf.go b/src/cmd/compile/internal/dwarfgen/dwarf.go index 30472a9ebd..3007262db9 100644 --- a/src/cmd/compile/internal/dwarfgen/dwarf.go +++ b/src/cmd/compile/internal/dwarfgen/dwarf.go @@ -217,6 +217,7 @@ func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []*ir DeclCol: declpos.RelCol(), InlIndex: int32(inlIndex), ChildIndex: -1, + DictIndex: n.DictIndex, }) // Record go type of to insure that it gets emitted by the linker. fnsym.Func().RecordAutoType(reflectdata.TypeLinksym(n.Type())) @@ -374,6 +375,7 @@ func createSimpleVar(fnsym *obj.LSym, n *ir.Name) *dwarf.Var { DeclCol: declpos.RelCol(), InlIndex: int32(inlIndex), ChildIndex: -1, + DictIndex: n.DictIndex, } } @@ -478,6 +480,7 @@ func createComplexVar(fnsym *obj.LSym, fn *ir.Func, varID ssa.VarID) *dwarf.Var DeclCol: declpos.RelCol(), InlIndex: int32(inlIndex), ChildIndex: -1, + DictIndex: n.DictIndex, } list := debug.LocationLists[varID] if len(list) != 0 { diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index 9fb22378cd..dcfff7deba 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -40,6 +40,7 @@ type Name struct { Class Class // uint8 pragma PragmaFlag // int16 flags bitset16 + DictIndex uint16 // index of the dictionary entry describing the type of this variable declaration plus 1 sym *types.Sym Func *Func // TODO(austin): nil for I.M, eqFor, hashfor, and hashmem Offset_ int64 diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 5069db9fe1..6c990c1828 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -779,6 +779,7 @@ func (subst *subster) localvar(name *ir.Name) *ir.Name { m.Func = name.Func subst.ts.Vars[name] = m m.SetTypecheck(1) + m.DictIndex = name.DictIndex if name.Defn != nil { if name.Defn.Op() == ir.ONAME { // This is a closure variable, so its Defn is the outer @@ -1268,14 +1269,18 @@ func (subst *subster) node(n ir.Node) ir.Node { // function info.gfInfo. This will indicate the dictionary entry with the // correct concrete type for the associated instantiated function. func findDictType(info *instInfo, t *types.Type) int { - for i, dt := range info.gfInfo.tparams { + return info.gfInfo.findDictType(t) +} + +func (gfInfo *gfInfo) findDictType(t *types.Type) int { + for i, dt := range gfInfo.tparams { if dt == t { return i } } - for i, dt := range info.gfInfo.derivedTypes { + for i, dt := range gfInfo.derivedTypes { if types.Identical(dt, t) { - return i + len(info.gfInfo.tparams) + return i + len(gfInfo.tparams) } } return -1 @@ -1736,6 +1741,7 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo { for _, n := range gf.Dcl { addType(&info, n, n.Type()) + n.DictIndex = uint16(info.findDictType(n.Type()) + 1) } if infoPrintMode { @@ -1805,9 +1811,13 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo { // Visit the closure body and add all relevant entries to the // dictionary of the outer function (closure will just use // the dictionary of the outer function). - for _, n1 := range n.(*ir.ClosureExpr).Func.Body { + cfunc := n.(*ir.ClosureExpr).Func + for _, n1 := range cfunc.Body { ir.Visit(n1, visitFunc) } + for _, n := range cfunc.Dcl { + n.DictIndex = uint16(info.findDictType(n.Type()) + 1) + } } if n.Op() == ir.OSWITCH && n.(*ir.SwitchStmt).Tag != nil && n.(*ir.SwitchStmt).Tag.Op() == ir.OTYPESW && !n.(*ir.SwitchStmt).Tag.(*ir.TypeSwitchGuard).X.Type().IsEmptyInterface() { for _, cc := range n.(*ir.SwitchStmt).Cases { diff --git a/src/cmd/internal/dwarf/dwarf.go b/src/cmd/internal/dwarf/dwarf.go index 69aafaf986..be37641706 100644 --- a/src/cmd/internal/dwarf/dwarf.go +++ b/src/cmd/internal/dwarf/dwarf.go @@ -50,6 +50,7 @@ type Var struct { Abbrev int // Either DW_ABRV_AUTO[_LOCLIST] or DW_ABRV_PARAM[_LOCLIST] IsReturnValue bool IsInlFormal bool + DictIndex uint16 // index of the dictionary entry describing the type of this variable StackOffset int32 // This package can't use the ssa package, so it can't mention ssa.FuncDebug, // so indirect through a closure. @@ -97,6 +98,8 @@ type FnState struct { Scopes []Scope InlCalls InlCalls UseBASEntries bool + + dictIndexToOffset []int64 } func EnableLogging(doit bool) { @@ -315,6 +318,7 @@ const ( DW_AT_go_runtime_type = 0x2904 DW_AT_go_package_name = 0x2905 // Attribute for DW_TAG_compile_unit + DW_AT_go_dict_index = 0x2906 // Attribute for DW_TAG_typedef_type, index of the dictionary entry describing the real type of this type shape DW_AT_internal_location = 253 // params and locals; not emitted ) @@ -362,6 +366,7 @@ const ( DW_ABRV_STRINGTYPE DW_ABRV_STRUCTTYPE DW_ABRV_TYPEDECL + DW_ABRV_DICT_INDEX DW_NABRV ) @@ -882,6 +887,17 @@ var abbrevs = [DW_NABRV]dwAbbrev{ {DW_AT_type, DW_FORM_ref_addr}, }, }, + + /* DICT_INDEX */ + { + DW_TAG_typedef, + DW_CHILDREN_no, + []dwAttrForm{ + {DW_AT_name, DW_FORM_string}, + {DW_AT_type, DW_FORM_ref_addr}, + {DW_AT_go_dict_index, DW_FORM_udata}, + }, + }, } // GetAbbrev returns the contents of the .debug_abbrev section. @@ -1196,6 +1212,9 @@ func putPrunedScopes(ctxt Context, s *FnState, fnabbrev int) error { sort.Sort(byChildIndex(pruned.Vars)) scopes[k] = pruned } + + s.dictIndexToOffset = putparamtypes(ctxt, s, scopes, fnabbrev) + var encbuf [20]byte if putscope(ctxt, s, scopes, 0, fnabbrev, encbuf[:0]) < int32(len(scopes)) { return errors.New("multiple toplevel scopes") @@ -1451,6 +1470,47 @@ func PutDefaultFunc(ctxt Context, s *FnState, isWrapper bool) error { return nil } +// putparamtypes writes typedef DIEs for any parametric types that are used by this function. +func putparamtypes(ctxt Context, s *FnState, scopes []Scope, fnabbrev int) []int64 { + if fnabbrev == DW_ABRV_FUNCTION_CONCRETE { + return nil + } + + maxDictIndex := uint16(0) + + for i := range scopes { + for _, v := range scopes[i].Vars { + if v.DictIndex > maxDictIndex { + maxDictIndex = v.DictIndex + } + } + } + + if maxDictIndex == 0 { + return nil + } + + dictIndexToOffset := make([]int64, maxDictIndex) + + for i := range scopes { + for _, v := range scopes[i].Vars { + if v.DictIndex == 0 || dictIndexToOffset[v.DictIndex-1] != 0 { + continue + } + + dictIndexToOffset[v.DictIndex-1] = ctxt.CurrentOffset(s.Info) + + Uleb128put(ctxt, s.Info, int64(DW_ABRV_DICT_INDEX)) + n := fmt.Sprintf(".param%d", v.DictIndex-1) + putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n) + putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type) + putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DictIndex-1), nil) + } + } + + return dictIndexToOffset +} + func putscope(ctxt Context, s *FnState, scopes []Scope, curscope int32, fnabbrev int, encbuf []byte) int32 { if logDwarf { @@ -1624,7 +1684,12 @@ func putvar(ctxt Context, s *FnState, v *Var, absfn Sym, fnabbrev, inlIndex int, putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil) } putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil) - putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type) + if v.DictIndex > 0 && s.dictIndexToOffset != nil && s.dictIndexToOffset[v.DictIndex-1] != 0 { + // If the type of this variable is parametric use the entry emitted by putparamtypes + putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, s.dictIndexToOffset[v.DictIndex-1], s.Info) + } else { + putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type) + } } if abbrevUsesLoclist(abbrev) { diff --git a/src/cmd/link/internal/ld/dwarf_test.go b/src/cmd/link/internal/ld/dwarf_test.go index 0aeaa7565c..3d112d97a4 100644 --- a/src/cmd/link/internal/ld/dwarf_test.go +++ b/src/cmd/link/internal/ld/dwarf_test.go @@ -11,6 +11,7 @@ import ( "debug/pe" "errors" "fmt" + "internal/buildcfg" "internal/testenv" "io" "io/ioutil" @@ -1746,3 +1747,86 @@ func main() { expected, found) } } + +func TestDictIndex(t *testing.T) { + // Check that variables with a parametric type have a dictionary index attribute + testenv.MustHaveGoBuild(t) + + if runtime.GOOS == "plan9" { + t.Skip("skipping on plan9; no DWARF symbol table in executables") + } + if buildcfg.Experiment.Unified { + t.Skip("GOEXPERIMENT=unified does not emit dictionaries yet") + } + t.Parallel() + + const prog = ` +package main + +import "fmt" + +func testfn[T any](arg T) { + var mapvar = make(map[int]T) + mapvar[0] = arg + fmt.Println(arg, mapvar) +} + +func main() { + testfn("test") +} +` + + dir := t.TempDir() + f := gobuild(t, dir, prog, NoOpt) + defer f.Close() + + d, err := f.DWARF() + if err != nil { + t.Fatalf("error reading DWARF: %v", err) + } + + rdr := d.Reader() + found := false + for entry, err := rdr.Next(); entry != nil; entry, err = rdr.Next() { + if err != nil { + t.Fatalf("error reading DWARF: %v", err) + } + name, _ := entry.Val(dwarf.AttrName).(string) + if strings.HasPrefix(name, "main.testfn") { + found = true + break + } + } + + if !found { + t.Fatalf("could not find main.testfn") + } + + offs := []dwarf.Offset{} + for entry, err := rdr.Next(); entry != nil; entry, err = rdr.Next() { + if err != nil { + t.Fatalf("error reading DWARF: %v", err) + } + if entry.Tag == 0 { + break + } + name, _ := entry.Val(dwarf.AttrName).(string) + switch name { + case "arg", "mapvar": + offs = append(offs, entry.Val(dwarf.AttrType).(dwarf.Offset)) + } + } + if len(offs) != 2 { + t.Errorf("wrong number of variables found in main.testfn %d", len(offs)) + } + for _, off := range offs { + rdr.Seek(off) + entry, err := rdr.Next() + if err != nil { + t.Fatalf("error reading DWARF: %v", err) + } + if _, ok := entry.Val(intdwarf.DW_AT_go_dict_index).(int64); !ok { + t.Errorf("could not find DW_AT_go_dict_index attribute offset %#x (%T)", off, entry.Val(intdwarf.DW_AT_go_dict_index)) + } + } +} -- GitLab From 6196979365ec6b527b3731c9ec13d7ddfe429f86 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 24 Aug 2021 11:51:07 -0700 Subject: [PATCH 1156/2500] cmd/go/internal/modload: prevent tidy downgrading disambiguating modules If an indirectly required module does not provide any packages needed to build packages in the main module but is needed to disambiguate imports, 'go mod tidy' may keep an indirect requirement on that module to prevent it from being downgraded. This can prevent the introduction of new ambiguities. This also ensures tidy keeps sums needed to load all packages. Fixes #47738 Change-Id: Ib8e33422b95394707894cda7cfbb71a4b111e0ed Reviewed-on: https://go-review.googlesource.com/c/go/+/344572 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/modload/buildlist.go | 68 ++++++++++++++++--- src/cmd/go/internal/modload/import.go | 46 +++++++------ src/cmd/go/internal/modload/load.go | 12 ++-- .../script/mod_tidy_downgrade_ambiguous.txt | 58 ++++++++++++++++ 4 files changed, 150 insertions(+), 34 deletions(-) create mode 100644 src/cmd/go/testdata/script/mod_tidy_downgrade_ambiguous.txt diff --git a/src/cmd/go/internal/modload/buildlist.go b/src/cmd/go/internal/modload/buildlist.go index 777e29af10..da9e6406b1 100644 --- a/src/cmd/go/internal/modload/buildlist.go +++ b/src/cmd/go/internal/modload/buildlist.go @@ -591,7 +591,7 @@ func updateRoots(ctx context.Context, direct map[string]bool, rs *Requirements, // selected at the same version or is upgraded by the dependencies of a // root. // -// If any module that provided a package has been upgraded above its previous, +// If any module that provided a package has been upgraded above its previous // version, the caller may need to reload and recompute the package graph. // // To ensure that the loading process eventually converges, the caller should @@ -980,17 +980,37 @@ func spotCheckRoots(ctx context.Context, rs *Requirements, mods map[module.Versi return true } -// tidyUnprunedRoots returns a minimal set of root requirements that maintains the -// selected version of every module that provided a package in pkgs, and -// includes the selected version of every such module in direct as a root. +// tidyUnprunedRoots returns a minimal set of root requirements that maintains +// the selected version of every module that provided or lexically could have +// provided a package in pkgs, and includes the selected version of every such +// module in direct as a root. func tidyUnprunedRoots(ctx context.Context, mainModule module.Version, direct map[string]bool, pkgs []*loadPkg) (*Requirements, error) { var ( + // keep is a set of of modules that provide packages or are needed to + // disambiguate imports. keep []module.Version keptPath = map[string]bool{} - ) - var ( - rootPaths []string // module paths that should be included as roots + + // rootPaths is a list of module paths that provide packages directly + // imported from the main module. They should be included as roots. + rootPaths []string inRootPaths = map[string]bool{} + + // altMods is a set of paths of modules that lexically could have provided + // imported packages. It may be okay to remove these from the list of + // explicit requirements if that removes them from the module graph. If they + // are present in the module graph reachable from rootPaths, they must not + // be at a lower version. That could cause a missing sum error or a new + // import ambiguity. + // + // For example, suppose a developer rewrites imports from example.com/m to + // example.com/m/v2, then runs 'go mod tidy'. Tidy may delete the + // requirement on example.com/m if there is no other transitive requirement + // on it. However, if example.com/m were downgraded to a version not in + // go.sum, when package example.com/m/v2/p is loaded, we'd get an error + // trying to disambiguate the import, since we can't check example.com/m + // without its sum. See #47738. + altMods = map[string]string{} ) for _, pkg := range pkgs { if !pkg.fromExternalModule() { @@ -1004,12 +1024,44 @@ func tidyUnprunedRoots(ctx context.Context, mainModule module.Version, direct ma inRootPaths[m.Path] = true } } + for _, m := range pkg.altMods { + altMods[m.Path] = m.Version + } } - min, err := mvs.Req(mainModule, rootPaths, &mvsReqs{roots: keep}) + // Construct a build list with a minimal set of roots. + // This may remove or downgrade modules in altMods. + reqs := &mvsReqs{roots: keep} + min, err := mvs.Req(mainModule, rootPaths, reqs) + if err != nil { + return nil, err + } + buildList, err := mvs.BuildList([]module.Version{mainModule}, reqs) if err != nil { return nil, err } + + // Check if modules in altMods were downgraded but not removed. + // If so, add them to roots, which will retain an "// indirect" requirement + // in go.mod. See comment on altMods above. + keptAltMod := false + for _, m := range buildList { + if v, ok := altMods[m.Path]; ok && semver.Compare(m.Version, v) < 0 { + keep = append(keep, module.Version{Path: m.Path, Version: v}) + keptAltMod = true + } + } + if keptAltMod { + // We must run mvs.Req again instead of simply adding altMods to min. + // It's possible that a requirement in altMods makes some other + // explicit indirect requirement unnecessary. + reqs.roots = keep + min, err = mvs.Req(mainModule, rootPaths, reqs) + if err != nil { + return nil, err + } + } + return newRequirements(unpruned, min, direct), nil } diff --git a/src/cmd/go/internal/modload/import.go b/src/cmd/go/internal/modload/import.go index de47974b9b..e64677acd0 100644 --- a/src/cmd/go/internal/modload/import.go +++ b/src/cmd/go/internal/modload/import.go @@ -243,20 +243,24 @@ func (e *invalidImportError) Unwrap() error { // // If the package is not present in any module selected from the requirement // graph, importFromModules returns an *ImportMissingError. -func importFromModules(ctx context.Context, path string, rs *Requirements, mg *ModuleGraph) (m module.Version, dir string, err error) { +// +// If the package is present in exactly one module, importFromModules will +// return the module, its root directory, and a list of other modules that +// lexically could have provided the package but did not. +func importFromModules(ctx context.Context, path string, rs *Requirements, mg *ModuleGraph) (m module.Version, dir string, altMods []module.Version, err error) { if strings.Contains(path, "@") { - return module.Version{}, "", fmt.Errorf("import path should not have @version") + return module.Version{}, "", nil, fmt.Errorf("import path should not have @version") } if build.IsLocalImport(path) { - return module.Version{}, "", fmt.Errorf("relative import not supported") + return module.Version{}, "", nil, fmt.Errorf("relative import not supported") } if path == "C" { // There's no directory for import "C". - return module.Version{}, "", nil + return module.Version{}, "", nil, nil } // Before any further lookup, check that the path is valid. if err := module.CheckImportPath(path); err != nil { - return module.Version{}, "", &invalidImportError{importPath: path, err: err} + return module.Version{}, "", nil, &invalidImportError{importPath: path, err: err} } // Is the package in the standard library? @@ -265,14 +269,14 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M for _, mainModule := range MainModules.Versions() { if MainModules.InGorootSrc(mainModule) { if dir, ok, err := dirInModule(path, MainModules.PathPrefix(mainModule), MainModules.ModRoot(mainModule), true); err != nil { - return module.Version{}, dir, err + return module.Version{}, dir, nil, err } else if ok { - return mainModule, dir, nil + return mainModule, dir, nil, nil } } } dir := filepath.Join(cfg.GOROOT, "src", path) - return module.Version{}, dir, nil + return module.Version{}, dir, nil, nil } // -mod=vendor is special. @@ -283,19 +287,19 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M mainDir, mainOK, mainErr := dirInModule(path, MainModules.PathPrefix(mainModule), modRoot, true) vendorDir, vendorOK, _ := dirInModule(path, "", filepath.Join(modRoot, "vendor"), false) if mainOK && vendorOK { - return module.Version{}, "", &AmbiguousImportError{importPath: path, Dirs: []string{mainDir, vendorDir}} + return module.Version{}, "", nil, &AmbiguousImportError{importPath: path, Dirs: []string{mainDir, vendorDir}} } // Prefer to return main directory if there is one, // Note that we're not checking that the package exists. // We'll leave that for load. if !vendorOK && mainDir != "" { - return mainModule, mainDir, nil + return mainModule, mainDir, nil, nil } if mainErr != nil { - return module.Version{}, "", mainErr + return module.Version{}, "", nil, mainErr } readVendorList(mainModule) - return vendorPkgModule[path], vendorDir, nil + return vendorPkgModule[path], vendorDir, nil, nil } // Check each module on the build list. @@ -316,7 +320,7 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M // already non-nil, then we attempt to load the package using the full // requirements in mg. for { - var sumErrMods []module.Version + var sumErrMods, altMods []module.Version for prefix := path; prefix != "."; prefix = pathpkg.Dir(prefix) { var ( v string @@ -350,13 +354,15 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M // continue the loop and find the package in some other module, // we need to look at this module to make sure the import is // not ambiguous. - return module.Version{}, "", err + return module.Version{}, "", nil, err } if dir, ok, err := dirInModule(path, m.Path, root, isLocal); err != nil { - return module.Version{}, "", err + return module.Version{}, "", nil, err } else if ok { mods = append(mods, m) dirs = append(dirs, dir) + } else { + altMods = append(altMods, m) } } @@ -369,7 +375,7 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M mods[i], mods[j] = mods[j], mods[i] dirs[i], dirs[j] = dirs[j], dirs[i] } - return module.Version{}, "", &AmbiguousImportError{importPath: path, Dirs: dirs, Modules: mods} + return module.Version{}, "", nil, &AmbiguousImportError{importPath: path, Dirs: dirs, Modules: mods} } if len(sumErrMods) > 0 { @@ -377,7 +383,7 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M j := len(sumErrMods) - 1 - i sumErrMods[i], sumErrMods[j] = sumErrMods[j], sumErrMods[i] } - return module.Version{}, "", &ImportMissingSumError{ + return module.Version{}, "", nil, &ImportMissingSumError{ importPath: path, mods: sumErrMods, found: len(mods) > 0, @@ -385,7 +391,7 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M } if len(mods) == 1 { - return mods[0], dirs[0], nil + return mods[0], dirs[0], altMods, nil } if mg != nil { @@ -395,7 +401,7 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M if !HasModRoot() { queryErr = ErrNoModRoot } - return module.Version{}, "", &ImportMissingError{Path: path, QueryErr: queryErr, isStd: pathIsStd} + return module.Version{}, "", nil, &ImportMissingError{Path: path, QueryErr: queryErr, isStd: pathIsStd} } // So far we've checked the root dependencies. @@ -406,7 +412,7 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M // the module graph, so we can't return an ImportMissingError here — one // of the missing modules might actually contain the package in question, // in which case we shouldn't go looking for it in some new dependency. - return module.Version{}, "", err + return module.Version{}, "", nil, err } } } diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index 40e6b50ed4..48f268ce5f 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -862,6 +862,7 @@ type loadPkg struct { imports []*loadPkg // packages imported by this one testImports []string // test-only imports, saved for use by pkg.test. inStd bool + altMods []module.Version // modules that could have contained the package but did not // Populated by (*loader).pkgTest: testOnce sync.Once @@ -1184,8 +1185,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader { } // updateRequirements ensures that ld.requirements is consistent with the -// information gained from ld.pkgs and includes the modules in add as roots at -// at least the given versions. +// information gained from ld.pkgs. // // In particular: // @@ -1343,7 +1343,7 @@ func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err err // // In some sense, we can think of this as ‘upgraded the module providing // pkg.path from "none" to a version higher than "none"’. - if _, _, err = importFromModules(ctx, pkg.path, rs, nil); err == nil { + if _, _, _, err = importFromModules(ctx, pkg.path, rs, nil); err == nil { changed = true break } @@ -1554,7 +1554,7 @@ func (ld *loader) preloadRootModules(ctx context.Context, rootPkgs []string) (ch // If the main module is tidy and the package is in "all" — or if we're // lucky — we can identify all of its imports without actually loading the // full module graph. - m, _, err := importFromModules(ctx, path, ld.requirements, nil) + m, _, _, err := importFromModules(ctx, path, ld.requirements, nil) if err != nil { var missing *ImportMissingError if errors.As(err, &missing) && ld.ResolveMissingImports { @@ -1659,7 +1659,7 @@ func (ld *loader) load(ctx context.Context, pkg *loadPkg) { } } - pkg.mod, pkg.dir, pkg.err = importFromModules(ctx, pkg.path, ld.requirements, mg) + pkg.mod, pkg.dir, pkg.altMods, pkg.err = importFromModules(ctx, pkg.path, ld.requirements, mg) if pkg.dir == "" { return } @@ -1918,7 +1918,7 @@ func (ld *loader) checkTidyCompatibility(ctx context.Context, rs *Requirements) pkg := pkg ld.work.Add(func() { - mod, _, err := importFromModules(ctx, pkg.path, rs, mg) + mod, _, _, err := importFromModules(ctx, pkg.path, rs, mg) if mod != pkg.mod { mismatches := <-mismatchMu mismatches[pkg] = mismatch{mod: mod, err: err} diff --git a/src/cmd/go/testdata/script/mod_tidy_downgrade_ambiguous.txt b/src/cmd/go/testdata/script/mod_tidy_downgrade_ambiguous.txt new file mode 100644 index 0000000000..8b508c7ea8 --- /dev/null +++ b/src/cmd/go/testdata/script/mod_tidy_downgrade_ambiguous.txt @@ -0,0 +1,58 @@ +# Verifies golang.org/issue/47738. + +# In this test, the user has rewritten their imports to use rsc.io/quote/v3, +# but their go.mod still requires rsc.io/quote@v1.5.2, and they indirectly +# require rsc.io/quote@v1.5.1 but don't import anything from it. +go list -m -f '{{.Path}}@{{.Version}}{{if .Indirect}} indirect{{end}}' all +stdout '^rsc.io/quote@v1.5.2$' +! stdout 'rsc.io/quote/v3' +go list -e all +! stdout '^rsc.io/quote$' + +# 'go mod tidy' should preserve the requirement on rsc.io/quote but mark it +# indirect. This prevents a downgrade to v1.5.1, which could introduce +# an ambiguity. +go mod tidy +go list -m -f '{{.Path}}@{{.Version}}{{if .Indirect}} indirect{{end}}' all +stdout '^rsc.io/quote@v1.5.2 indirect$' +stdout '^rsc.io/quote/v3@v3.0.0$' + +-- go.mod -- +module use + +go 1.16 + +require ( + old-indirect v0.0.0 + rsc.io/quote v1.5.2 +) + +replace old-indirect v0.0.0 => ./old-indirect +-- go.sum -- +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +rsc.io/quote v1.5.1/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0= +rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +-- use.go -- +package use + +import ( + _ "old-indirect/empty" + + _ "rsc.io/quote/v3" +) +-- old-indirect/empty/empty.go -- +package empty +-- old-indirect/go.mod -- +module old-indirect + +go 1.16 + +require rsc.io/quote v1.5.1 +-- old-indirect/go.sum -- +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -- GitLab From 739a42c1993a3a6b607a8349fbed3188da3e56e9 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Tue, 14 Sep 2021 15:21:54 -0400 Subject: [PATCH 1157/2500] [dev.fuzz] testing: adjust -fuzz multiple match stdout Fixes golang/go#48131 Change-Id: I40ff130c849dffe38363ddc0282e93ceb74ae140 Reviewed-on: https://go-review.googlesource.com/c/go/+/349969 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/testdata/script/test_fuzz_match.txt | 5 ++--- src/testing/fuzz.go | 18 ++++++++++++------ src/testing/testing.go | 9 +-------- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_match.txt b/src/cmd/go/testdata/script/test_fuzz_match.txt index 9d4c5125d3..47e143952a 100644 --- a/src/cmd/go/testdata/script/test_fuzz_match.txt +++ b/src/cmd/go/testdata/script/test_fuzz_match.txt @@ -30,11 +30,10 @@ stdout '^ok.*no tests to run' ! stdout 'no targets to fuzz' # Matches more than one fuzz target for fuzzing. -go test -fuzz Fuzz -fuzztime 1x multiple_fuzz_test.go -# The tests should run, but not be fuzzed +! go test -fuzz Fuzz -fuzztime 1x multiple_fuzz_test.go ! stdout 'no tests to run' ! stdout 'no targets to fuzz' -stdout ok +stdout FAIL stdout 'will not fuzz, -fuzz matches more than one target' -- standalone_fuzz_test.go -- diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 65c3437ed4..c2d9db843d 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -593,12 +593,12 @@ func runFuzzTargets(deps testDeps, fuzzTargets []InternalFuzzTarget, deadline ti // // If fuzzing is disabled (-test.fuzz is not set), runFuzzing // returns immediately. -func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran bool, matched int, ok bool) { +func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ok bool) { // TODO(katiehockman,jayconrod): Should we do something special to make sure // we don't print f.Log statements again with runFuzzing, since we already // would have printed them when we ran runFuzzTargets (ie. seed corpus run)? if len(fuzzTargets) == 0 || *matchFuzz == "" { - return false, 0, true + return true } m := newMatcher(deps.MatchString, *matchFuzz, "-test.fuzz") tctx := newTestContext(1, m) @@ -617,17 +617,23 @@ func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran bool, matc } var target *InternalFuzzTarget var targetName string + var matched []string for i := range fuzzTargets { name, ok, _ := tctx.match.fullName(nil, fuzzTargets[i].Name) if !ok { continue } - matched++ + matched = append(matched, name) target = &fuzzTargets[i] targetName = name } - if matched != 1 { - return false, matched, true + if len(matched) == 0 { + fmt.Fprintln(os.Stderr, "testing: warning: no targets to fuzz") + return true + } + if len(matched) > 1 { + fmt.Fprintf(os.Stderr, "testing: will not fuzz, -fuzz matches more than one target: %v\n", matched) + return false } f := &F{ @@ -649,7 +655,7 @@ func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ran bool, matc } go fRunner(f, target.Fn) <-f.signal - return f.ran, matched, !f.failed + return !f.failed } // fRunner wraps a call to a fuzz target and ensures that cleanup functions are diff --git a/src/testing/testing.go b/src/testing/testing.go index 5e66a0610b..f4d2b26650 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1634,14 +1634,7 @@ func (m *M) Run() (code int) { } } - fuzzingRan, fuzzingMatched, fuzzingOk := runFuzzing(m.deps, m.fuzzTargets) - if *matchFuzz != "" && !fuzzingRan { - if fuzzingMatched == 0 { - fmt.Fprintln(os.Stderr, "testing: warning: no targets to fuzz") - } else { - fmt.Fprintln(os.Stderr, "testing: warning: will not fuzz, -fuzz matches more than one target") - } - } + fuzzingOk := runFuzzing(m.deps, m.fuzzTargets) if !*isFuzzWorker && !fuzzingOk { fmt.Println("FAIL") if *isFuzzWorker { -- GitLab From f53b61d38793dfa8987378cbb6754365569c261b Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Tue, 14 Sep 2021 15:47:41 -0400 Subject: [PATCH 1158/2500] [dev.fuzz] internal: fuzzing output adjustments Print the elapsed time as a nicely formatted duration, and make small adjustments to the command line output while fuzzing. Fixes golang/go#48132 Change-Id: Id95f84c0939171a777448c444d9b87d7af26b654 Reviewed-on: https://go-review.googlesource.com/c/go/+/349970 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- .../go/testdata/script/test_fuzz_minimize.txt | 6 ++--- src/internal/fuzz/fuzz.go | 24 +++++++++++-------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize.txt b/src/cmd/go/testdata/script/test_fuzz_minimize.txt index c180890a9b..f0adb9ec3e 100644 --- a/src/cmd/go/testdata/script/test_fuzz_minimize.txt +++ b/src/cmd/go/testdata/script/test_fuzz_minimize.txt @@ -23,14 +23,14 @@ stdout FAIL # Test that fuzzminimizetime can be zero seconds, and minimization is disabled ! go test -fuzz=FuzzMinimizeZeroDurationSet -run=FuzzMinimizeZeroDurationSet -fuzztime=10000x -fuzzminimizetime=0s minimizer_test.go ! stdout '^ok' -! stdout 'found a crash, minimizing...' +! stdout 'minimizing' stdout 'there was an Error' stdout FAIL # Test that fuzzminimizetime can be zero times, and minimization is disabled ! go test -fuzz=FuzzMinimizeZeroLimitSet -run=FuzzMinimizeZeroLimitSet -fuzztime=10000x -fuzzminimizetime=0x minimizer_test.go ! stdout '^ok' -! stdout 'found a crash, minimizing...' +! stdout 'minimizing' stdout 'there was an Error' stdout FAIL @@ -51,7 +51,7 @@ rm testdata # Test that minimization is working for non-recoverable errors. ! go test -fuzz=FuzzMinimizerNonrecoverable -run=FuzzMinimizerNonrecoverable -fuzztime=10000x minimizer_test.go ! stdout '^ok' -stdout 'found a crash, minimizing' +stdout 'minimizing' stdout 'fuzzing process terminated unexpectedly: exit status 99' stdout FAIL diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index c19ea35f23..816da3286f 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -239,7 +239,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err // Send it back to a worker for minimization. Disable inputC so // other workers don't continue fuzzing. crashMinimizing = &result - fmt.Fprintf(c.opts.Log, "found a crash, minimizing...\n") + fmt.Fprintf(c.opts.Log, "fuzz: found a %d-byte crash input; minimizing...\n", len(result.entry.Data)) c.queueForMinimization(result, nil) } else if !crashWritten { // Found a crasher that's either minimized or not minimizable. @@ -256,7 +256,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err fmt.Fprintf( c.opts.Log, "DEBUG new crasher, elapsed: %s, id: %s, parent: %s, gen: %d, size: %d, exec time: %s\n", - time.Since(c.startTime), + c.elapsed(), fileName, result.entry.Parent, result.entry.Generation, @@ -272,7 +272,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err fmt.Fprintf( c.opts.Log, "DEBUG processed an initial input, elapsed: %s, id: %s, new bits: %d, size: %d, exec time: %s\n", - time.Since(c.startTime), + c.elapsed(), result.entry.Parent, countBits(diffCoverage(c.coverageMask, result.coverageData)), len(result.entry.Data), @@ -291,7 +291,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err fmt.Fprintf( c.opts.Log, "DEBUG finished processing input corpus, elapsed: %s, entries: %d, initial coverage bits: %d\n", - time.Since(c.startTime), + c.elapsed(), len(c.corpus.entries), countBits(c.coverageMask), ) @@ -329,7 +329,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err fmt.Fprintf( c.opts.Log, "DEBUG new interesting input, elapsed: %s, id: %s, parent: %s, gen: %d, new bits: %d, total bits: %d, size: %d, exec time: %s\n", - time.Since(c.startTime), + c.elapsed(), result.entry.Name, result.entry.Parent, result.entry.Generation, @@ -345,7 +345,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err fmt.Fprintf( c.opts.Log, "DEBUG worker reported interesting input that doesn't expand coverage, elapsed: %s, id: %s, parent: %s, minimized: %t\n", - time.Since(c.startTime), + c.elapsed(), result.entry.Name, result.entry.Parent, result.minimizeAttempted, @@ -644,12 +644,12 @@ func (c *coordinator) updateStats(result fuzzResult) { } func (c *coordinator) logStats() { - elapsed := time.Since(c.startTime) + elapsed := c.elapsed() if c.coverageOnlyRun() { - fmt.Fprintf(c.opts.Log, "gathering baseline coverage, elapsed: %.1fs, workers: %d, left: %d\n", elapsed.Seconds(), c.opts.Parallel, c.covOnlyInputs) + fmt.Fprintf(c.opts.Log, "gathering baseline coverage, elapsed: %s, workers: %d, left: %d\n", elapsed, c.opts.Parallel, c.covOnlyInputs) } else { - rate := float64(c.count) / elapsed.Seconds() - fmt.Fprintf(c.opts.Log, "fuzzing, elapsed: %.1fs, execs: %d (%.0f/sec), workers: %d, interesting: %d\n", elapsed.Seconds(), c.count, rate, c.opts.Parallel, c.interestingCount) + rate := float64(c.count) / time.Since(c.startTime).Seconds() // be more precise here + fmt.Fprintf(c.opts.Log, "fuzz: elapsed: %s, execs: %d (%.0f/sec), workers: %d, interesting: %d\n", elapsed, c.count, rate, c.opts.Parallel, c.interestingCount) } } @@ -820,6 +820,10 @@ func (c *coordinator) canMinimize() bool { (c.opts.Limit == 0 || c.count+c.countWaiting < c.opts.Limit) } +func (c *coordinator) elapsed() time.Duration { + return time.Since(c.startTime).Round(1 * time.Second) +} + // readCache creates a combined corpus from seed values and values in the cache // (in GOCACHE/fuzz). // -- GitLab From 4304cf62e9ba6a85e37d5fec33cfa580ce7ac6d1 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 14 Sep 2021 15:09:06 -0700 Subject: [PATCH 1159/2500] [dev.fuzz] testing: fix internal error exit condition for fuzz workers A fuzz worker process should exit with fuzzWorkerExitCode (70) if it encounters an internal error. This should generally only happen due to an I/O error on the worker side. I can't think of a way to write a realistic test case for this. test_fuzz_io_error.txt triggers an I/O error on the coordinator side, which is similar. Change-Id: I40d2e9aaf422e5ed925debcf7a152c252c3a6984 Reviewed-on: https://go-review.googlesource.com/c/go/+/349993 Trust: Jay Conrod Trust: Katie Hockman Reviewed-by: Katie Hockman --- src/testing/testing.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/testing/testing.go b/src/testing/testing.go index f4d2b26650..18a0657561 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1635,7 +1635,7 @@ func (m *M) Run() (code int) { } fuzzingOk := runFuzzing(m.deps, m.fuzzTargets) - if !*isFuzzWorker && !fuzzingOk { + if !fuzzingOk { fmt.Println("FAIL") if *isFuzzWorker { m.exitCode = fuzzWorkerExitCode -- GitLab From 03df68d3c33e83a23cf5f22389a37f2d09721bef Mon Sep 17 00:00:00 2001 From: nimelehin Date: Wed, 15 Sep 2021 18:37:08 +0000 Subject: [PATCH 1160/2500] runtime: fix setting of cpu features for amd64 Because of wrong case of letters, the cpu features flags were not set properly for amd64. Fixes #48406. Change-Id: If19782851670e91fd31d119f4701c47373fa7e71 GitHub-Last-Rev: 91c7321ca49343c86917f071babec8a004ca5c77 GitHub-Pull-Request: golang/go#48403 Reviewed-on: https://go-review.googlesource.com/c/go/+/350151 Trust: Keith Randall Reviewed-by: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot --- src/runtime/proc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 197441dfa7..605e133000 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -623,7 +623,7 @@ func cpuinit() { // Support cpu feature variables are used in code generated by the compiler // to guard execution of instructions that can not be assumed to be always supported. switch GOARCH { - case "386", "AMD64": + case "386", "amd64": x86HasPOPCNT = cpu.X86.HasPOPCNT x86HasSSE41 = cpu.X86.HasSSE41 x86HasFMA = cpu.X86.HasFMA -- GitLab From 0edc6c4fa088a74bef98d55cc93ffa387d4f7b2d Mon Sep 17 00:00:00 2001 From: Lynn Boger Date: Mon, 16 Aug 2021 09:37:07 -0500 Subject: [PATCH 1161/2500] cmd/internal/obj/ppc64: generate prologue code compatible with new ABI This changes the ppc64 prologue to avoid clobbering the registers that could contain incoming argument values. This means preserving the values in R3 - R10 and R14 - R19 for ppc64. Instead of modifying R3, R4, R5 and R6 the registers R22, R23, R24 and R25 are used. The argument registers that could be clobbered by the call to morestack are saved and restored around that call. Change-Id: If354c3dc73f2c8537ef4e513e5a4c05d7bd22866 Reviewed-on: https://go-review.googlesource.com/c/go/+/343872 Trust: Lynn Boger Run-TryBot: Lynn Boger TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/internal/obj/ppc64/obj9.go | 63 +++++++++++++++++------------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/src/cmd/internal/obj/ppc64/obj9.go b/src/cmd/internal/obj/ppc64/obj9.go index c2722b0afb..ee93fe048b 100644 --- a/src/cmd/internal/obj/ppc64/obj9.go +++ b/src/cmd/internal/obj/ppc64/obj9.go @@ -294,9 +294,9 @@ func (c *ctxt9) rewriteToUseGot(p *obj.Prog) { // BL (LR) var sym *obj.LSym if p.As == obj.ADUFFZERO { - sym = c.ctxt.Lookup("runtime.duffzero") + sym = c.ctxt.LookupABI("runtime.duffzero", obj.ABIInternal) } else { - sym = c.ctxt.Lookup("runtime.duffcopy") + sym = c.ctxt.LookupABI("runtime.duffcopy", obj.ABIInternal) } offset := p.To.Offset p.As = AMOVD @@ -687,7 +687,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { q.From.Reg = REG_LR q.To.Type = obj.TYPE_REG q.To.Reg = REGTMP - prologueEnd = q q = obj.Appendp(q, c.newprog) @@ -787,14 +786,14 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { q.From.Reg = REGG q.From.Offset = 4 * int64(c.ctxt.Arch.PtrSize) // G.panic q.To.Type = obj.TYPE_REG - q.To.Reg = REG_R3 + q.To.Reg = REG_R22 q = obj.Appendp(q, c.newprog) q.As = ACMP q.From.Type = obj.TYPE_REG q.From.Reg = REG_R0 q.To.Type = obj.TYPE_REG - q.To.Reg = REG_R3 + q.To.Reg = REG_R22 q = obj.Appendp(q, c.newprog) q.As = ABEQ @@ -804,10 +803,10 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { q = obj.Appendp(q, c.newprog) q.As = AMOVD q.From.Type = obj.TYPE_MEM - q.From.Reg = REG_R3 + q.From.Reg = REG_R22 q.From.Offset = 0 // Panic.argp q.To.Type = obj.TYPE_REG - q.To.Reg = REG_R4 + q.To.Reg = REG_R23 q = obj.Appendp(q, c.newprog) q.As = AADD @@ -815,14 +814,14 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { q.From.Offset = int64(autosize) + c.ctxt.FixedFrameSize() q.Reg = REGSP q.To.Type = obj.TYPE_REG - q.To.Reg = REG_R5 + q.To.Reg = REG_R24 q = obj.Appendp(q, c.newprog) q.As = ACMP q.From.Type = obj.TYPE_REG - q.From.Reg = REG_R4 + q.From.Reg = REG_R23 q.To.Type = obj.TYPE_REG - q.To.Reg = REG_R5 + q.To.Reg = REG_R24 q = obj.Appendp(q, c.newprog) q.As = ABNE @@ -835,14 +834,14 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { q.From.Offset = c.ctxt.FixedFrameSize() q.Reg = REGSP q.To.Type = obj.TYPE_REG - q.To.Reg = REG_R6 + q.To.Reg = REG_R25 q = obj.Appendp(q, c.newprog) q.As = AMOVD q.From.Type = obj.TYPE_REG - q.From.Reg = REG_R6 + q.From.Reg = REG_R25 q.To.Type = obj.TYPE_MEM - q.To.Reg = REG_R3 + q.To.Reg = REG_R22 q.To.Offset = 0 // Panic.argp q = obj.Appendp(q, c.newprog) @@ -1051,7 +1050,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { func (c *ctxt9) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { p0 := p // save entry point, but skipping the two instructions setting R2 in shared mode - // MOVD g_stackguard(g), R3 + // MOVD g_stackguard(g), R22 p = obj.Appendp(p, c.newprog) p.As = AMOVD @@ -1062,7 +1061,7 @@ func (c *ctxt9) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { p.From.Offset = 3 * int64(c.ctxt.Arch.PtrSize) // G.stackguard1 } p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R3 + p.To.Reg = REG_R22 // Mark the stack bound check and morestack call async nonpreemptible. // If we get preempted here, when resumed the preemption request is @@ -1078,7 +1077,7 @@ func (c *ctxt9) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { p.As = ACMPU p.From.Type = obj.TYPE_REG - p.From.Reg = REG_R3 + p.From.Reg = REG_R22 p.To.Type = obj.TYPE_REG p.To.Reg = REGSP } else { @@ -1108,14 +1107,14 @@ func (c *ctxt9) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { p.From.Type = obj.TYPE_CONST p.From.Offset = offset p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R4 + p.To.Reg = REG_R23 p = obj.Appendp(p, c.newprog) p.As = ACMPU p.From.Type = obj.TYPE_REG p.From.Reg = REGSP p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R4 + p.To.Reg = REG_R23 } p = obj.Appendp(p, c.newprog) @@ -1134,14 +1133,14 @@ func (c *ctxt9) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { p.From.Offset = -offset p.Reg = REGSP p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R4 + p.To.Reg = REG_R23 p = obj.Appendp(p, c.newprog) p.As = ACMPU p.From.Type = obj.TYPE_REG - p.From.Reg = REG_R3 + p.From.Reg = REG_R22 p.To.Type = obj.TYPE_REG - p.To.Reg = REG_R4 + p.To.Reg = REG_R23 } // q1: BLT done @@ -1151,17 +1150,25 @@ func (c *ctxt9) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { p.As = ABLT p.To.Type = obj.TYPE_BRANCH - // MOVD LR, R5 p = obj.Appendp(p, c.newprog) + p.As = obj.ANOP // zero-width place holder + + if q != nil { + q.To.SetTarget(p) + } + + // Spill the register args that could be clobbered by the + // morestack code. + spill := c.cursym.Func().SpillRegisterArgs(p, c.newprog) + + // MOVD LR, R5 + p = obj.Appendp(spill, c.newprog) p.As = AMOVD p.From.Type = obj.TYPE_REG p.From.Reg = REG_LR p.To.Type = obj.TYPE_REG p.To.Reg = REG_R5 - if q != nil { - q.To.SetTarget(p) - } p = c.ctxt.EmitEntryStackMap(c.cursym, p, c.newprog) @@ -1181,8 +1188,7 @@ func (c *ctxt9) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { // Fortunately, in shared mode, 8(SP) and 16(SP) are reserved in // the caller's frame, but not used (0(SP) is caller's saved LR, // 24(SP) is caller's saved R2). Use 8(SP) to save this function's R2. - - // MOVD R12, 8(SP) + // MOVD R2, 8(SP) p = obj.Appendp(p, c.newprog) p.As = AMOVD p.From.Type = obj.TYPE_REG @@ -1249,7 +1255,8 @@ func (c *ctxt9) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { p.To.Reg = REG_R2 } - p = c.ctxt.EndUnsafePoint(p, c.newprog, -1) + unspill := c.cursym.Func().UnspillRegisterArgs(p, c.newprog) + p = c.ctxt.EndUnsafePoint(unspill, c.newprog, -1) // BR start p = obj.Appendp(p, c.newprog) -- GitLab From 59a9a035ffa34c26a287d124180f6eca7c912311 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 13 Sep 2021 13:53:18 -0700 Subject: [PATCH 1162/2500] cmd/compile: switch to computing dict format on instantiated functions Change to computing the dictionary form on each shape-instantiated function, rather than once on the underlying generic function/method. The problem with computing the dictionary format on the generic function is that we had to force early transformations to create all the needed/implicit CONVIFACE nodes, since many of these nodes cause the need for a dictionary entry. Also, the dictionary entries needed can different with different instantiations of the same generic function, especially depending on whether a type argument is a non-interface or interface type, or a instantiated type vs. a non-instantiated type. By computing the dictionary format on the instantiated function, we are scanning a function where all the transformations have been done to create implicit CONVFIFACE nodes, and we know the above relevant information about the type params (which are shapes). Much of the change is more mechanical changes from typeparams to shapes, and generic functions/info to instantiated functions/info. Some of the most important non-mechanical changes are: - Separated out the dictionary transformations to nodes into a separate dictPass, since we need to analyze instantiated functions after stenciling, but before the dictionary transformations. - Added type param index to shape types, since we need to be able distinguish type params of an instantiation which are different but happen to have the same shape. - Allow the type substituter to work with shapes again (since for the dictionary entries we need to substitute shape params to the concrete type args). - Support types.IdentityStrict() that does strict type comparison (no special case for shapes). This needed for type substitution, formatting and creating dictionaries, etc. We can maybe create better names for this function. - Add new information to instInfo to contain a mapping from the shape type params to their instantiated type bound. This is needed when doing the dictionary transformations related to type bounds. Change-Id: I1c3ca312c5384f318c4dd7d0858dba9766396ff6 Reviewed-on: https://go-review.googlesource.com/c/go/+/349613 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/irgen.go | 57 +- src/cmd/compile/internal/noder/stencil.go | 534 ++++++++++-------- .../compile/internal/reflectdata/reflect.go | 2 +- src/cmd/compile/internal/typecheck/subr.go | 59 +- src/cmd/compile/internal/types/identity.go | 31 +- 5 files changed, 375 insertions(+), 308 deletions(-) diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index 414875615f..4f1b4e6bfd 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -97,39 +97,42 @@ func check2(noders []*noder) { } } -// gfInfo is information gathered on a generic function. -type gfInfo struct { - tparams []*types.Type +// dictInfo is the dictionary format for an instantiation of a generic function with +// particular shapes. shapeParams, derivedTypes, subDictCalls, and itabConvs describe +// the actual dictionary entries in order, and the remaining fields are other info +// needed in doing dictionary processing during compilation. +type dictInfo struct { + // Types substituted for the type parameters, which are shape types. + shapeParams []*types.Type + // All types derived from those typeparams used in the instantiation. derivedTypes []*types.Type - // Nodes in generic function that requires a subdictionary. Includes + // Nodes in the instantiation that requires a subdictionary. Includes // method and function calls (OCALL), function values (OFUNCINST), method // values/expressions (OXDOT). subDictCalls []ir.Node - // Nodes in generic functions that are a conversion from a typeparam/derived + // Nodes in the instantiation that are a conversion from a typeparam/derived // type to a specific interface. itabConvs []ir.Node + + // Mapping from each shape type that substitutes a type param, to its + // type bound (which is also substitued with shapes if it is parameterized) + shapeToBound map[*types.Type]*types.Type + // For type switches on nonempty interfaces, a map from OTYPE entries of - // HasTParam type, to the interface type we're switching from. - // TODO: what if the type we're switching from is a shape type? + // HasShape type, to the interface type we're switching from. type2switchType map[ir.Node]*types.Type + + startSubDict int // Start of dict entries for subdictionaries + startItabConv int // Start of dict entries for itab conversions + dictLen int // Total number of entries in dictionary } -// instInfo is information gathered on an gcshape (or fully concrete) -// instantiation of a function. +// instInfo is information gathered on an shape instantiation of a function. type instInfo struct { fun *ir.Func // The instantiated function (with body) dictParam *ir.Name // The node inside fun that refers to the dictionary param - gf *ir.Name // The associated generic function - gfInfo *gfInfo - - startSubDict int // Start of dict entries for subdictionaries - startItabConv int // Start of dict entries for itab conversions - dictLen int // Total number of entries in dictionary - - // Map from nodes in instantiated fun (OCALL, OCALLMETHOD, OFUNCINST, and - // OMETHEXPR) to the associated dictionary entry for a sub-dictionary - dictEntryMap map[ir.Node]int + dictInfo *dictInfo } type irgen struct { @@ -155,13 +158,8 @@ type irgen struct { dnum int // for generating unique dictionary variables - // Map from generic function to information about its type params, derived - // types, and subdictionaries. - gfInfoMap map[*types.Sym]*gfInfo - // Map from a name of function that been instantiated to information about - // its instantiated function, associated generic function/method, and the - // mapping from IR nodes to dictionary entries. + // its instantiated function (including dictionary format). instInfoMap map[*types.Sym]*instInfo // dictionary syms which we need to finish, by writing out any itabconv @@ -179,10 +177,11 @@ func (g *irgen) later(fn func()) { } type delayInfo struct { - gf *ir.Name - targs []*types.Type - sym *types.Sym - off int + gf *ir.Name + targs []*types.Type + sym *types.Sym + off int + isMeth bool } type typeDelayInfo struct { diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 6c990c1828..e60383f4e0 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -44,7 +44,6 @@ func infoPrint(format string, a ...interface{}) { // process. func (g *irgen) stencil() { g.instInfoMap = make(map[*types.Sym]*instInfo) - g.gfInfoMap = make(map[*types.Sym]*gfInfo) // Instantiate the methods of instantiated generic types that we have seen so far. g.instantiateMethods() @@ -106,7 +105,7 @@ func (g *irgen) stencil() { inst := call.X.(*ir.InstExpr) nameNode, isMeth := g.getInstNameNode(inst) targs := typecheck.TypesOf(inst.Targs) - st := g.getInstantiation(nameNode, targs, isMeth) + st := g.getInstantiation(nameNode, targs, isMeth).fun dictValue, usingSubdict := g.getDictOrSubdict(declInfo, n, nameNode, targs, isMeth) if infoPrintMode { dictkind := "Main dictionary" @@ -165,7 +164,7 @@ func (g *irgen) stencil() { // to OCALLFUNC and does typecheckaste/assignconvfn. transformCall(call) - st := g.getInstantiation(gf, targs, true) + st := g.getInstantiation(gf, targs, true).fun dictValue, usingSubdict := g.getDictOrSubdict(declInfo, n, gf, targs, true) // We have to be using a subdictionary, since this is // a generic method call. @@ -232,6 +231,31 @@ func (g *irgen) stencil() { } g.finalizeSyms() + + // All the instantiations and dictionaries have been created. Now go through + // each instantiation and transform the various operations that need to make + // use of their dictionary. + l := len(g.instInfoMap) + for _, info := range g.instInfoMap { + g.dictPass(info) + if doubleCheck { + ir.Visit(info.fun, func(n ir.Node) { + if n.Op() != ir.OCONVIFACE { + return + } + c := n.(*ir.ConvExpr) + if c.X.Type().HasShape() && !c.X.Type().IsInterface() { + ir.Dump("BAD FUNCTION", info.fun) + ir.Dump("BAD CONVERSION", c) + base.Fatalf("converting shape type to interface") + } + }) + } + if base.Flag.W > 1 { + ir.Dump(fmt.Sprintf("\ndictpass %v", info.fun), info.fun) + } + } + assert(l == len(g.instInfoMap)) } // buildClosure makes a closure to implement x, a OFUNCINST or OMETHEXPR @@ -274,7 +298,7 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { // For method values, the target expects a dictionary and the receiver // as its first two arguments. // dictValue is the value to use for the dictionary argument. - target = g.getInstantiation(gf, targs, rcvrValue != nil) + target = g.getInstantiation(gf, targs, rcvrValue != nil).fun dictValue, usingSubdict = g.getDictOrSubdict(outerInfo, x, gf, targs, rcvrValue != nil) if infoPrintMode { dictkind := "Main dictionary" @@ -321,7 +345,7 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { // Remember if value method, so we can detect (*T).M case. valueMethod = true } - target = g.getInstantiation(gf, targs, true) + target = g.getInstantiation(gf, targs, true).fun dictValue, usingSubdict = g.getDictOrSubdict(outerInfo, x, gf, targs, true) if infoPrintMode { dictkind := "Main dictionary" @@ -544,13 +568,18 @@ func (g *irgen) getDictOrSubdict(declInfo *instInfo, n ir.Node, nameNode *ir.Nam var dict ir.Node usingSubdict := false if declInfo != nil { - // Get the dictionary arg via sub-dictionary reference - entry, ok := declInfo.dictEntryMap[n] + entry := -1 + for i, de := range declInfo.dictInfo.subDictCalls { + if n == de { + entry = declInfo.dictInfo.startSubDict + i + break + } + } // If the entry is not found, it may be that this node did not have // any type args that depend on type params, so we need a main // dictionary, not a sub-dictionary. - if ok { - dict = getDictionaryEntry(n.Pos(), declInfo.dictParam, entry, declInfo.dictLen) + if entry >= 0 { + dict = getDictionaryEntry(n.Pos(), declInfo.dictParam, entry, declInfo.dictInfo.dictLen) usingSubdict = true } } @@ -577,7 +606,7 @@ func checkFetchBody(nameNode *ir.Name) { // getInstantiation gets the instantiantion and dictionary of the function or method nameNode // with the type arguments shapes. If the instantiated function is not already // cached, then it calls genericSubst to create the new instantiation. -func (g *irgen) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMeth bool) *ir.Func { +func (g *irgen) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMeth bool) *instInfo { checkFetchBody(nameNode) // Convert any non-shape type arguments to their shape, so we can reduce the @@ -586,12 +615,12 @@ func (g *irgen) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMeth // specified concrete type args. var s1 []*types.Type for i, t := range shapes { - if !t.HasShape() { + if !t.IsShape() { if s1 == nil { s1 = make([]*types.Type, len(shapes)) copy(s1[0:i], shapes[0:i]) } - s1[i] = typecheck.Shapify(t) + s1[i] = typecheck.Shapify(t, i) } else if s1 != nil { s1[i] = shapes[i] } @@ -605,28 +634,28 @@ func (g *irgen) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMeth if info == nil { // If instantiation doesn't exist yet, create it and add // to the list of decls. - gfInfo := g.getGfInfo(nameNode) info = &instInfo{ - gf: nameNode, - gfInfo: gfInfo, - startSubDict: len(shapes) + len(gfInfo.derivedTypes), - startItabConv: len(shapes) + len(gfInfo.derivedTypes) + len(gfInfo.subDictCalls), - dictLen: len(shapes) + len(gfInfo.derivedTypes) + len(gfInfo.subDictCalls) + len(gfInfo.itabConvs), - dictEntryMap: make(map[ir.Node]int), - } - // genericSubst fills in info.dictParam and info.dictEntryMap. + dictInfo: &dictInfo{}, + } + info.dictInfo.shapeToBound = make(map[*types.Type]*types.Type) + + // genericSubst fills in info.dictParam and info.tparamToBound. st := g.genericSubst(sym, nameNode, shapes, isMeth, info) info.fun = st g.instInfoMap[sym] = info + + // getInstInfo fills in info.dictInfo. + g.getInstInfo(st, shapes, info) + if base.Flag.W > 1 { + ir.Dump(fmt.Sprintf("\nstenciled %v", st), st) + } + // This ensures that the linker drops duplicates of this instantiation. // All just works! st.SetDupok(true) g.target.Decls = append(g.target.Decls, st) - if base.Flag.W > 1 { - ir.Dump(fmt.Sprintf("\nstenciled %v", st), st) - } } - return info.fun + return info } // Struct containing info needed for doing the substitution as we create the @@ -647,7 +676,7 @@ type subster struct { // args shapes. For a method with a generic receiver, it returns an instantiated // function type where the receiver becomes the first parameter. For either a generic // method or function, a dictionary parameter is the added as the very first -// parameter. genericSubst fills in info.dictParam and info.dictEntryMap. +// parameter. genericSubst fills in info.dictParam and info.tparamToBound. func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes []*types.Type, isMethod bool, info *instInfo) *ir.Func { var tparams []*types.Type if isMethod { @@ -744,23 +773,13 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes []*typ base.Fatalf("defnMap is not empty") } - ir.CurFunc = savef - - if doubleCheck { - ir.Visit(newf, func(n ir.Node) { - if n.Op() != ir.OCONVIFACE { - return - } - c := n.(*ir.ConvExpr) - if c.X.Type().HasShape() && !c.X.Type().IsInterface() { - ir.Dump("BAD FUNCTION", newf) - ir.Dump("BAD CONVERSION", c) - base.Fatalf("converting shape type to interface") - } - }) + for i, tp := range tparams { + info.dictInfo.shapeToBound[shapes[i]] = subst.ts.Typ(tp.Bound()) } - return newf + ir.CurFunc = savef + + return subst.newf } // localvar creates a new name node for the specified local variable and enters it @@ -870,11 +889,11 @@ func getDictionaryEntry(pos src.XPos, dict *ir.Name, i int, size int) ir.Node { // refers to a type param or a derived type that uses type params). It uses the // specified dictionary dictParam, rather than the one in info.dictParam. func getDictionaryType(info *instInfo, dictParam *ir.Name, pos src.XPos, i int) ir.Node { - if i < 0 || i >= info.startSubDict { + if i < 0 || i >= info.dictInfo.startSubDict { base.Fatalf(fmt.Sprintf("bad dict index %d", i)) } - r := getDictionaryEntry(pos, info.dictParam, i, info.startSubDict) + r := getDictionaryEntry(pos, info.dictParam, i, info.dictInfo.startSubDict) // change type of retrieved dictionary entry to *byte, which is the // standard typing of a *runtime._type in the compiler typed(types.Types[types.TUINT8].PtrTo(), r) @@ -936,17 +955,6 @@ func (subst *subster) node(n ir.Node) ir.Node { } } - for i, de := range subst.info.gfInfo.subDictCalls { - if de == x { - // Remember the dictionary entry associated with this - // node in the instantiated function - // TODO: make sure this remains correct with respect to the - // transformations below. - subst.info.dictEntryMap[m] = subst.info.startSubDict + i - break - } - } - ir.EditChildren(m, edit) m.SetTypecheck(1) @@ -1019,36 +1027,9 @@ func (subst *subster) node(n ir.Node) ir.Node { // we find in the OCALL case below that the method value // is actually called. mse := m.(*ir.SelectorExpr) - if src := mse.X.Type(); src.IsShape() { - // The only dot on a shape type value are methods. - if mse.X.Op() == ir.OTYPE { - // Method expression T.M - m = subst.g.buildClosure2(subst, m, x) - // No need for transformDot - buildClosure2 has already - // transformed to OCALLINTER/ODOTINTER. - } else { - // Implement x.M as a conversion-to-bound-interface - // 1) convert x to the bound interface - // 2) call M on that interface - gsrc := x.(*ir.SelectorExpr).X.Type() - bound := gsrc.Bound() - dst := bound - if dst.HasTParam() { - dst = subst.ts.Typ(dst) - } - if src.IsInterface() { - // If type arg is an interface (unusual case), - // we do a type assert to the type bound. - mse.X = assertToBound(subst.info, subst.info.dictParam, m.Pos(), mse.X, bound, dst) - } else { - mse.X = convertUsingDictionary(subst.info, subst.info.dictParam, m.Pos(), mse.X, x, dst, gsrc) - } - transformDot(mse, false) - } - } else { + if src := mse.X.Type(); !src.IsShape() { transformDot(mse, false) } - m.SetTypecheck(1) case ir.OCALL: call := m.(*ir.CallExpr) @@ -1103,7 +1084,7 @@ func (subst *subster) node(n ir.Node) ir.Node { // or channel receive to compute function value. transformCall(call) - case ir.OCALL, ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER, ir.ODYNAMICDOTTYPE: + case ir.OCALL, ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER: transformCall(call) case ir.OFUNCINST: @@ -1111,6 +1092,7 @@ func (subst *subster) node(n ir.Node) ir.Node { // in stencil() once we have created & attached the // instantiation to be called. + case ir.OXDOT, ir.ODOTTYPE, ir.ODOTTYPE2: default: base.FatalfAt(call.Pos(), fmt.Sprintf("Unexpected op with CALL during stenciling: %v", call.X.Op())) } @@ -1142,7 +1124,7 @@ func (subst *subster) node(n ir.Node) ir.Node { // Copy that closure variable to a local one. // Note: this allows the dictionary to be captured by child closures. // See issue 47723. - ldict := ir.NewNameAt(x.Pos(), subst.info.gf.Sym().Pkg.Lookup(".dict")) + ldict := ir.NewNameAt(x.Pos(), newfn.Sym().Pkg.Lookup(".dict")) typed(types.Types[types.TUINTPTR], ldict) ldict.Class = ir.PAUTO ldict.Curfn = newfn @@ -1154,16 +1136,11 @@ func (subst *subster) node(n ir.Node) ir.Node { // Create inst info for the instantiated closure. The dict // param is the closure variable for the dictionary of the // outer function. Since the dictionary is shared, use the - // same entries for startSubDict, dictLen, dictEntryMap. + // same dictInfo. cinfo := &instInfo{ - fun: newfn, - dictParam: ldict, - gf: subst.info.gf, - gfInfo: subst.info.gfInfo, - startSubDict: subst.info.startSubDict, - startItabConv: subst.info.startItabConv, - dictLen: subst.info.dictLen, - dictEntryMap: subst.info.dictEntryMap, + fun: newfn, + dictParam: ldict, + dictInfo: subst.info.dictInfo, } subst.g.instInfoMap[newfn.Nname.Sym()] = cinfo @@ -1182,117 +1159,176 @@ func (subst *subster) node(n ir.Node) ir.Node { m = ir.UseClosure(newfn.OClosure, subst.g.target) m.(*ir.ClosureExpr).SetInit(subst.list(x.Init())) + } + return m + } + + return edit(n) +} + +// dictPass takes a function instantiation and does the transformations on the +// operations that need to make use of the dictionary param. +func (g *irgen) dictPass(info *instInfo) { + savef := ir.CurFunc + ir.CurFunc = info.fun + + var edit func(ir.Node) ir.Node + edit = func(m ir.Node) ir.Node { + ir.EditChildren(m, edit) + + switch m.Op() { + case ir.OCLOSURE: + newf := m.(*ir.ClosureExpr).Func + ir.CurFunc = newf + outerinfo := info + info = g.instInfoMap[newf.Nname.Sym()] + + body := newf.Body + for i, n := range body { + body[i] = edit(n) + } + + info = outerinfo + ir.CurFunc = info.fun + + case ir.OXDOT: + mse := m.(*ir.SelectorExpr) + src := mse.X.Type() + assert(src.IsShape()) + + // The only dot on a shape type value are methods. + if mse.X.Op() == ir.OTYPE { + // Method expression T.M + m = g.buildClosure2(info, m) + // No need for transformDot - buildClosure2 has already + // transformed to OCALLINTER/ODOTINTER. + } else { + // Implement x.M as a conversion-to-bound-interface + // 1) convert x to the bound interface + // 2) call M on that interface + dst := info.dictInfo.shapeToBound[m.(*ir.SelectorExpr).X.Type()] + if src.IsInterface() { + // If type arg is an interface (unusual case), + // we do a type assert to the type bound. + mse.X = assertToBound(info, info.dictParam, m.Pos(), mse.X, dst) + } else { + mse.X = convertUsingDictionary(info, info.dictParam, m.Pos(), mse.X, m, dst) + } + transformDot(mse, false) + } + case ir.OCALL: + op := m.(*ir.CallExpr).X.Op() + if op != ir.OFUNCINST { + assert(op == ir.OMETHVALUE || op == ir.OCLOSURE || op == ir.ODYNAMICDOTTYPE || op == ir.ODYNAMICDOTTYPE2) + transformCall(m.(*ir.CallExpr)) + } + case ir.OCONVIFACE: - x := x.(*ir.ConvExpr) if m.Type().IsEmptyInterface() && m.(*ir.ConvExpr).X.Type().IsEmptyInterface() { // Was T->interface{}, after stenciling it is now interface{}->interface{}. // No longer need the conversion. See issue 48276. m.(*ir.ConvExpr).SetOp(ir.OCONVNOP) break } + mce := m.(*ir.ConvExpr) // Note: x's argument is still typed as a type parameter. // m's argument now has an instantiated type. - if x.X.Type().HasTParam() || (x.X.Type().IsInterface() && x.Type().HasTParam()) { - m = convertUsingDictionary(subst.info, subst.info.dictParam, m.Pos(), m.(*ir.ConvExpr).X, x, m.Type(), x.X.Type()) + if mce.X.Type().HasShape() || (mce.X.Type().IsInterface() && m.Type().HasShape()) { + m = convertUsingDictionary(info, info.dictParam, m.Pos(), m.(*ir.ConvExpr).X, m, m.Type()) } case ir.ODOTTYPE, ir.ODOTTYPE2: - if !x.Type().HasTParam() { + if !m.Type().HasShape() { break } dt := m.(*ir.TypeAssertExpr) var rt ir.Node if dt.Type().IsInterface() || dt.X.Type().IsEmptyInterface() { - ix := findDictType(subst.info, x.Type()) + ix := findDictType(info, m.Type()) assert(ix >= 0) - rt = getDictionaryType(subst.info, subst.info.dictParam, dt.Pos(), ix) + rt = getDictionaryType(info, info.dictParam, dt.Pos(), ix) } else { // nonempty interface to noninterface. Need an itab. ix := -1 - for i, ic := range subst.info.gfInfo.itabConvs { - if ic == x { - ix = subst.info.startItabConv + i + for i, ic := range info.dictInfo.itabConvs { + if ic == m { + ix = info.dictInfo.startItabConv + i break } } assert(ix >= 0) - rt = getDictionaryEntry(dt.Pos(), subst.info.dictParam, ix, subst.info.dictLen) + rt = getDictionaryEntry(dt.Pos(), info.dictParam, ix, info.dictInfo.dictLen) } op := ir.ODYNAMICDOTTYPE - if x.Op() == ir.ODOTTYPE2 { + if m.Op() == ir.ODOTTYPE2 { op = ir.ODYNAMICDOTTYPE2 } m = ir.NewDynamicTypeAssertExpr(dt.Pos(), op, dt.X, rt) m.SetType(dt.Type()) m.SetTypecheck(1) case ir.OCASE: - if _, ok := x.(*ir.CommClause); ok { + if _, ok := m.(*ir.CommClause); ok { // This is not a type switch. TODO: Should we use an OSWITCH case here instead of OCASE? break } - x := x.(*ir.CaseClause) m := m.(*ir.CaseClause) - for i, c := range x.List { - if c.Op() == ir.OTYPE && c.Type().HasTParam() { + for i, c := range m.List { + if c.Op() == ir.OTYPE && c.Type().HasShape() { // Use a *runtime._type for the dynamic type. - ix := findDictType(subst.info, c.Type()) + ix := findDictType(info, m.List[i].Type()) assert(ix >= 0) - dt := ir.NewDynamicType(c.Pos(), getDictionaryEntry(c.Pos(), subst.info.dictParam, ix, subst.info.dictLen)) + dt := ir.NewDynamicType(c.Pos(), getDictionaryEntry(c.Pos(), info.dictParam, ix, info.dictInfo.dictLen)) // For type switch from nonempty interfaces to non-interfaces, we need an itab as well. if !m.List[i].Type().IsInterface() { - if _, ok := subst.info.gfInfo.type2switchType[c]; ok { + if _, ok := info.dictInfo.type2switchType[m.List[i]]; ok { // Type switch from nonempty interface. We need a *runtime.itab // for the dynamic type. ix := -1 - for i, ic := range subst.info.gfInfo.itabConvs { - if ic == c { - ix = subst.info.startItabConv + i + for i, ic := range info.dictInfo.itabConvs { + if ic == m.List[i] { + ix = info.dictInfo.startItabConv + i break } } assert(ix >= 0) - dt.ITab = getDictionaryEntry(c.Pos(), subst.info.dictParam, ix, subst.info.dictLen) + dt.ITab = getDictionaryEntry(c.Pos(), info.dictParam, ix, info.dictInfo.dictLen) } } typed(m.List[i].Type(), dt) m.List[i] = dt } } + } return m } - - return edit(n) + edit(info.fun) + ir.CurFunc = savef } // findDictType looks for type t in the typeparams or derived types in the generic // function info.gfInfo. This will indicate the dictionary entry with the // correct concrete type for the associated instantiated function. func findDictType(info *instInfo, t *types.Type) int { - return info.gfInfo.findDictType(t) -} - -func (gfInfo *gfInfo) findDictType(t *types.Type) int { - for i, dt := range gfInfo.tparams { + for i, dt := range info.dictInfo.shapeParams { if dt == t { return i } } - for i, dt := range gfInfo.derivedTypes { - if types.Identical(dt, t) { - return i + len(gfInfo.tparams) + for i, dt := range info.dictInfo.derivedTypes { + if types.IdenticalStrict(dt, t) { + return i + len(info.dictInfo.shapeParams) } } return -1 } -// convertUsingDictionary converts value v from instantiated type src to an interface -// type dst, by returning a new set of nodes that make use of a dictionary entry. src -// is the generic (not shape) type, and gn is the original generic node of the -// CONVIFACE node or XDOT node (for a bound method call) that is causing the +// convertUsingDictionary converts instantiated value v (type v.Type()) to an interface +// type dst, by returning a new set of nodes that make use of a dictionary entry. in is the +// instantiated node of the CONVIFACE node or XDOT node (for a bound method call) that is causing the // conversion. -func convertUsingDictionary(info *instInfo, dictParam *ir.Name, pos src.XPos, v ir.Node, gn ir.Node, dst, src *types.Type) ir.Node { - assert(src.HasTParam() || src.IsInterface() && gn.Type().HasTParam()) +func convertUsingDictionary(info *instInfo, dictParam *ir.Name, pos src.XPos, v ir.Node, in ir.Node, dst *types.Type) ir.Node { + assert(v.Type().HasShape() || v.Type().IsInterface() && in.Type().HasShape()) assert(dst.IsInterface()) if v.Type().IsInterface() { @@ -1305,8 +1341,7 @@ func convertUsingDictionary(info *instInfo, dictParam *ir.Name, pos src.XPos, v v.SetTypecheck(1) return v } - gdst := gn.Type() // pre-stenciled destination type - if !gdst.HasTParam() { + if !in.Type().HasShape() { // Regular OCONVIFACE works if the destination isn't parameterized. v = ir.NewConvExpr(pos, ir.OCONVIFACE, dst, v) v.SetTypecheck(1) @@ -1328,7 +1363,7 @@ func convertUsingDictionary(info *instInfo, dictParam *ir.Name, pos src.XPos, v types.CalcSize(fn.Type()) call := ir.NewCallExpr(pos, ir.OCALLFUNC, fn, nil) typed(types.Types[types.TUINT8].PtrTo(), call) - ix := findDictType(info, gdst) + ix := findDictType(info, in.Type()) assert(ix >= 0) inter := getDictionaryType(info, dictParam, pos, ix) call.Args = []ir.Node{inter, itab} @@ -1344,16 +1379,16 @@ func convertUsingDictionary(info *instInfo, dictParam *ir.Name, pos src.XPos, v // will be more efficient than converting to an empty interface first // and then type asserting to dst. ix := -1 - for i, ic := range info.gfInfo.itabConvs { - if ic == gn { - ix = info.startItabConv + i + for i, ic := range info.dictInfo.itabConvs { + if ic == in { + ix = info.dictInfo.startItabConv + i break } } assert(ix >= 0) - rt = getDictionaryEntry(pos, dictParam, ix, info.dictLen) + rt = getDictionaryEntry(pos, dictParam, ix, info.dictInfo.dictLen) } else { - ix := findDictType(info, src) + ix := findDictType(info, v.Type()) assert(ix >= 0) // Load the actual runtime._type of the type parameter from the dictionary. rt = getDictionaryType(info, dictParam, pos, ix) @@ -1469,8 +1504,6 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) return sym } - info := g.getGfInfo(gf) - infoPrint("=== Creating dictionary %v\n", sym.Name) off := 0 // Emit an entry for each targ (concrete type or gcshape). @@ -1480,8 +1513,12 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) off = objw.SymPtr(lsym, off, s, 0) markTypeUsed(t, lsym) } + + instInfo := g.getInstantiation(gf, targs, isMeth) + info := instInfo.dictInfo + subst := typecheck.Tsubster{ - Tparams: info.tparams, + Tparams: info.shapeParams, Targs: targs, } // Emit an entry for each derived type (after substituting targs) @@ -1496,18 +1533,33 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) for _, n := range info.subDictCalls { var sym *types.Sym switch n.Op() { - case ir.OCALL: + case ir.OCALL, ir.OCALLFUNC, ir.OCALLMETH: call := n.(*ir.CallExpr) - if call.X.Op() == ir.OXDOT { + if call.X.Op() == ir.OXDOT || call.X.Op() == ir.ODOTMETH { var nameNode *ir.Name se := call.X.(*ir.SelectorExpr) - if types.IsInterfaceMethod(se.Selection.Type) { + if se.X.Type().IsShape() { // This is a method call enabled by a type bound. + + // We need this extra check for type expressions, which + // don't add in the implicit XDOTs. tmpse := ir.NewSelectorExpr(base.Pos, ir.OXDOT, se.X, se.Sel) tmpse = typecheck.AddImplicitDots(tmpse) tparam := tmpse.X.Type() - assert(tparam.IsTypeParam()) - recvType := targs[tparam.Index()] + if !tparam.IsShape() { + // The method expression is not + // really on a typeparam. + break + } + ix := -1 + for i, shape := range info.shapeParams { + if shape == tparam { + ix = i + break + } + } + assert(ix >= 0) + recvType := targs[ix] if recvType.IsInterface() || len(recvType.RParams()) == 0 { // No sub-dictionary entry is // actually needed, since the @@ -1526,8 +1578,10 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) } else { // This is the case of a normal // method call on a generic type. - nameNode = call.X.(*ir.SelectorExpr).Selection.Nname.(*ir.Name) - subtargs := deref(call.X.(*ir.SelectorExpr).X.Type()).RParams() + recvType := deref(call.X.(*ir.SelectorExpr).X.Type()) + genRecvType := recvType.OrigSym().Def.Type() + nameNode = typecheck.Lookdot1(call.X, se.Sel, genRecvType, genRecvType.Methods(), 1).Nname.(*ir.Name) + subtargs := recvType.RParams() s2targs := make([]*types.Type, len(subtargs)) for i, t := range subtargs { s2targs[i] = subst.Typ(t) @@ -1560,14 +1614,16 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) } sym = g.getDictionarySym(nameNode, subtargs, false) - case ir.OXDOT: + case ir.OXDOT, ir.OMETHEXPR, ir.OMETHVALUE: selExpr := n.(*ir.SelectorExpr) - subtargs := deref(selExpr.X.Type()).RParams() + recvType := deref(selExpr.Selection.Type.Recv().Type) + genRecvType := recvType.OrigSym().Def.Type() + subtargs := recvType.RParams() s2targs := make([]*types.Type, len(subtargs)) for i, t := range subtargs { s2targs[i] = subst.Typ(t) } - nameNode := selExpr.Selection.Nname.(*ir.Name) + nameNode := typecheck.Lookdot1(selExpr, selExpr.Sel, genRecvType, genRecvType.Methods(), 1).Nname.(*ir.Name) sym = g.getDictionarySym(nameNode, s2targs, true) default: @@ -1584,11 +1640,13 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) } } + g.instantiateMethods() delay := &delayInfo{ - gf: gf, - targs: targs, - sym: sym, - off: off, + gf: gf, + targs: targs, + sym: sym, + off: off, + isMeth: isMeth, } g.dictSymsToFinalize = append(g.dictSymsToFinalize, delay) return sym @@ -1604,10 +1662,11 @@ func (g *irgen) finalizeSyms() { infoPrint("=== Finalizing dictionary %s\n", d.sym.Name) lsym := d.sym.Linksym() - info := g.getGfInfo(d.gf) + instInfo := g.getInstantiation(d.gf, d.targs, d.isMeth) + info := instInfo.dictInfo subst := typecheck.Tsubster{ - Tparams: info.tparams, + Tparams: info.shapeParams, Targs: d.targs, } @@ -1615,10 +1674,10 @@ func (g *irgen) finalizeSyms() { for _, n := range info.itabConvs { var srctype, dsttype *types.Type switch n.Op() { - case ir.OXDOT: + case ir.OXDOT, ir.OMETHVALUE: se := n.(*ir.SelectorExpr) srctype = subst.Typ(se.X.Type()) - dsttype = subst.Typ(se.X.Type().Bound()) + dsttype = subst.Typ(info.shapeToBound[se.X.Type()]) found := false for i, m := range dsttype.AllMethods().Slice() { if se.Sel == m.Sym { @@ -1649,6 +1708,9 @@ func (g *irgen) finalizeSyms() { d.off = objw.Uintptr(lsym, d.off, 0) infoPrint(" + Unused itab entry for %v\n", srctype) } else { + // Make sure all new fully-instantiated types have + // their methods created before generating any itabs. + g.instantiateMethods() itabLsym := reflectdata.ITabLsym(srctype, dsttype) d.off = objw.SymPtr(lsym, d.off, itabLsym, 0) infoPrint(" + Itab for (%v,%v)\n", srctype, dsttype) @@ -1687,66 +1749,50 @@ func (g *irgen) getDictionaryValue(gf *ir.Name, targs []*types.Type, isMeth bool return np } -// hasTParamNodes returns true if the type of any node in targs has a typeparam. -func hasTParamNodes(targs []ir.Node) bool { +// hasShapeNodes returns true if the type of any node in targs has a shape. +func hasShapeNodes(targs []ir.Node) bool { for _, n := range targs { - if n.Type().HasTParam() { + if n.Type().HasShape() { return true } } return false } -// hasTParamNodes returns true if any type in targs has a typeparam. -func hasTParamTypes(targs []*types.Type) bool { +// hasShapeTypes returns true if any type in targs has a shape. +func hasShapeTypes(targs []*types.Type) bool { for _, t := range targs { - if t.HasTParam() { + if t.HasShape() { return true } } return false } -// getGfInfo get information for a generic function - type params, derived generic -// types, and subdictionaries. -func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo { - infop := g.gfInfoMap[gn.Sym()] - if infop != nil { - return infop - } +// getInstInfo get the dictionary format for a function instantiation- type params, derived +// types, and needed subdictionaries and itabs. +func (g *irgen) getInstInfo(st *ir.Func, shapes []*types.Type, instInfo *instInfo) { + info := instInfo.dictInfo + info.shapeParams = shapes - checkFetchBody(gn) - var info gfInfo - gf := gn.Func - recv := gf.Type().Recv() - if recv != nil { - info.tparams = deref(recv.Type).RParams() - } else { - tparams := gn.Type().TParams().FieldSlice() - info.tparams = make([]*types.Type, len(tparams)) - for i, f := range tparams { - info.tparams[i] = f.Type - } - } - - for _, t := range info.tparams { - b := t.Bound() - if b.HasTParam() { + for _, t := range info.shapeParams { + b := info.shapeToBound[t] + if b.HasShape() { // If a type bound is parameterized (unusual case), then we // may need its derived type to do a type assert when doing a // bound call for a type arg that is an interface. - addType(&info, nil, b) + addType(info, nil, b) } } - for _, n := range gf.Dcl { - addType(&info, n, n.Type()) - n.DictIndex = uint16(info.findDictType(n.Type()) + 1) + for _, n := range st.Dcl { + addType(info, n, n.Type()) + n.DictIndex = uint16(findDictType(instInfo, n.Type()) + 1) } if infoPrintMode { - fmt.Printf(">>> GfInfo for %v\n", gn) - for _, t := range info.tparams { + fmt.Printf(">>> InstInfo for %v\n", st) + for _, t := range info.shapeParams { fmt.Printf(" Typeparam %v\n", t) } } @@ -1754,14 +1800,14 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo { var visitFunc func(ir.Node) visitFunc = func(n ir.Node) { if n.Op() == ir.OFUNCINST && !n.(*ir.InstExpr).Implicit() { - if hasTParamNodes(n.(*ir.InstExpr).Targs) { + if hasShapeNodes(n.(*ir.InstExpr).Targs) { infoPrint(" Closure&subdictionary required at generic function value %v\n", n.(*ir.InstExpr).X) info.subDictCalls = append(info.subDictCalls, n) } - } else if n.Op() == ir.OXDOT && !n.(*ir.SelectorExpr).Implicit() && - n.(*ir.SelectorExpr).Selection != nil && + } else if (n.Op() == ir.OMETHEXPR || n.Op() == ir.OMETHVALUE) && !n.(*ir.SelectorExpr).Implicit() && + !types.IsInterfaceMethod(n.(*ir.SelectorExpr).Selection.Type) && len(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) > 0 { - if hasTParamTypes(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) { + if hasShapeTypes(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) { if n.(*ir.SelectorExpr).X.Op() == ir.OTYPE { infoPrint(" Closure&subdictionary required at generic meth expr %v\n", n) } else { @@ -1772,34 +1818,33 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo { } if n.Op() == ir.OCALL && n.(*ir.CallExpr).X.Op() == ir.OFUNCINST { n.(*ir.CallExpr).X.(*ir.InstExpr).SetImplicit(true) - if hasTParamNodes(n.(*ir.CallExpr).X.(*ir.InstExpr).Targs) { + if hasShapeNodes(n.(*ir.CallExpr).X.(*ir.InstExpr).Targs) { infoPrint(" Subdictionary at generic function/method call: %v - %v\n", n.(*ir.CallExpr).X.(*ir.InstExpr).X, n) info.subDictCalls = append(info.subDictCalls, n) } } - if n.Op() == ir.OCALL && n.(*ir.CallExpr).X.Op() == ir.OXDOT && - n.(*ir.CallExpr).X.(*ir.SelectorExpr).Selection != nil && + if n.Op() == ir.OCALLMETH && n.(*ir.CallExpr).X.Op() == ir.ODOTMETH && + //n.(*ir.CallExpr).X.(*ir.SelectorExpr).Selection != nil && len(deref(n.(*ir.CallExpr).X.(*ir.SelectorExpr).X.Type()).RParams()) > 0 { n.(*ir.CallExpr).X.(*ir.SelectorExpr).SetImplicit(true) - if hasTParamTypes(deref(n.(*ir.CallExpr).X.(*ir.SelectorExpr).X.Type()).RParams()) { + if hasShapeTypes(deref(n.(*ir.CallExpr).X.(*ir.SelectorExpr).X.Type()).RParams()) { infoPrint(" Subdictionary at generic method call: %v\n", n) info.subDictCalls = append(info.subDictCalls, n) } } if n.Op() == ir.OCALL && n.(*ir.CallExpr).X.Op() == ir.OXDOT && - n.(*ir.CallExpr).X.(*ir.SelectorExpr).Selection != nil && - deref(n.(*ir.CallExpr).X.(*ir.SelectorExpr).X.Type()).IsTypeParam() { + isShapeDeref(n.(*ir.CallExpr).X.(*ir.SelectorExpr).X.Type()) { n.(*ir.CallExpr).X.(*ir.SelectorExpr).SetImplicit(true) infoPrint(" Optional subdictionary at generic bound call: %v\n", n) info.subDictCalls = append(info.subDictCalls, n) } if n.Op() == ir.OCONVIFACE && n.Type().IsInterface() && !n.Type().IsEmptyInterface() && - n.(*ir.ConvExpr).X.Type().HasTParam() { + n.(*ir.ConvExpr).X.Type().HasShape() { infoPrint(" Itab for interface conv: %v\n", n) info.itabConvs = append(info.itabConvs, n) } - if n.Op() == ir.OXDOT && n.(*ir.SelectorExpr).X.Type().IsTypeParam() { + if n.Op() == ir.OXDOT && n.(*ir.SelectorExpr).X.Type().IsShape() { infoPrint(" Itab for bound call: %v\n", n) info.itabConvs = append(info.itabConvs, n) } @@ -1816,13 +1861,13 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo { ir.Visit(n1, visitFunc) } for _, n := range cfunc.Dcl { - n.DictIndex = uint16(info.findDictType(n.Type()) + 1) + n.DictIndex = uint16(findDictType(instInfo, n.Type()) + 1) } } if n.Op() == ir.OSWITCH && n.(*ir.SwitchStmt).Tag != nil && n.(*ir.SwitchStmt).Tag.Op() == ir.OTYPESW && !n.(*ir.SwitchStmt).Tag.(*ir.TypeSwitchGuard).X.Type().IsEmptyInterface() { for _, cc := range n.(*ir.SwitchStmt).Cases { for _, c := range cc.List { - if c.Op() == ir.OTYPE && c.Type().HasTParam() { + if c.Op() == ir.OTYPE && c.Type().HasShape() { // Type switch from a non-empty interface - might need an itab. infoPrint(" Itab for type switch: %v\n", c) info.itabConvs = append(info.itabConvs, c) @@ -1834,41 +1879,48 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo { } } } - addType(&info, n, n.Type()) + addType(info, n, n.Type()) } - for _, stmt := range gf.Body { + for _, stmt := range st.Body { ir.Visit(stmt, visitFunc) } if infoPrintMode { for _, t := range info.derivedTypes { fmt.Printf(" Derived type %v\n", t) } - fmt.Printf(">>> Done Gfinfo\n") + fmt.Printf(">>> Done Instinfo\n") } - g.gfInfoMap[gn.Sym()] = &info - return &info + info.startSubDict = len(info.shapeParams) + len(info.derivedTypes) + info.startItabConv = len(info.shapeParams) + len(info.derivedTypes) + len(info.subDictCalls) + info.dictLen = len(info.shapeParams) + len(info.derivedTypes) + len(info.subDictCalls) + len(info.itabConvs) +} + +// isShapeDeref returns true if t is either a shape or a pointer to a shape. (We +// can't just use deref(t).IsShape(), since a shape type is a complex type and may +// have a pointer as part of its shape.) +func isShapeDeref(t *types.Type) bool { + return t.IsShape() || t.IsPtr() && t.Elem().IsShape() } // addType adds t to info.derivedTypes if it is parameterized type (which is not -// just a simple type param) that is different from any existing type on +// just a simple shape) that is different from any existing type on // info.derivedTypes. -func addType(info *gfInfo, n ir.Node, t *types.Type) { - if t == nil || !t.HasTParam() { +func addType(info *dictInfo, n ir.Node, t *types.Type) { + if t == nil || !t.HasShape() { return } - if t.IsTypeParam() && t.Underlying() == t { + if t.IsShape() { return } if t.Kind() == types.TFUNC && n != nil && - (t.Recv() != nil || - n.Op() == ir.ONAME && n.Name().Class == ir.PFUNC) { + (t.Recv() != nil || n.Op() == ir.ONAME && n.Name().Class == ir.PFUNC) { // Don't use the type of a named generic function or method, // since that is parameterized by other typeparams. // (They all come from arguments of a FUNCINST node.) return } - if doubleCheck && !parameterizedBy(t, info.tparams) { + if doubleCheck && !parameterizedBy(t, info.shapeParams) { base.Fatalf("adding type with invalid parameters %+v", t) } if t.Kind() == types.TSTRUCT && t.IsFuncArgStruct() { @@ -1877,7 +1929,7 @@ func addType(info *gfInfo, n ir.Node, t *types.Type) { } // Ignore a derived type we've already added. for _, et := range info.derivedTypes { - if types.Identical(t, et) { + if types.IdenticalStrict(t, et) { return } } @@ -1903,8 +1955,7 @@ func parameterizedBy1(t *types.Type, params []*types.Type, visited map[*types.Ty } return true } - switch t.Kind() { - case types.TTYPEPARAM: + if t.IsShape() { // Check if t is one of the allowed parameters in scope. for _, p := range params { if p == t { @@ -1914,6 +1965,8 @@ func parameterizedBy1(t *types.Type, params []*types.Type, visited map[*types.Ty // Couldn't find t in the list of allowed parameters. return false + } + switch t.Kind() { case types.TARRAY, types.TPTR, types.TSLICE, types.TCHAN: return parameterizedBy1(t.Elem(), params, visited) @@ -2004,17 +2057,17 @@ func startClosure(pos src.XPos, outer *ir.Func, typ *types.Type) (*ir.Func, []*t } // assertToBound returns a new node that converts a node rcvr with interface type to -// the 'dst' interface type. bound is the unsubstituted form of dst. -func assertToBound(info *instInfo, dictVar *ir.Name, pos src.XPos, rcvr ir.Node, bound, dst *types.Type) ir.Node { - if bound.HasTParam() { - ix := findDictType(info, bound) +// the 'dst' interface type. +func assertToBound(info *instInfo, dictVar *ir.Name, pos src.XPos, rcvr ir.Node, dst *types.Type) ir.Node { + if dst.HasShape() { + ix := findDictType(info, dst) assert(ix >= 0) rt := getDictionaryType(info, dictVar, pos, ix) rcvr = ir.NewDynamicTypeAssertExpr(pos, ir.ODYNAMICDOTTYPE, rcvr, rt) typed(dst, rcvr) } else { rcvr = ir.NewTypeAssertExpr(pos, rcvr, nil) - typed(bound, rcvr) + typed(dst, rcvr) } return rcvr } @@ -2026,9 +2079,8 @@ func assertToBound(info *instInfo, dictVar *ir.Name, pos src.XPos, rcvr ir.Node, // // The returned closure is fully substituted and has already had any needed // transformations done. -func (g *irgen) buildClosure2(subst *subster, m, x ir.Node) ir.Node { - outer := subst.newf - info := subst.info +func (g *irgen) buildClosure2(info *instInfo, m ir.Node) ir.Node { + outer := info.fun pos := m.Pos() typ := m.Type() // type of the closure @@ -2051,24 +2103,18 @@ func (g *irgen) buildClosure2(subst *subster, m, x ir.Node) ir.Node { rcvr := args[0] args = args[1:] assert(m.(*ir.SelectorExpr).X.Type().IsShape()) - gsrc := x.(*ir.SelectorExpr).X.Type() - bound := gsrc.Bound() - dst := bound - if dst.HasTParam() { - dst = subst.ts.Typ(bound) - } + dst := info.dictInfo.shapeToBound[m.(*ir.SelectorExpr).X.Type()] if m.(*ir.SelectorExpr).X.Type().IsInterface() { // If type arg is an interface (unusual case), we do a type assert to // the type bound. - rcvr = assertToBound(info, dictVar, pos, rcvr, bound, dst) + rcvr = assertToBound(info, dictVar, pos, rcvr, dst) } else { - rcvr = convertUsingDictionary(info, dictVar, pos, rcvr, x, dst, gsrc) + rcvr = convertUsingDictionary(info, dictVar, pos, rcvr, m, dst) } - dot := ir.NewSelectorExpr(pos, ir.ODOTINTER, rcvr, x.(*ir.SelectorExpr).Sel) + dot := ir.NewSelectorExpr(pos, ir.ODOTINTER, rcvr, m.(*ir.SelectorExpr).Sel) dot.Selection = typecheck.Lookdot1(dot, dot.Sel, dot.X.Type(), dot.X.Type().AllMethods(), 1) - // Do a type substitution on the generic bound, in case it is parameterized. - typed(subst.ts.Typ(x.(*ir.SelectorExpr).Selection.Type), dot) + typed(dot.Selection.Type, dot) innerCall = ir.NewCallExpr(pos, ir.OCALLINTER, dot, args) t := m.Type() if t.NumResults() == 0 { diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 183ede789e..f42bb338d0 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -1921,7 +1921,7 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy // Target method uses shaped names. targs2 := make([]*types.Type, len(targs)) for i, t := range targs { - targs2[i] = typecheck.Shapify(t) + targs2[i] = typecheck.Shapify(t, i) } targs = targs2 diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 5854e3c458..64d30eeb5a 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1019,10 +1019,11 @@ type Tsubster struct { SubstForwFunc func(*types.Type) *types.Type } -// Typ computes the type obtained by substituting any type parameter in t with the -// corresponding type argument in subst. If t contains no type parameters, the -// result is t; otherwise the result is a new type. It deals with recursive types -// by using TFORW types and finding partially or fully created types via sym.Def. +// Typ computes the type obtained by substituting any type parameter or shape in t +// that appears in subst.Tparams with the corresponding type argument in subst.Targs. +// If t contains no type parameters, the result is t; otherwise the result is a new +// type. It deals with recursive types by using TFORW types and finding partially or +// fully created types via sym.Def. func (ts *Tsubster) Typ(t *types.Type) *types.Type { // Defer the CheckSize calls until we have fully-defined // (possibly-recursive) top-level type. @@ -1033,14 +1034,14 @@ func (ts *Tsubster) Typ(t *types.Type) *types.Type { } func (ts *Tsubster) typ1(t *types.Type) *types.Type { - if !t.HasTParam() && t.Kind() != types.TFUNC { + if !t.HasTParam() && !t.HasShape() && t.Kind() != types.TFUNC { // Note: function types need to be copied regardless, as the // types of closures may contain declarations that need // to be copied. See #45738. return t } - if t.IsTypeParam() { + if t.IsTypeParam() || t.IsShape() { for i, tp := range ts.Tparams { if tp == t { return ts.Targs[i] @@ -1072,14 +1073,14 @@ func (ts *Tsubster) typ1(t *types.Type) *types.Type { var targsChanged bool var forw *types.Type - if t.Sym() != nil && t.HasTParam() { + if t.Sym() != nil && (t.HasTParam() || t.HasShape()) { // Need to test for t.HasTParam() again because of special TFUNC case above. // Translate the type params for this type according to // the tparam/targs mapping from subst. neededTargs = make([]*types.Type, len(t.RParams())) for i, rparam := range t.RParams() { neededTargs[i] = ts.typ1(rparam) - if !types.Identical(neededTargs[i], rparam) { + if !types.IdenticalStrict(neededTargs[i], rparam) { targsChanged = true } } @@ -1286,7 +1287,7 @@ func (ts *Tsubster) typ1(t *types.Type) *types.Type { // fields, set force to true. func (ts *Tsubster) tstruct(t *types.Type, force bool) *types.Type { if t.NumFields() == 0 { - if t.HasTParam() { + if t.HasTParam() || t.HasShape() { // For an empty struct, we need to return a new type, // since it may now be fully instantiated (HasTParam // becomes false). @@ -1388,19 +1389,20 @@ func genericTypeName(sym *types.Sym) string { return sym.Name[0:strings.Index(sym.Name, "[")] } -// Shapify takes a concrete type and returns a GCshape type that can +// Shapify takes a concrete type and a type param index, and returns a GCshape type that can // be used in place of the input type and still generate identical code. // No methods are added - all methods calls directly on a shape should // be done by converting to an interface using the dictionary. // -// TODO: this could take the generic function and base its decisions -// on how that generic function uses this type argument. For instance, -// if it doesn't use it as a function argument/return value, then -// we don't need to distinguish int64 and float64 (because they only -// differ in how they get passed as arguments). For now, we only -// unify two different types if they are identical in every possible way. -func Shapify(t *types.Type) *types.Type { - assert(!t.HasShape()) +// For now, we only consider two types to have the same shape, if they have exactly +// the same underlying type or they are both pointer types. +// +// Shape types are also distinguished by the index of the type in a type param/arg +// list. We need to do this so we can distinguish and substitute properly for two +// type params in the same function that have the same shape for a particular +// instantiation. +func Shapify(t *types.Type, index int) *types.Type { + assert(!t.IsShape()) // Map all types with the same underlying type to the same shape. u := t.Underlying() @@ -1410,15 +1412,24 @@ func Shapify(t *types.Type) *types.Type { u = types.Types[types.TUINT8].PtrTo() } - if s := shaped[u]; s != nil { + if shapeMap == nil { + shapeMap = map[int]map[*types.Type]*types.Type{} + } + submap := shapeMap[index] + if submap == nil { + submap = map[*types.Type]*types.Type{} + shapeMap[index] = submap + } + if s := submap[u]; s != nil { return s } - sym := types.ShapePkg.Lookup(u.LinkString()) + nm := fmt.Sprintf("%s_%d", u.LinkString(), index) + sym := types.ShapePkg.Lookup(nm) if sym.Def != nil { // Use any existing type with the same name - shaped[u] = sym.Def.Type() - return shaped[u] + submap[u] = sym.Def.Type() + return submap[u] } name := ir.NewDeclNameAt(u.Pos(), ir.OTYPE, sym) s := types.NewNamed(name) @@ -1428,8 +1439,8 @@ func Shapify(t *types.Type) *types.Type { s.SetHasShape(true) name.SetType(s) name.SetTypecheck(1) - shaped[u] = s + submap[u] = s return s } -var shaped = map[*types.Type]*types.Type{} +var shapeMap map[int]map[*types.Type]*types.Type diff --git a/src/cmd/compile/internal/types/identity.go b/src/cmd/compile/internal/types/identity.go index 2e9e2f4fd8..dce7d29143 100644 --- a/src/cmd/compile/internal/types/identity.go +++ b/src/cmd/compile/internal/types/identity.go @@ -4,19 +4,30 @@ package types +const ( + identIgnoreTags = 1 << iota + identStrict +) + // Identical reports whether t1 and t2 are identical types, following the spec rules. // Receiver parameter types are ignored. Named (defined) types are only equal if they // are pointer-equal - i.e. there must be a unique types.Type for each specific named // type. Also, a type containing a shape type is considered identical to another type // (shape or not) if their underlying types are the same, or they are both pointers. func Identical(t1, t2 *Type) bool { - return identical(t1, t2, true, nil) + return identical(t1, t2, 0, nil) } // IdenticalIgnoreTags is like Identical, but it ignores struct tags // for struct identity. func IdenticalIgnoreTags(t1, t2 *Type) bool { - return identical(t1, t2, false, nil) + return identical(t1, t2, identIgnoreTags, nil) +} + +// IdenticalStrict is like Identical, but matches types exactly, without the +// exception for shapes. +func IdenticalStrict(t1, t2 *Type) bool { + return identical(t1, t2, identStrict, nil) } type typePair struct { @@ -24,7 +35,7 @@ type typePair struct { t2 *Type } -func identical(t1, t2 *Type, cmpTags bool, assumedEqual map[typePair]struct{}) bool { +func identical(t1, t2 *Type, flags int, assumedEqual map[typePair]struct{}) bool { if t1 == t2 { return true } @@ -32,7 +43,7 @@ func identical(t1, t2 *Type, cmpTags bool, assumedEqual map[typePair]struct{}) b return false } if t1.sym != nil || t2.sym != nil { - if t1.HasShape() || t2.HasShape() { + if flags&identStrict == 0 && (t1.HasShape() || t2.HasShape()) { switch t1.kind { case TINT8, TUINT8, TINT16, TUINT16, TINT32, TUINT32, TINT64, TUINT64, TINT, TUINT, TUINTPTR, TCOMPLEX64, TCOMPLEX128, TFLOAT32, TFLOAT64, TBOOL, TSTRING, TPTR, TUNSAFEPTR: return true @@ -78,7 +89,7 @@ cont: } for i, f1 := range t1.AllMethods().Slice() { f2 := t2.AllMethods().Index(i) - if f1.Sym != f2.Sym || !identical(f1.Type, f2.Type, cmpTags, assumedEqual) { + if f1.Sym != f2.Sym || !identical(f1.Type, f2.Type, flags, assumedEqual) { return false } } @@ -90,10 +101,10 @@ cont: } for i, f1 := range t1.FieldSlice() { f2 := t2.Field(i) - if f1.Sym != f2.Sym || f1.Embedded != f2.Embedded || !identical(f1.Type, f2.Type, cmpTags, assumedEqual) { + if f1.Sym != f2.Sym || f1.Embedded != f2.Embedded || !identical(f1.Type, f2.Type, flags, assumedEqual) { return false } - if cmpTags && f1.Note != f2.Note { + if (flags&identIgnoreTags) == 0 && f1.Note != f2.Note { return false } } @@ -111,7 +122,7 @@ cont: } for i, f1 := range fs1 { f2 := fs2[i] - if f1.IsDDD() != f2.IsDDD() || !identical(f1.Type, f2.Type, cmpTags, assumedEqual) { + if f1.IsDDD() != f2.IsDDD() || !identical(f1.Type, f2.Type, flags, assumedEqual) { return false } } @@ -129,10 +140,10 @@ cont: } case TMAP: - if !identical(t1.Key(), t2.Key(), cmpTags, assumedEqual) { + if !identical(t1.Key(), t2.Key(), flags, assumedEqual) { return false } } - return identical(t1.Elem(), t2.Elem(), cmpTags, assumedEqual) + return identical(t1.Elem(), t2.Elem(), flags, assumedEqual) } -- GitLab From cfa233d76bcff00f46f5e5acdb17cb819a309d2b Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sun, 12 Sep 2021 12:21:48 -0700 Subject: [PATCH 1163/2500] cmd/compile: remove unneeded early transforms, with dictionary change Now that we are computing the dictionary format on the instantiated functions, we can remove the early transformation code that was needed to create the implicit CONVIFACE nodes in the generic function. Change-Id: I1695484e7d59bccbfb757994f3e40e84288759a5 Reviewed-on: https://go-review.googlesource.com/c/go/+/349614 Run-TryBot: Dan Scales TryBot-Result: Go Bot Trust: Dan Scales Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/expr.go | 38 ---------- src/cmd/compile/internal/noder/helpers.go | 11 --- src/cmd/compile/internal/noder/stmt.go | 9 --- src/cmd/compile/internal/noder/transform.go | 84 ++++++--------------- src/cmd/compile/internal/typecheck/subr.go | 3 + 5 files changed, 26 insertions(+), 119 deletions(-) diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 045f028e1a..3e1960f7a4 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -250,44 +250,6 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto // only be fully transformed once it has an instantiated type. n := ir.NewSelectorExpr(pos, ir.OXDOT, x, typecheck.Lookup(expr.Sel.Value)) typed(g.typ(typ), n) - - // Fill in n.Selection for a generic method reference or a bound - // interface method, even though we won't use it directly, since it - // is useful for analysis. Specifically do not fill in for fields or - // other interfaces methods (method call on an interface value), so - // n.Selection being non-nil means a method reference for a generic - // type or a method reference due to a bound. - obj2 := g.info.Selections[expr].Obj() - sig := types2.AsSignature(obj2.Type()) - if sig == nil || sig.Recv() == nil { - return n - } - index := g.info.Selections[expr].Index() - last := index[len(index)-1] - // recvType is the receiver of the method being called. Because of the - // way methods are imported, g.obj(obj2) doesn't work across - // packages, so we have to lookup the method via the receiver type. - recvType := deref2(sig.Recv().Type()) - if types2.AsInterface(recvType.Underlying()) != nil { - fieldType := n.X.Type() - for _, ix := range index[:len(index)-1] { - fieldType = deref(fieldType).Field(ix).Type - } - if fieldType.Kind() == types.TTYPEPARAM { - n.Selection = fieldType.Bound().AllMethods().Index(last) - //fmt.Printf(">>>>> %v: Bound call %v\n", base.FmtPos(pos), n.Sel) - } else { - assert(fieldType.Kind() == types.TINTER) - //fmt.Printf(">>>>> %v: Interface call %v\n", base.FmtPos(pos), n.Sel) - } - return n - } - - recvObj := types2.AsNamed(recvType).Obj() - recv := g.pkg(recvObj.Pkg()).Lookup(recvObj.Name()).Def - n.Selection = recv.Type().Methods().Index(last) - //fmt.Printf(">>>>> %v: Method call %v\n", base.FmtPos(pos), n.Sel) - return n } diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index 9487e76336..f06dd8b065 100644 --- a/src/cmd/compile/internal/noder/helpers.go +++ b/src/cmd/compile/internal/noder/helpers.go @@ -189,17 +189,6 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) // A function instantiation (even if fully concrete) shouldn't be // transformed yet, because we need to add the dictionary during the // transformation. - // - // However, if we have a function type (even though it is - // parameterized), then we can add in any needed CONVIFACE nodes via - // typecheckaste(). We need to call transformArgs() to deal first - // with the f(g(()) case where g returns multiple return values. We - // can't do anything if fun is a type param (which is probably - // described by a structural constraint) - if fun.Type().Kind() == types.TFUNC { - transformArgs(n) - typecheckaste(ir.OCALL, fun, n.IsDDD, fun.Type().Params(), n.Args, true) - } return typed(typ, n) } diff --git a/src/cmd/compile/internal/noder/stmt.go b/src/cmd/compile/internal/noder/stmt.go index 146761c23f..1c366296fc 100644 --- a/src/cmd/compile/internal/noder/stmt.go +++ b/src/cmd/compile/internal/noder/stmt.go @@ -101,8 +101,6 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { n.Def = initDefn(n, names) if delay { - earlyTransformAssign(n, lhs, rhs) - n.X, n.Y = lhs[0], rhs[0] n.SetTypecheck(3) return n } @@ -117,7 +115,6 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { n := ir.NewAssignListStmt(g.pos(stmt), ir.OAS2, lhs, rhs) n.Def = initDefn(n, names) if delay { - earlyTransformAssign(n, lhs, rhs) n.SetTypecheck(3) return n } @@ -135,12 +132,6 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { if e.Type().HasTParam() { // Delay transforming the return statement if any of the // return values have a type param. - if !ir.HasNamedResults(ir.CurFunc) { - transformArgs(n) - // But add CONVIFACE nodes where needed if - // any of the return values have interface type. - typecheckaste(ir.ORETURN, nil, false, ir.CurFunc.Type().Results(), n.Results, true) - } n.SetTypecheck(3) return n } diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index 8173bfc747..91374054b6 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -157,7 +157,7 @@ func transformCall(n *ir.CallExpr) { n.SetOp(ir.OCALLFUNC) } - typecheckaste(ir.OCALL, n.X, n.IsDDD, t.Params(), n.Args, false) + typecheckaste(ir.OCALL, n.X, n.IsDDD, t.Params(), n.Args) if l.Op() == ir.ODOTMETH && len(deref(n.X.Type().Recv().Type).RParams()) == 0 { typecheck.FixMethodCall(n) } @@ -365,59 +365,6 @@ assignOK: } } -// Version of transformAssign that can run on generic code that adds CONVIFACE calls -// as needed (and rewrites multi-value calls). -func earlyTransformAssign(stmt ir.Node, lhs, rhs []ir.Node) { - cr := len(rhs) - if len(rhs) == 1 { - if rtyp := rhs[0].Type(); rtyp != nil && rtyp.IsFuncArgStruct() { - cr = rtyp.NumFields() - } - } - - // x,y,z = f() - _, isCallExpr := rhs[0].(*ir.CallExpr) - if isCallExpr && cr > len(rhs) { - stmt := stmt.(*ir.AssignListStmt) - stmt.SetOp(ir.OAS2FUNC) - r := rhs[0].(*ir.CallExpr) - rtyp := r.Type() - - mismatched := false - failed := false - for i := range lhs { - result := rtyp.Field(i).Type - - if lhs[i].Type() == nil || result == nil { - failed = true - } else if lhs[i] != ir.BlankNode && !types.Identical(lhs[i].Type(), result) { - mismatched = true - } - } - if mismatched && !failed { - typecheck.RewriteMultiValueCall(stmt, r) - } - return - } - - // x, ok = y - if len(lhs) != len(rhs) { - assert(len(lhs) == 2 && len(rhs) == 1) - // TODO(danscales): deal with case where x or ok is an interface - // type. We want to add CONVIFACE now, but that is tricky, because - // the rhs may be AS2MAPR, AS2RECV, etc. which has two result values, - // and that is not rewritten until the order phase (o.stmt, as2ok). - return - } - - // Check for interface conversion on each assignment - for i, r := range rhs { - if lhs[i].Type() != nil && lhs[i].Type().IsInterface() { - rhs[i] = assignconvfn(r, lhs[i].Type()) - } - } -} - // Corresponds to typecheck.typecheckargs. Really just deals with multi-value calls. func transformArgs(n ir.InitNode) { var list []ir.Node @@ -457,11 +404,11 @@ func assignconvfn(n ir.Node, t *types.Type) ir.Node { return n } - if types.Identical(n.Type(), t) { + if types.IdenticalStrict(n.Type(), t) { return n } - op, why := typecheck.Assignop(n.Type(), t) + op, why := Assignop(n.Type(), t) if op == ir.OXXX { base.Fatalf("found illegal assignment %+v -> %+v; %s", n.Type(), t, why) } @@ -472,11 +419,26 @@ func assignconvfn(n ir.Node, t *types.Type) ir.Node { return r } +func Assignop(src, dst *types.Type) (ir.Op, string) { + if src == dst { + return ir.OCONVNOP, "" + } + if src == nil || dst == nil || src.Kind() == types.TFORW || dst.Kind() == types.TFORW || src.Underlying() == nil || dst.Underlying() == nil { + return ir.OXXX, "" + } + + // 1. src type is identical to dst. + if types.IdenticalStrict(src, dst) { + return ir.OCONVNOP, "" + } + return typecheck.Assignop1(src, dst) +} + // Corresponds to typecheck.typecheckaste, but we add an extra flag convifaceOnly // only. If convifaceOnly is true, we only do interface conversion. We use this to do // early insertion of CONVIFACE nodes during noder2, when the function or args may // have typeparams. -func typecheckaste(op ir.Op, call ir.Node, isddd bool, tstruct *types.Type, nl ir.Nodes, convifaceOnly bool) { +func typecheckaste(op ir.Op, call ir.Node, isddd bool, tstruct *types.Type, nl ir.Nodes) { var t *types.Type var i int @@ -495,7 +457,7 @@ func typecheckaste(op ir.Op, call ir.Node, isddd bool, tstruct *types.Type, nl i if isddd { n = nl[i] ir.SetPos(n) - if n.Type() != nil && (!convifaceOnly || t.IsInterface()) { + if n.Type() != nil { nl[i] = assignconvfn(n, t) } return @@ -505,7 +467,7 @@ func typecheckaste(op ir.Op, call ir.Node, isddd bool, tstruct *types.Type, nl i for ; i < len(nl); i++ { n = nl[i] ir.SetPos(n) - if n.Type() != nil && (!convifaceOnly || t.IsInterface()) { + if n.Type() != nil { nl[i] = assignconvfn(n, t.Elem()) } } @@ -514,7 +476,7 @@ func typecheckaste(op ir.Op, call ir.Node, isddd bool, tstruct *types.Type, nl i n = nl[i] ir.SetPos(n) - if n.Type() != nil && (!convifaceOnly || t.IsInterface()) { + if n.Type() != nil { nl[i] = assignconvfn(n, t) } i++ @@ -536,7 +498,7 @@ func transformReturn(rs *ir.ReturnStmt) { return } - typecheckaste(ir.ORETURN, nil, false, ir.CurFunc.Type().Results(), nl, false) + typecheckaste(ir.ORETURN, nil, false, ir.CurFunc.Type().Results(), nl) } // transformSelect transforms a select node, creating an assignment list as needed diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 64d30eeb5a..d4af4e172e 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -352,7 +352,10 @@ func Assignop(src, dst *types.Type) (ir.Op, string) { if types.Identical(src, dst) { return ir.OCONVNOP, "" } + return Assignop1(src, dst) +} +func Assignop1(src, dst *types.Type) (ir.Op, string) { // 2. src and dst have identical underlying types and // a. either src or dst is not a named type, or // b. both are empty interface types, or -- GitLab From 5ed7dd0650cf32edd000d2268df961e2b825aab4 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Mon, 13 Sep 2021 12:23:43 -0400 Subject: [PATCH 1164/2500] [dev.fuzz] internal/fuzz: rework default test behavior before fuzzing This change refactors some of the code to support skipping a run of the seed corpus by the go command before runFuzzing occurs. Previously, the go command would run all seed corpus for all targets that match the provided `run` argument. This will be redundant when fuzzing a target. Now, the seed corpus is only run by targets other than the one that's about to be fuzzed, and the worker handles running and reporting issues with the seed corpus. Part of the logic that needed close inspection is what to do if a failure occurs during a testing-only or coverage-only fail. If the input is already in the seed corpus, the fuzzing engine shouldn't add it. If the input is currently in the cache, then it should be written to testdata. In all cases, if an error occurs, we need to report this to the user with enough information for them to debug it. This uncovered some issues with our code when fuzzing without instrumentation, and when -run=None was provided. There are some logic fixes in this change, and some small refactors. Fixes golang/go#48327 Fixes golang/go#48296 Change-Id: I9ce2be0219c5b09277ddd308df8bc5a46d4558fa Reviewed-on: https://go-review.googlesource.com/c/go/+/349630 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- .../go/testdata/script/test_fuzz_mutator.txt | 30 +--- .../testdata/script/test_fuzz_seed_corpus.txt | 168 ++++++++++++++++++ src/internal/fuzz/coverage.go | 17 +- src/internal/fuzz/fuzz.go | 168 ++++++++++-------- src/internal/fuzz/worker.go | 45 +++-- src/testing/fuzz.go | 24 ++- 6 files changed, 327 insertions(+), 125 deletions(-) create mode 100644 src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt diff --git a/src/cmd/go/testdata/script/test_fuzz_mutator.txt b/src/cmd/go/testdata/script/test_fuzz_mutator.txt index fb7984c662..9d0738e169 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutator.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutator.txt @@ -78,6 +78,7 @@ package main import ( "bufio" + "bytes" "fmt" "io" "os" @@ -111,34 +112,11 @@ func main() { } func checkCoordLog(r io.Reader) error { - scan := bufio.NewScanner(r) - var sawASeed, sawBSeed bool - for scan.Scan() { - line := scan.Text() - switch { - case line == `FuzzA "seed"`: - if sawASeed { - return fmt.Errorf("coordinator: tested FuzzA seed multiple times") - } - sawASeed = true - - case line == `FuzzB "seed"`: - if sawBSeed { - return fmt.Errorf("coordinator: tested FuzzB seed multiple times") - } - sawBSeed = true - - default: - return fmt.Errorf("coordinator: tested something other than seeds: %s", line) - } - } - if err := scan.Err(); err != nil { + b, err := io.ReadAll(r) + if err != nil { return err } - if !sawASeed { - return fmt.Errorf("coordinator: did not test FuzzA seed") - } - if !sawBSeed { + if string(bytes.TrimSpace(b)) != `FuzzB "seed"` { return fmt.Errorf("coordinator: did not test FuzzB seed") } return nil diff --git a/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt b/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt new file mode 100644 index 0000000000..016b101d72 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt @@ -0,0 +1,168 @@ +# TODO(jayconrod): support shared memory on more platforms. +[!darwin] [!linux] [!windows] skip + +[short] skip +env GOCACHE=$WORK/cache + +# Test that fuzzing a target with a failure in f.Add prints the crash +# and doesn't write anything to testdata/fuzz +! go test -fuzz=FuzzWithAdd -run=FuzzWithAdd -fuzztime=1x +! stdout ^ok +! stdout 'Crash written to testdata[/\\]fuzz[/\\]FuzzWithAdd[/\\]' +stdout FAIL + +# Test that fuzzing a target with a sucess in f.Add and a fuzztime of only +# 1 does not produce a crash. +go test -fuzz=FuzzWithGoodAdd -run=FuzzWithGoodAdd -fuzztime=1x +stdout ok +! stdout FAIL + +# Test that fuzzing a target with a failure in testdata/fuzz prints the crash +# and doesn't write anything to testdata/fuzz +! go test -fuzz=FuzzWithTestdata -run=FuzzWithTestdata -fuzztime=1x +! stdout ^ok +! stdout 'Crash written to testdata[/\\]fuzz[/\\]FuzzWithTestdata[/\\]' +stdout FAIL + +# Test that fuzzing a target with no seed corpus or cache finds a crash, prints +# it, and write it to testdata +! go test -fuzz=FuzzWithNoCache -run=FuzzWithNoCache -fuzztime=1x +! stdout ^ok +stdout 'Crash written to testdata[/\\]fuzz[/\\]FuzzWithNoCache[/\\]' +stdout FAIL + +# Write a crashing input to the cache +mkdir $GOCACHE/fuzz/example.com/x/FuzzWithCache +cp cache-file $GOCACHE/fuzz/example.com/x/FuzzWithCache/1 + +# Test that fuzzing a target with a failure in the cache prints the crash +# and writes this as a "new" crash to testdata/fuzz +! go test -fuzz=FuzzWithCache -run=FuzzWithCache -fuzztime=1x +! stdout ^ok +stdout 'Crash written to testdata[/\\]fuzz[/\\]FuzzWithCache[/\\]' +stdout FAIL + +# Clear the fuzz cache and make sure it's gone +go clean -fuzzcache +! exists $GOCACHE/fuzz + +# The tests below should operate the exact same as the previous tests. If -fuzz +# is enabled, then whatever target is going to be fuzzed shouldn't be run by +# anything other than the workers. + +# Test that fuzzing a target (with -run=None set) with a failure in f.Add prints +# the crash and doesn't write anything to testdata/fuzz -fuzztime=1x +! go test -fuzz=FuzzWithAdd -run=None +! stdout ^ok +! stdout 'Crash written to testdata[/\\]fuzz[/\\]FuzzWithAdd[/\\]' +stdout FAIL + +# Test that fuzzing a target (with -run=None set) with a sucess in f.Add and a +# fuzztime of only 1 does not produce a crash. +go test -fuzz=FuzzWithGoodAdd -run=None -fuzztime=1x +stdout ok +! stdout FAIL + +# Test that fuzzing a target (with -run=None set) with a failure in +# testdata/fuzz prints the crash and doesn't write anything to testdata/fuzz +! go test -fuzz=FuzzWithTestdata -run=None -fuzztime=1x +! stdout ^ok +! stdout 'Crash written to testdata[/\\]fuzz[/\\]FuzzWithTestdata[/\\]' +stdout FAIL + +# Write a crashing input to the cache +mkdir $GOCACHE/fuzz/example.com/x/FuzzRunNoneWithCache +cp cache-file $GOCACHE/fuzz/example.com/x/FuzzRunNoneWithCache/1 + +# Test that fuzzing a target (with -run=None set) with a failure in the cache +# prints the crash and writes this as a "new" crash to testdata/fuzz +! go test -fuzz=FuzzRunNoneWithCache -run=None -fuzztime=1x +! stdout ^ok +stdout 'Crash written to testdata[/\\]fuzz[/\\]FuzzRunNoneWithCache[/\\]' +stdout FAIL + +# Clear the fuzz cache and make sure it's gone +go clean -fuzzcache +! exists $GOCACHE/fuzz + +# The tests below should operate the exact same way for the previous tests with +# a seed corpus (namely, they should still fail). However, the binary is built +# without instrumentation, so this should be a "testing only" run which executes +# the seed corpus before attempting to fuzz. + +go test -c +! exec ./x.test$GOEXE -test.fuzz=FuzzWithAdd -test.run=FuzzWithAdd -test.fuzztime=1x -test.fuzzcachedir=$WORK/cache +! stdout ^ok +! stdout 'Crash written to testdata[/\\]fuzz[/\\]FuzzWithAdd[/\\]' +stdout FAIL +stderr warning + +go test -c +! exec ./x.test$GOEXE -test.fuzz=FuzzWithTestdata -test.run=FuzzWithTestdata -test.fuzztime=1x -test.fuzzcachedir=$WORK/cache +! stdout ^ok +! stdout 'Crash written to testdata[/\\]fuzz[/\\]FuzzWithTestdata[/\\]' +stdout FAIL +stderr warning + +-- go.mod -- +module example.com/x + +go 1.16 +-- x_test.go -- +package x + +import "testing" + +func FuzzWithAdd(f *testing.F) { + f.Add(10) + f.Fuzz(func(t *testing.T, i int) { + if i == 10 { + t.Error("bad thing here") + } + }) +} + +func FuzzWithGoodAdd(f *testing.F) { + f.Add(10) + f.Fuzz(func(t *testing.T, i int) { + if i != 10 { + t.Error("bad thing here") + } + }) +} + +func FuzzWithTestdata(f *testing.F) { + f.Fuzz(func(t *testing.T, i int) { + if i == 10 { + t.Error("bad thing here") + } + }) +} + +func FuzzWithNoCache(f *testing.F) { + f.Fuzz(func(t *testing.T, i int) { + t.Error("bad thing here") + }) +} + +func FuzzWithCache(f *testing.F) { + f.Fuzz(func(t *testing.T, i int) { + if i == 10 { + t.Error("bad thing here") + } + }) +} + +func FuzzRunNoneWithCache(f *testing.F) { + f.Fuzz(func(t *testing.T, i int) { + if i == 10 { + t.Error("bad thing here") + } + }) +} +-- testdata/fuzz/FuzzWithTestdata/1 -- +go test fuzz v1 +int(10) +-- cache-file -- +go test fuzz v1 +int(10) \ No newline at end of file diff --git a/src/internal/fuzz/coverage.go b/src/internal/fuzz/coverage.go index 2468e70fa4..71d0132e21 100644 --- a/src/internal/fuzz/coverage.go +++ b/src/internal/fuzz/coverage.go @@ -5,6 +5,7 @@ package fuzz import ( + "fmt" "internal/unsafeheader" "math/bits" "unsafe" @@ -54,6 +55,9 @@ func SnapshotCoverage() { // diffCoverage returns a set of bits set in snapshot but not in base. // If there are no new bits set, diffCoverage returns nil. func diffCoverage(base, snapshot []byte) []byte { + if len(base) != len(snapshot) { + panic(fmt.Sprintf("the number of coverage bits changed: before=%d, after=%d", len(base), len(snapshot))) + } found := false for i := range snapshot { if snapshot[i]&^base[i] != 0 { @@ -100,9 +104,12 @@ func countBits(cov []byte) int { return n } -var coverageSnapshot = make([]byte, len(coverage())) +var ( + coverageEnabled = len(coverage()) > 0 + coverageSnapshot = make([]byte, len(coverage())) -// _counters and _ecounters mark the start and end, respectively, of where -// the 8-bit coverage counters reside in memory. They're known to cmd/link, -// which specially assigns their addresses for this purpose. -var _counters, _ecounters [0]byte + // _counters and _ecounters mark the start and end, respectively, of where + // the 8-bit coverage counters reside in memory. They're known to cmd/link, + // which specially assigns their addresses for this purpose. + _counters, _ecounters [0]byte +) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 816da3286f..7343e17e44 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -194,6 +194,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err defer statTicker.Stop() defer c.logStats() + c.logStats() for { var inputC chan fuzzInput input, ok := c.peekInput() @@ -223,12 +224,20 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err case result := <-c.resultC: // Received response from worker. + if stopping { + break + } c.updateStats(result) if c.opts.Limit > 0 && c.count >= c.opts.Limit { stop(nil) } if result.crasherMsg != "" { + if c.warmupRun() && result.entry.IsSeed { + fmt.Fprintf(c.opts.Log, "found a crash while testing seed corpus entry: %q\n", result.entry.Parent) + stop(errors.New(result.crasherMsg)) + break + } if c.canMinimize() && !result.minimizeAttempted { if crashMinimizing != nil { // This crash is not minimized, and another crash is being minimized. @@ -267,7 +276,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err stop(err) } } else if result.coverageData != nil { - if c.coverageOnlyRun() { + if c.warmupRun() { if printDebugInfo() { fmt.Fprintf( c.opts.Log, @@ -280,22 +289,15 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err ) } c.updateCoverage(result.coverageData) - c.covOnlyInputs-- - if c.covOnlyInputs == 0 { - // The coordinator has finished getting a baseline for - // coverage. Tell all of the workers to initialize their - // baseline coverage data (by setting interestingCount - // to 0). - c.interestingCount = 0 - if printDebugInfo() { - fmt.Fprintf( - c.opts.Log, - "DEBUG finished processing input corpus, elapsed: %s, entries: %d, initial coverage bits: %d\n", - c.elapsed(), - len(c.corpus.entries), - countBits(c.coverageMask), - ) - } + c.warmupInputCount-- + if printDebugInfo() && c.warmupInputCount == 0 { + fmt.Fprintf( + c.opts.Log, + "DEBUG finished processing input corpus, elapsed: %s, entries: %d, initial coverage bits: %d\n", + c.elapsed(), + len(c.corpus.entries), + countBits(c.coverageMask), + ) } } else if keepCoverage := diffCoverage(c.coverageMask, result.coverageData); keepCoverage != nil { // Found a value that expanded coverage. @@ -352,6 +354,18 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err ) } } + } else if c.warmupRun() { + // No error or coverage data was reported for this input during + // warmup, so continue processing results. + c.warmupInputCount-- + if printDebugInfo() && c.warmupInputCount == 0 { + fmt.Fprintf( + c.opts.Log, + "DEBUG finished testing-only phase, elapsed: %s, entries: %d\n", + time.Since(c.startTime), + len(c.corpus.entries), + ) + } } case inputC <- input: @@ -418,6 +432,9 @@ type CorpusEntry = struct { Values []interface{} Generation int + + // IsSeed indicates whether this entry is part of the seed corpus. + IsSeed bool } // Data returns the raw input bytes, either from the data struct field, @@ -445,15 +462,11 @@ type fuzzInput struct { // fuzz function. limit int64 - // coverageOnly indicates whether this input is for a coverage-only run. If + // warmup indicates whether this is a warmup input before fuzzing begins. If // true, the input should not be fuzzed. - coverageOnly bool + warmup bool - // interestingCount reflects the coordinator's current interestingCount - // value. - interestingCount int64 - - // coverageData reflects the coordinator's current coverageData. + // coverageData reflects the coordinator's current coverageMask. coverageData []byte } @@ -538,10 +551,11 @@ type coordinator struct { // been found this execution. interestingCount int64 - // covOnlyInputs is the number of entries in the corpus which still need to - // be received from workers when gathering baseline coverage. - // See coverageOnlyRun. - covOnlyInputs int + // warmupInputCount is the number of entries in the corpus which still need + // to be received from workers to run once during warmup, but not fuzz. This + // could be for coverage data, or only for the purposes of verifying that + // the seed corpus doesn't have any crashers. See warmupRun. + warmupInputCount int // duration is the time spent fuzzing inside workers, not counting time // starting up or tearing down. @@ -590,16 +604,6 @@ func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { if err != nil { return nil, err } - if len(corpus.entries) == 0 { - var vals []interface{} - for _, t := range opts.Types { - vals = append(vals, zeroValue(t)) - } - data := marshalCorpusFile(vals...) - h := sha256.Sum256(data) - name := fmt.Sprintf("%x", h[:4]) - corpus.entries = append(corpus.entries, CorpusEntry{Name: name, Data: data}) - } c := &coordinator{ opts: opts, startTime: time.Now(), @@ -620,18 +624,31 @@ func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { covSize := len(coverage()) if covSize == 0 { fmt.Fprintf(c.opts.Log, "warning: the test binary was not built with coverage instrumentation, so fuzzing will run without coverage guidance and may be inefficient\n") + // Even though a coverage-only run won't occur, we should still run all + // of the seed corpus to make sure there are no existing failures before + // we start fuzzing. + c.warmupInputCount = len(c.opts.Seed) + for _, e := range c.opts.Seed { + c.inputQueue.enqueue(e) + } } else { - // Set c.coverageData to a clean []byte full of zeros. - c.coverageMask = make([]byte, covSize) - c.covOnlyInputs = len(c.corpus.entries) + c.warmupInputCount = len(c.corpus.entries) for _, e := range c.corpus.entries { c.inputQueue.enqueue(e) } - if c.covOnlyInputs > 0 { - // Set c.interestingCount to -1 so the workers know when the coverage - // run is finished and can update their local coverage data. - c.interestingCount = -1 + // Set c.coverageMask to a clean []byte full of zeros. + c.coverageMask = make([]byte, covSize) + } + + if len(c.corpus.entries) == 0 { + var vals []interface{} + for _, t := range opts.Types { + vals = append(vals, zeroValue(t)) } + data := marshalCorpusFile(vals...) + h := sha256.Sum256(data) + name := fmt.Sprintf("%x", h[:4]) + c.corpus.entries = append(c.corpus.entries, CorpusEntry{Name: name, Data: data}) } return c, nil @@ -645,8 +662,12 @@ func (c *coordinator) updateStats(result fuzzResult) { func (c *coordinator) logStats() { elapsed := c.elapsed() - if c.coverageOnlyRun() { - fmt.Fprintf(c.opts.Log, "gathering baseline coverage, elapsed: %s, workers: %d, left: %d\n", elapsed, c.opts.Parallel, c.covOnlyInputs) + if c.warmupRun() { + if coverageEnabled { + fmt.Fprintf(c.opts.Log, "gathering baseline coverage, elapsed: %s, workers: %d, left: %d\n", elapsed, c.opts.Parallel, c.warmupInputCount) + } else { + fmt.Fprintf(c.opts.Log, "testing seed corpus, elapsed: %s, workers: %d, left: %d\n", elapsed, c.opts.Parallel, c.warmupInputCount) + } } else { rate := float64(c.count) / time.Since(c.startTime).Seconds() // be more precise here fmt.Fprintf(c.opts.Log, "fuzz: elapsed: %s, execs: %d (%.0f/sec), workers: %d, interesting: %d\n", elapsed, c.count, rate, c.opts.Parallel, c.interestingCount) @@ -661,7 +682,7 @@ func (c *coordinator) logStats() { // peekInput doesn't actually remove the input from the queue. The caller // must call sentInput after sending the input. // -// If the input queue is empty and the coverage-only run has completed, +// If the input queue is empty and the coverage/testing-only run has completed, // queue refills it from the corpus. func (c *coordinator) peekInput() (fuzzInput, bool) { if c.opts.Limit > 0 && c.count+c.countWaiting >= c.opts.Limit { @@ -670,8 +691,9 @@ func (c *coordinator) peekInput() (fuzzInput, bool) { return fuzzInput{}, false } if c.inputQueue.len == 0 { - if c.covOnlyInputs > 0 { - // Wait for coverage-only run to finish before sending more inputs. + if c.warmupInputCount > 0 { + // Wait for coverage/testing-only run to finish before sending more + // inputs. return fuzzInput{}, false } c.refillInputQueue() @@ -682,17 +704,17 @@ func (c *coordinator) peekInput() (fuzzInput, bool) { panic("input queue empty after refill") } input := fuzzInput{ - entry: entry.(CorpusEntry), - interestingCount: c.interestingCount, - coverageData: make([]byte, len(c.coverageMask)), - timeout: workerFuzzDuration, + entry: entry.(CorpusEntry), + timeout: workerFuzzDuration, + warmup: c.warmupRun(), } - copy(input.coverageData, c.coverageMask) - - if c.coverageOnlyRun() { - // This is a coverage-only run, so this input shouldn't be fuzzed. - // It should count toward the limit set by -fuzztime though. - input.coverageOnly = true + if c.coverageMask != nil { + input.coverageData = make([]byte, len(c.coverageMask)) + copy(input.coverageData, c.coverageMask) + } + if input.warmup { + // No fuzzing will occur, but it should count toward the limit set by + // -fuzztime. input.limit = 1 return input, true } @@ -782,22 +804,24 @@ func (c *coordinator) sentMinimizeInput(input fuzzMinimizeInput) { c.countWaiting += input.limit } -// coverageOnlyRun returns true while the coordinator is gathering baseline -// coverage data for entries in the corpus. +// warmupRun returns true while the coordinator is running inputs without +// mutating them as a warmup before fuzzing. This could be to gather baseline +// coverage data for entries in the corpus, or to test all of the seed corpus +// for errors before fuzzing begins. // -// The coordinator starts in this phase. It doesn't store coverage data in the -// cache with each input because that data would be invalid when counter -// offsets in the test binary change. +// The coordinator doesn't store coverage data in the cache with each input +// because that data would be invalid when counter offsets in the test binary +// change. // // When gathering coverage, the coordinator sends each entry to a worker to // gather coverage for that entry only, without fuzzing or minimizing. This // phase ends when all workers have finished, and the coordinator has a combined // coverage map. -func (c *coordinator) coverageOnlyRun() bool { - return c.covOnlyInputs > 0 +func (c *coordinator) warmupRun() bool { + return c.warmupInputCount > 0 } -// updateCoverage sets bits in c.coverageData that are set in newCoverage. +// updateCoverage sets bits in c.coverageMask that are set in newCoverage. // updateCoverage returns the number of newly set bits. See the comment on // coverageMask for the format. func (c *coordinator) updateCoverage(newCoverage []byte) int { @@ -814,10 +838,12 @@ func (c *coordinator) updateCoverage(newCoverage []byte) int { } // canMinimize returns whether the coordinator should attempt to find smaller -// inputs that reproduce a crash or new coverage. +// inputs that reproduce a crash or new coverage. It shouldn't do this if it +// is in the warmup phase. func (c *coordinator) canMinimize() bool { return c.minimizationAllowed && - (c.opts.Limit == 0 || c.count+c.countWaiting < c.opts.Limit) + (c.opts.Limit == 0 || c.count+c.countWaiting < c.opts.Limit) && + !c.warmupRun() } func (c *coordinator) elapsed() time.Duration { @@ -827,7 +853,7 @@ func (c *coordinator) elapsed() time.Duration { // readCache creates a combined corpus from seed values and values in the cache // (in GOCACHE/fuzz). // -// TODO(jayconrod,katiehockman): need a mechanism that can remove values that +// TODO(fuzzing): need a mechanism that can remove values that // aren't useful anymore, for example, because they have the wrong type. func readCache(seed []CorpusEntry, types []reflect.Type, cacheDir string) (corpus, error) { var c corpus diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 344c1b45b7..da82a95fa1 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -98,10 +98,6 @@ func (w *worker) cleanup() error { // those inputs to the worker process, then passes the results back to // the coordinator. func (w *worker) coordinate(ctx context.Context) error { - // interestingCount starts at -1, like the coordinator does, so that the - // worker client's coverage data is updated after a coverage-only run. - interestingCount := int64(-1) - // Main event loop. for { // Start or restart the worker if it's not running. @@ -151,11 +147,11 @@ func (w *worker) coordinate(ctx context.Context) error { case input := <-w.coordinator.inputC: // Received input from coordinator. - args := fuzzArgs{Limit: input.limit, Timeout: input.timeout, CoverageOnly: input.coverageOnly} - if interestingCount < input.interestingCount { - // The coordinator's coverage data has changed, so send the data - // to the client. - args.CoverageData = input.coverageData + args := fuzzArgs{ + Limit: input.limit, + Timeout: input.timeout, + Warmup: input.warmup, + CoverageData: input.coverageData, } entry, resp, err := w.client.fuzz(ctx, input.entry, args) if err != nil { @@ -544,9 +540,10 @@ type fuzzArgs struct { // than Duration. 0 indicates no limit. Limit int64 - // CoverageOnly indicates whether this is a coverage-only run (ie. fuzzing - // should not occur). - CoverageOnly bool + // Warmup indicates whether this is part of a warmup run, meaning that + // fuzzing should not occur. If coverageEnabled is true, then coverage data + // should be reported. + Warmup bool // CoverageData is the coverage data. If set, the worker should update its // local coverage data prior to fuzzing. @@ -713,14 +710,16 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo return dur, nil, "" } - if args.CoverageOnly { + if args.Warmup { dur, _, errMsg := fuzzOnce(CorpusEntry{Values: vals}) if errMsg != "" { resp.Err = errMsg return resp } resp.InterestingDuration = dur - resp.CoverageData = coverageSnapshot + if coverageEnabled { + resp.CoverageData = coverageSnapshot + } return resp } @@ -742,6 +741,10 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo // run the same values once more to deflake. if !shouldStop() { dur, cov, errMsg = fuzzOnce(entry) + if errMsg != "" { + resp.Err = errMsg + return resp + } } if cov != nil { resp.CoverageData = cov @@ -1069,15 +1072,18 @@ func (wc *workerClient) fuzz(ctx context.Context, entryIn CorpusEntry, args fuzz panic("workerServer.fuzz modified input") } needEntryOut := callErr != nil || resp.Err != "" || - (!args.CoverageOnly && resp.CoverageData != nil) + (!args.Warmup && resp.CoverageData != nil) if needEntryOut { valuesOut, err := unmarshalCorpusFile(inp) if err != nil { panic(fmt.Sprintf("unmarshaling fuzz input value after call: %v", err)) } wc.m.r.restore(mem.header().randState, mem.header().randInc) - for i := int64(0); i < mem.header().count; i++ { - wc.m.mutate(valuesOut, cap(mem.valueRef())) + if !args.Warmup { + // Only mutate the valuesOut if fuzzing actually occurred. + for i := int64(0); i < mem.header().count; i++ { + wc.m.mutate(valuesOut, cap(mem.valueRef())) + } } dataOut := marshalCorpusFile(valuesOut...) @@ -1089,6 +1095,11 @@ func (wc *workerClient) fuzz(ctx context.Context, entryIn CorpusEntry, args fuzz Data: dataOut, Generation: entryIn.Generation + 1, } + if args.Warmup { + // The bytes weren't mutated, so if entryIn was a seed corpus value, + // then entryOut is too. + entryOut.IsSeed = entryIn.IsSeed + } } return entryOut, resp, callErr diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index c2d9db843d..3a1b0bdeaa 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -84,6 +84,7 @@ type corpusEntry = struct { Data []byte Values []interface{} Generation int + IsSeed bool } // Cleanup registers a function to be called after the fuzz function has been @@ -258,7 +259,7 @@ func (f *F) Add(args ...interface{}) { } values = append(values, args[i]) } - f.corpus = append(f.corpus, corpusEntry{Values: values, Name: fmt.Sprintf("seed#%d", len(f.corpus))}) + f.corpus = append(f.corpus, corpusEntry{Values: values, IsSeed: true, Name: fmt.Sprintf("seed#%d", len(f.corpus))}) } // supportedTypes represents all of the supported types which can be fuzzed. @@ -344,11 +345,11 @@ func (f *F) Fuzz(ff interface{}) { if err != nil { f.Fatal(err) } - - // If this is the coordinator process, zero the values, since we don't need - // to hold onto them. - if f.fuzzContext.mode == fuzzCoordinator { - for i := range c { + for i := range c { + c[i].IsSeed = true // these are all seed corpus values + if f.fuzzContext.mode == fuzzCoordinator { + // If this is the coordinator process, zero the values, since we don't need + // to hold onto them. c[i].Values = nil } } @@ -550,6 +551,10 @@ func runFuzzTargets(deps testDeps, fuzzTargets []InternalFuzzTarget, deadline ti m := newMatcher(deps.MatchString, *match, "-test.run") tctx := newTestContext(*parallel, m) tctx.deadline = deadline + var mFuzz *matcher + if *matchFuzz != "" { + mFuzz = newMatcher(deps.MatchString, *matchFuzz, "-test.fuzz") + } fctx := &fuzzContext{deps: deps, mode: seedCorpusOnly} root := common{w: os.Stdout} // gather output in one place if Verbose() { @@ -563,6 +568,13 @@ func runFuzzTargets(deps testDeps, fuzzTargets []InternalFuzzTarget, deadline ti if !matched { continue } + if mFuzz != nil { + if _, fuzzMatched, _ := mFuzz.fullName(nil, ft.Name); fuzzMatched { + // If this target will be fuzzed, then don't run the seed corpus + // right now. That will happen later. + continue + } + } f := &F{ common: common{ signal: make(chan bool), -- GitLab From e7dbe3908e17ec77851161e6cb98c7161823aa0d Mon Sep 17 00:00:00 2001 From: Leonard Wang Date: Sat, 24 Jul 2021 22:17:21 +0800 Subject: [PATCH 1165/2500] cmd/cgo: add missing tab in exports for a result of void Change-Id: I45575afbad364c13b7179ebe3f3dfc4ed9671d2b Reviewed-on: https://go-review.googlesource.com/c/go/+/336891 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Reviewed-by: Meng Zhuo --- src/cmd/cgo/out.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index ee989b95e5..93cc0c6dc9 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -1054,9 +1054,10 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) { fmt.Fprintf(fm, "void _cgoexp%s_%s(void* p){}\n", cPrefix, exp.ExpName) + fmt.Fprintf(fgo2, "\t") + if gccResult != "void" { // Write results back to frame. - fmt.Fprintf(fgo2, "\t") forFieldList(fntype.Results, func(i int, aname string, atype ast.Expr) { if i > 0 { -- GitLab From 04f5116c987082a834a29e81c81ece8537d87219 Mon Sep 17 00:00:00 2001 From: gerrard Date: Thu, 16 Sep 2021 07:10:58 +0000 Subject: [PATCH 1166/2500] cmd/go: clean paths before checking same directory Replace `filepath.Split` with `filepath.Dir`. Clean paths before checking whether command line files are in same directory. Fixes #47392 Change-Id: I259c3024e7670e78833622b02af4710bc4b68b31 GitHub-Last-Rev: c7c4905bb9c62737e95a4663813f076ee540046b GitHub-Pull-Request: golang/go#47412 Reviewed-on: https://go-review.googlesource.com/c/go/+/337629 Trust: Bryan C. Mills Trust: Cherry Mui Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/load/pkg.go | 5 +---- src/cmd/go/testdata/script/run_dirs.txt | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index f0613a4c0a..4013330bc4 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -2674,10 +2674,7 @@ func GoFilesPackage(ctx context.Context, opts PackageOpts, gofiles []string) *Pa if fi.IsDir() { base.Fatalf("%s is a directory, should be a Go file", file) } - dir1, _ := filepath.Split(file) - if dir1 == "" { - dir1 = "./" - } + dir1 := filepath.Dir(file) if dir == "" { dir = dir1 } else if dir != dir1 { diff --git a/src/cmd/go/testdata/script/run_dirs.txt b/src/cmd/go/testdata/script/run_dirs.txt index 538a6ac6f3..bd5cfbe3fb 100644 --- a/src/cmd/go/testdata/script/run_dirs.txt +++ b/src/cmd/go/testdata/script/run_dirs.txt @@ -1,11 +1,21 @@ cd rundir ! go run x.go sub/sub.go -stderr 'named files must all be in one directory; have ./ and sub/' +stderr 'named files must all be in one directory; have . and sub' ! go run sub/sub.go x.go -stderr 'named files must all be in one directory; have sub/ and ./' +stderr 'named files must all be in one directory; have sub and .' + +cd ../ +go run rundir/foo.go ./rundir/bar.go +stderr 'hello world' -- rundir/sub/sub.go -- package main -- rundir/x.go -- package main +-- rundir/foo.go -- +package main +func main() { println(msg) } +-- rundir/bar.go -- +package main +const msg = "hello world" -- GitLab From b1bedc0774d8a3a7ff8778e933ee92e8638e9493 Mon Sep 17 00:00:00 2001 From: nimelehin Date: Wed, 15 Sep 2021 04:30:49 +0000 Subject: [PATCH 1167/2500] cmd/go: add GOAMD64 environment variable The variable represents the microarchitecture level for which to compile. Valid values are v1 (default), v2, v3, v4. Updates #45453 Change-Id: I095197fc9239d79f98896d7e745e2341354daca4 GitHub-Last-Rev: f83ed17204606264073be5b9831f9d24f2f9dbc4 GitHub-Pull-Request: golang/go#48359 Reviewed-on: https://go-review.googlesource.com/c/go/+/349595 Reviewed-by: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Bryan C. Mills --- src/cmd/dist/build.go | 11 +++++++++++ src/cmd/dist/buildruntime.go | 1 + src/cmd/go/alldocs.go | 4 ++++ src/cmd/go/internal/cfg/cfg.go | 3 +++ src/cmd/go/internal/help/helpdoc.go | 4 ++++ src/cmd/go/internal/work/gc.go | 5 +++++ src/internal/buildcfg/cfg.go | 16 ++++++++++++++++ src/internal/buildcfg/cfg_test.go | 25 +++++++++++++++++++++++++ src/internal/cfg/cfg.go | 1 + test/run.go | 2 +- 10 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 src/internal/buildcfg/cfg_test.go diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go index 33a329e48b..39f016e315 100644 --- a/src/cmd/dist/build.go +++ b/src/cmd/dist/build.go @@ -32,6 +32,7 @@ var ( goos string goarm string go386 string + goamd64 string gomips string gomips64 string goppc64 string @@ -145,6 +146,12 @@ func xinit() { } go386 = b + b = os.Getenv("GOAMD64") + if b == "" { + b = "v1" + } + goamd64 = b + b = os.Getenv("GOMIPS") if b == "" { b = "hardfloat" @@ -217,6 +224,7 @@ func xinit() { // For tools being invoked but also for os.ExpandEnv. os.Setenv("GO386", go386) + os.Setenv("GOAMD64", goamd64) os.Setenv("GOARCH", goarch) os.Setenv("GOARM", goarm) os.Setenv("GOHOSTARCH", gohostarch) @@ -1181,6 +1189,9 @@ func cmdenv() { if goarch == "386" { xprintf(format, "GO386", go386) } + if goarch == "amd64" { + xprintf(format, "GOAMD64", goamd64) + } if goarch == "mips" || goarch == "mipsle" { xprintf(format, "GOMIPS", gomips) } diff --git a/src/cmd/dist/buildruntime.go b/src/cmd/dist/buildruntime.go index 54e935ad3b..fdc1d25774 100644 --- a/src/cmd/dist/buildruntime.go +++ b/src/cmd/dist/buildruntime.go @@ -60,6 +60,7 @@ func mkbuildcfg(file string) { fmt.Fprintf(&buf, "import \"runtime\"\n") fmt.Fprintln(&buf) fmt.Fprintf(&buf, "const defaultGO386 = `%s`\n", go386) + fmt.Fprintf(&buf, "const defaultGOAMD64 = `%s`\n", goamd64) fmt.Fprintf(&buf, "const defaultGOARM = `%s`\n", goarm) fmt.Fprintf(&buf, "const defaultGOMIPS = `%s`\n", gomips) fmt.Fprintf(&buf, "const defaultGOMIPS64 = `%s`\n", gomips64) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index b7e8212795..35c60744b8 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -1987,6 +1987,10 @@ // GO386 // For GOARCH=386, how to implement floating point instructions. // Valid values are sse2 (default), softfloat. +// GOAMD64 +// For GOARCH=GOAMD64, the microarchitecture level for which to compile. +// Valid values are v1 (default), v2, v3, v4. +// See https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels. // GOMIPS // For GOARCH=mips{,le}, whether to use floating point instructions. // Valid values are hardfloat (default), softfloat. diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go index da616ee1dd..5f4465e06b 100644 --- a/src/cmd/go/internal/cfg/cfg.go +++ b/src/cmd/go/internal/cfg/cfg.go @@ -263,6 +263,7 @@ var ( // Used in envcmd.MkEnv and build ID computations. GOARM = envOr("GOARM", fmt.Sprint(buildcfg.GOARM)) GO386 = envOr("GO386", buildcfg.GO386) + GOAMD64 = envOr("GOAMD64", fmt.Sprintf("%s%d", "v", buildcfg.GOAMD64)) GOMIPS = envOr("GOMIPS", buildcfg.GOMIPS) GOMIPS64 = envOr("GOMIPS64", buildcfg.GOMIPS64) GOPPC64 = envOr("GOPPC64", fmt.Sprintf("%s%d", "power", buildcfg.GOPPC64)) @@ -289,6 +290,8 @@ func GetArchEnv() (key, val string) { return "GOARM", GOARM case "386": return "GO386", GO386 + case "amd64": + return "GOAMD64", GOAMD64 case "mips", "mipsle": return "GOMIPS", GOMIPS case "mips64", "mips64le": diff --git a/src/cmd/go/internal/help/helpdoc.go b/src/cmd/go/internal/help/helpdoc.go index 490ff1fb7c..91876cefe0 100644 --- a/src/cmd/go/internal/help/helpdoc.go +++ b/src/cmd/go/internal/help/helpdoc.go @@ -592,6 +592,10 @@ Architecture-specific environment variables: GO386 For GOARCH=386, how to implement floating point instructions. Valid values are sse2 (default), softfloat. + GOAMD64 + For GOARCH=GOAMD64, the microarchitecture level for which to compile. + Valid values are v1 (default), v2, v3, v4. + See https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels. GOMIPS For GOARCH=mips{,le}, whether to use floating point instructions. Valid values are hardfloat (default), softfloat. diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go index 1cce5d4dd5..800800f788 100644 --- a/src/cmd/go/internal/work/gc.go +++ b/src/cmd/go/internal/work/gc.go @@ -379,6 +379,11 @@ func asmArgs(a *Action, p *load.Package) []interface{} { args = append(args, "-D", "GO386_"+cfg.GO386) } + if cfg.Goarch == "amd64" { + // Define GOAMD64_value from cfg.GOAMD64. + args = append(args, "-D", "GOAMD64_"+cfg.GOAMD64) + } + if cfg.Goarch == "mips" || cfg.Goarch == "mipsle" { // Define GOMIPS_value from cfg.GOMIPS. args = append(args, "-D", "GOMIPS_"+cfg.GOMIPS) diff --git a/src/internal/buildcfg/cfg.go b/src/internal/buildcfg/cfg.go index 9fe7f211fb..68c10a2824 100644 --- a/src/internal/buildcfg/cfg.go +++ b/src/internal/buildcfg/cfg.go @@ -25,6 +25,7 @@ var ( GOARCH = envOr("GOARCH", defaultGOARCH) GOOS = envOr("GOOS", defaultGOOS) GO386 = envOr("GO386", defaultGO386) + GOAMD64 = goamd64() GOARM = goarm() GOMIPS = gomips() GOMIPS64 = gomips64() @@ -52,6 +53,21 @@ func envOr(key, value string) string { return value } +func goamd64() int { + switch v := envOr("GOAMD64", defaultGOAMD64); v { + case "v1": + return 1 + case "v2": + return 2 + case "v3": + return 3 + case "v4": + return 4 + } + Error = fmt.Errorf("invalid GOAMD64: must be v1, v2, v3, v4") + return int(defaultGOAMD64[len("v")] - '0') +} + func goarm() int { def := defaultGOARM if GOOS == "android" && GOARCH == "arm" { diff --git a/src/internal/buildcfg/cfg_test.go b/src/internal/buildcfg/cfg_test.go new file mode 100644 index 0000000000..9180441c28 --- /dev/null +++ b/src/internal/buildcfg/cfg_test.go @@ -0,0 +1,25 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package buildcfg + +import ( + "os" + "testing" +) + +func TestConfigFlags(t *testing.T) { + os.Setenv("GOAMD64", "v1") + if goamd64() != 1 { + t.Errorf("Wrong parsing of GOAMD64=v1") + } + os.Setenv("GOAMD64", "v4") + if goamd64() != 4 { + t.Errorf("Wrong parsing of GOAMD64=v4") + } + os.Setenv("GOAMD64", "1") + if goamd64() != 1 { + t.Errorf("Wrong parsing of GOAMD64=1") + } +} diff --git a/src/internal/cfg/cfg.go b/src/internal/cfg/cfg.go index 815994b679..4cb3fbd4f3 100644 --- a/src/internal/cfg/cfg.go +++ b/src/internal/cfg/cfg.go @@ -33,6 +33,7 @@ const KnownEnv = ` GCCGO GO111MODULE GO386 + GOAMD64 GOARCH GOARM GOBIN diff --git a/test/run.go b/test/run.go index 3fb87af397..7317e8019e 100644 --- a/test/run.go +++ b/test/run.go @@ -1753,7 +1753,7 @@ var ( // are the supported variants. archVariants = map[string][]string{ "386": {"GO386", "sse2", "softfloat"}, - "amd64": {}, + "amd64": {"GOAMD64", "v1", "v2", "v3", "v4"}, "arm": {"GOARM", "5", "6", "7"}, "arm64": {}, "mips": {"GOMIPS", "hardfloat", "softfloat"}, -- GitLab From 48e2b1ea91171f4fcb56cc521368969e586f033f Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Mon, 13 Sep 2021 16:23:28 -0400 Subject: [PATCH 1168/2500] cmd/compile: fix LocResults formatting When a LocResults is an empty list, it currently prints as ">". Make it print "<>". Change-Id: I0f596791b471d74cd4bbc0059e269708c80592dd Reviewed-on: https://go-review.googlesource.com/c/go/+/350144 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: David Chase --- src/cmd/compile/internal/ssa/location.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/ssa/location.go b/src/cmd/compile/internal/ssa/location.go index 252c47cdeb..b575febd72 100644 --- a/src/cmd/compile/internal/ssa/location.go +++ b/src/cmd/compile/internal/ssa/location.go @@ -91,8 +91,8 @@ func (t LocPair) String() string { type LocResults []Location func (t LocResults) String() string { - s := "<" - a := "" + s := "" + a := "<" for _, r := range t { a += s s = "," -- GitLab From bcdc61d830be61fd5f371f4eb9c345f8dc9ada55 Mon Sep 17 00:00:00 2001 From: David Chase Date: Mon, 23 Aug 2021 17:19:34 -0400 Subject: [PATCH 1169/2500] cmd/compile: preserve statements better in expandCalls Arg/Load/Dereference rewriting was not using the best Pos for translated values. I also investigated whether OpCopy processing was losing statements, and though they flood the debugging output, doing the "obvious" thing of moving statement marks from copi-er to copy-ee actually makes the resulting binary score slightly worse on statement-boundary measures. (for -N -l, 0.9994 vs 0.9995 from "nostmt -c sqle.test") Fixes #47793. Change-Id: I65cb878d0e5a3ceb5da4ef679020ca5f40e9b02b Reviewed-on: https://go-review.googlesource.com/c/go/+/344769 Trust: David Chase Run-TryBot: David Chase TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/compile/internal/ssa/expand_calls.go | 91 +++++++++++--------- src/cmd/compile/internal/ssa/value.go | 10 ++- 2 files changed, 59 insertions(+), 42 deletions(-) diff --git a/src/cmd/compile/internal/ssa/expand_calls.go b/src/cmd/compile/internal/ssa/expand_calls.go index b37d3b8c9c..12c7b16acd 100644 --- a/src/cmd/compile/internal/ssa/expand_calls.go +++ b/src/cmd/compile/internal/ssa/expand_calls.go @@ -176,7 +176,7 @@ func (c *registerCursor) hasRegs() bool { type expandState struct { f *Func abi1 *abi.ABIConfig - debug bool + debug int // odd values log lost statement markers, so likely settings are 1 (stmts), 2 (expansion), and 3 (both) canSSAType func(*types.Type) bool regSize int64 sp *Value @@ -302,7 +302,7 @@ func (x *expandState) Printf(format string, a ...interface{}) (n int, err error) // // TODO when registers really arrive, must also decompose anything split across two registers or registers and memory. func (x *expandState) rewriteSelect(leaf *Value, selector *Value, offset int64, regOffset Abi1RO) []*LocalSlot { - if x.debug { + if x.debug > 1 { x.indent(3) defer x.indent(-3) x.Printf("rewriteSelect(%s; %s; memOff=%d; regOff=%d)\n", leaf.LongString(), selector.LongString(), offset, regOffset) @@ -325,7 +325,7 @@ func (x *expandState) rewriteSelect(leaf *Value, selector *Value, offset int64, } else { x.f.Fatalf("Unexpected %s type, selector=%s, leaf=%s\n", selector.Op.String(), selector.LongString(), leaf.LongString()) } - if x.debug { + if x.debug > 1 { x.Printf("---%s, break\n", selector.Op.String()) } case OpArg: @@ -335,7 +335,7 @@ func (x *expandState) rewriteSelect(leaf *Value, selector *Value, offset int64, } else { x.f.Fatalf("Unexpected OpArg type, selector=%s, leaf=%s\n", selector.LongString(), leaf.LongString()) } - if x.debug { + if x.debug > 1 { x.Printf("---OpArg, break\n") } break @@ -381,7 +381,7 @@ func (x *expandState) rewriteSelect(leaf *Value, selector *Value, offset int64, // This case removes that StructSelect. if leafType != selector.Type { if x.f.Config.SoftFloat && selector.Type.IsFloat() { - if x.debug { + if x.debug > 1 { x.Printf("---OpLoad, break\n") } break // softfloat pass will take care of that @@ -468,7 +468,7 @@ func (x *expandState) rewriteSelect(leaf *Value, selector *Value, offset int64, } else { w := call.Block.NewValue2(leaf.Pos, OpLoad, leafType, off, call) leaf.copyOf(w) - if x.debug { + if x.debug > 1 { x.Printf("---new %s\n", w.LongString()) } } @@ -687,7 +687,7 @@ func (x *expandState) decomposeArg(pos src.XPos, b *Block, source, mem *Value, t panic(fmt.Errorf("offset %d of requested register %d should be zero, source=%s", offs[loadRegOffset], loadRegOffset, source.LongString())) } - if x.debug { + if x.debug > 1 { x.Printf("decompose arg %s has %d locs\n", source.LongString(), len(locs)) } @@ -836,7 +836,7 @@ func (x *expandState) decomposeLoad(pos src.XPos, b *Block, source, mem *Value, // pos and b locate the store instruction, source is the "base" of the value input, // mem is the input mem, t is the type in question, and offArg and offStore are the offsets from the respective bases. func storeOneArg(x *expandState, pos src.XPos, b *Block, locs []*LocalSlot, suffix string, source, mem *Value, t *types.Type, argOffset, storeOffset int64, loadRegOffset Abi1RO, storeRc registerCursor) *Value { - if x.debug { + if x.debug > 1 { x.indent(3) defer x.indent(-3) x.Printf("storeOneArg(%s; %s; %s; aO=%d; sO=%d; lrO=%d; %s)\n", source.LongString(), mem.String(), t.String(), argOffset, storeOffset, loadRegOffset, storeRc.String()) @@ -877,7 +877,7 @@ func storeTwoLoad(x *expandState, pos src.XPos, b *Block, source, mem *Value, t1 // stores of non-aggregate types. It recursively walks up a chain of selectors until it reaches a Load or an Arg. // If it does not reach a Load or an Arg, nothing happens; this allows a little freedom in phase ordering. func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, source, mem *Value, t *types.Type, storeOffset int64, loadRegOffset Abi1RO, storeRc registerCursor) *Value { - if x.debug { + if x.debug > 1 { x.indent(3) defer x.indent(-3) x.Printf("storeArgOrLoad(%s; %s; %s; %d; %s)\n", source.LongString(), mem.String(), t.String(), storeOffset, storeRc.String()) @@ -1060,7 +1060,7 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, source, mem *Value, dst := x.offsetFrom(b, storeRc.storeDest, storeOffset, types.NewPtr(t)) s = b.NewValue3A(pos, OpStore, types.TypeMem, t, dst, source, mem) } - if x.debug { + if x.debug > 1 { x.Printf("-->storeArg returns %s, storeRc=%s\n", s.LongString(), storeRc.String()) } return s @@ -1071,14 +1071,13 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, source, mem *Value, // to account for any parameter stores required. // Any of the old Args that have their use count fall to zero are marked OpInvalid. func (x *expandState) rewriteArgs(v *Value, firstArg int) { - if x.debug { + if x.debug > 1 { x.indent(3) defer x.indent(-3) x.Printf("rewriteArgs(%s; %d)\n", v.LongString(), firstArg) } // Thread the stores on the memory arg aux := v.Aux.(*AuxCall) - pos := v.Pos.WithNotStmt() m0 := v.MemoryArg() mem := m0 newArgs := []*Value{} @@ -1095,7 +1094,7 @@ func (x *expandState) rewriteArgs(v *Value, firstArg int) { } // "Dereference" of addressed (probably not-SSA-eligible) value becomes Move // TODO(register args) this will be more complicated with registers in the picture. - mem = x.rewriteDereference(v.Block, x.sp, a, mem, aOffset, aux.SizeOfArg(auxI), aType, pos) + mem = x.rewriteDereference(v.Block, x.sp, a, mem, aOffset, aux.SizeOfArg(auxI), aType, a.Pos) } else { var rc registerCursor var result *[]*Value @@ -1105,11 +1104,11 @@ func (x *expandState) rewriteArgs(v *Value, firstArg int) { } else { aOffset = aux.OffsetOfArg(auxI) } - if x.debug { + if x.debug > 1 { x.Printf("...storeArg %s, %v, %d\n", a.LongString(), aType, aOffset) } rc.init(aRegs, aux.abiInfo, result, x.sp) - mem = x.storeArgOrLoad(pos, v.Block, a, mem, aType, aOffset, 0, rc) + mem = x.storeArgOrLoad(a.Pos, v.Block, a, mem, aType, aOffset, 0, rc) } } var preArgStore [2]*Value @@ -1120,16 +1119,31 @@ func (x *expandState) rewriteArgs(v *Value, firstArg int) { v.AddArg(mem) for _, a := range oldArgs { if a.Uses == 0 { - if x.debug { - x.Printf("...marking %v unused\n", a.LongString()) - } - a.invalidateRecursively() + x.invalidateRecursively(a) } } return } +func (x *expandState) invalidateRecursively(a *Value) { + var s string + if x.debug > 0 { + plus := " " + if a.Pos.IsStmt() == src.PosIsStmt { + plus = " +" + } + s = a.String() + plus + a.Pos.LineNumber() + " " + a.LongString() + if x.debug > 1 { + x.Printf("...marking %v unused\n", s) + } + } + lost := a.invalidateRecursively() + if x.debug&1 != 0 && lost { // For odd values of x.debug, do this. + x.Printf("Lost statement marker in %s on former %s\n", base.Ctxt.Pkgpath+"."+x.f.Name, s) + } +} + // expandCalls converts LE (Late Expansion) calls that act like they receive value args into a lower-level form // that is more oriented to a platform's ABI. The SelectN operations that extract results are rewritten into // more appropriate forms, and any StructMake or ArrayMake inputs are decomposed until non-struct values are @@ -1148,7 +1162,7 @@ func expandCalls(f *Func) { x := &expandState{ f: f, abi1: f.ABI1, - debug: f.pass.debug > 0, + debug: f.pass.debug, canSSAType: f.fe.CanSSA, regSize: f.Config.RegSize, sp: sp, @@ -1170,7 +1184,7 @@ func expandCalls(f *Func) { x.loRo, x.hiRo = 0, 1 } - if x.debug { + if x.debug > 1 { x.Printf("\nexpandsCalls(%s)\n", f.Name) } @@ -1210,9 +1224,8 @@ func expandCalls(f *Func) { m0 := v.MemoryArg() mem := m0 aux := f.OwnAux - pos := v.Pos.WithNotStmt() allResults := []*Value{} - if x.debug { + if x.debug > 1 { x.Printf("multiValueExit rewriting %s\n", v.LongString()) } var oldArgs []*Value @@ -1233,7 +1246,7 @@ func expandCalls(f *Func) { } continue } - mem = x.rewriteDereference(v.Block, auxBase, a, mem, auxOffset, auxSize, auxType, pos) + mem = x.rewriteDereference(v.Block, auxBase, a, mem, auxOffset, auxSize, auxType, a.Pos) } else { if a.Op == OpLoad && a.Args[0].Op == OpLocalAddr { addr := a.Args[0] // This is a self-move. // TODO(register args) do what here for registers? @@ -1257,13 +1270,13 @@ func expandCalls(f *Func) { b.SetControl(v) for _, a := range oldArgs { if a.Uses == 0 { - if x.debug { + if x.debug > 1 { x.Printf("...marking %v unused\n", a.LongString()) } - a.invalidateRecursively() + x.invalidateRecursively(a) } } - if x.debug { + if x.debug > 1 { x.Printf("...multiValueExit new result %s\n", v.LongString()) } x.indent(-3) @@ -1317,7 +1330,7 @@ func expandCalls(f *Func) { switch w.Op { case OpStructSelect, OpArraySelect, OpSelectN, OpArg: val2Preds[w] += 1 - if x.debug { + if x.debug > 1 { x.Printf("v2p[%s] = %d\n", w.LongString(), val2Preds[w]) } } @@ -1326,7 +1339,7 @@ func expandCalls(f *Func) { case OpSelectN: if _, ok := val2Preds[v]; !ok { val2Preds[v] = 0 - if x.debug { + if x.debug > 1 { x.Printf("v2p[%s] = %d\n", v.LongString(), val2Preds[v]) } } @@ -1337,7 +1350,7 @@ func expandCalls(f *Func) { } if _, ok := val2Preds[v]; !ok { val2Preds[v] = 0 - if x.debug { + if x.debug > 1 { x.Printf("v2p[%s] = %d\n", v.LongString(), val2Preds[v]) } } @@ -1451,7 +1464,7 @@ func expandCalls(f *Func) { if dupe == nil { x.commonSelectors[sk] = v } else if x.sdom.IsAncestorEq(dupe.Block, v.Block) { - if x.debug { + if x.debug > 1 { x.Printf("Duplicate, make %s copy of %s\n", v, dupe) } v.copyOf(dupe) @@ -1467,12 +1480,12 @@ func expandCalls(f *Func) { // Rewrite selectors. for i, v := range allOrdered { - if x.debug { + if x.debug > 1 { b := v.Block x.Printf("allOrdered[%d] = b%d, %s, uses=%d\n", i, b.ID, v.LongString(), v.Uses) } if v.Uses == 0 { - v.invalidateRecursively() + x.invalidateRecursively(v) continue } if v.Op == OpCopy { @@ -1583,7 +1596,7 @@ func expandCalls(f *Func) { v.SetArg(i, aa) for a.Uses == 0 { b := a.Args[0] - a.invalidateRecursively() + x.invalidateRecursively(a) a = b } } @@ -1619,7 +1632,7 @@ func expandCalls(f *Func) { // rewriteArgToMemOrRegs converts OpArg v in-place into the register version of v, // if that is appropriate. func (x *expandState) rewriteArgToMemOrRegs(v *Value) *Value { - if x.debug { + if x.debug > 1 { x.indent(3) defer x.indent(-3) x.Printf("rewriteArgToMemOrRegs(%s)\n", v.LongString()) @@ -1650,7 +1663,7 @@ func (x *expandState) rewriteArgToMemOrRegs(v *Value) *Value { default: panic(badVal("Saw unexpanded OpArg", v)) } - if x.debug { + if x.debug > 1 { x.Printf("-->%s\n", v.LongString()) } return v @@ -1660,7 +1673,7 @@ func (x *expandState) rewriteArgToMemOrRegs(v *Value) *Value { // or rewrites it into a copy of the appropriate OpArgXXX. The actual OpArgXXX is determined by combining baseArg (an OpArg) // with offset, regOffset, and t to determine which portion of it to reference (either all or a part, in memory or in registers). func (x *expandState) newArgToMemOrRegs(baseArg, toReplace *Value, offset int64, regOffset Abi1RO, t *types.Type, pos src.XPos) *Value { - if x.debug { + if x.debug > 1 { x.indent(3) defer x.indent(-3) x.Printf("newArgToMemOrRegs(base=%s; toReplace=%s; t=%s; memOff=%d; regOff=%d)\n", baseArg.String(), toReplace.LongString(), t.String(), offset, regOffset) @@ -1696,7 +1709,7 @@ func (x *expandState) newArgToMemOrRegs(baseArg, toReplace *Value, offset int64, if toReplace != nil { toReplace.copyOf(w) } - if x.debug { + if x.debug > 1 { x.Printf("-->%s\n", w.LongString()) } return w @@ -1727,7 +1740,7 @@ func (x *expandState) newArgToMemOrRegs(baseArg, toReplace *Value, offset int64, if toReplace != nil { toReplace.copyOf(w) } - if x.debug { + if x.debug > 1 { x.Printf("-->%s\n", w.LongString()) } return w diff --git a/src/cmd/compile/internal/ssa/value.go b/src/cmd/compile/internal/ssa/value.go index 630e4814b9..630143cc50 100644 --- a/src/cmd/compile/internal/ssa/value.go +++ b/src/cmd/compile/internal/ssa/value.go @@ -351,11 +351,13 @@ func (v *Value) reset(op Op) { // invalidateRecursively marks a value as invalid (unused) // and after decrementing reference counts on its Args, // also recursively invalidates any of those whose use -// count goes to zero. +// count goes to zero. It returns whether any of the +// invalidated values was marked with IsStmt. // // BEWARE of doing this *before* you've applied intended // updates to SSA. -func (v *Value) invalidateRecursively() { +func (v *Value) invalidateRecursively() bool { + lostStmt := v.Pos.IsStmt() == src.PosIsStmt if v.InCache { v.Block.Func.unCache(v) } @@ -364,7 +366,8 @@ func (v *Value) invalidateRecursively() { for _, a := range v.Args { a.Uses-- if a.Uses == 0 { - a.invalidateRecursively() + lost := a.invalidateRecursively() + lostStmt = lost || lostStmt } } @@ -375,6 +378,7 @@ func (v *Value) invalidateRecursively() { v.AuxInt = 0 v.Aux = nil + return lostStmt } // copyOf is called from rewrite rules. -- GitLab From d09e09bc615a50e9f2f1144991ebeba08a7c6f05 Mon Sep 17 00:00:00 2001 From: wdvxdr Date: Tue, 14 Sep 2021 13:37:21 +0800 Subject: [PATCH 1170/2500] cmd/compile: fixing writebarrier.go for -G=3 This is caused by some nodes didn't carry the real line number. Noder1 wraps these node with ir.ParenExpr. To fix this issue, wraps this node like what noder1 does. Change-Id: I212cad09b93b8bf1a7adfad416d229d15711918a Reviewed-on: https://go-review.googlesource.com/c/go/+/349769 Reviewed-by: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Keith Randall --- src/cmd/compile/internal/noder/expr.go | 5 +++-- src/cmd/compile/internal/noder/noder.go | 8 ++++++-- src/cmd/compile/internal/noder/stmt.go | 2 +- src/cmd/compile/internal/noder/transform.go | 4 ++++ test/run.go | 2 -- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 3e1960f7a4..9cd9545b75 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -390,9 +390,10 @@ func (g *irgen) compLit(typ types2.Type, lit *syntax.CompositeLit) ir.Node { } else { key = g.expr(elem.Key) } - exprs[i] = ir.NewKeyExpr(g.pos(elem), key, g.expr(elem.Value)) + value := wrapname(g.pos(elem.Value), g.expr(elem.Value)) + exprs[i] = ir.NewKeyExpr(g.pos(elem), key, value) default: - exprs[i] = g.expr(elem) + exprs[i] = wrapname(g.pos(elem), g.expr(elem)) } } diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index 2f18a2f231..7c14fcf041 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -1537,7 +1537,7 @@ func (p *noder) mkname(name *syntax.Name) ir.Node { return mkname(p.name(name)) } -func (p *noder) wrapname(n syntax.Node, x ir.Node) ir.Node { +func wrapname(pos src.XPos, x ir.Node) ir.Node { // These nodes do not carry line numbers. // Introduce a wrapper node to give them the correct line. switch x.Op() { @@ -1547,13 +1547,17 @@ func (p *noder) wrapname(n syntax.Node, x ir.Node) ir.Node { } fallthrough case ir.ONAME, ir.ONONAME, ir.OPACK: - p := ir.NewParenExpr(p.pos(n), x) + p := ir.NewParenExpr(pos, x) p.SetImplicit(true) return p } return x } +func (p *noder) wrapname(n syntax.Node, x ir.Node) ir.Node { + return wrapname(p.pos(n), x) +} + func (p *noder) setlineno(n syntax.Node) { if n != nil { base.Pos = p.pos(n) diff --git a/src/cmd/compile/internal/noder/stmt.go b/src/cmd/compile/internal/noder/stmt.go index 1c366296fc..7f608bb91f 100644 --- a/src/cmd/compile/internal/noder/stmt.go +++ b/src/cmd/compile/internal/noder/stmt.go @@ -37,7 +37,7 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { case *syntax.BlockStmt: return ir.NewBlockStmt(g.pos(stmt), g.blockStmt(stmt)) case *syntax.ExprStmt: - return g.expr(stmt.X) + return wrapname(g.pos(stmt.X), g.expr(stmt.X)) case *syntax.SendStmt: n := ir.NewSendStmt(g.pos(stmt), g.expr(stmt.Chan), g.expr(stmt.Value)) if n.Chan.Type().HasTParam() || n.Value.Type().HasTParam() { diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index 91374054b6..a117e310ea 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -404,6 +404,10 @@ func assignconvfn(n ir.Node, t *types.Type) ir.Node { return n } + if n.Op() == ir.OPAREN { + n = n.(*ir.ParenExpr).X + } + if types.IdenticalStrict(n.Type(), t) { return n } diff --git a/test/run.go b/test/run.go index 7317e8019e..0c9c8c5cb8 100644 --- a/test/run.go +++ b/test/run.go @@ -2184,8 +2184,6 @@ var types2Failures32Bit = setOf( ) var g3Failures = setOf( - "writebarrier.go", // correct diagnostics, but different lines (probably irgen's fault) - "typeparam/nested.go", // -G=3 doesn't support function-local types with generics ) -- GitLab From 5402b4376c0c51a31ea9c5ccf16b449a6ab3e79f Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 16 Sep 2021 15:00:47 -0700 Subject: [PATCH 1171/2500] spec: fix incorrect type in a shift example Thanks to @bodar (Github) for finding this. Fixes #48422. Change-Id: I031c3d82a02db1d204e2b86b494d89784d37f073 Reviewed-on: https://go-review.googlesource.com/c/go/+/350409 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Matthew Dempsky --- doc/go_spec.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index 6cc0b796b9..c8051f58af 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,6 +1,6 @@ @@ -3614,7 +3614,7 @@ var i = 1<<s // 1 has type int var j int32 = 1<<s // 1 has type int32; j == 0 var k = uint64(1<<s) // 1 has type uint64; k == 1<<33 var m int = 1.0<<s // 1.0 has type int; m == 1<<33 -var n = 1.0<<s == j // 1.0 has type int; n == true +var n = 1.0<<s == j // 1.0 has type int32; n == true var o = 1<<s == 2<<s // 1 and 2 have type int; o == false var p = 1<<s == 1<<33 // 1 has type int; p == true var u = 1.0<<s // illegal: 1.0 has type float64, cannot shift -- GitLab From e09dcc211a338450d3f680fe39abc13b79ddbb29 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 16 Sep 2021 15:09:31 -0700 Subject: [PATCH 1172/2500] go/types, types2: add an additional shift test case The extra test just confirms that the type-checker internally agrees with the spec with the (otherwise invisible) type given to an untyped constant in a specific shift expression. For #48422. Change-Id: I6d98045f90bd20b0cc0a96a147bec9701039cb07 Reviewed-on: https://go-review.googlesource.com/c/go/+/350410 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/types2/api_test.go | 1 + src/go/types/api_test.go | 1 + 2 files changed, 2 insertions(+) diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index 5a20738631..cd5a61332a 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -145,6 +145,7 @@ func TestValuesInfo(t *testing.T) { {`package f7b; var _ = -1e-2000i`, `-1e-2000i`, `complex128`, `(0 + 0i)`}, {`package g0; const (a = len([iota]int{}); b; c); const _ = c`, `c`, `int`, `2`}, // issue #22341 + {`package g1; var(j int32; s int; n = 1.0< Date: Sat, 28 Aug 2021 16:06:43 -0700 Subject: [PATCH 1173/2500] testing: skip panics when picking the line number for decoration Fixes #31154 Change-Id: I4cfd98b5e79f1abdc93044fb66855ac2cc0a9a49 Reviewed-on: https://go-review.googlesource.com/c/go/+/345909 Run-TryBot: Caleb Spare TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Carlos Amedee --- src/testing/helper_test.go | 35 +++------------------------------ src/testing/helperfuncs_test.go | 32 ++++++++++++++++++++++++++++++ src/testing/testing.go | 3 +++ 3 files changed, 38 insertions(+), 32 deletions(-) diff --git a/src/testing/helper_test.go b/src/testing/helper_test.go index b27fd62ee8..6175410f18 100644 --- a/src/testing/helper_test.go +++ b/src/testing/helper_test.go @@ -33,6 +33,9 @@ helperfuncs_test.go:45: 5 helperfuncs_test.go:21: 6 helperfuncs_test.go:44: 7 helperfuncs_test.go:56: 8 +--- FAIL: Test/sub2 (?s) +helperfuncs_test.go:71: 11 +helperfuncs_test.go:75: recover 12 helperfuncs_test.go:64: 9 helperfuncs_test.go:60: 10 ` @@ -71,38 +74,6 @@ func TestTBHelperParallel(t *T) { } } -func TestTBHelperLineNumer(t *T) { - var buf bytes.Buffer - ctx := newTestContext(1, newMatcher(regexp.MatchString, "", "")) - t1 := &T{ - common: common{ - signal: make(chan bool), - w: &buf, - }, - context: ctx, - } - t1.Run("Test", func(t *T) { - helperA := func(t *T) { - t.Helper() - t.Run("subtest", func(t *T) { - t.Helper() - t.Fatal("fatal error message") - }) - } - helperA(t) - }) - - want := "helper_test.go:92: fatal error message" - got := "" - lines := strings.Split(strings.TrimSpace(buf.String()), "\n") - if len(lines) > 0 { - got = strings.TrimSpace(lines[len(lines)-1]) - } - if got != want { - t.Errorf("got output:\n\n%v\nwant:\n\n%v", got, want) - } -} - type noopWriter int func (nw *noopWriter) Write(b []byte) (int, error) { return len(b), nil } diff --git a/src/testing/helperfuncs_test.go b/src/testing/helperfuncs_test.go index df0476ed73..272b33c0e5 100644 --- a/src/testing/helperfuncs_test.go +++ b/src/testing/helperfuncs_test.go @@ -65,6 +65,14 @@ func testHelper(t *T) { t.Helper() t.Error("9") }) + + // Check that helper-ness propagates up through subtests + // to helpers above. See https://golang.org/issue/44887. + helperSubCallingHelper(t, "11") + + // Check that helper-ness propagates up through panic/recover. + // See https://golang.org/issue/31154. + recoverHelper(t, "12") } func parallelTestHelper(t *T) { @@ -78,3 +86,27 @@ func parallelTestHelper(t *T) { } wg.Wait() } + +func helperSubCallingHelper(t *T, msg string) { + t.Helper() + t.Run("sub2", func(t *T) { + t.Helper() + t.Fatal(msg) + }) +} + +func recoverHelper(t *T, msg string) { + t.Helper() + defer func() { + t.Helper() + if err := recover(); err != nil { + t.Errorf("recover %s", err) + } + }() + doPanic(t, msg) +} + +func doPanic(t *T, msg string) { + t.Helper() + panic(msg) +} diff --git a/src/testing/testing.go b/src/testing/testing.go index a19238d31e..2239e01e22 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -483,6 +483,9 @@ func (c *common) frameSkip(skip int) runtime.Frame { var firstFrame, prevFrame, frame runtime.Frame for more := true; more; prevFrame = frame { frame, more = frames.Next() + if frame.Function == "runtime.gopanic" { + continue + } if frame.Function == c.cleanupName { frames = runtime.CallersFrames(c.cleanupPc) continue -- GitLab From 265b59aefdd383fc60fcfc7a2838018b16d1d29a Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 15 Sep 2021 16:11:37 -0700 Subject: [PATCH 1174/2500] cmd/cgo: for godefs, don't let field prefix removal cause duplicates Fixes #48396 Change-Id: Idd7cb66536ef513806c472d394a929bc271fc26b Reviewed-on: https://go-review.googlesource.com/c/go/+/350159 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Tobias Klauser Reviewed-by: Matt Layher --- misc/cgo/testgodefs/testdata/issue48396.go | 18 ++++++++++++++++ misc/cgo/testgodefs/testdata/main.go | 3 +++ misc/cgo/testgodefs/testgodefs_test.go | 1 + src/cmd/cgo/gcc.go | 25 ++++++++++++++++++++++ 4 files changed, 47 insertions(+) create mode 100644 misc/cgo/testgodefs/testdata/issue48396.go diff --git a/misc/cgo/testgodefs/testdata/issue48396.go b/misc/cgo/testgodefs/testdata/issue48396.go new file mode 100644 index 0000000000..d4c192403f --- /dev/null +++ b/misc/cgo/testgodefs/testdata/issue48396.go @@ -0,0 +1,18 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// +build ignore + +package main + +/* +// from +struct issue48396 { + int fd; + int bpf_fd; +}; +*/ +import "C" + +type Issue48396 C.struct_issue48396 diff --git a/misc/cgo/testgodefs/testdata/main.go b/misc/cgo/testgodefs/testdata/main.go index 4a3f6a701c..5c670f3d32 100644 --- a/misc/cgo/testgodefs/testdata/main.go +++ b/misc/cgo/testgodefs/testdata/main.go @@ -28,6 +28,9 @@ var v7 = S{} // Test that #define'd type is fully defined var _ = issue38649{X: 0} +// Test that prefixes do not cause duplicate field names. +var _ = Issue48396{Fd: 1, Bpf_fd: 2} + func main() { pass := true diff --git a/misc/cgo/testgodefs/testgodefs_test.go b/misc/cgo/testgodefs/testgodefs_test.go index aae3404360..7628ffc595 100644 --- a/misc/cgo/testgodefs/testgodefs_test.go +++ b/misc/cgo/testgodefs/testgodefs_test.go @@ -25,6 +25,7 @@ var filePrefixes = []string{ "issue37621", "issue38649", "issue39534", + "issue48396", } func TestGoDefs(t *testing.T) { diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index 92adb1ed9c..6b3112b41e 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -3030,6 +3030,31 @@ func upper(s string) string { // so that all fields are exported. func godefsFields(fld []*ast.Field) { prefix := fieldPrefix(fld) + + // Issue 48396: check for duplicate field names. + if prefix != "" { + names := make(map[string]bool) + fldLoop: + for _, f := range fld { + for _, n := range f.Names { + name := n.Name + if name == "_" { + continue + } + if name != prefix { + name = strings.TrimPrefix(n.Name, prefix) + } + name = upper(name) + if names[name] { + // Field name conflict: don't remove prefix. + prefix = "" + break fldLoop + } + names[name] = true + } + } + } + npad := 0 for _, f := range fld { for _, n := range f.Names { -- GitLab From af9da137a98f897c56d0bfb8e18b177b9ff5af4b Mon Sep 17 00:00:00 2001 From: ian woolf Date: Fri, 20 Aug 2021 10:16:20 +0800 Subject: [PATCH 1175/2500] A+C: update name to real name and add to AUTHORS Change-Id: I857b0e9aa7d933879239ef7ebc0d1a2812a74c25 Reviewed-on: https://go-review.googlesource.com/c/go/+/343533 Reviewed-by: Ian Lance Taylor Trust: Carlos Amedee --- AUTHORS | 1 + CONTRIBUTORS | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 95d3158d20..8d8d83605e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1479,6 +1479,7 @@ Zheng Dayu Zhongtao Chen Zhou Peng Ziad Hatahet +Zizhao Zhang Zorion Arrizabalaga Максим Федосеев Роман Хавроненко diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 1984d44c53..74d4687373 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -1109,7 +1109,6 @@ Ian Lance Taylor Ian Leue Ian Mckay Ian Tay -Ian Woolf Ian Zapolsky Ibrahim AshShohail Icarus Sparry @@ -2749,6 +2748,7 @@ Zhongwei Yao Zhou Peng Ziad Hatahet Ziheng Liu +Zizhao Zhang Zorion Arrizabalaga Zvonimir Pavlinovic Zyad A. Ali -- GitLab From 8d2a9c32a28838978f5d4e477bbd6db4144005d3 Mon Sep 17 00:00:00 2001 From: Dan Kortschak Date: Sun, 8 Aug 2021 19:44:30 +0930 Subject: [PATCH 1176/2500] all: remove incorrectly repeated words in comments Change-Id: Icbf36e1cd8311b40d18177464e7c41dd8cb1c65b Reviewed-on: https://go-review.googlesource.com/c/go/+/340350 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Carlos Amedee --- src/net/lookup.go | 16 ++++++++-------- src/runtime/mpagealloc.go | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/net/lookup.go b/src/net/lookup.go index 02beaca7e1..3c0153028c 100644 --- a/src/net/lookup.go +++ b/src/net/lookup.go @@ -442,7 +442,7 @@ func (r *Resolver) LookupCNAME(ctx context.Context, host string) (string, error) // The returned service names are validated to be properly // formatted presentation-format domain names. If the response contains // invalid names, those records are filtered out and an error -// will be returned alongside the the remaining results, if any. +// will be returned alongside the remaining results, if any. func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) { return DefaultResolver.LookupSRV(context.Background(), service, proto, name) } @@ -460,7 +460,7 @@ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err err // The returned service names are validated to be properly // formatted presentation-format domain names. If the response contains // invalid names, those records are filtered out and an error -// will be returned alongside the the remaining results, if any. +// will be returned alongside the remaining results, if any. func (r *Resolver) LookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) { cname, addrs, err := r.lookupSRV(ctx, service, proto, name) if err != nil { @@ -490,7 +490,7 @@ func (r *Resolver) LookupSRV(ctx context.Context, service, proto, name string) ( // The returned mail server names are validated to be properly // formatted presentation-format domain names. If the response contains // invalid names, those records are filtered out and an error -// will be returned alongside the the remaining results, if any. +// will be returned alongside the remaining results, if any. // // LookupMX uses context.Background internally; to specify the context, use // Resolver.LookupMX. @@ -503,7 +503,7 @@ func LookupMX(name string) ([]*MX, error) { // The returned mail server names are validated to be properly // formatted presentation-format domain names. If the response contains // invalid names, those records are filtered out and an error -// will be returned alongside the the remaining results, if any. +// will be returned alongside the remaining results, if any. func (r *Resolver) LookupMX(ctx context.Context, name string) ([]*MX, error) { records, err := r.lookupMX(ctx, name) if err != nil { @@ -532,7 +532,7 @@ func (r *Resolver) LookupMX(ctx context.Context, name string) ([]*MX, error) { // The returned name server names are validated to be properly // formatted presentation-format domain names. If the response contains // invalid names, those records are filtered out and an error -// will be returned alongside the the remaining results, if any. +// will be returned alongside the remaining results, if any. // // LookupNS uses context.Background internally; to specify the context, use // Resolver.LookupNS. @@ -545,7 +545,7 @@ func LookupNS(name string) ([]*NS, error) { // The returned name server names are validated to be properly // formatted presentation-format domain names. If the response contains // invalid names, those records are filtered out and an error -// will be returned alongside the the remaining results, if any. +// will be returned alongside the remaining results, if any. func (r *Resolver) LookupNS(ctx context.Context, name string) ([]*NS, error) { records, err := r.lookupNS(ctx, name) if err != nil { @@ -585,7 +585,7 @@ func (r *Resolver) LookupTXT(ctx context.Context, name string) ([]string, error) // // The returned names are validated to be properly formatted presentation-format // domain names. If the response contains invalid names, those records are filtered -// out and an error will be returned alongside the the remaining results, if any. +// out and an error will be returned alongside the remaining results, if any. // // When using the host C library resolver, at most one result will be // returned. To bypass the host resolver, use a custom Resolver. @@ -601,7 +601,7 @@ func LookupAddr(addr string) (names []string, err error) { // // The returned names are validated to be properly formatted presentation-format // domain names. If the response contains invalid names, those records are filtered -// out and an error will be returned alongside the the remaining results, if any. +// out and an error will be returned alongside the remaining results, if any. func (r *Resolver) LookupAddr(ctx context.Context, addr string) ([]string, error) { names, err := r.lookupAddr(ctx, addr) if err != nil { diff --git a/src/runtime/mpagealloc.go b/src/runtime/mpagealloc.go index 071f1fc274..862882cd82 100644 --- a/src/runtime/mpagealloc.go +++ b/src/runtime/mpagealloc.go @@ -155,7 +155,7 @@ func addrsToSummaryRange(level int, base, limit uintptr) (lo int, hi int) { // upper-bound. Note that the exclusive upper bound may be within a // summary at this level, meaning if we just do the obvious computation // hi will end up being an inclusive upper bound. Unfortunately, just - // adding 1 to that is too broad since we might be on the very edge of + // adding 1 to that is too broad since we might be on the very edge // of a summary's max page count boundary for this level // (1 << levelLogPages[level]). So, make limit an inclusive upper bound // then shift, then add 1, so we get an exclusive upper bound at the end. -- GitLab From 14e812bfc575400a02e9e7536344a3f78a6cba08 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Thu, 16 Sep 2021 16:11:19 -0600 Subject: [PATCH 1177/2500] syscall: do not use handle lists on windows when NoInheritHandles is true If NoInheritHandles is passed, then we shouldn't attempt to do anything with handle lists. Otherwise CreateProcess fails with invalid param, because it's being told both to not inherit handles and to inherit certain handles. This commit fixes that by using the same logic for handle lists as it does for enabling or disabling handle inheritance. It also adds a test to make sure this doesn't regress again. Fixes #48040 Change-Id: I507261baeec263091738ab90157a991d917dc92f Reviewed-on: https://go-review.googlesource.com/c/go/+/350411 Reviewed-by: Patrik Nyblom Trust: Jason A. Donenfeld Run-TryBot: Jason A. Donenfeld TryBot-Result: Go Bot --- src/os/exec/exec_windows_test.go | 14 ++++++++++++++ src/syscall/exec_windows.go | 8 +++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/os/exec/exec_windows_test.go b/src/os/exec/exec_windows_test.go index fbccffec0e..bd4dfb31da 100644 --- a/src/os/exec/exec_windows_test.go +++ b/src/os/exec/exec_windows_test.go @@ -10,6 +10,7 @@ package exec_test import ( "io" "os" + "os/exec" "strconv" "syscall" "testing" @@ -41,3 +42,16 @@ func TestPipePassing(t *testing.T) { t.Error(err) } } + +func TestNoInheritHandles(t *testing.T) { + cmd := exec.Command("cmd", "/c exit 88") + cmd.SysProcAttr = &syscall.SysProcAttr{NoInheritHandles: true} + err := cmd.Run() + exitError, ok := err.(*exec.ExitError) + if !ok { + t.Fatalf("got error %v; want ExitError", err) + } + if exitError.ExitCode() != 88 { + t.Fatalf("got exit code %d; want 88", exitError.ExitCode()) + } +} diff --git a/src/syscall/exec_windows.go b/src/syscall/exec_windows.go index 18d15028c3..9d10d6a512 100644 --- a/src/syscall/exec_windows.go +++ b/src/syscall/exec_windows.go @@ -390,8 +390,10 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle } fd = fd[:j] + willInheritHandles := len(fd) > 0 && !sys.NoInheritHandles + // Do not accidentally inherit more than these handles. - if len(fd) > 0 { + if willInheritHandles { err = updateProcThreadAttribute(si.ProcThreadAttributeList, 0, _PROC_THREAD_ATTRIBUTE_HANDLE_LIST, unsafe.Pointer(&fd[0]), uintptr(len(fd))*unsafe.Sizeof(fd[0]), nil, nil) if err != nil { return 0, 0, err @@ -401,9 +403,9 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle pi := new(ProcessInformation) flags := sys.CreationFlags | CREATE_UNICODE_ENVIRONMENT | _EXTENDED_STARTUPINFO_PRESENT if sys.Token != 0 { - err = CreateProcessAsUser(sys.Token, argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, len(fd) > 0 && !sys.NoInheritHandles, flags, createEnvBlock(attr.Env), dirp, &si.StartupInfo, pi) + err = CreateProcessAsUser(sys.Token, argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, willInheritHandles, flags, createEnvBlock(attr.Env), dirp, &si.StartupInfo, pi) } else { - err = CreateProcess(argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, len(fd) > 0 && !sys.NoInheritHandles, flags, createEnvBlock(attr.Env), dirp, &si.StartupInfo, pi) + err = CreateProcess(argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, willInheritHandles, flags, createEnvBlock(attr.Env), dirp, &si.StartupInfo, pi) } if err != nil { return 0, 0, err -- GitLab From 6602c86a38ff0d8889257e908489162de38ebbd8 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Tue, 14 Sep 2021 02:21:22 +1000 Subject: [PATCH 1178/2500] cmd/internal/obj/riscv: improve instruction validation Ensure that rs2 is none for various instruction encodings. Fix a couple of cases where it should have been but is not. Change-Id: I9f8211a0257e49643dbbc89e158e048050ebe6f0 Reviewed-on: https://go-review.googlesource.com/c/go/+/349649 Trust: Joel Sing Reviewed-by: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot --- src/cmd/internal/obj/riscv/obj.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index 62d44d8a3f..f0ea21de97 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -1003,6 +1003,7 @@ func validateII(ctxt *obj.Link, ins *instruction) { wantImmI(ctxt, ins.as, ins.imm, 12) wantIntReg(ctxt, ins.as, "rd", ins.rd) wantIntReg(ctxt, ins.as, "rs1", ins.rs1) + wantNoneReg(ctxt, ins.as, "rs2", ins.rs2) wantNoneReg(ctxt, ins.as, "rs3", ins.rs3) } @@ -1010,6 +1011,7 @@ func validateIF(ctxt *obj.Link, ins *instruction) { wantImmI(ctxt, ins.as, ins.imm, 12) wantFloatReg(ctxt, ins.as, "rd", ins.rd) wantIntReg(ctxt, ins.as, "rs1", ins.rs1) + wantNoneReg(ctxt, ins.as, "rs2", ins.rs2) wantNoneReg(ctxt, ins.as, "rs3", ins.rs3) } @@ -1017,6 +1019,7 @@ func validateSI(ctxt *obj.Link, ins *instruction) { wantImmI(ctxt, ins.as, ins.imm, 12) wantIntReg(ctxt, ins.as, "rd", ins.rd) wantIntReg(ctxt, ins.as, "rs1", ins.rs1) + wantNoneReg(ctxt, ins.as, "rs2", ins.rs2) wantNoneReg(ctxt, ins.as, "rs3", ins.rs3) } @@ -1024,6 +1027,7 @@ func validateSF(ctxt *obj.Link, ins *instruction) { wantImmI(ctxt, ins.as, ins.imm, 12) wantIntReg(ctxt, ins.as, "rd", ins.rd) wantFloatReg(ctxt, ins.as, "rs1", ins.rs1) + wantNoneReg(ctxt, ins.as, "rs2", ins.rs2) wantNoneReg(ctxt, ins.as, "rs3", ins.rs3) } @@ -1567,7 +1571,7 @@ func instructionForProg(p *obj.Prog) *instruction { func instructionsForOpImmediate(p *obj.Prog, as obj.As, rs int16) []*instruction { // $imm, REG, TO ins := instructionForProg(p) - ins.as, ins.rs1 = as, uint32(rs) + ins.as, ins.rs1, ins.rs2 = as, uint32(rs), obj.REG_NONE low, high, err := Split32BitImmediate(ins.imm) if err != nil { @@ -1990,7 +1994,7 @@ func instructionsForProg(p *obj.Prog) []*instruction { case ASEQZ: // SEQZ rs, rd -> SLTIU $1, rs, rd ins.as = ASLTIU - ins.rs1 = uint32(p.From.Reg) + ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE ins.imm = 1 case ASNEZ: -- GitLab From 6d02ce85840fb7a1a9239d02e02710a008b1657a Mon Sep 17 00:00:00 2001 From: Alessandro Arzilli Date: Fri, 17 Sep 2021 13:48:39 +0200 Subject: [PATCH 1179/2500] runtime: fix prettyprinting of parametric types in gdb golang.org/cl/344929 broke the minimal functionality that the python pretty printer for GDB had, this change restores it to its status prior to that CL. Change-Id: I4c7141d4ff726d224a074ecc533d0f896fc0052c Reviewed-on: https://go-review.googlesource.com/c/go/+/350529 TryBot-Result: Go Bot Reviewed-by: David Chase Trust: Than McIntosh --- src/runtime/runtime-gdb.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/runtime/runtime-gdb.py b/src/runtime/runtime-gdb.py index 8d96dfb609..5bb605cc37 100644 --- a/src/runtime/runtime-gdb.py +++ b/src/runtime/runtime-gdb.py @@ -219,6 +219,9 @@ class ChanTypePrinter: yield ('[{0}]'.format(i), (ptr + j).dereference()) +def paramtypematch(t, pattern): + return t.code == gdb.TYPE_CODE_TYPEDEF and str(t).startswith(".param") and pattern.match(str(t.target())) + # # Register all the *Printer classes above. # @@ -228,6 +231,8 @@ def makematcher(klass): try: if klass.pattern.match(str(val.type)): return klass(val) + elif paramtypematch(val.type, klass.pattern): + return klass(val.cast(val.type.target())) except Exception: pass return matcher @@ -387,7 +392,7 @@ class GoLenFunc(gdb.Function): def invoke(self, obj): typename = str(obj.type) for klass, fld in self.how: - if klass.pattern.match(typename): + if klass.pattern.match(typename) or paramtypematch(obj.type, klass.pattern): return obj[fld] @@ -402,7 +407,7 @@ class GoCapFunc(gdb.Function): def invoke(self, obj): typename = str(obj.type) for klass, fld in self.how: - if klass.pattern.match(typename): + if klass.pattern.match(typename) or paramtypematch(obj.type, klass.pattern): return obj[fld] -- GitLab From 70493b3eb06d10217d9aa346ffff0b4c4f2cc72b Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Fri, 16 Jul 2021 02:56:08 +1000 Subject: [PATCH 1180/2500] runtime/cgo: save and restore X3 (aka GP) for crosscall1 on riscv64 The C code that is calling crosscall1 may depend on the GP register, which Go code will currently clobber. Save and restore both X3 (aka GP) and X4 (aka TP) in this code path (note that the Go code does not currently clobber X4, however there is minimal downside to saving and restoring it here, which then also matches crosscall2). Updates #47100 Change-Id: Icbb706d7889d5dc59de3efb2b510fa6ea2069496 Reviewed-on: https://go-review.googlesource.com/c/go/+/334870 Trust: Joel Sing Trust: Meng Zhuo Reviewed-by: Meng Zhuo Reviewed-by: Ian Lance Taylor Run-TryBot: Meng Zhuo --- src/runtime/cgo/gcc_riscv64.S | 108 ++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 52 deletions(-) diff --git a/src/runtime/cgo/gcc_riscv64.S b/src/runtime/cgo/gcc_riscv64.S index f429dc64ee..fdc77496d9 100644 --- a/src/runtime/cgo/gcc_riscv64.S +++ b/src/runtime/cgo/gcc_riscv64.S @@ -8,36 +8,38 @@ * Calling into the gc tool chain, where all registers are caller save. * Called from standard RISCV ELF psABI, where x8-x9, x18-x27, f8-f9 and * f18-f27 are callee-save, so they must be saved explicitly, along with - * x1 (LR). + * x1 (LR), x3 (GP) and x4 (TP). */ .globl crosscall1 crosscall1: - sd x1, -200(sp) - addi sp, sp, -200 - sd x8, 8(sp) - sd x9, 16(sp) - sd x18, 24(sp) - sd x19, 32(sp) - sd x20, 40(sp) - sd x21, 48(sp) - sd x22, 56(sp) - sd x23, 64(sp) - sd x24, 72(sp) - sd x25, 80(sp) - sd x26, 88(sp) - sd x27, 96(sp) - fsd f8, 104(sp) - fsd f9, 112(sp) - fsd f18, 120(sp) - fsd f19, 128(sp) - fsd f20, 136(sp) - fsd f21, 144(sp) - fsd f22, 152(sp) - fsd f23, 160(sp) - fsd f24, 168(sp) - fsd f25, 176(sp) - fsd f26, 184(sp) - fsd f27, 192(sp) + sd x1, -216(sp) + addi sp, sp, -216 + sd x3, 8(sp) + sd x4, 16(sp) + sd x8, 24(sp) + sd x9, 32(sp) + sd x18, 40(sp) + sd x19, 48(sp) + sd x20, 56(sp) + sd x21, 64(sp) + sd x22, 72(sp) + sd x23, 80(sp) + sd x24, 88(sp) + sd x25, 96(sp) + sd x26, 104(sp) + sd x27, 112(sp) + fsd f8, 120(sp) + fsd f9, 128(sp) + fsd f18, 136(sp) + fsd f19, 144(sp) + fsd f20, 152(sp) + fsd f21, 160(sp) + fsd f22, 168(sp) + fsd f23, 176(sp) + fsd f24, 184(sp) + fsd f25, 192(sp) + fsd f26, 200(sp) + fsd f27, 208(sp) // a0 = *fn, a1 = *setg_gcc, a2 = *g mv s1, a0 @@ -47,31 +49,33 @@ crosscall1: jalr ra, s1 // call fn ld x1, 0(sp) - ld x8, 8(sp) - ld x9, 16(sp) - ld x18, 24(sp) - ld x19, 32(sp) - ld x20, 40(sp) - ld x21, 48(sp) - ld x22, 56(sp) - ld x23, 64(sp) - ld x24, 72(sp) - ld x25, 80(sp) - ld x26, 88(sp) - ld x27, 96(sp) - fld f8, 104(sp) - fld f9, 112(sp) - fld f18, 120(sp) - fld f19, 128(sp) - fld f20, 136(sp) - fld f21, 144(sp) - fld f22, 152(sp) - fld f23, 160(sp) - fld f24, 168(sp) - fld f25, 176(sp) - fld f26, 184(sp) - fld f27, 192(sp) - addi sp, sp, 200 + ld x3, 8(sp) + ld x4, 16(sp) + ld x8, 24(sp) + ld x9, 32(sp) + ld x18, 40(sp) + ld x19, 48(sp) + ld x20, 56(sp) + ld x21, 64(sp) + ld x22, 72(sp) + ld x23, 80(sp) + ld x24, 88(sp) + ld x25, 96(sp) + ld x26, 104(sp) + ld x27, 112(sp) + fld f8, 120(sp) + fld f9, 128(sp) + fld f18, 136(sp) + fld f19, 144(sp) + fld f20, 152(sp) + fld f21, 160(sp) + fld f22, 168(sp) + fld f23, 176(sp) + fld f24, 184(sp) + fld f25, 192(sp) + fld f26, 200(sp) + fld f27, 208(sp) + addi sp, sp, 216 jr ra -- GitLab From 7f36ef0aff702f2598390d0349f9c9632942d40b Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 17 Sep 2021 11:12:31 -0700 Subject: [PATCH 1181/2500] cmd/compile/internal/noder: hide TestUnifiedCompare behind -cmp flag This test is fragile and is starting to impede others' work. This CL disables it until I have time to either find a solution for the issues or decide to just delete the test altogether. Change-Id: Icefabb6d3fbedec5d16536de78be4ca20d63133c Reviewed-on: https://go-review.googlesource.com/c/go/+/350729 Trust: Matthew Dempsky Trust: Dan Scales Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/unified_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/cmd/compile/internal/noder/unified_test.go b/src/cmd/compile/internal/noder/unified_test.go index 96cc66f775..d7334df282 100644 --- a/src/cmd/compile/internal/noder/unified_test.go +++ b/src/cmd/compile/internal/noder/unified_test.go @@ -16,6 +16,7 @@ import ( ) var ( + flagCmp = flag.Bool("cmp", false, "enable TestUnifiedCompare") flagPkgs = flag.String("pkgs", "std", "list of packages to compare (ignored in -short mode)") flagAll = flag.Bool("all", false, "enable testing of all GOOS/GOARCH targets") flagParallel = flag.Bool("parallel", false, "test GOOS/GOARCH targets in parallel") @@ -37,6 +38,12 @@ var ( // command's -run flag for subtest matching is recommended for less // powerful machines. func TestUnifiedCompare(t *testing.T) { + // TODO(mdempsky): Either re-enable or delete. Disabled for now to + // avoid impeding others' forward progress. + if !*flagCmp { + t.Skip("skipping TestUnifiedCompare (use -cmp to enable)") + } + targets, err := exec.Command("go", "tool", "dist", "list").Output() if err != nil { t.Fatal(err) -- GitLab From 323c6f74d35ec29baac2a1aba4270f89b022815a Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 9 Sep 2021 14:49:41 -0700 Subject: [PATCH 1182/2500] log: don't format if writing to io.Discard Fixes #47164 Change-Id: Ied03842360be4c86f1d9ead816f12c057a1f8dad Reviewed-on: https://go-review.googlesource.com/c/go/+/348741 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Emmanuel Odeke Reviewed-by: Valentin Deleplace --- src/log/log.go | 53 +++++++++++++++++++++++++++++++++++---------- src/log/log_test.go | 14 +++++++++++- 2 files changed, 55 insertions(+), 12 deletions(-) diff --git a/src/log/log.go b/src/log/log.go index b77af29032..3172384718 100644 --- a/src/log/log.go +++ b/src/log/log.go @@ -20,6 +20,7 @@ import ( "os" "runtime" "sync" + "sync/atomic" "time" ) @@ -50,11 +51,12 @@ const ( // the Writer's Write method. A Logger can be used simultaneously from // multiple goroutines; it guarantees to serialize access to the Writer. type Logger struct { - mu sync.Mutex // ensures atomic writes; protects the following fields - prefix string // prefix on each line to identify the logger (but see Lmsgprefix) - flag int // properties - out io.Writer // destination for output - buf []byte // for accumulating text to write + mu sync.Mutex // ensures atomic writes; protects the following fields + prefix string // prefix on each line to identify the logger (but see Lmsgprefix) + flag int // properties + out io.Writer // destination for output + buf []byte // for accumulating text to write + isDiscard int32 // atomic boolean: whether out == io.Discard } // New creates a new Logger. The out variable sets the @@ -63,7 +65,11 @@ type Logger struct { // after the log header if the Lmsgprefix flag is provided. // The flag argument defines the logging properties. func New(out io.Writer, prefix string, flag int) *Logger { - return &Logger{out: out, prefix: prefix, flag: flag} + l := &Logger{out: out, prefix: prefix, flag: flag} + if out == io.Discard { + l.isDiscard = 1 + } + return l } // SetOutput sets the output destination for the logger. @@ -71,6 +77,11 @@ func (l *Logger) SetOutput(w io.Writer) { l.mu.Lock() defer l.mu.Unlock() l.out = w + isDiscard := int32(0) + if w == io.Discard { + isDiscard = 1 + } + atomic.StoreInt32(&l.isDiscard, isDiscard) } var std = New(os.Stderr, "", LstdFlags) @@ -188,16 +199,29 @@ func (l *Logger) Output(calldepth int, s string) error { // Printf calls l.Output to print to the logger. // Arguments are handled in the manner of fmt.Printf. func (l *Logger) Printf(format string, v ...interface{}) { + if atomic.LoadInt32(&l.isDiscard) != 0 { + return + } l.Output(2, fmt.Sprintf(format, v...)) } // Print calls l.Output to print to the logger. // Arguments are handled in the manner of fmt.Print. -func (l *Logger) Print(v ...interface{}) { l.Output(2, fmt.Sprint(v...)) } +func (l *Logger) Print(v ...interface{}) { + if atomic.LoadInt32(&l.isDiscard) != 0 { + return + } + l.Output(2, fmt.Sprint(v...)) +} // Println calls l.Output to print to the logger. // Arguments are handled in the manner of fmt.Println. -func (l *Logger) Println(v ...interface{}) { l.Output(2, fmt.Sprintln(v...)) } +func (l *Logger) Println(v ...interface{}) { + if atomic.LoadInt32(&l.isDiscard) != 0 { + return + } + l.Output(2, fmt.Sprintln(v...)) +} // Fatal is equivalent to l.Print() followed by a call to os.Exit(1). func (l *Logger) Fatal(v ...interface{}) { @@ -277,9 +301,7 @@ func (l *Logger) Writer() io.Writer { // SetOutput sets the output destination for the standard logger. func SetOutput(w io.Writer) { - std.mu.Lock() - defer std.mu.Unlock() - std.out = w + std.SetOutput(w) } // Flags returns the output flags for the standard logger. @@ -314,18 +336,27 @@ func Writer() io.Writer { // Print calls Output to print to the standard logger. // Arguments are handled in the manner of fmt.Print. func Print(v ...interface{}) { + if atomic.LoadInt32(&std.isDiscard) != 0 { + return + } std.Output(2, fmt.Sprint(v...)) } // Printf calls Output to print to the standard logger. // Arguments are handled in the manner of fmt.Printf. func Printf(format string, v ...interface{}) { + if atomic.LoadInt32(&std.isDiscard) != 0 { + return + } std.Output(2, fmt.Sprintf(format, v...)) } // Println calls Output to print to the standard logger. // Arguments are handled in the manner of fmt.Println. func Println(v ...interface{}) { + if atomic.LoadInt32(&std.isDiscard) != 0 { + return + } std.Output(2, fmt.Sprintln(v...)) } diff --git a/src/log/log_test.go b/src/log/log_test.go index 5be8e82258..938ed42357 100644 --- a/src/log/log_test.go +++ b/src/log/log_test.go @@ -9,6 +9,7 @@ package log import ( "bytes" "fmt" + "io" "os" "regexp" "strings" @@ -20,7 +21,7 @@ const ( Rdate = `[0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9]` Rtime = `[0-9][0-9]:[0-9][0-9]:[0-9][0-9]` Rmicroseconds = `\.[0-9][0-9][0-9][0-9][0-9][0-9]` - Rline = `(60|62):` // must update if the calls to l.Printf / l.Print below move + Rline = `(61|63):` // must update if the calls to l.Printf / l.Print below move Rlongfile = `.*/[A-Za-z0-9_\-]+\.go:` + Rline Rshortfile = `[A-Za-z0-9_\-]+\.go:` + Rline ) @@ -179,6 +180,17 @@ func TestEmptyPrintCreatesLine(t *testing.T) { } } +func TestDiscard(t *testing.T) { + l := New(io.Discard, "", 0) + s := strings.Repeat("a", 102400) + c := testing.AllocsPerRun(100, func() { l.Printf("%s", s) }) + // One allocation for slice passed to Printf, + // but none for formatting of long string. + if c > 1 { + t.Errorf("got %v allocs, want at most 1", c) + } +} + func BenchmarkItoa(b *testing.B) { dst := make([]byte, 0, 64) for i := 0; i < b.N; i++ { -- GitLab From 74e384f50d3071c97effa3afd43ec29111587d59 Mon Sep 17 00:00:00 2001 From: Andy Pan Date: Wed, 15 Sep 2021 12:37:20 +0800 Subject: [PATCH 1183/2500] internal/poll: inject a hook into the runtime finalizer to count the closed pipes Fixes #48066 Change-Id: Icd6974dfcc496c054bb096e5d70de6e135984517 Reviewed-on: https://go-review.googlesource.com/c/go/+/349774 Reviewed-by: Bryan C. Mills Reviewed-by: Ian Lance Taylor Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot --- src/internal/poll/splice_linux_test.go | 60 +++++++++++++++----------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/src/internal/poll/splice_linux_test.go b/src/internal/poll/splice_linux_test.go index deac5c3759..8c4363886e 100644 --- a/src/internal/poll/splice_linux_test.go +++ b/src/internal/poll/splice_linux_test.go @@ -6,40 +6,48 @@ package poll_test import ( "internal/poll" - "internal/syscall/unix" "runtime" - "syscall" + "sync" + "sync/atomic" "testing" "time" ) -// checkPipes returns true if all pipes are closed properly, false otherwise. -func checkPipes(fds []int) bool { - for _, fd := range fds { - // Check if each pipe fd has been closed. - _, _, errno := syscall.Syscall(unix.FcntlSyscall, uintptr(fd), syscall.F_GETPIPE_SZ, 0) - if errno == 0 { - return false +var closeHook atomic.Value // func(fd int) + +func init() { + closeFunc := poll.CloseFunc + poll.CloseFunc = func(fd int) (err error) { + if v := closeHook.Load(); v != nil { + if hook := v.(func(int)); hook != nil { + hook(fd) + } } + return closeFunc(fd) } - return true } func TestSplicePipePool(t *testing.T) { const N = 64 var ( - p *poll.SplicePipe - ps []*poll.SplicePipe - fds []int - err error + p *poll.SplicePipe + ps []*poll.SplicePipe + allFDs []int + pendingFDs sync.Map // fd → struct{}{} + err error ) + + closeHook.Store(func(fd int) { pendingFDs.Delete(fd) }) + t.Cleanup(func() { closeHook.Store((func(int))(nil)) }) + for i := 0; i < N; i++ { p, _, err = poll.GetPipe() if err != nil { - t.Skip("failed to create pipe, skip this test") + t.Skipf("failed to create pipe due to error(%v), skip this test", err) } _, pwfd := poll.GetPipeFds(p) - fds = append(fds, pwfd) + allFDs = append(allFDs, pwfd) + pendingFDs.Store(pwfd, struct{}{}) ps = append(ps, p) } for _, p = range ps { @@ -62,19 +70,21 @@ func TestSplicePipePool(t *testing.T) { for { runtime.GC() time.Sleep(10 * time.Millisecond) - if checkPipes(fds) { + + // Detect whether all pipes are closed properly. + var leakedFDs []int + pendingFDs.Range(func(k, v interface{}) bool { + leakedFDs = append(leakedFDs, k.(int)) + return true + }) + if len(leakedFDs) == 0 { break } + select { case <-expiredTime.C: - t.Logf("descriptors to check: %v", fds) - for _, fd := range fds { - _, _, errno := syscall.Syscall(unix.FcntlSyscall, uintptr(fd), syscall.F_GETPIPE_SZ, 0) - if errno == 0 { - t.Errorf("descriptor %d still open", fd) - } - } - t.Fatal("at least one pipe is still open") + t.Logf("all descriptors: %v", allFDs) + t.Fatalf("leaked descriptors: %v", leakedFDs) default: } } -- GitLab From cea7a71d40115333d5943162e5764162b767389d Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 13 Sep 2021 18:50:19 -0700 Subject: [PATCH 1184/2500] cmd/compile: fix generic type handling in crawler There are a bunch of nodes beside ONAME and OTYPE, (such as OSTRUCTLIT and OCOMPLIT) which can introduce a generic type that we need to mark. So, just mark any generic type on any node in markInlBody. In this particular issue, the type is introduced by an OSTRUCTLIT node. Updates #48337 Change-Id: I271932518f0c1fb54d91a603e01a855c69df631d Reviewed-on: https://go-review.googlesource.com/c/go/+/349909 Trust: Dan Scales Trust: Carlos Amedee Reviewed-by: Keith Randall --- src/cmd/compile/internal/typecheck/crawler.go | 45 +++++++++---------- test/typeparam/issue48337a.dir/a.go | 32 +++++++++++++ test/typeparam/issue48337a.dir/main.go | 12 +++++ test/typeparam/issue48337a.go | 7 +++ test/typeparam/issue48337a.out | 1 + 5 files changed, 73 insertions(+), 24 deletions(-) create mode 100644 test/typeparam/issue48337a.dir/a.go create mode 100644 test/typeparam/issue48337a.dir/main.go create mode 100644 test/typeparam/issue48337a.go create mode 100644 test/typeparam/issue48337a.out diff --git a/src/cmd/compile/internal/typecheck/crawler.go b/src/cmd/compile/internal/typecheck/crawler.go index 9e523c3d14..3f212aa805 100644 --- a/src/cmd/compile/internal/typecheck/crawler.go +++ b/src/cmd/compile/internal/typecheck/crawler.go @@ -44,12 +44,13 @@ func (p *crawler) markObject(n *ir.Name) { p.markType(n.Type()) } -// markType recursively visits types reachable from t to identify -// functions whose inline bodies may be needed. +// markType recursively visits types reachable from t to identify functions whose +// inline bodies may be needed. For instantiated generic types, it visits the base +// generic type, which has the relevant methods. func (p *crawler) markType(t *types.Type) { - if t.IsInstantiatedGeneric() { - // Re-instantiated types don't add anything new, so don't follow them. - return + if t.OrigSym() != nil { + // Convert to the base generic type. + t = t.OrigSym().Def.Type() } if p.marked[t] { return @@ -92,6 +93,9 @@ func (p *crawler) markType(t *types.Type) { p.markType(t.Elem()) case types.TSTRUCT: + if t.IsFuncArgStruct() { + break + } for _, f := range t.FieldSlice() { if types.IsExported(f.Sym.Name) || f.Embedded != 0 { p.markType(f.Type) @@ -129,9 +133,9 @@ func (p *crawler) markEmbed(t *types.Type) { t = t.Elem() } - if t.IsInstantiatedGeneric() { - // Re-instantiated types don't add anything new, so don't follow them. - return + if t.OrigSym() != nil { + // Convert to the base generic type. + t = t.OrigSym().Def.Type() } if p.embedded[t] { @@ -185,6 +189,15 @@ func (p *crawler) markInlBody(n *ir.Name) { var doFlood func(n ir.Node) doFlood = func(n ir.Node) { + t := n.Type() + if t != nil && (t.HasTParam() || t.IsFullyInstantiated()) { + // Ensure that we call markType() on any base generic type + // that is written to the export file (even if not explicitly + // marked for export), so we will call markInlBody on its + // methods, and the methods will be available for + // instantiation if needed. + p.markType(t) + } switch n.Op() { case ir.OMETHEXPR, ir.ODOTMETH: p.markInlBody(ir.MethodExprName(n)) @@ -198,9 +211,6 @@ func (p *crawler) markInlBody(n *ir.Name) { case ir.PEXTERN: Export(n) } - p.checkGenericType(n.Type()) - case ir.OTYPE: - p.checkGenericType(n.Type()) case ir.OMETHVALUE: // Okay, because we don't yet inline indirect // calls to method values. @@ -216,16 +226,3 @@ func (p *crawler) markInlBody(n *ir.Name) { // because after inlining they might be callable. ir.VisitList(fn.Inl.Body, doFlood) } - -// checkGenerictype ensures that we call markType() on any base generic type that -// is written to the export file (even if not explicitly marked -// for export), so its methods will be available for inlining if needed. -func (p *crawler) checkGenericType(t *types.Type) { - if t != nil && t.HasTParam() { - if t.OrigSym() != nil { - // Convert to the base generic type. - t = t.OrigSym().Def.Type() - } - p.markType(t) - } -} diff --git a/test/typeparam/issue48337a.dir/a.go b/test/typeparam/issue48337a.dir/a.go new file mode 100644 index 0000000000..6f1b128589 --- /dev/null +++ b/test/typeparam/issue48337a.dir/a.go @@ -0,0 +1,32 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +import ( + "fmt" + "sync" +) + +type WrapperWithLock[T any] interface { + PrintWithLock() +} + +func NewWrapperWithLock[T any](value T) WrapperWithLock[T] { + return &wrapperWithLock[T]{ + Object: value, + } +} + +type wrapperWithLock[T any] struct { + Lock sync.Mutex + Object T +} + +func (w *wrapperWithLock[T]) PrintWithLock() { + w.Lock.Lock() + defer w.Lock.Unlock() + + fmt.Println(w.Object) +} diff --git a/test/typeparam/issue48337a.dir/main.go b/test/typeparam/issue48337a.dir/main.go new file mode 100644 index 0000000000..16f71153f3 --- /dev/null +++ b/test/typeparam/issue48337a.dir/main.go @@ -0,0 +1,12 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "a" + +func main() { + obj := a.NewWrapperWithLock("this file does import sync") + obj.PrintWithLock() +} diff --git a/test/typeparam/issue48337a.go b/test/typeparam/issue48337a.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/issue48337a.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored diff --git a/test/typeparam/issue48337a.out b/test/typeparam/issue48337a.out new file mode 100644 index 0000000000..fa8d3eedcb --- /dev/null +++ b/test/typeparam/issue48337a.out @@ -0,0 +1 @@ +this file does import sync -- GitLab From 1a49dcb82f1ef0d028f74f4fd955ee01b09b466d Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Fri, 17 Sep 2021 14:23:04 +0200 Subject: [PATCH 1185/2500] syscall: remove //sysnb comment generating Setreuid for linux/arm64 CL 210639 moved the //sysnb for Setreuid from syscall_linux_$GOARCH.go to syscall_linux.go but forgot to remove the comment from syscall_linux_arm64.go which leads to Setreuid being generated twice for linux/arm64. Remove that //sysnb comment to avoid this. Change-Id: I2c8ad95f786530ca964685b0a4fe463c64764307 Reviewed-on: https://go-review.googlesource.com/c/go/+/350531 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/syscall/syscall_linux_arm64.go | 1 - 1 file changed, 1 deletion(-) diff --git a/src/syscall/syscall_linux_arm64.go b/src/syscall/syscall_linux_arm64.go index f575c84c93..517723ae47 100644 --- a/src/syscall/syscall_linux_arm64.go +++ b/src/syscall/syscall_linux_arm64.go @@ -42,7 +42,6 @@ func EpollCreate(size int) (fd int, err error) { //sys Setfsgid(gid int) (err error) //sys Setfsuid(uid int) (err error) //sysnb setrlimit(resource int, rlim *Rlimit) (err error) -//sysnb Setreuid(ruid int, euid int) (err error) //sys Shutdown(fd int, how int) (err error) //sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) -- GitLab From 974b0166d6a7c20b98f7e517e49197bea46fc5e2 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Fri, 17 Sep 2021 14:25:54 +0200 Subject: [PATCH 1186/2500] syscall: implement Pipe using pipe2 syscall on all linux platforms Most architectures currently already implement Pipe using the pipe2 syscall. Only 386, amd64 and mips{,le} still use the pipe syscall. However, some systems (e.g. Android seccomp policies) block that syscall, see #40828 for an example. The pipe2 syscall was added in Linux kernel version 2.6.27. The minimum required Linux kernel version for Go 1.18 will be changed to 2.6.32 per #45964 so it is possible to unify the implementation of Pipe using the pipe2 syscall. For #45964 Change-Id: I8ed6a391300c95f3107b4ec6b27d320e42fb535b Reviewed-on: https://go-review.googlesource.com/c/go/+/350530 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/syscall/syscall_linux.go | 17 ++++++++++++++ src/syscall/syscall_linux_386.go | 26 --------------------- src/syscall/syscall_linux_amd64.go | 26 --------------------- src/syscall/syscall_linux_arm.go | 26 --------------------- src/syscall/syscall_linux_arm64.go | 24 ------------------- src/syscall/syscall_linux_mips64x.go | 24 ------------------- src/syscall/syscall_linux_mipsx.go | 23 ------------------ src/syscall/syscall_linux_ppc64x.go | 24 ------------------- src/syscall/syscall_linux_riscv64.go | 24 ------------------- src/syscall/syscall_linux_s390x.go | 24 ------------------- src/syscall/zsyscall_linux_386.go | 30 ++++++++---------------- src/syscall/zsyscall_linux_amd64.go | 30 ++++++++---------------- src/syscall/zsyscall_linux_arm.go | 30 ++++++++---------------- src/syscall/zsyscall_linux_arm64.go | 20 ++++++++-------- src/syscall/zsyscall_linux_mips.go | 32 ++++++++------------------ src/syscall/zsyscall_linux_mips64.go | 20 ++++++++-------- src/syscall/zsyscall_linux_mips64le.go | 20 ++++++++-------- src/syscall/zsyscall_linux_mipsle.go | 32 ++++++++------------------ src/syscall/zsyscall_linux_ppc64.go | 20 ++++++++-------- src/syscall/zsyscall_linux_ppc64le.go | 20 ++++++++-------- src/syscall/zsyscall_linux_riscv64.go | 20 ++++++++-------- src/syscall/zsyscall_linux_s390x.go | 20 ++++++++-------- 22 files changed, 137 insertions(+), 395 deletions(-) diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go index 6d428d58dd..f02fa45a89 100644 --- a/src/syscall/syscall_linux.go +++ b/src/syscall/syscall_linux.go @@ -161,6 +161,23 @@ func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) return openat(dirfd, path, flags|O_LARGEFILE, mode) } +func Pipe(p []int) error { + return Pipe2(p, 0) +} + +//sysnb pipe2(p *[2]_C_int, flags int) (err error) + +func Pipe2(p []int, flags int) error { + if len(p) != 2 { + return EINVAL + } + var pp [2]_C_int + err := pipe2(&pp, flags) + p[0] = int(pp[0]) + p[1] = int(pp[1]) + return err +} + //sys readlinkat(dirfd int, path string, buf []byte) (n int, err error) func Readlink(path string, buf []byte) (n int, err error) { diff --git a/src/syscall/syscall_linux_386.go b/src/syscall/syscall_linux_386.go index 0db037470d..98442055d8 100644 --- a/src/syscall/syscall_linux_386.go +++ b/src/syscall/syscall_linux_386.go @@ -22,32 +22,6 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: int32(sec), Usec: int32(usec)} } -//sysnb pipe(p *[2]_C_int) (err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe(&pp) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - // 64-bit file system and 32-bit uid calls // (386 default is 32-bit file system and 16-bit uid). //sys Dup2(oldfd int, newfd int) (err error) diff --git a/src/syscall/syscall_linux_amd64.go b/src/syscall/syscall_linux_amd64.go index 5df3f796d1..04acd063fa 100644 --- a/src/syscall/syscall_linux_amd64.go +++ b/src/syscall/syscall_linux_amd64.go @@ -110,32 +110,6 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: sec, Usec: usec} } -//sysnb pipe(p *[2]_C_int) (err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe(&pp) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - func (r *PtraceRegs) PC() uint64 { return r.Rip } func (r *PtraceRegs) SetPC(pc uint64) { r.Rip = pc } diff --git a/src/syscall/syscall_linux_arm.go b/src/syscall/syscall_linux_arm.go index fffa4b29b9..f2f342e7ed 100644 --- a/src/syscall/syscall_linux_arm.go +++ b/src/syscall/syscall_linux_arm.go @@ -22,32 +22,6 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: int32(sec), Usec: int32(usec)} } -//sysnb pipe(p *[2]_C_int) (err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, 0) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - // Underlying system call writes to newoffset via pointer. // Implemented in assembly to avoid allocation. func seek(fd int, offset int64, whence int) (newoffset int64, err Errno) diff --git a/src/syscall/syscall_linux_arm64.go b/src/syscall/syscall_linux_arm64.go index 517723ae47..990e732f35 100644 --- a/src/syscall/syscall_linux_arm64.go +++ b/src/syscall/syscall_linux_arm64.go @@ -145,30 +145,6 @@ func utimes(path string, tv *[2]Timeval) (err error) { return utimensat(_AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) } -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, 0) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - // Getrlimit prefers the prlimit64 system call. See issue 38604. func Getrlimit(resource int, rlim *Rlimit) error { err := prlimit(0, resource, nil, rlim) diff --git a/src/syscall/syscall_linux_mips64x.go b/src/syscall/syscall_linux_mips64x.go index 5feb03e915..fa0d2799ed 100644 --- a/src/syscall/syscall_linux_mips64x.go +++ b/src/syscall/syscall_linux_mips64x.go @@ -103,30 +103,6 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: sec, Usec: usec} } -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, 0) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - func Ioperm(from int, num int, on int) (err error) { return ENOSYS } diff --git a/src/syscall/syscall_linux_mipsx.go b/src/syscall/syscall_linux_mipsx.go index 39104d71d8..568523eb27 100644 --- a/src/syscall/syscall_linux_mipsx.go +++ b/src/syscall/syscall_linux_mipsx.go @@ -112,29 +112,6 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: int32(sec), Usec: int32(usec)} } -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe() (p1 int, p2 int, err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - p[0], p[1], err = pipe() - return -} - //sys mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error) func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) { diff --git a/src/syscall/syscall_linux_ppc64x.go b/src/syscall/syscall_linux_ppc64x.go index 495ae29757..3e73f6f2a4 100644 --- a/src/syscall/syscall_linux_ppc64x.go +++ b/src/syscall/syscall_linux_ppc64x.go @@ -82,30 +82,6 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: sec, Usec: usec} } -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, 0) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - func (r *PtraceRegs) PC() uint64 { return r.Nip } func (r *PtraceRegs) SetPC(pc uint64) { r.Nip = pc } diff --git a/src/syscall/syscall_linux_riscv64.go b/src/syscall/syscall_linux_riscv64.go index 2a0fe64d25..bcb89c6e9a 100644 --- a/src/syscall/syscall_linux_riscv64.go +++ b/src/syscall/syscall_linux_riscv64.go @@ -149,30 +149,6 @@ func utimes(path string, tv *[2]Timeval) (err error) { return utimensat(_AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) } -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, 0) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - func (r *PtraceRegs) PC() uint64 { return r.Pc } func (r *PtraceRegs) SetPC(pc uint64) { r.Pc = pc } diff --git a/src/syscall/syscall_linux_s390x.go b/src/syscall/syscall_linux_s390x.go index 0f6f6277bb..123664f5b2 100644 --- a/src/syscall/syscall_linux_s390x.go +++ b/src/syscall/syscall_linux_s390x.go @@ -74,30 +74,6 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: sec, Usec: usec} } -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, 0) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - // Linux on s390x uses the old mmap interface, which requires arguments to be passed in a struct. // mmap2 also requires arguments to be passed in a struct; it is currently not exposed in . func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) { diff --git a/src/syscall/zsyscall_linux_386.go b/src/syscall/zsyscall_linux_386.go index ac822d6f7a..a1394d32cb 100644 --- a/src/syscall/zsyscall_linux_386.go +++ b/src/syscall/zsyscall_linux_386.go @@ -76,6 +76,16 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func readlinkat(dirfd int, path string, buf []byte) (n int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1048,26 +1058,6 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe(p *[2]_C_int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func pipe2(p *[2]_C_int, flags int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Dup2(oldfd int, newfd int) (err error) { _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) if e1 != 0 { diff --git a/src/syscall/zsyscall_linux_amd64.go b/src/syscall/zsyscall_linux_amd64.go index ed37fa8dec..de6047d11c 100644 --- a/src/syscall/zsyscall_linux_amd64.go +++ b/src/syscall/zsyscall_linux_amd64.go @@ -76,6 +76,16 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func readlinkat(dirfd int, path string, buf []byte) (n int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1644,23 +1654,3 @@ func utimes(path string, times *[2]Timeval) (err error) { } return } - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func pipe(p *[2]_C_int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func pipe2(p *[2]_C_int, flags int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} diff --git a/src/syscall/zsyscall_linux_arm.go b/src/syscall/zsyscall_linux_arm.go index 213aaf3bac..3663b2eead 100644 --- a/src/syscall/zsyscall_linux_arm.go +++ b/src/syscall/zsyscall_linux_arm.go @@ -76,6 +76,16 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func readlinkat(dirfd int, path string, buf []byte) (n int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1048,26 +1058,6 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe(p *[2]_C_int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func pipe2(p *[2]_C_int, flags int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) fd = int(r0) diff --git a/src/syscall/zsyscall_linux_arm64.go b/src/syscall/zsyscall_linux_arm64.go index e2f9c0fd9b..19a9c0ca61 100644 --- a/src/syscall/zsyscall_linux_arm64.go +++ b/src/syscall/zsyscall_linux_arm64.go @@ -76,6 +76,16 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func readlinkat(dirfd int, path string, buf []byte) (n int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1555,16 +1565,6 @@ func Gettimeofday(tv *Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe2(p *[2]_C_int, flags int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func ppoll(fds *pollFd, nfds int, timeout *Timespec, sigmask *sigset_t) (n int, err error) { r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) n = int(r0) diff --git a/src/syscall/zsyscall_linux_mips.go b/src/syscall/zsyscall_linux_mips.go index 617c2f5466..966b2e1f2c 100644 --- a/src/syscall/zsyscall_linux_mips.go +++ b/src/syscall/zsyscall_linux_mips.go @@ -76,6 +76,16 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func readlinkat(dirfd int, path string, buf []byte) (n int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1646,28 +1656,6 @@ func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe2(p *[2]_C_int, flags int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func pipe() (p1 int, p2 int, err error) { - r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) - p1 = int(r0) - p2 = int(r1) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error) { r0, _, e1 := Syscall6(SYS_MMAP2, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(pageOffset)) xaddr = uintptr(r0) diff --git a/src/syscall/zsyscall_linux_mips64.go b/src/syscall/zsyscall_linux_mips64.go index 793d4b9884..c6812a0515 100644 --- a/src/syscall/zsyscall_linux_mips64.go +++ b/src/syscall/zsyscall_linux_mips64.go @@ -76,6 +76,16 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func readlinkat(dirfd int, path string, buf []byte) (n int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1642,16 +1652,6 @@ func utimes(path string, times *[2]Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe2(p *[2]_C_int, flags int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func fstat(fd int, st *stat_t) (err error) { _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(st)), 0) if e1 != 0 { diff --git a/src/syscall/zsyscall_linux_mips64le.go b/src/syscall/zsyscall_linux_mips64le.go index 54e1760bda..eaaf7dfb41 100644 --- a/src/syscall/zsyscall_linux_mips64le.go +++ b/src/syscall/zsyscall_linux_mips64le.go @@ -76,6 +76,16 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func readlinkat(dirfd int, path string, buf []byte) (n int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1642,16 +1652,6 @@ func utimes(path string, times *[2]Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe2(p *[2]_C_int, flags int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func fstat(fd int, st *stat_t) (err error) { _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(st)), 0) if e1 != 0 { diff --git a/src/syscall/zsyscall_linux_mipsle.go b/src/syscall/zsyscall_linux_mipsle.go index ba7e2118c0..bb159f1fe7 100644 --- a/src/syscall/zsyscall_linux_mipsle.go +++ b/src/syscall/zsyscall_linux_mipsle.go @@ -76,6 +76,16 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func readlinkat(dirfd int, path string, buf []byte) (n int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1646,28 +1656,6 @@ func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe2(p *[2]_C_int, flags int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func pipe() (p1 int, p2 int, err error) { - r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) - p1 = int(r0) - p2 = int(r1) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error) { r0, _, e1 := Syscall6(SYS_MMAP2, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(pageOffset)) xaddr = uintptr(r0) diff --git a/src/syscall/zsyscall_linux_ppc64.go b/src/syscall/zsyscall_linux_ppc64.go index c3437722e0..8a4328560a 100644 --- a/src/syscall/zsyscall_linux_ppc64.go +++ b/src/syscall/zsyscall_linux_ppc64.go @@ -76,6 +76,16 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func readlinkat(dirfd int, path string, buf []byte) (n int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1703,16 +1713,6 @@ func utimes(path string, times *[2]Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe2(p *[2]_C_int, flags int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func syncFileRange2(fd int, flags int, off int64, n int64) (err error) { _, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE2, uintptr(fd), uintptr(flags), uintptr(off), uintptr(n), 0, 0) if e1 != 0 { diff --git a/src/syscall/zsyscall_linux_ppc64le.go b/src/syscall/zsyscall_linux_ppc64le.go index acc34a76d2..274b55ce6b 100644 --- a/src/syscall/zsyscall_linux_ppc64le.go +++ b/src/syscall/zsyscall_linux_ppc64le.go @@ -76,6 +76,16 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func readlinkat(dirfd int, path string, buf []byte) (n int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1703,16 +1713,6 @@ func utimes(path string, times *[2]Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe2(p *[2]_C_int, flags int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func syncFileRange2(fd int, flags int, off int64, n int64) (err error) { _, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE2, uintptr(fd), uintptr(flags), uintptr(off), uintptr(n), 0, 0) if e1 != 0 { diff --git a/src/syscall/zsyscall_linux_riscv64.go b/src/syscall/zsyscall_linux_riscv64.go index d662d780db..e21dc46f32 100644 --- a/src/syscall/zsyscall_linux_riscv64.go +++ b/src/syscall/zsyscall_linux_riscv64.go @@ -76,6 +76,16 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func readlinkat(dirfd int, path string, buf []byte) (n int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1555,16 +1565,6 @@ func Gettimeofday(tv *Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe2(p *[2]_C_int, flags int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func ppoll(fds *pollFd, nfds int, timeout *Timespec, sigmask *sigset_t) (n int, err error) { r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) n = int(r0) diff --git a/src/syscall/zsyscall_linux_s390x.go b/src/syscall/zsyscall_linux_s390x.go index 20f8c61366..fc667e7c3f 100644 --- a/src/syscall/zsyscall_linux_s390x.go +++ b/src/syscall/zsyscall_linux_s390x.go @@ -76,6 +76,16 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func readlinkat(dirfd int, path string, buf []byte) (n int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1490,13 +1500,3 @@ func utimes(path string, times *[2]Timeval) (err error) { } return } - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func pipe2(p *[2]_C_int, flags int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} -- GitLab From 3fa7dbeff53b56edd98f295bd0c34423c080ac57 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Fri, 17 Sep 2021 22:34:15 +0200 Subject: [PATCH 1187/2500] cmd/go: fix GOARCH value in GOAMD64 docs GOAMD64 is for GOARCH=amd64. Fix the GOAMD64 environment variable docs introduced by CL 349595. Change-Id: I794990ebe2e306d21ed275446fc52373bfe4ae7d Reviewed-on: https://go-review.googlesource.com/c/go/+/350534 Trust: Tobias Klauser Run-TryBot: Tobias Klauser Reviewed-by: Ian Lance Taylor Reviewed-by: Matthew Dempsky TryBot-Result: Go Bot --- src/cmd/go/alldocs.go | 2 +- src/cmd/go/internal/help/helpdoc.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 35c60744b8..9753ebba3e 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -1988,7 +1988,7 @@ // For GOARCH=386, how to implement floating point instructions. // Valid values are sse2 (default), softfloat. // GOAMD64 -// For GOARCH=GOAMD64, the microarchitecture level for which to compile. +// For GOARCH=amd64, the microarchitecture level for which to compile. // Valid values are v1 (default), v2, v3, v4. // See https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels. // GOMIPS diff --git a/src/cmd/go/internal/help/helpdoc.go b/src/cmd/go/internal/help/helpdoc.go index 91876cefe0..749dcf192b 100644 --- a/src/cmd/go/internal/help/helpdoc.go +++ b/src/cmd/go/internal/help/helpdoc.go @@ -593,7 +593,7 @@ Architecture-specific environment variables: For GOARCH=386, how to implement floating point instructions. Valid values are sse2 (default), softfloat. GOAMD64 - For GOARCH=GOAMD64, the microarchitecture level for which to compile. + For GOARCH=amd64, the microarchitecture level for which to compile. Valid values are v1 (default), v2, v3, v4. See https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels. GOMIPS -- GitLab From 3fa35b5f9741d7d1c9a9e047057c7210da04fbba Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 15 Sep 2021 17:18:37 -0400 Subject: [PATCH 1188/2500] go/types: ensure that we always get a new signature in expandNamed CL 349412 introduced a bug when Checker.subst does not return a new signature: we were still setting the receiver to the instantiated type. I'm not sure how this could manifest in practice (other than confusing object strings). It's possible that I could generate a testdata-driven test for this, but in the interest of time I just added a test to verify object strings. Change-Id: I29bc8e1419ddc4574755c3def52d18cb71c738eb Reviewed-on: https://go-review.googlesource.com/c/go/+/350143 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/instantiate_test.go | 43 ++++++++++++++++++++++++++++++++ src/go/types/named.go | 6 +++++ 2 files changed, 49 insertions(+) diff --git a/src/go/types/instantiate_test.go b/src/go/types/instantiate_test.go index 851800e76d..0c66acb875 100644 --- a/src/go/types/instantiate_test.go +++ b/src/go/types/instantiate_test.go @@ -6,6 +6,7 @@ package types_test import ( . "go/types" + "strings" "testing" ) @@ -109,3 +110,45 @@ var X T[int] } } } + +func TestImmutableSignatures(t *testing.T) { + const src = genericPkg + `p + +type T[P any] struct{} + +func (T[P]) m() {} + +var _ T[int] +` + pkg, err := pkgFor(".", src, nil) + if err != nil { + t.Fatal(err) + } + typ := pkg.Scope().Lookup("T").Type().(*Named) + obj, _, _ := LookupFieldOrMethod(typ, false, pkg, "m") + if obj == nil { + t.Fatalf(`LookupFieldOrMethod(%s, "m") = %v, want func m`, typ, obj) + } + + // Verify that the original method is not mutated by instantiating T (this + // bug manifested when subst did not return a new signature). + want := "func (T[P]).m()" + if got := stripAnnotations(ObjectString(obj, RelativeTo(pkg))); got != want { + t.Errorf("instantiated %q, want %q", got, want) + } +} + +// Copied from errors.go. +func stripAnnotations(s string) string { + var b strings.Builder + for _, r := range s { + // strip #'s and subscript digits + if r < '₀' || '₀'+10 <= r { // '₀' == U+2080 + b.WriteRune(r) + } + } + if b.Len() < len(s) { + return b.String() + } + return s +} diff --git a/src/go/types/named.go b/src/go/types/named.go index 00fde16445..4a263410fc 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -309,6 +309,12 @@ func (check *Checker) completeMethod(env *Environment, m *Func) { smap := makeSubstMap(origSig.RecvTypeParams().list(), rtyp.targs.list()) sig := check.subst(orig.pos, origSig, smap, env).(*Signature) + if sig == origSig { + // No substitution occurred, but we still need to create a copy to hold the + // instantiated receiver. + copy := *origSig + sig = © + } sig.recv = NewParam(origSig.recv.pos, origSig.recv.pkg, origSig.recv.name, rtyp) m.typ = sig -- GitLab From 50e450826916c777a7d61edab52793ed77314f7a Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Fri, 17 Sep 2021 12:18:19 -0700 Subject: [PATCH 1189/2500] cmd/compile: fix import/export of Init and Def fields. Change so that the Init and Def fields of assignments and OSELREVC2 nodes are exported/imported properly. A quirk of iimport.go is that it automatically converts an ODCL node to an ODCL/OAS sequence (where the OAS is to just zero out the declared variable). Given that the Inits are properly fixed, o.stmt needs adjustment for the OSELRECV2 case to skip over the new OAS nodes that are inserted only on re-import. Change-Id: Ic38017efca4b7ca9b3952ffbbfca067380902b7a Reviewed-on: https://go-review.googlesource.com/c/go/+/350809 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky Trust: Dan Scales --- src/cmd/compile/internal/typecheck/iexport.go | 25 ++++++++++++++++--- src/cmd/compile/internal/typecheck/iimport.go | 21 +++++++++++++--- src/cmd/compile/internal/walk/order.go | 6 +++++ 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index f001017a86..a9522c3887 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -1456,10 +1456,23 @@ func (w *exportWriter) node(n ir.Node) { } } -// Caution: stmt will emit more than one node for statement nodes n that have a non-empty -// n.Ninit and where n cannot have a natural init section (such as in "if", "for", etc.). +func isNonEmptyAssign(n ir.Node) bool { + switch n.Op() { + case ir.OAS: + if n.(*ir.AssignStmt).Y != nil { + return true + } + case ir.OAS2, ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV: + return true + } + return false +} + +// Caution: stmt will emit more than one node for statement nodes n that have a +// non-empty n.Ninit and where n is not a non-empty assignment or a node with a natural init +// section (such as in "if", "for", etc.). func (w *exportWriter) stmt(n ir.Node) { - if len(n.Init()) > 0 && !ir.StmtWithInit(n.Op()) { + if len(n.Init()) > 0 && !ir.StmtWithInit(n.Op()) && !isNonEmptyAssign(n) { // can't use stmtList here since we don't want the final OEND for _, n := range n.Init() { w.stmt(n) @@ -1495,8 +1508,10 @@ func (w *exportWriter) stmt(n ir.Node) { if n.Y != nil { w.op(ir.OAS) w.pos(n.Pos()) + w.stmtList(n.Init()) w.expr(n.X) w.expr(n.Y) + w.bool(n.Def) } case ir.OASOP: @@ -1517,8 +1532,10 @@ func (w *exportWriter) stmt(n ir.Node) { w.op(ir.OAS2) } w.pos(n.Pos()) + w.stmtList(n.Init()) w.exprList(n.Lhs) w.exprList(n.Rhs) + w.bool(n.Def) case ir.ORETURN: n := n.(*ir.ReturnStmt) @@ -2065,8 +2082,10 @@ func (w *exportWriter) expr(n ir.Node) { n := n.(*ir.AssignListStmt) w.op(ir.OSELRECV2) w.pos(n.Pos()) + w.stmtList(n.Init()) w.exprList(n.Lhs) w.exprList(n.Rhs) + w.bool(n.Def) default: base.Fatalf("cannot export %v (%d) node\n"+ diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index b3a0eb8871..3b3c2a2e2a 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1619,7 +1619,12 @@ func (r *importReader) node() ir.Node { // unreachable - never exported case ir.OAS: - return ir.NewAssignStmt(r.pos(), r.expr(), r.expr()) + pos := r.pos() + init := r.stmtList() + n := ir.NewAssignStmt(pos, r.expr(), r.expr()) + n.SetInit(init) + n.Def = r.bool() + return n case ir.OASOP: n := ir.NewAssignOpStmt(r.pos(), r.op(), r.expr(), nil) @@ -1636,7 +1641,12 @@ func (r *importReader) node() ir.Node { // unreachable - mapped to case OAS2 by exporter goto error } - return ir.NewAssignListStmt(r.pos(), op, r.exprList(), r.exprList()) + pos := r.pos() + init := r.stmtList() + n := ir.NewAssignListStmt(pos, op, r.exprList(), r.exprList()) + n.SetInit(init) + n.Def = r.bool() + return n case ir.ORETURN: return ir.NewReturnStmt(r.pos(), r.exprList()) @@ -1721,7 +1731,12 @@ func (r *importReader) node() ir.Node { return n case ir.OSELRECV2: - return ir.NewAssignListStmt(r.pos(), ir.OSELRECV2, r.exprList(), r.exprList()) + pos := r.pos() + init := r.stmtList() + n := ir.NewAssignListStmt(pos, ir.OSELRECV2, r.exprList(), r.exprList()) + n.SetInit(init) + n.Def = r.bool() + return n default: base.Fatalf("cannot import %v (%d) node\n"+ diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go index 4de8858f26..7ac1f75c8f 100644 --- a/src/cmd/compile/internal/walk/order.go +++ b/src/cmd/compile/internal/walk/order.go @@ -941,6 +941,12 @@ func (o *orderState) stmt(n ir.Node) { if colas { if len(init) > 0 && init[0].Op() == ir.ODCL && init[0].(*ir.Decl).X == n { init = init[1:] + + // iimport may have added a default initialization assignment, + // due to how it handles ODCL statements. + if len(init) > 0 && init[0].Op() == ir.OAS && init[0].(*ir.AssignStmt).X == n { + init = init[1:] + } } dcl := typecheck.Stmt(ir.NewDecl(base.Pos, ir.ODCL, n.(*ir.Name))) ncas.PtrInit().Append(dcl) -- GitLab From c10b98022027ce584b0571359439fae41a721dd3 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 10 Sep 2021 22:05:55 -0400 Subject: [PATCH 1190/2500] cmd/compile: restore tail call for method wrappers For certain type of method wrappers we used to generate a tail call. That was disabled in CL 307234 when register ABI is used, because with the current IR it was difficult to generate a tail call with the arguments in the right places. The problem was that the IR does not contain a CALL-like node with arguments; instead, it contains an OAS node that adjusts the receiver, than an OTAILCALL node that just contains the target, but no argument (with the assumption that the OAS node will put the adjusted receiver in the right place). With register ABI, putting arguments in registers are done in SSA. The assignment (OAS) doesn't put the receiver in register. This CL changes the IR of a tail call to take an actual OCALL node. Specifically, a tail call is represented as OTAILCALL (OCALL target args...) This way, the call target and args are connected through the OCALL node. So the call can be analyzed in SSA and the args can be passed in the right places. (Alternatively, we could have OTAILCALL node directly take the target and the args, without the OCALL node. Using an OCALL node is convenient as there are existing code that processes OCALL nodes which do not need to be changed. Also, a tail call is similar to ORETURN (OCALL target args...), except it doesn't preserve the frame. I did the former but I'm open to change.) The SSA representation is similar. Previously, the IR lowers to a Store the receiver then a BlockRetJmp which jumps to the target (without putting the arg in register). Now we use a TailCall op, which takes the target and the args. The call expansion pass and the register allocator handles TailCall pretty much like a StaticCall, and it will do the right ABI analysis and put the args in the right places. (Args other than the receiver are already in the right places. For register args it generates no code for them. For stack args currently it generates a self copy. I'll work on optimize that out.) BlockRetJmp is still used, signaling it is a tail call. The actual call is made in the TailCall op so BlockRetJmp generates no code (we could use BlockExit if we like). This slightly reduces binary size: old new cmd/go 14003088 13953936 cmd/link 6275552 6271456 Change-Id: I2d16d8d419fe1f17554916d317427383e17e27f0 Reviewed-on: https://go-review.googlesource.com/c/go/+/350145 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky Reviewed-by: David Chase --- src/cmd/compile/internal/amd64/ssa.go | 21 +-- src/cmd/compile/internal/arm/ssa.go | 10 +- src/cmd/compile/internal/arm64/ssa.go | 10 +- src/cmd/compile/internal/escape/stmt.go | 3 +- src/cmd/compile/internal/inline/inl.go | 3 + src/cmd/compile/internal/ir/fmt.go | 2 +- src/cmd/compile/internal/ir/node_gen.go | 6 +- src/cmd/compile/internal/ir/stmt.go | 9 +- src/cmd/compile/internal/mips/ssa.go | 9 +- src/cmd/compile/internal/mips64/ssa.go | 9 +- src/cmd/compile/internal/ppc64/ssa.go | 10 +- .../compile/internal/reflectdata/reflect.go | 15 +-- src/cmd/compile/internal/riscv64/ssa.go | 9 +- src/cmd/compile/internal/s390x/ssa.go | 10 +- src/cmd/compile/internal/ssa/check.go | 3 - src/cmd/compile/internal/ssa/expand_calls.go | 16 ++- src/cmd/compile/internal/ssa/gen/386.rules | 1 + src/cmd/compile/internal/ssa/gen/386Ops.go | 1 + src/cmd/compile/internal/ssa/gen/AMD64.rules | 1 + src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 1 + src/cmd/compile/internal/ssa/gen/ARM.rules | 1 + src/cmd/compile/internal/ssa/gen/ARM64.rules | 1 + src/cmd/compile/internal/ssa/gen/ARM64Ops.go | 1 + src/cmd/compile/internal/ssa/gen/ARMOps.go | 1 + src/cmd/compile/internal/ssa/gen/MIPS.rules | 1 + src/cmd/compile/internal/ssa/gen/MIPS64.rules | 1 + src/cmd/compile/internal/ssa/gen/MIPS64Ops.go | 1 + src/cmd/compile/internal/ssa/gen/MIPSOps.go | 1 + src/cmd/compile/internal/ssa/gen/PPC64.rules | 1 + src/cmd/compile/internal/ssa/gen/PPC64Ops.go | 1 + .../compile/internal/ssa/gen/RISCV64.rules | 1 + .../compile/internal/ssa/gen/RISCV64Ops.go | 1 + src/cmd/compile/internal/ssa/gen/S390X.rules | 1 + src/cmd/compile/internal/ssa/gen/S390XOps.go | 1 + src/cmd/compile/internal/ssa/gen/Wasm.rules | 1 + src/cmd/compile/internal/ssa/gen/WasmOps.go | 1 + .../compile/internal/ssa/gen/genericOps.go | 4 +- src/cmd/compile/internal/ssa/opGen.go | 124 ++++++++++++++++++ src/cmd/compile/internal/ssa/rewrite386.go | 3 + src/cmd/compile/internal/ssa/rewriteAMD64.go | 3 + src/cmd/compile/internal/ssa/rewriteARM.go | 3 + src/cmd/compile/internal/ssa/rewriteARM64.go | 3 + src/cmd/compile/internal/ssa/rewriteMIPS.go | 3 + src/cmd/compile/internal/ssa/rewriteMIPS64.go | 3 + src/cmd/compile/internal/ssa/rewritePPC64.go | 3 + .../compile/internal/ssa/rewriteRISCV64.go | 3 + src/cmd/compile/internal/ssa/rewriteS390X.go | 3 + src/cmd/compile/internal/ssa/rewriteWasm.go | 3 + src/cmd/compile/internal/ssa/writebarrier.go | 2 +- src/cmd/compile/internal/ssagen/abi.go | 20 ++- src/cmd/compile/internal/ssagen/ssa.go | 29 +++- .../compile/internal/typecheck/typecheck.go | 1 + src/cmd/compile/internal/walk/stmt.go | 8 ++ src/cmd/compile/internal/wasm/ssa.go | 13 +- src/cmd/compile/internal/x86/ssa.go | 9 +- test/abi/method_wrapper.go | 35 +++++ 56 files changed, 319 insertions(+), 121 deletions(-) create mode 100644 test/abi/method_wrapper.go diff --git a/src/cmd/compile/internal/amd64/ssa.go b/src/cmd/compile/internal/amd64/ssa.go index fc547ebba0..30131bd559 100644 --- a/src/cmd/compile/internal/amd64/ssa.go +++ b/src/cmd/compile/internal/amd64/ssa.go @@ -1008,7 +1008,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { } r := v.Reg() getgFromTLS(s, r) - case ssa.OpAMD64CALLstatic: + case ssa.OpAMD64CALLstatic, ssa.OpAMD64CALLtail: if s.ABI == obj.ABI0 && v.Aux.(*ssa.AuxCall).Fn.ABI() == obj.ABIInternal { // zeroing X15 when entering ABIInternal from ABI0 if buildcfg.GOOS != "plan9" { // do not use SSE on Plan 9 @@ -1017,6 +1017,10 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { // set G register from TLS getgFromTLS(s, x86.REG_R14) } + if v.Op == ssa.OpAMD64CALLtail { + s.TailCall(v) + break + } s.Call(v) if s.ABI == obj.ABIInternal && v.Aux.(*ssa.AuxCall).Fn.ABI() == obj.ABI0 { // zeroing X15 when entering ABIInternal from ABI0 @@ -1314,22 +1318,9 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) { p.To.Type = obj.TYPE_BRANCH s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()}) } - case ssa.BlockExit: + case ssa.BlockExit, ssa.BlockRetJmp: case ssa.BlockRet: s.Prog(obj.ARET) - case ssa.BlockRetJmp: - if s.ABI == obj.ABI0 && b.Aux.(*obj.LSym).ABI() == obj.ABIInternal { - // zeroing X15 when entering ABIInternal from ABI0 - if buildcfg.GOOS != "plan9" { // do not use SSE on Plan 9 - opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15) - } - // set G register from TLS - getgFromTLS(s, x86.REG_R14) - } - p := s.Prog(obj.ARET) - p.To.Type = obj.TYPE_MEM - p.To.Name = obj.NAME_EXTERN - p.To.Sym = b.Aux.(*obj.LSym) case ssa.BlockAMD64EQF: s.CombJump(b, next, &eqfJumps) diff --git a/src/cmd/compile/internal/arm/ssa.go b/src/cmd/compile/internal/arm/ssa.go index 4b083cec46..8aac80a22e 100644 --- a/src/cmd/compile/internal/arm/ssa.go +++ b/src/cmd/compile/internal/arm/ssa.go @@ -696,6 +696,8 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.To.Reg = v.Reg() case ssa.OpARMCALLstatic, ssa.OpARMCALLclosure, ssa.OpARMCALLinter: s.Call(v) + case ssa.OpARMCALLtail: + s.TailCall(v) case ssa.OpARMCALLudiv: p := s.Prog(obj.ACALL) p.To.Type = obj.TYPE_MEM @@ -936,17 +938,11 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) { s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()}) } - case ssa.BlockExit: + case ssa.BlockExit, ssa.BlockRetJmp: case ssa.BlockRet: s.Prog(obj.ARET) - case ssa.BlockRetJmp: - p := s.Prog(obj.ARET) - p.To.Type = obj.TYPE_MEM - p.To.Name = obj.NAME_EXTERN - p.To.Sym = b.Aux.(*obj.LSym) - case ssa.BlockARMEQ, ssa.BlockARMNE, ssa.BlockARMLT, ssa.BlockARMGE, ssa.BlockARMLE, ssa.BlockARMGT, diff --git a/src/cmd/compile/internal/arm64/ssa.go b/src/cmd/compile/internal/arm64/ssa.go index b985246117..c5e7a08914 100644 --- a/src/cmd/compile/internal/arm64/ssa.go +++ b/src/cmd/compile/internal/arm64/ssa.go @@ -1046,6 +1046,8 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p4.To.SetTarget(p) case ssa.OpARM64CALLstatic, ssa.OpARM64CALLclosure, ssa.OpARM64CALLinter: s.Call(v) + case ssa.OpARM64CALLtail: + s.TailCall(v) case ssa.OpARM64LoweredWB: p := s.Prog(obj.ACALL) p.To.Type = obj.TYPE_MEM @@ -1241,17 +1243,11 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) { s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()}) } - case ssa.BlockExit: + case ssa.BlockExit, ssa.BlockRetJmp: case ssa.BlockRet: s.Prog(obj.ARET) - case ssa.BlockRetJmp: - p := s.Prog(obj.ARET) - p.To.Type = obj.TYPE_MEM - p.To.Name = obj.NAME_EXTERN - p.To.Sym = b.Aux.(*obj.LSym) - case ssa.BlockARM64EQ, ssa.BlockARM64NE, ssa.BlockARM64LT, ssa.BlockARM64GE, ssa.BlockARM64LE, ssa.BlockARM64GT, diff --git a/src/cmd/compile/internal/escape/stmt.go b/src/cmd/compile/internal/escape/stmt.go index c71848b8a1..0afb5d64ef 100644 --- a/src/cmd/compile/internal/escape/stmt.go +++ b/src/cmd/compile/internal/escape/stmt.go @@ -180,7 +180,8 @@ func (e *escape) stmt(n ir.Node) { e.goDeferStmt(n) case ir.OTAILCALL: - // TODO(mdempsky): Treat like a normal call? esc.go used to just ignore it. + n := n.(*ir.TailCallStmt) + e.call(nil, n.Call) } } diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index 073373144d..04d751869b 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -544,6 +544,9 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool, edit func(ir.No call := call.(*ir.CallExpr) call.NoInline = true } + case ir.OTAILCALL: + n := n.(*ir.TailCallStmt) + n.Call.NoInline = true // Not inline a tail call for now. Maybe we could inline it just like RETURN fn(arg)? // TODO do them here (or earlier), // so escape analysis can avoid more heapmoves. diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index a99cb5ed98..29505357cc 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -386,7 +386,7 @@ func stmtFmt(n Node, s fmt.State) { case OTAILCALL: n := n.(*TailCallStmt) - fmt.Fprintf(s, "tailcall %v", n.Target) + fmt.Fprintf(s, "tailcall %v", n.Call) case OINLMARK: n := n.(*InlineMarkStmt) diff --git a/src/cmd/compile/internal/ir/node_gen.go b/src/cmd/compile/internal/ir/node_gen.go index aa41c03beb..44988880c8 100644 --- a/src/cmd/compile/internal/ir/node_gen.go +++ b/src/cmd/compile/internal/ir/node_gen.go @@ -1331,15 +1331,15 @@ func (n *TailCallStmt) doChildren(do func(Node) bool) bool { if doNodes(n.init, do) { return true } - if n.Target != nil && do(n.Target) { + if n.Call != nil && do(n.Call) { return true } return false } func (n *TailCallStmt) editChildren(edit func(Node) Node) { editNodes(n.init, edit) - if n.Target != nil { - n.Target = edit(n.Target).(*Name) + if n.Call != nil { + n.Call = edit(n.Call).(*CallExpr) } } diff --git a/src/cmd/compile/internal/ir/stmt.go b/src/cmd/compile/internal/ir/stmt.go index 69a74b9fdd..3482d7972e 100644 --- a/src/cmd/compile/internal/ir/stmt.go +++ b/src/cmd/compile/internal/ir/stmt.go @@ -385,14 +385,11 @@ func NewSwitchStmt(pos src.XPos, tag Node, cases []*CaseClause) *SwitchStmt { // code generation to jump directly to another function entirely. type TailCallStmt struct { miniStmt - Target *Name + Call *CallExpr // the underlying call } -func NewTailCallStmt(pos src.XPos, target *Name) *TailCallStmt { - if target.Op() != ONAME || target.Class != PFUNC { - base.FatalfAt(pos, "tail call to non-func %v", target) - } - n := &TailCallStmt{Target: target} +func NewTailCallStmt(pos src.XPos, call *CallExpr) *TailCallStmt { + n := &TailCallStmt{Call: call} n.pos = pos n.op = OTAILCALL return n diff --git a/src/cmd/compile/internal/mips/ssa.go b/src/cmd/compile/internal/mips/ssa.go index e0447f38cb..6326f966bf 100644 --- a/src/cmd/compile/internal/mips/ssa.go +++ b/src/cmd/compile/internal/mips/ssa.go @@ -475,6 +475,8 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p6.To.SetTarget(p2) case ssa.OpMIPSCALLstatic, ssa.OpMIPSCALLclosure, ssa.OpMIPSCALLinter: s.Call(v) + case ssa.OpMIPSCALLtail: + s.TailCall(v) case ssa.OpMIPSLoweredWB: p := s.Prog(obj.ACALL) p.To.Type = obj.TYPE_MEM @@ -841,14 +843,9 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) { p.To.Type = obj.TYPE_BRANCH s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()}) } - case ssa.BlockExit: + case ssa.BlockExit, ssa.BlockRetJmp: case ssa.BlockRet: s.Prog(obj.ARET) - case ssa.BlockRetJmp: - p := s.Prog(obj.ARET) - p.To.Type = obj.TYPE_MEM - p.To.Name = obj.NAME_EXTERN - p.To.Sym = b.Aux.(*obj.LSym) case ssa.BlockMIPSEQ, ssa.BlockMIPSNE, ssa.BlockMIPSLTZ, ssa.BlockMIPSGEZ, ssa.BlockMIPSLEZ, ssa.BlockMIPSGTZ, diff --git a/src/cmd/compile/internal/mips64/ssa.go b/src/cmd/compile/internal/mips64/ssa.go index e821a00876..990b9788f7 100644 --- a/src/cmd/compile/internal/mips64/ssa.go +++ b/src/cmd/compile/internal/mips64/ssa.go @@ -491,6 +491,8 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p6.To.SetTarget(p2) case ssa.OpMIPS64CALLstatic, ssa.OpMIPS64CALLclosure, ssa.OpMIPS64CALLinter: s.Call(v) + case ssa.OpMIPS64CALLtail: + s.TailCall(v) case ssa.OpMIPS64LoweredWB: p := s.Prog(obj.ACALL) p.To.Type = obj.TYPE_MEM @@ -808,14 +810,9 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) { p.To.Type = obj.TYPE_BRANCH s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()}) } - case ssa.BlockExit: + case ssa.BlockExit, ssa.BlockRetJmp: case ssa.BlockRet: s.Prog(obj.ARET) - case ssa.BlockRetJmp: - p := s.Prog(obj.ARET) - p.To.Type = obj.TYPE_MEM - p.To.Name = obj.NAME_EXTERN - p.To.Sym = b.Aux.(*obj.LSym) case ssa.BlockMIPS64EQ, ssa.BlockMIPS64NE, ssa.BlockMIPS64LTZ, ssa.BlockMIPS64GEZ, ssa.BlockMIPS64LEZ, ssa.BlockMIPS64GTZ, diff --git a/src/cmd/compile/internal/ppc64/ssa.go b/src/cmd/compile/internal/ppc64/ssa.go index 11226f65a0..e366e06949 100644 --- a/src/cmd/compile/internal/ppc64/ssa.go +++ b/src/cmd/compile/internal/ppc64/ssa.go @@ -1829,6 +1829,9 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { case ssa.OpPPC64CALLstatic: s.Call(v) + case ssa.OpPPC64CALLtail: + s.TailCall(v) + case ssa.OpPPC64CALLclosure, ssa.OpPPC64CALLinter: p := s.Prog(ppc64.AMOVD) p.From.Type = obj.TYPE_REG @@ -1980,14 +1983,9 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) { p.To.Type = obj.TYPE_BRANCH s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()}) } - case ssa.BlockExit: + case ssa.BlockExit, ssa.BlockRetJmp: case ssa.BlockRet: s.Prog(obj.ARET) - case ssa.BlockRetJmp: - p := s.Prog(obj.AJMP) - p.To.Type = obj.TYPE_MEM - p.To.Name = obj.NAME_EXTERN - p.To.Sym = b.Aux.(*obj.LSym) case ssa.BlockPPC64EQ, ssa.BlockPPC64NE, ssa.BlockPPC64LT, ssa.BlockPPC64GE, diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index f42bb338d0..6dbe3cb455 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -7,7 +7,6 @@ package reflectdata import ( "encoding/binary" "fmt" - "internal/buildcfg" "os" "sort" "strings" @@ -1869,15 +1868,11 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy // Disable tailcall for RegabiArgs for now. The IR does not connect the // arguments with the OTAILCALL node, and the arguments are not marshaled // correctly. - if !base.Flag.Cfg.Instrumenting && rcvr.IsPtr() && methodrcvr.IsPtr() && method.Embedded != 0 && !types.IsInterfaceMethod(method.Type) && !(base.Ctxt.Arch.Name == "ppc64le" && base.Ctxt.Flag_dynlink) && !buildcfg.Experiment.RegabiArgs && !generic { - // generate tail call: adjust pointer receiver and jump to embedded method. - left := dot.X // skip final .M - if !left.Type().IsPtr() { - left = typecheck.NodAddr(left) - } - as := ir.NewAssignStmt(base.Pos, nthis, typecheck.ConvNop(left, rcvr)) - fn.Body.Append(as) - fn.Body.Append(ir.NewTailCallStmt(base.Pos, method.Nname.(*ir.Name))) + if !base.Flag.Cfg.Instrumenting && rcvr.IsPtr() && methodrcvr.IsPtr() && method.Embedded != 0 && !types.IsInterfaceMethod(method.Type) && !(base.Ctxt.Arch.Name == "ppc64le" && base.Ctxt.Flag_dynlink) && !generic { + call := ir.NewCallExpr(base.Pos, ir.OCALL, dot, nil) + call.Args = ir.ParamNames(tfn.Type()) + call.IsDDD = tfn.Type().IsVariadic() + fn.Body.Append(ir.NewTailCallStmt(base.Pos, call)) } else { fn.SetWrapper(true) // ignore frame for panic+recover matching var call *ir.CallExpr diff --git a/src/cmd/compile/internal/riscv64/ssa.go b/src/cmd/compile/internal/riscv64/ssa.go index e400ca1ffe..1359b6a0c3 100644 --- a/src/cmd/compile/internal/riscv64/ssa.go +++ b/src/cmd/compile/internal/riscv64/ssa.go @@ -413,6 +413,8 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.To.Reg = v.Reg() case ssa.OpRISCV64CALLstatic, ssa.OpRISCV64CALLclosure, ssa.OpRISCV64CALLinter: s.Call(v) + case ssa.OpRISCV64CALLtail: + s.TailCall(v) case ssa.OpRISCV64LoweredWB: p := s.Prog(obj.ACALL) p.To.Type = obj.TYPE_MEM @@ -725,14 +727,9 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) { p.To.Type = obj.TYPE_BRANCH s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()}) } - case ssa.BlockExit: + case ssa.BlockExit, ssa.BlockRetJmp: case ssa.BlockRet: s.Prog(obj.ARET) - case ssa.BlockRetJmp: - p := s.Prog(obj.ARET) - p.To.Type = obj.TYPE_MEM - p.To.Name = obj.NAME_EXTERN - p.To.Sym = b.Aux.(*obj.LSym) case ssa.BlockRISCV64BEQ, ssa.BlockRISCV64BEQZ, ssa.BlockRISCV64BNE, ssa.BlockRISCV64BNEZ, ssa.BlockRISCV64BLT, ssa.BlockRISCV64BLEZ, ssa.BlockRISCV64BGE, ssa.BlockRISCV64BGEZ, ssa.BlockRISCV64BLTZ, ssa.BlockRISCV64BGTZ, ssa.BlockRISCV64BLTU, ssa.BlockRISCV64BGEU: diff --git a/src/cmd/compile/internal/s390x/ssa.go b/src/cmd/compile/internal/s390x/ssa.go index ddc05b36ad..deb6c79006 100644 --- a/src/cmd/compile/internal/s390x/ssa.go +++ b/src/cmd/compile/internal/s390x/ssa.go @@ -556,6 +556,8 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.To.Reg = v.Reg() case ssa.OpS390XCALLstatic, ssa.OpS390XCALLclosure, ssa.OpS390XCALLinter: s.Call(v) + case ssa.OpS390XCALLtail: + s.TailCall(v) case ssa.OpS390XLoweredWB: p := s.Prog(obj.ACALL) p.To.Type = obj.TYPE_MEM @@ -899,17 +901,11 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) { s.Br(s390x.ABR, b.Succs[0].Block()) } return - case ssa.BlockExit: + case ssa.BlockExit, ssa.BlockRetJmp: return case ssa.BlockRet: s.Prog(obj.ARET) return - case ssa.BlockRetJmp: - p := s.Prog(s390x.ABR) - p.To.Type = obj.TYPE_MEM - p.To.Name = obj.NAME_EXTERN - p.To.Sym = b.Aux.(*obj.LSym) - return } // Handle s390x-specific blocks. These blocks all have a diff --git a/src/cmd/compile/internal/ssa/check.go b/src/cmd/compile/internal/ssa/check.go index 969fd96dbf..28edfd2237 100644 --- a/src/cmd/compile/internal/ssa/check.go +++ b/src/cmd/compile/internal/ssa/check.go @@ -66,9 +66,6 @@ func checkFunc(f *Func) { if !b.Controls[0].Type.IsMemory() { f.Fatalf("retjmp block %s has non-memory control value %s", b, b.Controls[0].LongString()) } - if b.Aux == nil { - f.Fatalf("retjmp block %s has nil Aux field", b) - } case BlockPlain: if len(b.Succs) != 1 { f.Fatalf("plain block %s len(Succs)==%d, want 1", b, len(b.Succs)) diff --git a/src/cmd/compile/internal/ssa/expand_calls.go b/src/cmd/compile/internal/ssa/expand_calls.go index 12c7b16acd..79434f33d3 100644 --- a/src/cmd/compile/internal/ssa/expand_calls.go +++ b/src/cmd/compile/internal/ssa/expand_calls.go @@ -1082,6 +1082,12 @@ func (x *expandState) rewriteArgs(v *Value, firstArg int) { mem := m0 newArgs := []*Value{} oldArgs := []*Value{} + sp := x.sp + if v.Op == OpTailLECall { + // For tail call, we unwind the frame before the call so we'll use the caller's + // SP. + sp = x.f.Entry.NewValue0(src.NoXPos, OpGetCallerSP, x.typs.Uintptr) + } for i, a := range v.Args[firstArg : len(v.Args)-1] { // skip leading non-parameter SSA Args and trailing mem SSA Arg. oldArgs = append(oldArgs, a) auxI := int64(i) @@ -1094,7 +1100,7 @@ func (x *expandState) rewriteArgs(v *Value, firstArg int) { } // "Dereference" of addressed (probably not-SSA-eligible) value becomes Move // TODO(register args) this will be more complicated with registers in the picture. - mem = x.rewriteDereference(v.Block, x.sp, a, mem, aOffset, aux.SizeOfArg(auxI), aType, a.Pos) + mem = x.rewriteDereference(v.Block, sp, a, mem, aOffset, aux.SizeOfArg(auxI), aType, a.Pos) } else { var rc registerCursor var result *[]*Value @@ -1107,7 +1113,7 @@ func (x *expandState) rewriteArgs(v *Value, firstArg int) { if x.debug > 1 { x.Printf("...storeArg %s, %v, %d\n", a.LongString(), aType, aOffset) } - rc.init(aRegs, aux.abiInfo, result, x.sp) + rc.init(aRegs, aux.abiInfo, result, sp) mem = x.storeArgOrLoad(a.Pos, v.Block, a, mem, aType, aOffset, 0, rc) } } @@ -1207,7 +1213,7 @@ func expandCalls(f *Func) { for _, v := range b.Values { firstArg := 0 switch v.Op { - case OpStaticLECall: + case OpStaticLECall, OpTailLECall: case OpInterLECall: firstArg = 1 case OpClosureLECall: @@ -1525,6 +1531,10 @@ func expandCalls(f *Func) { v.Op = OpStaticCall rts := abi.RegisterTypes(v.Aux.(*AuxCall).abiInfo.OutParams()) v.Type = types.NewResults(append(rts, types.TypeMem)) + case OpTailLECall: + v.Op = OpTailCall + rts := abi.RegisterTypes(v.Aux.(*AuxCall).abiInfo.OutParams()) + v.Type = types.NewResults(append(rts, types.TypeMem)) case OpClosureLECall: v.Op = OpClosureCall rts := abi.RegisterTypes(v.Aux.(*AuxCall).abiInfo.OutParams()) diff --git a/src/cmd/compile/internal/ssa/gen/386.rules b/src/cmd/compile/internal/ssa/gen/386.rules index 199b73c42f..7bdebedafe 100644 --- a/src/cmd/compile/internal/ssa/gen/386.rules +++ b/src/cmd/compile/internal/ssa/gen/386.rules @@ -317,6 +317,7 @@ (StaticCall ...) => (CALLstatic ...) (ClosureCall ...) => (CALLclosure ...) (InterCall ...) => (CALLinter ...) +(TailCall ...) => (CALLtail ...) // Miscellaneous (IsNonNil p) => (SETNE (TESTL p p)) diff --git a/src/cmd/compile/internal/ssa/gen/386Ops.go b/src/cmd/compile/internal/ssa/gen/386Ops.go index 91f33c8374..3512d60865 100644 --- a/src/cmd/compile/internal/ssa/gen/386Ops.go +++ b/src/cmd/compile/internal/ssa/gen/386Ops.go @@ -455,6 +455,7 @@ func init() { }, {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLtail", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // tail call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("DX"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 5b127c98e7..bfed3bc7fd 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -408,6 +408,7 @@ (StaticCall ...) => (CALLstatic ...) (ClosureCall ...) => (CALLclosure ...) (InterCall ...) => (CALLinter ...) +(TailCall ...) => (CALLtail ...) // Lowering conditional moves // If the condition is a SETxx, we can just run a CMOV from the comparison that was diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index 52ea7ac5e0..51cbf5f78a 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -765,6 +765,7 @@ func init() { // With a register ABI, the actual register info for these instructions (i.e., what is used in regalloc) is augmented with per-call-site bindings of additional arguments to specific in and out registers. {name: "CALLstatic", argLength: -1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). last arg=mem, auxint=argsize, returns mem + {name: "CALLtail", argLength: -1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // tail call static function aux.(*obj.LSym). last arg=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: -1, reg: regInfo{inputs: []regMask{gpsp, buildReg("DX"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, last arg=mem, auxint=argsize, returns mem {name: "CALLinter", argLength: -1, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, last arg=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/ARM.rules b/src/cmd/compile/internal/ssa/gen/ARM.rules index bcacbafe3a..bfb97e5271 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM.rules @@ -351,6 +351,7 @@ (StaticCall ...) => (CALLstatic ...) (ClosureCall ...) => (CALLclosure ...) (InterCall ...) => (CALLinter ...) +(TailCall ...) => (CALLtail ...) // checks (NilCheck ...) => (LoweredNilCheck ...) diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index d99487c31b..7f9d5ec2bd 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -503,6 +503,7 @@ (StaticCall ...) => (CALLstatic ...) (ClosureCall ...) => (CALLclosure ...) (InterCall ...) => (CALLinter ...) +(TailCall ...) => (CALLtail ...) // checks (NilCheck ...) => (LoweredNilCheck ...) diff --git a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go index acfb2880c2..41231fb809 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go @@ -484,6 +484,7 @@ func init() { // function calls {name: "CALLstatic", argLength: -1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). last arg=mem, auxint=argsize, returns mem + {name: "CALLtail", argLength: -1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // tail call static function aux.(*obj.LSym). last arg=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: -1, reg: regInfo{inputs: []regMask{gpsp, buildReg("R26"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, last arg=mem, auxint=argsize, returns mem {name: "CALLinter", argLength: -1, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, last arg=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/ARMOps.go b/src/cmd/compile/internal/ssa/gen/ARMOps.go index d1f86039a3..eea0703f2c 100644 --- a/src/cmd/compile/internal/ssa/gen/ARMOps.go +++ b/src/cmd/compile/internal/ssa/gen/ARMOps.go @@ -431,6 +431,7 @@ func init() { // function calls {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLtail", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // tail call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R7"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/MIPS.rules b/src/cmd/compile/internal/ssa/gen/MIPS.rules index 4ac9668ea9..639dda4b07 100644 --- a/src/cmd/compile/internal/ssa/gen/MIPS.rules +++ b/src/cmd/compile/internal/ssa/gen/MIPS.rules @@ -334,6 +334,7 @@ (StaticCall ...) => (CALLstatic ...) (ClosureCall ...) => (CALLclosure ...) (InterCall ...) => (CALLinter ...) +(TailCall ...) => (CALLtail ...) // atomic intrinsics (AtomicLoad(8|32) ...) => (LoweredAtomicLoad(8|32) ...) diff --git a/src/cmd/compile/internal/ssa/gen/MIPS64.rules b/src/cmd/compile/internal/ssa/gen/MIPS64.rules index fd04a6c3a8..292ff2fc79 100644 --- a/src/cmd/compile/internal/ssa/gen/MIPS64.rules +++ b/src/cmd/compile/internal/ssa/gen/MIPS64.rules @@ -379,6 +379,7 @@ (StaticCall ...) => (CALLstatic ...) (ClosureCall ...) => (CALLclosure ...) (InterCall ...) => (CALLinter ...) +(TailCall ...) => (CALLtail ...) // atomic intrinsics (AtomicLoad(8|32|64) ...) => (LoweredAtomicLoad(8|32|64) ...) diff --git a/src/cmd/compile/internal/ssa/gen/MIPS64Ops.go b/src/cmd/compile/internal/ssa/gen/MIPS64Ops.go index a18cd4289d..54c0741efd 100644 --- a/src/cmd/compile/internal/ssa/gen/MIPS64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/MIPS64Ops.go @@ -276,6 +276,7 @@ func init() { // function calls {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLtail", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // tail call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R22"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/MIPSOps.go b/src/cmd/compile/internal/ssa/gen/MIPSOps.go index 8177c7e2d1..5f73e9f2dc 100644 --- a/src/cmd/compile/internal/ssa/gen/MIPSOps.go +++ b/src/cmd/compile/internal/ssa/gen/MIPSOps.go @@ -258,6 +258,7 @@ func init() { // function calls {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLtail", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // tail call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R22"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/PPC64.rules b/src/cmd/compile/internal/ssa/gen/PPC64.rules index ce4b324b5e..411bb8d29d 100644 --- a/src/cmd/compile/internal/ssa/gen/PPC64.rules +++ b/src/cmd/compile/internal/ssa/gen/PPC64.rules @@ -670,6 +670,7 @@ (StaticCall ...) => (CALLstatic ...) (ClosureCall ...) => (CALLclosure ...) (InterCall ...) => (CALLinter ...) +(TailCall ...) => (CALLtail ...) // Miscellaneous (GetClosurePtr ...) => (LoweredGetClosurePtr ...) diff --git a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go index d7d8a33a0a..a14d9cd490 100644 --- a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go @@ -429,6 +429,7 @@ func init() { {name: "LoweredRound64F", argLength: 1, reg: fp11, resultInArg0: true, zeroWidth: true}, {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLtail", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // tail call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{callptr, ctxt, 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{callptr}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64.rules b/src/cmd/compile/internal/ssa/gen/RISCV64.rules index aa7c452d05..4290d1b85c 100644 --- a/src/cmd/compile/internal/ssa/gen/RISCV64.rules +++ b/src/cmd/compile/internal/ssa/gen/RISCV64.rules @@ -546,6 +546,7 @@ (StaticCall ...) => (CALLstatic ...) (ClosureCall ...) => (CALLclosure ...) (InterCall ...) => (CALLinter ...) +(TailCall ...) => (CALLtail ...) // Atomic Intrinsics (AtomicLoad8 ...) => (LoweredAtomicLoad8 ...) diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go index ac1bcd2a06..8a3fdf75f7 100644 --- a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go @@ -241,6 +241,7 @@ func init() { // Calls {name: "CALLstatic", argLength: 1, reg: call, aux: "CallOff", call: true}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem + {name: "CALLtail", argLength: 1, reg: call, aux: "CallOff", call: true}, // tail call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: 3, reg: callClosure, aux: "CallOff", call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "CALLinter", argLength: 2, reg: callInter, aux: "CallOff", call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/S390X.rules b/src/cmd/compile/internal/ssa/gen/S390X.rules index 88762f7045..b3928c6a1e 100644 --- a/src/cmd/compile/internal/ssa/gen/S390X.rules +++ b/src/cmd/compile/internal/ssa/gen/S390X.rules @@ -434,6 +434,7 @@ (StaticCall ...) => (CALLstatic ...) (ClosureCall ...) => (CALLclosure ...) (InterCall ...) => (CALLinter ...) +(TailCall ...) => (CALLtail ...) // Miscellaneous (IsNonNil p) => (LOCGR {s390x.NotEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPconst p [0])) diff --git a/src/cmd/compile/internal/ssa/gen/S390XOps.go b/src/cmd/compile/internal/ssa/gen/S390XOps.go index 00fce8e0e5..9b6ac2bfb6 100644 --- a/src/cmd/compile/internal/ssa/gen/S390XOps.go +++ b/src/cmd/compile/internal/ssa/gen/S390XOps.go @@ -480,6 +480,7 @@ func init() { {name: "CLEAR", argLength: 2, reg: regInfo{inputs: []regMask{ptr, 0}}, asm: "CLEAR", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Write"}, {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLtail", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // tail call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{ptrsp, buildReg("R12"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{ptr}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/Wasm.rules b/src/cmd/compile/internal/ssa/gen/Wasm.rules index 7ad3d1c72e..9e683b116c 100644 --- a/src/cmd/compile/internal/ssa/gen/Wasm.rules +++ b/src/cmd/compile/internal/ssa/gen/Wasm.rules @@ -307,6 +307,7 @@ (StaticCall ...) => (LoweredStaticCall ...) (ClosureCall ...) => (LoweredClosureCall ...) (InterCall ...) => (LoweredInterCall ...) +(TailCall ...) => (LoweredTailCall ...) // Miscellaneous (Convert ...) => (LoweredConvert ...) diff --git a/src/cmd/compile/internal/ssa/gen/WasmOps.go b/src/cmd/compile/internal/ssa/gen/WasmOps.go index 7f7ae5e837..0d7327109a 100644 --- a/src/cmd/compile/internal/ssa/gen/WasmOps.go +++ b/src/cmd/compile/internal/ssa/gen/WasmOps.go @@ -124,6 +124,7 @@ func init() { var WasmOps = []opData{ {name: "LoweredStaticCall", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "LoweredTailCall", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", call: true}, // tail call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem {name: "LoweredClosureCall", argLength: 3, reg: regInfo{inputs: []regMask{gp, gp, 0}, clobbers: callerSave}, aux: "CallOff", call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "LoweredInterCall", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index c183aedf2d..a0166f58f4 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -417,10 +417,12 @@ var genericOps = []opData{ {name: "ClosureCall", argLength: -1, aux: "CallOff", call: true}, // arg0=code pointer, arg1=context ptr, arg2..argN-1 are register inputs, argN=memory. auxint=arg size. Returns Result of register results, plus memory. {name: "StaticCall", argLength: -1, aux: "CallOff", call: true}, // call function aux.(*obj.LSym), arg0..argN-1 are register inputs, argN=memory. auxint=arg size. Returns Result of register results, plus memory. {name: "InterCall", argLength: -1, aux: "CallOff", call: true}, // interface call. arg0=code pointer, arg1..argN-1 are register inputs, argN=memory, auxint=arg size. Returns Result of register results, plus memory. + {name: "TailCall", argLength: -1, aux: "CallOff", call: true}, // tail call function aux.(*obj.LSym), arg0..argN-1 are register inputs, argN=memory. auxint=arg size. Returns Result of register results, plus memory. {name: "ClosureLECall", argLength: -1, aux: "CallOff", call: true}, // late-expanded closure call. arg0=code pointer, arg1=context ptr, arg2..argN-1 are inputs, argN is mem. auxint = arg size. Result is tuple of result(s), plus mem. {name: "StaticLECall", argLength: -1, aux: "CallOff", call: true}, // late-expanded static call function aux.(*ssa.AuxCall.Fn). arg0..argN-1 are inputs, argN is mem. auxint = arg size. Result is tuple of result(s), plus mem. {name: "InterLECall", argLength: -1, aux: "CallOff", call: true}, // late-expanded interface call. arg0=code pointer, arg1..argN-1 are inputs, argN is mem. auxint = arg size. Result is tuple of result(s), plus mem. + {name: "TailLECall", argLength: -1, aux: "CallOff", call: true}, // late-expanded static tail call function aux.(*ssa.AuxCall.Fn). arg0..argN-1 are inputs, argN is mem. auxint = arg size. Result is tuple of result(s), plus mem. // Conversions: signed extensions, zero (unsigned) extensions, truncations {name: "SignExt8to16", argLength: 1, typ: "Int16"}, @@ -638,7 +640,7 @@ var genericBlocks = []blockData{ {name: "If", controls: 1}, // if Controls[0] goto Succs[0] else goto Succs[1] {name: "Defer", controls: 1}, // Succs[0]=defer queued, Succs[1]=defer recovered. Controls[0] is call op (of memory type) {name: "Ret", controls: 1}, // no successors, Controls[0] value is memory result - {name: "RetJmp", controls: 1}, // no successors, Controls[0] value is memory result, jumps to b.Aux.(*gc.Sym) + {name: "RetJmp", controls: 1}, // no successors, Controls[0] value is a tail call {name: "Exit", controls: 1}, // no successors, Controls[0] value generates a panic // transient block state used for dead code removal diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 1ca99c1ba9..4ec13a6629 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -515,6 +515,7 @@ const ( Op386DUFFZERO Op386REPSTOSL Op386CALLstatic + Op386CALLtail Op386CALLclosure Op386CALLinter Op386DUFFCOPY @@ -993,6 +994,7 @@ const ( OpAMD64DUFFZERO OpAMD64REPSTOSQ OpAMD64CALLstatic + OpAMD64CALLtail OpAMD64CALLclosure OpAMD64CALLinter OpAMD64DUFFCOPY @@ -1269,6 +1271,7 @@ const ( OpARMCMOVWLSconst OpARMSRAcond OpARMCALLstatic + OpARMCALLtail OpARMCALLclosure OpARMCALLinter OpARMLoweredNilCheck @@ -1552,6 +1555,7 @@ const ( OpARM64CSNEG OpARM64CSETM OpARM64CALLstatic + OpARM64CALLtail OpARM64CALLclosure OpARM64CALLinter OpARM64LoweredNilCheck @@ -1697,6 +1701,7 @@ const ( OpMIPSMOVFD OpMIPSMOVDF OpMIPSCALLstatic + OpMIPSCALLtail OpMIPSCALLclosure OpMIPSCALLinter OpMIPSLoweredAtomicLoad8 @@ -1813,6 +1818,7 @@ const ( OpMIPS64MOVFD OpMIPS64MOVDF OpMIPS64CALLstatic + OpMIPS64CALLtail OpMIPS64CALLclosure OpMIPS64CALLinter OpMIPS64DUFFZERO @@ -2025,6 +2031,7 @@ const ( OpPPC64LoweredRound32F OpPPC64LoweredRound64F OpPPC64CALLstatic + OpPPC64CALLtail OpPPC64CALLclosure OpPPC64CALLinter OpPPC64LoweredZero @@ -2128,6 +2135,7 @@ const ( OpRISCV64SLTIU OpRISCV64MOVconvert OpRISCV64CALLstatic + OpRISCV64CALLtail OpRISCV64CALLclosure OpRISCV64CALLinter OpRISCV64DUFFZERO @@ -2386,6 +2394,7 @@ const ( OpS390XMOVDstoreconst OpS390XCLEAR OpS390XCALLstatic + OpS390XCALLtail OpS390XCALLclosure OpS390XCALLinter OpS390XInvertFlags @@ -2439,6 +2448,7 @@ const ( OpS390XLoweredZero OpWasmLoweredStaticCall + OpWasmLoweredTailCall OpWasmLoweredClosureCall OpWasmLoweredInterCall OpWasmLoweredAddr @@ -2785,9 +2795,11 @@ const ( OpClosureCall OpStaticCall OpInterCall + OpTailCall OpClosureLECall OpStaticLECall OpInterLECall + OpTailLECall OpSignExt8to16 OpSignExt8to32 OpSignExt8to64 @@ -5906,6 +5918,16 @@ var opcodeTable = [...]opInfo{ clobbers: 65519, // AX CX DX BX BP SI DI X0 X1 X2 X3 X4 X5 X6 X7 }, }, + { + name: "CALLtail", + auxType: auxCallOff, + argLen: 1, + clobberFlags: true, + call: true, + reg: regInfo{ + clobbers: 65519, // AX CX DX BX BP SI DI X0 X1 X2 X3 X4 X5 X6 X7 + }, + }, { name: "CALLclosure", auxType: auxCallOff, @@ -13103,6 +13125,16 @@ var opcodeTable = [...]opInfo{ clobbers: 2147483631, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 g R15 X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 }, }, + { + name: "CALLtail", + auxType: auxCallOff, + argLen: -1, + clobberFlags: true, + call: true, + reg: regInfo{ + clobbers: 2147483631, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 g R15 X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 + }, + }, { name: "CALLclosure", auxType: auxCallOff, @@ -16939,6 +16971,16 @@ var opcodeTable = [...]opInfo{ clobbers: 4294924287, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 }, }, + { + name: "CALLtail", + auxType: auxCallOff, + argLen: 1, + clobberFlags: true, + call: true, + reg: regInfo{ + clobbers: 4294924287, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 + }, + }, { name: "CALLclosure", auxType: auxCallOff, @@ -20706,6 +20748,16 @@ var opcodeTable = [...]opInfo{ clobbers: 9223372035512336383, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, }, + { + name: "CALLtail", + auxType: auxCallOff, + argLen: -1, + clobberFlags: true, + call: true, + reg: regInfo{ + clobbers: 9223372035512336383, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + }, + }, { name: "CALLclosure", auxType: auxCallOff, @@ -22639,6 +22691,16 @@ var opcodeTable = [...]opInfo{ clobbers: 140737421246462, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31 F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30 HI LO }, }, + { + name: "CALLtail", + auxType: auxCallOff, + argLen: 1, + clobberFlags: true, + call: true, + reg: regInfo{ + clobbers: 140737421246462, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31 F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30 HI LO + }, + }, { name: "CALLclosure", auxType: auxCallOff, @@ -24198,6 +24260,16 @@ var opcodeTable = [...]opInfo{ clobbers: 4611686018393833470, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 HI LO }, }, + { + name: "CALLtail", + auxType: auxCallOff, + argLen: 1, + clobberFlags: true, + call: true, + reg: regInfo{ + clobbers: 4611686018393833470, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 HI LO + }, + }, { name: "CALLclosure", auxType: auxCallOff, @@ -27026,6 +27098,16 @@ var opcodeTable = [...]opInfo{ clobbers: 576460745860964344, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 g F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 }, }, + { + name: "CALLtail", + auxType: auxCallOff, + argLen: 1, + clobberFlags: true, + call: true, + reg: regInfo{ + clobbers: 576460745860964344, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 g F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 + }, + }, { name: "CALLclosure", auxType: auxCallOff, @@ -28432,6 +28514,15 @@ var opcodeTable = [...]opInfo{ clobbers: 9223372035781033972, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, }, + { + name: "CALLtail", + auxType: auxCallOff, + argLen: 1, + call: true, + reg: regInfo{ + clobbers: 9223372035781033972, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + }, + }, { name: "CALLclosure", auxType: auxCallOff, @@ -32187,6 +32278,16 @@ var opcodeTable = [...]opInfo{ clobbers: 4294933503, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 g R14 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 }, }, + { + name: "CALLtail", + auxType: auxCallOff, + argLen: 1, + clobberFlags: true, + call: true, + reg: regInfo{ + clobbers: 4294933503, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 g R14 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 + }, + }, { name: "CALLclosure", auxType: auxCallOff, @@ -32857,6 +32958,15 @@ var opcodeTable = [...]opInfo{ clobbers: 844424930131967, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 g }, }, + { + name: "LoweredTailCall", + auxType: auxCallOff, + argLen: 1, + call: true, + reg: regInfo{ + clobbers: 844424930131967, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 g + }, + }, { name: "LoweredClosureCall", auxType: auxCallOff, @@ -35633,6 +35743,13 @@ var opcodeTable = [...]opInfo{ call: true, generic: true, }, + { + name: "TailCall", + auxType: auxCallOff, + argLen: -1, + call: true, + generic: true, + }, { name: "ClosureLECall", auxType: auxCallOff, @@ -35654,6 +35771,13 @@ var opcodeTable = [...]opInfo{ call: true, generic: true, }, + { + name: "TailLECall", + auxType: auxCallOff, + argLen: -1, + call: true, + generic: true, + }, { name: "SignExt8to16", argLen: 1, diff --git a/src/cmd/compile/internal/ssa/rewrite386.go b/src/cmd/compile/internal/ssa/rewrite386.go index 1ec2d26f75..34f37867cf 100644 --- a/src/cmd/compile/internal/ssa/rewrite386.go +++ b/src/cmd/compile/internal/ssa/rewrite386.go @@ -652,6 +652,9 @@ func rewriteValue386(v *Value) bool { case OpSubPtr: v.Op = Op386SUBL return true + case OpTailCall: + v.Op = Op386CALLtail + return true case OpTrunc16to8: v.Op = OpCopy return true diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index aa9293e347..e20161c920 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -1103,6 +1103,9 @@ func rewriteValueAMD64(v *Value) bool { case OpSubPtr: v.Op = OpAMD64SUBQ return true + case OpTailCall: + v.Op = OpAMD64CALLtail + return true case OpTrunc: return rewriteValueAMD64_OpTrunc(v) case OpTrunc16to8: diff --git a/src/cmd/compile/internal/ssa/rewriteARM.go b/src/cmd/compile/internal/ssa/rewriteARM.go index febb5566e3..3d2f862705 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM.go +++ b/src/cmd/compile/internal/ssa/rewriteARM.go @@ -855,6 +855,9 @@ func rewriteValueARM(v *Value) bool { case OpSubPtr: v.Op = OpARMSUB return true + case OpTailCall: + v.Op = OpARMCALLtail + return true case OpTrunc16to8: v.Op = OpCopy return true diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index 83dd771436..3df84e161a 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -1042,6 +1042,9 @@ func rewriteValueARM64(v *Value) bool { case OpSubPtr: v.Op = OpARM64SUB return true + case OpTailCall: + v.Op = OpARM64CALLtail + return true case OpTrunc: v.Op = OpARM64FRINTZD return true diff --git a/src/cmd/compile/internal/ssa/rewriteMIPS.go b/src/cmd/compile/internal/ssa/rewriteMIPS.go index 429369d631..811ea9d9d3 100644 --- a/src/cmd/compile/internal/ssa/rewriteMIPS.go +++ b/src/cmd/compile/internal/ssa/rewriteMIPS.go @@ -544,6 +544,9 @@ func rewriteValueMIPS(v *Value) bool { case OpSubPtr: v.Op = OpMIPSSUB return true + case OpTailCall: + v.Op = OpMIPSCALLtail + return true case OpTrunc16to8: v.Op = OpCopy return true diff --git a/src/cmd/compile/internal/ssa/rewriteMIPS64.go b/src/cmd/compile/internal/ssa/rewriteMIPS64.go index 772d7b66ef..1fbd556b5c 100644 --- a/src/cmd/compile/internal/ssa/rewriteMIPS64.go +++ b/src/cmd/compile/internal/ssa/rewriteMIPS64.go @@ -625,6 +625,9 @@ func rewriteValueMIPS64(v *Value) bool { case OpSubPtr: v.Op = OpMIPS64SUBV return true + case OpTailCall: + v.Op = OpMIPS64CALLtail + return true case OpTrunc16to8: v.Op = OpCopy return true diff --git a/src/cmd/compile/internal/ssa/rewritePPC64.go b/src/cmd/compile/internal/ssa/rewritePPC64.go index 96dee0bd21..b35331a624 100644 --- a/src/cmd/compile/internal/ssa/rewritePPC64.go +++ b/src/cmd/compile/internal/ssa/rewritePPC64.go @@ -772,6 +772,9 @@ func rewriteValuePPC64(v *Value) bool { case OpSubPtr: v.Op = OpPPC64SUB return true + case OpTailCall: + v.Op = OpPPC64CALLtail + return true case OpTrunc: v.Op = OpPPC64FTRUNC return true diff --git a/src/cmd/compile/internal/ssa/rewriteRISCV64.go b/src/cmd/compile/internal/ssa/rewriteRISCV64.go index 3a277ca369..f856a26d49 100644 --- a/src/cmd/compile/internal/ssa/rewriteRISCV64.go +++ b/src/cmd/compile/internal/ssa/rewriteRISCV64.go @@ -639,6 +639,9 @@ func rewriteValueRISCV64(v *Value) bool { case OpSubPtr: v.Op = OpRISCV64SUB return true + case OpTailCall: + v.Op = OpRISCV64CALLtail + return true case OpTrunc16to8: v.Op = OpCopy return true diff --git a/src/cmd/compile/internal/ssa/rewriteS390X.go b/src/cmd/compile/internal/ssa/rewriteS390X.go index 8b41d62c31..0d63586149 100644 --- a/src/cmd/compile/internal/ssa/rewriteS390X.go +++ b/src/cmd/compile/internal/ssa/rewriteS390X.go @@ -819,6 +819,9 @@ func rewriteValueS390X(v *Value) bool { case OpSubPtr: v.Op = OpS390XSUB return true + case OpTailCall: + v.Op = OpS390XCALLtail + return true case OpTrunc: return rewriteValueS390X_OpTrunc(v) case OpTrunc16to8: diff --git a/src/cmd/compile/internal/ssa/rewriteWasm.go b/src/cmd/compile/internal/ssa/rewriteWasm.go index 5dab09f85b..defd40ddd1 100644 --- a/src/cmd/compile/internal/ssa/rewriteWasm.go +++ b/src/cmd/compile/internal/ssa/rewriteWasm.go @@ -556,6 +556,9 @@ func rewriteValueWasm(v *Value) bool { case OpSubPtr: v.Op = OpWasmI64Sub return true + case OpTailCall: + v.Op = OpWasmLoweredTailCall + return true case OpTrunc: v.Op = OpWasmF64Trunc return true diff --git a/src/cmd/compile/internal/ssa/writebarrier.go b/src/cmd/compile/internal/ssa/writebarrier.go index d7510965f6..52f060b601 100644 --- a/src/cmd/compile/internal/ssa/writebarrier.go +++ b/src/cmd/compile/internal/ssa/writebarrier.go @@ -544,7 +544,7 @@ func IsStackAddr(v *Value) bool { v = v.Args[0] } switch v.Op { - case OpSP, OpLocalAddr, OpSelectNAddr: + case OpSP, OpLocalAddr, OpSelectNAddr, OpGetCallerSP: return true } return false diff --git a/src/cmd/compile/internal/ssagen/abi.go b/src/cmd/compile/internal/ssagen/abi.go index 6d8c53e722..c54a734c75 100644 --- a/src/cmd/compile/internal/ssagen/abi.go +++ b/src/cmd/compile/internal/ssagen/abi.go @@ -382,18 +382,16 @@ func makeABIWrapper(f *ir.Func, wrapperABI obj.ABI) { } var tail ir.Node + call := ir.NewCallExpr(base.Pos, ir.OCALL, f.Nname, nil) + call.Args = ir.ParamNames(tfn.Type()) + call.IsDDD = tfn.Type().IsVariadic() + tail = call if tailcall { - tail = ir.NewTailCallStmt(base.Pos, f.Nname) - } else { - call := ir.NewCallExpr(base.Pos, ir.OCALL, f.Nname, nil) - call.Args = ir.ParamNames(tfn.Type()) - call.IsDDD = tfn.Type().IsVariadic() - tail = call - if tfn.Type().NumResults() > 0 { - n := ir.NewReturnStmt(base.Pos, nil) - n.Results = []ir.Node{call} - tail = n - } + tail = ir.NewTailCallStmt(base.Pos, call) + } else if tfn.Type().NumResults() > 0 { + n := ir.NewReturnStmt(base.Pos, nil) + n.Results = []ir.Node{call} + tail = n } fn.Body.Append(tail) diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 1e7eda94fc..346a801508 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -1696,9 +1696,11 @@ func (s *state) stmt(n ir.Node) { case ir.OTAILCALL: n := n.(*ir.TailCallStmt) - b := s.exit() - b.Kind = ssa.BlockRetJmp // override BlockRet - b.Aux = callTargetLSym(n.Target) + s.callResult(n.Call, callTail) + call := s.mem() + b := s.endBlock() + b.Kind = ssa.BlockRetJmp // could use BlockExit. BlockRetJmp is mostly for clarity. + b.SetControl(call) case ir.OCONTINUE, ir.OBREAK: n := n.(*ir.BranchStmt) @@ -3645,6 +3647,7 @@ const ( callDefer callDeferStack callGo + callTail ) type sfRtCallDef struct { @@ -4911,13 +4914,13 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val } } - if k != callNormal && (len(n.Args) != 0 || n.Op() == ir.OCALLINTER || n.X.Type().NumResults() != 0) { + if k != callNormal && k != callTail && (len(n.Args) != 0 || n.Op() == ir.OCALLINTER || n.X.Type().NumResults() != 0) { s.Fatalf("go/defer call with arguments: %v", n) } switch n.Op() { case ir.OCALLFUNC: - if k == callNormal && fn.Op() == ir.ONAME && fn.(*ir.Name).Class == ir.PFUNC { + if (k == callNormal || k == callTail) && fn.Op() == ir.ONAME && fn.(*ir.Name).Class == ir.PFUNC { fn := fn.(*ir.Name) callee = fn if buildcfg.Experiment.RegabiArgs { @@ -4971,7 +4974,7 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val stksize := params.ArgWidth() // includes receiver, args, and results res := n.X.Type().Results() - if k == callNormal { + if k == callNormal || k == callTail { for _, p := range params.OutParams() { ACResults = append(ACResults, p.Type) } @@ -5018,7 +5021,7 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val // These are written in SP-offset order. argStart := base.Ctxt.FixedFrameSize() // Defer/go args. - if k != callNormal { + if k != callNormal && k != callTail { // Write closure (arg to newproc/deferproc). ACArgs = append(ACArgs, types.Types[types.TUINTPTR]) // not argExtra callArgs = append(callArgs, closure) @@ -5068,6 +5071,10 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val case callee != nil: aux := ssa.StaticAuxCall(callTargetLSym(callee), params) call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux) + if k == callTail { + call.Op = ssa.OpTailLECall + stksize = 0 // Tail call does not use stack. We reuse caller's frame. + } default: s.Fatalf("bad call type %v %v", n.Op(), n) } @@ -7399,6 +7406,14 @@ func (s *State) Call(v *ssa.Value) *obj.Prog { return p } +// TailCall returns a new tail call instruction for the SSA value v. +// It is like Call, but for a tail call. +func (s *State) TailCall(v *ssa.Value) *obj.Prog { + p := s.Call(v) + p.As = obj.ARET + return p +} + // PrepareCall prepares to emit a CALL instruction for v and does call-related bookkeeping. // It must be called immediately before emitting the actual CALL instruction, // since it emits PCDATA for the stack map at the call (calls are safe points). diff --git a/src/cmd/compile/internal/typecheck/typecheck.go b/src/cmd/compile/internal/typecheck/typecheck.go index 404af5b1b2..42970f6a5e 100644 --- a/src/cmd/compile/internal/typecheck/typecheck.go +++ b/src/cmd/compile/internal/typecheck/typecheck.go @@ -879,6 +879,7 @@ func typecheck1(n ir.Node, top int) ir.Node { case ir.OTAILCALL: n := n.(*ir.TailCallStmt) + n.Call = typecheck(n.Call, ctxStmt|ctxExpr).(*ir.CallExpr) return n case ir.OCHECKNIL: diff --git a/src/cmd/compile/internal/walk/stmt.go b/src/cmd/compile/internal/walk/stmt.go index 4581bca3df..f09e916546 100644 --- a/src/cmd/compile/internal/walk/stmt.go +++ b/src/cmd/compile/internal/walk/stmt.go @@ -136,6 +136,14 @@ func walkStmt(n ir.Node) ir.Node { case ir.OTAILCALL: n := n.(*ir.TailCallStmt) + + var init ir.Nodes + n.Call.X = walkExpr(n.Call.X, &init) + + if len(init) > 0 { + init.Append(n) + return ir.NewBlockStmt(n.Pos(), init) + } return n case ir.OINLMARK: diff --git a/src/cmd/compile/internal/wasm/ssa.go b/src/cmd/compile/internal/wasm/ssa.go index 0b2ca3fdbb..765051c944 100644 --- a/src/cmd/compile/internal/wasm/ssa.go +++ b/src/cmd/compile/internal/wasm/ssa.go @@ -88,13 +88,7 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) { case ssa.BlockRet: s.Prog(obj.ARET) - case ssa.BlockRetJmp: - p := s.Prog(obj.ARET) - p.To.Type = obj.TYPE_MEM - p.To.Name = obj.NAME_EXTERN - p.To.Sym = b.Aux.(*obj.LSym) - - case ssa.BlockExit: + case ssa.BlockExit, ssa.BlockRetJmp: case ssa.BlockDefer: p := s.Prog(wasm.AGet) @@ -122,7 +116,7 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) { func ssaGenValue(s *ssagen.State, v *ssa.Value) { switch v.Op { - case ssa.OpWasmLoweredStaticCall, ssa.OpWasmLoweredClosureCall, ssa.OpWasmLoweredInterCall: + case ssa.OpWasmLoweredStaticCall, ssa.OpWasmLoweredClosureCall, ssa.OpWasmLoweredInterCall, ssa.OpWasmLoweredTailCall: s.PrepareCall(v) if call, ok := v.Aux.(*ssa.AuxCall); ok && call.Fn == ir.Syms.Deferreturn { // The runtime needs to inject jumps to @@ -141,6 +135,9 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p := s.Prog(obj.ACALL) p.To = obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_EXTERN, Sym: sym} p.Pos = v.Pos + if v.Op == ssa.OpWasmLoweredTailCall { + p.As = obj.ARET + } } else { getValue64(s, v.Args[0]) p := s.Prog(obj.ACALL) diff --git a/src/cmd/compile/internal/x86/ssa.go b/src/cmd/compile/internal/x86/ssa.go index a06fdbcb71..32e29f347b 100644 --- a/src/cmd/compile/internal/x86/ssa.go +++ b/src/cmd/compile/internal/x86/ssa.go @@ -752,6 +752,8 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { case ssa.Op386CALLstatic, ssa.Op386CALLclosure, ssa.Op386CALLinter: s.Call(v) + case ssa.Op386CALLtail: + s.TailCall(v) case ssa.Op386NEGL, ssa.Op386BSWAPL, ssa.Op386NOTL: @@ -892,14 +894,9 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) { p.To.Type = obj.TYPE_BRANCH s.Branches = append(s.Branches, ssagen.Branch{P: p, B: b.Succs[0].Block()}) } - case ssa.BlockExit: + case ssa.BlockExit, ssa.BlockRetJmp: case ssa.BlockRet: s.Prog(obj.ARET) - case ssa.BlockRetJmp: - p := s.Prog(obj.AJMP) - p.To.Type = obj.TYPE_MEM - p.To.Name = obj.NAME_EXTERN - p.To.Sym = b.Aux.(*obj.LSym) case ssa.Block386EQF: s.CombJump(b, next, &eqfJumps) diff --git a/test/abi/method_wrapper.go b/test/abi/method_wrapper.go new file mode 100644 index 0000000000..7aa262fb52 --- /dev/null +++ b/test/abi/method_wrapper.go @@ -0,0 +1,35 @@ +// run + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type S int + +type T struct { + a int + S +} + +//go:noinline +func (s *S) M(a int, x [2]int, b float64, y [2]float64) (S, int, [2]int, float64, [2]float64) { + return *s, a, x, b, y +} + +var s S = 42 +var t = &T{S: s} + +var fn = (*T).M // force a method wrapper + +func main() { + a := 123 + x := [2]int{456, 789} + b := 1.2 + y := [2]float64{3.4, 5.6} + s1, a1, x1, b1, y1 := fn(t, a, x, b, y) + if a1 != a || x1 != x || b1 != b || y1 != y || s1 != s { + panic("FAIL") + } +} -- GitLab From 07b30a4f77cf89a283c45c338f0cfcb68e15aab1 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Thu, 2 Sep 2021 08:47:40 -0700 Subject: [PATCH 1191/2500] cmd/compile: delay transformAssign if lhs/rhs have typeparam This also requires that we sometimes delay transformSelect(), if the assignments in the Comm part of the select have not been transformed. Fixes #48137 Change-Id: I163aa1f999d1e63616280dca807561b12b2aa779 Reviewed-on: https://go-review.googlesource.com/c/go/+/347915 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 3 +++ src/cmd/compile/internal/noder/stmt.go | 20 ++++++++++++++---- test/typeparam/issue48137.go | 25 +++++++++++++++++++++++ 3 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 test/typeparam/issue48137.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index e60383f4e0..e2525a8f7e 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -995,6 +995,9 @@ func (subst *subster) node(n ir.Node) ir.Node { case ir.OSEND: transformSend(m.(*ir.SendStmt)) + case ir.OSELECT: + transformSelect(m.(*ir.SelectStmt)) + } } diff --git a/src/cmd/compile/internal/noder/stmt.go b/src/cmd/compile/internal/noder/stmt.go index 7f608bb91f..aefd9fcdaa 100644 --- a/src/cmd/compile/internal/noder/stmt.go +++ b/src/cmd/compile/internal/noder/stmt.go @@ -84,13 +84,13 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { // to know the types of the left and right sides in various cases. delay := false for _, e := range lhs { - if e.Typecheck() == 3 { + if e.Type().HasTParam() || e.Typecheck() == 3 { delay = true break } } for _, e := range rhs { - if e.Typecheck() == 3 { + if e.Type().HasTParam() || e.Typecheck() == 3 { delay = true break } @@ -145,8 +145,20 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { return g.forStmt(stmt) case *syntax.SelectStmt: n := g.selectStmt(stmt) - transformSelect(n.(*ir.SelectStmt)) - n.SetTypecheck(1) + + delay := false + for _, ncase := range n.(*ir.SelectStmt).Cases { + if ncase.Comm != nil && ncase.Comm.Typecheck() == 3 { + delay = true + break + } + } + if delay { + n.SetTypecheck(3) + } else { + transformSelect(n.(*ir.SelectStmt)) + n.SetTypecheck(1) + } return n case *syntax.SwitchStmt: return g.switchStmt(stmt) diff --git a/test/typeparam/issue48137.go b/test/typeparam/issue48137.go new file mode 100644 index 0000000000..3dd7810482 --- /dev/null +++ b/test/typeparam/issue48137.go @@ -0,0 +1,25 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type Constraint[T any] interface { + ~func() T +} + +func Foo[T Constraint[T]]() T { + var t T + + t = func() T { + return t + } + return t +} + +func main() { + type Bar func() Bar + Foo[Bar]() +} -- GitLab From ac7c34767dd710643f5f5fea1720a18cc392b7f8 Mon Sep 17 00:00:00 2001 From: HowJMay Date: Thu, 16 Sep 2021 18:22:06 +0000 Subject: [PATCH 1192/2500] time: support fractional timezone minutes in MarshalBinary If the time is in 'LMT' and has fractional minute, then `MarshalBinary()` and `UnmarshalBinary()` will encode/decode the time in `timeBinaryVersionV2` in which the fractional minute is at bit 15 and 16, and presented in seconds. Fixes #39616 Change-Id: Ib762fb5fa26f54b1a8377a5dde0b994dd5a1236a GitHub-Last-Rev: 455d7a2496ba67d4a82890b14d57000e1a8a1415 GitHub-Pull-Request: golang/go#40293 Reviewed-on: https://go-review.googlesource.com/c/go/+/243402 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Carlos Amedee --- src/time/time.go | 30 ++++++++++++++++++++++++------ src/time/time_test.go | 32 +++++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/src/time/time.go b/src/time/time.go index 1919ebbc2c..edf0c62610 100644 --- a/src/time/time.go +++ b/src/time/time.go @@ -1162,19 +1162,26 @@ func (t Time) UnixNano() int64 { return (t.unixSec())*1e9 + int64(t.nsec()) } -const timeBinaryVersion byte = 1 +const ( + timeBinaryVersionV1 byte = iota + 1 // For general situation + timeBinaryVersionV2 // For LMT only +) // MarshalBinary implements the encoding.BinaryMarshaler interface. func (t Time) MarshalBinary() ([]byte, error) { var offsetMin int16 // minutes east of UTC. -1 is UTC. + var offsetSec int8 + version := timeBinaryVersionV1 if t.Location() == UTC { offsetMin = -1 } else { _, offset := t.Zone() if offset%60 != 0 { - return nil, errors.New("Time.MarshalBinary: zone offset has fractional minute") + version = timeBinaryVersionV2 + offsetSec = int8(offset % 60) } + offset /= 60 if offset < -32768 || offset == -1 || offset > 32767 { return nil, errors.New("Time.MarshalBinary: unexpected zone offset") @@ -1185,8 +1192,8 @@ func (t Time) MarshalBinary() ([]byte, error) { sec := t.sec() nsec := t.nsec() enc := []byte{ - timeBinaryVersion, // byte 0 : version - byte(sec >> 56), // bytes 1-8: seconds + version, // byte 0 : version + byte(sec >> 56), // bytes 1-8: seconds byte(sec >> 48), byte(sec >> 40), byte(sec >> 32), @@ -1201,6 +1208,9 @@ func (t Time) MarshalBinary() ([]byte, error) { byte(offsetMin >> 8), // bytes 13-14: zone offset in minutes byte(offsetMin), } + if version == timeBinaryVersionV2 { + enc = append(enc, byte(offsetSec)) + } return enc, nil } @@ -1212,11 +1222,16 @@ func (t *Time) UnmarshalBinary(data []byte) error { return errors.New("Time.UnmarshalBinary: no data") } - if buf[0] != timeBinaryVersion { + version := buf[0] + if version != timeBinaryVersionV1 && version != timeBinaryVersionV2 { return errors.New("Time.UnmarshalBinary: unsupported version") } - if len(buf) != /*version*/ 1+ /*sec*/ 8+ /*nsec*/ 4+ /*zone offset*/ 2 { + wantLen := /*version*/ 1 + /*sec*/ 8 + /*nsec*/ 4 + /*zone offset*/ 2 + if version == timeBinaryVersionV2 { + wantLen++ + } + if len(buf) != wantLen { return errors.New("Time.UnmarshalBinary: invalid length") } @@ -1229,6 +1244,9 @@ func (t *Time) UnmarshalBinary(data []byte) error { buf = buf[4:] offset := int(int16(buf[1])|int16(buf[0])<<8) * 60 + if version == timeBinaryVersionV2 { + offset += int(buf[2]) + } *t = Time{} t.wall = uint64(nsec) diff --git a/src/time/time_test.go b/src/time/time_test.go index cea5f2d3f5..e2fb897b6d 100644 --- a/src/time/time_test.go +++ b/src/time/time_test.go @@ -767,7 +767,6 @@ var notEncodableTimes = []struct { time Time want string }{ - {Date(0, 1, 2, 3, 4, 5, 6, FixedZone("", 1)), "Time.MarshalBinary: zone offset has fractional minute"}, {Date(0, 1, 2, 3, 4, 5, 6, FixedZone("", -1*60)), "Time.MarshalBinary: unexpected zone offset"}, {Date(0, 1, 2, 3, 4, 5, 6, FixedZone("", -32769*60)), "Time.MarshalBinary: unexpected zone offset"}, {Date(0, 1, 2, 3, 4, 5, 6, FixedZone("", 32768*60)), "Time.MarshalBinary: unexpected zone offset"}, @@ -1437,6 +1436,37 @@ func TestMarshalBinaryZeroTime(t *testing.T) { } } +func TestMarshalBinaryVersion2(t *testing.T) { + t0, err := Parse(RFC3339, "1880-01-01T00:00:00Z") + if err != nil { + t.Errorf("Failed to parse time, error = %v", err) + } + loc, err := LoadLocation("US/Eastern") + if err != nil { + t.Errorf("Failed to load location, error = %v", err) + } + t1 := t0.In(loc) + b, err := t1.MarshalBinary() + if err != nil { + t.Errorf("Failed to Marshal, error = %v", err) + } + + t2 := Time{} + err = t2.UnmarshalBinary(b) + if err != nil { + t.Errorf("Failed to Unmarshal, error = %v", err) + } + + if !(t0.Equal(t1) && t1.Equal(t2)) { + if !t0.Equal(t1) { + t.Errorf("The result t1: %+v after Marshal is not matched original t0: %+v", t1, t0) + } + if !t1.Equal(t2) { + t.Errorf("The result t2: %+v after Unmarshal is not matched original t1: %+v", t2, t1) + } + } +} + // Issue 17720: Zero value of time.Month fails to print func TestZeroMonthString(t *testing.T) { if got, want := Month(0).String(), "%!Month(0)"; got != want { -- GitLab From 163871feb177ca0d7c690052b4cdd17bd57fcc04 Mon Sep 17 00:00:00 2001 From: Riley Avron Date: Tue, 14 Sep 2021 18:45:53 +0000 Subject: [PATCH 1193/2500] time: re-add space-padded day of year to docs CL 320252 reworked the time docs, but accidentally deleted the format __2 from the sentence describing the three-character day of year component. Change-Id: I3f583733028657c2a677358a25e062ea81835ce8 GitHub-Last-Rev: 2fa98324191500fd6a37097a9712ae23cc509269 GitHub-Pull-Request: golang/go#48387 Reviewed-on: https://go-review.googlesource.com/c/go/+/349929 Reviewed-by: Ian Lance Taylor Trust: Carlos Amedee --- src/time/format.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/time/format.go b/src/time/format.go index c2bffb8ff6..7373892b97 100644 --- a/src/time/format.go +++ b/src/time/format.go @@ -74,7 +74,7 @@ import "errors" // for compatibility with fixed-width Unix time formats. A leading zero represents // a zero-padded value. // -// The formats and 002 are space-padded and zero-padded +// The formats __2 and 002 are space-padded and zero-padded // three-character day of year; there is no unpadded day of year format. // // A comma or decimal point followed by one or more zeros represents -- GitLab From f01721efb941edadc2e6a897e42919b0d68480e1 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 16 Sep 2021 13:55:45 -0400 Subject: [PATCH 1194/2500] cmd/compile: remove self copies in tail-call wrappers The previous CL re-enables tail calls for method wrappers. But with the changed IR and SSA representation, for stack arguments it generates self copies. This CL makes the compiler detect the self copies and remove them. Change-Id: I7252572a1a47834f28b6706e45906e2356408e02 Reviewed-on: https://go-review.googlesource.com/c/go/+/350349 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: David Chase --- src/cmd/compile/internal/ssa/expand_calls.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/cmd/compile/internal/ssa/expand_calls.go b/src/cmd/compile/internal/ssa/expand_calls.go index 79434f33d3..a0f0e653aa 100644 --- a/src/cmd/compile/internal/ssa/expand_calls.go +++ b/src/cmd/compile/internal/ssa/expand_calls.go @@ -1098,6 +1098,17 @@ func (x *expandState) rewriteArgs(v *Value, firstArg int) { if a.MemoryArg() != m0 { x.f.Fatalf("Op...LECall and OpDereference have mismatched mem, %s and %s", v.LongString(), a.LongString()) } + if v.Op == OpTailLECall { + // It's common for a tail call passing the same arguments (e.g. method wrapper), + // so this would be a self copy. Detect this and optimize it out. + a0 := a.Args[0] + if a0.Op == OpLocalAddr { + n := a0.Aux.(*ir.Name) + if n.Class == ir.PPARAM && n.FrameOffset()+x.f.Config.ctxt.FixedFrameSize() == aOffset { + continue + } + } + } // "Dereference" of addressed (probably not-SSA-eligible) value becomes Move // TODO(register args) this will be more complicated with registers in the picture. mem = x.rewriteDereference(v.Block, sp, a, mem, aOffset, aux.SizeOfArg(auxI), aType, a.Pos) @@ -1110,6 +1121,14 @@ func (x *expandState) rewriteArgs(v *Value, firstArg int) { } else { aOffset = aux.OffsetOfArg(auxI) } + if v.Op == OpTailLECall && a.Op == OpArg && a.AuxInt == 0 { + // It's common for a tail call passing the same arguments (e.g. method wrapper), + // so this would be a self copy. Detect this and optimize it out. + n := a.Aux.(*ir.Name) + if n.Class == ir.PPARAM && n.FrameOffset()+x.f.Config.ctxt.FixedFrameSize() == aOffset { + continue + } + } if x.debug > 1 { x.Printf("...storeArg %s, %v, %d\n", a.LongString(), aType, aOffset) } -- GitLab From 4b654c0eeca65ffc6588ffd9c99387a7e48002c1 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 17 Sep 2021 16:26:13 -0400 Subject: [PATCH 1195/2500] cmd/compile: SSA ".this" variable We used to not SSA ".this" variable, because in tail-call method wrappers it relies on updating ".this" in place in memory, and the tail call IR node and SSA op do not have an explicit use of ".this". It is no longer the case for the new tail call representation. Remove the restriction. Change-Id: I4e1ce8459adbb0d5a80c64f1ece982737bd95305 Reviewed-on: https://go-review.googlesource.com/c/go/+/350751 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: David Chase --- src/cmd/compile/internal/ssagen/ssa.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 346a801508..08f36ce7be 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -5311,12 +5311,6 @@ func (s *state) canSSAName(name *ir.Name) bool { return false } } - if name.Class == ir.PPARAM && name.Sym() != nil && name.Sym().Name == ".this" { - // wrappers generated by genwrapper need to update - // the .this pointer in place. - // TODO: treat as a PPARAMOUT? - return false - } return true // TODO: try to make more variables SSAable? } -- GitLab From c894b442d1e5e150ad33fa3ce13dbfab1c037b3a Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Tue, 14 Sep 2021 15:02:55 -0700 Subject: [PATCH 1196/2500] net/rpc: remove warnings on incompatible methods at registration When registering an RPC server, the type being registered may have additional methods that are not meant to be exposed as RPC endpoints. Remove the warnings net/rpc produces in this case. The functionality to report warnings is kept in the code with a compile-time constant that can be enabled for debugging. The documentation of net/rpc states that only methods satisfying a set of criteria will be made available, while other methods will be ignored. Fixes #19957 Change-Id: I5f8a148b4be1fdfffb2cd2029871193eaf24b751 Reviewed-on: https://go-review.googlesource.com/c/go/+/350009 Reviewed-by: Daniel Lublin Reviewed-by: Damien Neil Trust: Carlos Amedee --- src/net/rpc/server.go | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/net/rpc/server.go b/src/net/rpc/server.go index 074c5b9b0d..bfc19ac97c 100644 --- a/src/net/rpc/server.go +++ b/src/net/rpc/server.go @@ -231,6 +231,10 @@ func (server *Server) RegisterName(name string, rcvr interface{}) error { return server.register(rcvr, name, true) } +// logRegisterError specifies whether to log problems during method registration. +// To debug registration, recompile the package with this set to true. +const logRegisterError = false + func (server *Server) register(rcvr interface{}, name string, useName bool) error { s := new(service) s.typ = reflect.TypeOf(rcvr) @@ -252,7 +256,7 @@ func (server *Server) register(rcvr interface{}, name string, useName bool) erro s.name = sname // Install the methods - s.method = suitableMethods(s.typ, true) + s.method = suitableMethods(s.typ, logRegisterError) if len(s.method) == 0 { str := "" @@ -274,9 +278,9 @@ func (server *Server) register(rcvr interface{}, name string, useName bool) erro return nil } -// suitableMethods returns suitable Rpc methods of typ, it will report -// error using log if reportErr is true. -func suitableMethods(typ reflect.Type, reportErr bool) map[string]*methodType { +// suitableMethods returns suitable Rpc methods of typ. It will log +// errors if logErr is true. +func suitableMethods(typ reflect.Type, logErr bool) map[string]*methodType { methods := make(map[string]*methodType) for m := 0; m < typ.NumMethod(); m++ { method := typ.Method(m) @@ -288,7 +292,7 @@ func suitableMethods(typ reflect.Type, reportErr bool) map[string]*methodType { } // Method needs three ins: receiver, *args, *reply. if mtype.NumIn() != 3 { - if reportErr { + if logErr { log.Printf("rpc.Register: method %q has %d input parameters; needs exactly three\n", mname, mtype.NumIn()) } continue @@ -296,7 +300,7 @@ func suitableMethods(typ reflect.Type, reportErr bool) map[string]*methodType { // First arg need not be a pointer. argType := mtype.In(1) if !isExportedOrBuiltinType(argType) { - if reportErr { + if logErr { log.Printf("rpc.Register: argument type of method %q is not exported: %q\n", mname, argType) } continue @@ -304,28 +308,28 @@ func suitableMethods(typ reflect.Type, reportErr bool) map[string]*methodType { // Second arg must be a pointer. replyType := mtype.In(2) if replyType.Kind() != reflect.Ptr { - if reportErr { + if logErr { log.Printf("rpc.Register: reply type of method %q is not a pointer: %q\n", mname, replyType) } continue } // Reply type must be exported. if !isExportedOrBuiltinType(replyType) { - if reportErr { + if logErr { log.Printf("rpc.Register: reply type of method %q is not exported: %q\n", mname, replyType) } continue } // Method needs one out. if mtype.NumOut() != 1 { - if reportErr { + if logErr { log.Printf("rpc.Register: method %q has %d output parameters; needs exactly one\n", mname, mtype.NumOut()) } continue } // The return type of the method must be error. if returnType := mtype.Out(0); returnType != typeOfError { - if reportErr { + if logErr { log.Printf("rpc.Register: return type of method %q is %q, must be error\n", mname, returnType) } continue -- GitLab From 771b8ea4f4c56b3e27351807ade7ef72c3a15750 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sat, 18 Sep 2021 23:46:47 +0700 Subject: [PATCH 1197/2500] cmd/compile: fix missing markHiddenClosureDead in deadcode pass CL 342350 fixed panic with dead hidden closures, by marking discarded hidden closure as dead, and won't compile them. However, the fix is incomplete. In case the "if" or "else" block end with panic or return statement: if true { return } # All nodes starts from here are dead the dead nodes must be processed with markHiddenClosureDead, but they are not, causing the compiler crashes. This CL adds that missing part. Fixes #48459 Change-Id: Ibdd10a61fc6459d139bbf4a66b0893b523ac6b67 Reviewed-on: https://go-review.googlesource.com/c/go/+/350695 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/deadcode/deadcode.go | 1 + test/fixedbugs/issue48459.go | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 test/fixedbugs/issue48459.go diff --git a/src/cmd/compile/internal/deadcode/deadcode.go b/src/cmd/compile/internal/deadcode/deadcode.go index 3658c89912..65a48b6803 100644 --- a/src/cmd/compile/internal/deadcode/deadcode.go +++ b/src/cmd/compile/internal/deadcode/deadcode.go @@ -117,6 +117,7 @@ func stmts(nn *ir.Nodes) { } if cut { + ir.VisitList((*nn)[i+1:len(*nn)], markHiddenClosureDead) *nn = (*nn)[:i+1] break } diff --git a/test/fixedbugs/issue48459.go b/test/fixedbugs/issue48459.go new file mode 100644 index 0000000000..ceb7788ae4 --- /dev/null +++ b/test/fixedbugs/issue48459.go @@ -0,0 +1,17 @@ +// compile + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func main() { + if true { + return + } + + defer func() { + recover() + }() +} -- GitLab From 83b36ffb108cc6e6cc3282b94c090f70100b5ef0 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Sun, 19 Sep 2021 09:09:55 -0700 Subject: [PATCH 1198/2500] cmd/compile: implement constant rotates on arm64 Explicit constant rotates work, but constant arguments to bits.RotateLeft* needed the additional rule. Fixes #48465 Change-Id: Ia7544f21d0e7587b6b6506f72421459cd769aea6 Reviewed-on: https://go-review.googlesource.com/c/go/+/350909 Trust: Keith Randall Trust: Josh Bleecher Snyder Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Josh Bleecher Snyder --- src/cmd/compile/internal/ssa/gen/ARM.rules | 3 +- src/cmd/compile/internal/ssa/gen/ARM64.rules | 3 ++ src/cmd/compile/internal/ssa/rewriteARM.go | 33 +++++++++------- src/cmd/compile/internal/ssa/rewriteARM64.go | 40 ++++++++++++++++++++ test/codegen/rotate.go | 19 +++++++++- 5 files changed, 82 insertions(+), 16 deletions(-) diff --git a/src/cmd/compile/internal/ssa/gen/ARM.rules b/src/cmd/compile/internal/ssa/gen/ARM.rules index bfb97e5271..8a755b404b 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM.rules @@ -508,6 +508,8 @@ (TST x (MOVWconst [c])) => (TSTconst [c] x) (TEQ x (MOVWconst [c])) => (TEQconst [c] x) +(SRR x (MOVWconst [c])) => (SRRconst x [c&31]) + // Canonicalize the order of arguments to comparisons - helps with CSE. (CMP x y) && canonLessThan(x,y) => (InvertFlags (CMP y x)) @@ -1136,7 +1138,6 @@ ( ORshiftRL [c] (SLLconst x [32-c]) x) => (SRRconst [ c] x) (XORshiftRL [c] (SLLconst x [32-c]) x) => (SRRconst [ c] x) -(RotateLeft32 x (MOVWconst [c])) => (SRRconst [-c&31] x) (RotateLeft16 x (MOVWconst [c])) => (Or16 (Lsh16x32 x (MOVWconst [c&15])) (Rsh16Ux32 x (MOVWconst [-c&15]))) (RotateLeft8 x (MOVWconst [c])) => (Or8 (Lsh8x32 x (MOVWconst [c&7])) (Rsh8Ux32 x (MOVWconst [-c&7]))) (RotateLeft32 x y) => (SRR x (RSBconst [0] y)) diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index 7f9d5ec2bd..f63b2557c5 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -1175,6 +1175,9 @@ (CMPW x (MOVDconst [c])) => (CMPWconst [int32(c)] x) (CMPW (MOVDconst [c]) x) => (InvertFlags (CMPWconst [int32(c)] x)) +(ROR x (MOVDconst [c])) => (RORconst x [c&63]) +(RORW x (MOVDconst [c])) => (RORWconst x [c&31]) + // Canonicalize the order of arguments to comparisons - helps with CSE. ((CMP|CMPW) x y) && canonLessThan(x,y) => (InvertFlags ((CMP|CMPW) y x)) diff --git a/src/cmd/compile/internal/ssa/rewriteARM.go b/src/cmd/compile/internal/ssa/rewriteARM.go index 3d2f862705..6807507218 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM.go +++ b/src/cmd/compile/internal/ssa/rewriteARM.go @@ -338,6 +338,8 @@ func rewriteValueARM(v *Value) bool { return rewriteValueARM_OpARMSRL(v) case OpARMSRLconst: return rewriteValueARM_OpARMSRLconst(v) + case OpARMSRR: + return rewriteValueARM_OpARMSRR(v) case OpARMSUB: return rewriteValueARM_OpARMSUB(v) case OpARMSUBD: @@ -10523,6 +10525,24 @@ func rewriteValueARM_OpARMSRLconst(v *Value) bool { } return false } +func rewriteValueARM_OpARMSRR(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] + // match: (SRR x (MOVWconst [c])) + // result: (SRRconst x [c&31]) + for { + x := v_0 + if v_1.Op != OpARMMOVWconst { + break + } + c := auxIntToInt32(v_1.AuxInt) + v.reset(OpARMSRRconst) + v.AuxInt = int32ToAuxInt(c & 31) + v.AddArg(x) + return true + } + return false +} func rewriteValueARM_OpARMSUB(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -14904,19 +14924,6 @@ func rewriteValueARM_OpRotateLeft32(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - // match: (RotateLeft32 x (MOVWconst [c])) - // result: (SRRconst [-c&31] x) - for { - x := v_0 - if v_1.Op != OpARMMOVWconst { - break - } - c := auxIntToInt32(v_1.AuxInt) - v.reset(OpARMSRRconst) - v.AuxInt = int32ToAuxInt(-c & 31) - v.AddArg(x) - return true - } // match: (RotateLeft32 x y) // result: (SRR x (RSBconst [0] y)) for { diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index 3df84e161a..2bce96f0b2 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -323,6 +323,10 @@ func rewriteValueARM64(v *Value) bool { return rewriteValueARM64_OpARM64ORshiftRA(v) case OpARM64ORshiftRL: return rewriteValueARM64_OpARM64ORshiftRL(v) + case OpARM64ROR: + return rewriteValueARM64_OpARM64ROR(v) + case OpARM64RORW: + return rewriteValueARM64_OpARM64RORW(v) case OpARM64RORWconst: return rewriteValueARM64_OpARM64RORWconst(v) case OpARM64RORconst: @@ -19956,6 +19960,42 @@ func rewriteValueARM64_OpARM64ORshiftRL(v *Value) bool { } return false } +func rewriteValueARM64_OpARM64ROR(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] + // match: (ROR x (MOVDconst [c])) + // result: (RORconst x [c&63]) + for { + x := v_0 + if v_1.Op != OpARM64MOVDconst { + break + } + c := auxIntToInt64(v_1.AuxInt) + v.reset(OpARM64RORconst) + v.AuxInt = int64ToAuxInt(c & 63) + v.AddArg(x) + return true + } + return false +} +func rewriteValueARM64_OpARM64RORW(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] + // match: (RORW x (MOVDconst [c])) + // result: (RORWconst x [c&31]) + for { + x := v_0 + if v_1.Op != OpARM64MOVDconst { + break + } + c := auxIntToInt64(v_1.AuxInt) + v.reset(OpARM64RORWconst) + v.AuxInt = int64ToAuxInt(c & 31) + v.AddArg(x) + return true + } + return false +} func rewriteValueARM64_OpARM64RORWconst(v *Value) bool { v_0 := v.Args[0] // match: (RORWconst [c] (RORWconst [d] x)) diff --git a/test/codegen/rotate.go b/test/codegen/rotate.go index 519cc83263..70489a2adc 100644 --- a/test/codegen/rotate.go +++ b/test/codegen/rotate.go @@ -34,8 +34,15 @@ func rot64(x uint64) uint64 { // ppc64le:"ROTL\t[$]9" a += x<<9 ^ x>>55 - // s390x:"RISBGZ\t[$]0, [$]63, [$]7, " + // amd64:"ROLQ\t[$]10" + // arm64:"ROR\t[$]54" + // s390x:"RISBGZ\t[$]0, [$]63, [$]10, " + // ppc64:"ROTL\t[$]10" + // ppc64le:"ROTL\t[$]10" // arm64:"ROR\t[$]57" // TODO this is not great line numbering, but then again, the instruction did appear + // s390x:"RISBGZ\t[$]0, [$]63, [$]7, " // TODO ditto + a += bits.RotateLeft64(x, 10) + return a } @@ -64,8 +71,16 @@ func rot32(x uint32) uint32 { // ppc64le:"ROTLW\t[$]9" a += x<<9 ^ x>>23 - // s390x:"RLL\t[$]7" + // amd64:"ROLL\t[$]10" + // arm:"MOVW\tR\\d+@>22" + // arm64:"RORW\t[$]22" + // s390x:"RLL\t[$]10" + // ppc64:"ROTLW\t[$]10" + // ppc64le:"ROTLW\t[$]10" // arm64:"RORW\t[$]25" // TODO this is not great line numbering, but then again, the instruction did appear + // s390x:"RLL\t[$]7" // TODO ditto + a += bits.RotateLeft32(x, 10) + return a } -- GitLab From 315dbd10c90db3b41af2c975a5fbfa2ec7615c1b Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Sun, 19 Sep 2021 09:23:37 -0700 Subject: [PATCH 1199/2500] cmd/compile: fold double negate on arm64 Fixes #48467 Change-Id: I52305dbf561ee3eee6c1f053e555a3a6ec1ab892 Reviewed-on: https://go-review.googlesource.com/c/go/+/350910 Trust: Keith Randall Trust: Josh Bleecher Snyder Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Josh Bleecher Snyder --- src/cmd/compile/internal/ssa/gen/ARM64.rules | 1 + src/cmd/compile/internal/ssa/rewriteARM64.go | 10 ++++++++++ test/codegen/bits.go | 8 ++++++++ 3 files changed, 19 insertions(+) diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index f63b2557c5..23ae3b1286 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -1363,6 +1363,7 @@ (XOR x (MVN y)) => (EON x y) (OR x (MVN y)) => (ORN x y) (MVN (XOR x y)) => (EON x y) +(NEG (NEG x)) => x (CSEL [cc] (MOVDconst [-1]) (MOVDconst [0]) flag) => (CSETM [cc] flag) (CSEL [cc] (MOVDconst [0]) (MOVDconst [-1]) flag) => (CSETM [arm64Negate(cc)] flag) diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index 2bce96f0b2..661714307a 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -15691,6 +15691,16 @@ func rewriteValueARM64_OpARM64NEG(v *Value) bool { v.AddArg2(x, y) return true } + // match: (NEG (NEG x)) + // result: x + for { + if v_0.Op != OpARM64NEG { + break + } + x := v_0.Args[0] + v.copyOf(x) + return true + } // match: (NEG (MOVDconst [c])) // result: (MOVDconst [-c]) for { diff --git a/test/codegen/bits.go b/test/codegen/bits.go index 8117a62307..8e973d5726 100644 --- a/test/codegen/bits.go +++ b/test/codegen/bits.go @@ -6,6 +6,8 @@ package codegen +import "math/bits" + /************************************ * 64-bit instructions ************************************/ @@ -355,3 +357,9 @@ func issue44228b(a []int32, i int) bool { // amd64: "BTL", -"SHL" return a[i>>5]&(1<<(i&31)) != 0 } + +func issue48467(x, y uint64) uint64 { + // arm64: -"NEG" + d, borrow := bits.Sub64(x, y, 0) + return x - d&(-borrow) +} -- GitLab From a83a5587331392fc9483d183e446586b463ad8aa Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sun, 19 Sep 2021 09:23:21 -0700 Subject: [PATCH 1200/2500] cmd/compile: fix export/import of range loop. As with other recent issues, the Init field of a range loop was not being handled properly. Generally, it is much better to explicitly import/export the Init statements, else they are incorrectly added before the associated node, rather than as the Init value of the node. This was causing labels to not be correctly added to the range loop that it is immediately preceding. Made the ORANGE handling completely similar to the OFOR handling. Fixes #48462 Change-Id: I999530e84f9357f81deaa3dda50660061f710e7c Reviewed-on: https://go-review.googlesource.com/c/go/+/350911 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le Trust: Dan Scales --- src/cmd/compile/internal/typecheck/iexport.go | 3 ++- src/cmd/compile/internal/typecheck/iimport.go | 16 +++++++------ test/typeparam/issue48462.dir/a.go | 22 ++++++++++++++++++ test/typeparam/issue48462.dir/main.go | 23 +++++++++++++++++++ test/typeparam/issue48462.go | 7 ++++++ 5 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 test/typeparam/issue48462.dir/a.go create mode 100644 test/typeparam/issue48462.dir/main.go create mode 100644 test/typeparam/issue48462.go diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index a9522c3887..def9408544 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -1472,7 +1472,7 @@ func isNonEmptyAssign(n ir.Node) bool { // non-empty n.Ninit and where n is not a non-empty assignment or a node with a natural init // section (such as in "if", "for", etc.). func (w *exportWriter) stmt(n ir.Node) { - if len(n.Init()) > 0 && !ir.StmtWithInit(n.Op()) && !isNonEmptyAssign(n) { + if len(n.Init()) > 0 && !ir.StmtWithInit(n.Op()) && !isNonEmptyAssign(n) && n.Op() != ir.ORANGE { // can't use stmtList here since we don't want the final OEND for _, n := range n.Init() { w.stmt(n) @@ -1573,6 +1573,7 @@ func (w *exportWriter) stmt(n ir.Node) { n := n.(*ir.RangeStmt) w.op(ir.ORANGE) w.pos(n.Pos()) + w.stmtList(n.Init()) w.exprsOrNil(n.Key, n.Value) w.expr(n.X) w.stmtList(n.Body) diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 3b3c2a2e2a..a7339903fc 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1515,7 +1515,7 @@ func (r *importReader) node() ir.Node { if go117ExportTypes { n.SetOp(op) } - *n.PtrInit() = init + n.SetInit(init) n.IsDDD = r.bool() if go117ExportTypes { n.SetType(r.exoticType()) @@ -1660,26 +1660,28 @@ func (r *importReader) node() ir.Node { case ir.OIF: pos, init := r.pos(), r.stmtList() n := ir.NewIfStmt(pos, r.expr(), r.stmtList(), r.stmtList()) - *n.PtrInit() = init + n.SetInit(init) return n case ir.OFOR: pos, init := r.pos(), r.stmtList() cond, post := r.exprsOrNil() n := ir.NewForStmt(pos, nil, cond, post, r.stmtList()) - *n.PtrInit() = init + n.SetInit(init) return n case ir.ORANGE: - pos := r.pos() + pos, init := r.pos(), r.stmtList() k, v := r.exprsOrNil() - return ir.NewRangeStmt(pos, k, v, r.expr(), r.stmtList()) + n := ir.NewRangeStmt(pos, k, v, r.expr(), r.stmtList()) + n.SetInit(init) + return n case ir.OSELECT: pos := r.pos() init := r.stmtList() n := ir.NewSelectStmt(pos, r.commList()) - *n.PtrInit() = init + n.SetInit(init) return n case ir.OSWITCH: @@ -1687,7 +1689,7 @@ func (r *importReader) node() ir.Node { init := r.stmtList() x, _ := r.exprsOrNil() n := ir.NewSwitchStmt(pos, x, r.caseList(x)) - *n.PtrInit() = init + n.SetInit(init) return n // case OCASE: diff --git a/test/typeparam/issue48462.dir/a.go b/test/typeparam/issue48462.dir/a.go new file mode 100644 index 0000000000..26c704dbe4 --- /dev/null +++ b/test/typeparam/issue48462.dir/a.go @@ -0,0 +1,22 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +func Unique[T comparable](set []T) []T { + nset := make([]T, 0, 8) + +loop: + for _, s := range set { + for _, e := range nset { + if s == e { + continue loop + } + } + + nset = append(nset, s) + } + + return nset +} diff --git a/test/typeparam/issue48462.dir/main.go b/test/typeparam/issue48462.dir/main.go new file mode 100644 index 0000000000..8054ddd327 --- /dev/null +++ b/test/typeparam/issue48462.dir/main.go @@ -0,0 +1,23 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + "reflect" + + "a" +) + +func main() { + e := []int{1, 2, 2, 3, 1, 6} + + got := a.Unique(e) + want := []int{1, 2, 3, 6} + if !reflect.DeepEqual(got, want) { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } + +} diff --git a/test/typeparam/issue48462.go b/test/typeparam/issue48462.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/issue48462.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From 119213566a8e0da729a8bccc7d7f7d525f0c1cf9 Mon Sep 17 00:00:00 2001 From: jochen weber Date: Fri, 14 May 2021 12:45:13 +0000 Subject: [PATCH 1201/2500] cmd/cgo: remove hardcoded '-pie' ldflag for linux/arm a minimally invasive fix proposal for #45940. which keeps the fix for #26197. an alternative for (#26197) could be to fail if we have both flags. adding/removing a flag without an message to the user is inconvenient. Change-Id: I6ac2524d81ff57202fbe3032a53afd5106270a9e GitHub-Last-Rev: edaf02fa455329b5d794a139f99874b5e8cc12d1 GitHub-Pull-Request: golang/go#45989 Reviewed-on: https://go-review.googlesource.com/c/go/+/317569 Reviewed-by: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Trust: Bryan C. Mills --- src/cmd/go/internal/work/exec.go | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index f7fae9fdd9..f82028aef6 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -2963,18 +2963,24 @@ func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe linkobj := str.StringList(ofile, outObj, mkAbsFiles(p.Dir, p.SysoFiles)) dynobj := objdir + "_cgo_.o" - // we need to use -pie for Linux/ARM to get accurate imported sym ldflags := cgoLDFLAGS if (cfg.Goarch == "arm" && cfg.Goos == "linux") || cfg.Goos == "android" { - // -static -pie doesn't make sense, and causes link errors. - // Issue 26197. - n := make([]string, 0, len(ldflags)) - for _, flag := range ldflags { - if flag != "-static" { - n = append(n, flag) + if !str.Contains(ldflags, "-no-pie") { + // we need to use -pie for Linux/ARM to get accurate imported sym (added in https://golang.org/cl/5989058) + // this seems to be outdated, but we don't want to break existing builds depending on this (Issue 45940) + ldflags = append(ldflags, "-pie") + } + if str.Contains(ldflags, "-pie") && str.Contains(ldflags, "-static") { + // -static -pie doesn't make sense, and causes link errors. + // Issue 26197. + n := make([]string, 0, len(ldflags)-1) + for _, flag := range ldflags { + if flag != "-static" { + n = append(n, flag) + } } + ldflags = n } - ldflags = append(n, "-pie") } if err := b.gccld(a, p, objdir, dynobj, ldflags, linkobj); err != nil { return err -- GitLab From a81b0dc6ee9096e3885e083e2dea2c743c0f4540 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sun, 19 Sep 2021 18:18:41 -0700 Subject: [PATCH 1202/2500] cmd/compile: rename instType -> instanceType This is to keep in alignment with the naming in go/types. Change-Id: I19ded29b39665d7b892fdbc8e92c7f15caf7ab66 Reviewed-on: https://go-review.googlesource.com/c/go/+/350950 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Robert Griesemer Trust: Dan Scales --- src/cmd/compile/internal/typecheck/iexport.go | 4 ++-- src/cmd/compile/internal/typecheck/iimport.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index def9408544..bbdad09782 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -255,7 +255,7 @@ const ( structType interfaceType typeParamType - instType + instanceType // Instantiation of a generic type unionType ) @@ -893,7 +893,7 @@ func (w *exportWriter) doTyp(t *types.Type) { if strings.Index(s.Name, "[") < 0 { base.Fatalf("incorrect name for instantiated type") } - w.startType(instType) + w.startType(instanceType) w.pos(t.Pos()) // Export the type arguments for the instantiated type. The // instantiated type could be in a method header (e.g. "func (v diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index a7339903fc..ec4057a8d0 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -821,7 +821,7 @@ func (r *importReader) typ1() *types.Type { } return n.Type() - case instType: + case instanceType: if r.p.exportVersion < iexportVersionGenerics { base.Fatalf("unexpected instantiation type") } -- GitLab From 2d9b4864201d76bd30b55a7d74d73a24cc3ae165 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sun, 19 Sep 2021 18:26:19 -0700 Subject: [PATCH 1203/2500] cmd/compile: update doc at top of iexport.go on the changes for typeparams Add in the documentation of the new declarations and type descriptors to support parameterized functions and types. Change-Id: Ia21c544caa704309cc8fd639f104c192e1786b72 Reviewed-on: https://go-review.googlesource.com/c/go/+/350951 Trust: Dan Scales Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/typecheck/iexport.go | 38 +++++++++++++++++-- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index bbdad09782..489306e1e6 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -63,8 +63,9 @@ // } // // type Func struct { -// Tag byte // 'F' +// Tag byte // 'F' or 'G' // Pos Pos +// TypeParams []typeOff // only present if Tag == 'G' // Signature Signature // } // @@ -75,8 +76,9 @@ // } // // type Type struct { -// Tag byte // 'T' +// Tag byte // 'T' or 'U' // Pos Pos +// TypeParams []typeOff // only present if Tag == 'U' // Underlying typeOff // // Methods []struct{ // omitted if Underlying is an interface type @@ -93,6 +95,12 @@ // Type typeOff // } // +// // "Automatic" declaration of each typeparam +// type TypeParam struct { +// Tag byte // 'P' +// Pos Pos +// Bound typeOff +// } // // typeOff means a uvarint that either indicates a predeclared type, // or an offset into the Data section. If the uvarint is less than @@ -104,7 +112,7 @@ // (*exportWriter).value for details. // // -// There are nine kinds of type descriptors, distinguished by an itag: +// There are twelve kinds of type descriptors, distinguished by an itag: // // type DefinedType struct { // Tag itag // definedType @@ -172,8 +180,30 @@ // } // } // +// // Reference to a type param declaration +// type TypeParamType struct { +// Tag itag // typeParamType +// Name stringOff +// PkgPath stringOff +// } +// +// // Instantiation of a generic type (like List[T2] or List[int]) +// type InstanceType struct { +// Tag itag // instanceType +// Pos pos +// TypeArgs []typeOff +// BaseType typeOff +// } +// +// type UnionType struct { +// Tag itag // interfaceType +// Terms []struct { +// tilde bool +// Type typeOff +// } +// } +// // -// TODO(danscales): fill in doc for 'type TypeParamType' and 'type InstType' // // type Signature struct { // Params []Param -- GitLab From 6f35430faa622bad63a527c97e87b9291e480688 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Sun, 19 Sep 2021 13:51:37 -0700 Subject: [PATCH 1204/2500] cmd/compile: allow rotates to be merged with logical ops on arm64 Fixes #48002 Change-Id: Ie3a157d55b291f5ac2ef4845e6ce4fefd84fc642 Reviewed-on: https://go-review.googlesource.com/c/go/+/350912 Trust: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/compile/internal/arm64/ssa.go | 11 + src/cmd/compile/internal/ssa/gen/ARM64.rules | 26 + src/cmd/compile/internal/ssa/gen/ARM64Ops.go | 8 + src/cmd/compile/internal/ssa/opGen.go | 124 +++++ src/cmd/compile/internal/ssa/rewrite.go | 4 + src/cmd/compile/internal/ssa/rewriteARM64.go | 502 +++++++++++++++++++ src/cmd/internal/obj/arm64/a.out.go | 7 +- test/codegen/rotate.go | 23 + 8 files changed, 702 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/arm64/ssa.go b/src/cmd/compile/internal/arm64/ssa.go index c5e7a08914..4770a0c488 100644 --- a/src/cmd/compile/internal/arm64/ssa.go +++ b/src/cmd/compile/internal/arm64/ssa.go @@ -315,6 +315,8 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { genshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm64.SHIFT_LR, v.AuxInt) case ssa.OpARM64MVNshiftRA, ssa.OpARM64NEGshiftRA: genshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm64.SHIFT_AR, v.AuxInt) + case ssa.OpARM64MVNshiftRO: + genshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm64.SHIFT_ROR, v.AuxInt) case ssa.OpARM64ADDshiftLL, ssa.OpARM64SUBshiftLL, ssa.OpARM64ANDshiftLL, @@ -342,6 +344,13 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { ssa.OpARM64ORNshiftRA, ssa.OpARM64BICshiftRA: genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm64.SHIFT_AR, v.AuxInt) + case ssa.OpARM64ANDshiftRO, + ssa.OpARM64ORshiftRO, + ssa.OpARM64XORshiftRO, + ssa.OpARM64EONshiftRO, + ssa.OpARM64ORNshiftRO, + ssa.OpARM64BICshiftRO: + genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm64.SHIFT_ROR, v.AuxInt) case ssa.OpARM64MOVDconst: p := s.Prog(v.Op.Asm()) p.From.Type = obj.TYPE_CONST @@ -389,6 +398,8 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm64.SHIFT_LR, v.AuxInt) case ssa.OpARM64CMPshiftRA, ssa.OpARM64CMNshiftRA, ssa.OpARM64TSTshiftRA: genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm64.SHIFT_AR, v.AuxInt) + case ssa.OpARM64TSTshiftRO: + genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm64.SHIFT_ROR, v.AuxInt) case ssa.OpARM64MOVDaddr: p := s.Prog(arm64.AMOVD) p.From.Type = obj.TYPE_ADDR diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index 23ae3b1286..b722d1cf1c 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -1601,6 +1601,7 @@ (MVN x:(SLLconst [c] y)) && clobberIfDead(x) => (MVNshiftLL [c] y) (MVN x:(SRLconst [c] y)) && clobberIfDead(x) => (MVNshiftRL [c] y) (MVN x:(SRAconst [c] y)) && clobberIfDead(x) => (MVNshiftRA [c] y) +(MVN x:(RORconst [c] y)) && clobberIfDead(x) => (MVNshiftRO [c] y) (ADD x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) => (ADDshiftLL x0 y [c]) (ADD x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) => (ADDshiftRL x0 y [c]) (ADD x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) => (ADDshiftRA x0 y [c]) @@ -1610,21 +1611,27 @@ (AND x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) => (ANDshiftLL x0 y [c]) (AND x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) => (ANDshiftRL x0 y [c]) (AND x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) => (ANDshiftRA x0 y [c]) +(AND x0 x1:(RORconst [c] y)) && clobberIfDead(x1) => (ANDshiftRO x0 y [c]) (OR x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) => (ORshiftLL x0 y [c]) // useful for combined load (OR x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) => (ORshiftRL x0 y [c]) (OR x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) => (ORshiftRA x0 y [c]) +(OR x0 x1:(RORconst [c] y)) && clobberIfDead(x1) => (ORshiftRO x0 y [c]) (XOR x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) => (XORshiftLL x0 y [c]) (XOR x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) => (XORshiftRL x0 y [c]) (XOR x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) => (XORshiftRA x0 y [c]) +(XOR x0 x1:(RORconst [c] y)) && clobberIfDead(x1) => (XORshiftRO x0 y [c]) (BIC x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) => (BICshiftLL x0 y [c]) (BIC x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) => (BICshiftRL x0 y [c]) (BIC x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) => (BICshiftRA x0 y [c]) +(BIC x0 x1:(RORconst [c] y)) && clobberIfDead(x1) => (BICshiftRO x0 y [c]) (ORN x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) => (ORNshiftLL x0 y [c]) (ORN x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) => (ORNshiftRL x0 y [c]) (ORN x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) => (ORNshiftRA x0 y [c]) +(ORN x0 x1:(RORconst [c] y)) && clobberIfDead(x1) => (ORNshiftRO x0 y [c]) (EON x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) => (EONshiftLL x0 y [c]) (EON x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) => (EONshiftRL x0 y [c]) (EON x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) => (EONshiftRA x0 y [c]) +(EON x0 x1:(RORconst [c] y)) && clobberIfDead(x1) => (EONshiftRO x0 y [c]) (CMP x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) => (CMPshiftLL x0 y [c]) (CMP x0:(SLLconst [c] y) x1) && clobberIfDead(x0) => (InvertFlags (CMPshiftLL x1 y [c])) (CMP x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) => (CMPshiftRL x0 y [c]) @@ -1637,6 +1644,7 @@ (TST x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) => (TSTshiftLL x0 y [c]) (TST x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) => (TSTshiftRL x0 y [c]) (TST x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) => (TSTshiftRA x0 y [c]) +(TST x0 x1:(RORconst [c] y)) && clobberIfDead(x1) => (TSTshiftRO x0 y [c]) // prefer *const ops to *shift ops (ADDshiftLL (MOVDconst [c]) x [d]) => (ADDconst [c] (SLLconst x [d])) @@ -1645,12 +1653,15 @@ (ANDshiftLL (MOVDconst [c]) x [d]) => (ANDconst [c] (SLLconst x [d])) (ANDshiftRL (MOVDconst [c]) x [d]) => (ANDconst [c] (SRLconst x [d])) (ANDshiftRA (MOVDconst [c]) x [d]) => (ANDconst [c] (SRAconst x [d])) +(ANDshiftRO (MOVDconst [c]) x [d]) => (ANDconst [c] (RORconst x [d])) (ORshiftLL (MOVDconst [c]) x [d]) => (ORconst [c] (SLLconst x [d])) (ORshiftRL (MOVDconst [c]) x [d]) => (ORconst [c] (SRLconst x [d])) (ORshiftRA (MOVDconst [c]) x [d]) => (ORconst [c] (SRAconst x [d])) +(ORshiftRO (MOVDconst [c]) x [d]) => (ORconst [c] (RORconst x [d])) (XORshiftLL (MOVDconst [c]) x [d]) => (XORconst [c] (SLLconst x [d])) (XORshiftRL (MOVDconst [c]) x [d]) => (XORconst [c] (SRLconst x [d])) (XORshiftRA (MOVDconst [c]) x [d]) => (XORconst [c] (SRAconst x [d])) +(XORshiftRO (MOVDconst [c]) x [d]) => (XORconst [c] (RORconst x [d])) (CMPshiftLL (MOVDconst [c]) x [d]) => (InvertFlags (CMPconst [c] (SLLconst x [d]))) (CMPshiftRL (MOVDconst [c]) x [d]) => (InvertFlags (CMPconst [c] (SRLconst x [d]))) (CMPshiftRA (MOVDconst [c]) x [d]) => (InvertFlags (CMPconst [c] (SRAconst x [d]))) @@ -1660,11 +1671,13 @@ (TSTshiftLL (MOVDconst [c]) x [d]) => (TSTconst [c] (SLLconst x [d])) (TSTshiftRL (MOVDconst [c]) x [d]) => (TSTconst [c] (SRLconst x [d])) (TSTshiftRA (MOVDconst [c]) x [d]) => (TSTconst [c] (SRAconst x [d])) +(TSTshiftRO (MOVDconst [c]) x [d]) => (TSTconst [c] (RORconst x [d])) // constant folding in *shift ops (MVNshiftLL (MOVDconst [c]) [d]) => (MOVDconst [^int64(uint64(c)< (MOVDconst [^int64(uint64(c)>>uint64(d))]) (MVNshiftRA (MOVDconst [c]) [d]) => (MOVDconst [^(c>>uint64(d))]) +(MVNshiftRO (MOVDconst [c]) [d]) => (MOVDconst [^rotateRight64(c, d)]) (NEGshiftLL (MOVDconst [c]) [d]) => (MOVDconst [-int64(uint64(c)< (MOVDconst [-int64(uint64(c)>>uint64(d))]) (NEGshiftRA (MOVDconst [c]) [d]) => (MOVDconst [-(c>>uint64(d))]) @@ -1677,21 +1690,27 @@ (ANDshiftLL x (MOVDconst [c]) [d]) => (ANDconst x [int64(uint64(c)< (ANDconst x [int64(uint64(c)>>uint64(d))]) (ANDshiftRA x (MOVDconst [c]) [d]) => (ANDconst x [c>>uint64(d)]) +(ANDshiftRO x (MOVDconst [c]) [d]) => (ANDconst x [rotateRight64(c, d)]) (ORshiftLL x (MOVDconst [c]) [d]) => (ORconst x [int64(uint64(c)< (ORconst x [int64(uint64(c)>>uint64(d))]) (ORshiftRA x (MOVDconst [c]) [d]) => (ORconst x [c>>uint64(d)]) +(ORshiftRO x (MOVDconst [c]) [d]) => (ORconst x [rotateRight64(c, d)]) (XORshiftLL x (MOVDconst [c]) [d]) => (XORconst x [int64(uint64(c)< (XORconst x [int64(uint64(c)>>uint64(d))]) (XORshiftRA x (MOVDconst [c]) [d]) => (XORconst x [c>>uint64(d)]) +(XORshiftRO x (MOVDconst [c]) [d]) => (XORconst x [rotateRight64(c, d)]) (BICshiftLL x (MOVDconst [c]) [d]) => (ANDconst x [^int64(uint64(c)< (ANDconst x [^int64(uint64(c)>>uint64(d))]) (BICshiftRA x (MOVDconst [c]) [d]) => (ANDconst x [^(c>>uint64(d))]) +(BICshiftRO x (MOVDconst [c]) [d]) => (ANDconst x [^rotateRight64(c, d)]) (ORNshiftLL x (MOVDconst [c]) [d]) => (ORconst x [^int64(uint64(c)< (ORconst x [^int64(uint64(c)>>uint64(d))]) (ORNshiftRA x (MOVDconst [c]) [d]) => (ORconst x [^(c>>uint64(d))]) +(ORNshiftRO x (MOVDconst [c]) [d]) => (ORconst x [^rotateRight64(c, d)]) (EONshiftLL x (MOVDconst [c]) [d]) => (XORconst x [^int64(uint64(c)< (XORconst x [^int64(uint64(c)>>uint64(d))]) (EONshiftRA x (MOVDconst [c]) [d]) => (XORconst x [^(c>>uint64(d))]) +(EONshiftRO x (MOVDconst [c]) [d]) => (XORconst x [^rotateRight64(c, d)]) (CMPshiftLL x (MOVDconst [c]) [d]) => (CMPconst x [int64(uint64(c)< (CMPconst x [int64(uint64(c)>>uint64(d))]) (CMPshiftRA x (MOVDconst [c]) [d]) => (CMPconst x [c>>uint64(d)]) @@ -1701,6 +1720,7 @@ (TSTshiftLL x (MOVDconst [c]) [d]) => (TSTconst x [int64(uint64(c)< (TSTconst x [int64(uint64(c)>>uint64(d))]) (TSTshiftRA x (MOVDconst [c]) [d]) => (TSTconst x [c>>uint64(d)]) +(TSTshiftRO x (MOVDconst [c]) [d]) => (TSTconst x [rotateRight64(c, d)]) // simplification with *shift ops (SUBshiftLL x (SLLconst x [c]) [d]) && c==d => (MOVDconst [0]) @@ -1709,21 +1729,27 @@ (ANDshiftLL x y:(SLLconst x [c]) [d]) && c==d => y (ANDshiftRL x y:(SRLconst x [c]) [d]) && c==d => y (ANDshiftRA x y:(SRAconst x [c]) [d]) && c==d => y +(ANDshiftRO x y:(RORconst x [c]) [d]) && c==d => y (ORshiftLL x y:(SLLconst x [c]) [d]) && c==d => y (ORshiftRL x y:(SRLconst x [c]) [d]) && c==d => y (ORshiftRA x y:(SRAconst x [c]) [d]) && c==d => y +(ORshiftRO x y:(RORconst x [c]) [d]) && c==d => y (XORshiftLL x (SLLconst x [c]) [d]) && c==d => (MOVDconst [0]) (XORshiftRL x (SRLconst x [c]) [d]) && c==d => (MOVDconst [0]) (XORshiftRA x (SRAconst x [c]) [d]) && c==d => (MOVDconst [0]) +(XORshiftRO x (RORconst x [c]) [d]) && c==d => (MOVDconst [0]) (BICshiftLL x (SLLconst x [c]) [d]) && c==d => (MOVDconst [0]) (BICshiftRL x (SRLconst x [c]) [d]) && c==d => (MOVDconst [0]) (BICshiftRA x (SRAconst x [c]) [d]) && c==d => (MOVDconst [0]) +(BICshiftRO x (RORconst x [c]) [d]) && c==d => (MOVDconst [0]) (EONshiftLL x (SLLconst x [c]) [d]) && c==d => (MOVDconst [-1]) (EONshiftRL x (SRLconst x [c]) [d]) && c==d => (MOVDconst [-1]) (EONshiftRA x (SRAconst x [c]) [d]) && c==d => (MOVDconst [-1]) +(EONshiftRO x (RORconst x [c]) [d]) && c==d => (MOVDconst [-1]) (ORNshiftLL x (SLLconst x [c]) [d]) && c==d => (MOVDconst [-1]) (ORNshiftRL x (SRLconst x [c]) [d]) && c==d => (MOVDconst [-1]) (ORNshiftRA x (SRAconst x [c]) [d]) && c==d => (MOVDconst [-1]) +(ORNshiftRO x (RORconst x [c]) [d]) && c==d => (MOVDconst [-1]) // Generate rotates with const shift (ADDshiftLL [c] (SRLconst x [64-c]) x) => (RORconst [64-c] x) diff --git a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go index 41231fb809..e3ebb6e1af 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go @@ -302,6 +302,7 @@ func init() { {name: "MVNshiftLL", argLength: 1, reg: gp11, asm: "MVN", aux: "Int64"}, // ^(arg0<>auxInt), unsigned shift, auxInt should be in the range 0 to 63. {name: "MVNshiftRA", argLength: 1, reg: gp11, asm: "MVN", aux: "Int64"}, // ^(arg0>>auxInt), signed shift, auxInt should be in the range 0 to 63. + {name: "MVNshiftRO", argLength: 1, reg: gp11, asm: "MVN", aux: "Int64"}, // ^(arg0 ROR auxInt), signed shift, auxInt should be in the range 0 to 63. {name: "NEGshiftLL", argLength: 1, reg: gp11, asm: "NEG", aux: "Int64"}, // -(arg0<>auxInt), unsigned shift, auxInt should be in the range 0 to 63. {name: "NEGshiftRA", argLength: 1, reg: gp11, asm: "NEG", aux: "Int64"}, // -(arg0>>auxInt), signed shift, auxInt should be in the range 0 to 63. @@ -314,21 +315,27 @@ func init() { {name: "ANDshiftLL", argLength: 2, reg: gp21, asm: "AND", aux: "Int64"}, // arg0 & (arg1<>auxInt), unsigned shift, auxInt should be in the range 0 to 63. {name: "ANDshiftRA", argLength: 2, reg: gp21, asm: "AND", aux: "Int64"}, // arg0 & (arg1>>auxInt), signed shift, auxInt should be in the range 0 to 63. + {name: "ANDshiftRO", argLength: 2, reg: gp21, asm: "AND", aux: "Int64"}, // arg0 & (arg1 ROR auxInt), signed shift, auxInt should be in the range 0 to 63. {name: "ORshiftLL", argLength: 2, reg: gp21, asm: "ORR", aux: "Int64"}, // arg0 | arg1<>auxInt, unsigned shift, auxInt should be in the range 0 to 63. {name: "ORshiftRA", argLength: 2, reg: gp21, asm: "ORR", aux: "Int64"}, // arg0 | arg1>>auxInt, signed shift, auxInt should be in the range 0 to 63. + {name: "ORshiftRO", argLength: 2, reg: gp21, asm: "ORR", aux: "Int64"}, // arg0 | arg1 ROR auxInt, signed shift, auxInt should be in the range 0 to 63. {name: "XORshiftLL", argLength: 2, reg: gp21, asm: "EOR", aux: "Int64"}, // arg0 ^ arg1<>auxInt, unsigned shift, auxInt should be in the range 0 to 63. {name: "XORshiftRA", argLength: 2, reg: gp21, asm: "EOR", aux: "Int64"}, // arg0 ^ arg1>>auxInt, signed shift, auxInt should be in the range 0 to 63. + {name: "XORshiftRO", argLength: 2, reg: gp21, asm: "EOR", aux: "Int64"}, // arg0 ^ arg1 ROR auxInt, signed shift, auxInt should be in the range 0 to 63. {name: "BICshiftLL", argLength: 2, reg: gp21, asm: "BIC", aux: "Int64"}, // arg0 &^ (arg1<>auxInt), unsigned shift, auxInt should be in the range 0 to 63. {name: "BICshiftRA", argLength: 2, reg: gp21, asm: "BIC", aux: "Int64"}, // arg0 &^ (arg1>>auxInt), signed shift, auxInt should be in the range 0 to 63. + {name: "BICshiftRO", argLength: 2, reg: gp21, asm: "BIC", aux: "Int64"}, // arg0 &^ (arg1 ROR auxInt), signed shift, auxInt should be in the range 0 to 63. {name: "EONshiftLL", argLength: 2, reg: gp21, asm: "EON", aux: "Int64"}, // arg0 ^ ^(arg1<>auxInt), unsigned shift, auxInt should be in the range 0 to 63. {name: "EONshiftRA", argLength: 2, reg: gp21, asm: "EON", aux: "Int64"}, // arg0 ^ ^(arg1>>auxInt), signed shift, auxInt should be in the range 0 to 63. + {name: "EONshiftRO", argLength: 2, reg: gp21, asm: "EON", aux: "Int64"}, // arg0 ^ ^(arg1 ROR auxInt), signed shift, auxInt should be in the range 0 to 63. {name: "ORNshiftLL", argLength: 2, reg: gp21, asm: "ORN", aux: "Int64"}, // arg0 | ^(arg1<>auxInt), unsigned shift, auxInt should be in the range 0 to 63. {name: "ORNshiftRA", argLength: 2, reg: gp21, asm: "ORN", aux: "Int64"}, // arg0 | ^(arg1>>auxInt), signed shift, auxInt should be in the range 0 to 63. + {name: "ORNshiftRO", argLength: 2, reg: gp21, asm: "ORN", aux: "Int64"}, // arg0 | ^(arg1 ROR auxInt), signed shift, auxInt should be in the range 0 to 63. {name: "CMPshiftLL", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int64", typ: "Flags"}, // arg0 compare to arg1<>auxInt, unsigned shift, auxInt should be in the range 0 to 63. {name: "CMPshiftRA", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int64", typ: "Flags"}, // arg0 compare to arg1>>auxInt, signed shift, auxInt should be in the range 0 to 63. @@ -338,6 +345,7 @@ func init() { {name: "TSTshiftLL", argLength: 2, reg: gp2flags, asm: "TST", aux: "Int64", typ: "Flags"}, // (arg0 & arg1<>auxInt) compare to 0, unsigned shift, auxInt should be in the range 0 to 63. {name: "TSTshiftRA", argLength: 2, reg: gp2flags, asm: "TST", aux: "Int64", typ: "Flags"}, // (arg0 & arg1>>auxInt) compare to 0, signed shift, auxInt should be in the range 0 to 63. + {name: "TSTshiftRO", argLength: 2, reg: gp2flags, asm: "TST", aux: "Int64", typ: "Flags"}, // (arg0 & arg1 ROR auxInt) compare to 0, signed shift, auxInt should be in the range 0 to 63. // bitfield ops // for all bitfield ops lsb is auxInt>>8, width is auxInt&0xff diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 4ec13a6629..eb7e4b91bb 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -1412,6 +1412,7 @@ const ( OpARM64MVNshiftLL OpARM64MVNshiftRL OpARM64MVNshiftRA + OpARM64MVNshiftRO OpARM64NEGshiftLL OpARM64NEGshiftRL OpARM64NEGshiftRA @@ -1424,21 +1425,27 @@ const ( OpARM64ANDshiftLL OpARM64ANDshiftRL OpARM64ANDshiftRA + OpARM64ANDshiftRO OpARM64ORshiftLL OpARM64ORshiftRL OpARM64ORshiftRA + OpARM64ORshiftRO OpARM64XORshiftLL OpARM64XORshiftRL OpARM64XORshiftRA + OpARM64XORshiftRO OpARM64BICshiftLL OpARM64BICshiftRL OpARM64BICshiftRA + OpARM64BICshiftRO OpARM64EONshiftLL OpARM64EONshiftRL OpARM64EONshiftRA + OpARM64EONshiftRO OpARM64ORNshiftLL OpARM64ORNshiftRL OpARM64ORNshiftRA + OpARM64ORNshiftRO OpARM64CMPshiftLL OpARM64CMPshiftRL OpARM64CMPshiftRA @@ -1448,6 +1455,7 @@ const ( OpARM64TSTshiftLL OpARM64TSTshiftRL OpARM64TSTshiftRA + OpARM64TSTshiftRO OpARM64BFI OpARM64BFXIL OpARM64SBFIZ @@ -18807,6 +18815,20 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "MVNshiftRO", + auxType: auxInt64, + argLen: 1, + asm: arm64.AMVN, + reg: regInfo{ + inputs: []inputInfo{ + {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + }, + outputs: []outputInfo{ + {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30 + }, + }, + }, { name: "NEGshiftLL", auxType: auxInt64, @@ -18984,6 +19006,21 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "ANDshiftRO", + auxType: auxInt64, + argLen: 2, + asm: arm64.AAND, + reg: regInfo{ + inputs: []inputInfo{ + {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + }, + outputs: []outputInfo{ + {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30 + }, + }, + }, { name: "ORshiftLL", auxType: auxInt64, @@ -19029,6 +19066,21 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "ORshiftRO", + auxType: auxInt64, + argLen: 2, + asm: arm64.AORR, + reg: regInfo{ + inputs: []inputInfo{ + {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + }, + outputs: []outputInfo{ + {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30 + }, + }, + }, { name: "XORshiftLL", auxType: auxInt64, @@ -19074,6 +19126,21 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "XORshiftRO", + auxType: auxInt64, + argLen: 2, + asm: arm64.AEOR, + reg: regInfo{ + inputs: []inputInfo{ + {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + }, + outputs: []outputInfo{ + {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30 + }, + }, + }, { name: "BICshiftLL", auxType: auxInt64, @@ -19119,6 +19186,21 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "BICshiftRO", + auxType: auxInt64, + argLen: 2, + asm: arm64.ABIC, + reg: regInfo{ + inputs: []inputInfo{ + {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + }, + outputs: []outputInfo{ + {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30 + }, + }, + }, { name: "EONshiftLL", auxType: auxInt64, @@ -19164,6 +19246,21 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "EONshiftRO", + auxType: auxInt64, + argLen: 2, + asm: arm64.AEON, + reg: regInfo{ + inputs: []inputInfo{ + {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + }, + outputs: []outputInfo{ + {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30 + }, + }, + }, { name: "ORNshiftLL", auxType: auxInt64, @@ -19209,6 +19306,21 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "ORNshiftRO", + auxType: auxInt64, + argLen: 2, + asm: arm64.AORN, + reg: regInfo{ + inputs: []inputInfo{ + {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + }, + outputs: []outputInfo{ + {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30 + }, + }, + }, { name: "CMPshiftLL", auxType: auxInt64, @@ -19317,6 +19429,18 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "TSTshiftRO", + auxType: auxInt64, + argLen: 2, + asm: arm64.ATST, + reg: regInfo{ + inputs: []inputInfo{ + {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + }, + }, + }, { name: "BFI", auxType: auxARM64BitField, diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index 162d42773a..79f9efaebf 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -1567,6 +1567,10 @@ func rotateLeft32(v, rotate int64) int64 { return int64(bits.RotateLeft32(uint32(v), int(rotate))) } +func rotateRight64(v, rotate int64) int64 { + return int64(bits.RotateLeft64(uint64(v), int(-rotate))) +} + // encodes the lsb and width for arm(64) bitfield ops into the expected auxInt format. func armBFAuxInt(lsb, width int64) arm64BitField { if lsb < 0 || lsb > 63 { diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index 661714307a..06cc5a62b2 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -29,6 +29,8 @@ func rewriteValueARM64(v *Value) bool { return rewriteValueARM64_OpARM64ANDshiftRA(v) case OpARM64ANDshiftRL: return rewriteValueARM64_OpARM64ANDshiftRL(v) + case OpARM64ANDshiftRO: + return rewriteValueARM64_OpARM64ANDshiftRO(v) case OpARM64BIC: return rewriteValueARM64_OpARM64BIC(v) case OpARM64BICshiftLL: @@ -37,6 +39,8 @@ func rewriteValueARM64(v *Value) bool { return rewriteValueARM64_OpARM64BICshiftRA(v) case OpARM64BICshiftRL: return rewriteValueARM64_OpARM64BICshiftRL(v) + case OpARM64BICshiftRO: + return rewriteValueARM64_OpARM64BICshiftRO(v) case OpARM64CMN: return rewriteValueARM64_OpARM64CMN(v) case OpARM64CMNW: @@ -89,6 +93,8 @@ func rewriteValueARM64(v *Value) bool { return rewriteValueARM64_OpARM64EONshiftRA(v) case OpARM64EONshiftRL: return rewriteValueARM64_OpARM64EONshiftRL(v) + case OpARM64EONshiftRO: + return rewriteValueARM64_OpARM64EONshiftRO(v) case OpARM64Equal: return rewriteValueARM64_OpARM64Equal(v) case OpARM64FADDD: @@ -295,6 +301,8 @@ func rewriteValueARM64(v *Value) bool { return rewriteValueARM64_OpARM64MVNshiftRA(v) case OpARM64MVNshiftRL: return rewriteValueARM64_OpARM64MVNshiftRL(v) + case OpARM64MVNshiftRO: + return rewriteValueARM64_OpARM64MVNshiftRO(v) case OpARM64NEG: return rewriteValueARM64_OpARM64NEG(v) case OpARM64NEGshiftLL: @@ -315,6 +323,8 @@ func rewriteValueARM64(v *Value) bool { return rewriteValueARM64_OpARM64ORNshiftRA(v) case OpARM64ORNshiftRL: return rewriteValueARM64_OpARM64ORNshiftRL(v) + case OpARM64ORNshiftRO: + return rewriteValueARM64_OpARM64ORNshiftRO(v) case OpARM64ORconst: return rewriteValueARM64_OpARM64ORconst(v) case OpARM64ORshiftLL: @@ -323,6 +333,8 @@ func rewriteValueARM64(v *Value) bool { return rewriteValueARM64_OpARM64ORshiftRA(v) case OpARM64ORshiftRL: return rewriteValueARM64_OpARM64ORshiftRL(v) + case OpARM64ORshiftRO: + return rewriteValueARM64_OpARM64ORshiftRO(v) case OpARM64ROR: return rewriteValueARM64_OpARM64ROR(v) case OpARM64RORW: @@ -371,6 +383,8 @@ func rewriteValueARM64(v *Value) bool { return rewriteValueARM64_OpARM64TSTshiftRA(v) case OpARM64TSTshiftRL: return rewriteValueARM64_OpARM64TSTshiftRL(v) + case OpARM64TSTshiftRO: + return rewriteValueARM64_OpARM64TSTshiftRO(v) case OpARM64UBFIZ: return rewriteValueARM64_OpARM64UBFIZ(v) case OpARM64UBFX: @@ -393,6 +407,8 @@ func rewriteValueARM64(v *Value) bool { return rewriteValueARM64_OpARM64XORshiftRA(v) case OpARM64XORshiftRL: return rewriteValueARM64_OpARM64XORshiftRL(v) + case OpARM64XORshiftRO: + return rewriteValueARM64_OpARM64XORshiftRO(v) case OpAbs: v.Op = OpARM64FABSD return true @@ -2114,6 +2130,28 @@ func rewriteValueARM64_OpARM64AND(v *Value) bool { } break } + // match: (AND x0 x1:(RORconst [c] y)) + // cond: clobberIfDead(x1) + // result: (ANDshiftRO x0 y [c]) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x0 := v_0 + x1 := v_1 + if x1.Op != OpARM64RORconst { + continue + } + c := auxIntToInt64(x1.AuxInt) + y := x1.Args[0] + if !(clobberIfDead(x1)) { + continue + } + v.reset(OpARM64ANDshiftRO) + v.AuxInt = int64ToAuxInt(c) + v.AddArg2(x0, y) + return true + } + break + } return false } func rewriteValueARM64_OpARM64ANDconst(v *Value) bool { @@ -2403,6 +2441,60 @@ func rewriteValueARM64_OpARM64ANDshiftRL(v *Value) bool { } return false } +func rewriteValueARM64_OpARM64ANDshiftRO(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] + b := v.Block + // match: (ANDshiftRO (MOVDconst [c]) x [d]) + // result: (ANDconst [c] (RORconst x [d])) + for { + d := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64MOVDconst { + break + } + c := auxIntToInt64(v_0.AuxInt) + x := v_1 + v.reset(OpARM64ANDconst) + v.AuxInt = int64ToAuxInt(c) + v0 := b.NewValue0(v.Pos, OpARM64RORconst, x.Type) + v0.AuxInt = int64ToAuxInt(d) + v0.AddArg(x) + v.AddArg(v0) + return true + } + // match: (ANDshiftRO x (MOVDconst [c]) [d]) + // result: (ANDconst x [rotateRight64(c, d)]) + for { + d := auxIntToInt64(v.AuxInt) + x := v_0 + if v_1.Op != OpARM64MOVDconst { + break + } + c := auxIntToInt64(v_1.AuxInt) + v.reset(OpARM64ANDconst) + v.AuxInt = int64ToAuxInt(rotateRight64(c, d)) + v.AddArg(x) + return true + } + // match: (ANDshiftRO x y:(RORconst x [c]) [d]) + // cond: c==d + // result: y + for { + d := auxIntToInt64(v.AuxInt) + x := v_0 + y := v_1 + if y.Op != OpARM64RORconst { + break + } + c := auxIntToInt64(y.AuxInt) + if x != y.Args[0] || !(c == d) { + break + } + v.copyOf(y) + return true + } + return false +} func rewriteValueARM64_OpARM64BIC(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -2487,6 +2579,25 @@ func rewriteValueARM64_OpARM64BIC(v *Value) bool { v.AddArg2(x0, y) return true } + // match: (BIC x0 x1:(RORconst [c] y)) + // cond: clobberIfDead(x1) + // result: (BICshiftRO x0 y [c]) + for { + x0 := v_0 + x1 := v_1 + if x1.Op != OpARM64RORconst { + break + } + c := auxIntToInt64(x1.AuxInt) + y := x1.Args[0] + if !(clobberIfDead(x1)) { + break + } + v.reset(OpARM64BICshiftRO) + v.AuxInt = int64ToAuxInt(c) + v.AddArg2(x0, y) + return true + } return false } func rewriteValueARM64_OpARM64BICshiftLL(v *Value) bool { @@ -2597,6 +2708,42 @@ func rewriteValueARM64_OpARM64BICshiftRL(v *Value) bool { } return false } +func rewriteValueARM64_OpARM64BICshiftRO(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] + // match: (BICshiftRO x (MOVDconst [c]) [d]) + // result: (ANDconst x [^rotateRight64(c, d)]) + for { + d := auxIntToInt64(v.AuxInt) + x := v_0 + if v_1.Op != OpARM64MOVDconst { + break + } + c := auxIntToInt64(v_1.AuxInt) + v.reset(OpARM64ANDconst) + v.AuxInt = int64ToAuxInt(^rotateRight64(c, d)) + v.AddArg(x) + return true + } + // match: (BICshiftRO x (RORconst x [c]) [d]) + // cond: c==d + // result: (MOVDconst [0]) + for { + d := auxIntToInt64(v.AuxInt) + x := v_0 + if v_1.Op != OpARM64RORconst { + break + } + c := auxIntToInt64(v_1.AuxInt) + if x != v_1.Args[0] || !(c == d) { + break + } + v.reset(OpARM64MOVDconst) + v.AuxInt = int64ToAuxInt(0) + return true + } + return false +} func rewriteValueARM64_OpARM64CMN(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -3937,6 +4084,25 @@ func rewriteValueARM64_OpARM64EON(v *Value) bool { v.AddArg2(x0, y) return true } + // match: (EON x0 x1:(RORconst [c] y)) + // cond: clobberIfDead(x1) + // result: (EONshiftRO x0 y [c]) + for { + x0 := v_0 + x1 := v_1 + if x1.Op != OpARM64RORconst { + break + } + c := auxIntToInt64(x1.AuxInt) + y := x1.Args[0] + if !(clobberIfDead(x1)) { + break + } + v.reset(OpARM64EONshiftRO) + v.AuxInt = int64ToAuxInt(c) + v.AddArg2(x0, y) + return true + } return false } func rewriteValueARM64_OpARM64EONshiftLL(v *Value) bool { @@ -4047,6 +4213,42 @@ func rewriteValueARM64_OpARM64EONshiftRL(v *Value) bool { } return false } +func rewriteValueARM64_OpARM64EONshiftRO(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] + // match: (EONshiftRO x (MOVDconst [c]) [d]) + // result: (XORconst x [^rotateRight64(c, d)]) + for { + d := auxIntToInt64(v.AuxInt) + x := v_0 + if v_1.Op != OpARM64MOVDconst { + break + } + c := auxIntToInt64(v_1.AuxInt) + v.reset(OpARM64XORconst) + v.AuxInt = int64ToAuxInt(^rotateRight64(c, d)) + v.AddArg(x) + return true + } + // match: (EONshiftRO x (RORconst x [c]) [d]) + // cond: c==d + // result: (MOVDconst [-1]) + for { + d := auxIntToInt64(v.AuxInt) + x := v_0 + if v_1.Op != OpARM64RORconst { + break + } + c := auxIntToInt64(v_1.AuxInt) + if x != v_1.Args[0] || !(c == d) { + break + } + v.reset(OpARM64MOVDconst) + v.AuxInt = int64ToAuxInt(-1) + return true + } + return false +} func rewriteValueARM64_OpARM64Equal(v *Value) bool { v_0 := v.Args[0] // match: (Equal (FlagConstant [fc])) @@ -15615,6 +15817,24 @@ func rewriteValueARM64_OpARM64MVN(v *Value) bool { v.AddArg(y) return true } + // match: (MVN x:(RORconst [c] y)) + // cond: clobberIfDead(x) + // result: (MVNshiftRO [c] y) + for { + x := v_0 + if x.Op != OpARM64RORconst { + break + } + c := auxIntToInt64(x.AuxInt) + y := x.Args[0] + if !(clobberIfDead(x)) { + break + } + v.reset(OpARM64MVNshiftRO) + v.AuxInt = int64ToAuxInt(c) + v.AddArg(y) + return true + } return false } func rewriteValueARM64_OpARM64MVNshiftLL(v *Value) bool { @@ -15665,6 +15885,22 @@ func rewriteValueARM64_OpARM64MVNshiftRL(v *Value) bool { } return false } +func rewriteValueARM64_OpARM64MVNshiftRO(v *Value) bool { + v_0 := v.Args[0] + // match: (MVNshiftRO (MOVDconst [c]) [d]) + // result: (MOVDconst [^rotateRight64(c, d)]) + for { + d := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64MOVDconst { + break + } + c := auxIntToInt64(v_0.AuxInt) + v.reset(OpARM64MOVDconst) + v.AuxInt = int64ToAuxInt(^rotateRight64(c, d)) + return true + } + return false +} func rewriteValueARM64_OpARM64NEG(v *Value) bool { v_0 := v.Args[0] // match: (NEG (MUL x y)) @@ -15954,6 +16190,28 @@ func rewriteValueARM64_OpARM64OR(v *Value) bool { } break } + // match: (OR x0 x1:(RORconst [c] y)) + // cond: clobberIfDead(x1) + // result: (ORshiftRO x0 y [c]) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x0 := v_0 + x1 := v_1 + if x1.Op != OpARM64RORconst { + continue + } + c := auxIntToInt64(x1.AuxInt) + y := x1.Args[0] + if !(clobberIfDead(x1)) { + continue + } + v.reset(OpARM64ORshiftRO) + v.AuxInt = int64ToAuxInt(c) + v.AddArg2(x0, y) + return true + } + break + } // match: (OR (SLL x (ANDconst [63] y)) (CSEL0 [cc] (SRL x (SUB (MOVDconst [64]) (ANDconst [63] y))) (CMPconst [64] (SUB (MOVDconst [64]) (ANDconst [63] y))))) // cond: cc == OpARM64LessThanU // result: (ROR x (NEG y)) @@ -17923,6 +18181,25 @@ func rewriteValueARM64_OpARM64ORN(v *Value) bool { v.AddArg2(x0, y) return true } + // match: (ORN x0 x1:(RORconst [c] y)) + // cond: clobberIfDead(x1) + // result: (ORNshiftRO x0 y [c]) + for { + x0 := v_0 + x1 := v_1 + if x1.Op != OpARM64RORconst { + break + } + c := auxIntToInt64(x1.AuxInt) + y := x1.Args[0] + if !(clobberIfDead(x1)) { + break + } + v.reset(OpARM64ORNshiftRO) + v.AuxInt = int64ToAuxInt(c) + v.AddArg2(x0, y) + return true + } return false } func rewriteValueARM64_OpARM64ORNshiftLL(v *Value) bool { @@ -18033,6 +18310,42 @@ func rewriteValueARM64_OpARM64ORNshiftRL(v *Value) bool { } return false } +func rewriteValueARM64_OpARM64ORNshiftRO(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] + // match: (ORNshiftRO x (MOVDconst [c]) [d]) + // result: (ORconst x [^rotateRight64(c, d)]) + for { + d := auxIntToInt64(v.AuxInt) + x := v_0 + if v_1.Op != OpARM64MOVDconst { + break + } + c := auxIntToInt64(v_1.AuxInt) + v.reset(OpARM64ORconst) + v.AuxInt = int64ToAuxInt(^rotateRight64(c, d)) + v.AddArg(x) + return true + } + // match: (ORNshiftRO x (RORconst x [c]) [d]) + // cond: c==d + // result: (MOVDconst [-1]) + for { + d := auxIntToInt64(v.AuxInt) + x := v_0 + if v_1.Op != OpARM64RORconst { + break + } + c := auxIntToInt64(v_1.AuxInt) + if x != v_1.Args[0] || !(c == d) { + break + } + v.reset(OpARM64MOVDconst) + v.AuxInt = int64ToAuxInt(-1) + return true + } + return false +} func rewriteValueARM64_OpARM64ORconst(v *Value) bool { v_0 := v.Args[0] // match: (ORconst [0] x) @@ -19970,6 +20283,60 @@ func rewriteValueARM64_OpARM64ORshiftRL(v *Value) bool { } return false } +func rewriteValueARM64_OpARM64ORshiftRO(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] + b := v.Block + // match: (ORshiftRO (MOVDconst [c]) x [d]) + // result: (ORconst [c] (RORconst x [d])) + for { + d := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64MOVDconst { + break + } + c := auxIntToInt64(v_0.AuxInt) + x := v_1 + v.reset(OpARM64ORconst) + v.AuxInt = int64ToAuxInt(c) + v0 := b.NewValue0(v.Pos, OpARM64RORconst, x.Type) + v0.AuxInt = int64ToAuxInt(d) + v0.AddArg(x) + v.AddArg(v0) + return true + } + // match: (ORshiftRO x (MOVDconst [c]) [d]) + // result: (ORconst x [rotateRight64(c, d)]) + for { + d := auxIntToInt64(v.AuxInt) + x := v_0 + if v_1.Op != OpARM64MOVDconst { + break + } + c := auxIntToInt64(v_1.AuxInt) + v.reset(OpARM64ORconst) + v.AuxInt = int64ToAuxInt(rotateRight64(c, d)) + v.AddArg(x) + return true + } + // match: (ORshiftRO x y:(RORconst x [c]) [d]) + // cond: c==d + // result: y + for { + d := auxIntToInt64(v.AuxInt) + x := v_0 + y := v_1 + if y.Op != OpARM64RORconst { + break + } + c := auxIntToInt64(y.AuxInt) + if x != y.Args[0] || !(c == d) { + break + } + v.copyOf(y) + return true + } + return false +} func rewriteValueARM64_OpARM64ROR(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -21198,6 +21565,28 @@ func rewriteValueARM64_OpARM64TST(v *Value) bool { } break } + // match: (TST x0 x1:(RORconst [c] y)) + // cond: clobberIfDead(x1) + // result: (TSTshiftRO x0 y [c]) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x0 := v_0 + x1 := v_1 + if x1.Op != OpARM64RORconst { + continue + } + c := auxIntToInt64(x1.AuxInt) + y := x1.Args[0] + if !(clobberIfDead(x1)) { + continue + } + v.reset(OpARM64TSTshiftRO) + v.AuxInt = int64ToAuxInt(c) + v.AddArg2(x0, y) + return true + } + break + } return false } func rewriteValueARM64_OpARM64TSTW(v *Value) bool { @@ -21364,6 +21753,43 @@ func rewriteValueARM64_OpARM64TSTshiftRL(v *Value) bool { } return false } +func rewriteValueARM64_OpARM64TSTshiftRO(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] + b := v.Block + // match: (TSTshiftRO (MOVDconst [c]) x [d]) + // result: (TSTconst [c] (RORconst x [d])) + for { + d := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64MOVDconst { + break + } + c := auxIntToInt64(v_0.AuxInt) + x := v_1 + v.reset(OpARM64TSTconst) + v.AuxInt = int64ToAuxInt(c) + v0 := b.NewValue0(v.Pos, OpARM64RORconst, x.Type) + v0.AuxInt = int64ToAuxInt(d) + v0.AddArg(x) + v.AddArg(v0) + return true + } + // match: (TSTshiftRO x (MOVDconst [c]) [d]) + // result: (TSTconst x [rotateRight64(c, d)]) + for { + d := auxIntToInt64(v.AuxInt) + x := v_0 + if v_1.Op != OpARM64MOVDconst { + break + } + c := auxIntToInt64(v_1.AuxInt) + v.reset(OpARM64TSTconst) + v.AuxInt = int64ToAuxInt(rotateRight64(c, d)) + v.AddArg(x) + return true + } + return false +} func rewriteValueARM64_OpARM64UBFIZ(v *Value) bool { v_0 := v.Args[0] // match: (UBFIZ [bfc] (SLLconst [sc] x)) @@ -21823,6 +22249,28 @@ func rewriteValueARM64_OpARM64XOR(v *Value) bool { } break } + // match: (XOR x0 x1:(RORconst [c] y)) + // cond: clobberIfDead(x1) + // result: (XORshiftRO x0 y [c]) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x0 := v_0 + x1 := v_1 + if x1.Op != OpARM64RORconst { + continue + } + c := auxIntToInt64(x1.AuxInt) + y := x1.Args[0] + if !(clobberIfDead(x1)) { + continue + } + v.reset(OpARM64XORshiftRO) + v.AuxInt = int64ToAuxInt(c) + v.AddArg2(x0, y) + return true + } + break + } // match: (XOR (SLL x (ANDconst [63] y)) (CSEL0 [cc] (SRL x (SUB (MOVDconst [64]) (ANDconst [63] y))) (CMPconst [64] (SUB (MOVDconst [64]) (ANDconst [63] y))))) // cond: cc == OpARM64LessThanU // result: (ROR x (NEG y)) @@ -22512,6 +22960,60 @@ func rewriteValueARM64_OpARM64XORshiftRL(v *Value) bool { } return false } +func rewriteValueARM64_OpARM64XORshiftRO(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] + b := v.Block + // match: (XORshiftRO (MOVDconst [c]) x [d]) + // result: (XORconst [c] (RORconst x [d])) + for { + d := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64MOVDconst { + break + } + c := auxIntToInt64(v_0.AuxInt) + x := v_1 + v.reset(OpARM64XORconst) + v.AuxInt = int64ToAuxInt(c) + v0 := b.NewValue0(v.Pos, OpARM64RORconst, x.Type) + v0.AuxInt = int64ToAuxInt(d) + v0.AddArg(x) + v.AddArg(v0) + return true + } + // match: (XORshiftRO x (MOVDconst [c]) [d]) + // result: (XORconst x [rotateRight64(c, d)]) + for { + d := auxIntToInt64(v.AuxInt) + x := v_0 + if v_1.Op != OpARM64MOVDconst { + break + } + c := auxIntToInt64(v_1.AuxInt) + v.reset(OpARM64XORconst) + v.AuxInt = int64ToAuxInt(rotateRight64(c, d)) + v.AddArg(x) + return true + } + // match: (XORshiftRO x (RORconst x [c]) [d]) + // cond: c==d + // result: (MOVDconst [0]) + for { + d := auxIntToInt64(v.AuxInt) + x := v_0 + if v_1.Op != OpARM64RORconst { + break + } + c := auxIntToInt64(v_1.AuxInt) + if x != v_1.Args[0] || !(c == d) { + break + } + v.reset(OpARM64MOVDconst) + v.AuxInt = int64ToAuxInt(0) + return true + } + return false +} func rewriteValueARM64_OpAddr(v *Value) bool { v_0 := v.Args[0] // match: (Addr {sym} base) diff --git a/src/cmd/internal/obj/arm64/a.out.go b/src/cmd/internal/obj/arm64/a.out.go index bf75bb4a89..aa7c54df9a 100644 --- a/src/cmd/internal/obj/arm64/a.out.go +++ b/src/cmd/internal/obj/arm64/a.out.go @@ -1060,9 +1060,10 @@ const ( const ( // shift types - SHIFT_LL = 0 << 22 - SHIFT_LR = 1 << 22 - SHIFT_AR = 2 << 22 + SHIFT_LL = 0 << 22 + SHIFT_LR = 1 << 22 + SHIFT_AR = 2 << 22 + SHIFT_ROR = 3 << 22 ) // Arrangement for ARM64 SIMD instructions diff --git a/test/codegen/rotate.go b/test/codegen/rotate.go index 70489a2adc..204efaeafc 100644 --- a/test/codegen/rotate.go +++ b/test/codegen/rotate.go @@ -226,3 +226,26 @@ func checkMaskedRotate32(a []uint32, r int) { a[i] = bits.RotateLeft32(a[3], 4) & 0xFFF00FFF i++ } + +// combined arithmetic and rotate on arm64 +func checkArithmeticWithRotate(a *[1000]uint64) { + // arm64: "AND\tR[0-9]+@>51, R[0-9]+, R[0-9]+" + a[2] = a[1] & bits.RotateLeft64(a[0], 13) + // arm64: "ORR\tR[0-9]+@>51, R[0-9]+, R[0-9]+" + a[5] = a[4] | bits.RotateLeft64(a[3], 13) + // arm64: "EOR\tR[0-9]+@>51, R[0-9]+, R[0-9]+" + a[8] = a[7] ^ bits.RotateLeft64(a[6], 13) + // arm64: "MVN\tR[0-9]+@>51, R[0-9]+" + a[10] = ^bits.RotateLeft64(a[9], 13) + // arm64: "BIC\tR[0-9]+@>51, R[0-9]+, R[0-9]+" + a[13] = a[12] &^ bits.RotateLeft64(a[11], 13) + // arm64: "EON\tR[0-9]+@>51, R[0-9]+, R[0-9]+" + a[16] = a[15] ^ ^bits.RotateLeft64(a[14], 13) + // arm64: "ORN\tR[0-9]+@>51, R[0-9]+, R[0-9]+" + a[19] = a[18] | ^bits.RotateLeft64(a[17], 13) + // arm64: "TST\tR[0-9]+@>51, R[0-9]+" + if a[18]&bits.RotateLeft64(a[19], 13) == 0 { + a[20] = 1 + } + +} -- GitLab From 9ebe7c8ec6e95b73a7b0e480fe10f2188ef4928a Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Thu, 16 Sep 2021 09:42:06 -0700 Subject: [PATCH 1205/2500] go/test: add a test for issue 48344 This was fixed by https://go-review.googlesource.com/c/go/+/349613 and https://go-review.googlesource.com/c/go/+/349614 Fixes #48344 Change-Id: I4c62109fd34b20566b07fcca87fb3946a5702fef Reviewed-on: https://go-review.googlesource.com/c/go/+/350309 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Dan Scales --- test/typeparam/issue48344.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 test/typeparam/issue48344.go diff --git a/test/typeparam/issue48344.go b/test/typeparam/issue48344.go new file mode 100644 index 0000000000..7ea539cfcc --- /dev/null +++ b/test/typeparam/issue48344.go @@ -0,0 +1,26 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type G[T any] interface { + g() +} + +type Foo[T any] struct { +} + +func (foo *Foo[T]) g() { + +} + +func f[T any]() { + v := []G[T]{} + v = append(v, &Foo[T]{}) +} +func main() { + f[int]() +} -- GitLab From eff27e858b771bf5e0b5e7e836827c7d2941e6d4 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Sun, 19 Sep 2021 21:09:57 -0700 Subject: [PATCH 1206/2500] cmd/compile: ensure constant shift amounts are in range for arm Ensure constant shift amounts are in the range [0-31]. When shift amounts are out of range, bad things happen. Shift amounts out of range occur when lowering 64-bit shifts (we take an in-range shift s in [0-63] and calculate s-32 and 32-s, both of which might be out of [0-31]). The constant shift operations themselves still work, but their shift amounts get copied unmolested to operations like ORshiftLL which use only the low 5 bits. That changes an operation like <<100 which unconditionally produces 0, to <<4, which doesn't. Fixes #48476 Change-Id: I87363ef2b4ceaf3b2e316426064626efdfbb8ee3 Reviewed-on: https://go-review.googlesource.com/c/go/+/350969 Trust: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/compile/internal/ssa/gen/ARM.rules | 114 ++++----- src/cmd/compile/internal/ssa/gen/ARMOps.go | 9 +- .../compile/internal/ssa/gen/genericOps.go | 2 +- src/cmd/compile/internal/ssa/rewriteARM.go | 240 +++++++++++++++++- test/fixedbugs/issue48476.go | 21 ++ 5 files changed, 318 insertions(+), 68 deletions(-) create mode 100644 test/fixedbugs/issue48476.go diff --git a/src/cmd/compile/internal/ssa/gen/ARM.rules b/src/cmd/compile/internal/ssa/gen/ARM.rules index 8a755b404b..a6686237be 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM.rules @@ -498,9 +498,9 @@ (XOR x (MOVWconst [c])) => (XORconst [c] x) (BIC x (MOVWconst [c])) => (BICconst [c] x) -(SLL x (MOVWconst [c])) => (SLLconst x [c&31]) // Note: I don't think we ever generate bad constant shifts (i.e. c>=32) -(SRL x (MOVWconst [c])) => (SRLconst x [c&31]) -(SRA x (MOVWconst [c])) => (SRAconst x [c&31]) +(SLL x (MOVWconst [c])) && 0 <= c && c < 32 => (SLLconst x [c]) +(SRL x (MOVWconst [c])) && 0 <= c && c < 32 => (SRLconst x [c]) +(SRA x (MOVWconst [c])) && 0 <= c && c < 32 => (SRAconst x [c]) (CMP x (MOVWconst [c])) => (CMPconst [c] x) (CMP (MOVWconst [c]) x) => (InvertFlags (CMPconst [c] x)) @@ -1075,60 +1075,60 @@ (CMNshiftRL x (MOVWconst [c]) [d]) => (CMNconst x [int32(uint32(c)>>uint64(d))]) (CMNshiftRA x (MOVWconst [c]) [d]) => (CMNconst x [c>>uint64(d)]) -(ADDshiftLLreg x y (MOVWconst [c])) => (ADDshiftLL x y [c]) -(ADDshiftRLreg x y (MOVWconst [c])) => (ADDshiftRL x y [c]) -(ADDshiftRAreg x y (MOVWconst [c])) => (ADDshiftRA x y [c]) -(ADCshiftLLreg x y (MOVWconst [c]) flags) => (ADCshiftLL x y [c] flags) -(ADCshiftRLreg x y (MOVWconst [c]) flags) => (ADCshiftRL x y [c] flags) -(ADCshiftRAreg x y (MOVWconst [c]) flags) => (ADCshiftRA x y [c] flags) -(ADDSshiftLLreg x y (MOVWconst [c])) => (ADDSshiftLL x y [c]) -(ADDSshiftRLreg x y (MOVWconst [c])) => (ADDSshiftRL x y [c]) -(ADDSshiftRAreg x y (MOVWconst [c])) => (ADDSshiftRA x y [c]) -(SUBshiftLLreg x y (MOVWconst [c])) => (SUBshiftLL x y [c]) -(SUBshiftRLreg x y (MOVWconst [c])) => (SUBshiftRL x y [c]) -(SUBshiftRAreg x y (MOVWconst [c])) => (SUBshiftRA x y [c]) -(SBCshiftLLreg x y (MOVWconst [c]) flags) => (SBCshiftLL x y [c] flags) -(SBCshiftRLreg x y (MOVWconst [c]) flags) => (SBCshiftRL x y [c] flags) -(SBCshiftRAreg x y (MOVWconst [c]) flags) => (SBCshiftRA x y [c] flags) -(SUBSshiftLLreg x y (MOVWconst [c])) => (SUBSshiftLL x y [c]) -(SUBSshiftRLreg x y (MOVWconst [c])) => (SUBSshiftRL x y [c]) -(SUBSshiftRAreg x y (MOVWconst [c])) => (SUBSshiftRA x y [c]) -(RSBshiftLLreg x y (MOVWconst [c])) => (RSBshiftLL x y [c]) -(RSBshiftRLreg x y (MOVWconst [c])) => (RSBshiftRL x y [c]) -(RSBshiftRAreg x y (MOVWconst [c])) => (RSBshiftRA x y [c]) -(RSCshiftLLreg x y (MOVWconst [c]) flags) => (RSCshiftLL x y [c] flags) -(RSCshiftRLreg x y (MOVWconst [c]) flags) => (RSCshiftRL x y [c] flags) -(RSCshiftRAreg x y (MOVWconst [c]) flags) => (RSCshiftRA x y [c] flags) -(RSBSshiftLLreg x y (MOVWconst [c])) => (RSBSshiftLL x y [c]) -(RSBSshiftRLreg x y (MOVWconst [c])) => (RSBSshiftRL x y [c]) -(RSBSshiftRAreg x y (MOVWconst [c])) => (RSBSshiftRA x y [c]) -(ANDshiftLLreg x y (MOVWconst [c])) => (ANDshiftLL x y [c]) -(ANDshiftRLreg x y (MOVWconst [c])) => (ANDshiftRL x y [c]) -(ANDshiftRAreg x y (MOVWconst [c])) => (ANDshiftRA x y [c]) -(ORshiftLLreg x y (MOVWconst [c])) => (ORshiftLL x y [c]) -(ORshiftRLreg x y (MOVWconst [c])) => (ORshiftRL x y [c]) -(ORshiftRAreg x y (MOVWconst [c])) => (ORshiftRA x y [c]) -(XORshiftLLreg x y (MOVWconst [c])) => (XORshiftLL x y [c]) -(XORshiftRLreg x y (MOVWconst [c])) => (XORshiftRL x y [c]) -(XORshiftRAreg x y (MOVWconst [c])) => (XORshiftRA x y [c]) -(BICshiftLLreg x y (MOVWconst [c])) => (BICshiftLL x y [c]) -(BICshiftRLreg x y (MOVWconst [c])) => (BICshiftRL x y [c]) -(BICshiftRAreg x y (MOVWconst [c])) => (BICshiftRA x y [c]) -(MVNshiftLLreg x (MOVWconst [c])) => (MVNshiftLL x [c]) -(MVNshiftRLreg x (MOVWconst [c])) => (MVNshiftRL x [c]) -(MVNshiftRAreg x (MOVWconst [c])) => (MVNshiftRA x [c]) -(CMPshiftLLreg x y (MOVWconst [c])) => (CMPshiftLL x y [c]) -(CMPshiftRLreg x y (MOVWconst [c])) => (CMPshiftRL x y [c]) -(CMPshiftRAreg x y (MOVWconst [c])) => (CMPshiftRA x y [c]) -(TSTshiftLLreg x y (MOVWconst [c])) => (TSTshiftLL x y [c]) -(TSTshiftRLreg x y (MOVWconst [c])) => (TSTshiftRL x y [c]) -(TSTshiftRAreg x y (MOVWconst [c])) => (TSTshiftRA x y [c]) -(TEQshiftLLreg x y (MOVWconst [c])) => (TEQshiftLL x y [c]) -(TEQshiftRLreg x y (MOVWconst [c])) => (TEQshiftRL x y [c]) -(TEQshiftRAreg x y (MOVWconst [c])) => (TEQshiftRA x y [c]) -(CMNshiftLLreg x y (MOVWconst [c])) => (CMNshiftLL x y [c]) -(CMNshiftRLreg x y (MOVWconst [c])) => (CMNshiftRL x y [c]) -(CMNshiftRAreg x y (MOVWconst [c])) => (CMNshiftRA x y [c]) +(ADDshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (ADDshiftLL x y [c]) +(ADDshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (ADDshiftRL x y [c]) +(ADDshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (ADDshiftRA x y [c]) +(ADCshiftLLreg x y (MOVWconst [c]) flags) && 0 <= c && c < 32 => (ADCshiftLL x y [c] flags) +(ADCshiftRLreg x y (MOVWconst [c]) flags) && 0 <= c && c < 32 => (ADCshiftRL x y [c] flags) +(ADCshiftRAreg x y (MOVWconst [c]) flags) && 0 <= c && c < 32 => (ADCshiftRA x y [c] flags) +(ADDSshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (ADDSshiftLL x y [c]) +(ADDSshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (ADDSshiftRL x y [c]) +(ADDSshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (ADDSshiftRA x y [c]) +(SUBshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (SUBshiftLL x y [c]) +(SUBshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (SUBshiftRL x y [c]) +(SUBshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (SUBshiftRA x y [c]) +(SBCshiftLLreg x y (MOVWconst [c]) flags) && 0 <= c && c < 32 => (SBCshiftLL x y [c] flags) +(SBCshiftRLreg x y (MOVWconst [c]) flags) && 0 <= c && c < 32 => (SBCshiftRL x y [c] flags) +(SBCshiftRAreg x y (MOVWconst [c]) flags) && 0 <= c && c < 32 => (SBCshiftRA x y [c] flags) +(SUBSshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (SUBSshiftLL x y [c]) +(SUBSshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (SUBSshiftRL x y [c]) +(SUBSshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (SUBSshiftRA x y [c]) +(RSBshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (RSBshiftLL x y [c]) +(RSBshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (RSBshiftRL x y [c]) +(RSBshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (RSBshiftRA x y [c]) +(RSCshiftLLreg x y (MOVWconst [c]) flags) && 0 <= c && c < 32 => (RSCshiftLL x y [c] flags) +(RSCshiftRLreg x y (MOVWconst [c]) flags) && 0 <= c && c < 32 => (RSCshiftRL x y [c] flags) +(RSCshiftRAreg x y (MOVWconst [c]) flags) && 0 <= c && c < 32 => (RSCshiftRA x y [c] flags) +(RSBSshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (RSBSshiftLL x y [c]) +(RSBSshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (RSBSshiftRL x y [c]) +(RSBSshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (RSBSshiftRA x y [c]) +(ANDshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (ANDshiftLL x y [c]) +(ANDshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (ANDshiftRL x y [c]) +(ANDshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (ANDshiftRA x y [c]) +(ORshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (ORshiftLL x y [c]) +(ORshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (ORshiftRL x y [c]) +(ORshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (ORshiftRA x y [c]) +(XORshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (XORshiftLL x y [c]) +(XORshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (XORshiftRL x y [c]) +(XORshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (XORshiftRA x y [c]) +(BICshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (BICshiftLL x y [c]) +(BICshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (BICshiftRL x y [c]) +(BICshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (BICshiftRA x y [c]) +(MVNshiftLLreg x (MOVWconst [c])) && 0 <= c && c < 32 => (MVNshiftLL x [c]) +(MVNshiftRLreg x (MOVWconst [c])) && 0 <= c && c < 32 => (MVNshiftRL x [c]) +(MVNshiftRAreg x (MOVWconst [c])) && 0 <= c && c < 32 => (MVNshiftRA x [c]) +(CMPshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (CMPshiftLL x y [c]) +(CMPshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (CMPshiftRL x y [c]) +(CMPshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (CMPshiftRA x y [c]) +(TSTshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (TSTshiftLL x y [c]) +(TSTshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (TSTshiftRL x y [c]) +(TSTshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (TSTshiftRA x y [c]) +(TEQshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (TEQshiftLL x y [c]) +(TEQshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (TEQshiftRL x y [c]) +(TEQshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (TEQshiftRA x y [c]) +(CMNshiftLLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (CMNshiftLL x y [c]) +(CMNshiftRLreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (CMNshiftRL x y [c]) +(CMNshiftRAreg x y (MOVWconst [c])) && 0 <= c && c < 32 => (CMNshiftRA x y [c]) // Generate rotates (ADDshiftLL [c] (SRLconst x [32-c]) x) => (SRRconst [32-c] x) diff --git a/src/cmd/compile/internal/ssa/gen/ARMOps.go b/src/cmd/compile/internal/ssa/gen/ARMOps.go index eea0703f2c..75ba769724 100644 --- a/src/cmd/compile/internal/ssa/gen/ARMOps.go +++ b/src/cmd/compile/internal/ssa/gen/ARMOps.go @@ -228,14 +228,15 @@ func init() { // shifts {name: "SLL", argLength: 2, reg: gp21, asm: "SLL"}, // arg0 << arg1, shift amount is mod 256 - {name: "SLLconst", argLength: 1, reg: gp11, asm: "SLL", aux: "Int32"}, // arg0 << auxInt + {name: "SLLconst", argLength: 1, reg: gp11, asm: "SLL", aux: "Int32"}, // arg0 << auxInt, 0 <= auxInt < 32 {name: "SRL", argLength: 2, reg: gp21, asm: "SRL"}, // arg0 >> arg1, unsigned, shift amount is mod 256 - {name: "SRLconst", argLength: 1, reg: gp11, asm: "SRL", aux: "Int32"}, // arg0 >> auxInt, unsigned + {name: "SRLconst", argLength: 1, reg: gp11, asm: "SRL", aux: "Int32"}, // arg0 >> auxInt, unsigned, 0 <= auxInt < 32 {name: "SRA", argLength: 2, reg: gp21, asm: "SRA"}, // arg0 >> arg1, signed, shift amount is mod 256 - {name: "SRAconst", argLength: 1, reg: gp11, asm: "SRA", aux: "Int32"}, // arg0 >> auxInt, signed + {name: "SRAconst", argLength: 1, reg: gp11, asm: "SRA", aux: "Int32"}, // arg0 >> auxInt, signed, 0 <= auxInt < 32 {name: "SRR", argLength: 2, reg: gp21}, // arg0 right rotate by arg1 bits - {name: "SRRconst", argLength: 1, reg: gp11, aux: "Int32"}, // arg0 right rotate by auxInt bits + {name: "SRRconst", argLength: 1, reg: gp11, aux: "Int32"}, // arg0 right rotate by auxInt bits, 0 <= auxInt < 32 + // auxInt for all of these satisfy 0 <= auxInt < 32 {name: "ADDshiftLL", argLength: 2, reg: gp21, asm: "ADD", aux: "Int32"}, // arg0 + arg1<>auxInt, unsigned shift {name: "ADDshiftRA", argLength: 2, reg: gp21, asm: "ADD", aux: "Int32"}, // arg0 + arg1>>auxInt, signed shift diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index a0166f58f4..984552900f 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -106,7 +106,7 @@ var genericOps = []opData{ // For shifts, AxB means the shifted value has A bits and the shift amount has B bits. // Shift amounts are considered unsigned. - // If arg1 is known to be less than the number of bits in arg0, + // If arg1 is known to be nonnegative and less than the number of bits in arg0, // then auxInt may be set to 1. // This enables better code generation on some platforms. {name: "Lsh8x8", argLength: 2, aux: "Bool"}, // arg0 << arg1 diff --git a/src/cmd/compile/internal/ssa/rewriteARM.go b/src/cmd/compile/internal/ssa/rewriteARM.go index 6807507218..2c536e1a52 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM.go +++ b/src/cmd/compile/internal/ssa/rewriteARM.go @@ -1124,6 +1124,7 @@ func rewriteValueARM_OpARMADCshiftLLreg(v *Value) bool { return true } // match: (ADCshiftLLreg x y (MOVWconst [c]) flags) + // cond: 0 <= c && c < 32 // result: (ADCshiftLL x y [c] flags) for { x := v_0 @@ -1133,6 +1134,9 @@ func rewriteValueARM_OpARMADCshiftLLreg(v *Value) bool { } c := auxIntToInt32(v_2.AuxInt) flags := v_3 + if !(0 <= c && c < 32) { + break + } v.reset(OpARMADCshiftLL) v.AuxInt = int32ToAuxInt(c) v.AddArg3(x, y, flags) @@ -1204,6 +1208,7 @@ func rewriteValueARM_OpARMADCshiftRAreg(v *Value) bool { return true } // match: (ADCshiftRAreg x y (MOVWconst [c]) flags) + // cond: 0 <= c && c < 32 // result: (ADCshiftRA x y [c] flags) for { x := v_0 @@ -1213,6 +1218,9 @@ func rewriteValueARM_OpARMADCshiftRAreg(v *Value) bool { } c := auxIntToInt32(v_2.AuxInt) flags := v_3 + if !(0 <= c && c < 32) { + break + } v.reset(OpARMADCshiftRA) v.AuxInt = int32ToAuxInt(c) v.AddArg3(x, y, flags) @@ -1284,6 +1292,7 @@ func rewriteValueARM_OpARMADCshiftRLreg(v *Value) bool { return true } // match: (ADCshiftRLreg x y (MOVWconst [c]) flags) + // cond: 0 <= c && c < 32 // result: (ADCshiftRL x y [c] flags) for { x := v_0 @@ -1293,6 +1302,9 @@ func rewriteValueARM_OpARMADCshiftRLreg(v *Value) bool { } c := auxIntToInt32(v_2.AuxInt) flags := v_3 + if !(0 <= c && c < 32) { + break + } v.reset(OpARMADCshiftRL) v.AuxInt = int32ToAuxInt(c) v.AddArg3(x, y, flags) @@ -1745,6 +1757,7 @@ func rewriteValueARM_OpARMADDSshiftLLreg(v *Value) bool { return true } // match: (ADDSshiftLLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (ADDSshiftLL x y [c]) for { x := v_0 @@ -1753,6 +1766,9 @@ func rewriteValueARM_OpARMADDSshiftLLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMADDSshiftLL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -1819,6 +1835,7 @@ func rewriteValueARM_OpARMADDSshiftRAreg(v *Value) bool { return true } // match: (ADDSshiftRAreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (ADDSshiftRA x y [c]) for { x := v_0 @@ -1827,6 +1844,9 @@ func rewriteValueARM_OpARMADDSshiftRAreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMADDSshiftRA) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -1893,6 +1913,7 @@ func rewriteValueARM_OpARMADDSshiftRLreg(v *Value) bool { return true } // match: (ADDSshiftRLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (ADDSshiftRL x y [c]) for { x := v_0 @@ -1901,6 +1922,9 @@ func rewriteValueARM_OpARMADDSshiftRLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMADDSshiftRL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -2129,6 +2153,7 @@ func rewriteValueARM_OpARMADDshiftLLreg(v *Value) bool { return true } // match: (ADDshiftLLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (ADDshiftLL x y [c]) for { x := v_0 @@ -2137,6 +2162,9 @@ func rewriteValueARM_OpARMADDshiftLLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMADDshiftLL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -2203,6 +2231,7 @@ func rewriteValueARM_OpARMADDshiftRAreg(v *Value) bool { return true } // match: (ADDshiftRAreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (ADDshiftRA x y [c]) for { x := v_0 @@ -2211,6 +2240,9 @@ func rewriteValueARM_OpARMADDshiftRAreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMADDshiftRA) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -2293,6 +2325,7 @@ func rewriteValueARM_OpARMADDshiftRLreg(v *Value) bool { return true } // match: (ADDshiftRLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (ADDshiftRL x y [c]) for { x := v_0 @@ -2301,6 +2334,9 @@ func rewriteValueARM_OpARMADDshiftRLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMADDshiftRL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -2660,6 +2696,7 @@ func rewriteValueARM_OpARMANDshiftLLreg(v *Value) bool { return true } // match: (ANDshiftLLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (ANDshiftLL x y [c]) for { x := v_0 @@ -2668,6 +2705,9 @@ func rewriteValueARM_OpARMANDshiftLLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMANDshiftLL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -2751,6 +2791,7 @@ func rewriteValueARM_OpARMANDshiftRAreg(v *Value) bool { return true } // match: (ANDshiftRAreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (ANDshiftRA x y [c]) for { x := v_0 @@ -2759,6 +2800,9 @@ func rewriteValueARM_OpARMANDshiftRAreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMANDshiftRA) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -2842,6 +2886,7 @@ func rewriteValueARM_OpARMANDshiftRLreg(v *Value) bool { return true } // match: (ANDshiftRLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (ANDshiftRL x y [c]) for { x := v_0 @@ -2850,6 +2895,9 @@ func rewriteValueARM_OpARMANDshiftRLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMANDshiftRL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -3120,6 +3168,7 @@ func rewriteValueARM_OpARMBICshiftLLreg(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] // match: (BICshiftLLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (BICshiftLL x y [c]) for { x := v_0 @@ -3128,6 +3177,9 @@ func rewriteValueARM_OpARMBICshiftLLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMBICshiftLL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -3176,6 +3228,7 @@ func rewriteValueARM_OpARMBICshiftRAreg(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] // match: (BICshiftRAreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (BICshiftRA x y [c]) for { x := v_0 @@ -3184,6 +3237,9 @@ func rewriteValueARM_OpARMBICshiftRAreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMBICshiftRA) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -3232,6 +3288,7 @@ func rewriteValueARM_OpARMBICshiftRLreg(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] // match: (BICshiftRLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (BICshiftRL x y [c]) for { x := v_0 @@ -3240,6 +3297,9 @@ func rewriteValueARM_OpARMBICshiftRLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMBICshiftRL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -3442,6 +3502,7 @@ func rewriteValueARM_OpARMCMNshiftLLreg(v *Value) bool { return true } // match: (CMNshiftLLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (CMNshiftLL x y [c]) for { x := v_0 @@ -3450,6 +3511,9 @@ func rewriteValueARM_OpARMCMNshiftLLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMCMNshiftLL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -3516,6 +3580,7 @@ func rewriteValueARM_OpARMCMNshiftRAreg(v *Value) bool { return true } // match: (CMNshiftRAreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (CMNshiftRA x y [c]) for { x := v_0 @@ -3524,6 +3589,9 @@ func rewriteValueARM_OpARMCMNshiftRAreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMCMNshiftRA) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -3590,6 +3658,7 @@ func rewriteValueARM_OpARMCMNshiftRLreg(v *Value) bool { return true } // match: (CMNshiftRLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (CMNshiftRL x y [c]) for { x := v_0 @@ -3598,6 +3667,9 @@ func rewriteValueARM_OpARMCMNshiftRLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMCMNshiftRL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -4095,6 +4167,7 @@ func rewriteValueARM_OpARMCMPshiftLLreg(v *Value) bool { return true } // match: (CMPshiftLLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (CMPshiftLL x y [c]) for { x := v_0 @@ -4103,6 +4176,9 @@ func rewriteValueARM_OpARMCMPshiftLLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMCMPshiftLL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -4173,6 +4249,7 @@ func rewriteValueARM_OpARMCMPshiftRAreg(v *Value) bool { return true } // match: (CMPshiftRAreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (CMPshiftRA x y [c]) for { x := v_0 @@ -4181,6 +4258,9 @@ func rewriteValueARM_OpARMCMPshiftRAreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMCMPshiftRA) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -4251,6 +4331,7 @@ func rewriteValueARM_OpARMCMPshiftRLreg(v *Value) bool { return true } // match: (CMPshiftRLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (CMPshiftRL x y [c]) for { x := v_0 @@ -4259,6 +4340,9 @@ func rewriteValueARM_OpARMCMPshiftRLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMCMPshiftRL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -8106,6 +8190,7 @@ func rewriteValueARM_OpARMMVNshiftLLreg(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] // match: (MVNshiftLLreg x (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (MVNshiftLL x [c]) for { x := v_0 @@ -8113,6 +8198,9 @@ func rewriteValueARM_OpARMMVNshiftLLreg(v *Value) bool { break } c := auxIntToInt32(v_1.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMMVNshiftLL) v.AuxInt = int32ToAuxInt(c) v.AddArg(x) @@ -8140,6 +8228,7 @@ func rewriteValueARM_OpARMMVNshiftRAreg(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] // match: (MVNshiftRAreg x (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (MVNshiftRA x [c]) for { x := v_0 @@ -8147,6 +8236,9 @@ func rewriteValueARM_OpARMMVNshiftRAreg(v *Value) bool { break } c := auxIntToInt32(v_1.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMMVNshiftRA) v.AuxInt = int32ToAuxInt(c) v.AddArg(x) @@ -8174,6 +8266,7 @@ func rewriteValueARM_OpARMMVNshiftRLreg(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] // match: (MVNshiftRLreg x (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (MVNshiftRL x [c]) for { x := v_0 @@ -8181,6 +8274,9 @@ func rewriteValueARM_OpARMMVNshiftRLreg(v *Value) bool { break } c := auxIntToInt32(v_1.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMMVNshiftRL) v.AuxInt = int32ToAuxInt(c) v.AddArg(x) @@ -8602,6 +8698,7 @@ func rewriteValueARM_OpARMORshiftLLreg(v *Value) bool { return true } // match: (ORshiftLLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (ORshiftLL x y [c]) for { x := v_0 @@ -8610,6 +8707,9 @@ func rewriteValueARM_OpARMORshiftLLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMORshiftLL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -8693,6 +8793,7 @@ func rewriteValueARM_OpARMORshiftRAreg(v *Value) bool { return true } // match: (ORshiftRAreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (ORshiftRA x y [c]) for { x := v_0 @@ -8701,6 +8802,9 @@ func rewriteValueARM_OpARMORshiftRAreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMORshiftRA) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -8800,6 +8904,7 @@ func rewriteValueARM_OpARMORshiftRLreg(v *Value) bool { return true } // match: (ORshiftRLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (ORshiftRL x y [c]) for { x := v_0 @@ -8808,6 +8913,9 @@ func rewriteValueARM_OpARMORshiftRLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMORshiftRL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -9095,6 +9203,7 @@ func rewriteValueARM_OpARMRSBSshiftLLreg(v *Value) bool { return true } // match: (RSBSshiftLLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (RSBSshiftLL x y [c]) for { x := v_0 @@ -9103,6 +9212,9 @@ func rewriteValueARM_OpARMRSBSshiftLLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMRSBSshiftLL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -9169,6 +9281,7 @@ func rewriteValueARM_OpARMRSBSshiftRAreg(v *Value) bool { return true } // match: (RSBSshiftRAreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (RSBSshiftRA x y [c]) for { x := v_0 @@ -9177,6 +9290,9 @@ func rewriteValueARM_OpARMRSBSshiftRAreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMRSBSshiftRA) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -9243,6 +9359,7 @@ func rewriteValueARM_OpARMRSBSshiftRLreg(v *Value) bool { return true } // match: (RSBSshiftRLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (RSBSshiftRL x y [c]) for { x := v_0 @@ -9251,6 +9368,9 @@ func rewriteValueARM_OpARMRSBSshiftRLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMRSBSshiftRL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -9392,6 +9512,7 @@ func rewriteValueARM_OpARMRSBshiftLLreg(v *Value) bool { return true } // match: (RSBshiftLLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (RSBshiftLL x y [c]) for { x := v_0 @@ -9400,6 +9521,9 @@ func rewriteValueARM_OpARMRSBshiftLLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMRSBshiftLL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -9483,6 +9607,7 @@ func rewriteValueARM_OpARMRSBshiftRAreg(v *Value) bool { return true } // match: (RSBshiftRAreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (RSBshiftRA x y [c]) for { x := v_0 @@ -9491,6 +9616,9 @@ func rewriteValueARM_OpARMRSBshiftRAreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMRSBshiftRA) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -9574,6 +9702,7 @@ func rewriteValueARM_OpARMRSBshiftRLreg(v *Value) bool { return true } // match: (RSBshiftRLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (RSBshiftRL x y [c]) for { x := v_0 @@ -9582,6 +9711,9 @@ func rewriteValueARM_OpARMRSBshiftRLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMRSBshiftRL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -9688,6 +9820,7 @@ func rewriteValueARM_OpARMRSCshiftLLreg(v *Value) bool { return true } // match: (RSCshiftLLreg x y (MOVWconst [c]) flags) + // cond: 0 <= c && c < 32 // result: (RSCshiftLL x y [c] flags) for { x := v_0 @@ -9697,6 +9830,9 @@ func rewriteValueARM_OpARMRSCshiftLLreg(v *Value) bool { } c := auxIntToInt32(v_2.AuxInt) flags := v_3 + if !(0 <= c && c < 32) { + break + } v.reset(OpARMRSCshiftLL) v.AuxInt = int32ToAuxInt(c) v.AddArg3(x, y, flags) @@ -9768,6 +9904,7 @@ func rewriteValueARM_OpARMRSCshiftRAreg(v *Value) bool { return true } // match: (RSCshiftRAreg x y (MOVWconst [c]) flags) + // cond: 0 <= c && c < 32 // result: (RSCshiftRA x y [c] flags) for { x := v_0 @@ -9777,6 +9914,9 @@ func rewriteValueARM_OpARMRSCshiftRAreg(v *Value) bool { } c := auxIntToInt32(v_2.AuxInt) flags := v_3 + if !(0 <= c && c < 32) { + break + } v.reset(OpARMRSCshiftRA) v.AuxInt = int32ToAuxInt(c) v.AddArg3(x, y, flags) @@ -9848,6 +9988,7 @@ func rewriteValueARM_OpARMRSCshiftRLreg(v *Value) bool { return true } // match: (RSCshiftRLreg x y (MOVWconst [c]) flags) + // cond: 0 <= c && c < 32 // result: (RSCshiftRL x y [c] flags) for { x := v_0 @@ -9857,6 +9998,9 @@ func rewriteValueARM_OpARMRSCshiftRLreg(v *Value) bool { } c := auxIntToInt32(v_2.AuxInt) flags := v_3 + if !(0 <= c && c < 32) { + break + } v.reset(OpARMRSCshiftRL) v.AuxInt = int32ToAuxInt(c) v.AddArg3(x, y, flags) @@ -10171,6 +10315,7 @@ func rewriteValueARM_OpARMSBCshiftLLreg(v *Value) bool { return true } // match: (SBCshiftLLreg x y (MOVWconst [c]) flags) + // cond: 0 <= c && c < 32 // result: (SBCshiftLL x y [c] flags) for { x := v_0 @@ -10180,6 +10325,9 @@ func rewriteValueARM_OpARMSBCshiftLLreg(v *Value) bool { } c := auxIntToInt32(v_2.AuxInt) flags := v_3 + if !(0 <= c && c < 32) { + break + } v.reset(OpARMSBCshiftLL) v.AuxInt = int32ToAuxInt(c) v.AddArg3(x, y, flags) @@ -10251,6 +10399,7 @@ func rewriteValueARM_OpARMSBCshiftRAreg(v *Value) bool { return true } // match: (SBCshiftRAreg x y (MOVWconst [c]) flags) + // cond: 0 <= c && c < 32 // result: (SBCshiftRA x y [c] flags) for { x := v_0 @@ -10260,6 +10409,9 @@ func rewriteValueARM_OpARMSBCshiftRAreg(v *Value) bool { } c := auxIntToInt32(v_2.AuxInt) flags := v_3 + if !(0 <= c && c < 32) { + break + } v.reset(OpARMSBCshiftRA) v.AuxInt = int32ToAuxInt(c) v.AddArg3(x, y, flags) @@ -10331,6 +10483,7 @@ func rewriteValueARM_OpARMSBCshiftRLreg(v *Value) bool { return true } // match: (SBCshiftRLreg x y (MOVWconst [c]) flags) + // cond: 0 <= c && c < 32 // result: (SBCshiftRL x y [c] flags) for { x := v_0 @@ -10340,6 +10493,9 @@ func rewriteValueARM_OpARMSBCshiftRLreg(v *Value) bool { } c := auxIntToInt32(v_2.AuxInt) flags := v_3 + if !(0 <= c && c < 32) { + break + } v.reset(OpARMSBCshiftRL) v.AuxInt = int32ToAuxInt(c) v.AddArg3(x, y, flags) @@ -10351,15 +10507,19 @@ func rewriteValueARM_OpARMSLL(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] // match: (SLL x (MOVWconst [c])) - // result: (SLLconst x [c&31]) + // cond: 0 <= c && c < 32 + // result: (SLLconst x [c]) for { x := v_0 if v_1.Op != OpARMMOVWconst { break } c := auxIntToInt32(v_1.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMSLLconst) - v.AuxInt = int32ToAuxInt(c & 31) + v.AuxInt = int32ToAuxInt(c) v.AddArg(x) return true } @@ -10385,15 +10545,19 @@ func rewriteValueARM_OpARMSRA(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] // match: (SRA x (MOVWconst [c])) - // result: (SRAconst x [c&31]) + // cond: 0 <= c && c < 32 + // result: (SRAconst x [c]) for { x := v_0 if v_1.Op != OpARMMOVWconst { break } c := auxIntToInt32(v_1.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMSRAconst) - v.AuxInt = int32ToAuxInt(c & 31) + v.AuxInt = int32ToAuxInt(c) v.AddArg(x) return true } @@ -10477,15 +10641,19 @@ func rewriteValueARM_OpARMSRL(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] // match: (SRL x (MOVWconst [c])) - // result: (SRLconst x [c&31]) + // cond: 0 <= c && c < 32 + // result: (SRLconst x [c]) for { x := v_0 if v_1.Op != OpARMMOVWconst { break } c := auxIntToInt32(v_1.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMSRLconst) - v.AuxInt = int32ToAuxInt(c & 31) + v.AuxInt = int32ToAuxInt(c) v.AddArg(x) return true } @@ -11081,6 +11249,7 @@ func rewriteValueARM_OpARMSUBSshiftLLreg(v *Value) bool { return true } // match: (SUBSshiftLLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (SUBSshiftLL x y [c]) for { x := v_0 @@ -11089,6 +11258,9 @@ func rewriteValueARM_OpARMSUBSshiftLLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMSUBSshiftLL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -11155,6 +11327,7 @@ func rewriteValueARM_OpARMSUBSshiftRAreg(v *Value) bool { return true } // match: (SUBSshiftRAreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (SUBSshiftRA x y [c]) for { x := v_0 @@ -11163,6 +11336,9 @@ func rewriteValueARM_OpARMSUBSshiftRAreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMSUBSshiftRA) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -11229,6 +11405,7 @@ func rewriteValueARM_OpARMSUBSshiftRLreg(v *Value) bool { return true } // match: (SUBSshiftRLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (SUBSshiftRL x y [c]) for { x := v_0 @@ -11237,6 +11414,9 @@ func rewriteValueARM_OpARMSUBSshiftRLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMSUBSshiftRL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -11432,6 +11612,7 @@ func rewriteValueARM_OpARMSUBshiftLLreg(v *Value) bool { return true } // match: (SUBshiftLLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (SUBshiftLL x y [c]) for { x := v_0 @@ -11440,6 +11621,9 @@ func rewriteValueARM_OpARMSUBshiftLLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMSUBshiftLL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -11523,6 +11707,7 @@ func rewriteValueARM_OpARMSUBshiftRAreg(v *Value) bool { return true } // match: (SUBshiftRAreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (SUBshiftRA x y [c]) for { x := v_0 @@ -11531,6 +11716,9 @@ func rewriteValueARM_OpARMSUBshiftRAreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMSUBshiftRA) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -11614,6 +11802,7 @@ func rewriteValueARM_OpARMSUBshiftRLreg(v *Value) bool { return true } // match: (SUBshiftRLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (SUBshiftRL x y [c]) for { x := v_0 @@ -11622,6 +11811,9 @@ func rewriteValueARM_OpARMSUBshiftRLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMSUBshiftRL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -11824,6 +12016,7 @@ func rewriteValueARM_OpARMTEQshiftLLreg(v *Value) bool { return true } // match: (TEQshiftLLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (TEQshiftLL x y [c]) for { x := v_0 @@ -11832,6 +12025,9 @@ func rewriteValueARM_OpARMTEQshiftLLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMTEQshiftLL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -11898,6 +12094,7 @@ func rewriteValueARM_OpARMTEQshiftRAreg(v *Value) bool { return true } // match: (TEQshiftRAreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (TEQshiftRA x y [c]) for { x := v_0 @@ -11906,6 +12103,9 @@ func rewriteValueARM_OpARMTEQshiftRAreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMTEQshiftRA) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -11972,6 +12172,7 @@ func rewriteValueARM_OpARMTEQshiftRLreg(v *Value) bool { return true } // match: (TEQshiftRLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (TEQshiftRL x y [c]) for { x := v_0 @@ -11980,6 +12181,9 @@ func rewriteValueARM_OpARMTEQshiftRLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMTEQshiftRL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -12182,6 +12386,7 @@ func rewriteValueARM_OpARMTSTshiftLLreg(v *Value) bool { return true } // match: (TSTshiftLLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (TSTshiftLL x y [c]) for { x := v_0 @@ -12190,6 +12395,9 @@ func rewriteValueARM_OpARMTSTshiftLLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMTSTshiftLL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -12256,6 +12464,7 @@ func rewriteValueARM_OpARMTSTshiftRAreg(v *Value) bool { return true } // match: (TSTshiftRAreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (TSTshiftRA x y [c]) for { x := v_0 @@ -12264,6 +12473,9 @@ func rewriteValueARM_OpARMTSTshiftRAreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMTSTshiftRA) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -12330,6 +12542,7 @@ func rewriteValueARM_OpARMTSTshiftRLreg(v *Value) bool { return true } // match: (TSTshiftRLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (TSTshiftRL x y [c]) for { x := v_0 @@ -12338,6 +12551,9 @@ func rewriteValueARM_OpARMTSTshiftRLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMTSTshiftRL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -12659,6 +12875,7 @@ func rewriteValueARM_OpARMXORshiftLLreg(v *Value) bool { return true } // match: (XORshiftLLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (XORshiftLL x y [c]) for { x := v_0 @@ -12667,6 +12884,9 @@ func rewriteValueARM_OpARMXORshiftLLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMXORshiftLL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -12750,6 +12970,7 @@ func rewriteValueARM_OpARMXORshiftRAreg(v *Value) bool { return true } // match: (XORshiftRAreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (XORshiftRA x y [c]) for { x := v_0 @@ -12758,6 +12979,9 @@ func rewriteValueARM_OpARMXORshiftRAreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMXORshiftRA) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) @@ -12857,6 +13081,7 @@ func rewriteValueARM_OpARMXORshiftRLreg(v *Value) bool { return true } // match: (XORshiftRLreg x y (MOVWconst [c])) + // cond: 0 <= c && c < 32 // result: (XORshiftRL x y [c]) for { x := v_0 @@ -12865,6 +13090,9 @@ func rewriteValueARM_OpARMXORshiftRLreg(v *Value) bool { break } c := auxIntToInt32(v_2.AuxInt) + if !(0 <= c && c < 32) { + break + } v.reset(OpARMXORshiftRL) v.AuxInt = int32ToAuxInt(c) v.AddArg2(x, y) diff --git a/test/fixedbugs/issue48476.go b/test/fixedbugs/issue48476.go new file mode 100644 index 0000000000..6b77f7c3c6 --- /dev/null +++ b/test/fixedbugs/issue48476.go @@ -0,0 +1,21 @@ +// run + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "fmt" + +//go:noinline +func f(x uint64) uint64 { + s := "\x04" + c := s[0] + return x << c << 4 +} +func main() { + if want, got := uint64(1<<8), f(1); want != got { + panic(fmt.Sprintf("want %x got %x", want, got)) + } +} -- GitLab From 79159f2e83662dac4089e2f5231ec23de9da10b9 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Sun, 19 Sep 2021 14:20:56 -0700 Subject: [PATCH 1207/2500] cmd/compile: fix simplification rules on arm/arm64 Fixes #48473 Change-Id: Ic1e918f916eae223a3b530a51a58f03031924670 Reviewed-on: https://go-review.googlesource.com/c/go/+/350913 Trust: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/compile/internal/ssa/gen/ARM.rules | 36 +- src/cmd/compile/internal/ssa/gen/ARM64.rules | 54 +-- src/cmd/compile/internal/ssa/rewriteARM.go | 228 ++++++------- src/cmd/compile/internal/ssa/rewriteARM64.go | 340 ++++++++----------- test/fixedbugs/issue48473.go | 30 ++ 5 files changed, 314 insertions(+), 374 deletions(-) create mode 100644 test/fixedbugs/issue48473.go diff --git a/src/cmd/compile/internal/ssa/gen/ARM.rules b/src/cmd/compile/internal/ssa/gen/ARM.rules index a6686237be..2bc58a3c47 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM.rules @@ -1239,24 +1239,24 @@ (AND x (MVN y)) => (BIC x y) // simplification with *shift ops -(SUBshiftLL x (SLLconst x [c]) [d]) && c==d => (MOVWconst [0]) -(SUBshiftRL x (SRLconst x [c]) [d]) && c==d => (MOVWconst [0]) -(SUBshiftRA x (SRAconst x [c]) [d]) && c==d => (MOVWconst [0]) -(RSBshiftLL x (SLLconst x [c]) [d]) && c==d => (MOVWconst [0]) -(RSBshiftRL x (SRLconst x [c]) [d]) && c==d => (MOVWconst [0]) -(RSBshiftRA x (SRAconst x [c]) [d]) && c==d => (MOVWconst [0]) -(ANDshiftLL x y:(SLLconst x [c]) [d]) && c==d => y -(ANDshiftRL x y:(SRLconst x [c]) [d]) && c==d => y -(ANDshiftRA x y:(SRAconst x [c]) [d]) && c==d => y -(ORshiftLL x y:(SLLconst x [c]) [d]) && c==d => y -(ORshiftRL x y:(SRLconst x [c]) [d]) && c==d => y -(ORshiftRA x y:(SRAconst x [c]) [d]) && c==d => y -(XORshiftLL x (SLLconst x [c]) [d]) && c==d => (MOVWconst [0]) -(XORshiftRL x (SRLconst x [c]) [d]) && c==d => (MOVWconst [0]) -(XORshiftRA x (SRAconst x [c]) [d]) && c==d => (MOVWconst [0]) -(BICshiftLL x (SLLconst x [c]) [d]) && c==d => (MOVWconst [0]) -(BICshiftRL x (SRLconst x [c]) [d]) && c==d => (MOVWconst [0]) -(BICshiftRA x (SRAconst x [c]) [d]) && c==d => (MOVWconst [0]) +(SUBshiftLL (SLLconst x [c]) x [c]) => (MOVWconst [0]) +(SUBshiftRL (SRLconst x [c]) x [c]) => (MOVWconst [0]) +(SUBshiftRA (SRAconst x [c]) x [c]) => (MOVWconst [0]) +(RSBshiftLL (SLLconst x [c]) x [c]) => (MOVWconst [0]) +(RSBshiftRL (SRLconst x [c]) x [c]) => (MOVWconst [0]) +(RSBshiftRA (SRAconst x [c]) x [c]) => (MOVWconst [0]) +(ANDshiftLL y:(SLLconst x [c]) x [c]) => y +(ANDshiftRL y:(SRLconst x [c]) x [c]) => y +(ANDshiftRA y:(SRAconst x [c]) x [c]) => y +(ORshiftLL y:(SLLconst x [c]) x [c]) => y +(ORshiftRL y:(SRLconst x [c]) x [c]) => y +(ORshiftRA y:(SRAconst x [c]) x [c]) => y +(XORshiftLL (SLLconst x [c]) x [c]) => (MOVWconst [0]) +(XORshiftRL (SRLconst x [c]) x [c]) => (MOVWconst [0]) +(XORshiftRA (SRAconst x [c]) x [c]) => (MOVWconst [0]) +(BICshiftLL (SLLconst x [c]) x [c]) => (MOVWconst [0]) +(BICshiftRL (SRLconst x [c]) x [c]) => (MOVWconst [0]) +(BICshiftRA (SRAconst x [c]) x [c]) => (MOVWconst [0]) (AND x (MVNshiftLL y [c])) => (BICshiftLL x y [c]) (AND x (MVNshiftRL y [c])) => (BICshiftRL x y [c]) (AND x (MVNshiftRA y [c])) => (BICshiftRA x y [c]) diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index b722d1cf1c..4b66883f26 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -1723,33 +1723,33 @@ (TSTshiftRO x (MOVDconst [c]) [d]) => (TSTconst x [rotateRight64(c, d)]) // simplification with *shift ops -(SUBshiftLL x (SLLconst x [c]) [d]) && c==d => (MOVDconst [0]) -(SUBshiftRL x (SRLconst x [c]) [d]) && c==d => (MOVDconst [0]) -(SUBshiftRA x (SRAconst x [c]) [d]) && c==d => (MOVDconst [0]) -(ANDshiftLL x y:(SLLconst x [c]) [d]) && c==d => y -(ANDshiftRL x y:(SRLconst x [c]) [d]) && c==d => y -(ANDshiftRA x y:(SRAconst x [c]) [d]) && c==d => y -(ANDshiftRO x y:(RORconst x [c]) [d]) && c==d => y -(ORshiftLL x y:(SLLconst x [c]) [d]) && c==d => y -(ORshiftRL x y:(SRLconst x [c]) [d]) && c==d => y -(ORshiftRA x y:(SRAconst x [c]) [d]) && c==d => y -(ORshiftRO x y:(RORconst x [c]) [d]) && c==d => y -(XORshiftLL x (SLLconst x [c]) [d]) && c==d => (MOVDconst [0]) -(XORshiftRL x (SRLconst x [c]) [d]) && c==d => (MOVDconst [0]) -(XORshiftRA x (SRAconst x [c]) [d]) && c==d => (MOVDconst [0]) -(XORshiftRO x (RORconst x [c]) [d]) && c==d => (MOVDconst [0]) -(BICshiftLL x (SLLconst x [c]) [d]) && c==d => (MOVDconst [0]) -(BICshiftRL x (SRLconst x [c]) [d]) && c==d => (MOVDconst [0]) -(BICshiftRA x (SRAconst x [c]) [d]) && c==d => (MOVDconst [0]) -(BICshiftRO x (RORconst x [c]) [d]) && c==d => (MOVDconst [0]) -(EONshiftLL x (SLLconst x [c]) [d]) && c==d => (MOVDconst [-1]) -(EONshiftRL x (SRLconst x [c]) [d]) && c==d => (MOVDconst [-1]) -(EONshiftRA x (SRAconst x [c]) [d]) && c==d => (MOVDconst [-1]) -(EONshiftRO x (RORconst x [c]) [d]) && c==d => (MOVDconst [-1]) -(ORNshiftLL x (SLLconst x [c]) [d]) && c==d => (MOVDconst [-1]) -(ORNshiftRL x (SRLconst x [c]) [d]) && c==d => (MOVDconst [-1]) -(ORNshiftRA x (SRAconst x [c]) [d]) && c==d => (MOVDconst [-1]) -(ORNshiftRO x (RORconst x [c]) [d]) && c==d => (MOVDconst [-1]) +(SUBshiftLL (SLLconst x [c]) x [c]) => (MOVDconst [0]) +(SUBshiftRL (SRLconst x [c]) x [c]) => (MOVDconst [0]) +(SUBshiftRA (SRAconst x [c]) x [c]) => (MOVDconst [0]) +(ANDshiftLL y:(SLLconst x [c]) x [c]) => y +(ANDshiftRL y:(SRLconst x [c]) x [c]) => y +(ANDshiftRA y:(SRAconst x [c]) x [c]) => y +(ANDshiftRO y:(RORconst x [c]) x [c]) => y +(ORshiftLL y:(SLLconst x [c]) x [c]) => y +(ORshiftRL y:(SRLconst x [c]) x [c]) => y +(ORshiftRA y:(SRAconst x [c]) x [c]) => y +(ORshiftRO y:(RORconst x [c]) x [c]) => y +(XORshiftLL (SLLconst x [c]) x [c]) => (MOVDconst [0]) +(XORshiftRL (SRLconst x [c]) x [c]) => (MOVDconst [0]) +(XORshiftRA (SRAconst x [c]) x [c]) => (MOVDconst [0]) +(XORshiftRO (RORconst x [c]) x [c]) => (MOVDconst [0]) +(BICshiftLL (SLLconst x [c]) x [c]) => (MOVDconst [0]) +(BICshiftRL (SRLconst x [c]) x [c]) => (MOVDconst [0]) +(BICshiftRA (SRAconst x [c]) x [c]) => (MOVDconst [0]) +(BICshiftRO (RORconst x [c]) x [c]) => (MOVDconst [0]) +(EONshiftLL (SLLconst x [c]) x [c]) => (MOVDconst [-1]) +(EONshiftRL (SRLconst x [c]) x [c]) => (MOVDconst [-1]) +(EONshiftRA (SRAconst x [c]) x [c]) => (MOVDconst [-1]) +(EONshiftRO (RORconst x [c]) x [c]) => (MOVDconst [-1]) +(ORNshiftLL (SLLconst x [c]) x [c]) => (MOVDconst [-1]) +(ORNshiftRL (SRLconst x [c]) x [c]) => (MOVDconst [-1]) +(ORNshiftRA (SRAconst x [c]) x [c]) => (MOVDconst [-1]) +(ORNshiftRO (RORconst x [c]) x [c]) => (MOVDconst [-1]) // Generate rotates with const shift (ADDshiftLL [c] (SRLconst x [64-c]) x) => (RORconst [64-c] x) diff --git a/src/cmd/compile/internal/ssa/rewriteARM.go b/src/cmd/compile/internal/ssa/rewriteARM.go index 2c536e1a52..496f9b4ae2 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM.go +++ b/src/cmd/compile/internal/ssa/rewriteARM.go @@ -2655,18 +2655,16 @@ func rewriteValueARM_OpARMANDshiftLL(v *Value) bool { v.AddArg(x) return true } - // match: (ANDshiftLL x y:(SLLconst x [c]) [d]) - // cond: c==d + // match: (ANDshiftLL y:(SLLconst x [c]) x [c]) // result: y for { - d := auxIntToInt32(v.AuxInt) - x := v_0 - y := v_1 - if y.Op != OpARMSLLconst { + c := auxIntToInt32(v.AuxInt) + y := v_0 + if y.Op != OpARMSLLconst || auxIntToInt32(y.AuxInt) != c { break } - c := auxIntToInt32(y.AuxInt) - if x != y.Args[0] || !(c == d) { + x := y.Args[0] + if x != v_1 { break } v.copyOf(y) @@ -2750,18 +2748,16 @@ func rewriteValueARM_OpARMANDshiftRA(v *Value) bool { v.AddArg(x) return true } - // match: (ANDshiftRA x y:(SRAconst x [c]) [d]) - // cond: c==d + // match: (ANDshiftRA y:(SRAconst x [c]) x [c]) // result: y for { - d := auxIntToInt32(v.AuxInt) - x := v_0 - y := v_1 - if y.Op != OpARMSRAconst { + c := auxIntToInt32(v.AuxInt) + y := v_0 + if y.Op != OpARMSRAconst || auxIntToInt32(y.AuxInt) != c { break } - c := auxIntToInt32(y.AuxInt) - if x != y.Args[0] || !(c == d) { + x := y.Args[0] + if x != v_1 { break } v.copyOf(y) @@ -2845,18 +2841,16 @@ func rewriteValueARM_OpARMANDshiftRL(v *Value) bool { v.AddArg(x) return true } - // match: (ANDshiftRL x y:(SRLconst x [c]) [d]) - // cond: c==d + // match: (ANDshiftRL y:(SRLconst x [c]) x [c]) // result: y for { - d := auxIntToInt32(v.AuxInt) - x := v_0 - y := v_1 - if y.Op != OpARMSRLconst { + c := auxIntToInt32(v.AuxInt) + y := v_0 + if y.Op != OpARMSRLconst || auxIntToInt32(y.AuxInt) != c { break } - c := auxIntToInt32(y.AuxInt) - if x != y.Args[0] || !(c == d) { + x := y.Args[0] + if x != v_1 { break } v.copyOf(y) @@ -3144,17 +3138,15 @@ func rewriteValueARM_OpARMBICshiftLL(v *Value) bool { v.AddArg(x) return true } - // match: (BICshiftLL x (SLLconst x [c]) [d]) - // cond: c==d + // match: (BICshiftLL (SLLconst x [c]) x [c]) // result: (MOVWconst [0]) for { - d := auxIntToInt32(v.AuxInt) - x := v_0 - if v_1.Op != OpARMSLLconst { + c := auxIntToInt32(v.AuxInt) + if v_0.Op != OpARMSLLconst || auxIntToInt32(v_0.AuxInt) != c { break } - c := auxIntToInt32(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARMMOVWconst) @@ -3204,17 +3196,15 @@ func rewriteValueARM_OpARMBICshiftRA(v *Value) bool { v.AddArg(x) return true } - // match: (BICshiftRA x (SRAconst x [c]) [d]) - // cond: c==d + // match: (BICshiftRA (SRAconst x [c]) x [c]) // result: (MOVWconst [0]) for { - d := auxIntToInt32(v.AuxInt) - x := v_0 - if v_1.Op != OpARMSRAconst { + c := auxIntToInt32(v.AuxInt) + if v_0.Op != OpARMSRAconst || auxIntToInt32(v_0.AuxInt) != c { break } - c := auxIntToInt32(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARMMOVWconst) @@ -3264,17 +3254,15 @@ func rewriteValueARM_OpARMBICshiftRL(v *Value) bool { v.AddArg(x) return true } - // match: (BICshiftRL x (SRLconst x [c]) [d]) - // cond: c==d + // match: (BICshiftRL (SRLconst x [c]) x [c]) // result: (MOVWconst [0]) for { - d := auxIntToInt32(v.AuxInt) - x := v_0 - if v_1.Op != OpARMSRLconst { + c := auxIntToInt32(v.AuxInt) + if v_0.Op != OpARMSRLconst || auxIntToInt32(v_0.AuxInt) != c { break } - c := auxIntToInt32(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARMMOVWconst) @@ -8657,18 +8645,16 @@ func rewriteValueARM_OpARMORshiftLL(v *Value) bool { v.AddArg(x) return true } - // match: (ORshiftLL x y:(SLLconst x [c]) [d]) - // cond: c==d + // match: (ORshiftLL y:(SLLconst x [c]) x [c]) // result: y for { - d := auxIntToInt32(v.AuxInt) - x := v_0 - y := v_1 - if y.Op != OpARMSLLconst { + c := auxIntToInt32(v.AuxInt) + y := v_0 + if y.Op != OpARMSLLconst || auxIntToInt32(y.AuxInt) != c { break } - c := auxIntToInt32(y.AuxInt) - if x != y.Args[0] || !(c == d) { + x := y.Args[0] + if x != v_1 { break } v.copyOf(y) @@ -8752,18 +8738,16 @@ func rewriteValueARM_OpARMORshiftRA(v *Value) bool { v.AddArg(x) return true } - // match: (ORshiftRA x y:(SRAconst x [c]) [d]) - // cond: c==d + // match: (ORshiftRA y:(SRAconst x [c]) x [c]) // result: y for { - d := auxIntToInt32(v.AuxInt) - x := v_0 - y := v_1 - if y.Op != OpARMSRAconst { + c := auxIntToInt32(v.AuxInt) + y := v_0 + if y.Op != OpARMSRAconst || auxIntToInt32(y.AuxInt) != c { break } - c := auxIntToInt32(y.AuxInt) - if x != y.Args[0] || !(c == d) { + x := y.Args[0] + if x != v_1 { break } v.copyOf(y) @@ -8863,18 +8847,16 @@ func rewriteValueARM_OpARMORshiftRL(v *Value) bool { v.AddArg(x) return true } - // match: (ORshiftRL x y:(SRLconst x [c]) [d]) - // cond: c==d + // match: (ORshiftRL y:(SRLconst x [c]) x [c]) // result: y for { - d := auxIntToInt32(v.AuxInt) - x := v_0 - y := v_1 - if y.Op != OpARMSRLconst { + c := auxIntToInt32(v.AuxInt) + y := v_0 + if y.Op != OpARMSRLconst || auxIntToInt32(y.AuxInt) != c { break } - c := auxIntToInt32(y.AuxInt) - if x != y.Args[0] || !(c == d) { + x := y.Args[0] + if x != v_1 { break } v.copyOf(y) @@ -9471,17 +9453,15 @@ func rewriteValueARM_OpARMRSBshiftLL(v *Value) bool { v.AddArg(x) return true } - // match: (RSBshiftLL x (SLLconst x [c]) [d]) - // cond: c==d + // match: (RSBshiftLL (SLLconst x [c]) x [c]) // result: (MOVWconst [0]) for { - d := auxIntToInt32(v.AuxInt) - x := v_0 - if v_1.Op != OpARMSLLconst { + c := auxIntToInt32(v.AuxInt) + if v_0.Op != OpARMSLLconst || auxIntToInt32(v_0.AuxInt) != c { break } - c := auxIntToInt32(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARMMOVWconst) @@ -9566,17 +9546,15 @@ func rewriteValueARM_OpARMRSBshiftRA(v *Value) bool { v.AddArg(x) return true } - // match: (RSBshiftRA x (SRAconst x [c]) [d]) - // cond: c==d + // match: (RSBshiftRA (SRAconst x [c]) x [c]) // result: (MOVWconst [0]) for { - d := auxIntToInt32(v.AuxInt) - x := v_0 - if v_1.Op != OpARMSRAconst { + c := auxIntToInt32(v.AuxInt) + if v_0.Op != OpARMSRAconst || auxIntToInt32(v_0.AuxInt) != c { break } - c := auxIntToInt32(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARMMOVWconst) @@ -9661,17 +9639,15 @@ func rewriteValueARM_OpARMRSBshiftRL(v *Value) bool { v.AddArg(x) return true } - // match: (RSBshiftRL x (SRLconst x [c]) [d]) - // cond: c==d + // match: (RSBshiftRL (SRLconst x [c]) x [c]) // result: (MOVWconst [0]) for { - d := auxIntToInt32(v.AuxInt) - x := v_0 - if v_1.Op != OpARMSRLconst { + c := auxIntToInt32(v.AuxInt) + if v_0.Op != OpARMSRLconst || auxIntToInt32(v_0.AuxInt) != c { break } - c := auxIntToInt32(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARMMOVWconst) @@ -11571,17 +11547,15 @@ func rewriteValueARM_OpARMSUBshiftLL(v *Value) bool { v.AddArg(x) return true } - // match: (SUBshiftLL x (SLLconst x [c]) [d]) - // cond: c==d + // match: (SUBshiftLL (SLLconst x [c]) x [c]) // result: (MOVWconst [0]) for { - d := auxIntToInt32(v.AuxInt) - x := v_0 - if v_1.Op != OpARMSLLconst { + c := auxIntToInt32(v.AuxInt) + if v_0.Op != OpARMSLLconst || auxIntToInt32(v_0.AuxInt) != c { break } - c := auxIntToInt32(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARMMOVWconst) @@ -11666,17 +11640,15 @@ func rewriteValueARM_OpARMSUBshiftRA(v *Value) bool { v.AddArg(x) return true } - // match: (SUBshiftRA x (SRAconst x [c]) [d]) - // cond: c==d + // match: (SUBshiftRA (SRAconst x [c]) x [c]) // result: (MOVWconst [0]) for { - d := auxIntToInt32(v.AuxInt) - x := v_0 - if v_1.Op != OpARMSRAconst { + c := auxIntToInt32(v.AuxInt) + if v_0.Op != OpARMSRAconst || auxIntToInt32(v_0.AuxInt) != c { break } - c := auxIntToInt32(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARMMOVWconst) @@ -11761,17 +11733,15 @@ func rewriteValueARM_OpARMSUBshiftRL(v *Value) bool { v.AddArg(x) return true } - // match: (SUBshiftRL x (SRLconst x [c]) [d]) - // cond: c==d + // match: (SUBshiftRL (SRLconst x [c]) x [c]) // result: (MOVWconst [0]) for { - d := auxIntToInt32(v.AuxInt) - x := v_0 - if v_1.Op != OpARMSRLconst { + c := auxIntToInt32(v.AuxInt) + if v_0.Op != OpARMSRLconst || auxIntToInt32(v_0.AuxInt) != c { break } - c := auxIntToInt32(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARMMOVWconst) @@ -12834,17 +12804,15 @@ func rewriteValueARM_OpARMXORshiftLL(v *Value) bool { v.AddArg(x) return true } - // match: (XORshiftLL x (SLLconst x [c]) [d]) - // cond: c==d + // match: (XORshiftLL (SLLconst x [c]) x [c]) // result: (MOVWconst [0]) for { - d := auxIntToInt32(v.AuxInt) - x := v_0 - if v_1.Op != OpARMSLLconst { + c := auxIntToInt32(v.AuxInt) + if v_0.Op != OpARMSLLconst || auxIntToInt32(v_0.AuxInt) != c { break } - c := auxIntToInt32(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARMMOVWconst) @@ -12929,17 +12897,15 @@ func rewriteValueARM_OpARMXORshiftRA(v *Value) bool { v.AddArg(x) return true } - // match: (XORshiftRA x (SRAconst x [c]) [d]) - // cond: c==d + // match: (XORshiftRA (SRAconst x [c]) x [c]) // result: (MOVWconst [0]) for { - d := auxIntToInt32(v.AuxInt) - x := v_0 - if v_1.Op != OpARMSRAconst { + c := auxIntToInt32(v.AuxInt) + if v_0.Op != OpARMSRAconst || auxIntToInt32(v_0.AuxInt) != c { break } - c := auxIntToInt32(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARMMOVWconst) @@ -13040,17 +13006,15 @@ func rewriteValueARM_OpARMXORshiftRL(v *Value) bool { v.AddArg(x) return true } - // match: (XORshiftRL x (SRLconst x [c]) [d]) - // cond: c==d + // match: (XORshiftRL (SRLconst x [c]) x [c]) // result: (MOVWconst [0]) for { - d := auxIntToInt32(v.AuxInt) - x := v_0 - if v_1.Op != OpARMSRLconst { + c := auxIntToInt32(v.AuxInt) + if v_0.Op != OpARMSRLconst || auxIntToInt32(v_0.AuxInt) != c { break } - c := auxIntToInt32(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARMMOVWconst) diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index 06cc5a62b2..614e71f852 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -2314,18 +2314,16 @@ func rewriteValueARM64_OpARM64ANDshiftLL(v *Value) bool { v.AddArg(x) return true } - // match: (ANDshiftLL x y:(SLLconst x [c]) [d]) - // cond: c==d + // match: (ANDshiftLL y:(SLLconst x [c]) x [c]) // result: y for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - y := v_1 - if y.Op != OpARM64SLLconst { + c := auxIntToInt64(v.AuxInt) + y := v_0 + if y.Op != OpARM64SLLconst || auxIntToInt64(y.AuxInt) != c { break } - c := auxIntToInt64(y.AuxInt) - if x != y.Args[0] || !(c == d) { + x := y.Args[0] + if x != v_1 { break } v.copyOf(y) @@ -2368,18 +2366,16 @@ func rewriteValueARM64_OpARM64ANDshiftRA(v *Value) bool { v.AddArg(x) return true } - // match: (ANDshiftRA x y:(SRAconst x [c]) [d]) - // cond: c==d + // match: (ANDshiftRA y:(SRAconst x [c]) x [c]) // result: y for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - y := v_1 - if y.Op != OpARM64SRAconst { + c := auxIntToInt64(v.AuxInt) + y := v_0 + if y.Op != OpARM64SRAconst || auxIntToInt64(y.AuxInt) != c { break } - c := auxIntToInt64(y.AuxInt) - if x != y.Args[0] || !(c == d) { + x := y.Args[0] + if x != v_1 { break } v.copyOf(y) @@ -2422,18 +2418,16 @@ func rewriteValueARM64_OpARM64ANDshiftRL(v *Value) bool { v.AddArg(x) return true } - // match: (ANDshiftRL x y:(SRLconst x [c]) [d]) - // cond: c==d + // match: (ANDshiftRL y:(SRLconst x [c]) x [c]) // result: y for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - y := v_1 - if y.Op != OpARM64SRLconst { + c := auxIntToInt64(v.AuxInt) + y := v_0 + if y.Op != OpARM64SRLconst || auxIntToInt64(y.AuxInt) != c { break } - c := auxIntToInt64(y.AuxInt) - if x != y.Args[0] || !(c == d) { + x := y.Args[0] + if x != v_1 { break } v.copyOf(y) @@ -2476,18 +2470,16 @@ func rewriteValueARM64_OpARM64ANDshiftRO(v *Value) bool { v.AddArg(x) return true } - // match: (ANDshiftRO x y:(RORconst x [c]) [d]) - // cond: c==d + // match: (ANDshiftRO y:(RORconst x [c]) x [c]) // result: y for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - y := v_1 - if y.Op != OpARM64RORconst { + c := auxIntToInt64(v.AuxInt) + y := v_0 + if y.Op != OpARM64RORconst || auxIntToInt64(y.AuxInt) != c { break } - c := auxIntToInt64(y.AuxInt) - if x != y.Args[0] || !(c == d) { + x := y.Args[0] + if x != v_1 { break } v.copyOf(y) @@ -2617,17 +2609,15 @@ func rewriteValueARM64_OpARM64BICshiftLL(v *Value) bool { v.AddArg(x) return true } - // match: (BICshiftLL x (SLLconst x [c]) [d]) - // cond: c==d + // match: (BICshiftLL (SLLconst x [c]) x [c]) // result: (MOVDconst [0]) for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - if v_1.Op != OpARM64SLLconst { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != c { break } - c := auxIntToInt64(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARM64MOVDconst) @@ -2653,17 +2643,15 @@ func rewriteValueARM64_OpARM64BICshiftRA(v *Value) bool { v.AddArg(x) return true } - // match: (BICshiftRA x (SRAconst x [c]) [d]) - // cond: c==d + // match: (BICshiftRA (SRAconst x [c]) x [c]) // result: (MOVDconst [0]) for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - if v_1.Op != OpARM64SRAconst { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64SRAconst || auxIntToInt64(v_0.AuxInt) != c { break } - c := auxIntToInt64(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARM64MOVDconst) @@ -2689,17 +2677,15 @@ func rewriteValueARM64_OpARM64BICshiftRL(v *Value) bool { v.AddArg(x) return true } - // match: (BICshiftRL x (SRLconst x [c]) [d]) - // cond: c==d + // match: (BICshiftRL (SRLconst x [c]) x [c]) // result: (MOVDconst [0]) for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - if v_1.Op != OpARM64SRLconst { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64SRLconst || auxIntToInt64(v_0.AuxInt) != c { break } - c := auxIntToInt64(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARM64MOVDconst) @@ -2725,17 +2711,15 @@ func rewriteValueARM64_OpARM64BICshiftRO(v *Value) bool { v.AddArg(x) return true } - // match: (BICshiftRO x (RORconst x [c]) [d]) - // cond: c==d + // match: (BICshiftRO (RORconst x [c]) x [c]) // result: (MOVDconst [0]) for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - if v_1.Op != OpARM64RORconst { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64RORconst || auxIntToInt64(v_0.AuxInt) != c { break } - c := auxIntToInt64(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARM64MOVDconst) @@ -4122,17 +4106,15 @@ func rewriteValueARM64_OpARM64EONshiftLL(v *Value) bool { v.AddArg(x) return true } - // match: (EONshiftLL x (SLLconst x [c]) [d]) - // cond: c==d + // match: (EONshiftLL (SLLconst x [c]) x [c]) // result: (MOVDconst [-1]) for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - if v_1.Op != OpARM64SLLconst { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != c { break } - c := auxIntToInt64(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARM64MOVDconst) @@ -4158,17 +4140,15 @@ func rewriteValueARM64_OpARM64EONshiftRA(v *Value) bool { v.AddArg(x) return true } - // match: (EONshiftRA x (SRAconst x [c]) [d]) - // cond: c==d + // match: (EONshiftRA (SRAconst x [c]) x [c]) // result: (MOVDconst [-1]) for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - if v_1.Op != OpARM64SRAconst { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64SRAconst || auxIntToInt64(v_0.AuxInt) != c { break } - c := auxIntToInt64(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARM64MOVDconst) @@ -4194,17 +4174,15 @@ func rewriteValueARM64_OpARM64EONshiftRL(v *Value) bool { v.AddArg(x) return true } - // match: (EONshiftRL x (SRLconst x [c]) [d]) - // cond: c==d + // match: (EONshiftRL (SRLconst x [c]) x [c]) // result: (MOVDconst [-1]) for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - if v_1.Op != OpARM64SRLconst { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64SRLconst || auxIntToInt64(v_0.AuxInt) != c { break } - c := auxIntToInt64(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARM64MOVDconst) @@ -4230,17 +4208,15 @@ func rewriteValueARM64_OpARM64EONshiftRO(v *Value) bool { v.AddArg(x) return true } - // match: (EONshiftRO x (RORconst x [c]) [d]) - // cond: c==d + // match: (EONshiftRO (RORconst x [c]) x [c]) // result: (MOVDconst [-1]) for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - if v_1.Op != OpARM64RORconst { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64RORconst || auxIntToInt64(v_0.AuxInt) != c { break } - c := auxIntToInt64(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARM64MOVDconst) @@ -18219,17 +18195,15 @@ func rewriteValueARM64_OpARM64ORNshiftLL(v *Value) bool { v.AddArg(x) return true } - // match: (ORNshiftLL x (SLLconst x [c]) [d]) - // cond: c==d + // match: (ORNshiftLL (SLLconst x [c]) x [c]) // result: (MOVDconst [-1]) for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - if v_1.Op != OpARM64SLLconst { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != c { break } - c := auxIntToInt64(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARM64MOVDconst) @@ -18255,17 +18229,15 @@ func rewriteValueARM64_OpARM64ORNshiftRA(v *Value) bool { v.AddArg(x) return true } - // match: (ORNshiftRA x (SRAconst x [c]) [d]) - // cond: c==d + // match: (ORNshiftRA (SRAconst x [c]) x [c]) // result: (MOVDconst [-1]) for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - if v_1.Op != OpARM64SRAconst { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64SRAconst || auxIntToInt64(v_0.AuxInt) != c { break } - c := auxIntToInt64(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARM64MOVDconst) @@ -18291,17 +18263,15 @@ func rewriteValueARM64_OpARM64ORNshiftRL(v *Value) bool { v.AddArg(x) return true } - // match: (ORNshiftRL x (SRLconst x [c]) [d]) - // cond: c==d + // match: (ORNshiftRL (SRLconst x [c]) x [c]) // result: (MOVDconst [-1]) for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - if v_1.Op != OpARM64SRLconst { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64SRLconst || auxIntToInt64(v_0.AuxInt) != c { break } - c := auxIntToInt64(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARM64MOVDconst) @@ -18327,17 +18297,15 @@ func rewriteValueARM64_OpARM64ORNshiftRO(v *Value) bool { v.AddArg(x) return true } - // match: (ORNshiftRO x (RORconst x [c]) [d]) - // cond: c==d + // match: (ORNshiftRO (RORconst x [c]) x [c]) // result: (MOVDconst [-1]) for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - if v_1.Op != OpARM64RORconst { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64RORconst || auxIntToInt64(v_0.AuxInt) != c { break } - c := auxIntToInt64(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARM64MOVDconst) @@ -18450,18 +18418,16 @@ func rewriteValueARM64_OpARM64ORshiftLL(v *Value) bool { v.AddArg(x) return true } - // match: (ORshiftLL x y:(SLLconst x [c]) [d]) - // cond: c==d + // match: (ORshiftLL y:(SLLconst x [c]) x [c]) // result: y for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - y := v_1 - if y.Op != OpARM64SLLconst { + c := auxIntToInt64(v.AuxInt) + y := v_0 + if y.Op != OpARM64SLLconst || auxIntToInt64(y.AuxInt) != c { break } - c := auxIntToInt64(y.AuxInt) - if x != y.Args[0] || !(c == d) { + x := y.Args[0] + if x != v_1 { break } v.copyOf(y) @@ -20130,18 +20096,16 @@ func rewriteValueARM64_OpARM64ORshiftRA(v *Value) bool { v.AddArg(x) return true } - // match: (ORshiftRA x y:(SRAconst x [c]) [d]) - // cond: c==d + // match: (ORshiftRA y:(SRAconst x [c]) x [c]) // result: y for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - y := v_1 - if y.Op != OpARM64SRAconst { + c := auxIntToInt64(v.AuxInt) + y := v_0 + if y.Op != OpARM64SRAconst || auxIntToInt64(y.AuxInt) != c { break } - c := auxIntToInt64(y.AuxInt) - if x != y.Args[0] || !(c == d) { + x := y.Args[0] + if x != v_1 { break } v.copyOf(y) @@ -20184,18 +20148,16 @@ func rewriteValueARM64_OpARM64ORshiftRL(v *Value) bool { v.AddArg(x) return true } - // match: (ORshiftRL x y:(SRLconst x [c]) [d]) - // cond: c==d + // match: (ORshiftRL y:(SRLconst x [c]) x [c]) // result: y for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - y := v_1 - if y.Op != OpARM64SRLconst { + c := auxIntToInt64(v.AuxInt) + y := v_0 + if y.Op != OpARM64SRLconst || auxIntToInt64(y.AuxInt) != c { break } - c := auxIntToInt64(y.AuxInt) - if x != y.Args[0] || !(c == d) { + x := y.Args[0] + if x != v_1 { break } v.copyOf(y) @@ -20318,18 +20280,16 @@ func rewriteValueARM64_OpARM64ORshiftRO(v *Value) bool { v.AddArg(x) return true } - // match: (ORshiftRO x y:(RORconst x [c]) [d]) - // cond: c==d + // match: (ORshiftRO y:(RORconst x [c]) x [c]) // result: y for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - y := v_1 - if y.Op != OpARM64RORconst { + c := auxIntToInt64(v.AuxInt) + y := v_0 + if y.Op != OpARM64RORconst || auxIntToInt64(y.AuxInt) != c { break } - c := auxIntToInt64(y.AuxInt) - if x != y.Args[0] || !(c == d) { + x := y.Args[0] + if x != v_1 { break } v.copyOf(y) @@ -21389,17 +21349,15 @@ func rewriteValueARM64_OpARM64SUBshiftLL(v *Value) bool { v.AddArg(x) return true } - // match: (SUBshiftLL x (SLLconst x [c]) [d]) - // cond: c==d + // match: (SUBshiftLL (SLLconst x [c]) x [c]) // result: (MOVDconst [0]) for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - if v_1.Op != OpARM64SLLconst { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != c { break } - c := auxIntToInt64(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARM64MOVDconst) @@ -21425,17 +21383,15 @@ func rewriteValueARM64_OpARM64SUBshiftRA(v *Value) bool { v.AddArg(x) return true } - // match: (SUBshiftRA x (SRAconst x [c]) [d]) - // cond: c==d + // match: (SUBshiftRA (SRAconst x [c]) x [c]) // result: (MOVDconst [0]) for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - if v_1.Op != OpARM64SRAconst { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64SRAconst || auxIntToInt64(v_0.AuxInt) != c { break } - c := auxIntToInt64(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARM64MOVDconst) @@ -21461,17 +21417,15 @@ func rewriteValueARM64_OpARM64SUBshiftRL(v *Value) bool { v.AddArg(x) return true } - // match: (SUBshiftRL x (SRLconst x [c]) [d]) - // cond: c==d + // match: (SUBshiftRL (SRLconst x [c]) x [c]) // result: (MOVDconst [0]) for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - if v_1.Op != OpARM64SRLconst { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64SRLconst || auxIntToInt64(v_0.AuxInt) != c { break } - c := auxIntToInt64(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARM64MOVDconst) @@ -22641,17 +22595,15 @@ func rewriteValueARM64_OpARM64XORshiftLL(v *Value) bool { v.AddArg(x) return true } - // match: (XORshiftLL x (SLLconst x [c]) [d]) - // cond: c==d + // match: (XORshiftLL (SLLconst x [c]) x [c]) // result: (MOVDconst [0]) for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - if v_1.Op != OpARM64SLLconst { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64SLLconst || auxIntToInt64(v_0.AuxInt) != c { break } - c := auxIntToInt64(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARM64MOVDconst) @@ -22853,17 +22805,15 @@ func rewriteValueARM64_OpARM64XORshiftRA(v *Value) bool { v.AddArg(x) return true } - // match: (XORshiftRA x (SRAconst x [c]) [d]) - // cond: c==d + // match: (XORshiftRA (SRAconst x [c]) x [c]) // result: (MOVDconst [0]) for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - if v_1.Op != OpARM64SRAconst { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64SRAconst || auxIntToInt64(v_0.AuxInt) != c { break } - c := auxIntToInt64(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARM64MOVDconst) @@ -22907,17 +22857,15 @@ func rewriteValueARM64_OpARM64XORshiftRL(v *Value) bool { v.AddArg(x) return true } - // match: (XORshiftRL x (SRLconst x [c]) [d]) - // cond: c==d + // match: (XORshiftRL (SRLconst x [c]) x [c]) // result: (MOVDconst [0]) for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - if v_1.Op != OpARM64SRLconst { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64SRLconst || auxIntToInt64(v_0.AuxInt) != c { break } - c := auxIntToInt64(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARM64MOVDconst) @@ -22995,17 +22943,15 @@ func rewriteValueARM64_OpARM64XORshiftRO(v *Value) bool { v.AddArg(x) return true } - // match: (XORshiftRO x (RORconst x [c]) [d]) - // cond: c==d + // match: (XORshiftRO (RORconst x [c]) x [c]) // result: (MOVDconst [0]) for { - d := auxIntToInt64(v.AuxInt) - x := v_0 - if v_1.Op != OpARM64RORconst { + c := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64RORconst || auxIntToInt64(v_0.AuxInt) != c { break } - c := auxIntToInt64(v_1.AuxInt) - if x != v_1.Args[0] || !(c == d) { + x := v_0.Args[0] + if x != v_1 { break } v.reset(OpARM64MOVDconst) diff --git a/test/fixedbugs/issue48473.go b/test/fixedbugs/issue48473.go new file mode 100644 index 0000000000..8edef1f14f --- /dev/null +++ b/test/fixedbugs/issue48473.go @@ -0,0 +1,30 @@ +// run + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "fmt" + +func f(x uint64) uint64 { + s := "\x04" + c := s[0] + return x - x< Date: Tue, 17 Aug 2021 07:24:31 -0500 Subject: [PATCH 1208/2500] cmd/compile: document register-based ABI for ppc64 This adds the ppc64 information to the ABI doc. Change-Id: I55ce77a59a8b50309d02e3e0de0cea3fc62ad003 Reviewed-on: https://go-review.googlesource.com/c/go/+/342869 Trust: Lynn Boger Reviewed-by: Cherry Mui --- src/cmd/compile/abi-internal.md | 99 +++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/src/cmd/compile/abi-internal.md b/src/cmd/compile/abi-internal.md index 3619aea4aa..50d8ed9159 100644 --- a/src/cmd/compile/abi-internal.md +++ b/src/cmd/compile/abi-internal.md @@ -627,6 +627,105 @@ modifying or saving the FPCR. Functions are allowed to modify it between calls (as long as they restore it), but as of this writing Go code never does. +### ppc64 architecture + +The ppc64 architecture uses R3 – R10 and R14 – R17 for integer arguments +and results. + +It uses F1 – F12 for floating-point arguments and results. + +Register R31 is a permanent scratch register in Go. + +Special-purpose registers used within Go generated code and Go +assembly code are as follows: + +| Register | Call meaning | Return meaning | Body meaning | +| --- | --- | --- | --- | +| R0 | Zero value | Same | Same | +| R1 | Stack pointer | Same | Same | +| R2 | TOC register | Same | Same | +| R11 | Closure context pointer | Scratch | Scratch | +| R12 | Function address on indirect calls | Scratch | Scratch | +| R13 | TLS pointer | Same | Same | +| R20,R21 | Scratch | Scratch | Used by duffcopy, duffzero | +| R30 | Current goroutine | Same | Same | +| R31 | Scratch | Scratch | Scratch | +| LR | Link register | Link register | Scratch | +*Rationale*: These register meanings are compatible with Go’s +stack-based calling convention. + +The link register, LR, holds the function return +address at the function entry and is set to the correct return +address before exiting the function. It is also used +in some cases as the function address when doing an indirect call. + +The register R2 contains the address of the TOC (table of contents) which +contains data or code addresses used when generating position independent +code. Non-Go code generated when using cgo contains TOC-relative addresses +which depend on R2 holding a valid TOC. Go code compiled with -shared or +-dynlink initializes and maintains R2 and uses it in some cases for +function calls; Go code compiled without these options does not modify R2. + +When making a function call R12 contains the function address for use by the +code to generate R2 at the beginning of the function. R12 can be used for +other purposes within the body of the function, such as trampoline generation. + +R20 and R21 are used in duffcopy and duffzero which could be generated +before arguments are saved so should not be used for register arguments. + +The Count register CTR can be used as the call target for some branch instructions. +It holds the return address when preemption has occurred. + +On PPC64 when a float32 is loaded it becomes a float64 in the register, which is +different from other platforms and that needs to be recognized by the internal +implementation of reflection so that float32 arguments are passed correctly. + +Registers R18 - R29 and F13 - F31 are considered scratch registers. + +#### Stack layout + +The stack pointer, R1, grows down and is aligned to 8 bytes in Go, but changed +to 16 bytes when calling cgo. + +A function's stack frame, after the frame is created, is laid out as +follows: + + +------------------------------+ + | ... locals ... | + | ... outgoing arguments ... | + | 24 TOC register R2 save | When compiled with -shared/-dynlink + | 16 Unused in Go | Not used in Go + | 8 CR save | nonvolatile CR fields + | 0 return PC | ← R1 points to + +------------------------------+ ↓ lower addresses + +The "return PC" is loaded to the link register, LR, as part of the +ppc64 `BL` operations. + +On entry to a non-leaf function, the stack frame size is subtracted from R1 to +create its stack frame, and saves the value of LR at the bottom of the frame. + +A leaf function that does not require any stack space does not modify R1 and +does not save LR. + +*NOTE*: We might need to save the frame pointer on the stack as +in the PPC64 ELF v2 ABI so Go can inter-operate with platform debuggers +and profilers. + +This stack layout is used by both register-based (ABIInternal) and +stack-based (ABI0) calling conventions. + +#### Flags + +The condition register consists of 8 condition code register fields +CR0-CR7. Go generated code only sets and uses CR0, commonly set by +compare functions and use to determine the target of a conditional +branch. The generated code does not set or use CR1-CR7. + +The floating point status and control register (FPSCR) is initialized +to 0 by the kernel at startup of the Go program and not changed by +the Go generated code. + ## Future directions ### Spill path improvements -- GitLab From 5e9c1fedb69b405b75a0c499e2f32d35f294fd5c Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Thu, 16 Sep 2021 10:34:46 -0400 Subject: [PATCH 1209/2500] [dev.fuzz] internal/fuzz: warn if fuzzing begins with empty corpus Fixes golang/go#46219 Change-Id: I7b32707d490c046d15324a3d297ec8d9f45b6e36 Reviewed-on: https://go-review.googlesource.com/c/go/+/350269 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Julie Qiu Reviewed-by: Jay Conrod --- src/internal/fuzz/fuzz.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 7343e17e44..99cf39e100 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -641,6 +641,7 @@ func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { } if len(c.corpus.entries) == 0 { + fmt.Fprintf(c.opts.Log, "warning: starting with empty corpus\n") var vals []interface{} for _, t := range opts.Types { vals = append(vals, zeroValue(t)) -- GitLab From 24e25afff457839ddd78b802b42b8fceda0a6904 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Thu, 16 Sep 2021 10:03:04 -0400 Subject: [PATCH 1210/2500] [dev.fuzz] Revert "[dev.fuzz] testing: convert seed corpus values where possible" This reverts commit 413c125da38990720744c0d98ab65c0d5b1602da. Reason for revert: Giving this more thought, we've decided that converting types under the hood may cause unexpected behavior to users. This is a feature that can always be added after more consideration has been done, but is not something that can be removed due to the backwards compatibility promise. Updates golang/go#45593 Change-Id: I79bab24979d7e4c294e6cb6455d4c7729d6a0efb Reviewed-on: https://go-review.googlesource.com/c/go/+/350251 Trust: Katie Hockman Trust: Joe Tsai Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod Reviewed-by: Joe Tsai --- src/cmd/go/testdata/script/test_fuzz.txt | 32 ++++----------------- src/internal/fuzz/fuzz.go | 36 +++--------------------- src/testing/fuzz.go | 2 +- 3 files changed, 10 insertions(+), 60 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt index 3f825c1bc3..b1a02f46eb 100644 --- a/src/cmd/go/testdata/script/test_fuzz.txt +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -131,23 +131,11 @@ stdout FAIL ! stdout ^ok stdout FAIL -# Test that converting compatible value from f.Add successful runs cleanly. -go test -run FuzzConvertType fuzz_add_test.go -stdout ^ok -! stdout FAIL - -# Test that converting incompatible value from f.Add fails. -! go test -run FuzzConvertIncompatibleType fuzz_add_test.go +# Test that the wrong type given with f.Add will fail. +! go test -run FuzzWrongType fuzz_add_test.go ! stdout ^ok stdout FAIL -# Test that converts value which would lose precision from f.Add. -# Consider making a test like this fail, as it may have unexpected -# consequences for the developer. -go test -v -run FuzzConvertLosePrecision fuzz_add_test.go -stdout ok -! stdout FAIL - # Test fatal with testdata seed corpus ! go test -run FuzzFail corpustesting/fuzz_testdata_corpus_test.go ! stdout ^ok @@ -391,19 +379,9 @@ func FuzzAddDifferentType(f *testing.F) { f.Fuzz(func(*testing.T, []byte) {}) } -func FuzzConvertIncompatibleType(f *testing.F) { - f.Add("abcde") - f.Fuzz(func(*testing.T, int64) {}) -} - -func FuzzConvertLosePrecision(f *testing.F) { - f.Add(-1) - f.Fuzz(func(*testing.T, uint) {}) -} - -func FuzzConvertType(f *testing.F) { - f.Add(1, "hello") - f.Fuzz(func(*testing.T, uint, []byte) {}) +func FuzzWrongType(f *testing.F) { + f.Add("hello") + f.Fuzz(func(*testing.T, []byte) {}) } -- corpustesting/fuzz_testdata_corpus_test.go -- diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 99cf39e100..2cd7ebb472 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -942,47 +942,19 @@ func readCorpusData(data []byte, types []reflect.Type) ([]interface{}, error) { } // CheckCorpus verifies that the types in vals match the expected types -// provided. If not, attempt to convert them. If that's not possible, return an -// error. +// provided. func CheckCorpus(vals []interface{}, types []reflect.Type) error { if len(vals) != len(types) { - return fmt.Errorf("wrong number of values in corpus file: %d, want %d", len(vals), len(types)) + return fmt.Errorf("wrong number of values in corpus entry: %d, want %d", len(vals), len(types)) } for i := range types { - orig := reflect.ValueOf(vals[i]) - origType := orig.Type() - wantType := types[i] - if origType == wantType { - continue // already the same type - } - // Attempt to convert the corpus value to the expected type - if !origType.ConvertibleTo(wantType) { - return fmt.Errorf("cannot convert %v to %v", origType, wantType) - } - convertedVal, ok := convertToType(orig, wantType) - if !ok { - return fmt.Errorf("error converting %v to %v", origType, wantType) + if reflect.TypeOf(vals[i]) != types[i] { + return fmt.Errorf("mismatched types in corpus entry: %v, want %v", vals, types) } - // TODO: Check that the value didn't change. - // e.g. val went from int64(-1) -> uint(0) -> int64(0) which should fail - - // Updates vals to use the newly converted value of the expected type. - vals[i] = convertedVal.Interface() } return nil } -func convertToType(orig reflect.Value, t reflect.Type) (converted reflect.Value, ok bool) { - // Convert might panic even if ConvertibleTo returns true, so catch - // that panic and return false. - defer func() { - if r := recover(); r != nil { - ok = false - } - }() - return orig.Convert(t), true -} - // writeToCorpus atomically writes the given bytes to a new file in testdata. // If the directory does not exist, it will create one. If the file already // exists, writeToCorpus will not rewrite it. writeToCorpus returns the diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 3a1b0bdeaa..57ea418039 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -250,7 +250,7 @@ func (f *F) TempDir() string { // Add will add the arguments to the seed corpus for the fuzz target. This will // be a no-op if called after or within the Fuzz function. The args must match -// or be convertible to those in the Fuzz function. +// those in the Fuzz function. func (f *F) Add(args ...interface{}) { var values []interface{} for i := range args { -- GitLab From b6dddaccd7e8c9c6768943918d03f455385294b9 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sun, 19 Sep 2021 17:17:31 -0700 Subject: [PATCH 1211/2500] cmd/compile: fix transform.AssignOp to deal with tricky case When going to dictionary formats derived from the function instantiations, I had broken out noder.Assignop() to deal specially with shape types, but didn't quite get the tricky case right. We still need to allow conversion between shape types, but if the destination is an interface, we need to use CONVIFACE rather than CONVNOP. Fixes #48453. Change-Id: I8c4b39c2e628172ac34f493f1dd682cbac1e55ae Reviewed-on: https://go-review.googlesource.com/c/go/+/350949 Trust: Dan Scales Run-TryBot: Dan Scales Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/transform.go | 15 ++++++++++++--- test/typeparam/issue48453.go | 21 +++++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 test/typeparam/issue48453.go diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index a117e310ea..3e5cfacb97 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -431,9 +431,18 @@ func Assignop(src, dst *types.Type) (ir.Op, string) { return ir.OXXX, "" } - // 1. src type is identical to dst. - if types.IdenticalStrict(src, dst) { - return ir.OCONVNOP, "" + // 1. src type is identical to dst (taking shapes into account) + if types.Identical(src, dst) { + // We already know from assignconvfn above that IdenticalStrict(src, + // dst) is false, so the types are not exactly the same and one of + // src or dst is a shape. If dst is an interface (which means src is + // an interface too), we need a real OCONVIFACE op; otherwise we need a + // OCONVNOP. See issue #48453. + if dst.IsInterface() { + return ir.OCONVIFACE, "" + } else { + return ir.OCONVNOP, "" + } } return typecheck.Assignop1(src, dst) } diff --git a/test/typeparam/issue48453.go b/test/typeparam/issue48453.go new file mode 100644 index 0000000000..0f751d38ed --- /dev/null +++ b/test/typeparam/issue48453.go @@ -0,0 +1,21 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +//go:noinline +func CopyMap[M interface{ ~map[K]V }, K comparable, V any](m M) M { + out := make(M, len(m)) + for k, v := range m { + out[k] = v + } + return out +} + +func main() { + var m map[*string]int + CopyMap(m) +} -- GitLab From 988f18d61d27f75f6a21cef0aa28b8d85982a85d Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 20 Sep 2021 13:28:25 -0400 Subject: [PATCH 1212/2500] go/types: export Named._Orig as Named.Origin Export the _Orig method for Named types, and rename to Origin. As discussed in #47916, Orig is easily confused with Original, which is not as good a name. Spelling out 'Origin' resolves the ambiguity. Updates #47916 Change-Id: I377c73de82310d3f6aa0bd82dddcd60ee067155b Reviewed-on: https://go-review.googlesource.com/c/go/+/350996 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/named.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/go/types/named.go b/src/go/types/named.go index 4a263410fc..302e43174e 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -91,9 +91,9 @@ func (t *Named) Obj() *TypeName { return t.orig.obj // for non-instances this is the same as t.obj } -// _Orig returns the original generic type an instantiated type is derived from. -// If t is not an instantiated type, the result is t. -func (t *Named) _Orig() *Named { return t.orig } +// Origin returns the parameterized type from which the named type t is +// instantiated. If t is not an instantiated type, the result is t. +func (t *Named) Origin() *Named { return t.orig } // TODO(gri) Come up with a better representation and API to distinguish // between parameterized instantiated and non-instantiated types. -- GitLab From 6acac8b6856b2531f4ac7ee0eb37048d588d98c7 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 6 Sep 2021 17:46:50 -0700 Subject: [PATCH 1213/2500] cmd/compile: delay all transforms for generic funcs/methods This change cleans up the code, by just delaying all transforms on generic function methods/functions until stenciling time. That way, we don't have extra code to decide whether to delay, or an extra value for the typecheck flag. We are already doing all possible transforms at stencil time anyway, so no changes to the stenciling code. transform.go includes a change for one case where we check for shape rather than tparam, now that we only apply transforms to stenciled functions, not generic functions. This change is to allow CONVIFACE node to be correctly inserted (needed for dictionaries), even with this strange code that doesn't add the CONVIFACE node if the concrete type is NOT huge... Change-Id: I5f1e71fab11b53385902074915b3ad85f8e753fa Reviewed-on: https://go-review.googlesource.com/c/go/+/350736 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Dan Scales --- src/cmd/compile/internal/ir/mini.go | 2 +- src/cmd/compile/internal/noder/helpers.go | 60 ++++++----------- src/cmd/compile/internal/noder/stmt.go | 71 ++++----------------- src/cmd/compile/internal/noder/transform.go | 2 +- 4 files changed, 37 insertions(+), 98 deletions(-) diff --git a/src/cmd/compile/internal/ir/mini.go b/src/cmd/compile/internal/ir/mini.go index a7ff4ac9c7..eeb74081fb 100644 --- a/src/cmd/compile/internal/ir/mini.go +++ b/src/cmd/compile/internal/ir/mini.go @@ -62,7 +62,7 @@ const ( func (n *miniNode) Typecheck() uint8 { return n.bits.get2(miniTypecheckShift) } func (n *miniNode) SetTypecheck(x uint8) { - if x > 3 { + if x > 2 { panic(fmt.Sprintf("cannot SetTypecheck %d", x)) } n.bits.set2(miniTypecheckShift, x) diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index f06dd8b065..636b5d64cd 100644 --- a/src/cmd/compile/internal/noder/helpers.go +++ b/src/cmd/compile/internal/noder/helpers.go @@ -95,16 +95,12 @@ func Binary(pos src.XPos, op ir.Op, typ *types.Type, x, y ir.Node) ir.Node { return typed(x.Type(), ir.NewLogicalExpr(pos, op, x, y)) case ir.OADD: n := ir.NewBinaryExpr(pos, op, x, y) - if x.Type().HasTParam() || y.Type().HasTParam() { - // Delay transformAdd() if either arg has a type param, - // since it needs to know the exact types to decide whether - // to transform OADD to OADDSTR. - n.SetType(typ) - n.SetTypecheck(3) - return n - } typed(typ, n) - return transformAdd(n) + r := ir.Node(n) + if !delayTransform() { + r = transformAdd(n) + } + return r default: return typed(x.Type(), ir.NewBinaryExpr(pos, op, x, y)) } @@ -201,22 +197,10 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) func Compare(pos src.XPos, typ *types.Type, op ir.Op, x, y ir.Node) ir.Node { n := ir.NewBinaryExpr(pos, op, x, y) - if x.Type().HasTParam() || y.Type().HasTParam() { - xIsInt := x.Type().IsInterface() - yIsInt := y.Type().IsInterface() - if !(xIsInt && !yIsInt || !xIsInt && yIsInt) { - // If either arg is a type param, then we can still do the - // transformCompare() if we know that one arg is an interface - // and the other is not. Otherwise, we delay - // transformCompare(), since it needs to know the exact types - // to decide on any needed conversions. - n.SetType(typ) - n.SetTypecheck(3) - return n - } - } typed(typ, n) - transformCompare(n) + if !delayTransform() { + transformCompare(n) + } return n } @@ -288,15 +272,11 @@ func method(typ *types.Type, index int) *types.Field { func Index(pos src.XPos, typ *types.Type, x, index ir.Node) ir.Node { n := ir.NewIndexExpr(pos, x, index) - if x.Type().HasTParam() { - // transformIndex needs to know exact type - n.SetType(typ) - n.SetTypecheck(3) - return n - } typed(typ, n) - // transformIndex will modify n.Type() for OINDEXMAP. - transformIndex(n) + if !delayTransform() { + // transformIndex will modify n.Type() for OINDEXMAP. + transformIndex(n) + } return n } @@ -306,14 +286,10 @@ func Slice(pos src.XPos, typ *types.Type, x, low, high, max ir.Node) ir.Node { op = ir.OSLICE3 } n := ir.NewSliceExpr(pos, op, x, low, high, max) - if x.Type().HasTParam() { - // transformSlice needs to know if x.Type() is a string or an array or a slice. - n.SetType(typ) - n.SetTypecheck(3) - return n - } typed(typ, n) - transformSlice(n) + if !delayTransform() { + transformSlice(n) + } return n } @@ -355,3 +331,9 @@ func IncDec(pos src.XPos, op ir.Op, x ir.Node) *ir.AssignOpStmt { } return ir.NewAssignOpStmt(pos, op, x, bl) } + +// delayTransform returns true if we should delay all transforms, because we are +// creating the nodes for a generic function/method. +func delayTransform() bool { + return ir.CurFunc != nil && ir.CurFunc.Type().HasTParam() +} diff --git a/src/cmd/compile/internal/noder/stmt.go b/src/cmd/compile/internal/noder/stmt.go index aefd9fcdaa..805a4710c4 100644 --- a/src/cmd/compile/internal/noder/stmt.go +++ b/src/cmd/compile/internal/noder/stmt.go @@ -40,13 +40,9 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { return wrapname(g.pos(stmt.X), g.expr(stmt.X)) case *syntax.SendStmt: n := ir.NewSendStmt(g.pos(stmt), g.expr(stmt.Chan), g.expr(stmt.Value)) - if n.Chan.Type().HasTParam() || n.Value.Type().HasTParam() { - // Delay transforming the send if the channel or value - // have a type param. - n.SetTypecheck(3) - return n + if !delayTransform() { + transformSend(n) } - transformSend(n) n.SetTypecheck(1) return n case *syntax.DeclStmt: @@ -66,11 +62,9 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { lhs := g.expr(stmt.Lhs) n = ir.NewAssignOpStmt(g.pos(stmt), op, lhs, rhs) } - if n.X.Typecheck() == 3 { - n.SetTypecheck(3) - return n + if !delayTransform() { + transformAsOp(n) } - transformAsOp(n) n.SetTypecheck(1) return n } @@ -79,46 +73,24 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { rhs := g.exprList(stmt.Rhs) names, lhs := g.assignList(stmt.Lhs, stmt.Op == syntax.Def) - // We must delay transforming the assign statement if any of the - // lhs or rhs nodes are also delayed, since transformAssign needs - // to know the types of the left and right sides in various cases. - delay := false - for _, e := range lhs { - if e.Type().HasTParam() || e.Typecheck() == 3 { - delay = true - break - } - } - for _, e := range rhs { - if e.Type().HasTParam() || e.Typecheck() == 3 { - delay = true - break - } - } - if len(lhs) == 1 && len(rhs) == 1 { n := ir.NewAssignStmt(g.pos(stmt), lhs[0], rhs[0]) n.Def = initDefn(n, names) - if delay { - n.SetTypecheck(3) - return n + if !delayTransform() { + lhs, rhs := []ir.Node{n.X}, []ir.Node{n.Y} + transformAssign(n, lhs, rhs) + n.X, n.Y = lhs[0], rhs[0] } - - lhs, rhs := []ir.Node{n.X}, []ir.Node{n.Y} - transformAssign(n, lhs, rhs) - n.X, n.Y = lhs[0], rhs[0] n.SetTypecheck(1) return n } n := ir.NewAssignListStmt(g.pos(stmt), ir.OAS2, lhs, rhs) n.Def = initDefn(n, names) - if delay { - n.SetTypecheck(3) - return n + if !delayTransform() { + transformAssign(n, n.Lhs, n.Rhs) } - transformAssign(n, n.Lhs, n.Rhs) n.SetTypecheck(1) return n @@ -128,15 +100,9 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { return ir.NewGoDeferStmt(g.pos(stmt), g.tokOp(int(stmt.Tok), callOps[:]), g.expr(stmt.Call)) case *syntax.ReturnStmt: n := ir.NewReturnStmt(g.pos(stmt), g.exprList(stmt.Results)) - for _, e := range n.Results { - if e.Type().HasTParam() { - // Delay transforming the return statement if any of the - // return values have a type param. - n.SetTypecheck(3) - return n - } + if !delayTransform() { + transformReturn(n) } - transformReturn(n) n.SetTypecheck(1) return n case *syntax.IfStmt: @@ -146,19 +112,10 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { case *syntax.SelectStmt: n := g.selectStmt(stmt) - delay := false - for _, ncase := range n.(*ir.SelectStmt).Cases { - if ncase.Comm != nil && ncase.Comm.Typecheck() == 3 { - delay = true - break - } - } - if delay { - n.SetTypecheck(3) - } else { + if !delayTransform() { transformSelect(n.(*ir.SelectStmt)) - n.SetTypecheck(1) } + n.SetTypecheck(1) return n case *syntax.SwitchStmt: return g.switchStmt(stmt) diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index 3e5cfacb97..953036eb42 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -195,7 +195,7 @@ func transformCompare(n *ir.BinaryExpr) { aop, _ := typecheck.Assignop(lt, rt) if aop != ir.OXXX { types.CalcSize(lt) - if lt.HasTParam() || rt.IsInterface() == lt.IsInterface() || lt.Size() >= 1<<16 { + if lt.HasShape() || rt.IsInterface() == lt.IsInterface() || lt.Size() >= 1<<16 { l = ir.NewConvExpr(base.Pos, aop, rt, l) l.SetTypecheck(1) } -- GitLab From 6268468e024ce7fa063611b98a2f11f17fd4bad8 Mon Sep 17 00:00:00 2001 From: Alessandro Arzilli Date: Fri, 3 Sep 2021 17:00:41 +0200 Subject: [PATCH 1214/2500] cmd/link: generate DIE for types referenced only through dictionaries Generate debug_info entries for types that are only referenced through dictionaries. Change-Id: Ic36c2e6d9588ec6746793bb213c2dc0e17a8a850 Reviewed-on: https://go-review.googlesource.com/c/go/+/350532 Run-TryBot: Alessandro Arzilli TryBot-Result: Go Bot Reviewed-by: Dan Scales Reviewed-by: Than McIntosh Trust: Dan Scales Trust: David Chase --- src/cmd/compile/internal/noder/stencil.go | 1 + src/cmd/internal/goobj/objfile.go | 2 ++ src/cmd/internal/obj/objfile.go | 3 +++ src/cmd/link/internal/ld/dwarf.go | 16 +++++++++++++++- src/cmd/link/internal/ld/dwarf_test.go | 23 +++++++++++++++++++++-- src/cmd/link/internal/loader/loader.go | 9 +++++++++ 6 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index e2525a8f7e..7fca674132 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1479,6 +1479,7 @@ func markTypeUsed(t *types.Type, lsym *obj.LSym) { } else { // TODO: This is somewhat overkill, we really only need it // for types that are put into interfaces. + // Note: this relocation is also used in cmd/link/internal/ld/dwarf.go reflectdata.MarkTypeUsedInInterface(t, lsym) } } diff --git a/src/cmd/internal/goobj/objfile.go b/src/cmd/internal/goobj/objfile.go index e2858bd57d..20bf0eba89 100644 --- a/src/cmd/internal/goobj/objfile.go +++ b/src/cmd/internal/goobj/objfile.go @@ -304,6 +304,7 @@ const ( const ( SymFlagUsedInIface = 1 << iota SymFlagItab + SymFlagDict ) // Returns the length of the name of the symbol. @@ -333,6 +334,7 @@ func (s *Sym) ReflectMethod() bool { return s.Flag()&SymFlagReflectMethod != 0 } func (s *Sym) IsGoType() bool { return s.Flag()&SymFlagGoType != 0 } func (s *Sym) UsedInIface() bool { return s.Flag2()&SymFlagUsedInIface != 0 } func (s *Sym) IsItab() bool { return s.Flag2()&SymFlagItab != 0 } +func (s *Sym) IsDict() bool { return s.Flag2()&SymFlagDict != 0 } func (s *Sym) SetName(x string, w *Writer) { binary.LittleEndian.PutUint32(s[:], uint32(len(x))) diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index 01466ea736..910e6ef0d9 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -340,6 +340,9 @@ func (w *writer) Sym(s *LSym) { if strings.HasPrefix(s.Name, "go.itab.") && s.Type == objabi.SRODATA { flag2 |= goobj.SymFlagItab } + if strings.HasPrefix(s.Name, w.ctxt.Pkgpath) && strings.HasPrefix(s.Name[len(w.ctxt.Pkgpath):], "..dict") { + flag2 |= goobj.SymFlagDict + } name := s.Name if strings.HasPrefix(name, "gofile..") { name = filepath.ToSlash(name) diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go index 839609339f..d72846a691 100644 --- a/src/cmd/link/internal/ld/dwarf.go +++ b/src/cmd/link/internal/ld/dwarf.go @@ -1890,6 +1890,8 @@ func dwarfGenerateDebugInfo(ctxt *Link) { // global variables. For each global of this sort, locate // the corresponding compiler-generated DIE symbol and tack // it onto the list associated with the unit. + // Also looks for dictionary symbols and generates DIE symbols for each + // type they reference. for idx := loader.Sym(1); idx < loader.Sym(d.ldr.NDef()); idx++ { if !d.ldr.AttrReachable(idx) || d.ldr.AttrNotInSymbolTable(idx) || @@ -1903,9 +1905,21 @@ func dwarfGenerateDebugInfo(ctxt *Link) { default: continue } - // Skip things with no type + // Skip things with no type, unless it's a dictionary gt := d.ldr.SymGoType(idx) if gt == 0 { + if t == sym.SRODATA { + if d.ldr.IsDict(idx) { + // This is a dictionary, make sure that all types referenced by this dictionary are reachable + relocs := d.ldr.Relocs(idx) + for i := 0; i < relocs.Count(); i++ { + reloc := relocs.At(i) + if reloc.Type() == objabi.R_USEIFACE { + d.defgotype(reloc.Sym()) + } + } + } + } continue } // Skip file local symbols (this includes static tmps, stack diff --git a/src/cmd/link/internal/ld/dwarf_test.go b/src/cmd/link/internal/ld/dwarf_test.go index 3d112d97a4..db9002491e 100644 --- a/src/cmd/link/internal/ld/dwarf_test.go +++ b/src/cmd/link/internal/ld/dwarf_test.go @@ -1749,7 +1749,9 @@ func main() { } func TestDictIndex(t *testing.T) { - // Check that variables with a parametric type have a dictionary index attribute + // Check that variables with a parametric type have a dictionary index + // attribute and that types that are only referenced through dictionaries + // have DIEs. testenv.MustHaveGoBuild(t) if runtime.GOOS == "plan9" { @@ -1765,6 +1767,8 @@ package main import "fmt" +type CustomInt int + func testfn[T any](arg T) { var mapvar = make(map[int]T) mapvar[0] = arg @@ -1772,7 +1776,7 @@ func testfn[T any](arg T) { } func main() { - testfn("test") + testfn(CustomInt(3)) } ` @@ -1829,4 +1833,19 @@ func main() { t.Errorf("could not find DW_AT_go_dict_index attribute offset %#x (%T)", off, entry.Val(intdwarf.DW_AT_go_dict_index)) } } + + rdr.Seek(0) + ex := examiner{} + if err := ex.populate(rdr); err != nil { + t.Fatalf("error reading DWARF: %v", err) + } + for _, typeName := range []string{"main.CustomInt", "map[int]main.CustomInt"} { + dies := ex.Named(typeName) + if len(dies) != 1 { + t.Errorf("wanted 1 DIE named %s, found %v", typeName, len(dies)) + } + if dies[0].Val(intdwarf.DW_AT_go_runtime_type).(uint64) == 0 { + t.Errorf("type %s does not have DW_AT_go_runtime_type", typeName) + } + } } diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index f144e00f37..b9a1da6f45 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -1209,6 +1209,15 @@ func (l *Loader) IsItab(i Sym) bool { return r.Sym(li).IsItab() } +// Returns whether this symbol is a dictionary symbol. +func (l *Loader) IsDict(i Sym) bool { + if l.IsExternal(i) { + return false + } + r, li := l.toLocal(i) + return r.Sym(li).IsDict() +} + // Return whether this is a trampoline of a deferreturn call. func (l *Loader) IsDeferReturnTramp(i Sym) bool { return l.deferReturnTramp[i] -- GitLab From 3c764babe7b5e01a4e04b1a2c7975cdb5c5651a0 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Thu, 9 Sep 2021 09:38:55 -0700 Subject: [PATCH 1215/2500] cmd/go: write go.mod requirements more consistently for go 1.17+ If go.mod declares 1.17 or higher, when the go command rewrites go.mod (for example, after 'go mod tidy'), it will be more consistent about moving requirements in two blocks, one containing only direct requirements, and one containing only indirect requirements. The go command will not move requirements into or out of a block with comments. It may still update versions and "// indirect" comments, and it may delete unneeded requirements though. Fixes #47563 Fixes #47733 Change-Id: Ia6fb3e302be53097893abf01aa7cea60ac7b069a Reviewed-on: https://go-review.googlesource.com/c/go/+/343432 Trust: Jay Conrod Run-TryBot: Jay Conrod Reviewed-by: Bryan C. Mills --- src/cmd/go.mod | 11 +- src/cmd/go.sum | 4 +- src/cmd/go/testdata/script/mod_all.txt | 67 +++- src/cmd/go/testdata/script/mod_retention.txt | 22 +- .../script/mod_tidy_compat_ambiguous.txt | 7 +- .../script/mod_tidy_compat_incompatible.txt | 7 +- .../vendor/golang.org/x/mod/modfile/rule.go | 295 ++++++++++-------- src/cmd/vendor/modules.txt | 2 +- src/go.mod | 3 + 9 files changed, 266 insertions(+), 152 deletions(-) diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 05a118d812..26be677254 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -4,12 +4,15 @@ go 1.18 require ( github.com/google/pprof v0.0.0-20210827144239-02619b876842 - github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 // indirect golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1 - golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect - golang.org/x/mod v0.5.1-0.20210830214625-1b1db11ec8f4 - golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e // indirect + golang.org/x/mod v0.5.1-0.20210913215816-37dd6891021a golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b golang.org/x/tools v0.1.6-0.20210904010709-360456621443 +) + +require ( + github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 // indirect + golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect + golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index eebb44c053..19bb1ee213 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -9,8 +9,8 @@ golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1 h1:MwxAfiDvuwX8Nnnc6iRDhzyM golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/mod v0.5.1-0.20210830214625-1b1db11ec8f4 h1:7Qds88gNaRx0Dz/1wOwXlR7asekh1B1u26wEwN6FcEI= -golang.org/x/mod v0.5.1-0.20210830214625-1b1db11ec8f4/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.5.1-0.20210913215816-37dd6891021a h1:55PVa91KndtPGH2lus5l2gDZqoO/x+Oa5CV0lVf8Ij8= +golang.org/x/mod v0.5.1-0.20210913215816-37dd6891021a/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e h1:XMgFehsDnnLGtjvjOfqWSUzt0alpTR1RSEuznObga2c= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/src/cmd/go/testdata/script/mod_all.txt b/src/cmd/go/testdata/script/mod_all.txt index 6fa2d83239..b71a920870 100644 --- a/src/cmd/go/testdata/script/mod_all.txt +++ b/src/cmd/go/testdata/script/mod_all.txt @@ -202,9 +202,9 @@ go mod edit -go=1.17 u/go.mod go mod edit -go=1.17 w/go.mod go mod edit -go=1.17 x/go.mod go mod edit -go=1.17 -cp go.mod go.mod.orig +cmp go.mod go.mod.beforetidy go mod tidy -cmp go.mod go.mod.orig +cmp go.mod go.mod.aftertidy # With lazy loading, 'go list all' with neither -mod=vendor nor -test should # match -mod=vendor without -test in 1.15. @@ -466,3 +466,66 @@ module example.com/x go 1.15 -- x/x.go -- package x +-- go.mod.beforetidy -- +module example.com/main + +// Note: this go.mod file initially specifies go 1.15, +// but includes some redundant roots so that it +// also already obeys the 1.17 lazy loading invariants. +go 1.17 + +require ( + example.com/a v0.1.0 + example.com/b v0.1.0 // indirect + example.com/q v0.1.0 + example.com/r v0.1.0 // indirect + example.com/t v0.1.0 + example.com/u v0.1.0 // indirect +) + +replace ( + example.com/a v0.1.0 => ./a + example.com/b v0.1.0 => ./b + example.com/c v0.1.0 => ./c + example.com/d v0.1.0 => ./d + example.com/q v0.1.0 => ./q + example.com/r v0.1.0 => ./r + example.com/s v0.1.0 => ./s + example.com/t v0.1.0 => ./t + example.com/u v0.1.0 => ./u + example.com/w v0.1.0 => ./w + example.com/x v0.1.0 => ./x +) +-- go.mod.aftertidy -- +module example.com/main + +// Note: this go.mod file initially specifies go 1.15, +// but includes some redundant roots so that it +// also already obeys the 1.17 lazy loading invariants. +go 1.17 + +require ( + example.com/a v0.1.0 + example.com/q v0.1.0 + example.com/t v0.1.0 +) + +require ( + example.com/b v0.1.0 // indirect + example.com/r v0.1.0 // indirect + example.com/u v0.1.0 // indirect +) + +replace ( + example.com/a v0.1.0 => ./a + example.com/b v0.1.0 => ./b + example.com/c v0.1.0 => ./c + example.com/d v0.1.0 => ./d + example.com/q v0.1.0 => ./q + example.com/r v0.1.0 => ./r + example.com/s v0.1.0 => ./s + example.com/t v0.1.0 => ./t + example.com/u v0.1.0 => ./u + example.com/w v0.1.0 => ./w + example.com/x v0.1.0 => ./x +) diff --git a/src/cmd/go/testdata/script/mod_retention.txt b/src/cmd/go/testdata/script/mod_retention.txt index 481c10d2b7..9d30026459 100644 --- a/src/cmd/go/testdata/script/mod_retention.txt +++ b/src/cmd/go/testdata/script/mod_retention.txt @@ -83,14 +83,14 @@ require ( package x import _ "rsc.io/quote" -- go.mod.crlf -- -module m - -go 1.14 - -require ( - rsc.io/quote v1.5.2 - rsc.io/testonly v1.0.0 // indirect -) +module m + +go 1.14 + +require ( + rsc.io/quote v1.5.2 + rsc.io/testonly v1.0.0 // indirect +) -- go.mod.unsorted -- module m @@ -141,10 +141,10 @@ module m go $goversion +require rsc.io/quote v1.5.2 + require ( - rsc.io/quote v1.5.2 + golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect rsc.io/sampler v1.3.0 // indirect rsc.io/testonly v1.0.0 // indirect ) - -require golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect diff --git a/src/cmd/go/testdata/script/mod_tidy_compat_ambiguous.txt b/src/cmd/go/testdata/script/mod_tidy_compat_ambiguous.txt index 44bc58cc6c..a45de5ad8c 100644 --- a/src/cmd/go/testdata/script/mod_tidy_compat_ambiguous.txt +++ b/src/cmd/go/testdata/script/mod_tidy_compat_ambiguous.txt @@ -72,10 +72,9 @@ go 1.17 replace example.net/indirect v0.1.0 => ./indirect -require ( - example.net/ambiguous/nested v0.1.0 // indirect - example.net/indirect v0.1.0 -) +require example.net/indirect v0.1.0 + +require example.net/ambiguous/nested v0.1.0 // indirect -- all-m.txt -- example.com/m example.net/ambiguous v0.1.0 diff --git a/src/cmd/go/testdata/script/mod_tidy_compat_incompatible.txt b/src/cmd/go/testdata/script/mod_tidy_compat_incompatible.txt index ea9e42e87e..11313f144c 100644 --- a/src/cmd/go/testdata/script/mod_tidy_compat_incompatible.txt +++ b/src/cmd/go/testdata/script/mod_tidy_compat_incompatible.txt @@ -97,10 +97,9 @@ replace ( example.net/requireincompatible v0.1.0 => ./requireincompatible ) -require ( - example.com/retract/incompatible v1.0.0 // indirect - example.net/lazy v0.1.0 -) +require example.net/lazy v0.1.0 + +require example.com/retract/incompatible v1.0.0 // indirect -- incompatible.go -- package incompatible diff --git a/src/cmd/vendor/golang.org/x/mod/modfile/rule.go b/src/cmd/vendor/golang.org/x/mod/modfile/rule.go index d6a2d3879e..98211a450a 100644 --- a/src/cmd/vendor/golang.org/x/mod/modfile/rule.go +++ b/src/cmd/vendor/golang.org/x/mod/modfile/rule.go @@ -1034,170 +1034,217 @@ func (f *File) SetRequire(req []*Require) { // SetRequireSeparateIndirect updates the requirements of f to contain the given // requirements. Comment contents (except for 'indirect' markings) are retained -// from the first existing requirement for each module path, and block structure -// is maintained as long as the indirect markings match. +// from the first existing requirement for each module path. Like SetRequire, +// SetRequireSeparateIndirect adds requirements for new paths in req, +// updates the version and "// indirect" comment on existing requirements, +// and deletes requirements on paths not in req. Existing duplicate requirements +// are deleted. // -// Any requirements on paths not already present in the file are added. Direct -// requirements are added to the last block containing *any* other direct -// requirement. Indirect requirements are added to the last block containing -// *only* other indirect requirements. If no suitable block exists, a new one is -// added, with the last block containing a direct dependency (if any) -// immediately before the first block containing only indirect dependencies. +// As its name suggests, SetRequireSeparateIndirect puts direct and indirect +// requirements into two separate blocks, one containing only direct +// requirements, and the other containing only indirect requirements. +// SetRequireSeparateIndirect may move requirements between these two blocks +// when their indirect markings change. However, SetRequireSeparateIndirect +// won't move requirements from other blocks, especially blocks with comments. // -// The Syntax field is ignored for requirements in the given blocks. +// If the file initially has one uncommented block of requirements, +// SetRequireSeparateIndirect will split it into a direct-only and indirect-only +// block. This aids in the transition to separate blocks. func (f *File) SetRequireSeparateIndirect(req []*Require) { - type modKey struct { - path string - indirect bool - } - need := make(map[modKey]string) - for _, r := range req { - need[modKey{r.Mod.Path, r.Indirect}] = r.Mod.Version + // hasComments returns whether a line or block has comments + // other than "indirect". + hasComments := func(c Comments) bool { + return len(c.Before) > 0 || len(c.After) > 0 || len(c.Suffix) > 1 || + (len(c.Suffix) == 1 && + strings.TrimSpace(strings.TrimPrefix(c.Suffix[0].Token, string(slashSlash))) != "indirect") } - comments := make(map[string]Comments) - for _, r := range f.Require { - v, ok := need[modKey{r.Mod.Path, r.Indirect}] - if !ok { - if _, ok := need[modKey{r.Mod.Path, !r.Indirect}]; ok { - if _, dup := comments[r.Mod.Path]; !dup { - comments[r.Mod.Path] = r.Syntax.Comments - } + // moveReq adds r to block. If r was in another block, moveReq deletes + // it from that block and transfers its comments. + moveReq := func(r *Require, block *LineBlock) { + var line *Line + if r.Syntax == nil { + line = &Line{Token: []string{AutoQuote(r.Mod.Path), r.Mod.Version}} + r.Syntax = line + if r.Indirect { + r.setIndirect(true) } - r.markRemoved() - continue + } else { + line = new(Line) + *line = *r.Syntax + if !line.InBlock && len(line.Token) > 0 && line.Token[0] == "require" { + line.Token = line.Token[1:] + } + r.Syntax.Token = nil // Cleanup will delete the old line. + r.Syntax = line } - r.setVersion(v) - delete(need, modKey{r.Mod.Path, r.Indirect}) + line.InBlock = true + block.Line = append(block.Line, line) } + // Examine existing require lines and blocks. var ( - lastDirectOrMixedBlock Expr - firstIndirectOnlyBlock Expr - lastIndirectOnlyBlock Expr + // We may insert new requirements into the last uncommented + // direct-only and indirect-only blocks. We may also move requirements + // to the opposite block if their indirect markings change. + lastDirectIndex = -1 + lastIndirectIndex = -1 + + // If there are no direct-only or indirect-only blocks, a new block may + // be inserted after the last require line or block. + lastRequireIndex = -1 + + // If there's only one require line or block, and it's uncommented, + // we'll move its requirements to the direct-only or indirect-only blocks. + requireLineOrBlockCount = 0 + + // Track the block each requirement belongs to (if any) so we can + // move them later. + lineToBlock = make(map[*Line]*LineBlock) ) - for _, stmt := range f.Syntax.Stmt { + for i, stmt := range f.Syntax.Stmt { switch stmt := stmt.(type) { case *Line: if len(stmt.Token) == 0 || stmt.Token[0] != "require" { continue } - if isIndirect(stmt) { - lastIndirectOnlyBlock = stmt - } else { - lastDirectOrMixedBlock = stmt + lastRequireIndex = i + requireLineOrBlockCount++ + if !hasComments(stmt.Comments) { + if isIndirect(stmt) { + lastIndirectIndex = i + } else { + lastDirectIndex = i + } } + case *LineBlock: if len(stmt.Token) == 0 || stmt.Token[0] != "require" { continue } - indirectOnly := true + lastRequireIndex = i + requireLineOrBlockCount++ + allDirect := len(stmt.Line) > 0 && !hasComments(stmt.Comments) + allIndirect := len(stmt.Line) > 0 && !hasComments(stmt.Comments) for _, line := range stmt.Line { - if len(line.Token) == 0 { - continue - } - if !isIndirect(line) { - indirectOnly = false - break + lineToBlock[line] = stmt + if hasComments(line.Comments) { + allDirect = false + allIndirect = false + } else if isIndirect(line) { + allDirect = false + } else { + allIndirect = false } } - if indirectOnly { - lastIndirectOnlyBlock = stmt - if firstIndirectOnlyBlock == nil { - firstIndirectOnlyBlock = stmt - } - } else { - lastDirectOrMixedBlock = stmt + if allDirect { + lastDirectIndex = i + } + if allIndirect { + lastIndirectIndex = i } } } - isOrContainsStmt := func(stmt Expr, target Expr) bool { - if stmt == target { - return true - } - if stmt, ok := stmt.(*LineBlock); ok { - if target, ok := target.(*Line); ok { - for _, line := range stmt.Line { - if line == target { - return true - } - } + oneFlatUncommentedBlock := requireLineOrBlockCount == 1 && + !hasComments(*f.Syntax.Stmt[lastRequireIndex].Comment()) + + // Create direct and indirect blocks if needed. Convert lines into blocks + // if needed. If we end up with an empty block or a one-line block, + // Cleanup will delete it or convert it to a line later. + insertBlock := func(i int) *LineBlock { + block := &LineBlock{Token: []string{"require"}} + f.Syntax.Stmt = append(f.Syntax.Stmt, nil) + copy(f.Syntax.Stmt[i+1:], f.Syntax.Stmt[i:]) + f.Syntax.Stmt[i] = block + return block + } + + ensureBlock := func(i int) *LineBlock { + switch stmt := f.Syntax.Stmt[i].(type) { + case *LineBlock: + return stmt + case *Line: + block := &LineBlock{ + Token: []string{"require"}, + Line: []*Line{stmt}, } + stmt.Token = stmt.Token[1:] // remove "require" + stmt.InBlock = true + f.Syntax.Stmt[i] = block + return block + default: + panic(fmt.Sprintf("unexpected statement: %v", stmt)) } - return false } - addRequire := func(path, vers string, indirect bool, comments Comments) { - var line *Line - if indirect { - if lastIndirectOnlyBlock != nil { - line = f.Syntax.addLine(lastIndirectOnlyBlock, "require", path, vers) - } else { - // Add a new require block after the last direct-only or mixed "require" - // block (if any). - // - // (f.Syntax.addLine would add the line to an existing "require" block if - // present, but here the existing "require" blocks are all direct-only, so - // we know we need to add a new block instead.) - line = &Line{Token: []string{"require", path, vers}} - lastIndirectOnlyBlock = line - firstIndirectOnlyBlock = line // only block implies first block - if lastDirectOrMixedBlock == nil { - f.Syntax.Stmt = append(f.Syntax.Stmt, line) - } else { - for i, stmt := range f.Syntax.Stmt { - if isOrContainsStmt(stmt, lastDirectOrMixedBlock) { - f.Syntax.Stmt = append(f.Syntax.Stmt, nil) // increase size - copy(f.Syntax.Stmt[i+2:], f.Syntax.Stmt[i+1:]) // shuffle elements up - f.Syntax.Stmt[i+1] = line - break - } - } - } - } + var lastDirectBlock *LineBlock + if lastDirectIndex < 0 { + if lastIndirectIndex >= 0 { + lastDirectIndex = lastIndirectIndex + lastIndirectIndex++ + } else if lastRequireIndex >= 0 { + lastDirectIndex = lastRequireIndex + 1 } else { - if lastDirectOrMixedBlock != nil { - line = f.Syntax.addLine(lastDirectOrMixedBlock, "require", path, vers) - } else { - // Add a new require block before the first indirect block (if any). - // - // That way if the file initially contains only indirect lines, - // the direct lines still appear before it: we preserve existing - // structure, but only to the extent that that structure already - // reflects the direct/indirect split. - line = &Line{Token: []string{"require", path, vers}} - lastDirectOrMixedBlock = line - if firstIndirectOnlyBlock == nil { - f.Syntax.Stmt = append(f.Syntax.Stmt, line) - } else { - for i, stmt := range f.Syntax.Stmt { - if isOrContainsStmt(stmt, firstIndirectOnlyBlock) { - f.Syntax.Stmt = append(f.Syntax.Stmt, nil) // increase size - copy(f.Syntax.Stmt[i+1:], f.Syntax.Stmt[i:]) // shuffle elements up - f.Syntax.Stmt[i] = line - break - } - } - } - } + lastDirectIndex = len(f.Syntax.Stmt) } + lastDirectBlock = insertBlock(lastDirectIndex) + } else { + lastDirectBlock = ensureBlock(lastDirectIndex) + } - line.Comments.Before = commentsAdd(line.Comments.Before, comments.Before) - line.Comments.Suffix = commentsAdd(line.Comments.Suffix, comments.Suffix) + var lastIndirectBlock *LineBlock + if lastIndirectIndex < 0 { + lastIndirectIndex = lastDirectIndex + 1 + lastIndirectBlock = insertBlock(lastIndirectIndex) + } else { + lastIndirectBlock = ensureBlock(lastIndirectIndex) + } - r := &Require{ - Mod: module.Version{Path: path, Version: vers}, - Indirect: indirect, - Syntax: line, + // Delete requirements we don't want anymore. + // Update versions and indirect comments on requirements we want to keep. + // If a requirement is in last{Direct,Indirect}Block with the wrong + // indirect marking after this, or if the requirement is in an single + // uncommented mixed block (oneFlatUncommentedBlock), move it to the + // correct block. + // + // Some blocks may be empty after this. Cleanup will remove them. + need := make(map[string]*Require) + for _, r := range req { + need[r.Mod.Path] = r + } + have := make(map[string]*Require) + for _, r := range f.Require { + path := r.Mod.Path + if need[path] == nil || have[path] != nil { + // Requirement not needed, or duplicate requirement. Delete. + r.markRemoved() + continue + } + have[r.Mod.Path] = r + r.setVersion(need[path].Mod.Version) + r.setIndirect(need[path].Indirect) + if need[path].Indirect && + (oneFlatUncommentedBlock || lineToBlock[r.Syntax] == lastDirectBlock) { + moveReq(r, lastIndirectBlock) + } else if !need[path].Indirect && + (oneFlatUncommentedBlock || lineToBlock[r.Syntax] == lastIndirectBlock) { + moveReq(r, lastDirectBlock) } - r.setIndirect(indirect) - f.Require = append(f.Require, r) } - for k, vers := range need { - addRequire(k.path, vers, k.indirect, comments[k.path]) + // Add new requirements. + for path, r := range need { + if have[path] == nil { + if r.Indirect { + moveReq(r, lastIndirectBlock) + } else { + moveReq(r, lastDirectBlock) + } + f.Require = append(f.Require, r) + } } + f.SortBlocks() } diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 966ba1358e..4ff07ab015 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -28,7 +28,7 @@ golang.org/x/arch/x86/x86asm ## explicit; go 1.17 golang.org/x/crypto/ed25519 golang.org/x/crypto/ed25519/internal/edwards25519 -# golang.org/x/mod v0.5.1-0.20210830214625-1b1db11ec8f4 +# golang.org/x/mod v0.5.1-0.20210913215816-37dd6891021a ## explicit; go 1.17 golang.org/x/mod/internal/lazyregexp golang.org/x/mod/modfile diff --git a/src/go.mod b/src/go.mod index a4a6c4f05d..69e2655e88 100644 --- a/src/go.mod +++ b/src/go.mod @@ -5,6 +5,9 @@ go 1.18 require ( golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 golang.org/x/net v0.0.0-20210825183410-e898025ed96a +) + +require ( golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e // indirect golang.org/x/text v0.3.7 // indirect ) -- GitLab From 51ca5706ab2074a624f8a2590a2a81e6a5821e48 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Wed, 15 Sep 2021 15:30:18 -0700 Subject: [PATCH 1216/2500] [dev.fuzz] cmd/go: in 'go test' don't allow multiple packages with -fuzz Until we have a system for managing load across multiple fuzz targets in multiple test executables, we'll only support fuzzing one target in one package at a time. Users can still run multiple 'go test -fuzz' commands concurrently, but this may overwhelm some systems unless -parallel and -p are set carefully. For #46312 Change-Id: If84c58d1b3e60498ce955eae5ad4d52100dbd4b7 Reviewed-on: https://go-review.googlesource.com/c/go/+/350156 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/cmd/go/internal/test/test.go | 3 ++ .../go/testdata/script/test_fuzz_match.txt | 20 -------- .../go/testdata/script/test_fuzz_multiple.txt | 51 +++++++++++++++++++ 3 files changed, 54 insertions(+), 20 deletions(-) create mode 100644 src/cmd/go/testdata/script/test_fuzz_multiple.txt diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index c36cb0b221..173e8a2ee4 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -671,6 +671,9 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { if testO != "" && len(pkgs) != 1 { base.Fatalf("cannot use -o flag with multiple packages") } + if testFuzz != "" && len(pkgs) != 1 { + base.Fatalf("cannot use -fuzz flag with multiple packages") + } if testProfile() != "" && len(pkgs) != 1 { base.Fatalf("cannot use %s flag with multiple packages", testProfile()) } diff --git a/src/cmd/go/testdata/script/test_fuzz_match.txt b/src/cmd/go/testdata/script/test_fuzz_match.txt index 47e143952a..3a2ca631ad 100644 --- a/src/cmd/go/testdata/script/test_fuzz_match.txt +++ b/src/cmd/go/testdata/script/test_fuzz_match.txt @@ -29,13 +29,6 @@ go test -run ThisWillNotMatch standalone_fuzz_test.go stdout '^ok.*no tests to run' ! stdout 'no targets to fuzz' -# Matches more than one fuzz target for fuzzing. -! go test -fuzz Fuzz -fuzztime 1x multiple_fuzz_test.go -! stdout 'no tests to run' -! stdout 'no targets to fuzz' -stdout FAIL -stdout 'will not fuzz, -fuzz matches more than one target' - -- standalone_fuzz_test.go -- package standalone_fuzz @@ -44,16 +37,3 @@ import "testing" func Fuzz(f *testing.F) { f.Fuzz(func (*testing.T, []byte) {}) } - --- multiple_fuzz_test.go -- -package multiple_fuzz - -import "testing" - -func FuzzA(f *testing.F) { - f.Fuzz(func (*testing.T, []byte) {}) -} - -func FuzzB(f *testing.F) { - f.Fuzz(func (*testing.T, []byte) {}) -} diff --git a/src/cmd/go/testdata/script/test_fuzz_multiple.txt b/src/cmd/go/testdata/script/test_fuzz_multiple.txt new file mode 100644 index 0000000000..6a7732f514 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_multiple.txt @@ -0,0 +1,51 @@ +# This test checks that 'go test' prints a reasonable error when fuzzing is +# enabled, and multiple package or multiple fuzz targets match. +# TODO(#46312): support fuzzing multiple targets in multiple packages. + +# TODO(jayconrod): support shared memory on more platforms. +[!darwin] [!linux] [!windows] skip + +[short] skip + +# With fuzzing disabled, multiple targets can be tested. +go test ./... + +# With fuzzing enabled, at most one package may be tested, +# even if only one package contains fuzz targets. +! go test -fuzz=. ./... +stderr '^cannot use -fuzz flag with multiple packages$' +! go test -fuzz=. ./zero ./one +stderr '^cannot use -fuzz flag with multiple packages$' +go test -fuzz=. -fuzztime=1x ./one + +# With fuzzing enabled, at most one target in the same package may match. +! go test -fuzz=. ./two +stdout '^testing: will not fuzz, -fuzz matches more than one target: \[FuzzOne FuzzTwo\]$' +go test -fuzz=FuzzTwo -fuzztime=1x ./two + +-- go.mod -- +module fuzz + +go 1.18 +-- zero/zero.go -- +package zero +-- one/one_test.go -- +package one + +import "testing" + +func FuzzOne(f *testing.F) { + f.Fuzz(func(*testing.T, []byte) {}) +} +-- two/two_test.go -- +package two + +import "testing" + +func FuzzOne(f *testing.F) { + f.Fuzz(func(*testing.T, []byte) {}) +} + +func FuzzTwo(f *testing.F) { + f.Fuzz(func(*testing.T, []byte) {}) +} -- GitLab From af72ddfcd7826df9aefb2207b8ac270bb91fea2f Mon Sep 17 00:00:00 2001 From: David Chase Date: Thu, 9 Sep 2021 16:34:02 -0400 Subject: [PATCH 1217/2500] cmd/compile: extend dump-to-file to handle "genssa" (asm) case. Extend the existing dump-to-file to also do assembly output to make it easier to write debug-information tests that check for line-numbering in particular orders. Includes POC test (which is silent w/o -v): go test -v -run TestDebugLines cmd/compile/internal/ssa === RUN TestDebugLines Preserving temporary directory /var/folders/v6/xyzzy/T/debug_lines_test321 About to run (cd /var/folders/v6/xyzzy/T/debug_lines_test321; \ GOSSADIR=/var/folders/v6/xyzzy/T/debug_lines_test321 \ /Users/drchase/work/go/bin/go build -o foo.o \ '-gcflags=-N -l -d=ssa/genssa/dump=sayhi' \ /Users/drchase/work/go/src/cmd/compile/internal/ssa/testdata/sayhi.go ) Saw stmt# 8 for submatch '8' on dump line #7 = ' v107 00005 (+8) MOVQ AX, "".n(SP)' Saw stmt# 9 for submatch '9' on dump line #9 = ' v87 00007 (+9) MOVUPS X15, ""..autotmp_2-32(SP)' Saw stmt# 10 for submatch '10' on dump line #46 = ' v65 00044 (+10) MOVUPS X15, ""..autotmp_2-32(SP)' Saw stmt# 11 for submatch '11' on dump line #83 = ' v131 00081 (+11) MOVQ "".wg+8(SP), AX' --- PASS: TestDebugLines (4.95s) PASS ok cmd/compile/internal/ssa 5.685s Includes a test to ensure that inlining information is printed correctly. Updates #47880. Change-Id: I83b596476a88687d71d5b65dbb94641a576d747e Reviewed-on: https://go-review.googlesource.com/c/go/+/348970 Trust: David Chase Run-TryBot: David Chase TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/ssa/compile.go | 59 +++-- .../compile/internal/ssa/debug_lines_test.go | 213 ++++++++++++++++++ src/cmd/compile/internal/ssa/func.go | 2 +- src/cmd/compile/internal/ssa/print.go | 20 +- .../internal/ssa/testdata/inline-dump.go | 17 ++ .../compile/internal/ssa/testdata/sayhi.go | 12 + src/cmd/compile/internal/ssagen/ssa.go | 55 ++++- src/cmd/internal/obj/util.go | 5 + 8 files changed, 360 insertions(+), 23 deletions(-) create mode 100644 src/cmd/compile/internal/ssa/debug_lines_test.go create mode 100644 src/cmd/compile/internal/ssa/testdata/inline-dump.go create mode 100644 src/cmd/compile/internal/ssa/testdata/sayhi.go diff --git a/src/cmd/compile/internal/ssa/compile.go b/src/cmd/compile/internal/ssa/compile.go index cd8eba405d..f87ea5b893 100644 --- a/src/cmd/compile/internal/ssa/compile.go +++ b/src/cmd/compile/internal/ssa/compile.go @@ -10,9 +10,11 @@ import ( "fmt" "hash/crc32" "internal/buildcfg" + "io" "log" "math/rand" "os" + "path/filepath" "regexp" "runtime" "sort" @@ -59,7 +61,7 @@ func Compile(f *Func) { printFunc(f) } f.HTMLWriter.WritePhase("start", "start") - if BuildDump != "" && BuildDump == f.Name { + if BuildDump[f.Name] { f.dumpFile("build") } if checkEnabled { @@ -163,25 +165,37 @@ func Compile(f *Func) { phaseName = "" } -// dumpFile creates a file from the phase name and function name -// Dumping is done to files to avoid buffering huge strings before -// output. -func (f *Func) dumpFile(phaseName string) { +// DumpFileForPhase creates a file from the function name and phase name, +// warning and returning nil if this is not possible. +func (f *Func) DumpFileForPhase(phaseName string) io.WriteCloser { f.dumpFileSeq++ fname := fmt.Sprintf("%s_%02d__%s.dump", f.Name, int(f.dumpFileSeq), phaseName) fname = strings.Replace(fname, " ", "_", -1) fname = strings.Replace(fname, "/", "_", -1) fname = strings.Replace(fname, ":", "_", -1) + if ssaDir := os.Getenv("GOSSADIR"); ssaDir != "" { + fname = filepath.Join(ssaDir, fname) + } + fi, err := os.Create(fname) if err != nil { f.Warnl(src.NoXPos, "Unable to create after-phase dump file %s", fname) - return + return nil } + return fi +} - p := stringFuncPrinter{w: fi} - fprintFunc(p, f) - fi.Close() +// dumpFile creates a file from the phase name and function name +// Dumping is done to files to avoid buffering huge strings before +// output. +func (f *Func) dumpFile(phaseName string) { + fi := f.DumpFileForPhase(phaseName) + if fi != nil { + p := stringFuncPrinter{w: fi} + fprintFunc(p, f) + fi.Close() + } } type pass struct { @@ -224,7 +238,9 @@ var IntrinsicsDisable bool var BuildDebug int var BuildTest int var BuildStats int -var BuildDump string // name of function to dump after initial build of ssa +var BuildDump map[string]bool = make(map[string]bool) // names of functions to dump after initial build of ssa + +var GenssaDump map[string]bool = make(map[string]bool) // names of functions to dump after ssa has been converted to asm // PhaseOption sets the specified flag in the specified ssa phase, // returning empty string if this was successful or a string explaining @@ -248,7 +264,7 @@ func PhaseOption(phase, flag string, val int, valString string) string { switch phase { case "", "help": lastcr := 0 - phasenames := " check, all, build, intrinsics" + phasenames := " check, all, build, intrinsics, genssa" for _, p := range passes { pn := strings.Replace(p.name, " ", "_", -1) if len(pn)+len(phasenames)-lastcr > 70 { @@ -278,6 +294,7 @@ where: Phase "all" supports flags "time", "mem", and "dump". Phase "intrinsics" supports flags "on", "off", and "debug". +Phase "genssa" (assembly generation) supports the flag "dump". If the "dump" flag is specified, the output is written on a file named ___.dump; otherwise it is directed to stdout. @@ -339,10 +356,11 @@ commas. For example: case "dump": alldump = val != 0 if alldump { - BuildDump = valString + BuildDump[valString] = true + GenssaDump[valString] = true } default: - return fmt.Sprintf("Did not find a flag matching %s in -d=ssa/%s debug option", flag, phase) + return fmt.Sprintf("Did not find a flag matching %s in -d=ssa/%s debug option (expected ssa/all/{time,mem,dump=function_name})", flag, phase) } } @@ -355,7 +373,7 @@ commas. For example: case "debug": IntrinsicsDebug = val default: - return fmt.Sprintf("Did not find a flag matching %s in -d=ssa/%s debug option", flag, phase) + return fmt.Sprintf("Did not find a flag matching %s in -d=ssa/%s debug option (expected ssa/intrinsics/{on,off,debug})", flag, phase) } return "" } @@ -368,9 +386,18 @@ commas. For example: case "stats": BuildStats = val case "dump": - BuildDump = valString + BuildDump[valString] = true + default: + return fmt.Sprintf("Did not find a flag matching %s in -d=ssa/%s debug option (expected ssa/build/{debug,test,stats,dump=function_name})", flag, phase) + } + return "" + } + if phase == "genssa" { + switch flag { + case "dump": + GenssaDump[valString] = true default: - return fmt.Sprintf("Did not find a flag matching %s in -d=ssa/%s debug option", flag, phase) + return fmt.Sprintf("Did not find a flag matching %s in -d=ssa/%s debug option (expected ssa/genssa/dump=function_name)", flag, phase) } return "" } diff --git a/src/cmd/compile/internal/ssa/debug_lines_test.go b/src/cmd/compile/internal/ssa/debug_lines_test.go new file mode 100644 index 0000000000..c5a0fe449c --- /dev/null +++ b/src/cmd/compile/internal/ssa/debug_lines_test.go @@ -0,0 +1,213 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ssa_test + +import ( + "bufio" + "bytes" + "flag" + "runtime" + "sort" + + // "flag" + "fmt" + "internal/testenv" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "reflect" + "regexp" + "strconv" + "testing" +) + +// Matches lines in genssa output that are marked "isstmt", and the parenthesized plus-prefixed line number is a submatch +var asmLine *regexp.Regexp = regexp.MustCompile(`^\s[vb][0-9]+\s+[0-9]+\s\(\+([0-9]+)\)`) + +// this matches e.g. ` v123456789 000007 (+9876654310) MOVUPS X15, ""..autotmp_2-32(SP)` + +// Matches lines in genssa output that describe an inlined file (on a Unix filesystem). Note it expects an unadventurous choice of basename. +var inlineLine *regexp.Regexp = regexp.MustCompile(`^#\s/.*/[-a-zA-Z0-9_]+\.go:([0-9]+)`) + +// this matches e.g. # /pa/inline-dumpxxxx.go:6 + +var testGoArchFlag = flag.String("arch", "", "run test for specified architecture") + +func testGoArch() string { + if *testGoArchFlag == "" { + return runtime.GOARCH + } + return *testGoArchFlag +} + +func TestDebugLines(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("Windows lacks $HOME which complicates workaround for 'missing $GOPATH'") // $HOME needed to work around #43938 + } + // This test is potentially fragile, the goal is that debugging should step properly through "sayhi" + // If the blocks are reordered in a way that changes the statement order but execution flows correctly, + // then rearrange the expected numbers. Register abi and not-register-abi also have different sequences, + // at least for now. + + switch testGoArch() { + case "arm64", "amd64": // register ABI + testDebugLines(t, "sayhi.go", "sayhi", []int{8, 9, 10, 11}) + + case "arm", "386": // probably not register ABI for a while + testDebugLines(t, "sayhi.go", "sayhi", []int{9, 10, 11}) + + default: // expect ppc64le and riscv will pick up register ABI soonish, not sure about others + t.Skip("skipped for many architectures, also changes w/ register ABI") + } +} + +func TestInlineLines(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("Windows lacks $HOME which complicates workaround for 'missing $GOPATH'") // $HOME needed to work around #43938 + } + if runtime.GOARCH != "amd64" && *testGoArchFlag == "" { + // As of september 2021, works for everything except mips64, but still potentially fragile + t.Skip("only runs for amd64 unless -arch explicitly supplied") + } + + want := [][]int{{3}, {4, 10}, {4, 10, 16}, {4, 10}, {4, 11, 16}, {4, 11}, {4}, {5, 10}, {5, 10, 16}, {5, 10}, {5, 11, 16}, {5, 11}, {5}} + testInlineStack(t, "inline-dump.go", "f", want) +} + +func compileAndDump(t *testing.T, file, function, moreGCFlags string) []byte { + testenv.MustHaveGoBuild(t) + + tmpdir, err := ioutil.TempDir("", "debug_lines_test") + if err != nil { + panic(fmt.Sprintf("Problem creating TempDir, error %v", err)) + } + if testing.Verbose() { + fmt.Printf("Preserving temporary directory %s\n", tmpdir) + } else { + defer os.RemoveAll(tmpdir) + } + + source, err := filepath.Abs(filepath.Join("testdata", file)) + if err != nil { + panic(fmt.Sprintf("Could not get abspath of testdata directory and file, %v", err)) + } + + cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", "foo.o", "-gcflags=-d=ssa/genssa/dump="+function+" "+moreGCFlags, source) + cmd.Dir = tmpdir + cmd.Env = replaceEnv(cmd.Env, "GOSSADIR", tmpdir) + cmd.Env = replaceEnv(cmd.Env, "HOME", os.Getenv("HOME")) // workaround for #43938 + testGoos := "linux" // default to linux + if testGoArch() == "wasm" { + testGoos = "js" + } + cmd.Env = replaceEnv(cmd.Env, "GOOS", testGoos) + cmd.Env = replaceEnv(cmd.Env, "GOARCH", testGoArch()) + + if testing.Verbose() { + fmt.Printf("About to run %s\n", asCommandLine("", cmd)) + } + + var stdout, stderr bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stderr + + if err := cmd.Run(); err != nil { + t.Fatalf("error running cmd %s: %v\nstdout:\n%sstderr:\n%s\n", asCommandLine("", cmd), err, stdout.String(), stderr.String()) + } + + if s := stderr.String(); s != "" { + t.Fatalf("Wanted empty stderr, instead got:\n%s\n", s) + } + + dumpFile := filepath.Join(tmpdir, function+"_01__genssa.dump") + dumpBytes, err := os.ReadFile(dumpFile) + if err != nil { + t.Fatalf("Could not read dump file %s, err=%v", dumpFile, err) + } + return dumpBytes +} + +func sortInlineStacks(x [][]int) { + sort.Slice(x, func(i, j int) bool { + if len(x[i]) != len(x[j]) { + return len(x[i]) < len(x[j]) + } + for k := range x[i] { + if x[i][k] != x[j][k] { + return x[i][k] < x[j][k] + } + } + return false + }) +} + +// testInlineStack ensures that inlining is described properly in the comments in the dump file +func testInlineStack(t *testing.T, file, function string, wantStacks [][]int) { + // this is an inlining reporting test, not an optimization test. -N makes it less fragile + dumpBytes := compileAndDump(t, file, function, "-N") + dump := bufio.NewScanner(bytes.NewReader(dumpBytes)) + dumpLineNum := 0 + var gotStmts []int + var gotStacks [][]int + for dump.Scan() { + line := dump.Text() + dumpLineNum++ + matches := inlineLine.FindStringSubmatch(line) + if len(matches) == 2 { + stmt, err := strconv.ParseInt(matches[1], 10, 32) + if err != nil { + t.Fatalf("Expected to parse a line number but saw %s instead on dump line #%d, error %v", matches[1], dumpLineNum, err) + } + if testing.Verbose() { + fmt.Printf("Saw stmt# %d for submatch '%s' on dump line #%d = '%s'\n", stmt, matches[1], dumpLineNum, line) + } + gotStmts = append(gotStmts, int(stmt)) + } else if len(gotStmts) > 0 { + gotStacks = append(gotStacks, gotStmts) + gotStmts = nil + } + } + if len(gotStmts) > 0 { + gotStacks = append(gotStacks, gotStmts) + gotStmts = nil + } + sortInlineStacks(gotStacks) + sortInlineStacks(wantStacks) + if !reflect.DeepEqual(wantStacks, gotStacks) { + t.Errorf("wanted inlines %+v but got %+v", wantStacks, gotStacks) + } + +} + +// testDebugLines compiles testdata/ with flags -N -l and -d=ssa/genssa/dump= +// then verifies that the statement-marked lines in that file are the same as those in wantStmts +// These files must all be short because this is super-fragile. +// "go build" is run in a temporary directory that is normally deleted, unless -test.v +func testDebugLines(t *testing.T, file, function string, wantStmts []int) { + dumpBytes := compileAndDump(t, file, function, "-N -l") + dump := bufio.NewScanner(bytes.NewReader(dumpBytes)) + var gotStmts []int + dumpLineNum := 0 + for dump.Scan() { + line := dump.Text() + dumpLineNum++ + matches := asmLine.FindStringSubmatch(line) + if len(matches) == 2 { + stmt, err := strconv.ParseInt(matches[1], 10, 32) + if err != nil { + t.Fatalf("Expected to parse a line number but saw %s instead on dump line #%d, error %v", matches[1], dumpLineNum, err) + } + if testing.Verbose() { + fmt.Printf("Saw stmt# %d for submatch '%s' on dump line #%d = '%s'\n", stmt, matches[1], dumpLineNum, line) + } + gotStmts = append(gotStmts, int(stmt)) + } + } + if !reflect.DeepEqual(wantStmts, gotStmts) { + t.Errorf("wanted stmts %v but got %v", wantStmts, gotStmts) + } + +} diff --git a/src/cmd/compile/internal/ssa/func.go b/src/cmd/compile/internal/ssa/func.go index fac876c23e..7728a395e0 100644 --- a/src/cmd/compile/internal/ssa/func.go +++ b/src/cmd/compile/internal/ssa/func.go @@ -43,7 +43,7 @@ type Func struct { logfiles map[string]writeSyncer HTMLWriter *HTMLWriter // html writer, for debugging DebugTest bool // default true unless $GOSSAHASH != ""; as a debugging aid, make new code conditional on this and use GOSSAHASH to binary search for failing cases - PrintOrHtmlSSA bool // true if GOSSAFUNC matches, true even if fe.Log() (spew phase results to stdout) is false. + PrintOrHtmlSSA bool // true if GOSSAFUNC matches, true even if fe.Log() (spew phase results to stdout) is false. There's an odd dependence on this in debug.go for method logf. ruleMatches map[string]int // number of times countRule was called during compilation for any given string ABI0 *abi.ABIConfig // A copy, for no-sync access ABI1 *abi.ABIConfig // A copy, for no-sync access diff --git a/src/cmd/compile/internal/ssa/print.go b/src/cmd/compile/internal/ssa/print.go index 81c64a7692..96cd2c7c90 100644 --- a/src/cmd/compile/internal/ssa/print.go +++ b/src/cmd/compile/internal/ssa/print.go @@ -6,6 +6,7 @@ package ssa import ( "bytes" + "cmd/internal/src" "crypto/sha256" "fmt" "io" @@ -83,13 +84,26 @@ func (p stringFuncPrinter) endBlock(b *Block, reachable bool) { fmt.Fprintln(p.w, " "+b.LongString()) } +func StmtString(p src.XPos) string { + linenumber := "(?) " + if p.IsKnown() { + pfx := "" + if p.IsStmt() == src.PosIsStmt { + pfx = "+" + } + if p.IsStmt() == src.PosNotStmt { + pfx = "-" + } + linenumber = fmt.Sprintf("(%s%d) ", pfx, p.Line()) + } + return linenumber +} + func (p stringFuncPrinter) value(v *Value, live bool) { if !p.printDead && !live { return } - fmt.Fprint(p.w, " ") - //fmt.Fprint(p.w, v.Block.Func.fe.Pos(v.Pos)) - //fmt.Fprint(p.w, ": ") + fmt.Fprintf(p.w, " %s", StmtString(v.Pos)) fmt.Fprint(p.w, v.LongString()) if !live { fmt.Fprint(p.w, " DEAD") diff --git a/src/cmd/compile/internal/ssa/testdata/inline-dump.go b/src/cmd/compile/internal/ssa/testdata/inline-dump.go new file mode 100644 index 0000000000..97893b6f21 --- /dev/null +++ b/src/cmd/compile/internal/ssa/testdata/inline-dump.go @@ -0,0 +1,17 @@ +package foo + +func f(m, n int) int { + a := g(n) + b := g(m) + return a + b +} + +func g(x int) int { + y := h(x + 1) + z := h(x - 1) + return y + z +} + +func h(x int) int { + return x * x +} diff --git a/src/cmd/compile/internal/ssa/testdata/sayhi.go b/src/cmd/compile/internal/ssa/testdata/sayhi.go new file mode 100644 index 0000000000..680e1eb3a1 --- /dev/null +++ b/src/cmd/compile/internal/ssa/testdata/sayhi.go @@ -0,0 +1,12 @@ +package foo + +import ( + "fmt" + "sync" +) + +func sayhi(n int, wg *sync.WaitGroup) { + fmt.Println("hi", n) + fmt.Println("hi", n) + wg.Done() +} diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 08f36ce7be..82d232f940 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -6703,7 +6703,8 @@ func genssa(f *ssa.Func, pp *objw.Progs) { var progToValue map[*obj.Prog]*ssa.Value var progToBlock map[*obj.Prog]*ssa.Block var valueToProgAfter []*obj.Prog // The first Prog following computation of a value v; v is visible at this point. - if f.PrintOrHtmlSSA { + gatherPrintInfo := f.PrintOrHtmlSSA || ssa.GenssaDump[f.Name] + if gatherPrintInfo { progToValue = make(map[*obj.Prog]*ssa.Value, f.NumValues()) progToBlock = make(map[*obj.Prog]*ssa.Block, f.NumBlocks()) f.Logf("genssa %s\n", f.Name) @@ -6814,7 +6815,7 @@ func genssa(f *ssa.Func, pp *objw.Progs) { valueToProgAfter[v.ID] = s.pp.Next } - if f.PrintOrHtmlSSA { + if gatherPrintInfo { for ; x != s.pp.Next; x = x.Link { progToValue[x] = v } @@ -6844,7 +6845,7 @@ func genssa(f *ssa.Func, pp *objw.Progs) { x := s.pp.Next s.SetPos(b.Pos) Arch.SSAGenBlock(&s, b, next) - if f.PrintOrHtmlSSA { + if gatherPrintInfo { for ; x != s.pp.Next; x = x.Link { progToBlock[x] = b } @@ -7023,6 +7024,54 @@ func genssa(f *ssa.Func, pp *objw.Progs) { buf.WriteString("") f.HTMLWriter.WriteColumn("genssa", "genssa", "ssa-prog", buf.String()) } + if ssa.GenssaDump[f.Name] { + fi := f.DumpFileForPhase("genssa") + if fi != nil { + + // inliningDiffers if any filename changes or if any line number except the innermost (index 0) changes. + inliningDiffers := func(a, b []src.Pos) bool { + if len(a) != len(b) { + return true + } + for i := range a { + if a[i].Filename() != b[i].Filename() { + return true + } + if i > 0 && a[i].Line() != b[i].Line() { + return true + } + } + return false + } + + var allPosOld []src.Pos + var allPos []src.Pos + + for p := pp.Text; p != nil; p = p.Link { + if p.Pos.IsKnown() { + allPos = p.AllPos(allPos) + if inliningDiffers(allPos, allPosOld) { + for i := len(allPos) - 1; i >= 0; i-- { + pos := allPos[i] + fmt.Fprintf(fi, "# %s:%d\n", pos.Filename(), pos.Line()) + } + allPos, allPosOld = allPosOld, allPos // swap, not copy, so that they do not share slice storage. + } + } + + var s string + if v, ok := progToValue[p]; ok { + s = v.String() + } else if b, ok := progToBlock[p]; ok { + s = b.String() + } else { + s = " " // most value and branch strings are 2-3 characters long + } + fmt.Fprintf(fi, " %-6s\t%.5d %s\t%s\n", s, p.Pc, ssa.StmtString(p.Pos), p.InstructionString()) + } + fi.Close() + } + } defframe(&s, e, f) diff --git a/src/cmd/internal/obj/util.go b/src/cmd/internal/obj/util.go index e8441a6969..0c9dde7965 100644 --- a/src/cmd/internal/obj/util.go +++ b/src/cmd/internal/obj/util.go @@ -7,6 +7,7 @@ package obj import ( "bytes" "cmd/internal/objabi" + "cmd/internal/src" "fmt" "internal/buildcfg" "io" @@ -47,6 +48,10 @@ func (p *Prog) InnermostFilename() string { return pos.Filename() } +func (p *Prog) AllPos(result []src.Pos) []src.Pos { + return p.Ctxt.AllPos(p.Pos, result) +} + var armCondCode = []string{ ".EQ", ".NE", -- GitLab From b0fa2f5b09acfa5604e78cafc2183f3e1eac061b Mon Sep 17 00:00:00 2001 From: Amelia Downs Date: Mon, 20 Sep 2021 13:04:49 -0400 Subject: [PATCH 1218/2500] cmd/compile: fix ExampleInfo output Move the "TODO" to outside of the function so that the "Output" comment block is the last comment block. Output is only checked when it is the last comment block. See golang/go#48362 for this issue. Fixes: golang/go#48494 Change-Id: I7a31d7c13710e58fa876c96240a927a9bb8273ad Reviewed-on: https://go-review.googlesource.com/c/go/+/350995 Run-TryBot: Robert Griesemer Reviewed-by: Robert Griesemer Trust: David Chase --- .../compile/internal/types2/example_test.go | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/cmd/compile/internal/types2/example_test.go b/src/cmd/compile/internal/types2/example_test.go index 714bf77821..4edaad580e 100644 --- a/src/cmd/compile/internal/types2/example_test.go +++ b/src/cmd/compile/internal/types2/example_test.go @@ -216,36 +216,36 @@ func fib(x int) int { // var x int: // defined at fib.go:8:10 // used at 10:10, 12:13, 12:24, 9:5 - - // TODO(gri) Enable once positions are updated/verified - // Types and Values of each expression: - // 4: 8 | string | type : string - // 6:15 | len | builtin : func(string) int - // 6:15 | len(b) | value : int - // 6:19 | b | var : fib.S - // 6:23 | S | type : fib.S - // 6:23 | S(c) | value : fib.S - // 6:25 | c | var : string - // 6:29 | "hello" | value : string = "hello" - // 8:12 | int | type : int - // 8:17 | int | type : int - // 9: 5 | x | var : int - // 9: 5 | x < 2 | value : untyped bool - // 9: 9 | 2 | value : int = 2 - // 10:10 | x | var : int - // 12: 9 | fib | value : func(x int) int - // 12: 9 | fib(x - 1) | value : int - // 12: 9 | fib(x - 1) - fib(x - 2) | value : int - // 12:13 | x | var : int - // 12:13 | x - 1 | value : int - // 12:15 | 1 | value : int = 1 - // 12:20 | fib | value : func(x int) int - // 12:20 | fib(x - 2) | value : int - // 12:24 | x | var : int - // 12:24 | x - 2 | value : int - // 12:26 | 2 | value : int = 2 } +// TODO(gri) Enable once positions are updated/verified +// Types and Values of each expression: +// 4: 8 | string | type : string +// 6:15 | len | builtin : func(string) int +// 6:15 | len(b) | value : int +// 6:19 | b | var : fib.S +// 6:23 | S | type : fib.S +// 6:23 | S(c) | value : fib.S +// 6:25 | c | var : string +// 6:29 | "hello" | value : string = "hello" +// 8:12 | int | type : int +// 8:17 | int | type : int +// 9: 5 | x | var : int +// 9: 5 | x < 2 | value : untyped bool +// 9: 9 | 2 | value : int = 2 +// 10:10 | x | var : int +// 12: 9 | fib | value : func(x int) int +// 12: 9 | fib(x - 1) | value : int +// 12: 9 | fib(x - 1) - fib(x - 2) | value : int +// 12:13 | x | var : int +// 12:13 | x - 1 | value : int +// 12:15 | 1 | value : int = 1 +// 12:20 | fib | value : func(x int) int +// 12:20 | fib(x - 2) | value : int +// 12:24 | x | var : int +// 12:24 | x - 2 | value : int +// 12:26 | 2 | value : int = 2 + func mode(tv types2.TypeAndValue) string { switch { case tv.IsVoid(): -- GitLab From ba1c52d7d77724de4407572bd02421c36df3d78a Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 17 Sep 2021 12:27:23 -0700 Subject: [PATCH 1219/2500] text/template: initialize template before locking it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For #39807 Fixes #48436 Change-Id: I75f82fd8738dd2f11f0c69b1230e1be1abc36024 Reviewed-on: https://go-review.googlesource.com/c/go/+/350730 Trust: Ian Lance Taylor Trust: Daniel Martí Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Daniel Martí --- src/text/template/multi_test.go | 10 ++++++++++ src/text/template/template.go | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/text/template/multi_test.go b/src/text/template/multi_test.go index b543ab5c47..6b81ffe7ac 100644 --- a/src/text/template/multi_test.go +++ b/src/text/template/multi_test.go @@ -452,3 +452,13 @@ func TestIssue19294(t *testing.T) { } } } + +// Issue 48436 +func TestAddToZeroTemplate(t *testing.T) { + tree, err := parse.Parse("c", cloneText3, "", "", nil, builtins()) + if err != nil { + t.Fatal(err) + } + var tmpl Template + tmpl.AddParseTree("x", tree["c"]) +} diff --git a/src/text/template/template.go b/src/text/template/template.go index fd74d45e9b..776be9cd07 100644 --- a/src/text/template/template.go +++ b/src/text/template/template.go @@ -127,9 +127,9 @@ func (t *Template) copy(c *common) *Template { // its definition. If it has been defined and already has that name, the existing // definition is replaced; otherwise a new template is created, defined, and returned. func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) { + t.init() t.muTmpl.Lock() defer t.muTmpl.Unlock() - t.init() nt := t if name != t.name { nt = t.New(name) -- GitLab From d7e3e442febea1d4ba7b6b456f46b2fd9c3b69e6 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 20 Sep 2021 14:59:54 -0700 Subject: [PATCH 1220/2500] internal/buildcfg: fix test for GOAMD64=v3 ./all.bash If GOAMD64 is set to a bogus value, goamd64() will return the default value, which may not necessarily be 1. Instead, just test that it sets Error. Change-Id: Ibbc26608c1ae24e645c7753ef5765b9c2fdc089e Reviewed-on: https://go-review.googlesource.com/c/go/+/351129 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/internal/buildcfg/cfg_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/internal/buildcfg/cfg_test.go b/src/internal/buildcfg/cfg_test.go index 9180441c28..0123593317 100644 --- a/src/internal/buildcfg/cfg_test.go +++ b/src/internal/buildcfg/cfg_test.go @@ -18,8 +18,9 @@ func TestConfigFlags(t *testing.T) { if goamd64() != 4 { t.Errorf("Wrong parsing of GOAMD64=v4") } + Error = nil os.Setenv("GOAMD64", "1") - if goamd64() != 1 { + if goamd64(); Error == nil { t.Errorf("Wrong parsing of GOAMD64=1") } } -- GitLab From 2f87b9c942366ddf38f49d34671252663fca7889 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 20 Sep 2021 17:08:11 -0700 Subject: [PATCH 1221/2500] go/types, types2: remove duplicate resolve call Change-Id: I8afe8bf6304b6a3645bbd8d4d19f152862c58725 Reviewed-on: https://go-review.googlesource.com/c/go/+/351119 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley TryBot-Result: Go Bot --- src/cmd/compile/internal/types2/subst.go | 1 - src/go/types/subst.go | 1 - 2 files changed, 2 deletions(-) diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 87c1d7872b..fe73ef688c 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -224,7 +224,6 @@ func (subst *subster) typ(typ Type) Type { return named } - t.orig.resolve(subst.env) // Create a new instance and populate the environment to avoid endless // recursion. The position used here is irrelevant because validation only // occurs on t (we don't call validType on named), but we use subst.pos to diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 16aafd622e..999099572c 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -210,7 +210,6 @@ func (subst *subster) typ(typ Type) Type { return named } - t.orig.resolve(subst.env) // Create a new instance and populate the environment to avoid endless // recursion. The position used here is irrelevant because validation only // occurs on t (we don't call validType on named), but we use subst.pos to -- GitLab From d1fd3eb40e5facd6d056b377a5286b8b3891afd0 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 14 Sep 2021 17:25:00 -0700 Subject: [PATCH 1222/2500] cmd/compile/internal/types2: instantiate methods when instantiating Named types This is a port of CL 349412 from go/types to types2 with minor adjustments for types2 names, plus CL 350143 (slightly simplified) to make sure we always get a new signature in instantiated methods, plus CL 350810 to take care of pointer receivers. It also contains adjustments to the compiler (provided by Dan Scales) make it work with the types2 changes. Change-Id: Ia683a3a8adba3c369701c411d786092f02e77efe Reviewed-on: https://go-review.googlesource.com/c/go/+/349998 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/noder/types.go | 9 +- src/cmd/compile/internal/types2/call.go | 51 ----------- src/cmd/compile/internal/types2/decl.go | 6 ++ src/cmd/compile/internal/types2/infer.go | 1 + .../internal/types2/instantiate_test.go | 82 +++++++++++++++++ src/cmd/compile/internal/types2/lookup.go | 22 ----- src/cmd/compile/internal/types2/named.go | 91 ++++++++++++++++--- src/cmd/compile/internal/types2/object.go | 5 +- .../compile/internal/types2/sizeof_test.go | 2 +- src/cmd/compile/internal/types2/subst.go | 3 +- 10 files changed, 182 insertions(+), 90 deletions(-) diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index 03fb96c48b..99917ad974 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -42,7 +42,9 @@ func (g *irgen) typ(typ types2.Type) *types.Type { l := len(g.typesToFinalize) info := g.typesToFinalize[l-1] g.typesToFinalize = g.typesToFinalize[:l-1] + types.DeferCheckSize() g.fillinMethods(info.typ, info.ntyp) + types.ResumeCheckSize() } return res } @@ -283,15 +285,20 @@ func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) { m := typ.Method(i) recvType := deref2(types2.AsSignature(m.Type()).Recv().Type()) var meth *ir.Name + imported := false if m.Pkg() != g.self { // Imported methods cannot be loaded by name (what // g.obj() does) - they must be loaded via their // type. meth = g.obj(recvType.(*types2.Named).Obj()).Type().Methods().Index(i).Nname.(*ir.Name) + // XXX Because Obj() returns the object of the base generic + // type, we have to still do the method translation below. + imported = true } else { meth = g.obj(m) } - if recvType != types2.Type(typ) { + assert(recvType == types2.Type(typ)) + if imported { // Unfortunately, meth is the type of the method of the // generic type, so we have to do a substitution to get // the name/type of the method of the instantiated type, diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index ba3bb475a3..0480b7bef4 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -528,58 +528,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) { // methods may not have a fully set up signature yet if m, _ := obj.(*Func); m != nil { - // check.dump("### found method %s", m) check.objDecl(m, nil) - // If m has a parameterized receiver type, infer the type arguments from - // the actual receiver provided and then substitute the type parameters in - // the signature accordingly. - // TODO(gri) factor this code out - sig := m.typ.(*Signature) - if sig.RecvTypeParams().Len() > 0 { - // For inference to work, we must use the receiver type - // matching the receiver in the actual method declaration. - // If the method is embedded, the matching receiver is the - // embedded struct or interface that declared the method. - // Traverse the embedding to find that type (issue #44688). - recv := x.typ - for i := 0; i < len(index)-1; i++ { - // The embedded type is either a struct or a pointer to - // a struct except for the last one (which we don't need). - recv = asStruct(derefStructPtr(recv)).Field(index[i]).typ - } - //check.dump("### recv = %s", recv) - //check.dump("### method = %s rparams = %s tparams = %s", m, sig.rparams, sig.tparams) - // The method may have a pointer receiver, but the actually provided receiver - // may be a (hopefully addressable) non-pointer value, or vice versa. Here we - // only care about inferring receiver type parameters; to make the inference - // work, match up pointer-ness of receiver and argument. - if ptrRecv := isPointer(sig.recv.typ); ptrRecv != isPointer(recv) { - if ptrRecv { - recv = NewPointer(recv) - } else { - recv = recv.(*Pointer).base - } - } - // Disable reporting of errors during inference below. If we're unable to infer - // the receiver type arguments here, the receiver must be be otherwise invalid - // and an error has been reported elsewhere. - arg := operand{mode: variable, expr: x.expr, typ: recv} - targs := check.infer(m.pos, sig.RecvTypeParams().list(), nil, NewTuple(sig.recv), []*operand{&arg}, false /* no error reporting */) - //check.dump("### inferred targs = %s", targs) - if targs == nil { - // We may reach here if there were other errors (see issue #40056). - goto Error - } - // Don't modify m. Instead - for now - make a copy of m and use that instead. - // (If we modify m, some tests will fail; possibly because the m is in use.) - // TODO(gri) investigate and provide a correct explanation here - copy := *m - copy.typ = check.subst(e.Pos(), m.typ, makeSubstMap(sig.RecvTypeParams().list(), targs), nil) - obj = © - } - // TODO(gri) we also need to do substitution for parameterized interface methods - // (this breaks code in testdata/linalg.go2 at the moment) - // 12/20/2019: Is this TODO still correct? } if x.mode == typexpr { diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 26e050511e..1926d93a86 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -66,6 +66,12 @@ func (check *Checker) objDecl(obj Object, def *Named) { }() } + // Funcs with m.instRecv set have not yet be completed. Complete them now + // so that they have a type when objDecl exits. + if m, _ := obj.(*Func); m != nil && m.instRecv != nil { + check.completeMethod(check.conf.Environment, m) + } + // Checking the declaration of obj means inferring its type // (and possibly its value, for constants). // An object's type (and thus the object) may be in one of diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index c2a8155dc7..b98c8211df 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -29,6 +29,7 @@ const useConstraintTypeInference = true // // Constraint type inference is used after each step to expand the set of type arguments. // +// TODO(gri): remove the report parameter: is no longer needed. func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, params *Tuple, args []*operand, report bool) (result []Type) { if debug { defer func() { diff --git a/src/cmd/compile/internal/types2/instantiate_test.go b/src/cmd/compile/internal/types2/instantiate_test.go index 69a26491cb..5d37f29b6b 100644 --- a/src/cmd/compile/internal/types2/instantiate_test.go +++ b/src/cmd/compile/internal/types2/instantiate_test.go @@ -5,6 +5,7 @@ package types2_test import ( . "cmd/compile/internal/types2" + "strings" "testing" ) @@ -60,3 +61,84 @@ func TestInstantiateNonEquality(t *testing.T) { t.Errorf("instance from pkg1 (%s) is identical to instance from pkg2 (%s)", res1, res2) } } + +func TestMethodInstantiation(t *testing.T) { + const prefix = genericPkg + `p + +type T[P any] struct{} + +var X T[int] + +` + tests := []struct { + decl string + want string + }{ + {"func (r T[P]) m() P", "func (T[int]).m() int"}, + {"func (r T[P]) m(P)", "func (T[int]).m(int)"}, + {"func (r *T[P]) m(P)", "func (*T[int]).m(int)"}, + {"func (r T[P]) m() T[P]", "func (T[int]).m() T[int]"}, + {"func (r T[P]) m(T[P])", "func (T[int]).m(T[int])"}, + {"func (r T[P]) m(T[P], P, string)", "func (T[int]).m(T[int], int, string)"}, + {"func (r T[P]) m(T[P], T[string], T[int])", "func (T[int]).m(T[int], T[string], T[int])"}, + } + + for _, test := range tests { + src := prefix + test.decl + pkg, err := pkgFor(".", src, nil) + if err != nil { + t.Fatal(err) + } + typ := NewPointer(pkg.Scope().Lookup("X").Type()) + obj, _, _ := LookupFieldOrMethod(typ, false, pkg, "m") + m, _ := obj.(*Func) + if m == nil { + t.Fatalf(`LookupFieldOrMethod(%s, "m") = %v, want func m`, typ, obj) + } + if got := ObjectString(m, RelativeTo(pkg)); got != test.want { + t.Errorf("instantiated %q, want %q", got, test.want) + } + } +} + +func TestImmutableSignatures(t *testing.T) { + const src = genericPkg + `p + +type T[P any] struct{} + +func (T[P]) m() {} + +var _ T[int] +` + pkg, err := pkgFor(".", src, nil) + if err != nil { + t.Fatal(err) + } + typ := pkg.Scope().Lookup("T").Type().(*Named) + obj, _, _ := LookupFieldOrMethod(typ, false, pkg, "m") + if obj == nil { + t.Fatalf(`LookupFieldOrMethod(%s, "m") = %v, want func m`, typ, obj) + } + + // Verify that the original method is not mutated by instantiating T (this + // bug manifested when subst did not return a new signature). + want := "func (T[P]).m()" + if got := stripAnnotations(ObjectString(obj, RelativeTo(pkg))); got != want { + t.Errorf("instantiated %q, want %q", got, want) + } +} + +// Copied from errors.go. +func stripAnnotations(s string) string { + var b strings.Builder + for _, r := range s { + // strip #'s and subscript digits + if r < '₀' || '₀'+10 <= r { // '₀' == U+2080 + b.WriteRune(r) + } + } + if b.Len() < len(s) { + return b.String() + } + return s +} diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index 0e7a2b70e2..eb460ca200 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -344,8 +344,6 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, } // A concrete type implements T if it implements all methods of T. - Vd, _ := deref(V) - Vn := asNamed(Vd) for _, m := range T.typeSet().methods { // TODO(gri) should this be calling lookupFieldOrMethod instead (and why not)? obj, _, _ := lookupFieldOrMethod(V, false, m.pkg, m.name) @@ -380,26 +378,6 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, panic("method with type parameters") } - // If V is a (instantiated) generic type, its methods are still - // parameterized using the original (declaration) receiver type - // parameters (subst simply copies the existing method list, it - // does not instantiate the methods). - // In order to compare the signatures, substitute the receiver - // type parameters of ftyp with V's instantiation type arguments. - // This lazily instantiates the signature of method f. - if Vn != nil && Vn.TypeParams().Len() > 0 { - // Be careful: The number of type arguments may not match - // the number of receiver parameters. If so, an error was - // reported earlier but the length discrepancy is still - // here. Exit early in this case to prevent an assertion - // failure in makeSubstMap. - // TODO(gri) Can we avoid this check by fixing the lengths? - if len(ftyp.RecvTypeParams().list()) != Vn.targs.Len() { - return - } - ftyp = check.subst(nopos, ftyp, makeSubstMap(ftyp.RecvTypeParams().list(), Vn.targs.list()), nil).(*Signature) - } - // If the methods have type parameters we don't care whether they // are the same or not, as long as they match up. Use unification // to see if they can be made to match. diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index c844012e39..7fc84004e3 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -221,16 +221,17 @@ func (n *Named) setUnderlying(typ Type) { // expandNamed ensures that the underlying type of n is instantiated. // The underlying type will be Typ[Invalid] if there was an error. -func expandNamed(env *Environment, n *Named, instPos syntax.Pos) (*TypeParamList, Type, []*Func) { +func expandNamed(env *Environment, n *Named, instPos syntax.Pos) (tparams *TypeParamList, underlying Type, methods []*Func) { n.orig.resolve(env) - var u Type - if n.check.validateTArgLen(instPos, n.orig.tparams.Len(), n.targs.Len()) { + check := n.check + + if check.validateTArgLen(instPos, n.orig.tparams.Len(), n.targs.Len()) { // TODO(rfindley): handling an optional Checker and Environment here (and // in subst) feels overly complicated. Can we simplify? if env == nil { - if n.check != nil { - env = n.check.conf.Environment + if check != nil { + env = check.conf.Environment } else { // If we're instantiating lazily, we might be outside the scope of a // type-checking pass. In that case we won't have a pre-existing @@ -239,16 +240,84 @@ func expandNamed(env *Environment, n *Named, instPos syntax.Pos) (*TypeParamList env = NewEnvironment() } h := env.TypeHash(n.orig, n.targs.list()) - // add the instance to the environment to avoid infinite recursion. - // addInstance may return a different, existing instance, but we - // shouldn't return that instance from expand. + // ensure that an instance is recorded for h to avoid infinite recursion. env.typeForHash(h, n) } - u = n.check.subst(instPos, n.orig.underlying, makeSubstMap(n.orig.tparams.list(), n.targs.list()), env) + smap := makeSubstMap(n.orig.tparams.list(), n.targs.list()) + underlying = n.check.subst(instPos, n.orig.underlying, smap, env) + for i := 0; i < n.orig.NumMethods(); i++ { + origm := n.orig.Method(i) + + // During type checking origm may not have a fully set up type, so defer + // instantiation of its signature until later. + m := NewFunc(origm.pos, origm.pkg, origm.name, nil) + m.hasPtrRecv = ptrRecv(origm) + // Setting instRecv here allows us to complete later (we need the + // instRecv to get targs and the original method). + m.instRecv = n + + methods = append(methods, m) + } + } else { + underlying = Typ[Invalid] + } + + // Methods should not escape the type checker API without being completed. If + // we're in the context of a type checking pass, we need to defer this until + // later (not all methods may have types). + completeMethods := func() { + for _, m := range methods { + if m.instRecv != nil { + check.completeMethod(env, m) + } + } + } + if check != nil { + check.later(completeMethods) + } else { + completeMethods() + } + + return n.orig.tparams, underlying, methods +} + +func (check *Checker) completeMethod(env *Environment, m *Func) { + assert(m.instRecv != nil) + rbase := m.instRecv + m.instRecv = nil + m.setColor(black) + + assert(rbase.TypeArgs().Len() > 0) + + // Look up the original method. + _, orig := lookupMethod(rbase.orig.methods, rbase.obj.pkg, m.name) + assert(orig != nil) + if check != nil { + check.objDecl(orig, nil) + } + origSig := orig.typ.(*Signature) + if origSig.RecvTypeParams().Len() != rbase.targs.Len() { + m.typ = origSig // or new(Signature), but we can't use Typ[Invalid]: Funcs must have Signature type + return // error reported elsewhere + } + + smap := makeSubstMap(origSig.RecvTypeParams().list(), rbase.targs.list()) + sig := check.subst(orig.pos, origSig, smap, env).(*Signature) + if sig == origSig { + // No substitution occurred, but we still need to create a new signature to + // hold the instantiated receiver. + copy := *origSig + sig = © + } + var rtyp Type + if ptrRecv(m) { + rtyp = NewPointer(rbase) } else { - u = Typ[Invalid] + rtyp = rbase } - return n.orig.tparams, u, n.orig.methods + sig.recv = NewParam(origSig.recv.pos, origSig.recv.pkg, origSig.recv.name, rtyp) + + m.typ = sig } // safeUnderlying returns the underlying of typ without expanding instances, to diff --git a/src/cmd/compile/internal/types2/object.go b/src/cmd/compile/internal/types2/object.go index 540cb3f44f..f44e1a9353 100644 --- a/src/cmd/compile/internal/types2/object.go +++ b/src/cmd/compile/internal/types2/object.go @@ -363,7 +363,8 @@ func (*Var) isDependency() {} // a variable may be a dependency of an initializa // An abstract method may belong to many interfaces due to embedding. type Func struct { object - hasPtrRecv bool // only valid for methods that don't have a type yet + instRecv *Named // if non-nil, the receiver type for an incomplete instance method + hasPtrRecv bool // only valid for methods that don't have a type yet } // NewFunc returns a new function with the given signature, representing @@ -374,7 +375,7 @@ func NewFunc(pos syntax.Pos, pkg *Package, name string, sig *Signature) *Func { if sig != nil { typ = sig } - return &Func{object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}, false} + return &Func{object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}, nil, false} } // FullName returns the package- or receiver-type-qualified name of diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go index a7f1185fa8..d47e23f735 100644 --- a/src/cmd/compile/internal/types2/sizeof_test.go +++ b/src/cmd/compile/internal/types2/sizeof_test.go @@ -41,7 +41,7 @@ func TestSizeof(t *testing.T) { {Const{}, 64, 104}, {TypeName{}, 56, 88}, {Var{}, 60, 96}, - {Func{}, 60, 96}, + {Func{}, 64, 104}, {Label{}, 60, 96}, {Builtin{}, 60, 96}, {Nil{}, 56, 88}, diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index fe73ef688c..dcff1f822c 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -125,8 +125,7 @@ func (subst *subster) typ(typ Type) Type { if recv != t.recv || params != t.params || results != t.results { return &Signature{ rparams: t.rparams, - // TODO(gri) Why can't we nil out tparams here, rather than in - // instantiate above? + // TODO(gri) why can't we nil out tparams here, rather than in instantiate? tparams: t.tparams, scope: t.scope, recv: recv, -- GitLab From 986f8ea6b4fe5d479b9f3a05868bdf8266cf3467 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 14 Sep 2021 17:33:16 -0700 Subject: [PATCH 1223/2500] cmd/compile/internal/types2: minor cleanup of instantiation This is a clean port of CL 349429 from go/types to types2 with minor adjustments for types2 names. Change-Id: Ie6a39a01f074acb9e6565ffacb34c94666ae9a95 Reviewed-on: https://go-review.googlesource.com/c/go/+/349999 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/named.go | 38 ++++++++++++++---------- src/cmd/compile/internal/types2/subst.go | 32 +++++--------------- 2 files changed, 29 insertions(+), 41 deletions(-) diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index 7fc84004e3..bc4ac87b9d 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -219,6 +219,21 @@ func (n *Named) setUnderlying(typ Type) { } } +// bestEnv returns the best available environment. In order of preference: +// - the given env, if non-nil +// - the Checker env, if check is non-nil +// - a new environment +func (check *Checker) bestEnv(env *Environment) *Environment { + if env != nil { + return env + } + if check != nil { + assert(check.conf.Environment != nil) + return check.conf.Environment + } + return NewEnvironment() +} + // expandNamed ensures that the underlying type of n is instantiated. // The underlying type will be Typ[Invalid] if there was an error. func expandNamed(env *Environment, n *Named, instPos syntax.Pos) (tparams *TypeParamList, underlying Type, methods []*Func) { @@ -227,24 +242,15 @@ func expandNamed(env *Environment, n *Named, instPos syntax.Pos) (tparams *TypeP check := n.check if check.validateTArgLen(instPos, n.orig.tparams.Len(), n.targs.Len()) { - // TODO(rfindley): handling an optional Checker and Environment here (and - // in subst) feels overly complicated. Can we simplify? - if env == nil { - if check != nil { - env = check.conf.Environment - } else { - // If we're instantiating lazily, we might be outside the scope of a - // type-checking pass. In that case we won't have a pre-existing - // environment, but don't want to create a duplicate of the current - // instance in the process of expansion. - env = NewEnvironment() - } - h := env.TypeHash(n.orig, n.targs.list()) - // ensure that an instance is recorded for h to avoid infinite recursion. - env.typeForHash(h, n) - } + // We must always have an env, to avoid infinite recursion. + env = check.bestEnv(env) + h := env.TypeHash(n.orig, n.targs.list()) + // ensure that an instance is recorded for h to avoid infinite recursion. + env.typeForHash(h, n) + smap := makeSubstMap(n.orig.tparams.list(), n.targs.list()) underlying = n.check.subst(instPos, n.orig.underlying, smap, env) + for i := 0; i < n.orig.NumMethods(); i++ { origm := n.orig.Method(i) diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index dcff1f822c..ee68f22653 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -52,25 +52,12 @@ func (check *Checker) subst(pos syntax.Pos, typ Type, smap substMap, env *Enviro } // general case - var subst subster - subst.pos = pos - subst.smap = smap - - if check != nil { - subst.check = check - if env == nil { - env = check.conf.Environment - } - } - if env == nil { - // If we don't have a *Checker and its global type map, - // use a local version. Besides avoiding duplicate work, - // the type map prevents infinite recursive substitution - // for recursive types (example: type T[P any] *T[P]). - env = NewEnvironment() + subst := subster{ + pos: pos, + smap: smap, + check: check, + env: check.bestEnv(env), } - subst.env = env - return subst.typ(typ) } @@ -227,11 +214,8 @@ func (subst *subster) typ(typ Type) Type { // recursion. The position used here is irrelevant because validation only // occurs on t (we don't call validType on named), but we use subst.pos to // help with debugging. - named := subst.check.instance(subst.pos, t.orig, newTArgs, subst.env).(*Named) - // TODO(rfindley): we probably don't need to resolve here. Investigate if - // this can be removed. - named.resolve(subst.env) - assert(named.underlying != nil) + t.orig.resolve(subst.env) + return subst.check.instance(subst.pos, t.orig, newTArgs, subst.env) // Note that if we were to expose substitution more generally (not just in // the context of a declaration), we'd have to substitute in @@ -239,8 +223,6 @@ func (subst *subster) typ(typ Type) Type { // // But this is unnecessary for now. - return named - case *TypeParam: return subst.smap.lookup(t) -- GitLab From c7543e5db95d80205d1a0be3b4e946fac244601c Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 20 Sep 2021 17:56:35 -0700 Subject: [PATCH 1224/2500] go/types: fixes for pointer receivers of instantiated methods Backported changes from CL 349998 that were not already in go/types. Change-Id: I0341f76c080b4e73567b3e917a4cbbe2e82d3703 Reviewed-on: https://go-review.googlesource.com/c/go/+/351149 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/go/types/instantiate_test.go | 4 ++-- src/go/types/named.go | 22 ++++++++++++++-------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/go/types/instantiate_test.go b/src/go/types/instantiate_test.go index 0c66acb875..cf6d2a9198 100644 --- a/src/go/types/instantiate_test.go +++ b/src/go/types/instantiate_test.go @@ -86,7 +86,7 @@ var X T[int] }{ {"func (r T[P]) m() P", "func (T[int]).m() int"}, {"func (r T[P]) m(P)", "func (T[int]).m(int)"}, - {"func (r T[P]) m() func() P", "func (T[int]).m() func() int"}, + {"func (r *T[P]) m(P)", "func (*T[int]).m(int)"}, {"func (r T[P]) m() T[P]", "func (T[int]).m() T[int]"}, {"func (r T[P]) m(T[P])", "func (T[int]).m(T[int])"}, {"func (r T[P]) m(T[P], P, string)", "func (T[int]).m(T[int], int, string)"}, @@ -99,7 +99,7 @@ var X T[int] if err != nil { t.Fatal(err) } - typ := pkg.Scope().Lookup("X").Type().(*Named) + typ := NewPointer(pkg.Scope().Lookup("X").Type()) obj, _, _ := LookupFieldOrMethod(typ, false, pkg, "m") m, _ := obj.(*Func) if m == nil { diff --git a/src/go/types/named.go b/src/go/types/named.go index 302e43174e..1815aad014 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -257,7 +257,7 @@ func expandNamed(env *Environment, n *Named, instPos token.Pos) (tparams *TypePa // During type checking origm may not have a fully set up type, so defer // instantiation of its signature until later. m := NewFunc(origm.pos, origm.pkg, origm.name, nil) - m.hasPtrRecv = origm.hasPtrRecv + m.hasPtrRecv = ptrRecv(origm) // Setting instRecv here allows us to complete later (we need the // instRecv to get targs and the original method). m.instRecv = n @@ -289,32 +289,38 @@ func expandNamed(env *Environment, n *Named, instPos token.Pos) (tparams *TypePa func (check *Checker) completeMethod(env *Environment, m *Func) { assert(m.instRecv != nil) - rtyp := m.instRecv + rbase := m.instRecv m.instRecv = nil m.setColor(black) - assert(rtyp.TypeArgs().Len() > 0) + assert(rbase.TypeArgs().Len() > 0) // Look up the original method. - _, orig := lookupMethod(rtyp.orig.methods, rtyp.obj.pkg, m.name) + _, orig := lookupMethod(rbase.orig.methods, rbase.obj.pkg, m.name) assert(orig != nil) if check != nil { check.objDecl(orig, nil) } origSig := orig.typ.(*Signature) - if origSig.RecvTypeParams().Len() != rtyp.targs.Len() { + if origSig.RecvTypeParams().Len() != rbase.targs.Len() { m.typ = origSig // or new(Signature), but we can't use Typ[Invalid]: Funcs must have Signature type return // error reported elsewhere } - smap := makeSubstMap(origSig.RecvTypeParams().list(), rtyp.targs.list()) + smap := makeSubstMap(origSig.RecvTypeParams().list(), rbase.targs.list()) sig := check.subst(orig.pos, origSig, smap, env).(*Signature) if sig == origSig { - // No substitution occurred, but we still need to create a copy to hold the - // instantiated receiver. + // No substitution occurred, but we still need to create a new signature to + // hold the instantiated receiver. copy := *origSig sig = © } + var rtyp Type + if ptrRecv(m) { + rtyp = NewPointer(rbase) + } else { + rtyp = rbase + } sig.recv = NewParam(origSig.recv.pos, origSig.recv.pkg, origSig.recv.name, rtyp) m.typ = sig -- GitLab From cceadf8527bc941f641c212e446ff73072bcd500 Mon Sep 17 00:00:00 2001 From: Lynn Boger Date: Mon, 20 Sep 2021 13:53:19 -0500 Subject: [PATCH 1225/2500] cmd/compile/internal: add ABI register information for ppc64 This adds the defines for ABI registers on PPC64. Other changes will need to be in place before they are enabled. Updates #40724 Change-Id: Ia6ead140719eda9aa99b99c48afafff684c33039 Reviewed-on: https://go-review.googlesource.com/c/go/+/351110 Run-TryBot: Lynn Boger TryBot-Result: Go Bot Reviewed-by: Cherry Mui Trust: Lynn Boger --- src/cmd/compile/internal/ppc64/ssa.go | 3 +++ src/cmd/compile/internal/ssa/config.go | 2 ++ src/cmd/compile/internal/ssa/gen/PPC64Ops.go | 22 +++++++++++--------- src/cmd/compile/internal/ssa/opGen.go | 6 +++--- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/cmd/compile/internal/ppc64/ssa.go b/src/cmd/compile/internal/ppc64/ssa.go index e366e06949..d4b85bffe3 100644 --- a/src/cmd/compile/internal/ppc64/ssa.go +++ b/src/cmd/compile/internal/ppc64/ssa.go @@ -502,6 +502,9 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.From.Reg = v.Args[0].Reg() ssagen.AddrAuto(&p.To, v) + case ssa.OpArgIntReg, ssa.OpArgFloatReg: + ssagen.CheckArgReg(v) + case ssa.OpPPC64DIVD: // For now, // diff --git a/src/cmd/compile/internal/ssa/config.go b/src/cmd/compile/internal/ssa/config.go index 32e3a0860e..61d1dea642 100644 --- a/src/cmd/compile/internal/ssa/config.go +++ b/src/cmd/compile/internal/ssa/config.go @@ -239,6 +239,8 @@ func NewConfig(arch string, types Types, ctxt *obj.Link, optimize, softfloat boo c.registers = registersPPC64[:] c.gpRegMask = gpRegMaskPPC64 c.fpRegMask = fpRegMaskPPC64 + //c.intParamRegs = paramIntRegPPC64 + //c.floatParamRegs = paramFloatRegPPC64 c.FPReg = framepointerRegPPC64 c.LinkReg = linkRegPPC64 c.noDuffDevice = true // TODO: Resolve PPC64 DuffDevice (has zero, but not copy) diff --git a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go index a14d9cd490..9d9122e148 100644 --- a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go @@ -705,15 +705,17 @@ func init() { } archs = append(archs, arch{ - name: "PPC64", - pkg: "cmd/internal/obj/ppc64", - genfile: "../../ppc64/ssa.go", - ops: ops, - blocks: blocks, - regnames: regNamesPPC64, - gpregmask: gp, - fpregmask: fp, - framepointerreg: int8(num["SP"]), - linkreg: -1, // not used + name: "PPC64", + pkg: "cmd/internal/obj/ppc64", + genfile: "../../ppc64/ssa.go", + ops: ops, + blocks: blocks, + regnames: regNamesPPC64, + ParamIntRegNames: "R3 R4 R5 R6 R7 R8 R9 R10 R14 R15 R16 R17", + ParamFloatRegNames: "F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12", + gpregmask: gp, + fpregmask: fp, + framepointerreg: -1, + linkreg: -1, // not used }) } diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index eb7e4b91bb..ceb0a24285 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -37030,12 +37030,12 @@ var registersPPC64 = [...]Register{ {62, ppc64.REG_F30, -1, "F30"}, {63, ppc64.REG_F31, -1, "F31"}, } -var paramIntRegPPC64 = []int8(nil) -var paramFloatRegPPC64 = []int8(nil) +var paramIntRegPPC64 = []int8{3, 4, 5, 6, 7, 8, 9, 10, 14, 15, 16, 17} +var paramFloatRegPPC64 = []int8{33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44} var gpRegMaskPPC64 = regMask(1073733624) var fpRegMaskPPC64 = regMask(576460743713488896) var specialRegMaskPPC64 = regMask(0) -var framepointerRegPPC64 = int8(1) +var framepointerRegPPC64 = int8(-1) var linkRegPPC64 = int8(-1) var registersRISCV64 = [...]Register{ {0, riscv.REG_X0, -1, "X0"}, -- GitLab From 9cbdc1d48f75188f6816259e5f6cbd9ae8458bf9 Mon Sep 17 00:00:00 2001 From: Lynn Boger Date: Tue, 17 Aug 2021 13:38:41 -0500 Subject: [PATCH 1226/2500] internal/abi: define PPC64 register ABI constants Add the PPC64 register ABI constants, and allow GOEXPERIMENT regabi values to be set for PPC64. Change-Id: I1c9562ae6669c604db69a7b8ad935d1bc117c899 Reviewed-on: https://go-review.googlesource.com/c/go/+/343870 Run-TryBot: Lynn Boger TryBot-Result: Go Bot Reviewed-by: Cherry Mui Trust: Lynn Boger --- src/internal/abi/abi_ppc64x.go | 21 +++++++++++++++++++++ src/internal/buildcfg/exp.go | 4 ++-- 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 src/internal/abi/abi_ppc64x.go diff --git a/src/internal/abi/abi_ppc64x.go b/src/internal/abi/abi_ppc64x.go new file mode 100644 index 0000000000..e38653224a --- /dev/null +++ b/src/internal/abi/abi_ppc64x.go @@ -0,0 +1,21 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build goexperiment.regabireflect && (ppc64 || ppc64le) +// +build goexperiment.regabireflect +// +build ppc64 ppc64le + +package abi + +const ( + // See abi_generic.go. + + // R3 - R10, R14 - R17. + IntArgRegs = 12 + + // F1 - F12. + FloatArgRegs = 12 + + EffectiveFloatRegSize = 8 +) diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go index 3844e4f021..7cbe4c804d 100644 --- a/src/internal/buildcfg/exp.go +++ b/src/internal/buildcfg/exp.go @@ -111,8 +111,8 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (flags, baseline goexperiment flags.RegabiReflect = true flags.RegabiArgs = true } - // regabi is only supported on amd64 and arm64. - if goarch != "amd64" && goarch != "arm64" { + // regabi is only supported on amd64, arm64, ppc64 and ppc64le. + if goarch != "amd64" && goarch != "arm64" && goarch != "ppc64le" && goarch != "ppc64" { flags.RegabiReflect = false flags.RegabiArgs = false } -- GitLab From 39e08c6cd75da72059a58f05eb500b48124d563e Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 10 Sep 2021 10:47:03 -0400 Subject: [PATCH 1227/2500] io: relax documented Seeker invariants that do not hold in practice MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use “or” instead of “and” to describe error behavior. On error, nearly all Seeker implementations in the Go repo return 0 instead of “the new offset”. (Arguably on error “the new offset” is the same as the previous offset, but some Seeker implementations don't have that offset readily available.) Don't claim that “any positive offsite is legal”. In practice, most of the Seeker implementations within the Go standard library do not allow “[s]eeking to any [arbitrary] positive offset”: some reject all out-of-bounds offsets, and some reject only a subset that happen to overflow some underlying representation. Since some positive offsets may be rejected, we cannot claim that seeking to those offsets “is legal”. However, to avoid invalidating existing Seeker implemetations we must not require an implementation to reject invalid positive offsets either. This is technically a breaking change, since callers of Seek are no longer allowed to assume that a Seek resulting in an arbitrary positive offset will succeed. However, since basically none of the existing implementations actually conformed to the documented behavior I believe this falls under the “specification errors” exception to the Go 1 compatibility policy. Fixes #48316 Change-Id: Ib1b478599b20ad5361bcc97fe8ceb84f74e6d971 Reviewed-on: https://go-review.googlesource.com/c/go/+/349054 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick Reviewed-by: Ian Lance Taylor Reviewed-by: Rob Pike --- src/io/io.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/io/io.go b/src/io/io.go index 2724321ed9..2e697e7450 100644 --- a/src/io/io.go +++ b/src/io/io.go @@ -113,11 +113,12 @@ type Closer interface { // SeekCurrent means relative to the current offset, and // SeekEnd means relative to the end. // Seek returns the new offset relative to the start of the -// file and an error, if any. +// file or an error, if any. // // Seeking to an offset before the start of the file is an error. -// Seeking to any positive offset is legal, but the behavior of subsequent -// I/O operations on the underlying object is implementation-dependent. +// Seeking to any positive offset may be allowed, but if the new offset exceeds +// the size of the underlying object the behavior of subsequent I/O operations +// is implementation-dependent. type Seeker interface { Seek(offset int64, whence int) (int64, error) } -- GitLab From 7d67f8d4354d864fcbe6b218b7f80bcdfde851c9 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 20 May 2021 11:33:36 -0400 Subject: [PATCH 1228/2500] text/template: implement short-circuit and, or Making the builtin and and or functions use short-circuit evaluation was accepted as a proposal in April 2019, but we never got around to implementing it. Do that. Fixes #31103. Change-Id: Ia43d4a9a6b0ab814f2dd3471ebaca3e7bb1505cf Reviewed-on: https://go-review.googlesource.com/c/go/+/321490 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Rob Pike --- src/text/template/doc.go | 12 +++++++----- src/text/template/exec.go | 22 ++++++++++++++++++---- src/text/template/exec_test.go | 5 +++++ src/text/template/funcs.go | 30 ++++++------------------------ 4 files changed, 36 insertions(+), 33 deletions(-) diff --git a/src/text/template/doc.go b/src/text/template/doc.go index 7b30294336..0ea132e8e6 100644 --- a/src/text/template/doc.go +++ b/src/text/template/doc.go @@ -307,9 +307,10 @@ Predefined global functions are named as follows. and Returns the boolean AND of its arguments by returning the - first empty argument or the last argument, that is, - "and x y" behaves as "if x then y else x". All the - arguments are evaluated. + first empty argument or the last argument. That is, + "and x y" behaves as "if x then y else x." + Evaluation proceeds through the arguments left to right + and returns when the result is determined. call Returns the result of calling the first argument, which must be a function, with the remaining arguments as parameters. @@ -344,8 +345,9 @@ Predefined global functions are named as follows. or Returns the boolean OR of its arguments by returning the first non-empty argument or the last argument, that is, - "or x y" behaves as "if x then x else y". All the - arguments are evaluated. + "or x y" behaves as "if x then x else y". + Evaluation proceeds through the arguments left to right + and returns when the result is determined. print An alias for fmt.Sprint printf diff --git a/src/text/template/exec.go b/src/text/template/exec.go index 5ad3b4ec58..6e005b57d7 100644 --- a/src/text/template/exec.go +++ b/src/text/template/exec.go @@ -572,11 +572,11 @@ func (s *state) evalFieldChain(dot, receiver reflect.Value, node parse.Node, ide func (s *state) evalFunction(dot reflect.Value, node *parse.IdentifierNode, cmd parse.Node, args []parse.Node, final reflect.Value) reflect.Value { s.at(node) name := node.Ident - function, ok := findFunction(name, s.tmpl) + function, isBuiltin, ok := findFunction(name, s.tmpl) if !ok { s.errorf("%q is not a defined function", name) } - return s.evalCall(dot, function, cmd, name, args, final) + return s.evalCall(dot, function, isBuiltin, cmd, name, args, final) } // evalField evaluates an expression like (.Field) or (.Field arg1 arg2). @@ -605,7 +605,7 @@ func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node, ptr = ptr.Addr() } if method := ptr.MethodByName(fieldName); method.IsValid() { - return s.evalCall(dot, method, node, fieldName, args, final) + return s.evalCall(dot, method, false, node, fieldName, args, final) } hasArgs := len(args) > 1 || final != missingVal // It's not a method; must be a field of a struct or an element of a map. @@ -669,7 +669,7 @@ var ( // evalCall executes a function or method call. If it's a method, fun already has the receiver bound, so // it looks just like a function call. The arg list, if non-nil, includes (in the manner of the shell), arg[0] // as the function itself. -func (s *state) evalCall(dot, fun reflect.Value, node parse.Node, name string, args []parse.Node, final reflect.Value) reflect.Value { +func (s *state) evalCall(dot, fun reflect.Value, isBuiltin bool, node parse.Node, name string, args []parse.Node, final reflect.Value) reflect.Value { if args != nil { args = args[1:] // Zeroth arg is function name/node; not passed to function. } @@ -691,6 +691,20 @@ func (s *state) evalCall(dot, fun reflect.Value, node parse.Node, name string, a // TODO: This could still be a confusing error; maybe goodFunc should provide info. s.errorf("can't call method/function %q with %d results", name, typ.NumOut()) } + + // Special case for builtin and/or, which short-circuit. + if isBuiltin && (name == "and" || name == "or") { + argType := typ.In(0) + var v reflect.Value + for _, arg := range args { + v = s.evalArg(dot, argType, arg).Interface().(reflect.Value) + if truth(v) == (name == "or") { + break + } + } + return v + } + // Build the arg list. argv := make([]reflect.Value, numIn) // Args must be evaluated. Fixed args first. diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go index ef521645a7..ae67b9334f 100644 --- a/src/text/template/exec_test.go +++ b/src/text/template/exec_test.go @@ -481,6 +481,10 @@ var execTests = []execTest{ {"not", "{{not true}} {{not false}}", "false true", nil, true}, {"and", "{{and false 0}} {{and 1 0}} {{and 0 true}} {{and 1 1}}", "false 0 0 1", nil, true}, {"or", "{{or 0 0}} {{or 1 0}} {{or 0 true}} {{or 1 1}}", "0 1 true 1", nil, true}, + {"or short-circuit", "{{or 0 1 (die)}}", "1", nil, true}, + {"and short-circuit", "{{and 1 0 (die)}}", "0", nil, true}, + {"or short-circuit2", "{{or 0 0 (die)}}", "", nil, false}, + {"and short-circuit2", "{{and 1 1 (die)}}", "", nil, false}, {"boolean if", "{{if and true 1 `hi`}}TRUE{{else}}FALSE{{end}}", "TRUE", tVal, true}, {"boolean if not", "{{if and true 1 `hi` | not}}TRUE{{else}}FALSE{{end}}", "FALSE", nil, true}, @@ -764,6 +768,7 @@ func testExecute(execTests []execTest, template *Template, t *testing.T) { "add": add, "count": count, "dddArg": dddArg, + "die": func() bool { panic("die") }, "echo": echo, "makemap": makemap, "mapOfThree": mapOfThree, diff --git a/src/text/template/funcs.go b/src/text/template/funcs.go index fff833ed29..11e2e903c8 100644 --- a/src/text/template/funcs.go +++ b/src/text/template/funcs.go @@ -139,18 +139,18 @@ func goodName(name string) bool { } // findFunction looks for a function in the template, and global map. -func findFunction(name string, tmpl *Template) (reflect.Value, bool) { +func findFunction(name string, tmpl *Template) (v reflect.Value, isBuiltin, ok bool) { if tmpl != nil && tmpl.common != nil { tmpl.muFuncs.RLock() defer tmpl.muFuncs.RUnlock() if fn := tmpl.execFuncs[name]; fn.IsValid() { - return fn, true + return fn, false, true } } if fn := builtinFuncs()[name]; fn.IsValid() { - return fn, true + return fn, true, true } - return reflect.Value{}, false + return reflect.Value{}, false, false } // prepareArg checks if value can be used as an argument of type argType, and @@ -382,31 +382,13 @@ func truth(arg reflect.Value) bool { // and computes the Boolean AND of its arguments, returning // the first false argument it encounters, or the last argument. func and(arg0 reflect.Value, args ...reflect.Value) reflect.Value { - if !truth(arg0) { - return arg0 - } - for i := range args { - arg0 = args[i] - if !truth(arg0) { - break - } - } - return arg0 + panic("unreachable") // implemented as a special case in evalCall } // or computes the Boolean OR of its arguments, returning // the first true argument it encounters, or the last argument. func or(arg0 reflect.Value, args ...reflect.Value) reflect.Value { - if truth(arg0) { - return arg0 - } - for i := range args { - arg0 = args[i] - if truth(arg0) { - break - } - } - return arg0 + panic("unreachable") // implemented as a special case in evalCall } // not returns the Boolean negation of its argument. -- GitLab From 9ab6af9837f924869cd2213ce028b3f4d49c487c Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Fri, 17 Sep 2021 13:45:12 -0700 Subject: [PATCH 1229/2500] runtime, cmd/link: fix comment typos Change-Id: I33a10417939bfcfec117d6ad49c42312731ac30f Reviewed-on: https://go-review.googlesource.com/c/go/+/350733 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/link/internal/ld/pcln.go | 4 ++-- src/runtime/symtab.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index 70e3e1284b..5294da5724 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -51,7 +51,7 @@ type pclntab struct { } // addGeneratedSym adds a generator symbol to pclntab, returning the new Sym. -// It is the caller's responsibility to save they symbol in state. +// It is the caller's responsibility to save the symbol in state. func (state *pclntab) addGeneratedSym(ctxt *Link, name string, size int64, f generatorFunc) loader.Sym { size = Rnd(size, int64(ctxt.Arch.PtrSize)) state.size += size @@ -521,7 +521,7 @@ type pclnSetUint func(*loader.SymbolBuilder, *sys.Arch, int64, uint64) int64 // // Because of timing in the linker, generating this table takes two passes. // The first pass is executed early in the link, and it creates any needed -// relocations to layout the data. The pieces that need relocations are: +// relocations to lay out the data. The pieces that need relocations are: // 1) the PC->func table. // 2) The entry points in the func objects. // 3) The funcdata. diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index d08aa0b320..aa9dd7b40c 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -374,11 +374,11 @@ type pcHeader struct { minLC uint8 // min instruction size ptrSize uint8 // size of a ptr in bytes nfunc int // number of functions in the module - nfiles uint // number of entries in the file tab. + nfiles uint // number of entries in the file tab funcnameOffset uintptr // offset to the funcnametab variable from pcHeader cuOffset uintptr // offset to the cutab variable from pcHeader filetabOffset uintptr // offset to the filetab variable from pcHeader - pctabOffset uintptr // offset to the pctab varible from pcHeader + pctabOffset uintptr // offset to the pctab variable from pcHeader pclnOffset uintptr // offset to the pclntab variable from pcHeader } -- GitLab From d5427658963083d5bcb87c3c79aa2b13fa769715 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Mon, 20 Sep 2021 16:41:06 -0700 Subject: [PATCH 1230/2500] cmd/go: disable gofuzzbeta build tag by default It was enabled by default on the dev.fuzz branch so that users could check in fuzz targets without breaking their builds. Now that dev.fuzz is merged to master, users should switch to a go1.18 release constraint instead. For #47037 Change-Id: I0475368eb4570fe0c7027a3ae8f6950449c1a9ca Reviewed-on: https://go-review.googlesource.com/c/go/+/351118 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/cmd/go/internal/cfg/cfg.go | 3 -- src/cmd/go/testdata/script/test_fuzz_tag.txt | 31 -------------------- 2 files changed, 34 deletions(-) delete mode 100644 src/cmd/go/testdata/script/test_fuzz_tag.txt diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go index dd0e8cbbd6..b9632ea3c9 100644 --- a/src/cmd/go/internal/cfg/cfg.go +++ b/src/cmd/go/internal/cfg/cfg.go @@ -61,9 +61,6 @@ var ( func defaultContext() build.Context { ctxt := build.Default - // TODO(#47037): remove this tag before merging to master. - ctxt.BuildTags = []string{"gofuzzbeta"} - ctxt.JoinPath = filepath.Join // back door to say "do not use go command" ctxt.GOROOT = findGOROOT() diff --git a/src/cmd/go/testdata/script/test_fuzz_tag.txt b/src/cmd/go/testdata/script/test_fuzz_tag.txt deleted file mode 100644 index 07ed5d6d61..0000000000 --- a/src/cmd/go/testdata/script/test_fuzz_tag.txt +++ /dev/null @@ -1,31 +0,0 @@ -# Check that the gofuzzbeta tag is enabled by default and can be disabled. -# TODO(jayconrod,katiehockman): before merging to master, restore the old -# default and delete this test. - -[short] skip - -go test -list=. -stdout Test -stdout Fuzz - -go test -tags= - --- go.mod -- -module fuzz - -go 1.17 --- fuzz_test.go -- -// +build gofuzzbeta - -package fuzz - -import "testing" - -func Fuzz(f *testing.F) { - f.Add([]byte(nil)) - f.Fuzz(func(*testing.T, []byte) {}) -} - -func Test(*testing.T) {} --- empty_test.go -- -package fuzz -- GitLab From 901ac46df8e742369e4b79c41e739eb3d7ffc7e5 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 20 Sep 2021 14:13:07 -0700 Subject: [PATCH 1231/2500] cmd/link: document generator symbols more And make the existing docs easier to parse. In particular, document the interaction with relocations. Change-Id: I97579f88d9248c12e64af723a946959b88d4b674 Reviewed-on: https://go-review.googlesource.com/c/go/+/351112 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/link/internal/ld/link.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/cmd/link/internal/ld/link.go b/src/cmd/link/internal/ld/link.go index 13618beff9..64d18bd62c 100644 --- a/src/cmd/link/internal/ld/link.go +++ b/src/cmd/link/internal/ld/link.go @@ -148,12 +148,18 @@ func (ctxt *Link) MaxVersion() int { } // generatorFunc is a convenience type. -// Linker created symbols that are large, and shouldn't really live in the -// heap can define a generator function, and their bytes can be generated +// Some linker-created Symbols are large and shouldn't really live in the heap. +// Such Symbols can define a generator function. Their bytes can be generated // directly in the output mmap. // -// Generator symbols shouldn't grow the symbol size, and might be called in -// parallel in the future. +// Relocations are applied prior to emitting generator Symbol contents. +// Generator Symbols that require relocations can be written in two passes. +// The first pass, at Symbol creation time, adds only relocations. +// The second pass, at content generation time, adds the rest. +// See generateFunctab for an example. +// +// Generator functions shouldn't grow the Symbol size. +// Generator functions must be safe for concurrent use. // // Generator Symbols have their Data set to the mmapped area when the // generator is called. -- GitLab From 13aa0d8f578e9c293970fe462f79655899959093 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Fri, 17 Sep 2021 16:21:43 -0700 Subject: [PATCH 1232/2500] runtime: fix output for bad pcHeader With print, the output all runs together. Take this opportunity to clean up and label all the fields. Print pluginpath unilaterally; no reason not to. Wrap long lines. Remove pointless newline from throw. Change-Id: I37af15dc8fcb3dbdbc6da8bbea2c0ceaf7b5b889 Reviewed-on: https://go-review.googlesource.com/c/go/+/350734 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/symtab.go | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index aa9dd7b40c..87b4eeb220 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -568,13 +568,11 @@ const debugPcln = false func moduledataverify1(datap *moduledata) { // Check that the pclntab's format is valid. hdr := datap.pcHeader - if hdr.magic != 0xfffffffa || hdr.pad1 != 0 || hdr.pad2 != 0 || hdr.minLC != sys.PCQuantum || hdr.ptrSize != goarch.PtrSize { - print("runtime: function symbol table header:", hex(hdr.magic), hex(hdr.pad1), hex(hdr.pad2), hex(hdr.minLC), hex(hdr.ptrSize)) - if datap.pluginpath != "" { - print(", plugin:", datap.pluginpath) - } - println() - throw("invalid function symbol table\n") + if hdr.magic != 0xfffffffa || hdr.pad1 != 0 || hdr.pad2 != 0 || + hdr.minLC != sys.PCQuantum || hdr.ptrSize != goarch.PtrSize { + println("runtime: pcHeader: magic=", hex(hdr.magic), "pad1=", hdr.pad1, "pad2=", hdr.pad2, + "minLC=", hdr.minLC, "ptrSize=", hdr.ptrSize, "pluginpath=", datap.pluginpath) + throw("invalid function symbol table") } // ftab is lookup table for function by program counter. -- GitLab From fa5c5043bca5264fabbdc47d780cfb53b1f5d9a3 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Sat, 11 Sep 2021 06:50:06 -0700 Subject: [PATCH 1233/2500] encoding/xml: truncate generic type names xml names can't have any of '[],' in them, which might appear in generic type names. Truncate at the first '[' so the names are still valid. Fixes #48318 Change-Id: I110ff4269f763089467e7cf84b0f0c5075fb44b7 Reviewed-on: https://go-review.googlesource.com/c/go/+/349349 Trust: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Russ Cox --- src/encoding/xml/marshal.go | 4 ++++ test/typeparam/issue48318.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 test/typeparam/issue48318.go diff --git a/src/encoding/xml/marshal.go b/src/encoding/xml/marshal.go index d8a04a95a2..a8c8f659ca 100644 --- a/src/encoding/xml/marshal.go +++ b/src/encoding/xml/marshal.go @@ -494,6 +494,10 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplat } if start.Name.Local == "" { name := typ.Name() + if i := strings.IndexByte(name, '['); i >= 0 { + // Truncate generic instantiation name. See issue 48318. + name = name[:i] + } if name == "" { return &UnsupportedTypeError{typ} } diff --git a/test/typeparam/issue48318.go b/test/typeparam/issue48318.go new file mode 100644 index 0000000000..ae53a28dc5 --- /dev/null +++ b/test/typeparam/issue48318.go @@ -0,0 +1,33 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "encoding/xml" + "fmt" +) + +type A[T, U any] struct { + Name T `xml:"name"` + Data U `xml:"data"` +} + +func main() { + src := &A[string, int]{Name: "name", Data: 1} + data, err := xml.Marshal(src) + if err != nil { + panic(err) + } + dst := &A[string, int]{} + err = xml.Unmarshal(data, dst) + if err != nil { + panic(err) + } + if *src != *dst { + panic(fmt.Sprintf("wanted %#v got %#v", src, dst)) + } +} -- GitLab From cc85bd07cc27a1f78c13a699c1ea5737abeb47c2 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Wed, 15 Sep 2021 14:44:19 -0700 Subject: [PATCH 1234/2500] testing, cmd/go: clarify documentation This CL removes 'go help fuzz' but expands the testing package documentation with much of the same information. It also removes documentation for the unimplemented -keepfuzzing flag and makes a number of other clarifications. Addressing comments in CL 348469. Updates #46629 Change-Id: I12ab5971c900c2e43f2c2d83c6705e8cd642388b Reviewed-on: https://go-review.googlesource.com/c/go/+/351113 Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman Reviewed-by: Bryan C. Mills Trust: Katie Hockman Trust: Bryan C. Mills --- src/cmd/go/alldocs.go | 56 +++++++++-------------- src/cmd/go/internal/clean/clean.go | 4 +- src/cmd/go/internal/test/test.go | 54 ++++++++-------------- src/cmd/go/main.go | 1 - src/testing/testing.go | 72 +++++++++++++++++++++++------- 5 files changed, 98 insertions(+), 89 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 74522691ab..744d462c00 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -53,7 +53,6 @@ // private configuration for downloading non-public code // testflag testing flags // testfunc testing functions -// fuzz fuzzing // vcs controlling version control with GOVCS // // Use "go help " for more information about that topic. @@ -293,7 +292,9 @@ // download cache, including unpacked source code of versioned // dependencies. // -// The -fuzzcache flag causes clean to remove values used for fuzz testing. +// The -fuzzcache flag causes clean to remove files stored in the Go build +// cache for fuzz testing. Files stored in source testdata directories +// are left in place. // // For more about build flags, see 'go help build'. // @@ -2733,10 +2734,10 @@ // (for example, -benchtime 100x). // // -count n -// Run each test, benchmark, and fuzz targets' seed corpora n times -// (default 1). +// Run each test, benchmark, and fuzz seed n times (default 1). // If -cpu is set, run n times for each GOMAXPROCS value. -// Examples are always run once. +// Examples are always run once. -count does not apply to +// fuzz targets matched by -fuzz. // // -cover // Enable coverage analysis. @@ -2765,14 +2766,18 @@ // -cpu 1,2,4 // Specify a list of GOMAXPROCS values for which the tests, benchmarks or // fuzz targets should be executed. The default is the current value -// of GOMAXPROCS. +// of GOMAXPROCS. -cpu does not apply to fuzz targets matched by -fuzz. // // -failfast // Do not start new tests after the first test failure. // -// -fuzz name -// Run the fuzz target with the given regexp. Must match exactly one fuzz -// target. This is an experimental feature. +// -fuzz regexp +// Run the fuzz target matching the regular expression. When specified, +// the command line argument must match exactly one package, and regexp +// must match exactly one fuzz target within that package. After tests, +// benchmarks, seed corpora of other fuzz targets, and examples have +// completed, the matching target will be fuzzed. See the Fuzzing section +// of the testing package documentation for details. // // -fuzztime t // Run enough iterations of the fuzz test to take t, specified as a @@ -2785,9 +2790,6 @@ // Log verbose output and test results in JSON. This presents the // same information as the -v flag in a machine-readable format. // -// -keepfuzzing -// Keep running the fuzz target if a crasher is found. -// // -list regexp // List tests, benchmarks, fuzz targets, or examples matching the regular // expression. No tests, benchmarks, fuzz targets, or examples will be run. @@ -2798,10 +2800,13 @@ // Allow parallel execution of test functions that call t.Parallel, and // f.Fuzz functions that call t.Parallel when running the seed corpus. // The value of this flag is the maximum number of tests to run -// simultaneously. While fuzzing, the value of this flag is the -// maximum number of workers to run the fuzz function simultaneously, -// regardless of whether t.Parallel has been called; by default, it is set -// to the value of GOMAXPROCS. +// simultaneously. +// While fuzzing, the value of this flag is the maximum number of +// subprocesses that may call the fuzz function simultaneously, regardless of +// whether T.Parallel is called. +// By default, -parallel is set to the value of GOMAXPROCS. +// Setting -parallel to values higher than GOMAXPROCS may cause degraded +// performance due to CPU contention, especially when fuzzing. // Note that -parallel only applies within a single test binary. // The 'go test' command may run tests for different packages // in parallel as well, according to the setting of the -p flag @@ -3026,25 +3031,6 @@ // See the documentation of the testing package for more information. // // -// Fuzzing -// -// By default, go test will build and run the fuzz targets using the target's seed -// corpus only. Any generated corpora in $GOCACHE that were previously written by -// the fuzzing engine will not be run by default. -// -// When -fuzz is set, the binary will be instrumented for coverage. After all -// tests, examples, benchmark functions, and the seed corpora for all fuzz targets -// have been run, go test will begin to fuzz the specified fuzz target. -// Note that this feature is experimental. -// -// -run can be used for testing a single seed corpus entry for a fuzz target. The -// regular expression value of -run can be in the form $target/$name, where $target -// is the name of the fuzz target, and $name is the name of the file (ignoring file -// extensions) to run. For example, -run=FuzzFoo/497b6f87. -// -// See https://golang.org/s/draft-fuzzing-design for more details. -// -// // Controlling version control with GOVCS // // The 'go get' command can run version control commands like git diff --git a/src/cmd/go/internal/clean/clean.go b/src/cmd/go/internal/clean/clean.go index 518473c914..ca7623ea21 100644 --- a/src/cmd/go/internal/clean/clean.go +++ b/src/cmd/go/internal/clean/clean.go @@ -75,7 +75,9 @@ The -modcache flag causes clean to remove the entire module download cache, including unpacked source code of versioned dependencies. -The -fuzzcache flag causes clean to remove values used for fuzz testing. +The -fuzzcache flag causes clean to remove files stored in the Go build +cache for fuzz testing. Files stored in source testdata directories +are left in place. For more about build flags, see 'go help build'. diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 8f5d57eff1..c8305c7808 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -210,10 +210,10 @@ control the execution of any test: (for example, -benchtime 100x). -count n - Run each test, benchmark, and fuzz targets' seed corpora n times - (default 1). + Run each test, benchmark, and fuzz seed n times (default 1). If -cpu is set, run n times for each GOMAXPROCS value. - Examples are always run once. + Examples are always run once. -count does not apply to + fuzz targets matched by -fuzz. -cover Enable coverage analysis. @@ -242,14 +242,18 @@ control the execution of any test: -cpu 1,2,4 Specify a list of GOMAXPROCS values for which the tests, benchmarks or fuzz targets should be executed. The default is the current value - of GOMAXPROCS. + of GOMAXPROCS. -cpu does not apply to fuzz targets matched by -fuzz. -failfast Do not start new tests after the first test failure. - -fuzz name - Run the fuzz target with the given regexp. Must match exactly one fuzz - target. This is an experimental feature. + -fuzz regexp + Run the fuzz target matching the regular expression. When specified, + the command line argument must match exactly one package, and regexp + must match exactly one fuzz target within that package. After tests, + benchmarks, seed corpora of other fuzz targets, and examples have + completed, the matching target will be fuzzed. See the Fuzzing section + of the testing package documentation for details. -fuzztime t Run enough iterations of the fuzz test to take t, specified as a @@ -262,9 +266,6 @@ control the execution of any test: Log verbose output and test results in JSON. This presents the same information as the -v flag in a machine-readable format. - -keepfuzzing - Keep running the fuzz target if a crasher is found. - -list regexp List tests, benchmarks, fuzz targets, or examples matching the regular expression. No tests, benchmarks, fuzz targets, or examples will be run. @@ -275,10 +276,13 @@ control the execution of any test: Allow parallel execution of test functions that call t.Parallel, and f.Fuzz functions that call t.Parallel when running the seed corpus. The value of this flag is the maximum number of tests to run - simultaneously. While fuzzing, the value of this flag is the - maximum number of workers to run the fuzz function simultaneously, - regardless of whether t.Parallel has been called; by default, it is set - to the value of GOMAXPROCS. + simultaneously. + While fuzzing, the value of this flag is the maximum number of + subprocesses that may call the fuzz function simultaneously, regardless of + whether T.Parallel is called. + By default, -parallel is set to the value of GOMAXPROCS. + Setting -parallel to values higher than GOMAXPROCS may cause degraded + performance due to CPU contention, especially when fuzzing. Note that -parallel only applies within a single test binary. The 'go test' command may run tests for different packages in parallel as well, according to the setting of the -p flag @@ -507,28 +511,6 @@ See the documentation of the testing package for more information. `, } -var HelpFuzz = &base.Command{ - UsageLine: "fuzz", - Short: "fuzzing", - Long: ` -By default, go test will build and run the fuzz targets using the target's seed -corpus only. Any generated corpora in $GOCACHE that were previously written by -the fuzzing engine will not be run by default. - -When -fuzz is set, the binary will be instrumented for coverage. After all -tests, examples, benchmark functions, and the seed corpora for all fuzz targets -have been run, go test will begin to fuzz the specified fuzz target. -Note that this feature is experimental. - --run can be used for testing a single seed corpus entry for a fuzz target. The -regular expression value of -run can be in the form $target/$name, where $target -is the name of the fuzz target, and $name is the name of the file (ignoring file -extensions) to run. For example, -run=FuzzFoo/497b6f87. - -See https://golang.org/s/draft-fuzzing-design for more details. -`, -} - var ( testBench string // -bench flag testC bool // -c flag diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go index 11ff750aff..16361e02ca 100644 --- a/src/cmd/go/main.go +++ b/src/cmd/go/main.go @@ -80,7 +80,6 @@ func init() { modfetch.HelpPrivate, test.HelpTestflag, test.HelpTestfunc, - test.HelpFuzz, modget.HelpVCS, } } diff --git a/src/testing/testing.go b/src/testing/testing.go index 567eb0dfa3..ac1e52af85 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -134,28 +134,68 @@ // // Fuzzing // -// Functions of the form +// 'go test' and the testing package support fuzzing, a testing technique where +// a function is called with randomly generated inputs to find bugs not +// anticipated by unit tests. +// +// A fuzz target is a function that declares a set of "seed" inputs by calling +// F.Add, then provides a fuzz function by calling F.Fuzz. A fuzz target has +// the form: +// // func FuzzXxx(*testing.F) -// are considered fuzz targets, and are executed by the "go test" command. When -// the -fuzz flag is provided, the functions will be fuzzed. // -// For a description of the testing flags, see -// https://golang.org/cmd/go/#hdr-Testing_flags. +// For example: +// +// func FuzzHex(f *testing.F) { +// for _, seed := range [][]byte{{}, {0}, {9}, {0xa}, {0xf}, {1, 2, 3, 4}} { +// f.Add(seed) +// } +// f.Fuzz(func(t *testing.T, in []byte) { +// enc := hex.EncodeToString(in) +// out, err := hex.DecodeString(enc) +// if err != nil { +// t.Fatalf("%v: decode: %v", in, err) +// } +// if !bytes.Equal(in, out) { +// t.Fatalf("%v: not equal after round trip: %v", in, out) +// } +// }) +// } +// +// Seed inputs may be registered by calling F.Add or by storing files in the +// directory testdata/fuzz/ (where is the name of the fuzz target) +// within the package containing the fuzz target. Seed inputs are optional, but +// the fuzzing engine may find bugs more efficiently when provided with a set +// of small seed inputs with good code coverage. +// +// The fuzz function provided to F.Fuzz must accept a *testing.T parameter, +// followed by one or more parameters for random inputs. The types of arguments +// passed to F.Add must be identical to the types of these parameters. The fuzz +// function may signal that it's found a problem the same way tests do: by +// calling T.Fail (or any method that calls it like T.Error or T.Fatal) or by +// panicking. +// +// When fuzzing is enabled (by setting the -fuzz flag to a regular expression +// that matches a specific fuzz target), the fuzz function is called with +// arguments generated by repeatedly making random changes to the seed inputs. +// On supported platforms, 'go test' compiles the test executable with fuzzing +// coverage instrumentation. The fuzzing engine uses that instrumentation to +// find and cache inputs that expand coverage, increasing the liklihood of +// finding bugs. If the fuzz function finds a problem, the fuzzing engine writes +// the inputs that caused the problem to a file in the directory +// testdata/fuzz/ within the package directory. This file later serves as +// a seed input. If the file can't be written at that location (for example, +// because the directory is read-only), the fuzzing engine writes the file to +// the fuzz cache directory within the build cache instead. +// +// When fuzzing is disabled, the fuzz function is called with the seed inputs +// registered with F.Add and seed inputs from testdata/fuzz/. In this +// mode, the fuzz target acts much like a regular test, with subtests started +// with F.Fuzz instead of T.Run. // -// For a description of fuzzing, see golang.org/s/draft-fuzzing-design. // TODO(#48255): write and link to documentation that will be helpful to users // who are unfamiliar with fuzzing. // -// A sample fuzz target looks like this: -// -// func FuzzBytesCmp(f *testing.F) { -// f.Fuzz(func(t *testing.T, a, b []byte) { -// if bytes.HasPrefix(a, b) && !bytes.Contains(a, b) { -// t.Error("HasPrefix is true, but Contains is false") -// } -// }) -// } -// // Skipping // // Tests or benchmarks may be skipped at run time with a call to -- GitLab From 6097ebe627b7bc58d63d6765abc005f548b9644c Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sun, 12 Sep 2021 19:43:25 -0400 Subject: [PATCH 1235/2500] go/types: record all instances, not just inferred instances This change modifies the way we record instance information. It changes the Info.Inferred map to use the instantiated *ast.Ident as its key, and record information for all instances, not just those that were produced via function type inference. Accordingly, Info.Inferred is renamed to Info.Instances, and the Inferred type is renamed to Instance, with its Sig field changed to Type. This was largely motivated by suggestions from mdempsky on the go/types API proposal (#47916). In our analysis, always using the *ast.Ident as key and recording all instances makes the API easier to understand and use. Instance.TArgs is also renamed to TypeArgs, consistent with other name changes. Updates #47916 Change-Id: Ic25ad0cfd65fee6b05e513843c3866ee7a77cfe3 Reviewed-on: https://go-review.googlesource.com/c/go/+/349629 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer --- src/go/types/api.go | 30 +++++--- src/go/types/api_test.go | 155 +++++++++++++++++++++++++++------------ src/go/types/call.go | 10 +-- src/go/types/check.go | 36 +++++++-- src/go/types/typexpr.go | 1 + 5 files changed, 163 insertions(+), 69 deletions(-) diff --git a/src/go/types/api.go b/src/go/types/api.go index ebc3a01266..4cf0eb123f 100644 --- a/src/go/types/api.go +++ b/src/go/types/api.go @@ -203,11 +203,19 @@ type Info struct { // qualified identifiers are collected in the Uses map. Types map[ast.Expr]TypeAndValue - // Inferred maps calls of parameterized functions that use - // type inference to the inferred type arguments and signature - // of the function called. The recorded "call" expression may be - // an *ast.CallExpr (as in f(x)), or an *ast.IndexExpr (s in f[T]). - Inferred map[ast.Expr]Inferred + // Instances maps identifiers denoting parameterized types or functions to + // their type arguments and instantiated type. + // + // For example, Instances will map the identifier for 'T' in the type + // instantiation T[int, string] to the type arguments [int, string] and + // resulting instantiated *Named type. Given a parameterized function + // func F[A any](A), Instances will map the identifier for 'F' in the call + // expression F(int(1)) to the inferred type arguments [int], and resulting + // instantiated *Signature. + // + // Invariant: Instantiating Uses[id].Type() with Instances[id].TypeArgs + // results in an equivalent of Instances[id].Type. + Instances map[*ast.Ident]Instance // Defs maps identifiers to the objects they define (including // package names, dots "." of dot-imports, and blank "_" identifiers). @@ -365,11 +373,13 @@ func (tv TypeAndValue) HasOk() bool { return tv.mode == commaok || tv.mode == mapindex } -// Inferred reports the Inferred type arguments and signature -// for a parameterized function call that uses type inference. -type Inferred struct { - TArgs *TypeList - Sig *Signature +// Instance reports the type arguments and instantiated type for type and +// function instantiations. For type instantiations, Type will be of dynamic +// type *Named. For function instantiations, Type will be of dynamic type +// *Signature. +type Instance struct { + TypeArgs *TypeList + Type Type } // An Initializer describes a package-level variable, or a list of variables in case diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index d4f9bb65c9..9b584f390c 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -402,126 +402,189 @@ func TestTypesInfo(t *testing.T) { } } -func TestInferredInfo(t *testing.T) { +func TestInstanceInfo(t *testing.T) { var tests = []struct { src string - fun string + name string targs []string - sig string + typ string }{ - {genericPkg + `p0; func f[T any](T) {}; func _() { f(42) }`, + {`package p0; func f[T any](T) {}; func _() { f(42) }`, `f`, []string{`int`}, `func(int)`, }, - {genericPkg + `p1; func f[T any](T) T { panic(0) }; func _() { f('@') }`, + {`package p1; func f[T any](T) T { panic(0) }; func _() { f('@') }`, `f`, []string{`rune`}, `func(rune) rune`, }, - {genericPkg + `p2; func f[T any](...T) T { panic(0) }; func _() { f(0i) }`, + {`package p2; func f[T any](...T) T { panic(0) }; func _() { f(0i) }`, `f`, []string{`complex128`}, `func(...complex128) complex128`, }, - {genericPkg + `p3; func f[A, B, C any](A, *B, []C) {}; func _() { f(1.2, new(string), []byte{}) }`, + {`package p3; func f[A, B, C any](A, *B, []C) {}; func _() { f(1.2, new(string), []byte{}) }`, `f`, []string{`float64`, `string`, `byte`}, `func(float64, *string, []byte)`, }, - {genericPkg + `p4; func f[A, B any](A, *B, ...[]B) {}; func _() { f(1.2, new(byte)) }`, + {`package p4; func f[A, B any](A, *B, ...[]B) {}; func _() { f(1.2, new(byte)) }`, `f`, []string{`float64`, `byte`}, `func(float64, *byte, ...[]byte)`, }, - {genericPkg + `s1; func f[T any, P interface{~*T}](x T) {}; func _(x string) { f(x) }`, + {`package s1; func f[T any, P interface{~*T}](x T) {}; func _(x string) { f(x) }`, `f`, []string{`string`, `*string`}, `func(x string)`, }, - {genericPkg + `s2; func f[T any, P interface{~*T}](x []T) {}; func _(x []int) { f(x) }`, + {`package s2; func f[T any, P interface{~*T}](x []T) {}; func _(x []int) { f(x) }`, `f`, []string{`int`, `*int`}, `func(x []int)`, }, - {genericPkg + `s3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]](x []T) {}; func _(x []int) { f(x) }`, + {`package s3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]](x []T) {}; func _(x []int) { f(x) }`, `f`, []string{`int`, `chan<- int`}, `func(x []int)`, }, - {genericPkg + `s4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T) {}; func _(x []int) { f(x) }`, + {`package s4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T) {}; func _(x []int) { f(x) }`, `f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func(x []int)`, }, - {genericPkg + `t1; func f[T any, P interface{~*T}]() T { panic(0) }; func _() { _ = f[string] }`, + {`package t1; func f[T any, P interface{~*T}]() T { panic(0) }; func _() { _ = f[string] }`, `f`, []string{`string`, `*string`}, `func() string`, }, - {genericPkg + `t2; type C[T any] interface{~chan<- T}; func f[T any, P C[T]]() []T { return nil }; func _() { _ = f[int] }`, + {`package t2; func f[T any, P interface{~*T}]() T { panic(0) }; func _() { _ = (f[string]) }`, + `f`, + []string{`string`, `*string`}, + `func() string`, + }, + {`package t3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]]() []T { return nil }; func _() { _ = f[int] }`, `f`, []string{`int`, `chan<- int`}, `func() []int`, }, - {genericPkg + `t3; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = f[int] }`, + {`package t4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = f[int] }`, `f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func() []int`, }, + {`package i0; import "lib"; func _() { lib.F(42) }`, + `F`, + []string{`int`}, + `func(int)`, + }, + {`package type0; type T[P interface{~int}] struct{ x P }; var _ T[int]`, + `T`, + []string{`int`}, + `struct{x int}`, + }, + {`package type1; type T[P interface{~int}] struct{ x P }; var _ (T[int])`, + `T`, + []string{`int`}, + `struct{x int}`, + }, + {`package type2; type T[P interface{~int}] struct{ x P }; var _ T[(int)]`, + `T`, + []string{`int`}, + `struct{x int}`, + }, + {`package type3; type T[P1 interface{~[]P2}, P2 any] struct{ x P1; y P2 }; var _ T[[]int, int]`, + `T`, + []string{`[]int`, `int`}, + `struct{x []int; y int}`, + }, + {`package type4; import "lib"; var _ lib.T[int]`, + `T`, + []string{`int`}, + `[]int`, + }, } for _, test := range tests { - info := Info{} - info.Inferred = make(map[ast.Expr]Inferred) - name, err := mayTypecheck(t, "InferredInfo", test.src, &info) - if err != nil { - t.Errorf("package %s: %v", name, err) - continue - } + const lib = `package lib - // look for inferred type arguments and signature - var targs *TypeList - var sig *Signature - for call, inf := range info.Inferred { - var fun ast.Expr - switch x := call.(type) { - case *ast.CallExpr: - fun = x.Fun - case *ast.IndexExpr: - fun = x.X - default: - panic(fmt.Sprintf("unexpected call expression type %T", call)) +func F[P any](P) {} + +type T[P any] []P +` + + imports := make(testImporter) + conf := Config{Importer: imports} + instances := make(map[*ast.Ident]Instance) + uses := make(map[*ast.Ident]Object) + makePkg := func(src string) *Package { + f, err := parser.ParseFile(fset, "p.go", src, 0) + if err != nil { + t.Fatal(err) + } + pkg, err := conf.Check("", fset, []*ast.File{f}, &Info{Instances: instances, Uses: uses}) + if err != nil { + t.Fatal(err) } - if ExprString(fun) == test.fun { - targs = inf.TArgs - sig = inf.Sig + imports[pkg.Name()] = pkg + return pkg + } + makePkg(lib) + pkg := makePkg(test.src) + + // look for instance information + var targs []Type + var typ Type + for ident, inst := range instances { + if ExprString(ident) == test.name { + for i := 0; i < inst.TypeArgs.Len(); i++ { + targs = append(targs, inst.TypeArgs.At(i)) + } + typ = inst.Type + + // Check that we can find the corresponding parameterized type. + ptype := uses[ident].Type() + lister, _ := ptype.(interface{ TypeParams() *TypeParamList }) + if lister == nil || lister.TypeParams().Len() == 0 { + t.Errorf("package %s: info.Types[%v] = %v, want parameterized type", pkg.Name(), ident, ptype) + continue + } + + // Verify the invariant that re-instantiating the generic type with + // TypeArgs results in an equivalent type. + inst2, err := Instantiate(nil, ptype, targs, true) + if err != nil { + t.Errorf("Instantiate(%v, %v) failed: %v", ptype, targs, err) + } + if !Identical(inst.Type, inst2) { + t.Errorf("%v and %v are not identical", inst.Type, inst2) + } break } } if targs == nil { - t.Errorf("package %s: no inferred information found for %s", name, test.fun) + t.Errorf("package %s: no instance information found for %s", pkg.Name(), test.name) continue } // check that type arguments are correct - if targs.Len() != len(test.targs) { - t.Errorf("package %s: got %d type arguments; want %d", name, targs.Len(), len(test.targs)) + if len(targs) != len(test.targs) { + t.Errorf("package %s: got %d type arguments; want %d", pkg.Name(), len(targs), len(test.targs)) continue } - for i := 0; i < targs.Len(); i++ { - targ := targs.At(i) + for i, targ := range targs { if got := targ.String(); got != test.targs[i] { - t.Errorf("package %s, %d. type argument: got %s; want %s", name, i, got, test.targs[i]) + t.Errorf("package %s, %d. type argument: got %s; want %s", pkg.Name(), i, got, test.targs[i]) continue } } - // check that signature is correct - if got := sig.String(); got != test.sig { - t.Errorf("package %s: got %s; want %s", name, got, test.sig) + // check that the types match + if got := typ.Underlying().String(); got != test.typ { + t.Errorf("package %s: got %s; want %s", pkg.Name(), got, test.typ) } } } diff --git a/src/go/types/call.go b/src/go/types/call.go index 4d14e31730..cc2be4bec2 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -39,9 +39,6 @@ func (check *Checker) funcInst(x *operand, ix *typeparams.IndexExpr) { return } - // if we don't have enough type arguments, try type inference - inferred := false - if got < want { targs = check.infer(ix.Orig, sig.TypeParams().list(), targs, nil, nil, true) if targs == nil { @@ -51,7 +48,6 @@ func (check *Checker) funcInst(x *operand, ix *typeparams.IndexExpr) { return } got = len(targs) - inferred = true } assert(got == want) @@ -66,9 +62,7 @@ func (check *Checker) funcInst(x *operand, ix *typeparams.IndexExpr) { // instantiate function signature res := check.instantiate(x.Pos(), sig, targs, poslist).(*Signature) assert(res.TypeParams().Len() == 0) // signature is not generic anymore - if inferred { - check.recordInferred(ix.Orig, targs, res) - } + check.recordInstance(ix.Orig, targs, res) x.typ = res x.mode = value x.expr = ix.Orig @@ -354,7 +348,7 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type // compute result signature rsig = check.instantiate(call.Pos(), sig, targs, nil).(*Signature) assert(rsig.TypeParams().Len() == 0) // signature is not generic anymore - check.recordInferred(call, targs, rsig) + check.recordInstance(call.Fun, targs, rsig) // Optimization: Only if the parameter list was adjusted do we // need to compute it from the adjusted list; otherwise we can diff --git a/src/go/types/check.go b/src/go/types/check.go index 63f4cbd4a0..a55c01c17d 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -406,12 +406,38 @@ func (check *Checker) recordCommaOkTypes(x ast.Expr, a [2]Type) { } } -func (check *Checker) recordInferred(call ast.Expr, targs []Type, sig *Signature) { - assert(call != nil) - assert(sig != nil) - if m := check.Inferred; m != nil { - m[call] = Inferred{NewTypeList(targs), sig} +// recordInstance records instantiation information into check.Info, if the +// Instances map is non-nil. The given expr must be an ident, selector, or +// index (list) expr with ident or selector operand. +// +// TODO(rfindley): the expr parameter is fragile. See if we can access the +// instantiated identifier in some other way. +func (check *Checker) recordInstance(expr ast.Expr, targs []Type, typ Type) { + ident := instantiatedIdent(expr) + assert(ident != nil) + assert(typ != nil) + if m := check.Instances; m != nil { + m[ident] = Instance{NewTypeList(targs), typ} + } +} + +func instantiatedIdent(expr ast.Expr) *ast.Ident { + var selOrIdent ast.Expr + switch e := expr.(type) { + case *ast.IndexExpr: + selOrIdent = e.X + case *ast.IndexListExpr: + selOrIdent = e.X + case *ast.SelectorExpr, *ast.Ident: + selOrIdent = e + } + switch x := selOrIdent.(type) { + case *ast.Ident: + return x + case *ast.SelectorExpr: + return x.Sel } + panic("instantiated ident not found") } func (check *Checker) recordDef(id *ast.Ident, obj Object) { diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 0143f53009..a1b8bae3d5 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -398,6 +398,7 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named typ := check.instantiate(x.Pos(), base, targs, posList) def.setUnderlying(typ) + check.recordInstance(x, targs, typ) // make sure we check instantiation works at least once // and that the resulting type is valid -- GitLab From fdf2053d52e122f3e8cddccdf742f94333df09a8 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 14 Sep 2021 22:09:54 -0400 Subject: [PATCH 1236/2500] go/types: remove the report parameter from infer and inferB The report parameter is now always true, so we can simplify these functions. Change-Id: I851adad3011beef9c83172210ff5e93c624372cc Reviewed-on: https://go-review.googlesource.com/c/go/+/350049 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/call.go | 4 ++-- src/go/types/infer.go | 23 +++++++---------------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/src/go/types/call.go b/src/go/types/call.go index cc2be4bec2..2fa29dd439 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -40,7 +40,7 @@ func (check *Checker) funcInst(x *operand, ix *typeparams.IndexExpr) { } if got < want { - targs = check.infer(ix.Orig, sig.TypeParams().list(), targs, nil, nil, true) + targs = check.infer(ix.Orig, sig.TypeParams().list(), targs, nil, nil) if targs == nil { // error was already reported x.mode = invalid @@ -340,7 +340,7 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type } // TODO(gri) provide position information for targs so we can feed // it to the instantiate call for better error reporting - targs := check.infer(call, sig.TypeParams().list(), targs, sigParams, args, true) + targs := check.infer(call, sig.TypeParams().list(), targs, sigParams, args) if targs == nil { return // error already reported } diff --git a/src/go/types/infer.go b/src/go/types/infer.go index 18c5119177..1c4915571d 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -27,9 +27,7 @@ import ( // 3) Infer type arguments from untyped function arguments. // // Constraint type inference is used after each step to expand the set of type arguments. -// -// TODO(rfindley): remove the report parameter: is no longer needed. -func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, params *Tuple, args []*operand, report bool) (result []Type) { +func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, params *Tuple, args []*operand) (result []Type) { if debug { defer func() { assert(result == nil || len(result) == len(tparams)) @@ -61,7 +59,7 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, // If we have type arguments, see how far we get with constraint type inference. if len(targs) > 0 { var index int - targs, index = check.inferB(tparams, targs, report) + targs, index = check.inferB(tparams, targs) if targs == nil || index < 0 { return targs } @@ -106,9 +104,6 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, } errorf := func(kind string, tpar, targ Type, arg *operand) { - if !report { - return - } // provide a better error message if we can targs, index := u.x.types() if index == 0 { @@ -175,7 +170,7 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, // See how far we get with constraint type inference. // Note that even if we don't have any type arguments, constraint type inference // may produce results for constraints that explicitly specify a type. - targs, index = check.inferB(tparams, targs, report) + targs, index = check.inferB(tparams, targs) if targs == nil || index < 0 { return targs } @@ -211,7 +206,7 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, } // Again, follow up with constraint type inference. - targs, index = check.inferB(tparams, targs, report) + targs, index = check.inferB(tparams, targs) if targs == nil || index < 0 { return targs } @@ -219,9 +214,7 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, // At least one type argument couldn't be inferred. assert(index >= 0 && targs[index] == nil) tpar := tparams[index] - if report { - check.errorf(posn, _Todo, "cannot infer %s (%v) (%v)", tpar.obj.name, tpar.obj.pos, targs) - } + check.errorf(posn, _Todo, "cannot infer %s (%v) (%v)", tpar.obj.name, tpar.obj.pos, targs) return nil } @@ -362,7 +355,7 @@ func (w *tpWalker) isParameterizedTypeList(list []Type) bool { // first type argument in that list that couldn't be inferred (and thus is nil). If all // type arguments were inferred successfully, index is < 0. The number of type arguments // provided may be less than the number of type parameters, but there must be at least one. -func (check *Checker) inferB(tparams []*TypeParam, targs []Type, report bool) (types []Type, index int) { +func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type, index int) { assert(len(tparams) >= len(targs) && len(targs) > 0) // Setup bidirectional unification between those structural bounds @@ -384,9 +377,7 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type, report bool) (t sbound := typ.structuralType() if sbound != nil { if !u.unify(typ, sbound) { - if report { - check.errorf(tpar.obj, _Todo, "%s does not match %s", tpar.obj, sbound) - } + check.errorf(tpar.obj, _Todo, "%s does not match %s", tpar.obj, sbound) return nil, 0 } } -- GitLab From 2f70ce36d79ee94855daf7c6feb9a1296f9adfac Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Mon, 20 Sep 2021 16:29:50 -0700 Subject: [PATCH 1237/2500] internal/fuzz: temporarily work around test failures after dev.fuzz merge - Skip test_fuzz_cache and test_fuzz_seed_corpus on 386. - Skip worker benchmarks when race mode is enabled. - Stub coverage function on platforms we haven't tested yet. It's causing package initialization to panic on aix/ppc64. For #48504 Change-Id: I79318b52b11a33fca66476b5050445d07422ef36 Reviewed-on: https://go-review.googlesource.com/c/go/+/351117 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- .../go/testdata/script/test_fuzz_cache.txt | 3 ++ .../testdata/script/test_fuzz_seed_corpus.txt | 3 ++ src/internal/fuzz/counters_supported.go | 29 +++++++++++++++++++ src/internal/fuzz/counters_unsupported.go | 16 ++++++++++ src/internal/fuzz/coverage.go | 19 ------------ src/internal/fuzz/worker_test.go | 10 +++++++ 6 files changed, 61 insertions(+), 19 deletions(-) create mode 100644 src/internal/fuzz/counters_supported.go create mode 100644 src/internal/fuzz/counters_unsupported.go diff --git a/src/cmd/go/testdata/script/test_fuzz_cache.txt b/src/cmd/go/testdata/script/test_fuzz_cache.txt index 10e4c2926f..8bcf2be61e 100644 --- a/src/cmd/go/testdata/script/test_fuzz_cache.txt +++ b/src/cmd/go/testdata/script/test_fuzz_cache.txt @@ -1,6 +1,9 @@ # TODO(jayconrod): support shared memory on more platforms. [!darwin] [!linux] [!windows] skip +# TODO(#48504): fix and re-enable. +[linux] [386] skip + [short] skip env GOCACHE=$WORK/cache diff --git a/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt b/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt index 016b101d72..f810ad48d9 100644 --- a/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt +++ b/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt @@ -1,6 +1,9 @@ # TODO(jayconrod): support shared memory on more platforms. [!darwin] [!linux] [!windows] skip +# TODO(#48504): fix and re-enable. +[linux] [386] skip + [short] skip env GOCACHE=$WORK/cache diff --git a/src/internal/fuzz/counters_supported.go b/src/internal/fuzz/counters_supported.go new file mode 100644 index 0000000000..7ef553aaf2 --- /dev/null +++ b/src/internal/fuzz/counters_supported.go @@ -0,0 +1,29 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (darwin || linux || windows || freebsd) && (amd64 || arm64) + +package fuzz + +import ( + "internal/unsafeheader" + "unsafe" +) + +// coverage returns a []byte containing unique 8-bit counters for each edge of +// the instrumented source code. This coverage data will only be generated if +// `-d=libfuzzer` is set at build time. This can be used to understand the code +// coverage of a test execution. +func coverage() []byte { + addr := unsafe.Pointer(&_counters) + size := uintptr(unsafe.Pointer(&_ecounters)) - uintptr(addr) + + var res []byte + *(*unsafeheader.Slice)(unsafe.Pointer(&res)) = unsafeheader.Slice{ + Data: addr, + Len: int(size), + Cap: int(size), + } + return res +} diff --git a/src/internal/fuzz/counters_unsupported.go b/src/internal/fuzz/counters_unsupported.go new file mode 100644 index 0000000000..743ef45a66 --- /dev/null +++ b/src/internal/fuzz/counters_unsupported.go @@ -0,0 +1,16 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !((darwin || linux || windows || freebsd) && (amd64 || arm64)) + +package fuzz + +// TODO(#48504): re-enable on platforms where instrumentation works. +// This was disabled due to an init failure on aix_ppc64. + +// coverage returns a []byte containing unique 8-bit counters for each edge of +// the instrumented source code. This coverage data will only be generated if +// `-d=libfuzzer` is set at build time. This can be used to understand the code +// coverage of a test execution. +func coverage() []byte { return nil } diff --git a/src/internal/fuzz/coverage.go b/src/internal/fuzz/coverage.go index 71d0132e21..3dee73b81c 100644 --- a/src/internal/fuzz/coverage.go +++ b/src/internal/fuzz/coverage.go @@ -6,28 +6,9 @@ package fuzz import ( "fmt" - "internal/unsafeheader" "math/bits" - "unsafe" ) -// coverage returns a []byte containing unique 8-bit counters for each edge of -// the instrumented source code. This coverage data will only be generated if -// `-d=libfuzzer` is set at build time. This can be used to understand the code -// coverage of a test execution. -func coverage() []byte { - addr := unsafe.Pointer(&_counters) - size := uintptr(unsafe.Pointer(&_ecounters)) - uintptr(addr) - - var res []byte - *(*unsafeheader.Slice)(unsafe.Pointer(&res)) = unsafeheader.Slice{ - Data: addr, - Len: int(size), - Cap: int(size), - } - return res -} - // ResetCovereage sets all of the counters for each edge of the instrumented // source code to 0. func ResetCoverage() { diff --git a/src/internal/fuzz/worker_test.go b/src/internal/fuzz/worker_test.go index 2369b4ce3f..e32770b02b 100644 --- a/src/internal/fuzz/worker_test.go +++ b/src/internal/fuzz/worker_test.go @@ -8,6 +8,7 @@ import ( "context" "flag" "fmt" + "internal/race" "io" "os" "os/signal" @@ -27,6 +28,9 @@ func TestMain(m *testing.M) { } func BenchmarkWorkerFuzzOverhead(b *testing.B) { + if race.Enabled { + b.Skip("TODO(48504): fix and re-enable") + } origEnv := os.Getenv("GODEBUG") defer func() { os.Setenv("GODEBUG", origEnv) }() os.Setenv("GODEBUG", fmt.Sprintf("%s,fuzzseed=123", origEnv)) @@ -65,6 +69,9 @@ func BenchmarkWorkerFuzzOverhead(b *testing.B) { // BenchmarkWorkerPing acts as the coordinator and measures the time it takes // a worker to respond to N pings. This is a rough measure of our RPC latency. func BenchmarkWorkerPing(b *testing.B) { + if race.Enabled { + b.Skip("TODO(48504): fix and re-enable") + } b.SetParallelism(1) w := newWorkerForTest(b) for i := 0; i < b.N; i++ { @@ -77,6 +84,9 @@ func BenchmarkWorkerPing(b *testing.B) { // BenchmarkWorkerFuzz acts as the coordinator and measures the time it takes // a worker to mutate a given input and call a trivial fuzz function N times. func BenchmarkWorkerFuzz(b *testing.B) { + if race.Enabled { + b.Skip("TODO(48504): fix and re-enable") + } b.SetParallelism(1) w := newWorkerForTest(b) entry := CorpusEntry{Values: []interface{}{[]byte(nil)}} -- GitLab From 1367a60b064ea9ca2ba35affddfcfc1a3c3a6fbc Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 20 Sep 2021 20:28:01 -0700 Subject: [PATCH 1238/2500] cmd/compile/internal/types2: remove report parameter from infer and inferB This is a clean port of CL 350049 from go/types to types2. Change-Id: Ifc8551a772535f7b8e943bfbd9febbb78333fa68 Reviewed-on: https://go-review.googlesource.com/c/go/+/351169 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/call.go | 4 ++-- src/cmd/compile/internal/types2/infer.go | 23 +++++++---------------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 0480b7bef4..aaef97f58a 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -41,7 +41,7 @@ func (check *Checker) funcInst(x *operand, inst *syntax.IndexExpr) { // if we don't have enough type arguments, try type inference inferred := false if got < want { - targs = check.infer(inst.Pos(), sig.TypeParams().list(), targs, nil, nil, true) + targs = check.infer(inst.Pos(), sig.TypeParams().list(), targs, nil, nil) if targs == nil { // error was already reported x.mode = invalid @@ -338,7 +338,7 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T } // TODO(gri) provide position information for targs so we can feed // it to the instantiate call for better error reporting - targs := check.infer(call.Pos(), sig.TypeParams().list(), targs, sigParams, args, true) + targs := check.infer(call.Pos(), sig.TypeParams().list(), targs, sigParams, args) if targs == nil { return // error already reported } diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index b98c8211df..914ee9ea5d 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -28,9 +28,7 @@ const useConstraintTypeInference = true // 3) Infer type arguments from untyped function arguments. // // Constraint type inference is used after each step to expand the set of type arguments. -// -// TODO(gri): remove the report parameter: is no longer needed. -func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, params *Tuple, args []*operand, report bool) (result []Type) { +func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, params *Tuple, args []*operand) (result []Type) { if debug { defer func() { assert(result == nil || len(result) == len(tparams)) @@ -62,7 +60,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, // If we have type arguments, see how far we get with constraint type inference. if len(targs) > 0 && useConstraintTypeInference { var index int - targs, index = check.inferB(tparams, targs, report) + targs, index = check.inferB(tparams, targs) if targs == nil || index < 0 { return targs } @@ -107,9 +105,6 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, } errorf := func(kind string, tpar, targ Type, arg *operand) { - if !report { - return - } // provide a better error message if we can targs, index := u.x.types() if index == 0 { @@ -176,7 +171,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, // Note that even if we don't have any type arguments, constraint type inference // may produce results for constraints that explicitly specify a type. if useConstraintTypeInference { - targs, index = check.inferB(tparams, targs, report) + targs, index = check.inferB(tparams, targs) if targs == nil || index < 0 { return targs } @@ -214,7 +209,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, // Again, follow up with constraint type inference. if useConstraintTypeInference { - targs, index = check.inferB(tparams, targs, report) + targs, index = check.inferB(tparams, targs) if targs == nil || index < 0 { return targs } @@ -223,9 +218,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, // At least one type argument couldn't be inferred. assert(targs != nil && index >= 0 && targs[index] == nil) tpar := tparams[index] - if report { - check.errorf(pos, "cannot infer %s (%s) (%s)", tpar.obj.name, tpar.obj.pos, targs) - } + check.errorf(pos, "cannot infer %s (%s) (%s)", tpar.obj.name, tpar.obj.pos, targs) return nil } @@ -367,7 +360,7 @@ func (w *tpWalker) isParameterizedTypeList(list []Type) bool { // first type argument in that list that couldn't be inferred (and thus is nil). If all // type arguments were inferred successfully, index is < 0. The number of type arguments // provided may be less than the number of type parameters, but there must be at least one. -func (check *Checker) inferB(tparams []*TypeParam, targs []Type, report bool) (types []Type, index int) { +func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type, index int) { assert(len(tparams) >= len(targs) && len(targs) > 0) // Setup bidirectional unification between those structural bounds @@ -389,9 +382,7 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type, report bool) (t sbound := typ.structuralType() if sbound != nil { if !u.unify(typ, sbound) { - if report { - check.errorf(tpar.obj, "%s does not match %s", tpar.obj, sbound) - } + check.errorf(tpar.obj, "%s does not match %s", tpar.obj, sbound) return nil, 0 } } -- GitLab From 7dfe686a91a60a135deb2b64d28bcc010ba90b15 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 20 Sep 2021 20:34:17 -0700 Subject: [PATCH 1239/2500] cmd/compile/internal/types2: export Named.Orig as Named.Origin This is a slightly adjusted port of CL 350996 from go/types to types2. Change-Id: I8f5902ecb20a4b4d2a5ef0d3641d857bc3a618e2 Reviewed-on: https://go-review.googlesource.com/c/go/+/351170 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/noder/types.go | 2 +- src/cmd/compile/internal/noder/writer.go | 2 +- src/cmd/compile/internal/types2/named.go | 10 ++++------ 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index 99917ad974..e1cfe4a9d8 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -115,7 +115,7 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { // Make sure the base generic type exists in type1 (it may // not yet if we are referecing an imported generic type, as // opposed to a generic type declared in this package). - _ = g.obj(typ.Orig().Obj()) + _ = g.obj(typ.Origin().Obj()) // Create a forwarding type first and put it in the g.typs // map, in order to deal with recursive generic types diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 6a66bea239..9edf5fc97a 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -296,7 +296,7 @@ func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo { // TODO(mdempsky): Why do we need to loop here? orig := typ for orig.TypeArgs() != nil { - orig = orig.Orig() + orig = orig.Origin() } w.code(typeNamed) diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index bc4ac87b9d..36a8b88f25 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -87,13 +87,11 @@ func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tpar // Obj returns the type name for the declaration defining the named type t. For // instantiated types, this is the type name of the base type. -func (t *Named) Obj() *TypeName { - return t.orig.obj // for non-instances this is the same as t.obj -} +func (t *Named) Obj() *TypeName { return t.orig.obj } // for non-instances this is the same as t.obj -// Orig returns the original generic type an instantiated type is derived from. -// If t is not an instantiated type, the result is t. -func (t *Named) Orig() *Named { return t.orig } +// Origin returns the parameterized type from which the named type t is +// instantiated. If t is not an instantiated type, the result is t. +func (t *Named) Origin() *Named { return t.orig } // TODO(gri) Come up with a better representation and API to distinguish // between parameterized instantiated and non-instantiated types. -- GitLab From ebc6ce40ceb587af54dfcac910931606fe2d9a66 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 20 Sep 2021 20:45:09 -0700 Subject: [PATCH 1240/2500] go/types: return typeHash value without blanks This is an adjusted port of CL 349990 from types2 to go/types: typeHash remains unexported but is adjusted to not contain blanks. Change-Id: I37fa826b8a185e3c275ae9bea29a3b0ed386d2c9 Reviewed-on: https://go-review.googlesource.com/c/go/+/351171 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/go/types/environment.go | 5 ++-- src/go/types/typestring.go | 46 ++++++++++++++++++++++++++----------- 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/go/types/environment.go b/src/go/types/environment.go index 61fc3c5348..b818f81564 100644 --- a/src/go/types/environment.go +++ b/src/go/types/environment.go @@ -6,6 +6,7 @@ package types import ( "bytes" + "strings" "sync" ) @@ -32,7 +33,7 @@ func NewEnvironment() *Environment { // typeHash returns a string representation of typ, which can be used as an exact // type hash: types that are identical produce identical string representations. // If typ is a *Named type and targs is not empty, typ is printed as if it were -// instantiated with targs. +// instantiated with targs. The result is guaranteed to not contain blanks (" "). func (env *Environment) typeHash(typ Type, targs []Type) string { assert(env != nil) assert(typ != nil) @@ -50,7 +51,7 @@ func (env *Environment) typeHash(typ Type, targs []Type) string { h.typ(typ) } - return buf.String() + return strings.Replace(buf.String(), " ", "#", -1) // ReplaceAll is not available in Go1.4 } // typeForHash returns the recorded type for the type hash h, if it exists. diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index eadc50a754..e5dafc2e0d 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -8,7 +8,6 @@ package types import ( "bytes" - "fmt" "go/token" "strconv" "unicode/utf8" @@ -81,14 +80,29 @@ func newTypeHasher(buf *bytes.Buffer, env *Environment) *typeWriter { return &typeWriter{buf, make(map[Type]bool), nil, env} } -func (w *typeWriter) byte(b byte) { w.buf.WriteByte(b) } -func (w *typeWriter) string(s string) { w.buf.WriteString(s) } -func (w *typeWriter) writef(format string, args ...interface{}) { fmt.Fprintf(w.buf, format, args...) } +func (w *typeWriter) byte(b byte) { + if w.env != nil { + if b == ' ' { + b = '#' + } + w.buf.WriteByte(b) + return + } + w.buf.WriteByte(b) + if b == ',' || b == ';' { + w.buf.WriteByte(' ') + } +} + +func (w *typeWriter) string(s string) { + w.buf.WriteString(s) +} + func (w *typeWriter) error(msg string) { if w.env != nil { panic(msg) } - w.string("<" + msg + ">") + w.buf.WriteString("<" + msg + ">") } func (w *typeWriter) typ(typ Type) { @@ -115,7 +129,9 @@ func (w *typeWriter) typ(typ Type) { w.string(t.name) case *Array: - w.writef("[%d]", t.len) + w.byte('[') + w.string(strconv.FormatInt(t.len, 10)) + w.byte(']') w.typ(t.elem) case *Slice: @@ -126,7 +142,7 @@ func (w *typeWriter) typ(typ Type) { w.string("struct{") for i, f := range t.fields { if i > 0 { - w.string("; ") + w.byte(';') } // This doesn't do the right thing for embedded type // aliases where we should print the alias name, not @@ -137,7 +153,11 @@ func (w *typeWriter) typ(typ Type) { } w.typ(f.typ) if tag := t.Tag(i); tag != "" { - w.writef(" %q", tag) + w.byte(' ') + // TODO(rfindley) If tag contains blanks, replacing them with '#' + // in Environment.TypeHash may produce another tag + // accidentally. + w.string(strconv.Quote(tag)) } } w.byte('}') @@ -175,7 +195,7 @@ func (w *typeWriter) typ(typ Type) { first := true for _, m := range t.methods { if !first { - w.string("; ") + w.byte(';') } first = false w.string(m.name) @@ -183,7 +203,7 @@ func (w *typeWriter) typ(typ Type) { } for _, typ := range t.embeddeds { if !first { - w.string("; ") + w.byte(';') } first = false w.typ(typ) @@ -270,7 +290,7 @@ func (w *typeWriter) typeList(list []Type) { w.byte('[') for i, typ := range list { if i > 0 { - w.string(", ") + w.byte(',') } w.typ(typ) } @@ -294,7 +314,7 @@ func (w *typeWriter) tParamList(list []*TypeParam) { w.byte(' ') w.typ(prev) } - w.string(", ") + w.byte(',') } prev = tpar.bound w.typ(tpar) @@ -318,7 +338,7 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) { if tup != nil { for i, v := range tup.vars { if i > 0 { - w.string(", ") + w.byte(',') } // parameter names are ignored for type identity and thus type hashes if w.env == nil && v.name != "" { -- GitLab From 2fc7df93fe8e540ca101da33fe9157dfa7bdf6aa Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 21 Sep 2021 10:20:02 -0700 Subject: [PATCH 1241/2500] cmd/compile/internal/importer: remove // UNREVIEWED comments from tests The importer tests are exact copies of the corresponding test files in $GOROOT/src/go/internal/gcimporter/testdata/. With these changes, diff applied recursively doesn't show any differences anymore among the existing files between the directories src/cmd/compile/internal/importer/testdata src/go/internal/gcimporter/testdata Change-Id: I1fdd70a3d4d5e55f1fc580892d1d38cabbdab81b Reviewed-on: https://go-review.googlesource.com/c/go/+/351309 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/importer/testdata/a.go | 1 - src/cmd/compile/internal/importer/testdata/b.go | 1 - src/cmd/compile/internal/importer/testdata/exports.go | 1 - src/cmd/compile/internal/importer/testdata/issue15920.go | 1 - src/cmd/compile/internal/importer/testdata/issue20046.go | 1 - src/cmd/compile/internal/importer/testdata/issue25301.go | 1 - src/cmd/compile/internal/importer/testdata/issue25596.go | 1 - src/cmd/compile/internal/importer/testdata/p.go | 1 - src/cmd/compile/internal/importer/testdata/versions/test.go | 1 - 9 files changed, 9 deletions(-) diff --git a/src/cmd/compile/internal/importer/testdata/a.go b/src/cmd/compile/internal/importer/testdata/a.go index 06dafee98c..56e4292cda 100644 --- a/src/cmd/compile/internal/importer/testdata/a.go +++ b/src/cmd/compile/internal/importer/testdata/a.go @@ -1,4 +1,3 @@ -// UNREVIEWED // Copyright 2016 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/src/cmd/compile/internal/importer/testdata/b.go b/src/cmd/compile/internal/importer/testdata/b.go index a601dbccc5..4196678200 100644 --- a/src/cmd/compile/internal/importer/testdata/b.go +++ b/src/cmd/compile/internal/importer/testdata/b.go @@ -1,4 +1,3 @@ -// UNREVIEWED // Copyright 2016 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/src/cmd/compile/internal/importer/testdata/exports.go b/src/cmd/compile/internal/importer/testdata/exports.go index 2a720fd2c1..8ba3242102 100644 --- a/src/cmd/compile/internal/importer/testdata/exports.go +++ b/src/cmd/compile/internal/importer/testdata/exports.go @@ -1,4 +1,3 @@ -// UNREVIEWED // Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/src/cmd/compile/internal/importer/testdata/issue15920.go b/src/cmd/compile/internal/importer/testdata/issue15920.go index b402026162..c70f7d8267 100644 --- a/src/cmd/compile/internal/importer/testdata/issue15920.go +++ b/src/cmd/compile/internal/importer/testdata/issue15920.go @@ -1,4 +1,3 @@ -// UNREVIEWED // Copyright 2016 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/src/cmd/compile/internal/importer/testdata/issue20046.go b/src/cmd/compile/internal/importer/testdata/issue20046.go index e412f353ad..c63ee821c9 100644 --- a/src/cmd/compile/internal/importer/testdata/issue20046.go +++ b/src/cmd/compile/internal/importer/testdata/issue20046.go @@ -1,4 +1,3 @@ -// UNREVIEWED // Copyright 2017 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/src/cmd/compile/internal/importer/testdata/issue25301.go b/src/cmd/compile/internal/importer/testdata/issue25301.go index a9dc1d7f08..e3dc98b4e1 100644 --- a/src/cmd/compile/internal/importer/testdata/issue25301.go +++ b/src/cmd/compile/internal/importer/testdata/issue25301.go @@ -1,4 +1,3 @@ -// UNREVIEWED // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/src/cmd/compile/internal/importer/testdata/issue25596.go b/src/cmd/compile/internal/importer/testdata/issue25596.go index 95bef42280..8923373e5f 100644 --- a/src/cmd/compile/internal/importer/testdata/issue25596.go +++ b/src/cmd/compile/internal/importer/testdata/issue25596.go @@ -1,4 +1,3 @@ -// UNREVIEWED // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/src/cmd/compile/internal/importer/testdata/p.go b/src/cmd/compile/internal/importer/testdata/p.go index 34a20eaa14..9e2e705765 100644 --- a/src/cmd/compile/internal/importer/testdata/p.go +++ b/src/cmd/compile/internal/importer/testdata/p.go @@ -1,4 +1,3 @@ -// UNREVIEWED // Copyright 2016 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/src/cmd/compile/internal/importer/testdata/versions/test.go b/src/cmd/compile/internal/importer/testdata/versions/test.go index 2f8eb5ced0..227fc09251 100644 --- a/src/cmd/compile/internal/importer/testdata/versions/test.go +++ b/src/cmd/compile/internal/importer/testdata/versions/test.go @@ -1,4 +1,3 @@ -// UNREVIEWED // Copyright 2016 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -- GitLab From 5efa8ff340d9fcc2dfc7a5136f1ed4067eb5e91e Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 21 Sep 2021 10:54:08 -0700 Subject: [PATCH 1242/2500] cmd/compile/internal/types2: make ptrRecv a method hasPtrRecv of Func Reading the Func.hasPtrRecv field directly (without consulting a possibly existing signature) caused some issues in an earlier CL. The function ptrRecv (in lookup.go) does the right thing but is not easily discoverable. Rename ptrRecv to hasPtrRecv and make it a method of Func; rename Func.hasPtrRecv field to Func.hasPtrRecv_ to avoid name collisions. Make it clear in field comment that it must not be read through the hasPtrRecv method. Change-Id: Ida9856c4789e499538eb34377be781655958fd5b Reviewed-on: https://go-review.googlesource.com/c/go/+/351310 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/lookup.go | 21 +------------------ src/cmd/compile/internal/types2/named.go | 4 ++-- src/cmd/compile/internal/types2/object.go | 23 +++++++++++++++++++-- src/cmd/compile/internal/types2/resolver.go | 2 +- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index eb460ca200..e0fd74482a 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -216,7 +216,7 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o // is shorthand for (&x).m()". if f, _ := obj.(*Func); f != nil { // determine if method has a pointer receiver - hasPtrRecv := tpar == nil && ptrRecv(f) + hasPtrRecv := tpar == nil && f.hasPtrRecv() if hasPtrRecv && !indirect && !addressable { return nil, nil, true // pointer/addressable receiver required } @@ -474,22 +474,3 @@ func lookupMethod(methods []*Func, pkg *Package, name string) (int, *Func) { } return -1, nil } - -// ptrRecv reports whether the receiver is of the form *T. -func ptrRecv(f *Func) bool { - // If a method's receiver type is set, use that as the source of truth for the receiver. - // Caution: Checker.funcDecl (decl.go) marks a function by setting its type to an empty - // signature. We may reach here before the signature is fully set up: we must explicitly - // check if the receiver is set (we cannot just look for non-nil f.typ). - if sig, _ := f.typ.(*Signature); sig != nil && sig.recv != nil { - _, isPtr := deref(sig.recv.typ) - return isPtr - } - - // If a method's type is not set it may be a method/function that is: - // 1) client-supplied (via NewFunc with no signature), or - // 2) internally created but not yet type-checked. - // For case 1) we can't do anything; the client must know what they are doing. - // For case 2) we can use the information gathered by the resolver. - return f.hasPtrRecv -} diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index 36a8b88f25..1db993afc9 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -255,7 +255,7 @@ func expandNamed(env *Environment, n *Named, instPos syntax.Pos) (tparams *TypeP // During type checking origm may not have a fully set up type, so defer // instantiation of its signature until later. m := NewFunc(origm.pos, origm.pkg, origm.name, nil) - m.hasPtrRecv = ptrRecv(origm) + m.hasPtrRecv_ = origm.hasPtrRecv() // Setting instRecv here allows us to complete later (we need the // instRecv to get targs and the original method). m.instRecv = n @@ -314,7 +314,7 @@ func (check *Checker) completeMethod(env *Environment, m *Func) { sig = © } var rtyp Type - if ptrRecv(m) { + if m.hasPtrRecv() { rtyp = NewPointer(rbase) } else { rtyp = rbase diff --git a/src/cmd/compile/internal/types2/object.go b/src/cmd/compile/internal/types2/object.go index f44e1a9353..2e1cd7bff1 100644 --- a/src/cmd/compile/internal/types2/object.go +++ b/src/cmd/compile/internal/types2/object.go @@ -363,8 +363,8 @@ func (*Var) isDependency() {} // a variable may be a dependency of an initializa // An abstract method may belong to many interfaces due to embedding. type Func struct { object - instRecv *Named // if non-nil, the receiver type for an incomplete instance method - hasPtrRecv bool // only valid for methods that don't have a type yet + instRecv *Named // if non-nil, the receiver type for an incomplete instance method + hasPtrRecv_ bool // only valid for methods that don't have a type yet; use hasPtrRecv() to read } // NewFunc returns a new function with the given signature, representing @@ -389,6 +389,25 @@ func (obj *Func) FullName() string { // Scope returns the scope of the function's body block. func (obj *Func) Scope() *Scope { return obj.typ.(*Signature).scope } +// hasPtrRecv reports whether the receiver is of the form *T for the given method obj. +func (obj *Func) hasPtrRecv() bool { + // If a method's receiver type is set, use that as the source of truth for the receiver. + // Caution: Checker.funcDecl (decl.go) marks a function by setting its type to an empty + // signature. We may reach here before the signature is fully set up: we must explicitly + // check if the receiver is set (we cannot just look for non-nil obj.typ). + if sig, _ := obj.typ.(*Signature); sig != nil && sig.recv != nil { + _, isPtr := deref(sig.recv.typ) + return isPtr + } + + // If a method's type is not set it may be a method/function that is: + // 1) client-supplied (via NewFunc with no signature), or + // 2) internally created but not yet type-checked. + // For case 1) we can't do anything; the client must know what they are doing. + // For case 2) we can use the information gathered by the resolver. + return obj.hasPtrRecv_ +} + func (*Func) isDependency() {} // a function may be a dependency of an initialization expression // A Label represents a declared label. diff --git a/src/cmd/compile/internal/types2/resolver.go b/src/cmd/compile/internal/types2/resolver.go index 34fbc3d41b..a8cb244c55 100644 --- a/src/cmd/compile/internal/types2/resolver.go +++ b/src/cmd/compile/internal/types2/resolver.go @@ -509,7 +509,7 @@ func (check *Checker) collectObjects() { // Determine the receiver base type and associate m with it. ptr, base := check.resolveBaseTypeName(m.ptr, m.recv) if base != nil { - m.obj.hasPtrRecv = ptr + m.obj.hasPtrRecv_ = ptr check.methods[base] = append(check.methods[base], m.obj) } } -- GitLab From f6f6621312263e1e3ea2928bdccc967f0f977865 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 21 Sep 2021 11:25:59 -0700 Subject: [PATCH 1243/2500] go/types: make ptrRecv a method hasPtrRecv of Func This is a clean port of CL 351310 from types2 to go/types with the necessary changes to methodset.go which doesn't exist in types2. Change-Id: Ifdac820d3be14c7bfa778b7bca3f6ba58d220b2e Reviewed-on: https://go-review.googlesource.com/c/go/+/351311 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/go/types/lookup.go | 2 +- src/go/types/methodset.go | 23 ++--------------------- src/go/types/named.go | 4 ++-- src/go/types/object.go | 23 +++++++++++++++++++++-- src/go/types/resolver.go | 2 +- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index a270159499..afb1215af2 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -212,7 +212,7 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o // is shorthand for (&x).m()". if f, _ := obj.(*Func); f != nil { // determine if method has a pointer receiver - hasPtrRecv := tpar == nil && ptrRecv(f) + hasPtrRecv := tpar == nil && f.hasPtrRecv() if hasPtrRecv && !indirect && !addressable { return nil, nil, true // pointer/addressable receiver required } diff --git a/src/go/types/methodset.go b/src/go/types/methodset.go index 1462601d58..89e4b57627 100644 --- a/src/go/types/methodset.go +++ b/src/go/types/methodset.go @@ -232,10 +232,10 @@ func (s methodSet) add(list []*Func, index []int, indirect bool, multiples bool) // if f is not in the set, add it if !multiples { // TODO(gri) A found method may not be added because it's not in the method set - // (!indirect && ptrRecv(f)). A 2nd method on the same level may be in the method + // (!indirect && f.hasPtrRecv()). A 2nd method on the same level may be in the method // set and may not collide with the first one, thus leading to a false positive. // Is that possible? Investigate. - if _, found := s[key]; !found && (indirect || !ptrRecv(f)) { + if _, found := s[key]; !found && (indirect || !f.hasPtrRecv()) { s[key] = &Selection{MethodVal, nil, f, concat(index, i), indirect} continue } @@ -244,22 +244,3 @@ func (s methodSet) add(list []*Func, index []int, indirect bool, multiples bool) } return s } - -// ptrRecv reports whether the receiver is of the form *T. -func ptrRecv(f *Func) bool { - // If a method's receiver type is set, use that as the source of truth for the receiver. - // Caution: Checker.funcDecl (decl.go) marks a function by setting its type to an empty - // signature. We may reach here before the signature is fully set up: we must explicitly - // check if the receiver is set (we cannot just look for non-nil f.typ). - if sig, _ := f.typ.(*Signature); sig != nil && sig.recv != nil { - _, isPtr := deref(sig.recv.typ) - return isPtr - } - - // If a method's type is not set it may be a method/function that is: - // 1) client-supplied (via NewFunc with no signature), or - // 2) internally created but not yet type-checked. - // For case 1) we can't do anything; the client must know what they are doing. - // For case 2) we can use the information gathered by the resolver. - return f.hasPtrRecv -} diff --git a/src/go/types/named.go b/src/go/types/named.go index 1815aad014..07c837d14a 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -257,7 +257,7 @@ func expandNamed(env *Environment, n *Named, instPos token.Pos) (tparams *TypePa // During type checking origm may not have a fully set up type, so defer // instantiation of its signature until later. m := NewFunc(origm.pos, origm.pkg, origm.name, nil) - m.hasPtrRecv = ptrRecv(origm) + m.hasPtrRecv_ = origm.hasPtrRecv() // Setting instRecv here allows us to complete later (we need the // instRecv to get targs and the original method). m.instRecv = n @@ -316,7 +316,7 @@ func (check *Checker) completeMethod(env *Environment, m *Func) { sig = © } var rtyp Type - if ptrRecv(m) { + if m.hasPtrRecv() { rtyp = NewPointer(rbase) } else { rtyp = rbase diff --git a/src/go/types/object.go b/src/go/types/object.go index 454b714458..19e7fddeb6 100644 --- a/src/go/types/object.go +++ b/src/go/types/object.go @@ -317,8 +317,8 @@ func (*Var) isDependency() {} // a variable may be a dependency of an initializa // An abstract method may belong to many interfaces due to embedding. type Func struct { object - instRecv *Named // if non-nil, the receiver type for an incomplete instance method - hasPtrRecv bool // only valid for methods that don't have a type yet + instRecv *Named // if non-nil, the receiver type for an incomplete instance method + hasPtrRecv_ bool // only valid for methods that don't have a type yet; use hasPtrRecv() to read } // NewFunc returns a new function with the given signature, representing @@ -343,6 +343,25 @@ func (obj *Func) FullName() string { // Scope returns the scope of the function's body block. func (obj *Func) Scope() *Scope { return obj.typ.(*Signature).scope } +// hasPtrRecv reports whether the receiver is of the form *T for the given method obj. +func (obj *Func) hasPtrRecv() bool { + // If a method's receiver type is set, use that as the source of truth for the receiver. + // Caution: Checker.funcDecl (decl.go) marks a function by setting its type to an empty + // signature. We may reach here before the signature is fully set up: we must explicitly + // check if the receiver is set (we cannot just look for non-nil obj.typ). + if sig, _ := obj.typ.(*Signature); sig != nil && sig.recv != nil { + _, isPtr := deref(sig.recv.typ) + return isPtr + } + + // If a method's type is not set it may be a method/function that is: + // 1) client-supplied (via NewFunc with no signature), or + // 2) internally created but not yet type-checked. + // For case 1) we can't do anything; the client must know what they are doing. + // For case 2) we can use the information gathered by the resolver. + return obj.hasPtrRecv_ +} + func (*Func) isDependency() {} // a function may be a dependency of an initialization expression // A Label represents a declared label. diff --git a/src/go/types/resolver.go b/src/go/types/resolver.go index 486c09220b..5a82b4fd9c 100644 --- a/src/go/types/resolver.go +++ b/src/go/types/resolver.go @@ -483,7 +483,7 @@ func (check *Checker) collectObjects() { // Determine the receiver base type and associate m with it. ptr, base := check.resolveBaseTypeName(m.ptr, m.recv) if base != nil { - m.obj.hasPtrRecv = ptr + m.obj.hasPtrRecv_ = ptr check.methods[base] = append(check.methods[base], m.obj) } } -- GitLab From 48cf96c256ff1ec68fd9f9daa59900352d916730 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 20 Sep 2021 15:34:09 -0700 Subject: [PATCH 1244/2500] cmd/compile: don't create or instantiate methods on shape types We should never use or need methods on non-interface shape types. We do have corresponding functions instantiated with the appropriate shape types that take the dictionary and the shape-based receiver as the first two arguments. Each such function has the same name as what the corresponding method would be, so it's best not to create the methods (which would create confusion for import/export). This fixes issue 48414, which happened because of the confusion between these two functions/methods. Fixes #48414 Change-Id: I401fbdad791bdb5792617449cad68aa8df1d9911 Reviewed-on: https://go-review.googlesource.com/c/go/+/351114 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/reflectdata/reflect.go | 7 +++++++ src/cmd/compile/internal/typecheck/iimport.go | 10 ++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 6dbe3cb455..44919c2a4b 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -356,6 +356,13 @@ func methods(t *types.Type) []*typeSig { // imethods returns the methods of the interface type t, sorted by name. func imethods(t *types.Type) []*typeSig { + if t.HasShape() && !t.IsInterface() { + // Non-interface shape types have no methods. (There are + // corresponding functions (created by getInstantiation) that take + // the dictionary and the receiver of shape type as the first two + // arguments.) + return nil + } var methods []*typeSig for _, f := range t.AllMethods().Slice() { if f.Type.Kind() != types.TFUNC || f.Sym == nil { diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index ec4057a8d0..57f0dd8566 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1867,6 +1867,11 @@ func substInstType(t *types.Type, baseType *types.Type, targs []*types.Type) { } t.SetUnderlying(subst.Typ(baseType.Underlying())) + if t.HasShape() && !t.IsInterface() { + // Concrete shape types have no methods. + return + } + newfields := make([]*types.Field, baseType.Methods().Len()) for i, f := range baseType.Methods().Slice() { if !f.IsMethod() || types.IsInterfaceMethod(f.Type) { @@ -1903,8 +1908,9 @@ func substInstType(t *types.Type, baseType *types.Type, targs []*types.Type) { newfields[i].Nname = nname } t.Methods().Set(newfields) - if !t.HasTParam() && t.Kind() != types.TINTER && t.Methods().Len() > 0 { - // Generate all the methods for a new fully-instantiated type. + if !t.HasTParam() && !t.HasShape() && t.Kind() != types.TINTER && t.Methods().Len() > 0 { + // Generate all the methods for a new fully-instantiated, + // non-interface, non-shape type. NeedInstType(t) } } -- GitLab From 30faf968b1f348e944db3bde24c13462125007b1 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Wed, 23 Jun 2021 20:46:11 -0700 Subject: [PATCH 1245/2500] os/user: implement go native GroupIds Currently, GroupIds (a method that returns supplementary group IDs for a user) is not implemented when cgo is not available, or osusergo build tag is set, or the underlying OS lacks getgrouplist(3). This adds a native Go implementation of GroupIds (which parses /etc/group) for such cases, together with some tests. This implementation is used: - when cgo is not available; - when osusergo build tag is set; - on AIX (which lacks getgrouplist(3)); - on Illumos (which only recently added getgrouplist(3)). This commit moves listgroups_unix.go to cgo_listgroups_unix.go, and adds listgroups_unix.go which implements the feature. NOTE the +build equivalent of go:build expression in listgroups_unix.go is not provided as it is going to be bulky. Go 1.17 already prefers go:build over +build, and no longer fail if a file contains go:build without +build, so the absence of +build is not a problem even with Go 1.17, and this code is targeted for Go 1.18. Updates #14709 Updates #30563 Change-Id: Icc95cda97ee3bcb03ef028b16eab7d3faba9ffab Reviewed-on: https://go-review.googlesource.com/c/go/+/330753 Reviewed-by: Ian Lance Taylor Reviewed-by: Tobias Klauser Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot --- src/os/user/cgo_listgroups_unix.go | 51 ++++++++++++ src/os/user/listgroups_aix.go | 20 ----- src/os/user/listgroups_illumos.go | 24 ------ src/os/user/listgroups_stub.go | 20 +++++ src/os/user/listgroups_unix.go | 124 +++++++++++++++++++++------- src/os/user/listgroups_unix_test.go | 107 ++++++++++++++++++++++++ src/os/user/lookup_stubs.go | 12 --- src/os/user/lookup_unix.go | 11 +-- src/os/user/lookup_unix_test.go | 30 +------ src/os/user/user.go | 10 ++- 10 files changed, 279 insertions(+), 130 deletions(-) create mode 100644 src/os/user/cgo_listgroups_unix.go delete mode 100644 src/os/user/listgroups_aix.go delete mode 100644 src/os/user/listgroups_illumos.go create mode 100644 src/os/user/listgroups_stub.go create mode 100644 src/os/user/listgroups_unix_test.go diff --git a/src/os/user/cgo_listgroups_unix.go b/src/os/user/cgo_listgroups_unix.go new file mode 100644 index 0000000000..38aa7653b0 --- /dev/null +++ b/src/os/user/cgo_listgroups_unix.go @@ -0,0 +1,51 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (dragonfly || darwin || freebsd || (!android && linux) || netbsd || openbsd || (solaris && !illumos)) && cgo && !osusergo +// +build dragonfly darwin freebsd !android,linux netbsd openbsd solaris,!illumos +// +build cgo +// +build !osusergo + +package user + +import ( + "fmt" + "strconv" + "unsafe" +) + +/* +#include +#include +*/ +import "C" + +const maxGroups = 2048 + +func listGroups(u *User) ([]string, error) { + ug, err := strconv.Atoi(u.Gid) + if err != nil { + return nil, fmt.Errorf("user: list groups for %s: invalid gid %q", u.Username, u.Gid) + } + userGID := C.gid_t(ug) + nameC := make([]byte, len(u.Username)+1) + copy(nameC, u.Username) + + n := C.int(256) + gidsC := make([]C.gid_t, n) + rv := getGroupList((*C.char)(unsafe.Pointer(&nameC[0])), userGID, &gidsC[0], &n) + if rv == -1 { + // Mac is the only Unix that does not set n properly when rv == -1, so + // we need to use different logic for Mac vs. the other OS's. + if err := groupRetry(u.Username, nameC, userGID, &gidsC, &n); err != nil { + return nil, err + } + } + gidsC = gidsC[:n] + gids := make([]string, 0, n) + for _, g := range gidsC[:n] { + gids = append(gids, strconv.Itoa(int(g))) + } + return gids, nil +} diff --git a/src/os/user/listgroups_aix.go b/src/os/user/listgroups_aix.go deleted file mode 100644 index fbc1deb03f..0000000000 --- a/src/os/user/listgroups_aix.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build cgo && !osusergo -// +build cgo,!osusergo - -package user - -import "fmt" - -// Not implemented on AIX, see golang.org/issue/30563. - -func init() { - groupListImplemented = false -} - -func listGroups(u *User) ([]string, error) { - return nil, fmt.Errorf("user: list groups for %s: not supported on AIX", u.Username) -} diff --git a/src/os/user/listgroups_illumos.go b/src/os/user/listgroups_illumos.go deleted file mode 100644 index e783b26080..0000000000 --- a/src/os/user/listgroups_illumos.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build cgo && !osusergo -// +build cgo,!osusergo - -// Even though this file requires no C, it is used to provide a -// listGroup stub because all the other illumos calls work. Otherwise, -// this stub will conflict with the lookup_stubs.go fallback. - -package user - -import "fmt" - -// Not implemented on illumos, see golang.org/issue/14709. - -func init() { - groupListImplemented = false -} - -func listGroups(u *User) ([]string, error) { - return nil, fmt.Errorf("user: list groups for %s: not supported on illumos", u.Username) -} diff --git a/src/os/user/listgroups_stub.go b/src/os/user/listgroups_stub.go new file mode 100644 index 0000000000..a066c6db71 --- /dev/null +++ b/src/os/user/listgroups_stub.go @@ -0,0 +1,20 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build android || (js && !wasm) +// +build android js,!wasm + +package user + +import ( + "errors" +) + +func init() { + groupListImplemented = false +} + +func listGroups(*User) ([]string, error) { + return nil, errors.New("user: list groups not implemented") +} diff --git a/src/os/user/listgroups_unix.go b/src/os/user/listgroups_unix.go index 38aa7653b0..fa2df4931c 100644 --- a/src/os/user/listgroups_unix.go +++ b/src/os/user/listgroups_unix.go @@ -1,51 +1,113 @@ -// Copyright 2016 The Go Authors. All rights reserved. +// Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build (dragonfly || darwin || freebsd || (!android && linux) || netbsd || openbsd || (solaris && !illumos)) && cgo && !osusergo -// +build dragonfly darwin freebsd !android,linux netbsd openbsd solaris,!illumos -// +build cgo -// +build !osusergo +//go:build ((darwin || dragonfly || freebsd || (js && wasm) || (!android && linux) || netbsd || openbsd || solaris) && (!cgo || osusergo)) || aix || illumos package user import ( + "bufio" + "bytes" + "errors" "fmt" + "io" + "os" "strconv" - "unsafe" ) -/* -#include -#include -*/ -import "C" +const groupFile = "/etc/group" -const maxGroups = 2048 +var colon = []byte{':'} -func listGroups(u *User) ([]string, error) { - ug, err := strconv.Atoi(u.Gid) +func listGroupsFromReader(u *User, r io.Reader) ([]string, error) { + if u.Username == "" { + return nil, errors.New("user: list groups: empty username") + } + primaryGid, err := strconv.Atoi(u.Gid) if err != nil { return nil, fmt.Errorf("user: list groups for %s: invalid gid %q", u.Username, u.Gid) } - userGID := C.gid_t(ug) - nameC := make([]byte, len(u.Username)+1) - copy(nameC, u.Username) - - n := C.int(256) - gidsC := make([]C.gid_t, n) - rv := getGroupList((*C.char)(unsafe.Pointer(&nameC[0])), userGID, &gidsC[0], &n) - if rv == -1 { - // Mac is the only Unix that does not set n properly when rv == -1, so - // we need to use different logic for Mac vs. the other OS's. - if err := groupRetry(u.Username, nameC, userGID, &gidsC, &n); err != nil { - return nil, err + + userCommas := []byte("," + u.Username + ",") // ,john, + userFirst := userCommas[1:] // john, + userLast := userCommas[:len(userCommas)-1] // ,john + userOnly := userCommas[1 : len(userCommas)-1] // john + + // Add primary Gid first. + groups := []string{u.Gid} + + rd := bufio.NewReader(r) + done := false + for !done { + line, err := rd.ReadBytes('\n') + if err != nil { + if err == io.EOF { + done = true + } else { + return groups, err + } + } + + // Look for username in the list of users. If user is found, + // append the GID to the groups slice. + + // There's no spec for /etc/passwd or /etc/group, but we try to follow + // the same rules as the glibc parser, which allows comments and blank + // space at the beginning of a line. + line = bytes.TrimSpace(line) + if len(line) == 0 || line[0] == '#' || + // If you search for a gid in a row where the group + // name (the first field) starts with "+" or "-", + // glibc fails to find the record, and so should we. + line[0] == '+' || line[0] == '-' { + continue + } + + // Format of /etc/group is + // groupname:password:GID:user_list + // for example + // wheel:x:10:john,paul,jack + // tcpdump:x:72: + listIdx := bytes.LastIndexByte(line, ':') + if listIdx == -1 || listIdx == len(line)-1 { + // No commas, or empty group list. + continue + } + if bytes.Count(line[:listIdx], colon) != 2 { + // Incorrect number of colons. + continue } + list := line[listIdx+1:] + // Check the list for user without splitting or copying. + if !(bytes.Equal(list, userOnly) || bytes.HasPrefix(list, userFirst) || bytes.HasSuffix(list, userLast) || bytes.Contains(list, userCommas)) { + continue + } + + // groupname:password:GID + parts := bytes.Split(line[:listIdx], colon) + if len(parts) != 3 || len(parts[0]) == 0 { + continue + } + gid := string(parts[2]) + // Make sure it's numeric and not the same as primary GID. + numGid, err := strconv.Atoi(gid) + if err != nil || numGid == primaryGid { + continue + } + + groups = append(groups, gid) } - gidsC = gidsC[:n] - gids := make([]string, 0, n) - for _, g := range gidsC[:n] { - gids = append(gids, strconv.Itoa(int(g))) + + return groups, nil +} + +func listGroups(u *User) ([]string, error) { + f, err := os.Open(groupFile) + if err != nil { + return nil, err } - return gids, nil + defer f.Close() + + return listGroupsFromReader(u, f) } diff --git a/src/os/user/listgroups_unix_test.go b/src/os/user/listgroups_unix_test.go new file mode 100644 index 0000000000..a9f79ec6bb --- /dev/null +++ b/src/os/user/listgroups_unix_test.go @@ -0,0 +1,107 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ((darwin || dragonfly || freebsd || (js && wasm) || (!android && linux) || netbsd || openbsd || solaris) && (!cgo || osusergo)) || aix || illumos + +package user + +import ( + "fmt" + "sort" + "strings" + "testing" +) + +var testGroupFile = `# See the opendirectoryd(8) man page for additional +# information about Open Directory. +## +nobody:*:-2: +nogroup:*:-1: +wheel:*:0:root +emptyid:*::root +invalidgid:*:notanumber:root ++plussign:*:20:root +-minussign:*:21:root +# Next line is invalid (empty group name) +:*:22:root + +daemon:*:1:root + indented:*:7:root +# comment:*:4:found + # comment:*:4:found +kmem:*:2:root +manymembers:x:777:jill,jody,john,jack,jov,user777 +` + largeGroup() + +func largeGroup() (res string) { + var b strings.Builder + b.WriteString("largegroup:x:1000:user1") + for i := 2; i <= 7500; i++ { + fmt.Fprintf(&b, ",user%d", i) + } + return b.String() +} + +var listGroupsTests = []struct { + // input + in string + user string + gid string + // output + gids []string + err bool +}{ + {in: testGroupFile, user: "root", gid: "0", gids: []string{"0", "1", "2", "7"}}, + {in: testGroupFile, user: "jill", gid: "33", gids: []string{"33", "777"}}, + {in: testGroupFile, user: "jody", gid: "34", gids: []string{"34", "777"}}, + {in: testGroupFile, user: "john", gid: "35", gids: []string{"35", "777"}}, + {in: testGroupFile, user: "jov", gid: "37", gids: []string{"37", "777"}}, + {in: testGroupFile, user: "user777", gid: "7", gids: []string{"7", "777", "1000"}}, + {in: testGroupFile, user: "user1111", gid: "1111", gids: []string{"1111", "1000"}}, + {in: testGroupFile, user: "user1000", gid: "1000", gids: []string{"1000"}}, + {in: testGroupFile, user: "user7500", gid: "7500", gids: []string{"1000", "7500"}}, + {in: testGroupFile, user: "no-such-user", gid: "2345", gids: []string{"2345"}}, + {in: "", user: "no-such-user", gid: "2345", gids: []string{"2345"}}, + // Error cases. + {in: "", user: "", gid: "2345", err: true}, + {in: "", user: "joanna", gid: "bad", err: true}, +} + +func TestListGroups(t *testing.T) { + for _, tc := range listGroupsTests { + u := &User{Username: tc.user, Gid: tc.gid} + got, err := listGroupsFromReader(u, strings.NewReader(tc.in)) + if tc.err { + if err == nil { + t.Errorf("listGroups(%q): got nil; want error", tc.user) + } + continue // no more checks + } + if err != nil { + t.Errorf("listGroups(%q): got %v error, want nil", tc.user, err) + continue // no more checks + } + checkSameIDs(t, got, tc.gids) + } +} + +func checkSameIDs(t *testing.T, got, want []string) { + t.Helper() + if len(got) != len(want) { + t.Errorf("ID list mismatch: got %v; want %v", got, want) + return + } + sort.Strings(got) + sort.Strings(want) + mismatch := -1 + for i, g := range want { + if got[i] != g { + mismatch = i + break + } + } + if mismatch != -1 { + t.Errorf("ID list mismatch (at index %d): got %v; want %v", mismatch, got, want) + } +} diff --git a/src/os/user/lookup_stubs.go b/src/os/user/lookup_stubs.go index d8e3d4866a..efaa92923d 100644 --- a/src/os/user/lookup_stubs.go +++ b/src/os/user/lookup_stubs.go @@ -8,17 +8,12 @@ package user import ( - "errors" "fmt" "os" "runtime" "strconv" ) -func init() { - groupListImplemented = false -} - func current() (*User, error) { uid := currentUID() // $USER and /etc/passwd may disagree; prefer the latter if we can get it. @@ -64,13 +59,6 @@ func current() (*User, error) { return u, fmt.Errorf("user: Current requires cgo or %s set in environment", missing) } -func listGroups(*User) ([]string, error) { - if runtime.GOOS == "android" || runtime.GOOS == "aix" { - return nil, fmt.Errorf("user: GroupIds not implemented on %s", runtime.GOOS) - } - return nil, errors.New("user: GroupIds requires cgo") -} - func currentUID() string { if id := os.Getuid(); id >= 0 { return strconv.Itoa(id) diff --git a/src/os/user/lookup_unix.go b/src/os/user/lookup_unix.go index dffea4a885..ac4f1502af 100644 --- a/src/os/user/lookup_unix.go +++ b/src/os/user/lookup_unix.go @@ -18,16 +18,7 @@ import ( "strings" ) -const ( - groupFile = "/etc/group" - userFile = "/etc/passwd" -) - -var colon = []byte{':'} - -func init() { - groupListImplemented = false -} +const userFile = "/etc/passwd" // lineFunc returns a value, an error, or (nil, nil) to skip the row. type lineFunc func(line []byte) (v interface{}, err error) diff --git a/src/os/user/lookup_unix_test.go b/src/os/user/lookup_unix_test.go index 060cfe186f..05d23567c3 100644 --- a/src/os/user/lookup_unix_test.go +++ b/src/os/user/lookup_unix_test.go @@ -9,30 +9,11 @@ package user import ( - "fmt" "reflect" "strings" "testing" ) -var testGroupFile = `# See the opendirectoryd(8) man page for additional -# information about Open Directory. -## -nobody:*:-2: -nogroup:*:-1: -wheel:*:0:root -emptyid:*::root -invalidgid:*:notanumber:root -+plussign:*:20:root --minussign:*:21:root - -daemon:*:1:root - indented:*:7: -# comment:*:4:found - # comment:*:4:found -kmem:*:2:root -` + largeGroup() - var groupTests = []struct { in string name string @@ -51,19 +32,10 @@ var groupTests = []struct { {testGroupFile, "indented", "7"}, {testGroupFile, "# comment", ""}, {testGroupFile, "largegroup", "1000"}, + {testGroupFile, "manymembers", "777"}, {"", "emptyfile", ""}, } -// Generate a proper "largegroup" entry for testGroupFile string -func largeGroup() (res string) { - var b strings.Builder - b.WriteString("largegroup:x:1000:user1") - for i := 2; i <= 7500; i++ { - fmt.Fprintf(&b, ",user%d", i) - } - return b.String() -} - func TestFindGroupName(t *testing.T) { for _, tt := range groupTests { got, err := findGroupName(tt.name, strings.NewReader(tt.in)) diff --git a/src/os/user/user.go b/src/os/user/user.go index 4e1b5b3407..0307d2ad6a 100644 --- a/src/os/user/user.go +++ b/src/os/user/user.go @@ -6,11 +6,13 @@ Package user allows user account lookups by name or id. For most Unix systems, this package has two internal implementations of -resolving user and group ids to names. One is written in pure Go and -parses /etc/passwd and /etc/group. The other is cgo-based and relies on -the standard C library (libc) routines such as getpwuid_r and getgrnam_r. +resolving user and group ids to names, and listing supplementary group IDs. +One is written in pure Go and parses /etc/passwd and /etc/group. The other +is cgo-based and relies on the standard C library (libc) routines such as +getpwuid_r, getgrnam_r, and getgrouplist. -When cgo is available, cgo-based (libc-backed) code is used by default. +When cgo is available, and the required routines are implemented in libc +for a particular platform, cgo-based (libc-backed) code is used. This can be overridden by using osusergo build tag, which enforces the pure Go implementation. */ -- GitLab From 04572fa29ba689dcdd098cc6b7f84307bf1e171b Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 2 Jul 2021 21:02:30 -0700 Subject: [PATCH 1246/2500] cmd/compile: use BMI1 instructions for GOAMD64=v3 and higher BMI1 includes four instructions (ANDN, BLSI, BLSMSK, BLSR) that are easy to peephole optimize, and which GCC always seems to favor using when available and applicable. Updates #45453. Change-Id: I0274184057058f5c579e5bc3ea9c414396d3cf46 Reviewed-on: https://go-review.googlesource.com/c/go/+/351130 Run-TryBot: Matthew Dempsky Trust: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/amd64/ssa.go | 17 ++ src/cmd/compile/internal/ssa/gen/AMD64.rules | 7 + src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 10 ++ src/cmd/compile/internal/ssa/opGen.go | 122 +++++++++++++ src/cmd/compile/internal/ssa/rewriteAMD64.go | 175 +++++++++++++++++++ test/codegen/bmi.go | 47 +++++ 6 files changed, 378 insertions(+) create mode 100644 test/codegen/bmi.go diff --git a/src/cmd/compile/internal/amd64/ssa.go b/src/cmd/compile/internal/amd64/ssa.go index 30131bd559..68266d35d6 100644 --- a/src/cmd/compile/internal/amd64/ssa.go +++ b/src/cmd/compile/internal/amd64/ssa.go @@ -263,6 +263,23 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.To.Reg = lo p.SetFrom3Reg(hi) + case ssa.OpAMD64BLSIQ, ssa.OpAMD64BLSIL, + ssa.OpAMD64BLSMSKQ, ssa.OpAMD64BLSMSKL, + ssa.OpAMD64BLSRQ, ssa.OpAMD64BLSRL: + p := s.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_REG + p.From.Reg = v.Args[0].Reg() + p.To.Type = obj.TYPE_REG + p.To.Reg = v.Reg() + + case ssa.OpAMD64ANDNQ, ssa.OpAMD64ANDNL: + p := s.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_REG + p.From.Reg = v.Args[0].Reg() + p.To.Type = obj.TYPE_REG + p.To.Reg = v.Reg() + p.SetFrom3Reg(v.Args[1].Reg()) + case ssa.OpAMD64DIVQU, ssa.OpAMD64DIVLU, ssa.OpAMD64DIVWU: // Arg[0] (the dividend) is in AX. // Arg[1] (the divisor) can be in any other register. diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index bfed3bc7fd..edb1a4869a 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -639,6 +639,7 @@ // Recognize bit clearing: a &^= 1< (BTR(Q|L) x y) +(ANDN(Q|L) x (SHL(Q|L) (MOV(Q|L)const [1]) y)) => (BTR(Q|L) x y) (ANDQconst [c] x) && isUint64PowerOfTwo(int64(^c)) && uint64(^c) >= 128 => (BTRQconst [int8(log32(^c))] x) (ANDLconst [c] x) && isUint32PowerOfTwo(int64(^c)) && uint64(^c) >= 128 @@ -2204,3 +2205,9 @@ // Prefetch instructions (PrefetchCache ...) => (PrefetchT0 ...) (PrefetchCacheStreamed ...) => (PrefetchNTA ...) + +// CPUID feature: BMI1. +(AND(Q|L) x (NOT(Q|L) y)) && buildcfg.GOAMD64 >= 3 => (ANDN(Q|L) x y) +(AND(Q|L) x (NEG(Q|L) x)) && buildcfg.GOAMD64 >= 3 => (BLSI(Q|L) x) +(XOR(Q|L) x (ADD(Q|L)const [-1] x)) && buildcfg.GOAMD64 >= 3 => (BLSMSK(Q|L) x) +(AND(Q|L) x (ADD(Q|L)const [-1] x)) && buildcfg.GOAMD64 >= 3 => (BLSR(Q|L) x) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index 51cbf5f78a..6e4c514bd0 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -908,6 +908,16 @@ func init() { // Do prefetch arg0 address. arg0=addr, arg1=memory. Instruction variant selects locality hint {name: "PrefetchT0", argLength: 2, reg: prefreg, asm: "PREFETCHT0", hasSideEffects: true}, {name: "PrefetchNTA", argLength: 2, reg: prefreg, asm: "PREFETCHNTA", hasSideEffects: true}, + + // CPUID feature: BMI1. + {name: "ANDNQ", argLength: 2, reg: gp21, asm: "ANDNQ", clobberFlags: true}, // arg0 &^ arg1 + {name: "ANDNL", argLength: 2, reg: gp21, asm: "ANDNL", clobberFlags: true}, // arg0 &^ arg1 + {name: "BLSIQ", argLength: 1, reg: gp11, asm: "BLSIQ", clobberFlags: true}, // arg0 & -arg0 + {name: "BLSIL", argLength: 1, reg: gp11, asm: "BLSIL", clobberFlags: true}, // arg0 & -arg0 + {name: "BLSMSKQ", argLength: 1, reg: gp11, asm: "BLSMSKQ", clobberFlags: true}, // arg0 ^ (arg0 - 1) + {name: "BLSMSKL", argLength: 1, reg: gp11, asm: "BLSMSKL", clobberFlags: true}, // arg0 ^ (arg0 - 1) + {name: "BLSRQ", argLength: 1, reg: gp11, asm: "BLSRQ", clobberFlags: true}, // arg0 & (arg0 - 1) + {name: "BLSRL", argLength: 1, reg: gp11, asm: "BLSRL", clobberFlags: true}, // arg0 & (arg0 - 1) } var AMD64blocks = []blockData{ diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index ceb0a24285..fed3bc3386 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -1033,6 +1033,14 @@ const ( OpAMD64ORLlock OpAMD64PrefetchT0 OpAMD64PrefetchNTA + OpAMD64ANDNQ + OpAMD64ANDNL + OpAMD64BLSIQ + OpAMD64BLSIL + OpAMD64BLSMSKQ + OpAMD64BLSMSKL + OpAMD64BLSRQ + OpAMD64BLSRL OpARMADD OpARMADDconst @@ -13628,6 +13636,120 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "ANDNQ", + argLen: 2, + clobberFlags: true, + asm: x86.AANDNQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + {1, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + }, + outputs: []outputInfo{ + {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + }, + }, + }, + { + name: "ANDNL", + argLen: 2, + clobberFlags: true, + asm: x86.AANDNL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + {1, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + }, + outputs: []outputInfo{ + {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + }, + }, + }, + { + name: "BLSIQ", + argLen: 1, + clobberFlags: true, + asm: x86.ABLSIQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + }, + outputs: []outputInfo{ + {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + }, + }, + }, + { + name: "BLSIL", + argLen: 1, + clobberFlags: true, + asm: x86.ABLSIL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + }, + outputs: []outputInfo{ + {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + }, + }, + }, + { + name: "BLSMSKQ", + argLen: 1, + clobberFlags: true, + asm: x86.ABLSMSKQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + }, + outputs: []outputInfo{ + {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + }, + }, + }, + { + name: "BLSMSKL", + argLen: 1, + clobberFlags: true, + asm: x86.ABLSMSKL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + }, + outputs: []outputInfo{ + {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + }, + }, + }, + { + name: "BLSRQ", + argLen: 1, + clobberFlags: true, + asm: x86.ABLSRQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + }, + outputs: []outputInfo{ + {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + }, + }, + }, + { + name: "BLSRL", + argLen: 1, + clobberFlags: true, + asm: x86.ABLSRL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + }, + outputs: []outputInfo{ + {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + }, + }, + }, { name: "ADD", diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index e20161c920..906260fb14 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -3,6 +3,7 @@ package ssa +import "internal/buildcfg" import "math" import "cmd/internal/obj" import "cmd/compile/internal/types" @@ -53,6 +54,10 @@ func rewriteValueAMD64(v *Value) bool { return rewriteValueAMD64_OpAMD64ANDLload(v) case OpAMD64ANDLmodify: return rewriteValueAMD64_OpAMD64ANDLmodify(v) + case OpAMD64ANDNL: + return rewriteValueAMD64_OpAMD64ANDNL(v) + case OpAMD64ANDNQ: + return rewriteValueAMD64_OpAMD64ANDNQ(v) case OpAMD64ANDQ: return rewriteValueAMD64_OpAMD64ANDQ(v) case OpAMD64ANDQconst: @@ -2759,6 +2764,55 @@ func rewriteValueAMD64_OpAMD64ANDL(v *Value) bool { } break } + // match: (ANDL x (NOTL y)) + // cond: buildcfg.GOAMD64 >= 3 + // result: (ANDNL x y) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpAMD64NOTL { + continue + } + y := v_1.Args[0] + if !(buildcfg.GOAMD64 >= 3) { + continue + } + v.reset(OpAMD64ANDNL) + v.AddArg2(x, y) + return true + } + break + } + // match: (ANDL x (NEGL x)) + // cond: buildcfg.GOAMD64 >= 3 + // result: (BLSIL x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpAMD64NEGL || x != v_1.Args[0] || !(buildcfg.GOAMD64 >= 3) { + continue + } + v.reset(OpAMD64BLSIL) + v.AddArg(x) + return true + } + break + } + // match: (ANDL x (ADDLconst [-1] x)) + // cond: buildcfg.GOAMD64 >= 3 + // result: (BLSRL x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpAMD64ADDLconst || auxIntToInt32(v_1.AuxInt) != -1 || x != v_1.Args[0] || !(buildcfg.GOAMD64 >= 3) { + continue + } + v.reset(OpAMD64BLSRL) + v.AddArg(x) + return true + } + break + } return false } func rewriteValueAMD64_OpAMD64ANDLconst(v *Value) bool { @@ -3037,6 +3091,48 @@ func rewriteValueAMD64_OpAMD64ANDLmodify(v *Value) bool { } return false } +func rewriteValueAMD64_OpAMD64ANDNL(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] + // match: (ANDNL x (SHLL (MOVLconst [1]) y)) + // result: (BTRL x y) + for { + x := v_0 + if v_1.Op != OpAMD64SHLL { + break + } + y := v_1.Args[1] + v_1_0 := v_1.Args[0] + if v_1_0.Op != OpAMD64MOVLconst || auxIntToInt32(v_1_0.AuxInt) != 1 { + break + } + v.reset(OpAMD64BTRL) + v.AddArg2(x, y) + return true + } + return false +} +func rewriteValueAMD64_OpAMD64ANDNQ(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] + // match: (ANDNQ x (SHLQ (MOVQconst [1]) y)) + // result: (BTRQ x y) + for { + x := v_0 + if v_1.Op != OpAMD64SHLQ { + break + } + y := v_1.Args[1] + v_1_0 := v_1.Args[0] + if v_1_0.Op != OpAMD64MOVQconst || auxIntToInt64(v_1_0.AuxInt) != 1 { + break + } + v.reset(OpAMD64BTRQ) + v.AddArg2(x, y) + return true + } + return false +} func rewriteValueAMD64_OpAMD64ANDQ(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -3138,6 +3234,55 @@ func rewriteValueAMD64_OpAMD64ANDQ(v *Value) bool { } break } + // match: (ANDQ x (NOTQ y)) + // cond: buildcfg.GOAMD64 >= 3 + // result: (ANDNQ x y) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpAMD64NOTQ { + continue + } + y := v_1.Args[0] + if !(buildcfg.GOAMD64 >= 3) { + continue + } + v.reset(OpAMD64ANDNQ) + v.AddArg2(x, y) + return true + } + break + } + // match: (ANDQ x (NEGQ x)) + // cond: buildcfg.GOAMD64 >= 3 + // result: (BLSIQ x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpAMD64NEGQ || x != v_1.Args[0] || !(buildcfg.GOAMD64 >= 3) { + continue + } + v.reset(OpAMD64BLSIQ) + v.AddArg(x) + return true + } + break + } + // match: (ANDQ x (ADDQconst [-1] x)) + // cond: buildcfg.GOAMD64 >= 3 + // result: (BLSRQ x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpAMD64ADDQconst || auxIntToInt32(v_1.AuxInt) != -1 || x != v_1.Args[0] || !(buildcfg.GOAMD64 >= 3) { + continue + } + v.reset(OpAMD64BLSRQ) + v.AddArg(x) + return true + } + break + } return false } func rewriteValueAMD64_OpAMD64ANDQconst(v *Value) bool { @@ -26474,6 +26619,21 @@ func rewriteValueAMD64_OpAMD64XORL(v *Value) bool { } break } + // match: (XORL x (ADDLconst [-1] x)) + // cond: buildcfg.GOAMD64 >= 3 + // result: (BLSMSKL x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpAMD64ADDLconst || auxIntToInt32(v_1.AuxInt) != -1 || x != v_1.Args[0] || !(buildcfg.GOAMD64 >= 3) { + continue + } + v.reset(OpAMD64BLSMSKL) + v.AddArg(x) + return true + } + break + } return false } func rewriteValueAMD64_OpAMD64XORLconst(v *Value) bool { @@ -26950,6 +27110,21 @@ func rewriteValueAMD64_OpAMD64XORQ(v *Value) bool { } break } + // match: (XORQ x (ADDQconst [-1] x)) + // cond: buildcfg.GOAMD64 >= 3 + // result: (BLSMSKQ x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpAMD64ADDQconst || auxIntToInt32(v_1.AuxInt) != -1 || x != v_1.Args[0] || !(buildcfg.GOAMD64 >= 3) { + continue + } + v.reset(OpAMD64BLSMSKQ) + v.AddArg(x) + return true + } + break + } return false } func rewriteValueAMD64_OpAMD64XORQconst(v *Value) bool { diff --git a/test/codegen/bmi.go b/test/codegen/bmi.go new file mode 100644 index 0000000000..0c25e0b796 --- /dev/null +++ b/test/codegen/bmi.go @@ -0,0 +1,47 @@ +// asmcheck + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package codegen + +func andn64(x, y int64) int64 { + // amd64/v3:"ANDNQ" + return x &^ y +} + +func andn32(x, y int32) int32 { + // amd64/v3:"ANDNL" + return x &^ y +} + +func blsi64(x int64) int64 { + // amd64/v3:"BLSIQ" + return x & -x +} + +func blsi32(x int32) int32 { + // amd64/v3:"BLSIL" + return x & -x +} + +func blsmsk64(x int64) int64 { + // amd64/v3:"BLSMSKQ" + return x ^ (x - 1) +} + +func blsmsk32(x int32) int32 { + // amd64/v3:"BLSMSKL" + return x ^ (x - 1) +} + +func blsr64(x int64) int64 { + // amd64/v3:"BLSRQ" + return x & (x - 1) +} + +func blsr32(x int32) int32 { + // amd64/v3:"BLSRL" + return x & (x - 1) +} -- GitLab From 3664950ef68089716b9f22062db66a347c7246d4 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 21 Sep 2021 18:15:25 -0400 Subject: [PATCH 1247/2500] go/types: tweaks to ArgumentError to be more idiomatic This CL makes a few changes to the new ArgumentError type to be more idiomatic: - Use a pointer receiver for methods. - Export fields, similarly to Error. ArgumentError has a clear meaning (an error associated with an index), so there is no need to hide its representation. - Add an Unwrap method to access the underlying error. - Say explicitly that the error returned from Instantiate may wrap *ArgumentError. There is no need to commit to an API that always returns an error with dynamic type *ArgumentError. Updates #47916 Change-Id: Ib1a43e921f247794e7155280ccbf5a6775ed3978 Reviewed-on: https://go-review.googlesource.com/c/go/+/351335 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/api.go | 11 ++++------- src/go/types/api_test.go | 11 ++++++++--- src/go/types/instantiate.go | 6 +++--- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/go/types/api.go b/src/go/types/api.go index 4cf0eb123f..0bbd940d07 100644 --- a/src/go/types/api.go +++ b/src/go/types/api.go @@ -64,15 +64,12 @@ func (err Error) Error() string { // An ArgumentError holds an error associated with an argument index. type ArgumentError struct { - index int - error + Index int + Err error } -// Index returns the positional index of the argument associated with the -// error. -func (e ArgumentError) Index() int { - return e.index -} +func (e *ArgumentError) Error() string { return e.Err.Error() } +func (e *ArgumentError) Unwrap() error { return e.Err } // An Importer resolves import paths to Packages. // diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index 9b584f390c..d59d3d8923 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -6,6 +6,7 @@ package types_test import ( "bytes" + "errors" "fmt" "go/ast" "go/importer" @@ -2000,9 +2001,13 @@ func TestInstantiateErrors(t *testing.T) { t.Fatalf("Instantiate(%v, %v) returned nil error, want non-nil", T, test.targs) } - gotAt := err.(ArgumentError).Index() - if gotAt != test.wantAt { - t.Errorf("Instantate(%v, %v): error at index %d, want index %d", T, test.targs, gotAt, test.wantAt) + var argErr *ArgumentError + if !errors.As(err, &argErr) { + t.Fatalf("Instantiate(%v, %v): error is not an *ArgumentError", T, test.targs) + } + + if argErr.Index != test.wantAt { + t.Errorf("Instantate(%v, %v): error at index %d, want index %d", T, test.targs, argErr.Index, test.wantAt) } } } diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index b178d1eb3f..6cafc2fbed 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -25,8 +25,8 @@ import ( // unimplemented. // // If verify is set and constraint satisfaction fails, the returned error may -// be of dynamic type ArgumentError indicating which type argument did not -// satisfy its corresponding type parameter constraint, and why. +// wrap an *ArgumentError indicating which type argument did not satisfy its +// corresponding type parameter constraint, and why. // // TODO(rfindley): change this function to also return an error if lengths of // tparams and targs do not match. @@ -43,7 +43,7 @@ func Instantiate(env *Environment, typ Type, targs []Type, validate bool) (Type, tparams = t.TypeParams().list() } if i, err := (*Checker)(nil).verify(token.NoPos, tparams, targs); err != nil { - return inst, ArgumentError{i, err} + return inst, &ArgumentError{i, err} } } -- GitLab From 085c609a70f8f156734efe2cf4bfb5fe8bd94363 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Tue, 21 Sep 2021 00:23:28 +0700 Subject: [PATCH 1248/2500] cmd/go: fix go command fails to perform concurrent compilation CL 344909 fixed the bug in the order of passing gcflags from cmd/go to cmd/compile. In that process, we merged the flags passed by cmd/go and the flags specified by "-gcflags" to one variable. That causes the gcBackendConcurrency function fails to detect concurrency level, since when it expects only the latter flags. To fix this, just don't merge those two variables, so we can now correctly detect the concurrency level and passing the right -c to the compiler. Fixes #48490 Change-Id: I1293a7d6b946b7fccdd5cd34a38452bf6306e115 Reviewed-on: https://go-review.googlesource.com/c/go/+/351049 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/work/gc.go | 24 +++++++++---------- .../script/build_concurrent_backend.txt | 14 +++++++++++ 2 files changed, 26 insertions(+), 12 deletions(-) create mode 100644 src/cmd/go/testdata/script/build_concurrent_backend.txt diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go index 800800f788..4e4a1d8451 100644 --- a/src/cmd/go/internal/work/gc.go +++ b/src/cmd/go/internal/work/gc.go @@ -75,7 +75,7 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg } pkgpath := pkgPath(a) - gcflags := []string{"-p", pkgpath} + defaultGcFlags := []string{"-p", pkgpath} if p.Module != nil { v := p.Module.GoVersion if v == "" { @@ -94,11 +94,11 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg v = "1.16" } if allowedVersion(v) { - gcflags = append(gcflags, "-lang=go"+v) + defaultGcFlags = append(defaultGcFlags, "-lang=go"+v) } } if p.Standard { - gcflags = append(gcflags, "-std") + defaultGcFlags = append(defaultGcFlags, "-std") } _, compilingRuntime := runtimePackages[p.ImportPath] compilingRuntime = compilingRuntime && p.Standard @@ -106,7 +106,7 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg // runtime compiles with a special gc flag to check for // memory allocations that are invalid in the runtime package, // and to implement some special compiler pragmas. - gcflags = append(gcflags, "-+") + defaultGcFlags = append(defaultGcFlags, "-+") } // If we're giving the compiler the entire package (no C etc files), tell it that, @@ -125,25 +125,25 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg } } if extFiles == 0 { - gcflags = append(gcflags, "-complete") + defaultGcFlags = append(defaultGcFlags, "-complete") } if cfg.BuildContext.InstallSuffix != "" { - gcflags = append(gcflags, "-installsuffix", cfg.BuildContext.InstallSuffix) + defaultGcFlags = append(defaultGcFlags, "-installsuffix", cfg.BuildContext.InstallSuffix) } if a.buildID != "" { - gcflags = append(gcflags, "-buildid", a.buildID) + defaultGcFlags = append(defaultGcFlags, "-buildid", a.buildID) } if p.Internal.OmitDebug || cfg.Goos == "plan9" || cfg.Goarch == "wasm" { - gcflags = append(gcflags, "-dwarf=false") + defaultGcFlags = append(defaultGcFlags, "-dwarf=false") } if strings.HasPrefix(runtimeVersion, "go1") && !strings.Contains(os.Args[0], "go_bootstrap") { - gcflags = append(gcflags, "-goversion", runtimeVersion) + defaultGcFlags = append(defaultGcFlags, "-goversion", runtimeVersion) } if symabis != "" { - gcflags = append(gcflags, "-symabis", symabis) + defaultGcFlags = append(defaultGcFlags, "-symabis", symabis) } - gcflags = append(gcflags, str.StringList(forcedGcflags, p.Internal.Gcflags)...) + gcflags := str.StringList(forcedGcflags, p.Internal.Gcflags) if compilingRuntime { // Remove -N, if present. // It is not possible to build the runtime with no optimizations, @@ -157,7 +157,7 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg } } - args := []interface{}{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", a.trimpath(), gcflags} + args := []interface{}{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", a.trimpath(), defaultGcFlags, gcflags} if p.Internal.LocalPrefix != "" { // Workaround #43883. args = append(args, "-D", p.Internal.LocalPrefix) diff --git a/src/cmd/go/testdata/script/build_concurrent_backend.txt b/src/cmd/go/testdata/script/build_concurrent_backend.txt new file mode 100644 index 0000000000..a279fed9dc --- /dev/null +++ b/src/cmd/go/testdata/script/build_concurrent_backend.txt @@ -0,0 +1,14 @@ +# Tests golang.org/issue/48490 +# cmd/go should enable concurrent compilation by default + +# Skip test on darwin/arm64, see #48496. +# TODO(cuonglm): remove this once #48496 is fixed. +[darwin] [arm64] skip + +# Reset all experiments, since one of them can disable +# concurrent compilation, e.g: fieldtrack. +env GOEXPERIMENT=none + +env GOMAXPROCS=4 +go build -n -x -a fmt +stderr ' -c=4 ' -- GitLab From 051df0d722fd2ec4473f2ac0ae868a3487927d68 Mon Sep 17 00:00:00 2001 From: jiahua wang Date: Wed, 22 Sep 2021 09:50:32 +0800 Subject: [PATCH 1249/2500] io: fix spelling in documentation for writerFunc Change-Id: I9f55188859944e1b2b140d3547bcfcb335c5ff50 Reviewed-on: https://go-review.googlesource.com/c/go/+/351370 Reviewed-by: Ian Lance Taylor Trust: Robert Griesemer --- src/io/multi_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/io/multi_test.go b/src/io/multi_test.go index 909b6d8be2..c3a44fd3b2 100644 --- a/src/io/multi_test.go +++ b/src/io/multi_test.go @@ -141,7 +141,7 @@ func testMultiWriter(t *testing.T, sink interface { } } -// writerFunc is an Writer implemented by the underlying func. +// writerFunc is a Writer implemented by the underlying func. type writerFunc func(p []byte) (int, error) func (f writerFunc) Write(p []byte) (int, error) { -- GitLab From 7158ae4e32894cf7050eef287c5e9818b9fb9ce1 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 21 Sep 2021 20:20:36 -0400 Subject: [PATCH 1250/2500] go/types: don't panic if targs don't match tparams when substituting Invalid code may produce instances where the number of type arguments does not match the number of type parameters. Such code will cause an error, but should not cause a panic when substituting in those invalid instances. Fixes #48529 Change-Id: Ie5ff5ace55921540a7224cc5022ef9ff7649361a Reviewed-on: https://go-review.googlesource.com/c/go/+/351337 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/types/named.go | 2 +- src/go/types/subst.go | 4 +++- src/go/types/testdata/fixedbugs/issue46461.go2 | 11 +++++++++++ src/go/types/testdata/fixedbugs/issue48529.go2 | 11 +++++++++++ 4 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue46461.go2 create mode 100644 src/go/types/testdata/fixedbugs/issue48529.go2 diff --git a/src/go/types/named.go b/src/go/types/named.go index 07c837d14a..d29c67d4eb 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -332,7 +332,7 @@ func (check *Checker) completeMethod(env *Environment, m *Func) { // TODO(rfindley): eliminate this function or give it a better name. func safeUnderlying(typ Type) Type { if t, _ := typ.(*Named); t != nil { - return t.resolve(nil).underlying + return t.underlying } return typ.Underlying() } diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 999099572c..25629dca8a 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -177,7 +177,9 @@ func (subst *subster) typ(typ Type) Type { } var newTArgs []Type - assert(t.targs.Len() == t.orig.TypeParams().Len()) + if t.targs.Len() != t.orig.TypeParams().Len() { + return Typ[Invalid] // error reported elsewhere + } // already instantiated dump(">>> %s already instantiated", t) diff --git a/src/go/types/testdata/fixedbugs/issue46461.go2 b/src/go/types/testdata/fixedbugs/issue46461.go2 new file mode 100644 index 0000000000..bfeaf3a966 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue46461.go2 @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T[U interface{ M() T[U] }] int + +type X int + +func (X) M() T[X] { return 0 } diff --git a/src/go/types/testdata/fixedbugs/issue48529.go2 b/src/go/types/testdata/fixedbugs/issue48529.go2 new file mode 100644 index 0000000000..4f92dec7fe --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue48529.go2 @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T[U interface{ M() T /* ERROR "got 2 arguments but 1 type parameters" */ [U, int] }] int + +type X int + +func (X) M() T[X] { return 0 } -- GitLab From e925c4640d52587e6657bccc40899888b657e6df Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 21 Sep 2021 20:58:33 -0400 Subject: [PATCH 1251/2500] go/types: add a test for argument error unwrapping Add a sanity-check test that ArgumentErrors unwrap their inner Err. Change-Id: I5a670a490deeabc03a64e42b3843f79d622ba958 Reviewed-on: https://go-review.googlesource.com/c/go/+/351338 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/api_test.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index d59d3d8923..f1a820988f 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -2012,6 +2012,20 @@ func TestInstantiateErrors(t *testing.T) { } } +func TestArgumentErrorUnwrapping(t *testing.T) { + var err error = &ArgumentError{ + Index: 1, + Err: Error{Msg: "test"}, + } + var e Error + if !errors.As(err, &e) { + t.Fatalf("error %v does not wrap types.Error", err) + } + if e.Msg != "test" { + t.Errorf("e.Msg = %q, want %q", e.Msg, "test") + } +} + func TestInstanceIdentity(t *testing.T) { imports := make(testImporter) conf := Config{Importer: imports} -- GitLab From 98989f2a74aa53e9ea64c41c94e66f02beceecc9 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 21 Sep 2021 14:35:37 -0400 Subject: [PATCH 1252/2500] cmd/compile, cmd/link: avoid ABI aliases In the past we introduced ABI aliases, in preparation for ABI wrappers. Now that we have ABI wrappers implemented, we don't need ABI aliases. If ABI wrappers are not enabled, ABI0 and ABIInternal are actually identical, so we can resolve symbol references without distinguish them. This CL does so by normalizing ABIInternal to ABI0 at link time. This way, we no longer need to generate ABI aliases. This CL doesn't clean up everything related to ABI aliases, which will be done in followup CLs. Change-Id: I5b5db43370d29b8ad153078c70a853e3263ae6f7 Reviewed-on: https://go-review.googlesource.com/c/go/+/351271 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/compile/internal/ssagen/abi.go | 20 ------------------- src/cmd/internal/goobj/builtin.go | 4 +++- src/cmd/link/internal/ld/deadcode.go | 10 ++++++---- src/cmd/link/internal/ld/lib.go | 27 +++++++------------------- src/cmd/link/internal/ld/macho.go | 3 +-- src/cmd/link/internal/ld/main.go | 4 ++++ src/cmd/link/internal/ld/pcln.go | 2 +- src/cmd/link/internal/loader/loader.go | 2 +- src/cmd/link/internal/sym/symbol.go | 6 ++++++ 9 files changed, 29 insertions(+), 49 deletions(-) diff --git a/src/cmd/compile/internal/ssagen/abi.go b/src/cmd/compile/internal/ssagen/abi.go index c54a734c75..eabd232791 100644 --- a/src/cmd/compile/internal/ssagen/abi.go +++ b/src/cmd/compile/internal/ssagen/abi.go @@ -257,10 +257,6 @@ func InitLSym(f *ir.Func, hasBody bool) { // when we see that. staticdata.NeedFuncSym(f) } - if !buildcfg.Experiment.RegabiWrappers { - // Create ABI aliases instead of wrappers. - forEachWrapperABI(f, makeABIAlias) - } } if hasBody { setupTextLSym(f, 0) @@ -281,22 +277,6 @@ func forEachWrapperABI(fn *ir.Func, cb func(fn *ir.Func, wrapperABI obj.ABI)) { } } -// makeABIAlias creates a new ABI alias so calls to f via wrapperABI -// will be resolved directly to f's ABI by the linker. -func makeABIAlias(f *ir.Func, wrapperABI obj.ABI) { - // These LSyms have the same name as the native function, so - // we create them directly rather than looking them up. - // The uniqueness of f.lsym ensures uniqueness of asym. - asym := &obj.LSym{ - Name: f.LSym.Name, - Type: objabi.SABIALIAS, - R: []obj.Reloc{{Sym: f.LSym}}, // 0 size, so "informational" - } - asym.SetABI(wrapperABI) - asym.Set(obj.AttrDuplicateOK, true) - base.Ctxt.ABIAliases = append(base.Ctxt.ABIAliases, asym) -} - // makeABIWrapper creates a new function that will be called with // wrapperABI and calls "f" using f.ABI. func makeABIWrapper(f *ir.Func, wrapperABI obj.ABI) { diff --git a/src/cmd/internal/goobj/builtin.go b/src/cmd/internal/goobj/builtin.go index e7d612aeb7..aa665fde99 100644 --- a/src/cmd/internal/goobj/builtin.go +++ b/src/cmd/internal/goobj/builtin.go @@ -4,6 +4,8 @@ package goobj +import "internal/buildcfg" + // Builtin (compiler-generated) function references appear // frequently. We assign special indices for them, so they // don't need to be referenced by name. @@ -27,7 +29,7 @@ func BuiltinIdx(name string, abi int) int { if !ok { return -1 } - if builtins[i].abi != abi { + if buildcfg.Experiment.RegabiWrappers && builtins[i].abi != abi { return -1 } return i diff --git a/src/cmd/link/internal/ld/deadcode.go b/src/cmd/link/internal/ld/deadcode.go index dd5dafc21b..0221024d56 100644 --- a/src/cmd/link/internal/ld/deadcode.go +++ b/src/cmd/link/internal/ld/deadcode.go @@ -96,8 +96,10 @@ func (d *deadcodePass) init() { for _, name := range names { // Mark symbol as a data/ABI0 symbol. d.mark(d.ldr.Lookup(name, 0), 0) - // Also mark any Go functions (internal ABI). - d.mark(d.ldr.Lookup(name, sym.SymVerABIInternal), 0) + if abiInternalVer != 0 { + // Also mark any Go functions (internal ABI). + d.mark(d.ldr.Lookup(name, abiInternalVer), 0) + } } // All dynamic exports are roots. @@ -327,8 +329,8 @@ func deadcode(ctxt *Link) { d.init() d.flood() - methSym := ldr.Lookup("reflect.Value.Method", sym.SymVerABIInternal) - methByNameSym := ldr.Lookup("reflect.Value.MethodByName", sym.SymVerABIInternal) + methSym := ldr.Lookup("reflect.Value.Method", abiInternalVer) + methByNameSym := ldr.Lookup("reflect.Value.MethodByName", abiInternalVer) if ctxt.DynlinkingGo() { // Exported methods may satisfy interfaces we don't know diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index cf70374b16..f46d1f0221 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -144,7 +144,7 @@ func (ctxt *Link) setArchSyms() { ctxt.mkArchSym(".dynamic", 0, &ctxt.Dynamic) ctxt.mkArchSym(".dynsym", 0, &ctxt.DynSym) ctxt.mkArchSym(".dynstr", 0, &ctxt.DynStr) - ctxt.mkArchSym("runtime.unreachableMethod", sym.SymVerABIInternal, &ctxt.unreachableMethod) + ctxt.mkArchSym("runtime.unreachableMethod", abiInternalVer, &ctxt.unreachableMethod) if ctxt.IsPPC64() { ctxt.mkArchSym("TOC", 0, &ctxt.TOC) @@ -281,6 +281,10 @@ const ( MINFUNC = 16 // minimum size for a function ) +// Symbol version of ABIInternal symbols. It is sym.SymVerABIInternal if ABI wrappers +// are used, 0 otherwise. +var abiInternalVer = sym.SymVerABIInternal + // DynlinkingGo reports whether we are producing Go code that can live // in separate shared libraries linked together at runtime. func (ctxt *Link) DynlinkingGo() bool { @@ -500,10 +504,6 @@ func (ctxt *Link) loadlib() { default: log.Fatalf("invalid -strictdups flag value %d", *FlagStrictDups) } - if !buildcfg.Experiment.RegabiWrappers { - // Use ABI aliases if ABI wrappers are not used. - flags |= loader.FlagUseABIAlias - } elfsetstring1 := func(str string, off int) { elfsetstring(ctxt, 0, str, off) } ctxt.loader = loader.NewLoader(flags, elfsetstring1, &ctxt.ErrorReporter.ErrorReporter) ctxt.ErrorReporter.SymName = func(s loader.Sym) string { @@ -769,7 +769,7 @@ func (ctxt *Link) linksetup() { // Set runtime.disableMemoryProfiling bool if // runtime.MemProfile is not retained in the binary after // deadcode (and we're not dynamically linking). - memProfile := ctxt.loader.Lookup("runtime.MemProfile", sym.SymVerABIInternal) + memProfile := ctxt.loader.Lookup("runtime.MemProfile", abiInternalVer) if memProfile != 0 && !ctxt.loader.AttrReachable(memProfile) && !ctxt.DynlinkingGo() { memProfSym := ctxt.loader.LookupOrCreateSym("runtime.disableMemoryProfiling", 0) sb := ctxt.loader.MakeSymbolUpdater(memProfSym) @@ -2115,7 +2115,7 @@ func ldshlibsyms(ctxt *Link, shlib string) { ver := 0 symname := elfsym.Name // (unmangled) symbol name if elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC && strings.HasPrefix(elfsym.Name, "type.") { - ver = sym.SymVerABIInternal + ver = abiInternalVer } else if buildcfg.Experiment.RegabiWrappers && elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC { // Demangle the ABI name. Keep in sync with symtab.go:mangleABIName. if strings.HasSuffix(elfsym.Name, ".abiinternal") { @@ -2156,19 +2156,6 @@ func ldshlibsyms(ctxt *Link, shlib string) { if symname != elfsym.Name { l.SetSymExtname(s, elfsym.Name) } - - // For function symbols, if ABI wrappers are not used, we don't - // know what ABI is available, so alias it under both ABIs. - if !buildcfg.Experiment.RegabiWrappers && elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC && ver == 0 { - alias := ctxt.loader.LookupOrCreateSym(symname, sym.SymVerABIInternal) - if l.SymType(alias) != 0 { - continue - } - su := l.MakeSymbolUpdater(alias) - su.SetType(sym.SABIALIAS) - r, _ := su.AddRel(0) // type doesn't matter - r.SetSym(s) - } } ctxt.Shlibs = append(ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps, File: f}) } diff --git a/src/cmd/link/internal/ld/macho.go b/src/cmd/link/internal/ld/macho.go index 45a3971c33..a577a5308d 100644 --- a/src/cmd/link/internal/ld/macho.go +++ b/src/cmd/link/internal/ld/macho.go @@ -7,7 +7,6 @@ package ld import ( "bytes" "cmd/internal/codesign" - "cmd/internal/obj" "cmd/internal/objabi" "cmd/internal/sys" "cmd/link/internal/loader" @@ -561,7 +560,7 @@ func (ctxt *Link) domacho() { ver := 0 // _cgo_panic is a Go function, so it uses ABIInternal. if name == "_cgo_panic" { - ver = sym.ABIToVersion(obj.ABIInternal) + ver = abiInternalVer } s := ctxt.loader.Lookup(name, ver) if s != 0 { diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go index 33b03b5024..4d3b8b904c 100644 --- a/src/cmd/link/internal/ld/main.go +++ b/src/cmd/link/internal/ld/main.go @@ -173,6 +173,10 @@ func Main(arch *sys.Arch, theArch Arch) { checkStrictDups = *FlagStrictDups + if !buildcfg.Experiment.RegabiWrappers { + abiInternalVer = 0 + } + startProfile() if ctxt.BuildMode == BuildModeUnset { ctxt.BuildMode.Set("exe") diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index 5294da5724..3abbf05c54 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -739,7 +739,7 @@ func (state *pclntab) writeFuncData(ctxt *Link, sb *loader.SymbolBuilder, funcs // writeFuncs writes the func structures and pcdata to runtime.functab. func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSyms map[loader.Sym]loader.Sym, startLocations, cuOffsets []uint32, nameOffsets map[loader.Sym]uint32) { ldr := ctxt.loader - deferReturnSym := ldr.Lookup("runtime.deferreturn", sym.SymVerABIInternal) + deferReturnSym := ldr.Lookup("runtime.deferreturn", abiInternalVer) funcdata, funcdataoff := []loader.Sym{}, []int64{} // Write the individual func objects. diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index b9a1da6f45..487559829f 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -2192,7 +2192,7 @@ func (st *loadState) preloadSyms(r *oReader, kind int) { } if strings.HasPrefix(name, "runtime.") || (loadingRuntimePkg && strings.HasPrefix(name, "type.")) { - if bi := goobj.BuiltinIdx(name, v); bi != -1 { + if bi := goobj.BuiltinIdx(name, int(osym.ABI())); bi != -1 { // This is a definition of a builtin symbol. Record where it is. l.builtinSyms[bi] = gi } diff --git a/src/cmd/link/internal/sym/symbol.go b/src/cmd/link/internal/sym/symbol.go index 4687aa53bb..2f2c839006 100644 --- a/src/cmd/link/internal/sym/symbol.go +++ b/src/cmd/link/internal/sym/symbol.go @@ -6,6 +6,7 @@ package sym import ( "cmd/internal/obj" + "internal/buildcfg" ) const ( @@ -20,6 +21,11 @@ func ABIToVersion(abi obj.ABI) int { case obj.ABI0: return SymVerABI0 case obj.ABIInternal: + if !buildcfg.Experiment.RegabiWrappers { + // If wrappers are not enabled, ABI0 and ABIInternal are actually same + // so we normalize everything to ABI0. + return SymVerABI0 + } return SymVerABIInternal } return -1 -- GitLab From 09d3df0183a78a3900a888873519cc7d994d5e19 Mon Sep 17 00:00:00 2001 From: Lynn Boger Date: Tue, 21 Sep 2021 08:39:17 -0500 Subject: [PATCH 1253/2500] cmd/compile/internal/ppc64: add initial spill support This adds some initial support for spilling and reloading registers in the new ABI for PPC64. - Code has been added to allow argument registers to be spilled around the morestack call in the prolog. - Functions for loadRegResult and spillRegArg have been added and set in the arch config for PPC64. Change-Id: I4ede3c61468857aaf06f804b5e7c3dd9da9cf36b Reviewed-on: https://go-review.googlesource.com/c/go/+/351189 Trust: Lynn Boger Run-TryBot: Lynn Boger Reviewed-by: Cherry Mui --- src/cmd/compile/internal/ppc64/galign.go | 2 ++ src/cmd/compile/internal/ppc64/ssa.go | 31 ++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/cmd/compile/internal/ppc64/galign.go b/src/cmd/compile/internal/ppc64/galign.go index bff3e38f42..6f9d1407d6 100644 --- a/src/cmd/compile/internal/ppc64/galign.go +++ b/src/cmd/compile/internal/ppc64/galign.go @@ -24,4 +24,6 @@ func Init(arch *ssagen.ArchInfo) { arch.SSAMarkMoves = ssaMarkMoves arch.SSAGenValue = ssaGenValue arch.SSAGenBlock = ssaGenBlock + arch.LoadRegResult = loadRegResult + arch.SpillArgReg = spillArgReg } diff --git a/src/cmd/compile/internal/ppc64/ssa.go b/src/cmd/compile/internal/ppc64/ssa.go index d4b85bffe3..c0f58e60b2 100644 --- a/src/cmd/compile/internal/ppc64/ssa.go +++ b/src/cmd/compile/internal/ppc64/ssa.go @@ -8,6 +8,7 @@ import ( "cmd/compile/internal/base" "cmd/compile/internal/ir" "cmd/compile/internal/logopt" + "cmd/compile/internal/objw" "cmd/compile/internal/ssa" "cmd/compile/internal/ssagen" "cmd/compile/internal/types" @@ -503,6 +504,17 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { ssagen.AddrAuto(&p.To, v) case ssa.OpArgIntReg, ssa.OpArgFloatReg: + // The assembler needs to wrap the entry safepoint/stack growth code with spill/unspill + // The loop only runs once. + for _, a := range v.Block.Func.RegArgs { + // Pass the spill/unspill information along to the assembler, offset by size of + // the saved LR slot. + addr := ssagen.SpillSlotAddr(a, ppc64.REGSP, base.Ctxt.FixedFrameSize()) + s.FuncInfo().AddSpill( + obj.RegSpill{Reg: a.Reg, Addr: addr, Unspill: loadByType(a.Type), Spill: storeByType(a.Type)}) + } + v.Block.Func.RegArgs = nil + ssagen.CheckArgReg(v) case ssa.OpPPC64DIVD: @@ -2028,3 +2040,22 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) { b.Fatalf("branch not implemented: %s", b.LongString()) } } + +func loadRegResult(s *ssagen.State, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog { + p := s.Prog(loadByType(t)) + p.From.Type = obj.TYPE_MEM + p.From.Name = obj.NAME_AUTO + p.From.Sym = n.Linksym() + p.From.Offset = n.FrameOffset() + off + p.To.Type = obj.TYPE_REG + p.To.Reg = reg + return p +} + +func spillArgReg(pp *objw.Progs, p *obj.Prog, f *ssa.Func, t *types.Type, reg int16, n *ir.Name, off int64) *obj.Prog { + p = pp.Append(p, storeByType(t), obj.TYPE_REG, reg, 0, obj.TYPE_MEM, 0, n.FrameOffset()+off) + p.To.Name = obj.NAME_PARAM + p.To.Sym = n.Linksym() + p.Pos = p.Pos.WithNotStmt() + return p +} -- GitLab From dc5b1d31c8c648b2fad1b2e85f6cca2dc1249455 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Tue, 21 Sep 2021 15:51:45 -0400 Subject: [PATCH 1254/2500] [dev.fuzz] internal/fuzz: more fuzzing output adjustments This change also makes it so that non-recoverable errors (which should be pretty rare) will no longer be minimized as these failures can be flakier and harder to minimize successfully. Updates golang/go#48132 Change-Id: I991d837993ea1fb0304b3ec491cc725ef5265652 Reviewed-on: https://go-review.googlesource.com/c/go/+/351273 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- .../go/testdata/script/test_fuzz_minimize.txt | 4 +- src/internal/fuzz/fuzz.go | 104 ++++++++++-------- src/internal/fuzz/worker.go | 40 ++++--- 3 files changed, 83 insertions(+), 65 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize.txt b/src/cmd/go/testdata/script/test_fuzz_minimize.txt index f0adb9ec3e..3ef54aed93 100644 --- a/src/cmd/go/testdata/script/test_fuzz_minimize.txt +++ b/src/cmd/go/testdata/script/test_fuzz_minimize.txt @@ -48,10 +48,10 @@ go run check_testdata.go FuzzMinimizerRecoverable 50 ! go test -run=FuzzMinimizerRecoverable minimizer_test.go rm testdata -# Test that minimization is working for non-recoverable errors. +# Test that minimization doesn't run for non-recoverable errors. ! go test -fuzz=FuzzMinimizerNonrecoverable -run=FuzzMinimizerNonrecoverable -fuzztime=10000x minimizer_test.go ! stdout '^ok' -stdout 'minimizing' +! stdout 'minimizing' stdout 'fuzzing process terminated unexpectedly: exit status 99' stdout FAIL diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 2cd7ebb472..a38036b9d2 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -228,9 +228,6 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err break } c.updateStats(result) - if c.opts.Limit > 0 && c.count >= c.opts.Limit { - stop(nil) - } if result.crasherMsg != "" { if c.warmupRun() && result.entry.IsSeed { @@ -238,7 +235,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err stop(errors.New(result.crasherMsg)) break } - if c.canMinimize() && !result.minimizeAttempted { + if c.canMinimize() && result.canMinimize { if crashMinimizing != nil { // This crash is not minimized, and another crash is being minimized. // Ignore this one and wait for the other one to finish. @@ -248,7 +245,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err // Send it back to a worker for minimization. Disable inputC so // other workers don't continue fuzzing. crashMinimizing = &result - fmt.Fprintf(c.opts.Log, "fuzz: found a %d-byte crash input; minimizing...\n", len(result.entry.Data)) + fmt.Fprintf(c.opts.Log, "fuzz: minimizing %d-byte crash input...\n", len(result.entry.Data)) c.queueForMinimization(result, nil) } else if !crashWritten { // Found a crasher that's either minimized or not minimizable. @@ -261,7 +258,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err err: errors.New(result.crasherMsg), } } - if printDebugInfo() { + if shouldPrintDebugInfo() { fmt.Fprintf( c.opts.Log, "DEBUG new crasher, elapsed: %s, id: %s, parent: %s, gen: %d, size: %d, exec time: %s\n", @@ -277,7 +274,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err } } else if result.coverageData != nil { if c.warmupRun() { - if printDebugInfo() { + if shouldPrintDebugInfo() { fmt.Fprintf( c.opts.Log, "DEBUG processed an initial input, elapsed: %s, id: %s, new bits: %d, size: %d, exec time: %s\n", @@ -289,15 +286,18 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err ) } c.updateCoverage(result.coverageData) - c.warmupInputCount-- - if printDebugInfo() && c.warmupInputCount == 0 { - fmt.Fprintf( - c.opts.Log, - "DEBUG finished processing input corpus, elapsed: %s, entries: %d, initial coverage bits: %d\n", - c.elapsed(), - len(c.corpus.entries), - countBits(c.coverageMask), - ) + c.warmupInputLeft-- + if c.warmupInputLeft == 0 { + fmt.Fprintf(c.opts.Log, "fuzz: elapsed: %s, gathering baseline coverage: %d/%d completed, now fuzzing with %d workers\n", c.elapsed(), c.warmupInputCount, c.warmupInputCount, c.opts.Parallel) + if shouldPrintDebugInfo() { + fmt.Fprintf( + c.opts.Log, + "DEBUG finished processing input corpus, elapsed: %s, entries: %d, initial coverage bits: %d\n", + c.elapsed(), + len(c.corpus.entries), + countBits(c.coverageMask), + ) + } } } else if keepCoverage := diffCoverage(c.coverageMask, result.coverageData); keepCoverage != nil { // Found a value that expanded coverage. @@ -308,7 +308,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err // number of new edges that this result expanded. // TODO(jayconrod, katiehockman): Don't write a value that's already // in the corpus. - if !result.minimizeAttempted && crashMinimizing == nil && c.canMinimize() { + if c.canMinimize() && result.canMinimize && crashMinimizing == nil { // Send back to workers to find a smaller value that preserves // at least one new coverage bit. c.queueForMinimization(result, keepCoverage) @@ -327,7 +327,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err c.corpus.entries = append(c.corpus.entries, result.entry) c.inputQueue.enqueue(result.entry) c.interestingCount++ - if printDebugInfo() { + if shouldPrintDebugInfo() { fmt.Fprintf( c.opts.Log, "DEBUG new interesting input, elapsed: %s, id: %s, parent: %s, gen: %d, new bits: %d, total bits: %d, size: %d, exec time: %s\n", @@ -343,31 +343,40 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err } } } else { - if printDebugInfo() { + if shouldPrintDebugInfo() { fmt.Fprintf( c.opts.Log, - "DEBUG worker reported interesting input that doesn't expand coverage, elapsed: %s, id: %s, parent: %s, minimized: %t\n", + "DEBUG worker reported interesting input that doesn't expand coverage, elapsed: %s, id: %s, parent: %s, canMinimize: %t\n", c.elapsed(), result.entry.Name, result.entry.Parent, - result.minimizeAttempted, + result.canMinimize, ) } } } else if c.warmupRun() { // No error or coverage data was reported for this input during // warmup, so continue processing results. - c.warmupInputCount-- - if printDebugInfo() && c.warmupInputCount == 0 { - fmt.Fprintf( - c.opts.Log, - "DEBUG finished testing-only phase, elapsed: %s, entries: %d\n", - time.Since(c.startTime), - len(c.corpus.entries), - ) + c.warmupInputLeft-- + if c.warmupInputLeft == 0 { + fmt.Fprintf(c.opts.Log, "fuzz: elapsed: %s, testing seed corpus: %d/%d completed, now fuzzing with %d workers\n", c.elapsed(), c.warmupInputCount, c.warmupInputCount, c.opts.Parallel) + if shouldPrintDebugInfo() { + fmt.Fprintf( + c.opts.Log, + "DEBUG finished testing-only phase, elapsed: %s, entries: %d\n", + time.Since(c.startTime), + len(c.corpus.entries), + ) + } } } + // Once the result has been processed, stop the worker if we + // have reached the fuzzing limit. + if c.opts.Limit > 0 && c.count >= c.opts.Limit { + stop(nil) + } + case inputC <- input: // Sent the next input to a worker. c.sentInput(input) @@ -477,9 +486,9 @@ type fuzzResult struct { // crasherMsg is an error message from a crash. It's "" if no crash was found. crasherMsg string - // minimizeAttempted is true if the worker attempted to minimize this input. - // The worker may or may not have succeeded. - minimizeAttempted bool + // canMinimize is true if the worker should attempt to minimize this result. + // It may be false because an attempt has already been made. + canMinimize bool // coverageData is set if the worker found new coverage. coverageData []byte @@ -551,12 +560,17 @@ type coordinator struct { // been found this execution. interestingCount int64 - // warmupInputCount is the number of entries in the corpus which still need - // to be received from workers to run once during warmup, but not fuzz. This - // could be for coverage data, or only for the purposes of verifying that - // the seed corpus doesn't have any crashers. See warmupRun. + // warmupInputCount is the count of all entries in the corpus which will + // need to be received from workers to run once during warmup, but not fuzz. + // This could be for coverage data, or only for the purposes of verifying + // that the seed corpus doesn't have any crashers. See warmupRun. warmupInputCount int + // warmupInputLeft is the number of entries in the corpus which still need + // to be received from workers to run once during warmup, but not fuzz. + // See warmupInputLeft. + warmupInputLeft int + // duration is the time spent fuzzing inside workers, not counting time // starting up or tearing down. duration time.Duration @@ -570,8 +584,7 @@ type coordinator struct { corpus corpus // minimizationAllowed is true if one or more of the types of fuzz - // function's parameters can be minimized, and either the limit or duration - // for minimization is non-zero. + // function's parameters can be minimized. minimizationAllowed bool // inputQueue is a queue of inputs that workers should try fuzzing. This is @@ -639,6 +652,7 @@ func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { // Set c.coverageMask to a clean []byte full of zeros. c.coverageMask = make([]byte, covSize) } + c.warmupInputLeft = c.warmupInputCount if len(c.corpus.entries) == 0 { fmt.Fprintf(c.opts.Log, "warning: starting with empty corpus\n") @@ -662,16 +676,16 @@ func (c *coordinator) updateStats(result fuzzResult) { } func (c *coordinator) logStats() { - elapsed := c.elapsed() if c.warmupRun() { + runSoFar := c.warmupInputCount - c.warmupInputLeft if coverageEnabled { - fmt.Fprintf(c.opts.Log, "gathering baseline coverage, elapsed: %s, workers: %d, left: %d\n", elapsed, c.opts.Parallel, c.warmupInputCount) + fmt.Fprintf(c.opts.Log, "fuzz: elapsed: %s, gathering baseline coverage: %d/%d completed\n", c.elapsed(), runSoFar, c.warmupInputCount) } else { - fmt.Fprintf(c.opts.Log, "testing seed corpus, elapsed: %s, workers: %d, left: %d\n", elapsed, c.opts.Parallel, c.warmupInputCount) + fmt.Fprintf(c.opts.Log, "fuzz: elapsed: %s, testing seed corpus: %d/%d completed\n", c.elapsed(), runSoFar, c.warmupInputCount) } } else { rate := float64(c.count) / time.Since(c.startTime).Seconds() // be more precise here - fmt.Fprintf(c.opts.Log, "fuzz: elapsed: %s, execs: %d (%.0f/sec), workers: %d, interesting: %d\n", elapsed, c.count, rate, c.opts.Parallel, c.interestingCount) + fmt.Fprintf(c.opts.Log, "fuzz: elapsed: %s, execs: %d (%.0f/sec), interesting: %d\n", c.elapsed(), c.count, rate, c.interestingCount) } } @@ -692,7 +706,7 @@ func (c *coordinator) peekInput() (fuzzInput, bool) { return fuzzInput{}, false } if c.inputQueue.len == 0 { - if c.warmupInputCount > 0 { + if c.warmupRun() { // Wait for coverage/testing-only run to finish before sending more // inputs. return fuzzInput{}, false @@ -819,7 +833,7 @@ func (c *coordinator) sentMinimizeInput(input fuzzMinimizeInput) { // phase ends when all workers have finished, and the coordinator has a combined // coverage map. func (c *coordinator) warmupRun() bool { - return c.warmupInputCount > 0 + return c.warmupInputLeft > 0 } // updateCoverage sets bits in c.coverageMask that are set in newCoverage. @@ -1006,7 +1020,7 @@ var ( debugInfoOnce sync.Once ) -func printDebugInfo() bool { +func shouldPrintDebugInfo() bool { debugInfoOnce.Do(func() { debug := strings.Split(os.Getenv("GODEBUG"), ",") for _, f := range debug { diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index da82a95fa1..36a7c629e5 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -140,8 +140,8 @@ func (w *worker) coordinate(ctx context.Context) error { // for example, F.Fail was called first. return fmt.Errorf("fuzzing process exited unexpectedly due to an internal failure: %w", err) } - // Worker exited non-zero or was terminated by a non-interrupt signal - // (for example, SIGSEGV) while fuzzing. + // Worker exited non-zero or was terminated by a non-interrupt + // signal (for example, SIGSEGV) while fuzzing. return fmt.Errorf("fuzzing process terminated unexpectedly: %w", err) // TODO(jayconrod,katiehockman): if -keepfuzzing, restart worker. @@ -154,6 +154,7 @@ func (w *worker) coordinate(ctx context.Context) error { CoverageData: input.coverageData, } entry, resp, err := w.client.fuzz(ctx, input.entry, args) + canMinimize := true if err != nil { // Error communicating with worker. w.stop() @@ -184,7 +185,9 @@ func (w *worker) coordinate(ctx context.Context) error { } // Unexpected termination. Set error message and fall through. // We'll restart the worker on the next iteration. + // Don't attempt to minimize this since it crashed the worker. resp.Err = fmt.Sprintf("fuzzing process terminated unexpectedly: %v", w.waitErr) + canMinimize = false } result := fuzzResult{ limit: input.limit, @@ -194,6 +197,7 @@ func (w *worker) coordinate(ctx context.Context) error { entry: entry, crasherMsg: resp.Err, coverageData: resp.CoverageData, + canMinimize: canMinimize, } w.coordinator.resultC <- result @@ -206,10 +210,10 @@ func (w *worker) coordinate(ctx context.Context) error { // TODO: double-check this is handled correctly when // implementing -keepfuzzing. result = fuzzResult{ - entry: input.entry, - crasherMsg: input.crasherMsg, - minimizeAttempted: true, - limit: input.limit, + entry: input.entry, + crasherMsg: input.crasherMsg, + canMinimize: false, + limit: input.limit, } if result.crasherMsg == "" { result.crasherMsg = err.Error() @@ -247,11 +251,11 @@ func (w *worker) minimize(ctx context.Context, input fuzzMinimizeInput) (min fuz // may not have been in a good state, but the error won't be meaningful // to the user. Just return the original crasher without logging anything. return fuzzResult{ - entry: input.entry, - crasherMsg: input.crasherMsg, - coverageData: input.keepCoverage, - minimizeAttempted: true, - limit: input.limit, + entry: input.entry, + crasherMsg: input.crasherMsg, + coverageData: input.keepCoverage, + canMinimize: false, + limit: input.limit, }, nil } return fuzzResult{}, fmt.Errorf("fuzzing process terminated unexpectedly while minimizing: %w", w.waitErr) @@ -262,13 +266,13 @@ func (w *worker) minimize(ctx context.Context, input fuzzMinimizeInput) (min fuz } return fuzzResult{ - entry: entry, - crasherMsg: resp.Err, - coverageData: resp.CoverageData, - minimizeAttempted: true, - limit: input.limit, - count: resp.Count, - totalDuration: resp.Duration, + entry: entry, + crasherMsg: resp.Err, + coverageData: resp.CoverageData, + canMinimize: false, + limit: input.limit, + count: resp.Count, + totalDuration: resp.Duration, }, nil } -- GitLab From 91c2318e67da2e5948cd8ed0420863af69142c3d Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 22 Sep 2021 10:16:06 -0400 Subject: [PATCH 1255/2500] runtime: call cgocallbackg indirectly on PPC64 This is CL 312669, for PPC64. cgocallback calls cgocallbackg after switching the stack. Call it indirectly to bypass the linker's nosplit check. The nosplit check fails after CL 351271, which removes ABI aliases. It would have been failing before but the linker's nosplit check didn't resolve ABI alias (it should) so it didn't catch that. Removing the ABI aliases exposes it. For this partuclar case it is benign as there is actually a stack switch in between. Should fix PPC64 build. Change-Id: I49617aea55270663a9ee4692c54c070c5ab85470 Reviewed-on: https://go-review.googlesource.com/c/go/+/351469 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: Than McIntosh Reviewed-by: Michael Knyszek --- src/runtime/asm_ppc64x.s | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/runtime/asm_ppc64x.s b/src/runtime/asm_ppc64x.s index 7270abbdee..18edb67988 100644 --- a/src/runtime/asm_ppc64x.s +++ b/src/runtime/asm_ppc64x.s @@ -688,7 +688,10 @@ havem: MOVD R5, FIXED_FRAME+0(R1) MOVD R6, FIXED_FRAME+8(R1) MOVD R7, FIXED_FRAME+16(R1) - BL runtime·cgocallbackg(SB) + + MOVD $runtime·cgocallbackg(SB), R12 + MOVD R12, CTR + CALL (CTR) // indirect call to bypass nosplit check. We're on a different stack now. // Restore g->sched (== m->curg->sched) from saved values. MOVD 0(R1), R5 -- GitLab From ccf140f3d79248f5dc5e326b0d2942aa4ba70b98 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Tue, 14 Sep 2021 12:40:10 -0700 Subject: [PATCH 1256/2500] internal/fuzz: allocate memory for mutated strings Rather than directly pointing at the underlying scratch slice, allocate memory for strings. This prevents mutation of previous values we've passed to the fuzz function, which may be retained by something that expects them to be immutable. Fixes golang/go#48308 Change-Id: Iee9bed1a536fdc4188180e8e7c1c722f641271d2 Reviewed-on: https://go-review.googlesource.com/c/go/+/351312 Trust: Roland Shoemaker Trust: Katie Hockman Run-TryBot: Roland Shoemaker TryBot-Result: Go Bot Reviewed-by: Jay Conrod Reviewed-by: Katie Hockman --- src/internal/fuzz/mutator.go | 7 +------ src/internal/fuzz/mutator_test.go | 16 ++++++++++++++++ src/testing/fuzz.go | 5 ++++- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/internal/fuzz/mutator.go b/src/internal/fuzz/mutator.go index 9aa56782b0..da7200dcbe 100644 --- a/src/internal/fuzz/mutator.go +++ b/src/internal/fuzz/mutator.go @@ -106,12 +106,7 @@ func (m *mutator) mutate(vals []interface{}, maxBytes int) { copy(m.scratch, v) } m.mutateBytes(&m.scratch) - var s string - shdr := (*reflect.StringHeader)(unsafe.Pointer(&s)) - bhdr := (*reflect.SliceHeader)(unsafe.Pointer(&m.scratch)) - shdr.Data = bhdr.Data - shdr.Len = bhdr.Len - vals[i] = s + vals[i] = string(m.scratch) case []byte: if len(v) > maxPerVal { panic(fmt.Sprintf("cannot mutate bytes of length %d", len(v))) diff --git a/src/internal/fuzz/mutator_test.go b/src/internal/fuzz/mutator_test.go index ee2912dfd2..d8015ce213 100644 --- a/src/internal/fuzz/mutator_test.go +++ b/src/internal/fuzz/mutator_test.go @@ -5,6 +5,7 @@ package fuzz import ( + "bytes" "fmt" "os" "strconv" @@ -99,3 +100,18 @@ func BenchmarkMutatorAllBasicTypes(b *testing.B) { }) } } + +func TestStringImmutability(t *testing.T) { + v := []interface{}{"hello"} + m := newMutator() + m.mutate(v, 1024) + original := v[0].(string) + originalCopy := make([]byte, len(original)) + copy(originalCopy, []byte(original)) + for i := 0; i < 25; i++ { + m.mutate(v, 1024) + } + if !bytes.Equal([]byte(original), originalCopy) { + t.Fatalf("string was mutated: got %x, want %x", []byte(original), originalCopy) + } +} diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 57ea418039..ddce065783 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -293,7 +293,10 @@ var supportedTypes = map[reflect.Type]bool{ // f.Fuzz(func(t *testing.T, b []byte, i int) { ... }) // // This function should be fast, deterministic, and stateless. -// None of the pointers to any input data should be retained between executions. +// +// No mutatable input arguments, or pointers to them, should be retained between +// executions of the fuzz function, as the memory backing them may be mutated +// during a subsequent invocation. // // This is a terminal function which will terminate the currently running fuzz // target by calling runtime.Goexit. -- GitLab From 5ee32ff2527b64197f2eb09bc45e73e61c9c1ac3 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Tue, 21 Sep 2021 16:05:57 -0400 Subject: [PATCH 1257/2500] cmd/go: proceed with GOPATH unset if the command doesn't use it For #43938 Change-Id: I0937b9bb6de3d29d7242ee61f053d4803277dc0f Reviewed-on: https://go-review.googlesource.com/c/go/+/351329 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/modfetch/cache.go | 2 +- src/cmd/go/internal/modload/init.go | 17 +++++++++++------ src/cmd/go/testdata/script/mod_gomodcache.txt | 13 ++++++++++--- src/cmd/go/testdata/script/mod_no_gopath.txt | 15 +++++++++++++++ 4 files changed, 37 insertions(+), 10 deletions(-) create mode 100644 src/cmd/go/testdata/script/mod_no_gopath.txt diff --git a/src/cmd/go/internal/modfetch/cache.go b/src/cmd/go/internal/modfetch/cache.go index b01b467413..8d299e931a 100644 --- a/src/cmd/go/internal/modfetch/cache.go +++ b/src/cmd/go/internal/modfetch/cache.go @@ -720,7 +720,7 @@ func checkCacheDir() error { if cfg.GOMODCACHE == "" { // modload.Init exits if GOPATH[0] is empty, and cfg.GOMODCACHE // is set to GOPATH[0]/pkg/mod if GOMODCACHE is empty, so this should never happen. - return fmt.Errorf("internal error: cfg.GOMODCACHE not set") + return fmt.Errorf("module cache not found: neither GOMODCACHE nor GOPATH is set") } if !filepath.IsAbs(cfg.GOMODCACHE) { return fmt.Errorf("GOMODCACHE entry is relative; must be absolute path: %q.\n", cfg.GOMODCACHE) diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index a855e6c851..83414feb3c 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -246,6 +246,12 @@ func ModFile() *modfile.File { func BinDir() string { Init() + if cfg.GOBIN != "" { + return cfg.GOBIN + } + if gopath == "" { + return "" + } return filepath.Join(gopath, "bin") } @@ -381,12 +387,11 @@ func Init() { "verify, graph, and why. Implement support for go mod download and add test cases" + "to ensure verify, graph, and why work properly.") list := filepath.SplitList(cfg.BuildContext.GOPATH) - if len(list) == 0 || list[0] == "" { - base.Fatalf("missing $GOPATH") - } - gopath = list[0] - if _, err := fsys.Stat(filepath.Join(gopath, "go.mod")); err == nil { - base.Fatalf("$GOPATH/go.mod exists but should not") + if len(list) > 0 && list[0] != "" { + gopath = list[0] + if _, err := fsys.Stat(filepath.Join(gopath, "go.mod")); err == nil { + base.Fatalf("$GOPATH/go.mod exists but should not") + } } if inWorkspaceMode() { diff --git a/src/cmd/go/testdata/script/mod_gomodcache.txt b/src/cmd/go/testdata/script/mod_gomodcache.txt index 74a3c79622..a9d7ab3f04 100644 --- a/src/cmd/go/testdata/script/mod_gomodcache.txt +++ b/src/cmd/go/testdata/script/mod_gomodcache.txt @@ -31,11 +31,18 @@ env GOPATH= go env GOMODCACHE stdout $HOME[/\\]go[/\\]pkg[/\\]mod -# If GOMODCACHE isn't set and GOPATH starts with the path list separator, it's an error. +# If GOMODCACHE isn't set and GOPATH starts with the path list separator, +# GOMODCACHE is empty and any command that needs it errors out. env GOMODCACHE= env GOPATH=${:}$WORK/this/is/ignored -! go env GOMODCACHE -stderr 'missing \$GOPATH' + +go env GOMODCACHE +stdout '^$' +! stdout . +! stderr . + +! go mod download rsc.io/quote@v1.0.0 +stderr '^go: module cache not found: neither GOMODCACHE nor GOPATH is set$' # If GOMODCACHE isn't set and GOPATH has multiple elements only the first is used. env GOMODCACHE= diff --git a/src/cmd/go/testdata/script/mod_no_gopath.txt b/src/cmd/go/testdata/script/mod_no_gopath.txt new file mode 100644 index 0000000000..ed91f5d42e --- /dev/null +++ b/src/cmd/go/testdata/script/mod_no_gopath.txt @@ -0,0 +1,15 @@ +# https://golang.org/issue/43938: 'go build' should succeed +# if GOPATH and the variables needed for its default value +# are all unset but not relevant to the specific command. + +env HOME='' +env home='' +env GOPATH='' + +go list -deps main.go +stdout '^io$' + +-- main.go -- +package main + +import _ "io" -- GitLab From a630783ba0d1816f684bdab18b6f9f03dc93a209 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 21 Sep 2021 14:55:23 -0400 Subject: [PATCH 1258/2500] cmd/internal/obj: remove ABI aliases from object file Change-Id: I8a51f054e017e0116dee4e435b60c08d72e998e9 Reviewed-on: https://go-review.googlesource.com/c/go/+/351331 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/internal/obj/link.go | 10 ---------- src/cmd/internal/obj/sym.go | 4 ++-- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index 28626e6e03..592d2a655b 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -902,16 +902,6 @@ type Link struct { Text []*LSym Data []*LSym - // ABIAliases are text symbols that should be aliased to all - // ABIs. These symbols may only be referenced and not defined - // by this object, since the need for an alias may appear in a - // different object than the definition. Hence, this - // information can't be carried in the symbol definition. - // - // TODO(austin): Replace this with ABI wrappers once the ABIs - // actually diverge. - ABIAliases []*LSym - // Constant symbols (e.g. $i64.*) are data symbols created late // in the concurrent phase. To ensure a deterministic order, we // add them to a separate list, sort at the end, and append it diff --git a/src/cmd/internal/obj/sym.go b/src/cmd/internal/obj/sym.go index 9e8b4dd790..3289115439 100644 --- a/src/cmd/internal/obj/sym.go +++ b/src/cmd/internal/obj/sym.go @@ -330,7 +330,7 @@ const ( // Traverse symbols based on flag, call fn for each symbol. func (ctxt *Link) traverseSyms(flag traverseFlag, fn func(*LSym)) { - lists := [][]*LSym{ctxt.Text, ctxt.Data, ctxt.ABIAliases} + lists := [][]*LSym{ctxt.Text, ctxt.Data} for _, list := range lists { for _, s := range list { if flag&traverseDefs != 0 { @@ -410,7 +410,7 @@ func (ctxt *Link) traverseFuncAux(flag traverseFlag, fsym *LSym, fn func(parent // Traverse aux symbols, calling fn for each sym/aux pair. func (ctxt *Link) traverseAuxSyms(flag traverseFlag, fn func(parent *LSym, aux *LSym)) { - lists := [][]*LSym{ctxt.Text, ctxt.Data, ctxt.ABIAliases} + lists := [][]*LSym{ctxt.Text, ctxt.Data} for _, list := range lists { for _, s := range list { if s.Gotype != nil { -- GitLab From 55d22f74900cae2ff9444eb81b9084175606b5dc Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 21 Sep 2021 17:52:19 -0400 Subject: [PATCH 1259/2500] cmd/link: remove ABI aliases It is now gone. Change-Id: I59f68b324af706476695de2f291dd3aa5734e192 Reviewed-on: https://go-review.googlesource.com/c/go/+/351332 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/internal/objabi/symkind.go | 7 ------- src/cmd/internal/objabi/symkind_string.go | 7 +++---- src/cmd/link/internal/arm/asm.go | 3 +-- src/cmd/link/internal/arm64/asm.go | 2 +- src/cmd/link/internal/ld/data.go | 16 ++++++--------- src/cmd/link/internal/ld/lib.go | 2 +- src/cmd/link/internal/ld/pe.go | 1 - src/cmd/link/internal/ld/xcoff.go | 4 ++-- src/cmd/link/internal/loader/loader.go | 22 --------------------- src/cmd/link/internal/mips/asm.go | 1 - src/cmd/link/internal/mips64/asm.go | 1 - src/cmd/link/internal/ppc64/asm.go | 10 +++++----- src/cmd/link/internal/riscv64/asm.go | 2 +- src/cmd/link/internal/sym/symkind.go | 4 ---- src/cmd/link/internal/sym/symkind_string.go | 5 ++--- src/cmd/link/internal/wasm/asm.go | 2 +- 16 files changed, 23 insertions(+), 66 deletions(-) diff --git a/src/cmd/internal/objabi/symkind.go b/src/cmd/internal/objabi/symkind.go index 6c991121e7..28f430fc54 100644 --- a/src/cmd/internal/objabi/symkind.go +++ b/src/cmd/internal/objabi/symkind.go @@ -65,13 +65,6 @@ const ( SDWARFRANGE SDWARFLOC SDWARFLINES - // ABI alias. An ABI alias symbol is an empty symbol with a - // single relocation with 0 size that references the native - // function implementation symbol. - // - // TODO(austin): Remove this and all uses once the compiler - // generates real ABI wrappers rather than symbol aliases. - SABIALIAS // Coverage instrumentation counter for libfuzzer. SLIBFUZZER_EXTRA_COUNTER // Update cmd/link/internal/sym/AbiSymKindToSymKind for new SymKind values. diff --git a/src/cmd/internal/objabi/symkind_string.go b/src/cmd/internal/objabi/symkind_string.go index 1b1c394038..c90cf43b50 100644 --- a/src/cmd/internal/objabi/symkind_string.go +++ b/src/cmd/internal/objabi/symkind_string.go @@ -25,13 +25,12 @@ func _() { _ = x[SDWARFRANGE-14] _ = x[SDWARFLOC-15] _ = x[SDWARFLINES-16] - _ = x[SABIALIAS-17] - _ = x[SLIBFUZZER_EXTRA_COUNTER-18] + _ = x[SLIBFUZZER_EXTRA_COUNTER-17] } -const _SymKind_name = "SxxxSTEXTSRODATASNOPTRDATASDATASBSSSNOPTRBSSSTLSBSSSDWARFCUINFOSDWARFCONSTSDWARFFCNSDWARFABSFCNSDWARFTYPESDWARFVARSDWARFRANGESDWARFLOCSDWARFLINESSABIALIASSLIBFUZZER_EXTRA_COUNTER" +const _SymKind_name = "SxxxSTEXTSRODATASNOPTRDATASDATASBSSSNOPTRBSSSTLSBSSSDWARFCUINFOSDWARFCONSTSDWARFFCNSDWARFABSFCNSDWARFTYPESDWARFVARSDWARFRANGESDWARFLOCSDWARFLINESSLIBFUZZER_EXTRA_COUNTER" -var _SymKind_index = [...]uint8{0, 4, 9, 16, 26, 31, 35, 44, 51, 63, 74, 83, 95, 105, 114, 125, 134, 145, 154, 178} +var _SymKind_index = [...]uint8{0, 4, 9, 16, 26, 31, 35, 44, 51, 63, 74, 83, 95, 105, 114, 125, 134, 145, 169} func (i SymKind) String() string { if i >= SymKind(len(_SymKind_index)-1) { diff --git a/src/cmd/link/internal/arm/asm.go b/src/cmd/link/internal/arm/asm.go index ab780214bb..347932c6e1 100644 --- a/src/cmd/link/internal/arm/asm.go +++ b/src/cmd/link/internal/arm/asm.go @@ -544,7 +544,6 @@ func gentrampdyn(arch *sys.Arch, tramp *loader.SymbolBuilder, target loader.Sym, func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) (o int64, nExtReloc int, ok bool) { rs := r.Sym() - rs = ldr.ResolveABIAlias(rs) if target.IsExternal() { switch r.Type() { case objabi.R_CALLARM: @@ -592,7 +591,7 @@ func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc, sym.RelocVariant } func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) { - rs := ldr.ResolveABIAlias(r.Sym()) + rs := r.Sym() var rr loader.ExtReloc switch r.Type() { case objabi.R_CALLARM: diff --git a/src/cmd/link/internal/arm64/asm.go b/src/cmd/link/internal/arm64/asm.go index c10bdc4120..f56c9c1222 100644 --- a/src/cmd/link/internal/arm64/asm.go +++ b/src/cmd/link/internal/arm64/asm.go @@ -668,7 +668,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade const noExtReloc = 0 const isOk = true - rs := ldr.ResolveABIAlias(r.Sym()) + rs := r.Sym() if target.IsExternal() { nExtReloc := 0 diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 1898ee020c..1d65c49381 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -113,7 +113,6 @@ func trampoline(ctxt *Link, s loader.Sym) { if !ldr.AttrReachable(rs) || ldr.SymType(rs) == sym.Sxxx { continue // something is wrong. skip it here and we'll emit a better error later } - rs = ldr.ResolveABIAlias(rs) if ldr.SymValue(rs) == 0 && (ldr.SymType(rs) != sym.SDYNIMPORT && ldr.SymType(rs) != sym.SUNDEFEXT) { if ldr.SymPkg(s) != "" && ldr.SymPkg(rs) == ldr.SymPkg(s) { // Symbols in the same package are laid out together. @@ -194,7 +193,6 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) { off := r.Off() siz := int32(r.Siz()) rs := r.Sym() - rs = ldr.ResolveABIAlias(rs) rt := r.Type() weak := r.Weak() if off < 0 || off+siz > int32(len(P)) { @@ -340,7 +338,6 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) { if weak && !ldr.AttrReachable(rs) { // Redirect it to runtime.unreachableMethod, which will throw if called. rs = syms.unreachableMethod - rs = ldr.ResolveABIAlias(rs) } if target.IsExternal() { nExtReloc++ @@ -614,7 +611,7 @@ func extreloc(ctxt *Link, ldr *loader.Loader, s loader.Sym, r loader.Reloc) (loa case objabi.R_TLS_LE, objabi.R_TLS_IE: if target.IsElf() { - rs := ldr.ResolveABIAlias(r.Sym()) + rs := r.Sym() rr.Xsym = rs if rr.Xsym == 0 { rr.Xsym = ctxt.Tlsg @@ -626,10 +623,9 @@ func extreloc(ctxt *Link, ldr *loader.Loader, s loader.Sym, r loader.Reloc) (loa case objabi.R_ADDR: // set up addend for eventual relocation via outer symbol. - rs := ldr.ResolveABIAlias(r.Sym()) + rs := r.Sym() if r.Weak() && !ldr.AttrReachable(rs) { rs = ctxt.ArchSyms.unreachableMethod - rs = ldr.ResolveABIAlias(rs) } rs, off := FoldSubSymbolOffset(ldr, rs) rr.Xadd = r.Add() + off @@ -644,13 +640,13 @@ func extreloc(ctxt *Link, ldr *loader.Loader, s loader.Sym, r loader.Reloc) (loa if target.IsDarwin() { return rr, false } - rs := ldr.ResolveABIAlias(r.Sym()) + rs := r.Sym() rr.Xsym = loader.Sym(ldr.SymSect(rs).Sym) rr.Xadd = r.Add() + ldr.SymValue(rs) - int64(ldr.SymSect(rs).Vaddr) // r.Sym() can be 0 when CALL $(constant) is transformed from absolute PC to relative PC call. case objabi.R_GOTPCREL, objabi.R_CALL, objabi.R_PCREL: - rs := ldr.ResolveABIAlias(r.Sym()) + rs := r.Sym() if rt == objabi.R_GOTPCREL && target.IsDynlinkingGo() && target.IsDarwin() && rs != 0 { rr.Xadd = r.Add() rr.Xadd -= int64(siz) // relative to address after the relocated chunk @@ -692,7 +688,7 @@ func extreloc(ctxt *Link, ldr *loader.Loader, s loader.Sym, r loader.Reloc) (loa // symbol and addend. func ExtrelocSimple(ldr *loader.Loader, r loader.Reloc) loader.ExtReloc { var rr loader.ExtReloc - rs := ldr.ResolveABIAlias(r.Sym()) + rs := r.Sym() rr.Xsym = rs rr.Xadd = r.Add() rr.Type = r.Type() @@ -705,7 +701,7 @@ func ExtrelocSimple(ldr *loader.Loader, r loader.Reloc) loader.ExtReloc { func ExtrelocViaOuterSym(ldr *loader.Loader, r loader.Reloc, s loader.Sym) loader.ExtReloc { // set up addend for eventual relocation via outer symbol. var rr loader.ExtReloc - rs := ldr.ResolveABIAlias(r.Sym()) + rs := r.Sym() rs, off := FoldSubSymbolOffset(ldr, rs) rr.Xadd = r.Add() + off rst := ldr.SymType(rs) diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index f46d1f0221..feff16d0c0 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -2471,7 +2471,7 @@ func (ctxt *Link) callgraph() { if rs == 0 { continue } - if r.Type().IsDirectCall() && (ldr.SymType(rs) == sym.STEXT || ldr.SymType(rs) == sym.SABIALIAS) { + if r.Type().IsDirectCall() && ldr.SymType(rs) == sym.STEXT { ctxt.Logf("%s calls %s\n", ldr.SymName(s), ldr.SymName(rs)) } } diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go index 871bf8de2b..b7d413e9a9 100644 --- a/src/cmd/link/internal/ld/pe.go +++ b/src/cmd/link/internal/ld/pe.go @@ -1514,7 +1514,6 @@ func addPEBaseRelocSym(ldr *loader.Loader, s loader.Sym, rt *peBaseRelocTable) { continue } rs := r.Sym() - rs = ldr.ResolveABIAlias(rs) if rs == 0 { continue } diff --git a/src/cmd/link/internal/ld/xcoff.go b/src/cmd/link/internal/ld/xcoff.go index 12bd23f7e5..b57ccb4fe0 100644 --- a/src/cmd/link/internal/ld/xcoff.go +++ b/src/cmd/link/internal/ld/xcoff.go @@ -1238,7 +1238,7 @@ func Xcoffadddynrel(target *Target, ldr *loader.Loader, syms *ArchSyms, s loader sym: s, roff: r.Off(), } - targ := ldr.ResolveABIAlias(r.Sym()) + targ := r.Sym() var targType sym.SymKind if targ != 0 { targType = ldr.SymType(targ) @@ -1333,7 +1333,7 @@ func (ctxt *Link) doxcoff() { panic("cgo_export on static symbol") } - if ldr.SymType(s) == sym.STEXT || ldr.SymType(s) == sym.SABIALIAS { + if ldr.SymType(s) == sym.STEXT { // On AIX, a exported function must have two symbols: // - a .text symbol which must start with a ".". // - a .data symbol which is a function descriptor. diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index 487559829f..dcc33b966b 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -307,7 +307,6 @@ type extSymPayload struct { const ( // Loader.flags FlagStrictDups = 1 << iota - FlagUseABIAlias ) func NewLoader(flags uint32, elfsetstring elfsetstringFunc, reporter *ErrorReporter) *Loader { @@ -2297,27 +2296,6 @@ func abiToVer(abi uint16, localSymVersion int) int { return v } -// ResolveABIAlias given a symbol returns the ABI alias target of that -// symbol. If the sym in question is not an alias, the sym itself is -// returned. -func (l *Loader) ResolveABIAlias(s Sym) Sym { - if l.flags&FlagUseABIAlias == 0 { - return s - } - if s == 0 { - return 0 - } - if l.SymType(s) != sym.SABIALIAS { - return s - } - relocs := l.Relocs(s) - target := relocs.At(0).Sym() - if l.SymType(target) == sym.SABIALIAS { - panic(fmt.Sprintf("ABI alias %s references another ABI alias %s", l.SymName(s), l.SymName(target))) - } - return target -} - // TopLevelSym tests a symbol (by name and kind) to determine whether // the symbol first class sym (participating in the link) or is an // anonymous aux or sub-symbol containing some sub-part or payload of diff --git a/src/cmd/link/internal/mips/asm.go b/src/cmd/link/internal/mips/asm.go index 8505dc6109..5891d35888 100644 --- a/src/cmd/link/internal/mips/asm.go +++ b/src/cmd/link/internal/mips/asm.go @@ -92,7 +92,6 @@ func applyrel(arch *sys.Arch, ldr *loader.Loader, rt objabi.RelocType, off int32 func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) (o int64, nExtReloc int, ok bool) { rs := r.Sym() - rs = ldr.ResolveABIAlias(rs) if target.IsExternal() { switch r.Type() { default: diff --git a/src/cmd/link/internal/mips64/asm.go b/src/cmd/link/internal/mips64/asm.go index f7f91d1e8b..0e64af3e6a 100644 --- a/src/cmd/link/internal/mips64/asm.go +++ b/src/cmd/link/internal/mips64/asm.go @@ -120,7 +120,6 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade const isOk = true const noExtReloc = 0 rs := r.Sym() - rs = ldr.ResolveABIAlias(rs) switch r.Type() { case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSU: diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go index b877864b75..9507010603 100644 --- a/src/cmd/link/internal/ppc64/asm.go +++ b/src/cmd/link/internal/ppc64/asm.go @@ -547,7 +547,7 @@ func symtoc(ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) int64 { // symbol address can be used directly. // This code is for AIX only. func archreloctoc(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) int64 { - rs := ldr.ResolveABIAlias(r.Sym()) + rs := r.Sym() if target.IsLinux() { ldr.Errorf(s, "archrelocaddr called for %s relocation\n", ldr.SymName(rs)) } @@ -562,7 +562,7 @@ func archreloctoc(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r lo var t int64 useAddi := false relocs := ldr.Relocs(rs) - tarSym := ldr.ResolveABIAlias(relocs.At(0).Sym()) + tarSym := relocs.At(0).Sym() if target.IsInternal() && tarSym != 0 && ldr.AttrReachable(tarSym) && ldr.SymSect(tarSym).Seg == &ld.Segdata { t = ldr.SymValue(tarSym) + r.Add() - ldr.SymValue(syms.TOC) @@ -603,7 +603,7 @@ func archreloctoc(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r lo // archrelocaddr relocates a symbol address. // This code is for AIX only. func archrelocaddr(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) int64 { - rs := ldr.ResolveABIAlias(r.Sym()) + rs := r.Sym() if target.IsAIX() { ldr.Errorf(s, "archrelocaddr called for %s relocation\n", ldr.SymName(rs)) } @@ -802,7 +802,7 @@ func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, ta } func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) (relocatedOffset int64, nExtReloc int, ok bool) { - rs := ldr.ResolveABIAlias(r.Sym()) + rs := r.Sym() if target.IsExternal() { // On AIX, relocations (except TLS ones) must be also done to the // value with the current addresses. @@ -909,7 +909,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade } func archrelocvariant(target *ld.Target, ldr *loader.Loader, r loader.Reloc, rv sym.RelocVariant, s loader.Sym, t int64, p []byte) (relocatedOffset int64) { - rs := ldr.ResolveABIAlias(r.Sym()) + rs := r.Sym() switch rv & sym.RV_TYPE_MASK { default: ldr.Errorf(s, "unexpected relocation variant %d", rv) diff --git a/src/cmd/link/internal/riscv64/asm.go b/src/cmd/link/internal/riscv64/asm.go index 57a3c34836..ef941e52e9 100644 --- a/src/cmd/link/internal/riscv64/asm.go +++ b/src/cmd/link/internal/riscv64/asm.go @@ -168,7 +168,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade return val, 0, false } - rs := ldr.ResolveABIAlias(r.Sym()) + rs := r.Sym() switch r.Type() { case objabi.R_CALLRISCV: diff --git a/src/cmd/link/internal/sym/symkind.go b/src/cmd/link/internal/sym/symkind.go index c176d5e208..20b504e505 100644 --- a/src/cmd/link/internal/sym/symkind.go +++ b/src/cmd/link/internal/sym/symkind.go @@ -118,9 +118,6 @@ const ( SDWARFRANGE SDWARFLOC SDWARFLINES - - // ABI aliases (these never appear in the output) - SABIALIAS ) // AbiSymKindToSymKind maps values read from object files (which are @@ -143,7 +140,6 @@ var AbiSymKindToSymKind = [...]SymKind{ SDWARFRANGE, SDWARFLOC, SDWARFLINES, - SABIALIAS, SLIBFUZZER_EXTRA_COUNTER, } diff --git a/src/cmd/link/internal/sym/symkind_string.go b/src/cmd/link/internal/sym/symkind_string.go index 34cb314bd5..bf8eda713e 100644 --- a/src/cmd/link/internal/sym/symkind_string.go +++ b/src/cmd/link/internal/sym/symkind_string.go @@ -65,12 +65,11 @@ func _() { _ = x[SDWARFRANGE-54] _ = x[SDWARFLOC-55] _ = x[SDWARFLINES-56] - _ = x[SABIALIAS-57] } -const _SymKind_name = "SxxxSTEXTSELFRXSECTSMACHOPLTSTYPESSTRINGSGOSTRINGSGOFUNCSGCBITSSRODATASFUNCTABSELFROSECTSTYPERELROSSTRINGRELROSGOSTRINGRELROSGOFUNCRELROSGCBITSRELROSRODATARELROSFUNCTABRELROSTYPELINKSITABLINKSSYMTABSPCLNTABSFirstWritableSBUILDINFOSELFSECTSMACHOSMACHOGOTSWINDOWSSELFGOTSNOPTRDATASINITARRSDATASXCOFFTOCSBSSSNOPTRBSSSLIBFUZZER_EXTRA_COUNTERSTLSBSSSXREFSMACHOSYMSTRSMACHOSYMTABSMACHOINDIRECTPLTSMACHOINDIRECTGOTSFILEPATHSDYNIMPORTSHOSTOBJSUNDEFEXTSDWARFSECTSDWARFCUINFOSDWARFCONSTSDWARFFCNSDWARFABSFCNSDWARFTYPESDWARFVARSDWARFRANGESDWARFLOCSDWARFLINESSABIALIAS" +const _SymKind_name = "SxxxSTEXTSELFRXSECTSMACHOPLTSTYPESSTRINGSGOSTRINGSGOFUNCSGCBITSSRODATASFUNCTABSELFROSECTSTYPERELROSSTRINGRELROSGOSTRINGRELROSGOFUNCRELROSGCBITSRELROSRODATARELROSFUNCTABRELROSTYPELINKSITABLINKSSYMTABSPCLNTABSFirstWritableSBUILDINFOSELFSECTSMACHOSMACHOGOTSWINDOWSSELFGOTSNOPTRDATASINITARRSDATASXCOFFTOCSBSSSNOPTRBSSSLIBFUZZER_EXTRA_COUNTERSTLSBSSSXREFSMACHOSYMSTRSMACHOSYMTABSMACHOINDIRECTPLTSMACHOINDIRECTGOTSFILEPATHSDYNIMPORTSHOSTOBJSUNDEFEXTSDWARFSECTSDWARFCUINFOSDWARFCONSTSDWARFFCNSDWARFABSFCNSDWARFTYPESDWARFVARSDWARFRANGESDWARFLOCSDWARFLINES" -var _SymKind_index = [...]uint16{0, 4, 9, 19, 28, 33, 40, 49, 56, 63, 70, 78, 88, 98, 110, 124, 136, 148, 160, 173, 182, 191, 198, 206, 220, 230, 238, 244, 253, 261, 268, 278, 286, 291, 300, 304, 313, 337, 344, 349, 361, 373, 390, 407, 416, 426, 434, 443, 453, 465, 476, 485, 497, 507, 516, 527, 536, 547, 556} +var _SymKind_index = [...]uint16{0, 4, 9, 19, 28, 33, 40, 49, 56, 63, 70, 78, 88, 98, 110, 124, 136, 148, 160, 173, 182, 191, 198, 206, 220, 230, 238, 244, 253, 261, 268, 278, 286, 291, 300, 304, 313, 337, 344, 349, 361, 373, 390, 407, 416, 426, 434, 443, 453, 465, 476, 485, 497, 507, 516, 527, 536, 547} func (i SymKind) String() string { if i >= SymKind(len(_SymKind_index)-1) { diff --git a/src/cmd/link/internal/wasm/asm.go b/src/cmd/link/internal/wasm/asm.go index 5bdfdbaee6..01c500ed70 100644 --- a/src/cmd/link/internal/wasm/asm.go +++ b/src/cmd/link/internal/wasm/asm.go @@ -173,7 +173,7 @@ func asmb2(ctxt *ld.Link, ldr *loader.Loader) { } wfn.Write(P[off:r.Off()]) off = r.Off() - rs := ldr.ResolveABIAlias(r.Sym()) + rs := r.Sym() switch r.Type() { case objabi.R_ADDR: writeSleb128(wfn, ldr.SymValue(rs)+r.Add()) -- GitLab From 74ba70be680a9eb9740638b80f36f68baec5b35c Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 21 Sep 2021 18:05:28 -0400 Subject: [PATCH 1260/2500] cmd/link: use keyed literal for AbiSymKindToSymKind The correspondence is clearer. Also avoid accidental mismatch. Change-Id: Ibd9a31cfcd7c2301614f3496cac67cbae99972a9 Reviewed-on: https://go-review.googlesource.com/c/go/+/351334 Trust: Cherry Mui Reviewed-by: Than McIntosh --- src/cmd/link/internal/sym/symkind.go | 38 +++++++++++++++------------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/cmd/link/internal/sym/symkind.go b/src/cmd/link/internal/sym/symkind.go index 20b504e505..0a0741f84b 100644 --- a/src/cmd/link/internal/sym/symkind.go +++ b/src/cmd/link/internal/sym/symkind.go @@ -30,6 +30,8 @@ package sym +import "cmd/internal/objabi" + // A SymKind describes the kind of memory represented by a symbol. type SymKind uint8 @@ -123,24 +125,24 @@ const ( // AbiSymKindToSymKind maps values read from object files (which are // of type cmd/internal/objabi.SymKind) to values of type SymKind. var AbiSymKindToSymKind = [...]SymKind{ - Sxxx, - STEXT, - SRODATA, - SNOPTRDATA, - SDATA, - SBSS, - SNOPTRBSS, - STLSBSS, - SDWARFCUINFO, - SDWARFCONST, - SDWARFFCN, - SDWARFABSFCN, - SDWARFTYPE, - SDWARFVAR, - SDWARFRANGE, - SDWARFLOC, - SDWARFLINES, - SLIBFUZZER_EXTRA_COUNTER, + objabi.Sxxx: Sxxx, + objabi.STEXT: STEXT, + objabi.SRODATA: SRODATA, + objabi.SNOPTRDATA: SNOPTRDATA, + objabi.SDATA: SDATA, + objabi.SBSS: SBSS, + objabi.SNOPTRBSS: SNOPTRBSS, + objabi.STLSBSS: STLSBSS, + objabi.SDWARFCUINFO: SDWARFCUINFO, + objabi.SDWARFCONST: SDWARFCONST, + objabi.SDWARFFCN: SDWARFFCN, + objabi.SDWARFABSFCN: SDWARFABSFCN, + objabi.SDWARFTYPE: SDWARFTYPE, + objabi.SDWARFVAR: SDWARFVAR, + objabi.SDWARFRANGE: SDWARFRANGE, + objabi.SDWARFLOC: SDWARFLOC, + objabi.SDWARFLINES: SDWARFLINES, + objabi.SLIBFUZZER_EXTRA_COUNTER: SLIBFUZZER_EXTRA_COUNTER, } // ReadOnly are the symbol kinds that form read-only sections. In some -- GitLab From e128749be88278768c50907ca87270b9d5e96eb5 Mon Sep 17 00:00:00 2001 From: Archana R Date: Sun, 19 Sep 2021 23:50:02 -0500 Subject: [PATCH 1261/2500] hash/crc32: improve performance of ppc64SlicingUpdateBy8 on ppc64le MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduce the number of instructions in the short loop of ppc64SlicingUpdateBy8 function by combining MOVWZ and SRD into a SRD with appropriate parameters performing the same operation and remove MOVWZ R7,R7 from the loop This change produces the following improvements on POWER9. None of the other tests regress. Improvments on other POWERPC platforms similar. name old time/op new time/op delta CRC32/poly=IEEE/size=15/align=0 80.5ns ± 0% 70.6ns ± 0% -12% CRC32/poly=IEEE/size=15/align=1 80.5ns ± 0% 70.6ns ± 0% -12% CRC32/poly=IEEE/size=512/align=1 151ns ± 0% 139ns ± 0% -7% CRC32/poly=IEEE/size=1kB/align=1 167ns ± 0% 155ns ± 0% -7% CRC32/poly=Castagnoli/size=15/align=0 80.2ns ± 0% 70.5ns ± 0% -12% CRC32/poly=Castagnoli/size=15/align=1 80.2ns ± 0% 70.5ns ± 0% -12% CRC32/poly=Castagnoli/size=512/align=1 150ns ± 0% 139ns ± 0% -7% CRC32/poly=Castagnoli/size=1kB/align=1 166ns ± 0% 155ns ± 0% -6% Change-Id: I424709041c30d1c637b595d0845e3ae78dc3e0a0 Reviewed-on: https://go-review.googlesource.com/c/go/+/350989 Reviewed-by: Lynn Boger Reviewed-by: Cherry Mui Run-TryBot: Lynn Boger TryBot-Result: Go Bot --- src/hash/crc32/crc32_ppc64le.s | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/hash/crc32/crc32_ppc64le.s b/src/hash/crc32/crc32_ppc64le.s index 10d5dd61db..763d3270f3 100644 --- a/src/hash/crc32/crc32_ppc64le.s +++ b/src/hash/crc32/crc32_ppc64le.s @@ -112,19 +112,17 @@ loop: ANDCC $7,R6,R8 // any leftover bytes BEQ done // none --> done MOVD R8,CTR // byte count - + PCALIGN $16 // align short loop short: MOVBZ 0(R5),R8 // get v MOVBZ R7,R9 // byte(crc) -> R8 BE vs LE? - MOVWZ R7,R14 - SRD $8,R14,R14 // crc>>8 + SRD $8,R7,R14 // crc>>8 XOR R8,R9,R8 // byte(crc)^v -> R8 ADD $1,R5 // ptr to next v SLD $2,R8 // convert index-> bytes ADD R8,R4,R9 // &tab[byte(crc)^v] MOVWZ 0(R9),R10 // tab[byte(crc)^v] XOR R10,R14,R7 // loop crc in R7 - MOVWZ R7,R7 // 32 bits BC 16,0,short done: NOR R7,R7,R7 // ^crc -- GitLab From 635e49388bf746a2b8c7ab1e9026aede0eb88b31 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Wed, 15 Sep 2021 14:36:54 +0100 Subject: [PATCH 1262/2500] cmd/cgo: add go:notinheap annotation to Windows handle types Fixes #42018 Change-Id: I6a40f3effe860e67a45fca2e8ab86f3e9887ffee Reviewed-on: https://go-review.googlesource.com/c/go/+/350070 Trust: Elias Naur Reviewed-by: Keith Randall Run-TryBot: Keith Randall --- misc/cgo/test/cgo_test.go | 1 + misc/cgo/test/issue42018.go | 14 ++++++ misc/cgo/test/issue42018_windows.go | 46 ++++++++++++++++++ src/cmd/cgo/gcc.go | 73 +++++++++++++++++++++++++++++ src/cmd/cgo/out.go | 1 + 5 files changed, 135 insertions(+) create mode 100644 misc/cgo/test/issue42018.go create mode 100644 misc/cgo/test/issue42018_windows.go diff --git a/misc/cgo/test/cgo_test.go b/misc/cgo/test/cgo_test.go index 143f23f0e0..fe99e251e9 100644 --- a/misc/cgo/test/cgo_test.go +++ b/misc/cgo/test/cgo_test.go @@ -59,6 +59,7 @@ func Test28896(t *testing.T) { test28896(t) } func Test30065(t *testing.T) { test30065(t) } func Test32579(t *testing.T) { test32579(t) } func Test31891(t *testing.T) { test31891(t) } +func Test42018(t *testing.T) { test42018(t) } func Test45451(t *testing.T) { test45451(t) } func TestAlign(t *testing.T) { testAlign(t) } func TestAtol(t *testing.T) { testAtol(t) } diff --git a/misc/cgo/test/issue42018.go b/misc/cgo/test/issue42018.go new file mode 100644 index 0000000000..fab686a678 --- /dev/null +++ b/misc/cgo/test/issue42018.go @@ -0,0 +1,14 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !windows +// +build !windows + +package cgotest + +import "testing" + +func test42018(t *testing.T) { + t.Skip("skipping Windows-only test") +} diff --git a/misc/cgo/test/issue42018_windows.go b/misc/cgo/test/issue42018_windows.go new file mode 100644 index 0000000000..8f4570ab2a --- /dev/null +++ b/misc/cgo/test/issue42018_windows.go @@ -0,0 +1,46 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cgotest + +/* +typedef void *HANDLE; + +struct HWND__{int unused;}; typedef struct HWND__ *HWND; +*/ +import "C" + +import ( + "testing" + "unsafe" +) + +func test42018(t *testing.T) { + // Test that Windows handles are marked go:notinheap, by growing the + // stack and checking for pointer adjustments. Trick from + // test/fixedbugs/issue40954.go. + var i int + handle := C.HANDLE(unsafe.Pointer(uintptr(unsafe.Pointer(&i)))) + recurseHANDLE(100, handle, uintptr(unsafe.Pointer(&i))) + hwnd := C.HWND(unsafe.Pointer(uintptr(unsafe.Pointer(&i)))) + recurseHWND(400, hwnd, uintptr(unsafe.Pointer(&i))) +} + +func recurseHANDLE(n int, p C.HANDLE, v uintptr) { + if n > 0 { + recurseHANDLE(n-1, p, v) + } + if uintptr(unsafe.Pointer(p)) != v { + panic("adjusted notinheap pointer") + } +} + +func recurseHWND(n int, p C.HWND, v uintptr) { + if n > 0 { + recurseHWND(n-1, p, v) + } + if uintptr(unsafe.Pointer(p)) != v { + panic("adjusted notinheap pointer") + } +} diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index 6b3112b41e..f5682c0997 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -2106,6 +2106,9 @@ type typeConv struct { // Type names X for which there exists an XGetTypeID function with type func() CFTypeID. getTypeIDs map[string]bool + // badStructs contains C structs that should be marked NotInHeap. + notInHeapStructs map[string]bool + // Predeclared types. bool ast.Expr byte ast.Expr // denotes padding @@ -2117,6 +2120,7 @@ type typeConv struct { string ast.Expr goVoid ast.Expr // _Ctype_void, denotes C's void goVoidPtr ast.Expr // unsafe.Pointer or *byte + goVoidPtrNoHeap ast.Expr // *_Ctype_void_notinheap, like goVoidPtr but marked NotInHeap ptrSize int64 intSize int64 @@ -2140,6 +2144,7 @@ func (c *typeConv) Init(ptrSize, intSize int64) { c.m = make(map[string]*Type) c.ptrs = make(map[string][]*Type) c.getTypeIDs = make(map[string]bool) + c.notInHeapStructs = make(map[string]bool) c.bool = c.Ident("bool") c.byte = c.Ident("byte") c.int8 = c.Ident("int8") @@ -2158,6 +2163,7 @@ func (c *typeConv) Init(ptrSize, intSize int64) { c.void = c.Ident("void") c.string = c.Ident("string") c.goVoid = c.Ident("_Ctype_void") + c.goVoidPtrNoHeap = c.Ident("*_Ctype_void_notinheap") // Normally cgo translates void* to unsafe.Pointer, // but for historical reasons -godefs uses *byte instead. @@ -2538,6 +2544,7 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ tt.C = &TypeRepr{"struct %s", []interface{}{tag}} } tt.Go = g + tt.NotInHeap = c.notInHeapStructs[tag] typedef[name.Name] = &tt } @@ -2581,6 +2588,30 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ oldType.BadPointer = true } } + if c.badVoidPointerTypedef(dt) { + // Treat this typedef as a pointer to a NotInHeap void. + s := *sub + s.Go = c.goVoidPtrNoHeap + sub = &s + // Make sure we update any previously computed type. + if oldType := typedef[name.Name]; oldType != nil { + oldType.Go = sub.Go + } + } + // Check for non-pointer "struct {...}; typedef struct *" + // typedefs that should be marked NotInHeap. + if ptr, ok := dt.Type.(*dwarf.PtrType); ok { + if strct, ok := ptr.Type.(*dwarf.StructType); ok { + if c.badStructPointerTypedef(dt.Name, strct) { + c.notInHeapStructs[strct.StructName] = true + // Make sure we update any previously computed type. + name := "_Ctype_struct_" + strct.StructName + if oldType := typedef[name]; oldType != nil { + oldType.NotInHeap = true + } + } + } + } t.Go = name t.BadPointer = sub.BadPointer t.NotInHeap = sub.NotInHeap @@ -3132,6 +3163,48 @@ func (c *typeConv) badPointerTypedef(dt *dwarf.TypedefType) bool { return false } +// badVoidPointerTypedef is like badPointerTypeDef, but for "void *" typedefs that should be NotInHeap. +func (c *typeConv) badVoidPointerTypedef(dt *dwarf.TypedefType) bool { + // Match the Windows HANDLE type (#42018). + if goos != "windows" || dt.Name != "HANDLE" { + return false + } + // Check that the typedef is "typedef void *". + if ptr, ok := dt.Type.(*dwarf.PtrType); ok { + if _, ok := ptr.Type.(*dwarf.VoidType); ok { + return true + } + } + return false +} + +// badStructPointerTypedef is like badVoidPointerTypedefs but for structs. +func (c *typeConv) badStructPointerTypedef(name string, dt *dwarf.StructType) bool { + // Windows handle types can all potentially contain non-pointers. + // badVoidPointerTypedef handles the "void *" HANDLE type, but other + // handles are defined as + // + // struct __{int unused;}; typedef struct __ *name; + // + // by the DECLARE_HANDLE macro in STRICT mode. The macro is declared in + // the Windows ntdef.h header, + // + // https://github.com/tpn/winsdk-10/blob/master/Include/10.0.16299.0/shared/ntdef.h#L779 + if goos != "windows" { + return false + } + if len(dt.Field) != 1 { + return false + } + if dt.StructName != name+"__" { + return false + } + if f := dt.Field[0]; f.Name != "unused" || f.Type.Common().Name != "int" { + return false + } + return true +} + // baseBadPointerTypedef reports whether the base of a chain of typedefs is a bad typedef // as badPointerTypedef reports. func (c *typeConv) baseBadPointerTypedef(dt *dwarf.TypedefType) bool { diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index 93cc0c6dc9..4968f7059d 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -135,6 +135,7 @@ func (p *Package) writeDefs() { fmt.Fprintf(fgo2, "%s", buf.Bytes()) fmt.Fprintf(fgo2, "\n\n") } + fmt.Fprintf(fgo2, "//go:notinheap\ntype _Ctype_void_notinheap struct{}\n\n") if *gccgo { fmt.Fprintf(fgo2, "type _Ctype_void byte\n") } else { -- GitLab From ccfc41eee01772576f83784ae44578e955e4ae6f Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 22 Sep 2021 13:13:08 -0400 Subject: [PATCH 1263/2500] cmd/compile: check out-of-range shifts on ARM and ARM64 When encoding ARM or ARM64 shifted register operand, check that the shift is in range. Change-Id: If0014933bfd0a1b8eaaa01e0220a6eeb17ab9f40 Reviewed-on: https://go-review.googlesource.com/c/go/+/351530 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/arm/ssa.go | 51 ++++++++++++++------------- src/cmd/compile/internal/arm64/ssa.go | 33 +++++++++-------- 2 files changed, 45 insertions(+), 39 deletions(-) diff --git a/src/cmd/compile/internal/arm/ssa.go b/src/cmd/compile/internal/arm/ssa.go index 8aac80a22e..063fb65b33 100644 --- a/src/cmd/compile/internal/arm/ssa.go +++ b/src/cmd/compile/internal/arm/ssa.go @@ -88,15 +88,18 @@ func (v shift) String() string { } // makeshift encodes a register shifted by a constant -func makeshift(reg int16, typ int64, s int64) shift { +func makeshift(v *ssa.Value, reg int16, typ int64, s int64) shift { + if s < 0 || s >= 32 { + v.Fatalf("shift out of range: %d", s) + } return shift(int64(reg&0xf) | typ | (s&31)<<7) } // genshift generates a Prog for r = r0 op (r1 shifted by n) -func genshift(s *ssagen.State, as obj.As, r0, r1, r int16, typ int64, n int64) *obj.Prog { +func genshift(s *ssagen.State, v *ssa.Value, as obj.As, r0, r1, r int16, typ int64, n int64) *obj.Prog { p := s.Prog(as) p.From.Type = obj.TYPE_SHIFT - p.From.Offset = int64(makeshift(r1, typ, n)) + p.From.Offset = int64(makeshift(v, r1, typ, n)) p.Reg = r0 if r != 0 { p.To.Type = obj.TYPE_REG @@ -335,7 +338,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.To.Type = obj.TYPE_REG p.To.Reg = v.Reg0() case ssa.OpARMSRRconst: - genshift(s, arm.AMOVW, 0, v.Args[0].Reg(), v.Reg(), arm.SHIFT_RR, v.AuxInt) + genshift(s, v, arm.AMOVW, 0, v.Args[0].Reg(), v.Reg(), arm.SHIFT_RR, v.AuxInt) case ssa.OpARMADDshiftLL, ssa.OpARMADCshiftLL, ssa.OpARMSUBshiftLL, @@ -346,11 +349,11 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { ssa.OpARMORshiftLL, ssa.OpARMXORshiftLL, ssa.OpARMBICshiftLL: - genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm.SHIFT_LL, v.AuxInt) + genshift(s, v, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm.SHIFT_LL, v.AuxInt) case ssa.OpARMADDSshiftLL, ssa.OpARMSUBSshiftLL, ssa.OpARMRSBSshiftLL: - p := genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg0(), arm.SHIFT_LL, v.AuxInt) + p := genshift(s, v, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg0(), arm.SHIFT_LL, v.AuxInt) p.Scond = arm.C_SBIT case ssa.OpARMADDshiftRL, ssa.OpARMADCshiftRL, @@ -362,11 +365,11 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { ssa.OpARMORshiftRL, ssa.OpARMXORshiftRL, ssa.OpARMBICshiftRL: - genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm.SHIFT_LR, v.AuxInt) + genshift(s, v, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm.SHIFT_LR, v.AuxInt) case ssa.OpARMADDSshiftRL, ssa.OpARMSUBSshiftRL, ssa.OpARMRSBSshiftRL: - p := genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg0(), arm.SHIFT_LR, v.AuxInt) + p := genshift(s, v, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg0(), arm.SHIFT_LR, v.AuxInt) p.Scond = arm.C_SBIT case ssa.OpARMADDshiftRA, ssa.OpARMADCshiftRA, @@ -378,20 +381,20 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { ssa.OpARMORshiftRA, ssa.OpARMXORshiftRA, ssa.OpARMBICshiftRA: - genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm.SHIFT_AR, v.AuxInt) + genshift(s, v, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm.SHIFT_AR, v.AuxInt) case ssa.OpARMADDSshiftRA, ssa.OpARMSUBSshiftRA, ssa.OpARMRSBSshiftRA: - p := genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg0(), arm.SHIFT_AR, v.AuxInt) + p := genshift(s, v, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg0(), arm.SHIFT_AR, v.AuxInt) p.Scond = arm.C_SBIT case ssa.OpARMXORshiftRR: - genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm.SHIFT_RR, v.AuxInt) + genshift(s, v, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm.SHIFT_RR, v.AuxInt) case ssa.OpARMMVNshiftLL: - genshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm.SHIFT_LL, v.AuxInt) + genshift(s, v, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm.SHIFT_LL, v.AuxInt) case ssa.OpARMMVNshiftRL: - genshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm.SHIFT_LR, v.AuxInt) + genshift(s, v, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm.SHIFT_LR, v.AuxInt) case ssa.OpARMMVNshiftRA: - genshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm.SHIFT_AR, v.AuxInt) + genshift(s, v, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm.SHIFT_AR, v.AuxInt) case ssa.OpARMMVNshiftLLreg: genregshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm.SHIFT_LL) case ssa.OpARMMVNshiftRLreg: @@ -513,11 +516,11 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.From.Type = obj.TYPE_REG p.From.Reg = v.Args[0].Reg() case ssa.OpARMCMPshiftLL, ssa.OpARMCMNshiftLL, ssa.OpARMTSTshiftLL, ssa.OpARMTEQshiftLL: - genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm.SHIFT_LL, v.AuxInt) + genshift(s, v, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm.SHIFT_LL, v.AuxInt) case ssa.OpARMCMPshiftRL, ssa.OpARMCMNshiftRL, ssa.OpARMTSTshiftRL, ssa.OpARMTEQshiftRL: - genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm.SHIFT_LR, v.AuxInt) + genshift(s, v, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm.SHIFT_LR, v.AuxInt) case ssa.OpARMCMPshiftRA, ssa.OpARMCMNshiftRA, ssa.OpARMTSTshiftRA, ssa.OpARMTEQshiftRA: - genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm.SHIFT_AR, v.AuxInt) + genshift(s, v, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm.SHIFT_AR, v.AuxInt) case ssa.OpARMCMPshiftLLreg, ssa.OpARMCMNshiftLLreg, ssa.OpARMTSTshiftLLreg, ssa.OpARMTEQshiftLLreg: genregshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Args[2].Reg(), 0, arm.SHIFT_LL) case ssa.OpARMCMPshiftRLreg, ssa.OpARMCMNshiftRLreg, ssa.OpARMTSTshiftRLreg, ssa.OpARMTEQshiftRLreg: @@ -583,13 +586,13 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { // this is just shift 0 bits fallthrough case ssa.OpARMMOVWloadshiftLL: - p := genshift(s, v.Op.Asm(), 0, v.Args[1].Reg(), v.Reg(), arm.SHIFT_LL, v.AuxInt) + p := genshift(s, v, v.Op.Asm(), 0, v.Args[1].Reg(), v.Reg(), arm.SHIFT_LL, v.AuxInt) p.From.Reg = v.Args[0].Reg() case ssa.OpARMMOVWloadshiftRL: - p := genshift(s, v.Op.Asm(), 0, v.Args[1].Reg(), v.Reg(), arm.SHIFT_LR, v.AuxInt) + p := genshift(s, v, v.Op.Asm(), 0, v.Args[1].Reg(), v.Reg(), arm.SHIFT_LR, v.AuxInt) p.From.Reg = v.Args[0].Reg() case ssa.OpARMMOVWloadshiftRA: - p := genshift(s, v.Op.Asm(), 0, v.Args[1].Reg(), v.Reg(), arm.SHIFT_AR, v.AuxInt) + p := genshift(s, v, v.Op.Asm(), 0, v.Args[1].Reg(), v.Reg(), arm.SHIFT_AR, v.AuxInt) p.From.Reg = v.Args[0].Reg() case ssa.OpARMMOVWstoreidx, ssa.OpARMMOVBstoreidx, ssa.OpARMMOVHstoreidx: // this is just shift 0 bits @@ -600,21 +603,21 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.From.Reg = v.Args[2].Reg() p.To.Type = obj.TYPE_SHIFT p.To.Reg = v.Args[0].Reg() - p.To.Offset = int64(makeshift(v.Args[1].Reg(), arm.SHIFT_LL, v.AuxInt)) + p.To.Offset = int64(makeshift(v, v.Args[1].Reg(), arm.SHIFT_LL, v.AuxInt)) case ssa.OpARMMOVWstoreshiftRL: p := s.Prog(v.Op.Asm()) p.From.Type = obj.TYPE_REG p.From.Reg = v.Args[2].Reg() p.To.Type = obj.TYPE_SHIFT p.To.Reg = v.Args[0].Reg() - p.To.Offset = int64(makeshift(v.Args[1].Reg(), arm.SHIFT_LR, v.AuxInt)) + p.To.Offset = int64(makeshift(v, v.Args[1].Reg(), arm.SHIFT_LR, v.AuxInt)) case ssa.OpARMMOVWstoreshiftRA: p := s.Prog(v.Op.Asm()) p.From.Type = obj.TYPE_REG p.From.Reg = v.Args[2].Reg() p.To.Type = obj.TYPE_SHIFT p.To.Reg = v.Args[0].Reg() - p.To.Offset = int64(makeshift(v.Args[1].Reg(), arm.SHIFT_AR, v.AuxInt)) + p.To.Offset = int64(makeshift(v, v.Args[1].Reg(), arm.SHIFT_AR, v.AuxInt)) case ssa.OpARMMOVBreg, ssa.OpARMMOVBUreg, ssa.OpARMMOVHreg, @@ -645,7 +648,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { } if buildcfg.GOARM >= 6 { // generate more efficient "MOVB/MOVBU/MOVH/MOVHU Reg@>0, Reg" on ARMv6 & ARMv7 - genshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm.SHIFT_RR, 0) + genshift(s, v, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm.SHIFT_RR, 0) return } fallthrough diff --git a/src/cmd/compile/internal/arm64/ssa.go b/src/cmd/compile/internal/arm64/ssa.go index 4770a0c488..9c26d90fd0 100644 --- a/src/cmd/compile/internal/arm64/ssa.go +++ b/src/cmd/compile/internal/arm64/ssa.go @@ -79,15 +79,18 @@ func storeByType(t *types.Type) obj.As { } // makeshift encodes a register shifted by a constant, used as an Offset in Prog -func makeshift(reg int16, typ int64, s int64) int64 { +func makeshift(v *ssa.Value, reg int16, typ int64, s int64) int64 { + if s < 0 || s >= 64 { + v.Fatalf("shift out of range: %d", s) + } return int64(reg&31)<<16 | typ | (s&63)<<10 } // genshift generates a Prog for r = r0 op (r1 shifted by n) -func genshift(s *ssagen.State, as obj.As, r0, r1, r int16, typ int64, n int64) *obj.Prog { +func genshift(s *ssagen.State, v *ssa.Value, as obj.As, r0, r1, r int16, typ int64, n int64) *obj.Prog { p := s.Prog(as) p.From.Type = obj.TYPE_SHIFT - p.From.Offset = makeshift(r1, typ, n) + p.From.Offset = makeshift(v, r1, typ, n) p.Reg = r0 if r != 0 { p.To.Type = obj.TYPE_REG @@ -310,13 +313,13 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.To.Type = obj.TYPE_REG p.To.Reg = v.Reg() case ssa.OpARM64MVNshiftLL, ssa.OpARM64NEGshiftLL: - genshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm64.SHIFT_LL, v.AuxInt) + genshift(s, v, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm64.SHIFT_LL, v.AuxInt) case ssa.OpARM64MVNshiftRL, ssa.OpARM64NEGshiftRL: - genshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm64.SHIFT_LR, v.AuxInt) + genshift(s, v, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm64.SHIFT_LR, v.AuxInt) case ssa.OpARM64MVNshiftRA, ssa.OpARM64NEGshiftRA: - genshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm64.SHIFT_AR, v.AuxInt) + genshift(s, v, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm64.SHIFT_AR, v.AuxInt) case ssa.OpARM64MVNshiftRO: - genshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm64.SHIFT_ROR, v.AuxInt) + genshift(s, v, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm64.SHIFT_ROR, v.AuxInt) case ssa.OpARM64ADDshiftLL, ssa.OpARM64SUBshiftLL, ssa.OpARM64ANDshiftLL, @@ -325,7 +328,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { ssa.OpARM64EONshiftLL, ssa.OpARM64ORNshiftLL, ssa.OpARM64BICshiftLL: - genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm64.SHIFT_LL, v.AuxInt) + genshift(s, v, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm64.SHIFT_LL, v.AuxInt) case ssa.OpARM64ADDshiftRL, ssa.OpARM64SUBshiftRL, ssa.OpARM64ANDshiftRL, @@ -334,7 +337,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { ssa.OpARM64EONshiftRL, ssa.OpARM64ORNshiftRL, ssa.OpARM64BICshiftRL: - genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm64.SHIFT_LR, v.AuxInt) + genshift(s, v, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm64.SHIFT_LR, v.AuxInt) case ssa.OpARM64ADDshiftRA, ssa.OpARM64SUBshiftRA, ssa.OpARM64ANDshiftRA, @@ -343,14 +346,14 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { ssa.OpARM64EONshiftRA, ssa.OpARM64ORNshiftRA, ssa.OpARM64BICshiftRA: - genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm64.SHIFT_AR, v.AuxInt) + genshift(s, v, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm64.SHIFT_AR, v.AuxInt) case ssa.OpARM64ANDshiftRO, ssa.OpARM64ORshiftRO, ssa.OpARM64XORshiftRO, ssa.OpARM64EONshiftRO, ssa.OpARM64ORNshiftRO, ssa.OpARM64BICshiftRO: - genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm64.SHIFT_ROR, v.AuxInt) + genshift(s, v, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), v.Reg(), arm64.SHIFT_ROR, v.AuxInt) case ssa.OpARM64MOVDconst: p := s.Prog(v.Op.Asm()) p.From.Type = obj.TYPE_CONST @@ -393,13 +396,13 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.From.Offset = v.AuxInt p.Reg = v.Args[0].Reg() case ssa.OpARM64CMPshiftLL, ssa.OpARM64CMNshiftLL, ssa.OpARM64TSTshiftLL: - genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm64.SHIFT_LL, v.AuxInt) + genshift(s, v, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm64.SHIFT_LL, v.AuxInt) case ssa.OpARM64CMPshiftRL, ssa.OpARM64CMNshiftRL, ssa.OpARM64TSTshiftRL: - genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm64.SHIFT_LR, v.AuxInt) + genshift(s, v, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm64.SHIFT_LR, v.AuxInt) case ssa.OpARM64CMPshiftRA, ssa.OpARM64CMNshiftRA, ssa.OpARM64TSTshiftRA: - genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm64.SHIFT_AR, v.AuxInt) + genshift(s, v, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm64.SHIFT_AR, v.AuxInt) case ssa.OpARM64TSTshiftRO: - genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm64.SHIFT_ROR, v.AuxInt) + genshift(s, v, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm64.SHIFT_ROR, v.AuxInt) case ssa.OpARM64MOVDaddr: p := s.Prog(arm64.AMOVD) p.From.Type = obj.TYPE_ADDR -- GitLab From 7a03ca65b303474c2ea610178105304eae1180df Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Thu, 16 Sep 2021 11:33:17 -0700 Subject: [PATCH 1264/2500] internal/fuzz,cmd/compile: don't add race instrumentation to counters Don't add race detector instrumentation to the fuzzing counters, allowing usage of -race without immediately triggering the detector. Also fixes a minor race in contextReader.Read. Fixes #48307 Change-Id: Idb2cfeaa4283f8a74473b4bac6cd68eed577e943 Reviewed-on: https://go-review.googlesource.com/c/go/+/351453 Trust: Roland Shoemaker Trust: Katie Hockman Run-TryBot: Roland Shoemaker TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/cmd/compile/internal/ssa/writebarrier.go | 2 +- src/cmd/compile/internal/walk/order.go | 8 ++++++++ src/internal/fuzz/worker.go | 8 +++++--- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/ssa/writebarrier.go b/src/cmd/compile/internal/ssa/writebarrier.go index 52f060b601..5120cd1086 100644 --- a/src/cmd/compile/internal/ssa/writebarrier.go +++ b/src/cmd/compile/internal/ssa/writebarrier.go @@ -650,7 +650,7 @@ func IsSanitizerSafeAddr(v *Value) bool { // read-only once initialized. return true case OpAddr: - return v.Aux.(*obj.LSym).Type == objabi.SRODATA + return v.Aux.(*obj.LSym).Type == objabi.SRODATA || v.Aux.(*obj.LSym).Type == objabi.SLIBFUZZER_EXTRA_COUNTER } return false } diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go index 7ac1f75c8f..861c122456 100644 --- a/src/cmd/compile/internal/walk/order.go +++ b/src/cmd/compile/internal/walk/order.go @@ -14,6 +14,7 @@ import ( "cmd/compile/internal/staticinit" "cmd/compile/internal/typecheck" "cmd/compile/internal/types" + "cmd/internal/objabi" "cmd/internal/src" ) @@ -443,6 +444,13 @@ func (o *orderState) edge() { // __libfuzzer_extra_counters. counter := staticinit.StaticName(types.Types[types.TUINT8]) counter.SetLibfuzzerExtraCounter(true) + // As well as setting SetLibfuzzerExtraCounter, we preemptively set the + // symbol type to SLIBFUZZER_EXTRA_COUNTER so that the race detector + // instrumentation pass (which does not have access to the flags set by + // SetLibfuzzerExtraCounter) knows to ignore them. This information is + // lost by the time it reaches the compile step, so SetLibfuzzerExtraCounter + // is still necessary. + counter.Linksym().Type = objabi.SLIBFUZZER_EXTRA_COUNTER // counter += 1 incr := ir.NewAssignOpStmt(base.Pos, ir.OADD, counter, ir.NewInt(1)) diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 36a7c629e5..5b24e575c0 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -1142,14 +1142,16 @@ type contextReader struct { r io.Reader } -func (cr *contextReader) Read(b []byte) (n int, err error) { - if err := cr.ctx.Err(); err != nil { - return 0, err +func (cr *contextReader) Read(b []byte) (int, error) { + if ctxErr := cr.ctx.Err(); ctxErr != nil { + return 0, ctxErr } done := make(chan struct{}) // This goroutine may stay blocked after Read returns because the underlying // read is blocked. + var n int + var err error go func() { n, err = cr.r.Read(b) close(done) -- GitLab From 1e5774889212bdaff5d061b2a45cd0093a291b44 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 22 Sep 2021 11:26:40 -0700 Subject: [PATCH 1265/2500] cmd/compile, go/types: allow `any` anywhere (as a type) Adjust types2 and go/types and some test cases. Because `any` is not treated specially anymore in constraint position we get additional errors in constraints if `any` is used before Go1.18 (in addition to the error that type parameter lists are not permitted before Go1.18). Fixes #33232. Change-Id: I85590c6094b07c3e494fef319e3a38d0217cf6f0 Reviewed-on: https://go-review.googlesource.com/c/go/+/351456 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/decl.go | 8 +----- .../types2/testdata/check/typeparams.go2 | 8 +++--- .../types2/testdata/examples/constraints.go2 | 6 ++--- .../types2/testdata/examples/types.go2 | 8 +++--- .../types2/testdata/fixedbugs/issue47818.go2 | 8 +++--- src/cmd/compile/internal/types2/typexpr.go | 6 ----- src/go/types/decl.go | 25 ++++++------------- src/go/types/testdata/check/typeparams.go2 | 8 +++--- .../types/testdata/examples/constraints.go2 | 6 ++--- src/go/types/testdata/examples/types.go2 | 8 +++--- .../types/testdata/fixedbugs/issue47818.go2 | 8 +++--- src/go/types/typexpr.go | 6 ----- test/fixedbugs/issue14652.go | 5 ++-- test/typeparam/tparam1.go | 19 +++++++------- 14 files changed, 49 insertions(+), 80 deletions(-) diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 1926d93a86..994c19ea30 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -625,13 +625,7 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list []*syntax.Fiel // This also preserves the grouped output of type parameter lists // when printing type strings. if i == 0 || f.Type != list[i-1].Type { - // The predeclared identifier "any" is visible only as a type bound in a type parameter list. - // If we allow "any" for general use, this if-statement can be removed (issue #33232). - if name, _ := unparen(f.Type).(*syntax.Name); name != nil && name.Value == "any" && check.lookup("any") == universeAny { - bound = universeAny.Type() - } else { - bound = check.typ(f.Type) - } + bound = check.typ(f.Type) } tparams[i].bound = bound } diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 index 765d561f3b..69b6925b9f 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 @@ -6,11 +6,9 @@ package p // import "io" // for type assertion tests -// The predeclared identifier "any" can only be used as a constraint -// in a type parameter list. -var _ any // ERROR cannot use any outside constraint position -func _[_ any /* ok here */ , _ interface{any /* ERROR constraint */ }](any /* ERROR constraint */ ) { - var _ any /* ERROR constraint */ +var _ any // ok to use any anywhere +func _[_ any, _ interface{any}](any) { + var _ any } func identity[T any](x T) T { return x } diff --git a/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 b/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 index f40d18c63e..ecc75c1a46 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 @@ -33,20 +33,20 @@ type ( _ interface{int|~ /* ERROR overlapping terms ~int */ int } _ interface{~int|~ /* ERROR overlapping terms ~int */ int } _ interface{~int|MyInt /* ERROR overlapping terms p.MyInt and ~int */ } - _ interface{int|interface{}} + _ interface{int|any} _ interface{int|~string|union} _ interface{int|~string|interface{int}} _ interface{union|union /* ERROR overlapping terms p.union and p.union */ } // For now we do not permit interfaces with methods in unions. - _ interface{~ /* ERROR invalid use of ~ */ interface{}} + _ interface{~ /* ERROR invalid use of ~ */ any} _ interface{int|interface /* ERROR cannot use .* in union */ { m() }} ) type ( // Tilde is not permitted on defined types or interfaces. foo int - bar interface{} + bar any _ interface{foo} _ interface{~ /* ERROR invalid use of ~ */ foo } _ interface{~ /* ERROR invalid use of ~ */ bar } diff --git a/src/cmd/compile/internal/types2/testdata/examples/types.go2 b/src/cmd/compile/internal/types2/testdata/examples/types.go2 index 97c9951ada..55b1b0da57 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/types.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/types.go2 @@ -114,7 +114,7 @@ type I1[T any] interface{ } // There is no such thing as a variadic generic type. -type _[T ... /* ERROR invalid use of ... */ interface{}] struct{} +type _[T ... /* ERROR invalid use of ... */ any] struct{} // Generic interfaces may be embedded as one would expect. type I2 interface { @@ -213,9 +213,9 @@ func Sum[T Adder[T]](list []T) T { } // Valid and invalid variations. -type B0 interface {} -type B1[_ any] interface{} -type B2[_, _ any] interface{} +type B0 any +type B1[_ any] any +type B2[_, _ any] any func _[T1 B0]() {} func _[T1 B1[T1]]() {} diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2 index 5334695b5e..166cc680db 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2 @@ -8,13 +8,13 @@ package go1_17 -type T[P /* ERROR type parameters require go1\.18 or later */ any] struct{} +type T[P /* ERROR type parameters require go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ] struct{} // for init (and main, but we're not in package main) we should only get one error -func init[P /* ERROR func init must have no type parameters */ any]() {} -func main[P /* ERROR type parameters require go1\.18 or later */ any]() {} +func init[P /* ERROR func init must have no type parameters */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ]() {} +func main[P /* ERROR type parameters require go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ]() {} -func f[P /* ERROR type parameters require go1\.18 or later */ any](x P) { +func f[P /* ERROR type parameters require go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ](x P) { var _ T[ /* ERROR type instantiation requires go1\.18 or later */ int] var _ (T[ /* ERROR type instantiation requires go1\.18 or later */ int]) _ = T[ /* ERROR type instantiation requires go1\.18 or later */ int]{} diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 5aacb94a60..7f75a96bd8 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -38,16 +38,10 @@ func (check *Checker) ident(x *operand, e *syntax.Name, def *Named, wantType boo } return case universeAny, universeComparable: - // complain if necessary if !check.allowVersion(check.pkg, 1, 18) { check.errorf(e, "undeclared name: %s (requires version go1.18 or later)", e.Value) return // avoid follow-on errors } - if obj == universeAny { - // If we allow "any" for general use, this if-statement can be removed (issue #33232). - check.softErrorf(e, "cannot use any outside constraint position") - // ok to continue - } } check.recordUse(e, obj) diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 0fdcfa8023..061fc01829 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -668,27 +668,18 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list *ast.FieldList *dst = bindTParams(tparams) index := 0 - var bound Type var bounds []Type var posns []positioner // bound positions for _, f := range list.List { - if f.Type == nil { - goto next - } - // The predeclared identifier "any" is visible only as a type bound in a type parameter list. - // If we allow "any" for general use, this if-statement can be removed (issue #33232). - if name, _ := unparen(f.Type).(*ast.Ident); name != nil && name.Name == "any" && check.lookup("any") == universeAny { - bound = universeAny.Type() - } else { - bound = check.typ(f.Type) - } - bounds = append(bounds, bound) - posns = append(posns, f.Type) - for i := range f.Names { - tparams[index+i].bound = bound + // TODO(rfindley) we should be able to rely on f.Type != nil at this point + if f.Type != nil { + bound := check.typ(f.Type) + bounds = append(bounds, bound) + posns = append(posns, f.Type) + for i := range f.Names { + tparams[index+i].bound = bound + } } - - next: index += len(f.Names) } diff --git a/src/go/types/testdata/check/typeparams.go2 b/src/go/types/testdata/check/typeparams.go2 index 57b6d7a0ad..bfacb3e1e7 100644 --- a/src/go/types/testdata/check/typeparams.go2 +++ b/src/go/types/testdata/check/typeparams.go2 @@ -6,11 +6,9 @@ package p // import "io" // for type assertion tests -// The predeclared identifier "any" can only be used as a constraint -// in a type parameter list. -var _ any // ERROR cannot use any outside constraint position -func _[_ any /* ok here */ , _ interface{any /* ERROR constraint */ }](any /* ERROR constraint */ ) { - var _ any /* ERROR constraint */ +var _ any // ok to use any anywhere +func _[_ any, _ interface{any}](any) { + var _ any } func identity[T any](x T) T { return x } diff --git a/src/go/types/testdata/examples/constraints.go2 b/src/go/types/testdata/examples/constraints.go2 index f40d18c63e..ecc75c1a46 100644 --- a/src/go/types/testdata/examples/constraints.go2 +++ b/src/go/types/testdata/examples/constraints.go2 @@ -33,20 +33,20 @@ type ( _ interface{int|~ /* ERROR overlapping terms ~int */ int } _ interface{~int|~ /* ERROR overlapping terms ~int */ int } _ interface{~int|MyInt /* ERROR overlapping terms p.MyInt and ~int */ } - _ interface{int|interface{}} + _ interface{int|any} _ interface{int|~string|union} _ interface{int|~string|interface{int}} _ interface{union|union /* ERROR overlapping terms p.union and p.union */ } // For now we do not permit interfaces with methods in unions. - _ interface{~ /* ERROR invalid use of ~ */ interface{}} + _ interface{~ /* ERROR invalid use of ~ */ any} _ interface{int|interface /* ERROR cannot use .* in union */ { m() }} ) type ( // Tilde is not permitted on defined types or interfaces. foo int - bar interface{} + bar any _ interface{foo} _ interface{~ /* ERROR invalid use of ~ */ foo } _ interface{~ /* ERROR invalid use of ~ */ bar } diff --git a/src/go/types/testdata/examples/types.go2 b/src/go/types/testdata/examples/types.go2 index 6f6f95e781..2e6eeb2204 100644 --- a/src/go/types/testdata/examples/types.go2 +++ b/src/go/types/testdata/examples/types.go2 @@ -114,7 +114,7 @@ type I1[T any] interface{ } // There is no such thing as a variadic generic type. -type _[T ... /* ERROR invalid use of ... */ interface{}] struct{} +type _[T ... /* ERROR invalid use of ... */ any] struct{} // Generic interfaces may be embedded as one would expect. type I2 interface { @@ -219,9 +219,9 @@ func Sum[T Adder[T]](list []T) T { } // Valid and invalid variations. -type B0 interface {} -type B1[_ any] interface{} -type B2[_, _ any] interface{} +type B0 any +type B1[_ any] any +type B2[_, _ any] any func _[T1 B0]() {} func _[T1 B1[T1]]() {} diff --git a/src/go/types/testdata/fixedbugs/issue47818.go2 b/src/go/types/testdata/fixedbugs/issue47818.go2 index 68c6a94ed4..e3e5a99637 100644 --- a/src/go/types/testdata/fixedbugs/issue47818.go2 +++ b/src/go/types/testdata/fixedbugs/issue47818.go2 @@ -8,13 +8,13 @@ package go1_17 -type T[P /* ERROR type parameters require go1\.18 or later */ any] struct{} +type T[P /* ERROR type parameters require go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ] struct{} // for init (and main, but we're not in package main) we should only get one error -func init[P /* ERROR func init must have no type parameters */ any]() {} -func main[P /* ERROR type parameters require go1\.18 or later */ any]() {} +func init[P /* ERROR func init must have no type parameters */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ]() {} +func main[P /* ERROR type parameters require go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ]() {} -func f[P /* ERROR type parameters require go1\.18 or later */ any](x P) { +func f[P /* ERROR type parameters require go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ](x P) { var _ T[ /* ERROR type instantiation requires go1\.18 or later */ int] var _ (T[ /* ERROR type instantiation requires go1\.18 or later */ int]) _ = T[ /* ERROR type instantiation requires go1\.18 or later */ int]{} diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index a1b8bae3d5..505c639444 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -36,16 +36,10 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool) } return case universeAny, universeComparable: - // complain if necessary if !check.allowVersion(check.pkg, 1, 18) { check.errorf(e, _UndeclaredName, "undeclared name: %s (requires version go1.18 or later)", e.Name) return // avoid follow-on errors } - if obj == universeAny { - // If we allow "any" for general use, this if-statement can be removed (issue #33232). - check.softErrorf(e, _Todo, "cannot use any outside constraint position") - // ok to continue - } } check.recordUse(e, obj) diff --git a/test/fixedbugs/issue14652.go b/test/fixedbugs/issue14652.go index 14a223977b..586663b676 100644 --- a/test/fixedbugs/issue14652.go +++ b/test/fixedbugs/issue14652.go @@ -1,4 +1,4 @@ -// errorcheck +// compile // Copyright 2016 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style @@ -6,4 +6,5 @@ package p -var x any // ERROR "undefined: any|undefined type .*any.*|cannot use any outside constraint position" +// any is now permitted instead of interface{} +var x any diff --git a/test/typeparam/tparam1.go b/test/typeparam/tparam1.go index 698877a6f0..3b4260c102 100644 --- a/test/typeparam/tparam1.go +++ b/test/typeparam/tparam1.go @@ -8,11 +8,10 @@ package tparam1 -// The predeclared identifier "any" is only visible as a constraint -// in a type parameter list. -var _ any // ERROR "cannot use any outside constraint position" -func _(_ any) // ERROR "cannot use any outside constraint position" -type _[_ any /* ok here */] struct{} +// The predeclared identifier "any" may be used in place of interface{}. +var _ any +func _(_ any) +type _[_ any] struct{} const N = 10 @@ -24,16 +23,16 @@ type ( _[T1, T2 any, T3 any] struct{} ) -func _[T any]() {} -func _[T, T any]() {} // ERROR "T redeclared" +func _[T any]() {} +func _[T, T any]() {} // ERROR "T redeclared" func _[T1, T2 any](x T1) T2 { panic(0) } // Type parameters are visible from opening [ to end of function. type C interface{} -func _[T interface{}]() {} -func _[T C]() {} -func _[T struct{}]() {}// ERROR "not an interface" +func _[T interface{}]() {} +func _[T C]() {} +func _[T struct{}]() {} // ERROR "not an interface" func _[T interface{ m() T }]() {} func _[T1 interface{ m() T2 }, T2 interface{ m() T1 }]() { var _ T1 -- GitLab From 5b75a9b2c3078ab2ef8398c47be5b30ea02c03d3 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 22 Sep 2021 13:23:47 -0400 Subject: [PATCH 1266/2500] cmd/compile: update comments with ABI aliases/wrappers ABI aliases are gone. Change-Id: I0f5676d8730cac14b7495dd6c0c1e08ca85a1c77 Reviewed-on: https://go-review.googlesource.com/c/go/+/351531 Trust: Cherry Mui Reviewed-by: Than McIntosh --- src/cmd/compile/internal/ssagen/abi.go | 9 +++------ src/cmd/compile/internal/staticdata/data.go | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/cmd/compile/internal/ssagen/abi.go b/src/cmd/compile/internal/ssagen/abi.go index eabd232791..3a653e46b4 100644 --- a/src/cmd/compile/internal/ssagen/abi.go +++ b/src/cmd/compile/internal/ssagen/abi.go @@ -218,8 +218,6 @@ func (s *SymABIs) GenABIWrappers() { } if !buildcfg.Experiment.RegabiWrappers { - // We'll generate ABI aliases instead of - // wrappers once we have LSyms in InitLSym. continue } @@ -251,10 +249,9 @@ func InitLSym(f *ir.Func, hasBody bool) { // the funcsym for either the defining // function or its wrapper as appropriate. // - // If we're using ABI aliases instead of - // wrappers, we only InitLSym for the defining - // ABI of a function, so we make the funcsym - // when we see that. + // If we're not using ABI wrappers, we only + // InitLSym for the defining ABI of a function, + // so we make the funcsym when we see that. staticdata.NeedFuncSym(f) } } diff --git a/src/cmd/compile/internal/staticdata/data.go b/src/cmd/compile/internal/staticdata/data.go index f25d8d8ec5..57c15a34a0 100644 --- a/src/cmd/compile/internal/staticdata/data.go +++ b/src/cmd/compile/internal/staticdata/data.go @@ -279,7 +279,7 @@ func NeedFuncSym(fn *ir.Func) { // entry points, so it doesn't make sense to create a // funcsym for other ABIs. // - // (If we're using ABI aliases, it doesn't matter.) + // (If we're not using ABI wrappers, it doesn't matter.) base.Fatalf("expected ABIInternal: %v has %v", fn.Nname, fn.ABI) } if ir.IsBlank(fn.Nname) { -- GitLab From 41bb7446dcc5179047512aa10c5e6d01eb870b54 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 22 Sep 2021 13:38:05 -0700 Subject: [PATCH 1267/2500] cmd/compile/internal/types2: don't panic if targs don't match tparams when substituting This is a clean port of CL 351337 from go/types to types2. Change-Id: I974bf79fcc1ec0016c38e4c0b361d05f7b44e649 Reviewed-on: https://go-review.googlesource.com/c/go/+/351466 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley TryBot-Result: Go Bot --- src/cmd/compile/internal/types2/named.go | 2 +- src/cmd/compile/internal/types2/subst.go | 4 +++- .../internal/types2/testdata/fixedbugs/issue46461.go2 | 11 +++++++++++ .../internal/types2/testdata/fixedbugs/issue48529.go2 | 11 +++++++++++ 4 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue46461.go2 create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue48529.go2 diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index 1db993afc9..bc4d4f89c5 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -330,7 +330,7 @@ func (check *Checker) completeMethod(env *Environment, m *Func) { // TODO(rfindley): eliminate this function or give it a better name. func safeUnderlying(typ Type) Type { if t, _ := typ.(*Named); t != nil { - return t.resolve(nil).underlying + return t.underlying } return typ.Underlying() } diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index ee68f22653..5e057a6f80 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -177,7 +177,9 @@ func (subst *subster) typ(typ Type) Type { } var newTArgs []Type - assert(t.targs.Len() == t.orig.TypeParams().Len()) + if t.targs.Len() != t.orig.TypeParams().Len() { + return Typ[Invalid] // error reported elsewhere + } // already instantiated dump(">>> %s already instantiated", t) diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46461.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46461.go2 new file mode 100644 index 0000000000..bfeaf3a966 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46461.go2 @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T[U interface{ M() T[U] }] int + +type X int + +func (X) M() T[X] { return 0 } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48529.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48529.go2 new file mode 100644 index 0000000000..4f92dec7fe --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48529.go2 @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T[U interface{ M() T /* ERROR "got 2 arguments but 1 type parameters" */ [U, int] }] int + +type X int + +func (X) M() T[X] { return 0 } -- GitLab From 1537f14db558ced001ba6e5d75dadcca173b0189 Mon Sep 17 00:00:00 2001 From: jiahua wang Date: Wed, 22 Sep 2021 15:54:35 +0800 Subject: [PATCH 1268/2500] io: fix spelling in documentation Change-Id: Ie23a9f1300a803d9c713e82b0d892dd90333ca7b Reviewed-on: https://go-review.googlesource.com/c/go/+/351371 Reviewed-by: Robert Griesemer Reviewed-by: Ian Lance Taylor --- src/io/io.go | 2 +- src/io/multi_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/io/io.go b/src/io/io.go index 2e697e7450..4e49a782dc 100644 --- a/src/io/io.go +++ b/src/io/io.go @@ -47,7 +47,7 @@ var EOF = errors.New("EOF") // middle of reading a fixed-size block or data structure. var ErrUnexpectedEOF = errors.New("unexpected EOF") -// ErrNoProgress is returned by some clients of an Reader when +// ErrNoProgress is returned by some clients of a Reader when // many calls to Read have failed to return any data or error, // usually the sign of a broken Reader implementation. var ErrNoProgress = errors.New("multiple Read calls return no data or error") diff --git a/src/io/multi_test.go b/src/io/multi_test.go index c3a44fd3b2..e877e54571 100644 --- a/src/io/multi_test.go +++ b/src/io/multi_test.go @@ -216,7 +216,7 @@ func TestMultiWriterCopy(t *testing.T) { } } -// readerFunc is an Reader implemented by the underlying func. +// readerFunc is a Reader implemented by the underlying func. type readerFunc func(p []byte) (int, error) func (f readerFunc) Read(p []byte) (int, error) { -- GitLab From 333f3de2a10f22269b567d82144ab3528a3e6c07 Mon Sep 17 00:00:00 2001 From: Lynn Boger Date: Wed, 22 Sep 2021 14:05:49 -0500 Subject: [PATCH 1269/2500] cmd/compile: update PPC64 CALL* ops for register ABI Allow the CALL ops to take variable number of arguments. Change-Id: I6753c2fcb434ce2ebbce51dd595fbcbb39a60bed Reviewed-on: https://go-review.googlesource.com/c/go/+/351589 Run-TryBot: Cherry Mui Reviewed-by: Cherry Mui TryBot-Result: Go Bot Trust: Lynn Boger --- src/cmd/compile/internal/ssa/gen/PPC64Ops.go | 8 ++++---- src/cmd/compile/internal/ssa/opGen.go | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go index 9d9122e148..5f84290002 100644 --- a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go @@ -428,10 +428,10 @@ func init() { {name: "LoweredRound32F", argLength: 1, reg: fp11, resultInArg0: true, zeroWidth: true}, {name: "LoweredRound64F", argLength: 1, reg: fp11, resultInArg0: true, zeroWidth: true}, - {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem - {name: "CALLtail", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // tail call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem - {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{callptr, ctxt, 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem - {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{callptr}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem + {name: "CALLstatic", argLength: -1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLtail", argLength: -1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // tail call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLclosure", argLength: -1, reg: regInfo{inputs: []regMask{callptr, ctxt, 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem + {name: "CALLinter", argLength: -1, reg: regInfo{inputs: []regMask{callptr}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem // large or unaligned zeroing // arg0 = address of memory to zero (in R3, changed as side effect) diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index fed3bc3386..32ffd28b6a 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -27337,7 +27337,7 @@ var opcodeTable = [...]opInfo{ { name: "CALLstatic", auxType: auxCallOff, - argLen: 1, + argLen: -1, clobberFlags: true, call: true, reg: regInfo{ @@ -27347,7 +27347,7 @@ var opcodeTable = [...]opInfo{ { name: "CALLtail", auxType: auxCallOff, - argLen: 1, + argLen: -1, clobberFlags: true, call: true, reg: regInfo{ @@ -27357,7 +27357,7 @@ var opcodeTable = [...]opInfo{ { name: "CALLclosure", auxType: auxCallOff, - argLen: 3, + argLen: -1, clobberFlags: true, call: true, reg: regInfo{ @@ -27371,7 +27371,7 @@ var opcodeTable = [...]opInfo{ { name: "CALLinter", auxType: auxCallOff, - argLen: 2, + argLen: -1, clobberFlags: true, call: true, reg: regInfo{ -- GitLab From 1319b1476ea6f55c780936d133a005054fa81234 Mon Sep 17 00:00:00 2001 From: Zvonimir Pavlinovic Date: Wed, 11 Aug 2021 13:47:07 -0700 Subject: [PATCH 1270/2500] cmd/go/internal/test: pass only analysis flags to vet In go test vet=x, x should be off, all, or one of the analyses supported by vet. All other flags should not be passed to vet. This CL maintains a list of supported vet analyzers by running go tool vet -flags and parsing the flag info to figure out the names of the supported analyzers and their aliases. Fixes #47309 Change-Id: I16ade8024301ad4aee5ad45aa92cf63b63dbc2d1 Reviewed-on: https://go-review.googlesource.com/c/go/+/341334 Trust: Zvonimir Pavlinovic Run-TryBot: Zvonimir Pavlinovic TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/test/flagdefs.go | 34 ++++++++++ src/cmd/go/internal/test/flagdefs_test.go | 19 ++++++ src/cmd/go/internal/test/genflags.go | 21 +++++- .../test/internal/genflags/vetflag.go | 68 +++++++++++++++++++ src/cmd/go/internal/test/testflag.go | 10 ++- src/cmd/go/testdata/script/test_vet.txt | 11 +++ 6 files changed, 160 insertions(+), 3 deletions(-) create mode 100644 src/cmd/go/internal/test/internal/genflags/vetflag.go diff --git a/src/cmd/go/internal/test/flagdefs.go b/src/cmd/go/internal/test/flagdefs.go index 3148074d57..1b79314eff 100644 --- a/src/cmd/go/internal/test/flagdefs.go +++ b/src/cmd/go/internal/test/flagdefs.go @@ -36,3 +36,37 @@ var passFlagToTest = map[string]bool{ "trace": true, "v": true, } + +var passAnalyzersToVet = map[string]bool{ + "asmdecl": true, + "assign": true, + "atomic": true, + "bool": true, + "bools": true, + "buildtag": true, + "buildtags": true, + "cgocall": true, + "composites": true, + "copylocks": true, + "errorsas": true, + "framepointer": true, + "httpresponse": true, + "ifaceassert": true, + "loopclosure": true, + "lostcancel": true, + "methods": true, + "nilfunc": true, + "printf": true, + "rangeloops": true, + "shift": true, + "sigchanyzer": true, + "stdmethods": true, + "stringintconv": true, + "structtag": true, + "testinggoroutine": true, + "tests": true, + "unmarshal": true, + "unreachable": true, + "unsafeptr": true, + "unusedresult": true, +} diff --git a/src/cmd/go/internal/test/flagdefs_test.go b/src/cmd/go/internal/test/flagdefs_test.go index f238fc7d33..40dc558e90 100644 --- a/src/cmd/go/internal/test/flagdefs_test.go +++ b/src/cmd/go/internal/test/flagdefs_test.go @@ -5,7 +5,9 @@ package test import ( + "cmd/go/internal/test/internal/genflags" "flag" + "reflect" "strings" "testing" ) @@ -37,3 +39,20 @@ func TestPassFlagToTestIncludesAllTestFlags(t *testing.T) { } } } + +func TestVetAnalyzersSetIsCorrect(t *testing.T) { + vetAns, err := genflags.VetAnalyzers() + if err != nil { + t.Fatal(err) + } + + want := make(map[string]bool) + for _, a := range vetAns { + want[a] = true + } + + if !reflect.DeepEqual(want, passAnalyzersToVet) { + t.Errorf("stale vet analyzers: want %v; got %v", want, passAnalyzersToVet) + t.Logf("(Run 'go generate cmd/go/internal/test' to refresh the set of analyzers.)") + } +} diff --git a/src/cmd/go/internal/test/genflags.go b/src/cmd/go/internal/test/genflags.go index 645aae68b1..cba366062f 100644 --- a/src/cmd/go/internal/test/genflags.go +++ b/src/cmd/go/internal/test/genflags.go @@ -16,6 +16,8 @@ import ( "strings" "testing" "text/template" + + "cmd/go/internal/test/internal/genflags" ) func main() { @@ -25,9 +27,18 @@ func main() { } func regenerate() error { + vetAnalyzers, err := genflags.VetAnalyzers() + if err != nil { + return err + } + t := template.Must(template.New("fileTemplate").Parse(fileTemplate)) + tData := map[string][]string{ + "testFlags": testFlags(), + "vetAnalyzers": vetAnalyzers, + } buf := bytes.NewBuffer(nil) - if err := t.Execute(buf, testFlags()); err != nil { + if err := t.Execute(buf, tData); err != nil { return err } @@ -85,7 +96,13 @@ package test // passFlagToTest contains the flags that should be forwarded to // the test binary with the prefix "test.". var passFlagToTest = map[string]bool { -{{- range .}} +{{- range .testFlags}} + "{{.}}": true, +{{- end }} +} + +var passAnalyzersToVet = map[string]bool { +{{- range .vetAnalyzers}} "{{.}}": true, {{- end }} } diff --git a/src/cmd/go/internal/test/internal/genflags/vetflag.go b/src/cmd/go/internal/test/internal/genflags/vetflag.go new file mode 100644 index 0000000000..2195cc3447 --- /dev/null +++ b/src/cmd/go/internal/test/internal/genflags/vetflag.go @@ -0,0 +1,68 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package genflags + +import ( + "bytes" + "cmd/go/internal/base" + "encoding/json" + "fmt" + exec "internal/execabs" + "regexp" + "sort" +) + +// VetAnalyzers computes analyzers and their aliases supported by vet. +func VetAnalyzers() ([]string, error) { + // get supported vet flag information + tool := base.Tool("vet") + vetcmd := exec.Command(tool, "-flags") + out := new(bytes.Buffer) + vetcmd.Stdout = out + if err := vetcmd.Run(); err != nil { + return nil, fmt.Errorf("go vet: can't execute %s -flags: %v\n", tool, err) + } + var analysisFlags []struct { + Name string + Bool bool + Usage string + } + if err := json.Unmarshal(out.Bytes(), &analysisFlags); err != nil { + return nil, fmt.Errorf("go vet: can't unmarshal JSON from %s -flags: %v", tool, err) + } + + // parse the flags to figure out which ones stand for analyses + analyzerSet := make(map[string]bool) + rEnable := regexp.MustCompile("^enable .+ analysis$") + for _, flag := range analysisFlags { + if rEnable.MatchString(flag.Usage) { + analyzerSet[flag.Name] = true + } + } + + rDeprecated := regexp.MustCompile("^deprecated alias for -(?P(.+))$") + // Returns the original value matched by rDeprecated on input value. + // If there is no match, "" is returned. + originalValue := func(value string) string { + match := rDeprecated.FindStringSubmatch(value) + if len(match) < 2 { + return "" + } + return match[1] + } + // extract deprecated aliases for existing analyses + for _, flag := range analysisFlags { + if o := originalValue(flag.Usage); analyzerSet[o] { + analyzerSet[flag.Name] = true + } + } + + var analyzers []string + for a := range analyzerSet { + analyzers = append(analyzers, a) + } + sort.Strings(analyzers) + return analyzers, nil +} diff --git a/src/cmd/go/internal/test/testflag.go b/src/cmd/go/internal/test/testflag.go index cb3543884a..b9d1ec91ff 100644 --- a/src/cmd/go/internal/test/testflag.go +++ b/src/cmd/go/internal/test/testflag.go @@ -195,6 +195,7 @@ func (f *vetFlag) Set(value string) error { case strings.Contains(value, " "): return fmt.Errorf("-vet argument is comma-separated list, cannot contain spaces") } + *f = vetFlag{explicit: true} var single string for _, arg := range strings.Split(value, ",") { @@ -212,8 +213,15 @@ func (f *vetFlag) Set(value string) error { off: true, } continue + default: + if _, ok := passAnalyzersToVet[arg]; !ok { + return fmt.Errorf("-vet argument must be a supported analyzer or a distinguished value; found %s", arg) + } + f.flags = append(f.flags, "-"+arg) } - f.flags = append(f.flags, "-"+arg) + } + if len(f.flags) > 1 && single != "" { + return fmt.Errorf("-vet does not accept %q in a list with other analyzers", single) } if len(f.flags) > 1 && single != "" { return fmt.Errorf("-vet does not accept %q in a list with other analyzers", single) diff --git a/src/cmd/go/testdata/script/test_vet.txt b/src/cmd/go/testdata/script/test_vet.txt index 2e0ae1956a..687d4851de 100644 --- a/src/cmd/go/testdata/script/test_vet.txt +++ b/src/cmd/go/testdata/script/test_vet.txt @@ -20,6 +20,17 @@ stdout '\[no test files\]' ! go test -vet=all ./vetall/... stderr 'using resp before checking for errors' +# Test issue #47309 +! go test -vet=bools,xyz ./vetall/... +stderr '-vet argument must be a supported analyzer' + +# Test with a list of analyzers +! go test -vet=httpresponse ./vetall/... +stderr 'using resp before checking for errors' + +# Test with a single analyzer +go test -vet=atomic,bools,nilfunc ./vetall/... +stdout 'm/vetall.*\[no tests to run\]' # Test issue #22890 go test m/vetcycle -- GitLab From ee69b09424f611d02d4b0f0da3eff875e075438f Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 22 Sep 2021 08:52:41 -0700 Subject: [PATCH 1271/2500] cmd/compile: break out constants for local and global dictionary prefixes Create constant LocalDictName for the pname/refix for dictionary parameters or local variables, and constant GlobalDictPrefix for the prefix for names of global dictionaries. I wanted to make sure these constants were set up as we add more reference to dictionaries for debugging, etc. Change-Id: Ide801f842383300a2699c96943ec06decaecc358 Reviewed-on: https://go-review.googlesource.com/c/go/+/351450 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Reviewed-by: Than McIntosh --- src/cmd/compile/internal/noder/stencil.go | 11 ++++------- src/cmd/compile/internal/typecheck/iexport.go | 5 ++++- src/cmd/compile/internal/typecheck/subr.go | 3 ++- src/cmd/internal/obj/objfile.go | 2 +- src/cmd/internal/objabi/util.go | 3 ++- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 7fca674132..c8ce230121 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -401,10 +401,7 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { var dictVar *ir.Name var dictAssign *ir.AssignStmt if outer != nil { - // Note: for now this is a compile-time constant, so we don't really need a closure - // to capture it (a wrapper function would work just as well). But eventually it - // will be a read of a subdictionary from the parent dictionary. - dictVar = ir.NewNameAt(pos, typecheck.LookupNum(".dict", g.dnum)) + dictVar = ir.NewNameAt(pos, typecheck.LookupNum(typecheck.LocalDictName, g.dnum)) g.dnum++ dictVar.Class = ir.PAUTO typed(types.Types[types.TUINTPTR], dictVar) @@ -723,7 +720,7 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes []*typ newf.Dcl = make([]*ir.Name, 0, len(gf.Dcl)+1) // Create the needed dictionary param - dictionarySym := newsym.Pkg.Lookup(".dict") + dictionarySym := newsym.Pkg.Lookup(typecheck.LocalDictName) dictionaryType := types.Types[types.TUINTPTR] dictionaryName := ir.NewNameAt(gf.Pos(), dictionarySym) typed(dictionaryType, dictionaryName) @@ -731,7 +728,7 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes []*typ dictionaryName.Curfn = newf newf.Dcl = append(newf.Dcl, dictionaryName) for _, n := range gf.Dcl { - if n.Sym().Name == ".dict" { + if n.Sym().Name == typecheck.LocalDictName { panic("already has dictionary") } newf.Dcl = append(newf.Dcl, subst.localvar(n)) @@ -1127,7 +1124,7 @@ func (subst *subster) node(n ir.Node) ir.Node { // Copy that closure variable to a local one. // Note: this allows the dictionary to be captured by child closures. // See issue 47723. - ldict := ir.NewNameAt(x.Pos(), newfn.Sym().Pkg.Lookup(".dict")) + ldict := ir.NewNameAt(x.Pos(), newfn.Sym().Pkg.Lookup(typecheck.LocalDictName)) typed(types.Types[types.TUINTPTR], ldict) ldict.Class = ir.PAUTO ldict.Curfn = newfn diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 489306e1e6..a2ad71dd4c 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -2196,7 +2196,7 @@ func (w *exportWriter) localIdent(s *types.Sym) { return } - if i := strings.LastIndex(name, "."); i >= 0 && !strings.HasPrefix(name, ".dict") { // TODO: just use autotmp names for dictionaries? + if i := strings.LastIndex(name, "."); i >= 0 && !strings.HasPrefix(name, LocalDictName) { base.Fatalf("unexpected dot in identifier: %v", name) } @@ -2232,3 +2232,6 @@ func (w *intWriter) uint64(x uint64) { // information (e.g. length field for OSLICELIT). const go117ExportTypes = true const Go117ExportTypes = go117ExportTypes + +// The name used for dictionary parameters or local variables. +const LocalDictName = ".dict" diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index d4af4e172e..9233bbe6f2 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -14,6 +14,7 @@ import ( "cmd/compile/internal/base" "cmd/compile/internal/ir" "cmd/compile/internal/types" + "cmd/internal/objabi" "cmd/internal/src" ) @@ -987,7 +988,7 @@ func MakeDictSym(gf *types.Sym, targs []*types.Type, hasBrackets bool) *types.Sy } } name := makeInstName1(gf.Name, targs, hasBrackets) - name = ".dict." + name + name = fmt.Sprintf("%s.%s", objabi.GlobalDictPrefix, name) return gf.Pkg.Lookup(name) } diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index 910e6ef0d9..8a094df91a 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -340,7 +340,7 @@ func (w *writer) Sym(s *LSym) { if strings.HasPrefix(s.Name, "go.itab.") && s.Type == objabi.SRODATA { flag2 |= goobj.SymFlagItab } - if strings.HasPrefix(s.Name, w.ctxt.Pkgpath) && strings.HasPrefix(s.Name[len(w.ctxt.Pkgpath):], "..dict") { + if strings.HasPrefix(s.Name, w.ctxt.Pkgpath) && strings.HasPrefix(s.Name[len(w.ctxt.Pkgpath):], ".") && strings.HasPrefix(s.Name[len(w.ctxt.Pkgpath)+1:], objabi.GlobalDictPrefix) { flag2 |= goobj.SymFlagDict } name := s.Name diff --git a/src/cmd/internal/objabi/util.go b/src/cmd/internal/objabi/util.go index 63640950d9..6bfa25a5ca 100644 --- a/src/cmd/internal/objabi/util.go +++ b/src/cmd/internal/objabi/util.go @@ -13,7 +13,8 @@ import ( const ( ElfRelocOffset = 256 - MachoRelocOffset = 2048 // reserve enough space for ELF relocations + MachoRelocOffset = 2048 // reserve enough space for ELF relocations + GlobalDictPrefix = ".dict" // prefix for names of global dictionaries ) // HeaderString returns the toolchain configuration string written in -- GitLab From 93453233bd00cc641d2f959f1faf236e0094c2bf Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 22 Sep 2021 15:56:58 -0700 Subject: [PATCH 1272/2500] cmd/compile: fix unsafe.Add with small-size offsets operands Like other builtin functions, unsafe.Add's len operand is allowed to be variable sized. However, unlike other builtins, it doesn't get lowered to a runtime function call, so we never end up coercing it to a specific type. As a result, we could end up constructing an OpAddPtr value but with a less-than-ptr-sized addend operand. This CL fixes this by always coercing the second operand to uintptr during SSA construction. Theoretically, we could do this during walk instead, but the frontend doesn't allow converting negative constants to uintptr. Fixes #48536. Change-Id: Ib0619ea79df58b256b250fec967a6d3c8afea631 Reviewed-on: https://go-review.googlesource.com/c/go/+/351592 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/ssagen/ssa.go | 5 +++++ test/fixedbugs/issue48536.go | 29 ++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 test/fixedbugs/issue48536.go diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 82d232f940..9746fbd316 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -3206,6 +3206,11 @@ func (s *state) exprCheckPtr(n ir.Node, checkPtrOK bool) *ssa.Value { n := n.(*ir.BinaryExpr) ptr := s.expr(n.X) len := s.expr(n.Y) + + // Force len to uintptr to prevent misuse of garbage bits in the + // upper part of the register (#48536). + len = s.conv(n, len, len.Type, types.Types[types.TUINTPTR]) + return s.newValue2(ssa.OpAddPtr, n.Type(), ptr, len) default: diff --git a/test/fixedbugs/issue48536.go b/test/fixedbugs/issue48536.go new file mode 100644 index 0000000000..68c7d1c261 --- /dev/null +++ b/test/fixedbugs/issue48536.go @@ -0,0 +1,29 @@ +// run + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "unsafe" + +var i = 257 + +func main() { + var buf [10]byte + p0 := unsafe.Pointer(&buf[0]) + p1 := unsafe.Pointer(&buf[1]) + + if p := unsafe.Add(p0, uint8(i)); p != p1 { + println("FAIL:", p, "!=", p1) + } + + var x uint8 + if i != 0 { + x = 1 + } + if p := unsafe.Add(p0, x); p != p1 { + println("FAIL:", p, "!=", p1) + } +} -- GitLab From d0dd26a88c019d54f22463daae81e785f5867565 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 20 May 2021 12:46:33 -0400 Subject: [PATCH 1273/2500] html/template, text/template: implement break and continue for range loops Break and continue for range loops was accepted as a proposal in June 2017. It was implemented in CL 66410 (Oct 2017) but then rolled back in CL 92155 (Feb 2018) because html/template changes had not been implemented. This CL reimplements break and continue in text/template and then adds support for them in html/template as well. Fixes #20531. Change-Id: I05330482a976f1c078b4b49c2287bd9031bb7616 Reviewed-on: https://go-review.googlesource.com/c/go/+/321491 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Rob Pike --- src/html/template/context.go | 4 ++ src/html/template/escape.go | 71 ++++++++++++++++++++++++++- src/html/template/escape_test.go | 24 +++++++++ src/html/template/exec_test.go | 2 + src/text/template/doc.go | 8 +++ src/text/template/exec.go | 24 ++++++++- src/text/template/exec_test.go | 2 + src/text/template/parse/lex.go | 13 ++++- src/text/template/parse/lex_test.go | 2 + src/text/template/parse/node.go | 36 ++++++++++++++ src/text/template/parse/parse.go | 42 +++++++++++++++- src/text/template/parse/parse_test.go | 8 +++ 12 files changed, 232 insertions(+), 4 deletions(-) diff --git a/src/html/template/context.go b/src/html/template/context.go index f7d4849928..aaa7d08359 100644 --- a/src/html/template/context.go +++ b/src/html/template/context.go @@ -6,6 +6,7 @@ package template import ( "fmt" + "text/template/parse" ) // context describes the state an HTML parser must be in when it reaches the @@ -22,6 +23,7 @@ type context struct { jsCtx jsCtx attr attr element element + n parse.Node // for range break/continue err *Error } @@ -141,6 +143,8 @@ const ( // stateError is an infectious error state outside any valid // HTML/CSS/JS construct. stateError + // stateDead marks unreachable code after a {{break}} or {{continue}}. + stateDead ) // isComment is true for any state that contains content meant for template diff --git a/src/html/template/escape.go b/src/html/template/escape.go index 8739735cb7..6dea79c7b5 100644 --- a/src/html/template/escape.go +++ b/src/html/template/escape.go @@ -97,6 +97,15 @@ type escaper struct { actionNodeEdits map[*parse.ActionNode][]string templateNodeEdits map[*parse.TemplateNode]string textNodeEdits map[*parse.TextNode][]byte + // rangeContext holds context about the current range loop. + rangeContext *rangeContext +} + +// rangeContext holds information about the current range loop. +type rangeContext struct { + outer *rangeContext // outer loop + breaks []context // context at each break action + continues []context // context at each continue action } // makeEscaper creates a blank escaper for the given set. @@ -109,6 +118,7 @@ func makeEscaper(n *nameSpace) escaper { map[*parse.ActionNode][]string{}, map[*parse.TemplateNode]string{}, map[*parse.TextNode][]byte{}, + nil, } } @@ -124,8 +134,16 @@ func (e *escaper) escape(c context, n parse.Node) context { switch n := n.(type) { case *parse.ActionNode: return e.escapeAction(c, n) + case *parse.BreakNode: + c.n = n + e.rangeContext.breaks = append(e.rangeContext.breaks, c) + return context{state: stateDead} case *parse.CommentNode: return c + case *parse.ContinueNode: + c.n = n + e.rangeContext.continues = append(e.rangeContext.breaks, c) + return context{state: stateDead} case *parse.IfNode: return e.escapeBranch(c, &n.BranchNode, "if") case *parse.ListNode: @@ -427,6 +445,12 @@ func join(a, b context, node parse.Node, nodeName string) context { if b.state == stateError { return b } + if a.state == stateDead { + return b + } + if b.state == stateDead { + return a + } if a.eq(b) { return a } @@ -466,14 +490,27 @@ func join(a, b context, node parse.Node, nodeName string) context { // escapeBranch escapes a branch template node: "if", "range" and "with". func (e *escaper) escapeBranch(c context, n *parse.BranchNode, nodeName string) context { + if nodeName == "range" { + e.rangeContext = &rangeContext{outer: e.rangeContext} + } c0 := e.escapeList(c, n.List) - if nodeName == "range" && c0.state != stateError { + if nodeName == "range" { + if c0.state != stateError { + c0 = joinRange(c0, e.rangeContext) + } + e.rangeContext = e.rangeContext.outer + if c0.state == stateError { + return c0 + } + // The "true" branch of a "range" node can execute multiple times. // We check that executing n.List once results in the same context // as executing n.List twice. + e.rangeContext = &rangeContext{outer: e.rangeContext} c1, _ := e.escapeListConditionally(c0, n.List, nil) c0 = join(c0, c1, n, nodeName) if c0.state == stateError { + e.rangeContext = e.rangeContext.outer // Make clear that this is a problem on loop re-entry // since developers tend to overlook that branch when // debugging templates. @@ -481,11 +518,39 @@ func (e *escaper) escapeBranch(c context, n *parse.BranchNode, nodeName string) c0.err.Description = "on range loop re-entry: " + c0.err.Description return c0 } + c0 = joinRange(c0, e.rangeContext) + e.rangeContext = e.rangeContext.outer + if c0.state == stateError { + return c0 + } } c1 := e.escapeList(c, n.ElseList) return join(c0, c1, n, nodeName) } +func joinRange(c0 context, rc *rangeContext) context { + // Merge contexts at break and continue statements into overall body context. + // In theory we could treat breaks differently from continues, but for now it is + // enough to treat them both as going back to the start of the loop (which may then stop). + for _, c := range rc.breaks { + c0 = join(c0, c, c.n, "range") + if c0.state == stateError { + c0.err.Line = c.n.(*parse.BreakNode).Line + c0.err.Description = "at range loop break: " + c0.err.Description + return c0 + } + } + for _, c := range rc.continues { + c0 = join(c0, c, c.n, "range") + if c0.state == stateError { + c0.err.Line = c.n.(*parse.ContinueNode).Line + c0.err.Description = "at range loop continue: " + c0.err.Description + return c0 + } + } + return c0 +} + // escapeList escapes a list template node. func (e *escaper) escapeList(c context, n *parse.ListNode) context { if n == nil { @@ -493,6 +558,9 @@ func (e *escaper) escapeList(c context, n *parse.ListNode) context { } for _, m := range n.Nodes { c = e.escape(c, m) + if c.state == stateDead { + break + } } return c } @@ -503,6 +571,7 @@ func (e *escaper) escapeList(c context, n *parse.ListNode) context { // which is the same as whether e was updated. func (e *escaper) escapeListConditionally(c context, n *parse.ListNode, filter func(*escaper, context) bool) (context, bool) { e1 := makeEscaper(e.ns) + e1.rangeContext = e.rangeContext // Make type inferences available to f. for k, v := range e.output { e1.output[k] = v diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go index fbc84a7592..3b0aa8c846 100644 --- a/src/html/template/escape_test.go +++ b/src/html/template/escape_test.go @@ -920,6 +920,22 @@ func TestErrors(t *testing.T) { "", "", }, + { + "{{range .Items}}{{end}}", + "", + }, + { + "{{range .Items}}{{continue}}{{end}}", + "", + }, + { + "{{range .Items}}{{break}}{{end}}", + "", + }, + { + "{{range .Items}}{{if .X}}{{break}}{{end}}{{end}}", + "", + }, // Error cases. { "{{if .Cond}} itemKeyword: - l.emit(key[word]) + item := key[word] + if item == itemBreak && !l.breakOK || item == itemContinue && !l.continueOK { + l.emit(itemIdentifier) + } else { + l.emit(item) + } case word[0] == '.': l.emit(itemField) case word == "true", word == "false": diff --git a/src/text/template/parse/lex_test.go b/src/text/template/parse/lex_test.go index 6510eed674..df6aabffb2 100644 --- a/src/text/template/parse/lex_test.go +++ b/src/text/template/parse/lex_test.go @@ -35,6 +35,8 @@ var itemName = map[itemType]string{ // keywords itemDot: ".", itemBlock: "block", + itemBreak: "break", + itemContinue: "continue", itemDefine: "define", itemElse: "else", itemIf: "if", diff --git a/src/text/template/parse/node.go b/src/text/template/parse/node.go index 177482f9b2..47268225c8 100644 --- a/src/text/template/parse/node.go +++ b/src/text/template/parse/node.go @@ -71,6 +71,8 @@ const ( NodeVariable // A $ variable. NodeWith // A with action. NodeComment // A comment. + NodeBreak // A break action. + NodeContinue // A continue action. ) // Nodes. @@ -907,6 +909,40 @@ func (i *IfNode) Copy() Node { return i.tr.newIf(i.Pos, i.Line, i.Pipe.CopyPipe(), i.List.CopyList(), i.ElseList.CopyList()) } +// BreakNode represents a {{break}} action. +type BreakNode struct { + tr *Tree + NodeType + Pos + Line int +} + +func (t *Tree) newBreak(pos Pos, line int) *BreakNode { + return &BreakNode{tr: t, NodeType: NodeBreak, Pos: pos, Line: line} +} + +func (b *BreakNode) Copy() Node { return b.tr.newBreak(b.Pos, b.Line) } +func (b *BreakNode) String() string { return "{{break}}" } +func (b *BreakNode) tree() *Tree { return b.tr } +func (b *BreakNode) writeTo(sb *strings.Builder) { sb.WriteString("{{break}}") } + +// ContinueNode represents a {{continue}} action. +type ContinueNode struct { + tr *Tree + NodeType + Pos + Line int +} + +func (t *Tree) newContinue(pos Pos, line int) *ContinueNode { + return &ContinueNode{tr: t, NodeType: NodeContinue, Pos: pos, Line: line} +} + +func (c *ContinueNode) Copy() Node { return c.tr.newContinue(c.Pos, c.Line) } +func (c *ContinueNode) String() string { return "{{continue}}" } +func (c *ContinueNode) tree() *Tree { return c.tr } +func (c *ContinueNode) writeTo(sb *strings.Builder) { sb.WriteString("{{continue}}") } + // RangeNode represents a {{range}} action and its commands. type RangeNode struct { BranchNode diff --git a/src/text/template/parse/parse.go b/src/text/template/parse/parse.go index 1a63961c13..d92bed5d3d 100644 --- a/src/text/template/parse/parse.go +++ b/src/text/template/parse/parse.go @@ -31,6 +31,7 @@ type Tree struct { vars []string // variables defined at the moment. treeSet map[string]*Tree actionLine int // line of left delim starting action + rangeDepth int mode Mode } @@ -224,6 +225,8 @@ func (t *Tree) startParse(funcs []map[string]interface{}, lex *lexer, treeSet ma t.vars = []string{"$"} t.funcs = funcs t.treeSet = treeSet + lex.breakOK = !t.hasFunction("break") + lex.continueOK = !t.hasFunction("continue") } // stopParse terminates parsing. @@ -386,6 +389,10 @@ func (t *Tree) action() (n Node) { switch token := t.nextNonSpace(); token.typ { case itemBlock: return t.blockControl() + case itemBreak: + return t.breakControl(token.pos, token.line) + case itemContinue: + return t.continueControl(token.pos, token.line) case itemElse: return t.elseControl() case itemEnd: @@ -405,6 +412,32 @@ func (t *Tree) action() (n Node) { return t.newAction(token.pos, token.line, t.pipeline("command", itemRightDelim)) } +// Break: +// {{break}} +// Break keyword is past. +func (t *Tree) breakControl(pos Pos, line int) Node { + if token := t.next(); token.typ != itemRightDelim { + t.unexpected(token, "in {{break}}") + } + if t.rangeDepth == 0 { + t.errorf("{{break}} outside {{range}}") + } + return t.newBreak(pos, line) +} + +// Continue: +// {{continue}} +// Continue keyword is past. +func (t *Tree) continueControl(pos Pos, line int) Node { + if token := t.next(); token.typ != itemRightDelim { + t.unexpected(token, "in {{continue}}") + } + if t.rangeDepth == 0 { + t.errorf("{{continue}} outside {{range}}") + } + return t.newContinue(pos, line) +} + // Pipeline: // declarations? command ('|' command)* func (t *Tree) pipeline(context string, end itemType) (pipe *PipeNode) { @@ -480,8 +513,14 @@ func (t *Tree) checkPipeline(pipe *PipeNode, context string) { func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) { defer t.popVars(len(t.vars)) pipe = t.pipeline(context, itemRightDelim) + if context == "range" { + t.rangeDepth++ + } var next Node list, next = t.itemList() + if context == "range" { + t.rangeDepth-- + } switch next.Type() { case nodeEnd: //done case nodeElse: @@ -523,7 +562,8 @@ func (t *Tree) ifControl() Node { // {{range pipeline}} itemList {{else}} itemList {{end}} // Range keyword is past. func (t *Tree) rangeControl() Node { - return t.newRange(t.parseControl(false, "range")) + r := t.newRange(t.parseControl(false, "range")) + return r } // With: diff --git a/src/text/template/parse/parse_test.go b/src/text/template/parse/parse_test.go index 9b1be272e5..c3679a08de 100644 --- a/src/text/template/parse/parse_test.go +++ b/src/text/template/parse/parse_test.go @@ -230,6 +230,10 @@ var parseTests = []parseTest{ `{{range $x := .SI}}{{.}}{{end}}`}, {"range 2 vars", "{{range $x, $y := .SI}}{{.}}{{end}}", noError, `{{range $x, $y := .SI}}{{.}}{{end}}`}, + {"range with break", "{{range .SI}}{{.}}{{break}}{{end}}", noError, + `{{range .SI}}{{.}}{{break}}{{end}}`}, + {"range with continue", "{{range .SI}}{{.}}{{continue}}{{end}}", noError, + `{{range .SI}}{{.}}{{continue}}{{end}}`}, {"constants", "{{range .SI 1 -3.2i true false 'a' nil}}{{end}}", noError, `{{range .SI 1 -3.2i true false 'a' nil}}{{end}}`}, {"template", "{{template `x`}}", noError, @@ -279,6 +283,10 @@ var parseTests = []parseTest{ {"adjacent args", "{{printf 3`x`}}", hasError, ""}, {"adjacent args with .", "{{printf `x`.}}", hasError, ""}, {"extra end after if", "{{if .X}}a{{else if .Y}}b{{end}}{{end}}", hasError, ""}, + {"break outside range", "{{range .}}{{end}} {{break}}", hasError, ""}, + {"continue outside range", "{{range .}}{{end}} {{continue}}", hasError, ""}, + {"break in range else", "{{range .}}{{else}}{{break}}{{end}}", hasError, ""}, + {"continue in range else", "{{range .}}{{else}}{{continue}}{{end}}", hasError, ""}, // Other kinds of assignments and operators aren't available yet. {"bug0a", "{{$x := 0}}{{$x}}", noError, "{{$x := 0}}{{$x}}"}, {"bug0b", "{{$x += 1}}{{$x}}", hasError, ""}, -- GitLab From abbfec2829b001cf758a058eba4ccdc940e029f4 Mon Sep 17 00:00:00 2001 From: zhouguangyuan Date: Sat, 11 Sep 2021 00:33:34 +0800 Subject: [PATCH 1274/2500] cmd/go: insert goroot to the hash of build cache when the packages include C files There are some absolute paths in the object file of the packages include C files. The path in C objects file can't be rewritten by linker. The goroot must be used as input for the hash when the packages include C files. So that the debug_info of the binary is correctly. Fixes #48319 Change-Id: I659a3d6d71c4e49fff83f5bcf53a0a417e552a93 Reviewed-on: https://go-review.googlesource.com/c/go/+/348991 Reviewed-by: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Trust: Meng Zhuo Trust: Jay Conrod --- src/cmd/go/internal/work/exec.go | 34 ++-- .../go/testdata/script/build_issue48319.txt | 153 ++++++++++++++++++ 2 files changed, 177 insertions(+), 10 deletions(-) create mode 100644 src/cmd/go/testdata/script/build_issue48319.txt diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index f82028aef6..ed02c3c247 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -222,18 +222,32 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID { // same compiler settings and can reuse each other's results. // If not, the reason is already recorded in buildGcflags. fmt.Fprintf(h, "compile\n") - // Only include the package directory if it may affect the output. - // We trim workspace paths for all packages when -trimpath is set. - // The compiler hides the exact value of $GOROOT - // when building things in GOROOT. - // Assume b.WorkDir is being trimmed properly. - // When -trimpath is used with a package built from the module cache, - // use the module path and version instead of the directory. - if !p.Goroot && !cfg.BuildTrimpath && !strings.HasPrefix(p.Dir, b.WorkDir) { + + // Include information about the origin of the package that + // may be embedded in the debug info for the object file. + if cfg.BuildTrimpath { + // When -trimpath is used with a package built from the module cache, + // its debug information refers to the module path and version + // instead of the directory. + if p.Module != nil { + fmt.Fprintf(h, "module %s@%s\n", p.Module.Path, p.Module.Version) + } + } else if p.Goroot { + // The Go compiler always hides the exact value of $GOROOT + // when building things in GOROOT, but the C compiler + // merely rewrites GOROOT to GOROOT_FINAL. + if len(p.CFiles) > 0 { + fmt.Fprintf(h, "goroot %s\n", cfg.GOROOT_FINAL) + } + // b.WorkDir is always either trimmed or rewritten to + // the literal string "/tmp/go-build". + } else if !strings.HasPrefix(p.Dir, b.WorkDir) { + // -trimpath is not set and no other rewrite rules apply, + // so the object file may refer to the absolute directory + // containing the package. fmt.Fprintf(h, "dir %s\n", p.Dir) - } else if cfg.BuildTrimpath && p.Module != nil { - fmt.Fprintf(h, "module %s@%s\n", p.Module.Path, p.Module.Version) } + if p.Module != nil { fmt.Fprintf(h, "go %s\n", p.Module.GoVersion) } diff --git a/src/cmd/go/testdata/script/build_issue48319.txt b/src/cmd/go/testdata/script/build_issue48319.txt new file mode 100644 index 0000000000..f58a5faa3f --- /dev/null +++ b/src/cmd/go/testdata/script/build_issue48319.txt @@ -0,0 +1,153 @@ +[short] skip +[!cgo] skip + +# Set up fresh GOCACHE +env GOCACHE=$WORK/gocache +mkdir $GOCACHE + +# 1. unset GOROOT_FINAL, Build a simple binary with cgo by origin go. +# The DW_AT_comp_dir of runtime/cgo should have a prefix with origin goroot. +env GOROOT_FINAL= +# If using "go run", it is no debuginfo in binary. So use "go build". +# And we can check the stderr to judge if the cache of "runtime/cgo" +# was used or not. +go build -o binary.exe +exec ./binary.exe $TESTGO_GOROOT +stdout 'cgo DW_AT_comp_dir is right in binary' + + +# 2. GOROOT_FINAL will be changed, the runtime/cgo will be rebuild. +env GOROOT_FINAL=$WORK/gorootfinal +go build -x -o binary.exe +stderr '(clang|gcc)( |\.exe).*gcc_.*\.c' +exec ./binary.exe $GOROOT_FINAL +stdout 'cgo DW_AT_comp_dir is right in binary' + + +[!symlink] skip + +# Symlink the compiler to another path +env GOROOT=$WORK/goroot +symlink $GOROOT -> $TESTGO_GOROOT + +# 3. GOROOT_FINAL is same with 2, build with the other go +# the runtime/cgo will not be rebuild. +go build -x -o binary.exe +! stderr '(clang|gcc)( |\.exe).*gcc_.*\.c' +exec ./binary.exe $GOROOT_FINAL +stdout 'cgo DW_AT_comp_dir is right in binary' + + +# 4. unset GOROOT_FINAL, build with the other go +# the runtime/cgo will be rebuild. +env GOROOT_FINAL= +go build -x -o binary.exe +stderr '(clang|gcc)( |\.exe).*gcc_.*\.c' +exec ./binary.exe $GOROOT +stdout 'cgo DW_AT_comp_dir is right in binary' + +-- go.mod -- +module main + +go 1.18 +-- main.go -- +package main + +import "C" +import ( + "debug/dwarf" + "fmt" + "log" + "os" + "path/filepath" + "strings" +) + +var _ C.int + +func main() { + dwarfData, err := readDWARF(os.Args[0]) + if err != nil { + log.Fatal(err) + } + goroot := filepath.Join(os.Args[1], "src") + dwarfReader := dwarfData.Reader() + cgopackage := filepath.Join("runtime", "cgo") + var hascgo bool + for { + e, err := dwarfReader.Next() + if err != nil { + log.Fatal(err) + } + if e == nil { + break + } + field := e.AttrField(dwarf.AttrCompDir) + if field == nil { + continue + } + compdir := field.Val.(string) + if strings.HasSuffix(compdir, cgopackage) { + hascgo = true + if !strings.HasPrefix(compdir, goroot) { + fmt.Printf("cgo DW_AT_comp_dir %s contains incorrect path in binary.\n", compdir) + return + } + } + } + if hascgo { + fmt.Println("cgo DW_AT_comp_dir is right in binary") + } else { + fmt.Println("binary does not contain cgo") + } +} +-- read_darwin.go -- +package main + +import ( + "debug/dwarf" + "debug/macho" +) + +func readDWARF(exePath string) (*dwarf.Data, error) { + machoFile, err := macho.Open(exePath) + if err != nil { + return nil, err + } + defer machoFile.Close() + return machoFile.DWARF() +} +-- read_elf.go -- +// +build android dragonfly freebsd illumos linux netbsd openbsd solaris + +package main + +import ( + "debug/dwarf" + "debug/elf" +) + +func readDWARF(exePath string) (*dwarf.Data, error) { + elfFile, err := elf.Open(exePath) + if err != nil { + return nil, err + } + defer elfFile.Close() + return elfFile.DWARF() +} +-- read_windows.go -- +package main + +import ( + "debug/dwarf" + "debug/pe" +) + +func readDWARF(exePath string) (*dwarf.Data, error) { + peFile, err := pe.Open(exePath) + if err != nil { + return nil, err + } + defer peFile.Close() + return peFile.DWARF() +} -- GitLab From 24c2ee7b6578c683a608c3d8c41fe626d50e6b61 Mon Sep 17 00:00:00 2001 From: Lynn Boger Date: Wed, 22 Sep 2021 09:37:12 -0500 Subject: [PATCH 1275/2500] cmd/compile: enable reg args and add duffcopy support on ppc64x This adds support for duffcopy on ppc64x and updates the ssa/config.go file to enable register args and recognize the duffDevice is available on ppc64x. Change-Id: Ifc472cc9cc19c9a80e468fb52078c75f7dd44d36 Reviewed-on: https://go-review.googlesource.com/c/go/+/351490 Run-TryBot: Lynn Boger TryBot-Result: Go Bot Trust: Lynn Boger Reviewed-by: Cherry Mui --- src/cmd/compile/internal/ssa/config.go | 5 +- src/cmd/internal/obj/ppc64/a.out.go | 4 +- src/runtime/duff_ppc64x.s | 518 ++++++++++++++++++------- src/runtime/mkduff.go | 12 +- 4 files changed, 399 insertions(+), 140 deletions(-) diff --git a/src/cmd/compile/internal/ssa/config.go b/src/cmd/compile/internal/ssa/config.go index 61d1dea642..5ab7240acf 100644 --- a/src/cmd/compile/internal/ssa/config.go +++ b/src/cmd/compile/internal/ssa/config.go @@ -239,11 +239,10 @@ func NewConfig(arch string, types Types, ctxt *obj.Link, optimize, softfloat boo c.registers = registersPPC64[:] c.gpRegMask = gpRegMaskPPC64 c.fpRegMask = fpRegMaskPPC64 - //c.intParamRegs = paramIntRegPPC64 - //c.floatParamRegs = paramFloatRegPPC64 + c.intParamRegs = paramIntRegPPC64 + c.floatParamRegs = paramFloatRegPPC64 c.FPReg = framepointerRegPPC64 c.LinkReg = linkRegPPC64 - c.noDuffDevice = true // TODO: Resolve PPC64 DuffDevice (has zero, but not copy) c.hasGReg = true case "mips64": c.BigEndian = true diff --git a/src/cmd/internal/obj/ppc64/a.out.go b/src/cmd/internal/obj/ppc64/a.out.go index dda24a0b96..b5696f7993 100644 --- a/src/cmd/internal/obj/ppc64/a.out.go +++ b/src/cmd/internal/obj/ppc64/a.out.go @@ -242,8 +242,8 @@ const ( REGSB = REG_R2 REGRET = REG_R3 REGARG = -1 /* -1 disables passing the first argument in register */ - REGRT1 = REG_R3 /* reserved for runtime, duffzero and duffcopy */ - REGRT2 = REG_R4 /* reserved for runtime, duffcopy */ + REGRT1 = REG_R20 /* reserved for runtime, duffzero and duffcopy */ + REGRT2 = REG_R21 /* reserved for runtime, duffcopy */ REGMIN = REG_R7 /* register variables allocated from here to REGMAX */ REGCTXT = REG_R11 /* context for closures */ REGTLS = REG_R13 /* C ABI TLS base pointer */ diff --git a/src/runtime/duff_ppc64x.s b/src/runtime/duff_ppc64x.s index d4e3b409d2..eeecf13df1 100644 --- a/src/runtime/duff_ppc64x.s +++ b/src/runtime/duff_ppc64x.s @@ -7,136 +7,392 @@ #include "textflag.h" -TEXT runtime·duffzero(SB), NOSPLIT|NOFRAME, $0-0 - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) - MOVDU R0, 8(R3) +TEXT runtime·duffzero(SB), NOSPLIT|NOFRAME, $0-0 + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) + MOVDU R0, 8(R20) RET -TEXT runtime·duffcopy(SB), NOSPLIT|NOFRAME, $0-0 - UNDEF +TEXT runtime·duffcopy(SB), NOSPLIT|NOFRAME, $0-0 + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + MOVDU 8(R20), R5 + MOVDU R5, 8(R21) + RET diff --git a/src/runtime/mkduff.go b/src/runtime/mkduff.go index f036745092..f3c3d8dfb5 100644 --- a/src/runtime/mkduff.go +++ b/src/runtime/mkduff.go @@ -188,17 +188,21 @@ func zeroPPC64x(w io.Writer) { // R0: always zero // R3 (aka REGRT1): ptr to memory to be zeroed - 8 // On return, R3 points to the last zeroed dword. - fmt.Fprintln(w, "TEXT runtime·duffzero(SB), NOSPLIT|NOFRAME, $0-0") + fmt.Fprintln(w, "TEXT runtime·duffzero(SB), NOSPLIT|NOFRAME, $0-0") for i := 0; i < 128; i++ { - fmt.Fprintln(w, "\tMOVDU\tR0, 8(R3)") + fmt.Fprintln(w, "\tMOVDU\tR0, 8(R20)") } fmt.Fprintln(w, "\tRET") } func copyPPC64x(w io.Writer) { // duffcopy is not used on PPC64. - fmt.Fprintln(w, "TEXT runtime·duffcopy(SB), NOSPLIT|NOFRAME, $0-0") - fmt.Fprintln(w, "\tUNDEF") + fmt.Fprintln(w, "TEXT runtime·duffcopy(SB), NOSPLIT|NOFRAME, $0-0") + for i := 0; i < 128; i++ { + fmt.Fprintln(w, "\tMOVDU\t8(R20), R5") + fmt.Fprintln(w, "\tMOVDU\tR5, 8(R21)") + } + fmt.Fprintln(w, "\tRET") } func tagsMIPS64x(w io.Writer) { -- GitLab From 335e72bcb6a5f670e2b3c65170c4287ca7265934 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Thu, 23 Sep 2021 11:46:28 +0100 Subject: [PATCH 1276/2500] cmd/go: fix indentation of -workfile help text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While reading the help text for #48576, I noticed that the output was misaligned. Turns out it's because two lines have space indentation, while the rest use tab indentation. Fix that. Change-Id: Ie7c473d892ca13852fa2134f3cdef21e9210e02e Reviewed-on: https://go-review.googlesource.com/c/go/+/351750 Trust: Daniel Martí Run-TryBot: Daniel Martí TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/alldocs.go | 4 ++-- src/cmd/go/internal/work/build.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 744d462c00..0036d8615f 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -167,8 +167,8 @@ // directory, but it is not accessed. When -modfile is specified, an // alternate go.sum file is also used: its path is derived from the // -modfile flag by trimming the ".mod" extension and appending ".sum". -// -workfile file -// in module aware mode, use the given go.work file as a workspace file. +// -workfile file +// in module aware mode, use the given go.work file as a workspace file. // By default or when -workfile is "auto", the go command searches for a // file named go.work in the current directory and then containing directories // until one is found. If a valid go.work file is found, the modules diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go index e5d7f4a8fd..55e4954eee 100644 --- a/src/cmd/go/internal/work/build.go +++ b/src/cmd/go/internal/work/build.go @@ -121,8 +121,8 @@ and test commands: directory, but it is not accessed. When -modfile is specified, an alternate go.sum file is also used: its path is derived from the -modfile flag by trimming the ".mod" extension and appending ".sum". - -workfile file - in module aware mode, use the given go.work file as a workspace file. + -workfile file + in module aware mode, use the given go.work file as a workspace file. By default or when -workfile is "auto", the go command searches for a file named go.work in the current directory and then containing directories until one is found. If a valid go.work file is found, the modules -- GitLab From 5961134fa5530e8e07b5536b9577e4755ac1e04a Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Mon, 30 Aug 2021 10:25:11 -0700 Subject: [PATCH 1277/2500] crypto: avoid escaping Hash.Sum on generic architectures For architectures without a specialized implementation (e.g. arm), the generic implementation allocates because it does: var block = blockGeneric which causes the compiler to give up trying to analyze block even though it is technically only ever one implementation. Instead of a variable, declare a function that wraps blockGeneric. We apply this fix to md5, sha1, and sha256, while sha512 already had the equivalent change. We add a test to all hashing packages to ensure no allocations. Credit goes to Cuong Manh Le for more specifically identifying the problem and Keith Randal for suggesting a concrete solution. Fixes #48055 Change-Id: I1a6a2e028038e051c83fd72b10a8bf4d210df57d Reviewed-on: https://go-review.googlesource.com/c/go/+/346209 Trust: Joe Tsai Run-TryBot: Joe Tsai Reviewed-by: Filippo Valsorda Reviewed-by: Cuong Manh Le Reviewed-by: Keith Randall TryBot-Result: Go Bot --- src/crypto/md5/md5_test.go | 14 ++++++++++++++ src/crypto/md5/md5block_generic.go | 4 +++- src/crypto/sha1/sha1_test.go | 14 ++++++++++++++ src/crypto/sha1/sha1block_generic.go | 4 +++- src/crypto/sha256/sha256_test.go | 14 ++++++++++++++ src/crypto/sha256/sha256block_generic.go | 4 +++- src/crypto/sha512/sha512_test.go | 14 ++++++++++++++ 7 files changed, 65 insertions(+), 3 deletions(-) diff --git a/src/crypto/md5/md5_test.go b/src/crypto/md5/md5_test.go index acd456af21..851e7fb10d 100644 --- a/src/crypto/md5/md5_test.go +++ b/src/crypto/md5/md5_test.go @@ -211,6 +211,20 @@ func TestLargeHashes(t *testing.T) { } } +func TestAllocations(t *testing.T) { + in := []byte("hello, world!") + out := make([]byte, 0, Size) + h := New() + n := int(testing.AllocsPerRun(10, func() { + h.Reset() + h.Write(in) + out = h.Sum(out[:0]) + })) + if n > 0 { + t.Errorf("allocs = %d, want 0", n) + } +} + var bench = New() var buf = make([]byte, 1024*1024*8+1) var sum = make([]byte, bench.Size()) diff --git a/src/crypto/md5/md5block_generic.go b/src/crypto/md5/md5block_generic.go index ea4fbcd0b4..23ed75304f 100644 --- a/src/crypto/md5/md5block_generic.go +++ b/src/crypto/md5/md5block_generic.go @@ -9,4 +9,6 @@ package md5 const haveAsm = false -var block = blockGeneric +func block(dig *digest, p []byte) { + blockGeneric(dig, p) +} diff --git a/src/crypto/sha1/sha1_test.go b/src/crypto/sha1/sha1_test.go index c3e6010af1..ab43c7792d 100644 --- a/src/crypto/sha1/sha1_test.go +++ b/src/crypto/sha1/sha1_test.go @@ -210,6 +210,20 @@ func TestLargeHashes(t *testing.T) { } } +func TestAllocations(t *testing.T) { + in := []byte("hello, world!") + out := make([]byte, 0, Size) + h := New() + n := int(testing.AllocsPerRun(10, func() { + h.Reset() + h.Write(in) + out = h.Sum(out[:0]) + })) + if n > 0 { + t.Errorf("allocs = %d, want 0", n) + } +} + var bench = New() var buf = make([]byte, 8192) diff --git a/src/crypto/sha1/sha1block_generic.go b/src/crypto/sha1/sha1block_generic.go index feaba5a23a..105aa31832 100644 --- a/src/crypto/sha1/sha1block_generic.go +++ b/src/crypto/sha1/sha1block_generic.go @@ -7,4 +7,6 @@ package sha1 -var block = blockGeneric +func block(dig *digest, p []byte) { + blockGeneric(dig, p) +} diff --git a/src/crypto/sha256/sha256_test.go b/src/crypto/sha256/sha256_test.go index a2794b015d..702aa0b371 100644 --- a/src/crypto/sha256/sha256_test.go +++ b/src/crypto/sha256/sha256_test.go @@ -289,6 +289,20 @@ func TestLargeHashes(t *testing.T) { } } +func TestAllocations(t *testing.T) { + in := []byte("hello, world!") + out := make([]byte, 0, Size) + h := New() + n := int(testing.AllocsPerRun(10, func() { + h.Reset() + h.Write(in) + out = h.Sum(out[:0]) + })) + if n > 0 { + t.Errorf("allocs = %d, want 0", n) + } +} + var bench = New() var buf = make([]byte, 8192) diff --git a/src/crypto/sha256/sha256block_generic.go b/src/crypto/sha256/sha256block_generic.go index 620c048b93..0f2bf8b231 100644 --- a/src/crypto/sha256/sha256block_generic.go +++ b/src/crypto/sha256/sha256block_generic.go @@ -7,4 +7,6 @@ package sha256 -var block = blockGeneric +func block(dig *digest, p []byte) { + blockGeneric(dig, p) +} diff --git a/src/crypto/sha512/sha512_test.go b/src/crypto/sha512/sha512_test.go index 0e1528fc69..aea772c7da 100644 --- a/src/crypto/sha512/sha512_test.go +++ b/src/crypto/sha512/sha512_test.go @@ -888,6 +888,20 @@ func TestLargeHashes(t *testing.T) { } } +func TestAllocations(t *testing.T) { + in := []byte("hello, world!") + out := make([]byte, 0, Size) + h := New() + n := int(testing.AllocsPerRun(10, func() { + h.Reset() + h.Write(in) + out = h.Sum(out[:0]) + })) + if n > 0 { + t.Errorf("allocs = %d, want 0", n) + } +} + var bench = New() var buf = make([]byte, 8192) -- GitLab From 13f3c57cefef59e5d94f678483aff527807fb33b Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Thu, 23 Sep 2021 12:19:05 -0400 Subject: [PATCH 1278/2500] go/types,types2: disallow illegal cycles through Unions Checker.validType was not considering Unions when looking for illegal cycles. Fixes #48582 Change-Id: I11ad0279eeaaa56bb6d5731b0572c1c3a0c459eb Reviewed-on: https://go-review.googlesource.com/c/go/+/351829 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/decl.go | 7 +++++ .../types2/testdata/fixedbugs/issue41124.go2 | 2 +- .../types2/testdata/fixedbugs/issue48582.go2 | 29 +++++++++++++++++++ src/go/types/decl.go | 7 +++++ .../types/testdata/fixedbugs/issue41124.go2 | 4 +-- .../types/testdata/fixedbugs/issue48582.go2 | 29 +++++++++++++++++++ 6 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue48582.go2 create mode 100644 src/go/types/testdata/fixedbugs/issue48582.go2 diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 994c19ea30..ab2e3b875f 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -315,6 +315,13 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { } } + case *Union: + for _, t := range t.terms { + if check.validType(t.typ, path) == invalid { + return invalid + } + } + case *Interface: for _, etyp := range t.embeddeds { if check.validType(etyp, path) == invalid { diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2 index 4642ab60fc..cef24bd237 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2 @@ -6,7 +6,7 @@ package p // Test case from issue. -type Nat interface { +type Nat /* ERROR cycle */ interface { Zero|Succ } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48582.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48582.go2 new file mode 100644 index 0000000000..c12091be79 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48582.go2 @@ -0,0 +1,29 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type N /* ERROR cycle */ interface { + int | N +} + +type A /* ERROR cycle */ interface { + int | B +} + +type B interface { + int | A +} + +type S /* ERROR cycle */ struct { + I // ERROR interface contains type constraints +} + +type I interface { + int | S +} + +type P interface { + *P // ERROR interface contains type constraints +} diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 061fc01829..77914dd1af 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -314,6 +314,13 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { } } + case *Union: + for _, t := range t.terms { + if check.validType(t.typ, path) == invalid { + return invalid + } + } + case *Interface: for _, etyp := range t.embeddeds { if check.validType(etyp, path) == invalid { diff --git a/src/go/types/testdata/fixedbugs/issue41124.go2 b/src/go/types/testdata/fixedbugs/issue41124.go2 index 4642ab60fc..ac336a2ece 100644 --- a/src/go/types/testdata/fixedbugs/issue41124.go2 +++ b/src/go/types/testdata/fixedbugs/issue41124.go2 @@ -6,13 +6,13 @@ package p // Test case from issue. -type Nat interface { +type Nat /* ERROR cycle */ interface { Zero|Succ } type Zero struct{} type Succ struct{ - Nat // ERROR interface contains type constraints + Nat /* ERROR interface contains type constraints */ } // Struct tests. diff --git a/src/go/types/testdata/fixedbugs/issue48582.go2 b/src/go/types/testdata/fixedbugs/issue48582.go2 new file mode 100644 index 0000000000..c12091be79 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue48582.go2 @@ -0,0 +1,29 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type N /* ERROR cycle */ interface { + int | N +} + +type A /* ERROR cycle */ interface { + int | B +} + +type B interface { + int | A +} + +type S /* ERROR cycle */ struct { + I // ERROR interface contains type constraints +} + +type I interface { + int | S +} + +type P interface { + *P // ERROR interface contains type constraints +} -- GitLab From 2fc7697da43f24e19d2a9efb79dd7bb9a4e16556 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Fri, 24 Sep 2021 00:15:49 +0700 Subject: [PATCH 1279/2500] Revert "cmd/go: insert goroot to the hash of build cache when the packages include C files" This reverts commit abbfec2829b001cf758a058eba4ccdc940e029f4. Reason to revert: breaks darwin builders. Updates #48319 Change-Id: I50c957a6a3f46ffcdaf972bdbb0574867ddc9486 Reviewed-on: https://go-review.googlesource.com/c/go/+/351851 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le Reviewed-by: Cherry Mui TryBot-Result: Go Bot --- src/cmd/go/internal/work/exec.go | 34 ++-- .../go/testdata/script/build_issue48319.txt | 153 ------------------ 2 files changed, 10 insertions(+), 177 deletions(-) delete mode 100644 src/cmd/go/testdata/script/build_issue48319.txt diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index ed02c3c247..f82028aef6 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -222,32 +222,18 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID { // same compiler settings and can reuse each other's results. // If not, the reason is already recorded in buildGcflags. fmt.Fprintf(h, "compile\n") - - // Include information about the origin of the package that - // may be embedded in the debug info for the object file. - if cfg.BuildTrimpath { - // When -trimpath is used with a package built from the module cache, - // its debug information refers to the module path and version - // instead of the directory. - if p.Module != nil { - fmt.Fprintf(h, "module %s@%s\n", p.Module.Path, p.Module.Version) - } - } else if p.Goroot { - // The Go compiler always hides the exact value of $GOROOT - // when building things in GOROOT, but the C compiler - // merely rewrites GOROOT to GOROOT_FINAL. - if len(p.CFiles) > 0 { - fmt.Fprintf(h, "goroot %s\n", cfg.GOROOT_FINAL) - } - // b.WorkDir is always either trimmed or rewritten to - // the literal string "/tmp/go-build". - } else if !strings.HasPrefix(p.Dir, b.WorkDir) { - // -trimpath is not set and no other rewrite rules apply, - // so the object file may refer to the absolute directory - // containing the package. + // Only include the package directory if it may affect the output. + // We trim workspace paths for all packages when -trimpath is set. + // The compiler hides the exact value of $GOROOT + // when building things in GOROOT. + // Assume b.WorkDir is being trimmed properly. + // When -trimpath is used with a package built from the module cache, + // use the module path and version instead of the directory. + if !p.Goroot && !cfg.BuildTrimpath && !strings.HasPrefix(p.Dir, b.WorkDir) { fmt.Fprintf(h, "dir %s\n", p.Dir) + } else if cfg.BuildTrimpath && p.Module != nil { + fmt.Fprintf(h, "module %s@%s\n", p.Module.Path, p.Module.Version) } - if p.Module != nil { fmt.Fprintf(h, "go %s\n", p.Module.GoVersion) } diff --git a/src/cmd/go/testdata/script/build_issue48319.txt b/src/cmd/go/testdata/script/build_issue48319.txt deleted file mode 100644 index f58a5faa3f..0000000000 --- a/src/cmd/go/testdata/script/build_issue48319.txt +++ /dev/null @@ -1,153 +0,0 @@ -[short] skip -[!cgo] skip - -# Set up fresh GOCACHE -env GOCACHE=$WORK/gocache -mkdir $GOCACHE - -# 1. unset GOROOT_FINAL, Build a simple binary with cgo by origin go. -# The DW_AT_comp_dir of runtime/cgo should have a prefix with origin goroot. -env GOROOT_FINAL= -# If using "go run", it is no debuginfo in binary. So use "go build". -# And we can check the stderr to judge if the cache of "runtime/cgo" -# was used or not. -go build -o binary.exe -exec ./binary.exe $TESTGO_GOROOT -stdout 'cgo DW_AT_comp_dir is right in binary' - - -# 2. GOROOT_FINAL will be changed, the runtime/cgo will be rebuild. -env GOROOT_FINAL=$WORK/gorootfinal -go build -x -o binary.exe -stderr '(clang|gcc)( |\.exe).*gcc_.*\.c' -exec ./binary.exe $GOROOT_FINAL -stdout 'cgo DW_AT_comp_dir is right in binary' - - -[!symlink] skip - -# Symlink the compiler to another path -env GOROOT=$WORK/goroot -symlink $GOROOT -> $TESTGO_GOROOT - -# 3. GOROOT_FINAL is same with 2, build with the other go -# the runtime/cgo will not be rebuild. -go build -x -o binary.exe -! stderr '(clang|gcc)( |\.exe).*gcc_.*\.c' -exec ./binary.exe $GOROOT_FINAL -stdout 'cgo DW_AT_comp_dir is right in binary' - - -# 4. unset GOROOT_FINAL, build with the other go -# the runtime/cgo will be rebuild. -env GOROOT_FINAL= -go build -x -o binary.exe -stderr '(clang|gcc)( |\.exe).*gcc_.*\.c' -exec ./binary.exe $GOROOT -stdout 'cgo DW_AT_comp_dir is right in binary' - --- go.mod -- -module main - -go 1.18 --- main.go -- -package main - -import "C" -import ( - "debug/dwarf" - "fmt" - "log" - "os" - "path/filepath" - "strings" -) - -var _ C.int - -func main() { - dwarfData, err := readDWARF(os.Args[0]) - if err != nil { - log.Fatal(err) - } - goroot := filepath.Join(os.Args[1], "src") - dwarfReader := dwarfData.Reader() - cgopackage := filepath.Join("runtime", "cgo") - var hascgo bool - for { - e, err := dwarfReader.Next() - if err != nil { - log.Fatal(err) - } - if e == nil { - break - } - field := e.AttrField(dwarf.AttrCompDir) - if field == nil { - continue - } - compdir := field.Val.(string) - if strings.HasSuffix(compdir, cgopackage) { - hascgo = true - if !strings.HasPrefix(compdir, goroot) { - fmt.Printf("cgo DW_AT_comp_dir %s contains incorrect path in binary.\n", compdir) - return - } - } - } - if hascgo { - fmt.Println("cgo DW_AT_comp_dir is right in binary") - } else { - fmt.Println("binary does not contain cgo") - } -} --- read_darwin.go -- -package main - -import ( - "debug/dwarf" - "debug/macho" -) - -func readDWARF(exePath string) (*dwarf.Data, error) { - machoFile, err := macho.Open(exePath) - if err != nil { - return nil, err - } - defer machoFile.Close() - return machoFile.DWARF() -} --- read_elf.go -- -// +build android dragonfly freebsd illumos linux netbsd openbsd solaris - -package main - -import ( - "debug/dwarf" - "debug/elf" -) - -func readDWARF(exePath string) (*dwarf.Data, error) { - elfFile, err := elf.Open(exePath) - if err != nil { - return nil, err - } - defer elfFile.Close() - return elfFile.DWARF() -} --- read_windows.go -- -package main - -import ( - "debug/dwarf" - "debug/pe" -) - -func readDWARF(exePath string) (*dwarf.Data, error) { - peFile, err := pe.Open(exePath) - if err != nil { - return nil, err - } - defer peFile.Close() - return peFile.DWARF() -} -- GitLab From 0626ac064d9300d16e1e5878777efc0430088569 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 22 Sep 2021 17:08:00 -0700 Subject: [PATCH 1280/2500] cmd/compile: restore original assignment error messages When used with the compiler, types2 will report assignment error messages that closely match what the compiler type checker (types1) produces. Also, mark lhs variables as used in invalid variable initializations to avoid a class of follow-on errors. Fixes #48558. Change-Id: I92d1de006c66b3a2364bb1bea773a312963afe75 Reviewed-on: https://go-review.googlesource.com/c/go/+/351669 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- .../compile/internal/types2/assignments.go | 40 +++++++++- src/cmd/compile/internal/types2/expr.go | 6 +- test/fixedbugs/issue19323.go | 2 +- test/fixedbugs/issue26616.go | 6 +- test/fixedbugs/issue27595.go | 2 +- test/fixedbugs/issue48558.go | 77 +++++++++++++++++++ 6 files changed, 124 insertions(+), 9 deletions(-) create mode 100644 test/fixedbugs/issue48558.go diff --git a/src/cmd/compile/internal/types2/assignments.go b/src/cmd/compile/internal/types2/assignments.go index 29d63cf819..a1847b21ca 100644 --- a/src/cmd/compile/internal/types2/assignments.go +++ b/src/cmd/compile/internal/types2/assignments.go @@ -6,7 +6,10 @@ package types2 -import "cmd/compile/internal/syntax" +import ( + "cmd/compile/internal/syntax" + "fmt" +) // assignment reports whether x can be assigned to a variable of type T, // if necessary by attempting to convert untyped values to the appropriate @@ -236,6 +239,28 @@ func (check *Checker) assignVar(lhs syntax.Expr, x *operand) Type { return x.typ } +func (check *Checker) assignError(rhs []syntax.Expr, nvars, nvals int) { + measure := func(x int, unit string) string { + s := fmt.Sprintf("%d %s", x, unit) + if x != 1 { + s += "s" + } + return s + } + + vars := measure(nvars, "variable") + vals := measure(nvals, "value") + rhs0 := rhs[0] + + if len(rhs) == 1 { + if call, _ := unparen(rhs0).(*syntax.CallExpr); call != nil { + check.errorf(rhs0, "assignment mismatch: %s but %s returns %s", vars, call.Fun, vals) + return + } + } + check.errorf(rhs0, "assignment mismatch: %s but %s", vars, vals) +} + // If returnPos is valid, initVars is called to type-check the assignment of // return expressions, and returnPos is the position of the return statement. func (check *Checker) initVars(lhs []*Var, orig_rhs []syntax.Expr, returnPos syntax.Pos) { @@ -244,6 +269,7 @@ func (check *Checker) initVars(lhs []*Var, orig_rhs []syntax.Expr, returnPos syn if len(lhs) != len(rhs) { // invalidate lhs for _, obj := range lhs { + obj.used = true // avoid declared but not used errors if obj.typ == nil { obj.typ = Typ[Invalid] } @@ -258,7 +284,11 @@ func (check *Checker) initVars(lhs []*Var, orig_rhs []syntax.Expr, returnPos syn check.errorf(returnPos, "wrong number of return values (want %d, got %d)", len(lhs), len(rhs)) return } - check.errorf(rhs[0], "cannot initialize %d variables with %d values", len(lhs), len(rhs)) + if check.conf.CompilerErrorMessages { + check.assignError(orig_rhs, len(lhs), len(rhs)) + } else { + check.errorf(rhs[0], "cannot initialize %d variables with %d values", len(lhs), len(rhs)) + } return } @@ -292,7 +322,11 @@ func (check *Checker) assignVars(lhs, orig_rhs []syntax.Expr) { return } } - check.errorf(rhs[0], "cannot assign %d values to %d variables", len(rhs), len(lhs)) + if check.conf.CompilerErrorMessages { + check.assignError(orig_rhs, len(lhs), len(rhs)) + } else { + check.errorf(rhs[0], "cannot assign %d values to %d variables", len(rhs), len(lhs)) + } return } diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 99204762bc..12b7b6cd9f 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -1689,7 +1689,11 @@ func (check *Checker) singleValue(x *operand) { // tuple types are never named - no need for underlying type below if t, ok := x.typ.(*Tuple); ok { assert(t.Len() != 1) - check.errorf(x, "%d-valued %s where single value is expected", t.Len(), x) + if check.conf.CompilerErrorMessages { + check.errorf(x, "multiple-value %s in single-value context", x) + } else { + check.errorf(x, "%d-valued %s where single value is expected", t.Len(), x) + } x.mode = invalid } } diff --git a/test/fixedbugs/issue19323.go b/test/fixedbugs/issue19323.go index 77cac3ee16..5db0a48a34 100644 --- a/test/fixedbugs/issue19323.go +++ b/test/fixedbugs/issue19323.go @@ -15,5 +15,5 @@ func f() { func g2() ([]byte, []byte) { return nil, nil } func f2() { - g2()[:] // ERROR "multiple-value g2.. in single-value context|attempt to slice object that is not|2\-valued g" + g2()[:] // ERROR "multiple-value g2.* in single-value context|attempt to slice object that is not|2\-valued g" } diff --git a/test/fixedbugs/issue26616.go b/test/fixedbugs/issue26616.go index d5210e87b0..edf88d489e 100644 --- a/test/fixedbugs/issue26616.go +++ b/test/fixedbugs/issue26616.go @@ -6,11 +6,11 @@ package p -var x int = three() // ERROR "assignment mismatch: 1 variable but three returns 3 values|multiple-value function call in single-value context|3\-valued" +var x int = three() // ERROR "assignment mismatch: 1 variable but three returns 3 values|multiple-value function call in single-value context|multiple-value " func f() { - var _ int = three() // ERROR "assignment mismatch: 1 variable but three returns 3 values|multiple-value function call in single-value context|3\-valued" - var a int = three() // ERROR "assignment mismatch: 1 variable but three returns 3 values|multiple-value function call in single-value context|3\-valued" + var _ int = three() // ERROR "assignment mismatch: 1 variable but three returns 3 values|multiple-value function call in single-value context|multiple-value " + var a int = three() // ERROR "assignment mismatch: 1 variable but three returns 3 values|multiple-value function call in single-value context|multiple-value " a = three() // ERROR "assignment mismatch: 1 variable but three returns 3 values|multiple-value function call in single-value context|cannot assign" b := three() // ERROR "assignment mismatch: 1 variable but three returns 3 values|single variable set to multiple-value|multiple-value function call in single-value context|cannot initialize" _, _ = a, b diff --git a/test/fixedbugs/issue27595.go b/test/fixedbugs/issue27595.go index 2fc0eb2a58..86fb6384cd 100644 --- a/test/fixedbugs/issue27595.go +++ b/test/fixedbugs/issue27595.go @@ -6,7 +6,7 @@ package main -var a = twoResults() // ERROR "assignment mismatch: 1 variable but twoResults returns 2 values|2\-valued" +var a = twoResults() // ERROR "assignment mismatch: 1 variable but twoResults returns 2 values|multiple-value twoResults\(\) .*in single-value context" var b, c, d = twoResults() // ERROR "assignment mismatch: 3 variables but twoResults returns 2 values|cannot initialize" var e, f = oneResult() // ERROR "assignment mismatch: 2 variables but oneResult returns 1 value|cannot initialize" diff --git a/test/fixedbugs/issue48558.go b/test/fixedbugs/issue48558.go new file mode 100644 index 0000000000..9ab56d9e46 --- /dev/null +++ b/test/fixedbugs/issue48558.go @@ -0,0 +1,77 @@ +// errorcheck + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func _(a, b, c int) { + _ = a + _ = a, b // ERROR "assignment mismatch: 1 variable but 2 values" + _ = a, b, c // ERROR "assignment mismatch: 1 variable but 3 values" + + _, _ = a // ERROR "assignment mismatch: 2 variables but 1 value" + _, _ = a, b + _, _ = a, b, c // ERROR "assignment mismatch: 2 variables but 3 values" + + _, _, _ = a // ERROR "assignment mismatch: 3 variables but 1 value" + _, _, _ = a, b // ERROR "assignment mismatch: 3 variables but 2 values" + _, _, _ = a, b, c +} + +func f1() int +func f2() (int, int) +func f3() (int, int, int) + +func _() { + _ = f1() + _ = f2() // ERROR "assignment mismatch: 1 variable but f2 returns 2 values" + _ = f3() // ERROR "assignment mismatch: 1 variable but f3 returns 3 values" + + _, _ = f1() // ERROR "assignment mismatch: 2 variables but f1 returns 1 value" + _, _ = f2() + _, _ = f3() // ERROR "assignment mismatch: 2 variables but f3 returns 3 values" + + _, _, _ = f1() // ERROR "assignment mismatch: 3 variables but f1 returns 1 value" + _, _, _ = f2() // ERROR "assignment mismatch: 3 variables but f2 returns 2 values" + _, _, _ = f3() + + // test just a few := cases as they use the same code as the = case + a1 := f3() // ERROR "assignment mismatch: 1 variable but f3 returns 3 values" + a2, b2 := f1() // ERROR "assignment mismatch: 2 variables but f1 returns 1 value" + a3, b3, c3 := f2() // ERROR "assignment mismatch: 3 variables but f2 returns 2 values" +} + +type T struct{} + +func (T) f1() int +func (T) f2() (int, int) +func (T) f3() (int, int, int) + +func _(x T) { + _ = x.f1() + _ = x.f2() // ERROR "assignment mismatch: 1 variable but .\.f2 returns 2 values" + _ = x.f3() // ERROR "assignment mismatch: 1 variable but .\.f3 returns 3 values" + + _, _ = x.f1() // ERROR "assignment mismatch: 2 variables but .\.f1 returns 1 value" + _, _ = x.f2() + _, _ = x.f3() // ERROR "assignment mismatch: 2 variables but .\.f3 returns 3 values" + + _, _, _ = x.f1() // ERROR "assignment mismatch: 3 variables but .\.f1 returns 1 value" + _, _, _ = x.f2() // ERROR "assignment mismatch: 3 variables but .\.f2 returns 2 values" + _, _, _ = x.f3() + + // test just a few := cases as they use the same code as the = case + a1 := x.f3() // ERROR "assignment mismatch: 1 variable but .\.f3 returns 3 values" + a2, b2 := x.f1() // ERROR "assignment mismatch: 2 variables but .\.f1 returns 1 value" + a3, b3, c3 := x.f2() // ERROR "assignment mismatch: 3 variables but .\.f2 returns 2 values" +} + +// some one-off cases +func _() { + _ = (f2) + _ = f1(), 2 // ERROR "assignment mismatch: 1 variable but 2 values" + _, _ = (f1()), f2() // ERROR "multiple-value f2\(\) .*in single-value context" + _, _, _ = f3(), 3 // ERROR "assignment mismatch: 3 variables but 2 values|multiple-value f3\(\) .*in single-value context" +} -- GitLab From c0766d2cd0453b33da74407bcb0d32bbc5392c9b Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 22 Sep 2021 17:28:36 -0700 Subject: [PATCH 1281/2500] go/types: avoid "declared but not used errors" for invalid variable initializations This is a partial port of CL 351669 from types2 to go/types; it only copies the fix for variable usage. Eventually we may want to use the compiler error messages for assignment errors everywhere, but that doesn't need to happen now. Change-Id: I62b024b1b29cc27c29d919de3de44f944f6e2b4d Reviewed-on: https://go-review.googlesource.com/c/go/+/351670 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/go/types/assignments.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/go/types/assignments.go b/src/go/types/assignments.go index c46a97f2e2..2810133a1f 100644 --- a/src/go/types/assignments.go +++ b/src/go/types/assignments.go @@ -237,6 +237,7 @@ func (check *Checker) initVars(lhs []*Var, origRHS []ast.Expr, returnPos token.P if len(lhs) != len(rhs) { // invalidate lhs for _, obj := range lhs { + obj.used = true // avoid declared but not used errors if obj.typ == nil { obj.typ = Typ[Invalid] } -- GitLab From ddb5a42b25c63df9f11669bd4b14eeebcd2ba2bb Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 22 Sep 2021 21:57:19 -0700 Subject: [PATCH 1282/2500] cmd/compile/internal/types2: avoid "declared but not used" errors for invalid code Agressively mark all LHS variables in assignments as used if there is any error in the (entire) assignment. This reduces the number of spurious "declared but not used" errors in programs that are invalid in the first place. This behavior is closer to the behavior of the compiler's original type checker (types1) and lets us remove lines of the form "_ = variable" just to satisfy test cases. It also makes more important errors visible by not crowding them out. Remove the Checker.useLHS function and use Checker.use instead: useLHS didn't evaluate top-level variables, but we actually want them to be evaluated in an error scenario so that they are getting used (and thus we don't get the "declared but not used" error). Fixes #42937. Change-Id: Idda460f6b81c66735bf9fd597c54188949bf12b8 Reviewed-on: https://go-review.googlesource.com/c/go/+/351730 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- .../compile/internal/types2/assignments.go | 39 +++++++++++++-- src/cmd/compile/internal/types2/call.go | 48 ++++--------------- src/cmd/compile/internal/types2/stmt.go | 3 -- test/fixedbugs/bug062.go | 3 +- test/fixedbugs/bug131.go | 5 +- test/fixedbugs/bug175.go | 3 +- test/fixedbugs/bug289.go | 10 ++-- test/fixedbugs/issue9083.go | 12 ++--- test/interface/pointer.go | 5 +- 9 files changed, 57 insertions(+), 71 deletions(-) diff --git a/src/cmd/compile/internal/types2/assignments.go b/src/cmd/compile/internal/types2/assignments.go index a1847b21ca..bfc5578683 100644 --- a/src/cmd/compile/internal/types2/assignments.go +++ b/src/cmd/compile/internal/types2/assignments.go @@ -156,6 +156,7 @@ func (check *Checker) initVar(lhs *Var, x *operand, context string) Type { check.assignment(x, lhs.typ, context) if x.mode == invalid { + lhs.used = true // avoid follow-on "declared but not used" errors return nil } @@ -164,7 +165,7 @@ func (check *Checker) initVar(lhs *Var, x *operand, context string) Type { func (check *Checker) assignVar(lhs syntax.Expr, x *operand) Type { if x.mode == invalid || x.typ == Typ[Invalid] { - check.useLHS(lhs) + check.use(lhs) return nil } @@ -306,8 +307,18 @@ func (check *Checker) initVars(lhs []*Var, orig_rhs []syntax.Expr, returnPos syn return } + ok := true for i, lhs := range lhs { - check.initVar(lhs, rhs[i], context) + if check.initVar(lhs, rhs[i], context) == nil { + ok = false + } + } + + // avoid follow-on "declared but not used" errors if any initialization failed + if !ok { + for _, lhs := range lhs { + lhs.used = true + } } } @@ -315,7 +326,7 @@ func (check *Checker) assignVars(lhs, orig_rhs []syntax.Expr) { rhs, commaOk := check.exprList(orig_rhs, len(lhs) == 2) if len(lhs) != len(rhs) { - check.useLHS(lhs...) + check.use(lhs...) // don't report an error if we already reported one for _, x := range rhs { if x.mode == invalid { @@ -339,8 +350,26 @@ func (check *Checker) assignVars(lhs, orig_rhs []syntax.Expr) { return } + ok := true for i, lhs := range lhs { - check.assignVar(lhs, rhs[i]) + if check.assignVar(lhs, rhs[i]) == nil { + ok = false + } + } + + // avoid follow-on "declared but not used" errors if any assignment failed + if !ok { + // don't call check.use to avoid re-evaluation of the lhs expressions + for _, lhs := range lhs { + if name, _ := unparen(lhs).(*syntax.Name); name != nil { + if obj := check.lookup(name.Value); obj != nil { + // see comment in assignVar + if v, _ := obj.(*Var); v != nil && v.pkg == check.pkg { + v.used = true + } + } + } + } } } @@ -371,7 +400,7 @@ func (check *Checker) shortVarDecl(pos syntax.Pos, lhs, rhs []syntax.Expr) { for i, lhs := range lhs { ident, _ := lhs.(*syntax.Name) if ident == nil { - check.useLHS(lhs) + check.use(lhs) check.errorf(lhs, "non-name %s on left side of :=", lhs) hasErr = true continue diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index aaef97f58a..99afecaf19 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -627,48 +627,20 @@ Error: func (check *Checker) use(arg ...syntax.Expr) { var x operand for _, e := range arg { - // Certain AST fields may legally be nil (e.g., the ast.SliceExpr.High field). - if e == nil { + switch n := e.(type) { + case nil: + // some AST fields may be nil (e.g., elements of syntax.SliceExpr.Index) + // TODO(gri) can those fields really make it here? continue - } - if l, _ := e.(*syntax.ListExpr); l != nil { - check.use(l.ElemList...) - continue - } - check.rawExpr(&x, e, nil, false) - } -} - -// useLHS is like use, but doesn't "use" top-level identifiers. -// It should be called instead of use if the arguments are -// expressions on the lhs of an assignment. -// The arguments must not be nil. -func (check *Checker) useLHS(arg ...syntax.Expr) { - var x operand - for _, e := range arg { - // If the lhs is an identifier denoting a variable v, this assignment - // is not a 'use' of v. Remember current value of v.used and restore - // after evaluating the lhs via check.rawExpr. - var v *Var - var v_used bool - if ident, _ := unparen(e).(*syntax.Name); ident != nil { - // never type-check the blank name on the lhs - if ident.Value == "_" { + case *syntax.Name: + // don't report an error evaluating blank + if n.Value == "_" { continue } - if _, obj := check.scope.LookupParent(ident.Value, nopos); obj != nil { - // It's ok to mark non-local variables, but ignore variables - // from other packages to avoid potential race conditions with - // dot-imported variables. - if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg { - v = w - v_used = v.used - } - } + case *syntax.ListExpr: + check.use(n.ElemList...) + continue } check.rawExpr(&x, e, nil, false) - if v != nil { - v.used = v_used // restore v.used - } } } diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index e138c58123..f3f345fd2f 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -654,9 +654,6 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) { // declaration, but the post statement must not." if s, _ := s.Post.(*syntax.AssignStmt); s != nil && s.Op == syntax.Def { // The parser already reported an error. - // Don't call useLHS here because we want to use the lhs in - // this erroneous statement so that we don't get errors about - // these lhs variables being declared but not used. check.use(s.Lhs) // avoid follow-up errors } check.stmt(inner, s.Body) diff --git a/test/fixedbugs/bug062.go b/test/fixedbugs/bug062.go index 24c2dff933..1008f1af9c 100644 --- a/test/fixedbugs/bug062.go +++ b/test/fixedbugs/bug062.go @@ -7,6 +7,5 @@ package main func main() { - var s string = nil; // ERROR "illegal|invalid|incompatible|cannot" - _ = s + var s string = nil // ERROR "illegal|invalid|incompatible|cannot" } diff --git a/test/fixedbugs/bug131.go b/test/fixedbugs/bug131.go index 2c9d120ed0..de606da167 100644 --- a/test/fixedbugs/bug131.go +++ b/test/fixedbugs/bug131.go @@ -7,7 +7,6 @@ package main func main() { - const a uint64 = 10; - var b int64 = a; // ERROR "convert|cannot|incompatible" - _ = b + const a uint64 = 10 + var b int64 = a // ERROR "convert|cannot|incompatible" } diff --git a/test/fixedbugs/bug175.go b/test/fixedbugs/bug175.go index 88210a59b3..caf3168536 100644 --- a/test/fixedbugs/bug175.go +++ b/test/fixedbugs/bug175.go @@ -9,6 +9,5 @@ package main func f() (int, bool) { return 0, true } func main() { - x, y := f(), 2; // ERROR "multi|2-valued" - _, _ = x, y + x, y := f(), 2 // ERROR "multi|2-valued" } diff --git a/test/fixedbugs/bug289.go b/test/fixedbugs/bug289.go index fea6829992..7e8346ee0f 100644 --- a/test/fixedbugs/bug289.go +++ b/test/fixedbugs/bug289.go @@ -9,18 +9,14 @@ package main func f1() { - a, b := f() // ERROR "assignment mismatch|does not match|cannot initialize" - _ = a - _ = b + a, b := f() // ERROR "assignment mismatch|does not match|cannot initialize" } func f2() { var a, b int - a, b = f() // ERROR "assignment mismatch|does not match|cannot assign" - _ = a - _ = b + a, b = f() // ERROR "assignment mismatch|does not match|cannot assign" } func f() int { - return 1; + return 1 } diff --git a/test/fixedbugs/issue9083.go b/test/fixedbugs/issue9083.go index f5c5296a2b..ea53e7a69a 100644 --- a/test/fixedbugs/issue9083.go +++ b/test/fixedbugs/issue9083.go @@ -13,12 +13,10 @@ const zero = 0 func main() { var x int - _ = x - x = make(map[int]int) // ERROR "cannot use make\(map\[int\]int\)|incompatible" - x = make(map[int]int, 0) // ERROR "cannot use make\(map\[int\]int, 0\)|incompatible" + x = make(map[int]int) // ERROR "cannot use make\(map\[int\]int\)|incompatible" + x = make(map[int]int, 0) // ERROR "cannot use make\(map\[int\]int, 0\)|incompatible" x = make(map[int]int, zero) // ERROR "cannot use make\(map\[int\]int, zero\)|incompatible" - x = make(chan int) // ERROR "cannot use make\(chan int\)|incompatible" - x = make(chan int, 0) // ERROR "cannot use make\(chan int, 0\)|incompatible" - x = make(chan int, zero) // ERROR "cannot use make\(chan int, zero\)|incompatible" - _ = x + x = make(chan int) // ERROR "cannot use make\(chan int\)|incompatible" + x = make(chan int, 0) // ERROR "cannot use make\(chan int, 0\)|incompatible" + x = make(chan int, zero) // ERROR "cannot use make\(chan int, zero\)|incompatible" } diff --git a/test/interface/pointer.go b/test/interface/pointer.go index c21e4da390..a71b3f4bf8 100644 --- a/test/interface/pointer.go +++ b/test/interface/pointer.go @@ -24,7 +24,6 @@ type Start struct { func (start *Start) Next() *Inst { return nil } - func AddInst(Inst) *Inst { print("ok in addinst\n") return nil @@ -33,8 +32,6 @@ func AddInst(Inst) *Inst { func main() { print("call addinst\n") var x Inst = AddInst(new(Start)) // ERROR "pointer to interface|incompatible type" - _ = x print("return from addinst\n") - var y *Inst = new(Start) // ERROR "pointer to interface|incompatible type" - _ = y + var y *Inst = new(Start) // ERROR "pointer to interface|incompatible type" } -- GitLab From 02913aa51c1f1c1338596310ceafc63d4a93a19d Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 22 Sep 2021 22:11:17 -0700 Subject: [PATCH 1283/2500] test/fixedbugs: adjust test case (fix longtest builders) For #33232. Change-Id: Id95a92bfdad91e3ccde9f5654c3b1b02ca95f6ea Reviewed-on: https://go-review.googlesource.com/c/go/+/351731 Trust: Robert Griesemer Trust: Bryan C. Mills Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- test/fixedbugs/issue14652.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fixedbugs/issue14652.go b/test/fixedbugs/issue14652.go index 586663b676..6dd2fbfbf6 100644 --- a/test/fixedbugs/issue14652.go +++ b/test/fixedbugs/issue14652.go @@ -1,4 +1,4 @@ -// compile +// compile -G=3 // Copyright 2016 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style -- GitLab From 93f964b4122b7f9a1ae3f80ad75363403a5753ca Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Wed, 22 Sep 2021 11:54:22 -0400 Subject: [PATCH 1284/2500] cmd/compile/internal/ssa: remove workarounds for #43938 The cmd/go bug this worked around should be fixed as of CL 351329. Fixes #43938 Fixes #48550 Change-Id: Ida930e7ee33d44d89556b9b8bbc3c26bb53697b2 Reviewed-on: https://go-review.googlesource.com/c/go/+/351529 Trust: Bryan C. Mills Reviewed-by: David Chase Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot --- src/cmd/compile/internal/ssa/debug_lines_test.go | 15 +++++---------- src/cmd/compile/internal/ssa/debug_test.go | 3 +++ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/cmd/compile/internal/ssa/debug_lines_test.go b/src/cmd/compile/internal/ssa/debug_lines_test.go index c5a0fe449c..da04e5b04e 100644 --- a/src/cmd/compile/internal/ssa/debug_lines_test.go +++ b/src/cmd/compile/internal/ssa/debug_lines_test.go @@ -29,8 +29,10 @@ var asmLine *regexp.Regexp = regexp.MustCompile(`^\s[vb][0-9]+\s+[0-9]+\s\(\+([0 // this matches e.g. ` v123456789 000007 (+9876654310) MOVUPS X15, ""..autotmp_2-32(SP)` -// Matches lines in genssa output that describe an inlined file (on a Unix filesystem). Note it expects an unadventurous choice of basename. -var inlineLine *regexp.Regexp = regexp.MustCompile(`^#\s/.*/[-a-zA-Z0-9_]+\.go:([0-9]+)`) +// Matches lines in genssa output that describe an inlined file. +// Note it expects an unadventurous choice of basename. +var sepRE = regexp.QuoteMeta(string(filepath.Separator)) +var inlineLine *regexp.Regexp = regexp.MustCompile(`^#\s.*` + sepRE + `[-a-zA-Z0-9_]+\.go:([0-9]+)`) // this matches e.g. # /pa/inline-dumpxxxx.go:6 @@ -44,9 +46,6 @@ func testGoArch() string { } func TestDebugLines(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("Windows lacks $HOME which complicates workaround for 'missing $GOPATH'") // $HOME needed to work around #43938 - } // This test is potentially fragile, the goal is that debugging should step properly through "sayhi" // If the blocks are reordered in a way that changes the statement order but execution flows correctly, // then rearrange the expected numbers. Register abi and not-register-abi also have different sequences, @@ -65,9 +64,6 @@ func TestDebugLines(t *testing.T) { } func TestInlineLines(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("Windows lacks $HOME which complicates workaround for 'missing $GOPATH'") // $HOME needed to work around #43938 - } if runtime.GOARCH != "amd64" && *testGoArchFlag == "" { // As of september 2021, works for everything except mips64, but still potentially fragile t.Skip("only runs for amd64 unless -arch explicitly supplied") @@ -98,8 +94,7 @@ func compileAndDump(t *testing.T, file, function, moreGCFlags string) []byte { cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", "foo.o", "-gcflags=-d=ssa/genssa/dump="+function+" "+moreGCFlags, source) cmd.Dir = tmpdir cmd.Env = replaceEnv(cmd.Env, "GOSSADIR", tmpdir) - cmd.Env = replaceEnv(cmd.Env, "HOME", os.Getenv("HOME")) // workaround for #43938 - testGoos := "linux" // default to linux + testGoos := "linux" // default to linux if testGoArch() == "wasm" { testGoos = "js" } diff --git a/src/cmd/compile/internal/ssa/debug_test.go b/src/cmd/compile/internal/ssa/debug_test.go index 3346312542..b20041c1b5 100644 --- a/src/cmd/compile/internal/ssa/debug_test.go +++ b/src/cmd/compile/internal/ssa/debug_test.go @@ -952,6 +952,9 @@ func (s *ioState) readSimpleExpecting(expectedRE string) tstring { // replaceEnv returns a new environment derived from env // by removing any existing definition of ev and adding ev=evv. func replaceEnv(env []string, ev string, evv string) []string { + if env == nil { + env = os.Environ() + } evplus := ev + "=" var found bool for i, v := range env { -- GitLab From 4e308d73ba3610838305997b6f4793c4f4dcfc4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Wed, 22 Sep 2021 14:59:42 +0100 Subject: [PATCH 1285/2500] cmd/go: refer to the right package in a test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test checks that two packages aren't non-test dependencies. There's a copy-paste typo, however. When net/http is unexpectedly found as a dependendency, we instead mention the other package in the error message. Change-Id: I3232c6252255c839e08efa048f2232c192d0fb85 Reviewed-on: https://go-review.googlesource.com/c/go/+/351372 Trust: Daniel Martí Reviewed-by: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot --- src/cmd/go/internal/imports/scan_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/go/internal/imports/scan_test.go b/src/cmd/go/internal/imports/scan_test.go index 2d245ee787..7e69c56513 100644 --- a/src/cmd/go/internal/imports/scan_test.go +++ b/src/cmd/go/internal/imports/scan_test.go @@ -33,7 +33,7 @@ func TestScan(t *testing.T) { } if p == "net/http" { // A test import but not an import - t.Errorf("json reported as importing encoding/binary but does not") + t.Errorf("json reported as importing net/http but does not") } } if !foundBase64 { -- GitLab From c90ead97ad7542437079462e0b70ff7b3f8e7811 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 23 Sep 2021 16:53:21 -0700 Subject: [PATCH 1286/2500] cmd/compile/internal/types2: delay union element checks We cannot determine the underlying type right when parsing a union term since it may lead to types that are not yet fully set up. Fixes #46461. Change-Id: I1fcadb1dcef2160be2f088a4a34e99dbab01da67 Reviewed-on: https://go-review.googlesource.com/c/go/+/351969 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- .../types2/testdata/fixedbugs/issue46461.go2 | 9 +++++++++ src/cmd/compile/internal/types2/typeset.go | 8 ++++---- src/cmd/compile/internal/types2/union.go | 20 +++++++++++++------ 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46461.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46461.go2 index bfeaf3a966..8bf31090b8 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46461.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46461.go2 @@ -4,8 +4,17 @@ package p +// test case 1 type T[U interface{ M() T[U] }] int type X int func (X) M() T[X] { return 0 } + +// test case 2 +type A[T interface{ A[T] }] interface{} + +// test case 3 +type A2[U interface{ A2[U] }] interface{ M() A2[U] } + +type I interface{ A2[I]; M() A2[I] } diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index ae39f26e4f..c56aa56e2e 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -291,8 +291,8 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_ terms = tset.terms case *TypeParam: // Embedding stand-alone type parameters is not permitted. - // This case is handled during union parsing. - unreachable() + // Union parsing reports a (delayed) error, so we can ignore this entry. + continue default: if typ == Typ[Invalid] { continue @@ -372,8 +372,8 @@ func computeUnionTypeSet(check *Checker, pos syntax.Pos, utyp *Union) *_TypeSet terms = computeInterfaceTypeSet(check, pos, u).terms case *TypeParam: // A stand-alone type parameters is not permitted as union term. - // This case is handled during union parsing. - unreachable() + // Union parsing reports a (delayed) error, so we can ignore this entry. + continue default: if t.typ == Typ[Invalid] { continue diff --git a/src/cmd/compile/internal/types2/union.go b/src/cmd/compile/internal/types2/union.go index d4c749a89b..87985dd133 100644 --- a/src/cmd/compile/internal/types2/union.go +++ b/src/cmd/compile/internal/types2/union.go @@ -54,7 +54,10 @@ func parseUnion(check *Checker, tlist []syntax.Expr) Type { for _, x := range tlist { tilde, typ := parseTilde(check, x) if len(tlist) == 1 && !tilde { - return typ // single type (optimization) + // Single type. Ok to return early because all relevant + // checks have been performed in parseTilde (no need to + // run through term validity check below). + return typ } if len(terms) >= maxTermCount { check.errorf(x, "cannot handle more than %d union terms (implementation limitation)", maxTermCount) @@ -123,11 +126,16 @@ func parseTilde(check *Checker, x syntax.Expr) (tilde bool, typ Type) { tilde = true } typ = check.typ(x) - // embedding stand-alone type parameters is not permitted (issue #47127). - if _, ok := under(typ).(*TypeParam); ok { - check.error(x, "cannot embed a type parameter") - typ = Typ[Invalid] - } + // Embedding stand-alone type parameters is not permitted (issue #47127). + // Do this check later because it requires computation of the underlying type (see also issue #46461). + // Note: If an underlying type cannot be a type parameter, the call to + // under() will not be needed and then we don't need to delay this + // check to later and could return Typ[Invalid] instead. + check.later(func() { + if _, ok := under(typ).(*TypeParam); ok { + check.error(x, "cannot embed a type parameter") + } + }) return } -- GitLab From 4dd5f0994f2e2079582876db4af1cba95fe3b6c2 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 13 Sep 2021 15:40:11 -0700 Subject: [PATCH 1287/2500] constraints: new package The constraint packages defined a set of useful constraints to be used with type parameters. Fixes #45458 Change-Id: Id4f4e6c55debb90e6b10ea0dbe2319be1e888746 Reviewed-on: https://go-review.googlesource.com/c/go/+/349709 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/constraints/constraints.go | 65 ++++++++++++ src/constraints/constraints_test.go | 155 ++++++++++++++++++++++++++++ src/go/build/deps_test.go | 2 +- 3 files changed, 221 insertions(+), 1 deletion(-) create mode 100644 src/constraints/constraints.go create mode 100644 src/constraints/constraints_test.go diff --git a/src/constraints/constraints.go b/src/constraints/constraints.go new file mode 100644 index 0000000000..2a5f673a7e --- /dev/null +++ b/src/constraints/constraints.go @@ -0,0 +1,65 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package constraints defines a set of useful constraints to be used +// with type parameters. +package constraints + +// Signed is a constraint that permits any signed integer type. +// If future releases of Go add new predeclared signed integer types, +// this constraint will be modified to include them. +type Signed interface { + ~int | ~int8 | ~int16 | ~int32 | ~int64 +} + +// Unsigned is a constraint that permits any unsigned integer type. +// If future releases of Go add new predeclared unsigned integer types, +// this constraint will be modified to include them. +type Unsigned interface { + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr +} + +// Integer is a constraint that permits any integer type. +// If future releases of Go add new predeclared integer types, +// this constraint will be modified to include them. +type Integer interface { + Signed | Unsigned +} + +// Float is a constraint that permits any floating-point type. +// If future releases of Go add new predeclared floating-point types, +// this constraint will be modified to include them. +type Float interface { + ~float32 | ~float64 +} + +// Complex is a constraint that permits any complex numeric type. +// If future releases of Go add new predeclared complex numeric types, +// this constraint will be modified to include them. +type Complex interface { + ~complex64 | ~complex128 +} + +// Ordered is a constraint that permits any ordered type: any type +// that supports the operators < <= >= >. +// If future releases of Go add new ordered types, +// this constraint will be modified to include them. +type Ordered interface { + Integer | Float | ~string +} + +// Slice is a constraint that matches slices of any element type. +type Slice[Elem any] interface { + ~[]Elem +} + +// Map is a constraint that matches maps of any element and value type. +type Map[Key comparable, Val any] interface { + ~map[Key]Val +} + +// Chan is a constraint that matches channels of any element type. +type Chan[Elem any] interface { + ~chan Elem +} diff --git a/src/constraints/constraints_test.go b/src/constraints/constraints_test.go new file mode 100644 index 0000000000..db5a957313 --- /dev/null +++ b/src/constraints/constraints_test.go @@ -0,0 +1,155 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package constraints + +import ( + "bytes" + "fmt" + "internal/testenv" + "os" + "os/exec" + "path/filepath" + "testing" +) + +type ( + testSigned[T Signed] struct{ f T } + testUnsigned[T Unsigned] struct{ f T } + testInteger[T Integer] struct{ f T } + testFloat[T Float] struct{ f T } + testComplex[T Complex] struct{ f T } + testOrdered[T Ordered] struct{ f T } + testSlice[T Slice[E], E any] struct{ f T } + testMap[T Map[K, V], K comparable, V any] struct{ f T } + testChan[T Chan[E], E any] struct{ f T } +) + +// TestTypes passes if it compiles. +type TestTypes struct { + _ testSigned[int] + _ testSigned[int64] + _ testUnsigned[uint] + _ testUnsigned[uintptr] + _ testInteger[int8] + _ testInteger[uint8] + _ testInteger[uintptr] + _ testFloat[float32] + _ testComplex[complex64] + _ testOrdered[int] + _ testOrdered[float64] + _ testOrdered[string] + _ testSlice[[]int, int] + _ testMap[map[int]bool, int, bool] + _ testChan[chan int, int] +} + +func infer1[S Slice[E], E any](s S, v E) S { return s } +func infer2[M Map[K, V], K comparable, V any](m M, k K, v V) M { return m } +func infer3[C Chan[E], E any](c C, v E) C { return c } + +func TestInference(t *testing.T) { + var empty interface{} + + type S []int + empty = infer1(S{}, 0) + if _, ok := empty.(S); !ok { + t.Errorf("infer1(S) returned %T, expected S", empty) + } + + type M map[int]bool + empty = infer2(M{}, 0, false) + if _, ok := empty.(M); !ok { + t.Errorf("infer2(M) returned %T, expected M", empty) + } + + type C chan bool + empty = infer3(make(C), true) + if _, ok := empty.(C); !ok { + t.Errorf("infer3(C) returned %T, expected C", empty) + } +} + +var prolog = []byte(` +package constrainttest + +import "constraints" + +type ( + testSigned[T constraints.Signed] struct{ f T } + testUnsigned[T constraints.Unsigned] struct{ f T } + testInteger[T constraints.Integer] struct{ f T } + testFloat[T constraints.Float] struct{ f T } + testComplex[T constraints.Complex] struct{ f T } + testOrdered[T constraints.Ordered] struct{ f T } + testSlice[T constraints.Slice[E], E any] struct{ f T } + testMap[T constraints.Map[K, V], K comparable, V any] struct{ f T } + testChan[T constraints.Chan[E], E any] struct{ f T } +) +`) + +func TestFailure(t *testing.T) { + testenv.MustHaveGoBuild(t) + gocmd := testenv.GoToolPath(t) + tmpdir := t.TempDir() + + if err := os.WriteFile(filepath.Join(tmpdir, "go.mod"), []byte("module constraintest"), 0666); err != nil { + t.Fatal(err) + } + + // Test for types that should not satisfy a constraint. + // For each pair of constraint and type, write a Go file + // var V constraint[type] + // For example, + // var V testSigned[uint] + // This should not compile, as testSigned (above) uses + // constraints.Signed, and uint does not satisfy that constraint. + // Therefore, the build of that code should fail. + for i, test := range []struct { + constraint, typ string + }{ + {"testSigned", "uint"}, + {"testUnsigned", "int"}, + {"testInteger", "float32"}, + {"testFloat", "int8"}, + {"testComplex", "float64"}, + {"testOrdered", "bool"}, + {"testSlice", "int, int"}, + {"testMap", "string, string, string"}, + {"testChan", "[]int, int"}, + } { + i := i + test := test + t.Run(fmt.Sprintf("%s %d", test.constraint, i), func(t *testing.T) { + t.Parallel() + name := fmt.Sprintf("go%d.go", i) + f, err := os.Create(filepath.Join(tmpdir, name)) + if err != nil { + t.Fatal(err) + } + if _, err := f.Write(prolog); err != nil { + t.Fatal(err) + } + if _, err := fmt.Fprintf(f, "var V %s[%s]\n", test.constraint, test.typ); err != nil { + t.Fatal(err) + } + if err := f.Close(); err != nil { + t.Fatal(err) + } + cmd := exec.Command(gocmd, "build", name) + cmd.Dir = tmpdir + if out, err := cmd.CombinedOutput(); err == nil { + t.Error("build succeeded, but expected to fail") + } else if len(out) > 0 { + t.Logf("%s", out) + const want = "does not satisfy" + if !bytes.Contains(out, []byte(want)) { + t.Errorf("output does not include %q", want) + } + } else { + t.Error("no error output, expected something") + } + }) + } +} diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index a9939dfcf3..3c3819f3b3 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -70,7 +70,7 @@ import ( var depsRules = ` # No dependencies allowed for any of these packages. NONE - < container/list, container/ring, + < constraints, container/list, container/ring, internal/cfg, internal/cpu, internal/goarch, internal/goexperiment, internal/goos, internal/goversion, internal/nettrace, -- GitLab From 0f1159bf5429b7e2dc774b77be41a66b53d25c55 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 23 Sep 2021 17:35:36 -0700 Subject: [PATCH 1288/2500] go/types: delay union element checks This is a clean port of CL 351969 from types2 to go/types with a minor adjustment for error handling (provide an error code). For #46461. Change-Id: I493dde12d8ccf86aa33f4913ac6e82f2eb459088 Reviewed-on: https://go-review.googlesource.com/c/go/+/351971 Trust: Robert Griesemer Reviewed-by: Robert Findley --- .../types/testdata/fixedbugs/issue46461.go2 | 9 +++++++++ src/go/types/typeset.go | 8 ++++---- src/go/types/union.go | 20 +++++++++++++------ 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/go/types/testdata/fixedbugs/issue46461.go2 b/src/go/types/testdata/fixedbugs/issue46461.go2 index bfeaf3a966..8bf31090b8 100644 --- a/src/go/types/testdata/fixedbugs/issue46461.go2 +++ b/src/go/types/testdata/fixedbugs/issue46461.go2 @@ -4,8 +4,17 @@ package p +// test case 1 type T[U interface{ M() T[U] }] int type X int func (X) M() T[X] { return 0 } + +// test case 2 +type A[T interface{ A[T] }] interface{} + +// test case 3 +type A2[U interface{ A2[U] }] interface{ M() A2[U] } + +type I interface{ A2[I]; M() A2[I] } diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index 648d3c7bf3..3e59155e5c 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -289,8 +289,8 @@ func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_T terms = tset.terms case *TypeParam: // Embedding stand-alone type parameters is not permitted. - // This case is handled during union parsing. - unreachable() + // Union parsing reports a (delayed) error, so we can ignore this entry. + continue default: if typ == Typ[Invalid] { continue @@ -370,8 +370,8 @@ func computeUnionTypeSet(check *Checker, pos token.Pos, utyp *Union) *_TypeSet { terms = computeInterfaceTypeSet(check, pos, u).terms case *TypeParam: // A stand-alone type parameters is not permitted as union term. - // This case is handled during union parsing. - unreachable() + // Union parsing reports a (delayed) error, so we can ignore this entry. + continue default: if t.typ == Typ[Invalid] { continue diff --git a/src/go/types/union.go b/src/go/types/union.go index f6b32b9e5d..88b2a9ff8f 100644 --- a/src/go/types/union.go +++ b/src/go/types/union.go @@ -57,7 +57,10 @@ func parseUnion(check *Checker, tlist []ast.Expr) Type { for _, x := range tlist { tilde, typ := parseTilde(check, x) if len(tlist) == 1 && !tilde { - return typ // single type (optimization) + // Single type. Ok to return early because all relevant + // checks have been performed in parseTilde (no need to + // run through term validity check below). + return typ } if len(terms) >= maxTermCount { check.errorf(x, _Todo, "cannot handle more than %d union terms (implementation limitation)", maxTermCount) @@ -126,11 +129,16 @@ func parseTilde(check *Checker, x ast.Expr) (tilde bool, typ Type) { tilde = true } typ = check.typ(x) - // embedding stand-alone type parameters is not permitted (issue #47127). - if _, ok := under(typ).(*TypeParam); ok { - check.error(x, _Todo, "cannot embed a type parameter") - typ = Typ[Invalid] - } + // Embedding stand-alone type parameters is not permitted (issue #47127). + // Do this check later because it requires computation of the underlying type (see also issue #46461). + // Note: If an underlying type cannot be a type parameter, the call to + // under() will not be needed and then we don't need to delay this + // check to later and could return Typ[Invalid] instead. + check.later(func() { + if _, ok := under(typ).(*TypeParam); ok { + check.error(x, _Todo, "cannot embed a type parameter") + } + }) return } -- GitLab From 483533df9e35eea46747c5545307b230eca997b6 Mon Sep 17 00:00:00 2001 From: Meng Zhuo Date: Tue, 14 Sep 2021 10:48:18 +0800 Subject: [PATCH 1289/2500] runtime: using wyrand for fastrand MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For modern 64-bit CPU architecture multiplier is faster than xorshift darwin/amd64 name old time/op new time/op delta Fastrand 2.13ns ± 1% 1.78ns ± 1% -16.47% (p=0.000 n=9+10) FastrandHashiter 32.5ns ± 4% 32.1ns ± 3% ~ (p=0.277 n=8+9) Fastrandn/2 2.16ns ± 1% 1.99ns ± 1% -7.53% (p=0.000 n=10+10) Fastrandn/3 2.13ns ± 3% 2.00ns ± 1% -5.88% (p=0.000 n=10+10) Fastrandn/4 2.08ns ± 2% 1.98ns ± 2% -4.71% (p=0.000 n=10+10) Fastrandn/5 2.08ns ± 2% 1.98ns ± 1% -4.90% (p=0.000 n=10+9) linux/mips64le name old time/op new time/op delta Fastrand 12.1ns ± 0% 10.8ns ± 1% -10.58% (p=0.000 n=8+10) FastrandHashiter 105ns ± 1% 105ns ± 1% ~ (p=0.138 n=10+10) Fastrandn/2 16.9ns ± 0% 16.4ns ± 4% -2.84% (p=0.020 n=10+10) Fastrandn/3 16.9ns ± 0% 16.4ns ± 3% -3.03% (p=0.000 n=10+10) Fastrandn/4 16.9ns ± 0% 16.5ns ± 2% -2.01% (p=0.002 n=8+10) Fastrandn/5 16.9ns ± 0% 16.4ns ± 3% -2.70% (p=0.000 n=8+10) linux/riscv64 name old time/op new time/op delta Fastrand 22.7ns ± 0% 12.7ns ±19% -44.09% (p=0.000 n=9+10) FastrandHashiter 255ns ± 4% 250ns ± 7% ~ (p=0.363 n=10+10) Fastrandn/2 31.8ns ± 2% 28.5ns ±13% -10.45% (p=0.000 n=10+10) Fastrandn/3 33.0ns ± 2% 27.4ns ± 8% -17.16% (p=0.000 n=9+10) Fastrandn/4 29.6ns ± 3% 28.2ns ± 5% -4.81% (p=0.000 n=8+9) Fastrandn/5 33.4ns ± 3% 26.5ns ± 9% -20.49% (p=0.000 n=8+10) Change-Id: I88ac69625ef923f8be66647e3361e3be986de002 Reviewed-on: https://go-review.googlesource.com/c/go/+/337350 Trust: Meng Zhuo Run-TryBot: Meng Zhuo TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/runtime/proc.go | 11 ++++------- src/runtime/runtime2.go | 2 +- src/runtime/stubs.go | 17 +++++++++++++++-- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 605e133000..b744d0e71e 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -680,10 +680,10 @@ func schedinit() { moduledataverify() stackinit() mallocinit() + cpuinit() // must run before alginit + alginit() // maps, hash, fastrand must not be used before this call fastrandinit() // must run before mcommoninit mcommoninit(_g_.m, -1) - cpuinit() // must run before alginit - alginit() // maps must not be used before this call modulesinit() // provides activeModules typelinksinit() // uses maps, activeModules itabsinit() // uses activeModules @@ -787,11 +787,8 @@ func mcommoninit(mp *m, id int64) { mp.id = mReserveID() } - mp.fastrand[0] = uint32(int64Hash(uint64(mp.id), fastrandseed)) - mp.fastrand[1] = uint32(int64Hash(uint64(cputicks()), ^fastrandseed)) - if mp.fastrand[0]|mp.fastrand[1] == 0 { - mp.fastrand[1] = 1 - } + // cputicks is not very random in startup virtual machine + mp.fastrand = uint64(int64Hash(uint64(mp.id), fastrandseed^uintptr(cputicks()))) mpreinit(mp) if mp.gsignal != nil { diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index 271d57e5d0..04bd5cb887 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -538,7 +538,7 @@ type m struct { printlock int8 incgo bool // m is executing a cgo call freeWait uint32 // if == 0, safe to free g0 and delete m (atomic) - fastrand [2]uint32 + fastrand uint64 needextram bool traceback uint8 ncgocall uint64 // number of cgo calls in total diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go index c85b7d7330..91380a0d51 100644 --- a/src/runtime/stubs.go +++ b/src/runtime/stubs.go @@ -8,6 +8,7 @@ import ( "internal/abi" "internal/goarch" "internal/goexperiment" + "runtime/internal/math" "unsafe" ) @@ -124,15 +125,27 @@ const hashLoad = float32(loadFactorNum) / float32(loadFactorDen) //go:nosplit func fastrand() uint32 { mp := getg().m + // Implement wyrand: https://github.com/wangyi-fudan/wyhash + // Only the platform that math.Mul64 can be lowered + // by the compiler should be in this list. + if goarch.IsAmd64|goarch.IsArm64|goarch.IsPpc64| + goarch.IsPpc64le|goarch.IsMips64|goarch.IsMips64le| + goarch.IsS390x|goarch.IsRiscv64 == 1 { + mp.fastrand += 0xa0761d6478bd642f + hi, lo := math.Mul64(mp.fastrand, mp.fastrand^0xe7037ed1a0b428db) + return uint32(hi ^ lo) + } + // Implement xorshift64+: 2 32-bit xorshift sequences added together. // Shift triplet [17,7,16] was calculated as indicated in Marsaglia's // Xorshift paper: https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf // This generator passes the SmallCrush suite, part of TestU01 framework: // http://simul.iro.umontreal.ca/testu01/tu01.html - s1, s0 := mp.fastrand[0], mp.fastrand[1] + t := (*[2]uint32)(unsafe.Pointer(&mp.fastrand)) + s1, s0 := t[0], t[1] s1 ^= s1 << 17 s1 = s1 ^ s0 ^ s1>>7 ^ s0>>16 - mp.fastrand[0], mp.fastrand[1] = s0, s1 + t[0], t[1] = s0, s1 return s0 + s1 } -- GitLab From aa878ee49b6954a818cc00c26754c84b86a4215b Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 23 Sep 2021 20:50:48 -0700 Subject: [PATCH 1290/2500] cmd/compile/internal/syntax: assume generic code for std lib Also: improve some error message prints in testSyntaxErrors. Change-Id: Iaa1d642398fa82975fefb4bde54f476dd5229eb5 Reviewed-on: https://go-review.googlesource.com/c/go/+/351791 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Cuong Manh Le TryBot-Result: Go Bot --- src/cmd/compile/internal/syntax/error_test.go | 4 ++-- src/cmd/compile/internal/syntax/parser_test.go | 7 ++----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/cmd/compile/internal/syntax/error_test.go b/src/cmd/compile/internal/syntax/error_test.go index 30e68ff1d9..0952ddc647 100644 --- a/src/cmd/compile/internal/syntax/error_test.go +++ b/src/cmd/compile/internal/syntax/error_test.go @@ -154,11 +154,11 @@ func testSyntaxErrors(t *testing.T, filename string) { if found { rx, err := regexp.Compile(pattern) if err != nil { - t.Errorf("%s: %v", pos, err) + t.Errorf("%s:%s: %v", filename, pos, err) return } if match := rx.MatchString(e.Msg); !match { - t.Errorf("%s: %q does not match %q", pos, e.Msg, pattern) + t.Errorf("%s:%s: %q does not match %q", filename, pos, e.Msg, pattern) return } // we have a match - eliminate this error diff --git a/src/cmd/compile/internal/syntax/parser_test.go b/src/cmd/compile/internal/syntax/parser_test.go index 6afe109e1b..04a16e96fe 100644 --- a/src/cmd/compile/internal/syntax/parser_test.go +++ b/src/cmd/compile/internal/syntax/parser_test.go @@ -51,10 +51,7 @@ func TestParseGo2(t *testing.T) { } } -func TestStdLib(t *testing.T) { testStdLib(t, 0) } -func TestStdLibGeneric(t *testing.T) { testStdLib(t, AllowGenerics) } - -func testStdLib(t *testing.T, mode Mode) { +func TestStdLib(t *testing.T) { if testing.Short() { t.Skip("skipping test in short mode") } @@ -93,7 +90,7 @@ func testStdLib(t *testing.T, mode Mode) { if debug { fmt.Printf("parsing %s\n", filename) } - ast, err := ParseFile(filename, nil, nil, mode) + ast, err := ParseFile(filename, nil, nil, AllowGenerics) if err != nil { t.Error(err) return -- GitLab From 9ce601df6a8292f763b07994680013facd7b4a63 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 23 Sep 2021 23:40:58 +0700 Subject: [PATCH 1291/2500] cmd/go: move gc concurrency level computation near gcflags So after constructing "args" variable, "gcflags" is not used anywhere. It makes the code easier to maintain, and prevent subtle bug like #48490. Change-Id: I41653536480880a8a6f9fbf6cfa8a461b6fb3208 Reviewed-on: https://go-review.googlesource.com/c/go/+/351849 Reviewed-by: Bryan C. Mills Reviewed-by: Jay Conrod Reviewed-by: Russ Cox Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Trust: Cuong Manh Le --- src/cmd/go/internal/work/gc.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go index 4e4a1d8451..fe0a45ec2a 100644 --- a/src/cmd/go/internal/work/gc.go +++ b/src/cmd/go/internal/work/gc.go @@ -156,6 +156,10 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg } } } + // Add -c=N to use concurrent backend compilation, if possible. + if c := gcBackendConcurrency(gcflags); c > 1 { + gcflags = append(gcflags, fmt.Sprintf("-c=%d", c)) + } args := []interface{}{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", a.trimpath(), defaultGcFlags, gcflags} if p.Internal.LocalPrefix != "" { @@ -181,11 +185,6 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg args = append(args, "-asmhdr", objdir+"go_asm.h") } - // Add -c=N to use concurrent backend compilation, if possible. - if c := gcBackendConcurrency(gcflags); c > 1 { - args = append(args, fmt.Sprintf("-c=%d", c)) - } - for _, f := range gofiles { f := mkAbs(p.Dir, f) -- GitLab From 242d02dd5e9bddc3392237752abe7dfe1f9cb300 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 23 Sep 2021 21:47:45 -0700 Subject: [PATCH 1292/2500] cmd/compile/internal/types2: assume generic code for std lib Change-Id: Ib24890af8caa02af61358cadac6637574d62ff52 Reviewed-on: https://go-review.googlesource.com/c/go/+/351792 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/types2/stdlib_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/types2/stdlib_test.go b/src/cmd/compile/internal/types2/stdlib_test.go index 5bf2982418..6e340d0777 100644 --- a/src/cmd/compile/internal/types2/stdlib_test.go +++ b/src/cmd/compile/internal/types2/stdlib_test.go @@ -217,7 +217,7 @@ func typecheck(t *testing.T, path string, filenames []string) { var files []*syntax.File for _, filename := range filenames { errh := func(err error) { t.Error(err) } - file, err := syntax.ParseFile(filename, errh, nil, 0) + file, err := syntax.ParseFile(filename, errh, nil, syntax.AllowGenerics) if err != nil { return } -- GitLab From d4139083204ab83778ad4ea575fb8370a14d7b7b Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Wed, 22 Sep 2021 02:46:00 +1000 Subject: [PATCH 1293/2500] test/codegen: add shift tests for RISCV64 Add tests for shift by constant, masked shifts and bounded shifts. While here, sort tests by architecture and keep order of tests consistent (lsh, rshU, rsh). Change-Id: I512d64196f34df9cb2884e8c0f6adcf9dd88b0fc Reviewed-on: https://go-review.googlesource.com/c/go/+/351289 Trust: Joel Sing Reviewed-by: Michael Munday Reviewed-by: Cherry Mui Run-TryBot: Cherry Mui --- test/codegen/shift.go | 120 ++++++++++++++++++++++++++++++++---------- 1 file changed, 92 insertions(+), 28 deletions(-) diff --git a/test/codegen/shift.go b/test/codegen/shift.go index 06f6f12473..8e87e96c9e 100644 --- a/test/codegen/shift.go +++ b/test/codegen/shift.go @@ -6,91 +6,152 @@ package codegen +// ------------------ // +// constant shifts // +// ------------------ // + +func lshConst64x64(v int64) int64 { + // riscv64:"SLL","AND","SLTIU" + return v << uint64(33) +} + +func rshConst64Ux64(v uint64) uint64 { + // riscv64:"SRL","AND","SLTIU" + return v >> uint64(33) +} + +func rshConst64x64(v int64) int64 { + // riscv64:"SRA","OR","SLTIU" + return v >> uint64(33) +} + +func lshConst32x64(v int32) int32 { + // riscv64:"SLL","AND","SLTIU" + return v << uint64(29) +} + +func rshConst32Ux64(v uint32) uint32 { + // riscv64:"SRL","AND","SLTIU" + return v >> uint64(29) +} + +func rshConst32x64(v int32) int32 { + // riscv64:"SRA","OR","SLTIU" + return v >> uint64(29) +} + +func lshConst64x32(v int64) int64 { + // riscv64:"SLL","AND","SLTIU" + return v << uint32(33) +} + +func rshConst64Ux32(v uint64) uint64 { + // riscv64:"SRL","AND","SLTIU" + return v >> uint32(33) +} + +func rshConst64x32(v int64) int64 { + // riscv64:"SRA","OR","SLTIU" + return v >> uint32(33) +} + // ------------------ // // masked shifts // // ------------------ // func lshMask64x64(v int64, s uint64) int64 { - // s390x:-"RISBGZ",-"AND",-"LOCGR" - // ppc64le:"ANDCC",-"ORN",-"ISEL" // ppc64:"ANDCC",-"ORN",-"ISEL" + // ppc64le:"ANDCC",-"ORN",-"ISEL" + // riscv64:"SLL","AND","SLTIU" + // s390x:-"RISBGZ",-"AND",-"LOCGR" return v << (s & 63) } func rshMask64Ux64(v uint64, s uint64) uint64 { - // s390x:-"RISBGZ",-"AND",-"LOCGR" - // ppc64le:"ANDCC",-"ORN",-"ISEL" // ppc64:"ANDCC",-"ORN",-"ISEL" + // ppc64le:"ANDCC",-"ORN",-"ISEL" + // riscv64:"SRL","AND","SLTIU" + // s390x:-"RISBGZ",-"AND",-"LOCGR" return v >> (s & 63) } func rshMask64x64(v int64, s uint64) int64 { - // s390x:-"RISBGZ",-"AND",-"LOCGR" - // ppc64le:"ANDCC",-ORN",-"ISEL" // ppc64:"ANDCC",-"ORN",-"ISEL" + // ppc64le:"ANDCC",-ORN",-"ISEL" + // riscv64:"SRA","OR","SLTIU" + // s390x:-"RISBGZ",-"AND",-"LOCGR" return v >> (s & 63) } func lshMask32x64(v int32, s uint64) int32 { - // s390x:-"RISBGZ",-"AND",-"LOCGR" - // ppc64le:"ISEL",-"ORN" // ppc64:"ISEL",-"ORN" + // ppc64le:"ISEL",-"ORN" + // riscv64:"SLL","AND","SLTIU" + // s390x:-"RISBGZ",-"AND",-"LOCGR" return v << (s & 63) } func rshMask32Ux64(v uint32, s uint64) uint32 { - // s390x:-"RISBGZ",-"AND",-"LOCGR" - // ppc64le:"ISEL",-"ORN" // ppc64:"ISEL",-"ORN" + // ppc64le:"ISEL",-"ORN" + // riscv64:"SRL","AND","SLTIU" + // s390x:-"RISBGZ",-"AND",-"LOCGR" return v >> (s & 63) } func rshMask32x64(v int32, s uint64) int32 { - // s390x:-"RISBGZ",-"AND",-"LOCGR" - // ppc64le:"ISEL",-"ORN" // ppc64:"ISEL",-"ORN" + // ppc64le:"ISEL",-"ORN" + // riscv64:"SRA","OR","SLTIU" + // s390x:-"RISBGZ",-"AND",-"LOCGR" return v >> (s & 63) } func lshMask64x32(v int64, s uint32) int64 { - // s390x:-"RISBGZ",-"AND",-"LOCGR" - // ppc64le:"ANDCC",-"ORN" // ppc64:"ANDCC",-"ORN" + // ppc64le:"ANDCC",-"ORN" + // riscv64:"SLL","AND","SLTIU" + // s390x:-"RISBGZ",-"AND",-"LOCGR" return v << (s & 63) } func rshMask64Ux32(v uint64, s uint32) uint64 { - // s390x:-"RISBGZ",-"AND",-"LOCGR" - // ppc64le:"ANDCC",-"ORN" // ppc64:"ANDCC",-"ORN" + // ppc64le:"ANDCC",-"ORN" + // riscv64:"SRL","AND","SLTIU" + // s390x:-"RISBGZ",-"AND",-"LOCGR" return v >> (s & 63) } func rshMask64x32(v int64, s uint32) int64 { - // s390x:-"RISBGZ",-"AND",-"LOCGR" - // ppc64le:"ANDCC",-"ORN",-"ISEL" // ppc64:"ANDCC",-"ORN",-"ISEL" + // ppc64le:"ANDCC",-"ORN",-"ISEL" + // riscv64:"SRA","OR","SLTIU" + // s390x:-"RISBGZ",-"AND",-"LOCGR" return v >> (s & 63) } func lshMask64x32Ext(v int64, s int32) int64 { - // s390x:-"RISBGZ",-"AND",-"LOCGR" - // ppc64le:"ANDCC",-"ORN",-"ISEL" // ppc64:"ANDCC",-"ORN",-"ISEL" + // ppc64le:"ANDCC",-"ORN",-"ISEL" + // riscv64:"SLL","AND","SLTIU" + // s390x:-"RISBGZ",-"AND",-"LOCGR" return v << uint(s&63) } func rshMask64Ux32Ext(v uint64, s int32) uint64 { - // s390x:-"RISBGZ",-"AND",-"LOCGR" - // ppc64le:"ANDCC",-"ORN",-"ISEL" // ppc64:"ANDCC",-"ORN",-"ISEL" + // ppc64le:"ANDCC",-"ORN",-"ISEL" + // riscv64:"SRL","AND","SLTIU" + // s390x:-"RISBGZ",-"AND",-"LOCGR" return v >> uint(s&63) } func rshMask64x32Ext(v int64, s int32) int64 { - // s390x:-"RISBGZ",-"AND",-"LOCGR" - // ppc64le:"ANDCC",-"ORN",-"ISEL" // ppc64:"ANDCC",-"ORN",-"ISEL" + // ppc64le:"ANDCC",-"ORN",-"ISEL" + // riscv64:"SRA","OR","SLTIU" + // s390x:-"RISBGZ",-"AND",-"LOCGR" return v >> uint(s&63) } @@ -126,17 +187,19 @@ func lshSignedMasked(v8 int8, v16 int16, v32 int32, v64 int64, x int) { // bounded shifts // // ------------------ // -func rshGuarded64(v int64, s uint) int64 { +func lshGuarded64(v int64, s uint) int64 { if s < 64 { + // riscv64:"SLL","AND","SLTIU" // s390x:-"RISBGZ",-"AND",-"LOCGR" // wasm:-"Select",-".*LtU" - return v >> s + return v << s } panic("shift too large") } func rshGuarded64U(v uint64, s uint) uint64 { if s < 64 { + // riscv64:"SRL","AND","SLTIU" // s390x:-"RISBGZ",-"AND",-"LOCGR" // wasm:-"Select",-".*LtU" return v >> s @@ -144,11 +207,12 @@ func rshGuarded64U(v uint64, s uint) uint64 { panic("shift too large") } -func lshGuarded64(v int64, s uint) int64 { +func rshGuarded64(v int64, s uint) int64 { if s < 64 { + // riscv64:"SRA","OR","SLTIU" // s390x:-"RISBGZ",-"AND",-"LOCGR" // wasm:-"Select",-".*LtU" - return v << s + return v >> s } panic("shift too large") } -- GitLab From fe8347b61a5e33506c9e3827877ec318c90377e6 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Fri, 17 Sep 2021 16:53:11 +1000 Subject: [PATCH 1294/2500] cmd/compile: optimise immediate operands with constants on riscv64 Instructions with immediates can be precomputed when operating on a constant - do so for SLTI/SLTIU, SLLI/SRLI/SRAI, NEG/NEGW, ANDI, ORI and ADDI. Additionally, optimise ANDI and ORI when the immediate is all ones or all zeroes. In particular, the RISCV64 logical left and right shift rules (Lsh*x*/Rsh*Ux*) produce sequences that check if the shift amount exceeds 64 and if so returns zero. When the shift amount is a constant we can precompute and eliminate the filter entirely. Likewise the arithmetic right shift rules produce sequences that check if the shift amount exceeds 64 and if so, ensures that the lower six bits of the shift are all ones. When the shift amount is a constant we can precompute the shift value. Arithmetic right shift sequences like: 117fc: 00100513 li a0,1 11800: 04053593 sltiu a1,a0,64 11804: fff58593 addi a1,a1,-1 11808: 0015e593 ori a1,a1,1 1180c: 40b45433 sra s0,s0,a1 Are now a single srai instruction: 117fc: 40145413 srai s0,s0,0x1 Likewise for logical left shift (and logical right shift): 1d560: 01100413 li s0,17 1d564: 04043413 sltiu s0,s0,64 1d568: 40800433 neg s0,s0 1d56c: 01131493 slli s1,t1,0x11 1d570: 0084f433 and s0,s1,s0 Which are now a single slli (or srli) instruction: 1d120: 01131413 slli s0,t1,0x11 This removes more than 30,000 instructions from the Go binary and should improve performance in a variety of areas - of note runtime.makemap_small drops from 48 to 36 instructions. Similar gains exist in at least other parts of runtime and math/bits. Change-Id: I33f6f3d1fd36d9ff1bda706997162bfe4bb859b6 Reviewed-on: https://go-review.googlesource.com/c/go/+/350689 Trust: Joel Sing Reviewed-by: Michael Munday Reviewed-by: Cherry Mui --- .../compile/internal/ssa/gen/RISCV64.rules | 38 ++- .../compile/internal/ssa/rewriteRISCV64.go | 220 ++++++++++++++++++ test/codegen/shift.go | 18 +- 3 files changed, 257 insertions(+), 19 deletions(-) diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64.rules b/src/cmd/compile/internal/ssa/gen/RISCV64.rules index 4290d1b85c..3379e1dac5 100644 --- a/src/cmd/compile/internal/ssa/gen/RISCV64.rules +++ b/src/cmd/compile/internal/ssa/gen/RISCV64.rules @@ -6,9 +6,7 @@ // * Use SLTI and SLTIU for comparisons to constants, instead of SLT/SLTU with constants in registers // * Use the zero register instead of moving 0 into a register. // * Add rules to avoid generating a temp bool value for (If (SLT[U] ...) ...). -// * Optimize left and right shift by simplifying SLTIU, Neg, and ADD for constants. // * Arrange for non-trivial Zero and Move lowerings to use aligned loads and stores. -// * Eliminate zero immediate shifts, adds, etc. // * Avoid using Neq32 for writeBarrier.enabled checks. // Lowering arithmetic @@ -229,7 +227,7 @@ (Rsh64x32 x y) => (SRA x (OR y (ADDI [-1] (SLTIU [64] (ZeroExt32to64 y))))) (Rsh64x64 x y) => (SRA x (OR y (ADDI [-1] (SLTIU [64] y)))) -// rotates +// Rotates. (RotateLeft8 x (MOVDconst [c])) => (Or8 (Lsh8x64 x (MOVDconst [c&7])) (Rsh8Ux64 x (MOVDconst [-c&7]))) (RotateLeft16 x (MOVDconst [c])) => (Or16 (Lsh16x64 x (MOVDconst [c&15])) (Rsh16Ux64 x (MOVDconst [-c&15]))) (RotateLeft32 x (MOVDconst [c])) => (Or32 (Lsh32x64 x (MOVDconst [c&31])) (Rsh32Ux64 x (MOVDconst [-c&31]))) @@ -707,19 +705,39 @@ (SUB x (MOVDconst [val])) && is32Bit(-val) => (ADDI [-val] x) // Subtraction of zero. -(SUB x (MOVDconst [0])) => x - -// Subtraction of zero with sign extension. +(SUB x (MOVDconst [0])) => x (SUBW x (MOVDconst [0])) => (ADDIW [0] x) // Subtraction from zero. -(SUB (MOVDconst [0]) x) => (NEG x) - -// Subtraction from zero with sign extension. +(SUB (MOVDconst [0]) x) => (NEG x) (SUBW (MOVDconst [0]) x) => (NEGW x) -// Addition of zero. +// Addition of zero or two constants. (ADDI [0] x) => x +(ADDI [x] (MOVDconst [y])) && is32Bit(x + y) => (MOVDconst [x + y]) + +// ANDI with all zeros, all ones or two constants. +(ANDI [0] x) => (MOVDconst [0]) +(ANDI [-1] x) => x +(ANDI [x] (MOVDconst [y])) => (MOVDconst [x & y]) + +// ORI with all zeroes, all ones or two constants. +(ORI [0] x) => x +(ORI [-1] x) => (MOVDconst [-1]) +(ORI [x] (MOVDconst [y])) => (MOVDconst [x | y]) + +// Negation of a constant. +(NEG (MOVDconst [x])) => (MOVDconst [-x]) +(NEGW (MOVDconst [x])) => (MOVDconst [int64(int32(-x))]) + +// Shift of a constant. +(SLLI [x] (MOVDconst [y])) && is32Bit(y << x) => (MOVDconst [y << x]) +(SRLI [x] (MOVDconst [y])) => (MOVDconst [int64(uint64(y) >> x)]) +(SRAI [x] (MOVDconst [y])) => (MOVDconst [int64(y) >> x]) + +// SLTI/SLTIU with constants. +(SLTI [x] (MOVDconst [y])) => (MOVDconst [b2i(int64(y) < int64(x))]) +(SLTIU [x] (MOVDconst [y])) => (MOVDconst [b2i(uint64(y) < uint64(x))]) // Merge negation into fused multiply-add and multiply-subtract. // diff --git a/src/cmd/compile/internal/ssa/rewriteRISCV64.go b/src/cmd/compile/internal/ssa/rewriteRISCV64.go index f856a26d49..885bbaf4a1 100644 --- a/src/cmd/compile/internal/ssa/rewriteRISCV64.go +++ b/src/cmd/compile/internal/ssa/rewriteRISCV64.go @@ -441,6 +441,8 @@ func rewriteValueRISCV64(v *Value) bool { return rewriteValueRISCV64_OpRISCV64ADDI(v) case OpRISCV64AND: return rewriteValueRISCV64_OpRISCV64AND(v) + case OpRISCV64ANDI: + return rewriteValueRISCV64_OpRISCV64ANDI(v) case OpRISCV64FMADDD: return rewriteValueRISCV64_OpRISCV64FMADDD(v) case OpRISCV64FMSUBD: @@ -495,14 +497,30 @@ func rewriteValueRISCV64(v *Value) bool { return rewriteValueRISCV64_OpRISCV64MOVWstore(v) case OpRISCV64MOVWstorezero: return rewriteValueRISCV64_OpRISCV64MOVWstorezero(v) + case OpRISCV64NEG: + return rewriteValueRISCV64_OpRISCV64NEG(v) + case OpRISCV64NEGW: + return rewriteValueRISCV64_OpRISCV64NEGW(v) case OpRISCV64OR: return rewriteValueRISCV64_OpRISCV64OR(v) + case OpRISCV64ORI: + return rewriteValueRISCV64_OpRISCV64ORI(v) case OpRISCV64SLL: return rewriteValueRISCV64_OpRISCV64SLL(v) + case OpRISCV64SLLI: + return rewriteValueRISCV64_OpRISCV64SLLI(v) + case OpRISCV64SLTI: + return rewriteValueRISCV64_OpRISCV64SLTI(v) + case OpRISCV64SLTIU: + return rewriteValueRISCV64_OpRISCV64SLTIU(v) case OpRISCV64SRA: return rewriteValueRISCV64_OpRISCV64SRA(v) + case OpRISCV64SRAI: + return rewriteValueRISCV64_OpRISCV64SRAI(v) case OpRISCV64SRL: return rewriteValueRISCV64_OpRISCV64SRL(v) + case OpRISCV64SRLI: + return rewriteValueRISCV64_OpRISCV64SRLI(v) case OpRISCV64SUB: return rewriteValueRISCV64_OpRISCV64SUB(v) case OpRISCV64SUBW: @@ -2822,6 +2840,22 @@ func rewriteValueRISCV64_OpRISCV64ADDI(v *Value) bool { v.copyOf(x) return true } + // match: (ADDI [x] (MOVDconst [y])) + // cond: is32Bit(x + y) + // result: (MOVDconst [x + y]) + for { + x := auxIntToInt64(v.AuxInt) + if v_0.Op != OpRISCV64MOVDconst { + break + } + y := auxIntToInt64(v_0.AuxInt) + if !(is32Bit(x + y)) { + break + } + v.reset(OpRISCV64MOVDconst) + v.AuxInt = int64ToAuxInt(x + y) + return true + } return false } func rewriteValueRISCV64_OpRISCV64AND(v *Value) bool { @@ -2849,6 +2883,42 @@ func rewriteValueRISCV64_OpRISCV64AND(v *Value) bool { } return false } +func rewriteValueRISCV64_OpRISCV64ANDI(v *Value) bool { + v_0 := v.Args[0] + // match: (ANDI [0] x) + // result: (MOVDconst [0]) + for { + if auxIntToInt64(v.AuxInt) != 0 { + break + } + v.reset(OpRISCV64MOVDconst) + v.AuxInt = int64ToAuxInt(0) + return true + } + // match: (ANDI [-1] x) + // result: x + for { + if auxIntToInt64(v.AuxInt) != -1 { + break + } + x := v_0 + v.copyOf(x) + return true + } + // match: (ANDI [x] (MOVDconst [y])) + // result: (MOVDconst [x & y]) + for { + x := auxIntToInt64(v.AuxInt) + if v_0.Op != OpRISCV64MOVDconst { + break + } + y := auxIntToInt64(v_0.AuxInt) + v.reset(OpRISCV64MOVDconst) + v.AuxInt = int64ToAuxInt(x & y) + return true + } + return false +} func rewriteValueRISCV64_OpRISCV64FMADDD(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] @@ -4619,6 +4689,36 @@ func rewriteValueRISCV64_OpRISCV64MOVWstorezero(v *Value) bool { } return false } +func rewriteValueRISCV64_OpRISCV64NEG(v *Value) bool { + v_0 := v.Args[0] + // match: (NEG (MOVDconst [x])) + // result: (MOVDconst [-x]) + for { + if v_0.Op != OpRISCV64MOVDconst { + break + } + x := auxIntToInt64(v_0.AuxInt) + v.reset(OpRISCV64MOVDconst) + v.AuxInt = int64ToAuxInt(-x) + return true + } + return false +} +func rewriteValueRISCV64_OpRISCV64NEGW(v *Value) bool { + v_0 := v.Args[0] + // match: (NEGW (MOVDconst [x])) + // result: (MOVDconst [int64(int32(-x))]) + for { + if v_0.Op != OpRISCV64MOVDconst { + break + } + x := auxIntToInt64(v_0.AuxInt) + v.reset(OpRISCV64MOVDconst) + v.AuxInt = int64ToAuxInt(int64(int32(-x))) + return true + } + return false +} func rewriteValueRISCV64_OpRISCV64OR(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -4644,6 +4744,42 @@ func rewriteValueRISCV64_OpRISCV64OR(v *Value) bool { } return false } +func rewriteValueRISCV64_OpRISCV64ORI(v *Value) bool { + v_0 := v.Args[0] + // match: (ORI [0] x) + // result: x + for { + if auxIntToInt64(v.AuxInt) != 0 { + break + } + x := v_0 + v.copyOf(x) + return true + } + // match: (ORI [-1] x) + // result: (MOVDconst [-1]) + for { + if auxIntToInt64(v.AuxInt) != -1 { + break + } + v.reset(OpRISCV64MOVDconst) + v.AuxInt = int64ToAuxInt(-1) + return true + } + // match: (ORI [x] (MOVDconst [y])) + // result: (MOVDconst [x | y]) + for { + x := auxIntToInt64(v.AuxInt) + if v_0.Op != OpRISCV64MOVDconst { + break + } + y := auxIntToInt64(v_0.AuxInt) + v.reset(OpRISCV64MOVDconst) + v.AuxInt = int64ToAuxInt(x | y) + return true + } + return false +} func rewriteValueRISCV64_OpRISCV64SLL(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -4662,6 +4798,58 @@ func rewriteValueRISCV64_OpRISCV64SLL(v *Value) bool { } return false } +func rewriteValueRISCV64_OpRISCV64SLLI(v *Value) bool { + v_0 := v.Args[0] + // match: (SLLI [x] (MOVDconst [y])) + // cond: is32Bit(y << x) + // result: (MOVDconst [y << x]) + for { + x := auxIntToInt64(v.AuxInt) + if v_0.Op != OpRISCV64MOVDconst { + break + } + y := auxIntToInt64(v_0.AuxInt) + if !(is32Bit(y << x)) { + break + } + v.reset(OpRISCV64MOVDconst) + v.AuxInt = int64ToAuxInt(y << x) + return true + } + return false +} +func rewriteValueRISCV64_OpRISCV64SLTI(v *Value) bool { + v_0 := v.Args[0] + // match: (SLTI [x] (MOVDconst [y])) + // result: (MOVDconst [b2i(int64(y) < int64(x))]) + for { + x := auxIntToInt64(v.AuxInt) + if v_0.Op != OpRISCV64MOVDconst { + break + } + y := auxIntToInt64(v_0.AuxInt) + v.reset(OpRISCV64MOVDconst) + v.AuxInt = int64ToAuxInt(b2i(int64(y) < int64(x))) + return true + } + return false +} +func rewriteValueRISCV64_OpRISCV64SLTIU(v *Value) bool { + v_0 := v.Args[0] + // match: (SLTIU [x] (MOVDconst [y])) + // result: (MOVDconst [b2i(uint64(y) < uint64(x))]) + for { + x := auxIntToInt64(v.AuxInt) + if v_0.Op != OpRISCV64MOVDconst { + break + } + y := auxIntToInt64(v_0.AuxInt) + v.reset(OpRISCV64MOVDconst) + v.AuxInt = int64ToAuxInt(b2i(uint64(y) < uint64(x))) + return true + } + return false +} func rewriteValueRISCV64_OpRISCV64SRA(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -4680,6 +4868,22 @@ func rewriteValueRISCV64_OpRISCV64SRA(v *Value) bool { } return false } +func rewriteValueRISCV64_OpRISCV64SRAI(v *Value) bool { + v_0 := v.Args[0] + // match: (SRAI [x] (MOVDconst [y])) + // result: (MOVDconst [int64(y) >> x]) + for { + x := auxIntToInt64(v.AuxInt) + if v_0.Op != OpRISCV64MOVDconst { + break + } + y := auxIntToInt64(v_0.AuxInt) + v.reset(OpRISCV64MOVDconst) + v.AuxInt = int64ToAuxInt(int64(y) >> x) + return true + } + return false +} func rewriteValueRISCV64_OpRISCV64SRL(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -4698,6 +4902,22 @@ func rewriteValueRISCV64_OpRISCV64SRL(v *Value) bool { } return false } +func rewriteValueRISCV64_OpRISCV64SRLI(v *Value) bool { + v_0 := v.Args[0] + // match: (SRLI [x] (MOVDconst [y])) + // result: (MOVDconst [int64(uint64(y) >> x)]) + for { + x := auxIntToInt64(v.AuxInt) + if v_0.Op != OpRISCV64MOVDconst { + break + } + y := auxIntToInt64(v_0.AuxInt) + v.reset(OpRISCV64MOVDconst) + v.AuxInt = int64ToAuxInt(int64(uint64(y) >> x)) + return true + } + return false +} func rewriteValueRISCV64_OpRISCV64SUB(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] diff --git a/test/codegen/shift.go b/test/codegen/shift.go index 8e87e96c9e..b3ed69d9e3 100644 --- a/test/codegen/shift.go +++ b/test/codegen/shift.go @@ -11,47 +11,47 @@ package codegen // ------------------ // func lshConst64x64(v int64) int64 { - // riscv64:"SLL","AND","SLTIU" + // riscv64:"SLLI",-"AND",-"SLTIU" return v << uint64(33) } func rshConst64Ux64(v uint64) uint64 { - // riscv64:"SRL","AND","SLTIU" + // riscv64:"SRLI",-"AND",-"SLTIU" return v >> uint64(33) } func rshConst64x64(v int64) int64 { - // riscv64:"SRA","OR","SLTIU" + // riscv64:"SRAI",-"OR",-"SLTIU" return v >> uint64(33) } func lshConst32x64(v int32) int32 { - // riscv64:"SLL","AND","SLTIU" + // riscv64:"SLLI",-"AND",-"SLTIU" return v << uint64(29) } func rshConst32Ux64(v uint32) uint32 { - // riscv64:"SRL","AND","SLTIU" + // riscv64:"SRLI",-"AND",-"SLTIU" return v >> uint64(29) } func rshConst32x64(v int32) int32 { - // riscv64:"SRA","OR","SLTIU" + // riscv64:"SRAI",-"OR",-"SLTIU" return v >> uint64(29) } func lshConst64x32(v int64) int64 { - // riscv64:"SLL","AND","SLTIU" + // riscv64:"SLLI",-"AND",-"SLTIU" return v << uint32(33) } func rshConst64Ux32(v uint64) uint64 { - // riscv64:"SRL","AND","SLTIU" + // riscv64:"SRLI",-"AND",-"SLTIU" return v >> uint32(33) } func rshConst64x32(v int64) int64 { - // riscv64:"SRA","OR","SLTIU" + // riscv64:"SRAI",-"OR",-"SLTIU" return v >> uint32(33) } -- GitLab From 217507eb035933bac6c990844f0d71d6000fd339 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 22 Sep 2021 18:32:45 -0400 Subject: [PATCH 1295/2500] runtime: set vdsoSP to caller's SP consistently m.vdsoSP should be set to the SP of the caller of nanotime1, instead of the SP of nanotime1 itself, which matches m.vdsoPC. Otherwise the unmatched vdsoPC and vdsoSP would make the stack trace look like recursive. We already do it correctly on AMD64, 386, and RISCV64. This CL fixes the rest. Fixes #47324. Change-Id: I98b6fcfbe9fc6bdd28b8fe2a1299b7c505371dd4 Reviewed-on: https://go-review.googlesource.com/c/go/+/337590 Trust: Cherry Mui Trust: Josh Bleecher Snyder Reviewed-by: Josh Bleecher Snyder --- src/runtime/pprof/pprof_test.go | 30 ++++++++++++++++++++++++++++++ src/runtime/sys_linux_arm.s | 6 ++++-- src/runtime/sys_linux_arm64.s | 6 ++++-- src/runtime/sys_linux_mips64x.s | 6 ++++-- src/runtime/sys_linux_ppc64x.s | 8 +++++--- 5 files changed, 47 insertions(+), 9 deletions(-) diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go index e0d32a0f54..5b9ad50746 100644 --- a/src/runtime/pprof/pprof_test.go +++ b/src/runtime/pprof/pprof_test.go @@ -1544,3 +1544,33 @@ func TestTryAdd(t *testing.T) { }) } } + +func TestTimeVDSO(t *testing.T) { + // Test that time functions have the right stack trace. In particular, + // it shouldn't be recursive. + + p := testCPUProfile(t, stackContains, []string{"time.now"}, avoidFunctions(), func(dur time.Duration) { + t0 := time.Now() + for { + t := time.Now() + if t.Sub(t0) >= dur { + return + } + } + }) + + // Check for recursive time.now sample. + for _, sample := range p.Sample { + var seenNow bool + for _, loc := range sample.Location { + for _, line := range loc.Line { + if line.Function.Name == "time.now" { + if seenNow { + t.Fatalf("unexpected recursive time.now") + } + seenNow = true + } + } + } + } +} diff --git a/src/runtime/sys_linux_arm.s b/src/runtime/sys_linux_arm.s index 02a5d4a642..ae99810c10 100644 --- a/src/runtime/sys_linux_arm.s +++ b/src/runtime/sys_linux_arm.s @@ -259,8 +259,9 @@ TEXT runtime·walltime(SB),NOSPLIT,$8-12 MOVW R1, 4(R13) MOVW R2, 8(R13) + MOVW $ret-4(FP), R2 // caller's SP MOVW LR, m_vdsoPC(R5) - MOVW R13, m_vdsoSP(R5) + MOVW R2, m_vdsoSP(R5) MOVW m_curg(R5), R0 @@ -351,8 +352,9 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$8-8 MOVW R1, 4(R13) MOVW R2, 8(R13) + MOVW $ret-4(FP), R2 // caller's SP MOVW LR, m_vdsoPC(R5) - MOVW R13, m_vdsoSP(R5) + MOVW R2, m_vdsoSP(R5) MOVW m_curg(R5), R0 diff --git a/src/runtime/sys_linux_arm64.s b/src/runtime/sys_linux_arm64.s index 69ac160278..9289ad5028 100644 --- a/src/runtime/sys_linux_arm64.s +++ b/src/runtime/sys_linux_arm64.s @@ -221,8 +221,9 @@ TEXT runtime·walltime(SB),NOSPLIT,$24-12 MOVD R2, 8(RSP) MOVD R3, 16(RSP) + MOVD $ret-8(FP), R2 // caller's SP MOVD LR, m_vdsoPC(R21) - MOVD R20, m_vdsoSP(R21) + MOVD R2, m_vdsoSP(R21) MOVD m_curg(R21), R0 CMP g, R0 @@ -304,8 +305,9 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$24-8 MOVD R2, 8(RSP) MOVD R3, 16(RSP) + MOVD $ret-8(FP), R2 // caller's SP MOVD LR, m_vdsoPC(R21) - MOVD R20, m_vdsoSP(R21) + MOVD R2, m_vdsoSP(R21) MOVD m_curg(R21), R0 CMP g, R0 diff --git a/src/runtime/sys_linux_mips64x.s b/src/runtime/sys_linux_mips64x.s index e18d291445..7529a0ed27 100644 --- a/src/runtime/sys_linux_mips64x.s +++ b/src/runtime/sys_linux_mips64x.s @@ -229,8 +229,9 @@ TEXT runtime·walltime(SB),NOSPLIT,$16-12 MOVV R2, 8(R29) MOVV R3, 16(R29) + MOVV $ret-8(FP), R2 // caller's SP MOVV R31, m_vdsoPC(R17) - MOVV R29, m_vdsoSP(R17) + MOVV R2, m_vdsoSP(R17) MOVV m_curg(R17), R4 MOVV g, R5 @@ -298,8 +299,9 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$16-8 MOVV R2, 8(R29) MOVV R3, 16(R29) + MOVV $ret-8(FP), R2 // caller's SP MOVV R31, m_vdsoPC(R17) - MOVV R29, m_vdsoSP(R17) + MOVV R2, m_vdsoSP(R17) MOVV m_curg(R17), R4 MOVV g, R5 diff --git a/src/runtime/sys_linux_ppc64x.s b/src/runtime/sys_linux_ppc64x.s index 005fa4d2b4..33b6a9409c 100644 --- a/src/runtime/sys_linux_ppc64x.s +++ b/src/runtime/sys_linux_ppc64x.s @@ -205,8 +205,9 @@ TEXT runtime·walltime(SB),NOSPLIT,$16-12 MOVD R5, 40(R1) MOVD LR, R14 + MOVD $ret-FIXED_FRAME(FP), R5 // caller's SP MOVD R14, m_vdsoPC(R21) - MOVD R15, m_vdsoSP(R21) + MOVD R5, m_vdsoSP(R21) MOVD m_curg(R21), R6 CMP g, R6 @@ -297,9 +298,10 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$16-8 MOVD R4, 32(R1) MOVD R5, 40(R1) - MOVD LR, R14 // R14 is unchanged by C code + MOVD LR, R14 // R14 is unchanged by C code + MOVD $ret-FIXED_FRAME(FP), R5 // caller's SP MOVD R14, m_vdsoPC(R21) - MOVD R15, m_vdsoSP(R21) + MOVD R5, m_vdsoSP(R21) MOVD m_curg(R21), R6 CMP g, R6 -- GitLab From d5d3f80013fa9c4fda5ed2fd3d04868dd212ff8d Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 21 Sep 2021 13:54:58 -0700 Subject: [PATCH 1296/2500] cmd/go: adjust comments on why fuzzing instrumentation is disabled For #48504 Related #14565 Change-Id: Ibe43c75224525c4b80dbb66a1b6e0d688e47e2e4 Reviewed-on: https://go-review.googlesource.com/c/go/+/351314 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/cmd/go/internal/work/init.go | 18 ++++++++++++++++-- src/cmd/go/testdata/script/test_fuzz_cache.txt | 5 +++-- .../testdata/script/test_fuzz_seed_corpus.txt | 5 +++-- src/internal/fuzz/counters_unsupported.go | 4 +++- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/cmd/go/internal/work/init.go b/src/cmd/go/internal/work/init.go index 2a605e73ee..34d2e1cbe1 100644 --- a/src/cmd/go/internal/work/init.go +++ b/src/cmd/go/internal/work/init.go @@ -60,9 +60,23 @@ func BuildInit() { } } +// FuzzInstrumentFlags returns compiler flags that enable fuzzing instrumation +// on supported platforms. On unsupported platforms, FuzzInstrumentFlags returns +// nil. func FuzzInstrumentFlags() []string { - if cfg.Goarch != "amd64" && cfg.Goarch != "arm64" { - // Instrumentation is only supported on 64-bit architectures. + // TODO: expand the set of supported platforms, with testing. + // Nothing about the instrumentation is OS specific, but only amd64 and arm64 + // are supported in the runtime. See src/runtime/libfuzzer*. + // + // Keep in sync with build constraints in internal/fuzz/counters_{un,}supported.go + switch cfg.Goos { + case "darwin", "freebsd", "linux", "windows": + default: + return nil + } + switch cfg.Goarch { + case "amd64", "arm64": + default: return nil } return []string{"-d=libfuzzer"} diff --git a/src/cmd/go/testdata/script/test_fuzz_cache.txt b/src/cmd/go/testdata/script/test_fuzz_cache.txt index 8bcf2be61e..a3fcca887e 100644 --- a/src/cmd/go/testdata/script/test_fuzz_cache.txt +++ b/src/cmd/go/testdata/script/test_fuzz_cache.txt @@ -1,8 +1,9 @@ # TODO(jayconrod): support shared memory on more platforms. [!darwin] [!linux] [!windows] skip -# TODO(#48504): fix and re-enable. -[linux] [386] skip +# Instrumentation not supported on other archs. +# See #14565. +[!amd64] [!arm64] skip [short] skip env GOCACHE=$WORK/cache diff --git a/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt b/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt index f810ad48d9..a66d0554b6 100644 --- a/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt +++ b/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt @@ -1,8 +1,9 @@ # TODO(jayconrod): support shared memory on more platforms. [!darwin] [!linux] [!windows] skip -# TODO(#48504): fix and re-enable. -[linux] [386] skip +# Instrumentation not supported on other archs. +# See #14565. +[!amd64] [!arm64] skip [short] skip env GOCACHE=$WORK/cache diff --git a/src/internal/fuzz/counters_unsupported.go b/src/internal/fuzz/counters_unsupported.go index 743ef45a66..9595cb93f7 100644 --- a/src/internal/fuzz/counters_unsupported.go +++ b/src/internal/fuzz/counters_unsupported.go @@ -7,7 +7,9 @@ package fuzz // TODO(#48504): re-enable on platforms where instrumentation works. -// This was disabled due to an init failure on aix_ppc64. +// In theory, we shouldn't need this file at all: if the binary was built +// without coverage, then _counters and _ecounters should have the same address. +// However, this caused an init failure on aix/ppc64, so it's disabled here. // coverage returns a []byte containing unique 8-bit counters for each edge of // the instrumented source code. This coverage data will only be generated if -- GitLab From 584afc29289c2f1a204daa39f44a4a4afbacb741 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Wed, 22 Sep 2021 16:16:16 -0700 Subject: [PATCH 1297/2500] cmd/go: test that graph, verify, and why don't write go.mod or go.sum They should also not report an error if these files need to be updated. These commands are used for debugging, so it's important that they still work when go.mod and go.sum are incomplete. For #40775 Change-Id: I1b731599e5a4510f47827b9812525636a7402bf4 Reviewed-on: https://go-review.googlesource.com/c/go/+/351468 Trust: Jay Conrod Reviewed-by: Bryan C. Mills --- src/cmd/go/testdata/script/mod_skip_write.txt | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 src/cmd/go/testdata/script/mod_skip_write.txt diff --git a/src/cmd/go/testdata/script/mod_skip_write.txt b/src/cmd/go/testdata/script/mod_skip_write.txt new file mode 100644 index 0000000000..c3e5906589 --- /dev/null +++ b/src/cmd/go/testdata/script/mod_skip_write.txt @@ -0,0 +1,96 @@ +# Commands used to debug the module graph should not write go.mod or go.sum +# or report errors when those files need to be updated. + +# Everything's okay initially. +go list -m all + +# Downgrading sampler makes go.mod inconsistent, but 'go mod graph', +# 'go mod verify', and 'go mod why' still work. +cp go.mod go.mod.orig +go mod edit -require=rsc.io/sampler@v1.2.0 +cp go.mod go.mod.edit +! go list -m all +stderr 'updates to go.mod needed' + +go mod graph +cmp stdout graph.want +cmp go.mod go.mod.edit + +go mod verify +stdout '^all modules verified$' +cmp go.mod go.mod.edit + +go mod why rsc.io/sampler +cmp stdout why.want +cmp go.mod go.mod.edit + +# TODO(#48613): 'go mod why -m' incorrectly reports sampler is not needed. +go mod why -m rsc.io/sampler +cmp stdout why-broken.want +cmp go.mod go.mod.edit + +cp go.mod.orig go.mod + +# Removing go.sum breaks other commands, but 'go mod graph' and +# 'go mod why' still work. +rm go.sum +! go list -m all +stderr 'missing go.sum entry' + +go mod graph +cmp stdout graph.want +! exists go.sum + +go mod verify +stdout '^all modules verified$' +! exists go.sum + +go mod why rsc.io/sampler +cmp stdout why.want +! exists go.sum + +go mod why -m rsc.io/sampler +cmp stdout why.want +! exists go.sum + +-- go.mod -- +module m + +go 1.18 + +require rsc.io/quote v1.5.2 + +require ( + golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect + rsc.io/sampler v1.3.0 // indirect + rsc.io/testonly v1.0.0 // indirect +) +-- go.sum -- +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0= +rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/sampler v1.2.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64= +rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY= +-- use.go -- +package use + +import _ "rsc.io/quote" +-- graph.want -- +m golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c +m rsc.io/quote@v1.5.2 +m rsc.io/sampler@v1.3.0 +m rsc.io/testonly@v1.0.0 +rsc.io/quote@v1.5.2 rsc.io/sampler@v1.3.0 +rsc.io/sampler@v1.3.0 golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c +-- why.want -- +# rsc.io/sampler +m +rsc.io/quote +rsc.io/sampler +-- why-broken.want -- +# rsc.io/sampler +(main module does not need module rsc.io/sampler) -- GitLab From b00222fcdd9f2aeb426887b005865eca1aec3631 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Mon, 13 Sep 2021 16:48:53 -0700 Subject: [PATCH 1298/2500] cmd/go: refactor {Allow,Disallow}WriteGoMod to ExplicitWriteGoMod Subcommands may now set the global flag modload.ExplicitWriteGoMod instead of calling {Allow,Disallow}WriteGoMod. When ExplicitWriteGoMod is false (default), modload.LoadPackages and ListModules will either update go.mod and go.sum or report an error if they need to be updated, depending on cfg.BuildMod. When ExplicitWriteGoMod is true, commands must explicitly call modload.WriteGoMod to update go.mod and go.sum or report an error. Commands that perform some operation after loading the build list (like downloading zips or building packages) and commands that load packages multiple times should set this. For now, only 'go get' and 'go mod download' set this. This CL is a pure refactor: no change in behavior is expected. There are some other minor changes in here, too: commitRequirements no longer sets the global requirements: that should be done separately first. Change-Id: I69942a808bb177faf7904a53aaf2d4ac68500e82 Reviewed-on: https://go-review.googlesource.com/c/go/+/349600 Trust: Jay Conrod Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/modcmd/download.go | 22 ++-- src/cmd/go/internal/modcmd/why.go | 1 + src/cmd/go/internal/modget/get.go | 8 +- src/cmd/go/internal/modload/buildlist.go | 5 +- src/cmd/go/internal/modload/init.go | 130 ++++++++++------------- src/cmd/go/internal/modload/list.go | 5 +- src/cmd/go/internal/modload/load.go | 18 +++- 7 files changed, 96 insertions(+), 93 deletions(-) diff --git a/src/cmd/go/internal/modcmd/download.go b/src/cmd/go/internal/modcmd/download.go index 0f64785656..5ea56c34bd 100644 --- a/src/cmd/go/internal/modcmd/download.go +++ b/src/cmd/go/internal/modcmd/download.go @@ -86,6 +86,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { // Check whether modules are enabled and whether we're in a module. modload.ForceUseModules = true + modload.ExplicitWriteGoMod = true if !modload.HasModRoot() && len(args) == 0 { base.Fatalf("go: no modules specified (see 'go help mod download')") } @@ -149,13 +150,16 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { if !haveExplicitArgs { // 'go mod download' is sometimes run without arguments to pre-populate the // module cache. It may fetch modules that aren't needed to build packages - // in the main mdoule. This is usually not intended, so don't save sums for - // downloaded modules (golang.org/issue/45332). - // TODO(golang.org/issue/45551): For now, in ListModules, save sums needed - // to load the build list (same as 1.15 behavior). In the future, report an - // error if go.mod or go.sum need to be updated after loading the build - // list. - modload.DisallowWriteGoMod() + // in the main module. This is usually not intended, so don't save sums for + // downloaded modules (golang.org/issue/45332). We do still fix + // inconsistencies in go.mod though. + // + // TODO(#45551): In the future, report an error if go.mod or go.sum need to + // be updated after loading the build list. This may require setting + // the mode to "mod" or "readonly" depending on haveExplicitArgs. + if err := modload.WriteGoMod(ctx); err != nil { + base.Fatalf("go: %v", err) + } } for _, info := range infos { @@ -215,7 +219,9 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { // // Don't save sums for 'go mod download' without arguments; see comment above. if haveExplicitArgs { - modload.WriteGoMod(ctx) + if err := modload.WriteGoMod(ctx); err != nil { + base.Errorf("go: %v", err) + } } // If there was an error matching some of the requested packages, emit it now diff --git a/src/cmd/go/internal/modcmd/why.go b/src/cmd/go/internal/modcmd/why.go index ed5e9d7f1a..9647784b67 100644 --- a/src/cmd/go/internal/modcmd/why.go +++ b/src/cmd/go/internal/modcmd/why.go @@ -68,6 +68,7 @@ func runWhy(ctx context.Context, cmd *base.Command, args []string) { modload.InitWorkfile() modload.ForceUseModules = true modload.RootMode = modload.NeedRoot + modload.ExplicitWriteGoMod = true // don't write go.mod in ListModules loadOpts := modload.PackageOpts{ Tags: imports.AnyTags(), diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index db07624e38..20734bdd23 100644 --- a/src/cmd/go/internal/modget/get.go +++ b/src/cmd/go/internal/modget/get.go @@ -281,7 +281,7 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { // Do not allow any updating of go.mod until we've applied // all the requested changes and checked that the result matches // what was requested. - modload.DisallowWriteGoMod() + modload.ExplicitWriteGoMod = true // Allow looking up modules for import paths when outside of a module. // 'go get' is expected to do this, unlike other commands. @@ -423,9 +423,9 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { // Everything succeeded. Update go.mod. oldReqs := reqsFromGoMod(modload.ModFile()) - modload.AllowWriteGoMod() - modload.WriteGoMod(ctx) - modload.DisallowWriteGoMod() + if err := modload.WriteGoMod(ctx); err != nil { + base.Fatalf("go: %v", err) + } newReqs := reqsFromGoMod(modload.ModFile()) r.reportChanges(oldReqs, newReqs) diff --git a/src/cmd/go/internal/modload/buildlist.go b/src/cmd/go/internal/modload/buildlist.go index da9e6406b1..4634ad009d 100644 --- a/src/cmd/go/internal/modload/buildlist.go +++ b/src/cmd/go/internal/modload/buildlist.go @@ -469,7 +469,8 @@ func LoadModGraph(ctx context.Context, goVersion string) *ModuleGraph { base.Fatalf("go: %v", err) } - commitRequirements(ctx, rs) + requirements = rs + return mg } @@ -534,7 +535,7 @@ func EditBuildList(ctx context.Context, add, mustSelect []module.Version) (chang if err != nil { return false, err } - commitRequirements(ctx, rs) + requirements = rs return changed, err } diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 83414feb3c..621099beb3 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -44,6 +44,16 @@ var ( ForceUseModules bool allowMissingModuleImports bool + + // ExplicitWriteGoMod prevents LoadPackages, ListModules, and other functions + // from updating go.mod and go.sum or reporting errors when updates are + // needed. A package should set this if it would cause go.mod to be written + // multiple times (for example, 'go get' calls LoadPackages multiple times) or + // if it needs some other operation to be successful before go.mod and go.sum + // can be written (for example, 'go mod download' must download modules before + // adding sums to go.sum). Packages that set this are responsible for calling + // WriteGoMod explicitly. + ExplicitWriteGoMod bool ) func TODOWorkspaces(s string) error { @@ -591,8 +601,9 @@ func loadWorkFile(path string) (goVersion string, modRoots []string, err error) // build list from its go.mod file. // // LoadModFile may make changes in memory, like adding a go directive and -// ensuring requirements are consistent, and will write those changes back to -// disk unless DisallowWriteGoMod is in effect. +// ensuring requirements are consistent. The caller is responsible for ensuring +// those changes are written to disk by calling LoadPackages or ListModules +// (unless ExplicitWriteGoMod is set) or by calling WriteGoMod directly. // // As a side-effect, LoadModFile may change cfg.BuildMod to "vendor" if // -mod wasn't set explicitly and automatic vendoring should be enabled. @@ -605,22 +616,8 @@ func loadWorkFile(path string) (goVersion string, modRoots []string, err error) // it for global consistency. Most callers outside of the modload package should // use LoadModGraph instead. func LoadModFile(ctx context.Context) *Requirements { - rs, needCommit := loadModFile(ctx) - if needCommit { - commitRequirements(ctx, rs) - } - return rs -} - -// loadModFile is like LoadModFile, but does not implicitly commit the -// requirements back to disk after fixing inconsistencies. -// -// If needCommit is true, after the caller makes any other needed changes to the -// returned requirements they should invoke commitRequirements to fix any -// inconsistencies that may be present in the on-disk go.mod file. -func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { if requirements != nil { - return requirements, false + return requirements } Init() @@ -631,7 +628,7 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { goVersion := LatestGoVersion() rawGoVersion.Store(mainModule, goVersion) requirements = newRequirements(pruningForGoVersion(goVersion), nil, nil) - return requirements, false + return requirements } var modFiles []*modfile.File @@ -660,13 +657,13 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { MainModules = makeMainModules(mainModules, modRoots, modFiles, indices, workFileGoVersion) setDefaultBuildMod() // possibly enable automatic vendoring - rs = requirementsFromModFiles(ctx, modFiles) + rs := requirementsFromModFiles(ctx, modFiles) if inWorkspaceMode() { // We don't need to do anything for vendor or update the mod file so // return early. - - return rs, true + requirements = rs + return rs } mainModule := MainModules.mustGetSingleMainModule() @@ -712,7 +709,7 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { } requirements = rs - return requirements, true + return requirements } // CreateModFile initializes a new module by creating a go.mod file. @@ -777,7 +774,10 @@ func CreateModFile(ctx context.Context, modPath string) { if err != nil { base.Fatalf("go: %v", err) } - commitRequirements(ctx, rs) + requirements = rs + if err := commitRequirements(ctx); err != nil { + base.Fatalf("go: %v", err) + } // Suggest running 'go mod tidy' unless the project is empty. Even if we // imported all the correct requirements above, we're probably missing @@ -1003,7 +1003,6 @@ func setDefaultBuildMod() { // go.mod is inconsistent. They're useful for debugging, and they need // to work in buggy situations. cfg.BuildMod = "mod" - allowWriteGoMod = false return case "mod vendor": cfg.BuildMod = "readonly" @@ -1309,62 +1308,44 @@ func findImportComment(file string) string { return path } -var allowWriteGoMod = true - -// DisallowWriteGoMod causes future calls to WriteGoMod to do nothing at all. -func DisallowWriteGoMod() { - allowWriteGoMod = false -} - -// AllowWriteGoMod undoes the effect of DisallowWriteGoMod: -// future calls to WriteGoMod will update go.mod if needed. -// Note that any past calls have been discarded, so typically -// a call to AlowWriteGoMod should be followed by a call to WriteGoMod. -func AllowWriteGoMod() { - allowWriteGoMod = true -} - // WriteGoMod writes the current build list back to go.mod. -func WriteGoMod(ctx context.Context) { - if !allowWriteGoMod { - panic("WriteGoMod called while disallowed") - } - commitRequirements(ctx, LoadModFile(ctx)) +func WriteGoMod(ctx context.Context) error { + requirements = LoadModFile(ctx) + return commitRequirements(ctx) } -// commitRequirements writes sets the global requirements variable to rs and -// writes its contents back to the go.mod file on disk. -// goVersion, if non-empty, is used to set the version on the go.mod file. -func commitRequirements(ctx context.Context, rs *Requirements) { - requirements = rs - - if !allowWriteGoMod { - // Some package outside of modload promised to update the go.mod file later. - return - } - +// commitRequirements ensures go.mod and go.sum are up to date with the current +// requirements. +// +// In "mod" mode, commitRequirements writes changes to go.mod and go.sum. +// +// In "readonly" and "vendor" modes, commitRequirements returns an error if +// go.mod or go.sum are out of date in a semantically significant way. +// +// In workspace mode, commitRequirements only writes changes to go.work.sum. +func commitRequirements(ctx context.Context) (err error) { if inWorkspaceMode() { // go.mod files aren't updated in workspace mode, but we still want to // update the go.work.sum file. - if err := modfetch.WriteGoSum(keepSums(ctx, loaded, rs, addBuildListZipSums), mustHaveCompleteRequirements()); err != nil { - base.Fatalf("go: %v", err) - } - return + return modfetch.WriteGoSum(keepSums(ctx, loaded, requirements, addBuildListZipSums), mustHaveCompleteRequirements()) } - if MainModules.Len() != 1 || MainModules.ModRoot(MainModules.Versions()[0]) == "" { // We aren't in a module, so we don't have anywhere to write a go.mod file. - return + return nil } mainModule := MainModules.mustGetSingleMainModule() - modFilePath := modFilePath(MainModules.ModRoot(mainModule)) modFile := MainModules.ModFile(mainModule) + if modFile == nil { + // command-line-arguments has no .mod file to write. + return nil + } + modFilePath := modFilePath(MainModules.ModRoot(mainModule)) var list []*modfile.Require - for _, m := range rs.rootModules { + for _, m := range requirements.rootModules { list = append(list, &modfile.Require{ Mod: m, - Indirect: !rs.direct[m.Path], + Indirect: !requirements.direct[m.Path], }) } if modFile.Go == nil || modFile.Go.Version == "" { @@ -1382,7 +1363,7 @@ func commitRequirements(ctx context.Context, rs *Requirements) { if dirty && cfg.BuildMod != "mod" { // If we're about to fail due to -mod=readonly, // prefer to report a dirty go.mod over a dirty go.sum - base.Fatalf("go: %v", errGoModDirty) + return errGoModDirty } if !dirty && cfg.CmdName != "mod tidy" { @@ -1391,22 +1372,22 @@ func commitRequirements(ctx context.Context, rs *Requirements) { // Don't write go.mod, but write go.sum in case we added or trimmed sums. // 'go mod init' shouldn't write go.sum, since it will be incomplete. if cfg.CmdName != "mod init" { - if err := modfetch.WriteGoSum(keepSums(ctx, loaded, rs, addBuildListZipSums), mustHaveCompleteRequirements()); err != nil { - base.Fatalf("go: %v", err) + if err := modfetch.WriteGoSum(keepSums(ctx, loaded, requirements, addBuildListZipSums), mustHaveCompleteRequirements()); err != nil { + return err } } - return + return nil } if _, ok := fsys.OverlayPath(modFilePath); ok { if dirty { - base.Fatalf("go: updates to go.mod needed, but go.mod is part of the overlay specified with -overlay") + return errors.New("updates to go.mod needed, but go.mod is part of the overlay specified with -overlay") } - return + return nil } new, err := modFile.Format() if err != nil { - base.Fatalf("go: %v", err) + return err } defer func() { // At this point we have determined to make the go.mod file on disk equal to new. @@ -1415,8 +1396,8 @@ func commitRequirements(ctx context.Context, rs *Requirements) { // Update go.sum after releasing the side lock and refreshing the index. // 'go mod init' shouldn't write go.sum, since it will be incomplete. if cfg.CmdName != "mod init" { - if err := modfetch.WriteGoSum(keepSums(ctx, loaded, rs, addBuildListZipSums), mustHaveCompleteRequirements()); err != nil { - base.Fatalf("go: %v", err) + if err == nil { + err = modfetch.WriteGoSum(keepSums(ctx, loaded, requirements, addBuildListZipSums), mustHaveCompleteRequirements()) } } }() @@ -1450,8 +1431,9 @@ func commitRequirements(ctx context.Context, rs *Requirements) { }) if err != nil && err != errNoChange { - base.Fatalf("go: updating go.mod: %v", err) + return fmt.Errorf("updating go.mod: %w", err) } + return nil } // keepSums returns the set of modules (and go.mod file entries) for which diff --git a/src/cmd/go/internal/modload/list.go b/src/cmd/go/internal/modload/list.go index ac10a42c5a..f782cd93db 100644 --- a/src/cmd/go/internal/modload/list.go +++ b/src/cmd/go/internal/modload/list.go @@ -72,7 +72,10 @@ func ListModules(ctx context.Context, args []string, mode ListMode) ([]*modinfo. } if err == nil { - commitRequirements(ctx, rs) + requirements = rs + if !ExplicitWriteGoMod { + err = commitRequirements(ctx) + } } return mods, err } diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index 48f268ce5f..3498c662f3 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -327,7 +327,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma } } - initialRS, _ := loadModFile(ctx) // Ignore needCommit — we're going to commit at the end regardless. + initialRS := LoadModFile(ctx) ld := loadFromRoots(ctx, loaderParams{ PackageOpts: opts, @@ -396,7 +396,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma } } - if allowWriteGoMod { + if !ExplicitWriteGoMod { modfetch.TrimGoSum(keep) // commitRequirements below will also call WriteGoSum, but the "keep" map @@ -417,8 +417,11 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma } // Success! Update go.mod and go.sum (if needed) and return the results. + // We'll skip updating if ExplicitWriteGoMod is true (the caller has opted + // to call WriteGoMod itself) or if ResolveMissingImports is false (the + // command wants to examine the package graph as-is). loaded = ld - commitRequirements(ctx, loaded.requirements) + requirements = loaded.requirements for _, pkg := range ld.pkgs { if !pkg.isTest() { @@ -426,6 +429,13 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma } } sort.Strings(loadedPackages) + + if !ExplicitWriteGoMod && opts.ResolveMissingImports { + if err := commitRequirements(ctx); err != nil { + base.Fatalf("go: %v", err) + } + } + return matches, loadedPackages } @@ -685,7 +695,7 @@ func ImportFromFiles(ctx context.Context, gofiles []string) { return roots }, }) - commitRequirements(ctx, loaded.requirements) + requirements = loaded.requirements } // DirImportPath returns the effective import path for dir, -- GitLab From 812c99f86a1b38d50c5c0b501d10b72c3b7dfb95 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Fri, 24 Sep 2021 09:13:32 -0700 Subject: [PATCH 1299/2500] cmd/compile: fix case in dictPass where OMETHVALUE should become ODOTMETH When I separate out the dictionary transformations to dictPass, I missed duplicating a conditional that deals with OMETHVALUE nodes that are actually called. We create the OMETHVALUE when transforming bounds function reference (before we know whether that reference will be called), and we need to call transformDot() again to convert the OMETHVALUE to ODOTMETH if the reference is actually called (the usual case). Without this change, we leave the OMETHVALUE in, and extra *-fm are created and used unncessarily. Also, fixed a few places where we were missing ir.MarkFunc(), which sets the class of a function node properly. Change-Id: I6b02613039b16b507b44525faa2cd7031afb6982 Reviewed-on: https://go-review.googlesource.com/c/go/+/352069 Trust: Dan Scales Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 6 ++++++ src/cmd/compile/internal/typecheck/iimport.go | 1 + src/cmd/compile/internal/typecheck/subr.go | 1 + 3 files changed, 8 insertions(+) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index c8ce230121..cf8641d60e 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1220,6 +1220,12 @@ func (g *irgen) dictPass(info *instInfo) { op := m.(*ir.CallExpr).X.Op() if op != ir.OFUNCINST { assert(op == ir.OMETHVALUE || op == ir.OCLOSURE || op == ir.ODYNAMICDOTTYPE || op == ir.ODYNAMICDOTTYPE2) + if op == ir.OMETHVALUE { + // Redo the transformation of OXDOT, now that we + // know the method value is being called. + m.(*ir.CallExpr).X.(*ir.SelectorExpr).SetOp(ir.OXDOT) + transformDot(m.(*ir.CallExpr).X.(*ir.SelectorExpr), true) + } transformCall(m.(*ir.CallExpr)) } diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 57f0dd8566..9bd8e35a13 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1902,6 +1902,7 @@ func substInstType(t *types.Type, baseType *types.Type, targs []*types.Type) { } else { nname = ir.NewNameAt(f.Pos, newsym) nname.SetType(t2) + ir.MarkFunc(nname) newsym.Def = nname } newfields[i] = types.NewField(f.Pos, f.Sym, t2) diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 9233bbe6f2..fbfe1b3720 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1269,6 +1269,7 @@ func (ts *Tsubster) typ1(t *types.Type) *types.Type { } else { nname = ir.NewNameAt(f.Pos, newsym) nname.SetType(t2) + ir.MarkFunc(nname) newsym.Def = nname } newfields[i] = types.NewField(f.Pos, f.Sym, t2) -- GitLab From f6b5ffb5e1d31fd24edadfe6c105886093638825 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sat, 18 Sep 2021 20:02:08 -0700 Subject: [PATCH 1300/2500] cmd/compile: fix crawler for unexported fields with instantiated types In markType() in crawler.go, mark the type of a unexported field if it is a fully-instantiated type, since we create and instantiate the methods of any fully-instantiated type that we see during import. As before, we still do not mark the type of an unexported field if that type is not generic. Fixes #48454 and most recent issue described in 48337. The included test is similar to the case in 48454. Fixes #48454 Fixes #48337 Change-Id: I77a2a62b9e2647876facfa6f004201e8f699c905 Reviewed-on: https://go-review.googlesource.com/c/go/+/351315 Trust: Dan Scales Reviewed-by: Cuong Manh Le Reviewed-by: Keith Randall --- src/cmd/compile/internal/typecheck/crawler.go | 28 +++++++++++++------ test/typeparam/issue48454.dir/a.go | 16 +++++++++++ test/typeparam/issue48454.dir/b.go | 11 ++++++++ test/typeparam/issue48454.dir/main.go | 11 ++++++++ test/typeparam/issue48454.go | 7 +++++ 5 files changed, 65 insertions(+), 8 deletions(-) create mode 100644 test/typeparam/issue48454.dir/a.go create mode 100644 test/typeparam/issue48454.dir/b.go create mode 100644 test/typeparam/issue48454.dir/main.go create mode 100644 test/typeparam/issue48454.go diff --git a/src/cmd/compile/internal/typecheck/crawler.go b/src/cmd/compile/internal/typecheck/crawler.go index 3f212aa805..667e76e130 100644 --- a/src/cmd/compile/internal/typecheck/crawler.go +++ b/src/cmd/compile/internal/typecheck/crawler.go @@ -10,10 +10,12 @@ import ( "cmd/compile/internal/types" ) -// crawlExports crawls the type/object graph rooted at the given list -// of exported objects. Any functions that are found to be potentially -// callable by importers are marked with ExportInline so that -// iexport.go knows to re-export their inline body. +// crawlExports crawls the type/object graph rooted at the given list of exported +// objects. It descends through all parts of types and follows any methods on defined +// types. Any functions that are found to be potentially callable by importers are +// marked with ExportInline, so that iexport.go knows to re-export their inline body. +// Also, any function or global referenced by a function marked by ExportInline() is +// marked for export (whether its name is exported or not). func crawlExports(exports []*ir.Name) { p := crawler{ marked: make(map[*types.Type]bool), @@ -29,7 +31,7 @@ type crawler struct { embedded map[*types.Type]bool // types already seen by markEmbed } -// markObject visits a reachable object. +// markObject visits a reachable object (function, method, global type, or global variable) func (p *crawler) markObject(n *ir.Name) { if n.Op() == ir.ONAME && n.Class == ir.PFUNC { p.markInlBody(n) @@ -97,7 +99,12 @@ func (p *crawler) markType(t *types.Type) { break } for _, f := range t.FieldSlice() { - if types.IsExported(f.Sym.Name) || f.Embedded != 0 { + // Mark the type of a unexported field if it is a + // fully-instantiated type, since we create and instantiate + // the methods of any fully-instantiated type that we see + // during import (see end of typecheck.substInstType). + if types.IsExported(f.Sym.Name) || f.Embedded != 0 || + isPtrFullyInstantiated(f.Type) { p.markType(f.Type) } } @@ -108,8 +115,6 @@ func (p *crawler) markType(t *types.Type) { } case types.TINTER: - // TODO(danscales) - will have to deal with the types in interface - // elements here when implemented in types2 and represented in types1. for _, f := range t.AllMethods().Slice() { if types.IsExported(f.Sym.Name) { p.markType(f.Type) @@ -226,3 +231,10 @@ func (p *crawler) markInlBody(n *ir.Name) { // because after inlining they might be callable. ir.VisitList(fn.Inl.Body, doFlood) } + +// isPtrFullyInstantiated returns true if t is a fully-instantiated type, or it is a +// pointer to a fully-instantiated type. +func isPtrFullyInstantiated(t *types.Type) bool { + return t.IsPtr() && t.Elem().IsFullyInstantiated() || + t.IsFullyInstantiated() +} diff --git a/test/typeparam/issue48454.dir/a.go b/test/typeparam/issue48454.dir/a.go new file mode 100644 index 0000000000..9613916a4c --- /dev/null +++ b/test/typeparam/issue48454.dir/a.go @@ -0,0 +1,16 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +import "sync" + +type Val[T any] struct { + mu sync.RWMutex + val T +} + +func (v *Val[T]) Has() { + v.mu.RLock() +} diff --git a/test/typeparam/issue48454.dir/b.go b/test/typeparam/issue48454.dir/b.go new file mode 100644 index 0000000000..2b59b714b8 --- /dev/null +++ b/test/typeparam/issue48454.dir/b.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package b + +import "a" + +type Session struct { + privateField a.Val[string] +} diff --git a/test/typeparam/issue48454.dir/main.go b/test/typeparam/issue48454.dir/main.go new file mode 100644 index 0000000000..becb5f3024 --- /dev/null +++ b/test/typeparam/issue48454.dir/main.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "b" + +func main() { + var _ b.Session +} diff --git a/test/typeparam/issue48454.go b/test/typeparam/issue48454.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/issue48454.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From c94543b85fe6f41dc3bc1725f928c6ed98d8d72c Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Fri, 24 Sep 2021 23:02:08 +0700 Subject: [PATCH 1301/2500] cmd/compile: move all usage of delayTransform out of helpers.go So next CL will make delayTransform to become irgen's method, because the delay transform logic also depends on irgen.topFuncIsGeneric field. For #48609 Change-Id: I660ed19856bd06c3b6f4279a9184db96175dea2d Reviewed-on: https://go-review.googlesource.com/c/go/+/351854 Trust: Cuong Manh Le Trust: Dan Scales Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/expr.go | 29 +++++++++++++++++++--- src/cmd/compile/internal/noder/helpers.go | 30 ++++++----------------- 2 files changed, 33 insertions(+), 26 deletions(-) diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 9cd9545b75..1f40503302 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -167,7 +167,12 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { index := g.expr(expr.Index) if index.Op() != ir.OTYPE { // This is just a normal index expression - return Index(pos, g.typ(typ), g.expr(expr.X), index) + n := Index(pos, g.typ(typ), g.expr(expr.X), index) + if !delayTransform() { + // transformIndex will modify n.Type() for OINDEXMAP. + transformIndex(n) + } + return n } // This is generic function instantiation with a single type targs = []ir.Node{index} @@ -200,7 +205,11 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { return g.selectorExpr(pos, typ, expr) case *syntax.SliceExpr: - return Slice(pos, g.typ(typ), g.expr(expr.X), g.expr(expr.Index[0]), g.expr(expr.Index[1]), g.expr(expr.Index[2])) + n := Slice(pos, g.typ(typ), g.expr(expr.X), g.expr(expr.Index[0]), g.expr(expr.Index[1]), g.expr(expr.Index[2])) + if !delayTransform() { + transformSlice(n) + } + return n case *syntax.Operation: if expr.Y == nil { @@ -208,9 +217,21 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { } switch op := g.op(expr.Op, binOps[:]); op { case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE: - return Compare(pos, g.typ(typ), op, g.expr(expr.X), g.expr(expr.Y)) + n := Compare(pos, g.typ(typ), op, g.expr(expr.X), g.expr(expr.Y)) + if !delayTransform() { + transformCompare(n) + } + return n + case ir.OANDAND, ir.OOROR: + x := g.expr(expr.X) + y := g.expr(expr.Y) + return typed(x.Type(), ir.NewLogicalExpr(pos, op, x, y)) default: - return Binary(pos, op, g.typ(typ), g.expr(expr.X), g.expr(expr.Y)) + n := Binary(pos, op, g.typ(typ), g.expr(expr.X), g.expr(expr.Y)) + if op == ir.OADD && !delayTransform() { + return transformAdd(n) + } + return n } default: diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index 636b5d64cd..aecda86e9d 100644 --- a/src/cmd/compile/internal/noder/helpers.go +++ b/src/cmd/compile/internal/noder/helpers.go @@ -89,20 +89,16 @@ func Assert(pos src.XPos, x ir.Node, typ *types.Type) ir.Node { return typed(typ, ir.NewTypeAssertExpr(pos, x, nil)) } -func Binary(pos src.XPos, op ir.Op, typ *types.Type, x, y ir.Node) ir.Node { +func Binary(pos src.XPos, op ir.Op, typ *types.Type, x, y ir.Node) *ir.BinaryExpr { switch op { - case ir.OANDAND, ir.OOROR: - return typed(x.Type(), ir.NewLogicalExpr(pos, op, x, y)) case ir.OADD: n := ir.NewBinaryExpr(pos, op, x, y) typed(typ, n) - r := ir.Node(n) - if !delayTransform() { - r = transformAdd(n) - } - return r + return n default: - return typed(x.Type(), ir.NewBinaryExpr(pos, op, x, y)) + n := ir.NewBinaryExpr(pos, op, x, y) + typed(x.Type(), n) + return n } } @@ -195,12 +191,9 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) return n } -func Compare(pos src.XPos, typ *types.Type, op ir.Op, x, y ir.Node) ir.Node { +func Compare(pos src.XPos, typ *types.Type, op ir.Op, x, y ir.Node) *ir.BinaryExpr { n := ir.NewBinaryExpr(pos, op, x, y) typed(typ, n) - if !delayTransform() { - transformCompare(n) - } return n } @@ -270,26 +263,19 @@ func method(typ *types.Type, index int) *types.Field { return types.ReceiverBaseType(typ).Methods().Index(index) } -func Index(pos src.XPos, typ *types.Type, x, index ir.Node) ir.Node { +func Index(pos src.XPos, typ *types.Type, x, index ir.Node) *ir.IndexExpr { n := ir.NewIndexExpr(pos, x, index) typed(typ, n) - if !delayTransform() { - // transformIndex will modify n.Type() for OINDEXMAP. - transformIndex(n) - } return n } -func Slice(pos src.XPos, typ *types.Type, x, low, high, max ir.Node) ir.Node { +func Slice(pos src.XPos, typ *types.Type, x, low, high, max ir.Node) *ir.SliceExpr { op := ir.OSLICE if max != nil { op = ir.OSLICE3 } n := ir.NewSliceExpr(pos, op, x, low, high, max) typed(typ, n) - if !delayTransform() { - transformSlice(n) - } return n } -- GitLab From cfd0868fc3252e349b11066ed300c389d4495587 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Fri, 24 Sep 2021 23:11:18 +0700 Subject: [PATCH 1302/2500] cmd/compile: fix delayTransform condition The delayTransform only checks whether ir.CurFunc is generic function or not. but when compiling a non-generic closure inside a generic function, we also want to delay the transformation, which delayTransform fails to detect, since when ir.CurFunc is the closure, not the top level function. Instead, we must rely on irgen.topFuncIsGeneric field to decide whether to delay the transformation, the same logic with what is being done for not adding closure inside a generic function to g.target.Decls list. Fixes #48609 Change-Id: I5bf5592027d112fe8b19c92eb906add424c46507 Reviewed-on: https://go-review.googlesource.com/c/go/+/351855 Trust: Cuong Manh Le Trust: Dan Scales Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/expr.go | 8 ++++---- src/cmd/compile/internal/noder/helpers.go | 6 ------ src/cmd/compile/internal/noder/irgen.go | 6 ++++++ src/cmd/compile/internal/noder/stmt.go | 12 ++++++------ test/typeparam/issue48609.go | 18 ++++++++++++++++++ 5 files changed, 34 insertions(+), 16 deletions(-) create mode 100644 test/typeparam/issue48609.go diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 1f40503302..9852ad964c 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -168,7 +168,7 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { if index.Op() != ir.OTYPE { // This is just a normal index expression n := Index(pos, g.typ(typ), g.expr(expr.X), index) - if !delayTransform() { + if !g.delayTransform() { // transformIndex will modify n.Type() for OINDEXMAP. transformIndex(n) } @@ -206,7 +206,7 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { case *syntax.SliceExpr: n := Slice(pos, g.typ(typ), g.expr(expr.X), g.expr(expr.Index[0]), g.expr(expr.Index[1]), g.expr(expr.Index[2])) - if !delayTransform() { + if !g.delayTransform() { transformSlice(n) } return n @@ -218,7 +218,7 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { switch op := g.op(expr.Op, binOps[:]); op { case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE: n := Compare(pos, g.typ(typ), op, g.expr(expr.X), g.expr(expr.Y)) - if !delayTransform() { + if !g.delayTransform() { transformCompare(n) } return n @@ -228,7 +228,7 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { return typed(x.Type(), ir.NewLogicalExpr(pos, op, x, y)) default: n := Binary(pos, op, g.typ(typ), g.expr(expr.X), g.expr(expr.Y)) - if op == ir.OADD && !delayTransform() { + if op == ir.OADD && !g.delayTransform() { return transformAdd(n) } return n diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index aecda86e9d..e8a1540307 100644 --- a/src/cmd/compile/internal/noder/helpers.go +++ b/src/cmd/compile/internal/noder/helpers.go @@ -317,9 +317,3 @@ func IncDec(pos src.XPos, op ir.Op, x ir.Node) *ir.AssignOpStmt { } return ir.NewAssignOpStmt(pos, op, x, bl) } - -// delayTransform returns true if we should delay all transforms, because we are -// creating the nodes for a generic function/method. -func delayTransform() bool { - return ir.CurFunc != nil && ir.CurFunc.Type().HasTParam() -} diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index 4f1b4e6bfd..e01e753a1d 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -319,3 +319,9 @@ func (g *irgen) unhandled(what string, p poser) { base.FatalfAt(g.pos(p), "unhandled %s: %T", what, p) panic("unreachable") } + +// delayTransform returns true if we should delay all transforms, because we are +// creating the nodes for a generic function/method. +func (g *irgen) delayTransform() bool { + return g.topFuncIsGeneric +} diff --git a/src/cmd/compile/internal/noder/stmt.go b/src/cmd/compile/internal/noder/stmt.go index 805a4710c4..aedb09e21e 100644 --- a/src/cmd/compile/internal/noder/stmt.go +++ b/src/cmd/compile/internal/noder/stmt.go @@ -40,7 +40,7 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { return wrapname(g.pos(stmt.X), g.expr(stmt.X)) case *syntax.SendStmt: n := ir.NewSendStmt(g.pos(stmt), g.expr(stmt.Chan), g.expr(stmt.Value)) - if !delayTransform() { + if !g.delayTransform() { transformSend(n) } n.SetTypecheck(1) @@ -62,7 +62,7 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { lhs := g.expr(stmt.Lhs) n = ir.NewAssignOpStmt(g.pos(stmt), op, lhs, rhs) } - if !delayTransform() { + if !g.delayTransform() { transformAsOp(n) } n.SetTypecheck(1) @@ -77,7 +77,7 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { n := ir.NewAssignStmt(g.pos(stmt), lhs[0], rhs[0]) n.Def = initDefn(n, names) - if !delayTransform() { + if !g.delayTransform() { lhs, rhs := []ir.Node{n.X}, []ir.Node{n.Y} transformAssign(n, lhs, rhs) n.X, n.Y = lhs[0], rhs[0] @@ -88,7 +88,7 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { n := ir.NewAssignListStmt(g.pos(stmt), ir.OAS2, lhs, rhs) n.Def = initDefn(n, names) - if !delayTransform() { + if !g.delayTransform() { transformAssign(n, n.Lhs, n.Rhs) } n.SetTypecheck(1) @@ -100,7 +100,7 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { return ir.NewGoDeferStmt(g.pos(stmt), g.tokOp(int(stmt.Tok), callOps[:]), g.expr(stmt.Call)) case *syntax.ReturnStmt: n := ir.NewReturnStmt(g.pos(stmt), g.exprList(stmt.Results)) - if !delayTransform() { + if !g.delayTransform() { transformReturn(n) } n.SetTypecheck(1) @@ -112,7 +112,7 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { case *syntax.SelectStmt: n := g.selectStmt(stmt) - if !delayTransform() { + if !g.delayTransform() { transformSelect(n.(*ir.SelectStmt)) } n.SetTypecheck(1) diff --git a/test/typeparam/issue48609.go b/test/typeparam/issue48609.go new file mode 100644 index 0000000000..3ca9d6e7d6 --- /dev/null +++ b/test/typeparam/issue48609.go @@ -0,0 +1,18 @@ +// compile -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +import "constraints" + +func f[T constraints.Chan[E], E any](e E) T { + ch := make(T) + go func() { + defer close(ch) + ch <- e + }() + return ch +} -- GitLab From 7e4fb8b3ef9774e58f90359f51e89ac5103d388d Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Fri, 24 Sep 2021 10:46:09 -0700 Subject: [PATCH 1303/2500] cmd/go: make 'go mod why -m' work in inconsistent, pruned module 'go mod why -m' works by listing modules matching command line arguments, then loading "all" packages and finding which of the listed modules provide packages imported by the main module. If go.mod is inconsistent (that is, a requirement has a lower version than MVS would select when the module graph is loaded) and pruned (that is, the module graph is only loaded when necessary), then modload.ListModules may return modules with different versions than would be selected in modload.LoadPackages. 'go mod why -m' was too strict about this, mapping module paths and versions to packages. With this fix, it maps module paths without versions to packages. Fixes #48613 Change-Id: I836c46289bb647d6c46ec65e7589531da532d5e8 Reviewed-on: https://go-review.googlesource.com/c/go/+/352115 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/modcmd/why.go | 8 +++----- src/cmd/go/testdata/script/mod_skip_write.txt | 6 +----- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/cmd/go/internal/modcmd/why.go b/src/cmd/go/internal/modcmd/why.go index 9647784b67..d8355cca95 100644 --- a/src/cmd/go/internal/modcmd/why.go +++ b/src/cmd/go/internal/modcmd/why.go @@ -12,8 +12,6 @@ import ( "cmd/go/internal/base" "cmd/go/internal/imports" "cmd/go/internal/modload" - - "golang.org/x/mod/module" ) var cmdWhy = &base.Command{ @@ -90,19 +88,19 @@ func runWhy(ctx context.Context, cmd *base.Command, args []string) { base.Fatalf("go: %v", err) } - byModule := make(map[module.Version][]string) + byModule := make(map[string][]string) _, pkgs := modload.LoadPackages(ctx, loadOpts, "all") for _, path := range pkgs { m := modload.PackageModule(path) if m.Path != "" { - byModule[m] = append(byModule[m], path) + byModule[m.Path] = append(byModule[m.Path], path) } } sep := "" for _, m := range mods { best := "" bestDepth := 1000000000 - for _, path := range byModule[module.Version{Path: m.Path, Version: m.Version}] { + for _, path := range byModule[m.Path] { d := modload.WhyDepth(path) if d > 0 && d < bestDepth { best = path diff --git a/src/cmd/go/testdata/script/mod_skip_write.txt b/src/cmd/go/testdata/script/mod_skip_write.txt index c3e5906589..9fdb6fc121 100644 --- a/src/cmd/go/testdata/script/mod_skip_write.txt +++ b/src/cmd/go/testdata/script/mod_skip_write.txt @@ -24,9 +24,8 @@ go mod why rsc.io/sampler cmp stdout why.want cmp go.mod go.mod.edit -# TODO(#48613): 'go mod why -m' incorrectly reports sampler is not needed. go mod why -m rsc.io/sampler -cmp stdout why-broken.want +cmp stdout why.want cmp go.mod go.mod.edit cp go.mod.orig go.mod @@ -91,6 +90,3 @@ rsc.io/sampler@v1.3.0 golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c m rsc.io/quote rsc.io/sampler --- why-broken.want -- -# rsc.io/sampler -(main module does not need module rsc.io/sampler) -- GitLab From 1ce6fd03b8a72fd8346fb23a975124edf977d25e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Sat, 16 Jan 2021 18:03:31 +0000 Subject: [PATCH 1304/2500] cmd/gofmt: format files in parallel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gofmt is pretty heavily CPU-bound, since parsing and formatting 1MiB of Go code takes much longer than reading that amount of bytes from disk. However, parsing and manipulating a large Go source file is very difficult to parallelize, so we continue to process each file in its own goroutine. A Go module may contain a large number of Go source files, so we need to bound the amount of work in flight. However, because the distribution of sizes for Go source files varies widely — from tiny doc.go files containing a single package comment all the way up to massive API wrappers generated by automated tools — the amount of time, work, and memory overhead needed to process each file also varies. To account for this variability, we limit the in-flight work by bytes of input rather than by number of files. That allows us to make progress on many small files while we wait for work on a handful of large files to complete. The gofmt tool has a well-defined output format on stdout, which was previously deterministic. We keep it deterministic by printing the results of each file in order, using a lazily-synchronized io.Writer (loosly inspired by Haskell's IO monad). After a file has been formatted in memory, we keep it in memory (again, limited by the corresponding number of input bytes) until the output for all previous files has been flushed. This adds a bit of latency compared to emitting the output in nondeterministic order, but a little extra latency seems worth the cost to preserve output stability. This change is based on Daniel Martí's work in CL 284139, but using a weighted semaphore and ephemeral goroutines instead of a worker pool and batches. Benchmark results are similar, and I find the concurrency in this approach a bit easier to reason about. In the batching-based approach, the batch size allows us to "look ahead" to find large files and start processing them early. To keep the CPUs saturated and prevent stragglers, we would need to tune the batch size to be about the same as the largest input files. If the batch size is set too high, a large batch of small files could turn into a straggler, but if the batch size is set too low, the largest files in the data set won't be started early enough and we'll end up with a large-file straggler. One possible alternative would be to sort by file size instead of batching: identify all of the files to be processed, sort from largest to smallest, and then process the largest files first so that the "tail" of processing covers the smallest files. However, that approach would still fail to saturate available CPU when disk latency is high, would require buffering an arbitrary amount of metadata in order to sort by size, and (perhaps most importantly!) would not allow the `gofmt` binary to preserve the same (deterministic) output order that it has today. In contrast, with a semaphore we can produce the same deterministic output as ever using only one tuning parameter: the memory footprint, expressed as a rough lower bound on the amount of RAM available per thread. While we're below the memory limit, we can run arbitrarily many disk operations arbitrarily far ahead, and process the results of those operations whenever they become avaliable. Then it's up to the kernel (not us) to schedule the disk operations for throughput and latency, and it's up to the runtime (not us) to schedule the goroutines so that they complete quickly. In practice, even a modest assumption of a few megabytes per thread seems to provide a nice speedup, and it should scale reasonably even to machines with vastly different ratios of CPU to disk. (In practice, I expect that most 'gofmt' invocations will work with files on at most one physical disk, so the CPU:disk ratio should vary more-or-less directly with the thread count, whereas the CPU:memory ratio is more-or-less independent of thread count.) name \ time/op baseline.txt 284139.txt simplified.txt GofmtGorootCmd 11.9s ± 2% 2.7s ± 3% 2.8s ± 5% name \ user-time/op baseline.txt 284139.txt simplified.txt GofmtGorootCmd 13.5s ± 2% 14.4s ± 1% 14.7s ± 1% name \ sys-time/op baseline.txt 284139.txt simplified.txt GofmtGorootCmd 465ms ± 8% 229ms ±28% 232ms ±31% name \ peak-RSS-bytes baseline.txt 284139.txt simplified.txt GofmtGorootCmd 77.7MB ± 4% 162.2MB ±10% 192.9MB ±15% For #43566 Change-Id: I4ba251eb4d188a3bd1901039086be57f0b341910 Reviewed-on: https://go-review.googlesource.com/c/go/+/317975 Trust: Bryan C. Mills Trust: Daniel Martí Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Daniel Martí --- doc/go1.18.html | 11 +- src/cmd/go.mod | 1 + src/cmd/go.sum | 2 + src/cmd/gofmt/gofmt.go | 306 +++++++++++++++--- src/cmd/gofmt/gofmt_test.go | 24 +- src/cmd/gofmt/rewrite.go | 6 +- src/cmd/vendor/golang.org/x/sync/AUTHORS | 3 + src/cmd/vendor/golang.org/x/sync/CONTRIBUTORS | 3 + src/cmd/vendor/golang.org/x/sync/LICENSE | 27 ++ src/cmd/vendor/golang.org/x/sync/PATENTS | 22 ++ .../golang.org/x/sync/semaphore/semaphore.go | 136 ++++++++ src/cmd/vendor/modules.txt | 3 + 12 files changed, 481 insertions(+), 63 deletions(-) create mode 100644 src/cmd/vendor/golang.org/x/sync/AUTHORS create mode 100644 src/cmd/vendor/golang.org/x/sync/CONTRIBUTORS create mode 100644 src/cmd/vendor/golang.org/x/sync/LICENSE create mode 100644 src/cmd/vendor/golang.org/x/sync/PATENTS create mode 100644 src/cmd/vendor/golang.org/x/sync/semaphore/semaphore.go diff --git a/doc/go1.18.html b/doc/go1.18.html index 911bb712f7..63715ef0d6 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -47,6 +47,15 @@ Do not send CLs removing the interior tags from such phrases. TODO: complete this section, or delete if not needed

    +

    gofmt

    + +

    + gofmt now reads and formats input files concurrently, with a + memory limit proportional to GOMAXPROCS. On a machine with + multiple CPUs, gofmt should now be significantly faster. +

    + +

    Runtime

    @@ -111,4 +120,4 @@ Do not send CLs removing the interior tags from such phrases. deprecated in favor of SyscallN.

-
\ No newline at end of file + diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 26be677254..c52a936b4e 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -6,6 +6,7 @@ require ( github.com/google/pprof v0.0.0-20210827144239-02619b876842 golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1 golang.org/x/mod v0.5.1-0.20210913215816-37dd6891021a + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b golang.org/x/tools v0.1.6-0.20210904010709-360456621443 ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 19bb1ee213..9afba00791 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -11,6 +11,8 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s3 golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/mod v0.5.1-0.20210913215816-37dd6891021a h1:55PVa91KndtPGH2lus5l2gDZqoO/x+Oa5CV0lVf8Ij8= golang.org/x/mod v0.5.1-0.20210913215816-37dd6891021a/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e h1:XMgFehsDnnLGtjvjOfqWSUzt0alpTR1RSEuznObga2c= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go index b3c120daab..860d77aaf0 100644 --- a/src/cmd/gofmt/gofmt.go +++ b/src/cmd/gofmt/gofmt.go @@ -6,6 +6,7 @@ package main import ( "bytes" + "context" "flag" "fmt" "go/ast" @@ -22,6 +23,8 @@ import ( "strings" "cmd/internal/diff" + + "golang.org/x/sync/semaphore" ) var ( @@ -50,17 +53,10 @@ const ( ) var ( - fileSet = token.NewFileSet() // per process FileSet - exitCode = 0 - rewrite func(*ast.File) *ast.File + rewrite func(*token.FileSet, *ast.File) *ast.File parserMode parser.Mode ) -func report(err error) { - scanner.PrintError(os.Stderr, err) - exitCode = 2 -} - func usage() { fmt.Fprintf(os.Stderr, "usage: gofmt [flags] [path ...]\n") flag.PrintDefaults() @@ -76,41 +72,211 @@ func initParserMode() { func isGoFile(f fs.DirEntry) bool { // ignore non-Go files name := f.Name() - return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") + return !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") && !f.IsDir() +} + +// A sequencer performs concurrent tasks that may write output, but emits that +// output in a deterministic order. +type sequencer struct { + maxWeight int64 + sem *semaphore.Weighted // weighted by input bytes (an approximate proxy for memory overhead) + prev <-chan *reporterState // 1-buffered +} + +// newSequencer returns a sequencer that allows concurrent tasks up to maxWeight +// and writes tasks' output to out and err. +func newSequencer(maxWeight int64, out, err io.Writer) *sequencer { + sem := semaphore.NewWeighted(maxWeight) + prev := make(chan *reporterState, 1) + prev <- &reporterState{out: out, err: err} + return &sequencer{ + maxWeight: maxWeight, + sem: sem, + prev: prev, + } +} + +// exclusive is a weight that can be passed to a sequencer to cause +// a task to be executed without any other concurrent tasks. +const exclusive = -1 + +// Add blocks until the sequencer has enough weight to spare, then adds f as a +// task to be executed concurrently. +// +// If the weight is either negative or larger than the sequencer's maximum +// weight, Add blocks until all other tasks have completed, then the task +// executes exclusively (blocking all other calls to Add until it completes). +// +// f may run concurrently in a goroutine, but its output to the passed-in +// reporter will be sequential relative to the other tasks in the sequencer. +// +// If f invokes a method on the reporter, execution of that method may block +// until the previous task has finished. (To maximize concurrency, f should +// avoid invoking the reporter until it has finished any parallelizable work.) +// +// If f returns a non-nil error, that error will be reported after f's output +// (if any) and will cause a nonzero final exit code. +func (s *sequencer) Add(weight int64, f func(*reporter) error) { + if weight < 0 || weight > s.maxWeight { + weight = s.maxWeight + } + if err := s.sem.Acquire(context.TODO(), weight); err != nil { + // Change the task from "execute f" to "report err". + weight = 0 + f = func(*reporter) error { return err } + } + + r := &reporter{prev: s.prev} + next := make(chan *reporterState, 1) + s.prev = next + + // Start f in parallel: it can run until it invokes a method on r, at which + // point it will block until the previous task releases the output state. + go func() { + if err := f(r); err != nil { + r.Report(err) + } + next <- r.getState() // Release the next task. + s.sem.Release(weight) + }() +} + +// AddReport prints an error to s after the output of any previously-added +// tasks, causing the final exit code to be nonzero. +func (s *sequencer) AddReport(err error) { + s.Add(0, func(*reporter) error { return err }) +} + +// GetExitCode waits for all previously-added tasks to complete, then returns an +// exit code for the sequence suitable for passing to os.Exit. +func (s *sequencer) GetExitCode() int { + c := make(chan int, 1) + s.Add(0, func(r *reporter) error { + c <- r.ExitCode() + return nil + }) + return <-c +} + +// A reporter reports output, warnings, and errors. +type reporter struct { + prev <-chan *reporterState + state *reporterState +} + +// reporterState carries the state of a reporter instance. +// +// Only one reporter at a time may have access to a reporterState. +type reporterState struct { + out, err io.Writer + exitCode int +} + +// getState blocks until any prior reporters are finished with the reporter +// state, then returns the state for manipulation. +func (r *reporter) getState() *reporterState { + if r.state == nil { + r.state = <-r.prev + } + return r.state } +// Warnf emits a warning message to the reporter's error stream, +// without changing its exit code. +func (r *reporter) Warnf(format string, args ...interface{}) { + fmt.Fprintf(r.getState().err, format, args...) +} + +// Write emits a slice to the reporter's output stream. +// +// Any error is returned to the caller, and does not otherwise affect the +// reporter's exit code. +func (r *reporter) Write(p []byte) (int, error) { + return r.getState().out.Write(p) +} + +// Report emits a non-nil error to the reporter's error stream, +// changing its exit code to a nonzero value. +func (r *reporter) Report(err error) { + if err == nil { + panic("Report with nil error") + } + st := r.getState() + scanner.PrintError(st.err, err) + st.exitCode = 2 +} + +func (r *reporter) ExitCode() int { + return r.getState().exitCode +} + +// If info == nil, we are formatting stdin instead of a file. // If in == nil, the source is the contents of the file with the given filename. -func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error { - var perm fs.FileMode = 0644 +func processFile(filename string, info fs.FileInfo, in io.Reader, r *reporter) error { if in == nil { - f, err := os.Open(filename) + var err error + in, err = os.Open(filename) if err != nil { return err } - defer f.Close() - fi, err := f.Stat() + } + + // Compute the file's size and read its contents with minimal allocations. + // + // If the size is unknown (or bogus, or overflows an int), fall back to + // a size-independent ReadAll. + var src []byte + size := -1 + if info != nil && info.Mode().IsRegular() && int64(int(info.Size())) == info.Size() { + size = int(info.Size()) + } + if size+1 > 0 { + // If we have the FileInfo from filepath.WalkDir, use it to make + // a buffer of the right size and avoid ReadAll's reallocations. + // + // We try to read size+1 bytes so that we can detect modifications: if we + // read more than size bytes, then the file was modified concurrently. + // (If that happens, we could, say, append to src to finish the read, or + // proceed with a truncated buffer — but the fact that it changed at all + // indicates a possible race with someone editing the file, so we prefer to + // stop to avoid corrupting it.) + src = make([]byte, size+1) + n, err := io.ReadFull(in, src) + if err != nil && err != io.ErrUnexpectedEOF { + return err + } + if n < size { + return fmt.Errorf("error: size of %s changed during reading (from %d to %d bytes)", filename, size, n) + } else if n > size { + return fmt.Errorf("error: size of %s changed during reading (from %d to >=%d bytes)", filename, size, len(src)) + } + src = src[:n] + } else { + // The file is not known to be regular, so we don't have a reliable size for it. + var err error + src, err = io.ReadAll(in) if err != nil { return err } - in = f - perm = fi.Mode().Perm() } - src, err := io.ReadAll(in) - if err != nil { - return err + fileSet := token.NewFileSet() + fragmentOk := false + if info == nil { + // If we are formatting stdin, we accept a program fragment in lieu of a + // complete source file. + fragmentOk = true } - - file, sourceAdj, indentAdj, err := parse(fileSet, filename, src, stdin) + file, sourceAdj, indentAdj, err := parse(fileSet, filename, src, fragmentOk) if err != nil { return err } if rewrite != nil { if sourceAdj == nil { - file = rewrite(file) + file = rewrite(fileSet, file) } else { - fmt.Fprintf(os.Stderr, "warning: rewrite ignored for incomplete programs\n") + r.Warnf("warning: rewrite ignored for incomplete programs\n") } } @@ -128,10 +294,14 @@ func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error if !bytes.Equal(src, res) { // formatting has changed if *list { - fmt.Fprintln(out, filename) + fmt.Fprintln(r, filename) } if *write { + if info == nil { + panic("-w should not have been allowed with stdin") + } // make a temporary backup before overwriting original + perm := info.Mode().Perm() bakname, err := backupFile(filename+".", src, perm) if err != nil { return err @@ -151,45 +321,42 @@ func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error if err != nil { return fmt.Errorf("computing diff: %s", err) } - fmt.Fprintf(out, "diff -u %s %s\n", filepath.ToSlash(filename+".orig"), filepath.ToSlash(filename)) - out.Write(data) + fmt.Fprintf(r, "diff -u %s %s\n", filepath.ToSlash(filename+".orig"), filepath.ToSlash(filename)) + r.Write(data) } } if !*list && !*write && !*doDiff { - _, err = out.Write(res) + _, err = r.Write(res) } return err } -func visitFile(path string, f fs.DirEntry, err error) error { - if err != nil || !isGoFile(f) { - return err - } - if err := processFile(path, nil, os.Stdout, false); err != nil { - report(err) - } - return nil -} - func main() { + // Arbitrarily limit in-flight work to 2MiB times the number of threads. + // + // The actual overhead for the parse tree and output will depend on the + // specifics of the file, but this at least keeps the footprint of the process + // roughly proportional to GOMAXPROCS. + maxWeight := (2 << 20) * int64(runtime.GOMAXPROCS(0)) + s := newSequencer(maxWeight, os.Stdout, os.Stderr) + // call gofmtMain in a separate function // so that it can use defer and have them // run before the exit. - gofmtMain() - os.Exit(exitCode) + gofmtMain(s) + os.Exit(s.GetExitCode()) } -func gofmtMain() { +func gofmtMain(s *sequencer) { flag.Usage = usage flag.Parse() if *cpuprofile != "" { f, err := os.Create(*cpuprofile) if err != nil { - fmt.Fprintf(os.Stderr, "creating cpu profile: %s\n", err) - exitCode = 2 + s.AddReport(fmt.Errorf("creating cpu profile: %s", err)) return } defer f.Close() @@ -203,34 +370,67 @@ func gofmtMain() { args := flag.Args() if len(args) == 0 { if *write { - fmt.Fprintln(os.Stderr, "error: cannot use -w with standard input") - exitCode = 2 + s.AddReport(fmt.Errorf("error: cannot use -w with standard input")) return } - if err := processFile("", os.Stdin, os.Stdout, true); err != nil { - report(err) - } + s.Add(0, func(r *reporter) error { + return processFile("", nil, os.Stdin, r) + }) return } for _, arg := range args { switch info, err := os.Stat(arg); { case err != nil: - report(err) + s.AddReport(err) case !info.IsDir(): // Non-directory arguments are always formatted. - if err := processFile(arg, nil, os.Stdout, false); err != nil { - report(err) - } + arg := arg + s.Add(fileWeight(arg, info), func(r *reporter) error { + return processFile(arg, info, nil, r) + }) default: // Directories are walked, ignoring non-Go files. - if err := filepath.WalkDir(arg, visitFile); err != nil { - report(err) + err := filepath.WalkDir(arg, func(path string, f fs.DirEntry, err error) error { + if err != nil || !isGoFile(f) { + return err + } + info, err := f.Info() + if err != nil { + s.AddReport(err) + return nil + } + s.Add(fileWeight(path, info), func(r *reporter) error { + return processFile(path, info, nil, r) + }) + return nil + }) + if err != nil { + s.AddReport(err) } } } } +func fileWeight(path string, info fs.FileInfo) int64 { + if info == nil { + return exclusive + } + if info.Mode().Type() == fs.ModeSymlink { + var err error + info, err = os.Stat(path) + if err != nil { + return exclusive + } + } + if !info.Mode().IsRegular() { + // For non-regular files, FileInfo.Size is system-dependent and thus not a + // reliable indicator of weight. + return exclusive + } + return info.Size() +} + func diffWithReplaceTempFile(b1, b2 []byte, filename string) ([]byte, error) { data, err := diff.Diff("gofmt", b1, b2) if len(data) > 0 { diff --git a/src/cmd/gofmt/gofmt_test.go b/src/cmd/gofmt/gofmt_test.go index 9ef7676214..676c5b43ed 100644 --- a/src/cmd/gofmt/gofmt_test.go +++ b/src/cmd/gofmt/gofmt_test.go @@ -58,7 +58,11 @@ func runTest(t *testing.T, in, out string) { // process flags *simplifyAST = false *rewriteRule = "" - stdin := false + info, err := os.Lstat(in) + if err != nil { + t.Error(err) + return + } for _, flag := range strings.Split(gofmtFlags(in, 20), " ") { elts := strings.SplitN(flag, "=", 2) name := elts[0] @@ -75,7 +79,7 @@ func runTest(t *testing.T, in, out string) { *simplifyAST = true case "-stdin": // fake flag - pretend input is from stdin - stdin = true + info = nil default: t.Errorf("unrecognized flag name: %s", name) } @@ -84,11 +88,17 @@ func runTest(t *testing.T, in, out string) { initParserMode() initRewrite() - var buf bytes.Buffer - err := processFile(in, nil, &buf, stdin) - if err != nil { - t.Error(err) - return + const maxWeight = 2 << 20 + var buf, errBuf bytes.Buffer + s := newSequencer(maxWeight, &buf, &errBuf) + s.Add(fileWeight(in, info), func(r *reporter) error { + return processFile(in, info, nil, r) + }) + if errBuf.Len() > 0 { + t.Logf("%q", errBuf.Bytes()) + } + if s.GetExitCode() != 0 { + t.Fail() } expected, err := os.ReadFile(out) diff --git a/src/cmd/gofmt/rewrite.go b/src/cmd/gofmt/rewrite.go index bab22e04cd..0e736e6132 100644 --- a/src/cmd/gofmt/rewrite.go +++ b/src/cmd/gofmt/rewrite.go @@ -28,7 +28,9 @@ func initRewrite() { } pattern := parseExpr(f[0], "pattern") replace := parseExpr(f[1], "replacement") - rewrite = func(p *ast.File) *ast.File { return rewriteFile(pattern, replace, p) } + rewrite = func(fset *token.FileSet, p *ast.File) *ast.File { + return rewriteFile(fset, pattern, replace, p) + } } // parseExpr parses s as an expression. @@ -54,7 +56,7 @@ func dump(msg string, val reflect.Value) { */ // rewriteFile applies the rewrite rule 'pattern -> replace' to an entire file. -func rewriteFile(pattern, replace ast.Expr, p *ast.File) *ast.File { +func rewriteFile(fileSet *token.FileSet, pattern, replace ast.Expr, p *ast.File) *ast.File { cmap := ast.NewCommentMap(fileSet, p, p.Comments) m := make(map[string]reflect.Value) pat := reflect.ValueOf(pattern) diff --git a/src/cmd/vendor/golang.org/x/sync/AUTHORS b/src/cmd/vendor/golang.org/x/sync/AUTHORS new file mode 100644 index 0000000000..15167cd746 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/sync/AUTHORS @@ -0,0 +1,3 @@ +# This source code refers to The Go Authors for copyright purposes. +# The master list of authors is in the main Go distribution, +# visible at http://tip.golang.org/AUTHORS. diff --git a/src/cmd/vendor/golang.org/x/sync/CONTRIBUTORS b/src/cmd/vendor/golang.org/x/sync/CONTRIBUTORS new file mode 100644 index 0000000000..1c4577e968 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/sync/CONTRIBUTORS @@ -0,0 +1,3 @@ +# This source code was written by the Go contributors. +# The master list of contributors is in the main Go distribution, +# visible at http://tip.golang.org/CONTRIBUTORS. diff --git a/src/cmd/vendor/golang.org/x/sync/LICENSE b/src/cmd/vendor/golang.org/x/sync/LICENSE new file mode 100644 index 0000000000..6a66aea5ea --- /dev/null +++ b/src/cmd/vendor/golang.org/x/sync/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/cmd/vendor/golang.org/x/sync/PATENTS b/src/cmd/vendor/golang.org/x/sync/PATENTS new file mode 100644 index 0000000000..733099041f --- /dev/null +++ b/src/cmd/vendor/golang.org/x/sync/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/src/cmd/vendor/golang.org/x/sync/semaphore/semaphore.go b/src/cmd/vendor/golang.org/x/sync/semaphore/semaphore.go new file mode 100644 index 0000000000..30f632c577 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/sync/semaphore/semaphore.go @@ -0,0 +1,136 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package semaphore provides a weighted semaphore implementation. +package semaphore // import "golang.org/x/sync/semaphore" + +import ( + "container/list" + "context" + "sync" +) + +type waiter struct { + n int64 + ready chan<- struct{} // Closed when semaphore acquired. +} + +// NewWeighted creates a new weighted semaphore with the given +// maximum combined weight for concurrent access. +func NewWeighted(n int64) *Weighted { + w := &Weighted{size: n} + return w +} + +// Weighted provides a way to bound concurrent access to a resource. +// The callers can request access with a given weight. +type Weighted struct { + size int64 + cur int64 + mu sync.Mutex + waiters list.List +} + +// Acquire acquires the semaphore with a weight of n, blocking until resources +// are available or ctx is done. On success, returns nil. On failure, returns +// ctx.Err() and leaves the semaphore unchanged. +// +// If ctx is already done, Acquire may still succeed without blocking. +func (s *Weighted) Acquire(ctx context.Context, n int64) error { + s.mu.Lock() + if s.size-s.cur >= n && s.waiters.Len() == 0 { + s.cur += n + s.mu.Unlock() + return nil + } + + if n > s.size { + // Don't make other Acquire calls block on one that's doomed to fail. + s.mu.Unlock() + <-ctx.Done() + return ctx.Err() + } + + ready := make(chan struct{}) + w := waiter{n: n, ready: ready} + elem := s.waiters.PushBack(w) + s.mu.Unlock() + + select { + case <-ctx.Done(): + err := ctx.Err() + s.mu.Lock() + select { + case <-ready: + // Acquired the semaphore after we were canceled. Rather than trying to + // fix up the queue, just pretend we didn't notice the cancelation. + err = nil + default: + isFront := s.waiters.Front() == elem + s.waiters.Remove(elem) + // If we're at the front and there're extra tokens left, notify other waiters. + if isFront && s.size > s.cur { + s.notifyWaiters() + } + } + s.mu.Unlock() + return err + + case <-ready: + return nil + } +} + +// TryAcquire acquires the semaphore with a weight of n without blocking. +// On success, returns true. On failure, returns false and leaves the semaphore unchanged. +func (s *Weighted) TryAcquire(n int64) bool { + s.mu.Lock() + success := s.size-s.cur >= n && s.waiters.Len() == 0 + if success { + s.cur += n + } + s.mu.Unlock() + return success +} + +// Release releases the semaphore with a weight of n. +func (s *Weighted) Release(n int64) { + s.mu.Lock() + s.cur -= n + if s.cur < 0 { + s.mu.Unlock() + panic("semaphore: released more than held") + } + s.notifyWaiters() + s.mu.Unlock() +} + +func (s *Weighted) notifyWaiters() { + for { + next := s.waiters.Front() + if next == nil { + break // No more waiters blocked. + } + + w := next.Value.(waiter) + if s.size-s.cur < w.n { + // Not enough tokens for the next waiter. We could keep going (to try to + // find a waiter with a smaller request), but under load that could cause + // starvation for large requests; instead, we leave all remaining waiters + // blocked. + // + // Consider a semaphore used as a read-write lock, with N tokens, N + // readers, and one writer. Each reader can Acquire(1) to obtain a read + // lock. The writer can Acquire(N) to obtain a write lock, excluding all + // of the readers. If we allow the readers to jump ahead in the queue, + // the writer will starve — there is always one token available for every + // reader. + break + } + + s.cur += w.n + s.waiters.Remove(next) + close(w.ready) + } +} diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 4ff07ab015..49a79890bc 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -39,6 +39,9 @@ golang.org/x/mod/sumdb/dirhash golang.org/x/mod/sumdb/note golang.org/x/mod/sumdb/tlog golang.org/x/mod/zip +# golang.org/x/sync v0.0.0-20210220032951-036812b2e83c +## explicit +golang.org/x/sync/semaphore # golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e ## explicit; go 1.17 golang.org/x/sys/internal/unsafeheader -- GitLab From d60ad1e068263832c711aaf17b6ccb1b7f71b000 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 21 Sep 2021 16:30:06 -0700 Subject: [PATCH 1305/2500] testing: address feedback for dev.fuzz merge Based on comments in CL 348469. Note that with this change, F.Fuzz no longer calls runtime.Goexit. This simplifies our logic and makes F.Fuzz more predictable. Change-Id: I6c3c65b0e8e8f261621cbe2f17375e8164ef60a0 Reviewed-on: https://go-review.googlesource.com/c/go/+/351316 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/alldocs.go | 14 ++- src/cmd/go/internal/cache/cache.go | 2 + src/cmd/go/internal/clean/clean.go | 9 +- src/cmd/go/internal/help/helpdoc.go | 7 ++ src/cmd/go/internal/load/flag.go | 5 +- src/cmd/go/internal/load/pkg.go | 18 +--- src/cmd/go/internal/test/test.go | 2 +- src/cmd/go/internal/work/init.go | 7 +- src/cmd/go/testdata/script/test_fuzz.txt | 25 +++++- .../script/test_fuzz_mutate_crash.txt | 17 +++- src/testing/fuzz.go | 85 +++++++++---------- src/testing/testing.go | 57 ++++++------- 12 files changed, 142 insertions(+), 106 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 0036d8615f..02d2afc582 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -293,8 +293,11 @@ // dependencies. // // The -fuzzcache flag causes clean to remove files stored in the Go build -// cache for fuzz testing. Files stored in source testdata directories -// are left in place. +// cache for fuzz testing. The fuzzing engine caches files that expand +// code coverage, so removing them may make fuzzing less effective until +// new inputs are found that provide the same coverage. These files are +// distinct from those stored in testdata directory; clean does not remove +// those files. // // For more about build flags, see 'go help build'. // @@ -1854,6 +1857,13 @@ // See 'go help test' for details. Running 'go clean -testcache' removes // all cached test results (but not cached build results). // +// The go command also caches values used in fuzzing with 'go test -fuzz', +// specifically, values that expanded code coverage when passed to a +// fuzz function. These values are not used for regular building and +// testing, but they're stored in a subdirectory of the build cache. +// Running 'go clean -fuzzcache' removes all cached fuzzing values. +// This may make fuzzing less effective, temporarily. +// // The GODEBUG environment variable can enable printing of debugging // information about the state of the cache: // diff --git a/src/cmd/go/internal/cache/cache.go b/src/cmd/go/internal/cache/cache.go index 596f22e8fc..93d7c25658 100644 --- a/src/cmd/go/internal/cache/cache.go +++ b/src/cmd/go/internal/cache/cache.go @@ -540,6 +540,8 @@ func (c *Cache) copyFile(file io.ReadSeeker, out OutputID, size int64) error { // This directory is managed by the internal/fuzz package. Files in this // directory aren't removed by the 'go clean -cache' command or by Trim. // They may be removed with 'go clean -fuzzcache'. +// +// TODO(#48526): make Trim remove unused files from this directory. func (c *Cache) FuzzDir() string { return filepath.Join(c.dir, "fuzz") } diff --git a/src/cmd/go/internal/clean/clean.go b/src/cmd/go/internal/clean/clean.go index ca7623ea21..dc93cdf598 100644 --- a/src/cmd/go/internal/clean/clean.go +++ b/src/cmd/go/internal/clean/clean.go @@ -76,8 +76,11 @@ download cache, including unpacked source code of versioned dependencies. The -fuzzcache flag causes clean to remove files stored in the Go build -cache for fuzz testing. Files stored in source testdata directories -are left in place. +cache for fuzz testing. The fuzzing engine caches files that expand +code coverage, so removing them may make fuzzing less effective until +new inputs are found that provide the same coverage. These files are +distinct from those stored in testdata directory; clean does not remove +those files. For more about build flags, see 'go help build'. @@ -220,7 +223,7 @@ func runClean(ctx context.Context, cmd *base.Command, args []string) { } if !cfg.BuildN { if err := os.RemoveAll(fuzzDir); err != nil { - base.Errorf("go clean -fuzzcache: %v", err) + base.Errorf("go: %v", err) } } } diff --git a/src/cmd/go/internal/help/helpdoc.go b/src/cmd/go/internal/help/helpdoc.go index 749dcf192b..035235fe1b 100644 --- a/src/cmd/go/internal/help/helpdoc.go +++ b/src/cmd/go/internal/help/helpdoc.go @@ -775,6 +775,13 @@ The go command also caches successful package test results. See 'go help test' for details. Running 'go clean -testcache' removes all cached test results (but not cached build results). +The go command also caches values used in fuzzing with 'go test -fuzz', +specifically, values that expanded code coverage when passed to a +fuzz function. These values are not used for regular building and +testing, but they're stored in a subdirectory of the build cache. +Running 'go clean -fuzzcache' removes all cached fuzzing values. +This may make fuzzing less effective, temporarily. + The GODEBUG environment variable can enable printing of debugging information about the state of the cache: diff --git a/src/cmd/go/internal/load/flag.go b/src/cmd/go/internal/load/flag.go index 24670524fc..4e0cb5bc19 100644 --- a/src/cmd/go/internal/load/flag.go +++ b/src/cmd/go/internal/load/flag.go @@ -22,9 +22,8 @@ var ( // that allows specifying different effective flags for different packages. // See 'go help build' for more details about per-package flags. type PerPackageFlag struct { - present bool - values []ppfValue - seenPackages map[*Package]bool // the packages for which the flags have already been set + present bool + values []ppfValue } // A ppfValue is a single = per-package flag value. diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index 317053d918..4013330bc4 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -2630,20 +2630,10 @@ func (e *mainPackageError) ImportPath() string { func setToolFlags(pkgs ...*Package) { for _, p := range PackageList(pkgs) { - appendFlags(p, &p.Internal.Asmflags, &BuildAsmflags) - appendFlags(p, &p.Internal.Gcflags, &BuildGcflags) - appendFlags(p, &p.Internal.Ldflags, &BuildLdflags) - appendFlags(p, &p.Internal.Gccgoflags, &BuildGccgoflags) - } -} - -func appendFlags(p *Package, flags *[]string, packageFlag *PerPackageFlag) { - if !packageFlag.seenPackages[p] { - if packageFlag.seenPackages == nil { - packageFlag.seenPackages = make(map[*Package]bool) - } - packageFlag.seenPackages[p] = true - *flags = append(*flags, packageFlag.For(p)...) + p.Internal.Asmflags = BuildAsmflags.For(p) + p.Internal.Gcflags = BuildGcflags.For(p) + p.Internal.Ldflags = BuildLdflags.For(p) + p.Internal.Gccgoflags = BuildGccgoflags.For(p) } } diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index c8305c7808..518555ecba 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -824,7 +824,7 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { if testFuzz != "" && fuzzFlags != nil { // Don't instrument packages which may affect coverage guidance but are // unlikely to be useful. Most of these are used by the testing or - // internal/fuzz concurrently with fuzzing. + // internal/fuzz packages concurrently with fuzzing. var fuzzNoInstrument = map[string]bool{ "context": true, "internal/fuzz": true, diff --git a/src/cmd/go/internal/work/init.go b/src/cmd/go/internal/work/init.go index 34d2e1cbe1..1f8ec02df1 100644 --- a/src/cmd/go/internal/work/init.go +++ b/src/cmd/go/internal/work/init.go @@ -61,8 +61,11 @@ func BuildInit() { } // FuzzInstrumentFlags returns compiler flags that enable fuzzing instrumation -// on supported platforms. On unsupported platforms, FuzzInstrumentFlags returns -// nil. +// on supported platforms. +// +// On unsupported platforms, FuzzInstrumentFlags returns nil, meaning no +// instrumentation is added. 'go test -fuzz' still works without coverage, +// but it generates random inputs without guidance, so it's much less effective. func FuzzInstrumentFlags() []string { // TODO: expand the set of supported platforms, with testing. // Nothing about the instrumentation is OS specific, but only amd64 and arm64 diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt index b1a02f46eb..c9930aa37e 100644 --- a/src/cmd/go/testdata/script/test_fuzz.txt +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -77,10 +77,15 @@ stdout 'f.Fuzz function' stdout FAIL stdout 'f.Fuzz function' -# Test that a call to f.Fatal after the Fuzz func is never executed. -go test fatal_after_fuzz_func_fuzz_test.go -stdout ok -! stdout FAIL +# Test that runtime.Goexit within the fuzz function is an error. +! go test goexit_fuzz_fn_fuzz_test.go +! stdout ^ok +stdout FAIL + +# Test that a call to f.Fatal after the Fuzz func is executed. +! go test fatal_after_fuzz_func_fuzz_test.go +! stdout ok +stdout FAIL # Test that missing *T in f.Fuzz causes a non-zero exit status. ! go test incomplete_fuzz_call_fuzz_test.go @@ -267,6 +272,18 @@ func Fuzz(f *testing.F) { }) } +-- goexit_fuzz_fn_fuzz_test.go -- +package goexit_fuzz_fn_fuzz + +import "testing" + +func Fuzz(f *testing.F) { + f.Add([]byte("aa")) + f.Fuzz(func(t *testing.T, b []byte) { + runtime.Goexit() + }) +} + -- fatal_after_fuzz_func_fuzz_test.go -- package fatal_after_fuzz_func_fuzz diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt index 1b8b79b3dd..79476ecb28 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt @@ -29,6 +29,11 @@ stdout 'testdata[/\\]fuzz[/\\]FuzzWithNilPanic[/\\]' stdout 'runtime.Goexit' go run check_testdata.go FuzzWithNilPanic +! go test -run=FuzzWithGoexit -fuzz=FuzzWithGoexit -fuzztime=100x -fuzzminimizetime=1000x +stdout 'testdata[/\\]fuzz[/\\]FuzzWithGoexit[/\\]' +stdout 'runtime.Goexit' +go run check_testdata.go FuzzWithGoexit + ! go test -run=FuzzWithFail -fuzz=FuzzWithFail -fuzztime=100x -fuzzminimizetime=1000x stdout 'testdata[/\\]fuzz[/\\]FuzzWithFail[/\\]' go run check_testdata.go FuzzWithFail @@ -108,7 +113,8 @@ go 1.16 package fuzz_crash import ( - "os" + "os" + "runtime" "testing" ) @@ -130,6 +136,15 @@ func FuzzWithNilPanic(f *testing.F) { }) } +func FuzzWithGoexit(f *testing.F) { + f.Add([]byte("aa")) + f.Fuzz(func(t *testing.T, b []byte) { + if string(b) != "aa" { + runtime.Goexit() + } + }) +} + func FuzzWithFail(f *testing.F) { f.Add([]byte("aa")) f.Fuzz(func(t *testing.T, b []byte) { diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index ddce065783..771917b069 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -69,7 +69,7 @@ type F struct { // from testdata. corpus []corpusEntry - result FuzzResult + result fuzzResult fuzzCalled bool } @@ -290,17 +290,20 @@ var supportedTypes = map[reflect.Type]bool{ // whose remaining arguments are the types to be fuzzed. // For example: // -// f.Fuzz(func(t *testing.T, b []byte, i int) { ... }) +// f.Fuzz(func(t *testing.T, b []byte, i int) { ... }) // -// This function should be fast, deterministic, and stateless. +// The following types are allowed: []byte, string, bool, byte, rune, float32, +// float64, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64. +// More types may be supported in the future. // -// No mutatable input arguments, or pointers to them, should be retained between -// executions of the fuzz function, as the memory backing them may be mutated -// during a subsequent invocation. +// This function sould be fast and deterministic, and its behavior should not +// depend on shared state. No mutatable input arguments, or pointers to them, +// should be retained between executions of the fuzz function, as the memory +// backing them may be mutated during a subsequent invocation. // -// This is a terminal function which will terminate the currently running fuzz -// target by calling runtime.Goexit. -// To run any code after fuzzing stops, use (*F).Cleanup. +// When fuzzing, F.Fuzz does not return until a problem is found, time runs +// out (set with -fuzztime), or the test process is interrupted by a signal. +// F.Fuzz should be called exactly once unless F.Skip or F.Fail is called. func (f *F) Fuzz(ff interface{}) { if f.fuzzCalled { panic("testing: F.Fuzz called more than once") @@ -440,7 +443,7 @@ func (f *F) Fuzz(ff interface{}) { corpusTargetDir, cacheTargetDir) if err != nil { - f.result = FuzzResult{Error: err} + f.result = fuzzResult{Error: err} f.Fail() fmt.Fprintf(f.w, "%v\n", err) if crashErr, ok := err.(fuzzCrashError); ok { @@ -469,16 +472,6 @@ func (f *F) Fuzz(ff interface{}) { run(e) } } - - // Record that the fuzz function (or coordinateFuzzing or runFuzzWorker) - // returned normally. This is used to distinguish runtime.Goexit below - // from panic(nil). - f.finished = true - - // Terminate the goroutine. F.Fuzz should not return. - // We cannot call runtime.Goexit from a deferred function: if there is a - // panic, that would replace the panic value with nil. - runtime.Goexit() } func (f *F) report() { @@ -498,14 +491,14 @@ func (f *F) report() { } } -// FuzzResult contains the results of a fuzz run. -type FuzzResult struct { +// fuzzResult contains the results of a fuzz run. +type fuzzResult struct { N int // The number of iterations. T time.Duration // The total time taken. Error error // Error is the error from the crash } -func (r FuzzResult) String() string { +func (r fuzzResult) String() string { s := "" if r.Error == nil { return s @@ -698,27 +691,28 @@ func fRunner(f *F, fn func(*F)) { atomic.AddUint32(&numFailed, 1) } err := recover() - f.mu.RLock() - ok := f.skipped || f.failed || (f.fuzzCalled && f.finished) - f.mu.RUnlock() - if err == nil && !ok { - err = errNilPanicOrGoexit + if err == nil { + f.mu.RLock() + fuzzNotCalled := !f.fuzzCalled && !f.skipped && !f.failed + if !f.finished && !f.skipped && !f.failed { + err = errNilPanicOrGoexit + } + f.mu.RUnlock() + if fuzzNotCalled && err == nil { + f.Error("returned without calling F.Fuzz, F.Fail, or F.Skip") + } } // Use a deferred call to ensure that we report that the test is - // complete even if a cleanup function calls t.FailNow. See issue 41355. + // complete even if a cleanup function calls F.FailNow. See issue 41355. didPanic := false defer func() { - if didPanic { - return + if !didPanic { + // Only report that the test is complete if it doesn't panic, + // as otherwise the test binary can exit before the panic is + // reported to the user. See issue 41479. + f.signal <- true } - if err != nil { - panic(err) - } - // Only report that the test is complete if it doesn't panic, - // as otherwise the test binary can exit before the panic is - // reported to the user. See issue 41479. - f.signal <- true }() // If we recovered a panic or inappropriate runtime.Goexit, fail the test, @@ -747,8 +741,9 @@ func fRunner(f *F, fn func(*F)) { if len(f.sub) > 0 { // Unblock inputs that called T.Parallel while running the seed corpus. - // T.Parallel has no effect while fuzzing, so this only affects fuzz - // targets run as normal tests. + // This only affects fuzz targets run as normal tests. + // While fuzzing, T.Parallel has no effect, so f.sub is empty, and this + // branch is not taken. f.barrier is nil in that case. close(f.barrier) // Wait for the subtests to complete. for _, sub := range f.sub { @@ -776,11 +771,9 @@ func fRunner(f *F, fn func(*F)) { f.start = time.Now() fn(f) - // Code beyond this point is only executed if fn returned normally. - // That means fn did not call F.Fuzz or F.Skip. It should have called F.Fail. + // Code beyond this point will not be executed when FailNow or SkipNow + // is invoked. f.mu.Lock() - defer f.mu.Unlock() - if !f.failed { - panic(f.name + " returned without calling F.Fuzz, F.Fail, or F.Skip") - } + f.finished = true + f.mu.Unlock() } diff --git a/src/testing/testing.go b/src/testing/testing.go index ac1e52af85..b3f4b4da58 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -146,21 +146,21 @@ // // For example: // -// func FuzzHex(f *testing.F) { -// for _, seed := range [][]byte{{}, {0}, {9}, {0xa}, {0xf}, {1, 2, 3, 4}} { -// f.Add(seed) -// } -// f.Fuzz(func(t *testing.T, in []byte) { -// enc := hex.EncodeToString(in) -// out, err := hex.DecodeString(enc) -// if err != nil { -// t.Fatalf("%v: decode: %v", in, err) -// } -// if !bytes.Equal(in, out) { -// t.Fatalf("%v: not equal after round trip: %v", in, out) +// func FuzzHex(f *testing.F) { +// for _, seed := range [][]byte{{}, {0}, {9}, {0xa}, {0xf}, {1, 2, 3, 4}} { +// f.Add(seed) +// } +// f.Fuzz(func(t *testing.T, in []byte) { +// enc := hex.EncodeToString(in) +// out, err := hex.DecodeString(enc) +// if err != nil { +// t.Fatalf("%v: decode: %v", in, err) +// } +// if !bytes.Equal(in, out) { +// t.Fatalf("%v: not equal after round trip: %v", in, out) +// } +// }) // } -// }) -// } // // Seed inputs may be registered by calling F.Add or by storing files in the // directory testdata/fuzz/ (where is the name of the fuzz target) @@ -506,7 +506,7 @@ type common struct { name string // Name of test or benchmark. start time.Time // Time test or benchmark started duration time.Duration - barrier chan bool // To signal parallel subtests they may start. + barrier chan bool // To signal parallel subtests they may start. Nil when T.Parallel is not present (B) or not usable (when fuzzing). signal chan bool // To signal a test is done. sub []*T // Queue of subtests to be run in parallel. @@ -628,13 +628,6 @@ func (c *common) frameSkip(skip int) runtime.Frame { // and inserts the final newline if needed and indentation spaces for formatting. // This function must be called with c.mu held. func (c *common) decorate(s string, skip int) string { - if c.helperNames == nil { - c.helperNames = make(map[string]struct{}) - for pc := range c.helperPCs { - c.helperNames[pcToName(pc)] = struct{}{} - } - } - frame := c.frameSkip(skip) file := frame.File line := frame.Line @@ -1280,14 +1273,6 @@ func tRunner(t *T, fn func(t *T)) { err := recover() signal := true - if err != nil && t.isFuzzing() { - t.Errorf("panic: %s\n%s\n", err, string(debug.Stack())) - t.mu.Lock() - t.finished = true - t.mu.Unlock() - err = nil - } - t.mu.RLock() finished := t.finished t.mu.RUnlock() @@ -1306,6 +1291,18 @@ func tRunner(t *T, fn func(t *T)) { } } + if err != nil && t.isFuzzing() { + prefix := "panic: " + if err == errNilPanicOrGoexit { + prefix = "" + } + t.Errorf("%s%s\n%s\n", prefix, err, string(debug.Stack())) + t.mu.Lock() + t.finished = true + t.mu.Unlock() + err = nil + } + // Use a deferred call to ensure that we report that the test is // complete even if a cleanup function calls t.FailNow. See issue 41355. didPanic := false -- GitLab From 8854368cb076ea9a2b71c8b3c8f675a8e19b751c Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Fri, 24 Sep 2021 08:57:06 -0700 Subject: [PATCH 1306/2500] cmd/compile: deal with blank nodes with typeparam type during stenciling Deal correctly with a blank local variable with type param type. This is a special case, because a blank local variable is not in the fn.Dcl list. In this case, we must explicitly create a new blank node with the correct substituted type, so we have correct types if the blank local variable has an initializing assignment. Fixes #48602 Change-Id: I903ea44b29934e180404e32800773b7309bf297b Reviewed-on: https://go-review.googlesource.com/c/go/+/352117 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le Trust: Cuong Manh Le Trust: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 6 ++++++ test/typeparam/issue48602.go | 25 +++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 test/typeparam/issue48602.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index cf8641d60e..23f53bac04 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -912,6 +912,12 @@ func (subst *subster) node(n ir.Node) ir.Node { if v := subst.ts.Vars[x.(*ir.Name)]; v != nil { return v } + if ir.IsBlank(x) { + // Special case, because a blank local variable is + // not in the fn.Dcl list. + m := ir.NewNameAt(x.Pos(), ir.BlankNode.Sym()) + return typed(subst.ts.Typ(x.Type()), m) + } return x case ir.ONONAME: // This handles the identifier in a type switch guard diff --git a/test/typeparam/issue48602.go b/test/typeparam/issue48602.go new file mode 100644 index 0000000000..53ce20e6ea --- /dev/null +++ b/test/typeparam/issue48602.go @@ -0,0 +1,25 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type Iterator[T any] interface { + Iterate(fn T) +} + +type IteratorFunc[T any] func(fn T) + +func (f IteratorFunc[T]) Iterate(fn T) { + f(fn) +} + +func Foo[R any]() { + var _ Iterator[R] = IteratorFunc[R](nil) +} + +func main() { + Foo[int]() +} -- GitLab From ba7673069d9be4972a864023d74e9e0dd6a77b80 Mon Sep 17 00:00:00 2001 From: korzhao Date: Sat, 25 Sep 2021 01:13:27 +0800 Subject: [PATCH 1307/2500] cmd/compile: add required CONVIFACE nodes when translating OFUNCINST node In CL 349614. we removed the early transformation code that was needed to create the implicit CONVIFACE nodes. Because the transformCall function is not called when translating OFUNCINST. So we add in needed CONVIFACE nodes via typecheckaste(). Fixes #48598 Change-Id: If9dc7040cdc38ef2e52fdbb08c840095651426f2 Reviewed-on: https://go-review.googlesource.com/c/go/+/351856 Reviewed-by: Cuong Manh Le Reviewed-by: Dan Scales Trust: Cuong Manh Le Trust: Dan Scales Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot --- src/cmd/compile/internal/noder/stencil.go | 4 +++ src/cmd/compile/internal/noder/transform.go | 6 +++++ test/typeparam/issue48598.go | 28 +++++++++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 test/typeparam/issue48598.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 23f53bac04..d5fb9f338c 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1097,6 +1097,10 @@ func (subst *subster) node(n ir.Node) ir.Node { // A call with an OFUNCINST will get transformed // in stencil() once we have created & attached the // instantiation to be called. + // We must transform the arguments of the call now, though, + // so that any needed CONVIFACE nodes are exposed, + // so the dictionary format is correct + transformEarlyCall(call) case ir.OXDOT, ir.ODOTTYPE, ir.ODOTTYPE2: default: diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index 953036eb42..f7115904fe 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -177,6 +177,12 @@ func transformCall(n *ir.CallExpr) { } } +// transformEarlyCall transforms the arguments of a call with an OFUNCINST node. +func transformEarlyCall(n *ir.CallExpr) { + transformArgs(n) + typecheckaste(ir.OCALL, n.X, n.IsDDD, n.X.Type().Params(), n.Args) +} + // transformCompare transforms a compare operation (currently just equals/not // equals). Corresponds to the "comparison operators" case in // typecheck.typecheck1, including tcArith. diff --git a/test/typeparam/issue48598.go b/test/typeparam/issue48598.go new file mode 100644 index 0000000000..ea360f2135 --- /dev/null +++ b/test/typeparam/issue48598.go @@ -0,0 +1,28 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type Iterator[T any] interface { + Iterate() +} + +type IteratorFunc[T any] func(fn func(T) bool) + +func (f IteratorFunc[T]) Iterate() { +} + +func FromIterator[T any](it Iterator[T]) { + it.Iterate() +} + +func Foo[T, R any]() { + FromIterator[R](IteratorFunc[R](nil)) +} + +func main() { + Foo[int, int]() +} -- GitLab From aeea5bacbf79fb945edbeac6cd7630dd70c4d9ce Mon Sep 17 00:00:00 2001 From: korzhao Date: Sat, 25 Sep 2021 15:29:52 +0800 Subject: [PATCH 1308/2500] test/typeparam: add a test case for issue48617 For #48617 Change-Id: I6c00b7912c441ac323a0adede63b7d4a9ae6f92d Reviewed-on: https://go-review.googlesource.com/c/go/+/351858 Reviewed-by: Cuong Manh Le Reviewed-by: Dan Scales Trust: Cuong Manh Le Trust: Dan Scales Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot --- test/typeparam/issue48617.go | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 test/typeparam/issue48617.go diff --git a/test/typeparam/issue48617.go b/test/typeparam/issue48617.go new file mode 100644 index 0000000000..4b00570ba6 --- /dev/null +++ b/test/typeparam/issue48617.go @@ -0,0 +1,29 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type Foo[T any] interface { + CreateBar() Bar[T] +} + +type Bar[T any] func() Bar[T] + +func (f Bar[T]) CreateBar() Bar[T] { + return f +} + +func abc[T any]() { + var b Bar[T] = func() Bar[T] { + var b Bar[T] + return b + } + var _ Foo[T] = b() +} + +func main() { + abc[int]() +} -- GitLab From ff8a7e513bda9e89dfbde8ecefaa4514c11ec596 Mon Sep 17 00:00:00 2001 From: Leonard Wang Date: Mon, 20 Sep 2021 00:23:40 +0800 Subject: [PATCH 1309/2500] cmd/compile: print expression for invalid operation errors For #48472 Change-Id: I5072ebcf53e03fb5515c51a2ad01f02d72b30719 Reviewed-on: https://go-review.googlesource.com/c/go/+/350929 Reviewed-by: Robert Griesemer Trust: David Chase --- src/cmd/compile/internal/types2/expr.go | 2 +- .../internal/types2/testdata/fixedbugs/issue48472.go2 | 11 +++++++++++ src/go/types/expr.go | 2 +- src/go/types/testdata/fixedbugs/issue48472.go2 | 11 +++++++++++ 4 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue48472.go2 create mode 100644 src/go/types/testdata/fixedbugs/issue48472.go2 diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 12b7b6cd9f..90c80f9de0 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -1019,7 +1019,7 @@ func (check *Checker) binary(x *operand, e syntax.Expr, lhs, rhs syntax.Expr, op // only report an error if we have valid types // (otherwise we had an error reported elsewhere already) if x.typ != Typ[Invalid] && y.typ != Typ[Invalid] { - check.errorf(x, invalidOp+"mismatched types %s and %s", x.typ, y.typ) + check.errorf(x, invalidOp+"%s (mismatched types %s and %s)", e, x.typ, y.typ) } x.mode = invalid return diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48472.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48472.go2 new file mode 100644 index 0000000000..5fefcaf22b --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48472.go2 @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func g() { + var s string + var i int + _ = s /* ERROR invalid operation: s \+ i \(mismatched types string and int\) */ + i +} diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 007205a9fb..2fc5aa85d2 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -994,7 +994,7 @@ func (check *Checker) binary(x *operand, e ast.Expr, lhs, rhs ast.Expr, op token if e != nil { posn = e } - check.invalidOp(posn, _MismatchedTypes, "mismatched types %s and %s", x.typ, y.typ) + check.invalidOp(posn, _MismatchedTypes, "%s (mismatched types %s and %s)", e, x.typ, y.typ) } x.mode = invalid return diff --git a/src/go/types/testdata/fixedbugs/issue48472.go2 b/src/go/types/testdata/fixedbugs/issue48472.go2 new file mode 100644 index 0000000000..5fefcaf22b --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue48472.go2 @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func g() { + var s string + var i int + _ = s /* ERROR invalid operation: s \+ i \(mismatched types string and int\) */ + i +} -- GitLab From 54079dfd7fff6c61d41c4832c074e8231f235fc3 Mon Sep 17 00:00:00 2001 From: korzhao Date: Sat, 25 Sep 2021 04:42:57 +0800 Subject: [PATCH 1310/2500] cmd/compile: fix stencil call expression In CL 349613,we have supported types.IdentityStrict() that does strict type comparison. Therefore, OCONVNOP becomes a possible case in call.X.Op(). Fixes #48604 Change-Id: Ibab27ffcf09656e3380314662f05f38294c1c6ed Reviewed-on: https://go-review.googlesource.com/c/go/+/351857 Trust: Dan Scales Trust: David Chase Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 3 +++ test/typeparam/issue48604.go | 25 +++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 test/typeparam/issue48604.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index d5fb9f338c..bc142e6985 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1093,6 +1093,9 @@ func (subst *subster) node(n ir.Node) ir.Node { case ir.OCALL, ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER: transformCall(call) + case ir.OCONVNOP: + transformCall(call) + case ir.OFUNCINST: // A call with an OFUNCINST will get transformed // in stencil() once we have created & attached the diff --git a/test/typeparam/issue48604.go b/test/typeparam/issue48604.go new file mode 100644 index 0000000000..1babd3f864 --- /dev/null +++ b/test/typeparam/issue48604.go @@ -0,0 +1,25 @@ +// build -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type Foo[T any] interface { + CreateBar() Bar[T] +} + +type Bar[T any] func() Bar[T] + +func (f Bar[T]) CreateBar() Bar[T] { + return f +} + +func abc[R any]() { + var _ Foo[R] = Bar[R](nil)() +} + +func main() { + abc[int]() +} \ No newline at end of file -- GitLab From dac89a9d7fb253d30e5161e9ff6d80fbdfc79d75 Mon Sep 17 00:00:00 2001 From: Nigel Tao Date: Fri, 24 Sep 2021 10:43:55 +1000 Subject: [PATCH 1311/2500] image/draw: add RGBA64Image fast path for RGBA dst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should have been part of https://golang.org/cl/340049 but I overlooked it. That commit added fast path code when the destination image was *not* an *image.RGBA. This commit edits func drawRGBA. name old time/op new time/op delta RGBA1-4 5.11ms ± 1% 1.12ms ± 1% -78.01% (p=0.008 n=5+5) RGBA2-4 8.69ms ± 1% 2.98ms ± 1% -65.77% (p=0.008 n=5+5) Updates #44808. Updates #46395. Change-Id: I899d46d985634fc81ea47ff4f0d436630e8a961c Reviewed-on: https://go-review.googlesource.com/c/go/+/351852 Trust: Nigel Tao Reviewed-by: Dmitri Shuralyov --- src/image/draw/bench_test.go | 9 +++- src/image/draw/draw.go | 87 ++++++++++++++++++++++++++++++++++++ src/image/draw/draw_test.go | 84 +++++++++++++++++++++++++++++----- 3 files changed, 166 insertions(+), 14 deletions(-) diff --git a/src/image/draw/bench_test.go b/src/image/draw/bench_test.go index 831fd958ba..524ead2b8e 100644 --- a/src/image/draw/bench_test.go +++ b/src/image/draw/bench_test.go @@ -190,7 +190,8 @@ func bench(b *testing.B, dcm, scm, mcm color.Model, op Op) { } } -// The BenchmarkFoo functions exercise a drawFoo fast-path function in draw.go. +// The BenchmarkFoo and BenchmarkFooN functions exercise a drawFoo fast-path +// function in draw.go. func BenchmarkFillOver(b *testing.B) { bench(b, color.RGBAModel, nil, nil, Over) @@ -232,10 +233,14 @@ func BenchmarkGlyphOver(b *testing.B) { bench(b, color.RGBAModel, nil, color.AlphaModel, Over) } -func BenchmarkRGBA(b *testing.B) { +func BenchmarkRGBA1(b *testing.B) { bench(b, color.RGBAModel, color.RGBA64Model, nil, Src) } +func BenchmarkRGBA2(b *testing.B) { + bench(b, color.RGBAModel, color.RGBAModel, color.AlphaModel, Over) +} + func BenchmarkPalettedFill(b *testing.B) { bench(b, palette, nil, nil, Src) } diff --git a/src/image/draw/draw.go b/src/image/draw/draw.go index 4431028201..5e81ddc395 100644 --- a/src/image/draw/draw.go +++ b/src/image/draw/draw.go @@ -220,6 +220,8 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas y0, y1, dy = y1-1, y0-1, -1 } + // FALLBACK1.17 + // // Try the draw.RGBA64Image and image.RGBA64Image interfaces, part of the // standard library since Go 1.17. These are like the draw.Image and // image.Image interfaces but they can avoid allocations from converting @@ -295,6 +297,8 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas } } + // FALLBACK1.0 + // // If none of the faster code paths above apply, use the draw.Image and // image.Image interfaces, part of the standard library since Go 1.0. @@ -615,6 +619,89 @@ func drawRGBA(dst *image.RGBA, r image.Rectangle, src image.Image, sp image.Poin sx1 := sx0 + (x1 - x0) i0 := dst.PixOffset(x0, y0) di := dx * 4 + + // Try the image.RGBA64Image interface, part of the standard library since + // Go 1.17. + // + // This optimization is similar to how FALLBACK1.17 optimizes FALLBACK1.0 + // in DrawMask, except here the concrete type of dst is known to be + // *image.RGBA. + if src0, _ := src.(image.RGBA64Image); src0 != nil { + if mask == nil { + if op == Over { + for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy { + for i, sx, mx := i0, sx0, mx0; sx != sx1; i, sx, mx = i+di, sx+dx, mx+dx { + srgba := src0.RGBA64At(sx, sy) + d := dst.Pix[i : i+4 : i+4] + dr := uint32(d[0]) + dg := uint32(d[1]) + db := uint32(d[2]) + da := uint32(d[3]) + a := (m - uint32(srgba.A)) * 0x101 + d[0] = uint8((dr*a/m + uint32(srgba.R)) >> 8) + d[1] = uint8((dg*a/m + uint32(srgba.G)) >> 8) + d[2] = uint8((db*a/m + uint32(srgba.B)) >> 8) + d[3] = uint8((da*a/m + uint32(srgba.A)) >> 8) + } + i0 += dy * dst.Stride + } + } else { + for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy { + for i, sx, mx := i0, sx0, mx0; sx != sx1; i, sx, mx = i+di, sx+dx, mx+dx { + srgba := src0.RGBA64At(sx, sy) + d := dst.Pix[i : i+4 : i+4] + d[0] = uint8(srgba.R >> 8) + d[1] = uint8(srgba.G >> 8) + d[2] = uint8(srgba.B >> 8) + d[3] = uint8(srgba.A >> 8) + } + i0 += dy * dst.Stride + } + } + return + + } else if mask0, _ := mask.(image.RGBA64Image); mask0 != nil { + if op == Over { + for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy { + for i, sx, mx := i0, sx0, mx0; sx != sx1; i, sx, mx = i+di, sx+dx, mx+dx { + ma := uint32(mask0.RGBA64At(mx, my).A) + srgba := src0.RGBA64At(sx, sy) + d := dst.Pix[i : i+4 : i+4] + dr := uint32(d[0]) + dg := uint32(d[1]) + db := uint32(d[2]) + da := uint32(d[3]) + a := (m - (uint32(srgba.A) * ma / m)) * 0x101 + d[0] = uint8((dr*a + uint32(srgba.R)*ma) / m >> 8) + d[1] = uint8((dg*a + uint32(srgba.G)*ma) / m >> 8) + d[2] = uint8((db*a + uint32(srgba.B)*ma) / m >> 8) + d[3] = uint8((da*a + uint32(srgba.A)*ma) / m >> 8) + } + i0 += dy * dst.Stride + } + } else { + for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy { + for i, sx, mx := i0, sx0, mx0; sx != sx1; i, sx, mx = i+di, sx+dx, mx+dx { + ma := uint32(mask0.RGBA64At(mx, my).A) + srgba := src0.RGBA64At(sx, sy) + d := dst.Pix[i : i+4 : i+4] + d[0] = uint8(uint32(srgba.R) * ma / m >> 8) + d[1] = uint8(uint32(srgba.G) * ma / m >> 8) + d[2] = uint8(uint32(srgba.B) * ma / m >> 8) + d[3] = uint8(uint32(srgba.A) * ma / m >> 8) + } + i0 += dy * dst.Stride + } + } + return + } + } + + // Use the image.Image interface, part of the standard library since Go + // 1.0. + // + // This is similar to FALLBACK1.0 in DrawMask, except here the concrete + // type of dst is known to be *image.RGBA. for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy { for i, sx, mx := i0, sx0, mx0; sx != sx1; i, sx, mx = i+di, sx+dx, mx+dx { ma := uint32(m) diff --git a/src/image/draw/draw_test.go b/src/image/draw/draw_test.go index ea383a0172..8a51409526 100644 --- a/src/image/draw/draw_test.go +++ b/src/image/draw/draw_test.go @@ -66,6 +66,23 @@ func (p *slowestRGBA) PixOffset(x, y int) int { return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4 } +func convertToSlowestRGBA(m image.Image) *slowestRGBA { + if rgba, ok := m.(*image.RGBA); ok { + return &slowestRGBA{ + Pix: append([]byte(nil), rgba.Pix...), + Stride: rgba.Stride, + Rect: rgba.Rect, + } + } + rgba := image.NewRGBA(m.Bounds()) + Draw(rgba, rgba.Bounds(), m, m.Bounds().Min, Src) + return &slowestRGBA{ + Pix: rgba.Pix, + Stride: rgba.Stride, + Rect: rgba.Rect, + } +} + func init() { var p interface{} = (*slowestRGBA)(nil) if _, ok := p.(RGBA64Image); ok { @@ -138,6 +155,23 @@ func (p *slowerRGBA) PixOffset(x, y int) int { return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4 } +func convertToSlowerRGBA(m image.Image) *slowerRGBA { + if rgba, ok := m.(*image.RGBA); ok { + return &slowerRGBA{ + Pix: append([]byte(nil), rgba.Pix...), + Stride: rgba.Stride, + Rect: rgba.Rect, + } + } + rgba := image.NewRGBA(m.Bounds()) + Draw(rgba, rgba.Bounds(), m, m.Bounds().Min, Src) + return &slowerRGBA{ + Pix: rgba.Pix, + Stride: rgba.Stride, + Rect: rgba.Rect, + } +} + func init() { var p interface{} = (*slowerRGBA)(nil) if _, ok := p.(RGBA64Image); !ok { @@ -310,6 +344,32 @@ var drawTests = []drawTest{ {"grayAlphaSrc", vgradGray(), fillAlpha(192), Src, color.RGBA{102, 102, 102, 192}}, {"grayNil", vgradGray(), nil, Over, color.RGBA{136, 136, 136, 255}}, {"grayNilSrc", vgradGray(), nil, Src, color.RGBA{136, 136, 136, 255}}, + // Same again, but with a slowerRGBA source. + {"graySlower", convertToSlowerRGBA(vgradGray()), fillAlpha(255), + Over, color.RGBA{136, 136, 136, 255}}, + {"graySrcSlower", convertToSlowerRGBA(vgradGray()), fillAlpha(255), + Src, color.RGBA{136, 136, 136, 255}}, + {"grayAlphaSlower", convertToSlowerRGBA(vgradGray()), fillAlpha(192), + Over, color.RGBA{136, 102, 102, 255}}, + {"grayAlphaSrcSlower", convertToSlowerRGBA(vgradGray()), fillAlpha(192), + Src, color.RGBA{102, 102, 102, 192}}, + {"grayNilSlower", convertToSlowerRGBA(vgradGray()), nil, + Over, color.RGBA{136, 136, 136, 255}}, + {"grayNilSrcSlower", convertToSlowerRGBA(vgradGray()), nil, + Src, color.RGBA{136, 136, 136, 255}}, + // Same again, but with a slowestRGBA source. + {"graySlowest", convertToSlowestRGBA(vgradGray()), fillAlpha(255), + Over, color.RGBA{136, 136, 136, 255}}, + {"graySrcSlowest", convertToSlowestRGBA(vgradGray()), fillAlpha(255), + Src, color.RGBA{136, 136, 136, 255}}, + {"grayAlphaSlowest", convertToSlowestRGBA(vgradGray()), fillAlpha(192), + Over, color.RGBA{136, 102, 102, 255}}, + {"grayAlphaSrcSlowest", convertToSlowestRGBA(vgradGray()), fillAlpha(192), + Src, color.RGBA{102, 102, 102, 192}}, + {"grayNilSlowest", convertToSlowestRGBA(vgradGray()), nil, + Over, color.RGBA{136, 136, 136, 255}}, + {"grayNilSrcSlowest", convertToSlowestRGBA(vgradGray()), nil, + Src, color.RGBA{136, 136, 136, 255}}, // Uniform mask (100%, 75%, nil) and variable CMYK source. // At (x, y) == (8, 8): // The destination pixel is {136, 0, 0, 255}. @@ -327,6 +387,16 @@ var drawTests = []drawTest{ // The mask pixel's alpha is 102, or 40%. {"generic", fillBlue(255), vgradAlpha(192), Over, color.RGBA{81, 0, 102, 255}}, {"genericSrc", fillBlue(255), vgradAlpha(192), Src, color.RGBA{0, 0, 102, 102}}, + // Same again, but with a slowerRGBA mask. + {"genericSlower", fillBlue(255), convertToSlowerRGBA(vgradAlpha(192)), + Over, color.RGBA{81, 0, 102, 255}}, + {"genericSrcSlower", fillBlue(255), convertToSlowerRGBA(vgradAlpha(192)), + Src, color.RGBA{0, 0, 102, 102}}, + // Same again, but with a slowestRGBA mask. + {"genericSlowest", fillBlue(255), convertToSlowestRGBA(vgradAlpha(192)), + Over, color.RGBA{81, 0, 102, 255}}, + {"genericSrcSlowest", fillBlue(255), convertToSlowestRGBA(vgradAlpha(192)), + Src, color.RGBA{0, 0, 102, 102}}, } func makeGolden(dst image.Image, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op) image.Image { @@ -399,19 +469,9 @@ func TestDraw(t *testing.T) { // result, in terms of final pixel RGBA values. switch i { case 1: - d := dst.(*image.RGBA) - dst = &slowerRGBA{ - Pix: d.Pix, - Stride: d.Stride, - Rect: d.Rect, - } + dst = convertToSlowerRGBA(dst) case 2: - d := dst.(*image.RGBA) - dst = &slowestRGBA{ - Pix: d.Pix, - Stride: d.Stride, - Rect: d.Rect, - } + dst = convertToSlowestRGBA(dst) } // Draw the (src, mask, op) onto a copy of dst using a slow but obviously correct implementation. -- GitLab From 6e5dd0b59bd1380542666d12eaf9f415dea162f6 Mon Sep 17 00:00:00 2001 From: Lynn Boger Date: Wed, 22 Sep 2021 14:50:29 -0500 Subject: [PATCH 1312/2500] runtime: add runtime changes for register ABI on ppc64x This adds the changes for the register ABI in the runtime functions for ppc64x: - Add spill functions used by runtime - Add ABIInternal to functions Some changes were needed to the stubs files due to vet issues when compiling for linux/ppc64. Change-Id: I010ddbc774ed4f22e1f9d77833bd55b919d95c99 Reviewed-on: https://go-review.googlesource.com/c/go/+/351590 Trust: Lynn Boger Run-TryBot: Lynn Boger TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/asm_ppc64x.s | 222 +++++++++++++++--- src/runtime/stubs_ppc64.go | 6 +- .../{stubs_ppc64le.go => stubs_ppc64x.go} | 8 + 3 files changed, 192 insertions(+), 44 deletions(-) rename src/runtime/{stubs_ppc64le.go => stubs_ppc64x.go} (56%) diff --git a/src/runtime/asm_ppc64x.s b/src/runtime/asm_ppc64x.s index 18edb67988..2810324ce2 100644 --- a/src/runtime/asm_ppc64x.s +++ b/src/runtime/asm_ppc64x.s @@ -103,7 +103,7 @@ nocgo: MOVD R0, 0(R0) RET -DATA runtime·mainPC+0(SB)/8,$runtime·main(SB) +DATA runtime·mainPC+0(SB)/8,$runtime·main(SB) GLOBL runtime·mainPC(SB),RODATA,$8 TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0 @@ -165,8 +165,14 @@ TEXT gogo<>(SB), NOSPLIT|NOFRAME, $0 // Switch to m->g0's stack, call fn(g). // Fn must never return. It should gogo(&g->sched) // to keep running g. -TEXT runtime·mcall(SB), NOSPLIT|NOFRAME, $0-8 +TEXT runtime·mcall(SB), NOSPLIT|NOFRAME, $0-8 // Save caller state in g->sched + // R11 should be safe across save_g?? +#ifdef GOEXPERIMENT_regabiargs + MOVD R3, R11 +#else + MOVD fn+0(FP), R11 +#endif MOVD R1, (g_sched+gobuf_sp)(g) MOVD LR, R31 MOVD R31, (g_sched+gobuf_pc)(g) @@ -180,10 +186,11 @@ TEXT runtime·mcall(SB), NOSPLIT|NOFRAME, $0-8 CMP g, R3 BNE 2(PC) BR runtime·badmcall(SB) - MOVD fn+0(FP), R11 // context MOVD 0(R11), R12 // code pointer MOVD R12, CTR MOVD (g_sched+gobuf_sp)(g), R1 // sp = m->g0->sched.sp + // Don't need to do anything special for regabiargs here + // R3 is g; stack is set anyway MOVDU R3, -8(R1) MOVDU R0, -8(R1) MOVDU R0, -8(R1) @@ -428,6 +435,8 @@ callfn: \ BNE 2(PC) \ MOVD R0, 0(R0) \ #endif \ + MOVD regArgs+40(FP), R20; \ + BL runtime·unspillArgs(SB); \ MOVD (R11), R12; \ MOVD R12, CTR; \ PCDATA $PCDATA_StackMapIndex, $0; \ @@ -436,6 +445,8 @@ callfn: \ MOVD 24(R1), R2; \ #endif \ /* copy return values back */ \ + MOVD regArgs+40(FP), R20; \ + BL runtime·spillArgs(SB); \ MOVD stackArgsType+0(FP), R7; \ MOVD stackArgs+16(FP), R3; \ MOVWZ stackArgsSize+24(FP), R4; \ @@ -452,11 +463,12 @@ callfn: \ // to reflectcallmove. It does not follow the Go ABI; it expects its // arguments in registers. TEXT callRet<>(SB), NOSPLIT, $40-0 + NO_LOCAL_POINTERS MOVD R7, FIXED_FRAME+0(R1) MOVD R3, FIXED_FRAME+8(R1) MOVD R5, FIXED_FRAME+16(R1) MOVD R4, FIXED_FRAME+24(R1) - MOVD $0, FIXED_FRAME+32(R1) + MOVD R20, FIXED_FRAME+32(R1) BL runtime·reflectcallmove(SB) RET @@ -777,6 +789,71 @@ TEXT runtime·cputicks(SB),NOSPLIT,$0-8 MOVD R3, ret+0(FP) RET +#ifdef GOEXPERIMENT_regabireflect +// spillArgs stores return values from registers to a *internal/abi.RegArgs in R20. +TEXT runtime·spillArgs(SB),NOSPLIT,$0-0 + MOVD R3, 0(R20) + MOVD R4, 8(R20) + MOVD R5, 16(R20) + MOVD R6, 24(R20) + MOVD R7, 32(R20) + MOVD R8, 40(R20) + MOVD R9, 48(R20) + MOVD R10, 56(R20) + MOVD R14, 64(R20) + MOVD R15, 72(R20) + MOVD R16, 80(R20) + MOVD R17, 88(R20) + FMOVD F1, 96(R20) + FMOVD F2, 104(R20) + FMOVD F3, 112(R20) + FMOVD F4, 120(R20) + FMOVD F5, 128(R20) + FMOVD F6, 136(R20) + FMOVD F7, 144(R20) + FMOVD F8, 152(R20) + FMOVD F9, 160(R20) + FMOVD F10, 168(R20) + FMOVD F11, 176(R20) + FMOVD F12, 184(R20) + RET + +// unspillArgs loads args into registers from a *internal/abi.RegArgs in R20. +TEXT runtime·unspillArgs(SB),NOSPLIT,$0-0 + MOVD 0(R20), R3 + MOVD 8(R20), R4 + MOVD 16(R20), R5 + MOVD 24(R20), R6 + MOVD 32(R20), R7 + MOVD 40(R20), R8 + MOVD 48(R20), R9 + MOVD 56(R20), R10 + MOVD 64(R20), R14 + MOVD 72(R20), R15 + MOVD 80(R20), R16 + MOVD 88(R20), R17 + FMOVD 96(R20), F1 + FMOVD 104(R20), F2 + FMOVD 112(R20), F3 + FMOVD 120(R20), F4 + FMOVD 128(R20), F5 + FMOVD 136(R20), F6 + FMOVD 144(R20), F7 + FMOVD 152(R20), F8 + FMOVD 160(R20), F9 + FMOVD 168(R20), F10 + FMOVD 176(R20), F11 + FMOVD 184(R20), F12 + RET +#else + +TEXT runtime·spillArgs(SB),NOSPLIT,$0-0 + RET + +TEXT runtime·unspillArgs(SB),NOSPLIT,$0-0 + RET +#endif + // AES hashing not implemented for ppc64 TEXT runtime·memhash(SB),NOSPLIT|NOFRAME,$0-32 JMP runtime·memhashFallback(SB) @@ -863,7 +940,7 @@ TEXT ·checkASM(SB),NOSPLIT,$0-1 // It clobbers condition codes. // It does not clobber R0 through R17 (except special registers), // but may clobber any other register, *including* R31. -TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$112 +TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$112 // The standard prologue clobbers R31. // We use R18 and R19 as scratch registers. MOVD g_m(g), R18 @@ -932,71 +1009,138 @@ flush: // in the caller's stack frame. These stubs write the args into that stack space and // then tail call to the corresponding runtime handler. // The tail call makes these stubs disappear in backtraces. -TEXT runtime·panicIndex(SB),NOSPLIT,$0-16 +TEXT runtime·panicIndex(SB),NOSPLIT,$0-16 +#ifndef GOEXPERIMENT_regabiargs MOVD R3, x+0(FP) MOVD R4, y+8(FP) - JMP runtime·goPanicIndex(SB) -TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16 +#endif + JMP runtime·goPanicIndex(SB) +TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16 +#ifndef GOEXPERIMENT_regabiargs MOVD R3, x+0(FP) MOVD R4, y+8(FP) - JMP runtime·goPanicIndexU(SB) -TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16 +#endif + JMP runtime·goPanicIndexU(SB) +TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16 +#ifdef GOEXPERIMENT_regabiargs + MOVD R4, R3 + MOVD R5, R4 +#else MOVD R4, x+0(FP) MOVD R5, y+8(FP) - JMP runtime·goPanicSliceAlen(SB) -TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-16 +#endif + JMP runtime·goPanicSliceAlen(SB) +TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-16 +#ifdef GOEXPERIMENT_regabiargs + MOVD R4, R3 + MOVD R5, R4 +#else MOVD R4, x+0(FP) MOVD R5, y+8(FP) - JMP runtime·goPanicSliceAlenU(SB) -TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-16 +#endif + JMP runtime·goPanicSliceAlenU(SB) +TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-16 +#ifdef GOEXPERIMENT_regabiargs + MOVD R4, R3 + MOVD R5, R4 +#else MOVD R4, x+0(FP) MOVD R5, y+8(FP) - JMP runtime·goPanicSliceAcap(SB) -TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16 +#endif + JMP runtime·goPanicSliceAcap(SB) +TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16 +#ifdef GOEXPERIMENT_regabiargs + MOVD R4, R3 + MOVD R5, R4 +#else MOVD R4, x+0(FP) MOVD R5, y+8(FP) - JMP runtime·goPanicSliceAcapU(SB) -TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16 +#endif + JMP runtime·goPanicSliceAcapU(SB) +TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16 +#ifndef GOEXPERIMENT_regabiargs MOVD R3, x+0(FP) MOVD R4, y+8(FP) - JMP runtime·goPanicSliceB(SB) -TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16 +#endif + JMP runtime·goPanicSliceB(SB) +TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16 +#ifndef GOEXPERIMENT_regabiargs MOVD R3, x+0(FP) MOVD R4, y+8(FP) - JMP runtime·goPanicSliceBU(SB) -TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16 +#endif + JMP runtime·goPanicSliceBU(SB) +TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16 +#ifdef GOEXPERIMENT_regabiargs + MOVD R5, R3 + MOVD R6, R4 +#else MOVD R5, x+0(FP) MOVD R6, y+8(FP) - JMP runtime·goPanicSlice3Alen(SB) -TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-16 +#endif + JMP runtime·goPanicSlice3Alen(SB) +TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-16 +#ifdef GOEXPERIMENT_regabiargs + MOVD R5, R3 + MOVD R6, R4 +#else MOVD R5, x+0(FP) MOVD R6, y+8(FP) - JMP runtime·goPanicSlice3AlenU(SB) -TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-16 +#endif + JMP runtime·goPanicSlice3AlenU(SB) +TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-16 +#ifdef GOEXPERIMENT_regabiargs + MOVD R5, R3 + MOVD R6, R4 +#else MOVD R5, x+0(FP) MOVD R6, y+8(FP) - JMP runtime·goPanicSlice3Acap(SB) -TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-16 +#endif + JMP runtime·goPanicSlice3Acap(SB) +TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-16 +#ifdef GOEXPERIMENT_regabiargs + MOVD R5, R3 + MOVD R6, R4 +#else MOVD R5, x+0(FP) MOVD R6, y+8(FP) - JMP runtime·goPanicSlice3AcapU(SB) -TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-16 +#endif + JMP runtime·goPanicSlice3AcapU(SB) +TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-16 +#ifdef GOEXPERIMENT_regabiargs + MOVD R4, R3 + MOVD R5, R4 +#else MOVD R4, x+0(FP) MOVD R5, y+8(FP) - JMP runtime·goPanicSlice3B(SB) -TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16 +#endif + JMP runtime·goPanicSlice3B(SB) +TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16 +#ifdef GOEXPERIMENT_regabiargs + MOVD R4, R3 + MOVD R5, R4 +#else MOVD R4, x+0(FP) MOVD R5, y+8(FP) - JMP runtime·goPanicSlice3BU(SB) -TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16 +#endif + JMP runtime·goPanicSlice3BU(SB) +TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16 +#ifndef GOEXPERIMENT_regabiargs MOVD R3, x+0(FP) MOVD R4, y+8(FP) - JMP runtime·goPanicSlice3C(SB) -TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16 +#endif + JMP runtime·goPanicSlice3C(SB) +TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16 +#ifndef GOEXPERIMENT_regabiargs MOVD R3, x+0(FP) MOVD R4, y+8(FP) - JMP runtime·goPanicSlice3CU(SB) -TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-16 +#endif + JMP runtime·goPanicSlice3CU(SB) +TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-16 +#ifdef GOEXPERIMENT_regabiargs + MOVD R5, R3 + MOVD R6, R4 +#else MOVD R5, x+0(FP) MOVD R6, y+8(FP) - JMP runtime·goPanicSliceConvert(SB) +#endif + JMP runtime·goPanicSliceConvert(SB) diff --git a/src/runtime/stubs_ppc64.go b/src/runtime/stubs_ppc64.go index f692947109..3895973f7c 100644 --- a/src/runtime/stubs_ppc64.go +++ b/src/runtime/stubs_ppc64.go @@ -7,10 +7,6 @@ package runtime -// Called from assembly only; declared for go vet. -func load_g() -func save_g() -func reginit() - +// This is needed for vet //go:noescape func callCgoSigaction(sig uintptr, new, old *sigactiont) int32 diff --git a/src/runtime/stubs_ppc64le.go b/src/runtime/stubs_ppc64x.go similarity index 56% rename from src/runtime/stubs_ppc64le.go rename to src/runtime/stubs_ppc64x.go index 5b733136e3..2c647ea672 100644 --- a/src/runtime/stubs_ppc64le.go +++ b/src/runtime/stubs_ppc64x.go @@ -2,9 +2,17 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ppc64le || ppc64 +// +build ppc64le ppc64 + package runtime // Called from assembly only; declared for go vet. func load_g() func save_g() func reginit() + +// Spills/loads arguments in registers to/from an internal/abi.RegArgs +// respectively. Does not follow the Go ABI. +func spillArgs() +func unspillArgs() -- GitLab From 516d75ccf1879cba1277cc92d0c6b61725b4aab5 Mon Sep 17 00:00:00 2001 From: "Paul E. Murphy" Date: Mon, 30 Aug 2021 11:56:58 -0500 Subject: [PATCH 1313/2500] cmd/internal/obj/ppc64: add a test for long branch fixups Cribbed and modified from arm64, verify each transformation rewrites a too-far conditional branch as expected. Change-Id: I87d35085158ed7d7478aa9725b273401fcd0bd01 Reviewed-on: https://go-review.googlesource.com/c/go/+/347049 Trust: David Chase Reviewed-by: Lynn Boger --- src/cmd/internal/obj/ppc64/asm_test.go | 127 +++++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/src/cmd/internal/obj/ppc64/asm_test.go b/src/cmd/internal/obj/ppc64/asm_test.go index b851d3c86b..60c5f346e0 100644 --- a/src/cmd/internal/obj/ppc64/asm_test.go +++ b/src/cmd/internal/obj/ppc64/asm_test.go @@ -5,6 +5,8 @@ package ppc64 import ( + "bytes" + "fmt" "internal/testenv" "io/ioutil" "os" @@ -35,6 +37,131 @@ ADD $4, R8 RET ` +var platformEnvs = [][]string{ + {"GOOS=aix", "GOARCH=ppc64"}, + {"GOOS=linux", "GOARCH=ppc64"}, + {"GOOS=linux", "GOARCH=ppc64le"}, +} + +// TestLarge generates a very large file to verify that large +// program builds successfully, and branches which exceed the +// range of BC are rewritten to reach. +func TestLarge(t *testing.T) { + if testing.Short() { + t.Skip("Skip in short mode") + } + testenv.MustHaveGoBuild(t) + + dir, err := ioutil.TempDir("", "testlarge") + if err != nil { + t.Fatalf("could not create directory: %v", err) + } + defer os.RemoveAll(dir) + + // A few interesting test cases for long conditional branch fixups + tests := []struct { + jmpinsn string + backpattern []string + fwdpattern []string + }{ + // Test the interesting cases of conditional branch rewrites for too-far targets. Simple conditional + // branches can be made to reach with one JMP insertion, compound conditionals require two. + // + // TODO: BI is interpreted as a register (the R???x/R0 should be $x) + // beq <-> bne conversion (insert one jump) + {"BEQ", + []string{``, + `0x20030 131120\s\(.*\)\tBC\t\$4,\sR\?\?\?2,\s131128`, + `0x20034 131124\s\(.*\)\tJMP\t0`}, + []string{``, + `0x0000 00000\s\(.*\)\tBC\t\$4,\sR\?\?\?2,\s8`, + `0x0004 00004\s\(.*\)\tJMP\t131128`}, + }, + {"BNE", + []string{``, + `0x20030 131120\s\(.*\)\tBC\t\$12,\sR\?\?\?2,\s131128`, + `0x20034 131124\s\(.*\)\tJMP\t0`}, + []string{``, + `0x0000 00000\s\(.*\)\tBC\t\$12,\sR\?\?\?2,\s8`, + `0x0004 00004\s\(.*\)\tJMP\t131128`}}, + // bdnz (BC 16,0,tgt) <-> bdz (BC 18,0,+4) conversion (insert one jump) + {"BC 16,0,", + []string{``, + `0x20030 131120\s\(.*\)\tBC\t\$18,\s131128`, + `0x20034 131124\s\(.*\)\tJMP\t0`}, + []string{``, + `0x0000 00000\s\(.*\)\tBC\t\$18,\s8`, + `0x0004 00004\s\(.*\)\tJMP\t131128`}}, + {"BC 18,0,", + []string{``, + `0x20030 131120\s\(.*\)\tBC\t\$16,\s131128`, + `0x20034 131124\s\(.*\)\tJMP\t0`}, + []string{``, + `0x0000 00000\s\(.*\)\tBC\t\$16,\s8`, + `0x0004 00004\s\(.*\)\tJMP\t131128`}}, + // bdnzt (BC 8,0,tgt) <-> bdnzt (BC 8,0,+4) conversion (insert two jumps) + {"BC 8,0,", + []string{``, + `0x20034 131124\s\(.*\)\tBC\t\$8,\sR0,\s131132`, + `0x20038 131128\s\(.*\)\tJMP\t131136`, + `0x2003c 131132\s\(.*\)\tJMP\t0\n`}, + []string{``, + `0x0000 00000\s\(.*\)\tBC\t\$8,\sR0,\s8`, + `0x0004 00004\s\(.*\)\tJMP\t12`, + `0x0008 00008\s\(.*\)\tJMP\t131136\n`}}, + } + + for _, test := range tests { + // generate a very large function + buf := bytes.NewBuffer(make([]byte, 0, 7000000)) + gen(buf, test.jmpinsn) + + tmpfile := filepath.Join(dir, "x.s") + err = ioutil.WriteFile(tmpfile, buf.Bytes(), 0644) + if err != nil { + t.Fatalf("can't write output: %v\n", err) + } + + // Test on all supported ppc64 platforms + for _, platenv := range platformEnvs { + cmd := exec.Command(testenv.GoToolPath(t), "tool", "asm", "-S", "-o", filepath.Join(dir, "test.o"), tmpfile) + cmd.Env = append(os.Environ(), platenv...) + out, err := cmd.CombinedOutput() + if err != nil { + t.Errorf("Assemble failed (%v): %v, output: %s", platenv, err, out) + } + matched, err := regexp.MatchString(strings.Join(test.fwdpattern, "\n\t*"), string(out)) + if err != nil { + t.Fatal(err) + } + if !matched { + t.Errorf("Failed to detect long foward BC fixup in (%v):%s\n", platenv, out) + } + matched, err = regexp.MatchString(strings.Join(test.backpattern, "\n\t*"), string(out)) + if err != nil { + t.Fatal(err) + } + if !matched { + t.Errorf("Failed to detect long backward BC fixup in (%v):%s\n", platenv, out) + } + } + } +} + +// gen generates a very large program with a very long forward and backwards conditional branch. +func gen(buf *bytes.Buffer, jmpinsn string) { + fmt.Fprintln(buf, "TEXT f(SB),0,$0-0") + fmt.Fprintln(buf, "label_start:") + fmt.Fprintln(buf, jmpinsn, "label_end") + for i := 0; i < (1<<15 + 10); i++ { + fmt.Fprintln(buf, "MOVD R0, R1") + } + fmt.Fprintln(buf, jmpinsn, "label_start") + fmt.Fprintln(buf, "label_end:") + fmt.Fprintln(buf, "MOVD R0, R1") + fmt.Fprintln(buf, "RET") +} + // TestPCalign generates two asm files containing the // PCALIGN directive, to verify correct values are and // accepted, and incorrect values are flagged in error. -- GitLab From d5cfba087f4947ac25714f925e610d0d3575d05e Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Mon, 27 Sep 2021 04:20:34 +0000 Subject: [PATCH 1314/2500] cmd/go: remove references to 'go help fuzz' Fixes: #48623 Change-Id: Idab917b90ceb332cf49b6ca2a6b79be97ac56e18 GitHub-Last-Rev: 3143ce8b95e70a0466c836ce9be3e13a3e85c12e GitHub-Pull-Request: golang/go#48640 Reviewed-on: https://go-review.googlesource.com/c/go/+/352313 Reviewed-by: Bryan C. Mills Trust: Bryan C. Mills Trust: Jay Conrod Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot --- src/cmd/go/alldocs.go | 2 -- src/cmd/go/internal/test/test.go | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 02d2afc582..7be673b290 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -1566,8 +1566,6 @@ // in no time at all,so a successful package test result will be cached and // reused regardless of -timeout setting. // -// Run 'go help fuzz' for details around how the go command handles fuzz targets. -// // In addition to the build flags, the flags handled by 'go test' itself are: // // -args diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 518555ecba..7c6f109cc5 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -132,8 +132,6 @@ variables are unchanged. A cached test result is treated as executing in no time at all,so a successful package test result will be cached and reused regardless of -timeout setting. -Run 'go help fuzz' for details around how the go command handles fuzz targets. - In addition to the build flags, the flags handled by 'go test' itself are: -args -- GitLab From 078247a4075650aa4eaf9b9e7fab3b4b70b27a5f Mon Sep 17 00:00:00 2001 From: jiahua wang Date: Fri, 24 Sep 2021 10:07:44 +0800 Subject: [PATCH 1315/2500] bytes: add example for (*Buffer).Next Change-Id: Ic0a97fd7bb89865448e436e5c092415a29d8badf Reviewed-on: https://go-review.googlesource.com/c/go/+/352009 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: David Chase --- src/bytes/example_test.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/bytes/example_test.go b/src/bytes/example_test.go index ae93202b57..d0d4dd2c2d 100644 --- a/src/bytes/example_test.go +++ b/src/bytes/example_test.go @@ -54,6 +54,19 @@ func ExampleBuffer_Len() { // Output: 5 } +func ExampleBuffer_Next() { + var b bytes.Buffer + b.Grow(64) + b.Write([]byte("abcde")) + fmt.Printf("%s\n", string(b.Next(2))) + fmt.Printf("%s\n", string(b.Next(2))) + fmt.Printf("%s", string(b.Next(2))) + // Output: + // ab + // cd + // e +} + func ExampleCompare() { // Interpret Compare's result by comparing it to zero. var a, b []byte -- GitLab From b88a6882a5411d705e4f05d300668f157f476749 Mon Sep 17 00:00:00 2001 From: DQNEO Date: Sat, 18 Sep 2021 23:24:07 +0900 Subject: [PATCH 1316/2500] cmd/internal/obj: fix wording in a comment Change-Id: I9921ba5c29ada6ff06d147f6d9b46a29101c449c Reviewed-on: https://go-review.googlesource.com/c/go/+/350694 Reviewed-by: Ian Lance Taylor Trust: David Chase --- src/cmd/internal/obj/link.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index 592d2a655b..9be173ff98 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -283,7 +283,7 @@ func (a *Addr) SetConst(v int64) { // Each Prog is charged to a specific source line in the debug information, // specified by Pos.Line(). // Every Prog has a Ctxt field that defines its context. -// For performance reasons, Progs usually are usually bulk allocated, cached, and reused; +// For performance reasons, Progs are usually bulk allocated, cached, and reused; // those bulk allocators should always be used, rather than new(Prog). // // The other fields not yet mentioned are for use by the back ends and should -- GitLab From f9a53b6b4d6d2a036e80ff79cc7bc34d788cd1c0 Mon Sep 17 00:00:00 2001 From: jiahua wang Date: Wed, 22 Sep 2021 22:32:55 +0800 Subject: [PATCH 1317/2500] encoding/base32: Add examples for Encode/Decode Updates golang/go#37595 Change-Id: I7568e7416d5504e9dc67061c79f66e3a0d597dee Reviewed-on: https://go-review.googlesource.com/c/go/+/351470 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: David Chase --- src/encoding/base32/example_test.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/encoding/base32/example_test.go b/src/encoding/base32/example_test.go index 2a302d88da..251624f0bd 100644 --- a/src/encoding/base32/example_test.go +++ b/src/encoding/base32/example_test.go @@ -20,6 +20,15 @@ func ExampleEncoding_EncodeToString() { // MFXHSIBLEBXWYZBAEYQGIYLUME====== } +func ExampleEncoding_Encode() { + data := []byte("Hello, world!") + dst := make([]byte, base32.StdEncoding.EncodedLen(len(data))) + base32.StdEncoding.Encode(dst, data) + fmt.Println(string(dst)) + // Output: + // JBSWY3DPFQQHO33SNRSCC=== +} + func ExampleEncoding_DecodeString() { str := "ONXW2ZJAMRQXIYJAO5UXI2BAAAQGC3TEEDX3XPY=" data, err := base32.StdEncoding.DecodeString(str) @@ -32,6 +41,20 @@ func ExampleEncoding_DecodeString() { // "some data with \x00 and \ufeff" } +func ExampleEncoding_Decode() { + str := "JBSWY3DPFQQHO33SNRSCC===" + dst := make([]byte, base32.StdEncoding.DecodedLen(len(str))) + n, err := base32.StdEncoding.Decode(dst, []byte(str)) + if err != nil { + fmt.Println("decode error:", err) + return + } + dst = dst[:n] + fmt.Printf("%q\n", dst) + // Output: + // "Hello, world!" +} + func ExampleNewEncoder() { input := []byte("foo\x00bar") encoder := base32.NewEncoder(base32.StdEncoding, os.Stdout) -- GitLab From ecac3512e5454bc8d778a07d641e11579e9d7a4b Mon Sep 17 00:00:00 2001 From: nimelehin Date: Fri, 24 Sep 2021 21:11:21 +0300 Subject: [PATCH 1318/2500] cmd/compile: clean up remnants of amd64p32 in OnesCount Change-Id: Ie90d8dd3f644a96cda706c6a5286e99042e070bb Reviewed-on: https://go-review.googlesource.com/c/go/+/352129 Reviewed-by: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Trust: David Chase --- src/cmd/compile/internal/ssagen/ssa.go | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 9746fbd316..baf7242f4a 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -4503,7 +4503,7 @@ func InitTables() { sys.AMD64, sys.ARM64, sys.S390X, sys.PPC64, sys.Wasm) alias("math/bits", "RotateLeft", "math/bits", "RotateLeft64", p8...) - makeOnesCountAMD64 := func(op64 ssa.Op, op32 ssa.Op) func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { + makeOnesCountAMD64 := func(op ssa.Op) func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { v := s.entryNewValue0A(ssa.OpHasCPUFeature, types.Types[types.TBOOL], ir.Syms.X86HasPOPCNT) b := s.endBlock() @@ -4518,10 +4518,6 @@ func InitTables() { // We have the intrinsic - use it directly. s.startBlock(bTrue) - op := op64 - if s.config.PtrSize == 4 { - op = op32 - } s.vars[n] = s.newValue1(op, types.Types[types.TINT], args[0]) s.endBlock().AddEdgeTo(bEnd) @@ -4536,7 +4532,7 @@ func InitTables() { } } addF("math/bits", "OnesCount64", - makeOnesCountAMD64(ssa.OpPopCount64, ssa.OpPopCount64), + makeOnesCountAMD64(ssa.OpPopCount64), sys.AMD64) addF("math/bits", "OnesCount64", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { @@ -4544,7 +4540,7 @@ func InitTables() { }, sys.PPC64, sys.ARM64, sys.S390X, sys.Wasm) addF("math/bits", "OnesCount32", - makeOnesCountAMD64(ssa.OpPopCount32, ssa.OpPopCount32), + makeOnesCountAMD64(ssa.OpPopCount32), sys.AMD64) addF("math/bits", "OnesCount32", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { @@ -4552,7 +4548,7 @@ func InitTables() { }, sys.PPC64, sys.ARM64, sys.S390X, sys.Wasm) addF("math/bits", "OnesCount16", - makeOnesCountAMD64(ssa.OpPopCount16, ssa.OpPopCount16), + makeOnesCountAMD64(ssa.OpPopCount16), sys.AMD64) addF("math/bits", "OnesCount16", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { @@ -4565,7 +4561,7 @@ func InitTables() { }, sys.S390X, sys.PPC64, sys.Wasm) addF("math/bits", "OnesCount", - makeOnesCountAMD64(ssa.OpPopCount64, ssa.OpPopCount32), + makeOnesCountAMD64(ssa.OpPopCount64), sys.AMD64) addF("math/bits", "Mul64", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { -- GitLab From 40fce515f98c0c16c361b1c85a4e638fd5b63491 Mon Sep 17 00:00:00 2001 From: Lynn Boger Date: Mon, 27 Sep 2021 08:10:20 -0500 Subject: [PATCH 1319/2500] runtime: mark race functions as ABIInternal This adds ABIInternal to the race function declarations. Change-Id: I99f8a310972ff09b4d56eedbcc6e9609bab0f224 Reviewed-on: https://go-review.googlesource.com/c/go/+/352369 Trust: Lynn Boger Run-TryBot: Lynn Boger TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/race_ppc64le.s | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/runtime/race_ppc64le.s b/src/runtime/race_ppc64le.s index 963e57099c..625c81a255 100644 --- a/src/runtime/race_ppc64le.s +++ b/src/runtime/race_ppc64le.s @@ -43,8 +43,12 @@ // func runtime·RaceRead(addr uintptr) // Called from instrumented Go code -TEXT runtime·raceread(SB), NOSPLIT, $0-8 +TEXT runtime·raceread(SB), NOSPLIT, $0-8 +#ifndef GOEXPERIMENT_regabiargs MOVD addr+0(FP), R4 +#else + MOVD R3, R4 +#endif MOVD LR, R5 // caller of this? // void __tsan_read(ThreadState *thr, void *addr, void *pc); MOVD $__tsan_read(SB), R8 @@ -64,8 +68,12 @@ TEXT runtime·racereadpc(SB), NOSPLIT, $0-24 // func runtime·RaceWrite(addr uintptr) // Called from instrumented Go code -TEXT runtime·racewrite(SB), NOSPLIT, $0-8 +TEXT runtime·racewrite(SB), NOSPLIT, $0-8 +#ifndef GOEXPERIMENT_regabiargs MOVD addr+0(FP), R4 +#else + MOVD R3, R4 +#endif MOVD LR, R5 // caller has set LR via BL inst // void __tsan_write(ThreadState *thr, void *addr, void *pc); MOVD $__tsan_write(SB), R8 @@ -85,9 +93,14 @@ TEXT runtime·racewritepc(SB), NOSPLIT, $0-24 // func runtime·RaceReadRange(addr, size uintptr) // Called from instrumented Go code. -TEXT runtime·racereadrange(SB), NOSPLIT, $0-16 +TEXT runtime·racereadrange(SB), NOSPLIT, $0-16 +#ifndef GOEXPERIMENT_regabiargs MOVD addr+0(FP), R4 MOVD size+8(FP), R5 +#else + MOVD R4, R5 + MOVD R3, R4 +#endif MOVD LR, R6 // void __tsan_read_range(ThreadState *thr, void *addr, uintptr size, void *pc); MOVD $__tsan_read_range(SB), R8 @@ -108,9 +121,14 @@ TEXT runtime·RaceReadRange(SB), NOSPLIT, $0-16 // func runtime·RaceWriteRange(addr, size uintptr) // Called from instrumented Go code. -TEXT runtime·racewriterange(SB), NOSPLIT, $0-16 +TEXT runtime·racewriterange(SB), NOSPLIT, $0-16 +#ifndef GOEXPERIMENT_regabiargs MOVD addr+0(FP), R4 MOVD size+8(FP), R5 +#else + MOVD R4, R5 + MOVD R3, R4 +#endif MOVD LR, R6 // void __tsan_write_range(ThreadState *thr, void *addr, uintptr size, void *pc); MOVD $__tsan_write_range(SB), R8 -- GitLab From d4007aedfaf3f551f9ea7d5e2d2f86dcd2c4c990 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sun, 26 Sep 2021 20:45:54 -0700 Subject: [PATCH 1320/2500] go/types, types2: factor out some code, fix/add comments (cleanups) Change-Id: Id6a2e3eadc9099abbdd21b6880e1ff3ac9cfb599 Reviewed-on: https://go-review.googlesource.com/c/go/+/352312 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/infer.go | 2 +- src/cmd/compile/internal/types2/unify.go | 6 ++++-- src/go/types/infer.go | 2 +- src/go/types/unify.go | 6 ++++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index 914ee9ea5d..ad8c6ac412 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -334,7 +334,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { case *TypeParam: // t must be one of w.tparams - return t.index < len(w.tparams) && w.tparams[t.index] == t + return tparamIndex(w.tparams, t) >= 0 default: unreachable() diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index bb69f0d27b..a252c5e1a5 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -108,7 +108,7 @@ func (d *tparamsList) init(tparams []*TypeParam) { // join unifies the i'th type parameter of x with the j'th type parameter of y. // If both type parameters already have a type associated with them and they are -// not joined, join fails and return false. +// not joined, join fails and returns false. func (u *unifier) join(i, j int) bool { ti := u.x.indices[i] tj := u.y.indices[j] @@ -132,6 +132,7 @@ func (u *unifier) join(i, j int) bool { break case ti > 0 && tj > 0: // Both type parameters have (possibly different) inferred types. Cannot join. + // TODO(gri) Should we check if types are identical? Investigate. return false case ti > 0: // Only the type parameter for x has an inferred type. Use x slot for y. @@ -226,7 +227,7 @@ func (u *unifier) nifyEq(x, y Type, p *ifacePair) bool { } // nify implements the core unification algorithm which is an -// adapted version of Checker.identical0. For changes to that +// adapted version of Checker.identical. For changes to that // code the corresponding changes should be made here. // Must not be called directly from outside the unifier. func (u *unifier) nify(x, y Type, p *ifacePair) bool { @@ -427,6 +428,7 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { } case *Named: + // TODO(gri) This code differs now from the parallel code in Checker.identical. Investigate. if y, ok := y.(*Named); ok { xargs := x.targs.list() yargs := y.targs.list() diff --git a/src/go/types/infer.go b/src/go/types/infer.go index 1c4915571d..0be01d31e8 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -329,7 +329,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { case *TypeParam: // t must be one of w.tparams - return t.index < len(w.tparams) && w.tparams[t.index] == t + return tparamIndex(w.tparams, t) >= 0 default: unreachable() diff --git a/src/go/types/unify.go b/src/go/types/unify.go index 6d10f71a90..ce78fc8241 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -109,7 +109,7 @@ func (d *tparamsList) init(tparams []*TypeParam) { // join unifies the i'th type parameter of x with the j'th type parameter of y. // If both type parameters already have a type associated with them and they are -// not joined, join fails and return false. +// not joined, join fails and returns false. func (u *unifier) join(i, j int) bool { ti := u.x.indices[i] tj := u.y.indices[j] @@ -133,6 +133,7 @@ func (u *unifier) join(i, j int) bool { break case ti > 0 && tj > 0: // Both type parameters have (possibly different) inferred types. Cannot join. + // TODO(gri) Should we check if types are identical? Investigate. return false case ti > 0: // Only the type parameter for x has an inferred type. Use x slot for y. @@ -223,7 +224,7 @@ func (u *unifier) nifyEq(x, y Type, p *ifacePair) bool { } // nify implements the core unification algorithm which is an -// adapted version of Checker.identical0. For changes to that +// adapted version of Checker.identical. For changes to that // code the corresponding changes should be made here. // Must not be called directly from outside the unifier. func (u *unifier) nify(x, y Type, p *ifacePair) bool { @@ -424,6 +425,7 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { } case *Named: + // TODO(gri) This code differs now from the parallel code in Checker.identical. Investigate. if y, ok := y.(*Named); ok { xargs := x.targs.list() yargs := y.targs.list() -- GitLab From 3d795ea798edf0f9da4d2e33e15a58e59aa42e83 Mon Sep 17 00:00:00 2001 From: Rhys Hiltner Date: Fri, 13 Aug 2021 08:34:25 -0700 Subject: [PATCH 1321/2500] runtime: add timer_create syscalls for Linux Updates #35057 Change-Id: Id702b502fa4e4005ba1e450a945bc4420a8a8b8c Reviewed-on: https://go-review.googlesource.com/c/go/+/342052 Run-TryBot: Rhys Hiltner TryBot-Result: Go Bot Reviewed-by: Michael Pratt Trust: Than McIntosh --- src/runtime/defs_linux.go | 9 +++++++++ src/runtime/defs_linux_386.go | 20 +++++++++++++++++++ src/runtime/defs_linux_amd64.go | 20 +++++++++++++++++++ src/runtime/defs_linux_arm.go | 19 ++++++++++++++++++ src/runtime/defs_linux_arm64.go | 20 +++++++++++++++++++ src/runtime/defs_linux_mips64x.go | 20 +++++++++++++++++++ src/runtime/defs_linux_mipsx.go | 20 +++++++++++++++++++ src/runtime/defs_linux_ppc64.go | 20 +++++++++++++++++++ src/runtime/defs_linux_ppc64le.go | 20 +++++++++++++++++++ src/runtime/defs_linux_riscv64.go | 20 +++++++++++++++++++ src/runtime/defs_linux_s390x.go | 20 +++++++++++++++++++ src/runtime/os_linux.go | 9 +++++++++ src/runtime/sys_linux_386.s | 29 ++++++++++++++++++++++++++++ src/runtime/sys_linux_amd64.s | 29 ++++++++++++++++++++++++++++ src/runtime/sys_linux_arm.s | 29 ++++++++++++++++++++++++++++ src/runtime/sys_linux_arm64.s | 29 ++++++++++++++++++++++++++++ src/runtime/sys_linux_mips64x.s | 29 ++++++++++++++++++++++++++++ src/runtime/sys_linux_mipsx.s | 29 ++++++++++++++++++++++++++++ src/runtime/sys_linux_ppc64x.s | 26 +++++++++++++++++++++++++ src/runtime/sys_linux_riscv64.s | 32 +++++++++++++++++++++++++++++++ src/runtime/sys_linux_s390x.s | 29 ++++++++++++++++++++++++++++ 21 files changed, 478 insertions(+) diff --git a/src/runtime/defs_linux.go b/src/runtime/defs_linux.go index 022ef19427..7c3167032f 100644 --- a/src/runtime/defs_linux.go +++ b/src/runtime/defs_linux.go @@ -58,6 +58,9 @@ const ( SA_ONSTACK = C.SA_ONSTACK SA_SIGINFO = C.SA_SIGINFO + SI_KERNEL = C.SI_KERNEL + SI_TIMER = C.SI_TIMER + SIGHUP = C.SIGHUP SIGINT = C.SIGINT SIGQUIT = C.SIGQUIT @@ -109,6 +112,10 @@ const ( ITIMER_VIRTUAL = C.ITIMER_VIRTUAL ITIMER_PROF = C.ITIMER_PROF + CLOCK_THREAD_CPUTIME_ID = C.CLOCK_THREAD_CPUTIME_ID + + SIGEV_THREAD_ID = C.SIGEV_THREAD_ID + EPOLLIN = C.POLLIN EPOLLOUT = C.POLLOUT EPOLLERR = C.POLLERR @@ -126,5 +133,7 @@ type Timespec C.struct_timespec type Timeval C.struct_timeval type Sigaction C.struct_sigaction type Siginfo C.siginfo_t +type Itimerspec C.struct_itimerspec type Itimerval C.struct_itimerval +type Sigevent C.struct_sigevent type EpollEvent C.struct_epoll_event diff --git a/src/runtime/defs_linux_386.go b/src/runtime/defs_linux_386.go index 64a0fbcaaa..d8b546cb4c 100644 --- a/src/runtime/defs_linux_386.go +++ b/src/runtime/defs_linux_386.go @@ -28,6 +28,9 @@ const ( _SA_RESTORER = 0x4000000 _SA_SIGINFO = 0x4 + _SI_KERNEL = 0x80 + _SI_TIMER = -0x2 + _SIGHUP = 0x1 _SIGINT = 0x2 _SIGQUIT = 0x3 @@ -79,6 +82,10 @@ const ( _ITIMER_VIRTUAL = 0x1 _ITIMER_PROF = 0x2 + _CLOCK_THREAD_CPUTIME_ID = 0x3 + + _SIGEV_THREAD_ID = 0x4 + _O_RDONLY = 0x0 _O_NONBLOCK = 0x800 _O_CLOEXEC = 0x80000 @@ -212,11 +219,24 @@ type ucontext struct { uc_sigmask uint32 } +type itimerspec struct { + it_interval timespec + it_value timespec +} + type itimerval struct { it_interval timeval it_value timeval } +type sigevent struct { + value uintptr + signo int32 + notify int32 + // below here is a union; sigev_notify_thread_id is the only field we use + sigev_notify_thread_id int32 +} + type epollevent struct { events uint32 data [8]byte // to match amd64 diff --git a/src/runtime/defs_linux_amd64.go b/src/runtime/defs_linux_amd64.go index 1ae18a309b..6afb67f77f 100644 --- a/src/runtime/defs_linux_amd64.go +++ b/src/runtime/defs_linux_amd64.go @@ -28,6 +28,9 @@ const ( _SA_RESTORER = 0x4000000 _SA_SIGINFO = 0x4 + _SI_KERNEL = 0x80 + _SI_TIMER = -0x2 + _SIGHUP = 0x1 _SIGINT = 0x2 _SIGQUIT = 0x3 @@ -79,6 +82,10 @@ const ( _ITIMER_VIRTUAL = 0x1 _ITIMER_PROF = 0x2 + _CLOCK_THREAD_CPUTIME_ID = 0x3 + + _SIGEV_THREAD_ID = 0x4 + _EPOLLIN = 0x1 _EPOLLOUT = 0x4 _EPOLLERR = 0x8 @@ -129,11 +136,24 @@ type siginfo struct { si_addr uint64 } +type itimerspec struct { + it_interval timespec + it_value timespec +} + type itimerval struct { it_interval timeval it_value timeval } +type sigevent struct { + value uintptr + signo int32 + notify int32 + // below here is a union; sigev_notify_thread_id is the only field we use + sigev_notify_thread_id int32 +} + type epollevent struct { events uint32 data [8]byte // unaligned uintptr diff --git a/src/runtime/defs_linux_arm.go b/src/runtime/defs_linux_arm.go index 5bc0916f8b..ec24d76326 100644 --- a/src/runtime/defs_linux_arm.go +++ b/src/runtime/defs_linux_arm.go @@ -29,6 +29,8 @@ const ( _SA_ONSTACK = 0x8000000 _SA_RESTORER = 0 // unused on ARM _SA_SIGINFO = 0x4 + _SI_KERNEL = 0x80 + _SI_TIMER = -0x2 _SIGHUP = 0x1 _SIGINT = 0x2 _SIGQUIT = 0x3 @@ -79,6 +81,10 @@ const ( _O_NONBLOCK = 0x800 _O_CLOEXEC = 0x80000 + _CLOCK_THREAD_CPUTIME_ID = 0x3 + + _SIGEV_THREAD_ID = 0x4 + _EPOLLIN = 0x1 _EPOLLOUT = 0x4 _EPOLLERR = 0x8 @@ -153,11 +159,24 @@ func (tv *timeval) set_usec(x int32) { tv.tv_usec = x } +type itimerspec struct { + it_interval timespec + it_value timespec +} + type itimerval struct { it_interval timeval it_value timeval } +type sigevent struct { + value uintptr + signo int32 + notify int32 + // below here is a union; sigev_notify_thread_id is the only field we use + sigev_notify_thread_id int32 +} + type siginfo struct { si_signo int32 si_errno int32 diff --git a/src/runtime/defs_linux_arm64.go b/src/runtime/defs_linux_arm64.go index 0690cd35b2..f9f175004b 100644 --- a/src/runtime/defs_linux_arm64.go +++ b/src/runtime/defs_linux_arm64.go @@ -28,6 +28,9 @@ const ( _SA_RESTORER = 0x0 // Only used on intel _SA_SIGINFO = 0x4 + _SI_KERNEL = 0x80 + _SI_TIMER = -0x2 + _SIGHUP = 0x1 _SIGINT = 0x2 _SIGQUIT = 0x3 @@ -79,6 +82,10 @@ const ( _ITIMER_VIRTUAL = 0x1 _ITIMER_PROF = 0x2 + _CLOCK_THREAD_CPUTIME_ID = 0x3 + + _SIGEV_THREAD_ID = 0x4 + _EPOLLIN = 0x1 _EPOLLOUT = 0x4 _EPOLLERR = 0x8 @@ -129,11 +136,24 @@ type siginfo struct { si_addr uint64 } +type itimerspec struct { + it_interval timespec + it_value timespec +} + type itimerval struct { it_interval timeval it_value timeval } +type sigevent struct { + value uintptr + signo int32 + notify int32 + // below here is a union; sigev_notify_thread_id is the only field we use + sigev_notify_thread_id int32 +} + type epollevent struct { events uint32 _pad uint32 diff --git a/src/runtime/defs_linux_mips64x.go b/src/runtime/defs_linux_mips64x.go index 2cafad20cf..1743bbce41 100644 --- a/src/runtime/defs_linux_mips64x.go +++ b/src/runtime/defs_linux_mips64x.go @@ -32,6 +32,9 @@ const ( _SA_ONSTACK = 0x8000000 _SA_SIGINFO = 0x8 + _SI_KERNEL = 0x80 + _SI_TIMER = -0x2 + _SIGHUP = 0x1 _SIGINT = 0x2 _SIGQUIT = 0x3 @@ -83,6 +86,10 @@ const ( _ITIMER_VIRTUAL = 0x1 _ITIMER_PROF = 0x2 + _CLOCK_THREAD_CPUTIME_ID = 0x3 + + _SIGEV_THREAD_ID = 0x4 + _EPOLLIN = 0x1 _EPOLLOUT = 0x4 _EPOLLERR = 0x8 @@ -138,11 +145,24 @@ type siginfo struct { si_addr uint64 } +type itimerspec struct { + it_interval timespec + it_value timespec +} + type itimerval struct { it_interval timeval it_value timeval } +type sigevent struct { + value uintptr + signo int32 + notify int32 + // below here is a union; sigev_notify_thread_id is the only field we use + sigev_notify_thread_id int32 +} + type epollevent struct { events uint32 pad_cgo_0 [4]byte diff --git a/src/runtime/defs_linux_mipsx.go b/src/runtime/defs_linux_mipsx.go index 3a8dfe2e99..e84d4979e1 100644 --- a/src/runtime/defs_linux_mipsx.go +++ b/src/runtime/defs_linux_mipsx.go @@ -32,6 +32,9 @@ const ( _SA_ONSTACK = 0x8000000 _SA_SIGINFO = 0x8 + _SI_KERNEL = 0x80 + _SI_TIMER = -0x2 + _SIGHUP = 0x1 _SIGINT = 0x2 _SIGQUIT = 0x3 @@ -83,6 +86,10 @@ const ( _ITIMER_VIRTUAL = 0x1 _ITIMER_PROF = 0x2 + _CLOCK_THREAD_CPUTIME_ID = 0x3 + + _SIGEV_THREAD_ID = 0x4 + _EPOLLIN = 0x1 _EPOLLOUT = 0x4 _EPOLLERR = 0x8 @@ -132,11 +139,24 @@ type siginfo struct { si_addr uint32 } +type itimerspec struct { + it_interval timespec + it_value timespec +} + type itimerval struct { it_interval timeval it_value timeval } +type sigevent struct { + value uintptr + signo int32 + notify int32 + // below here is a union; sigev_notify_thread_id is the only field we use + sigev_notify_thread_id int32 +} + type epollevent struct { events uint32 pad_cgo_0 [4]byte diff --git a/src/runtime/defs_linux_ppc64.go b/src/runtime/defs_linux_ppc64.go index 90b1dc1ff9..e0775e2974 100644 --- a/src/runtime/defs_linux_ppc64.go +++ b/src/runtime/defs_linux_ppc64.go @@ -27,6 +27,9 @@ const ( _SA_ONSTACK = 0x8000000 _SA_SIGINFO = 0x4 + _SI_KERNEL = 0x80 + _SI_TIMER = -0x2 + _SIGHUP = 0x1 _SIGINT = 0x2 _SIGQUIT = 0x3 @@ -78,6 +81,10 @@ const ( _ITIMER_VIRTUAL = 0x1 _ITIMER_PROF = 0x2 + _CLOCK_THREAD_CPUTIME_ID = 0x3 + + _SIGEV_THREAD_ID = 0x4 + _EPOLLIN = 0x1 _EPOLLOUT = 0x4 _EPOLLERR = 0x8 @@ -130,11 +137,24 @@ type siginfo struct { si_addr uint64 } +type itimerspec struct { + it_interval timespec + it_value timespec +} + type itimerval struct { it_interval timeval it_value timeval } +type sigevent struct { + value uintptr + signo int32 + notify int32 + // below here is a union; sigev_notify_thread_id is the only field we use + sigev_notify_thread_id int32 +} + type epollevent struct { events uint32 pad_cgo_0 [4]byte diff --git a/src/runtime/defs_linux_ppc64le.go b/src/runtime/defs_linux_ppc64le.go index 90b1dc1ff9..e0775e2974 100644 --- a/src/runtime/defs_linux_ppc64le.go +++ b/src/runtime/defs_linux_ppc64le.go @@ -27,6 +27,9 @@ const ( _SA_ONSTACK = 0x8000000 _SA_SIGINFO = 0x4 + _SI_KERNEL = 0x80 + _SI_TIMER = -0x2 + _SIGHUP = 0x1 _SIGINT = 0x2 _SIGQUIT = 0x3 @@ -78,6 +81,10 @@ const ( _ITIMER_VIRTUAL = 0x1 _ITIMER_PROF = 0x2 + _CLOCK_THREAD_CPUTIME_ID = 0x3 + + _SIGEV_THREAD_ID = 0x4 + _EPOLLIN = 0x1 _EPOLLOUT = 0x4 _EPOLLERR = 0x8 @@ -130,11 +137,24 @@ type siginfo struct { si_addr uint64 } +type itimerspec struct { + it_interval timespec + it_value timespec +} + type itimerval struct { it_interval timeval it_value timeval } +type sigevent struct { + value uintptr + signo int32 + notify int32 + // below here is a union; sigev_notify_thread_id is the only field we use + sigev_notify_thread_id int32 +} + type epollevent struct { events uint32 pad_cgo_0 [4]byte diff --git a/src/runtime/defs_linux_riscv64.go b/src/runtime/defs_linux_riscv64.go index 60da0fae00..1052213a4c 100644 --- a/src/runtime/defs_linux_riscv64.go +++ b/src/runtime/defs_linux_riscv64.go @@ -29,6 +29,9 @@ const ( _SA_RESTORER = 0x0 _SA_SIGINFO = 0x4 + _SI_KERNEL = 0x80 + _SI_TIMER = -0x2 + _SIGHUP = 0x1 _SIGINT = 0x2 _SIGQUIT = 0x3 @@ -80,6 +83,10 @@ const ( _ITIMER_VIRTUAL = 0x1 _ITIMER_PROF = 0x2 + _CLOCK_THREAD_CPUTIME_ID = 0x3 + + _SIGEV_THREAD_ID = 0x4 + _EPOLLIN = 0x1 _EPOLLOUT = 0x4 _EPOLLERR = 0x8 @@ -127,11 +134,24 @@ type siginfo struct { si_addr uint64 } +type itimerspec struct { + it_interval timespec + it_value timespec +} + type itimerval struct { it_interval timeval it_value timeval } +type sigevent struct { + value uintptr + signo int32 + notify int32 + // below here is a union; sigev_notify_thread_id is the only field we use + sigev_notify_thread_id int32 +} + type epollevent struct { events uint32 pad_cgo_0 [4]byte diff --git a/src/runtime/defs_linux_s390x.go b/src/runtime/defs_linux_s390x.go index fa289d531c..b072955d4a 100644 --- a/src/runtime/defs_linux_s390x.go +++ b/src/runtime/defs_linux_s390x.go @@ -28,6 +28,9 @@ const ( _SA_ONSTACK = 0x8000000 _SA_SIGINFO = 0x4 + _SI_KERNEL = 0x80 + _SI_TIMER = -0x2 + _SIGHUP = 0x1 _SIGINT = 0x2 _SIGQUIT = 0x3 @@ -79,6 +82,10 @@ const ( _ITIMER_VIRTUAL = 0x1 _ITIMER_PROF = 0x2 + _CLOCK_THREAD_CPUTIME_ID = 0x3 + + _SIGEV_THREAD_ID = 0x4 + _EPOLLIN = 0x1 _EPOLLOUT = 0x4 _EPOLLERR = 0x8 @@ -126,11 +133,24 @@ type siginfo struct { si_addr uint64 } +type itimerspec struct { + it_interval timespec + it_value timespec +} + type itimerval struct { it_interval timeval it_value timeval } +type sigevent struct { + value uintptr + signo int32 + notify int32 + // below here is a union; sigev_notify_thread_id is the only field we use + sigev_notify_thread_id int32 +} + type epollevent struct { events uint32 pad_cgo_0 [4]byte diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go index 88c16f7163..b60dc9ea01 100644 --- a/src/runtime/os_linux.go +++ b/src/runtime/os_linux.go @@ -395,6 +395,15 @@ func sigaltstack(new, old *stackt) //go:noescape func setitimer(mode int32, new, old *itimerval) +//go:noescape +func timer_create(clockid int32, sevp *sigevent, timerid *int32) int32 + +//go:noescape +func timer_settime(timerid int32, flags int32, new, old *itimerspec) int32 + +//go:noescape +func timer_delete(timerid int32) int32 + //go:noescape func rtsigprocmask(how int32, new, old *sigset, size int32) diff --git a/src/runtime/sys_linux_386.s b/src/runtime/sys_linux_386.s index 3ae5a9099f..6df812234c 100644 --- a/src/runtime/sys_linux_386.s +++ b/src/runtime/sys_linux_386.s @@ -56,6 +56,9 @@ #define SYS_epoll_create 254 #define SYS_epoll_ctl 255 #define SYS_epoll_wait 256 +#define SYS_timer_create 259 +#define SYS_timer_settime 260 +#define SYS_timer_delete 263 #define SYS_clock_gettime 265 #define SYS_tgkill 270 #define SYS_epoll_create1 329 @@ -210,6 +213,32 @@ TEXT runtime·setitimer(SB),NOSPLIT,$0-12 INVOKE_SYSCALL RET +TEXT runtime·timer_create(SB),NOSPLIT,$0-16 + MOVL $SYS_timer_create, AX + MOVL clockid+0(FP), BX + MOVL sevp+4(FP), CX + MOVL timerid+8(FP), DX + INVOKE_SYSCALL + MOVL AX, ret+12(FP) + RET + +TEXT runtime·timer_settime(SB),NOSPLIT,$0-20 + MOVL $SYS_timer_settime, AX + MOVL timerid+0(FP), BX + MOVL flags+4(FP), CX + MOVL new+8(FP), DX + MOVL old+12(FP), SI + INVOKE_SYSCALL + MOVL AX, ret+16(FP) + RET + +TEXT runtime·timer_delete(SB),NOSPLIT,$0-8 + MOVL $SYS_timer_delete, AX + MOVL timerid+0(FP), BX + INVOKE_SYSCALL + MOVL AX, ret+4(FP) + RET + TEXT runtime·mincore(SB),NOSPLIT,$0-16 MOVL $SYS_mincore, AX MOVL addr+0(FP), BX diff --git a/src/runtime/sys_linux_amd64.s b/src/runtime/sys_linux_amd64.s index 64ddc2354e..345dc90eb0 100644 --- a/src/runtime/sys_linux_amd64.s +++ b/src/runtime/sys_linux_amd64.s @@ -41,6 +41,9 @@ #define SYS_futex 202 #define SYS_sched_getaffinity 204 #define SYS_epoll_create 213 +#define SYS_timer_create 222 +#define SYS_timer_settime 223 +#define SYS_timer_delete 226 #define SYS_clock_gettime 228 #define SYS_exit_group 231 #define SYS_epoll_ctl 233 @@ -195,6 +198,32 @@ TEXT runtime·setitimer(SB),NOSPLIT,$0-24 SYSCALL RET +TEXT runtime·timer_create(SB),NOSPLIT,$0-28 + MOVL clockid+0(FP), DI + MOVQ sevp+8(FP), SI + MOVQ timerid+16(FP), DX + MOVL $SYS_timer_create, AX + SYSCALL + MOVL AX, ret+24(FP) + RET + +TEXT runtime·timer_settime(SB),NOSPLIT,$0-28 + MOVL timerid+0(FP), DI + MOVL flags+4(FP), SI + MOVQ new+8(FP), DX + MOVQ old+16(FP), R10 + MOVL $SYS_timer_settime, AX + SYSCALL + MOVL AX, ret+24(FP) + RET + +TEXT runtime·timer_delete(SB),NOSPLIT,$0-12 + MOVL timerid+0(FP), DI + MOVL $SYS_timer_delete, AX + SYSCALL + MOVL AX, ret+8(FP) + RET + TEXT runtime·mincore(SB),NOSPLIT,$0-28 MOVQ addr+0(FP), DI MOVQ n+8(FP), SI diff --git a/src/runtime/sys_linux_arm.s b/src/runtime/sys_linux_arm.s index ae99810c10..3f30da7b54 100644 --- a/src/runtime/sys_linux_arm.s +++ b/src/runtime/sys_linux_arm.s @@ -45,6 +45,9 @@ #define SYS_epoll_create (SYS_BASE + 250) #define SYS_epoll_ctl (SYS_BASE + 251) #define SYS_epoll_wait (SYS_BASE + 252) +#define SYS_timer_create (SYS_BASE + 257) +#define SYS_timer_settime (SYS_BASE + 258) +#define SYS_timer_delete (SYS_BASE + 261) #define SYS_epoll_create1 (SYS_BASE + 357) #define SYS_pipe2 (SYS_BASE + 359) #define SYS_fcntl (SYS_BASE + 55) @@ -233,6 +236,32 @@ TEXT runtime·setitimer(SB),NOSPLIT,$0 SWI $0 RET +TEXT runtime·timer_create(SB),NOSPLIT,$0-16 + MOVW clockid+0(FP), R0 + MOVW sevp+4(FP), R1 + MOVW timerid+8(FP), R2 + MOVW $SYS_timer_create, R7 + SWI $0 + MOVW R0, ret+12(FP) + RET + +TEXT runtime·timer_settime(SB),NOSPLIT,$0-20 + MOVW timerid+0(FP), R0 + MOVW flags+4(FP), R1 + MOVW new+8(FP), R2 + MOVW old+12(FP), R3 + MOVW $SYS_timer_settime, R7 + SWI $0 + MOVW R0, ret+16(FP) + RET + +TEXT runtime·timer_delete(SB),NOSPLIT,$0-8 + MOVW timerid+0(FP), R0 + MOVW $SYS_timer_delete, R7 + SWI $0 + MOVW R0, ret+4(FP) + RET + TEXT runtime·mincore(SB),NOSPLIT,$0 MOVW addr+0(FP), R0 MOVW n+4(FP), R1 diff --git a/src/runtime/sys_linux_arm64.s b/src/runtime/sys_linux_arm64.s index 9289ad5028..1276c077d7 100644 --- a/src/runtime/sys_linux_arm64.s +++ b/src/runtime/sys_linux_arm64.s @@ -49,6 +49,9 @@ #define SYS_socket 198 #define SYS_connect 203 #define SYS_brk 214 +#define SYS_timer_create 107 +#define SYS_timer_settime 110 +#define SYS_timer_delete 111 TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0-4 MOVW code+0(FP), R0 @@ -197,6 +200,32 @@ TEXT runtime·setitimer(SB),NOSPLIT|NOFRAME,$0-24 SVC RET +TEXT runtime·timer_create(SB),NOSPLIT,$0-28 + MOVW clockid+0(FP), R0 + MOVD sevp+8(FP), R1 + MOVD timerid+16(FP), R2 + MOVD $SYS_timer_create, R8 + SVC + MOVW R0, ret+24(FP) + RET + +TEXT runtime·timer_settime(SB),NOSPLIT,$0-28 + MOVW timerid+0(FP), R0 + MOVW flags+4(FP), R1 + MOVD new+8(FP), R2 + MOVD old+16(FP), R3 + MOVD $SYS_timer_settime, R8 + SVC + MOVW R0, ret+24(FP) + RET + +TEXT runtime·timer_delete(SB),NOSPLIT,$0-12 + MOVW timerid+0(FP), R0 + MOVD $SYS_timer_delete, R8 + SVC + MOVW R0, ret+8(FP) + RET + TEXT runtime·mincore(SB),NOSPLIT|NOFRAME,$0-28 MOVD addr+0(FP), R0 MOVD n+8(FP), R1 diff --git a/src/runtime/sys_linux_mips64x.s b/src/runtime/sys_linux_mips64x.s index 7529a0ed27..08e44d671b 100644 --- a/src/runtime/sys_linux_mips64x.s +++ b/src/runtime/sys_linux_mips64x.s @@ -41,6 +41,9 @@ #define SYS_exit_group 5205 #define SYS_epoll_create 5207 #define SYS_epoll_ctl 5208 +#define SYS_timer_create 5216 +#define SYS_timer_settime 5217 +#define SYS_timer_delete 5220 #define SYS_tgkill 5225 #define SYS_openat 5247 #define SYS_epoll_pwait 5272 @@ -204,6 +207,32 @@ TEXT runtime·setitimer(SB),NOSPLIT|NOFRAME,$0-24 SYSCALL RET +TEXT runtime·timer_create(SB),NOSPLIT,$0-28 + MOVW clockid+0(FP), R4 + MOVV sevp+8(FP), R5 + MOVV timerid+16(FP), R6 + MOVV $SYS_timer_create, R2 + SYSCALL + MOVW R2, ret+24(FP) + RET + +TEXT runtime·timer_settime(SB),NOSPLIT,$0-28 + MOVW timerid+0(FP), R4 + MOVW flags+4(FP), R5 + MOVV new+8(FP), R6 + MOVV old+16(FP), R7 + MOVV $SYS_timer_settime, R2 + SYSCALL + MOVW R2, ret+24(FP) + RET + +TEXT runtime·timer_delete(SB),NOSPLIT,$0-12 + MOVW timerid+0(FP), R4 + MOVV $SYS_timer_delete, R2 + SYSCALL + MOVW R2, ret+8(FP) + RET + TEXT runtime·mincore(SB),NOSPLIT|NOFRAME,$0-28 MOVV addr+0(FP), R4 MOVV n+8(FP), R5 diff --git a/src/runtime/sys_linux_mipsx.s b/src/runtime/sys_linux_mipsx.s index b3970be9cf..c828431899 100644 --- a/src/runtime/sys_linux_mipsx.s +++ b/src/runtime/sys_linux_mipsx.s @@ -43,6 +43,9 @@ #define SYS_epoll_create 4248 #define SYS_epoll_ctl 4249 #define SYS_epoll_wait 4250 +#define SYS_timer_create 4257 +#define SYS_timer_settime 4258 +#define SYS_timer_delete 4261 #define SYS_clock_gettime 4263 #define SYS_tgkill 4266 #define SYS_epoll_create1 4326 @@ -209,6 +212,32 @@ TEXT runtime·setitimer(SB),NOSPLIT,$0-12 SYSCALL RET +TEXT runtime·timer_create(SB),NOSPLIT,$0-16 + MOVW clockid+0(FP), R4 + MOVW sevp+4(FP), R5 + MOVW timerid+8(FP), R6 + MOVW $SYS_timer_create, R2 + SYSCALL + MOVW R2, ret+12(FP) + RET + +TEXT runtime·timer_settime(SB),NOSPLIT,$0-20 + MOVW timerid+0(FP), R4 + MOVW flags+4(FP), R5 + MOVW new+8(FP), R6 + MOVW old+12(FP), R7 + MOVW $SYS_timer_settime, R2 + SYSCALL + MOVW R2, ret+16(FP) + RET + +TEXT runtime·timer_delete(SB),NOSPLIT,$0-8 + MOVW timerid+0(FP), R4 + MOVW $SYS_timer_delete, R2 + SYSCALL + MOVW R2, ret+4(FP) + RET + TEXT runtime·mincore(SB),NOSPLIT,$0-16 MOVW addr+0(FP), R4 MOVW n+4(FP), R5 diff --git a/src/runtime/sys_linux_ppc64x.s b/src/runtime/sys_linux_ppc64x.s index 33b6a9409c..56d600b6ea 100644 --- a/src/runtime/sys_linux_ppc64x.s +++ b/src/runtime/sys_linux_ppc64x.s @@ -44,6 +44,9 @@ #define SYS_epoll_create 236 #define SYS_epoll_ctl 237 #define SYS_epoll_wait 238 +#define SYS_timer_create 240 +#define SYS_timer_settime 241 +#define SYS_timer_delete 244 #define SYS_clock_gettime 246 #define SYS_tgkill 250 #define SYS_epoll_create1 315 @@ -176,6 +179,29 @@ TEXT runtime·setitimer(SB),NOSPLIT|NOFRAME,$0-24 SYSCALL $SYS_setitimer RET +TEXT runtime·timer_create(SB),NOSPLIT,$0-28 + MOVW clockid+0(FP), R3 + MOVD sevp+8(FP), R4 + MOVD timerid+16(FP), R5 + SYSCALL $SYS_timer_create + MOVW R3, ret+24(FP) + RET + +TEXT runtime·timer_settime(SB),NOSPLIT,$0-28 + MOVW timerid+0(FP), R3 + MOVW flags+4(FP), R4 + MOVD new+8(FP), R5 + MOVD old+16(FP), R6 + SYSCALL $SYS_timer_settime + MOVW R3, ret+24(FP) + RET + +TEXT runtime·timer_delete(SB),NOSPLIT,$0-12 + MOVW timerid+0(FP), R3 + SYSCALL $SYS_timer_delete + MOVW R3, ret+8(FP) + RET + TEXT runtime·mincore(SB),NOSPLIT|NOFRAME,$0-28 MOVD addr+0(FP), R3 MOVD n+8(FP), R4 diff --git a/src/runtime/sys_linux_riscv64.s b/src/runtime/sys_linux_riscv64.s index ebcdd56a45..a3da46d136 100644 --- a/src/runtime/sys_linux_riscv64.s +++ b/src/runtime/sys_linux_riscv64.s @@ -48,6 +48,9 @@ #define SYS_sigaltstack 132 #define SYS_socket 198 #define SYS_tgkill 131 +#define SYS_timer_create 107 +#define SYS_timer_delete 111 +#define SYS_timer_settime 110 #define SYS_tkill 130 #define SYS_write 64 @@ -201,6 +204,35 @@ TEXT runtime·setitimer(SB),NOSPLIT|NOFRAME,$0-24 ECALL RET +// func timer_create(clockid int32, sevp *sigevent, timerid *int32) int32 +TEXT runtime·timer_create(SB),NOSPLIT,$0-28 + MOVW clockid+0(FP), A0 + MOV sevp+8(FP), A1 + MOV timerid+16(FP), A2 + MOV $SYS_timer_create, A7 + ECALL + MOVW A0, ret+24(FP) + RET + +// func timer_settime(timerid int32, flags int32, new, old *itimerspec) int32 +TEXT runtime·timer_settime(SB),NOSPLIT,$0-28 + MOVW timerid+0(FP), A0 + MOVW flags+4(FP), A1 + MOV new+8(FP), A2 + MOV old+16(FP), A3 + MOV $SYS_timer_settime, A7 + ECALL + MOVW A0, ret+24(FP) + RET + +// func timer_delete(timerid int32) int32 +TEXT runtime·timer_delete(SB),NOSPLIT,$0-12 + MOVW timerid+0(FP), A0 + MOV $SYS_timer_delete, A7 + ECALL + MOVW A0, ret+8(FP) + RET + // func mincore(addr unsafe.Pointer, n uintptr, dst *byte) int32 TEXT runtime·mincore(SB),NOSPLIT|NOFRAME,$0-28 MOV addr+0(FP), A0 diff --git a/src/runtime/sys_linux_s390x.s b/src/runtime/sys_linux_s390x.s index 916dfada8d..886add8b54 100644 --- a/src/runtime/sys_linux_s390x.s +++ b/src/runtime/sys_linux_s390x.s @@ -39,6 +39,9 @@ #define SYS_epoll_create 249 #define SYS_epoll_ctl 250 #define SYS_epoll_wait 251 +#define SYS_timer_create 254 +#define SYS_timer_settime 255 +#define SYS_timer_delete 258 #define SYS_clock_gettime 260 #define SYS_pipe2 325 #define SYS_epoll_create1 327 @@ -185,6 +188,32 @@ TEXT runtime·setitimer(SB),NOSPLIT|NOFRAME,$0-24 SYSCALL RET +TEXT runtime·timer_create(SB),NOSPLIT|NOFRAME,$0-28 + MOVW clockid+0(FP), R2 + MOVD sevp+8(FP), R3 + MOVD timerid+16(FP), R4 + MOVW $SYS_timer_create, R1 + SYSCALL + MOVW R2, ret+24(FP) + RET + +TEXT runtime·timer_settime(SB),NOSPLIT|NOFRAME,$0-28 + MOVW timerid+0(FP), R2 + MOVW flags+4(FP), R3 + MOVD new+8(FP), R4 + MOVD old+16(FP), R5 + MOVW $SYS_timer_settime, R1 + SYSCALL + MOVW R2, ret+24(FP) + RET + +TEXT runtime·timer_delete(SB),NOSPLIT|NOFRAME,$0-12 + MOVW timerid+0(FP), R2 + MOVW $SYS_timer_delete, R1 + SYSCALL + MOVW R2, ret+8(FP) + RET + TEXT runtime·mincore(SB),NOSPLIT|NOFRAME,$0-28 MOVD addr+0(FP), R2 MOVD n+8(FP), R3 -- GitLab From f9e90f7e7401b7222ea10420140dc43687e4017f Mon Sep 17 00:00:00 2001 From: Rhys Hiltner Date: Fri, 13 Aug 2021 08:51:46 -0700 Subject: [PATCH 1322/2500] runtime: allow per-OS changes to unix profiler Updates #35057 Change-Id: I56ea8f4750022847f0866c85e237a2cea40e0ff7 Reviewed-on: https://go-review.googlesource.com/c/go/+/342053 Run-TryBot: Rhys Hiltner TryBot-Result: Go Bot Reviewed-by: Michael Pratt Trust: Michael Knyszek --- src/runtime/os3_solaris.go | 13 +++++++++++++ src/runtime/os_aix.go | 13 +++++++++++++ src/runtime/os_darwin.go | 13 +++++++++++++ src/runtime/os_dragonfly.go | 13 +++++++++++++ src/runtime/os_freebsd.go | 13 +++++++++++++ src/runtime/os_linux.go | 16 ++++++++++++++++ src/runtime/os_netbsd.go | 13 +++++++++++++ src/runtime/os_openbsd.go | 13 +++++++++++++ src/runtime/signal_unix.go | 25 +++++++++++++++++-------- 9 files changed, 124 insertions(+), 8 deletions(-) diff --git a/src/runtime/os3_solaris.go b/src/runtime/os3_solaris.go index 84194a3050..3149d13869 100644 --- a/src/runtime/os3_solaris.go +++ b/src/runtime/os3_solaris.go @@ -289,6 +289,19 @@ func sigdelset(mask *sigset, i int) { func (c *sigctxt) fixsigcode(sig uint32) { } +func setProcessCPUProfiler(hz int32) { + setProcessCPUProfilerTimer(hz) +} + +func setThreadCPUProfiler(hz int32) { + setThreadCPUProfilerHz(hz) +} + +//go:nosplit +func validSIGPROF(mp *m, c *sigctxt) bool { + return true +} + //go:nosplit func semacreate(mp *m) { if mp.waitsema != 0 { diff --git a/src/runtime/os_aix.go b/src/runtime/os_aix.go index 478dde2fc3..54e0cfbb8d 100644 --- a/src/runtime/os_aix.go +++ b/src/runtime/os_aix.go @@ -323,6 +323,19 @@ func sigdelset(mask *sigset, i int) { (*mask)[(i-1)/64] &^= 1 << ((uint32(i) - 1) & 63) } +func setProcessCPUProfiler(hz int32) { + setProcessCPUProfilerTimer(hz) +} + +func setThreadCPUProfiler(hz int32) { + setThreadCPUProfilerHz(hz) +} + +//go:nosplit +func validSIGPROF(mp *m, c *sigctxt) bool { + return true +} + const ( _CLOCK_REALTIME = 9 _CLOCK_MONOTONIC = 10 diff --git a/src/runtime/os_darwin.go b/src/runtime/os_darwin.go index ca61f20e8a..0f0eb6c6fd 100644 --- a/src/runtime/os_darwin.go +++ b/src/runtime/os_darwin.go @@ -425,6 +425,19 @@ func sigdelset(mask *sigset, i int) { *mask &^= 1 << (uint32(i) - 1) } +func setProcessCPUProfiler(hz int32) { + setProcessCPUProfilerTimer(hz) +} + +func setThreadCPUProfiler(hz int32) { + setThreadCPUProfilerHz(hz) +} + +//go:nosplit +func validSIGPROF(mp *m, c *sigctxt) bool { + return true +} + //go:linkname executablePath os.executablePath var executablePath string diff --git a/src/runtime/os_dragonfly.go b/src/runtime/os_dragonfly.go index 191a560667..cba2e42ab0 100644 --- a/src/runtime/os_dragonfly.go +++ b/src/runtime/os_dragonfly.go @@ -268,6 +268,19 @@ func sigdelset(mask *sigset, i int) { func (c *sigctxt) fixsigcode(sig uint32) { } +func setProcessCPUProfiler(hz int32) { + setProcessCPUProfilerTimer(hz) +} + +func setThreadCPUProfiler(hz int32) { + setThreadCPUProfilerHz(hz) +} + +//go:nosplit +func validSIGPROF(mp *m, c *sigctxt) bool { + return true +} + func sysargs(argc int32, argv **byte) { n := argc + 1 diff --git a/src/runtime/os_freebsd.go b/src/runtime/os_freebsd.go index 5a8121a420..c63b0e3d69 100644 --- a/src/runtime/os_freebsd.go +++ b/src/runtime/os_freebsd.go @@ -380,6 +380,19 @@ func sigdelset(mask *sigset, i int) { func (c *sigctxt) fixsigcode(sig uint32) { } +func setProcessCPUProfiler(hz int32) { + setProcessCPUProfilerTimer(hz) +} + +func setThreadCPUProfiler(hz int32) { + setThreadCPUProfilerHz(hz) +} + +//go:nosplit +func validSIGPROF(mp *m, c *sigctxt) bool { + return true +} + func sysargs(argc int32, argv **byte) { n := argc + 1 diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go index b60dc9ea01..d307c472b8 100644 --- a/src/runtime/os_linux.go +++ b/src/runtime/os_linux.go @@ -517,3 +517,19 @@ func tgkill(tgid, tid, sig int) func signalM(mp *m, sig int) { tgkill(getpid(), int(mp.procid), sig) } + +func setProcessCPUProfiler(hz int32) { + setProcessCPUProfilerTimer(hz) +} + +func setThreadCPUProfiler(hz int32) { + setThreadCPUProfilerHz(hz) +} + +//go:nosplit +func validSIGPROF(mp *m, c *sigctxt) bool { + // Once the profiler for Linux uses timer_create, this function will need to + // do more than return true. But so long as the only profiling timer in use + // is setitimer, returning true is correct. + return true +} diff --git a/src/runtime/os_netbsd.go b/src/runtime/os_netbsd.go index 0b95fa7a6e..cd9508c706 100644 --- a/src/runtime/os_netbsd.go +++ b/src/runtime/os_netbsd.go @@ -371,6 +371,19 @@ func sigdelset(mask *sigset, i int) { func (c *sigctxt) fixsigcode(sig uint32) { } +func setProcessCPUProfiler(hz int32) { + setProcessCPUProfilerTimer(hz) +} + +func setThreadCPUProfiler(hz int32) { + setThreadCPUProfilerHz(hz) +} + +//go:nosplit +func validSIGPROF(mp *m, c *sigctxt) bool { + return true +} + func sysargs(argc int32, argv **byte) { n := argc + 1 diff --git a/src/runtime/os_openbsd.go b/src/runtime/os_openbsd.go index 54f36c6ebf..2d0e71de53 100644 --- a/src/runtime/os_openbsd.go +++ b/src/runtime/os_openbsd.go @@ -233,6 +233,19 @@ func sigdelset(mask *sigset, i int) { func (c *sigctxt) fixsigcode(sig uint32) { } +func setProcessCPUProfiler(hz int32) { + setProcessCPUProfilerTimer(hz) +} + +func setThreadCPUProfiler(hz int32) { + setThreadCPUProfilerHz(hz) +} + +//go:nosplit +func validSIGPROF(mp *m, c *sigctxt) bool { + return true +} + var haveMapStack = false func osStackAlloc(s *mspan) { diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go index cab5c879d3..228497c508 100644 --- a/src/runtime/signal_unix.go +++ b/src/runtime/signal_unix.go @@ -263,11 +263,11 @@ func clearSignalHandlers() { } } -// setProcessCPUProfiler is called when the profiling timer changes. -// It is called with prof.lock held. hz is the new timer, and is 0 if +// setProcessCPUProfilerTimer is called when the profiling timer changes. +// It is called with prof.signalLock held. hz is the new timer, and is 0 if // profiling is being disabled. Enable or disable the signal as // required for -buildmode=c-archive. -func setProcessCPUProfiler(hz int32) { +func setProcessCPUProfilerTimer(hz int32) { if hz != 0 { // Enable the Go signal handler if not enabled. if atomic.Cas(&handlingSig[_SIGPROF], 0, 1) { @@ -309,10 +309,10 @@ func setProcessCPUProfiler(hz int32) { } } -// setThreadCPUProfiler makes any thread-specific changes required to +// setThreadCPUProfilerHz makes any thread-specific changes required to // implement profiling at a rate of hz. -// No changes required on Unix systems. -func setThreadCPUProfiler(hz int32) { +// No changes required on Unix systems when using setitimer. +func setThreadCPUProfilerHz(hz int32) { getg().m.profilehz = hz } @@ -423,7 +423,11 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) { setg(g) if g == nil { if sig == _SIGPROF { - sigprofNonGoPC(c.sigpc()) + // Some platforms (Linux) have per-thread timers, which we use in + // combination with the process-wide timer. Avoid double-counting. + if validSIGPROF(nil, c) { + sigprofNonGoPC(c.sigpc()) + } return } if sig == sigPreempt && preemptMSupported && debug.asyncpreemptoff == 0 { @@ -540,7 +544,12 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) { c := &sigctxt{info, ctxt} if sig == _SIGPROF { - sigprof(c.sigpc(), c.sigsp(), c.siglr(), gp, _g_.m) + mp := _g_.m + // Some platforms (Linux) have per-thread timers, which we use in + // combination with the process-wide timer. Avoid double-counting. + if validSIGPROF(mp, c) { + sigprof(c.sigpc(), c.sigsp(), c.siglr(), gp, mp) + } return } -- GitLab From 8cfd8c3db8e32fed0cf61371335d87a47a4738c3 Mon Sep 17 00:00:00 2001 From: Rhys Hiltner Date: Fri, 13 Aug 2021 08:58:40 -0700 Subject: [PATCH 1323/2500] runtime: profile with per-thread timers on Linux Using setitimer on Linux to request SIGPROF signal deliveries in proportion to the process's on-CPU time results in under-reporting when the program uses several goroutines in parallel. Linux calculates the process's total CPU spend on a regular basis (often every 4ms); if the process has spent enough CPU time since the last calculation to warrant more than one SIGPROF (usually 10ms for the default sample rate of 100 Hz), the kernel is often able to deliver only one of them. With these common settings, that results in Go CPU profiles being attenuated for programs that use more than 2.5 goroutines in parallel. To avoid in effect overflowing the kernel's process-wide CPU counter, and relying on Linux's typical behavior of having the active thread handle the resulting process-targeted signal, use timer_create to request a timer for each OS thread that the Go runtime manages. Have each timer track the CPU time of a single thread, with the resulting SIGPROF going directly to that thread. To continue tracking CPU time spent on threads that don't interact with the Go runtime (such as those created and used in cgo), keep using setitimer in addition to the new mechanism. When a SIGPROF signal arrives, check whether it's due to setitimer or timer_create and filter as appropriate: If the thread is known to Go (has an M) and has a timer_create timer, ignore SIGPROF signals from setitimer. If the thread is not known to Go (does not have an M), ignore SIGPROF signals that are not from setitimer. Counteract the new bias that per-thread profiling adds against short-lived threads (or those that are only active on occasion for a short time, such as garbage collection workers on mostly-idle systems) by configuring the timers' initial trigger to be from a uniform random distribution between "immediate trigger" and the full requested sample period. Updates #35057 Change-Id: Iab753c4e5101bdc09ef9132eec84a75478e05579 Reviewed-on: https://go-review.googlesource.com/c/go/+/324129 Run-TryBot: Rhys Hiltner TryBot-Result: Go Bot Trust: David Chase Reviewed-by: Michael Pratt --- src/runtime/cgocall.go | 7 ++ src/runtime/os_linux.go | 147 +++++++++++++++++++++++++++++-- src/runtime/pprof/pprof_test.go | 101 +++++++++++++++++++++ src/runtime/pprof/rusage_test.go | 40 +++++++++ 4 files changed, 286 insertions(+), 9 deletions(-) create mode 100644 src/runtime/pprof/rusage_test.go diff --git a/src/runtime/cgocall.go b/src/runtime/cgocall.go index 2f3c609907..694b3e66cd 100644 --- a/src/runtime/cgocall.go +++ b/src/runtime/cgocall.go @@ -291,6 +291,13 @@ func cgocallbackg1(fn, frame unsafe.Pointer, ctxt uintptr) { <-main_init_done } + // Check whether the profiler needs to be turned on or off; this route to + // run Go code does not use runtime.execute, so bypasses the check there. + hz := sched.profilehz + if gp.m.profilehz != hz { + setThreadCPUProfiler(hz) + } + // Add entry to defer stack in case of panic. restore := true defer unwindm(&restore) diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go index d307c472b8..a4646577cb 100644 --- a/src/runtime/os_linux.go +++ b/src/runtime/os_linux.go @@ -7,10 +7,21 @@ package runtime import ( "internal/abi" "internal/goarch" + "runtime/internal/atomic" "unsafe" ) -type mOS struct{} +type mOS struct { + // profileTimer holds the ID of the POSIX interval timer for profiling CPU + // usage on this thread. + // + // It is valid when the profileTimerValid field is non-zero. A thread + // creates and manages its own timer, and these fields are read and written + // only by this thread. But because some of the reads on profileTimerValid + // are in signal handling code, access to that field uses atomic operations. + profileTimer int32 + profileTimerValid uint32 +} //go:noescape func futex(addr unsafe.Pointer, op int32, val uint32, ts, addr2 unsafe.Pointer, val3 uint32) int32 @@ -518,18 +529,136 @@ func signalM(mp *m, sig int) { tgkill(getpid(), int(mp.procid), sig) } +// go118UseTimerCreateProfiler enables the per-thread CPU profiler. Platforms +// with support for SetCgoTraceback do some signal handling in assembly; do not +// enable it for them until the changes to those code paths are in place. +const go118UseTimerCreateProfiler = GOARCH != "amd64" && GOARCH != "ppc64le" + +// validSIGPROF compares this signal delivery's code against the signal sources +// that the profiler uses, returning whether the delivery should be processed. +// To be processed, a signal delivery from a known profiling mechanism should +// correspond to the best profiling mechanism available to this thread. Signals +// from other sources are always considered valid. +// +//go:nosplit +func validSIGPROF(mp *m, c *sigctxt) bool { + code := int32(c.sigcode()) + setitimer := code == _SI_KERNEL + timer_create := code == _SI_TIMER + + if !(setitimer || timer_create) { + // The signal doesn't correspond to a profiling mechanism that the + // runtime enables itself. There's no reason to process it, but there's + // no reason to ignore it either. + return true + } + + if mp == nil { + // Since we don't have an M, we can't check if there's an active + // per-thread timer for this thread. We don't know how long this thread + // has been around, and if it happened to interact with the Go scheduler + // at a time when profiling was active (causing it to have a per-thread + // timer). But it may have never interacted with the Go scheduler, or + // never while profiling was active. To avoid double-counting, process + // only signals from setitimer. + // + // When a custom cgo traceback function has been registered (on + // platforms that support runtime.SetCgoTraceback), SIGPROF signals + // delivered to a thread that cannot find a matching M do this check in + // the assembly implementations of runtime.cgoSigtramp. + return setitimer + } + + // Having an M means the thread interacts with the Go scheduler, and we can + // check whether there's an active per-thread timer for this thread. + if atomic.Load(&mp.profileTimerValid) != 0 { + // If this M has its own per-thread CPU profiling interval timer, we + // should track the SIGPROF signals that come from that timer (for + // accurate reporting of its CPU usage; see issue 35057) and ignore any + // that it gets from the process-wide setitimer (to not over-count its + // CPU consumption). + return timer_create + } + + // No active per-thread timer means the only valid profiler is setitimer. + return setitimer +} + func setProcessCPUProfiler(hz int32) { setProcessCPUProfilerTimer(hz) } func setThreadCPUProfiler(hz int32) { - setThreadCPUProfilerHz(hz) -} + mp := getg().m + mp.profilehz = hz -//go:nosplit -func validSIGPROF(mp *m, c *sigctxt) bool { - // Once the profiler for Linux uses timer_create, this function will need to - // do more than return true. But so long as the only profiling timer in use - // is setitimer, returning true is correct. - return true + if !go118UseTimerCreateProfiler { + return + } + + // destroy any active timer + if atomic.Load(&mp.profileTimerValid) != 0 { + timerid := mp.profileTimer + atomic.Store(&mp.profileTimerValid, 0) + mp.profileTimer = 0 + + ret := timer_delete(timerid) + if ret != 0 { + print("runtime: failed to disable profiling timer; timer_delete(", timerid, ") errno=", -ret, "\n") + throw("timer_delete") + } + } + + if hz == 0 { + // If the goal was to disable profiling for this thread, then the job's done. + return + } + + // The period of the timer should be 1/Hz. For every "1/Hz" of additional + // work, the user should expect one additional sample in the profile. + // + // But to scale down to very small amounts of application work, to observe + // even CPU usage of "one tenth" of the requested period, set the initial + // timing delay in a different way: So that "one tenth" of a period of CPU + // spend shows up as a 10% chance of one sample (for an expected value of + // 0.1 samples), and so that "two and six tenths" periods of CPU spend show + // up as a 60% chance of 3 samples and a 40% chance of 2 samples (for an + // expected value of 2.6). Set the initial delay to a value in the unifom + // random distribution between 0 and the desired period. And because "0" + // means "disable timer", add 1 so the half-open interval [0,period) turns + // into (0,period]. + // + // Otherwise, this would show up as a bias away from short-lived threads and + // from threads that are only occasionally active: for example, when the + // garbage collector runs on a mostly-idle system, the additional threads it + // activates may do a couple milliseconds of GC-related work and nothing + // else in the few seconds that the profiler observes. + spec := new(itimerspec) + spec.it_value.setNsec(1 + int64(fastrandn(uint32(1e9/hz)))) + spec.it_interval.setNsec(1e9 / int64(hz)) + + var timerid int32 + sevp := &sigevent{ + notify: _SIGEV_THREAD_ID, + signo: _SIGPROF, + sigev_notify_thread_id: int32(mp.procid), + } + ret := timer_create(_CLOCK_THREAD_CPUTIME_ID, sevp, &timerid) + if ret != 0 { + // If we cannot create a timer for this M, leave profileTimerValid false + // to fall back to the process-wide setitimer profiler. + return + } + + ret = timer_settime(timerid, 0, spec, nil) + if ret != 0 { + print("runtime: failed to configure profiling timer; timer_settime(", timerid, + ", 0, {interval: {", + spec.it_interval.tv_sec, "s + ", spec.it_interval.tv_nsec, "ns} value: {", + spec.it_value.tv_sec, "s + ", spec.it_value.tv_nsec, "ns}}, nil) errno=", -ret, "\n") + throw("timer_settime") + } + + mp.profileTimer = timerid + atomic.Store(&mp.profileTimerValid, 1) } diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go index 5b9ad50746..8c34d39ad5 100644 --- a/src/runtime/pprof/pprof_test.go +++ b/src/runtime/pprof/pprof_test.go @@ -79,6 +79,10 @@ func cpuHog2(x int) int { return foo } +func cpuHog3(x int) int { + return cpuHog0(x, 1e5) +} + // Return a list of functions that we don't want to ever appear in CPU // profiles. For gccgo, that list includes the sigprof handler itself. func avoidFunctions() []string { @@ -107,6 +111,93 @@ func TestCPUProfileMultithreaded(t *testing.T) { }) } +func TestCPUProfileMultithreadMagnitude(t *testing.T) { + if runtime.GOOS != "linux" { + t.Skip("issue 35057 is only confirmed on Linux") + } + + // Run a workload in a single goroutine, then run copies of the same + // workload in several goroutines. For both the serial and parallel cases, + // the CPU time the process measures with its own profiler should match the + // total CPU usage that the OS reports. + // + // We could also check that increases in parallelism (GOMAXPROCS) lead to a + // linear increase in the CPU usage reported by both the OS and the + // profiler, but without a guarantee of exclusive access to CPU resources + // that is likely to be a flaky test. + + // Require the smaller value to be within 10%, or 40% in short mode. + maxDiff := 0.10 + if testing.Short() { + maxDiff = 0.40 + } + + parallelism := runtime.GOMAXPROCS(0) + + var cpuTime1, cpuTimeN time.Duration + p := testCPUProfile(t, stackContains, []string{"runtime/pprof.cpuHog1", "runtime/pprof.cpuHog3"}, avoidFunctions(), func(dur time.Duration) { + cpuTime1 = diffCPUTime(t, func() { + // Consume CPU in one goroutine + cpuHogger(cpuHog1, &salt1, dur) + }) + + cpuTimeN = diffCPUTime(t, func() { + // Next, consume CPU in several goroutines + var wg sync.WaitGroup + var once sync.Once + for i := 0; i < parallelism; i++ { + wg.Add(1) + go func() { + defer wg.Done() + var salt = 0 + cpuHogger(cpuHog3, &salt, dur) + once.Do(func() { salt1 = salt }) + }() + } + wg.Wait() + }) + }) + + for i, unit := range []string{"count", "nanoseconds"} { + if have, want := p.SampleType[i].Unit, unit; have != want { + t.Errorf("pN SampleType[%d]; %q != %q", i, have, want) + } + } + + var value1, valueN time.Duration + for _, sample := range p.Sample { + if stackContains("runtime/pprof.cpuHog1", uintptr(sample.Value[0]), sample.Location, sample.Label) { + value1 += time.Duration(sample.Value[1]) * time.Nanosecond + } + if stackContains("runtime/pprof.cpuHog3", uintptr(sample.Value[0]), sample.Location, sample.Label) { + valueN += time.Duration(sample.Value[1]) * time.Nanosecond + } + } + + compare := func(a, b time.Duration, maxDiff float64) func(*testing.T) { + return func(t *testing.T) { + t.Logf("compare %s vs %s", a, b) + if a <= 0 || b <= 0 { + t.Errorf("Expected both time reports to be positive") + return + } + + if a < b { + a, b = b, a + } + + diff := float64(a-b) / float64(a) + if diff > maxDiff { + t.Errorf("CPU usage reports are too different (limit -%.1f%%, got -%.1f%%)", maxDiff*100, diff*100) + } + } + } + + // check that the OS's perspective matches what the Go runtime measures + t.Run("serial execution OS vs pprof", compare(cpuTime1, value1, maxDiff)) + t.Run("parallel execution OS vs pprof", compare(cpuTimeN, valueN, maxDiff)) +} + // containsInlinedCall reports whether the function body for the function f is // known to contain an inlined function call within the first maxBytes bytes. func containsInlinedCall(f interface{}, maxBytes int) bool { @@ -350,6 +441,16 @@ func testCPUProfile(t *testing.T, matches matchFunc, need []string, avoid []stri return nil } +var diffCPUTimeImpl func(f func()) time.Duration + +func diffCPUTime(t *testing.T, f func()) time.Duration { + if fn := diffCPUTimeImpl; fn != nil { + return fn(f) + } + t.Fatalf("cannot measure CPU time on GOOS=%s GOARCH=%s", runtime.GOOS, runtime.GOARCH) + return 0 +} + func contains(slice []string, s string) bool { for i := range slice { if slice[i] == s { diff --git a/src/runtime/pprof/rusage_test.go b/src/runtime/pprof/rusage_test.go new file mode 100644 index 0000000000..66b1b3bbe1 --- /dev/null +++ b/src/runtime/pprof/rusage_test.go @@ -0,0 +1,40 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin || freebsd || linux || netbsd || openbsd +// +build darwin freebsd linux netbsd openbsd + +package pprof + +import ( + "syscall" + "time" +) + +func init() { + diffCPUTimeImpl = diffCPUTimeRUsage +} + +func diffCPUTimeRUsage(f func()) time.Duration { + ok := true + var before, after syscall.Rusage + + err := syscall.Getrusage(syscall.RUSAGE_SELF, &before) + if err != nil { + ok = false + } + + f() + + err = syscall.Getrusage(syscall.RUSAGE_SELF, &after) + if err != nil { + ok = false + } + + if !ok { + return 0 + } + + return time.Duration((after.Utime.Nano() + after.Stime.Nano()) - (before.Utime.Nano() + before.Stime.Nano())) +} -- GitLab From 5b909580849c611c633c111a15adb40c9c42ec8e Mon Sep 17 00:00:00 2001 From: Rhys Hiltner Date: Thu, 23 Sep 2021 16:46:58 -0700 Subject: [PATCH 1324/2500] runtime: move sigprofNonGo The sigprofNonGo and sigprofNonGoPC functions are only used on unix-like platforms. In preparation for unix-specific changes to sigprofNonGo, move it (plus its close relative) to a unix-specific file. Updates #35057 Change-Id: I9c814127c58612ea9a9fbd28a992b04ace5c604d Reviewed-on: https://go-review.googlesource.com/c/go/+/351790 Run-TryBot: Rhys Hiltner TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Reviewed-by: Michael Pratt Trust: David Chase --- src/runtime/proc.go | 39 ------------------------------------- src/runtime/signal_unix.go | 40 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 39 deletions(-) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index b744d0e71e..2f619f93d3 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -4705,45 +4705,6 @@ func sigprof(pc, sp, lr uintptr, gp *g, mp *m) { getg().m.mallocing-- } -// If the signal handler receives a SIGPROF signal on a non-Go thread, -// it tries to collect a traceback into sigprofCallers. -// sigprofCallersUse is set to non-zero while sigprofCallers holds a traceback. -var sigprofCallers cgoCallers -var sigprofCallersUse uint32 - -// sigprofNonGo is called if we receive a SIGPROF signal on a non-Go thread, -// and the signal handler collected a stack trace in sigprofCallers. -// When this is called, sigprofCallersUse will be non-zero. -// g is nil, and what we can do is very limited. -//go:nosplit -//go:nowritebarrierrec -func sigprofNonGo() { - if prof.hz != 0 { - n := 0 - for n < len(sigprofCallers) && sigprofCallers[n] != 0 { - n++ - } - cpuprof.addNonGo(sigprofCallers[:n]) - } - - atomic.Store(&sigprofCallersUse, 0) -} - -// sigprofNonGoPC is called when a profiling signal arrived on a -// non-Go thread and we have a single PC value, not a stack trace. -// g is nil, and what we can do is very limited. -//go:nosplit -//go:nowritebarrierrec -func sigprofNonGoPC(pc uintptr) { - if prof.hz != 0 { - stk := []uintptr{ - pc, - abi.FuncPCABIInternal(_ExternalCode) + sys.PCQuantum, - } - cpuprof.addNonGo(stk) - } -} - // setcpuprofilerate sets the CPU profiling rate to hz times per second. // If hz <= 0, setcpuprofilerate turns off CPU profiling. func setcpuprofilerate(hz int32) { diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go index 228497c508..0b32598d54 100644 --- a/src/runtime/signal_unix.go +++ b/src/runtime/signal_unix.go @@ -10,6 +10,7 @@ package runtime import ( "internal/abi" "runtime/internal/atomic" + "runtime/internal/sys" "unsafe" ) @@ -469,6 +470,45 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) { } } +// If the signal handler receives a SIGPROF signal on a non-Go thread, +// it tries to collect a traceback into sigprofCallers. +// sigprofCallersUse is set to non-zero while sigprofCallers holds a traceback. +var sigprofCallers cgoCallers +var sigprofCallersUse uint32 + +// sigprofNonGo is called if we receive a SIGPROF signal on a non-Go thread, +// and the signal handler collected a stack trace in sigprofCallers. +// When this is called, sigprofCallersUse will be non-zero. +// g is nil, and what we can do is very limited. +//go:nosplit +//go:nowritebarrierrec +func sigprofNonGo() { + if prof.hz != 0 { + n := 0 + for n < len(sigprofCallers) && sigprofCallers[n] != 0 { + n++ + } + cpuprof.addNonGo(sigprofCallers[:n]) + } + + atomic.Store(&sigprofCallersUse, 0) +} + +// sigprofNonGoPC is called when a profiling signal arrived on a +// non-Go thread and we have a single PC value, not a stack trace. +// g is nil, and what we can do is very limited. +//go:nosplit +//go:nowritebarrierrec +func sigprofNonGoPC(pc uintptr) { + if prof.hz != 0 { + stk := []uintptr{ + pc, + abi.FuncPCABIInternal(_ExternalCode) + sys.PCQuantum, + } + cpuprof.addNonGo(stk) + } +} + // adjustSignalStack adjusts the current stack guard based on the // stack pointer that is actually in use while handling a signal. // We do this in case some non-Go code called sigaltstack. -- GitLab From 8d09f7c5178b04bade2859d32d0710233a620d4f Mon Sep 17 00:00:00 2001 From: Rhys Hiltner Date: Fri, 13 Aug 2021 09:01:13 -0700 Subject: [PATCH 1325/2500] runtime: use per-thread profiler for SetCgoTraceback platforms Updates #35057 Change-Id: I61d772a2cbfb27540fb70c14676c68593076ca94 Reviewed-on: https://go-review.googlesource.com/c/go/+/342054 Run-TryBot: Rhys Hiltner TryBot-Result: Go Bot Reviewed-by: Michael Pratt Trust: Michael Knyszek --- src/runtime/os_linux.go | 6 ++---- src/runtime/signal_unix.go | 21 ++++++++++++++++----- src/runtime/sys_darwin_amd64.s | 23 ++++++++++++++++++++--- src/runtime/sys_freebsd_amd64.s | 23 ++++++++++++++++++++--- src/runtime/sys_linux_amd64.s | 23 ++++++++++++++++++++--- src/runtime/sys_linux_ppc64x.s | 3 +++ 6 files changed, 81 insertions(+), 18 deletions(-) diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go index a4646577cb..06773c2193 100644 --- a/src/runtime/os_linux.go +++ b/src/runtime/os_linux.go @@ -529,10 +529,8 @@ func signalM(mp *m, sig int) { tgkill(getpid(), int(mp.procid), sig) } -// go118UseTimerCreateProfiler enables the per-thread CPU profiler. Platforms -// with support for SetCgoTraceback do some signal handling in assembly; do not -// enable it for them until the changes to those code paths are in place. -const go118UseTimerCreateProfiler = GOARCH != "amd64" && GOARCH != "ppc64le" +// go118UseTimerCreateProfiler enables the per-thread CPU profiler. +const go118UseTimerCreateProfiler = true // validSIGPROF compares this signal delivery's code against the signal sources // that the profiler uses, returning whether the delivery should be processed. diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go index 0b32598d54..07f371cefe 100644 --- a/src/runtime/signal_unix.go +++ b/src/runtime/signal_unix.go @@ -480,15 +480,26 @@ var sigprofCallersUse uint32 // and the signal handler collected a stack trace in sigprofCallers. // When this is called, sigprofCallersUse will be non-zero. // g is nil, and what we can do is very limited. +// +// It is called from the signal handling functions written in assembly code that +// are active for cgo programs, cgoSigtramp and sigprofNonGoWrapper, which have +// not verified that the SIGPROF delivery corresponds to the best available +// profiling source for this thread. +// //go:nosplit //go:nowritebarrierrec -func sigprofNonGo() { +func sigprofNonGo(sig uint32, info *siginfo, ctx unsafe.Pointer) { if prof.hz != 0 { - n := 0 - for n < len(sigprofCallers) && sigprofCallers[n] != 0 { - n++ + c := &sigctxt{info, ctx} + // Some platforms (Linux) have per-thread timers, which we use in + // combination with the process-wide timer. Avoid double-counting. + if validSIGPROF(nil, c) { + n := 0 + for n < len(sigprofCallers) && sigprofCallers[n] != 0 { + n++ + } + cpuprof.addNonGo(sigprofCallers[:n]) } - cpuprof.addNonGo(sigprofCallers[:n]) } atomic.Store(&sigprofCallersUse, 0) diff --git a/src/runtime/sys_darwin_amd64.s b/src/runtime/sys_darwin_amd64.s index 3bd027f982..5d89cda8e6 100644 --- a/src/runtime/sys_darwin_amd64.s +++ b/src/runtime/sys_darwin_amd64.s @@ -230,6 +230,23 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0 POP_REGS_HOST_TO_ABI0() RET +// Called using C ABI. +TEXT runtime·sigprofNonGoWrapper<>(SB),NOSPLIT,$0 + // Transition from C ABI to Go ABI. + PUSH_REGS_HOST_TO_ABI0() + + // Call into the Go signal handler + NOP SP // disable vet stack checking + ADJSP $24 + MOVL DI, 0(SP) // sig + MOVQ SI, 8(SP) // info + MOVQ DX, 16(SP) // ctx + CALL ·sigprofNonGo(SB) + ADJSP $-24 + + POP_REGS_HOST_TO_ABI0() + RET + // Used instead of sigtramp in programs that use cgo. // Arguments from kernel are in DI, SI, DX. TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0 @@ -297,12 +314,12 @@ sigtrampnog: JNZ sigtramp // Skip stack trace if already locked. // Jump to the traceback function in runtime/cgo. - // It will call back to sigprofNonGo, which will ignore the - // arguments passed in registers. + // It will call back to sigprofNonGo, via sigprofNonGoWrapper, to convert + // the arguments to the Go calling convention. // First three arguments to traceback function are in registers already. MOVQ runtime·cgoTraceback(SB), CX MOVQ $runtime·sigprofCallers(SB), R8 - MOVQ $runtime·sigprofNonGo(SB), R9 + MOVQ $runtime·sigprofNonGoWrapper<>(SB), R9 MOVQ _cgo_callers(SB), AX JMP AX diff --git a/src/runtime/sys_freebsd_amd64.s b/src/runtime/sys_freebsd_amd64.s index 71a60cae65..165e97c60d 100644 --- a/src/runtime/sys_freebsd_amd64.s +++ b/src/runtime/sys_freebsd_amd64.s @@ -255,6 +255,23 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0 POP_REGS_HOST_TO_ABI0() RET +// Called using C ABI. +TEXT runtime·sigprofNonGoWrapper<>(SB),NOSPLIT,$0 + // Transition from C ABI to Go ABI. + PUSH_REGS_HOST_TO_ABI0() + + // Call into the Go signal handler + NOP SP // disable vet stack checking + ADJSP $24 + MOVL DI, 0(SP) // sig + MOVQ SI, 8(SP) // info + MOVQ DX, 16(SP) // ctx + CALL ·sigprofNonGo(SB) + ADJSP $-24 + + POP_REGS_HOST_TO_ABI0() + RET + // Used instead of sigtramp in programs that use cgo. // Arguments from kernel are in DI, SI, DX. TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0 @@ -322,12 +339,12 @@ sigtrampnog: JNZ sigtramp // Skip stack trace if already locked. // Jump to the traceback function in runtime/cgo. - // It will call back to sigprofNonGo, which will ignore the - // arguments passed in registers. + // It will call back to sigprofNonGo, via sigprofNonGoWrapper, to convert + // the arguments to the Go calling convention. // First three arguments to traceback function are in registers already. MOVQ runtime·cgoTraceback(SB), CX MOVQ $runtime·sigprofCallers(SB), R8 - MOVQ $runtime·sigprofNonGo(SB), R9 + MOVQ $runtime·sigprofNonGoWrapper<>(SB), R9 MOVQ _cgo_callers(SB), AX JMP AX diff --git a/src/runtime/sys_linux_amd64.s b/src/runtime/sys_linux_amd64.s index 345dc90eb0..f0e58e11db 100644 --- a/src/runtime/sys_linux_amd64.s +++ b/src/runtime/sys_linux_amd64.s @@ -364,6 +364,23 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0 POP_REGS_HOST_TO_ABI0() RET +// Called using C ABI. +TEXT runtime·sigprofNonGoWrapper<>(SB),NOSPLIT,$0 + // Transition from C ABI to Go ABI. + PUSH_REGS_HOST_TO_ABI0() + + // Call into the Go signal handler + NOP SP // disable vet stack checking + ADJSP $24 + MOVL DI, 0(SP) // sig + MOVQ SI, 8(SP) // info + MOVQ DX, 16(SP) // ctx + CALL ·sigprofNonGo(SB) + ADJSP $-24 + + POP_REGS_HOST_TO_ABI0() + RET + // Used instead of sigtramp in programs that use cgo. // Arguments from kernel are in DI, SI, DX. TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0 @@ -431,12 +448,12 @@ sigtrampnog: JNZ sigtramp // Skip stack trace if already locked. // Jump to the traceback function in runtime/cgo. - // It will call back to sigprofNonGo, which will ignore the - // arguments passed in registers. + // It will call back to sigprofNonGo, via sigprofNonGoWrapper, to convert + // the arguments to the Go calling convention. // First three arguments to traceback function are in registers already. MOVQ runtime·cgoTraceback(SB), CX MOVQ $runtime·sigprofCallers(SB), R8 - MOVQ $runtime·sigprofNonGo(SB), R9 + MOVQ $runtime·sigprofNonGoWrapper<>(SB), R9 MOVQ _cgo_callers(SB), AX JMP AX diff --git a/src/runtime/sys_linux_ppc64x.s b/src/runtime/sys_linux_ppc64x.s index 56d600b6ea..9347afaf19 100644 --- a/src/runtime/sys_linux_ppc64x.s +++ b/src/runtime/sys_linux_ppc64x.s @@ -743,6 +743,9 @@ TEXT cgoSigtramp<>(SB),NOSPLIT,$0 TEXT runtime·sigprofNonGoWrapper<>(SB),NOSPLIT,$0 // We're coming from C code, set up essential register, then call sigprofNonGo. CALL runtime·reginit(SB) + MOVW R3, FIXED_FRAME+0(R1) // sig + MOVD R4, FIXED_FRAME+8(R1) // info + MOVD R5, FIXED_FRAME+16(R1) // ctx CALL runtime·sigprofNonGo(SB) RET -- GitLab From a80cbc25bddfa1e6be76cf539ae9276d41b5108f Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 24 Sep 2021 14:55:06 -0700 Subject: [PATCH 1326/2500] runtime: elide instantiated types in tracebacks They tend to be things like ".shape.int" which are noisy, if not otherwise confusing. It would be nice to somehow print the real instantiations here, but that requires keeping track of the dictionary argument so the instantiating types could be found. One day, maybe, but not today. Fixes #48578 Change-Id: I0968d24e110b6d47c9468c45372a6979575a8d29 Reviewed-on: https://go-review.googlesource.com/c/go/+/352118 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/link/internal/ld/pcln.go | 30 +++++++++++++++++-- src/cmd/link/internal/loader/loader.go | 16 ---------- src/cmd/link/internal/loader/symbolbuilder.go | 10 +++++++ 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index 3abbf05c54..56c4fe0b46 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -14,6 +14,7 @@ import ( "internal/buildcfg" "os" "path/filepath" + "strings" ) // pclntab holds the state needed for pclntab generation. @@ -286,11 +287,35 @@ func walkFuncs(ctxt *Link, funcs []loader.Sym, f func(loader.Sym)) { func (state *pclntab) generateFuncnametab(ctxt *Link, funcs []loader.Sym) map[loader.Sym]uint32 { nameOffsets := make(map[loader.Sym]uint32, state.nfunc) + // The name used by the runtime is the concatenation of the 3 returned strings. + // For regular functions, only one returned string is nonempty. + // For generic functions, we use three parts so that we can print everything + // within the outermost "[]" as "...". + nameParts := func(name string) (string, string, string) { + i := strings.IndexByte(name, '[') + if i < 0 { + return name, "", "" + } + // TODO: use LastIndexByte once the bootstrap compiler is >= Go 1.5. + j := len(name) - 1 + for j > i && name[j] != ']' { + j-- + } + if j <= i { + return name, "", "" + } + return name[:i], "[...]", name[j+1:] + } + // Write the null terminated strings. writeFuncNameTab := func(ctxt *Link, s loader.Sym) { symtab := ctxt.loader.MakeSymbolUpdater(s) for s, off := range nameOffsets { - symtab.AddStringAt(int64(off), ctxt.loader.SymName(s)) + a, b, c := nameParts(ctxt.loader.SymName(s)) + o := int64(off) + o = symtab.AddStringAt(o, a) + o = symtab.AddStringAt(o, b) + _ = symtab.AddCStringAt(o, c) } } @@ -298,7 +323,8 @@ func (state *pclntab) generateFuncnametab(ctxt *Link, funcs []loader.Sym) map[lo var size int64 walkFuncs(ctxt, funcs, func(s loader.Sym) { nameOffsets[s] = uint32(size) - size += int64(ctxt.loader.SymNameLen(s)) + 1 // NULL terminate + a, b, c := nameParts(ctxt.loader.SymName(s)) + size += int64(len(a) + len(b) + len(c) + 1) // NULL terminate }) state.funcnametab = state.addGeneratedSym(ctxt, "runtime.funcnametab", size, writeFuncNameTab) diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index dcc33b966b..4bf5475a32 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -752,22 +752,6 @@ func (l *Loader) NReachableSym() int { return l.attrReachable.Count() } -// SymNameLen returns the length of the symbol name, trying hard not to load -// the name. -func (l *Loader) SymNameLen(i Sym) int { - // Not much we can do about external symbols. - if l.IsExternal(i) { - return len(l.SymName(i)) - } - r, li := l.toLocal(i) - le := r.Sym(li).NameLen(r.Reader) - if !r.NeedNameExpansion() { - return le - } - // Just load the symbol name. We don't know how expanded it'll be. - return len(l.SymName(i)) -} - // Returns the raw (unpatched) name of the i-th symbol. func (l *Loader) RawSymName(i Sym) string { if l.IsExternal(i) { diff --git a/src/cmd/link/internal/loader/symbolbuilder.go b/src/cmd/link/internal/loader/symbolbuilder.go index 204d04412d..558c0a7dff 100644 --- a/src/cmd/link/internal/loader/symbolbuilder.go +++ b/src/cmd/link/internal/loader/symbolbuilder.go @@ -308,6 +308,16 @@ func (sb *SymbolBuilder) SetAddr(arch *sys.Arch, off int64, tgt Sym) int64 { } func (sb *SymbolBuilder) AddStringAt(off int64, str string) int64 { + strLen := int64(len(str)) + if off+strLen > int64(len(sb.data)) { + panic("attempt to write past end of buffer") + } + copy(sb.data[off:off+strLen], str) + return off + strLen +} + +// AddCStringAt adds str plus a null terminating byte. +func (sb *SymbolBuilder) AddCStringAt(off int64, str string) int64 { strLen := int64(len(str)) if off+strLen+1 > int64(len(sb.data)) { panic("attempt to write past end of buffer") -- GitLab From 315cec25bc7b5045f6081545a63cb27d44fcbde9 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 24 Sep 2021 15:07:59 -0700 Subject: [PATCH 1327/2500] cmd/compile: leave dictionary argument out of traceback argument list The dictionary argument is implicit; the user doesn't need to see it. Update #48578 Change-Id: I367ba4b6622119d3e01aaded90463d16823915a7 Reviewed-on: https://go-review.googlesource.com/c/go/+/352119 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/ssagen/ssa.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index baf7242f4a..56fc191e5a 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -6664,7 +6664,13 @@ func EmitArgInfo(f *ir.Func, abiInfo *abi.ABIParamResultInfo) *obj.LSym { return true } - for _, a := range abiInfo.InParams() { + start := 0 + if strings.Contains(f.LSym.Name, "[") { + // Skip the dictionary argument - it is implicit and the user doesn't need to see it. + start = 1 + } + + for _, a := range abiInfo.InParams()[start:] { if !visitType(a.FrameOffset(abiInfo), a.Type, 0) { break } -- GitLab From 964ea8c6482f48b242072697d150bb2192710892 Mon Sep 17 00:00:00 2001 From: Zvonimir Pavlinovic Date: Thu, 23 Sep 2021 15:50:22 -0700 Subject: [PATCH 1328/2500] cmd/go/testdata/script: fix incorrect comments Change-Id: I675d66c229a4293146366bc9b927e0fd2d7a3eeb Reviewed-on: https://go-review.googlesource.com/c/go/+/351929 Run-TryBot: Zvonimir Pavlinovic TryBot-Result: Go Bot Reviewed-by: Ingo Oeser Reviewed-by: Bryan C. Mills Trust: Than McIntosh Trust: Zvonimir Pavlinovic --- src/cmd/go/testdata/script/test_vet.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/go/testdata/script/test_vet.txt b/src/cmd/go/testdata/script/test_vet.txt index 687d4851de..6151f912ae 100644 --- a/src/cmd/go/testdata/script/test_vet.txt +++ b/src/cmd/go/testdata/script/test_vet.txt @@ -24,11 +24,11 @@ stderr 'using resp before checking for errors' ! go test -vet=bools,xyz ./vetall/... stderr '-vet argument must be a supported analyzer' -# Test with a list of analyzers +# Test with a single analyzer ! go test -vet=httpresponse ./vetall/... stderr 'using resp before checking for errors' -# Test with a single analyzer +# Test with a list of analyzers go test -vet=atomic,bools,nilfunc ./vetall/... stdout 'm/vetall.*\[no tests to run\]' -- GitLab From dfd875d015fb67671a2374c229e2159388d37693 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 22 Sep 2021 20:20:09 -0700 Subject: [PATCH 1329/2500] cmd/compile: allow methods on shape types (but no bodies) In a previous change, I was too aggressive in substInstType() in not generating methods for shape types during import. We do actually want to generate the method nodes - we just don't want to generate method bodies (which we would never use). We may need the method nodes for checking types later in the compile (especially with inlining). So, we do generate method nodes for shape types during import. In order to avoid the name collision we previously had, we now add ".nofunc." to the method nodes for shape types (during import and in the type substituter). We do that by passing in a 'isMethodNode' arg to MakeInstSym. We keep the normal name (without ".nofunc") for any other method nodes, and for the instantiated functions that help with implementing the methods of fully-instantiated types. The ".nofunc" names will never appear in the executable, since we don't generate any method bodies for the method nodes of shape types. Change-Id: I3e57e328691214140ca5f48d32011552d2a0d45d Reviewed-on: https://go-review.googlesource.com/c/go/+/352470 Trust: Dan Scales Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 2 +- .../compile/internal/reflectdata/reflect.go | 2 +- src/cmd/compile/internal/typecheck/iimport.go | 7 +------ src/cmd/compile/internal/typecheck/subr.go | 21 ++++++++++++++----- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index bc142e6985..772fcca46a 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -626,7 +626,7 @@ func (g *irgen) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMeth shapes = s1 } - sym := typecheck.MakeFuncInstSym(nameNode.Sym(), shapes, isMeth) + sym := typecheck.MakeFuncInstSym(nameNode.Sym(), shapes, false, isMeth) info := g.instInfoMap[sym] if info == nil { // If instantiation doesn't exist yet, create it and add diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 44919c2a4b..295dc2cdfa 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -1927,7 +1927,7 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy } targs = targs2 - sym := typecheck.MakeFuncInstSym(ir.MethodSym(methodrcvr, method.Sym), targs, true) + sym := typecheck.MakeFuncInstSym(ir.MethodSym(methodrcvr, method.Sym), targs, false, true) if sym.Def == nil { // Currently we make sure that we have all the instantiations // we need by generating them all in ../noder/stencil.go:instantiateMethods diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 9bd8e35a13..77119ce9bd 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1867,11 +1867,6 @@ func substInstType(t *types.Type, baseType *types.Type, targs []*types.Type) { } t.SetUnderlying(subst.Typ(baseType.Underlying())) - if t.HasShape() && !t.IsInterface() { - // Concrete shape types have no methods. - return - } - newfields := make([]*types.Field, baseType.Methods().Len()) for i, f := range baseType.Methods().Slice() { if !f.IsMethod() || types.IsInterfaceMethod(f.Type) { @@ -1895,7 +1890,7 @@ func substInstType(t *types.Type, baseType *types.Type, targs []*types.Type) { } t2 := msubst.Typ(f.Type) oldsym := f.Nname.Sym() - newsym := MakeFuncInstSym(oldsym, targs, true) + newsym := MakeFuncInstSym(oldsym, targs, true, true) var nname *ir.Name if newsym.Def != nil { nname = newsym.Def.(*ir.Name) diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index fbfe1b3720..56e6ec0e27 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -962,8 +962,8 @@ func makeInstName1(name string, targs []*types.Type, hasBrackets bool) string { } // MakeFuncInstSym makes the unique sym for a stenciled generic function or method, -// based on the name of the function fnsym and the targs. It replaces any -// existing bracket type list in the name. MakeInstName asserts that fnsym has +// based on the name of the function gf and the targs. It replaces any +// existing bracket type list in the name. MakeInstName asserts that gf has // brackets in its name if and only if hasBrackets is true. // // Names of declared generic functions have no brackets originally, so hasBrackets @@ -973,8 +973,19 @@ func makeInstName1(name string, targs []*types.Type, hasBrackets bool) string { // // The standard naming is something like: 'genFn[int,bool]' for functions and // '(*genType[int,bool]).methodName' for methods -func MakeFuncInstSym(gf *types.Sym, targs []*types.Type, hasBrackets bool) *types.Sym { - return gf.Pkg.Lookup(makeInstName1(gf.Name, targs, hasBrackets)) +// +// isMethodNode specifies if the name of a method node is being generated (as opposed +// to a name of an instantiation of generic function or name of the shape-based +// function that helps implement a method of an instantiated type). For method nodes +// on shape types, we prepend "nofunc.", because method nodes for shape types will +// have no body, and we want to avoid a name conflict with the shape-based function +// that helps implement the same method for fully-instantiated types. +func MakeFuncInstSym(gf *types.Sym, targs []*types.Type, isMethodNode, hasBrackets bool) *types.Sym { + nm := makeInstName1(gf.Name, targs, hasBrackets) + if targs[0].HasShape() && isMethodNode { + nm = "nofunc." + nm + } + return gf.Pkg.Lookup(nm) } func MakeDictSym(gf *types.Sym, targs []*types.Type, hasBrackets bool) *types.Sym { @@ -1262,7 +1273,7 @@ func (ts *Tsubster) typ1(t *types.Type) *types.Type { for i, f := range t.Methods().Slice() { t2 := ts.typ1(f.Type) oldsym := f.Nname.Sym() - newsym := MakeFuncInstSym(oldsym, ts.Targs, true) + newsym := MakeFuncInstSym(oldsym, ts.Targs, true, true) var nname *ir.Name if newsym.Def != nil { nname = newsym.Def.(*ir.Name) -- GitLab From 301f6c8019bea813b039c3d376a6464a0e117dce Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 10 Sep 2021 15:24:16 -0700 Subject: [PATCH 1330/2500] cmd/compile: keep methods on generic types from being deadcode eliminated We currently make dictionaries contain a relocation pointing to methods that generic code might use, so that those methods are not deadcode eliminated. However, with inlining we can end up not using the dictionary, making the reference from the dictionary to the method no longer keep the method alive. Fix this by keeping the dictionary alive at generic interface call sites. It's a bit of overkill, as we only need to keep the dictionary statically alive. We don't actually need it dynamically alive, which is what KeepAlive does. But it works. It ends up generating a LEAQ + stack spill that aren't necessary, but that's pretty low overhead. To make this work, I needed to stop generating methods on shape types. We should do this anyway, as we shouldn't ever need them. But currently we do use them! issue44688.go has a test that only works because it calls a method on a shape type. I've disabled that test for now, will work on it in a subsequent CL. Fixes #48047 Change-Id: I78968868d6486c1745f51b8b43be0898931432a2 Reviewed-on: https://go-review.googlesource.com/c/go/+/349169 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales Reviewed-by: Than McIntosh --- src/cmd/compile/internal/noder/helpers.go | 2 +- src/cmd/compile/internal/noder/stencil.go | 22 +++++++------- src/cmd/compile/internal/noder/transform.go | 15 +++++++++- .../compile/internal/reflectdata/reflect.go | 3 ++ src/cmd/compile/internal/walk/expr.go | 12 +++++++- test/typeparam/issue44688.go | 5 ++-- test/typeparam/issue48047.go | 30 +++++++++++++++++++ 7 files changed, 73 insertions(+), 16 deletions(-) create mode 100644 test/typeparam/issue48047.go diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index e8a1540307..83830a5d31 100644 --- a/src/cmd/compile/internal/noder/helpers.go +++ b/src/cmd/compile/internal/noder/helpers.go @@ -187,7 +187,7 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) // If no type params, do the normal call transformations. This // will convert OCALL to OCALLFUNC. typed(typ, n) - transformCall(n) + transformCall(n, nil) return n } diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 772fcca46a..e49702c04c 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -124,7 +124,7 @@ func (g *irgen) stencil() { // it before installing the instantiation, so we are // checking against non-shape param types in // typecheckaste. - transformCall(call) + transformCall(call, nil) // Replace the OFUNCINST with a direct reference to the // new stenciled function @@ -162,7 +162,7 @@ func (g *irgen) stencil() { // Transform the Call now, which changes OCALL // to OCALLFUNC and does typecheckaste/assignconvfn. - transformCall(call) + transformCall(call, nil) st := g.getInstantiation(gf, targs, true).fun dictValue, usingSubdict := g.getDictOrSubdict(declInfo, n, gf, targs, true) @@ -258,7 +258,7 @@ func (g *irgen) stencil() { assert(l == len(g.instInfoMap)) } -// buildClosure makes a closure to implement x, a OFUNCINST or OMETHEXPR +// buildClosure makes a closure to implement x, a OFUNCINST or OMETHEXPR/OMETHVALUE // of generic type. outer is the containing function (or nil if closure is // in a global assignment instead of a function). func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { @@ -1053,14 +1053,14 @@ func (subst *subster) node(n ir.Node) ir.Node { // transform the call. call.X.(*ir.SelectorExpr).SetOp(ir.OXDOT) transformDot(call.X.(*ir.SelectorExpr), true) - transformCall(call) + transformCall(call, subst.info.dictParam) case ir.ODOT, ir.ODOTPTR: // An OXDOT for a generic receiver was resolved to // an access to a field which has a function // value. Transform the call to that function, now // that the OXDOT was resolved. - transformCall(call) + transformCall(call, subst.info.dictParam) case ir.ONAME: name := call.X.Name() @@ -1077,24 +1077,24 @@ func (subst *subster) node(n ir.Node) ir.Node { // This is the case of a function value that was a // type parameter (implied to be a function via a // structural constraint) which is now resolved. - transformCall(call) + transformCall(call, subst.info.dictParam) } case ir.OCLOSURE: - transformCall(call) + transformCall(call, subst.info.dictParam) case ir.ODEREF, ir.OINDEX, ir.OINDEXMAP, ir.ORECV: // Transform a call that was delayed because of the // use of typeparam inside an expression that required // a pointer dereference, array indexing, map indexing, // or channel receive to compute function value. - transformCall(call) + transformCall(call, subst.info.dictParam) case ir.OCALL, ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER: - transformCall(call) + transformCall(call, subst.info.dictParam) case ir.OCONVNOP: - transformCall(call) + transformCall(call, subst.info.dictParam) case ir.OFUNCINST: // A call with an OFUNCINST will get transformed @@ -1239,7 +1239,7 @@ func (g *irgen) dictPass(info *instInfo) { m.(*ir.CallExpr).X.(*ir.SelectorExpr).SetOp(ir.OXDOT) transformDot(m.(*ir.CallExpr).X.(*ir.SelectorExpr), true) } - transformCall(m.(*ir.CallExpr)) + transformCall(m.(*ir.CallExpr), info.dictParam) } case ir.OCONVIFACE: diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index f7115904fe..9076db2822 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -132,7 +132,9 @@ func transformConvCall(n *ir.CallExpr) ir.Node { // transformCall transforms a normal function/method call. Corresponds to last half // (non-conversion, non-builtin part) of typecheck.tcCall. This code should work even // in the case of OCALL/OFUNCINST. -func transformCall(n *ir.CallExpr) { +// The dict parameter is used for OCALLINTER nodes to ensure that the called method +// is retained by the linker. +func transformCall(n *ir.CallExpr, dict *ir.Name) { // n.Type() can be nil for calls with no return value assert(n.Typecheck() == 1) transformArgs(n) @@ -142,6 +144,17 @@ func transformCall(n *ir.CallExpr) { switch l.Op() { case ir.ODOTINTER: n.SetOp(ir.OCALLINTER) + if n.X.(*ir.SelectorExpr).X.Type().HasShape() { + if dict == nil { + base.Fatalf("calls on shape interfaces need a dictionary reference") + } + dict.SetAddrtaken(true) + // KeepAlive isn't exactly the right thing here, as we only + // need to keep the dictionary live in the linker-deadcode + // sense, not the at-runtime sense. But the at-runtime sense + // is stronger, so it works. See issue 48047. + n.KeepAlive = append(n.KeepAlive, dict) + } case ir.ODOTMETH: l := l.(*ir.SelectorExpr) diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 295dc2cdfa..8503dee60d 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -2006,6 +2006,9 @@ func MarkUsedIfaceMethod(n *ir.CallExpr) { } dot := n.X.(*ir.SelectorExpr) ityp := dot.X.Type() + if ityp.HasShape() { + base.Fatalf("marking method of shape type used %+v %s", ityp, dot.Sel.Name) + } tsym := TypeLinksym(ityp) r := obj.Addrel(ir.CurFunc.LSym) r.Sym = tsym diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go index e5bf6cf0b5..c452cecbed 100644 --- a/src/cmd/compile/internal/walk/expr.go +++ b/src/cmd/compile/internal/walk/expr.go @@ -506,7 +506,17 @@ func walkCall(n *ir.CallExpr, init *ir.Nodes) ir.Node { usemethod(n) } if n.Op() == ir.OCALLINTER { - reflectdata.MarkUsedIfaceMethod(n) + if n.X.(*ir.SelectorExpr).X.Type().HasShape() { + // There should be an entry in n.KeepAlive to keep the + // dictionary alive (added in ../noder/transformCall). + // The dictionary in turn marks the method as used. + if len(n.KeepAlive) == 0 { + // TODO(khr): this fails for issue44688.go. + //base.Fatalf("KeepAlive of dictionary arg missing") + } + } else { + reflectdata.MarkUsedIfaceMethod(n) + } } if n.Op() == ir.OCALLFUNC && n.X.Op() == ir.OCLOSURE { diff --git a/test/typeparam/issue44688.go b/test/typeparam/issue44688.go index 5ebce72628..98260694dc 100644 --- a/test/typeparam/issue44688.go +++ b/test/typeparam/issue44688.go @@ -77,8 +77,9 @@ func test1[T any](arg T) { // calling method expressions m1x := B1[T].m1 m1x(b1, arg) - m2x := B2[T].m2 - m2x(b2, arg) + // TODO(khr): reenable these. + //m2x := B2[T].m2 + //m2x(b2, arg) // calling method values m1v := b1.m1 diff --git a/test/typeparam/issue48047.go b/test/typeparam/issue48047.go new file mode 100644 index 0000000000..1bff65a949 --- /dev/null +++ b/test/typeparam/issue48047.go @@ -0,0 +1,30 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type A[T any] struct { + field B[T] +} + +type B[T any] interface { + Work(T) +} + +func (a *A[T]) Work(t T) { + a.field.Work(t) +} + +type BImpl struct{} + +func (b BImpl) Work(s string) {} + +func main() { + a := &A[string]{ + field: BImpl{}, + } + a.Work("") +} -- GitLab From 2dda92ff6f9f07eeb110ecbf0fc2d7a0ddd27f9d Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 7 Sep 2021 09:44:29 -0700 Subject: [PATCH 1331/2500] runtime: make slice growth formula a bit smoother MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of growing 2x for < 1024 elements and 1.25x for >= 1024 elements, use a somewhat smoother formula for the growth factor. Start reducing the growth factor after 256 elements, but slowly. starting cap growth factor 256 2.0 512 1.63 1024 1.44 2048 1.35 4096 1.30 (Note that the real growth factor, both before and now, is somewhat larger because we round up to the next size class.) This CL also makes the growth monotonic (larger initial capacities make larger final capacities, which was not true before). See discussion at https://groups.google.com/g/golang-nuts/c/UaVlMQ8Nz3o 256 was chosen as the threshold to roughly match the total number of reallocations when appending to eventually make a very large slice. (We allocate smaller when appending to capacities [256,1024] and larger with capacities [1024,...]). Change-Id: I876df09fdc9ae911bb94e41cb62675229cb10512 Reviewed-on: https://go-review.googlesource.com/c/go/+/347917 Trust: Keith Randall Trust: Martin Möhrmann Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Martin Möhrmann --- src/reflect/value.go | 5 +++-- src/runtime/slice.go | 8 ++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/reflect/value.go b/src/reflect/value.go index 33b81d7209..786c494166 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -2487,11 +2487,12 @@ func grow(s Value, extra int) (Value, int, int) { if m == 0 { m = extra } else { + const threshold = 256 for m < i1 { - if i0 < 1024 { + if i0 < threshold { m += m } else { - m += m / 4 + m += (m + 3*threshold) / 4 } } } diff --git a/src/runtime/slice.go b/src/runtime/slice.go index e8267be885..cfa862e047 100644 --- a/src/runtime/slice.go +++ b/src/runtime/slice.go @@ -185,13 +185,17 @@ func growslice(et *_type, old slice, cap int) slice { if cap > doublecap { newcap = cap } else { - if old.cap < 1024 { + const threshold = 256 + if old.cap < threshold { newcap = doublecap } else { // Check 0 < newcap to detect overflow // and prevent an infinite loop. for 0 < newcap && newcap < cap { - newcap += newcap / 4 + // Transition from growing 2x for small slices + // to growing 1.25x for large slices. This formula + // gives a smooth-ish transition between the two. + newcap += (newcap + 3*threshold) / 4 } // Set newcap to the requested cap when // the newcap calculation overflowed. -- GitLab From f961d8e5b10c317b86efca18e19ef0f238032c0a Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 21 Sep 2021 14:31:09 -0700 Subject: [PATCH 1332/2500] runtime: add Func method benchmarks Change-Id: Ib76872c22b1be9e611199b84fd96b59beedf786c Reviewed-on: https://go-review.googlesource.com/c/go/+/351457 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/runtime/symtab_test.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/runtime/symtab_test.go b/src/runtime/symtab_test.go index ffa07c7f3a..99ff0d4420 100644 --- a/src/runtime/symtab_test.go +++ b/src/runtime/symtab_test.go @@ -250,3 +250,35 @@ func TestFunctionAlignmentTraceback(t *testing.T) { t.Errorf("frames.Next() got %+v want %+v", frame.Func, f) } } + +func BenchmarkFunc(b *testing.B) { + pc, _, _, ok := runtime.Caller(0) + if !ok { + b.Fatal("failed to look up PC") + } + f := runtime.FuncForPC(pc) + b.Run("Name", func(b *testing.B) { + for i := 0; i < b.N; i++ { + name := f.Name() + if name != "runtime_test.BenchmarkFunc" { + b.Fatalf("unexpected name %q", name) + } + } + }) + b.Run("Entry", func(b *testing.B) { + for i := 0; i < b.N; i++ { + pc := f.Entry() + if pc == 0 { + b.Fatal("zero PC") + } + } + }) + b.Run("FileLine", func(b *testing.B) { + for i := 0; i < b.N; i++ { + file, line := f.FileLine(pc) + if !strings.HasSuffix(file, "symtab_test.go") || line == 0 { + b.Fatalf("unexpected file/line %q:%d", file, line) + } + } + }) +} -- GitLab From e54843f2f4c3b11b52b691eaa187871fb4355d4c Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 21 Sep 2021 12:18:38 -0700 Subject: [PATCH 1333/2500] runtime: look up funcInfo by func pointer runtime.Func.{Name,FileLine} need to be able to go from a *_func to a funcInfo. The missing bit of information is what module contains that *_func. The existing implementation looked up the module using the *_func's entry PC. A subsequent change will store *_func's entry PC relative to the containing module. Change the module lookup to instead for the module whose pclntable contains the *_func, cutting all dependencies on the contents of the *_func. Change-Id: I2dbbfec043ebc2e9a6ef19bbdec623ac84353b10 Reviewed-on: https://go-review.googlesource.com/c/go/+/351458 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/symtab.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 87b4eeb220..6236643ceb 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -273,7 +273,22 @@ func (f *Func) raw() *_func { func (f *Func) funcInfo() funcInfo { fn := f.raw() - return funcInfo{fn, findmoduledatap(fn.entry)} + // Find the module containing fn. fn is located in the pclntable. + // The unsafe.Pointer to uintptr conversions and arithmetic + // are safe because we are working with module addresses. + ptr := uintptr(unsafe.Pointer(fn)) + var mod *moduledata + for datap := &firstmoduledata; datap != nil; datap = datap.next { + if len(datap.pclntable) == 0 { + continue + } + base := uintptr(unsafe.Pointer(&datap.pclntable[0])) + if base <= ptr && ptr < base+uintptr(len(datap.pclntable)) { + mod = datap + break + } + } + return funcInfo{fn, mod} } // PCDATA and FUNCDATA table indexes. -- GitLab From 6c163e5ac9cdb258566f1287de7915a2fd30a0de Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 21 Sep 2021 13:48:23 -0700 Subject: [PATCH 1334/2500] runtime: change funcinl sentinel value from 0 to ^0 _func and funcinl are type-punned. We distinguish them at runtime by inspecting the first word. Prior to this change, we used 0 as the sentinel value that means that a Func is a funcinl. That worked because _func's first word is the functions' entry PC, and 0 is not a valid PC. I plan to make *_func's entry PC relative to the containing module. As a result, 0 will be a valid value, for the first function in the module. Switch to ^0 as the new sentinel value, which is neither a valid entry PC nor a valid PC offset. Change-Id: I4c718523a083ed6edd57767c3548640681993522 Reviewed-on: https://go-review.googlesource.com/c/go/+/351459 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/runtime2.go | 4 ++-- src/runtime/symtab.go | 12 +++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index 04bd5cb887..442042eb16 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -879,8 +879,8 @@ type _func struct { // A *Func can be either a *_func or a *funcinl, and they are distinguished // by the first uintptr. type funcinl struct { - zero uintptr // set to 0 to distinguish from _func - entry uintptr // entry of the real (the "outermost") frame. + ones uintptr // set to ^0 to distinguish from _func + entry uintptr // entry of the real (the "outermost") frame name string file string line int diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 6236643ceb..0f4ad5ab95 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -650,6 +650,7 @@ func FuncForPC(pc uintptr) *Func { name := funcnameFromNameoff(f, inltree[ix].func_) file, line := funcline(f, pc) fi := &funcinl{ + ones: ^uintptr(0), entry: f.entry, // entry of the real (the outermost) function. name: name, file: file, @@ -667,7 +668,7 @@ func (f *Func) Name() string { return "" } fn := f.raw() - if fn.entry == 0 { // inlined version + if fn.isInlined() { // inlined version fi := (*funcinl)(unsafe.Pointer(fn)) return fi.name } @@ -677,7 +678,7 @@ func (f *Func) Name() string { // Entry returns the entry address of the function. func (f *Func) Entry() uintptr { fn := f.raw() - if fn.entry == 0 { // inlined version + if fn.isInlined() { // inlined version fi := (*funcinl)(unsafe.Pointer(fn)) return fi.entry } @@ -690,7 +691,7 @@ func (f *Func) Entry() uintptr { // counter within f. func (f *Func) FileLine(pc uintptr) (file string, line int) { fn := f.raw() - if fn.entry == 0 { // inlined version + if fn.isInlined() { // inlined version fi := (*funcinl)(unsafe.Pointer(fn)) return fi.file, fi.line } @@ -728,6 +729,11 @@ func (f funcInfo) _Func() *Func { return (*Func)(unsafe.Pointer(f._func)) } +// isInlined reports whether f should be re-interpreted as a *funcinl. +func (f *_func) isInlined() bool { + return f.entry == ^uintptr(0) // see comment for funcinl.ones +} + // findfunc looks up function metadata for a PC. // // It is nosplit because it's part of the isgoexception -- GitLab From 61a0a701135e38c48131ea18925dc5b027cc3a3c Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 21 Sep 2021 14:05:57 -0700 Subject: [PATCH 1335/2500] runtime: convert _func.entry to a method A subsequent change will alter the semantics of _func.entry. To make that change obvious and clear, change _func.entry to a method, and rename the field to _func.entryPC. Change-Id: I05d66b54d06c5956d4537b0729ddf4290c3e2635 Reviewed-on: https://go-review.googlesource.com/c/go/+/351460 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/compile/internal/test/inl_test.go | 1 + src/runtime/debugcall.go | 2 +- src/runtime/debuglog.go | 4 ++-- src/runtime/heapdump.go | 6 ++--- src/runtime/panic.go | 2 +- src/runtime/plugin.go | 2 +- src/runtime/preempt.go | 2 +- src/runtime/print.go | 2 +- src/runtime/runtime2.go | 2 +- src/runtime/stack.go | 4 ++-- src/runtime/symtab.go | 29 +++++++++++++---------- src/runtime/traceback.go | 26 ++++++++++---------- 12 files changed, 44 insertions(+), 38 deletions(-) diff --git a/src/cmd/compile/internal/test/inl_test.go b/src/cmd/compile/internal/test/inl_test.go index 4f20ec1bd1..06afe835e2 100644 --- a/src/cmd/compile/internal/test/inl_test.go +++ b/src/cmd/compile/internal/test/inl_test.go @@ -65,6 +65,7 @@ func TestIntendedInlining(t *testing.T) { "(*bmap).keys", "(*bmap).overflow", "(*waitq).enqueue", + "(*_func).entry", // GC-related ones "cgoInRange", diff --git a/src/runtime/debugcall.go b/src/runtime/debugcall.go index ad66a18c26..a1440f7649 100644 --- a/src/runtime/debugcall.go +++ b/src/runtime/debugcall.go @@ -78,7 +78,7 @@ func debugCallCheck(pc uintptr) string { } // Check that this isn't an unsafe-point. - if pc != f.entry { + if pc != f.entry() { pc-- } up := pcdatavalue(f, _PCDATA_UnsafePoint, pc, nil) diff --git a/src/runtime/debuglog.go b/src/runtime/debuglog.go index 3ce3273f4d..588b54d1f5 100644 --- a/src/runtime/debuglog.go +++ b/src/runtime/debuglog.go @@ -802,7 +802,7 @@ func printDebugLog() { // pc is a return PC that must first be converted to a call PC. func printDebugLogPC(pc uintptr, returnPC bool) { fn := findfunc(pc) - if returnPC && (!fn.valid() || pc > fn.entry) { + if returnPC && (!fn.valid() || pc > fn.entry()) { // TODO(austin): Don't back up if the previous frame // was a sigpanic. pc-- @@ -814,7 +814,7 @@ func printDebugLogPC(pc uintptr, returnPC bool) { } else { name := funcname(fn) file, line := funcline(fn, pc) - print(" [", name, "+", hex(pc-fn.entry), + print(" [", name, "+", hex(pc-fn.entry()), " ", file, ":", line, "]") } } diff --git a/src/runtime/heapdump.go b/src/runtime/heapdump.go index 8fb30d95b9..871637a09e 100644 --- a/src/runtime/heapdump.go +++ b/src/runtime/heapdump.go @@ -259,7 +259,7 @@ func dumpframe(s *stkframe, arg unsafe.Pointer) bool { // Figure out what we can about our stack map pc := s.pc pcdata := int32(-1) // Use the entry map at function entry - if pc != f.entry { + if pc != f.entry() { pc-- pcdata = pcdatavalue(f, _PCDATA_StackMapIndex, pc, nil) } @@ -284,7 +284,7 @@ func dumpframe(s *stkframe, arg unsafe.Pointer) bool { dumpint(uint64(child.depth)) // # of frames deep on the stack dumpint(uint64(uintptr(unsafe.Pointer(child.sp)))) // sp of child, or 0 if bottom of stack dumpmemrange(unsafe.Pointer(s.sp), s.fp-s.sp) // frame contents - dumpint(uint64(f.entry)) + dumpint(uint64(f.entry())) dumpint(uint64(s.pc)) dumpint(uint64(s.continpc)) name := funcname(f) @@ -631,7 +631,7 @@ func dumpmemprof_callback(b *bucket, nstk uintptr, pstk *uintptr, size, allocs, dumpint(0) } else { dumpstr(funcname(f)) - if i > 0 && pc > f.entry { + if i > 0 && pc > f.entry() { pc-- } file, line := funcline(f, pc) diff --git a/src/runtime/panic.go b/src/runtime/panic.go index e4bdceb32f..942898716e 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -626,7 +626,7 @@ func addOneOpenDeferFrame(gp *g, pc uintptr, sp unsafe.Pointer) { // deferreturn that runs any remaining // defers and then returns from the // function. - d1.pc = frame.fn.entry + uintptr(frame.fn.deferreturn) + d1.pc = frame.fn.entry() + uintptr(frame.fn.deferreturn) d1.varp = frame.varp d1.fd = fd // Save the SP/PC associated with current frame, diff --git a/src/runtime/plugin.go b/src/runtime/plugin.go index cd7fc5f848..500663bfe2 100644 --- a/src/runtime/plugin.go +++ b/src/runtime/plugin.go @@ -112,7 +112,7 @@ func pluginftabverify(md *moduledata) { f2 := findfunc(entry) if f2.valid() { name2 = funcname(f2) - entry2 = f2.entry + entry2 = f2.entry() } badtable = true println("ftab entry", hex(entry), "/", hex(entry2), ": ", diff --git a/src/runtime/preempt.go b/src/runtime/preempt.go index 334bac779e..18566a7459 100644 --- a/src/runtime/preempt.go +++ b/src/runtime/preempt.go @@ -451,7 +451,7 @@ func isAsyncSafePoint(gp *g, pc, sp, lr uintptr) (bool, uintptr) { return true, startpc case _PCDATA_RestartAtEntry: // Restart from the function entry at resumption. - return true, f.entry + return true, f.entry() } return true, pc } diff --git a/src/runtime/print.go b/src/runtime/print.go index 59a91203b9..b2a642bb86 100644 --- a/src/runtime/print.go +++ b/src/runtime/print.go @@ -293,7 +293,7 @@ func hexdumpWords(p, end uintptr, mark func(uintptr) byte) { // Can we symbolize val? fn := findfunc(val) if fn.valid() { - print("<", funcname(fn), "+", hex(val-fn.entry), "> ") + print("<", funcname(fn), "+", hex(val-fn.entry()), "> ") } } minhexdigits = 0 diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index 442042eb16..8188872ae8 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -858,7 +858,7 @@ const ( // Keep in sync with linker (../cmd/link/internal/ld/pcln.go:/pclntab) // and with package debug/gosym and with symtab.go in package runtime. type _func struct { - entry uintptr // start pc + entryPC uintptr // start pc nameoff int32 // function name args int32 // in/out args size diff --git a/src/runtime/stack.go b/src/runtime/stack.go index 368ad6efa4..cccec49f8e 100644 --- a/src/runtime/stack.go +++ b/src/runtime/stack.go @@ -966,7 +966,7 @@ func newstack() { f := findfunc(gp.sched.pc) if f.valid() { pcname = funcname(f) - pcoff = gp.sched.pc - f.entry + pcoff = gp.sched.pc - f.entry() } print("runtime: newstack at ", pcname, "+", hex(pcoff), " sp=", hex(gp.sched.sp), " stack=[", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n", @@ -1240,7 +1240,7 @@ func getStackMap(frame *stkframe, cache *pcvalueCache, debug bool) (locals, args f := frame.fn pcdata := int32(-1) - if targetpc != f.entry { + if targetpc != f.entry() { // Back up to the CALL. If we're at the function entry // point, we want to use the entry map (-1), even if // the first instruction of the function changes the diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 0f4ad5ab95..a11e22130d 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -206,7 +206,7 @@ func runtime_expandFinalInlineFrame(stk []uintptr) []uintptr { } lastFuncID = inltree[ix].funcID // Back up to an instruction in the "caller". - tracepc = f.entry + uintptr(inltree[ix].parentPc) + tracepc = f.entry() + uintptr(inltree[ix].parentPc) pc = tracepc + 1 } @@ -651,7 +651,7 @@ func FuncForPC(pc uintptr) *Func { file, line := funcline(f, pc) fi := &funcinl{ ones: ^uintptr(0), - entry: f.entry, // entry of the real (the outermost) function. + entry: f.entry(), // entry of the real (the outermost) function. name: name, file: file, line: int(line), @@ -682,7 +682,7 @@ func (f *Func) Entry() uintptr { fi := (*funcinl)(unsafe.Pointer(fn)) return fi.entry } - return fn.entry + return fn.entry() } // FileLine returns the file name and line number of the @@ -731,7 +731,12 @@ func (f funcInfo) _Func() *Func { // isInlined reports whether f should be re-interpreted as a *funcinl. func (f *_func) isInlined() bool { - return f.entry == ^uintptr(0) // see comment for funcinl.ones + return f.entryPC == ^uintptr(0) // see comment for funcinl.ones +} + +// entry returns the entry PC for f. +func (f *_func) entry() uintptr { + return f.entryPC } // findfunc looks up function metadata for a PC. @@ -838,19 +843,19 @@ func pcvalue(f funcInfo, off uint32, targetpc uintptr, cache *pcvalueCache, stri if !f.valid() { if strict && panicking == 0 { - print("runtime: no module data for ", hex(f.entry), "\n") + print("runtime: no module data for ", hex(f.entry()), "\n") throw("no module data") } return -1, 0 } datap := f.datap p := datap.pctab[off:] - pc := f.entry + pc := f.entry() prevpc := pc val := int32(-1) for { var ok bool - p, ok = step(p, &pc, &val, pc == f.entry) + p, ok = step(p, &pc, &val, pc == f.entry()) if !ok { break } @@ -887,11 +892,11 @@ func pcvalue(f funcInfo, off uint32, targetpc uintptr, cache *pcvalueCache, stri print("runtime: invalid pc-encoded table f=", funcname(f), " pc=", hex(pc), " targetpc=", hex(targetpc), " tab=", p, "\n") p = datap.pctab[off:] - pc = f.entry + pc = f.entry() val = -1 for { var ok bool - p, ok = step(p, &pc, &val, pc == f.entry) + p, ok = step(p, &pc, &val, pc == f.entry()) if !ok { break } @@ -975,7 +980,7 @@ func funcline(f funcInfo, targetpc uintptr) (file string, line int32) { func funcspdelta(f funcInfo, targetpc uintptr, cache *pcvalueCache) int32 { x, _ := pcvalue(f, f.pcsp, targetpc, cache, true) if x&(goarch.PtrSize-1) != 0 { - print("invalid spdelta ", funcname(f), " ", hex(f.entry), " ", hex(targetpc), " ", hex(f.pcsp), " ", x, "\n") + print("invalid spdelta ", funcname(f), " ", hex(f.entry()), " ", hex(targetpc), " ", hex(f.pcsp), " ", x, "\n") } return x } @@ -984,12 +989,12 @@ func funcspdelta(f funcInfo, targetpc uintptr, cache *pcvalueCache) int32 { func funcMaxSPDelta(f funcInfo) int32 { datap := f.datap p := datap.pctab[f.pcsp:] - pc := f.entry + pc := f.entry() val := int32(-1) max := int32(0) for { var ok bool - p, ok = step(p, &pc, &val, pc == f.entry) + p, ok = step(p, &pc, &val, pc == f.entry()) if !ok { return max } diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go index 8c0979eec2..530d572095 100644 --- a/src/runtime/traceback.go +++ b/src/runtime/traceback.go @@ -297,7 +297,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in frame.continpc = frame.pc if waspanic { if frame.fn.deferreturn != 0 { - frame.continpc = frame.fn.entry + uintptr(frame.fn.deferreturn) + 1 + frame.continpc = frame.fn.entry() + uintptr(frame.fn.deferreturn) + 1 // Note: this may perhaps keep return variables alive longer than // strictly necessary, as we are using "function has a defer statement" // as a proxy for "function actually deferred something". It seems @@ -333,7 +333,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in // See issue 34123. // The pc can be at function entry when the frame is initialized without // actually running code, like runtime.mstart. - if (n == 0 && flags&_TraceTrap != 0) || waspanic || pc == f.entry { + if (n == 0 && flags&_TraceTrap != 0) || waspanic || pc == f.entry() { pc++ } else { tracepc-- @@ -357,7 +357,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in } lastFuncID = inltree[ix].funcID // Back up to an instruction in the "caller". - tracepc = frame.fn.entry + uintptr(inltree[ix].parentPc) + tracepc = frame.fn.entry() + uintptr(inltree[ix].parentPc) pc = tracepc + 1 } } @@ -384,7 +384,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in // backup to CALL instruction to read inlining info (same logic as below) tracepc := frame.pc - if (n > 0 || flags&_TraceTrap == 0) && frame.pc > f.entry && !waspanic { + if (n > 0 || flags&_TraceTrap == 0) && frame.pc > f.entry() && !waspanic { tracepc-- } // If there is inlining info, print the inner frames. @@ -412,7 +412,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in } lastFuncID = inltree[ix].funcID // Back up to an instruction in the "caller". - tracepc = frame.fn.entry + uintptr(inltree[ix].parentPc) + tracepc = frame.fn.entry() + uintptr(inltree[ix].parentPc) } } if (flags&_TraceRuntimeFrames) != 0 || showframe(f, gp, nprint == 0, f.funcID, lastFuncID) { @@ -430,8 +430,8 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in printArgs(f, argp) print(")\n") print("\t", file, ":", line) - if frame.pc > f.entry { - print(" +", hex(frame.pc-f.entry)) + if frame.pc > f.entry() { + print(" +", hex(frame.pc-f.entry())) } if gp.m != nil && gp.m.throwing > 0 && gp == gp.m.curg || level >= 2 { print(" fp=", hex(frame.fp), " sp=", hex(frame.sp), " pc=", hex(frame.pc)) @@ -668,7 +668,7 @@ func getArgInfo(frame *stkframe, f funcInfo, needArgMap bool, ctxt *funcval) (ar // in the return values. retValid = *(*bool)(unsafe.Pointer(arg0 + 4*goarch.PtrSize)) } - if mv.fn != f.entry { + if mv.fn != f.entry() { print("runtime: confused by ", funcname(f), "\n") throw("reflect mismatch") } @@ -728,13 +728,13 @@ func printcreatedby(gp *g) { func printcreatedby1(f funcInfo, pc uintptr) { print("created by ", funcname(f), "\n") tracepc := pc // back up to CALL instruction for funcline. - if pc > f.entry { + if pc > f.entry() { tracepc -= sys.PCQuantum } file, line := funcline(f, tracepc) print("\t", file, ":", line) - if pc > f.entry { - print(" +", hex(pc-f.entry)) + if pc > f.entry() { + print(" +", hex(pc-f.entry())) } print("\n") } @@ -842,8 +842,8 @@ func printAncestorTracebackFuncInfo(f funcInfo, pc uintptr) { } print(name, "(...)\n") print("\t", file, ":", line) - if pc > f.entry { - print(" +", hex(pc-f.entry)) + if pc > f.entry() { + print(" +", hex(pc-f.entry())) } print("\n") } -- GitLab From f0c79caa1398b6a840ec9406eb34b46a125ecb82 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 21 Sep 2021 14:22:51 -0700 Subject: [PATCH 1336/2500] runtime: move entry method from _func to funcInfo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will be required when we change from storing entry PCs in _func to entry PC offsets, which are relative to the containing module. Notably, almost all uses of the entry method were already called on a funcInfo. Only Func.Entry incurs the additional module lookup cost. This makes Entry considerably slower, but it is probably still fast enough in absolute terms that it is OK. name old time/op new time/op delta Func/Name-8 8.86ns ± 0% 8.33ns ± 2% -5.92% (p=0.000 n=12+13) Func/Entry-8 0.64ns ± 0% 2.62ns ±36% +310.07% (p=0.000 n=14+15) Func/FileLine-8 24.5ns ± 0% 25.0ns ± 4% +2.21% (p=0.015 n=14+13) Change-Id: Ia2d5de5f2f83fab334f1875452b9e8e87651d340 Reviewed-on: https://go-review.googlesource.com/c/go/+/351461 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/compile/internal/test/inl_test.go | 2 +- src/runtime/symtab.go | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/test/inl_test.go b/src/cmd/compile/internal/test/inl_test.go index 06afe835e2..89247fbabf 100644 --- a/src/cmd/compile/internal/test/inl_test.go +++ b/src/cmd/compile/internal/test/inl_test.go @@ -65,7 +65,7 @@ func TestIntendedInlining(t *testing.T) { "(*bmap).keys", "(*bmap).overflow", "(*waitq).enqueue", - "(*_func).entry", + "funcInfo.entry", // GC-related ones "cgoInRange", diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index a11e22130d..7a9bb3e06b 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -272,11 +272,14 @@ func (f *Func) raw() *_func { } func (f *Func) funcInfo() funcInfo { - fn := f.raw() + return f.raw().funcInfo() +} + +func (f *_func) funcInfo() funcInfo { // Find the module containing fn. fn is located in the pclntable. // The unsafe.Pointer to uintptr conversions and arithmetic // are safe because we are working with module addresses. - ptr := uintptr(unsafe.Pointer(fn)) + ptr := uintptr(unsafe.Pointer(f)) var mod *moduledata for datap := &firstmoduledata; datap != nil; datap = datap.next { if len(datap.pclntable) == 0 { @@ -288,7 +291,7 @@ func (f *Func) funcInfo() funcInfo { break } } - return funcInfo{fn, mod} + return funcInfo{f, mod} } // PCDATA and FUNCDATA table indexes. @@ -682,7 +685,7 @@ func (f *Func) Entry() uintptr { fi := (*funcinl)(unsafe.Pointer(fn)) return fi.entry } - return fn.entry() + return fn.funcInfo().entry() } // FileLine returns the file name and line number of the @@ -735,7 +738,7 @@ func (f *_func) isInlined() bool { } // entry returns the entry PC for f. -func (f *_func) entry() uintptr { +func (f funcInfo) entry() uintptr { return f.entryPC } -- GitLab From 8e34d779578736942c78f9857f5bb9b9025815c6 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 21 Sep 2021 09:45:34 -0700 Subject: [PATCH 1337/2500] runtime, cmd/link: minor cleanup Fix some comments. Adjust capitalization for initialisms. Use a println directly instead of emulating it. Change-Id: I0d8fa0eb39547e2db8113fd0358136285b86f16a Reviewed-on: https://go-review.googlesource.com/c/go/+/351462 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui Reviewed-by: Than McIntosh --- src/cmd/link/internal/ld/pcln.go | 14 +++++++------- src/runtime/symtab.go | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index 56c4fe0b46..fede00586b 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -551,7 +551,7 @@ type pclnSetUint func(*loader.SymbolBuilder, *sys.Arch, int64, uint64) int64 // 1) the PC->func table. // 2) The entry points in the func objects. // 3) The funcdata. -// (1) and (2) are handled in walkPCToFunc. (3) is handled in walkFuncdata. +// (1) and (2) are handled in writePCToFunc. (3) is handled in writeFuncdata. // // After relocations, once we know where to write things in the output buffer, // we execute the second pass, which is actually writing the data. @@ -586,7 +586,7 @@ func (state *pclntab) generateFunctab(ctxt *Link, funcs []loader.Sym, inlSyms ma } // Write the data. - writePcToFunc(ctxt, sb, funcs, startLocations, setAddr, (*loader.SymbolBuilder).SetUint) + writePCToFunc(ctxt, sb, funcs, startLocations, setAddr, (*loader.SymbolBuilder).SetUint) writeFuncs(ctxt, sb, funcs, inlSyms, startLocations, cuOffsets, nameOffsets) state.writeFuncData(ctxt, sb, funcs, inlSyms, startLocations, setAddr, (*loader.SymbolBuilder).SetUint) } @@ -611,7 +611,7 @@ func (state *pclntab) generateFunctab(ctxt *Link, funcs []loader.Sym, inlSyms ma setAddr = (*loader.SymbolBuilder).SetAddrPlus } setUintNOP := func(*loader.SymbolBuilder, *sys.Arch, int64, uint64) int64 { return 0 } - writePcToFunc(ctxt, sb, funcs, startLocations, setAddr, setUintNOP) + writePCToFunc(ctxt, sb, funcs, startLocations, setAddr, setUintNOP) if !useSymValue { // Generate relocations for funcdata when externally linking. state.writeFuncData(ctxt, sb, funcs, inlSyms, startLocations, setAddr, setUintNOP) @@ -687,10 +687,10 @@ func (state pclntab) calculateFunctabSize(ctxt *Link, funcs []loader.Sym) (int64 return size, startLocations } -// writePcToFunc writes the PC->func lookup table. +// writePCToFunc writes the PC->func lookup table. // This function walks the pc->func lookup table, executing callbacks // to generate relocations and writing the values for the table. -func writePcToFunc(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, startLocations []uint32, setAddr pclnSetAddr, setUint pclnSetUint) { +func writePCToFunc(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, startLocations []uint32, setAddr pclnSetAddr, setUint pclnSetUint) { ldr := ctxt.loader var prevFunc loader.Sym prevSect := ldr.SymSect(funcs[0]) @@ -775,8 +775,8 @@ func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSym fi.Preload() } - // Note we skip the space for the entry value -- that's handled inn - // walkPCToFunc. We don't write it here, because it might require a + // Note we skip the space for the entry value -- that's handled in + // writePCToFunc. We don't write it here, because it might require a // relocation. off := startLocations[i] + uint32(ctxt.Arch.PtrSize) // entry diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 7a9bb3e06b..792513f796 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -846,7 +846,7 @@ func pcvalue(f funcInfo, off uint32, targetpc uintptr, cache *pcvalueCache, stri if !f.valid() { if strict && panicking == 0 { - print("runtime: no module data for ", hex(f.entry()), "\n") + println("runtime: no module data for", hex(f.entry())) throw("no module data") } return -1, 0 -- GitLab From 04f7521b0aef10d523d6de006e723afd349b4b95 Mon Sep 17 00:00:00 2001 From: Fabio Falzoi Date: Sat, 25 Sep 2021 18:44:24 +0200 Subject: [PATCH 1338/2500] reflect: add Value.{CanInt, CanUint, CanFloat, CanComplex} As discussed in #47658, Value already has CanAddr and CanInterface to test if a call to Addr or Inteface, respectively, does not result in a panic. Therefore we add CanInt, CanUint, CanFloat and CanComplex to ease the test for a possible panic in calling, respectively, Int, Uint, Float and Complex. Fixes #47658 Change-Id: I58b77d77e6eec9f34234e985f631eab72b5b935e Reviewed-on: https://go-review.googlesource.com/c/go/+/352131 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Trust: David Chase Trust: Brad Fitzpatrick Reviewed-by: Keith Randall --- src/cmd/compile/internal/test/inl_test.go | 4 ++ src/reflect/all_test.go | 69 +++++++++++++++++++++++ src/reflect/value.go | 40 +++++++++++++ 3 files changed, 113 insertions(+) diff --git a/src/cmd/compile/internal/test/inl_test.go b/src/cmd/compile/internal/test/inl_test.go index 89247fbabf..5fa6411ae4 100644 --- a/src/cmd/compile/internal/test/inl_test.go +++ b/src/cmd/compile/internal/test/inl_test.go @@ -127,6 +127,10 @@ func TestIntendedInlining(t *testing.T) { "ValidRune", }, "reflect": { + "Value.CanInt", + "Value.CanUint", + "Value.CanFloat", + "Value.CanComplex", "Value.CanAddr", "Value.CanSet", "Value.CanInterface", diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index 22885c548f..5e10cc7a63 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -376,6 +376,75 @@ func TestMapIterSet(t *testing.T) { } } +func TestCanIntUintFloatComplex(t *testing.T) { + type integer int + type uinteger uint + type float float64 + type complex complex128 + + var ops = [...]string{"CanInt", "CanUint", "CanFloat", "CanComplex"} + + var testCases = []struct { + i interface{} + want [4]bool + }{ + // signed integer + {132, [...]bool{true, false, false, false}}, + {int8(8), [...]bool{true, false, false, false}}, + {int16(16), [...]bool{true, false, false, false}}, + {int32(32), [...]bool{true, false, false, false}}, + {int64(64), [...]bool{true, false, false, false}}, + // unsigned integer + {uint(132), [...]bool{false, true, false, false}}, + {uint8(8), [...]bool{false, true, false, false}}, + {uint16(16), [...]bool{false, true, false, false}}, + {uint32(32), [...]bool{false, true, false, false}}, + {uint64(64), [...]bool{false, true, false, false}}, + {uintptr(0xABCD), [...]bool{false, true, false, false}}, + // floating-point + {float32(256.25), [...]bool{false, false, true, false}}, + {float64(512.125), [...]bool{false, false, true, false}}, + // complex + {complex64(532.125 + 10i), [...]bool{false, false, false, true}}, + {complex128(564.25 + 1i), [...]bool{false, false, false, true}}, + // underlying + {integer(-132), [...]bool{true, false, false, false}}, + {uinteger(132), [...]bool{false, true, false, false}}, + {float(256.25), [...]bool{false, false, true, false}}, + {complex(532.125 + 10i), [...]bool{false, false, false, true}}, + // not-acceptable + {"hello world", [...]bool{false, false, false, false}}, + {new(int), [...]bool{false, false, false, false}}, + {new(uint), [...]bool{false, false, false, false}}, + {new(float64), [...]bool{false, false, false, false}}, + {new(complex64), [...]bool{false, false, false, false}}, + {new([5]int), [...]bool{false, false, false, false}}, + {new(integer), [...]bool{false, false, false, false}}, + {new(map[int]int), [...]bool{false, false, false, false}}, + {new(chan<- int), [...]bool{false, false, false, false}}, + {new(func(a int8)), [...]bool{false, false, false, false}}, + {new(struct{ i int }), [...]bool{false, false, false, false}}, + } + + for i, tc := range testCases { + v := ValueOf(tc.i) + got := [...]bool{v.CanInt(), v.CanUint(), v.CanFloat(), v.CanComplex()} + + for j := range tc.want { + if got[j] != tc.want[j] { + t.Errorf( + "#%d: v.%s() returned %t for type %T, want %t", + i, + ops[j], + got[j], + tc.i, + tc.want[j], + ) + } + } + } +} + func TestCanSetField(t *testing.T) { type embed struct{ x, X int } type Embed struct{ x, X int } diff --git a/src/reflect/value.go b/src/reflect/value.go index 786c494166..39b82a8c01 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -1122,6 +1122,16 @@ func (v Value) Close() { chanclose(v.pointer()) } +// CanComplex reports whether Complex can be used without panicking. +func (v Value) CanComplex() bool { + switch v.kind() { + case Complex64, Complex128: + return true + default: + return false + } +} + // Complex returns v's underlying value, as a complex128. // It panics if v's Kind is not Complex64 or Complex128 func (v Value) Complex() complex128 { @@ -1249,6 +1259,16 @@ func (v Value) FieldByNameFunc(match func(string) bool) Value { return Value{} } +// CanFloat reports whether Float can be used without panicking. +func (v Value) CanFloat() bool { + switch v.kind() { + case Float32, Float64: + return true + default: + return false + } +} + // Float returns v's underlying value, as a float64. // It panics if v's Kind is not Float32 or Float64 func (v Value) Float() float64 { @@ -1310,6 +1330,16 @@ func (v Value) Index(i int) Value { panic(&ValueError{"reflect.Value.Index", v.kind()}) } +// CanInt reports whether Int can be used without panicking. +func (v Value) CanInt() bool { + switch v.kind() { + case Int, Int8, Int16, Int32, Int64: + return true + default: + return false + } +} + // Int returns v's underlying value, as an int64. // It panics if v's Kind is not Int, Int8, Int16, Int32, or Int64. func (v Value) Int() int64 { @@ -2391,6 +2421,16 @@ func (v Value) Type() Type { return v.typ.typeOff(m.mtyp) } +// CanUint reports whether Uint can be used without panicking. +func (v Value) CanUint() bool { + switch v.kind() { + case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr: + return true + default: + return false + } +} + // Uint returns v's underlying value, as a uint64. // It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64. func (v Value) Uint() uint64 { -- GitLab From 788731387932e70d4dd951770c046c7eec9f9d96 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Mon, 27 Sep 2021 14:37:13 -0400 Subject: [PATCH 1339/2500] runtime/pprof: skip TestTimeVDSO on Android The test is flaky on Android. VDSO may not be enabled so it may not have the original problem anyway. Change-Id: I73c2902c682a44d893e0d4e34f006c2377ef8816 Reviewed-on: https://go-review.googlesource.com/c/go/+/352509 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/runtime/pprof/pprof_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go index 8c34d39ad5..f39d65c0b5 100644 --- a/src/runtime/pprof/pprof_test.go +++ b/src/runtime/pprof/pprof_test.go @@ -1650,6 +1650,11 @@ func TestTimeVDSO(t *testing.T) { // Test that time functions have the right stack trace. In particular, // it shouldn't be recursive. + if runtime.GOOS == "android" { + // Flaky on Android, issue 48655. VDSO may not be enabled. + testenv.SkipFlaky(t, 48655) + } + p := testCPUProfile(t, stackContains, []string{"time.now"}, avoidFunctions(), func(dur time.Duration) { t0 := time.Now() for { -- GitLab From 45134acbe645665e93cf1d399027d56b44f23299 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Wed, 22 Sep 2021 11:13:20 -0700 Subject: [PATCH 1340/2500] debug/gosym: add pcHeader parsing helpers A subsequent change will duplicate most of case ver116. Make it easier to read. Change-Id: I3a93181c7f094b12715b8a618e9efef7a1438a27 Reviewed-on: https://go-review.googlesource.com/c/go/+/351909 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/debug/gosym/pclntab.go | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/debug/gosym/pclntab.go b/src/debug/gosym/pclntab.go index a72f9847d7..555add67e3 100644 --- a/src/debug/gosym/pclntab.go +++ b/src/debug/gosym/pclntab.go @@ -225,21 +225,23 @@ func (t *LineTable) parsePclnTab() { t.quantum = uint32(t.Data[6]) t.ptrsize = uint32(t.Data[7]) + offset := func(word uint32) uint64 { + return t.uintptr(t.Data[8+word*t.ptrsize:]) + } + data := func(word uint32) []byte { + return t.Data[offset(word):] + } + switch possibleVersion { case ver116: - t.nfunctab = uint32(t.uintptr(t.Data[8:])) - t.nfiletab = uint32(t.uintptr(t.Data[8+t.ptrsize:])) - offset := t.uintptr(t.Data[8+2*t.ptrsize:]) - t.funcnametab = t.Data[offset:] - offset = t.uintptr(t.Data[8+3*t.ptrsize:]) - t.cutab = t.Data[offset:] - offset = t.uintptr(t.Data[8+4*t.ptrsize:]) - t.filetab = t.Data[offset:] - offset = t.uintptr(t.Data[8+5*t.ptrsize:]) - t.pctab = t.Data[offset:] - offset = t.uintptr(t.Data[8+6*t.ptrsize:]) - t.funcdata = t.Data[offset:] - t.functab = t.Data[offset:] + t.nfunctab = uint32(offset(0)) + t.nfiletab = uint32(offset(1)) + t.funcnametab = data(2) + t.cutab = data(3) + t.filetab = data(4) + t.pctab = data(5) + t.funcdata = data(6) + t.functab = data(6) functabsize := t.nfunctab*2*t.ptrsize + t.ptrsize t.functab = t.functab[:functabsize] case ver12: -- GitLab From 52b23a50f8a2028b6155da12161941803abd6198 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Thu, 23 Sep 2021 18:03:56 -0700 Subject: [PATCH 1341/2500] cmd/link: put type descriptor method arginfo in the correct section We were putting type descriptor funcdata, such as type..eq.[2]interface {}.arginfo1 in type.* or typerel.* instead of go.func.*. Fix that. Change-Id: I779e6be3dd91c8029f2c3dc0e10a7d597c16678f Reviewed-on: https://go-review.googlesource.com/c/go/+/352071 Trust: Josh Bleecher Snyder Reviewed-by: Cherry Mui --- src/cmd/link/internal/ld/symtab.go | 35 ++++++++++++++++-------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index 1f5e333cfd..924d6fd6c3 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -537,22 +537,6 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { name := ldr.SymName(s) switch { - case strings.HasPrefix(name, "type."): - if !ctxt.DynlinkingGo() { - ldr.SetAttrNotInSymbolTable(s, true) - } - if ctxt.UseRelro() { - symGroupType[s] = sym.STYPERELRO - if symtyperel != 0 { - ldr.SetCarrierSym(s, symtyperel) - } - } else { - symGroupType[s] = sym.STYPE - if symtyperel != 0 { - ldr.SetCarrierSym(s, symtype) - } - } - case strings.HasPrefix(name, "go.importpath.") && ctxt.UseRelro(): // Keep go.importpath symbols in the same section as types and // names, as they can be referred to by a section offset. @@ -599,6 +583,25 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { align = a } liveness += (ldr.SymSize(s) + int64(align) - 1) &^ (int64(align) - 1) + + // Note: Check for "type." prefix after checking for .arginfo1 suffix. + // That way symbols like "type..eq.[2]interface {}.arginfo1" that belong + // in go.func.* end up there. + case strings.HasPrefix(name, "type."): + if !ctxt.DynlinkingGo() { + ldr.SetAttrNotInSymbolTable(s, true) + } + if ctxt.UseRelro() { + symGroupType[s] = sym.STYPERELRO + if symtyperel != 0 { + ldr.SetCarrierSym(s, symtyperel) + } + } else { + symGroupType[s] = sym.STYPE + if symtyperel != 0 { + ldr.SetCarrierSym(s, symtype) + } + } } } -- GitLab From cd4d59232e01f8b351cf83c0a669e56b10e8945d Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Fri, 24 Sep 2021 10:57:27 -0700 Subject: [PATCH 1342/2500] runtime: fix and simplify printing on bad ftab Unilaterally print plugin. Use println instead of print. Change-Id: Ib58f187bff9c3dbedfa2725c44754a222807cc36 Reviewed-on: https://go-review.googlesource.com/c/go/+/352072 Trust: Josh Bleecher Snyder Reviewed-by: Cherry Mui --- src/runtime/symtab.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 792513f796..0d0fe8055b 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -604,13 +604,9 @@ func moduledataverify1(datap *moduledata) { if i+1 < nftab { f2name = funcname(f2) } - print("function symbol table not sorted by program counter:", hex(datap.ftab[i].entry), funcname(f1), ">", hex(datap.ftab[i+1].entry), f2name) - if datap.pluginpath != "" { - print(", plugin:", datap.pluginpath) - } - println() + println("function symbol table not sorted by PC:", hex(datap.ftab[i].entry), funcname(f1), ">", hex(datap.ftab[i+1].entry), f2name, ", plugin:", datap.pluginpath) for j := 0; j <= i; j++ { - print("\t", hex(datap.ftab[j].entry), " ", funcname(funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[j].funcoff])), datap}), "\n") + println("\t", hex(datap.ftab[j].entry), funcname(funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[j].funcoff])), datap})) } if GOOS == "aix" && isarchive { println("-Wl,-bnoobjreorder is mandatory on aix/ppc64 with c-archive") -- GitLab From 12e8ffc18e84a76f8e01457852c456a3b28ec55a Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 27 Sep 2021 14:27:59 -0700 Subject: [PATCH 1343/2500] io: avoid integer overflow in NewSectionReader Fixes #48620 Change-Id: I37a5909ad27dc4a170929cb2e2ed1045cf524d59 Reviewed-on: https://go-review.googlesource.com/c/go/+/352629 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Brad Fitzpatrick TryBot-Result: Go Bot --- src/io/io.go | 11 ++++++++++- src/io/io_test.go | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/io/io.go b/src/io/io.go index 4e49a782dc..cb2a37e427 100644 --- a/src/io/io.go +++ b/src/io/io.go @@ -479,7 +479,16 @@ func (l *LimitedReader) Read(p []byte) (n int, err error) { // NewSectionReader returns a SectionReader that reads from r // starting at offset off and stops with EOF after n bytes. func NewSectionReader(r ReaderAt, off int64, n int64) *SectionReader { - return &SectionReader{r, off, off, off + n} + var remaining int64 + const maxint64 = 1<<63 - 1 + if off <= maxint64-n { + remaining = n + off + } else { + // Overflow, with no way to return error. + // Assume we can read up to an offset of 1<<63 - 1. + remaining = maxint64 + } + return &SectionReader{r, off, off, remaining} } // SectionReader implements Read, Seek, and ReadAt on a section diff --git a/src/io/io_test.go b/src/io/io_test.go index 5b355e8c55..3088460480 100644 --- a/src/io/io_test.go +++ b/src/io/io_test.go @@ -430,6 +430,20 @@ func TestSectionReader_Size(t *testing.T) { } } +func TestSectionReader_Max(t *testing.T) { + r := strings.NewReader("abcdef") + const maxint64 = 1<<63 - 1 + sr := NewSectionReader(r, 3, maxint64) + n, err := sr.Read(make([]byte, 3)) + if n != 3 || err != nil { + t.Errorf("Read = %v %v, want 3, nil", n, err) + } + n, err = sr.Read(make([]byte, 3)) + if n != 0 || err != EOF { + t.Errorf("Read = %v, %v, want 0, EOF", n, err) + } +} + // largeWriter returns an invalid count that is larger than the number // of bytes provided (issue 39978). type largeWriter struct { -- GitLab From 850a4ffb6346dd53f6f5624c13410d99e6509cae Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Mon, 27 Sep 2021 13:52:53 -0400 Subject: [PATCH 1344/2500] cmd/internal/goobj: remove Pcdata from object file As of CL 247399 we use separate symbols for PCDATA. There is no more need for writing PCDATA directly into the object file as a separate block. Change-Id: I942d1a372540415e0cc07fb2a01f79718a264142 Reviewed-on: https://go-review.googlesource.com/c/go/+/352610 Trust: Cherry Mui Trust: Josh Bleecher Snyder Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Josh Bleecher Snyder --- src/cmd/internal/goobj/objfile.go | 2 -- src/cmd/internal/obj/objfile.go | 19 ------------------- 2 files changed, 21 deletions(-) diff --git a/src/cmd/internal/goobj/objfile.go b/src/cmd/internal/goobj/objfile.go index 20bf0eba89..fc6dbb8af6 100644 --- a/src/cmd/internal/goobj/objfile.go +++ b/src/cmd/internal/goobj/objfile.go @@ -100,7 +100,6 @@ import ( // } // // Data [...]byte -// Pcdata [...]byte // // // blocks only used by tools (objdump, nm) // @@ -204,7 +203,6 @@ const ( BlkReloc BlkAux BlkData - BlkPcdata BlkRefName BlkEnd NBlk diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index 8a094df91a..3e5cf0e243 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -193,25 +193,6 @@ func WriteObjFile(ctxt *Link, b *bio.Writer) { } } - // Pcdata - h.Offsets[goobj.BlkPcdata] = w.Offset() - for _, s := range ctxt.Text { // iteration order must match genFuncInfoSyms - // Because of the phase order, it's possible that we try to write an invalid - // object file, and the Pcln variables haven't been filled in. As such, we - // need to check that Pcsp exists, and assume the other pcln variables exist - // as well. Tests like test/fixedbugs/issue22200.go demonstrate this issue. - if fn := s.Func(); fn != nil && fn.Pcln.Pcsp != nil { - pc := &fn.Pcln - w.Bytes(pc.Pcsp.P) - w.Bytes(pc.Pcfile.P) - w.Bytes(pc.Pcline.P) - w.Bytes(pc.Pcinline.P) - for i := range pc.Pcdata { - w.Bytes(pc.Pcdata[i].P) - } - } - } - // Blocks used only by tools (objdump, nm). // Referenced symbol names from other packages -- GitLab From 534dfb2aeb0721eeedb847e0d60785da8ac13315 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 27 Sep 2021 13:39:43 -0700 Subject: [PATCH 1345/2500] cmd/internal/obj: refactor code to separate content-addressable symbols by section The goal of this change is to improve the documentation and make it easier to keep Link.NumberSyms and writer.contentHash aligned. No functional changes. A subsequent change will add conditions to contentHashSection. Change-Id: I0a274f6974459d34d5a8553081f33ea4cd87f248 Reviewed-on: https://go-review.googlesource.com/c/go/+/352669 Trust: Josh Bleecher Snyder Reviewed-by: Cherry Mui --- src/cmd/internal/obj/objfile.go | 30 ++++++++++++++++++++++-------- src/cmd/internal/obj/sym.go | 6 +++--- src/cmd/link/internal/ld/symtab.go | 2 ++ 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index 3e5cf0e243..1a8a9635d6 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -381,7 +381,26 @@ func (w *writer) Hash(s *LSym) { w.Bytes(b[:]) } +// contentHashSection returns a mnemonic for s's section. +// The goal is to prevent content-addressability from moving symbols between sections. +// contentHashSection only distinguishes between sets of sections for which this matters. +// Allowing flexibility increases the effectiveness of content-addressibility. +// But in some cases, such as doing addressing based on a base symbol, +// we need to ensure that a symbol is always in a prticular section. +// Some of these conditions are duplicated in cmd/link/internal/ld.(*Link).symtab. +// TODO: instead of duplicating them, have the compiler decide where symbols go. +func contentHashSection(s *LSym) byte { + name := s.Name + if strings.HasPrefix(name, "type.") { + return 'T' + } + return 0 +} + func contentHash64(s *LSym) goobj.Hash64Type { + if contentHashSection(s) != 0 { + panic("short hash of non-default-section sym " + s.Name) + } var b goobj.Hash64Type copy(b[:], s.P) return b @@ -416,15 +435,10 @@ func (w *writer) contentHash(s *LSym) goobj.HashType { // In this case, if the smaller symbol is alive, the larger is not kept unless // needed. binary.LittleEndian.PutUint64(tmp[:8], uint64(s.Size)) - h.Write(tmp[:8]) + // Some symbols require being in separate sections. + tmp[8] = contentHashSection(s) + h.Write(tmp[:9]) - // Don't dedup type symbols with others, as they are in a different - // section. - if strings.HasPrefix(s.Name, "type.") { - h.Write([]byte{'T'}) - } else { - h.Write([]byte{0}) - } // The compiler trims trailing zeros _sometimes_. We just do // it always. h.Write(bytes.TrimRight(s.P, "\x00")) diff --git a/src/cmd/internal/obj/sym.go b/src/cmd/internal/obj/sym.go index 3289115439..6cd8bb3c3f 100644 --- a/src/cmd/internal/obj/sym.go +++ b/src/cmd/internal/obj/sym.go @@ -39,7 +39,6 @@ import ( "log" "math" "sort" - "strings" ) func Linknew(arch *LinkArch) *Link { @@ -206,9 +205,10 @@ func (ctxt *Link) NumberSyms() { // if Pkgpath is unknown, cannot hash symbols with relocations, as it // may reference named symbols whose names are not fully expanded. if s.ContentAddressable() && (ctxt.Pkgpath != "" || len(s.R) == 0) { - if s.Size <= 8 && len(s.R) == 0 && !strings.HasPrefix(s.Name, "type.") { + if s.Size <= 8 && len(s.R) == 0 && contentHashSection(s) == 0 { // We can use short hash only for symbols without relocations. - // Don't use short hash for type symbols, as they need special handling. + // Don't use short hash for symbols that belong in a particular section + // or require special handling (such as type symbols). s.PkgIdx = goobj.PkgIdxHashed64 s.SymIdx = hashed64idx if hashed64idx != int32(len(ctxt.hashed64defs)) { diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index 924d6fd6c3..8dec78e017 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -525,6 +525,8 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { // within a type they sort by size, so the .* symbols // just defined above will be first. // hide the specific symbols. + // Some of these symbol section conditions are duplicated + // in cmd/internal/obj.contentHashSection. nsym := loader.Sym(ldr.NSym()) symGroupType := make([]sym.SymKind, nsym) for s := loader.Sym(1); s < nsym; s++ { -- GitLab From 5511f14a735736e88c5fc832975f9b27244c56e1 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 27 Sep 2021 19:23:17 -0400 Subject: [PATCH 1346/2500] go/types: add a NewSignatureType constructor accepting type parameters In #47916, consensus has emerged that adding a new constructor is preferable to using setters for type parameters. This is more consistent with the rest of the type API, which is immutable except in cases where mutation is necessary to break cycles (such as Named.SetUnderlying). This CL adds a new constructor NewSignatureType that accepts type parameters and receiver type parameters, deprecating the existing NewSignature constructor. SetTypeParams and SetRecvTypeParams are not yet removed: this will be done in a follow-up CL once x/tools no longer has a dependency on the old APIs. Updates #47916 Change-Id: I9d04dcfd304344d2aa08e527b371c3faa9d738e8 Reviewed-on: https://go-review.googlesource.com/c/go/+/352615 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/internal/gcimporter/iimport.go | 19 +++++++++---------- src/go/types/signature.go | 26 +++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go index f570aab2bf..2a02c04ef3 100644 --- a/src/go/internal/gcimporter/iimport.go +++ b/src/go/internal/gcimporter/iimport.go @@ -304,8 +304,7 @@ func (r *importReader) obj(name string) { if tag == 'G' { tparams = r.tparamList() } - sig := r.signature(nil) - sig.SetTypeParams(tparams) + sig := r.signature(nil, nil, tparams) r.declare(types.NewFunc(pos, r.currPkg, name, sig)) case 'T', 'U': @@ -329,19 +328,19 @@ func (r *importReader) obj(name string) { mpos := r.pos() mname := r.ident() recv := r.param() - msig := r.signature(recv) // If the receiver has any targs, set those as the // rparams of the method (since those are the // typeparams being used in the method sig/body). - targs := baseType(msig.Recv().Type()).TypeArgs() + targs := baseType(recv.Type()).TypeArgs() + var rparams []*types.TypeParam if targs.Len() > 0 { - rparams := make([]*types.TypeParam, targs.Len()) + rparams = make([]*types.TypeParam, targs.Len()) for i := range rparams { rparams[i], _ = targs.At(i).(*types.TypeParam) } - msig.SetRecvTypeParams(rparams) } + msig := r.signature(recv, rparams, nil) named.AddMethod(types.NewFunc(mpos, r.currPkg, mname, msig)) } @@ -576,7 +575,7 @@ func (r *importReader) doType(base *types.Named) types.Type { return types.NewMap(r.typ(), r.typ()) case signatureType: r.currPkg = r.pkg() - return r.signature(nil) + return r.signature(nil, nil, nil) case structType: r.currPkg = r.pkg() @@ -616,7 +615,7 @@ func (r *importReader) doType(base *types.Named) types.Type { recv = types.NewVar(token.NoPos, r.currPkg, "", base) } - msig := r.signature(recv) + msig := r.signature(recv, nil, nil) methods[i] = types.NewFunc(mpos, r.currPkg, mname, msig) } @@ -673,11 +672,11 @@ func (r *importReader) kind() itag { return itag(r.uint64()) } -func (r *importReader) signature(recv *types.Var) *types.Signature { +func (r *importReader) signature(recv *types.Var, rparams, tparams []*types.TypeParam) *types.Signature { params := r.paramList() results := r.paramList() variadic := params.Len() > 0 && r.bool() - return types.NewSignature(recv, params, results, variadic) + return types.NewSignatureType(recv, rparams, tparams, params, results, variadic) } func (r *importReader) tparamList() []*types.TypeParam { diff --git a/src/go/types/signature.go b/src/go/types/signature.go index bf6c775b89..df38e7124b 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -34,7 +34,18 @@ type Signature struct { // and results, either of which may be nil. If variadic is set, the function // is variadic, it must have at least one parameter, and the last parameter // must be of unnamed slice type. +// +// Deprecated: Use NewSignatureType instead which allows for type parameters. func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature { + return NewSignatureType(recv, nil, nil, params, results, variadic) +} + +// NewSignatureType creates a new function type for the given receiver, +// receiver type parameters, type parameters, parameters, and results. If +// variadic is set, params must hold at least one parameter and the last +// parameter must be of unnamed slice type. If recv is non-nil, typeParams must +// be empty. If recvTypeParams is non-empty, recv must be non-nil. +func NewSignatureType(recv *Var, recvTypeParams, typeParams []*TypeParam, params, results *Tuple, variadic bool) *Signature { if variadic { n := params.Len() if n == 0 { @@ -44,7 +55,20 @@ func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature { panic("variadic parameter must be of unnamed slice type") } } - return &Signature{recv: recv, params: params, results: results, variadic: variadic} + sig := &Signature{recv: recv, params: params, results: results, variadic: variadic} + if len(recvTypeParams) != 0 { + if recv == nil { + panic("function with receiver type parameters must have a receiver") + } + sig.rparams = bindTParams(recvTypeParams) + } + if len(typeParams) != 0 { + if recv != nil { + panic("function with type parameters cannot have a receiver") + } + sig.tparams = bindTParams(typeParams) + } + return sig } // Recv returns the receiver of signature s (if a method), or nil if a -- GitLab From 02d56a1584f968b86b669b3b943dc2ffad30e087 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 27 Sep 2021 19:49:38 -0400 Subject: [PATCH 1347/2500] go/types: add the Interface.IsMethodSet method As pointed out in #47916, the IsConstraint method becomes ambiguously named if ever we allow interfaces with structural restrictions outside of constraint position. Add instead an IsMethodSet method, which has the opposite sense and avoids this ambiguity. In a subsequent CL the IsConstraint method will be removed, once x/tools has been updated to use the IsMethodSet API. Updates #47916 Change-Id: I82ad16b111464b0cd2f354b8ecdd4b3f14796cd9 Reviewed-on: https://go-review.googlesource.com/c/go/+/352616 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/interface.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/go/types/interface.go b/src/go/types/interface.go index c67aca7a20..ccea1f6dcc 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -104,7 +104,13 @@ func (t *Interface) Empty() bool { return t.typeSet().IsAll() } // IsComparable reports whether each type in interface t's type set is comparable. func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() } +// IsMethodSet reports whether the interface t is fully described by its method +// set. +func (t *Interface) IsMethodSet() bool { return !t.typeSet().IsConstraint() } + // IsConstraint reports whether interface t is not just a method set. +// +// TODO(rfindley): remove this method. func (t *Interface) IsConstraint() bool { return t.typeSet().IsConstraint() } // Complete computes the interface's type set. It must be called by users of -- GitLab From df63673d6a85d4243cc68c2225264afab6cfbf3b Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Mon, 27 Sep 2021 15:35:46 -0400 Subject: [PATCH 1348/2500] cmd/internal/obj: index pcdata symbols in NumberSyms When writing an object file, most symbols are indexed in NumberSyms. Currently, pcdata symbols are indexed late and separately. This is not really necessary, as pcdata symbols already exist at the time of NumberSyms. Just do it there. As pcdata symbols are laid out in the pclntab in a special way at link time, distinguish them from other symbols in the content hash. (In the old code this was partly achieved by indexing them late.) Change-Id: Ie9e721382b0af2cfb39350d031e2e66d79095a3c Reviewed-on: https://go-review.googlesource.com/c/go/+/352611 Trust: Cherry Mui Trust: Josh Bleecher Snyder Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Josh Bleecher Snyder --- src/cmd/internal/obj/link.go | 4 ++++ src/cmd/internal/obj/objfile.go | 24 ++++++++---------------- src/cmd/internal/obj/pcln.go | 4 ++-- src/cmd/internal/obj/sym.go | 28 ++++++++++++++++++++-------- 4 files changed, 34 insertions(+), 26 deletions(-) diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index 9be173ff98..82ff5994d1 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -700,6 +700,9 @@ const ( // convert between ABI0 and ABIInternal calling conventions. AttrABIWrapper + // IsPcdata indicates this is a pcdata symbol. + AttrPcdata + // attrABIBase is the value at which the ABI is encoded in // Attribute. This must be last; all bits after this are // assumed to be an ABI value. @@ -727,6 +730,7 @@ func (a *Attribute) Indexed() bool { return a.load()&AttrIndexed != 0 func (a *Attribute) UsedInIface() bool { return a.load()&AttrUsedInIface != 0 } func (a *Attribute) ContentAddressable() bool { return a.load()&AttrContentAddressable != 0 } func (a *Attribute) ABIWrapper() bool { return a.load()&AttrABIWrapper != 0 } +func (a *Attribute) IsPcdata() bool { return a.load()&AttrPcdata != 0 } func (a *Attribute) Set(flag Attribute, value bool) { for { diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index 1a8a9635d6..030a02b499 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -391,7 +391,9 @@ func (w *writer) Hash(s *LSym) { // TODO: instead of duplicating them, have the compiler decide where symbols go. func contentHashSection(s *LSym) byte { name := s.Name - if strings.HasPrefix(name, "type.") { + if s.IsPcdata() { + return 'P' + } else if strings.HasPrefix(name, "type.") { return 'T' } return 0 @@ -655,16 +657,6 @@ func nAuxSym(s *LSym) int { func genFuncInfoSyms(ctxt *Link) { infosyms := make([]*LSym, 0, len(ctxt.Text)) hashedsyms := make([]*LSym, 0, 4*len(ctxt.Text)) - preparePcSym := func(s *LSym) *LSym { - if s == nil { - return s - } - s.PkgIdx = goobj.PkgIdxHashed - s.SymIdx = int32(len(hashedsyms) + len(ctxt.hasheddefs)) - s.Set(AttrIndexed, true) - hashedsyms = append(hashedsyms, s) - return s - } var b bytes.Buffer symidx := int32(len(ctxt.defs)) for _, s := range ctxt.Text { @@ -679,13 +671,13 @@ func genFuncInfoSyms(ctxt *Link) { FuncFlag: fn.FuncFlag, } pc := &fn.Pcln - o.Pcsp = makeSymRef(preparePcSym(pc.Pcsp)) - o.Pcfile = makeSymRef(preparePcSym(pc.Pcfile)) - o.Pcline = makeSymRef(preparePcSym(pc.Pcline)) - o.Pcinline = makeSymRef(preparePcSym(pc.Pcinline)) + o.Pcsp = makeSymRef(pc.Pcsp) + o.Pcfile = makeSymRef(pc.Pcfile) + o.Pcline = makeSymRef(pc.Pcline) + o.Pcinline = makeSymRef(pc.Pcinline) o.Pcdata = make([]goobj.SymRef, len(pc.Pcdata)) for i, pcSym := range pc.Pcdata { - o.Pcdata[i] = makeSymRef(preparePcSym(pcSym)) + o.Pcdata[i] = makeSymRef(pcSym) } o.Funcdataoff = make([]uint32, len(pc.Funcdataoff)) for i, x := range pc.Funcdataoff { diff --git a/src/cmd/internal/obj/pcln.go b/src/cmd/internal/obj/pcln.go index 7af81335fb..42c4a2a9d9 100644 --- a/src/cmd/internal/obj/pcln.go +++ b/src/cmd/internal/obj/pcln.go @@ -26,7 +26,7 @@ func funcpctab(ctxt *Link, func_ *LSym, desc string, valfunc func(*Link, *LSym, dst := []byte{} sym := &LSym{ Type: objabi.SRODATA, - Attribute: AttrContentAddressable, + Attribute: AttrContentAddressable | AttrPcdata, } if dbg { @@ -337,7 +337,7 @@ func linkpcln(ctxt *Link, cursym *LSym) { // use an empty symbol. pcln.Pcdata[i] = &LSym{ Type: objabi.SRODATA, - Attribute: AttrContentAddressable, + Attribute: AttrContentAddressable | AttrPcdata, } } else { pcln.Pcdata[i] = funcpctab(ctxt, cursym, "pctopcdata", pctopcdata, interface{}(uint32(i))) diff --git a/src/cmd/internal/obj/sym.go b/src/cmd/internal/obj/sym.go index 6cd8bb3c3f..a272c517b3 100644 --- a/src/cmd/internal/obj/sym.go +++ b/src/cmd/internal/obj/sym.go @@ -201,7 +201,7 @@ func (ctxt *Link) NumberSyms() { ctxt.nonpkgdefs = []*LSym{} var idx, hashedidx, hashed64idx, nonpkgidx int32 - ctxt.traverseSyms(traverseDefs, func(s *LSym) { + ctxt.traverseSyms(traverseDefs|traversePcdata, func(s *LSym) { // if Pkgpath is unknown, cannot hash symbols with relocations, as it // may reference named symbols whose names are not fully expanded. if s.ContentAddressable() && (ctxt.Pkgpath != "" || len(s.R) == 0) { @@ -324,12 +324,18 @@ const ( traverseDefs traverseFlag = 1 << iota traverseRefs traverseAux + traversePcdata - traverseAll = traverseDefs | traverseRefs | traverseAux + traverseAll = traverseDefs | traverseRefs | traverseAux | traversePcdata ) // Traverse symbols based on flag, call fn for each symbol. func (ctxt *Link) traverseSyms(flag traverseFlag, fn func(*LSym)) { + fnNoNil := func(s *LSym) { + if s != nil { + fn(s) + } + } lists := [][]*LSym{ctxt.Text, ctxt.Data} for _, list := range lists { for _, s := range list { @@ -338,15 +344,11 @@ func (ctxt *Link) traverseSyms(flag traverseFlag, fn func(*LSym)) { } if flag&traverseRefs != 0 { for _, r := range s.R { - if r.Sym != nil { - fn(r.Sym) - } + fnNoNil(r.Sym) } } if flag&traverseAux != 0 { - if s.Gotype != nil { - fn(s.Gotype) - } + fnNoNil(s.Gotype) if s.Type == objabi.STEXT { f := func(parent *LSym, aux *LSym) { fn(aux) @@ -354,6 +356,16 @@ func (ctxt *Link) traverseSyms(flag traverseFlag, fn func(*LSym)) { ctxt.traverseFuncAux(flag, s, f) } } + if flag&traversePcdata != 0 && s.Type == objabi.STEXT { + fi := s.Func().Pcln + fnNoNil(fi.Pcsp) + fnNoNil(fi.Pcfile) + fnNoNil(fi.Pcline) + fnNoNil(fi.Pcinline) + for _, d := range fi.Pcdata { + fnNoNil(d) + } + } } } } -- GitLab From 583eeaae509a01cc50955c4174044b9dac539ff6 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Mon, 27 Sep 2021 15:55:53 -0400 Subject: [PATCH 1349/2500] cmd/internal/objfile: use aux symbol for pcdata references Pcdata are now separate aux symbols. Read them from aux, instead of using funcinfo. Change-Id: Ib3e4b5cff1e3329d0600504a8829a969a9c9f517 Reviewed-on: https://go-review.googlesource.com/c/go/+/352612 Trust: Cherry Mui Trust: Josh Bleecher Snyder Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Josh Bleecher Snyder --- src/cmd/internal/goobj/objfile.go | 2 ++ src/cmd/internal/objfile/goobj.go | 25 ++++++++++--------------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/cmd/internal/goobj/objfile.go b/src/cmd/internal/goobj/objfile.go index fc6dbb8af6..2c44696f84 100644 --- a/src/cmd/internal/goobj/objfile.go +++ b/src/cmd/internal/goobj/objfile.go @@ -357,6 +357,8 @@ type SymRef struct { SymIdx uint32 } +func (s SymRef) IsZero() bool { return s == SymRef{} } + // Hash64 type Hash64Type [Hash64Size]byte diff --git a/src/cmd/internal/objfile/goobj.go b/src/cmd/internal/objfile/goobj.go index dd21d22351..24d2d0bb5c 100644 --- a/src/cmd/internal/objfile/goobj.go +++ b/src/cmd/internal/objfile/goobj.go @@ -250,26 +250,21 @@ func (f *goobjFile) PCToLine(pc uint64) (string, int, *gosym.Func) { if pc < addr || pc >= addr+uint64(osym.Siz()) { continue } - isym := ^uint32(0) - auxs := r.Auxs(i) - for j := range auxs { - a := &auxs[j] - if a.Type() != goobj.AuxFuncInfo { - continue + var pcfileSym, pclineSym goobj.SymRef + for _, a := range r.Auxs(i) { + switch a.Type() { + case goobj.AuxPcfile: + pcfileSym = a.Sym() + case goobj.AuxPcline: + pclineSym = a.Sym() } - if a.Sym().PkgIdx != goobj.PkgIdxSelf { - panic("funcinfo symbol not defined in current package") - } - isym = a.Sym().SymIdx } - if isym == ^uint32(0) { + if pcfileSym.IsZero() || pclineSym.IsZero() { continue } - b := r.BytesAt(r.DataOff(isym), r.DataSize(isym)) - var info *goobj.FuncInfo - pcline := getSymData(info.ReadPcline(b)) + pcline := getSymData(pclineSym) line := int(pcValue(pcline, pc-addr, f.arch)) - pcfile := getSymData(info.ReadPcfile(b)) + pcfile := getSymData(pcfileSym) fileID := pcValue(pcfile, pc-addr, f.arch) fileName := r.File(int(fileID)) // Note: we provide only the name in the Func structure. -- GitLab From 73418bca347c94560a6cb605d8eb393b56941446 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 22 Sep 2021 09:55:10 -0700 Subject: [PATCH 1350/2500] cmd/compile/internal/types2: record all instances, not just inferred instances This is a port of CL 349629 from go/types to types2, adjusted to make it work for types2. It also includes the necessary compiler changes, provided by mdempsky. Change-Id: If8de174cee9c69df0d0642fcec1ee7622b7c3852 Reviewed-on: https://go-review.googlesource.com/c/go/+/351455 Trust: Robert Griesemer Trust: Dan Scales Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/expr.go | 79 ++--------- src/cmd/compile/internal/noder/irgen.go | 2 +- src/cmd/compile/internal/noder/object.go | 21 ++- src/cmd/compile/internal/noder/writer.go | 57 +++----- src/cmd/compile/internal/types2/api.go | 30 ++-- src/cmd/compile/internal/types2/api_test.go | 148 ++++++++++++++------ src/cmd/compile/internal/types2/call.go | 9 +- src/cmd/compile/internal/types2/check.go | 34 ++++- src/cmd/compile/internal/types2/typexpr.go | 1 + 9 files changed, 207 insertions(+), 174 deletions(-) diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 9852ad964c..3dd7737c9f 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -114,86 +114,27 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { case *syntax.CallExpr: fun := g.expr(expr.Fun) - - // The key for the Inferred map is the CallExpr (if inferring - // types required the function arguments) or the IndexExpr below - // (if types could be inferred without the function arguments). - if inferred, ok := g.info.Inferred[expr]; ok && inferred.TArgs.Len() > 0 { - // This is the case where inferring types required the - // types of the function arguments. - targs := make([]ir.Node, inferred.TArgs.Len()) - for i := range targs { - targs[i] = ir.TypeNode(g.typ(inferred.TArgs.At(i))) - } - if fun.Op() == ir.OFUNCINST { - if len(fun.(*ir.InstExpr).Targs) < len(targs) { - // Replace explicit type args with the full list that - // includes the additional inferred type args. - // Substitute the type args for the type params in - // the generic function's type. - fun.(*ir.InstExpr).Targs = targs - newt := g.substType(fun.(*ir.InstExpr).X.Type(), fun.(*ir.InstExpr).X.Type().TParams(), targs) - typed(newt, fun) - } - } else { - // Create a function instantiation here, given there - // are only inferred type args (e.g. min(5,6), where - // min is a generic function). Substitute the type - // args for the type params in the generic function's - // type. - inst := ir.NewInstExpr(pos, ir.OFUNCINST, fun, targs) - newt := g.substType(fun.Type(), fun.Type().TParams(), targs) - typed(newt, inst) - fun = inst - } - - } return Call(pos, g.typ(typ), fun, g.exprs(expr.ArgList), expr.HasDots) case *syntax.IndexExpr: - var targs []ir.Node - - if inferred, ok := g.info.Inferred[expr]; ok && inferred.TArgs.Len() > 0 { - // This is the partial type inference case where the types - // can be inferred from other type arguments without using - // the types of the function arguments. - targs = make([]ir.Node, inferred.TArgs.Len()) - for i := range targs { - targs[i] = ir.TypeNode(g.typ(inferred.TArgs.At(i))) - } - } else if _, ok := expr.Index.(*syntax.ListExpr); ok { - targs = g.exprList(expr.Index) - } else { - index := g.expr(expr.Index) - if index.Op() != ir.OTYPE { + args := unpackListExpr(expr.Index) + if len(args) == 1 { + tv, ok := g.info.Types[args[0]] + assert(ok) + if tv.IsValue() { // This is just a normal index expression - n := Index(pos, g.typ(typ), g.expr(expr.X), index) + n := Index(pos, g.typ(typ), g.expr(expr.X), g.expr(args[0])) if !g.delayTransform() { // transformIndex will modify n.Type() for OINDEXMAP. transformIndex(n) } return n } - // This is generic function instantiation with a single type - targs = []ir.Node{index} - } - // This is a generic function instantiation (e.g. min[int]). - // Generic type instantiation is handled in the type - // section of expr() above (using g.typ). - x := g.expr(expr.X) - if x.Op() != ir.ONAME || x.Type().Kind() != types.TFUNC { - panic("Incorrect argument for generic func instantiation") } - n := ir.NewInstExpr(pos, ir.OFUNCINST, x, targs) - newt := g.typ(typ) - // Substitute the type args for the type params in the uninstantiated - // function's type. If there aren't enough type args, then the rest - // will be inferred at the call node, so don't try the substitution yet. - if x.Type().TParams().NumFields() == len(targs) { - newt = g.substType(g.typ(typ), x.Type().TParams(), targs) - } - typed(newt, n) - return n + + // expr.Index is a list of type args, so we ignore it, since types2 has + // already provided this info with the Info.Instances map. + return g.expr(expr.X) case *syntax.SelectorExpr: // Qualified identifier. diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index e01e753a1d..c1a4f30f4a 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -59,7 +59,7 @@ func checkFiles(noders []*noder) (posMap, *types2.Package, *types2.Info) { Selections: make(map[*syntax.SelectorExpr]*types2.Selection), Implicits: make(map[syntax.Node]types2.Object), Scopes: make(map[syntax.Node]*types2.Scope), - Inferred: make(map[syntax.Expr]types2.Inferred), + Instances: make(map[*syntax.Name]types2.Instance), // expand as needed } diff --git a/src/cmd/compile/internal/noder/object.go b/src/cmd/compile/internal/noder/object.go index 40c0b9cf42..37a995b519 100644 --- a/src/cmd/compile/internal/noder/object.go +++ b/src/cmd/compile/internal/noder/object.go @@ -22,9 +22,10 @@ func (g *irgen) def(name *syntax.Name) (*ir.Name, types2.Object) { return g.obj(obj), obj } -// use returns the Name node associated with the use of name. The returned node -// will have the correct type and be marked as typechecked. -func (g *irgen) use(name *syntax.Name) *ir.Name { +// use returns the Name or InstExpr node associated with the use of name, +// possibly instantiated by type arguments. The returned node will have +// the correct type and be marked as typechecked. +func (g *irgen) use(name *syntax.Name) ir.Node { obj2, ok := g.info.Uses[name] if !ok { base.FatalfAt(g.pos(name), "unknown name %v", name) @@ -36,6 +37,20 @@ func (g *irgen) use(name *syntax.Name) *ir.Name { obj.SetTypecheck(1) obj.SetType(obj.Defn.Type()) } + + if obj.Class == ir.PFUNC { + if inst, ok := g.info.Instances[name]; ok { + // This is the case where inferring types required the + // types of the function arguments. + targs := make([]ir.Node, inst.TypeArgs.Len()) + for i := range targs { + targs[i] = ir.TypeNode(g.typ(inst.TypeArgs.At(i))) + } + typ := g.substType(obj.Type(), obj.Type().TParams(), targs) + return typed(typ, ir.NewInstExpr(g.pos(name), ir.OFUNCINST, obj, targs)) + } + } + return obj } diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 9edf5fc97a..47de992033 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -337,7 +337,7 @@ func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo { w.typ(typ.Elem()) case *types2.Signature: - assert(typ.TypeParams() == nil) + base.Assertf(typ.TypeParams() == nil, "unexpected type params: %v", typ) w.code(typeSignature) w.signature(typ) @@ -1158,11 +1158,16 @@ func (w *writer) optLabel(label *syntax.Name) { func (w *writer) expr(expr syntax.Expr) { expr = unparen(expr) // skip parens; unneeded after typecheck - obj, targs := lookupObj(w.p.info, expr) + obj, inst := lookupObj(w.p.info, expr) + targs := inst.TypeArgs if tv, ok := w.p.info.Types[expr]; ok { // TODO(mdempsky): Be more judicious about which types are marked as "needed". - w.needType(tv.Type) + if inst.Type != nil { + w.needType(inst.Type) + } else { + w.needType(tv.Type) + } if tv.IsType() { w.code(exprType) @@ -1303,16 +1308,7 @@ func (w *writer) expr(expr syntax.Expr) { } } - if inf, ok := w.p.info.Inferred[expr]; ok { - obj, _ := lookupObj(w.p.info, expr.Fun) - assert(obj != nil) - - // As if w.expr(expr.Fun), but using inf.TArgs instead. - w.code(exprName) - w.obj(obj, inf.TArgs) - } else { - w.expr(expr.Fun) - } + w.expr(expr.Fun) w.bool(false) // not a method call (i.e., normal function call) } @@ -1756,31 +1752,17 @@ func isGlobal(obj types2.Object) bool { } // lookupObj returns the object that expr refers to, if any. If expr -// is an explicit instantiation of a generic object, then the type -// arguments are returned as well. -func lookupObj(info *types2.Info, expr syntax.Expr) (obj types2.Object, targs *types2.TypeList) { +// is an explicit instantiation of a generic object, then the instance +// object is returned as well. +func lookupObj(info *types2.Info, expr syntax.Expr) (obj types2.Object, inst types2.Instance) { if index, ok := expr.(*syntax.IndexExpr); ok { - if inf, ok := info.Inferred[index]; ok { - targs = inf.TArgs - } else { - args := unpackListExpr(index.Index) - - if len(args) == 1 { - tv, ok := info.Types[args[0]] - assert(ok) - if tv.IsValue() { - return // normal index expression - } - } - - list := make([]types2.Type, len(args)) - for i, arg := range args { - tv, ok := info.Types[arg] - assert(ok) - assert(tv.IsType()) - list[i] = tv.Type + args := unpackListExpr(index.Index) + if len(args) == 1 { + tv, ok := info.Types[args[0]] + assert(ok) + if tv.IsValue() { + return // normal index expression } - targs = types2.NewTypeList(list) } expr = index.X @@ -1795,7 +1777,8 @@ func lookupObj(info *types2.Info, expr syntax.Expr) (obj types2.Object, targs *t } if name, ok := expr.(*syntax.Name); ok { - obj, _ = info.Uses[name] + obj = info.Uses[name] + inst = info.Instances[name] } return } diff --git a/src/cmd/compile/internal/types2/api.go b/src/cmd/compile/internal/types2/api.go index 6914e6c89f..b0e86357b7 100644 --- a/src/cmd/compile/internal/types2/api.go +++ b/src/cmd/compile/internal/types2/api.go @@ -214,11 +214,19 @@ type Info struct { // qualified identifiers are collected in the Uses map. Types map[syntax.Expr]TypeAndValue - // Inferred maps calls of parameterized functions that use - // type inference to the inferred type arguments and signature - // of the function called. The recorded "call" expression may be - // an *ast.CallExpr (as in f(x)), or an *ast.IndexExpr (s in f[T]). - Inferred map[syntax.Expr]Inferred + // Instances maps identifiers denoting parameterized types or functions to + // their type arguments and instantiated type. + // + // For example, Instances will map the identifier for 'T' in the type + // instantiation T[int, string] to the type arguments [int, string] and + // resulting instantiated *Named type. Given a parameterized function + // func F[A any](A), Instances will map the identifier for 'F' in the call + // expression F(int(1)) to the inferred type arguments [int], and resulting + // instantiated *Signature. + // + // Invariant: Instantiating Uses[id].Type() with Instances[id].TypeArgs + // results in an equivalent of Instances[id].Type. + Instances map[*syntax.Name]Instance // Defs maps identifiers to the objects they define (including // package names, dots "." of dot-imports, and blank "_" identifiers). @@ -375,11 +383,13 @@ func (tv TypeAndValue) HasOk() bool { return tv.mode == commaok || tv.mode == mapindex } -// Inferred reports the inferred type arguments and signature -// for a parameterized function call that uses type inference. -type Inferred struct { - TArgs *TypeList - Sig *Signature +// Instance reports the type arguments and instantiated type for type and +// function instantiations. For type instantiations, Type will be of dynamic +// type *Named. For function instantiations, Type will be of dynamic type +// *Signature. +type Instance struct { + TypeArgs *TypeList + Type Type } // An Initializer describes a package-level variable, or a list of variables in case diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index cd5a61332a..ca81620a78 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -382,12 +382,12 @@ func TestTypesInfo(t *testing.T) { } } -func TestInferredInfo(t *testing.T) { +func TestInstanceInfo(t *testing.T) { var tests = []struct { src string - fun string + name string targs []string - sig string + typ string }{ {genericPkg + `p0; func f[T any](T) {}; func _() { f(42) }`, `f`, @@ -417,33 +417,33 @@ func TestInferredInfo(t *testing.T) { // we don't know how to translate these but we can type-check them {genericPkg + `q0; type T struct{}; func (T) m[P any](P) {}; func _(x T) { x.m(42) }`, - `x.m`, + `m`, []string{`int`}, `func(int)`, }, {genericPkg + `q1; type T struct{}; func (T) m[P any](P) P { panic(0) }; func _(x T) { x.m(42) }`, - `x.m`, + `m`, []string{`int`}, `func(int) int`, }, {genericPkg + `q2; type T struct{}; func (T) m[P any](...P) P { panic(0) }; func _(x T) { x.m(42) }`, - `x.m`, + `m`, []string{`int`}, `func(...int) int`, }, {genericPkg + `q3; type T struct{}; func (T) m[A, B, C any](A, *B, []C) {}; func _(x T) { x.m(1.2, new(string), []byte{}) }`, - `x.m`, + `m`, []string{`float64`, `string`, `byte`}, `func(float64, *string, []byte)`, }, {genericPkg + `q4; type T struct{}; func (T) m[A, B any](A, *B, ...[]B) {}; func _(x T) { x.m(1.2, new(byte)) }`, - `x.m`, + `m`, []string{`float64`, `byte`}, `func(float64, *byte, ...[]byte)`, }, {genericPkg + `r0; type T[P any] struct{}; func (_ T[P]) m[Q any](Q) {}; func _[P any](x T[P]) { x.m(42) }`, - `x.m`, + `m`, []string{`int`}, `func(int)`, }, @@ -480,66 +480,130 @@ func TestInferredInfo(t *testing.T) { []string{`string`, `*string`}, `func() string`, }, - {genericPkg + `t2; type C[T any] interface{~chan<- T}; func f[T any, P C[T]]() []T { return nil }; func _() { _ = f[int] }`, + {genericPkg + `t2; func f[T any, P interface{~*T}]() T { panic(0) }; func _() { _ = (f[string]) }`, `f`, - []string{`int`, `chan<- int`}, - `func() []int`, + []string{`string`, `*string`}, + `func() string`, }, {genericPkg + `t3; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = f[int] }`, `f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func() []int`, }, + {genericPkg + `t4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = f[int] }`, + `f`, + []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, + `func() []int`, + }, + {genericPkg + `i0; import lib "generic_lib"; func _() { lib.F(42) }`, + `F`, + []string{`int`}, + `func(int)`, + }, + {genericPkg + `type0; type T[P interface{~int}] struct{ x P }; var _ T[int]`, + `T`, + []string{`int`}, + `struct{x int}`, + }, + {genericPkg + `type1; type T[P interface{~int}] struct{ x P }; var _ (T[int])`, + `T`, + []string{`int`}, + `struct{x int}`, + }, + {genericPkg + `type2; type T[P interface{~int}] struct{ x P }; var _ T[(int)]`, + `T`, + []string{`int`}, + `struct{x int}`, + }, + {genericPkg + `type3; type T[P1 interface{~[]P2}, P2 any] struct{ x P1; y P2 }; var _ T[[]int, int]`, + `T`, + []string{`[]int`, `int`}, + `struct{x []int; y int}`, + }, + {genericPkg + `type4; import lib "generic_lib"; var _ lib.T[int]`, + `T`, + []string{`int`}, + `[]int`, + }, } for _, test := range tests { - info := Info{Inferred: make(map[syntax.Expr]Inferred)} - name, err := mayTypecheck(t, "InferredInfo", test.src, &info) - if err != nil { - t.Errorf("package %s: %v", name, err) - continue - } + const lib = `package generic_lib - // look for inferred type arguments and signature - var targs *TypeList - var sig *Signature - for call, inf := range info.Inferred { - var fun syntax.Expr - switch x := call.(type) { - case *syntax.CallExpr: - fun = x.Fun - case *syntax.IndexExpr: - fun = x.X - default: - panic(fmt.Sprintf("unexpected call expression type %T", call)) +func F[P any](P) {} + +type T[P any] []P +` + + imports := make(testImporter) + conf := Config{Importer: imports} + instances := make(map[*syntax.Name]Instance) + uses := make(map[*syntax.Name]Object) + makePkg := func(src string) *Package { + f, err := parseSrc("p.go", src) + if err != nil { + t.Fatal(err) } - if syntax.String(fun) == test.fun { - targs = inf.TArgs - sig = inf.Sig + pkg, err := conf.Check("", []*syntax.File{f}, &Info{Instances: instances, Uses: uses}) + if err != nil { + t.Fatal(err) + } + imports[pkg.Name()] = pkg + return pkg + } + makePkg(lib) + pkg := makePkg(test.src) + + // look for instance information + var targs []Type + var typ Type + for ident, inst := range instances { + if syntax.String(ident) == test.name { + for i := 0; i < inst.TypeArgs.Len(); i++ { + targs = append(targs, inst.TypeArgs.At(i)) + } + typ = inst.Type + + // Check that we can find the corresponding parameterized type. + ptype := uses[ident].Type() + lister, _ := ptype.(interface{ TypeParams() *TypeParamList }) + if lister == nil || lister.TypeParams().Len() == 0 { + t.Errorf("package %s: info.Types[%v] = %v, want parameterized type", pkg.Name(), ident, ptype) + continue + } + + // Verify the invariant that re-instantiating the generic type with + // TypeArgs results in an equivalent type. + inst2, err := Instantiate(nil, ptype, targs, true) + if err != nil { + t.Errorf("Instantiate(%v, %v) failed: %v", ptype, targs, err) + } + if !Identical(inst.Type, inst2) { + t.Errorf("%v and %v are not identical", inst.Type, inst2) + } break } } if targs == nil { - t.Errorf("package %s: no inferred information found for %s", name, test.fun) + t.Errorf("package %s: no instance information found for %s", pkg.Name(), test.name) continue } // check that type arguments are correct - if targs.Len() != len(test.targs) { - t.Errorf("package %s: got %d type arguments; want %d", name, targs.Len(), len(test.targs)) + if len(targs) != len(test.targs) { + t.Errorf("package %s: got %d type arguments; want %d", pkg.Name(), len(targs), len(test.targs)) continue } - for i := 0; i < targs.Len(); i++ { - targ := targs.At(i) + for i, targ := range targs { if got := targ.String(); got != test.targs[i] { - t.Errorf("package %s, %d. type argument: got %s; want %s", name, i, got, test.targs[i]) + t.Errorf("package %s, %d. type argument: got %s; want %s", pkg.Name(), i, got, test.targs[i]) continue } } - // check that signature is correct - if got := sig.String(); got != test.sig { - t.Errorf("package %s: got %s; want %s", name, got, test.sig) + // check that the types match + if got := typ.Underlying().String(); got != test.typ { + t.Errorf("package %s: got %s; want %s", pkg.Name(), got, test.typ) } } } diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 99afecaf19..5cf292ce8a 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -38,8 +38,6 @@ func (check *Checker) funcInst(x *operand, inst *syntax.IndexExpr) { return } - // if we don't have enough type arguments, try type inference - inferred := false if got < want { targs = check.infer(inst.Pos(), sig.TypeParams().list(), targs, nil, nil) if targs == nil { @@ -49,7 +47,6 @@ func (check *Checker) funcInst(x *operand, inst *syntax.IndexExpr) { return } got = len(targs) - inferred = true } assert(got == want) @@ -62,9 +59,7 @@ func (check *Checker) funcInst(x *operand, inst *syntax.IndexExpr) { // instantiate function signature res := check.instantiate(x.Pos(), sig, targs, poslist).(*Signature) assert(res.TypeParams().Len() == 0) // signature is not generic anymore - if inferred { - check.recordInferred(inst, targs, res) - } + check.recordInstance(inst.X, targs, res) x.typ = res x.mode = value x.expr = inst @@ -346,7 +341,7 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T // compute result signature rsig = check.instantiate(call.Pos(), sig, targs, nil).(*Signature) assert(rsig.TypeParams().Len() == 0) // signature is not generic anymore - check.recordInferred(call, targs, rsig) + check.recordInstance(call.Fun, targs, rsig) // Optimization: Only if the parameter list was adjusted do we // need to compute it from the adjusted list; otherwise we can diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go index 24a05e6b37..e45598e0ef 100644 --- a/src/cmd/compile/internal/types2/check.go +++ b/src/cmd/compile/internal/types2/check.go @@ -415,12 +415,36 @@ func (check *Checker) recordCommaOkTypes(x syntax.Expr, a [2]Type) { } } -func (check *Checker) recordInferred(call syntax.Expr, targs []Type, sig *Signature) { - assert(call != nil) - assert(sig != nil) - if m := check.Inferred; m != nil { - m[call] = Inferred{NewTypeList(targs), sig} +// recordInstance records instantiation information into check.Info, if the +// Instances map is non-nil. The given expr must be an ident, selector, or +// index (list) expr with ident or selector operand. +// +// TODO(rfindley): the expr parameter is fragile. See if we can access the +// instantiated identifier in some other way. +func (check *Checker) recordInstance(expr syntax.Expr, targs []Type, typ Type) { + ident := instantiatedIdent(expr) + assert(ident != nil) + assert(typ != nil) + if m := check.Instances; m != nil { + m[ident] = Instance{NewTypeList(targs), typ} + } +} + +func instantiatedIdent(expr syntax.Expr) *syntax.Name { + var selOrIdent syntax.Expr + switch e := expr.(type) { + case *syntax.IndexExpr: + selOrIdent = e.X + case *syntax.SelectorExpr, *syntax.Name: + selOrIdent = e + } + switch x := selOrIdent.(type) { + case *syntax.Name: + return x + case *syntax.SelectorExpr: + return x.Sel } + panic("instantiated ident not found") } func (check *Checker) recordDef(id *syntax.Name, obj Object) { diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 7f75a96bd8..3bfce2ebf2 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -408,6 +408,7 @@ func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def typ := check.instantiate(x.Pos(), base, targs, posList) def.setUnderlying(typ) + check.recordInstance(x, targs, typ) // make sure we check instantiation works at least once // and that the resulting type is valid -- GitLab From 4a8995179edc48bf37aacc80703287c4c6b2e8e1 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 28 Sep 2021 09:45:24 -0700 Subject: [PATCH 1351/2500] cmd/compile/internal/types2: add a NewSignatureType constructor accepting type parameters This is a clean port of CL 352615 from go/types to types2 with renames from types -> types2. Change-Id: Ib9bae3fd8b93c3bd6c56e4e039a296cb34b0eb47 Reviewed-on: https://go-review.googlesource.com/c/go/+/352869 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/importer/iimport.go | 21 ++++++++-------- src/cmd/compile/internal/types2/signature.go | 26 +++++++++++++++++++- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index a92720d52e..b99956de26 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -313,8 +313,7 @@ func (r *importReader) obj(name string) { if tag == 'G' { tparams = r.tparamList() } - sig := r.signature(nil) - sig.SetTypeParams(tparams) + sig := r.signature(nil, nil, tparams) r.declare(types2.NewFunc(pos, r.currPkg, name, sig)) case 'T', 'U': @@ -338,19 +337,19 @@ func (r *importReader) obj(name string) { mpos := r.pos() mname := r.ident() recv := r.param() - msig := r.signature(recv) // If the receiver has any targs, set those as the // rparams of the method (since those are the // typeparams being used in the method sig/body). - targs := baseType(msig.Recv().Type()).TypeArgs() + targs := baseType(recv.Type()).TypeArgs() + var rparams []*types2.TypeParam if targs.Len() > 0 { - rparams := make([]*types2.TypeParam, targs.Len()) + rparams = make([]*types2.TypeParam, targs.Len()) for i := range rparams { - rparams[i] = types2.AsTypeParam(targs.At(i)) + rparams[i], _ = targs.At(i).(*types2.TypeParam) } - msig.SetRecvTypeParams(rparams) } + msig := r.signature(recv, rparams, nil) named.AddMethod(types2.NewFunc(mpos, r.currPkg, mname, msig)) } @@ -584,7 +583,7 @@ func (r *importReader) doType(base *types2.Named) types2.Type { return types2.NewMap(r.typ(), r.typ()) case signatureType: r.currPkg = r.pkg() - return r.signature(nil) + return r.signature(nil, nil, nil) case structType: r.currPkg = r.pkg() @@ -624,7 +623,7 @@ func (r *importReader) doType(base *types2.Named) types2.Type { recv = types2.NewVar(syntax.Pos{}, r.currPkg, "", base) } - msig := r.signature(recv) + msig := r.signature(recv, nil, nil) methods[i] = types2.NewFunc(mpos, r.currPkg, mname, msig) } @@ -681,11 +680,11 @@ func (r *importReader) kind() itag { return itag(r.uint64()) } -func (r *importReader) signature(recv *types2.Var) *types2.Signature { +func (r *importReader) signature(recv *types2.Var, rparams, tparams []*types2.TypeParam) *types2.Signature { params := r.paramList() results := r.paramList() variadic := params.Len() > 0 && r.bool() - return types2.NewSignature(recv, params, results, variadic) + return types2.NewSignatureType(recv, rparams, tparams, params, results, variadic) } func (r *importReader) tparamList() []*types2.TypeParam { diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index e3186f5eed..a5348b3b14 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -32,7 +32,18 @@ type Signature struct { // and results, either of which may be nil. If variadic is set, the function // is variadic, it must have at least one parameter, and the last parameter // must be of unnamed slice type. +// +// Deprecated: Use NewSignatureType instead which allows for type parameters. func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature { + return NewSignatureType(recv, nil, nil, params, results, variadic) +} + +// NewSignatureType creates a new function type for the given receiver, +// receiver type parameters, type parameters, parameters, and results. If +// variadic is set, params must hold at least one parameter and the last +// parameter must be of unnamed slice type. If recv is non-nil, typeParams must +// be empty. If recvTypeParams is non-empty, recv must be non-nil. +func NewSignatureType(recv *Var, recvTypeParams, typeParams []*TypeParam, params, results *Tuple, variadic bool) *Signature { if variadic { n := params.Len() if n == 0 { @@ -42,7 +53,20 @@ func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature { panic("variadic parameter must be of unnamed slice type") } } - return &Signature{recv: recv, params: params, results: results, variadic: variadic} + sig := &Signature{recv: recv, params: params, results: results, variadic: variadic} + if len(recvTypeParams) != 0 { + if recv == nil { + panic("function with receiver type parameters must have a receiver") + } + sig.rparams = bindTParams(recvTypeParams) + } + if len(typeParams) != 0 { + if recv != nil { + panic("function with type parameters cannot have a receiver") + } + sig.tparams = bindTParams(typeParams) + } + return sig } // Recv returns the receiver of signature s (if a method), or nil if a -- GitLab From e301b2f11c905672eccd418fd581c0432a07ac04 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 23 Sep 2021 11:37:52 -0400 Subject: [PATCH 1352/2500] io: update ByteScanner and RuneScanner docs to match long-standing implementations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do not require the byte or rune unread by the call to match the last return from ReadByte or ReadRune, since in practice the implementations of these methods (especially ReadByte) may also unread bytes from other Read-style methods without reporting an error. Explicitly allow the Seek-like behavior implemented by bytes.Reader and bufio.Reader, which can “unread” bytes that were never actually read. Explicitly allow ReadByte or ReadRune to return an error after a call to a non-ReadByte or non-ReadRune operation respectively. (In practice, implementations today allow very liberal calls to ReadByte and tend to be more strict about ReadRune, but it seems simpler to keep the two definitions completely parallel.) Like CL 349054, this is techincally a breaking change, but given the long-standing behavior of the implementations in the Go standard library (such as strings.Reader, bytes.Buffer, and bufio.Reader), I believe it falls under the “specification errors” exception to the Go 1 compatibility policy. Fixes #48449 Change-Id: I61696a59770fe83c667377ba25a072762d3f6f19 Reviewed-on: https://go-review.googlesource.com/c/go/+/351809 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Rob Pike --- src/io/io.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/io/io.go b/src/io/io.go index cb2a37e427..ceac7ba7f8 100644 --- a/src/io/io.go +++ b/src/io/io.go @@ -262,10 +262,11 @@ type ByteReader interface { // ByteScanner is the interface that adds the UnreadByte method to the // basic ReadByte method. // -// UnreadByte causes the next call to ReadByte to return the same byte -// as the previous call to ReadByte. -// It may be an error to call UnreadByte twice without an intervening -// call to ReadByte. +// UnreadByte causes the next call to ReadByte to return the last byte read. +// If the last operation was not a successful call to ReadByte, UnreadByte may +// return an error, unread the last byte read (or the byte prior to the +// last-unread byte), or (in implementations that support the Seeker interface) +// seek to one byte before the current offset. type ByteScanner interface { ByteReader UnreadByte() error @@ -288,10 +289,11 @@ type RuneReader interface { // RuneScanner is the interface that adds the UnreadRune method to the // basic ReadRune method. // -// UnreadRune causes the next call to ReadRune to return the same rune -// as the previous call to ReadRune. -// It may be an error to call UnreadRune twice without an intervening -// call to ReadRune. +// UnreadRune causes the next call to ReadRune to return the last rune read. +// If the last operation was not a successful call to ReadRune, UnreadRune may +// return an error, unread the last rune read (or the rune prior to the +// last-unread rune), or (in implementations that support the Seeker interface) +// seek to the start of the rune before the current offset. type RuneScanner interface { RuneReader UnreadRune() error -- GitLab From ff7b04136091f8208352e97c117ca6489ca95a86 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 14 Sep 2021 16:23:10 -0700 Subject: [PATCH 1353/2500] cmd/go: 'go get' no longer builds or installs packages As part of #40267, 'go install' is now fully responsible for building and installing executables. 'go get' will only be used to change versions in go.mod. The -d flag no longer has any effect; its behavior is the default. When 'go get' is invoked inside a module on a main package outside of the main module, it no longer prints any warning. In 1.16-1.17, we suggested using -d in this situation, but we want 'go get example.com/cmd' to be able to upgrade a tool dependency without needing -d to suppress the warning. For #43684 Change-Id: I9daf29c123a5a0e382aa326d62721cb26fc26c19 Reviewed-on: https://go-review.googlesource.com/c/go/+/349997 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/alldocs.go | 24 ++--- src/cmd/go/internal/modget/get.go | 95 +++---------------- src/cmd/go/testdata/script/build_trimpath.txt | 3 +- .../{mod_get_svn.txt => mod_download_svn.txt} | 15 +-- src/cmd/go/testdata/script/mod_get_cmd.txt | 20 ---- src/cmd/go/testdata/script/mod_get_commit.txt | 9 +- .../script/mod_get_deprecate_install.txt | 16 ++-- src/cmd/go/testdata/script/mod_get_errors.txt | 22 +---- src/cmd/go/testdata/script/mod_get_tags.txt | 13 +-- src/cmd/go/testdata/script/mod_outside.txt | 24 ----- 10 files changed, 48 insertions(+), 193 deletions(-) rename src/cmd/go/testdata/script/{mod_get_svn.txt => mod_download_svn.txt} (61%) delete mode 100644 src/cmd/go/testdata/script/mod_get_cmd.txt diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 7be673b290..8a2109619d 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -613,11 +613,11 @@ // // Usage: // -// go get [-d] [-t] [-u] [-v] [build flags] [packages] +// go get [-t] [-u] [-v] [build flags] [packages] // // Get resolves its command-line arguments to packages at specific module versions, -// updates go.mod to require those versions, downloads source code into the -// module cache, then builds and installs the named packages. +// updates go.mod to require those versions, and downloads source code into the +// module cache. // // To add a dependency for a package or upgrade it to its latest version: // @@ -633,9 +633,11 @@ // // See https://golang.org/ref/mod#go-get for details. // -// The 'go install' command may be used to build and install packages. When a -// version is specified, 'go install' runs in module-aware mode and ignores -// the go.mod file in the current directory. For example: +// In earlier versions of Go, 'go get' was used to build and install packages. +// Now, 'go get' is dedicated to adjusting dependencies in go.mod. 'go install' +// may be used to build and install commands instead. When a version is specified, +// 'go install' runs in module-aware mode and ignores the go.mod file in the +// current directory. For example: // // go install example.com/pkg@v1.2.3 // go install example.com/pkg@latest @@ -658,16 +660,6 @@ // When the -t and -u flags are used together, get will update // test dependencies as well. // -// The -d flag instructs get not to build or install packages. get will only -// update go.mod and download source code needed to build packages. -// -// Building and installing packages with get is deprecated. In a future release, -// the -d flag will be enabled by default, and 'go get' will be only be used to -// adjust dependencies of the current module. To install a package using -// dependencies from the current module, use 'go install'. To install a package -// ignoring the current module, use 'go install' with an @version suffix like -// "@latest" after each argument. -// // For more about modules, see https://golang.org/ref/mod. // // For more about specifying packages, see 'go help packages'. diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index 20734bdd23..674ee1c267 100644 --- a/src/cmd/go/internal/modget/get.go +++ b/src/cmd/go/internal/modget/get.go @@ -37,7 +37,6 @@ import ( "cmd/go/internal/base" "cmd/go/internal/imports" - "cmd/go/internal/load" "cmd/go/internal/modfetch" "cmd/go/internal/modload" "cmd/go/internal/par" @@ -50,14 +49,14 @@ import ( ) var CmdGet = &base.Command{ - // Note: -d -u are listed explicitly because they are the most common get flags. + // Note: flags below are listed explicitly because they're the most common. // Do not send CLs removing them because they're covered by [get flags]. - UsageLine: "go get [-d] [-t] [-u] [-v] [build flags] [packages]", + UsageLine: "go get [-t] [-u] [-v] [build flags] [packages]", Short: "add dependencies to current module and install them", Long: ` Get resolves its command-line arguments to packages at specific module versions, -updates go.mod to require those versions, downloads source code into the -module cache, then builds and installs the named packages. +updates go.mod to require those versions, and downloads source code into the +module cache. To add a dependency for a package or upgrade it to its latest version: @@ -73,9 +72,11 @@ To remove a dependency on a module and downgrade modules that require it: See https://golang.org/ref/mod#go-get for details. -The 'go install' command may be used to build and install packages. When a -version is specified, 'go install' runs in module-aware mode and ignores -the go.mod file in the current directory. For example: +In earlier versions of Go, 'go get' was used to build and install packages. +Now, 'go get' is dedicated to adjusting dependencies in go.mod. 'go install' +may be used to build and install commands instead. When a version is specified, +'go install' runs in module-aware mode and ignores the go.mod file in the +current directory. For example: go install example.com/pkg@v1.2.3 go install example.com/pkg@latest @@ -98,16 +99,6 @@ but changes the default to select patch releases. When the -t and -u flags are used together, get will update test dependencies as well. -The -d flag instructs get not to build or install packages. get will only -update go.mod and download source code needed to build packages. - -Building and installing packages with get is deprecated. In a future release, -the -d flag will be enabled by default, and 'go get' will be only be used to -adjust dependencies of the current module. To install a package using -dependencies from the current module, use 'go install'. To install a package -ignoring the current module, use 'go install' with an @version suffix like -"@latest" after each argument. - For more about modules, see https://golang.org/ref/mod. For more about specifying packages, see 'go help packages'. @@ -218,7 +209,7 @@ variable for future go command invocations. } var ( - getD = CmdGet.Flag.Bool("d", false, "") + getD = CmdGet.Flag.Bool("d", true, "") getF = CmdGet.Flag.Bool("f", false, "") getFix = CmdGet.Flag.Bool("fix", false, "") getM = CmdGet.Flag.Bool("m", false, "") @@ -265,6 +256,10 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { default: base.Fatalf("go: unknown upgrade flag -u=%s", getU.rawVersion) } + // TODO(#43684): in the future (Go 1.20), warn that -d is a no-op. + if !*getD { + base.Fatalf("go: -d flag may not be disabled") + } if *getF { fmt.Fprintf(os.Stderr, "go: -f flag is a no-op when using modules\n") } @@ -272,7 +267,7 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { fmt.Fprintf(os.Stderr, "go: -fix flag is a no-op when using modules\n") } if *getM { - base.Fatalf("go: -m flag is no longer supported; consider -d to skip building packages") + base.Fatalf("go: -m flag is no longer supported") } if *getInsecure { base.Fatalf("go: -insecure flag is no longer supported; use GOINSECURE instead") @@ -356,66 +351,6 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { } r.checkPackageProblems(ctx, pkgPatterns) - // We've already downloaded modules (and identified direct and indirect - // dependencies) by loading packages in findAndUpgradeImports. - // So if -d is set, we're done after the module work. - // - // Otherwise, we need to build and install the packages matched by - // command line arguments. - // Note that 'go get -u' without arguments is equivalent to - // 'go get -u .', so we'll typically build the package in the current - // directory. - if !*getD && len(pkgPatterns) > 0 { - work.BuildInit() - - pkgOpts := load.PackageOpts{ModResolveTests: *getT} - var pkgs []*load.Package - for _, pkg := range load.PackagesAndErrors(ctx, pkgOpts, pkgPatterns) { - if pkg.Error != nil { - var noGo *load.NoGoError - if errors.As(pkg.Error.Err, &noGo) { - if m := modload.PackageModule(pkg.ImportPath); m.Path == pkg.ImportPath { - // pkg is at the root of a module, and doesn't exist with the current - // build tags. Probably the user just wanted to change the version of - // that module — not also build the package — so suppress the error. - // (See https://golang.org/issue/33526.) - continue - } - } - } - pkgs = append(pkgs, pkg) - } - load.CheckPackageErrors(pkgs) - - haveExternalExe := false - for _, pkg := range pkgs { - if pkg.Name == "main" && pkg.Module != nil { - if !modload.MainModules.Contains(pkg.Module.Path) { - haveExternalExe = true - break - } - } - } - if haveExternalExe { - fmt.Fprint(os.Stderr, "go: installing executables with 'go get' in module mode is deprecated.") - var altMsg string - if modload.HasModRoot() { - altMsg = ` - To adjust and download dependencies of the current module, use 'go get -d'. - To install using requirements of the current module, use 'go install'. - To install ignoring the current module, use 'go install' with a version, - like 'go install example.com/cmd@latest'. -` - } else { - altMsg = "\n\tUse 'go install pkg@version' instead.\n" - } - fmt.Fprint(os.Stderr, altMsg) - fmt.Fprintf(os.Stderr, "\tFor more information, see https://golang.org/doc/go-get-install-deprecation\n\tor run 'go help get' or 'go help install'.\n") - } - - work.InstallPackages(ctx, pkgPatterns, pkgs) - } - if !modload.HasModRoot() { return } diff --git a/src/cmd/go/testdata/script/build_trimpath.txt b/src/cmd/go/testdata/script/build_trimpath.txt index 2c3bee8fdc..f36b1237dc 100644 --- a/src/cmd/go/testdata/script/build_trimpath.txt +++ b/src/cmd/go/testdata/script/build_trimpath.txt @@ -32,7 +32,8 @@ stdout 'binary contains GOROOT: false' # A binary from an external module built with -trimpath should not contain # the current workspace or GOROOT. -go get -trimpath rsc.io/fortune +go get rsc.io/fortune +go install -trimpath rsc.io/fortune exec $WORK/paths-a.exe $GOPATH/bin/fortune$GOEXE stdout 'binary contains module root: false' stdout 'binary contains GOROOT: false' diff --git a/src/cmd/go/testdata/script/mod_get_svn.txt b/src/cmd/go/testdata/script/mod_download_svn.txt similarity index 61% rename from src/cmd/go/testdata/script/mod_get_svn.txt rename to src/cmd/go/testdata/script/mod_download_svn.txt index 4d6b94ae5b..79e00dc970 100644 --- a/src/cmd/go/testdata/script/mod_get_svn.txt +++ b/src/cmd/go/testdata/script/mod_download_svn.txt @@ -1,7 +1,7 @@ [!net] skip [!exec:svn] skip -# 'go get' will fall back to svn+ssh once svn fails over protocols like https. +# 'go mod download' will fall back to svn+ssh once svn fails over protocols like https. # If vcs-test.golang.org isn't in the user's known_hosts file, this will result # in an ssh prompt, which will stop 'go test' entirely # @@ -19,18 +19,11 @@ env GOPROXY=direct env GOSUMDB=off # Attempting to get a module zip using svn should succeed. -go get vcs-test.golang.org/svn/hello.svn@000000000001 +go mod download vcs-test.golang.org/svn/hello.svn@000000000001 exists $GOPATH/pkg/mod/cache/download/vcs-test.golang.org/svn/hello.svn/@v/v0.0.0-20170922011245-000000000001.zip -exists $GOPATH/bin/hello.svn$GOEXE # Attempting to get a nonexistent module using svn should fail with a # reasonable message instead of a panic. -! go get -d vcs-test.golang.org/svn/nonexistent.svn +! go mod download vcs-test.golang.org/svn/nonexistent.svn@latest ! stderr panic -stderr 'go: vcs-test.golang.org/svn/nonexistent.svn: no matching versions for query "upgrade"' - --- go.mod -- -module golang/go/issues/28943/main --- go.sum -- -vcs-test.golang.org/svn/hello.svn v0.0.0-20170922011245-000000000001 h1:rZjvboXMfQICKXdhx/QHqJ2Y/AQsJVrXnwGqwcTxQiw= -vcs-test.golang.org/svn/hello.svn v0.0.0-20170922011245-000000000001/go.mod h1:0memnh/BRLuxiK2zF4rvUgz6ts/fhhB28l3ULFWPusc= +stderr 'go: module vcs-test.golang.org/svn/nonexistent.svn: no matching versions for query "latest"$' diff --git a/src/cmd/go/testdata/script/mod_get_cmd.txt b/src/cmd/go/testdata/script/mod_get_cmd.txt deleted file mode 100644 index d31cee1444..0000000000 --- a/src/cmd/go/testdata/script/mod_get_cmd.txt +++ /dev/null @@ -1,20 +0,0 @@ -env GO111MODULE=on -[short] skip - -# Test that when 'go get' is run from $GOBIN, it does not delete binaries -# after it installs them. Verifies golang.org/issue/32766. - -go get example.com/tools/cmd/hello - -# 'go get' should not delete the command when run from $GOPATH/bin -cd $GOPATH/bin -exists hello$GOEXE -go get example.com/tools/cmd/hello -exists hello$GOEXE - -# 'go get' should not delete the command when run from a different $GOBIN -mkdir $WORK/bin -cd $WORK/bin -env GOBIN=$WORK/bin -go get example.com/tools/cmd/hello -exists hello$GOEXE diff --git a/src/cmd/go/testdata/script/mod_get_commit.txt b/src/cmd/go/testdata/script/mod_get_commit.txt index 0cf94ae182..ff7185f59a 100644 --- a/src/cmd/go/testdata/script/mod_get_commit.txt +++ b/src/cmd/go/testdata/script/mod_get_commit.txt @@ -16,7 +16,7 @@ go get -d golang.org/x/text@14c0d48 env GOCACHE=$WORK/gocache # Looking for compile commands, so need a clean cache. -go get -x golang.org/x/text/language@14c0d48 +go build -x golang.org/x/text/language stderr 'compile|cp|gccgo .*language\.a$' # BUG: after the build, the package should not be stale, as 'go install' would @@ -24,12 +24,13 @@ stderr 'compile|cp|gccgo .*language\.a$' go list -f '{{.Stale}}' golang.org/x/text/language stdout ^true -# install after get should not run the compiler again. +# install after build should not run the compiler again. go install -x golang.org/x/text/language ! stderr 'compile|cp|gccgo .*language\.a$' -# even with -d, we should see an error for unknown packages. -! go get -d -x golang.org/x/text/foo@14c0d48 +# we should see an error for unknown packages. +! go get -x golang.org/x/text/foo@14c0d48 +stderr '^go: module golang.org/x/text@14c0d48 found \(v0.3.0\), but does not contain package golang.org/x/text/foo$' # get pseudo-version should record that version go get -d rsc.io/quote@v0.0.0-20180214005840-23179ee8a569 diff --git a/src/cmd/go/testdata/script/mod_get_deprecate_install.txt b/src/cmd/go/testdata/script/mod_get_deprecate_install.txt index e8142afee9..ab1d6a43f7 100644 --- a/src/cmd/go/testdata/script/mod_get_deprecate_install.txt +++ b/src/cmd/go/testdata/script/mod_get_deprecate_install.txt @@ -2,10 +2,7 @@ env GO111MODULE=on -# 'go get' outside a module with an executable prints a deprecation message. -go get example.com/cmd/a -stderr '^go: installing executables with ''go get'' in module mode is deprecated.$' -stderr 'Use ''go install pkg@version'' instead.' +# TODO(#43684): test message outside module. cp go.mod.orig go.mod @@ -13,13 +10,16 @@ cp go.mod.orig go.mod # This will stop building in the future, but it's the command we want to use. go get rsc.io/quote ! stderr deprecated +! stderr 'no longer installs' cp go.mod.orig go.mod -# 'go get' inside a module with an executable prints a different -# deprecation message. +# 'go get' inside a module with an executable does not print a message. +# In 1.16 and 1.17, 'go get' did print a message in this case suggesting the +# use of -d. In 1.18, -d is a no-op, and we'd like to begin discouraging +# its use. go get example.com/cmd/a -stderr '^go: installing executables with ''go get'' in module mode is deprecated.$' -stderr 'To adjust and download dependencies of the current module, use ''go get -d''' +! stderr deprecated +! stderr 'no longer installs' cp go.mod.orig go.mod # 'go get' should not print a warning for a main package inside the main module. diff --git a/src/cmd/go/testdata/script/mod_get_errors.txt b/src/cmd/go/testdata/script/mod_get_errors.txt index 5c37058d1c..7cb03ce2f1 100644 --- a/src/cmd/go/testdata/script/mod_get_errors.txt +++ b/src/cmd/go/testdata/script/mod_get_errors.txt @@ -1,35 +1,23 @@ cp go.mod go.mod.orig -# Both 'go get' and 'go get -d' should fail, without updating go.mod, -# if the transitive dependencies of the requested package (by default, -# the package in the current directory) cannot be resolved. +# 'go get' should fail, without updating go.mod, if the transitive dependencies +# of the requested package (by default, the package in the current directory) +# cannot be resolved. ! go get stderr '^example.com/m imports\n\texample.com/badimport imports\n\texample.net/oops: cannot find module providing package example.net/oops$' cmp go.mod.orig go.mod -! go get -d -stderr '^example.com/m imports\n\texample.com/badimport imports\n\texample.net/oops: cannot find module providing package example.net/oops$' -cmp go.mod.orig go.mod - cd importsyntax -# If 'go get' fails due to a compile error (such as a syntax error), -# it should not update the go.mod file. - -! go get -stderr '^..[/\\]badimport[/\\]syntaxerror[/\\]syntaxerror.go:1:1: expected ''package'', found pack$' # TODO: An import stack would be nice. -cmp ../go.mod.orig ../go.mod - - # A syntax error in a dependency prevents the compiler from needing that -# dependency's imports, so 'go get -d' should not report an error when those +# dependency's imports, so 'go get' should not report an error when those # imports cannot be resolved: it has all of the dependencies that the compiler # needs, and the user did not request to run the compiler. -go get -d +go get cmp ../go.mod.syntax-d ../go.mod diff --git a/src/cmd/go/testdata/script/mod_get_tags.txt b/src/cmd/go/testdata/script/mod_get_tags.txt index e9869e3f02..e4fb6c4326 100644 --- a/src/cmd/go/testdata/script/mod_get_tags.txt +++ b/src/cmd/go/testdata/script/mod_get_tags.txt @@ -1,25 +1,14 @@ env GO111MODULE=on -[short] skip - # get should add modules needed to build packages, even if those # dependencies are in sources excluded by build tags. # All build tags are considered true except "ignore". go mod init m -go get -d . +go get . go list -m all stdout 'example.com/version v1.1.0' stdout 'rsc.io/quote v1.5.2' -[short] skip - -# Packages that are only imported in excluded files should not be built. -env GOCACHE=$WORK/gocache # Looking for compile commands, so need a clean cache. -go get -n -x . -stderr 'compile.* -p m ' -! stderr 'compile.* -p example.com/version ' -! stderr 'compile.* -p rsc.io/quote ' - -- empty.go -- package m diff --git a/src/cmd/go/testdata/script/mod_outside.txt b/src/cmd/go/testdata/script/mod_outside.txt index 6da6314b79..e5318ee13d 100644 --- a/src/cmd/go/testdata/script/mod_outside.txt +++ b/src/cmd/go/testdata/script/mod_outside.txt @@ -223,30 +223,6 @@ go fmt needmod/needmod.go # The remainder of the test checks dependencies by linking and running binaries. -# 'go get' of a binary without a go.mod should install the requested version, -# resolving outside dependencies to the latest available versions. -go get example.com/printversion@v0.1.0 -exec ../bin/printversion -stdout 'path is example.com/printversion' -stdout 'main is example.com/printversion v0.1.0' -stdout 'using example.com/version v1.1.0' - -# 'go get' of a versioned binary should build and install the latest version -# using its minimal required modules, ignoring replacements and exclusions. -go get example.com/printversion -exec ../bin/printversion -stdout 'path is example.com/printversion' -stdout 'main is example.com/printversion v1.0.0' -stdout 'using example.com/version v1.0.0' - -# 'go get -u=patch' should patch dependencies before installing, -# again ignoring replacements and exclusions. -go get -u=patch example.com/printversion@v1.0.0 -exec ../bin/printversion -stdout 'path is example.com/printversion' -stdout 'main is example.com/printversion v1.0.0' -stdout 'using example.com/version v1.0.1' - # 'go run' should work with file arguments if they don't import anything # outside std. go run ./stdonly/stdonly.go -- GitLab From 1c6e50a15200673eb90c817cb6709be5d06cd3f4 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Fri, 24 Sep 2021 13:26:35 -0700 Subject: [PATCH 1354/2500] cmd/go: make 'go get' fail with an error when outside a module There's no go.mod file for 'go get' to update, so it has no effect, other than checking arguments and filling the module cache. That might be useul in some cases, but it seems better to fail loudly in case the user hasn't seen the deprecation warning, for example, inside a script. For #43684 Change-Id: I6e67c782e3a1cb7046eac5c9df17eda7a31c7bce Reviewed-on: https://go-review.googlesource.com/c/go/+/352149 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/modget/get.go | 20 ++++++++-- src/cmd/go/testdata/script/get_404_meta.txt | 6 +++ src/cmd/go/testdata/script/mod_cache_dir.txt | 4 +- ...txt => mod_download_insecure_redirect.txt} | 10 ++--- ...e_vcs.txt => mod_download_private_vcs.txt} | 6 +-- ...xt => mod_download_too_many_redirects.txt} | 4 +- .../script/mod_get_deprecate_install.txt | 5 ++- .../go/testdata/script/mod_get_fallback.txt | 5 +++ .../go/testdata/script/mod_get_go_file.txt | 5 +++ src/cmd/go/testdata/script/mod_getx.txt | 5 +++ .../go/testdata/script/mod_missing_repo.txt | 4 +- src/cmd/go/testdata/script/mod_outside.txt | 38 +++++++++---------- 12 files changed, 74 insertions(+), 38 deletions(-) rename src/cmd/go/testdata/script/{mod_get_insecure_redirect.txt => mod_download_insecure_redirect.txt} (65%) rename src/cmd/go/testdata/script/{mod_get_private_vcs.txt => mod_download_private_vcs.txt} (88%) rename src/cmd/go/testdata/script/{mod_get_too_many_redirects.txt => mod_download_too_many_redirects.txt} (69%) diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index 674ee1c267..4d87d2670d 100644 --- a/src/cmd/go/internal/modget/get.go +++ b/src/cmd/go/internal/modget/get.go @@ -273,6 +273,8 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { base.Fatalf("go: -insecure flag is no longer supported; use GOINSECURE instead") } + modload.ForceUseModules = true + // Do not allow any updating of go.mod until we've applied // all the requested changes and checked that the result matches // what was requested. @@ -282,6 +284,20 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { // 'go get' is expected to do this, unlike other commands. modload.AllowMissingModuleImports() + // 'go get' no longer builds or installs packages, so there's nothing to do + // if there's no go.mod file. + // TODO(#40775): make modload.Init return ErrNoModRoot instead of exiting. + // We could handle that here by printing a different message. + modload.Init() + if !modload.HasModRoot() { + base.Fatalf("go: go.mod file not found in current directory or any parent directory.\n" + + "\t'go get' is no longer supported outside a module.\n" + + "\tTo build and install a command, use 'go install' with a version,\n" + + "\tlike 'go install example.com/cmd@latest'\n" + + "\tFor more information, see https://golang.org/doc/go-get-install-deprecation\n" + + "\tor run 'go help get' or 'go help install'.") + } + queries := parseArgs(ctx, args) r := newResolver(ctx, queries) @@ -351,10 +367,6 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { } r.checkPackageProblems(ctx, pkgPatterns) - if !modload.HasModRoot() { - return - } - // Everything succeeded. Update go.mod. oldReqs := reqsFromGoMod(modload.ModFile()) diff --git a/src/cmd/go/testdata/script/get_404_meta.txt b/src/cmd/go/testdata/script/get_404_meta.txt index ec4f8d3243..3caf0bfecc 100644 --- a/src/cmd/go/testdata/script/get_404_meta.txt +++ b/src/cmd/go/testdata/script/get_404_meta.txt @@ -10,3 +10,9 @@ go get -d bazil.org/fuse/fs/fstestutil env GO111MODULE=on env GOPROXY=direct go get -d bazil.org/fuse/fs/fstestutil + + +-- go.mod -- +module m + +go 1.18 diff --git a/src/cmd/go/testdata/script/mod_cache_dir.txt b/src/cmd/go/testdata/script/mod_cache_dir.txt index 7284ccf8ba..4045928a97 100644 --- a/src/cmd/go/testdata/script/mod_cache_dir.txt +++ b/src/cmd/go/testdata/script/mod_cache_dir.txt @@ -3,9 +3,9 @@ env GO111MODULE=on # Go should reject relative paths in GOMODCACHE environment. env GOMODCACHE="~/test" -! go get example.com/tools/cmd/hello +! go install example.com/tools/cmd/hello@latest stderr 'must be absolute path' env GOMODCACHE="./test" -! go get example.com/tools/cmd/hello +! go install example.com/tools/cmd/hello@latest stderr 'must be absolute path' diff --git a/src/cmd/go/testdata/script/mod_get_insecure_redirect.txt b/src/cmd/go/testdata/script/mod_download_insecure_redirect.txt similarity index 65% rename from src/cmd/go/testdata/script/mod_get_insecure_redirect.txt rename to src/cmd/go/testdata/script/mod_download_insecure_redirect.txt index 2e12834495..46eb666686 100644 --- a/src/cmd/go/testdata/script/mod_get_insecure_redirect.txt +++ b/src/cmd/go/testdata/script/mod_download_insecure_redirect.txt @@ -7,26 +7,26 @@ env GO111MODULE=on env GOPROXY=direct env GOSUMDB=off -! go get -d vcs-test.golang.org/insecure/go/insecure +! go mod download vcs-test.golang.org/insecure/go/insecure@latest stderr 'redirected .* to insecure URL' # insecure host env GOINSECURE=vcs-test.golang.org go clean -modcache -go get -d vcs-test.golang.org/insecure/go/insecure +go mod download vcs-test.golang.org/insecure/go/insecure@latest # insecure glob host env GOINSECURE=*.golang.org go clean -modcache -go get -d vcs-test.golang.org/insecure/go/insecure +go mod download vcs-test.golang.org/insecure/go/insecure@latest # insecure multiple host env GOINSECURE=somewhere-else.com,*.golang.org go clean -modcache -go get -d vcs-test.golang.org/insecure/go/insecure +go mod download vcs-test.golang.org/insecure/go/insecure@latest # different insecure host does not fetch env GOINSECURE=somewhere-else.com go clean -modcache -! go get -d vcs-test.golang.org/insecure/go/insecure +! go mod download vcs-test.golang.org/insecure/go/insecure@latest stderr 'redirected .* to insecure URL' diff --git a/src/cmd/go/testdata/script/mod_get_private_vcs.txt b/src/cmd/go/testdata/script/mod_download_private_vcs.txt similarity index 88% rename from src/cmd/go/testdata/script/mod_get_private_vcs.txt rename to src/cmd/go/testdata/script/mod_download_private_vcs.txt index c8862f42f9..e126793907 100644 --- a/src/cmd/go/testdata/script/mod_get_private_vcs.txt +++ b/src/cmd/go/testdata/script/mod_download_private_vcs.txt @@ -5,18 +5,18 @@ env GO111MODULE=on [!exec:git] skip env GOPROXY=direct -! go get github.com/golang/nonexist +! go mod download github.com/golang/nonexist@latest stderr 'Confirm the import path was entered correctly.' stderr 'If this is a private repository, see https://golang.org/doc/faq#git_https for additional information.' ! stdout . # Fetching a nonexistent commit should return an "unknown revision" # error message. -! go get github.com/golang/term@86186f3aba07ed0212cfb944f3398997d2d07c6b +! go mod download github.com/golang/term@86186f3aba07ed0212cfb944f3398997d2d07c6b stderr '^go: github.com/golang/term@86186f3aba07ed0212cfb944f3398997d2d07c6b: invalid version: unknown revision 86186f3aba07ed0212cfb944f3398997d2d07c6b$' ! stdout . -! go get github.com/golang/nonexist@master +! go mod download github.com/golang/nonexist@master stderr '^Confirm the import path was entered correctly.$' stderr '^If this is a private repository, see https://golang.org/doc/faq#git_https for additional information.$' ! stderr 'unknown revision' diff --git a/src/cmd/go/testdata/script/mod_get_too_many_redirects.txt b/src/cmd/go/testdata/script/mod_download_too_many_redirects.txt similarity index 69% rename from src/cmd/go/testdata/script/mod_get_too_many_redirects.txt rename to src/cmd/go/testdata/script/mod_download_too_many_redirects.txt index 9cbe0d279d..a6b5a59054 100644 --- a/src/cmd/go/testdata/script/mod_get_too_many_redirects.txt +++ b/src/cmd/go/testdata/script/mod_download_too_many_redirects.txt @@ -3,8 +3,8 @@ env GOPROXYBASE=$GOPROXY env GOPROXY=$GOPROXYBASE/redirect/11 env GOSUMDB=off -! go get -d rsc.io/quote@v1.2.0 +! go mod download rsc.io/quote@v1.2.0 stderr 'stopped after 10 redirects' env GOPROXY=$GOPROXYBASE/redirect/9 -go get -d rsc.io/quote@v1.2.0 +go mod download rsc.io/quote@v1.2.0 diff --git a/src/cmd/go/testdata/script/mod_get_deprecate_install.txt b/src/cmd/go/testdata/script/mod_get_deprecate_install.txt index ab1d6a43f7..03258f5296 100644 --- a/src/cmd/go/testdata/script/mod_get_deprecate_install.txt +++ b/src/cmd/go/testdata/script/mod_get_deprecate_install.txt @@ -2,7 +2,10 @@ env GO111MODULE=on -# TODO(#43684): test message outside module. +# 'go get' outside a module prints an error. +! go get example.com/cmd/a +stderr '^go: go.mod file not found in current directory or any parent directory.$' +stderr '^\t''go get'' is no longer supported outside a module.$' cp go.mod.orig go.mod diff --git a/src/cmd/go/testdata/script/mod_get_fallback.txt b/src/cmd/go/testdata/script/mod_get_fallback.txt index 9733fa366b..a61d5cb00e 100644 --- a/src/cmd/go/testdata/script/mod_get_fallback.txt +++ b/src/cmd/go/testdata/script/mod_get_fallback.txt @@ -8,3 +8,8 @@ env GOSUMDB=off go get -x -v -d golang.org/x/tools/cmd/goimports stderr '# get https://proxy.golang.org/golang.org/x/tools/@v/list' ! stderr '# get https://golang.org' + +-- go.mod -- +module m + +go 1.18 diff --git a/src/cmd/go/testdata/script/mod_get_go_file.txt b/src/cmd/go/testdata/script/mod_get_go_file.txt index 35a77a9d83..c81e491b94 100644 --- a/src/cmd/go/testdata/script/mod_get_go_file.txt +++ b/src/cmd/go/testdata/script/mod_get_go_file.txt @@ -58,6 +58,11 @@ mkdir test/test_dir.go rm test/test_dir.go +-- go.mod -- +module m + +go 1.18 + -- test.go -- package main func main() {println("test")} diff --git a/src/cmd/go/testdata/script/mod_getx.txt b/src/cmd/go/testdata/script/mod_getx.txt index ccb8d1375a..ce9ef0d6ce 100644 --- a/src/cmd/go/testdata/script/mod_getx.txt +++ b/src/cmd/go/testdata/script/mod_getx.txt @@ -12,3 +12,8 @@ go get -x -d golang.org/x/text@v0.1.0 stderr '^# get https://golang.org/x/text\?go-get=1$' stderr '^# get https://golang.org/x/text\?go-get=1: 200 OK \([0-9.]+s\)$' ! stderr '^# get //.*' + +-- go.mod -- +module m + +go 1.18 diff --git a/src/cmd/go/testdata/script/mod_missing_repo.txt b/src/cmd/go/testdata/script/mod_missing_repo.txt index 8dae85fa88..b91a8dbeda 100644 --- a/src/cmd/go/testdata/script/mod_missing_repo.txt +++ b/src/cmd/go/testdata/script/mod_missing_repo.txt @@ -9,7 +9,7 @@ env GO111MODULE=on env GOPROXY=direct env GOSUMDB=off -! go get -d vcs-test.golang.org/go/missingrepo/missingrepo-git +! go mod download vcs-test.golang.org/go/missingrepo/missingrepo-git@latest stderr 'vcs-test.golang.org/go/missingrepo/missingrepo-git: git ls-remote .*: exit status .*' -go get -d vcs-test.golang.org/go/missingrepo/missingrepo-git/notmissing +go mod download vcs-test.golang.org/go/missingrepo/missingrepo-git/notmissing@latest diff --git a/src/cmd/go/testdata/script/mod_outside.txt b/src/cmd/go/testdata/script/mod_outside.txt index e5318ee13d..d9d364cc10 100644 --- a/src/cmd/go/testdata/script/mod_outside.txt +++ b/src/cmd/go/testdata/script/mod_outside.txt @@ -123,30 +123,30 @@ stderr '^go: go.mod file not found in current directory or any parent directory; stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$' -# 'go get' without arguments implicitly operates on the main module, and thus -# should fail. +# 'go get' has no go.mod file to update outside a module and should fail. ! go get -stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$' +stderr '^go: go.mod file not found in current directory or any parent directory.$' +stderr '^\t''go get'' is no longer supported outside a module.$' ! go get -u -stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$' +stderr '^go: go.mod file not found in current directory or any parent directory.$' +stderr '^\t''go get'' is no longer supported outside a module.$' ! go get -u ./needmod -stderr '^go: go.mod file not found in current directory or any parent directory; see ''go help modules''$' - -# 'go get -u all' upgrades the transitive import graph of the main module, -# which is empty. +stderr '^go: go.mod file not found in current directory or any parent directory.$' +stderr '^\t''go get'' is no longer supported outside a module.$' ! go get -u all -stderr '^go: cannot match "all": go.mod file not found in current directory or any parent directory; see ''go help modules''$' - -# 'go get' should check the proposed module graph for consistency, -# even though we won't write it anywhere. +stderr '^go: go.mod file not found in current directory or any parent directory.$' +stderr '^\t''go get'' is no longer supported outside a module.$' ! go get -d example.com/printversion@v1.0.0 example.com/version@none -stderr '^go: example.com/printversion@v1.0.0 requires example.com/version@v1.0.0, not example.com/version@none$' - -# 'go get -d' should download and extract the source code needed to build the requested version. -rm -r $GOPATH/pkg/mod/example.com -go get -d example.com/printversion@v1.0.0 -exists $GOPATH/pkg/mod/example.com/printversion@v1.0.0 -exists $GOPATH/pkg/mod/example.com/version@v1.0.0 +stderr '^go: go.mod file not found in current directory or any parent directory.$' +stderr '^\t''go get'' is no longer supported outside a module.$' + +# 'go get -d' should not download anything. +go clean -modcache +! go get -d example.com/printversion@v1.0.0 +stderr '^go: go.mod file not found in current directory or any parent directory.$' +stderr '^\t''go get'' is no longer supported outside a module.$' +! exists $GOPATH/pkg/mod/example.com/printversion@v1.0.0 +! exists $GOPATH/pkg/mod/example.com/version@v1.0.0 # 'go build' without arguments implicitly operates on the current directory, and should fail. -- GitLab From 86bd1ecef01f2c25c311b0e3a5a82527676b80c6 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Fri, 24 Sep 2021 13:51:39 -0700 Subject: [PATCH 1355/2500] cmd/go: change 'go get -d' to 'go get' in tests The -d flag has no effect in module mode. GOPATH tests are left alone. For #43684 Change-Id: If0f0aad73d8b543ca4058fe9c9fea9d7fd7f95bd Reviewed-on: https://go-review.googlesource.com/c/go/+/352150 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- .../testdata/script/build_cache_disabled.txt | 2 +- .../testdata/script/build_cache_trimpath.txt | 4 +-- src/cmd/go/testdata/script/get_404_meta.txt | 2 +- src/cmd/go/testdata/script/govcs.txt | 2 +- src/cmd/go/testdata/script/mod_bad_domain.txt | 4 +-- .../go/testdata/script/mod_build_info_err.txt | 2 +- .../testdata/script/mod_build_versioned.txt | 2 +- src/cmd/go/testdata/script/mod_cache_rw.txt | 4 +-- src/cmd/go/testdata/script/mod_case.txt | 4 +-- src/cmd/go/testdata/script/mod_case_cgo.txt | 2 +- src/cmd/go/testdata/script/mod_concurrent.txt | 2 +- .../testdata/script/mod_deprecate_message.txt | 8 +++--- .../go/testdata/script/mod_domain_root.txt | 2 +- .../testdata/script/mod_download_partial.txt | 2 +- .../testdata/script/mod_get_ambiguous_arg.txt | 8 +++--- .../script/mod_get_ambiguous_import.txt | 4 +-- .../testdata/script/mod_get_ambiguous_pkg.txt | 14 +++++----- .../go/testdata/script/mod_get_changes.txt | 6 ++--- src/cmd/go/testdata/script/mod_get_commit.txt | 8 +++--- .../go/testdata/script/mod_get_deprecated.txt | 16 ++++++------ .../script/mod_get_downadd_indirect.txt | 2 +- .../go/testdata/script/mod_get_downgrade.txt | 12 ++++----- .../script/mod_get_downgrade_missing.txt | 8 +++--- .../script/mod_get_downup_artifact.txt | 2 +- .../script/mod_get_downup_indirect.txt | 2 +- .../script/mod_get_downup_pseudo_artifact.txt | 2 +- src/cmd/go/testdata/script/mod_get_extra.txt | 4 +-- .../go/testdata/script/mod_get_fallback.txt | 2 +- .../testdata/script/mod_get_incompatible.txt | 6 ++--- .../go/testdata/script/mod_get_indirect.txt | 2 +- .../go/testdata/script/mod_get_issue37438.txt | 2 +- .../go/testdata/script/mod_get_issue47979.txt | 4 +-- .../testdata/script/mod_get_latest_pseudo.txt | 2 +- src/cmd/go/testdata/script/mod_get_local.txt | 22 ++++++++-------- src/cmd/go/testdata/script/mod_get_main.txt | 22 ++++++++-------- src/cmd/go/testdata/script/mod_get_major.txt | 4 +-- .../script/mod_get_missing_ziphash.txt | 4 +-- src/cmd/go/testdata/script/mod_get_moved.txt | 12 ++++----- src/cmd/go/testdata/script/mod_get_none.txt | 4 +-- src/cmd/go/testdata/script/mod_get_nopkgs.txt | 8 +++--- src/cmd/go/testdata/script/mod_get_patch.txt | 6 ++--- .../go/testdata/script/mod_get_patchbound.txt | 2 +- .../go/testdata/script/mod_get_patchmod.txt | 12 ++++----- .../go/testdata/script/mod_get_patterns.txt | 10 +++---- .../go/testdata/script/mod_get_pkgtags.txt | 16 ++++++------ .../script/mod_get_prefer_incompatible.txt | 2 +- .../script/mod_get_promote_implicit.txt | 4 +-- src/cmd/go/testdata/script/mod_get_pseudo.txt | 26 +++++++++---------- .../script/mod_get_pseudo_other_branch.txt | 2 +- .../testdata/script/mod_get_pseudo_prefix.txt | 4 +-- .../go/testdata/script/mod_get_replaced.txt | 22 ++++++++-------- .../go/testdata/script/mod_get_retract.txt | 14 +++++----- .../script/mod_get_retract_ambiguous.txt | 2 +- src/cmd/go/testdata/script/mod_get_split.txt | 24 ++++++++--------- .../go/testdata/script/mod_get_sum_noroot.txt | 2 +- src/cmd/go/testdata/script/mod_get_test.txt | 14 +++++----- .../script/mod_get_trailing_slash.txt | 9 +------ .../script/mod_get_update_unrelated_sum.txt | 10 +++---- .../go/testdata/script/mod_get_upgrade.txt | 14 +++++----- .../script/mod_get_upgrade_pseudo.txt | 20 +++++++------- src/cmd/go/testdata/script/mod_get_wild.txt | 4 +-- .../go/testdata/script/mod_getmode_vendor.txt | 2 +- src/cmd/go/testdata/script/mod_getx.txt | 2 +- src/cmd/go/testdata/script/mod_gomodcache.txt | 4 +-- src/cmd/go/testdata/script/mod_gonoproxy.txt | 14 +++++----- .../go/testdata/script/mod_gopkg_unstable.txt | 4 +-- src/cmd/go/testdata/script/mod_import.txt | 2 +- .../testdata/script/mod_import_v1suffix.txt | 2 +- .../testdata/script/mod_in_testdata_dir.txt | 2 +- .../script/mod_install_pkg_version.txt | 4 +-- .../testdata/script/mod_install_versioned.txt | 4 +-- src/cmd/go/testdata/script/mod_internal.txt | 20 +++++++------- .../go/testdata/script/mod_invalid_path.txt | 4 +-- .../script/mod_invalid_path_dotname.txt | 6 ++--- .../testdata/script/mod_invalid_path_plus.txt | 4 +-- .../testdata/script/mod_invalid_version.txt | 10 +++---- src/cmd/go/testdata/script/mod_issue35317.txt | 2 +- .../go/testdata/script/mod_lazy_downgrade.txt | 12 ++++----- .../testdata/script/mod_list_deprecated.txt | 2 +- src/cmd/go/testdata/script/mod_list_dir.txt | 4 +-- .../go/testdata/script/mod_list_direct.txt | 2 +- .../testdata/script/mod_list_replace_dir.txt | 2 +- .../script/mod_list_upgrade_pseudo.txt | 4 +-- .../go/testdata/script/mod_load_badchain.txt | 4 +-- .../go/testdata/script/mod_load_badzip.txt | 2 +- src/cmd/go/testdata/script/mod_multirepo.txt | 2 +- src/cmd/go/testdata/script/mod_outside.txt | 6 ++--- src/cmd/go/testdata/script/mod_overlay.txt | 14 +++++----- .../go/testdata/script/mod_permissions.txt | 2 +- src/cmd/go/testdata/script/mod_proxy_list.txt | 14 +++++----- .../go/testdata/script/mod_query_empty.txt | 8 +++--- .../go/testdata/script/mod_query_exclude.txt | 6 ++--- src/cmd/go/testdata/script/mod_readonly.txt | 6 ++--- src/cmd/go/testdata/script/mod_replace.txt | 2 +- .../go/testdata/script/mod_replace_import.txt | 2 +- .../testdata/script/mod_replace_readonly.txt | 4 +-- src/cmd/go/testdata/script/mod_retract.txt | 2 +- .../script/mod_retract_incompatible.txt | 4 +-- .../script/mod_retract_pseudo_base.txt | 4 +-- .../testdata/script/mod_retract_rationale.txt | 14 +++++----- .../go/testdata/script/mod_retract_rename.txt | 6 ++--- .../testdata/script/mod_retract_replace.txt | 2 +- src/cmd/go/testdata/script/mod_sum_lookup.txt | 2 +- .../go/testdata/script/mod_sum_replaced.txt | 4 +-- src/cmd/go/testdata/script/mod_sumdb.txt | 10 +++---- .../go/testdata/script/mod_sumdb_cache.txt | 14 +++++----- .../testdata/script/mod_sumdb_file_path.txt | 10 +++---- .../go/testdata/script/mod_sumdb_golang.txt | 2 +- .../go/testdata/script/mod_sumdb_proxy.txt | 14 +++++----- src/cmd/go/testdata/script/mod_symlink.txt | 6 ++--- .../testdata/script/mod_tidy_convergence.txt | 4 +-- .../script/mod_tidy_convergence_loop.txt | 4 +-- .../go/testdata/script/mod_tidy_replace.txt | 2 +- src/cmd/go/testdata/script/mod_tidy_sum.txt | 4 +-- .../go/testdata/script/mod_upgrade_patch.txt | 26 +++++++++---------- .../go/testdata/script/mod_vcs_missing.txt | 2 +- .../go/testdata/script/mod_vendor_auto.txt | 2 +- .../go/testdata/script/mod_vendor_build.txt | 2 +- src/cmd/go/testdata/script/mod_verify.txt | 2 +- src/cmd/go/testdata/script/modfile_flag.txt | 2 +- .../script/vendor_list_issue11977.txt | 2 +- src/cmd/go/testdata/script/version.txt | 2 +- .../go/testdata/script/version_replace.txt | 2 +- 123 files changed, 385 insertions(+), 392 deletions(-) diff --git a/src/cmd/go/testdata/script/build_cache_disabled.txt b/src/cmd/go/testdata/script/build_cache_disabled.txt index 8b005c857f..cb1a7558fc 100644 --- a/src/cmd/go/testdata/script/build_cache_disabled.txt +++ b/src/cmd/go/testdata/script/build_cache_disabled.txt @@ -9,7 +9,7 @@ # * go fix # * go fmt # * go generate -# * go get -d +# * go get # * go list (without -export or -compiled) env GOCACHE=off diff --git a/src/cmd/go/testdata/script/build_cache_trimpath.txt b/src/cmd/go/testdata/script/build_cache_trimpath.txt index 9a4b9d7b40..7ee3c3b41d 100644 --- a/src/cmd/go/testdata/script/build_cache_trimpath.txt +++ b/src/cmd/go/testdata/script/build_cache_trimpath.txt @@ -16,10 +16,10 @@ stderr 'link( |\.exe)' # Two distinct versions of the same module with identical content should # still be cached separately. # Verifies golang.org/issue/35412. -go get -d example.com/stack@v1.0.0 +go get example.com/stack@v1.0.0 go run -trimpath printstack.go stdout '^example.com/stack@v1.0.0/stack.go$' -go get -d example.com/stack@v1.0.1 +go get example.com/stack@v1.0.1 go run -trimpath printstack.go stdout '^example.com/stack@v1.0.1/stack.go$' diff --git a/src/cmd/go/testdata/script/get_404_meta.txt b/src/cmd/go/testdata/script/get_404_meta.txt index 3caf0bfecc..29fc5421e1 100644 --- a/src/cmd/go/testdata/script/get_404_meta.txt +++ b/src/cmd/go/testdata/script/get_404_meta.txt @@ -9,7 +9,7 @@ go get -d bazil.org/fuse/fs/fstestutil env GO111MODULE=on env GOPROXY=direct -go get -d bazil.org/fuse/fs/fstestutil +go get bazil.org/fuse/fs/fstestutil -- go.mod -- diff --git a/src/cmd/go/testdata/script/govcs.txt b/src/cmd/go/testdata/script/govcs.txt index e8dd791267..46f1bd0da2 100644 --- a/src/cmd/go/testdata/script/govcs.txt +++ b/src/cmd/go/testdata/script/govcs.txt @@ -43,7 +43,7 @@ stderr '^go: github.com/google/go-cmp: unreachable pattern in GOVCS: "github.com # bad GOVCS patterns do not stop commands that do not need to check VCS go list env GOPROXY=$proxy -go get -d rsc.io/quote # ok because used proxy +go get rsc.io/quote # ok because used proxy env GOPROXY=direct # svn is disallowed by default diff --git a/src/cmd/go/testdata/script/mod_bad_domain.txt b/src/cmd/go/testdata/script/mod_bad_domain.txt index ed6a8c656d..afd6e5186c 100644 --- a/src/cmd/go/testdata/script/mod_bad_domain.txt +++ b/src/cmd/go/testdata/script/mod_bad_domain.txt @@ -24,10 +24,10 @@ stderr '^usenonexistent[/\\]x.go:2:8: no required module provides package nonexi # 'get -d' should be similarly definitive -go get -d ./useappengine # TODO(#41315): This should fail. +go get ./useappengine # TODO(#41315): This should fail. # stderr '^useappengine[/\\]x.go:2:8: cannot find package$' -! go get -d ./usenonexistent +! go get ./usenonexistent stderr '^x/usenonexistent imports\n\tnonexistent.rsc.io: cannot find module providing package nonexistent.rsc.io$' diff --git a/src/cmd/go/testdata/script/mod_build_info_err.txt b/src/cmd/go/testdata/script/mod_build_info_err.txt index cee055eabe..5c3c309b0d 100644 --- a/src/cmd/go/testdata/script/mod_build_info_err.txt +++ b/src/cmd/go/testdata/script/mod_build_info_err.txt @@ -11,7 +11,7 @@ stderr '^bad[/\\]bad.go:3:8: malformed import path "🐧.example.com/string": in # TODO(#41688): This should include a file and line, and report the reason for the error.. # (Today it includes only an import stack.) -! go get -d ./main +! go get ./main stderr '^m/main imports\n\tm/bad imports\n\t🐧.example.com/string: malformed import path "🐧.example.com/string": invalid char ''🐧''$' diff --git a/src/cmd/go/testdata/script/mod_build_versioned.txt b/src/cmd/go/testdata/script/mod_build_versioned.txt index d1d74de10c..f55041834a 100644 --- a/src/cmd/go/testdata/script/mod_build_versioned.txt +++ b/src/cmd/go/testdata/script/mod_build_versioned.txt @@ -1,7 +1,7 @@ env GO111MODULE=on [short] skip -go get -d rsc.io/fortune/v2 +go get rsc.io/fortune/v2 # The default executable name shouldn't be v2$GOEXE go build rsc.io/fortune/v2 diff --git a/src/cmd/go/testdata/script/mod_cache_rw.txt b/src/cmd/go/testdata/script/mod_cache_rw.txt index a5410764bc..07755415d6 100644 --- a/src/cmd/go/testdata/script/mod_cache_rw.txt +++ b/src/cmd/go/testdata/script/mod_cache_rw.txt @@ -5,7 +5,7 @@ env GO111MODULE=on # golang.org/issue/31481: an explicit flag should make directories in the module # cache writable in order to work around the historical inability of 'rm -rf' to # forcibly remove files in unwritable directories. -go get -modcacherw -d rsc.io/quote@v1.5.2 +go get -modcacherw rsc.io/quote@v1.5.2 cp $WORK/extraneous.txt $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/extraneous_file.go # After adding an extraneous file, 'go mod verify' should fail. @@ -28,7 +28,7 @@ cp $WORK/extraneous.txt $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/extraneous_file.go # Windows does not respect FILE_ATTRIBUTE_READONLY on directories, according # to MSDN, so there we disable testing whether the directory itself is # unwritable. -go get -d rsc.io/quote@latest +go get rsc.io/quote@latest [!root] ! cp $WORK/extraneous.txt $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/go.mod [!windows] [!root] ! cp $WORK/extraneous.txt $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/extraneous_file.go ! exists $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/extraneous_file.go diff --git a/src/cmd/go/testdata/script/mod_case.txt b/src/cmd/go/testdata/script/mod_case.txt index 4a4698600f..d3fb11dfa3 100644 --- a/src/cmd/go/testdata/script/mod_case.txt +++ b/src/cmd/go/testdata/script/mod_case.txt @@ -1,6 +1,6 @@ env GO111MODULE=on -go get -d +go get go list -m all stdout '^rsc.io/quote v1.5.2' stdout '^rsc.io/QUOTE v1.5.2' @@ -9,7 +9,7 @@ go list -f 'DIR {{.Dir}} DEPS {{.Deps}}' rsc.io/QUOTE/QUOTE stdout 'DEPS.*rsc.io/quote' stdout 'DIR.*!q!u!o!t!e' -go get -d rsc.io/QUOTE@v1.5.3-PRE +go get rsc.io/QUOTE@v1.5.3-PRE go list -m all stdout '^rsc.io/QUOTE v1.5.3-PRE' diff --git a/src/cmd/go/testdata/script/mod_case_cgo.txt b/src/cmd/go/testdata/script/mod_case_cgo.txt index f3d6aaa5ab..7c768a0963 100644 --- a/src/cmd/go/testdata/script/mod_case_cgo.txt +++ b/src/cmd/go/testdata/script/mod_case_cgo.txt @@ -2,7 +2,7 @@ env GO111MODULE=on -go get -d rsc.io/CGO +go get rsc.io/CGO [short] stop go build rsc.io/CGO diff --git a/src/cmd/go/testdata/script/mod_concurrent.txt b/src/cmd/go/testdata/script/mod_concurrent.txt index 8c21525158..e2224d659b 100644 --- a/src/cmd/go/testdata/script/mod_concurrent.txt +++ b/src/cmd/go/testdata/script/mod_concurrent.txt @@ -1,7 +1,7 @@ env GO111MODULE=on # Concurrent builds should succeed, even if they need to download modules. -go get -d ./x ./y +go get ./x ./y go build ./x & go build ./y wait diff --git a/src/cmd/go/testdata/script/mod_deprecate_message.txt b/src/cmd/go/testdata/script/mod_deprecate_message.txt index 567027935d..8e2771dc1f 100644 --- a/src/cmd/go/testdata/script/mod_deprecate_message.txt +++ b/src/cmd/go/testdata/script/mod_deprecate_message.txt @@ -1,25 +1,25 @@ # When there is a short single-line message, 'go get' should print it all. -go get -d short +go get short stderr '^go: module short is deprecated: short$' go list -m -u -f '{{.Deprecated}}' short stdout '^short$' # When there is a multi-line message, 'go get' should print the first line. -go get -d multiline +go get multiline stderr '^go: module multiline is deprecated: first line$' ! stderr 'second line' go list -m -u -f '{{.Deprecated}}' multiline stdout '^first line\nsecond line.$' # When there is a long message, 'go get' should print a placeholder. -go get -d long +go get long stderr '^go: module long is deprecated: \(message omitted: too long\)$' go list -m -u -f '{{.Deprecated}}' long stdout '^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$' # When a message contains unprintable chracters, 'go get' should say that # without printing the message. -go get -d unprintable +go get unprintable stderr '^go: module unprintable is deprecated: \(message omitted: contains non-printable characters\)$' go list -m -u -f '{{.Deprecated}}' unprintable stdout '^message contains ASCII BEL\x07$' diff --git a/src/cmd/go/testdata/script/mod_domain_root.txt b/src/cmd/go/testdata/script/mod_domain_root.txt index 14745b5812..c13029d534 100644 --- a/src/cmd/go/testdata/script/mod_domain_root.txt +++ b/src/cmd/go/testdata/script/mod_domain_root.txt @@ -2,7 +2,7 @@ # (example.com not example.com/something) env GO111MODULE=on -go get -d +go get -- go.mod -- module x diff --git a/src/cmd/go/testdata/script/mod_download_partial.txt b/src/cmd/go/testdata/script/mod_download_partial.txt index 0aab60ddaf..3a02fcd747 100644 --- a/src/cmd/go/testdata/script/mod_download_partial.txt +++ b/src/cmd/go/testdata/script/mod_download_partial.txt @@ -1,5 +1,5 @@ # Download modules and populate go.sum. -go get -d -modcacherw +go get -modcacherw exists $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/go.mod # 'go mod verify' should fail if we delete a file. diff --git a/src/cmd/go/testdata/script/mod_get_ambiguous_arg.txt b/src/cmd/go/testdata/script/mod_get_ambiguous_arg.txt index daed03b02c..9214993368 100644 --- a/src/cmd/go/testdata/script/mod_get_ambiguous_arg.txt +++ b/src/cmd/go/testdata/script/mod_get_ambiguous_arg.txt @@ -4,14 +4,14 @@ cp go.mod go.mod.orig # If there is no sensible *package* meaning for 'm/p', it should refer # to *module* m/p. -go get -d m/p # @latest +go get m/p # @latest go list -m all stdout '^m/p v0.3.0 ' ! stdout '^m ' cp go.mod.orig go.mod -go get -d m/p@v0.1.0 +go get m/p@v0.1.0 go list -m all stdout '^m/p v0.1.0 ' ! stdout '^m ' @@ -22,7 +22,7 @@ stdout '^m/p v0.1.0 ' # (It only refers to *module* m/p if there is no such package at the # requested version.) -go get -d m/p@v0.2.0 +go get m/p@v0.2.0 go list -m all stdout '^m v0.2.0 ' stdout '^m/p v0.1.0 ' # unchanged from the previous case @@ -30,7 +30,7 @@ stdout '^m/p v0.1.0 ' # unchanged from the previous case # Repeating the above with module m/p already in the module graph does not # change its meaning. -go get -d m/p@v0.2.0 +go get m/p@v0.2.0 go list -m all stdout '^m v0.2.0 ' stdout '^m/p v0.1.0 ' diff --git a/src/cmd/go/testdata/script/mod_get_ambiguous_import.txt b/src/cmd/go/testdata/script/mod_get_ambiguous_import.txt index 33605f51a5..0af78bd4f2 100644 --- a/src/cmd/go/testdata/script/mod_get_ambiguous_import.txt +++ b/src/cmd/go/testdata/script/mod_get_ambiguous_import.txt @@ -8,14 +8,14 @@ cp go.mod go.mod.orig # # TODO(#27899): Should we automatically upgrade example.net/m to v0.2.0 # to resolve the conflict? -! go get -d example.net/m/p@v1.0.0 +! go get example.net/m/p@v1.0.0 stderr '^example.net/m/p: ambiguous import: found package example.net/m/p in multiple modules:\n\texample.net/m v0.1.0 \(.*[/\\]m1[/\\]p\)\n\texample.net/m/p v1.0.0 \(.*[/\\]p0\)\n\z' cmp go.mod go.mod.orig # Upgrading both modules simultaneously resolves the ambiguous upgrade. # Note that this command line mixes a module path (example.net/m) # and a package path (example.net/m/p) in the same command. -go get -d example.net/m@v0.2.0 example.net/m/p@v1.0.0 +go get example.net/m@v0.2.0 example.net/m/p@v1.0.0 go list -m all stdout '^example.net/m v0.2.0 ' diff --git a/src/cmd/go/testdata/script/mod_get_ambiguous_pkg.txt b/src/cmd/go/testdata/script/mod_get_ambiguous_pkg.txt index 0e7f93bccb..1641196007 100644 --- a/src/cmd/go/testdata/script/mod_get_ambiguous_pkg.txt +++ b/src/cmd/go/testdata/script/mod_get_ambiguous_pkg.txt @@ -8,7 +8,7 @@ cp go.mod go.mod.orig # From a clean slate, 'go get' currently does the same thing as 'go mod tidy': # it resolves the package from the module with the longest matching prefix. -go get -d example.net/ambiguous/nested/pkg@v0.1.0 +go get example.net/ambiguous/nested/pkg@v0.1.0 go list -m all stdout '^example.net/ambiguous/nested v0.1.0$' ! stdout '^example.net/ambiguous ' @@ -21,7 +21,7 @@ stdout '^example.net/ambiguous/nested v0.1.0$' cp go.mod.orig go.mod go mod edit -require=example.net/ambiguous@v0.1.0 -go get -d example.net/ambiguous/nested/pkg@v0.1.0 +go get example.net/ambiguous/nested/pkg@v0.1.0 go list -m all stdout '^example.net/ambiguous v0.1.0$' ! stdout '^example.net/ambiguous/nested ' @@ -30,7 +30,7 @@ stdout '^example.net/ambiguous v0.1.0$' # The user should be able to make the command unambiguous by explicitly # upgrading the conflicting module... -go get -d example.net/ambiguous@v0.2.0 example.net/ambiguous/nested/pkg@v0.1.0 +go get example.net/ambiguous@v0.2.0 example.net/ambiguous/nested/pkg@v0.1.0 go list -m all stdout '^example.net/ambiguous/nested v0.1.0$' stdout '^example.net/ambiguous v0.2.0$' @@ -41,7 +41,7 @@ stdout '^example.net/ambiguous v0.2.0$' cp go.mod.orig go.mod go mod edit -require=example.net/ambiguous@v0.1.0 -go get -d example.net/ambiguous/nested/pkg@v0.1.0 example.net/ambiguous/nested@none +go get example.net/ambiguous/nested/pkg@v0.1.0 example.net/ambiguous/nested@none go list -m all ! stdout '^example.net/ambiguous/nested ' stdout '^example.net/ambiguous v0.1.0$' @@ -53,7 +53,7 @@ stdout '^example.net/ambiguous v0.1.0$' cp go.mod.orig go.mod go mod edit -require=example.net/ambiguous@v0.1.0 -go get -d example.net/ambiguous@none example.net/ambiguous/nested/pkg@v0.1.0 +go get example.net/ambiguous@none example.net/ambiguous/nested/pkg@v0.1.0 go list -m all stdout '^example.net/ambiguous/nested v0.1.0$' ! stdout '^example.net/ambiguous ' @@ -66,7 +66,7 @@ stdout '^example.net/ambiguous/nested v0.1.0$' cp go.mod.orig go.mod -go get -d example.net/ambiguous/nested/pkg/...@v0.1.0 +go get example.net/ambiguous/nested/pkg/...@v0.1.0 go list -m all stdout '^example.net/ambiguous/nested v0.1.0$' ! stdout '^example.net/ambiguous ' @@ -75,7 +75,7 @@ stdout '^example.net/ambiguous/nested v0.1.0$' cp go.mod.orig go.mod go mod edit -require=example.net/ambiguous@v0.1.0 -go get -d example.net/ambiguous/nested/pkg/...@v0.1.0 +go get example.net/ambiguous/nested/pkg/...@v0.1.0 go list -m all ! stdout '^example.net/ambiguous/nested ' stdout '^example.net/ambiguous v0.1.0$' diff --git a/src/cmd/go/testdata/script/mod_get_changes.txt b/src/cmd/go/testdata/script/mod_get_changes.txt index 2829111fe5..12a112b4d8 100644 --- a/src/cmd/go/testdata/script/mod_get_changes.txt +++ b/src/cmd/go/testdata/script/mod_get_changes.txt @@ -3,7 +3,7 @@ # for changed indirect dependencies. go list -m all ! stdout golang.org/x/text -go get -d rsc.io/quote@v1.5.2 +go get rsc.io/quote@v1.5.2 stderr '^go: added rsc.io/quote v1.5.2$' stderr '^go: upgraded rsc.io/sampler v1.0.0 => v1.3.0$' ! stderr '^go get.*golang.org/x/text' @@ -14,7 +14,7 @@ cmp go.mod go.mod.upgrade # When removing a requirement, 'go get' prints a message for the requiremnent # and for changed explicit dependencies. 'go get' does not print messages # for changed indirect dependencies. -go get -d rsc.io/sampler@none +go get rsc.io/sampler@none stderr '^go: downgraded rsc.io/quote v1.5.2 => v1.3.0$' stderr '^go: removed rsc.io/sampler v1.3.0$' ! stderr '^go get.*golang.org/x/text' @@ -23,7 +23,7 @@ cmp go.mod go.mod.downgrade # When removing or downgrading a requirement, 'go get' also prints a message # for explicit dependencies removed as a consequence. cp go.mod.usequote go.mod -go get -d rsc.io/quote@v1.5.1 +go get rsc.io/quote@v1.5.1 stderr '^go: downgraded rsc.io/quote v1.5.2 => v1.5.1$' stderr '^go: removed usequote v0.0.0$' diff --git a/src/cmd/go/testdata/script/mod_get_commit.txt b/src/cmd/go/testdata/script/mod_get_commit.txt index ff7185f59a..f60eaab3a7 100644 --- a/src/cmd/go/testdata/script/mod_get_commit.txt +++ b/src/cmd/go/testdata/script/mod_get_commit.txt @@ -5,11 +5,11 @@ env GO111MODULE=on # golang.org/x/text/language@commit should resolve. # Because of -d, the compiler should not run. -go get -d -x golang.org/x/text/language@14c0d48 +go get -x golang.org/x/text/language@14c0d48 ! stderr 'compile|cp|gccgo .*language\.a$' # go get should skip build with no Go files in root -go get -d golang.org/x/text@14c0d48 +go get golang.org/x/text@14c0d48 # dropping -d, we should see a build. [short] skip @@ -33,11 +33,11 @@ go install -x golang.org/x/text/language stderr '^go: module golang.org/x/text@14c0d48 found \(v0.3.0\), but does not contain package golang.org/x/text/foo$' # get pseudo-version should record that version -go get -d rsc.io/quote@v0.0.0-20180214005840-23179ee8a569 +go get rsc.io/quote@v0.0.0-20180214005840-23179ee8a569 grep 'rsc.io/quote v0.0.0-20180214005840-23179ee8a569' go.mod # but as commit should record as v1.5.1 -go get -d rsc.io/quote@23179ee8 +go get rsc.io/quote@23179ee8 grep 'rsc.io/quote v1.5.1' go.mod # go mod edit -require does not interpret commits diff --git a/src/cmd/go/testdata/script/mod_get_deprecated.txt b/src/cmd/go/testdata/script/mod_get_deprecated.txt index 7bdd7a58a8..ec7bcfdb99 100644 --- a/src/cmd/go/testdata/script/mod_get_deprecated.txt +++ b/src/cmd/go/testdata/script/mod_get_deprecated.txt @@ -1,31 +1,31 @@ # 'go get pkg' should not show a deprecation message for an unrelated module. -go get -d ./use/nothing +go get ./use/nothing ! stderr 'module.*is deprecated' # 'go get pkg' should show a deprecation message for the module providing pkg. -go get -d example.com/deprecated/a +go get example.com/deprecated/a stderr '^go: module example.com/deprecated/a is deprecated: in example.com/deprecated/a@v1.9.0$' -go get -d example.com/deprecated/a@v1.0.0 +go get example.com/deprecated/a@v1.0.0 stderr '^go: module example.com/deprecated/a is deprecated: in example.com/deprecated/a@v1.9.0$' # 'go get pkg' should show a deprecation message for a module providing # packages directly imported by pkg. -go get -d ./use/a +go get ./use/a stderr '^go: module example.com/deprecated/a is deprecated: in example.com/deprecated/a@v1.9.0$' # 'go get pkg' may show a deprecation message for an indirectly required module # if it provides a package named on the command line. -go get -d ./use/b +go get ./use/b ! stderr 'module.*is deprecated' -go get -d local/use +go get local/use ! stderr 'module.*is deprecated' -go get -d example.com/deprecated/b +go get example.com/deprecated/b stderr '^go: module example.com/deprecated/b is deprecated: in example.com/deprecated/b@v1.9.0$' # 'go get pkg' does not show a deprecation message for a module providing a # directly imported package if the module is no longer deprecated in its # latest version, even if the module is deprecated in its current version. -go get -d ./use/undeprecated +go get ./use/undeprecated ! stderr 'module.*is deprecated' -- go.mod -- diff --git a/src/cmd/go/testdata/script/mod_get_downadd_indirect.txt b/src/cmd/go/testdata/script/mod_get_downadd_indirect.txt index efc38f77c8..0f5ba992da 100644 --- a/src/cmd/go/testdata/script/mod_get_downadd_indirect.txt +++ b/src/cmd/go/testdata/script/mod_get_downadd_indirect.txt @@ -18,7 +18,7 @@ cp go.mod go.mod.orig go mod tidy cmp go.mod.orig go.mod -go get -d example.com/d@v0.1.0 +go get example.com/d@v0.1.0 go list -m all stdout '^example.com/b v0.1.0 ' stdout '^example.com/c v0.1.0 ' diff --git a/src/cmd/go/testdata/script/mod_get_downgrade.txt b/src/cmd/go/testdata/script/mod_get_downgrade.txt index 685bde7efd..2eed56d9b7 100644 --- a/src/cmd/go/testdata/script/mod_get_downgrade.txt +++ b/src/cmd/go/testdata/script/mod_get_downgrade.txt @@ -3,23 +3,23 @@ env GO111MODULE=on # downgrade sampler should downgrade quote cp go.mod.orig go.mod -go get -d rsc.io/sampler@v1.0.0 +go get rsc.io/sampler@v1.0.0 go list -m all stdout 'rsc.io/quote v1.4.0' stdout 'rsc.io/sampler v1.0.0' # downgrade sampler away should downgrade quote further -go get -d rsc.io/sampler@none +go get rsc.io/sampler@none go list -m all stdout 'rsc.io/quote v1.3.0' # downgrade should report inconsistencies and not change go.mod -go get -d rsc.io/quote@v1.5.1 +go get rsc.io/quote@v1.5.1 go list -m all stdout 'rsc.io/quote v1.5.1' stdout 'rsc.io/sampler v1.3.0' -! go get -d rsc.io/sampler@v1.0.0 rsc.io/quote@v1.5.2 golang.org/x/text@none +! go get rsc.io/sampler@v1.0.0 rsc.io/quote@v1.5.2 golang.org/x/text@none ! stderr add|remove|upgrad|downgrad stderr '^go: rsc.io/quote@v1.5.2 requires rsc.io/sampler@v1.3.0, not rsc.io/sampler@v1.0.0$' @@ -29,7 +29,7 @@ stdout 'rsc.io/sampler v1.3.0' # go get -u args should limit upgrades cp go.mod.empty go.mod -go get -d -u rsc.io/quote@v1.4.0 rsc.io/sampler@v1.0.0 +go get -u rsc.io/quote@v1.4.0 rsc.io/sampler@v1.0.0 go list -m all stdout 'rsc.io/quote v1.4.0' stdout 'rsc.io/sampler v1.0.0' @@ -40,7 +40,7 @@ stdout 'rsc.io/sampler v1.0.0' cp go.mod.orig go.mod go list -m -versions example.com/latemigrate/v2 stdout v2.0.0 # proxy may serve incompatible versions -go get -d rsc.io/quote@none +go get rsc.io/quote@none go list -m all ! stdout 'example.com/latemigrate/v2' diff --git a/src/cmd/go/testdata/script/mod_get_downgrade_missing.txt b/src/cmd/go/testdata/script/mod_get_downgrade_missing.txt index 2068cae755..582593b96c 100644 --- a/src/cmd/go/testdata/script/mod_get_downgrade_missing.txt +++ b/src/cmd/go/testdata/script/mod_get_downgrade_missing.txt @@ -4,7 +4,7 @@ cp go.mod go.mod.orig # not yet present in that module should report the version mismatch # rather than a "matched no packages" warning. -! go get -d example.net/pkgadded@v1.1.0 example.net/pkgadded/subpkg/... +! go get example.net/pkgadded@v1.1.0 example.net/pkgadded/subpkg/... stderr '^go: example.net/pkgadded@v1.1.0 conflicts with example.net/pkgadded/subpkg/...@upgrade \(v1.2.0\)$' ! stderr 'matched no packages' cmp go.mod.orig go.mod @@ -12,7 +12,7 @@ cmp go.mod.orig go.mod # A wildcard pattern should match the pattern with that path. -go get -d example.net/pkgadded/...@v1.0.0 +go get example.net/pkgadded/...@v1.0.0 go list -m all stdout '^example.net/pkgadded v1.0.0' cp go.mod.orig go.mod @@ -22,12 +22,12 @@ cp go.mod.orig go.mod # and another argument constrains away the version that provides that # package, then 'go get' should fail with a useful error message. -! go get -d example.net/pkgadded@v1.0.0 . +! go get example.net/pkgadded@v1.0.0 . stderr '^example.com/m imports\n\texample.net/pkgadded/subpkg: cannot find module providing package example.net/pkgadded/subpkg$' ! stderr 'example.net/pkgadded v1\.2\.0' cmp go.mod.orig go.mod -go get -d example.net/pkgadded@v1.0.0 +go get example.net/pkgadded@v1.0.0 ! go list -deps -mod=readonly . stderr '^m.go:3:8: cannot find module providing package example\.net/pkgadded/subpkg: ' diff --git a/src/cmd/go/testdata/script/mod_get_downup_artifact.txt b/src/cmd/go/testdata/script/mod_get_downup_artifact.txt index c20583b22a..111a54f8f7 100644 --- a/src/cmd/go/testdata/script/mod_get_downup_artifact.txt +++ b/src/cmd/go/testdata/script/mod_get_downup_artifact.txt @@ -55,7 +55,7 @@ stdout '^example.com/d v0.1.0 ' # upgrades of module d and addition of module e, which are not relevant to # b@v0.1.0 and should not be added to the main module's dependencies. -go get -u -d example.com/a@latest example.com/c@v0.1.0 +go get -u example.com/a@latest example.com/c@v0.1.0 go list -m all stdout '^example.com/a v0.1.0 ' diff --git a/src/cmd/go/testdata/script/mod_get_downup_indirect.txt b/src/cmd/go/testdata/script/mod_get_downup_indirect.txt index ced1dcd6b1..3a46a774ce 100644 --- a/src/cmd/go/testdata/script/mod_get_downup_indirect.txt +++ b/src/cmd/go/testdata/script/mod_get_downup_indirect.txt @@ -25,7 +25,7 @@ cp go.mod go.mod.orig go mod tidy cmp go.mod.orig go.mod -go get -d example.com/d@v0.1.0 +go get example.com/d@v0.1.0 go list -m all ! stdout '^example.com/b ' ! stdout '^example.com/c ' diff --git a/src/cmd/go/testdata/script/mod_get_downup_pseudo_artifact.txt b/src/cmd/go/testdata/script/mod_get_downup_pseudo_artifact.txt index c49615cecb..b678a177b5 100644 --- a/src/cmd/go/testdata/script/mod_get_downup_pseudo_artifact.txt +++ b/src/cmd/go/testdata/script/mod_get_downup_pseudo_artifact.txt @@ -28,7 +28,7 @@ cmp go.mod.orig go.mod # When we downgrade d.2 to d.1, no dependency on e should be added # because nothing else in the module or import graph requires it. -go get -d example.net/d@v0.1.0 +go get example.net/d@v0.1.0 go list -m all stdout '^example.net/b v0.2.1-0.20210219000000-000000000000 ' diff --git a/src/cmd/go/testdata/script/mod_get_extra.txt b/src/cmd/go/testdata/script/mod_get_extra.txt index 7efa24e87b..083e03678e 100644 --- a/src/cmd/go/testdata/script/mod_get_extra.txt +++ b/src/cmd/go/testdata/script/mod_get_extra.txt @@ -4,7 +4,7 @@ cp go.mod go.mod.orig # determined by explicit queries to any version other than the explicit one. # Otherwise, 'go get -u' could introduce spurious dependencies. -go get -d -u example.net/a@v0.1.0 example.net/b@v0.1.0 +go get -u example.net/a@v0.1.0 example.net/b@v0.1.0 go list -m all stdout '^example.net/a v0.1.0 ' stdout '^example.net/b v0.1.0 ' @@ -16,7 +16,7 @@ stdout '^example.net/b v0.1.0 ' cp go.mod.orig go.mod -go get -d -u example.net/a@v0.1.0 example.net/b/...@v0.1.0 +go get -u example.net/a@v0.1.0 example.net/b/...@v0.1.0 go list -m all stdout '^example.net/a v0.1.0 ' stdout '^example.net/b v0.1.0 ' diff --git a/src/cmd/go/testdata/script/mod_get_fallback.txt b/src/cmd/go/testdata/script/mod_get_fallback.txt index a61d5cb00e..35722333d6 100644 --- a/src/cmd/go/testdata/script/mod_get_fallback.txt +++ b/src/cmd/go/testdata/script/mod_get_fallback.txt @@ -5,7 +5,7 @@ env GO111MODULE=on env GOPROXY=https://proxy.golang.org,direct env GOSUMDB=off -go get -x -v -d golang.org/x/tools/cmd/goimports +go get -x -v golang.org/x/tools/cmd/goimports stderr '# get https://proxy.golang.org/golang.org/x/tools/@v/list' ! stderr '# get https://golang.org' diff --git a/src/cmd/go/testdata/script/mod_get_incompatible.txt b/src/cmd/go/testdata/script/mod_get_incompatible.txt index 8000ee6148..5a7d706371 100644 --- a/src/cmd/go/testdata/script/mod_get_incompatible.txt +++ b/src/cmd/go/testdata/script/mod_get_incompatible.txt @@ -1,15 +1,15 @@ env GO111MODULE=on -go get -d x +go get x go list -m all stdout 'rsc.io/breaker v2.0.0\+incompatible' cp go.mod2 go.mod -go get -d rsc.io/breaker@7307b30 +go get rsc.io/breaker@7307b30 go list -m all stdout 'rsc.io/breaker v2.0.0\+incompatible' -go get -d rsc.io/breaker@v2.0.0 +go get rsc.io/breaker@v2.0.0 go list -m all stdout 'rsc.io/breaker v2.0.0\+incompatible' diff --git a/src/cmd/go/testdata/script/mod_get_indirect.txt b/src/cmd/go/testdata/script/mod_get_indirect.txt index e1cc1ab411..fa7edf22d7 100644 --- a/src/cmd/go/testdata/script/mod_get_indirect.txt +++ b/src/cmd/go/testdata/script/mod_get_indirect.txt @@ -27,7 +27,7 @@ grep 'golang.org/x/text v0.3.0 // indirect$' go.mod # indirect tag should be removed upon seeing direct import. cp $WORK/tmp/uselang.go x.go -go get -d +go get grep 'rsc.io/quote v1.5.2$' go.mod grep 'golang.org/x/text [v0-9a-f\.-]+$' go.mod diff --git a/src/cmd/go/testdata/script/mod_get_issue37438.txt b/src/cmd/go/testdata/script/mod_get_issue37438.txt index 38b2031d3a..9392e73a17 100644 --- a/src/cmd/go/testdata/script/mod_get_issue37438.txt +++ b/src/cmd/go/testdata/script/mod_get_issue37438.txt @@ -6,7 +6,7 @@ # 'go get foo@requested' should resolve the requested version, # not error out on the (unrelated) latest one. -go get -d example.net/a/p@v0.2.0 +go get example.net/a/p@v0.2.0 -- go.mod -- module example diff --git a/src/cmd/go/testdata/script/mod_get_issue47979.txt b/src/cmd/go/testdata/script/mod_get_issue47979.txt index f5d4304ab2..848ee3aa09 100644 --- a/src/cmd/go/testdata/script/mod_get_issue47979.txt +++ b/src/cmd/go/testdata/script/mod_get_issue47979.txt @@ -10,7 +10,7 @@ cp go.mod go.mod.orig # 'go get -u' from performing upgrades. cp go.mod.orig go.mod -go get -u -d . +go get -u . cmp go.mod go.mod.want @@ -21,7 +21,7 @@ cmp go.mod go.mod.want # (in this case, example.net/indirect). cp go.mod.orig go.mod -go get -d example.net/a@v0.2.0 +go get example.net/a@v0.2.0 cmp go.mod go.mod.want diff --git a/src/cmd/go/testdata/script/mod_get_latest_pseudo.txt b/src/cmd/go/testdata/script/mod_get_latest_pseudo.txt index 241a0c2f0d..00da0c3164 100644 --- a/src/cmd/go/testdata/script/mod_get_latest_pseudo.txt +++ b/src/cmd/go/testdata/script/mod_get_latest_pseudo.txt @@ -5,6 +5,6 @@ env GO111MODULE=on go mod init m -go get -d example.com/notags +go get example.com/notags go list -m all stdout '^example.com/notags v0.0.0-20190507143103-cc8cbe209b64$' diff --git a/src/cmd/go/testdata/script/mod_get_local.txt b/src/cmd/go/testdata/script/mod_get_local.txt index eb09da58b3..4c81d16a1f 100644 --- a/src/cmd/go/testdata/script/mod_get_local.txt +++ b/src/cmd/go/testdata/script/mod_get_local.txt @@ -7,7 +7,7 @@ cp go.mod go.mod.orig # 'go get -u' within the main module should work, even if it has a local-only name. cp go.mod.orig go.mod -go get -d -u ./... +go get -u ./... grep 'rsc.io/quote.*v1.5.2' go.mod grep 'golang.org/x/text.*v0.3.0' go.mod cp go.mod go.mod.implicitmod @@ -15,34 +15,34 @@ cp go.mod go.mod.implicitmod # 'go get -u local/...' should be equivalent to 'go get -u ./...' # (assuming no nested modules) cp go.mod.orig go.mod -go get -d -u local/... +go get -u local/... cmp go.mod go.mod.implicitmod # For the main module, @patch should be a no-op. cp go.mod.orig go.mod -go get -d -u local/...@patch +go get -u local/...@patch cmp go.mod go.mod.implicitmod -# 'go get -u -d' in the empty root of the main module should fail. -# 'go get -u -d .' should also fail. +# 'go get -u' in the empty root of the main module should fail. +# 'go get -u .' should also fail. cp go.mod.orig go.mod -! go get -u -d -! go get -u -d . +! go get -u +! go get -u . -# 'go get -u -d .' within a package in the main module updates the dependencies +# 'go get -u .' within a package in the main module updates the dependencies # of that package. cp go.mod.orig go.mod cd uselang -go get -u -d . +go get -u . cd .. grep 'rsc.io/quote.*v1.3.0' go.mod grep 'golang.org/x/text.*v0.3.0' go.mod cp go.mod go.mod.dotpkg -# 'go get -u -d' with an explicit package in the main module updates the +# 'go get -u' with an explicit package in the main module updates the # dependencies of that package. cp go.mod.orig go.mod -go get -u -d local/uselang +go get -u local/uselang cmp go.mod go.mod.dotpkg -- go.mod -- diff --git a/src/cmd/go/testdata/script/mod_get_main.txt b/src/cmd/go/testdata/script/mod_get_main.txt index 5c9b762543..cddd5f7082 100644 --- a/src/cmd/go/testdata/script/mod_get_main.txt +++ b/src/cmd/go/testdata/script/mod_get_main.txt @@ -2,43 +2,43 @@ env GO111MODULE=on cp go.mod.orig go.mod # relative and absolute paths must be within the main module. -! go get -d .. +! go get .. stderr '^go: \.\. \('$WORK'[/\\]gopath\) is not within module rooted at '$WORK'[/\\]gopath[/\\]src$' -! go get -d $WORK +! go get $WORK stderr '^go: '$WORK' is not within module rooted at '$WORK'[/\\]gopath[/\\]src$' -! go get -d ../... +! go get ../... stderr '^go: \.\./\.\.\. \('$WORK'[/\\]gopath([/\\]...)?\) is not within module rooted at '$WORK'[/\\]gopath[/\\]src$' -! go get -d $WORK/... +! go get $WORK/... stderr '^go: '$WORK'[/\\]\.\.\. is not within module rooted at '$WORK'[/\\]gopath[/\\]src$' # @patch and @latest within the main module refer to the current version. # The main module won't be upgraded, but missing dependencies will be added. -go get -d rsc.io/x +go get rsc.io/x grep 'rsc.io/quote v1.5.2' go.mod -go get -d rsc.io/x@upgrade +go get rsc.io/x@upgrade grep 'rsc.io/quote v1.5.2' go.mod cp go.mod.orig go.mod -go get -d rsc.io/x@patch +go get rsc.io/x@patch grep 'rsc.io/quote v1.5.2' go.mod cp go.mod.orig go.mod # Upgrading a package pattern not contained in the main module should not # attempt to upgrade the main module. -go get -d rsc.io/quote/...@v1.5.1 +go get rsc.io/quote/...@v1.5.1 grep 'rsc.io/quote v1.5.1' go.mod # The main module cannot be updated to a specific version. -! go get -d rsc.io@v0.1.0 +! go get rsc.io@v0.1.0 stderr '^go: can''t request version "v0.1.0" of the main module \(rsc.io\)$' # A package in the main module can't be upgraded either. -! go get -d rsc.io/x@v0.1.0 +! go get rsc.io/x@v0.1.0 stderr '^go: package rsc.io/x is in the main module, so can''t request version v0.1.0$' # Nor can a pattern matching packages in the main module. -! go get -d rsc.io/x/...@latest +! go get rsc.io/x/...@latest stderr '^go: pattern rsc.io/x/... matches package rsc.io/x in the main module, so can''t request version latest$' -- go.mod.orig -- diff --git a/src/cmd/go/testdata/script/mod_get_major.txt b/src/cmd/go/testdata/script/mod_get_major.txt index 367ede9ded..2db13180bd 100644 --- a/src/cmd/go/testdata/script/mod_get_major.txt +++ b/src/cmd/go/testdata/script/mod_get_major.txt @@ -8,12 +8,12 @@ env GOSUMDB=off # golang.org/issue/34383: if a module path ends in a major-version suffix, # ensure that 'direct' mode can resolve the package to a module. -go get -d vcs-test.golang.org/git/v3pkg.git/v3@v3.0.0 +go get vcs-test.golang.org/git/v3pkg.git/v3@v3.0.0 go list -m vcs-test.golang.org/git/v3pkg.git/v3 stdout '^vcs-test.golang.org/git/v3pkg.git/v3 v3.0.0$' -go get -d vcs-test.golang.org/git/empty-v2-without-v1.git/v2@v2.0.0 +go get vcs-test.golang.org/git/empty-v2-without-v1.git/v2@v2.0.0 go list -m vcs-test.golang.org/git/empty-v2-without-v1.git/v2 stdout '^vcs-test.golang.org/git/empty-v2-without-v1.git/v2 v2.0.0$' diff --git a/src/cmd/go/testdata/script/mod_get_missing_ziphash.txt b/src/cmd/go/testdata/script/mod_get_missing_ziphash.txt index 789d42d24d..5934251e4b 100644 --- a/src/cmd/go/testdata/script/mod_get_missing_ziphash.txt +++ b/src/cmd/go/testdata/script/mod_get_missing_ziphash.txt @@ -13,7 +13,7 @@ env GOSUMDB=off cp go.sum.bug go.sum ! go build -n use stderr '^use.go:3:8: missing go.sum entry for module providing package rsc.io/quote \(imported by use\); to add:\n\tgo get use$' -go get -d use +go get use cmp go.sum go.sum.tidy go build -n use @@ -22,7 +22,7 @@ cp go.sum.bug go.sum rm $WORK/gopath/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.ziphash ! go build -n use stderr '^use.go:3:8: missing go.sum entry for module providing package rsc.io/quote \(imported by use\); to add:\n\tgo get use$' -go get -d use +go get use cmp go.sum go.sum.tidy go build -n use diff --git a/src/cmd/go/testdata/script/mod_get_moved.txt b/src/cmd/go/testdata/script/mod_get_moved.txt index 8430a737c4..ba79c8263c 100644 --- a/src/cmd/go/testdata/script/mod_get_moved.txt +++ b/src/cmd/go/testdata/script/mod_get_moved.txt @@ -4,17 +4,17 @@ env GO111MODULE=on # A 'go get' that worked at a previous version should continue to work at that version, # even if the package was subsequently moved into a submodule. go mod init example.com/foo -go get -d example.com/split/subpkg@v1.0.0 +go get example.com/split/subpkg@v1.0.0 go list -m all stdout 'example.com/split v1.0.0' # A 'go get' that simultaneously upgrades away conflicting package defitions is not ambiguous. -go get -d example.com/split/subpkg@v1.1.0 +go get example.com/split/subpkg@v1.1.0 # A 'go get' without an upgrade should find the package. rm go.mod go mod init example.com/foo -go get -d example.com/split/subpkg +go get example.com/split/subpkg go list -m all stdout 'example.com/split/subpkg v1.1.0' @@ -23,18 +23,18 @@ stdout 'example.com/split/subpkg v1.1.0' # even if the package was subsequently moved into a parent module. rm go.mod go mod init example.com/foo -go get -d example.com/join/subpkg@v1.0.0 +go get example.com/join/subpkg@v1.0.0 go list -m all stdout 'example.com/join/subpkg v1.0.0' # A 'go get' that simultaneously upgrades away conflicting package definitions is not ambiguous. # (A wildcard pattern applies to both packages and modules, # because we define wildcard matching to apply after version resolution.) -go get -d example.com/join/subpkg/...@v1.1.0 +go get example.com/join/subpkg/...@v1.1.0 # A 'go get' without an upgrade should find the package. rm go.mod go mod init example.com/foo -go get -d example.com/join/subpkg@v1.1.0 +go get example.com/join/subpkg@v1.1.0 go list -m all stdout 'example.com/join v1.1.0' diff --git a/src/cmd/go/testdata/script/mod_get_none.txt b/src/cmd/go/testdata/script/mod_get_none.txt index b358f05af3..5aec209f59 100644 --- a/src/cmd/go/testdata/script/mod_get_none.txt +++ b/src/cmd/go/testdata/script/mod_get_none.txt @@ -3,10 +3,10 @@ env GO111MODULE=on go mod init example.com/foo # 'go get bar@none' should be a no-op if module bar is not active. -go get -d example.com/bar@none +go get example.com/bar@none go list -m all ! stdout example.com/bar -go get -d example.com/bar@none +go get example.com/bar@none go list -m all ! stdout example.com/bar diff --git a/src/cmd/go/testdata/script/mod_get_nopkgs.txt b/src/cmd/go/testdata/script/mod_get_nopkgs.txt index 2711f93498..14176a7dc8 100644 --- a/src/cmd/go/testdata/script/mod_get_nopkgs.txt +++ b/src/cmd/go/testdata/script/mod_get_nopkgs.txt @@ -6,15 +6,15 @@ cd subdir go get ./... stderr -count=1 'matched no packages' -go get -d ./... +go get ./... stderr -count=1 'matched no packages' # 'go get' on patterns that could conceivably match nested modules # should report a module resolution error. -go get -d example.net/emptysubdir/... # control case +go get example.net/emptysubdir/... # control case -! go get -d example.net/emptysubdir/subdir/... +! go get example.net/emptysubdir/subdir/... ! stderr 'matched no packages' stderr '^go: example\.net/emptysubdir/subdir/\.\.\.: module example\.net/emptysubdir/subdir: reading http://.*: 404 Not Found\n\tserver response: 404 page not found\n\z' @@ -26,7 +26,7 @@ stderr '^go: example\.net/emptysubdir/subdir/\.\.\.: module example\.net/emptysu # For that case, we emit a "malformed module path" error message, # which isn't ideal either. -! go get -d builtin/... # in GOROOT/src, but contains no packages +! go get builtin/... # in GOROOT/src, but contains no packages stderr '^go: builtin/...: malformed module path "builtin": missing dot in first path element$' -- go.mod -- diff --git a/src/cmd/go/testdata/script/mod_get_patch.txt b/src/cmd/go/testdata/script/mod_get_patch.txt index 5957a360b0..35cc276c5c 100644 --- a/src/cmd/go/testdata/script/mod_get_patch.txt +++ b/src/cmd/go/testdata/script/mod_get_patch.txt @@ -7,7 +7,7 @@ cp go.mod go.mod.orig # example.net/b@patch refers to the patch for the version of b that was selected # at the start of 'go get', not the version after applying other changes. -! go get -d example.net/a@v0.2.0 example.net/b@patch +! go get example.net/a@v0.2.0 example.net/b@patch stderr '^go: example.net/a@v0.2.0 requires example.net/b@v0.2.0, not example.net/b@patch \(v0.1.1\)$' cmp go.mod go.mod.orig @@ -18,7 +18,7 @@ cmp go.mod go.mod.orig # # TODO(#42360): Reconsider the change in defaults. -! go get -d -u=patch example.net/a@v0.2.0 example.net/b +! go get -u=patch example.net/a@v0.2.0 example.net/b stderr '^go: example.net/a@v0.2.0 requires example.net/b@v0.2.0, not example.net/b@patch \(v0.1.1\)$' cmp go.mod go.mod.orig @@ -27,7 +27,7 @@ cmp go.mod go.mod.orig # applying other version changes, not the versions that were selected at the start. # However, it should not patch versions determined by explicit arguments. -go get -d -u=patch example.net/a@v0.2.0 +go get -u=patch example.net/a@v0.2.0 go list -m all stdout '^example.net/a v0.2.0 ' stdout '^example.net/b v0.2.1 ' diff --git a/src/cmd/go/testdata/script/mod_get_patchbound.txt b/src/cmd/go/testdata/script/mod_get_patchbound.txt index 4fd1ec53e1..e4d3c491f4 100644 --- a/src/cmd/go/testdata/script/mod_get_patchbound.txt +++ b/src/cmd/go/testdata/script/mod_get_patchbound.txt @@ -5,7 +5,7 @@ go list -m all stdout '^example.net/a v0.1.0 ' stdout '^example.net/b v0.1.0 ' -go get -d -u=patch example.net/a@v0.2.0 +go get -u=patch example.net/a@v0.2.0 go list -m all stdout '^example.net/a v0.2.0 ' stdout '^example.net/b v0.1.1 ' # not v0.1.2, which requires …/a v0.3.0. diff --git a/src/cmd/go/testdata/script/mod_get_patchmod.txt b/src/cmd/go/testdata/script/mod_get_patchmod.txt index bc1859edc2..28277310aa 100644 --- a/src/cmd/go/testdata/script/mod_get_patchmod.txt +++ b/src/cmd/go/testdata/script/mod_get_patchmod.txt @@ -1,5 +1,5 @@ # example.net/pkgremoved@v0.1.0 refers to a package. -go get -d example.net/pkgremoved@v0.1.0 +go get example.net/pkgremoved@v0.1.0 go list example.net/pkgremoved stdout '^example.net/pkgremoved' @@ -15,7 +15,7 @@ cp go.mod go.mod.orig # be constrained to the latest patch of its originally-selected version (v0.1.0), # not upgraded to the latest patch of the new transitive dependency. -! go get -d example.net/pkgremoved@patch example.net/other@v0.1.0 +! go get example.net/pkgremoved@patch example.net/other@v0.1.0 stderr '^go: example.net/other@v0.1.0 requires example.net/pkgremoved@v0.2.0, not example.net/pkgremoved@patch \(v0.1.1\)$' cmp go.mod.orig go.mod @@ -24,19 +24,19 @@ cmp go.mod.orig go.mod # Package to module ... -go get -d example.net/pkgremoved@v0.3.0 +go get example.net/pkgremoved@v0.3.0 go list example.net/pkgremoved stdout 'example.net/pkgremoved' -go get -d example.net/pkgremoved@patch +go get example.net/pkgremoved@patch ! go list example.net/pkgremoved # ... and module to package. -go get -d example.net/pkgremoved@v0.4.0 +go get example.net/pkgremoved@v0.4.0 ! go list example.net/pkgremoved -go get -d example.net/pkgremoved@patch +go get example.net/pkgremoved@patch go list example.net/pkgremoved stdout 'example.net/pkgremoved' diff --git a/src/cmd/go/testdata/script/mod_get_patterns.txt b/src/cmd/go/testdata/script/mod_get_patterns.txt index 3b5ab43339..891353fd4b 100644 --- a/src/cmd/go/testdata/script/mod_get_patterns.txt +++ b/src/cmd/go/testdata/script/mod_get_patterns.txt @@ -5,15 +5,15 @@ env GO111MODULE=on # in the build list, we assume the pattern matches a single module # whose path is a prefix of the part of the pattern before "...". cp go.mod.orig go.mod -go get -d rsc.io/quote/... +go get rsc.io/quote/... grep 'require rsc.io/quote' go.mod cp go.mod.orig go.mod -! go get -d rsc.io/quote/x... +! go get rsc.io/quote/x... stderr 'go: module rsc.io/quote@upgrade found \(v1.5.2\), but does not contain packages matching rsc.io/quote/x...' ! grep 'require rsc.io/quote' go.mod -! go get -d rsc.io/quote/x/... +! go get rsc.io/quote/x/... stderr 'go: module rsc.io/quote@upgrade found \(v1.5.2\), but does not contain packages matching rsc.io/quote/x/...' ! grep 'require rsc.io/quote' go.mod @@ -21,13 +21,13 @@ stderr 'go: module rsc.io/quote@upgrade found \(v1.5.2\), but does not contain p # be upgraded, even if the module path is a prefix of the pattern. cp go.mod.orig go.mod go mod edit -require example.com/nest@v1.0.0 -go get -d example.com/nest/sub/y... +go get example.com/nest/sub/y... grep 'example.com/nest/sub v1.0.0' go.mod grep 'example.com/nest v1.0.0' go.mod # However, if the pattern matches the module path itself, the module # should be upgraded even if it contains no matching packages. -go get -d example.com/n...t +go get example.com/n...t grep 'example.com/nest v1.1.0' go.mod grep 'example.com/nest/sub v1.0.0' go.mod diff --git a/src/cmd/go/testdata/script/mod_get_pkgtags.txt b/src/cmd/go/testdata/script/mod_get_pkgtags.txt index 2e2ab72032..7ad3c3c7c4 100644 --- a/src/cmd/go/testdata/script/mod_get_pkgtags.txt +++ b/src/cmd/go/testdata/script/mod_get_pkgtags.txt @@ -12,10 +12,10 @@ stderr '^module example\.net/cmd provides package example\.net/cmd/tool and is r go mod edit -droprequire example.net/tools -# 'go get -d' makes a best effort to fetch those dependencies, but shouldn't +# 'go get' makes a best effort to fetch those dependencies, but shouldn't # error out if dependencies of tag-guarded files are missing. -go get -d example.net/tools@v0.1.0 +go get example.net/tools@v0.1.0 ! stderr 'no Go source files' ! go list example.net/tools @@ -48,26 +48,26 @@ stderr '^package example.net/tools: build constraints exclude all Go files in .* # 'go get' should fetch modules whose roots contain test-only packages, but # without the -t flag shouldn't error out if the test has missing dependencies. -go get -d example.net/testonly@v0.1.0 +go get example.net/testonly@v0.1.0 # With the -t flag, the test dependencies must resolve successfully. -! go get -d -t example.net/testonly@v0.1.0 +! go get -t example.net/testonly@v0.1.0 stderr '^example.net/testonly tested by\n\texample.net/testonly\.test imports\n\texample.net/missing: cannot find module providing package example.net/missing$' -# 'go get -d' should succeed for a module path that does not contain a package, +# 'go get' should succeed for a module path that does not contain a package, # but fail for a non-package subdirectory of a module. -! go get -d example.net/missing/subdir@v0.1.0 +! go get example.net/missing/subdir@v0.1.0 stderr '^go: module example.net/missing@v0.1.0 found \(replaced by ./missing\), but does not contain package example.net/missing/subdir$' -go get -d example.net/missing@v0.1.0 +go get example.net/missing@v0.1.0 # Getting the subdirectory should continue to fail even if the corresponding # module is already present in the build list. -! go get -d example.net/missing/subdir@v0.1.0 +! go get example.net/missing/subdir@v0.1.0 stderr '^go: module example.net/missing@v0.1.0 found \(replaced by ./missing\), but does not contain package example.net/missing/subdir$' diff --git a/src/cmd/go/testdata/script/mod_get_prefer_incompatible.txt b/src/cmd/go/testdata/script/mod_get_prefer_incompatible.txt index be3db42d1d..06e2fc6860 100644 --- a/src/cmd/go/testdata/script/mod_get_prefer_incompatible.txt +++ b/src/cmd/go/testdata/script/mod_get_prefer_incompatible.txt @@ -8,7 +8,7 @@ cmp go.mod.orig go.mod grep '^example.com/incompatiblewithsub v2\.0\.0\+incompatible' go.sum ! grep '^example.com/incompatiblewithsub v1.0.0' go.sum -go get -d example.com/incompatiblewithsub/sub +go get example.com/incompatiblewithsub/sub cmp go.mod.orig go.mod ! grep '^example.com/incompatiblewithsub v1.0.0' go.sum diff --git a/src/cmd/go/testdata/script/mod_get_promote_implicit.txt b/src/cmd/go/testdata/script/mod_get_promote_implicit.txt index 9eec201321..03f6810e35 100644 --- a/src/cmd/go/testdata/script/mod_get_promote_implicit.txt +++ b/src/cmd/go/testdata/script/mod_get_promote_implicit.txt @@ -12,7 +12,7 @@ stderr '^package m/use-indirect imports indirect-with-pkg from implicitly requir # NOTE: the hint recommends getting the imported package (tested below) since # it's more obvious and doesn't require -d. However, that adds an '// indirect' # comment on the requirement. -go get -d m/use-indirect +go get m/use-indirect cmp go.mod go.mod.use cp go.mod.orig go.mod @@ -21,7 +21,7 @@ cp go.mod.orig go.mod # know they're needed by the main module. See #43131 for the rationale. # The hint above recommends this because it's more obvious usage and doesn't # require the -d flag. -go get -d indirect-with-pkg indirect-without-pkg +go get indirect-with-pkg indirect-without-pkg cmp go.mod go.mod.indirect -- go.mod.orig -- diff --git a/src/cmd/go/testdata/script/mod_get_pseudo.txt b/src/cmd/go/testdata/script/mod_get_pseudo.txt index 582837a166..b964ae4484 100644 --- a/src/cmd/go/testdata/script/mod_get_pseudo.txt +++ b/src/cmd/go/testdata/script/mod_get_pseudo.txt @@ -9,69 +9,69 @@ env GOSUMDB=off # We can resolve the @master branch without unshallowing the local repository # (even with older gits), so try that before we do anything else. # (This replicates https://golang.org/issue/26713 with git 2.7.4.) -go get -d github.com/rsc/legacytest@master +go get github.com/rsc/legacytest@master go list -m all stdout '^github.com/rsc/legacytest v2\.0\.1-0\.\d{14}-7303f7796364\+incompatible$' # get should include incompatible tags in "latest" calculation. go mod edit -droprequire github.com/rsc/legacytest -go get -d github.com/rsc/legacytest@latest +go get github.com/rsc/legacytest@latest go list go list -m all stdout '^github.com/rsc/legacytest v2\.0\.0\+incompatible$' # v2.0.1-0.pseudo+incompatible -go get -d ...test@7303f77 +go get ...test@7303f77 go list -m all stdout '^github.com/rsc/legacytest v2\.0\.1-0\.\d{14}-7303f7796364\+incompatible$' # v2.0.0+incompatible by tag+incompatible -go get -d ...test@v2.0.0+incompatible +go get ...test@v2.0.0+incompatible go list -m all stdout '^github.com/rsc/legacytest v2\.0\.0\+incompatible$' # v2.0.0+incompatible by tag -go get -d ...test@v2.0.0 +go get ...test@v2.0.0 go list -m all stdout '^github.com/rsc/legacytest v2\.0\.0\+incompatible$' # v2.0.0+incompatible by hash (back on master) -go get -d ...test@d7ae1e4 +go get ...test@d7ae1e4 go list -m all stdout '^github.com/rsc/legacytest v2\.0\.0\+incompatible$' # v1.2.1-0.pseudo -go get -d ...test@d2d4c3e +go get ...test@d2d4c3e go list -m all stdout '^github.com/rsc/legacytest v1\.2\.1-0\.\d{14}-d2d4c3ea6623$' # v1.2.0 -go get -d ...test@9f6f860 +go get ...test@9f6f860 go list -m all stdout '^github.com/rsc/legacytest v1\.2\.0$' # v1.1.0-pre.0.pseudo -go get -d ...test@fb3c628 +go get ...test@fb3c628 go list -m all stdout '^github.com/rsc/legacytest v1\.1\.0-pre\.0\.\d{14}-fb3c628075e3$' # v1.1.0-pre (no longer on master) -go get -d ...test@731e3b1 +go get ...test@731e3b1 go list -m all stdout '^github.com/rsc/legacytest v1\.1\.0-pre$' # v1.0.1-0.pseudo -go get -d ...test@fa4f5d6 +go get ...test@fa4f5d6 go list -m all stdout '^github.com/rsc/legacytest v1\.0\.1-0\.\d{14}-fa4f5d6a71c6$' # v1.0.0 -go get -d ...test@7fff7f3 +go get ...test@7fff7f3 go list -m all stdout '^github.com/rsc/legacytest v1\.0\.0$' # v0.0.0-pseudo -go get -d ...test@52853eb +go get ...test@52853eb go list -m all stdout '^github.com/rsc/legacytest v0\.0\.0-\d{14}-52853eb7b552$' diff --git a/src/cmd/go/testdata/script/mod_get_pseudo_other_branch.txt b/src/cmd/go/testdata/script/mod_get_pseudo_other_branch.txt index 0fbd041f86..d085f4fa3c 100644 --- a/src/cmd/go/testdata/script/mod_get_pseudo_other_branch.txt +++ b/src/cmd/go/testdata/script/mod_get_pseudo_other_branch.txt @@ -17,7 +17,7 @@ env GOSUMDB=off # The pseudo-version hence sorts immediately after v0.2.2 rather # than v0.2.1, even though the v0.2.2 tag is not on master. -go get -d vcs-test.golang.org/git/tagtests.git@master +go get vcs-test.golang.org/git/tagtests.git@master go list -m all stdout '^vcs-test.golang.org/git/tagtests.git v0.2.3-0\.' diff --git a/src/cmd/go/testdata/script/mod_get_pseudo_prefix.txt b/src/cmd/go/testdata/script/mod_get_pseudo_prefix.txt index b78e6e644f..8e6cd907f1 100644 --- a/src/cmd/go/testdata/script/mod_get_pseudo_prefix.txt +++ b/src/cmd/go/testdata/script/mod_get_pseudo_prefix.txt @@ -16,11 +16,11 @@ env GOSUMDB=off # # The pseudo-version is based on sub/v0.0.10, since v0.2.0 doesn't # contain the prefix. -go get -d vcs-test.golang.org/git/prefixtagtests.git/sub +go get vcs-test.golang.org/git/prefixtagtests.git/sub go list -m all stdout '^vcs-test.golang.org/git/prefixtagtests.git/sub v0.0.10$' -go get -d -u vcs-test.golang.org/git/prefixtagtests.git/sub@master +go get -u vcs-test.golang.org/git/prefixtagtests.git/sub@master go list -m all stdout '^vcs-test.golang.org/git/prefixtagtests.git/sub v0.0.11-0\.' diff --git a/src/cmd/go/testdata/script/mod_get_replaced.txt b/src/cmd/go/testdata/script/mod_get_replaced.txt index ab21bd57fa..b1fc8b8056 100644 --- a/src/cmd/go/testdata/script/mod_get_replaced.txt +++ b/src/cmd/go/testdata/script/mod_get_replaced.txt @@ -6,7 +6,7 @@ env oldGOPROXY=$GOPROXY # 'go get' should resolve it to the minimum valid pseudo-version. go mod edit -replace=example.com/x=./x -go get -d example.com/x +go get example.com/x go list -m example.com/x stdout '^example.com/x v0.0.0-00010101000000-000000000000 ' @@ -15,11 +15,11 @@ stdout '^example.com/x v0.0.0-00010101000000-000000000000 ' go mod edit -replace=example.com/x@v0.1.0=./x go mod edit -replace=example.com/x@v0.2.0=./x -go get -d example.com/x +go get example.com/x go list -m example.com/x stdout '^example.com/x v0.2.0 ' -go get -d example.com/x@v1.3.1 +go get rsc.io/quote@>v1.3.1 go list -m rsc.io/quote stdout '^rsc.io/quote v1.4.0' @@ -81,7 +81,7 @@ cp go.mod.orig go.mod ! go list example stderr '^package example is not in GOROOT \(.*\)$' -! go get -d example +! go get example stderr '^go: malformed module path "example": missing dot in first path element$' go mod edit -replace example@v0.1.0=./example @@ -89,7 +89,7 @@ go mod edit -replace example@v0.1.0=./example ! go list example stderr '^module example provides package example and is replaced but not required; to add it:\n\tgo get example@v0.1.0$' -go get -d example +go get example go list -m example stdout '^example v0.1.0 ' diff --git a/src/cmd/go/testdata/script/mod_get_retract.txt b/src/cmd/go/testdata/script/mod_get_retract.txt index 560fa7bfb2..9757989666 100644 --- a/src/cmd/go/testdata/script/mod_get_retract.txt +++ b/src/cmd/go/testdata/script/mod_get_retract.txt @@ -1,7 +1,7 @@ # 'go get pkg' should not upgrade to a retracted version. cp go.mod.orig go.mod go mod edit -require example.com/retract/self/prev@v1.1.0 -go get -d example.com/retract/self/prev +go get example.com/retract/self/prev go list -m example.com/retract/self/prev stdout '^example.com/retract/self/prev v1.1.0$' @@ -9,7 +9,7 @@ stdout '^example.com/retract/self/prev v1.1.0$' # version is available. cp go.mod.orig go.mod go mod edit -require example.com/retract/self/prev@v1.9.0 -go get -d example.com/retract/self/prev +go get example.com/retract/self/prev stderr '^go: warning: example.com/retract/self/prev@v1.9.0: retracted by module author: self$' stderr '^go: to switch to the latest unretracted version, run:\n\tgo get example.com/retract/self/prev@latest\n$' go list -m example.com/retract/self/prev @@ -18,14 +18,14 @@ stdout '^example.com/retract/self/prev v1.9.0$' # 'go get pkg@latest' should downgrade from a retracted version. cp go.mod.orig go.mod go mod edit -require example.com/retract/self/prev@v1.9.0 -go get -d example.com/retract/self/prev@latest +go get example.com/retract/self/prev@latest go list -m example.com/retract/self/prev stdout '^example.com/retract/self/prev v1.1.0$' # 'go get pkg@version' should update to a specific version, even if that # version is retracted. cp go.mod.orig go.mod -go get -d example.com/retract@v1.0.0-bad +go get example.com/retract@v1.0.0-bad stderr '^go: warning: example.com/retract@v1.0.0-bad: retracted by module author: bad$' go list -m example.com/retract stdout '^example.com/retract v1.0.0-bad$' @@ -34,16 +34,16 @@ stdout '^example.com/retract v1.0.0-bad$' # version is available. cp go.mod.orig go.mod go mod edit -require example.com/retract/self/prev@v1.9.0 -go get -d -u ./use +go get -u ./use stderr '^go: warning: example.com/retract/self/prev@v1.9.0: retracted by module author: self$' go list -m example.com/retract/self/prev stdout '^example.com/retract/self/prev v1.9.0$' # 'go get' should warn if a module needed to build named packages is retracted. # 'go get' should not warn about unrelated modules. -go get -d ./empty +go get ./empty ! stderr retracted -go get -d ./use +go get ./use stderr '^go: warning: example.com/retract/self/prev@v1.9.0: retracted by module author: self$' -- go.mod.orig -- diff --git a/src/cmd/go/testdata/script/mod_get_retract_ambiguous.txt b/src/cmd/go/testdata/script/mod_get_retract_ambiguous.txt index b49ba54982..4b4f5da03c 100644 --- a/src/cmd/go/testdata/script/mod_get_retract_ambiguous.txt +++ b/src/cmd/go/testdata/script/mod_get_retract_ambiguous.txt @@ -1,4 +1,4 @@ -! go get -d example.com/retract/ambiguous/other +! go get example.com/retract/ambiguous/other stderr 'ambiguous import: found package example.com/retract/ambiguous/nested in multiple modules:' stderr '^go: warning: example.com/retract/ambiguous/nested@v1.9.0-bad: retracted by module author: nested modules are bad$' diff --git a/src/cmd/go/testdata/script/mod_get_split.txt b/src/cmd/go/testdata/script/mod_get_split.txt index 2fb88ab2da..0fb22c85d3 100644 --- a/src/cmd/go/testdata/script/mod_get_split.txt +++ b/src/cmd/go/testdata/script/mod_get_split.txt @@ -4,7 +4,7 @@ cp go.mod go.mod.orig # 'go get' on a package already provided by the build list should update # the module already in the build list, not fail with an ambiguous import error. -go get -d example.net/split/nested@patch +go get example.net/split/nested@patch go list -m all stdout '^example.net/split v0.2.1 ' ! stdout '^example.net/split/nested' @@ -13,7 +13,7 @@ stdout '^example.net/split v0.2.1 ' cp go.mod.orig go.mod -go get -d example.net/split/nested/...@patch +go get example.net/split/nested/...@patch go list -m all stdout '^example.net/split v0.2.1 ' ! stdout '^example.net/split/nested' @@ -32,7 +32,7 @@ stdout '^example.net/split v0.2.1 ' cp go.mod.orig go.mod -! go get -d example.net/split/nested@v0.1.0 +! go get example.net/split/nested@v0.1.0 stderr '^example.net/split/nested: ambiguous import: found package example.net/split/nested in multiple modules:\n\texample.net/split v0.2.0 \(.*split.2[/\\]nested\)\n\texample.net/split/nested v0.1.0 \(.*nested.1\)$' # A wildcard that matches packages in some module at its selected version @@ -54,7 +54,7 @@ stderr '^example.net/split/nested: ambiguous import: found package example.net/s # # TODO(#27899): Should we instead upgrade or downgrade to an arbirary version? -! go get -d example.net/split/nested/...@v0.1.0 +! go get example.net/split/nested/...@v0.1.0 stderr '^go: example.net/split/nested/\.\.\.@v0.1.0 matches packages in example.net/split@v0.2.0 but not example.net/split@v0.1.0: specify a different version for module example.net/split$' cmp go.mod go.mod.orig @@ -62,14 +62,14 @@ cmp go.mod go.mod.orig # If another argument resolves the ambiguity, we should be ok again. -go get -d example.net/split@none example.net/split/nested@v0.1.0 +go get example.net/split@none example.net/split/nested@v0.1.0 go list -m all ! stdout '^example.net/split ' stdout '^example.net/split/nested v0.1.0 ' cp go.mod.orig go.mod -go get -d example.net/split@v0.3.0 example.net/split/nested@v0.1.0 +go get example.net/split@v0.3.0 example.net/split/nested@v0.1.0 go list -m all stdout '^example.net/split v0.3.0 ' stdout '^example.net/split/nested v0.1.0 ' @@ -80,14 +80,14 @@ stdout '^example.net/split/nested v0.1.0 ' # to match the pattern if possible. cp go.mod.orig go.mod -go get -d example.net/split/nested@v0.0.0 +go get example.net/split/nested@v0.0.0 -go get -d example.net/...@v0.1.0 +go get example.net/...@v0.1.0 go list -m all stdout '^example.net/split v0.1.0 ' stdout '^example.net/split/nested v0.1.0 ' -go get -d example.net/... +go get example.net/... go list -m all stdout '^example.net/split v0.3.0 ' stdout '^example.net/split/nested v0.2.0 ' @@ -96,15 +96,15 @@ stdout '^example.net/split/nested v0.2.0 ' # @none applies to all matching module paths, # regardless of whether they contain any packages. -go get -d example.net/...@none +go get example.net/...@none go list -m all ! stdout '^example.net' # Starting from no dependencies, a wildcard can resolve to an empty module with # the same prefix even if it contains no packages. -go get -d example.net/...@none -go get -d example.net/split/...@v0.1.0 +go get example.net/...@none +go get example.net/split/...@v0.1.0 go list -m all stdout '^example.net/split v0.1.0 ' diff --git a/src/cmd/go/testdata/script/mod_get_sum_noroot.txt b/src/cmd/go/testdata/script/mod_get_sum_noroot.txt index 4f1cf03277..0d9a840e77 100644 --- a/src/cmd/go/testdata/script/mod_get_sum_noroot.txt +++ b/src/cmd/go/testdata/script/mod_get_sum_noroot.txt @@ -2,7 +2,7 @@ # it should add sums for the module's go.mod file and its content to go.sum. # Verifies golang.org/issue/41103. go mod init m -go get -d rsc.io/QUOTE +go get rsc.io/QUOTE grep '^rsc.io/QUOTE v1.5.2/go.mod ' go.sum grep '^rsc.io/QUOTE v1.5.2 ' go.sum diff --git a/src/cmd/go/testdata/script/mod_get_test.txt b/src/cmd/go/testdata/script/mod_get_test.txt index 23722bd4e4..0fa7cd98b9 100644 --- a/src/cmd/go/testdata/script/mod_get_test.txt +++ b/src/cmd/go/testdata/script/mod_get_test.txt @@ -2,38 +2,38 @@ env GO111MODULE=on # By default, 'go get' should ignore tests cp go.mod.empty go.mod -go get -d m/a +go get m/a ! grep rsc.io/quote go.mod # 'go get -t' should consider test dependencies of the named package. cp go.mod.empty go.mod -go get -d -t m/a +go get -t m/a grep 'rsc.io/quote v1.5.2$' go.mod # 'go get -t' should not consider test dependencies of imported packages, # including packages imported from tests. cp go.mod.empty go.mod -go get -d -t m/b +go get -t m/b ! grep rsc.io/quote go.mod # 'go get -t -u' should update test dependencies of the named package. cp go.mod.empty go.mod go mod edit -require=rsc.io/quote@v1.5.1 -go get -d -t -u m/a +go get -t -u m/a grep 'rsc.io/quote v1.5.2$' go.mod # 'go get -t -u' should not add or update test dependencies # of imported packages, including packages imported from tests. cp go.mod.empty go.mod -go get -d -t -u m/b +go get -t -u m/b ! grep rsc.io/quote go.mod go mod edit -require=rsc.io/quote@v1.5.1 -go get -d -t -u m/b +go get -t -u m/b grep 'rsc.io/quote v1.5.1$' go.mod # 'go get all' should consider test dependencies with or without -t. cp go.mod.empty go.mod -go get -d all +go get all grep 'rsc.io/quote v1.5.2$' go.mod -- go.mod.empty -- diff --git a/src/cmd/go/testdata/script/mod_get_trailing_slash.txt b/src/cmd/go/testdata/script/mod_get_trailing_slash.txt index c536693537..7b469008ba 100644 --- a/src/cmd/go/testdata/script/mod_get_trailing_slash.txt +++ b/src/cmd/go/testdata/script/mod_get_trailing_slash.txt @@ -7,16 +7,9 @@ stdout ^example.com/dotgo.go$ go list example.com/dotgo.go/ stdout ^example.com/dotgo.go$ -# go get -d should succeed in either case, with or without a version. +# go get should succeed in either case, with or without a version. # Arguments are interpreted as packages or package patterns with versions, # not source files. -go get -d example.com/dotgo.go -go get -d example.com/dotgo.go/ -go get -d example.com/dotgo.go@v1.0.0 -go get -d example.com/dotgo.go/@v1.0.0 - -# go get (without -d) should also succeed in either case. -[short] skip go get example.com/dotgo.go go get example.com/dotgo.go/ go get example.com/dotgo.go@v1.0.0 diff --git a/src/cmd/go/testdata/script/mod_get_update_unrelated_sum.txt b/src/cmd/go/testdata/script/mod_get_update_unrelated_sum.txt index 0093c0eda0..a5651e9341 100644 --- a/src/cmd/go/testdata/script/mod_get_update_unrelated_sum.txt +++ b/src/cmd/go/testdata/script/mod_get_update_unrelated_sum.txt @@ -18,7 +18,7 @@ cmp go.sum.orig go.sum # Upgrade a module. This also upgrades rsc.io/quote, and though we didn't load # a package from it, we had the sum for its old version, so we need the # sum for the new version, too. -go get -d example.com/upgrade@v0.0.2 +go get example.com/upgrade@v0.0.2 grep '^rsc.io/quote v1.5.2 ' go.sum # The upgrade still breaks the build because the new version of quote imports @@ -34,7 +34,7 @@ cp go.sum.orig go.sum # We didn't need a sum for it before (even though we had one), so we won't # fetch a new sum. go mod edit -replace rsc.io/quote@v1.0.0=./dummy -go get -d example.com/upgrade@v0.0.2 +go get example.com/upgrade@v0.0.2 ! grep '^rsc.io/quote v1.5.2 ' go.sum cp go.mod.orig go.mod cp go.sum.orig go.sum @@ -43,7 +43,7 @@ cp go.sum.orig go.sum # Replace the new version with a directory before upgrading. # We can't get a sum for a directory. go mod edit -replace rsc.io/quote@v1.5.2=./dummy -go get -d example.com/upgrade@v0.0.2 +go get example.com/upgrade@v0.0.2 ! grep '^rsc.io/quote v1.5.2 ' go.sum cp go.mod.orig go.mod cp go.sum.orig go.sum @@ -52,7 +52,7 @@ cp go.sum.orig go.sum # Replace the new version with a different version. # We should get a sum for that version. go mod edit -replace rsc.io/quote@v1.5.2=rsc.io/quote@v1.5.1 -go get -d example.com/upgrade@v0.0.2 +go get example.com/upgrade@v0.0.2 ! grep '^rsc.io/quote v1.5.2 ' go.sum grep '^rsc.io/quote v1.5.1 ' go.sum cp go.mod.orig go.mod @@ -63,7 +63,7 @@ cp go.sum.orig go.sum # 'go get' should fail when fetching the zip. rm $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip env GOPROXY=off -! go get -d example.com/upgrade@v0.0.2 +! go get example.com/upgrade@v0.0.2 stderr '^go: upgraded rsc.io/quote v1.0.0 => v1.5.2: error finding sum for rsc.io/quote@v1.5.2: module lookup disabled by GOPROXY=off$' -- go.mod.orig -- diff --git a/src/cmd/go/testdata/script/mod_get_upgrade.txt b/src/cmd/go/testdata/script/mod_get_upgrade.txt index eeb6d6f6af..51d5990ee1 100644 --- a/src/cmd/go/testdata/script/mod_get_upgrade.txt +++ b/src/cmd/go/testdata/script/mod_get_upgrade.txt @@ -1,35 +1,35 @@ env GO111MODULE=on -go get -d rsc.io/quote@v1.5.1 +go get rsc.io/quote@v1.5.1 go list -m all stdout 'rsc.io/quote v1.5.1' grep 'rsc.io/quote v1.5.1$' go.mod # get -u should update dependencies of the package in the current directory -go get -d -u +go get -u grep 'rsc.io/quote v1.5.2$' go.mod grep 'golang.org/x/text [v0-9a-f\.-]+ // indirect' go.mod # get -u rsc.io/sampler should update only sampler's dependencies cp go.mod-v1.5.1 go.mod -go get -d -u rsc.io/sampler +go get -u rsc.io/sampler grep 'rsc.io/quote v1.5.1$' go.mod grep 'golang.org/x/text [v0-9a-f\.-]+ // indirect' go.mod # move to a pseudo-version after any tags -go get -d rsc.io/quote@dd9747d +go get rsc.io/quote@dd9747d grep 'rsc.io/quote v0.0.0-20180628003336-dd9747d19b04' go.mod # get -u should not jump off newer pseudo-version to earlier tag -go get -d -u +go get -u grep 'rsc.io/quote v0.0.0-20180628003336-dd9747d19b04' go.mod # move to earlier pseudo-version -go get -d rsc.io/quote@e7a685a342 +go get rsc.io/quote@e7a685a342 grep 'rsc.io/quote v0.0.0-20180214005133-e7a685a342c0' go.mod # get -u should jump off earlier pseudo-version to newer tag -go get -d -u +go get -u grep 'rsc.io/quote v1.5.2' go.mod -- go.mod -- diff --git a/src/cmd/go/testdata/script/mod_get_upgrade_pseudo.txt b/src/cmd/go/testdata/script/mod_get_upgrade_pseudo.txt index f5f415aa3f..deff9358f0 100644 --- a/src/cmd/go/testdata/script/mod_get_upgrade_pseudo.txt +++ b/src/cmd/go/testdata/script/mod_get_upgrade_pseudo.txt @@ -10,52 +10,52 @@ env GO111MODULE=on # The v0.0.0 pseudo-version is chronologically newer. # Start at v0.1.1-0.20190429073117-b5426c86b553 -go get -d example.com/pseudoupgrade@b5426c8 +go get example.com/pseudoupgrade@b5426c8 go list -m -u all stdout '^example.com/pseudoupgrade v0.1.1-0.20190429073117-b5426c86b553$' # 'get -u' should not downgrade to the (lower) tagged version. -go get -d -u +go get -u go list -m -u all stdout '^example.com/pseudoupgrade v0.1.1-0.20190429073117-b5426c86b553$' # 'get example.com/pseudoupgrade@upgrade' should not downgrade. -go get -d example.com/pseudoupgrade@upgrade +go get example.com/pseudoupgrade@upgrade go list -m all stdout '^example.com/pseudoupgrade v0.1.1-0.20190429073117-b5426c86b553$' # 'get example.com/pseudoupgrade' should not downgrade. # This is equivalent to 'get example.com/pseudoupgrade@upgrade'. -go get -d example.com/pseudoupgrade +go get example.com/pseudoupgrade go list -m all stdout '^example.com/pseudoupgrade v0.1.1-0.20190429073117-b5426c86b553$' # 'get example.com/pseudoupgrade@latest' should downgrade. # @latest should not consider the current version. -go get -d example.com/pseudoupgrade@latest +go get example.com/pseudoupgrade@latest go list -m all stdout '^example.com/pseudoupgrade v0.1.0$' # We should observe the same behavior with the newer pseudo-version. -go get -d example.com/pseudoupgrade@v0.0.0-20190430073000-30950c05d534 +go get example.com/pseudoupgrade@v0.0.0-20190430073000-30950c05d534 # 'get -u' should not downgrade to the chronologically older tagged version. -go get -d -u +go get -u go list -m -u all stdout '^example.com/pseudoupgrade v0.0.0-20190430073000-30950c05d534$' # 'get example.com/pseudoupgrade@upgrade should not downgrade. -go get -d example.com/pseudoupgrade@upgrade +go get example.com/pseudoupgrade@upgrade go list -m -u all stdout '^example.com/pseudoupgrade v0.0.0-20190430073000-30950c05d534$' # 'get example.com/pseudoupgrade' should not downgrade. -go get -d example.com/pseudoupgrade +go get example.com/pseudoupgrade go list -m -u all stdout '^example.com/pseudoupgrade v0.0.0-20190430073000-30950c05d534$' # 'get example.com/pseudoupgrade@latest' should downgrade. -go get -d example.com/pseudoupgrade@latest +go get example.com/pseudoupgrade@latest go list -m -u all stdout '^example.com/pseudoupgrade v0.1.0$' diff --git a/src/cmd/go/testdata/script/mod_get_wild.txt b/src/cmd/go/testdata/script/mod_get_wild.txt index b88f268a1d..06f9973e43 100644 --- a/src/cmd/go/testdata/script/mod_get_wild.txt +++ b/src/cmd/go/testdata/script/mod_get_wild.txt @@ -11,7 +11,7 @@ stdout '^example.net/a v0.1.0 ' # already in the build list, and the wildcard in the first element prevents us # from attempting to resolve a new module whose path is a prefix of the pattern. -! go get -d -u=patch example.../b@upgrade +! go get -u=patch example.../b@upgrade stderr '^go: no modules to query for example\.\.\./b@upgrade because first path element contains a wildcard$' @@ -19,7 +19,7 @@ stderr '^go: no modules to query for example\.\.\./b@upgrade because first path # for example.net/b/..., which is itself patched and causes another upgrade to # example.net/a, which is then patched again. -go get -d -u=patch . example.../b@upgrade +go get -u=patch . example.../b@upgrade go list -m all stdout '^example.net/a v0.2.1 ' # upgraded by dependency of b and -u=patch stdout '^example.net/b v0.2.0 ' # introduced by patch of a and upgraded by wildcard diff --git a/src/cmd/go/testdata/script/mod_getmode_vendor.txt b/src/cmd/go/testdata/script/mod_getmode_vendor.txt index a4e23ac9d0..aaf526b2ab 100644 --- a/src/cmd/go/testdata/script/mod_getmode_vendor.txt +++ b/src/cmd/go/testdata/script/mod_getmode_vendor.txt @@ -1,6 +1,6 @@ env GO111MODULE=on -go get -d rsc.io/quote@v1.5.1 +go get rsc.io/quote@v1.5.1 go mod vendor env GOPATH=$WORK/empty env GOPROXY=file:///nonexist diff --git a/src/cmd/go/testdata/script/mod_getx.txt b/src/cmd/go/testdata/script/mod_getx.txt index ce9ef0d6ce..b3d06c17c8 100644 --- a/src/cmd/go/testdata/script/mod_getx.txt +++ b/src/cmd/go/testdata/script/mod_getx.txt @@ -8,7 +8,7 @@ env GOSUMDB=off # 'go get -x' should log URLs with an HTTP or HTTPS scheme. # A bug had caused us to log schemeless URLs instead. -go get -x -d golang.org/x/text@v0.1.0 +go get -x golang.org/x/text@v0.1.0 stderr '^# get https://golang.org/x/text\?go-get=1$' stderr '^# get https://golang.org/x/text\?go-get=1: 200 OK \([0-9.]+s\)$' ! stderr '^# get //.*' diff --git a/src/cmd/go/testdata/script/mod_gomodcache.txt b/src/cmd/go/testdata/script/mod_gomodcache.txt index a9d7ab3f04..bafa587624 100644 --- a/src/cmd/go/testdata/script/mod_gomodcache.txt +++ b/src/cmd/go/testdata/script/mod_gomodcache.txt @@ -5,7 +5,7 @@ env GO111MODULE=on env GOMODCACHE=$WORK/modcache go env GOMODCACHE stdout $WORK[/\\]modcache -go get -d rsc.io/quote@v1.0.0 +go get rsc.io/quote@v1.0.0 exists $WORK/modcache/cache/download/rsc.io/quote/@v/v1.0.0.info grep '{"Version":"v1.0.0","Time":"2018-02-14T00:45:20Z"}' $WORK/modcache/cache/download/rsc.io/quote/@v/v1.0.0.info @@ -18,7 +18,7 @@ exists $WORK/modcache/cache/download/sumdb env GOMODCACHE= go env GOMODCACHE stdout $GOPATH[/\\]pkg[/\\]mod -go get -d rsc.io/quote@v1.0.0 +go get rsc.io/quote@v1.0.0 exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.0.0.info grep '{"Version":"v1.0.0","Time":"2018-02-14T00:45:20Z"}' $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.0.0.info diff --git a/src/cmd/go/testdata/script/mod_gonoproxy.txt b/src/cmd/go/testdata/script/mod_gonoproxy.txt index 190940030c..d42d668f67 100644 --- a/src/cmd/go/testdata/script/mod_gonoproxy.txt +++ b/src/cmd/go/testdata/script/mod_gonoproxy.txt @@ -7,16 +7,16 @@ env dbname=localhost.localdev/sumdb # disagree with sumdb fails cp go.mod.orig go.mod env GOSUMDB=$sumdb' '$proxy/sumdb-wrong -! go get -d rsc.io/quote +! go get rsc.io/quote stderr 'SECURITY ERROR' # GONOSUMDB bypasses sumdb, for rsc.io/quote, rsc.io/sampler, golang.org/x/text env GONOSUMDB='*/quote,*/*mple*,golang.org/x' -go get -d rsc.io/quote +go get rsc.io/quote rm go.sum env GOPRIVATE='*/quote,*/*mple*,golang.org/x' env GONOPROXY=none # that is, proxy all despite GOPRIVATE -go get -d rsc.io/quote +go get rsc.io/quote # Download .info files needed for 'go list -m all' later. # TODO(#42723): either 'go list -m' should not read these files, @@ -26,13 +26,13 @@ stdout '^golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c$' # When GOPROXY is not empty but contains no entries, an error should be reported. env GOPROXY=',' -! go get -d golang.org/x/text +! go get golang.org/x/text stderr '^go: golang.org/x/text: GOPROXY list is not the empty string, but contains no entries$' # When GOPROXY=off, fetching modules not matched by GONOPROXY fails. env GONOPROXY=*/fortune env GOPROXY=off -! go get -d golang.org/x/text +! go get golang.org/x/text stderr '^go: golang.org/x/text: module lookup disabled by GOPROXY=off$' # GONOPROXY bypasses proxy @@ -40,13 +40,13 @@ stderr '^go: golang.org/x/text: module lookup disabled by GOPROXY=off$' [!exec:git] skip env GOPRIVATE=none env GONOPROXY='*/fortune' -! go get -d rsc.io/fortune # does not exist in real world, only on test proxy +! go get rsc.io/fortune # does not exist in real world, only on test proxy stderr 'git ls-remote' env GOSUMDB= env GONOPROXY= env GOPRIVATE='*/x' -go get -d golang.org/x/text +go get golang.org/x/text go list -m all ! stdout 'text.*v0.0.0-2017' # should not have the version from the proxy diff --git a/src/cmd/go/testdata/script/mod_gopkg_unstable.txt b/src/cmd/go/testdata/script/mod_gopkg_unstable.txt index 5ad9106378..beba3e7b02 100644 --- a/src/cmd/go/testdata/script/mod_gopkg_unstable.txt +++ b/src/cmd/go/testdata/script/mod_gopkg_unstable.txt @@ -1,7 +1,7 @@ env GO111MODULE=on cp go.mod.empty go.mod -go get -d gopkg.in/dummy.v2-unstable +go get gopkg.in/dummy.v2-unstable cp x.go.txt x.go cp go.mod.empty go.mod @@ -12,7 +12,7 @@ go list env GOPROXY=direct env GOSUMDB=off -go get -d gopkg.in/macaroon-bakery.v2-unstable/bakery +go get gopkg.in/macaroon-bakery.v2-unstable/bakery go list -m all stdout 'gopkg.in/macaroon-bakery.v2-unstable v2.0.0-[0-9]+-[0-9a-f]+$' diff --git a/src/cmd/go/testdata/script/mod_import.txt b/src/cmd/go/testdata/script/mod_import.txt index 28358b5b0c..07714e92c7 100644 --- a/src/cmd/go/testdata/script/mod_import.txt +++ b/src/cmd/go/testdata/script/mod_import.txt @@ -1,7 +1,7 @@ env GO111MODULE=on # latest rsc.io/quote should be v1.5.2 not v1.5.3-pre1 -go get -d +go get go list -m all stdout 'rsc.io/quote v1.5.2' diff --git a/src/cmd/go/testdata/script/mod_import_v1suffix.txt b/src/cmd/go/testdata/script/mod_import_v1suffix.txt index a429450466..75b3374bca 100644 --- a/src/cmd/go/testdata/script/mod_import_v1suffix.txt +++ b/src/cmd/go/testdata/script/mod_import_v1suffix.txt @@ -1,6 +1,6 @@ env GO111MODULE=on -! go get -d example.com/invalidpath/v1 +! go get example.com/invalidpath/v1 ! go install . -- go.mod -- diff --git a/src/cmd/go/testdata/script/mod_in_testdata_dir.txt b/src/cmd/go/testdata/script/mod_in_testdata_dir.txt index 66f79faa6d..866f7841b9 100644 --- a/src/cmd/go/testdata/script/mod_in_testdata_dir.txt +++ b/src/cmd/go/testdata/script/mod_in_testdata_dir.txt @@ -9,7 +9,7 @@ cd $WORK/testdata go mod init testdata.tld/foo # Getting a package within that module should resolve its dependencies. -go get -d +go get grep 'rsc.io/quote' go.mod # Tidying the module should preserve those dependencies. diff --git a/src/cmd/go/testdata/script/mod_install_pkg_version.txt b/src/cmd/go/testdata/script/mod_install_pkg_version.txt index 1ee68e7ad8..14153b8e9e 100644 --- a/src/cmd/go/testdata/script/mod_install_pkg_version.txt +++ b/src/cmd/go/testdata/script/mod_install_pkg_version.txt @@ -70,7 +70,7 @@ go mod edit -require=rsc.io/fortune@v1.0.0 stderr '^missing go\.sum entry for module providing package rsc\.io/fortune; to add:\n\tgo mod download rsc\.io/fortune$' ! go install -mod=readonly ../../pkg/mod/rsc.io/fortune@v1.0.0 stderr '^missing go\.sum entry for module providing package rsc\.io/fortune; to add:\n\tgo mod download rsc\.io/fortune$' -go get -d rsc.io/fortune@v1.0.0 +go get rsc.io/fortune@v1.0.0 go install -mod=readonly $GOPATH/pkg/mod/rsc.io/fortune@v1.0.0 exists $GOPATH/bin/fortune$GOEXE cd .. @@ -125,7 +125,7 @@ stderr '^package example.com/cmd/err is not a main package$' mkdir tmp cd tmp go mod init m -go get -d example.com/cmd@v1.0.0 +go get example.com/cmd@v1.0.0 ! go build example.com/cmd/... stderr 'err[/\\]err.go:3:9: undefined: DoesNotCompile$' cd .. diff --git a/src/cmd/go/testdata/script/mod_install_versioned.txt b/src/cmd/go/testdata/script/mod_install_versioned.txt index c6bce418b4..627a9a81b0 100644 --- a/src/cmd/go/testdata/script/mod_install_versioned.txt +++ b/src/cmd/go/testdata/script/mod_install_versioned.txt @@ -1,11 +1,11 @@ env GO111MODULE=on -go get -d rsc.io/fortune +go get rsc.io/fortune go list -f '{{.Target}}' rsc.io/fortune ! stdout fortune@v1 stdout 'fortune(\.exe)?$' -go get -d rsc.io/fortune/v2 +go get rsc.io/fortune/v2 go list -f '{{.Target}}' rsc.io/fortune/v2 ! stdout v2 stdout 'fortune(\.exe)?$' diff --git a/src/cmd/go/testdata/script/mod_internal.txt b/src/cmd/go/testdata/script/mod_internal.txt index 687269d18f..787b21f379 100644 --- a/src/cmd/go/testdata/script/mod_internal.txt +++ b/src/cmd/go/testdata/script/mod_internal.txt @@ -3,34 +3,34 @@ env GO111MODULE=on # golang.org/x/internal should be importable from other golang.org/x modules. go mod edit -module=golang.org/x/anything -go get -d . +go get . # ...and their tests... go test stdout PASS # ...but that should not leak into other modules. -go get -d ./baddep +go get ./baddep ! go build ./baddep stderr golang.org[/\\]notx[/\\]useinternal stderr 'use of internal package golang.org/x/.* not allowed' # Internal packages in the standard library should not leak into modules. -go get -d ./fromstd +go get ./fromstd ! go build ./fromstd stderr 'use of internal package internal/testenv not allowed' # Dependencies should be able to use their own internal modules... go mod edit -module=golang.org/notx -go get -d ./throughdep +go get ./throughdep # ... but other modules should not, even if they have transitive dependencies. -go get -d . +go get . ! go build . stderr 'use of internal package golang.org/x/.* not allowed' # And transitive dependencies still should not leak. -go get -d ./baddep +go get ./baddep ! go build ./baddep stderr golang.org[/\\]notx[/\\]useinternal stderr 'use of internal package golang.org/x/.* not allowed' @@ -38,17 +38,17 @@ stderr 'use of internal package golang.org/x/.* not allowed' # Replacing an internal module should keep it internal to the same paths. go mod edit -module=golang.org/notx go mod edit -replace golang.org/x/internal=./replace/golang.org/notx/internal -go get -d ./throughdep +go get ./throughdep -go get -d ./baddep +go get ./baddep ! go build ./baddep stderr golang.org[/\\]notx[/\\]useinternal stderr 'use of internal package golang.org/x/.* not allowed' go mod edit -replace golang.org/x/internal=./vendor/golang.org/x/internal -go get -d ./throughdep +go get ./throughdep -go get -d ./baddep +go get ./baddep ! go build ./baddep stderr golang.org[/\\]notx[/\\]useinternal stderr 'use of internal package golang.org/x/.* not allowed' diff --git a/src/cmd/go/testdata/script/mod_invalid_path.txt b/src/cmd/go/testdata/script/mod_invalid_path.txt index 766e9c0909..667b76e340 100644 --- a/src/cmd/go/testdata/script/mod_invalid_path.txt +++ b/src/cmd/go/testdata/script/mod_invalid_path.txt @@ -30,8 +30,8 @@ go list ./use stdout '^example.com/dotname/use$' ! go list -m example.com/dotname/.dot@latest stderr '^go: example.com/dotname/.dot@latest: malformed module path "example.com/dotname/.dot": leading dot in path element$' -go get -d example.com/dotname/.dot -go get -d example.com/dotname/use +go get example.com/dotname/.dot +go get example.com/dotname/use go mod tidy -- mod/go.mod -- diff --git a/src/cmd/go/testdata/script/mod_invalid_path_dotname.txt b/src/cmd/go/testdata/script/mod_invalid_path_dotname.txt index 85934332d1..484c208f0f 100644 --- a/src/cmd/go/testdata/script/mod_invalid_path_dotname.txt +++ b/src/cmd/go/testdata/script/mod_invalid_path_dotname.txt @@ -3,19 +3,19 @@ # 'go get' works with no version query. cp go.mod.empty go.mod -go get -d example.com/dotname/.dot +go get example.com/dotname/.dot go list -m example.com/dotname stdout '^example.com/dotname v1.0.0$' # 'go get' works with a version query. cp go.mod.empty go.mod -go get -d example.com/dotname/.dot@latest +go get example.com/dotname/.dot@latest go list -m example.com/dotname stdout '^example.com/dotname v1.0.0$' # 'go get' works on an importing package. cp go.mod.empty go.mod -go get -d . +go get . go list -m example.com/dotname stdout '^example.com/dotname v1.0.0$' diff --git a/src/cmd/go/testdata/script/mod_invalid_path_plus.txt b/src/cmd/go/testdata/script/mod_invalid_path_plus.txt index 6a29eb8ce0..dd59eb1fed 100644 --- a/src/cmd/go/testdata/script/mod_invalid_path_plus.txt +++ b/src/cmd/go/testdata/script/mod_invalid_path_plus.txt @@ -4,7 +4,7 @@ # 'go list' accepts package paths with pluses. cp go.mod.orig go.mod -go get -d example.net/cmd +go get example.net/cmd go list example.net/cmd/x++ # 'go list -m' rejects module paths with pluses. @@ -13,7 +13,7 @@ stderr '^go: malformed module path "example.net/bad\+\+": invalid char ''\+''$' # 'go get' accepts package paths with pluses. cp go.mod.orig go.mod -go get -d example.net/cmd/x++ +go get example.net/cmd/x++ go list -m example.net/cmd stdout '^example.net/cmd v0.0.0-00010101000000-000000000000 => ./cmd$' diff --git a/src/cmd/go/testdata/script/mod_invalid_version.txt b/src/cmd/go/testdata/script/mod_invalid_version.txt index 31b25f757e..f9317b676d 100644 --- a/src/cmd/go/testdata/script/mod_invalid_version.txt +++ b/src/cmd/go/testdata/script/mod_invalid_version.txt @@ -37,7 +37,7 @@ stderr 'golang.org/x/text/unicode@v0.0.0-20170915032832-14c0d48ead0c: invalid ve # However, arguments to 'go get' can name packages above the root. cp go.mod.orig go.mod -go get -d golang.org/x/text/unicode@v0.0.0-20170915032832-14c0d48ead0c +go get golang.org/x/text/unicode@v0.0.0-20170915032832-14c0d48ead0c go list -m golang.org/x/text/... stdout 'golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c' ! stdout 'golang.org/x/text/unicode' @@ -141,10 +141,10 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v1.999999.0 go mod edit -replace golang.org/x/text@v1.999999.0=golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c cd outside -! go get -d golang.org/x/text@upgrade +! go get golang.org/x/text@upgrade stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v1.999999.0: reading golang.org/x/text/go.mod at revision v1.999999.0: unknown revision v1.999999.0' cd .. -go get -d golang.org/x/text@upgrade +go get golang.org/x/text@upgrade go list -m golang.org/x/text stdout 'golang.org/x/text v1.999999.0 => golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c' @@ -214,14 +214,14 @@ stdout 'github.com/pierrec/lz4 v2.0.4-0.20180826165652-dbe9298ce099\+incompatibl # to the equivalent +incompatible version, not a pseudo-version with a different # major version. cp go.mod.orig go.mod -go get -d github.com/pierrec/lz4@v2.0.5 +go get github.com/pierrec/lz4@v2.0.5 go list -m github.com/pierrec/lz4 stdout 'github.com/pierrec/lz4 v2.0.5\+incompatible' # 'go get' for a mismatched major version with a go.mod file should error out, # not resolve to a pseudo-version with a different major version. cp go.mod.orig go.mod -! go get -d github.com/pierrec/lz4@v2.0.8 +! go get github.com/pierrec/lz4@v2.0.8 stderr 'go: github.com/pierrec/lz4@v2.0.8: invalid version: module contains a go.mod file, so major version must be compatible: should be v0 or v1, not v2' # An invalid +incompatible suffix for a canonical version should error out, diff --git a/src/cmd/go/testdata/script/mod_issue35317.txt b/src/cmd/go/testdata/script/mod_issue35317.txt index b1852ab031..92416a54e4 100644 --- a/src/cmd/go/testdata/script/mod_issue35317.txt +++ b/src/cmd/go/testdata/script/mod_issue35317.txt @@ -5,4 +5,4 @@ env GO111MODULE=on [short] skip go mod init example.com -go get -d golang.org/x/text@v0.3.0 golang.org/x/internal@v0.1.0 golang.org/x/exp@none +go get golang.org/x/text@v0.3.0 golang.org/x/internal@v0.1.0 golang.org/x/exp@none diff --git a/src/cmd/go/testdata/script/mod_lazy_downgrade.txt b/src/cmd/go/testdata/script/mod_lazy_downgrade.txt index 2f815fef22..eb69d2eb8f 100644 --- a/src/cmd/go/testdata/script/mod_lazy_downgrade.txt +++ b/src/cmd/go/testdata/script/mod_lazy_downgrade.txt @@ -27,7 +27,7 @@ stdout '^example.com/c v0.2.0 ' # Downgrading c should also downgrade the b that requires it. -go get -d example.com/c@v0.1.0 +go get example.com/c@v0.1.0 go list -m all stdout '^example.com/a v0.1.0 ' stdout '^example.com/b v0.2.0 ' @@ -35,7 +35,7 @@ stdout '^example.com/c v0.1.0 ' # Removing c entirely should also remove the a and b that require it. -go get -d example.com/c@none +go get example.com/c@none go list -m all ! stdout '^example.com/a ' ! stdout '^example.com/b ' @@ -53,7 +53,7 @@ stdout '^example.com/a v0.1.0 ' stdout '^example.com/b v0.3.0 ' stdout '^example.com/c v0.2.0 ' -go get -d example.com/c@v0.1.0 +go get example.com/c@v0.1.0 go list -m all stdout '^example.com/a v0.1.0 ' stdout '^example.com/b v0.2.0 ' @@ -63,7 +63,7 @@ stdout '^example.com/c v0.1.0 ' # is still tracked, and it will still be downgraded away if we remove c. # ('go get' never makes a root into a non-root. Only 'go mod tidy' does that.) -go get -d example.com/c@none +go get example.com/c@none go list -m all ! stdout '^example.com/a ' ! stdout '^example.com/b ' @@ -84,7 +84,7 @@ stdout '^example.com/a v0.1.0 ' stdout '^example.com/b v0.3.0 ' stdout '^example.com/c v0.2.0 ' -go get -d example.com/c@v0.1.0 example.com/b@v0.1.0 +go get example.com/c@v0.1.0 example.com/b@v0.1.0 go list -m all stdout '^example.com/a v0.1.0 ' stdout '^example.com/b v0.1.0 ' @@ -96,7 +96,7 @@ stdout '^example.com/a v0.1.0 ' stdout '^example.com/b v0.1.0 ' ! stdout '^example.com/c ' -go get -d example.com/c@none +go get example.com/c@none go list -m all stdout '^example.com/a v0.1.0' stdout '^example.com/b v0.1.0' diff --git a/src/cmd/go/testdata/script/mod_list_deprecated.txt b/src/cmd/go/testdata/script/mod_list_deprecated.txt index f0ecbba2ce..ee985cccbf 100644 --- a/src/cmd/go/testdata/script/mod_list_deprecated.txt +++ b/src/cmd/go/testdata/script/mod_list_deprecated.txt @@ -20,7 +20,7 @@ stdout '^in example.com/deprecated/a@v1.9.0$' # This works even if we use an old version that does not have the deprecation # message in its go.mod file. -go get -d example.com/deprecated/a@v1.0.0 +go get example.com/deprecated/a@v1.0.0 ! grep Deprecated: $WORK/gopath/pkg/mod/cache/download/example.com/deprecated/a/@v/v1.0.0.mod go list -m -u -f {{.Deprecated}} example.com/deprecated/a stdout '^in example.com/deprecated/a@v1.9.0$' diff --git a/src/cmd/go/testdata/script/mod_list_dir.txt b/src/cmd/go/testdata/script/mod_list_dir.txt index 1adab8f027..7ad65ffbc7 100644 --- a/src/cmd/go/testdata/script/mod_list_dir.txt +++ b/src/cmd/go/testdata/script/mod_list_dir.txt @@ -3,7 +3,7 @@ # go list with path to directory should work # populate go.sum -go get -d +go get env GO111MODULE=off go list -f '{{.ImportPath}}' $GOROOT/src/math @@ -20,7 +20,7 @@ go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/quote@v1.5.2 stdout '^rsc.io/quote$' go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/sampler@v1.3.0 stdout '^rsc.io/sampler$' -go get -d rsc.io/sampler@v1.3.1 +go get rsc.io/sampler@v1.3.1 go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/sampler@v1.3.1 stdout '^rsc.io/sampler$' ! go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/sampler@v1.3.0 diff --git a/src/cmd/go/testdata/script/mod_list_direct.txt b/src/cmd/go/testdata/script/mod_list_direct.txt index 62a472f475..9b7a04c504 100644 --- a/src/cmd/go/testdata/script/mod_list_direct.txt +++ b/src/cmd/go/testdata/script/mod_list_direct.txt @@ -10,7 +10,7 @@ env GOSUMDB=off # For a while, (*modfetch.codeRepo).Stat was not checking for a go.mod file, # which would produce a hard error at the subsequent call to GoMod. -go get -d +go get -- go.mod -- module example.com diff --git a/src/cmd/go/testdata/script/mod_list_replace_dir.txt b/src/cmd/go/testdata/script/mod_list_replace_dir.txt index f2f2d2b2bb..eac5ca7dd3 100644 --- a/src/cmd/go/testdata/script/mod_list_replace_dir.txt +++ b/src/cmd/go/testdata/script/mod_list_replace_dir.txt @@ -3,7 +3,7 @@ # Verifies golang.org/issue/29548 # Populate go.sum and download dependencies. -go get -d +go get # Ensure v1.5.2 is also in the cache so we can list it. go mod download rsc.io/quote@v1.5.2 diff --git a/src/cmd/go/testdata/script/mod_list_upgrade_pseudo.txt b/src/cmd/go/testdata/script/mod_list_upgrade_pseudo.txt index b983bec73d..8e51dfcd2a 100644 --- a/src/cmd/go/testdata/script/mod_list_upgrade_pseudo.txt +++ b/src/cmd/go/testdata/script/mod_list_upgrade_pseudo.txt @@ -12,11 +12,11 @@ env GO111MODULE=on # The latest pseudo-version is semantically higher than the latest tag. # 'list -u' should not suggest a lower version as an upgrade. -go get -d example.com/pseudoupgrade@b5426c8 +go get example.com/pseudoupgrade@b5426c8 go list -m -u all stdout '^example.com/pseudoupgrade v0.1.1-0.20190429073117-b5426c86b553$' -go get -d example.com/pseudoupgrade@v0.0.0-20190430073000-30950c05d534 +go get example.com/pseudoupgrade@v0.0.0-20190430073000-30950c05d534 go list -m -u all stdout '^example.com/pseudoupgrade v0.0.0-20190430073000-30950c05d534$' diff --git a/src/cmd/go/testdata/script/mod_load_badchain.txt b/src/cmd/go/testdata/script/mod_load_badchain.txt index 0c4e5e1714..be2a4bc1db 100644 --- a/src/cmd/go/testdata/script/mod_load_badchain.txt +++ b/src/cmd/go/testdata/script/mod_load_badchain.txt @@ -10,13 +10,13 @@ go mod download example.com/badchain/b@v1.1.0 go mod download example.com/badchain/c@v1.1.0 # Try to update example.com/badchain/a (and its dependencies). -! go get -d example.com/badchain/a +! go get example.com/badchain/a cmp stderr update-a-expected cmp go.mod go.mod.orig # Try to update the main module. This updates everything, including # modules that aren't direct requirements, so the error stack is shorter. -! go get -d -u ./... +! go get -u ./... cmp stderr update-main-expected cmp go.mod go.mod.orig diff --git a/src/cmd/go/testdata/script/mod_load_badzip.txt b/src/cmd/go/testdata/script/mod_load_badzip.txt index 65374d2a6d..58160b4d44 100644 --- a/src/cmd/go/testdata/script/mod_load_badzip.txt +++ b/src/cmd/go/testdata/script/mod_load_badzip.txt @@ -1,7 +1,7 @@ # Zip files with unexpected file names inside should be rejected. env GO111MODULE=on -! go get -d rsc.io/badzip +! go get rsc.io/badzip stderr 'zip for rsc.io/badzip@v1.0.0 has unexpected file rsc.io/badzip@v1.0.0.txt' ! grep rsc.io/badzip go.mod diff --git a/src/cmd/go/testdata/script/mod_multirepo.txt b/src/cmd/go/testdata/script/mod_multirepo.txt index 0f335a11f0..bbefb78d90 100644 --- a/src/cmd/go/testdata/script/mod_multirepo.txt +++ b/src/cmd/go/testdata/script/mod_multirepo.txt @@ -7,7 +7,7 @@ go list -deps -f {{.Dir}} # v2 import should use a downloaded module # both without an explicit go.mod entry ... cp tmp/use_v2.go x.go -go get -d . +go get . go list -deps -f {{.Dir}} stdout 'pkg[\\/]mod[\\/]rsc.io[\\/]quote[\\/]v2@v2.0.1$' diff --git a/src/cmd/go/testdata/script/mod_outside.txt b/src/cmd/go/testdata/script/mod_outside.txt index d9d364cc10..f88e2ae7ef 100644 --- a/src/cmd/go/testdata/script/mod_outside.txt +++ b/src/cmd/go/testdata/script/mod_outside.txt @@ -136,13 +136,13 @@ stderr '^\t''go get'' is no longer supported outside a module.$' ! go get -u all stderr '^go: go.mod file not found in current directory or any parent directory.$' stderr '^\t''go get'' is no longer supported outside a module.$' -! go get -d example.com/printversion@v1.0.0 example.com/version@none +! go get example.com/printversion@v1.0.0 example.com/version@none stderr '^go: go.mod file not found in current directory or any parent directory.$' stderr '^\t''go get'' is no longer supported outside a module.$' -# 'go get -d' should not download anything. +# 'go get' should not download anything. go clean -modcache -! go get -d example.com/printversion@v1.0.0 +! go get example.com/printversion@v1.0.0 stderr '^go: go.mod file not found in current directory or any parent directory.$' stderr '^\t''go get'' is no longer supported outside a module.$' ! exists $GOPATH/pkg/mod/example.com/printversion@v1.0.0 diff --git a/src/cmd/go/testdata/script/mod_overlay.txt b/src/cmd/go/testdata/script/mod_overlay.txt index 86ab04bd3c..da35be6a19 100644 --- a/src/cmd/go/testdata/script/mod_overlay.txt +++ b/src/cmd/go/testdata/script/mod_overlay.txt @@ -20,7 +20,7 @@ go list -deps -overlay overlay.json . # Overlaid go.mod is not rewritten by 'go get'. cd $WORK/gopath/src/get-doesnt-add-dep cp $WORK/overlay/get_doesnt_add_dep_go_mod $WORK/want_go_mod -! go get -d -overlay overlay.json . +! go get -overlay overlay.json . stderr '^go: updates to go.mod needed, but go.mod is part of the overlay specified with -overlay$' cmp $WORK/overlay/get_doesnt_add_dep_go_mod $WORK/want_go_mod @@ -30,17 +30,17 @@ cmp $WORK/overlay/get_doesnt_add_dep_go_mod $WORK/want_go_mod # the correct go.sum is used with the overlay, 'go get .' should # not report a security error. cd $WORK/gopath/src/overlay-sum-used -! go get -d . +! go get . stderr 'SECURITY ERROR' ! go mod verify stderr 'SECURITY ERROR' -go get -d -overlay overlay.json . +go get -overlay overlay.json . go mod verify -overlay overlay.json # Overlaid go.sum is not rewritten. # Copy an incomplete file to the overlay file, and expect an error # attempting to update the file cp incomplete-sum-file $WORK/overlay/overlay-sum-used-correct-sums -! go get -d -overlay overlay.json . +! go get -overlay overlay.json . stderr '^go: updates to go.sum needed, but go.sum is part of the overlay specified with -overlay$' cmp incomplete-sum-file $WORK/overlay/overlay-sum-used-correct-sums ! go mod tidy -overlay overlay.json @@ -55,7 +55,7 @@ cd $WORK/gopath/src/overlay-and-dash-modfile go list -modfile=alternate.mod -overlay overlay.json . stdout 'found.the/module' # Even with -modfile, overlaid files can't be opened for write. -! go get -modfile=alternate.mod -overlay overlay.json -d rsc.io/quote +! go get -modfile=alternate.mod -overlay overlay.json rsc.io/quote stderr '^go: updates to go.mod needed, but go.mod is part of the overlay specified with -overlay$' # Carving out a module by adding an overlaid go.mod file @@ -77,11 +77,11 @@ go list -overlay overlay.json all ! stdout ^carve2$ stdout ^carve2/nomod$ # Editing go.mod file fails because overlay is read only -! go get -overlay overlay.json -d rsc.io/quote +! go get -overlay overlay.json rsc.io/quote stderr '^go: updates to go.mod needed, but go.mod is part of the overlay specified with -overlay$' ! grep rsc.io/quote $WORK/overlay/carve2-nomod-go.mod # Editing go.mod file succeeds because we use -modfile to redirect to same file -go get -overlay overlay.json -modfile $WORK/overlay/carve2-nomod-go.mod -d rsc.io/quote +go get -overlay overlay.json -modfile $WORK/overlay/carve2-nomod-go.mod rsc.io/quote grep rsc.io/quote $WORK/overlay/carve2-nomod-go.mod -- no-go-mod/file.go -- diff --git a/src/cmd/go/testdata/script/mod_permissions.txt b/src/cmd/go/testdata/script/mod_permissions.txt index 2d32dcd10f..77e2508cb7 100644 --- a/src/cmd/go/testdata/script/mod_permissions.txt +++ b/src/cmd/go/testdata/script/mod_permissions.txt @@ -12,7 +12,7 @@ chmod 0640 go.mod chmod 0604 go.sum go mod edit -module=golang.org/issue/34634 -go get -d +go get cmp go.mod go.mod.want cmp go.sum go.sum.want diff --git a/src/cmd/go/testdata/script/mod_proxy_list.txt b/src/cmd/go/testdata/script/mod_proxy_list.txt index 89129f4fe2..849cf2c476 100644 --- a/src/cmd/go/testdata/script/mod_proxy_list.txt +++ b/src/cmd/go/testdata/script/mod_proxy_list.txt @@ -3,34 +3,34 @@ env proxy=$GOPROXY # Proxy that can't serve should fail. env GOPROXY=$proxy/404 -! go get -d rsc.io/quote@v1.0.0 +! go get rsc.io/quote@v1.0.0 stderr '404 Not Found' # get should walk down the proxy list past 404 and 410 responses. env GOPROXY=$proxy/404,$proxy/410,$proxy -go get -d rsc.io/quote@v1.1.0 +go get rsc.io/quote@v1.1.0 # get should not walk past other 4xx errors if proxies are separated with ','. env GOPROXY=$proxy/403,$proxy -! go get -d rsc.io/quote@v1.2.0 +! go get rsc.io/quote@v1.2.0 stderr 'reading.*/403/rsc.io/.*: 403 Forbidden' # get should not walk past non-4xx errors if proxies are separated with ','. env GOPROXY=$proxy/500,$proxy -! go get -d rsc.io/quote@v1.3.0 +! go get rsc.io/quote@v1.3.0 stderr 'reading.*/500/rsc.io/.*: 500 Internal Server Error' # get should walk past other 4xx errors if proxies are separated with '|'. env GOPROXY=$proxy/403|https://0.0.0.0|$proxy -go get -d rsc.io/quote@v1.2.0 +go get rsc.io/quote@v1.2.0 # get should walk past non-4xx errors if proxies are separated with '|'. env GOPROXY=$proxy/500|https://0.0.0.0|$proxy -go get -d rsc.io/quote@v1.3.0 +go get rsc.io/quote@v1.3.0 # get should return the final error if that's all we have. env GOPROXY=$proxy/404,$proxy/410 -! go get -d rsc.io/quote@v1.4.0 +! go get rsc.io/quote@v1.4.0 stderr 'reading.*/410/rsc.io/.*: 410 Gone' -- go.mod -- diff --git a/src/cmd/go/testdata/script/mod_query_empty.txt b/src/cmd/go/testdata/script/mod_query_empty.txt index af0871173e..1c39eae574 100644 --- a/src/cmd/go/testdata/script/mod_query_empty.txt +++ b/src/cmd/go/testdata/script/mod_query_empty.txt @@ -7,14 +7,14 @@ go mod download example.com/join@v1.1.0 # reading that version should cause 'go get' to fail. env GOPROXY=file:///$WORK/badproxy cp go.mod.orig go.mod -! go get -d example.com/join/subpkg +! go get example.com/join/subpkg stderr 'go: example.com/join/subpkg@v0.0.0-20190624000000-123456abcdef: .*' # If @v/list is empty, the 'go' command should still try to resolve # other module paths. env GOPROXY=file:///$WORK/emptysub cp go.mod.orig go.mod -go get -d example.com/join/subpkg +go get example.com/join/subpkg go list -m example.com/join/... ! stdout 'example.com/join/subpkg' stdout 'example.com/join v1.1.0' @@ -23,7 +23,7 @@ stdout 'example.com/join v1.1.0' # that version is treated as nonexistent. env GOPROXY=file:///$WORK/notfound cp go.mod.orig go.mod -go get -d example.com/join/subpkg +go get example.com/join/subpkg go list -m example.com/join/... ! stdout 'example.com/join/subpkg' stdout 'example.com/join v1.1.0' @@ -39,7 +39,7 @@ stdout 'example.com/join v1.1.0' env GOPROXY=file:///$WORK/gatekeeper chmod 0000 $WORK/gatekeeper/example.com/join/subpkg/@latest cp go.mod.orig go.mod -! go get -d example.com/join/subpkg +! go get example.com/join/subpkg stderr 'go: module example.com/join/subpkg: (invalid response from proxy ".+": invalid character .+|reading file://.*/gatekeeper/example.com/join/subpkg/@latest: .+)' -- go.mod.orig -- diff --git a/src/cmd/go/testdata/script/mod_query_exclude.txt b/src/cmd/go/testdata/script/mod_query_exclude.txt index 8eae42dec6..f76b20c6d8 100644 --- a/src/cmd/go/testdata/script/mod_query_exclude.txt +++ b/src/cmd/go/testdata/script/mod_query_exclude.txt @@ -18,17 +18,17 @@ stdout '^rsc.io/quote v1.5.1$' # get excluded version cp go.exclude.mod go.exclude.mod.orig -! go get -modfile=go.exclude.mod -d rsc.io/quote@v1.5.0 +! go get -modfile=go.exclude.mod rsc.io/quote@v1.5.0 stderr '^go: rsc.io/quote@v1.5.0: excluded by go.mod$' # get non-excluded version cp go.exclude.mod.orig go.exclude.mod -go get -modfile=go.exclude.mod -d rsc.io/quote@v1.5.1 +go get -modfile=go.exclude.mod rsc.io/quote@v1.5.1 stderr 'rsc.io/quote v1.5.1' # get query with excluded version cp go.exclude.mod.orig go.exclude.mod -go get -modfile=go.exclude.mod -d rsc.io/quote@>=v1.5 +go get -modfile=go.exclude.mod rsc.io/quote@>=v1.5 go list -modfile=go.exclude.mod -m ...quote stdout 'rsc.io/quote v1.5.[1-9]' diff --git a/src/cmd/go/testdata/script/mod_readonly.txt b/src/cmd/go/testdata/script/mod_readonly.txt index d05ad2a317..9e950c3898 100644 --- a/src/cmd/go/testdata/script/mod_readonly.txt +++ b/src/cmd/go/testdata/script/mod_readonly.txt @@ -19,7 +19,7 @@ cmp go.mod go.mod.empty env GOFLAGS=-mod=readonly # update go.mod - go get allowed -go get -d rsc.io/quote +go get rsc.io/quote grep rsc.io/quote go.mod # update go.mod - go mod tidy allowed @@ -41,7 +41,7 @@ go list -m all # -mod=readonly should reject inconsistent go.mod files # (ones that would be rewritten). -go get -d rsc.io/sampler@v1.2.0 +go get rsc.io/sampler@v1.2.0 go mod edit -require rsc.io/quote@v1.5.2 cp go.mod go.mod.inconsistent ! go list @@ -81,7 +81,7 @@ stderr '^x.go:2:8: no required module provides package rsc.io/quote; to add it:\ stderr '^x.go:2:8: no required module provides package rsc.io/quote; to add it:\n\tgo get rsc.io/quote$' # However, if we didn't see an import from the main module, we should suggest -# 'go get -d' instead, because we don't know whether 'go mod tidy' would add it. +# 'go get' instead, because we don't know whether 'go mod tidy' would add it. ! go list rsc.io/quote stderr '^no required module provides package rsc.io/quote; to add it:\n\tgo get rsc.io/quote$' diff --git a/src/cmd/go/testdata/script/mod_replace.txt b/src/cmd/go/testdata/script/mod_replace.txt index a0a367fb1d..26b15518d9 100644 --- a/src/cmd/go/testdata/script/mod_replace.txt +++ b/src/cmd/go/testdata/script/mod_replace.txt @@ -42,7 +42,7 @@ stdout 'Concurrency is not parallelism.' # indicate the replacement module. cp go.mod.orig go.mod go mod edit -replace=rsc.io/quote/v3=./local/rsc.io/quote/v3 -! go get -d rsc.io/quote/v3/missing-package +! go get rsc.io/quote/v3/missing-package stderr 'module rsc.io/quote/v3@upgrade found \(v3.0.0, replaced by ./local/rsc.io/quote/v3\), but does not contain package' # The reported Dir and GoMod for a replaced module should be accurate. diff --git a/src/cmd/go/testdata/script/mod_replace_import.txt b/src/cmd/go/testdata/script/mod_replace_import.txt index 2add31f71c..7bf3a86fed 100644 --- a/src/cmd/go/testdata/script/mod_replace_import.txt +++ b/src/cmd/go/testdata/script/mod_replace_import.txt @@ -6,7 +6,7 @@ cp go.mod go.mod.orig cmp go.mod go.mod.orig # 'go list' should resolve imports using replacements. -go get -d +go get go list all stdout 'example.com/a/b$' stdout 'example.com/x/v3$' diff --git a/src/cmd/go/testdata/script/mod_replace_readonly.txt b/src/cmd/go/testdata/script/mod_replace_readonly.txt index d950d78bd3..5c1226b15e 100644 --- a/src/cmd/go/testdata/script/mod_replace_readonly.txt +++ b/src/cmd/go/testdata/script/mod_replace_readonly.txt @@ -10,7 +10,7 @@ cp go.mod go.mod.orig go mod edit -replace rsc.io/quote=./quote ! go list rsc.io/quote stderr '^module rsc.io/quote provides package rsc.io/quote and is replaced but not required; to add it:\n\tgo get rsc.io/quote$' -go get -d rsc.io/quote +go get rsc.io/quote cmp go.mod go.mod.latest go list rsc.io/quote cp go.mod.orig go.mod @@ -19,7 +19,7 @@ cp go.mod.orig go.mod go mod edit -replace rsc.io/quote@v1.0.0-doesnotexist=./quote ! go list rsc.io/quote stderr '^module rsc.io/quote provides package rsc.io/quote and is replaced but not required; to add it:\n\tgo get rsc.io/quote@v1.0.0-doesnotexist$' -go get -d rsc.io/quote@v1.0.0-doesnotexist +go get rsc.io/quote@v1.0.0-doesnotexist cmp go.mod go.mod.specific go list rsc.io/quote cp go.mod.orig go.mod diff --git a/src/cmd/go/testdata/script/mod_retract.txt b/src/cmd/go/testdata/script/mod_retract.txt index 4f95ece8d7..37aae4896d 100644 --- a/src/cmd/go/testdata/script/mod_retract.txt +++ b/src/cmd/go/testdata/script/mod_retract.txt @@ -17,7 +17,7 @@ exists $GOPATH/pkg/mod/cache/download/example.com/retract/@v/v1.0.0-bad.mod # Importing a package from a module with a retracted latest version will # select the latest non-retracted version. -go get -d ./use_self_prev +go get ./use_self_prev go list -m example.com/retract/self/prev stdout '^example.com/retract/self/prev v1.1.0$' exists $GOPATH/pkg/mod/cache/download/example.com/retract/self/prev/@v/v1.9.0.mod diff --git a/src/cmd/go/testdata/script/mod_retract_incompatible.txt b/src/cmd/go/testdata/script/mod_retract_incompatible.txt index 61538e8024..5d09532529 100644 --- a/src/cmd/go/testdata/script/mod_retract_incompatible.txt +++ b/src/cmd/go/testdata/script/mod_retract_incompatible.txt @@ -6,10 +6,10 @@ go mod init m # Request a +incompatible version retracted in v1.0.0. -go get -d example.com/retract/incompatible@v2.0.0+incompatible +go get example.com/retract/incompatible@v2.0.0+incompatible stderr '^go: warning: example.com/retract/incompatible@v2.0.0\+incompatible: retracted by module author$' # We should still see a warning if the +incompatible was previously in the # build list. -go get -d example.com/retract/incompatible@v2.0.0+incompatible +go get example.com/retract/incompatible@v2.0.0+incompatible stderr '^go: warning: example.com/retract/incompatible@v2.0.0\+incompatible: retracted by module author$' diff --git a/src/cmd/go/testdata/script/mod_retract_pseudo_base.txt b/src/cmd/go/testdata/script/mod_retract_pseudo_base.txt index d1a5e1236a..27c2b67065 100644 --- a/src/cmd/go/testdata/script/mod_retract_pseudo_base.txt +++ b/src/cmd/go/testdata/script/mod_retract_pseudo_base.txt @@ -24,11 +24,11 @@ stdout '^vcs-test.golang.org/git/retract-pseudo.git v0.0.0-20201009173747-64c061 # A retracted version is a valid base. Retraction should not validate existing # pseudo-versions, nor should it turn invalid pseudo-versions valid. -go get -d vcs-test.golang.org/git/retract-pseudo.git@v1.0.1-0.20201009173747-713affd19d7b +go get vcs-test.golang.org/git/retract-pseudo.git@v1.0.1-0.20201009173747-713affd19d7b go list -m vcs-test.golang.org/git/retract-pseudo.git stdout '^vcs-test.golang.org/git/retract-pseudo.git v1.0.1-0.20201009173747-713affd19d7b$' -! go get -d vcs-test.golang.org/git/retract-pseudo.git@v1.0.1-0.20201009173747-64c061ed4371 +! go get vcs-test.golang.org/git/retract-pseudo.git@v1.0.1-0.20201009173747-64c061ed4371 stderr '^go: vcs-test.golang.org/git/retract-pseudo.git@v1.0.1-0.20201009173747-64c061ed4371: invalid pseudo-version: tag \(v1.0.0\) found on revision 64c061ed4371 is already canonical, so should not be replaced with a pseudo-version derived from that tag$' -- retract-pseudo.sh -- diff --git a/src/cmd/go/testdata/script/mod_retract_rationale.txt b/src/cmd/go/testdata/script/mod_retract_rationale.txt index 823c384e48..92e9b7d6ea 100644 --- a/src/cmd/go/testdata/script/mod_retract_rationale.txt +++ b/src/cmd/go/testdata/script/mod_retract_rationale.txt @@ -1,5 +1,5 @@ # When there is no rationale, 'go get' should print a hard-coded message. -go get -d example.com/retract/rationale@v1.0.0-empty +go get example.com/retract/rationale@v1.0.0-empty stderr '^go: warning: example.com/retract/rationale@v1.0.0-empty: retracted by module author$' # 'go list' should print the same hard-coded message. @@ -8,7 +8,7 @@ stdout '^\[retracted by module author\]$' # When there is a multi-line message, 'go get' should print the first line. -go get -d example.com/retract/rationale@v1.0.0-multiline1 +go get example.com/retract/rationale@v1.0.0-multiline1 stderr '^go: warning: example.com/retract/rationale@v1.0.0-multiline1: retracted by module author: short description$' ! stderr 'detail' @@ -18,7 +18,7 @@ cmp stdout multiline # 'go get' output should be the same whether the retraction appears at top-level # or in a block. -go get -d example.com/retract/rationale@v1.0.0-multiline2 +go get example.com/retract/rationale@v1.0.0-multiline2 stderr '^go: warning: example.com/retract/rationale@v1.0.0-multiline2: retracted by module author: short description$' ! stderr 'detail' @@ -28,7 +28,7 @@ cmp stdout multiline # 'go get' should omit long messages. -go get -d example.com/retract/rationale@v1.0.0-long +go get example.com/retract/rationale@v1.0.0-long stderr '^go: warning: example.com/retract/rationale@v1.0.0-long: retracted by module author: \(message omitted: too long\)' # 'go list' should show the full message. @@ -37,7 +37,7 @@ stdout '^\[lo{500}ng\]$' # 'go get' should omit messages with unprintable characters. -go get -d example.com/retract/rationale@v1.0.0-unprintable +go get example.com/retract/rationale@v1.0.0-unprintable stderr '^go: warning: example.com/retract/rationale@v1.0.0-unprintable: retracted by module author: \(message omitted: contains non-printable characters\)' # 'go list' should show the full message. @@ -61,9 +61,9 @@ go list -m -retracted -f '{{range .Retracted}}{{.}},{{end}}' example.com/retract stdout '^single version,degenerate range,$' # 'go get' will only report the first retraction to avoid being too verbose. -go get -d example.com/retract/rationale@v1.0.0-order +go get example.com/retract/rationale@v1.0.0-order stderr '^go: warning: example.com/retract/rationale@v1.0.0-order: retracted by module author: degenerate range$' -go get -d example.com/retract/rationale@v1.0.1-order +go get example.com/retract/rationale@v1.0.1-order stderr '^go: warning: example.com/retract/rationale@v1.0.1-order: retracted by module author: single version$' -- go.mod -- diff --git a/src/cmd/go/testdata/script/mod_retract_rename.txt b/src/cmd/go/testdata/script/mod_retract_rename.txt index f54742c523..38986f333f 100644 --- a/src/cmd/go/testdata/script/mod_retract_rename.txt +++ b/src/cmd/go/testdata/script/mod_retract_rename.txt @@ -1,5 +1,5 @@ # Populate go.sum. -go get -d +go get # 'go list -m -retracted' should load retractions, even if the version # containing retractions has a different module path. @@ -9,11 +9,11 @@ go list -m -retracted -f '{{with .Retracted}}retracted{{end}}' example.com/retra go list -m -u -f '{{with .Retracted}}retracted{{end}}' example.com/retract/rename # 'go get' should warn about the retracted version. -go get -d +go get stderr '^go: warning: example.com/retract/rename@v1.0.0-bad: retracted by module author: bad$' # We can't upgrade, since this latest version has a different module path. -! go get -d example.com/retract/rename +! go get example.com/retract/rename stderr 'module declares its path as: example.com/retract/newname' -- go.mod -- diff --git a/src/cmd/go/testdata/script/mod_retract_replace.txt b/src/cmd/go/testdata/script/mod_retract_replace.txt index 9cd714739a..788968f420 100644 --- a/src/cmd/go/testdata/script/mod_retract_replace.txt +++ b/src/cmd/go/testdata/script/mod_retract_replace.txt @@ -2,7 +2,7 @@ # obtain retractions from the replacement. # Populate go.sum. -go get -d +go get # The latest version, v1.9.0, is not available on the proxy. go list -m -retracted example.com/retract/missingmod diff --git a/src/cmd/go/testdata/script/mod_sum_lookup.txt b/src/cmd/go/testdata/script/mod_sum_lookup.txt index e021921380..7513f7f49f 100644 --- a/src/cmd/go/testdata/script/mod_sum_lookup.txt +++ b/src/cmd/go/testdata/script/mod_sum_lookup.txt @@ -8,7 +8,7 @@ go list -e -mod=mod -tags=ignore ./noexist # When an import is resolved successfully, we should only save hashes for # the module that provides the package, not for other modules looked up. # Verifies golang.org/issue/31580. -go get -d ./exist +go get ./exist grep '^example.com/join v1.1.0 h1:' go.sum ! grep '^example.com/join/subpkg' go.sum cp go.sum go.list.sum diff --git a/src/cmd/go/testdata/script/mod_sum_replaced.txt b/src/cmd/go/testdata/script/mod_sum_replaced.txt index b03982d9cf..6c322a00d6 100644 --- a/src/cmd/go/testdata/script/mod_sum_replaced.txt +++ b/src/cmd/go/testdata/script/mod_sum_replaced.txt @@ -1,7 +1,7 @@ env GO111MODULE=on -# After 'go get -d', the go.sum file should contain the sum for the module. -go get -d rsc.io/quote@v1.5.0 +# After 'go get', the go.sum file should contain the sum for the module. +go get rsc.io/quote@v1.5.0 grep 'rsc.io/quote v1.5.0' go.sum # If we replace the module and run 'go mod tidy', we should get a sum for the replacement. diff --git a/src/cmd/go/testdata/script/mod_sumdb.txt b/src/cmd/go/testdata/script/mod_sumdb.txt index dd791be1d4..d06db4ae69 100644 --- a/src/cmd/go/testdata/script/mod_sumdb.txt +++ b/src/cmd/go/testdata/script/mod_sumdb.txt @@ -8,13 +8,13 @@ env dbname=localhost.localdev/sumdb # (this also populates tiles on the sumdb server). cp go.mod.orig go.mod env GOSUMDB=$sumdb' '$proxy/sumdb-wrong -! go get -d rsc.io/quote +! go get rsc.io/quote stderr 'go: rsc.io/quote@v1.5.2: verifying module: checksum mismatch' stderr 'downloaded: h1:3fEy' stderr 'localhost.localdev/sumdb: h1:wrong' stderr 'SECURITY ERROR\nThis download does NOT match the one reported by the checksum server.' -! go get -d rsc.io/sampler -! go get -d golang.org/x/text +! go get rsc.io/sampler +! go get golang.org/x/text go mod edit -require rsc.io/quote@v1.5.2 ! go mod tidy @@ -26,14 +26,14 @@ rm go.sum # switching to truthful sumdb detects timeline inconsistency cp go.mod.orig go.mod env GOSUMDB=$sumdb -! go get -d rsc.io/fortune +! go get rsc.io/fortune stderr 'SECURITY ERROR\ngo.sum database server misbehavior detected!' stderr 'proof of misbehavior:' # removing the cached wrong tree head and cached tiles clears the bad data rm $GOPATH/pkg/sumdb/$dbname/latest go clean -modcache -go get -d rsc.io/fortune +go get rsc.io/fortune -- go.mod.orig -- module m diff --git a/src/cmd/go/testdata/script/mod_sumdb_cache.txt b/src/cmd/go/testdata/script/mod_sumdb_cache.txt index 1b38475fb5..063fd20964 100644 --- a/src/cmd/go/testdata/script/mod_sumdb_cache.txt +++ b/src/cmd/go/testdata/script/mod_sumdb_cache.txt @@ -7,40 +7,40 @@ env GOPROXY GONOPROXY GOSUMDB GONOSUMDB cp go.mod.orig go.mod rm go.sum env GOPROXY=$proxy/sumdb-503 -! go get -d rsc.io/quote +! go get rsc.io/quote stderr 503 # fetch through working proxy is OK cp go.mod.orig go.mod rm go.sum env GOPROXY=$proxy -go get -d rsc.io/quote +go get rsc.io/quote # repeated fetch works entirely from cache, does not consult sumdb cp go.mod.orig go.mod rm go.sum env GOPROXY=$proxy/sumdb-503 -go get -d rsc.io/quote +go get rsc.io/quote rm go.sum # fetch specific module can work without proxy, using cache or go.sum cp go.mod.orig go.mod rm go.sum env GOPROXY=off -go get -d rsc.io/quote@v1.5.2 # using cache +go get rsc.io/quote@v1.5.2 # using cache rm $GOPATH/pkg/mod/cache/download/sumdb/localhost.localdev/sumdb/lookup/rsc.io/quote@v1.5.2 -go get -d rsc.io/quote@v1.5.2 # using go.sum +go get rsc.io/quote@v1.5.2 # using go.sum # fetch fails once we lose access to both cache and go.sum rm go.sum env GOPROXY=$proxy/sumdb-504 -! go get -d rsc.io/quote@v1.5.2 +! go get rsc.io/quote@v1.5.2 stderr 504 # GOINSECURE does not bypass checksum lookup env GOINSECURE=rsc.io env GOPROXY=$proxy/sumdb-504 -! go get -d rsc.io/quote@v1.5.2 +! go get rsc.io/quote@v1.5.2 stderr 504 -- go.mod.orig -- diff --git a/src/cmd/go/testdata/script/mod_sumdb_file_path.txt b/src/cmd/go/testdata/script/mod_sumdb_file_path.txt index 575c7c4817..a834c4800d 100644 --- a/src/cmd/go/testdata/script/mod_sumdb_file_path.txt +++ b/src/cmd/go/testdata/script/mod_sumdb_file_path.txt @@ -12,7 +12,7 @@ env GOPATH=$WORK/gopath1 # It comes from the sumweb package, which isn't yet producing structured errors. [windows] env GOPROXY=file:///$WORK/sumproxy,https://proxy.golang.org [!windows] env GOPROXY=file://$WORK/sumproxy,https://proxy.golang.org -! go get -d golang.org/x/text@v0.3.2 +! go get golang.org/x/text@v0.3.2 stderr '^go: golang.org/x/text@v0.3.2: verifying module: golang.org/x/text@v0.3.2: reading file://.*/sumdb/sum.golang.org/lookup/golang.org/x/text@v0.3.2: (no such file or directory|.*cannot find the path specified.*)' # If the proxy does not claim to support the database, @@ -20,7 +20,7 @@ stderr '^go: golang.org/x/text@v0.3.2: verifying module: golang.org/x/text@v0.3. # and downloading should succeed. [windows] env GOPROXY=file:///$WORK/emptyproxy,https://proxy.golang.org [!windows] env GOPROXY=file://$WORK/emptyproxy,https://proxy.golang.org -go get -d golang.org/x/text@v0.3.2 +go get golang.org/x/text@v0.3.2 # After a successful sumdb lookup, the lookup can be repeated # using the download cache as a proxy. @@ -29,7 +29,7 @@ cp supported $GOPATH/pkg/mod/cache/download/sumdb/sum.golang.org/supported [!windows] env GOPROXY=file://$WORK/gopath1/pkg/mod/cache/download,file://$WORK/sumproxy env GOPATH=$WORK/gopath2 rm go.sum -go get -d -x -v golang.org/x/text@v0.3.2 +go get -x -v golang.org/x/text@v0.3.2 # Once the checksum is present in the go.sum file, # an empty file-based sumdb can be used in conjunction with @@ -38,10 +38,10 @@ grep golang.org/x/text go.sum env GOPATH=$WORK/gopath3 [windows] env GOPROXY=file:///$WORK/sumproxy [!windows] env GOPROXY=file://$WORK/sumproxy -! go get -d golang.org/x/text@v0.3.2 +! go get golang.org/x/text@v0.3.2 [windows] env GOPROXY=file:///$WORK/sumproxy,https://proxy.golang.org [!windows] env GOPROXY=file://$WORK/sumproxy,https://proxy.golang.org -go get -d golang.org/x/text@v0.3.2 +go get golang.org/x/text@v0.3.2 -- supported -- diff --git a/src/cmd/go/testdata/script/mod_sumdb_golang.txt b/src/cmd/go/testdata/script/mod_sumdb_golang.txt index becd88b52e..a48a5ba1b0 100644 --- a/src/cmd/go/testdata/script/mod_sumdb_golang.txt +++ b/src/cmd/go/testdata/script/mod_sumdb_golang.txt @@ -16,7 +16,7 @@ stdout '^sum.golang.org$' env GOSUMDB=sum.golang.org env GOPROXY=direct -go get -d rsc.io/quote@v1.5.2 +go get rsc.io/quote@v1.5.2 cp go.sum saved.sum diff --git a/src/cmd/go/testdata/script/mod_sumdb_proxy.txt b/src/cmd/go/testdata/script/mod_sumdb_proxy.txt index 70b8e3fc44..194c0c92e5 100644 --- a/src/cmd/go/testdata/script/mod_sumdb_proxy.txt +++ b/src/cmd/go/testdata/script/mod_sumdb_proxy.txt @@ -5,14 +5,14 @@ env GOPROXY GONOPROXY GOSUMDB GONOSUMDB # basic fetch (through proxy) works cp go.mod.orig go.mod -go get -d rsc.io/fortune@v1.0.0 # note: must use test proxy, does not exist in real world +go get rsc.io/fortune@v1.0.0 # note: must use test proxy, does not exist in real world rm $GOPATH/pkg/mod/cache/download/sumdb # rm sumdb cache but NOT package download cache rm go.sum # can fetch by explicit URL cp go.mod.orig go.mod env GOSUMDB=$sumdb' '$proxy/sumdb-direct -go get -d rsc.io/fortune@v1.0.0 +go get rsc.io/fortune@v1.0.0 rm $GOPATH/pkg/mod/cache/download/sumdb rm go.sum @@ -21,7 +21,7 @@ rm go.sum cp go.mod.orig go.mod env GOSUMDB=$sumdb env GOPROXY=direct -! go get -d rsc.io/fortune@v1.0.0 +! go get rsc.io/fortune@v1.0.0 stderr 'verifying module: rsc.io/fortune@v1.0.0: .*: no such host localhost.localdev' rm $GOPATH/pkg/mod/cache/download/sumdb rm go.sum @@ -30,7 +30,7 @@ rm go.sum cp go.mod.orig go.mod env GOSUMDB=$sumdb env GOPROXY=$proxy/sumdb-404 -! go get -d rsc.io/fortune@v1.0.0 +! go get rsc.io/fortune@v1.0.0 stderr 'verifying.*localhost.localdev' rm $GOPATH/pkg/mod/cache/download/sumdb rm go.sum @@ -39,7 +39,7 @@ rm go.sum cp go.mod.orig go.mod env GOSUMDB=$sumdb env GOPROXY=$proxy/sumdb-503 -! go get -d rsc.io/fortune@v1.0.0 +! go get rsc.io/fortune@v1.0.0 stderr '503 Service Unavailable' rm $GOPATH/pkg/mod/cache/download/sumdb rm go.sum @@ -48,7 +48,7 @@ rm go.sum cp go.mod.orig go.mod env GOSUMDB=$sumdb env GOPROXY=$proxy/sumdb-404,$proxy/sumdb-503 -! go get -d rsc.io/fortune@v1.0.0 +! go get rsc.io/fortune@v1.0.0 stderr '503 Service Unavailable' rm $GOPATH/pkg/mod/cache/download/sumdb rm go.sum @@ -57,7 +57,7 @@ rm go.sum cp go.mod.orig go.mod env GOSUMDB=$sumdb env GOPROXY=$proxy/sumdb-503|https://0.0.0.0|$proxy -go get -d rsc.io/fortune@v1.0.0 +go get rsc.io/fortune@v1.0.0 rm $GOPATH/pkg/mod/cache/download/sumdb rm go.sum diff --git a/src/cmd/go/testdata/script/mod_symlink.txt b/src/cmd/go/testdata/script/mod_symlink.txt index dbc23fb8f0..0604e1a4c4 100644 --- a/src/cmd/go/testdata/script/mod_symlink.txt +++ b/src/cmd/go/testdata/script/mod_symlink.txt @@ -1,12 +1,12 @@ env GO111MODULE=on [!symlink] skip -# 'go get -d' should resolve modules of imported packages. -go get -d +# 'go get' should resolve modules of imported packages. +go get go list -deps -f '{{.Module}}' . stdout golang.org/x/text -go get -d ./subpkg +go get ./subpkg go list -deps -f '{{.Module}}' ./subpkg stdout golang.org/x/text diff --git a/src/cmd/go/testdata/script/mod_tidy_convergence.txt b/src/cmd/go/testdata/script/mod_tidy_convergence.txt index 09c46f764b..be0a8e9b8c 100644 --- a/src/cmd/go/testdata/script/mod_tidy_convergence.txt +++ b/src/cmd/go/testdata/script/mod_tidy_convergence.txt @@ -79,7 +79,7 @@ cmp go.mod go.mod.tidye # succeed and remain stable. y.1 does not upgrade x, and can therefore be used # with it. -go get -d example.net/x@v0.1.0 example.net/y@v0.1.0 +go get example.net/x@v0.1.0 example.net/y@v0.1.0 go mod tidy cmp go.mod go.mod.postget @@ -96,7 +96,7 @@ cmp go.mod go.mod.tidye stderr '^go: found example\.net/y in example\.net/y v0.2.0$' stderr '^example\.net/m imports\n\texample\.net/x: package example\.net/x provided by example\.net/x at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$' -go get -d example.net/x@v0.1.0 example.net/y@v0.1.0 +go get example.net/x@v0.1.0 example.net/y@v0.1.0 go mod tidy cmp go.mod go.mod.postget-117 diff --git a/src/cmd/go/testdata/script/mod_tidy_convergence_loop.txt b/src/cmd/go/testdata/script/mod_tidy_convergence_loop.txt index 3c4d3244d5..99599e551a 100644 --- a/src/cmd/go/testdata/script/mod_tidy_convergence_loop.txt +++ b/src/cmd/go/testdata/script/mod_tidy_convergence_loop.txt @@ -94,7 +94,7 @@ cmp go.mod go.mod.orig # packages simultaneously over-upgrades all of the dependencies, and 'go mod # tidy' treats "no package can be added" as a terminal state. -go get -d example.net/w@v0.2.0-pre example.net/x@v0.2.0-pre example.net/y@v0.2.0-pre example.net/z@v0.2.0-pre +go get example.net/w@v0.2.0-pre example.net/x@v0.2.0-pre example.net/y@v0.2.0-pre example.net/z@v0.2.0-pre go mod tidy -e cmp go.mod go.mod.postget go mod tidy -e @@ -154,7 +154,7 @@ cmp go.mod go.mod.117 # As in the eager case, for the lazy module the fully-upgraded dependency graph # becomes empty, and the empty graph is stable. -go get -d example.net/w@v0.2.0-pre example.net/x@v0.2.0-pre example.net/y@v0.2.0-pre example.net/z@v0.2.0-pre +go get example.net/w@v0.2.0-pre example.net/x@v0.2.0-pre example.net/y@v0.2.0-pre example.net/z@v0.2.0-pre go mod tidy -e cmp go.mod go.mod.postget go mod tidy -e diff --git a/src/cmd/go/testdata/script/mod_tidy_replace.txt b/src/cmd/go/testdata/script/mod_tidy_replace.txt index 297f6a6a45..274f3bf509 100644 --- a/src/cmd/go/testdata/script/mod_tidy_replace.txt +++ b/src/cmd/go/testdata/script/mod_tidy_replace.txt @@ -35,7 +35,7 @@ grep 'golang.org/x/text' go.mod # 'go get' and 'go mod tidy' should follow the requirements of the replacements, # not the originals, even if that results in a set of versions that are # misleading or redundant without those replacements. -go get -d rsc.io/sampler@v1.2.0 +go get rsc.io/sampler@v1.2.0 go mod tidy go list -m all stdout 'rsc.io/quote/v3 v3.0.0' diff --git a/src/cmd/go/testdata/script/mod_tidy_sum.txt b/src/cmd/go/testdata/script/mod_tidy_sum.txt index c583f56058..5a15818543 100644 --- a/src/cmd/go/testdata/script/mod_tidy_sum.txt +++ b/src/cmd/go/testdata/script/mod_tidy_sum.txt @@ -1,12 +1,12 @@ env GO111MODULE=on # go.sum should list directly used modules and dependencies -go get -d rsc.io/quote@v1.5.2 +go get rsc.io/quote@v1.5.2 go mod tidy grep rsc.io/sampler go.sum # go.sum should not normally lose old entries -go get -d rsc.io/quote@v1.0.0 +go get rsc.io/quote@v1.0.0 grep 'rsc.io/quote v1.0.0' go.sum grep 'rsc.io/quote v1.5.2' go.sum grep rsc.io/sampler go.sum diff --git a/src/cmd/go/testdata/script/mod_upgrade_patch.txt b/src/cmd/go/testdata/script/mod_upgrade_patch.txt index b8c178c75e..79a9808ef0 100644 --- a/src/cmd/go/testdata/script/mod_upgrade_patch.txt +++ b/src/cmd/go/testdata/script/mod_upgrade_patch.txt @@ -2,7 +2,7 @@ env GO111MODULE=on [short] skip # Initially, we are at v1.0.0 for all dependencies. -go get -d +go get cp go.mod go.mod.orig go list -m all stdout '^patch.example.com/direct v1.0.0' @@ -10,7 +10,7 @@ stdout '^patch.example.com/indirect v1.0.0' ! stdout '^patch.example.com/depofdirectpatch' # @patch should be rejected for modules not already in the build list. -! go get -d patch.example.com/depofdirectpatch@patch +! go get patch.example.com/depofdirectpatch@patch stderr '^go: can''t query version "patch" of module patch.example.com/depofdirectpatch: no existing version is required$' cmp go.mod.orig go.mod @@ -18,7 +18,7 @@ cmp go.mod.orig go.mod # of the package in the current directory, pulling in transitive dependencies # and also patching those. cp go.mod.orig go.mod -go get -d -u=patch +go get -u=patch go list -m all stdout '^patch.example.com/direct v1.0.1' stdout '^patch.example.com/indirect v1.0.1' @@ -26,7 +26,7 @@ stdout '^patch.example.com/depofdirectpatch v1.0.0' # 'get all@patch' should patch the modules that provide packages in 'all'. cp go.mod.orig go.mod -go get -d all@patch +go get all@patch go list -m all stdout '^patch.example.com/direct v1.0.1' stdout '^patch.example.com/indirect v1.0.1' @@ -37,14 +37,14 @@ stdout '^patch.example.com/depofdirectpatch v1.0.0' cp go.mod.orig go.mod go mod edit -droprequire=patch.example.com/direct cp go.mod go.mod.dropped -! go get -d all@patch +! go get all@patch stderr '^go: all@patch: can''t query version "patch" of module patch.example.com/direct: no existing version is required$' cmp go.mod.dropped go.mod # Requesting the direct dependency with -u=patch but without an explicit version # should patch-update it and its dependencies. cp go.mod.orig go.mod -go get -d -u=patch patch.example.com/direct +go get -u=patch patch.example.com/direct go list -m all stdout '^patch.example.com/direct v1.0.1' stdout '^patch.example.com/indirect v1.0.1' @@ -52,7 +52,7 @@ stdout '^patch.example.com/depofdirectpatch v1.0.0' # Requesting only the indirect dependency should not update the direct one. cp go.mod.orig go.mod -go get -d -u=patch patch.example.com/indirect +go get -u=patch patch.example.com/indirect go list -m all stdout '^patch.example.com/direct v1.0.0' stdout '^patch.example.com/indirect v1.0.1' @@ -61,7 +61,7 @@ stdout '^patch.example.com/indirect v1.0.1' # @patch should apply only to the specific module, # but the result must reflect its upgraded requirements. cp go.mod.orig go.mod -go get -d patch.example.com/direct@patch +go get patch.example.com/direct@patch go list -m all stdout '^patch.example.com/direct v1.0.1' stdout '^patch.example.com/indirect v1.0.0' @@ -69,7 +69,7 @@ stdout '^patch.example.com/depofdirectpatch v1.0.0' # An explicit @patch should override a general -u. cp go.mod.orig go.mod -go get -d -u patch.example.com/direct@patch +go get -u patch.example.com/direct@patch go list -m all stdout '^patch.example.com/direct v1.0.1' stdout '^patch.example.com/indirect v1.1.0' @@ -77,7 +77,7 @@ stdout '^patch.example.com/depofdirectpatch v1.0.0' # An explicit @latest should override a general -u=patch. cp go.mod.orig go.mod -go get -d -u=patch patch.example.com/direct@latest +go get -u=patch patch.example.com/direct@latest go list -m all stdout '^patch.example.com/direct v1.1.0' stdout '^patch.example.com/indirect v1.0.1' @@ -89,13 +89,13 @@ cp go.mod.orig go.mod stderr 'go: can''t request explicit version "patch" of standard library package cmd/vet$' # However, standard-library packages without explicit versions are fine. -go get -d -u=patch -d cmd/go +go get -u=patch cmd/go # We can upgrade to a new version of a module with no root package. -go get -d example.com/noroot@v1.0.0 +go get example.com/noroot@v1.0.0 go list -m all stdout '^example.com/noroot v1.0.0$' -go get -d example.com/noroot@patch +go get example.com/noroot@patch go list -m all stdout '^example.com/noroot v1.0.1$' diff --git a/src/cmd/go/testdata/script/mod_vcs_missing.txt b/src/cmd/go/testdata/script/mod_vcs_missing.txt index f8be43cf4c..9e6e371927 100644 --- a/src/cmd/go/testdata/script/mod_vcs_missing.txt +++ b/src/cmd/go/testdata/script/mod_vcs_missing.txt @@ -5,7 +5,7 @@ env GO111MODULE=on env GOPROXY=direct cd empty -! go get -d launchpad.net/gocheck +! go get launchpad.net/gocheck stderr '"bzr": executable file not found' cd .. diff --git a/src/cmd/go/testdata/script/mod_vendor_auto.txt b/src/cmd/go/testdata/script/mod_vendor_auto.txt index 96db5c1600..3cace73a89 100644 --- a/src/cmd/go/testdata/script/mod_vendor_auto.txt +++ b/src/cmd/go/testdata/script/mod_vendor_auto.txt @@ -177,7 +177,7 @@ stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]version$' # 'go get' should update from the network or module cache, # even if a vendor directory is present. -go get -d example.com/version@v1.1.0 +go get example.com/version@v1.1.0 ! go list -f {{.Dir}} -tags tools all stderr '^go: inconsistent vendoring' diff --git a/src/cmd/go/testdata/script/mod_vendor_build.txt b/src/cmd/go/testdata/script/mod_vendor_build.txt index 3b8eec0119..4efda55e08 100644 --- a/src/cmd/go/testdata/script/mod_vendor_build.txt +++ b/src/cmd/go/testdata/script/mod_vendor_build.txt @@ -10,7 +10,7 @@ stdout rsc.io/sampler ! grep 'rsc.io/sampler v1.3.0' go.mod # update to v1.3.1, now indirect in go.mod. -go get -d rsc.io/sampler@v1.3.1 +go get rsc.io/sampler@v1.3.1 grep 'rsc.io/sampler v1.3.1 // indirect' go.mod cp go.mod go.mod.good diff --git a/src/cmd/go/testdata/script/mod_verify.txt b/src/cmd/go/testdata/script/mod_verify.txt index f02d15aa28..018709e33b 100644 --- a/src/cmd/go/testdata/script/mod_verify.txt +++ b/src/cmd/go/testdata/script/mod_verify.txt @@ -54,7 +54,7 @@ go mod verify # Packages below module root should not be mentioned in go.sum. rm go.sum go mod edit -droprequire rsc.io/quote -go get -d rsc.io/quote/buggy +go get rsc.io/quote/buggy grep '^rsc.io/quote v1.5.2/go.mod ' go.sum ! grep buggy go.sum diff --git a/src/cmd/go/testdata/script/modfile_flag.txt b/src/cmd/go/testdata/script/modfile_flag.txt index 7cce581e55..398e523a9c 100644 --- a/src/cmd/go/testdata/script/modfile_flag.txt +++ b/src/cmd/go/testdata/script/modfile_flag.txt @@ -46,7 +46,7 @@ go list -mod=mod . grep rsc.io/quote go.alt.mod go build -n -mod=mod . go test -n -mod=mod . -go get -d rsc.io/quote +go get rsc.io/quote # 'go mod vendor' should work. diff --git a/src/cmd/go/testdata/script/vendor_list_issue11977.txt b/src/cmd/go/testdata/script/vendor_list_issue11977.txt index ce2e29f99a..cdab33c089 100644 --- a/src/cmd/go/testdata/script/vendor_list_issue11977.txt +++ b/src/cmd/go/testdata/script/vendor_list_issue11977.txt @@ -2,7 +2,7 @@ [!exec:git] skip env GO111MODULE=off -go get -d github.com/rsc/go-get-issue-11864 +go get github.com/rsc/go-get-issue-11864 go list -f '{{join .TestImports "\n"}}' github.com/rsc/go-get-issue-11864/t stdout 'go-get-issue-11864/vendor/vendor.org/p' diff --git a/src/cmd/go/testdata/script/version.txt b/src/cmd/go/testdata/script/version.txt index f3aa57e8c7..8c08bae725 100644 --- a/src/cmd/go/testdata/script/version.txt +++ b/src/cmd/go/testdata/script/version.txt @@ -20,7 +20,7 @@ env GO111MODULE=on [short] skip # Check that 'go version' and 'go version -m' work on a binary built in module mode. -go get -d rsc.io/fortune +go get rsc.io/fortune go build -o fortune.exe rsc.io/fortune go version fortune.exe stdout '^fortune.exe: .+' diff --git a/src/cmd/go/testdata/script/version_replace.txt b/src/cmd/go/testdata/script/version_replace.txt index ec98f4e3f3..82b8504458 100644 --- a/src/cmd/go/testdata/script/version_replace.txt +++ b/src/cmd/go/testdata/script/version_replace.txt @@ -1,7 +1,7 @@ [short] skip go mod download example.com/printversion@v0.1.0 example.com/printversion@v1.0.0 -go get -d example.com/printversion@v0.1.0 +go get example.com/printversion@v0.1.0 go install example.com/printversion go run example.com/printversion -- GitLab From 3a555977fc9db6b51a9198b3d70921d41bc40e2e Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Fri, 24 Sep 2021 13:54:52 -0700 Subject: [PATCH 1356/2500] cmd/go: add release note for 'go get' changes For #43684 Change-Id: I9ce47de82203ec87e7d3683f56e6c6d61ae255f5 Reviewed-on: https://go-review.googlesource.com/c/go/+/352151 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- doc/go1.18.html | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/doc/go1.18.html b/doc/go1.18.html index 63715ef0d6..8a5ba487a9 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -43,6 +43,25 @@ Do not send CLs removing the interior tags from such phrases.

Go command

+

+ go get no longer builds or installs packages in + module-aware mode. go get is now dedicated to + adjusting dependencies in go.mod. Effectively, the + -d flag is always enabled. To install the latest version + of an executable outside the context of the current module, use + go + install example.com/cmd@latest. Any + version query + may be used instead of latest. This form of go + install was added in Go 1.16, so projects supporting older + versions may need to provide install instructions for both go + install and go get. go + get now reports an error when used outside a module, since there + is no go.mod file to update. In GOPATH mode (with + GO111MODULE=off), go get still builds + and installs packages, as before. +

+

TODO: complete this section, or delete if not needed

-- GitLab From 8cf0a087c00db2e9ba24f763db903adcbffaade4 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 28 Sep 2021 09:56:38 -0700 Subject: [PATCH 1357/2500] cmd/compile/internal/types2: add Interface.IsMethodSet, remove Interface.IsContraint This is a port of CL 352616 from go/types to types2. It also removes Interface.IsConstraint and adjusts all uses to use IsMethodSet. The dual changes are made to the (unexported) type set implementation. Change-Id: I292b741d1f7cdbaefb483eed75faf7b85a8d2792 Reviewed-on: https://go-review.googlesource.com/c/go/+/352872 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/noder/writer.go | 2 +- src/cmd/compile/internal/types2/call.go | 2 +- src/cmd/compile/internal/types2/decl.go | 2 +- src/cmd/compile/internal/types2/interface.go | 4 ++-- src/cmd/compile/internal/types2/typeset.go | 4 ++-- src/cmd/compile/internal/types2/typexpr.go | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 47de992033..dde42c85d6 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -1687,7 +1687,7 @@ func (w *writer) pkgDecl(decl syntax.Decl) { name := w.p.info.Defs[decl.Name].(*types2.TypeName) // Skip type declarations for interfaces that are only usable as // type parameter bounds. - if iface, ok := name.Type().Underlying().(*types2.Interface); ok && iface.IsConstraint() { + if iface, ok := name.Type().Underlying().(*types2.Interface); ok && !iface.IsMethodSet() { break } diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 5cf292ce8a..118e76fdcf 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -103,7 +103,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { check.expr(x, call.ArgList[0]) if x.mode != invalid { if t := asInterface(T); t != nil { - if t.IsConstraint() { + if !t.IsMethodSet() { check.errorf(call, "cannot use interface %s in conversion (contains type list or is comparable)", T) break } diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index ab2e3b875f..326763d9b7 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -534,7 +534,7 @@ func (check *Checker) isImportedConstraint(typ Type) bool { return false } u, _ := named.under().(*Interface) - return u != nil && u.IsConstraint() + return u != nil && !u.IsMethodSet() } func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named) { diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index 340df51524..8a6bc75c43 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -98,8 +98,8 @@ func (t *Interface) Empty() bool { return t.typeSet().IsAll() } // IsComparable reports whether each type in interface t's type set is comparable. func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() } -// IsConstraint reports whether interface t is not just a method set. -func (t *Interface) IsConstraint() bool { return t.typeSet().IsConstraint() } +// IsMethodSet reports whether the interface t is fully described by its method set. +func (t *Interface) IsMethodSet() bool { return t.typeSet().IsMethodSet() } func (t *Interface) Underlying() Type { return t } func (t *Interface) String() string { return TypeString(t, nil) } diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index c56aa56e2e..37030b2ca1 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -30,8 +30,8 @@ func (s *_TypeSet) IsAll() bool { return !s.comparable && len(s.methods) == 0 && s.terms.isAll() } -// IsConstraint reports whether type set s is not just a set of methods. -func (s *_TypeSet) IsConstraint() bool { return s.comparable || !s.terms.isAll() } +// IsMethodSet reports whether the interface t is fully described by its method set. +func (s *_TypeSet) IsMethodSet() bool { return !s.comparable && s.terms.isAll() } // IsComparable reports whether each type in the set is comparable. func (s *_TypeSet) IsComparable() bool { diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 3bfce2ebf2..62cfda825f 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -143,7 +143,7 @@ func (check *Checker) varType(e syntax.Expr) Type { if t := asInterface(typ); t != nil { pos := syntax.StartPos(e) tset := computeInterfaceTypeSet(check, pos, t) // TODO(gri) is this the correct position? - if tset.IsConstraint() { + if !tset.IsMethodSet() { if tset.comparable { check.softErrorf(pos, "interface is (or embeds) comparable") } else { -- GitLab From 84ba117fd7446030f93ab679d5c819dc028ad881 Mon Sep 17 00:00:00 2001 From: Leonard Wang Date: Sat, 11 Sep 2021 20:53:24 +0800 Subject: [PATCH 1358/2500] runtime: add mp parameter for getMCache Since all callers of getMCache appear to have mp available, we pass the mp to getMCache, and reduce one call to getg. And after modification, getMCache is also inlined. Change-Id: Ib7880c118336acc026ecd7c60c5a88722c3ddfc7 Reviewed-on: https://go-review.googlesource.com/c/go/+/349329 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Michael Knyszek Trust: Michael Knyszek Trust: Carlos Amedee --- src/runtime/malloc.go | 4 ++-- src/runtime/mcache.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index f8d5d48a28..7affe244a2 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -972,7 +972,7 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { shouldhelpgc := false dataSize := size - c := getMCache() + c := getMCache(mp) if c == nil { throw("mallocgc called without a P or outside bootstrapping") } @@ -1247,7 +1247,7 @@ func reflect_unsafe_NewArray(typ *_type, n int) unsafe.Pointer { } func profilealloc(mp *m, x unsafe.Pointer, size uintptr) { - c := getMCache() + c := getMCache(mp) if c == nil { throw("profilealloc called without a P or outside bootstrapping") } diff --git a/src/runtime/mcache.go b/src/runtime/mcache.go index a9e959109a..21c36ca750 100644 --- a/src/runtime/mcache.go +++ b/src/runtime/mcache.go @@ -122,9 +122,9 @@ func freemcache(c *mcache) { // // Returns nil if we're not bootstrapping or we don't have a P. The caller's // P must not change, so we must be in a non-preemptible state. -func getMCache() *mcache { +func getMCache(mp *m) *mcache { // Grab the mcache, since that's where stats live. - pp := getg().m.p.ptr() + pp := mp.p.ptr() var c *mcache if pp == nil { // We will be called without a P while bootstrapping, -- GitLab From 9c43872bd831396ccf637f4569a18d784d1e9bce Mon Sep 17 00:00:00 2001 From: Lynn Boger Date: Mon, 27 Sep 2021 07:48:33 -0500 Subject: [PATCH 1359/2500] reflect,runtime: add reflect support for regabi on PPC64 This adds the regabi support needed for reflect including: - implementation of the makeFuncSub and methodValueCall for reflect - implementations of archFloat32FromReg and archFloat32ToReg needed for PPC64 due to differences in the way float32 are represented in registers as compared to other platforms - change needed to stack.go due to the functions that are changed above Change-Id: Ida40d831370e39b91711ccb9616492b7fad3debf Reviewed-on: https://go-review.googlesource.com/c/go/+/352429 Run-TryBot: Lynn Boger Reviewed-by: Cherry Mui TryBot-Result: Go Bot Trust: Lynn Boger --- src/reflect/asm_ppc64x.s | 74 ++++++++++++++++++++++++------- src/reflect/float32reg_generic.go | 3 ++ src/reflect/float32reg_ppc64x.s | 31 +++++++++++++ src/reflect/stubs_ppc64x.go | 11 +++++ src/runtime/stack.go | 2 +- 5 files changed, 104 insertions(+), 17 deletions(-) create mode 100644 src/reflect/float32reg_ppc64x.s create mode 100644 src/reflect/stubs_ppc64x.go diff --git a/src/reflect/asm_ppc64x.s b/src/reflect/asm_ppc64x.s index d955e4110f..1ccfb25b94 100644 --- a/src/reflect/asm_ppc64x.s +++ b/src/reflect/asm_ppc64x.s @@ -9,34 +9,76 @@ #include "funcdata.h" #include "asm_ppc64x.h" +// The frames of each of the two functions below contain two locals, at offsets +// that are known to the runtime. +// +// The first local is a bool called retValid with a whole pointer-word reserved +// for it on the stack. The purpose of this word is so that the runtime knows +// whether the stack-allocated return space contains valid values for stack +// scanning. +// +// The second local is an abi.RegArgs value whose offset is also known to the +// runtime, so that a stack map for it can be constructed, since it contains +// pointers visible to the GC. + +#define LOCAL_RETVALID 32+FIXED_FRAME +#define LOCAL_REGARGS 40+FIXED_FRAME + +// The frame size of the functions below is +// 32 (args of callReflect) + 8 (bool + padding) + 296 (abi.RegArgs) = 336. + // makeFuncStub is the code half of the function returned by MakeFunc. // See the comment on the declaration of makeFuncStub in makefunc.go // for more details. // No arg size here, runtime pulls arg map out of the func value. -TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$40 +TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$336 NO_LOCAL_POINTERS - MOVD R11, FIXED_FRAME+0(R1) - MOVD $argframe+0(FP), R3 - MOVD R3, FIXED_FRAME+8(R1) - MOVB R0, FIXED_FRAME+32(R1) - ADD $FIXED_FRAME+32, R1, R3 - MOVD R3, FIXED_FRAME+16(R1) - MOVD R0, FIXED_FRAME+24(R1) + // NO_LOCAL_POINTERS is a lie. The stack map for the two locals in this + // frame is specially handled in the runtime. See the comment above LOCAL_RETVALID. + ADD $LOCAL_REGARGS, R1, R20 + CALL runtime·spillArgs(SB) + MOVD R11, FIXED_FRAME+32(R1) // save R11 + MOVD R11, FIXED_FRAME+0(R1) // arg for moveMakeFuncArgPtrs + MOVD R20, FIXED_FRAME+8(R1) // arg for local args + CALL ·moveMakeFuncArgPtrs(SB) + MOVD FIXED_FRAME+32(R1), R11 // restore R11 ctxt + MOVD R11, FIXED_FRAME+0(R1) // ctxt (arg0) + MOVD $argframe+0(FP), R3 // save arg to callArg + MOVD R3, FIXED_FRAME+8(R1) // frame (arg1) + ADD $LOCAL_RETVALID, R1, R3 // addr of return flag + MOVB R0, (R3) // clear flag + MOVD R3, FIXED_FRAME+16(R1) // addr retvalid (arg2) + ADD $LOCAL_REGARGS, R1, R3 + MOVD R3, FIXED_FRAME+24(R1) // abiregargs (arg3) BL ·callReflect(SB) + ADD $LOCAL_REGARGS, R1, R20 // set address of spill area + CALL runtime·unspillArgs(SB) RET // methodValueCall is the code half of the function returned by makeMethodValue. // See the comment on the declaration of methodValueCall in makefunc.go // for more details. // No arg size here; runtime pulls arg map out of the func value. -TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$40 +TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$336 NO_LOCAL_POINTERS - MOVD R11, FIXED_FRAME+0(R1) - MOVD $argframe+0(FP), R3 - MOVD R3, FIXED_FRAME+8(R1) - MOVB R0, FIXED_FRAME+32(R1) - ADD $FIXED_FRAME+32, R1, R3 - MOVD R3, FIXED_FRAME+16(R1) - MOVD R0, FIXED_FRAME+24(R1) + // NO_LOCAL_POINTERS is a lie. The stack map for the two locals in this + // frame is specially handled in the runtime. See the comment above LOCAL_RETVALID. + ADD $LOCAL_REGARGS, R1, R20 + CALL runtime·spillArgs(SB) + MOVD R11, FIXED_FRAME+0(R1) // arg0 ctxt + MOVD R11, FIXED_FRAME+32(R1) // save for later + MOVD R20, FIXED_FRAME+8(R1) // arg1 abiregargs + CALL ·moveMakeFuncArgPtrs(SB) + MOVD FIXED_FRAME+32(R1), R11 // restore ctxt + MOVD R11, FIXED_FRAME+0(R1) // set as arg0 + MOVD $argframe+0(FP), R3 // frame pointer + MOVD R3, FIXED_FRAME+8(R1) // set as arg1 + ADD $LOCAL_RETVALID, R1, R3 + MOVB $0, (R3) // clear ret flag + MOVD R3, FIXED_FRAME+16(R1) // addr of return flag + ADD $LOCAL_REGARGS, R1, R3 // addr of abiregargs + MOVD R3, FIXED_FRAME+24(R1) // set as arg3 BL ·callMethod(SB) + ADD $LOCAL_REGARGS, R1, R20 + CALL runtime·unspillArgs(SB) RET diff --git a/src/reflect/float32reg_generic.go b/src/reflect/float32reg_generic.go index 381d458057..bfceb9ecaa 100644 --- a/src/reflect/float32reg_generic.go +++ b/src/reflect/float32reg_generic.go @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !ppc64 && !ppc64le +// +build !ppc64,!ppc64le + package reflect import "unsafe" diff --git a/src/reflect/float32reg_ppc64x.s b/src/reflect/float32reg_ppc64x.s new file mode 100644 index 0000000000..391edfa7ce --- /dev/null +++ b/src/reflect/float32reg_ppc64x.s @@ -0,0 +1,31 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ppc64 || ppc64le +// +build ppc64 ppc64le + +#include "textflag.h" + +// On PPC64, the float32 becomes a float64 +// when loaded in a register, different from +// other platforms. These functions are +// needed to ensure correct conversions on PPC64. + +// Convert float32->uint64 +TEXT ·archFloat32ToReg(SB),NOSPLIT,$0-16 + FMOVS val+0(FP), F1 + FMOVD F1, ret+8(FP) + RET + +// Convert uint64->float32 +TEXT ·archFloat32FromReg(SB),NOSPLIT,$0-12 + FMOVD reg+0(FP), F1 + // Normally a float64->float32 conversion + // would need rounding, but that is not needed + // here since the uint64 was originally converted + // from float32, and should be avoided to + // preserve SNaN values. + FMOVS F1, ret+8(FP) + RET + diff --git a/src/reflect/stubs_ppc64x.go b/src/reflect/stubs_ppc64x.go new file mode 100644 index 0000000000..dbd3f9e748 --- /dev/null +++ b/src/reflect/stubs_ppc64x.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ppc64le || ppc64 +// +build ppc64le ppc64 + +package reflect + +func archFloat32FromReg(reg uint64) float32 +func archFloat32ToReg(val float32) uint64 diff --git a/src/runtime/stack.go b/src/runtime/stack.go index cccec49f8e..22fff73947 100644 --- a/src/runtime/stack.go +++ b/src/runtime/stack.go @@ -1316,7 +1316,7 @@ func getStackMap(frame *stkframe, cache *pcvalueCache, debug bool) (locals, args } // stack objects. - if (GOARCH == "amd64" || GOARCH == "arm64") && unsafe.Sizeof(abi.RegArgs{}) > 0 && frame.argmap != nil { + if (GOARCH == "amd64" || GOARCH == "arm64" || GOARCH == "ppc64" || GOARCH == "ppc64le") && unsafe.Sizeof(abi.RegArgs{}) > 0 && frame.argmap != nil { // argmap is set when the function is reflect.makeFuncStub or reflect.methodValueCall. // We don't actually use argmap in this case, but we need to fake the stack object // record for these frames which contain an internal/abi.RegArgs at a hard-coded offset. -- GitLab From 7eb0dd289a173e8fa1d6666689ebba2c91705a5c Mon Sep 17 00:00:00 2001 From: jiahua wang Date: Sat, 25 Sep 2021 09:24:04 +0800 Subject: [PATCH 1360/2500] io: add examples for (*SectionReader) Read/Size Change-Id: Ie804f9a5d1d6beec210d2f8075c030a5c60a78ea Reviewed-on: https://go-review.googlesource.com/c/go/+/352152 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Heschi Kreinick --- src/io/example_test.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/io/example_test.go b/src/io/example_test.go index a18df9feff..f6d9fd575f 100644 --- a/src/io/example_test.go +++ b/src/io/example_test.go @@ -160,6 +160,21 @@ func ExampleSectionReader() { // io.Reader stream } +func ExampleSectionReader_Read() { + r := strings.NewReader("some io.Reader stream to be read\n") + s := io.NewSectionReader(r, 5, 17) + + buf := make([]byte, 9) + if _, err := s.Read(buf); err != nil { + log.Fatal(err) + } + + fmt.Printf("%s\n", buf) + + // Output: + // io.Reader +} + func ExampleSectionReader_ReadAt() { r := strings.NewReader("some io.Reader stream to be read\n") s := io.NewSectionReader(r, 5, 17) @@ -191,6 +206,16 @@ func ExampleSectionReader_Seek() { // stream } +func ExampleSectionReader_Size() { + r := strings.NewReader("some io.Reader stream to be read\n") + s := io.NewSectionReader(r, 5, 17) + + fmt.Println(s.Size()) + + // Output: + // 17 +} + func ExampleSeeker_Seek() { r := strings.NewReader("some io.Reader stream to be read\n") -- GitLab From e7a25731697111ea939e4cb05d638c76cdb6f0c2 Mon Sep 17 00:00:00 2001 From: jiahua wang Date: Mon, 27 Sep 2021 22:54:16 +0800 Subject: [PATCH 1361/2500] compress/gzip: add missing license Change-Id: I80c2c6054f6a5be3555c72056159a47f927f9a44 Reviewed-on: https://go-review.googlesource.com/c/go/+/352409 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Heschi Kreinick --- src/compress/gzip/issue14937_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/compress/gzip/issue14937_test.go b/src/compress/gzip/issue14937_test.go index 20da0b6824..faee9bd43a 100644 --- a/src/compress/gzip/issue14937_test.go +++ b/src/compress/gzip/issue14937_test.go @@ -1,3 +1,7 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package gzip import ( -- GitLab From daec057602d9a18f4464343e66d74b08ea41cce6 Mon Sep 17 00:00:00 2001 From: Lynn Boger Date: Tue, 28 Sep 2021 14:43:58 -0500 Subject: [PATCH 1362/2500] runtime: port memmove, memclr to register ABI on ppc64x This allows memmove and memclr to be invoked using the new register ABI on ppc64x. Change-Id: Ie397a942d7ebf76f62896924c3bb5b3a3dbba73e Reviewed-on: https://go-review.googlesource.com/c/go/+/352891 Run-TryBot: Lynn Boger TryBot-Result: Go Bot Reviewed-by: Cherry Mui Trust: Lynn Boger --- src/runtime/memclr_ppc64x.s | 4 +++- src/runtime/memmove_ppc64x.s | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/runtime/memclr_ppc64x.s b/src/runtime/memclr_ppc64x.s index 65639322b2..91aa417ca2 100644 --- a/src/runtime/memclr_ppc64x.s +++ b/src/runtime/memclr_ppc64x.s @@ -10,9 +10,11 @@ // See memclrNoHeapPointers Go doc for important implementation constraints. // func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr) -TEXT runtime·memclrNoHeapPointers(SB), NOSPLIT|NOFRAME, $0-16 +TEXT runtime·memclrNoHeapPointers(SB), NOSPLIT|NOFRAME, $0-16 +#ifndef GOEXPERIMENT_regabiargs MOVD ptr+0(FP), R3 MOVD n+8(FP), R4 +#endif // Determine if there are doublewords to clear check: diff --git a/src/runtime/memmove_ppc64x.s b/src/runtime/memmove_ppc64x.s index fd16ad8129..b36b23f8ef 100644 --- a/src/runtime/memmove_ppc64x.s +++ b/src/runtime/memmove_ppc64x.s @@ -28,10 +28,12 @@ // number of 32 byte chunks #define QWORDS R10 -TEXT runtime·memmove(SB), NOSPLIT|NOFRAME, $0-24 +TEXT runtime·memmove(SB), NOSPLIT|NOFRAME, $0-24 +#ifndef GOEXPERIMENT_regabiargs MOVD to+0(FP), TGT MOVD from+8(FP), SRC MOVD n+16(FP), LEN +#endif // Determine if there are doublewords to // copy so a more efficient move can be done -- GitLab From b8a601756abdb6f1503e41d86c122c4e7c7409ff Mon Sep 17 00:00:00 2001 From: Lynn Boger Date: Tue, 21 Sep 2021 09:36:40 -0500 Subject: [PATCH 1363/2500] internal/bytealg: port bytealg functions to reg ABI on ppc64x This adds support for the reg ABI to the bytes functions for ppc64/ppc64le. These are initially under control of the GOEXPERIMENT macro until all changes are in. Change-Id: Id82f31056af8caa8541e27c6735f6b815a5dbf5a Reviewed-on: https://go-review.googlesource.com/c/go/+/351190 Trust: Lynn Boger Reviewed-by: Cherry Mui --- src/internal/bytealg/compare_ppc64x.s | 75 +++++++++++++++++++++---- src/internal/bytealg/equal_ppc64x.s | 21 +++++-- src/internal/bytealg/indexbyte_ppc64x.s | 19 ++++++- 3 files changed, 95 insertions(+), 20 deletions(-) diff --git a/src/internal/bytealg/compare_ppc64x.s b/src/internal/bytealg/compare_ppc64x.s index 83444fa826..390a72688b 100644 --- a/src/internal/bytealg/compare_ppc64x.s +++ b/src/internal/bytealg/compare_ppc64x.s @@ -8,64 +8,99 @@ #include "go_asm.h" #include "textflag.h" -TEXT ·Compare(SB),NOSPLIT|NOFRAME,$0-56 +TEXT ·Compare(SB),NOSPLIT|NOFRAME,$0-56 +#ifdef GOEXPERIMENT_regabiargs +// incoming: +// R3 a addr -> R5 +// R4 a len -> R3 +// R5 a cap unused +// R6 b addr -> R6 +// R7 b len -> R4 +// R8 b cap unused + MOVD R3, R5 + MOVD R4, R3 + MOVD R7, R4 +#else MOVD a_base+0(FP), R5 MOVD b_base+24(FP), R6 MOVD a_len+8(FP), R3 - CMP R5,R6,CR7 MOVD b_len+32(FP), R4 MOVD $ret+48(FP), R7 +#endif + CMP R5,R6,CR7 CMP R3,R4,CR6 BEQ CR7,equal - #ifdef GOARCH_ppc64le BR cmpbodyLE<>(SB) #else BR cmpbodyBE<>(SB) #endif - equal: BEQ CR6,done MOVD $1, R8 BGT CR6,greater NEG R8 - greater: +#ifdef GOEXPERIMENT_regabiargs + MOVD R8, R3 +#else MOVD R8, (R7) +#endif RET - done: +#ifdef GOEXPERIMENT_regabiargs + MOVD $0, R3 +#else MOVD $0, (R7) +#endif RET -TEXT runtime·cmpstring(SB),NOSPLIT|NOFRAME,$0-40 +TEXT runtime·cmpstring(SB),NOSPLIT|NOFRAME,$0-40 +#ifdef GOEXPERIMENT_regabiargs +// incoming: +// R3 a addr -> R5 +// R4 a len -> R3 +// R5 b addr -> R6 +// R6 b len -> R4 + MOVD R6, R7 + MOVD R5, R6 + MOVD R3, R5 + MOVD R4, R3 + MOVD R7, R4 +#else MOVD a_base+0(FP), R5 MOVD b_base+16(FP), R6 MOVD a_len+8(FP), R3 - CMP R5,R6,CR7 MOVD b_len+24(FP), R4 MOVD $ret+32(FP), R7 +#endif + CMP R5,R6,CR7 CMP R3,R4,CR6 BEQ CR7,equal - #ifdef GOARCH_ppc64le BR cmpbodyLE<>(SB) #else BR cmpbodyBE<>(SB) #endif - equal: BEQ CR6,done MOVD $1, R8 BGT CR6,greater NEG R8 - greater: +#ifdef GOEXPERIMENT_regabiargs + MOVD R8, R3 +#else MOVD R8, (R7) +#endif RET done: +#ifdef GOEXPERIMENT_regabiargs + MOVD $0, R3 +#else MOVD $0, (R7) +#endif RET // Do an efficient memcmp for ppc64le @@ -73,7 +108,7 @@ done: // R4 = b len // R5 = a addr // R6 = b addr -// R7 = addr of return value +// R7 = addr of return value if not regabi TEXT cmpbodyLE<>(SB),NOSPLIT|NOFRAME,$0-0 MOVD R3,R8 // set up length CMP R3,R4,CR2 // unequal? @@ -168,14 +203,22 @@ cmpne: // only here is not equal BGT greater // here only if NE less: MOVD $-1,R3 +#ifndef GOEXPERIMENT_regabiargs MOVD R3,(R7) // return value if A < B +#endif RET equal: +#ifdef GOEXPERIMENT_regabiargs + MOVD $0, R3 +#else MOVD $0,(R7) // return value if A == B +#endif RET greater: MOVD $1,R3 +#ifndef GOEXPERIMENT_regabiargs MOVD R3,(R7) // return value if A > B +#endif RET // Do an efficient memcmp for ppc64 (BE) @@ -267,12 +310,20 @@ simple: BC 12,9,greater // 2nd len > 1st len less: MOVD $-1,R3 +#ifndef GOEXPERIMENT_regabiargs MOVD R3,(R7) // return value if A < B +#endif RET equal: +#ifdef GOEXPERIMENT_regabiargs + MOVD $0, R3 +#else MOVD $0,(R7) // return value if A == B +#endif RET greater: MOVD $1,R3 +#ifndef GOEXPERIMENT_regabiargs MOVD R3,(R7) // return value if A > B +#endif RET diff --git a/src/internal/bytealg/equal_ppc64x.s b/src/internal/bytealg/equal_ppc64x.s index 5f0fea521b..d59154101a 100644 --- a/src/internal/bytealg/equal_ppc64x.s +++ b/src/internal/bytealg/equal_ppc64x.s @@ -9,33 +9,38 @@ #include "textflag.h" // memequal(a, b unsafe.Pointer, size uintptr) bool -TEXT runtime·memequal(SB),NOSPLIT|NOFRAME,$0-25 +TEXT runtime·memequal(SB),NOSPLIT|NOFRAME,$0-25 +#ifndef GOEXPERIMENT_regabiargs MOVD a+0(FP), R3 MOVD b+8(FP), R4 MOVD size+16(FP), R5 MOVD $ret+24(FP), R10 - +#endif BR memeqbody<>(SB) // memequal_varlen(a, b unsafe.Pointer) bool -TEXT runtime·memequal_varlen(SB),NOSPLIT|NOFRAME,$0-17 +TEXT runtime·memequal_varlen(SB),NOSPLIT|NOFRAME,$0-17 +#ifndef GOEXPERIMENT_regabiargs MOVD a+0(FP), R3 MOVD b+8(FP), R4 + MOVD $ret+16(FP), R10 +#endif CMP R3, R4 BEQ eq MOVD 8(R11), R5 // compiler stores size at offset 8 in the closure - MOVD $ret+16(FP), R10 BR memeqbody<>(SB) eq: MOVD $1, R3 +#ifndef GOEXPERIMENT_regabiargs MOVB R3, ret+16(FP) +#endif RET // Do an efficient memequal for ppc64 // R3 = s1 // R4 = s2 // R5 = len -// R10 = addr of return value (byte) +// R10 = addr of return value (byte) when not regabi TEXT memeqbody<>(SB),NOSPLIT|NOFRAME,$0-0 MOVD R5,CTR CMP R5,$8 // only optimize >=8 @@ -94,10 +99,16 @@ simple: BNE noteq BR equal noteq: +#ifdef GOEXPERIMENT_regabiargs + MOVD $0, R3 +#else MOVB $0, (R10) +#endif RET equal: MOVD $1, R3 +#ifndef GOEXPERIMENT_regabiargs MOVB R3, (R10) +#endif RET diff --git a/src/internal/bytealg/indexbyte_ppc64x.s b/src/internal/bytealg/indexbyte_ppc64x.s index 8e13c5a56e..27e1ad7e0d 100644 --- a/src/internal/bytealg/indexbyte_ppc64x.s +++ b/src/internal/bytealg/indexbyte_ppc64x.s @@ -8,20 +8,29 @@ #include "go_asm.h" #include "textflag.h" -TEXT ·IndexByte(SB),NOSPLIT|NOFRAME,$0-40 +TEXT ·IndexByte(SB),NOSPLIT|NOFRAME,$0-40 +#ifndef GOEXPERIMENT_regabiargs MOVD b_base+0(FP), R3 // R3 = byte array pointer MOVD b_len+8(FP), R4 // R4 = length MOVBZ c+24(FP), R5 // R5 = byte MOVD $ret+32(FP), R14 // R14 = &ret +#else + MOVD R6, R5 +#endif BR indexbytebody<>(SB) -TEXT ·IndexByteString(SB),NOSPLIT|NOFRAME,$0-32 +TEXT ·IndexByteString(SB),NOSPLIT|NOFRAME,$0-32 +#ifndef GOEXPERIMENT_regabiargs MOVD s_base+0(FP), R3 // R3 = string MOVD s_len+8(FP), R4 // R4 = length MOVBZ c+16(FP), R5 // R5 = byte MOVD $ret+24(FP), R14 // R14 = &ret +#endif BR indexbytebody<>(SB) - +// R3 = addr of string +// R4 = len of string +// R5 = byte to find +// R14 = addr of return value when not regabi TEXT indexbytebody<>(SB),NOSPLIT|NOFRAME,$0-0 MOVD R3,R17 // Save base address for calculating the index later. RLDICR $0,R3,$60,R8 // Align address to doubleword boundary in R8. @@ -186,7 +195,9 @@ tail: notfound: MOVD $-1,R3 +#ifndef GOEXPERIMENT_regabiargs MOVD R3,(R14) +#endif RET found: @@ -229,7 +240,9 @@ found: return: SUB R17,R3 +#ifndef GOEXPERIMENT_regabiargs MOVD R3,(R14) +#endif RET found_qw_align: -- GitLab From 435718edd9e9ba60d0c5bca45cc9d57c6b5527bc Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 28 Sep 2021 13:50:15 -0700 Subject: [PATCH 1364/2500] cmd/compile/internal/types2: avoid infinite recursion in unification If the type T inferred for a type parameter P is P itself (or a derived type containing P), a subsequent unification step leads to infinite recursion: at each encounter of P with the already inferred type T (which is or contains P), P stands for that T and the recursive matching process continues with T, which inevitably contains P again and recursion never terminates. This CL introduces a set of masks, one for each type parameter. When a type parameter is encountered for which a type has already been inferred, the type parameter is "masked" for the recursive matching of the inferred type. Masking makes the type parameter "invisible" such that it will be handled like any other type and not unpacked further. Fixes #48619. For #48656. Change-Id: Ic1d938322be51fd44323ea14f925303f58b27c97 Reviewed-on: https://go-review.googlesource.com/c/go/+/352832 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley --- .../types2/testdata/fixedbugs/issue48619.go2 | 22 ++++++++++++++++ .../types2/testdata/fixedbugs/issue48656.go2 | 13 ++++++++++ src/cmd/compile/internal/types2/unify.go | 26 ++++++++++++++++--- 3 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue48619.go2 create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue48656.go2 diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48619.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48619.go2 new file mode 100644 index 0000000000..24650a3a70 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48619.go2 @@ -0,0 +1,22 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func f[P any](a, _ P) { + var x int + f(a, x /* ERROR type int of x does not match P */) + f(x, a /* ERROR type P of a does not match inferred type int for P */) +} + +func g[P any](a, b P) { + g(a, b) + g(&a, &b) + g([]P{}, []P{}) +} + +func h[P any](a, b P) { + h(&a, &b) + h([]P{a}, []P{b}) +} diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48656.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48656.go2 new file mode 100644 index 0000000000..7d292e0cc4 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48656.go2 @@ -0,0 +1,13 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +// TODO(gri) Still need better error positions and message here. +// But this doesn't crash anymore. + +func f[P /* ERROR does not match \*Q */ interface{*Q}, Q any](p P, q Q) { + _ = f[P] + _ = f[/* ERROR cannot infer P */ *P] +} diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index a252c5e1a5..ee41264116 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -63,6 +63,10 @@ func (u *unifier) unify(x, y Type) bool { type tparamsList struct { unifier *unifier tparams []*TypeParam + // For each tparams element, there is a corresponding mask bit in masks. + // If set, the corresponding type parameter is masked and doesn't appear + // as a type parameter with tparamsList.index. + masks []bool // For each tparams element, there is a corresponding type slot index in indices. // index < 0: unifier.types[-index-1] == nil // index == 0: no type slot allocated yet @@ -103,9 +107,14 @@ func (d *tparamsList) init(tparams []*TypeParam) { } } d.tparams = tparams + d.masks = make([]bool, len(tparams)) d.indices = make([]int, len(tparams)) } +// mask and unmask permit the masking/unmasking of the i'th type parameter of d. +func (d *tparamsList) mask(i int) { d.masks[i] = true } +func (d *tparamsList) unmask(i int) { d.masks[i] = false } + // join unifies the i'th type parameter of x with the j'th type parameter of y. // If both type parameters already have a type associated with them and they are // not joined, join fails and returns false. @@ -149,11 +158,13 @@ func (u *unifier) join(i, j int) bool { return true } -// If typ is a type parameter of d, index returns the type parameter index. +// If typ is an unmasked type parameter of d, index returns the type parameter index. // Otherwise, the result is < 0. func (d *tparamsList) index(typ Type) int { if tpar, ok := typ.(*TypeParam); ok { - return tparamIndex(d.tparams, tpar) + if i := tparamIndex(d.tparams, tpar); i >= 0 && !d.masks[i] { + return i + } } return -1 } @@ -246,7 +257,7 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { } } - // Cases where at least one of x or y is a type parameter. + // Cases where at least one of x or y is an (unmasked) type parameter. switch i, j := u.x.index(x), u.y.index(y); { case i >= 0 && j >= 0: // both x and y are type parameters @@ -259,6 +270,12 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { case i >= 0: // x is a type parameter, y is not if tx := u.x.at(i); tx != nil { + // The inferred type tx may be or contain x again but we don't + // want to "unpack" it again when unifying tx with y: tx is the + // inferred type. Mask type parameter x for this recursion, so + // that subsequent encounters treat x like an ordinary type. + u.x.mask(i) + defer u.x.unmask(i) return u.nifyEq(tx, y, p) } // otherwise, infer type from y @@ -268,6 +285,9 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { case j >= 0: // y is a type parameter, x is not if ty := u.y.at(j); ty != nil { + // see comment above + u.y.mask(j) + defer u.y.unmask(j) return u.nifyEq(x, ty, p) } // otherwise, infer type from x -- GitLab From 587b3c1192397393afb0ec5acd608e3dfe9f2116 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 28 Sep 2021 16:20:29 -0400 Subject: [PATCH 1365/2500] cmd/link: access pcdata via aux symbols Pcdata are now separate aux symbols. Read them from aux, instead of using funcinfo. Now we can remove pcdata fields from funcinfo. Change-Id: Ie65e3962edecc0f39127a5f6963dc59d1f141e67 Reviewed-on: https://go-review.googlesource.com/c/go/+/352893 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/internal/goobj/funcinfo.go | 55 +---------- src/cmd/internal/obj/objfile.go | 8 -- src/cmd/link/internal/ld/dwarf.go | 2 +- src/cmd/link/internal/ld/lib.go | 2 +- src/cmd/link/internal/ld/pcln.go | 32 +++--- src/cmd/link/internal/loader/loader.go | 129 ++++++++++++------------- 6 files changed, 86 insertions(+), 142 deletions(-) diff --git a/src/cmd/internal/goobj/funcinfo.go b/src/cmd/internal/goobj/funcinfo.go index 6d33a10a51..6e7970fb74 100644 --- a/src/cmd/internal/goobj/funcinfo.go +++ b/src/cmd/internal/goobj/funcinfo.go @@ -16,19 +16,12 @@ type CUFileIndex uint32 // FuncInfo is serialized as a symbol (aux symbol). The symbol data is // the binary encoding of the struct below. -// -// TODO: make each pcdata a separate symbol? type FuncInfo struct { Args uint32 Locals uint32 FuncID objabi.FuncID FuncFlag objabi.FuncFlag - Pcsp SymRef - Pcfile SymRef - Pcline SymRef - Pcinline SymRef - Pcdata []SymRef Funcdataoff []uint32 File []CUFileIndex @@ -44,10 +37,6 @@ func (a *FuncInfo) Write(w *bytes.Buffer) { binary.LittleEndian.PutUint32(b[:], x) w.Write(b[:]) } - writeSymRef := func(s SymRef) { - writeUint32(s.PkgIdx) - writeUint32(s.SymIdx) - } writeUint32(a.Args) writeUint32(a.Locals) @@ -55,14 +44,6 @@ func (a *FuncInfo) Write(w *bytes.Buffer) { writeUint8(uint8(a.FuncFlag)) writeUint8(0) // pad to uint32 boundary writeUint8(0) - writeSymRef(a.Pcsp) - writeSymRef(a.Pcfile) - writeSymRef(a.Pcline) - writeSymRef(a.Pcinline) - writeUint32(uint32(len(a.Pcdata))) - for _, sym := range a.Pcdata { - writeSymRef(sym) - } writeUint32(uint32(len(a.Funcdataoff))) for _, x := range a.Funcdataoff { @@ -84,8 +65,6 @@ func (a *FuncInfo) Write(w *bytes.Buffer) { // corresponding "off" field stores the byte offset of the start of // the items in question. type FuncInfoLengths struct { - NumPcdata uint32 - PcdataOff uint32 NumFuncdataoff uint32 FuncdataoffOff uint32 NumFile uint32 @@ -98,13 +77,9 @@ type FuncInfoLengths struct { func (*FuncInfo) ReadFuncInfoLengths(b []byte) FuncInfoLengths { var result FuncInfoLengths - // Offset to the number of pcdata values. This value is determined by counting - // the number of bytes until we write pcdata to the file. - const numpcdataOff = 44 - result.NumPcdata = binary.LittleEndian.Uint32(b[numpcdataOff:]) - result.PcdataOff = numpcdataOff + 4 - - numfuncdataoffOff := result.PcdataOff + 8*result.NumPcdata + // Offset to the number of funcdataoff values. This value is determined by counting + // the number of bytes until we write funcdataoff to the file. + const numfuncdataoffOff = 12 result.NumFuncdataoff = binary.LittleEndian.Uint32(b[numfuncdataoffOff:]) result.FuncdataoffOff = numfuncdataoffOff + 4 @@ -129,30 +104,6 @@ func (*FuncInfo) ReadFuncID(b []byte) objabi.FuncID { return objabi.FuncID(b[8]) func (*FuncInfo) ReadFuncFlag(b []byte) objabi.FuncFlag { return objabi.FuncFlag(b[9]) } -func (*FuncInfo) ReadPcsp(b []byte) SymRef { - return SymRef{binary.LittleEndian.Uint32(b[12:]), binary.LittleEndian.Uint32(b[16:])} -} - -func (*FuncInfo) ReadPcfile(b []byte) SymRef { - return SymRef{binary.LittleEndian.Uint32(b[20:]), binary.LittleEndian.Uint32(b[24:])} -} - -func (*FuncInfo) ReadPcline(b []byte) SymRef { - return SymRef{binary.LittleEndian.Uint32(b[28:]), binary.LittleEndian.Uint32(b[32:])} -} - -func (*FuncInfo) ReadPcinline(b []byte) SymRef { - return SymRef{binary.LittleEndian.Uint32(b[36:]), binary.LittleEndian.Uint32(b[40:])} -} - -func (*FuncInfo) ReadPcdata(b []byte) []SymRef { - syms := make([]SymRef, binary.LittleEndian.Uint32(b[44:])) - for i := range syms { - syms[i] = SymRef{binary.LittleEndian.Uint32(b[48+i*8:]), binary.LittleEndian.Uint32(b[52+i*8:])} - } - return syms -} - func (*FuncInfo) ReadFuncdataoff(b []byte, funcdataofffoff uint32, k uint32) int64 { return int64(binary.LittleEndian.Uint32(b[funcdataofffoff+4*k:])) } diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index 030a02b499..bed32198d7 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -671,14 +671,6 @@ func genFuncInfoSyms(ctxt *Link) { FuncFlag: fn.FuncFlag, } pc := &fn.Pcln - o.Pcsp = makeSymRef(pc.Pcsp) - o.Pcfile = makeSymRef(pc.Pcfile) - o.Pcline = makeSymRef(pc.Pcline) - o.Pcinline = makeSymRef(pc.Pcinline) - o.Pcdata = make([]goobj.SymRef, len(pc.Pcdata)) - for i, pcSym := range pc.Pcdata { - o.Pcdata[i] = makeSymRef(pcSym) - } o.Funcdataoff = make([]uint32, len(pc.Funcdataoff)) for i, x := range pc.Funcdataoff { o.Funcdataoff[i] = uint32(x) diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go index d72846a691..47b4921cd8 100644 --- a/src/cmd/link/internal/ld/dwarf.go +++ b/src/cmd/link/internal/ld/dwarf.go @@ -1417,7 +1417,7 @@ func (d *dwctxt) writeframes(fs loader.Sym) dwarfSecInfo { if !fi.Valid() { continue } - fpcsp := fi.Pcsp() + fpcsp := d.ldr.Pcsp(s) // Emit a FDE, Section 6.4.1. // First build the section contents into a byte buffer. diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index feff16d0c0..5af20b4d18 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -2310,7 +2310,7 @@ func (sc *stkChk) check(up *chain, depth int) int { var ch1 chain pcsp := obj.NewPCIter(uint32(ctxt.Arch.MinLC)) ri := 0 - for pcsp.Init(ldr.Data(info.Pcsp())); !pcsp.Done; pcsp.Next() { + for pcsp.Init(ldr.Data(ldr.Pcsp(s))); !pcsp.Done; pcsp.Next() { // pcsp.value is in effect for [pcsp.pc, pcsp.nextpc). // Check stack size in effect for this span. diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index fede00586b..c8cd7bf09e 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -485,22 +485,25 @@ func (state *pclntab) generatePctab(ctxt *Link, funcs []loader.Sym) { seen[pcSym] = struct{}{} } } + var pcsp, pcline, pcfile, pcinline loader.Sym + var pcdata []loader.Sym for _, s := range funcs { fi := ldr.FuncInfo(s) if !fi.Valid() { continue } fi.Preload() + pcsp, pcfile, pcline, pcinline, pcdata = ldr.PcdataAuxs(s, pcdata) - pcSyms := []loader.Sym{fi.Pcsp(), fi.Pcfile(), fi.Pcline()} + pcSyms := []loader.Sym{pcsp, pcfile, pcline} for _, pcSym := range pcSyms { saveOffset(pcSym) } - for _, pcSym := range fi.Pcdata() { + for _, pcSym := range pcdata { saveOffset(pcSym) } if fi.NumInlTree() > 0 { - saveOffset(fi.Pcinline()) + saveOffset(pcinline) } } @@ -521,11 +524,11 @@ func (state *pclntab) generatePctab(ctxt *Link, funcs []loader.Sym) { // numPCData returns the number of PCData syms for the FuncInfo. // NB: Preload must be called on valid FuncInfos before calling this function. -func numPCData(fi loader.FuncInfo) uint32 { +func numPCData(ldr *loader.Loader, s loader.Sym, fi loader.FuncInfo) uint32 { if !fi.Valid() { return 0 } - numPCData := uint32(len(fi.Pcdata())) + numPCData := uint32(ldr.NumPcdata(s)) if fi.NumInlTree() > 0 { if numPCData < objabi.PCDATA_InlTreeIndex+1 { numPCData = objabi.PCDATA_InlTreeIndex + 1 @@ -676,7 +679,7 @@ func (state pclntab) calculateFunctabSize(ctxt *Link, funcs []loader.Sym) (int64 numFuncData = objabi.FUNCDATA_InlTree + 1 } } - size += int64(numPCData(fi) * 4) + size += int64(numPCData(ldr, s, fi) * 4) if numFuncData > 0 { // Func data is aligned. size = Rnd(size, int64(ctxt.Arch.PtrSize)) } @@ -747,7 +750,7 @@ func (state *pclntab) writeFuncData(ctxt *Link, sb *loader.SymbolBuilder, funcs // Missing funcdata will be 0 (nil pointer). funcdata, funcdataoff := funcData(fi, inlSyms[s], funcdata, funcdataoff) if len(funcdata) > 0 { - off := int64(startLocations[i] + state.funcSize + numPCData(fi)*4) + off := int64(startLocations[i] + state.funcSize + numPCData(ldr, s, fi)*4) off = Rnd(off, int64(ctxt.Arch.PtrSize)) for j := range funcdata { dataoff := off + int64(ctxt.Arch.PtrSize*j) @@ -767,12 +770,15 @@ func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSym ldr := ctxt.loader deferReturnSym := ldr.Lookup("runtime.deferreturn", abiInternalVer) funcdata, funcdataoff := []loader.Sym{}, []int64{} + var pcsp, pcfile, pcline, pcinline loader.Sym + var pcdata []loader.Sym // Write the individual func objects. for i, s := range funcs { fi := ldr.FuncInfo(s) if fi.Valid() { fi.Preload() + pcsp, pcfile, pcline, pcinline, pcdata = ldr.PcdataAuxs(s, pcdata) } // Note we skip the space for the entry value -- that's handled in @@ -801,13 +807,13 @@ func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSym // pcdata if fi.Valid() { - off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(ldr.SymValue(fi.Pcsp())))) - off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(ldr.SymValue(fi.Pcfile())))) - off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(ldr.SymValue(fi.Pcline())))) + off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(ldr.SymValue(pcsp)))) + off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(ldr.SymValue(pcfile)))) + off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(ldr.SymValue(pcline)))) } else { off += 12 } - off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(numPCData(fi)))) + off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(numPCData(ldr, s, fi)))) // Store the offset to compilation unit's file table. cuIdx := ^uint32(0) @@ -838,11 +844,11 @@ func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSym // Output the pcdata. if fi.Valid() { - for j, pcSym := range fi.Pcdata() { + for j, pcSym := range pcdata { sb.SetUint32(ctxt.Arch, int64(off+uint32(j*4)), uint32(ldr.SymValue(pcSym))) } if fi.NumInlTree() > 0 { - sb.SetUint32(ctxt.Arch, int64(off+objabi.PCDATA_InlTreeIndex*4), uint32(ldr.SymValue(fi.Pcinline()))) + sb.SetUint32(ctxt.Arch, int64(off+objabi.PCDATA_InlTreeIndex*4), uint32(ldr.SymValue(pcinline))) } } } diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index 4bf5475a32..ec145da26d 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -1532,27 +1532,7 @@ func (l *Loader) DynidSyms() []Sym { // approach would be to check for gotype during preload and copy the // results in to a map (might want to try this at some point and see // if it helps speed things up). -func (l *Loader) SymGoType(i Sym) Sym { - var r *oReader - var auxs []goobj.Aux - if l.IsExternal(i) { - pp := l.getPayload(i) - r = l.objs[pp.objidx].r - auxs = pp.auxs - } else { - var li uint32 - r, li = l.toLocal(i) - auxs = r.Auxs(li) - } - for j := range auxs { - a := &auxs[j] - switch a.Type() { - case goobj.AuxGotype: - return l.resolve(r, a.Sym()) - } - } - return 0 -} +func (l *Loader) SymGoType(i Sym) Sym { return l.aux1(i, goobj.AuxGotype) } // SymUnit returns the compilation unit for a given symbol (which will // typically be nil for external or linker-manufactured symbols). @@ -1890,6 +1870,66 @@ func (l *Loader) relocs(r *oReader, li uint32) Relocs { } } +func (l *Loader) auxs(i Sym) (*oReader, []goobj.Aux) { + if l.IsExternal(i) { + pp := l.getPayload(i) + return l.objs[pp.objidx].r, pp.auxs + } else { + r, li := l.toLocal(i) + return r, r.Auxs(li) + } +} + +// Returns a specific aux symbol of type t for symbol i. +func (l *Loader) aux1(i Sym, t uint8) Sym { + r, auxs := l.auxs(i) + for j := range auxs { + a := &auxs[j] + if a.Type() == t { + return l.resolve(r, a.Sym()) + } + } + return 0 +} + +func (l *Loader) Pcsp(i Sym) Sym { return l.aux1(i, goobj.AuxPcsp) } + +// Returns all aux symbols of per-PC data for symbol i. +// tmp is a scratch space for the pcdata slice. +func (l *Loader) PcdataAuxs(i Sym, tmp []Sym) (pcsp, pcfile, pcline, pcinline Sym, pcdata []Sym) { + pcdata = tmp[:0] + r, auxs := l.auxs(i) + for j := range auxs { + a := &auxs[j] + switch a.Type() { + case goobj.AuxPcsp: + pcsp = l.resolve(r, a.Sym()) + case goobj.AuxPcline: + pcline = l.resolve(r, a.Sym()) + case goobj.AuxPcfile: + pcfile = l.resolve(r, a.Sym()) + case goobj.AuxPcinline: + pcinline = l.resolve(r, a.Sym()) + case goobj.AuxPcdata: + pcdata = append(pcdata, l.resolve(r, a.Sym())) + } + } + return +} + +// Returns the number of pcdata for symbol i. +func (l *Loader) NumPcdata(i Sym) int { + n := 0 + _, auxs := l.auxs(i) + for j := range auxs { + a := &auxs[j] + if a.Type() == goobj.AuxPcdata { + n++ + } + } + return n +} + // FuncInfo provides hooks to access goobj.FuncInfo in the objects. type FuncInfo struct { l *Loader @@ -1917,44 +1957,12 @@ func (fi *FuncInfo) FuncFlag() objabi.FuncFlag { return (*goobj.FuncInfo)(nil).ReadFuncFlag(fi.data) } -func (fi *FuncInfo) Pcsp() Sym { - sym := (*goobj.FuncInfo)(nil).ReadPcsp(fi.data) - return fi.l.resolve(fi.r, sym) -} - -func (fi *FuncInfo) Pcfile() Sym { - sym := (*goobj.FuncInfo)(nil).ReadPcfile(fi.data) - return fi.l.resolve(fi.r, sym) -} - -func (fi *FuncInfo) Pcline() Sym { - sym := (*goobj.FuncInfo)(nil).ReadPcline(fi.data) - return fi.l.resolve(fi.r, sym) -} - -func (fi *FuncInfo) Pcinline() Sym { - sym := (*goobj.FuncInfo)(nil).ReadPcinline(fi.data) - return fi.l.resolve(fi.r, sym) -} - // Preload has to be called prior to invoking the various methods // below related to pcdata, funcdataoff, files, and inltree nodes. func (fi *FuncInfo) Preload() { fi.lengths = (*goobj.FuncInfo)(nil).ReadFuncInfoLengths(fi.data) } -func (fi *FuncInfo) Pcdata() []Sym { - if !fi.lengths.Initialized { - panic("need to call Preload first") - } - syms := (*goobj.FuncInfo)(nil).ReadPcdata(fi.data) - ret := make([]Sym, len(syms)) - for i := range ret { - ret[i] = fi.l.resolve(fi.r, syms[i]) - } - return ret -} - func (fi *FuncInfo) NumFuncdataoff() uint32 { if !fi.lengths.Initialized { panic("need to call Preload first") @@ -2038,20 +2046,7 @@ func (fi *FuncInfo) InlTree(k int) InlTreeNode { } func (l *Loader) FuncInfo(i Sym) FuncInfo { - var r *oReader - var auxs []goobj.Aux - if l.IsExternal(i) { - pp := l.getPayload(i) - if pp.objidx == 0 { - return FuncInfo{} - } - r = l.objs[pp.objidx].r - auxs = pp.auxs - } else { - var li uint32 - r, li = l.toLocal(i) - auxs = r.Auxs(li) - } + r, auxs := l.auxs(i) for j := range auxs { a := &auxs[j] if a.Type() == goobj.AuxFuncInfo { -- GitLab From e180e2c27c3c3f06a4df6352386efedc15a1e38c Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 28 Sep 2021 17:07:01 -0400 Subject: [PATCH 1366/2500] cmd/internal/goobj, cmd/link: remove funcdataoff FUNCDATA is always a symbol reference with 0 offset. Assert the offset is 0 and remove funcdataoff. Change-Id: I326815365c9db5aeef6b869df5d78a9957bc16a6 Reviewed-on: https://go-review.googlesource.com/c/go/+/352894 Trust: Cherry Mui Reviewed-by: Than McIntosh --- src/cmd/internal/goobj/funcinfo.go | 35 ++++----------- src/cmd/internal/obj/link.go | 17 ++++--- src/cmd/internal/obj/objfile.go | 4 -- src/cmd/internal/obj/pcln.go | 11 ++--- src/cmd/link/internal/ld/pcln.go | 35 ++++++--------- src/cmd/link/internal/loader/loader.go | 62 ++++++++++++-------------- 6 files changed, 62 insertions(+), 102 deletions(-) diff --git a/src/cmd/internal/goobj/funcinfo.go b/src/cmd/internal/goobj/funcinfo.go index 6e7970fb74..59cb957fa7 100644 --- a/src/cmd/internal/goobj/funcinfo.go +++ b/src/cmd/internal/goobj/funcinfo.go @@ -21,11 +21,8 @@ type FuncInfo struct { Locals uint32 FuncID objabi.FuncID FuncFlag objabi.FuncFlag - - Funcdataoff []uint32 - File []CUFileIndex - - InlTree []InlTreeNode + File []CUFileIndex + InlTree []InlTreeNode } func (a *FuncInfo) Write(w *bytes.Buffer) { @@ -45,10 +42,6 @@ func (a *FuncInfo) Write(w *bytes.Buffer) { writeUint8(0) // pad to uint32 boundary writeUint8(0) - writeUint32(uint32(len(a.Funcdataoff))) - for _, x := range a.Funcdataoff { - writeUint32(x) - } writeUint32(uint32(len(a.File))) for _, f := range a.File { writeUint32(uint32(f)) @@ -65,25 +58,19 @@ func (a *FuncInfo) Write(w *bytes.Buffer) { // corresponding "off" field stores the byte offset of the start of // the items in question. type FuncInfoLengths struct { - NumFuncdataoff uint32 - FuncdataoffOff uint32 - NumFile uint32 - FileOff uint32 - NumInlTree uint32 - InlTreeOff uint32 - Initialized bool + NumFile uint32 + FileOff uint32 + NumInlTree uint32 + InlTreeOff uint32 + Initialized bool } func (*FuncInfo) ReadFuncInfoLengths(b []byte) FuncInfoLengths { var result FuncInfoLengths - // Offset to the number of funcdataoff values. This value is determined by counting + // Offset to the number of the file table. This value is determined by counting // the number of bytes until we write funcdataoff to the file. - const numfuncdataoffOff = 12 - result.NumFuncdataoff = binary.LittleEndian.Uint32(b[numfuncdataoffOff:]) - result.FuncdataoffOff = numfuncdataoffOff + 4 - - numfileOff := result.FuncdataoffOff + 4*result.NumFuncdataoff + const numfileOff = 12 result.NumFile = binary.LittleEndian.Uint32(b[numfileOff:]) result.FileOff = numfileOff + 4 @@ -104,10 +91,6 @@ func (*FuncInfo) ReadFuncID(b []byte) objabi.FuncID { return objabi.FuncID(b[8]) func (*FuncInfo) ReadFuncFlag(b []byte) objabi.FuncFlag { return objabi.FuncFlag(b[9]) } -func (*FuncInfo) ReadFuncdataoff(b []byte, funcdataofffoff uint32, k uint32) int64 { - return int64(binary.LittleEndian.Uint32(b[funcdataofffoff+4*k:])) -} - func (*FuncInfo) ReadFile(b []byte, filesoff uint32, k uint32) CUFileIndex { return CUFileIndex(binary.LittleEndian.Uint32(b[filesoff+4*k:])) } diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index 82ff5994d1..abb37416cc 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -830,15 +830,14 @@ func (*LSym) CanBeAnSSAAux() {} type Pcln struct { // Aux symbols for pcln - Pcsp *LSym - Pcfile *LSym - Pcline *LSym - Pcinline *LSym - Pcdata []*LSym - Funcdata []*LSym - Funcdataoff []int64 - UsedFiles map[goobj.CUFileIndex]struct{} // file indices used while generating pcfile - InlTree InlTree // per-function inlining tree extracted from the global tree + Pcsp *LSym + Pcfile *LSym + Pcline *LSym + Pcinline *LSym + Pcdata []*LSym + Funcdata []*LSym + UsedFiles map[goobj.CUFileIndex]struct{} // file indices used while generating pcfile + InlTree InlTree // per-function inlining tree extracted from the global tree } type Reloc struct { diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index bed32198d7..3d8d69f069 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -671,10 +671,6 @@ func genFuncInfoSyms(ctxt *Link) { FuncFlag: fn.FuncFlag, } pc := &fn.Pcln - o.Funcdataoff = make([]uint32, len(pc.Funcdataoff)) - for i, x := range pc.Funcdataoff { - o.Funcdataoff[i] = uint32(x) - } i := 0 o.File = make([]goobj.CUFileIndex, len(pc.UsedFiles)) for f := range pc.UsedFiles { diff --git a/src/cmd/internal/obj/pcln.go b/src/cmd/internal/obj/pcln.go index 42c4a2a9d9..49b425b124 100644 --- a/src/cmd/internal/obj/pcln.go +++ b/src/cmd/internal/obj/pcln.go @@ -8,6 +8,7 @@ import ( "cmd/internal/goobj" "cmd/internal/objabi" "encoding/binary" + "fmt" "log" ) @@ -280,8 +281,6 @@ func linkpcln(ctxt *Link, cursym *LSym) { pcln.Pcdata = make([]*LSym, npcdata) pcln.Funcdata = make([]*LSym, nfuncdata) - pcln.Funcdataoff = make([]int64, nfuncdata) - pcln.Funcdataoff = pcln.Funcdataoff[:nfuncdata] pcln.Pcsp = funcpctab(ctxt, cursym, "pctospadj", pctospadj, nil) pcln.Pcfile = funcpctab(ctxt, cursym, "pctofile", pctofileline, pcln) @@ -351,12 +350,10 @@ func linkpcln(ctxt *Link, cursym *LSym) { continue } i := int(p.From.Offset) - pcln.Funcdataoff[i] = p.To.Offset - if p.To.Type != TYPE_CONST { - // TODO: Dedup. - //funcdata_bytes += p->to.sym->size; - pcln.Funcdata[i] = p.To.Sym + if p.To.Type != TYPE_MEM || p.To.Offset != 0 { + panic(fmt.Sprintf("bad funcdata: %v", p)) } + pcln.Funcdata[i] = p.To.Sym } } } diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index c8cd7bf09e..f319c10b5b 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -623,33 +623,24 @@ func (state *pclntab) generateFunctab(ctxt *Link, funcs []loader.Sym, inlSyms ma } // funcData returns the funcdata and offsets for the FuncInfo. -// The funcdata and offsets are written into runtime.functab after each func +// The funcdata are written into runtime.functab after each func // object. This is a helper function to make querying the FuncInfo object // cleaner. // -// Note, the majority of fdOffsets are 0, meaning there is no offset between -// the compiler's generated symbol, and what the runtime needs. They are -// plumbed through for no loss of generality. -// // NB: Preload must be called on the FuncInfo before calling. -// NB: fdSyms and fdOffs are used as scratch space. -func funcData(fi loader.FuncInfo, inlSym loader.Sym, fdSyms []loader.Sym, fdOffs []int64) ([]loader.Sym, []int64) { - fdSyms, fdOffs = fdSyms[:0], fdOffs[:0] +// NB: fdSyms is used as scratch space. +func funcData(ldr *loader.Loader, s loader.Sym, fi loader.FuncInfo, inlSym loader.Sym, fdSyms []loader.Sym) []loader.Sym { + fdSyms = fdSyms[:0] if fi.Valid() { - numOffsets := int(fi.NumFuncdataoff()) - for i := 0; i < numOffsets; i++ { - fdOffs = append(fdOffs, fi.Funcdataoff(i)) - } - fdSyms = fi.Funcdata(fdSyms) + fdSyms = ldr.Funcdata(s, fdSyms) if fi.NumInlTree() > 0 { if len(fdSyms) < objabi.FUNCDATA_InlTree+1 { fdSyms = append(fdSyms, make([]loader.Sym, objabi.FUNCDATA_InlTree+1-len(fdSyms))...) - fdOffs = append(fdOffs, make([]int64, objabi.FUNCDATA_InlTree+1-len(fdOffs))...) } fdSyms[objabi.FUNCDATA_InlTree] = inlSym } } - return fdSyms, fdOffs + return fdSyms } // calculateFunctabSize calculates the size of the pclntab, and the offsets in @@ -673,7 +664,7 @@ func (state pclntab) calculateFunctabSize(ctxt *Link, funcs []loader.Sym) (int64 size += int64(state.funcSize) if fi.Valid() { fi.Preload() - numFuncData := int(fi.NumFuncdataoff()) + numFuncData := ldr.NumFuncdata(s) if fi.NumInlTree() > 0 { if numFuncData < objabi.FUNCDATA_InlTree+1 { numFuncData = objabi.FUNCDATA_InlTree + 1 @@ -738,7 +729,7 @@ func writePCToFunc(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, sta // generateFunctab. func (state *pclntab) writeFuncData(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSyms map[loader.Sym]loader.Sym, startLocations []uint32, setAddr pclnSetAddr, setUint pclnSetUint) { ldr := ctxt.loader - funcdata, funcdataoff := []loader.Sym{}, []int64{} + funcdata := []loader.Sym{} for i, s := range funcs { fi := ldr.FuncInfo(s) if !fi.Valid() { @@ -748,18 +739,18 @@ func (state *pclntab) writeFuncData(ctxt *Link, sb *loader.SymbolBuilder, funcs // funcdata, must be pointer-aligned and we're only int32-aligned. // Missing funcdata will be 0 (nil pointer). - funcdata, funcdataoff := funcData(fi, inlSyms[s], funcdata, funcdataoff) + funcdata = funcData(ldr, s, fi, inlSyms[s], funcdata) if len(funcdata) > 0 { off := int64(startLocations[i] + state.funcSize + numPCData(ldr, s, fi)*4) off = Rnd(off, int64(ctxt.Arch.PtrSize)) for j := range funcdata { dataoff := off + int64(ctxt.Arch.PtrSize*j) if funcdata[j] == 0 { - setUint(sb, ctxt.Arch, dataoff, uint64(funcdataoff[j])) + setUint(sb, ctxt.Arch, dataoff, 0) continue } // TODO: Does this need deduping? - setAddr(sb, ctxt.Arch, dataoff, funcdata[j], funcdataoff[j]) + setAddr(sb, ctxt.Arch, dataoff, funcdata[j], 0) } } } @@ -769,7 +760,7 @@ func (state *pclntab) writeFuncData(ctxt *Link, sb *loader.SymbolBuilder, funcs func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSyms map[loader.Sym]loader.Sym, startLocations, cuOffsets []uint32, nameOffsets map[loader.Sym]uint32) { ldr := ctxt.loader deferReturnSym := ldr.Lookup("runtime.deferreturn", abiInternalVer) - funcdata, funcdataoff := []loader.Sym{}, []int64{} + funcdata := []loader.Sym{} var pcsp, pcfile, pcline, pcinline loader.Sym var pcdata []loader.Sym @@ -839,7 +830,7 @@ func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSym off += 1 // pad // nfuncdata must be the final entry. - funcdata, funcdataoff = funcData(fi, 0, funcdata, funcdataoff) + funcdata = funcData(ldr, s, fi, 0, funcdata) off = uint32(sb.SetUint8(ctxt.Arch, int64(off), uint8(len(funcdata)))) // Output the pcdata. diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index ec145da26d..9b7888e940 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -1930,12 +1930,38 @@ func (l *Loader) NumPcdata(i Sym) int { return n } +// Returns all funcdata symbols of symbol i. +// tmp is a scratch space. +func (l *Loader) Funcdata(i Sym, tmp []Sym) []Sym { + fd := tmp[:0] + r, auxs := l.auxs(i) + for j := range auxs { + a := &auxs[j] + if a.Type() == goobj.AuxFuncdata { + fd = append(fd, l.resolve(r, a.Sym())) + } + } + return fd +} + +// Returns the number of funcdata for symbol i. +func (l *Loader) NumFuncdata(i Sym) int { + n := 0 + _, auxs := l.auxs(i) + for j := range auxs { + a := &auxs[j] + if a.Type() == goobj.AuxFuncdata { + n++ + } + } + return n +} + // FuncInfo provides hooks to access goobj.FuncInfo in the objects. type FuncInfo struct { l *Loader r *oReader data []byte - auxs []goobj.Aux lengths goobj.FuncInfoLengths } @@ -1963,38 +1989,6 @@ func (fi *FuncInfo) Preload() { fi.lengths = (*goobj.FuncInfo)(nil).ReadFuncInfoLengths(fi.data) } -func (fi *FuncInfo) NumFuncdataoff() uint32 { - if !fi.lengths.Initialized { - panic("need to call Preload first") - } - return fi.lengths.NumFuncdataoff -} - -func (fi *FuncInfo) Funcdataoff(k int) int64 { - if !fi.lengths.Initialized { - panic("need to call Preload first") - } - return (*goobj.FuncInfo)(nil).ReadFuncdataoff(fi.data, fi.lengths.FuncdataoffOff, uint32(k)) -} - -func (fi *FuncInfo) Funcdata(syms []Sym) []Sym { - if !fi.lengths.Initialized { - panic("need to call Preload first") - } - if int(fi.lengths.NumFuncdataoff) > cap(syms) { - syms = make([]Sym, 0, fi.lengths.NumFuncdataoff) - } else { - syms = syms[:0] - } - for j := range fi.auxs { - a := &fi.auxs[j] - if a.Type() == goobj.AuxFuncdata { - syms = append(syms, fi.l.resolve(fi.r, a.Sym())) - } - } - return syms -} - func (fi *FuncInfo) NumFile() uint32 { if !fi.lengths.Initialized { panic("need to call Preload first") @@ -2051,7 +2045,7 @@ func (l *Loader) FuncInfo(i Sym) FuncInfo { a := &auxs[j] if a.Type() == goobj.AuxFuncInfo { b := r.Data(a.Sym().SymIdx) - return FuncInfo{l, r, b, auxs, goobj.FuncInfoLengths{}} + return FuncInfo{l, r, b, goobj.FuncInfoLengths{}} } } return FuncInfo{} -- GitLab From 3f224bbf9a52cf2e19cdd2ada4a6d7372cc70141 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 28 Sep 2021 20:42:45 -0700 Subject: [PATCH 1367/2500] go/types: avoid infinite recursion in unification This is an almost clean port of CL 352832 from types2 to go/types: The nest files and unify.go where copied verbatim; unify.go was adjusted with correct package name, a slightly different comment was restored to what it was. The test files got adjustments for error position. infer.go got a missing _Todo error code. For #48619. For #48656. Change-Id: Ia1a2d09e8bb37a85032b4b7e7c7a0b08e8c793a5 Reviewed-on: https://go-review.googlesource.com/c/go/+/353029 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/go/types/infer.go | 2 +- .../types/testdata/fixedbugs/issue48619.go2 | 22 +++++++++++ .../types/testdata/fixedbugs/issue48656.go2 | 13 +++++++ src/go/types/unify.go | 39 +++++++++++++++---- 4 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue48619.go2 create mode 100644 src/go/types/testdata/fixedbugs/issue48656.go2 diff --git a/src/go/types/infer.go b/src/go/types/infer.go index 0be01d31e8..3348c29476 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -128,7 +128,7 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, if inferred != tpar { check.errorf(arg, _Todo, "%s %s of %s does not match inferred type %s for %s", kind, targ, arg.expr, inferred, tpar) } else { - check.errorf(arg, 0, "%s %s of %s does not match %s", kind, targ, arg.expr, tpar) + check.errorf(arg, _Todo, "%s %s of %s does not match %s", kind, targ, arg.expr, tpar) } } diff --git a/src/go/types/testdata/fixedbugs/issue48619.go2 b/src/go/types/testdata/fixedbugs/issue48619.go2 new file mode 100644 index 0000000000..24650a3a70 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue48619.go2 @@ -0,0 +1,22 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func f[P any](a, _ P) { + var x int + f(a, x /* ERROR type int of x does not match P */) + f(x, a /* ERROR type P of a does not match inferred type int for P */) +} + +func g[P any](a, b P) { + g(a, b) + g(&a, &b) + g([]P{}, []P{}) +} + +func h[P any](a, b P) { + h(&a, &b) + h([]P{a}, []P{b}) +} diff --git a/src/go/types/testdata/fixedbugs/issue48656.go2 b/src/go/types/testdata/fixedbugs/issue48656.go2 new file mode 100644 index 0000000000..ee639e1042 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue48656.go2 @@ -0,0 +1,13 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +// TODO(gri) Still need better error positions and message here. +// But this doesn't crash anymore. + +func f[P /* ERROR does not match \*Q */ interface{*Q}, Q any](p P, q Q) { + _ = f[P] + _ = f /* ERROR cannot infer P */ [*P] +} diff --git a/src/go/types/unify.go b/src/go/types/unify.go index ce78fc8241..984ba59e6d 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -9,7 +9,6 @@ package types import ( "bytes" "fmt" - "sort" ) // The unifier maintains two separate sets of type parameters x and y @@ -64,6 +63,10 @@ func (u *unifier) unify(x, y Type) bool { type tparamsList struct { unifier *unifier tparams []*TypeParam + // For each tparams element, there is a corresponding mask bit in masks. + // If set, the corresponding type parameter is masked and doesn't appear + // as a type parameter with tparamsList.index. + masks []bool // For each tparams element, there is a corresponding type slot index in indices. // index < 0: unifier.types[-index-1] == nil // index == 0: no type slot allocated yet @@ -104,9 +107,14 @@ func (d *tparamsList) init(tparams []*TypeParam) { } } d.tparams = tparams + d.masks = make([]bool, len(tparams)) d.indices = make([]int, len(tparams)) } +// mask and unmask permit the masking/unmasking of the i'th type parameter of d. +func (d *tparamsList) mask(i int) { d.masks[i] = true } +func (d *tparamsList) unmask(i int) { d.masks[i] = false } + // join unifies the i'th type parameter of x with the j'th type parameter of y. // If both type parameters already have a type associated with them and they are // not joined, join fails and returns false. @@ -138,19 +146,25 @@ func (u *unifier) join(i, j int) bool { case ti > 0: // Only the type parameter for x has an inferred type. Use x slot for y. u.y.setIndex(j, ti) + // This case is handled like the default case. + // case tj > 0: + // // Only the type parameter for y has an inferred type. Use y slot for x. + // u.x.setIndex(i, tj) default: - // Either the type parameter for y has an inferred type, or neither type - // parameter has an inferred type. In either case, use y slot for x. + // Neither type parameter has an inferred type. Use y slot for x + // (or x slot for y, it doesn't matter). u.x.setIndex(i, tj) } return true } -// If typ is a type parameter of d, index returns the type parameter index. +// If typ is an unmasked type parameter of d, index returns the type parameter index. // Otherwise, the result is < 0. func (d *tparamsList) index(typ Type) int { if tpar, ok := typ.(*TypeParam); ok { - return tparamIndex(d.tparams, tpar) + if i := tparamIndex(d.tparams, tpar); i >= 0 && !d.masks[i] { + return i + } } return -1 } @@ -243,7 +257,7 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { } } - // Cases where at least one of x or y is a type parameter. + // Cases where at least one of x or y is an (unmasked) type parameter. switch i, j := u.x.index(x), u.y.index(y); { case i >= 0 && j >= 0: // both x and y are type parameters @@ -256,6 +270,12 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { case i >= 0: // x is a type parameter, y is not if tx := u.x.at(i); tx != nil { + // The inferred type tx may be or contain x again but we don't + // want to "unpack" it again when unifying tx with y: tx is the + // inferred type. Mask type parameter x for this recursion, so + // that subsequent encounters treat x like an ordinary type. + u.x.mask(i) + defer u.x.unmask(i) return u.nifyEq(tx, y, p) } // otherwise, infer type from y @@ -265,6 +285,9 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { case j >= 0: // y is a type parameter, x is not if ty := u.y.at(j); ty != nil { + // see comment above + u.y.mask(j) + defer u.y.unmask(j) return u.nifyEq(x, ty, p) } // otherwise, infer type from x @@ -399,8 +422,8 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { p = p.prev } if debug { - assert(sort.IsSorted(byUniqueMethodName(a))) - assert(sort.IsSorted(byUniqueMethodName(b))) + assertSortedMethods(a) + assertSortedMethods(b) } for i, f := range a { g := b[i] -- GitLab From aeb4fbabc0aaa5293dd34821c450855e9ff82230 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Tue, 28 Sep 2021 14:35:03 -0400 Subject: [PATCH 1368/2500] runtime: drop nowritebarrier from gcParkAssist Nothing in this function is at odds with having write barriers. It originally inherited the annotation from gcAssistAlloc http://golang.org/cl/30700, which subsequently dropped the annotation in http://golang.org/cl/32431 as it was unnecessary. Change-Id: Ie464e6b4ed957f57e922ec043728ff4e15bf35ad Reviewed-on: https://go-review.googlesource.com/c/go/+/352811 Trust: Michael Pratt Run-TryBot: Michael Pratt TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/runtime/mgcmark.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/runtime/mgcmark.go b/src/runtime/mgcmark.go index 64f1c79c36..eb5221443e 100644 --- a/src/runtime/mgcmark.go +++ b/src/runtime/mgcmark.go @@ -587,8 +587,6 @@ func gcWakeAllAssists() { // // gcParkAssist reports whether the assist is now satisfied. If it // returns false, the caller must retry the assist. -// -//go:nowritebarrier func gcParkAssist() bool { lock(&work.assistQueue.lock) // If the GC cycle finished while we were getting the lock, -- GitLab From c2de759581aef5d14fd07b843caf76db3c8a115b Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 28 Sep 2021 21:14:17 -0700 Subject: [PATCH 1369/2500] cmd/compile: make sure shapes have proper indexes for sub-instantiation The computation for determining the shapes to use at the top of getInstantation was not always creating shapes with the proper indexes. If an instantiation is being called from another instantiated function, we cannot just copy the shape types unchanged, because their indexes may have changed. So, for type args that already shapes, we still call Shapify() with the correct index. Fixes #48645 Change-Id: Ibb61c6f9a3c317220fb85135ca87eb5ad4dcff9e Reviewed-on: https://go-review.googlesource.com/c/go/+/353030 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 15 ++--- test/typeparam/issue48645a.go | 31 +++++++++ test/typeparam/issue48645a.out | 1 + test/typeparam/issue48645b.go | 81 +++++++++++++++++++++++ 4 files changed, 118 insertions(+), 10 deletions(-) create mode 100644 test/typeparam/issue48645a.go create mode 100644 test/typeparam/issue48645a.out create mode 100644 test/typeparam/issue48645b.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index e49702c04c..2bc1756b8d 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -610,21 +610,16 @@ func (g *irgen) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMeth // number of instantiations we have to generate. You can actually have a mix // of shape and non-shape arguments, because of inferred or explicitly // specified concrete type args. - var s1 []*types.Type + s1 := make([]*types.Type, len(shapes)) for i, t := range shapes { if !t.IsShape() { - if s1 == nil { - s1 = make([]*types.Type, len(shapes)) - copy(s1[0:i], shapes[0:i]) - } s1[i] = typecheck.Shapify(t, i) - } else if s1 != nil { - s1[i] = shapes[i] + } else { + // Already a shape, but make sure it has the correct index. + s1[i] = typecheck.Shapify(shapes[i].Underlying(), i) } } - if s1 != nil { - shapes = s1 - } + shapes = s1 sym := typecheck.MakeFuncInstSym(nameNode.Sym(), shapes, false, isMeth) info := g.instInfoMap[sym] diff --git a/test/typeparam/issue48645a.go b/test/typeparam/issue48645a.go new file mode 100644 index 0000000000..8d5aac94c6 --- /dev/null +++ b/test/typeparam/issue48645a.go @@ -0,0 +1,31 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + "reflect" +) + +type Stream[T any] struct { +} + +func (s Stream[T]) DropWhile() Stream[T] { + return Pipe[T, T](s) +} + +func Pipe[T, R any](s Stream[T]) Stream[R] { + it := func(fn func(R) bool) { + } + fmt.Println(reflect.TypeOf(it).String()) + return Stream[R]{} +} + +func main() { + s := Stream[int]{} + s = s.DropWhile() +} diff --git a/test/typeparam/issue48645a.out b/test/typeparam/issue48645a.out new file mode 100644 index 0000000000..5093d0f0ff --- /dev/null +++ b/test/typeparam/issue48645a.out @@ -0,0 +1 @@ +func(func(int) bool) diff --git a/test/typeparam/issue48645b.go b/test/typeparam/issue48645b.go new file mode 100644 index 0000000000..0f3a7f230a --- /dev/null +++ b/test/typeparam/issue48645b.go @@ -0,0 +1,81 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type Iterator[T any] interface { + Iterate(fn func(T) bool) +} + +type IteratorFunc[T any] func(fn func(T) bool) + +func (f IteratorFunc[T]) Iterate(fn func(T) bool) { + f(fn) +} + +type Stream[T any] struct { + it Iterator[T] +} + +func (s Stream[T]) Iterate(fn func(T) bool) { + if s.it == nil { + return + } + s.it.Iterate(fn) +} + +func FromIterator[T any](it Iterator[T]) Stream[T] { + return Stream[T]{it: it} +} + +func (s Stream[T]) DropWhile(fn func(T) bool) Stream[T] { + return Pipe[T, T](s, func(t T) (T, bool) { + return t, true + }) +} + +func Pipe[T, R any](s Stream[T], op func(d T) (R, bool)) Stream[R] { + it := func(fn func(R) bool) { + // XXX Not getting the closure right when converting to interface. + // s.it.Iterate(func(t T) bool { + // r, ok := op(t) + // if !ok { + // return true + // } + + // return fn(r) + // }) + } + + return FromIterator[R](IteratorFunc[R](it)) +} + +func Reduce[T, U any](s Stream[T], identity U, acc func(U, T) U) (r U) { + r = identity + s.Iterate(func(t T) bool { + r = acc(r, t) + return true + }) + + return r +} + +type myIterator struct { +} + +func (myIterator) Iterate(fn func(int) bool) { +} + +func main() { + s := Stream[int]{} + s.it = myIterator{} + s = s.DropWhile(func(i int) bool { + return false + }) + Reduce(s, nil, func(acc []int, e int) []int { + return append(acc, e) + }) +} -- GitLab From 2fad7dbb893737a01c7ab4f382720a2b0440b736 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 28 Sep 2021 13:13:49 -0700 Subject: [PATCH 1370/2500] debug/gosym: add hook to disable recovers debug/gosym assumes throughout that bogus input means a malformed file. That's generally true, but not when you're changing the package. In that case, the panic usually indicates a newly introduced bug, and seeing the panic is really useful. Add a manually-enabled way to make panics panic. Change-Id: I07af6c7b982c4cf61180db29f07aa63576ba7837 Reviewed-on: https://go-review.googlesource.com/c/go/+/352949 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/debug/gosym/pclntab.go | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/debug/gosym/pclntab.go b/src/debug/gosym/pclntab.go index 555add67e3..5d65b7826a 100644 --- a/src/debug/gosym/pclntab.go +++ b/src/debug/gosym/pclntab.go @@ -193,10 +193,12 @@ func (t *LineTable) parsePclnTab() { // Error paths through this code will default the version to 1.1. t.version = ver11 - defer func() { - // If we panic parsing, assume it's a Go 1.1 pclntab. - recover() - }() + if !disableRecover { + defer func() { + // If we panic parsing, assume it's a Go 1.1 pclntab. + recover() + }() + } // Check header: 4-byte magic, two zeros, pc quantum, pointer size. if len(t.Data) < 16 || t.Data[4] != 0 || t.Data[5] != 0 || @@ -265,9 +267,11 @@ func (t *LineTable) parsePclnTab() { // go12Funcs returns a slice of Funcs derived from the Go 1.2 pcln table. func (t *LineTable) go12Funcs() []Func { // Assume it is malformed and return nil on error. - defer func() { - recover() - }() + if !disableRecover { + defer func() { + recover() + }() + } n := len(t.functab) / int(t.ptrsize) / 2 funcs := make([]Func, n) @@ -441,7 +445,7 @@ func (t *LineTable) findFileLine(entry uint64, filetab, linetab uint32, filenum, // go12PCToLine maps program counter to line number for the Go 1.2 pcln table. func (t *LineTable) go12PCToLine(pc uint64) (line int) { defer func() { - if recover() != nil { + if !disableRecover && recover() != nil { line = -1 } }() @@ -458,7 +462,7 @@ func (t *LineTable) go12PCToLine(pc uint64) (line int) { // go12PCToFile maps program counter to file name for the Go 1.2 pcln table. func (t *LineTable) go12PCToFile(pc uint64) (file string) { defer func() { - if recover() != nil { + if !disableRecover && recover() != nil { file = "" } }() @@ -490,7 +494,7 @@ func (t *LineTable) go12PCToFile(pc uint64) (file string) { // go12LineToPC maps a (file, line) pair to a program counter for the Go 1.2/1.16 pcln table. func (t *LineTable) go12LineToPC(file string, line int) (pc uint64) { defer func() { - if recover() != nil { + if !disableRecover && recover() != nil { pc = 0 } }() @@ -552,12 +556,18 @@ func (t *LineTable) initFileMap() { // Every key maps to obj. That's not a very interesting map, but it provides // a way for callers to obtain the list of files in the program. func (t *LineTable) go12MapFiles(m map[string]*Obj, obj *Obj) { - defer func() { - recover() - }() + if !disableRecover { + defer func() { + recover() + }() + } t.initFileMap() for file := range t.fileMap { m[file] = obj } } + +// disableRecover causes this package not to swallow panics. +// This is useful when making changes. +const disableRecover = false -- GitLab From 10186e8d691f2af92c17034a70b01ca7eb9f4fee Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 28 Sep 2021 15:57:09 -0700 Subject: [PATCH 1371/2500] debug/gosym: adjust go12* method comments These methods are for use with Go 1.2 _and later_ pcln tables. Make that clearer. Change-Id: Iee06e0828fd5895639b654363b6d91bf9151d224 Reviewed-on: https://go-review.googlesource.com/c/go/+/352950 Trust: Josh Bleecher Snyder Reviewed-by: Cherry Mui --- src/debug/gosym/pclntab.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/debug/gosym/pclntab.go b/src/debug/gosym/pclntab.go index 5d65b7826a..5d18410a78 100644 --- a/src/debug/gosym/pclntab.go +++ b/src/debug/gosym/pclntab.go @@ -264,7 +264,7 @@ func (t *LineTable) parsePclnTab() { t.version = possibleVersion } -// go12Funcs returns a slice of Funcs derived from the Go 1.2 pcln table. +// go12Funcs returns a slice of Funcs derived from the Go 1.2+ pcln table. func (t *LineTable) go12Funcs() []Func { // Assume it is malformed and return nil on error. if !disableRecover { @@ -442,7 +442,7 @@ func (t *LineTable) findFileLine(entry uint64, filetab, linetab uint32, filenum, return 0 } -// go12PCToLine maps program counter to line number for the Go 1.2 pcln table. +// go12PCToLine maps program counter to line number for the Go 1.2+ pcln table. func (t *LineTable) go12PCToLine(pc uint64) (line int) { defer func() { if !disableRecover && recover() != nil { @@ -459,7 +459,7 @@ func (t *LineTable) go12PCToLine(pc uint64) (line int) { return int(t.pcvalue(linetab, entry, pc)) } -// go12PCToFile maps program counter to file name for the Go 1.2 pcln table. +// go12PCToFile maps program counter to file name for the Go 1.2+ pcln table. func (t *LineTable) go12PCToFile(pc uint64) (file string) { defer func() { if !disableRecover && recover() != nil { @@ -491,7 +491,7 @@ func (t *LineTable) go12PCToFile(pc uint64) (file string) { return "" } -// go12LineToPC maps a (file, line) pair to a program counter for the Go 1.2/1.16 pcln table. +// go12LineToPC maps a (file, line) pair to a program counter for the Go 1.2+ pcln table. func (t *LineTable) go12LineToPC(file string, line int) (pc uint64) { defer func() { if !disableRecover && recover() != nil { -- GitLab From b35c668072204c2ef2773df383bab5b04b7abca6 Mon Sep 17 00:00:00 2001 From: Archana R Date: Fri, 24 Sep 2021 10:31:20 -0500 Subject: [PATCH 1372/2500] cmd/compile: add PPC64-specific inlining for runtime.memmove Add rule to PPC64.rules to inline runtime.memmove in more cases, as is done for other target architectures Updated tests in codegen/copy.go to verify changes are done on ppc64/ppc64le Updates #41662 Change-Id: Id937ce21f9b4f4047b3e66dfa3c960128ee16a2a Reviewed-on: https://go-review.googlesource.com/c/go/+/352054 Run-TryBot: Lynn Boger TryBot-Result: Go Bot Reviewed-by: Cherry Mui Trust: Lynn Boger --- src/cmd/compile/internal/ssa/gen/PPC64.rules | 19 +++++ src/cmd/compile/internal/ssa/rewritePPC64.go | 78 ++++++++++++++++++++ test/codegen/copy.go | 8 ++ 3 files changed, 105 insertions(+) diff --git a/src/cmd/compile/internal/ssa/gen/PPC64.rules b/src/cmd/compile/internal/ssa/gen/PPC64.rules index 411bb8d29d..4b11e81fa2 100644 --- a/src/cmd/compile/internal/ssa/gen/PPC64.rules +++ b/src/cmd/compile/internal/ssa/gen/PPC64.rules @@ -1451,3 +1451,22 @@ && i1 == i0+1 && i2 == i0+2 && i3 == i0+3 && i4 == i0+4 && i5 == i0+5 && i6 == i0+6 && i7 == i0+7 && clobber(x0, x1, x2, x3, x4, x5, x6) => (MOVDBRstore (MOVDaddr [i0] {s} p) w mem) + +// Arch-specific inlining for small or disjoint runtime.memmove +(SelectN [0] call:(CALLstatic {sym} s1:(MOVDstore _ (MOVDconst [sz]) s2:(MOVDstore _ src s3:(MOVDstore {t} _ dst mem))))) + && sz >= 0 + && isSameCall(sym, "runtime.memmove") + && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 + && isInlinableMemmove(dst, src, sz, config) + && clobber(s1, s2, s3, call) + => (Move [sz] dst src mem) + +// Match post-lowering calls, register version. +(SelectN [0] call:(CALLstatic {sym} dst src (MOVDconst [sz]) mem)) + && sz >= 0 + && isSameCall(sym, "runtime.memmove") + && call.Uses == 1 + && isInlinableMemmove(dst, src, sz, config) + && clobber(call) + => (Move [sz] dst src mem) + diff --git a/src/cmd/compile/internal/ssa/rewritePPC64.go b/src/cmd/compile/internal/ssa/rewritePPC64.go index b35331a624..6127fd262b 100644 --- a/src/cmd/compile/internal/ssa/rewritePPC64.go +++ b/src/cmd/compile/internal/ssa/rewritePPC64.go @@ -720,6 +720,8 @@ func rewriteValuePPC64(v *Value) bool { return rewriteValuePPC64_OpRsh8x64(v) case OpRsh8x8: return rewriteValuePPC64_OpRsh8x8(v) + case OpSelectN: + return rewriteValuePPC64_OpSelectN(v) case OpSignExt16to32: v.Op = OpPPC64MOVHreg return true @@ -16439,6 +16441,82 @@ func rewriteValuePPC64_OpRsh8x8(v *Value) bool { return true } } +func rewriteValuePPC64_OpSelectN(v *Value) bool { + v_0 := v.Args[0] + b := v.Block + config := b.Func.Config + // match: (SelectN [0] call:(CALLstatic {sym} s1:(MOVDstore _ (MOVDconst [sz]) s2:(MOVDstore _ src s3:(MOVDstore {t} _ dst mem))))) + // cond: sz >= 0 && isSameCall(sym, "runtime.memmove") && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, sz, config) && clobber(s1, s2, s3, call) + // result: (Move [sz] dst src mem) + for { + if auxIntToInt64(v.AuxInt) != 0 { + break + } + call := v_0 + if call.Op != OpPPC64CALLstatic || len(call.Args) != 1 { + break + } + sym := auxToCall(call.Aux) + s1 := call.Args[0] + if s1.Op != OpPPC64MOVDstore { + break + } + _ = s1.Args[2] + s1_1 := s1.Args[1] + if s1_1.Op != OpPPC64MOVDconst { + break + } + sz := auxIntToInt64(s1_1.AuxInt) + s2 := s1.Args[2] + if s2.Op != OpPPC64MOVDstore { + break + } + _ = s2.Args[2] + src := s2.Args[1] + s3 := s2.Args[2] + if s3.Op != OpPPC64MOVDstore { + break + } + mem := s3.Args[2] + dst := s3.Args[1] + if !(sz >= 0 && isSameCall(sym, "runtime.memmove") && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, sz, config) && clobber(s1, s2, s3, call)) { + break + } + v.reset(OpMove) + v.AuxInt = int64ToAuxInt(sz) + v.AddArg3(dst, src, mem) + return true + } + // match: (SelectN [0] call:(CALLstatic {sym} dst src (MOVDconst [sz]) mem)) + // cond: sz >= 0 && isSameCall(sym, "runtime.memmove") && call.Uses == 1 && isInlinableMemmove(dst, src, sz, config) && clobber(call) + // result: (Move [sz] dst src mem) + for { + if auxIntToInt64(v.AuxInt) != 0 { + break + } + call := v_0 + if call.Op != OpPPC64CALLstatic || len(call.Args) != 4 { + break + } + sym := auxToCall(call.Aux) + mem := call.Args[3] + dst := call.Args[0] + src := call.Args[1] + call_2 := call.Args[2] + if call_2.Op != OpPPC64MOVDconst { + break + } + sz := auxIntToInt64(call_2.AuxInt) + if !(sz >= 0 && isSameCall(sym, "runtime.memmove") && call.Uses == 1 && isInlinableMemmove(dst, src, sz, config) && clobber(call)) { + break + } + v.reset(OpMove) + v.AuxInt = int64ToAuxInt(sz) + v.AddArg3(dst, src, mem) + return true + } + return false +} func rewriteValuePPC64_OpSlicemask(v *Value) bool { v_0 := v.Args[0] b := v.Block diff --git a/test/codegen/copy.go b/test/codegen/copy.go index ea8a01f803..9b3bf75b7a 100644 --- a/test/codegen/copy.go +++ b/test/codegen/copy.go @@ -103,6 +103,8 @@ func moveArchLowering1(b []byte, x *[1]byte) { _ = b[1] // amd64:-".*memmove" // arm64:-".*memmove" + // ppc64:-".*memmove" + // ppc64le:-".*memmove" copy(b, x[:]) } @@ -110,6 +112,8 @@ func moveArchLowering2(b []byte, x *[2]byte) { _ = b[2] // amd64:-".*memmove" // arm64:-".*memmove" + // ppc64:-".*memmove" + // ppc64le:-".*memmove" copy(b, x[:]) } @@ -117,6 +121,8 @@ func moveArchLowering4(b []byte, x *[4]byte) { _ = b[4] // amd64:-".*memmove" // arm64:-".*memmove" + // ppc64:-".*memmove" + // ppc64le:-".*memmove" copy(b, x[:]) } @@ -124,6 +130,8 @@ func moveArchLowering8(b []byte, x *[8]byte) { _ = b[8] // amd64:-".*memmove" // arm64:-".*memmove" + // ppc64:-".*memmove" + // ppc64le:-".*memmove" copy(b, x[:]) } -- GitLab From 99d5d8ab6b6819f84bb62aeb3b1eaefaab01989f Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 29 Sep 2021 09:35:02 -0400 Subject: [PATCH 1373/2500] go/types, types2: rename Environment to Context Replace the name Environment with Context, as discussed in #47916. Along the way, fix some stale or inaccurate comments. The Environment type remains temporarily as an alias for Context, to allow the x/tools Trybot to pass until dependency on types.Environment can be removed. Updates #47916 Change-Id: Iffd069ab0e8adebf4207c8f8891468a64d32b7cc Reviewed-on: https://go-review.googlesource.com/c/go/+/353089 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/cmd/compile/internal/noder/import.go | 6 +-- src/cmd/compile/internal/noder/irgen.go | 4 +- src/cmd/compile/internal/noder/reader2.go | 4 +- src/cmd/compile/internal/noder/unified.go | 2 +- src/cmd/compile/internal/types2/api.go | 7 ++- src/cmd/compile/internal/types2/check.go | 6 +-- .../types2/{environment.go => context.go} | 42 ++++++++--------- src/cmd/compile/internal/types2/decl.go | 4 +- .../compile/internal/types2/instantiate.go | 35 +++++++------- .../internal/types2/instantiate_test.go | 14 +++--- src/cmd/compile/internal/types2/named.go | 46 +++++++++---------- src/cmd/compile/internal/types2/object.go | 2 +- src/cmd/compile/internal/types2/signature.go | 2 +- src/cmd/compile/internal/types2/subst.go | 18 ++++---- src/cmd/compile/internal/types2/typestring.go | 28 +++++------ src/go/types/api.go | 7 ++- src/go/types/check.go | 6 +-- src/go/types/{environment.go => context.go} | 46 ++++++++++--------- src/go/types/decl.go | 4 +- src/go/types/instantiate.go | 35 +++++++------- src/go/types/instantiate_test.go | 14 +++--- src/go/types/named.go | 46 +++++++++---------- src/go/types/object.go | 2 +- src/go/types/signature.go | 2 +- src/go/types/subst.go | 18 ++++---- src/go/types/typestring.go | 28 +++++------ 26 files changed, 214 insertions(+), 214 deletions(-) rename src/cmd/compile/internal/types2/{environment.go => context.go} (67%) rename src/go/types/{environment.go => context.go} (65%) diff --git a/src/cmd/compile/internal/noder/import.go b/src/cmd/compile/internal/noder/import.go index f13f8ca7f5..f065c97763 100644 --- a/src/cmd/compile/internal/noder/import.go +++ b/src/cmd/compile/internal/noder/import.go @@ -43,12 +43,12 @@ var haveLegacyImports = false // for an imported package by overloading writeNewExportFunc, then // that payload will be mapped into memory and passed to // newReadImportFunc. -var newReadImportFunc = func(data string, pkg1 *types.Pkg, env *types2.Environment, packages map[string]*types2.Package) (pkg2 *types2.Package, err error) { +var newReadImportFunc = func(data string, pkg1 *types.Pkg, env *types2.Context, packages map[string]*types2.Package) (pkg2 *types2.Package, err error) { panic("unexpected new export data payload") } type gcimports struct { - env *types2.Environment + env *types2.Context packages map[string]*types2.Package } @@ -224,7 +224,7 @@ func parseImportPath(pathLit *syntax.BasicLit) (string, error) { // readImportFile reads the import file for the given package path and // returns its types.Pkg representation. If packages is non-nil, the // types2.Package representation is also returned. -func readImportFile(path string, target *ir.Package, env *types2.Environment, packages map[string]*types2.Package) (pkg1 *types.Pkg, pkg2 *types2.Package, err error) { +func readImportFile(path string, target *ir.Package, env *types2.Context, packages map[string]*types2.Package) (pkg1 *types.Pkg, pkg2 *types2.Package, err error) { path, err = resolveImportPath(path) if err != nil { return diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index c1a4f30f4a..6a09c2ee0c 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -34,13 +34,13 @@ func checkFiles(noders []*noder) (posMap, *types2.Package, *types2.Info) { } // typechecking - env := types2.NewEnvironment() + env := types2.NewContext() importer := gcimports{ env: env, packages: map[string]*types2.Package{"unsafe": types2.Unsafe}, } conf := types2.Config{ - Environment: env, + Context: env, GoVersion: base.Flag.Lang, IgnoreLabels: true, // parser already checked via syntax.CheckBranches mode CompilerErrorMessages: true, // use error strings matching existing compiler errors diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index dcd9a65f40..de7211305b 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -16,7 +16,7 @@ import ( type pkgReader2 struct { pkgDecoder - env *types2.Environment + env *types2.Context imports map[string]*types2.Package posBases []*syntax.PosBase @@ -24,7 +24,7 @@ type pkgReader2 struct { typs []types2.Type } -func readPackage2(env *types2.Environment, imports map[string]*types2.Package, input pkgDecoder) *types2.Package { +func readPackage2(env *types2.Context, imports map[string]*types2.Package, input pkgDecoder) *types2.Package { pr := pkgReader2{ pkgDecoder: input, diff --git a/src/cmd/compile/internal/noder/unified.go b/src/cmd/compile/internal/noder/unified.go index 3d4650a01f..ee76ff34af 100644 --- a/src/cmd/compile/internal/noder/unified.go +++ b/src/cmd/compile/internal/noder/unified.go @@ -78,7 +78,7 @@ func unified(noders []*noder) { base.Errorf("cannot use -G and -d=quirksmode together") } - newReadImportFunc = func(data string, pkg1 *types.Pkg, env *types2.Environment, packages map[string]*types2.Package) (pkg2 *types2.Package, err error) { + newReadImportFunc = func(data string, pkg1 *types.Pkg, env *types2.Context, packages map[string]*types2.Package) (pkg2 *types2.Package, err error) { pr := newPkgDecoder(pkg1.Path, data) // Read package descriptors for both types2 and compiler backend. diff --git a/src/cmd/compile/internal/types2/api.go b/src/cmd/compile/internal/types2/api.go index b0e86357b7..faf570c32e 100644 --- a/src/cmd/compile/internal/types2/api.go +++ b/src/cmd/compile/internal/types2/api.go @@ -108,10 +108,9 @@ type ImporterFrom interface { // A Config specifies the configuration for type checking. // The zero value for Config is a ready-to-use default configuration. type Config struct { - // Environment is the environment used for resolving global - // identifiers. If nil, the type checker will initialize this - // field with a newly created environment. - Environment *Environment + // Context is the context used for resolving global identifiers. If nil, the + // type checker will initialize this field with a newly created context. + Context *Context // GoVersion describes the accepted Go language version. The string // must follow the format "go%d.%d" (e.g. "go1.12") or ist must be diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go index e45598e0ef..5957518c17 100644 --- a/src/cmd/compile/internal/types2/check.go +++ b/src/cmd/compile/internal/types2/check.go @@ -170,9 +170,9 @@ func NewChecker(conf *Config, pkg *Package, info *Info) *Checker { conf = new(Config) } - // make sure we have an environment - if conf.Environment == nil { - conf.Environment = NewEnvironment() + // make sure we have a context + if conf.Context == nil { + conf.Context = NewContext() } // make sure we have an info struct diff --git a/src/cmd/compile/internal/types2/environment.go b/src/cmd/compile/internal/types2/context.go similarity index 67% rename from src/cmd/compile/internal/types2/environment.go rename to src/cmd/compile/internal/types2/context.go index fe9a3099fe..a8f8591243 100644 --- a/src/cmd/compile/internal/types2/environment.go +++ b/src/cmd/compile/internal/types2/context.go @@ -9,21 +9,21 @@ import ( "sync" ) -// An Environment is an opaque type checking environment. It may be used to -// share identical type instances across type-checked packages or calls to +// An Context is an opaque type checking context. It may be used to share +// identical type instances across type-checked packages or calls to // Instantiate. // // It is safe for concurrent use. -type Environment struct { +type Context struct { mu sync.Mutex typeMap map[string]*Named // type hash -> instance nextID int // next unique ID seen map[*Named]int // assigned unique IDs } -// NewEnvironment creates a new Environment. -func NewEnvironment() *Environment { - return &Environment{ +// NewContext creates a new Context. +func NewContext() *Context { + return &Context{ typeMap: make(map[string]*Named), seen: make(map[*Named]int), } @@ -33,12 +33,12 @@ func NewEnvironment() *Environment { // type hash: types that are identical produce identical string representations. // If typ is a *Named type and targs is not empty, typ is printed as if it were // instantiated with targs. The result is guaranteed to not contain blanks (" "). -func (env *Environment) TypeHash(typ Type, targs []Type) string { - assert(env != nil) +func (ctxt *Context) TypeHash(typ Type, targs []Type) string { + assert(ctxt != nil) assert(typ != nil) var buf bytes.Buffer - h := newTypeHasher(&buf, env) + h := newTypeHasher(&buf, ctxt) if named, _ := typ.(*Named); named != nil && len(targs) > 0 { // Don't use WriteType because we need to use the provided targs // and not any targs that might already be with the *Named type. @@ -55,27 +55,27 @@ func (env *Environment) TypeHash(typ Type, targs []Type) string { // typeForHash returns the recorded type for the type hash h, if it exists. // If no type exists for h and n is non-nil, n is recorded for h. -func (env *Environment) typeForHash(h string, n *Named) *Named { - env.mu.Lock() - defer env.mu.Unlock() - if existing := env.typeMap[h]; existing != nil { +func (ctxt *Context) typeForHash(h string, n *Named) *Named { + ctxt.mu.Lock() + defer ctxt.mu.Unlock() + if existing := ctxt.typeMap[h]; existing != nil { return existing } if n != nil { - env.typeMap[h] = n + ctxt.typeMap[h] = n } return n } // idForType returns a unique ID for the pointer n. -func (env *Environment) idForType(n *Named) int { - env.mu.Lock() - defer env.mu.Unlock() - id, ok := env.seen[n] +func (ctxt *Context) idForType(n *Named) int { + ctxt.mu.Lock() + defer ctxt.mu.Unlock() + id, ok := ctxt.seen[n] if !ok { - id = env.nextID - env.seen[n] = id - env.nextID++ + id = ctxt.nextID + ctxt.seen[n] = id + ctxt.nextID++ } return id } diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 326763d9b7..128e89dec6 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -69,7 +69,7 @@ func (check *Checker) objDecl(obj Object, def *Named) { // Funcs with m.instRecv set have not yet be completed. Complete them now // so that they have a type when objDecl exits. if m, _ := obj.(*Func); m != nil && m.instRecv != nil { - check.completeMethod(check.conf.Environment, m) + check.completeMethod(check.conf.Context, m) } // Checking the declaration of obj means inferring its type @@ -330,7 +330,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { } case *Named: - t.resolve(check.conf.Environment) + t.resolve(check.conf.Context) // don't touch the type if it is from a different package or the Universe scope // (doing so would lead to a race condition - was issue #35049) diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 7a9279943c..5da371f201 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -20,9 +20,8 @@ import ( // *Signature). Any methods attached to a *Named are simply copied; they are // not instantiated. // -// If env is non-nil, it may be used to de-dupe the instance against previous -// instances with the same identity. This functionality is implemented for -// environments with non-nil Checkers. +// If ctxt is non-nil, it may be used to de-dupe the instance against previous +// instances with the same identity. // // If verify is set and constraint satisfaction fails, the returned error may // be of dynamic type ArgumentError indicating which type argument did not @@ -30,8 +29,8 @@ import ( // // TODO(rfindley): change this function to also return an error if lengths of // tparams and targs do not match. -func Instantiate(env *Environment, typ Type, targs []Type, validate bool) (Type, error) { - inst := (*Checker)(nil).instance(nopos, typ, targs, env) +func Instantiate(ctxt *Context, typ Type, targs []Type, validate bool) (Type, error) { + inst := (*Checker)(nil).instance(nopos, typ, targs, ctxt) var err error if validate { @@ -71,7 +70,7 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, posLis }() } - inst := check.instance(pos, typ, targs, check.conf.Environment) + inst := check.instance(pos, typ, targs, check.conf.Context) assert(len(posList) <= len(targs)) check.later(func() { @@ -103,28 +102,28 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, posLis // instance creates a type or function instance using the given original type // typ and arguments targs. For Named types the resulting instance will be // unexpanded. -func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type, env *Environment) Type { +func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type, ctxt *Context) Type { switch t := typ.(type) { case *Named: var h string - if env != nil { - h = env.TypeHash(t, targs) + if ctxt != nil { + h = ctxt.TypeHash(t, targs) // typ may already have been instantiated with identical type arguments. In // that case, re-use the existing instance. - if named := env.typeForHash(h, nil); named != nil { + if named := ctxt.typeForHash(h, nil); named != nil { return named } } tname := NewTypeName(pos, t.obj.pkg, t.obj.name, nil) named := check.newNamed(tname, t, nil, nil, nil) // methods and tparams are set when named is resolved named.targs = NewTypeList(targs) - named.resolver = func(env *Environment, n *Named) (*TypeParamList, Type, []*Func) { - return expandNamed(env, n, pos) + named.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, []*Func) { + return expandNamed(ctxt, n, pos) } - if env != nil { - // It's possible that we've lost a race to add named to the environment. - // In this case, use whichever instance is recorded in the environment. - named = env.typeForHash(h, named) + if ctxt != nil { + // It's possible that we've lost a race to add named to the context. + // In this case, use whichever instance is recorded in the context. + named = ctxt.typeForHash(h, named) } return named @@ -136,7 +135,7 @@ func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type, env *Envi if tparams.Len() == 0 { return typ // nothing to do (minor optimization) } - sig := check.subst(pos, typ, makeSubstMap(tparams.list(), targs), env).(*Signature) + sig := check.subst(pos, typ, makeSubstMap(tparams.list(), targs), ctxt).(*Signature) // If the signature doesn't use its type parameters, subst // will not make a copy. In that case, make a copy now (so // we can set tparams to nil w/o causing side-effects). @@ -192,7 +191,7 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap // TODO(rfindley): it would be great if users could pass in a qualifier here, // rather than falling back to verbose qualification. Maybe this can be part - // of a the shared environment. + // of the shared context. var qf Qualifier if check != nil { qf = check.qualifier diff --git a/src/cmd/compile/internal/types2/instantiate_test.go b/src/cmd/compile/internal/types2/instantiate_test.go index 5d37f29b6b..a99fc5d032 100644 --- a/src/cmd/compile/internal/types2/instantiate_test.go +++ b/src/cmd/compile/internal/types2/instantiate_test.go @@ -18,12 +18,12 @@ func TestInstantiateEquality(t *testing.T) { T := pkg.Scope().Lookup("T").Type().(*Named) // Instantiating the same type twice should result in pointer-equivalent // instances. - env := NewEnvironment() - res1, err := Instantiate(env, T, []Type{Typ[Int]}, false) + ctxt := NewContext() + res1, err := Instantiate(ctxt, T, []Type{Typ[Int]}, false) if err != nil { t.Fatal(err) } - res2, err := Instantiate(env, T, []Type{Typ[Int]}, false) + res2, err := Instantiate(ctxt, T, []Type{Typ[Int]}, false) if err != nil { t.Fatal(err) } @@ -42,15 +42,15 @@ func TestInstantiateNonEquality(t *testing.T) { t.Fatal(err) } // We consider T1 and T2 to be distinct types, so their instances should not - // be deduplicated by the environment. + // be deduplicated by the context. T1 := pkg1.Scope().Lookup("T").Type().(*Named) T2 := pkg2.Scope().Lookup("T").Type().(*Named) - env := NewEnvironment() - res1, err := Instantiate(env, T1, []Type{Typ[Int]}, false) + ctxt := NewContext() + res1, err := Instantiate(ctxt, T1, []Type{Typ[Int]}, false) if err != nil { t.Fatal(err) } - res2, err := Instantiate(env, T2, []Type{Typ[Int]}, false) + res2, err := Instantiate(ctxt, T2, []Type{Typ[Int]}, false) if err != nil { t.Fatal(err) } diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index bc4d4f89c5..3971e03179 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -22,7 +22,7 @@ type Named struct { methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily // resolver may be provided to lazily resolve type parameters, underlying, and methods. - resolver func(*Environment, *Named) (tparams *TypeParamList, underlying Type, methods []*Func) + resolver func(*Context, *Named) (tparams *TypeParamList, underlying Type, methods []*Func) once sync.Once // ensures that tparams, underlying, and methods are resolved before accessing } @@ -36,7 +36,7 @@ func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named { return (*Checker)(nil).newNamed(obj, nil, underlying, nil, methods) } -func (t *Named) resolve(env *Environment) *Named { +func (t *Named) resolve(ctxt *Context) *Named { if t.resolver == nil { return t } @@ -50,7 +50,7 @@ func (t *Named) resolve(env *Environment) *Named { // methods would need to support reentrant calls though. It would // also make the API more future-proof towards further extensions // (like SetTypeParams). - t.tparams, t.underlying, t.methods = t.resolver(env, t) + t.tparams, t.underlying, t.methods = t.resolver(ctxt, t) t.fromRHS = t.underlying // for cycle detection }) return t @@ -217,37 +217,37 @@ func (n *Named) setUnderlying(typ Type) { } } -// bestEnv returns the best available environment. In order of preference: -// - the given env, if non-nil -// - the Checker env, if check is non-nil -// - a new environment -func (check *Checker) bestEnv(env *Environment) *Environment { - if env != nil { - return env +// bestContext returns the best available context. In order of preference: +// - the given ctxt, if non-nil +// - check.Config.Context, if check is non-nil +// - a new Context +func (check *Checker) bestContext(ctxt *Context) *Context { + if ctxt != nil { + return ctxt } if check != nil { - assert(check.conf.Environment != nil) - return check.conf.Environment + assert(check.conf.Context != nil) + return check.conf.Context } - return NewEnvironment() + return NewContext() } // expandNamed ensures that the underlying type of n is instantiated. // The underlying type will be Typ[Invalid] if there was an error. -func expandNamed(env *Environment, n *Named, instPos syntax.Pos) (tparams *TypeParamList, underlying Type, methods []*Func) { - n.orig.resolve(env) +func expandNamed(ctxt *Context, n *Named, instPos syntax.Pos) (tparams *TypeParamList, underlying Type, methods []*Func) { + n.orig.resolve(ctxt) check := n.check if check.validateTArgLen(instPos, n.orig.tparams.Len(), n.targs.Len()) { - // We must always have an env, to avoid infinite recursion. - env = check.bestEnv(env) - h := env.TypeHash(n.orig, n.targs.list()) + // We must always have a context, to avoid infinite recursion. + ctxt = check.bestContext(ctxt) + h := ctxt.TypeHash(n.orig, n.targs.list()) // ensure that an instance is recorded for h to avoid infinite recursion. - env.typeForHash(h, n) + ctxt.typeForHash(h, n) smap := makeSubstMap(n.orig.tparams.list(), n.targs.list()) - underlying = n.check.subst(instPos, n.orig.underlying, smap, env) + underlying = n.check.subst(instPos, n.orig.underlying, smap, ctxt) for i := 0; i < n.orig.NumMethods(); i++ { origm := n.orig.Method(i) @@ -272,7 +272,7 @@ func expandNamed(env *Environment, n *Named, instPos syntax.Pos) (tparams *TypeP completeMethods := func() { for _, m := range methods { if m.instRecv != nil { - check.completeMethod(env, m) + check.completeMethod(ctxt, m) } } } @@ -285,7 +285,7 @@ func expandNamed(env *Environment, n *Named, instPos syntax.Pos) (tparams *TypeP return n.orig.tparams, underlying, methods } -func (check *Checker) completeMethod(env *Environment, m *Func) { +func (check *Checker) completeMethod(ctxt *Context, m *Func) { assert(m.instRecv != nil) rbase := m.instRecv m.instRecv = nil @@ -306,7 +306,7 @@ func (check *Checker) completeMethod(env *Environment, m *Func) { } smap := makeSubstMap(origSig.RecvTypeParams().list(), rbase.targs.list()) - sig := check.subst(orig.pos, origSig, smap, env).(*Signature) + sig := check.subst(orig.pos, origSig, smap, ctxt).(*Signature) if sig == origSig { // No substitution occurred, but we still need to create a new signature to // hold the instantiated receiver. diff --git a/src/cmd/compile/internal/types2/object.go b/src/cmd/compile/internal/types2/object.go index 2e1cd7bff1..affeaf61f2 100644 --- a/src/cmd/compile/internal/types2/object.go +++ b/src/cmd/compile/internal/types2/object.go @@ -281,7 +281,7 @@ func NewTypeName(pos syntax.Pos, pkg *Package, name string, typ Type) *TypeName func NewTypeNameLazy(pos syntax.Pos, pkg *Package, name string, load func(named *Named) (tparams []*TypeParam, underlying Type, methods []*Func)) *TypeName { obj := NewTypeName(pos, pkg, name, nil) - resolve := func(_ *Environment, t *Named) (*TypeParamList, Type, []*Func) { + resolve := func(_ *Context, t *Named) (*TypeParamList, Type, []*Func) { tparams, underlying, methods := load(t) switch underlying.(type) { diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index a5348b3b14..803dd8e5e7 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -234,7 +234,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] var err string switch T := rtyp.(type) { case *Named: - T.resolve(check.conf.Environment) + T.resolve(check.conf.Context) // The receiver type may be an instantiated type referred to // by an alias (which cannot have receiver parameters for now). if T.TypeArgs() != nil && sig.RecvTypeParams() == nil { diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 5e057a6f80..a5ebd416aa 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -37,8 +37,8 @@ func (m substMap) lookup(tpar *TypeParam) Type { // incoming type. If a substitution took place, the result type is different // from the incoming type. // -// If the given environment is non-nil, it is used in lieu of check.env. -func (check *Checker) subst(pos syntax.Pos, typ Type, smap substMap, env *Environment) Type { +// If the given context is non-nil, it is used in lieu of check.Config.Context. +func (check *Checker) subst(pos syntax.Pos, typ Type, smap substMap, ctxt *Context) Type { if smap.empty() { return typ } @@ -56,7 +56,7 @@ func (check *Checker) subst(pos syntax.Pos, typ Type, smap substMap, env *Enviro pos: pos, smap: smap, check: check, - env: check.bestEnv(env), + ctxt: check.bestContext(ctxt), } return subst.typ(typ) } @@ -65,7 +65,7 @@ type subster struct { pos syntax.Pos smap substMap check *Checker // nil if called via Instantiate - env *Environment + ctxt *Context } func (subst *subster) typ(typ Type) Type { @@ -205,19 +205,19 @@ func (subst *subster) typ(typ Type) Type { } // before creating a new named type, check if we have this one already - h := subst.env.TypeHash(t.orig, newTArgs) + h := subst.ctxt.TypeHash(t.orig, newTArgs) dump(">>> new type hash: %s", h) - if named := subst.env.typeForHash(h, nil); named != nil { + if named := subst.ctxt.typeForHash(h, nil); named != nil { dump(">>> found %s", named) return named } - // Create a new instance and populate the environment to avoid endless + // Create a new instance and populate the context to avoid endless // recursion. The position used here is irrelevant because validation only // occurs on t (we don't call validType on named), but we use subst.pos to // help with debugging. - t.orig.resolve(subst.env) - return subst.check.instance(subst.pos, t.orig, newTArgs, subst.env) + t.orig.resolve(subst.ctxt) + return subst.check.instance(subst.pos, t.orig, newTArgs, subst.ctxt) // Note that if we were to expose substitution more generally (not just in // the context of a declaration), we'd have to substitute in diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index bdafcf883d..930acf053a 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -67,20 +67,20 @@ type typeWriter struct { buf *bytes.Buffer seen map[Type]bool qf Qualifier - env *Environment // if non-nil, we are type hashing + ctxt *Context // if non-nil, we are type hashing } func newTypeWriter(buf *bytes.Buffer, qf Qualifier) *typeWriter { return &typeWriter{buf, make(map[Type]bool), qf, nil} } -func newTypeHasher(buf *bytes.Buffer, env *Environment) *typeWriter { - assert(env != nil) - return &typeWriter{buf, make(map[Type]bool), nil, env} +func newTypeHasher(buf *bytes.Buffer, ctxt *Context) *typeWriter { + assert(ctxt != nil) + return &typeWriter{buf, make(map[Type]bool), nil, ctxt} } func (w *typeWriter) byte(b byte) { - if w.env != nil { + if w.ctxt != nil { if b == ' ' { b = '#' } @@ -98,7 +98,7 @@ func (w *typeWriter) string(s string) { } func (w *typeWriter) error(msg string) { - if w.env != nil { + if w.ctxt != nil { panic(msg) } w.buf.WriteString("<" + msg + ">") @@ -154,7 +154,7 @@ func (w *typeWriter) typ(typ Type) { if tag := t.Tag(i); tag != "" { w.byte(' ') // TODO(gri) If tag contains blanks, replacing them with '#' - // in Environment.TypeHash may produce another tag + // in Context.TypeHash may produce another tag // accidentally. w.string(strconv.Quote(tag)) } @@ -247,7 +247,7 @@ func (w *typeWriter) typ(typ Type) { if t.targs != nil { // instantiated type w.typeList(t.targs.list()) - } else if w.env == nil && t.TypeParams().Len() != 0 { // For type hashing, don't need to format the TParams + } else if w.ctxt == nil && t.TypeParams().Len() != 0 { // For type hashing, don't need to format the TParams // parameterized type w.tParamList(t.TypeParams().list()) } @@ -276,12 +276,12 @@ func (w *typeWriter) typ(typ Type) { } } -// If w.env is non-nil, typePrefix writes a unique prefix for the named type t -// based on the types already observed by w.env. If w.env is nil, it does +// If w.ctxt is non-nil, typePrefix writes a unique prefix for the named type t +// based on the types already observed by w.ctxt. If w.ctxt is nil, it does // nothing. func (w *typeWriter) typePrefix(t *Named) { - if w.env != nil { - w.string(strconv.Itoa(w.env.idForType(t))) + if w.ctxt != nil { + w.string(strconv.Itoa(w.ctxt.idForType(t))) } } @@ -340,7 +340,7 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) { w.byte(',') } // parameter names are ignored for type identity and thus type hashes - if w.env == nil && v.name != "" { + if w.ctxt == nil && v.name != "" { w.string(v.name) w.byte(' ') } @@ -381,7 +381,7 @@ func (w *typeWriter) signature(sig *Signature) { } w.byte(' ') - if n == 1 && (w.env != nil || sig.results.vars[0].name == "") { + if n == 1 && (w.ctxt != nil || sig.results.vars[0].name == "") { // single unnamed result (if type hashing, name must be ignored) w.typ(sig.results.vars[0].typ) return diff --git a/src/go/types/api.go b/src/go/types/api.go index 0bbd940d07..c115d07b41 100644 --- a/src/go/types/api.go +++ b/src/go/types/api.go @@ -112,10 +112,9 @@ type ImporterFrom interface { // A Config specifies the configuration for type checking. // The zero value for Config is a ready-to-use default configuration. type Config struct { - // Environment is the environment used for resolving global - // identifiers. If nil, the type checker will initialize this - // field with a newly created environment. - Environment *Environment + // Context is the context used for resolving global identifiers. If nil, the + // type checker will initialize this field with a newly created context. + Context *Context // GoVersion describes the accepted Go language version. The string // must follow the format "go%d.%d" (e.g. "go1.12") or it must be diff --git a/src/go/types/check.go b/src/go/types/check.go index a55c01c17d..cfcdd68de3 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -173,9 +173,9 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch conf = new(Config) } - // make sure we have an environment - if conf.Environment == nil { - conf.Environment = NewEnvironment() + // make sure we have a context + if conf.Context == nil { + conf.Context = NewContext() } // make sure we have an info struct diff --git a/src/go/types/environment.go b/src/go/types/context.go similarity index 65% rename from src/go/types/environment.go rename to src/go/types/context.go index b818f81564..bbdaade632 100644 --- a/src/go/types/environment.go +++ b/src/go/types/context.go @@ -10,21 +10,25 @@ import ( "sync" ) -// An Environment is an opaque type checking environment. It may be used to -// share identical type instances across type-checked packages or calls to +// An Context is an opaque type checking context. It may be used to share +// identical type instances across type-checked packages or calls to // Instantiate. // // It is safe for concurrent use. -type Environment struct { +type Context struct { mu sync.Mutex typeMap map[string]*Named // type hash -> instance nextID int // next unique ID seen map[*Named]int // assigned unique IDs } -// NewEnvironment creates a new Environment. -func NewEnvironment() *Environment { - return &Environment{ +// Temporary alias to allow x/tools tests to pass. +// TODO(rfindley): remove the Environment type. +type Environment = Context + +// NewContext creates a new Context. +func NewContext() *Context { + return &Context{ typeMap: make(map[string]*Named), seen: make(map[*Named]int), } @@ -34,12 +38,12 @@ func NewEnvironment() *Environment { // type hash: types that are identical produce identical string representations. // If typ is a *Named type and targs is not empty, typ is printed as if it were // instantiated with targs. The result is guaranteed to not contain blanks (" "). -func (env *Environment) typeHash(typ Type, targs []Type) string { - assert(env != nil) +func (ctxt *Context) typeHash(typ Type, targs []Type) string { + assert(ctxt != nil) assert(typ != nil) var buf bytes.Buffer - h := newTypeHasher(&buf, env) + h := newTypeHasher(&buf, ctxt) if named, _ := typ.(*Named); named != nil && len(targs) > 0 { // Don't use WriteType because we need to use the provided targs // and not any targs that might already be with the *Named type. @@ -56,27 +60,27 @@ func (env *Environment) typeHash(typ Type, targs []Type) string { // typeForHash returns the recorded type for the type hash h, if it exists. // If no type exists for h and n is non-nil, n is recorded for h. -func (env *Environment) typeForHash(h string, n *Named) *Named { - env.mu.Lock() - defer env.mu.Unlock() - if existing := env.typeMap[h]; existing != nil { +func (ctxt *Context) typeForHash(h string, n *Named) *Named { + ctxt.mu.Lock() + defer ctxt.mu.Unlock() + if existing := ctxt.typeMap[h]; existing != nil { return existing } if n != nil { - env.typeMap[h] = n + ctxt.typeMap[h] = n } return n } // idForType returns a unique ID for the pointer n. -func (env *Environment) idForType(n *Named) int { - env.mu.Lock() - defer env.mu.Unlock() - id, ok := env.seen[n] +func (ctxt *Context) idForType(n *Named) int { + ctxt.mu.Lock() + defer ctxt.mu.Unlock() + id, ok := ctxt.seen[n] if !ok { - id = env.nextID - env.seen[n] = id - env.nextID++ + id = ctxt.nextID + ctxt.seen[n] = id + ctxt.nextID++ } return id } diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 77914dd1af..d0809f5a6e 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -68,7 +68,7 @@ func (check *Checker) objDecl(obj Object, def *Named) { // Funcs with m.instRecv set have not yet be completed. Complete them now // so that they have a type when objDecl exits. if m, _ := obj.(*Func); m != nil && m.instRecv != nil { - check.completeMethod(check.conf.Environment, m) + check.completeMethod(check.conf.Context, m) } // Checking the declaration of obj means inferring its type @@ -329,7 +329,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { } case *Named: - t.resolve(check.conf.Environment) + t.resolve(check.conf.Context) // don't touch the type if it is from a different package or the Universe scope // (doing so would lead to a race condition - was issue #35049) if t.obj.pkg != check.pkg { diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 6cafc2fbed..2a255bcb87 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -20,9 +20,8 @@ import ( // *Signature). Any methods attached to a *Named are simply copied; they are // not instantiated. // -// If env is non-nil, it may be used to de-dupe the instance against previous -// instances with the same identity. This functionality is currently -// unimplemented. +// If ctxt is non-nil, it may be used to de-dupe the instance against previous +// instances with the same identity. // // If verify is set and constraint satisfaction fails, the returned error may // wrap an *ArgumentError indicating which type argument did not satisfy its @@ -30,8 +29,8 @@ import ( // // TODO(rfindley): change this function to also return an error if lengths of // tparams and targs do not match. -func Instantiate(env *Environment, typ Type, targs []Type, validate bool) (Type, error) { - inst := (*Checker)(nil).instance(token.NoPos, typ, targs, env) +func Instantiate(ctxt *Context, typ Type, targs []Type, validate bool) (Type, error) { + inst := (*Checker)(nil).instance(token.NoPos, typ, targs, ctxt) var err error if validate { @@ -71,7 +70,7 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, posList }() } - inst := check.instance(pos, typ, targs, check.conf.Environment) + inst := check.instance(pos, typ, targs, check.conf.Context) assert(len(posList) <= len(targs)) check.later(func() { @@ -103,28 +102,28 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, posList // instance creates a type or function instance using the given original type // typ and arguments targs. For Named types the resulting instance will be // unexpanded. -func (check *Checker) instance(pos token.Pos, typ Type, targs []Type, env *Environment) Type { +func (check *Checker) instance(pos token.Pos, typ Type, targs []Type, ctxt *Context) Type { switch t := typ.(type) { case *Named: var h string - if env != nil { - h = env.typeHash(t, targs) + if ctxt != nil { + h = ctxt.typeHash(t, targs) // typ may already have been instantiated with identical type arguments. In // that case, re-use the existing instance. - if named := env.typeForHash(h, nil); named != nil { + if named := ctxt.typeForHash(h, nil); named != nil { return named } } tname := NewTypeName(pos, t.obj.pkg, t.obj.name, nil) named := check.newNamed(tname, t, nil, nil, nil) // methods and tparams are set when named is resolved named.targs = NewTypeList(targs) - named.resolver = func(env *Environment, n *Named) (*TypeParamList, Type, []*Func) { - return expandNamed(env, n, pos) + named.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, []*Func) { + return expandNamed(ctxt, n, pos) } - if env != nil { - // It's possible that we've lost a race to add named to the environment. - // In this case, use whichever instance is recorded in the environment. - named = env.typeForHash(h, named) + if ctxt != nil { + // It's possible that we've lost a race to add named to the context. + // In this case, use whichever instance is recorded in the context. + named = ctxt.typeForHash(h, named) } return named @@ -136,7 +135,7 @@ func (check *Checker) instance(pos token.Pos, typ Type, targs []Type, env *Envir if tparams.Len() == 0 { return typ // nothing to do (minor optimization) } - sig := check.subst(pos, typ, makeSubstMap(tparams.list(), targs), env).(*Signature) + sig := check.subst(pos, typ, makeSubstMap(tparams.list(), targs), ctxt).(*Signature) // If the signature doesn't use its type parameters, subst // will not make a copy. In that case, make a copy now (so // we can set tparams to nil w/o causing side-effects). @@ -191,7 +190,7 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap // TODO(rfindley): it would be great if users could pass in a qualifier here, // rather than falling back to verbose qualification. Maybe this can be part - // of a the shared environment. + // of the shared context. var qf Qualifier if check != nil { qf = check.qualifier diff --git a/src/go/types/instantiate_test.go b/src/go/types/instantiate_test.go index cf6d2a9198..832c822224 100644 --- a/src/go/types/instantiate_test.go +++ b/src/go/types/instantiate_test.go @@ -22,12 +22,12 @@ func TestInstantiateEquality(t *testing.T) { // Instantiating the same type twice should result in pointer-equivalent // instances. - env := NewEnvironment() - res1, err := Instantiate(env, T, []Type{Typ[Int]}, false) + ctxt := NewContext() + res1, err := Instantiate(ctxt, T, []Type{Typ[Int]}, false) if err != nil { t.Fatal(err) } - res2, err := Instantiate(env, T, []Type{Typ[Int]}, false) + res2, err := Instantiate(ctxt, T, []Type{Typ[Int]}, false) if err != nil { t.Fatal(err) } @@ -50,16 +50,16 @@ func TestInstantiateNonEquality(t *testing.T) { } // We consider T1 and T2 to be distinct types, so their instances should not - // be deduplicated by the environment. + // be deduplicated by the context. T1 := pkg1.Scope().Lookup("T").Type().(*Named) T2 := pkg2.Scope().Lookup("T").Type().(*Named) - env := NewEnvironment() - res1, err := Instantiate(env, T1, []Type{Typ[Int]}, false) + ctxt := NewContext() + res1, err := Instantiate(ctxt, T1, []Type{Typ[Int]}, false) if err != nil { t.Fatal(err) } - res2, err := Instantiate(env, T2, []Type{Typ[Int]}, false) + res2, err := Instantiate(ctxt, T2, []Type{Typ[Int]}, false) if err != nil { t.Fatal(err) } diff --git a/src/go/types/named.go b/src/go/types/named.go index d29c67d4eb..82b2afcb63 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -22,7 +22,7 @@ type Named struct { methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily // resolver may be provided to lazily resolve type parameters, underlying, and methods. - resolver func(*Environment, *Named) (tparams *TypeParamList, underlying Type, methods []*Func) + resolver func(*Context, *Named) (tparams *TypeParamList, underlying Type, methods []*Func) once sync.Once // ensures that tparams, underlying, and methods are resolved before accessing } @@ -36,7 +36,7 @@ func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named { return (*Checker)(nil).newNamed(obj, nil, underlying, nil, methods) } -func (t *Named) resolve(env *Environment) *Named { +func (t *Named) resolve(ctxt *Context) *Named { if t.resolver == nil { return t } @@ -50,7 +50,7 @@ func (t *Named) resolve(env *Environment) *Named { // methods would need to support reentrant calls though. It would // also make the API more future-proof towards further extensions // (like SetTypeParams). - t.tparams, t.underlying, t.methods = t.resolver(env, t) + t.tparams, t.underlying, t.methods = t.resolver(ctxt, t) t.fromRHS = t.underlying // for cycle detection }) return t @@ -219,37 +219,37 @@ func (n *Named) setUnderlying(typ Type) { } } -// bestEnv returns the best available environment. In order of preference: -// - the given env, if non-nil -// - the Checker env, if check is non-nil -// - a new environment -func (check *Checker) bestEnv(env *Environment) *Environment { - if env != nil { - return env +// bestContext returns the best available context. In order of preference: +// - the given ctxt, if non-nil +// - check.Config.Context, if check is non-nil +// - a new Context +func (check *Checker) bestContext(ctxt *Context) *Context { + if ctxt != nil { + return ctxt } if check != nil { - assert(check.conf.Environment != nil) - return check.conf.Environment + assert(check.conf.Context != nil) + return check.conf.Context } - return NewEnvironment() + return NewContext() } // expandNamed ensures that the underlying type of n is instantiated. // The underlying type will be Typ[Invalid] if there was an error. -func expandNamed(env *Environment, n *Named, instPos token.Pos) (tparams *TypeParamList, underlying Type, methods []*Func) { - n.orig.resolve(env) +func expandNamed(ctxt *Context, n *Named, instPos token.Pos) (tparams *TypeParamList, underlying Type, methods []*Func) { + n.orig.resolve(ctxt) check := n.check if check.validateTArgLen(instPos, n.orig.tparams.Len(), n.targs.Len()) { - // We must always have an env, to avoid infinite recursion. - env = check.bestEnv(env) - h := env.typeHash(n.orig, n.targs.list()) + // We must always have a context, to avoid infinite recursion. + ctxt = check.bestContext(ctxt) + h := ctxt.typeHash(n.orig, n.targs.list()) // ensure that an instance is recorded for h to avoid infinite recursion. - env.typeForHash(h, n) + ctxt.typeForHash(h, n) smap := makeSubstMap(n.orig.tparams.list(), n.targs.list()) - underlying = n.check.subst(instPos, n.orig.underlying, smap, env) + underlying = n.check.subst(instPos, n.orig.underlying, smap, ctxt) for i := 0; i < n.orig.NumMethods(); i++ { origm := n.orig.Method(i) @@ -274,7 +274,7 @@ func expandNamed(env *Environment, n *Named, instPos token.Pos) (tparams *TypePa completeMethods := func() { for _, m := range methods { if m.instRecv != nil { - check.completeMethod(env, m) + check.completeMethod(ctxt, m) } } } @@ -287,7 +287,7 @@ func expandNamed(env *Environment, n *Named, instPos token.Pos) (tparams *TypePa return n.orig.tparams, underlying, methods } -func (check *Checker) completeMethod(env *Environment, m *Func) { +func (check *Checker) completeMethod(ctxt *Context, m *Func) { assert(m.instRecv != nil) rbase := m.instRecv m.instRecv = nil @@ -308,7 +308,7 @@ func (check *Checker) completeMethod(env *Environment, m *Func) { } smap := makeSubstMap(origSig.RecvTypeParams().list(), rbase.targs.list()) - sig := check.subst(orig.pos, origSig, smap, env).(*Signature) + sig := check.subst(orig.pos, origSig, smap, ctxt).(*Signature) if sig == origSig { // No substitution occurred, but we still need to create a new signature to // hold the instantiated receiver. diff --git a/src/go/types/object.go b/src/go/types/object.go index 19e7fddeb6..18015fc967 100644 --- a/src/go/types/object.go +++ b/src/go/types/object.go @@ -235,7 +235,7 @@ func NewTypeName(pos token.Pos, pkg *Package, name string, typ Type) *TypeName { func _NewTypeNameLazy(pos token.Pos, pkg *Package, name string, load func(named *Named) (tparams []*TypeParam, underlying Type, methods []*Func)) *TypeName { obj := NewTypeName(pos, pkg, name, nil) - resolve := func(_ *Environment, t *Named) (*TypeParamList, Type, []*Func) { + resolve := func(_ *Context, t *Named) (*TypeParamList, Type, []*Func) { tparams, underlying, methods := load(t) switch underlying.(type) { diff --git a/src/go/types/signature.go b/src/go/types/signature.go index df38e7124b..c26437afe4 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -224,7 +224,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast var err string switch T := rtyp.(type) { case *Named: - T.resolve(check.conf.Environment) + T.resolve(check.conf.Context) // The receiver type may be an instantiated type referred to // by an alias (which cannot have receiver parameters for now). if T.TypeArgs() != nil && sig.RecvTypeParams() == nil { diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 25629dca8a..e539ab54e6 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -37,8 +37,8 @@ func (m substMap) lookup(tpar *TypeParam) Type { // that it doesn't modify the incoming type. If a substitution took place, the // result type is different from the incoming type. // -// If the given environment is non-nil, it is used in lieu of check.env. -func (check *Checker) subst(pos token.Pos, typ Type, smap substMap, env *Environment) Type { +// If the given context is non-nil, it is used in lieu of check.Config.Context +func (check *Checker) subst(pos token.Pos, typ Type, smap substMap, ctxt *Context) Type { if smap.empty() { return typ } @@ -56,7 +56,7 @@ func (check *Checker) subst(pos token.Pos, typ Type, smap substMap, env *Environ pos: pos, smap: smap, check: check, - env: check.bestEnv(env), + ctxt: check.bestContext(ctxt), } return subst.typ(typ) } @@ -65,7 +65,7 @@ type subster struct { pos token.Pos smap substMap check *Checker // nil if called via Instantiate - env *Environment + ctxt *Context } func (subst *subster) typ(typ Type) Type { @@ -205,19 +205,19 @@ func (subst *subster) typ(typ Type) Type { } // before creating a new named type, check if we have this one already - h := subst.env.typeHash(t.orig, newTArgs) + h := subst.ctxt.typeHash(t.orig, newTArgs) dump(">>> new type hash: %s", h) - if named := subst.env.typeForHash(h, nil); named != nil { + if named := subst.ctxt.typeForHash(h, nil); named != nil { dump(">>> found %s", named) return named } - // Create a new instance and populate the environment to avoid endless + // Create a new instance and populate the context to avoid endless // recursion. The position used here is irrelevant because validation only // occurs on t (we don't call validType on named), but we use subst.pos to // help with debugging. - t.orig.resolve(subst.env) - return subst.check.instance(subst.pos, t.orig, newTArgs, subst.env) + t.orig.resolve(subst.ctxt) + return subst.check.instance(subst.pos, t.orig, newTArgs, subst.ctxt) // Note that if we were to expose substitution more generally (not just in // the context of a declaration), we'd have to substitute in diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index e5dafc2e0d..4a087c4ed1 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -68,20 +68,20 @@ type typeWriter struct { buf *bytes.Buffer seen map[Type]bool qf Qualifier - env *Environment // if non-nil, we are type hashing + ctxt *Context // if non-nil, we are type hashing } func newTypeWriter(buf *bytes.Buffer, qf Qualifier) *typeWriter { return &typeWriter{buf, make(map[Type]bool), qf, nil} } -func newTypeHasher(buf *bytes.Buffer, env *Environment) *typeWriter { - assert(env != nil) - return &typeWriter{buf, make(map[Type]bool), nil, env} +func newTypeHasher(buf *bytes.Buffer, ctxt *Context) *typeWriter { + assert(ctxt != nil) + return &typeWriter{buf, make(map[Type]bool), nil, ctxt} } func (w *typeWriter) byte(b byte) { - if w.env != nil { + if w.ctxt != nil { if b == ' ' { b = '#' } @@ -99,7 +99,7 @@ func (w *typeWriter) string(s string) { } func (w *typeWriter) error(msg string) { - if w.env != nil { + if w.ctxt != nil { panic(msg) } w.buf.WriteString("<" + msg + ">") @@ -155,7 +155,7 @@ func (w *typeWriter) typ(typ Type) { if tag := t.Tag(i); tag != "" { w.byte(' ') // TODO(rfindley) If tag contains blanks, replacing them with '#' - // in Environment.TypeHash may produce another tag + // in Context.TypeHash may produce another tag // accidentally. w.string(strconv.Quote(tag)) } @@ -248,7 +248,7 @@ func (w *typeWriter) typ(typ Type) { if t.targs != nil { // instantiated type w.typeList(t.targs.list()) - } else if w.env == nil && t.TypeParams().Len() != 0 { // For type hashing, don't need to format the TypeParams + } else if w.ctxt == nil && t.TypeParams().Len() != 0 { // For type hashing, don't need to format the TypeParams // parameterized type w.tParamList(t.TypeParams().list()) } @@ -277,12 +277,12 @@ func (w *typeWriter) typ(typ Type) { } } -// If w.env is non-nil, typePrefix writes a unique prefix for the named type t -// based on the types already observed by w.env. If w.env is nil, it does +// If w.ctxt is non-nil, typePrefix writes a unique prefix for the named type t +// based on the types already observed by w.ctxt. If w.ctxt is nil, it does // nothing. func (w *typeWriter) typePrefix(t *Named) { - if w.env != nil { - w.string(strconv.Itoa(w.env.idForType(t))) + if w.ctxt != nil { + w.string(strconv.Itoa(w.ctxt.idForType(t))) } } @@ -341,7 +341,7 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) { w.byte(',') } // parameter names are ignored for type identity and thus type hashes - if w.env == nil && v.name != "" { + if w.ctxt == nil && v.name != "" { w.string(v.name) w.byte(' ') } @@ -382,7 +382,7 @@ func (w *typeWriter) signature(sig *Signature) { } w.byte(' ') - if n == 1 && (w.env != nil || sig.results.vars[0].name == "") { + if n == 1 && (w.ctxt != nil || sig.results.vars[0].name == "") { // single unnamed result (if type hashing, name must be ignored) w.typ(sig.results.vars[0].typ) return -- GitLab From c9af2bd21e86a218622b9c753cddfb5bba46d780 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Mon, 27 Sep 2021 16:12:05 -0400 Subject: [PATCH 1374/2500] cmd/go: prevent necessary GCFlag from being removed There are special flags that must be passed to the compiler at build time in order to instrument the testing binary for fuzzing. One potential option would be to add these flags to p.Internal.Gcflags inside cmd/go/internal/test. However, future calls to setToolFlags can cause these flags to get cleared about before the build starts, removing virtually all coverage guidance. This change moves the logic to add the flag deeper down the call stack, preventing it from being cleared. Change-Id: I40eadb0cacc18f29cee75379cd9380f9e73bb8da Reviewed-on: https://go-review.googlesource.com/c/go/+/352511 Trust: Katie Hockman Run-TryBot: Katie Hockman Reviewed-by: Bryan C. Mills Reviewed-by: Jay Conrod TryBot-Result: Go Bot --- src/cmd/go/internal/load/pkg.go | 1 + src/cmd/go/internal/test/test.go | 10 ++++------ src/cmd/go/internal/work/exec.go | 5 +++++ src/cmd/go/internal/work/gc.go | 3 +++ src/cmd/go/internal/work/init.go | 15 ++++++++------- 5 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index 4013330bc4..8a5a1a5fe2 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -203,6 +203,7 @@ type PackageInternal struct { Local bool // imported via local path (./ or ../) LocalPrefix string // interpret ./ and ../ imports relative to this prefix ExeName string // desired name for temporary executable + FuzzInstrument bool // package should be instrumented for fuzzing CoverMode string // preprocess Go source files with the coverage tool in this mode CoverVars map[string]*CoverVar // variables created by coverage analysis OmitDebug bool // tell linker not to write debug information diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 7c6f109cc5..a6c8631a37 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -818,12 +818,11 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { // Inform the compiler that it should instrument the binary at // build-time when fuzzing is enabled. - fuzzFlags := work.FuzzInstrumentFlags() - if testFuzz != "" && fuzzFlags != nil { + if testFuzz != "" { // Don't instrument packages which may affect coverage guidance but are // unlikely to be useful. Most of these are used by the testing or // internal/fuzz packages concurrently with fuzzing. - var fuzzNoInstrument = map[string]bool{ + var skipInstrumentation = map[string]bool{ "context": true, "internal/fuzz": true, "reflect": true, @@ -835,10 +834,9 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { "time": true, } for _, p := range load.TestPackageList(ctx, pkgOpts, pkgs) { - if fuzzNoInstrument[p.ImportPath] { - continue + if !skipInstrumentation[p.ImportPath] { + p.Internal.FuzzInstrument = true } - p.Internal.Gcflags = append(p.Internal.Gcflags, fuzzFlags...) } } diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index f82028aef6..692d394520 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -281,6 +281,11 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID { if p.Internal.CoverMode != "" { fmt.Fprintf(h, "cover %q %q\n", p.Internal.CoverMode, b.toolID("cover")) } + if p.Internal.FuzzInstrument { + if fuzzFlags := fuzzInstrumentFlags(); fuzzFlags != nil { + fmt.Fprintf(h, "fuzz %q\n", fuzzFlags) + } + } fmt.Fprintf(h, "modinfo %q\n", p.Internal.BuildInfo) // Configuration specific to compiler toolchain. diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go index fe0a45ec2a..414736cbd7 100644 --- a/src/cmd/go/internal/work/gc.go +++ b/src/cmd/go/internal/work/gc.go @@ -144,6 +144,9 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg } gcflags := str.StringList(forcedGcflags, p.Internal.Gcflags) + if p.Internal.FuzzInstrument { + gcflags = append(gcflags, fuzzInstrumentFlags()...) + } if compilingRuntime { // Remove -N, if present. // It is not possible to build the runtime with no optimizations, diff --git a/src/cmd/go/internal/work/init.go b/src/cmd/go/internal/work/init.go index 1f8ec02df1..6a29abb03b 100644 --- a/src/cmd/go/internal/work/init.go +++ b/src/cmd/go/internal/work/init.go @@ -60,18 +60,19 @@ func BuildInit() { } } -// FuzzInstrumentFlags returns compiler flags that enable fuzzing instrumation +// fuzzInstrumentFlags returns compiler flags that enable fuzzing instrumation // on supported platforms. // -// On unsupported platforms, FuzzInstrumentFlags returns nil, meaning no +// On unsupported platforms, fuzzInstrumentFlags returns nil, meaning no // instrumentation is added. 'go test -fuzz' still works without coverage, // but it generates random inputs without guidance, so it's much less effective. -func FuzzInstrumentFlags() []string { - // TODO: expand the set of supported platforms, with testing. - // Nothing about the instrumentation is OS specific, but only amd64 and arm64 - // are supported in the runtime. See src/runtime/libfuzzer*. +func fuzzInstrumentFlags() []string { + // TODO: expand the set of supported platforms, with testing. Nothing about + // the instrumentation is OS specific, but only amd64 and arm64 are + // supported in the runtime. See src/runtime/libfuzzer*. // - // Keep in sync with build constraints in internal/fuzz/counters_{un,}supported.go + // Keep in sync with build constraints in + // internal/fuzz/counters_{un,}supported.go switch cfg.Goos { case "darwin", "freebsd", "linux", "windows": default: -- GitLab From b8990ec932c21e503f28e95e8323dbd9a090ac28 Mon Sep 17 00:00:00 2001 From: Lynn Boger Date: Wed, 29 Sep 2021 09:24:50 -0500 Subject: [PATCH 1375/2500] test: update test/codegen/noextend.go to work with either ABI on ppc64x This updates the codegen tests in noextend.go so they are not dependent on the ABI. Change-Id: I8433bea9dc78830c143290a7e0cf901b2397d38a Reviewed-on: https://go-review.googlesource.com/c/go/+/353070 Trust: Lynn Boger Run-TryBot: Lynn Boger TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- test/codegen/noextend.go | 120 ++++++++++++++------------------------- 1 file changed, 44 insertions(+), 76 deletions(-) diff --git a/test/codegen/noextend.go b/test/codegen/noextend.go index 424fd2008d..d8e2917bf2 100644 --- a/test/codegen/noextend.go +++ b/test/codegen/noextend.go @@ -15,19 +15,18 @@ var val32 [8]uint32 var val16 [8]uint16 var val8 [8]uint8 -// ----------------------------- // -// avoid zero/sign extensions // -// ----------------------------- // +// Avoid zero/sign extensions following a load +// which has extended the value correctly. +// Note: No tests are done for int8 since +// an extra extension is usually needed due to +// no signed byte load. -func set16(x8 int8, u8 uint8, y8 int8, z8 uint8) { +func set16(x8 int8, u8 *uint8, y8 int8, z8 uint8) { // Truncate not needed, load does sign/zero extend - // ppc64:-"MOVB\tR\\d+,\\sR\\d+" - // ppc64le:-"MOVB\tR\\d+,\\sR\\d+" - sval16[0] = int16(x8) // ppc64:-"MOVBZ\tR\\d+,\\sR\\d+" // ppc64le:-"MOVBZ\tR\\d+,\\sR\\d+" - val16[0] = uint16(u8) + val16[0] = uint16(*u8) // AND not needed due to size // ppc64:-"ANDCC" @@ -36,217 +35,186 @@ func set16(x8 int8, u8 uint8, y8 int8, z8 uint8) { // ppc64:-"ANDCC" // ppc64le:-"ANDCC" - val16[1] = 255 & uint16(u8+z8) + val16[1] = 255 & uint16(*u8+z8) } -func shiftidx(x8 int8, u8 uint8, x16 int16, u16 uint16, x32 int32, u32 uint32) { - // ppc64:-"MOVB\tR\\d+,\\sR\\d+" - // ppc64le:-"MOVB\tR\\d+,\\sR\\d+" - sval16[0] = int16(val16[x8>>1]) +func shiftidx(u8 *uint8, x16 *int16, u16 *uint16) { // ppc64:-"MOVBZ\tR\\d+,\\sR\\d+" // ppc64le:-"MOVBZ\tR\\d+,\\sR\\d+" - val16[0] = uint16(sval16[u8>>2]) + val16[0] = uint16(sval16[*u8>>2]) // ppc64:-"MOVH\tR\\d+,\\sR\\d+" // ppc64le:-"MOVH\tR\\d+,\\sR\\d+" - sval16[1] = int16(val16[x16>>1]) + sval16[1] = int16(val16[*x16>>1]) // ppc64:-"MOVHZ\tR\\d+,\\sR\\d+" // ppc64le:-"MOVHZ\tR\\d+,\\sR\\d+" - val16[1] = uint16(sval16[u16>>2]) + val16[1] = uint16(sval16[*u16>>2]) } -func setnox(x8 int8, u8 uint8, y8 int8, z8 uint8, x16 int16, u16 uint16, x32 int32, u32 uint32) { - // Truncate not needed due to sign/zero extension on load - - // ppc64:-"MOVB\tR\\d+,\\sR\\d+" - // ppc64le:-"MOVB\tR\\d+,\\sR\\d+" - sval16[0] = int16(x8) +func setnox(x8 int8, u8 *uint8, y8 *int8, z8 *uint8, x16 *int16, u16 *uint16, x32 *int32, u32 *uint32) { // ppc64:-"MOVBZ\tR\\d+,\\sR\\d+" // ppc64le:-"MOVBZ\tR\\d+,\\sR\\d+" - val16[0] = uint16(u8) + val16[0] = uint16(*u8) // AND not needed due to size // ppc64:-"ANDCC" // ppc64le:-"ANDCC" - sval16[1] = 255 & int16(x8+y8) + sval16[1] = 255 & int16(x8+*y8) // ppc64:-"ANDCC" // ppc64le:-"ANDCC" - val16[1] = 255 & uint16(u8+z8) - - // ppc64:-"MOVB\tR\\d+,\\sR\\d+" - // ppc64le:-"MOVB\tR\\d+,\\sR\\d+" - sval32[0] = int32(x8) + val16[1] = 255 & uint16(*u8+*z8) // ppc64:-"MOVH\tR\\d+,\\sR\\d+" // ppc64le:-"MOVH\tR\\d+,\\sR\\d+" - sval32[1] = int32(x16) + sval32[1] = int32(*x16) //ppc64:-"MOVBZ\tR\\d+,\\sR\\d+" //ppc64le:-"MOVBZ\tR\\d+,\\sR\\d+" - val32[0] = uint32(u8) + val32[0] = uint32(*u8) // ppc64:-"MOVHZ\tR\\d+,\\sR\\d+" // ppc64le:-"MOVHZ\tR\\d+,\\sR\\d+" - val32[1] = uint32(u16) - - // ppc64:-"MOVB\tR\\d+,\\sR\\d+" - // ppc64le:-"MOVB\tR\\d+,\\sR\\d+" - sval64[0] = int64(x8) + val32[1] = uint32(*u16) // ppc64:-"MOVH\tR\\d+,\\sR\\d+" // ppc64le:-"MOVH\tR\\d+,\\sR\\d+" - sval64[1] = int64(x16) + sval64[1] = int64(*x16) // ppc64:-"MOVW\tR\\d+,\\sR\\d+" // ppc64le:-"MOVW\tR\\d+,\\sR\\d+" - sval64[2] = int64(x32) + sval64[2] = int64(*x32) //ppc64:-"MOVBZ\tR\\d+,\\sR\\d+" //ppc64le:-"MOVBZ\tR\\d+,\\sR\\d+" - val64[0] = uint64(u8) + val64[0] = uint64(*u8) // ppc64:-"MOVHZ\tR\\d+,\\sR\\d+" // ppc64le:-"MOVHZ\tR\\d+,\\sR\\d+" - val64[1] = uint64(u16) + val64[1] = uint64(*u16) // ppc64:-"MOVWZ\tR\\d+,\\sR\\d+" // ppc64le:-"MOVWZ\tR\\d+,\\sR\\d+" - val64[2] = uint64(u32) + val64[2] = uint64(*u32) } -func cmp16(x8 int8, u8 uint8, x32 int32, u32 uint32, x64 int64, u64 uint64) bool { - // ppc64:-"MOVB\tR\\d+,\\sR\\d+" - // ppc64le:-"MOVB\tR\\d+,\\sR\\d+" - if int16(x8) == sval16[0] { - return true - } +func cmp16(u8 *uint8, x32 *int32, u32 *uint32, x64 *int64, u64 *uint64) bool { // ppc64:-"MOVBZ\tR\\d+,\\sR\\d+" // ppc64le:-"MOVBZ\tR\\d+,\\sR\\d+" - if uint16(u8) == val16[0] { + if uint16(*u8) == val16[0] { return true } // ppc64:-"MOVHZ\tR\\d+,\\sR\\d+" // ppc64le:-"MOVHZ\tR\\d+,\\sR\\d+" - if uint16(u32>>16) == val16[0] { + if uint16(*u32>>16) == val16[0] { return true } // ppc64:-"MOVHZ\tR\\d+,\\sR\\d+" // ppc64le:-"MOVHZ\tR\\d+,\\sR\\d+" - if uint16(u64>>48) == val16[0] { + if uint16(*u64>>48) == val16[0] { return true } // Verify the truncates are using the correct sign. // ppc64:-"MOVHZ\tR\\d+,\\sR\\d+" // ppc64le:-"MOVHZ\tR\\d+,\\sR\\d+" - if int16(x32) == sval16[0] { + if int16(*x32) == sval16[0] { return true } // ppc64:-"MOVH\tR\\d+,\\sR\\d+" // ppc64le:-"MOVH\tR\\d+,\\sR\\d+" - if uint16(u32) == val16[0] { + if uint16(*u32) == val16[0] { return true } // ppc64:-"MOVHZ\tR\\d+,\\sR\\d+" // ppc64le:-"MOVHZ\tR\\d+,\\sR\\d+" - if int16(x64) == sval16[0] { + if int16(*x64) == sval16[0] { return true } // ppc64:-"MOVH\tR\\d+,\\sR\\d+" // ppc64le:-"MOVH\tR\\d+,\\sR\\d+" - if uint16(u64) == val16[0] { + if uint16(*u64) == val16[0] { return true } return false } -func cmp32(x8 int8, u8 uint8, x16 int16, u16 uint16, x64 int64, u64 uint64) bool { - // ppc64:-"MOVB\tR\\d+,\\sR\\d+" - // ppc64le:-"MOVB\tR\\d+,\\sR\\d+" - if int32(x8) == sval32[0] { - return true - } +func cmp32(u8 *uint8, x16 *int16, u16 *uint16, x64 *int64, u64 *uint64) bool { // ppc64:-"MOVBZ\tR\\d+,\\sR\\d+" // ppc64le:-"MOVBZ\tR\\d+,\\sR\\d+" - if uint32(u8) == val32[0] { + if uint32(*u8) == val32[0] { return true } // ppc64:-"MOVH\tR\\d+,\\sR\\d+" // ppc64le:-"MOVH\tR\\d+,\\sR\\d+" - if int32(x16) == sval32[0] { + if int32(*x16) == sval32[0] { return true } // ppc64:-"MOVHZ\tR\\d+,\\sR\\d+" // ppc64le:-"MOVHZ\tR\\d+,\\sR\\d+" - if uint32(u16) == val32[0] { + if uint32(*u16) == val32[0] { return true } // Verify the truncates are using the correct sign. // ppc64:-"MOVWZ\tR\\d+,\\sR\\d+" // ppc64le:-"MOVWZ\tR\\d+,\\sR\\d+" - if int32(x64) == sval32[0] { + if int32(*x64) == sval32[0] { return true } // ppc64:-"MOVW\tR\\d+,\\sR\\d+" // ppc64le:-"MOVW\tR\\d+,\\sR\\d+" - if uint32(u64) == val32[0] { + if uint32(*u64) == val32[0] { return true } return false } -func cmp64(x8 int8, u8 uint8, x16 int16, u16 uint16, x32 int32, u32 uint32) bool { - // ppc64:-"MOVB\tR\\d+,\\sR\\d+" - // ppc64le:-"MOVB\tR\\d+,\\sR\\d+" - if int64(x8) == sval64[0] { - return true - } +func cmp64(u8 *uint8, x16 *int16, u16 *uint16, x32 *int32, u32 *uint32) bool { // ppc64:-"MOVBZ\tR\\d+,\\sR\\d+" // ppc64le:-"MOVBZ\tR\\d+,\\sR\\d+" - if uint64(u8) == val64[0] { + if uint64(*u8) == val64[0] { return true } // ppc64:-"MOVH\tR\\d+,\\sR\\d+" // ppc64le:-"MOVH\tR\\d+,\\sR\\d+" - if int64(x16) == sval64[0] { + if int64(*x16) == sval64[0] { return true } // ppc64:-"MOVHZ\tR\\d+,\\sR\\d+" // ppc64le:-"MOVHZ\tR\\d+,\\sR\\d+" - if uint64(u16) == val64[0] { + if uint64(*u16) == val64[0] { return true } // ppc64:-"MOVW\tR\\d+,\\sR\\d+" // ppc64le:-"MOVW\tR\\d+,\\sR\\d+" - if int64(x32) == sval64[0] { + if int64(*x32) == sval64[0] { return true } // ppc64:-"MOVWZ\tR\\d+,\\sR\\d+" // ppc64le:-"MOVWZ\tR\\d+,\\sR\\d+" - if uint64(u32) == val64[0] { + if uint64(*u32) == val64[0] { return true } return false -- GitLab From a9d5ea650b39ed144ea32a41fb551c038fb48f0c Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 28 Sep 2021 17:42:05 -0700 Subject: [PATCH 1376/2500] runtime: use unsafe.Slice in getStackMap It's not less code, but it is clearer code. Change-Id: I32239baf92487a56900a4edd8a2593014f37d093 Reviewed-on: https://go-review.googlesource.com/c/go/+/352953 Trust: Josh Bleecher Snyder Trust: Brad Fitzpatrick Run-TryBot: Josh Bleecher Snyder Reviewed-by: Brad Fitzpatrick --- src/runtime/stack.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/runtime/stack.go b/src/runtime/stack.go index 22fff73947..0946e6975a 100644 --- a/src/runtime/stack.go +++ b/src/runtime/stack.go @@ -1327,7 +1327,8 @@ func getStackMap(frame *stkframe, cache *pcvalueCache, debug bool) (locals, args if p != nil { n := *(*uintptr)(p) p = add(p, goarch.PtrSize) - *(*slice)(unsafe.Pointer(&objs)) = slice{array: noescape(p), len: int(n), cap: int(n)} + r0 := (*stackObjectRecord)(noescape(p)) + objs = unsafe.Slice(r0, int(n)) // Note: the noescape above is needed to keep // getStackMap from "leaking param content: // frame". That leak propagates up to getgcmask, then -- GitLab From e48cf0db4edb139901946fcee1497bd539229d71 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 29 Sep 2021 13:05:37 -0400 Subject: [PATCH 1377/2500] cmd/compile: rename some types2.Context variables from env to ctxt Rename some variables in the compiler that were missed in CL 353089. Change-Id: Ie748fe9b64e584a841d08ff60c439c93aae412d7 Reviewed-on: https://go-review.googlesource.com/c/go/+/353149 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/importer/iimport.go | 2 +- src/cmd/compile/internal/noder/import.go | 4 ++-- src/cmd/compile/internal/noder/irgen.go | 6 +++--- src/cmd/compile/internal/noder/reader2.go | 8 ++++---- src/cmd/compile/internal/noder/unified.go | 4 ++-- src/go/internal/gcimporter/iimport.go | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index b99956de26..b9d2ecbdb5 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -660,7 +660,7 @@ func (r *importReader) doType(base *types2.Named) types2.Type { baseType := r.typ() // The imported instantiated type doesn't include any methods, so // we must always use the methods of the base (orig) type. - // TODO provide a non-nil *Environment + // TODO provide a non-nil *Context t, _ := types2.Instantiate(nil, baseType, targs, false) return t diff --git a/src/cmd/compile/internal/noder/import.go b/src/cmd/compile/internal/noder/import.go index f065c97763..0aaf894641 100644 --- a/src/cmd/compile/internal/noder/import.go +++ b/src/cmd/compile/internal/noder/import.go @@ -48,7 +48,7 @@ var newReadImportFunc = func(data string, pkg1 *types.Pkg, env *types2.Context, } type gcimports struct { - env *types2.Context + ctxt *types2.Context packages map[string]*types2.Package } @@ -61,7 +61,7 @@ func (m *gcimports) ImportFrom(path, srcDir string, mode types2.ImportMode) (*ty panic("mode must be 0") } - _, pkg, err := readImportFile(path, typecheck.Target, m.env, m.packages) + _, pkg, err := readImportFile(path, typecheck.Target, m.ctxt, m.packages) return pkg, err } diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index 6a09c2ee0c..b0a4da3536 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -34,13 +34,13 @@ func checkFiles(noders []*noder) (posMap, *types2.Package, *types2.Info) { } // typechecking - env := types2.NewContext() + ctxt := types2.NewContext() importer := gcimports{ - env: env, + ctxt: ctxt, packages: map[string]*types2.Package{"unsafe": types2.Unsafe}, } conf := types2.Config{ - Context: env, + Context: ctxt, GoVersion: base.Flag.Lang, IgnoreLabels: true, // parser already checked via syntax.CheckBranches mode CompilerErrorMessages: true, // use error strings matching existing compiler errors diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index de7211305b..d474db2427 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -16,7 +16,7 @@ import ( type pkgReader2 struct { pkgDecoder - env *types2.Context + ctxt *types2.Context imports map[string]*types2.Package posBases []*syntax.PosBase @@ -24,11 +24,11 @@ type pkgReader2 struct { typs []types2.Type } -func readPackage2(env *types2.Context, imports map[string]*types2.Package, input pkgDecoder) *types2.Package { +func readPackage2(ctxt *types2.Context, imports map[string]*types2.Package, input pkgDecoder) *types2.Package { pr := pkgReader2{ pkgDecoder: input, - env: env, + ctxt: ctxt, imports: imports, posBases: make([]*syntax.PosBase, input.numElems(relocPosBase)), @@ -231,7 +231,7 @@ func (r *reader2) doTyp() (res types2.Type) { obj, targs := r.obj() name := obj.(*types2.TypeName) if len(targs) != 0 { - t, _ := types2.Instantiate(r.p.env, name.Type(), targs, false) + t, _ := types2.Instantiate(r.p.ctxt, name.Type(), targs, false) return t } return name.Type() diff --git a/src/cmd/compile/internal/noder/unified.go b/src/cmd/compile/internal/noder/unified.go index ee76ff34af..ec0012db4c 100644 --- a/src/cmd/compile/internal/noder/unified.go +++ b/src/cmd/compile/internal/noder/unified.go @@ -78,12 +78,12 @@ func unified(noders []*noder) { base.Errorf("cannot use -G and -d=quirksmode together") } - newReadImportFunc = func(data string, pkg1 *types.Pkg, env *types2.Context, packages map[string]*types2.Package) (pkg2 *types2.Package, err error) { + newReadImportFunc = func(data string, pkg1 *types.Pkg, ctxt *types2.Context, packages map[string]*types2.Package) (pkg2 *types2.Package, err error) { pr := newPkgDecoder(pkg1.Path, data) // Read package descriptors for both types2 and compiler backend. readPackage(newPkgReader(pr), pkg1) - pkg2 = readPackage2(env, packages, pr) + pkg2 = readPackage2(ctxt, packages, pr) return } diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go index 2a02c04ef3..e61a3a51a1 100644 --- a/src/go/internal/gcimporter/iimport.go +++ b/src/go/internal/gcimporter/iimport.go @@ -652,7 +652,7 @@ func (r *importReader) doType(base *types.Named) types.Type { baseType := r.typ() // The imported instantiated type doesn't include any methods, so // we must always use the methods of the base (orig) type. - // TODO provide a non-nil *Environment + // TODO provide a non-nil *Context t, _ := types.Instantiate(nil, baseType, targs, false) return t -- GitLab From 82ac9ab83a47468046bda9bf6c4676a9695fae24 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 29 Sep 2021 10:50:18 -0700 Subject: [PATCH 1378/2500] text/template: check final value for short-circuit and/or There was a bug in the short-circuit code for and/or added in CL 321490: it ignored the value passed in by an earlier pipeline. For #31103 Change-Id: Ic31f4d7cedfe563ef968cbb712ecfb2413c42eb5 Reviewed-on: https://go-review.googlesource.com/c/go/+/353130 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Bryan C. Mills TryBot-Result: Go Bot --- src/text/template/exec.go | 5 ++++- src/text/template/exec_test.go | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/text/template/exec.go b/src/text/template/exec.go index e03920964e..fce3b0abbf 100644 --- a/src/text/template/exec.go +++ b/src/text/template/exec.go @@ -721,9 +721,12 @@ func (s *state) evalCall(dot, fun reflect.Value, isBuiltin bool, node parse.Node for _, arg := range args { v = s.evalArg(dot, argType, arg).Interface().(reflect.Value) if truth(v) == (name == "or") { - break + return v } } + if final != missingVal { + v = s.validateType(final, argType) + } return v } diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go index 93fd54e84d..a0432a588d 100644 --- a/src/text/template/exec_test.go +++ b/src/text/template/exec_test.go @@ -485,6 +485,10 @@ var execTests = []execTest{ {"and short-circuit", "{{and 1 0 (die)}}", "0", nil, true}, {"or short-circuit2", "{{or 0 0 (die)}}", "", nil, false}, {"and short-circuit2", "{{and 1 1 (die)}}", "", nil, false}, + {"and pipe-true", "{{1 | and 1}}", "1", nil, true}, + {"and pipe-false", "{{0 | and 1}}", "0", nil, true}, + {"or pipe-true", "{{1 | or 0}}", "1", nil, true}, + {"or pipe-false", "{{0 | or 0}}", "0", nil, true}, {"boolean if", "{{if and true 1 `hi`}}TRUE{{else}}FALSE{{end}}", "TRUE", tVal, true}, {"boolean if not", "{{if and true 1 `hi` | not}}TRUE{{else}}FALSE{{end}}", "FALSE", nil, true}, -- GitLab From e213c72fb9492a409bd0ed9620ca9aaaa96ddebe Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Tue, 28 Sep 2021 15:59:34 -0400 Subject: [PATCH 1379/2500] internal/fuzz: disconnect stdout and stderr from the worker This was useful for debugging while we were developing the feature, but is now causing extraneous prints that make the command output difficult to read. This change also prevents the go command from printing an extraneous "FAIL" when fuzzing is enabled. Fixes #48633 Fixes #46631 Change-Id: I636e65f305a20f6dcd843e62090ae228741a3725 Reviewed-on: https://go-review.googlesource.com/c/go/+/352892 Trust: Katie Hockman Run-TryBot: Katie Hockman Reviewed-by: Jay Conrod Reviewed-by: Bryan C. Mills TryBot-Result: Go Bot --- src/cmd/go/internal/test/test.go | 18 ++++++++++++++++-- src/internal/fuzz/worker.go | 2 -- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index a6c8631a37..dc1bea505b 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -1790,9 +1790,23 @@ func builderNoTest(b *work.Builder, ctx context.Context, a *work.Action) error { return nil } -// printExitStatus is the action for printing the exit status +// printExitStatus is the action for printing the final exit status. +// If we are running multiple test targets, print a final "FAIL" +// in case a failure in an early package has already scrolled +// off of the user's terminal. +// (See https://golang.org/issue/30507#issuecomment-470593235.) +// +// In JSON mode, we need to maintain valid JSON output and +// we assume that the test output is being parsed by a tool +// anyway, so the failure will not be missed and would be +// awkward to try to wedge into the JSON stream. +// +// In fuzz mode, we only allow a single package for now +// (see CL 350156 and https://golang.org/issue/46312), +// so there is no possibility of scrolling off and no need +// to print the final status. func printExitStatus(b *work.Builder, ctx context.Context, a *work.Action) error { - if !testJSON && len(pkgArgs) != 0 { + if !testJSON && testFuzz == "" && len(pkgArgs) != 0 { if base.GetExitStatus() != 0 { fmt.Println("FAIL") return nil diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 5b24e575c0..1429decba8 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -331,8 +331,6 @@ func (w *worker) start() (err error) { cmd := exec.Command(w.binPath, w.args...) cmd.Dir = w.dir cmd.Env = w.env[:len(w.env):len(w.env)] // copy on append to ensure workers don't overwrite each other. - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr // Create the "fuzz_in" and "fuzz_out" pipes so we can communicate with // the worker. We don't use stdin and stdout, since the test binary may -- GitLab From 5930cff093c44b86a299c1841ab4e6a2c7a239d2 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Wed, 29 Sep 2021 10:16:47 -0700 Subject: [PATCH 1380/2500] debug/gosym: add benchmark Use a Go 1.15 executable for the benchmark, because it is handy. Most of the code paths are shared for Go 1.2+. Change-Id: Id7ddc76a05d76335108c58ff9f1ab2ff837b7227 Reviewed-on: https://go-review.googlesource.com/c/go/+/353131 Trust: Josh Bleecher Snyder Trust: Brad Fitzpatrick Run-TryBot: Josh Bleecher Snyder Reviewed-by: Brad Fitzpatrick TryBot-Result: Go Bot --- src/debug/gosym/pclntab_test.go | 91 ++++++++++++++++++++++++++++++--- 1 file changed, 84 insertions(+), 7 deletions(-) diff --git a/src/debug/gosym/pclntab_test.go b/src/debug/gosym/pclntab_test.go index 7347139b5d..8589227157 100644 --- a/src/debug/gosym/pclntab_test.go +++ b/src/debug/gosym/pclntab_test.go @@ -267,7 +267,8 @@ func TestPCLine(t *testing.T) { } } -// Test that we can parse a pclntab from 1.15. +// read115Executable returns a hello world executable compiled by Go 1.15. +// // The file was compiled in /tmp/hello.go: // [BEGIN] // package main @@ -276,25 +277,30 @@ func TestPCLine(t *testing.T) { // println("hello") // } // [END] -func Test115PclnParsing(t *testing.T) { +func read115Executable(tb testing.TB) []byte { zippedDat, err := os.ReadFile("testdata/pcln115.gz") if err != nil { - t.Fatal(err) + tb.Fatal(err) } var gzReader *gzip.Reader gzReader, err = gzip.NewReader(bytes.NewBuffer(zippedDat)) if err != nil { - t.Fatal(err) + tb.Fatal(err) } var dat []byte dat, err = io.ReadAll(gzReader) if err != nil { - t.Fatal(err) + tb.Fatal(err) } + return dat +} + +// Test that we can parse a pclntab from 1.15. +func Test115PclnParsing(t *testing.T) { + dat := read115Executable(t) const textStart = 0x1001000 pcln := NewLineTable(dat, textStart) - var tab *Table - tab, err = NewTable(nil, pcln) + tab, err := NewTable(nil, pcln) if err != nil { t.Fatal(err) } @@ -314,3 +320,74 @@ func Test115PclnParsing(t *testing.T) { t.Fatalf("expected to parse name as main.main, got %v", f.Name) } } + +var ( + sinkLineTable *LineTable + sinkTable *Table +) + +func Benchmark115(b *testing.B) { + dat := read115Executable(b) + const textStart = 0x1001000 + + b.Run("NewLineTable", func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + sinkLineTable = NewLineTable(dat, textStart) + } + }) + + pcln := NewLineTable(dat, textStart) + b.Run("NewTable", func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + var err error + sinkTable, err = NewTable(nil, pcln) + if err != nil { + b.Fatal(err) + } + } + }) + + tab, err := NewTable(nil, pcln) + if err != nil { + b.Fatal(err) + } + + b.Run("LineToPC", func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + var f *Func + var pc uint64 + pc, f, err = tab.LineToPC("/tmp/hello.go", 3) + if err != nil { + b.Fatal(err) + } + if pcln.version != ver12 { + b.Fatalf("want version=%d, got %d", ver12, pcln.version) + } + if pc != 0x105c280 { + b.Fatalf("want pc=0x105c280, got 0x%x", pc) + } + if f.Name != "main.main" { + b.Fatalf("want name=main.main, got %q", f.Name) + } + } + }) + + b.Run("PCToLine", func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + file, line, fn := tab.PCToLine(0x105c280) + if file != "/tmp/hello.go" { + b.Fatalf("want name=/tmp/hello.go, got %q", file) + } + if line != 3 { + b.Fatalf("want line=3, got %d", line) + } + if fn.Name != "main.main" { + b.Fatalf("want name=main.main, got %q", fn.Name) + } + } + }) +} -- GitLab From 40fa8c200cc18a361843a526f3e0116e5dfd006f Mon Sep 17 00:00:00 2001 From: citizen233 Date: Tue, 28 Sep 2021 14:05:20 +0800 Subject: [PATCH 1381/2500] cmd/go/internal/modcmd: fix "go mod editwork" error text Fixes #48583 Change-Id: I863ece5c546c383a2f46b8b1a36cbf9f2526d3ed Reviewed-on: https://go-review.googlesource.com/c/go/+/352709 Reviewed-by: Jay Conrod Trust: Dmitri Shuralyov --- src/cmd/go/internal/modcmd/editwork.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/go/internal/modcmd/editwork.go b/src/cmd/go/internal/modcmd/editwork.go index 235c655387..50f86366a0 100644 --- a/src/cmd/go/internal/modcmd/editwork.go +++ b/src/cmd/go/internal/modcmd/editwork.go @@ -118,7 +118,7 @@ func runEditwork(ctx context.Context, cmd *base.Command, args []string) { len(workedits) > 0 if !anyFlags { - base.Fatalf("go: no flags specified (see 'go help mod edit').") + base.Fatalf("go: no flags specified (see 'go help mod editwork').") } if *editworkJSON && *editworkPrint { -- GitLab From ed57d7bb15992bf7ffbbe643401b03f0a418663c Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Thu, 23 Sep 2021 13:11:04 -0700 Subject: [PATCH 1382/2500] debug/gosym: refactor handling of funcdata MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We do a bunch of manual offset calculations everywhere. Add a bit of type safety and some helpers. In addition to making the code clearer and providing a place to hang some documentation, it also makes upcoming changes easier. name old time/op new time/op delta 115/NewLineTable-8 79.9ns ± 1% 90.2ns ±23% ~ (p=0.234 n=9+10) 115/NewTable-8 72.0µs ± 1% 73.4µs ± 1% +1.96% (p=0.000 n=8+8) 115/LineToPC-8 53.3µs ± 1% 54.4µs ± 1% +2.02% (p=0.000 n=10+10) 115/PCToLine-8 249ns ± 0% 249ns ± 2% ~ (p=0.147 n=9+10) name old alloc/op new alloc/op delta 115/NewLineTable-8 384B ± 0% 384B ± 0% ~ (all equal) 115/NewTable-8 164kB ± 0% 164kB ± 0% ~ (p=0.610 n=10+10) 115/LineToPC-8 0.00B 0.00B ~ (all equal) 115/PCToLine-8 0.00B 0.00B ~ (all equal) name old allocs/op new allocs/op delta 115/NewLineTable-8 3.00 ± 0% 3.00 ± 0% ~ (all equal) 115/NewTable-8 1.04k ± 0% 1.04k ± 0% ~ (all equal) 115/LineToPC-8 0.00 0.00 ~ (all equal) 115/PCToLine-8 0.00 0.00 ~ (all equal) Change-Id: If357dce5ae4277e6ddc6d90ba6b5b83e470b9121 Reviewed-on: https://go-review.googlesource.com/c/go/+/352951 Trust: Josh Bleecher Snyder Trust: Brad Fitzpatrick Run-TryBot: Josh Bleecher Snyder Reviewed-by: Cherry Mui Reviewed-by: Brad Fitzpatrick TryBot-Result: Go Bot --- src/debug/gosym/pclntab.go | 83 ++++++++++++++++++++++++++++---------- 1 file changed, 62 insertions(+), 21 deletions(-) diff --git a/src/debug/gosym/pclntab.go b/src/debug/gosym/pclntab.go index 5d18410a78..bf97976b3c 100644 --- a/src/debug/gosym/pclntab.go +++ b/src/debug/gosym/pclntab.go @@ -279,13 +279,13 @@ func (t *LineTable) go12Funcs() []Func { f := &funcs[i] f.Entry = t.uintptr(t.functab[2*i*int(t.ptrsize):]) f.End = t.uintptr(t.functab[(2*i+2)*int(t.ptrsize):]) - info := t.funcdata[t.uintptr(t.functab[(2*i+1)*int(t.ptrsize):]):] + info := t.funcData(uint32(i)) f.LineTable = t - f.FrameSize = int(t.binary.Uint32(info[t.ptrsize+2*4:])) + f.FrameSize = int(info.deferreturn()) f.Sym = &Sym{ Value: f.Entry, Type: 'T', - Name: t.funcName(t.binary.Uint32(info[t.ptrsize:])), + Name: t.funcName(info.nameoff()), GoType: 0, Func: f, } @@ -293,10 +293,10 @@ func (t *LineTable) go12Funcs() []Func { return funcs } -// findFunc returns the func corresponding to the given program counter. -func (t *LineTable) findFunc(pc uint64) []byte { +// findFunc returns the funcData corresponding to the given program counter. +func (t *LineTable) findFunc(pc uint64) funcData { if pc < t.uintptr(t.functab) || pc >= t.uintptr(t.functab[len(t.functab)-int(t.ptrsize):]) { - return nil + return funcData{} } // The function table is a list of 2*nfunctab+1 uintptrs, @@ -307,7 +307,8 @@ func (t *LineTable) findFunc(pc uint64) []byte { m := nf / 2 fm := f[2*t.ptrsize*m:] if t.uintptr(fm) <= pc && pc < t.uintptr(fm[2*t.ptrsize:]) { - return t.funcdata[t.uintptr(fm[t.ptrsize:]):] + data := t.funcdata[t.uintptr(fm[t.ptrsize:]):] + return funcData{t: t, data: data} } else if pc < t.uintptr(fm) { nf = m } else { @@ -315,7 +316,7 @@ func (t *LineTable) findFunc(pc uint64) []byte { nf -= m + 1 } } - return nil + return funcData{} } // readvarint reads, removes, and returns a varint from *pp. @@ -361,6 +362,47 @@ func (t *LineTable) string(off uint32) string { return t.stringFrom(t.funcdata, off) } +// funcData is memory corresponding to an _func struct. +type funcData struct { + t *LineTable // LineTable this data is a part of + data []byte // raw memory for the function +} + +// funcData returns the ith funcData in t.functab. +func (t *LineTable) funcData(i uint32) funcData { + data := t.funcdata[t.uintptr(t.functab[2*t.ptrsize*i+t.ptrsize:]):] + return funcData{t: t, data: data} +} + +// IsZero reports whether f is the zero value. +func (f funcData) IsZero() bool { + return f.t == nil && f.data == nil +} + +// entryPC returns the func's entry PC. +func (f funcData) entryPC() uint64 { + return f.t.uintptr(f.data) +} + +func (f funcData) nameoff() uint32 { return f.field(1) } +func (f funcData) deferreturn() uint32 { return f.field(3) } +func (f funcData) pcfile() uint32 { return f.field(5) } +func (f funcData) pcln() uint32 { return f.field(6) } +func (f funcData) cuOffset() uint32 { return f.field(8) } + +// field returns the nth field of the _func struct. +// It panics if n == 0 or n > 9; for n == 0, call f.entryPC. +// Most callers should use a named field accessor (just above). +func (f funcData) field(n uint32) uint32 { + if n == 0 || n > 9 { + panic("bad funcdata field") + } + sz0 := f.t.ptrsize + off := sz0 + (n-1)*4 // subsequent fields are 4 bytes each + data := f.data[off:] + return f.t.binary.Uint32(data) +} + // step advances to the next pc, value pair in the encoded table. func (t *LineTable) step(p *[]byte, pc *uint64, val *int32, first bool) bool { uvdelta := t.readvarint(p) @@ -451,11 +493,11 @@ func (t *LineTable) go12PCToLine(pc uint64) (line int) { }() f := t.findFunc(pc) - if f == nil { + if f.IsZero() { return -1 } - entry := t.uintptr(f) - linetab := t.binary.Uint32(f[t.ptrsize+5*4:]) + entry := f.entryPC() + linetab := f.pcln() return int(t.pcvalue(linetab, entry, pc)) } @@ -468,11 +510,11 @@ func (t *LineTable) go12PCToFile(pc uint64) (file string) { }() f := t.findFunc(pc) - if f == nil { + if f.IsZero() { return "" } - entry := t.uintptr(f) - filetab := t.binary.Uint32(f[t.ptrsize+4*4:]) + entry := f.entryPC() + filetab := f.pcfile() fno := t.pcvalue(filetab, entry, pc) if t.version == ver12 { if fno <= 0 { @@ -484,7 +526,7 @@ func (t *LineTable) go12PCToFile(pc uint64) (file string) { if fno < 0 { // 0 is valid for ≥ 1.16 return "" } - cuoff := t.binary.Uint32(f[t.ptrsize+7*4:]) + cuoff := f.cuOffset() if fnoff := t.binary.Uint32(t.cutab[(cuoff+uint32(fno))*4:]); fnoff != ^uint32(0) { return t.stringFrom(t.filetab, fnoff) } @@ -510,13 +552,12 @@ func (t *LineTable) go12LineToPC(file string, line int) (pc uint64) { // mapping file number to a list of functions with code from that file. var cutab []byte for i := uint32(0); i < t.nfunctab; i++ { - f := t.funcdata[t.uintptr(t.functab[2*t.ptrsize*i+t.ptrsize:]):] - entry := t.uintptr(f) - filetab := t.binary.Uint32(f[t.ptrsize+4*4:]) - linetab := t.binary.Uint32(f[t.ptrsize+5*4:]) + f := t.funcData(i) + entry := f.entryPC() + filetab := f.pcfile() + linetab := f.pcln() if t.version == ver116 { - cuoff := t.binary.Uint32(f[t.ptrsize+7*4:]) * 4 - cutab = t.cutab[cuoff:] + cutab = t.cutab[f.cuOffset()*4:] } pc := t.findFileLine(entry, filetab, linetab, int32(filenum), int32(line), cutab) if pc != 0 { -- GitLab From 88ea8a5fe0526bc53e944420c42cf75fc7b11c4f Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Wed, 29 Sep 2021 09:49:54 -0700 Subject: [PATCH 1383/2500] runtime: extract text address calculation into a separate method Pure code movement. Change-Id: I7216e50fe14afa3d19c5047c92e515c90838f834 Reviewed-on: https://go-review.googlesource.com/c/go/+/353129 Trust: Josh Bleecher Snyder Trust: Brad Fitzpatrick Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick Reviewed-by: Cherry Mui --- src/runtime/symtab.go | 36 ++++++++++++++++++++++++++++++++++++ src/runtime/type.go | 29 +---------------------------- 2 files changed, 37 insertions(+), 28 deletions(-) diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 0d0fe8055b..f65e16ff1d 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -628,6 +628,42 @@ func moduledataverify1(datap *moduledata) { } } +// textAddr returns md.text + off, with special handling for multiple text sections. +// off is a (virtual) offset computed at internal linking time, +// before the external linker adjusts the sections' base addresses. +// +// The text, or instruction stream is generated as one large buffer. +// The off (offset) for a function is its offset within this buffer. +// If the total text size gets too large, there can be issues on platforms like ppc64 +// if the target of calls are too far for the call instruction. +// To resolve the large text issue, the text is split into multiple text sections +// to allow the linker to generate long calls when necessary. +// When this happens, the vaddr for each text section is set to its offset within the text. +// Each function's offset is compared against the section vaddrs and sizes to determine the containing section. +// Then the section relative offset is added to the section's +// relocated baseaddr to compute the function addess. +func (md *moduledata) textAddr(off uintptr) uintptr { + var res uintptr + if len(md.textsectmap) > 1 { + for i := range md.textsectmap { + sectaddr := md.textsectmap[i].vaddr + sectlen := md.textsectmap[i].length + if uintptr(off) >= sectaddr && uintptr(off) < sectaddr+sectlen { + res = md.textsectmap[i].baseaddr + uintptr(off) - uintptr(md.textsectmap[i].vaddr) + break + } + } + } else { + // single text section + res = md.text + uintptr(off) + } + if res > md.etext && GOARCH != "wasm" { // on wasm, functions do not live in the same address space as the linear memory + println("runtime: textOff", hex(off), "out of range", hex(md.text), "-", hex(md.etext)) + throw("runtime: text offset out of range") + } + return res +} + // FuncForPC returns a *Func describing the function that contains the // given program counter address, or else nil. // diff --git a/src/runtime/type.go b/src/runtime/type.go index ad01d5095e..e609acbc1e 100644 --- a/src/runtime/type.go +++ b/src/runtime/type.go @@ -288,34 +288,7 @@ func (t *_type) textOff(off textOff) unsafe.Pointer { } return res } - res := uintptr(0) - - // The text, or instruction stream is generated as one large buffer. The off (offset) for a method is - // its offset within this buffer. If the total text size gets too large, there can be issues on platforms like ppc64 if - // the target of calls are too far for the call instruction. To resolve the large text issue, the text is split - // into multiple text sections to allow the linker to generate long calls when necessary. When this happens, the vaddr - // for each text section is set to its offset within the text. Each method's offset is compared against the section - // vaddrs and sizes to determine the containing section. Then the section relative offset is added to the section's - // relocated baseaddr to compute the method addess. - - if len(md.textsectmap) > 1 { - for i := range md.textsectmap { - sectaddr := md.textsectmap[i].vaddr - sectlen := md.textsectmap[i].length - if uintptr(off) >= sectaddr && uintptr(off) < sectaddr+sectlen { - res = md.textsectmap[i].baseaddr + uintptr(off) - uintptr(md.textsectmap[i].vaddr) - break - } - } - } else { - // single text section - res = md.text + uintptr(off) - } - - if res > md.etext && GOARCH != "wasm" { // on wasm, functions do not live in the same address space as the linear memory - println("runtime: textOff", hex(off), "out of range", hex(md.text), "-", hex(md.etext)) - throw("runtime: text offset out of range") - } + res := md.textAddr(uintptr(off)) return unsafe.Pointer(res) } -- GitLab From d3ad216f8e7ea7699fe44990c65213c26aba907d Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 28 Sep 2021 17:06:56 -0700 Subject: [PATCH 1384/2500] cmd/link, runtime: use offset for _func.entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The first field of the func data stored by the linker is the entry PC for the function. Prior to this change, this was stored as a relocation to the function. Change this to be an offset relative to runtime.text. This reduces the number of relocations on darwin/arm64 by about 10%. It also slightly shrinks binaries: file before after Δ % addr2line 3803058 3791298 -11760 -0.309% api 5140114 5104242 -35872 -0.698% asm 4886850 4840626 -46224 -0.946% buildid 2512466 2503042 -9424 -0.375% cgo 4374770 4342274 -32496 -0.743% compile 22920530 22769202 -151328 -0.660% cover 4624626 4588242 -36384 -0.787% dist 3217570 3205522 -12048 -0.374% doc 3715026 3684498 -30528 -0.822% fix 3148226 3119266 -28960 -0.920% link 6350226 6313362 -36864 -0.581% nm 3768850 3757106 -11744 -0.312% objdump 4140594 4127618 -12976 -0.313% pack 2227474 2218818 -8656 -0.389% pprof 13598706 13506786 -91920 -0.676% test2json 2497234 2487426 -9808 -0.393% trace 10198066 10118498 -79568 -0.780% vet 6930658 6889074 -41584 -0.600% total 108055044 107366900 -688144 -0.637% It should also incrementally speed up binary launching. This is the first step towards removing enough relocations that pages that were previously dirtied by the loader may remain clean, which will offer memory savings useful in constrained environments. Change-Id: Icfba55e696ba2f9c99c4f179125ba5a3ba4369c9 Reviewed-on: https://go-review.googlesource.com/c/go/+/351463 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/link/internal/ld/pcln.go | 41 +++++++++++++++++++----------- src/debug/gosym/pclntab.go | 43 ++++++++++++++++++++++++++++---- src/runtime/runtime2.go | 6 ++--- src/runtime/symtab.go | 16 ++++++------ 4 files changed, 76 insertions(+), 30 deletions(-) diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index f319c10b5b..08b33ed815 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -72,7 +72,7 @@ func makePclntab(ctxt *Link, container loader.Bitmap) (*pclntab, []*sym.Compilat state := &pclntab{ // This is the size of the _func object in runtime/runtime2.go. - funcSize: uint32(ctxt.Arch.PtrSize + 9*4), + funcSize: 10 * 4, } // Gather some basic stats and info. @@ -225,8 +225,10 @@ func makeInlSyms(ctxt *Link, funcs []loader.Sym, nameOffsets map[loader.Sym]uint // generatePCHeader creates the runtime.pcheader symbol, setting it up as a // generator to fill in its data later. func (state *pclntab) generatePCHeader(ctxt *Link) { + ldr := ctxt.loader + textStartOff := int64(8 + 2*ctxt.Arch.PtrSize) + size := int64(8 + 8*ctxt.Arch.PtrSize) writeHeader := func(ctxt *Link, s loader.Sym) { - ldr := ctxt.loader header := ctxt.loader.MakeSymbolUpdater(s) writeSymOffset := func(off int64, ws loader.Sym) int64 { @@ -239,21 +241,30 @@ func (state *pclntab) generatePCHeader(ctxt *Link) { } // Write header. - // Keep in sync with runtime/symtab.go:pcHeader. - header.SetUint32(ctxt.Arch, 0, 0xfffffffa) + // Keep in sync with runtime/symtab.go:pcHeader and package debug/gosym. + header.SetUint32(ctxt.Arch, 0, 0xfffffff0) header.SetUint8(ctxt.Arch, 6, uint8(ctxt.Arch.MinLC)) header.SetUint8(ctxt.Arch, 7, uint8(ctxt.Arch.PtrSize)) off := header.SetUint(ctxt.Arch, 8, uint64(state.nfunc)) off = header.SetUint(ctxt.Arch, off, uint64(state.nfiles)) + if off != textStartOff { + panic(fmt.Sprintf("pcHeader textStartOff: %d != %d", off, textStartOff)) + } + off += int64(ctxt.Arch.PtrSize) // skip runtimeText relocation off = writeSymOffset(off, state.funcnametab) off = writeSymOffset(off, state.cutab) off = writeSymOffset(off, state.filetab) off = writeSymOffset(off, state.pctab) off = writeSymOffset(off, state.pclntab) + if off != size { + panic(fmt.Sprintf("pcHeader size: %d != %d", off, size)) + } } - size := int64(8 + 7*ctxt.Arch.PtrSize) state.pcheader = state.addGeneratedSym(ctxt, "runtime.pcheader", size, writeHeader) + // Create the runtimeText relocation. + sb := ldr.MakeSymbolUpdater(state.pcheader) + sb.SetAddr(ctxt.Arch, textStartOff, ldr.Lookup("runtime.text", 0)) } // walkFuncs iterates over the funcs, calling a function for each unique @@ -552,9 +563,8 @@ type pclnSetUint func(*loader.SymbolBuilder, *sys.Arch, int64, uint64) int64 // The first pass is executed early in the link, and it creates any needed // relocations to lay out the data. The pieces that need relocations are: // 1) the PC->func table. -// 2) The entry points in the func objects. -// 3) The funcdata. -// (1) and (2) are handled in writePCToFunc. (3) is handled in writeFuncdata. +// 2) The funcdata. +// (1) is handled in writePCToFunc. (2) is handled in writeFuncdata. // // After relocations, once we know where to write things in the output buffer, // we execute the second pass, which is actually writing the data. @@ -708,9 +718,6 @@ func writePCToFunc(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, sta setAddr(sb, ctxt.Arch, int64(funcIndex*2*ctxt.Arch.PtrSize), s, 0) setUint(sb, ctxt.Arch, int64((funcIndex*2+1)*ctxt.Arch.PtrSize), uint64(startLocations[i])) funcIndex++ - - // Write the entry location. - setAddr(sb, ctxt.Arch, int64(startLocations[i]), s, 0) } // Final entry of table is just end pc. @@ -760,6 +767,7 @@ func (state *pclntab) writeFuncData(ctxt *Link, sb *loader.SymbolBuilder, funcs func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSyms map[loader.Sym]loader.Sym, startLocations, cuOffsets []uint32, nameOffsets map[loader.Sym]uint32) { ldr := ctxt.loader deferReturnSym := ldr.Lookup("runtime.deferreturn", abiInternalVer) + textStart := ldr.SymValue(ldr.Lookup("runtime.text", 0)) funcdata := []loader.Sym{} var pcsp, pcfile, pcline, pcinline loader.Sym var pcdata []loader.Sym @@ -772,10 +780,13 @@ func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSym pcsp, pcfile, pcline, pcinline, pcdata = ldr.PcdataAuxs(s, pcdata) } - // Note we skip the space for the entry value -- that's handled in - // writePCToFunc. We don't write it here, because it might require a - // relocation. - off := startLocations[i] + uint32(ctxt.Arch.PtrSize) // entry + off := startLocations[i] + // entry uintptr (offset of func entry PC from textStart) + entryOff := ldr.SymValue(s) - textStart + if entryOff < 0 { + panic(fmt.Sprintf("expected func %s(%x) to be placed before or at textStart (%x)", ldr.SymName(s), ldr.SymValue(s), textStart)) + } + off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(entryOff))) // name int32 nameoff, ok := nameOffsets[s] diff --git a/src/debug/gosym/pclntab.go b/src/debug/gosym/pclntab.go index bf97976b3c..fdaa47a917 100644 --- a/src/debug/gosym/pclntab.go +++ b/src/debug/gosym/pclntab.go @@ -22,6 +22,7 @@ const ( ver11 ver12 ver116 + ver118 ) // A LineTable is a data structure mapping program counters to line numbers. @@ -48,10 +49,11 @@ type LineTable struct { // Contains the version of the pclntab section. version version - // Go 1.2/1.16 state + // Go 1.2/1.16/1.18 state binary binary.ByteOrder quantum uint32 ptrsize uint32 + textStart uintptr // address of runtime.text symbol (1.18+) funcnametab []byte cutab []byte funcdata []byte @@ -166,8 +168,11 @@ func (t *LineTable) isGo12() bool { return t.version >= ver12 } -const go12magic = 0xfffffffb -const go116magic = 0xfffffffa +const ( + go12magic = 0xfffffffb + go116magic = 0xfffffffa + go118magic = 0xfffffff0 +) // uintptr returns the pointer-sized value encoded at b. // The pointer size is dictated by the table being read. @@ -219,11 +224,15 @@ func (t *LineTable) parsePclnTab() { t.binary, possibleVersion = binary.LittleEndian, ver116 case beMagic == go116magic: t.binary, possibleVersion = binary.BigEndian, ver116 + case leMagic == go118magic: + t.binary, possibleVersion = binary.LittleEndian, ver118 + case beMagic == go118magic: + t.binary, possibleVersion = binary.BigEndian, ver118 default: return } - // quantum and ptrSize are the same between 1.2 and 1.16 + // quantum and ptrSize are the same between 1.2, 1.16, and 1.18 t.quantum = uint32(t.Data[6]) t.ptrsize = uint32(t.Data[7]) @@ -235,6 +244,18 @@ func (t *LineTable) parsePclnTab() { } switch possibleVersion { + case ver118: + t.nfunctab = uint32(offset(0)) + t.nfiletab = uint32(offset(1)) + t.textStart = uintptr(offset(2)) + t.funcnametab = data(3) + t.cutab = data(4) + t.filetab = data(5) + t.pctab = data(6) + t.funcdata = data(7) + t.functab = data(7) + functabsize := t.nfunctab*2*t.ptrsize + t.ptrsize + t.functab = t.functab[:functabsize] case ver116: t.nfunctab = uint32(offset(0)) t.nfiletab = uint32(offset(1)) @@ -380,7 +401,14 @@ func (f funcData) IsZero() bool { } // entryPC returns the func's entry PC. -func (f funcData) entryPC() uint64 { +func (f *funcData) entryPC() uint64 { + // In Go 1.18, the first field of _func changed + // from a uintptr entry PC to a uint32 entry offset. + if f.t.version >= ver118 { + // TODO: support multiple text sections. + // See runtime/symtab.go:(*moduledata).textAddr. + return uint64(f.t.binary.Uint32(f.data)) + uint64(f.t.textStart) + } return f.t.uintptr(f.data) } @@ -397,7 +425,12 @@ func (f funcData) field(n uint32) uint32 { if n == 0 || n > 9 { panic("bad funcdata field") } + // In Go 1.18, the first field of _func changed + // from a uintptr entry PC to a uint32 entry offset. sz0 := f.t.ptrsize + if f.t.version >= ver118 { + sz0 = 4 + } off := sz0 + (n-1)*4 // subsequent fields are 4 bytes each data := f.data[off:] return f.t.binary.Uint32(data) diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index 8188872ae8..db1c6e307b 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -858,8 +858,8 @@ const ( // Keep in sync with linker (../cmd/link/internal/ld/pcln.go:/pclntab) // and with package debug/gosym and with symtab.go in package runtime. type _func struct { - entryPC uintptr // start pc - nameoff int32 // function name + entryoff uint32 // start pc, as offset from moduledata.text/pcHeader.textStart + nameoff int32 // function name args int32 // in/out args size deferreturn uint32 // offset of start of a deferreturn call instruction from entry, if any. @@ -879,7 +879,7 @@ type _func struct { // A *Func can be either a *_func or a *funcinl, and they are distinguished // by the first uintptr. type funcinl struct { - ones uintptr // set to ^0 to distinguish from _func + ones uint32 // set to ^0 to distinguish from _func entry uintptr // entry of the real (the "outermost") frame name string file string diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index f65e16ff1d..d1fe1a4fcc 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -387,12 +387,13 @@ const ( // pcHeader holds data used by the pclntab lookups. type pcHeader struct { - magic uint32 // 0xFFFFFFFA + magic uint32 // 0xFFFFFFF0 pad1, pad2 uint8 // 0,0 minLC uint8 // min instruction size ptrSize uint8 // size of a ptr in bytes nfunc int // number of functions in the module nfiles uint // number of entries in the file tab + textStart uintptr // base for function entry PC offsets in this module, equal to moduledata.text funcnameOffset uintptr // offset to the funcnametab variable from pcHeader cuOffset uintptr // offset to the cutab variable from pcHeader filetabOffset uintptr // offset to the filetab variable from pcHeader @@ -586,10 +587,11 @@ const debugPcln = false func moduledataverify1(datap *moduledata) { // Check that the pclntab's format is valid. hdr := datap.pcHeader - if hdr.magic != 0xfffffffa || hdr.pad1 != 0 || hdr.pad2 != 0 || - hdr.minLC != sys.PCQuantum || hdr.ptrSize != goarch.PtrSize { + if hdr.magic != 0xfffffff0 || hdr.pad1 != 0 || hdr.pad2 != 0 || + hdr.minLC != sys.PCQuantum || hdr.ptrSize != goarch.PtrSize || hdr.textStart != datap.text { println("runtime: pcHeader: magic=", hex(hdr.magic), "pad1=", hdr.pad1, "pad2=", hdr.pad2, - "minLC=", hdr.minLC, "ptrSize=", hdr.ptrSize, "pluginpath=", datap.pluginpath) + "minLC=", hdr.minLC, "ptrSize=", hdr.ptrSize, "pcHeader.textStart=", hex(hdr.textStart), + "text=", hex(datap.text), "pluginpath=", datap.pluginpath) throw("invalid function symbol table") } @@ -685,7 +687,7 @@ func FuncForPC(pc uintptr) *Func { name := funcnameFromNameoff(f, inltree[ix].func_) file, line := funcline(f, pc) fi := &funcinl{ - ones: ^uintptr(0), + ones: ^uint32(0), entry: f.entry(), // entry of the real (the outermost) function. name: name, file: file, @@ -766,12 +768,12 @@ func (f funcInfo) _Func() *Func { // isInlined reports whether f should be re-interpreted as a *funcinl. func (f *_func) isInlined() bool { - return f.entryPC == ^uintptr(0) // see comment for funcinl.ones + return f.entryoff == ^uint32(0) // see comment for funcinl.ones } // entry returns the entry PC for f. func (f funcInfo) entry() uintptr { - return f.entryPC + return f.datap.textAddr(uintptr(f.entryoff)) } // findfunc looks up function metadata for a PC. -- GitLab From 2d6d5584179cf89e44abc2829fcdc68c29dfc5a4 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 28 Sep 2021 17:26:24 -0700 Subject: [PATCH 1385/2500] cmd/link: make funcSize a constant Now that it no longer depends on the size of a pointer, we can make it a constant, which simplifies a bit of code. Change-Id: I1b7c3b1b648da5c8960378a02b9263e2cc902441 Reviewed-on: https://go-review.googlesource.com/c/go/+/352952 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/link/internal/ld/pcln.go | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index 08b33ed815..5f4724970c 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -17,11 +17,10 @@ import ( "strings" ) +const funcSize = 10 * 4 // funcSize is the size of the _func object in runtime/runtime2.go + // pclntab holds the state needed for pclntab generation. type pclntab struct { - // The size of the func object in the runtime. - funcSize uint32 - // The first and last functions found. firstFunc, lastFunc loader.Sym @@ -69,11 +68,7 @@ func (state *pclntab) addGeneratedSym(ctxt *Link, name string, size int64, f gen // generate pclntab. func makePclntab(ctxt *Link, container loader.Bitmap) (*pclntab, []*sym.CompilationUnit, []loader.Sym) { ldr := ctxt.loader - - state := &pclntab{ - // This is the size of the _func object in runtime/runtime2.go. - funcSize: 10 * 4, - } + state := new(pclntab) // Gather some basic stats and info. seenCUs := make(map[*sym.CompilationUnit]struct{}) @@ -671,7 +666,7 @@ func (state pclntab) calculateFunctabSize(ctxt *Link, funcs []loader.Sym) (int64 size = Rnd(size, int64(ctxt.Arch.PtrSize)) startLocations[i] = uint32(size) fi := ldr.FuncInfo(s) - size += int64(state.funcSize) + size += funcSize if fi.Valid() { fi.Preload() numFuncData := ldr.NumFuncdata(s) @@ -748,7 +743,7 @@ func (state *pclntab) writeFuncData(ctxt *Link, sb *loader.SymbolBuilder, funcs // Missing funcdata will be 0 (nil pointer). funcdata = funcData(ldr, s, fi, inlSyms[s], funcdata) if len(funcdata) > 0 { - off := int64(startLocations[i] + state.funcSize + numPCData(ldr, s, fi)*4) + off := int64(startLocations[i] + funcSize + numPCData(ldr, s, fi)*4) off = Rnd(off, int64(ctxt.Arch.PtrSize)) for j := range funcdata { dataoff := off + int64(ctxt.Arch.PtrSize*j) -- GitLab From 665626928807c484d31a4bcb3b4b553a7a9d80eb Mon Sep 17 00:00:00 2001 From: fanzha02 Date: Tue, 28 Sep 2021 13:46:14 +0800 Subject: [PATCH 1386/2500] cmd/asm: add error check for move constant instructions on arm64 The current Go assembler encodes "MOVK $(0<<16|32|48), Rd" as the same binary with "MOVK $0, Rd", but for arm64 move constant instructions MOVK, MOVN and MOVZ, "op $0, Rd" and "op $(0<<16|32|48), Rd" have different semantics. In order not to change the way the assembler frontend parses constants, this patch adds a check for the zero shifts. Change-Id: Ia844c419ce49f63605b549e3a2e98d9075dd1cf1 Reviewed-on: https://go-review.googlesource.com/c/go/+/275812 Run-TryBot: Cherry Mui TryBot-Result: Go Bot Trust: fannie zhang Reviewed-by: Cherry Mui --- src/cmd/asm/internal/asm/testdata/arm64error.s | 2 ++ src/cmd/internal/obj/arm64/asm7.go | 3 +++ 2 files changed, 5 insertions(+) diff --git a/src/cmd/asm/internal/asm/testdata/arm64error.s b/src/cmd/asm/internal/asm/testdata/arm64error.s index 7b006432c0..3d3de1d9b1 100644 --- a/src/cmd/asm/internal/asm/testdata/arm64error.s +++ b/src/cmd/asm/internal/asm/testdata/arm64error.s @@ -430,4 +430,6 @@ TEXT errors(SB),$0 STP (R3, R4), 0x1234567(R27) // ERROR "REGTMP used in large offset store" LDP 0x1234567(R27), (R3, R4) // ERROR "REGTMP used in large offset load" STP (R26, R27), 700(R2) // ERROR "cannot use REGTMP as source" + MOVK $0, R10 // ERROR "zero shifts cannot be handled correctly" + MOVK $(0<<32), R10 // ERROR "zero shifts cannot be handled correctly" RET diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go index 5d6caaed5f..68f0921d4d 100644 --- a/src/cmd/internal/obj/arm64/asm7.go +++ b/src/cmd/internal/obj/arm64/asm7.go @@ -3877,6 +3877,9 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { o1 = c.opirr(p, p.As) d := p.From.Offset + if d == 0 { + c.ctxt.Diag("zero shifts cannot be handled correctly: %v", p) + } s := movcon(d) if s < 0 || s >= 4 { c.ctxt.Diag("bad constant for MOVK: %#x\n%v", uint64(d), p) -- GitLab From bd8009d4392fae3ad148a0fe9adb4ea4ac5ab8d3 Mon Sep 17 00:00:00 2001 From: 180909 <734461790@qq.com> Date: Tue, 31 Aug 2021 17:57:33 +0000 Subject: [PATCH 1387/2500] README.md: update contribute URL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /doc/contribute.html now redirects to /doc/contribute. Change-Id: Ib342d515bf6e74bb5807ce21f8df3d985bc7e490 GitHub-Last-Rev: c491a060da22d1bb456283f5ed0ae2894f0365ca GitHub-Pull-Request: golang/go#48005 Reviewed-on: https://go-review.googlesource.com/c/go/+/345590 Trust: Cherry Mui Trust: Daniel Martí Reviewed-by: Daniel Martí --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 837734b6e5..5aca9587fa 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ for source installation instructions. Go is the work of thousands of contributors. We appreciate your help! -To contribute, please read the contribution guidelines at https://golang.org/doc/contribute.html. +To contribute, please read the contribution guidelines at https://golang.org/doc/contribute. Note that the Go project uses the issue tracker for bug reports and proposals only. See https://golang.org/wiki/Questions for a list of -- GitLab From 6b0026ae31720a01f846335d05e42e67e3a2a7cc Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Wed, 29 Sep 2021 02:19:34 +0000 Subject: [PATCH 1388/2500] time: add doc comment about tzdata package Add doc comment about the time/tzdata package to the time.LoadLocation function. The time.LoadLocation function was changed in Go 1.15 to add an extra source that it considers for the time zone database. That location is the time/tzdata package. It is not easy to discover this behavior because the documentation for the time package doesn't mention it in the discussion on the time.LoadLocation function when discussing the different sources. It would be helpful to describe all possible sources that time.LoadLocation considers when loading the time zone database, and so I think it would be worthwhile to mention time/tzdata. Change-Id: I408fbe188bf9d4ba797e59ec17eb677136d6a9c2 GitHub-Last-Rev: 3dac204326960a18c4e44d3ea24fd428e91e9fcb GitHub-Pull-Request: golang/go#48673 Reviewed-on: https://go-review.googlesource.com/c/go/+/352830 Reviewed-by: Ian Lance Taylor Trust: Heschi Kreinick --- src/time/zoneinfo.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/time/zoneinfo.go b/src/time/zoneinfo.go index 57aed03fec..7b39f869e6 100644 --- a/src/time/zoneinfo.go +++ b/src/time/zoneinfo.go @@ -631,12 +631,13 @@ var zoneinfoOnce sync.Once // Otherwise, the name is taken to be a location name corresponding to a file // in the IANA Time Zone database, such as "America/New_York". // -// The time zone database needed by LoadLocation may not be -// present on all systems, especially non-Unix systems. -// LoadLocation looks in the directory or uncompressed zip file -// named by the ZONEINFO environment variable, if any, then looks in -// known installation locations on Unix systems, -// and finally looks in $GOROOT/lib/time/zoneinfo.zip. +// LoadLocation looks for the IANA Time Zone database in the following +// locations in order: +// +// - the directory or uncompressed zip file named by the ZONEINFO environment variable +// - on a Unix system, the system standard installation location +// - $GOROOT/lib/time/zoneinfo.zip +// - the time/tzdata package, if it was imported func LoadLocation(name string) (*Location, error) { if name == "" || name == "UTC" { return UTC, nil -- GitLab From 7162c4c7caf72a3f29d3ceee48ff352dab659472 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Wed, 29 Sep 2021 13:09:34 +0200 Subject: [PATCH 1389/2500] crypto: document the extended key interfaces Change-Id: Iaff3f77b0a168e8bde981c791035a6451b3a49ac Reviewed-on: https://go-review.googlesource.com/c/go/+/353049 Trust: Filippo Valsorda Run-TryBot: Filippo Valsorda TryBot-Result: Go Bot Reviewed-by: Julie Qiu --- src/crypto/crypto.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/crypto/crypto.go b/src/crypto/crypto.go index ce473b5afe..cb87972afc 100644 --- a/src/crypto/crypto.go +++ b/src/crypto/crypto.go @@ -150,9 +150,29 @@ func RegisterHash(h Hash, f func() hash.Hash) { } // PublicKey represents a public key using an unspecified algorithm. +// +// Although this type is an empty interface for backwards compatibility reasons, +// all public key types in the standard library implement the following interface +// +// interface{ +// Equal(x crypto.PublicKey) bool +// } +// +// which can be used for increased type safety within applications. type PublicKey interface{} // PrivateKey represents a private key using an unspecified algorithm. +// +// Although this type is an empty interface for backwards compatibility reasons, +// all private key types in the standard library implement the following interface +// +// interface{ +// Public() crypto.PublicKey +// Equal(x crypto.PrivateKey) bool +// } +// +// as well as purpose-specific interfaces such as Signer and Decrypter, which +// can be used for increased type safety within applications. type PrivateKey interface{} // Signer is an interface for an opaque private key that can be used for -- GitLab From b043d231fa1e1cbc17ddcfb007d92d83dee72428 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 30 Sep 2021 11:46:41 -0400 Subject: [PATCH 1390/2500] debug/gosym: fix version check in file table access Go 1.16 and 1.18 table are the same for that part. Accept 1.18 version number in that code. Fixes #48699. Change-Id: I44eafa279a94bd06444f61518aedd541b25390fd Reviewed-on: https://go-review.googlesource.com/c/go/+/353329 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: Bryan C. Mills --- src/debug/gosym/pclntab.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/debug/gosym/pclntab.go b/src/debug/gosym/pclntab.go index fdaa47a917..b2bd914ad7 100644 --- a/src/debug/gosym/pclntab.go +++ b/src/debug/gosym/pclntab.go @@ -490,7 +490,7 @@ func (t *LineTable) findFileLine(entry uint64, filetab, linetab uint32, filenum, fileStartPC := filePC for t.step(&fp, &filePC, &fileVal, filePC == entry) { fileIndex := fileVal - if t.version == ver116 { + if t.version == ver116 || t.version == ver118 { fileIndex = int32(t.binary.Uint32(cutab[fileVal*4:])) } if fileIndex == filenum && fileStartPC < filePC { @@ -589,7 +589,7 @@ func (t *LineTable) go12LineToPC(file string, line int) (pc uint64) { entry := f.entryPC() filetab := f.pcfile() linetab := f.pcln() - if t.version == ver116 { + if t.version == ver116 || t.version == ver118 { cutab = t.cutab[f.cuOffset()*4:] } pc := t.findFileLine(entry, filetab, linetab, int32(filenum), int32(line), cutab) -- GitLab From d4aed7e42cd187c3031350489dba814f29f215a5 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 30 Sep 2021 12:02:56 -0400 Subject: [PATCH 1391/2500] debug/gosym: run TestPCLine on Linux/AMD64 in short mode Currently TestPCLine is skipped in short mode. The test builds a Linux/AMD64 binary, so it makes sense to skip it if we're cross compiling, as building the runtime takes a while. But if we are on Linux/AMD64, it will only build a small amount of code, which isn't really slow. The test runs in 0.14 second on my machine. I think it is acceptable to run in short mode. Then we'll have trybot coverage for this test. Change-Id: If682f88c28050f7daafde35b4f9e59c03b764a35 Reviewed-on: https://go-review.googlesource.com/c/go/+/353330 Trust: Cherry Mui Trust: Josh Bleecher Snyder Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Josh Bleecher Snyder --- src/debug/gosym/pclntab_test.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/debug/gosym/pclntab_test.go b/src/debug/gosym/pclntab_test.go index 8589227157..d690a1e3f2 100644 --- a/src/debug/gosym/pclntab_test.go +++ b/src/debug/gosym/pclntab_test.go @@ -29,6 +29,10 @@ func dotest(t *testing.T) { if runtime.GOARCH != "amd64" { t.Skipf("skipping on non-AMD64 system %s", runtime.GOARCH) } + // This test builds a Linux/AMD64 binary. Skipping in short mode if cross compiling. + if runtime.GOOS != "linux" && testing.Short() { + t.Skipf("skipping in short mode on non-Linux system %s", runtime.GOARCH) + } var err error pclineTempDir, err = os.MkdirTemp("", "pclinetest") if err != nil { @@ -198,9 +202,6 @@ func TestLineAline(t *testing.T) { } func TestPCLine(t *testing.T) { - if testing.Short() { - t.Skip("skipping in -short mode") - } dotest(t) defer endtest() -- GitLab From 9112d296e84315a07d76a24874037448e2affdd7 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 29 Sep 2021 16:47:12 -0400 Subject: [PATCH 1392/2500] cmd/link: add runtime.text.N symbols to Mach-O symbol table On Darwin/ARM64 when external linking, for very large text we split it into multiple sections. For each section (other than the first) we create runtime.text.N marker symbols. In CL 316050 I forgot to add those symbols to the symbol table. This CL does it. It doesn't actually matter for program execution. But we add them on ELF when splitting text sections, so we do it here as well. Also, this makes it easier to tell if we split text sections. Change-Id: Ida7f8e9431867881e5ee2bc1a2129eeaf83cb878 Reviewed-on: https://go-review.googlesource.com/c/go/+/353209 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: Than McIntosh --- src/cmd/link/internal/ld/ld_test.go | 18 ++++++++++++++---- src/cmd/link/internal/ld/macho.go | 8 ++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/cmd/link/internal/ld/ld_test.go b/src/cmd/link/internal/ld/ld_test.go index 3702a4d08f..2d5a7add9d 100644 --- a/src/cmd/link/internal/ld/ld_test.go +++ b/src/cmd/link/internal/ld/ld_test.go @@ -5,6 +5,7 @@ package ld import ( + "bytes" "debug/pe" "fmt" "internal/testenv" @@ -154,13 +155,22 @@ func TestLargeTextSectionSplitting(t *testing.T) { // is arbitrary; we just need something sufficiently large that uses // external linking. exe := filepath.Join(dir, "go.exe") - out, eerr := exec.Command(testenv.GoToolPath(t), "build", "-o", exe, "-ldflags=-linkmode=external -debugtextsize=1048576", "cmd/go").CombinedOutput() - if eerr != nil { - t.Fatalf("build failure: %s\n%s\n", eerr, string(out)) + out, err := exec.Command(testenv.GoToolPath(t), "build", "-o", exe, "-ldflags=-linkmode=external -debugtextsize=1048576", "cmd/go").CombinedOutput() + if err != nil { + t.Fatalf("build failure: %s\n%s\n", err, string(out)) + } + + // Check that we did split text sections. + out, err = exec.Command(testenv.GoToolPath(t), "tool", "nm", exe).CombinedOutput() + if err != nil { + t.Fatalf("nm failure: %s\n%s\n", err, string(out)) + } + if !bytes.Contains(out, []byte("runtime.text.1")) { + t.Errorf("runtime.text.1 not found, text section not split?") } // Result should be runnable. - _, err := exec.Command(exe, "version").CombinedOutput() + _, err = exec.Command(exe, "version").CombinedOutput() if err != nil { t.Fatal(err) } diff --git a/src/cmd/link/internal/ld/macho.go b/src/cmd/link/internal/ld/macho.go index a577a5308d..8633222ee3 100644 --- a/src/cmd/link/internal/ld/macho.go +++ b/src/cmd/link/internal/ld/macho.go @@ -897,6 +897,14 @@ func collectmachosyms(ctxt *Link) { if ldr.SymType(s) == sym.STEXT { addsym(s) } + for n := range Segtext.Sections[1:] { + s := ldr.Lookup(fmt.Sprintf("runtime.text.%d", n+1), 0) + if s != 0 { + addsym(s) + } else { + break + } + } s = ldr.Lookup("runtime.etext", 0) if ldr.SymType(s) == sym.STEXT { addsym(s) -- GitLab From 205640ed7b6b93d88351c85f0ecfb37d075f8dcf Mon Sep 17 00:00:00 2001 From: Changkun Ou Date: Fri, 27 Aug 2021 17:08:23 +0200 Subject: [PATCH 1393/2500] runtime: avoid run TestSyscallN in parallel Fixes #48012 Change-Id: Ie27eb864ac387ecf5155a3aefa81661f1448ace5 Reviewed-on: https://go-review.googlesource.com/c/go/+/345670 Trust: Bryan C. Mills Trust: Heschi Kreinick Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/runtime/syscall_windows_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/src/runtime/syscall_windows_test.go b/src/runtime/syscall_windows_test.go index 235c79f68f..65f74b32fb 100644 --- a/src/runtime/syscall_windows_test.go +++ b/src/runtime/syscall_windows_test.go @@ -770,7 +770,6 @@ func TestSyscallN(t *testing.T) { for arglen := 0; arglen <= runtime.MaxArgs; arglen++ { arglen := arglen t.Run(fmt.Sprintf("arg-%d", arglen), func(t *testing.T) { - t.Parallel() args := make([]string, arglen) rets := make([]string, arglen+1) params := make([]uintptr, arglen) -- GitLab From eb9f090d1b543f54b319cab78027cdf2ce1a08b8 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 22 Jul 2021 18:57:52 -0400 Subject: [PATCH 1394/2500] cmd/link: use "CC --print-prog-name" to locate tools When building for macOS with external linking, we currently use "xcrun" to invoke "dsymutil" and "strip" tools. That doesn't work well for cross compilation. Use "CC --print-prog-name" to find the tool path instead. Fixes #47316. Change-Id: Ib30c6494c48bfb6a505dc26fe644ef543d777076 Reviewed-on: https://go-review.googlesource.com/c/go/+/336769 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/link/internal/ld/lib.go | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 5af20b4d18..9709c2e886 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -1644,13 +1644,31 @@ func (ctxt *Link) hostlink() { } if combineDwarf { + // Find "dsymutils" and "strip" tools using CC --print-prog-name. + var cc []string + cc = append(cc, ctxt.extld()...) + cc = append(cc, hostlinkArchArgs(ctxt.Arch)...) + cc = append(cc, "--print-prog-name", "dsymutil") + out, err := exec.Command(cc[0], cc[1:]...).CombinedOutput() + if err != nil { + Exitf("%s: finding dsymutil failed: %v\n%s", os.Args[0], err, out) + } + dsymutilCmd := strings.TrimSuffix(string(out), "\n") + + cc[len(cc)-1] = "strip" + out, err = exec.Command(cc[0], cc[1:]...).CombinedOutput() + if err != nil { + Exitf("%s: finding strip failed: %v\n%s", os.Args[0], err, out) + } + stripCmd := strings.TrimSuffix(string(out), "\n") + dsym := filepath.Join(*flagTmpdir, "go.dwarf") - if out, err := exec.Command("xcrun", "dsymutil", "-f", *flagOutfile, "-o", dsym).CombinedOutput(); err != nil { + if out, err := exec.Command(dsymutilCmd, "-f", *flagOutfile, "-o", dsym).CombinedOutput(); err != nil { Exitf("%s: running dsymutil failed: %v\n%s", os.Args[0], err, out) } // Remove STAB (symbolic debugging) symbols after we are done with them (by dsymutil). // They contain temporary file paths and make the build not reproducible. - if out, err := exec.Command("xcrun", "strip", "-S", *flagOutfile).CombinedOutput(); err != nil { + if out, err := exec.Command(stripCmd, "-S", *flagOutfile).CombinedOutput(); err != nil { Exitf("%s: running strip failed: %v\n%s", os.Args[0], err, out) } // Skip combining if `dsymutil` didn't generate a file. See #11994. -- GitLab From 70b1a45425a5e456b4e347e96fc94f94b04ce121 Mon Sep 17 00:00:00 2001 From: Sean Liao Date: Fri, 23 Jul 2021 20:14:14 +0200 Subject: [PATCH 1395/2500] .github: update IRC server MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updates #46281 Change-Id: I1c70ad72a155a39138f120df5b71de61bb01e20c Reviewed-on: https://go-review.googlesource.com/c/go/+/336931 Reviewed-by: Dmitri Shuralyov Reviewed-by: Daniel Martí Trust: Ian Lance Taylor Trust: Daniel Martí --- .github/SUPPORT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/SUPPORT.md b/.github/SUPPORT.md index 23fec84fb6..2ec957a52b 100644 --- a/.github/SUPPORT.md +++ b/.github/SUPPORT.md @@ -11,4 +11,4 @@ For asking questions, see: * [Stack Overflow](https://stackoverflow.com/questions/tagged/go) with questions tagged "go" -* **IRC** channel #go-nuts on Freenode +* **IRC** channel #go-nuts on Libera -- GitLab From 8b2f583ad141b1123b26a75202ead2d4eaf143ef Mon Sep 17 00:00:00 2001 From: wangyuntao Date: Sat, 10 Jul 2021 04:11:22 +0000 Subject: [PATCH 1396/2500] cmd/compile: correct comment: walkSwitch -> walkSelect fix typo Change-Id: Ie2470e494ba95eed067ad42677520b35b383555f GitHub-Last-Rev: 831f1973194f55b435dcdc6ef30290848228a114 GitHub-Pull-Request: golang/go#47117 Reviewed-on: https://go-review.googlesource.com/c/go/+/333789 Reviewed-by: Matthew Dempsky Trust: Keith Randall --- src/cmd/compile/internal/ir/stmt.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/ir/stmt.go b/src/cmd/compile/internal/ir/stmt.go index 3482d7972e..e7d0d873b7 100644 --- a/src/cmd/compile/internal/ir/stmt.go +++ b/src/cmd/compile/internal/ir/stmt.go @@ -338,7 +338,7 @@ type SelectStmt struct { HasBreak bool // TODO(rsc): Instead of recording here, replace with a block? - Compiled Nodes // compiled form, after walkSwitch + Compiled Nodes // compiled form, after walkSelect } func NewSelectStmt(pos src.XPos, cases []*CommClause) *SelectStmt { -- GitLab From c035d829e9fbd150148a1738020fe9c155cda61f Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 30 Sep 2021 15:15:45 -0400 Subject: [PATCH 1397/2500] cmd/dist: consistently set PWD when executing a command in a different directory For #33598 Change-Id: If0de906ffa2fcc83bb2a90f9e80a5b29d7667398 Reviewed-on: https://go-review.googlesource.com/c/go/+/353449 Trust: Bryan C. Mills Reviewed-by: Ian Lance Taylor --- src/cmd/dist/exec.go | 53 +++++++++++++++++++++++++++++++++++++++++++ src/cmd/dist/test.go | 54 +++++++++++++++++++++----------------------- src/cmd/dist/util.go | 2 +- 3 files changed, 80 insertions(+), 29 deletions(-) create mode 100644 src/cmd/dist/exec.go diff --git a/src/cmd/dist/exec.go b/src/cmd/dist/exec.go new file mode 100644 index 0000000000..67305530ae --- /dev/null +++ b/src/cmd/dist/exec.go @@ -0,0 +1,53 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "os" + "os/exec" + "strings" +) + +// setDir sets cmd.Dir to dir, and also adds PWD=dir to cmd's environment. +func setDir(cmd *exec.Cmd, dir string) { + cmd.Dir = dir + setEnv(cmd, "PWD", dir) +} + +// setEnv sets cmd.Env so that key = value. +// +// It first removes any existing values for key, so it is safe to call +// even from within cmdbootstrap. +func setEnv(cmd *exec.Cmd, key, value string) { + kv := key + "=" + value + if cmd.Env == nil { + cmd.Env = os.Environ() + } + + prefix := kv[:len(key)+1] + for i, entry := range cmd.Env { + if strings.HasPrefix(entry, prefix) { + cmd.Env[i] = kv + return + } + } + + cmd.Env = append(cmd.Env, kv) +} + +// unsetEnv sets cmd.Env so that key is not present in the environment. +func unsetEnv(cmd *exec.Cmd, key string) { + if cmd.Env == nil { + cmd.Env = os.Environ() + } + + prefix := key + "=" + for i, entry := range cmd.Env { + if strings.HasPrefix(entry, prefix) { + cmd.Env = append(cmd.Env[:i], cmd.Env[i+1:]...) + return + } + } +} diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index dd4e96ec21..de9135c3c4 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -509,7 +509,8 @@ func (t *tester) registerTests() { heading: "GOOS=ios on darwin/amd64", fn: func(dt *distTest) error { cmd := t.addCmd(dt, "src", t.goTest(), t.timeout(300), "-run=SystemRoots", "crypto/x509") - cmd.Env = append(os.Environ(), "GOOS=ios", "CGO_ENABLED=1") + setEnv(cmd, "GOOS", "ios") + setEnv(cmd, "CGO_ENABLED", "1") return nil }, }) @@ -529,7 +530,7 @@ func (t *tester) registerTests() { cmd := t.addCmd(dt, "src", t.goTest(), t.timeout(300), "runtime", "-cpu=1,2,4", "-quick") // We set GOMAXPROCS=2 in addition to -cpu=1,2,4 in order to test runtime bootstrap code, // creation of first goroutines and first garbage collections in the parallel setting. - cmd.Env = append(os.Environ(), "GOMAXPROCS=2") + setEnv(cmd, "GOMAXPROCS", "2") return nil }, }) @@ -550,7 +551,7 @@ func (t *tester) registerTests() { return nil } cmd := exec.Command("go", "test") - cmd.Dir = filepath.Join(os.Getenv("GOROOT"), "src/cmd/go/testdata/testterminal18153") + setDir(cmd, filepath.Join(os.Getenv("GOROOT"), "src/cmd/go/testdata/testterminal18153")) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr return cmd.Run() @@ -587,16 +588,13 @@ func (t *tester) registerTests() { return err } - // Run `go test fmt` in the moved GOROOT. + // Run `go test fmt` in the moved GOROOT, without explicitly setting + // GOROOT in the environment. The 'go' command should find itself. cmd := exec.Command(filepath.Join(moved, "bin", "go"), "test", "fmt") cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr - // Don't set GOROOT in the environment. - for _, e := range os.Environ() { - if !strings.HasPrefix(e, "GOROOT=") && !strings.HasPrefix(e, "GOCACHE=") { - cmd.Env = append(cmd.Env, e) - } - } + unsetEnv(cmd, "GOROOT") + unsetEnv(cmd, "GOCACHE") // TODO(bcmills): ...why‽ err := cmd.Run() if rerr := os.Rename(moved, goroot); rerr != nil { @@ -723,11 +721,9 @@ func (t *tester) registerTests() { heading: "../misc/swig/callback", fn: func(dt *distTest) error { cmd := t.addCmd(dt, "misc/swig/callback", t.goTest()) - cmd.Env = append(os.Environ(), - "CGO_CFLAGS=-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option", - "CGO_CXXFLAGS=-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option", - "CGO_LDFLAGS=-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option", - ) + setEnv(cmd, "CGO_CFLAGS", "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option") + setEnv(cmd, "CGO_CXXFLAGS", "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option") + setEnv(cmd, "CGO_LDFLAGS", "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option") return nil }, }, @@ -879,9 +875,9 @@ func (t *tester) registerSeqTest(name, dirBanner string, cmdline ...interface{}) func (t *tester) bgDirCmd(dir, bin string, args ...string) *exec.Cmd { cmd := exec.Command(bin, args...) if filepath.IsAbs(dir) { - cmd.Dir = dir + setDir(cmd, dir) } else { - cmd.Dir = filepath.Join(goroot, dir) + setDir(cmd, filepath.Join(goroot, dir)) } return cmd } @@ -1114,7 +1110,8 @@ func (t *tester) runHostTest(dir, pkg string) error { defer os.Remove(f.Name()) cmd := t.dirCmd(dir, t.goTest(), "-c", "-o", f.Name(), pkg) - cmd.Env = append(os.Environ(), "GOARCH="+gohostarch, "GOOS="+gohostos) + setEnv(cmd, "GOARCH", gohostarch) + setEnv(cmd, "GOOS", gohostos) if err := cmd.Run(); err != nil { return err } @@ -1123,7 +1120,7 @@ func (t *tester) runHostTest(dir, pkg string) error { func (t *tester) cgoTest(dt *distTest) error { cmd := t.addCmd(dt, "misc/cgo/test", t.goTest()) - cmd.Env = append(os.Environ(), "GOFLAGS=-ldflags=-linkmode=auto") + setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=auto") // Skip internal linking cases on linux/arm64 to support GCC-9.4 and above. // See issue #39466. @@ -1131,7 +1128,7 @@ func (t *tester) cgoTest(dt *distTest) error { if t.internalLink() && !skipInternalLink { cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=internal") - cmd.Env = append(os.Environ(), "GOFLAGS=-ldflags=-linkmode=internal") + setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=internal") } pair := gohostos + "-" + goarch @@ -1143,9 +1140,9 @@ func (t *tester) cgoTest(dt *distTest) error { break } cmd := t.addCmd(dt, "misc/cgo/test", t.goTest()) - cmd.Env = append(os.Environ(), "GOFLAGS=-ldflags=-linkmode=external") + setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=external") - cmd = t.addCmd(dt, "misc/cgo/test", t.goTest(), "-ldflags", "-linkmode=external -s") + t.addCmd(dt, "misc/cgo/test", t.goTest(), "-ldflags", "-linkmode=external -s") if t.supportedBuildmode("pie") { t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie") @@ -1163,10 +1160,10 @@ func (t *tester) cgoTest(dt *distTest) error { "openbsd-386", "openbsd-amd64", "openbsd-arm", "openbsd-arm64", "openbsd-mips64": cmd := t.addCmd(dt, "misc/cgo/test", t.goTest()) - cmd.Env = append(os.Environ(), "GOFLAGS=-ldflags=-linkmode=external") + setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=external") // cgo should be able to cope with both -g arguments and colored // diagnostics. - cmd.Env = append(cmd.Env, "CGO_CFLAGS=-g0 -fdiagnostics-color") + setEnv(cmd, "CGO_CFLAGS", "-g0 -fdiagnostics-color") t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", "-linkmode=auto") t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", "-linkmode=external") @@ -1199,7 +1196,7 @@ func (t *tester) cgoTest(dt *distTest) error { // than -static in -extldflags, so test both. // See issue #16651. cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=static") - cmd.Env = append(os.Environ(), "CGO_LDFLAGS=-static -pthread") + setEnv(cmd, "CGO_LDFLAGS", "-static -pthread") } } @@ -1438,7 +1435,7 @@ func (t *tester) raceTest(dt *distTest) error { // We shouldn't need to redo all of misc/cgo/test too. // The race buildler will take care of this. // cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-race") - // cmd.Env = append(os.Environ(), "GOTRACEBACK=2") + // setEnv(cmd, "GOTRACEBACK", "2") } if t.extLink() { // Test with external linking; see issue 9133. @@ -1468,7 +1465,8 @@ func (t *tester) testDirTest(dt *distTest, shard, shards int) error { }) cmd := t.dirCmd("test", "go", "build", "-o", runtest.exe, "run.go") - cmd.Env = append(os.Environ(), "GOOS="+gohostos, "GOARCH="+gohostarch) + setEnv(cmd, "GOOS", gohostos) + setEnv(cmd, "GOARCH", gohostarch) runtest.err = cmd.Run() }) if runtest.err != nil { @@ -1632,7 +1630,7 @@ func (t *tester) runPrecompiledStdTest(timeout time.Duration) error { bin := t.prebuiltGoPackageTestBinary() fmt.Fprintf(os.Stderr, "# %s: using pre-built %s...\n", stdMatches[0], bin) cmd := exec.Command(bin, "-test.short="+short(), "-test.timeout="+timeout.String()) - cmd.Dir = filepath.Dir(bin) + setDir(cmd, filepath.Dir(bin)) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Start(); err != nil { diff --git a/src/cmd/dist/util.go b/src/cmd/dist/util.go index df60145d1e..28fe5e1d8d 100644 --- a/src/cmd/dist/util.go +++ b/src/cmd/dist/util.go @@ -72,7 +72,7 @@ func run(dir string, mode int, cmd ...string) string { } xcmd := exec.Command(cmd[0], cmd[1:]...) - xcmd.Dir = dir + setDir(xcmd, dir) var data []byte var err error -- GitLab From 6a79f358069195e1cddb821e81fab956d9a0c7d1 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 27 Sep 2021 08:59:46 -0700 Subject: [PATCH 1398/2500] go/internal/gccgoimporter: change all .gox files to text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid problems with distro scanning by not using files that look like object files. For #48548 Change-Id: I4a06d5690d0870d6253f176e510faa5eebf2d057 Reviewed-on: https://go-review.googlesource.com/c/go/+/352450 Trust: Ian Lance Taylor Trust: Daniel Martí Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Daniel Martí --- .../gccgoimporter/testdata/escapeinfo.gox | Bin 824 -> 350 bytes .../internal/gccgoimporter/testdata/time.gox | Bin 7977 -> 7499 bytes .../gccgoimporter/testdata/unicode.gox | Bin 7945 -> 7474 bytes .../gccgoimporter/testdata/v1reflect.gox | Bin 10872 -> 10546 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/src/go/internal/gccgoimporter/testdata/escapeinfo.gox b/src/go/internal/gccgoimporter/testdata/escapeinfo.gox index 1db81562c1d74a34f1739fd1bf1ac5dd269502d8..94ce0393fc0353bc2647ff1e3babc16c50d848cb 100644 GIT binary patch delta 8 PcmdnNc8_VJLmVRj4{-wT literal 824 zcmb<-^>JfjWMqH=Mg}_u1P><4!0-b}&;cy$z`)AD!cb;p%~gW znU|Jt%~ep8nwD9ikPc#ENGqi0>md}Q@~pYiO7oHx{8Gz96f{y2OA-}qN-7Id6$}-k zW1&o4BLh1-O(@4mK?|b5SV1X72`Xr!P+U?}np~n#t)PcummZRdrf4QwE7aO?DS&O) zu!kCC1~(mKV^C^hih@Rgf=z01vXw!Fp&e9}IhskD)?9XW)?8qBLmg*l&6S*ynw(u+ znyX-JYG7btY+-0@U~XaTY+zt&>Fi?QY+-0>WbS5W;A&}ZY~gC`= diff --git a/src/go/internal/gccgoimporter/testdata/time.gox b/src/go/internal/gccgoimporter/testdata/time.gox index 80c2dbcb472813d114032c583c85134a8f340590..a6822ea19859bef114e34b24b05ddca7c8966833 100644 GIT binary patch delta 8 PcmZ2!ciL*BgSRXI5gh|Y delta 490 zcmX?YwbIU^-qpvAiII^31{fLa7!W*|C zpjTW{1fervtn~c&)QW=qq7twkDiG2P3}_ClhnNa+6$67el1o7{=)MtTU|?VdNuc3w zs6I6`adiD4J`=JUsQnB-3?fq?;}kORt>fYO{e9H1c&Q2??4!h(?Ke26H5 MR75aAKEt9M0Ps8*V*mgE diff --git a/src/go/internal/gccgoimporter/testdata/unicode.gox b/src/go/internal/gccgoimporter/testdata/unicode.gox index e70e539655e9f00af598bffa62f987c77cd96009..ae1a6f758b4d807567569126b1fe2df57a3152cb 100644 GIT binary patch delta 8 PcmeCQ+hn!T!AKSW4^;y6 delta 483 zcmdmF)oJHY@9N{m#K_111B?uI3F1l6a8 zCXTKj#AiZN1LD@-kONT+3TK7kB^w diff --git a/src/go/internal/gccgoimporter/testdata/v1reflect.gox b/src/go/internal/gccgoimporter/testdata/v1reflect.gox index ea468414d9fa8ad66e978799a8ff5d2f90eb4961..d693fe631b53ee3ac530c76d6ce35782421db9a0 100644 GIT binary patch delta 8 PcmewnvMFeziIFA%6UPIQ delta 337 zcmdlK^drQi-qpvAk&%%B1{fKb84x@Mh7Fn!851z2!NAJE#IV6gvz|e(xH7jSF^NI1 zxTFX|XTVtL`SGb01^GoKU_H19RC{o#LWoN E0I6CRr2qf` -- GitLab From 822f349eb9586ff75dbf0fba7e8e939ad208a6fc Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 30 Sep 2021 14:39:52 -0700 Subject: [PATCH 1399/2500] go/types: switch uses of NewSignature to NewSignatureType (cleanup) Change-Id: I05ed5806e2a35a57ef3e8c9275a157574abcb0ff Reviewed-on: https://go-review.googlesource.com/c/go/+/353399 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley --- src/go/internal/gccgoimporter/parser.go | 4 ++-- src/go/types/universe.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/go/internal/gccgoimporter/parser.go b/src/go/internal/gccgoimporter/parser.go index 1b1d07d3f6..267c9953e4 100644 --- a/src/go/internal/gccgoimporter/parser.go +++ b/src/go/internal/gccgoimporter/parser.go @@ -599,7 +599,7 @@ func (p *parser) parseNamedType(nlist []interface{}) types.Type { p.skipInlineBody() p.expectEOL() - sig := types.NewSignature(receiver, params, results, isVariadic) + sig := types.NewSignatureType(receiver, nil, nil, params, results, isVariadic) nt.AddMethod(types.NewFunc(token.NoPos, pkg, name, sig)) } } @@ -766,7 +766,7 @@ func (p *parser) parseFunctionType(pkg *types.Package, nlist []interface{}) *typ params, isVariadic := p.parseParamList(pkg) results := p.parseResultList(pkg) - *t = *types.NewSignature(nil, params, results, isVariadic) + *t = *types.NewSignatureType(nil, nil, nil, params, results, isVariadic) return t } diff --git a/src/go/types/universe.go b/src/go/types/universe.go index 6045c61c30..4d52242e61 100644 --- a/src/go/types/universe.go +++ b/src/go/types/universe.go @@ -87,7 +87,7 @@ func defPredeclaredTypes() { obj := NewTypeName(token.NoPos, nil, "error", nil) obj.setColor(black) res := NewVar(token.NoPos, nil, "", Typ[String]) - sig := NewSignature(nil, nil, NewTuple(res), false) + sig := NewSignatureType(nil, nil, nil, nil, NewTuple(res), false) err := NewFunc(token.NoPos, nil, "Error", sig) ityp := &Interface{nil, obj, []*Func{err}, nil, nil, true, nil} computeInterfaceTypeSet(nil, token.NoPos, ityp) // prevent races due to lazy computation of tset -- GitLab From 8ac5cbe05d61df0a7a7c9a38ff33305d4dcfea32 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 30 Sep 2021 14:21:18 -0700 Subject: [PATCH 1400/2500] cmd/compile/internal/types2: removed deprecated API entry points We don't need to keep them around in types2. Switched a couple of uses of NewSignature to NewSignatureType. Change-Id: I62880c2b49ec82caa9362ed8a798cfc3bcea300e Reviewed-on: https://go-review.googlesource.com/c/go/+/353397 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/noder/reader2.go | 2 +- src/cmd/compile/internal/types2/interface.go | 19 ------------------- src/cmd/compile/internal/types2/signature.go | 10 ---------- src/cmd/compile/internal/types2/universe.go | 2 +- 4 files changed, 2 insertions(+), 31 deletions(-) diff --git a/src/cmd/compile/internal/noder/reader2.go b/src/cmd/compile/internal/noder/reader2.go index d474db2427..9396c0c87c 100644 --- a/src/cmd/compile/internal/noder/reader2.go +++ b/src/cmd/compile/internal/noder/reader2.go @@ -316,7 +316,7 @@ func (r *reader2) signature(recv *types2.Var) *types2.Signature { results := r.params() variadic := r.bool() - return types2.NewSignature(recv, params, results, variadic) + return types2.NewSignatureType(recv, nil, nil, params, results, variadic) } func (r *reader2) params() *types2.Tuple { diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index 8a6bc75c43..a6faf3267b 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -27,19 +27,6 @@ func (t *Interface) typeSet() *_TypeSet { return computeInterfaceTypeSet(t.check // emptyInterface represents the empty interface var emptyInterface = Interface{complete: true, tset: &topTypeSet} -// NewInterface returns a new interface for the given methods and embedded types. -// NewInterface takes ownership of the provided methods and may modify their types -// by setting missing receivers. -// -// Deprecated: Use NewInterfaceType instead which allows arbitrary embedded types. -func NewInterface(methods []*Func, embeddeds []*Named) *Interface { - tnames := make([]Type, len(embeddeds)) - for i, t := range embeddeds { - tnames[i] = t - } - return NewInterfaceType(methods, tnames) -} - // NewInterfaceType returns a new interface for the given methods and embedded types. // NewInterfaceType takes ownership of the provided methods and may modify their types // by setting missing receivers. @@ -76,12 +63,6 @@ func (t *Interface) ExplicitMethod(i int) *Func { return t.methods[i] } // NumEmbeddeds returns the number of embedded types in interface t. func (t *Interface) NumEmbeddeds() int { return len(t.embeddeds) } -// Embedded returns the i'th embedded defined (*Named) type of interface t for 0 <= i < t.NumEmbeddeds(). -// The result is nil if the i'th embedded type is not a defined type. -// -// Deprecated: Use EmbeddedType which is not restricted to defined (*Named) types. -func (t *Interface) Embedded(i int) *Named { tname, _ := t.embeddeds[i].(*Named); return tname } - // EmbeddedType returns the i'th embedded type of interface t for 0 <= i < t.NumEmbeddeds(). func (t *Interface) EmbeddedType(i int) Type { return t.embeddeds[i] } diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index 803dd8e5e7..5ea3a056a0 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -28,16 +28,6 @@ type Signature struct { variadic bool // true if the last parameter's type is of the form ...T (or string, for append built-in only) } -// NewSignature returns a new function type for the given receiver, parameters, -// and results, either of which may be nil. If variadic is set, the function -// is variadic, it must have at least one parameter, and the last parameter -// must be of unnamed slice type. -// -// Deprecated: Use NewSignatureType instead which allows for type parameters. -func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature { - return NewSignatureType(recv, nil, nil, params, results, variadic) -} - // NewSignatureType creates a new function type for the given receiver, // receiver type parameters, type parameters, parameters, and results. If // variadic is set, params must hold at least one parameter and the last diff --git a/src/cmd/compile/internal/types2/universe.go b/src/cmd/compile/internal/types2/universe.go index af3ab97325..27f38de27a 100644 --- a/src/cmd/compile/internal/types2/universe.go +++ b/src/cmd/compile/internal/types2/universe.go @@ -86,7 +86,7 @@ func defPredeclaredTypes() { obj := NewTypeName(nopos, nil, "error", nil) obj.setColor(black) res := NewVar(nopos, nil, "", Typ[String]) - sig := NewSignature(nil, nil, NewTuple(res), false) + sig := NewSignatureType(nil, nil, nil, nil, NewTuple(res), false) err := NewFunc(nopos, nil, "Error", sig) ityp := &Interface{nil, obj, []*Func{err}, nil, nil, true, nil} computeInterfaceTypeSet(nil, nopos, ityp) // prevent races due to lazy computation of tset -- GitLab From 96d3ba868aae7aa043147f18e0ca299ada4e34b7 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 30 Sep 2021 11:46:00 -0400 Subject: [PATCH 1401/2500] cmd/link: reduce alignment for some funcdata symbols Funcdata like opendefer info and traceback arginfo are varints or bytes. There is no need to align them. GC liveness map and inline tree have 32-bit fields, so continue align them to 4 bytes. Change-Id: I9d5dd750a926c65a910efe5817f9f5c473019bc6 Reviewed-on: https://go-review.googlesource.com/c/go/+/353469 Trust: Cherry Mui Reviewed-by: Than McIntosh --- src/cmd/link/internal/ld/symtab.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index 8dec78e017..76cca41d25 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -537,6 +537,7 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { continue } + align := int32(1) name := ldr.SymName(s) switch { case strings.HasPrefix(name, "go.importpath.") && ctxt.UseRelro(): @@ -571,14 +572,17 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { case strings.HasPrefix(name, "gcargs."), strings.HasPrefix(name, "gclocals."), strings.HasPrefix(name, "gclocals·"), - ldr.SymType(s) == sym.SGOFUNC && s != symgofunc, - strings.HasSuffix(name, ".opendefer"), + ldr.SymType(s) == sym.SGOFUNC && s != symgofunc: // inltree, see pcln.go + // GC stack maps and inltrees have 32-bit fields. + align = 4 + fallthrough + case strings.HasSuffix(name, ".opendefer"), strings.HasSuffix(name, ".arginfo0"), strings.HasSuffix(name, ".arginfo1"): + // These are just bytes, or varints, use align 1 (set before the switch). symGroupType[s] = sym.SGOFUNC ldr.SetAttrNotInSymbolTable(s, true) ldr.SetCarrierSym(s, symgofunc) - align := int32(4) if a := ldr.SymAlign(s); a < align { ldr.SetSymAlign(s, align) } else { -- GitLab From 8d494b08189cda1b66b9f851d4d7088c77ac7b6b Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 30 Sep 2021 17:42:15 -0400 Subject: [PATCH 1402/2500] cmd/link: set alignment for string symbols in symtab pass Set alignment for string symbols in symtab pass, so we don't need to look at symbol name in symalign in dodata pass. (Ideally we should not use symbol name like this in symtab pass either, but we already use the names there anyway.) Change-Id: I9fd61e0dd0824c50e3d0d7c07f75b967c8654796 Reviewed-on: https://go-review.googlesource.com/c/go/+/353470 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/link/internal/ld/data.go | 7 ------- src/cmd/link/internal/ld/symtab.go | 6 ++++++ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 1d65c49381..21169f66ef 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -1165,13 +1165,6 @@ func symalign(ldr *loader.Loader, s loader.Sym) int32 { } else if align != 0 { return min } - // FIXME: figure out a way to avoid checking by name here. - sname := ldr.SymName(s) - if strings.HasPrefix(sname, "go.string.") || strings.HasPrefix(sname, "type..namedata.") { - // String data is just bytes. - // If we align it, we waste a lot of space to padding. - return min - } align = int32(thearch.Maxalign) ssz := ldr.SymSize(s) for int64(align) > ssz && align > min { diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index 76cca41d25..4d099b1133 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -549,6 +549,9 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { symGroupType[s] = sym.SGOSTRING ldr.SetAttrNotInSymbolTable(s, true) ldr.SetCarrierSym(s, symgostring) + if ldr.SymAlign(s) == 0 { + ldr.SetSymAlign(s, 1) // String data is just bytes, no padding. + } case strings.HasPrefix(name, "runtime.gcbits."): symGroupType[s] = sym.SGCBITS @@ -608,6 +611,9 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { ldr.SetCarrierSym(s, symtype) } } + if strings.HasPrefix(name, "type..namedata.") && ldr.SymAlign(s) == 0 { + ldr.SetSymAlign(s, 1) // String data is just bytes, no padding. + } } } -- GitLab From e5ad363fff6e602bf72ce7bf5084297c0d1a2e51 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 30 Sep 2021 18:09:24 -0400 Subject: [PATCH 1403/2500] cmd/link: correct type..importpath symbol handling The linker specially handles go.importpath symbols. But the compiler doesn't actually generate such symbols. Instead, it generates type..importpath symbols. It is already in the type section as the name starts with "type.". Also set its alignment to 1, as it is string data. Change-Id: I771f5529a0ff41a5bb476b3a02c8cc75729792de Reviewed-on: https://go-review.googlesource.com/c/go/+/353489 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/link/internal/ld/symtab.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index 4d099b1133..1e5c73c573 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -540,11 +540,6 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { align := int32(1) name := ldr.SymName(s) switch { - case strings.HasPrefix(name, "go.importpath.") && ctxt.UseRelro(): - // Keep go.importpath symbols in the same section as types and - // names, as they can be referred to by a section offset. - symGroupType[s] = sym.STYPERELRO - case strings.HasPrefix(name, "go.string."): symGroupType[s] = sym.SGOSTRING ldr.SetAttrNotInSymbolTable(s, true) @@ -611,7 +606,7 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { ldr.SetCarrierSym(s, symtype) } } - if strings.HasPrefix(name, "type..namedata.") && ldr.SymAlign(s) == 0 { + if (strings.HasPrefix(name, "type..namedata.") || strings.HasPrefix(name, "type..importpath.")) && ldr.SymAlign(s) == 0 { ldr.SetSymAlign(s, 1) // String data is just bytes, no padding. } } -- GitLab From f19b2d50c6d9918c1c121ccd8cb2a4f4a2d3f30b Mon Sep 17 00:00:00 2001 From: jiahua wang Date: Fri, 1 Oct 2021 21:58:51 +0800 Subject: [PATCH 1404/2500] go/types: remove Environment type Change-Id: Id53633477d1c07bce0c5fcbcab079da51076cdf2 Reviewed-on: https://go-review.googlesource.com/c/go/+/353351 Reviewed-by: Robert Griesemer Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot --- src/go/types/context.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/go/types/context.go b/src/go/types/context.go index bbdaade632..99baad8d0f 100644 --- a/src/go/types/context.go +++ b/src/go/types/context.go @@ -22,10 +22,6 @@ type Context struct { seen map[*Named]int // assigned unique IDs } -// Temporary alias to allow x/tools tests to pass. -// TODO(rfindley): remove the Environment type. -type Environment = Context - // NewContext creates a new Context. func NewContext() *Context { return &Context{ -- GitLab From 5279e534b5ced1eaea19e8b75968498287ff6228 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 29 Sep 2021 11:14:05 -0700 Subject: [PATCH 1405/2500] cmd/compile/internal/syntax: allow eliding interface in constraint literals This CL permits an arbitrary type as well as the type sets ~T and A|B in constraint position, without the need of a surrrounding interface. For instance, the type parameter list [P interface{ ~map[K]V }, K comparable, V interface{ ~string }] may be written as [P ~map[K]V, K comparable, V ~string] The feature must be enabled explicitly with the AllowTypeSets mode and is only available if AllowGenerics is set as well. For #48424. Change-Id: Ic70bb97a49ff75e67e040853eac10e6aed0fef1a Reviewed-on: https://go-review.googlesource.com/c/go/+/353133 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/syntax/error_test.go | 2 +- src/cmd/compile/internal/syntax/parser.go | 68 +++++++++++++----- .../compile/internal/syntax/parser_test.go | 6 +- .../compile/internal/syntax/printer_test.go | 6 +- src/cmd/compile/internal/syntax/syntax.go | 1 + .../internal/syntax/testdata/typeset.go2 | 72 +++++++++++++++++++ 6 files changed, 133 insertions(+), 22 deletions(-) create mode 100644 src/cmd/compile/internal/syntax/testdata/typeset.go2 diff --git a/src/cmd/compile/internal/syntax/error_test.go b/src/cmd/compile/internal/syntax/error_test.go index 0952ddc647..966b36f6bc 100644 --- a/src/cmd/compile/internal/syntax/error_test.go +++ b/src/cmd/compile/internal/syntax/error_test.go @@ -130,7 +130,7 @@ func testSyntaxErrors(t *testing.T, filename string) { var mode Mode if strings.HasSuffix(filename, ".go2") { - mode = AllowGenerics | AllowTypeLists + mode = AllowGenerics | AllowTypeSets | AllowTypeLists } ParseFile(filename, func(err error) { e, ok := err.(Error) diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index 82cb06b180..54e77b9958 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -87,6 +87,8 @@ func (p *parser) init(file *PosBase, r io.Reader, errh ErrorHandler, pragh Pragm p.indent = nil } +func (p *parser) allowGenerics() bool { return p.mode&AllowGenerics != 0 } + // takePragma returns the current parsed pragmas // and clears them from the parser state. func (p *parser) takePragma() Pragma { @@ -597,7 +599,7 @@ func (p *parser) typeDecl(group *Group) Decl { p.xnest++ x := p.expr() p.xnest-- - if name0, ok := x.(*Name); p.mode&AllowGenerics != 0 && ok && p.tok != _Rbrack { + if name0, ok := x.(*Name); p.allowGenerics() && ok && p.tok != _Rbrack { // generic type d.TParamList = p.paramList(name0, _Rbrack, true) pos := p.pos() @@ -687,7 +689,7 @@ func (p *parser) funcDeclOrNil() *FuncDecl { } f.Name = p.name() - if p.mode&AllowGenerics != 0 && p.got(_Lbrack) { + if p.allowGenerics() && p.got(_Lbrack) { if p.tok == _Rbrack { p.syntaxError("empty type parameter list") p.next() @@ -1425,7 +1427,7 @@ func (p *parser) interfaceType() *InterfaceType { switch p.tok { case _Name: f := p.methodDecl() - if f.Name == nil && p.mode&AllowGenerics != 0 { + if f.Name == nil && p.allowGenerics() { f = p.embeddedElem(f) } typ.MethodList = append(typ.MethodList, f) @@ -1443,14 +1445,14 @@ func (p *parser) interfaceType() *InterfaceType { return false case _Operator: - if p.op == Tilde && p.mode&AllowGenerics != 0 { + if p.op == Tilde && p.allowGenerics() { typ.MethodList = append(typ.MethodList, p.embeddedElem(nil)) return false } case _Type: // TODO(gri) remove TypeList syntax if we accept #45346 - if p.mode&AllowGenerics != 0 && p.mode&AllowTypeLists != 0 { + if p.allowGenerics() && p.mode&AllowTypeLists != 0 { type_ := NewName(p.pos(), "type") // cannot have a method named "type" p.next() if p.tok != _Semi && p.tok != _Rbrace { @@ -1473,7 +1475,7 @@ func (p *parser) interfaceType() *InterfaceType { } default: - if p.mode&AllowGenerics != 0 { + if p.allowGenerics() { pos := p.pos() if t := p.typeOrNil(); t != nil { f := new(Field) @@ -1485,7 +1487,7 @@ func (p *parser) interfaceType() *InterfaceType { } } - if p.mode&AllowGenerics != 0 { + if p.allowGenerics() { if p.mode&AllowTypeLists != 0 { p.syntaxError("expecting method, type list, or embedded element") p.advance(_Semi, _Rbrace, _Type) @@ -1570,7 +1572,7 @@ func (p *parser) fieldDecl(styp *StructType) { // Careful dance: We don't know if we have an embedded instantiated // type T[P1, P2, ...] or a field T of array/slice type [P]E or []E. - if p.mode&AllowGenerics != 0 && len(names) == 1 && p.tok == _Lbrack { + if p.allowGenerics() && len(names) == 1 && p.tok == _Lbrack { typ = p.arrayOrTArgs() if typ, ok := typ.(*IndexExpr); ok { // embedded type T[P1, P2, ...] @@ -1708,7 +1710,7 @@ func (p *parser) methodDecl() *Field { f.Type = p.funcType() case _Lbrack: - if p.mode&AllowGenerics != 0 { + if p.allowGenerics() { // Careful dance: We don't know if we have a generic method m[T C](x T) // or an embedded instantiated type T[P1, P2] (we accept generic methods // for generality and robustness of parsing). @@ -1846,38 +1848,60 @@ func (p *parser) paramDeclOrNil(name *Name, follow token) *Field { defer p.trace("paramDecl")() } - f := new(Field) + // type set notation is ok in type parameter lists + typeSetsOk := p.mode&AllowTypeSets != 0 && follow == _Rbrack + + pos := p.pos() if name != nil { - f.pos = name.pos - } else { - f.pos = p.pos() + pos = name.pos + } else if typeSetsOk && p.tok == _Operator && p.op == Tilde { + // "~" ... + return p.embeddedElem(nil) } + f := new(Field) + f.pos = pos + if p.tok == _Name || name != nil { + // name if name == nil { name = p.name() } - if p.mode&AllowGenerics != 0 && p.tok == _Lbrack { + if p.allowGenerics() && p.tok == _Lbrack { + // name "[" ... f.Type = p.arrayOrTArgs() if typ, ok := f.Type.(*IndexExpr); ok { + // name "[" ... "]" typ.X = name } else { + // name "[" n "]" E f.Name = name } return f } if p.tok == _Dot { - // name_or_type + // name "." ... f.Type = p.qualifiedName(name) + if typeSetsOk && p.tok == _Operator && p.op == Or { + // name "." name "|" ... + f = p.embeddedElem(f) + } return f } + if typeSetsOk && p.tok == _Operator && p.op == Or { + // name "|" ... + f.Type = name + return p.embeddedElem(f) + } + f.Name = name } if p.tok == _DotDotDot { + // [name] "..." ... t := new(DotsType) t.pos = p.pos() p.next() @@ -1890,7 +1914,17 @@ func (p *parser) paramDeclOrNil(name *Name, follow token) *Field { return f } + if typeSetsOk && p.tok == _Operator && p.op == Tilde { + // [name] "~" ... + f.Type = p.embeddedElem(nil).Type + return f + } + f.Type = p.typeOrNil() + if typeSetsOk && p.tok == _Operator && p.op == Or && f.Type != nil { + // [name] type "|" + f = p.embeddedElem(f) + } if f.Name != nil || f.Type != nil { return f } @@ -1952,7 +1986,7 @@ func (p *parser) paramList(name *Name, close token, requireNames bool) (list []* if par.Type != nil { typ = par.Type if par.Name == nil { - pos = typ.Pos() + pos = StartPos(typ) par.Name = NewName(pos, "_") } } else if typ != nil { @@ -2654,7 +2688,7 @@ func (p *parser) qualifiedName(name *Name) Expr { x = s } - if p.mode&AllowGenerics != 0 && p.tok == _Lbrack { + if p.allowGenerics() && p.tok == _Lbrack { x = p.typeInstance(x) } diff --git a/src/cmd/compile/internal/syntax/parser_test.go b/src/cmd/compile/internal/syntax/parser_test.go index 04a16e96fe..fb02c8b95f 100644 --- a/src/cmd/compile/internal/syntax/parser_test.go +++ b/src/cmd/compile/internal/syntax/parser_test.go @@ -26,11 +26,11 @@ var ( ) func TestParse(t *testing.T) { - ParseFile(*src_, func(err error) { t.Error(err) }, nil, AllowGenerics) + ParseFile(*src_, func(err error) { t.Error(err) }, nil, AllowGenerics|AllowTypeSets) } func TestVerify(t *testing.T) { - ast, err := ParseFile(*src_, func(err error) { t.Error(err) }, nil, AllowGenerics) + ast, err := ParseFile(*src_, func(err error) { t.Error(err) }, nil, AllowGenerics|AllowTypeSets) if err != nil { return // error already reported } @@ -46,7 +46,7 @@ func TestParseGo2(t *testing.T) { for _, fi := range list { name := fi.Name() if !fi.IsDir() && !strings.HasPrefix(name, ".") { - ParseFile(filepath.Join(dir, name), func(err error) { t.Error(err) }, nil, AllowGenerics|AllowTypeLists) + ParseFile(filepath.Join(dir, name), func(err error) { t.Error(err) }, nil, AllowGenerics|AllowTypeSets|AllowTypeLists) } } } diff --git a/src/cmd/compile/internal/syntax/printer_test.go b/src/cmd/compile/internal/syntax/printer_test.go index d3469a2599..ee083ad159 100644 --- a/src/cmd/compile/internal/syntax/printer_test.go +++ b/src/cmd/compile/internal/syntax/printer_test.go @@ -72,6 +72,10 @@ var stringTests = []string{ "package p; func (*R[A, B, C]) _()", "package p; func (_ *R[A, B, C]) _()", + // type constraint literals with elided interfaces (only if AllowTypeSets is set) + "package p; func _[P ~int, Q int | string]() {}", + "package p; func _[P struct{f int}, Q *P]() {}", + // channels "package p; type _ chan chan int", "package p; type _ chan (<-chan int)", @@ -90,7 +94,7 @@ var stringTests = []string{ func TestPrintString(t *testing.T) { for _, want := range stringTests { - ast, err := Parse(nil, strings.NewReader(want), nil, nil, AllowGenerics|AllowTypeLists) + ast, err := Parse(nil, strings.NewReader(want), nil, nil, AllowGenerics|AllowTypeSets|AllowTypeLists) if err != nil { t.Error(err) continue diff --git a/src/cmd/compile/internal/syntax/syntax.go b/src/cmd/compile/internal/syntax/syntax.go index 08f450c94f..8828c39ad5 100644 --- a/src/cmd/compile/internal/syntax/syntax.go +++ b/src/cmd/compile/internal/syntax/syntax.go @@ -17,6 +17,7 @@ type Mode uint const ( CheckBranches Mode = 1 << iota // check correct use of labels, break, continue, and goto statements AllowGenerics + AllowTypeSets // requires AllowGenerics; remove once #48424 is decided AllowTypeLists // requires AllowGenerics; remove once 1.18 is out ) diff --git a/src/cmd/compile/internal/syntax/testdata/typeset.go2 b/src/cmd/compile/internal/syntax/testdata/typeset.go2 new file mode 100644 index 0000000000..a173bb1d4f --- /dev/null +++ b/src/cmd/compile/internal/syntax/testdata/typeset.go2 @@ -0,0 +1,72 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file contains test cases for typeset-only constraint elements. +// TODO(gri) gofmt once/if gofmt supports this notation. + +package p + +type ( + _[_ t] t + _[_ ~t] t + _[_ t|t] t + _[_ ~t|t] t + _[_ t|~t] t + _[_ ~t|~t] t + + _[_ t, _, _ t|t] t + _[_ t, _, _ ~t|t] t + _[_ t, _, _ t|~t] t + _[_ t, _, _ ~t|~t] t + + _[_ t.t] t + _[_ ~t.t] t + _[_ t.t|t.t] t + _[_ ~t.t|t.t] t + _[_ t.t|~t.t] t + _[_ ~t.t|~t.t] t + + _[_ t, _, _ t.t|t.t] t + _[_ t, _, _ ~t.t|t.t] t + _[_ t, _, _ t.t|~t.t] t + _[_ t, _, _ ~t.t|~t.t] t + + _[_ struct{}] t + _[_ ~struct{}] t + + _[_ struct{}|t] t + _[_ ~struct{}|t] t + _[_ struct{}|~t] t + _[_ ~struct{}|~t] t + + _[_ t|struct{}] t + _[_ ~t|struct{}] t + _[_ t|~struct{}] t + _[_ ~t|~struct{}] t +) + +// Single-expression type parameter lists and those that don't start +// with a (type parameter) name are considered array sizes. +// The term must be a valid expression (it could be a type - and then +// a type-checker will complain - but we don't allow ~ in the expr). +type ( + _[t] t + _[/* ERROR unexpected ~ */ ~t] t + _[t|t] t + _[/* ERROR unexpected ~ */ ~t|t] t + _[t| /* ERROR unexpected ~ */ ~t] t + _[/* ERROR unexpected ~ */ ~t|~t] t +) + +type ( + _[_ t, t /* ERROR missing type constraint */ ] t + _[_ ~t, t /* ERROR missing type constraint */ ] t + _[_ t, /* ERROR type parameters must be named */ ~t] t + _[_ ~t, /* ERROR type parameters must be named */ ~t] t + + _[_ t|t, /* ERROR type parameters must be named */ t|t] t + _[_ ~t|t, /* ERROR type parameters must be named */ t|t] t + _[_ t|t, /* ERROR type parameters must be named */ ~t|t] t + _[_ ~t|t, /* ERROR type parameters must be named */ ~t|t] t +) -- GitLab From dab16c1c90626ca6c9704959500f120fd09546e6 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 29 Sep 2021 20:56:36 -0700 Subject: [PATCH 1406/2500] cmd/compile/internal/types2: accept constraint literals with elided interfaces When collecting type parameters, wrap constraint literals of the form ~T or A|B into interfaces so the type checker doesn't have to deal with these type set expressions syntactically anywhere else but in interfaces (i.e., union types continue to appear only as embedded elements in interfaces). Since a type constraint doesn't need to be an interface anymore, we can remove the respective restriction. Instead, when accessing the constraint interface via TypeParam.iface, wrap non-interface constraints at that point and update the constraint so it happens only once. By computing the types sets of all type parameters at before the end of type-checking, we ensure that type constraints are in their final form when accessed through the API. For #48424. Change-Id: I3a47a644ad4ab20f91d93ee39fcf3214bb5a81f9 Reviewed-on: https://go-review.googlesource.com/c/go/+/353139 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/check_test.go | 2 +- src/cmd/compile/internal/types2/decl.go | 22 +++++++-- .../types2/testdata/examples/typesets.go2 | 48 ++++++++++++++++++ .../types2/testdata/fixedbugs/issue39723.go2 | 2 +- src/cmd/compile/internal/types2/typeparam.go | 49 +++++++++++++------ test/typeparam/tparam1.go | 4 +- 6 files changed, 106 insertions(+), 21 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/examples/typesets.go2 diff --git a/src/cmd/compile/internal/types2/check_test.go b/src/cmd/compile/internal/types2/check_test.go index 26c8eba727..1ca2eea5c6 100644 --- a/src/cmd/compile/internal/types2/check_test.go +++ b/src/cmd/compile/internal/types2/check_test.go @@ -100,7 +100,7 @@ func testFiles(t *testing.T, filenames []string, colDelta uint, manual bool) { var mode syntax.Mode if strings.HasSuffix(filenames[0], ".go2") { - mode |= syntax.AllowGenerics | syntax.AllowTypeLists + mode |= syntax.AllowGenerics | syntax.AllowTypeSets | syntax.AllowTypeLists } // parse files and collect parser errors files, errlist := parseFiles(t, filenames, mode) diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 128e89dec6..10c63355e9 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -632,21 +632,35 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list []*syntax.Fiel // This also preserves the grouped output of type parameter lists // when printing type strings. if i == 0 || f.Type != list[i-1].Type { - bound = check.typ(f.Type) + bound = check.bound(f.Type) } tparams[i].bound = bound } check.later(func() { for i, tpar := range tparams { - u := under(tpar.bound) - if _, ok := u.(*Interface); !ok && u != Typ[Invalid] { - check.errorf(list[i].Type, "%s is not an interface", tpar.bound) + if _, ok := under(tpar.bound).(*TypeParam); ok { + check.error(list[i].Type, "cannot use a type parameter as constraint") } + tpar.iface() // compute type set } }) } +func (check *Checker) bound(x syntax.Expr) Type { + // A type set literal of the form ~T and A|B may only appear as constraint; + // embed it in an implicit interface so that only interface type-checking + // needs to take care of such type expressions. + if op, _ := x.(*syntax.Operation); op != nil && (op.Op == syntax.Tilde || op.Op == syntax.Or) { + // TODO(gri) Should mark this interface as "implicit" somehow + // (and propagate the info to types2.Interface) so + // that we can elide the interface again in error + // messages. Could use a sentinel name for the field. + x = &syntax.InterfaceType{MethodList: []*syntax.Field{{Type: x}}} + } + return check.typ(x) +} + func (check *Checker) declareTypeParam(name *syntax.Name) *TypeParam { // Use Typ[Invalid] for the type constraint to ensure that a type // is present even if the actual constraint has not been assigned diff --git a/src/cmd/compile/internal/types2/testdata/examples/typesets.go2 b/src/cmd/compile/internal/types2/testdata/examples/typesets.go2 new file mode 100644 index 0000000000..0a1b0f5cfc --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/examples/typesets.go2 @@ -0,0 +1,48 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file shows some examples of constraint literals with elided interfaces. +// These examples are permitted if proposal issue #48424 is accepted. + +package p + +// Constraint type sets of the form T, ~T, or A|B may omit the interface. +type ( + _[T int] struct{} + _[T ~int] struct{} + _[T int|string] struct{} + _[T ~int|~string] struct{} +) + +func min[T int|string](x, y T) T { + if x < y { + return x + } + return y +} + +func lookup[M ~map[K]V, K comparable, V any](m M, k K) V { + return m[k] +} + +func deref[P ~*E, E any](p P) E { + return *p +} + +func _() int { + p := new(int) + return deref(p) +} + +func addrOfCopy[V any, P ~*V](v V) P { + return &v +} + +func _() *int { + return addrOfCopy(0) +} + +// A type parameter may not be embedded in an interface; +// so it can also not be used as a constraint. +func _[A any, B A /* ERROR cannot use a type parameter as constraint */ ]() {} diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39723.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39723.go2 index d5311ed3e7..00885238e6 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39723.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39723.go2 @@ -6,4 +6,4 @@ package p // A constraint must be an interface; it cannot // be a type parameter, for instance. -func _[A interface{ ~int }, B A /* ERROR not an interface */ ]() {} +func _[A interface{ ~int }, B A /* ERROR cannot use a type parameter as constraint */ ]() {} diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index 505596f571..c295702fe5 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -21,8 +21,7 @@ type TypeParam struct { id uint64 // unique id, for debugging only obj *TypeName // corresponding type name index int // type parameter index in source order, starting at 0 - // TODO(rfindley): this could also be Typ[Invalid]. Verify that this is handled correctly. - bound Type // *Named or *Interface; underlying type is always *Interface + bound Type // any type, but eventually an *Interface for correct programs (see TypeParam.iface) } // Obj returns the type name for the type parameter t. @@ -64,15 +63,6 @@ func (t *TypeParam) SetId(id uint64) { // Constraint returns the type constraint specified for t. func (t *TypeParam) Constraint() Type { - // compute the type set if possible (we may not have an interface) - if iface, _ := under(t.bound).(*Interface); iface != nil { - // use the type bound position if we have one - pos := nopos - if n, _ := t.bound.(*Named); n != nil { - pos = n.obj.pos - } - computeInterfaceTypeSet(t.check, pos, iface) - } return t.bound } @@ -92,10 +82,41 @@ func (t *TypeParam) String() string { return TypeString(t, nil) } // iface returns the constraint interface of t. func (t *TypeParam) iface() *Interface { - if iface, _ := under(t.Constraint()).(*Interface); iface != nil { - return iface + bound := t.bound + + // determine constraint interface + var ityp *Interface + switch u := under(bound).(type) { + case *Basic: + if u == Typ[Invalid] { + // error is reported elsewhere + return &emptyInterface + } + case *Interface: + ityp = u + case *TypeParam: + // error is reported in Checker.collectTypeParams + return &emptyInterface + } + + // If we don't have an interface, wrap constraint into an implicit interface. + // TODO(gri) mark it as implicit - see comment in Checker.bound + if ityp == nil { + ityp = NewInterfaceType(nil, []Type{bound}) + t.bound = ityp // update t.bound for next time (optimization) } - return &emptyInterface + + // compute type set if necessary + if ityp.tset == nil { + // use the (original) type bound position if we have one + pos := nopos + if n, _ := bound.(*Named); n != nil { + pos = n.obj.pos + } + computeInterfaceTypeSet(t.check, pos, ityp) + } + + return ityp } // structuralType returns the structural type of the type parameter's constraint; or nil. diff --git a/test/typeparam/tparam1.go b/test/typeparam/tparam1.go index 3b4260c102..ef024ce40f 100644 --- a/test/typeparam/tparam1.go +++ b/test/typeparam/tparam1.go @@ -10,7 +10,9 @@ package tparam1 // The predeclared identifier "any" may be used in place of interface{}. var _ any + func _(_ any) + type _[_ any] struct{} const N = 10 @@ -32,7 +34,7 @@ type C interface{} func _[T interface{}]() {} func _[T C]() {} -func _[T struct{}]() {} // ERROR "not an interface" +func _[T struct{}]() {} // ok if #48424 is accepted func _[T interface{ m() T }]() {} func _[T1 interface{ m() T2 }, T2 interface{ m() T1 }]() { var _ T1 -- GitLab From 952df981580659389679b27d65e1eceeedf0e2df Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 30 Sep 2021 10:04:46 -0700 Subject: [PATCH 1407/2500] cmd/compile: accept constraint literals with elided interfaces This change enables the relaxed syntax for constraint literals as proposed in issue #48424 and adds a simple smoke test for the compiler. (Most of the relevant changes are in the syntax and types2 package which have more extensive tests for this.) This makes it possible to experiment with the new syntax while we contemplate the fate of #48424. If #48424 is accepted, this change can remain. If #48424 is not accepted, reverting this CL will remove this feature in the compiler. For #48424. Change-Id: I624fbb37c2f616ee9ad692e17e4fc75c9d5b06e5 Reviewed-on: https://go-review.googlesource.com/c/go/+/353389 Trust: Robert Griesemer Trust: Dan Scales Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/noder.go | 2 +- src/go/internal/gcimporter/gcimporter_test.go | 5 +- test/typeparam/issue48424.go | 54 +++++++++++++++++++ 3 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 test/typeparam/issue48424.go diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index 7c14fcf041..2e7b636681 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -36,7 +36,7 @@ func LoadPackage(filenames []string) { mode := syntax.CheckBranches if supportsGenerics { - mode |= syntax.AllowGenerics + mode |= syntax.AllowGenerics | syntax.AllowTypeSets } // Limit the number of simultaneously open files. diff --git a/src/go/internal/gcimporter/gcimporter_test.go b/src/go/internal/gcimporter/gcimporter_test.go index 3a9ed79df6..825f735db9 100644 --- a/src/go/internal/gcimporter/gcimporter_test.go +++ b/src/go/internal/gcimporter/gcimporter_test.go @@ -165,8 +165,9 @@ func TestImportTypeparamTests(t *testing.T) { } skip := map[string]string{ - "equal.go": "inconsistent embedded sorting", // TODO(rfindley): investigate this. - "nested.go": "fails to compile", // TODO(rfindley): investigate this. + "equal.go": "inconsistent embedded sorting", // TODO(rfindley): investigate this. + "nested.go": "fails to compile", // TODO(rfindley): investigate this. + "issue48424.go": "go/types support missing", // TODO: need to implement this if #48424 is accepted } for _, entry := range list { diff --git a/test/typeparam/issue48424.go b/test/typeparam/issue48424.go new file mode 100644 index 0000000000..b1238df697 --- /dev/null +++ b/test/typeparam/issue48424.go @@ -0,0 +1,54 @@ +// run + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Smoke test for constraint literals with elided interface +// per issue #48424. + +package main + +func identity[T int](x T) T { + return x +} + +func min[T int|string](x, y T) T { + if x < y { + return x + } + return y +} + +func max[T ~float64](x, y T) T { + if x > y { + return x + } + return y +} + +func main() { + if identity(1) != 1 { + panic("identity(1) failed") + } + + if min(2, 3) != 2 { + panic("min(2, 3) failed") + } + + if min("foo", "bar") != "bar" { + panic(`min("foo", "bar") failed`) + } + + if max(2, 3) != 3 { + panic("max(2, 3) failed") + } +} + +// Some random type parameter lists with elided interfaces. + +type ( + _ [T struct{}] struct{} + _ [M map[K]V, K comparable, V any] struct{} + _ [_ interface{}|int] struct{} +) -- GitLab From 33576247e295b19311484d943d85495006d2fb39 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 30 Sep 2021 13:37:30 -0700 Subject: [PATCH 1408/2500] cmd/compile/internal/types2: mark implicit interfaces as such Provide an accessor for clients, and don't print the interface around implicitly wrapped embedded types. For #48424. Change-Id: Ib2c76315508fc749ea4337d52e13d17de80e04da Reviewed-on: https://go-review.googlesource.com/c/go/+/353396 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/decl.go | 11 ++++++----- src/cmd/compile/internal/types2/interface.go | 5 ++++- .../internal/types2/testdata/examples/typesets.go2 | 10 ++++++++++ src/cmd/compile/internal/types2/typeparam.go | 2 +- src/cmd/compile/internal/types2/typestring.go | 9 +++++++++ src/cmd/compile/internal/types2/universe.go | 4 ++-- 6 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 10c63355e9..7ae980e5c9 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -652,11 +652,12 @@ func (check *Checker) bound(x syntax.Expr) Type { // embed it in an implicit interface so that only interface type-checking // needs to take care of such type expressions. if op, _ := x.(*syntax.Operation); op != nil && (op.Op == syntax.Tilde || op.Op == syntax.Or) { - // TODO(gri) Should mark this interface as "implicit" somehow - // (and propagate the info to types2.Interface) so - // that we can elide the interface again in error - // messages. Could use a sentinel name for the field. - x = &syntax.InterfaceType{MethodList: []*syntax.Field{{Type: x}}} + t := check.typ(&syntax.InterfaceType{MethodList: []*syntax.Field{{Type: x}}}) + // mark t as implicit interface if all went well + if t, _ := t.(*Interface); t != nil { + t.implicit = true + } + return t } return check.typ(x) } diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index a6faf3267b..431ba93c17 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -16,6 +16,7 @@ type Interface struct { methods []*Func // ordered list of explicitly declared methods embeddeds []Type // ordered list of explicitly embedded elements embedPos *[]syntax.Pos // positions of embedded elements; or nil (for error messages) - use pointer to save space + implicit bool // interface is wrapper for type set literal (non-interface T, ~T, or A|B) complete bool // indicates that all fields (except for tset) are set up tset *_TypeSet // type set described by this interface, computed lazily @@ -82,6 +83,9 @@ func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() } // IsMethodSet reports whether the interface t is fully described by its method set. func (t *Interface) IsMethodSet() bool { return t.typeSet().IsMethodSet() } +// IsImplicit reports whether the interface t is a wrapper for a type set literal. +func (t *Interface) IsImplicit() bool { return t.implicit } + func (t *Interface) Underlying() Type { return t } func (t *Interface) String() string { return TypeString(t, nil) } @@ -102,7 +106,6 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType for _, f := range iface.MethodList { if f.Name == nil { - // We have an embedded type; possibly a union of types. addEmbedded(posFor(f.Type), parseUnion(check, flattenUnion(nil, f.Type))) continue } diff --git a/src/cmd/compile/internal/types2/testdata/examples/typesets.go2 b/src/cmd/compile/internal/types2/testdata/examples/typesets.go2 index 0a1b0f5cfc..cf01072d8c 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/typesets.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/typesets.go2 @@ -46,3 +46,13 @@ func _() *int { // A type parameter may not be embedded in an interface; // so it can also not be used as a constraint. func _[A any, B A /* ERROR cannot use a type parameter as constraint */ ]() {} + +// Error messages refer to the type constraint as it appears in the source. +// (No implicit interface should be exposed.) +func _[T string](x T) T { + return x /* ERROR constrained by string */ * x +} + +func _[T int|string](x T) T { + return x /* ERROR constrained by int|string */ * x +} diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index c295702fe5..3ec4a641a6 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -100,9 +100,9 @@ func (t *TypeParam) iface() *Interface { } // If we don't have an interface, wrap constraint into an implicit interface. - // TODO(gri) mark it as implicit - see comment in Checker.bound if ityp == nil { ityp = NewInterfaceType(nil, []Type{bound}) + ityp.implicit = true t.bound = ityp // update t.bound for next time (optimization) } diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 930acf053a..c1feaa97cc 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -190,6 +190,15 @@ func (w *typeWriter) typ(typ Type) { } case *Interface: + if t.implicit { + if len(t.methods) == 0 && len(t.embeddeds) == 1 { + w.typ(t.embeddeds[0]) + break + } + // Something's wrong with the implicit interface. + // Print it as such and continue. + w.string("/* implicit */ ") + } w.string("interface{") first := true for _, m := range t.methods { diff --git a/src/cmd/compile/internal/types2/universe.go b/src/cmd/compile/internal/types2/universe.go index 27f38de27a..92fa32524c 100644 --- a/src/cmd/compile/internal/types2/universe.go +++ b/src/cmd/compile/internal/types2/universe.go @@ -88,7 +88,7 @@ func defPredeclaredTypes() { res := NewVar(nopos, nil, "", Typ[String]) sig := NewSignatureType(nil, nil, nil, nil, NewTuple(res), false) err := NewFunc(nopos, nil, "Error", sig) - ityp := &Interface{nil, obj, []*Func{err}, nil, nil, true, nil} + ityp := &Interface{nil, obj, []*Func{err}, nil, nil, false, true, nil} computeInterfaceTypeSet(nil, nopos, ityp) // prevent races due to lazy computation of tset typ := NewNamed(obj, ityp, nil) sig.recv = NewVar(nopos, nil, "", typ) @@ -99,7 +99,7 @@ func defPredeclaredTypes() { { obj := NewTypeName(nopos, nil, "comparable", nil) obj.setColor(black) - ityp := &Interface{nil, obj, nil, nil, nil, true, &_TypeSet{true, nil, allTermlist}} + ityp := &Interface{nil, obj, nil, nil, nil, false, true, &_TypeSet{true, nil, allTermlist}} NewNamed(obj, ityp, nil) def(obj) } -- GitLab From 243d65c8e551be424008a3dfcaf5c87dc1f35a77 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 23 Sep 2021 11:56:16 -0400 Subject: [PATCH 1409/2500] bufio: reject UnreadByte or UnreadRune after a Discard or WriteTo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Discard is not really a read operation, and in theory it could Seek the underlying Reader without actually reading anything, so an UnreadByte following a Discard is disallowed. Similarly, although WriteTo usually does end up calling Read on the underlying buffer, if the underlying Reader implements io.WriterTo it may instead terminate in a call to WriteTo, without ever buffering or even seeing the last byte written. (It is conceptually read-like, but not strictly “a read operation”.) Fixes #48446 Change-Id: Ide6f2b157332b423486810399f66140c914144e5 Reviewed-on: https://go-review.googlesource.com/c/go/+/351810 Trust: Bryan C. Mills Trust: Joe Tsai Reviewed-by: Joe Tsai --- src/bufio/bufio.go | 11 +++++++++-- src/bufio/bufio_test.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/bufio/bufio.go b/src/bufio/bufio.go index 506b84f6ba..a58df25494 100644 --- a/src/bufio/bufio.go +++ b/src/bufio/bufio.go @@ -173,6 +173,10 @@ func (b *Reader) Discard(n int) (discarded int, err error) { if n == 0 { return } + + b.lastByte = -1 + b.lastRuneSize = -1 + remain := n for { skip := b.Buffered() @@ -266,8 +270,8 @@ func (b *Reader) ReadByte() (byte, error) { // UnreadByte unreads the last byte. Only the most recently read byte can be unread. // // UnreadByte returns an error if the most recent method called on the -// Reader was not a read operation. Notably, Peek is not considered a -// read operation. +// Reader was not a read operation. Notably, Peek, Discard, and WriteTo are not +// considered read operations. func (b *Reader) UnreadByte() error { if b.lastByte < 0 || b.r == 0 && b.w > 0 { return ErrInvalidUnreadByte @@ -502,6 +506,9 @@ func (b *Reader) ReadString(delim byte) (string, error) { // If the underlying reader supports the WriteTo method, // this calls the underlying WriteTo without buffering. func (b *Reader) WriteTo(w io.Writer) (n int64, err error) { + b.lastByte = -1 + b.lastRuneSize = -1 + n, err = b.writeBuf(w) if err != nil { return diff --git a/src/bufio/bufio_test.go b/src/bufio/bufio_test.go index 04a810c206..8e8a8a1778 100644 --- a/src/bufio/bufio_test.go +++ b/src/bufio/bufio_test.go @@ -304,6 +304,40 @@ func TestNoUnreadByteAfterPeek(t *testing.T) { } } +func TestNoUnreadRuneAfterDiscard(t *testing.T) { + br := NewReader(strings.NewReader("example")) + br.ReadRune() + br.Discard(1) + if err := br.UnreadRune(); err == nil { + t.Error("UnreadRune didn't fail after Discard") + } +} + +func TestNoUnreadByteAfterDiscard(t *testing.T) { + br := NewReader(strings.NewReader("example")) + br.ReadByte() + br.Discard(1) + if err := br.UnreadByte(); err == nil { + t.Error("UnreadByte didn't fail after Discard") + } +} + +func TestNoUnreadRuneAfterWriteTo(t *testing.T) { + br := NewReader(strings.NewReader("example")) + br.WriteTo(io.Discard) + if err := br.UnreadRune(); err == nil { + t.Error("UnreadRune didn't fail after WriteTo") + } +} + +func TestNoUnreadByteAfterWriteTo(t *testing.T) { + br := NewReader(strings.NewReader("example")) + br.WriteTo(io.Discard) + if err := br.UnreadByte(); err == nil { + t.Error("UnreadByte didn't fail after WriteTo") + } +} + func TestUnreadByte(t *testing.T) { segments := []string{"Hello, ", "world"} r := NewReader(&StringReader{data: segments}) -- GitLab From 0d65c272c9e494cbb604f2bee99d434b8cde46ff Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 29 Sep 2021 10:54:27 -0700 Subject: [PATCH 1410/2500] cmd/compile: remove typeparam subscripts, use func/type prefix for uniqueness In types1 and for the export format, we were using type param subscripts coming from types2 (originally for debugging) to provide unique names. We need unique full-names for type params in types1 to ensure consistent references to type params in function/method bodies and type params derived from translation from types2. We also currently need unique names for type params in importer/iimport.go and gcimporter/iimport.go, because there are no levels of scoping in the package symbol lookup and pkgIndex table. As a step to eliminate the typeparam subscripts (which have no relation to the source code), we change so that the typeparams' unique name is just prefixing the type param name with the name of the enclosing generic function, type, or method. We now no longer use types2.TypeString in types2-to-types1 translation, so Typestring can be changed to eliminate the subscript, as needed. Also, types2.TypeParam.SetId() is no longer needed and is eliminated. We can decide later if we want to do the further step of adding scoping to the importer/iimport.go and gcimporter/iimport.go, which could be used to eliminate the type param "path" prefix from the export format. Change-Id: I0e37795664be2c2e1869b8f9e93393b83fc56409 Reviewed-on: https://go-review.googlesource.com/c/go/+/353135 Trust: Dan Scales Run-TryBot: Dan Scales Reviewed-by: Robert Findley --- src/cmd/compile/internal/importer/iimport.go | 32 ++++------------- src/cmd/compile/internal/noder/decl.go | 17 +++++++++ src/cmd/compile/internal/noder/irgen.go | 6 ++++ src/cmd/compile/internal/noder/types.go | 9 ++++- src/cmd/compile/internal/types2/typeparam.go | 6 ---- src/cmd/compile/internal/types2/typestring.go | 3 -- src/go/internal/gcimporter/iimport.go | 36 ++++--------------- 7 files changed, 44 insertions(+), 65 deletions(-) diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index b9d2ecbdb5..cbc78539fd 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -362,13 +362,13 @@ func (r *importReader) obj(name string) { if r.p.exportVersion < iexportVersionGenerics { errorf("unexpected type param type") } - name0, sub := parseSubscript(name) - tn := types2.NewTypeName(pos, r.currPkg, name0, nil) - t := types2.NewTypeParam(tn, nil) - if sub == 0 { - errorf("missing subscript") + // Remove the "path" from the type param name that makes it unique + ix := strings.LastIndex(name, ".") + if ix < 0 { + errorf("missing path for type param") } - t.SetId(sub) + tn := types2.NewTypeName(pos, r.currPkg, name[ix+1:], nil) + t := types2.NewTypeParam(tn, nil) // To handle recursive references to the typeparam within its // bound, save the partial type in tparamIndex before reading the bounds. id := ident{r.currPkg.Name(), name} @@ -752,23 +752,3 @@ func baseType(typ types2.Type) *types2.Named { n, _ := typ.(*types2.Named) return n } - -func parseSubscript(name string) (string, uint64) { - // Extract the subscript value from the type param name. We export - // and import the subscript value, so that all type params have - // unique names. - sub := uint64(0) - startsub := -1 - for i, r := range name { - if '₀' <= r && r < '₀'+10 { - if startsub == -1 { - startsub = i - } - sub = sub*10 + uint64(r-'₀') - } - } - if startsub >= 0 { - name = name[:startsub] - } - return name, sub -} diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go index c9ab31f203..f2dad9c302 100644 --- a/src/cmd/compile/internal/noder/decl.go +++ b/src/cmd/compile/internal/noder/decl.go @@ -86,6 +86,17 @@ func (g *irgen) constDecl(out *ir.Nodes, decl *syntax.ConstDecl) { } func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) { + // Set g.curDecl to the function name, as context for the type params declared + // during types2-to-types1 translation if this is a generic function. + g.curDecl = decl.Name.Value + obj2 := g.info.Defs[decl.Name] + recv := types2.AsSignature(obj2.Type()).Recv() + if recv != nil { + t2 := deref2(recv.Type()) + // This is a method, so set g.curDecl to recvTypeName.methName instead. + g.curDecl = types2.AsNamed(t2).Obj().Name() + "." + g.curDecl + } + fn := ir.NewFunc(g.pos(decl)) fn.Nname, _ = g.def(decl.Name) fn.Nname.Func = fn @@ -143,6 +154,9 @@ func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) { } func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) { + // Set g.curDecl to the type name, as context for the type params declared + // during types2-to-types1 translation if this is a generic type. + g.curDecl = decl.Name.Value if decl.Alias { name, _ := g.def(decl.Name) g.pragmaFlags(decl.Pragma, 0) @@ -205,6 +219,9 @@ func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) { methods := make([]*types.Field, otyp.NumMethods()) for i := range methods { m := otyp.Method(i) + // Set g.curDecl to recvTypeName.methName, as context for the + // method-specific type params in the receiver. + g.curDecl = decl.Name.Value + "." + m.Name() meth := g.obj(m) methods[i] = types.NewField(meth.Pos(), g.selector(m), meth.Type()) methods[i].Nname = meth diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index b0a4da3536..645ac2c214 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -170,6 +170,12 @@ type irgen struct { // avoid adding closures of generic functions/methods to the target.Decls // list. topFuncIsGeneric bool + + // The context during type/function/method declarations that is used to + // uniquely name type parameters. We need unique names for type params so we + // can be sure they match up correctly between types2-to-types1 translation + // and types1 importing. + curDecl string } func (g *irgen) later(fn func()) { diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index e1cfe4a9d8..1a7cef4aa3 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -219,7 +219,10 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { // Save the name of the type parameter in the sym of the type. // Include the types2 subscript in the sym name pkg := g.tpkg(typ) - sym := pkg.Lookup(types2.TypeString(typ, func(*types2.Package) string { return "" })) + // Create the unique types1 name for a type param, using its context with a + // function, type, or method declaration. + nm := g.curDecl + "." + typ.Obj().Name() + sym := pkg.Lookup(nm) if sym.Def != nil { // Make sure we use the same type param type for the same // name, whether it is created during types1-import or @@ -318,6 +321,10 @@ func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) { meth2 = ir.NewNameAt(meth.Pos(), newsym) rparams := types2.AsSignature(m.Type()).RecvTypeParams() tparams := make([]*types.Type, rparams.Len()) + // Set g.curDecl to be the method context, so type + // params in the receiver of the method that we are + // translating gets the right unique name. + g.curDecl = typ.Obj().Name() + "." + m.Name() for i := range tparams { tparams[i] = g.typ1(rparams.At(i)) } diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index 3ec4a641a6..6bc9dbc24d 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -55,12 +55,6 @@ func (t *TypeParam) Index() int { return t.index } -// SetId sets the unique id of a type param. Should only be used for type params -// in imported generic types. -func (t *TypeParam) SetId(id uint64) { - t.id = id -} - // Constraint returns the type constraint specified for t. func (t *TypeParam) Constraint() Type { return t.bound diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index c1feaa97cc..61c8a9158c 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -267,9 +267,6 @@ func (w *typeWriter) typ(typ Type) { break } // Optionally write out package for typeparams (like Named). - // TODO(danscales): this is required for import/export, so - // we maybe need a separate function that won't be changed - // for debugging purposes. if t.obj.pkg != nil { writePackage(w.buf, t.obj.pkg, w.qf) } diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go index e61a3a51a1..9aae2a31f3 100644 --- a/src/go/internal/gcimporter/iimport.go +++ b/src/go/internal/gcimporter/iimport.go @@ -18,6 +18,7 @@ import ( "io" "math/big" "sort" + "strings" ) type intReader struct { @@ -353,16 +354,13 @@ func (r *importReader) obj(name string) { if r.p.exportVersion < iexportVersionGenerics { errorf("unexpected type param type") } - name0, sub := parseSubscript(name) - tn := types.NewTypeName(pos, r.currPkg, name0, nil) - t := types.NewTypeParam(tn, nil) - if sub == 0 { - errorf("missing subscript") + // Remove the "path" from the type param name that makes it unique + ix := strings.LastIndex(name, ".") + if ix < 0 { + errorf("missing path for type param") } - - // TODO(rfindley): can we use a different, stable ID? - // t.SetId(sub) - + tn := types.NewTypeName(pos, r.currPkg, name[ix+1:], nil) + t := types.NewTypeParam(tn, nil) // To handle recursive references to the typeparam within its // bound, save the partial type in tparamIndex before reading the bounds. id := ident{r.currPkg.Name(), name} @@ -743,23 +741,3 @@ func baseType(typ types.Type) *types.Named { n, _ := typ.(*types.Named) return n } - -func parseSubscript(name string) (string, uint64) { - // Extract the subscript value from the type param name. We export - // and import the subscript value, so that all type params have - // unique names. - sub := uint64(0) - startsub := -1 - for i, r := range name { - if '₀' <= r && r < '₀'+10 { - if startsub == -1 { - startsub = i - } - sub = sub*10 + uint64(r-'₀') - } - } - if startsub >= 0 { - name = name[:startsub] - } - return name, sub -} -- GitLab From c129af90eb20a5723fc7ed19b19afe054036fe71 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 1 Oct 2021 12:32:41 -0700 Subject: [PATCH 1411/2500] text/template: undo reflect.Value wrapping for short-circuit and/or For #31103 Change-Id: I9c0aa64f95f564de31a4c178e3930584d41316bb Reviewed-on: https://go-review.googlesource.com/c/go/+/353610 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/text/template/exec.go | 16 ++++++++++------ src/text/template/exec_test.go | 1 + 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/text/template/exec.go b/src/text/template/exec.go index fce3b0abbf..9a4c9e29dd 100644 --- a/src/text/template/exec.go +++ b/src/text/template/exec.go @@ -714,6 +714,13 @@ func (s *state) evalCall(dot, fun reflect.Value, isBuiltin bool, node parse.Node s.errorf("can't call method/function %q with %d results", name, typ.NumOut()) } + unwrap := func(v reflect.Value) reflect.Value { + if v.Type() == reflectValueType { + v = v.Interface().(reflect.Value) + } + return v + } + // Special case for builtin and/or, which short-circuit. if isBuiltin && (name == "and" || name == "or") { argType := typ.In(0) @@ -721,13 +728,13 @@ func (s *state) evalCall(dot, fun reflect.Value, isBuiltin bool, node parse.Node for _, arg := range args { v = s.evalArg(dot, argType, arg).Interface().(reflect.Value) if truth(v) == (name == "or") { - return v + return unwrap(v) } } if final != missingVal { v = s.validateType(final, argType) } - return v + return unwrap(v) } // Build the arg list. @@ -767,10 +774,7 @@ func (s *state) evalCall(dot, fun reflect.Value, isBuiltin bool, node parse.Node s.at(node) s.errorf("error calling %s: %w", name, err) } - if v.Type() == reflectValueType { - v = v.Interface().(reflect.Value) - } - return v + return unwrap(v) } // canBeNil reports whether an untyped nil can be assigned to the type. See reflect.Zero. diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go index a0432a588d..1a839a641b 100644 --- a/src/text/template/exec_test.go +++ b/src/text/template/exec_test.go @@ -491,6 +491,7 @@ var execTests = []execTest{ {"or pipe-false", "{{0 | or 0}}", "0", nil, true}, {"boolean if", "{{if and true 1 `hi`}}TRUE{{else}}FALSE{{end}}", "TRUE", tVal, true}, {"boolean if not", "{{if and true 1 `hi` | not}}TRUE{{else}}FALSE{{end}}", "FALSE", nil, true}, + {"boolean if pipe", "{{if true | not | and 1}}TRUE{{else}}FALSE{{end}}", "FALSE", nil, true}, // Indexing. {"slice[0]", "{{index .SI 0}}", "3", tVal, true}, -- GitLab From cf241a34a2ee8b337e11731958d918cbfd338caf Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 30 Sep 2021 16:35:52 -0700 Subject: [PATCH 1412/2500] net: consistently return DNSError on lookup failure Previously if we failed because the context timed out or was canceled, we returned errCanceled or errTimeout. Fixes #39178 Change-Id: I11bd7ebfaa7e5775fb05dfbb6b67f8307c8d8697 Reviewed-on: https://go-review.googlesource.com/c/go/+/353400 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Damien Neil --- src/net/lookup.go | 27 ++++++++++++++-- src/net/lookup_test.go | 70 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 93 insertions(+), 4 deletions(-) diff --git a/src/net/lookup.go b/src/net/lookup.go index 3c0153028c..fe573b8a27 100644 --- a/src/net/lookup.go +++ b/src/net/lookup.go @@ -316,18 +316,39 @@ func (r *Resolver) lookupIPAddr(ctx context.Context, network, host string) ([]IP lookupGroupCancel() }() } - err := mapErr(ctx.Err()) + ctxErr := ctx.Err() + err := &DNSError{ + Err: mapErr(ctxErr).Error(), + Name: host, + IsTimeout: ctxErr == context.DeadlineExceeded, + } if trace != nil && trace.DNSDone != nil { trace.DNSDone(nil, false, err) } return nil, err case r := <-ch: lookupGroupCancel() + err := r.Err + if err != nil { + if _, ok := err.(*DNSError); !ok { + isTimeout := false + if err == context.DeadlineExceeded { + isTimeout = true + } else if terr, ok := err.(timeout); ok { + isTimeout = terr.Timeout() + } + err = &DNSError{ + Err: err.Error(), + Name: host, + IsTimeout: isTimeout, + } + } + } if trace != nil && trace.DNSDone != nil { addrs, _ := r.Val.([]IPAddr) - trace.DNSDone(ipAddrsEface(addrs), r.Shared, r.Err) + trace.DNSDone(ipAddrsEface(addrs), r.Shared, err) } - return lookupIPReturn(r.Val, r.Err, r.Shared) + return lookupIPReturn(r.Val, err, r.Shared) } } diff --git a/src/net/lookup_test.go b/src/net/lookup_test.go index 3faaf00710..7ca6ac16ec 100644 --- a/src/net/lookup_test.go +++ b/src/net/lookup_test.go @@ -890,7 +890,7 @@ func TestLookupContextCancel(t *testing.T) { ctx, ctxCancel := context.WithCancel(context.Background()) ctxCancel() _, err := DefaultResolver.LookupIPAddr(ctx, "google.com") - if err != errCanceled { + if err.(*DNSError).Err != errCanceled.Error() { testenv.SkipFlakyNet(t) t.Fatal(err) } @@ -1267,3 +1267,71 @@ func TestResolverLookupIP(t *testing.T) { }) } } + +// A context timeout should still return a DNSError. +func TestDNSTimeout(t *testing.T) { + origTestHookLookupIP := testHookLookupIP + defer func() { testHookLookupIP = origTestHookLookupIP }() + defer dnsWaitGroup.Wait() + + timeoutHookGo := make(chan bool, 1) + timeoutHook := func(ctx context.Context, fn func(context.Context, string, string) ([]IPAddr, error), network, host string) ([]IPAddr, error) { + <-timeoutHookGo + return nil, context.DeadlineExceeded + } + testHookLookupIP = timeoutHook + + checkErr := func(err error) { + t.Helper() + if err == nil { + t.Error("expected an error") + } else if dnserr, ok := err.(*DNSError); !ok { + t.Errorf("got error type %T, want %T", err, (*DNSError)(nil)) + } else if !dnserr.IsTimeout { + t.Errorf("got error %#v, want IsTimeout == true", dnserr) + } else if isTimeout := dnserr.Timeout(); !isTimeout { + t.Errorf("got err.Timeout() == %t, want true", isTimeout) + } + } + + // Single lookup. + timeoutHookGo <- true + _, err := LookupIP("golang.org") + checkErr(err) + + // Double lookup. + var err1, err2 error + var wg sync.WaitGroup + wg.Add(2) + go func() { + defer wg.Done() + _, err1 = LookupIP("golang1.org") + }() + go func() { + defer wg.Done() + _, err2 = LookupIP("golang1.org") + }() + close(timeoutHookGo) + wg.Wait() + checkErr(err1) + checkErr(err2) + + // Double lookup with context. + timeoutHookGo = make(chan bool) + ctx, cancel := context.WithTimeout(context.Background(), time.Nanosecond) + wg.Add(2) + go func() { + defer wg.Done() + _, err1 = DefaultResolver.LookupIPAddr(ctx, "golang2.org") + }() + go func() { + defer wg.Done() + _, err2 = DefaultResolver.LookupIPAddr(ctx, "golang2.org") + }() + time.Sleep(10 * time.Nanosecond) + close(timeoutHookGo) + wg.Wait() + checkErr(err1) + checkErr(err2) + cancel() +} -- GitLab From 64da5e0fd5979ba489e03cedf3c63c21f8bfcefe Mon Sep 17 00:00:00 2001 From: Leon Klingele Date: Fri, 1 Oct 2021 09:05:13 +0000 Subject: [PATCH 1413/2500] net/http/pprof: use "curl" instead of "wget" in usage example The "curl" binary is already used at several other places inside the code base, whereas this was the only occurrence of "wget". Change-Id: I2b9c5c353d08b3ba8289819b4a602c51f1ebd593 GitHub-Last-Rev: abf94855223c4ceac08dd0d18c5a2b97d1abcca9 GitHub-Pull-Request: golang/go#48718 Reviewed-on: https://go-review.googlesource.com/c/go/+/353401 Reviewed-by: Cherry Mui Reviewed-by: Ian Lance Taylor Run-TryBot: Cherry Mui TryBot-Result: Go Bot --- src/net/http/pprof/pprof.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/http/pprof/pprof.go b/src/net/http/pprof/pprof.go index 888ea35c9a..dc855c8a6d 100644 --- a/src/net/http/pprof/pprof.go +++ b/src/net/http/pprof/pprof.go @@ -44,7 +44,7 @@ // The package also exports a handler that serves execution trace data // for the "go tool trace" command. To collect a 5-second execution trace: // -// wget -O trace.out http://localhost:6060/debug/pprof/trace?seconds=5 +// curl -o trace.out http://localhost:6060/debug/pprof/trace?seconds=5 // go tool trace trace.out // // To view all available profiles, open http://localhost:6060/debug/pprof/ -- GitLab From afe43f1e5e0d256341689195454527726b26ccae Mon Sep 17 00:00:00 2001 From: roudkerk Date: Mon, 19 Jul 2021 12:49:57 +0100 Subject: [PATCH 1414/2500] context: implement Context.Value using iteration rather than recursion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In profiles of a production server, 2.3% of CPU time is spent in runtime.newstack for stacks with 12 or more chained Context.Value calls. Using iteration will avoid some needless stack resizes. When calling Context.Value in the same goroutine (see DeepValueSameGoRoutine) , no stack resizing is needed (after warming up), and this change reduces time/op by around 10%. The time to start a new goroutine and call Context.Value (see DeepValueNewGoRoutine) is reduced by over 75% if a stack resize is needed. If you factor out the overhead of starting the goroutine (about 960ns) then, avoiding the stack resize saves about 95%. ``` name old time/op new time/op delta CommonParentCancel-12 960ns ± 1% 958ns ± 1% ~ (p=0.561 n=9+9) WithTimeout/concurrency=40-12 1.31µs ± 2% 1.29µs ± 6% ~ (p=0.305 n=9+10) WithTimeout/concurrency=4000-12 1.30µs ± 2% 1.30µs ± 2% ~ (p=0.343 n=10+10) WithTimeout/concurrency=400000-12 1.03µs ± 1% 1.02µs ± 2% ~ (p=0.213 n=9+9) CancelTree/depth=1/Root=Background-12 123ns ± 5% 126ns ± 2% +2.61% (p=0.023 n=10+9) CancelTree/depth=1/Root=OpenCanceler-12 781ns ± 4% 806ns ± 4% +3.20% (p=0.022 n=9+10) CancelTree/depth=1/Root=ClosedCanceler-12 370ns ± 4% 369ns ± 3% ~ (p=0.497 n=9+10) CancelTree/depth=10/Root=Background-12 4.74µs ± 4% 4.78µs ± 3% ~ (p=0.516 n=10+10) CancelTree/depth=10/Root=OpenCanceler-12 6.31µs ± 4% 6.29µs ± 4% ~ (p=1.000 n=10+10) CancelTree/depth=10/Root=ClosedCanceler-12 2.10µs ± 5% 2.09µs ± 5% ~ (p=0.839 n=10+10) CancelTree/depth=100/Root=Background-12 51.0µs ± 3% 51.2µs ± 2% ~ (p=0.631 n=10+10) CancelTree/depth=100/Root=OpenCanceler-12 60.8µs ± 1% 61.6µs ± 4% ~ (p=0.274 n=8+10) CancelTree/depth=100/Root=ClosedCanceler-12 19.3µs ± 2% 19.0µs ± 3% ~ (p=0.123 n=10+10) CancelTree/depth=1000/Root=Background-12 504µs ± 4% 512µs ± 4% ~ (p=0.123 n=10+10) CancelTree/depth=1000/Root=OpenCanceler-12 615µs ± 6% 619µs ± 4% ~ (p=1.000 n=10+10) CancelTree/depth=1000/Root=ClosedCanceler-12 190µs ± 2% 192µs ± 3% ~ (p=0.190 n=9+9) CheckCanceled/Err-12 12.1ns ± 2% 12.1ns ± 2% ~ (p=0.615 n=10+10) CheckCanceled/Done-12 7.27ns ± 1% 7.26ns ± 1% ~ (p=0.698 n=10+10) ContextCancelDone-12 1.03ns ± 1% 1.03ns ± 1% ~ (p=0.474 n=9+9) DeepValueNewGoRoutine/depth=10-12 1.02µs ± 3% 0.99µs ± 2% -3.41% (p=0.000 n=10+10) DeepValueNewGoRoutine/depth=20-12 1.11µs ± 3% 1.08µs ± 2% -2.51% (p=0.004 n=10+10) DeepValueNewGoRoutine/depth=30-12 5.55µs ±10% 1.17µs ± 4% -78.91% (p=0.000 n=10+10) DeepValueNewGoRoutine/depth=50-12 5.70µs ±13% 1.35µs ± 2% -76.31% (p=0.000 n=10+10) DeepValueNewGoRoutine/depth=100-12 9.69µs ± 4% 1.82µs ± 2% -81.18% (p=0.000 n=10+10) DeepValueSameGoRoutine/depth=10-12 54.2ns ± 2% 46.8ns ± 2% -13.71% (p=0.000 n=9+9) DeepValueSameGoRoutine/depth=20-12 109ns ± 2% 97ns ± 2% -11.11% (p=0.000 n=10+10) DeepValueSameGoRoutine/depth=30-12 155ns ± 3% 140ns ± 1% -9.49% (p=0.000 n=10+10) DeepValueSameGoRoutine/depth=50-12 256ns ± 2% 226ns ± 2% -11.83% (p=0.000 n=10+10) DeepValueSameGoRoutine/depth=100-12 492ns ± 3% 442ns ± 1% -10.15% (p=0.000 n=10+10) ``` Fixes #47292 Change-Id: I6bdeb234c979fb8fd6bfb91fd345cb5038f52c75 Reviewed-on: https://go-review.googlesource.com/c/go/+/335790 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Damien Neil --- src/context/benchmark_test.go | 36 +++++++++++++++++++++++++++++++++++ src/context/context.go | 30 +++++++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/context/benchmark_test.go b/src/context/benchmark_test.go index 69d75fff18..144f473a44 100644 --- a/src/context/benchmark_test.go +++ b/src/context/benchmark_test.go @@ -152,3 +152,39 @@ func BenchmarkContextCancelDone(b *testing.B) { } }) } + +func BenchmarkDeepValueNewGoRoutine(b *testing.B) { + for _, depth := range []int{10, 20, 30, 50, 100} { + ctx := Background() + for i := 0; i < depth; i++ { + ctx = WithValue(ctx, i, i) + } + + b.Run(fmt.Sprintf("depth=%d", depth), func(b *testing.B) { + for i := 0; i < b.N; i++ { + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + ctx.Value(-1) + }() + wg.Wait() + } + }) + } +} + +func BenchmarkDeepValueSameGoRoutine(b *testing.B) { + for _, depth := range []int{10, 20, 30, 50, 100} { + ctx := Background() + for i := 0; i < depth; i++ { + ctx = WithValue(ctx, i, i) + } + + b.Run(fmt.Sprintf("depth=%d", depth), func(b *testing.B) { + for i := 0; i < b.N; i++ { + ctx.Value(-1) + } + }) + } +} diff --git a/src/context/context.go b/src/context/context.go index 733c5f56d9..a9e14703fd 100644 --- a/src/context/context.go +++ b/src/context/context.go @@ -352,7 +352,7 @@ func (c *cancelCtx) Value(key interface{}) interface{} { if key == &cancelCtxKey { return c } - return c.Context.Value(key) + return value(c.Context, key) } func (c *cancelCtx) Done() <-chan struct{} { @@ -563,5 +563,31 @@ func (c *valueCtx) Value(key interface{}) interface{} { if c.key == key { return c.val } - return c.Context.Value(key) + return value(c.Context, key) +} + +func value(c Context, key interface{}) interface{} { + for { + switch ctx := c.(type) { + case *valueCtx: + if key == ctx.key { + return ctx.val + } + c = ctx.Context + case *cancelCtx: + if key == &cancelCtxKey { + return c + } + c = ctx.Context + case *timerCtx: + if key == &cancelCtxKey { + return &ctx.cancelCtx + } + c = ctx.Context + case *emptyCtx: + return nil + default: + return c.Value(key) + } + } } -- GitLab From 7bf7bbc2419795f11b2a4fd482ae67d6f66e2df8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Sat, 16 Jan 2021 18:03:31 +0000 Subject: [PATCH 1415/2500] cmd/go: remove double parallelism from "go fmt" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that gofmt knows how to format many files in parallel, there's no need for "go fmt" to have its own parallelism. Instead of running "gofmt -l -w $file" in parallel with GOMAXPROCS, simply collect a large list of files and hand it to "gofmt -l -w $files". The benchmark below was obtained via: benchcmd -n 10 FmtGorootCmd go fmt cmd We can see a drastic improvement in system time per call. This makes sense, as we used to fork+exec one gofmt program per file, and now we only do that for every thousand or so files. We also see an increase in peak memory usage and user CPU time. This seems to be because each gofmt process was very short lived before. This meant that there was a limit to the total amount of allocations produced by go/parser and go/printer before the process stopped, and thus the GC probably didn't kick in most of the time. Now that each gofmt process formats hundreds or thousands of files, a lot of those allocations pile up in the same process, making peak-RSS go higher and piling on garbage for the GC to clean up. Finally, note that time/op seems largely unchanged. I did many benchmark runs; some ended up in noise like the one below, and others gave small wall time speed-ups of 3-4%. It seems like we get very little wall time benefit, possibly due to the factors mentioned earlier cancelling each other out. Overall, it seems worthwhile to not let "go fmt" do its own parallelism, to keep the tool simpler to understand and maintain going forward. Plus, the sys-time savings do seem to be the biggest change here. name old time/op new time/op delta FmtGorootCmd 850ms ± 4% 842ms ± 6% ~ (p=0.529 n=10+10) name old user-time/op new user-time/op delta FmtGorootCmd 7.30s ± 4% 7.67s ± 3% +5.07% (p=0.000 n=10+10) name old sys-time/op new sys-time/op delta FmtGorootCmd 1.66s ± 7% 0.43s ±24% -74.08% (p=0.000 n=10+10) name old peak-RSS-bytes new peak-RSS-bytes delta FmtGorootCmd 30.1MB ± 4% 199.4MB ±21% +563.03% (p=0.000 n=10+10) To make use of the already-present "maximum exec arg length limit" constant in cmd/go/internal, move it to cmd/internal. Fixes #43566. Change-Id: If864151d0c851a40bf7138f9864640f15a066d48 Reviewed-on: https://go-review.googlesource.com/c/go/+/353309 Trust: Daniel Martí Run-TryBot: Daniel Martí TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/go_test.go | 3 +-- src/cmd/go/internal/fmtcmd/fmt.go | 36 +++++++++++++-------------- src/cmd/go/internal/work/exec.go | 9 ++----- src/cmd/go/internal/work/exec_test.go | 5 ++-- src/cmd/internal/sys/args.go | 13 ++++++++++ 5 files changed, 37 insertions(+), 29 deletions(-) create mode 100644 src/cmd/internal/sys/args.go diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index b13191f678..07e9962896 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -31,7 +31,6 @@ import ( "cmd/go/internal/cache" "cmd/go/internal/cfg" "cmd/go/internal/robustio" - "cmd/go/internal/work" "cmd/internal/sys" ) @@ -1378,7 +1377,7 @@ func TestLdFlagsLongArgumentsIssue42295(t *testing.T) { }`) testStr := "test test test test test \n\\ " var buf bytes.Buffer - for buf.Len() < work.ArgLengthForResponseFile+1 { + for buf.Len() < sys.ExecArgLengthLimit+1 { buf.WriteString(testStr) } tg.run("run", "-ldflags", fmt.Sprintf(`-X "main.extern=%s"`, buf.String()), tg.path("main.go")) diff --git a/src/cmd/go/internal/fmtcmd/fmt.go b/src/cmd/go/internal/fmtcmd/fmt.go index 2b89a078ac..19656eab7f 100644 --- a/src/cmd/go/internal/fmtcmd/fmt.go +++ b/src/cmd/go/internal/fmtcmd/fmt.go @@ -11,14 +11,12 @@ import ( "fmt" "os" "path/filepath" - "runtime" - "sync" "cmd/go/internal/base" "cmd/go/internal/cfg" "cmd/go/internal/load" "cmd/go/internal/modload" - "cmd/internal/str" + "cmd/internal/sys" ) func init() { @@ -53,18 +51,13 @@ See also: go fix, go vet. func runFmt(ctx context.Context, cmd *base.Command, args []string) { printed := false gofmt := gofmtPath() - procs := runtime.GOMAXPROCS(0) - var wg sync.WaitGroup - wg.Add(procs) - fileC := make(chan string, 2*procs) - for i := 0; i < procs; i++ { - go func() { - defer wg.Done() - for file := range fileC { - base.Run(str.StringList(gofmt, "-l", "-w", file)) - } - }() - } + + gofmtArgs := []string{gofmt, "-l", "-w"} + gofmtArgLen := len(gofmt) + len(" -l -w") + + baseGofmtArgs := len(gofmtArgs) + baseGofmtArgLen := gofmtArgLen + for _, pkg := range load.PackagesAndErrors(ctx, load.PackageOpts{}, args) { if modload.Enabled() && pkg.Module != nil && !pkg.Module.Main { if !printed { @@ -89,11 +82,18 @@ func runFmt(ctx context.Context, cmd *base.Command, args []string) { // not to packages in subdirectories. files := base.RelPaths(pkg.InternalAllGoFiles()) for _, file := range files { - fileC <- file + gofmtArgs = append(gofmtArgs, file) + gofmtArgLen += 1 + len(file) // plus separator + if gofmtArgLen >= sys.ExecArgLengthLimit { + base.Run(gofmtArgs) + gofmtArgs = gofmtArgs[:baseGofmtArgs] + gofmtArgLen = baseGofmtArgLen + } } } - close(fileC) - wg.Wait() + if len(gofmtArgs) > baseGofmtArgs { + base.Run(gofmtArgs) + } } func gofmtPath() string { diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index 692d394520..99e92947ee 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -36,6 +36,7 @@ import ( "cmd/go/internal/modload" "cmd/go/internal/trace" "cmd/internal/str" + "cmd/internal/sys" ) // actionList returns the list of actions in the dag rooted at root @@ -3307,12 +3308,6 @@ func passLongArgsInResponseFiles(cmd *exec.Cmd) (cleanup func()) { return cleanup } -// Windows has a limit of 32 KB arguments. To be conservative and not worry -// about whether that includes spaces or not, just use 30 KB. Darwin's limit is -// less clear. The OS claims 256KB, but we've seen failures with arglen as -// small as 50KB. -const ArgLengthForResponseFile = (30 << 10) - func useResponseFile(path string, argLen int) bool { // Unless the program uses objabi.Flagparse, which understands // response files, don't use response files. @@ -3324,7 +3319,7 @@ func useResponseFile(path string, argLen int) bool { return false } - if argLen > ArgLengthForResponseFile { + if argLen > sys.ExecArgLengthLimit { return true } diff --git a/src/cmd/go/internal/work/exec_test.go b/src/cmd/go/internal/work/exec_test.go index 4eb762cb28..8bbf25bb33 100644 --- a/src/cmd/go/internal/work/exec_test.go +++ b/src/cmd/go/internal/work/exec_test.go @@ -7,6 +7,7 @@ package work import ( "bytes" "cmd/internal/objabi" + "cmd/internal/sys" "fmt" "math/rand" "testing" @@ -56,7 +57,7 @@ func TestEncodeDecodeFuzz(t *testing.T) { } t.Parallel() - nRunes := ArgLengthForResponseFile + 100 + nRunes := sys.ExecArgLengthLimit + 100 rBuffer := make([]rune, nRunes) buf := bytes.NewBuffer([]byte(string(rBuffer))) @@ -67,7 +68,7 @@ func TestEncodeDecodeFuzz(t *testing.T) { for i := 0; i < 50; i++ { // Generate a random string of runes. buf.Reset() - for buf.Len() < ArgLengthForResponseFile+1 { + for buf.Len() < sys.ExecArgLengthLimit+1 { var r rune for { r = rune(rng.Intn(utf8.MaxRune + 1)) diff --git a/src/cmd/internal/sys/args.go b/src/cmd/internal/sys/args.go new file mode 100644 index 0000000000..cc9fb64af2 --- /dev/null +++ b/src/cmd/internal/sys/args.go @@ -0,0 +1,13 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sys + +// ExecArgLengthLimit is the number of bytes we can safely +// pass as arguments to an exec.Command. +// +// Windows has a limit of 32 KB. To be conservative and not worry about whether +// that includes spaces or not, just use 30 KB. Darwin's limit is less clear. +// The OS claims 256KB, but we've seen failures with arglen as small as 50KB. +const ExecArgLengthLimit = (30 << 10) -- GitLab From 07a7c6f904a4deed9a37bf5c79a1c3d21d623347 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 1 Oct 2021 21:02:43 -0700 Subject: [PATCH 1416/2500] test/typeparam: require -G=3 for issue48424.go (fix build) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Icabef5cf75770ffde012b1fc785a72f53f9b2c46 Reviewed-on: https://go-review.googlesource.com/c/go/+/353669 Trust: Robert Griesemer Trust: Daniel Martí Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Daniel Martí --- test/typeparam/issue48424.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/typeparam/issue48424.go b/test/typeparam/issue48424.go index b1238df697..3253e6457b 100644 --- a/test/typeparam/issue48424.go +++ b/test/typeparam/issue48424.go @@ -1,4 +1,4 @@ -// run +// run -gcflags=-G=3 // Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style -- GitLab From a7fe161ccceb330cd1f19cd103a61f8deacbbdc3 Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Fri, 1 Oct 2021 17:45:09 -0700 Subject: [PATCH 1417/2500] net: don't use syscall.NET_RT_IFLISTL on FreeBSD The golang.org/x/net/route package can't parse the RIB returned by NET_RT_IFLISTL. Use the route.RIBTypeInterface constant instead, leaving the choice of syscall up to the route package. Fixes #48553. Change-Id: Ida4bd6e332c0dc6dc871d3a93cfb56c0fbc93e1b Reviewed-on: https://go-review.googlesource.com/c/go/+/353611 Trust: Damien Neil Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot --- src/net/interface_freebsd.go | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/net/interface_freebsd.go b/src/net/interface_freebsd.go index 2b51fcb632..8536bd3cf6 100644 --- a/src/net/interface_freebsd.go +++ b/src/net/interface_freebsd.go @@ -11,16 +11,11 @@ import ( ) func interfaceMessages(ifindex int) ([]route.Message, error) { - typ := route.RIBType(syscall.NET_RT_IFLISTL) - rib, err := route.FetchRIB(syscall.AF_UNSPEC, typ, ifindex) + rib, err := route.FetchRIB(syscall.AF_UNSPEC, route.RIBTypeInterface, ifindex) if err != nil { - typ = route.RIBType(syscall.NET_RT_IFLIST) - rib, err = route.FetchRIB(syscall.AF_UNSPEC, typ, ifindex) - if err != nil { - return nil, err - } + return nil, err } - return route.ParseRIB(typ, rib) + return route.ParseRIB(route.RIBTypeInterface, rib) } // interfaceMulticastAddrTable returns addresses for a specific -- GitLab From 3bbc82371eb801ce489f77359f0badc8e469c26d Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Thu, 26 Aug 2021 01:33:29 +1000 Subject: [PATCH 1418/2500] cmd/internal/obj/riscv,cmd/link/internal/riscv64: add call trampolines for riscv64 CALL and JMP on riscv64 are currently implemented as an AUIPC+JALR pair. This means that every call requires two instructions and makes use of the REG_TMP register, even when the symbol would be directly reachable via a single JAL instruction. Add support for call trampolines - CALL and JMP are now implemented as a single JAL instruction, with the linker generating trampolines in the case where the symbol is not reachable (more than +/-1MiB from the JAL instruction), is an unknown symbol or does not yet have an address assigned. Each trampoline contains an AUIPC+JALR pair, which the relocation is applied to. Due to the limited reachability of the JAL instruction, combined with the way that the Go linker currently assigns symbol addresses, there are cases where a call is to a symbol that has no address currently assigned. In this situation we have to assume that a trampoline will be required, however we can patch this up during relocation, potentially calling directly instead. This means that we will end up with trampolines that are unused. In the case of the Go binary, there are around 3,500 trampolines of which approximately 2,300 are unused (around 9200 bytes of machine instructions). Overall, this removes over 72,000 AUIPC instructions from the Go binary. Change-Id: I2d9ecfb85dfc285c7729a3cd0b3a77b6f6c98be0 Reviewed-on: https://go-review.googlesource.com/c/go/+/345051 Trust: Joel Sing Run-TryBot: Joel Sing TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/asm/internal/asm/testdata/riscv64.s | 13 +- src/cmd/internal/obj/riscv/cpu.go | 12 +- src/cmd/internal/obj/riscv/obj.go | 88 ++++++------ src/cmd/internal/objabi/reloctype.go | 13 +- src/cmd/internal/objabi/reloctype_string.go | 101 +++++++------- src/cmd/link/internal/ld/data.go | 15 ++- src/cmd/link/internal/ld/pcln.go | 7 +- src/cmd/link/internal/riscv64/asm.go | 141 ++++++++++++++++++-- src/cmd/link/internal/riscv64/obj.go | 14 +- 9 files changed, 269 insertions(+), 135 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/riscv64.s b/src/cmd/asm/internal/asm/testdata/riscv64.s index 64b94a2a04..fe911a74f5 100644 --- a/src/cmd/asm/internal/asm/testdata/riscv64.s +++ b/src/cmd/asm/internal/asm/testdata/riscv64.s @@ -357,13 +357,12 @@ start: JMP (X5) // 67800200 JMP 4(X5) // 67804200 - // JMP and CALL to symbol are encoded as: - // AUIPC $0, TMP - // JALR $0, TMP - // with a R_RISCV_PCREL_ITYPE relocation - the linker resolves the - // real address and updates the immediates for both instructions. - CALL asmtest(SB) // 970f0000 - JMP asmtest(SB) // 970f0000 + // CALL and JMP to symbol are encoded as JAL (using LR or ZERO + // respectively), with a R_RISCV_CALL relocation. The linker resolves + // the real address and updates the immediate, using a trampoline in + // the case where the address is not directly reachable. + CALL asmtest(SB) // ef000000 + JMP asmtest(SB) // 6f000000 // Branch pseudo-instructions BEQZ X5, 2(PC) // 63840200 diff --git a/src/cmd/internal/obj/riscv/cpu.go b/src/cmd/internal/obj/riscv/cpu.go index a258367ae9..ed88f621d9 100644 --- a/src/cmd/internal/obj/riscv/cpu.go +++ b/src/cmd/internal/obj/riscv/cpu.go @@ -260,6 +260,10 @@ const ( // corresponding *obj.Prog uses the temporary register. USES_REG_TMP = 1 << iota + // NEED_CALL_RELOC is set on JAL instructions to indicate that a + // R_RISCV_CALL relocation is needed. + NEED_CALL_RELOC + // NEED_PCREL_ITYPE_RELOC is set on AUIPC instructions to indicate that // it is the first instruction in an AUIPC + I-type pair that needs a // R_RISCV_PCREL_ITYPE relocation. @@ -632,6 +636,10 @@ var unaryDst = map[obj.As]bool{ // Instruction encoding masks. const ( + // JTypeImmMask is a mask including only the immediate portion of + // J-type instructions. + JTypeImmMask = 0xfffff000 + // ITypeImmMask is a mask including only the immediate portion of // I-type instructions. ITypeImmMask = 0xfff00000 @@ -643,8 +651,4 @@ const ( // UTypeImmMask is a mask including only the immediate portion of // U-type instructions. UTypeImmMask = 0xfffff000 - - // UJTypeImmMask is a mask including only the immediate portion of - // UJ-type instructions. - UJTypeImmMask = UTypeImmMask ) diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index f0ea21de97..b346b13577 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -30,41 +30,19 @@ import ( func buildop(ctxt *obj.Link) {} -// jalrToSym replaces p with a set of Progs needed to jump to the Sym in p. -// lr is the link register to use for the JALR. -// p must be a CALL, JMP or RET. -func jalrToSym(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, lr int16) *obj.Prog { - if p.As != obj.ACALL && p.As != obj.AJMP && p.As != obj.ARET && p.As != obj.ADUFFZERO && p.As != obj.ADUFFCOPY { - ctxt.Diag("unexpected Prog in jalrToSym: %v", p) - return p +func jalToSym(ctxt *obj.Link, p *obj.Prog, lr int16) { + switch p.As { + case obj.ACALL, obj.AJMP, obj.ARET, obj.ADUFFZERO, obj.ADUFFCOPY: + default: + ctxt.Diag("unexpected Prog in jalToSym: %v", p) + return } - // TODO(jsing): Consider using a single JAL instruction and teaching - // the linker to provide trampolines for the case where the destination - // offset is too large. This would potentially reduce instructions for - // the common case, but would require three instructions to go via the - // trampoline. - - to := p.To - - p.As = AAUIPC - p.Mark |= NEED_PCREL_ITYPE_RELOC - p.SetFrom3(obj.Addr{Type: obj.TYPE_CONST, Offset: to.Offset, Sym: to.Sym}) - p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: 0} - p.Reg = obj.REG_NONE - p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP} - p = obj.Appendp(p, newprog) - - // Leave Sym only for the CALL reloc in assemble. - p.As = AJALR + p.As = AJAL + p.Mark |= NEED_CALL_RELOC p.From.Type = obj.TYPE_REG p.From.Reg = lr p.Reg = obj.REG_NONE - p.To.Type = obj.TYPE_REG - p.To.Reg = REG_TMP - p.To.Sym = to.Sym - - return p } // progedit is called individually for each *obj.Prog. It normalizes instruction @@ -531,7 +509,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { case obj.ACALL, obj.ADUFFZERO, obj.ADUFFCOPY: switch p.To.Type { case obj.TYPE_MEM: - jalrToSym(ctxt, p, newprog, REG_LR) + jalToSym(ctxt, p, REG_LR) } case obj.AJMP: @@ -539,8 +517,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { case obj.TYPE_MEM: switch p.To.Name { case obj.NAME_EXTERN, obj.NAME_STATIC: - // JMP to symbol. - jalrToSym(ctxt, p, newprog, REG_ZERO) + jalToSym(ctxt, p, REG_ZERO) } } @@ -566,7 +543,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { if retJMP != nil { p.As = obj.ARET p.To.Sym = retJMP - p = jalrToSym(ctxt, p, newprog, REG_ZERO) + jalToSym(ctxt, p, REG_ZERO) } else { p.As = AJALR p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO} @@ -640,8 +617,9 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { rescan = true } case AJAL: + // Linker will handle the intersymbol case and trampolines. if p.To.Target() == nil { - panic("intersymbol jumps should be expressed as AUIPC+JALR") + break } offset := p.To.Target().Pc - p.Pc if offset < -(1<<20) || (1<<20) <= offset { @@ -676,7 +654,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { // instructions will break everything--don't do it! for p := cursym.Func().Text; p != nil; p = p.Link { switch p.As { - case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ, AJAL: + case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ: switch p.To.Type { case obj.TYPE_BRANCH: p.To.Type, p.To.Offset = obj.TYPE_CONST, p.To.Target().Pc-p.Pc @@ -684,6 +662,12 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { panic("unhandled type") } + case AJAL: + // Linker will handle the intersymbol case and trampolines. + if p.To.Target() != nil { + p.To.Type, p.To.Offset = obj.TYPE_CONST, p.To.Target().Pc-p.Pc + } + case AAUIPC: if p.From.Type == obj.TYPE_BRANCH { low, high, err := Split32BitImmediate(p.From.Target().Pc - p.Pc) @@ -802,7 +786,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, cursym *obj.LSym, newprog obj.ProgA if to_more != nil { to_more.To.SetTarget(p) } - p = jalrToSym(ctxt, p, newprog, REG_X5) + jalToSym(ctxt, p, REG_X5) // JMP start p = obj.Appendp(p, newprog) @@ -1187,6 +1171,11 @@ func encodeU(ins *instruction) uint32 { return imm<<12 | rd<<7 | enc.opcode } +// encodeJImmediate encodes an immediate for a J-type RISC-V instruction. +func encodeJImmediate(imm uint32) uint32 { + return (imm>>20)<<31 | ((imm>>1)&0x3ff)<<21 | ((imm>>11)&0x1)<<20 | ((imm>>12)&0xff)<<12 +} + // encodeJ encodes a J-type RISC-V instruction. func encodeJ(ins *instruction) uint32 { imm := immI(ins.as, ins.imm, 21) @@ -1195,7 +1184,7 @@ func encodeJ(ins *instruction) uint32 { if enc == nil { panic("encodeJ: could not encode instruction") } - return (imm>>20)<<31 | ((imm>>1)&0x3ff)<<21 | ((imm>>11)&0x1)<<20 | ((imm>>12)&0xff)<<12 | rd<<7 | enc.opcode + return encodeJImmediate(imm) | rd<<7 | enc.opcode } func encodeRawIns(ins *instruction) uint32 { @@ -1207,6 +1196,16 @@ func encodeRawIns(ins *instruction) uint32 { return uint32(ins.imm) } +func EncodeJImmediate(imm int64) (int64, error) { + if !immIFits(imm, 21) { + return 0, fmt.Errorf("immediate %#x does not fit in 21 bits", imm) + } + if imm&1 != 0 { + return 0, fmt.Errorf("immediate %#x is not a multiple of two", imm) + } + return int64(encodeJImmediate(uint32(imm))), nil +} + func EncodeIImmediate(imm int64) (int64, error) { if !immIFits(imm, 12) { return 0, fmt.Errorf("immediate %#x does not fit in 12 bits", imm) @@ -2035,17 +2034,18 @@ func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { for p := cursym.Func().Text; p != nil; p = p.Link { switch p.As { - case AJALR: - if p.To.Sym != nil { - // This is a CALL/JMP. We add a relocation only - // for linker stack checking. No actual - // relocation is needed. + case AJAL: + if p.Mark&NEED_CALL_RELOC == NEED_CALL_RELOC { rel := obj.Addrel(cursym) rel.Off = int32(p.Pc) rel.Siz = 4 rel.Sym = p.To.Sym rel.Add = p.To.Offset - rel.Type = objabi.R_CALLRISCV + rel.Type = objabi.R_RISCV_CALL + } + case AJALR: + if p.To.Sym != nil { + ctxt.Diag("%v: unexpected AJALR with to symbol", p) } case AAUIPC, AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD: diff --git a/src/cmd/internal/objabi/reloctype.go b/src/cmd/internal/objabi/reloctype.go index 52827a6dee..0cc60fbe3b 100644 --- a/src/cmd/internal/objabi/reloctype.go +++ b/src/cmd/internal/objabi/reloctype.go @@ -59,8 +59,6 @@ const ( // R_CALLMIPS (only used on mips64) resolves to non-PC-relative target address // of a CALL (JAL) instruction, by encoding the address into the instruction. R_CALLMIPS - // R_CALLRISCV marks RISC-V CALLs for stack checking. - R_CALLRISCV R_CONST R_PCREL // R_TLS_LE, used on 386, amd64, and ARM, resolves to the offset of the @@ -218,6 +216,15 @@ const ( // RISC-V. + // R_RISCV_CALL relocates a J-type instruction with a 21 bit PC-relative + // address. + R_RISCV_CALL + + // R_RISCV_CALL_TRAMP is the same as R_RISCV_CALL but denotes the use of a + // trampoline, which we may be able to avoid during relocation. These are + // only used by the linker and are not emitted by the compiler or assembler. + R_RISCV_CALL_TRAMP + // R_RISCV_PCREL_ITYPE resolves a 32-bit PC-relative address using an // AUIPC + I-type instruction pair. R_RISCV_PCREL_ITYPE @@ -274,7 +281,7 @@ const ( // the target address in register or memory. func (r RelocType) IsDirectCall() bool { switch r { - case R_CALL, R_CALLARM, R_CALLARM64, R_CALLMIPS, R_CALLPOWER, R_CALLRISCV: + case R_CALL, R_CALLARM, R_CALLARM64, R_CALLMIPS, R_CALLPOWER, R_RISCV_CALL, R_RISCV_CALL_TRAMP: return true } return false diff --git a/src/cmd/internal/objabi/reloctype_string.go b/src/cmd/internal/objabi/reloctype_string.go index 4638ef14d9..f2e06a5b21 100644 --- a/src/cmd/internal/objabi/reloctype_string.go +++ b/src/cmd/internal/objabi/reloctype_string.go @@ -20,59 +20,60 @@ func _() { _ = x[R_CALLIND-10] _ = x[R_CALLPOWER-11] _ = x[R_CALLMIPS-12] - _ = x[R_CALLRISCV-13] - _ = x[R_CONST-14] - _ = x[R_PCREL-15] - _ = x[R_TLS_LE-16] - _ = x[R_TLS_IE-17] - _ = x[R_GOTOFF-18] - _ = x[R_PLT0-19] - _ = x[R_PLT1-20] - _ = x[R_PLT2-21] - _ = x[R_USEFIELD-22] - _ = x[R_USETYPE-23] - _ = x[R_USEIFACE-24] - _ = x[R_USEIFACEMETHOD-25] - _ = x[R_METHODOFF-26] - _ = x[R_KEEP-27] - _ = x[R_POWER_TOC-28] - _ = x[R_GOTPCREL-29] - _ = x[R_JMPMIPS-30] - _ = x[R_DWARFSECREF-31] - _ = x[R_DWARFFILEREF-32] - _ = x[R_ARM64_TLS_LE-33] - _ = x[R_ARM64_TLS_IE-34] - _ = x[R_ARM64_GOTPCREL-35] - _ = x[R_ARM64_GOT-36] - _ = x[R_ARM64_PCREL-37] - _ = x[R_ARM64_LDST8-38] - _ = x[R_ARM64_LDST16-39] - _ = x[R_ARM64_LDST32-40] - _ = x[R_ARM64_LDST64-41] - _ = x[R_ARM64_LDST128-42] - _ = x[R_POWER_TLS_LE-43] - _ = x[R_POWER_TLS_IE-44] - _ = x[R_POWER_TLS-45] - _ = x[R_ADDRPOWER_DS-46] - _ = x[R_ADDRPOWER_GOT-47] - _ = x[R_ADDRPOWER_PCREL-48] - _ = x[R_ADDRPOWER_TOCREL-49] - _ = x[R_ADDRPOWER_TOCREL_DS-50] - _ = x[R_RISCV_PCREL_ITYPE-51] - _ = x[R_RISCV_PCREL_STYPE-52] - _ = x[R_RISCV_TLS_IE_ITYPE-53] - _ = x[R_RISCV_TLS_IE_STYPE-54] - _ = x[R_PCRELDBL-55] - _ = x[R_ADDRMIPSU-56] - _ = x[R_ADDRMIPSTLS-57] - _ = x[R_ADDRCUOFF-58] - _ = x[R_WASMIMPORT-59] - _ = x[R_XCOFFREF-60] + _ = x[R_CONST-13] + _ = x[R_PCREL-14] + _ = x[R_TLS_LE-15] + _ = x[R_TLS_IE-16] + _ = x[R_GOTOFF-17] + _ = x[R_PLT0-18] + _ = x[R_PLT1-19] + _ = x[R_PLT2-20] + _ = x[R_USEFIELD-21] + _ = x[R_USETYPE-22] + _ = x[R_USEIFACE-23] + _ = x[R_USEIFACEMETHOD-24] + _ = x[R_METHODOFF-25] + _ = x[R_KEEP-26] + _ = x[R_POWER_TOC-27] + _ = x[R_GOTPCREL-28] + _ = x[R_JMPMIPS-29] + _ = x[R_DWARFSECREF-30] + _ = x[R_DWARFFILEREF-31] + _ = x[R_ARM64_TLS_LE-32] + _ = x[R_ARM64_TLS_IE-33] + _ = x[R_ARM64_GOTPCREL-34] + _ = x[R_ARM64_GOT-35] + _ = x[R_ARM64_PCREL-36] + _ = x[R_ARM64_LDST8-37] + _ = x[R_ARM64_LDST16-38] + _ = x[R_ARM64_LDST32-39] + _ = x[R_ARM64_LDST64-40] + _ = x[R_ARM64_LDST128-41] + _ = x[R_POWER_TLS_LE-42] + _ = x[R_POWER_TLS_IE-43] + _ = x[R_POWER_TLS-44] + _ = x[R_ADDRPOWER_DS-45] + _ = x[R_ADDRPOWER_GOT-46] + _ = x[R_ADDRPOWER_PCREL-47] + _ = x[R_ADDRPOWER_TOCREL-48] + _ = x[R_ADDRPOWER_TOCREL_DS-49] + _ = x[R_RISCV_CALL-50] + _ = x[R_RISCV_CALL_TRAMP-51] + _ = x[R_RISCV_PCREL_ITYPE-52] + _ = x[R_RISCV_PCREL_STYPE-53] + _ = x[R_RISCV_TLS_IE_ITYPE-54] + _ = x[R_RISCV_TLS_IE_STYPE-55] + _ = x[R_PCRELDBL-56] + _ = x[R_ADDRMIPSU-57] + _ = x[R_ADDRMIPSTLS-58] + _ = x[R_ADDRCUOFF-59] + _ = x[R_WASMIMPORT-60] + _ = x[R_XCOFFREF-61] } -const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CALLRISCVR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_METHODOFFR_KEEPR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IE_ITYPER_RISCV_TLS_IE_STYPER_PCRELDBLR_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREF" +const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_METHODOFFR_KEEPR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_RISCV_CALLR_RISCV_CALL_TRAMPR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IE_ITYPER_RISCV_TLS_IE_STYPER_PCRELDBLR_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREF" -var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 53, 59, 68, 79, 88, 99, 109, 120, 127, 134, 142, 150, 158, 164, 170, 176, 186, 195, 205, 221, 232, 238, 249, 259, 268, 281, 295, 309, 323, 339, 350, 363, 376, 390, 404, 418, 433, 447, 461, 472, 486, 501, 518, 536, 557, 576, 595, 615, 635, 645, 656, 669, 680, 692, 702} +var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 53, 59, 68, 79, 88, 99, 109, 116, 123, 131, 139, 147, 153, 159, 165, 175, 184, 194, 210, 221, 227, 238, 248, 257, 270, 284, 298, 312, 328, 339, 352, 365, 379, 393, 407, 422, 436, 450, 461, 475, 490, 507, 525, 546, 558, 576, 595, 614, 634, 654, 664, 675, 688, 699, 711, 721} func (i RelocType) String() string { i -= 1 diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 21169f66ef..8de0e0df1a 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -92,10 +92,10 @@ func maxSizeTrampolines(ctxt *Link, ldr *loader.Loader, s loader.Sym, isTramp bo panic("unreachable") } -// detect too-far jumps in function s, and add trampolines if necessary -// ARM, PPC64 & PPC64LE support trampoline insertion for internal and external linking -// On PPC64 & PPC64LE the text sections might be split but will still insert trampolines -// where necessary. +// Detect too-far jumps in function s, and add trampolines if necessary. +// ARM, PPC64, PPC64LE and RISCV64 support trampoline insertion for internal +// and external linking. On PPC64 and PPC64LE the text sections might be split +// but will still insert trampolines where necessary. func trampoline(ctxt *Link, s loader.Sym) { if thearch.Trampoline == nil { return // no need or no support of trampolines on this arch @@ -113,7 +113,11 @@ func trampoline(ctxt *Link, s loader.Sym) { if !ldr.AttrReachable(rs) || ldr.SymType(rs) == sym.Sxxx { continue // something is wrong. skip it here and we'll emit a better error later } - if ldr.SymValue(rs) == 0 && (ldr.SymType(rs) != sym.SDYNIMPORT && ldr.SymType(rs) != sym.SUNDEFEXT) { + + // RISC-V is only able to reach +/-1MiB via a JAL instruction, + // which we can readily exceed in the same package. As such, we + // need to generate trampolines when the address is unknown. + if ldr.SymValue(rs) == 0 && !ctxt.Target.IsRISCV64() && ldr.SymType(rs) != sym.SDYNIMPORT && ldr.SymType(rs) != sym.SUNDEFEXT { if ldr.SymPkg(s) != "" && ldr.SymPkg(rs) == ldr.SymPkg(s) { // Symbols in the same package are laid out together. // Except that if SymPkg(s) == "", it is a host object symbol @@ -124,7 +128,6 @@ func trampoline(ctxt *Link, s loader.Sym) { continue // runtime packages are laid out together } } - thearch.Trampoline(ctxt, ldr, ri, rs, s) } } diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index 5f4724970c..39dd4b916e 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -143,13 +143,8 @@ func computeDeferReturn(ctxt *Link, deferReturnSym, s loader.Sym) uint32 { switch target.Arch.Family { case sys.AMD64, sys.I386: deferreturn-- - case sys.PPC64, sys.ARM, sys.ARM64, sys.MIPS, sys.MIPS64: + case sys.ARM, sys.ARM64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64: // no change - case sys.RISCV64: - // TODO(jsing): The JALR instruction is marked with - // R_CALLRISCV, whereas the actual reloc is currently - // one instruction earlier starting with the AUIPC. - deferreturn -= 4 case sys.S390X: deferreturn -= 2 default: diff --git a/src/cmd/link/internal/riscv64/asm.go b/src/cmd/link/internal/riscv64/asm.go index ef941e52e9..cb53a605d7 100644 --- a/src/cmd/link/internal/riscv64/asm.go +++ b/src/cmd/link/internal/riscv64/asm.go @@ -96,10 +96,10 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, } out.Write64(uint64(r.Xadd)) - case objabi.R_CALLRISCV: - // Call relocations are currently handled via R_RISCV_PCREL_ITYPE. - // TODO(jsing): Consider generating elf.R_RISCV_CALL instead of a - // HI20/LO12_I pair. + case objabi.R_RISCV_CALL, objabi.R_RISCV_CALL_TRAMP: + out.Write64(uint64(sectoff)) + out.Write64(uint64(elf.R_RISCV_JAL) | uint64(elfsym)<<32) + out.Write64(uint64(r.Xadd)) case objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE_ITYPE, objabi.R_RISCV_TLS_IE_STYPE: // Find the text symbol for the AUIPC instruction targeted @@ -156,10 +156,38 @@ func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtRe } func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) (o int64, nExtReloc int, ok bool) { + rs := r.Sym() + pc := ldr.SymValue(s) + int64(r.Off()) + + // If the call points to a trampoline, see if we can reach the symbol + // directly. This situation can occur when the relocation symbol is + // not assigned an address until after the trampolines are generated. + if r.Type() == objabi.R_RISCV_CALL_TRAMP { + relocs := ldr.Relocs(rs) + if relocs.Count() != 1 { + ldr.Errorf(s, "trampoline %v has %d relocations", ldr.SymName(rs), relocs.Count()) + } + tr := relocs.At(0) + if tr.Type() != objabi.R_RISCV_PCREL_ITYPE { + ldr.Errorf(s, "trampoline %v has unexpected relocation %v", ldr.SymName(rs), tr.Type()) + } + trs := tr.Sym() + if ldr.SymValue(trs) != 0 && ldr.SymType(trs) != sym.SDYNIMPORT && ldr.SymType(trs) != sym.SUNDEFEXT { + trsOff := ldr.SymValue(trs) + tr.Add() - pc + if trsOff >= -(1<<20) && trsOff < (1<<20) { + r.SetType(objabi.R_RISCV_CALL) + r.SetSym(trs) + r.SetAdd(tr.Add()) + rs = trs + } + } + + } + if target.IsExternal() { switch r.Type() { - case objabi.R_CALLRISCV: - return val, 0, true + case objabi.R_RISCV_CALL, objabi.R_RISCV_CALL_TRAMP: + return val, 1, true case objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE_ITYPE, objabi.R_RISCV_TLS_IE_STYPE: return val, 2, true @@ -168,11 +196,19 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade return val, 0, false } - rs := r.Sym() + off := ldr.SymValue(rs) + r.Add() - pc switch r.Type() { - case objabi.R_CALLRISCV: - // Nothing to do. + case objabi.R_RISCV_CALL, objabi.R_RISCV_CALL_TRAMP: + // Generate instruction immediates. + imm, err := riscv.EncodeJImmediate(off) + if err != nil { + ldr.Errorf(s, "cannot encode R_RISCV_CALL relocation offset for %s: %v", ldr.SymName(rs), err) + } + immMask := int64(riscv.JTypeImmMask) + + val = (val &^ immMask) | int64(imm) + return val, 0, true case objabi.R_RISCV_TLS_IE_ITYPE, objabi.R_RISCV_TLS_IE_STYPE: @@ -186,9 +222,6 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade return ebreakIns<<32 | ebreakIns, 0, true case objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE: - pc := ldr.SymValue(s) + int64(r.Off()) - off := ldr.SymValue(rs) + r.Add() - pc - // Generate AUIPC and second instruction immediates. low, high, err := riscv.Split32BitImmediate(off) if err != nil { @@ -237,8 +270,92 @@ func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc, sym.RelocVariant func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) { switch r.Type() { + case objabi.R_RISCV_CALL, objabi.R_RISCV_CALL_TRAMP: + return ld.ExtrelocSimple(ldr, r), true + case objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE_ITYPE, objabi.R_RISCV_TLS_IE_STYPE: return ld.ExtrelocViaOuterSym(ldr, r, s), true } return loader.ExtReloc{}, false } + +func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) { + relocs := ldr.Relocs(s) + r := relocs.At(ri) + + switch r.Type() { + case objabi.R_RISCV_CALL: + pc := ldr.SymValue(s) + int64(r.Off()) + off := ldr.SymValue(rs) + r.Add() - pc + + // Relocation symbol has an address and is directly reachable, + // therefore there is no need for a trampoline. + if ldr.SymValue(rs) != 0 && off >= -(1<<20) && off < (1<<20) && (*ld.FlagDebugTramp <= 1 || ldr.SymPkg(s) == ldr.SymPkg(rs)) { + break + } + + // Relocation symbol is too far for a direct call or has not + // yet been given an address. See if an existing trampoline is + // reachable and if so, reuse it. Otherwise we need to create + // a new trampoline. + var tramp loader.Sym + for i := 0; ; i++ { + oName := ldr.SymName(rs) + name := fmt.Sprintf("%s-tramp%d", oName, i) + if r.Add() != 0 { + name = fmt.Sprintf("%s%+x-tramp%d", oName, r.Add(), i) + } + tramp = ldr.LookupOrCreateSym(name, int(ldr.SymVersion(rs))) + ldr.SetAttrReachable(tramp, true) + if ldr.SymType(tramp) == sym.SDYNIMPORT { + // Do not reuse trampoline defined in other module. + continue + } + if oName == "runtime.deferreturn" { + ldr.SetIsDeferReturnTramp(tramp, true) + } + if ldr.SymValue(tramp) == 0 { + // Either trampoline does not exist or we found one + // that does not have an address assigned and will be + // laid down immediately after the current function. + break + } + + trampOff := ldr.SymValue(tramp) - (ldr.SymValue(s) + int64(r.Off())) + if trampOff >= -(1<<20) && trampOff < (1<<20) { + // An existing trampoline that is reachable. + break + } + } + if ldr.SymType(tramp) == 0 { + trampb := ldr.MakeSymbolUpdater(tramp) + ctxt.AddTramp(trampb) + genCallTramp(ctxt.Arch, ctxt.LinkMode, ldr, trampb, rs, int64(r.Add())) + } + sb := ldr.MakeSymbolUpdater(s) + if ldr.SymValue(rs) == 0 { + // In this case the target symbol has not yet been assigned an + // address, so we have to assume a trampoline is required. Mark + // this as a call via a trampoline so that we can potentially + // switch to a direct call during relocation. + sb.SetRelocType(ri, objabi.R_RISCV_CALL_TRAMP) + } + relocs := sb.Relocs() + r := relocs.At(ri) + r.SetSym(tramp) + r.SetAdd(0) + + default: + ctxt.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type(), sym.RelocName(ctxt.Arch, r.Type())) + } +} + +func genCallTramp(arch *sys.Arch, linkmode ld.LinkMode, ldr *loader.Loader, tramp *loader.SymbolBuilder, target loader.Sym, offset int64) { + tramp.AddUint32(arch, 0x00000f97) // AUIPC $0, X31 + tramp.AddUint32(arch, 0x000f8067) // JALR X0, (X31) + + r, _ := tramp.AddRel(objabi.R_RISCV_PCREL_ITYPE) + r.SetSiz(8) + r.SetSym(target) + r.SetAdd(offset) +} diff --git a/src/cmd/link/internal/riscv64/obj.go b/src/cmd/link/internal/riscv64/obj.go index 917324d922..557e8932c9 100644 --- a/src/cmd/link/internal/riscv64/obj.go +++ b/src/cmd/link/internal/riscv64/obj.go @@ -27,9 +27,17 @@ func Init() (*sys.Arch, ld.Arch) { Elfreloc1: elfreloc1, ElfrelocSize: 24, Elfsetupplt: elfsetupplt, - Gentext: gentext, - GenSymsLate: genSymsLate, - Machoreloc1: machoreloc1, + + // TrampLimit is set such that we always run the trampoline + // generation code. This is necessary since calls to external + // symbols require the use of trampolines, regardless of the + // text size. + TrampLimit: 1, + Trampoline: trampoline, + + Gentext: gentext, + GenSymsLate: genSymsLate, + Machoreloc1: machoreloc1, Linuxdynld: "/lib/ld.so.1", -- GitLab From 94323206aee1363471a4ae3b8d40dd4ae7a5cd9c Mon Sep 17 00:00:00 2001 From: Lynn Boger Date: Mon, 4 Oct 2021 08:00:20 -0500 Subject: [PATCH 1419/2500] cmd/compile: fix PPC64.rules to correct failure in issue45344.go with regabi This changes a rule in PPC64.rules to fix a failure in test/issue45344.go when regabi is enabled. Change-Id: I98baf2ae92c766b7276b0f3167b2e6fef37dfe84 Reviewed-on: https://go-review.googlesource.com/c/go/+/353789 Run-TryBot: Lynn Boger Reviewed-by: Cherry Mui Trust: Lynn Boger --- src/cmd/compile/internal/ssa/gen/PPC64.rules | 2 +- src/cmd/compile/internal/ssa/rewritePPC64.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/ssa/gen/PPC64.rules b/src/cmd/compile/internal/ssa/gen/PPC64.rules index 4b11e81fa2..0393feb125 100644 --- a/src/cmd/compile/internal/ssa/gen/PPC64.rules +++ b/src/cmd/compile/internal/ssa/gen/PPC64.rules @@ -580,7 +580,7 @@ (Store {t} ptr val mem) && t.Size() == 8 && is64BitFloat(val.Type) => (FMOVDstore ptr val mem) (Store {t} ptr val mem) && t.Size() == 8 && is32BitFloat(val.Type) => (FMOVDstore ptr val mem) // glitch from (Cvt32Fto64F x) => x -- type is wrong (Store {t} ptr val mem) && t.Size() == 4 && is32BitFloat(val.Type) => (FMOVSstore ptr val mem) -(Store {t} ptr val mem) && t.Size() == 8 && (is64BitInt(val.Type) || isPtr(val.Type)) => (MOVDstore ptr val mem) +(Store {t} ptr val mem) && t.Size() == 8 && !is64BitFloat(val.Type) => (MOVDstore ptr val mem) (Store {t} ptr val mem) && t.Size() == 4 && is32BitInt(val.Type) => (MOVWstore ptr val mem) (Store {t} ptr val mem) && t.Size() == 2 => (MOVHstore ptr val mem) (Store {t} ptr val mem) && t.Size() == 1 => (MOVBstore ptr val mem) diff --git a/src/cmd/compile/internal/ssa/rewritePPC64.go b/src/cmd/compile/internal/ssa/rewritePPC64.go index 6127fd262b..450ea861f3 100644 --- a/src/cmd/compile/internal/ssa/rewritePPC64.go +++ b/src/cmd/compile/internal/ssa/rewritePPC64.go @@ -16583,14 +16583,14 @@ func rewriteValuePPC64_OpStore(v *Value) bool { return true } // match: (Store {t} ptr val mem) - // cond: t.Size() == 8 && (is64BitInt(val.Type) || isPtr(val.Type)) + // cond: t.Size() == 8 && !is64BitFloat(val.Type) // result: (MOVDstore ptr val mem) for { t := auxToType(v.Aux) ptr := v_0 val := v_1 mem := v_2 - if !(t.Size() == 8 && (is64BitInt(val.Type) || isPtr(val.Type))) { + if !(t.Size() == 8 && !is64BitFloat(val.Type)) { break } v.reset(OpPPC64MOVDstore) -- GitLab From cc5e3de593afca73cf1b4d732ddceffb2837b390 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Sat, 8 May 2021 01:07:30 -0400 Subject: [PATCH 1420/2500] crypto/tls: use cryptobyte.NewFixedBuilder Change-Id: Ia2a9465680e766336dae34f5d2b3cb412185bf1f Reviewed-on: https://go-review.googlesource.com/c/go/+/318131 Trust: Filippo Valsorda Run-TryBot: Filippo Valsorda TryBot-Result: Go Bot Reviewed-by: Roland Shoemaker --- src/crypto/tls/handshake_messages.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/crypto/tls/handshake_messages.go b/src/crypto/tls/handshake_messages.go index b5f81e4436..17cf85910f 100644 --- a/src/crypto/tls/handshake_messages.go +++ b/src/crypto/tls/handshake_messages.go @@ -329,8 +329,7 @@ func (m *clientHelloMsg) updateBinders(pskBinders [][]byte) { m.pskBinders = pskBinders if m.raw != nil { lenWithoutBinders := len(m.marshalWithoutBinders()) - // TODO(filippo): replace with NewFixedBuilder once CL 148882 is imported. - b := cryptobyte.NewBuilder(m.raw[:lenWithoutBinders]) + b := cryptobyte.NewFixedBuilder(m.raw[:lenWithoutBinders]) b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { for _, binder := range m.pskBinders { b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { @@ -338,7 +337,7 @@ func (m *clientHelloMsg) updateBinders(pskBinders [][]byte) { }) } }) - if len(b.BytesOrPanic()) != len(m.raw) { + if out, err := b.Bytes(); err != nil || len(out) != len(m.raw) { panic("tls: internal error: failed to update binders") } } -- GitLab From 9f8d558c3b28def1b188e60e1b3b8361a461c9e2 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Fri, 1 Oct 2021 14:22:34 -0400 Subject: [PATCH 1421/2500] go/types: remove 1.18 APIs that have been replaced Remove the Interface.IsConstraint, Signature.SetTypeParams, and Signature.SetRecvTypeParams methods, as they have been replaced and usage removed from x/tools. Change-Id: I8786c3cf34e96ab5211cd8e7e6348e9ee792b843 Reviewed-on: https://go-review.googlesource.com/c/go/+/353570 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/call.go | 2 +- src/go/types/decl.go | 2 +- src/go/types/interface.go | 7 +------ src/go/types/signature.go | 6 ------ src/go/types/typeset.go | 4 ++-- src/go/types/typexpr.go | 2 +- 6 files changed, 6 insertions(+), 17 deletions(-) diff --git a/src/go/types/call.go b/src/go/types/call.go index 2fa29dd439..98a8fda9d1 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -112,7 +112,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { break } if t := asInterface(T); t != nil { - if t.IsConstraint() { + if !t.IsMethodSet() { check.errorf(call, _Todo, "cannot use interface %s in conversion (contains type list or is comparable)", T) break } diff --git a/src/go/types/decl.go b/src/go/types/decl.go index d0809f5a6e..3c68bbfb20 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -586,7 +586,7 @@ func (check *Checker) isImportedConstraint(typ Type) bool { return false } u, _ := named.under().(*Interface) - return u != nil && u.IsConstraint() + return u != nil && !u.IsMethodSet() } func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { diff --git a/src/go/types/interface.go b/src/go/types/interface.go index ccea1f6dcc..866a3427ca 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -106,12 +106,7 @@ func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() } // IsMethodSet reports whether the interface t is fully described by its method // set. -func (t *Interface) IsMethodSet() bool { return !t.typeSet().IsConstraint() } - -// IsConstraint reports whether interface t is not just a method set. -// -// TODO(rfindley): remove this method. -func (t *Interface) IsConstraint() bool { return t.typeSet().IsConstraint() } +func (t *Interface) IsMethodSet() bool { return t.typeSet().IsMethodSet() } // Complete computes the interface's type set. It must be called by users of // NewInterfaceType and NewInterface after the interface's embedded types are diff --git a/src/go/types/signature.go b/src/go/types/signature.go index c26437afe4..9bb6ec2f4f 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -82,15 +82,9 @@ func (s *Signature) Recv() *Var { return s.recv } // TypeParams returns the type parameters of signature s, or nil. func (s *Signature) TypeParams() *TypeParamList { return s.tparams } -// SetTypeParams sets the type parameters of signature s. -func (s *Signature) SetTypeParams(tparams []*TypeParam) { s.tparams = bindTParams(tparams) } - // RecvTypeParams returns the receiver type parameters of signature s, or nil. func (s *Signature) RecvTypeParams() *TypeParamList { return s.rparams } -// SetRecvTypeParams sets the receiver type params of signature s. -func (s *Signature) SetRecvTypeParams(rparams []*TypeParam) { s.rparams = bindTParams(rparams) } - // Params returns the parameters of signature s, or nil. func (s *Signature) Params() *Tuple { return s.params } diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index 3e59155e5c..b447799862 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -28,8 +28,8 @@ func (s *_TypeSet) IsEmpty() bool { return s.terms.isEmpty() } // IsAll reports whether type set s is the set of all types (corresponding to the empty interface). func (s *_TypeSet) IsAll() bool { return !s.comparable && len(s.methods) == 0 && s.terms.isAll() } -// IsConstraint reports whether type set s is not just a set of methods. -func (s *_TypeSet) IsConstraint() bool { return s.comparable || !s.terms.isAll() } +// IsMethodSet reports whether the interface t is fully described by its method set. +func (s *_TypeSet) IsMethodSet() bool { return !s.comparable && s.terms.isAll() } // IsComparable reports whether each type in the set is comparable. func (s *_TypeSet) IsComparable() bool { diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 505c639444..c4e4bc3dfe 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -139,7 +139,7 @@ func (check *Checker) varType(e ast.Expr) Type { check.later(func() { if t := asInterface(typ); t != nil { tset := computeInterfaceTypeSet(check, e.Pos(), t) // TODO(gri) is this the correct position? - if tset.IsConstraint() { + if !tset.IsMethodSet() { if tset.comparable { check.softErrorf(e, _Todo, "interface is (or embeds) comparable") } else { -- GitLab From 7d822af4500831d131562f17dcf53374469d823e Mon Sep 17 00:00:00 2001 From: siddharth Date: Mon, 28 Jun 2021 19:36:53 -0400 Subject: [PATCH 1422/2500] cmd/go/internal/cfg: improve error message when GOPATH is unset Add GoPathError variable. This variable gets set when GOPATH is not set in the environment and in build.Default.GOPATH. GoPathError may be used in "GOPATH unset" error messages to explain why GOPATH is not set. This CL improves upon CL 158257. Fixes #29341 Change-Id: Ib42b42fb442c8297d58da4ca556be55e21a034e1 Reviewed-on: https://go-review.googlesource.com/c/go/+/331529 Reviewed-by: Bryan C. Mills Reviewed-by: Jay Conrod Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Trust: Jay Conrod Trust: Michael Knyszek --- src/cmd/go/internal/cfg/cfg.go | 27 ++++++++++++++++++++++++++- src/cmd/go/internal/modfetch/sumdb.go | 6 ++++-- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go index b9632ea3c9..c8747d6c11 100644 --- a/src/cmd/go/internal/cfg/cfg.go +++ b/src/cmd/go/internal/cfg/cfg.go @@ -56,6 +56,10 @@ var ( DebugActiongraph string // -debug-actiongraph flag (undocumented, unstable) DebugTrace string // -debug-trace flag + + // GoPathError is set when GOPATH is not set. it contains an + // explanation why GOPATH is unset. + GoPathError string ) func defaultContext() build.Context { @@ -73,7 +77,7 @@ func defaultContext() build.Context { build.ToolDir = filepath.Join(ctxt.GOROOT, "pkg/tool/"+runtime.GOOS+"_"+runtime.GOARCH) } - ctxt.GOPATH = envOr("GOPATH", ctxt.GOPATH) + ctxt.GOPATH = envOr("GOPATH", gopath(ctxt)) // Override defaults computed in go/build with defaults // from go environment configuration file, if known. @@ -402,3 +406,24 @@ func gopathDir(rel string) string { } return filepath.Join(list[0], rel) } + +func gopath(ctxt build.Context) string { + if len(ctxt.GOPATH) > 0 { + return ctxt.GOPATH + } + env := "HOME" + if runtime.GOOS == "windows" { + env = "USERPROFILE" + } else if runtime.GOOS == "plan9" { + env = "home" + } + if home := os.Getenv(env); home != "" { + def := filepath.Join(home, "go") + if filepath.Clean(def) == filepath.Clean(runtime.GOROOT()) { + GoPathError = "cannot set GOROOT as GOPATH" + } + return "" + } + GoPathError = fmt.Sprintf("%s is not set", env) + return "" +} diff --git a/src/cmd/go/internal/modfetch/sumdb.go b/src/cmd/go/internal/modfetch/sumdb.go index f233cba6df..79961b4324 100644 --- a/src/cmd/go/internal/modfetch/sumdb.go +++ b/src/cmd/go/internal/modfetch/sumdb.go @@ -201,7 +201,8 @@ func (c *dbClient) ReadConfig(file string) (data []byte, err error) { } if cfg.SumdbDir == "" { - return nil, errors.New("could not locate sumdb file: missing $GOPATH") + return nil, fmt.Errorf("could not locate sumdb file: missing $GOPATH: %s", + cfg.GoPathError) } targ := filepath.Join(cfg.SumdbDir, file) data, err = lockedfile.Read(targ) @@ -220,7 +221,8 @@ func (*dbClient) WriteConfig(file string, old, new []byte) error { return fmt.Errorf("cannot write key") } if cfg.SumdbDir == "" { - return errors.New("could not locate sumdb file: missing $GOPATH") + return fmt.Errorf("could not locate sumdb file: missing $GOPATH: %s", + cfg.GoPathError) } targ := filepath.Join(cfg.SumdbDir, file) os.MkdirAll(filepath.Dir(targ), 0777) -- GitLab From 579ff8b1313479b795e3b536f7b9444094060b32 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 4 Oct 2021 12:14:10 -0700 Subject: [PATCH 1423/2500] cmd/go,cmd/compile: re-enable concurrent compilation on darwin/arm64 I've manually reviewed all uses of ctxt.Flag_shared for concurrency safety. And I manually tested with the race detector and found no issues. Allow -shared to be used with compiler concurrency, thereby re-enabling concurrent compilation on darwin/arm64. Fixes #48496 Change-Id: I8a084cb08e6050950e404ceb9bd7e3a20e07e9c5 Reviewed-on: https://go-review.googlesource.com/c/go/+/353871 Trust: Josh Bleecher Snyder Reviewed-by: Bryan C. Mills --- src/cmd/compile/internal/base/flag.go | 2 +- src/cmd/go/internal/work/gc.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/base/flag.go b/src/cmd/compile/internal/base/flag.go index 942659bcc0..241f5da185 100644 --- a/src/cmd/compile/internal/base/flag.go +++ b/src/cmd/compile/internal/base/flag.go @@ -357,7 +357,7 @@ func concurrentBackendAllowed() bool { return false } // TODO: fix races and enable the following flags - if Ctxt.Flag_shared || Ctxt.Flag_dynlink || Flag.Race { + if Ctxt.Flag_dynlink || Flag.Race { return false } return true diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go index 414736cbd7..85f661bf31 100644 --- a/src/cmd/go/internal/work/gc.go +++ b/src/cmd/go/internal/work/gc.go @@ -234,7 +234,7 @@ CheckFlags: // except for known commonly used flags. // If the user knows better, they can manually add their own -c to the gcflags. switch flag { - case "-N", "-l", "-S", "-B", "-C", "-I": + case "-N", "-l", "-S", "-B", "-C", "-I", "-shared": // OK default: canDashC = false -- GitLab From 2dc91a25f619c49b5d64af1b92497705a3325951 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 30 Sep 2021 13:26:19 -0400 Subject: [PATCH 1424/2500] cmd/api: set architecture sizes when type checking Otherwise the type checker defaults to amd64, which can break type-checking for definitions using unsafe.Sizeof. This has the side effect of changing the API output: constants with different values across architectures (e.g., MaxInt) are now individually listed per-arch. This actually makes the API file more accurate, but does introduce a one-time discontinuity. These changes have been integrated into the API files where the constants were added. Change-Id: I4bbb0b7a7f405d3adda2d83869475c8bacdeb6a9 Reviewed-on: https://go-review.googlesource.com/c/go/+/353331 Trust: Michael Pratt Run-TryBot: Michael Pratt TryBot-Result: Go Bot Reviewed-by: Dmitri Shuralyov Reviewed-by: Robert Findley Reviewed-by: Alexander Rakoczy --- api/go1.1.txt | 31 +++++++++++++++- api/go1.17.txt | 87 ++++++++++++++++++++++++++++++++++++++++++-- api/go1.9.txt | 29 ++++++++++++++- src/cmd/api/goapi.go | 5 +++ 4 files changed, 146 insertions(+), 6 deletions(-) diff --git a/api/go1.1.txt b/api/go1.1.txt index 81d095704a..bb00b3b02c 100644 --- a/api/go1.1.txt +++ b/api/go1.1.txt @@ -2603,7 +2603,34 @@ pkg runtime/debug, type GCStats struct, Pause []time.Duration pkg runtime/debug, type GCStats struct, PauseQuantiles []time.Duration pkg runtime/debug, type GCStats struct, PauseTotal time.Duration pkg sort, func Reverse(Interface) Interface -pkg strconv, const IntSize = 64 +pkg strconv (darwin-amd64), const IntSize = 64 +pkg strconv (darwin-amd64-cgo), const IntSize = 64 +pkg strconv (freebsd-386), const IntSize = 32 +pkg strconv (freebsd-386-cgo), const IntSize = 32 +pkg strconv (freebsd-amd64), const IntSize = 64 +pkg strconv (freebsd-amd64-cgo), const IntSize = 64 +pkg strconv (freebsd-arm), const IntSize = 32 +pkg strconv (freebsd-arm-cgo), const IntSize = 32 +pkg strconv (linux-386), const IntSize = 32 +pkg strconv (linux-386-cgo), const IntSize = 32 +pkg strconv (linux-amd64), const IntSize = 64 +pkg strconv (linux-amd64-cgo), const IntSize = 64 +pkg strconv (linux-arm), const IntSize = 32 +pkg strconv (linux-arm-cgo), const IntSize = 32 +pkg strconv (netbsd-386), const IntSize = 32 +pkg strconv (netbsd-386-cgo), const IntSize = 32 +pkg strconv (netbsd-amd64), const IntSize = 64 +pkg strconv (netbsd-amd64-cgo), const IntSize = 64 +pkg strconv (netbsd-arm), const IntSize = 32 +pkg strconv (netbsd-arm-cgo), const IntSize = 32 +pkg strconv (netbsd-arm64), const IntSize = 64 +pkg strconv (netbsd-arm64-cgo), const IntSize = 64 +pkg strconv (openbsd-386), const IntSize = 32 +pkg strconv (openbsd-386-cgo), const IntSize = 32 +pkg strconv (openbsd-amd64), const IntSize = 64 +pkg strconv (openbsd-amd64-cgo), const IntSize = 64 +pkg strconv (windows-386), const IntSize = 32 +pkg strconv (windows-amd64), const IntSize = 64 pkg strings, func TrimPrefix(string, string) string pkg strings, func TrimSuffix(string, string) string pkg strings, method (*Reader) WriteTo(io.Writer) (int64, error) @@ -49366,7 +49393,7 @@ pkg syscall (windows-386), const IP_MULTICAST_TTL = 10 pkg syscall (windows-386), const IP_TOS = 3 pkg syscall (windows-386), const IP_TTL = 4 pkg syscall (windows-386), const ImplementsGetwd = true -pkg syscall (windows-386), const InvalidHandle = 18446744073709551615 +pkg syscall (windows-386), const InvalidHandle = 4294967295 pkg syscall (windows-386), const KEY_ALL_ACCESS = 983103 pkg syscall (windows-386), const KEY_CREATE_LINK = 32 pkg syscall (windows-386), const KEY_CREATE_SUB_KEY = 4 diff --git a/api/go1.17.txt b/api/go1.17.txt index 48505381f1..ca2cd162f8 100644 --- a/api/go1.17.txt +++ b/api/go1.17.txt @@ -63,12 +63,93 @@ pkg image/draw, type RGBA64Image interface, RGBA64At(int, int) color.RGBA64 pkg image/draw, type RGBA64Image interface, Set(int, int, color.Color) pkg image/draw, type RGBA64Image interface, SetRGBA64(int, int, color.RGBA64) pkg io/fs, func FileInfoToDirEntry(FileInfo) DirEntry +pkg math (darwin-amd64), const MaxInt = 9223372036854775807 +pkg math (darwin-amd64), const MaxUint = 18446744073709551615 +pkg math (darwin-amd64), const MinInt = -9223372036854775808 +pkg math (darwin-amd64-cgo), const MaxInt = 9223372036854775807 +pkg math (darwin-amd64-cgo), const MaxUint = 18446744073709551615 +pkg math (darwin-amd64-cgo), const MinInt = -9223372036854775808 +pkg math (freebsd-386), const MaxInt = 2147483647 +pkg math (freebsd-386), const MaxUint = 4294967295 +pkg math (freebsd-386), const MinInt = -2147483648 +pkg math (freebsd-386-cgo), const MaxInt = 2147483647 +pkg math (freebsd-386-cgo), const MaxUint = 4294967295 +pkg math (freebsd-386-cgo), const MinInt = -2147483648 +pkg math (freebsd-amd64), const MaxInt = 9223372036854775807 +pkg math (freebsd-amd64), const MaxUint = 18446744073709551615 +pkg math (freebsd-amd64), const MinInt = -9223372036854775808 +pkg math (freebsd-amd64-cgo), const MaxInt = 9223372036854775807 +pkg math (freebsd-amd64-cgo), const MaxUint = 18446744073709551615 +pkg math (freebsd-amd64-cgo), const MinInt = -9223372036854775808 +pkg math (freebsd-arm), const MaxInt = 2147483647 +pkg math (freebsd-arm), const MaxUint = 4294967295 +pkg math (freebsd-arm), const MinInt = -2147483648 +pkg math (freebsd-arm-cgo), const MaxInt = 2147483647 +pkg math (freebsd-arm-cgo), const MaxUint = 4294967295 +pkg math (freebsd-arm-cgo), const MinInt = -2147483648 +pkg math (linux-386), const MaxInt = 2147483647 +pkg math (linux-386), const MaxUint = 4294967295 +pkg math (linux-386), const MinInt = -2147483648 +pkg math (linux-386-cgo), const MaxInt = 2147483647 +pkg math (linux-386-cgo), const MaxUint = 4294967295 +pkg math (linux-386-cgo), const MinInt = -2147483648 +pkg math (linux-amd64), const MaxInt = 9223372036854775807 +pkg math (linux-amd64), const MaxUint = 18446744073709551615 +pkg math (linux-amd64), const MinInt = -9223372036854775808 +pkg math (linux-amd64-cgo), const MaxInt = 9223372036854775807 +pkg math (linux-amd64-cgo), const MaxUint = 18446744073709551615 +pkg math (linux-amd64-cgo), const MinInt = -9223372036854775808 +pkg math (linux-arm), const MaxInt = 2147483647 +pkg math (linux-arm), const MaxUint = 4294967295 +pkg math (linux-arm), const MinInt = -2147483648 +pkg math (linux-arm-cgo), const MaxInt = 2147483647 +pkg math (linux-arm-cgo), const MaxUint = 4294967295 +pkg math (linux-arm-cgo), const MinInt = -2147483648 +pkg math (netbsd-386), const MaxInt = 2147483647 +pkg math (netbsd-386), const MaxUint = 4294967295 +pkg math (netbsd-386), const MinInt = -2147483648 +pkg math (netbsd-386-cgo), const MaxInt = 2147483647 +pkg math (netbsd-386-cgo), const MaxUint = 4294967295 +pkg math (netbsd-386-cgo), const MinInt = -2147483648 +pkg math (netbsd-amd64), const MaxInt = 9223372036854775807 +pkg math (netbsd-amd64), const MaxUint = 18446744073709551615 +pkg math (netbsd-amd64), const MinInt = -9223372036854775808 +pkg math (netbsd-amd64-cgo), const MaxInt = 9223372036854775807 +pkg math (netbsd-amd64-cgo), const MaxUint = 18446744073709551615 +pkg math (netbsd-amd64-cgo), const MinInt = -9223372036854775808 +pkg math (netbsd-arm), const MaxInt = 2147483647 +pkg math (netbsd-arm), const MaxUint = 4294967295 +pkg math (netbsd-arm), const MinInt = -2147483648 +pkg math (netbsd-arm-cgo), const MaxInt = 2147483647 +pkg math (netbsd-arm-cgo), const MaxUint = 4294967295 +pkg math (netbsd-arm-cgo), const MinInt = -2147483648 +pkg math (netbsd-arm64), const MaxInt = 9223372036854775807 +pkg math (netbsd-arm64), const MaxUint = 18446744073709551615 +pkg math (netbsd-arm64), const MinInt = -9223372036854775808 +pkg math (netbsd-arm64-cgo), const MaxInt = 9223372036854775807 +pkg math (netbsd-arm64-cgo), const MaxUint = 18446744073709551615 +pkg math (netbsd-arm64-cgo), const MinInt = -9223372036854775808 +pkg math (openbsd-386), const MaxInt = 2147483647 +pkg math (openbsd-386), const MaxUint = 4294967295 +pkg math (openbsd-386), const MinInt = -2147483648 +pkg math (openbsd-386-cgo), const MaxInt = 2147483647 +pkg math (openbsd-386-cgo), const MaxUint = 4294967295 +pkg math (openbsd-386-cgo), const MinInt = -2147483648 +pkg math (openbsd-amd64), const MaxInt = 9223372036854775807 +pkg math (openbsd-amd64), const MaxUint = 18446744073709551615 +pkg math (openbsd-amd64), const MinInt = -9223372036854775808 +pkg math (openbsd-amd64-cgo), const MaxInt = 9223372036854775807 +pkg math (openbsd-amd64-cgo), const MaxUint = 18446744073709551615 +pkg math (openbsd-amd64-cgo), const MinInt = -9223372036854775808 +pkg math (windows-386), const MaxInt = 2147483647 +pkg math (windows-386), const MaxUint = 4294967295 +pkg math (windows-386), const MinInt = -2147483648 +pkg math (windows-amd64), const MaxInt = 9223372036854775807 +pkg math (windows-amd64), const MaxUint = 18446744073709551615 +pkg math (windows-amd64), const MinInt = -9223372036854775808 pkg math, const MaxFloat64 = 1.79769e+308 // 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368 -pkg math, const MaxInt = 9223372036854775807 pkg math, const MaxInt ideal-int -pkg math, const MaxUint = 18446744073709551615 pkg math, const MaxUint ideal-int -pkg math, const MinInt = -9223372036854775808 pkg math, const MinInt ideal-int pkg math, const SmallestNonzeroFloat32 = 1.4013e-45 // 1/713623846352979940529142984724747568191373312 pkg math, const SmallestNonzeroFloat64 = 4.94066e-324 // 1/202402253307310618352495346718917307049556649764142118356901358027430339567995346891960383701437124495187077864316811911389808737385793476867013399940738509921517424276566361364466907742093216341239767678472745068562007483424692698618103355649159556340810056512358769552333414615230502532186327508646006263307707741093494784 diff --git a/api/go1.9.txt b/api/go1.9.txt index c23a17ea1a..87fae57920 100644 --- a/api/go1.9.txt +++ b/api/go1.9.txt @@ -49,7 +49,34 @@ pkg image/png, type EncoderBufferPool interface, Put(*EncoderBuffer) pkg math/big, method (*Int) IsInt64() bool pkg math/big, method (*Int) IsUint64() bool pkg math/big, type Word uint -pkg math/bits, const UintSize = 64 +pkg math/bits (darwin-amd64), const UintSize = 64 +pkg math/bits (darwin-amd64-cgo), const UintSize = 64 +pkg math/bits (freebsd-386), const UintSize = 32 +pkg math/bits (freebsd-386-cgo), const UintSize = 32 +pkg math/bits (freebsd-amd64), const UintSize = 64 +pkg math/bits (freebsd-amd64-cgo), const UintSize = 64 +pkg math/bits (freebsd-arm), const UintSize = 32 +pkg math/bits (freebsd-arm-cgo), const UintSize = 32 +pkg math/bits (linux-386), const UintSize = 32 +pkg math/bits (linux-386-cgo), const UintSize = 32 +pkg math/bits (linux-amd64), const UintSize = 64 +pkg math/bits (linux-amd64-cgo), const UintSize = 64 +pkg math/bits (linux-arm), const UintSize = 32 +pkg math/bits (linux-arm-cgo), const UintSize = 32 +pkg math/bits (netbsd-386), const UintSize = 32 +pkg math/bits (netbsd-386-cgo), const UintSize = 32 +pkg math/bits (netbsd-amd64), const UintSize = 64 +pkg math/bits (netbsd-amd64-cgo), const UintSize = 64 +pkg math/bits (netbsd-arm), const UintSize = 32 +pkg math/bits (netbsd-arm-cgo), const UintSize = 32 +pkg math/bits (netbsd-arm64), const UintSize = 64 +pkg math/bits (netbsd-arm64-cgo), const UintSize = 64 +pkg math/bits (openbsd-386), const UintSize = 32 +pkg math/bits (openbsd-386-cgo), const UintSize = 32 +pkg math/bits (openbsd-amd64), const UintSize = 64 +pkg math/bits (openbsd-amd64-cgo), const UintSize = 64 +pkg math/bits (windows-386), const UintSize = 32 +pkg math/bits (windows-amd64), const UintSize = 64 pkg math/bits, const UintSize ideal-int pkg math/bits, func LeadingZeros(uint) int pkg math/bits, func LeadingZeros16(uint16) int diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go index b07a238d67..43c761a657 100644 --- a/src/cmd/api/goapi.go +++ b/src/cmd/api/goapi.go @@ -653,10 +653,15 @@ func (w *Walker) ImportFrom(fromPath, fromDir string, mode types.ImportMode) (*t } // Type-check package files. + var sizes types.Sizes + if w.context != nil { + sizes = types.SizesFor(w.context.Compiler, w.context.GOARCH) + } conf := types.Config{ IgnoreFuncBodies: true, FakeImportC: true, Importer: w, + Sizes: sizes, } pkg, err = conf.Check(name, fset, files, nil) if err != nil { -- GitLab From e8a85e90aca4adb472c66f8c42f6d4a41b8cca99 Mon Sep 17 00:00:00 2001 From: Amelia Downs Date: Thu, 30 Sep 2021 11:35:30 -0400 Subject: [PATCH 1425/2500] internal/fuzz: print size of interesting cache This change updates the log lines to clarify that the printed interesting count is only for newly discovered cache entries, and prints the total cache size. It only prints information about interesting entries when coverageEnabled is true. Fixes #48669 Change-Id: I2045afc204764c1842d323e8ae42016fb21b6fb7 Reviewed-on: https://go-review.googlesource.com/c/go/+/353172 Trust: Michael Knyszek Trust: Katie Hockman Reviewed-by: Katie Hockman Reviewed-by: Jay Conrod Run-TryBot: Katie Hockman TryBot-Result: Go Bot --- src/internal/fuzz/fuzz.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index a38036b9d2..87f5459afd 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -685,7 +685,12 @@ func (c *coordinator) logStats() { } } else { rate := float64(c.count) / time.Since(c.startTime).Seconds() // be more precise here - fmt.Fprintf(c.opts.Log, "fuzz: elapsed: %s, execs: %d (%.0f/sec), interesting: %d\n", c.elapsed(), c.count, rate, c.interestingCount) + if coverageEnabled { + interestingTotalCount := len(c.corpus.entries) - len(c.opts.Seed) + fmt.Fprintf(c.opts.Log, "fuzz: elapsed: %s, execs: %d (%.0f/sec), new interesting: %d (total: %d)\n", c.elapsed(), c.count, rate, c.interestingCount, interestingTotalCount) + } else { + fmt.Fprintf(c.opts.Log, "fuzz: elapsed: %s, execs: %d (%.0f/sec)", c.elapsed(), c.count, rate) + } } } -- GitLab From f0db7eae74ea235e9fbc2598252bfd46c1cc5510 Mon Sep 17 00:00:00 2001 From: Rhys Hiltner Date: Wed, 29 Sep 2021 17:35:27 -0700 Subject: [PATCH 1426/2500] runtime: add padding to Linux kernel structures Go exchanges siginfo and sigevent structures with the kernel. They contain unions, but Go's use is limited to the first few fields. Pad out the rest so the size Go sees is the same as what the Linux kernel sees. This is a follow-up to CL 342052 which added the sigevent struct without padding. It updates the siginfo struct as well so there are no bad examples in the defs_linux_*.go files. Change-Id: Id991d4a57826677dd7e6cc30ad113fa3b321cddf Reviewed-on: https://go-review.googlesource.com/c/go/+/353136 Run-TryBot: Rhys Hiltner TryBot-Result: Go Bot Reviewed-by: Michael Pratt Trust: Michael Knyszek --- src/runtime/defs_linux_386.go | 11 +++++++++++ src/runtime/defs_linux_amd64.go | 11 +++++++++++ src/runtime/defs_linux_arm.go | 11 +++++++++++ src/runtime/defs_linux_arm64.go | 11 +++++++++++ src/runtime/defs_linux_mips64x.go | 11 +++++++++++ src/runtime/defs_linux_mipsx.go | 11 +++++++++++ src/runtime/defs_linux_ppc64.go | 11 +++++++++++ src/runtime/defs_linux_ppc64le.go | 11 +++++++++++ src/runtime/defs_linux_riscv64.go | 11 +++++++++++ src/runtime/defs_linux_s390x.go | 11 +++++++++++ src/runtime/os_linux.go | 12 ++++++++++++ 11 files changed, 122 insertions(+) diff --git a/src/runtime/defs_linux_386.go b/src/runtime/defs_linux_386.go index d8b546cb4c..fd9b60c444 100644 --- a/src/runtime/defs_linux_386.go +++ b/src/runtime/defs_linux_386.go @@ -3,6 +3,8 @@ package runtime +import "internal/goarch" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -172,6 +174,11 @@ type siginfo struct { si_code int32 // below here is a union; si_addr is the only field we use si_addr uint32 + + // Pad struct to the max size in the kernel. Account for the 3 32-bit + // fields, the alignment to this architecture's pointer size, and the final + // pointer-length field. + _ [_si_max_size - (3*4 + (1-4/goarch.PtrSize)*4 + 1*goarch.PtrSize)]byte } type stackt struct { @@ -235,6 +242,10 @@ type sigevent struct { notify int32 // below here is a union; sigev_notify_thread_id is the only field we use sigev_notify_thread_id int32 + + // Pad struct to the max size in the kernel. Account for the pointer-length + // field and the 3 32-bit fields. + _ [_sigev_max_size - (1*goarch.PtrSize + 3*4)]byte } type epollevent struct { diff --git a/src/runtime/defs_linux_amd64.go b/src/runtime/defs_linux_amd64.go index 6afb67f77f..29dabe08dd 100644 --- a/src/runtime/defs_linux_amd64.go +++ b/src/runtime/defs_linux_amd64.go @@ -3,6 +3,8 @@ package runtime +import "internal/goarch" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -134,6 +136,11 @@ type siginfo struct { si_code int32 // below here is a union; si_addr is the only field we use si_addr uint64 + + // Pad struct to the max size in the kernel. Account for the 3 32-bit + // fields, the alignment to this architecture's pointer size, and the final + // pointer-length field. + _ [_si_max_size - (3*4 + (1-4/goarch.PtrSize)*4 + 1*goarch.PtrSize)]byte } type itimerspec struct { @@ -152,6 +159,10 @@ type sigevent struct { notify int32 // below here is a union; sigev_notify_thread_id is the only field we use sigev_notify_thread_id int32 + + // Pad struct to the max size in the kernel. Account for the pointer-length + // field and the 3 32-bit fields. + _ [_sigev_max_size - (1*goarch.PtrSize + 3*4)]byte } type epollevent struct { diff --git a/src/runtime/defs_linux_arm.go b/src/runtime/defs_linux_arm.go index ec24d76326..3ed6940647 100644 --- a/src/runtime/defs_linux_arm.go +++ b/src/runtime/defs_linux_arm.go @@ -4,6 +4,8 @@ package runtime +import "internal/goarch" + // Constants const ( _EINTR = 0x4 @@ -175,6 +177,10 @@ type sigevent struct { notify int32 // below here is a union; sigev_notify_thread_id is the only field we use sigev_notify_thread_id int32 + + // Pad struct to the max size in the kernel. Account for the pointer-length + // field and the 3 32-bit fields. + _ [_sigev_max_size - (1*goarch.PtrSize + 3*4)]byte } type siginfo struct { @@ -183,6 +189,11 @@ type siginfo struct { si_code int32 // below here is a union; si_addr is the only field we use si_addr uint32 + + // Pad struct to the max size in the kernel. Account for the 3 32-bit + // fields, the alignment to this architecture's pointer size, and the final + // pointer-length field. + _ [_si_max_size - (3*4 + (1-4/goarch.PtrSize)*4 + 1*goarch.PtrSize)]byte } type sigactiont struct { diff --git a/src/runtime/defs_linux_arm64.go b/src/runtime/defs_linux_arm64.go index f9f175004b..6a126c4a15 100644 --- a/src/runtime/defs_linux_arm64.go +++ b/src/runtime/defs_linux_arm64.go @@ -3,6 +3,8 @@ package runtime +import "internal/goarch" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -134,6 +136,11 @@ type siginfo struct { si_code int32 // below here is a union; si_addr is the only field we use si_addr uint64 + + // Pad struct to the max size in the kernel. Account for the 3 32-bit + // fields, the alignment to this architecture's pointer size, and the final + // pointer-length field. + _ [_si_max_size - (3*4 + (1-4/goarch.PtrSize)*4 + 1*goarch.PtrSize)]byte } type itimerspec struct { @@ -152,6 +159,10 @@ type sigevent struct { notify int32 // below here is a union; sigev_notify_thread_id is the only field we use sigev_notify_thread_id int32 + + // Pad struct to the max size in the kernel. Account for the pointer-length + // field and the 3 32-bit fields. + _ [_sigev_max_size - (1*goarch.PtrSize + 3*4)]byte } type epollevent struct { diff --git a/src/runtime/defs_linux_mips64x.go b/src/runtime/defs_linux_mips64x.go index 1743bbce41..34e803331c 100644 --- a/src/runtime/defs_linux_mips64x.go +++ b/src/runtime/defs_linux_mips64x.go @@ -8,6 +8,8 @@ package runtime +import "internal/goarch" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -143,6 +145,11 @@ type siginfo struct { __pad0 [1]int32 // below here is a union; si_addr is the only field we use si_addr uint64 + + // Pad struct to the max size in the kernel. Account for the 3 32-bit + // fields, the alignment to this architecture's pointer size, and the final + // pointer-length field. + _ [_si_max_size - (3*4 + (1-4/goarch.PtrSize)*4 + 1*goarch.PtrSize)]byte } type itimerspec struct { @@ -161,6 +168,10 @@ type sigevent struct { notify int32 // below here is a union; sigev_notify_thread_id is the only field we use sigev_notify_thread_id int32 + + // Pad struct to the max size in the kernel. Account for the pointer-length + // field and the 3 32-bit fields. + _ [_sigev_max_size - (1*goarch.PtrSize + 3*4)]byte } type epollevent struct { diff --git a/src/runtime/defs_linux_mipsx.go b/src/runtime/defs_linux_mipsx.go index e84d4979e1..7a7db7f181 100644 --- a/src/runtime/defs_linux_mipsx.go +++ b/src/runtime/defs_linux_mipsx.go @@ -8,6 +8,8 @@ package runtime +import "internal/goarch" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -137,6 +139,11 @@ type siginfo struct { si_errno int32 // below here is a union; si_addr is the only field we use si_addr uint32 + + // Pad struct to the max size in the kernel. Account for the 3 32-bit + // fields, the alignment to this architecture's pointer size, and the final + // pointer-length field. + _ [_si_max_size - (3*4 + (1-4/goarch.PtrSize)*4 + 1*goarch.PtrSize)]byte } type itimerspec struct { @@ -155,6 +162,10 @@ type sigevent struct { notify int32 // below here is a union; sigev_notify_thread_id is the only field we use sigev_notify_thread_id int32 + + // Pad struct to the max size in the kernel. Account for the pointer-length + // field and the 3 32-bit fields. + _ [_sigev_max_size - (1*goarch.PtrSize + 3*4)]byte } type epollevent struct { diff --git a/src/runtime/defs_linux_ppc64.go b/src/runtime/defs_linux_ppc64.go index e0775e2974..7971ca7058 100644 --- a/src/runtime/defs_linux_ppc64.go +++ b/src/runtime/defs_linux_ppc64.go @@ -3,6 +3,8 @@ package runtime +import "internal/goarch" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -135,6 +137,11 @@ type siginfo struct { si_code int32 // below here is a union; si_addr is the only field we use si_addr uint64 + + // Pad struct to the max size in the kernel. Account for the 3 32-bit + // fields, the alignment to this architecture's pointer size, and the final + // pointer-length field. + _ [_si_max_size - (3*4 + (1-4/goarch.PtrSize)*4 + 1*goarch.PtrSize)]byte } type itimerspec struct { @@ -153,6 +160,10 @@ type sigevent struct { notify int32 // below here is a union; sigev_notify_thread_id is the only field we use sigev_notify_thread_id int32 + + // Pad struct to the max size in the kernel. Account for the pointer-length + // field and the 3 32-bit fields. + _ [_sigev_max_size - (1*goarch.PtrSize + 3*4)]byte } type epollevent struct { diff --git a/src/runtime/defs_linux_ppc64le.go b/src/runtime/defs_linux_ppc64le.go index e0775e2974..7971ca7058 100644 --- a/src/runtime/defs_linux_ppc64le.go +++ b/src/runtime/defs_linux_ppc64le.go @@ -3,6 +3,8 @@ package runtime +import "internal/goarch" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -135,6 +137,11 @@ type siginfo struct { si_code int32 // below here is a union; si_addr is the only field we use si_addr uint64 + + // Pad struct to the max size in the kernel. Account for the 3 32-bit + // fields, the alignment to this architecture's pointer size, and the final + // pointer-length field. + _ [_si_max_size - (3*4 + (1-4/goarch.PtrSize)*4 + 1*goarch.PtrSize)]byte } type itimerspec struct { @@ -153,6 +160,10 @@ type sigevent struct { notify int32 // below here is a union; sigev_notify_thread_id is the only field we use sigev_notify_thread_id int32 + + // Pad struct to the max size in the kernel. Account for the pointer-length + // field and the 3 32-bit fields. + _ [_sigev_max_size - (1*goarch.PtrSize + 3*4)]byte } type epollevent struct { diff --git a/src/runtime/defs_linux_riscv64.go b/src/runtime/defs_linux_riscv64.go index 1052213a4c..92f4563dd5 100644 --- a/src/runtime/defs_linux_riscv64.go +++ b/src/runtime/defs_linux_riscv64.go @@ -4,6 +4,8 @@ package runtime +import "internal/goarch" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -132,6 +134,11 @@ type siginfo struct { si_code int32 // below here is a union; si_addr is the only field we use si_addr uint64 + + // Pad struct to the max size in the kernel. Account for the 3 32-bit + // fields, the alignment to this architecture's pointer size, and the final + // pointer-length field. + _ [_si_max_size - (3*4 + (1-4/goarch.PtrSize)*4 + 1*goarch.PtrSize)]byte } type itimerspec struct { @@ -150,6 +157,10 @@ type sigevent struct { notify int32 // below here is a union; sigev_notify_thread_id is the only field we use sigev_notify_thread_id int32 + + // Pad struct to the max size in the kernel. Account for the pointer-length + // field and the 3 32-bit fields. + _ [_sigev_max_size - (1*goarch.PtrSize + 3*4)]byte } type epollevent struct { diff --git a/src/runtime/defs_linux_s390x.go b/src/runtime/defs_linux_s390x.go index b072955d4a..8a56ef0b80 100644 --- a/src/runtime/defs_linux_s390x.go +++ b/src/runtime/defs_linux_s390x.go @@ -4,6 +4,8 @@ package runtime +import "internal/goarch" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -131,6 +133,11 @@ type siginfo struct { si_code int32 // below here is a union; si_addr is the only field we use si_addr uint64 + + // Pad struct to the max size in the kernel. Account for the 3 32-bit + // fields, the alignment to this architecture's pointer size, and the final + // pointer-length field. + _ [_si_max_size - (3*4 + (1-4/goarch.PtrSize)*4 + 1*goarch.PtrSize)]byte } type itimerspec struct { @@ -149,6 +156,10 @@ type sigevent struct { notify int32 // below here is a union; sigev_notify_thread_id is the only field we use sigev_notify_thread_id int32 + + // Pad struct to the max size in the kernel. Account for the pointer-length + // field and the 3 32-bit fields. + _ [_sigev_max_size - (1*goarch.PtrSize + 3*4)]byte } type epollevent struct { diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go index 06773c2193..d5a5ff763b 100644 --- a/src/runtime/os_linux.go +++ b/src/runtime/os_linux.go @@ -440,6 +440,18 @@ func pipe() (r, w int32, errno int32) func pipe2(flags int32) (r, w int32, errno int32) func setNonblock(fd int32) +const ( + _si_max_size = 128 + _sigev_max_size = 64 +) + +// Assert that the Go definitions of structures exchanged with the kernel are +// the same size as what the kernel defines. +var ( + _ [_si_max_size]struct{} = [unsafe.Sizeof(siginfo{})]struct{}{} + _ [_sigev_max_size]struct{} = [unsafe.Sizeof(sigevent{})]struct{}{} +) + //go:nosplit //go:nowritebarrierrec func setsig(i uint32, fn uintptr) { -- GitLab From d99f1de56e7d86389a373e36ed3325e1e5069c31 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 4 Oct 2021 14:17:50 -0400 Subject: [PATCH 1427/2500] go/types: update the recorded function type after inference This change preserves the observable invariant that for an *ast.CallExpr 'call', Info.Types[call.Fun] is the signature being called. Updates #47916 Change-Id: I3e97c712a7ee33a4f29e8cf4c18dc7c946b66cc9 Reviewed-on: https://go-review.googlesource.com/c/go/+/353831 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/api_test.go | 6 ++++-- src/go/types/call.go | 8 +++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index f1a820988f..9044449e5c 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -347,8 +347,10 @@ func TestTypesInfo(t *testing.T) { // parameterized functions {genericPkg + `p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[generic_p0.T₁ interface{}](generic_p0.T₁)`}, {genericPkg + `p1; func f[T any](T) {}; var _ = f[int]`, `f[int]`, `func(int)`}, - {genericPkg + `p2; func f[T any](T) {}; func _() { f(42) }`, `f`, `func[generic_p2.T₁ interface{}](generic_p2.T₁)`}, - {genericPkg + `p3; func f[T any](T) {}; func _() { f(42) }`, `f(42)`, `()`}, + {genericPkg + `p2; func f[T any](T) {}; func _() { f(42) }`, `f`, `func(int)`}, + {genericPkg + `p3; func f[T any](T) {}; func _() { f[int](42) }`, `f[int]`, `func(int)`}, + {genericPkg + `p4; func f[T any](T) {}; func _() { f[int](42) }`, `f`, `func[generic_p4.T₁ interface{}](generic_p4.T₁)`}, + {genericPkg + `p5; func f[T any](T) {}; func _() { f(42) }`, `f(42)`, `()`}, // type parameters {genericPkg + `t0; type t[] int; var _ t`, `t`, `generic_t0.t`}, // t[] is a syntax error that is ignored in this test in favor of t diff --git a/src/go/types/call.go b/src/go/types/call.go index 98a8fda9d1..a642f6f295 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -85,7 +85,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { } else { check.exprOrType(x, call.Fun, true) } - // x.typ map be generic + // x.typ may be generic switch x.mode { case invalid: @@ -177,8 +177,14 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { // evaluate arguments args, _ := check.exprList(call.Args, false) + isGeneric := sig.TypeParams().Len() > 0 sig = check.arguments(call, sig, targs, args) + if isGeneric && sig.TypeParams().Len() == 0 { + // Update the recorded type of call.Fun to its instantiated type. + check.recordTypeAndValue(call.Fun, value, sig, nil) + } + // determine result switch sig.results.Len() { case 0: -- GitLab From 739328c694d5e608faa66d17192f0a59f6e01d04 Mon Sep 17 00:00:00 2001 From: Ruslan Andreev Date: Fri, 11 Jun 2021 09:27:09 +0000 Subject: [PATCH 1428/2500] cmd/compile: intrinsify publicationBarrier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This CL intrinsify asm call for publicationBarrier on ARM64. As for x86 we may completly removes any instructions due to strong memory oredering, but decided to leave it as is for compiler barrier. Benchmarks Go1 ARM64: name old time/op new time/op delta BinaryTree17-8 3.38s ± 1% 3.36s ± 1% ~ (p=0.095 n=5+5) Fannkuch11-8 2.93s ± 0% 2.84s ± 0% -3.26% (p=0.008 n=5+5) FmtFprintfEmpty-8 54.2ns ± 1% 54.0ns ± 1% ~ (p=0.690 n=5+5) FmtFprintfString-8 111ns ± 0% 109ns ± 0% -1.48% (p=0.008 n=5+5) FmtFprintfInt-8 140ns ± 0% 138ns ± 0% -1.10% (p=0.000 n=4+5) FmtFprintfIntInt-8 168ns ± 0% 169ns ± 0% +0.66% (p=0.008 n=5+5) FmtFprintfPrefixedInt-8 206ns ± 1% 195ns ± 0% -5.12% (p=0.008 n=5+5) FmtFprintfFloat-8 270ns ± 0% 269ns ± 0% -0.20% (p=0.024 n=5+5) FmtManyArgs-8 721ns ± 0% 733ns ± 0% +1.69% (p=0.008 n=5+5) GobDecode-8 9.75ms ± 1% 9.28ms ± 3% -4.88% (p=0.008 n=5+5) GobEncode-8 6.38ms ± 1% 6.34ms ± 1% ~ (p=0.095 n=5+5) Gzip-8 255ms ± 0% 254ms ± 0% -0.44% (p=0.008 n=5+5) Gunzip-8 41.8ms ± 1% 40.8ms ± 0% -2.40% (p=0.008 n=5+5) HTTPClientServer-8 65.1µs ± 1% 65.1µs ± 1% ~ (p=0.690 n=5+5) JSONEncode-8 11.7ms ± 0% 11.7ms ± 1% ~ (p=0.841 n=5+5) JSONDecode-8 60.2ms ± 1% 60.0ms ± 0% ~ (p=0.841 n=5+5) Mandelbrot200-8 5.85ms ± 0% 5.86ms ± 0% +0.22% (p=0.016 n=4+5) GoParse-8 4.38ms ± 0% 4.35ms ± 0% -0.60% (p=0.008 n=5+5) RegexpMatchEasy0_32-8 87.1ns ± 2% 88.3ns ± 1% ~ (p=0.151 n=5+5) RegexpMatchEasy0_1K-8 306ns ± 0% 306ns ± 1% ~ (p=0.143 n=5+5) RegexpMatchEasy1_32-8 86.3ns ± 0% 84.8ns ± 0% -1.81% (p=0.008 n=5+5) RegexpMatchEasy1_1K-8 491ns ± 2% 487ns ± 1% ~ (p=0.548 n=5+5) RegexpMatchMedium_32-8 7.50ns ± 0% 7.49ns ± 1% ~ (p=0.817 n=5+5) RegexpMatchMedium_1K-8 40.3µs ± 1% 39.9µs ± 0% -1.02% (p=0.008 n=5+5) RegexpMatchHard_32-8 2.10µs ± 1% 2.10µs ± 1% ~ (p=0.548 n=5+5) RegexpMatchHard_1K-8 62.4µs ± 1% 62.5µs ± 2% ~ (p=0.690 n=5+5) Revcomp-8 504ms ± 1% 502ms ± 1% ~ (p=0.095 n=5+5) Template-8 86.8ms ± 1% 86.5ms ± 1% ~ (p=0.222 n=5+5) TimeParse-8 330ns ± 0% 327ns ± 0% -0.84% (p=0.008 n=5+5) TimeFormat-8 383ns ± 1% 392ns ± 1% +2.42% (p=0.008 n=5+5) [Geo mean] 54.3µs 53.9µs -0.67% name old speed new speed delta GobDecode-8 78.7MB/s ± 1% 82.8MB/s ± 4% +5.16% (p=0.008 n=5+5) GobEncode-8 120MB/s ± 1% 121MB/s ± 1% ~ (p=0.095 n=5+5) Gzip-8 76.2MB/s ± 0% 76.5MB/s ± 0% +0.44% (p=0.008 n=5+5) Gunzip-8 464MB/s ± 1% 475MB/s ± 0% +2.45% (p=0.008 n=5+5) JSONEncode-8 166MB/s ± 0% 166MB/s ± 1% ~ (p=0.841 n=5+5) JSONDecode-8 32.2MB/s ± 1% 32.3MB/s ± 0% ~ (p=0.714 n=5+5) GoParse-8 13.2MB/s ± 0% 13.3MB/s ± 0% +0.59% (p=0.008 n=5+5) RegexpMatchEasy0_32-8 368MB/s ± 2% 362MB/s ± 1% ~ (p=0.151 n=5+5) RegexpMatchEasy0_1K-8 3.34GB/s ± 0% 3.34GB/s ± 1% ~ (p=0.127 n=5+5) RegexpMatchEasy1_32-8 371MB/s ± 0% 378MB/s ± 0% +1.84% (p=0.008 n=5+5) RegexpMatchEasy1_1K-8 2.09GB/s ± 2% 2.10GB/s ± 1% ~ (p=0.548 n=5+5) RegexpMatchMedium_32-8 133MB/s ± 0% 134MB/s ± 1% ~ (p=0.952 n=5+5) RegexpMatchMedium_1K-8 25.4MB/s ± 1% 25.6MB/s ± 0% +1.04% (p=0.008 n=5+5) RegexpMatchHard_32-8 15.3MB/s ± 1% 15.2MB/s ± 1% ~ (p=0.500 n=5+5) RegexpMatchHard_1K-8 16.4MB/s ± 1% 16.4MB/s ± 2% ~ (p=0.595 n=5+5) Revcomp-8 504MB/s ± 1% 506MB/s ± 1% ~ (p=0.095 n=5+5) Template-8 22.4MB/s ± 1% 22.4MB/s ± 1% ~ (p=0.206 n=5+5) [Geo mean] 120MB/s 121MB/s +0.71% Change-Id: I9cc10840b5c0d6bf759150f052c79f4c499e35e1 Reviewed-on: https://go-review.googlesource.com/c/go/+/328290 Reviewed-by: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Trust: David Chase --- src/cmd/compile/internal/arm64/ssa.go | 4 ++++ src/cmd/compile/internal/ssa/gen/ARM64.rules | 3 +++ src/cmd/compile/internal/ssa/gen/ARM64Ops.go | 3 +++ src/cmd/compile/internal/ssa/gen/genericOps.go | 3 +++ src/cmd/compile/internal/ssa/opGen.go | 16 ++++++++++++++++ src/cmd/compile/internal/ssa/rewriteARM64.go | 14 ++++++++++++++ src/cmd/compile/internal/ssagen/ssa.go | 7 +++++++ 7 files changed, 50 insertions(+) diff --git a/src/cmd/compile/internal/arm64/ssa.go b/src/cmd/compile/internal/arm64/ssa.go index 9c26d90fd0..96a29224bf 100644 --- a/src/cmd/compile/internal/arm64/ssa.go +++ b/src/cmd/compile/internal/arm64/ssa.go @@ -1132,6 +1132,10 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p := s.Prog(obj.AGETCALLERPC) p.To.Type = obj.TYPE_REG p.To.Reg = v.Reg() + case ssa.OpARM64DMB: + p := s.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_CONST + p.From.Offset = v.AuxInt case ssa.OpARM64FlagConstant: v.Fatalf("FlagConstant op should never make it to codegen %v", v.LongString()) case ssa.OpARM64InvertFlags: diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index 4b66883f26..02fb4e1990 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -568,6 +568,9 @@ // Write barrier. (WB ...) => (LoweredWB ...) +// Publication barrier (0xe is ST option) +(PubBarrier mem) => (DMB [0xe] mem) + (PanicBounds [kind] x y mem) && boundsABI(kind) == 0 => (LoweredPanicBoundsA [kind] x y mem) (PanicBounds [kind] x y mem) && boundsABI(kind) == 1 => (LoweredPanicBoundsB [kind] x y mem) (PanicBounds [kind] x y mem) && boundsABI(kind) == 2 => (LoweredPanicBoundsC [kind] x y mem) diff --git a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go index e3ebb6e1af..a4a5b9bdcd 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go @@ -743,6 +743,9 @@ func init() { // Prefetch instruction // Do prefetch arg0 address with option aux. arg0=addr, arg1=memory, aux=option. {name: "PRFM", argLength: 2, aux: "Int64", reg: prefreg, asm: "PRFM", hasSideEffects: true}, + + // Publication barrier + {name: "DMB", argLength: 1, aux: "Int64", asm: "DMB", hasSideEffects: true}, // Do data barrier. arg0=memory, aux=option. } blocks := []blockData{ diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index 984552900f..4f133b1ff6 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -617,6 +617,9 @@ var genericOps = []opData{ {name: "AtomicOr8Variant", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 |= arg1. arg2=memory. Returns memory. {name: "AtomicOr32Variant", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 |= arg1. arg2=memory. Returns memory. + // Publication barrier + {name: "PubBarrier", argLength: 1, hasSideEffects: true}, // Do data barrier. arg0=memory. + // Clobber experiment op {name: "Clobber", argLength: 0, typ: "Void", aux: "SymOff", symEffect: "None"}, // write an invalid pointer value to the given pointer slot of a stack variable {name: "ClobberReg", argLength: 0, typ: "Void"}, // clobber a register diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 32ffd28b6a..128ec1f049 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -1633,6 +1633,7 @@ const ( OpARM64LoweredPanicBoundsB OpARM64LoweredPanicBoundsC OpARM64PRFM + OpARM64DMB OpMIPSADD OpMIPSADDconst @@ -2949,6 +2950,7 @@ const ( OpAtomicAnd32Variant OpAtomicOr8Variant OpAtomicOr32Variant + OpPubBarrier OpClobber OpClobberReg OpPrefetchCache @@ -21790,6 +21792,14 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "DMB", + auxType: auxInt64, + argLen: 1, + hasSideEffects: true, + asm: arm64.ADMB, + reg: regInfo{}, + }, { name: "ADD", @@ -36739,6 +36749,12 @@ var opcodeTable = [...]opInfo{ hasSideEffects: true, generic: true, }, + { + name: "PubBarrier", + argLen: 1, + hasSideEffects: true, + generic: true, + }, { name: "Clobber", auxType: auxSymOff, diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index 614e71f852..8ad9e400eb 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -920,6 +920,8 @@ func rewriteValueARM64(v *Value) bool { return rewriteValueARM64_OpPrefetchCache(v) case OpPrefetchCacheStreamed: return rewriteValueARM64_OpPrefetchCacheStreamed(v) + case OpPubBarrier: + return rewriteValueARM64_OpPubBarrier(v) case OpRotateLeft16: return rewriteValueARM64_OpRotateLeft16(v) case OpRotateLeft32: @@ -25613,6 +25615,18 @@ func rewriteValueARM64_OpPrefetchCacheStreamed(v *Value) bool { return true } } +func rewriteValueARM64_OpPubBarrier(v *Value) bool { + v_0 := v.Args[0] + // match: (PubBarrier mem) + // result: (DMB [0xe] mem) + for { + mem := v_0 + v.reset(OpARM64DMB) + v.AuxInt = int64ToAuxInt(0xe) + v.AddArg(mem) + return true + } +} func rewriteValueARM64_OpRotateLeft16(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 56fc191e5a..1bfbe7ce65 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -3856,6 +3856,13 @@ func InitTables() { }, all...) + addF("runtime", "publicationBarrier", + func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { + s.vars[memVar] = s.newValue1(ssa.OpPubBarrier, types.TypeMem, s.mem()) + return nil + }, + sys.ARM64) + /******** runtime/internal/sys ********/ addF("runtime/internal/sys", "Ctz32", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { -- GitLab From d9952ff5119d35751d44d5cd66c7164c7bc21ce0 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Mon, 4 Oct 2021 12:51:06 -0400 Subject: [PATCH 1429/2500] cmd/compile: set opendefer info symbol as content-addressable Also move the logic of setting arginfo symbols content-addressable to the place of symbol creation. Change-Id: Ia5c3d77b1cec988c42c84d573170120948575c07 Reviewed-on: https://go-review.googlesource.com/c/go/+/353830 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/compile/internal/gc/obj.go | 1 - src/cmd/compile/internal/ssagen/ssa.go | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go index aae7d03ebe..432c003b9a 100644 --- a/src/cmd/compile/internal/gc/obj.go +++ b/src/cmd/compile/internal/gc/obj.go @@ -259,7 +259,6 @@ func addGCLocals() { if x := fn.ArgInfo; x != nil { objw.Global(x, int32(len(x.P)), obj.RODATA|obj.DUPOK) x.Set(obj.AttrStatic, true) - x.Set(obj.AttrContentAddressable, true) } } } diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 1bfbe7ce65..91e585748e 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -318,6 +318,7 @@ func dvarint(x *obj.LSym, off int, v int64) int { // - Offset of the closure value to call func (s *state) emitOpenDeferInfo() { x := base.Ctxt.Lookup(s.curfn.LSym.Name + ".opendefer") + x.Set(obj.AttrContentAddressable, true) s.curfn.LSym.Func().OpenCodedDeferInfo = x off := 0 off = dvarint(x, off, -s.deferBitsTemp.FrameOffset()) @@ -6544,6 +6545,7 @@ func emitArgInfo(e *ssafn, f *ssa.Func, pp *objw.Progs) { } x := EmitArgInfo(e.curfn, f.OwnAux.ABIInfo()) + x.Set(obj.AttrContentAddressable, true) e.curfn.LSym.Func().ArgInfo = x // Emit a funcdata pointing at the arg info data. @@ -6557,6 +6559,9 @@ func emitArgInfo(e *ssafn, f *ssa.Func, pp *objw.Progs) { // emit argument info (locations on stack) of f for traceback. func EmitArgInfo(f *ir.Func, abiInfo *abi.ABIParamResultInfo) *obj.LSym { x := base.Ctxt.Lookup(fmt.Sprintf("%s.arginfo%d", f.LSym.Name, f.ABI)) + // NOTE: do not set ContentAddressable here. This may be referenced from + // assembly code by name (in this case f is a declaration). + // Instead, set it in emitArgInfo above. PtrSize := int64(types.PtrSize) uintptrTyp := types.Types[types.TUINTPTR] -- GitLab From 7ee4c1665477c6cf574cb9128deaf9d00906c69f Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Mon, 4 Oct 2021 21:44:08 +0000 Subject: [PATCH 1430/2500] Revert "runtime: add padding to Linux kernel structures" This reverts commit f0db7eae74ea235e9fbc2598252bfd46c1cc5510. Reason for revert: Breaks linux-386 tests Change-Id: Ia51fbf97460ab52920b67d6db6177ac2d6b0058e Reviewed-on: https://go-review.googlesource.com/c/go/+/353432 Trust: Michael Pratt Run-TryBot: Michael Pratt TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/runtime/defs_linux_386.go | 11 ----------- src/runtime/defs_linux_amd64.go | 11 ----------- src/runtime/defs_linux_arm.go | 11 ----------- src/runtime/defs_linux_arm64.go | 11 ----------- src/runtime/defs_linux_mips64x.go | 11 ----------- src/runtime/defs_linux_mipsx.go | 11 ----------- src/runtime/defs_linux_ppc64.go | 11 ----------- src/runtime/defs_linux_ppc64le.go | 11 ----------- src/runtime/defs_linux_riscv64.go | 11 ----------- src/runtime/defs_linux_s390x.go | 11 ----------- src/runtime/os_linux.go | 12 ------------ 11 files changed, 122 deletions(-) diff --git a/src/runtime/defs_linux_386.go b/src/runtime/defs_linux_386.go index fd9b60c444..d8b546cb4c 100644 --- a/src/runtime/defs_linux_386.go +++ b/src/runtime/defs_linux_386.go @@ -3,8 +3,6 @@ package runtime -import "internal/goarch" - const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -174,11 +172,6 @@ type siginfo struct { si_code int32 // below here is a union; si_addr is the only field we use si_addr uint32 - - // Pad struct to the max size in the kernel. Account for the 3 32-bit - // fields, the alignment to this architecture's pointer size, and the final - // pointer-length field. - _ [_si_max_size - (3*4 + (1-4/goarch.PtrSize)*4 + 1*goarch.PtrSize)]byte } type stackt struct { @@ -242,10 +235,6 @@ type sigevent struct { notify int32 // below here is a union; sigev_notify_thread_id is the only field we use sigev_notify_thread_id int32 - - // Pad struct to the max size in the kernel. Account for the pointer-length - // field and the 3 32-bit fields. - _ [_sigev_max_size - (1*goarch.PtrSize + 3*4)]byte } type epollevent struct { diff --git a/src/runtime/defs_linux_amd64.go b/src/runtime/defs_linux_amd64.go index 29dabe08dd..6afb67f77f 100644 --- a/src/runtime/defs_linux_amd64.go +++ b/src/runtime/defs_linux_amd64.go @@ -3,8 +3,6 @@ package runtime -import "internal/goarch" - const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -136,11 +134,6 @@ type siginfo struct { si_code int32 // below here is a union; si_addr is the only field we use si_addr uint64 - - // Pad struct to the max size in the kernel. Account for the 3 32-bit - // fields, the alignment to this architecture's pointer size, and the final - // pointer-length field. - _ [_si_max_size - (3*4 + (1-4/goarch.PtrSize)*4 + 1*goarch.PtrSize)]byte } type itimerspec struct { @@ -159,10 +152,6 @@ type sigevent struct { notify int32 // below here is a union; sigev_notify_thread_id is the only field we use sigev_notify_thread_id int32 - - // Pad struct to the max size in the kernel. Account for the pointer-length - // field and the 3 32-bit fields. - _ [_sigev_max_size - (1*goarch.PtrSize + 3*4)]byte } type epollevent struct { diff --git a/src/runtime/defs_linux_arm.go b/src/runtime/defs_linux_arm.go index 3ed6940647..ec24d76326 100644 --- a/src/runtime/defs_linux_arm.go +++ b/src/runtime/defs_linux_arm.go @@ -4,8 +4,6 @@ package runtime -import "internal/goarch" - // Constants const ( _EINTR = 0x4 @@ -177,10 +175,6 @@ type sigevent struct { notify int32 // below here is a union; sigev_notify_thread_id is the only field we use sigev_notify_thread_id int32 - - // Pad struct to the max size in the kernel. Account for the pointer-length - // field and the 3 32-bit fields. - _ [_sigev_max_size - (1*goarch.PtrSize + 3*4)]byte } type siginfo struct { @@ -189,11 +183,6 @@ type siginfo struct { si_code int32 // below here is a union; si_addr is the only field we use si_addr uint32 - - // Pad struct to the max size in the kernel. Account for the 3 32-bit - // fields, the alignment to this architecture's pointer size, and the final - // pointer-length field. - _ [_si_max_size - (3*4 + (1-4/goarch.PtrSize)*4 + 1*goarch.PtrSize)]byte } type sigactiont struct { diff --git a/src/runtime/defs_linux_arm64.go b/src/runtime/defs_linux_arm64.go index 6a126c4a15..f9f175004b 100644 --- a/src/runtime/defs_linux_arm64.go +++ b/src/runtime/defs_linux_arm64.go @@ -3,8 +3,6 @@ package runtime -import "internal/goarch" - const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -136,11 +134,6 @@ type siginfo struct { si_code int32 // below here is a union; si_addr is the only field we use si_addr uint64 - - // Pad struct to the max size in the kernel. Account for the 3 32-bit - // fields, the alignment to this architecture's pointer size, and the final - // pointer-length field. - _ [_si_max_size - (3*4 + (1-4/goarch.PtrSize)*4 + 1*goarch.PtrSize)]byte } type itimerspec struct { @@ -159,10 +152,6 @@ type sigevent struct { notify int32 // below here is a union; sigev_notify_thread_id is the only field we use sigev_notify_thread_id int32 - - // Pad struct to the max size in the kernel. Account for the pointer-length - // field and the 3 32-bit fields. - _ [_sigev_max_size - (1*goarch.PtrSize + 3*4)]byte } type epollevent struct { diff --git a/src/runtime/defs_linux_mips64x.go b/src/runtime/defs_linux_mips64x.go index 34e803331c..1743bbce41 100644 --- a/src/runtime/defs_linux_mips64x.go +++ b/src/runtime/defs_linux_mips64x.go @@ -8,8 +8,6 @@ package runtime -import "internal/goarch" - const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -145,11 +143,6 @@ type siginfo struct { __pad0 [1]int32 // below here is a union; si_addr is the only field we use si_addr uint64 - - // Pad struct to the max size in the kernel. Account for the 3 32-bit - // fields, the alignment to this architecture's pointer size, and the final - // pointer-length field. - _ [_si_max_size - (3*4 + (1-4/goarch.PtrSize)*4 + 1*goarch.PtrSize)]byte } type itimerspec struct { @@ -168,10 +161,6 @@ type sigevent struct { notify int32 // below here is a union; sigev_notify_thread_id is the only field we use sigev_notify_thread_id int32 - - // Pad struct to the max size in the kernel. Account for the pointer-length - // field and the 3 32-bit fields. - _ [_sigev_max_size - (1*goarch.PtrSize + 3*4)]byte } type epollevent struct { diff --git a/src/runtime/defs_linux_mipsx.go b/src/runtime/defs_linux_mipsx.go index 7a7db7f181..e84d4979e1 100644 --- a/src/runtime/defs_linux_mipsx.go +++ b/src/runtime/defs_linux_mipsx.go @@ -8,8 +8,6 @@ package runtime -import "internal/goarch" - const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -139,11 +137,6 @@ type siginfo struct { si_errno int32 // below here is a union; si_addr is the only field we use si_addr uint32 - - // Pad struct to the max size in the kernel. Account for the 3 32-bit - // fields, the alignment to this architecture's pointer size, and the final - // pointer-length field. - _ [_si_max_size - (3*4 + (1-4/goarch.PtrSize)*4 + 1*goarch.PtrSize)]byte } type itimerspec struct { @@ -162,10 +155,6 @@ type sigevent struct { notify int32 // below here is a union; sigev_notify_thread_id is the only field we use sigev_notify_thread_id int32 - - // Pad struct to the max size in the kernel. Account for the pointer-length - // field and the 3 32-bit fields. - _ [_sigev_max_size - (1*goarch.PtrSize + 3*4)]byte } type epollevent struct { diff --git a/src/runtime/defs_linux_ppc64.go b/src/runtime/defs_linux_ppc64.go index 7971ca7058..e0775e2974 100644 --- a/src/runtime/defs_linux_ppc64.go +++ b/src/runtime/defs_linux_ppc64.go @@ -3,8 +3,6 @@ package runtime -import "internal/goarch" - const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -137,11 +135,6 @@ type siginfo struct { si_code int32 // below here is a union; si_addr is the only field we use si_addr uint64 - - // Pad struct to the max size in the kernel. Account for the 3 32-bit - // fields, the alignment to this architecture's pointer size, and the final - // pointer-length field. - _ [_si_max_size - (3*4 + (1-4/goarch.PtrSize)*4 + 1*goarch.PtrSize)]byte } type itimerspec struct { @@ -160,10 +153,6 @@ type sigevent struct { notify int32 // below here is a union; sigev_notify_thread_id is the only field we use sigev_notify_thread_id int32 - - // Pad struct to the max size in the kernel. Account for the pointer-length - // field and the 3 32-bit fields. - _ [_sigev_max_size - (1*goarch.PtrSize + 3*4)]byte } type epollevent struct { diff --git a/src/runtime/defs_linux_ppc64le.go b/src/runtime/defs_linux_ppc64le.go index 7971ca7058..e0775e2974 100644 --- a/src/runtime/defs_linux_ppc64le.go +++ b/src/runtime/defs_linux_ppc64le.go @@ -3,8 +3,6 @@ package runtime -import "internal/goarch" - const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -137,11 +135,6 @@ type siginfo struct { si_code int32 // below here is a union; si_addr is the only field we use si_addr uint64 - - // Pad struct to the max size in the kernel. Account for the 3 32-bit - // fields, the alignment to this architecture's pointer size, and the final - // pointer-length field. - _ [_si_max_size - (3*4 + (1-4/goarch.PtrSize)*4 + 1*goarch.PtrSize)]byte } type itimerspec struct { @@ -160,10 +153,6 @@ type sigevent struct { notify int32 // below here is a union; sigev_notify_thread_id is the only field we use sigev_notify_thread_id int32 - - // Pad struct to the max size in the kernel. Account for the pointer-length - // field and the 3 32-bit fields. - _ [_sigev_max_size - (1*goarch.PtrSize + 3*4)]byte } type epollevent struct { diff --git a/src/runtime/defs_linux_riscv64.go b/src/runtime/defs_linux_riscv64.go index 92f4563dd5..1052213a4c 100644 --- a/src/runtime/defs_linux_riscv64.go +++ b/src/runtime/defs_linux_riscv64.go @@ -4,8 +4,6 @@ package runtime -import "internal/goarch" - const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -134,11 +132,6 @@ type siginfo struct { si_code int32 // below here is a union; si_addr is the only field we use si_addr uint64 - - // Pad struct to the max size in the kernel. Account for the 3 32-bit - // fields, the alignment to this architecture's pointer size, and the final - // pointer-length field. - _ [_si_max_size - (3*4 + (1-4/goarch.PtrSize)*4 + 1*goarch.PtrSize)]byte } type itimerspec struct { @@ -157,10 +150,6 @@ type sigevent struct { notify int32 // below here is a union; sigev_notify_thread_id is the only field we use sigev_notify_thread_id int32 - - // Pad struct to the max size in the kernel. Account for the pointer-length - // field and the 3 32-bit fields. - _ [_sigev_max_size - (1*goarch.PtrSize + 3*4)]byte } type epollevent struct { diff --git a/src/runtime/defs_linux_s390x.go b/src/runtime/defs_linux_s390x.go index 8a56ef0b80..b072955d4a 100644 --- a/src/runtime/defs_linux_s390x.go +++ b/src/runtime/defs_linux_s390x.go @@ -4,8 +4,6 @@ package runtime -import "internal/goarch" - const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -133,11 +131,6 @@ type siginfo struct { si_code int32 // below here is a union; si_addr is the only field we use si_addr uint64 - - // Pad struct to the max size in the kernel. Account for the 3 32-bit - // fields, the alignment to this architecture's pointer size, and the final - // pointer-length field. - _ [_si_max_size - (3*4 + (1-4/goarch.PtrSize)*4 + 1*goarch.PtrSize)]byte } type itimerspec struct { @@ -156,10 +149,6 @@ type sigevent struct { notify int32 // below here is a union; sigev_notify_thread_id is the only field we use sigev_notify_thread_id int32 - - // Pad struct to the max size in the kernel. Account for the pointer-length - // field and the 3 32-bit fields. - _ [_sigev_max_size - (1*goarch.PtrSize + 3*4)]byte } type epollevent struct { diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go index d5a5ff763b..06773c2193 100644 --- a/src/runtime/os_linux.go +++ b/src/runtime/os_linux.go @@ -440,18 +440,6 @@ func pipe() (r, w int32, errno int32) func pipe2(flags int32) (r, w int32, errno int32) func setNonblock(fd int32) -const ( - _si_max_size = 128 - _sigev_max_size = 64 -) - -// Assert that the Go definitions of structures exchanged with the kernel are -// the same size as what the kernel defines. -var ( - _ [_si_max_size]struct{} = [unsafe.Sizeof(siginfo{})]struct{}{} - _ [_sigev_max_size]struct{} = [unsafe.Sizeof(sigevent{})]struct{}{} -) - //go:nosplit //go:nowritebarrierrec func setsig(i uint32, fn uintptr) { -- GitLab From 752cc07c77767d28a61525daa359d087b035f5c1 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Fri, 1 Oct 2021 16:19:27 -0700 Subject: [PATCH 1431/2500] cmd, runtime: mark assembly routines in FuncFlags There's no good way to ascertain at runtime whether a function was implemented in assembly. The existing workaround doesn't play nicely with some upcoming linker changes. This change introduces an explicit marker for routines implemented in assembly. This change doesn't use the new bit anywhere, it only introduces it. Change-Id: I4051dc0afc15b260724a04b9d18aeeb94911bb29 Reviewed-on: https://go-review.googlesource.com/c/go/+/353671 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/internal/obj/objfile.go | 3 +++ src/cmd/internal/obj/plist.go | 7 +++++-- src/cmd/internal/objabi/funcid.go | 1 + src/runtime/symtab.go | 3 +++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index 3d8d69f069..4fd2119b96 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -772,6 +772,9 @@ func (ctxt *Link) writeSymDebugNamed(s *LSym, name string) { if s.Func() != nil && s.Func().FuncFlag&objabi.FuncFlag_TOPFRAME != 0 { fmt.Fprintf(ctxt.Bso, "topframe ") } + if s.Func() != nil && s.Func().FuncFlag&objabi.FuncFlag_ASM != 0 { + fmt.Fprintf(ctxt.Bso, "asm ") + } fmt.Fprintf(ctxt.Bso, "size=%d", s.Size) if s.Type == objabi.STEXT { fn := s.Func() diff --git a/src/cmd/internal/obj/plist.go b/src/cmd/internal/obj/plist.go index 6beb4dd94c..348a16356e 100644 --- a/src/cmd/internal/obj/plist.go +++ b/src/cmd/internal/obj/plist.go @@ -156,7 +156,7 @@ func (ctxt *Link) InitTextSym(s *LSym, flag int) { } name := strings.Replace(s.Name, "\"\"", ctxt.Pkgpath, -1) s.Func().FuncID = objabi.GetFuncID(name, flag&WRAPPER != 0 || flag&ABIWRAPPER != 0) - s.Func().FuncFlag = toFuncFlag(flag) + s.Func().FuncFlag = ctxt.toFuncFlag(flag) s.Set(AttrOnList, true) s.Set(AttrDuplicateOK, flag&DUPOK != 0) s.Set(AttrNoSplit, flag&NOSPLIT != 0) @@ -172,11 +172,14 @@ func (ctxt *Link) InitTextSym(s *LSym, flag int) { ctxt.dwarfSym(s) } -func toFuncFlag(flag int) objabi.FuncFlag { +func (ctxt *Link) toFuncFlag(flag int) objabi.FuncFlag { var out objabi.FuncFlag if flag&TOPFRAME != 0 { out |= objabi.FuncFlag_TOPFRAME } + if ctxt.IsAsm { + out |= objabi.FuncFlag_ASM + } return out } diff --git a/src/cmd/internal/objabi/funcid.go b/src/cmd/internal/objabi/funcid.go index 68f6a26a76..084fcdf712 100644 --- a/src/cmd/internal/objabi/funcid.go +++ b/src/cmd/internal/objabi/funcid.go @@ -13,6 +13,7 @@ type FuncFlag uint8 const ( FuncFlag_TOPFRAME = 1 << iota FuncFlag_SPWRITE + FuncFlag_ASM ) // A FuncID identifies particular functions that need to be treated diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index d1fe1a4fcc..14591602a3 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -383,6 +383,9 @@ const ( // to be an incomplete unwinding of the stack. In certain contexts // (in particular garbage collector stack scans) that is a fatal error. funcFlag_SPWRITE + + // ASM indicates that a function was implemented in assembly. + funcFlag_ASM ) // pcHeader holds data used by the pclntab lookups. -- GitLab From a8d78fae95d5a8a09e248ce4d26f04b38791a7b6 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Fri, 1 Oct 2021 15:39:21 -0700 Subject: [PATCH 1432/2500] cmd/compile: refactor gclocals sym creation It'll be used in second place in a subsequent change. No functional changes. Change-Id: I58dd12d7dde45b36995d031fc7fbb27d6eaf48d3 Reviewed-on: https://go-review.googlesource.com/c/go/+/353670 Trust: Josh Bleecher Snyder Trust: David Crawshaw Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: David Crawshaw --- src/cmd/compile/internal/liveness/plive.go | 13 +------------ src/cmd/internal/obj/sym.go | 9 +++++++++ 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/cmd/compile/internal/liveness/plive.go b/src/cmd/compile/internal/liveness/plive.go index 1e9d5748cc..dc778a6fb9 100644 --- a/src/cmd/compile/internal/liveness/plive.go +++ b/src/cmd/compile/internal/liveness/plive.go @@ -15,7 +15,6 @@ package liveness import ( - "crypto/md5" "crypto/sha1" "fmt" "os" @@ -1326,19 +1325,9 @@ func (lv *liveness) emit() (argsSym, liveSym *obj.LSym) { loff = objw.BitVec(&liveSymTmp, loff, locals) } - // Give these LSyms content-addressable names, - // so that they can be de-duplicated. - // This provides significant binary size savings. - // // These symbols will be added to Ctxt.Data by addGCLocals // after parallel compilation is done. - makeSym := func(tmpSym *obj.LSym) *obj.LSym { - return base.Ctxt.LookupInit(fmt.Sprintf("gclocals·%x", md5.Sum(tmpSym.P)), func(lsym *obj.LSym) { - lsym.P = tmpSym.P - lsym.Set(obj.AttrContentAddressable, true) - }) - } - return makeSym(&argsSymTmp), makeSym(&liveSymTmp) + return base.Ctxt.GCLocalsSym(argsSymTmp.P), base.Ctxt.GCLocalsSym(liveSymTmp.P) } // Entry pointer for Compute analysis. Solves for the Compute of diff --git a/src/cmd/internal/obj/sym.go b/src/cmd/internal/obj/sym.go index a272c517b3..a8360527ef 100644 --- a/src/cmd/internal/obj/sym.go +++ b/src/cmd/internal/obj/sym.go @@ -34,6 +34,7 @@ package obj import ( "cmd/internal/goobj" "cmd/internal/objabi" + "crypto/md5" "fmt" "internal/buildcfg" "log" @@ -172,6 +173,14 @@ func (ctxt *Link) Int64Sym(i int64) *LSym { }) } +// GCLocalsSym generates a content-addressable sym containing data. +func (ctxt *Link) GCLocalsSym(data []byte) *LSym { + return ctxt.LookupInit(fmt.Sprintf("gclocals·%x", md5.Sum(data)), func(lsym *LSym) { + lsym.P = data + lsym.Set(AttrContentAddressable, true) + }) +} + // Assign index to symbols. // asm is set to true if this is called by the assembler (i.e. not the compiler), // in which case all the symbols are non-package (for now). -- GitLab From c2483a5c034152fcdfbb2e6dbcf48b0103d8db6a Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Fri, 1 Oct 2021 16:25:32 -0700 Subject: [PATCH 1433/2500] cmd, runtime: eliminate runtime.no_pointers_stackmap runtime.no_pointers_stackmap is an odd beast. It is defined in a Go file, populated by assembly, used by the GC, and its address is magic used by async pre-emption to ascertain whether a routine was implemented in assembly. A subsequent change will force all GC data into the go.func.* linker symbol. runtime.no_pointers_stackmap is GC data, so it must go there. Yet it also needs to go into rodata, for the runtime address trick. This change eliminates it entirely. Replace the runtime address check with the newly introduced asm funcflag. Handle the assembly macro as magic, similarly to our handling of go_args_stackmap. This allows the no_pointers_stackmap to be identical in all ways to other gclocals stackmaps, including content-addressability. Change-Id: Id2f20a262cfab0719beb88e6342984ec4b196268 Reviewed-on: https://go-review.googlesource.com/c/go/+/353672 Trust: Josh Bleecher Snyder Reviewed-by: Cherry Mui --- src/cmd/internal/obj/plist.go | 19 ++++++++++++++++++- src/runtime/asm.s | 8 -------- src/runtime/funcdata.h | 2 +- src/runtime/preempt.go | 12 +++--------- 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/cmd/internal/obj/plist.go b/src/cmd/internal/obj/plist.go index 348a16356e..e5bbdd51a7 100644 --- a/src/cmd/internal/obj/plist.go +++ b/src/cmd/internal/obj/plist.go @@ -54,11 +54,28 @@ func Flushplist(ctxt *Link, plist *Plist, newprog ProgAlloc, myimportpath string if curtext == nil { // func _() {} continue } - if p.To.Sym.Name == "go_args_stackmap" { + switch p.To.Sym.Name { + case "go_args_stackmap": if p.From.Type != TYPE_CONST || p.From.Offset != objabi.FUNCDATA_ArgsPointerMaps { ctxt.Diag("FUNCDATA use of go_args_stackmap(SB) without FUNCDATA_ArgsPointerMaps") } p.To.Sym = ctxt.LookupDerived(curtext, curtext.Name+".args_stackmap") + case "no_pointers_stackmap": + if p.From.Type != TYPE_CONST || p.From.Offset != objabi.FUNCDATA_LocalsPointerMaps { + ctxt.Diag("FUNCDATA use of no_pointers_stackmap(SB) without FUNCDATA_LocalsPointerMaps") + } + // funcdata for functions with no local variables in frame. + // Define two zero-length bitmaps, because the same index is used + // for the local variables as for the argument frame, and assembly + // frames have two argument bitmaps, one without results and one with results. + // Write []uint32{2, 0}. + b := make([]byte, 8) + ctxt.Arch.ByteOrder.PutUint32(b, 2) + s := ctxt.GCLocalsSym(b) + if !s.OnList() { + ctxt.Globl(s, int64(len(s.P)), int(RODATA|DUPOK)) + } + p.To.Sym = s } } diff --git a/src/runtime/asm.s b/src/runtime/asm.s index 0e14fcd3e6..84d56de7dd 100644 --- a/src/runtime/asm.s +++ b/src/runtime/asm.s @@ -4,14 +4,6 @@ #include "textflag.h" -// funcdata for functions with no local variables in frame. -// Define two zero-length bitmaps, because the same index is used -// for the local variables as for the argument frame, and assembly -// frames have two argument bitmaps, one without results and one with results. -DATA runtime·no_pointers_stackmap+0x00(SB)/4, $2 -DATA runtime·no_pointers_stackmap+0x04(SB)/4, $0 -GLOBL runtime·no_pointers_stackmap(SB),RODATA, $8 - #ifndef GOARCH_amd64 TEXT ·sigpanic0(SB),NOSPLIT,$0-0 JMP ·sigpanic(SB) diff --git a/src/runtime/funcdata.h b/src/runtime/funcdata.h index 1002b181e4..15f1b5c9a1 100644 --- a/src/runtime/funcdata.h +++ b/src/runtime/funcdata.h @@ -44,7 +44,7 @@ // NO_LOCAL_POINTERS indicates that the assembly function stores // no pointers to heap objects in its local stack variables. -#define NO_LOCAL_POINTERS FUNCDATA $FUNCDATA_LocalsPointerMaps, runtime·no_pointers_stackmap(SB) +#define NO_LOCAL_POINTERS FUNCDATA $FUNCDATA_LocalsPointerMaps, no_pointers_stackmap(SB) // ArgsSizeUnknown is set in Func.argsize to mark all functions // whose argument size is unknown (C vararg functions, and diff --git a/src/runtime/preempt.go b/src/runtime/preempt.go index 18566a7459..da24f5042c 100644 --- a/src/runtime/preempt.go +++ b/src/runtime/preempt.go @@ -56,7 +56,6 @@ import ( "internal/abi" "internal/goarch" "runtime/internal/atomic" - "unsafe" ) type suspendGState struct { @@ -405,12 +404,9 @@ func isAsyncSafePoint(gp *g, pc, sp, lr uintptr) (bool, uintptr) { // functions (except at calls). return false, 0 } - if fd := funcdata(f, _FUNCDATA_LocalsPointerMaps); fd == nil || fd == unsafe.Pointer(&no_pointers_stackmap) { - // This is assembly code. Don't assume it's - // well-formed. We identify assembly code by - // checking that it has either no stack map, or - // no_pointers_stackmap, which is the stack map - // for ones marked as NO_LOCAL_POINTERS. + if fd := funcdata(f, _FUNCDATA_LocalsPointerMaps); fd == nil || f.flag&funcFlag_ASM != 0 { + // This is assembly code. Don't assume it's well-formed. + // TODO: Empirically we still need the fd == nil check. Why? // // TODO: Are there cases that are safe but don't have a // locals pointer map, like empty frame functions? @@ -455,5 +451,3 @@ func isAsyncSafePoint(gp *g, pc, sp, lr uintptr) (bool, uintptr) { } return true, pc } - -var no_pointers_stackmap uint64 // defined in assembly, for NO_LOCAL_POINTERS macro -- GitLab From 17674e2f174280c38ea7ae8297571c09b6eb076b Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 1 Oct 2021 12:21:36 -0400 Subject: [PATCH 1434/2500] cmd/internal/obj, cmd/link: move symbol alignment logic to object file writer Change-Id: I827a9702dfa01b712b88331668434f8db94df249 Reviewed-on: https://go-review.googlesource.com/c/go/+/353569 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/internal/obj/objfile.go | 26 ++++++++++++++++++++------ src/cmd/link/internal/ld/lib.go | 2 +- src/cmd/link/internal/ld/pcln.go | 1 + src/cmd/link/internal/ld/symtab.go | 23 +++++------------------ 4 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index 4fd2119b96..b6b922e02b 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -332,14 +332,27 @@ func (w *writer) Sym(s *LSym) { if fn := s.Func(); fn != nil { align = uint32(fn.Align) } - if s.ContentAddressable() { - // We generally assume data symbols are natually aligned, - // except for strings. If we dedup a string symbol and a - // non-string symbol with the same content, we should keep + if s.ContentAddressable() && s.Size != 0 { + // We generally assume data symbols are natually aligned + // (e.g. integer constants), except for strings and a few + // compiler-emitted funcdata. If we dedup a string symbol and + // a non-string symbol with the same content, we should keep // the largest alignment. // TODO: maybe the compiler could set the alignment for all // data symbols more carefully. - if s.Size != 0 && !strings.HasPrefix(s.Name, "go.string.") { + switch { + case strings.HasPrefix(s.Name, "go.string."), + strings.HasPrefix(name, "type..namedata."), + strings.HasPrefix(name, "type..importpath."), + strings.HasSuffix(name, ".opendefer"), + strings.HasSuffix(name, ".arginfo0"), + strings.HasSuffix(name, ".arginfo1"): + // These are just bytes, or varints. + align = 1 + case strings.HasPrefix(name, "gclocals·"): + // It has 32-bit fields. + align = 4 + default: switch { case w.ctxt.Arch.PtrSize == 8 && s.Size%8 == 0: align = 8 @@ -347,8 +360,9 @@ func (w *writer) Sym(s *LSym) { align = 4 case s.Size%2 == 0: align = 2 + default: + align = 1 } - // don't bother setting align to 1. } } if s.Size > cutoff { diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 9709c2e886..3221d60f80 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -320,7 +320,7 @@ var ( HEADR int32 nerrors int - liveness int64 + liveness int64 // size of liveness data (funcdata), printed if -v // See -strictdups command line flag. checkStrictDups int // 0=off 1=warning 2=error diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index 39dd4b916e..7506bf17a3 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -169,6 +169,7 @@ func genInlTreeSym(ctxt *Link, cu *sym.CompilationUnit, fi loader.FuncInfo, arch // eventually switch the type back to SRODATA. inlTreeSym.SetType(sym.SGOFUNC) ldr.SetAttrReachable(its, true) + ldr.SetSymAlign(its, 4) // it has 32-bit fields ninl := fi.NumInlTree() for i := 0; i < int(ninl); i++ { call := fi.InlTree(i) diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index 1e5c73c573..5e7eeeb94f 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -537,16 +537,12 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { continue } - align := int32(1) name := ldr.SymName(s) switch { case strings.HasPrefix(name, "go.string."): symGroupType[s] = sym.SGOSTRING ldr.SetAttrNotInSymbolTable(s, true) ldr.SetCarrierSym(s, symgostring) - if ldr.SymAlign(s) == 0 { - ldr.SetSymAlign(s, 1) // String data is just bytes, no padding. - } case strings.HasPrefix(name, "runtime.gcbits."): symGroupType[s] = sym.SGCBITS @@ -570,23 +566,17 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { case strings.HasPrefix(name, "gcargs."), strings.HasPrefix(name, "gclocals."), strings.HasPrefix(name, "gclocals·"), - ldr.SymType(s) == sym.SGOFUNC && s != symgofunc: // inltree, see pcln.go - // GC stack maps and inltrees have 32-bit fields. - align = 4 - fallthrough - case strings.HasSuffix(name, ".opendefer"), + ldr.SymType(s) == sym.SGOFUNC && s != symgofunc, // inltree, see pcln.go + strings.HasSuffix(name, ".opendefer"), strings.HasSuffix(name, ".arginfo0"), strings.HasSuffix(name, ".arginfo1"): - // These are just bytes, or varints, use align 1 (set before the switch). symGroupType[s] = sym.SGOFUNC ldr.SetAttrNotInSymbolTable(s, true) ldr.SetCarrierSym(s, symgofunc) - if a := ldr.SymAlign(s); a < align { - ldr.SetSymAlign(s, align) - } else { - align = a + if ctxt.Debugvlog != 0 { + align := ldr.SymAlign(s) + liveness += (ldr.SymSize(s) + int64(align) - 1) &^ (int64(align) - 1) } - liveness += (ldr.SymSize(s) + int64(align) - 1) &^ (int64(align) - 1) // Note: Check for "type." prefix after checking for .arginfo1 suffix. // That way symbols like "type..eq.[2]interface {}.arginfo1" that belong @@ -606,9 +596,6 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { ldr.SetCarrierSym(s, symtype) } } - if (strings.HasPrefix(name, "type..namedata.") || strings.HasPrefix(name, "type..importpath.")) && ldr.SymAlign(s) == 0 { - ldr.SetSymAlign(s, 1) // String data is just bytes, no padding. - } } } -- GitLab From 7c79e8ef0922ae27349cea9abd7e637ac429dfa0 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 4 Oct 2021 14:06:37 -0700 Subject: [PATCH 1435/2500] cmd/objdump: print full disassembly when testing with -v It is helpful for debugging. Change-Id: Idd566d312037420f8341fcf502a45410a8497798 Reviewed-on: https://go-review.googlesource.com/c/go/+/353878 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder Reviewed-by: Brad Fitzpatrick --- src/cmd/objdump/objdump_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/objdump/objdump_test.go b/src/cmd/objdump/objdump_test.go index f231a7c6e0..ff43161030 100644 --- a/src/cmd/objdump/objdump_test.go +++ b/src/cmd/objdump/objdump_test.go @@ -228,7 +228,7 @@ func testDisasm(t *testing.T, srcfname string, printCode bool, printGnuAsm bool, } } - if !ok { + if !ok || testing.Verbose() { t.Logf("full disassembly:\n%s", text) } } -- GitLab From 199ec4235000a51518802ce822447df5901c7df5 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 4 Oct 2021 14:08:05 -0700 Subject: [PATCH 1436/2500] debug/gosym: use sort.Search in findFunc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use sort.Search instead of open-coding the binary search. This makes the code a lot easier to work on. As a bonus, it speeds it up. name old time/op new time/op delta 115/LineToPC-8 57.4µs ± 5% 59.2µs ± 8% +3.19% (p=0.003 n=15+13) 115/PCToLine-8 255ns ± 1% 192ns ± 3% -24.63% (p=0.000 n=15+15) Change-Id: I41da18bfb0e745c40d24e5b96e50dfdd0c3b79f5 Reviewed-on: https://go-review.googlesource.com/c/go/+/353879 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder Reviewed-by: Brad Fitzpatrick --- src/debug/gosym/pclntab.go | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/src/debug/gosym/pclntab.go b/src/debug/gosym/pclntab.go index b2bd914ad7..4d312d22f1 100644 --- a/src/debug/gosym/pclntab.go +++ b/src/debug/gosym/pclntab.go @@ -11,6 +11,7 @@ package gosym import ( "bytes" "encoding/binary" + "sort" "sync" ) @@ -319,25 +320,13 @@ func (t *LineTable) findFunc(pc uint64) funcData { if pc < t.uintptr(t.functab) || pc >= t.uintptr(t.functab[len(t.functab)-int(t.ptrsize):]) { return funcData{} } - // The function table is a list of 2*nfunctab+1 uintptrs, // alternating program counters and offsets to func structures. - f := t.functab - nf := t.nfunctab - for nf > 0 { - m := nf / 2 - fm := f[2*t.ptrsize*m:] - if t.uintptr(fm) <= pc && pc < t.uintptr(fm[2*t.ptrsize:]) { - data := t.funcdata[t.uintptr(fm[t.ptrsize:]):] - return funcData{t: t, data: data} - } else if pc < t.uintptr(fm) { - nf = m - } else { - f = f[(m+1)*2*t.ptrsize:] - nf -= m + 1 - } - } - return funcData{} + idx := sort.Search(int(t.nfunctab), func(i int) bool { + return t.uintptr(t.functab[2*i*int(t.ptrsize):]) > pc + }) + idx-- + return t.funcData(uint32(idx)) } // readvarint reads, removes, and returns a varint from *pp. -- GitLab From 78c2529d73fbd2e2213c9f03862bcf2aaa86d78b Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 4 Oct 2021 14:49:42 -0700 Subject: [PATCH 1437/2500] debug/gosym: add funcTab abstraction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This clarifies the existing code and makes modifications easier. name old time/op new time/op delta 115/LineToPC-8 58.6µs ± 3% 56.4µs ± 3% -3.80% (p=0.000 n=15+15) 115/PCToLine-8 194ns ± 2% 188ns ± 2% -3.31% (p=0.000 n=15+15) Change-Id: Iafdf57af93d5e3c145965c32e0227e37c69ab017 Reviewed-on: https://go-review.googlesource.com/c/go/+/353880 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/debug/gosym/pclntab.go | 64 ++++++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 13 deletions(-) diff --git a/src/debug/gosym/pclntab.go b/src/debug/gosym/pclntab.go index 4d312d22f1..8fe45decd6 100644 --- a/src/debug/gosym/pclntab.go +++ b/src/debug/gosym/pclntab.go @@ -232,6 +232,7 @@ func (t *LineTable) parsePclnTab() { default: return } + t.version = possibleVersion // quantum and ptrSize are the same between 1.2, 1.16, and 1.18 t.quantum = uint32(t.Data[6]) @@ -255,7 +256,7 @@ func (t *LineTable) parsePclnTab() { t.pctab = data(6) t.funcdata = data(7) t.functab = data(7) - functabsize := t.nfunctab*2*t.ptrsize + t.ptrsize + functabsize := (int(t.nfunctab)*2 + 1) * t.functabFieldSize() t.functab = t.functab[:functabsize] case ver116: t.nfunctab = uint32(offset(0)) @@ -266,7 +267,7 @@ func (t *LineTable) parsePclnTab() { t.pctab = data(5) t.funcdata = data(6) t.functab = data(6) - functabsize := t.nfunctab*2*t.ptrsize + t.ptrsize + functabsize := (int(t.nfunctab)*2 + 1) * t.functabFieldSize() t.functab = t.functab[:functabsize] case ver12: t.nfunctab = uint32(t.uintptr(t.Data[8:])) @@ -274,7 +275,7 @@ func (t *LineTable) parsePclnTab() { t.funcnametab = t.Data t.functab = t.Data[8+t.ptrsize:] t.pctab = t.Data - functabsize := t.nfunctab*2*t.ptrsize + t.ptrsize + functabsize := (int(t.nfunctab)*2 + 1) * t.functabFieldSize() fileoff := t.binary.Uint32(t.functab[functabsize:]) t.functab = t.functab[:functabsize] t.filetab = t.Data[fileoff:] @@ -283,7 +284,6 @@ func (t *LineTable) parsePclnTab() { default: panic("unreachable") } - t.version = possibleVersion } // go12Funcs returns a slice of Funcs derived from the Go 1.2+ pcln table. @@ -295,12 +295,12 @@ func (t *LineTable) go12Funcs() []Func { }() } - n := len(t.functab) / int(t.ptrsize) / 2 - funcs := make([]Func, n) + ft := t.funcTab() + funcs := make([]Func, ft.Count()) for i := range funcs { f := &funcs[i] - f.Entry = t.uintptr(t.functab[2*i*int(t.ptrsize):]) - f.End = t.uintptr(t.functab[(2*i+2)*int(t.ptrsize):]) + f.Entry = ft.pc(i) + f.End = ft.pc(i + 1) info := t.funcData(uint32(i)) f.LineTable = t f.FrameSize = int(info.deferreturn()) @@ -317,13 +317,12 @@ func (t *LineTable) go12Funcs() []Func { // findFunc returns the funcData corresponding to the given program counter. func (t *LineTable) findFunc(pc uint64) funcData { - if pc < t.uintptr(t.functab) || pc >= t.uintptr(t.functab[len(t.functab)-int(t.ptrsize):]) { + ft := t.funcTab() + if pc < ft.pc(0) || pc >= ft.pc(ft.Count()) { return funcData{} } - // The function table is a list of 2*nfunctab+1 uintptrs, - // alternating program counters and offsets to func structures. idx := sort.Search(int(t.nfunctab), func(i int) bool { - return t.uintptr(t.functab[2*i*int(t.ptrsize):]) > pc + return ft.pc(i) > pc }) idx-- return t.funcData(uint32(idx)) @@ -372,6 +371,45 @@ func (t *LineTable) string(off uint32) string { return t.stringFrom(t.funcdata, off) } +// functabFieldSize returns the size in bytes of a single functab field. +func (t *LineTable) functabFieldSize() int { + return int(t.ptrsize) +} + +// funcTab returns t's funcTab. +func (t *LineTable) funcTab() funcTab { + return funcTab{t} +} + +// funcTab is memory corresponding to a slice of functab structs, followed by an invalid PC. +// A functab struct is a PC and a func offset. +type funcTab struct { + *LineTable +} + +// Count returns the number of func entries in f. +func (f funcTab) Count() int { + return int(f.nfunctab) +} + +// pc returns the PC of the i'th func in f. +func (f funcTab) pc(i int) uint64 { + return f.uint(f.functab[2*i*f.functabFieldSize():]) +} + +// funcOff returns the funcdata offset of the i'th func in f. +func (f funcTab) funcOff(i int) uint64 { + return f.uint(f.functab[(2*i+1)*f.functabFieldSize():]) +} + +// uint returns the uint stored at b. +func (f funcTab) uint(b []byte) uint64 { + if f.functabFieldSize() == 4 { + return uint64(f.binary.Uint32(b)) + } + return f.binary.Uint64(b) +} + // funcData is memory corresponding to an _func struct. type funcData struct { t *LineTable // LineTable this data is a part of @@ -380,7 +418,7 @@ type funcData struct { // funcData returns the ith funcData in t.functab. func (t *LineTable) funcData(i uint32) funcData { - data := t.funcdata[t.uintptr(t.functab[2*t.ptrsize*i+t.ptrsize:]):] + data := t.funcdata[t.funcTab().funcOff(int(i)):] return funcData{t: t, data: data} } -- GitLab From e5f6d8d00c3d0c1f77665f493109925c831e7cf8 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 1 Oct 2021 17:02:50 -0400 Subject: [PATCH 1438/2500] cmd/internal/obj: reduce alignment for gcbits runtime.gcbits symbols are pointer masks, which are just bytes. Change-Id: I6e86359451c7da69da435e1928e55712dd904047 Reviewed-on: https://go-review.googlesource.com/c/go/+/353571 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/internal/obj/objfile.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index b6b922e02b..0f3356f85e 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -344,6 +344,7 @@ func (w *writer) Sym(s *LSym) { case strings.HasPrefix(s.Name, "go.string."), strings.HasPrefix(name, "type..namedata."), strings.HasPrefix(name, "type..importpath."), + strings.HasPrefix(name, "runtime.gcbits."), strings.HasSuffix(name, ".opendefer"), strings.HasSuffix(name, ".arginfo0"), strings.HasSuffix(name, ".arginfo1"): -- GitLab From 81b7ec1ad5b50b8e73a63b44d8c2538154def535 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 4 Oct 2021 16:42:13 -0700 Subject: [PATCH 1439/2500] cmd/dist: omit cmd/cgo from toolchain1 We don't need cmd/cgo for building go_bootstrap or toolchain2, so skip building it as part of toolchain1. This allows cmd/cgo to assume a current go/ast; e.g., that ast.IndexListExpr exists (needed for next CL). Change-Id: I642bba780bf273e6ea9c6e7c5d5d7ccfe86bf462 Reviewed-on: https://go-review.googlesource.com/c/go/+/353884 Trust: Matthew Dempsky Reviewed-by: Ian Lance Taylor --- src/cmd/dist/build.go | 2 +- src/cmd/dist/buildtool.go | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go index 39f016e315..dca5464e56 100644 --- a/src/cmd/dist/build.go +++ b/src/cmd/dist/build.go @@ -1359,7 +1359,7 @@ func cmdbootstrap() { } // To recap, so far we have built the new toolchain - // (cmd/asm, cmd/cgo, cmd/compile, cmd/link) + // (cmd/asm, cmd/compile, cmd/link) // using Go 1.4's toolchain and go command. // Then we built the new go command (as go_bootstrap) // using the new toolchain and our own build logic (above). diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go index 320c62f850..8d1c914f30 100644 --- a/src/cmd/dist/buildtool.go +++ b/src/cmd/dist/buildtool.go @@ -33,7 +33,6 @@ import ( var bootstrapDirs = []string{ "cmd/asm", "cmd/asm/internal/...", - "cmd/cgo", "cmd/compile", "cmd/compile/internal/...", "cmd/internal/archive", @@ -102,6 +101,7 @@ func bootstrapBuildTools() { mkbuildcfg(pathf("%s/src/internal/buildcfg/zbootstrap.go", goroot)) mkobjabi(pathf("%s/src/cmd/internal/objabi/zbootstrap.go", goroot)) + mkzdefaultcc("", pathf("%s/src/cmd/cgo/zdefaultcc.go", goroot)) // Use $GOROOT/pkg/bootstrap as the bootstrap workspace root. // We use a subdirectory of $GOROOT/pkg because that's the @@ -134,12 +134,6 @@ func bootstrapBuildTools() { } xmkdirall(dst) - if path == "cmd/cgo" { - // Write to src because we need the file both for bootstrap - // and for later in the main build. - mkzdefaultcc("", pathf("%s/zdefaultcc.go", src)) - mkzdefaultcc("", pathf("%s/zdefaultcc.go", dst)) - } return nil } -- GitLab From 123393a535dc9f4b7fe80b564139de2ff7030ac4 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Tue, 5 Oct 2021 07:42:48 +0700 Subject: [PATCH 1440/2500] cmd/go: enable test build concurrent backend on darwin/arm64 After CL 353871, darwin/arm64 now do concurrent build, so enable the test for it. Updates #48490 Change-Id: I29336f6fc7d7d2f463d8ad2a620534bd7f048d2c Reviewed-on: https://go-review.googlesource.com/c/go/+/353949 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/testdata/script/build_concurrent_backend.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/cmd/go/testdata/script/build_concurrent_backend.txt b/src/cmd/go/testdata/script/build_concurrent_backend.txt index a279fed9dc..9cac635e5a 100644 --- a/src/cmd/go/testdata/script/build_concurrent_backend.txt +++ b/src/cmd/go/testdata/script/build_concurrent_backend.txt @@ -1,10 +1,6 @@ # Tests golang.org/issue/48490 # cmd/go should enable concurrent compilation by default -# Skip test on darwin/arm64, see #48496. -# TODO(cuonglm): remove this once #48496 is fixed. -[darwin] [arm64] skip - # Reset all experiments, since one of them can disable # concurrent compilation, e.g: fieldtrack. env GOEXPERIMENT=none -- GitLab From d55009c59458c5fe8520f8cd10e8b61696ebab7a Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 4 Oct 2021 23:55:52 +0200 Subject: [PATCH 1441/2500] crypto/rand: document additional getrandom/getentropy support in Reader CL 269999 added support for getrandom on Dragonfly. CL 299134 added support for getrandom on Solaris. CL 302489 added support for getentropy on macOS. Update the godoc for Reader accordingly. Change-Id: Ice39e5e62f052f21b664db6abbfd97f03944586e Reviewed-on: https://go-review.googlesource.com/c/go/+/353190 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/crypto/rand/rand.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/crypto/rand/rand.go b/src/crypto/rand/rand.go index fddd1147e6..b6248a4438 100644 --- a/src/crypto/rand/rand.go +++ b/src/crypto/rand/rand.go @@ -11,8 +11,9 @@ import "io" // Reader is a global, shared instance of a cryptographically // secure random number generator. // -// On Linux and FreeBSD, Reader uses getrandom(2) if available, /dev/urandom otherwise. -// On OpenBSD, Reader uses getentropy(2). +// On Linux, FreeBSD, Dragonfly and Solaris, Reader uses getrandom(2) if +// available, /dev/urandom otherwise. +// On OpenBSD and macOS, Reader uses getentropy(2). // On other Unix-like systems, Reader reads from /dev/urandom. // On Windows systems, Reader uses the RtlGenRandom API. // On Wasm, Reader uses the Web Crypto API. -- GitLab From 7983830423ca0017dc5d990532e28df13862dc2d Mon Sep 17 00:00:00 2001 From: Lynn Boger Date: Mon, 4 Oct 2021 16:27:56 -0500 Subject: [PATCH 1442/2500] runtime: add ABIInternal to strhash and memhash on ppc64x In testing the register ABI changes I found that the benchmarks for strhash and memhash degraded unless I marked them as ABIInternal. This fixes that. Change-Id: I9c7a04eaa6a66b888877f43454c51277c07e638a Reviewed-on: https://go-review.googlesource.com/c/go/+/353832 Reviewed-by: Cherry Mui Trust: Lynn Boger --- src/runtime/asm_ppc64x.s | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/runtime/asm_ppc64x.s b/src/runtime/asm_ppc64x.s index 2810324ce2..0e7ef7b2b8 100644 --- a/src/runtime/asm_ppc64x.s +++ b/src/runtime/asm_ppc64x.s @@ -855,14 +855,14 @@ TEXT runtime·unspillArgs(SB),NOSPLIT,$0-0 #endif // AES hashing not implemented for ppc64 -TEXT runtime·memhash(SB),NOSPLIT|NOFRAME,$0-32 - JMP runtime·memhashFallback(SB) -TEXT runtime·strhash(SB),NOSPLIT|NOFRAME,$0-24 - JMP runtime·strhashFallback(SB) -TEXT runtime·memhash32(SB),NOSPLIT|NOFRAME,$0-24 - JMP runtime·memhash32Fallback(SB) -TEXT runtime·memhash64(SB),NOSPLIT|NOFRAME,$0-24 - JMP runtime·memhash64Fallback(SB) +TEXT runtime·memhash(SB),NOSPLIT|NOFRAME,$0-32 + JMP runtime·memhashFallback(SB) +TEXT runtime·strhash(SB),NOSPLIT|NOFRAME,$0-24 + JMP runtime·strhashFallback(SB) +TEXT runtime·memhash32(SB),NOSPLIT|NOFRAME,$0-24 + JMP runtime·memhash32Fallback(SB) +TEXT runtime·memhash64(SB),NOSPLIT|NOFRAME,$0-24 + JMP runtime·memhash64Fallback(SB) TEXT runtime·return0(SB), NOSPLIT, $0 MOVW $0, R3 -- GitLab From cfd74f7727f6ad5a81d574c28cbee52cc13fdc52 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Fri, 24 Sep 2021 13:50:22 -0700 Subject: [PATCH 1443/2500] cmd/link: move all FUNCDATA refs into go.func.* This change moves all symbols referred to by FUNCDATA into go.func.* and go.funcrel.*. Surprisingly (because it inhibits some content-addressability), it shrinks binaries by a little bit, about 0.1%. This paves the way for a subsequent change to change FUNCDATA relocations to offsets. Change-Id: I70e487205073699f442192b0791cc92da5663057 Reviewed-on: https://go-review.googlesource.com/c/go/+/352189 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/internal/obj/objfile.go | 16 +++++++++++++++- src/cmd/link/internal/ld/symtab.go | 25 ++++++++++++++----------- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index 0f3356f85e..687cddc70c 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -408,7 +408,21 @@ func contentHashSection(s *LSym) byte { name := s.Name if s.IsPcdata() { return 'P' - } else if strings.HasPrefix(name, "type.") { + } + if strings.HasPrefix(name, "runtime.gcbits.") { + return 'G' // gcbits + } + if strings.HasPrefix(name, "gcargs.") || + strings.HasPrefix(name, "gclocals.") || + strings.HasPrefix(name, "gclocals·") || + strings.HasSuffix(name, ".opendefer") || + strings.HasSuffix(name, ".arginfo0") || + strings.HasSuffix(name, ".arginfo1") || + strings.HasSuffix(name, ".args_stackmap") || + strings.HasSuffix(name, ".stkobj") { + return 'F' // go.func.* or go.funcrel.* + } + if strings.HasPrefix(name, "type.") { return 'T' } return 0 diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index 5e7eeeb94f..7fddc59bb5 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -507,13 +507,9 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { symgcbits = groupSym("runtime.gcbits.*", sym.SGCBITS) ) - var symgofuncrel loader.Sym - if !ctxt.DynlinkingGo() { - if ctxt.UseRelro() { - symgofuncrel = groupSym("go.funcrel.*", sym.SGOFUNCRELRO) - } else { - symgofuncrel = symgofunc - } + symgofuncrel := symgofunc + if ctxt.UseRelro() { + symgofuncrel = groupSym("go.funcrel.*", sym.SGOFUNCRELRO) } symt := ldr.CreateSymForUpdate("runtime.symtab", 0) @@ -555,7 +551,7 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { } if ctxt.UseRelro() { symGroupType[s] = sym.SGOFUNCRELRO - if symgofuncrel != 0 { + if !ctxt.DynlinkingGo() { ldr.SetCarrierSym(s, symgofuncrel) } } else { @@ -569,10 +565,17 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { ldr.SymType(s) == sym.SGOFUNC && s != symgofunc, // inltree, see pcln.go strings.HasSuffix(name, ".opendefer"), strings.HasSuffix(name, ".arginfo0"), - strings.HasSuffix(name, ".arginfo1"): - symGroupType[s] = sym.SGOFUNC + strings.HasSuffix(name, ".arginfo1"), + strings.HasSuffix(name, ".args_stackmap"), + strings.HasSuffix(name, ".stkobj"): ldr.SetAttrNotInSymbolTable(s, true) - ldr.SetCarrierSym(s, symgofunc) + if ctxt.UseRelro() && strings.HasSuffix(name, ".stkobj") { + symGroupType[s] = sym.SGOFUNCRELRO + ldr.SetCarrierSym(s, symgofuncrel) + } else { + symGroupType[s] = sym.SGOFUNC + ldr.SetCarrierSym(s, symgofunc) + } if ctxt.Debugvlog != 0 { align := ldr.SymAlign(s) liveness += (ldr.SymSize(s) + int64(align) - 1) &^ (int64(align) - 1) -- GitLab From 017ffcd10d980e7fe6ca101e253a12c9326fba37 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Fri, 1 Oct 2021 16:35:43 -0700 Subject: [PATCH 1444/2500] cmd/link, runtime: convert FUNCDATA relocations to offsets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every function has associated numbered extra funcdata to another symbol. Prior to this change, a funcdata pointer was stored as a relocation. This change alters this to be an offset relative to go.func.* or go.funcrel.*. This reduces the number of relocations on darwin/arm64 by about 40%. It also shrinks externally linked binaries. On darwin/arm64: size before after Δ % addr2line 3788498 3699730 -88768 -2.343% api 5100018 4951074 -148944 -2.920% asm 4855234 4744274 -110960 -2.285% buildid 2500162 2419986 -80176 -3.207% cgo 4338258 4218306 -119952 -2.765% compile 22764418 22132226 -632192 -2.777% cover 4583186 4432770 -150416 -3.282% dist 3200962 3094626 -106336 -3.322% doc 3680402 3583602 -96800 -2.630% fix 3114914 3023922 -90992 -2.921% link 6308578 6154786 -153792 -2.438% nm 3754338 3665826 -88512 -2.358% objdump 4124738 4015234 -109504 -2.655% pack 2232626 2155010 -77616 -3.476% pprof 13497474 13044066 -453408 -3.359% test2json 2483810 2402146 -81664 -3.288% trace 10108898 9748802 -360096 -3.562% vet 6884322 6681314 -203008 -2.949% total 107320836 104167700 -3153136 -2.938% relocs before after Δ % addr2line 33357 25563 -7794 -23.365% api 31589 18409 -13180 -41.723% asm 27825 18904 -8921 -32.061% buildid 15603 9513 -6090 -39.031% cgo 27809 17103 -10706 -38.498% compile 114769 64829 -49940 -43.513% cover 32932 19462 -13470 -40.902% dist 18797 10796 -8001 -42.565% doc 22891 13503 -9388 -41.012% fix 19700 11465 -8235 -41.802% link 37324 23198 -14126 -37.847% nm 33226 25480 -7746 -23.313% objdump 35237 26610 -8627 -24.483% pack 13535 7951 -5584 -41.256% pprof 97986 63961 -34025 -34.724% test2json 15113 8735 -6378 -42.202% trace 66786 39636 -27150 -40.652% vet 43328 25971 -17357 -40.060% total 687806 431088 -256718 -37.324% It should also incrementally speed up binary launching and may reduce linker memory use. This is another step towards removing relocations so that pages that were previously dirtied by the loader may remain clean, which will offer memory savings useful in constrained environments like iOS. Removing the relocations in .stkobj symbols will allow some simplifications. There will be no references into go.funcrel.*, so we will no longer need to use the bottom bit to distinguish offset bases. Change-Id: I83d34c1701d6f3f515b9905941477d522441019d Reviewed-on: https://go-review.googlesource.com/c/go/+/352110 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/link/internal/ld/pcln.go | 90 +++++++++++++----------------- src/cmd/link/internal/ld/symtab.go | 6 ++ src/runtime/symtab.go | 14 ++++- 3 files changed, 58 insertions(+), 52 deletions(-) diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index 7506bf17a3..b041174cfe 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -552,11 +552,8 @@ type pclnSetUint func(*loader.SymbolBuilder, *sys.Arch, int64, uint64) int64 // // Because of timing in the linker, generating this table takes two passes. // The first pass is executed early in the link, and it creates any needed -// relocations to lay out the data. The pieces that need relocations are: -// 1) the PC->func table. -// 2) The funcdata. -// (1) is handled in writePCToFunc. (2) is handled in writeFuncdata. -// +// relocations to lay out the data. The piece that needs relocations is +// the PC->func table, handled in writePCToFunc. // After relocations, once we know where to write things in the output buffer, // we execute the second pass, which is actually writing the data. func (state *pclntab) generateFunctab(ctxt *Link, funcs []loader.Sym, inlSyms map[loader.Sym]loader.Sym, cuOffsets []uint32, nameOffsets map[loader.Sym]uint32) { @@ -592,7 +589,6 @@ func (state *pclntab) generateFunctab(ctxt *Link, funcs []loader.Sym, inlSyms ma // Write the data. writePCToFunc(ctxt, sb, funcs, startLocations, setAddr, (*loader.SymbolBuilder).SetUint) writeFuncs(ctxt, sb, funcs, inlSyms, startLocations, cuOffsets, nameOffsets) - state.writeFuncData(ctxt, sb, funcs, inlSyms, startLocations, setAddr, (*loader.SymbolBuilder).SetUint) } state.pclntab = state.addGeneratedSym(ctxt, "runtime.functab", size, writePcln) @@ -616,11 +612,6 @@ func (state *pclntab) generateFunctab(ctxt *Link, funcs []loader.Sym, inlSyms ma } setUintNOP := func(*loader.SymbolBuilder, *sys.Arch, int64, uint64) int64 { return 0 } writePCToFunc(ctxt, sb, funcs, startLocations, setAddr, setUintNOP) - if !useSymValue { - // Generate relocations for funcdata when externally linking. - state.writeFuncData(ctxt, sb, funcs, inlSyms, startLocations, setAddr, setUintNOP) - sb.SortRelocs() - } } // funcData returns the funcdata and offsets for the FuncInfo. @@ -675,7 +666,7 @@ func (state pclntab) calculateFunctabSize(ctxt *Link, funcs []loader.Sym) (int64 if numFuncData > 0 { // Func data is aligned. size = Rnd(size, int64(ctxt.Arch.PtrSize)) } - size += int64(numFuncData * ctxt.Arch.PtrSize) + size += int64(numFuncData * 4) } } @@ -715,49 +706,12 @@ func writePCToFunc(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, sta setAddr(sb, ctxt.Arch, int64(funcIndex)*2*int64(ctxt.Arch.PtrSize), prevFunc, ldr.SymSize(prevFunc)) } -// writeFuncData writes the funcdata tables. -// -// This function executes a callback for each funcdata needed in -// runtime.functab. It should be called once for internally linked static -// binaries, or twice (once to generate the needed relocations) for other -// build modes. -// -// Note the output of this function is interwoven with writeFuncs, but this is -// a separate function, because it's needed in different passes in -// generateFunctab. -func (state *pclntab) writeFuncData(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSyms map[loader.Sym]loader.Sym, startLocations []uint32, setAddr pclnSetAddr, setUint pclnSetUint) { - ldr := ctxt.loader - funcdata := []loader.Sym{} - for i, s := range funcs { - fi := ldr.FuncInfo(s) - if !fi.Valid() { - continue - } - fi.Preload() - - // funcdata, must be pointer-aligned and we're only int32-aligned. - // Missing funcdata will be 0 (nil pointer). - funcdata = funcData(ldr, s, fi, inlSyms[s], funcdata) - if len(funcdata) > 0 { - off := int64(startLocations[i] + funcSize + numPCData(ldr, s, fi)*4) - off = Rnd(off, int64(ctxt.Arch.PtrSize)) - for j := range funcdata { - dataoff := off + int64(ctxt.Arch.PtrSize*j) - if funcdata[j] == 0 { - setUint(sb, ctxt.Arch, dataoff, 0) - continue - } - // TODO: Does this need deduping? - setAddr(sb, ctxt.Arch, dataoff, funcdata[j], 0) - } - } - } -} - // writeFuncs writes the func structures and pcdata to runtime.functab. func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSyms map[loader.Sym]loader.Sym, startLocations, cuOffsets []uint32, nameOffsets map[loader.Sym]uint32) { ldr := ctxt.loader deferReturnSym := ldr.Lookup("runtime.deferreturn", abiInternalVer) + gofunc := ldr.Lookup("go.func.*", 0) + gofuncrel := ldr.Lookup("go.funcrel.*", 0) textStart := ldr.SymValue(ldr.Lookup("runtime.text", 0)) funcdata := []loader.Sym{} var pcsp, pcfile, pcline, pcinline loader.Sym @@ -844,6 +798,40 @@ func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSym sb.SetUint32(ctxt.Arch, int64(off+objabi.PCDATA_InlTreeIndex*4), uint32(ldr.SymValue(pcinline))) } } + + // Write funcdata refs as offsets from go.func.* and go.funcrel.*. + funcdata = funcData(ldr, s, fi, inlSyms[s], funcdata) + // funcdata must be pointer-aligned and we're only int32-aligned. + // Missing funcdata will be ^0. See runtime/symtab.go:funcdata. + off = uint32(startLocations[i] + funcSize + numPCData(ldr, s, fi)*4) + off = uint32(Rnd(int64(off), int64(ctxt.Arch.PtrSize))) + for j := range funcdata { + dataoff := off + uint32(4*j) + fdsym := funcdata[j] + if fdsym == 0 { + sb.SetUint32(ctxt.Arch, int64(dataoff), ^uint32(0)) // ^0 is a sentinel for "no value" + continue + } + + outer := ldr.OuterSym(fdsym) + if outer == 0 { + panic(fmt.Sprintf("no carrier sym for symbol %s (funcdata %s#%d)", ldr.SymName(fdsym), ldr.SymName(s), j)) + } + rel := uint32(ldr.SymValue(fdsym) - ldr.SymValue(outer)) + // Record gofunc vs gofuncrel in bottom bit. See runtime/symtab.go:funcdata. + // TODO: The only symbols that in gofuncrel are .stkobj symbols. + // Remove those relocations, and simplify this. + rel <<= 1 + switch outer { + case gofunc: + case gofuncrel: + rel |= 1 + default: + panic(fmt.Sprintf("expected symbol %s (funcdata %s#%d) to be placed in go.func.* or go.funcrel.*, got %s (%d)", + ldr.SymName(fdsym), ldr.SymName(s), j, ldr.SymName(outer), outer)) + } + sb.SetUint32(ctxt.Arch, int64(dataoff), rel) + } } } diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index 7fddc59bb5..c582e4908d 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -676,6 +676,12 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.gcbss", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.types", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.etypes", 0)) + moduledata.AddAddr(ctxt.Arch, ldr.Lookup("go.func.*", 0)) + if gofuncrel := ldr.Lookup("go.funcrel.*", 0); gofuncrel != 0 { + moduledata.AddAddr(ctxt.Arch, gofuncrel) + } else { + moduledata.AddUint(ctxt.Arch, 0) + } if ctxt.IsAIX() && ctxt.IsExternal() { // Add R_XCOFFREF relocation to prevent ld's garbage collection of diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 14591602a3..8f7b439dc5 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -427,6 +427,7 @@ type moduledata struct { noptrbss, enoptrbss uintptr end, gcdata, gcbss uintptr types, etypes uintptr + gofunc, gofuncrel uintptr // go.func.*, go.funcrel.* textsectmap []textsect typelinks []int32 // offsets from types @@ -1073,6 +1074,8 @@ func pcdatavalue2(f funcInfo, table uint32, targetpc uintptr) (int32, uintptr) { return pcvalue(f, pcdatastart(f, table), targetpc, nil, true) } +// funcdata returns a pointer to the ith funcdata for f. +// funcdata should be kept in sync with cmd/link:writeFuncs. func funcdata(f funcInfo, i uint8) unsafe.Pointer { if i < 0 || i >= f.nfuncdata { return nil @@ -1084,7 +1087,16 @@ func funcdata(f funcInfo, i uint8) unsafe.Pointer { } p = add(p, 4) } - return *(*unsafe.Pointer)(add(p, uintptr(i)*goarch.PtrSize)) + p = add(p, uintptr(i)*4) + off := *(*uint32)(p) + if off == ^uint32(0) { + return nil + } + base := f.datap.gofunc + if off&1 != 0 { + base = f.datap.gofuncrel + } + return unsafe.Pointer(base + uintptr(off>>1)) } // step advances to the next pc, value pair in the encoded table. -- GitLab From f1f626de5382220f3b34fd3f5616d5c0868b3561 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 5 Oct 2021 10:48:24 -0400 Subject: [PATCH 1445/2500] cmd/link: mangle function name with ABI on XCOFF This is like CL 304432 and CL 307229, for XCOFF. With this, GOEXPERIMENT=regabi works on AIX/PPC64. Change-Id: I8cf00681df5c93f397913febd78f38099d91e7c8 Reviewed-on: https://go-review.googlesource.com/c/go/+/353972 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/link/internal/ld/xcoff.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/cmd/link/internal/ld/xcoff.go b/src/cmd/link/internal/ld/xcoff.go index b57ccb4fe0..aba6138c83 100644 --- a/src/cmd/link/internal/ld/xcoff.go +++ b/src/cmd/link/internal/ld/xcoff.go @@ -822,9 +822,12 @@ func (f *xcoffFile) writeSymbolFunc(ctxt *Link, x loader.Sym) []xcoffSym { } } + name = ldr.SymExtname(x) + name = mangleABIName(ctxt, ldr, x, name) + s := &XcoffSymEnt64{ Nsclass: C_EXT, - Noffset: uint32(xfile.stringTable.add(ldr.SymExtname(x))), + Noffset: uint32(xfile.stringTable.add(name)), Nvalue: uint64(ldr.SymValue(x)), Nscnum: f.getXCOFFscnum(ldr.SymSect(x)), Ntype: SYM_TYPE_FUNC, -- GitLab From 060cd73ab930339d4565b57593293615b0e0315a Mon Sep 17 00:00:00 2001 From: wdvxdr Date: Thu, 30 Sep 2021 09:57:04 +0800 Subject: [PATCH 1446/2500] cmd/compile: use TZCNT instruction for GOAMD64>=v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit on my Intel CoffeeLake CPU: name old time/op new time/op delta TrailingZeros-8 0.68ns ± 1% 0.64ns ± 1% -6.26% (p=0.000 n=10+10) TrailingZeros8-8 0.70ns ± 1% 0.70ns ± 1% ~ (p=0.697 n=10+10) TrailingZeros16-8 0.70ns ± 1% 0.70ns ± 1% +0.57% (p=0.043 n=10+10) TrailingZeros32-8 0.66ns ± 1% 0.64ns ± 1% -3.35% (p=0.000 n=10+10) TrailingZeros64-8 0.68ns ± 1% 0.64ns ± 1% -5.84% (p=0.000 n=9+10) Updates #45453 Change-Id: I228ff2d51df24b1306136f061432f8a12bb1d6fd Reviewed-on: https://go-review.googlesource.com/c/go/+/353249 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/amd64/ssa.go | 3 +- src/cmd/compile/internal/ssa/gen/AMD64.rules | 18 ++- src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 4 + src/cmd/compile/internal/ssa/opGen.go | 30 ++++ src/cmd/compile/internal/ssa/rewriteAMD64.go | 144 ++++++++++++++++++- test/codegen/mathbits.go | 24 ++-- 6 files changed, 202 insertions(+), 21 deletions(-) diff --git a/src/cmd/compile/internal/amd64/ssa.go b/src/cmd/compile/internal/amd64/ssa.go index 68266d35d6..33cd5985e0 100644 --- a/src/cmd/compile/internal/amd64/ssa.go +++ b/src/cmd/compile/internal/amd64/ssa.go @@ -265,7 +265,8 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { case ssa.OpAMD64BLSIQ, ssa.OpAMD64BLSIL, ssa.OpAMD64BLSMSKQ, ssa.OpAMD64BLSMSKL, - ssa.OpAMD64BLSRQ, ssa.OpAMD64BLSRL: + ssa.OpAMD64BLSRQ, ssa.OpAMD64BLSRL, + ssa.OpAMD64TZCNTQ, ssa.OpAMD64TZCNTL: p := s.Prog(v.Op.Asm()) p.From.Type = obj.TYPE_REG p.From.Reg = v.Args[0].Reg() diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index edb1a4869a..1c63a3f70c 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -78,15 +78,21 @@ (OffPtr [off] ptr) => (ADDQ (MOVQconst [off]) ptr) // Lowering other arithmetic -(Ctz64 x) => (CMOVQEQ (Select0 (BSFQ x)) (MOVQconst [64]) (Select1 (BSFQ x))) -(Ctz32 x) => (Select0 (BSFQ (BTSQconst [32] x))) +(Ctz64 x) && buildcfg.GOAMD64 >= 3 => (TZCNTQ x) +(Ctz32 x) && buildcfg.GOAMD64 >= 3 => (TZCNTL x) +(Ctz64 x) && buildcfg.GOAMD64 < 3 => (CMOVQEQ (Select0 (BSFQ x)) (MOVQconst [64]) (Select1 (BSFQ x))) +(Ctz32 x) && buildcfg.GOAMD64 < 3 => (Select0 (BSFQ (BTSQconst [32] x))) (Ctz16 x) => (BSFL (BTSLconst [16] x)) (Ctz8 x) => (BSFL (BTSLconst [ 8] x)) -(Ctz64NonZero x) => (Select0 (BSFQ x)) -(Ctz32NonZero ...) => (BSFL ...) -(Ctz16NonZero ...) => (BSFL ...) -(Ctz8NonZero ...) => (BSFL ...) +(Ctz64NonZero x) && buildcfg.GOAMD64 >= 3 => (TZCNTQ x) +(Ctz32NonZero x) && buildcfg.GOAMD64 >= 3 => (TZCNTL x) +(Ctz16NonZero x) && buildcfg.GOAMD64 >= 3 => (TZCNTL x) +(Ctz8NonZero x) && buildcfg.GOAMD64 >= 3 => (TZCNTL x) +(Ctz64NonZero x) && buildcfg.GOAMD64 < 3 => (Select0 (BSFQ x)) +(Ctz32NonZero x) && buildcfg.GOAMD64 < 3 => (BSFL x) +(Ctz16NonZero x) && buildcfg.GOAMD64 < 3 => (BSFL x) +(Ctz8NonZero x) && buildcfg.GOAMD64 < 3 => (BSFL x) // BitLen64 of a 64 bit value x requires checking whether x == 0, since BSRQ is undefined when x == 0. // However, for zero-extended values, we can cheat a bit, and calculate diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index 6e4c514bd0..1887772736 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -918,6 +918,10 @@ func init() { {name: "BLSMSKL", argLength: 1, reg: gp11, asm: "BLSMSKL", clobberFlags: true}, // arg0 ^ (arg0 - 1) {name: "BLSRQ", argLength: 1, reg: gp11, asm: "BLSRQ", clobberFlags: true}, // arg0 & (arg0 - 1) {name: "BLSRL", argLength: 1, reg: gp11, asm: "BLSRL", clobberFlags: true}, // arg0 & (arg0 - 1) + // count the number of trailing zero bits, prefer TZCNTQ over BSFQ, as TZCNTQ(0)==64 + // and BSFQ(0) is undefined. Same for TZCNTL(0)==32 + {name: "TZCNTQ", argLength: 1, reg: gp11, asm: "TZCNTQ", clobberFlags: true}, + {name: "TZCNTL", argLength: 1, reg: gp11, asm: "TZCNTL", clobberFlags: true}, } var AMD64blocks = []blockData{ diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 128ec1f049..6266092f6f 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -1041,6 +1041,8 @@ const ( OpAMD64BLSMSKL OpAMD64BLSRQ OpAMD64BLSRL + OpAMD64TZCNTQ + OpAMD64TZCNTL OpARMADD OpARMADDconst @@ -13752,6 +13754,34 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "TZCNTQ", + argLen: 1, + clobberFlags: true, + asm: x86.ATZCNTQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + }, + outputs: []outputInfo{ + {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + }, + }, + }, + { + name: "TZCNTL", + argLen: 1, + clobberFlags: true, + asm: x86.ATZCNTL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + }, + outputs: []outputInfo{ + {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + }, + }, + }, { name: "ADD", diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 906260fb14..10d3afbc7d 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -647,13 +647,11 @@ func rewriteValueAMD64(v *Value) bool { case OpCtz16: return rewriteValueAMD64_OpCtz16(v) case OpCtz16NonZero: - v.Op = OpAMD64BSFL - return true + return rewriteValueAMD64_OpCtz16NonZero(v) case OpCtz32: return rewriteValueAMD64_OpCtz32(v) case OpCtz32NonZero: - v.Op = OpAMD64BSFL - return true + return rewriteValueAMD64_OpCtz32NonZero(v) case OpCtz64: return rewriteValueAMD64_OpCtz64(v) case OpCtz64NonZero: @@ -661,8 +659,7 @@ func rewriteValueAMD64(v *Value) bool { case OpCtz8: return rewriteValueAMD64_OpCtz8(v) case OpCtz8NonZero: - v.Op = OpAMD64BSFL - return true + return rewriteValueAMD64_OpCtz8NonZero(v) case OpCvt32Fto32: v.Op = OpAMD64CVTTSS2SL return true @@ -28694,14 +28691,58 @@ func rewriteValueAMD64_OpCtz16(v *Value) bool { return true } } +func rewriteValueAMD64_OpCtz16NonZero(v *Value) bool { + v_0 := v.Args[0] + // match: (Ctz16NonZero x) + // cond: buildcfg.GOAMD64 >= 3 + // result: (TZCNTL x) + for { + x := v_0 + if !(buildcfg.GOAMD64 >= 3) { + break + } + v.reset(OpAMD64TZCNTL) + v.AddArg(x) + return true + } + // match: (Ctz16NonZero x) + // cond: buildcfg.GOAMD64 < 3 + // result: (BSFL x) + for { + x := v_0 + if !(buildcfg.GOAMD64 < 3) { + break + } + v.reset(OpAMD64BSFL) + v.AddArg(x) + return true + } + return false +} func rewriteValueAMD64_OpCtz32(v *Value) bool { v_0 := v.Args[0] b := v.Block typ := &b.Func.Config.Types // match: (Ctz32 x) + // cond: buildcfg.GOAMD64 >= 3 + // result: (TZCNTL x) + for { + x := v_0 + if !(buildcfg.GOAMD64 >= 3) { + break + } + v.reset(OpAMD64TZCNTL) + v.AddArg(x) + return true + } + // match: (Ctz32 x) + // cond: buildcfg.GOAMD64 < 3 // result: (Select0 (BSFQ (BTSQconst [32] x))) for { x := v_0 + if !(buildcfg.GOAMD64 < 3) { + break + } v.reset(OpSelect0) v0 := b.NewValue0(v.Pos, OpAMD64BSFQ, types.NewTuple(typ.UInt64, types.TypeFlags)) v1 := b.NewValue0(v.Pos, OpAMD64BTSQconst, typ.UInt64) @@ -28711,16 +28752,61 @@ func rewriteValueAMD64_OpCtz32(v *Value) bool { v.AddArg(v0) return true } + return false +} +func rewriteValueAMD64_OpCtz32NonZero(v *Value) bool { + v_0 := v.Args[0] + // match: (Ctz32NonZero x) + // cond: buildcfg.GOAMD64 >= 3 + // result: (TZCNTL x) + for { + x := v_0 + if !(buildcfg.GOAMD64 >= 3) { + break + } + v.reset(OpAMD64TZCNTL) + v.AddArg(x) + return true + } + // match: (Ctz32NonZero x) + // cond: buildcfg.GOAMD64 < 3 + // result: (BSFL x) + for { + x := v_0 + if !(buildcfg.GOAMD64 < 3) { + break + } + v.reset(OpAMD64BSFL) + v.AddArg(x) + return true + } + return false } func rewriteValueAMD64_OpCtz64(v *Value) bool { v_0 := v.Args[0] b := v.Block typ := &b.Func.Config.Types + // match: (Ctz64 x) + // cond: buildcfg.GOAMD64 >= 3 + // result: (TZCNTQ x) + for { + x := v_0 + if !(buildcfg.GOAMD64 >= 3) { + break + } + v.reset(OpAMD64TZCNTQ) + v.AddArg(x) + return true + } // match: (Ctz64 x) + // cond: buildcfg.GOAMD64 < 3 // result: (CMOVQEQ (Select0 (BSFQ x)) (MOVQconst [64]) (Select1 (BSFQ x))) for { t := v.Type x := v_0 + if !(buildcfg.GOAMD64 < 3) { + break + } v.reset(OpAMD64CMOVQEQ) v0 := b.NewValue0(v.Pos, OpSelect0, t) v1 := b.NewValue0(v.Pos, OpAMD64BSFQ, types.NewTuple(typ.UInt64, types.TypeFlags)) @@ -28733,21 +28819,39 @@ func rewriteValueAMD64_OpCtz64(v *Value) bool { v.AddArg3(v0, v2, v3) return true } + return false } func rewriteValueAMD64_OpCtz64NonZero(v *Value) bool { v_0 := v.Args[0] b := v.Block typ := &b.Func.Config.Types // match: (Ctz64NonZero x) + // cond: buildcfg.GOAMD64 >= 3 + // result: (TZCNTQ x) + for { + x := v_0 + if !(buildcfg.GOAMD64 >= 3) { + break + } + v.reset(OpAMD64TZCNTQ) + v.AddArg(x) + return true + } + // match: (Ctz64NonZero x) + // cond: buildcfg.GOAMD64 < 3 // result: (Select0 (BSFQ x)) for { x := v_0 + if !(buildcfg.GOAMD64 < 3) { + break + } v.reset(OpSelect0) v0 := b.NewValue0(v.Pos, OpAMD64BSFQ, types.NewTuple(typ.UInt64, types.TypeFlags)) v0.AddArg(x) v.AddArg(v0) return true } + return false } func rewriteValueAMD64_OpCtz8(v *Value) bool { v_0 := v.Args[0] @@ -28765,6 +28869,34 @@ func rewriteValueAMD64_OpCtz8(v *Value) bool { return true } } +func rewriteValueAMD64_OpCtz8NonZero(v *Value) bool { + v_0 := v.Args[0] + // match: (Ctz8NonZero x) + // cond: buildcfg.GOAMD64 >= 3 + // result: (TZCNTL x) + for { + x := v_0 + if !(buildcfg.GOAMD64 >= 3) { + break + } + v.reset(OpAMD64TZCNTL) + v.AddArg(x) + return true + } + // match: (Ctz8NonZero x) + // cond: buildcfg.GOAMD64 < 3 + // result: (BSFL x) + for { + x := v_0 + if !(buildcfg.GOAMD64 < 3) { + break + } + v.reset(OpAMD64BSFL) + v.AddArg(x) + return true + } + return false +} func rewriteValueAMD64_OpDiv16(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] diff --git a/test/codegen/mathbits.go b/test/codegen/mathbits.go index aecd84a78b..50527fea04 100644 --- a/test/codegen/mathbits.go +++ b/test/codegen/mathbits.go @@ -272,7 +272,8 @@ func RotateLeftVariable32(n uint32, m int) uint32 { // ------------------------ // func TrailingZeros(n uint) int { - // amd64:"BSFQ","MOVL\t\\$64","CMOVQEQ" + // amd64/v1,amd64/v2:"BSFQ","MOVL\t\\$64","CMOVQEQ" + // amd64/v3:"TZCNTQ" // arm:"CLZ" // arm64:"RBIT","CLZ" // s390x:"FLOGR" @@ -285,7 +286,8 @@ func TrailingZeros(n uint) int { } func TrailingZeros64(n uint64) int { - // amd64:"BSFQ","MOVL\t\\$64","CMOVQEQ" + // amd64/v1,amd64/v2:"BSFQ","MOVL\t\\$64","CMOVQEQ" + // amd64/v3:"TZCNTQ" // arm64:"RBIT","CLZ" // s390x:"FLOGR" // ppc64/power8:"ANDN","POPCNTD" @@ -303,7 +305,8 @@ func TrailingZeros64Subtract(n uint64) int { } func TrailingZeros32(n uint32) int { - // amd64:"BTSQ\\t\\$32","BSFQ" + // amd64/v1,amd64/v2:"BTSQ\\t\\$32","BSFQ" + // amd64/v3:"TZCNTL" // arm:"CLZ" // arm64:"RBITW","CLZW" // s390x:"FLOGR","MOVWZ" @@ -343,7 +346,8 @@ func TrailingZeros8(n uint8) int { func IterateBits(n uint) int { i := 0 for n != 0 { - // amd64:"BSFQ",-"CMOVEQ" + // amd64/v1,amd64/v2:"BSFQ",-"CMOVEQ" + // amd64/v3:"TZCNTQ" i += bits.TrailingZeros(n) n &= n - 1 } @@ -353,7 +357,8 @@ func IterateBits(n uint) int { func IterateBits64(n uint64) int { i := 0 for n != 0 { - // amd64:"BSFQ",-"CMOVEQ" + // amd64/v1,amd64/v2:"BSFQ",-"CMOVEQ" + // amd64/v3:"TZCNTQ" i += bits.TrailingZeros64(n) n &= n - 1 } @@ -363,7 +368,8 @@ func IterateBits64(n uint64) int { func IterateBits32(n uint32) int { i := 0 for n != 0 { - // amd64:"BSFL",-"BTSQ" + // amd64/v1,amd64/v2:"BSFL",-"BTSQ" + // amd64/v3:"TZCNTL" i += bits.TrailingZeros32(n) n &= n - 1 } @@ -373,7 +379,8 @@ func IterateBits32(n uint32) int { func IterateBits16(n uint16) int { i := 0 for n != 0 { - // amd64:"BSFL",-"BTSL" + // amd64/v1,amd64/v2:"BSFL",-"BTSL" + // amd64/v3:"TZCNTL" // arm64:"RBITW","CLZW",-"ORR" i += bits.TrailingZeros16(n) n &= n - 1 @@ -384,7 +391,8 @@ func IterateBits16(n uint16) int { func IterateBits8(n uint8) int { i := 0 for n != 0 { - // amd64:"BSFL",-"BTSL" + // amd64/v1,amd64/v2:"BSFL",-"BTSL" + // amd64/v3:"TZCNTL" // arm64:"RBITW","CLZW",-"ORR" i += bits.TrailingZeros8(n) n &= n - 1 -- GitLab From cbd7200167292b62792272bda46887bdf1b62fb0 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 28 Sep 2021 13:23:08 -0700 Subject: [PATCH 1447/2500] cmd/compile: test to ensure we guard GOAMD64>v1 instructions When compiling with GOAMD64=v1, clobber all the >v1 instructions with faulting instructions. Run the binary with the corresponding feature flags off. We shouldn't try to execute any of the clobbered instructions. Change-Id: I295acaf9fd0eafd037192aa6f933365c794cc76e Reviewed-on: https://go-review.googlesource.com/c/go/+/352831 Run-TryBot: Keith Randall TryBot-Result: Go Bot Trust: Keith Randall Reviewed-by: Matthew Dempsky --- .../compile/internal/amd64/versions_test.go | 335 ++++++++++++++++++ 1 file changed, 335 insertions(+) create mode 100644 src/cmd/compile/internal/amd64/versions_test.go diff --git a/src/cmd/compile/internal/amd64/versions_test.go b/src/cmd/compile/internal/amd64/versions_test.go new file mode 100644 index 0000000000..b47de12efd --- /dev/null +++ b/src/cmd/compile/internal/amd64/versions_test.go @@ -0,0 +1,335 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package amd64_test + +import ( + "bufio" + "debug/elf" + "debug/macho" + "fmt" + "internal/testenv" + "io" + "math/bits" + "os" + "os/exec" + "regexp" + "runtime" + "strconv" + "strings" + "testing" +) + +// Test to make sure that when building for GOAMD64=v1, we don't +// use any >v1 instructions. +func TestGoAMD64v1(t *testing.T) { + if runtime.GOARCH != "amd64" { + t.Skip("amd64-only test") + } + if runtime.GOOS != "linux" && runtime.GOOS != "darwin" { + t.Skip("test only works on elf or macho platforms") + } + if v := os.Getenv("GOAMD64"); v != "" && v != "v1" { + // Test runs only on v1 (which is the default). + // TODO: use build tags from #45454 instead. + t.Skip("GOAMD64 already set") + } + if os.Getenv("TESTGOAMD64V1") != "" { + t.Skip("recursive call") + } + + // Make a binary which will be a modified version of the + // currently running binary. + dst, err := os.CreateTemp("", "TestGoAMD64v1") + if err != nil { + t.Fatalf("failed to create temp file: %v", err) + } + defer os.Remove(dst.Name()) + dst.Chmod(0500) // make executable + + // Clobber all the non-v1 opcodes. + opcodes := map[string]bool{} + var features []string + for feature, opcodeList := range featureToOpcodes { + features = append(features, fmt.Sprintf("cpu.%s=off", feature)) + for _, op := range opcodeList { + opcodes[op] = true + } + } + clobber(t, os.Args[0], dst, opcodes) + if err = dst.Close(); err != nil { + t.Fatalf("can't close binary: %v", err) + } + + // Run the resulting binary. + cmd := exec.Command(dst.Name()) + testenv.CleanCmdEnv(cmd) + cmd.Env = append(cmd.Env, "TESTGOAMD64V1=yes") + cmd.Env = append(cmd.Env, fmt.Sprintf("GODEBUG=%s", strings.Join(features, ","))) + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("couldn't execute test: %s", err) + } + if string(out) != "PASS\n" { + t.Fatalf("test reported error: %s", string(out)) + } +} + +// Clobber copies the binary src to dst, replacing all the instructions in opcodes with +// faulting instructions. +func clobber(t *testing.T, src string, dst *os.File, opcodes map[string]bool) { + // Run objdump to get disassembly. + var re *regexp.Regexp + var disasm io.Reader + if false { + // TODO: go tool objdump doesn't disassemble the bmi1 instructions + // in question correctly. See issue 48584. + cmd := exec.Command("go", "tool", "objdump", src) + var err error + disasm, err = cmd.StdoutPipe() + if err != nil { + t.Fatal(err) + } + if err := cmd.Start(); err != nil { + t.Fatal(err) + } + re = regexp.MustCompile(`^[^:]*:[-0-9]+\s+0x([0-9a-f]+)\s+([0-9a-f]+)\s+([A-Z]+)`) + } else { + // TODO: we're depending on platform-native objdump here. Hence the Skipf + // below if it doesn't run for some reason. + cmd := exec.Command("objdump", "-d", src) + var err error + disasm, err = cmd.StdoutPipe() + if err != nil { + t.Skipf("can't run test due to missing objdump: %s", err) + } + if err := cmd.Start(); err != nil { + t.Fatal(err) + } + re = regexp.MustCompile(`^\s*([0-9a-f]+):\s*((?:[0-9a-f][0-9a-f] )+)\s*([a-z]+)`) + } + + // Find all the instruction addresses we need to edit. + virtualEdits := map[uint64]bool{} + scanner := bufio.NewScanner(disasm) + for scanner.Scan() { + line := scanner.Text() + parts := re.FindStringSubmatch(line) + if len(parts) == 0 { + continue + } + addr, err := strconv.ParseUint(parts[1], 16, 64) + if err != nil { + continue // not a hex address + } + opcode := strings.ToLower(parts[3]) + if !opcodes[opcode] { + continue + } + t.Logf("clobbering instruction %s", line) + n := (len(parts[2]) - strings.Count(parts[2], " ")) / 2 // number of bytes in instruction encoding + for i := 0; i < n; i++ { + // Only really need to make the first byte faulting, but might + // as well make all the bytes faulting. + virtualEdits[addr+uint64(i)] = true + } + } + + // Figure out where in the binary the edits must be done. + physicalEdits := map[uint64]bool{} + if e, err := elf.Open(src); err == nil { + for _, sec := range e.Sections { + vaddr := sec.Addr + paddr := sec.Offset + size := sec.Size + for a := range virtualEdits { + if a >= vaddr && a < vaddr+size { + physicalEdits[paddr+(a-vaddr)] = true + } + } + } + } else if m, err2 := macho.Open(src); err2 == nil { + for _, sec := range m.Sections { + vaddr := sec.Addr + paddr := uint64(sec.Offset) + size := sec.Size + for a := range virtualEdits { + if a >= vaddr && a < vaddr+size { + physicalEdits[paddr+(a-vaddr)] = true + } + } + } + } else { + t.Log(err) + t.Log(err2) + t.Fatal("executable format not elf or macho") + } + if len(virtualEdits) != len(physicalEdits) { + t.Fatal("couldn't find an instruction in text sections") + } + + // Copy source to destination, making edits along the way. + f, err := os.Open(src) + if err != nil { + t.Fatal(err) + } + r := bufio.NewReader(f) + w := bufio.NewWriter(dst) + a := uint64(0) + done := 0 + for { + b, err := r.ReadByte() + if err == io.EOF { + break + } + if err != nil { + t.Fatal("can't read") + } + if physicalEdits[a] { + b = 0xcc // INT3 opcode + done++ + } + err = w.WriteByte(b) + if err != nil { + t.Fatal("can't write") + } + a++ + } + if done != len(physicalEdits) { + t.Fatal("physical edits remaining") + } + w.Flush() + f.Close() +} + +var featureToOpcodes = map[string][]string{ + // Note: we include *q, *l, and plain opcodes here. + // go tool objdump doesn't include a [QL] on popcnt instructions, until CL 351889 + // native objdump doesn't include [QL] on linux. + "popcnt": []string{"popcntq", "popcntl", "popcnt"}, + "bmi1": []string{"andnq", "andnl", "andn", "blsiq", "blsil", "blsi", "blsmskq", "blsmskl", "blsmsk", "blsrq", "blsrl", "blsr", "tzcntq", "tzcntl", "tzcnt"}, + // TODO: more? +} + +// Test to use POPCNT instruction, if available +func TestPopCnt(t *testing.T) { + for _, tt := range []struct { + x uint64 + want int + }{ + {0b00001111, 4}, + {0b00001110, 3}, + {0b00001100, 2}, + {0b00000000, 0}, + } { + if got := bits.OnesCount64(tt.x); got != tt.want { + t.Errorf("OnesCount64(%#x) = %d, want %d", tt.x, got, tt.want) + } + if got := bits.OnesCount32(uint32(tt.x)); got != tt.want { + t.Errorf("OnesCount32(%#x) = %d, want %d", tt.x, got, tt.want) + } + } +} + +// Test to use ANDN, if available +func TestAndNot(t *testing.T) { + for _, tt := range []struct { + x, y, want uint64 + }{ + {0b00001111, 0b00000011, 0b1100}, + {0b00001111, 0b00001100, 0b0011}, + {0b00000000, 0b00000000, 0b0000}, + } { + if got := tt.x &^ tt.y; got != tt.want { + t.Errorf("%#x &^ %#x = %#x, want %#x", tt.x, tt.y, got, tt.want) + } + if got := uint32(tt.x) &^ uint32(tt.y); got != uint32(tt.want) { + t.Errorf("%#x &^ %#x = %#x, want %#x", tt.x, tt.y, got, tt.want) + } + } +} + +// Test to use BLSI, if available +func TestBLSI(t *testing.T) { + for _, tt := range []struct { + x, want uint64 + }{ + {0b00001111, 0b001}, + {0b00001110, 0b010}, + {0b00001100, 0b100}, + {0b11000110, 0b010}, + {0b00000000, 0b000}, + } { + if got := tt.x & -tt.x; got != tt.want { + t.Errorf("%#x & (-%#x) = %#x, want %#x", tt.x, tt.x, got, tt.want) + } + if got := uint32(tt.x) & -uint32(tt.x); got != uint32(tt.want) { + t.Errorf("%#x & (-%#x) = %#x, want %#x", tt.x, tt.x, got, tt.want) + } + } +} + +// Test to use BLSMSK, if available +func TestBLSMSK(t *testing.T) { + for _, tt := range []struct { + x, want uint64 + }{ + {0b00001111, 0b001}, + {0b00001110, 0b011}, + {0b00001100, 0b111}, + {0b11000110, 0b011}, + {0b00000000, 1<<64 - 1}, + } { + if got := tt.x ^ (tt.x - 1); got != tt.want { + t.Errorf("%#x ^ (%#x-1) = %#x, want %#x", tt.x, tt.x, got, tt.want) + } + if got := uint32(tt.x) ^ (uint32(tt.x) - 1); got != uint32(tt.want) { + t.Errorf("%#x ^ (%#x-1) = %#x, want %#x", tt.x, tt.x, got, uint32(tt.want)) + } + } +} + +// Test to use BLSR, if available +func TestBLSR(t *testing.T) { + for _, tt := range []struct { + x, want uint64 + }{ + {0b00001111, 0b00001110}, + {0b00001110, 0b00001100}, + {0b00001100, 0b00001000}, + {0b11000110, 0b11000100}, + {0b00000000, 0b00000000}, + } { + if got := tt.x & (tt.x - 1); got != tt.want { + t.Errorf("%#x & (%#x-1) = %#x, want %#x", tt.x, tt.x, got, tt.want) + } + if got := uint32(tt.x) & (uint32(tt.x) - 1); got != uint32(tt.want) { + t.Errorf("%#x & (%#x-1) = %#x, want %#x", tt.x, tt.x, got, tt.want) + } + } +} + +func TestTrailingZeros(t *testing.T) { + for _, tt := range []struct { + x uint64 + want int + }{ + {0b00001111, 0}, + {0b00001110, 1}, + {0b00001100, 2}, + {0b00001000, 3}, + {0b00000000, 64}, + } { + if got := bits.TrailingZeros64(tt.x); got != tt.want { + t.Errorf("TrailingZeros64(%#x) = %d, want %d", tt.x, got, tt.want) + } + want := tt.want + if want == 64 { + want = 32 + } + if got := bits.TrailingZeros32(uint32(tt.x)); got != want { + t.Errorf("TrailingZeros64(%#x) = %d, want %d", tt.x, got, want) + } + } +} -- GitLab From 5140ad104b03f6c119beb7e74546fb53bf40b66d Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 4 Oct 2021 17:44:56 -0700 Subject: [PATCH 1448/2500] cmd/compile/internal/types2: update the recorded function type after inference This is a clean port of CL 353831 from go/types to types2. For #47916. Change-Id: I2c2b9c7bbcd416fb21f3032c55a06406bad9334a Reviewed-on: https://go-review.googlesource.com/c/go/+/353934 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/api_test.go | 6 ++++-- src/cmd/compile/internal/types2/call.go | 6 ++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index ca81620a78..4966848ed4 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -328,8 +328,10 @@ func TestTypesInfo(t *testing.T) { // parameterized functions {genericPkg + `p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[generic_p0.T₁ interface{}](generic_p0.T₁)`}, {genericPkg + `p1; func f[T any](T) {}; var _ = f[int]`, `f[int]`, `func(int)`}, - {genericPkg + `p2; func f[T any](T) {}; func _() { f(42) }`, `f`, `func[generic_p2.T₁ interface{}](generic_p2.T₁)`}, - {genericPkg + `p3; func f[T any](T) {}; func _() { f(42) }`, `f(42)`, `()`}, + {genericPkg + `p2; func f[T any](T) {}; func _() { f(42) }`, `f`, `func(int)`}, + {genericPkg + `p3; func f[T any](T) {}; func _() { f[int](42) }`, `f[int]`, `func(int)`}, + {genericPkg + `p4; func f[T any](T) {}; func _() { f[int](42) }`, `f`, `func[generic_p4.T₁ interface{}](generic_p4.T₁)`}, + {genericPkg + `p5; func f[T any](T) {}; func _() { f(42) }`, `f(42)`, `()`}, // type parameters {genericPkg + `t0; type t[] int; var _ t`, `t`, `generic_t0.t`}, // t[] is a syntax error that is ignored in this test in favor of t diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 118e76fdcf..8b45b28017 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -173,8 +173,14 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { // evaluate arguments args, _ := check.exprList(call.ArgList, false) + isGeneric := sig.TypeParams().Len() > 0 sig = check.arguments(call, sig, targs, args) + if isGeneric && sig.TypeParams().Len() == 0 { + // update the recorded type of call.Fun to its instantiated type + check.recordTypeAndValue(call.Fun, value, sig, nil) + } + // determine result switch sig.results.Len() { case 0: -- GitLab From 5d946f1892dc4ae3d3220fb0bc4d61cdf6175ee6 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 5 Oct 2021 10:21:09 -0700 Subject: [PATCH 1449/2500] cmd/compile: add remaining >v1 instructions to v1-only test roundsd and FMA (vfmadd231sd). Change-Id: I2d91332667e577bd9bb903ac58904f62b8454128 Reviewed-on: https://go-review.googlesource.com/c/go/+/354069 Trust: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- .../compile/internal/amd64/versions_test.go | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/amd64/versions_test.go b/src/cmd/compile/internal/amd64/versions_test.go index b47de12efd..de677f3a69 100644 --- a/src/cmd/compile/internal/amd64/versions_test.go +++ b/src/cmd/compile/internal/amd64/versions_test.go @@ -11,6 +11,7 @@ import ( "fmt" "internal/testenv" "io" + "math" "math/bits" "os" "os/exec" @@ -107,7 +108,7 @@ func clobber(t *testing.T, src string, dst *os.File, opcodes map[string]bool) { if err := cmd.Start(); err != nil { t.Fatal(err) } - re = regexp.MustCompile(`^\s*([0-9a-f]+):\s*((?:[0-9a-f][0-9a-f] )+)\s*([a-z]+)`) + re = regexp.MustCompile(`^\s*([0-9a-f]+):\s*((?:[0-9a-f][0-9a-f] )+)\s*([a-z0-9]+)`) } // Find all the instruction addresses we need to edit. @@ -209,7 +210,8 @@ var featureToOpcodes = map[string][]string{ // native objdump doesn't include [QL] on linux. "popcnt": []string{"popcntq", "popcntl", "popcnt"}, "bmi1": []string{"andnq", "andnl", "andn", "blsiq", "blsil", "blsi", "blsmskq", "blsmskl", "blsmsk", "blsrq", "blsrl", "blsr", "tzcntq", "tzcntl", "tzcnt"}, - // TODO: more? + "sse41": []string{"roundsd"}, + "fma": []string{"vfmadd231sd"}, } // Test to use POPCNT instruction, if available @@ -333,3 +335,34 @@ func TestTrailingZeros(t *testing.T) { } } } + +func TestRound(t *testing.T) { + for _, tt := range []struct { + x, want float64 + }{ + {1.4, 1}, + {1.5, 2}, + {1.6, 2}, + {2.4, 2}, + {2.5, 2}, + {2.6, 3}, + } { + if got := math.RoundToEven(tt.x); got != tt.want { + t.Errorf("RoundToEven(%f) = %f, want %f", tt.x, got, tt.want) + } + } +} + +func TestFMA(t *testing.T) { + for _, tt := range []struct { + x, y, z, want float64 + }{ + {2, 3, 4, 10}, + {3, 4, 5, 17}, + } { + if got := math.FMA(tt.x, tt.y, tt.z); got != tt.want { + t.Errorf("FMA(%f,%f,%f) = %f, want %f", tt.x, tt.y, tt.z, got, tt.want) + } + } + +} -- GitLab From 097a82f54d20cb722b8712025caac44c357c1b13 Mon Sep 17 00:00:00 2001 From: nimelehin Date: Wed, 15 Sep 2021 10:31:05 +0300 Subject: [PATCH 1450/2500] cmd/compile: don't emit unnecessary amd64 extension checks In case of amd64 the compiler issues checks if extensions are available on a platform. With GOAMD64 microarchitecture levels provided, some of the checks could be eliminated. Change-Id: If15c178bcae273b2ce7d3673415cb8849292e087 Reviewed-on: https://go-review.googlesource.com/c/go/+/352010 Reviewed-by: Keith Randall Reviewed-by: Matthew Dempsky Run-TryBot: Keith Randall TryBot-Result: Go Bot --- src/cmd/compile/internal/ssagen/ssa.go | 13 +++++++++++++ test/codegen/math.go | 9 +++++++++ test/codegen/mathbits.go | 6 +++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 91e585748e..2d8e21ee05 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -4245,6 +4245,11 @@ func InitTables() { s.vars[n] = s.callResult(n, callNormal) // types.Types[TFLOAT64] return s.variable(n, types.Types[types.TFLOAT64]) } + + if buildcfg.GOAMD64 >= 3 { + return s.newValue3(ssa.OpFMA, types.Types[types.TFLOAT64], args[0], args[1], args[2]) + } + v := s.entryNewValue0A(ssa.OpHasCPUFeature, types.Types[types.TBOOL], ir.Syms.X86HasFMA) b := s.endBlock() b.Kind = ssa.BlockIf @@ -4307,6 +4312,10 @@ func InitTables() { makeRoundAMD64 := func(op ssa.Op) func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { + if buildcfg.GOAMD64 >= 2 { + return s.newValue1(op, types.Types[types.TFLOAT64], args[0]) + } + v := s.entryNewValue0A(ssa.OpHasCPUFeature, types.Types[types.TBOOL], ir.Syms.X86HasSSE41) b := s.endBlock() b.Kind = ssa.BlockIf @@ -4513,6 +4522,10 @@ func InitTables() { makeOnesCountAMD64 := func(op ssa.Op) func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { + if buildcfg.GOAMD64 >= 2 { + return s.newValue1(op, types.Types[types.TINT], args[0]) + } + v := s.entryNewValue0A(ssa.OpHasCPUFeature, types.Types[types.TBOOL], ir.Syms.X86HasPOPCNT) b := s.endBlock() b.Kind = ssa.BlockIf diff --git a/test/codegen/math.go b/test/codegen/math.go index df2ebd79e1..ad154e0c40 100644 --- a/test/codegen/math.go +++ b/test/codegen/math.go @@ -11,6 +11,8 @@ import "math" var sink64 [8]float64 func approx(x float64) { + // amd64/v2:-".*x86HasSSE41" amd64/v3:-".*x86HasSSE41" + // amd64:"ROUNDSD\t[$]2" // s390x:"FIDBR\t[$]6" // arm64:"FRINTPD" // ppc64:"FRIP" @@ -18,6 +20,8 @@ func approx(x float64) { // wasm:"F64Ceil" sink64[0] = math.Ceil(x) + // amd64/v2:-".*x86HasSSE41" amd64/v3:-".*x86HasSSE41" + // amd64:"ROUNDSD\t[$]1" // s390x:"FIDBR\t[$]7" // arm64:"FRINTMD" // ppc64:"FRIM" @@ -31,6 +35,8 @@ func approx(x float64) { // ppc64le:"FRIN" sink64[2] = math.Round(x) + // amd64/v2:-".*x86HasSSE41" amd64/v3:-".*x86HasSSE41" + // amd64:"ROUNDSD\t[$]3" // s390x:"FIDBR\t[$]5" // arm64:"FRINTZD" // ppc64:"FRIZ" @@ -38,6 +44,8 @@ func approx(x float64) { // wasm:"F64Trunc" sink64[3] = math.Trunc(x) + // amd64/v2:-".*x86HasSSE41" amd64/v3:-".*x86HasSSE41" + // amd64:"ROUNDSD\t[$]0" // s390x:"FIDBR\t[$]4" // arm64:"FRINTND" // wasm:"F64Nearest" @@ -123,6 +131,7 @@ func copysign(a, b, c float64) { } func fma(x, y, z float64) float64 { + // amd64/v3:-".*x86HasFMA" // amd64:"VFMADD231SD" // arm/6:"FMULAD" // arm64:"FMADDD" diff --git a/test/codegen/mathbits.go b/test/codegen/mathbits.go index 50527fea04..2d8790c1de 100644 --- a/test/codegen/mathbits.go +++ b/test/codegen/mathbits.go @@ -118,8 +118,9 @@ func Len8(n uint8) int { // bits.OnesCount // // -------------------- // -// TODO(register args) Restore a m d 6 4 :.*x86HasPOPCNT when only one ABI is tested. +// TODO(register args) Restore a m d 6 4 / v 1 :.*x86HasPOPCNT when only one ABI is tested. func OnesCount(n uint) int { + // amd64/v2:-".*x86HasPOPCNT" amd64/v3:-".*x86HasPOPCNT" // amd64:"POPCNTQ" // arm64:"VCNT","VUADDLV" // s390x:"POPCNT" @@ -130,6 +131,7 @@ func OnesCount(n uint) int { } func OnesCount64(n uint64) int { + // amd64/v2:-".*x86HasPOPCNT" amd64/v3:-".*x86HasPOPCNT" // amd64:"POPCNTQ" // arm64:"VCNT","VUADDLV" // s390x:"POPCNT" @@ -140,6 +142,7 @@ func OnesCount64(n uint64) int { } func OnesCount32(n uint32) int { + // amd64/v2:-".*x86HasPOPCNT" amd64/v3:-".*x86HasPOPCNT" // amd64:"POPCNTL" // arm64:"VCNT","VUADDLV" // s390x:"POPCNT" @@ -150,6 +153,7 @@ func OnesCount32(n uint32) int { } func OnesCount16(n uint16) int { + // amd64/v2:-".*x86HasPOPCNT" amd64/v3:-".*x86HasPOPCNT" // amd64:"POPCNTL" // arm64:"VCNT","VUADDLV" // s390x:"POPCNT" -- GitLab From 7e69c5decf0b95ce2856769b9798c3a1cf3078ee Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 5 Oct 2021 10:29:21 -0700 Subject: [PATCH 1451/2500] cmd/compile/internal/types2: implement generic slice expressions For now, the constraint's underlying type set must be a single type that is sliceable. Change-Id: I08b6a2e88fe35e8238a95b3f40dc969689021a0f Reviewed-on: https://go-review.googlesource.com/c/go/+/354070 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/cmd/compile/internal/types2/index.go | 7 +------ .../compile/internal/types2/testdata/check/typeparams.go2 | 8 ++++++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index 848a70dea8..47a5e50f62 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -207,7 +207,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { valid := false length := int64(-1) // valid if >= 0 - switch typ := under(x.typ).(type) { + switch typ := optype(x.typ).(type) { case *Basic: if isString(typ) { if e.Full { @@ -246,11 +246,6 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { case *Slice: valid = true // x.typ doesn't change - - case *TypeParam: - check.error(x, "generic slice expressions not yet implemented") - x.mode = invalid - return } if !valid { diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 index 69b6925b9f..29c25b0bb4 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 @@ -115,9 +115,13 @@ func _[T interface{ [10]byte | string }](x T, i int) { _ = x[i]; _ = x[9]; _ = x func _[T interface{ [10]int | *[20]int | []int }](x T, i int) { _ = x[i]; _ = x[9]; _ = x[10 /* ERROR out of bounds */ ] } // slicing -// TODO(gri) implement this -func _[T interface{ ~string }] (x T, i, j, k int) { _ = x /* ERROR generic slice expressions not yet implemented */ [i:j:k] } +func _[T interface{ ~[10]E }, E any] (x T, i, j, k int) { var _ []E = x[i:j] } +func _[T interface{ ~[10]E }, E any] (x T, i, j, k int) { var _ []E = x[i:j:k] } +func _[T interface{ ~[]byte }] (x T, i, j, k int) { var _ T = x[i:j] } +func _[T interface{ ~[]byte }] (x T, i, j, k int) { var _ T = x[i:j:k] } +func _[T interface{ ~string }] (x T, i, j, k int) { var _ T = x[i:j] } +func _[T interface{ ~string }] (x T, i, j, k int) { var _ T = x /* ERROR 3-index slice of string */ [i:j:k] } // len/cap built-ins -- GitLab From ae83301ab21fd3a0664d1277ee7b313cbf6590d9 Mon Sep 17 00:00:00 2001 From: Lynn Boger Date: Mon, 4 Oct 2021 12:13:41 -0500 Subject: [PATCH 1452/2500] internal/buildcfg: enable register ABI for PPC64 This enables the new register ABI for all PPC64 targets by default including linux/ppc64, linux/ppc64le, and aix/ppc64. Improvements with the new register ABI on a power9: name old time/op (ns/op) new time/op (ns/op) delta BinaryTree17 3882070000 3274900000 -15.64% Fannkuch11 3787620000 3614740000 -4.56% FmtFprintfEmpty 58.705 51.1875 -12.81% FmtFprintfString 101.675 94.4725 -7.08% FmtFprintfInt 112.725 104.075 -7.67% FmtFprintfIntInt 166.475 158.05 -5.06% FmtFprintfPrefixedInt 183.7 178.975 -2.57% FmtFprintfFloat 246.55 258.8 +4.97% FmtManyArgs 648.325 665.875 +2.71% GobDecode 8004660 6802210 -15.02% GobEncode 7289780 5675710 -22.14% Gzip 326931000 323586000 -1.02% Gunzip 47544700 37808000 -20.48% HTTPClientServer 46927.2 42357.8 -9.74% JSONEncode 12098300 9621450 -20.47% JSONDecode 62305300 55410200 -11.07% Mandelbrot200 5841540 5934590 +1.59% GoParse 5594880 4003360 -28.45% RegexpMatchEasy0_32 96.185 89.6325 -6.81% RegexpMatchEasy0_1K 255.775 210.45 -17.72% RegexpMatchEasy1_32 102.95 93.8825 -8.81% RegexpMatchEasy1_1K 511.65 385.075 -24.74% RegexpMatchMedium_32 1414.75 1236.75 -12.58% RegexpMatchMedium_1K 42114.5 37022.5 -12.09% RegexpMatchHard_32 2110.5 1901.5 -9.90% RegexpMatchHard_1K 63559.5 59494 -6.40% Revcomp 532981000 480640000 -9.82% Template 81903600 65743300 -19.73% TimeParse 310.75 276.525 -11.01% TimeFormat 483.4 355.475 -26.46% Change-Id: Ib7c5dfe8ddc2f17050943912048f55667dabde39 Reviewed-on: https://go-review.googlesource.com/c/go/+/353969 Trust: Lynn Boger Reviewed-by: Cherry Mui --- src/internal/buildcfg/exp.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go index 7cbe4c804d..043d079cf6 100644 --- a/src/internal/buildcfg/exp.go +++ b/src/internal/buildcfg/exp.go @@ -46,7 +46,11 @@ var FramePointerEnabled = GOARCH == "amd64" || GOARCH == "arm64" // // TODO(mdempsky): Move to internal/goexperiment. func ParseGOEXPERIMENT(goos, goarch, goexp string) (flags, baseline goexperiment.Flags, err error) { - regabiSupported := goarch == "amd64" || goarch == "arm64" + regabiSupported := false + switch goarch { + case "amd64", "arm64", "ppc64le", "ppc64": + regabiSupported = true + } baseline = goexperiment.Flags{ RegabiWrappers: regabiSupported, @@ -112,7 +116,7 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (flags, baseline goexperiment flags.RegabiArgs = true } // regabi is only supported on amd64, arm64, ppc64 and ppc64le. - if goarch != "amd64" && goarch != "arm64" && goarch != "ppc64le" && goarch != "ppc64" { + if !regabiSupported { flags.RegabiReflect = false flags.RegabiArgs = false } -- GitLab From 3100dc1a7fe3f3302cf2419298b0585bc8e83890 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 27 Sep 2021 14:27:20 -0700 Subject: [PATCH 1453/2500] cmd/link,runtime: remove relocations from stkobjs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use an offset from go.func.* instead. This removes the last relocation from funcdata symbols, which lets us simplify that code. size before after Δ % addr2line 3683218 3680706 -2512 -0.068% api 4951074 4944850 -6224 -0.126% asm 4744258 4757586 +13328 +0.281% buildid 2419986 2418546 -1440 -0.060% cgo 4218306 4197346 -20960 -0.497% compile 22132066 22076882 -55184 -0.249% cover 4432834 4411362 -21472 -0.484% dist 3111202 3091346 -19856 -0.638% doc 3583602 3563234 -20368 -0.568% fix 3023922 3020658 -3264 -0.108% link 6188034 6164642 -23392 -0.378% nm 3665826 3646818 -19008 -0.519% objdump 4015234 4012450 -2784 -0.069% pack 2155010 2153554 -1456 -0.068% pprof 13044178 13011522 -32656 -0.250% test2json 2402146 2383906 -18240 -0.759% trace 9765410 9736514 -28896 -0.296% vet 6681250 6655058 -26192 -0.392% total 104217556 103926980 -290576 -0.279% relocs before after Δ % addr2line 25563 25066 -497 -1.944% api 18409 17176 -1233 -6.698% asm 18903 18271 -632 -3.343% buildid 9513 9233 -280 -2.943% cgo 17103 16222 -881 -5.151% compile 64825 60421 -4404 -6.794% cover 19464 18479 -985 -5.061% dist 10798 10135 -663 -6.140% doc 13503 12735 -768 -5.688% fix 11465 10820 -645 -5.626% link 23214 21849 -1365 -5.880% nm 25480 24987 -493 -1.935% objdump 26610 26057 -553 -2.078% pack 7951 7665 -286 -3.597% pprof 63964 60761 -3203 -5.008% test2json 8735 8389 -346 -3.961% trace 39639 37180 -2459 -6.203% vet 25970 24044 -1926 -7.416% total 431108 409489 -21619 -5.015% Change-Id: I43c26196a008da6d1cb3a782eea2f428778bd569 Reviewed-on: https://go-review.googlesource.com/c/go/+/353138 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/compile/internal/liveness/plive.go | 2 +- src/cmd/link/internal/ld/data.go | 5 ++ src/cmd/link/internal/ld/pcln.go | 22 ++----- src/cmd/link/internal/ld/symtab.go | 15 +---- src/runtime/mgcmark.go | 7 ++- src/runtime/proc.go | 1 + src/runtime/stack.go | 68 +++++++++++++++------- src/runtime/symtab.go | 9 +-- 8 files changed, 69 insertions(+), 60 deletions(-) diff --git a/src/cmd/compile/internal/liveness/plive.go b/src/cmd/compile/internal/liveness/plive.go index dc778a6fb9..e358155a34 100644 --- a/src/cmd/compile/internal/liveness/plive.go +++ b/src/cmd/compile/internal/liveness/plive.go @@ -1443,7 +1443,7 @@ func (lv *liveness) emitStackObjects() *obj.LSym { } off = objw.Uint32(x, off, uint32(sz)) off = objw.Uint32(x, off, uint32(ptrdata)) - off = objw.SymPtr(x, off, lsym, 0) + off = objw.SymPtrOff(x, off, lsym) } if base.Flag.Live != 0 { diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 8de0e0df1a..4f0ce23ce7 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -1367,6 +1367,11 @@ func (state *dodataState) makeRelroForSharedLib(target *Link) { // the relro data. isRelro = true } + case sym.SGOFUNC: + // The only SGOFUNC symbols that contain relocations are .stkobj, + // and their relocations are of type objabi.R_ADDROFF, + // which always get resolved during linking. + isRelro = false } if isRelro { state.setSymType(s, symnrelro) diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index b041174cfe..b5a66b8517 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -711,7 +711,7 @@ func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSym ldr := ctxt.loader deferReturnSym := ldr.Lookup("runtime.deferreturn", abiInternalVer) gofunc := ldr.Lookup("go.func.*", 0) - gofuncrel := ldr.Lookup("go.funcrel.*", 0) + gofuncBase := ldr.SymValue(gofunc) textStart := ldr.SymValue(ldr.Lookup("runtime.text", 0)) funcdata := []loader.Sym{} var pcsp, pcfile, pcline, pcinline loader.Sym @@ -813,24 +813,10 @@ func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSym continue } - outer := ldr.OuterSym(fdsym) - if outer == 0 { - panic(fmt.Sprintf("no carrier sym for symbol %s (funcdata %s#%d)", ldr.SymName(fdsym), ldr.SymName(s), j)) + if outer := ldr.OuterSym(fdsym); outer != gofunc { + panic(fmt.Sprintf("bad carrier sym for symbol %s (funcdata %s#%d), want go.func.* got %s", ldr.SymName(fdsym), ldr.SymName(s), j, ldr.SymName(outer))) } - rel := uint32(ldr.SymValue(fdsym) - ldr.SymValue(outer)) - // Record gofunc vs gofuncrel in bottom bit. See runtime/symtab.go:funcdata. - // TODO: The only symbols that in gofuncrel are .stkobj symbols. - // Remove those relocations, and simplify this. - rel <<= 1 - switch outer { - case gofunc: - case gofuncrel: - rel |= 1 - default: - panic(fmt.Sprintf("expected symbol %s (funcdata %s#%d) to be placed in go.func.* or go.funcrel.*, got %s (%d)", - ldr.SymName(fdsym), ldr.SymName(s), j, ldr.SymName(outer), outer)) - } - sb.SetUint32(ctxt.Arch, int64(dataoff), rel) + sb.SetUint32(ctxt.Arch, int64(dataoff), uint32(ldr.SymValue(fdsym)-gofuncBase)) } } } diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index c582e4908d..878d30b5f1 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -569,13 +569,8 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { strings.HasSuffix(name, ".args_stackmap"), strings.HasSuffix(name, ".stkobj"): ldr.SetAttrNotInSymbolTable(s, true) - if ctxt.UseRelro() && strings.HasSuffix(name, ".stkobj") { - symGroupType[s] = sym.SGOFUNCRELRO - ldr.SetCarrierSym(s, symgofuncrel) - } else { - symGroupType[s] = sym.SGOFUNC - ldr.SetCarrierSym(s, symgofunc) - } + symGroupType[s] = sym.SGOFUNC + ldr.SetCarrierSym(s, symgofunc) if ctxt.Debugvlog != 0 { align := ldr.SymAlign(s) liveness += (ldr.SymSize(s) + int64(align) - 1) &^ (int64(align) - 1) @@ -676,12 +671,8 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.gcbss", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.types", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.etypes", 0)) + moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.rodata", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("go.func.*", 0)) - if gofuncrel := ldr.Lookup("go.funcrel.*", 0); gofuncrel != 0 { - moduledata.AddAddr(ctxt.Arch, gofuncrel) - } else { - moduledata.AddUint(ctxt.Arch, 0) - } if ctxt.IsAIX() && ctxt.IsExternal() { // Add R_XCOFFREF relocation to prevent ld's garbage collection of diff --git a/src/runtime/mgcmark.go b/src/runtime/mgcmark.go index eb5221443e..246907e538 100644 --- a/src/runtime/mgcmark.go +++ b/src/runtime/mgcmark.go @@ -803,7 +803,7 @@ func scanstack(gp *g, gcw *gcWork) { println() printunlock() } - gcdata := r.gcdata + gcdata := r.gcdata() var s *mspan if r.useGCProg() { // This path is pretty unlikely, an object large enough @@ -923,7 +923,8 @@ func scanframeworker(frame *stkframe, state *stackScanState, gcw *gcWork) { // varp is 0 for defers, where there are no locals. // In that case, there can't be a pointer to its args, either. // (And all args would be scanned above anyway.) - for i, obj := range objs { + for i := range objs { + obj := &objs[i] off := obj.off base := frame.varp // locals base pointer if off >= 0 { @@ -937,7 +938,7 @@ func scanframeworker(frame *stkframe, state *stackScanState, gcw *gcWork) { if stackTraceDebug { println("stkobj at", hex(ptr), "of size", obj.size) } - state.addObject(ptr, &objs[i]) + state.addObject(ptr, obj) } } } diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 2f619f93d3..aa2ba96c8f 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -687,6 +687,7 @@ func schedinit() { modulesinit() // provides activeModules typelinksinit() // uses maps, activeModules itabsinit() // uses activeModules + stkobjinit() // must run before GC starts sigsave(&_g_.m.sigmask) initSigmask = _g_.m.sigmask diff --git a/src/runtime/stack.go b/src/runtime/stack.go index 0946e6975a..efaa799022 100644 --- a/src/runtime/stack.go +++ b/src/runtime/stack.go @@ -691,7 +691,8 @@ func adjustframe(frame *stkframe, arg unsafe.Pointer) bool { // Adjust pointers in all stack objects (whether they are live or not). // See comments in mgcmark.go:scanframeworker. if frame.varp != 0 { - for _, obj := range objs { + for i := range objs { + obj := &objs[i] off := obj.off base := frame.varp // locals base pointer if off >= 0 { @@ -705,7 +706,7 @@ func adjustframe(frame *stkframe, arg unsafe.Pointer) bool { continue } ptrdata := obj.ptrdata() - gcdata := obj.gcdata + gcdata := obj.gcdata() var s *mspan if obj.useGCProg() { // See comments in mgcmark.go:scanstack @@ -1321,7 +1322,7 @@ func getStackMap(frame *stkframe, cache *pcvalueCache, debug bool) (locals, args // We don't actually use argmap in this case, but we need to fake the stack object // record for these frames which contain an internal/abi.RegArgs at a hard-coded offset. // This offset matches the assembly code on amd64 and arm64. - objs = methodValueCallFrameObjs + objs = methodValueCallFrameObjs[:] } else { p := funcdata(f, _FUNCDATA_StackObjects) if p != nil { @@ -1340,23 +1341,33 @@ func getStackMap(frame *stkframe, cache *pcvalueCache, debug bool) (locals, args return } -var ( - abiRegArgsEface interface{} = abi.RegArgs{} - abiRegArgsType *_type = efaceOf(&abiRegArgsEface)._type - methodValueCallFrameObjs = []stackObjectRecord{ - { - off: -int32(alignUp(abiRegArgsType.size, 8)), // It's always the highest address local. - size: int32(abiRegArgsType.size), - _ptrdata: int32(abiRegArgsType.ptrdata), - gcdata: abiRegArgsType.gcdata, - }, - } -) +var methodValueCallFrameObjs [1]stackObjectRecord // initialized in stackobjectinit -func init() { +func stkobjinit() { + var abiRegArgsEface interface{} = abi.RegArgs{} + abiRegArgsType := efaceOf(&abiRegArgsEface)._type if abiRegArgsType.kind&kindGCProg != 0 { throw("abiRegArgsType needs GC Prog, update methodValueCallFrameObjs") } + // Set methodValueCallFrameObjs[0].gcdataoff so that + // stackObjectRecord.gcdata() will work correctly with it. + ptr := uintptr(unsafe.Pointer(&methodValueCallFrameObjs[0])) + var mod *moduledata + for datap := &firstmoduledata; datap != nil; datap = datap.next { + if datap.gofunc <= ptr && ptr < datap.end { + mod = datap + break + } + } + if mod == nil { + throw("methodValueCallFrameObjs is not in a module") + } + methodValueCallFrameObjs[0] = stackObjectRecord{ + off: -int32(alignUp(abiRegArgsType.size, 8)), // It's always the highest address local. + size: int32(abiRegArgsType.size), + _ptrdata: int32(abiRegArgsType.ptrdata), + gcdataoff: uint32(uintptr(unsafe.Pointer(abiRegArgsType.gcdata)) - mod.rodata), + } } // A stackObjectRecord is generated by the compiler for each stack object in a stack frame. @@ -1365,10 +1376,10 @@ type stackObjectRecord struct { // offset in frame // if negative, offset from varp // if non-negative, offset from argp - off int32 - size int32 - _ptrdata int32 // ptrdata, or -ptrdata is GC prog is used - gcdata *byte // pointer map or GC prog of the type + off int32 + size int32 + _ptrdata int32 // ptrdata, or -ptrdata is GC prog is used + gcdataoff uint32 // offset to gcdata from moduledata.rodata } func (r *stackObjectRecord) useGCProg() bool { @@ -1383,6 +1394,23 @@ func (r *stackObjectRecord) ptrdata() uintptr { return uintptr(x) } +// gcdata returns pointer map or GC prog of the type. +func (r *stackObjectRecord) gcdata() *byte { + ptr := uintptr(unsafe.Pointer(r)) + var mod *moduledata + for datap := &firstmoduledata; datap != nil; datap = datap.next { + if datap.gofunc <= ptr && ptr < datap.end { + mod = datap + break + } + } + // If you get a panic here due to a nil mod, + // you may have made a copy of a stackObjectRecord. + // You must use the original pointer. + res := mod.rodata + uintptr(r.gcdataoff) + return (*byte)(unsafe.Pointer(res)) +} + // This is exported as ABI0 via linkname so obj can call it. // //go:nosplit diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 8f7b439dc5..cbfe604f1b 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -427,7 +427,8 @@ type moduledata struct { noptrbss, enoptrbss uintptr end, gcdata, gcbss uintptr types, etypes uintptr - gofunc, gofuncrel uintptr // go.func.*, go.funcrel.* + rodata uintptr + gofunc uintptr // go.func.* textsectmap []textsect typelinks []int32 // offsets from types @@ -1092,11 +1093,7 @@ func funcdata(f funcInfo, i uint8) unsafe.Pointer { if off == ^uint32(0) { return nil } - base := f.datap.gofunc - if off&1 != 0 { - base = f.datap.gofuncrel - } - return unsafe.Pointer(base + uintptr(off>>1)) + return unsafe.Pointer(f.datap.gofunc + uintptr(off)) } // step advances to the next pc, value pair in the encoded table. -- GitLab From c1a0aa300a1003ab823d5633e521e064a063271c Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 4 Oct 2021 15:51:22 -0700 Subject: [PATCH 1454/2500] cmd/compile: make stkobj symbols content-addressable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Shrinks binaries a little bit. size before after Δ % api 4892370 4875858 -16512 -0.338% asm 4711218 4694706 -16512 -0.350% cgo 4164770 4148258 -16512 -0.396% compile 21875922 21826386 -49536 -0.226% cover 4358370 4341858 -16512 -0.379% doc 3532562 3516050 -16512 -0.467% link 6110786 6094274 -16512 -0.270% objdump 3982914 3966402 -16512 -0.415% pprof 12869986 12836962 -33024 -0.257% trace 9614626 9598114 -16512 -0.172% vet 6580322 6563810 -16512 -0.251% total 102897284 102666116 -231168 -0.225% Change-Id: Idf4ba3c05e35ec1d1ae957d6ded00ae79cc0fd2a Reviewed-on: https://go-review.googlesource.com/c/go/+/172198 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/compile/internal/liveness/plive.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cmd/compile/internal/liveness/plive.go b/src/cmd/compile/internal/liveness/plive.go index e358155a34..56580d11b5 100644 --- a/src/cmd/compile/internal/liveness/plive.go +++ b/src/cmd/compile/internal/liveness/plive.go @@ -1417,6 +1417,7 @@ func (lv *liveness) emitStackObjects() *obj.LSym { // Populate the stack object data. // Format must match runtime/stack.go:stackObjectRecord. x := base.Ctxt.Lookup(lv.fn.LSym.Name + ".stkobj") + x.Set(obj.AttrContentAddressable, true) lv.fn.LSym.Func().StackObjects = x off := 0 off = objw.Uintptr(x, off, uint64(len(vars))) -- GitLab From 7ae83c8f38bc79e999a8657da443d815036c7d72 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 5 Oct 2021 11:45:22 -0700 Subject: [PATCH 1455/2500] go/types: implement generic slice expressions This is a clean port of CL 354070 from types2 to go/types. Change-Id: I44de1b8e6c0177e2a33e7f36a82465dc520c35aa Reviewed-on: https://go-review.googlesource.com/c/go/+/354092 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley TryBot-Result: Go Bot --- src/go/types/index.go | 7 +------ src/go/types/testdata/check/typeparams.go2 | 8 ++++++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/go/types/index.go b/src/go/types/index.go index ca04072f7a..613f6292e4 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -207,7 +207,7 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { valid := false length := int64(-1) // valid if >= 0 - switch typ := under(x.typ).(type) { + switch typ := optype(x.typ).(type) { case *Basic: if isString(typ) { if e.Slice3 { @@ -246,11 +246,6 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { case *Slice: valid = true // x.typ doesn't change - - case *TypeParam: - check.errorf(x, _Todo, "generic slice expressions not yet implemented") - x.mode = invalid - return } if !valid { diff --git a/src/go/types/testdata/check/typeparams.go2 b/src/go/types/testdata/check/typeparams.go2 index bfacb3e1e7..10f84314fd 100644 --- a/src/go/types/testdata/check/typeparams.go2 +++ b/src/go/types/testdata/check/typeparams.go2 @@ -115,9 +115,13 @@ func _[T interface{ [10]byte | string }](x T, i int) { _ = x[i]; _ = x[9]; _ = x func _[T interface{ [10]int | *[20]int | []int }](x T, i int) { _ = x[i]; _ = x[9]; _ = x[10 /* ERROR out of bounds */ ] } // slicing -// TODO(gri) implement this -func _[T interface{ ~string }] (x T, i, j, k int) { _ = x /* ERROR generic slice expressions not yet implemented */ [i:j:k] } +func _[T interface{ ~[10]E }, E any] (x T, i, j, k int) { var _ []E = x[i:j] } +func _[T interface{ ~[10]E }, E any] (x T, i, j, k int) { var _ []E = x[i:j:k] } +func _[T interface{ ~[]byte }] (x T, i, j, k int) { var _ T = x[i:j] } +func _[T interface{ ~[]byte }] (x T, i, j, k int) { var _ T = x[i:j:k] } +func _[T interface{ ~string }] (x T, i, j, k int) { var _ T = x[i:j] } +func _[T interface{ ~string }] (x T, i, j, k int) { var _ T = x /* ERROR 3-index slice of string */ [i:j:k] } // len/cap built-ins -- GitLab From 0b4d4998d57936cf8bb2566f5f3e36eb70892ca4 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Tue, 5 Oct 2021 13:05:09 -0400 Subject: [PATCH 1456/2500] testing: document f.Fuzz requirement to not change underlying data Updates #48606 Change-Id: I6d555fdefccd842fb65ec8d630b4808bcb54a825 Reviewed-on: https://go-review.googlesource.com/c/go/+/353977 Trust: Katie Hockman Run-TryBot: Katie Hockman Reviewed-by: Jay Conrod --- src/testing/fuzz.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 771917b069..60e2603da9 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -299,11 +299,12 @@ var supportedTypes = map[reflect.Type]bool{ // This function sould be fast and deterministic, and its behavior should not // depend on shared state. No mutatable input arguments, or pointers to them, // should be retained between executions of the fuzz function, as the memory -// backing them may be mutated during a subsequent invocation. +// backing them may be mutated during a subsequent invocation. ff must not +// modify the underlying data of the arguments provided by the fuzzing engine. // -// When fuzzing, F.Fuzz does not return until a problem is found, time runs -// out (set with -fuzztime), or the test process is interrupted by a signal. -// F.Fuzz should be called exactly once unless F.Skip or F.Fail is called. +// When fuzzing, F.Fuzz does not return until a problem is found, time runs out +// (set with -fuzztime), or the test process is interrupted by a signal. F.Fuzz +// should be called exactly once, unless F.Skip or F.Fail is called beforehand. func (f *F) Fuzz(ff interface{}) { if f.fuzzCalled { panic("testing: F.Fuzz called more than once") -- GitLab From 75773b0e7b4dac6b779e869a13096a7b7f0be5bb Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 5 Oct 2021 09:40:15 -0700 Subject: [PATCH 1457/2500] runtime: add BenchmarkStackCopyWithStkobj For benchmarking and improving recent stkobj-related changes. Co-Authored-By: Cherry Mui Change-Id: I34c8b1a09e4cf98547460882b0d3908158269f57 Reviewed-on: https://go-review.googlesource.com/c/go/+/354071 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/stack_test.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/runtime/stack_test.go b/src/runtime/stack_test.go index 43fc5cac55..3f02243a1e 100644 --- a/src/runtime/stack_test.go +++ b/src/runtime/stack_test.go @@ -585,6 +585,34 @@ func count21(n int) int { return 1 + count22(n-1) } func count22(n int) int { return 1 + count23(n-1) } func count23(n int) int { return 1 + count1(n-1) } +type stkobjT struct { + p *stkobjT + x int64 + y [20]int // consume some stack +} + +// Sum creates a linked list of stkobjTs. +func Sum(n int64, p *stkobjT) { + if n == 0 { + return + } + s := stkobjT{p: p, x: n} + Sum(n-1, &s) + p.x += s.x +} + +func BenchmarkStackCopyWithStkobj(b *testing.B) { + c := make(chan bool) + for i := 0; i < b.N; i++ { + go func() { + var s stkobjT + Sum(100000, &s) + c <- true + }() + <-c + } +} + type structWithMethod struct{} func (s structWithMethod) caller() string { -- GitLab From 113b52979f48331b611e0fe7dadff97d6393ca27 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 5 Oct 2021 10:21:54 -0700 Subject: [PATCH 1458/2500] runtime: remove a branch from funcdata MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit name old time/op new time/op delta StackCopyWithStkobj-8 12.1ms ± 7% 11.6ms ± 8% -3.88% (p=0.002 n=19+19) Change-Id: Idf810017d541eba70bcf9c736267de9efae916d5 Reviewed-on: https://go-review.googlesource.com/c/go/+/354072 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/symtab.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index cbfe604f1b..f423957f88 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -1090,10 +1090,15 @@ func funcdata(f funcInfo, i uint8) unsafe.Pointer { } p = add(p, uintptr(i)*4) off := *(*uint32)(p) + // Return off == ^uint32(0) ? 0 : f.datap.gofunc + uintptr(off), but without branches. + // The compiler calculates mask on most architectures using conditional assignment. + var mask uintptr if off == ^uint32(0) { - return nil + mask = 1 } - return unsafe.Pointer(f.datap.gofunc + uintptr(off)) + mask-- + raw := f.datap.gofunc + uintptr(off) + return unsafe.Pointer(raw & mask) } // step advances to the next pc, value pair in the encoded table. -- GitLab From 990c9c6cabad6a083ac67c591a38f73d00850da8 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 5 Oct 2021 11:31:57 -0700 Subject: [PATCH 1459/2500] Revert "runtime: use unsafe.Slice in getStackMap" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit golang.org/cl/352953. Reason for revert: unsafe.Slice is considerably slower. Part of this is extra safety checks (good), but most of it is the function call overhead. We should consider open-coding it (#48798). Impact of this change: name old time/op new time/op delta StackCopyWithStkobj-8 12.1ms ± 5% 11.6ms ± 3% -4.03% (p=0.009 n=10+8) Change-Id: Ib2448e3edac25afd8fb55ffbea073b8b11521bde Reviewed-on: https://go-review.googlesource.com/c/go/+/354090 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/runtime/stack.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/runtime/stack.go b/src/runtime/stack.go index efaa799022..284c6b3b84 100644 --- a/src/runtime/stack.go +++ b/src/runtime/stack.go @@ -1328,8 +1328,7 @@ func getStackMap(frame *stkframe, cache *pcvalueCache, debug bool) (locals, args if p != nil { n := *(*uintptr)(p) p = add(p, goarch.PtrSize) - r0 := (*stackObjectRecord)(noescape(p)) - objs = unsafe.Slice(r0, int(n)) + *(*slice)(unsafe.Pointer(&objs)) = slice{array: noescape(p), len: int(n), cap: int(n)} // Note: the noescape above is needed to keep // getStackMap from "leaking param content: // frame". That leak propagates up to getgcmask, then -- GitLab From 0d6561b72b8bd837e4691346579880a7ef7fc18a Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Tue, 5 Oct 2021 16:11:17 -0400 Subject: [PATCH 1460/2500] cmd/go: do not check for a built binary in TestScript/mod_get_fossil This test hasn't passed since CL 349997, but the failure was not detected because the Go project's builders do not have a 'fossil' binary installed (#48802). For #43684 Change-Id: I25544574ab48f4f146ae3795e541179e78815758 Reviewed-on: https://go-review.googlesource.com/c/go/+/354149 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills Reviewed-by: Russ Cox TryBot-Result: Go Bot --- src/cmd/go/testdata/script/mod_get_fossil.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cmd/go/testdata/script/mod_get_fossil.txt b/src/cmd/go/testdata/script/mod_get_fossil.txt index baad544557..c2d42f0f59 100644 --- a/src/cmd/go/testdata/script/mod_get_fossil.txt +++ b/src/cmd/go/testdata/script/mod_get_fossil.txt @@ -18,11 +18,10 @@ env GOSUMDB=off env USER=fossiluser env FOSSIL_HOME=$WORK/home -# Attempting to get the latest version of a fossil repo. +# Attempt to get the latest version of a fossil repo. go get vcs-test.golang.org/fossil/hello.fossil ! stderr 'unexpected response from fossil info' grep 'vcs-test.golang.org/fossil/hello.fossil' go.mod -exists $GOPATH/bin/hello.fossil$GOEXE -- go.mod -- module x -- GitLab From 695a59b5139ca8791e19b84259dc85622eea47e8 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 4 Oct 2021 16:15:17 -0700 Subject: [PATCH 1461/2500] test: add test for export/import of recover & defer Add a simple test with an exported generic function that does recover/defer, to test that recover/defer are exported/imported properly (and a generic function with recover/defer works fine). Change-Id: Idc3af101cbb78fc96bf945f1f5eab2740dd8994b Reviewed-on: https://go-review.googlesource.com/c/go/+/353883 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Dan Scales --- test/typeparam/recoverimp.dir/a.go | 16 ++++++++++++++++ test/typeparam/recoverimp.dir/main.go | 12 ++++++++++++ test/typeparam/recoverimp.go | 7 +++++++ test/typeparam/recoverimp.out | 2 ++ 4 files changed, 37 insertions(+) create mode 100644 test/typeparam/recoverimp.dir/a.go create mode 100644 test/typeparam/recoverimp.dir/main.go create mode 100644 test/typeparam/recoverimp.go create mode 100644 test/typeparam/recoverimp.out diff --git a/test/typeparam/recoverimp.dir/a.go b/test/typeparam/recoverimp.dir/a.go new file mode 100644 index 0000000000..a465fd1545 --- /dev/null +++ b/test/typeparam/recoverimp.dir/a.go @@ -0,0 +1,16 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +import "fmt" + +func F[T any](a T) { + defer func() { + if x := recover(); x != nil { + fmt.Printf("panic: %v\n", x) + } + }() + panic(a) +} diff --git a/test/typeparam/recoverimp.dir/main.go b/test/typeparam/recoverimp.dir/main.go new file mode 100644 index 0000000000..c9d8e3cc08 --- /dev/null +++ b/test/typeparam/recoverimp.dir/main.go @@ -0,0 +1,12 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "a" + +func main() { + a.F(5.3) + a.F("hello") +} diff --git a/test/typeparam/recoverimp.go b/test/typeparam/recoverimp.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/recoverimp.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored diff --git a/test/typeparam/recoverimp.out b/test/typeparam/recoverimp.out new file mode 100644 index 0000000000..3c8b38cbae --- /dev/null +++ b/test/typeparam/recoverimp.out @@ -0,0 +1,2 @@ +panic: 5.3 +panic: hello -- GitLab From 55e7f7e12d46292e130a3b48c86bac2a6e5a1739 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 29 Sep 2021 17:47:19 -0700 Subject: [PATCH 1462/2500] cmd/compile: fix problem with methods of instantiated types which are nointerface In the case of a nointerface method on an instantiated type, we still have to call methodWrapper, because methodWrapper generates the actual generic method on the type as well. Currently, we don't call methodWrapper, so the method on the instantiated type never gets filled in. Adjusted the code to still call methodWrapper, but not use the result, in the case of a nointerface method on an instantiated type. Change-Id: I34bca58de2861aa772be04eb8dd7695c5b7f3a77 Reviewed-on: https://go-review.googlesource.com/c/go/+/353369 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Dan Scales --- src/cmd/compile/internal/reflectdata/reflect.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 8503dee60d..a8d911f003 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -329,7 +329,11 @@ func methods(t *types.Type) []*typeSig { if f.Type.Recv() == nil { base.Fatalf("receiver with no type on %v method %v %v", mt, f.Sym, f) } - if f.Nointerface() { + if f.Nointerface() && !t.IsFullyInstantiated() { + // Skip creating method wrappers if f is nointerface. But, if + // t is an instantiated type, we still have to call + // methodWrapper, because methodWrapper generates the actual + // generic method on the type as well. continue } @@ -348,6 +352,11 @@ func methods(t *types.Type) []*typeSig { type_: typecheck.NewMethodType(f.Type, t), mtype: typecheck.NewMethodType(f.Type, nil), } + if f.Nointerface() { + // In the case of a nointerface method on an instantiated + // type, don't actually apppend the typeSig. + continue + } ms = append(ms, sig) } -- GitLab From 8444a545e3d38c2e470df5035ef4b5a9365aaefc Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 5 Oct 2021 11:41:40 -0700 Subject: [PATCH 1463/2500] text/template: only unwrap final and/or value In the last CL I missed the fact that except for the final value the code already unwraps the argument. For #31103 Change-Id: Ic9099aeb50c6b3322fc14a90ac8026c1d8cb1698 Reviewed-on: https://go-review.googlesource.com/c/go/+/354091 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Bryan C. Mills --- src/text/template/exec.go | 14 +++++++++++--- src/text/template/exec_test.go | 2 ++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/text/template/exec.go b/src/text/template/exec.go index 9a4c9e29dd..9ae6fdc3cc 100644 --- a/src/text/template/exec.go +++ b/src/text/template/exec.go @@ -728,13 +728,21 @@ func (s *state) evalCall(dot, fun reflect.Value, isBuiltin bool, node parse.Node for _, arg := range args { v = s.evalArg(dot, argType, arg).Interface().(reflect.Value) if truth(v) == (name == "or") { - return unwrap(v) + // This value was already unwrapped + // by the .Interface().(reflect.Value). + return v } } if final != missingVal { - v = s.validateType(final, argType) + // The last argument to and/or is coming from + // the pipeline. We didn't short circuit on an earlier + // argument, so we are going to return this one. + // We don't have to evaluate final, but we do + // have to check its type. Then, since we are + // going to return it, we have to unwrap it. + v = unwrap(s.validateType(final, argType)) } - return unwrap(v) + return v } // Build the arg list. diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go index 1a839a641b..9c0772945e 100644 --- a/src/text/template/exec_test.go +++ b/src/text/template/exec_test.go @@ -489,6 +489,8 @@ var execTests = []execTest{ {"and pipe-false", "{{0 | and 1}}", "0", nil, true}, {"or pipe-true", "{{1 | or 0}}", "1", nil, true}, {"or pipe-false", "{{0 | or 0}}", "0", nil, true}, + {"and undef", "{{and 1 .Unknown}}", "", nil, true}, + {"or undef", "{{or 0 .Unknown}}", "", nil, true}, {"boolean if", "{{if and true 1 `hi`}}TRUE{{else}}FALSE{{end}}", "TRUE", tVal, true}, {"boolean if not", "{{if and true 1 `hi` | not}}TRUE{{else}}FALSE{{end}}", "FALSE", nil, true}, {"boolean if pipe", "{{if true | not | and 1}}TRUE{{else}}FALSE{{end}}", "FALSE", nil, true}, -- GitLab From 6ae3afa7e784aadea23793b0527bd8880e002d2f Mon Sep 17 00:00:00 2001 From: Archana R Date: Mon, 4 Oct 2021 04:16:50 -0500 Subject: [PATCH 1464/2500] cmd/compile: add prefetch intrinsic support on PPC64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This CL enables intrinsic support to emit the following prefetch instructions for PPC64 platform that are already emitted on other platforms 1. Prefetch - prefetches data from memory address to cache; 2. PrefetchStreamed - prefetches data from memory address, with a hint that this data is being streamed. Benchmarks picked from go/test/bench/garbage Parameters tested with: GOMAXPROCS=8 tree2 -heapsize=1000000000 -cpus=8 tree -n=18 parser peano Performance results with this change on POWER9 name old time/op new time/op delta Tree2-8 75.3ms ± 2% 65.0ms ± 6% -13.61% (p=0.003 n=5+7) Tree-8 576ms ± 2% 576ms ± 1% ~ (p=0.756 n=11+10) Parser-8 3.60s ± 2% 3.59s ± 1% ~ (p=0.818 n=6+6) Peano-8 84.8ms ± 1% 84.6ms ± 1% ~ (p=0.180 n=6+6) Results on POWER8 and POWER10 are similar Change-Id: If4ac95a85aaa7b2266014e1f8fb7cd7440cbf906 Reviewed-on: https://go-review.googlesource.com/c/go/+/353730 Run-TryBot: Lynn Boger TryBot-Result: Go Bot Reviewed-by: Cherry Mui Trust: Michael Knyszek --- src/cmd/compile/internal/ppc64/ssa.go | 7 +++++ src/cmd/compile/internal/ssa/gen/PPC64.rules | 4 +++ src/cmd/compile/internal/ssa/gen/PPC64Ops.go | 5 +++ src/cmd/compile/internal/ssa/opGen.go | 13 ++++++++ src/cmd/compile/internal/ssa/rewritePPC64.go | 32 ++++++++++++++++++++ src/cmd/compile/internal/ssagen/ssa.go | 4 +-- 6 files changed, 63 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/ppc64/ssa.go b/src/cmd/compile/internal/ppc64/ssa.go index c0f58e60b2..98316c16fa 100644 --- a/src/cmd/compile/internal/ppc64/ssa.go +++ b/src/cmd/compile/internal/ppc64/ssa.go @@ -901,6 +901,13 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.To.Type = obj.TYPE_REG p.To.Reg = v.Reg() + case ssa.OpPPC64DCBT: + p := s.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_MEM + p.From.Reg = v.Args[0].Reg() + p.To.Type = obj.TYPE_CONST + p.To.Offset = v.AuxInt + case ssa.OpPPC64MOVWstorezero, ssa.OpPPC64MOVHstorezero, ssa.OpPPC64MOVBstorezero: p := s.Prog(v.Op.Asm()) p.From.Type = obj.TYPE_REG diff --git a/src/cmd/compile/internal/ssa/gen/PPC64.rules b/src/cmd/compile/internal/ssa/gen/PPC64.rules index 0393feb125..4c766df4b3 100644 --- a/src/cmd/compile/internal/ssa/gen/PPC64.rules +++ b/src/cmd/compile/internal/ssa/gen/PPC64.rules @@ -1470,3 +1470,7 @@ && clobber(call) => (Move [sz] dst src mem) +// Prefetch instructions (aux is option: 0 - DCBT ; 8 - DCBT stream) +(PrefetchCache ptr mem) => (DCBT ptr mem [0]) +(PrefetchCacheStreamed ptr mem) => (DCBT ptr mem [8]) + diff --git a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go index 5f84290002..ff9ce64e18 100644 --- a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go @@ -149,6 +149,7 @@ func init() { crgp21 = regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{gp}} gpload = regInfo{inputs: []regMask{gp | sp | sb}, outputs: []regMask{gp}} gploadidx = regInfo{inputs: []regMask{gp | sp | sb, gp}, outputs: []regMask{gp}} + prefreg = regInfo{inputs: []regMask{gp | sp | sb}} gpstore = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb}} gpstoreidx = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb, gp | sp | sb}} gpstorezero = regInfo{inputs: []regMask{gp | sp | sb}} // ppc64.REGZERO is reserved zero value @@ -336,6 +337,10 @@ func init() { {name: "FMOVDloadidx", argLength: 3, reg: fploadidx, asm: "FMOVD", typ: "Float64"}, {name: "FMOVSloadidx", argLength: 3, reg: fploadidx, asm: "FMOVS", typ: "Float32"}, + // Prefetch instruction + // Do prefetch of address generated with arg0 and arg1 with option aux. arg0=addr,arg1=memory, aux=option. + {name: "DCBT", argLength: 2, aux: "Int64", reg: prefreg, asm: "DCBT", hasSideEffects: true}, + // Store bytes in the reverse endian order of the arch into arg0. // These are indexed stores with no offset field in the instruction so the auxint fields are not used. {name: "MOVDBRstore", argLength: 3, reg: gpstore, asm: "MOVDBR", aux: "Sym", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes reverse order diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 6266092f6f..09006c8c85 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -1994,6 +1994,7 @@ const ( OpPPC64MOVDBRloadidx OpPPC64FMOVDloadidx OpPPC64FMOVSloadidx + OpPPC64DCBT OpPPC64MOVDBRstore OpPPC64MOVWBRstore OpPPC64MOVHBRstore @@ -26715,6 +26716,18 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "DCBT", + auxType: auxInt64, + argLen: 2, + hasSideEffects: true, + asm: ppc64.ADCBT, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 + }, + }, + }, { name: "MOVDBRstore", auxType: auxSym, diff --git a/src/cmd/compile/internal/ssa/rewritePPC64.go b/src/cmd/compile/internal/ssa/rewritePPC64.go index 450ea861f3..b278a4cb44 100644 --- a/src/cmd/compile/internal/ssa/rewritePPC64.go +++ b/src/cmd/compile/internal/ssa/rewritePPC64.go @@ -639,6 +639,10 @@ func rewriteValuePPC64(v *Value) bool { return true case OpPopCount8: return rewriteValuePPC64_OpPopCount8(v) + case OpPrefetchCache: + return rewriteValuePPC64_OpPrefetchCache(v) + case OpPrefetchCacheStreamed: + return rewriteValuePPC64_OpPrefetchCacheStreamed(v) case OpRotateLeft16: return rewriteValuePPC64_OpRotateLeft16(v) case OpRotateLeft32: @@ -14005,6 +14009,34 @@ func rewriteValuePPC64_OpPopCount8(v *Value) bool { return true } } +func rewriteValuePPC64_OpPrefetchCache(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] + // match: (PrefetchCache ptr mem) + // result: (DCBT ptr mem [0]) + for { + ptr := v_0 + mem := v_1 + v.reset(OpPPC64DCBT) + v.AuxInt = int64ToAuxInt(0) + v.AddArg2(ptr, mem) + return true + } +} +func rewriteValuePPC64_OpPrefetchCacheStreamed(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] + // match: (PrefetchCacheStreamed ptr mem) + // result: (DCBT ptr mem [8]) + for { + ptr := v_0 + mem := v_1 + v.reset(OpPPC64DCBT) + v.AuxInt = int64ToAuxInt(8) + v.AddArg2(ptr, mem) + return true + } +} func rewriteValuePPC64_OpRotateLeft16(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 2d8e21ee05..08114b7828 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -3897,9 +3897,9 @@ func InitTables() { // Make Prefetch intrinsics for supported platforms // On the unsupported platforms stub function will be eliminated addF("runtime/internal/sys", "Prefetch", makePrefetchFunc(ssa.OpPrefetchCache), - sys.AMD64, sys.ARM64) + sys.AMD64, sys.ARM64, sys.PPC64) addF("runtime/internal/sys", "PrefetchStreamed", makePrefetchFunc(ssa.OpPrefetchCacheStreamed), - sys.AMD64, sys.ARM64) + sys.AMD64, sys.ARM64, sys.PPC64) /******** runtime/internal/atomic ********/ addF("runtime/internal/atomic", "Load", -- GitLab From 96fface83ad69b6d6ad8059d61d232737572e85d Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 5 Oct 2021 21:58:30 +0000 Subject: [PATCH 1465/2500] Revert "cmd/dist: omit cmd/cgo from toolchain1" This reverts commit 81b7ec1ad5b50b8e73a63b44d8c2538154def535. Reason for revert: broke ios builder Change-Id: I7f469161c3c632ae48b7d938d355c9929eaaad92 Reviewed-on: https://go-review.googlesource.com/c/go/+/354135 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: Cherry Mui --- src/cmd/dist/build.go | 2 +- src/cmd/dist/buildtool.go | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go index dca5464e56..39f016e315 100644 --- a/src/cmd/dist/build.go +++ b/src/cmd/dist/build.go @@ -1359,7 +1359,7 @@ func cmdbootstrap() { } // To recap, so far we have built the new toolchain - // (cmd/asm, cmd/compile, cmd/link) + // (cmd/asm, cmd/cgo, cmd/compile, cmd/link) // using Go 1.4's toolchain and go command. // Then we built the new go command (as go_bootstrap) // using the new toolchain and our own build logic (above). diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go index 8d1c914f30..320c62f850 100644 --- a/src/cmd/dist/buildtool.go +++ b/src/cmd/dist/buildtool.go @@ -33,6 +33,7 @@ import ( var bootstrapDirs = []string{ "cmd/asm", "cmd/asm/internal/...", + "cmd/cgo", "cmd/compile", "cmd/compile/internal/...", "cmd/internal/archive", @@ -101,7 +102,6 @@ func bootstrapBuildTools() { mkbuildcfg(pathf("%s/src/internal/buildcfg/zbootstrap.go", goroot)) mkobjabi(pathf("%s/src/cmd/internal/objabi/zbootstrap.go", goroot)) - mkzdefaultcc("", pathf("%s/src/cmd/cgo/zdefaultcc.go", goroot)) // Use $GOROOT/pkg/bootstrap as the bootstrap workspace root. // We use a subdirectory of $GOROOT/pkg because that's the @@ -134,6 +134,12 @@ func bootstrapBuildTools() { } xmkdirall(dst) + if path == "cmd/cgo" { + // Write to src because we need the file both for bootstrap + // and for later in the main build. + mkzdefaultcc("", pathf("%s/zdefaultcc.go", src)) + mkzdefaultcc("", pathf("%s/zdefaultcc.go", dst)) + } return nil } -- GitLab From e31c9ab557e9f5ee20a61914f1a2bf94191997dc Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Fri, 24 Sep 2021 10:57:37 -0700 Subject: [PATCH 1466/2500] cmd/link,runtime: remove functab relocations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use an offset from runtime.text instead. This removes the last relocation from functab generation, which lets us simplify that code. size before after Δ % addr2line 3680818 3652498 -28320 -0.769% api 4944850 4892418 -52432 -1.060% asm 4757586 4711266 -46320 -0.974% buildid 2418546 2392578 -25968 -1.074% cgo 4197346 4164818 -32528 -0.775% compile 22076882 21875890 -200992 -0.910% cover 4411362 4358418 -52944 -1.200% dist 3091346 3062738 -28608 -0.925% doc 3563234 3532610 -30624 -0.859% fix 3020658 2991666 -28992 -0.960% link 6164642 6110834 -53808 -0.873% nm 3646818 3618482 -28336 -0.777% objdump 4012594 3983042 -29552 -0.736% pack 2153554 2128338 -25216 -1.171% pprof 13011666 12870114 -141552 -1.088% test2json 2383906 2357554 -26352 -1.105% trace 9736514 9631186 -105328 -1.082% vet 6655058 6580370 -74688 -1.122% total 103927380 102914820 -1012560 -0.974% relocs before after Δ % addr2line 25069 22709 -2360 -9.414% api 17176 13321 -3855 -22.444% asm 18271 15630 -2641 -14.455% buildid 9233 7352 -1881 -20.373% cgo 16222 13044 -3178 -19.591% compile 60421 46299 -14122 -23.373% cover 18479 14526 -3953 -21.392% dist 10135 7733 -2402 -23.700% doc 12735 9940 -2795 -21.947% fix 10820 8341 -2479 -22.911% link 21849 17785 -4064 -18.600% nm 24988 22642 -2346 -9.389% objdump 26060 23462 -2598 -9.969% pack 7665 5936 -1729 -22.557% pprof 60764 50998 -9766 -16.072% test2json 8389 6431 -1958 -23.340% trace 37180 29382 -7798 -20.974% vet 24044 19055 -4989 -20.749% total 409499 334585 -74914 -18.294% Caching the field size in debug/gosym.funcTab avoids a 20% PCToLine performance regression. name old time/op new time/op delta 115/LineToPC-8 56.4µs ± 3% 57.3µs ± 2% +1.66% (p=0.006 n=15+13) 115/PCToLine-8 188ns ± 2% 190ns ± 3% +1.46% (p=0.030 n=15+15) Change-Id: I2816a1b28e62b01852e3b306f08546f1e56cd5ac Reviewed-on: https://go-review.googlesource.com/c/go/+/352191 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder Reviewed-by: Cherry Mui TryBot-Result: Go Bot --- src/cmd/link/internal/ld/pcln.go | 92 +++++++------------------------- src/debug/gosym/pclntab.go | 16 ++++-- src/runtime/plugin.go | 2 +- src/runtime/symtab.go | 34 +++++++----- 4 files changed, 52 insertions(+), 92 deletions(-) diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index b5a66b8517..8f025f91e2 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -539,79 +539,23 @@ func numPCData(ldr *loader.Loader, s loader.Sym, fi loader.FuncInfo) uint32 { return numPCData } -// Helper types for iterating pclntab. -type pclnSetAddr func(*loader.SymbolBuilder, *sys.Arch, int64, loader.Sym, int64) int64 -type pclnSetUint func(*loader.SymbolBuilder, *sys.Arch, int64, uint64) int64 - // generateFunctab creates the runtime.functab // // runtime.functab contains two things: // // - pc->func look up table. // - array of func objects, interleaved with pcdata and funcdata -// -// Because of timing in the linker, generating this table takes two passes. -// The first pass is executed early in the link, and it creates any needed -// relocations to lay out the data. The piece that needs relocations is -// the PC->func table, handled in writePCToFunc. -// After relocations, once we know where to write things in the output buffer, -// we execute the second pass, which is actually writing the data. func (state *pclntab) generateFunctab(ctxt *Link, funcs []loader.Sym, inlSyms map[loader.Sym]loader.Sym, cuOffsets []uint32, nameOffsets map[loader.Sym]uint32) { // Calculate the size of the table. size, startLocations := state.calculateFunctabSize(ctxt, funcs) - - // If we are internally linking a static executable, the function addresses - // are known, so we can just use them instead of emitting relocations. For - // other cases we still need to emit relocations. - // - // This boolean just helps us figure out which callback to use. - useSymValue := ctxt.IsExe() && ctxt.IsInternal() - writePcln := func(ctxt *Link, s loader.Sym) { ldr := ctxt.loader sb := ldr.MakeSymbolUpdater(s) - - // Create our callbacks. - var setAddr pclnSetAddr - if useSymValue { - // We need to write the offset. - setAddr = func(s *loader.SymbolBuilder, arch *sys.Arch, off int64, tgt loader.Sym, add int64) int64 { - if v := ldr.SymValue(tgt); v != 0 { - s.SetUint(arch, off, uint64(v+add)) - } - return 0 - } - } else { - // We already wrote relocations. - setAddr = func(s *loader.SymbolBuilder, arch *sys.Arch, off int64, tgt loader.Sym, add int64) int64 { return 0 } - } - // Write the data. - writePCToFunc(ctxt, sb, funcs, startLocations, setAddr, (*loader.SymbolBuilder).SetUint) + writePCToFunc(ctxt, sb, funcs, startLocations) writeFuncs(ctxt, sb, funcs, inlSyms, startLocations, cuOffsets, nameOffsets) } - state.pclntab = state.addGeneratedSym(ctxt, "runtime.functab", size, writePcln) - - // Create the relocations we need. - ldr := ctxt.loader - sb := ldr.MakeSymbolUpdater(state.pclntab) - - var setAddr pclnSetAddr - if useSymValue { - // If we should use the symbol value, and we don't have one, write a relocation. - setAddr = func(sb *loader.SymbolBuilder, arch *sys.Arch, off int64, tgt loader.Sym, add int64) int64 { - if v := ldr.SymValue(tgt); v == 0 { - sb.SetAddrPlus(arch, off, tgt, add) - } - return 0 - } - } else { - // If we're externally linking, write a relocation. - setAddr = (*loader.SymbolBuilder).SetAddrPlus - } - setUintNOP := func(*loader.SymbolBuilder, *sys.Arch, int64, uint64) int64 { return 0 } - writePCToFunc(ctxt, sb, funcs, startLocations, setAddr, setUintNOP) } // funcData returns the funcdata and offsets for the FuncInfo. @@ -641,10 +585,10 @@ func (state pclntab) calculateFunctabSize(ctxt *Link, funcs []loader.Sym) (int64 ldr := ctxt.loader startLocations := make([]uint32, len(funcs)) - // Allocate space for the pc->func table. This structure consists of a pc + // Allocate space for the pc->func table. This structure consists of a pc offset // and an offset to the func structure. After that, we have a single pc // value that marks the end of the last function in the binary. - size := int64(int(state.nfunc)*2*ctxt.Arch.PtrSize + ctxt.Arch.PtrSize) + size := int64(int(state.nfunc)*2*4 + 4) // Now find the space for the func objects. We do this in a running manner, // so that we can find individual starting locations, and because funcdata @@ -674,10 +618,16 @@ func (state pclntab) calculateFunctabSize(ctxt *Link, funcs []loader.Sym) (int64 } // writePCToFunc writes the PC->func lookup table. -// This function walks the pc->func lookup table, executing callbacks -// to generate relocations and writing the values for the table. -func writePCToFunc(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, startLocations []uint32, setAddr pclnSetAddr, setUint pclnSetUint) { +func writePCToFunc(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, startLocations []uint32) { ldr := ctxt.loader + textStart := ldr.SymValue(ldr.Lookup("runtime.text", 0)) + pcOff := func(s loader.Sym) uint32 { + off := ldr.SymValue(s) - textStart + if off < 0 { + panic(fmt.Sprintf("expected func %s(%x) to be placed at or after textStart (%x)", ldr.SymName(s), ldr.SymValue(s), textStart)) + } + return uint32(off) + } var prevFunc loader.Sym prevSect := ldr.SymSect(funcs[0]) funcIndex := 0 @@ -686,24 +636,20 @@ func writePCToFunc(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, sta // With multiple text sections, there may be a hole here in the // address space. We use an invalid funcoff value to mark the hole. // See also runtime/symtab.go:findfunc - prevFuncSize := int64(ldr.SymSize(prevFunc)) - setAddr(sb, ctxt.Arch, int64(funcIndex*2*ctxt.Arch.PtrSize), prevFunc, prevFuncSize) - setUint(sb, ctxt.Arch, int64((funcIndex*2+1)*ctxt.Arch.PtrSize), ^uint64(0)) + prevFuncSize := uint32(ldr.SymSize(prevFunc)) + sb.SetUint32(ctxt.Arch, int64(funcIndex*2*4), pcOff(prevFunc)+prevFuncSize) + sb.SetUint32(ctxt.Arch, int64((funcIndex*2+1)*4), ^uint32(0)) funcIndex++ prevSect = thisSect } prevFunc = s - // TODO: We don't actually need these relocations, provided we go to a - // module->func look-up-table like we do for filenames. We could have a - // single relocation for the module, and have them all laid out as - // offsets from the beginning of that module. - setAddr(sb, ctxt.Arch, int64(funcIndex*2*ctxt.Arch.PtrSize), s, 0) - setUint(sb, ctxt.Arch, int64((funcIndex*2+1)*ctxt.Arch.PtrSize), uint64(startLocations[i])) + sb.SetUint32(ctxt.Arch, int64(funcIndex*2*4), pcOff(s)) + sb.SetUint32(ctxt.Arch, int64((funcIndex*2+1)*4), startLocations[i]) funcIndex++ } - // Final entry of table is just end pc. - setAddr(sb, ctxt.Arch, int64(funcIndex)*2*int64(ctxt.Arch.PtrSize), prevFunc, ldr.SymSize(prevFunc)) + // Final entry of table is just end pc offset. + sb.SetUint32(ctxt.Arch, int64(funcIndex)*2*4, pcOff(prevFunc)+uint32(ldr.SymSize(prevFunc))) } // writeFuncs writes the func structures and pcdata to runtime.functab. diff --git a/src/debug/gosym/pclntab.go b/src/debug/gosym/pclntab.go index 8fe45decd6..134cb3d194 100644 --- a/src/debug/gosym/pclntab.go +++ b/src/debug/gosym/pclntab.go @@ -373,18 +373,22 @@ func (t *LineTable) string(off uint32) string { // functabFieldSize returns the size in bytes of a single functab field. func (t *LineTable) functabFieldSize() int { + if t.version >= ver118 { + return 4 + } return int(t.ptrsize) } // funcTab returns t's funcTab. func (t *LineTable) funcTab() funcTab { - return funcTab{t} + return funcTab{LineTable: t, sz: t.functabFieldSize()} } // funcTab is memory corresponding to a slice of functab structs, followed by an invalid PC. // A functab struct is a PC and a func offset. type funcTab struct { *LineTable + sz int // cached result of t.functabFieldSize } // Count returns the number of func entries in f. @@ -394,17 +398,21 @@ func (f funcTab) Count() int { // pc returns the PC of the i'th func in f. func (f funcTab) pc(i int) uint64 { - return f.uint(f.functab[2*i*f.functabFieldSize():]) + u := f.uint(f.functab[2*i*f.sz:]) + if f.version >= ver118 { + u += uint64(f.textStart) + } + return u } // funcOff returns the funcdata offset of the i'th func in f. func (f funcTab) funcOff(i int) uint64 { - return f.uint(f.functab[(2*i+1)*f.functabFieldSize():]) + return f.uint(f.functab[(2*i+1)*f.sz:]) } // uint returns the uint stored at b. func (f funcTab) uint(b []byte) uint64 { - if f.functabFieldSize() == 4 { + if f.sz == 4 { return uint64(f.binary.Uint32(b)) } return f.binary.Uint64(b) diff --git a/src/runtime/plugin.go b/src/runtime/plugin.go index 500663bfe2..ab3d802389 100644 --- a/src/runtime/plugin.go +++ b/src/runtime/plugin.go @@ -96,7 +96,7 @@ func plugin_lastmoduleinit() (path string, syms map[string]interface{}, errstr s func pluginftabverify(md *moduledata) { badtable := false for i := 0; i < len(md.ftab); i++ { - entry := md.ftab[i].entry + entry := md.textAddr(uintptr(md.ftab[i].entryoff)) if md.minpc <= entry && entry <= md.maxpc { continue } diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index f423957f88..647300b0c4 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -553,8 +553,8 @@ func modulesinit() { } type functab struct { - entry uintptr - funcoff uintptr + entryoff uint32 // relative to runtime.text + funcoff uint32 } // Mapping information for secondary text sections @@ -604,16 +604,16 @@ func moduledataverify1(datap *moduledata) { nftab := len(datap.ftab) - 1 for i := 0; i < nftab; i++ { // NOTE: ftab[nftab].entry is legal; it is the address beyond the final function. - if datap.ftab[i].entry > datap.ftab[i+1].entry { + if datap.ftab[i].entryoff > datap.ftab[i+1].entryoff { f1 := funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[i].funcoff])), datap} f2 := funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[i+1].funcoff])), datap} f2name := "end" if i+1 < nftab { f2name = funcname(f2) } - println("function symbol table not sorted by PC:", hex(datap.ftab[i].entry), funcname(f1), ">", hex(datap.ftab[i+1].entry), f2name, ", plugin:", datap.pluginpath) + println("function symbol table not sorted by PC offset:", hex(datap.ftab[i].entryoff), funcname(f1), ">", hex(datap.ftab[i+1].entryoff), f2name, ", plugin:", datap.pluginpath) for j := 0; j <= i; j++ { - println("\t", hex(datap.ftab[j].entry), funcname(funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[j].funcoff])), datap})) + println("\t", hex(datap.ftab[j].entryoff), funcname(funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[j].funcoff])), datap})) } if GOOS == "aix" && isarchive { println("-Wl,-bnoobjreorder is mandatory on aix/ppc64 with c-archive") @@ -622,8 +622,12 @@ func moduledataverify1(datap *moduledata) { } } - if datap.minpc != datap.ftab[0].entry || - datap.maxpc != datap.ftab[nftab].entry { + min := datap.textAddr(uintptr(datap.ftab[0].entryoff)) + // The max PC is outside of the text section. + // Subtract 1 to get a PC inside the text section, look it up, then add 1 back in. + max := datap.textAddr(uintptr(datap.ftab[nftab].entryoff-1)) + 1 + if datap.minpc != min || datap.maxpc != max { + println("minpc=", hex(datap.minpc), "min=", hex(min), "maxpc=", hex(datap.maxpc), "max=", hex(max)) throw("minpc or maxpc invalid") } @@ -649,6 +653,9 @@ func moduledataverify1(datap *moduledata) { // Each function's offset is compared against the section vaddrs and sizes to determine the containing section. // Then the section relative offset is added to the section's // relocated baseaddr to compute the function addess. +// +// It is nosplit because it is part of the findfunc implementation. +//go:nosplit func (md *moduledata) textAddr(off uintptr) uintptr { var res uintptr if len(md.textsectmap) > 1 { @@ -808,24 +815,23 @@ func findfunc(pc uintptr) funcInfo { if idx >= uint32(len(datap.ftab)) { idx = uint32(len(datap.ftab) - 1) } - if pc < datap.ftab[idx].entry { + if pc < datap.textAddr(uintptr(datap.ftab[idx].entryoff)) { // With multiple text sections, the idx might reference a function address that - // is higher than the pc being searched, so search backward until the matching address is found. - - for datap.ftab[idx].entry > pc && idx > 0 { + // is higher than the pcOff being searched, so search backward until the matching address is found. + for datap.textAddr(uintptr(datap.ftab[idx].entryoff)) > pc && idx > 0 { idx-- } if idx == 0 { throw("findfunc: bad findfunctab entry idx") } } else { - // linear search to find func with pc >= entry. - for datap.ftab[idx+1].entry <= pc { + // linear search to find func with pcOff >= entry. + for datap.textAddr(uintptr(datap.ftab[idx+1].entryoff)) <= pc { idx++ } } funcoff := datap.ftab[idx].funcoff - if funcoff == ^uintptr(0) { + if funcoff == ^uint32(0) { // With multiple text sections, there may be functions inserted by the external // linker that are not known by Go. This means there may be holes in the PC // range covered by the func table. The invalid funcoff value indicates a hole. -- GitLab From 77bd0da688bf9d53db6ad34a1b17df0cab0b2105 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 5 Oct 2021 10:51:53 -0700 Subject: [PATCH 1467/2500] cmd/link,runtime: remove unnecessary funcdata alignment Change-Id: I2777feaae4f266de99b56b444045370c82447cff Reviewed-on: https://go-review.googlesource.com/c/go/+/354011 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/link/internal/ld/pcln.go | 8 +------- src/runtime/symtab.go | 6 ------ 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index 8f025f91e2..0bcf6c980a 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -591,8 +591,7 @@ func (state pclntab) calculateFunctabSize(ctxt *Link, funcs []loader.Sym) (int64 size := int64(int(state.nfunc)*2*4 + 4) // Now find the space for the func objects. We do this in a running manner, - // so that we can find individual starting locations, and because funcdata - // requires alignment. + // so that we can find individual starting locations. for i, s := range funcs { size = Rnd(size, int64(ctxt.Arch.PtrSize)) startLocations[i] = uint32(size) @@ -607,9 +606,6 @@ func (state pclntab) calculateFunctabSize(ctxt *Link, funcs []loader.Sym) (int64 } } size += int64(numPCData(ldr, s, fi) * 4) - if numFuncData > 0 { // Func data is aligned. - size = Rnd(size, int64(ctxt.Arch.PtrSize)) - } size += int64(numFuncData * 4) } } @@ -747,10 +743,8 @@ func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSym // Write funcdata refs as offsets from go.func.* and go.funcrel.*. funcdata = funcData(ldr, s, fi, inlSyms[s], funcdata) - // funcdata must be pointer-aligned and we're only int32-aligned. // Missing funcdata will be ^0. See runtime/symtab.go:funcdata. off = uint32(startLocations[i] + funcSize + numPCData(ldr, s, fi)*4) - off = uint32(Rnd(int64(off), int64(ctxt.Arch.PtrSize))) for j := range funcdata { dataoff := off + uint32(4*j) fdsym := funcdata[j] diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 647300b0c4..fc02cb4ae5 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -1088,12 +1088,6 @@ func funcdata(f funcInfo, i uint8) unsafe.Pointer { return nil } p := add(unsafe.Pointer(&f.nfuncdata), unsafe.Sizeof(f.nfuncdata)+uintptr(f.npcdata)*4) - if goarch.PtrSize == 8 && uintptr(p)&4 != 0 { - if uintptr(unsafe.Pointer(f._func))&4 != 0 { - println("runtime: misaligned func", f._func) - } - p = add(p, 4) - } p = add(p, uintptr(i)*4) off := *(*uint32)(p) // Return off == ^uint32(0) ? 0 : f.datap.gofunc + uintptr(off), but without branches. -- GitLab From 5758c40ac850f249eccd1676974aac11cb0e8b66 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 5 Oct 2021 12:11:46 -0700 Subject: [PATCH 1468/2500] runtime: add a single-text-section fast path to findfunc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit name old time/op new time/op delta StackCopyWithStkobj-8 11.5ms ± 4% 10.7ms ± 7% -7.10% (p=0.000 n=10+10) Change-Id: Ib806d732ec11f2a6cfde229fd88aff0fe68d9e7d Reviewed-on: https://go-review.googlesource.com/c/go/+/354129 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/symtab.go | 44 +++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index fc02cb4ae5..7724f0d2f0 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -808,28 +808,36 @@ func findfunc(pc uintptr) funcInfo { ffb := (*findfuncbucket)(add(unsafe.Pointer(datap.findfunctab), b*unsafe.Sizeof(findfuncbucket{}))) idx := ffb.idx + uint32(ffb.subbuckets[i]) - // If the idx is beyond the end of the ftab, set it to the end of the table and search backward. - // This situation can occur if multiple text sections are generated to handle large text sections - // and the linker has inserted jump tables between them. - - if idx >= uint32(len(datap.ftab)) { - idx = uint32(len(datap.ftab) - 1) - } - if pc < datap.textAddr(uintptr(datap.ftab[idx].entryoff)) { - // With multiple text sections, the idx might reference a function address that - // is higher than the pcOff being searched, so search backward until the matching address is found. - for datap.textAddr(uintptr(datap.ftab[idx].entryoff)) > pc && idx > 0 { - idx-- - } - if idx == 0 { - throw("findfunc: bad findfunctab entry idx") + // Find the ftab entry. + if len(datap.textsectmap) == 1 { + // fast path for the common case + pcOff := uint32(pc - datap.text) + for datap.ftab[idx+1].entryoff <= pcOff { + idx++ } } else { - // linear search to find func with pcOff >= entry. - for datap.textAddr(uintptr(datap.ftab[idx+1].entryoff)) <= pc { - idx++ + // Multiple text sections. + // If the idx is beyond the end of the ftab, set it to the end of the table and search backward. + if idx >= uint32(len(datap.ftab)) { + idx = uint32(len(datap.ftab) - 1) + } + if pc < datap.textAddr(uintptr(datap.ftab[idx].entryoff)) { + // The idx might reference a function address that + // is higher than the pcOff being searched, so search backward until the matching address is found. + for datap.textAddr(uintptr(datap.ftab[idx].entryoff)) > pc && idx > 0 { + idx-- + } + if idx == 0 { + throw("findfunc: bad findfunctab entry idx") + } + } else { + // linear search to find func with pc >= entry. + for datap.textAddr(uintptr(datap.ftab[idx+1].entryoff)) <= pc { + idx++ + } } } + funcoff := datap.ftab[idx].funcoff if funcoff == ^uint32(0) { // With multiple text sections, there may be functions inserted by the external -- GitLab From 2a5d4ea97e0dd6f1e192aac081430b848084521b Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 5 Oct 2021 13:52:50 -0700 Subject: [PATCH 1469/2500] runtime: make funcspdelta inlineable funcspdelta should be inlined: It is a tiny wrapper around another func. The sanity check prevents that. Condition the sanity check on debugPcln. While we're here, make the sanity check throw when it fails. Change-Id: Iec022b8463b13a8e5a6d8479e7ddcb68909d6fe0 Reviewed-on: https://go-review.googlesource.com/c/go/+/354133 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/symtab.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 7724f0d2f0..8d21fdc42c 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -1035,8 +1035,9 @@ func funcline(f funcInfo, targetpc uintptr) (file string, line int32) { func funcspdelta(f funcInfo, targetpc uintptr, cache *pcvalueCache) int32 { x, _ := pcvalue(f, f.pcsp, targetpc, cache, true) - if x&(goarch.PtrSize-1) != 0 { + if debugPcln && x&(goarch.PtrSize-1) != 0 { print("invalid spdelta ", funcname(f), " ", hex(f.entry()), " ", hex(targetpc), " ", hex(f.pcsp), " ", x, "\n") + throw("bad spdelta") } return x } -- GitLab From e82ed0cd83cec1e6d15ba5a037f77c0b9f1ec8c2 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 5 Oct 2021 14:10:39 -0700 Subject: [PATCH 1470/2500] runtime: start moduledata memory load early MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The slowest thing that can happen in funcdata is a cache miss on moduledata.gofunc. Move that memory load earlier. Also, for better ergonomics when working on this code, do more calculations as uintptrs. name old time/op new time/op delta StackCopyWithStkobj-8 10.5ms ± 5% 9.9ms ± 4% -6.03% (p=0.000 n=15+15) Change-Id: I590f4449725983c7f8d274c4ac7ed384d9018d85 Reviewed-on: https://go-review.googlesource.com/c/go/+/354134 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/symtab.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 8d21fdc42c..e26c05bc0c 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -1096,9 +1096,9 @@ func funcdata(f funcInfo, i uint8) unsafe.Pointer { if i < 0 || i >= f.nfuncdata { return nil } - p := add(unsafe.Pointer(&f.nfuncdata), unsafe.Sizeof(f.nfuncdata)+uintptr(f.npcdata)*4) - p = add(p, uintptr(i)*4) - off := *(*uint32)(p) + base := f.datap.gofunc // load gofunc address early so that we calculate during cache misses + p := uintptr(unsafe.Pointer(&f.nfuncdata)) + unsafe.Sizeof(f.nfuncdata) + uintptr(f.npcdata)*4 + uintptr(i)*4 + off := *(*uint32)(unsafe.Pointer(p)) // Return off == ^uint32(0) ? 0 : f.datap.gofunc + uintptr(off), but without branches. // The compiler calculates mask on most architectures using conditional assignment. var mask uintptr @@ -1106,7 +1106,7 @@ func funcdata(f funcInfo, i uint8) unsafe.Pointer { mask = 1 } mask-- - raw := f.datap.gofunc + uintptr(off) + raw := base + uintptr(off) return unsafe.Pointer(raw & mask) } -- GitLab From ac60900759c29d9c06d9fe131825c4677e47d6a1 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 5 Oct 2021 15:29:50 -0700 Subject: [PATCH 1471/2500] cmd/go: use os.ErrProcessDone rather than matching error string Change-Id: Ied57fb6e71d56618d46aeb36a37a709e08b4346e Reviewed-on: https://go-review.googlesource.com/c/go/+/354136 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/script_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go index 3c5855bd6f..17782420c7 100644 --- a/src/cmd/go/script_test.go +++ b/src/cmd/go/script_test.go @@ -1172,7 +1172,7 @@ func waitOrStop(ctx context.Context, cmd *exec.Cmd, interrupt os.Signal, killDel err := cmd.Process.Signal(interrupt) if err == nil { err = ctx.Err() // Report ctx.Err() as the reason we interrupted. - } else if err.Error() == "os: process already finished" { + } else if err == os.ErrProcessDone { errc <- nil return } -- GitLab From 72c52bfbe2f72fbcacc865e18f132366bdd2effa Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Mon, 7 Jun 2021 16:16:45 -0700 Subject: [PATCH 1472/2500] net/http: parse HTTP version strings according to RFC 7230 RFC 2616 permits multiple digits in the major and minor numbers of an HTTP version: https://datatracker.ietf.org/doc/html/rfc2616#section-3.1 RFC 7230 obsoletes 2616 and tightens the specification to permit only a single digit in the major and minor number: https://datatracker.ietf.org/doc/html/rfc7230#section-2.6 Use the stricter definition. Also fix a bug which caused version numbers with a leading "+" to be accepted (e.g., "HTTP/1.+1".) Fixes #46587. Change-Id: Ic5923bb858e5ac402cfde486fba2c075e221553d Reviewed-on: https://go-review.googlesource.com/c/go/+/325874 Trust: Damien Neil Trust: Brad Fitzpatrick Run-TryBot: Damien Neil TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/net/http/request.go | 19 ++++++++++--------- src/net/http/request_test.go | 8 +++++++- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/net/http/request.go b/src/net/http/request.go index 09cb0c7f56..0eb7042d7b 100644 --- a/src/net/http/request.go +++ b/src/net/http/request.go @@ -779,11 +779,10 @@ func removeZone(host string) string { return host[:j] + host[i:] } -// ParseHTTPVersion parses an HTTP version string. +// ParseHTTPVersion parses an HTTP version string according to RFC 7230, section 2.6. // "HTTP/1.0" returns (1, 0, true). Note that strings without // a minor version, such as "HTTP/2", are not valid. func ParseHTTPVersion(vers string) (major, minor int, ok bool) { - const Big = 1000000 // arbitrary upper bound switch vers { case "HTTP/1.1": return 1, 1, true @@ -793,19 +792,21 @@ func ParseHTTPVersion(vers string) (major, minor int, ok bool) { if !strings.HasPrefix(vers, "HTTP/") { return 0, 0, false } - dot := strings.Index(vers, ".") - if dot < 0 { + if len(vers) != len("HTTP/X.Y") { return 0, 0, false } - major, err := strconv.Atoi(vers[5:dot]) - if err != nil || major < 0 || major > Big { + if vers[6] != '.' { return 0, 0, false } - minor, err = strconv.Atoi(vers[dot+1:]) - if err != nil || minor < 0 || minor > Big { + maj, err := strconv.ParseUint(vers[5:6], 10, 0) + if err != nil { + return 0, 0, false + } + min, err := strconv.ParseUint(vers[7:8], 10, 0) + if err != nil { return 0, 0, false } - return major, minor, true + return int(maj), int(min), true } func validMethod(method string) bool { diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go index 4e0c4ba207..4363e11033 100644 --- a/src/net/http/request_test.go +++ b/src/net/http/request_test.go @@ -639,10 +639,10 @@ var parseHTTPVersionTests = []struct { major, minor int ok bool }{ + {"HTTP/0.0", 0, 0, true}, {"HTTP/0.9", 0, 9, true}, {"HTTP/1.0", 1, 0, true}, {"HTTP/1.1", 1, 1, true}, - {"HTTP/3.14", 3, 14, true}, {"HTTP", 0, 0, false}, {"HTTP/one.one", 0, 0, false}, @@ -651,6 +651,12 @@ var parseHTTPVersionTests = []struct { {"HTTP/0,-1", 0, 0, false}, {"HTTP/", 0, 0, false}, {"HTTP/1,1", 0, 0, false}, + {"HTTP/+1.1", 0, 0, false}, + {"HTTP/1.+1", 0, 0, false}, + {"HTTP/0000000001.1", 0, 0, false}, + {"HTTP/1.0000000001", 0, 0, false}, + {"HTTP/3.14", 0, 0, false}, + {"HTTP/12.3", 0, 0, false}, } func TestParseHTTPVersion(t *testing.T) { -- GitLab From ce72766a02a4be127a26e95fbd62c4b4bb906e91 Mon Sep 17 00:00:00 2001 From: Lynn Boger Date: Tue, 5 Oct 2021 10:22:47 -0500 Subject: [PATCH 1473/2500] cmd/compile: improve PPC64 rules for AtomicLoad{8,32} This adds a rule to avoid the zero extension after an AtomicLoad8 or AtomicLoad32 since the atomic load has already filled it with zeros. This eliminates an instruction in a high use block in findObject and the AtomicLoad8 appears many times within runtime. Change-Id: I7e684bf73d3812110bd371e05b1aa44fa235fc9b Reviewed-on: https://go-review.googlesource.com/c/go/+/354029 Run-TryBot: Lynn Boger TryBot-Result: Go Bot Reviewed-by: Cherry Mui Trust: Lynn Boger --- src/cmd/compile/internal/ssa/gen/PPC64.rules | 2 ++ src/cmd/compile/internal/ssa/rewritePPC64.go | 28 ++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/cmd/compile/internal/ssa/gen/PPC64.rules b/src/cmd/compile/internal/ssa/gen/PPC64.rules index 4c766df4b3..8e42bae215 100644 --- a/src/cmd/compile/internal/ssa/gen/PPC64.rules +++ b/src/cmd/compile/internal/ssa/gen/PPC64.rules @@ -1019,6 +1019,8 @@ (MOVWZreg x:(MOVWZloadidx _ _ _)) => x (MOVWreg x:(MOVWload _ _)) => x (MOVWreg x:(MOVWloadidx _ _ _)) => x +(MOVBZreg x:(Select0 (LoweredAtomicLoad8 _ _))) => x +(MOVWZreg x:(Select0 (LoweredAtomicLoad32 _ _))) => x // don't extend if argument is already extended (MOVBreg x:(Arg )) && is8BitInt(t) && isSigned(t) => x diff --git a/src/cmd/compile/internal/ssa/rewritePPC64.go b/src/cmd/compile/internal/ssa/rewritePPC64.go index b278a4cb44..1e6624e906 100644 --- a/src/cmd/compile/internal/ssa/rewritePPC64.go +++ b/src/cmd/compile/internal/ssa/rewritePPC64.go @@ -7093,6 +7093,20 @@ func rewriteValuePPC64_OpPPC64MOVBZreg(v *Value) bool { v.copyOf(x) return true } + // match: (MOVBZreg x:(Select0 (LoweredAtomicLoad8 _ _))) + // result: x + for { + x := v_0 + if x.Op != OpSelect0 { + break + } + x_0 := x.Args[0] + if x_0.Op != OpPPC64LoweredAtomicLoad8 { + break + } + v.copyOf(x) + return true + } // match: (MOVBZreg x:(Arg )) // cond: is8BitInt(t) && !isSigned(t) // result: x @@ -10549,6 +10563,20 @@ func rewriteValuePPC64_OpPPC64MOVWZreg(v *Value) bool { v.copyOf(x) return true } + // match: (MOVWZreg x:(Select0 (LoweredAtomicLoad32 _ _))) + // result: x + for { + x := v_0 + if x.Op != OpSelect0 { + break + } + x_0 := x.Args[0] + if x_0.Op != OpPPC64LoweredAtomicLoad32 { + break + } + v.copyOf(x) + return true + } // match: (MOVWZreg x:(Arg )) // cond: (is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && !isSigned(t) // result: x -- GitLab From 810b08b8ec28ea00bce4c008f7c1b48bc9f3e134 Mon Sep 17 00:00:00 2001 From: Ruslan Andreev Date: Wed, 16 Jun 2021 16:25:57 +0000 Subject: [PATCH 1474/2500] cmd/compile: inline memequal(x, const, sz) for small sizes This CL adds late expanded memequal(x, const, sz) inlining for 2, 4, 8 bytes size. This PoC is using the same method as CL 248404. This optimization fires about 100 times in Go compiler (1675 occurrences reduced to 1574, so -6%). Also, added unit-tests to codegen/comparisions.go file. Updates #37275 Change-Id: Ia52808d573cb706d1da8166c5746ede26f46c5da Reviewed-on: https://go-review.googlesource.com/c/go/+/328291 Reviewed-by: Cherry Mui Run-TryBot: Cherry Mui Trust: David Chase --- .../compile/internal/ssa/gen/generic.rules | 20 +++- src/cmd/compile/internal/ssa/rewrite.go | 5 + .../compile/internal/ssa/rewritegeneric.go | 100 ++++++++++++++++++ test/codegen/comparisons.go | 62 +++++++++++ 4 files changed, 186 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules index 40db1a6ee8..6dbe9b47d0 100644 --- a/src/cmd/compile/internal/ssa/gen/generic.rules +++ b/src/cmd/compile/internal/ssa/gen/generic.rules @@ -2011,12 +2011,30 @@ => (Invalid) // for late-expanded calls, recognize memequal applied to a single constant byte -// TODO figure out breakeven number of bytes for this optimization. +// Support is limited by 1, 2, 4, 8 byte sizes (StaticLECall {callAux} sptr (Addr {scon} (SB)) (Const64 [1]) mem) && isSameCall(callAux, "runtime.memequal") && symIsRO(scon) => (MakeResult (Eq8 (Load sptr mem) (Const8 [int8(read8(scon,0))])) mem) +(StaticLECall {callAux} sptr (Addr {scon} (SB)) (Const64 [2]) mem) + && isSameCall(callAux, "runtime.memequal") + && symIsRO(scon) + && canLoadUnaligned(config) + => (MakeResult (Eq16 (Load sptr mem) (Const16 [int16(read16(scon,0,config.ctxt.Arch.ByteOrder))])) mem) + +(StaticLECall {callAux} sptr (Addr {scon} (SB)) (Const64 [4]) mem) + && isSameCall(callAux, "runtime.memequal") + && symIsRO(scon) + && canLoadUnaligned(config) + => (MakeResult (Eq32 (Load sptr mem) (Const32 [int32(read32(scon,0,config.ctxt.Arch.ByteOrder))])) mem) + +(StaticLECall {callAux} sptr (Addr {scon} (SB)) (Const64 [8]) mem) + && isSameCall(callAux, "runtime.memequal") + && symIsRO(scon) + && canLoadUnaligned(config) && config.PtrSize == 8 + => (MakeResult (Eq64 (Load sptr mem) (Const64 [int64(read64(scon,0,config.ctxt.Arch.ByteOrder))])) mem) + // Evaluate constant address comparisons. (EqPtr x x) => (ConstBool [true]) (NeqPtr x x) => (ConstBool [false]) diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index 79f9efaebf..2fe0ca64c8 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -415,6 +415,11 @@ func isSameCall(sym interface{}, name string) bool { return fn != nil && fn.String() == name } +// canLoadUnaligned reports if the achitecture supports unaligned load operations +func canLoadUnaligned(c *Config) bool { + return c.ctxt.Arch.Alignment == 1 +} + // nlz returns the number of leading zeros. func nlz64(x int64) int { return bits.LeadingZeros64(uint64(x)) } func nlz32(x int32) int { return bits.LeadingZeros32(uint32(x)) } diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index a6757e0d10..fbf227562a 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -21746,6 +21746,7 @@ func rewriteValuegeneric_OpSqrt(v *Value) bool { } func rewriteValuegeneric_OpStaticLECall(v *Value) bool { b := v.Block + config := b.Func.Config typ := &b.Func.Config.Types // match: (StaticLECall {callAux} sptr (Addr {scon} (SB)) (Const64 [1]) mem) // cond: isSameCall(callAux, "runtime.memequal") && symIsRO(scon) @@ -21780,6 +21781,105 @@ func rewriteValuegeneric_OpStaticLECall(v *Value) bool { v.AddArg2(v0, mem) return true } + // match: (StaticLECall {callAux} sptr (Addr {scon} (SB)) (Const64 [2]) mem) + // cond: isSameCall(callAux, "runtime.memequal") && symIsRO(scon) && canLoadUnaligned(config) + // result: (MakeResult (Eq16 (Load sptr mem) (Const16 [int16(read16(scon,0,config.ctxt.Arch.ByteOrder))])) mem) + for { + if len(v.Args) != 4 { + break + } + callAux := auxToCall(v.Aux) + mem := v.Args[3] + sptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != OpAddr { + break + } + scon := auxToSym(v_1.Aux) + v_1_0 := v_1.Args[0] + if v_1_0.Op != OpSB { + break + } + v_2 := v.Args[2] + if v_2.Op != OpConst64 || auxIntToInt64(v_2.AuxInt) != 2 || !(isSameCall(callAux, "runtime.memequal") && symIsRO(scon) && canLoadUnaligned(config)) { + break + } + v.reset(OpMakeResult) + v0 := b.NewValue0(v.Pos, OpEq16, typ.Bool) + v1 := b.NewValue0(v.Pos, OpLoad, typ.Int16) + v1.AddArg2(sptr, mem) + v2 := b.NewValue0(v.Pos, OpConst16, typ.Int16) + v2.AuxInt = int16ToAuxInt(int16(read16(scon, 0, config.ctxt.Arch.ByteOrder))) + v0.AddArg2(v1, v2) + v.AddArg2(v0, mem) + return true + } + // match: (StaticLECall {callAux} sptr (Addr {scon} (SB)) (Const64 [4]) mem) + // cond: isSameCall(callAux, "runtime.memequal") && symIsRO(scon) && canLoadUnaligned(config) + // result: (MakeResult (Eq32 (Load sptr mem) (Const32 [int32(read32(scon,0,config.ctxt.Arch.ByteOrder))])) mem) + for { + if len(v.Args) != 4 { + break + } + callAux := auxToCall(v.Aux) + mem := v.Args[3] + sptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != OpAddr { + break + } + scon := auxToSym(v_1.Aux) + v_1_0 := v_1.Args[0] + if v_1_0.Op != OpSB { + break + } + v_2 := v.Args[2] + if v_2.Op != OpConst64 || auxIntToInt64(v_2.AuxInt) != 4 || !(isSameCall(callAux, "runtime.memequal") && symIsRO(scon) && canLoadUnaligned(config)) { + break + } + v.reset(OpMakeResult) + v0 := b.NewValue0(v.Pos, OpEq32, typ.Bool) + v1 := b.NewValue0(v.Pos, OpLoad, typ.Int32) + v1.AddArg2(sptr, mem) + v2 := b.NewValue0(v.Pos, OpConst32, typ.Int32) + v2.AuxInt = int32ToAuxInt(int32(read32(scon, 0, config.ctxt.Arch.ByteOrder))) + v0.AddArg2(v1, v2) + v.AddArg2(v0, mem) + return true + } + // match: (StaticLECall {callAux} sptr (Addr {scon} (SB)) (Const64 [8]) mem) + // cond: isSameCall(callAux, "runtime.memequal") && symIsRO(scon) && canLoadUnaligned(config) && config.PtrSize == 8 + // result: (MakeResult (Eq64 (Load sptr mem) (Const64 [int64(read64(scon,0,config.ctxt.Arch.ByteOrder))])) mem) + for { + if len(v.Args) != 4 { + break + } + callAux := auxToCall(v.Aux) + mem := v.Args[3] + sptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != OpAddr { + break + } + scon := auxToSym(v_1.Aux) + v_1_0 := v_1.Args[0] + if v_1_0.Op != OpSB { + break + } + v_2 := v.Args[2] + if v_2.Op != OpConst64 || auxIntToInt64(v_2.AuxInt) != 8 || !(isSameCall(callAux, "runtime.memequal") && symIsRO(scon) && canLoadUnaligned(config) && config.PtrSize == 8) { + break + } + v.reset(OpMakeResult) + v0 := b.NewValue0(v.Pos, OpEq64, typ.Bool) + v1 := b.NewValue0(v.Pos, OpLoad, typ.Int64) + v1.AddArg2(sptr, mem) + v2 := b.NewValue0(v.Pos, OpConst64, typ.Int64) + v2.AuxInt = int64ToAuxInt(int64(read64(scon, 0, config.ctxt.Arch.ByteOrder))) + v0.AddArg2(v1, v2) + v.AddArg2(v0, mem) + return true + } return false } func rewriteValuegeneric_OpStore(v *Value) bool { diff --git a/test/codegen/comparisons.go b/test/codegen/comparisons.go index 17dcd94ae1..35a181f83b 100644 --- a/test/codegen/comparisons.go +++ b/test/codegen/comparisons.go @@ -538,3 +538,65 @@ func CmpToOneU_ex2(a uint8, b uint16, c uint32, d uint64) int { } return 0 } + +// Check that small memequals are replaced with eq instructions + +func equalConstString1() bool { + a := string("A") + b := string("Z") + // amd64:-".*memequal" + // arm64:-".*memequal" + return a == b +} + +func equalVarString1(a string) bool { + b := string("Z") + // amd64:-".*memequal" + // arm64:-".*memequal" + return a[:1] == b +} + +func equalConstString2() bool { + a := string("AA") + b := string("ZZ") + // amd64:-".*memequal" + // arm64:-".*memequal" + return a == b +} + +func equalVarString2(a string) bool { + b := string("ZZ") + // amd64:-".*memequal" + // arm64:-".*memequal" + return a[:2] == b +} + +func equalConstString4() bool { + a := string("AAAA") + b := string("ZZZZ") + // amd64:-".*memequal" + // arm64:-".*memequal" + return a == b +} + +func equalVarString4(a string) bool { + b := string("ZZZZ") + // amd64:-".*memequal" + // arm64:-".*memequal" + return a[:4] == b +} + +func equalConstString8() bool { + a := string("AAAAAAAA") + b := string("ZZZZZZZZ") + // amd64:-".*memequal" + // arm64:-".*memequal" + return a == b +} + +func equalVarString8(a string) bool { + b := string("ZZZZZZZZ") + // amd64:-".*memequal" + // arm64:-".*memequal" + return a[:8] == b +} -- GitLab From 8e36ab055162efa6f67f3b9ee62f625ac8874901 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 21 Sep 2021 10:59:16 -0400 Subject: [PATCH 1475/2500] bytes, strings: add Cut Using Cut is a clearer way to write the vast majority (>70%) of existing code that calls Index, IndexByte, IndexRune, and SplitN. There is more discussion on https://golang.org/issue/46336. Fixes #46336. Change-Id: Ia418ed7c3706c65bf61e1b2c5baf534cb783e4d3 Reviewed-on: https://go-review.googlesource.com/c/go/+/351710 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/bytes/bytes.go | 13 ++++ src/bytes/bytes_test.go | 23 ++++++ src/bytes/example_test.go | 138 ++++++++++++++++++------------------ src/strings/example_test.go | 58 +++++++++------ src/strings/strings.go | 11 +++ src/strings/strings_test.go | 25 ++++++- 6 files changed, 178 insertions(+), 90 deletions(-) diff --git a/src/bytes/bytes.go b/src/bytes/bytes.go index cd859d086d..a9f10031c4 100644 --- a/src/bytes/bytes.go +++ b/src/bytes/bytes.go @@ -1192,3 +1192,16 @@ func Index(s, sep []byte) int { } return -1 } + +// Cut slices s around the first instance of sep, +// returning the text before and after sep. +// The found result reports whether sep appears in s. +// If sep does not appear in s, cut returns s, "", false. +// +// Cut returns slices of the original slice s, not copies. +func Cut(s, sep []byte) (before, after []byte, found bool) { + if i := Index(s, sep); i >= 0 { + return s[:i], s[i+len(sep):], true + } + return s, nil, false +} diff --git a/src/bytes/bytes_test.go b/src/bytes/bytes_test.go index 850b2ed061..3bece6adf0 100644 --- a/src/bytes/bytes_test.go +++ b/src/bytes/bytes_test.go @@ -1567,6 +1567,29 @@ func TestEqualFold(t *testing.T) { } } +var cutTests = []struct { + s, sep string + before, after string + found bool +}{ + {"abc", "b", "a", "c", true}, + {"abc", "a", "", "bc", true}, + {"abc", "c", "ab", "", true}, + {"abc", "abc", "", "", true}, + {"abc", "", "", "abc", true}, + {"abc", "d", "abc", "", false}, + {"", "d", "", "", false}, + {"", "", "", "", true}, +} + +func TestCut(t *testing.T) { + for _, tt := range cutTests { + if before, after, found := Cut([]byte(tt.s), []byte(tt.sep)); string(before) != tt.before || string(after) != tt.after || found != tt.found { + t.Errorf("Cut(%q, %q) = %q, %q, %v, want %q, %q, %v", tt.s, tt.sep, before, after, found, tt.before, tt.after, tt.found) + } + } +} + func TestBufferGrowNegative(t *testing.T) { defer func() { if err := recover(); err == nil { diff --git a/src/bytes/example_test.go b/src/bytes/example_test.go index d0d4dd2c2d..d04b088fab 100644 --- a/src/bytes/example_test.go +++ b/src/bytes/example_test.go @@ -105,36 +105,6 @@ func ExampleCompare_search() { } } -func ExampleTrimSuffix() { - var b = []byte("Hello, goodbye, etc!") - b = bytes.TrimSuffix(b, []byte("goodbye, etc!")) - b = bytes.TrimSuffix(b, []byte("gopher")) - b = append(b, bytes.TrimSuffix([]byte("world!"), []byte("x!"))...) - os.Stdout.Write(b) - // Output: Hello, world! -} - -func ExampleTrimPrefix() { - var b = []byte("Goodbye,, world!") - b = bytes.TrimPrefix(b, []byte("Goodbye,")) - b = bytes.TrimPrefix(b, []byte("See ya,")) - fmt.Printf("Hello%s", b) - // Output: Hello, world! -} - -func ExampleFields() { - fmt.Printf("Fields are: %q", bytes.Fields([]byte(" foo bar baz "))) - // Output: Fields are: ["foo" "bar" "baz"] -} - -func ExampleFieldsFunc() { - f := func(c rune) bool { - return !unicode.IsLetter(c) && !unicode.IsNumber(c) - } - fmt.Printf("Fields are: %q", bytes.FieldsFunc([]byte(" foo1;bar2,baz3..."), f)) - // Output: Fields are: ["foo1" "bar2" "baz3"] -} - func ExampleContains() { fmt.Println(bytes.Contains([]byte("seafood"), []byte("foo"))) fmt.Println(bytes.Contains([]byte("seafood"), []byte("bar"))) @@ -181,6 +151,22 @@ func ExampleCount() { // 5 } +func ExampleCut() { + show := func(s, sep string) { + before, after, found := bytes.Cut([]byte(s), []byte(sep)) + fmt.Printf("Cut(%q, %q) = %q, %q, %v\n", s, sep, before, after, found) + } + show("Gopher", "Go") + show("Gopher", "ph") + show("Gopher", "er") + show("Gopher", "Badger") + // Output: + // Cut("Gopher", "Go") = "", "pher", true + // Cut("Gopher", "ph") = "Go", "er", true + // Cut("Gopher", "er") = "Goph", "", true + // Cut("Gopher", "Badger") = "Gopher", "", false +} + func ExampleEqual() { fmt.Println(bytes.Equal([]byte("Go"), []byte("Go"))) fmt.Println(bytes.Equal([]byte("Go"), []byte("C++"))) @@ -194,6 +180,19 @@ func ExampleEqualFold() { // Output: true } +func ExampleFields() { + fmt.Printf("Fields are: %q", bytes.Fields([]byte(" foo bar baz "))) + // Output: Fields are: ["foo" "bar" "baz"] +} + +func ExampleFieldsFunc() { + f := func(c rune) bool { + return !unicode.IsLetter(c) && !unicode.IsNumber(c) + } + fmt.Printf("Fields are: %q", bytes.FieldsFunc([]byte(" foo1;bar2,baz3..."), f)) + // Output: Fields are: ["foo1" "bar2" "baz3"] +} + func ExampleHasPrefix() { fmt.Println(bytes.HasPrefix([]byte("Gopher"), []byte("Go"))) fmt.Println(bytes.HasPrefix([]byte("Gopher"), []byte("C"))) @@ -259,6 +258,12 @@ func ExampleIndexRune() { // -1 } +func ExampleJoin() { + s := [][]byte{[]byte("foo"), []byte("bar"), []byte("baz")} + fmt.Printf("%s", bytes.Join(s, []byte(", "))) + // Output: foo, bar, baz +} + func ExampleLastIndex() { fmt.Println(bytes.Index([]byte("go gopher"), []byte("go"))) fmt.Println(bytes.LastIndex([]byte("go gopher"), []byte("go"))) @@ -299,10 +304,12 @@ func ExampleLastIndexFunc() { // -1 } -func ExampleJoin() { - s := [][]byte{[]byte("foo"), []byte("bar"), []byte("baz")} - fmt.Printf("%s", bytes.Join(s, []byte(", "))) - // Output: foo, bar, baz +func ExampleReader_Len() { + fmt.Println(bytes.NewReader([]byte("Hi!")).Len()) + fmt.Println(bytes.NewReader([]byte("こんにちは!")).Len()) + // Output: + // 3 + // 16 } func ExampleRepeat() { @@ -412,20 +419,6 @@ func ExampleTrimFunc() { // go-gopher! } -func ExampleMap() { - rot13 := func(r rune) rune { - switch { - case r >= 'A' && r <= 'Z': - return 'A' + (r-'A'+13)%26 - case r >= 'a' && r <= 'z': - return 'a' + (r-'a'+13)%26 - } - return r - } - fmt.Printf("%s", bytes.Map(rot13, []byte("'Twas brillig and the slithy gopher..."))) - // Output: 'Gjnf oevyyvt naq gur fyvgul tbcure... -} - func ExampleTrimLeft() { fmt.Print(string(bytes.TrimLeft([]byte("453gopher8257"), "0123456789"))) // Output: @@ -442,11 +435,28 @@ func ExampleTrimLeftFunc() { // go-gopher!567 } +func ExampleTrimPrefix() { + var b = []byte("Goodbye,, world!") + b = bytes.TrimPrefix(b, []byte("Goodbye,")) + b = bytes.TrimPrefix(b, []byte("See ya,")) + fmt.Printf("Hello%s", b) + // Output: Hello, world! +} + func ExampleTrimSpace() { fmt.Printf("%s", bytes.TrimSpace([]byte(" \t\n a lone gopher \n\t\r\n"))) // Output: a lone gopher } +func ExampleTrimSuffix() { + var b = []byte("Hello, goodbye, etc!") + b = bytes.TrimSuffix(b, []byte("goodbye, etc!")) + b = bytes.TrimSuffix(b, []byte("gopher")) + b = append(b, bytes.TrimSuffix([]byte("world!"), []byte("x!"))...) + os.Stdout.Write(b) + // Output: Hello, world! +} + func ExampleTrimRight() { fmt.Print(string(bytes.TrimRight([]byte("453gopher8257"), "0123456789"))) // Output: @@ -463,21 +473,6 @@ func ExampleTrimRightFunc() { // 1234go-gopher! } -func ExampleToUpper() { - fmt.Printf("%s", bytes.ToUpper([]byte("Gopher"))) - // Output: GOPHER -} - -func ExampleToUpperSpecial() { - str := []byte("ahoj vývojári golang") - totitle := bytes.ToUpperSpecial(unicode.AzeriCase, str) - fmt.Println("Original : " + string(str)) - fmt.Println("ToUpper : " + string(totitle)) - // Output: - // Original : ahoj vývojári golang - // ToUpper : AHOJ VÝVOJÁRİ GOLANG -} - func ExampleToLower() { fmt.Printf("%s", bytes.ToLower([]byte("Gopher"))) // Output: gopher @@ -493,10 +488,17 @@ func ExampleToLowerSpecial() { // ToLower : ahoj vývojári golang } -func ExampleReader_Len() { - fmt.Println(bytes.NewReader([]byte("Hi!")).Len()) - fmt.Println(bytes.NewReader([]byte("こんにちは!")).Len()) +func ExampleToUpper() { + fmt.Printf("%s", bytes.ToUpper([]byte("Gopher"))) + // Output: GOPHER +} + +func ExampleToUpperSpecial() { + str := []byte("ahoj vývojári golang") + totitle := bytes.ToUpperSpecial(unicode.AzeriCase, str) + fmt.Println("Original : " + string(str)) + fmt.Println("ToUpper : " + string(totitle)) // Output: - // 3 - // 16 + // Original : ahoj vývojári golang + // ToUpper : AHOJ VÝVOJÁRİ GOLANG } diff --git a/src/strings/example_test.go b/src/strings/example_test.go index 375f9cac65..94aa167f90 100644 --- a/src/strings/example_test.go +++ b/src/strings/example_test.go @@ -10,17 +10,15 @@ import ( "unicode" ) -func ExampleFields() { - fmt.Printf("Fields are: %q", strings.Fields(" foo bar baz ")) - // Output: Fields are: ["foo" "bar" "baz"] -} - -func ExampleFieldsFunc() { - f := func(c rune) bool { - return !unicode.IsLetter(c) && !unicode.IsNumber(c) +func ExampleBuilder() { + var b strings.Builder + for i := 3; i >= 1; i-- { + fmt.Fprintf(&b, "%d...", i) } - fmt.Printf("Fields are: %q", strings.FieldsFunc(" foo1;bar2,baz3...", f)) - // Output: Fields are: ["foo1" "bar2" "baz3"] + b.WriteString("ignition") + fmt.Println(b.String()) + + // Output: 3...2...1...ignition } func ExampleCompare() { @@ -79,11 +77,40 @@ func ExampleCount() { // 5 } +func ExampleCut() { + show := func(s, sep string) { + before, after, found := strings.Cut(s, sep) + fmt.Printf("Cut(%q, %q) = %q, %q, %v\n", s, sep, before, after, found) + } + show("Gopher", "Go") + show("Gopher", "ph") + show("Gopher", "er") + show("Gopher", "Badger") + // Output: + // Cut("Gopher", "Go") = "", "pher", true + // Cut("Gopher", "ph") = "Go", "er", true + // Cut("Gopher", "er") = "Goph", "", true + // Cut("Gopher", "Badger") = "Gopher", "", false +} + func ExampleEqualFold() { fmt.Println(strings.EqualFold("Go", "go")) // Output: true } +func ExampleFields() { + fmt.Printf("Fields are: %q", strings.Fields(" foo bar baz ")) + // Output: Fields are: ["foo" "bar" "baz"] +} + +func ExampleFieldsFunc() { + f := func(c rune) bool { + return !unicode.IsLetter(c) && !unicode.IsNumber(c) + } + fmt.Printf("Fields are: %q", strings.FieldsFunc(" foo1;bar2,baz3...", f)) + // Output: Fields are: ["foo1" "bar2" "baz3"] +} + func ExampleHasPrefix() { fmt.Println(strings.HasPrefix("Gopher", "Go")) fmt.Println(strings.HasPrefix("Gopher", "C")) @@ -370,14 +397,3 @@ func ExampleTrimRightFunc() { })) // Output: ¡¡¡Hello, Gophers } - -func ExampleBuilder() { - var b strings.Builder - for i := 3; i >= 1; i-- { - fmt.Fprintf(&b, "%d...", i) - } - b.WriteString("ignition") - fmt.Println(b.String()) - - // Output: 3...2...1...ignition -} diff --git a/src/strings/strings.go b/src/strings/strings.go index 0df8d2eb28..4b543dcc1a 100644 --- a/src/strings/strings.go +++ b/src/strings/strings.go @@ -1118,3 +1118,14 @@ func Index(s, substr string) int { } return -1 } + +// Cut slices s around the first instance of sep, +// returning the text before and after sep. +// The found result reports whether sep appears in s. +// If sep does not appear in s, cut returns s, "", false. +func Cut(s, sep string) (before, after string, found bool) { + if i := Index(s, sep); i >= 0 { + return s[:i], s[i+len(sep):], true + } + return s, "", false +} diff --git a/src/strings/strings_test.go b/src/strings/strings_test.go index edc6c20590..0f30ca738e 100644 --- a/src/strings/strings_test.go +++ b/src/strings/strings_test.go @@ -1579,7 +1579,30 @@ var CountTests = []struct { func TestCount(t *testing.T) { for _, tt := range CountTests { if num := Count(tt.s, tt.sep); num != tt.num { - t.Errorf("Count(\"%s\", \"%s\") = %d, want %d", tt.s, tt.sep, num, tt.num) + t.Errorf("Count(%q, %q) = %d, want %d", tt.s, tt.sep, num, tt.num) + } + } +} + +var cutTests = []struct { + s, sep string + before, after string + found bool +}{ + {"abc", "b", "a", "c", true}, + {"abc", "a", "", "bc", true}, + {"abc", "c", "ab", "", true}, + {"abc", "abc", "", "", true}, + {"abc", "", "", "abc", true}, + {"abc", "d", "abc", "", false}, + {"", "d", "", "", false}, + {"", "", "", "", true}, +} + +func TestCut(t *testing.T) { + for _, tt := range cutTests { + if before, after, found := Cut(tt.s, tt.sep); before != tt.before || after != tt.after || found != tt.found { + t.Errorf("Cut(%q, %q) = %q, %q, %v, want %q, %q, %v", tt.s, tt.sep, before, after, found, tt.before, tt.after, tt.found) } } } -- GitLab From 4d8db00641cc9ff4f44de7df9b8c4f4a4f9416ee Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 22 Sep 2021 10:46:32 -0400 Subject: [PATCH 1476/2500] all: use bytes.Cut, strings.Cut Many uses of Index/IndexByte/IndexRune/Split/SplitN can be written more clearly using the new Cut functions. Do that. Also rewrite to other functions if that's clearer. For #46336. Change-Id: I68d024716ace41a57a8bf74455c62279bde0f448 Reviewed-on: https://go-review.googlesource.com/c/go/+/351711 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- misc/cgo/errors/errors_test.go | 9 ++- misc/cgo/testcshared/cshared_test.go | 4 +- misc/cgo/testsanitizers/cc_test.go | 2 +- misc/ios/go_ios_exec.go | 10 ++-- misc/linkcheck/linkcheck.go | 6 +- src/archive/tar/strconv.go | 43 ++++---------- src/archive/tar/writer_test.go | 4 +- src/archive/zip/writer_test.go | 2 +- src/cmd/doc/dirs.go | 6 +- src/cmd/doc/pkg.go | 4 +- src/cmd/fix/typecheck.go | 18 +++--- src/cmd/vet/vet_test.go | 4 +- src/crypto/ecdsa/ecdsa_test.go | 6 +- src/crypto/tls/handshake_client_test.go | 10 ++-- src/crypto/tls/handshake_test.go | 13 ++--- src/crypto/x509/pem_decrypt.go | 5 +- src/encoding/asn1/common.go | 9 +-- src/encoding/json/tags.go | 16 ++--- src/encoding/pem/pem.go | 10 ++-- src/encoding/xml/typeinfo.go | 4 +- src/encoding/xml/xml.go | 49 ++++++++-------- src/go/build/build.go | 24 +++----- src/go/build/build_test.go | 2 +- src/go/build/read.go | 8 +-- src/go/build/read_test.go | 21 +++---- src/go/constant/value_test.go | 12 ++-- src/go/doc/comment.go | 16 +++-- src/go/doc/headscan.go | 17 ++---- src/go/importer/importer_test.go | 3 +- src/go/printer/nodes.go | 2 +- src/go/printer/printer.go | 13 ++--- src/go/types/eval_test.go | 6 +- src/html/template/attr.go | 6 +- src/html/template/js.go | 4 +- src/html/template/url.go | 4 +- src/internal/profile/legacy_profile.go | 10 ++-- src/mime/encodedword.go | 22 ++----- src/mime/mediatype.go | 15 ++--- src/net/http/cgi/child.go | 4 +- src/net/http/cgi/host.go | 5 +- src/net/http/cgi/host_test.go | 10 ++-- src/net/http/client_test.go | 7 +-- src/net/http/cookie.go | 27 +++------ src/net/http/fs.go | 6 +- src/net/http/internal/chunked.go | 9 ++- src/net/http/main_test.go | 7 +-- src/net/http/request.go | 25 ++++---- src/net/http/response.go | 15 ++--- src/net/http/server.go | 2 +- src/net/http/transport.go | 6 +- src/net/mail/message.go | 2 +- src/net/main_posix_test.go | 4 +- src/net/main_test.go | 7 +-- src/net/platform_test.go | 10 ++-- src/net/smtp/smtp.go | 8 +-- src/net/textproto/reader.go | 28 +++------ src/net/url/url.go | 58 +++++-------------- src/net/url/url_test.go | 9 --- src/os/exec/exec.go | 10 ++-- src/os/exec/exec_test.go | 8 +-- src/os/os_test.go | 4 +- src/os/user/cgo_lookup_unix.go | 4 +- src/os/user/lookup_unix.go | 4 +- src/regexp/exec_test.go | 14 ++--- src/regexp/regexp.go | 22 ++++--- src/regexp/syntax/parse.go | 8 +-- src/runtime/debug/mod.go | 5 +- src/runtime/pprof/pprof_test.go | 17 +++--- src/runtime/pprof/proto.go | 33 ++++------- src/runtime/pprof/proto_test.go | 5 +- src/runtime/runtime-gdb_test.go | 2 +- .../testdata/testprog/numcpu_freebsd.go | 11 ++-- .../testdata/testprog/traceback_ancestors.go | 38 ++++++------ src/strconv/fp_test.go | 20 +++---- src/syscall/exec_linux_test.go | 4 +- src/text/template/option.go | 10 ++-- test/run.go | 44 ++++++-------- test/zerodivide.go | 2 +- 78 files changed, 356 insertions(+), 577 deletions(-) diff --git a/misc/cgo/errors/errors_test.go b/misc/cgo/errors/errors_test.go index 68a30a44fe..e90ed1e058 100644 --- a/misc/cgo/errors/errors_test.go +++ b/misc/cgo/errors/errors_test.go @@ -36,14 +36,13 @@ func check(t *testing.T, file string) { continue } - frags := bytes.SplitAfterN(line, []byte("ERROR HERE: "), 2) - if len(frags) == 1 { + _, frag, ok := bytes.Cut(line, []byte("ERROR HERE: ")) + if !ok { continue } - frag := fmt.Sprintf(":%d:.*%s", i+1, frags[1]) - re, err := regexp.Compile(frag) + re, err := regexp.Compile(fmt.Sprintf(":%d:.*%s", i+1, frag)) if err != nil { - t.Errorf("Invalid regexp after `ERROR HERE: `: %#q", frags[1]) + t.Errorf("Invalid regexp after `ERROR HERE: `: %#q", frag) continue } errors = append(errors, re) diff --git a/misc/cgo/testcshared/cshared_test.go b/misc/cgo/testcshared/cshared_test.go index 19ad8c76a8..84b92d502f 100644 --- a/misc/cgo/testcshared/cshared_test.go +++ b/misc/cgo/testcshared/cshared_test.go @@ -200,7 +200,7 @@ func adbRun(t *testing.T, env []string, adbargs ...string) string { args := append(adbCmd(), "exec-out") // Propagate LD_LIBRARY_PATH to the adb shell invocation. for _, e := range env { - if strings.Index(e, "LD_LIBRARY_PATH=") != -1 { + if strings.Contains(e, "LD_LIBRARY_PATH=") { adbargs = append([]string{e}, adbargs...) break } @@ -326,7 +326,7 @@ func createHeaders() error { base, name := filepath.Split(args[0]) args[0] = filepath.Join(base, "llvm-dlltool") var machine string - switch strings.SplitN(name, "-", 2)[0] { + switch prefix, _, _ := strings.Cut(name, "-"); prefix { case "i686": machine = "i386" case "x86_64": diff --git a/misc/cgo/testsanitizers/cc_test.go b/misc/cgo/testsanitizers/cc_test.go index 384b6250e1..7af30ab557 100644 --- a/misc/cgo/testsanitizers/cc_test.go +++ b/misc/cgo/testsanitizers/cc_test.go @@ -344,7 +344,7 @@ func (c *config) checkCSanitizer() (skip bool, err error) { if os.IsNotExist(err) { return true, fmt.Errorf("%#q failed to produce executable: %v", strings.Join(cmd.Args, " "), err) } - snippet := bytes.SplitN(out, []byte{'\n'}, 2)[0] + snippet, _, _ := bytes.Cut(out, []byte("\n")) return true, fmt.Errorf("%#q generated broken executable: %v\n%s", strings.Join(cmd.Args, " "), err, snippet) } diff --git a/misc/ios/go_ios_exec.go b/misc/ios/go_ios_exec.go index 9e63717d92..34a734cda7 100644 --- a/misc/ios/go_ios_exec.go +++ b/misc/ios/go_ios_exec.go @@ -148,9 +148,8 @@ func runOnDevice(appdir string) error { // Device IDs as listed with ios-deploy -c. deviceID = os.Getenv("GOIOS_DEVICE_ID") - parts := strings.SplitN(appID, ".", 2) - if len(parts) == 2 { - bundleID = parts[1] + if _, id, ok := strings.Cut(appID, "."); ok { + bundleID = id } if err := signApp(appdir); err != nil { @@ -291,11 +290,10 @@ func findDevImage() (string, error) { var iosVer, buildVer string lines := bytes.Split(out, []byte("\n")) for _, line := range lines { - spl := bytes.SplitN(line, []byte(": "), 2) - if len(spl) != 2 { + key, val, ok := strings.Cut(string(line), ": ") + if !ok { continue } - key, val := string(spl[0]), string(spl[1]) switch key { case "ProductVersion": iosVer = val diff --git a/misc/linkcheck/linkcheck.go b/misc/linkcheck/linkcheck.go index 570b430da4..efe400965b 100644 --- a/misc/linkcheck/linkcheck.go +++ b/misc/linkcheck/linkcheck.go @@ -81,10 +81,8 @@ func crawl(url string, sourceURL string) { } mu.Lock() defer mu.Unlock() - var frag string - if i := strings.Index(url, "#"); i >= 0 { - frag = url[i+1:] - url = url[:i] + if u, frag, ok := strings.Cut(url, "#"); ok { + url = u if frag != "" { uf := urlFrag{url, frag} neededFrags[uf] = append(neededFrags[uf], sourceURL) diff --git a/src/archive/tar/strconv.go b/src/archive/tar/strconv.go index f0b61e6dba..275db6f026 100644 --- a/src/archive/tar/strconv.go +++ b/src/archive/tar/strconv.go @@ -14,7 +14,7 @@ import ( // hasNUL reports whether the NUL character exists within s. func hasNUL(s string) bool { - return strings.IndexByte(s, 0) >= 0 + return strings.Contains(s, "\x00") } // isASCII reports whether the input is an ASCII C-style string. @@ -201,10 +201,7 @@ func parsePAXTime(s string) (time.Time, error) { const maxNanoSecondDigits = 9 // Split string into seconds and sub-seconds parts. - ss, sn := s, "" - if pos := strings.IndexByte(s, '.'); pos >= 0 { - ss, sn = s[:pos], s[pos+1:] - } + ss, sn, _ := strings.Cut(s, ".") // Parse the seconds. secs, err := strconv.ParseInt(ss, 10, 64) @@ -254,48 +251,32 @@ func formatPAXTime(ts time.Time) (s string) { // return the remainder as r. func parsePAXRecord(s string) (k, v, r string, err error) { // The size field ends at the first space. - sp := strings.IndexByte(s, ' ') - if sp == -1 { + nStr, rest, ok := strings.Cut(s, " ") + if !ok { return "", "", s, ErrHeader } // Parse the first token as a decimal integer. - n, perr := strconv.ParseInt(s[:sp], 10, 0) // Intentionally parse as native int - if perr != nil || n < 5 || int64(len(s)) < n { + n, perr := strconv.ParseInt(nStr, 10, 0) // Intentionally parse as native int + if perr != nil || n < 5 || n > int64(len(s)) { return "", "", s, ErrHeader } - - afterSpace := int64(sp + 1) - beforeLastNewLine := n - 1 - // In some cases, "length" was perhaps padded/malformed, and - // trying to index past where the space supposedly is goes past - // the end of the actual record. - // For example: - // "0000000000000000000000000000000030 mtime=1432668921.098285006\n30 ctime=2147483649.15163319" - // ^ ^ - // | | - // | afterSpace=35 - // | - // beforeLastNewLine=29 - // yet indexOf(firstSpace) MUST BE before endOfRecord. - // - // See https://golang.org/issues/40196. - if afterSpace >= beforeLastNewLine { + n -= int64(len(nStr) + 1) // convert from index in s to index in rest + if n <= 0 { return "", "", s, ErrHeader } // Extract everything between the space and the final newline. - rec, nl, rem := s[afterSpace:beforeLastNewLine], s[beforeLastNewLine:n], s[n:] + rec, nl, rem := rest[:n-1], rest[n-1:n], rest[n:] if nl != "\n" { return "", "", s, ErrHeader } // The first equals separates the key from the value. - eq := strings.IndexByte(rec, '=') - if eq == -1 { + k, v, ok = strings.Cut(rec, "=") + if !ok { return "", "", s, ErrHeader } - k, v = rec[:eq], rec[eq+1:] if !validPAXRecord(k, v) { return "", "", s, ErrHeader @@ -333,7 +314,7 @@ func formatPAXRecord(k, v string) (string, error) { // for the PAX version of the USTAR string fields. // The key must not contain an '=' character. func validPAXRecord(k, v string) bool { - if k == "" || strings.IndexByte(k, '=') >= 0 { + if k == "" || strings.Contains(k, "=") { return false } switch k { diff --git a/src/archive/tar/writer_test.go b/src/archive/tar/writer_test.go index 43f2f5976c..95ce99a3ed 100644 --- a/src/archive/tar/writer_test.go +++ b/src/archive/tar/writer_test.go @@ -988,9 +988,7 @@ func TestIssue12594(t *testing.T) { var blk block copy(blk[:], b.Bytes()) prefix := string(blk.toUSTAR().prefix()) - if i := strings.IndexByte(prefix, 0); i >= 0 { - prefix = prefix[:i] // Truncate at the NUL terminator - } + prefix, _, _ = strings.Cut(prefix, "\x00") // Truncate at the NUL terminator if blk.getFormat() == FormatGNU && len(prefix) > 0 && strings.HasPrefix(name, prefix) { t.Errorf("test %d, found prefix in GNU format: %s", i, prefix) } diff --git a/src/archive/zip/writer_test.go b/src/archive/zip/writer_test.go index 97c6c52979..2b73eca814 100644 --- a/src/archive/zip/writer_test.go +++ b/src/archive/zip/writer_test.go @@ -362,7 +362,7 @@ func TestWriterDirAttributes(t *testing.T) { } binary.LittleEndian.PutUint32(sig[:], uint32(dataDescriptorSignature)) - if bytes.Index(b, sig[:]) != -1 { + if bytes.Contains(b, sig[:]) { t.Error("there should be no data descriptor") } } diff --git a/src/cmd/doc/dirs.go b/src/cmd/doc/dirs.go index 661624cfe4..f27af1d27b 100644 --- a/src/cmd/doc/dirs.go +++ b/src/cmd/doc/dirs.go @@ -221,11 +221,7 @@ func findCodeRoots() []Dir { cmd.Stderr = os.Stderr out, _ := cmd.Output() for _, line := range strings.Split(string(out), "\n") { - i := strings.Index(line, "\t") - if i < 0 { - continue - } - path, dir := line[:i], line[i+1:] + path, dir, _ := strings.Cut(line, "\t") if dir != "" { list = append(list, Dir{importPath: path, dir: dir, inModule: true}) } diff --git a/src/cmd/doc/pkg.go b/src/cmd/doc/pkg.go index 587f0bdc14..822c9e16f8 100644 --- a/src/cmd/doc/pkg.go +++ b/src/cmd/doc/pkg.go @@ -315,9 +315,7 @@ func (pkg *Package) oneLineNodeDepth(node ast.Node, depth int) string { recv = "(" + recv + ") " } fnc := pkg.oneLineNodeDepth(n.Type, depth) - if strings.Index(fnc, "func") == 0 { - fnc = fnc[4:] - } + fnc = strings.TrimPrefix(fnc, "func") return fmt.Sprintf("func %s%s%s", recv, name, fnc) case *ast.TypeSpec: diff --git a/src/cmd/fix/typecheck.go b/src/cmd/fix/typecheck.go index 39a53785b7..8c4beb4b65 100644 --- a/src/cmd/fix/typecheck.go +++ b/src/cmd/fix/typecheck.go @@ -544,8 +544,8 @@ func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string, a if strings.HasPrefix(t, "[") || strings.HasPrefix(t, "map[") { // Lazy: assume there are no nested [] in the array // length or map key type. - if i := strings.Index(t, "]"); i >= 0 { - typeof[n] = t[i+1:] + if _, elem, ok := strings.Cut(t, "]"); ok { + typeof[n] = elem } } @@ -575,8 +575,7 @@ func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string, a t := expand(typeof[n]) if strings.HasPrefix(t, "[") { // array or slice // Lazy: assume there are no nested [] in the array length. - if i := strings.Index(t, "]"); i >= 0 { - et := t[i+1:] + if _, et, ok := strings.Cut(t, "]"); ok { for _, e := range n.Elts { if kv, ok := e.(*ast.KeyValueExpr); ok { e = kv.Value @@ -589,8 +588,7 @@ func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string, a } if strings.HasPrefix(t, "map[") { // map // Lazy: assume there are no nested [] in the map key type. - if i := strings.Index(t, "]"); i >= 0 { - kt, vt := t[4:i], t[i+1:] + if kt, vt, ok := strings.Cut(t[len("map["):], "]"); ok { for _, e := range n.Elts { if kv, ok := e.(*ast.KeyValueExpr); ok { if typeof[kv.Key] == "" { @@ -629,12 +627,10 @@ func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string, a key, value = "int", "rune" } else if strings.HasPrefix(t, "[") { key = "int" - if i := strings.Index(t, "]"); i >= 0 { - value = t[i+1:] - } + _, value, _ = strings.Cut(t, "]") } else if strings.HasPrefix(t, "map[") { - if i := strings.Index(t, "]"); i >= 0 { - key, value = t[4:i], t[i+1:] + if k, v, ok := strings.Cut(t[len("map["):], "]"); ok { + key, value = k, v } } changed := false diff --git a/src/cmd/vet/vet_test.go b/src/cmd/vet/vet_test.go index 50dd0735fa..714ee320ae 100644 --- a/src/cmd/vet/vet_test.go +++ b/src/cmd/vet/vet_test.go @@ -241,8 +241,8 @@ func errorCheck(outStr string, wantAuto bool, fullshort ...string) (err error) { // Assume errmsg says "file:line: foo". // Cut leading "file:line: " to avoid accidental matching of file name instead of message. text := errmsg - if i := strings.Index(text, " "); i >= 0 { - text = text[i+1:] + if _, suffix, ok := strings.Cut(text, " "); ok { + text = suffix } if we.re.MatchString(text) { matched = true diff --git a/src/crypto/ecdsa/ecdsa_test.go b/src/crypto/ecdsa/ecdsa_test.go index 556818acf4..c8390b2cc9 100644 --- a/src/crypto/ecdsa/ecdsa_test.go +++ b/src/crypto/ecdsa/ecdsa_test.go @@ -219,9 +219,9 @@ func TestVectors(t *testing.T) { if line[0] == '[' { line = line[1 : len(line)-1] - parts := strings.SplitN(line, ",", 2) + curve, hash, _ := strings.Cut(line, ",") - switch parts[0] { + switch curve { case "P-224": pub.Curve = elliptic.P224() case "P-256": @@ -234,7 +234,7 @@ func TestVectors(t *testing.T) { pub.Curve = nil } - switch parts[1] { + switch hash { case "SHA-1": h = sha1.New() case "SHA-224": diff --git a/src/crypto/tls/handshake_client_test.go b/src/crypto/tls/handshake_client_test.go index b6eb488a4d..2158f3247b 100644 --- a/src/crypto/tls/handshake_client_test.go +++ b/src/crypto/tls/handshake_client_test.go @@ -97,18 +97,18 @@ func (o *opensslOutputSink) Write(data []byte) (n int, err error) { o.all = append(o.all, data...) for { - i := bytes.IndexByte(o.line, '\n') - if i < 0 { + line, next, ok := bytes.Cut(o.line, []byte("\n")) + if !ok { break } - if bytes.Equal([]byte(opensslEndOfHandshake), o.line[:i]) { + if bytes.Equal([]byte(opensslEndOfHandshake), line) { o.handshakeComplete <- struct{}{} } - if bytes.Equal([]byte(opensslReadKeyUpdate), o.line[:i]) { + if bytes.Equal([]byte(opensslReadKeyUpdate), line) { o.readKeyUpdate <- struct{}{} } - o.line = o.line[i+1:] + o.line = next } return len(data), nil diff --git a/src/crypto/tls/handshake_test.go b/src/crypto/tls/handshake_test.go index 9bfb1177f2..90ac9bd11e 100644 --- a/src/crypto/tls/handshake_test.go +++ b/src/crypto/tls/handshake_test.go @@ -191,18 +191,17 @@ func parseTestData(r io.Reader) (flows [][]byte, err error) { // Otherwise the line is a line of hex dump that looks like: // 00000170 fc f5 06 bf (...) |.....X{&?......!| // (Some bytes have been omitted from the middle section.) - - if i := strings.IndexByte(line, ' '); i >= 0 { - line = line[i:] - } else { + _, after, ok := strings.Cut(line, " ") + if !ok { return nil, errors.New("invalid test data") } + line = after - if i := strings.IndexByte(line, '|'); i >= 0 { - line = line[:i] - } else { + before, _, ok := strings.Cut(line, "|") + if !ok { return nil, errors.New("invalid test data") } + line = before hexBytes := strings.Fields(line) for _, hexByte := range hexBytes { diff --git a/src/crypto/x509/pem_decrypt.go b/src/crypto/x509/pem_decrypt.go index 781cb3de83..682923ac53 100644 --- a/src/crypto/x509/pem_decrypt.go +++ b/src/crypto/x509/pem_decrypt.go @@ -127,12 +127,11 @@ func DecryptPEMBlock(b *pem.Block, password []byte) ([]byte, error) { return nil, errors.New("x509: no DEK-Info header in block") } - idx := strings.Index(dek, ",") - if idx == -1 { + mode, hexIV, ok := strings.Cut(dek, ",") + if !ok { return nil, errors.New("x509: malformed DEK-Info header") } - mode, hexIV := dek[:idx], dek[idx+1:] ciph := cipherByName(mode) if ciph == nil { return nil, errors.New("x509: unknown encryption mode") diff --git a/src/encoding/asn1/common.go b/src/encoding/asn1/common.go index 1c712e1eff..40115df8b4 100644 --- a/src/encoding/asn1/common.go +++ b/src/encoding/asn1/common.go @@ -94,14 +94,7 @@ type fieldParameters struct { func parseFieldParameters(str string) (ret fieldParameters) { var part string for len(str) > 0 { - // This loop uses IndexByte and explicit slicing - // instead of strings.Split(str, ",") to reduce allocations. - i := strings.IndexByte(str, ',') - if i < 0 { - part, str = str, "" - } else { - part, str = str[:i], str[i+1:] - } + part, str, _ = strings.Cut(str, ",") switch { case part == "optional": ret.optional = true diff --git a/src/encoding/json/tags.go b/src/encoding/json/tags.go index c38fd5102f..b490328f4c 100644 --- a/src/encoding/json/tags.go +++ b/src/encoding/json/tags.go @@ -15,10 +15,8 @@ type tagOptions string // parseTag splits a struct field's json tag into its name and // comma-separated options. func parseTag(tag string) (string, tagOptions) { - if idx := strings.Index(tag, ","); idx != -1 { - return tag[:idx], tagOptions(tag[idx+1:]) - } - return tag, tagOptions("") + tag, opt, _ := strings.Cut(tag, ",") + return tag, tagOptions(opt) } // Contains reports whether a comma-separated list of options @@ -30,15 +28,11 @@ func (o tagOptions) Contains(optionName string) bool { } s := string(o) for s != "" { - var next string - i := strings.Index(s, ",") - if i >= 0 { - s, next = s[:i], s[i+1:] - } - if s == optionName { + var name string + name, s, _ = strings.Cut(s, ",") + if name == optionName { return true } - s = next } return false } diff --git a/src/encoding/pem/pem.go b/src/encoding/pem/pem.go index a7272da5ad..e7adf88382 100644 --- a/src/encoding/pem/pem.go +++ b/src/encoding/pem/pem.go @@ -78,6 +78,7 @@ func removeSpacesAndTabs(data []byte) []byte { var pemStart = []byte("\n-----BEGIN ") var pemEnd = []byte("\n-----END ") var pemEndOfLine = []byte("-----") +var colon = []byte(":") // Decode will find the next PEM formatted block (certificate, private key // etc) in the input. It returns that block and the remainder of the input. If @@ -89,8 +90,8 @@ func Decode(data []byte) (p *Block, rest []byte) { rest = data if bytes.HasPrefix(data, pemStart[1:]) { rest = rest[len(pemStart)-1 : len(data)] - } else if i := bytes.Index(data, pemStart); i >= 0 { - rest = rest[i+len(pemStart) : len(data)] + } else if _, after, ok := bytes.Cut(data, pemStart); ok { + rest = after } else { return nil, data } @@ -114,13 +115,12 @@ func Decode(data []byte) (p *Block, rest []byte) { } line, next := getLine(rest) - i := bytes.IndexByte(line, ':') - if i == -1 { + key, val, ok := bytes.Cut(line, colon) + if !ok { break } // TODO(agl): need to cope with values that spread across lines. - key, val := line[:i], line[i+1:] key = bytes.TrimSpace(key) val = bytes.TrimSpace(val) p.Headers[string(key)] = string(val) diff --git a/src/encoding/xml/typeinfo.go b/src/encoding/xml/typeinfo.go index 162724ef1a..51e976cf01 100644 --- a/src/encoding/xml/typeinfo.go +++ b/src/encoding/xml/typeinfo.go @@ -115,8 +115,8 @@ func structFieldInfo(typ reflect.Type, f *reflect.StructField) (*fieldInfo, erro // Split the tag from the xml namespace if necessary. tag := f.Tag.Get("xml") - if i := strings.Index(tag, " "); i >= 0 { - finfo.xmlns, tag = tag[:i], tag[i+1:] + if ns, t, ok := strings.Cut(tag, " "); ok { + finfo.xmlns, tag = ns, t } // Parse flags. diff --git a/src/encoding/xml/xml.go b/src/encoding/xml/xml.go index c14954df15..33d0b417b9 100644 --- a/src/encoding/xml/xml.go +++ b/src/encoding/xml/xml.go @@ -1164,11 +1164,11 @@ func (d *Decoder) nsname() (name Name, ok bool) { } if strings.Count(s, ":") > 1 { name.Local = s - } else if i := strings.Index(s, ":"); i < 1 || i > len(s)-2 { + } else if space, local, ok := strings.Cut(s, ":"); !ok || space == "" || local == "" { name.Local = s } else { - name.Space = s[0:i] - name.Local = s[i+1:] + name.Space = space + name.Local = local } return name, true } @@ -2012,25 +2012,26 @@ func emitCDATA(w io.Writer, s []byte) error { if _, err := w.Write(cdataStart); err != nil { return err } + for { - i := bytes.Index(s, cdataEnd) - if i >= 0 && i+len(cdataEnd) <= len(s) { - // Found a nested CDATA directive end. - if _, err := w.Write(s[:i]); err != nil { - return err - } - if _, err := w.Write(cdataEscape); err != nil { - return err - } - i += len(cdataEnd) - } else { - if _, err := w.Write(s); err != nil { - return err - } + before, after, ok := bytes.Cut(s, cdataEnd) + if !ok { break } - s = s[i:] + // Found a nested CDATA directive end. + if _, err := w.Write(before); err != nil { + return err + } + if _, err := w.Write(cdataEscape); err != nil { + return err + } + s = after + } + + if _, err := w.Write(s); err != nil { + return err } + _, err := w.Write(cdataEnd) return err } @@ -2041,20 +2042,16 @@ func procInst(param, s string) string { // TODO: this parsing is somewhat lame and not exact. // It works for all actual cases, though. param = param + "=" - idx := strings.Index(s, param) - if idx == -1 { - return "" - } - v := s[idx+len(param):] + _, v, _ := strings.Cut(s, param) if v == "" { return "" } if v[0] != '\'' && v[0] != '"' { return "" } - idx = strings.IndexRune(v[1:], rune(v[0])) - if idx == -1 { + unquote, _, ok := strings.Cut(v[1:], v[:1]) + if !ok { return "" } - return v[1 : idx+1] + return unquote } diff --git a/src/go/build/build.go b/src/go/build/build.go index 8afa9d5240..eb47ffe285 100644 --- a/src/go/build/build.go +++ b/src/go/build/build.go @@ -1258,19 +1258,14 @@ func findImportComment(data []byte) (s string, line int) { var comment []byte switch { case bytes.HasPrefix(data, slashSlash): - i := bytes.Index(data, newline) - if i < 0 { - i = len(data) - } - comment = data[2:i] + comment, _, _ = bytes.Cut(data[2:], newline) case bytes.HasPrefix(data, slashStar): - data = data[2:] - i := bytes.Index(data, starSlash) - if i < 0 { + var ok bool + comment, _, ok = bytes.Cut(data[2:], starSlash) + if !ok { // malformed comment return "", 0 } - comment = data[:i] if bytes.Contains(comment, newline) { return "", 0 } @@ -1654,12 +1649,10 @@ func (ctxt *Context) saveCgo(filename string, di *Package, cg *ast.CommentGroup) } // Split at colon. - line = strings.TrimSpace(line[4:]) - i := strings.Index(line, ":") - if i < 0 { + line, argstr, ok := strings.Cut(strings.TrimSpace(line[4:]), ":") + if !ok { return fmt.Errorf("%s: invalid #cgo line: %s", filename, orig) } - line, argstr := line[:i], line[i+1:] // Parse GOOS/GOARCH stuff. f := strings.Fields(line) @@ -1685,7 +1678,6 @@ func (ctxt *Context) saveCgo(filename string, di *Package, cg *ast.CommentGroup) if err != nil { return fmt.Errorf("%s: invalid #cgo line: %s", filename, orig) } - var ok bool for i, arg := range args { if arg, ok = expandSrcDir(arg, di.Dir); !ok { return fmt.Errorf("%s: malformed #cgo argument: %s", filename, arg) @@ -1944,9 +1936,7 @@ func (ctxt *Context) matchTag(name string, allTags map[string]bool) bool { // if GOOS=illumos, then files with GOOS=solaris are also matched. // if GOOS=ios, then files with GOOS=darwin are also matched. func (ctxt *Context) goodOSArchFile(name string, allTags map[string]bool) bool { - if dot := strings.Index(name, "."); dot != -1 { - name = name[:dot] - } + name, _, _ = strings.Cut(name, ".") // Before Go 1.4, a file called "linux.go" would be equivalent to having a // build tag "linux" in that file. For Go 1.4 and beyond, we require this diff --git a/src/go/build/build_test.go b/src/go/build/build_test.go index 80f930f3c2..cfe9c5e4bb 100644 --- a/src/go/build/build_test.go +++ b/src/go/build/build_test.go @@ -712,7 +712,7 @@ func TestMissingImportErrorRepetition(t *testing.T) { // Also don't count instances in suggested "go get" or similar commands // (see https://golang.org/issue/41576). The suggested command typically // follows a semicolon. - errStr = strings.SplitN(errStr, ";", 2)[0] + errStr, _, _ = strings.Cut(errStr, ";") if n := strings.Count(errStr, pkgPath); n != 1 { t.Fatalf("package path %q appears in error %d times; should appear once\nerror: %v", pkgPath, n, err) diff --git a/src/go/build/read.go b/src/go/build/read.go index b98c7938a8..6115ef810c 100644 --- a/src/go/build/read.go +++ b/src/go/build/read.go @@ -516,12 +516,12 @@ func parseGoEmbed(args string, pos token.Position) ([]fileEmbed, error) { trimBytes(i) case '`': - i := strings.Index(args[1:], "`") - if i < 0 { + var ok bool + path, _, ok = strings.Cut(args[1:], "`") + if !ok { return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args) } - path = args[1 : 1+i] - trimBytes(1 + i + 1) + trimBytes(1 + len(path) + 1) case '"': i := 1 diff --git a/src/go/build/read_test.go b/src/go/build/read_test.go index 1e5e1c2de2..6851e6b6d6 100644 --- a/src/go/build/read_test.go +++ b/src/go/build/read_test.go @@ -119,20 +119,15 @@ var readCommentsTests = []readTest{ func testRead(t *testing.T, tests []readTest, read func(io.Reader) ([]byte, error)) { for i, tt := range tests { - var in, testOut string - j := strings.Index(tt.in, "ℙ") - if j < 0 { - in = tt.in - testOut = tt.in - } else { - in = tt.in[:j] + tt.in[j+len("ℙ"):] - testOut = tt.in[:j] - } - d := strings.Index(tt.in, "𝔻") - if d >= 0 { - in = in[:d] + in[d+len("𝔻"):] - testOut = testOut[d+len("𝔻"):] + beforeP, afterP, _ := strings.Cut(tt.in, "ℙ") + in := beforeP + afterP + testOut := beforeP + + if beforeD, afterD, ok := strings.Cut(beforeP, "𝔻"); ok { + in = beforeD + afterD + afterP + testOut = afterD } + r := strings.NewReader(in) buf, err := read(r) if err != nil { diff --git a/src/go/constant/value_test.go b/src/go/constant/value_test.go index 91ad0b0c2b..ac179b3d8c 100644 --- a/src/go/constant/value_test.go +++ b/src/go/constant/value_test.go @@ -143,9 +143,9 @@ func testNumbers(t *testing.T, kind token.Token, tests []string) { if a[1] == "?" { y = MakeUnknown() } else { - if i := strings.Index(a[1], "/"); i >= 0 && kind == token.FLOAT { - n := MakeFromLiteral(a[1][:i], token.INT, 0) - d := MakeFromLiteral(a[1][i+1:], token.INT, 0) + if ns, ds, ok := strings.Cut(a[1], "/"); ok && kind == token.FLOAT { + n := MakeFromLiteral(ns, token.INT, 0) + d := MakeFromLiteral(ds, token.INT, 0) y = BinaryOp(n, token.QUO, d) } else { y = MakeFromLiteral(a[1], kind, 0) @@ -454,10 +454,10 @@ func val(lit string) Value { return MakeBool(false) } - if i := strings.IndexByte(lit, '/'); i >= 0 { + if as, bs, ok := strings.Cut(lit, "/"); ok { // assume fraction - a := MakeFromLiteral(lit[:i], token.INT, 0) - b := MakeFromLiteral(lit[i+1:], token.INT, 0) + a := MakeFromLiteral(as, token.INT, 0) + b := MakeFromLiteral(bs, token.INT, 0) return BinaryOp(a, token.QUO, b) } diff --git a/src/go/doc/comment.go b/src/go/doc/comment.go index 92131a3b83..a93c05fbb7 100644 --- a/src/go/doc/comment.go +++ b/src/go/doc/comment.go @@ -236,26 +236,24 @@ func heading(line string) string { // allow "'" for possessive "'s" only for b := line; ; { - i := strings.IndexRune(b, '\'') - if i < 0 { + var ok bool + if _, b, ok = strings.Cut(b, "'"); !ok { break } - if i+1 >= len(b) || b[i+1] != 's' || (i+2 < len(b) && b[i+2] != ' ') { - return "" // not followed by "s " + if b != "s" && !strings.HasPrefix(b, "s ") { + return "" // ' not followed by s and then end-of-word } - b = b[i+2:] } // allow "." when followed by non-space for b := line; ; { - i := strings.IndexRune(b, '.') - if i < 0 { + var ok bool + if _, b, ok = strings.Cut(b, "."); !ok { break } - if i+1 >= len(b) || b[i+1] == ' ' { + if b == "" || strings.HasPrefix(b, " ") { return "" // not followed by non-space } - b = b[i+1:] } return line diff --git a/src/go/doc/headscan.go b/src/go/doc/headscan.go index 28cb84f91d..df54b4bd61 100644 --- a/src/go/doc/headscan.go +++ b/src/go/doc/headscan.go @@ -23,10 +23,10 @@ import ( "go/doc" "go/parser" "go/token" - "internal/lazyregexp" "io/fs" "os" "path/filepath" + "regexp" "runtime" "strings" ) @@ -37,7 +37,7 @@ var ( ) // ToHTML in comment.go assigns a (possibly blank) ID to each heading -var html_h = lazyregexp.New(`

`) +var html_h = regexp.MustCompile(`

`) const html_endh = "

\n" @@ -49,19 +49,14 @@ func isGoFile(fi fs.FileInfo) bool { func appendHeadings(list []string, comment string) []string { var buf bytes.Buffer doc.ToHTML(&buf, comment, nil) - for s := buf.String(); ; { + for s := buf.String(); s != ""; { loc := html_h.FindStringIndex(s) if len(loc) == 0 { break } - i := loc[1] - j := strings.Index(s, html_endh) - if j < 0 { - list = append(list, s[i:]) // incorrect HTML - break - } - list = append(list, s[i:j]) - s = s[j+len(html_endh):] + var inner string + inner, s, _ = strings.Cut(s[loc[1]:], html_endh) + list = append(list, inner) } return list } diff --git a/src/go/importer/importer_test.go b/src/go/importer/importer_test.go index 0f5121d802..27c4aa7871 100644 --- a/src/go/importer/importer_test.go +++ b/src/go/importer/importer_test.go @@ -24,8 +24,7 @@ func TestForCompiler(t *testing.T) { t.Fatalf("go list %s: %v\n%s", thePackage, err, out) } target := strings.TrimSpace(string(out)) - i := strings.Index(target, ":") - compiler, target := target[:i], target[i+1:] + compiler, target, _ := strings.Cut(target, ":") if !strings.HasSuffix(target, ".a") { t.Fatalf("unexpected package %s target %q (not *.a)", thePackage, target) } diff --git a/src/go/printer/nodes.go b/src/go/printer/nodes.go index 053a8ef174..567b2339b4 100644 --- a/src/go/printer/nodes.go +++ b/src/go/printer/nodes.go @@ -1049,7 +1049,7 @@ func normalizedNumber(lit *ast.BasicLit) *ast.BasicLit { break } // remove leading 0's from integer (but not floating-point) imaginary literals - if x[len(x)-1] == 'i' && strings.IndexByte(x, '.') < 0 && strings.IndexByte(x, 'e') < 0 { + if x[len(x)-1] == 'i' && !strings.ContainsAny(x, ".e") { x = strings.TrimLeft(x, "0_") if x == "i" { x = "0i" diff --git a/src/go/printer/printer.go b/src/go/printer/printer.go index ba61f78226..2f41e7bf72 100644 --- a/src/go/printer/printer.go +++ b/src/go/printer/printer.go @@ -559,12 +559,9 @@ func stripCommonPrefix(lines []string) { * Check for vertical "line of stars" and correct prefix accordingly. */ lineOfStars := false - if i := strings.Index(prefix, "*"); i >= 0 { - // Line of stars present. - if i > 0 && prefix[i-1] == ' ' { - i-- // remove trailing blank from prefix so stars remain aligned - } - prefix = prefix[0:i] + if p, _, ok := strings.Cut(prefix, "*"); ok { + // remove trailing blank from prefix so stars remain aligned + prefix = strings.TrimSuffix(p, " ") lineOfStars = true } else { // No line of stars present. @@ -616,8 +613,8 @@ func stripCommonPrefix(lines []string) { // lines. last := lines[len(lines)-1] closing := "*/" - i := strings.Index(last, closing) // i >= 0 (closing is always present) - if isBlank(last[0:i]) { + before, _, _ := strings.Cut(last, closing) // closing always present + if isBlank(before) { // last line only contains closing */ if lineOfStars { closing = " */" // add blank to align final star diff --git a/src/go/types/eval_test.go b/src/go/types/eval_test.go index 41d3a61b89..345bd14305 100644 --- a/src/go/types/eval_test.go +++ b/src/go/types/eval_test.go @@ -195,10 +195,10 @@ func TestEvalPos(t *testing.T) { } } -// split splits string s at the first occurrence of s. +// split splits string s at the first occurrence of s, trimming spaces. func split(s, sep string) (string, string) { - i := strings.Index(s, sep) - return strings.TrimSpace(s[:i]), strings.TrimSpace(s[i+len(sep):]) + before, after, _ := strings.Cut(s, sep) + return strings.TrimSpace(before), strings.TrimSpace(after) } func TestCheckExpr(t *testing.T) { diff --git a/src/html/template/attr.go b/src/html/template/attr.go index 22922e6038..6c52211fed 100644 --- a/src/html/template/attr.go +++ b/src/html/template/attr.go @@ -143,12 +143,12 @@ func attrType(name string) contentType { // widely applied. // Treat data-action as URL below. name = name[5:] - } else if colon := strings.IndexRune(name, ':'); colon != -1 { - if name[:colon] == "xmlns" { + } else if prefix, short, ok := strings.Cut(name, ":"); ok { + if prefix == "xmlns" { return contentTypeURL } // Treat svg:href and xlink:href as href below. - name = name[colon+1:] + name = short } if t, ok := attrTypeMap[name]; ok { return t diff --git a/src/html/template/js.go b/src/html/template/js.go index ea9c18346b..32a4fbd30a 100644 --- a/src/html/template/js.go +++ b/src/html/template/js.go @@ -398,9 +398,7 @@ func isJSType(mimeType string) bool { // https://tools.ietf.org/html/rfc4329#section-3 // https://www.ietf.org/rfc/rfc4627.txt // discard parameters - if i := strings.Index(mimeType, ";"); i >= 0 { - mimeType = mimeType[:i] - } + mimeType, _, _ = strings.Cut(mimeType, ";") mimeType = strings.ToLower(mimeType) mimeType = strings.TrimSpace(mimeType) switch mimeType { diff --git a/src/html/template/url.go b/src/html/template/url.go index 6f8185a4e9..4b39fddf07 100644 --- a/src/html/template/url.go +++ b/src/html/template/url.go @@ -46,9 +46,7 @@ func urlFilter(args ...interface{}) string { // isSafeURL is true if s is a relative URL or if URL has a protocol in // (http, https, mailto). func isSafeURL(s string) bool { - if i := strings.IndexRune(s, ':'); i >= 0 && !strings.ContainsRune(s[:i], '/') { - - protocol := s[:i] + if protocol, _, ok := strings.Cut(s, ":"); ok && !strings.Contains(protocol, "/") { if !strings.EqualFold(protocol, "http") && !strings.EqualFold(protocol, "https") && !strings.EqualFold(protocol, "mailto") { return false } diff --git a/src/internal/profile/legacy_profile.go b/src/internal/profile/legacy_profile.go index d69f8deee7..377a43d585 100644 --- a/src/internal/profile/legacy_profile.go +++ b/src/internal/profile/legacy_profile.go @@ -750,11 +750,11 @@ func parseCppContention(r *bytes.Buffer) (*Profile, error) { break } - attr := strings.SplitN(l, delimiter, 2) - if len(attr) != 2 { + key, val, ok := strings.Cut(l, delimiter) + if !ok { break } - key, val := strings.TrimSpace(attr[0]), strings.TrimSpace(attr[1]) + key, val = strings.TrimSpace(key), strings.TrimSpace(val) var err error switch key { case "cycles/second": @@ -1050,8 +1050,8 @@ func (p *Profile) ParseMemoryMap(rd io.Reader) error { if err == errUnrecognized { // Recognize assignments of the form: attr=value, and replace // $attr with value on subsequent mappings. - if attr := strings.SplitN(l, delimiter, 2); len(attr) == 2 { - attrs = append(attrs, "$"+strings.TrimSpace(attr[0]), strings.TrimSpace(attr[1])) + if attr, value, ok := strings.Cut(l, delimiter); ok { + attrs = append(attrs, "$"+strings.TrimSpace(attr), strings.TrimSpace(value)) r = strings.NewReplacer(attrs...) } // Ignore any unrecognized entries diff --git a/src/mime/encodedword.go b/src/mime/encodedword.go index 58f60daec4..e6b470b1fb 100644 --- a/src/mime/encodedword.go +++ b/src/mime/encodedword.go @@ -203,35 +203,25 @@ func (d *WordDecoder) Decode(word string) (string, error) { } word = word[2 : len(word)-2] - // split delimits the first 2 fields - split := strings.IndexByte(word, '?') - - // split word "UTF-8?q?ascii" into "UTF-8", 'q', and "ascii" - charset := word[:split] - if len(charset) == 0 { - return "", errInvalidWord - } - if len(word) < split+3 { + // split word "UTF-8?q?text" into "UTF-8", 'q', and "text" + charset, text, _ := strings.Cut(word, "?") + if charset == "" { return "", errInvalidWord } - encoding := word[split+1] - // the field after split must only be one byte - if word[split+2] != '?' { + encoding, text, _ := strings.Cut(text, "?") + if len(encoding) != 1 { return "", errInvalidWord } - text := word[split+3:] - content, err := decode(encoding, text) + content, err := decode(encoding[0], text) if err != nil { return "", err } var buf strings.Builder - if err := d.convert(&buf, charset, content); err != nil { return "", err } - return buf.String(), nil } diff --git a/src/mime/mediatype.go b/src/mime/mediatype.go index 56ceb48853..9456570cf1 100644 --- a/src/mime/mediatype.go +++ b/src/mime/mediatype.go @@ -19,13 +19,12 @@ import ( // FormatMediaType returns the empty string. func FormatMediaType(t string, param map[string]string) string { var b strings.Builder - if slash := strings.IndexByte(t, '/'); slash == -1 { + if major, sub, ok := strings.Cut(t, "/"); !ok { if !isToken(t) { return "" } b.WriteString(strings.ToLower(t)) } else { - major, sub := t[:slash], t[slash+1:] if !isToken(major) || !isToken(sub) { return "" } @@ -138,11 +137,8 @@ var ErrInvalidMediaParameter = errors.New("mime: invalid media parameter") // The returned map, params, maps from the lowercase // attribute to the attribute value with its case preserved. func ParseMediaType(v string) (mediatype string, params map[string]string, err error) { - i := strings.Index(v, ";") - if i == -1 { - i = len(v) - } - mediatype = strings.TrimSpace(strings.ToLower(v[0:i])) + base, _, _ := strings.Cut(v, ";") + mediatype = strings.TrimSpace(strings.ToLower(base)) err = checkMediaTypeDisposition(mediatype) if err != nil { @@ -156,7 +152,7 @@ func ParseMediaType(v string) (mediatype string, params map[string]string, err e // Lazily initialized. var continuation map[string]map[string]string - v = v[i:] + v = v[len(base):] for len(v) > 0 { v = strings.TrimLeftFunc(v, unicode.IsSpace) if len(v) == 0 { @@ -174,8 +170,7 @@ func ParseMediaType(v string) (mediatype string, params map[string]string, err e } pmap := params - if idx := strings.Index(key, "*"); idx != -1 { - baseName := key[:idx] + if baseName, _, ok := strings.Cut(key, "*"); ok { if continuation == nil { continuation = make(map[string]map[string]string) } diff --git a/src/net/http/cgi/child.go b/src/net/http/cgi/child.go index 0114da377b..bdb35a64e5 100644 --- a/src/net/http/cgi/child.go +++ b/src/net/http/cgi/child.go @@ -39,8 +39,8 @@ func Request() (*http.Request, error) { func envMap(env []string) map[string]string { m := make(map[string]string) for _, kv := range env { - if idx := strings.Index(kv, "="); idx != -1 { - m[kv[:idx]] = kv[idx+1:] + if k, v, ok := strings.Cut(kv, "="); ok { + m[k] = v } } return m diff --git a/src/net/http/cgi/host.go b/src/net/http/cgi/host.go index eff67caf4e..e7124a2ab0 100644 --- a/src/net/http/cgi/host.go +++ b/src/net/http/cgi/host.go @@ -273,12 +273,11 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { break } headerLines++ - parts := strings.SplitN(string(line), ":", 2) - if len(parts) < 2 { + header, val, ok := strings.Cut(string(line), ":") + if !ok { h.printf("cgi: bogus header line: %s", string(line)) continue } - header, val := parts[0], parts[1] if !httpguts.ValidHeaderFieldName(header) { h.printf("cgi: invalid header name: %q", header) continue diff --git a/src/net/http/cgi/host_test.go b/src/net/http/cgi/host_test.go index fb869a6728..f8abc88c89 100644 --- a/src/net/http/cgi/host_test.go +++ b/src/net/http/cgi/host_test.go @@ -62,12 +62,12 @@ readlines: } linesRead++ trimmedLine := strings.TrimRight(line, "\r\n") - split := strings.SplitN(trimmedLine, "=", 2) - if len(split) != 2 { - t.Fatalf("Unexpected %d parts from invalid line number %v: %q; existing map=%v", - len(split), linesRead, line, m) + k, v, ok := strings.Cut(trimmedLine, "=") + if !ok { + t.Fatalf("Unexpected response from invalid line number %v: %q; existing map=%v", + linesRead, line, m) } - m[split[0]] = split[1] + m[k] = v } for key, expected := range expectedMap { diff --git a/src/net/http/client_test.go b/src/net/http/client_test.go index 05ed2268b5..e741c3746f 100644 --- a/src/net/http/client_test.go +++ b/src/net/http/client_test.go @@ -431,11 +431,10 @@ func testRedirectsByMethod(t *testing.T, method string, table []redirectTest, wa if v := urlQuery.Get("code"); v != "" { location := ts.URL if final := urlQuery.Get("next"); final != "" { - splits := strings.Split(final, ",") - first, rest := splits[0], splits[1:] + first, rest, _ := strings.Cut(final, ",") location = fmt.Sprintf("%s?code=%s", location, first) - if len(rest) > 0 { - location = fmt.Sprintf("%s&next=%s", location, strings.Join(rest, ",")) + if rest != "" { + location = fmt.Sprintf("%s&next=%s", location, rest) } } code, _ := strconv.Atoi(v) diff --git a/src/net/http/cookie.go b/src/net/http/cookie.go index ca2c1c2506..02b40315de 100644 --- a/src/net/http/cookie.go +++ b/src/net/http/cookie.go @@ -67,15 +67,14 @@ func readSetCookies(h Header) []*Cookie { continue } parts[0] = textproto.TrimString(parts[0]) - j := strings.Index(parts[0], "=") - if j < 0 { + name, value, ok := strings.Cut(parts[0], "=") + if !ok { continue } - name, value := parts[0][:j], parts[0][j+1:] if !isCookieNameValid(name) { continue } - value, ok := parseCookieValue(value, true) + value, ok = parseCookieValue(value, true) if !ok { continue } @@ -90,10 +89,7 @@ func readSetCookies(h Header) []*Cookie { continue } - attr, val := parts[i], "" - if j := strings.Index(attr, "="); j >= 0 { - attr, val = attr[:j], attr[j+1:] - } + attr, val, _ := strings.Cut(parts[i], "=") lowerAttr, isASCII := ascii.ToLower(attr) if !isASCII { continue @@ -256,19 +252,12 @@ func readCookies(h Header, filter string) []*Cookie { var part string for len(line) > 0 { // continue since we have rest - if splitIndex := strings.Index(line, ";"); splitIndex > 0 { - part, line = line[:splitIndex], line[splitIndex+1:] - } else { - part, line = line, "" - } + part, line, _ = strings.Cut(line, ";") part = textproto.TrimString(part) - if len(part) == 0 { + if part == "" { continue } - name, val := part, "" - if j := strings.Index(part, "="); j >= 0 { - name, val = name[:j], name[j+1:] - } + name, val, _ := strings.Cut(part, "=") if !isCookieNameValid(name) { continue } @@ -379,7 +368,7 @@ func sanitizeCookieValue(v string) string { if len(v) == 0 { return v } - if strings.IndexByte(v, ' ') >= 0 || strings.IndexByte(v, ',') >= 0 { + if strings.ContainsAny(v, " ,") { return `"` + v + `"` } return v diff --git a/src/net/http/fs.go b/src/net/http/fs.go index 57e731e481..19b2894bf2 100644 --- a/src/net/http/fs.go +++ b/src/net/http/fs.go @@ -881,11 +881,11 @@ func parseRange(s string, size int64) ([]httpRange, error) { if ra == "" { continue } - i := strings.Index(ra, "-") - if i < 0 { + start, end, ok := strings.Cut(ra, "-") + if !ok { return nil, errors.New("invalid range") } - start, end := textproto.TrimString(ra[:i]), textproto.TrimString(ra[i+1:]) + start, end = textproto.TrimString(start), textproto.TrimString(end) var r httpRange if start == "" { // If no start is specified, end specifies the diff --git a/src/net/http/internal/chunked.go b/src/net/http/internal/chunked.go index f06e5725f3..923e6a6d2c 100644 --- a/src/net/http/internal/chunked.go +++ b/src/net/http/internal/chunked.go @@ -152,6 +152,8 @@ func isASCIISpace(b byte) bool { return b == ' ' || b == '\t' || b == '\n' || b == '\r' } +var semi = []byte(";") + // removeChunkExtension removes any chunk-extension from p. // For example, // "0" => "0" @@ -159,14 +161,11 @@ func isASCIISpace(b byte) bool { // "0;token=val" => "0" // `0;token="quoted string"` => "0" func removeChunkExtension(p []byte) ([]byte, error) { - semi := bytes.IndexByte(p, ';') - if semi == -1 { - return p, nil - } + p, _, _ = bytes.Cut(p, semi) // TODO: care about exact syntax of chunk extensions? We're // ignoring and stripping them anyway. For now just never // return an error. - return p[:semi], nil + return p, nil } // NewChunkedWriter returns a new chunkedWriter that translates writes into HTTP diff --git a/src/net/http/main_test.go b/src/net/http/main_test.go index 6564627998..632a308a5c 100644 --- a/src/net/http/main_test.go +++ b/src/net/http/main_test.go @@ -31,11 +31,8 @@ func interestingGoroutines() (gs []string) { buf := make([]byte, 2<<20) buf = buf[:runtime.Stack(buf, true)] for _, g := range strings.Split(string(buf), "\n\n") { - sl := strings.SplitN(g, "\n", 2) - if len(sl) != 2 { - continue - } - stack := strings.TrimSpace(sl[1]) + _, stack, _ := strings.Cut(g, "\n") + stack = strings.TrimSpace(stack) if stack == "" || strings.Contains(stack, "testing.(*M).before.func1") || strings.Contains(stack, "os/signal.signal_recv") || diff --git a/src/net/http/request.go b/src/net/http/request.go index 0eb7042d7b..76c2317d28 100644 --- a/src/net/http/request.go +++ b/src/net/http/request.go @@ -940,7 +940,7 @@ func NewRequestWithContext(ctx context.Context, method, url string, body io.Read func (r *Request) BasicAuth() (username, password string, ok bool) { auth := r.Header.Get("Authorization") if auth == "" { - return + return "", "", false } return parseBasicAuth(auth) } @@ -951,18 +951,18 @@ func parseBasicAuth(auth string) (username, password string, ok bool) { const prefix = "Basic " // Case insensitive prefix match. See Issue 22736. if len(auth) < len(prefix) || !ascii.EqualFold(auth[:len(prefix)], prefix) { - return + return "", "", false } c, err := base64.StdEncoding.DecodeString(auth[len(prefix):]) if err != nil { - return + return "", "", false } cs := string(c) - s := strings.IndexByte(cs, ':') - if s < 0 { - return + username, password, ok = strings.Cut(cs, ":") + if !ok { + return "", "", false } - return cs[:s], cs[s+1:], true + return username, password, true } // SetBasicAuth sets the request's Authorization header to use HTTP @@ -980,13 +980,12 @@ func (r *Request) SetBasicAuth(username, password string) { // parseRequestLine parses "GET /foo HTTP/1.1" into its three parts. func parseRequestLine(line string) (method, requestURI, proto string, ok bool) { - s1 := strings.Index(line, " ") - s2 := strings.Index(line[s1+1:], " ") - if s1 < 0 || s2 < 0 { - return + method, rest, ok1 := strings.Cut(line, " ") + requestURI, proto, ok2 := strings.Cut(rest, " ") + if !ok1 || !ok2 { + return "", "", "", false } - s2 += s1 + 1 - return line[:s1], line[s1+1 : s2], line[s2+1:], true + return method, requestURI, proto, true } var textprotoReaderPool sync.Pool diff --git a/src/net/http/response.go b/src/net/http/response.go index b8985da3c8..297394eabe 100644 --- a/src/net/http/response.go +++ b/src/net/http/response.go @@ -165,16 +165,14 @@ func ReadResponse(r *bufio.Reader, req *Request) (*Response, error) { } return nil, err } - if i := strings.IndexByte(line, ' '); i == -1 { + proto, status, ok := strings.Cut(line, " ") + if !ok { return nil, badStringError("malformed HTTP response", line) - } else { - resp.Proto = line[:i] - resp.Status = strings.TrimLeft(line[i+1:], " ") - } - statusCode := resp.Status - if i := strings.IndexByte(resp.Status, ' '); i != -1 { - statusCode = resp.Status[:i] } + resp.Proto = proto + resp.Status = strings.TrimLeft(status, " ") + + statusCode, _, _ := strings.Cut(resp.Status, " ") if len(statusCode) != 3 { return nil, badStringError("malformed HTTP status code", statusCode) } @@ -182,7 +180,6 @@ func ReadResponse(r *bufio.Reader, req *Request) (*Response, error) { if err != nil || resp.StatusCode < 0 { return nil, badStringError("malformed HTTP status code", statusCode) } - var ok bool if resp.ProtoMajor, resp.ProtoMinor, ok = ParseHTTPVersion(resp.Proto); !ok { return nil, badStringError("malformed HTTP version", resp.Proto) } diff --git a/src/net/http/server.go b/src/net/http/server.go index 4d0ce5619f..55fd4ae22f 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -2282,7 +2282,7 @@ func cleanPath(p string) string { // stripHostPort returns h without any trailing ":". func stripHostPort(h string) string { // If no port on host, return unchanged - if strings.IndexByte(h, ':') == -1 { + if !strings.Contains(h, ":") { return h } host, _, err := net.SplitHostPort(h) diff --git a/src/net/http/transport.go b/src/net/http/transport.go index 309194e8e5..17f0047b59 100644 --- a/src/net/http/transport.go +++ b/src/net/http/transport.go @@ -1715,12 +1715,12 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (pconn *pers return nil, err } if resp.StatusCode != 200 { - f := strings.SplitN(resp.Status, " ", 2) + _, text, ok := strings.Cut(resp.Status, " ") conn.Close() - if len(f) < 2 { + if !ok { return nil, errors.New("unknown status code") } - return nil, errors.New(f[1]) + return nil, errors.New(text) } } diff --git a/src/net/mail/message.go b/src/net/mail/message.go index 47bbf6ca97..c120316730 100644 --- a/src/net/mail/message.go +++ b/src/net/mail/message.go @@ -100,7 +100,7 @@ func ParseDate(date string) (time.Time, error) { dateLayoutsBuildOnce.Do(buildDateLayouts) // CR and LF must match and are tolerated anywhere in the date field. date = strings.ReplaceAll(date, "\r\n", "") - if strings.Index(date, "\r") != -1 { + if strings.Contains(date, "\r") { return time.Time{}, errors.New("mail: header has a CR without LF") } // Re-using some addrParser methods which support obsolete text, i.e. non-printable ASCII diff --git a/src/net/main_posix_test.go b/src/net/main_posix_test.go index c9ab25a4ad..c804c4e755 100644 --- a/src/net/main_posix_test.go +++ b/src/net/main_posix_test.go @@ -18,9 +18,9 @@ func enableSocketConnect() { } func disableSocketConnect(network string) { - ss := strings.Split(network, ":") + net, _, _ := strings.Cut(network, ":") sw.Set(socktest.FilterConnect, func(so *socktest.Status) (socktest.AfterFilter, error) { - switch ss[0] { + switch net { case "tcp4": if so.Cookie.Family() == syscall.AF_INET && so.Cookie.Type() == syscall.SOCK_STREAM { return nil, syscall.EHOSTUNREACH diff --git a/src/net/main_test.go b/src/net/main_test.go index dc17d3fbb8..4f004071f0 100644 --- a/src/net/main_test.go +++ b/src/net/main_test.go @@ -174,11 +174,8 @@ func runningGoroutines() []string { b := make([]byte, 2<<20) b = b[:runtime.Stack(b, true)] for _, s := range strings.Split(string(b), "\n\n") { - ss := strings.SplitN(s, "\n", 2) - if len(ss) != 2 { - continue - } - stack := strings.TrimSpace(ss[1]) + _, stack, _ := strings.Cut(s, "\n") + stack = strings.TrimSpace(stack) if !strings.Contains(stack, "created by net") { continue } diff --git a/src/net/platform_test.go b/src/net/platform_test.go index 2da23dedce..7d92a0de5d 100644 --- a/src/net/platform_test.go +++ b/src/net/platform_test.go @@ -34,8 +34,8 @@ func init() { // testableNetwork reports whether network is testable on the current // platform configuration. func testableNetwork(network string) bool { - ss := strings.Split(network, ":") - switch ss[0] { + net, _, _ := strings.Cut(network, ":") + switch net { case "ip+nopriv": case "ip", "ip4", "ip6": switch runtime.GOOS { @@ -68,7 +68,7 @@ func testableNetwork(network string) bool { } } } - switch ss[0] { + switch net { case "tcp4", "udp4", "ip4": if !supportsIPv4() { return false @@ -88,7 +88,7 @@ func iOS() bool { // testableAddress reports whether address of network is testable on // the current platform configuration. func testableAddress(network, address string) bool { - switch ss := strings.Split(network, ":"); ss[0] { + switch net, _, _ := strings.Cut(network, ":"); net { case "unix", "unixgram", "unixpacket": // Abstract unix domain sockets, a Linux-ism. if address[0] == '@' && runtime.GOOS != "linux" { @@ -107,7 +107,7 @@ func testableListenArgs(network, address, client string) bool { var err error var addr Addr - switch ss := strings.Split(network, ":"); ss[0] { + switch net, _, _ := strings.Cut(network, ":"); net { case "tcp", "tcp4", "tcp6": addr, err = ResolveTCPAddr("tcp", address) case "udp", "udp4", "udp6": diff --git a/src/net/smtp/smtp.go b/src/net/smtp/smtp.go index 1a6864a0f2..bcccaa2597 100644 --- a/src/net/smtp/smtp.go +++ b/src/net/smtp/smtp.go @@ -136,12 +136,8 @@ func (c *Client) ehlo() error { if len(extList) > 1 { extList = extList[1:] for _, line := range extList { - args := strings.SplitN(line, " ", 2) - if len(args) > 1 { - ext[args[0]] = args[1] - } else { - ext[args[0]] = "" - } + k, v, _ := strings.Cut(line, " ") + ext[k] = v } } if mechs, ok := ext["AUTH"]; ok { diff --git a/src/net/textproto/reader.go b/src/net/textproto/reader.go index 5c3084f8a7..157c59b17a 100644 --- a/src/net/textproto/reader.go +++ b/src/net/textproto/reader.go @@ -460,6 +460,8 @@ func (r *Reader) ReadDotLines() ([]string, error) { return v, err } +var colon = []byte(":") + // ReadMIMEHeader reads a MIME-style header from r. // The header is a sequence of possibly continued Key: Value lines // ending in a blank line. @@ -508,11 +510,11 @@ func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) { } // Key ends at first colon. - i := bytes.IndexByte(kv, ':') - if i < 0 { + k, v, ok := bytes.Cut(kv, colon) + if !ok { return m, ProtocolError("malformed MIME header line: " + string(kv)) } - key := canonicalMIMEHeaderKey(kv[:i]) + key := canonicalMIMEHeaderKey(k) // As per RFC 7230 field-name is a token, tokens consist of one or more chars. // We could return a ProtocolError here, but better to be liberal in what we @@ -522,11 +524,7 @@ func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) { } // Skip initial spaces in value. - i++ // skip colon - for i < len(kv) && (kv[i] == ' ' || kv[i] == '\t') { - i++ - } - value := string(kv[i:]) + value := strings.TrimLeft(string(v), " \t") vv := m[key] if vv == nil && len(strs) > 0 { @@ -561,6 +559,8 @@ func mustHaveFieldNameColon(line []byte) error { return nil } +var nl = []byte("\n") + // upcomingHeaderNewlines returns an approximation of the number of newlines // that will be in this header. If it gets confused, it returns 0. func (r *Reader) upcomingHeaderNewlines() (n int) { @@ -571,17 +571,7 @@ func (r *Reader) upcomingHeaderNewlines() (n int) { return } peek, _ := r.R.Peek(s) - for len(peek) > 0 { - i := bytes.IndexByte(peek, '\n') - if i < 3 { - // Not present (-1) or found within the next few bytes, - // implying we're at the end ("\r\n\r\n" or "\n\n") - return - } - n++ - peek = peek[i+1:] - } - return + return bytes.Count(peek, nl) } // CanonicalMIMEHeaderKey returns the canonical format of the diff --git a/src/net/url/url.go b/src/net/url/url.go index 20de0f6f51..d571ab2fc4 100644 --- a/src/net/url/url.go +++ b/src/net/url/url.go @@ -452,20 +452,6 @@ func getScheme(rawURL string) (scheme, path string, err error) { return "", rawURL, nil } -// split slices s into two substrings separated by the first occurrence of -// sep. If cutc is true then sep is excluded from the second substring. -// If sep does not occur in s then s and the empty string is returned. -func split(s string, sep byte, cutc bool) (string, string) { - i := strings.IndexByte(s, sep) - if i < 0 { - return s, "" - } - if cutc { - return s[:i], s[i+1:] - } - return s[:i], s[i:] -} - // Parse parses a raw url into a URL structure. // // The url may be relative (a path, without a host) or absolute @@ -474,7 +460,7 @@ func split(s string, sep byte, cutc bool) (string, string) { // error, due to parsing ambiguities. func Parse(rawURL string) (*URL, error) { // Cut off #frag - u, frag := split(rawURL, '#', true) + u, frag, _ := strings.Cut(rawURL, "#") url, err := parse(u, false) if err != nil { return nil, &Error{"parse", u, err} @@ -534,7 +520,7 @@ func parse(rawURL string, viaRequest bool) (*URL, error) { url.ForceQuery = true rest = rest[:len(rest)-1] } else { - rest, url.RawQuery = split(rest, '?', true) + rest, url.RawQuery, _ = strings.Cut(rest, "?") } if !strings.HasPrefix(rest, "/") { @@ -553,9 +539,7 @@ func parse(rawURL string, viaRequest bool) (*URL, error) { // RFC 3986, §3.3: // In addition, a URI reference (Section 4.1) may be a relative-path reference, // in which case the first path segment cannot contain a colon (":") character. - colon := strings.Index(rest, ":") - slash := strings.Index(rest, "/") - if colon >= 0 && (slash < 0 || colon < slash) { + if segment, _, _ := strings.Cut(rest, "/"); strings.Contains(segment, ":") { // First path segment has colon. Not allowed in relative URL. return nil, errors.New("first path segment in URL cannot contain colon") } @@ -563,7 +547,10 @@ func parse(rawURL string, viaRequest bool) (*URL, error) { if (url.Scheme != "" || !viaRequest && !strings.HasPrefix(rest, "///")) && strings.HasPrefix(rest, "//") { var authority string - authority, rest = split(rest[2:], '/', false) + authority, rest = rest[2:], "" + if i := strings.Index(authority, "/"); i >= 0 { + authority, rest = authority[:i], authority[i:] + } url.User, url.Host, err = parseAuthority(authority) if err != nil { return nil, err @@ -602,7 +589,7 @@ func parseAuthority(authority string) (user *Userinfo, host string, err error) { } user = User(userinfo) } else { - username, password := split(userinfo, ':', true) + username, password, _ := strings.Cut(userinfo, ":") if username, err = unescape(username, encodeUserPassword); err != nil { return nil, "", err } @@ -840,7 +827,7 @@ func (u *URL) String() string { // it would be mistaken for a scheme name. Such a segment must be // preceded by a dot-segment (e.g., "./this:that") to make a relative- // path reference. - if i := strings.IndexByte(path, ':'); i > -1 && strings.IndexByte(path[:i], '/') == -1 { + if segment, _, _ := strings.Cut(path, "/"); strings.Contains(segment, ":") { buf.WriteString("./") } } @@ -933,12 +920,8 @@ func ParseQuery(query string) (Values, error) { func parseQuery(m Values, query string) (err error) { for query != "" { - key := query - if i := strings.IndexAny(key, "&"); i >= 0 { - key, query = key[:i], key[i+1:] - } else { - query = "" - } + var key string + key, query, _ = strings.Cut(query, "&") if strings.Contains(key, ";") { err = fmt.Errorf("invalid semicolon separator in query") continue @@ -946,10 +929,7 @@ func parseQuery(m Values, query string) (err error) { if key == "" { continue } - value := "" - if i := strings.Index(key, "="); i >= 0 { - key, value = key[:i], key[i+1:] - } + key, value, _ := strings.Cut(key, "=") key, err1 := QueryUnescape(key) if err1 != nil { if err == nil { @@ -1013,22 +993,16 @@ func resolvePath(base, ref string) string { } var ( - last string elem string - i int dst strings.Builder ) first := true remaining := full // We want to return a leading '/', so write it now. dst.WriteByte('/') - for i >= 0 { - i = strings.IndexByte(remaining, '/') - if i < 0 { - last, elem, remaining = remaining, remaining, "" - } else { - elem, remaining = remaining[:i], remaining[i+1:] - } + found := true + for found { + elem, remaining, found = strings.Cut(remaining, "/") if elem == "." { first = false // drop @@ -1056,7 +1030,7 @@ func resolvePath(base, ref string) string { } } - if last == "." || last == ".." { + if elem == "." || elem == ".." { dst.WriteByte('/') } diff --git a/src/net/url/url_test.go b/src/net/url/url_test.go index 63c8e695af..5059d34bf1 100644 --- a/src/net/url/url_test.go +++ b/src/net/url/url_test.go @@ -2059,12 +2059,3 @@ func BenchmarkPathUnescape(b *testing.B) { }) } } - -var sink string - -func BenchmarkSplit(b *testing.B) { - url := "http://www.google.com/?q=go+language#foo%26bar" - for i := 0; i < b.N; i++ { - sink, sink = split(url, '#', true) - } -} diff --git a/src/os/exec/exec.go b/src/os/exec/exec.go index 0c49575511..9551c22d6e 100644 --- a/src/os/exec/exec.go +++ b/src/os/exec/exec.go @@ -748,12 +748,11 @@ func dedupEnvCase(caseInsensitive bool, env []string) []string { out := make([]string, 0, len(env)) saw := make(map[string]int, len(env)) // key => index into out for _, kv := range env { - eq := strings.Index(kv, "=") - if eq < 0 { + k, _, ok := strings.Cut(kv, "=") + if !ok { out = append(out, kv) continue } - k := kv[:eq] if caseInsensitive { k = strings.ToLower(k) } @@ -775,11 +774,10 @@ func addCriticalEnv(env []string) []string { return env } for _, kv := range env { - eq := strings.Index(kv, "=") - if eq < 0 { + k, _, ok := strings.Cut(kv, "=") + if !ok { continue } - k := kv[:eq] if strings.EqualFold(k, "SYSTEMROOT") { // We already have it. return env diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go index d854e0de84..459ba39dff 100644 --- a/src/os/exec/exec_test.go +++ b/src/os/exec/exec_test.go @@ -166,12 +166,10 @@ func TestCatGoodAndBadFile(t *testing.T) { if _, ok := err.(*exec.ExitError); !ok { t.Errorf("expected *exec.ExitError from cat combined; got %T: %v", err, err) } - s := string(bs) - sp := strings.SplitN(s, "\n", 2) - if len(sp) != 2 { - t.Fatalf("expected two lines from cat; got %q", s) + errLine, body, ok := strings.Cut(string(bs), "\n") + if !ok { + t.Fatalf("expected two lines from cat; got %q", bs) } - errLine, body := sp[0], sp[1] if !strings.HasPrefix(errLine, "Error: open /bogus/file.foo") { t.Errorf("expected stderr to complain about file; got %q", errLine) } diff --git a/src/os/os_test.go b/src/os/os_test.go index 506f1fb0ee..62173d9bf4 100644 --- a/src/os/os_test.go +++ b/src/os/os_test.go @@ -1761,8 +1761,8 @@ func TestHostname(t *testing.T) { // and the /bin/hostname only returns the first component want := runBinHostname(t) if hostname != want { - i := strings.Index(hostname, ".") - if i < 0 || hostname[0:i] != want { + host, _, ok := strings.Cut(hostname, ".") + if !ok || host != want { t.Errorf("Hostname() = %q, want %q", hostname, want) } } diff --git a/src/os/user/cgo_lookup_unix.go b/src/os/user/cgo_lookup_unix.go index abc9e9ce6d..5c972e77cf 100644 --- a/src/os/user/cgo_lookup_unix.go +++ b/src/os/user/cgo_lookup_unix.go @@ -125,9 +125,7 @@ func buildUser(pwd *C.struct_passwd) *User { // say: "It is expected to be a comma separated list of // personal data where the first item is the full name of the // user." - if i := strings.Index(u.Name, ","); i >= 0 { - u.Name = u.Name[:i] - } + u.Name, _, _ = strings.Cut(u.Name, ",") return u } diff --git a/src/os/user/lookup_unix.go b/src/os/user/lookup_unix.go index ac4f1502af..1cabdb5b71 100644 --- a/src/os/user/lookup_unix.go +++ b/src/os/user/lookup_unix.go @@ -174,9 +174,7 @@ func matchUserIndexValue(value string, idx int) lineFunc { // say: "It is expected to be a comma separated list of // personal data where the first item is the full name of the // user." - if i := strings.Index(u.Name, ","); i >= 0 { - u.Name = u.Name[:i] - } + u.Name, _, _ = strings.Cut(u.Name, ",") return u, nil } } diff --git a/src/regexp/exec_test.go b/src/regexp/exec_test.go index 1f9a7a96e0..5f8442668c 100644 --- a/src/regexp/exec_test.go +++ b/src/regexp/exec_test.go @@ -294,12 +294,9 @@ func parseResult(t *testing.T, file string, lineno int, res string) []int { out[n] = -1 out[n+1] = -1 } else { - k := strings.Index(pair, "-") - if k < 0 { - t.Fatalf("%s:%d: invalid pair %s", file, lineno, pair) - } - lo, err1 := strconv.Atoi(pair[:k]) - hi, err2 := strconv.Atoi(pair[k+1:]) + loStr, hiStr, _ := strings.Cut(pair, "-") + lo, err1 := strconv.Atoi(loStr) + hi, err2 := strconv.Atoi(hiStr) if err1 != nil || err2 != nil || lo > hi { t.Fatalf("%s:%d: invalid pair %s", file, lineno, pair) } @@ -457,12 +454,11 @@ Reading: continue Reading } case ':': - i := strings.Index(flag[1:], ":") - if i < 0 { + var ok bool + if _, flag, ok = strings.Cut(flag[1:], ":"); !ok { t.Logf("skip: %s", line) continue Reading } - flag = flag[1+i+1:] case 'C', 'N', 'T', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': t.Logf("skip: %s", line) continue Reading diff --git a/src/regexp/regexp.go b/src/regexp/regexp.go index b547a2ab97..bfcf7910cf 100644 --- a/src/regexp/regexp.go +++ b/src/regexp/regexp.go @@ -922,23 +922,22 @@ func (re *Regexp) ExpandString(dst []byte, template string, src string, match [] func (re *Regexp) expand(dst []byte, template string, bsrc []byte, src string, match []int) []byte { for len(template) > 0 { - i := strings.Index(template, "$") - if i < 0 { + before, after, ok := strings.Cut(template, "$") + if !ok { break } - dst = append(dst, template[:i]...) - template = template[i:] - if len(template) > 1 && template[1] == '$' { + dst = append(dst, before...) + template = after + if template != "" && template[0] == '$' { // Treat $$ as $. dst = append(dst, '$') - template = template[2:] + template = template[1:] continue } name, num, rest, ok := extract(template) if !ok { // Malformed; treat $ as raw text. dst = append(dst, '$') - template = template[1:] continue } template = rest @@ -967,17 +966,16 @@ func (re *Regexp) expand(dst []byte, template string, bsrc []byte, src string, m return dst } -// extract returns the name from a leading "$name" or "${name}" in str. +// extract returns the name from a leading "name" or "{name}" in str. +// (The $ has already been removed by the caller.) // If it is a number, extract returns num set to that number; otherwise num = -1. func extract(str string) (name string, num int, rest string, ok bool) { - if len(str) < 2 || str[0] != '$' { + if str == "" { return } brace := false - if str[1] == '{' { + if str[0] == '{' { brace = true - str = str[2:] - } else { str = str[1:] } i := 0 diff --git a/src/regexp/syntax/parse.go b/src/regexp/syntax/parse.go index 7b4030935a..06a92fb3d7 100644 --- a/src/regexp/syntax/parse.go +++ b/src/regexp/syntax/parse.go @@ -824,13 +824,7 @@ func Parse(s string, flags Flags) (*Regexp, error) { case 'Q': // \Q ... \E: the ... is always literals var lit string - if i := strings.Index(t, `\E`); i < 0 { - lit = t[2:] - t = "" - } else { - lit = t[2:i] - t = t[i+2:] - } + lit, t, _ = strings.Cut(t[2:], `\E`) for lit != "" { c, rest, err := nextRune(lit) if err != nil { diff --git a/src/runtime/debug/mod.go b/src/runtime/debug/mod.go index 0381bdcc53..05cad61155 100644 --- a/src/runtime/debug/mod.go +++ b/src/runtime/debug/mod.go @@ -70,11 +70,10 @@ func readBuildInfo(data string) (*BuildInfo, bool) { ) // Reverse of cmd/go/internal/modload.PackageBuildInfo for len(data) > 0 { - i := strings.IndexByte(data, '\n') - if i < 0 { + line, data, ok = strings.Cut(data, "\n") + if !ok { break } - line, data = data[:i], data[i+1:] switch { case strings.HasPrefix(line, pathLine): elem := line[len(pathLine):] diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go index f39d65c0b5..03ff55b541 100644 --- a/src/runtime/pprof/pprof_test.go +++ b/src/runtime/pprof/pprof_test.go @@ -1234,11 +1234,10 @@ func TestGoroutineCounts(t *testing.T) { func containsInOrder(s string, all ...string) bool { for _, t := range all { - i := strings.Index(s, t) - if i < 0 { + var ok bool + if _, s, ok = strings.Cut(s, t); !ok { return false } - s = s[i+len(t):] } return true } @@ -1318,18 +1317,18 @@ func TestEmptyCallStack(t *testing.T) { // stackContainsLabeled takes a spec like funcname;key=value and matches if the stack has that key // and value and has funcname somewhere in the stack. func stackContainsLabeled(spec string, count uintptr, stk []*profile.Location, labels map[string][]string) bool { - semi := strings.Index(spec, ";") - if semi == -1 { + base, kv, ok := strings.Cut(spec, ";") + if !ok { panic("no semicolon in key/value spec") } - kv := strings.SplitN(spec[semi+1:], "=", 2) - if len(kv) != 2 { + k, v, ok := strings.Cut(kv, "=") + if !ok { panic("missing = in key/value spec") } - if !contains(labels[kv[0]], kv[1]) { + if !contains(labels[k], v) { return false } - return stackContains(spec[:semi], count, stk, labels) + return stackContains(base, count, stk, labels) } func TestCPUProfileLabel(t *testing.T) { diff --git a/src/runtime/pprof/proto.go b/src/runtime/pprof/proto.go index 6862513956..54e7a80183 100644 --- a/src/runtime/pprof/proto.go +++ b/src/runtime/pprof/proto.go @@ -13,6 +13,7 @@ import ( "os" "runtime" "strconv" + "strings" "time" "unsafe" ) @@ -581,6 +582,9 @@ func (b *profileBuilder) readMapping() { } } +var space = []byte(" ") +var newline = []byte("\n") + func parseProcSelfMaps(data []byte, addMapping func(lo, hi, offset uint64, file, buildID string)) { // $ cat /proc/self/maps // 00400000-0040b000 r-xp 00000000 fc:01 787766 /bin/cat @@ -607,37 +611,24 @@ func parseProcSelfMaps(data []byte, addMapping func(lo, hi, offset uint64, file, // next removes and returns the next field in the line. // It also removes from line any spaces following the field. next := func() []byte { - j := bytes.IndexByte(line, ' ') - if j < 0 { - f := line - line = nil - return f - } - f := line[:j] - line = line[j+1:] - for len(line) > 0 && line[0] == ' ' { - line = line[1:] - } + var f []byte + f, line, _ = bytes.Cut(line, space) + line = bytes.TrimLeft(line, " ") return f } for len(data) > 0 { - i := bytes.IndexByte(data, '\n') - if i < 0 { - line, data = data, nil - } else { - line, data = data[:i], data[i+1:] - } + line, data, _ = bytes.Cut(data, newline) addr := next() - i = bytes.IndexByte(addr, '-') - if i < 0 { + loStr, hiStr, ok := strings.Cut(string(addr), "-") + if !ok { continue } - lo, err := strconv.ParseUint(string(addr[:i]), 16, 64) + lo, err := strconv.ParseUint(loStr, 16, 64) if err != nil { continue } - hi, err := strconv.ParseUint(string(addr[i+1:]), 16, 64) + hi, err := strconv.ParseUint(hiStr, 16, 64) if err != nil { continue } diff --git a/src/runtime/pprof/proto_test.go b/src/runtime/pprof/proto_test.go index d052b9fa42..4a9749a83f 100644 --- a/src/runtime/pprof/proto_test.go +++ b/src/runtime/pprof/proto_test.go @@ -274,11 +274,10 @@ func TestProcSelfMaps(t *testing.T) { f := func(t *testing.T, input string) { for tx, tt := range strings.Split(input, "\n\n") { - i := strings.Index(tt, "->\n") - if i < 0 { + in, out, ok := strings.Cut(tt, "->\n") + if !ok { t.Fatal("malformed test case") } - in, out := tt[:i], tt[i+len("->\n"):] if len(out) > 0 && out[len(out)-1] != '\n' { out += "\n" } diff --git a/src/runtime/runtime-gdb_test.go b/src/runtime/runtime-gdb_test.go index 8c76a9123c..4a0f489c2f 100644 --- a/src/runtime/runtime-gdb_test.go +++ b/src/runtime/runtime-gdb_test.go @@ -267,7 +267,7 @@ func testGdbPython(t *testing.T, cgo bool) { t.Fatalf("gdb exited with error: %v", err) } - firstLine := bytes.SplitN(got, []byte("\n"), 2)[0] + firstLine, _, _ := bytes.Cut(got, []byte("\n")) if string(firstLine) != "Loading Go Runtime support." { // This can happen when using all.bash with // GOROOT_FINAL set, because the tests are run before diff --git a/src/runtime/testdata/testprog/numcpu_freebsd.go b/src/runtime/testdata/testprog/numcpu_freebsd.go index aff36ec702..7209f67959 100644 --- a/src/runtime/testdata/testprog/numcpu_freebsd.go +++ b/src/runtime/testdata/testprog/numcpu_freebsd.go @@ -85,19 +85,18 @@ func getList() ([]string, error) { if err != nil { return nil, fmt.Errorf("fail to execute '%s': %s", cmdline, err) } - pos := bytes.IndexRune(output, '\n') - if pos == -1 { + output, _, ok := bytes.Cut(output, []byte("\n")) + if !ok { return nil, fmt.Errorf("invalid output from '%s', '\\n' not found: %s", cmdline, output) } - output = output[0:pos] - pos = bytes.IndexRune(output, ':') - if pos == -1 { + _, cpus, ok := bytes.Cut(output, []byte(":")) + if !ok { return nil, fmt.Errorf("invalid output from '%s', ':' not found: %s", cmdline, output) } var list []string - for _, val := range bytes.Split(output[pos+1:], []byte(",")) { + for _, val := range bytes.Split(cpus, []byte(",")) { index := string(bytes.TrimSpace(val)) if len(index) == 0 { continue diff --git a/src/runtime/testdata/testprog/traceback_ancestors.go b/src/runtime/testdata/testprog/traceback_ancestors.go index 0ee402c4bd..1d0d00bab7 100644 --- a/src/runtime/testdata/testprog/traceback_ancestors.go +++ b/src/runtime/testdata/testprog/traceback_ancestors.go @@ -33,30 +33,27 @@ func printStack() { for { n := runtime.Stack(buf, true) if n < len(buf) { - tb := string(buf[:n]) + all := string(buf[:n]) + var saved string // Delete any ignored goroutines, if present. - pos := 0 - for pos < len(tb) { - next := pos + strings.Index(tb[pos:], "\n\n") - if next < pos { - next = len(tb) - } else { - next += len("\n\n") - } + for all != "" { + var g string + g, all, _ = strings.Cut(all, "\n\n") - if strings.HasPrefix(tb[pos:], "goroutine ") { - id := tb[pos+len("goroutine "):] - id = id[:strings.IndexByte(id, ' ')] + if strings.HasPrefix(g, "goroutine ") { + id, _, _ := strings.Cut(strings.TrimPrefix(g, "goroutine "), " ") if ignoreGoroutines[id] { - tb = tb[:pos] + tb[next:] - next = pos + continue } } - pos = next + if saved != "" { + saved += "\n\n" + } + saved += g } - fmt.Print(tb) + fmt.Print(saved) return } buf = make([]byte, 2*len(buf)) @@ -89,11 +86,10 @@ func recurseThenCallGo(w chan struct{}, frames int, goroutines int, main bool) { func goroutineID() string { buf := make([]byte, 128) runtime.Stack(buf, false) - const prefix = "goroutine " - if !bytes.HasPrefix(buf, []byte(prefix)) { + prefix := []byte("goroutine ") + if !bytes.HasPrefix(buf, prefix) { panic(fmt.Sprintf("expected %q at beginning of traceback:\n%s", prefix, buf)) } - buf = buf[len(prefix):] - n := bytes.IndexByte(buf, ' ') - return string(buf[:n]) + id, _, _ := bytes.Cut(bytes.TrimPrefix(buf, prefix), []byte(" ")) + return string(id) } diff --git a/src/strconv/fp_test.go b/src/strconv/fp_test.go index 39dd9c4a58..fd73958c97 100644 --- a/src/strconv/fp_test.go +++ b/src/strconv/fp_test.go @@ -28,15 +28,14 @@ func pow2(i int) float64 { // Wrapper around strconv.ParseFloat(x, 64). Handles dddddp+ddd (binary exponent) // itself, passes the rest on to strconv.ParseFloat. func myatof64(s string) (f float64, ok bool) { - a := strings.SplitN(s, "p", 2) - if len(a) == 2 { - n, err := strconv.ParseInt(a[0], 10, 64) + if mant, exp, ok := strings.Cut(s, "p"); ok { + n, err := strconv.ParseInt(mant, 10, 64) if err != nil { return 0, false } - e, err1 := strconv.Atoi(a[1]) + e, err1 := strconv.Atoi(exp) if err1 != nil { - println("bad e", a[1]) + println("bad e", exp) return 0, false } v := float64(n) @@ -72,16 +71,15 @@ func myatof64(s string) (f float64, ok bool) { // Wrapper around strconv.ParseFloat(x, 32). Handles dddddp+ddd (binary exponent) // itself, passes the rest on to strconv.ParseFloat. func myatof32(s string) (f float32, ok bool) { - a := strings.SplitN(s, "p", 2) - if len(a) == 2 { - n, err := strconv.Atoi(a[0]) + if mant, exp, ok := strings.Cut(s, "p"); ok { + n, err := strconv.Atoi(mant) if err != nil { - println("bad n", a[0]) + println("bad n", mant) return 0, false } - e, err1 := strconv.Atoi(a[1]) + e, err1 := strconv.Atoi(exp) if err1 != nil { - println("bad p", a[1]) + println("bad p", exp) return 0, false } return float32(float64(n) * pow2(e)), true diff --git a/src/syscall/exec_linux_test.go b/src/syscall/exec_linux_test.go index 1555318eda..79b2633aca 100644 --- a/src/syscall/exec_linux_test.go +++ b/src/syscall/exec_linux_test.go @@ -510,9 +510,7 @@ func mustSupportAmbientCaps(t *testing.T) { buf[i] = byte(b) } ver := string(buf[:]) - if i := strings.Index(ver, "\x00"); i != -1 { - ver = ver[:i] - } + ver, _, _ = strings.Cut(ver, "\x00") if strings.HasPrefix(ver, "2.") || strings.HasPrefix(ver, "3.") || strings.HasPrefix(ver, "4.1.") || diff --git a/src/text/template/option.go b/src/text/template/option.go index addce2d890..1035afad72 100644 --- a/src/text/template/option.go +++ b/src/text/template/option.go @@ -51,13 +51,11 @@ func (t *Template) setOption(opt string) { if opt == "" { panic("empty option string") } - elems := strings.Split(opt, "=") - switch len(elems) { - case 2: - // key=value - switch elems[0] { + // key=value + if key, value, ok := strings.Cut(opt, "="); ok { + switch key { case "missingkey": - switch elems[1] { + switch value { case "invalid", "default": t.option.missingKey = mapInvalid return diff --git a/test/run.go b/test/run.go index 0c9c8c5cb8..0c5da1af78 100644 --- a/test/run.go +++ b/test/run.go @@ -535,9 +535,9 @@ func (ctxt *context) match(name string) bool { if name == "" { return false } - if i := strings.Index(name, ","); i >= 0 { + if first, rest, ok := strings.Cut(name, ","); ok { // comma-separated list - return ctxt.match(name[:i]) && ctxt.match(name[i+1:]) + return ctxt.match(first) && ctxt.match(rest) } if strings.HasPrefix(name, "!!") { // bad syntax, reject always return false @@ -622,24 +622,23 @@ func (t *test) run() { } // Execution recipe stops at first blank line. - pos := strings.Index(t.src, "\n\n") - if pos == -1 { + action, _, ok := strings.Cut(t.src, "\n\n") + if !ok { t.err = fmt.Errorf("double newline ending execution recipe not found in %s", t.goFileName()) return } - action := t.src[:pos] - if nl := strings.Index(action, "\n"); nl >= 0 && strings.Contains(action[:nl], "+build") { + if firstLine, rest, ok := strings.Cut(action, "\n"); ok && strings.Contains(firstLine, "+build") { // skip first line - action = action[nl+1:] + action = rest } action = strings.TrimPrefix(action, "//") // Check for build constraints only up to the actual code. - pkgPos := strings.Index(t.src, "\npackage") - if pkgPos == -1 { - pkgPos = pos // some files are intentionally malformed + header, _, ok := strings.Cut(t.src, "\npackage") + if !ok { + header = action // some files are intentionally malformed } - if ok, why := shouldTest(t.src[:pkgPos], goos, goarch); !ok { + if ok, why := shouldTest(header, goos, goarch); !ok { if *showSkips { fmt.Printf("%-20s %-20s: %s\n", "skip", t.goFileName(), why) } @@ -1516,8 +1515,8 @@ func (t *test) errorCheck(outStr string, wantAuto bool, fullshort ...string) (er // Assume errmsg says "file:line: foo". // Cut leading "file:line: " to avoid accidental matching of file name instead of message. text := errmsg - if i := strings.Index(text, " "); i >= 0 { - text = text[i+1:] + if _, suffix, ok := strings.Cut(text, " "); ok { + text = suffix } if we.re.MatchString(text) { matched = true @@ -1562,31 +1561,26 @@ func (t *test) updateErrors(out, file string) { } lines := strings.Split(string(src), "\n") // Remove old errors. - for i, ln := range lines { - pos := strings.Index(ln, " // ERROR ") - if pos >= 0 { - lines[i] = ln[:pos] - } + for i := range lines { + lines[i], _, _ = strings.Cut(lines[i], " // ERROR ") } // Parse new errors. errors := make(map[int]map[string]bool) tmpRe := regexp.MustCompile(`autotmp_[0-9]+`) for _, errStr := range splitOutput(out, false) { - colon1 := strings.Index(errStr, ":") - if colon1 < 0 || errStr[:colon1] != file { + errFile, rest, ok := strings.Cut(errStr, ":") + if !ok || errFile != file { continue } - colon2 := strings.Index(errStr[colon1+1:], ":") - if colon2 < 0 { + lineStr, msg, ok := strings.Cut(rest, ":") + if !ok { continue } - colon2 += colon1 + 1 - line, err := strconv.Atoi(errStr[colon1+1 : colon2]) + line, err := strconv.Atoi(lineStr) line-- if err != nil || line < 0 || line >= len(lines) { continue } - msg := errStr[colon2+2:] msg = strings.Replace(msg, file, base, -1) // normalize file mentions in error itself msg = strings.TrimLeft(msg, " \t") for _, r := range []string{`\`, `*`, `+`, `?`, `[`, `]`, `(`, `)`} { diff --git a/test/zerodivide.go b/test/zerodivide.go index 214d481164..fd36d67d1a 100644 --- a/test/zerodivide.go +++ b/test/zerodivide.go @@ -218,7 +218,7 @@ func main() { } fmt.Printf("%s: expected no error; got %q\n", t.name, err) case t.err != "" && err != "": - if strings.Index(err, t.err) < 0 { + if !strings.Contains(err, t.err) { if !bad { bad = true fmt.Printf("BUG\n") -- GitLab From aecf4b12e100dbf1ced36f981fbf00ae64d32af8 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Tue, 5 Oct 2021 16:25:06 -0400 Subject: [PATCH 1477/2500] internal/fuzz: log average execs/sec since last log This change also fixes a bug with calculating the total interesting count. When fuzzing with an empty corpus, the fuzzing engine adds an starting corpus value in that run in order to start fuzzing. That meant that the interesting total count was off by one: it would start at 1, even though the cache was empty. Added some tests for this as well. Fixes #48787 Change-Id: I47acf96f0a0797214ebb24a95366d8460bf303bc Reviewed-on: https://go-review.googlesource.com/c/go/+/354150 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod Reviewed-by: Roland Shoemaker --- src/cmd/go/testdata/script/test_fuzz.txt | 14 ++++++++++++ src/internal/fuzz/fuzz.go | 27 +++++++++++++++++------- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt index c9930aa37e..0b01c2fb43 100644 --- a/src/cmd/go/testdata/script/test_fuzz.txt +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -184,6 +184,20 @@ stdout ok ! stdout ^ok stdout FAIL + +# Fuzzing indicates that one new interesting value was found with an empty +# corpus, and the total size of the cache is now 1. +go clean -fuzzcache +go test -fuzz=Fuzz -fuzztime=10000x success_fuzz_test.go +stdout 'new interesting: 1' +stdout 'total: 1' + +# Fuzzing again with a small fuzztime does not find any other interesting +# values but still indicates that the cache size is 1. +go test -fuzz=Fuzz -fuzztime=2x success_fuzz_test.go +stdout 'new interesting: 0' +stdout 'total: 1' + -- noop_fuzz_test.go -- package noop_fuzz diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 87f5459afd..2c2a365f4c 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -556,6 +556,13 @@ type coordinator struct { // count is the number of values fuzzed so far. count int64 + // countLastLog is the number of values fuzzed when the output was last + // logged. + countLastLog int64 + + // timeLastLog is the time at which the output was last logged. + timeLastLog time.Time + // interestingCount is the number of unique interesting values which have // been found this execution. interestingCount int64 @@ -618,12 +625,13 @@ func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { return nil, err } c := &coordinator{ - opts: opts, - startTime: time.Now(), - inputC: make(chan fuzzInput), - minimizeC: make(chan fuzzMinimizeInput), - resultC: make(chan fuzzResult), - corpus: corpus, + opts: opts, + startTime: time.Now(), + inputC: make(chan fuzzInput), + minimizeC: make(chan fuzzMinimizeInput), + resultC: make(chan fuzzResult), + corpus: corpus, + timeLastLog: time.Now(), } if opts.MinimizeLimit > 0 || opts.MinimizeTimeout > 0 { for _, t := range opts.Types { @@ -676,6 +684,7 @@ func (c *coordinator) updateStats(result fuzzResult) { } func (c *coordinator) logStats() { + now := time.Now() if c.warmupRun() { runSoFar := c.warmupInputCount - c.warmupInputLeft if coverageEnabled { @@ -684,14 +693,16 @@ func (c *coordinator) logStats() { fmt.Fprintf(c.opts.Log, "fuzz: elapsed: %s, testing seed corpus: %d/%d completed\n", c.elapsed(), runSoFar, c.warmupInputCount) } } else { - rate := float64(c.count) / time.Since(c.startTime).Seconds() // be more precise here + rate := float64(c.count-c.countLastLog) / now.Sub(c.timeLastLog).Seconds() if coverageEnabled { - interestingTotalCount := len(c.corpus.entries) - len(c.opts.Seed) + interestingTotalCount := int64(c.warmupInputCount-len(c.opts.Seed)) + c.interestingCount fmt.Fprintf(c.opts.Log, "fuzz: elapsed: %s, execs: %d (%.0f/sec), new interesting: %d (total: %d)\n", c.elapsed(), c.count, rate, c.interestingCount, interestingTotalCount) } else { fmt.Fprintf(c.opts.Log, "fuzz: elapsed: %s, execs: %d (%.0f/sec)", c.elapsed(), c.count, rate) } } + c.countLastLog = c.count + c.timeLastLog = now } // peekInput returns the next value that should be sent to workers. -- GitLab From 7109323af5a8c7e076fa2af7185caa6185df97cd Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Mon, 4 Oct 2021 10:50:02 -0700 Subject: [PATCH 1478/2500] all: update golang.org/x/net to pull in CL 353390 Fixes #48564. Fixes #23559. Change-Id: I8e0b646c4791d3a6fb17df1af0a7175b68ce8983 Reviewed-on: https://go-review.googlesource.com/c/go/+/353870 Trust: Damien Neil Run-TryBot: Damien Neil TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/go.mod | 2 +- src/go.sum | 6 + src/net/http/h2_bundle.go | 1397 +++++++++++++++++++++---------------- src/vendor/modules.txt | 2 +- 4 files changed, 807 insertions(+), 600 deletions(-) diff --git a/src/go.mod b/src/go.mod index 69e2655e88..3464adfeee 100644 --- a/src/go.mod +++ b/src/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 - golang.org/x/net v0.0.0-20210825183410-e898025ed96a + golang.org/x/net v0.0.0-20211004220534-69340ce214a7 ) require ( diff --git a/src/go.sum b/src/go.sum index 1c419b90ba..18cdc2854a 100644 --- a/src/go.sum +++ b/src/go.sum @@ -2,6 +2,12 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s3 golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/net v0.0.0-20210825183410-e898025ed96a h1:bRuuGXV8wwSdGTB+CtJf+FjgO1APK1CoO39T4BN/XBw= golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211004164453-cedda3a722dd h1:Q6PfiuMddtCdycHT4hrZ7ZhVpAdQlA7qJp+ZhUw7Rdo= +golang.org/x/net v0.0.0-20211004164453-cedda3a722dd/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211004195052-b30845b58a23 h1:j34uvNZ757YpJXjsTk19wPCR/3tAhHPT4EMFysLc9Xg= +golang.org/x/net v0.0.0-20211004195052-b30845b58a23/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211004220534-69340ce214a7 h1:mAWBL9V7JYRSixWOKNpbAMF16bdRk4x94pU+I+WPGW4= +golang.org/x/net v0.0.0-20211004220534-69340ce214a7/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e h1:XMgFehsDnnLGtjvjOfqWSUzt0alpTR1RSEuznObga2c= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go index 14f4d0e5fc..29226d4065 100644 --- a/src/net/http/h2_bundle.go +++ b/src/net/http/h2_bundle.go @@ -737,6 +737,12 @@ func http2isBadCipher(cipher uint16) bool { // ClientConnPool manages a pool of HTTP/2 client connections. type http2ClientConnPool interface { + // GetClientConn returns a specific HTTP/2 connection (usually + // a TLS-TCP connection) to an HTTP/2 server. On success, the + // returned ClientConn accounts for the upcoming RoundTrip + // call, so the caller should not omit it. If the caller needs + // to, ClientConn.RoundTrip can be called with a bogus + // new(http.Request) to release the stream reservation. GetClientConn(req *Request, addr string) (*http2ClientConn, error) MarkDead(*http2ClientConn) } @@ -763,7 +769,7 @@ type http2clientConnPool struct { conns map[string][]*http2ClientConn // key is host:port dialing map[string]*http2dialCall // currently in-flight dials keys map[*http2ClientConn][]string - addConnCalls map[string]*http2addConnCall // in-flight addConnIfNeede calls + addConnCalls map[string]*http2addConnCall // in-flight addConnIfNeeded calls } func (p *http2clientConnPool) GetClientConn(req *Request, addr string) (*http2ClientConn, error) { @@ -775,28 +781,8 @@ const ( http2noDialOnMiss = false ) -// shouldTraceGetConn reports whether getClientConn should call any -// ClientTrace.GetConn hook associated with the http.Request. -// -// This complexity is needed to avoid double calls of the GetConn hook -// during the back-and-forth between net/http and x/net/http2 (when the -// net/http.Transport is upgraded to also speak http2), as well as support -// the case where x/net/http2 is being used directly. -func (p *http2clientConnPool) shouldTraceGetConn(st http2clientConnIdleState) bool { - // If our Transport wasn't made via ConfigureTransport, always - // trace the GetConn hook if provided, because that means the - // http2 package is being used directly and it's the one - // dialing, as opposed to net/http. - if _, ok := p.t.ConnPool.(http2noDialClientConnPool); !ok { - return true - } - // Otherwise, only use the GetConn hook if this connection has - // been used previously for other requests. For fresh - // connections, the net/http package does the dialing. - return !st.freshConn -} - func (p *http2clientConnPool) getClientConn(req *Request, addr string, dialOnMiss bool) (*http2ClientConn, error) { + // TODO(dneil): Dial a new connection when t.DisableKeepAlives is set? if http2isConnectionCloseRequest(req) && dialOnMiss { // It gets its own connection. http2traceGetConn(req, addr) @@ -810,10 +796,14 @@ func (p *http2clientConnPool) getClientConn(req *Request, addr string, dialOnMis for { p.mu.Lock() for _, cc := range p.conns[addr] { - if st := cc.idleState(); st.canTakeNewRequest { - if p.shouldTraceGetConn(st) { + if cc.ReserveNewRequest() { + // When a connection is presented to us by the net/http package, + // the GetConn hook has already been called. + // Don't call it a second time here. + if !cc.getConnCalled { http2traceGetConn(req, addr) } + cc.getConnCalled = false p.mu.Unlock() return cc, nil } @@ -829,7 +819,13 @@ func (p *http2clientConnPool) getClientConn(req *Request, addr string, dialOnMis if http2shouldRetryDial(call, req) { continue } - return call.res, call.err + cc, err := call.res, call.err + if err != nil { + return nil, err + } + if cc.ReserveNewRequest() { + return cc, nil + } } } @@ -926,6 +922,7 @@ func (c *http2addConnCall) run(t *http2Transport, key string, tc *tls.Conn) { if err != nil { c.err = err } else { + cc.getConnCalled = true // already called by the net/http package p.addConnLocked(key, cc) } delete(p.addConnCalls, key) @@ -1212,6 +1209,13 @@ func (e http2ErrCode) String() string { return fmt.Sprintf("unknown error code 0x%x", uint32(e)) } +func (e http2ErrCode) stringToken() string { + if s, ok := http2errCodeName[e]; ok { + return s + } + return fmt.Sprintf("ERR_UNKNOWN_%d", uint32(e)) +} + // ConnectionError is an error that results in the termination of the // entire connection. type http2ConnectionError http2ErrCode @@ -1228,6 +1232,11 @@ type http2StreamError struct { Cause error // optional additional detail } +// errFromPeer is a sentinel error value for StreamError.Cause to +// indicate that the StreamError was sent from the peer over the wire +// and wasn't locally generated in the Transport. +var http2errFromPeer = errors.New("received from peer") + func http2streamError(id uint32, code http2ErrCode) http2StreamError { return http2StreamError{StreamID: id, Code: code} } @@ -1442,7 +1451,7 @@ var http2flagName = map[http2FrameType]map[http2Flags]string{ // a frameParser parses a frame given its FrameHeader and payload // bytes. The length of payload will always equal fh.Length (which // might be 0). -type http2frameParser func(fc *http2frameCache, fh http2FrameHeader, payload []byte) (http2Frame, error) +type http2frameParser func(fc *http2frameCache, fh http2FrameHeader, countError func(string), payload []byte) (http2Frame, error) var http2frameParsers = map[http2FrameType]http2frameParser{ http2FrameData: http2parseDataFrame, @@ -1587,6 +1596,11 @@ type http2Framer struct { lastFrame http2Frame errDetail error + // countError is a non-nil func that's called on a frame parse + // error with some unique error path token. It's initialized + // from Transport.CountError or Server.CountError. + countError func(errToken string) + // lastHeaderStream is non-zero if the last frame was an // unfinished HEADERS/CONTINUATION. lastHeaderStream uint32 @@ -1749,6 +1763,7 @@ func http2NewFramer(w io.Writer, r io.Reader) *http2Framer { fr := &http2Framer{ w: w, r: r, + countError: func(string) {}, logReads: http2logFrameReads, logWrites: http2logFrameWrites, debugReadLoggerf: log.Printf, @@ -1823,7 +1838,7 @@ func (fr *http2Framer) ReadFrame() (http2Frame, error) { if _, err := io.ReadFull(fr.r, payload); err != nil { return nil, err } - f, err := http2typeFrameParser(fh.Type)(fr.frameCache, fh, payload) + f, err := http2typeFrameParser(fh.Type)(fr.frameCache, fh, fr.countError, payload) if err != nil { if ce, ok := err.(http2connError); ok { return nil, fr.connError(ce.Code, ce.Reason) @@ -1911,13 +1926,14 @@ func (f *http2DataFrame) Data() []byte { return f.data } -func http2parseDataFrame(fc *http2frameCache, fh http2FrameHeader, payload []byte) (http2Frame, error) { +func http2parseDataFrame(fc *http2frameCache, fh http2FrameHeader, countError func(string), payload []byte) (http2Frame, error) { if fh.StreamID == 0 { // DATA frames MUST be associated with a stream. If a // DATA frame is received whose stream identifier // field is 0x0, the recipient MUST respond with a // connection error (Section 5.4.1) of type // PROTOCOL_ERROR. + countError("frame_data_stream_0") return nil, http2connError{http2ErrCodeProtocol, "DATA frame with stream ID 0"} } f := fc.getDataFrame() @@ -1928,6 +1944,7 @@ func http2parseDataFrame(fc *http2frameCache, fh http2FrameHeader, payload []byt var err error payload, padSize, err = http2readByte(payload) if err != nil { + countError("frame_data_pad_byte_short") return nil, err } } @@ -1936,6 +1953,7 @@ func http2parseDataFrame(fc *http2frameCache, fh http2FrameHeader, payload []byt // length of the frame payload, the recipient MUST // treat this as a connection error. // Filed: https://github.com/http2/http2-spec/issues/610 + countError("frame_data_pad_too_big") return nil, http2connError{http2ErrCodeProtocol, "pad size larger than data payload"} } f.data = payload[:len(payload)-int(padSize)] @@ -2018,7 +2036,7 @@ type http2SettingsFrame struct { p []byte } -func http2parseSettingsFrame(_ *http2frameCache, fh http2FrameHeader, p []byte) (http2Frame, error) { +func http2parseSettingsFrame(_ *http2frameCache, fh http2FrameHeader, countError func(string), p []byte) (http2Frame, error) { if fh.Flags.Has(http2FlagSettingsAck) && fh.Length > 0 { // When this (ACK 0x1) bit is set, the payload of the // SETTINGS frame MUST be empty. Receipt of a @@ -2026,6 +2044,7 @@ func http2parseSettingsFrame(_ *http2frameCache, fh http2FrameHeader, p []byte) // field value other than 0 MUST be treated as a // connection error (Section 5.4.1) of type // FRAME_SIZE_ERROR. + countError("frame_settings_ack_with_length") return nil, http2ConnectionError(http2ErrCodeFrameSize) } if fh.StreamID != 0 { @@ -2036,14 +2055,17 @@ func http2parseSettingsFrame(_ *http2frameCache, fh http2FrameHeader, p []byte) // field is anything other than 0x0, the endpoint MUST // respond with a connection error (Section 5.4.1) of // type PROTOCOL_ERROR. + countError("frame_settings_has_stream") return nil, http2ConnectionError(http2ErrCodeProtocol) } if len(p)%6 != 0 { + countError("frame_settings_mod_6") // Expecting even number of 6 byte settings. return nil, http2ConnectionError(http2ErrCodeFrameSize) } f := &http2SettingsFrame{http2FrameHeader: fh, p: p} if v, ok := f.Value(http2SettingInitialWindowSize); ok && v > (1<<31)-1 { + countError("frame_settings_window_size_too_big") // Values above the maximum flow control window size of 2^31 - 1 MUST // be treated as a connection error (Section 5.4.1) of type // FLOW_CONTROL_ERROR. @@ -2155,11 +2177,13 @@ type http2PingFrame struct { func (f *http2PingFrame) IsAck() bool { return f.Flags.Has(http2FlagPingAck) } -func http2parsePingFrame(_ *http2frameCache, fh http2FrameHeader, payload []byte) (http2Frame, error) { +func http2parsePingFrame(_ *http2frameCache, fh http2FrameHeader, countError func(string), payload []byte) (http2Frame, error) { if len(payload) != 8 { + countError("frame_ping_length") return nil, http2ConnectionError(http2ErrCodeFrameSize) } if fh.StreamID != 0 { + countError("frame_ping_has_stream") return nil, http2ConnectionError(http2ErrCodeProtocol) } f := &http2PingFrame{http2FrameHeader: fh} @@ -2195,11 +2219,13 @@ func (f *http2GoAwayFrame) DebugData() []byte { return f.debugData } -func http2parseGoAwayFrame(_ *http2frameCache, fh http2FrameHeader, p []byte) (http2Frame, error) { +func http2parseGoAwayFrame(_ *http2frameCache, fh http2FrameHeader, countError func(string), p []byte) (http2Frame, error) { if fh.StreamID != 0 { + countError("frame_goaway_has_stream") return nil, http2ConnectionError(http2ErrCodeProtocol) } if len(p) < 8 { + countError("frame_goaway_short") return nil, http2ConnectionError(http2ErrCodeFrameSize) } return &http2GoAwayFrame{ @@ -2235,7 +2261,7 @@ func (f *http2UnknownFrame) Payload() []byte { return f.p } -func http2parseUnknownFrame(_ *http2frameCache, fh http2FrameHeader, p []byte) (http2Frame, error) { +func http2parseUnknownFrame(_ *http2frameCache, fh http2FrameHeader, countError func(string), p []byte) (http2Frame, error) { return &http2UnknownFrame{fh, p}, nil } @@ -2246,8 +2272,9 @@ type http2WindowUpdateFrame struct { Increment uint32 // never read with high bit set } -func http2parseWindowUpdateFrame(_ *http2frameCache, fh http2FrameHeader, p []byte) (http2Frame, error) { +func http2parseWindowUpdateFrame(_ *http2frameCache, fh http2FrameHeader, countError func(string), p []byte) (http2Frame, error) { if len(p) != 4 { + countError("frame_windowupdate_bad_len") return nil, http2ConnectionError(http2ErrCodeFrameSize) } inc := binary.BigEndian.Uint32(p[:4]) & 0x7fffffff // mask off high reserved bit @@ -2259,8 +2286,10 @@ func http2parseWindowUpdateFrame(_ *http2frameCache, fh http2FrameHeader, p []by // control window MUST be treated as a connection // error (Section 5.4.1). if fh.StreamID == 0 { + countError("frame_windowupdate_zero_inc_conn") return nil, http2ConnectionError(http2ErrCodeProtocol) } + countError("frame_windowupdate_zero_inc_stream") return nil, http2streamError(fh.StreamID, http2ErrCodeProtocol) } return &http2WindowUpdateFrame{ @@ -2311,7 +2340,7 @@ func (f *http2HeadersFrame) HasPriority() bool { return f.http2FrameHeader.Flags.Has(http2FlagHeadersPriority) } -func http2parseHeadersFrame(_ *http2frameCache, fh http2FrameHeader, p []byte) (_ http2Frame, err error) { +func http2parseHeadersFrame(_ *http2frameCache, fh http2FrameHeader, countError func(string), p []byte) (_ http2Frame, err error) { hf := &http2HeadersFrame{ http2FrameHeader: fh, } @@ -2320,11 +2349,13 @@ func http2parseHeadersFrame(_ *http2frameCache, fh http2FrameHeader, p []byte) ( // is received whose stream identifier field is 0x0, the recipient MUST // respond with a connection error (Section 5.4.1) of type // PROTOCOL_ERROR. + countError("frame_headers_zero_stream") return nil, http2connError{http2ErrCodeProtocol, "HEADERS frame with stream ID 0"} } var padLength uint8 if fh.Flags.Has(http2FlagHeadersPadded) { if p, padLength, err = http2readByte(p); err != nil { + countError("frame_headers_pad_short") return } } @@ -2332,16 +2363,19 @@ func http2parseHeadersFrame(_ *http2frameCache, fh http2FrameHeader, p []byte) ( var v uint32 p, v, err = http2readUint32(p) if err != nil { + countError("frame_headers_prio_short") return nil, err } hf.Priority.StreamDep = v & 0x7fffffff hf.Priority.Exclusive = (v != hf.Priority.StreamDep) // high bit was set p, hf.Priority.Weight, err = http2readByte(p) if err != nil { + countError("frame_headers_prio_weight_short") return nil, err } } - if len(p)-int(padLength) <= 0 { + if len(p)-int(padLength) < 0 { + countError("frame_headers_pad_too_big") return nil, http2streamError(fh.StreamID, http2ErrCodeProtocol) } hf.headerFragBuf = p[:len(p)-int(padLength)] @@ -2448,11 +2482,13 @@ func (p http2PriorityParam) IsZero() bool { return p == http2PriorityParam{} } -func http2parsePriorityFrame(_ *http2frameCache, fh http2FrameHeader, payload []byte) (http2Frame, error) { +func http2parsePriorityFrame(_ *http2frameCache, fh http2FrameHeader, countError func(string), payload []byte) (http2Frame, error) { if fh.StreamID == 0 { + countError("frame_priority_zero_stream") return nil, http2connError{http2ErrCodeProtocol, "PRIORITY frame with stream ID 0"} } if len(payload) != 5 { + countError("frame_priority_bad_length") return nil, http2connError{http2ErrCodeFrameSize, fmt.Sprintf("PRIORITY frame payload size was %d; want 5", len(payload))} } v := binary.BigEndian.Uint32(payload[:4]) @@ -2495,11 +2531,13 @@ type http2RSTStreamFrame struct { ErrCode http2ErrCode } -func http2parseRSTStreamFrame(_ *http2frameCache, fh http2FrameHeader, p []byte) (http2Frame, error) { +func http2parseRSTStreamFrame(_ *http2frameCache, fh http2FrameHeader, countError func(string), p []byte) (http2Frame, error) { if len(p) != 4 { + countError("frame_rststream_bad_len") return nil, http2ConnectionError(http2ErrCodeFrameSize) } if fh.StreamID == 0 { + countError("frame_rststream_zero_stream") return nil, http2ConnectionError(http2ErrCodeProtocol) } return &http2RSTStreamFrame{fh, http2ErrCode(binary.BigEndian.Uint32(p[:4]))}, nil @@ -2525,8 +2563,9 @@ type http2ContinuationFrame struct { headerFragBuf []byte } -func http2parseContinuationFrame(_ *http2frameCache, fh http2FrameHeader, p []byte) (http2Frame, error) { +func http2parseContinuationFrame(_ *http2frameCache, fh http2FrameHeader, countError func(string), p []byte) (http2Frame, error) { if fh.StreamID == 0 { + countError("frame_continuation_zero_stream") return nil, http2connError{http2ErrCodeProtocol, "CONTINUATION frame with stream ID 0"} } return &http2ContinuationFrame{fh, p}, nil @@ -2575,7 +2614,7 @@ func (f *http2PushPromiseFrame) HeadersEnded() bool { return f.http2FrameHeader.Flags.Has(http2FlagPushPromiseEndHeaders) } -func http2parsePushPromise(_ *http2frameCache, fh http2FrameHeader, p []byte) (_ http2Frame, err error) { +func http2parsePushPromise(_ *http2frameCache, fh http2FrameHeader, countError func(string), p []byte) (_ http2Frame, err error) { pp := &http2PushPromiseFrame{ http2FrameHeader: fh, } @@ -2586,6 +2625,7 @@ func http2parsePushPromise(_ *http2frameCache, fh http2FrameHeader, p []byte) (_ // with. If the stream identifier field specifies the value // 0x0, a recipient MUST respond with a connection error // (Section 5.4.1) of type PROTOCOL_ERROR. + countError("frame_pushpromise_zero_stream") return nil, http2ConnectionError(http2ErrCodeProtocol) } // The PUSH_PROMISE frame includes optional padding. @@ -2593,18 +2633,21 @@ func http2parsePushPromise(_ *http2frameCache, fh http2FrameHeader, p []byte) (_ var padLength uint8 if fh.Flags.Has(http2FlagPushPromisePadded) { if p, padLength, err = http2readByte(p); err != nil { + countError("frame_pushpromise_pad_short") return } } p, pp.PromiseID, err = http2readUint32(p) if err != nil { + countError("frame_pushpromise_promiseid_short") return } pp.PromiseID = pp.PromiseID & (1<<31 - 1) if int(padLength) > len(p) { // like the DATA frame, error out if padding is longer than the body. + countError("frame_pushpromise_pad_too_big") return nil, http2ConnectionError(http2ErrCodeProtocol) } pp.headerFragBuf = p[:len(p)-int(padLength)] @@ -3574,6 +3617,17 @@ type http2pipeBuffer interface { io.Reader } +// setBuffer initializes the pipe buffer. +// It has no effect if the pipe is already closed. +func (p *http2pipe) setBuffer(b http2pipeBuffer) { + p.mu.Lock() + defer p.mu.Unlock() + if p.err != nil || p.breakErr != nil { + return + } + p.b = b +} + func (p *http2pipe) Len() int { p.mu.Lock() defer p.mu.Unlock() @@ -3790,6 +3844,12 @@ type http2Server struct { // If nil, a default scheduler is chosen. NewWriteScheduler func() http2WriteScheduler + // CountError, if non-nil, is called on HTTP/2 server errors. + // It's intended to increment a metric for monitoring, such + // as an expvar or Prometheus metric. + // The errType consists of only ASCII word characters. + CountError func(errType string) + // Internal state. This is a pointer (rather than embedded directly) // so that we don't embed a Mutex in this struct, which will make the // struct non-copyable, which might break some callers. @@ -4065,6 +4125,9 @@ func (s *http2Server) ServeConn(c net.Conn, opts *http2ServeConnOpts) { sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf) fr := http2NewFramer(sc.bw, c) + if s.CountError != nil { + fr.countError = s.CountError + } fr.ReadMetaHeaders = hpack.NewDecoder(http2initialHeaderTableSize, nil) fr.MaxHeaderListSize = sc.maxHeaderListSize() fr.SetMaxReadFrameSize(s.maxReadFrameSize()) @@ -5064,7 +5127,7 @@ func (sc *http2serverConn) processFrame(f http2Frame) error { // First frame received must be SETTINGS. if !sc.sawFirstSettings { if _, ok := f.(*http2SettingsFrame); !ok { - return http2ConnectionError(http2ErrCodeProtocol) + return sc.countError("first_settings", http2ConnectionError(http2ErrCodeProtocol)) } sc.sawFirstSettings = true } @@ -5089,7 +5152,7 @@ func (sc *http2serverConn) processFrame(f http2Frame) error { case *http2PushPromiseFrame: // A client cannot push. Thus, servers MUST treat the receipt of a PUSH_PROMISE // frame as a connection error (Section 5.4.1) of type PROTOCOL_ERROR. - return http2ConnectionError(http2ErrCodeProtocol) + return sc.countError("push_promise", http2ConnectionError(http2ErrCodeProtocol)) default: sc.vlogf("http2: server ignoring frame: %v", f.Header()) return nil @@ -5109,7 +5172,7 @@ func (sc *http2serverConn) processPing(f *http2PingFrame) error { // identifier field value other than 0x0, the recipient MUST // respond with a connection error (Section 5.4.1) of type // PROTOCOL_ERROR." - return http2ConnectionError(http2ErrCodeProtocol) + return sc.countError("ping_on_stream", http2ConnectionError(http2ErrCodeProtocol)) } if sc.inGoAway && sc.goAwayCode != http2ErrCodeNo { return nil @@ -5128,7 +5191,7 @@ func (sc *http2serverConn) processWindowUpdate(f *http2WindowUpdateFrame) error // or PRIORITY on a stream in this state MUST be // treated as a connection error (Section 5.4.1) of // type PROTOCOL_ERROR." - return http2ConnectionError(http2ErrCodeProtocol) + return sc.countError("stream_idle", http2ConnectionError(http2ErrCodeProtocol)) } if st == nil { // "WINDOW_UPDATE can be sent by a peer that has sent a @@ -5139,7 +5202,7 @@ func (sc *http2serverConn) processWindowUpdate(f *http2WindowUpdateFrame) error return nil } if !st.flow.add(int32(f.Increment)) { - return http2streamError(f.StreamID, http2ErrCodeFlowControl) + return sc.countError("bad_flow", http2streamError(f.StreamID, http2ErrCodeFlowControl)) } default: // connection-level flow control if !sc.flow.add(int32(f.Increment)) { @@ -5160,7 +5223,7 @@ func (sc *http2serverConn) processResetStream(f *http2RSTStreamFrame) error { // identifying an idle stream is received, the // recipient MUST treat this as a connection error // (Section 5.4.1) of type PROTOCOL_ERROR. - return http2ConnectionError(http2ErrCodeProtocol) + return sc.countError("reset_idle_stream", http2ConnectionError(http2ErrCodeProtocol)) } if st != nil { st.cancelCtx() @@ -5212,7 +5275,7 @@ func (sc *http2serverConn) processSettings(f *http2SettingsFrame) error { // Why is the peer ACKing settings we never sent? // The spec doesn't mention this case, but // hang up on them anyway. - return http2ConnectionError(http2ErrCodeProtocol) + return sc.countError("ack_mystery", http2ConnectionError(http2ErrCodeProtocol)) } return nil } @@ -5220,7 +5283,7 @@ func (sc *http2serverConn) processSettings(f *http2SettingsFrame) error { // This isn't actually in the spec, but hang up on // suspiciously large settings frames or those with // duplicate entries. - return http2ConnectionError(http2ErrCodeProtocol) + return sc.countError("settings_big_or_dups", http2ConnectionError(http2ErrCodeProtocol)) } if err := f.ForeachSetting(sc.processSetting); err != nil { return err @@ -5287,7 +5350,7 @@ func (sc *http2serverConn) processSettingInitialWindowSize(val uint32) error { // control window to exceed the maximum size as a // connection error (Section 5.4.1) of type // FLOW_CONTROL_ERROR." - return http2ConnectionError(http2ErrCodeFlowControl) + return sc.countError("setting_win_size", http2ConnectionError(http2ErrCodeFlowControl)) } } return nil @@ -5320,7 +5383,7 @@ func (sc *http2serverConn) processData(f *http2DataFrame) error { // or PRIORITY on a stream in this state MUST be // treated as a connection error (Section 5.4.1) of // type PROTOCOL_ERROR." - return http2ConnectionError(http2ErrCodeProtocol) + return sc.countError("data_on_idle", http2ConnectionError(http2ErrCodeProtocol)) } // "If a DATA frame is received whose stream is not in "open" @@ -5337,7 +5400,7 @@ func (sc *http2serverConn) processData(f *http2DataFrame) error { // and return any flow control bytes since we're not going // to consume them. if sc.inflow.available() < int32(f.Length) { - return http2streamError(id, http2ErrCodeFlowControl) + return sc.countError("data_flow", http2streamError(id, http2ErrCodeFlowControl)) } // Deduct the flow control from inflow, since we're // going to immediately add it back in @@ -5350,7 +5413,7 @@ func (sc *http2serverConn) processData(f *http2DataFrame) error { // Already have a stream error in flight. Don't send another. return nil } - return http2streamError(id, http2ErrCodeStreamClosed) + return sc.countError("closed", http2streamError(id, http2ErrCodeStreamClosed)) } if st.body == nil { panic("internal error: should have a body in this state") @@ -5362,12 +5425,12 @@ func (sc *http2serverConn) processData(f *http2DataFrame) error { // RFC 7540, sec 8.1.2.6: A request or response is also malformed if the // value of a content-length header field does not equal the sum of the // DATA frame payload lengths that form the body. - return http2streamError(id, http2ErrCodeProtocol) + return sc.countError("send_too_much", http2streamError(id, http2ErrCodeProtocol)) } if f.Length > 0 { // Check whether the client has flow control quota. if st.inflow.available() < int32(f.Length) { - return http2streamError(id, http2ErrCodeFlowControl) + return sc.countError("flow_on_data_length", http2streamError(id, http2ErrCodeFlowControl)) } st.inflow.take(int32(f.Length)) @@ -5375,7 +5438,7 @@ func (sc *http2serverConn) processData(f *http2DataFrame) error { wrote, err := st.body.Write(data) if err != nil { sc.sendWindowUpdate(nil, int(f.Length)-wrote) - return http2streamError(id, http2ErrCodeStreamClosed) + return sc.countError("body_write_err", http2streamError(id, http2ErrCodeStreamClosed)) } if wrote != len(data) { panic("internal error: bad Writer") @@ -5461,7 +5524,7 @@ func (sc *http2serverConn) processHeaders(f *http2MetaHeadersFrame) error { // stream identifier MUST respond with a connection error // (Section 5.4.1) of type PROTOCOL_ERROR. if id%2 != 1 { - return http2ConnectionError(http2ErrCodeProtocol) + return sc.countError("headers_even", http2ConnectionError(http2ErrCodeProtocol)) } // A HEADERS frame can be used to create a new stream or // send a trailer for an open one. If we already have a stream @@ -5478,7 +5541,7 @@ func (sc *http2serverConn) processHeaders(f *http2MetaHeadersFrame) error { // this state, it MUST respond with a stream error (Section 5.4.2) of // type STREAM_CLOSED. if st.state == http2stateHalfClosedRemote { - return http2streamError(id, http2ErrCodeStreamClosed) + return sc.countError("headers_half_closed", http2streamError(id, http2ErrCodeStreamClosed)) } return st.processTrailerHeaders(f) } @@ -5489,7 +5552,7 @@ func (sc *http2serverConn) processHeaders(f *http2MetaHeadersFrame) error { // receives an unexpected stream identifier MUST respond with // a connection error (Section 5.4.1) of type PROTOCOL_ERROR. if id <= sc.maxClientStreamID { - return http2ConnectionError(http2ErrCodeProtocol) + return sc.countError("stream_went_down", http2ConnectionError(http2ErrCodeProtocol)) } sc.maxClientStreamID = id @@ -5506,14 +5569,14 @@ func (sc *http2serverConn) processHeaders(f *http2MetaHeadersFrame) error { if sc.curClientStreams+1 > sc.advMaxStreams { if sc.unackedSettings == 0 { // They should know better. - return http2streamError(id, http2ErrCodeProtocol) + return sc.countError("over_max_streams", http2streamError(id, http2ErrCodeProtocol)) } // Assume it's a network race, where they just haven't // received our last SETTINGS update. But actually // this can't happen yet, because we don't yet provide // a way for users to adjust server parameters at // runtime. - return http2streamError(id, http2ErrCodeRefusedStream) + return sc.countError("over_max_streams_race", http2streamError(id, http2ErrCodeRefusedStream)) } initialState := http2stateOpen @@ -5523,7 +5586,7 @@ func (sc *http2serverConn) processHeaders(f *http2MetaHeadersFrame) error { st := sc.newStream(id, 0, initialState) if f.HasPriority() { - if err := http2checkPriority(f.StreamID, f.Priority); err != nil { + if err := sc.checkPriority(f.StreamID, f.Priority); err != nil { return err } sc.writeSched.AdjustStream(st.id, f.Priority) @@ -5567,15 +5630,15 @@ func (st *http2stream) processTrailerHeaders(f *http2MetaHeadersFrame) error { sc := st.sc sc.serveG.check() if st.gotTrailerHeader { - return http2ConnectionError(http2ErrCodeProtocol) + return sc.countError("dup_trailers", http2ConnectionError(http2ErrCodeProtocol)) } st.gotTrailerHeader = true if !f.StreamEnded() { - return http2streamError(st.id, http2ErrCodeProtocol) + return sc.countError("trailers_not_ended", http2streamError(st.id, http2ErrCodeProtocol)) } if len(f.PseudoFields()) > 0 { - return http2streamError(st.id, http2ErrCodeProtocol) + return sc.countError("trailers_pseudo", http2streamError(st.id, http2ErrCodeProtocol)) } if st.trailer != nil { for _, hf := range f.RegularFields() { @@ -5584,7 +5647,7 @@ func (st *http2stream) processTrailerHeaders(f *http2MetaHeadersFrame) error { // TODO: send more details to the peer somehow. But http2 has // no way to send debug data at a stream level. Discuss with // HTTP folk. - return http2streamError(st.id, http2ErrCodeProtocol) + return sc.countError("trailers_bogus", http2streamError(st.id, http2ErrCodeProtocol)) } st.trailer[key] = append(st.trailer[key], hf.Value) } @@ -5593,13 +5656,13 @@ func (st *http2stream) processTrailerHeaders(f *http2MetaHeadersFrame) error { return nil } -func http2checkPriority(streamID uint32, p http2PriorityParam) error { +func (sc *http2serverConn) checkPriority(streamID uint32, p http2PriorityParam) error { if streamID == p.StreamDep { // Section 5.3.1: "A stream cannot depend on itself. An endpoint MUST treat // this as a stream error (Section 5.4.2) of type PROTOCOL_ERROR." // Section 5.3.3 says that a stream can depend on one of its dependencies, // so it's only self-dependencies that are forbidden. - return http2streamError(streamID, http2ErrCodeProtocol) + return sc.countError("priority", http2streamError(streamID, http2ErrCodeProtocol)) } return nil } @@ -5608,7 +5671,7 @@ func (sc *http2serverConn) processPriority(f *http2PriorityFrame) error { if sc.inGoAway { return nil } - if err := http2checkPriority(f.StreamID, f.http2PriorityParam); err != nil { + if err := sc.checkPriority(f.StreamID, f.http2PriorityParam); err != nil { return err } sc.writeSched.AdjustStream(f.StreamID, f.http2PriorityParam) @@ -5665,7 +5728,7 @@ func (sc *http2serverConn) newWriterAndRequest(st *http2stream, f *http2MetaHead isConnect := rp.method == "CONNECT" if isConnect { if rp.path != "" || rp.scheme != "" || rp.authority == "" { - return nil, nil, http2streamError(f.StreamID, http2ErrCodeProtocol) + return nil, nil, sc.countError("bad_connect", http2streamError(f.StreamID, http2ErrCodeProtocol)) } } else if rp.method == "" || rp.path == "" || (rp.scheme != "https" && rp.scheme != "http") { // See 8.1.2.6 Malformed Requests and Responses: @@ -5678,13 +5741,13 @@ func (sc *http2serverConn) newWriterAndRequest(st *http2stream, f *http2MetaHead // "All HTTP/2 requests MUST include exactly one valid // value for the :method, :scheme, and :path // pseudo-header fields" - return nil, nil, http2streamError(f.StreamID, http2ErrCodeProtocol) + return nil, nil, sc.countError("bad_path_method", http2streamError(f.StreamID, http2ErrCodeProtocol)) } bodyOpen := !f.StreamEnded() if rp.method == "HEAD" && bodyOpen { // HEAD requests can't have bodies - return nil, nil, http2streamError(f.StreamID, http2ErrCodeProtocol) + return nil, nil, sc.countError("head_body", http2streamError(f.StreamID, http2ErrCodeProtocol)) } rp.header = make(Header) @@ -5767,7 +5830,7 @@ func (sc *http2serverConn) newWriterAndRequestNoBody(st *http2stream, rp http2re var err error url_, err = url.ParseRequestURI(rp.path) if err != nil { - return nil, nil, http2streamError(st.id, http2ErrCodeProtocol) + return nil, nil, sc.countError("bad_path", http2streamError(st.id, http2ErrCodeProtocol)) } requestURI = rp.path } @@ -6651,6 +6714,34 @@ func http2h1ServerKeepAlivesDisabled(hs *Server) bool { return false } +func (sc *http2serverConn) countError(name string, err error) error { + if sc == nil || sc.srv == nil { + return err + } + f := sc.srv.CountError + if f == nil { + return err + } + var typ string + var code http2ErrCode + switch e := err.(type) { + case http2ConnectionError: + typ = "conn" + code = http2ErrCode(e) + case http2StreamError: + typ = "stream" + code = http2ErrCode(e.Code) + default: + return err + } + codeStr := http2errCodeName[code] + if codeStr == "" { + codeStr = strconv.Itoa(int(code)) + } + f(fmt.Sprintf("%s_%s_%s", typ, codeStr, name)) + return err +} + const ( // transportDefaultConnFlow is how many connection-level flow control // tokens we give the server at start-up, past the default 64k. @@ -6666,6 +6757,15 @@ const ( http2transportDefaultStreamMinRefresh = 4 << 10 http2defaultUserAgent = "Go-http-client/2.0" + + // initialMaxConcurrentStreams is a connections maxConcurrentStreams until + // it's received servers initial SETTINGS frame, which corresponds with the + // spec's minimum recommended value. + http2initialMaxConcurrentStreams = 100 + + // defaultMaxConcurrentStreams is a connections default maxConcurrentStreams + // if the server doesn't include one in its initial SETTINGS frame. + http2defaultMaxConcurrentStreams = 1000 ) // Transport is an HTTP/2 Transport. @@ -6736,6 +6836,12 @@ type http2Transport struct { // Defaults to 15s. PingTimeout time.Duration + // CountError, if non-nil, is called on HTTP/2 transport errors. + // It's intended to increment a metric for monitoring, such + // as an expvar or Prometheus metric. + // The errType consists of only ASCII word characters. + CountError func(errType string) + // t1, if non-nil, is the standard library Transport using // this transport. Its settings are used (but not its // RoundTrip method, etc). @@ -6842,11 +6948,12 @@ func (t *http2Transport) initConnPool() { // ClientConn is the state of a single HTTP/2 client connection to an // HTTP/2 server. type http2ClientConn struct { - t *http2Transport - tconn net.Conn // usually *tls.Conn, except specialized impls - tlsState *tls.ConnectionState // nil only for specialized impls - reused uint32 // whether conn is being reused; atomic - singleUse bool // whether being used for a single http.Request + t *http2Transport + tconn net.Conn // usually *tls.Conn, except specialized impls + tlsState *tls.ConnectionState // nil only for specialized impls + reused uint32 // whether conn is being reused; atomic + singleUse bool // whether being used for a single http.Request + getConnCalled bool // used by clientConnPool // readLoop goroutine fields: readerDone chan struct{} // closed on error @@ -6859,31 +6966,41 @@ type http2ClientConn struct { cond *sync.Cond // hold mu; broadcast on flow/closed changes flow http2flow // our conn-level flow control quota (cs.flow is per stream) inflow http2flow // peer's conn-level flow control + doNotReuse bool // whether conn is marked to not be reused for any future requests closing bool closed bool + seenSettings bool // true if we've seen a settings frame, false otherwise wantSettingsAck bool // we sent a SETTINGS frame and haven't heard back goAway *http2GoAwayFrame // if non-nil, the GoAwayFrame we received goAwayDebug string // goAway frame's debug data, retained as a string streams map[uint32]*http2clientStream // client-initiated + streamsReserved int // incr by ReserveNewRequest; decr on RoundTrip nextStreamID uint32 pendingRequests int // requests blocked and waiting to be sent because len(streams) == maxConcurrentStreams pings map[[8]byte]chan struct{} // in flight ping data to notification channel - bw *bufio.Writer br *bufio.Reader - fr *http2Framer lastActive time.Time lastIdle time.Time // time last idle - // Settings from peer: (also guarded by mu) + // Settings from peer: (also guarded by wmu) maxFrameSize uint32 maxConcurrentStreams uint32 peerMaxHeaderListSize uint64 initialWindowSize uint32 + // reqHeaderMu is a 1-element semaphore channel controlling access to sending new requests. + // Write to reqHeaderMu to lock it, read from it to unlock. + // Lock reqmu BEFORE mu or wmu. + reqHeaderMu chan struct{} + + // wmu is held while writing. + // Acquire BEFORE mu when holding both, to avoid blocking mu on network writes. + // Only acquire both at the same time when changing peer settings. + wmu sync.Mutex + bw *bufio.Writer + fr *http2Framer + werr error // first write error that has occurred hbuf bytes.Buffer // HPACK encoder writes into this henc *hpack.Encoder - - wmu sync.Mutex // held while writing; acquire AFTER mu if holding both - werr error // first write error that has occurred } // clientStream is the state for a single HTTP/2 stream. One of these @@ -6893,52 +7010,42 @@ type http2clientStream struct { req *Request trace *httptrace.ClientTrace // or nil ID uint32 - resc chan http2resAndError bufPipe http2pipe // buffered pipe with the flow-controlled response payload - startedWrite bool // started request body write; guarded by cc.mu requestedGzip bool - on100 func() // optional code to run if get a 100 continue response + + abortOnce sync.Once + abort chan struct{} // closed to signal stream should end immediately + abortErr error // set if abort is closed + + peerClosed chan struct{} // closed when the peer sends an END_STREAM flag + donec chan struct{} // closed after the stream is in the closed state + on100 chan struct{} // buffered; written to if a 100 is received + + respHeaderRecv chan struct{} // closed when headers are received + res *Response // set if respHeaderRecv is closed flow http2flow // guarded by cc.mu inflow http2flow // guarded by cc.mu bytesRemain int64 // -1 means unknown; owned by transportResponseBody.Read readErr error // sticky read error; owned by transportResponseBody.Read stopReqBody error // if non-nil, stop writing req body; guarded by cc.mu - didReset bool // whether we sent a RST_STREAM to the server; guarded by cc.mu - peerReset chan struct{} // closed on peer reset - resetErr error // populated before peerReset is closed - - done chan struct{} // closed when stream remove from cc.streams map; close calls guarded by cc.mu + // owned by writeRequest: + sentEndStream bool // sent an END_STREAM flag to the peer + sentHeaders bool // owned by clientConnReadLoop: firstByte bool // got the first response byte pastHeaders bool // got first MetaHeadersFrame (actual headers) pastTrailers bool // got optional second MetaHeadersFrame (trailers) num1xx uint8 // number of 1xx responses seen + readClosed bool // peer sent an END_STREAM flag + readAborted bool // read loop reset the stream trailer Header // accumulated trailers resTrailer *Header // client's Response.Trailer } -// awaitRequestCancel waits for the user to cancel a request or for the done -// channel to be signaled. A non-nil error is returned only if the request was -// canceled. -func http2awaitRequestCancel(req *Request, done <-chan struct{}) error { - ctx := req.Context() - if req.Cancel == nil && ctx.Done() == nil { - return nil - } - select { - case <-req.Cancel: - return http2errRequestCanceled - case <-ctx.Done(): - return ctx.Err() - case <-done: - return nil - } -} - var http2got1xxFuncForTests func(int, textproto.MIMEHeader) error // get1xxTraceFunc returns the value of request's httptrace.ClientTrace.Got1xxResponse func, @@ -6950,50 +7057,24 @@ func (cs *http2clientStream) get1xxTraceFunc() func(int, textproto.MIMEHeader) e return http2traceGot1xxResponseFunc(cs.trace) } -// awaitRequestCancel waits for the user to cancel a request, its context to -// expire, or for the request to be done (any way it might be removed from the -// cc.streams map: peer reset, successful completion, TCP connection breakage, -// etc). If the request is canceled, then cs will be canceled and closed. -func (cs *http2clientStream) awaitRequestCancel(req *Request) { - if err := http2awaitRequestCancel(req, cs.done); err != nil { - cs.cancelStream() - cs.bufPipe.CloseWithError(err) - } +func (cs *http2clientStream) abortStream(err error) { + cs.cc.mu.Lock() + defer cs.cc.mu.Unlock() + cs.abortStreamLocked(err) } -func (cs *http2clientStream) cancelStream() { - cc := cs.cc - cc.mu.Lock() - didReset := cs.didReset - cs.didReset = true - cc.mu.Unlock() - - if !didReset { - cc.writeStreamReset(cs.ID, http2ErrCodeCancel, nil) - cc.forgetStreamID(cs.ID) - } -} - -// checkResetOrDone reports any error sent in a RST_STREAM frame by the -// server, or errStreamClosed if the stream is complete. -func (cs *http2clientStream) checkResetOrDone() error { - select { - case <-cs.peerReset: - return cs.resetErr - case <-cs.done: - return http2errStreamClosed - default: - return nil +func (cs *http2clientStream) abortStreamLocked(err error) { + cs.abortOnce.Do(func() { + cs.abortErr = err + close(cs.abort) + }) + // TODO(dneil): Clean up tests where cs.cc.cond is nil. + if cs.cc.cond != nil { + // Wake up writeRequestBody if it is waiting on flow control. + cs.cc.cond.Broadcast() } } -func (cs *http2clientStream) getStartedWrite() bool { - cc := cs.cc - cc.mu.Lock() - defer cc.mu.Unlock() - return cs.startedWrite -} - func (cs *http2clientStream) abortRequestBodyWrite(err error) { if err == nil { panic("nil error") @@ -7002,9 +7083,6 @@ func (cs *http2clientStream) abortRequestBodyWrite(err error) { cc.mu.Lock() if cs.stopReqBody == nil { cs.stopReqBody = err - if cs.req.Body != nil { - cs.req.Body.Close() - } cc.cond.Broadcast() } cc.mu.Unlock() @@ -7095,9 +7173,9 @@ func (t *http2Transport) RoundTripOpt(req *Request, opt http2RoundTripOpt) (*Res } reused := !atomic.CompareAndSwapUint32(&cc.reused, 0, 1) http2traceGotConn(req, cc, reused) - res, gotErrAfterReqBodyWrite, err := cc.roundTrip(req) + res, err := cc.RoundTrip(req) if err != nil && retry <= 6 { - if req, err = http2shouldRetryRequest(req, err, gotErrAfterReqBodyWrite); err == nil { + if req, err = http2shouldRetryRequest(req, err); err == nil { // After the first retry, do exponential backoff with 10% jitter. if retry == 0 { continue @@ -7108,7 +7186,7 @@ func (t *http2Transport) RoundTripOpt(req *Request, opt http2RoundTripOpt) (*Res case <-time.After(time.Second * time.Duration(backoff)): continue case <-req.Context().Done(): - return nil, req.Context().Err() + err = req.Context().Err() } } } @@ -7139,7 +7217,7 @@ var ( // response headers. It is always called with a non-nil error. // It returns either a request to retry (either the same request, or a // modified clone), or an error if the request can't be replayed. -func http2shouldRetryRequest(req *Request, err error, afterBodyWrite bool) (*Request, error) { +func http2shouldRetryRequest(req *Request, err error) (*Request, error) { if !http2canRetryError(err) { return nil, err } @@ -7152,7 +7230,6 @@ func http2shouldRetryRequest(req *Request, err error, afterBodyWrite bool) (*Req // If the request body can be reset back to its original // state via the optional req.GetBody, do that. if req.GetBody != nil { - // TODO: consider a req.Body.Close here? or audit that all caller paths do? body, err := req.GetBody() if err != nil { return nil, err @@ -7164,10 +7241,8 @@ func http2shouldRetryRequest(req *Request, err error, afterBodyWrite bool) (*Req // The Request.Body can't reset back to the beginning, but we // don't seem to have started to read from it yet, so reuse - // the request directly. The "afterBodyWrite" means the - // bodyWrite process has started, which becomes true before - // the first Read. - if !afterBodyWrite { + // the request directly. + if err == http2errClientConnUnusable { return req, nil } @@ -7179,6 +7254,10 @@ func http2canRetryError(err error) bool { return true } if se, ok := err.(http2StreamError); ok { + if se.Code == http2ErrCodeProtocol && se.Cause == http2errFromPeer { + // See golang/go#47635, golang/go#42777 + return true + } return se.Code == http2ErrCodeRefusedStream } return false @@ -7253,14 +7332,15 @@ func (t *http2Transport) newClientConn(c net.Conn, singleUse bool) (*http2Client tconn: c, readerDone: make(chan struct{}), nextStreamID: 1, - maxFrameSize: 16 << 10, // spec default - initialWindowSize: 65535, // spec default - maxConcurrentStreams: 1000, // "infinite", per spec. 1000 seems good enough. - peerMaxHeaderListSize: 0xffffffffffffffff, // "infinite", per spec. Use 2^64-1 instead. + maxFrameSize: 16 << 10, // spec default + initialWindowSize: 65535, // spec default + maxConcurrentStreams: http2initialMaxConcurrentStreams, // "infinite", per spec. Use a smaller value until we have received server settings. + peerMaxHeaderListSize: 0xffffffffffffffff, // "infinite", per spec. Use 2^64-1 instead. streams: make(map[uint32]*http2clientStream), singleUse: singleUse, wantSettingsAck: true, pings: make(map[[8]byte]chan struct{}), + reqHeaderMu: make(chan struct{}, 1), } if d := t.idleConnTimeout(); d != 0 { cc.idleTimeout = d @@ -7278,6 +7358,9 @@ func (t *http2Transport) newClientConn(c net.Conn, singleUse bool) (*http2Client cc.bw = bufio.NewWriter(http2stickyErrWriter{c, &cc.werr}) cc.br = bufio.NewReader(c) cc.fr = http2NewFramer(cc.bw, cc.br) + if t.CountError != nil { + cc.fr.countError = t.CountError + } cc.fr.ReadMetaHeaders = hpack.NewDecoder(http2initialHeaderTableSize, nil) cc.fr.MaxHeaderListSize = t.maxHeaderListSize() @@ -7330,6 +7413,13 @@ func (cc *http2ClientConn) healthCheck() { } } +// SetDoNotReuse marks cc as not reusable for future HTTP requests. +func (cc *http2ClientConn) SetDoNotReuse() { + cc.mu.Lock() + defer cc.mu.Unlock() + cc.doNotReuse = true +} + func (cc *http2ClientConn) setGoAway(f *http2GoAwayFrame) { cc.mu.Lock() defer cc.mu.Unlock() @@ -7347,27 +7437,39 @@ func (cc *http2ClientConn) setGoAway(f *http2GoAwayFrame) { last := f.LastStreamID for streamID, cs := range cc.streams { if streamID > last { - select { - case cs.resc <- http2resAndError{err: http2errClientConnGotGoAway}: - default: - } + cs.abortStreamLocked(http2errClientConnGotGoAway) } } } // CanTakeNewRequest reports whether the connection can take a new request, // meaning it has not been closed or received or sent a GOAWAY. +// +// If the caller is going to immediately make a new request on this +// connection, use ReserveNewRequest instead. func (cc *http2ClientConn) CanTakeNewRequest() bool { cc.mu.Lock() defer cc.mu.Unlock() return cc.canTakeNewRequestLocked() } +// ReserveNewRequest is like CanTakeNewRequest but also reserves a +// concurrent stream in cc. The reservation is decremented on the +// next call to RoundTrip. +func (cc *http2ClientConn) ReserveNewRequest() bool { + cc.mu.Lock() + defer cc.mu.Unlock() + if st := cc.idleStateLocked(); !st.canTakeNewRequest { + return false + } + cc.streamsReserved++ + return true +} + // clientConnIdleState describes the suitability of a client // connection to initiate a new RoundTrip request. type http2clientConnIdleState struct { canTakeNewRequest bool - freshConn bool // whether it's unused by any previous request } func (cc *http2ClientConn) idleState() http2clientConnIdleState { @@ -7388,13 +7490,13 @@ func (cc *http2ClientConn) idleStateLocked() (st http2clientConnIdleState) { // writing it. maxConcurrentOkay = true } else { - maxConcurrentOkay = int64(len(cc.streams)+1) < int64(cc.maxConcurrentStreams) + maxConcurrentOkay = int64(len(cc.streams)+cc.streamsReserved+1) <= int64(cc.maxConcurrentStreams) } st.canTakeNewRequest = cc.goAway == nil && !cc.closed && !cc.closing && maxConcurrentOkay && + !cc.doNotReuse && int64(cc.nextStreamID)+2*int64(cc.pendingRequests) < math.MaxInt32 && !cc.tooIdleLocked() - st.freshConn = cc.nextStreamID == 1 && st.canTakeNewRequest return } @@ -7425,7 +7527,7 @@ func (cc *http2ClientConn) onIdleTimeout() { func (cc *http2ClientConn) closeIfIdle() { cc.mu.Lock() - if len(cc.streams) > 0 { + if len(cc.streams) > 0 || cc.streamsReserved > 0 { cc.mu.Unlock() return } @@ -7440,9 +7542,15 @@ func (cc *http2ClientConn) closeIfIdle() { cc.tconn.Close() } +func (cc *http2ClientConn) isDoNotReuseAndIdle() bool { + cc.mu.Lock() + defer cc.mu.Unlock() + return cc.doNotReuse && len(cc.streams) == 0 +} + var http2shutdownEnterWaitStateHook = func() {} -// Shutdown gracefully close the client connection, waiting for running streams to complete. +// Shutdown gracefully closes the client connection, waiting for running streams to complete. func (cc *http2ClientConn) Shutdown(ctx context.Context) error { if err := cc.sendGoAway(); err != nil { return err @@ -7481,15 +7589,18 @@ func (cc *http2ClientConn) Shutdown(ctx context.Context) error { func (cc *http2ClientConn) sendGoAway() error { cc.mu.Lock() - defer cc.mu.Unlock() - cc.wmu.Lock() - defer cc.wmu.Unlock() - if cc.closing { + closing := cc.closing + cc.closing = true + maxStreamID := cc.nextStreamID + cc.mu.Unlock() + if closing { // GOAWAY sent already return nil } + + cc.wmu.Lock() + defer cc.wmu.Unlock() // Send a graceful shutdown frame to server - maxStreamID := cc.nextStreamID if err := cc.fr.WriteGoAway(maxStreamID, http2ErrCodeNo, nil); err != nil { return err } @@ -7497,7 +7608,6 @@ func (cc *http2ClientConn) sendGoAway() error { return err } // Prevent new requests - cc.closing = true return nil } @@ -7505,17 +7615,12 @@ func (cc *http2ClientConn) sendGoAway() error { // err is sent to streams. func (cc *http2ClientConn) closeForError(err error) error { cc.mu.Lock() + cc.closed = true + for _, cs := range cc.streams { + cs.abortStreamLocked(err) + } defer cc.cond.Broadcast() defer cc.mu.Unlock() - for id, cs := range cc.streams { - select { - case cs.resc <- http2resAndError{err: err}: - default: - } - cs.bufPipe.CloseWithError(err) - delete(cc.streams, id) - } - cc.closed = true return cc.tconn.Close() } @@ -7530,6 +7635,9 @@ func (cc *http2ClientConn) Close() error { // closes the client connection immediately. In-flight requests are interrupted. func (cc *http2ClientConn) closeForLostPing() error { err := errors.New("http2: client connection lost") + if f := cc.t.CountError; f != nil { + f("conn_close_lost_ping") + } return cc.closeForError(err) } @@ -7594,37 +7702,132 @@ func http2actualContentLength(req *Request) int64 { return -1 } -func (cc *http2ClientConn) RoundTrip(req *Request) (*Response, error) { - resp, _, err := cc.roundTrip(req) - return resp, err +func (cc *http2ClientConn) decrStreamReservations() { + cc.mu.Lock() + defer cc.mu.Unlock() + cc.decrStreamReservationsLocked() } -func (cc *http2ClientConn) roundTrip(req *Request) (res *Response, gotErrAfterReqBodyWrite bool, err error) { - if err := http2checkConnHeaders(req); err != nil { - return nil, false, err +func (cc *http2ClientConn) decrStreamReservationsLocked() { + if cc.streamsReserved > 0 { + cc.streamsReserved-- } - if cc.idleTimer != nil { - cc.idleTimer.Stop() +} + +func (cc *http2ClientConn) RoundTrip(req *Request) (*Response, error) { + ctx := req.Context() + cs := &http2clientStream{ + cc: cc, + req: req, + trace: httptrace.ContextClientTrace(req.Context()), + peerClosed: make(chan struct{}), + abort: make(chan struct{}), + respHeaderRecv: make(chan struct{}), + donec: make(chan struct{}), } + go cs.doRequest() - trailers, err := http2commaSeparatedTrailers(req) - if err != nil { - return nil, false, err + waitDone := func() error { + select { + case <-cs.donec: + return nil + case <-ctx.Done(): + return ctx.Err() + case <-req.Cancel: + return http2errRequestCanceled + } + } + + for { + select { + case <-cs.respHeaderRecv: + res := cs.res + if res.StatusCode > 299 { + // On error or status code 3xx, 4xx, 5xx, etc abort any + // ongoing write, assuming that the server doesn't care + // about our request body. If the server replied with 1xx or + // 2xx, however, then assume the server DOES potentially + // want our body (e.g. full-duplex streaming: + // golang.org/issue/13444). If it turns out the server + // doesn't, they'll RST_STREAM us soon enough. This is a + // heuristic to avoid adding knobs to Transport. Hopefully + // we can keep it. + cs.abortRequestBodyWrite(http2errStopReqBodyWrite) + } + res.Request = req + res.TLS = cc.tlsState + if res.Body == http2noBody && http2actualContentLength(req) == 0 { + // If there isn't a request or response body still being + // written, then wait for the stream to be closed before + // RoundTrip returns. + if err := waitDone(); err != nil { + return nil, err + } + } + return res, nil + case <-cs.abort: + waitDone() + return nil, cs.abortErr + case <-ctx.Done(): + return nil, ctx.Err() + case <-req.Cancel: + return nil, http2errRequestCanceled + } + } +} + +// doRequest runs for the duration of the request lifetime. +// +// It sends the request and performs post-request cleanup (closing Request.Body, etc.). +func (cs *http2clientStream) doRequest() { + err := cs.writeRequest() + cs.cleanupWriteRequest(err) +} + +// writeRequest sends a request. +// +// It returns nil after the request is written, the response read, +// and the request stream is half-closed by the peer. +// +// It returns non-nil if the request ends otherwise. +// If the returned error is StreamError, the error Code may be used in resetting the stream. +func (cs *http2clientStream) writeRequest() (err error) { + cc := cs.cc + req := cs.req + ctx := req.Context() + + if err := http2checkConnHeaders(cs.req); err != nil { + return err + } + + // Acquire the new-request lock by writing to reqHeaderMu. + // This lock guards the critical section covering allocating a new stream ID + // (requires mu) and creating the stream (requires wmu). + if cc.reqHeaderMu == nil { + panic("RoundTrip on uninitialized ClientConn") // for tests + } + select { + case cc.reqHeaderMu <- struct{}{}: + case <-req.Cancel: + return http2errRequestCanceled + case <-ctx.Done(): + return ctx.Err() } - hasTrailers := trailers != "" cc.mu.Lock() - if err := cc.awaitOpenSlotForRequest(req); err != nil { + if cc.idleTimer != nil { + cc.idleTimer.Stop() + } + cc.decrStreamReservationsLocked() + if err := cc.awaitOpenSlotForStreamLocked(cs); err != nil { cc.mu.Unlock() - return nil, false, err + <-cc.reqHeaderMu + return err } - - body := req.Body - contentLen := http2actualContentLength(req) - hasBody := contentLen != 0 + cc.addStreamLocked(cs) // assigns stream ID + cc.mu.Unlock() // TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere? - var requestedGzip bool if !cc.t.disableCompression() && req.Header.Get("Accept-Encoding") == "" && req.Header.Get("Range") == "" && @@ -7641,183 +7844,218 @@ func (cc *http2ClientConn) roundTrip(req *Request) (res *Response, gotErrAfterRe // We don't request gzip if the request is for a range, since // auto-decoding a portion of a gzipped document will just fail // anyway. See https://golang.org/issue/8923 - requestedGzip = true + cs.requestedGzip = true } - // we send: HEADERS{1}, CONTINUATION{0,} + DATA{0,} (DATA is - // sent by writeRequestBody below, along with any Trailers, - // again in form HEADERS{1}, CONTINUATION{0,}) - hdrs, err := cc.encodeHeaders(req, requestedGzip, trailers, contentLen) - if err != nil { - cc.mu.Unlock() - return nil, false, err + continueTimeout := cc.t.expectContinueTimeout() + if continueTimeout != 0 && + !httpguts.HeaderValuesContainsToken( + cs.req.Header["Expect"], + "100-continue") { + continueTimeout = 0 + cs.on100 = make(chan struct{}, 1) } - cs := cc.newStream() - cs.req = req - cs.trace = httptrace.ContextClientTrace(req.Context()) - cs.requestedGzip = requestedGzip - bodyWriter := cc.t.getBodyWriterState(cs, body) - cs.on100 = bodyWriter.on100 + err = cs.encodeAndWriteHeaders() + <-cc.reqHeaderMu + if err != nil { + return err + } - defer func() { - cc.wmu.Lock() - werr := cc.werr - cc.wmu.Unlock() - if werr != nil { - cc.Close() + hasBody := http2actualContentLength(cs.req) != 0 + if !hasBody { + cs.sentEndStream = true + } else { + if continueTimeout != 0 { + http2traceWait100Continue(cs.trace) + timer := time.NewTimer(continueTimeout) + select { + case <-timer.C: + err = nil + case <-cs.on100: + err = nil + case <-cs.abort: + err = cs.abortErr + case <-ctx.Done(): + err = ctx.Err() + case <-req.Cancel: + err = http2errRequestCanceled + } + timer.Stop() + if err != nil { + http2traceWroteRequest(cs.trace, err) + return err + } } - }() - - cc.wmu.Lock() - endStream := !hasBody && !hasTrailers - werr := cc.writeHeaders(cs.ID, endStream, int(cc.maxFrameSize), hdrs) - cc.wmu.Unlock() - http2traceWroteHeaders(cs.trace) - cc.mu.Unlock() - if werr != nil { - if hasBody { - req.Body.Close() // per RoundTripper contract - bodyWriter.cancel() + if err = cs.writeRequestBody(req.Body); err != nil { + if err != http2errStopReqBodyWrite { + http2traceWroteRequest(cs.trace, err) + return err + } + } else { + cs.sentEndStream = true } - cc.forgetStreamID(cs.ID) - // Don't bother sending a RST_STREAM (our write already failed; - // no need to keep writing) - http2traceWroteRequest(cs.trace, werr) - return nil, false, werr } + http2traceWroteRequest(cs.trace, err) + var respHeaderTimer <-chan time.Time - if hasBody { - bodyWriter.scheduleBodyWrite() - } else { - http2traceWroteRequest(cs.trace, nil) - if d := cc.responseHeaderTimeout(); d != 0 { - timer := time.NewTimer(d) - defer timer.Stop() - respHeaderTimer = timer.C + var respHeaderRecv chan struct{} + if d := cc.responseHeaderTimeout(); d != 0 { + timer := time.NewTimer(d) + defer timer.Stop() + respHeaderTimer = timer.C + respHeaderRecv = cs.respHeaderRecv + } + // Wait until the peer half-closes its end of the stream, + // or until the request is aborted (via context, error, or otherwise), + // whichever comes first. + for { + select { + case <-cs.peerClosed: + return nil + case <-respHeaderTimer: + return http2errTimeout + case <-respHeaderRecv: + respHeaderTimer = nil // keep waiting for END_STREAM + case <-cs.abort: + return cs.abortErr + case <-ctx.Done(): + return ctx.Err() + case <-req.Cancel: + return http2errRequestCanceled } } +} - readLoopResCh := cs.resc - bodyWritten := false +func (cs *http2clientStream) encodeAndWriteHeaders() error { + cc := cs.cc + req := cs.req ctx := req.Context() - handleReadLoopResponse := func(re http2resAndError) (*Response, bool, error) { - res := re.res - if re.err != nil || res.StatusCode > 299 { - // On error or status code 3xx, 4xx, 5xx, etc abort any - // ongoing write, assuming that the server doesn't care - // about our request body. If the server replied with 1xx or - // 2xx, however, then assume the server DOES potentially - // want our body (e.g. full-duplex streaming: - // golang.org/issue/13444). If it turns out the server - // doesn't, they'll RST_STREAM us soon enough. This is a - // heuristic to avoid adding knobs to Transport. Hopefully - // we can keep it. - bodyWriter.cancel() - cs.abortRequestBodyWrite(http2errStopReqBodyWrite) - if hasBody && !bodyWritten { - <-bodyWriter.resc - } - } - if re.err != nil { - cc.forgetStreamID(cs.ID) - return nil, cs.getStartedWrite(), re.err - } - res.Request = req - res.TLS = cc.tlsState - return res, false, nil + cc.wmu.Lock() + defer cc.wmu.Unlock() + + // If the request was canceled while waiting for cc.mu, just quit. + select { + case <-cs.abort: + return cs.abortErr + case <-ctx.Done(): + return ctx.Err() + case <-req.Cancel: + return http2errRequestCanceled + default: } - handleError := func(err error) (*Response, bool, error) { - if !hasBody || bodyWritten { - cc.writeStreamReset(cs.ID, http2ErrCodeCancel, nil) - } else { - bodyWriter.cancel() - cs.abortRequestBodyWrite(http2errStopReqBodyWriteAndCancel) - <-bodyWriter.resc + // Encode headers. + // + // we send: HEADERS{1}, CONTINUATION{0,} + DATA{0,} (DATA is + // sent by writeRequestBody below, along with any Trailers, + // again in form HEADERS{1}, CONTINUATION{0,}) + trailers, err := http2commaSeparatedTrailers(cs.req) + if err != nil { + return err + } + hasTrailers := trailers != "" + contentLen := http2actualContentLength(cs.req) + hasBody := contentLen != 0 + hdrs, err := cc.encodeHeaders(cs.req, cs.requestedGzip, trailers, contentLen) + if err != nil { + return err + } + + // Write the request. + endStream := !hasBody && !hasTrailers + cs.sentHeaders = true + err = cc.writeHeaders(cs.ID, endStream, int(cc.maxFrameSize), hdrs) + http2traceWroteHeaders(cs.trace) + return err +} + +// cleanupWriteRequest performs post-request tasks. +// +// If err (the result of writeRequest) is non-nil and the stream is not closed, +// cleanupWriteRequest will send a reset to the peer. +func (cs *http2clientStream) cleanupWriteRequest(err error) { + cc := cs.cc + req := cs.req + + if cs.ID == 0 { + // We were canceled before creating the stream, so return our reservation. + cc.decrStreamReservations() + } + + // TODO: write h12Compare test showing whether + // Request.Body is closed by the Transport, + // and in multiple cases: server replies <=299 and >299 + // while still writing request body + if req.Body != nil { + if e := req.Body.Close(); err == nil { + err = e } - cc.forgetStreamID(cs.ID) - return nil, cs.getStartedWrite(), err } - for { + if err != nil && cs.sentEndStream { + // If the connection is closed immediately after the response is read, + // we may be aborted before finishing up here. If the stream was closed + // cleanly on both sides, there is no error. select { - case re := <-readLoopResCh: - return handleReadLoopResponse(re) - case <-respHeaderTimer: - return handleError(http2errTimeout) - case <-ctx.Done(): - return handleError(ctx.Err()) - case <-req.Cancel: - return handleError(http2errRequestCanceled) - case <-cs.peerReset: - // processResetStream already removed the - // stream from the streams map; no need for - // forgetStreamID. - return nil, cs.getStartedWrite(), cs.resetErr - case err := <-bodyWriter.resc: - bodyWritten = true - // Prefer the read loop's response, if available. Issue 16102. - select { - case re := <-readLoopResCh: - return handleReadLoopResponse(re) - default: - } - if err != nil { - cc.forgetStreamID(cs.ID) - return nil, cs.getStartedWrite(), err - } - if d := cc.responseHeaderTimeout(); d != 0 { - timer := time.NewTimer(d) - defer timer.Stop() - respHeaderTimer = timer.C + case <-cs.peerClosed: + err = nil + default: + } + } + if err != nil { + cs.abortStream(err) // possibly redundant, but harmless + if cs.sentHeaders { + if se, ok := err.(http2StreamError); ok { + if se.Cause != http2errFromPeer { + cc.writeStreamReset(cs.ID, se.Code, err) + } + } else { + cc.writeStreamReset(cs.ID, http2ErrCodeCancel, err) } } + cs.bufPipe.CloseWithError(err) // no-op if already closed + } else { + if cs.sentHeaders && !cs.sentEndStream { + cc.writeStreamReset(cs.ID, http2ErrCodeNo, nil) + } + cs.bufPipe.CloseWithError(http2errRequestCanceled) + } + if cs.ID != 0 { + cc.forgetStreamID(cs.ID) + } + close(cs.donec) + + cc.wmu.Lock() + werr := cc.werr + cc.wmu.Unlock() + if werr != nil { + cc.Close() } } -// awaitOpenSlotForRequest waits until len(streams) < maxConcurrentStreams. +// awaitOpenSlotForStream waits until len(streams) < maxConcurrentStreams. // Must hold cc.mu. -func (cc *http2ClientConn) awaitOpenSlotForRequest(req *Request) error { - var waitingForConn chan struct{} - var waitingForConnErr error // guarded by cc.mu +func (cc *http2ClientConn) awaitOpenSlotForStreamLocked(cs *http2clientStream) error { for { cc.lastActive = time.Now() if cc.closed || !cc.canTakeNewRequestLocked() { - if waitingForConn != nil { - close(waitingForConn) - } return http2errClientConnUnusable } cc.lastIdle = time.Time{} - if int64(len(cc.streams))+1 <= int64(cc.maxConcurrentStreams) { - if waitingForConn != nil { - close(waitingForConn) - } + if int64(len(cc.streams)) < int64(cc.maxConcurrentStreams) { return nil } - // Unfortunately, we cannot wait on a condition variable and channel at - // the same time, so instead, we spin up a goroutine to check if the - // request is canceled while we wait for a slot to open in the connection. - if waitingForConn == nil { - waitingForConn = make(chan struct{}) - go func() { - if err := http2awaitRequestCancel(req, waitingForConn); err != nil { - cc.mu.Lock() - waitingForConnErr = err - cc.cond.Broadcast() - cc.mu.Unlock() - } - }() - } cc.pendingRequests++ cc.cond.Wait() cc.pendingRequests-- - if waitingForConnErr != nil { - return waitingForConnErr + select { + case <-cs.abort: + return cs.abortErr + default: } } } @@ -7844,10 +8082,6 @@ func (cc *http2ClientConn) writeHeaders(streamID uint32, endStream bool, maxFram cc.fr.WriteContinuation(streamID, endHeaders, chunk) } } - // TODO(bradfitz): this Flush could potentially block (as - // could the WriteHeaders call(s) above), which means they - // wouldn't respond to Request.Cancel being readable. That's - // rare, but this should probably be in a goroutine. cc.bw.Flush() return cc.werr } @@ -7889,28 +8123,10 @@ func (cs *http2clientStream) frameScratchBufferLen(maxFrameSize int) int { var http2bufPool sync.Pool // of *[]byte -func (cs *http2clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) (err error) { +func (cs *http2clientStream) writeRequestBody(body io.Reader) (err error) { cc := cs.cc sentEnd := false // whether we sent the final DATA frame w/ END_STREAM - defer func() { - http2traceWroteRequest(cs.trace, err) - // TODO: write h12Compare test showing whether - // Request.Body is closed by the Transport, - // and in multiple cases: server replies <=299 and >299 - // while still writing request body - var cerr error - cc.mu.Lock() - if cs.stopReqBody == nil { - cs.stopReqBody = http2errStopReqBodyWrite - cerr = bodyCloser.Close() - } - cc.mu.Unlock() - if err == nil { - err = cerr - } - }() - req := cs.req hasTrailers := req.Trailer != nil remainLen := http2actualContentLength(req) @@ -7951,7 +8167,6 @@ func (cs *http2clientStream) writeRequestBody(body io.Reader, bodyCloser io.Clos } if remainLen < 0 { err = http2errReqBodyTooLong - cc.writeStreamReset(cs.ID, http2ErrCodeCancel, err) return err } } @@ -7959,7 +8174,6 @@ func (cs *http2clientStream) writeRequestBody(body io.Reader, bodyCloser io.Clos sawEOF = true err = nil } else if err != nil { - cc.writeStreamReset(cs.ID, http2ErrCodeCancel, err) return err } @@ -7971,7 +8185,6 @@ func (cs *http2clientStream) writeRequestBody(body io.Reader, bodyCloser io.Clos case err == http2errStopReqBodyWrite: return err case err == http2errStopReqBodyWriteAndCancel: - cc.writeStreamReset(cs.ID, http2ErrCodeCancel, nil) return err case err != nil: return err @@ -8004,19 +8217,15 @@ func (cs *http2clientStream) writeRequestBody(body io.Reader, bodyCloser io.Clos return nil } + cc.wmu.Lock() var trls []byte if hasTrailers { - cc.mu.Lock() trls, err = cc.encodeTrailers(req) - cc.mu.Unlock() if err != nil { - cc.writeStreamReset(cs.ID, http2ErrCodeInternal, err) - cc.forgetStreamID(cs.ID) + cc.wmu.Unlock() return err } } - - cc.wmu.Lock() defer cc.wmu.Unlock() // Two ways to send END_STREAM: either with trailers, or @@ -8038,6 +8247,8 @@ func (cs *http2clientStream) writeRequestBody(body io.Reader, bodyCloser io.Clos // if the stream is dead. func (cs *http2clientStream) awaitFlowControl(maxBytes int) (taken int32, err error) { cc := cs.cc + req := cs.req + ctx := req.Context() cc.mu.Lock() defer cc.mu.Unlock() for { @@ -8047,8 +8258,14 @@ func (cs *http2clientStream) awaitFlowControl(maxBytes int) (taken int32, err er if cs.stopReqBody != nil { return 0, cs.stopReqBody } - if err := cs.checkResetOrDone(); err != nil { - return 0, err + select { + case <-cs.abort: + return 0, cs.abortErr + case <-ctx.Done(): + return 0, ctx.Err() + case <-req.Cancel: + return 0, http2errRequestCanceled + default: } if a := cs.flow.available(); a > 0 { take := a @@ -8066,9 +8283,14 @@ func (cs *http2clientStream) awaitFlowControl(maxBytes int) (taken int32, err er } } -// requires cc.mu be held. +var http2errNilRequestURL = errors.New("http2: Request.URI is nil") + +// requires cc.wmu be held. func (cc *http2ClientConn) encodeHeaders(req *Request, addGzipHeader bool, trailers string, contentLength int64) ([]byte, error) { cc.hbuf.Reset() + if req.URL == nil { + return nil, http2errNilRequestURL + } host := req.Host if host == "" { @@ -8254,7 +8476,7 @@ func http2shouldSendReqContentLength(method string, contentLength int64) bool { } } -// requires cc.mu be held. +// requires cc.wmu be held. func (cc *http2ClientConn) encodeTrailers(req *Request) ([]byte, error) { cc.hbuf.Reset() @@ -8299,51 +8521,51 @@ type http2resAndError struct { } // requires cc.mu be held. -func (cc *http2ClientConn) newStream() *http2clientStream { - cs := &http2clientStream{ - cc: cc, - ID: cc.nextStreamID, - resc: make(chan http2resAndError, 1), - peerReset: make(chan struct{}), - done: make(chan struct{}), - } +func (cc *http2ClientConn) addStreamLocked(cs *http2clientStream) { cs.flow.add(int32(cc.initialWindowSize)) cs.flow.setConnFlow(&cc.flow) cs.inflow.add(http2transportDefaultStreamFlow) cs.inflow.setConnFlow(&cc.inflow) + cs.ID = cc.nextStreamID cc.nextStreamID += 2 cc.streams[cs.ID] = cs - return cs + if cs.ID == 0 { + panic("assigned stream ID 0") + } } func (cc *http2ClientConn) forgetStreamID(id uint32) { - cc.streamByID(id, true) -} - -func (cc *http2ClientConn) streamByID(id uint32, andRemove bool) *http2clientStream { cc.mu.Lock() - defer cc.mu.Unlock() - cs := cc.streams[id] - if andRemove && cs != nil && !cc.closed { - cc.lastActive = time.Now() - delete(cc.streams, id) - if len(cc.streams) == 0 && cc.idleTimer != nil { - cc.idleTimer.Reset(cc.idleTimeout) - cc.lastIdle = time.Now() - } - close(cs.done) - // Wake up checkResetOrDone via clientStream.awaitFlowControl and - // wake up RoundTrip if there is a pending request. - cc.cond.Broadcast() + slen := len(cc.streams) + delete(cc.streams, id) + if len(cc.streams) != slen-1 { + panic("forgetting unknown stream id") + } + cc.lastActive = time.Now() + if len(cc.streams) == 0 && cc.idleTimer != nil { + cc.idleTimer.Reset(cc.idleTimeout) + cc.lastIdle = time.Now() + } + // Wake up writeRequestBody via clientStream.awaitFlowControl and + // wake up RoundTrip if there is a pending request. + cc.cond.Broadcast() + + closeOnIdle := cc.singleUse || cc.doNotReuse || cc.t.disableKeepAlives() + if closeOnIdle && cc.streamsReserved == 0 && len(cc.streams) == 0 { + if http2VerboseLogs { + cc.vlogf("http2: Transport closing idle conn %p (forSingleUse=%v, maxStream=%v)", cc, cc.singleUse, cc.nextStreamID-2) + } + cc.closed = true + defer cc.tconn.Close() } - return cs + + cc.mu.Unlock() } // clientConnReadLoop is the state owned by the clientConn's frame-reading readLoop. type http2clientConnReadLoop struct { - _ http2incomparable - cc *http2ClientConn - closeWhenIdle bool + _ http2incomparable + cc *http2ClientConn } // readLoop runs in its own goroutine and reads and dispatches frames. @@ -8403,23 +8625,43 @@ func (rl *http2clientConnReadLoop) cleanup() { } else if err == io.EOF { err = io.ErrUnexpectedEOF } + cc.closed = true for _, cs := range cc.streams { - cs.bufPipe.CloseWithError(err) // no-op if already closed - select { - case cs.resc <- http2resAndError{err: err}: - default: - } - close(cs.done) + cs.abortStreamLocked(err) } - cc.closed = true cc.cond.Broadcast() cc.mu.Unlock() } +// countReadFrameError calls Transport.CountError with a string +// representing err. +func (cc *http2ClientConn) countReadFrameError(err error) { + f := cc.t.CountError + if f == nil || err == nil { + return + } + if ce, ok := err.(http2ConnectionError); ok { + errCode := http2ErrCode(ce) + f(fmt.Sprintf("read_frame_conn_error_%s", errCode.stringToken())) + return + } + if errors.Is(err, io.EOF) { + f("read_frame_eof") + return + } + if errors.Is(err, io.ErrUnexpectedEOF) { + f("read_frame_unexpected_eof") + return + } + if errors.Is(err, http2ErrFrameTooLarge) { + f("read_frame_too_large") + return + } + f("read_frame_other") +} + func (rl *http2clientConnReadLoop) run() error { cc := rl.cc - rl.closeWhenIdle = cc.t.disableKeepAlives() || cc.singleUse - gotReply := false // ever saw a HEADERS reply gotSettings := false readIdleTimeout := cc.t.ReadIdleTimeout var t *time.Timer @@ -8436,9 +8678,7 @@ func (rl *http2clientConnReadLoop) run() error { cc.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", cc, err, err) } if se, ok := err.(http2StreamError); ok { - if cs := cc.streamByID(se.StreamID, false); cs != nil { - cs.cc.writeStreamReset(cs.ID, se.Code, err) - cs.cc.forgetStreamID(cs.ID) + if cs := rl.streamByID(se.StreamID); cs != nil { if se.Cause == nil { se.Cause = cc.fr.errDetail } @@ -8446,6 +8686,7 @@ func (rl *http2clientConnReadLoop) run() error { } continue } else if err != nil { + cc.countReadFrameError(err) return err } if http2VerboseLogs { @@ -8458,22 +8699,16 @@ func (rl *http2clientConnReadLoop) run() error { } gotSettings = true } - maybeIdle := false // whether frame might transition us to idle switch f := f.(type) { case *http2MetaHeadersFrame: err = rl.processHeaders(f) - maybeIdle = true - gotReply = true case *http2DataFrame: err = rl.processData(f) - maybeIdle = true case *http2GoAwayFrame: err = rl.processGoAway(f) - maybeIdle = true case *http2RSTStreamFrame: err = rl.processResetStream(f) - maybeIdle = true case *http2SettingsFrame: err = rl.processSettings(f) case *http2PushPromiseFrame: @@ -8491,38 +8726,24 @@ func (rl *http2clientConnReadLoop) run() error { } return err } - if rl.closeWhenIdle && gotReply && maybeIdle { - cc.closeIfIdle() - } } } func (rl *http2clientConnReadLoop) processHeaders(f *http2MetaHeadersFrame) error { - cc := rl.cc - cs := cc.streamByID(f.StreamID, false) + cs := rl.streamByID(f.StreamID) if cs == nil { // We'd get here if we canceled a request while the // server had its response still in flight. So if this // was just something we canceled, ignore it. return nil } - if f.StreamEnded() { - // Issue 20521: If the stream has ended, streamByID() causes - // clientStream.done to be closed, which causes the request's bodyWriter - // to be closed with an errStreamClosed, which may be received by - // clientConn.RoundTrip before the result of processing these headers. - // Deferring stream closure allows the header processing to occur first. - // clientConn.RoundTrip may still receive the bodyWriter error first, but - // the fix for issue 16102 prioritises any response. - // - // Issue 22413: If there is no request body, we should close the - // stream before writing to cs.resc so that the stream is closed - // immediately once RoundTrip returns. - if cs.req.Body != nil { - defer cc.forgetStreamID(f.StreamID) - } else { - cc.forgetStreamID(f.StreamID) - } + if cs.readClosed { + rl.endStreamError(cs, http2StreamError{ + StreamID: f.StreamID, + Code: http2ErrCodeProtocol, + Cause: errors.New("protocol error: headers after END_STREAM"), + }) + return nil } if !cs.firstByte { if cs.trace != nil { @@ -8546,9 +8767,11 @@ func (rl *http2clientConnReadLoop) processHeaders(f *http2MetaHeadersFrame) erro return err } // Any other error type is a stream error. - cs.cc.writeStreamReset(f.StreamID, http2ErrCodeProtocol, err) - cc.forgetStreamID(cs.ID) - cs.resc <- http2resAndError{err: err} + rl.endStreamError(cs, http2StreamError{ + StreamID: f.StreamID, + Code: http2ErrCodeProtocol, + Cause: err, + }) return nil // return nil from process* funcs to keep conn alive } if res == nil { @@ -8556,7 +8779,11 @@ func (rl *http2clientConnReadLoop) processHeaders(f *http2MetaHeadersFrame) erro return nil } cs.resTrailer = &res.Trailer - cs.resc <- http2resAndError{res: res} + cs.res = res + close(cs.respHeaderRecv) + if f.StreamEnded() { + rl.endStream(cs) + } return nil } @@ -8618,6 +8845,9 @@ func (rl *http2clientConnReadLoop) handleResponse(cs *http2clientStream, f *http } if statusCode >= 100 && statusCode <= 199 { + if f.StreamEnded() { + return nil, errors.New("1xx informational response with END_STREAM flag") + } cs.num1xx++ const max1xxResponses = 5 // arbitrary bound on number of informational responses, same as net/http if cs.num1xx > max1xxResponses { @@ -8630,8 +8860,9 @@ func (rl *http2clientConnReadLoop) handleResponse(cs *http2clientStream, f *http } if statusCode == 100 { http2traceGot100Continue(cs.trace) - if cs.on100 != nil { - cs.on100() // forces any write delay timer to fire + select { + case cs.on100 <- struct{}{}: + default: } } cs.pastHeaders = false // do it all again @@ -8660,10 +8891,9 @@ func (rl *http2clientConnReadLoop) handleResponse(cs *http2clientStream, f *http return res, nil } - cs.bufPipe = http2pipe{b: &http2dataBuffer{expected: res.ContentLength}} + cs.bufPipe.setBuffer(&http2dataBuffer{expected: res.ContentLength}) cs.bytesRemain = res.ContentLength res.Body = http2transportResponseBody{cs} - go cs.awaitRequestCancel(cs.req) if cs.requestedGzip && res.Header.Get("Content-Encoding") == "gzip" { res.Header.Del("Content-Encoding") @@ -8723,7 +8953,7 @@ func (b http2transportResponseBody) Read(p []byte) (n int, err error) { n = int(cs.bytesRemain) if err == nil { err = errors.New("net/http: server replied with more than declared Content-Length; truncated") - cc.writeStreamReset(cs.ID, http2ErrCodeProtocol, err) + cs.abortStream(err) } cs.readErr = err return int(cs.bytesRemain), err @@ -8741,8 +8971,6 @@ func (b http2transportResponseBody) Read(p []byte) (n int, err error) { } cc.mu.Lock() - defer cc.mu.Unlock() - var connAdd, streamAdd int32 // Check the conn-level first, before the stream-level. if v := cc.inflow.available(); v < http2transportDefaultConnFlow/2 { @@ -8759,6 +8987,8 @@ func (b http2transportResponseBody) Read(p []byte) (n int, err error) { cs.inflow.add(streamAdd) } } + cc.mu.Unlock() + if connAdd != 0 || streamAdd != 0 { cc.wmu.Lock() defer cc.wmu.Unlock() @@ -8779,34 +9009,40 @@ func (b http2transportResponseBody) Close() error { cs := b.cs cc := cs.cc - serverSentStreamEnd := cs.bufPipe.Err() == io.EOF unread := cs.bufPipe.Len() - - if unread > 0 || !serverSentStreamEnd { + if unread > 0 { cc.mu.Lock() - cc.wmu.Lock() - if !serverSentStreamEnd { - cc.fr.WriteRSTStream(cs.ID, http2ErrCodeCancel) - cs.didReset = true - } // Return connection-level flow control. if unread > 0 { cc.inflow.add(int32(unread)) + } + cc.mu.Unlock() + + cc.wmu.Lock() + // Return connection-level flow control. + if unread > 0 { cc.fr.WriteWindowUpdate(0, uint32(unread)) } cc.bw.Flush() cc.wmu.Unlock() - cc.mu.Unlock() } cs.bufPipe.BreakWithError(http2errClosedResponseBody) - cc.forgetStreamID(cs.ID) + cs.abortStream(http2errClosedResponseBody) + + select { + case <-cs.donec: + case <-cs.req.Context().Done(): + return cs.req.Context().Err() + case <-cs.req.Cancel: + return http2errRequestCanceled + } return nil } func (rl *http2clientConnReadLoop) processData(f *http2DataFrame) error { cc := rl.cc - cs := cc.streamByID(f.StreamID, f.StreamEnded()) + cs := rl.streamByID(f.StreamID) data := f.Data() if cs == nil { cc.mu.Lock() @@ -8835,6 +9071,14 @@ func (rl *http2clientConnReadLoop) processData(f *http2DataFrame) error { } return nil } + if cs.readClosed { + cc.logf("protocol error: received DATA after END_STREAM") + rl.endStreamError(cs, http2StreamError{ + StreamID: f.StreamID, + Code: http2ErrCodeProtocol, + }) + return nil + } if !cs.firstByte { cc.logf("protocol error: received DATA before a HEADERS frame") rl.endStreamError(cs, http2StreamError{ @@ -8866,30 +9110,39 @@ func (rl *http2clientConnReadLoop) processData(f *http2DataFrame) error { if pad := int(f.Length) - len(data); pad > 0 { refund += pad } - // Return len(data) now if the stream is already closed, - // since data will never be read. - didReset := cs.didReset - if didReset { - refund += len(data) + + didReset := false + var err error + if len(data) > 0 { + if _, err = cs.bufPipe.Write(data); err != nil { + // Return len(data) now if the stream is already closed, + // since data will never be read. + didReset = true + refund += len(data) + } } + if refund > 0 { cc.inflow.add(int32(refund)) + if !didReset { + cs.inflow.add(int32(refund)) + } + } + cc.mu.Unlock() + + if refund > 0 { cc.wmu.Lock() cc.fr.WriteWindowUpdate(0, uint32(refund)) if !didReset { - cs.inflow.add(int32(refund)) cc.fr.WriteWindowUpdate(cs.ID, uint32(refund)) } cc.bw.Flush() cc.wmu.Unlock() } - cc.mu.Unlock() - if len(data) > 0 && !didReset { - if _, err := cs.bufPipe.Write(data); err != nil { - rl.endStreamError(cs, err) - return err - } + if err != nil { + rl.endStreamError(cs, err) + return nil } } @@ -8902,24 +9155,26 @@ func (rl *http2clientConnReadLoop) processData(f *http2DataFrame) error { func (rl *http2clientConnReadLoop) endStream(cs *http2clientStream) { // TODO: check that any declared content-length matches, like // server.go's (*stream).endStream method. - rl.endStreamError(cs, nil) + if !cs.readClosed { + cs.readClosed = true + cs.bufPipe.closeWithErrorAndCode(io.EOF, cs.copyTrailers) + close(cs.peerClosed) + } } func (rl *http2clientConnReadLoop) endStreamError(cs *http2clientStream, err error) { - var code func() - if err == nil { - err = io.EOF - code = cs.copyTrailers - } - if http2isConnectionCloseRequest(cs.req) { - rl.closeWhenIdle = true - } - cs.bufPipe.closeWithErrorAndCode(err, code) + cs.readAborted = true + cs.abortStream(err) +} - select { - case cs.resc <- http2resAndError{err: err}: - default: +func (rl *http2clientConnReadLoop) streamByID(id uint32) *http2clientStream { + rl.cc.mu.Lock() + defer rl.cc.mu.Unlock() + cs := rl.cc.streams[id] + if cs != nil && !cs.readAborted { + return cs } + return nil } func (cs *http2clientStream) copyTrailers() { @@ -8938,12 +9193,33 @@ func (rl *http2clientConnReadLoop) processGoAway(f *http2GoAwayFrame) error { if f.ErrCode != 0 { // TODO: deal with GOAWAY more. particularly the error code cc.vlogf("transport got GOAWAY with error code = %v", f.ErrCode) + if fn := cc.t.CountError; fn != nil { + fn("recv_goaway_" + f.ErrCode.stringToken()) + } + } cc.setGoAway(f) return nil } func (rl *http2clientConnReadLoop) processSettings(f *http2SettingsFrame) error { + cc := rl.cc + // Locking both mu and wmu here allows frame encoding to read settings with only wmu held. + // Acquiring wmu when f.IsAck() is unnecessary, but convenient and mostly harmless. + cc.wmu.Lock() + defer cc.wmu.Unlock() + + if err := rl.processSettingsNoWrite(f); err != nil { + return err + } + if !f.IsAck() { + cc.fr.WriteSettingsAck() + cc.bw.Flush() + } + return nil +} + +func (rl *http2clientConnReadLoop) processSettingsNoWrite(f *http2SettingsFrame) error { cc := rl.cc cc.mu.Lock() defer cc.mu.Unlock() @@ -8956,12 +9232,14 @@ func (rl *http2clientConnReadLoop) processSettings(f *http2SettingsFrame) error return http2ConnectionError(http2ErrCodeProtocol) } + var seenMaxConcurrentStreams bool err := f.ForeachSetting(func(s http2Setting) error { switch s.ID { case http2SettingMaxFrameSize: cc.maxFrameSize = s.Val case http2SettingMaxConcurrentStreams: cc.maxConcurrentStreams = s.Val + seenMaxConcurrentStreams = true case http2SettingMaxHeaderListSize: cc.peerMaxHeaderListSize = uint64(s.Val) case http2SettingInitialWindowSize: @@ -8993,17 +9271,23 @@ func (rl *http2clientConnReadLoop) processSettings(f *http2SettingsFrame) error return err } - cc.wmu.Lock() - defer cc.wmu.Unlock() + if !cc.seenSettings { + if !seenMaxConcurrentStreams { + // This was the servers initial SETTINGS frame and it + // didn't contain a MAX_CONCURRENT_STREAMS field so + // increase the number of concurrent streams this + // connection can establish to our default. + cc.maxConcurrentStreams = http2defaultMaxConcurrentStreams + } + cc.seenSettings = true + } - cc.fr.WriteSettingsAck() - cc.bw.Flush() - return cc.werr + return nil } func (rl *http2clientConnReadLoop) processWindowUpdate(f *http2WindowUpdateFrame) error { cc := rl.cc - cs := cc.streamByID(f.StreamID, false) + cs := rl.streamByID(f.StreamID) if f.StreamID != 0 && cs == nil { return nil } @@ -9023,24 +9307,22 @@ func (rl *http2clientConnReadLoop) processWindowUpdate(f *http2WindowUpdateFrame } func (rl *http2clientConnReadLoop) processResetStream(f *http2RSTStreamFrame) error { - cs := rl.cc.streamByID(f.StreamID, true) + cs := rl.streamByID(f.StreamID) if cs == nil { - // TODO: return error if server tries to RST_STEAM an idle stream + // TODO: return error if server tries to RST_STREAM an idle stream return nil } - select { - case <-cs.peerReset: - // Already reset. - // This is the only goroutine - // which closes this, so there - // isn't a race. - default: - err := http2streamError(cs.ID, f.ErrCode) - cs.resetErr = err - close(cs.peerReset) - cs.bufPipe.CloseWithError(err) - cs.cc.cond.Broadcast() // wake up checkResetOrDone via clientStream.awaitFlowControl + serr := http2streamError(cs.ID, f.ErrCode) + serr.Cause = http2errFromPeer + if f.ErrCode == http2ErrCodeProtocol { + rl.cc.SetDoNotReuse() } + if fn := cs.cc.t.CountError; fn != nil { + fn("recv_rststream_" + f.ErrCode.stringToken()) + } + cs.abortStream(serr) + + cs.bufPipe.CloseWithError(serr) return nil } @@ -9197,87 +9479,6 @@ type http2errorReader struct{ err error } func (r http2errorReader) Read(p []byte) (int, error) { return 0, r.err } -// bodyWriterState encapsulates various state around the Transport's writing -// of the request body, particularly regarding doing delayed writes of the body -// when the request contains "Expect: 100-continue". -type http2bodyWriterState struct { - cs *http2clientStream - timer *time.Timer // if non-nil, we're doing a delayed write - fnonce *sync.Once // to call fn with - fn func() // the code to run in the goroutine, writing the body - resc chan error // result of fn's execution - delay time.Duration // how long we should delay a delayed write for -} - -func (t *http2Transport) getBodyWriterState(cs *http2clientStream, body io.Reader) (s http2bodyWriterState) { - s.cs = cs - if body == nil { - return - } - resc := make(chan error, 1) - s.resc = resc - s.fn = func() { - cs.cc.mu.Lock() - cs.startedWrite = true - cs.cc.mu.Unlock() - resc <- cs.writeRequestBody(body, cs.req.Body) - } - s.delay = t.expectContinueTimeout() - if s.delay == 0 || - !httpguts.HeaderValuesContainsToken( - cs.req.Header["Expect"], - "100-continue") { - return - } - s.fnonce = new(sync.Once) - - // Arm the timer with a very large duration, which we'll - // intentionally lower later. It has to be large now because - // we need a handle to it before writing the headers, but the - // s.delay value is defined to not start until after the - // request headers were written. - const hugeDuration = 365 * 24 * time.Hour - s.timer = time.AfterFunc(hugeDuration, func() { - s.fnonce.Do(s.fn) - }) - return -} - -func (s http2bodyWriterState) cancel() { - if s.timer != nil { - if s.timer.Stop() { - s.resc <- nil - } - } -} - -func (s http2bodyWriterState) on100() { - if s.timer == nil { - // If we didn't do a delayed write, ignore the server's - // bogus 100 continue response. - return - } - s.timer.Stop() - go func() { s.fnonce.Do(s.fn) }() -} - -// scheduleBodyWrite starts writing the body, either immediately (in -// the common case) or after the delay timeout. It should not be -// called until after the headers have been written. -func (s http2bodyWriterState) scheduleBodyWrite() { - if s.timer == nil { - // We're not doing a delayed write (see - // getBodyWriterState), so just start the writing - // goroutine immediately. - go s.fn() - return - } - http2traceWait100Continue(s.cs.trace) - if s.timer.Stop() { - s.timer.Reset(s.delay) - } -} - // isConnectionCloseRequest reports whether req should use its own // connection for a single request and then close the connection. func http2isConnectionCloseRequest(req *Request) bool { diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index 3dc867957e..250c87a663 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -9,7 +9,7 @@ golang.org/x/crypto/curve25519/internal/field golang.org/x/crypto/hkdf golang.org/x/crypto/internal/subtle golang.org/x/crypto/poly1305 -# golang.org/x/net v0.0.0-20210825183410-e898025ed96a +# golang.org/x/net v0.0.0-20211004220534-69340ce214a7 ## explicit; go 1.17 golang.org/x/net/dns/dnsmessage golang.org/x/net/http/httpguts -- GitLab From 316057142cc6055952621ccbaccc53d58d88be3f Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Tue, 28 Sep 2021 11:52:45 -0400 Subject: [PATCH 1479/2500] cmd/go: do not pass a local prefix to the compiler in module mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In GOPATH mode, source files may import other packages using relative (“local”) paths. In module mode, relative imports are never allowed: import paths must always be fully specified. When local imports are allowed, we pass a local-import prefix to the compiler using the '-D' flag. That could theoretically change the compiler's output, so it must be included in the cache key even when -trimpath is set. (TODO: when -trimpath is set, the local-import prefix ought to be trimmed anyway, so it still shouldn't matter.) However, when local imports are disallowed, we should not pass the local-import prefix and it should not affect cmd/go's cache key or the final build ID of any artifact. For #48557 Change-Id: I2d627d67d13e5da2cac6d411cd4e2d87e510876c Reviewed-on: https://go-review.googlesource.com/c/go/+/352810 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/load/pkg.go | 9 ++-- src/cmd/go/internal/work/gc.go | 5 +- .../script/mod_build_trimpath_issue48557.txt | 52 +++++++++++++++++++ 3 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 src/cmd/go/testdata/script/mod_build_trimpath_issue48557.txt diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index 8a5a1a5fe2..a3a8de81c9 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -1678,9 +1678,10 @@ func (p *Package) DefaultExecName() string { func (p *Package) load(ctx context.Context, opts PackageOpts, path string, stk *ImportStack, importPos []token.Position, bp *build.Package, err error) { p.copyBuild(opts, bp) - // The localPrefix is the path we interpret ./ imports relative to. + // The localPrefix is the path we interpret ./ imports relative to, + // if we support them at all (not in module mode!). // Synthesized main packages sometimes override this. - if p.Internal.Local { + if p.Internal.Local && !cfg.ModulesEnabled { p.Internal.LocalPrefix = dirToImportPath(p.Dir) } @@ -2703,7 +2704,9 @@ func GoFilesPackage(ctx context.Context, opts PackageOpts, gofiles []string) *Pa pkg.Internal.Local = true pkg.Internal.CmdlineFiles = true pkg.load(ctx, opts, "command-line-arguments", &stk, nil, bp, err) - pkg.Internal.LocalPrefix = dirToImportPath(dir) + if !cfg.ModulesEnabled { + pkg.Internal.LocalPrefix = dirToImportPath(dir) + } pkg.ImportPath = "command-line-arguments" pkg.Target = "" pkg.Match = gofiles diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go index 85f661bf31..3eb9b35f40 100644 --- a/src/cmd/go/internal/work/gc.go +++ b/src/cmd/go/internal/work/gc.go @@ -165,8 +165,9 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg } args := []interface{}{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", a.trimpath(), defaultGcFlags, gcflags} - if p.Internal.LocalPrefix != "" { - // Workaround #43883. + if p.Internal.LocalPrefix == "" { + args = append(args, "-nolocalimports") + } else { args = append(args, "-D", p.Internal.LocalPrefix) } if importcfg != nil { diff --git a/src/cmd/go/testdata/script/mod_build_trimpath_issue48557.txt b/src/cmd/go/testdata/script/mod_build_trimpath_issue48557.txt new file mode 100644 index 0000000000..859eafcf84 --- /dev/null +++ b/src/cmd/go/testdata/script/mod_build_trimpath_issue48557.txt @@ -0,0 +1,52 @@ +# Regression test for issue #48557. +# Since builds in module mode do not support relative imports at all, the build +# ID for (and other contents of) a binary built with -trimpath in module mode +# should not depend on its working directory, even if the binary is specified as +# a list of relative source files. + +[short] skip # links and runs binaries + +env GOFLAGS=-trimpath +env GOCACHE=$WORK/gocache + + +# When we build a binary in module mode with -trimpath, the -D flag (for the +# "local import prefix") should not be passed to it. + +cd $WORK/tmp/foo +go build -x -o a.exe main.go +stderr ${/}compile$GOEXE.*' -nolocalimports' +! stderr ${/}compile$GOEXE.*' -D[ =]' + +go tool buildid a.exe +cp stdout ../foo-buildid.txt +go version a.exe +cp stdout ../foo-version.txt +cd .. + + +# On the second build — in a different directory but with -trimpath — the +# compiler should not be invoked, since the cache key should be identical. +# Only the linker and buildid tool should be needed. + +mkdir bar +cp foo/main.go bar/main.go +cd bar +go build -x -o a.exe main.go +! stderr ${/}compile$GOEXE + +go tool buildid a.exe +cp stdout ../bar-buildid.txt +go version a.exe +cp stdout ../bar-version.txt +cd .. + +cmp bar-buildid.txt foo-buildid.txt +cmp bar-version.txt foo-version.txt +cmp bar/a.exe foo/a.exe + + +-- $WORK/tmp/foo/main.go -- +package main + +func main() {} -- GitLab From 415f0a33750a7cb4ad282fc5aa664d3fde244f84 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 6 Oct 2021 12:39:41 -0400 Subject: [PATCH 1480/2500] cmd/link: keep go.buildid alive on AIX external linking As we use relative addressing for text symbols in functab, it is important that the offsets we computed stay unchanged by the external linker, i.e. all symbols in Textp should not be removed by the external linker. Most of them are actually referenced (our deadcode pass ensures that), except go.buildid which is generated late and not used by the program. Keep it alive. Should fix AIX builder. Change-Id: Ibc4a8951be997b9d8d870d75c54754977d9b8333 Reviewed-on: https://go-review.googlesource.com/c/go/+/354369 Trust: Cherry Mui Trust: Josh Bleecher Snyder Run-TryBot: Cherry Mui Reviewed-by: Than McIntosh Reviewed-by: Josh Bleecher Snyder TryBot-Result: Go Bot --- src/cmd/link/internal/ld/symtab.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index 878d30b5f1..8eca250131 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -676,7 +676,7 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { if ctxt.IsAIX() && ctxt.IsExternal() { // Add R_XCOFFREF relocation to prevent ld's garbage collection of - // runtime.rodata, runtime.erodata and runtime.epclntab. + // the following symbols. They might not be referenced in the program. addRef := func(name string) { r, _ := moduledata.AddRel(objabi.R_XCOFFREF) r.SetSym(ldr.Lookup(name, 0)) @@ -685,6 +685,12 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { addRef("runtime.rodata") addRef("runtime.erodata") addRef("runtime.epclntab") + // As we use relative addressing for text symbols in functab, it is + // important that the offsets we computed stay unchanged by the external + // linker, i.e. all symbols in Textp should not be removed. + // Most of them are actually referenced (our deadcode pass ensures that), + // except go.buildid which is generated late and not used by the program. + addRef("go.buildid") } // text section information -- GitLab From 195945a40d6c644e91d4811c727e65a0593be1eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6hrmann?= Date: Wed, 6 Oct 2021 05:27:52 +0200 Subject: [PATCH 1481/2500] internal/cpu: remove option to mark cpu features required MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the removal of SSE2 runtime detection made in golang.org/cl/344350 we can remove this mechanism as there are no required features anymore. For making sure CPUs running a go program support all the minimal hardware requirements the go runtime should do feature checks early in the runtime initialization before it is likely any compiler emitted but unsupported instructions are used. This is already the case for e.g. checking MMX support on 386 arch targets. Change-Id: If7b1cb6f43233841e917d37a18314d06a334a734 Reviewed-on: https://go-review.googlesource.com/c/go/+/354209 Trust: Martin Möhrmann Run-TryBot: Martin Möhrmann TryBot-Result: Go Bot Reviewed-by: Tobias Klauser Reviewed-by: Keith Randall --- src/internal/cpu/cpu.go | 8 +------- src/internal/cpu/cpu_test.go | 20 +------------------- 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/src/internal/cpu/cpu.go b/src/internal/cpu/cpu.go index 4f0c5d2896..30745344e1 100644 --- a/src/internal/cpu/cpu.go +++ b/src/internal/cpu/cpu.go @@ -136,7 +136,6 @@ type option struct { Feature *bool Specified bool // whether feature value was specified in GODEBUG Enable bool // whether feature should be enabled - Required bool // whether feature is mandatory and can not be disabled } // processOptions enables or disables CPU feature values based on the parsed env string. @@ -179,7 +178,7 @@ field: if key == "all" { for i := range options { options[i].Specified = true - options[i].Enable = enable || options[i].Required + options[i].Enable = enable } continue field } @@ -205,11 +204,6 @@ field: continue } - if !o.Enable && o.Required { - print("GODEBUG: can not disable \"", o.Name, "\", required CPU feature\n") - continue - } - *o.Feature = o.Enable } } diff --git a/src/internal/cpu/cpu_test.go b/src/internal/cpu/cpu_test.go index 2de7365732..06ad20800f 100644 --- a/src/internal/cpu/cpu_test.go +++ b/src/internal/cpu/cpu_test.go @@ -9,28 +9,10 @@ import ( "internal/testenv" "os" "os/exec" - "runtime" "strings" "testing" ) -func TestMinimalFeatures(t *testing.T) { - // TODO: maybe do MustSupportFeatureDectection(t) ? - if runtime.GOARCH == "arm64" { - switch runtime.GOOS { - case "linux", "android", "darwin": - default: - t.Skipf("%s/%s is not supported", runtime.GOOS, runtime.GOARCH) - } - } - - for _, o := range Options { - if o.Required && !*o.Feature { - t.Errorf("%v expected true, got false", o.Name) - } - } -} - func MustHaveDebugOptionsSupport(t *testing.T) { if !DebugOptions { t.Skipf("skipping test: cpu feature options not supported by OS") @@ -75,7 +57,7 @@ func TestAllCapabilitiesDisabled(t *testing.T) { } for _, o := range Options { - want := o.Required + want := false if got := *o.Feature; got != want { t.Errorf("%v: expected %v, got %v", o.Name, want, got) } -- GitLab From 0e13da8fae55d17c0c4ca64b1b8f259d633cee51 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 5 Oct 2021 14:35:24 -0700 Subject: [PATCH 1482/2500] cmd/internal/obj: allow more gcbits content addressability Follow-up to feedback on CL 352189. Change-Id: I3d9fa87878a74a5a725812c7852050c02c433fa3 Reviewed-on: https://go-review.googlesource.com/c/go/+/354137 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/internal/obj/objfile.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index 687cddc70c..98af803880 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -409,9 +409,6 @@ func contentHashSection(s *LSym) byte { if s.IsPcdata() { return 'P' } - if strings.HasPrefix(name, "runtime.gcbits.") { - return 'G' // gcbits - } if strings.HasPrefix(name, "gcargs.") || strings.HasPrefix(name, "gclocals.") || strings.HasPrefix(name, "gclocals·") || -- GitLab From 6487b1573e8359c1406a073c978c60a406055b5e Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 5 Oct 2021 15:36:25 -0700 Subject: [PATCH 1483/2500] cmd/link: remove unnecessary int conversions By making off an int64 at the beginning, the code gets a lot simpler. Cleanup only. Change-Id: I4a2519f953e2f71081a4ff3032f8fd6da06c7e24 Reviewed-on: https://go-review.googlesource.com/c/go/+/354138 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/link/internal/ld/pcln.go | 38 ++++++++++++++++---------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index 0bcf6c980a..ee26ee27a0 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -667,20 +667,20 @@ func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSym pcsp, pcfile, pcline, pcinline, pcdata = ldr.PcdataAuxs(s, pcdata) } - off := startLocations[i] + off := int64(startLocations[i]) // entry uintptr (offset of func entry PC from textStart) entryOff := ldr.SymValue(s) - textStart if entryOff < 0 { panic(fmt.Sprintf("expected func %s(%x) to be placed before or at textStart (%x)", ldr.SymName(s), ldr.SymValue(s), textStart)) } - off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(entryOff))) + off = sb.SetUint32(ctxt.Arch, off, uint32(entryOff)) // name int32 nameoff, ok := nameOffsets[s] if !ok { panic("couldn't find function name offset") } - off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(nameoff))) + off = sb.SetUint32(ctxt.Arch, off, uint32(nameoff)) // args int32 // TODO: Move into funcinfo. @@ -688,75 +688,75 @@ func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSym if fi.Valid() { args = uint32(fi.Args()) } - off = uint32(sb.SetUint32(ctxt.Arch, int64(off), args)) + off = sb.SetUint32(ctxt.Arch, off, args) // deferreturn deferreturn := computeDeferReturn(ctxt, deferReturnSym, s) - off = uint32(sb.SetUint32(ctxt.Arch, int64(off), deferreturn)) + off = sb.SetUint32(ctxt.Arch, off, deferreturn) // pcdata if fi.Valid() { - off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(ldr.SymValue(pcsp)))) - off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(ldr.SymValue(pcfile)))) - off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(ldr.SymValue(pcline)))) + off = sb.SetUint32(ctxt.Arch, off, uint32(ldr.SymValue(pcsp))) + off = sb.SetUint32(ctxt.Arch, off, uint32(ldr.SymValue(pcfile))) + off = sb.SetUint32(ctxt.Arch, off, uint32(ldr.SymValue(pcline))) } else { off += 12 } - off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(numPCData(ldr, s, fi)))) + off = sb.SetUint32(ctxt.Arch, off, uint32(numPCData(ldr, s, fi))) // Store the offset to compilation unit's file table. cuIdx := ^uint32(0) if cu := ldr.SymUnit(s); cu != nil { cuIdx = cuOffsets[cu.PclnIndex] } - off = uint32(sb.SetUint32(ctxt.Arch, int64(off), cuIdx)) + off = sb.SetUint32(ctxt.Arch, off, cuIdx) // funcID uint8 var funcID objabi.FuncID if fi.Valid() { funcID = fi.FuncID() } - off = uint32(sb.SetUint8(ctxt.Arch, int64(off), uint8(funcID))) + off = sb.SetUint8(ctxt.Arch, off, uint8(funcID)) // flag uint8 var flag objabi.FuncFlag if fi.Valid() { flag = fi.FuncFlag() } - off = uint32(sb.SetUint8(ctxt.Arch, int64(off), uint8(flag))) + off = sb.SetUint8(ctxt.Arch, off, uint8(flag)) off += 1 // pad // nfuncdata must be the final entry. funcdata = funcData(ldr, s, fi, 0, funcdata) - off = uint32(sb.SetUint8(ctxt.Arch, int64(off), uint8(len(funcdata)))) + off = sb.SetUint8(ctxt.Arch, off, uint8(len(funcdata))) // Output the pcdata. if fi.Valid() { for j, pcSym := range pcdata { - sb.SetUint32(ctxt.Arch, int64(off+uint32(j*4)), uint32(ldr.SymValue(pcSym))) + sb.SetUint32(ctxt.Arch, off+int64(j*4), uint32(ldr.SymValue(pcSym))) } if fi.NumInlTree() > 0 { - sb.SetUint32(ctxt.Arch, int64(off+objabi.PCDATA_InlTreeIndex*4), uint32(ldr.SymValue(pcinline))) + sb.SetUint32(ctxt.Arch, off+objabi.PCDATA_InlTreeIndex*4, uint32(ldr.SymValue(pcinline))) } } // Write funcdata refs as offsets from go.func.* and go.funcrel.*. funcdata = funcData(ldr, s, fi, inlSyms[s], funcdata) // Missing funcdata will be ^0. See runtime/symtab.go:funcdata. - off = uint32(startLocations[i] + funcSize + numPCData(ldr, s, fi)*4) + off = int64(startLocations[i] + funcSize + numPCData(ldr, s, fi)*4) for j := range funcdata { - dataoff := off + uint32(4*j) + dataoff := off + int64(4*j) fdsym := funcdata[j] if fdsym == 0 { - sb.SetUint32(ctxt.Arch, int64(dataoff), ^uint32(0)) // ^0 is a sentinel for "no value" + sb.SetUint32(ctxt.Arch, dataoff, ^uint32(0)) // ^0 is a sentinel for "no value" continue } if outer := ldr.OuterSym(fdsym); outer != gofunc { panic(fmt.Sprintf("bad carrier sym for symbol %s (funcdata %s#%d), want go.func.* got %s", ldr.SymName(fdsym), ldr.SymName(s), j, ldr.SymName(outer))) } - sb.SetUint32(ctxt.Arch, int64(dataoff), uint32(ldr.SymValue(fdsym)-gofuncBase)) + sb.SetUint32(ctxt.Arch, dataoff, uint32(ldr.SymValue(fdsym)-gofuncBase)) } } } -- GitLab From f05c67f18259800e4847e44c9ca34de2bf5ed198 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 5 Oct 2021 14:03:47 -0700 Subject: [PATCH 1484/2500] cmd/compile/internal/syntax, types2: remove ability to handle type lists The type set notation has been accepted a while ago. We're not going back to supporting the original type list notation. Remove support for it in the parser and type checker. Change-Id: I860651f80b89fa43a3a5a2a02cf823ec0dae583c Reviewed-on: https://go-review.googlesource.com/c/go/+/354131 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/syntax/error_test.go | 2 +- src/cmd/compile/internal/syntax/nodes.go | 4 +-- src/cmd/compile/internal/syntax/parser.go | 33 ++--------------- .../compile/internal/syntax/parser_test.go | 2 +- src/cmd/compile/internal/syntax/printer.go | 35 ++++--------------- .../compile/internal/syntax/printer_test.go | 18 +++++----- src/cmd/compile/internal/syntax/syntax.go | 3 +- .../syntax/testdata/go2/typeinst2.go2 | 34 +++--------------- .../internal/syntax/testdata/interface.go2 | 6 ---- src/cmd/compile/internal/types2/check_test.go | 2 +- src/cmd/compile/internal/types2/interface.go | 35 ------------------- .../types2/testdata/check/typeinst2.go2 | 5 +-- .../types2/testdata/examples/constraints.go2 | 12 ------- 13 files changed, 29 insertions(+), 162 deletions(-) diff --git a/src/cmd/compile/internal/syntax/error_test.go b/src/cmd/compile/internal/syntax/error_test.go index 966b36f6bc..0ab3c20ce5 100644 --- a/src/cmd/compile/internal/syntax/error_test.go +++ b/src/cmd/compile/internal/syntax/error_test.go @@ -130,7 +130,7 @@ func testSyntaxErrors(t *testing.T, filename string) { var mode Mode if strings.HasSuffix(filename, ".go2") { - mode = AllowGenerics | AllowTypeSets | AllowTypeLists + mode = AllowGenerics | AllowTypeSets } ParseFile(filename, func(err error) { e, ok := err.(Error) diff --git a/src/cmd/compile/internal/syntax/nodes.go b/src/cmd/compile/internal/syntax/nodes.go index fb9786daa3..2f9b43edef 100644 --- a/src/cmd/compile/internal/syntax/nodes.go +++ b/src/cmd/compile/internal/syntax/nodes.go @@ -275,14 +275,14 @@ type ( // Name Type // Type Field struct { - Name *Name // nil means anonymous field/parameter (structs/parameters), or embedded interface (interfaces) + Name *Name // nil means anonymous field/parameter (structs/parameters), or embedded element (interfaces) Type Expr // field names declared in a list share the same Type (identical pointers) node } // interface { MethodList[0]; MethodList[1]; ... } InterfaceType struct { - MethodList []*Field // a field named "type" means a type constraint + MethodList []*Field expr } diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index 54e77b9958..a669c54712 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -1450,30 +1450,6 @@ func (p *parser) interfaceType() *InterfaceType { return false } - case _Type: - // TODO(gri) remove TypeList syntax if we accept #45346 - if p.allowGenerics() && p.mode&AllowTypeLists != 0 { - type_ := NewName(p.pos(), "type") // cannot have a method named "type" - p.next() - if p.tok != _Semi && p.tok != _Rbrace { - f := new(Field) - f.pos = p.pos() - f.Name = type_ - f.Type = p.type_() - typ.MethodList = append(typ.MethodList, f) - for p.got(_Comma) { - f := new(Field) - f.pos = p.pos() - f.Name = type_ - f.Type = p.type_() - typ.MethodList = append(typ.MethodList, f) - } - } else { - p.syntaxError("expecting type") - } - return false - } - default: if p.allowGenerics() { pos := p.pos() @@ -1488,13 +1464,8 @@ func (p *parser) interfaceType() *InterfaceType { } if p.allowGenerics() { - if p.mode&AllowTypeLists != 0 { - p.syntaxError("expecting method, type list, or embedded element") - p.advance(_Semi, _Rbrace, _Type) - } else { - p.syntaxError("expecting method or embedded element") - p.advance(_Semi, _Rbrace) - } + p.syntaxError("expecting method or embedded element") + p.advance(_Semi, _Rbrace) return false } diff --git a/src/cmd/compile/internal/syntax/parser_test.go b/src/cmd/compile/internal/syntax/parser_test.go index fb02c8b95f..29682012e5 100644 --- a/src/cmd/compile/internal/syntax/parser_test.go +++ b/src/cmd/compile/internal/syntax/parser_test.go @@ -46,7 +46,7 @@ func TestParseGo2(t *testing.T) { for _, fi := range list { name := fi.Name() if !fi.IsDir() && !strings.HasPrefix(name, ".") { - ParseFile(filepath.Join(dir, name), func(err error) { t.Error(err) }, nil, AllowGenerics|AllowTypeSets|AllowTypeLists) + ParseFile(filepath.Join(dir, name), func(err error) { t.Error(err) }, nil, AllowGenerics|AllowTypeSets) } } } diff --git a/src/cmd/compile/internal/syntax/printer.go b/src/cmd/compile/internal/syntax/printer.go index e557f5d924..c8d31799af 100644 --- a/src/cmd/compile/internal/syntax/printer.go +++ b/src/cmd/compile/internal/syntax/printer.go @@ -494,39 +494,16 @@ func (p *printer) printRawNode(n Node) { p.printSignature(n) case *InterfaceType: - // separate type list and method list - var types []Expr - var methods []*Field - for _, f := range n.MethodList { - if f.Name != nil && f.Name.Value == "type" { - types = append(types, f.Type) - } else { - // method or embedded interface - methods = append(methods, f) - } - } - - multiLine := len(n.MethodList) > 0 && p.linebreaks p.print(_Interface) - if multiLine { + if p.linebreaks && len(n.MethodList) > 1 { p.print(blank) - } - p.print(_Lbrace) - if multiLine { + p.print(_Lbrace) p.print(newline, indent) - } - if len(types) > 0 { - p.print(_Type, blank) - p.printExprList(types) - if len(methods) > 0 { - p.print(_Semi, blank) - } - } - if len(methods) > 0 { - p.printMethodList(methods) - } - if multiLine { + p.printMethodList(n.MethodList) p.print(outdent, newline) + } else { + p.print(_Lbrace) + p.printMethodList(n.MethodList) } p.print(_Rbrace) diff --git a/src/cmd/compile/internal/syntax/printer_test.go b/src/cmd/compile/internal/syntax/printer_test.go index ee083ad159..9b5331b148 100644 --- a/src/cmd/compile/internal/syntax/printer_test.go +++ b/src/cmd/compile/internal/syntax/printer_test.go @@ -60,12 +60,12 @@ var stringTests = []string{ // generic type declarations "package p; type _[T any] struct{}", "package p; type _[A, B, C interface{m()}] struct{}", - "package p; type _[T any, A, B, C interface{m()}, X, Y, Z interface{type int}] struct{}", + "package p; type _[T any, A, B, C interface{m()}, X, Y, Z interface{~int}] struct{}", // generic function declarations "package p; func _[T any]()", "package p; func _[A, B, C interface{m()}]()", - "package p; func _[T any, A, B, C interface{m()}, X, Y, Z interface{type int}]()", + "package p; func _[T any, A, B, C interface{m()}, X, Y, Z interface{~int}]()", // methods with generic receiver types "package p; func (R[T]) _()", @@ -94,7 +94,7 @@ var stringTests = []string{ func TestPrintString(t *testing.T) { for _, want := range stringTests { - ast, err := Parse(nil, strings.NewReader(want), nil, nil, AllowGenerics|AllowTypeSets|AllowTypeLists) + ast, err := Parse(nil, strings.NewReader(want), nil, nil, AllowGenerics|AllowTypeSets) if err != nil { t.Error(err) continue @@ -140,10 +140,10 @@ var exprTests = [][2]string{ dup("func(int, float32) string"), dup("interface{m()}"), dup("interface{m() string; n(x int)}"), - dup("interface{type int}"), - dup("interface{type int, float64, string}"), - dup("interface{type int; m()}"), - dup("interface{type int, float64, string; m() string; n(x int)}"), + dup("interface{~int}"), + dup("interface{~int | ~float64 | ~string}"), + dup("interface{~int; m()}"), + dup("interface{~int | ~float64 | ~string; m() string; n(x int)}"), dup("map[string]int"), dup("chan E"), dup("<-chan E"), @@ -155,7 +155,7 @@ var exprTests = [][2]string{ dup("interface{~int}"), dup("interface{int | string}"), dup("interface{~int | ~string; float64; m()}"), - dup("interface{type a, b, c; ~int | ~string; float64; m()}"), + dup("interface{~a | ~b | ~c; ~int | ~string; float64; m()}"), dup("interface{~T[int, string] | string}"), // non-type expressions @@ -214,7 +214,7 @@ var exprTests = [][2]string{ func TestShortString(t *testing.T) { for _, test := range exprTests { src := "package p; var _ = " + test[0] - ast, err := Parse(nil, strings.NewReader(src), nil, nil, AllowGenerics|AllowTypeLists) + ast, err := Parse(nil, strings.NewReader(src), nil, nil, AllowGenerics) if err != nil { t.Errorf("%s: %s", test[0], err) continue diff --git a/src/cmd/compile/internal/syntax/syntax.go b/src/cmd/compile/internal/syntax/syntax.go index 8828c39ad5..49ba87786e 100644 --- a/src/cmd/compile/internal/syntax/syntax.go +++ b/src/cmd/compile/internal/syntax/syntax.go @@ -17,8 +17,7 @@ type Mode uint const ( CheckBranches Mode = 1 << iota // check correct use of labels, break, continue, and goto statements AllowGenerics - AllowTypeSets // requires AllowGenerics; remove once #48424 is decided - AllowTypeLists // requires AllowGenerics; remove once 1.18 is out + AllowTypeSets // requires AllowGenerics; remove once #48424 is decided ) // Error describes a syntax error. Error implements the error interface. diff --git a/src/cmd/compile/internal/syntax/testdata/go2/typeinst2.go2 b/src/cmd/compile/internal/syntax/testdata/go2/typeinst2.go2 index f3deb703b6..76b8d5591f 100644 --- a/src/cmd/compile/internal/syntax/testdata/go2/typeinst2.go2 +++ b/src/cmd/compile/internal/syntax/testdata/go2/typeinst2.go2 @@ -148,31 +148,7 @@ func _[T any](r R2[T, int], p *R2[string, T]) { p.pm() } -// An interface can (explicitly) declare at most one type list. -type _ interface { - m0() - type int, string, bool - type /* ERROR multiple type lists */ float32, float64 - m1() - m2() - type /* ERROR multiple type lists */ complex64, complex128 - type /* ERROR multiple type lists */ rune -} - -// Interface type lists may contain each type at most once. -// (If there are multiple lists, we assume the author intended -// for them to be all in a single list, and we report the error -// as well.) -type _ interface { - type int, int /* ERROR duplicate type int */ - type /* ERROR multiple type lists */ int /* ERROR duplicate type int */ -} - -type _ interface { - type struct{f int}, struct{g int}, struct /* ERROR duplicate type */ {f int} -} - -// Interface type lists can contain any type, incl. *Named types. +// Interface type constraints can contain any type, incl. *Named types. // Verify that we use the underlying type to compute the operational type. type MyInt int func add1[T interface{ ~MyInt }](x T) T { @@ -184,9 +160,9 @@ func double[T interface{ ~MyInt | ~MyString }](x T) T { return x + x } -// Embedding of interfaces with type lists leads to interfaces -// with type lists that are the intersection of the embedded -// type lists. +// Embedding of interfaces with type constraints leads to interfaces +// with type constraints that are the intersection of the embedded +// type constraints. type E0 interface { ~int | ~bool | ~string @@ -246,7 +222,7 @@ var _ = f12[float64] type I0_ interface { E0 - type int + ~int } func f0_[T I0_]() diff --git a/src/cmd/compile/internal/syntax/testdata/interface.go2 b/src/cmd/compile/internal/syntax/testdata/interface.go2 index b399d75148..dbc4187989 100644 --- a/src/cmd/compile/internal/syntax/testdata/interface.go2 +++ b/src/cmd/compile/internal/syntax/testdata/interface.go2 @@ -4,16 +4,11 @@ // This file contains test cases for interfaces containing // constraint elements. -// -// For now, we accept both ordinary type lists and the -// more complex constraint elements. package p type _ interface { m() - type int - type int, string E } @@ -31,7 +26,6 @@ type _ interface { T[int, string] | string int | ~T[string, struct{}] ~int | ~string - type bool, int, float64 } type _ interface { diff --git a/src/cmd/compile/internal/types2/check_test.go b/src/cmd/compile/internal/types2/check_test.go index 1ca2eea5c6..5b2f09425b 100644 --- a/src/cmd/compile/internal/types2/check_test.go +++ b/src/cmd/compile/internal/types2/check_test.go @@ -100,7 +100,7 @@ func testFiles(t *testing.T, filenames []string, colDelta uint, manual bool) { var mode syntax.Mode if strings.HasSuffix(filenames[0], ".go2") { - mode |= syntax.AllowGenerics | syntax.AllowTypeSets | syntax.AllowTypeLists + mode |= syntax.AllowGenerics | syntax.AllowTypeSets } // parse files and collect parser errors files, errlist := parseFiles(t, filenames, mode) diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index 431ba93c17..0879d29d3d 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -93,9 +93,6 @@ func (t *Interface) String() string { return TypeString(t, nil) } // Implementation func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType, def *Named) { - var tlist []syntax.Expr // types collected from all type lists - var tname *syntax.Name // most recent "type" name - addEmbedded := func(pos syntax.Pos, typ Type) { ityp.embeddeds = append(ityp.embeddeds, typ) if ityp.embedPos == nil { @@ -122,31 +119,6 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType continue // ignore } - // TODO(gri) Remove type list handling once the parser doesn't accept type lists anymore. - if name == "type" { - // Report an error for the first type list per interface - // if we don't allow type lists, but continue. - if !check.conf.AllowTypeLists && tlist == nil { - check.softErrorf(f.Name, "use generalized embedding syntax instead of a type list") - } - // For now, collect all type list entries as if it - // were a single union, where each union element is - // of the form ~T. - op := new(syntax.Operation) - // We should also set the position (but there is no setter); - // we don't care because this code will eventually go away. - op.Op = syntax.Tilde - op.X = f.Type - tlist = append(tlist, op) - // Report an error if we have multiple type lists in an - // interface, but only if they are permitted in the first place. - if check.conf.AllowTypeLists && tname != nil && tname != f.Name { - check.error(f.Name, "cannot have multiple type lists in an interface") - } - tname = f.Name - continue - } - typ := check.typ(f.Type) sig, _ := typ.(*Signature) if sig == nil { @@ -175,13 +147,6 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType ityp.methods = append(ityp.methods, m) } - // If we saw a type list, add it like an embedded union. - if tlist != nil { - // Types T in a type list are added as ~T expressions but we don't - // have the position of the '~'. Use the first type position instead. - addEmbedded(tlist[0].(*syntax.Operation).X.Pos(), parseUnion(check, tlist)) - } - // All methods and embedded elements for this interface are collected; // i.e., this interface may be used in a type set computation. ityp.complete = true diff --git a/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 b/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 index d087c26a47..49f48c7283 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 @@ -159,10 +159,7 @@ type _ interface { ~rune } -// Interface type lists may contain each type at most once. -// (If there are multiple lists, we assume the author intended -// for them to be all in a single list, and we report the error -// as well.) +// Type sets may contain each type at most once. type _ interface { ~int|~int /* ERROR overlapping terms ~int */ ~int|int /* ERROR overlapping terms int */ diff --git a/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 b/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 index ecc75c1a46..4d7f70313a 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/constraints.go2 @@ -6,18 +6,6 @@ package p -type ( - // Type lists are processed as unions but an error is reported. - // TODO(gri) remove this once the parser doesn't accept type lists anymore. - _ interface{ - type /* ERROR use generalized embedding syntax instead of a type list */ int - } - _ interface{ - type /* ERROR use generalized embedding syntax instead of a type list */ int - type float32 - } -) - type MyInt int type ( -- GitLab From 9062a5298bdee895dd9f4e9c07ffd3e261c0ac13 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 6 Oct 2021 09:03:34 -0700 Subject: [PATCH 1485/2500] cmd/compile/internal/types2: break cycles in invalid types This CL reverses the change in CL 284254 (which was ported to types2) which originated in CL 240901 to address a crash in a test created by a fuzzer (that crash appears to be avoided in other ways, now). This exposed another bug in typeset.go where we don't look for the underlying type when testing if a type is an interface or not. Fixed that as well. Adjusted a test case that now doesn't report an error anymore (which is good). Fixes #48819. Change-Id: I611d68e053d6b8a2f7176d0cd5a44da2df28ad21 Reviewed-on: https://go-review.googlesource.com/c/go/+/354329 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/decl.go | 1 + .../types2/testdata/fixedbugs/issue41124.go2 | 2 +- .../types2/testdata/fixedbugs/issue48819.src | 15 +++++++++++++++ src/cmd/compile/internal/types2/typeset.go | 2 +- 4 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue48819.src diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 7ae980e5c9..5fa1ca889f 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -358,6 +358,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { if tn == t.obj { check.cycleError(path[i:]) t.info = invalid + t.underlying = Typ[Invalid] return t.info } } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2 index cef24bd237..7f55ba85a6 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue41124.go2 @@ -12,7 +12,7 @@ type Nat /* ERROR cycle */ interface { type Zero struct{} type Succ struct{ - Nat // ERROR interface contains type constraints + Nat // Nat contains type constraints but is invalid, so no error } // Struct tests. diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48819.src b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48819.src new file mode 100644 index 0000000000..9262110ea0 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48819.src @@ -0,0 +1,15 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +import "unsafe" + +type T /* ERROR illegal cycle in declaration of T */ struct { + T +} + +func _(t T) { + _ = unsafe.Sizeof(t) // should not go into infinite recursion here +} diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index 37030b2ca1..8eb43a27e5 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -294,7 +294,7 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_ // Union parsing reports a (delayed) error, so we can ignore this entry. continue default: - if typ == Typ[Invalid] { + if u == Typ[Invalid] { continue } if check != nil && !check.allowVersion(check.pkg, 1, 18) { -- GitLab From 39a4df49674540ba8b835ece03edb8d304941187 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 6 Oct 2021 09:33:55 -0700 Subject: [PATCH 1486/2500] go/types: break cycles in invalid types This is a clean port of CL 354329 from types2 to go/types. For #48819. Change-Id: I9efdcdbfa6432f3cee64d924a4c67ecc6793cf86 Reviewed-on: https://go-review.googlesource.com/c/go/+/354349 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/go/types/decl.go | 1 + src/go/types/testdata/fixedbugs/issue41124.go2 | 2 +- src/go/types/testdata/fixedbugs/issue48819.src | 15 +++++++++++++++ src/go/types/typeset.go | 2 +- 4 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue48819.src diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 3c68bbfb20..22202cc7c9 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -356,6 +356,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { if tn == t.obj { check.cycleError(path[i:]) t.info = invalid + t.underlying = Typ[Invalid] return t.info } } diff --git a/src/go/types/testdata/fixedbugs/issue41124.go2 b/src/go/types/testdata/fixedbugs/issue41124.go2 index ac336a2ece..7f55ba85a6 100644 --- a/src/go/types/testdata/fixedbugs/issue41124.go2 +++ b/src/go/types/testdata/fixedbugs/issue41124.go2 @@ -12,7 +12,7 @@ type Nat /* ERROR cycle */ interface { type Zero struct{} type Succ struct{ - Nat /* ERROR interface contains type constraints */ + Nat // Nat contains type constraints but is invalid, so no error } // Struct tests. diff --git a/src/go/types/testdata/fixedbugs/issue48819.src b/src/go/types/testdata/fixedbugs/issue48819.src new file mode 100644 index 0000000000..9262110ea0 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue48819.src @@ -0,0 +1,15 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +import "unsafe" + +type T /* ERROR illegal cycle in declaration of T */ struct { + T +} + +func _(t T) { + _ = unsafe.Sizeof(t) // should not go into infinite recursion here +} diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index b447799862..a1893d0588 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -292,7 +292,7 @@ func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_T // Union parsing reports a (delayed) error, so we can ignore this entry. continue default: - if typ == Typ[Invalid] { + if u == Typ[Invalid] { continue } if check != nil && !check.allowVersion(check.pkg, 1, 18) { -- GitLab From e38ec96c69f826516a99f16952bd73c766f96719 Mon Sep 17 00:00:00 2001 From: Alexander Yastrebov Date: Sun, 3 Oct 2021 15:45:38 +0000 Subject: [PATCH 1487/2500] time: truncate fractional seconds longer than 9 digits Fixes #48685 Change-Id: Id246708878c2902b407ab759537f6b545a1f459f GitHub-Last-Rev: 4d985192c5a66ae8891539f166ef88b53cd1cbea GitHub-Pull-Request: golang/go#48750 Reviewed-on: https://go-review.googlesource.com/c/go/+/353713 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Reviewed-by: Emmanuel Odeke Trust: Emmanuel Odeke --- src/time/format.go | 9 ++++++--- src/time/format_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/time/format.go b/src/time/format.go index 7373892b97..464effdb43 100644 --- a/src/time/format.go +++ b/src/time/format.go @@ -1420,16 +1420,19 @@ func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string, err = errBad return } + if nbytes > 10 { + value = value[:10] + nbytes = 10 + } if ns, err = atoi(value[1:nbytes]); err != nil { return } - if ns < 0 || 1e9 <= ns { + if ns < 0 { rangeErrString = "fractional second" return } // We need nanoseconds, which means scaling by the number - // of missing digits in the format, maximum length 10. If it's - // longer than 10, we won't scale. + // of missing digits in the format, maximum length 10. scaleDigits := 10 - nbytes for i := 0; i < scaleDigits; i++ { ns *= 10 diff --git a/src/time/format_test.go b/src/time/format_test.go index 93cbcf9401..db95536390 100644 --- a/src/time/format_test.go +++ b/src/time/format_test.go @@ -852,3 +852,44 @@ func TestFormatFractionalSecondSeparators(t *testing.T) { } } } + +// Issue 48685 +func TestParseFractionalSecondsLongerThanNineDigits(t *testing.T) { + tests := []struct { + s string + want int + }{ + // 9 digits + {"2021-09-29T16:04:33.000000000Z", 0}, + {"2021-09-29T16:04:33.000000001Z", 1}, + {"2021-09-29T16:04:33.100000000Z", 100_000_000}, + {"2021-09-29T16:04:33.100000001Z", 100_000_001}, + {"2021-09-29T16:04:33.999999999Z", 999_999_999}, + {"2021-09-29T16:04:33.012345678Z", 12_345_678}, + // 10 digits, truncates + {"2021-09-29T16:04:33.0000000000Z", 0}, + {"2021-09-29T16:04:33.0000000001Z", 0}, + {"2021-09-29T16:04:33.1000000000Z", 100_000_000}, + {"2021-09-29T16:04:33.1000000009Z", 100_000_000}, + {"2021-09-29T16:04:33.9999999999Z", 999_999_999}, + {"2021-09-29T16:04:33.0123456789Z", 12_345_678}, + // 11 digits, truncates + {"2021-09-29T16:04:33.10000000000Z", 100_000_000}, + {"2021-09-29T16:04:33.00123456789Z", 1_234_567}, + // 12 digits, truncates + {"2021-09-29T16:04:33.000123456789Z", 123_456}, + // 15 digits, truncates + {"2021-09-29T16:04:33.9999999999999999Z", 999_999_999}, + } + + for _, tt := range tests { + tm, err := Parse(RFC3339, tt.s) + if err != nil { + t.Errorf("Unexpected error: %v", err) + continue + } + if got := tm.Nanosecond(); got != tt.want { + t.Errorf("Parse(%q) = got %d, want %d", tt.s, got, tt.want) + } + } +} -- GitLab From b5cdb1b71c2198c6c5e209e77ce3801087a21d62 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Wed, 6 Oct 2021 15:10:39 -0400 Subject: [PATCH 1488/2500] cmd/go/testdata/script: move test from test_fuzz to test_fuzz_cache Tests that require instrumentation must be in a test script which only runs for architectures where coverage is supported. Change-Id: Ia56b1cef1071f848c9dce8c87597207937fdb6c9 Reviewed-on: https://go-review.googlesource.com/c/go/+/354372 Trust: Katie Hockman Run-TryBot: Katie Hockman Reviewed-by: Bryan C. Mills --- src/cmd/go/testdata/script/test_fuzz.txt | 14 -------------- src/cmd/go/testdata/script/test_fuzz_cache.txt | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt index 0b01c2fb43..c9930aa37e 100644 --- a/src/cmd/go/testdata/script/test_fuzz.txt +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -184,20 +184,6 @@ stdout ok ! stdout ^ok stdout FAIL - -# Fuzzing indicates that one new interesting value was found with an empty -# corpus, and the total size of the cache is now 1. -go clean -fuzzcache -go test -fuzz=Fuzz -fuzztime=10000x success_fuzz_test.go -stdout 'new interesting: 1' -stdout 'total: 1' - -# Fuzzing again with a small fuzztime does not find any other interesting -# values but still indicates that the cache size is 1. -go test -fuzz=Fuzz -fuzztime=2x success_fuzz_test.go -stdout 'new interesting: 0' -stdout 'total: 1' - -- noop_fuzz_test.go -- package noop_fuzz diff --git a/src/cmd/go/testdata/script/test_fuzz_cache.txt b/src/cmd/go/testdata/script/test_fuzz_cache.txt index a3fcca887e..fc1c9a1752 100644 --- a/src/cmd/go/testdata/script/test_fuzz_cache.txt +++ b/src/cmd/go/testdata/script/test_fuzz_cache.txt @@ -32,6 +32,19 @@ go clean -fuzzcache go list -f {{.Stale}} ./empty stdout false +# Fuzzing indicates that one new interesting value was found with an empty +# corpus, and the total size of the cache is now 1. +go clean -fuzzcache +go test -fuzz=FuzzEmpty -fuzztime=10000x . +stdout 'new interesting: 1' +stdout 'total: 1' + +# Fuzzing again with a small fuzztime does not find any other interesting +# values but still indicates that the cache size is 1. +go test -fuzz=FuzzEmpty -fuzztime=2x . +stdout 'new interesting: 0' +stdout 'total: 1' + -- go.mod -- module example.com/y @@ -44,6 +57,10 @@ import ( "testing" ) +func FuzzEmpty(f *testing.F) { + f.Fuzz(func (*testing.T, []byte) {}) +} + func FuzzY(f *testing.F) { f.Add([]byte("y")) f.Fuzz(func(t *testing.T, b []byte) { Y(io.Discard, b) }) -- GitLab From 058fa255bcbe414011f5b9f469f44ec64a168224 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 5 Oct 2021 11:26:25 -0700 Subject: [PATCH 1489/2500] cmd/link,runtime: make textsectmap fields more convenient for runtime They're only used in a single place. Instead of calculating the end every time, calculate it in the linker. It'd be nice to recalculate baseaddr-vaddr, but that generates relocations that are too large. While we're here, remove some pointless uintptr -> uintptr conversions. Change-Id: I91758f9bff11b365bc3a63fee172dbdc3d90b966 Reviewed-on: https://go-review.googlesource.com/c/go/+/354089 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder Reviewed-by: Cherry Mui TryBot-Result: Go Bot --- src/cmd/link/internal/ld/symtab.go | 29 ++++++++++++++--------------- src/runtime/symtab.go | 14 ++++++-------- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index 8eca250131..4be2634f44 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -406,22 +406,21 @@ func textsectionmap(ctxt *Link) (loader.Sym, uint32) { if sect.Name != ".text" { break } - off = t.SetUint(ctxt.Arch, off, sect.Vaddr-textbase) - off = t.SetUint(ctxt.Arch, off, sect.Length) - if n == 0 { - s := ldr.Lookup("runtime.text", 0) - if s == 0 { - ctxt.Errorf(s, "Unable to find symbol runtime.text\n") - } - off = t.SetAddr(ctxt.Arch, off, s) - - } else { - s := ldr.Lookup(fmt.Sprintf("runtime.text.%d", n), 0) - if s == 0 { - ctxt.Errorf(s, "Unable to find symbol runtime.text.%d\n", n) - } - off = t.SetAddr(ctxt.Arch, off, s) + // The fields written should match runtime/symtab.go:textsect. + // They are designed to minimize runtime calculations. + vaddr := sect.Vaddr - textbase + off = t.SetUint(ctxt.Arch, off, vaddr) // field vaddr + end := vaddr + sect.Length + off = t.SetUint(ctxt.Arch, off, end) // field end + name := "runtime.text" + if n != 0 { + name = fmt.Sprintf("runtime.text.%d", n) + } + s := ldr.Lookup(name, 0) + if s == 0 { + ctxt.Errorf(s, "Unable to find symbol %s\n", name) } + off = t.SetAddr(ctxt.Arch, off, s) // field baseaddr n++ } return t.Sym(), uint32(n) diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index e26c05bc0c..37abdb6dfa 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -561,7 +561,7 @@ type functab struct { type textsect struct { vaddr uintptr // prelinked section vaddr - length uintptr // section length + end uintptr // vaddr + section length baseaddr uintptr // relocated section address } @@ -650,9 +650,9 @@ func moduledataverify1(datap *moduledata) { // To resolve the large text issue, the text is split into multiple text sections // to allow the linker to generate long calls when necessary. // When this happens, the vaddr for each text section is set to its offset within the text. -// Each function's offset is compared against the section vaddrs and sizes to determine the containing section. +// Each function's offset is compared against the section vaddrs and ends to determine the containing section. // Then the section relative offset is added to the section's -// relocated baseaddr to compute the function addess. +// relocated baseaddr to compute the function address. // // It is nosplit because it is part of the findfunc implementation. //go:nosplit @@ -660,16 +660,14 @@ func (md *moduledata) textAddr(off uintptr) uintptr { var res uintptr if len(md.textsectmap) > 1 { for i := range md.textsectmap { - sectaddr := md.textsectmap[i].vaddr - sectlen := md.textsectmap[i].length - if uintptr(off) >= sectaddr && uintptr(off) < sectaddr+sectlen { - res = md.textsectmap[i].baseaddr + uintptr(off) - uintptr(md.textsectmap[i].vaddr) + if off >= md.textsectmap[i].vaddr && off < md.textsectmap[i].end { + res = md.textsectmap[i].baseaddr + off - md.textsectmap[i].vaddr break } } } else { // single text section - res = md.text + uintptr(off) + res = md.text + off } if res > md.etext && GOARCH != "wasm" { // on wasm, functions do not live in the same address space as the linear memory println("runtime: textOff", hex(off), "out of range", hex(md.text), "-", hex(md.etext)) -- GitLab From 17c513e722e72739a59851e3a052952de36315aa Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 13 Sep 2021 15:28:55 -0700 Subject: [PATCH 1490/2500] cmd/compile: make encoding/binary loads/stores cheaper to inline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The encoding/binary little- and big-endian load and store routines are frequently used in performance sensitive code. They look fairly complex to the inliner. Though the routines themselves can be inlined, code using them typically cannot be. Yet they typically compile down to an instruction or two on architectures that support merging such loads. This change teaches the inliner to treat calls to these methods as cheap, so that code using them will be more inlineable. It'd be better to teach the inliner that this pattern of code is cheap, rather than these particular methods. However, that is difficult to do robustly when working with the IR representation. And the broader project of which that would be a part, namely to model the rest of the compiler in the inliner, is probably a non-starter. By way of contrast, imperfect though it is, this change is an easy, cheap, and useful heuristic. If/when we base inlining decisions on more accurate information obtained later in the compilation process, or on PGO/FGO, we can remove this and other such heuristics. Newly inlineable functions in the standard library: crypto/cipher.gcmInc32 crypto/sha512.appendUint64 crypto/md5.appendUint64 crypto/sha1.appendUint64 crypto/sha256.appendUint64 vendor/golang.org/x/crypto/poly1305.initialize encoding/gob.(*encoderState).encodeUint vendor/golang.org/x/text/unicode/norm.buildRecompMap net/http.(*http2SettingsFrame).Setting net/http.http2parseGoAwayFrame net/http.http2parseWindowUpdateFrame Benchmark impact for encoding/gob (the only package I measured): name old time/op new time/op delta EndToEndPipe-8 2.25µs ± 1% 2.21µs ± 3% -1.79% (p=0.000 n=28+27) EndToEndByteBuffer-8 93.3ns ± 5% 94.2ns ± 5% ~ (p=0.174 n=30+30) EndToEndSliceByteBuffer-8 10.5µs ± 1% 10.6µs ± 1% +0.87% (p=0.000 n=30+30) EncodeComplex128Slice-8 1.81µs ± 0% 1.75µs ± 1% -3.23% (p=0.000 n=28+30) EncodeFloat64Slice-8 900ns ± 1% 847ns ± 0% -5.91% (p=0.000 n=29+28) EncodeInt32Slice-8 1.02µs ± 0% 0.90µs ± 0% -11.82% (p=0.000 n=28+26) EncodeStringSlice-8 1.16µs ± 1% 1.04µs ± 1% -10.20% (p=0.000 n=29+26) EncodeInterfaceSlice-8 28.7µs ± 3% 29.2µs ± 6% ~ (p=0.067 n=29+30) DecodeComplex128Slice-8 7.98µs ± 1% 7.96µs ± 1% -0.27% (p=0.017 n=30+30) DecodeFloat64Slice-8 4.33µs ± 1% 4.34µs ± 1% +0.24% (p=0.022 n=30+29) DecodeInt32Slice-8 4.18µs ± 1% 4.18µs ± 0% ~ (p=0.074 n=30+28) DecodeStringSlice-8 13.2µs ± 1% 13.1µs ± 1% -0.64% (p=0.000 n=28+28) DecodeStringsSlice-8 31.9µs ± 1% 31.8µs ± 1% -0.34% (p=0.001 n=30+30) DecodeBytesSlice-8 8.88µs ± 1% 8.84µs ± 1% -0.48% (p=0.000 n=30+30) DecodeInterfaceSlice-8 64.1µs ± 1% 64.2µs ± 1% ~ (p=0.173 n=30+28) DecodeMap-8 74.3µs ± 0% 74.2µs ± 0% ~ (p=0.131 n=29+30) Fixes #42958 Change-Id: Ie048b8976fb403d8bcc72ac6bde4b33e133e2a47 Reviewed-on: https://go-review.googlesource.com/c/go/+/349931 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/inline/inl.go | 33 +++- src/cmd/compile/internal/walk/compare.go | 21 +-- src/cmd/internal/sys/arch.go | 215 ++++++++++++----------- test/inline_endian.go | 22 +++ 4 files changed, 166 insertions(+), 125 deletions(-) create mode 100644 test/inline_endian.go diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index 04d751869b..51270a3315 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -275,14 +275,31 @@ func (v *hairyVisitor) doNode(n ir.Node) bool { } if n.X.Op() == ir.OMETHEXPR { if meth := ir.MethodExprName(n.X); meth != nil { - fn := meth.Func - if fn != nil && types.IsRuntimePkg(fn.Sym().Pkg) && fn.Sym().Name == "heapBits.nextArena" { - // Special case: explicitly allow - // mid-stack inlining of - // runtime.heapBits.next even though - // it calls slow-path - // runtime.heapBits.nextArena. - break + if fn := meth.Func; fn != nil { + s := fn.Sym() + var cheap bool + if types.IsRuntimePkg(s.Pkg) && s.Name == "heapBits.nextArena" { + // Special case: explicitly allow mid-stack inlining of + // runtime.heapBits.next even though it calls slow-path + // runtime.heapBits.nextArena. + cheap = true + } + // Special case: on architectures that can do unaligned loads, + // explicitly mark encoding/binary methods as cheap, + // because in practice they are, even though our inlining + // budgeting system does not see that. See issue 42958. + if base.Ctxt.Arch.CanMergeLoads && s.Pkg.Path == "encoding/binary" { + switch s.Name { + case "littleEndian.Uint64", "littleEndian.Uint32", "littleEndian.Uint16", + "bigEndian.Uint64", "bigEndian.Uint32", "bigEndian.Uint16", + "littleEndian.PutUint64", "littleEndian.PutUint32", "littleEndian.PutUint16", + "bigEndian.PutUint64", "bigEndian.PutUint32", "bigEndian.PutUint16": + cheap = true + } + } + if cheap { + break // treat like any other node, that is, cost of 1 + } } } } diff --git a/src/cmd/compile/internal/walk/compare.go b/src/cmd/compile/internal/walk/compare.go index daebc47965..625e216050 100644 --- a/src/cmd/compile/internal/walk/compare.go +++ b/src/cmd/compile/internal/walk/compare.go @@ -5,7 +5,6 @@ package walk import ( - "encoding/binary" "go/constant" "cmd/compile/internal/base" @@ -14,7 +13,6 @@ import ( "cmd/compile/internal/ssagen" "cmd/compile/internal/typecheck" "cmd/compile/internal/types" - "cmd/internal/sys" ) // The result of walkCompare MUST be assigned back to n, e.g. @@ -81,7 +79,7 @@ func walkCompare(n *ir.BinaryExpr, init *ir.Nodes) ir.Node { var inline bool maxcmpsize := int64(4) - unalignedLoad := canMergeLoads() + unalignedLoad := ssagen.Arch.LinkArch.CanMergeLoads if unalignedLoad { // Keep this low enough to generate less code than a function call. maxcmpsize = 2 * int64(ssagen.Arch.LinkArch.RegSize) @@ -311,7 +309,7 @@ func walkCompareString(n *ir.BinaryExpr, init *ir.Nodes) ir.Node { maxRewriteLen := 6 // Some architectures can load unaligned byte sequence as 1 word. // So we can cover longer strings with the same amount of code. - canCombineLoads := canMergeLoads() + canCombineLoads := ssagen.Arch.LinkArch.CanMergeLoads combine64bit := false if canCombineLoads { // Keep this low enough to generate less code than a function call. @@ -491,18 +489,3 @@ func tracecmpArg(n ir.Node, t *types.Type, init *ir.Nodes) ir.Node { return typecheck.Conv(n, t) } - -// canMergeLoads reports whether the backend optimization passes for -// the current architecture can combine adjacent loads into a single -// larger, possibly unaligned, load. Note that currently the -// optimizations must be able to handle little endian byte order. -func canMergeLoads() bool { - switch ssagen.Arch.LinkArch.Family { - case sys.ARM64, sys.AMD64, sys.I386, sys.S390X: - return true - case sys.PPC64: - // Load combining only supported on ppc64le. - return ssagen.Arch.LinkArch.ByteOrder == binary.LittleEndian - } - return false -} diff --git a/src/cmd/internal/sys/arch.go b/src/cmd/internal/sys/arch.go index 4b2b4c38a0..ea76b596c1 100644 --- a/src/cmd/internal/sys/arch.go +++ b/src/cmd/internal/sys/arch.go @@ -47,6 +47,11 @@ type Arch struct { // Loads or stores smaller than Alignment must be naturally aligned. // Loads or stores larger than Alignment need only be Alignment-aligned. Alignment int8 + + // CanMergeLoads reports whether the backend optimization passes + // can combine adjacent loads into a single larger, possibly unaligned, load. + // Note that currently the optimizations must be able to handle little endian byte order. + CanMergeLoads bool } // InFamily reports whether a is a member of any of the specified @@ -61,143 +66,157 @@ func (a *Arch) InFamily(xs ...ArchFamily) bool { } var Arch386 = &Arch{ - Name: "386", - Family: I386, - ByteOrder: binary.LittleEndian, - PtrSize: 4, - RegSize: 4, - MinLC: 1, - Alignment: 1, + Name: "386", + Family: I386, + ByteOrder: binary.LittleEndian, + PtrSize: 4, + RegSize: 4, + MinLC: 1, + Alignment: 1, + CanMergeLoads: true, } var ArchAMD64 = &Arch{ - Name: "amd64", - Family: AMD64, - ByteOrder: binary.LittleEndian, - PtrSize: 8, - RegSize: 8, - MinLC: 1, - Alignment: 1, + Name: "amd64", + Family: AMD64, + ByteOrder: binary.LittleEndian, + PtrSize: 8, + RegSize: 8, + MinLC: 1, + Alignment: 1, + CanMergeLoads: true, } var ArchARM = &Arch{ - Name: "arm", - Family: ARM, - ByteOrder: binary.LittleEndian, - PtrSize: 4, - RegSize: 4, - MinLC: 4, - Alignment: 4, // TODO: just for arm5? + Name: "arm", + Family: ARM, + ByteOrder: binary.LittleEndian, + PtrSize: 4, + RegSize: 4, + MinLC: 4, + Alignment: 4, // TODO: just for arm5? + CanMergeLoads: false, } var ArchARM64 = &Arch{ - Name: "arm64", - Family: ARM64, - ByteOrder: binary.LittleEndian, - PtrSize: 8, - RegSize: 8, - MinLC: 4, - Alignment: 1, + Name: "arm64", + Family: ARM64, + ByteOrder: binary.LittleEndian, + PtrSize: 8, + RegSize: 8, + MinLC: 4, + Alignment: 1, + CanMergeLoads: true, } var ArchLoong64 = &Arch{ - Name: "loong64", - Family: Loong64, - ByteOrder: binary.LittleEndian, - PtrSize: 8, - RegSize: 8, - MinLC: 4, - Alignment: 8, // Unaligned accesses are not guaranteed to be fast + Name: "loong64", + Family: Loong64, + ByteOrder: binary.LittleEndian, + PtrSize: 8, + RegSize: 8, + MinLC: 4, + Alignment: 8, // Unaligned accesses are not guaranteed to be fast + CanMergeLoads: false, } var ArchMIPS = &Arch{ - Name: "mips", - Family: MIPS, - ByteOrder: binary.BigEndian, - PtrSize: 4, - RegSize: 4, - MinLC: 4, - Alignment: 4, + Name: "mips", + Family: MIPS, + ByteOrder: binary.BigEndian, + PtrSize: 4, + RegSize: 4, + MinLC: 4, + Alignment: 4, + CanMergeLoads: false, } var ArchMIPSLE = &Arch{ - Name: "mipsle", - Family: MIPS, - ByteOrder: binary.LittleEndian, - PtrSize: 4, - RegSize: 4, - MinLC: 4, - Alignment: 4, + Name: "mipsle", + Family: MIPS, + ByteOrder: binary.LittleEndian, + PtrSize: 4, + RegSize: 4, + MinLC: 4, + Alignment: 4, + CanMergeLoads: false, } var ArchMIPS64 = &Arch{ - Name: "mips64", - Family: MIPS64, - ByteOrder: binary.BigEndian, - PtrSize: 8, - RegSize: 8, - MinLC: 4, - Alignment: 8, + Name: "mips64", + Family: MIPS64, + ByteOrder: binary.BigEndian, + PtrSize: 8, + RegSize: 8, + MinLC: 4, + Alignment: 8, + CanMergeLoads: false, } var ArchMIPS64LE = &Arch{ - Name: "mips64le", - Family: MIPS64, - ByteOrder: binary.LittleEndian, - PtrSize: 8, - RegSize: 8, - MinLC: 4, - Alignment: 8, + Name: "mips64le", + Family: MIPS64, + ByteOrder: binary.LittleEndian, + PtrSize: 8, + RegSize: 8, + MinLC: 4, + Alignment: 8, + CanMergeLoads: false, } var ArchPPC64 = &Arch{ - Name: "ppc64", - Family: PPC64, - ByteOrder: binary.BigEndian, - PtrSize: 8, - RegSize: 8, - MinLC: 4, - Alignment: 1, + Name: "ppc64", + Family: PPC64, + ByteOrder: binary.BigEndian, + PtrSize: 8, + RegSize: 8, + MinLC: 4, + Alignment: 1, + CanMergeLoads: false, } var ArchPPC64LE = &Arch{ - Name: "ppc64le", - Family: PPC64, - ByteOrder: binary.LittleEndian, - PtrSize: 8, - RegSize: 8, - MinLC: 4, - Alignment: 1, + Name: "ppc64le", + Family: PPC64, + ByteOrder: binary.LittleEndian, + PtrSize: 8, + RegSize: 8, + MinLC: 4, + Alignment: 1, + CanMergeLoads: true, } var ArchRISCV64 = &Arch{ - Name: "riscv64", - Family: RISCV64, - ByteOrder: binary.LittleEndian, - PtrSize: 8, - RegSize: 8, - MinLC: 4, - Alignment: 8, // riscv unaligned loads work, but are really slow (trap + simulated by OS) + Name: "riscv64", + Family: RISCV64, + ByteOrder: binary.LittleEndian, + PtrSize: 8, + RegSize: 8, + MinLC: 4, + Alignment: 8, // riscv unaligned loads work, but are really slow (trap + simulated by OS) + CanMergeLoads: false, } var ArchS390X = &Arch{ - Name: "s390x", - Family: S390X, - ByteOrder: binary.BigEndian, - PtrSize: 8, - RegSize: 8, - MinLC: 2, - Alignment: 1, + Name: "s390x", + Family: S390X, + ByteOrder: binary.BigEndian, + PtrSize: 8, + RegSize: 8, + MinLC: 2, + Alignment: 1, + CanMergeLoads: true, } var ArchWasm = &Arch{ - Name: "wasm", - Family: Wasm, - ByteOrder: binary.LittleEndian, - PtrSize: 8, - RegSize: 8, - MinLC: 1, - Alignment: 1, + Name: "wasm", + Family: Wasm, + ByteOrder: binary.LittleEndian, + PtrSize: 8, + RegSize: 8, + MinLC: 1, + Alignment: 1, + CanMergeLoads: false, } var Archs = [...]*Arch{ diff --git a/test/inline_endian.go b/test/inline_endian.go new file mode 100644 index 0000000000..baca133452 --- /dev/null +++ b/test/inline_endian.go @@ -0,0 +1,22 @@ +// errorcheckwithauto -0 -m -d=inlfuncswithclosures=1 + +//go:build 386 || amd64 || arm64 || ppc64le || s390x +// +build 386 amd64 arm64 ppc64le s390x + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Similar to inline.go, but only for architectures that can merge loads. + +package foo + +import ( + "encoding/binary" +) + +// Ensure that simple encoding/binary functions are cheap enough +// that functions using them can also be inlined (issue 42958). +func endian(b []byte) uint64 { // ERROR "can inline endian" "b does not escape" + return binary.LittleEndian.Uint64(b) + binary.BigEndian.Uint64(b) // ERROR "inlining call to binary.littleEndian.Uint64" "inlining call to binary.bigEndian.Uint64" +} -- GitLab From f580b7511491c866a102f3f8be912be8f824b830 Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Wed, 6 Oct 2021 12:16:47 -0700 Subject: [PATCH 1491/2500] all: update go.mod for golang.org/x/net Somehow CL 353390 managed to update the vendored code to d2e5035098b3, but not the go.mod and other version references. Fix. Change-Id: Ic265c10f7bd7ec982671b46c5d9ae50636a13309 Reviewed-on: https://go-review.googlesource.com/c/go/+/354391 Trust: Damien Neil Run-TryBot: Damien Neil TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go.mod | 2 +- src/go.sum | 10 ++-------- src/vendor/modules.txt | 2 +- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/go.mod b/src/go.mod index 3464adfeee..35231cf911 100644 --- a/src/go.mod +++ b/src/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 - golang.org/x/net v0.0.0-20211004220534-69340ce214a7 + golang.org/x/net v0.0.0-20211005215030-d2e5035098b3 ) require ( diff --git a/src/go.sum b/src/go.sum index 18cdc2854a..621d61384a 100644 --- a/src/go.sum +++ b/src/go.sum @@ -1,13 +1,7 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/net v0.0.0-20210825183410-e898025ed96a h1:bRuuGXV8wwSdGTB+CtJf+FjgO1APK1CoO39T4BN/XBw= -golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211004164453-cedda3a722dd h1:Q6PfiuMddtCdycHT4hrZ7ZhVpAdQlA7qJp+ZhUw7Rdo= -golang.org/x/net v0.0.0-20211004164453-cedda3a722dd/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211004195052-b30845b58a23 h1:j34uvNZ757YpJXjsTk19wPCR/3tAhHPT4EMFysLc9Xg= -golang.org/x/net v0.0.0-20211004195052-b30845b58a23/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211004220534-69340ce214a7 h1:mAWBL9V7JYRSixWOKNpbAMF16bdRk4x94pU+I+WPGW4= -golang.org/x/net v0.0.0-20211004220534-69340ce214a7/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211005215030-d2e5035098b3 h1:G64nFNerDErBd2KdvHvIn3Ee6ccUQBTfhDZEO0DccfU= +golang.org/x/net v0.0.0-20211005215030-d2e5035098b3/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e h1:XMgFehsDnnLGtjvjOfqWSUzt0alpTR1RSEuznObga2c= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index 250c87a663..683040db9b 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -9,7 +9,7 @@ golang.org/x/crypto/curve25519/internal/field golang.org/x/crypto/hkdf golang.org/x/crypto/internal/subtle golang.org/x/crypto/poly1305 -# golang.org/x/net v0.0.0-20211004220534-69340ce214a7 +# golang.org/x/net v0.0.0-20211005215030-d2e5035098b3 ## explicit; go 1.17 golang.org/x/net/dns/dnsmessage golang.org/x/net/http/httpguts -- GitLab From 8238f82bf1ddadd906585e3f11600968d95ce98c Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 5 Oct 2021 13:44:51 -0700 Subject: [PATCH 1492/2500] runtime: streamline moduledata.textAddr Accept a uint32 instead of a uintptr to make call sites simpler. Do less work in the common case in which len(textsectmap) == 1. Change-Id: Idd6cdc3fdad7a9356864c83790463b5d3000171b Reviewed-on: https://go-review.googlesource.com/c/go/+/354132 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/plugin.go | 2 +- src/runtime/symtab.go | 28 +++++++++++++--------------- src/runtime/type.go | 2 +- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/runtime/plugin.go b/src/runtime/plugin.go index ab3d802389..f37854f915 100644 --- a/src/runtime/plugin.go +++ b/src/runtime/plugin.go @@ -96,7 +96,7 @@ func plugin_lastmoduleinit() (path string, syms map[string]interface{}, errstr s func pluginftabverify(md *moduledata) { badtable := false for i := 0; i < len(md.ftab); i++ { - entry := md.textAddr(uintptr(md.ftab[i].entryoff)) + entry := md.textAddr(md.ftab[i].entryoff) if md.minpc <= entry && entry <= md.maxpc { continue } diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 37abdb6dfa..7641c491f1 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -622,10 +622,10 @@ func moduledataverify1(datap *moduledata) { } } - min := datap.textAddr(uintptr(datap.ftab[0].entryoff)) + min := datap.textAddr(datap.ftab[0].entryoff) // The max PC is outside of the text section. // Subtract 1 to get a PC inside the text section, look it up, then add 1 back in. - max := datap.textAddr(uintptr(datap.ftab[nftab].entryoff-1)) + 1 + max := datap.textAddr(datap.ftab[nftab].entryoff-1) + 1 if datap.minpc != min || datap.maxpc != max { println("minpc=", hex(datap.minpc), "min=", hex(min), "maxpc=", hex(datap.maxpc), "max=", hex(max)) throw("minpc or maxpc invalid") @@ -656,8 +656,9 @@ func moduledataverify1(datap *moduledata) { // // It is nosplit because it is part of the findfunc implementation. //go:nosplit -func (md *moduledata) textAddr(off uintptr) uintptr { - var res uintptr +func (md *moduledata) textAddr(off32 uint32) uintptr { + off := uintptr(off32) + res := md.text + off if len(md.textsectmap) > 1 { for i := range md.textsectmap { if off >= md.textsectmap[i].vaddr && off < md.textsectmap[i].end { @@ -665,13 +666,10 @@ func (md *moduledata) textAddr(off uintptr) uintptr { break } } - } else { - // single text section - res = md.text + off - } - if res > md.etext && GOARCH != "wasm" { // on wasm, functions do not live in the same address space as the linear memory - println("runtime: textOff", hex(off), "out of range", hex(md.text), "-", hex(md.etext)) - throw("runtime: text offset out of range") + if res > md.etext && GOARCH != "wasm" { // on wasm, functions do not live in the same address space as the linear memory + println("runtime: textAddr", hex(res), "out of range", hex(md.text), "-", hex(md.etext)) + throw("runtime: text offset out of range") + } } return res } @@ -783,7 +781,7 @@ func (f *_func) isInlined() bool { // entry returns the entry PC for f. func (f funcInfo) entry() uintptr { - return f.datap.textAddr(uintptr(f.entryoff)) + return f.datap.textAddr(f.entryoff) } // findfunc looks up function metadata for a PC. @@ -819,10 +817,10 @@ func findfunc(pc uintptr) funcInfo { if idx >= uint32(len(datap.ftab)) { idx = uint32(len(datap.ftab) - 1) } - if pc < datap.textAddr(uintptr(datap.ftab[idx].entryoff)) { + if pc < datap.textAddr(datap.ftab[idx].entryoff) { // The idx might reference a function address that // is higher than the pcOff being searched, so search backward until the matching address is found. - for datap.textAddr(uintptr(datap.ftab[idx].entryoff)) > pc && idx > 0 { + for datap.textAddr(datap.ftab[idx].entryoff) > pc && idx > 0 { idx-- } if idx == 0 { @@ -830,7 +828,7 @@ func findfunc(pc uintptr) funcInfo { } } else { // linear search to find func with pc >= entry. - for datap.textAddr(uintptr(datap.ftab[idx+1].entryoff)) <= pc { + for datap.textAddr(datap.ftab[idx+1].entryoff) <= pc { idx++ } } diff --git a/src/runtime/type.go b/src/runtime/type.go index e609acbc1e..da47147897 100644 --- a/src/runtime/type.go +++ b/src/runtime/type.go @@ -288,7 +288,7 @@ func (t *_type) textOff(off textOff) unsafe.Pointer { } return res } - res := md.textAddr(uintptr(off)) + res := md.textAddr(uint32(off)) return unsafe.Pointer(res) } -- GitLab From 4a37a1d49fd472665b59b581fe6563a9e578fd71 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Wed, 6 Oct 2021 12:24:59 -0700 Subject: [PATCH 1493/2500] cmd/compile: add runtime.funcspdelta to intended inlining test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up to CL 354133. Suggested-by: Daniel Martí Change-Id: I0d0895dfa8c2deae0dbda6e683fbe41469849145 Reviewed-on: https://go-review.googlesource.com/c/go/+/354392 Trust: Josh Bleecher Snyder Trust: Daniel Martí Run-TryBot: Josh Bleecher Snyder Reviewed-by: Daniel Martí --- src/cmd/compile/internal/test/inl_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cmd/compile/internal/test/inl_test.go b/src/cmd/compile/internal/test/inl_test.go index 5fa6411ae4..b10d37a17c 100644 --- a/src/cmd/compile/internal/test/inl_test.go +++ b/src/cmd/compile/internal/test/inl_test.go @@ -46,6 +46,7 @@ func TestIntendedInlining(t *testing.T) { "fastlog2", "fastrand", "float64bits", + "funcspdelta", "getArgInfoFast", "getm", "getMCache", -- GitLab From 197b32817b8619d18cd648a7ab487e933c7150df Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 3 Aug 2021 15:49:01 -0700 Subject: [PATCH 1494/2500] go/build: ignore package main files in TestDependencies The tree has package main files scattered around in it for the purposes of running go generate. They're all marked "// +build ignore", which gets special handling in TestDependencies. It would be nice to be able to use other build tags, such as "generate", as suggested by the go generate design doc. Plus the build tag syntax is changing. This change skips all "package main" files. By definition these aren't importable, so they can't contribute to the dependency tree. We can't quite eliminate the "// +build ignore" check, as it is used by packages runtime and syscall. But it's still a step in the right direction. Change-Id: Ib9449acfdba75f570b87a4200afe944910d76222 Reviewed-on: https://go-review.googlesource.com/c/go/+/339592 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder Reviewed-by: Ian Lance Taylor --- src/go/build/deps_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 3c3819f3b3..07fbc8b023 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -657,6 +657,9 @@ func findImports(pkg string) ([]string, error) { if err != nil { return nil, fmt.Errorf("reading %v: %v", name, err) } + if info.parsed.Name.Name == "main" { + continue + } if bytes.Contains(info.header, buildIgnore) { continue } -- GitLab From 2e107b43c7afd166c7ff98b254485bce102d4b46 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Wed, 6 Oct 2021 13:16:02 -0700 Subject: [PATCH 1495/2500] cmd/compile: simplify code in walkPrint Use typecheck.Conv; it does the same thing. Change-Id: I6bf27b8e929f8016ffc8350931c8320e36584a3d Reviewed-on: https://go-review.googlesource.com/c/go/+/354350 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder Reviewed-by: Matthew Dempsky TryBot-Result: Go Bot --- src/cmd/compile/internal/walk/builtin.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/walk/builtin.go b/src/cmd/compile/internal/walk/builtin.go index 3c9ef636f8..d0aaee03d5 100644 --- a/src/cmd/compile/internal/walk/builtin.go +++ b/src/cmd/compile/internal/walk/builtin.go @@ -622,10 +622,7 @@ func walkPrint(nn *ir.CallExpr, init *ir.Nodes) ir.Node { r := ir.NewCallExpr(base.Pos, ir.OCALL, on, nil) if params := on.Type().Params().FieldSlice(); len(params) > 0 { t := params[0].Type - if !types.Identical(t, n.Type()) { - n = ir.NewConvExpr(base.Pos, ir.OCONV, nil, n) - n.SetType(t) - } + n = typecheck.Conv(n, t) r.Args.Append(n) } calls = append(calls, r) -- GitLab From 4002616f9a34410797e7bbff142c374a1de3ac6b Mon Sep 17 00:00:00 2001 From: Carlo Alberto Ferraris Date: Fri, 4 Jun 2021 20:58:55 +0900 Subject: [PATCH 1496/2500] strings,bytes: avoid allocations in Trim/TrimLeft/TrimRight MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is evidence that the vast majority of uses for Trim* involve cutsets with a single ASCII character, and the vast majority of remaining uses involve cutsets with a small (<4) ASCII characters. For this reason it makes sense to provide better fast paths for these common cases. Furthermore the current implementation needlessly allocates for unclear benefits. This CL also replaces all paths to avoid allocations and, as a side effect, it speeds up also the slow path. strings: name old time/op new time/op delta Trim 1.71µs ± 1% 0.70µs ± 0% -58.93% (p=0.008 n=5+5) TrimASCII/1:1 6.43ns ± 0% 6.34ns ± 0% -1.41% (p=0.008 n=5+5) TrimASCII/1:2 97.3ns ± 0% 18.2ns ± 1% -81.34% (p=0.008 n=5+5) TrimASCII/1:4 101ns ± 0% 21ns ± 0% -78.77% (p=0.008 n=5+5) TrimASCII/1:8 109ns ± 0% 29ns ± 0% -73.60% (p=0.008 n=5+5) TrimASCII/1:16 124ns ± 0% 43ns ± 0% -65.16% (p=0.008 n=5+5) TrimASCII/16:1 19.8ns ± 0% 18.6ns ± 0% -5.90% (p=0.008 n=5+5) TrimASCII/16:2 167ns ± 0% 33ns ± 0% -80.21% (p=0.008 n=5+5) TrimASCII/16:4 169ns ± 0% 35ns ± 0% -79.01% (p=0.008 n=5+5) TrimASCII/16:8 177ns ± 0% 43ns ± 0% -75.88% (p=0.008 n=5+5) TrimASCII/16:16 193ns ± 2% 57ns ± 1% -70.30% (p=0.008 n=5+5) TrimASCII/256:1 232ns ± 0% 232ns ± 0% ~ (p=1.000 n=5+5) TrimASCII/256:2 1.28µs ± 1% 0.26µs ± 0% -79.46% (p=0.008 n=5+5) TrimASCII/256:4 1.27µs ± 0% 0.27µs ± 0% -78.95% (p=0.008 n=5+5) TrimASCII/256:8 1.28µs ± 0% 0.28µs ± 1% -78.28% (p=0.008 n=5+5) TrimASCII/256:16 1.30µs ± 1% 0.29µs ± 0% -77.49% (p=0.008 n=5+5) TrimASCII/4096:1 3.47µs ± 0% 3.47µs ± 0% -0.14% (p=0.008 n=5+5) TrimASCII/4096:2 18.2µs ± 0% 3.9µs ± 0% -78.53% (p=0.008 n=5+5) TrimASCII/4096:4 18.2µs ± 0% 3.9µs ± 0% -78.55% (p=0.008 n=5+5) TrimASCII/4096:8 18.2µs ± 0% 3.9µs ± 0% -78.49% (p=0.008 n=5+5) TrimASCII/4096:16 18.3µs ± 0% 3.9µs ± 0% -78.44% (p=0.008 n=5+5) TrimByte 10.6ns ± 1% 10.1ns ± 0% -5.01% (p=0.008 n=5+5) TrimSpace/NoTrim 5.90ns ± 0% 5.89ns ± 0% ~ (p=0.135 n=5+5) TrimSpace/ASCII 10.6ns ± 0% 9.9ns ± 0% -6.21% (p=0.008 n=5+5) TrimSpace/SomeNonASCII 127ns ± 0% 126ns ± 0% -0.96% (p=0.008 n=5+5) TrimSpace/JustNonASCII 178ns ± 0% 178ns ± 0% ~ (p=0.825 n=5+4) name old alloc/op new alloc/op delta Trim 456B ± 0% 0B -100.00% (p=0.008 n=5+5) TrimASCII/1:1 0.00B 0.00B ~ (all equal) TrimASCII/1:2 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/1:4 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/1:8 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/1:16 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/16:1 0.00B 0.00B ~ (all equal) TrimASCII/16:2 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/16:4 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/16:8 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/16:16 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/256:1 0.00B 0.00B ~ (all equal) TrimASCII/256:2 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/256:4 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/256:8 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/256:16 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/4096:1 0.00B 0.00B ~ (all equal) TrimASCII/4096:2 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/4096:4 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/4096:8 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/4096:16 48.0B ± 0% 0.0B ~ (p=0.079 n=4+5) TrimByte 0.00B 0.00B ~ (all equal) TrimSpace/NoTrim 0.00B 0.00B ~ (all equal) TrimSpace/ASCII 0.00B 0.00B ~ (all equal) TrimSpace/SomeNonASCII 0.00B 0.00B ~ (all equal) TrimSpace/JustNonASCII 0.00B 0.00B ~ (all equal) name old allocs/op new allocs/op delta Trim 18.0 ± 0% 0.0 -100.00% (p=0.008 n=5+5) TrimASCII/1:1 0.00 0.00 ~ (all equal) TrimASCII/1:2 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/1:4 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/1:8 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/1:16 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/16:1 0.00 0.00 ~ (all equal) TrimASCII/16:2 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/16:4 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/16:8 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/16:16 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/256:1 0.00 0.00 ~ (all equal) TrimASCII/256:2 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/256:4 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/256:8 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/256:16 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/4096:1 0.00 0.00 ~ (all equal) TrimASCII/4096:2 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/4096:4 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/4096:8 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/4096:16 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimByte 0.00 0.00 ~ (all equal) TrimSpace/NoTrim 0.00 0.00 ~ (all equal) TrimSpace/ASCII 0.00 0.00 ~ (all equal) TrimSpace/SomeNonASCII 0.00 0.00 ~ (all equal) TrimSpace/JustNonASCII 0.00 0.00 ~ (all equal) bytes: name old time/op new time/op delta TrimSpace/NoTrim 5.89ns ± 0% 5.91ns ± 0% ~ (p=0.095 n=5+4) TrimSpace/ASCII 10.3ns ± 1% 10.2ns ± 0% ~ (p=0.095 n=5+5) TrimSpace/SomeNonASCII 120ns ± 1% 121ns ± 0% +1.13% (p=0.008 n=5+5) TrimSpace/JustNonASCII 194ns ± 1% 195ns ± 0% ~ (p=0.143 n=5+5) TrimASCII/1:1 6.28ns ± 0% 5.95ns ± 0% -5.26% (p=0.008 n=5+5) TrimASCII/1:2 95.8ns ± 1% 18.6ns ± 0% -80.63% (p=0.008 n=5+5) TrimASCII/1:4 98.8ns ± 0% 22.1ns ± 0% -77.62% (p=0.008 n=5+5) TrimASCII/1:8 107ns ± 0% 29ns ± 0% -72.72% (p=0.008 n=5+5) TrimASCII/1:16 123ns ± 0% 44ns ± 1% -64.30% (p=0.008 n=5+5) TrimASCII/16:1 13.2ns ± 0% 12.8ns ± 1% -2.75% (p=0.008 n=5+5) TrimASCII/16:2 169ns ± 0% 33ns ± 0% -80.33% (p=0.008 n=5+5) TrimASCII/16:4 173ns ± 0% 36ns ± 0% -79.31% (p=0.008 n=5+5) TrimASCII/16:8 180ns ± 0% 43ns ± 0% -76.02% (p=0.008 n=5+5) TrimASCII/16:16 197ns ± 2% 58ns ± 0% -70.73% (p=0.008 n=5+5) TrimASCII/256:1 137ns ± 1% 136ns ± 0% -0.82% (p=0.016 n=5+5) TrimASCII/256:2 1.40µs ± 0% 0.26µs ± 0% -81.02% (p=0.008 n=5+5) TrimASCII/256:4 1.40µs ± 0% 0.27µs ± 0% -80.83% (p=0.008 n=5+5) TrimASCII/256:8 1.41µs ± 0% 0.28µs ± 0% -80.36% (p=0.008 n=5+5) TrimASCII/256:16 1.42µs ± 0% 0.29µs ± 0% -79.48% (p=0.008 n=5+5) TrimASCII/4096:1 1.75µs ± 0% 1.75µs ± 0% ~ (p=0.595 n=5+5) TrimASCII/4096:2 20.9µs ± 0% 3.9µs ± 0% -81.29% (p=0.008 n=5+5) TrimASCII/4096:4 20.9µs ± 0% 3.9µs ± 0% -81.27% (p=0.008 n=5+5) TrimASCII/4096:8 20.9µs ± 0% 3.9µs ± 0% -81.22% (p=0.008 n=5+5) TrimASCII/4096:16 20.9µs ± 0% 3.9µs ± 0% -81.21% (p=0.008 n=5+5) TrimByte 9.21ns ± 0% 9.30ns ± 0% +0.91% (p=0.008 n=5+5) name old alloc/op new alloc/op delta TrimSpace/NoTrim 0.00B 0.00B ~ (all equal) TrimSpace/ASCII 0.00B 0.00B ~ (all equal) TrimSpace/SomeNonASCII 0.00B 0.00B ~ (all equal) TrimSpace/JustNonASCII 0.00B 0.00B ~ (all equal) TrimASCII/1:1 0.00B 0.00B ~ (all equal) TrimASCII/1:2 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/1:4 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/1:8 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/1:16 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/16:1 0.00B 0.00B ~ (all equal) TrimASCII/16:2 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/16:4 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/16:8 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/16:16 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/256:1 0.00B 0.00B ~ (all equal) TrimASCII/256:2 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/256:4 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/256:8 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/256:16 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/4096:1 0.00B 0.00B ~ (all equal) TrimASCII/4096:2 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/4096:4 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/4096:8 48.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimASCII/4096:16 49.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) TrimByte 0.00B 0.00B ~ (all equal) name old allocs/op new allocs/op delta TrimSpace/NoTrim 0.00 0.00 ~ (all equal) TrimSpace/ASCII 0.00 0.00 ~ (all equal) TrimSpace/SomeNonASCII 0.00 0.00 ~ (all equal) TrimSpace/JustNonASCII 0.00 0.00 ~ (all equal) TrimASCII/1:1 0.00 0.00 ~ (all equal) TrimASCII/1:2 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/1:4 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/1:8 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/1:16 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/16:1 0.00 0.00 ~ (all equal) TrimASCII/16:2 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/16:4 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/16:8 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/16:16 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/256:1 0.00 0.00 ~ (all equal) TrimASCII/256:2 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/256:4 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/256:8 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/256:16 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/4096:1 0.00 0.00 ~ (all equal) TrimASCII/4096:2 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/4096:4 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/4096:8 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimASCII/4096:16 2.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) TrimByte 0.00 0.00 ~ (all equal) Fixes #46446 Change-Id: I9537c86f888af6285027f67bda4a97aeedb41d4a Reviewed-on: https://go-review.googlesource.com/c/go/+/332771 Reviewed-by: Josh Bleecher Snyder Reviewed-by: Joe Tsai Trust: Joe Tsai Trust: Than McIntosh --- src/bytes/bytes.go | 98 ++++++++++++++++++++++++++++++++++-------- src/strings/strings.go | 78 +++++++++++++++++++++++++++------ 2 files changed, 145 insertions(+), 31 deletions(-) diff --git a/src/bytes/bytes.go b/src/bytes/bytes.go index a9f10031c4..d3e01c3de7 100644 --- a/src/bytes/bytes.go +++ b/src/bytes/bytes.go @@ -867,6 +867,8 @@ func lastIndexFunc(s []byte, f func(r rune) bool, truth bool) int { // most-significant bit of the highest word, map to the full range of all // 128 ASCII characters. The 128-bits of the upper 16 bytes will be zeroed, // ensuring that any non-ASCII character will be reported as not in the set. +// This allocates a total of 32 bytes even though the upper half +// is unused to avoid bounds checks in asciiSet.contains. type asciiSet [8]uint32 // makeASCIISet creates a set of ASCII characters and reports whether all @@ -877,48 +879,56 @@ func makeASCIISet(chars string) (as asciiSet, ok bool) { if c >= utf8.RuneSelf { return as, false } - as[c>>5] |= 1 << uint(c&31) + as[c/32] |= 1 << (c % 32) } return as, true } // contains reports whether c is inside the set. func (as *asciiSet) contains(c byte) bool { - return (as[c>>5] & (1 << uint(c&31))) != 0 + return (as[c/32] & (1 << (c % 32))) != 0 } -func makeCutsetFunc(cutset string) func(r rune) bool { - if as, isASCII := makeASCIISet(cutset); isASCII { - return func(r rune) bool { - return r < utf8.RuneSelf && as.contains(byte(r)) +// containsRune is a simplified version of strings.ContainsRune +// to avoid importing the strings package. +// We avoid bytes.ContainsRune to avoid allocating a temporary copy of s. +func containsRune(s string, r rune) bool { + for _, c := range s { + if c == r { + return true } } - return func(r rune) bool { - for _, c := range cutset { - if c == r { - return true - } - } - return false - } + return false } // Trim returns a subslice of s by slicing off all leading and // trailing UTF-8-encoded code points contained in cutset. func Trim(s []byte, cutset string) []byte { + if len(s) == 0 || cutset == "" { + return s + } if len(cutset) == 1 && cutset[0] < utf8.RuneSelf { return trimLeftByte(trimRightByte(s, cutset[0]), cutset[0]) } - return TrimFunc(s, makeCutsetFunc(cutset)) + if as, ok := makeASCIISet(cutset); ok { + return trimLeftASCII(trimRightASCII(s, &as), &as) + } + return trimLeftUnicode(trimRightUnicode(s, cutset), cutset) } // TrimLeft returns a subslice of s by slicing off all leading // UTF-8-encoded code points contained in cutset. func TrimLeft(s []byte, cutset string) []byte { + if len(s) == 0 || cutset == "" { + return s + } if len(cutset) == 1 && cutset[0] < utf8.RuneSelf { return trimLeftByte(s, cutset[0]) } - return TrimLeftFunc(s, makeCutsetFunc(cutset)) + if as, ok := makeASCIISet(cutset); ok { + return trimLeftASCII(s, &as) + } + return trimLeftUnicode(s, cutset) } func trimLeftByte(s []byte, c byte) []byte { @@ -928,13 +938,43 @@ func trimLeftByte(s []byte, c byte) []byte { return s } +func trimLeftASCII(s []byte, as *asciiSet) []byte { + for len(s) > 0 { + if !as.contains(s[0]) { + break + } + s = s[1:] + } + return s +} + +func trimLeftUnicode(s []byte, cutset string) []byte { + for len(s) > 0 { + r, n := rune(s[0]), 1 + if r >= utf8.RuneSelf { + r, n = utf8.DecodeRune(s) + } + if !containsRune(cutset, r) { + break + } + s = s[n:] + } + return s +} + // TrimRight returns a subslice of s by slicing off all trailing // UTF-8-encoded code points that are contained in cutset. func TrimRight(s []byte, cutset string) []byte { + if len(s) == 0 || cutset == "" { + return s + } if len(cutset) == 1 && cutset[0] < utf8.RuneSelf { return trimRightByte(s, cutset[0]) } - return TrimRightFunc(s, makeCutsetFunc(cutset)) + if as, ok := makeASCIISet(cutset); ok { + return trimRightASCII(s, &as) + } + return trimRightUnicode(s, cutset) } func trimRightByte(s []byte, c byte) []byte { @@ -944,6 +984,30 @@ func trimRightByte(s []byte, c byte) []byte { return s } +func trimRightASCII(s []byte, as *asciiSet) []byte { + for len(s) > 0 { + if !as.contains(s[len(s)-1]) { + break + } + s = s[:len(s)-1] + } + return s +} + +func trimRightUnicode(s []byte, cutset string) []byte { + for len(s) > 0 { + r, n := rune(s[len(s)-1]), 1 + if r >= utf8.RuneSelf { + r, n = utf8.DecodeLastRune(s) + } + if !containsRune(cutset, r) { + break + } + s = s[:len(s)-n] + } + return s +} + // TrimSpace returns a subslice of s by slicing off all leading and // trailing white space, as defined by Unicode. func TrimSpace(s []byte) []byte { diff --git a/src/strings/strings.go b/src/strings/strings.go index 4b543dcc1a..bc734048c3 100644 --- a/src/strings/strings.go +++ b/src/strings/strings.go @@ -797,6 +797,8 @@ func lastIndexFunc(s string, f func(rune) bool, truth bool) int { // most-significant bit of the highest word, map to the full range of all // 128 ASCII characters. The 128-bits of the upper 16 bytes will be zeroed, // ensuring that any non-ASCII character will be reported as not in the set. +// This allocates a total of 32 bytes even though the upper half +// is unused to avoid bounds checks in asciiSet.contains. type asciiSet [8]uint32 // makeASCIISet creates a set of ASCII characters and reports whether all @@ -807,23 +809,14 @@ func makeASCIISet(chars string) (as asciiSet, ok bool) { if c >= utf8.RuneSelf { return as, false } - as[c>>5] |= 1 << uint(c&31) + as[c/32] |= 1 << (c % 32) } return as, true } // contains reports whether c is inside the set. func (as *asciiSet) contains(c byte) bool { - return (as[c>>5] & (1 << uint(c&31))) != 0 -} - -func makeCutsetFunc(cutset string) func(rune) bool { - if as, isASCII := makeASCIISet(cutset); isASCII { - return func(r rune) bool { - return r < utf8.RuneSelf && as.contains(byte(r)) - } - } - return func(r rune) bool { return IndexRune(cutset, r) >= 0 } + return (as[c/32] & (1 << (c % 32))) != 0 } // Trim returns a slice of the string s with all leading and @@ -835,7 +828,10 @@ func Trim(s, cutset string) string { if len(cutset) == 1 && cutset[0] < utf8.RuneSelf { return trimLeftByte(trimRightByte(s, cutset[0]), cutset[0]) } - return TrimFunc(s, makeCutsetFunc(cutset)) + if as, ok := makeASCIISet(cutset); ok { + return trimLeftASCII(trimRightASCII(s, &as), &as) + } + return trimLeftUnicode(trimRightUnicode(s, cutset), cutset) } // TrimLeft returns a slice of the string s with all leading @@ -849,7 +845,10 @@ func TrimLeft(s, cutset string) string { if len(cutset) == 1 && cutset[0] < utf8.RuneSelf { return trimLeftByte(s, cutset[0]) } - return TrimLeftFunc(s, makeCutsetFunc(cutset)) + if as, ok := makeASCIISet(cutset); ok { + return trimLeftASCII(s, &as) + } + return trimLeftUnicode(s, cutset) } func trimLeftByte(s string, c byte) string { @@ -859,6 +858,30 @@ func trimLeftByte(s string, c byte) string { return s } +func trimLeftASCII(s string, as *asciiSet) string { + for len(s) > 0 { + if !as.contains(s[0]) { + break + } + s = s[1:] + } + return s +} + +func trimLeftUnicode(s, cutset string) string { + for len(s) > 0 { + r, n := rune(s[0]), 1 + if r >= utf8.RuneSelf { + r, n = utf8.DecodeRuneInString(s) + } + if !ContainsRune(cutset, r) { + break + } + s = s[n:] + } + return s +} + // TrimRight returns a slice of the string s, with all trailing // Unicode code points contained in cutset removed. // @@ -870,7 +893,10 @@ func TrimRight(s, cutset string) string { if len(cutset) == 1 && cutset[0] < utf8.RuneSelf { return trimRightByte(s, cutset[0]) } - return TrimRightFunc(s, makeCutsetFunc(cutset)) + if as, ok := makeASCIISet(cutset); ok { + return trimRightASCII(s, &as) + } + return trimRightUnicode(s, cutset) } func trimRightByte(s string, c byte) string { @@ -880,6 +906,30 @@ func trimRightByte(s string, c byte) string { return s } +func trimRightASCII(s string, as *asciiSet) string { + for len(s) > 0 { + if !as.contains(s[len(s)-1]) { + break + } + s = s[:len(s)-1] + } + return s +} + +func trimRightUnicode(s, cutset string) string { + for len(s) > 0 { + r, n := rune(s[len(s)-1]), 1 + if r >= utf8.RuneSelf { + r, n = utf8.DecodeLastRuneInString(s) + } + if !ContainsRune(cutset, r) { + break + } + s = s[:len(s)-n] + } + return s +} + // TrimSpace returns a slice of the string s, with all leading // and trailing white space removed, as defined by Unicode. func TrimSpace(s string) string { -- GitLab From 4ffa2f1c23d5d43be18c4ebf74ca553119683670 Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Wed, 4 Aug 2021 16:07:28 -0700 Subject: [PATCH 1497/2500] time: fallback to slower TestTicker test after one failure TestTicker is sensitive to overloaded or slow systems, where a 20ms ticker running for 10 ticks has a total run time out of the range [110ms, 290ms]. To counter this flakiness, it tries five times to get a successful result. This is insufficient--an overloaded test machine can introduce more than 100ms of delay across the test. Reduce the five attempts to two, but use a 1s ticker for 8 ticks in the second attempt. Updates #46474. Updates #35692. Change-Id: Ibd5187b00ccceeb981b652f2af9a1c3766357b78 Reviewed-on: https://go-review.googlesource.com/c/go/+/339892 Trust: Damien Neil Run-TryBot: Damien Neil TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/time/tick_test.go | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/time/tick_test.go b/src/time/tick_test.go index b5d0a189bc..d8cd59228f 100644 --- a/src/time/tick_test.go +++ b/src/time/tick_test.go @@ -15,10 +15,11 @@ func TestTicker(t *testing.T) { // We want to test that a ticker takes as much time as expected. // Since we don't want the test to run for too long, we don't // want to use lengthy times. This makes the test inherently flaky. - // So only report an error if it fails five times in a row. + // Start with a short time, but try again with a long one if the + // first test fails. - count := 10 - delta := 20 * Millisecond + baseCount := 10 + baseDelta := 20 * Millisecond // On Darwin ARM64 the tick frequency seems limited. Issue 35692. if (runtime.GOOS == "darwin" || runtime.GOOS == "ios") && runtime.GOARCH == "arm64" { @@ -27,8 +28,8 @@ func TestTicker(t *testing.T) { // Since tick frequency is limited on Darwin ARM64, use even // number to give the ticks more time to let the test pass. // See CL 220638. - count = 6 - delta = 100 * Millisecond + baseCount = 6 + baseDelta = 100 * Millisecond } var errs []string @@ -38,7 +39,17 @@ func TestTicker(t *testing.T) { } } - for i := 0; i < 5; i++ { + for _, test := range []struct { + count int + delta Duration + }{{ + count: baseCount, + delta: baseDelta, + }, { + count: 8, + delta: 1 * Second, + }} { + count, delta := test.count, test.delta ticker := NewTicker(delta) t0 := Now() for i := 0; i < count/2; i++ { -- GitLab From 4707a6c284a9d8a0927cbc1badc6d09535a79bff Mon Sep 17 00:00:00 2001 From: Pedro Lopez Mareque Date: Sat, 2 Oct 2021 16:14:58 +0200 Subject: [PATCH 1498/2500] unicode: add examples for the Is functions Change-Id: If4afe33985dc0a758db32564244095190b82e5c4 Reviewed-on: https://go-review.googlesource.com/c/go/+/353691 Trust: Michael Knyszek Reviewed-by: Rob Pike --- src/unicode/example_test.go | 60 +++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/unicode/example_test.go b/src/unicode/example_test.go index 50c5b18a48..416ad1fe08 100644 --- a/src/unicode/example_test.go +++ b/src/unicode/example_test.go @@ -194,3 +194,63 @@ func ExampleSpecialCase() { // U+0130 'İ' // U+0130 'İ' } + +func ExampleIsDigit() { + fmt.Printf("%t\n", unicode.IsDigit('৩')) + fmt.Printf("%t\n", unicode.IsDigit('A')) + // Output: + // true + // false +} + +func ExampleIsNumber() { + fmt.Printf("%t\n", unicode.IsNumber('Ⅷ')) + fmt.Printf("%t\n", unicode.IsNumber('A')) + // Output: + // true + // false +} + +func ExampleIsLetter() { + fmt.Printf("%t\n", unicode.IsLetter('A')) + fmt.Printf("%t\n", unicode.IsLetter('7')) + // Output: + // true + // false +} + +func ExampleIsLower() { + fmt.Printf("%t\n", unicode.IsLower('a')) + fmt.Printf("%t\n", unicode.IsLower('A')) + // Output: + // true + // false +} + +func ExampleIsUpper() { + fmt.Printf("%t\n", unicode.IsUpper('A')) + fmt.Printf("%t\n", unicode.IsUpper('a')) + // Output: + // true + // false +} + +func ExampleIsTitle() { + fmt.Printf("%t\n", unicode.IsTitle('Dž')) + fmt.Printf("%t\n", unicode.IsTitle('a')) + // Output: + // true + // false +} + +func ExampleIsSpace() { + fmt.Printf("%t\n", unicode.IsSpace(' ')) + fmt.Printf("%t\n", unicode.IsSpace('\n')) + fmt.Printf("%t\n", unicode.IsSpace('\t')) + fmt.Printf("%t\n", unicode.IsUpper('a')) + // Output: + // true + // true + // true + // false +} -- GitLab From f3758443424dd6e411e2ac0108efdefd2ad7b294 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 4 Oct 2021 17:54:51 -0700 Subject: [PATCH 1499/2500] cmd/compile: fix -W=3 output after the # line I've noticed for a while that there is some duplicated and some useful information being put out in -W=3 mode after the comment marker (besides the position). dumpNodeHeader puts out a comment marker '#' before putting out the position of a node (which is for almost all nodes). Therefore, we shouldn't print out anything on the same line after calling dumpNodeHeader(). But we happen to be putting out a duplicate type of the node in some cases. Also, we put out the Sym() associate with the node after dumpNodeHeader(). So, I got rid of the duplicate type print-out, and moved the print-out of n.Sym() to be inside dumpNodeHeader() before the position information. Also, moved the tc flag to be right after the type information, which seems like it makes more sense. Change-Id: I05210fbf9f3b2d8e3b73fc0ceab26a7bce5dc104 Reviewed-on: https://go-review.googlesource.com/c/go/+/354355 Run-TryBot: Dan Scales TryBot-Result: Go Bot Trust: Dan Scales Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/fmt.go | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index 29505357cc..033188547b 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -1061,8 +1061,8 @@ func dumpNodeHeader(w io.Writer, n Node) { } } - if n.Typecheck() != 0 { - fmt.Fprintf(w, " tc(%d)", n.Typecheck()) + if n.Sym() != nil && n.Op() != ONAME && n.Op() != ONONAME && n.Op() != OTYPE { + fmt.Fprintf(w, " %+v", n.Sym()) } // Print Node-specific fields of basic type in header line. @@ -1132,6 +1132,9 @@ func dumpNodeHeader(w io.Writer, n Node) { } fmt.Fprintf(w, " %+v", n.Type()) } + if n.Typecheck() != 0 { + fmt.Fprintf(w, " tc(%d)", n.Typecheck()) + } if n.Pos().IsKnown() { fmt.Fprint(w, " # ") @@ -1248,13 +1251,6 @@ func dumpNode(w io.Writer, n Node, depth int) { return } - if n.Sym() != nil { - fmt.Fprintf(w, " %+v", n.Sym()) - } - if n.Type() != nil { - fmt.Fprintf(w, " %+v", n.Type()) - } - v := reflect.ValueOf(n).Elem() t := reflect.TypeOf(n).Elem() nf := t.NumField() -- GitLab From c8dd89ed3dde52933d981d7d7c4c200160f47ec3 Mon Sep 17 00:00:00 2001 From: John Kelly Date: Thu, 29 Jul 2021 15:47:23 -0400 Subject: [PATCH 1500/2500] net/http: add Cookie.Valid method The (*http.Cookie).String method used by SetCookie will silently discard or sanitize any fields it deems invalid, making it difficult to tell whether a cookie will be sent as expected. This change introduces a new (*http.Cookie).Valid method which may be used to check if any cookie fields will be discarded or sanitized prior to calling (*http.Cookie).String. Fixes #46370 Change-Id: I2db80078de190d267a9c675a9717c8be8acc8704 Reviewed-on: https://go-review.googlesource.com/c/go/+/338590 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Trust: Cherry Mui Trust: Damien Neil Reviewed-by: Damien Neil --- api/next.txt | 1 + src/net/http/cookie.go | 33 +++++++++++++++++++++++++++++++++ src/net/http/cookie_test.go | 25 +++++++++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/api/next.txt b/api/next.txt index b1b9c1d7b1..1192fc9069 100644 --- a/api/next.txt +++ b/api/next.txt @@ -142,3 +142,4 @@ pkg testing, type FuzzResult struct, T time.Duration pkg testing, type InternalFuzzTarget struct pkg testing, type InternalFuzzTarget struct, Fn func(*F) pkg testing, type InternalFuzzTarget struct, Name string +pkg net/http, method (*Cookie) Valid() error diff --git a/src/net/http/cookie.go b/src/net/http/cookie.go index 02b40315de..cb37f2351f 100644 --- a/src/net/http/cookie.go +++ b/src/net/http/cookie.go @@ -5,6 +5,8 @@ package http import ( + "errors" + "fmt" "log" "net" "net/http/internal/ascii" @@ -236,6 +238,37 @@ func (c *Cookie) String() string { return b.String() } +// Valid reports whether the cookie is valid. +func (c *Cookie) Valid() error { + if c == nil { + return errors.New("http: nil Cookie") + } + if !isCookieNameValid(c.Name) { + return errors.New("http: invalid Cookie.Name") + } + if !validCookieExpires(c.Expires) { + return errors.New("http: invalid Cookie.Expires") + } + for i := 0; i < len(c.Value); i++ { + if !validCookieValueByte(c.Value[i]) { + return fmt.Errorf("http: invalid byte %q in Cookie.Value", c.Value[i]) + } + } + if len(c.Path) > 0 { + for i := 0; i < len(c.Path); i++ { + if !validCookiePathByte(c.Path[i]) { + return fmt.Errorf("http: invalid byte %q in Cookie.Path", c.Path[i]) + } + } + } + if len(c.Domain) > 0 { + if !validCookieDomain(c.Domain) { + return errors.New("http: invalid Cookie.Domain") + } + } + return nil +} + // readCookies parses all "Cookie" values from the header h and // returns the successfully parsed Cookies. // diff --git a/src/net/http/cookie_test.go b/src/net/http/cookie_test.go index 959713a0dc..257dc57420 100644 --- a/src/net/http/cookie_test.go +++ b/src/net/http/cookie_test.go @@ -529,6 +529,31 @@ func TestCookieSanitizePath(t *testing.T) { } } +func TestCookieValid(t *testing.T) { + tests := []struct { + cookie *Cookie + valid bool + }{ + {nil, false}, + {&Cookie{Name: ""}, false}, + {&Cookie{Name: "invalid-expires"}, false}, + {&Cookie{Name: "invalid-value", Value: "foo\"bar"}, false}, + {&Cookie{Name: "invalid-path", Path: "/foo;bar/"}, false}, + {&Cookie{Name: "invalid-domain", Domain: "example.com:80"}, false}, + {&Cookie{Name: "valid", Value: "foo", Path: "/bar", Domain: "example.com", Expires: time.Unix(0, 0)}, true}, + } + + for _, tt := range tests { + err := tt.cookie.Valid() + if err != nil && tt.valid { + t.Errorf("%#v.Valid() returned error %v; want nil", tt.cookie, err) + } + if err == nil && !tt.valid { + t.Errorf("%#v.Valid() returned nil; want error", tt.cookie) + } + } +} + func BenchmarkCookieString(b *testing.B) { const wantCookieString = `cookie-9=i3e01nf61b6t23bvfmplnanol3; Path=/restricted/; Domain=example.com; Expires=Tue, 10 Nov 2009 23:00:00 GMT; Max-Age=3600` c := &Cookie{ -- GitLab From 812a33dc7df6a4f7b8b0bd2e6ea6500f312b3fed Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Wed, 6 Oct 2021 13:42:17 -0700 Subject: [PATCH 1501/2500] test: skip endian inlining test on noopt builder Change-Id: I73b1ac23f322bcaff36eff7a5829654f299c1fdd Reviewed-on: https://go-review.googlesource.com/c/go/+/354353 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- test/inline_endian.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/inline_endian.go b/test/inline_endian.go index baca133452..e00e06a75e 100644 --- a/test/inline_endian.go +++ b/test/inline_endian.go @@ -1,7 +1,8 @@ // errorcheckwithauto -0 -m -d=inlfuncswithclosures=1 -//go:build 386 || amd64 || arm64 || ppc64le || s390x +//go:build (386 || amd64 || arm64 || ppc64le || s390x) && !gcflags_noopt // +build 386 amd64 arm64 ppc64le s390x +// +build !gcflags_noopt // Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style -- GitLab From 39bbf08e7139d0e041b0633945a42d0621d2897e Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 6 Oct 2021 18:23:06 -0700 Subject: [PATCH 1502/2500] cmd/compile/internal/types2: implement copy for generic argument types For now, the underlying types of the the argument types' constraints must be a single type that is a slice (the source operand may also be a string). Change-Id: I9e705e3349c9242f126b9c3e0af65e9ffb25fe6e Reviewed-on: https://go-review.googlesource.com/c/go/+/354432 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Ian Lance Taylor --- src/cmd/compile/internal/types2/builtins.go | 4 +- .../types2/testdata/check/builtins.go2 | 37 +++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 3b8d85859a..cb4d93c6c4 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -336,15 +336,13 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( return } var src Type - switch t := under(y.typ).(type) { + switch t := optype(y.typ).(type) { case *Basic: if isString(y.typ) { src = universeByte } case *Slice: src = t.elem - case *TypeParam: - check.error(x, "copy on generic operands not yet implemented") } if dst == nil || src == nil { diff --git a/src/cmd/compile/internal/types2/testdata/check/builtins.go2 b/src/cmd/compile/internal/types2/testdata/check/builtins.go2 index 0cfea93bf6..243e888ff7 100644 --- a/src/cmd/compile/internal/types2/testdata/check/builtins.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/builtins.go2 @@ -45,6 +45,43 @@ func _[T C5[X], X any](ch T) { close(ch) } +// copy + +func _[T any](x, y T) { + copy(x /* ERROR copy expects slice arguments */ , y) +} + +func _[T ~[]byte](x, y T) { + copy(x, y) + copy(x, "foo") + copy("foo" /* ERROR expects slice arguments */ , y) + + var x2 []byte + copy(x2, y) // element types are identical + copy(y, x2) // element types are identical + + type myByte byte + var x3 []myByte + copy(x3 /* ERROR different element types */ , y) + copy(y, x3 /* ERROR different element types */ ) +} + +func _[T ~[]E, E any](x T, y []E) { + copy(x, y) + copy(x /* ERROR different element types */ , "foo") +} + +func _[T ~string](x []byte, y T) { + copy(x, y) + copy(y /* ERROR expects slice arguments */ , x) +} + +func _[T ~[]byte|~string](x T, y []byte) { + copy(x /* ERROR expects slice arguments */ , y) + // TODO(gri) should this be valid? + copy(y /* ERROR expects slice arguments */ , x) +} + // delete type M0 interface{ int } -- GitLab From 6f74ed06c5b0e1d69fb70e89f31f002f18554c79 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 6 Oct 2021 19:38:15 -0700 Subject: [PATCH 1503/2500] go/types: implement copy for generic argument types This is a port of CL 354432 from types2 to go/types with minor adjustments: - an error message has a different position - the constraint literals are wrapped in interfaces because the interface-free notation has not been ported yet Change-Id: I167094b57b39027566f2b7ce3aa97a071bae4da5 Reviewed-on: https://go-review.googlesource.com/c/go/+/354489 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/go/types/builtins.go | 4 +-- src/go/types/testdata/check/builtins.go2 | 37 ++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index d805e46666..3e2c994b09 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -341,15 +341,13 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b return } var src Type - switch t := under(y.typ).(type) { + switch t := optype(y.typ).(type) { case *Basic: if isString(y.typ) { src = universeByte } case *Slice: src = t.elem - case *TypeParam: - check.error(x, _Todo, "copy on generic operands not yet implemented") } if dst == nil || src == nil { diff --git a/src/go/types/testdata/check/builtins.go2 b/src/go/types/testdata/check/builtins.go2 index 1c773cc70b..fb912a1918 100644 --- a/src/go/types/testdata/check/builtins.go2 +++ b/src/go/types/testdata/check/builtins.go2 @@ -45,6 +45,43 @@ func _[T C5[X], X any](ch T) { close(ch) } +// copy + +func _[T any](x, y T) { + copy(x /* ERROR copy expects slice arguments */ , y) +} + +func _[T interface{~[]byte}](x, y T) { + copy(x, y) + copy(x, "foo") + copy("foo" /* ERROR expects slice arguments */ , y) + + var x2 []byte + copy(x2, y) // element types are identical + copy(y, x2) // element types are identical + + type myByte byte + var x3 []myByte + copy(x3 /* ERROR different element types */ , y) + copy(y /* ERROR different element types */ , x3) +} + +func _[T interface{~[]E}, E any](x T, y []E) { + copy(x, y) + copy(x /* ERROR different element types */ , "foo") +} + +func _[T interface{~string}](x []byte, y T) { + copy(x, y) + copy(y /* ERROR expects slice arguments */ , x) +} + +func _[T interface{~[]byte|~string}](x T, y []byte) { + copy(x /* ERROR expects slice arguments */ , y) + // TODO(gri) should this be valid? + copy(y /* ERROR expects slice arguments */ , x) +} + // delete type M0 interface{ int } -- GitLab From ecb2f231fa41b581319505139f8d5ac779763bee Mon Sep 17 00:00:00 2001 From: Meng Zhuo Date: Thu, 30 Sep 2021 22:46:09 +0800 Subject: [PATCH 1504/2500] runtime,sync: using fastrandn instead of modulo reduction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fastrandn is ~50% faster than fastrand() % n. `ack -v 'fastrand\(\)\s?\%'` finds all modulo on fastrand() name old time/op new time/op delta Fastrandn/2 2.86ns ± 0% 1.59ns ± 0% -44.35% (p=0.000 n=9+10) Fastrandn/3 2.87ns ± 1% 1.59ns ± 0% -44.41% (p=0.000 n=10+9) Fastrandn/4 2.87ns ± 1% 1.58ns ± 1% -45.10% (p=0.000 n=10+10) Fastrandn/5 2.86ns ± 1% 1.58ns ± 1% -44.84% (p=0.000 n=10+10) Change-Id: Ic91f5ca9b9e3b65127bc34792b62fd64fbd13b5c Reviewed-on: https://go-review.googlesource.com/c/go/+/353269 Trust: Meng Zhuo Run-TryBot: Meng Zhuo TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/runtime/malloc.go | 4 ++-- src/runtime/mbitmap.go | 2 +- src/runtime/proc.go | 2 +- src/runtime/stubs.go | 4 ++-- src/runtime/symtab.go | 2 +- src/sync/pool.go | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index 7affe244a2..c389cb1e45 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -1301,7 +1301,7 @@ func fastexprand(mean int) int32 { // x = -log_e(q) * mean // x = log_2(q) * (-log_e(2)) * mean ; Using log_2 for efficiency const randomBitCount = 26 - q := fastrand()%(1< 0 { qlog = 0 @@ -1319,7 +1319,7 @@ func nextSampleNoFP() uintptr { rate = 0x3fffffff } if rate != 0 { - return uintptr(fastrand() % uint32(2*rate)) + return uintptr(fastrandn(uint32(2 * rate))) } return 0 } diff --git a/src/runtime/mbitmap.go b/src/runtime/mbitmap.go index 9363409e36..daf1fcfbc0 100644 --- a/src/runtime/mbitmap.go +++ b/src/runtime/mbitmap.go @@ -974,7 +974,7 @@ func heapBitsSetType(x, size, dataSize uintptr, typ *_type) { // machine instructions. outOfPlace := false - if arenaIndex(x+size-1) != arenaIdx(h.arena) || (doubleCheck && fastrand()%2 == 0) { + if arenaIndex(x+size-1) != arenaIdx(h.arena) || (doubleCheck && fastrandn(2) == 0) { // This object spans heap arenas, so the bitmap may be // discontiguous. Unroll it into the object instead // and then copy it out. diff --git a/src/runtime/proc.go b/src/runtime/proc.go index aa2ba96c8f..c14a1f143c 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -5840,7 +5840,7 @@ const randomizeScheduler = raceenabled // If the run queue is full, runnext puts g on the global queue. // Executed only by the owner P. func runqput(_p_ *p, gp *g, next bool) { - if randomizeScheduler && next && fastrand()%2 == 0 { + if randomizeScheduler && next && fastrandn(2) == 0 { next = false } diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go index 91380a0d51..ad78363bb6 100644 --- a/src/runtime/stubs.go +++ b/src/runtime/stubs.go @@ -156,8 +156,8 @@ func fastrandn(n uint32) uint32 { return uint32(uint64(fastrand()) * uint64(n) >> 32) } -//go:linkname sync_fastrand sync.fastrand -func sync_fastrand() uint32 { return fastrand() } +//go:linkname sync_fastrandn sync.fastrandn +func sync_fastrandn(n uint32) uint32 { return fastrandn(n) } //go:linkname net_fastrand net.fastrand func net_fastrand() uint32 { return fastrand() } diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 7641c491f1..2de518d2e6 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -921,7 +921,7 @@ func pcvalue(f funcInfo, off uint32, targetpc uintptr, cache *pcvalueCache, stri if cache != nil { x := pcvalueCacheKey(targetpc) e := &cache.entries[x] - ci := fastrand() % uint32(len(cache.entries[x])) + ci := fastrandn(uint32(len(cache.entries[x]))) e[ci] = e[0] e[0] = pcvalueCacheEnt{ targetpc: targetpc, diff --git a/src/sync/pool.go b/src/sync/pool.go index 1ae70127ac..9802f29d6f 100644 --- a/src/sync/pool.go +++ b/src/sync/pool.go @@ -71,7 +71,7 @@ type poolLocal struct { } // from runtime -func fastrand() uint32 +func fastrandn(n uint32) uint32 var poolRaceHash [128]uint64 @@ -92,7 +92,7 @@ func (p *Pool) Put(x interface{}) { return } if race.Enabled { - if fastrand()%4 == 0 { + if fastrandn(4) == 0 { // Randomly drop x on floor. return } -- GitLab From 375a1fba0eb733676698ac3a9fdd12e6a8dd6602 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Tue, 5 Oct 2021 22:59:49 +0700 Subject: [PATCH 1505/2500] cmd/compile: better error message for invalid untyped nil conversion In case of an invalid untyped nil conversion, the compiler's original type checker leaves it to the caller to report a suitable error message. But types2 does not, it always reports the invalid conversion. CL 328053 made types2 report a better error message, and match the original compiler behavior. But it ignored the case of untyped nil. This CL adds that missing case, by checking whether the two operands can be mixed when untyped nil is present. Fixes #48784 Change-Id: Idc7d86eb0245aa18ca428e278f4416d6b3679058 Reviewed-on: https://go-review.googlesource.com/c/go/+/354049 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le Reviewed-by: Robert Griesemer Reviewed-by: Robert Findley TryBot-Result: Go Bot --- src/cmd/compile/internal/types2/expr.go | 6 +++++ .../internal/types2/testdata/check/expr2.src | 4 ++-- test/fixedbugs/issue48784.go | 23 +++++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 test/fixedbugs/issue48784.go diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 90c80f9de0..3a3a139156 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -996,6 +996,12 @@ func (check *Checker) binary(x *operand, e syntax.Expr, lhs, rhs syntax.Expr, op if isString(x.typ) != isString(y.typ) { return false } + if x.isNil() && !hasNil(y.typ) { + return false + } + if y.isNil() && !hasNil(x.typ) { + return false + } return true } if canMix(x, &y) { diff --git a/src/cmd/compile/internal/types2/testdata/check/expr2.src b/src/cmd/compile/internal/types2/testdata/check/expr2.src index f9726b5de5..8e5862319e 100644 --- a/src/cmd/compile/internal/types2/testdata/check/expr2.src +++ b/src/cmd/compile/internal/types2/testdata/check/expr2.src @@ -29,7 +29,7 @@ func arrays() { _ = a == b _ = a != b _ = a /* ERROR < not defined */ < b - _ = a == nil /* ERROR cannot convert */ + _ = a == nil /* ERROR invalid operation.*mismatched types */ type C [10]int var c C @@ -53,7 +53,7 @@ func structs() { _ = s == t _ = s != t _ = s /* ERROR < not defined */ < t - _ = s == nil /* ERROR cannot convert */ + _ = s == nil /* ERROR invalid operation.*mismatched types */ type S struct { x int diff --git a/test/fixedbugs/issue48784.go b/test/fixedbugs/issue48784.go new file mode 100644 index 0000000000..6048518df2 --- /dev/null +++ b/test/fixedbugs/issue48784.go @@ -0,0 +1,23 @@ +// errorcheck -e + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T struct{} + +var s string +var b bool +var i int +var t T +var a [1]int + +var ( + _ = s == nil // ERROR "invalid operation:.*mismatched types string and untyped nil" + _ = b == nil // ERROR "invalid operation:.*mismatched types bool and untyped nil" + _ = i == nil // ERROR "invalid operation:.*mismatched types int and untyped nil" + _ = t == nil // ERROR "invalid operation:.*mismatched types T and untyped nil" + _ = a == nil // ERROR "invalid operation:.*mismatched types \[1\]int and untyped nil" +) -- GitLab From ebeab63d9515b539ae627f10cfc1766eecd243aa Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Tue, 5 Oct 2021 23:53:07 +0700 Subject: [PATCH 1506/2500] go/types: better error message for invalid untyped nil conversion This is port of CL 354049 for types2 to go/type. The change is identical, but for some tweaks to the error message/position in tests, since when go/types reports the exact operation "cannot convert" instead of the general "invalid operation" like types2. Updates #48784 Change-Id: I3e99f2721501d23187fd0a8970eb1de28e0c41d8 Reviewed-on: https://go-review.googlesource.com/c/go/+/354050 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/go/types/errorcodes.go | 2 +- src/go/types/expr.go | 6 ++++++ src/go/types/testdata/check/expr2.src | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/go/types/errorcodes.go b/src/go/types/errorcodes.go index bcc850f753..49c6a74c20 100644 --- a/src/go/types/errorcodes.go +++ b/src/go/types/errorcodes.go @@ -875,7 +875,7 @@ const ( // context in which it is used. // // Example: - // var _ = 1 + nil + // var _ = 1 + new(int) _InvalidUntypedConversion // _BadOffsetofSyntax occurs when unsafe.Offsetof is called with an argument diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 2fc5aa85d2..fac5a5e31d 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -967,6 +967,12 @@ func (check *Checker) binary(x *operand, e ast.Expr, lhs, rhs ast.Expr, op token if isString(x.typ) != isString(y.typ) { return false } + if x.isNil() && !hasNil(y.typ) { + return false + } + if y.isNil() && !hasNil(x.typ) { + return false + } return true } if canMix(x, &y) { diff --git a/src/go/types/testdata/check/expr2.src b/src/go/types/testdata/check/expr2.src index f9726b5de5..8757fd9e48 100644 --- a/src/go/types/testdata/check/expr2.src +++ b/src/go/types/testdata/check/expr2.src @@ -29,7 +29,7 @@ func arrays() { _ = a == b _ = a != b _ = a /* ERROR < not defined */ < b - _ = a == nil /* ERROR cannot convert */ + _ = a /* ERROR cannot compare.*mismatched types */ == nil type C [10]int var c C @@ -53,7 +53,7 @@ func structs() { _ = s == t _ = s != t _ = s /* ERROR < not defined */ < t - _ = s == nil /* ERROR cannot convert */ + _ = s /* ERROR cannot compare.*mismatched types */ == nil type S struct { x int -- GitLab From be571a36c7aa7198aef4712f8c6cde633e2f380b Mon Sep 17 00:00:00 2001 From: Leonard Wang Date: Thu, 7 Oct 2021 20:14:22 +0800 Subject: [PATCH 1507/2500] cmd/compile: fix the index variable is shadowed in dictPass The CL 349613 causes this problem. In fact, we want to use the outer i to find m.List[i], but the newly created index variable i in the nearest for range shadow the outer i. Fixes #48838. Change-Id: I10f0bd985340f9443eefaadda6fc56e4e7e9a10c Reviewed-on: https://go-review.googlesource.com/c/go/+/354549 Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Keith Randall Reviewed-by: Dan Scales Trust: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 4 +-- test/typeparam/issue48838.go | 31 +++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 test/typeparam/issue48838.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 2bc1756b8d..62d6a45819 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1298,9 +1298,9 @@ func (g *irgen) dictPass(info *instInfo) { // Type switch from nonempty interface. We need a *runtime.itab // for the dynamic type. ix := -1 - for i, ic := range info.dictInfo.itabConvs { + for j, ic := range info.dictInfo.itabConvs { if ic == m.List[i] { - ix = info.dictInfo.startItabConv + i + ix = info.dictInfo.startItabConv + j break } } diff --git a/test/typeparam/issue48838.go b/test/typeparam/issue48838.go new file mode 100644 index 0000000000..ef2150d6a2 --- /dev/null +++ b/test/typeparam/issue48838.go @@ -0,0 +1,31 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func main() { + check[string]() +} + +func check[T any]() { + var result setter[T] + switch result.(type) { + case fooA[T]: + case fooB[T]: + } +} + +type setter[T any] interface { + Set(T) +} + +type fooA[T any] struct{} + +func (fooA[T]) Set(T) {} + +type fooB[T any] struct{} + +func (fooB[T]) Set(T) {} -- GitLab From 019ad98b5337992625327ea07185ad06a9c19169 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 4 Oct 2021 16:20:57 -0700 Subject: [PATCH 1508/2500] cmd/cgo: update to handle ast.IndexListExpr Allows cgo to work with generics. Updates #47781. Change-Id: Id1a5d1a0a8193c5b157e3e671b1490d687d10384 Reviewed-on: https://go-review.googlesource.com/c/go/+/353882 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- misc/cgo/test/typeparam.go | 17 +++++++++++++++++ misc/go.mod | 2 +- src/cmd/cgo/ast.go | 3 +-- src/cmd/cgo/ast_go1.go | 17 +++++++++++++++++ src/cmd/cgo/ast_go118.go | 25 +++++++++++++++++++++++++ src/cmd/cgo/gcc.go | 2 +- 6 files changed, 62 insertions(+), 4 deletions(-) create mode 100644 misc/cgo/test/typeparam.go create mode 100644 src/cmd/cgo/ast_go1.go create mode 100644 src/cmd/cgo/ast_go118.go diff --git a/misc/cgo/test/typeparam.go b/misc/cgo/test/typeparam.go new file mode 100644 index 0000000000..5f766c2bcb --- /dev/null +++ b/misc/cgo/test/typeparam.go @@ -0,0 +1,17 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cgotest + +// #include +import "C" + +func generic[T, U any](t T, u U) {} + +func useGeneric() { + const zero C.size_t = 0 + + generic(zero, zero) + generic[C.size_t, C.size_t](0, 0) +} diff --git a/misc/go.mod b/misc/go.mod index fc9f1133a4..712a051f45 100644 --- a/misc/go.mod +++ b/misc/go.mod @@ -8,4 +8,4 @@ // directory.) module misc -go 1.12 +go 1.18 diff --git a/src/cmd/cgo/ast.go b/src/cmd/cgo/ast.go index a073407a96..28879e349c 100644 --- a/src/cmd/cgo/ast.go +++ b/src/cmd/cgo/ast.go @@ -338,8 +338,7 @@ func (f *File) walk(x interface{}, context astContext, visit func(*File, interfa // everything else just recurs default: - error_(token.NoPos, "unexpected type %T in walk", x) - panic("unexpected type") + f.walkUnexpected(x, context, visit) case nil: diff --git a/src/cmd/cgo/ast_go1.go b/src/cmd/cgo/ast_go1.go new file mode 100644 index 0000000000..cf6d99f64a --- /dev/null +++ b/src/cmd/cgo/ast_go1.go @@ -0,0 +1,17 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !go1.18 +// +build !go1.18 + +package main + +import ( + "go/token" +) + +func (f *File) walkUnexpected(x interface{}, context astContext, visit func(*File, interface{}, astContext)) { + error_(token.NoPos, "unexpected type %T in walk", x) + panic("unexpected type") +} diff --git a/src/cmd/cgo/ast_go118.go b/src/cmd/cgo/ast_go118.go new file mode 100644 index 0000000000..2e3ce27521 --- /dev/null +++ b/src/cmd/cgo/ast_go118.go @@ -0,0 +1,25 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.18 +// +build go1.18 + +package main + +import ( + "go/ast" + "go/token" +) + +func (f *File) walkUnexpected(x interface{}, context astContext, visit func(*File, interface{}, astContext)) { + switch n := x.(type) { + default: + error_(token.NoPos, "unexpected type %T in walk", x) + panic("unexpected type") + + case *ast.IndexListExpr: + f.walk(&n.X, ctxExpr, visit) + f.walk(n.Indices, ctxExpr, visit) + } +} diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index f5682c0997..c78197896c 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -1506,7 +1506,7 @@ func (p *Package) rewriteName(f *File, r *Ref, addPosition bool) ast.Expr { Args: []ast.Expr{getNewIdent(name.Mangle)}, } case "type": - // Okay - might be new(T) + // Okay - might be new(T), T(x), Generic[T], etc. if r.Name.Type == nil { error_(r.Pos(), "expression C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C) } -- GitLab From 4607ebc7d897c36687ae4ede3cfd4939c6dd0a54 Mon Sep 17 00:00:00 2001 From: Pedro Lopez Mareque Date: Sat, 2 Oct 2021 11:59:08 +0200 Subject: [PATCH 1509/2500] math: add Remainder example Change-Id: I4b0fa69a36b04103473aa08e246fa193315ac5aa Reviewed-on: https://go-review.googlesource.com/c/go/+/353689 Reviewed-by: Emmanuel Odeke Reviewed-by: Robert Griesemer Run-TryBot: Emmanuel Odeke TryBot-Result: Go Bot --- src/math/example_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/math/example_test.go b/src/math/example_test.go index 9fc1967967..a26d8cbe97 100644 --- a/src/math/example_test.go +++ b/src/math/example_test.go @@ -162,6 +162,11 @@ func ExampleLog10() { // Output: 2.0 } +func ExampleRemainder() { + fmt.Printf("%.1f", math.Remainder(100, 30)) + // Output: 10.0 +} + func ExampleMod() { c := math.Mod(7, 4) fmt.Printf("%.1f", c) -- GitLab From 2043b3b47b3ca76d8ce44f05a77e48d2291b6fc6 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Wed, 6 Oct 2021 14:53:32 -0700 Subject: [PATCH 1510/2500] cmd/compile,runtime: implement uint64->float32 correctly on 32-bit archs The old way of implementing it, float32(float64(x)), involves 2 roundings which can cause accuracy errors in some strange cases. Implement a runtime version of [u]int64tofloat32 which only does one rounding. Fixes #48807 Change-Id: Ie580be480bee4f3a479e58ef8dce23032f231704 Reviewed-on: https://go-review.googlesource.com/c/go/+/354429 Trust: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: David Chase --- src/cmd/compile/internal/typecheck/builtin.go | 73 ++++++++++--------- .../internal/typecheck/builtin/runtime.go | 2 + src/cmd/compile/internal/walk/convert.go | 4 +- src/runtime/float_test.go | 25 +++++++ src/runtime/vlrt.go | 30 ++++++++ 5 files changed, 98 insertions(+), 36 deletions(-) create mode 100644 src/runtime/float_test.go diff --git a/src/cmd/compile/internal/typecheck/builtin.go b/src/cmd/compile/internal/typecheck/builtin.go index 3f177d9173..524360e8df 100644 --- a/src/cmd/compile/internal/typecheck/builtin.go +++ b/src/cmd/compile/internal/typecheck/builtin.go @@ -176,30 +176,32 @@ var runtimeDecls = [...]struct { {"float64touint64", funcTag, 130}, {"float64touint32", funcTag, 131}, {"int64tofloat64", funcTag, 132}, - {"uint64tofloat64", funcTag, 133}, - {"uint32tofloat64", funcTag, 134}, - {"complex128div", funcTag, 135}, - {"getcallerpc", funcTag, 136}, - {"getcallersp", funcTag, 136}, + {"int64tofloat32", funcTag, 134}, + {"uint64tofloat64", funcTag, 135}, + {"uint64tofloat32", funcTag, 136}, + {"uint32tofloat64", funcTag, 137}, + {"complex128div", funcTag, 138}, + {"getcallerpc", funcTag, 139}, + {"getcallersp", funcTag, 139}, {"racefuncenter", funcTag, 31}, {"racefuncexit", funcTag, 9}, {"raceread", funcTag, 31}, {"racewrite", funcTag, 31}, - {"racereadrange", funcTag, 137}, - {"racewriterange", funcTag, 137}, - {"msanread", funcTag, 137}, - {"msanwrite", funcTag, 137}, - {"msanmove", funcTag, 138}, - {"checkptrAlignment", funcTag, 139}, - {"checkptrArithmetic", funcTag, 141}, - {"libfuzzerTraceCmp1", funcTag, 142}, - {"libfuzzerTraceCmp2", funcTag, 143}, - {"libfuzzerTraceCmp4", funcTag, 144}, - {"libfuzzerTraceCmp8", funcTag, 145}, - {"libfuzzerTraceConstCmp1", funcTag, 142}, - {"libfuzzerTraceConstCmp2", funcTag, 143}, - {"libfuzzerTraceConstCmp4", funcTag, 144}, - {"libfuzzerTraceConstCmp8", funcTag, 145}, + {"racereadrange", funcTag, 140}, + {"racewriterange", funcTag, 140}, + {"msanread", funcTag, 140}, + {"msanwrite", funcTag, 140}, + {"msanmove", funcTag, 141}, + {"checkptrAlignment", funcTag, 142}, + {"checkptrArithmetic", funcTag, 144}, + {"libfuzzerTraceCmp1", funcTag, 145}, + {"libfuzzerTraceCmp2", funcTag, 146}, + {"libfuzzerTraceCmp4", funcTag, 147}, + {"libfuzzerTraceCmp8", funcTag, 148}, + {"libfuzzerTraceConstCmp1", funcTag, 145}, + {"libfuzzerTraceConstCmp2", funcTag, 146}, + {"libfuzzerTraceConstCmp4", funcTag, 147}, + {"libfuzzerTraceConstCmp8", funcTag, 148}, {"x86HasPOPCNT", varTag, 6}, {"x86HasSSE41", varTag, 6}, {"x86HasFMA", varTag, 6}, @@ -222,7 +224,7 @@ func params(tlist ...*types.Type) []*types.Field { } func runtimeTypes() []*types.Type { - var typs [146]*types.Type + var typs [149]*types.Type typs[0] = types.ByteType typs[1] = types.NewPtr(typs[0]) typs[2] = types.Types[types.TANY] @@ -356,18 +358,21 @@ func runtimeTypes() []*types.Type { typs[130] = newSig(params(typs[20]), params(typs[24])) typs[131] = newSig(params(typs[20]), params(typs[62])) typs[132] = newSig(params(typs[22]), params(typs[20])) - typs[133] = newSig(params(typs[24]), params(typs[20])) - typs[134] = newSig(params(typs[62]), params(typs[20])) - typs[135] = newSig(params(typs[26], typs[26]), params(typs[26])) - typs[136] = newSig(nil, params(typs[5])) - typs[137] = newSig(params(typs[5], typs[5]), nil) - typs[138] = newSig(params(typs[5], typs[5], typs[5]), nil) - typs[139] = newSig(params(typs[7], typs[1], typs[5]), nil) - typs[140] = types.NewSlice(typs[7]) - typs[141] = newSig(params(typs[7], typs[140]), nil) - typs[142] = newSig(params(typs[66], typs[66]), nil) - typs[143] = newSig(params(typs[60], typs[60]), nil) - typs[144] = newSig(params(typs[62], typs[62]), nil) - typs[145] = newSig(params(typs[24], typs[24]), nil) + typs[133] = types.Types[types.TFLOAT32] + typs[134] = newSig(params(typs[22]), params(typs[133])) + typs[135] = newSig(params(typs[24]), params(typs[20])) + typs[136] = newSig(params(typs[24]), params(typs[133])) + typs[137] = newSig(params(typs[62]), params(typs[20])) + typs[138] = newSig(params(typs[26], typs[26]), params(typs[26])) + typs[139] = newSig(nil, params(typs[5])) + typs[140] = newSig(params(typs[5], typs[5]), nil) + typs[141] = newSig(params(typs[5], typs[5], typs[5]), nil) + typs[142] = newSig(params(typs[7], typs[1], typs[5]), nil) + typs[143] = types.NewSlice(typs[7]) + typs[144] = newSig(params(typs[7], typs[143]), nil) + typs[145] = newSig(params(typs[66], typs[66]), nil) + typs[146] = newSig(params(typs[60], typs[60]), nil) + typs[147] = newSig(params(typs[62], typs[62]), nil) + typs[148] = newSig(params(typs[24], typs[24]), nil) return typs[:] } diff --git a/src/cmd/compile/internal/typecheck/builtin/runtime.go b/src/cmd/compile/internal/typecheck/builtin/runtime.go index 605b904288..66641fb5aa 100644 --- a/src/cmd/compile/internal/typecheck/builtin/runtime.go +++ b/src/cmd/compile/internal/typecheck/builtin/runtime.go @@ -227,7 +227,9 @@ func float64toint64(float64) int64 func float64touint64(float64) uint64 func float64touint32(float64) uint32 func int64tofloat64(int64) float64 +func int64tofloat32(int64) float32 func uint64tofloat64(uint64) float64 +func uint64tofloat32(uint64) float32 func uint32tofloat64(uint32) float64 func complex128div(num complex128, den complex128) (quo complex128) diff --git a/src/cmd/compile/internal/walk/convert.go b/src/cmd/compile/internal/walk/convert.go index 5d69fc3868..ffc5fd19e8 100644 --- a/src/cmd/compile/internal/walk/convert.go +++ b/src/cmd/compile/internal/walk/convert.go @@ -367,7 +367,7 @@ func rtconvfn(src, dst *types.Type) (param, result types.Kind) { if dst.IsFloat() { switch src.Kind() { case types.TINT64, types.TUINT64: - return src.Kind(), types.TFLOAT64 + return src.Kind(), dst.Kind() } } @@ -383,7 +383,7 @@ func rtconvfn(src, dst *types.Type) (param, result types.Kind) { if dst.IsFloat() { switch src.Kind() { case types.TINT64, types.TUINT64: - return src.Kind(), types.TFLOAT64 + return src.Kind(), dst.Kind() case types.TUINT32, types.TUINT, types.TUINTPTR: return types.TUINT32, types.TFLOAT64 } diff --git a/src/runtime/float_test.go b/src/runtime/float_test.go new file mode 100644 index 0000000000..b2aa43da59 --- /dev/null +++ b/src/runtime/float_test.go @@ -0,0 +1,25 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime_test + +import ( + "testing" +) + +func TestIssue48807(t *testing.T) { + for _, i := range []uint64{ + 0x8234508000000001, // from issue48807 + 1<<56 + 1<<32 + 1, + } { + got := float32(i) + dontwant := float32(float64(i)) + if got == dontwant { + // The test cases above should be uint64s such that + // this equality doesn't hold. These examples trigger + // the case where using an intermediate float64 doesn't work. + t.Errorf("direct float32 conversion doesn't work: arg=%x got=%x dontwant=%x", i, got, dontwant) + } + } +} diff --git a/src/runtime/vlrt.go b/src/runtime/vlrt.go index cf631bdcca..927b585a92 100644 --- a/src/runtime/vlrt.go +++ b/src/runtime/vlrt.go @@ -59,6 +59,36 @@ func uint64tofloat64(y uint64) float64 { return d } +func int64tofloat32(y int64) float32 { + if y < 0 { + return -uint64tofloat32(-uint64(y)) + } + return uint64tofloat32(uint64(y)) +} + +func uint64tofloat32(y uint64) float32 { + // divide into top 18, mid 23, and bottom 23 bits. + // (23-bit integers fit into a float32 without loss.) + top := uint32(y >> 46) + mid := uint32(y >> 23 & (1<<23 - 1)) + bot := uint32(y & (1<<23 - 1)) + if top == 0 { + return float32(mid)*(1<<23) + float32(bot) + } + if bot != 0 { + // Top is not zero, so the bits in bot + // won't make it into the final mantissa. + // In fact, the bottom bit of mid won't + // make it into the mantissa either. + // We only need to make sure that if top+mid + // is about to round down in a round-to-even + // scenario, and bot is not zero, we make it + // round up instead. + mid |= 1 + } + return float32(top)*(1<<46) + float32(mid)*(1<<23) +} + func _d2v(y *uint64, d float64) { x := *(*uint64)(unsafe.Pointer(&d)) -- GitLab From 77f2750f4398990eed972186706f160631d7dae4 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 2 Sep 2021 16:51:59 -0400 Subject: [PATCH 1511/2500] misc/wasm, cmd/link: do not let command line args overwrite global data On Wasm, wasm_exec.js puts command line arguments at the beginning of the linear memory (following the "zero page"). Currently there is no limit for this, and a very long command line can overwrite the program's data section. Prevent this by limiting the command line to 4096 bytes, and in the linker ensuring the data section starts at a high enough address (8192). (Arguably our address assignment on Wasm is a bit confusing. This is the minimum fix I can come up with.) Thanks to Ben Lubar for reporting this issue. Fixes #48797 Fixes CVE-2021-38297 Change-Id: I0f50fbb2a5b6d0d047e3c134a88988d9133e4ab3 Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1205933 Reviewed-by: Roland Shoemaker Reviewed-by: Than McIntosh Reviewed-on: https://go-review.googlesource.com/c/go/+/354571 Reviewed-by: Cherry Mui Reviewed-by: Heschi Kreinick Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot --- misc/wasm/wasm_exec.js | 7 +++++++ src/cmd/link/internal/ld/data.go | 11 ++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/misc/wasm/wasm_exec.js b/misc/wasm/wasm_exec.js index 22b19fbe80..e2f3cda995 100644 --- a/misc/wasm/wasm_exec.js +++ b/misc/wasm/wasm_exec.js @@ -568,6 +568,13 @@ offset += 8; }); + // The linker guarantees global data starts from at least wasmMinDataAddr. + // Keep in sync with cmd/link/internal/ld/data.go:wasmMinDataAddr. + const wasmMinDataAddr = 4096 + 4096; + if (offset >= wasmMinDataAddr) { + throw new Error("command line too long"); + } + this._inst.exports.run(argc, argv); if (this.exited) { this._resolveExitPromise(); diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 4f0ce23ce7..45e0e08793 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -2442,6 +2442,11 @@ func splitTextSections(ctxt *Link) bool { return (ctxt.IsPPC64() || (ctxt.IsARM64() && ctxt.IsDarwin())) && ctxt.IsExternal() } +// On Wasm, we reserve 4096 bytes for zero page, then 4096 bytes for wasm_exec.js +// to store command line args. Data sections starts from at least address 8192. +// Keep in sync with wasm_exec.js. +const wasmMinDataAddr = 4096 + 4096 + // address assigns virtual addresses to all segments and sections and // returns all segments in file order. func (ctxt *Link) address() []*sym.Segment { @@ -2451,10 +2456,14 @@ func (ctxt *Link) address() []*sym.Segment { order = append(order, &Segtext) Segtext.Rwx = 05 Segtext.Vaddr = va - for _, s := range Segtext.Sections { + for i, s := range Segtext.Sections { va = uint64(Rnd(int64(va), int64(s.Align))) s.Vaddr = va va += s.Length + + if ctxt.IsWasm() && i == 0 && va < wasmMinDataAddr { + va = wasmMinDataAddr + } } Segtext.Length = va - uint64(*FlagTextAddr) -- GitLab From 7286502b0d225b995d391c72efbaa7690ad023a9 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 7 Oct 2021 14:23:54 -0400 Subject: [PATCH 1512/2500] test/fixedbugs: fix issue48784.go to pass with -G=0 This test is currently failing in the longtest builders. I do not know how or why the builders are adding the -G=0 parameter. Updates #48784 Change-Id: I62248d3fbc47567a8c73b4868a2d4aeb0bc47bc3 Reviewed-on: https://go-review.googlesource.com/c/go/+/354631 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills Reviewed-by: Robert Griesemer Reviewed-by: Matthew Dempsky TryBot-Result: Go Bot --- test/fixedbugs/issue48784.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/fixedbugs/issue48784.go b/test/fixedbugs/issue48784.go index 6048518df2..b07f524305 100644 --- a/test/fixedbugs/issue48784.go +++ b/test/fixedbugs/issue48784.go @@ -15,9 +15,9 @@ var t T var a [1]int var ( - _ = s == nil // ERROR "invalid operation:.*mismatched types string and untyped nil" - _ = b == nil // ERROR "invalid operation:.*mismatched types bool and untyped nil" - _ = i == nil // ERROR "invalid operation:.*mismatched types int and untyped nil" - _ = t == nil // ERROR "invalid operation:.*mismatched types T and untyped nil" - _ = a == nil // ERROR "invalid operation:.*mismatched types \[1\]int and untyped nil" + _ = s == nil // ERROR "invalid operation:.*mismatched types string and (untyped )?nil" + _ = b == nil // ERROR "invalid operation:.*mismatched types bool and (untyped )?nil" + _ = i == nil // ERROR "invalid operation:.*mismatched types int and (untyped )?nil" + _ = t == nil // ERROR "invalid operation:.*mismatched types T and (untyped )?nil" + _ = a == nil // ERROR "invalid operation:.*mismatched types \[1\]int and (untyped )?nil" ) -- GitLab From 4ab3c1065eb38b90247f7ad46160fc5bb07ca2ed Mon Sep 17 00:00:00 2001 From: Jinwen Wo Date: Thu, 7 Oct 2021 17:24:47 +0000 Subject: [PATCH 1513/2500] cmd/go/internal/web: improve IP check testing on ipv6 env The existing implementation lacks consideration of running test on a machine which has ipv6 address but no ipv4 address. Use net.IP.IsLoopback and net.IP.IsUnspecified instead of hardcoded addresses. Fixes: #48575 This PR will be imported into Gerrit with the title and first comment (this text) used to generate the subject and body of the Gerrit change. Change-Id: I9c3c26d2ba13c7a24065751b59a1e002098ed654 GitHub-Last-Rev: fc45adbf7b944122d8f07bd451a8eeed1e69140c GitHub-Pull-Request: golang/go#48850 Reviewed-on: https://go-review.googlesource.com/c/go/+/354609 Reviewed-by: Bryan C. Mills Reviewed-by: Jay Conrod Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Trust: Jay Conrod --- src/cmd/go/internal/web/http.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/cmd/go/internal/web/http.go b/src/cmd/go/internal/web/http.go index f177278eba..81f841d2c6 100644 --- a/src/cmd/go/internal/web/http.go +++ b/src/cmd/go/internal/web/http.go @@ -17,6 +17,7 @@ import ( "errors" "fmt" "mime" + "net" "net/http" urlpkg "net/url" "os" @@ -84,8 +85,15 @@ func get(security SecurityMode, url *urlpkg.URL) (*Response, error) { if url.Host == "localhost.localdev" { return nil, fmt.Errorf("no such host localhost.localdev") } - if os.Getenv("TESTGONETWORK") == "panic" && !strings.HasPrefix(url.Host, "127.0.0.1") && !strings.HasPrefix(url.Host, "0.0.0.0") { - panic("use of network: " + url.String()) + if os.Getenv("TESTGONETWORK") == "panic" { + host := url.Host + if h, _, err := net.SplitHostPort(url.Host); err == nil && h != "" { + host = h + } + addr := net.ParseIP(host) + if addr == nil || (!addr.IsLoopback() && !addr.IsUnspecified()) { + panic("use of network: " + url.String()) + } } fetch := func(url *urlpkg.URL) (*urlpkg.URL, *http.Response, error) { -- GitLab From 0f52292e72ebbb79b2d41c8dca8e23ef9597e17d Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Thu, 7 Oct 2021 09:55:43 +0200 Subject: [PATCH 1514/2500] os: don't use wait6 on netbsd CL 315281 changed the os package use wait6 on netbsd. This seems to be causing frequent test failures as reported in #48789. Revert that change using wait6 on netbsd for now. Updates #13987 Updates #16028 For #48789 Change-Id: Ieddffc65611c7f449971eaa8ed6f4299a5f742c2 Reviewed-on: https://go-review.googlesource.com/c/go/+/354249 Trust: Tobias Klauser Trust: Bryan C. Mills Trust: Benny Siegert Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills Reviewed-by: Benny Siegert Reviewed-by: Ian Lance Taylor --- src/os/wait_unimp.go | 12 +++++++++--- src/os/wait_wait6.go | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/os/wait_unimp.go b/src/os/wait_unimp.go index 9bb85da802..c1f66ca155 100644 --- a/src/os/wait_unimp.go +++ b/src/os/wait_unimp.go @@ -2,8 +2,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build aix || darwin || (js && wasm) || openbsd || solaris -// +build aix darwin js,wasm openbsd solaris +// aix, darwin, js/wasm, openbsd and solaris don't implement +// waitid/wait6. netbsd implements wait6, but that is causing test +// failures, see issue #48789. + +//go:build aix || darwin || (js && wasm) || netbsd || openbsd || solaris +// +build aix darwin js,wasm netbsd openbsd solaris package os @@ -11,7 +15,9 @@ package os // succeed immediately, and reports whether it has done so. // It does not actually call p.Wait. // This version is used on systems that do not implement waitid, -// or where we have not implemented it yet. +// or where we have not implemented it yet. Note that this is racy: +// a call to Process.Signal can in an extremely unlikely case send a +// signal to the wrong process, see issue #13987. func (p *Process) blockUntilWaitable() (bool, error) { return false, nil } diff --git a/src/os/wait_wait6.go b/src/os/wait_wait6.go index 45b370a802..51193401f9 100644 --- a/src/os/wait_wait6.go +++ b/src/os/wait_wait6.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build dragonfly || freebsd || netbsd -// +build dragonfly freebsd netbsd +//go:build dragonfly || freebsd +// +build dragonfly freebsd package os -- GitLab From ef2ebbebf976fba17bb97ed285e9c3d10b192d74 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Wed, 6 Oct 2021 14:13:23 -0400 Subject: [PATCH 1515/2500] internal/fuzz: log that minimization is occurring Previously, when fuzzing for a period of time, the command line output would look something like this: fuzz: minimizing 34995-byte crash input... fuzz: elapsed: 3s, execs: 13821 (4604/sec), new interesting: 0 (total: 1) fuzz: elapsed: 6s, execs: 13821 (2303/sec), new interesting: 0 (total: 1) fuzz: elapsed: 9s, execs: 13821 (1535/sec), new interesting: 0 (total: 1) --- FAIL: FuzzFoo (9.05s) This is the same output it has while fuzzing, so if minimization runs for a long time (default allows 1 minute), then it looks like minimization is hanging. It's also confusing that the execs/sec would continually decrease. Now, when minimization is running, the command line output will look something like this: fuzz: minimizing 34995-byte crash input... fuzz: elapsed: 3s, minimizing fuzz: elapsed: 6s, minimizing fuzz: elapsed: 9s, minimizing fuzz: elapsed: 9s, minimizing --- FAIL: FuzzFoo (9.05s) The final "fuzz: elapsed: 6s, minimizing" could be printed twice because we always print one final log to the command line before we exit. Updates #48820 Change-Id: Ie5b9fde48b8d4e36e13a81ae50a6d69bf4d0dbe3 Reviewed-on: https://go-review.googlesource.com/c/go/+/354371 Trust: Katie Hockman Run-TryBot: Katie Hockman Reviewed-by: Jay Conrod --- .../go/testdata/script/test_fuzz_minimize.txt | 17 ++++++++++++++++ src/internal/fuzz/fuzz.go | 20 +++++++++++-------- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize.txt b/src/cmd/go/testdata/script/test_fuzz_minimize.txt index 3ef54aed93..727399f4bb 100644 --- a/src/cmd/go/testdata/script/test_fuzz_minimize.txt +++ b/src/cmd/go/testdata/script/test_fuzz_minimize.txt @@ -74,6 +74,12 @@ stdout FAIL # Test that re-running the unminimized value causes a crash. ! go test -run=FuzzMinimizerRecoverable minimizer_test.go +! go test -fuzz=FuzzMinimizerTooSlow -run=FuzzMinimizerTooSlow -fuzzminimizetime=3s minimizer_test.go +stdout 'fuzz: minimizing' +stdout 'fuzz: elapsed: 3s, minimizing' +stdout 'testdata[/\\]fuzz[/\\]FuzzMinimizerTooSlow[/\\]' +stdout FAIL + # TODO(jayconrod,katiehockman): add a test which verifies that the right bytes # are written to testdata in the case of an interrupt during minimization. @@ -87,6 +93,7 @@ package fuzz_test import ( "os" "testing" + "time" ) func FuzzMinimizeZeroDurationSet(f *testing.F) { @@ -142,6 +149,16 @@ func FuzzMinimizerNonrecoverable(f *testing.F) { } }) } + +func FuzzMinimizerTooSlow(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + if len(b) > 50 { + t.Error("error here") + time.Sleep(2 * time.Second) + } + }) +} + -- check_testdata.go -- // +build ignore diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 2c2a365f4c..f660052911 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -136,13 +136,12 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err // Ensure that any crash we find is written to the corpus, even if an error // or interruption occurs while minimizing it. - var crashMinimizing *fuzzResult crashWritten := false defer func() { - if crashMinimizing == nil || crashWritten { + if c.crashMinimizing == nil || crashWritten { return } - fileName, werr := writeToCorpus(crashMinimizing.entry.Data, opts.CorpusDir) + fileName, werr := writeToCorpus(c.crashMinimizing.entry.Data, opts.CorpusDir) if werr != nil { err = fmt.Errorf("%w\n%v", err, werr) return @@ -150,7 +149,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err if err == nil { err = &crashError{ name: filepath.Base(fileName), - err: errors.New(crashMinimizing.crasherMsg), + err: errors.New(c.crashMinimizing.crasherMsg), } } }() @@ -198,7 +197,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err for { var inputC chan fuzzInput input, ok := c.peekInput() - if ok && crashMinimizing == nil && !stopping { + if ok && c.crashMinimizing == nil && !stopping { inputC = c.inputC } @@ -236,7 +235,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err break } if c.canMinimize() && result.canMinimize { - if crashMinimizing != nil { + if c.crashMinimizing != nil { // This crash is not minimized, and another crash is being minimized. // Ignore this one and wait for the other one to finish. break @@ -244,7 +243,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err // Found a crasher but haven't yet attempted to minimize it. // Send it back to a worker for minimization. Disable inputC so // other workers don't continue fuzzing. - crashMinimizing = &result + c.crashMinimizing = &result fmt.Fprintf(c.opts.Log, "fuzz: minimizing %d-byte crash input...\n", len(result.entry.Data)) c.queueForMinimization(result, nil) } else if !crashWritten { @@ -308,7 +307,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err // number of new edges that this result expanded. // TODO(jayconrod, katiehockman): Don't write a value that's already // in the corpus. - if c.canMinimize() && result.canMinimize && crashMinimizing == nil { + if c.canMinimize() && result.canMinimize && c.crashMinimizing == nil { // Send back to workers to find a smaller value that preserves // at least one new coverage bit. c.queueForMinimization(result, keepCoverage) @@ -604,6 +603,9 @@ type coordinator struct { // same thing. minimizeQueue queue + // crashMinimizing is the crash that is currently being minimized. + crashMinimizing *fuzzResult + // coverageMask aggregates coverage that was found for all inputs in the // corpus. Each byte represents a single basic execution block. Each set bit // within the byte indicates that an input has triggered that block at least @@ -692,6 +694,8 @@ func (c *coordinator) logStats() { } else { fmt.Fprintf(c.opts.Log, "fuzz: elapsed: %s, testing seed corpus: %d/%d completed\n", c.elapsed(), runSoFar, c.warmupInputCount) } + } else if c.crashMinimizing != nil { + fmt.Fprintf(c.opts.Log, "fuzz: elapsed: %s, minimizing\n", c.elapsed()) } else { rate := float64(c.count-c.countLastLog) / now.Sub(c.timeLastLog).Seconds() if coverageEnabled { -- GitLab From 6b4cf2be9385ea25fed011f7c862d9e023b71df6 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Thu, 30 Sep 2021 15:45:29 -0700 Subject: [PATCH 1516/2500] cmd/compile: improving printing of type names in func/meth instantiations Change to using types.(*Type).LinkString() for printing names of types in function/method instantiations. (e.g. f[int] or Value[p.Myint].Set()) LinkString already generates a unique string description for t, using package paths, except that it uses "" for the local package path. The "" will be expanded in the linker, so the names in the executable will have full package paths everywhere and de-duplication of function/method instantiations will work properly. We do need to add an explicit substitution of "" in ReadImports() for function/method names. We previously were using NameString(), which doesn't use full package paths, so is not fully unique. We had also discussed that we would prefer to minimize spaces in function/method instantiation names. So, I changed LinkString() to eliminate all unneeded spaces. In the one case where we need a separator, which is between field names and types, we use a "#" instead of a space. This change has the advantage of eliminating spaces in some existing non-generic function name - mainly .type.eq functions for anonymous types (e.g. "type..eq.struct { runtime.gList; runtime.n int32 }") shows up in a hello-world executable (as Cherry pointed out). We do not need an analogous function for types2 right now, since we create all instantiations using types1 types. In the one case where we need to create an instantiation during types2-to-types1 translation, we convert the types to types1 first (see (*irgen).instTypeName2). Change-Id: Iac4748fa0d0d6f89af59bd51076266986daee945 Reviewed-on: https://go-review.googlesource.com/c/go/+/353609 Trust: Dan Scales Run-TryBot: Dan Scales Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/typecheck/iimport.go | 11 ++++- src/cmd/compile/internal/typecheck/subr.go | 14 +++--- src/cmd/compile/internal/types/fmt.go | 47 +++++++++++++++---- 3 files changed, 53 insertions(+), 19 deletions(-) diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 77119ce9bd..01ac1679b2 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -188,9 +188,18 @@ func ReadImports(pkg *types.Pkg, data string) { // Inline body index. for nPkgs := ird.uint64(); nPkgs > 0; nPkgs-- { pkg := p.pkgAt(ird.uint64()) + pkgPrefix := pkg.Prefix + "." for nSyms := ird.uint64(); nSyms > 0; nSyms-- { - s := pkg.Lookup(p.stringAt(ird.uint64())) + s2 := p.stringAt(ird.uint64()) + // Function/method instantiation names may include "" to + // represent the path name of the imported package (in type + // names), so replace "" with pkg.Prefix. The "" in the names + // will get replaced by the linker as well, so will not + // appear in the executable. Include the dot to avoid + // matching with struct tags ending in '"'. + s2 = strings.Replace(s2, "\"\".", pkgPrefix, -1) + s := pkg.Lookup(s2) off := ird.uint64() if _, ok := inlineImporter[s]; !ok { diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 56e6ec0e27..68240329f5 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -919,14 +919,11 @@ func addTargs(b *bytes.Buffer, targs []*types.Type) { if i > 0 { b.WriteByte(',') } - // Use NameString(), which includes the package name for the local - // package, to make sure that type arguments (including type params), - // are uniquely specified. - tstring := targ.NameString() - // types1 uses "interface {" and types2 uses "interface{" - convert - // to consistent types2 format. Same for "struct {" - tstring = strings.Replace(tstring, "interface {", "interface{", -1) - tstring = strings.Replace(tstring, "struct {", "struct{", -1) + // Make sure that type arguments (including type params), are + // uniquely specified. LinkString() eliminates all spaces + // and includes the package path (local package path is "" before + // linker substitution). + tstring := targ.LinkString() b.WriteString(tstring) } b.WriteString("]") @@ -1440,6 +1437,7 @@ func Shapify(t *types.Type, index int) *types.Type { return s } + // LinkString specifies the type uniquely, but has no spaces. nm := fmt.Sprintf("%s_%d", u.LinkString(), index) sym := types.ShapePkg.Lookup(nm) if sym.Def != nil { diff --git a/src/cmd/compile/internal/types/fmt.go b/src/cmd/compile/internal/types/fmt.go index 2f81c7b2e1..c70e22c946 100644 --- a/src/cmd/compile/internal/types/fmt.go +++ b/src/cmd/compile/internal/types/fmt.go @@ -64,7 +64,7 @@ var NumImport = make(map[string]int) // The default is regular Go syntax (fmtGo). // fmtDebug is like fmtGo but for debugging dumps and prints the type kind too. // fmtTypeID and fmtTypeIDName are for generating various unique representations -// of types used in hashes and the linker. +// of types used in hashes, the linker, and function/method instantiations. type fmtMode int const ( @@ -461,15 +461,25 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type case TINTER: if t.IsEmptyInterface() { - b.WriteString("interface {}") + if mode == fmtTypeID { + b.WriteString("interface{}") + } else { + b.WriteString("interface {}") + } break } - b.WriteString("interface {") + if mode == fmtTypeID { + b.WriteString("interface{") + } else { + b.WriteString("interface {") + } for i, f := range t.AllMethods().Slice() { if i != 0 { b.WriteByte(';') } - b.WriteByte(' ') + if mode != fmtTypeID { + b.WriteByte(' ') + } switch { case f.Sym == nil: // Check first that a symbol is defined for this type. @@ -485,7 +495,7 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type } tconv2(b, f.Type, 'S', mode, visited) } - if t.AllMethods().Len() != 0 { + if t.AllMethods().Len() != 0 && mode != fmtTypeID { b.WriteByte(' ') } b.WriteByte('}') @@ -560,15 +570,21 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type } b.WriteByte(byte(close)) } else { - b.WriteString("struct {") + if mode == fmtTypeID { + b.WriteString("struct{") + } else { + b.WriteString("struct {") + } for i, f := range t.Fields().Slice() { if i != 0 { b.WriteByte(';') } - b.WriteByte(' ') + if mode != fmtTypeID { + b.WriteByte(' ') + } fldconv(b, f, 'L', mode, visited, funarg) } - if t.NumFields() != 0 { + if t.NumFields() != 0 && mode != fmtTypeID { b.WriteByte(' ') } b.WriteByte('}') @@ -652,7 +668,14 @@ func fldconv(b *bytes.Buffer, f *Field, verb rune, mode fmtMode, visited map[*Ty if name != "" { b.WriteString(name) - b.WriteString(" ") + if mode == fmtTypeID { + // This is the one case where we can't omit the space, since + // we need a separate between field name and type, so we use + // "#" instead. + b.WriteString("#") + } else { + b.WriteString(" ") + } } if f.IsDDD() { @@ -667,7 +690,11 @@ func fldconv(b *bytes.Buffer, f *Field, verb rune, mode fmtMode, visited map[*Ty } if verb != 'S' && funarg == FunargNone && f.Note != "" { - b.WriteString(" ") + if mode != fmtTypeID { + b.WriteString(" ") + } + // TODO: for fmtTypeID, we should possibly using %-quoting, so + // space is %20, etc. b.WriteString(strconv.Quote(f.Note)) } } -- GitLab From b69f823ece741f21d06591657f4e0a5b17d492e3 Mon Sep 17 00:00:00 2001 From: Caleb Spare Date: Fri, 25 Jun 2021 13:40:30 -0700 Subject: [PATCH 1517/2500] testing: with -benchtime=1x, run the benchmark loop exactly once Like with -benchtime=1ns, if we find that the "discovery" round (run1) has already crossed the -benchtime threshold, we skip running more iterations. Fixes #32051 Change-Id: I76aaef2ba521ba8ad6bbde2b14977e191aada5e4 Reviewed-on: https://go-review.googlesource.com/c/go/+/331089 Trust: Caleb Spare Run-TryBot: Caleb Spare TryBot-Result: Go Bot Reviewed-by: Emmanuel Odeke --- .../go/testdata/script/test_benchmark_1x.txt | 37 +++++++++++++++++++ src/testing/benchmark.go | 7 +++- 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 src/cmd/go/testdata/script/test_benchmark_1x.txt diff --git a/src/cmd/go/testdata/script/test_benchmark_1x.txt b/src/cmd/go/testdata/script/test_benchmark_1x.txt new file mode 100644 index 0000000000..b1d4c39c16 --- /dev/null +++ b/src/cmd/go/testdata/script/test_benchmark_1x.txt @@ -0,0 +1,37 @@ +# Test that -benchtime 1x only runs a total of 1 loop iteration. +# See golang.org/issue/32051. + +go test -run ^$ -bench . -benchtime 1x + +-- go.mod -- +module bench + +go 1.16 +-- x_test.go -- +package bench + +import ( + "fmt" + "os" + "testing" +) + +var called = false + +func TestMain(m *testing.M) { + m.Run() + if !called { + fmt.Println("benchmark never called") + os.Exit(1) + } +} + +func Benchmark(b *testing.B) { + if b.N > 1 { + b.Fatalf("called with b.N=%d; want b.N=1 only", b.N) + } + if called { + b.Fatal("called twice") + } + called = true +} diff --git a/src/testing/benchmark.go b/src/testing/benchmark.go index 30fa106dd4..1ce637e137 100644 --- a/src/testing/benchmark.go +++ b/src/testing/benchmark.go @@ -299,7 +299,12 @@ func (b *B) launch() { // Run the benchmark for at least the specified amount of time. if b.benchTime.n > 0 { - b.runN(b.benchTime.n) + // We already ran a single iteration in run1. + // If -benchtime=1x was requested, use that result. + // See https://golang.org/issue/32051. + if b.benchTime.n > 1 { + b.runN(b.benchTime.n) + } } else { d := b.benchTime.d for n := int64(1); !b.failed && b.duration < d && n < 1e9; { -- GitLab From 6436f5c13d6a5ced6cd5f3873f83ebfae32cce36 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 7 Oct 2021 16:26:29 -0400 Subject: [PATCH 1518/2500] runtime: handle end PC in textAddr As the func table contains the end marker of the text section, we sometimes need to get that address from an offset. Currently textAddr doesn't handle that address, as it is not within any text section. Instead of letting the callers not call textAddr with the end offset, just handle it more elegantly in textAddr. For #48837. Change-Id: I6e97e455f6cb66e9680a7aac6152ba6f4cda2e12 Reviewed-on: https://go-review.googlesource.com/c/go/+/354635 Trust: Cherry Mui Trust: Josh Bleecher Snyder Run-TryBot: Cherry Mui Reviewed-by: Josh Bleecher Snyder --- src/runtime/symtab.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 2de518d2e6..e35d8047a1 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -623,9 +623,7 @@ func moduledataverify1(datap *moduledata) { } min := datap.textAddr(datap.ftab[0].entryoff) - // The max PC is outside of the text section. - // Subtract 1 to get a PC inside the text section, look it up, then add 1 back in. - max := datap.textAddr(datap.ftab[nftab].entryoff-1) + 1 + max := datap.textAddr(datap.ftab[nftab].entryoff) if datap.minpc != min || datap.maxpc != max { println("minpc=", hex(datap.minpc), "min=", hex(min), "maxpc=", hex(datap.maxpc), "max=", hex(max)) throw("minpc or maxpc invalid") @@ -660,9 +658,10 @@ func (md *moduledata) textAddr(off32 uint32) uintptr { off := uintptr(off32) res := md.text + off if len(md.textsectmap) > 1 { - for i := range md.textsectmap { - if off >= md.textsectmap[i].vaddr && off < md.textsectmap[i].end { - res = md.textsectmap[i].baseaddr + off - md.textsectmap[i].vaddr + for i, sect := range md.textsectmap { + // For the last section, include the end address (etext), as it is included in the functab. + if off >= sect.vaddr && off < sect.end || (i == len(md.textsectmap)-1 && off == sect.end) { + res = sect.baseaddr + off - sect.vaddr break } } -- GitLab From 1ceb72394e250d5776726bba63c34cd2be5745d1 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 7 Oct 2021 16:33:43 -0400 Subject: [PATCH 1519/2500] cmd/link: mark holes in functab with end PC-1 When we have multiple text sections, we need to mark holes between the sections in the functab. A hole is marked with an entry with the end PC of the previous section. As we now use offsets instead of (relocated) PCs, the end offset of a section may be the same of the start of the next one. Distinguish it by using the end address -1. For #48837. Change-Id: I121aac53b32a869378632cf151cb1b6f98ad3089 Reviewed-on: https://go-review.googlesource.com/c/go/+/354636 Trust: Cherry Mui Trust: Josh Bleecher Snyder Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Josh Bleecher Snyder --- src/cmd/link/internal/ld/pcln.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index ee26ee27a0..465c52b6cf 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -631,9 +631,11 @@ func writePCToFunc(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, sta if thisSect := ldr.SymSect(s); thisSect != prevSect { // With multiple text sections, there may be a hole here in the // address space. We use an invalid funcoff value to mark the hole. + // Use the end PC - 1 to distinguish the end of a section vs. the + // start of the next. // See also runtime/symtab.go:findfunc prevFuncSize := uint32(ldr.SymSize(prevFunc)) - sb.SetUint32(ctxt.Arch, int64(funcIndex*2*4), pcOff(prevFunc)+prevFuncSize) + sb.SetUint32(ctxt.Arch, int64(funcIndex*2*4), pcOff(prevFunc)+prevFuncSize-1) sb.SetUint32(ctxt.Arch, int64((funcIndex*2+1)*4), ^uint32(0)) funcIndex++ prevSect = thisSect -- GitLab From 7cef83162bbe0008f3e158297b94a7dead64a9b1 Mon Sep 17 00:00:00 2001 From: Pedro Lopez Mareque Date: Thu, 7 Oct 2021 07:34:47 +0200 Subject: [PATCH 1520/2500] unicode: use IsSpace not IsUpper in IsSpace example test Change-Id: Ie3017e5507f57cbb2ae9c8b737b378cef91fefeb Reviewed-on: https://go-review.googlesource.com/c/go/+/354509 Reviewed-by: Emmanuel Odeke Reviewed-by: Ian Lance Taylor Run-TryBot: Emmanuel Odeke TryBot-Result: Go Bot --- src/unicode/example_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/unicode/example_test.go b/src/unicode/example_test.go index 416ad1fe08..d3a47aca91 100644 --- a/src/unicode/example_test.go +++ b/src/unicode/example_test.go @@ -247,7 +247,7 @@ func ExampleIsSpace() { fmt.Printf("%t\n", unicode.IsSpace(' ')) fmt.Printf("%t\n", unicode.IsSpace('\n')) fmt.Printf("%t\n", unicode.IsSpace('\t')) - fmt.Printf("%t\n", unicode.IsUpper('a')) + fmt.Printf("%t\n", unicode.IsSpace('a')) // Output: // true // true -- GitLab From 5780be401fbf1c4766f45301e727fde4a89ac2cc Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 7 Oct 2021 15:53:32 -0700 Subject: [PATCH 1521/2500] cmd/compile/internal/types2: partial revert of incorrect unification "fix" The "fix" (CL 352832) for #48619 was incorrect and broke the unification algorithm in some cases (e.g., #48695). This CL reverts the changes made by CL 352832 to unify.go, and comments out code in corresponding tests. As a result, #48695 will be fixed, and we will re-open #48619. Fixes #48695. For #48619. For #48656. Change-Id: I91bc492062dbcc8dae7626f6b33f6dfabf48bcb8 Reviewed-on: https://go-review.googlesource.com/c/go/+/354690 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- .../types2/testdata/fixedbugs/issue48619.go2 | 18 +++++++------ .../types2/testdata/fixedbugs/issue48656.go2 | 11 ++++---- .../types2/testdata/fixedbugs/issue48695.go2 | 14 ++++++++++ src/cmd/compile/internal/types2/unify.go | 26 +++---------------- 4 files changed, 32 insertions(+), 37 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue48695.go2 diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48619.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48619.go2 index 24650a3a70..870bacd0bd 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48619.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48619.go2 @@ -2,21 +2,23 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// This issue has been re-opened. + package p func f[P any](a, _ P) { - var x int - f(a, x /* ERROR type int of x does not match P */) - f(x, a /* ERROR type P of a does not match inferred type int for P */) + // var x int + // f(a, x /* ERROR type int of x does not match P */) + // f(x, a /* ERROR type P of a does not match inferred type int for P */) } func g[P any](a, b P) { - g(a, b) - g(&a, &b) - g([]P{}, []P{}) + // g(a, b) + // g(&a, &b) + // g([]P{}, []P{}) } func h[P any](a, b P) { - h(&a, &b) - h([]P{a}, []P{b}) + // h(&a, &b) + // h([]P{a}, []P{b}) } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48656.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48656.go2 index 7d292e0cc4..652f8ce37a 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48656.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48656.go2 @@ -2,12 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package p +// This issue is still open. -// TODO(gri) Still need better error positions and message here. -// But this doesn't crash anymore. +package p -func f[P /* ERROR does not match \*Q */ interface{*Q}, Q any](p P, q Q) { - _ = f[P] - _ = f[/* ERROR cannot infer P */ *P] +func f[P *Q, Q any](p P, q Q) { + // _ = f[P] + // _ = f[/* ERROR cannot infer P */ *P] } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48695.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48695.go2 new file mode 100644 index 0000000000..9f4a76851d --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48695.go2 @@ -0,0 +1,14 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func g[P ~func(T) P, T any](P) {} + +func _() { + type F func(int) F + var f F + g(f) + _ = g[F] +} diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index ee41264116..a252c5e1a5 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -63,10 +63,6 @@ func (u *unifier) unify(x, y Type) bool { type tparamsList struct { unifier *unifier tparams []*TypeParam - // For each tparams element, there is a corresponding mask bit in masks. - // If set, the corresponding type parameter is masked and doesn't appear - // as a type parameter with tparamsList.index. - masks []bool // For each tparams element, there is a corresponding type slot index in indices. // index < 0: unifier.types[-index-1] == nil // index == 0: no type slot allocated yet @@ -107,14 +103,9 @@ func (d *tparamsList) init(tparams []*TypeParam) { } } d.tparams = tparams - d.masks = make([]bool, len(tparams)) d.indices = make([]int, len(tparams)) } -// mask and unmask permit the masking/unmasking of the i'th type parameter of d. -func (d *tparamsList) mask(i int) { d.masks[i] = true } -func (d *tparamsList) unmask(i int) { d.masks[i] = false } - // join unifies the i'th type parameter of x with the j'th type parameter of y. // If both type parameters already have a type associated with them and they are // not joined, join fails and returns false. @@ -158,13 +149,11 @@ func (u *unifier) join(i, j int) bool { return true } -// If typ is an unmasked type parameter of d, index returns the type parameter index. +// If typ is a type parameter of d, index returns the type parameter index. // Otherwise, the result is < 0. func (d *tparamsList) index(typ Type) int { if tpar, ok := typ.(*TypeParam); ok { - if i := tparamIndex(d.tparams, tpar); i >= 0 && !d.masks[i] { - return i - } + return tparamIndex(d.tparams, tpar) } return -1 } @@ -257,7 +246,7 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { } } - // Cases where at least one of x or y is an (unmasked) type parameter. + // Cases where at least one of x or y is a type parameter. switch i, j := u.x.index(x), u.y.index(y); { case i >= 0 && j >= 0: // both x and y are type parameters @@ -270,12 +259,6 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { case i >= 0: // x is a type parameter, y is not if tx := u.x.at(i); tx != nil { - // The inferred type tx may be or contain x again but we don't - // want to "unpack" it again when unifying tx with y: tx is the - // inferred type. Mask type parameter x for this recursion, so - // that subsequent encounters treat x like an ordinary type. - u.x.mask(i) - defer u.x.unmask(i) return u.nifyEq(tx, y, p) } // otherwise, infer type from y @@ -285,9 +268,6 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { case j >= 0: // y is a type parameter, x is not if ty := u.y.at(j); ty != nil { - // see comment above - u.y.mask(j) - defer u.y.unmask(j) return u.nifyEq(x, ty, p) } // otherwise, infer type from x -- GitLab From 78d749fbe978bf6eac9c5e11aa4641dc126c9128 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 7 Oct 2021 17:02:53 -0700 Subject: [PATCH 1522/2500] go/types: partial revert of incorrect unification "fix" This is a port of CL 354690 from types2 to go/types. Change-Id: I50e7297a67e37d261335260e285b9cb1c0d2a62d Reviewed-on: https://go-review.googlesource.com/c/go/+/354691 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- .../types/testdata/fixedbugs/issue48619.go2 | 18 +++++++------ .../types/testdata/fixedbugs/issue48656.go2 | 11 ++++---- .../types/testdata/fixedbugs/issue48695.go2 | 14 ++++++++++ src/go/types/unify.go | 26 +++---------------- 4 files changed, 32 insertions(+), 37 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue48695.go2 diff --git a/src/go/types/testdata/fixedbugs/issue48619.go2 b/src/go/types/testdata/fixedbugs/issue48619.go2 index 24650a3a70..870bacd0bd 100644 --- a/src/go/types/testdata/fixedbugs/issue48619.go2 +++ b/src/go/types/testdata/fixedbugs/issue48619.go2 @@ -2,21 +2,23 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// This issue has been re-opened. + package p func f[P any](a, _ P) { - var x int - f(a, x /* ERROR type int of x does not match P */) - f(x, a /* ERROR type P of a does not match inferred type int for P */) + // var x int + // f(a, x /* ERROR type int of x does not match P */) + // f(x, a /* ERROR type P of a does not match inferred type int for P */) } func g[P any](a, b P) { - g(a, b) - g(&a, &b) - g([]P{}, []P{}) + // g(a, b) + // g(&a, &b) + // g([]P{}, []P{}) } func h[P any](a, b P) { - h(&a, &b) - h([]P{a}, []P{b}) + // h(&a, &b) + // h([]P{a}, []P{b}) } diff --git a/src/go/types/testdata/fixedbugs/issue48656.go2 b/src/go/types/testdata/fixedbugs/issue48656.go2 index ee639e1042..52863d446b 100644 --- a/src/go/types/testdata/fixedbugs/issue48656.go2 +++ b/src/go/types/testdata/fixedbugs/issue48656.go2 @@ -2,12 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package p +// This issue is still open. -// TODO(gri) Still need better error positions and message here. -// But this doesn't crash anymore. +package p -func f[P /* ERROR does not match \*Q */ interface{*Q}, Q any](p P, q Q) { - _ = f[P] - _ = f /* ERROR cannot infer P */ [*P] +func f[P interface{*Q}, Q any](p P, q Q) { + // _ = f[P] + // _ = f[/* ERROR cannot infer P */ *P] } diff --git a/src/go/types/testdata/fixedbugs/issue48695.go2 b/src/go/types/testdata/fixedbugs/issue48695.go2 new file mode 100644 index 0000000000..2d9e6a5f3d --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue48695.go2 @@ -0,0 +1,14 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func g[P interface{~func(T) P}, T any](P) {} + +func _() { + type F func(int) F + var f F + g(f) + _ = g[F] +} diff --git a/src/go/types/unify.go b/src/go/types/unify.go index 984ba59e6d..99c9c9e614 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -63,10 +63,6 @@ func (u *unifier) unify(x, y Type) bool { type tparamsList struct { unifier *unifier tparams []*TypeParam - // For each tparams element, there is a corresponding mask bit in masks. - // If set, the corresponding type parameter is masked and doesn't appear - // as a type parameter with tparamsList.index. - masks []bool // For each tparams element, there is a corresponding type slot index in indices. // index < 0: unifier.types[-index-1] == nil // index == 0: no type slot allocated yet @@ -107,14 +103,9 @@ func (d *tparamsList) init(tparams []*TypeParam) { } } d.tparams = tparams - d.masks = make([]bool, len(tparams)) d.indices = make([]int, len(tparams)) } -// mask and unmask permit the masking/unmasking of the i'th type parameter of d. -func (d *tparamsList) mask(i int) { d.masks[i] = true } -func (d *tparamsList) unmask(i int) { d.masks[i] = false } - // join unifies the i'th type parameter of x with the j'th type parameter of y. // If both type parameters already have a type associated with them and they are // not joined, join fails and returns false. @@ -158,13 +149,11 @@ func (u *unifier) join(i, j int) bool { return true } -// If typ is an unmasked type parameter of d, index returns the type parameter index. +// If typ is a type parameter of d, index returns the type parameter index. // Otherwise, the result is < 0. func (d *tparamsList) index(typ Type) int { if tpar, ok := typ.(*TypeParam); ok { - if i := tparamIndex(d.tparams, tpar); i >= 0 && !d.masks[i] { - return i - } + return tparamIndex(d.tparams, tpar) } return -1 } @@ -257,7 +246,7 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { } } - // Cases where at least one of x or y is an (unmasked) type parameter. + // Cases where at least one of x or y is a type parameter. switch i, j := u.x.index(x), u.y.index(y); { case i >= 0 && j >= 0: // both x and y are type parameters @@ -270,12 +259,6 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { case i >= 0: // x is a type parameter, y is not if tx := u.x.at(i); tx != nil { - // The inferred type tx may be or contain x again but we don't - // want to "unpack" it again when unifying tx with y: tx is the - // inferred type. Mask type parameter x for this recursion, so - // that subsequent encounters treat x like an ordinary type. - u.x.mask(i) - defer u.x.unmask(i) return u.nifyEq(tx, y, p) } // otherwise, infer type from y @@ -285,9 +268,6 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { case j >= 0: // y is a type parameter, x is not if ty := u.y.at(j); ty != nil { - // see comment above - u.y.mask(j) - defer u.y.unmask(j) return u.nifyEq(x, ty, p) } // otherwise, infer type from x -- GitLab From 8c4ea3140e7c79d828fe7683a3dfe3474a9938fb Mon Sep 17 00:00:00 2001 From: Nigel Tao Date: Fri, 8 Oct 2021 10:33:47 +1100 Subject: [PATCH 1523/2500] image/png: fix interlaced palette out-of-bounds PNG images can be paletted, where each pixel value (a uint8) indexes a slice of colors. In terms of wire format, the PLTE chunk explicitly contains the palette length. However, in practice, some arguably malformed images contain pixel values greater than or equal to the explicit PLTE length. Go's image/png decoder accomodates such images by lengthening the decoded image's palette if the implicit maximum is larger than the explicit maximum. This was already done, prior to this commit, by the "if len(paletted.Palette) <= int(idx)" lines in decoder.readImagePass. Separately, PNG images can also be interlaced, where the final image is the result of merging multiple partial images, also called passes. Prior to this commit, we applied the palette lengthening to the pass images but not the final image. This commit fixes that. Fixes #48612 Change-Id: I77606538cc9a504fbd726071756ebcd10c9da73f Reviewed-on: https://go-review.googlesource.com/c/go/+/354709 Trust: Nigel Tao Reviewed-by: Andrew Gerrand --- src/image/png/reader.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/image/png/reader.go b/src/image/png/reader.go index 910520bd4b..4c65038cb5 100644 --- a/src/image/png/reader.go +++ b/src/image/png/reader.go @@ -821,9 +821,17 @@ func (d *decoder) mergePassInto(dst image.Image, src image.Image, pass int) { dstPix, stride, rect = target.Pix, target.Stride, target.Rect bytesPerPixel = 8 case *image.Paletted: - srcPix = src.(*image.Paletted).Pix + source := src.(*image.Paletted) + srcPix = source.Pix dstPix, stride, rect = target.Pix, target.Stride, target.Rect bytesPerPixel = 1 + if len(target.Palette) < len(source.Palette) { + // readImagePass can return a paletted image whose implicit palette + // length (one more than the maximum Pix value) is larger than the + // explicit palette length (what's in the PLTE chunk). Make the + // same adjustment here. + target.Palette = source.Palette + } case *image.RGBA: srcPix = src.(*image.RGBA).Pix dstPix, stride, rect = target.Pix, target.Stride, target.Rect -- GitLab From e74db46519a7cbed16a7f14932da2ef93d647ece Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Thu, 7 Oct 2021 19:12:16 -0400 Subject: [PATCH 1524/2500] go/types: use an identifier map rather than isubst for recv type params Receiver type parameters are the only type expressions allowed to be blank. Previously this was handled by substitution of synthetic non-blank names in the receiver type expression, but that introduced problems related to AST mangling: the scope had extra elements, Object.Name() was inaccurate, and synthetic nodes were recorded in types.Info. Fix this instead by recording a map of *ast.Ident->*TypeParam on the Checker, which is read in Checker.ident to resolve blank identifiers denoting receiver type parameters. Change-Id: I6a7a86b823409f54778c0f141e8bd269a2cc85d9 Reviewed-on: https://go-review.googlesource.com/c/go/+/354643 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/check.go | 2 + src/go/types/signature.go | 86 ++++++++------------------------------- src/go/types/typexpr.go | 10 ++++- 3 files changed, 28 insertions(+), 70 deletions(-) diff --git a/src/go/types/check.go b/src/go/types/check.go index cfcdd68de3..fa3bd94681 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -106,6 +106,7 @@ type Checker struct { files []*ast.File // package files imports []*PkgName // list of imported packages dotImportMap map[dotImportKey]*PkgName // maps dot-imported objects to the package they were dot-imported through + rparamMap map[*ast.Ident]*TypeParam // maps blank receiver type params to their type firstErr error // first error encountered methods map[*TypeName][]*Func // maps package scope type names to associated non-blank (non-interface) methods @@ -283,6 +284,7 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) { check.dotImportMap = nil check.pkgPathMap = nil check.seenPkgMap = nil + check.rparamMap = nil // TODO(rFindley) There's more memory we should release at this point. diff --git a/src/go/types/signature.go b/src/go/types/signature.go index 9bb6ec2f4f..ae7818afdf 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -5,9 +5,7 @@ package types import ( - "fmt" "go/ast" - "go/internal/typeparams" "go/token" ) @@ -108,35 +106,29 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast sig.scope = check.scope defer check.closeScope() - var recvTyp ast.Expr // rewritten receiver type; valid if != nil if recvPar != nil && len(recvPar.List) > 0 { // collect generic receiver type parameters, if any // - a receiver type parameter is like any other type parameter, except that it is declared implicitly // - the receiver specification acts as local declaration for its type parameters, which may be blank _, rname, rparams := check.unpackRecv(recvPar.List[0].Type, true) if len(rparams) > 0 { - // Blank identifiers don't get declared and regular type-checking of the instantiated - // parameterized receiver type expression fails in Checker.collectParams of receiver. - // Identify blank type parameters and substitute each with a unique new identifier named - // "n_" (where n is the parameter index) and which cannot conflict with any user-defined - // name. - var smap map[*ast.Ident]*ast.Ident // substitution map from "_" to "n_" identifiers + sig.rparams = bindTParams(check.declareTypeParams(nil, rparams)) + // Blank identifiers don't get declared, so naive type-checking of the + // receiver type expression would fail in Checker.collectParams below, + // when Checker.ident cannot resolve the _ to a type. + // + // Checker.rparamMap maps these blank identifiers to their type parameter + // types, so that they may be resolved in Checker.ident when they fail + // lookup in the scope. for i, p := range rparams { if p.Name == "_" { - new := *p - new.Name = fmt.Sprintf("%d_", i) - rparams[i] = &new // use n_ identifier instead of _ so it can be looked up - if smap == nil { - smap = make(map[*ast.Ident]*ast.Ident) + tpar := sig.rparams.At(i) + if check.rparamMap == nil { + check.rparamMap = make(map[*ast.Ident]*TypeParam) } - smap[p] = &new + check.rparamMap[p] = tpar } } - if smap != nil { - // blank identifiers were found => use rewritten receiver type - recvTyp = isubst(recvPar.List[0].Type, smap) - } - sig.rparams = bindTParams(check.declareTypeParams(nil, rparams)) // determine receiver type to get its type parameters // and the respective type parameter bounds var recvTParams []*TypeParam @@ -183,9 +175,9 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast // declarations and then squash that scope into the parent scope (and report any redeclarations at // that time). scope := NewScope(check.scope, token.NoPos, token.NoPos, "function body (temp. scope)") - recvList, _ := check.collectParams(scope, recvPar, recvTyp, false) // use rewritten receiver type, if any - params, variadic := check.collectParams(scope, ftyp.Params, nil, true) - results, _ := check.collectParams(scope, ftyp.Results, nil, false) + recvList, _ := check.collectParams(scope, recvPar, false) + params, variadic := check.collectParams(scope, ftyp.Params, true) + results, _ := check.collectParams(scope, ftyp.Results, false) scope.squash(func(obj, alt Object) { check.errorf(obj, _DuplicateDecl, "%s redeclared in this block", obj.Name()) check.reportAltDecl(alt) @@ -267,8 +259,8 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast } // collectParams declares the parameters of list in scope and returns the corresponding -// variable list. If type0 != nil, it is used instead of the first type in list. -func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, type0 ast.Expr, variadicOk bool) (params []*Var, variadic bool) { +// variable list. +func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicOk bool) (params []*Var, variadic bool) { if list == nil { return } @@ -276,9 +268,6 @@ func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, type0 ast var named, anonymous bool for i, field := range list.List { ftype := field.Type - if i == 0 && type0 != nil { - ftype = type0 - } if t, _ := ftype.(*ast.Ellipsis); t != nil { ftype = t.Elt if variadicOk && i == len(list.List)-1 && len(field.Names) <= 1 { @@ -328,44 +317,3 @@ func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, type0 ast return } - -// isubst returns an x with identifiers substituted per the substitution map smap. -// isubst only handles the case of (valid) method receiver type expressions correctly. -func isubst(x ast.Expr, smap map[*ast.Ident]*ast.Ident) ast.Expr { - switch n := x.(type) { - case *ast.Ident: - if alt := smap[n]; alt != nil { - return alt - } - case *ast.StarExpr: - X := isubst(n.X, smap) - if X != n.X { - new := *n - new.X = X - return &new - } - case *ast.IndexExpr, *ast.IndexListExpr: - ix := typeparams.UnpackIndexExpr(x) - var newIndexes []ast.Expr - for i, index := range ix.Indices { - new := isubst(index, smap) - if new != index { - if newIndexes == nil { - newIndexes = make([]ast.Expr, len(ix.Indices)) - copy(newIndexes, ix.Indices) - } - newIndexes[i] = new - } - } - if newIndexes != nil { - return typeparams.PackIndexExpr(ix.X, ix.Lbrack, newIndexes, ix.Rbrack) - } - case *ast.ParenExpr: - return isubst(n.X, smap) // no need to keep parentheses - default: - // Other receiver type expressions are invalid. - // It's fine to ignore those here as they will - // be checked elsewhere. - } - return x -} diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index c4e4bc3dfe..f581effc19 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -30,7 +30,15 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool) switch obj { case nil: if e.Name == "_" { - check.error(e, _InvalidBlank, "cannot use _ as value or type") + // Blank identifiers are never declared, but the current identifier may + // be a placeholder for a receiver type parameter. In this case we can + // resolve its type and object from Checker.rparamMap. + if tpar := check.rparamMap[e]; tpar != nil { + x.mode = typexpr + x.typ = tpar + } else { + check.error(e, _InvalidBlank, "cannot use _ as value or type") + } } else { check.errorf(e, _UndeclaredName, "undeclared name: %s", e.Name) } -- GitLab From 5b9206f64ef4d8ea3201627cf9ba5c2b86e65022 Mon Sep 17 00:00:00 2001 From: Meng Zhuo Date: Sun, 26 Sep 2021 14:56:55 +0800 Subject: [PATCH 1525/2500] time: allow minimum int64 in ParseDuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ParseDuration should handle minimum int64 (-1<<63) nanosecond since type Duration is alias of int64 name old time/op new time/op delta ParseDuration 91.4ns ± 0% 86.4ns ± 1% -5.49% (p=0.000 n=9+8) Fixes: #48629 Change-Id: I81b7035b25cefb4c1e5b7801c20f2d335e29358a Reviewed-on: https://go-review.googlesource.com/c/go/+/352269 Trust: Meng Zhuo Run-TryBot: Meng Zhuo Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/time/format.go | 56 +++++++++++++++++++++---------------------- src/time/time_test.go | 27 +++++++++++++++++---- 2 files changed, 49 insertions(+), 34 deletions(-) diff --git a/src/time/format.go b/src/time/format.go index 464effdb43..5fb9cdc969 100644 --- a/src/time/format.go +++ b/src/time/format.go @@ -1402,10 +1402,7 @@ func parseSignedOffset(value string) int { if err != nil || value[1:] == rem { return 0 } - if sign == '-' { - x = -x - } - if x < -23 || 23 < x { + if x > 23 { return 0 } return len(value) - len(rem) @@ -1443,19 +1440,19 @@ func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string, var errLeadingInt = errors.New("time: bad [0-9]*") // never printed // leadingInt consumes the leading [0-9]* from s. -func leadingInt(s string) (x int64, rem string, err error) { +func leadingInt(s string) (x uint64, rem string, err error) { i := 0 for ; i < len(s); i++ { c := s[i] if c < '0' || c > '9' { break } - if x > (1<<63-1)/10 { + if x > 1<<63/10 { // overflow return 0, "", errLeadingInt } - x = x*10 + int64(c) - '0' - if x < 0 { + x = x*10 + uint64(c) - '0' + if x > 1<<63 { // overflow return 0, "", errLeadingInt } @@ -1466,7 +1463,7 @@ func leadingInt(s string) (x int64, rem string, err error) { // leadingFraction consumes the leading [0-9]* from s. // It is used only for fractions, so does not return an error on overflow, // it just stops accumulating precision. -func leadingFraction(s string) (x int64, scale float64, rem string) { +func leadingFraction(s string) (x uint64, scale float64, rem string) { i := 0 scale = 1 overflow := false @@ -1483,8 +1480,8 @@ func leadingFraction(s string) (x int64, scale float64, rem string) { overflow = true continue } - y := x*10 + int64(c) - '0' - if y < 0 { + y := x*10 + uint64(c) - '0' + if y > 1<<63 { overflow = true continue } @@ -1494,15 +1491,15 @@ func leadingFraction(s string) (x int64, scale float64, rem string) { return x, scale, s[i:] } -var unitMap = map[string]int64{ - "ns": int64(Nanosecond), - "us": int64(Microsecond), - "µs": int64(Microsecond), // U+00B5 = micro symbol - "μs": int64(Microsecond), // U+03BC = Greek letter mu - "ms": int64(Millisecond), - "s": int64(Second), - "m": int64(Minute), - "h": int64(Hour), +var unitMap = map[string]uint64{ + "ns": uint64(Nanosecond), + "us": uint64(Microsecond), + "µs": uint64(Microsecond), // U+00B5 = micro symbol + "μs": uint64(Microsecond), // U+03BC = Greek letter mu + "ms": uint64(Millisecond), + "s": uint64(Second), + "m": uint64(Minute), + "h": uint64(Hour), } // ParseDuration parses a duration string. @@ -1513,7 +1510,7 @@ var unitMap = map[string]int64{ func ParseDuration(s string) (Duration, error) { // [-+]?([0-9]*(\.[0-9]*)?[a-z]+)+ orig := s - var d int64 + var d uint64 neg := false // Consume [-+]? @@ -1533,7 +1530,7 @@ func ParseDuration(s string) (Duration, error) { } for s != "" { var ( - v, f int64 // integers before, after decimal point + v, f uint64 // integers before, after decimal point scale float64 = 1 // value = v + f/scale ) @@ -1581,7 +1578,7 @@ func ParseDuration(s string) (Duration, error) { if !ok { return 0, errors.New("time: unknown unit " + quote(u) + " in duration " + quote(orig)) } - if v > (1<<63-1)/unit { + if v > 1<<63/unit { // overflow return 0, errors.New("time: invalid duration " + quote(orig)) } @@ -1589,21 +1586,22 @@ func ParseDuration(s string) (Duration, error) { if f > 0 { // float64 is needed to be nanosecond accurate for fractions of hours. // v >= 0 && (f*unit/scale) <= 3.6e+12 (ns/h, h is the largest unit) - v += int64(float64(f) * (float64(unit) / scale)) - if v < 0 { + v += uint64(float64(f) * (float64(unit) / scale)) + if v > 1<<63 { // overflow return 0, errors.New("time: invalid duration " + quote(orig)) } } d += v - if d < 0 { - // overflow + if d > 1<<63 { return 0, errors.New("time: invalid duration " + quote(orig)) } } - if neg { - d = -d + return -Duration(d), nil + } + if d > 1<<63-1 { + return 0, errors.New("time: invalid duration " + quote(orig)) } return Duration(d), nil } diff --git a/src/time/time_test.go b/src/time/time_test.go index e2fb897b6d..5007b6e723 100644 --- a/src/time/time_test.go +++ b/src/time/time_test.go @@ -9,6 +9,7 @@ import ( "encoding/gob" "encoding/json" "fmt" + "math" "math/big" "math/rand" "os" @@ -885,8 +886,13 @@ var parseDurationTests = []struct { {"9223372036854775807ns", (1<<63 - 1) * Nanosecond}, {"9223372036854775.807us", (1<<63 - 1) * Nanosecond}, {"9223372036s854ms775us807ns", (1<<63 - 1) * Nanosecond}, - // large negative value - {"-9223372036854775807ns", -1<<63 + 1*Nanosecond}, + {"-9223372036854775808ns", -1 << 63 * Nanosecond}, + {"-9223372036854775.808us", -1 << 63 * Nanosecond}, + {"-9223372036s854ms775us808ns", -1 << 63 * Nanosecond}, + // largest negative value + {"-9223372036854775808ns", -1 << 63 * Nanosecond}, + // largest negative round trip value, see https://golang.org/issue/48629 + {"-2562047h47m16.854775808s", -1 << 63 * Nanosecond}, // huge string; issue 15011. {"0.100000000000000000000h", 6 * Minute}, // This value tests the first overflow check in leadingFraction. @@ -924,9 +930,7 @@ var parseDurationErrorTests = []struct { // overflow {"9223372036854775810ns", `"9223372036854775810ns"`}, {"9223372036854775808ns", `"9223372036854775808ns"`}, - // largest negative value of type int64 in nanoseconds should fail - // see https://go-review.googlesource.com/#/c/2461/ - {"-9223372036854775808ns", `"-9223372036854775808ns"`}, + {"-9223372036854775809ns", `"-9223372036854775809ns"`}, {"9223372036854776us", `"9223372036854776us"`}, {"3000000h", `"3000000h"`}, {"9223372036854775.808us", `"9223372036854775.808us"`}, @@ -945,6 +949,19 @@ func TestParseDurationErrors(t *testing.T) { } func TestParseDurationRoundTrip(t *testing.T) { + // https://golang.org/issue/48629 + max0 := Duration(math.MaxInt64) + max1, err := ParseDuration(max0.String()) + if err != nil || max0 != max1 { + t.Errorf("round-trip failed: %d => %q => %d, %v", max0, max0.String(), max1, err) + } + + min0 := Duration(math.MinInt64) + min1, err := ParseDuration(min0.String()) + if err != nil || min0 != min1 { + t.Errorf("round-trip failed: %d => %q => %d, %v", min0, min0.String(), min1, err) + } + for i := 0; i < 100; i++ { // Resolutions finer than milliseconds will result in // imprecise round-trips. -- GitLab From b3a4b2df09be4e0a85f4204e71a4c1c8e542f4f8 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 7 Oct 2021 11:20:05 -0400 Subject: [PATCH 1526/2500] misc/cgo/testshared: pass the testing.T to goCmd when available Noticed while investigating the test failure in https://build.golang.org/log/4fc4aa11087c74bb8f66c81a8b212f41fb495be4. Change-Id: I0ed80dad99d6920a187af4339e437a08fbe91ade Reviewed-on: https://go-review.googlesource.com/c/go/+/354572 Trust: Bryan C. Mills Reviewed-by: Ian Lance Taylor --- misc/cgo/testshared/shared_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/misc/cgo/testshared/shared_test.go b/misc/cgo/testshared/shared_test.go index e77f848915..1bd89bc27a 100644 --- a/misc/cgo/testshared/shared_test.go +++ b/misc/cgo/testshared/shared_test.go @@ -1033,7 +1033,7 @@ func TestGlobal(t *testing.T) { // Run a test using -linkshared of an installed shared package. // Issue 26400. func TestTestInstalledShared(t *testing.T) { - goCmd(nil, "test", "-linkshared", "-test.short", "sync/atomic") + goCmd(t, "test", "-linkshared", "-test.short", "sync/atomic") } // Test generated pointer method with -linkshared. @@ -1045,8 +1045,8 @@ func TestGeneratedMethod(t *testing.T) { // Test use of shared library struct with generated hash function. // Issue 30768. func TestGeneratedHash(t *testing.T) { - goCmd(nil, "install", "-buildmode=shared", "-linkshared", "./issue30768/issue30768lib") - goCmd(nil, "test", "-linkshared", "./issue30768") + goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue30768/issue30768lib") + goCmd(t, "test", "-linkshared", "./issue30768") } // Test that packages can be added not in dependency order (here a depends on b, and a adds -- GitLab From 99c1b249b1ffe3b36c5c95572f4497be86b5d727 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Fri, 8 Oct 2021 10:37:54 -0400 Subject: [PATCH 1527/2500] go/ast, go/types: remove some stale TODOs We've decided to leave TParams on FuncType, and type list syntax is no longer part of the proposal. Change-Id: Id34f6495a358d76994df331384a4b93487275c4d Reviewed-on: https://go-review.googlesource.com/c/go/+/354751 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/ast/ast.go | 2 -- src/go/types/typestring_test.go | 4 ---- 2 files changed, 6 deletions(-) diff --git a/src/go/ast/ast.go b/src/go/ast/ast.go index 70d0912f67..38b6de57d3 100644 --- a/src/go/ast/ast.go +++ b/src/go/ast/ast.go @@ -998,8 +998,6 @@ type ( Name *Ident // function/method name Type *FuncType // function signature: type and value parameters, results, and position of "func" keyword Body *BlockStmt // function body; or nil for external (non-Go) function - // TODO(rFindley) consider storing TParams here, rather than FuncType, as - // they are only valid for declared functions } ) diff --git a/src/go/types/typestring_test.go b/src/go/types/typestring_test.go index ddbb2884b6..5718ffcc6c 100644 --- a/src/go/types/typestring_test.go +++ b/src/go/types/typestring_test.go @@ -98,10 +98,6 @@ var independentTestTypes = []testEntry{ dup("interface{int|float32|complex128}"), dup("interface{int|~float32|~complex128}"), - // TODO(rFindley) uncomment this once this AST is accepted, and add more test - // cases. - // dup(`interface{type int, float32, complex128}`), - // maps dup("map[string]int"), {"map[struct{x, y int}][]byte", "map[struct{x int; y int}][]byte"}, -- GitLab From 0d838ea5a2b69255d0a486dd9df27d14ad680aba Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 22 Sep 2021 10:05:33 -0700 Subject: [PATCH 1528/2500] cmd/compile: allow delaying of transformCompLit, new transformAddr For this unusual case, where a constraint specifies exactly one type, we can have a COMPLIT expression with a type that is/has typeparams. Therefore, we add code to delay transformCompLit for generic functions. We also need to break out transformAddr (which corresponds to tcAddr), and added code for delaying it as well. Also, we now need to export generic functions containing untransformed OCOMPLIT and OKEY nodes, so added support for that in iexport.go/iimport.go. Untransformed OKEY nodes include an ir.Ident/ONONAME which we can now export. Had to adjust some code/asserts in transformCompLit(), since we may now be transforming an OCOMPLIT from an imported generic function (i.e. from a non-local package). Fixes #48537 Change-Id: I09e1b3bd08b4e013c0b098b8a25d082efa1fef51 Reviewed-on: https://go-review.googlesource.com/c/go/+/354354 Run-TryBot: Dan Scales TryBot-Result: Go Bot Trust: Dan Scales Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/expr.go | 20 ++++++++++++++++-- src/cmd/compile/internal/noder/helpers.go | 4 ---- src/cmd/compile/internal/noder/stencil.go | 6 ++++++ src/cmd/compile/internal/noder/transform.go | 20 ++++++++++++++++-- src/cmd/compile/internal/typecheck/iexport.go | 14 +++++++++++-- src/cmd/compile/internal/typecheck/iimport.go | 6 +++++- test/typeparam/issue48537.go | 21 +++++++++++++++++++ 7 files changed, 80 insertions(+), 11 deletions(-) create mode 100644 test/typeparam/issue48537.go diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 3dd7737c9f..65568f2307 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -154,7 +154,11 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { case *syntax.Operation: if expr.Y == nil { - return Unary(pos, g.typ(typ), g.op(expr.Op, unOps[:]), g.expr(expr.X)) + n := Unary(pos, g.typ(typ), g.op(expr.Op, unOps[:]), g.expr(expr.X)) + if n.Op() == ir.OADDR && !g.delayTransform() { + transformAddr(n.(*ir.AddrExpr)) + } + return n } switch op := g.op(expr.Op, binOps[:]); op { case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE: @@ -353,15 +357,27 @@ func (g *irgen) compLit(typ types2.Type, lit *syntax.CompositeLit) ir.Node { key = g.expr(elem.Key) } value := wrapname(g.pos(elem.Value), g.expr(elem.Value)) + if value.Op() == ir.OPAREN { + // Make sure any PAREN node added by wrapper has a type + typed(value.(*ir.ParenExpr).X.Type(), value) + } exprs[i] = ir.NewKeyExpr(g.pos(elem), key, value) default: exprs[i] = wrapname(g.pos(elem), g.expr(elem)) + if exprs[i].Op() == ir.OPAREN { + // Make sure any PAREN node added by wrapper has a type + typed(exprs[i].(*ir.ParenExpr).X.Type(), exprs[i]) + } } } n := ir.NewCompLitExpr(g.pos(lit), ir.OCOMPLIT, nil, exprs) typed(g.typ(typ), n) - return transformCompLit(n) + var r ir.Node = n + if !g.delayTransform() { + r = transformCompLit(n) + } + return r } func (g *irgen) funcLit(typ2 types2.Type, expr *syntax.FuncLit) ir.Node { diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index 83830a5d31..adb5a0e89f 100644 --- a/src/cmd/compile/internal/noder/helpers.go +++ b/src/cmd/compile/internal/noder/helpers.go @@ -77,10 +77,6 @@ func Nil(pos src.XPos, typ *types.Type) ir.Node { func Addr(pos src.XPos, x ir.Node) *ir.AddrExpr { n := typecheck.NodAddrAt(pos, x) - switch x.Op() { - case ir.OARRAYLIT, ir.OMAPLIT, ir.OSLICELIT, ir.OSTRUCTLIT: - n.SetOp(ir.OPTRLIT) - } typed(types.NewPtr(x.Type()), n) return n } diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 62d6a45819..447fe8a538 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -996,6 +996,12 @@ func (subst *subster) node(n ir.Node) ir.Node { case ir.OSELECT: transformSelect(m.(*ir.SelectStmt)) + case ir.OCOMPLIT: + transformCompLit(m.(*ir.CompLitExpr)) + + case ir.OADDR: + transformAddr(m.(*ir.AddrExpr)) + } } diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index 9076db2822..29ee601d82 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -933,7 +933,7 @@ func transformArrayLit(elemType *types.Type, bound int64, elts []ir.Node) int64 // transformCompLit transforms n to an OARRAYLIT, OSLICELIT, OMAPLIT, or // OSTRUCTLIT node, with any needed conversions. Corresponds to -// typecheck.tcCompLit. +// typecheck.tcCompLit (and includes parts corresponding to tcStructLitKey). func transformCompLit(n *ir.CompLitExpr) (res ir.Node) { assert(n.Type() != nil && n.Typecheck() == 1) lno := base.Pos @@ -1007,12 +1007,20 @@ func transformCompLit(n *ir.CompLitExpr) (res ir.Node) { if id, ok := key.(*ir.Ident); ok && typecheck.DotImportRefs[id] != nil { s = typecheck.Lookup(s.Name) } + if types.IsExported(s.Name) && s.Pkg != types.LocalPkg { + // Exported field names should always have + // local pkg. We only need to do this + // adjustment for generic functions that are + // being transformed after being imported + // from another package. + s = typecheck.Lookup(s.Name) + } // An OXDOT uses the Sym field to hold // the field to the right of the dot, // so s will be non-nil, but an OXDOT // is never a valid struct literal key. - assert(!(s == nil || s.Pkg != types.LocalPkg || key.Op() == ir.OXDOT || s.IsBlank())) + assert(!(s == nil || key.Op() == ir.OXDOT || s.IsBlank())) f := typecheck.Lookdot1(nil, s, t, t.Fields(), 0) l := ir.NewStructKeyExpr(l.Pos(), f, kv.Value) @@ -1027,3 +1035,11 @@ func transformCompLit(n *ir.CompLitExpr) (res ir.Node) { return n } + +// transformAddr corresponds to typecheck.tcAddr. +func transformAddr(n *ir.AddrExpr) { + switch n.X.Op() { + case ir.OARRAYLIT, ir.OMAPLIT, ir.OSLICELIT, ir.OSTRUCTLIT: + n.SetOp(ir.OPTRLIT) + } +} diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index a2ad71dd4c..3c0b8bc319 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -1746,7 +1746,17 @@ func (w *exportWriter) expr(n ir.Node) { } w.localName(n) - // case OPACK, ONONAME: + case ir.ONONAME: + w.op(ir.ONONAME) + // This should only be for OKEY nodes in generic functions + s := n.Sym() + w.string(s.Name) + w.pkg(s.Pkg) + if go117ExportTypes { + w.typ(n.Type()) + } + + // case OPACK: // should have been resolved by typechecking - handled by default case case ir.OTYPE: @@ -1818,7 +1828,7 @@ func (w *exportWriter) expr(n ir.Node) { w.typ(n.Type()) w.fieldList(n.List) // special handling of field names - case ir.OARRAYLIT, ir.OSLICELIT, ir.OMAPLIT: + case ir.OCOMPLIT, ir.OARRAYLIT, ir.OSLICELIT, ir.OMAPLIT: n := n.(*ir.CompLitExpr) if go117ExportTypes { w.op(n.Op()) diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 01ac1679b2..08850079eb 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1368,7 +1368,11 @@ func (r *importReader) node() ir.Node { return ir.NewCompLitExpr(r.pos(), ir.OCOMPLIT, ir.TypeNode(r.typ()), r.fieldList()) case ir.OCOMPLIT: - return ir.NewCompLitExpr(r.pos(), ir.OCOMPLIT, ir.TypeNode(r.typ()), r.exprList()) + pos := r.pos() + t := r.typ() + n := ir.NewCompLitExpr(pos, ir.OCOMPLIT, ir.TypeNode(t), r.exprList()) + n.SetType(t) + return n case ir.OARRAYLIT, ir.OSLICELIT, ir.OMAPLIT: if !go117ExportTypes { diff --git a/test/typeparam/issue48537.go b/test/typeparam/issue48537.go new file mode 100644 index 0000000000..a2dc5cf082 --- /dev/null +++ b/test/typeparam/issue48537.go @@ -0,0 +1,21 @@ +// compile -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func main() { +} + +type C interface { + map[int]string +} + +func f[A C]() A { + return A{ + 1: "a", + 2: "b", + } +} -- GitLab From a7d3a0e971818c754217829c8bd10b1e167d3481 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 8 Oct 2021 09:49:22 -0700 Subject: [PATCH 1529/2500] cmd/compile/internal/types2: use an identifier map rather than isubst for recv type params This is a port of CL 354643 from go/types to types2 with adjustments: - use of syntax rather than go/ast package as needed - adjustments due to the different code for type parameter declarations - rename of Checker.rparamMap to Checker.recvTParamMap, which seems clearer Change-Id: I5311a0c05a13c6b87ea1422b250b90c3d05c5dce Reviewed-on: https://go-review.googlesource.com/c/go/+/354693 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/check.go | 8 +- src/cmd/compile/internal/types2/signature.go | 114 ++++--------------- src/cmd/compile/internal/types2/typexpr.go | 10 +- 3 files changed, 36 insertions(+), 96 deletions(-) diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go index 5957518c17..d89ec3d29f 100644 --- a/src/cmd/compile/internal/types2/check.go +++ b/src/cmd/compile/internal/types2/check.go @@ -100,9 +100,10 @@ type Checker struct { // information collected during type-checking of a set of package files // (initialized by Files, valid only for the duration of check.Files; // maps and lists are allocated on demand) - files []*syntax.File // list of package files - imports []*PkgName // list of imported packages - dotImportMap map[dotImportKey]*PkgName // maps dot-imported objects to the package they were dot-imported through + files []*syntax.File // list of package files + imports []*PkgName // list of imported packages + dotImportMap map[dotImportKey]*PkgName // maps dot-imported objects to the package they were dot-imported through + recvTParamMap map[*syntax.Name]*TypeParam // maps blank receiver type parameters to their type firstErr error // first error encountered methods map[*TypeName][]*Func // maps package scope type names to associated non-blank (non-interface) methods @@ -292,6 +293,7 @@ func (check *Checker) checkFiles(files []*syntax.File) (err error) { check.dotImportMap = nil check.pkgPathMap = nil check.seenPkgMap = nil + check.recvTParamMap = nil // TODO(gri) There's more memory we should release at this point. diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index 5ea3a056a0..604d0c9dbd 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -4,10 +4,7 @@ package types2 -import ( - "cmd/compile/internal/syntax" - "fmt" -) +import "cmd/compile/internal/syntax" // ---------------------------------------------------------------------------- // API @@ -105,39 +102,33 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] sig.scope = check.scope defer check.closeScope() - var recvTyp syntax.Expr // rewritten receiver type; valid if != nil if recvPar != nil { // collect generic receiver type parameters, if any // - a receiver type parameter is like any other type parameter, except that it is declared implicitly // - the receiver specification acts as local declaration for its type parameters, which may be blank _, rname, rparams := check.unpackRecv(recvPar.Type, true) if len(rparams) > 0 { - // Blank identifiers don't get declared and regular type-checking of the instantiated - // parameterized receiver type expression fails in Checker.collectParams of receiver. - // Identify blank type parameters and substitute each with a unique new identifier named - // "n_" (where n is the parameter index) and which cannot conflict with any user-defined - // name. - var smap map[*syntax.Name]*syntax.Name // substitution map from "_" to "!n" identifiers + tparams := make([]*TypeParam, len(rparams)) + for i, rparam := range rparams { + tparams[i] = check.declareTypeParam(rparam) + } + sig.rparams = bindTParams(tparams) + // Blank identifiers don't get declared, so naive type-checking of the + // receiver type expression would fail in Checker.collectParams below, + // when Checker.ident cannot resolve the _ to a type. + // + // Checker.recvTParamMap maps these blank identifiers to their type parameter + // types, so that they may be resolved in Checker.ident when they fail + // lookup in the scope. for i, p := range rparams { if p.Value == "_" { - new := *p - new.Value = fmt.Sprintf("%d_", i) - rparams[i] = &new // use n_ identifier instead of _ so it can be looked up - if smap == nil { - smap = make(map[*syntax.Name]*syntax.Name) + tpar := sig.rparams.At(i) + if check.recvTParamMap == nil { + check.recvTParamMap = make(map[*syntax.Name]*TypeParam) } - smap[p] = &new + check.recvTParamMap[p] = tpar } } - if smap != nil { - // blank identifiers were found => use rewritten receiver type - recvTyp = isubst(recvPar.Type, smap) - } - rlist := make([]*TypeParam, len(rparams)) - for i, rparam := range rparams { - rlist[i] = check.declareTypeParam(rparam) - } - sig.rparams = bindTParams(rlist) // determine receiver type to get its type parameters // and the respective type parameter bounds var recvTParams []*TypeParam @@ -186,10 +177,10 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] scope := NewScope(check.scope, nopos, nopos, "function body (temp. scope)") var recvList []*Var // TODO(gri) remove the need for making a list here if recvPar != nil { - recvList, _ = check.collectParams(scope, []*syntax.Field{recvPar}, recvTyp, false) // use rewritten receiver type, if any + recvList, _ = check.collectParams(scope, []*syntax.Field{recvPar}, false) // use rewritten receiver type, if any } - params, variadic := check.collectParams(scope, ftyp.ParamList, nil, true) - results, _ := check.collectParams(scope, ftyp.ResultList, nil, false) + params, variadic := check.collectParams(scope, ftyp.ParamList, true) + results, _ := check.collectParams(scope, ftyp.ResultList, false) scope.Squash(func(obj, alt Object) { var err error_ err.errorf(obj, "%s redeclared in this block", obj.Name()) @@ -281,8 +272,8 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] } // collectParams declares the parameters of list in scope and returns the corresponding -// variable list. If type0 != nil, it is used instead of the first type in list. -func (check *Checker) collectParams(scope *Scope, list []*syntax.Field, type0 syntax.Expr, variadicOk bool) (params []*Var, variadic bool) { +// variable list. +func (check *Checker) collectParams(scope *Scope, list []*syntax.Field, variadicOk bool) (params []*Var, variadic bool) { if list == nil { return } @@ -296,9 +287,6 @@ func (check *Checker) collectParams(scope *Scope, list []*syntax.Field, type0 sy // type-check type of grouped fields only once if ftype != prev { prev = ftype - if i == 0 && type0 != nil { - ftype = type0 - } if t, _ := ftype.(*syntax.DotsType); t != nil { ftype = t.Elem if variadicOk && i == len(list)-1 { @@ -348,61 +336,3 @@ func (check *Checker) collectParams(scope *Scope, list []*syntax.Field, type0 sy return } - -// isubst returns an x with identifiers substituted per the substitution map smap. -// isubst only handles the case of (valid) method receiver type expressions correctly. -func isubst(x syntax.Expr, smap map[*syntax.Name]*syntax.Name) syntax.Expr { - switch n := x.(type) { - case *syntax.Name: - if alt := smap[n]; alt != nil { - return alt - } - // case *syntax.StarExpr: - // X := isubst(n.X, smap) - // if X != n.X { - // new := *n - // new.X = X - // return &new - // } - case *syntax.Operation: - if n.Op == syntax.Mul && n.Y == nil { - X := isubst(n.X, smap) - if X != n.X { - new := *n - new.X = X - return &new - } - } - case *syntax.IndexExpr: - Index := isubst(n.Index, smap) - if Index != n.Index { - new := *n - new.Index = Index - return &new - } - case *syntax.ListExpr: - var elems []syntax.Expr - for i, elem := range n.ElemList { - new := isubst(elem, smap) - if new != elem { - if elems == nil { - elems = make([]syntax.Expr, len(n.ElemList)) - copy(elems, n.ElemList) - } - elems[i] = new - } - } - if elems != nil { - new := *n - new.ElemList = elems - return &new - } - case *syntax.ParenExpr: - return isubst(n.X, smap) // no need to keep parentheses - default: - // Other receiver type expressions are invalid. - // It's fine to ignore those here as they will - // be checked elsewhere. - } - return x -} diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 62cfda825f..746fe78b38 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -28,7 +28,15 @@ func (check *Checker) ident(x *operand, e *syntax.Name, def *Named, wantType boo switch obj { case nil: if e.Value == "_" { - check.error(e, "cannot use _ as value or type") + // Blank identifiers are never declared, but the current identifier may + // be a placeholder for a receiver type parameter. In this case we can + // resolve its type and object from Checker.recvTParamMap. + if tpar := check.recvTParamMap[e]; tpar != nil { + x.mode = typexpr + x.typ = tpar + } else { + check.error(e, "cannot use _ as value or type") + } } else { if check.conf.CompilerErrorMessages { check.errorf(e, "undefined: %s", e.Value) -- GitLab From d7ba1d276be37989cfbcf3dc17a17e2ee9c5382d Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 8 Oct 2021 09:52:37 -0700 Subject: [PATCH 1530/2500] go/types: rename rparamMap to recvTParamMap to match types2 See also CL 354693. Change-Id: Id7579c5f7d486652a5b53b29663a6573a493121f Reviewed-on: https://go-review.googlesource.com/c/go/+/354694 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/go/types/check.go | 10 +++++----- src/go/types/signature.go | 8 ++++---- src/go/types/typexpr.go | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/go/types/check.go b/src/go/types/check.go index fa3bd94681..46a0000940 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -103,10 +103,10 @@ type Checker struct { // information collected during type-checking of a set of package files // (initialized by Files, valid only for the duration of check.Files; // maps and lists are allocated on demand) - files []*ast.File // package files - imports []*PkgName // list of imported packages - dotImportMap map[dotImportKey]*PkgName // maps dot-imported objects to the package they were dot-imported through - rparamMap map[*ast.Ident]*TypeParam // maps blank receiver type params to their type + files []*ast.File // package files + imports []*PkgName // list of imported packages + dotImportMap map[dotImportKey]*PkgName // maps dot-imported objects to the package they were dot-imported through + recvTParamMap map[*ast.Ident]*TypeParam // maps blank receiver type parameters to their type firstErr error // first error encountered methods map[*TypeName][]*Func // maps package scope type names to associated non-blank (non-interface) methods @@ -284,7 +284,7 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) { check.dotImportMap = nil check.pkgPathMap = nil check.seenPkgMap = nil - check.rparamMap = nil + check.recvTParamMap = nil // TODO(rFindley) There's more memory we should release at this point. diff --git a/src/go/types/signature.go b/src/go/types/signature.go index ae7818afdf..c83bf09032 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -117,16 +117,16 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast // receiver type expression would fail in Checker.collectParams below, // when Checker.ident cannot resolve the _ to a type. // - // Checker.rparamMap maps these blank identifiers to their type parameter + // Checker.recvTParamMap maps these blank identifiers to their type parameter // types, so that they may be resolved in Checker.ident when they fail // lookup in the scope. for i, p := range rparams { if p.Name == "_" { tpar := sig.rparams.At(i) - if check.rparamMap == nil { - check.rparamMap = make(map[*ast.Ident]*TypeParam) + if check.recvTParamMap == nil { + check.recvTParamMap = make(map[*ast.Ident]*TypeParam) } - check.rparamMap[p] = tpar + check.recvTParamMap[p] = tpar } } // determine receiver type to get its type parameters diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index f581effc19..71623c336e 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -32,8 +32,8 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool) if e.Name == "_" { // Blank identifiers are never declared, but the current identifier may // be a placeholder for a receiver type parameter. In this case we can - // resolve its type and object from Checker.rparamMap. - if tpar := check.rparamMap[e]; tpar != nil { + // resolve its type and object from Checker.recvTParamMap. + if tpar := check.recvTParamMap[e]; tpar != nil { x.mode = typexpr x.typ = tpar } else { -- GitLab From 16a3cefc93d9b896b2053320e387d0e449904aba Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 7 Oct 2021 13:29:09 -0700 Subject: [PATCH 1531/2500] runtime: fix uint64->float32 conversion for softfloat The fix for #48807 in CL 354429 forgot that we also need to fix the softfloat implementation. Update #48807 Change-Id: I596fb4e14e78145d1ad43c130b2cc5122b73655c Reviewed-on: https://go-review.googlesource.com/c/go/+/354613 Trust: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: David Chase --- src/cmd/compile/internal/test/ssa_test.go | 2 +- src/runtime/softfloat64.go | 36 ++++++++++++++++++++--- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/cmd/compile/internal/test/ssa_test.go b/src/cmd/compile/internal/test/ssa_test.go index 2f3e24c2d3..af7d9626f9 100644 --- a/src/cmd/compile/internal/test/ssa_test.go +++ b/src/cmd/compile/internal/test/ssa_test.go @@ -162,7 +162,7 @@ func TestCode(t *testing.T) { } flags := []string{""} - if runtime.GOARCH == "arm" || runtime.GOARCH == "mips" || runtime.GOARCH == "mips64" { + if runtime.GOARCH == "arm" || runtime.GOARCH == "mips" || runtime.GOARCH == "mips64" || runtime.GOARCH == "386" { flags = append(flags, ",softfloat") } for _, flag := range flags { diff --git a/src/runtime/softfloat64.go b/src/runtime/softfloat64.go index 084aa132d9..42ef009297 100644 --- a/src/runtime/softfloat64.go +++ b/src/runtime/softfloat64.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // Software IEEE754 64-bit floating point. -// Only referred to (and thus linked in) by arm port +// Only referred to (and thus linked in) by softfloat targets // and by tests in this directory. package runtime @@ -414,6 +414,25 @@ func fintto64(val int64) (f uint64) { } return fpack64(fs, mant, int(mantbits64), 0) } +func fintto32(val int64) (f uint32) { + fs := uint64(val) & (1 << 63) + mant := uint64(val) + if fs != 0 { + mant = -mant + } + // Reduce mantissa size until it fits into a uint32. + // Keep track of the bits we throw away, and if any are + // nonzero or them into the lowest bit. + exp := int(mantbits32) + var trunc uint32 + for mant >= 1<<32 { + trunc |= uint32(mant) & 1 + mant >>= 1 + exp++ + } + + return fpack32(uint32(fs>>32), uint32(mant), exp, trunc) +} // 64x64 -> 128 multiply. // adapted from hacker's delight. @@ -493,6 +512,7 @@ func fmul32(x, y uint32) uint32 { } func fdiv32(x, y uint32) uint32 { + // TODO: are there double-rounding problems here? See issue 48807. return f64to32(fdiv64(f32to64(x), f32to64(y))) } @@ -527,7 +547,7 @@ func fge64(x, y uint64) bool { } func fint32to32(x int32) uint32 { - return f64to32(fintto64(int64(x))) + return fintto32(int64(x)) } func fint32to64(x int32) uint64 { @@ -535,7 +555,7 @@ func fint32to64(x int32) uint64 { } func fint64to32(x int64) uint32 { - return f64to32(fintto64(x)) + return fintto32(x) } func fint64to64(x int64) uint64 { @@ -595,5 +615,13 @@ func fuint64to64(x uint64) uint64 { } func fuint64to32(x uint64) uint32 { - return f64to32(fuint64to64(x)) + if int64(x) >= 0 { + return fint64to32(int64(x)) + } + // See ../cmd/compile/internal/ssagen/ssa.go:uint64Tofloat + y := x & 1 + z := x >> 1 + z = z | y + r := fint64to32(int64(z)) + return fadd32(r, r) } -- GitLab From d480b5c790196c615213f2308d6b7b975eb99ff9 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 8 Oct 2021 13:10:08 -0400 Subject: [PATCH 1532/2500] cmd/link: put gcprog symbols along with gcbits A stack object record may refer to the object's type's GC mask or GC program (for very large types). For the latter, currently the GC program symbol is named "type..gcprog.XXX" which is then laid out along with type symbols at link time. When relro is used, the type symbols end up in a different section. As we now use relative addressing for stack object records to refer to GC masks or GC programs, it is important that it is laid out in the rodata section (not rodata.rel.ro). Move GC program symbols to be along with GC masks, as they are similar and accessed the same way. They don't have relocations so they don't need to be laid to a relro section. This fixes flaky failures like https://build.golang.org/log/3bdbaaf786ec831b4393a64a959d2130edb5e050 Change-Id: I97aeac1234869da5b0f3a73a3010513d6a3156c6 Reviewed-on: https://go-review.googlesource.com/c/go/+/354793 Trust: Cherry Mui Trust: Josh Bleecher Snyder Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Josh Bleecher Snyder --- src/cmd/link/internal/ld/symtab.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index 4be2634f44..7b1a0b7d1a 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -539,7 +539,8 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { ldr.SetAttrNotInSymbolTable(s, true) ldr.SetCarrierSym(s, symgostring) - case strings.HasPrefix(name, "runtime.gcbits."): + case strings.HasPrefix(name, "runtime.gcbits."), + strings.HasPrefix(name, "type..gcprog."): symGroupType[s] = sym.SGCBITS ldr.SetAttrNotInSymbolTable(s, true) ldr.SetCarrierSym(s, symgcbits) -- GitLab From b9e1e1ba3d44069ce0b0564abab1b130ed120539 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 8 Oct 2021 11:23:38 -0700 Subject: [PATCH 1533/2500] cmd/cgo: use "!compiler_bootstrap" tag instead of "go1.18" The illumos builder is using a Go 1.18 prerelease toolchain for bootstrapping, which doesn't have ast.IndexListExpr. But we can instead check for the "compiler_bootstrap" build tag that's already used for distinguishing binaries built for toolchain1. Fixes #48863. Change-Id: I87b672322eee22a60ab8d0bb3be5f76cffc97545 Reviewed-on: https://go-review.googlesource.com/c/go/+/354695 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/cmd/cgo/ast_go1.go | 4 ++-- src/cmd/cgo/ast_go118.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cmd/cgo/ast_go1.go b/src/cmd/cgo/ast_go1.go index cf6d99f64a..f52bf00d7c 100644 --- a/src/cmd/cgo/ast_go1.go +++ b/src/cmd/cgo/ast_go1.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build !go1.18 -// +build !go1.18 +//go:build compiler_bootstrap +// +build compiler_bootstrap package main diff --git a/src/cmd/cgo/ast_go118.go b/src/cmd/cgo/ast_go118.go index 2e3ce27521..db0108ed72 100644 --- a/src/cmd/cgo/ast_go118.go +++ b/src/cmd/cgo/ast_go118.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.18 -// +build go1.18 +//go:build !compiler_bootstrap +// +build !compiler_bootstrap package main -- GitLab From f430bda2582bdea5cf3afd8a44ef5a46567a325a Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Fri, 8 Oct 2021 19:23:35 +0200 Subject: [PATCH 1534/2500] go/build, internal/goarch: sort goarchList alphabetically Change-Id: I0534b61e34d78104cb85124b805fd90f3250e6c2 Reviewed-on: https://go-review.googlesource.com/c/go/+/354829 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/go/build/syslist.go | 2 +- src/internal/goarch/zgoarch_386.go | 4 ++-- src/internal/goarch/zgoarch_amd64.go | 4 ++-- src/internal/goarch/zgoarch_arm.go | 4 ++-- src/internal/goarch/zgoarch_arm64.go | 4 ++-- src/internal/goarch/zgoarch_arm64be.go | 4 ++-- src/internal/goarch/zgoarch_armbe.go | 4 ++-- src/internal/goarch/zgoarch_loong64.go | 4 ++-- src/internal/goarch/zgoarch_mips.go | 4 ++-- src/internal/goarch/zgoarch_mips64.go | 4 ++-- src/internal/goarch/zgoarch_mips64le.go | 4 ++-- src/internal/goarch/zgoarch_mips64p32.go | 4 ++-- src/internal/goarch/zgoarch_mips64p32le.go | 4 ++-- src/internal/goarch/zgoarch_mipsle.go | 4 ++-- src/internal/goarch/zgoarch_ppc.go | 4 ++-- src/internal/goarch/zgoarch_ppc64.go | 4 ++-- src/internal/goarch/zgoarch_ppc64le.go | 4 ++-- src/internal/goarch/zgoarch_riscv.go | 4 ++-- src/internal/goarch/zgoarch_riscv64.go | 4 ++-- src/internal/goarch/zgoarch_s390.go | 4 ++-- src/internal/goarch/zgoarch_s390x.go | 4 ++-- src/internal/goarch/zgoarch_sparc.go | 4 ++-- src/internal/goarch/zgoarch_sparc64.go | 4 ++-- src/internal/goarch/zgoarch_wasm.go | 4 ++-- 24 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/go/build/syslist.go b/src/go/build/syslist.go index 60ac5511bd..0f6e336925 100644 --- a/src/go/build/syslist.go +++ b/src/go/build/syslist.go @@ -8,4 +8,4 @@ package build // Do not remove from this list, as these are used for go/build filename matching. const goosList = "aix android darwin dragonfly freebsd hurd illumos ios js linux nacl netbsd openbsd plan9 solaris windows zos " -const goarchList = "386 amd64 amd64p32 arm armbe arm64 arm64be ppc64 ppc64le loong64 mips mipsle mips64 mips64le mips64p32 mips64p32le ppc riscv riscv64 s390 s390x sparc sparc64 wasm " +const goarchList = "386 amd64 amd64p32 arm armbe arm64 arm64be loong64 mips mipsle mips64 mips64le mips64p32 mips64p32le ppc ppc64 ppc64le riscv riscv64 s390 s390x sparc sparc64 wasm " diff --git a/src/internal/goarch/zgoarch_386.go b/src/internal/goarch/zgoarch_386.go index 2395b80951..364367722f 100644 --- a/src/internal/goarch/zgoarch_386.go +++ b/src/internal/goarch/zgoarch_386.go @@ -14,8 +14,6 @@ const IsArm = 0 const IsArmbe = 0 const IsArm64 = 0 const IsArm64be = 0 -const IsPpc64 = 0 -const IsPpc64le = 0 const IsLoong64 = 0 const IsMips = 0 const IsMipsle = 0 @@ -24,6 +22,8 @@ const IsMips64le = 0 const IsMips64p32 = 0 const IsMips64p32le = 0 const IsPpc = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 const IsRiscv = 0 const IsRiscv64 = 0 const IsS390 = 0 diff --git a/src/internal/goarch/zgoarch_amd64.go b/src/internal/goarch/zgoarch_amd64.go index c301d279c1..8169580857 100644 --- a/src/internal/goarch/zgoarch_amd64.go +++ b/src/internal/goarch/zgoarch_amd64.go @@ -14,8 +14,6 @@ const IsArm = 0 const IsArmbe = 0 const IsArm64 = 0 const IsArm64be = 0 -const IsPpc64 = 0 -const IsPpc64le = 0 const IsLoong64 = 0 const IsMips = 0 const IsMipsle = 0 @@ -24,6 +22,8 @@ const IsMips64le = 0 const IsMips64p32 = 0 const IsMips64p32le = 0 const IsPpc = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 const IsRiscv = 0 const IsRiscv64 = 0 const IsS390 = 0 diff --git a/src/internal/goarch/zgoarch_arm.go b/src/internal/goarch/zgoarch_arm.go index 4a5ff37999..edc69f3349 100644 --- a/src/internal/goarch/zgoarch_arm.go +++ b/src/internal/goarch/zgoarch_arm.go @@ -14,8 +14,6 @@ const IsArm = 1 const IsArmbe = 0 const IsArm64 = 0 const IsArm64be = 0 -const IsPpc64 = 0 -const IsPpc64le = 0 const IsLoong64 = 0 const IsMips = 0 const IsMipsle = 0 @@ -24,6 +22,8 @@ const IsMips64le = 0 const IsMips64p32 = 0 const IsMips64p32le = 0 const IsPpc = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 const IsRiscv = 0 const IsRiscv64 = 0 const IsS390 = 0 diff --git a/src/internal/goarch/zgoarch_arm64.go b/src/internal/goarch/zgoarch_arm64.go index 840e280f94..0459376349 100644 --- a/src/internal/goarch/zgoarch_arm64.go +++ b/src/internal/goarch/zgoarch_arm64.go @@ -14,8 +14,6 @@ const IsArm = 0 const IsArmbe = 0 const IsArm64 = 1 const IsArm64be = 0 -const IsPpc64 = 0 -const IsPpc64le = 0 const IsLoong64 = 0 const IsMips = 0 const IsMipsle = 0 @@ -24,6 +22,8 @@ const IsMips64le = 0 const IsMips64p32 = 0 const IsMips64p32le = 0 const IsPpc = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 const IsRiscv = 0 const IsRiscv64 = 0 const IsS390 = 0 diff --git a/src/internal/goarch/zgoarch_arm64be.go b/src/internal/goarch/zgoarch_arm64be.go index bdbe5faacf..b9439c147e 100644 --- a/src/internal/goarch/zgoarch_arm64be.go +++ b/src/internal/goarch/zgoarch_arm64be.go @@ -14,8 +14,6 @@ const IsArm = 0 const IsArmbe = 0 const IsArm64 = 0 const IsArm64be = 1 -const IsPpc64 = 0 -const IsPpc64le = 0 const IsLoong64 = 0 const IsMips = 0 const IsMipsle = 0 @@ -24,6 +22,8 @@ const IsMips64le = 0 const IsMips64p32 = 0 const IsMips64p32le = 0 const IsPpc = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 const IsRiscv = 0 const IsRiscv64 = 0 const IsS390 = 0 diff --git a/src/internal/goarch/zgoarch_armbe.go b/src/internal/goarch/zgoarch_armbe.go index 36be514a0b..bbb07603d6 100644 --- a/src/internal/goarch/zgoarch_armbe.go +++ b/src/internal/goarch/zgoarch_armbe.go @@ -14,8 +14,6 @@ const IsArm = 0 const IsArmbe = 1 const IsArm64 = 0 const IsArm64be = 0 -const IsPpc64 = 0 -const IsPpc64le = 0 const IsLoong64 = 0 const IsMips = 0 const IsMipsle = 0 @@ -24,6 +22,8 @@ const IsMips64le = 0 const IsMips64p32 = 0 const IsMips64p32le = 0 const IsPpc = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 const IsRiscv = 0 const IsRiscv64 = 0 const IsS390 = 0 diff --git a/src/internal/goarch/zgoarch_loong64.go b/src/internal/goarch/zgoarch_loong64.go index 9465cf5bf5..4d2cd70a00 100644 --- a/src/internal/goarch/zgoarch_loong64.go +++ b/src/internal/goarch/zgoarch_loong64.go @@ -14,8 +14,6 @@ const IsArm = 0 const IsArmbe = 0 const IsArm64 = 0 const IsArm64be = 0 -const IsPpc64 = 0 -const IsPpc64le = 0 const IsLoong64 = 1 const IsMips = 0 const IsMipsle = 0 @@ -24,6 +22,8 @@ const IsMips64le = 0 const IsMips64p32 = 0 const IsMips64p32le = 0 const IsPpc = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 const IsRiscv = 0 const IsRiscv64 = 0 const IsS390 = 0 diff --git a/src/internal/goarch/zgoarch_mips.go b/src/internal/goarch/zgoarch_mips.go index e1458c0485..25a8071727 100644 --- a/src/internal/goarch/zgoarch_mips.go +++ b/src/internal/goarch/zgoarch_mips.go @@ -14,8 +14,6 @@ const IsArm = 0 const IsArmbe = 0 const IsArm64 = 0 const IsArm64be = 0 -const IsPpc64 = 0 -const IsPpc64le = 0 const IsLoong64 = 0 const IsMips = 1 const IsMipsle = 0 @@ -24,6 +22,8 @@ const IsMips64le = 0 const IsMips64p32 = 0 const IsMips64p32le = 0 const IsPpc = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 const IsRiscv = 0 const IsRiscv64 = 0 const IsS390 = 0 diff --git a/src/internal/goarch/zgoarch_mips64.go b/src/internal/goarch/zgoarch_mips64.go index 7de345e321..907ae30ec4 100644 --- a/src/internal/goarch/zgoarch_mips64.go +++ b/src/internal/goarch/zgoarch_mips64.go @@ -14,8 +14,6 @@ const IsArm = 0 const IsArmbe = 0 const IsArm64 = 0 const IsArm64be = 0 -const IsPpc64 = 0 -const IsPpc64le = 0 const IsLoong64 = 0 const IsMips = 0 const IsMipsle = 0 @@ -24,6 +22,8 @@ const IsMips64le = 0 const IsMips64p32 = 0 const IsMips64p32le = 0 const IsPpc = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 const IsRiscv = 0 const IsRiscv64 = 0 const IsS390 = 0 diff --git a/src/internal/goarch/zgoarch_mips64le.go b/src/internal/goarch/zgoarch_mips64le.go index 96b1c3c021..3f4c369d16 100644 --- a/src/internal/goarch/zgoarch_mips64le.go +++ b/src/internal/goarch/zgoarch_mips64le.go @@ -14,8 +14,6 @@ const IsArm = 0 const IsArmbe = 0 const IsArm64 = 0 const IsArm64be = 0 -const IsPpc64 = 0 -const IsPpc64le = 0 const IsLoong64 = 0 const IsMips = 0 const IsMipsle = 0 @@ -24,6 +22,8 @@ const IsMips64le = 1 const IsMips64p32 = 0 const IsMips64p32le = 0 const IsPpc = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 const IsRiscv = 0 const IsRiscv64 = 0 const IsS390 = 0 diff --git a/src/internal/goarch/zgoarch_mips64p32.go b/src/internal/goarch/zgoarch_mips64p32.go index 91d1f3c4df..d03e503c59 100644 --- a/src/internal/goarch/zgoarch_mips64p32.go +++ b/src/internal/goarch/zgoarch_mips64p32.go @@ -14,8 +14,6 @@ const IsArm = 0 const IsArmbe = 0 const IsArm64 = 0 const IsArm64be = 0 -const IsPpc64 = 0 -const IsPpc64le = 0 const IsLoong64 = 0 const IsMips = 0 const IsMipsle = 0 @@ -24,6 +22,8 @@ const IsMips64le = 0 const IsMips64p32 = 1 const IsMips64p32le = 0 const IsPpc = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 const IsRiscv = 0 const IsRiscv64 = 0 const IsS390 = 0 diff --git a/src/internal/goarch/zgoarch_mips64p32le.go b/src/internal/goarch/zgoarch_mips64p32le.go index 18f2ef2347..bbaa010ada 100644 --- a/src/internal/goarch/zgoarch_mips64p32le.go +++ b/src/internal/goarch/zgoarch_mips64p32le.go @@ -14,8 +14,6 @@ const IsArm = 0 const IsArmbe = 0 const IsArm64 = 0 const IsArm64be = 0 -const IsPpc64 = 0 -const IsPpc64le = 0 const IsLoong64 = 0 const IsMips = 0 const IsMipsle = 0 @@ -24,6 +22,8 @@ const IsMips64le = 0 const IsMips64p32 = 0 const IsMips64p32le = 1 const IsPpc = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 const IsRiscv = 0 const IsRiscv64 = 0 const IsS390 = 0 diff --git a/src/internal/goarch/zgoarch_mipsle.go b/src/internal/goarch/zgoarch_mipsle.go index 4551de1a32..b22be64d6e 100644 --- a/src/internal/goarch/zgoarch_mipsle.go +++ b/src/internal/goarch/zgoarch_mipsle.go @@ -14,8 +14,6 @@ const IsArm = 0 const IsArmbe = 0 const IsArm64 = 0 const IsArm64be = 0 -const IsPpc64 = 0 -const IsPpc64le = 0 const IsLoong64 = 0 const IsMips = 0 const IsMipsle = 1 @@ -24,6 +22,8 @@ const IsMips64le = 0 const IsMips64p32 = 0 const IsMips64p32le = 0 const IsPpc = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 const IsRiscv = 0 const IsRiscv64 = 0 const IsS390 = 0 diff --git a/src/internal/goarch/zgoarch_ppc.go b/src/internal/goarch/zgoarch_ppc.go index ffed58c2e5..ed50bf8275 100644 --- a/src/internal/goarch/zgoarch_ppc.go +++ b/src/internal/goarch/zgoarch_ppc.go @@ -14,8 +14,6 @@ const IsArm = 0 const IsArmbe = 0 const IsArm64 = 0 const IsArm64be = 0 -const IsPpc64 = 0 -const IsPpc64le = 0 const IsLoong64 = 0 const IsMips = 0 const IsMipsle = 0 @@ -24,6 +22,8 @@ const IsMips64le = 0 const IsMips64p32 = 0 const IsMips64p32le = 0 const IsPpc = 1 +const IsPpc64 = 0 +const IsPpc64le = 0 const IsRiscv = 0 const IsRiscv64 = 0 const IsS390 = 0 diff --git a/src/internal/goarch/zgoarch_ppc64.go b/src/internal/goarch/zgoarch_ppc64.go index c369c74166..26b921d343 100644 --- a/src/internal/goarch/zgoarch_ppc64.go +++ b/src/internal/goarch/zgoarch_ppc64.go @@ -14,8 +14,6 @@ const IsArm = 0 const IsArmbe = 0 const IsArm64 = 0 const IsArm64be = 0 -const IsPpc64 = 1 -const IsPpc64le = 0 const IsLoong64 = 0 const IsMips = 0 const IsMipsle = 0 @@ -24,6 +22,8 @@ const IsMips64le = 0 const IsMips64p32 = 0 const IsMips64p32le = 0 const IsPpc = 0 +const IsPpc64 = 1 +const IsPpc64le = 0 const IsRiscv = 0 const IsRiscv64 = 0 const IsS390 = 0 diff --git a/src/internal/goarch/zgoarch_ppc64le.go b/src/internal/goarch/zgoarch_ppc64le.go index de5bae2a81..de4fe0fb80 100644 --- a/src/internal/goarch/zgoarch_ppc64le.go +++ b/src/internal/goarch/zgoarch_ppc64le.go @@ -14,8 +14,6 @@ const IsArm = 0 const IsArmbe = 0 const IsArm64 = 0 const IsArm64be = 0 -const IsPpc64 = 0 -const IsPpc64le = 1 const IsLoong64 = 0 const IsMips = 0 const IsMipsle = 0 @@ -24,6 +22,8 @@ const IsMips64le = 0 const IsMips64p32 = 0 const IsMips64p32le = 0 const IsPpc = 0 +const IsPpc64 = 0 +const IsPpc64le = 1 const IsRiscv = 0 const IsRiscv64 = 0 const IsS390 = 0 diff --git a/src/internal/goarch/zgoarch_riscv.go b/src/internal/goarch/zgoarch_riscv.go index 07c9d81b39..3eff474467 100644 --- a/src/internal/goarch/zgoarch_riscv.go +++ b/src/internal/goarch/zgoarch_riscv.go @@ -14,8 +14,6 @@ const IsArm = 0 const IsArmbe = 0 const IsArm64 = 0 const IsArm64be = 0 -const IsPpc64 = 0 -const IsPpc64le = 0 const IsLoong64 = 0 const IsMips = 0 const IsMipsle = 0 @@ -24,6 +22,8 @@ const IsMips64le = 0 const IsMips64p32 = 0 const IsMips64p32le = 0 const IsPpc = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 const IsRiscv = 1 const IsRiscv64 = 0 const IsS390 = 0 diff --git a/src/internal/goarch/zgoarch_riscv64.go b/src/internal/goarch/zgoarch_riscv64.go index 24e6ef3fdf..d99ab9dc29 100644 --- a/src/internal/goarch/zgoarch_riscv64.go +++ b/src/internal/goarch/zgoarch_riscv64.go @@ -14,8 +14,6 @@ const IsArm = 0 const IsArmbe = 0 const IsArm64 = 0 const IsArm64be = 0 -const IsPpc64 = 0 -const IsPpc64le = 0 const IsLoong64 = 0 const IsMips = 0 const IsMipsle = 0 @@ -24,6 +22,8 @@ const IsMips64le = 0 const IsMips64p32 = 0 const IsMips64p32le = 0 const IsPpc = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 const IsRiscv = 0 const IsRiscv64 = 1 const IsS390 = 0 diff --git a/src/internal/goarch/zgoarch_s390.go b/src/internal/goarch/zgoarch_s390.go index 429206d653..6d4ff71cc9 100644 --- a/src/internal/goarch/zgoarch_s390.go +++ b/src/internal/goarch/zgoarch_s390.go @@ -14,8 +14,6 @@ const IsArm = 0 const IsArmbe = 0 const IsArm64 = 0 const IsArm64be = 0 -const IsPpc64 = 0 -const IsPpc64le = 0 const IsLoong64 = 0 const IsMips = 0 const IsMipsle = 0 @@ -24,6 +22,8 @@ const IsMips64le = 0 const IsMips64p32 = 0 const IsMips64p32le = 0 const IsPpc = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 const IsRiscv = 0 const IsRiscv64 = 0 const IsS390 = 1 diff --git a/src/internal/goarch/zgoarch_s390x.go b/src/internal/goarch/zgoarch_s390x.go index 0c59005216..6c215060a3 100644 --- a/src/internal/goarch/zgoarch_s390x.go +++ b/src/internal/goarch/zgoarch_s390x.go @@ -14,8 +14,6 @@ const IsArm = 0 const IsArmbe = 0 const IsArm64 = 0 const IsArm64be = 0 -const IsPpc64 = 0 -const IsPpc64le = 0 const IsLoong64 = 0 const IsMips = 0 const IsMipsle = 0 @@ -24,6 +22,8 @@ const IsMips64le = 0 const IsMips64p32 = 0 const IsMips64p32le = 0 const IsPpc = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 const IsRiscv = 0 const IsRiscv64 = 0 const IsS390 = 0 diff --git a/src/internal/goarch/zgoarch_sparc.go b/src/internal/goarch/zgoarch_sparc.go index 83a356e4c7..029e790fb0 100644 --- a/src/internal/goarch/zgoarch_sparc.go +++ b/src/internal/goarch/zgoarch_sparc.go @@ -14,8 +14,6 @@ const IsArm = 0 const IsArmbe = 0 const IsArm64 = 0 const IsArm64be = 0 -const IsPpc64 = 0 -const IsPpc64le = 0 const IsLoong64 = 0 const IsMips = 0 const IsMipsle = 0 @@ -24,6 +22,8 @@ const IsMips64le = 0 const IsMips64p32 = 0 const IsMips64p32le = 0 const IsPpc = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 const IsRiscv = 0 const IsRiscv64 = 0 const IsS390 = 0 diff --git a/src/internal/goarch/zgoarch_sparc64.go b/src/internal/goarch/zgoarch_sparc64.go index 7c9d40986e..bcd7b6f7df 100644 --- a/src/internal/goarch/zgoarch_sparc64.go +++ b/src/internal/goarch/zgoarch_sparc64.go @@ -14,8 +14,6 @@ const IsArm = 0 const IsArmbe = 0 const IsArm64 = 0 const IsArm64be = 0 -const IsPpc64 = 0 -const IsPpc64le = 0 const IsLoong64 = 0 const IsMips = 0 const IsMipsle = 0 @@ -24,6 +22,8 @@ const IsMips64le = 0 const IsMips64p32 = 0 const IsMips64p32le = 0 const IsPpc = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 const IsRiscv = 0 const IsRiscv64 = 0 const IsS390 = 0 diff --git a/src/internal/goarch/zgoarch_wasm.go b/src/internal/goarch/zgoarch_wasm.go index 5aac1dfc47..0816c85a11 100644 --- a/src/internal/goarch/zgoarch_wasm.go +++ b/src/internal/goarch/zgoarch_wasm.go @@ -14,8 +14,6 @@ const IsArm = 0 const IsArmbe = 0 const IsArm64 = 0 const IsArm64be = 0 -const IsPpc64 = 0 -const IsPpc64le = 0 const IsLoong64 = 0 const IsMips = 0 const IsMipsle = 0 @@ -24,6 +22,8 @@ const IsMips64le = 0 const IsMips64p32 = 0 const IsMips64p32le = 0 const IsPpc = 0 +const IsPpc64 = 0 +const IsPpc64le = 0 const IsRiscv = 0 const IsRiscv64 = 0 const IsS390 = 0 -- GitLab From 7fcf9a1e58c088eb63b7fc3db494016bf210966b Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 8 Oct 2021 14:12:33 -0400 Subject: [PATCH 1535/2500] cmd/go: do not expect a specific timing in test_fuzz_minimize Empirically, it may take more than 3 seconds for minimization to begin. If that is the case, the "elapsed:" message may start at 4s or higher. Fixes #48870 Change-Id: I6bb4367b61377454b0af664d80232fdb46e7c245 Reviewed-on: https://go-review.googlesource.com/c/go/+/354794 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/testdata/script/test_fuzz_minimize.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize.txt b/src/cmd/go/testdata/script/test_fuzz_minimize.txt index 727399f4bb..0a0359fabb 100644 --- a/src/cmd/go/testdata/script/test_fuzz_minimize.txt +++ b/src/cmd/go/testdata/script/test_fuzz_minimize.txt @@ -76,7 +76,7 @@ stdout FAIL ! go test -fuzz=FuzzMinimizerTooSlow -run=FuzzMinimizerTooSlow -fuzzminimizetime=3s minimizer_test.go stdout 'fuzz: minimizing' -stdout 'fuzz: elapsed: 3s, minimizing' +stdout 'fuzz: elapsed: \d+s, minimizing' stdout 'testdata[/\\]fuzz[/\\]FuzzMinimizerTooSlow[/\\]' stdout FAIL -- GitLab From 74abcabf3045d2c893a517c872ace719f0e9d88f Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 8 Oct 2021 12:19:57 -0700 Subject: [PATCH 1536/2500] cmd/internal/obj: rename MOVBE{LL,QQ,WW} to just MOVBE{L,Q,W} The double suffix doesn't seem to serve any purpose, and we can keep the old spelling as a backwards compatible alias in cmd/asm. Change-Id: I3f01fc7249fb093ac1b25bd75c1cb9f39b8f62a9 Reviewed-on: https://go-review.googlesource.com/c/go/+/354700 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Matthew Dempsky --- src/cmd/asm/internal/arch/arch.go | 4 ++ src/cmd/asm/internal/asm/testdata/amd64enc.s | 48 ++++++++++---------- src/cmd/internal/obj/x86/aenum.go | 6 +-- src/cmd/internal/obj/x86/anames.go | 6 +-- src/cmd/internal/obj/x86/asm6.go | 6 +-- 5 files changed, 37 insertions(+), 33 deletions(-) diff --git a/src/cmd/asm/internal/arch/arch.go b/src/cmd/asm/internal/arch/arch.go index 026d8abf81..cffa9a26a4 100644 --- a/src/cmd/asm/internal/arch/arch.go +++ b/src/cmd/asm/internal/arch/arch.go @@ -178,6 +178,10 @@ func archX86(linkArch *obj.LinkArch) *Arch { instructions["PSLLDQ"] = x86.APSLLO instructions["PSRLDQ"] = x86.APSRLO instructions["PADDD"] = x86.APADDL + // Spellings originally used in CL 97235. + instructions["MOVBELL"] = x86.AMOVBEL + instructions["MOVBEQQ"] = x86.AMOVBEQ + instructions["MOVBEWW"] = x86.AMOVBEW return &Arch{ LinkArch: linkArch, diff --git a/src/cmd/asm/internal/asm/testdata/amd64enc.s b/src/cmd/asm/internal/asm/testdata/amd64enc.s index c02f51d125..5bba292dee 100644 --- a/src/cmd/asm/internal/asm/testdata/amd64enc.s +++ b/src/cmd/asm/internal/asm/testdata/amd64enc.s @@ -2495,30 +2495,30 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0 MOVAPS X11, (BX) // 440f291b MOVAPS X2, (R11) // 410f2913 MOVAPS X11, (R11) // 450f291b - MOVBEWW DX, (BX) // 660f38f113 - MOVBEWW R11, (BX) // 66440f38f11b - MOVBEWW DX, (R11) // 66410f38f113 - MOVBEWW R11, (R11) // 66450f38f11b - MOVBEWW (BX), DX // 660f38f013 - MOVBEWW (R11), DX // 66410f38f013 - MOVBEWW (BX), R11 // 66440f38f01b - MOVBEWW (R11), R11 // 66450f38f01b - MOVBELL DX, (BX) // 0f38f113 - MOVBELL R11, (BX) // 440f38f11b - MOVBELL DX, (R11) // 410f38f113 - MOVBELL R11, (R11) // 450f38f11b - MOVBELL (BX), DX // 0f38f013 - MOVBELL (R11), DX // 410f38f013 - MOVBELL (BX), R11 // 440f38f01b - MOVBELL (R11), R11 // 450f38f01b - MOVBEQQ DX, (BX) // 480f38f113 - MOVBEQQ R11, (BX) // 4c0f38f11b - MOVBEQQ DX, (R11) // 490f38f113 - MOVBEQQ R11, (R11) // 4d0f38f11b - MOVBEQQ (BX), DX // 480f38f013 - MOVBEQQ (R11), DX // 490f38f013 - MOVBEQQ (BX), R11 // 4c0f38f01b - MOVBEQQ (R11), R11 // 4d0f38f01b + MOVBEW DX, (BX) // 660f38f113 + MOVBEW R11, (BX) // 66440f38f11b + MOVBEW DX, (R11) // 66410f38f113 + MOVBEW R11, (R11) // 66450f38f11b + MOVBEW (BX), DX // 660f38f013 + MOVBEW (R11), DX // 66410f38f013 + MOVBEW (BX), R11 // 66440f38f01b + MOVBEW (R11), R11 // 66450f38f01b + MOVBEL DX, (BX) // 0f38f113 + MOVBEL R11, (BX) // 440f38f11b + MOVBEL DX, (R11) // 410f38f113 + MOVBEL R11, (R11) // 450f38f11b + MOVBEL (BX), DX // 0f38f013 + MOVBEL (R11), DX // 410f38f013 + MOVBEL (BX), R11 // 440f38f01b + MOVBEL (R11), R11 // 450f38f01b + MOVBEQ DX, (BX) // 480f38f113 + MOVBEQ R11, (BX) // 4c0f38f11b + MOVBEQ DX, (R11) // 490f38f113 + MOVBEQ R11, (R11) // 4d0f38f11b + MOVBEQ (BX), DX // 480f38f013 + MOVBEQ (R11), DX // 490f38f013 + MOVBEQ (BX), R11 // 4c0f38f01b + MOVBEQ (R11), R11 // 4d0f38f01b MOVQ (BX), M2 // 0f6e13 or 0f6f13 or 480f6e13 MOVQ (R11), M2 // 410f6e13 or 410f6f13 or 490f6e13 MOVQ DX, M2 // 0f6ed2 or 480f6ed2 diff --git a/src/cmd/internal/obj/x86/aenum.go b/src/cmd/internal/obj/x86/aenum.go index 2c035641f5..f0913d7c55 100644 --- a/src/cmd/internal/obj/x86/aenum.go +++ b/src/cmd/internal/obj/x86/aenum.go @@ -496,9 +496,9 @@ const ( AMOVAPD AMOVAPS AMOVB - AMOVBELL - AMOVBEQQ - AMOVBEWW + AMOVBEL + AMOVBEQ + AMOVBEW AMOVBLSX AMOVBLZX AMOVBQSX diff --git a/src/cmd/internal/obj/x86/anames.go b/src/cmd/internal/obj/x86/anames.go index e6c00bdbe0..7869e366f9 100644 --- a/src/cmd/internal/obj/x86/anames.go +++ b/src/cmd/internal/obj/x86/anames.go @@ -494,9 +494,9 @@ var Anames = []string{ "MOVAPD", "MOVAPS", "MOVB", - "MOVBELL", - "MOVBEQQ", - "MOVBEWW", + "MOVBEL", + "MOVBEQ", + "MOVBEW", "MOVBLSX", "MOVBLZX", "MOVBQSX", diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go index 331a98dfef..43ce832b17 100644 --- a/src/cmd/internal/obj/x86/asm6.go +++ b/src/cmd/internal/obj/x86/asm6.go @@ -1735,9 +1735,9 @@ var optab = {ASTRL, yincq, Px, opBytes{0x0f, 0x00, 01}}, {ASTRQ, yincq, Pw, opBytes{0x0f, 0x00, 01}}, {AXSETBV, ynone, Pm, opBytes{0x01, 0xd1, 0}}, - {AMOVBEWW, ymovbe, Pq, opBytes{0x38, 0xf0, 0, 0x38, 0xf1, 0}}, - {AMOVBELL, ymovbe, Pm, opBytes{0x38, 0xf0, 0, 0x38, 0xf1, 0}}, - {AMOVBEQQ, ymovbe, Pw, opBytes{0x0f, 0x38, 0xf0, 0, 0x0f, 0x38, 0xf1, 0}}, + {AMOVBEW, ymovbe, Pq, opBytes{0x38, 0xf0, 0, 0x38, 0xf1, 0}}, + {AMOVBEL, ymovbe, Pm, opBytes{0x38, 0xf0, 0, 0x38, 0xf1, 0}}, + {AMOVBEQ, ymovbe, Pw, opBytes{0x0f, 0x38, 0xf0, 0, 0x0f, 0x38, 0xf1, 0}}, {ANOPW, ydivl, Pe, opBytes{0x0f, 0x1f, 00}}, {ANOPL, ydivl, Px, opBytes{0x0f, 0x1f, 00}}, {ASLDTW, yincq, Pe, opBytes{0x0f, 0x00, 00}}, -- GitLab From e1c294a56d5d03cdba1f059cdb6b1225477dc546 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Garc=C3=ADa=20Montoro?= Date: Fri, 14 May 2021 18:42:16 +0200 Subject: [PATCH 1537/2500] cmd/compile: eliminate successive swaps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The code generated when storing eight bytes loaded from memory in big endian introduced two successive byte swaps that did not actually modified the data. The new rules match this specific pattern both for amd64 and for arm64, eliminating the double swap. Fixes #41684 Change-Id: Icb6dc20b68e4393cef4fe6a07b33aba0d18c3ff3 Reviewed-on: https://go-review.googlesource.com/c/go/+/320073 Reviewed-by: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Trust: Daniel Martí Trust: Dmitri Shuralyov --- src/cmd/compile/internal/ssa/gen/AMD64.rules | 2 ++ src/cmd/compile/internal/ssa/gen/ARM64.rules | 2 ++ src/cmd/compile/internal/ssa/rewriteAMD64.go | 32 ++++++++++++++++++++ src/cmd/compile/internal/ssa/rewriteARM64.go | 32 ++++++++++++++++++++ test/codegen/memcombine.go | 12 ++++++++ 5 files changed, 80 insertions(+) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 1c63a3f70c..9c476d885a 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -2217,3 +2217,5 @@ (AND(Q|L) x (NEG(Q|L) x)) && buildcfg.GOAMD64 >= 3 => (BLSI(Q|L) x) (XOR(Q|L) x (ADD(Q|L)const [-1] x)) && buildcfg.GOAMD64 >= 3 => (BLSMSK(Q|L) x) (AND(Q|L) x (ADD(Q|L)const [-1] x)) && buildcfg.GOAMD64 >= 3 => (BLSR(Q|L) x) + +(BSWAP(Q|L) (BSWAP(Q|L) p)) => p diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index 02fb4e1990..d34e1899db 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -2931,3 +2931,5 @@ && isInlinableMemmove(dst, src, sz, config) && clobber(call) => (Move [sz] dst src mem) + +((REV|REVW) ((REV|REVW) p)) => p diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 10d3afbc7d..88c76dd169 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -70,6 +70,10 @@ func rewriteValueAMD64(v *Value) bool { return rewriteValueAMD64_OpAMD64ANDQmodify(v) case OpAMD64BSFQ: return rewriteValueAMD64_OpAMD64BSFQ(v) + case OpAMD64BSWAPL: + return rewriteValueAMD64_OpAMD64BSWAPL(v) + case OpAMD64BSWAPQ: + return rewriteValueAMD64_OpAMD64BSWAPQ(v) case OpAMD64BTCLconst: return rewriteValueAMD64_OpAMD64BTCLconst(v) case OpAMD64BTCQconst: @@ -3607,6 +3611,34 @@ func rewriteValueAMD64_OpAMD64BSFQ(v *Value) bool { } return false } +func rewriteValueAMD64_OpAMD64BSWAPL(v *Value) bool { + v_0 := v.Args[0] + // match: (BSWAPL (BSWAPL p)) + // result: p + for { + if v_0.Op != OpAMD64BSWAPL { + break + } + p := v_0.Args[0] + v.copyOf(p) + return true + } + return false +} +func rewriteValueAMD64_OpAMD64BSWAPQ(v *Value) bool { + v_0 := v.Args[0] + // match: (BSWAPQ (BSWAPQ p)) + // result: p + for { + if v_0.Op != OpAMD64BSWAPQ { + break + } + p := v_0.Args[0] + v.copyOf(p) + return true + } + return false +} func rewriteValueAMD64_OpAMD64BTCLconst(v *Value) bool { v_0 := v.Args[0] // match: (BTCLconst [c] (XORLconst [d] x)) diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index 8ad9e400eb..ad34855c30 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -335,6 +335,10 @@ func rewriteValueARM64(v *Value) bool { return rewriteValueARM64_OpARM64ORshiftRL(v) case OpARM64ORshiftRO: return rewriteValueARM64_OpARM64ORshiftRO(v) + case OpARM64REV: + return rewriteValueARM64_OpARM64REV(v) + case OpARM64REVW: + return rewriteValueARM64_OpARM64REVW(v) case OpARM64ROR: return rewriteValueARM64_OpARM64ROR(v) case OpARM64RORW: @@ -20299,6 +20303,34 @@ func rewriteValueARM64_OpARM64ORshiftRO(v *Value) bool { } return false } +func rewriteValueARM64_OpARM64REV(v *Value) bool { + v_0 := v.Args[0] + // match: (REV (REV p)) + // result: p + for { + if v_0.Op != OpARM64REV { + break + } + p := v_0.Args[0] + v.copyOf(p) + return true + } + return false +} +func rewriteValueARM64_OpARM64REVW(v *Value) bool { + v_0 := v.Args[0] + // match: (REVW (REVW p)) + // result: p + for { + if v_0.Op != OpARM64REVW { + break + } + p := v_0.Args[0] + v.copyOf(p) + return true + } + return false +} func rewriteValueARM64_OpARM64ROR(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] diff --git a/test/codegen/memcombine.go b/test/codegen/memcombine.go index d74dae07f5..2a0c534df0 100644 --- a/test/codegen/memcombine.go +++ b/test/codegen/memcombine.go @@ -432,6 +432,18 @@ func store_be32(b []byte) { binary.BigEndian.PutUint32(b, sink32) } +func store_be64_load(b, x *[8]byte) { + // arm64:-`REV` + // amd64:-`BSWAPQ` + binary.BigEndian.PutUint64(b[:], binary.BigEndian.Uint64(x[:])) +} + +func store_be32_load(b, x *[8]byte) { + // arm64:-`REVW` + // amd64:-`BSWAPL` + binary.BigEndian.PutUint32(b[:], binary.BigEndian.Uint32(x[:])) +} + func store_be32_idx(b []byte, idx int) { // amd64:`BSWAPL`,-`SHR.` // arm64:`REVW`,`MOVW\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOV[BH]`,-`REV16W` -- GitLab From eba91e83b05f146892aec8922615e77b6496d886 Mon Sep 17 00:00:00 2001 From: Sean Liao Date: Sat, 9 Oct 2021 12:22:01 +0200 Subject: [PATCH 1538/2500] sync: use example.com for url in ExampleWaitGroup Fixes #48886 Change-Id: I1093ae0ba30dab5a73d4d6bcfd083564d13877a6 Reviewed-on: https://go-review.googlesource.com/c/go/+/354830 Reviewed-by: Alberto Donizetti Reviewed-by: Meng Zhuo Trust: Alberto Donizetti --- src/sync/example_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sync/example_test.go b/src/sync/example_test.go index bdd3af6fed..f009a68cf2 100644 --- a/src/sync/example_test.go +++ b/src/sync/example_test.go @@ -22,7 +22,7 @@ func ExampleWaitGroup() { var urls = []string{ "http://www.golang.org/", "http://www.google.com/", - "http://www.somestupidname.com/", + "http://www.example.com/", } for _, url := range urls { // Increment the WaitGroup counter. -- GitLab From ba2c9fef035da3ef93e0eb0dbf4d583663829139 Mon Sep 17 00:00:00 2001 From: Jake Ciolek Date: Sat, 9 Oct 2021 17:57:06 +0200 Subject: [PATCH 1539/2500] cmd/compile: mark NOT as an op that doesn't clobber flags on i386/AMD64 NOT does not affect any FLAGS register values on i386/AMD64 so we do not need to mark it as an Op that clobbers them. Change-Id: I6d99cad49cfa2568b01e58190256582b18fb3b7b Reviewed-on: https://go-review.googlesource.com/c/go/+/354831 Reviewed-by: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Trust: Josh Bleecher Snyder --- src/cmd/compile/internal/ssa/gen/386Ops.go | 2 +- src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 4 ++-- src/cmd/compile/internal/ssa/opGen.go | 3 --- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/ssa/gen/386Ops.go b/src/cmd/compile/internal/ssa/gen/386Ops.go index 3512d60865..a6da7a5fce 100644 --- a/src/cmd/compile/internal/ssa/gen/386Ops.go +++ b/src/cmd/compile/internal/ssa/gen/386Ops.go @@ -298,7 +298,7 @@ func init() { // unary ops {name: "NEGL", argLength: 1, reg: gp11, asm: "NEGL", resultInArg0: true, clobberFlags: true}, // -arg0 - {name: "NOTL", argLength: 1, reg: gp11, asm: "NOTL", resultInArg0: true, clobberFlags: true}, // ^arg0 + {name: "NOTL", argLength: 1, reg: gp11, asm: "NOTL", resultInArg0: true}, // ^arg0 {name: "BSFL", argLength: 1, reg: gp11, asm: "BSFL", clobberFlags: true}, // arg0 # of low-order zeroes ; undef if zero {name: "BSFW", argLength: 1, reg: gp11, asm: "BSFW", clobberFlags: true}, // arg0 # of low-order zeroes ; undef if zero diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index 1887772736..731454c761 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -513,8 +513,8 @@ func init() { {name: "NEGQ", argLength: 1, reg: gp11, asm: "NEGQ", resultInArg0: true, clobberFlags: true}, // -arg0 {name: "NEGL", argLength: 1, reg: gp11, asm: "NEGL", resultInArg0: true, clobberFlags: true}, // -arg0 - {name: "NOTQ", argLength: 1, reg: gp11, asm: "NOTQ", resultInArg0: true, clobberFlags: true}, // ^arg0 - {name: "NOTL", argLength: 1, reg: gp11, asm: "NOTL", resultInArg0: true, clobberFlags: true}, // ^arg0 + {name: "NOTQ", argLength: 1, reg: gp11, asm: "NOTQ", resultInArg0: true}, // ^arg0 + {name: "NOTL", argLength: 1, reg: gp11, asm: "NOTL", resultInArg0: true}, // ^arg0 // BS{F,R}Q returns a tuple [result, flags] // result is undefined if the input is zero. diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 09006c8c85..640e517fe7 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -4733,7 +4733,6 @@ var opcodeTable = [...]opInfo{ name: "NOTL", argLen: 1, resultInArg0: true, - clobberFlags: true, asm: x86.ANOTL, reg: regInfo{ inputs: []inputInfo{ @@ -10777,7 +10776,6 @@ var opcodeTable = [...]opInfo{ name: "NOTQ", argLen: 1, resultInArg0: true, - clobberFlags: true, asm: x86.ANOTQ, reg: regInfo{ inputs: []inputInfo{ @@ -10792,7 +10790,6 @@ var opcodeTable = [...]opInfo{ name: "NOTL", argLen: 1, resultInArg0: true, - clobberFlags: true, asm: x86.ANOTL, reg: regInfo{ inputs: []inputInfo{ -- GitLab From b99abf3cce16721d79351c92031239a27fec3d22 Mon Sep 17 00:00:00 2001 From: Jake Ciolek Date: Sat, 9 Oct 2021 20:09:21 +0200 Subject: [PATCH 1540/2500] cmd/compile: use the shorter version of XOR for breaking POPCNT register dependency XORL accomplishes the same thing while being shorter to encode. Change-Id: I4397999ff617edb61a7fb7d1eca757a202ab8134 Reviewed-on: https://go-review.googlesource.com/c/go/+/354832 Reviewed-by: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Trust: Josh Bleecher Snyder --- src/cmd/compile/internal/amd64/ssa.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/amd64/ssa.go b/src/cmd/compile/internal/amd64/ssa.go index 33cd5985e0..78822098a7 100644 --- a/src/cmd/compile/internal/amd64/ssa.go +++ b/src/cmd/compile/internal/amd64/ssa.go @@ -1125,7 +1125,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { if v.Args[0].Reg() != v.Reg() { // POPCNT on Intel has a false dependency on the destination register. // Xor register with itself to break the dependency. - p := s.Prog(x86.AXORQ) + p := s.Prog(x86.AXORL) p.From.Type = obj.TYPE_REG p.From.Reg = v.Reg() p.To.Type = obj.TYPE_REG -- GitLab From d2d21d98e4f9181f92f3d484623ed4153444877c Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Sat, 9 Oct 2021 15:17:03 -0700 Subject: [PATCH 1541/2500] cmd/compile: used TESTL instead of TESTQ for cpu feature flag detection Uses one less byte when encoded. Performance is unchanged. Change-Id: If400c9c9fc07a033e5ae9bf975ec512e432f7825 Reviewed-on: https://go-review.googlesource.com/c/go/+/354949 Trust: Keith Randall Trust: Josh Bleecher Snyder Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Josh Bleecher Snyder --- src/cmd/compile/internal/ssa/gen/AMD64.rules | 2 +- src/cmd/compile/internal/ssa/rewriteAMD64.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 9c476d885a..8b73ee14ea 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -472,7 +472,7 @@ (GetCallerPC ...) => (LoweredGetCallerPC ...) (GetCallerSP ...) => (LoweredGetCallerSP ...) -(HasCPUFeature {s}) => (SETNE (CMPQconst [0] (LoweredHasCPUFeature {s}))) +(HasCPUFeature {s}) => (SETNE (CMPLconst [0] (LoweredHasCPUFeature {s}))) (Addr {sym} base) => (LEAQ {sym} base) (LocalAddr {sym} base _) => (LEAQ {sym} base) diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 88c76dd169..201fbf2954 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -29254,11 +29254,11 @@ func rewriteValueAMD64_OpHasCPUFeature(v *Value) bool { b := v.Block typ := &b.Func.Config.Types // match: (HasCPUFeature {s}) - // result: (SETNE (CMPQconst [0] (LoweredHasCPUFeature {s}))) + // result: (SETNE (CMPLconst [0] (LoweredHasCPUFeature {s}))) for { s := auxToSym(v.Aux) v.reset(OpAMD64SETNE) - v0 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags) + v0 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags) v0.AuxInt = int32ToAuxInt(0) v1 := b.NewValue0(v.Pos, OpAMD64LoweredHasCPUFeature, typ.UInt64) v1.Aux = symToAux(s) -- GitLab From 59b2f516e8ec66b76789142fbba4787a0e80d09a Mon Sep 17 00:00:00 2001 From: "Paul E. Murphy" Date: Mon, 29 Mar 2021 16:15:50 -0500 Subject: [PATCH 1542/2500] cmd/internal/obj/ppc64: remove unused REG_DCR types The assembler does not support parsing DCRx registers, nor does the compiler generate opcodes with these. Likewise, these registers are only available on ISA 2.07 embedded processors which are not supported in golang. Change-Id: Iea258e5958a2022bda0eee8348de1b06437148df Reviewed-on: https://go-review.googlesource.com/c/go/+/352790 Reviewed-by: Cherry Mui Run-TryBot: Cherry Mui Run-TryBot: Lynn Boger TryBot-Result: Go Bot Trust: Lynn Boger --- src/cmd/internal/obj/ppc64/a.out.go | 1 - src/cmd/internal/obj/ppc64/asm9.go | 18 +++--------------- src/cmd/internal/obj/ppc64/list9.go | 5 +---- 3 files changed, 4 insertions(+), 20 deletions(-) diff --git a/src/cmd/internal/obj/ppc64/a.out.go b/src/cmd/internal/obj/ppc64/a.out.go index b5696f7993..3a1e2d3c9a 100644 --- a/src/cmd/internal/obj/ppc64/a.out.go +++ b/src/cmd/internal/obj/ppc64/a.out.go @@ -231,7 +231,6 @@ const ( REG_SPECIAL = REG_CR0 REG_SPR0 = obj.RBasePPC64 + 1024 // first of 1024 registers - REG_DCR0 = obj.RBasePPC64 + 2048 // first of 1024 registers REG_XER = REG_SPR0 + 1 REG_LR = REG_SPR0 + 8 diff --git a/src/cmd/internal/obj/ppc64/asm9.go b/src/cmd/internal/obj/ppc64/asm9.go index 1d92c4866f..ff94fa72c7 100644 --- a/src/cmd/internal/obj/ppc64/asm9.go +++ b/src/cmd/internal/obj/ppc64/asm9.go @@ -828,10 +828,6 @@ func (c *ctxt9) aclass(a *obj.Addr) int { return C_SPR } - - if REG_DCR0 <= a.Reg && a.Reg <= REG_DCR0+1023 { - return C_SPR - } if a.Reg == REG_FPSCR { return C_FPSCR } @@ -3341,25 +3337,17 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) { } o1 = OP_MTFSFI | (uint32(p.To.Reg)&15)<<23 | (uint32(c.regoff(&p.From))&31)<<12 - case 66: /* mov spr,r1; mov r1,spr, also dcr */ + case 66: /* mov spr,r1; mov r1,spr */ var r int var v int32 if REG_R0 <= p.From.Reg && p.From.Reg <= REG_R31 { r = int(p.From.Reg) v = int32(p.To.Reg) - if REG_DCR0 <= v && v <= REG_DCR0+1023 { - o1 = OPVCC(31, 451, 0, 0) /* mtdcr */ - } else { - o1 = OPVCC(31, 467, 0, 0) /* mtspr */ - } + o1 = OPVCC(31, 467, 0, 0) /* mtspr */ } else { r = int(p.To.Reg) v = int32(p.From.Reg) - if REG_DCR0 <= v && v <= REG_DCR0+1023 { - o1 = OPVCC(31, 323, 0, 0) /* mfdcr */ - } else { - o1 = OPVCC(31, 339, 0, 0) /* mfspr */ - } + o1 = OPVCC(31, 339, 0, 0) /* mfspr */ } o1 = AOP_RRR(o1, uint32(r), 0, 0) | (uint32(v)&0x1f)<<16 | ((uint32(v)>>5)&0x1f)<<11 diff --git a/src/cmd/internal/obj/ppc64/list9.go b/src/cmd/internal/obj/ppc64/list9.go index 461950dc60..8b0b36f375 100644 --- a/src/cmd/internal/obj/ppc64/list9.go +++ b/src/cmd/internal/obj/ppc64/list9.go @@ -35,7 +35,7 @@ import ( ) func init() { - obj.RegisterRegister(obj.RBasePPC64, REG_DCR0+1024, rconv) + obj.RegisterRegister(obj.RBasePPC64, REG_SPR0+1024, rconv) obj.RegisterOpcode(obj.ABasePPC64, Anames) } @@ -80,9 +80,6 @@ func rconv(r int) string { return fmt.Sprintf("SPR(%d)", r-REG_SPR0) } - if REG_DCR0 <= r && r <= REG_DCR0+1023 { - return fmt.Sprintf("DCR(%d)", r-REG_DCR0) - } if r == REG_FPSCR { return "FPSCR" } -- GitLab From 34f7b1f841cc450cc3aba42019e613fd03a84fce Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Fri, 8 Oct 2021 11:14:35 -0400 Subject: [PATCH 1543/2500] go/parser: clean up unnecessary arguments and replace an if statement Eliminate an unnecessary argument from parseGenericType, and replace an if statement with a switch. Change-Id: Iaa8afeface929332579f183c8e523961cca9aca4 Reviewed-on: https://go-review.googlesource.com/c/go/+/354869 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/parser/parser.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go index 049515656c..dd6b93d20f 100644 --- a/src/go/parser/parser.go +++ b/src/go/parser/parser.go @@ -2506,9 +2506,9 @@ func (p *parser) parseValueSpec(doc *ast.CommentGroup, _ token.Pos, keyword toke return spec } -func (p *parser) parseGenericType(spec *ast.TypeSpec, openPos token.Pos, name0 *ast.Ident, closeTok token.Token) { - list := p.parseParameterList(name0, closeTok, p.parseParamDecl, true) - closePos := p.expect(closeTok) +func (p *parser) parseGenericType(spec *ast.TypeSpec, openPos token.Pos, name0 *ast.Ident) { + list := p.parseParameterList(name0, token.RBRACK, p.parseParamDecl, true) + closePos := p.expect(token.RBRACK) spec.TypeParams = &ast.FieldList{Opening: openPos, List: list, Closing: closePos} // Type alias cannot have type parameters. Accept them for robustness but complain. if p.tok == token.ASSIGN { @@ -2537,7 +2537,7 @@ func (p *parser) parseTypeSpec(doc *ast.CommentGroup, _ token.Pos, _ token.Token p.exprLev-- if name0, _ := x.(*ast.Ident); p.parseTypeParams() && name0 != nil && p.tok != token.RBRACK { // generic type [T any]; - p.parseGenericType(spec, lbrack, name0, token.RBRACK) + p.parseGenericType(spec, lbrack, name0) } else { // array type // TODO(rfindley) should resolve all identifiers in x. @@ -2619,10 +2619,11 @@ func (p *parser) parseFuncDecl() *ast.FuncDecl { results := p.parseResult() var body *ast.BlockStmt - if p.tok == token.LBRACE { + switch p.tok { + case token.LBRACE: body = p.parseBody() p.expectSemi() - } else if p.tok == token.SEMICOLON { + case token.SEMICOLON: p.next() if p.tok == token.LBRACE { // opening { of function declaration on next line @@ -2630,7 +2631,7 @@ func (p *parser) parseFuncDecl() *ast.FuncDecl { body = p.parseBody() p.expectSemi() } - } else { + default: p.expectSemi() } -- GitLab From 702e33717486cb8331db17304f2369ef641da61f Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 7 Oct 2021 09:56:29 -0400 Subject: [PATCH 1544/2500] regexp: document and implement that invalid UTF-8 bytes are the same as U+FFFD What should it mean to run a regexp match on invalid UTF-8 bytes? The coherent behavior options are: 1. Invalid UTF-8 does not match any character classes, nor a U+FFFD literal (nor \x{fffd}). 2. Each byte of invalid UTF-8 is treated identically to a U+FFFD in the input, as a utf8.DecodeRune loop might. RE2 uses Rule 1. Because it works byte at a time, it can also provide \C to match any single byte of input, which matches invalid UTF-8 as well. This provides the nice property that a match for a regexp without \C is guaranteed to be valid UTF-8. Unfortunately, today Go has an incoherent mix of these two, although mostly Rule 2. This is a deviation from RE2, and it gives up the nice property, but we probably can't correct that at this point. In particular .* already matches entire inputs today, valid UTF-8 or not, and I doubt we can break that. This CL adopts Rule 2 officially, fixing the few places that deviate from it. Fixes #48749. Change-Id: I96402527c5dfb1146212f568ffa09dde91d71244 Reviewed-on: https://go-review.googlesource.com/c/go/+/354569 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Rob Pike --- src/regexp/all_test.go | 3 +++ src/regexp/find_test.go | 7 +++++++ src/regexp/onepass.go | 3 ++- src/regexp/regexp.go | 8 +++++++- src/regexp/syntax/prog.go | 3 ++- 5 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/regexp/all_test.go b/src/regexp/all_test.go index be7a2e7111..c233cfa9ea 100644 --- a/src/regexp/all_test.go +++ b/src/regexp/all_test.go @@ -372,6 +372,9 @@ var literalPrefixTests = []MetaTest{ {`^^0$$`, ``, ``, false}, {`^$^$`, ``, ``, false}, {`$$0^^`, ``, ``, false}, + {`a\x{fffd}b`, ``, `a`, false}, + {`\x{fffd}b`, ``, ``, false}, + {"\ufffd", ``, ``, false}, } func TestQuoteMeta(t *testing.T) { diff --git a/src/regexp/find_test.go b/src/regexp/find_test.go index 64c2239d90..2edbe9b86e 100644 --- a/src/regexp/find_test.go +++ b/src/regexp/find_test.go @@ -116,6 +116,13 @@ var findTests = []FindTest{ {"\\`", "`", build(1, 0, 1)}, {"[\\`]+", "`", build(1, 0, 1)}, + {"\ufffd", "\xff", build(1, 0, 1)}, + {"\ufffd", "hello\xffworld", build(1, 5, 6)}, + {`.*`, "hello\xffworld", build(1, 0, 11)}, + {`\x{fffd}`, "\xc2\x00", build(1, 0, 1)}, + {"[\ufffd]", "\xff", build(1, 0, 1)}, + {`[\x{fffd}]`, "\xc2\x00", build(1, 0, 1)}, + // long set of matches (longer than startSize) { ".", diff --git a/src/regexp/onepass.go b/src/regexp/onepass.go index 2f3ce6f9f6..bc47f4c4a8 100644 --- a/src/regexp/onepass.go +++ b/src/regexp/onepass.go @@ -9,6 +9,7 @@ import ( "sort" "strings" "unicode" + "unicode/utf8" ) // "One-pass" regexp execution. @@ -55,7 +56,7 @@ func onePassPrefix(p *syntax.Prog) (prefix string, complete bool, pc uint32) { // Have prefix; gather characters. var buf strings.Builder - for iop(i) == syntax.InstRune && len(i.Rune) == 1 && syntax.Flags(i.Arg)&syntax.FoldCase == 0 { + for iop(i) == syntax.InstRune && len(i.Rune) == 1 && syntax.Flags(i.Arg)&syntax.FoldCase == 0 && i.Rune[0] != utf8.RuneError { buf.WriteRune(i.Rune[0]) pc, i = i.Out, &p.Inst[i.Out] } diff --git a/src/regexp/regexp.go b/src/regexp/regexp.go index bfcf7910cf..af7259c9bf 100644 --- a/src/regexp/regexp.go +++ b/src/regexp/regexp.go @@ -20,6 +20,8 @@ // or any book about automata theory. // // All characters are UTF-8-encoded code points. +// Following utf8.DecodeRune, each byte of an invalid UTF-8 sequence +// is treated as if it encoded utf8.RuneError (U+FFFD). // // There are 16 methods of Regexp that match a regular expression and identify // the matched text. Their names are matched by this regular expression: @@ -276,7 +278,11 @@ func minInputLen(re *syntax.Regexp) int { case syntax.OpLiteral: l := 0 for _, r := range re.Rune { - l += utf8.RuneLen(r) + if r == utf8.RuneError { + l++ + } else { + l += utf8.RuneLen(r) + } } return l case syntax.OpCapture, syntax.OpPlus: diff --git a/src/regexp/syntax/prog.go b/src/regexp/syntax/prog.go index ae7a9a2fe0..8583f55e54 100644 --- a/src/regexp/syntax/prog.go +++ b/src/regexp/syntax/prog.go @@ -8,6 +8,7 @@ import ( "strconv" "strings" "unicode" + "unicode/utf8" ) // Compiled program. @@ -154,7 +155,7 @@ func (p *Prog) Prefix() (prefix string, complete bool) { // Have prefix; gather characters. var buf strings.Builder - for i.op() == InstRune && len(i.Rune) == 1 && Flags(i.Arg)&FoldCase == 0 { + for i.op() == InstRune && len(i.Rune) == 1 && Flags(i.Arg)&FoldCase == 0 && i.Rune[0] != utf8.RuneError { buf.WriteRune(i.Rune[0]) i = p.skipNop(i.Out) } -- GitLab From f2141a71c6619617d32c224bd2e272a07904b8e9 Mon Sep 17 00:00:00 2001 From: Yuval Pavel Zholkover Date: Mon, 11 Oct 2021 00:05:09 +0300 Subject: [PATCH 1545/2500] doc/go1.18: document FreeBSD 11.x will no longer be supported Mention future versions will require the COMPAT_FREEBSD12 kernel option set in the kernel. For #47694. Change-Id: Ia94c4f9dbb38c68025d3c1d12dd2e241a5480a6b Reviewed-on: https://go-review.googlesource.com/c/go/+/354971 Reviewed-by: Ian Lance Taylor Reviewed-by: Tobias Klauser --- doc/go1.18.html | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 8a5ba487a9..a5b47fa261 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -31,8 +31,11 @@ Do not send CLs removing the interior tags from such phrases.

Ports

-

- TODO: complete this section, or delete if not needed +

+ Go 1.18 is the last release that is supported on FreeBSD 11.x, which has + already reached end-of-life. Go 1.19 will require FreeBSD 12.2+ or FreeBSD + 13.0+. + FreeBSD 13.0+ will require a kernel with the COMPAT_FREEBSD12 option set (this is the default).

Tools

-- GitLab From 2478b6f6d6c1da1085e958ece8b17255aa17be6e Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 8 Oct 2021 19:24:53 -0400 Subject: [PATCH 1546/2500] runtime: simplify multiple text section handling in findfunc In findfunc, we first us the relative PC to find the function's index in functab. When we split text sections, as the external linker may shift the sections, and the PC may not match the (virtual) PC we used to build the functab. So the index may be inaccurate, and we need to do a (forward or backward) linear search to find the actual entry. Instead of using the PC directly, we can first compute the (pre-external-link virtual) relative PC and use that to find the index in functab. This way, the index will be accurate and we will not need to do the special backward linear search. Change-Id: I8ab11c66b7a5a3d79aae00198b98780e10db27b0 Reviewed-on: https://go-review.googlesource.com/c/go/+/354873 Trust: Cherry Mui Trust: Josh Bleecher Snyder Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Josh Bleecher Snyder --- src/runtime/symtab.go | 70 +++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index e35d8047a1..ced39026c9 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -673,6 +673,33 @@ func (md *moduledata) textAddr(off32 uint32) uintptr { return res } +// textOff is the opposite of textAddr. It converts a PC to a (virtual) offset +// to md.text, and returns if the PC is in any Go text section. +// +// It is nosplit because it is part of the findfunc implementation. +//go:nosplit +func (md *moduledata) textOff(pc uintptr) (uint32, bool) { + res := uint32(pc - md.text) + if len(md.textsectmap) > 1 { + for i, sect := range md.textsectmap { + if sect.baseaddr > pc { + // pc is not in any section. + return 0, false + } + end := sect.baseaddr + (sect.end - sect.vaddr) + // For the last section, include the end address (etext), as it is included in the functab. + if i == len(md.textsectmap) { + end++ + } + if pc < end { + res = uint32(pc - sect.baseaddr + sect.vaddr) + break + } + } + } + return res, true +} + // FuncForPC returns a *Func describing the function that contains the // given program counter address, or else nil. // @@ -796,7 +823,12 @@ func findfunc(pc uintptr) funcInfo { } const nsub = uintptr(len(findfuncbucket{}.subbuckets)) - x := pc - datap.minpc + pcOff, ok := datap.textOff(pc) + if !ok { + return funcInfo{} + } + + x := uintptr(pcOff) + datap.text - datap.minpc // TODO: are datap.text and datap.minpc always equal? b := x / pcbucketsize i := x % pcbucketsize / (pcbucketsize / nsub) @@ -804,43 +836,11 @@ func findfunc(pc uintptr) funcInfo { idx := ffb.idx + uint32(ffb.subbuckets[i]) // Find the ftab entry. - if len(datap.textsectmap) == 1 { - // fast path for the common case - pcOff := uint32(pc - datap.text) - for datap.ftab[idx+1].entryoff <= pcOff { - idx++ - } - } else { - // Multiple text sections. - // If the idx is beyond the end of the ftab, set it to the end of the table and search backward. - if idx >= uint32(len(datap.ftab)) { - idx = uint32(len(datap.ftab) - 1) - } - if pc < datap.textAddr(datap.ftab[idx].entryoff) { - // The idx might reference a function address that - // is higher than the pcOff being searched, so search backward until the matching address is found. - for datap.textAddr(datap.ftab[idx].entryoff) > pc && idx > 0 { - idx-- - } - if idx == 0 { - throw("findfunc: bad findfunctab entry idx") - } - } else { - // linear search to find func with pc >= entry. - for datap.textAddr(datap.ftab[idx+1].entryoff) <= pc { - idx++ - } - } + for datap.ftab[idx+1].entryoff <= pcOff { + idx++ } funcoff := datap.ftab[idx].funcoff - if funcoff == ^uint32(0) { - // With multiple text sections, there may be functions inserted by the external - // linker that are not known by Go. This means there may be holes in the PC - // range covered by the func table. The invalid funcoff value indicates a hole. - // See also cmd/link/internal/ld/pcln.go:pclntab - return funcInfo{} - } return funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[funcoff])), datap} } -- GitLab From bd41f2d3cd82a37e85fcf44067ffd2f728554a3b Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 8 Oct 2021 19:55:17 -0400 Subject: [PATCH 1547/2500] cmd/link: do not mark holes in functab With multiple text sections, there may be holes (non-Go code) in the PC range of Go code and covered by the functab. Previously, we use a linear search with actual PCs to find the functab entry. We need to use special entries to mark holes, so a PC in the hole can be distinguished from the previous function. Now, with the previous CL we find if the PC is in between of the sections upfront in textOff. There is no need to mark holes in the functab. Change-Id: I22ff27279422bfc855c2ca35ba0fdfb63234c113 Reviewed-on: https://go-review.googlesource.com/c/go/+/354874 Trust: Cherry Mui Trust: Josh Bleecher Snyder Reviewed-by: Josh Bleecher Snyder --- src/cmd/link/internal/ld/pcln.go | 35 ++++---------------------------- 1 file changed, 4 insertions(+), 31 deletions(-) diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index 465c52b6cf..b57e212794 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -72,7 +72,6 @@ func makePclntab(ctxt *Link, container loader.Bitmap) (*pclntab, []*sym.Compilat // Gather some basic stats and info. seenCUs := make(map[*sym.CompilationUnit]struct{}) - prevSect := ldr.SymSect(ctxt.Textp[0]) compUnits := []*sym.CompilationUnit{} funcs := []loader.Sym{} @@ -86,16 +85,6 @@ func makePclntab(ctxt *Link, container loader.Bitmap) (*pclntab, []*sym.Compilat state.firstFunc = s } state.lastFunc = s - ss := ldr.SymSect(s) - if ss != prevSect { - // With multiple text sections, the external linker may - // insert functions between the sections, which are not - // known by Go. This leaves holes in the PC range covered - // by the func table. We need to generate an entry to mark - // the hole. - state.nfunc++ - prevSect = ss - } // We need to keep track of all compilation units we see. Some symbols // (eg, go.buildid, _cgoexp_, etc) won't have a compilation unit. @@ -624,30 +613,14 @@ func writePCToFunc(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, sta } return uint32(off) } - var prevFunc loader.Sym - prevSect := ldr.SymSect(funcs[0]) - funcIndex := 0 for i, s := range funcs { - if thisSect := ldr.SymSect(s); thisSect != prevSect { - // With multiple text sections, there may be a hole here in the - // address space. We use an invalid funcoff value to mark the hole. - // Use the end PC - 1 to distinguish the end of a section vs. the - // start of the next. - // See also runtime/symtab.go:findfunc - prevFuncSize := uint32(ldr.SymSize(prevFunc)) - sb.SetUint32(ctxt.Arch, int64(funcIndex*2*4), pcOff(prevFunc)+prevFuncSize-1) - sb.SetUint32(ctxt.Arch, int64((funcIndex*2+1)*4), ^uint32(0)) - funcIndex++ - prevSect = thisSect - } - prevFunc = s - sb.SetUint32(ctxt.Arch, int64(funcIndex*2*4), pcOff(s)) - sb.SetUint32(ctxt.Arch, int64((funcIndex*2+1)*4), startLocations[i]) - funcIndex++ + sb.SetUint32(ctxt.Arch, int64(i*2*4), pcOff(s)) + sb.SetUint32(ctxt.Arch, int64((i*2+1)*4), startLocations[i]) } // Final entry of table is just end pc offset. - sb.SetUint32(ctxt.Arch, int64(funcIndex)*2*4, pcOff(prevFunc)+uint32(ldr.SymSize(prevFunc))) + lastFunc := funcs[len(funcs)-1] + sb.SetUint32(ctxt.Arch, int64(len(funcs))*2*4, pcOff(lastFunc)+uint32(ldr.SymSize(lastFunc))) } // writeFuncs writes the func structures and pcdata to runtime.functab. -- GitLab From aa1c6f56398882fea0969396666004d6ea7ddd57 Mon Sep 17 00:00:00 2001 From: "Paul E. Murphy" Date: Thu, 26 Aug 2021 17:14:12 -0500 Subject: [PATCH 1548/2500] cmd/internal/obj/ppc64: fix mtocrf, cleanup other CR ops Fix "MOVW CRx, Rx" and "MOVFL Rx, constant", The FXM field was not encoded correctly. Generate mtocrf instead of mtcrf when a CRx argument is used. This form is much faster. Simplify several conditional statements which test if the register argument is REG_CR or one of REG_CRx if the tested argument is known to be matched as C_CREG. Likewise, a4 is (the From3 arg) is always TYPE_NONE in the existing optab entries for type_ 69. Change-Id: I3a4749b1cbfdfab6a2616586ae59e932e01dae50 Reviewed-on: https://go-review.googlesource.com/c/go/+/352789 Reviewed-by: Cherry Mui Reviewed-by: Lynn Boger --- src/cmd/asm/internal/asm/testdata/ppc64.s | 13 +++++++ src/cmd/internal/obj/ppc64/asm9.go | 43 +++++++++++------------ 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/ppc64.s b/src/cmd/asm/internal/asm/testdata/ppc64.s index 28ceb621cb..b9da48acdd 100644 --- a/src/cmd/asm/internal/asm/testdata/ppc64.s +++ b/src/cmd/asm/internal/asm/testdata/ppc64.s @@ -751,4 +751,17 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0 MOVD XER, R3 // 7c6102a6 MOVFL CR3, CR1 // 4c8c0000 + MOVW CR0, R1 // 7c380026 + MOVW CR7, R1 // 7c301026 + MOVW CR, R1 // 7c200026 + + MOVW R1, CR // 7c2ff120 + MOVFL R1, CR // 7c2ff120 + MOVW R1, CR2 // 7c320120 + MOVFL R1, CR2 // 7c320120 + MOVFL R1, $255 // 7c2ff120 + MOVFL R1, $1 // 7c301120 + MOVFL R1, $128 // 7c380120 + MOVFL R1, $3 // 7c203120 + RET diff --git a/src/cmd/internal/obj/ppc64/asm9.go b/src/cmd/internal/obj/ppc64/asm9.go index ff94fa72c7..0901d64792 100644 --- a/src/cmd/internal/obj/ppc64/asm9.go +++ b/src/cmd/internal/obj/ppc64/asm9.go @@ -36,6 +36,7 @@ import ( "fmt" "log" "math" + "math/bits" "sort" ) @@ -3353,32 +3354,30 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) { o1 = AOP_RRR(o1, uint32(r), 0, 0) | (uint32(v)&0x1f)<<16 | ((uint32(v)>>5)&0x1f)<<11 case 67: /* mcrf crfD,crfS */ - if p.From.Type != obj.TYPE_REG || p.From.Reg < REG_CR0 || REG_CR7 < p.From.Reg || p.To.Type != obj.TYPE_REG || p.To.Reg < REG_CR0 || REG_CR7 < p.To.Reg { - c.ctxt.Diag("illegal CR field number\n%v", p) + if p.From.Reg == REG_CR || p.To.Reg == REG_CR { + c.ctxt.Diag("CR argument must be a conditional register field (CR0-CR7)\n%v", p) } o1 = AOP_RRR(OP_MCRF, ((uint32(p.To.Reg) & 7) << 2), ((uint32(p.From.Reg) & 7) << 2), 0) case 68: /* mfcr rD; mfocrf CRM,rD */ - if p.From.Type == obj.TYPE_REG && REG_CR0 <= p.From.Reg && p.From.Reg <= REG_CR7 { - v := int32(1 << uint(7-(p.To.Reg&7))) /* CR(n) */ - o1 = AOP_RRR(OP_MFCR, uint32(p.To.Reg), 0, 0) | 1<<20 | uint32(v)<<12 /* new form, mfocrf */ - } else { - o1 = AOP_RRR(OP_MFCR, uint32(p.To.Reg), 0, 0) /* old form, whole register */ - } - - case 69: /* mtcrf CRM,rS */ - var v int32 - if p.From3Type() != obj.TYPE_NONE { - if p.To.Reg != 0 { - c.ctxt.Diag("can't use both mask and CR(n)\n%v", p) - } - v = c.regoff(p.GetFrom3()) & 0xff - } else { - if p.To.Reg == 0 { - v = 0xff /* CR */ - } else { - v = 1 << uint(7-(p.To.Reg&7)) /* CR(n) */ - } + o1 = AOP_RRR(OP_MFCR, uint32(p.To.Reg), 0, 0) /* form, whole register */ + if p.From.Reg != REG_CR { + v := uint32(1) << uint(7-(p.From.Reg&7)) /* CR(n) */ + o1 |= 1<<20 | v<<12 /* new form, mfocrf */ + } + + case 69: /* mtcrf CRM,rS, mtocrf CRx,rS */ + var v uint32 + if p.To.Reg == REG_CR { + v = 0xff + } else if p.To.Offset != 0 { // MOVFL gpr, constant + v = uint32(p.To.Offset) + } else { // p.To.Reg == REG_CRx + v = 1 << uint(7-(p.To.Reg&7)) + } + // Use mtocrf form if only one CR field moved. + if bits.OnesCount32(v) == 1 { + v |= 1 << 8 } o1 = AOP_RRR(OP_MTCRF, uint32(p.From.Reg), 0, 0) | uint32(v)<<12 -- GitLab From 577bb7dba11ef2f6588664dcface13fba32bb354 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 11 Oct 2021 12:22:52 -0400 Subject: [PATCH 1549/2500] all: update vendored golang.org/x/tools Now that x/tools/go/types/objectpath has been updates to support type parameters, I ran the following commands to update x/tools inside the cmd module: go get -d golang.org/x/tools@18fa840216958359dc43466f3e70d96add38edbb # main branch go mod tidy go mod vendor Updates #48588 Change-Id: Ibebc1ac2f721d6e2eb1a4f6c610918770d4879ed Reviewed-on: https://go-review.googlesource.com/c/go/+/355012 Trust: Robert Findley Run-TryBot: Dmitri Shuralyov Reviewed-by: Dmitri Shuralyov TryBot-Result: Go Bot --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 +- .../golang.org/x/tools/cover/profile.go | 11 +- .../x/tools/go/analysis/passes/tests/tests.go | 60 +++++- .../go/analysis/passes/unmarshal/unmarshal.go | 3 +- .../x/tools/go/ast/astutil/enclosing.go | 20 +- .../x/tools/go/ast/astutil/rewrite.go | 12 +- .../x/tools/go/ast/inspector/typeof.go | 9 +- .../x/tools/go/types/objectpath/objectpath.go | 151 ++++++++++--- .../internal/typeparams/enabled_go117.go | 12 ++ .../internal/typeparams/enabled_go118.go | 15 ++ .../tools/internal/typeparams/notypeparams.go | 93 -------- .../x/tools/internal/typeparams/typeparams.go | 134 ------------ .../internal/typeparams/typeparams_go117.go | 201 ++++++++++++++++++ .../internal/typeparams/typeparams_go118.go | 189 ++++++++++++++++ src/cmd/vendor/modules.txt | 2 +- 16 files changed, 639 insertions(+), 279 deletions(-) create mode 100644 src/cmd/vendor/golang.org/x/tools/internal/typeparams/enabled_go117.go create mode 100644 src/cmd/vendor/golang.org/x/tools/internal/typeparams/enabled_go118.go delete mode 100644 src/cmd/vendor/golang.org/x/tools/internal/typeparams/notypeparams.go delete mode 100644 src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams.go create mode 100644 src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go create mode 100644 src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go diff --git a/src/cmd/go.mod b/src/cmd/go.mod index c52a936b4e..5431def67a 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -8,7 +8,7 @@ require ( golang.org/x/mod v0.5.1-0.20210913215816-37dd6891021a golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b - golang.org/x/tools v0.1.6-0.20210904010709-360456621443 + golang.org/x/tools v0.1.8-0.20211011152358-18fa84021695 ) require ( diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 9afba00791..0c575bf777 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -18,7 +18,7 @@ golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e h1:XMgFehsDnnLGtjvjOfqWSUzt0 golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/tools v0.1.6-0.20210904010709-360456621443 h1:7JswviZfk9Rtd4NOelZtuLUdkHdruludwWkfOE6sdZk= -golang.org/x/tools v0.1.6-0.20210904010709-360456621443/go.mod h1:YD9qOF0M9xpSpdWTBbzEl5e/RnCefISl8E5Noe10jFM= +golang.org/x/tools v0.1.8-0.20211011152358-18fa84021695 h1:H+g8CC6T05IOoW6fXaWvb5N3XBYQElWwgDS/7Yxg8dU= +golang.org/x/tools v0.1.8-0.20211011152358-18fa84021695/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/src/cmd/vendor/golang.org/x/tools/cover/profile.go b/src/cmd/vendor/golang.org/x/tools/cover/profile.go index 57195774ce..47a9a54116 100644 --- a/src/cmd/vendor/golang.org/x/tools/cover/profile.go +++ b/src/cmd/vendor/golang.org/x/tools/cover/profile.go @@ -10,6 +10,7 @@ import ( "bufio" "errors" "fmt" + "io" "math" "os" "sort" @@ -45,14 +46,18 @@ func ParseProfiles(fileName string) ([]*Profile, error) { return nil, err } defer pf.Close() + return ParseProfilesFromReader(pf) +} - files := make(map[string]*Profile) - buf := bufio.NewReader(pf) +// ParseProfilesFromReader parses profile data from the Reader and +// returns a Profile for each source file described therein. +func ParseProfilesFromReader(rd io.Reader) ([]*Profile, error) { // First line is "mode: foo", where foo is "set", "count", or "atomic". // Rest of file is in the format // encoding/base64/base64.go:34.44,37.40 3 1 // where the fields are: name.go:line.column,line.column numberOfStatements count - s := bufio.NewScanner(buf) + files := make(map[string]*Profile) + s := bufio.NewScanner(rd) mode := "" for s.Scan() { line := s.Text() diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go index 8232276186..570ad5c209 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go @@ -8,7 +8,9 @@ package tests import ( "go/ast" + "go/token" "go/types" + "regexp" "strings" "unicode" "unicode/utf8" @@ -42,10 +44,10 @@ func run(pass *analysis.Pass) (interface{}, error) { // Ignore non-functions or functions with receivers. continue } - switch { case strings.HasPrefix(fn.Name.Name, "Example"): - checkExample(pass, fn) + checkExampleName(pass, fn) + checkExampleOutput(pass, fn, f.Comments) case strings.HasPrefix(fn.Name.Name, "Test"): checkTest(pass, fn, "Test") case strings.HasPrefix(fn.Name.Name, "Benchmark"): @@ -108,7 +110,59 @@ func lookup(pkg *types.Package, name string) []types.Object { return ret } -func checkExample(pass *analysis.Pass, fn *ast.FuncDecl) { +// This pattern is taken from /go/src/go/doc/example.go +var outputRe = regexp.MustCompile(`(?i)^[[:space:]]*(unordered )?output:`) + +type commentMetadata struct { + isOutput bool + pos token.Pos +} + +func checkExampleOutput(pass *analysis.Pass, fn *ast.FuncDecl, fileComments []*ast.CommentGroup) { + commentsInExample := []commentMetadata{} + numOutputs := 0 + + // Find the comment blocks that are in the example. These comments are + // guaranteed to be in order of appearance. + for _, cg := range fileComments { + if cg.Pos() < fn.Pos() { + continue + } else if cg.End() > fn.End() { + break + } + + isOutput := outputRe.MatchString(cg.Text()) + if isOutput { + numOutputs++ + } + + commentsInExample = append(commentsInExample, commentMetadata{ + isOutput: isOutput, + pos: cg.Pos(), + }) + } + + // Change message based on whether there are multiple output comment blocks. + msg := "output comment block must be the last comment block" + if numOutputs > 1 { + msg = "there can only be one output comment block per example" + } + + for i, cg := range commentsInExample { + // Check for output comments that are not the last comment in the example. + isLast := (i == len(commentsInExample)-1) + if cg.isOutput && !isLast { + pass.Report( + analysis.Diagnostic{ + Pos: cg.pos, + Message: msg, + }, + ) + } + } +} + +func checkExampleName(pass *analysis.Pass, fn *ast.FuncDecl) { fnName := fn.Name.Name if params := fn.Type.Params; len(params.List) != 0 { pass.Reportf(fn.Pos(), "%s should be niladic", fnName) diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unmarshal/unmarshal.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unmarshal/unmarshal.go index 92b37caff9..5129048a07 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unmarshal/unmarshal.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unmarshal/unmarshal.go @@ -14,6 +14,7 @@ import ( "golang.org/x/tools/go/analysis/passes/inspect" "golang.org/x/tools/go/ast/inspector" "golang.org/x/tools/go/types/typeutil" + "golang.org/x/tools/internal/typeparams" ) const Doc = `report passing non-pointer or non-interface values to unmarshal @@ -85,7 +86,7 @@ func run(pass *analysis.Pass) (interface{}, error) { t := pass.TypesInfo.Types[call.Args[argidx]].Type switch t.Underlying().(type) { - case *types.Pointer, *types.Interface: + case *types.Pointer, *types.Interface, *typeparams.TypeParam: return } diff --git a/src/cmd/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go b/src/cmd/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go index 6b7052b892..a5c6d6d4fa 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go +++ b/src/cmd/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go @@ -11,6 +11,8 @@ import ( "go/ast" "go/token" "sort" + + "golang.org/x/tools/internal/typeparams" ) // PathEnclosingInterval returns the node that encloses the source @@ -294,8 +296,8 @@ func childrenOf(n ast.Node) []ast.Node { case *ast.FieldList: children = append(children, - tok(n.Opening, len("(")), - tok(n.Closing, len(")"))) + tok(n.Opening, len("(")), // or len("[") + tok(n.Closing, len(")"))) // or len("]") case *ast.File: // TODO test: Doc @@ -322,6 +324,9 @@ func childrenOf(n ast.Node) []ast.Node { children = append(children, n.Recv) } children = append(children, n.Name) + if tparams := typeparams.ForFuncType(n.Type); tparams != nil { + children = append(children, tparams) + } if n.Type.Params != nil { children = append(children, n.Type.Params) } @@ -371,8 +376,13 @@ func childrenOf(n ast.Node) []ast.Node { case *ast.IndexExpr: children = append(children, - tok(n.Lbrack, len("{")), - tok(n.Rbrack, len("}"))) + tok(n.Lbrack, len("[")), + tok(n.Rbrack, len("]"))) + + case *typeparams.IndexListExpr: + children = append(children, + tok(n.Lbrack, len("[")), + tok(n.Rbrack, len("]"))) case *ast.InterfaceType: children = append(children, @@ -581,6 +591,8 @@ func NodeDescription(n ast.Node) string { return "decrement statement" case *ast.IndexExpr: return "index expression" + case *typeparams.IndexListExpr: + return "index list expression" case *ast.InterfaceType: return "interface type" case *ast.KeyValueExpr: diff --git a/src/cmd/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go b/src/cmd/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go index 5fe75b14c7..6d9ca23e2b 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go +++ b/src/cmd/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go @@ -253,6 +253,10 @@ func (a *application) apply(parent ast.Node, name string, iter *iterator, n ast. a.apply(n, "X", nil, n.X) a.apply(n, "Index", nil, n.Index) + case *typeparams.IndexListExpr: + a.apply(n, "X", nil, n.X) + a.applyList(n, "Indices") + case *ast.SliceExpr: a.apply(n, "X", nil, n.X) a.apply(n, "Low", nil, n.Low) @@ -439,13 +443,7 @@ func (a *application) apply(parent ast.Node, name string, iter *iterator, n ast. } default: - if ix := typeparams.GetIndexExprData(n); ix != nil { - a.apply(n, "X", nil, ix.X) - // *ast.IndexExpr was handled above, so n must be an *ast.MultiIndexExpr. - a.applyList(n, "Indices") - } else { - panic(fmt.Sprintf("Apply: unexpected node type %T", n)) - } + panic(fmt.Sprintf("Apply: unexpected node type %T", n)) } if a.post != nil && !a.post(&a.cursor) { diff --git a/src/cmd/vendor/golang.org/x/tools/go/ast/inspector/typeof.go b/src/cmd/vendor/golang.org/x/tools/go/ast/inspector/typeof.go index b6b00cf2e1..11f4fc369a 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/ast/inspector/typeof.go +++ b/src/cmd/vendor/golang.org/x/tools/go/ast/inspector/typeof.go @@ -9,7 +9,11 @@ package inspector // The initial map-based implementation was too slow; // see https://go-review.googlesource.com/c/tools/+/135655/1/go/ast/inspector/inspector.go#196 -import "go/ast" +import ( + "go/ast" + + "golang.org/x/tools/internal/typeparams" +) const ( nArrayType = iota @@ -47,6 +51,7 @@ const ( nImportSpec nIncDecStmt nIndexExpr + nIndexListExpr nInterfaceType nKeyValueExpr nLabeledStmt @@ -164,6 +169,8 @@ func typeOf(n ast.Node) uint64 { return 1 << nIncDecStmt case *ast.IndexExpr: return 1 << nIndexExpr + case *typeparams.IndexListExpr: + return 1 << nIndexListExpr case *ast.InterfaceType: return 1 << nInterfaceType case *ast.KeyValueExpr: diff --git a/src/cmd/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go b/src/cmd/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go index 81e8fdcf0c..7e96fc234e 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go +++ b/src/cmd/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go @@ -23,10 +23,12 @@ package objectpath import ( "fmt" + "go/types" + "sort" "strconv" "strings" - "go/types" + "golang.org/x/tools/internal/typeparams" ) // A Path is an opaque name that identifies a types.Object @@ -57,12 +59,16 @@ type Path string // - The only PO operator is Package.Scope.Lookup, which requires an identifier. // - The only OT operator is Object.Type, // which we encode as '.' because dot cannot appear in an identifier. -// - The TT operators are encoded as [EKPRU]. +// - The TT operators are encoded as [EKPRUTC]; +// one of these (TypeParam) requires an integer operand, +// which is encoded as a string of decimal digits. // - The TO operators are encoded as [AFMO]; // three of these (At,Field,Method) require an integer operand, // which is encoded as a string of decimal digits. // These indices are stable across different representations // of the same package, even source and export data. +// The indices used are implementation specific and may not correspond to +// the argument to the go/types function. // // In the example below, // @@ -89,17 +95,19 @@ const ( opType = '.' // .Type() (Object) // type->type operators - opElem = 'E' // .Elem() (Pointer, Slice, Array, Chan, Map) - opKey = 'K' // .Key() (Map) - opParams = 'P' // .Params() (Signature) - opResults = 'R' // .Results() (Signature) - opUnderlying = 'U' // .Underlying() (Named) + opElem = 'E' // .Elem() (Pointer, Slice, Array, Chan, Map) + opKey = 'K' // .Key() (Map) + opParams = 'P' // .Params() (Signature) + opResults = 'R' // .Results() (Signature) + opUnderlying = 'U' // .Underlying() (Named) + opTypeParam = 'T' // .TypeParams.At(i) (Named, Signature) + opConstraint = 'C' // .Constraint() (TypeParam) // type->object operators - opAt = 'A' // .At(i) (Tuple) - opField = 'F' // .Field(i) (Struct) - opMethod = 'M' // .Method(i) (Named or Interface; not Struct: "promoted" names are ignored) - opObj = 'O' // .Obj() (Named) + opAt = 'A' // .At(i) (Tuple) + opField = 'F' // .Field(i) (Struct) + opMethod = 'M' // .Method(i) (Named or Interface; not Struct: "promoted" names are ignored) + opObj = 'O' // .Obj() (Named, TypeParam) ) // The For function returns the path to an object relative to its package, @@ -190,10 +198,15 @@ func For(obj types.Object) (Path, error) { // 3. Not a package-level object. // Reject obviously non-viable cases. switch obj := obj.(type) { + case *types.TypeName: + if _, ok := obj.Type().(*typeparams.TypeParam); !ok { + // With the exception of type parameters, only package-level type names + // have a path. + return "", fmt.Errorf("no path for %v", obj) + } case *types.Const, // Only package-level constants have a path. - *types.TypeName, // Only package-level types have a path. - *types.Label, // Labels are function-local. - *types.PkgName: // PkgNames are file-local. + *types.Label, // Labels are function-local. + *types.PkgName: // PkgNames are file-local. return "", fmt.Errorf("no path for %v", obj) case *types.Var: @@ -245,6 +258,12 @@ func For(obj types.Object) (Path, error) { return Path(r), nil } } else { + if named, _ := T.(*types.Named); named != nil { + if r := findTypeParam(obj, typeparams.ForNamed(named), path); r != nil { + // generic named type + return Path(r), nil + } + } // defined (named) type if r := find(obj, T.Underlying(), append(path, opUnderlying)); r != nil { return Path(r), nil @@ -270,8 +289,12 @@ func For(obj types.Object) (Path, error) { // Inspect declared methods of defined types. if T, ok := o.Type().(*types.Named); ok { path = append(path, opType) - for i := 0; i < T.NumMethods(); i++ { - m := T.Method(i) + // Note that method index here is always with respect + // to canonical ordering of methods, regardless of how + // they appear in the underlying type. + canonical := canonicalize(T) + for i := 0; i < len(canonical); i++ { + m := canonical[i] path2 := appendOpArg(path, opMethod, i) if m == obj { return Path(path2), nil // found declared method @@ -313,6 +336,9 @@ func find(obj types.Object, T types.Type, path []byte) []byte { } return find(obj, T.Elem(), append(path, opElem)) case *types.Signature: + if r := findTypeParam(obj, typeparams.ForSignature(T), path); r != nil { + return r + } if r := find(obj, T.Params(), append(path, opParams)); r != nil { return r } @@ -353,10 +379,30 @@ func find(obj types.Object, T types.Type, path []byte) []byte { } } return nil + case *typeparams.TypeParam: + name := T.Obj() + if name == obj { + return append(path, opObj) + } + if r := find(obj, T.Constraint(), append(path, opConstraint)); r != nil { + return r + } + return nil } panic(T) } +func findTypeParam(obj types.Object, list *typeparams.TypeParamList, path []byte) []byte { + for i := 0; i < list.Len(); i++ { + tparam := list.At(i) + path2 := appendOpArg(path, opTypeParam, i) + if r := find(obj, tparam, path2); r != nil { + return r + } + } + return nil +} + // Object returns the object denoted by path p within the package pkg. func Object(pkg *types.Package, p Path) (types.Object, error) { if p == "" { @@ -381,10 +427,13 @@ func Object(pkg *types.Package, p Path) (types.Object, error) { type hasElem interface { Elem() types.Type } - // abstraction of *types.{Interface,Named} - type hasMethods interface { - Method(int) *types.Func - NumMethods() int + // abstraction of *types.{Named,Signature} + type hasTypeParams interface { + TypeParams() *typeparams.TypeParamList + } + // abstraction of *types.{Named,TypeParam} + type hasObj interface { + Obj() *types.TypeName } // The loop state is the pair (t, obj), @@ -401,7 +450,7 @@ func Object(pkg *types.Package, p Path) (types.Object, error) { // Codes [AFM] have an integer operand. var index int switch code { - case opAt, opField, opMethod: + case opAt, opField, opMethod, opTypeParam: rest := strings.TrimLeft(suffix, "0123456789") numerals := suffix[:len(suffix)-len(rest)] suffix = rest @@ -466,14 +515,32 @@ func Object(pkg *types.Package, p Path) (types.Object, error) { case opUnderlying: named, ok := t.(*types.Named) if !ok { - return nil, fmt.Errorf("cannot apply %q to %s (got %s, want named)", code, t, t) + return nil, fmt.Errorf("cannot apply %q to %s (got %T, want named)", code, t, t) } t = named.Underlying() + case opTypeParam: + hasTypeParams, ok := t.(hasTypeParams) // Named, Signature + if !ok { + return nil, fmt.Errorf("cannot apply %q to %s (got %T, want named or signature)", code, t, t) + } + tparams := hasTypeParams.TypeParams() + if n := tparams.Len(); index >= n { + return nil, fmt.Errorf("tuple index %d out of range [0-%d)", index, n) + } + t = tparams.At(index) + + case opConstraint: + tparam, ok := t.(*typeparams.TypeParam) + if !ok { + return nil, fmt.Errorf("cannot apply %q to %s (got %T, want type parameter)", code, t, t) + } + t = tparam.Constraint() + case opAt: tuple, ok := t.(*types.Tuple) if !ok { - return nil, fmt.Errorf("cannot apply %q to %s (got %s, want tuple)", code, t, t) + return nil, fmt.Errorf("cannot apply %q to %s (got %T, want tuple)", code, t, t) } if n := tuple.Len(); index >= n { return nil, fmt.Errorf("tuple index %d out of range [0-%d)", index, n) @@ -495,20 +562,21 @@ func Object(pkg *types.Package, p Path) (types.Object, error) { case opMethod: hasMethods, ok := t.(hasMethods) // Interface or Named if !ok { - return nil, fmt.Errorf("cannot apply %q to %s (got %s, want interface or named)", code, t, t) + return nil, fmt.Errorf("cannot apply %q to %s (got %T, want interface or named)", code, t, t) } - if n := hasMethods.NumMethods(); index >= n { + canonical := canonicalize(hasMethods) + if n := len(canonical); index >= n { return nil, fmt.Errorf("method index %d out of range [0-%d)", index, n) } - obj = hasMethods.Method(index) + obj = canonical[index] t = nil case opObj: - named, ok := t.(*types.Named) + hasObj, ok := t.(hasObj) if !ok { - return nil, fmt.Errorf("cannot apply %q to %s (got %s, want named)", code, t, t) + return nil, fmt.Errorf("cannot apply %q to %s (got %T, want named or type param)", code, t, t) } - obj = named.Obj() + obj = hasObj.Obj() t = nil default: @@ -522,3 +590,28 @@ func Object(pkg *types.Package, p Path) (types.Object, error) { return obj, nil // success } + +// hasMethods is an abstraction of *types.{Interface,Named}. This is pulled up +// because it is used by methodOrdering, which is in turn used by both encoding +// and decoding. +type hasMethods interface { + Method(int) *types.Func + NumMethods() int +} + +// canonicalize returns a canonical order for the methods in a hasMethod. +func canonicalize(hm hasMethods) []*types.Func { + count := hm.NumMethods() + if count <= 0 { + return nil + } + canon := make([]*types.Func, count) + for i := 0; i < count; i++ { + canon[i] = hm.Method(i) + } + less := func(i, j int) bool { + return canon[i].Id() < canon[j].Id() + } + sort.Slice(canon, less) + return canon +} diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/enabled_go117.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/enabled_go117.go new file mode 100644 index 0000000000..18212390e1 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/enabled_go117.go @@ -0,0 +1,12 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !go1.18 +// +build !go1.18 + +package typeparams + +// Enabled reports whether type parameters are enabled in the current build +// environment. +const Enabled = false diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/enabled_go118.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/enabled_go118.go new file mode 100644 index 0000000000..d67148823c --- /dev/null +++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/enabled_go118.go @@ -0,0 +1,15 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.18 +// +build go1.18 + +package typeparams + +// Note: this constant is in a separate file as this is the only acceptable +// diff between the <1.18 API of this package and the 1.18 API. + +// Enabled reports whether type parameters are enabled in the current build +// environment. +const Enabled = true diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/notypeparams.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/notypeparams.go deleted file mode 100644 index e975e476f6..0000000000 --- a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/notypeparams.go +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !typeparams || !go1.18 -// +build !typeparams !go1.18 - -package typeparams - -import ( - "go/ast" - "go/types" -) - -// NOTE: doc comments must be kept in sync with typeparams.go. - -// Enabled reports whether type parameters are enabled in the current build -// environment. -const Enabled = false - -// GetIndexExprData extracts data from AST nodes that represent index -// expressions. -// -// For an ast.IndexExpr, the resulting IndexExprData will have exactly one -// index expression. For an ast.MultiIndexExpr (go1.18+), it may have a -// variable number of index expressions. -// -// For nodes that don't represent index expressions, GetIndexExprData returns -// nil. -func GetIndexExprData(n ast.Node) *IndexExprData { - if e, _ := n.(*ast.IndexExpr); e != nil { - return &IndexExprData{ - X: e.X, - Lbrack: e.Lbrack, - Indices: []ast.Expr{e.Index}, - Rbrack: e.Rbrack, - } - } - return nil -} - -// ForTypeDecl extracts the (possibly nil) type parameter node list from n. -func ForTypeDecl(*ast.TypeSpec) *ast.FieldList { - return nil -} - -// ForFuncDecl extracts the (possibly nil) type parameter node list from n. -func ForFuncDecl(*ast.FuncDecl) *ast.FieldList { - return nil -} - -// ForSignature extracts the (possibly empty) type parameter object list from -// sig. -func ForSignature(*types.Signature) []*types.TypeName { - return nil -} - -// IsComparable reports if iface is the comparable interface. -func IsComparable(*types.Interface) bool { - return false -} - -// IsConstraint reports whether iface may only be used as a type parameter -// constraint (i.e. has a type set or is the comparable interface). -func IsConstraint(*types.Interface) bool { - return false -} - -// ForNamed extracts the (possibly empty) type parameter object list from -// named. -func ForNamed(*types.Named) []*types.TypeName { - return nil -} - -// NamedTArgs extracts the (possibly empty) type argument list from named. -func NamedTArgs(*types.Named) []types.Type { - return nil -} - -// InitInferred initializes info to record inferred type information. -func InitInferred(*types.Info) { -} - -// GetInferred extracts inferred type information from info for e. -// -// The expression e may have an inferred type if it is an *ast.IndexExpr -// representing partial instantiation of a generic function type for which type -// arguments have been inferred using constraint type inference, or if it is an -// *ast.CallExpr for which type type arguments have be inferred using both -// constraint type inference and function argument inference. -func GetInferred(*types.Info, ast.Expr) ([]types.Type, *types.Signature) { - return nil, nil -} diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams.go deleted file mode 100644 index d459b32cb3..0000000000 --- a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams.go +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build typeparams && go1.18 -// +build typeparams,go1.18 - -package typeparams - -import ( - "go/ast" - "go/types" -) - -// NOTE: doc comments must be kept in sync with notypeparams.go. - -// Enabled reports whether type parameters are enabled in the current build -// environment. -const Enabled = true - -// GetIndexExprData extracts data from AST nodes that represent index -// expressions. -// -// For an ast.IndexExpr, the resulting IndexExprData will have exactly one -// index expression. For an ast.MultiIndexExpr (go1.18+), it may have a -// variable number of index expressions. -// -// For nodes that don't represent index expressions, GetIndexExprData returns -// nil. -func GetIndexExprData(n ast.Node) *IndexExprData { - switch e := n.(type) { - case *ast.IndexExpr: - return &IndexExprData{ - X: e.X, - Lbrack: e.Lbrack, - Indices: []ast.Expr{e.Index}, - Rbrack: e.Rbrack, - } - case *ast.MultiIndexExpr: - return (*IndexExprData)(e) - } - return nil -} - -// ForTypeDecl extracts the (possibly nil) type parameter node list from n. -func ForTypeDecl(n *ast.TypeSpec) *ast.FieldList { - return n.TParams -} - -// ForFuncDecl extracts the (possibly nil) type parameter node list from n. -func ForFuncDecl(n *ast.FuncDecl) *ast.FieldList { - if n.Type != nil { - return n.Type.TParams - } - return nil -} - -// ForSignature extracts the (possibly empty) type parameter object list from -// sig. -func ForSignature(sig *types.Signature) []*types.TypeName { - return tparamsSlice(sig.TParams()) -} - -// IsComparable reports if iface is the comparable interface. -func IsComparable(iface *types.Interface) bool { - return iface.IsComparable() -} - -// IsConstraint reports whether iface may only be used as a type parameter -// constraint (i.e. has a type set or is the comparable interface). -func IsConstraint(iface *types.Interface) bool { - return iface.IsConstraint() -} - -// ForNamed extracts the (possibly empty) type parameter object list from -// named. -func ForNamed(named *types.Named) []*types.TypeName { - return tparamsSlice(named.TParams()) -} - -func tparamsSlice(tparams *types.TParamList) []*types.TypeName { - length := tparams.Len() - if length == 0 { - return nil - } - - result := make([]*types.TypeName, length) - for i := 0; i < length; i++ { - result[i] = tparams.At(i).Obj() - } - - return result -} - -// NamedTArgs extracts the (possibly empty) type argument list from named. -func NamedTArgs(named *types.Named) []types.Type { - targs := named.TArgs() - numArgs := targs.Len() - - typs := make([]types.Type, numArgs) - for i := 0; i < numArgs; i++ { - typs[i] = targs.At(i) - } - - return typs -} - -// InitInferred initializes info to record inferred type information. -func InitInferred(info *types.Info) { - info.Inferred = make(map[ast.Expr]types.Inferred) -} - -// GetInferred extracts inferred type information from info for e. -// -// The expression e may have an inferred type if it is an *ast.IndexExpr -// representing partial instantiation of a generic function type for which type -// arguments have been inferred using constraint type inference, or if it is an -// *ast.CallExpr for which type type arguments have be inferred using both -// constraint type inference and function argument inference. -func GetInferred(info *types.Info, e ast.Expr) ([]types.Type, *types.Signature) { - if info.Inferred == nil { - return nil, nil - } - inf := info.Inferred[e] - - length := inf.TArgs.Len() - - typs := make([]types.Type, length) - for i := 0; i < length; i++ { - typs[i] = inf.TArgs.At(i) - } - - return typs, inf.Sig -} diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go new file mode 100644 index 0000000000..d22899d29e --- /dev/null +++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go @@ -0,0 +1,201 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !go1.18 +// +build !go1.18 + +package typeparams + +import ( + "go/ast" + "go/token" + "go/types" +) + +func unsupported() { + panic("type parameters are unsupported at this go version") +} + +// GetIndexExprData extracts data from *ast.IndexExpr nodes. +// For other nodes, GetIndexExprData returns nil. +func GetIndexExprData(n ast.Node) *IndexExprData { + if e, _ := n.(*ast.IndexExpr); e != nil { + return &IndexExprData{ + X: e.X, + Lbrack: e.Lbrack, + Indices: []ast.Expr{e.Index}, + Rbrack: e.Rbrack, + } + } + return nil +} + +// PackIndexExpr returns an *ast.IndexExpr with the given index. +// Calling PackIndexExpr with len(indices) != 1 will panic. +func PackIndexExpr(x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack token.Pos) ast.Expr { + switch len(indices) { + case 0: + panic("empty indices") + case 1: + return &ast.IndexExpr{ + X: x, + Lbrack: lbrack, + Index: indices[0], + Rbrack: rbrack, + } + default: + panic("cannot pack multiple indices at this go version") + } +} + +// IndexListExpr is a placeholder type, as type parameters are not supported at +// this Go version. Its methods panic on use. +type IndexListExpr struct { + ast.Expr + X ast.Expr // expression + Lbrack token.Pos // position of "[" + Indices []ast.Expr // index expressions + Rbrack token.Pos // position of "]" +} + +// ForTypeSpec returns an empty field list, as type parameters on not supported +// at this Go version. +func ForTypeSpec(*ast.TypeSpec) *ast.FieldList { + return nil +} + +// ForFuncType returns an empty field list, as type parameters are not +// supported at this Go version. +func ForFuncType(*ast.FuncType) *ast.FieldList { + return nil +} + +// TypeParam is a placeholder type, as type parameters are not supported at +// this Go version. Its methods panic on use. +type TypeParam struct{ types.Type } + +func (*TypeParam) Constraint() types.Type { unsupported(); return nil } +func (*TypeParam) Obj() *types.TypeName { unsupported(); return nil } + +// TypeParamList is a placeholder for an empty type parameter list. +type TypeParamList struct{} + +func (*TypeParamList) Len() int { return 0 } +func (*TypeParamList) At(int) *TypeParam { unsupported(); return nil } + +// TypeList is a placeholder for an empty type list. +type TypeList struct{} + +func (*TypeList) Len() int { return 0 } +func (*TypeList) At(int) types.Type { unsupported(); return nil } + +// NewTypeParam is unsupported at this Go version, and panics. +func NewTypeParam(name *types.TypeName, constraint types.Type) *TypeParam { + unsupported() + return nil +} + +// SetTypeParamConstraint is unsupported at this Go version, and panics. +func SetTypeParamConstraint(tparam *TypeParam, constraint types.Type) { + unsupported() +} + +// NewSignatureType calls types.NewSignature, panicking if recvTypeParams or +// typeParams is non-empty. +func NewSignatureType(recv *types.Var, recvTypeParams, typeParams []*TypeParam, params, results *types.Tuple, variadic bool) *types.Signature { + if len(recvTypeParams) != 0 || len(typeParams) != 0 { + panic("signatures cannot have type parameters at this Go version") + } + return types.NewSignature(recv, params, results, variadic) +} + +// ForSignature returns an empty slice. +func ForSignature(*types.Signature) *TypeParamList { + return nil +} + +// RecvTypeParams returns a nil slice. +func RecvTypeParams(sig *types.Signature) *TypeParamList { + return nil +} + +// IsComparable returns false, as no interfaces are type-restricted at this Go +// version. +func IsComparable(*types.Interface) bool { + return false +} + +// IsMethodSet returns true, as no interfaces are type-restricted at this Go +// version. +func IsMethodSet(*types.Interface) bool { + return true +} + +// ForNamed returns an empty type parameter list, as type parameters are not +// supported at this Go version. +func ForNamed(*types.Named) *TypeParamList { + return nil +} + +// SetForNamed panics if tparams is non-empty. +func SetForNamed(_ *types.Named, tparams []*TypeParam) { + if len(tparams) > 0 { + unsupported() + } +} + +// NamedTypeArgs returns nil. +func NamedTypeArgs(*types.Named) *TypeList { + return nil +} + +// NamedTypeOrigin is the identity method at this Go version. +func NamedTypeOrigin(named *types.Named) types.Type { + return named +} + +// Term is a placeholder type, as type parameters are not supported at this Go +// version. Its methods panic on use. +type Term struct{} + +func (*Term) Tilde() bool { unsupported(); return false } +func (*Term) Type() types.Type { unsupported(); return nil } +func (*Term) String() string { unsupported(); return "" } +func (*Term) Underlying() types.Type { unsupported(); return nil } + +// NewTerm is unsupported at this Go version, and panics. +func NewTerm(tilde bool, typ types.Type) *Term { + unsupported() + return nil +} + +// Union is a placeholder type, as type parameters are not supported at this Go +// version. Its methods panic on use. +type Union struct{ types.Type } + +func (*Union) Len() int { return 0 } +func (*Union) Term(i int) *Term { unsupported(); return nil } + +// NewUnion is unsupported at this Go version, and panics. +func NewUnion(terms []*Term) *Union { + unsupported() + return nil +} + +// InitInstanceInfo is a noop at this Go version. +func InitInstanceInfo(*types.Info) {} + +// GetInstance returns nothing, as type parameters are not supported at this Go +// version. +func GetInstance(*types.Info, *ast.Ident) (*TypeList, types.Type) { return nil, nil } + +// Context is a placeholder type, as type parameters are not supported at +// this Go version. +type Context struct{} + +// Instantiate is unsupported on this Go version, and panics. +func Instantiate(ctxt *Context, typ types.Type, targs []types.Type, validate bool) (types.Type, error) { + unsupported() + return nil, nil +} diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go new file mode 100644 index 0000000000..a252183411 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go @@ -0,0 +1,189 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.18 +// +build go1.18 + +package typeparams + +import ( + "go/ast" + "go/token" + "go/types" +) + +// GetIndexExprData extracts data from AST nodes that represent index +// expressions. +// +// For an ast.IndexExpr, the resulting IndexExprData will have exactly one +// index expression. For an ast.IndexListExpr (go1.18+), it may have a +// variable number of index expressions. +// +// For nodes that don't represent index expressions, GetIndexExprData returns +// nil. +// TODO(rfindley): remove this function in favor of using the alias below. +func GetIndexExprData(n ast.Node) *IndexExprData { + switch e := n.(type) { + case *ast.IndexExpr: + return &IndexExprData{ + X: e.X, + Lbrack: e.Lbrack, + Indices: []ast.Expr{e.Index}, + Rbrack: e.Rbrack, + } + case *ast.IndexListExpr: + return (*IndexExprData)(e) + } + return nil +} + +// PackIndexExpr returns an *ast.IndexExpr or *ast.IndexListExpr, depending on +// the cardinality of indices. Calling PackIndexExpr with len(indices) == 0 +// will panic. +func PackIndexExpr(x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack token.Pos) ast.Expr { + switch len(indices) { + case 0: + panic("empty indices") + case 1: + return &ast.IndexExpr{ + X: x, + Lbrack: lbrack, + Index: indices[0], + Rbrack: rbrack, + } + default: + return &ast.IndexListExpr{ + X: x, + Lbrack: lbrack, + Indices: indices, + Rbrack: rbrack, + } + } +} + +// IndexListExpr is an alias for ast.IndexListExpr. +type IndexListExpr = ast.IndexListExpr + +// ForTypeSpec returns n.TypeParams. +func ForTypeSpec(n *ast.TypeSpec) *ast.FieldList { + if n == nil { + return nil + } + return n.TypeParams +} + +// ForFuncType returns n.TypeParams. +func ForFuncType(n *ast.FuncType) *ast.FieldList { + if n == nil { + return nil + } + return n.TypeParams +} + +// TypeParam is an alias for types.TypeParam +type TypeParam = types.TypeParam + +// TypeParamList is an alias for types.TypeParamList +type TypeParamList = types.TypeParamList + +// TypeList is an alias for types.TypeList +type TypeList = types.TypeList + +// NewTypeParam calls types.NewTypeParam. +func NewTypeParam(name *types.TypeName, constraint types.Type) *TypeParam { + return types.NewTypeParam(name, constraint) +} + +// SetTypeParamConstraint calls tparam.SetConstraint(constraint). +func SetTypeParamConstraint(tparam *TypeParam, constraint types.Type) { + tparam.SetConstraint(constraint) +} + +// NewSignatureType calls types.NewSignatureType. +func NewSignatureType(recv *types.Var, recvTypeParams, typeParams []*TypeParam, params, results *types.Tuple, variadic bool) *types.Signature { + return types.NewSignatureType(recv, recvTypeParams, typeParams, params, results, variadic) +} + +// ForSignature returns sig.TypeParams() +func ForSignature(sig *types.Signature) *TypeParamList { + return sig.TypeParams() +} + +// RecvTypeParams returns sig.RecvTypeParams(). +func RecvTypeParams(sig *types.Signature) *TypeParamList { + return sig.RecvTypeParams() +} + +// IsComparable calls iface.IsComparable(). +func IsComparable(iface *types.Interface) bool { + return iface.IsComparable() +} + +// IsMethodSet calls iface.IsMethodSet(). +func IsMethodSet(iface *types.Interface) bool { + return iface.IsMethodSet() +} + +// ForNamed extracts the (possibly empty) type parameter object list from +// named. +func ForNamed(named *types.Named) *TypeParamList { + return named.TypeParams() +} + +// SetForNamed sets the type params tparams on n. Each tparam must be of +// dynamic type *types.TypeParam. +func SetForNamed(n *types.Named, tparams []*TypeParam) { + n.SetTypeParams(tparams) +} + +// NamedTypeArgs returns named.TypeArgs(). +func NamedTypeArgs(named *types.Named) *TypeList { + return named.TypeArgs() +} + +// NamedTypeOrigin returns named.Orig(). +func NamedTypeOrigin(named *types.Named) types.Type { + return named.Origin() +} + +// Term is an alias for types.Term. +type Term = types.Term + +// NewTerm calls types.NewTerm. +func NewTerm(tilde bool, typ types.Type) *Term { + return types.NewTerm(tilde, typ) +} + +// Union is an alias for types.Union +type Union = types.Union + +// NewUnion calls types.NewUnion. +func NewUnion(terms []*Term) *Union { + return types.NewUnion(terms) +} + +// InitInstanceInfo initializes info to record information about type and +// function instances. +func InitInstanceInfo(info *types.Info) { + info.Instances = make(map[*ast.Ident]types.Instance) +} + +// GetInstance extracts information about the instantiation occurring at the +// identifier id. id should be the identifier denoting a parameterized type or +// function in an instantiation expression or function call. +func GetInstance(info *types.Info, id *ast.Ident) (*TypeList, types.Type) { + if info.Instances != nil { + inf := info.Instances[id] + return inf.TypeArgs, inf.Type + } + return nil, nil +} + +// Context is an alias for types.Context. +type Context = types.Context + +// Instantiate calls types.Instantiate. +func Instantiate(ctxt *Context, typ types.Type, targs []types.Type, validate bool) (types.Type, error) { + return types.Instantiate(ctxt, typ, targs, validate) +} diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 49a79890bc..1e64528968 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -51,7 +51,7 @@ golang.org/x/sys/windows # golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b ## explicit; go 1.17 golang.org/x/term -# golang.org/x/tools v0.1.6-0.20210904010709-360456621443 +# golang.org/x/tools v0.1.8-0.20211011152358-18fa84021695 ## explicit; go 1.17 golang.org/x/tools/cover golang.org/x/tools/go/analysis -- GitLab From 52078fa477a0a8a8440ca40d64850730e2cf27f8 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 11 Oct 2021 09:15:02 -0700 Subject: [PATCH 1550/2500] cmd/compile: deal with TODO related to generic wrappers with embedded fields It turns out there is no real TODO here - things are working fine. If we are generating a wrapper for a method on a generic type that is actually the method on embedded type, then we should just just generate the normal embedded wrapper, which calls the wrapper for the real receiver type on that method. There is no need to do the generic path where we add in the dictionary argument. So, just updated that TODO comment with this explanation. Added a new test case embedded.go, which specifically tests various situations involving converting to empty and non-empty interfaces. issue44688.go already tests a bunch of these situations as well. Also made some other cleanups in reflect.go: - The shape test (that I had added) at the top of imethods is useless (never true), since it is always an interface type, so removed it. - Added usual helper function deref() to make code clearer in several places. - The shape test in methodWrapper() doesn't have to check HasShape() on each targ - it can just check HasShape() on the whole receiver. - The comment about disabling the tail call optimization for RegABI is no longer true. - Simplified code in several places by using the value of existing variable 'methodrcvr'. Change-Id: I8b1a5dc518dad37585824a1f73ceebb7627a9f82 Reviewed-on: https://go-review.googlesource.com/c/go/+/355129 Trust: Dan Scales Reviewed-by: Keith Randall --- .../compile/internal/reflectdata/reflect.go | 58 +++++++------------ 1 file changed, 22 insertions(+), 36 deletions(-) diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index a8d911f003..27e6188ab7 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -365,13 +365,6 @@ func methods(t *types.Type) []*typeSig { // imethods returns the methods of the interface type t, sorted by name. func imethods(t *types.Type) []*typeSig { - if t.HasShape() && !t.IsInterface() { - // Non-interface shape types have no methods. (There are - // corresponding functions (created by getInstantiation) that take - // the dictionary and the receiver of shape type as the first two - // arguments.) - return nil - } var methods []*typeSig for _, f := range t.AllMethods().Slice() { if f.Type.Kind() != types.TFUNC || f.Sym == nil { @@ -1804,19 +1797,13 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy // We don't need a dictionary if we are reaching a method (possibly via an // embedded field) which is an interface method. if !types.IsInterfaceMethod(method.Type) { - rcvr1 := rcvr - if rcvr1.IsPtr() { - rcvr1 = rcvr.Elem() - } + rcvr1 := deref(rcvr) if len(rcvr1.RParams()) > 0 { // If rcvr has rparams, remember method as generic, which // means we need to add a dictionary to the wrapper. generic = true - targs := rcvr1.RParams() - for _, t := range targs { - if t.HasShape() { - base.Fatalf("method on type instantiated with shapes targ:%+v rcvr:%+v", t, rcvr) - } + if rcvr.HasShape() { + base.Fatalf("method on type instantiated with shapes, rcvr:%+v", rcvr) } } } @@ -1833,9 +1820,10 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy return lsym } + methodrcvr := method.Type.Recv().Type // For generic methods, we need to generate the wrapper even if the receiver // types are identical, because we want to add the dictionary. - if !generic && types.Identical(rcvr, method.Type.Recv().Type) { + if !generic && types.Identical(rcvr, methodrcvr) { return lsym } @@ -1859,7 +1847,6 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy nthis := ir.AsNode(tfn.Type().Recv().Nname) - methodrcvr := method.Type.Recv().Type indirect := rcvr.IsPtr() && rcvr.Elem() == methodrcvr // generate nil pointer check for better error @@ -1880,10 +1867,6 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy // the TOC to the appropriate value for that module. But if it returns // directly to the wrapper's caller, nothing will reset it to the correct // value for that function. - // - // Disable tailcall for RegabiArgs for now. The IR does not connect the - // arguments with the OTAILCALL node, and the arguments are not marshaled - // correctly. if !base.Flag.Cfg.Instrumenting && rcvr.IsPtr() && methodrcvr.IsPtr() && method.Embedded != 0 && !types.IsInterfaceMethod(method.Type) && !(base.Ctxt.Arch.Name == "ppc64le" && base.Ctxt.Flag_dynlink) && !generic { call := ir.NewCallExpr(base.Pos, ir.OCALL, dot, nil) call.Args = ir.ParamNames(tfn.Type()) @@ -1894,30 +1877,26 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy var call *ir.CallExpr if generic && dot.X != nthis { - // TODO: for now, we don't try to generate dictionary wrappers for - // any methods involving embedded fields, because we're not - // generating the needed dictionaries in instantiateMethods. + // If there is embedding involved, then we should do the + // normal non-generic embedding wrapper below, which calls + // the wrapper for the real receiver type using dot as an + // argument. There is no need for generic processing (adding + // a dictionary) for this wrapper. generic = false } if generic { - var args []ir.Node - var targs []*types.Type - if rcvr.IsPtr() { - targs = rcvr.Elem().RParams() - } else { - targs = rcvr.RParams() - } + targs := deref(rcvr).RParams() // The wrapper for an auto-generated pointer/non-pointer // receiver method should share the same dictionary as the // corresponding original (user-written) method. baseOrig := orig - if baseOrig.IsPtr() && !method.Type.Recv().Type.IsPtr() { + if baseOrig.IsPtr() && !methodrcvr.IsPtr() { baseOrig = baseOrig.Elem() - } else if !baseOrig.IsPtr() && method.Type.Recv().Type.IsPtr() { + } else if !baseOrig.IsPtr() && methodrcvr.IsPtr() { baseOrig = types.NewPtr(baseOrig) } - args = append(args, getDictionary(ir.MethodSym(baseOrig, method.Sym), targs)) + args := []ir.Node{getDictionary(ir.MethodSym(baseOrig, method.Sym), targs)} if indirect { args = append(args, ir.NewStarExpr(base.Pos, dot.X)) } else if methodrcvr.IsPtr() && methodrcvr.Elem() == dot.X.Type() { @@ -2052,7 +2031,7 @@ func getDictionary(gf *types.Sym, targs []*types.Type) ir.Node { sym := typecheck.MakeDictSym(gf, targs, true) - // Initialize the dictionary, if we haven't yet already. + // Dictionary should already have been generated by instantiateMethods(). if lsym := sym.Linksym(); len(lsym.P) == 0 { base.Fatalf("Dictionary should have already been generated: %s.%s", sym.Pkg.Path, sym.Name) } @@ -2078,3 +2057,10 @@ func getDictionary(gf *types.Sym, targs []*types.Type) ir.Node { np.SetTypecheck(1) return np } + +func deref(t *types.Type) *types.Type { + if t.IsPtr() { + return t.Elem() + } + return t +} -- GitLab From 65ffee6f9a949023f10e5b6b918a7a218d9836a1 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 1 Oct 2021 11:52:56 -0400 Subject: [PATCH 1551/2500] cmd/go: insert goroot to the hash of build cache when the packages include C files This reverts CL 351851, which itself reverted CL 348991. The problem with the original CL, as far as I can tell, was due to a bug in the Go project's builder infrastructure (#33598) and not the change itself. Once the build infrastructure is fixed, this change can be resubmitted. Fixes #48319 Updates #33598 Change-Id: I0fdbcc241eb2bdeb350944aad58bf58774fb591e Reviewed-on: https://go-review.googlesource.com/c/go/+/353352 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/work/exec.go | 34 ++-- .../go/testdata/script/build_issue48319.txt | 153 ++++++++++++++++++ 2 files changed, 177 insertions(+), 10 deletions(-) create mode 100644 src/cmd/go/testdata/script/build_issue48319.txt diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index 99e92947ee..d4e24d4cd1 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -223,18 +223,32 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID { // same compiler settings and can reuse each other's results. // If not, the reason is already recorded in buildGcflags. fmt.Fprintf(h, "compile\n") - // Only include the package directory if it may affect the output. - // We trim workspace paths for all packages when -trimpath is set. - // The compiler hides the exact value of $GOROOT - // when building things in GOROOT. - // Assume b.WorkDir is being trimmed properly. - // When -trimpath is used with a package built from the module cache, - // use the module path and version instead of the directory. - if !p.Goroot && !cfg.BuildTrimpath && !strings.HasPrefix(p.Dir, b.WorkDir) { + + // Include information about the origin of the package that + // may be embedded in the debug info for the object file. + if cfg.BuildTrimpath { + // When -trimpath is used with a package built from the module cache, + // its debug information refers to the module path and version + // instead of the directory. + if p.Module != nil { + fmt.Fprintf(h, "module %s@%s\n", p.Module.Path, p.Module.Version) + } + } else if p.Goroot { + // The Go compiler always hides the exact value of $GOROOT + // when building things in GOROOT, but the C compiler + // merely rewrites GOROOT to GOROOT_FINAL. + if len(p.CFiles) > 0 { + fmt.Fprintf(h, "goroot %s\n", cfg.GOROOT_FINAL) + } + // b.WorkDir is always either trimmed or rewritten to + // the literal string "/tmp/go-build". + } else if !strings.HasPrefix(p.Dir, b.WorkDir) { + // -trimpath is not set and no other rewrite rules apply, + // so the object file may refer to the absolute directory + // containing the package. fmt.Fprintf(h, "dir %s\n", p.Dir) - } else if cfg.BuildTrimpath && p.Module != nil { - fmt.Fprintf(h, "module %s@%s\n", p.Module.Path, p.Module.Version) } + if p.Module != nil { fmt.Fprintf(h, "go %s\n", p.Module.GoVersion) } diff --git a/src/cmd/go/testdata/script/build_issue48319.txt b/src/cmd/go/testdata/script/build_issue48319.txt new file mode 100644 index 0000000000..f58a5faa3f --- /dev/null +++ b/src/cmd/go/testdata/script/build_issue48319.txt @@ -0,0 +1,153 @@ +[short] skip +[!cgo] skip + +# Set up fresh GOCACHE +env GOCACHE=$WORK/gocache +mkdir $GOCACHE + +# 1. unset GOROOT_FINAL, Build a simple binary with cgo by origin go. +# The DW_AT_comp_dir of runtime/cgo should have a prefix with origin goroot. +env GOROOT_FINAL= +# If using "go run", it is no debuginfo in binary. So use "go build". +# And we can check the stderr to judge if the cache of "runtime/cgo" +# was used or not. +go build -o binary.exe +exec ./binary.exe $TESTGO_GOROOT +stdout 'cgo DW_AT_comp_dir is right in binary' + + +# 2. GOROOT_FINAL will be changed, the runtime/cgo will be rebuild. +env GOROOT_FINAL=$WORK/gorootfinal +go build -x -o binary.exe +stderr '(clang|gcc)( |\.exe).*gcc_.*\.c' +exec ./binary.exe $GOROOT_FINAL +stdout 'cgo DW_AT_comp_dir is right in binary' + + +[!symlink] skip + +# Symlink the compiler to another path +env GOROOT=$WORK/goroot +symlink $GOROOT -> $TESTGO_GOROOT + +# 3. GOROOT_FINAL is same with 2, build with the other go +# the runtime/cgo will not be rebuild. +go build -x -o binary.exe +! stderr '(clang|gcc)( |\.exe).*gcc_.*\.c' +exec ./binary.exe $GOROOT_FINAL +stdout 'cgo DW_AT_comp_dir is right in binary' + + +# 4. unset GOROOT_FINAL, build with the other go +# the runtime/cgo will be rebuild. +env GOROOT_FINAL= +go build -x -o binary.exe +stderr '(clang|gcc)( |\.exe).*gcc_.*\.c' +exec ./binary.exe $GOROOT +stdout 'cgo DW_AT_comp_dir is right in binary' + +-- go.mod -- +module main + +go 1.18 +-- main.go -- +package main + +import "C" +import ( + "debug/dwarf" + "fmt" + "log" + "os" + "path/filepath" + "strings" +) + +var _ C.int + +func main() { + dwarfData, err := readDWARF(os.Args[0]) + if err != nil { + log.Fatal(err) + } + goroot := filepath.Join(os.Args[1], "src") + dwarfReader := dwarfData.Reader() + cgopackage := filepath.Join("runtime", "cgo") + var hascgo bool + for { + e, err := dwarfReader.Next() + if err != nil { + log.Fatal(err) + } + if e == nil { + break + } + field := e.AttrField(dwarf.AttrCompDir) + if field == nil { + continue + } + compdir := field.Val.(string) + if strings.HasSuffix(compdir, cgopackage) { + hascgo = true + if !strings.HasPrefix(compdir, goroot) { + fmt.Printf("cgo DW_AT_comp_dir %s contains incorrect path in binary.\n", compdir) + return + } + } + } + if hascgo { + fmt.Println("cgo DW_AT_comp_dir is right in binary") + } else { + fmt.Println("binary does not contain cgo") + } +} +-- read_darwin.go -- +package main + +import ( + "debug/dwarf" + "debug/macho" +) + +func readDWARF(exePath string) (*dwarf.Data, error) { + machoFile, err := macho.Open(exePath) + if err != nil { + return nil, err + } + defer machoFile.Close() + return machoFile.DWARF() +} +-- read_elf.go -- +// +build android dragonfly freebsd illumos linux netbsd openbsd solaris + +package main + +import ( + "debug/dwarf" + "debug/elf" +) + +func readDWARF(exePath string) (*dwarf.Data, error) { + elfFile, err := elf.Open(exePath) + if err != nil { + return nil, err + } + defer elfFile.Close() + return elfFile.DWARF() +} +-- read_windows.go -- +package main + +import ( + "debug/dwarf" + "debug/pe" +) + +func readDWARF(exePath string) (*dwarf.Data, error) { + peFile, err := pe.Open(exePath) + if err != nil { + return nil, err + } + defer peFile.Close() + return peFile.DWARF() +} -- GitLab From 70235351263caee1fd9840d1d652bf28778cd51d Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Thu, 7 Oct 2021 12:21:01 -0700 Subject: [PATCH 1552/2500] cmd/compile: adjust debug/gosym to deal with instantiated types/funcs/methods This changes debug/gosym so it can deal with instantiated types/funcs/methods. I also added tests for instantiated names. My assumption is that the concatenation of PackageName, ReceiverName, and BaseName in order should cover the entire symbol name, so either the ReceiverName or the BaseName should include any bracketed information (either the instantiation of the receiver of a method or the instantiation of function). This can provide a model for how to parse instantiated functions and method names. Fixes #48032 Change-Id: I476781de2d6fc096efbb4be85c197d6f1cafac21 Reviewed-on: https://go-review.googlesource.com/c/go/+/354689 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/debug/gosym/symtab.go | 53 ++++++++++++++++++++++++++++++---- src/debug/gosym/symtab_test.go | 19 ++++++++++++ 2 files changed, 66 insertions(+), 6 deletions(-) diff --git a/src/debug/gosym/symtab.go b/src/debug/gosym/symtab.go index 00701c2875..72490dca8a 100644 --- a/src/debug/gosym/symtab.go +++ b/src/debug/gosym/symtab.go @@ -32,10 +32,28 @@ type Sym struct { // Static reports whether this symbol is static (not visible outside its file). func (s *Sym) Static() bool { return s.Type >= 'a' } +// nameWithoutInst returns s.Name if s.Name has no brackets (does not reference an +// instantiated type, function, or method). If s.Name contains brackets, then it +// returns s.Name with all the contents between (and including) the outermost left +// and right bracket removed. This is useful to ignore any extra slashes or dots +// inside the brackets from the string searches below, where needed. +func (s *Sym) nameWithoutInst() string { + start := strings.Index(s.Name, "[") + if start < 0 { + return s.Name + } + end := strings.LastIndex(s.Name, "]") + if end < 0 { + // Malformed name, should contain closing bracket too. + return s.Name + } + return s.Name[0:start] + s.Name[end+1:] +} + // PackageName returns the package part of the symbol name, // or the empty string if there is none. func (s *Sym) PackageName() string { - name := s.Name + name := s.nameWithoutInst() // A prefix of "type." and "go." is a compiler-generated symbol that doesn't belong to any package. // See variable reservedimports in cmd/compile/internal/gc/subr.go @@ -55,23 +73,46 @@ func (s *Sym) PackageName() string { } // ReceiverName returns the receiver type name of this symbol, -// or the empty string if there is none. +// or the empty string if there is none. A receiver name is only detected in +// the case that s.Name is fully-specified with a package name. func (s *Sym) ReceiverName() string { - pathend := strings.LastIndex(s.Name, "/") + name := s.nameWithoutInst() + // If we find a slash in name, it should precede any bracketed expression + // that was removed, so pathend will apply correctly to name and s.Name. + pathend := strings.LastIndex(name, "/") if pathend < 0 { pathend = 0 } - l := strings.Index(s.Name[pathend:], ".") - r := strings.LastIndex(s.Name[pathend:], ".") + // Find the first dot after pathend (or from the beginning, if there was + // no slash in name). + l := strings.Index(name[pathend:], ".") + // Find the last dot after pathend (or the beginnng). + r := strings.LastIndex(name[pathend:], ".") if l == -1 || r == -1 || l == r { + // There is no receiver if we didn't find two distinct dots after pathend. return "" } + // Given there is a trailing '.' that is in name, find it now in s.Name. + // pathend+l should apply to s.Name, because it should be the dot in the + // package name. + r = strings.LastIndex(s.Name[pathend:], ".") return s.Name[pathend+l+1 : pathend+r] } // BaseName returns the symbol name without the package or receiver name. func (s *Sym) BaseName() string { - if i := strings.LastIndex(s.Name, "."); i != -1 { + name := s.nameWithoutInst() + if i := strings.LastIndex(name, "."); i != -1 { + if s.Name != name { + brack := strings.Index(s.Name, "[") + if i > brack { + // BaseName is a method name after the brackets, so + // recalculate for s.Name. Otherwise, i applies + // correctly to s.Name, since it is before the + // brackets. + i = strings.LastIndex(s.Name, ".") + } + } return s.Name[i+1:] } return s.Name diff --git a/src/debug/gosym/symtab_test.go b/src/debug/gosym/symtab_test.go index b6ed8f554c..da3c21209d 100644 --- a/src/debug/gosym/symtab_test.go +++ b/src/debug/gosym/symtab_test.go @@ -33,6 +33,25 @@ func TestStandardLibPathPackage(t *testing.T) { assertString(t, fmt.Sprintf("receiver of %q", s2.Name), s2.ReceiverName(), "") } +func TestGenericNames(t *testing.T) { + s1 := Sym{Name: "main.set[int]"} + s2 := Sym{Name: "main.(*value[int]).get"} + s3 := Sym{Name: "a/b.absDifference[c/d.orderedAbs[float64]]"} + s4 := Sym{Name: "main.testfunction[.shape.int]"} + assertString(t, fmt.Sprintf("package of %q", s1.Name), s1.PackageName(), "main") + assertString(t, fmt.Sprintf("package of %q", s2.Name), s2.PackageName(), "main") + assertString(t, fmt.Sprintf("package of %q", s3.Name), s3.PackageName(), "a/b") + assertString(t, fmt.Sprintf("package of %q", s4.Name), s4.PackageName(), "main") + assertString(t, fmt.Sprintf("receiver of %q", s1.Name), s1.ReceiverName(), "") + assertString(t, fmt.Sprintf("receiver of %q", s2.Name), s2.ReceiverName(), "(*value[int])") + assertString(t, fmt.Sprintf("receiver of %q", s3.Name), s3.ReceiverName(), "") + assertString(t, fmt.Sprintf("receiver of %q", s4.Name), s4.ReceiverName(), "") + assertString(t, fmt.Sprintf("base of %q", s1.Name), s1.BaseName(), "set[int]") + assertString(t, fmt.Sprintf("base of %q", s2.Name), s2.BaseName(), "get") + assertString(t, fmt.Sprintf("base of %q", s3.Name), s3.BaseName(), "absDifference[c/d.orderedAbs[float64]]") + assertString(t, fmt.Sprintf("base of %q", s4.Name), s4.BaseName(), "testfunction[.shape.int]") +} + func TestRemotePackage(t *testing.T) { s1 := Sym{Name: "github.com/docker/doc.ker/pkg/mflag.(*FlagSet).PrintDefaults"} s2 := Sym{Name: "github.com/docker/doc.ker/pkg/mflag.PrintDefaults"} -- GitLab From d973bb107e9142cf17e4a7f2666a71ed2d457e91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Mon, 11 Oct 2021 11:12:38 +0100 Subject: [PATCH 1553/2500] encoding/gob: follow documented io.EOF semantics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The docs say: If the input is at EOF, Decode returns io.EOF and does not modify e. However, the added test fails: --- FAIL: TestDecodePartial (0.00s) encoder_test.go:1263: 31/81: expected io.ErrUnexpectedEOF: EOF encoder_test.go:1263: 51/81: expected io.ErrUnexpectedEOF: EOF In particular, the decoder would return io.EOF after reading a valid message for a type specification, and then hit EOF before reading a data item message. Fix that by only allowing a Decode call to return io.EOF if the reader hits EOF immediately, without successfully reading any message. Otherwise, hitting EOF is an ErrUnexpectedEOF, like in other cases. Also fix a net/rpc test that, coincidentally, expected an io.EOF as an error when feeding bad non-zero data to a gob decoder. An io.ErrUnexpectedEOF is clearly better in that scenario. Fixes #48905. Change-Id: Ied6a0d8ac8377f89646319a18c0380c4f2b09b85 Reviewed-on: https://go-review.googlesource.com/c/go/+/354972 Trust: Daniel Martí Run-TryBot: Daniel Martí TryBot-Result: Go Bot Reviewed-by: Rob Pike --- src/encoding/gob/decoder.go | 9 +++++ src/encoding/gob/encoder_test.go | 63 ++++++++++++++++++++++++++++++++ src/net/rpc/client_test.go | 4 +- 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/src/encoding/gob/decoder.go b/src/encoding/gob/decoder.go index b476aaac93..5e4ed5a7d7 100644 --- a/src/encoding/gob/decoder.go +++ b/src/encoding/gob/decoder.go @@ -138,9 +138,17 @@ func (dec *Decoder) nextUint() uint64 { // decoded. If this is an interface value, it can be ignored by // resetting that buffer. func (dec *Decoder) decodeTypeSequence(isInterface bool) typeId { + firstMessage := true for dec.err == nil { if dec.buf.Len() == 0 { if !dec.recvMessage() { + // We can only return io.EOF if the input was empty. + // If we read one or more type spec messages, + // require a data item message to follow. + // If we hit an EOF before that, then give ErrUnexpectedEOF. + if !firstMessage && dec.err == io.EOF { + dec.err = io.ErrUnexpectedEOF + } break } } @@ -166,6 +174,7 @@ func (dec *Decoder) decodeTypeSequence(isInterface bool) typeId { } dec.nextUint() } + firstMessage = false } return -1 } diff --git a/src/encoding/gob/encoder_test.go b/src/encoding/gob/encoder_test.go index 6d50b82573..a358d5bc30 100644 --- a/src/encoding/gob/encoder_test.go +++ b/src/encoding/gob/encoder_test.go @@ -1202,3 +1202,66 @@ func TestMarshalFloatMap(t *testing.T) { t.Fatalf("\nEncode: %v\nDecode: %v", want, got) } } + +func TestDecodePartial(t *testing.T) { + type T struct { + X []int + Y string + } + + var buf bytes.Buffer + t1 := T{X: []int{1, 2, 3}, Y: "foo"} + t2 := T{X: []int{4, 5, 6}, Y: "bar"} + enc := NewEncoder(&buf) + + t1start := 0 + if err := enc.Encode(&t1); err != nil { + t.Fatal(err) + } + + t2start := buf.Len() + if err := enc.Encode(&t2); err != nil { + t.Fatal(err) + } + + data := buf.Bytes() + for i := 0; i <= len(data); i++ { + bufr := bytes.NewReader(data[:i]) + + // Decode both values, stopping at the first error. + var t1b, t2b T + dec := NewDecoder(bufr) + var err error + err = dec.Decode(&t1b) + if err == nil { + err = dec.Decode(&t2b) + } + + switch i { + case t1start, t2start: + // Either the first or the second Decode calls had zero input. + if err != io.EOF { + t.Errorf("%d/%d: expected io.EOF: %v", i, len(data), err) + } + case len(data): + // We reached the end of the entire input. + if err != nil { + t.Errorf("%d/%d: unexpected error: %v", i, len(data), err) + } + if !reflect.DeepEqual(t1b, t1) { + t.Fatalf("t1 value mismatch: got %v, want %v", t1b, t1) + } + if !reflect.DeepEqual(t2b, t2) { + t.Fatalf("t2 value mismatch: got %v, want %v", t2b, t2) + } + default: + // In between, we must see io.ErrUnexpectedEOF. + // The decoder used to erroneously return io.EOF in some cases here, + // such as if the input was cut off right after some type specs, + // but before any value was actually transmitted. + if err != io.ErrUnexpectedEOF { + t.Errorf("%d/%d: expected io.ErrUnexpectedEOF: %v", i, len(data), err) + } + } + } +} diff --git a/src/net/rpc/client_test.go b/src/net/rpc/client_test.go index 03225e3d01..38a10ce0b3 100644 --- a/src/net/rpc/client_test.go +++ b/src/net/rpc/client_test.go @@ -57,8 +57,8 @@ func TestGobError(t *testing.T) { if err == nil { t.Fatal("no error") } - if !strings.Contains(err.(error).Error(), "reading body EOF") { - t.Fatal("expected `reading body EOF', got", err) + if !strings.Contains(err.(error).Error(), "reading body unexpected EOF") { + t.Fatal("expected `reading body unexpected EOF', got", err) } }() Register(new(S)) -- GitLab From 2ecdf9d800f631cfde30b7463a3ed2c0b60611d5 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Fri, 8 Oct 2021 16:28:35 -0400 Subject: [PATCH 1554/2500] go/parser: allow eliding interface in constraint literals This is a port of CL 353133 from cmd/compile/internal/syntax, with significant adjustments for the mechanics of go/parser. Some additional cleanup is made along the way: parseParameterList can call parseParamDecl without indirection, and the tparams argument is redundant with the closing token. Also, the error that "all type parameters must be named" is positioned on the first unnamed type parameter. Error recovery in go/parser is notably worse here than the compiler parser, so the test data had to be adjusted to synchronize positions. Fixing this error recovery will have to wait for a later CL. As with the compiler changes, these changes are guarded behind a flag so that they may be easily removed if #48424 is not accepted. For #48424 Change-Id: If87925d246f36aaab11a95442f75f659462d4286 Reviewed-on: https://go-review.googlesource.com/c/go/+/354870 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/internal/typeparams/common.go | 10 +- src/go/parser/parser.go | 126 +++++++++++++++--------- src/go/parser/testdata/typeset.go2 | 75 ++++++++++++++ src/go/printer/testdata/generics.golden | 5 + src/go/printer/testdata/generics.input | 5 + 5 files changed, 170 insertions(+), 51 deletions(-) create mode 100644 src/go/parser/testdata/typeset.go2 diff --git a/src/go/internal/typeparams/common.go b/src/go/internal/typeparams/common.go index 47b8f7cf02..9b82e6061a 100644 --- a/src/go/internal/typeparams/common.go +++ b/src/go/internal/typeparams/common.go @@ -7,7 +7,9 @@ // constraint. package typeparams -// DisallowParsing is the numeric value of a parsing mode that disallows type -// parameters. This only matters if the typeparams experiment is active, and -// may be used for running tests that disallow generics. -const DisallowParsing = 1 << 30 +// 'Hidden' parser modes to control the parsing of type-parameter related +// features. +const ( + DisallowTypeSets = 1 << 29 // Disallow eliding 'interface' in constraint type sets. + DisallowParsing = 1 << 30 // Disallow type parameters entirely. +) diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go index dd6b93d20f..4f7a498780 100644 --- a/src/go/parser/parser.go +++ b/src/go/parser/parser.go @@ -76,9 +76,8 @@ func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode Mod p.next() } -func (p *parser) parseTypeParams() bool { - return p.mode&typeparams.DisallowParsing == 0 -} +func (p *parser) allowGenerics() bool { return p.mode&typeparams.DisallowParsing == 0 } +func (p *parser) allowTypeSets() bool { return p.mode&typeparams.DisallowTypeSets == 0 } // ---------------------------------------------------------------------------- // Parsing support @@ -499,7 +498,7 @@ func (p *parser) parseQualifiedIdent(ident *ast.Ident) ast.Expr { } typ := p.parseTypeName(ident) - if p.tok == token.LBRACK && p.parseTypeParams() { + if p.tok == token.LBRACK && p.allowGenerics() { typ = p.parseTypeInstance(typ) } @@ -558,7 +557,7 @@ func (p *parser) parseArrayFieldOrTypeInstance(x *ast.Ident) (*ast.Ident, ast.Ex // TODO(rfindley): consider changing parseRhsOrType so that this function variable // is not needed. argparser := p.parseRhsOrType - if !p.parseTypeParams() { + if !p.allowGenerics() { argparser = p.parseRhs } if p.tok != token.RBRACK { @@ -588,13 +587,13 @@ func (p *parser) parseArrayFieldOrTypeInstance(x *ast.Ident) (*ast.Ident, ast.Ex // x [P]E return x, &ast.ArrayType{Lbrack: lbrack, Len: args[0], Elt: elt} } - if !p.parseTypeParams() { + if !p.allowGenerics() { p.error(rbrack, "missing element type in array type expression") return nil, &ast.BadExpr{From: args[0].Pos(), To: args[0].End()} } } - if !p.parseTypeParams() { + if !p.allowGenerics() { p.error(firstComma, "expected ']', found ','") return x, &ast.BadExpr{From: args[0].Pos(), To: args[len(args)-1].End()} } @@ -711,8 +710,9 @@ type field struct { typ ast.Expr } -func (p *parser) parseParamDecl(name *ast.Ident) (f field) { - // TODO(rFindley) compare with parser.paramDeclOrNil in the syntax package +func (p *parser) parseParamDecl(name *ast.Ident, typeSetsOK bool) (f field) { + // TODO(rFindley) refactor to be more similar to paramDeclOrNil in the syntax + // package if p.trace { defer un(trace(p, "ParamDeclOrNil")) } @@ -720,10 +720,14 @@ func (p *parser) parseParamDecl(name *ast.Ident) (f field) { ptok := p.tok if name != nil { p.tok = token.IDENT // force token.IDENT case in switch below + } else if typeSetsOK && p.tok == token.TILDE { + // "~" ... + return field{nil, p.embeddedElem(nil)} } switch p.tok { case token.IDENT: + // name if name != nil { f.name = name p.tok = ptok @@ -736,17 +740,32 @@ func (p *parser) parseParamDecl(name *ast.Ident) (f field) { f.typ = p.parseType() case token.LBRACK: - // name[type1, type2, ...] or name []type or name [len]type + // name "[" type1, ..., typeN "]" or name "[" n "]" type f.name, f.typ = p.parseArrayFieldOrTypeInstance(f.name) case token.ELLIPSIS: - // name ...type + // name "..." type f.typ = p.parseDotsType() + return // don't allow ...type "|" ... case token.PERIOD: - // qualified.typename + // name "." ... f.typ = p.parseQualifiedIdent(f.name) f.name = nil + + case token.TILDE: + if typeSetsOK { + f.typ = p.embeddedElem(nil) + return + } + + case token.OR: + if typeSetsOK { + // name "|" typeset + f.typ = p.embeddedElem(f.name) + f.name = nil + return + } } case token.MUL, token.ARROW, token.FUNC, token.LBRACK, token.CHAN, token.MAP, token.STRUCT, token.INTERFACE, token.LPAREN: @@ -754,23 +773,36 @@ func (p *parser) parseParamDecl(name *ast.Ident) (f field) { f.typ = p.parseType() case token.ELLIPSIS: - // ...type + // "..." type // (always accepted) f.typ = p.parseDotsType() + return // don't allow ...type "|" ... default: + // TODO(rfindley): this looks incorrect in the case of type parameter + // lists. p.errorExpected(p.pos, ")") p.advance(exprEnd) } + // [name] type "|" + if typeSetsOK && p.tok == token.OR && f.typ != nil { + f.typ = p.embeddedElem(f.typ) + } + return } -func (p *parser) parseParameterList(name0 *ast.Ident, closing token.Token, parseParamDecl func(*ast.Ident) field, tparams bool) (params []*ast.Field) { +func (p *parser) parseParameterList(name0 *ast.Ident, closing token.Token) (params []*ast.Field) { if p.trace { defer un(trace(p, "ParameterList")) } + // Type parameters are the only parameter list closed by ']'. + tparams := closing == token.RBRACK + // Type set notation is ok in type parameter lists. + typeSetsOK := tparams && p.allowTypeSets() + pos := p.pos if name0 != nil { pos = name0.Pos() @@ -780,7 +812,7 @@ func (p *parser) parseParameterList(name0 *ast.Ident, closing token.Token, parse var named int // number of parameters that have an explicit name and type for name0 != nil || p.tok != closing && p.tok != token.EOF { - par := parseParamDecl(name0) + par := p.parseParamDecl(name0, typeSetsOK) name0 = nil // 1st name was consumed if present if par.name != nil || par.typ != nil { list = append(list, par) @@ -818,11 +850,13 @@ func (p *parser) parseParameterList(name0 *ast.Ident, closing token.Token, parse // some named => all must be named ok := true var typ ast.Expr + missingName := pos for i := len(list) - 1; i >= 0; i-- { if par := &list[i]; par.typ != nil { typ = par.typ if par.name == nil { ok = false + missingName = par.typ.Pos() n := ast.NewIdent("_") n.NamePos = typ.Pos() // correct position par.name = n @@ -832,12 +866,13 @@ func (p *parser) parseParameterList(name0 *ast.Ident, closing token.Token, parse } else { // par.typ == nil && typ == nil => we only have a par.name ok = false + missingName = par.name.Pos() par.typ = &ast.BadExpr{From: par.name.Pos(), To: p.pos} } } if !ok { if tparams { - p.error(pos, "all type parameters must be named") + p.error(missingName, "all type parameters must be named") } else { p.error(pos, "mixed named and unnamed parameters") } @@ -883,11 +918,11 @@ func (p *parser) parseParameters(acceptTParams bool) (tparams, params *ast.Field defer un(trace(p, "Parameters")) } - if p.parseTypeParams() && acceptTParams && p.tok == token.LBRACK { + if p.allowGenerics() && acceptTParams && p.tok == token.LBRACK { opening := p.pos p.next() // [T any](params) syntax - list := p.parseParameterList(nil, token.RBRACK, p.parseParamDecl, true) + list := p.parseParameterList(nil, token.RBRACK) rbrack := p.expect(token.RBRACK) tparams = &ast.FieldList{Opening: opening, List: list, Closing: rbrack} // Type parameter lists must not be empty. @@ -901,7 +936,7 @@ func (p *parser) parseParameters(acceptTParams bool) (tparams, params *ast.Field var fields []*ast.Field if p.tok != token.RPAREN { - fields = p.parseParameterList(nil, token.RPAREN, p.parseParamDecl, false) + fields = p.parseParameterList(nil, token.RPAREN) } rparen := p.expect(token.RPAREN) @@ -956,7 +991,7 @@ func (p *parser) parseMethodSpec() *ast.Field { x := p.parseTypeName(nil) if ident, _ := x.(*ast.Ident); ident != nil { switch { - case p.tok == token.LBRACK && p.parseTypeParams(): + case p.tok == token.LBRACK && p.allowGenerics(): // generic method or embedded instantiated type lbrack := p.pos p.next() @@ -965,7 +1000,7 @@ func (p *parser) parseMethodSpec() *ast.Field { p.exprLev-- if name0, _ := x.(*ast.Ident); name0 != nil && p.tok != token.COMMA && p.tok != token.RBRACK { // generic method m[T any] - list := p.parseParameterList(name0, token.RBRACK, p.parseParamDecl, true) + list := p.parseParameterList(name0, token.RBRACK) rbrack := p.expect(token.RBRACK) tparams := &ast.FieldList{Opening: lbrack, List: list, Closing: rbrack} // TODO(rfindley) refactor to share code with parseFuncType. @@ -1011,7 +1046,7 @@ func (p *parser) parseMethodSpec() *ast.Field { } else { // embedded, possibly instantiated type typ = x - if p.tok == token.LBRACK && p.parseTypeParams() { + if p.tok == token.LBRACK && p.allowGenerics() { // embedded instantiated interface typ = p.parseTypeInstance(typ) } @@ -1024,24 +1059,23 @@ func (p *parser) parseMethodSpec() *ast.Field { return &ast.Field{Doc: doc, Names: idents, Type: typ} } -func (p *parser) embeddedElem(f *ast.Field) *ast.Field { +func (p *parser) embeddedElem(x ast.Expr) ast.Expr { if p.trace { defer un(trace(p, "EmbeddedElem")) } - if f == nil { - f = new(ast.Field) - f.Type = p.embeddedTerm() + if x == nil { + x = p.embeddedTerm() } for p.tok == token.OR { t := new(ast.BinaryExpr) t.OpPos = p.pos t.Op = token.OR p.next() - t.X = f.Type + t.X = x t.Y = p.embeddedTerm() - f.Type = t + x = t } - return f + return x } func (p *parser) embeddedTerm() ast.Expr { @@ -1083,18 +1117,18 @@ parseElements: switch { case p.tok == token.IDENT: f := p.parseMethodSpec() - if f.Names == nil && p.parseTypeParams() { - f = p.embeddedElem(f) + if f.Names == nil && p.allowGenerics() { + f.Type = p.embeddedElem(f.Type) } p.expectSemi() f.Comment = p.lineComment list = append(list, f) - case p.tok == token.TILDE && p.parseTypeParams(): - f := p.embeddedElem(nil) + case p.tok == token.TILDE && p.allowGenerics(): + typ := p.embeddedElem(nil) p.expectSemi() - f.Comment = p.lineComment - list = append(list, f) - case p.tok == token.TYPE && p.parseTypeParams(): + comment := p.lineComment + list = append(list, &ast.Field{Type: typ, Comment: comment}) + case p.tok == token.TYPE && p.allowGenerics(): // TODO(rfindley): remove TypeList syntax and refactor the clauses above. // all types in a type list share the same field name "type" @@ -1106,14 +1140,12 @@ parseElements: list = append(list, &ast.Field{Names: name, Type: typ}) } p.expectSemi() - case p.parseTypeParams(): + case p.allowGenerics(): if t := p.tryIdentOrType(); t != nil { - f := new(ast.Field) - f.Type = t - f = p.embeddedElem(f) + typ := p.embeddedElem(t) p.expectSemi() - f.Comment = p.lineComment - list = append(list, f) + comment := p.lineComment + list = append(list, &ast.Field{Type: typ, Comment: comment}) } else { break parseElements } @@ -1176,7 +1208,7 @@ func (p *parser) parseChanType() *ast.ChanType { } func (p *parser) parseTypeInstance(typ ast.Expr) ast.Expr { - assert(p.parseTypeParams(), "parseTypeInstance while not parsing type params") + assert(p.allowGenerics(), "parseTypeInstance while not parsing type params") if p.trace { defer un(trace(p, "TypeInstance")) } @@ -1212,7 +1244,7 @@ func (p *parser) tryIdentOrType() ast.Expr { switch p.tok { case token.IDENT: typ := p.parseTypeName(nil) - if p.tok == token.LBRACK && p.parseTypeParams() { + if p.tok == token.LBRACK && p.allowGenerics() { typ = p.parseTypeInstance(typ) } return typ @@ -1462,7 +1494,7 @@ func (p *parser) parseIndexOrSliceOrInstance(x ast.Expr) ast.Expr { return &ast.IndexExpr{X: x, Lbrack: lbrack, Index: index[0], Rbrack: rbrack} } - if !p.parseTypeParams() { + if !p.allowGenerics() { p.error(firstComma, "expected ']' or ':', found ','") return &ast.BadExpr{From: args[0].Pos(), To: args[len(args)-1].End()} } @@ -2507,7 +2539,7 @@ func (p *parser) parseValueSpec(doc *ast.CommentGroup, _ token.Pos, keyword toke } func (p *parser) parseGenericType(spec *ast.TypeSpec, openPos token.Pos, name0 *ast.Ident) { - list := p.parseParameterList(name0, token.RBRACK, p.parseParamDecl, true) + list := p.parseParameterList(name0, token.RBRACK) closePos := p.expect(token.RBRACK) spec.TypeParams = &ast.FieldList{Opening: openPos, List: list, Closing: closePos} // Type alias cannot have type parameters. Accept them for robustness but complain. @@ -2535,7 +2567,7 @@ func (p *parser) parseTypeSpec(doc *ast.CommentGroup, _ token.Pos, _ token.Token p.exprLev++ x := p.parseExpr() p.exprLev-- - if name0, _ := x.(*ast.Ident); p.parseTypeParams() && name0 != nil && p.tok != token.RBRACK { + if name0, _ := x.(*ast.Ident); p.allowGenerics() && name0 != nil && p.tok != token.RBRACK { // generic type [T any]; p.parseGenericType(spec, lbrack, name0) } else { diff --git a/src/go/parser/testdata/typeset.go2 b/src/go/parser/testdata/typeset.go2 new file mode 100644 index 0000000000..aa18e8ccff --- /dev/null +++ b/src/go/parser/testdata/typeset.go2 @@ -0,0 +1,75 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file contains test cases for typeset-only constraint elements. +// TODO(gri) gofmt once/if gofmt supports this notation. + +package p + +type ( + _[_ t] t + _[_ ~t] t + _[_ t|t] t + _[_ ~t|t] t + _[_ t|~t] t + _[_ ~t|~t] t + + _[_ t, _, _ t|t] t + _[_ t, _, _ ~t|t] t + _[_ t, _, _ t|~t] t + _[_ t, _, _ ~t|~t] t + + _[_ t.t] t + _[_ ~t.t] t + _[_ t.t|t.t] t + _[_ ~t.t|t.t] t + _[_ t.t|~t.t] t + _[_ ~t.t|~t.t] t + + _[_ t, _, _ t.t|t.t] t + _[_ t, _, _ ~t.t|t.t] t + _[_ t, _, _ t.t|~t.t] t + _[_ t, _, _ ~t.t|~t.t] t + + _[_ struct{}] t + _[_ ~struct{}] t + + _[_ struct{}|t] t + _[_ ~struct{}|t] t + _[_ struct{}|~t] t + _[_ ~struct{}|~t] t + + _[_ t|struct{}] t + _[_ ~t|struct{}] t + _[_ t|~struct{}] t + _[_ ~t|~struct{}] t +) + +// Single-expression type parameter lists and those that don't start +// with a (type parameter) name are considered array sizes. +// The term must be a valid expression (it could be a type - and then +// a type-checker will complain - but we don't allow ~ in the expr). +// TODO(rfindley): Improve error recover here. In these cases go/parser error +// recovery is worse than cmd/compile/internal/syntax, and unnecessary type +// declarations had to be inserted to force synchronization. +type _[t] t +type _[~ /* ERROR "expected operand" */ t] t +type /* ERROR "expected ']'" */ Sync int // placeholder to synchronize the parser +type _[t|t] t +type _[~ /* ERROR "expected operand" */ t|t] t +type /* ERROR "expected ']'" */ Sync int // placeholder to synchronize the parser +type _[t| ~ /* ERROR "expected operand" */ t] t +type /* ERROR "expected ']'" */ Sync int // placeholder to synchronize the parser +type _[~ /* ERROR "expected operand" */ t|~t] t +type /* ERROR "expected ']'" */ Sync int // placeholder to synchronize the parser + +type _[_ t, t /* ERROR "type parameters must be named" */ ] t +type _[_ ~t, t /* ERROR "type parameters must be named" */ ] t +type _[_ t, ~ /* ERROR "type parameters must be named" */ t] t +type _[_ ~t, ~ /* ERROR "type parameters must be named" */ t] t + +type _[_ t|t, t /* ERROR "type parameters must be named" */ |t] t +type _[_ ~t|t, t /* ERROR "type parameters must be named" */ |t] t +type _[_ t|t, ~ /* ERROR "type parameters must be named" */ t|t] t +type _[_ ~t|t, ~ /* ERROR "type parameters must be named" */ t|t] t diff --git a/src/go/printer/testdata/generics.golden b/src/go/printer/testdata/generics.golden index cc7fbbe1d8..31ab7716dd 100644 --- a/src/go/printer/testdata/generics.golden +++ b/src/go/printer/testdata/generics.golden @@ -36,8 +36,13 @@ func _() { } // properly format one-line type lists +// TODO(rfindley): remove support for type lists type _ interface{ type a } type _ interface { type a, b, c } + +// type constraint literals with elided interfaces +func _[P ~int, Q int | string]() {} +func _[P struct{ f int }, Q *P]() {} diff --git a/src/go/printer/testdata/generics.input b/src/go/printer/testdata/generics.input index f4571ad336..11431c5a0a 100644 --- a/src/go/printer/testdata/generics.input +++ b/src/go/printer/testdata/generics.input @@ -33,6 +33,11 @@ func _() { } // properly format one-line type lists +// TODO(rfindley): remove support for type lists type _ interface { type a } type _ interface { type a,b,c } + +// type constraint literals with elided interfaces +func _[P ~int, Q int | string]() {} +func _[P struct{f int}, Q *P]() {} -- GitLab From 662c5eed3324a334d2d9418deb9e60a6765ff972 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sun, 10 Oct 2021 10:43:20 -0400 Subject: [PATCH 1555/2500] go/types: accept constraint literals with elided interfaces This is a port of CL 353139 to go/types, adjusted for error reporting and for the different representation of field lists in go/ast. A TODO is added to verify if types2 produces redundant error messages for type parameters sharing a bound. For #48424 Change-Id: I3549942be0328de616d1d87d0ba621311fc53576 Reviewed-on: https://go-review.googlesource.com/c/go/+/354989 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/decl.go | 2 + src/go/types/decl.go | 31 ++++++++++-- src/go/types/testdata/examples/typesets.go2 | 48 ++++++++++++++++++ .../types/testdata/fixedbugs/issue39723.go2 | 2 +- src/go/types/typeparam.go | 49 +++++++++++++------ 5 files changed, 113 insertions(+), 19 deletions(-) create mode 100644 src/go/types/testdata/examples/typesets.go2 diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 5fa1ca889f..d427f26b7c 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -640,6 +640,8 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list []*syntax.Fiel check.later(func() { for i, tpar := range tparams { + // TODO(rfindley): this results in duplicate error messages for type + // parameters that share a constraint. if _, ok := under(tpar.bound).(*TypeParam); ok { check.error(list[i].Type, "cannot use a type parameter as constraint") } diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 22202cc7c9..c8cac0f148 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -681,7 +681,7 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list *ast.FieldList for _, f := range list.List { // TODO(rfindley) we should be able to rely on f.Type != nil at this point if f.Type != nil { - bound := check.typ(f.Type) + bound := check.bound(f.Type) bounds = append(bounds, bound) posns = append(posns, f.Type) for i := range f.Names { @@ -693,14 +693,37 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list *ast.FieldList check.later(func() { for i, bound := range bounds { - u := under(bound) - if _, ok := u.(*Interface); !ok && u != Typ[Invalid] { - check.errorf(posns[i], _Todo, "%s is not an interface", bound) + if _, ok := under(bound).(*TypeParam); ok { + check.error(posns[i], _Todo, "cannot use a type parameter as constraint") } } + for _, tpar := range tparams { + tpar.iface() // compute type set + } }) } +func (check *Checker) bound(x ast.Expr) Type { + // A type set literal of the form ~T and A|B may only appear as constraint; + // embed it in an implicit interface so that only interface type-checking + // needs to take care of such type expressions. + wrap := false + switch op := x.(type) { + case *ast.UnaryExpr: + wrap = op.Op == token.TILDE + case *ast.BinaryExpr: + wrap = op.Op == token.OR + } + if wrap { + // TODO(gri) Should mark this interface as "implicit" somehow + // (and propagate the info to types2.Interface) so + // that we can elide the interface again in error + // messages. Could use a sentinel name for the field. + x = &ast.InterfaceType{Methods: &ast.FieldList{List: []*ast.Field{{Type: x}}}} + } + return check.typ(x) +} + func (check *Checker) declareTypeParams(tparams []*TypeParam, names []*ast.Ident) []*TypeParam { // Use Typ[Invalid] for the type constraint to ensure that a type // is present even if the actual constraint has not been assigned diff --git a/src/go/types/testdata/examples/typesets.go2 b/src/go/types/testdata/examples/typesets.go2 new file mode 100644 index 0000000000..0a1b0f5cfc --- /dev/null +++ b/src/go/types/testdata/examples/typesets.go2 @@ -0,0 +1,48 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file shows some examples of constraint literals with elided interfaces. +// These examples are permitted if proposal issue #48424 is accepted. + +package p + +// Constraint type sets of the form T, ~T, or A|B may omit the interface. +type ( + _[T int] struct{} + _[T ~int] struct{} + _[T int|string] struct{} + _[T ~int|~string] struct{} +) + +func min[T int|string](x, y T) T { + if x < y { + return x + } + return y +} + +func lookup[M ~map[K]V, K comparable, V any](m M, k K) V { + return m[k] +} + +func deref[P ~*E, E any](p P) E { + return *p +} + +func _() int { + p := new(int) + return deref(p) +} + +func addrOfCopy[V any, P ~*V](v V) P { + return &v +} + +func _() *int { + return addrOfCopy(0) +} + +// A type parameter may not be embedded in an interface; +// so it can also not be used as a constraint. +func _[A any, B A /* ERROR cannot use a type parameter as constraint */ ]() {} diff --git a/src/go/types/testdata/fixedbugs/issue39723.go2 b/src/go/types/testdata/fixedbugs/issue39723.go2 index d5311ed3e7..00885238e6 100644 --- a/src/go/types/testdata/fixedbugs/issue39723.go2 +++ b/src/go/types/testdata/fixedbugs/issue39723.go2 @@ -6,4 +6,4 @@ package p // A constraint must be an interface; it cannot // be a type parameter, for instance. -func _[A interface{ ~int }, B A /* ERROR not an interface */ ]() {} +func _[A interface{ ~int }, B A /* ERROR cannot use a type parameter as constraint */ ]() {} diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index 150ad079a8..51bedc2b7d 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -24,8 +24,7 @@ type TypeParam struct { id uint64 // unique id, for debugging only obj *TypeName // corresponding type name index int // type parameter index in source order, starting at 0 - // TODO(rfindley): this could also be Typ[Invalid]. Verify that this is handled correctly. - bound Type // *Named or *Interface; underlying type is always *Interface + bound Type // any type, but eventually an *Interface for correct programs (see TypeParam.iface) } // NewTypeParam returns a new TypeParam. Type parameters may be set on a Named @@ -69,15 +68,6 @@ func (t *TypeParam) Obj() *TypeName { return t.obj } // Constraint returns the type constraint specified for t. func (t *TypeParam) Constraint() Type { - // compute the type set if possible (we may not have an interface) - if iface, _ := under(t.bound).(*Interface); iface != nil { - // use the type bound position if we have one - pos := token.NoPos - if n, _ := t.bound.(*Named); n != nil { - pos = n.obj.pos - } - computeInterfaceTypeSet(t.check, pos, iface) - } return t.bound } @@ -97,10 +87,41 @@ func (t *TypeParam) String() string { return TypeString(t, nil) } // iface returns the constraint interface of t. func (t *TypeParam) iface() *Interface { - if iface, _ := under(t.Constraint()).(*Interface); iface != nil { - return iface + bound := t.bound + + // determine constraint interface + var ityp *Interface + switch u := under(bound).(type) { + case *Basic: + if u == Typ[Invalid] { + // error is reported elsewhere + return &emptyInterface + } + case *Interface: + ityp = u + case *TypeParam: + // error is reported in Checker.collectTypeParams + return &emptyInterface + } + + // If we don't have an interface, wrap constraint into an implicit interface. + // TODO(gri) mark it as implicit - see comment in Checker.bound + if ityp == nil { + ityp = NewInterfaceType(nil, []Type{bound}) + t.bound = ityp // update t.bound for next time (optimization) } - return &emptyInterface + + // compute type set if necessary + if ityp.tset == nil { + // use the (original) type bound position if we have one + pos := token.NoPos + if n, _ := bound.(*Named); n != nil { + pos = n.obj.pos + } + computeInterfaceTypeSet(t.check, pos, ityp) + } + + return ityp } // structuralType returns the structural type of the type parameter's constraint; or nil. -- GitLab From b41030e6e00d1507141c7c00c014fe8bd9e41ef6 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sun, 10 Oct 2021 10:46:56 -0400 Subject: [PATCH 1556/2500] go/internal/gcimporter: enable importing typeparam/issue48424.go This is a partial revert of CL 353389, now that go/types supports eliding interface in constraints. For #48424 Change-Id: Ibde26fb66bf6bd5a4c919acffd045a57783d1b47 Reviewed-on: https://go-review.googlesource.com/c/go/+/354990 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/internal/gcimporter/gcimporter_test.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/go/internal/gcimporter/gcimporter_test.go b/src/go/internal/gcimporter/gcimporter_test.go index 825f735db9..3a9ed79df6 100644 --- a/src/go/internal/gcimporter/gcimporter_test.go +++ b/src/go/internal/gcimporter/gcimporter_test.go @@ -165,9 +165,8 @@ func TestImportTypeparamTests(t *testing.T) { } skip := map[string]string{ - "equal.go": "inconsistent embedded sorting", // TODO(rfindley): investigate this. - "nested.go": "fails to compile", // TODO(rfindley): investigate this. - "issue48424.go": "go/types support missing", // TODO: need to implement this if #48424 is accepted + "equal.go": "inconsistent embedded sorting", // TODO(rfindley): investigate this. + "nested.go": "fails to compile", // TODO(rfindley): investigate this. } for _, entry := range list { -- GitLab From c1b0ae4154b44ce0bc4929455ee468fddb5dca9d Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sun, 10 Oct 2021 10:53:06 -0400 Subject: [PATCH 1557/2500] go/types: mark implicit interfaces as such This is a straightforward port of CL 353396 to go/types. For #48424 Change-Id: I3040c2ad3a8c9573026277de01deb9c47953cec8 Reviewed-on: https://go-review.googlesource.com/c/go/+/354991 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/decl.go | 10 ++++++---- src/go/types/interface.go | 5 ++++- src/go/types/testdata/examples/typesets.go2 | 10 ++++++++++ src/go/types/typeparam.go | 1 + src/go/types/typestring.go | 9 +++++++++ src/go/types/universe.go | 4 ++-- 6 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/go/types/decl.go b/src/go/types/decl.go index c8cac0f148..f97fa252cb 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -715,11 +715,13 @@ func (check *Checker) bound(x ast.Expr) Type { wrap = op.Op == token.OR } if wrap { - // TODO(gri) Should mark this interface as "implicit" somehow - // (and propagate the info to types2.Interface) so - // that we can elide the interface again in error - // messages. Could use a sentinel name for the field. x = &ast.InterfaceType{Methods: &ast.FieldList{List: []*ast.Field{{Type: x}}}} + t := check.typ(x) + // mark t as implicit interface if all went well + if t, _ := t.(*Interface); t != nil { + t.implicit = true + } + return t } return check.typ(x) } diff --git a/src/go/types/interface.go b/src/go/types/interface.go index 866a3427ca..2f4f10d45f 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -19,6 +19,7 @@ type Interface struct { methods []*Func // ordered list of explicitly declared methods embeddeds []Type // ordered list of explicitly embedded elements embedPos *[]token.Pos // positions of embedded elements; or nil (for error messages) - use pointer to save space + implicit bool // interface is wrapper for type set literal (non-interface T, ~T, or A|B) complete bool // indicates that obj, methods, and embeddeds are set and type set can be computed tset *_TypeSet // type set described by this interface, computed lazily @@ -108,6 +109,9 @@ func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() } // set. func (t *Interface) IsMethodSet() bool { return t.typeSet().IsMethodSet() } +// IsImplicit reports whether the interface t is a wrapper for a type set literal. +func (t *Interface) IsImplicit() bool { return t.implicit } + // Complete computes the interface's type set. It must be called by users of // NewInterfaceType and NewInterface after the interface's embedded types are // fully defined and before using the interface type in any way other than to @@ -143,7 +147,6 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d for _, f := range iface.Methods.List { if len(f.Names) == 0 { - // We have an embedded type; possibly a union of types. addEmbedded(f.Type.Pos(), parseUnion(check, flattenUnion(nil, f.Type))) continue } diff --git a/src/go/types/testdata/examples/typesets.go2 b/src/go/types/testdata/examples/typesets.go2 index 0a1b0f5cfc..cf01072d8c 100644 --- a/src/go/types/testdata/examples/typesets.go2 +++ b/src/go/types/testdata/examples/typesets.go2 @@ -46,3 +46,13 @@ func _() *int { // A type parameter may not be embedded in an interface; // so it can also not be used as a constraint. func _[A any, B A /* ERROR cannot use a type parameter as constraint */ ]() {} + +// Error messages refer to the type constraint as it appears in the source. +// (No implicit interface should be exposed.) +func _[T string](x T) T { + return x /* ERROR constrained by string */ * x +} + +func _[T int|string](x T) T { + return x /* ERROR constrained by int|string */ * x +} diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index 51bedc2b7d..e2755cbbda 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -108,6 +108,7 @@ func (t *TypeParam) iface() *Interface { // TODO(gri) mark it as implicit - see comment in Checker.bound if ityp == nil { ityp = NewInterfaceType(nil, []Type{bound}) + ityp.implicit = true t.bound = ityp // update t.bound for next time (optimization) } diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 4a087c4ed1..a0c78e8cc3 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -191,6 +191,15 @@ func (w *typeWriter) typ(typ Type) { } case *Interface: + if t.implicit { + if len(t.methods) == 0 && len(t.embeddeds) == 1 { + w.typ(t.embeddeds[0]) + break + } + // Something's wrong with the implicit interface. + // Print it as such and continue. + w.string("/* implicit */ ") + } w.string("interface{") first := true for _, m := range t.methods { diff --git a/src/go/types/universe.go b/src/go/types/universe.go index 4d52242e61..519cf0b707 100644 --- a/src/go/types/universe.go +++ b/src/go/types/universe.go @@ -89,7 +89,7 @@ func defPredeclaredTypes() { res := NewVar(token.NoPos, nil, "", Typ[String]) sig := NewSignatureType(nil, nil, nil, nil, NewTuple(res), false) err := NewFunc(token.NoPos, nil, "Error", sig) - ityp := &Interface{nil, obj, []*Func{err}, nil, nil, true, nil} + ityp := &Interface{nil, obj, []*Func{err}, nil, nil, false, true, nil} computeInterfaceTypeSet(nil, token.NoPos, ityp) // prevent races due to lazy computation of tset typ := NewNamed(obj, ityp, nil) sig.recv = NewVar(token.NoPos, nil, "", typ) @@ -100,7 +100,7 @@ func defPredeclaredTypes() { { obj := NewTypeName(token.NoPos, nil, "comparable", nil) obj.setColor(black) - ityp := &Interface{nil, obj, nil, nil, nil, true, &_TypeSet{true, nil, allTermlist}} + ityp := &Interface{nil, obj, nil, nil, nil, false, true, &_TypeSet{true, nil, allTermlist}} NewNamed(obj, ityp, nil) def(obj) } -- GitLab From d90f0b920054e5e3fba981eea67fe092732a4376 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 11 Oct 2021 09:59:40 -0400 Subject: [PATCH 1558/2500] cmd/compile/internal/types2: avoid duplicate errors for invalid bounds Resolve a TODO from an earlier CL: we should only check type parameter bounds once in collectTypeParams. Change-Id: Icf6053ec359f8ac8143cf68ee2defd504f8f86e6 Reviewed-on: https://go-review.googlesource.com/c/go/+/355069 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/decl.go | 15 ++++++++++----- .../types2/testdata/examples/typesets.go2 | 2 ++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index d427f26b7c..26a16d9917 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -627,24 +627,29 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list []*syntax.Fiel // Example: type T[P T[P]] interface{} *dst = bindTParams(tparams) + // Keep track of bounds for later validation. var bound Type + var bounds []Type + var posers []poser for i, f := range list { // Optimization: Re-use the previous type bound if it hasn't changed. // This also preserves the grouped output of type parameter lists // when printing type strings. if i == 0 || f.Type != list[i-1].Type { bound = check.bound(f.Type) + bounds = append(bounds, bound) + posers = append(posers, f.Type) } tparams[i].bound = bound } check.later(func() { - for i, tpar := range tparams { - // TODO(rfindley): this results in duplicate error messages for type - // parameters that share a constraint. - if _, ok := under(tpar.bound).(*TypeParam); ok { - check.error(list[i].Type, "cannot use a type parameter as constraint") + for i, bound := range bounds { + if _, ok := under(bound).(*TypeParam); ok { + check.error(posers[i], "cannot use a type parameter as constraint") } + } + for _, tpar := range tparams { tpar.iface() // compute type set } }) diff --git a/src/cmd/compile/internal/types2/testdata/examples/typesets.go2 b/src/cmd/compile/internal/types2/testdata/examples/typesets.go2 index cf01072d8c..e19dcf8da3 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/typesets.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/typesets.go2 @@ -46,6 +46,8 @@ func _() *int { // A type parameter may not be embedded in an interface; // so it can also not be used as a constraint. func _[A any, B A /* ERROR cannot use a type parameter as constraint */ ]() {} +func _[A any, B, C A /* ERROR cannot use a type parameter as constraint */ ]() {} + // Error messages refer to the type constraint as it appears in the source. // (No implicit interface should be exposed.) -- GitLab From 6372e7efbab5a613b73271938acbd1c6f558814e Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 7 Oct 2021 13:05:16 -0700 Subject: [PATCH 1559/2500] cmd/api: support type parameters Fixes #48706 Change-Id: If0f8d0b49300027e3b2b46f6870302acf2e00f4e Reviewed-on: https://go-review.googlesource.com/c/go/+/354612 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/cmd/api/goapi.go | 76 +++++++++++++++++++++- src/cmd/api/testdata/src/pkg/p4/golden.txt | 4 ++ src/cmd/api/testdata/src/pkg/p4/p4.go | 22 +++++++ 3 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 src/cmd/api/testdata/src/pkg/p4/golden.txt create mode 100644 src/cmd/api/testdata/src/pkg/p4/p4.go diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go index 43c761a657..eca113a638 100644 --- a/src/cmd/api/goapi.go +++ b/src/cmd/api/goapi.go @@ -706,6 +706,36 @@ func sortedMethodNames(typ *types.Interface) []string { return list } +// sortedEmbeddeds returns constraint types embedded in an +// interface. It does not include embedded interface types or methods. +func (w *Walker) sortedEmbeddeds(typ *types.Interface) []string { + n := typ.NumEmbeddeds() + list := make([]string, 0, n) + for i := 0; i < n; i++ { + emb := typ.EmbeddedType(i) + switch emb := emb.(type) { + case *types.Interface: + list = append(list, w.sortedEmbeddeds(emb)...) + case *types.Union: + var buf bytes.Buffer + nu := emb.Len() + for i := 0; i < nu; i++ { + if i > 0 { + buf.WriteString(" | ") + } + term := emb.Term(i) + if term.Tilde() { + buf.WriteByte('~') + } + w.writeType(&buf, term.Type()) + } + list = append(list, buf.String()) + } + } + sort.Strings(list) + return list +} + func (w *Walker) writeType(buf *bytes.Buffer, typ types.Type) { switch typ := typ.(type) { case *types.Basic: @@ -763,9 +793,16 @@ func (w *Walker) writeType(buf *bytes.Buffer, typ types.Type) { case *types.Interface: buf.WriteString("interface{") - if typ.NumMethods() > 0 { + if typ.NumMethods() > 0 || typ.NumEmbeddeds() > 0 { buf.WriteByte(' ') + } + if typ.NumMethods() > 0 { buf.WriteString(strings.Join(sortedMethodNames(typ), ", ")) + } + if typ.NumEmbeddeds() > 0 { + buf.WriteString(strings.Join(w.sortedEmbeddeds(typ), ", ")) + } + if typ.NumMethods() > 0 || typ.NumEmbeddeds() > 0 { buf.WriteByte(' ') } buf.WriteString("}") @@ -800,12 +837,18 @@ func (w *Walker) writeType(buf *bytes.Buffer, typ types.Type) { } buf.WriteString(typ.Obj().Name()) + case *types.TypeParam: + buf.WriteString(typ.Obj().Name()) + default: panic(fmt.Sprintf("unknown type %T", typ)) } } func (w *Walker) writeSignature(buf *bytes.Buffer, sig *types.Signature) { + if tparams := sig.TypeParams(); tparams != nil { + w.writeTypeParams(buf, tparams, true) + } w.writeParams(buf, sig.Params(), sig.Variadic()) switch res := sig.Results(); res.Len() { case 0: @@ -819,6 +862,23 @@ func (w *Walker) writeSignature(buf *bytes.Buffer, sig *types.Signature) { } } +func (w *Walker) writeTypeParams(buf *bytes.Buffer, tparams *types.TypeParamList, withConstraints bool) { + buf.WriteByte('[') + c := tparams.Len() + for i := 0; i < c; i++ { + if i > 0 { + buf.WriteString(", ") + } + tp := tparams.At(i) + buf.WriteString(tp.Obj().Name()) + if withConstraints { + buf.WriteByte(' ') + w.writeType(buf, tp.Constraint()) + } + } + buf.WriteByte(']') +} + func (w *Walker) writeParams(buf *bytes.Buffer, t *types.Tuple, variadic bool) { buf.WriteByte('(') for i, n := 0, t.Len(); i < n; i++ { @@ -872,6 +932,12 @@ func (w *Walker) emitObj(obj types.Object) { func (w *Walker) emitType(obj *types.TypeName) { name := obj.Name() + if tparams := obj.Type().(*types.Named).TypeParams(); tparams != nil { + var buf bytes.Buffer + buf.WriteString(name) + w.writeTypeParams(&buf, tparams, true) + name = buf.String() + } typ := obj.Type() if obj.IsAlias() { w.emitf("type %s = %s", name, w.typeString(typ)) @@ -995,7 +1061,13 @@ func (w *Walker) emitMethod(m *types.Selection) { log.Fatalf("exported method with unexported receiver base type: %s", m) } } - w.emitf("method (%s) %s%s", w.typeString(recv), m.Obj().Name(), w.signatureString(sig)) + tps := "" + if rtp := sig.RecvTypeParams(); rtp != nil { + var buf bytes.Buffer + w.writeTypeParams(&buf, rtp, false) + tps = buf.String() + } + w.emitf("method (%s%s) %s%s", w.typeString(recv), tps, m.Obj().Name(), w.signatureString(sig)) } func (w *Walker) emitf(format string, args ...interface{}) { diff --git a/src/cmd/api/testdata/src/pkg/p4/golden.txt b/src/cmd/api/testdata/src/pkg/p4/golden.txt new file mode 100644 index 0000000000..d5f282be8e --- /dev/null +++ b/src/cmd/api/testdata/src/pkg/p4/golden.txt @@ -0,0 +1,4 @@ +pkg p4, func NewPair[T1 interface{ M }, T2 interface{ ~int }](T1, T2) Pair +pkg p4, method (Pair[_, X2]) Second() X2 +pkg p4, method (Pair[X1, _]) First() X1 +pkg p4, type Pair[T1 interface{ M }, T2 interface{ ~int }] struct diff --git a/src/cmd/api/testdata/src/pkg/p4/p4.go b/src/cmd/api/testdata/src/pkg/p4/p4.go new file mode 100644 index 0000000000..187339b169 --- /dev/null +++ b/src/cmd/api/testdata/src/pkg/p4/p4.go @@ -0,0 +1,22 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p4 + +type Pair[T1 interface { M() }, T2 ~int] struct { + f1 T1 + f2 T2 +} + +func NewPair[T1 interface { M() }, T2 ~int](v1 T1, v2 T2) Pair[T1, T2] { + return Pair[T1, T2]{f1: v1, f2: v2} +} + +func (p Pair[X1, _]) First() X1 { + return p.f1 +} + +func (p Pair[_, X2]) Second() X2 { + return p.f2 +} -- GitLab From d887d3be5f8f143f2475ddb2ea6c48ceb32def17 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 11 Oct 2021 09:32:52 +0200 Subject: [PATCH 1560/2500] cmd/link/internal/ld: use libc based fcntl for (*OutBuf).fallocate on darwin Direct syscalls are no longer supported on darwin. Instead, use libc fcntl go:linkname'd from the syscall package. Change-Id: Ieeec64810452455faedd200f661a8b5839ca1fa0 Reviewed-on: https://go-review.googlesource.com/c/go/+/255260 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Reviewed-by: Cherry Mui --- src/cmd/link/internal/ld/outbuf_darwin.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cmd/link/internal/ld/outbuf_darwin.go b/src/cmd/link/internal/ld/outbuf_darwin.go index 9444b6567e..6920a0a843 100644 --- a/src/cmd/link/internal/ld/outbuf_darwin.go +++ b/src/cmd/link/internal/ld/outbuf_darwin.go @@ -9,6 +9,10 @@ import ( "unsafe" ) +// Implemented in the syscall package. +//go:linkname fcntl syscall.fcntl +func fcntl(fd int, cmd int, arg int) (int, error) + func (out *OutBuf) fallocate(size uint64) error { stat, err := out.f.Stat() if err != nil { @@ -29,12 +33,8 @@ func (out *OutBuf) fallocate(size uint64) error { Length: int64(size - cursize), } - _, _, errno := syscall.Syscall(syscall.SYS_FCNTL, uintptr(out.f.Fd()), syscall.F_PREALLOCATE, uintptr(unsafe.Pointer(store))) - if errno != 0 { - return errno - } - - return nil + _, err = fcntl(int(out.f.Fd()), syscall.F_PREALLOCATE, int(uintptr(unsafe.Pointer(store)))) + return err } func (out *OutBuf) purgeSignatureCache() { -- GitLab From 9c1dbdf60edbffeff10f58af21fa055eb0fdd29f Mon Sep 17 00:00:00 2001 From: Nigel Tao Date: Sat, 9 Oct 2021 16:52:19 +1100 Subject: [PATCH 1561/2500] compress/lzw: output a Clear code first, per GIF spec The TestStartsWithClearCode test is new, but if it existed beforehand, the want strings would be "\x81" and "Hi\x81" without a starting "\x80". Fixes #26108 Fixes #33748 Updates makeworld-the-better-one/didder#7 Updates nothings/stb#1222 Change-Id: I35ac0ed862ba6ee921ba9aee257bc19828abaa82 Reviewed-on: https://go-review.googlesource.com/c/go/+/354710 Trust: Nigel Tao Run-TryBot: Nigel Tao TryBot-Result: Go Bot Reviewed-by: Andrew Gerrand --- src/compress/lzw/writer.go | 20 +++++++++++++++++++- src/compress/lzw/writer_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/compress/lzw/writer.go b/src/compress/lzw/writer.go index 552bdc2ce1..cf06ea80c7 100644 --- a/src/compress/lzw/writer.go +++ b/src/compress/lzw/writer.go @@ -137,7 +137,19 @@ func (w *Writer) Write(p []byte) (n int, err error) { n = len(p) code := w.savedCode if code == invalidCode { - // The first code sent is always a literal code. + // This is the first write; send a clear code. + // https://www.w3.org/Graphics/GIF/spec-gif89a.txt Appendix F + // "Variable-Length-Code LZW Compression" says that "Encoders should + // output a Clear code as the first code of each image data stream". + // + // LZW compression isn't only used by GIF, but it's cheap to follow + // that directive unconditionally. + clear := uint32(1) << w.litWidth + if err := w.write(w, clear); err != nil { + return 0, err + } + // After the starting clear code, the next code sent (for non-empty + // input) is always a literal code. code, p = uint32(p[0]), p[1:] } loop: @@ -202,6 +214,12 @@ func (w *Writer) Close() error { if err := w.incHi(); err != nil && err != errOutOfCodes { return err } + } else { + // Write the starting clear code, as w.Write did not. + clear := uint32(1) << w.litWidth + if err := w.write(w, clear); err != nil { + return err + } } // Write the eof code. eof := uint32(1)< Date: Tue, 9 Mar 2021 16:55:20 -0600 Subject: [PATCH 1562/2500] cmd/internal/obj/ppc64: support alignment of prefixed insn Insert machine NOPs when a prefixed instruction crosses a 64B boundary. ISA 3.1 prohibits prefixed instructions being placed across them. Such instructions generate SIGILL if executed. Likewise, adjust the function alignment to guarantee such instructions can never cross one. And, don't pad the PC based on alignment. The linker can fit these more optimally. Likewise, include the function alignment when printing function debug information. This is needed to verify function alignment happens. Updates #44549 Change-Id: I434fb0ee4e984ca00dc4566f7569c3bcdf93f910 Reviewed-on: https://go-review.googlesource.com/c/go/+/347050 Run-TryBot: Paul Murphy TryBot-Result: Go Bot Reviewed-by: Cherry Mui Reviewed-by: Lynn Boger --- src/cmd/internal/obj/objfile.go | 2 +- src/cmd/internal/obj/ppc64/a.out.go | 24 ++-- src/cmd/internal/obj/ppc64/anames.go | 1 + src/cmd/internal/obj/ppc64/asm9.go | 72 ++++++++-- src/cmd/internal/obj/ppc64/asm_test.go | 174 ++++++++++++++++++++++++- 5 files changed, 245 insertions(+), 28 deletions(-) diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index 98af803880..a590549f52 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -804,7 +804,7 @@ func (ctxt *Link) writeSymDebugNamed(s *LSym, name string) { fmt.Fprintf(ctxt.Bso, "size=%d", s.Size) if s.Type == objabi.STEXT { fn := s.Func() - fmt.Fprintf(ctxt.Bso, " args=%#x locals=%#x funcid=%#x", uint64(fn.Args), uint64(fn.Locals), uint64(fn.FuncID)) + fmt.Fprintf(ctxt.Bso, " args=%#x locals=%#x funcid=%#x align=%#x", uint64(fn.Args), uint64(fn.Locals), uint64(fn.FuncID), uint64(fn.Align)) if s.Leaf() { fmt.Fprintf(ctxt.Bso, " leaf") } diff --git a/src/cmd/internal/obj/ppc64/a.out.go b/src/cmd/internal/obj/ppc64/a.out.go index 3a1e2d3c9a..dd6d903e28 100644 --- a/src/cmd/internal/obj/ppc64/a.out.go +++ b/src/cmd/internal/obj/ppc64/a.out.go @@ -295,16 +295,17 @@ const ( const ( /* mark flags */ - LABEL = 1 << 0 - LEAF = 1 << 1 - FLOAT = 1 << 2 - BRANCH = 1 << 3 - LOAD = 1 << 4 - FCMP = 1 << 5 - SYNC = 1 << 6 - LIST = 1 << 7 - FOLL = 1 << 8 - NOSCHED = 1 << 9 + LABEL = 1 << 0 + LEAF = 1 << 1 + FLOAT = 1 << 2 + BRANCH = 1 << 3 + LOAD = 1 << 4 + FCMP = 1 << 5 + SYNC = 1 << 6 + LIST = 1 << 7 + FOLL = 1 << 8 + NOSCHED = 1 << 9 + PFX_X64B = 1 << 10 // A prefixed instruction crossing a 64B boundary ) // Values for use in branch instruction BC @@ -1013,6 +1014,9 @@ const ( AXVCVUXDSP AXVCVUXWSP + /* ISA 3.1 opcodes */ + APNOP + ALAST // aliases diff --git a/src/cmd/internal/obj/ppc64/anames.go b/src/cmd/internal/obj/ppc64/anames.go index fca4b3e355..0da73ca91e 100644 --- a/src/cmd/internal/obj/ppc64/anames.go +++ b/src/cmd/internal/obj/ppc64/anames.go @@ -613,5 +613,6 @@ var Anames = []string{ "XVCVSXWSP", "XVCVUXDSP", "XVCVUXWSP", + "PNOP", "LAST", } diff --git a/src/cmd/internal/obj/ppc64/asm9.go b/src/cmd/internal/obj/ppc64/asm9.go index 0901d64792..6ed11b3f7e 100644 --- a/src/cmd/internal/obj/ppc64/asm9.go +++ b/src/cmd/internal/obj/ppc64/asm9.go @@ -73,6 +73,12 @@ type Optab struct { a6 uint8 // p.To (obj.Addr) type_ int8 // cases in asmout below. E.g., 44 = st r,(ra+rb); 45 = ld (ra+rb), r size int8 // Text space in bytes to lay operation + + // A prefixed instruction is generated by this opcode. This cannot be placed + // across a 64B PC address. Opcodes should not translate to more than one + // prefixed instruction. The prefixed instruction should be written first + // (e.g when Optab.size > 8). + ispfx bool } // optab contains an array to be sliced of accepted operand combinations for an @@ -509,6 +515,9 @@ var optab = []Optab{ {as: ASTSW, a1: C_REG, a3: C_LCON, a6: C_ZOREG, type_: 41, size: 4}, {as: ALSW, a1: C_ZOREG, a6: C_REG, type_: 45, size: 4}, {as: ALSW, a1: C_ZOREG, a3: C_LCON, a6: C_REG, type_: 42, size: 4}, + + {as: APNOP, type_: 105, size: 8, ispfx: true}, + {as: obj.AUNDEF, type_: 78, size: 4}, {as: obj.APCDATA, a1: C_LCON, a6: C_LCON, type_: 0, size: 0}, {as: obj.AFUNCDATA, a1: C_SCON, a6: C_ADDR, type_: 0, size: 0}, @@ -642,9 +651,11 @@ func span9(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { var otxt int64 var q *obj.Prog var out [6]uint32 + var falign int32 // Track increased alignment requirements for prefix. for bflag != 0 { bflag = 0 pc = 0 + falign = 0 // Note, linker bumps function symbols to funcAlign. for p = c.cursym.Func().Text.Link; p != nil; p = p.Link { p.Pc = pc o = c.oplook(p) @@ -738,25 +749,56 @@ func span9(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { } } + // Prefixed instructions cannot be placed across a 64B boundary. + // Mark and adjust the PC of those which do. A nop will be + // inserted during final assembly. + if o.ispfx { + mark := p.Mark &^ PFX_X64B + if pc&63 == 60 { + p.Pc += 4 + m += 4 + mark |= PFX_X64B + } + + // Marks may be adjusted if a too-far conditional branch is + // fixed up above. Likewise, inserting a NOP may cause a + // branch target to become too far away. We need to run + // another iteration and verify no additional changes + // are needed. + if mark != p.Mark { + bflag = 1 + p.Mark = mark + } + + // Check for 16 or 32B crossing of this prefixed insn. + // These do no require padding, but do require increasing + // the function alignment to prevent them from potentially + // crossing a 64B boundary when the linker assigns the final + // PC. + switch p.Pc & 31 { + case 28: // 32B crossing + falign = 64 + case 12: // 16B crossing + if falign < 64 { + falign = 32 + } + } + } + pc += int64(m) } c.cursym.Size = pc } - if r := pc & funcAlignMask; r != 0 { - pc += funcAlign - r - } - c.cursym.Size = pc - - /* - * lay out the code, emitting code and data relocations. - */ - + c.cursym.Func().Align = falign c.cursym.Grow(c.cursym.Size) + // lay out the code, emitting code and data relocations. + bp := c.cursym.P + nop := LOP_IRR(OP_ORI, REGZERO, REGZERO, 0) var i int32 for p := c.cursym.Func().Text.Link; p != nil; p = p.Link { c.pc = p.Pc @@ -766,17 +808,20 @@ func span9(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { } // asmout is not set up to add large amounts of padding if o.type_ == 0 && p.As == obj.APCALIGN { - pad := LOP_RRR(OP_OR, REGZERO, REGZERO, REGZERO) aln := c.vregoff(&p.From) v := addpad(p.Pc, aln, c.ctxt, c.cursym) if v > 0 { // Same padding instruction for all for i = 0; i < int32(v/4); i++ { - c.ctxt.Arch.ByteOrder.PutUint32(bp, pad) + c.ctxt.Arch.ByteOrder.PutUint32(bp, nop) bp = bp[4:] } } } else { + if p.Mark&PFX_X64B != 0 { + c.ctxt.Arch.ByteOrder.PutUint32(bp, nop) + bp = bp[4:] + } c.asmout(p, o, out[:]) for i = 0; i < int32(o.size/4); i++ { c.ctxt.Arch.ByteOrder.PutUint32(bp, out[i]) @@ -1979,6 +2024,7 @@ func buildop(ctxt *obj.Link) { AECIWX, ACLRLSLWI, AMTVSRDD, + APNOP, obj.ANOP, obj.ATEXT, obj.AUNDEF, @@ -3695,6 +3741,10 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) { case 104: /* VSX mtvsr* instructions, XX1-form RA,RB,XT */ o1 = AOP_XX1(c.oprrr(p.As), uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg)) + + case 105: /* PNOP */ + o1 = 0x07000000 + o2 = 0x00000000 } out[0] = o1 diff --git a/src/cmd/internal/obj/ppc64/asm_test.go b/src/cmd/internal/obj/ppc64/asm_test.go index 60c5f346e0..ec0ba19e37 100644 --- a/src/cmd/internal/obj/ppc64/asm_test.go +++ b/src/cmd/internal/obj/ppc64/asm_test.go @@ -17,14 +17,20 @@ import ( "testing" ) -var invalidPCAlignSrc = ` +var platformEnvs = [][]string{ + {"GOOS=aix", "GOARCH=ppc64"}, + {"GOOS=linux", "GOARCH=ppc64"}, + {"GOOS=linux", "GOARCH=ppc64le"}, +} + +const invalidPCAlignSrc = ` TEXT test(SB),0,$0-0 ADD $2, R3 PCALIGN $64 RET ` -var validPCAlignSrc = ` +const validPCAlignSrc = ` TEXT test(SB),0,$0-0 ADD $2, R3 PCALIGN $16 @@ -37,10 +43,166 @@ ADD $4, R8 RET ` -var platformEnvs = [][]string{ - {"GOOS=aix", "GOARCH=ppc64"}, - {"GOOS=linux", "GOARCH=ppc64"}, - {"GOOS=linux", "GOARCH=ppc64le"}, +const x64pgm = ` +TEXT test(SB),0,$0-0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +PNOP +` +const x32pgm = ` +TEXT test(SB),0,$0-0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +PNOP +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +` + +const x16pgm = ` +TEXT test(SB),0,$0-0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +PNOP +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +` + +const x0pgm = ` +TEXT test(SB),0,$0-0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +PNOP +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +` +const x64pgmA64 = ` +TEXT test(SB),0,$0-0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +PNOP +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +PNOP +` + +const x64pgmA32 = ` +TEXT test(SB),0,$0-0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +PNOP +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +OR R0, R0 +PNOP +` + +// Test that nops are inserted when crossing 64B boundaries, and +// alignment is adjusted to avoid crossing. +func TestPfxAlign(t *testing.T) { + testenv.MustHaveGoBuild(t) + + dir, err := ioutil.TempDir("", "testpfxalign") + if err != nil { + t.Fatalf("could not create directory: %v", err) + } + defer os.RemoveAll(dir) + + pgms := []struct { + text []byte + align string + hasNop bool + }{ + {[]byte(x0pgm), "align=0x0", false}, // No alignment or nop adjustments needed + {[]byte(x16pgm), "align=0x20", false}, // Increased alignment needed + {[]byte(x32pgm), "align=0x40", false}, // Worst case alignment needed + {[]byte(x64pgm), "align=0x0", true}, // 0 aligned is default (16B) alignment + {[]byte(x64pgmA64), "align=0x40", true}, // extra alignment + nop + {[]byte(x64pgmA32), "align=0x20", true}, // extra alignment + nop + } + + for _, pgm := range pgms { + tmpfile := filepath.Join(dir, "x.s") + err = ioutil.WriteFile(tmpfile, pgm.text, 0644) + if err != nil { + t.Fatalf("can't write output: %v\n", err) + } + cmd := exec.Command(testenv.GoToolPath(t), "tool", "asm", "-S", "-o", filepath.Join(dir, "test.o"), tmpfile) + cmd.Env = append(os.Environ(), "GOOS=linux", "GOARCH=ppc64le") + out, err := cmd.CombinedOutput() + if err != nil { + t.Errorf("Failed to compile %v: %v\n", pgm, err) + } + if !strings.Contains(string(out), pgm.align) { + t.Errorf(fmt.Sprintf("Fatal, misaligned text with prefixed instructions:\n%s\n", string(out))) + } + hasNop := strings.Contains(string(out), "00 00 00 60") + if hasNop != pgm.hasNop { + t.Errorf(fmt.Sprintf("Fatal, prefixed instruction is missing nop padding:\n%s\n", string(out))) + } + } } // TestLarge generates a very large file to verify that large -- GitLab From 36a265a625a8320fea93aad62da4003b2cc54f72 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Thu, 7 Oct 2021 16:26:36 -0400 Subject: [PATCH 1563/2500] testing: fix -run behavior with fuzz tests This change fixes some issues with -run, and the subsequent command line output when running in verbose mode. It replaces CorpusEntry.Name with CorpusEntry.Path, and refactors the code accordingly. This change also adds a lot of additional tests which check explicit command line output when fuzz targets are run without fuzzing. This will be important to avoid regressions. Updates #48149 Change-Id: If34b1f51db646317b7b51c3c38ae53231d01f568 Reviewed-on: https://go-review.googlesource.com/c/go/+/354632 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- .../script/test_fuzz_mutate_crash.txt | 2 +- src/cmd/go/testdata/script/test_fuzz_run.txt | 145 ++++++++++++++++++ .../testdata/script/test_fuzz_seed_corpus.txt | 1 + src/internal/fuzz/fuzz.go | 78 +++++----- src/internal/fuzz/worker.go | 6 +- src/testing/fuzz.go | 38 +++-- 6 files changed, 212 insertions(+), 58 deletions(-) create mode 100644 src/cmd/go/testdata/script/test_fuzz_run.txt diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt index 79476ecb28..628e003f41 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt @@ -21,7 +21,7 @@ go run check_testdata.go FuzzWithBug # Now, the failing bytes should have been added to the seed corpus for # the target, and should fail when run without fuzzing. ! go test -stdout 'testdata[/\\]fuzz[/\\]FuzzWithBug[/\\][a-f0-9]{64}' +stdout 'FuzzWithBug/[a-f0-9]{64}' stdout 'this input caused a crash!' ! go test -run=FuzzWithNilPanic -fuzz=FuzzWithNilPanic -fuzztime=100x -fuzzminimizetime=1000x diff --git a/src/cmd/go/testdata/script/test_fuzz_run.txt b/src/cmd/go/testdata/script/test_fuzz_run.txt new file mode 100644 index 0000000000..e546d997cb --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_run.txt @@ -0,0 +1,145 @@ +# TODO(jayconrod): support shared memory on more platforms. +[!darwin] [!linux] [!windows] skip + +[short] skip +env GOCACHE=$WORK/cache + +# Tests which verify the behavior and command line output when +# running a fuzz target as a unit test. + +# Tests without -run. + +! go test +stdout FAIL +stdout 'error here' + +! go test -v +stdout FAIL +stdout 'error here' +stdout '=== RUN FuzzFoo/thisfails' +stdout '--- FAIL: FuzzFoo/thisfails' +stdout '=== RUN FuzzFoo/thispasses' +stdout '--- PASS: FuzzFoo/thispasses' + +# Tests where -run matches all seed corpora. + +! go test -run FuzzFoo/this +stdout FAIL +stdout 'error here' +! stdout 'no tests to run' + +! go test -run /this +stdout FAIL +stdout 'error here' +! stdout 'no tests to run' + +! go test -v -run FuzzFoo/this +stdout FAIL +stdout 'error here' +stdout '=== RUN FuzzFoo/thisfails' +stdout '--- FAIL: FuzzFoo/thisfails' +stdout '=== RUN FuzzFoo/thispasses' +stdout '--- PASS: FuzzFoo/thispasses' +! stdout 'no tests to run' + +! go test -v -run /this +stdout FAIL +stdout 'error here' +stdout '=== RUN FuzzFoo/thisfails' +stdout '--- FAIL: FuzzFoo/thisfails' +stdout '=== RUN FuzzFoo/thispasses' +stdout '--- PASS: FuzzFoo/thispasses' +! stdout 'no tests to run' + +# Tests where -run only matches one seed corpus which passes. + +go test -run FuzzFoo/thispasses +stdout ok +! stdout 'no tests to run' + +go test -run /thispasses +stdout ok +! stdout 'no tests to run' + +# Same tests in verbose mode +go test -v -run FuzzFoo/thispasses +stdout '=== RUN FuzzFoo/thispasses' +stdout '--- PASS: FuzzFoo/thispasses' +! stdout '=== RUN FuzzFoo/thisfails' +! stdout 'no tests to run' + +go test -v -run /thispasses +stdout '=== RUN FuzzFoo/thispasses' +stdout '--- PASS: FuzzFoo/thispasses' +! stdout '=== RUN FuzzFoo/thisfails' +! stdout 'no tests to run' + +# Tests where -run only matches one seed corpus which fails. + +! go test -run FuzzFoo/thisfails +stdout FAIL +stdout 'error here' +! stdout 'no tests to run' + +! go test -run /thisfails +stdout FAIL +stdout 'error here' +! stdout 'no tests to run' + +! go test -v -run FuzzFoo/thisfails +stdout 'error here' +stdout '=== RUN FuzzFoo/thisfails' +stdout '--- FAIL: FuzzFoo/thisfails' +! stdout '=== RUN FuzzFoo/thispasses' +! stdout 'no tests to run' + +! go test -v -run /thisfails +stdout 'error here' +stdout '=== RUN FuzzFoo/thisfails' +stdout '--- FAIL: FuzzFoo/thisfails' +! stdout '=== RUN FuzzFoo/thispasses' +! stdout 'no tests to run' + +# Tests where -run doesn't match any seed corpora. + +go test -run FuzzFoo/nomatch +stdout ok + +go test -run /nomatch +stdout ok + +go test -v -run FuzzFoo/nomatch +stdout '=== RUN FuzzFoo' +stdout '--- PASS: FuzzFoo' +stdout ok +! stdout 'no tests to run' + +go test -v -run /nomatch +stdout '=== RUN FuzzFoo' +stdout '--- PASS: FuzzFoo' +stdout ok +! stdout 'no tests to run' + +-- go.mod -- +module example.com/x + +go 1.16 +-- x_test.go -- +package x + +import "testing" + +func FuzzFoo(f *testing.F) { + f.Add("this is fine") + f.Fuzz(func(t *testing.T, s string) { + if s == "fails" { + t.Error("error here") + } + }) +} +-- testdata/fuzz/FuzzFoo/thisfails -- +go test fuzz v1 +string("fails") +-- testdata/fuzz/FuzzFoo/thispasses -- +go test fuzz v1 +string("passes") \ No newline at end of file diff --git a/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt b/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt index a66d0554b6..5d04d8c022 100644 --- a/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt +++ b/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt @@ -26,6 +26,7 @@ stdout ok ! go test -fuzz=FuzzWithTestdata -run=FuzzWithTestdata -fuzztime=1x ! stdout ^ok ! stdout 'Crash written to testdata[/\\]fuzz[/\\]FuzzWithTestdata[/\\]' +stdout 'found a crash while testing seed corpus entry: FuzzWithTestdata/1' stdout FAIL # Test that fuzzing a target with no seed corpus or cache finds a crash, prints diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index f660052911..a8bbd60b1c 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -141,14 +141,14 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err if c.crashMinimizing == nil || crashWritten { return } - fileName, werr := writeToCorpus(c.crashMinimizing.entry.Data, opts.CorpusDir) + werr := writeToCorpus(&c.crashMinimizing.entry, opts.CorpusDir) if werr != nil { err = fmt.Errorf("%w\n%v", err, werr) return } if err == nil { err = &crashError{ - name: filepath.Base(fileName), + path: c.crashMinimizing.entry.Path, err: errors.New(c.crashMinimizing.crasherMsg), } } @@ -230,7 +230,8 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err if result.crasherMsg != "" { if c.warmupRun() && result.entry.IsSeed { - fmt.Fprintf(c.opts.Log, "found a crash while testing seed corpus entry: %q\n", result.entry.Parent) + target := filepath.Base(c.opts.CorpusDir) + fmt.Fprintf(c.opts.Log, "found a crash while testing seed corpus entry: %s/%s\n", target, testName(result.entry.Parent)) stop(errors.New(result.crasherMsg)) break } @@ -249,11 +250,11 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err } else if !crashWritten { // Found a crasher that's either minimized or not minimizable. // Write to corpus and stop. - fileName, err := writeToCorpus(result.entry.Data, opts.CorpusDir) + err := writeToCorpus(&result.entry, opts.CorpusDir) if err == nil { crashWritten = true err = &crashError{ - name: filepath.Base(fileName), + path: result.entry.Path, err: errors.New(result.crasherMsg), } } @@ -262,7 +263,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err c.opts.Log, "DEBUG new crasher, elapsed: %s, id: %s, parent: %s, gen: %d, size: %d, exec time: %s\n", c.elapsed(), - fileName, + result.entry.Path, result.entry.Parent, result.entry.Generation, len(result.entry.Data), @@ -315,12 +316,11 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err // Update the coordinator's coverage mask and save the value. inputSize := len(result.entry.Data) if opts.CacheDir != "" { - filename, err := writeToCorpus(result.entry.Data, opts.CacheDir) + err := writeToCorpus(&result.entry, opts.CacheDir) if err != nil { stop(err) } result.entry.Data = nil - result.entry.Name = filename } c.updateCoverage(keepCoverage) c.corpus.entries = append(c.corpus.entries, result.entry) @@ -331,7 +331,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err c.opts.Log, "DEBUG new interesting input, elapsed: %s, id: %s, parent: %s, gen: %d, new bits: %d, total bits: %d, size: %d, exec time: %s\n", c.elapsed(), - result.entry.Name, + result.entry.Path, result.entry.Parent, result.entry.Generation, countBits(keepCoverage), @@ -347,7 +347,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err c.opts.Log, "DEBUG worker reported interesting input that doesn't expand coverage, elapsed: %s, id: %s, parent: %s, canMinimize: %t\n", c.elapsed(), - result.entry.Name, + result.entry.Path, result.entry.Parent, result.canMinimize, ) @@ -397,7 +397,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err // of the file where the input causing the crasher was saved. The testing // framework uses this to report a command to re-run that specific input. type crashError struct { - name string + path string err error } @@ -409,8 +409,8 @@ func (e *crashError) Unwrap() error { return e.err } -func (e *crashError) CrashName() string { - return e.name +func (e *crashError) CrashPath() string { + return e.path } type corpus struct { @@ -426,14 +426,14 @@ type corpus struct { type CorpusEntry = struct { Parent string - // Name is the name of the corpus file, if the entry was loaded from the - // seed corpus. It can be used with -run. For entries added with f.Add and - // entries generated by the mutator, Name is empty and Data is populated. - Name string + // Path is the path of the corpus file, if the entry was loaded from disk. + // For other entries, including seed values provided by f.Add, Path is the + // name of the test, e.g. seed#0 or its hash. + Path string - // Data is the raw input data. Data should only be populated for initial - // seed values added with f.Add. For on-disk corpus files, Data will - // be nil. + // Data is the raw input data. Data should only be populated for seed + // values. For on-disk corpus files, Data will be nil, as it will be loaded + // from disk using Path. Data []byte // Values is the unmarshaled values from a corpus file. @@ -452,7 +452,7 @@ func CorpusEntryData(ce CorpusEntry) ([]byte, error) { return ce.Data, nil } - return os.ReadFile(ce.Name) + return os.ReadFile(ce.Path) } type fuzzInput struct { @@ -616,7 +616,7 @@ type coordinator struct { } func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { - // Make sure all of the seed corpus given by f.Add has marshalled data. + // Make sure all of the seed corpus has marshalled data. for i := range opts.Seed { if opts.Seed[i].Data == nil && opts.Seed[i].Values != nil { opts.Seed[i].Data = marshalCorpusFile(opts.Seed[i].Values...) @@ -673,7 +673,7 @@ func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { data := marshalCorpusFile(vals...) h := sha256.Sum256(data) name := fmt.Sprintf("%x", h[:4]) - c.corpus.entries = append(c.corpus.entries, CorpusEntry{Name: name, Data: data}) + c.corpus.entries = append(c.corpus.entries, CorpusEntry{Path: name, Data: data}) } return c, nil @@ -956,7 +956,7 @@ func ReadCorpus(dir string, types []reflect.Type) ([]CorpusEntry, error) { errs = append(errs, fmt.Errorf("%q: %v", filename, err)) continue } - corpus = append(corpus, CorpusEntry{Name: filename, Values: vals}) + corpus = append(corpus, CorpusEntry{Path: filename, Values: vals}) } if len(errs) > 0 { return corpus, &MalformedCorpusError{errs: errs} @@ -979,7 +979,7 @@ func readCorpusData(data []byte, types []reflect.Type) ([]interface{}, error) { // provided. func CheckCorpus(vals []interface{}, types []reflect.Type) error { if len(vals) != len(types) { - return fmt.Errorf("wrong number of values in corpus entry: %d, want %d", len(vals), len(types)) + return fmt.Errorf("wrong number of values in corpus entry %v: want %v", vals, types) } for i := range types { if reflect.TypeOf(vals[i]) != types[i] { @@ -989,21 +989,25 @@ func CheckCorpus(vals []interface{}, types []reflect.Type) error { return nil } -// writeToCorpus atomically writes the given bytes to a new file in testdata. -// If the directory does not exist, it will create one. If the file already -// exists, writeToCorpus will not rewrite it. writeToCorpus returns the -// file's name, or an error if it failed. -func writeToCorpus(b []byte, dir string) (name string, err error) { - sum := fmt.Sprintf("%x", sha256.Sum256(b)) - name = filepath.Join(dir, sum) +// writeToCorpus atomically writes the given bytes to a new file in testdata. If +// the directory does not exist, it will create one. If the file already exists, +// writeToCorpus will not rewrite it. writeToCorpus sets entry.Path to the new +// file that was just written or an error if it failed. +func writeToCorpus(entry *CorpusEntry, dir string) (err error) { + sum := fmt.Sprintf("%x", sha256.Sum256(entry.Data)) + entry.Path = filepath.Join(dir, sum) if err := os.MkdirAll(dir, 0777); err != nil { - return "", err + return err } - if err := ioutil.WriteFile(name, b, 0666); err != nil { - os.Remove(name) // remove partially written file - return "", err + if err := ioutil.WriteFile(entry.Path, entry.Data, 0666); err != nil { + os.Remove(entry.Path) // remove partially written file + return err } - return name, nil + return nil +} + +func testName(path string) string { + return filepath.Base(path) } func zeroValue(t reflect.Type) interface{} { diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 1429decba8..0c428ed832 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -1029,7 +1029,7 @@ func (wc *workerClient) minimize(ctx context.Context, entryIn CorpusEntry, args entryOut.Values, err = unmarshalCorpusFile(entryOut.Data) h := sha256.Sum256(entryOut.Data) name := fmt.Sprintf("%x", h[:4]) - entryOut.Name = name + entryOut.Path = name entryOut.Parent = entryIn.Parent entryOut.Generation = entryIn.Generation if err != nil { @@ -1092,8 +1092,8 @@ func (wc *workerClient) fuzz(ctx context.Context, entryIn CorpusEntry, args fuzz h := sha256.Sum256(dataOut) name := fmt.Sprintf("%x", h[:4]) entryOut = CorpusEntry{ - Name: name, - Parent: entryIn.Name, + Parent: entryIn.Path, + Path: name, Data: dataOut, Generation: entryIn.Generation + 1, } diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 60e2603da9..40b77c1331 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -80,7 +80,7 @@ var _ TB = (*F)(nil) // import internal/fuzz from testing. type corpusEntry = struct { Parent string - Name string + Path string Data []byte Values []interface{} Generation int @@ -259,7 +259,7 @@ func (f *F) Add(args ...interface{}) { } values = append(values, args[i]) } - f.corpus = append(f.corpus, corpusEntry{Values: values, IsSeed: true, Name: fmt.Sprintf("seed#%d", len(f.corpus))}) + f.corpus = append(f.corpus, corpusEntry{Values: values, IsSeed: true, Path: fmt.Sprintf("seed#%d", len(f.corpus))}) } // supportedTypes represents all of the supported types which can be fuzzed. @@ -369,16 +369,16 @@ func (f *F) Fuzz(ff interface{}) { // fn is called in its own goroutine. run := func(e corpusEntry) error { if e.Values == nil { - // Every code path should have already unmarshaled Data into Values. - // It's our fault if it didn't. - panic(fmt.Sprintf("corpus file %q was not unmarshaled", e.Name)) + // The corpusEntry must have non-nil Values in order to run the + // test. If Values is nil, it is a bug in our code. + panic(fmt.Sprintf("corpus file %q was not unmarshaled", e.Path)) } if shouldFailFast() { return nil } - testName := f.common.name - if e.Name != "" { - testName = fmt.Sprintf("%s/%s", testName, e.Name) + testName := f.name + if e.Path != "" { + testName = fmt.Sprintf("%s/%s", testName, filepath.Base(e.Path)) } // Record the stack trace at the point of this call so that if the subtest @@ -448,9 +448,10 @@ func (f *F) Fuzz(ff interface{}) { f.Fail() fmt.Fprintf(f.w, "%v\n", err) if crashErr, ok := err.(fuzzCrashError); ok { - crashName := crashErr.CrashName() - fmt.Fprintf(f.w, "Crash written to %s\n", filepath.Join(corpusDir, f.name, crashName)) - fmt.Fprintf(f.w, "To re-run:\ngo test %s -run=%s/%s\n", f.fuzzContext.deps.ImportPath(), f.name, crashName) + crashPath := crashErr.CrashPath() + fmt.Fprintf(f.w, "Crash written to %s\n", crashPath) + testName := filepath.Base(crashPath) + fmt.Fprintf(f.w, "To re-run:\ngo test %s -run=%s/%s\n", f.fuzzContext.deps.ImportPath(), f.name, testName) } } // TODO(jayconrod,katiehockman): Aggregate statistics across workers @@ -470,7 +471,10 @@ func (f *F) Fuzz(ff interface{}) { // Fuzzing is not enabled, or will be done later. Only run the seed // corpus now. for _, e := range f.corpus { - run(e) + name := fmt.Sprintf("%s/%s", f.name, filepath.Base(e.Path)) + if _, ok, _ := f.testContext.match.fullName(nil, name); ok { + run(e) + } } } } @@ -516,11 +520,11 @@ type fuzzCrashError interface { error Unwrap() error - // CrashName returns the name of the subtest that corresponds to the saved - // crash input file in the seed corpus. The test can be re-run with - // go test $pkg -run=$target/$name where $pkg is the package's import path, - // $target is the fuzz target name, and $name is the string returned here. - CrashName() string + // CrashPath returns the path of the subtest that corresponds to the saved + // crash input file in the seed corpus. The test can be re-run with go test + // -run=$target/$name $target is the fuzz target name, and $name is the + // filepath.Base of the string returned here. + CrashPath() string } // fuzzContext holds fields common to all fuzz targets. -- GitLab From 6e0adde1e9467f5a0b9bdbe3d64f9093981ba5df Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 12 Oct 2021 12:38:42 -0400 Subject: [PATCH 1564/2500] cmd/compile: do not reuse dead value in expand_calls pass We reuse a value for the same selector on the same arg. But if the value is already marked dead, don't reuse it. A use of an OpInvalid will confuse the compiler. Fixes #48916. Change-Id: I15b9e15b49f6e1991fe91df246cd12a193385e85 Reviewed-on: https://go-review.googlesource.com/c/go/+/355409 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: Cuong Manh Le Reviewed-by: David Chase TryBot-Result: Go Bot --- src/cmd/compile/internal/ssa/expand_calls.go | 10 ++++-- test/fixedbugs/issue48916.go | 37 ++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 test/fixedbugs/issue48916.go diff --git a/src/cmd/compile/internal/ssa/expand_calls.go b/src/cmd/compile/internal/ssa/expand_calls.go index a0f0e653aa..18c9ab696d 100644 --- a/src/cmd/compile/internal/ssa/expand_calls.go +++ b/src/cmd/compile/internal/ssa/expand_calls.go @@ -1678,7 +1678,7 @@ func (x *expandState) rewriteArgToMemOrRegs(v *Value) *Value { t := v.Type key := selKey{v, 0, t.Size(), t} w := x.commonArgs[key] - if w != nil { + if w != nil && w.Uses != 0 { // do not reuse dead value v.copyOf(w) break } @@ -1709,9 +1709,15 @@ func (x *expandState) newArgToMemOrRegs(baseArg, toReplace *Value, offset int64, } key := selKey{baseArg, offset, t.Size(), t} w := x.commonArgs[key] - if w != nil { + if w != nil && w.Uses != 0 { // do not reuse dead value if toReplace != nil { toReplace.copyOf(w) + if x.debug > 1 { + x.Printf("...replace %s\n", toReplace.LongString()) + } + } + if x.debug > 1 { + x.Printf("-->%s\n", w.LongString()) } return w } diff --git a/test/fixedbugs/issue48916.go b/test/fixedbugs/issue48916.go new file mode 100644 index 0000000000..cbe97b5127 --- /dev/null +++ b/test/fixedbugs/issue48916.go @@ -0,0 +1,37 @@ +// compile + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Issue 48916: expand_calls pass crashes due to a (dead) +// use of an OpInvalid value. + +package p + +type T struct { + num int64 +} + +func foo(vs map[T]struct{}, d T) error { + _, ok := vs[d] + if !ok { + return nil + } + + switch d.num { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + var num float64 + if num != 0 { + return nil + } + } + + return nil +} -- GitLab From f8bfdc9eda4a065b88e5d7ab968957d9c84694bf Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Mon, 11 Oct 2021 15:51:10 -0700 Subject: [PATCH 1565/2500] cmd/go: adjust documentation mentioning 'go get' In module-aware mode, 'go get' no longer builds or installs packages. - 'go generate' explains build commands do not run generate commands. 'go get' is no longer a build command, so this CL removes mention of it. - 'go get' will continue to accept build flags, but they're ignored. The documentation no longer mentions them, though it does mention -x for printing VCS commands. For #43684 Change-Id: I1eea7241eecf72ba9f98238b729d91cc77ec7665 Reviewed-on: https://go-review.googlesource.com/c/go/+/355209 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/alldocs.go | 9 ++++++--- src/cmd/go/internal/generate/generate.go | 2 +- src/cmd/go/internal/modget/get.go | 7 +++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 8a2109619d..c3e4179025 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -498,7 +498,7 @@ // files. Those commands can run any process but the intent is to // create or update Go source files. // -// Go generate is never run automatically by go build, go get, go test, +// Go generate is never run automatically by go build, go test, // and so on. It must be run explicitly. // // Go generate scans the file for directives, which are lines of @@ -644,8 +644,7 @@ // // See 'go help install' or https://golang.org/ref/mod#go-install for details. // -// In addition to build flags (listed in 'go help build') 'go get' accepts the -// following flags. +// 'go get' accepts the following flags. // // The -t flag instructs get to consider modules needed to build tests of // packages specified on the command line. @@ -660,6 +659,10 @@ // When the -t and -u flags are used together, get will update // test dependencies as well. // +// The -x flag prints commands as they are executed. This is useful for +// debugging version control commands when a module is downloaded directly +// from a repository. +// // For more about modules, see https://golang.org/ref/mod. // // For more about specifying packages, see 'go help packages'. diff --git a/src/cmd/go/internal/generate/generate.go b/src/cmd/go/internal/generate/generate.go index d7f2eb4610..5981e5ecdb 100644 --- a/src/cmd/go/internal/generate/generate.go +++ b/src/cmd/go/internal/generate/generate.go @@ -38,7 +38,7 @@ Generate runs commands described by directives within existing files. Those commands can run any process but the intent is to create or update Go source files. -Go generate is never run automatically by go build, go get, go test, +Go generate is never run automatically by go build, go test, and so on. It must be run explicitly. Go generate scans the file for directives, which are lines of diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index 4d87d2670d..c634512072 100644 --- a/src/cmd/go/internal/modget/get.go +++ b/src/cmd/go/internal/modget/get.go @@ -83,8 +83,7 @@ current directory. For example: See 'go help install' or https://golang.org/ref/mod#go-install for details. -In addition to build flags (listed in 'go help build') 'go get' accepts the -following flags. +'go get' accepts the following flags. The -t flag instructs get to consider modules needed to build tests of packages specified on the command line. @@ -99,6 +98,10 @@ but changes the default to select patch releases. When the -t and -u flags are used together, get will update test dependencies as well. +The -x flag prints commands as they are executed. This is useful for +debugging version control commands when a module is downloaded directly +from a repository. + For more about modules, see https://golang.org/ref/mod. For more about specifying packages, see 'go help packages'. -- GitLab From 26b6833308548f78a0926309c3acf7fd59b287f5 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 6 Oct 2021 13:51:21 -0400 Subject: [PATCH 1566/2500] go/types: export TypeParam.Index and remove TypeParam._SetId This change resolves a TODO regarding a couple uncertain APIs for types.TypeParam. In the case of TypeParam._Index, we've decided it is worth exporting. In the case of TypeParam._SetId, we've decided it is unnecessary. This aligns go/types with types2 (a doc comment in types2 is also updated). Updates #47916 Change-Id: I705e8b3437d014775c473e2f8be6f32b1540bb0e Reviewed-on: https://go-review.googlesource.com/c/go/+/354370 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/typeparam.go | 3 ++- src/go/types/typeparam.go | 13 +++---------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index 6bc9dbc24d..f7cdff0180 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -50,7 +50,8 @@ func (check *Checker) newTypeParam(obj *TypeName, constraint Type) *TypeParam { return typ } -// Index returns the index of the type param within its param list. +// Index returns the index of the type param within its param list, or -1 if +// the type parameter has not yet been bound to a type. func (t *TypeParam) Index() int { return t.index } diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index e2755cbbda..af36266f11 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -50,19 +50,12 @@ func (check *Checker) newTypeParam(obj *TypeName, constraint Type) *TypeParam { return typ } -// TODO(rfindley): remove or export these placeholder APIs. - -// Index returns the index of the type param within its param list. -func (t *TypeParam) _Index() int { +// Index returns the index of the type param within its param list, or -1 if +// the type parameter has not yet been bound to a type. +func (t *TypeParam) Index() int { return t.index } -// SetId sets the unique id of a type param. Should only be used for type params -// in imported generic types. -func (t *TypeParam) _SetId(id uint64) { - t.id = id -} - // Obj returns the type name for t. func (t *TypeParam) Obj() *TypeName { return t.obj } -- GitLab From 4186db6155ccd4cfcf71dee0bce566a097f49406 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 4 Oct 2021 11:56:12 -0700 Subject: [PATCH 1567/2500] cmd/compile: some fixes in type substituter for Instantiate In the case in (*TSubster).Type() that we were running into an incomplete underlying type (TFORW), we should just be immediately returning the type returned by ts.SubstForwFunc(forw), since that call returns a proper type node, and has set up any remaining work that has to be done when we get done with the current top-level type definition. (For import, that function is doInst, which does an Instantiate of the new substituted type, with the delayed part via deferredInstStack.) We should not continue doing the later parts of (*TSubster).Type(), since the underlying type may not yet have its methods filled in, etc. Also, in Instantiate(), we need to put the desired new type on deferredInstStack, even if the base type node already exists, if the type node is in TFORW state. This is now exactly the case when Instantiate is called from (*TSubster).Type via doInst, since (*TSubster).Type has already called NewIncompleteNamedType(). Fixes #48716 Fixes #48889 Change-Id: Icd6be5721c4ac75bf8869b8bbdeca50069d632ec Reviewed-on: https://go-review.googlesource.com/c/go/+/355250 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/typecheck/iimport.go | 24 +++++++- src/cmd/compile/internal/typecheck/subr.go | 2 +- test/typeparam/issue48716.dir/a.go | 51 ++++++++++++++++ test/typeparam/issue48716.dir/main.go | 58 +++++++++++++++++++ test/typeparam/issue48716.go | 7 +++ 5 files changed, 138 insertions(+), 4 deletions(-) create mode 100644 test/typeparam/issue48716.dir/a.go create mode 100644 test/typeparam/issue48716.dir/main.go create mode 100644 test/typeparam/issue48716.go diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 08850079eb..df49d74a40 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1822,9 +1822,25 @@ func Instantiate(pos src.XPos, baseType *types.Type, targs []*types.Type) *types instSym := baseSym.Pkg.Lookup(name) if instSym.Def != nil { // May match existing type from previous import or - // types2-to-types1 conversion, or from in-progress instantiation - // in the current type import stack. - return instSym.Def.Type() + // types2-to-types1 conversion. + t := instSym.Def.Type() + if t.Kind() != types.TFORW { + return t + } + // Or, we have started creating this type in (*TSubster).Typ, but its + // underlying type was not completed yet, so we need to add this type + // to deferredInstStack, if not already there. + found := false + for _, t2 := range deferredInstStack { + if t2 == t { + found = true + break + } + } + if !found { + deferredInstStack = append(deferredInstStack, t) + } + return t } t := NewIncompleteNamedType(baseType.Pos(), instSym) @@ -1865,6 +1881,7 @@ func resumeDoInst() { // during a type substitution for an instantiation. This is needed for // instantiations of mutually recursive types. func doInst(t *types.Type) *types.Type { + assert(t.Kind() == types.TFORW) return Instantiate(t.Pos(), t.OrigSym().Def.(*ir.Name).Type(), t.RParams()) } @@ -1873,6 +1890,7 @@ func doInst(t *types.Type) *types.Type { // instantiation being created, baseType is the base generic type, and targs are // the type arguments that baseType is being instantiated with. func substInstType(t *types.Type, baseType *types.Type, targs []*types.Type) { + assert(t.Kind() == types.TFORW) subst := Tsubster{ Tparams: baseType.RParams(), Targs: targs, diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 68240329f5..6288d15a01 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1217,7 +1217,7 @@ func (ts *Tsubster) typ1(t *types.Type) *types.Type { } case types.TFORW: if ts.SubstForwFunc != nil { - newt = ts.SubstForwFunc(t) + return ts.SubstForwFunc(forw) } else { assert(false) } diff --git a/test/typeparam/issue48716.dir/a.go b/test/typeparam/issue48716.dir/a.go new file mode 100644 index 0000000000..63e599d9a1 --- /dev/null +++ b/test/typeparam/issue48716.dir/a.go @@ -0,0 +1,51 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type Pair[L, R any] struct { + L L + R R +} + +func Two[L, R any](l L, r R) Pair[L, R] { + return Pair[L, R]{L: l, R: r} +} + +type Map[K, V any] interface { + Put(K, V) + Len() int + Iterate(func(Pair[K, V]) bool) +} + +type HashMap[K comparable, V any] struct { + m map[K]V +} + +func NewHashMap[K comparable, V any](capacity int) HashMap[K, V] { + var m map[K]V + if capacity >= 1 { + m = make(map[K]V, capacity) + } else { + m = map[K]V{} + } + + return HashMap[K, V]{m: m} +} + +func (m HashMap[K, V]) Put(k K, v V) { + m.m[k] = v +} + +func (m HashMap[K, V]) Len() int { + return len(m.m) +} + +func (m HashMap[K, V]) Iterate(cb func(Pair[K, V]) bool) { + for k, v := range m.m { + if !cb(Two(k, v)) { + return + } + } +} diff --git a/test/typeparam/issue48716.dir/main.go b/test/typeparam/issue48716.dir/main.go new file mode 100644 index 0000000000..adde0f5afe --- /dev/null +++ b/test/typeparam/issue48716.dir/main.go @@ -0,0 +1,58 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "a" +) + +// Creates copy of set +func Copy[T comparable](src MapSet[T]) (dst MapSet[T]) { + dst = HashSet[T](src.Len()) + Fill(src, dst) + return +} + +// Fill src from dst +func Fill[T any](src, dst MapSet[T]) { + src.Iterate(func(t T) bool { + dst.Add(t) + return true + }) + return +} + +type MapSet[T any] struct { + m a.Map[T, struct{}] +} + +func HashSet[T comparable](capacity int) MapSet[T] { + return FromMap[T](a.NewHashMap[T, struct{}](capacity)) +} + +func FromMap[T any](m a.Map[T, struct{}]) MapSet[T] { + return MapSet[T]{ + m: m, + } +} + +func (s MapSet[T]) Add(t T) { + s.m.Put(t, struct{}{}) +} + +func (s MapSet[T]) Len() int { + return s.m.Len() +} + +func (s MapSet[T]) Iterate(cb func(T) bool) { + s.m.Iterate(func(p a.Pair[T, struct{}]) bool { + return cb(p.L) + }) +} + +func main() { + x := FromMap[int](a.NewHashMap[int, struct{}](1)) + Copy[int](x) +} diff --git a/test/typeparam/issue48716.go b/test/typeparam/issue48716.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/issue48716.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From d032b2b2c8235ef25275405f6655866f2c81661d Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Wed, 6 Oct 2021 14:58:22 -0700 Subject: [PATCH 1568/2500] testing: don't create unique subtest names while fuzzing T.Run uses a map[string]int64 to keep track of subtest names that may be returned through T.Name. T.Name can't return duplicate names for subtests started with T.Run. If a fuzz target calls T.Run, this map takes a large amount of memory, since there are a very large number of subtests that would otherwise have duplicate names, and the map stores one entry per subtest. The unique suffixes are not useful (and may be confusing) since the full sequence of tests cannot be re-run deterministically. This change deletes all entries in the map before each call to the function being fuzzed. There is a slight change in the contract of T.Name while fuzzing. This change was discussed in CL 351452. Fixes #44517 Change-Id: I3093a2e5568099ce54aca1006fac84a6fd2c3ddf Reviewed-on: https://go-review.googlesource.com/c/go/+/354430 Trust: Jay Conrod Trust: Katie Hockman Trust: Bryan C. Mills Run-TryBot: Jay Conrod Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/testing/fuzz.go | 9 ++++++++- src/testing/match.go | 11 +++++++++++ src/testing/testing.go | 20 +++++++------------- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 40b77c1331..0429f8243d 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -380,6 +380,13 @@ func (f *F) Fuzz(ff interface{}) { if e.Path != "" { testName = fmt.Sprintf("%s/%s", testName, filepath.Base(e.Path)) } + if f.testContext.isFuzzing { + // Don't preserve subtest names while fuzzing. If fn calls T.Run, + // there will be a very large number of subtests with duplicate names, + // which will use a large amount of memory. The subtest names aren't + // useful since there's no way to re-run them deterministically. + f.testContext.match.clearSubNames() + } // Record the stack trace at the point of this call so that if the subtest // function - which runs in a separate stack - is marked as a helper, we can @@ -395,7 +402,6 @@ func (f *F) Fuzz(ff interface{}) { level: f.level + 1, creator: pc[:n], chatty: f.chatty, - fuzzing: true, }, context: f.testContext, } @@ -615,6 +621,7 @@ func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ok bool) { } m := newMatcher(deps.MatchString, *matchFuzz, "-test.fuzz") tctx := newTestContext(1, m) + tctx.isFuzzing = true fctx := &fuzzContext{ deps: deps, } diff --git a/src/testing/match.go b/src/testing/match.go index d97e415765..c6ff429fe4 100644 --- a/src/testing/match.go +++ b/src/testing/match.go @@ -82,6 +82,17 @@ func (m *matcher) fullName(c *common, subname string) (name string, ok, partial return name, ok, partial } +// clearSubNames clears the matcher's internal state, potentially freeing +// memory. After this is called, T.Name may return the same strings as it did +// for earlier subtests. +func (m *matcher) clearSubNames() { + m.mu.Lock() + defer m.mu.Unlock() + for key := range m.subNames { + delete(m.subNames, key) + } +} + func (m simpleMatch) matches(name []string, matchString func(pat, str string) (bool, error)) (ok, partial bool) { for i, s := range name { if i >= len(m) { diff --git a/src/testing/testing.go b/src/testing/testing.go index b3f4b4da58..57ac580051 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -495,7 +495,6 @@ type common struct { chatty *chattyPrinter // A copy of chattyPrinter, if the chatty flag is set. bench bool // Whether the current test is a benchmark. - fuzzing bool // Whether the current test is a fuzzing target. hasSub int32 // Written atomically. raceErrors int // Number of races detected during test. runner string // Function name of tRunner running the test. @@ -697,17 +696,6 @@ func (c *common) flushToParent(testName, format string, args ...interface{}) { } } -// isFuzzing returns whether the current context, or any of the parent contexts, -// are a fuzzing target -func (c *common) isFuzzing() bool { - for com := c; com != nil; com = com.parent { - if com.fuzzing { - return true - } - } - return false -} - type indenter struct { c *common } @@ -1291,7 +1279,7 @@ func tRunner(t *T, fn func(t *T)) { } } - if err != nil && t.isFuzzing() { + if err != nil && t.context.isFuzzing { prefix := "panic: " if err == errNilPanicOrGoexit { prefix = "" @@ -1457,6 +1445,12 @@ type testContext struct { match *matcher deadline time.Time + // isFuzzing is true in the context used when generating random inputs + // for fuzz targets. isFuzzing is false when running normal tests and + // when running fuzz tests as unit tests (without -fuzz or when -fuzz + // does not match). + isFuzzing bool + mu sync.Mutex // Channel used to signal tests that are ready to be run in parallel. -- GitLab From ac6d706a058de56e5817ea820df4ed59492adbdf Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 10 Aug 2021 14:51:57 -0700 Subject: [PATCH 1569/2500] [dev.typeparams] cmd/compile: add test for number of instantiations Add a test for a generic sort function, operating on several different pointer types (across two packages), so they should all share the same shape-based instantiation. Actually check that only one instantiation of Sort is created using 'go tool nm', and also check that the output is correct. In order to do the test on the executable using 'go nm', added this as a 'go test' in cmd/compile/internal/test. Added the genembed.go test that I meant to include with a previous CL. Change-Id: I9962913c2f1809484c2b1dfef3b07e4c8770731c Reviewed-on: https://go-review.googlesource.com/c/go/+/354696 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/test/inst_test.go | 71 +++++++++++++++++++ .../internal/test/testdata/mysort/mysort.go | 40 +++++++++++ .../compile/internal/test/testdata/ptrsort.go | 30 ++++++++ .../internal/test/testdata/ptrsort.out | 3 + test/typeparam/genembed.go | 52 ++++++++++++++ 5 files changed, 196 insertions(+) create mode 100644 src/cmd/compile/internal/test/inst_test.go create mode 100644 src/cmd/compile/internal/test/testdata/mysort/mysort.go create mode 100644 src/cmd/compile/internal/test/testdata/ptrsort.go create mode 100644 src/cmd/compile/internal/test/testdata/ptrsort.out create mode 100644 test/typeparam/genembed.go diff --git a/src/cmd/compile/internal/test/inst_test.go b/src/cmd/compile/internal/test/inst_test.go new file mode 100644 index 0000000000..59a67cb545 --- /dev/null +++ b/src/cmd/compile/internal/test/inst_test.go @@ -0,0 +1,71 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package test + +import ( + "internal/goexperiment" + "internal/testenv" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "regexp" + "testing" +) + +// TestInst tests that only one instantiation of Sort is created, even though generic +// Sort is used for multiple pointer types across two packages. +func TestInst(t *testing.T) { + if goexperiment.Unified { + t.Skip("unified currently does stenciling, not dictionaries") + } + testenv.MustHaveGoBuild(t) + testenv.MustHaveGoRun(t) + + var tmpdir string + var err error + tmpdir, err = ioutil.TempDir("", "TestDict") + if err != nil { + t.Fatalf("Failed to create temporary directory: %v", err) + } + defer os.RemoveAll(tmpdir) + + // Build ptrsort.go, which uses package mysort. + var output []byte + filename := "ptrsort.go" + exename := "ptrsort" + outname := "ptrsort.out" + gotool := testenv.GoToolPath(t) + dest := filepath.Join(tmpdir, exename) + cmd := exec.Command(gotool, "build", "-o", dest, filepath.Join("testdata", filename)) + if output, err = cmd.CombinedOutput(); err != nil { + t.Fatalf("Failed: %v:\nOutput: %s\n", err, output) + } + + // Test that there is exactly one shape-based instantiation of Sort in + // the executable. + cmd = exec.Command(gotool, "tool", "nm", dest) + if output, err = cmd.CombinedOutput(); err != nil { + t.Fatalf("Failed: %v:\nOut: %s\n", err, output) + } + re := regexp.MustCompile(`\bSort\[.*shape.*\]`) + r := re.FindAllIndex(output, -1) + if len(r) != 1 { + t.Fatalf("Wanted 1 instantiations of Sort function, got %d\n", len(r)) + } + + // Actually run the test and make sure output is correct. + cmd = exec.Command(gotool, "run", filepath.Join("testdata", filename)) + if output, err = cmd.CombinedOutput(); err != nil { + t.Fatalf("Failed: %v:\nOut: %s\n", err, output) + } + out, err := ioutil.ReadFile(filepath.Join("testdata", outname)) + if err != nil { + t.Fatalf("Could not find %s\n", outname) + } + if string(out) != string(output) { + t.Fatalf("Wanted output %v, got %v\n", string(out), string(output)) + } +} diff --git a/src/cmd/compile/internal/test/testdata/mysort/mysort.go b/src/cmd/compile/internal/test/testdata/mysort/mysort.go new file mode 100644 index 0000000000..14852c868a --- /dev/null +++ b/src/cmd/compile/internal/test/testdata/mysort/mysort.go @@ -0,0 +1,40 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Generic sort function, tested with two different pointer types. + +package mysort + +import ( + "fmt" +) + +type LessConstraint[T any] interface { + Less(T) bool +} + +//go:noinline +func Sort[T LessConstraint[T]](x []T) { + n := len(x) + for i := 1; i < n; i++ { + for j := i; j > 0 && x[j].Less(x[j-1]); j-- { + x[j], x[j-1] = x[j-1], x[j] + } + } +} + +type MyInt struct { + Value int +} + +func (a *MyInt) Less(b *MyInt) bool { + return a.Value < b.Value +} + +//go:noinline +func F() { + sl1 := []*MyInt{&MyInt{4}, &MyInt{3}, &MyInt{8}, &MyInt{7}} + Sort(sl1) + fmt.Printf("%v %v %v %v\n", sl1[0], sl1[1], sl1[2], sl1[3]) +} diff --git a/src/cmd/compile/internal/test/testdata/ptrsort.go b/src/cmd/compile/internal/test/testdata/ptrsort.go new file mode 100644 index 0000000000..6cc7ba4851 --- /dev/null +++ b/src/cmd/compile/internal/test/testdata/ptrsort.go @@ -0,0 +1,30 @@ +package main + +// Test generic sort function with two different pointer types in different packages, +// make sure only one instantiation is created. + +import ( + "fmt" + + "./mysort" +) + +type MyString struct { + string +} + +func (a *MyString) Less(b *MyString) bool { + return a.string < b.string +} + +func main() { + mysort.F() + + sl1 := []*mysort.MyInt{{7}, {1}, {4}, {6}} + mysort.Sort(sl1) + fmt.Printf("%v %v %v %v\n", sl1[0], sl1[1], sl1[2], sl1[3]) + + sl2 := []*MyString{{"when"}, {"in"}, {"the"}, {"course"}, {"of"}} + mysort.Sort(sl2) + fmt.Printf("%v %v %v %v %v\n", sl2[0], sl2[1], sl2[2], sl2[3], sl2[4]) +} diff --git a/src/cmd/compile/internal/test/testdata/ptrsort.out b/src/cmd/compile/internal/test/testdata/ptrsort.out new file mode 100644 index 0000000000..41f1621d1a --- /dev/null +++ b/src/cmd/compile/internal/test/testdata/ptrsort.out @@ -0,0 +1,3 @@ +&{3} &{4} &{7} &{8} +&{1} &{4} &{6} &{7} +&{course} &{in} &{of} &{the} &{when} diff --git a/test/typeparam/genembed.go b/test/typeparam/genembed.go new file mode 100644 index 0000000000..43ab3d6f4c --- /dev/null +++ b/test/typeparam/genembed.go @@ -0,0 +1,52 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test wrappers/interfaces for generic type embedding another generic type. + +package main + +import "fmt" + +type A[T any] struct { + B[T] +} + +type B[T any] struct { + val T +} + +func (b *B[T]) get() T { + return b.val +} + +type getter[T any] interface { + get() T +} + +//go:noinline +func doGet[T any](i getter[T]) T { + return i.get() +} + +//go:noline +func doGet2[T any](i interface{}) T { + i2 := i.(getter[T]) + return i2.get() +} + +func main() { + a := A[int]{B: B[int]{3}} + var i getter[int] = &a + + if got, want := doGet(i), 3; got != want { + panic(fmt.Sprintf("got %v, want %v", got, want)) + } + + as := A[string]{B: B[string]{"abc"}} + if got, want := doGet2[string](&as), "abc"; got != want { + panic(fmt.Sprintf("got %v, want %v", got, want)) + } +} -- GitLab From 3d051ba8d40a8c2e2b02c0a96cf0c47b1a9c469b Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Tue, 17 Mar 2020 21:29:54 -0400 Subject: [PATCH 1570/2500] cmd/dist: run a checkNotStale on the builders before running tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should be a no-op, but if the sharded builders are for some reason distributing stale snapshots — or testing them with mismatched environments — this should catch them out at a relatively low cost (#24300 notwithstanding). Given the frequently at which (*tester).runPending already checks for staleness, we do not expect the impact of this extra check to be significant for most builders. For #33598 Updates #24300 Change-Id: I197d6a69c72e2eec9e4563b459206de76c89e8a1 Reviewed-on: https://go-review.googlesource.com/c/go/+/223755 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Dmitri Shuralyov --- src/cmd/dist/test.go | 50 +++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index de9135c3c4..5935011e19 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -139,27 +139,35 @@ func (t *tester) run() { goInstall("go", append([]string{"-a", "-i"}, toolchain...)...) } - // Complete rebuild bootstrap, even with -no-rebuild. - // If everything is up-to-date, this is a no-op. - // If everything is not up-to-date, the first checkNotStale - // during the test process will kill the tests, so we might - // as well install the world. - // Now that for example "go install cmd/compile" does not - // also install runtime (you need "go install -i cmd/compile" - // for that), it's easy for previous workflows like - // "rebuild the compiler and then run run.bash" - // to break if we don't automatically refresh things here. - // Rebuilding is a shortened bootstrap. - // See cmdbootstrap for a description of the overall process. - // - // But don't do this if we're running in the Go build system, - // where cmd/dist is invoked many times. This just slows that - // down (Issue 24300). - if !t.listMode && os.Getenv("GO_BUILDER_NAME") == "" { - goInstall("go", append([]string{"-i"}, toolchain...)...) - goInstall("go", append([]string{"-i"}, toolchain...)...) - goInstall("go", "std", "cmd") - checkNotStale("go", "std", "cmd") + if !t.listMode { + if os.Getenv("GO_BUILDER_NAME") == "" { + // Complete rebuild bootstrap, even with -no-rebuild. + // If everything is up-to-date, this is a no-op. + // If everything is not up-to-date, the first checkNotStale + // during the test process will kill the tests, so we might + // as well install the world. + // Now that for example "go install cmd/compile" does not + // also install runtime (you need "go install -i cmd/compile" + // for that), it's easy for previous workflows like + // "rebuild the compiler and then run run.bash" + // to break if we don't automatically refresh things here. + // Rebuilding is a shortened bootstrap. + // See cmdbootstrap for a description of the overall process. + goInstall("go", append([]string{"-i"}, toolchain...)...) + goInstall("go", append([]string{"-i"}, toolchain...)...) + goInstall("go", "std", "cmd") + } else { + // The Go builder infrastructure should always begin running tests from a + // clean, non-stale state, so there is no need to rebuild the world. + // Instead, we can just check that it is not stale, which may be less + // expensive (and is also more likely to catch bugs in the builder + // implementation). + willTest := []string{"std"} + if t.shouldTestCmd() { + willTest = append(willTest, "cmd") + } + checkNotStale("go", willTest...) + } } t.timeoutScale = 1 -- GitLab From 61890fb1237a3d2c3be809f66dd3f831cd2cc3d2 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Tue, 12 Oct 2021 16:45:40 -0400 Subject: [PATCH 1571/2500] internal/fuzz: fix -fuzzminimizetime with 'x' bug Fixes #48928 Change-Id: I3825ec615ab5fc19389ef4c10ad1042005a3761c Reviewed-on: https://go-review.googlesource.com/c/go/+/355450 Trust: Katie Hockman Run-TryBot: Katie Hockman Reviewed-by: Jay Conrod TryBot-Result: Go Bot --- .../go/testdata/script/test_fuzz_fuzztime.txt | 57 ++++++++++++++++--- src/internal/fuzz/fuzz.go | 8 ++- 2 files changed, 54 insertions(+), 11 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt index 7d644b4d13..9c9972f9e9 100644 --- a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt +++ b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt @@ -16,13 +16,24 @@ exec ./fuzz.test$GOEXE -test.timeout=10ms -test.fuzz=FuzzFast -test.fuzztime=5s # Timeout should not cause inputs to be written as crashers. ! exists testdata/fuzz +env GOCACHE=$WORK/tmp + # When we use fuzztime with an "x" suffix, it runs a specific number of times. -# This fuzz function creates a file with a unique name ($pid.$count) on each run. -# We count the files to find the number of runs. +# This fuzz function creates a file with a unique name ($pid.$count) on each +# run. We count the files to find the number of runs. mkdir count -env GOCACHE=$WORK/tmp -go test -fuzz=FuzzCount -fuzztime=1000x -fuzzminimizetime=1x -go run check_file_count.go 1000 +go test -fuzz=FuzzTestCount -fuzztime=1000x -fuzzminimizetime=1x +go run check_file_count.go count 1000 + +# When we use fuzzminimizetime with an "x" suffix, it runs a specific number of +# times while minimizing. This fuzz function creates a file with a unique name +# ($pid.$count) on each run once the first crash has been found. That means that +# there should be one file for each execution of the fuzz function during +# minimization, so we count these to determine how many times minimization was +# run. +mkdir minimizecount +! go test -fuzz=FuzzMinimizeCount -fuzzminimizetime=3x -parallel=1 +go run check_file_count.go minimizecount 3 -- go.mod -- module fuzz @@ -45,7 +56,7 @@ import ( "testing" ) -func FuzzCount(f *testing.F) { +func FuzzTestCount(f *testing.F) { pid := os.Getpid() n := 0 f.Fuzz(func(t *testing.T, _ []byte) { @@ -56,6 +67,36 @@ func FuzzCount(f *testing.F) { n++ }) } +-- fuzz_minimize_count_test.go -- +package fuzz + +import ( + "bytes" + "fmt" + "os" + "testing" +) + +func FuzzMinimizeCount(f *testing.F) { + pid := os.Getpid() + n := 0 + seed := bytes.Repeat([]byte("a"), 357) + f.Add(seed) + crashFound := false + f.Fuzz(func(t *testing.T, b []byte) { + if crashFound { + name := fmt.Sprintf("minimizecount/%v.%d", pid, n) + if err := os.WriteFile(name, nil, 0666); err != nil { + t.Fatal(err) + } + n++ + } + if !bytes.Equal(b, seed) { // this should happen right away + crashFound = true + t.Error("minimize this!") + } + }) +} -- check_file_count.go -- // +build ignore @@ -68,13 +109,13 @@ import ( ) func main() { - dir, err := os.ReadDir("count") + dir, err := os.ReadDir(os.Args[1]) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } got := len(dir) - want, _ := strconv.Atoi(os.Args[1]) + want, _ := strconv.Atoi(os.Args[2]) if got != want { fmt.Fprintf(os.Stderr, "got %d files; want %d\n", got, want) os.Exit(1) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index a8bbd60b1c..03071d5521 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -825,9 +825,11 @@ func (c *coordinator) peekMinimizeInput() (fuzzMinimizeInput, bool) { } } } - remaining := c.opts.Limit - c.count - c.countWaiting - if input.limit > remaining { - input.limit = remaining + if c.opts.Limit > 0 { + remaining := c.opts.Limit - c.count - c.countWaiting + if input.limit > remaining { + input.limit = remaining + } } return input, true } -- GitLab From 3283d1a2f29496d882b6edc57543446967dc8233 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 12 Oct 2021 16:00:23 -0400 Subject: [PATCH 1572/2500] os: Simplify size using io.Discard. Change-Id: Ib7cc86643a3dcae788a94472e54de171e0d655fc Reviewed-on: https://go-review.googlesource.com/c/go/+/355449 Trust: Michael Pratt Trust: Keith Randall Run-TryBot: Michael Pratt TryBot-Result: Go Bot Reviewed-by: Michael Pratt --- src/os/os_test.go | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/os/os_test.go b/src/os/os_test.go index 62173d9bf4..717330e86a 100644 --- a/src/os/os_test.go +++ b/src/os/os_test.go @@ -115,20 +115,16 @@ func size(name string, t *testing.T) int64 { if err != nil { t.Fatal("open failed:", err) } - defer file.Close() - var buf [100]byte - len := 0 - for { - n, e := file.Read(buf[0:]) - len += n - if e == io.EOF { - break - } - if e != nil { - t.Fatal("read failed:", e) + defer func() { + if err := file.Close(); err != nil { + t.Error(err) } + }() + n, err := io.Copy(io.Discard, file) + if err != nil { + t.Fatal(err) } - return int64(len) + return n } func equal(name1, name2 string) (r bool) { -- GitLab From 732f6fa9d552c643b6225dd56689eb653ad61473 Mon Sep 17 00:00:00 2001 From: Jake Ciolek Date: Sun, 10 Oct 2021 17:56:16 +0200 Subject: [PATCH 1573/2500] cmd/compile: use ANDL for small immediates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can rewrite ANDQ with an immediate fitting in 32bit with an ANDL, which is shorter to encode. Looking at Go binary itself, before the change there was: ANDL: 2337 ANDQ: 4476 After the change: ANDL: 3790 ANDQ: 3024 So we got rid of 1452 ANDQs This makes the Linux x86_64 binary 0.03% smaller. There seems to be an impact on performance. Intel Cascade Lake benchmarks (with perflock): name old time/op new time/op delta BinaryTree17-8 1.91s ± 1% 1.89s ± 1% -1.22% (p=0.000 n=21+18) Fannkuch11-8 2.34s ± 0% 2.34s ± 0% ~ (p=0.052 n=20+20) FmtFprintfEmpty-8 27.7ns ± 1% 27.4ns ± 3% ~ (p=0.497 n=21+21) FmtFprintfString-8 53.2ns ± 0% 51.5ns ± 0% -3.21% (p=0.000 n=20+19) FmtFprintfInt-8 57.3ns ± 0% 55.7ns ± 0% -2.89% (p=0.000 n=19+19) FmtFprintfIntInt-8 92.3ns ± 0% 88.4ns ± 1% -4.23% (p=0.000 n=20+21) FmtFprintfPrefixedInt-8 103ns ± 0% 103ns ± 0% +0.23% (p=0.000 n=20+21) FmtFprintfFloat-8 147ns ± 0% 148ns ± 0% +0.75% (p=0.000 n=20+21) FmtManyArgs-8 384ns ± 0% 381ns ± 0% -0.63% (p=0.000 n=21+21) GobDecode-8 3.86ms ± 1% 3.88ms ± 1% +0.52% (p=0.000 n=20+21) GobEncode-8 2.77ms ± 1% 2.77ms ± 0% ~ (p=0.078 n=21+21) Gzip-8 168ms ± 1% 168ms ± 0% +0.24% (p=0.000 n=20+20) Gunzip-8 25.1ms ± 0% 24.3ms ± 0% -3.03% (p=0.000 n=21+21) HTTPClientServer-8 61.4µs ± 8% 59.1µs ±10% ~ (p=0.088 n=20+21) JSONEncode-8 6.86ms ± 0% 6.70ms ± 0% -2.29% (p=0.000 n=20+19) JSONDecode-8 30.8ms ± 1% 30.6ms ± 1% -0.82% (p=0.000 n=20+20) Mandelbrot200-8 3.85ms ± 0% 3.85ms ± 0% ~ (p=0.191 n=16+17) GoParse-8 2.61ms ± 2% 2.60ms ± 1% ~ (p=0.561 n=21+20) RegexpMatchEasy0_32-8 48.5ns ± 2% 45.9ns ± 3% -5.26% (p=0.000 n=20+21) RegexpMatchEasy0_1K-8 139ns ± 0% 139ns ± 0% +0.27% (p=0.000 n=18+20) RegexpMatchEasy1_32-8 41.3ns ± 0% 42.1ns ± 4% +1.95% (p=0.000 n=17+21) RegexpMatchEasy1_1K-8 216ns ± 2% 216ns ± 0% +0.17% (p=0.020 n=21+19) RegexpMatchMedium_32-8 790ns ± 7% 803ns ± 8% ~ (p=0.178 n=21+21) RegexpMatchMedium_1K-8 23.5µs ± 5% 23.7µs ± 5% ~ (p=0.421 n=21+21) RegexpMatchHard_32-8 1.09µs ± 1% 1.09µs ± 1% -0.53% (p=0.000 n=19+18) RegexpMatchHard_1K-8 33.0µs ± 0% 33.0µs ± 0% ~ (p=0.610 n=21+20) Revcomp-8 348ms ± 0% 353ms ± 0% +1.38% (p=0.000 n=17+18) Template-8 42.0ms ± 1% 41.9ms ± 1% -0.30% (p=0.049 n=20+20) TimeParse-8 185ns ± 0% 185ns ± 0% ~ (p=0.387 n=20+18) TimeFormat-8 237ns ± 1% 241ns ± 1% +1.57% (p=0.000 n=21+21) [Geo mean] 35.4µs 35.2µs -0.66% name old speed new speed delta GobDecode-8 199MB/s ± 1% 198MB/s ± 1% -0.52% (p=0.000 n=20+21) GobEncode-8 277MB/s ± 1% 277MB/s ± 0% ~ (p=0.075 n=21+21) Gzip-8 116MB/s ± 1% 115MB/s ± 0% -0.25% (p=0.000 n=20+20) Gunzip-8 773MB/s ± 0% 797MB/s ± 0% +3.12% (p=0.000 n=21+21) JSONEncode-8 283MB/s ± 0% 290MB/s ± 0% +2.35% (p=0.000 n=20+19) JSONDecode-8 63.0MB/s ± 1% 63.5MB/s ± 1% +0.82% (p=0.000 n=20+20) GoParse-8 22.2MB/s ± 2% 22.3MB/s ± 1% ~ (p=0.539 n=21+20) RegexpMatchEasy0_32-8 660MB/s ± 2% 697MB/s ± 3% +5.57% (p=0.000 n=20+21) RegexpMatchEasy0_1K-8 7.36GB/s ± 0% 7.34GB/s ± 0% -0.26% (p=0.000 n=18+20) RegexpMatchEasy1_32-8 775MB/s ± 0% 761MB/s ± 4% -1.88% (p=0.000 n=17+21) RegexpMatchEasy1_1K-8 4.74GB/s ± 2% 4.74GB/s ± 0% -0.18% (p=0.020 n=21+19) RegexpMatchMedium_32-8 40.6MB/s ± 7% 39.9MB/s ± 9% ~ (p=0.191 n=21+21) RegexpMatchMedium_1K-8 43.7MB/s ± 5% 43.2MB/s ± 5% ~ (p=0.435 n=21+21) RegexpMatchHard_32-8 29.3MB/s ± 1% 29.4MB/s ± 1% +0.53% (p=0.000 n=19+18) RegexpMatchHard_1K-8 31.0MB/s ± 0% 31.0MB/s ± 0% ~ (p=0.572 n=21+20) Revcomp-8 730MB/s ± 0% 720MB/s ± 0% -1.36% (p=0.000 n=17+18) Template-8 46.2MB/s ± 1% 46.3MB/s ± 1% +0.30% (p=0.041 n=20+20) [Geo mean] 204MB/s 205MB/s +0.30% Change-Id: Iac75d0ec184a515ce0e65e19559d5fe2e9840514 Reviewed-on: https://go-review.googlesource.com/c/go/+/354970 Reviewed-by: Josh Bleecher Snyder Trust: Josh Bleecher Snyder Trust: Keith Randall Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot --- src/cmd/compile/internal/amd64/ssa.go | 15 ++++++++++++++- test/codegen/arithmetic.go | 8 ++++---- test/codegen/bits.go | 2 +- test/codegen/bool.go | 2 +- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/cmd/compile/internal/amd64/ssa.go b/src/cmd/compile/internal/amd64/ssa.go index 78822098a7..0e74574422 100644 --- a/src/cmd/compile/internal/amd64/ssa.go +++ b/src/cmd/compile/internal/amd64/ssa.go @@ -618,8 +618,21 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.To.Reg = r p.SetFrom3Reg(v.Args[0].Reg()) + case ssa.OpAMD64ANDQconst: + asm := v.Op.Asm() + // If the constant is positive and fits into 32 bits, use ANDL. + // This saves a few bytes of encoding. + if 0 <= v.AuxInt && v.AuxInt <= (1<<32-1) { + asm = x86.AANDL + } + p := s.Prog(asm) + p.From.Type = obj.TYPE_CONST + p.From.Offset = v.AuxInt + p.To.Type = obj.TYPE_REG + p.To.Reg = v.Reg() + case ssa.OpAMD64SUBQconst, ssa.OpAMD64SUBLconst, - ssa.OpAMD64ANDQconst, ssa.OpAMD64ANDLconst, + ssa.OpAMD64ANDLconst, ssa.OpAMD64ORQconst, ssa.OpAMD64ORLconst, ssa.OpAMD64XORQconst, ssa.OpAMD64XORLconst, ssa.OpAMD64SHLQconst, ssa.OpAMD64SHLLconst, diff --git a/test/codegen/arithmetic.go b/test/codegen/arithmetic.go index eb95416b6a..8b8c8ed64b 100644 --- a/test/codegen/arithmetic.go +++ b/test/codegen/arithmetic.go @@ -241,7 +241,7 @@ func FloatDivs(a []float32) float32 { func Pow2Mods(n1 uint, n2 int) (uint, int) { // 386:"ANDL\t[$]31",-"DIVL" - // amd64:"ANDQ\t[$]31",-"DIVQ" + // amd64:"ANDL\t[$]31",-"DIVQ" // arm:"AND\t[$]31",-".*udiv" // arm64:"AND\t[$]31",-"UDIV" // ppc64:"ANDCC\t[$]31" @@ -452,7 +452,7 @@ func LenDiv2(s string) int { func LenMod1(a []int) int { // 386:"ANDL\t[$]1023" - // amd64:"ANDQ\t[$]1023" + // amd64:"ANDL\t[$]1023" // arm64:"AND\t[$]1023",-"SDIV" // arm/6:"AND",-".*udiv" // arm/7:"BFC",-".*udiv",-"AND" @@ -463,7 +463,7 @@ func LenMod1(a []int) int { func LenMod2(s string) int { // 386:"ANDL\t[$]2047" - // amd64:"ANDQ\t[$]2047" + // amd64:"ANDL\t[$]2047" // arm64:"AND\t[$]2047",-"SDIV" // arm/6:"AND",-".*udiv" // arm/7:"BFC",-".*udiv",-"AND" @@ -484,7 +484,7 @@ func CapDiv(a []int) int { func CapMod(a []int) int { // 386:"ANDL\t[$]4095" - // amd64:"ANDQ\t[$]4095" + // amd64:"ANDL\t[$]4095" // arm64:"AND\t[$]4095",-"SDIV" // arm/6:"AND",-".*udiv" // arm/7:"BFC",-".*udiv",-"AND" diff --git a/test/codegen/bits.go b/test/codegen/bits.go index 8e973d5726..e7826b8e65 100644 --- a/test/codegen/bits.go +++ b/test/codegen/bits.go @@ -332,7 +332,7 @@ func bitSetPowerOf2Test(x int) bool { } func bitSetTest(x int) bool { - // amd64:"ANDQ\t[$]9, AX" + // amd64:"ANDL\t[$]9, AX" // amd64:"CMPQ\tAX, [$]9" return x&9 == 9 } diff --git a/test/codegen/bool.go b/test/codegen/bool.go index 929b1b49b9..a32423308e 100644 --- a/test/codegen/bool.go +++ b/test/codegen/bool.go @@ -27,7 +27,7 @@ func convertNeq0L(x uint32, c bool) bool { } func convertNeq0Q(x uint64, c bool) bool { - // amd64:"ANDQ\t[$]1",-"SETB" + // amd64:"ANDL\t[$]1",-"SETB" b := x&1 != 0 return c && b } -- GitLab From 78d01be00b68d1f5c3f5eb493f053ba97adc92df Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 12 Oct 2021 11:54:09 -0400 Subject: [PATCH 1574/2500] cmd/api: use placeholder names for type parameters Changing type parameter names is not a breaking API change, so we should not include these names in the output of cmd/api. Instead print a placeholder '$' wherever type parameters are referenced. This is valid for cmd/api as there is at most one type parameter list in scope for any exported declaration. If we ever support method type parameters, we'll need to revisit this syntax. Change-Id: I7e677b1dab6ffeb0b79afefdb8d2580bef93891c Reviewed-on: https://go-review.googlesource.com/c/go/+/355389 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/api/goapi.go | 5 +++-- src/cmd/api/testdata/src/pkg/p4/golden.txt | 9 +++++---- src/cmd/api/testdata/src/pkg/p4/p4.go | 4 ++++ 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go index eca113a638..0c61b1b489 100644 --- a/src/cmd/api/goapi.go +++ b/src/cmd/api/goapi.go @@ -838,7 +838,8 @@ func (w *Walker) writeType(buf *bytes.Buffer, typ types.Type) { buf.WriteString(typ.Obj().Name()) case *types.TypeParam: - buf.WriteString(typ.Obj().Name()) + // Type parameter names may change, so use a placeholder instead. + fmt.Fprintf(buf, "$%d", typ.Index()) default: panic(fmt.Sprintf("unknown type %T", typ)) @@ -870,7 +871,7 @@ func (w *Walker) writeTypeParams(buf *bytes.Buffer, tparams *types.TypeParamList buf.WriteString(", ") } tp := tparams.At(i) - buf.WriteString(tp.Obj().Name()) + w.writeType(buf, tp) if withConstraints { buf.WriteByte(' ') w.writeType(buf, tp.Constraint()) diff --git a/src/cmd/api/testdata/src/pkg/p4/golden.txt b/src/cmd/api/testdata/src/pkg/p4/golden.txt index d5f282be8e..7997ab4471 100644 --- a/src/cmd/api/testdata/src/pkg/p4/golden.txt +++ b/src/cmd/api/testdata/src/pkg/p4/golden.txt @@ -1,4 +1,5 @@ -pkg p4, func NewPair[T1 interface{ M }, T2 interface{ ~int }](T1, T2) Pair -pkg p4, method (Pair[_, X2]) Second() X2 -pkg p4, method (Pair[X1, _]) First() X1 -pkg p4, type Pair[T1 interface{ M }, T2 interface{ ~int }] struct +pkg p4, func NewPair[$0 interface{ M }, $1 interface{ ~int }]($0, $1) Pair +pkg p4, method (Pair[$0, $1]) Second() $1 +pkg p4, method (Pair[$0, $1]) First() $0 +pkg p4, type Pair[$0 interface{ M }, $1 interface{ ~int }] struct +pkg p4, func Clone[$0 interface{ ~[]$1 }, $1 interface{}]($0) $0 diff --git a/src/cmd/api/testdata/src/pkg/p4/p4.go b/src/cmd/api/testdata/src/pkg/p4/p4.go index 187339b169..462a75be1a 100644 --- a/src/cmd/api/testdata/src/pkg/p4/p4.go +++ b/src/cmd/api/testdata/src/pkg/p4/p4.go @@ -20,3 +20,7 @@ func (p Pair[X1, _]) First() X1 { func (p Pair[_, X2]) Second() X2 { return p.f2 } + +func Clone[S ~[]T, T any](s S) S { + return append(S(nil), s...) +} -- GitLab From 4fb2e1cb86a1f15a69ebf97a80503e865287642c Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 12 Oct 2021 12:52:59 -0700 Subject: [PATCH 1575/2500] cmd/compile: allow spaces in types.(*Type).LinkString() Go back to allowing spaces in types.(*Type).LinkSring(). Delve folks prefer that there are spaces in type names, if needed, since DWARF expects type names to be "a string representing the name as it appears in the source program". At this point, it doesn't necessarily seem worth having a separate function that removes spaces, only for use when printing the type names in a function/method instantiation. Most names of function/method instantiations will still not have spaces, since they most type args are named or builtin types. I confirmed that we are back to the original definition of LinkString(), except for some comment changes. Change-Id: Iab7143f659ddea4f099c6230cb134edf8aaef868 Reviewed-on: https://go-review.googlesource.com/c/go/+/355354 Run-TryBot: Dan Scales TryBot-Result: Go Bot Trust: Dan Scales Reviewed-by: Keith Randall --- src/cmd/compile/internal/types/fmt.go | 45 ++++++--------------------- 1 file changed, 9 insertions(+), 36 deletions(-) diff --git a/src/cmd/compile/internal/types/fmt.go b/src/cmd/compile/internal/types/fmt.go index c70e22c946..23fc4221e1 100644 --- a/src/cmd/compile/internal/types/fmt.go +++ b/src/cmd/compile/internal/types/fmt.go @@ -461,25 +461,15 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type case TINTER: if t.IsEmptyInterface() { - if mode == fmtTypeID { - b.WriteString("interface{}") - } else { - b.WriteString("interface {}") - } + b.WriteString("interface {}") break } - if mode == fmtTypeID { - b.WriteString("interface{") - } else { - b.WriteString("interface {") - } + b.WriteString("interface {") for i, f := range t.AllMethods().Slice() { if i != 0 { b.WriteByte(';') } - if mode != fmtTypeID { - b.WriteByte(' ') - } + b.WriteByte(' ') switch { case f.Sym == nil: // Check first that a symbol is defined for this type. @@ -495,7 +485,7 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type } tconv2(b, f.Type, 'S', mode, visited) } - if t.AllMethods().Len() != 0 && mode != fmtTypeID { + if t.AllMethods().Len() != 0 { b.WriteByte(' ') } b.WriteByte('}') @@ -570,21 +560,15 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type } b.WriteByte(byte(close)) } else { - if mode == fmtTypeID { - b.WriteString("struct{") - } else { - b.WriteString("struct {") - } + b.WriteString("struct {") for i, f := range t.Fields().Slice() { if i != 0 { b.WriteByte(';') } - if mode != fmtTypeID { - b.WriteByte(' ') - } + b.WriteByte(' ') fldconv(b, f, 'L', mode, visited, funarg) } - if t.NumFields() != 0 && mode != fmtTypeID { + if t.NumFields() != 0 { b.WriteByte(' ') } b.WriteByte('}') @@ -668,14 +652,7 @@ func fldconv(b *bytes.Buffer, f *Field, verb rune, mode fmtMode, visited map[*Ty if name != "" { b.WriteString(name) - if mode == fmtTypeID { - // This is the one case where we can't omit the space, since - // we need a separate between field name and type, so we use - // "#" instead. - b.WriteString("#") - } else { - b.WriteString(" ") - } + b.WriteString(" ") } if f.IsDDD() { @@ -690,11 +667,7 @@ func fldconv(b *bytes.Buffer, f *Field, verb rune, mode fmtMode, visited map[*Ty } if verb != 'S' && funarg == FunargNone && f.Note != "" { - if mode != fmtTypeID { - b.WriteString(" ") - } - // TODO: for fmtTypeID, we should possibly using %-quoting, so - // space is %20, etc. + b.WriteString(" ") b.WriteString(strconv.Quote(f.Note)) } } -- GitLab From e8f99da8ed6180732ace00f8fc6b17f636515bc4 Mon Sep 17 00:00:00 2001 From: nicksherron Date: Wed, 13 Oct 2021 01:39:13 +0000 Subject: [PATCH 1576/2500] all: fix spelling mistakes Corrections were only made to comments and can be reproduced with the following sed. sed -i 's/communciation/communication/g' src/internal/fuzz/sys_windows.go sed -i 's/communciation/communication/g' src/internal/fuzz/sys_posix.go sed -i 's/substitued/substituted/g' src/cmd/compile/internal/noder/irgen.go Change-Id: I435aee2fdb41e73b694e6233d52742559d32cf7e GitHub-Last-Rev: a471e3d123aa6c8bb9b091e65de5d16609fb8db1 GitHub-Pull-Request: golang/go#48932 Reviewed-on: https://go-review.googlesource.com/c/go/+/355494 Reviewed-by: Robert Griesemer Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot --- src/cmd/compile/internal/noder/irgen.go | 2 +- src/internal/fuzz/sys_posix.go | 2 +- src/internal/fuzz/sys_windows.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index 645ac2c214..e912f797b2 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -115,7 +115,7 @@ type dictInfo struct { itabConvs []ir.Node // Mapping from each shape type that substitutes a type param, to its - // type bound (which is also substitued with shapes if it is parameterized) + // type bound (which is also substituted with shapes if it is parameterized) shapeToBound map[*types.Type]*types.Type // For type switches on nonempty interfaces, a map from OTYPE entries of diff --git a/src/internal/fuzz/sys_posix.go b/src/internal/fuzz/sys_posix.go index 2473274ecf..ca6b1456e2 100644 --- a/src/internal/fuzz/sys_posix.go +++ b/src/internal/fuzz/sys_posix.go @@ -48,7 +48,7 @@ func (m *sharedMem) Close() error { return nil } -// setWorkerComm configures communciation channels on the cmd that will +// setWorkerComm configures communication channels on the cmd that will // run a worker process. func setWorkerComm(cmd *exec.Cmd, comm workerComm) { mem := <-comm.memMu diff --git a/src/internal/fuzz/sys_windows.go b/src/internal/fuzz/sys_windows.go index fabf954ba7..9c006b010e 100644 --- a/src/internal/fuzz/sys_windows.go +++ b/src/internal/fuzz/sys_windows.go @@ -86,7 +86,7 @@ func (m *sharedMem) Close() error { return nil } -// setWorkerComm configures communciation channels on the cmd that will +// setWorkerComm configures communication channels on the cmd that will // run a worker process. func setWorkerComm(cmd *exec.Cmd, comm workerComm) { mem := <-comm.memMu -- GitLab From 0454d7346f4ca89261356d3f17da11ab5bc643c5 Mon Sep 17 00:00:00 2001 From: helbing Date: Tue, 12 Oct 2021 23:33:50 +0000 Subject: [PATCH 1577/2500] embed: add example Change-Id: I4e50e469047ac7efbf4ed464e238000dbdf53d6b GitHub-Last-Rev: 8d29b73d1160b4498a38aa3ef6530ee5c9353186 GitHub-Pull-Request: golang/go#48785 Reviewed-on: https://go-review.googlesource.com/c/go/+/353936 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Alexander Rakoczy --- src/embed/example_test.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/embed/example_test.go diff --git a/src/embed/example_test.go b/src/embed/example_test.go new file mode 100644 index 0000000000..5498c275fd --- /dev/null +++ b/src/embed/example_test.go @@ -0,0 +1,23 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package embed_test + +import ( + "embed" + "log" + "net/http" +) + +//go:embed internal/embedtest/testdata/*.txt +var content embed.FS + +func Example() { + mutex := http.NewServeMux() + mutex.Handle("/", http.FileServer(http.FS(content))) + err := http.ListenAndServe(":8080", mutex) + if err != nil { + log.Fatal(err) + } +} -- GitLab From f687831e4cfa06d19533d47ae93c0451bd1ca688 Mon Sep 17 00:00:00 2001 From: zhouguangyuan Date: Thu, 16 Sep 2021 02:10:17 +0800 Subject: [PATCH 1578/2500] cmd/link: disable weak reference in itab if build with "-linkshared" When build with "-linkshared", we can't tell if the interface method will be used or not. It can be used in shared library. Fixes #47873 Change-Id: Iba12812f199b7679cf2fd41a304268d6d6dd03c6 Reviewed-on: https://go-review.googlesource.com/c/go/+/350189 Reviewed-by: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Trust: Alexander Rakoczy --- misc/cgo/testshared/shared_test.go | 8 ++++++++ .../cgo/testshared/testdata/issue47837/a/a.go | 19 +++++++++++++++++++ .../testdata/issue47837/main/main.go | 14 ++++++++++++++ src/cmd/link/internal/ld/deadcode.go | 4 +++- 4 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 misc/cgo/testshared/testdata/issue47837/a/a.go create mode 100644 misc/cgo/testshared/testdata/issue47837/main/main.go diff --git a/misc/cgo/testshared/shared_test.go b/misc/cgo/testshared/shared_test.go index 1bd89bc27a..672811fe0e 100644 --- a/misc/cgo/testshared/shared_test.go +++ b/misc/cgo/testshared/shared_test.go @@ -1070,3 +1070,11 @@ func TestIssue44031(t *testing.T) { goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue44031/b") goCmd(t, "run", "-linkshared", "./issue44031/main") } + +// Test that we use a variable from shared libraries (which implement an +// interface in shared libraries.). A weak reference is used in the itab +// in main process. It can cause unreacheble panic. See issue 47873. +func TestIssue47873(t *testing.T) { + goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue47837/a") + goCmd(t, "run", "-linkshared", "./issue47837/main") +} diff --git a/misc/cgo/testshared/testdata/issue47837/a/a.go b/misc/cgo/testshared/testdata/issue47837/a/a.go new file mode 100644 index 0000000000..68588eda2f --- /dev/null +++ b/misc/cgo/testshared/testdata/issue47837/a/a.go @@ -0,0 +1,19 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type A interface { + M() +} + +//go:noinline +func TheFuncWithArgA(a A) { + a.M() +} + +type ImplA struct{} + +//go:noinline +func (A *ImplA) M() {} diff --git a/misc/cgo/testshared/testdata/issue47837/main/main.go b/misc/cgo/testshared/testdata/issue47837/main/main.go new file mode 100644 index 0000000000..77c6f34379 --- /dev/null +++ b/misc/cgo/testshared/testdata/issue47837/main/main.go @@ -0,0 +1,14 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "testshared/issue47837/a" +) + +func main() { + var vara a.ImplA + a.TheFuncWithArgA(&vara) +} diff --git a/src/cmd/link/internal/ld/deadcode.go b/src/cmd/link/internal/ld/deadcode.go index 0221024d56..79acd73387 100644 --- a/src/cmd/link/internal/ld/deadcode.go +++ b/src/cmd/link/internal/ld/deadcode.go @@ -134,7 +134,9 @@ func (d *deadcodePass) flood() { methods = methods[:0] for i := 0; i < relocs.Count(); i++ { r := relocs.At(i) - if r.Weak() { + // When build with "-linkshared", we can't tell if the interface + // method in itab will be used or not. Ignore the weak attribute. + if r.Weak() && !(d.ctxt.linkShared && d.ldr.IsItab(symIdx)) { continue } t := r.Type() -- GitLab From b8e4df01dd1aa61b3de978e4874c81b0d23349d5 Mon Sep 17 00:00:00 2001 From: Mark Hansen Date: Fri, 8 Oct 2021 03:53:09 +0000 Subject: [PATCH 1579/2500] cmd/pprof: update vendored github.com/google/pprof Pull in the latest published version of github.com/google/pprof This adds the tagroot and tagleaf options from https://github.com/google/pprof/commit/7fe48b4c820be13151ae35ce5a5e3f54f1b53eef Done with: go get -d github.com/google/pprof@latest go mod tidy go mod vendor Fixes #48839 Change-Id: I85bf0e0689310014eb198c8d5e0bb3a86b0aef1c GitHub-Last-Rev: b26260f30514eb71be76c9b2f74f9d3aace205b9 GitHub-Pull-Request: golang/go#48856 Reviewed-on: https://go-review.googlesource.com/c/go/+/354692 Run-TryBot: Dmitri Shuralyov Reviewed-by: Dmitri Shuralyov TryBot-Result: Go Bot Trust: Alexander Rakoczy --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 +- .../google/pprof/internal/driver/commands.go | 8 ++ .../google/pprof/internal/driver/config.go | 4 + .../google/pprof/internal/driver/driver.go | 23 ++++ .../google/pprof/internal/driver/tagroot.go | 124 ++++++++++++++++++ src/cmd/vendor/modules.txt | 2 +- 7 files changed, 163 insertions(+), 4 deletions(-) create mode 100644 src/cmd/vendor/github.com/google/pprof/internal/driver/tagroot.go diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 5431def67a..b2ec091292 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -3,7 +3,7 @@ module cmd go 1.18 require ( - github.com/google/pprof v0.0.0-20210827144239-02619b876842 + github.com/google/pprof v0.0.0-20211001005136-7fe48b4c820b golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1 golang.org/x/mod v0.5.1-0.20210913215816-37dd6891021a golang.org/x/sync v0.0.0-20210220032951-036812b2e83c diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 0c575bf777..ff8df7b749 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -1,8 +1,8 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/google/pprof v0.0.0-20210827144239-02619b876842 h1:JCrt5MIE1fHQtdy1825HwJ45oVQaqHE6lgssRhjcg/o= -github.com/google/pprof v0.0.0-20210827144239-02619b876842/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20211001005136-7fe48b4c820b h1:GX4+fGLMW5XTmDXB3R6UhTwZIYqgAOdA19+Ea0+3CU4= +github.com/google/pprof v0.0.0-20211001005136-7fe48b4c820b/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 h1:mV02weKRL81bEnm8A0HT1/CAelMQDBuQIfLw8n+d6xI= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1 h1:MwxAfiDvuwX8Nnnc6iRDhzyMyyc2tz5tYyCP/pZcPCg= diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/commands.go b/src/cmd/vendor/github.com/google/pprof/internal/driver/commands.go index 4397e253e0..c9edf10bb4 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/driver/commands.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/commands.go @@ -189,6 +189,14 @@ var configHelp = map[string]string{ "Drops functions above the highest matched frame.", "If set, all frames above the highest match are dropped from every sample.", "Matching includes the function name, filename or object name."), + "tagroot": helpText( + "Adds pseudo stack frames for labels key/value pairs at the callstack root.", + "A comma-separated list of label keys.", + "The first key creates frames at the new root."), + "tagleaf": helpText( + "Adds pseudo stack frames for labels key/value pairs at the callstack leaf.", + "A comma-separated list of label keys.", + "The last key creates frames at the new leaf."), "tagfocus": helpText( "Restricts to samples with tags in range or matched by regexp", "Use name=value syntax to limit the matching to a specific tag.", diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/config.go b/src/cmd/vendor/github.com/google/pprof/internal/driver/config.go index b3f82f22c9..9fcdd459b2 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/driver/config.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/config.go @@ -30,6 +30,10 @@ type config struct { Normalize bool `json:"normalize,omitempty"` Sort string `json:"sort,omitempty"` + // Label pseudo stack frame generation options + TagRoot string `json:"tagroot,omitempty"` + TagLeaf string `json:"tagleaf,omitempty"` + // Filtering options DropNegative bool `json:"drop_negative,omitempty"` NodeCount int `json:"nodecount,omitempty"` diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/driver.go b/src/cmd/vendor/github.com/google/pprof/internal/driver/driver.go index 3967a12d45..6a1e64c600 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/driver/driver.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/driver.go @@ -73,6 +73,10 @@ func generateRawReport(p *profile.Profile, cmd []string, cfg config, o *plugin.O cfg = applyCommandOverrides(cmd[0], c.format, cfg) + // Create label pseudo nodes before filtering, in case the filters use + // the generated nodes. + generateTagRootsLeaves(p, cfg, o.UI) + // Delay focus after configuring report to get percentages on all samples. relative := cfg.RelativePercentages if relative { @@ -208,6 +212,25 @@ func applyCommandOverrides(cmd string, outputFormat int, cfg config) config { return cfg } +// generateTagRootsLeaves generates extra nodes from the tagroot and tagleaf options. +func generateTagRootsLeaves(prof *profile.Profile, cfg config, ui plugin.UI) { + tagRootLabelKeys := dropEmptyStrings(strings.Split(cfg.TagRoot, ",")) + tagLeafLabelKeys := dropEmptyStrings(strings.Split(cfg.TagLeaf, ",")) + rootm, leafm := addLabelNodes(prof, tagRootLabelKeys, tagLeafLabelKeys, cfg.Unit) + warnNoMatches(cfg.TagRoot == "" || rootm, "TagRoot", ui) + warnNoMatches(cfg.TagLeaf == "" || leafm, "TagLeaf", ui) +} + +// dropEmptyStrings filters a slice to only non-empty strings +func dropEmptyStrings(in []string) (out []string) { + for _, s := range in { + if s != "" { + out = append(out, s) + } + } + return +} + func aggregate(prof *profile.Profile, cfg config) error { var function, filename, linenumber, address bool inlines := !cfg.NoInlines diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/tagroot.go b/src/cmd/vendor/github.com/google/pprof/internal/driver/tagroot.go new file mode 100644 index 0000000000..c2cdfa455e --- /dev/null +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/tagroot.go @@ -0,0 +1,124 @@ +package driver + +import ( + "strings" + + "github.com/google/pprof/internal/measurement" + "github.com/google/pprof/profile" +) + +// addLabelNodes adds pseudo stack frames "label:value" to each Sample with +// labels matching the supplied keys. +// +// rootKeys adds frames at the root of the callgraph (first key becomes new root). +// leafKeys adds frames at the leaf of the callgraph (last key becomes new leaf). +// +// Returns whether there were matches found for the label keys. +func addLabelNodes(p *profile.Profile, rootKeys, leafKeys []string, outputUnit string) (rootm, leafm bool) { + // Find where to insert the new locations and functions at the end of + // their ID spaces. + var maxLocID uint64 + var maxFunctionID uint64 + for _, loc := range p.Location { + if loc.ID > maxLocID { + maxLocID = loc.ID + } + } + for _, f := range p.Function { + if f.ID > maxFunctionID { + maxFunctionID = f.ID + } + } + nextLocID := maxLocID + 1 + nextFuncID := maxFunctionID + 1 + + // Intern the new locations and functions we are generating. + type locKey struct { + functionName, fileName string + } + locs := map[locKey]*profile.Location{} + + internLoc := func(locKey locKey) *profile.Location { + loc, found := locs[locKey] + if found { + return loc + } + + function := &profile.Function{ + ID: nextFuncID, + Name: locKey.functionName, + Filename: locKey.fileName, + } + nextFuncID++ + p.Function = append(p.Function, function) + + loc = &profile.Location{ + ID: nextLocID, + Line: []profile.Line{ + { + Function: function, + }, + }, + } + nextLocID++ + p.Location = append(p.Location, loc) + locs[locKey] = loc + return loc + } + + makeLabelLocs := func(s *profile.Sample, keys []string) ([]*profile.Location, bool) { + var locs []*profile.Location + var match bool + for i := range keys { + // Loop backwards, ensuring the first tag is closest to the root, + // and the last tag is closest to the leaves. + k := keys[len(keys)-1-i] + values := formatLabelValues(s, k, outputUnit) + if len(values) > 0 { + match = true + } + locKey := locKey{ + functionName: strings.Join(values, ","), + fileName: k, + } + loc := internLoc(locKey) + locs = append(locs, loc) + } + return locs, match + } + + for _, s := range p.Sample { + rootsToAdd, sampleMatchedRoot := makeLabelLocs(s, rootKeys) + if sampleMatchedRoot { + rootm = true + } + leavesToAdd, sampleMatchedLeaf := makeLabelLocs(s, leafKeys) + if sampleMatchedLeaf { + leafm = true + } + + var newLocs []*profile.Location + newLocs = append(newLocs, leavesToAdd...) + newLocs = append(newLocs, s.Location...) + newLocs = append(newLocs, rootsToAdd...) + s.Location = newLocs + } + return +} + +// formatLabelValues returns all the string and numeric labels in Sample, with +// the numeric labels formatted according to outputUnit. +func formatLabelValues(s *profile.Sample, k string, outputUnit string) []string { + var values []string + values = append(values, s.Label[k]...) + numLabels := s.NumLabel[k] + numUnits := s.NumUnit[k] + if len(numLabels) != len(numUnits) { + return values + } + for i, numLabel := range numLabels { + unit := numUnits[i] + values = append(values, measurement.ScaledLabel(numLabel, unit, outputUnit)) + } + return values +} diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 1e64528968..e0e116a634 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -1,4 +1,4 @@ -# github.com/google/pprof v0.0.0-20210827144239-02619b876842 +# github.com/google/pprof v0.0.0-20211001005136-7fe48b4c820b ## explicit; go 1.14 github.com/google/pprof/driver github.com/google/pprof/internal/binutils -- GitLab From 53260943eac49dde51e0ce28e50e9b4bc90661b8 Mon Sep 17 00:00:00 2001 From: Forest Johnson Date: Fri, 8 Oct 2021 19:03:35 +0000 Subject: [PATCH 1580/2500] os: explain ProccessState.Exited() SIGKILL interaction When a process is forcefully killed (for example, with SIGKILL on unix), its ProccessState.Exited() will return false. Change-Id: I8cebc8d28f2ba1b687c145f6d941647fc3a10665 GitHub-Last-Rev: 414ae1980fe61dd530c46cc2c7f4de3a5bc83ed5 GitHub-Pull-Request: golang/go#48871 Reviewed-on: https://go-review.googlesource.com/c/go/+/354698 Reviewed-by: Ian Lance Taylor Trust: Alexander Rakoczy Run-TryBot: Alexander Rakoczy TryBot-Result: Go Bot --- src/os/exec.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/os/exec.go b/src/os/exec.go index bc75d4dd66..2beac55f89 100644 --- a/src/os/exec.go +++ b/src/os/exec.go @@ -149,6 +149,8 @@ func (p *ProcessState) SystemTime() time.Duration { } // Exited reports whether the program has exited. +// On Unix systems this reports true if the program exited due to calling exit, +// but false if the program terminated due to a signal. func (p *ProcessState) Exited() bool { return p.exited() } -- GitLab From 69041c79dc2767c220519cbcb9538c39fadec59c Mon Sep 17 00:00:00 2001 From: Amelia Downs Date: Mon, 30 Aug 2021 17:05:36 -0400 Subject: [PATCH 1581/2500] net: add examples for remaining IP functions Fixes #48848 Change-Id: If85fc16ed10a26eca840ed128ab47c5f00776ddd Reviewed-on: https://go-review.googlesource.com/c/go/+/346289 Reviewed-by: Amelia Downs Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Trust: Alexander Rakoczy --- src/net/example_test.go | 206 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) diff --git a/src/net/example_test.go b/src/net/example_test.go index 72c7183c13..2c045d73a2 100644 --- a/src/net/example_test.go +++ b/src/net/example_test.go @@ -124,6 +124,176 @@ func ExampleIP_DefaultMask() { // ffffff00 } +func ExampleIP_Equal() { + ipv4DNS := net.ParseIP("8.8.8.8") + ipv4Lo := net.ParseIP("127.0.0.1") + ipv6DNS := net.ParseIP("0:0:0:0:0:FFFF:0808:0808") + + fmt.Println(ipv4DNS.Equal(ipv4DNS)) + fmt.Println(ipv4DNS.Equal(ipv4Lo)) + fmt.Println(ipv4DNS.Equal(ipv6DNS)) + + // Output: + // true + // false + // true +} + +func ExampleIP_IsGlobalUnicast() { + ipv6Global := net.ParseIP("2000::") + ipv6UniqLocal := net.ParseIP("2000::") + ipv6Multi := net.ParseIP("FF00::") + + ipv4Private := net.ParseIP("10.255.0.0") + ipv4Public := net.ParseIP("8.8.8.8") + ipv4Broadcast := net.ParseIP("255.255.255.255") + + fmt.Println(ipv6Global.IsGlobalUnicast()) + fmt.Println(ipv6UniqLocal.IsGlobalUnicast()) + fmt.Println(ipv6Multi.IsGlobalUnicast()) + + fmt.Println(ipv4Private.IsGlobalUnicast()) + fmt.Println(ipv4Public.IsGlobalUnicast()) + fmt.Println(ipv4Broadcast.IsGlobalUnicast()) + + // Output: + // true + // true + // false + // true + // true + // false +} + +func ExampleIP_IsInterfaceLocalMulticast() { + ipv6InterfaceLocalMulti := net.ParseIP("ff01::1") + ipv6Global := net.ParseIP("2000::") + ipv4 := net.ParseIP("255.0.0.0") + + fmt.Println(ipv6InterfaceLocalMulti.IsInterfaceLocalMulticast()) + fmt.Println(ipv6Global.IsInterfaceLocalMulticast()) + fmt.Println(ipv4.IsInterfaceLocalMulticast()) + + // Output: + // true + // false + // false +} + +func ExampleIP_IsLinkLocalMulticast() { + ipv6LinkLocalMulti := net.ParseIP("ff02::2") + ipv6LinkLocalUni := net.ParseIP("fe80::") + ipv4LinkLocalMulti := net.ParseIP("224.0.0.0") + ipv4LinkLocalUni := net.ParseIP("169.254.0.0") + + fmt.Println(ipv6LinkLocalMulti.IsLinkLocalMulticast()) + fmt.Println(ipv6LinkLocalUni.IsLinkLocalMulticast()) + fmt.Println(ipv4LinkLocalMulti.IsLinkLocalMulticast()) + fmt.Println(ipv4LinkLocalUni.IsLinkLocalMulticast()) + + // Output: + // true + // false + // true + // false +} + +func ExampleIP_IsLinkLocalUnicast() { + ipv6LinkLocalUni := net.ParseIP("fe80::") + ipv6Global := net.ParseIP("2000::") + ipv4LinkLocalUni := net.ParseIP("169.254.0.0") + ipv4LinkLocalMulti := net.ParseIP("224.0.0.0") + + fmt.Println(ipv6LinkLocalUni.IsLinkLocalUnicast()) + fmt.Println(ipv6Global.IsLinkLocalUnicast()) + fmt.Println(ipv4LinkLocalUni.IsLinkLocalUnicast()) + fmt.Println(ipv4LinkLocalMulti.IsLinkLocalUnicast()) + + // Output: + // true + // false + // true + // false +} + +func ExampleIP_IsLoopback() { + ipv6Lo := net.ParseIP("::1") + ipv6 := net.ParseIP("ff02::1") + ipv4Lo := net.ParseIP("127.0.0.0") + ipv4 := net.ParseIP("128.0.0.0") + + fmt.Println(ipv6Lo.IsLoopback()) + fmt.Println(ipv6.IsLoopback()) + fmt.Println(ipv4Lo.IsLoopback()) + fmt.Println(ipv4.IsLoopback()) + + // Output: + // true + // false + // true + // false +} + +func ExampleIP_IsMulticast() { + ipv6Multi := net.ParseIP("FF00::") + ipv6LinkLocalMulti := net.ParseIP("ff02::1") + ipv6Lo := net.ParseIP("::1") + ipv4Multi := net.ParseIP("239.0.0.0") + ipv4LinkLocalMulti := net.ParseIP("224.0.0.0") + ipv4Lo := net.ParseIP("127.0.0.0") + + fmt.Println(ipv6Multi.IsMulticast()) + fmt.Println(ipv6LinkLocalMulti.IsMulticast()) + fmt.Println(ipv6Lo.IsMulticast()) + fmt.Println(ipv4Multi.IsMulticast()) + fmt.Println(ipv4LinkLocalMulti.IsMulticast()) + fmt.Println(ipv4Lo.IsMulticast()) + + // Output: + // true + // true + // false + // true + // true + // false +} + +func ExampleIP_IsPrivate() { + ipv6Private := net.ParseIP("fc00::") + ipv6Public := net.ParseIP("fe00::") + ipv4Private := net.ParseIP("10.255.0.0") + ipv4Public := net.ParseIP("11.0.0.0") + + fmt.Println(ipv6Private.IsPrivate()) + fmt.Println(ipv6Public.IsPrivate()) + fmt.Println(ipv4Private.IsPrivate()) + fmt.Println(ipv4Public.IsPrivate()) + + // Output: + // true + // false + // true + // false +} + +func ExampleIP_IsUnspecified() { + ipv6Unspecified := net.ParseIP("::") + ipv6Specified := net.ParseIP("fe00::") + ipv4Unspecified := net.ParseIP("0.0.0.0") + ipv4Specified := net.ParseIP("8.8.8.8") + + fmt.Println(ipv6Unspecified.IsUnspecified()) + fmt.Println(ipv6Specified.IsUnspecified()) + fmt.Println(ipv4Unspecified.IsUnspecified()) + fmt.Println(ipv4Specified.IsUnspecified()) + + // Output: + // true + // false + // true + // false +} + func ExampleIP_Mask() { ipv4Addr := net.ParseIP("192.0.2.1") // This mask corresponds to a /24 subnet for IPv4. @@ -140,6 +310,42 @@ func ExampleIP_Mask() { // 2001:db8:: } +func ExampleIP_String() { + ipv6 := net.IP{0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + ipv4 := net.IPv4(10, 255, 0, 0) + + fmt.Println(ipv6.String()) + fmt.Println(ipv4.String()) + + // Output: + // fc00:: + // 10.255.0.0 +} + +func ExampleIP_To16() { + ipv6 := net.IP{0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + ipv4 := net.IPv4(10, 255, 0, 0) + + fmt.Println(ipv6.To16()) + fmt.Println(ipv4.To16()) + + // Output: + // fc00:: + // 10.255.0.0 +} + +func ExampleIP_to4() { + ipv6 := net.IP{0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + ipv4 := net.IPv4(10, 255, 0, 0) + + fmt.Println(ipv6.To4()) + fmt.Println(ipv4.To4()) + + // Output: + // + // 10.255.0.0 +} + func ExampleCIDRMask() { // This mask corresponds to a /31 subnet for IPv4. fmt.Println(net.CIDRMask(31, 32)) -- GitLab From 3986e5c8e7df958cc1412ad06afc011022da76e1 Mon Sep 17 00:00:00 2001 From: kjgorman Date: Sun, 10 Oct 2021 14:30:26 +0100 Subject: [PATCH 1582/2500] bytes: fix Cut godoc typo If sep does not appear in s, we return nil here rather than the empty string. Presumably the docs were copied from the strings package implementation and brought that along. Change-Id: I3706c94fe04abd9e2a2c8840f7cc6116386965c8 Reviewed-on: https://go-review.googlesource.com/c/go/+/354969 Reviewed-by: Ian Lance Taylor Trust: Alexander Rakoczy --- src/bytes/bytes.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bytes/bytes.go b/src/bytes/bytes.go index d3e01c3de7..926f65cc8f 100644 --- a/src/bytes/bytes.go +++ b/src/bytes/bytes.go @@ -1260,7 +1260,7 @@ func Index(s, sep []byte) int { // Cut slices s around the first instance of sep, // returning the text before and after sep. // The found result reports whether sep appears in s. -// If sep does not appear in s, cut returns s, "", false. +// If sep does not appear in s, cut returns s, nil, false. // // Cut returns slices of the original slice s, not copies. func Cut(s, sep []byte) (before, after []byte, found bool) { -- GitLab From aded1679ef6a33ef6fe6c0b466ecf59186706d23 Mon Sep 17 00:00:00 2001 From: Koichi Shiraishi Date: Tue, 12 Oct 2021 00:33:43 +0900 Subject: [PATCH 1583/2500] internal/poll,net: support poll.Sendfile for darwin darwin already supports syscall.Sendfile. Change-Id: Id3db06591ffad0550b4173bacddeb0acfe355f9e Reviewed-on: https://go-review.googlesource.com/c/go/+/355109 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Trust: Alexander Rakoczy --- src/internal/poll/sendfile_bsd.go | 4 ++-- src/net/sendfile_stub.go | 4 ++-- src/net/sendfile_unix_alt.go | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/internal/poll/sendfile_bsd.go b/src/internal/poll/sendfile_bsd.go index 3ba30a2154..5531e533c5 100644 --- a/src/internal/poll/sendfile_bsd.go +++ b/src/internal/poll/sendfile_bsd.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build dragonfly || freebsd -// +build dragonfly freebsd +//go:build darwin || dragonfly || freebsd +// +build darwin dragonfly freebsd package poll diff --git a/src/net/sendfile_stub.go b/src/net/sendfile_stub.go index 5753bc0289..c079064262 100644 --- a/src/net/sendfile_stub.go +++ b/src/net/sendfile_stub.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build aix || darwin || (js && wasm) || netbsd || openbsd -// +build aix darwin js,wasm netbsd openbsd +//go:build aix || (js && wasm) || netbsd || openbsd +// +build aix js,wasm netbsd openbsd package net diff --git a/src/net/sendfile_unix_alt.go b/src/net/sendfile_unix_alt.go index 54667d672f..cd63dcc32c 100644 --- a/src/net/sendfile_unix_alt.go +++ b/src/net/sendfile_unix_alt.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build dragonfly || freebsd || solaris -// +build dragonfly freebsd solaris +//go:build darwin || dragonfly || freebsd || solaris +// +build darwin dragonfly freebsd solaris package net -- GitLab From b5904f3de0937aac72acd40d6c26494ebb9d7909 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 12 Oct 2021 15:03:25 -0400 Subject: [PATCH 1584/2500] net: remove timeout in TestDialTimeoutMaxDuration This test seems only to be testing that Dial does not time out immediately as a result of integer overflow; the precise time taken to connect is immaterial. Replace naked loop with sub-tests. Fixes #43069. Change-Id: Ib5e38a1d8cd191b74c2bc7c26bef57b180e16f68 Reviewed-on: https://go-review.googlesource.com/c/go/+/355390 Trust: Michael Pratt Run-TryBot: Michael Pratt TryBot-Result: Go Bot Reviewed-by: Damien Neil --- src/net/timeout_test.go | 53 +++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 34 deletions(-) diff --git a/src/net/timeout_test.go b/src/net/timeout_test.go index e1cf1467c3..6c8e9cf76e 100644 --- a/src/net/timeout_test.go +++ b/src/net/timeout_test.go @@ -93,53 +93,38 @@ func TestDialTimeout(t *testing.T) { } } -var dialTimeoutMaxDurationTests = []struct { - timeout time.Duration - delta time.Duration // for deadline -}{ - // Large timeouts that will overflow an int64 unix nanos. - {1<<63 - 1, 0}, - {0, 1<<63 - 1}, -} - func TestDialTimeoutMaxDuration(t *testing.T) { - if runtime.GOOS == "openbsd" { - testenv.SkipFlaky(t, 15157) - } - ln, err := newLocalListener("tcp") if err != nil { t.Fatal(err) } - defer ln.Close() + defer func() { + if err := ln.Close(); err != nil { + t.Error(err) + } + }() - for i, tt := range dialTimeoutMaxDurationTests { - ch := make(chan error) - max := time.NewTimer(250 * time.Millisecond) - defer max.Stop() - go func() { + for _, tt := range []struct { + timeout time.Duration + delta time.Duration // for deadline + }{ + // Large timeouts that will overflow an int64 unix nanos. + {1<<63 - 1, 0}, + {0, 1<<63 - 1}, + } { + t.Run(fmt.Sprintf("timeout=%s/delta=%s", tt.timeout, tt.delta), func(t *testing.T) { d := Dialer{Timeout: tt.timeout} if tt.delta != 0 { d.Deadline = time.Now().Add(tt.delta) } c, err := d.Dial(ln.Addr().Network(), ln.Addr().String()) - if err == nil { - c.Close() - } - ch <- err - }() - - select { - case <-max.C: - t.Fatalf("#%d: Dial didn't return in an expected time", i) - case err := <-ch: - if perr := parseDialError(err); perr != nil { - t.Error(perr) - } if err != nil { - t.Errorf("#%d: %v", i, err) + t.Fatal(err) } - } + if err := c.Close(); err != nil { + t.Error(err) + } + }) } } -- GitLab From 4a3daeee636751a262eb9f77d8e90c59955ee6bb Mon Sep 17 00:00:00 2001 From: James Harris Date: Fri, 17 Sep 2021 02:29:00 +0000 Subject: [PATCH 1585/2500] net/http/httputil: allow MIME parameters when detecting SSE in ReverseProxy This change allows httputil.ReverseProxy to detect SSE (server-sent events) content when the response's Content-Type header includes MIME parameters, such as "text/event-stream;charset=utf-8". Prior to this change the value of the Content-Type header was compared directly to the literal "text/event-stream". This caused a false-negative which failed to set the FlushInterval correctly when MIME parameters were present. Change-Id: If8bb43efb78787b6519d7fe7599ca018a0da0023 GitHub-Last-Rev: 224518c5eb9686ee050c79f5f853ebacfdf6fc42 GitHub-Pull-Request: golang/go#48427 Reviewed-on: https://go-review.googlesource.com/c/go/+/350509 Trust: Alexander Rakoczy Trust: Damien Neil Run-TryBot: Alexander Rakoczy TryBot-Result: Go Bot Reviewed-by: Damien Neil --- src/net/http/httputil/reverseproxy.go | 3 ++- src/net/http/httputil/reverseproxy_test.go | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go index 8b63368386..71849bb8f7 100644 --- a/src/net/http/httputil/reverseproxy.go +++ b/src/net/http/httputil/reverseproxy.go @@ -11,6 +11,7 @@ import ( "fmt" "io" "log" + "mime" "net" "net/http" "net/http/internal/ascii" @@ -412,7 +413,7 @@ func (p *ReverseProxy) flushInterval(res *http.Response) time.Duration { // For Server-Sent Events responses, flush immediately. // The MIME type is defined in https://www.w3.org/TR/eventsource/#text-event-stream - if resCT == "text/event-stream" { + if baseCT, _, _ := mime.ParseMediaType(resCT); baseCT == "text/event-stream" { return -1 // negative means immediately } diff --git a/src/net/http/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go index 4b6ad77a29..90e8903e9c 100644 --- a/src/net/http/httputil/reverseproxy_test.go +++ b/src/net/http/httputil/reverseproxy_test.go @@ -1194,6 +1194,26 @@ func TestSelectFlushInterval(t *testing.T) { p: &ReverseProxy{FlushInterval: 0}, want: -1, }, + { + name: "server-sent events with media-type parameters overrides non-zero", + res: &http.Response{ + Header: http.Header{ + "Content-Type": {"text/event-stream;charset=utf-8"}, + }, + }, + p: &ReverseProxy{FlushInterval: 123}, + want: -1, + }, + { + name: "server-sent events with media-type parameters overrides zero", + res: &http.Response{ + Header: http.Header{ + "Content-Type": {"text/event-stream;charset=utf-8"}, + }, + }, + p: &ReverseProxy{FlushInterval: 0}, + want: -1, + }, { name: "Content-Length: -1, overrides non-zero", res: &http.Response{ -- GitLab From 4efa216c9d753c0853aa96a8c54ed5014fbc12e6 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 12 Oct 2021 15:31:25 -0700 Subject: [PATCH 1586/2500] unsafe: allow unsafe.Slice up to end of address space Allow the user to construct slices that are larger than the Go heap as long as they don't overflow the address space. Updates #48798. Change-Id: I659c8334d04676e1f253b9c3cd499eab9b9f989a Reviewed-on: https://go-review.googlesource.com/c/go/+/355489 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: Ian Lance Taylor --- src/runtime/slice.go | 2 +- test/unsafebuiltins.go | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/runtime/slice.go b/src/runtime/slice.go index cfa862e047..66bb7d9d93 100644 --- a/src/runtime/slice.go +++ b/src/runtime/slice.go @@ -124,7 +124,7 @@ func unsafeslice(et *_type, ptr unsafe.Pointer, len int) { } mem, overflow := math.MulUintptr(et.size, uintptr(len)) - if overflow || mem > maxAlloc || len < 0 { + if overflow || mem > -uintptr(ptr) || len < 0 { panicunsafeslicelen() } } diff --git a/test/unsafebuiltins.go b/test/unsafebuiltins.go index 4c940aa855..d04bcbdc7d 100644 --- a/test/unsafebuiltins.go +++ b/test/unsafebuiltins.go @@ -47,6 +47,11 @@ func main() { // size overflows address space mustPanic(func() { _ = unsafe.Slice(new(uint64), maxUintptr/8) }) mustPanic(func() { _ = unsafe.Slice(new(uint64), maxUintptr/8+1) }) + + // sliced memory overflows address space + last := (*byte)(unsafe.Pointer(^uintptr(0))) + _ = unsafe.Slice(last, 1) + mustPanic(func() { _ = unsafe.Slice(last, 2) }) } } -- GitLab From 40f82f8a092ac1f23eb3af86f34b7436a6fc19e0 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 12 Oct 2021 15:38:52 -0700 Subject: [PATCH 1587/2500] unsafe: optimize Slice bounds checking This reduces the number of branches to bounds check non-empty slices from 5 to 3. It does also increase the number of branches to handle empty slices from 1 to 3; but for non-panicking calls, they should all be predictable. Updates #48798. Change-Id: I3ffa66857096486f4dee417e1a66eb8fdf7a3777 Reviewed-on: https://go-review.googlesource.com/c/go/+/355490 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/runtime/slice.go | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/runtime/slice.go b/src/runtime/slice.go index 66bb7d9d93..aab8a598c5 100644 --- a/src/runtime/slice.go +++ b/src/runtime/slice.go @@ -115,16 +115,15 @@ func makeslice64(et *_type, len64, cap64 int64) unsafe.Pointer { } func unsafeslice(et *_type, ptr unsafe.Pointer, len int) { - if len == 0 { - return - } - - if ptr == nil { - panic(errorString("unsafe.Slice: ptr is nil and len is not zero")) + if len < 0 { + panicunsafeslicelen() } mem, overflow := math.MulUintptr(et.size, uintptr(len)) - if overflow || mem > -uintptr(ptr) || len < 0 { + if overflow || mem > -uintptr(ptr) { + if ptr == nil { + panic(errorString("unsafe.Slice: ptr is nil and len is not zero")) + } panicunsafeslicelen() } } -- GitLab From b90d258b18e2fe728a3d7c856ad08c7fa6845fc2 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 13 Oct 2021 10:27:01 -0700 Subject: [PATCH 1588/2500] cmd/compile: fix inst_test.go for riscv5 On riscv5, apparently extra wrappers (trampolines) are created for some functions with the suffix "-tramp". Modify inst_test.go to not match these "-tramp" wrappers. Change-Id: I754c724f03555c30f8e1b5cfc08152555bbbcf17 Reviewed-on: https://go-review.googlesource.com/c/go/+/355650 Run-TryBot: Dan Scales Reviewed-by: Keith Randall Trust: Dan Scales --- src/cmd/compile/internal/test/inst_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/test/inst_test.go b/src/cmd/compile/internal/test/inst_test.go index 59a67cb545..951f6a05aa 100644 --- a/src/cmd/compile/internal/test/inst_test.go +++ b/src/cmd/compile/internal/test/inst_test.go @@ -50,7 +50,9 @@ func TestInst(t *testing.T) { if output, err = cmd.CombinedOutput(); err != nil { t.Fatalf("Failed: %v:\nOut: %s\n", err, output) } - re := regexp.MustCompile(`\bSort\[.*shape.*\]`) + // Look for shape-based instantiation of Sort, but ignore any extra wrapper + // ending in "-tramp" (which are created on riscv). + re := regexp.MustCompile(`\bSort\[.*shape.*\][^-]`) r := re.FindAllIndex(output, -1) if len(r) != 1 { t.Fatalf("Wanted 1 instantiations of Sort function, got %d\n", len(r)) -- GitLab From 276fb279d1703451e5b962350727f84e4e8e9814 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 13 Oct 2021 11:50:46 -0700 Subject: [PATCH 1589/2500] cmd/compile/internal/syntax: remove AllowTypeSets mode The respective issue has been accepted, so we can always accept constraint literals with omitted interfaces. For #48424. Change-Id: Ia3d325401252a5a22d5ffa98d2ae6af73178dec0 Reviewed-on: https://go-review.googlesource.com/c/go/+/355709 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/noder/noder.go | 2 +- src/cmd/compile/internal/syntax/error_test.go | 2 +- src/cmd/compile/internal/syntax/parser.go | 2 +- src/cmd/compile/internal/syntax/parser_test.go | 6 +++--- src/cmd/compile/internal/syntax/printer_test.go | 4 ++-- src/cmd/compile/internal/syntax/syntax.go | 1 - src/cmd/compile/internal/types2/check_test.go | 2 +- 7 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index 2e7b636681..7c14fcf041 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -36,7 +36,7 @@ func LoadPackage(filenames []string) { mode := syntax.CheckBranches if supportsGenerics { - mode |= syntax.AllowGenerics | syntax.AllowTypeSets + mode |= syntax.AllowGenerics } // Limit the number of simultaneously open files. diff --git a/src/cmd/compile/internal/syntax/error_test.go b/src/cmd/compile/internal/syntax/error_test.go index 0ab3c20ce5..d87e8eaee3 100644 --- a/src/cmd/compile/internal/syntax/error_test.go +++ b/src/cmd/compile/internal/syntax/error_test.go @@ -130,7 +130,7 @@ func testSyntaxErrors(t *testing.T, filename string) { var mode Mode if strings.HasSuffix(filename, ".go2") { - mode = AllowGenerics | AllowTypeSets + mode = AllowGenerics } ParseFile(filename, func(err error) { e, ok := err.(Error) diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index a669c54712..e78e77561d 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -1820,7 +1820,7 @@ func (p *parser) paramDeclOrNil(name *Name, follow token) *Field { } // type set notation is ok in type parameter lists - typeSetsOk := p.mode&AllowTypeSets != 0 && follow == _Rbrack + typeSetsOk := follow == _Rbrack pos := p.pos() if name != nil { diff --git a/src/cmd/compile/internal/syntax/parser_test.go b/src/cmd/compile/internal/syntax/parser_test.go index 29682012e5..68f3c376c9 100644 --- a/src/cmd/compile/internal/syntax/parser_test.go +++ b/src/cmd/compile/internal/syntax/parser_test.go @@ -26,11 +26,11 @@ var ( ) func TestParse(t *testing.T) { - ParseFile(*src_, func(err error) { t.Error(err) }, nil, AllowGenerics|AllowTypeSets) + ParseFile(*src_, func(err error) { t.Error(err) }, nil, AllowGenerics) } func TestVerify(t *testing.T) { - ast, err := ParseFile(*src_, func(err error) { t.Error(err) }, nil, AllowGenerics|AllowTypeSets) + ast, err := ParseFile(*src_, func(err error) { t.Error(err) }, nil, AllowGenerics) if err != nil { return // error already reported } @@ -46,7 +46,7 @@ func TestParseGo2(t *testing.T) { for _, fi := range list { name := fi.Name() if !fi.IsDir() && !strings.HasPrefix(name, ".") { - ParseFile(filepath.Join(dir, name), func(err error) { t.Error(err) }, nil, AllowGenerics|AllowTypeSets) + ParseFile(filepath.Join(dir, name), func(err error) { t.Error(err) }, nil, AllowGenerics) } } } diff --git a/src/cmd/compile/internal/syntax/printer_test.go b/src/cmd/compile/internal/syntax/printer_test.go index 9b5331b148..604f1fc1ca 100644 --- a/src/cmd/compile/internal/syntax/printer_test.go +++ b/src/cmd/compile/internal/syntax/printer_test.go @@ -72,7 +72,7 @@ var stringTests = []string{ "package p; func (*R[A, B, C]) _()", "package p; func (_ *R[A, B, C]) _()", - // type constraint literals with elided interfaces (only if AllowTypeSets is set) + // type constraint literals with elided interfaces "package p; func _[P ~int, Q int | string]() {}", "package p; func _[P struct{f int}, Q *P]() {}", @@ -94,7 +94,7 @@ var stringTests = []string{ func TestPrintString(t *testing.T) { for _, want := range stringTests { - ast, err := Parse(nil, strings.NewReader(want), nil, nil, AllowGenerics|AllowTypeSets) + ast, err := Parse(nil, strings.NewReader(want), nil, nil, AllowGenerics) if err != nil { t.Error(err) continue diff --git a/src/cmd/compile/internal/syntax/syntax.go b/src/cmd/compile/internal/syntax/syntax.go index 49ba87786e..f3d4c09ed5 100644 --- a/src/cmd/compile/internal/syntax/syntax.go +++ b/src/cmd/compile/internal/syntax/syntax.go @@ -17,7 +17,6 @@ type Mode uint const ( CheckBranches Mode = 1 << iota // check correct use of labels, break, continue, and goto statements AllowGenerics - AllowTypeSets // requires AllowGenerics; remove once #48424 is decided ) // Error describes a syntax error. Error implements the error interface. diff --git a/src/cmd/compile/internal/types2/check_test.go b/src/cmd/compile/internal/types2/check_test.go index 5b2f09425b..bc68e76407 100644 --- a/src/cmd/compile/internal/types2/check_test.go +++ b/src/cmd/compile/internal/types2/check_test.go @@ -100,7 +100,7 @@ func testFiles(t *testing.T, filenames []string, colDelta uint, manual bool) { var mode syntax.Mode if strings.HasSuffix(filenames[0], ".go2") { - mode |= syntax.AllowGenerics | syntax.AllowTypeSets + mode |= syntax.AllowGenerics } // parse files and collect parser errors files, errlist := parseFiles(t, filenames, mode) -- GitLab From 9e4dc6f37f75840d1193accae697a0e9283f5384 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 13 Oct 2021 12:46:33 -0700 Subject: [PATCH 1590/2500] cmd/link/internal/ld: don't use linkname before 1.12 Before the 1.12 release the use of linkname did not prevent a compiler error for an empty function body (see #23311). Add some build tags so that cmd/link will build with earlier releases. It's true that we currently require Go 1.16 as the bootstrap compiler (#44505). But for this simple case keep things working with older compilers for now. Change-Id: I67fe021406096c64c01d6e2c9adbcc4388988a6e Reviewed-on: https://go-review.googlesource.com/c/go/+/355690 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Russ Cox --- src/cmd/link/internal/ld/outbuf_darwin.go | 3 +++ src/cmd/link/internal/ld/outbuf_nofallocate.go | 4 ++-- src/cmd/link/internal/ld/outbuf_notdarwin.go | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/cmd/link/internal/ld/outbuf_darwin.go b/src/cmd/link/internal/ld/outbuf_darwin.go index 6920a0a843..b1ee3c5628 100644 --- a/src/cmd/link/internal/ld/outbuf_darwin.go +++ b/src/cmd/link/internal/ld/outbuf_darwin.go @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin && go1.12 +// +build darwin,go1.12 + package ld import ( diff --git a/src/cmd/link/internal/ld/outbuf_nofallocate.go b/src/cmd/link/internal/ld/outbuf_nofallocate.go index 6564bd54a3..3bffe4543d 100644 --- a/src/cmd/link/internal/ld/outbuf_nofallocate.go +++ b/src/cmd/link/internal/ld/outbuf_nofallocate.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build !darwin && !linux -// +build !darwin,!linux +//go:build (!darwin && !linux) || (darwin && !go1.12) +// +build !darwin,!linux darwin,!go1.12 package ld diff --git a/src/cmd/link/internal/ld/outbuf_notdarwin.go b/src/cmd/link/internal/ld/outbuf_notdarwin.go index f9caa413e3..85e64421a3 100644 --- a/src/cmd/link/internal/ld/outbuf_notdarwin.go +++ b/src/cmd/link/internal/ld/outbuf_notdarwin.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build !darwin -// +build !darwin +//go:build !darwin || (darwin && !go1.12) +// +build !darwin darwin,!go1.12 package ld -- GitLab From 1349c6eb1e3faf8b83db9a1ea30764d56b40c7dc Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 13 Oct 2021 15:42:31 +0200 Subject: [PATCH 1591/2500] syscall: separate ProcSysAttr and forkAndExecInChild for FreeBSD To allow adding fields to ProcSysAttr which are supported on FreeBSD but not on other BSDs. For now exec_freebsd.go is an exact copy of exec_bsd.go with adjusted build tags and copyright year. For #46258 For #46259 Change-Id: I7667a0cdf1ca86ef64a147b77c06db70c5f8eb90 Reviewed-on: https://go-review.googlesource.com/c/go/+/355569 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/syscall/exec_bsd.go | 4 +- src/syscall/exec_freebsd.go | 263 ++++++++++++++++++++++++++++++++++++ 2 files changed, 265 insertions(+), 2 deletions(-) create mode 100644 src/syscall/exec_freebsd.go diff --git a/src/syscall/exec_bsd.go b/src/syscall/exec_bsd.go index 709066e809..4c36f9ec13 100644 --- a/src/syscall/exec_bsd.go +++ b/src/syscall/exec_bsd.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build dragonfly || freebsd || netbsd || (openbsd && mips64) -// +build dragonfly freebsd netbsd openbsd,mips64 +//go:build dragonfly || netbsd || (openbsd && mips64) +// +build dragonfly netbsd openbsd,mips64 package syscall diff --git a/src/syscall/exec_freebsd.go b/src/syscall/exec_freebsd.go new file mode 100644 index 0000000000..393b3d485b --- /dev/null +++ b/src/syscall/exec_freebsd.go @@ -0,0 +1,263 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package syscall + +import ( + "unsafe" +) + +type SysProcAttr struct { + Chroot string // Chroot. + Credential *Credential // Credential. + Ptrace bool // Enable tracing. + Setsid bool // Create session. + // Setpgid sets the process group ID of the child to Pgid, + // or, if Pgid == 0, to the new child's process ID. + Setpgid bool + // Setctty sets the controlling terminal of the child to + // file descriptor Ctty. Ctty must be a descriptor number + // in the child process: an index into ProcAttr.Files. + // This is only meaningful if Setsid is true. + Setctty bool + Noctty bool // Detach fd 0 from controlling terminal + Ctty int // Controlling TTY fd + // Foreground places the child process group in the foreground. + // This implies Setpgid. The Ctty field must be set to + // the descriptor of the controlling TTY. + // Unlike Setctty, in this case Ctty must be a descriptor + // number in the parent process. + Foreground bool + Pgid int // Child's process group ID if Setpgid. +} + +// Implemented in runtime package. +func runtime_BeforeFork() +func runtime_AfterFork() +func runtime_AfterForkInChild() + +// Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child. +// If a dup or exec fails, write the errno error to pipe. +// (Pipe is close-on-exec so if exec succeeds, it will be closed.) +// In the child, this function must not acquire any locks, because +// they might have been locked at the time of the fork. This means +// no rescheduling, no malloc calls, and no new stack segments. +// For the same reason compiler does not race instrument it. +// The calls to RawSyscall are okay because they are assembly +// functions that do not grow the stack. +//go:norace +func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) { + // Declare all variables at top in case any + // declarations require heap allocation (e.g., err1). + var ( + r1 uintptr + err1 Errno + nextfd int + i int + ) + + // guard against side effects of shuffling fds below. + // Make sure that nextfd is beyond any currently open files so + // that we can't run the risk of overwriting any of them. + fd := make([]int, len(attr.Files)) + nextfd = len(attr.Files) + for i, ufd := range attr.Files { + if nextfd < int(ufd) { + nextfd = int(ufd) + } + fd[i] = int(ufd) + } + nextfd++ + + // About to call fork. + // No more allocation or calls of non-assembly functions. + runtime_BeforeFork() + r1, _, err1 = RawSyscall(SYS_FORK, 0, 0, 0) + if err1 != 0 { + runtime_AfterFork() + return 0, err1 + } + + if r1 != 0 { + // parent; return PID + runtime_AfterFork() + return int(r1), 0 + } + + // Fork succeeded, now in child. + + // Enable tracing if requested. + if sys.Ptrace { + _, _, err1 = RawSyscall(SYS_PTRACE, uintptr(PTRACE_TRACEME), 0, 0) + if err1 != 0 { + goto childerror + } + } + + // Session ID + if sys.Setsid { + _, _, err1 = RawSyscall(SYS_SETSID, 0, 0, 0) + if err1 != 0 { + goto childerror + } + } + + // Set process group + if sys.Setpgid || sys.Foreground { + // Place child in process group. + _, _, err1 = RawSyscall(SYS_SETPGID, 0, uintptr(sys.Pgid), 0) + if err1 != 0 { + goto childerror + } + } + + if sys.Foreground { + // This should really be pid_t, however _C_int (aka int32) is + // generally equivalent. + pgrp := _C_int(sys.Pgid) + if pgrp == 0 { + r1, _, err1 = RawSyscall(SYS_GETPID, 0, 0, 0) + if err1 != 0 { + goto childerror + } + + pgrp = _C_int(r1) + } + + // Place process group in foreground. + _, _, err1 = RawSyscall(SYS_IOCTL, uintptr(sys.Ctty), uintptr(TIOCSPGRP), uintptr(unsafe.Pointer(&pgrp))) + if err1 != 0 { + goto childerror + } + } + + // Restore the signal mask. We do this after TIOCSPGRP to avoid + // having the kernel send a SIGTTOU signal to the process group. + runtime_AfterForkInChild() + + // Chroot + if chroot != nil { + _, _, err1 = RawSyscall(SYS_CHROOT, uintptr(unsafe.Pointer(chroot)), 0, 0) + if err1 != 0 { + goto childerror + } + } + + // User and groups + if cred := sys.Credential; cred != nil { + ngroups := uintptr(len(cred.Groups)) + groups := uintptr(0) + if ngroups > 0 { + groups = uintptr(unsafe.Pointer(&cred.Groups[0])) + } + if !cred.NoSetGroups { + _, _, err1 = RawSyscall(SYS_SETGROUPS, ngroups, groups, 0) + if err1 != 0 { + goto childerror + } + } + _, _, err1 = RawSyscall(SYS_SETGID, uintptr(cred.Gid), 0, 0) + if err1 != 0 { + goto childerror + } + _, _, err1 = RawSyscall(SYS_SETUID, uintptr(cred.Uid), 0, 0) + if err1 != 0 { + goto childerror + } + } + + // Chdir + if dir != nil { + _, _, err1 = RawSyscall(SYS_CHDIR, uintptr(unsafe.Pointer(dir)), 0, 0) + if err1 != 0 { + goto childerror + } + } + + // Pass 1: look for fd[i] < i and move those up above len(fd) + // so that pass 2 won't stomp on an fd it needs later. + if pipe < nextfd { + _, _, err1 = RawSyscall(SYS_DUP2, uintptr(pipe), uintptr(nextfd), 0) + if err1 != 0 { + goto childerror + } + RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC) + pipe = nextfd + nextfd++ + } + for i = 0; i < len(fd); i++ { + if fd[i] >= 0 && fd[i] < int(i) { + if nextfd == pipe { // don't stomp on pipe + nextfd++ + } + _, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(nextfd), 0) + if err1 != 0 { + goto childerror + } + RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC) + fd[i] = nextfd + nextfd++ + } + } + + // Pass 2: dup fd[i] down onto i. + for i = 0; i < len(fd); i++ { + if fd[i] == -1 { + RawSyscall(SYS_CLOSE, uintptr(i), 0, 0) + continue + } + if fd[i] == int(i) { + // dup2(i, i) won't clear close-on-exec flag on Linux, + // probably not elsewhere either. + _, _, err1 = RawSyscall(SYS_FCNTL, uintptr(fd[i]), F_SETFD, 0) + if err1 != 0 { + goto childerror + } + continue + } + // The new fd is created NOT close-on-exec, + // which is exactly what we want. + _, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(i), 0) + if err1 != 0 { + goto childerror + } + } + + // By convention, we don't close-on-exec the fds we are + // started with, so if len(fd) < 3, close 0, 1, 2 as needed. + // Programs that know they inherit fds >= 3 will need + // to set them close-on-exec. + for i = len(fd); i < 3; i++ { + RawSyscall(SYS_CLOSE, uintptr(i), 0, 0) + } + + // Detach fd 0 from tty + if sys.Noctty { + _, _, err1 = RawSyscall(SYS_IOCTL, 0, uintptr(TIOCNOTTY), 0) + if err1 != 0 { + goto childerror + } + } + + // Set the controlling TTY to Ctty + if sys.Setctty { + _, _, err1 = RawSyscall(SYS_IOCTL, uintptr(sys.Ctty), uintptr(TIOCSCTTY), 0) + if err1 != 0 { + goto childerror + } + } + + // Time to exec. + _, _, err1 = RawSyscall(SYS_EXECVE, + uintptr(unsafe.Pointer(argv0)), + uintptr(unsafe.Pointer(&argv[0])), + uintptr(unsafe.Pointer(&envv[0]))) + +childerror: + // send error code on pipe + RawSyscall(SYS_WRITE, uintptr(pipe), uintptr(unsafe.Pointer(&err1)), unsafe.Sizeof(err1)) + for { + RawSyscall(SYS_EXIT, 253, 0, 0) + } +} -- GitLab From 2feb2cc450e1925b9359957c90bae27e01662171 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 13 Oct 2021 16:30:12 +0200 Subject: [PATCH 1592/2500] syscall: add support for SysProcAttr.Pdeathsig on FreeBSD Fixes #46258 Change-Id: I63f70e67274a9df39c757243b99b12e50a9e4784 Reviewed-on: https://go-review.googlesource.com/c/go/+/355570 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/syscall/exec_freebsd.go | 38 +++++++- src/syscall/exec_linux.go | 2 +- src/syscall/exec_pdeathsig_test.go | 135 ++++++++++++++++++++++++++++ src/syscall/syscall_freebsd_test.go | 11 +++ src/syscall/syscall_linux_test.go | 117 ------------------------ 5 files changed, 184 insertions(+), 119 deletions(-) create mode 100644 src/syscall/exec_pdeathsig_test.go diff --git a/src/syscall/exec_freebsd.go b/src/syscall/exec_freebsd.go index 393b3d485b..a7410db4b6 100644 --- a/src/syscall/exec_freebsd.go +++ b/src/syscall/exec_freebsd.go @@ -5,6 +5,7 @@ package syscall import ( + "runtime" "unsafe" ) @@ -29,9 +30,16 @@ type SysProcAttr struct { // Unlike Setctty, in this case Ctty must be a descriptor // number in the parent process. Foreground bool - Pgid int // Child's process group ID if Setpgid. + Pgid int // Child's process group ID if Setpgid. + Pdeathsig Signal // Signal that the process will get when its parent dies (Linux and FreeBSD only) } +const ( + _P_PID = 0 + + _PROC_PDEATHSIG_CTL = 11 +) + // Implemented in runtime package. func runtime_BeforeFork() func runtime_AfterFork() @@ -57,6 +65,9 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr i int ) + // Record parent PID so child can test if it has died. + ppid, _, _ := RawSyscall(SYS_GETPID, 0, 0, 0) + // guard against side effects of shuffling fds below. // Make sure that nextfd is beyond any currently open files so // that we can't run the risk of overwriting any of them. @@ -175,6 +186,31 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr } } + // Parent death signal + if sys.Pdeathsig != 0 { + switch runtime.GOARCH { + case "386", "arm": + _, _, err1 = RawSyscall6(SYS_PROCCTL, _P_PID, 0, 0, _PROC_PDEATHSIG_CTL, uintptr(unsafe.Pointer(&sys.Pdeathsig)), 0) + default: + _, _, err1 = RawSyscall6(SYS_PROCCTL, _P_PID, 0, _PROC_PDEATHSIG_CTL, uintptr(unsafe.Pointer(&sys.Pdeathsig)), 0, 0) + } + if err1 != 0 { + goto childerror + } + + // Signal self if parent is already dead. This might cause a + // duplicate signal in rare cases, but it won't matter when + // using SIGKILL. + r1, _, _ = RawSyscall(SYS_GETPPID, 0, 0, 0) + if r1 != ppid { + pid, _, _ := RawSyscall(SYS_GETPID, 0, 0, 0) + _, _, err1 := RawSyscall(SYS_KILL, pid, uintptr(sys.Pdeathsig), 0) + if err1 != 0 { + goto childerror + } + } + } + // Pass 1: look for fd[i] < i and move those up above len(fd) // so that pass 2 won't stomp on an fd it needs later. if pipe < nextfd { diff --git a/src/syscall/exec_linux.go b/src/syscall/exec_linux.go index dfc5228545..e1506e1e2b 100644 --- a/src/syscall/exec_linux.go +++ b/src/syscall/exec_linux.go @@ -46,7 +46,7 @@ type SysProcAttr struct { // number in the parent process. Foreground bool Pgid int // Child's process group ID if Setpgid. - Pdeathsig Signal // Signal that the process will get when its parent dies (Linux only) + Pdeathsig Signal // Signal that the process will get when its parent dies (Linux and FreeBSD only) Cloneflags uintptr // Flags for clone calls (Linux only) Unshareflags uintptr // Flags for unshare calls (Linux only) UidMappings []SysProcIDMap // User ID mappings for user namespaces. diff --git a/src/syscall/exec_pdeathsig_test.go b/src/syscall/exec_pdeathsig_test.go new file mode 100644 index 0000000000..6533d3a138 --- /dev/null +++ b/src/syscall/exec_pdeathsig_test.go @@ -0,0 +1,135 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build freebsd || linux +// +build freebsd linux + +package syscall_test + +import ( + "bufio" + "fmt" + "io" + "os" + "os/exec" + "os/signal" + "path/filepath" + "syscall" + "testing" + "time" +) + +func TestDeathSignal(t *testing.T) { + if os.Getuid() != 0 { + t.Skip("skipping root only test") + } + + // Copy the test binary to a location that a non-root user can read/execute + // after we drop privileges + tempDir, err := os.MkdirTemp("", "TestDeathSignal") + if err != nil { + t.Fatalf("cannot create temporary directory: %v", err) + } + defer os.RemoveAll(tempDir) + os.Chmod(tempDir, 0755) + + tmpBinary := filepath.Join(tempDir, filepath.Base(os.Args[0])) + + src, err := os.Open(os.Args[0]) + if err != nil { + t.Fatalf("cannot open binary %q, %v", os.Args[0], err) + } + defer src.Close() + + dst, err := os.OpenFile(tmpBinary, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755) + if err != nil { + t.Fatalf("cannot create temporary binary %q, %v", tmpBinary, err) + } + if _, err := io.Copy(dst, src); err != nil { + t.Fatalf("failed to copy test binary to %q, %v", tmpBinary, err) + } + err = dst.Close() + if err != nil { + t.Fatalf("failed to close test binary %q, %v", tmpBinary, err) + } + + cmd := exec.Command(tmpBinary) + cmd.Env = append(os.Environ(), "GO_DEATHSIG_PARENT=1") + chldStdin, err := cmd.StdinPipe() + if err != nil { + t.Fatalf("failed to create new stdin pipe: %v", err) + } + chldStdout, err := cmd.StdoutPipe() + if err != nil { + t.Fatalf("failed to create new stdout pipe: %v", err) + } + cmd.Stderr = os.Stderr + + err = cmd.Start() + defer cmd.Wait() + if err != nil { + t.Fatalf("failed to start first child process: %v", err) + } + + chldPipe := bufio.NewReader(chldStdout) + + if got, err := chldPipe.ReadString('\n'); got == "start\n" { + syscall.Kill(cmd.Process.Pid, syscall.SIGTERM) + + go func() { + time.Sleep(5 * time.Second) + chldStdin.Close() + }() + + want := "ok\n" + if got, err = chldPipe.ReadString('\n'); got != want { + t.Fatalf("expected %q, received %q, %v", want, got, err) + } + } else { + t.Fatalf("did not receive start from child, received %q, %v", got, err) + } +} + +func deathSignalParent() { + cmd := exec.Command(os.Args[0]) + cmd.Env = append(os.Environ(), + "GO_DEATHSIG_PARENT=", + "GO_DEATHSIG_CHILD=1", + ) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + attrs := syscall.SysProcAttr{ + Pdeathsig: syscall.SIGUSR1, + // UID/GID 99 is the user/group "nobody" on RHEL/Fedora and is + // unused on Ubuntu + Credential: &syscall.Credential{Uid: 99, Gid: 99}, + } + cmd.SysProcAttr = &attrs + + err := cmd.Start() + if err != nil { + fmt.Fprintf(os.Stderr, "death signal parent error: %v\n", err) + os.Exit(1) + } + cmd.Wait() + os.Exit(0) +} + +func deathSignalChild() { + c := make(chan os.Signal, 1) + signal.Notify(c, syscall.SIGUSR1) + go func() { + <-c + fmt.Println("ok") + os.Exit(0) + }() + fmt.Println("start") + + buf := make([]byte, 32) + os.Stdin.Read(buf) + + // We expected to be signaled before stdin closed + fmt.Println("not ok") + os.Exit(1) +} diff --git a/src/syscall/syscall_freebsd_test.go b/src/syscall/syscall_freebsd_test.go index 89c7959d0c..72cd133b85 100644 --- a/src/syscall/syscall_freebsd_test.go +++ b/src/syscall/syscall_freebsd_test.go @@ -9,6 +9,7 @@ package syscall_test import ( "fmt" + "os" "syscall" "testing" "unsafe" @@ -53,3 +54,13 @@ func TestConvertFromDirent11(t *testing.T) { } } } + +func TestMain(m *testing.M) { + if os.Getenv("GO_DEATHSIG_PARENT") == "1" { + deathSignalParent() + } else if os.Getenv("GO_DEATHSIG_CHILD") == "1" { + deathSignalChild() + } + + os.Exit(m.Run()) +} diff --git a/src/syscall/syscall_linux_test.go b/src/syscall/syscall_linux_test.go index 442dc9f10e..8d828be015 100644 --- a/src/syscall/syscall_linux_test.go +++ b/src/syscall/syscall_linux_test.go @@ -5,13 +5,11 @@ package syscall_test import ( - "bufio" "fmt" "io" "io/fs" "os" "os/exec" - "os/signal" "path/filepath" "runtime" "sort" @@ -19,7 +17,6 @@ import ( "strings" "syscall" "testing" - "time" "unsafe" ) @@ -153,120 +150,6 @@ func TestMain(m *testing.M) { os.Exit(m.Run()) } -func TestLinuxDeathSignal(t *testing.T) { - if os.Getuid() != 0 { - t.Skip("skipping root only test") - } - - // Copy the test binary to a location that a non-root user can read/execute - // after we drop privileges - tempDir, err := os.MkdirTemp("", "TestDeathSignal") - if err != nil { - t.Fatalf("cannot create temporary directory: %v", err) - } - defer os.RemoveAll(tempDir) - os.Chmod(tempDir, 0755) - - tmpBinary := filepath.Join(tempDir, filepath.Base(os.Args[0])) - - src, err := os.Open(os.Args[0]) - if err != nil { - t.Fatalf("cannot open binary %q, %v", os.Args[0], err) - } - defer src.Close() - - dst, err := os.OpenFile(tmpBinary, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755) - if err != nil { - t.Fatalf("cannot create temporary binary %q, %v", tmpBinary, err) - } - if _, err := io.Copy(dst, src); err != nil { - t.Fatalf("failed to copy test binary to %q, %v", tmpBinary, err) - } - err = dst.Close() - if err != nil { - t.Fatalf("failed to close test binary %q, %v", tmpBinary, err) - } - - cmd := exec.Command(tmpBinary) - cmd.Env = append(os.Environ(), "GO_DEATHSIG_PARENT=1") - chldStdin, err := cmd.StdinPipe() - if err != nil { - t.Fatalf("failed to create new stdin pipe: %v", err) - } - chldStdout, err := cmd.StdoutPipe() - if err != nil { - t.Fatalf("failed to create new stdout pipe: %v", err) - } - cmd.Stderr = os.Stderr - - err = cmd.Start() - defer cmd.Wait() - if err != nil { - t.Fatalf("failed to start first child process: %v", err) - } - - chldPipe := bufio.NewReader(chldStdout) - - if got, err := chldPipe.ReadString('\n'); got == "start\n" { - syscall.Kill(cmd.Process.Pid, syscall.SIGTERM) - - go func() { - time.Sleep(5 * time.Second) - chldStdin.Close() - }() - - want := "ok\n" - if got, err = chldPipe.ReadString('\n'); got != want { - t.Fatalf("expected %q, received %q, %v", want, got, err) - } - } else { - t.Fatalf("did not receive start from child, received %q, %v", got, err) - } -} - -func deathSignalParent() { - cmd := exec.Command(os.Args[0]) - cmd.Env = append(os.Environ(), - "GO_DEATHSIG_PARENT=", - "GO_DEATHSIG_CHILD=1", - ) - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - attrs := syscall.SysProcAttr{ - Pdeathsig: syscall.SIGUSR1, - // UID/GID 99 is the user/group "nobody" on RHEL/Fedora and is - // unused on Ubuntu - Credential: &syscall.Credential{Uid: 99, Gid: 99}, - } - cmd.SysProcAttr = &attrs - - err := cmd.Start() - if err != nil { - fmt.Fprintf(os.Stderr, "death signal parent error: %v\n", err) - os.Exit(1) - } - cmd.Wait() - os.Exit(0) -} - -func deathSignalChild() { - c := make(chan os.Signal, 1) - signal.Notify(c, syscall.SIGUSR1) - go func() { - <-c - fmt.Println("ok") - os.Exit(0) - }() - fmt.Println("start") - - buf := make([]byte, 32) - os.Stdin.Read(buf) - - // We expected to be signaled before stdin closed - fmt.Println("not ok") - os.Exit(1) -} - func TestParseNetlinkMessage(t *testing.T) { for i, b := range [][]byte{ {103, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 11, 0, 1, 0, 0, 0, 0, 5, 8, 0, 3, -- GitLab From 24e798e2876f05d628f1e9a32ce8c7f4a3ed3268 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 13 Oct 2021 16:30:16 +0200 Subject: [PATCH 1593/2500] syscall: use fcntl with F_DUP2FD_CLOEXEC in forkAndExecInChild on FreeBSD Use fcntl(oldfd, F_DUP2FD_CLOEXEC, newfd) to duplicate the file descriptor and mark is as close-on-exec instead of dup2 & fcntl. FreeBSD implements dup3 like this in libc. Change-Id: I36e37bc61c2e31561adb49001f287764125a74de Reviewed-on: https://go-review.googlesource.com/c/go/+/355571 Trust: Tobias Klauser Reviewed-by: Ian Lance Taylor --- src/syscall/exec_freebsd.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/syscall/exec_freebsd.go b/src/syscall/exec_freebsd.go index a7410db4b6..90793fe83f 100644 --- a/src/syscall/exec_freebsd.go +++ b/src/syscall/exec_freebsd.go @@ -214,11 +214,10 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr // Pass 1: look for fd[i] < i and move those up above len(fd) // so that pass 2 won't stomp on an fd it needs later. if pipe < nextfd { - _, _, err1 = RawSyscall(SYS_DUP2, uintptr(pipe), uintptr(nextfd), 0) + _, _, err1 = RawSyscall(SYS_FCNTL, uintptr(pipe), F_DUP2FD_CLOEXEC, uintptr(nextfd)) if err1 != 0 { goto childerror } - RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC) pipe = nextfd nextfd++ } @@ -227,11 +226,10 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr if nextfd == pipe { // don't stomp on pipe nextfd++ } - _, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(nextfd), 0) + _, _, err1 = RawSyscall(SYS_FCNTL, uintptr(fd[i]), F_DUP2FD_CLOEXEC, uintptr(nextfd)) if err1 != 0 { goto childerror } - RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC) fd[i] = nextfd nextfd++ } -- GitLab From ad99d8840edc655a757570d3d4ec62ad8f4df8a7 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 13 Oct 2021 21:13:05 -0700 Subject: [PATCH 1594/2500] cmd/compile/internal/types2: avoid infinite expansion for invalid recursive generic types The algorithm for detecting invalid recursive types that expand indefinitely suffered from the exact problem is was intended to detect: if the indefinite expansion is happening through type parameters, the algorithm ended up in an infinite sequence of instantiations. (This is only a problem for generic types). Changed the algorithm to always only consider the "original" uninstantiated types. This avoids the problem but it will also not detect some invalid recursive generic types anymore. That requires a more sophisticated type flow analysis. Opened #48962 to track. Addressed with help from @findleyr. For #48951. Change-Id: Ie29cea8f810dae55153dbb1b17c9390cd823c2d9 Reviewed-on: https://go-review.googlesource.com/c/go/+/355732 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/decl.go | 13 ++++++++++-- .../internal/types2/testdata/check/issues.go2 | 4 ++-- .../types2/testdata/fixedbugs/issue39634.go2 | 4 ++-- .../types2/testdata/fixedbugs/issue39938.go2 | 12 ++++++----- .../types2/testdata/fixedbugs/issue48951.go2 | 21 +++++++++++++++++++ 5 files changed, 43 insertions(+), 11 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue48951.go2 diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 26a16d9917..9fd60d6aa2 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -330,7 +330,16 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { } case *Named: - t.resolve(check.conf.Context) + // If t is parameterized, we should be considering the instantiated (expanded) + // form of t, but in general we can't with this algorithm: if t is an invalid + // type it may be so because it infinitely expands through a type parameter. + // Instantiating such a type would lead to an infinite sequence of instantiations. + // In general, we need "type flow analysis" to recognize those cases. + // Example: type A[T any] struct{ x A[*T] } (issue #48951) + // In this algorithm we always only consider the orginal, uninstantiated type. + // This won't recognize some invalid cases with parameterized types, but it + // will terminate. + t = t.orig // don't touch the type if it is from a different package or the Universe scope // (doing so would lead to a race condition - was issue #35049) @@ -359,7 +368,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { check.cycleError(path[i:]) t.info = invalid t.underlying = Typ[Invalid] - return t.info + return invalid } } panic("cycle start not found") diff --git a/src/cmd/compile/internal/types2/testdata/check/issues.go2 b/src/cmd/compile/internal/types2/testdata/check/issues.go2 index effc2db7ae..7c5659ba17 100644 --- a/src/cmd/compile/internal/types2/testdata/check/issues.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/issues.go2 @@ -145,8 +145,8 @@ type List3[TElem any] struct { } // Infinite generic type declarations must lead to an error. -type inf1[T any] struct{ _ inf1 /* ERROR illegal cycle */ [T] } -type inf2[T any] struct{ inf2 /* ERROR illegal cycle */ [T] } +type inf1 /* ERROR illegal cycle */ [T any] struct{ _ inf1[T] } +type inf2 /* ERROR illegal cycle */ [T any] struct{ inf2[T] } // The implementation of conversions T(x) between integers and floating-point // numbers checks that both T and x have either integer or floating-point diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 index 8e6bd974e8..200484b6d9 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 @@ -37,8 +37,8 @@ func main7() { var _ foo7 = x7[int]{} } // func main8() {} // crash 9 -type foo9[A any] interface { foo9 /* ERROR illegal cycle */ [A] } -func _() { var _ = new(foo9 /* ERROR illegal cycle */ [int]) } +type foo9 /* ERROR illegal cycle */ [A any] interface { foo9[A] } +func _() { var _ = new(foo9[int]) } // crash 12 var u /* ERROR cycle */ , i [func /* ERROR used as value */ /* ERROR used as value */ (u, c /* ERROR undeclared */ /* ERROR undeclared */ ) {}(0, len /* ERROR must be called */ /* ERROR must be called */ )]c /* ERROR undeclared */ /* ERROR undeclared */ diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39938.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39938.go2 index 0da6e103fd..31bec5fb01 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39938.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39938.go2 @@ -3,6 +3,8 @@ // license that can be found in the LICENSE file. // Check "infinite expansion" cycle errors across instantiated types. +// We can't detect these errors anymore at the moment. See #48962 for +// details. package p @@ -11,11 +13,11 @@ type E1[P any] *P type E2[P any] struct{ _ P } type E3[P any] struct{ _ *P } -type T0 /* ERROR illegal cycle */ struct { +type T0 /* illegal cycle */ struct { _ E0[T0] } -type T0_ /* ERROR illegal cycle */ struct { +type T0_ /* illegal cycle */ struct { E0[T0_] } @@ -23,7 +25,7 @@ type T1 struct { _ E1[T1] } -type T2 /* ERROR illegal cycle */ struct { +type T2 /* illegal cycle */ struct { _ E2[T2] } @@ -33,7 +35,7 @@ type T3 struct { // some more complex cases -type T4 /* ERROR illegal cycle */ struct { +type T4 /* illegal cycle */ struct { _ E0[E2[T4]] } @@ -41,7 +43,7 @@ type T5 struct { _ E0[E2[E0[E1[E2[[10]T5]]]]] } -type T6 /* ERROR illegal cycle */ struct { +type T6 /* illegal cycle */ struct { _ E0[[10]E2[E0[E2[E2[T6]]]]] } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48951.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48951.go2 new file mode 100644 index 0000000000..cf02cc130a --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48951.go2 @@ -0,0 +1,21 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type ( + A1 /* ERROR illegal cycle */ [P any] [10]A1[P] + A2 /* ERROR illegal cycle */ [P any] [10]A2[*P] + A3[P any] [10]*A3[P] + + L1[P any] []L1[P] + + S1 /* ERROR illegal cycle */ [P any] struct{ f S1[P] } + S2 /* ERROR illegal cycle */ [P any] struct{ f S2[*P] } // like example in issue + S3[P any] struct{ f *S3[P] } + + I1 /* ERROR illegal cycle */ [P any] interface{ I1[P] } + I2 /* ERROR illegal cycle */ [P any] interface{ I2[*P] } + I3[P any] interface{ *I3 /* ERROR interface contains type constraints */ [P] } +) -- GitLab From fbdf83072c413943ccbd3b556654276126117463 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 13 Oct 2021 21:36:03 -0700 Subject: [PATCH 1595/2500] go/types: avoid infinite expansion for invalid recursive generic types This is a clean port of CL 355732 from types2 to go/types. Fixes #48951. Change-Id: I9f8cc0655166835d9450608f6e50b726659a73f1 Reviewed-on: https://go-review.googlesource.com/c/go/+/355733 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/go/types/decl.go | 14 +++++++++++-- src/go/types/testdata/check/issues.go2 | 4 ++-- .../types/testdata/fixedbugs/issue39634.go2 | 4 ++-- .../types/testdata/fixedbugs/issue39938.go2 | 12 ++++++----- .../types/testdata/fixedbugs/issue48951.go2 | 21 +++++++++++++++++++ 5 files changed, 44 insertions(+), 11 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue48951.go2 diff --git a/src/go/types/decl.go b/src/go/types/decl.go index f97fa252cb..4aa49b17ca 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -329,7 +329,17 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { } case *Named: - t.resolve(check.conf.Context) + // If t is parameterized, we should be considering the instantiated (expanded) + // form of t, but in general we can't with this algorithm: if t is an invalid + // type it may be so because it infinitely expands through a type parameter. + // Instantiating such a type would lead to an infinite sequence of instantiations. + // In general, we need "type flow analysis" to recognize those cases. + // Example: type A[T any] struct{ x A[*T] } (issue #48951) + // In this algorithm we always only consider the orginal, uninstantiated type. + // This won't recognize some invalid cases with parameterized types, but it + // will terminate. + t = t.orig + // don't touch the type if it is from a different package or the Universe scope // (doing so would lead to a race condition - was issue #35049) if t.obj.pkg != check.pkg { @@ -357,7 +367,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { check.cycleError(path[i:]) t.info = invalid t.underlying = Typ[Invalid] - return t.info + return invalid } } panic("cycle start not found") diff --git a/src/go/types/testdata/check/issues.go2 b/src/go/types/testdata/check/issues.go2 index a994d73f66..c46a34e2eb 100644 --- a/src/go/types/testdata/check/issues.go2 +++ b/src/go/types/testdata/check/issues.go2 @@ -146,8 +146,8 @@ type List3[TElem any] struct { } // Infinite generic type declarations must lead to an error. -type inf1[T any] struct{ _ inf1 /* ERROR illegal cycle */ [T] } -type inf2[T any] struct{ inf2 /* ERROR illegal cycle */ [T] } +type inf1 /* ERROR illegal cycle */ [T any] struct{ _ inf1[T] } +type inf2 /* ERROR illegal cycle */ [T any] struct{ inf2[T] } // The implementation of conversions T(x) between integers and floating-point // numbers checks that both T and x have either integer or floating-point diff --git a/src/go/types/testdata/fixedbugs/issue39634.go2 b/src/go/types/testdata/fixedbugs/issue39634.go2 index c46d38f8c4..5cff6e7555 100644 --- a/src/go/types/testdata/fixedbugs/issue39634.go2 +++ b/src/go/types/testdata/fixedbugs/issue39634.go2 @@ -37,8 +37,8 @@ func main7() { var _ foo7 = x7[int]{} } // func main8() {} // crash 9 -type foo9[A any] interface { foo9 /* ERROR illegal cycle */ [A] } -func _() { var _ = new(foo9 /* ERROR illegal cycle */ [int]) } +type foo9 /* ERROR illegal cycle */ [A any] interface { foo9[A] } +func _() { var _ = new(foo9[int]) } // crash 12 var u /* ERROR cycle */ , i [func /* ERROR used as value */ /* ERROR used as value */ (u, c /* ERROR undeclared */ /* ERROR undeclared */ ) {}(0, len /* ERROR must be called */ /* ERROR must be called */ )]c /* ERROR undeclared */ /* ERROR undeclared */ diff --git a/src/go/types/testdata/fixedbugs/issue39938.go2 b/src/go/types/testdata/fixedbugs/issue39938.go2 index 0da6e103fd..31bec5fb01 100644 --- a/src/go/types/testdata/fixedbugs/issue39938.go2 +++ b/src/go/types/testdata/fixedbugs/issue39938.go2 @@ -3,6 +3,8 @@ // license that can be found in the LICENSE file. // Check "infinite expansion" cycle errors across instantiated types. +// We can't detect these errors anymore at the moment. See #48962 for +// details. package p @@ -11,11 +13,11 @@ type E1[P any] *P type E2[P any] struct{ _ P } type E3[P any] struct{ _ *P } -type T0 /* ERROR illegal cycle */ struct { +type T0 /* illegal cycle */ struct { _ E0[T0] } -type T0_ /* ERROR illegal cycle */ struct { +type T0_ /* illegal cycle */ struct { E0[T0_] } @@ -23,7 +25,7 @@ type T1 struct { _ E1[T1] } -type T2 /* ERROR illegal cycle */ struct { +type T2 /* illegal cycle */ struct { _ E2[T2] } @@ -33,7 +35,7 @@ type T3 struct { // some more complex cases -type T4 /* ERROR illegal cycle */ struct { +type T4 /* illegal cycle */ struct { _ E0[E2[T4]] } @@ -41,7 +43,7 @@ type T5 struct { _ E0[E2[E0[E1[E2[[10]T5]]]]] } -type T6 /* ERROR illegal cycle */ struct { +type T6 /* illegal cycle */ struct { _ E0[[10]E2[E0[E2[E2[T6]]]]] } diff --git a/src/go/types/testdata/fixedbugs/issue48951.go2 b/src/go/types/testdata/fixedbugs/issue48951.go2 new file mode 100644 index 0000000000..cf02cc130a --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue48951.go2 @@ -0,0 +1,21 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type ( + A1 /* ERROR illegal cycle */ [P any] [10]A1[P] + A2 /* ERROR illegal cycle */ [P any] [10]A2[*P] + A3[P any] [10]*A3[P] + + L1[P any] []L1[P] + + S1 /* ERROR illegal cycle */ [P any] struct{ f S1[P] } + S2 /* ERROR illegal cycle */ [P any] struct{ f S2[*P] } // like example in issue + S3[P any] struct{ f *S3[P] } + + I1 /* ERROR illegal cycle */ [P any] interface{ I1[P] } + I2 /* ERROR illegal cycle */ [P any] interface{ I2[*P] } + I3[P any] interface{ *I3 /* ERROR interface contains type constraints */ [P] } +) -- GitLab From 011fd002457da0823da5f06b099fcf6e21444b00 Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Thu, 5 Aug 2021 11:32:43 -0700 Subject: [PATCH 1596/2500] sync: remove TestWaitGroupMisuse2 and TestWaitGroupMisuse3 These tests are inherently nondeterministic: They exercise a racy code path for up to one million iterations, and require that an error occur at least once. TestWaitGroupMisuse2 in particular is an ongoing source of trybot flakiness. Fixes #38163. Change-Id: Ibbbda2c998c915333487ad262d3df6829de01c2b Reviewed-on: https://go-review.googlesource.com/c/go/+/340249 Trust: Damien Neil Trust: Dmitri Shuralyov Run-TryBot: Damien Neil TryBot-Result: Go Bot Reviewed-by: Dmitry Vyukov --- src/sync/waitgroup_test.go | 126 ------------------------------------- 1 file changed, 126 deletions(-) diff --git a/src/sync/waitgroup_test.go b/src/sync/waitgroup_test.go index c569e0faa2..4ded218d2d 100644 --- a/src/sync/waitgroup_test.go +++ b/src/sync/waitgroup_test.go @@ -5,8 +5,6 @@ package sync_test import ( - "internal/race" - "runtime" . "sync" "sync/atomic" "testing" @@ -48,12 +46,6 @@ func TestWaitGroup(t *testing.T) { } } -func knownRacy(t *testing.T) { - if race.Enabled { - t.Skip("skipping known-racy test under the race detector") - } -} - func TestWaitGroupMisuse(t *testing.T) { defer func() { err := recover() @@ -68,124 +60,6 @@ func TestWaitGroupMisuse(t *testing.T) { t.Fatal("Should panic") } -// pollUntilEqual blocks until v, loaded atomically, is -// equal to the target. -func pollUntilEqual(v *uint32, target uint32) { - for { - for i := 0; i < 1e3; i++ { - if atomic.LoadUint32(v) == target { - return - } - } - // yield to avoid deadlock with the garbage collector - // see issue #20072 - runtime.Gosched() - } -} - -func TestWaitGroupMisuse2(t *testing.T) { - knownRacy(t) - if runtime.NumCPU() <= 4 { - t.Skip("NumCPU<=4, skipping: this test requires parallelism") - } - defer func() { - err := recover() - if err != "sync: negative WaitGroup counter" && - err != "sync: WaitGroup misuse: Add called concurrently with Wait" && - err != "sync: WaitGroup is reused before previous Wait has returned" { - t.Fatalf("Unexpected panic: %#v", err) - } - }() - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) - done := make(chan interface{}, 2) - // The detection is opportunistic, so we want it to panic - // at least in one run out of a million. - for i := 0; i < 1e6; i++ { - var wg WaitGroup - var here uint32 - wg.Add(1) - go func() { - defer func() { - done <- recover() - }() - atomic.AddUint32(&here, 1) - pollUntilEqual(&here, 3) - wg.Wait() - }() - go func() { - defer func() { - done <- recover() - }() - atomic.AddUint32(&here, 1) - pollUntilEqual(&here, 3) - wg.Add(1) // This is the bad guy. - wg.Done() - }() - atomic.AddUint32(&here, 1) - pollUntilEqual(&here, 3) - wg.Done() - for j := 0; j < 2; j++ { - if err := <-done; err != nil { - panic(err) - } - } - } - t.Fatal("Should panic") -} - -func TestWaitGroupMisuse3(t *testing.T) { - knownRacy(t) - if runtime.NumCPU() <= 1 { - t.Skip("NumCPU==1, skipping: this test requires parallelism") - } - defer func() { - err := recover() - if err != "sync: negative WaitGroup counter" && - err != "sync: WaitGroup misuse: Add called concurrently with Wait" && - err != "sync: WaitGroup is reused before previous Wait has returned" { - t.Fatalf("Unexpected panic: %#v", err) - } - }() - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) - done := make(chan interface{}, 3) - // The detection is opportunistically, so we want it to panic - // at least in one run out of a million. - for i := 0; i < 1e6; i++ { - var wg WaitGroup - wg.Add(1) - go func() { - defer func() { - done <- recover() - }() - wg.Done() - }() - go func() { - defer func() { - done <- recover() - }() - wg.Wait() - // Start reusing the wg before waiting for the Wait below to return. - wg.Add(1) - go func() { - wg.Done() - }() - wg.Wait() - }() - go func() { - defer func() { - done <- recover() - }() - wg.Wait() - }() - for j := 0; j < 3; j++ { - if err := <-done; err != nil { - panic(err) - } - } - } - t.Fatal("Should panic") -} - func TestWaitGroupRace(t *testing.T) { // Run this test for about 1ms. for i := 0; i < 1000; i++ { -- GitLab From 765c9116be44641854f580c19e3589d7b86a3d28 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Thu, 30 Sep 2021 14:37:30 -0700 Subject: [PATCH 1597/2500] cmd/go: move module build info formatting into runtime/debug Previously, modload.PackageBuildInfo returned a string containing information about modules used to build an executable. This string is embedded in the binary and can be read with debug.ReadBuildInfo or 'go version -m'. With this change, debug.BuildInfo now has a MarshalText method that returns a string in the same format as modload.PackageBuildInfo. Package.load now calls Package.setBuildInfo, which constructs a debug.BuildInfo, formats it with MarshalText, then sets Package.Internal.BuildInfo. This is equivalent to what modload.PackageBuildInfo did. modload.PackageBuildInfo is deleted, since it's no longer used. For #37475 Change-Id: I5875a98cb64737637fec2a450ab2ffa7f1805707 Reviewed-on: https://go-review.googlesource.com/c/go/+/353886 Trust: Jay Conrod Run-TryBot: Jay Conrod Reviewed-by: Bryan C. Mills --- api/next.txt | 1 + src/cmd/go/internal/load/pkg.go | 83 +++++++++++++++++++++++++++- src/cmd/go/internal/modload/build.go | 48 ---------------- src/runtime/debug/mod.go | 37 +++++++++++++ 4 files changed, 118 insertions(+), 51 deletions(-) diff --git a/api/next.txt b/api/next.txt index 1192fc9069..cb729ea72f 100644 --- a/api/next.txt +++ b/api/next.txt @@ -1,3 +1,4 @@ +pkg runtime/debug, method (*BuildInfo) MarshalText() ([]byte, error) pkg syscall (darwin-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) pkg syscall (darwin-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (darwin-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index a3a8de81c9..a7428ed420 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -21,6 +21,7 @@ import ( pathpkg "path" "path/filepath" "runtime" + "runtime/debug" "sort" "strconv" "strings" @@ -1921,9 +1922,8 @@ func (p *Package) load(ctx context.Context, opts PackageOpts, path string, stk * } p.Internal.Imports = imports p.collectDeps() - - if cfg.ModulesEnabled && p.Error == nil && p.Name == "main" && len(p.DepsErrors) == 0 { - p.Internal.BuildInfo = modload.PackageBuildInfo(pkgPath, p.Deps) + if p.Error == nil && p.Name == "main" && len(p.DepsErrors) == 0 { + p.setBuildInfo() } // unsafe is a fake package. @@ -2195,6 +2195,83 @@ func (p *Package) collectDeps() { } } +// setBuildInfo gathers build information, formats it as a string to be +// embedded in the binary, then sets p.Internal.BuildInfo to that string. +// setBuildInfo should only be called on a main package with no errors. +// +// This information can be retrieved using debug.ReadBuildInfo. +func (p *Package) setBuildInfo() { + setPkgErrorf := func(format string, args ...interface{}) { + if p.Error == nil { + p.Error = &PackageError{Err: fmt.Errorf(format, args...)} + } + } + + var debugModFromModinfo func(*modinfo.ModulePublic) *debug.Module + debugModFromModinfo = func(mi *modinfo.ModulePublic) *debug.Module { + dm := &debug.Module{ + Path: mi.Path, + Version: mi.Version, + } + if mi.Replace != nil { + dm.Replace = debugModFromModinfo(mi.Replace) + } else { + dm.Sum = modfetch.Sum(module.Version{Path: mi.Path, Version: mi.Version}) + } + return dm + } + + var main debug.Module + if p.Module != nil { + main = *debugModFromModinfo(p.Module) + } + + visited := make(map[*Package]bool) + mdeps := make(map[module.Version]*debug.Module) + var q []*Package + q = append(q, p.Internal.Imports...) + for len(q) > 0 { + p1 := q[0] + q = q[1:] + if visited[p1] { + continue + } + visited[p1] = true + if p1.Module != nil { + m := module.Version{Path: p1.Module.Path, Version: p1.Module.Version} + if p1.Module.Path != main.Path && mdeps[m] == nil { + mdeps[m] = debugModFromModinfo(p1.Module) + } + } + q = append(q, p1.Internal.Imports...) + } + sortedMods := make([]module.Version, 0, len(mdeps)) + for mod := range mdeps { + sortedMods = append(sortedMods, mod) + } + module.Sort(sortedMods) + deps := make([]*debug.Module, len(sortedMods)) + for i, mod := range sortedMods { + deps[i] = mdeps[mod] + } + + pkgPath := p.ImportPath + if p.Internal.CmdlineFiles { + pkgPath = "command-line-arguments" + } + info := &debug.BuildInfo{ + Path: pkgPath, + Main: main, + Deps: deps, + } + text, err := info.MarshalText() + if err != nil { + setPkgErrorf("error formatting build info: %v", err) + return + } + p.Internal.BuildInfo = string(text) +} + // SafeArg reports whether arg is a "safe" command-line argument, // meaning that when it appears in a command-line, it probably // doesn't have some special meaning other than its own name. diff --git a/src/cmd/go/internal/modload/build.go b/src/cmd/go/internal/modload/build.go index 8a9792089b..da50743138 100644 --- a/src/cmd/go/internal/modload/build.go +++ b/src/cmd/go/internal/modload/build.go @@ -5,7 +5,6 @@ package modload import ( - "bytes" "context" "encoding/hex" "errors" @@ -336,53 +335,6 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li return info } -// PackageBuildInfo returns a string containing module version information -// for modules providing packages named by path and deps. path and deps must -// name packages that were resolved successfully with LoadPackages. -func PackageBuildInfo(path string, deps []string) string { - if !Enabled() { - return "" - } - target, _ := findModule(loaded, path) - mdeps := make(map[module.Version]bool) - for _, dep := range deps { - if m, ok := findModule(loaded, dep); ok { - mdeps[m] = true - } - } - var mods []module.Version - delete(mdeps, target) - for mod := range mdeps { - mods = append(mods, mod) - } - module.Sort(mods) - - var buf bytes.Buffer - fmt.Fprintf(&buf, "path\t%s\n", path) - - writeEntry := func(token string, m module.Version) { - mv := m.Version - if mv == "" { - mv = "(devel)" - } - fmt.Fprintf(&buf, "%s\t%s\t%s", token, m.Path, mv) - if r, _ := Replacement(m); r.Path == "" { - fmt.Fprintf(&buf, "\t%s\n", modfetch.Sum(m)) - } else { - fmt.Fprintf(&buf, "\n=>\t%s\t%s\t%s\n", r.Path, r.Version, modfetch.Sum(r)) - } - } - - if target.Path != "" { - writeEntry("mod", target) - } - for _, mod := range mods { - writeEntry("dep", mod) - } - - return buf.String() -} - // findModule searches for the module that contains the package at path. // If the package was loaded, its containing module and true are returned. // Otherwise, module.Version{} and false are returned. diff --git a/src/runtime/debug/mod.go b/src/runtime/debug/mod.go index 05cad61155..11f995ba75 100644 --- a/src/runtime/debug/mod.go +++ b/src/runtime/debug/mod.go @@ -5,6 +5,8 @@ package debug import ( + "bytes" + "fmt" "strings" ) @@ -34,6 +36,41 @@ type Module struct { Replace *Module // replaced by this module } +func (bi *BuildInfo) MarshalText() ([]byte, error) { + buf := &bytes.Buffer{} + if bi.Path != "" { + fmt.Fprintf(buf, "path\t%s\n", bi.Path) + } + var formatMod func(string, Module) + formatMod = func(word string, m Module) { + buf.WriteString(word) + buf.WriteByte('\t') + buf.WriteString(m.Path) + mv := m.Version + if mv == "" { + mv = "(devel)" + } + buf.WriteByte('\t') + buf.WriteString(mv) + if m.Replace == nil { + buf.WriteByte('\t') + buf.WriteString(m.Sum) + } else { + buf.WriteByte('\n') + formatMod("=>", *m.Replace) + } + buf.WriteByte('\n') + } + if bi.Main.Path != "" { + formatMod("mod", bi.Main) + } + for _, dep := range bi.Deps { + formatMod("dep", *dep) + } + + return buf.Bytes(), nil +} + func readBuildInfo(data string) (*BuildInfo, bool) { if len(data) < 32 { return nil, false -- GitLab From 434cdd0337b9e6c7e0c369c9293cc14fd38dc80d Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Thu, 30 Sep 2021 10:25:49 -0700 Subject: [PATCH 1598/2500] debug/buildinfo: new package with Read and ReadFile These functions provide access to module information stamped into Go binaries. In the future, they'll provide access to other information (like VCS info). These functions are added in a new package instead of runtime/debug since they use binary parsing packages like debug/elf, which would make runtime/debug an unacceptably heavy dependency. The types in runtime/debug are still used; debug/buildinfo uses them via type aliases. This information is already available for the running binary through debug.ReadBuildInfo and for other binaries with 'go version -m', but until now, there hasn't been a way to get it for other binaries without installing cmd/go. This change copies most of the code in cmd/go/internal/version. A later CL will migrate 'go version -m' to use this package. For #37475 Fixes #39301 Change-Id: I0fbe0896e04f12ef81c6d79fb61b20daede86159 Reviewed-on: https://go-review.googlesource.com/c/go/+/353887 Trust: Jay Conrod Run-TryBot: Jay Conrod Reviewed-by: Bryan C. Mills --- api/next.txt | 4 + src/debug/buildinfo/buildinfo.go | 374 ++++++++++++++++++++++++++ src/debug/buildinfo/buildinfo_test.go | 206 ++++++++++++++ src/go/build/deps_test.go | 5 +- src/runtime/debug/mod.go | 104 +++---- 5 files changed, 645 insertions(+), 48 deletions(-) create mode 100644 src/debug/buildinfo/buildinfo.go create mode 100644 src/debug/buildinfo/buildinfo_test.go diff --git a/api/next.txt b/api/next.txt index cb729ea72f..0a976d7b19 100644 --- a/api/next.txt +++ b/api/next.txt @@ -1,4 +1,8 @@ +pkg debug/buildinfo, func Read(io.ReaderAt) (*debug.BuildInfo, error) +pkg debug/buildinfo, func ReadFile(string) (*debug.BuildInfo, error) +pkg debug/buildinfo, type BuildInfo = debug.BuildInfo pkg runtime/debug, method (*BuildInfo) MarshalText() ([]byte, error) +pkg runtime/debug, method (*BuildInfo) UnmarshalText() ([]byte, error) pkg syscall (darwin-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) pkg syscall (darwin-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (darwin-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error diff --git a/src/debug/buildinfo/buildinfo.go b/src/debug/buildinfo/buildinfo.go new file mode 100644 index 0000000000..8def2eae6e --- /dev/null +++ b/src/debug/buildinfo/buildinfo.go @@ -0,0 +1,374 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package buildinfo provides access to information embedded in a Go binary +// about how it was built. This includes the Go toolchain version, and the +// set of modules used (for binaries built in module mode). +// +// Build information is available for the currently running binary in +// runtime/debug.ReadBuildInfo. +package buildinfo + +import ( + "bytes" + "debug/elf" + "debug/macho" + "debug/pe" + "encoding/binary" + "errors" + "fmt" + "internal/xcoff" + "io" + "io/fs" + "os" + "runtime/debug" +) + +// Type alias for build info. We cannot move the types here, since +// runtime/debug would need to import this package, which would make it +// a much larger dependency. +type BuildInfo = debug.BuildInfo + +var ( + // errUnrecognizedFormat is returned when a given executable file doesn't + // appear to be in a known format, or it breaks the rules of that format, + // or when there are I/O errors reading the file. + errUnrecognizedFormat = errors.New("unrecognized file format") + + // errNotGoExe is returned when a given executable file is valid but does + // not contain Go build information. + errNotGoExe = errors.New("not a Go executable") + + // The build info blob left by the linker is identified by + // a 16-byte header, consisting of buildInfoMagic (14 bytes), + // the binary's pointer size (1 byte), + // and whether the binary is big endian (1 byte). + buildInfoMagic = []byte("\xff Go buildinf:") +) + +// ReadFile returns build information embedded in a Go binary +// file at the given path. Most information is only available for binaries built +// with module support. +func ReadFile(name string) (info *BuildInfo, err error) { + defer func() { + if pathErr := (*fs.PathError)(nil); errors.As(err, &pathErr) { + err = fmt.Errorf("could not read Go build info: %w", err) + } else if err != nil { + err = fmt.Errorf("could not read Go build info from %s: %w", name, err) + } + }() + + f, err := os.Open(name) + if err != nil { + return nil, err + } + defer f.Close() + return Read(f) +} + +// Read returns build information embedded in a Go binary file +// accessed through the given ReaderAt. Most information is only available for +// binaries built with module support. +func Read(r io.ReaderAt) (*BuildInfo, error) { + _, mod, err := readRawBuildInfo(r) + if err != nil { + return nil, err + } + bi := &BuildInfo{} + if err := bi.UnmarshalText([]byte(mod)); err != nil { + return nil, err + } + return bi, nil +} + +type exe interface { + // ReadData reads and returns up to size bytes starting at virtual address addr. + ReadData(addr, size uint64) ([]byte, error) + + // DataStart returns the virtual address of the segment or section that + // should contain build information. This is either a specially named section + // or the first writable non-zero data segment. + DataStart() uint64 +} + +// readRawBuildInfo extracts the Go toolchain version and module information +// strings from a Go binary. On success, vers should be non-empty. mod +// is empty if the binary was not built with modules enabled. +func readRawBuildInfo(r io.ReaderAt) (vers, mod string, err error) { + // Read the first bytes of the file to identify the format, then delegate to + // a format-specific function to load segment and section headers. + ident := make([]byte, 16) + if n, err := r.ReadAt(ident, 0); n < len(ident) || err != nil { + return "", "", errUnrecognizedFormat + } + + var x exe + switch { + case bytes.HasPrefix(ident, []byte("\x7FELF")): + f, err := elf.NewFile(r) + if err != nil { + return "", "", errUnrecognizedFormat + } + x = &elfExe{f} + case bytes.HasPrefix(ident, []byte("MZ")): + f, err := pe.NewFile(r) + if err != nil { + return "", "", errUnrecognizedFormat + } + x = &peExe{f} + case bytes.HasPrefix(ident, []byte("\xFE\xED\xFA")) || bytes.HasPrefix(ident[1:], []byte("\xFA\xED\xFE")): + f, err := macho.NewFile(r) + if err != nil { + return "", "", errUnrecognizedFormat + } + x = &machoExe{f} + case bytes.HasPrefix(ident, []byte{0x01, 0xDF}) || bytes.HasPrefix(ident, []byte{0x01, 0xF7}): + f, err := xcoff.NewFile(r) + if err != nil { + return "", "", errUnrecognizedFormat + } + x = &xcoffExe{f} + default: + return "", "", errUnrecognizedFormat + } + + // Read the first 64kB of dataAddr to find the build info blob. + // On some platforms, the blob will be in its own section, and DataStart + // returns the address of that section. On others, it's somewhere in the + // data segment; the linker puts it near the beginning. + // See cmd/link/internal/ld.Link.buildinfo. + dataAddr := x.DataStart() + data, err := x.ReadData(dataAddr, 64*1024) + if err != nil { + return "", "", err + } + const ( + buildInfoAlign = 16 + buildinfoSize = 32 + ) + for ; !bytes.HasPrefix(data, buildInfoMagic); data = data[buildInfoAlign:] { + if len(data) < 32 { + return "", "", errNotGoExe + } + } + + // Decode the blob. + // The first 14 bytes are buildInfoMagic. + // The next two bytes indicate pointer size in bytes (4 or 8) and endianness + // (0 for little, 1 for big). + // Two virtual addresses to Go strings follow that: runtime.buildVersion, + // and runtime.modinfo. + // On 32-bit platforms, the last 8 bytes are unused. + ptrSize := int(data[14]) + bigEndian := data[15] != 0 + var bo binary.ByteOrder + if bigEndian { + bo = binary.BigEndian + } else { + bo = binary.LittleEndian + } + var readPtr func([]byte) uint64 + if ptrSize == 4 { + readPtr = func(b []byte) uint64 { return uint64(bo.Uint32(b)) } + } else { + readPtr = bo.Uint64 + } + vers = readString(x, ptrSize, readPtr, readPtr(data[16:])) + if vers == "" { + return "", "", errNotGoExe + } + mod = readString(x, ptrSize, readPtr, readPtr(data[16+ptrSize:])) + if len(mod) >= 33 && mod[len(mod)-17] == '\n' { + // Strip module framing: sentinel strings delimiting the module info. + // These are cmd/go/internal/modload.infoStart and infoEnd. + mod = mod[16 : len(mod)-16] + } else { + mod = "" + } + + return vers, mod, nil +} + +// readString returns the string at address addr in the executable x. +func readString(x exe, ptrSize int, readPtr func([]byte) uint64, addr uint64) string { + hdr, err := x.ReadData(addr, uint64(2*ptrSize)) + if err != nil || len(hdr) < 2*ptrSize { + return "" + } + dataAddr := readPtr(hdr) + dataLen := readPtr(hdr[ptrSize:]) + data, err := x.ReadData(dataAddr, dataLen) + if err != nil || uint64(len(data)) < dataLen { + return "" + } + return string(data) +} + +// elfExe is the ELF implementation of the exe interface. +type elfExe struct { + f *elf.File +} + +func (x *elfExe) ReadData(addr, size uint64) ([]byte, error) { + for _, prog := range x.f.Progs { + if prog.Vaddr <= addr && addr <= prog.Vaddr+prog.Filesz-1 { + n := prog.Vaddr + prog.Filesz - addr + if n > size { + n = size + } + data := make([]byte, n) + _, err := prog.ReadAt(data, int64(addr-prog.Vaddr)) + if err != nil { + return nil, err + } + return data, nil + } + } + return nil, errUnrecognizedFormat +} + +func (x *elfExe) DataStart() uint64 { + for _, s := range x.f.Sections { + if s.Name == ".go.buildinfo" { + return s.Addr + } + } + for _, p := range x.f.Progs { + if p.Type == elf.PT_LOAD && p.Flags&(elf.PF_X|elf.PF_W) == elf.PF_W { + return p.Vaddr + } + } + return 0 +} + +// peExe is the PE (Windows Portable Executable) implementation of the exe interface. +type peExe struct { + f *pe.File +} + +func (x *peExe) imageBase() uint64 { + switch oh := x.f.OptionalHeader.(type) { + case *pe.OptionalHeader32: + return uint64(oh.ImageBase) + case *pe.OptionalHeader64: + return oh.ImageBase + } + return 0 +} + +func (x *peExe) ReadData(addr, size uint64) ([]byte, error) { + addr -= x.imageBase() + for _, sect := range x.f.Sections { + if uint64(sect.VirtualAddress) <= addr && addr <= uint64(sect.VirtualAddress+sect.Size-1) { + n := uint64(sect.VirtualAddress+sect.Size) - addr + if n > size { + n = size + } + data := make([]byte, n) + _, err := sect.ReadAt(data, int64(addr-uint64(sect.VirtualAddress))) + if err != nil { + return nil, errUnrecognizedFormat + } + return data, nil + } + } + return nil, errUnrecognizedFormat +} + +func (x *peExe) DataStart() uint64 { + // Assume data is first writable section. + const ( + IMAGE_SCN_CNT_CODE = 0x00000020 + IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040 + IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080 + IMAGE_SCN_MEM_EXECUTE = 0x20000000 + IMAGE_SCN_MEM_READ = 0x40000000 + IMAGE_SCN_MEM_WRITE = 0x80000000 + IMAGE_SCN_MEM_DISCARDABLE = 0x2000000 + IMAGE_SCN_LNK_NRELOC_OVFL = 0x1000000 + IMAGE_SCN_ALIGN_32BYTES = 0x600000 + ) + for _, sect := range x.f.Sections { + if sect.VirtualAddress != 0 && sect.Size != 0 && + sect.Characteristics&^IMAGE_SCN_ALIGN_32BYTES == IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE { + return uint64(sect.VirtualAddress) + x.imageBase() + } + } + return 0 +} + +// machoExe is the Mach-O (Apple macOS/iOS) implementation of the exe interface. +type machoExe struct { + f *macho.File +} + +func (x *machoExe) ReadData(addr, size uint64) ([]byte, error) { + for _, load := range x.f.Loads { + seg, ok := load.(*macho.Segment) + if !ok { + continue + } + if seg.Addr <= addr && addr <= seg.Addr+seg.Filesz-1 { + if seg.Name == "__PAGEZERO" { + continue + } + n := seg.Addr + seg.Filesz - addr + if n > size { + n = size + } + data := make([]byte, n) + _, err := seg.ReadAt(data, int64(addr-seg.Addr)) + if err != nil { + return nil, err + } + return data, nil + } + } + return nil, errUnrecognizedFormat +} + +func (x *machoExe) DataStart() uint64 { + // Look for section named "__go_buildinfo". + for _, sec := range x.f.Sections { + if sec.Name == "__go_buildinfo" { + return sec.Addr + } + } + // Try the first non-empty writable segment. + const RW = 3 + for _, load := range x.f.Loads { + seg, ok := load.(*macho.Segment) + if ok && seg.Addr != 0 && seg.Filesz != 0 && seg.Prot == RW && seg.Maxprot == RW { + return seg.Addr + } + } + return 0 +} + +// xcoffExe is the XCOFF (AIX eXtended COFF) implementation of the exe interface. +type xcoffExe struct { + f *xcoff.File +} + +func (x *xcoffExe) ReadData(addr, size uint64) ([]byte, error) { + for _, sect := range x.f.Sections { + if uint64(sect.VirtualAddress) <= addr && addr <= uint64(sect.VirtualAddress+sect.Size-1) { + n := uint64(sect.VirtualAddress+sect.Size) - addr + if n > size { + n = size + } + data := make([]byte, n) + _, err := sect.ReadAt(data, int64(addr-uint64(sect.VirtualAddress))) + if err != nil { + return nil, err + } + return data, nil + } + } + return nil, fmt.Errorf("address not mapped") +} + +func (x *xcoffExe) DataStart() uint64 { + return x.f.SectionByType(xcoff.STYP_DATA).VirtualAddress +} diff --git a/src/debug/buildinfo/buildinfo_test.go b/src/debug/buildinfo/buildinfo_test.go new file mode 100644 index 0000000000..765bf24627 --- /dev/null +++ b/src/debug/buildinfo/buildinfo_test.go @@ -0,0 +1,206 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package buildinfo_test + +import ( + "bytes" + "debug/buildinfo" + "flag" + "internal/testenv" + "os" + "os/exec" + "path" + "path/filepath" + "runtime" + "strings" + "testing" +) + +var flagAll = flag.Bool("all", false, "test all supported GOOS/GOARCH platforms, instead of only the current platform") + +// TestReadFile confirms that ReadFile can read build information from binaries +// on supported target platforms. It builds a trivial binary on the current +// platforms (or all platforms if -all is set) in various configurations and +// checks that build information can or cannot be read. +func TestReadFile(t *testing.T) { + if testing.Short() { + t.Skip("test requires compiling and linking, which may be slow") + } + testenv.MustHaveGoBuild(t) + + type platform struct{ goos, goarch string } + platforms := []platform{ + {"aix", "ppc64"}, + {"darwin", "amd64"}, + {"darwin", "arm64"}, + {"linux", "386"}, + {"linux", "amd64"}, + {"windows", "386"}, + {"windows", "amd64"}, + } + runtimePlatform := platform{runtime.GOOS, runtime.GOARCH} + haveRuntimePlatform := false + for _, p := range platforms { + if p == runtimePlatform { + haveRuntimePlatform = true + break + } + } + if !haveRuntimePlatform { + platforms = append(platforms, runtimePlatform) + } + + buildWithModules := func(t *testing.T, goos, goarch string) string { + dir := t.TempDir() + gomodPath := filepath.Join(dir, "go.mod") + gomodData := []byte("module example.com/m\ngo 1.18\n") + if err := os.WriteFile(gomodPath, gomodData, 0666); err != nil { + t.Fatal(err) + } + helloPath := filepath.Join(dir, "hello.go") + helloData := []byte("package main\nfunc main() {}\n") + if err := os.WriteFile(helloPath, helloData, 0666); err != nil { + t.Fatal(err) + } + outPath := filepath.Join(dir, path.Base(t.Name())) + cmd := exec.Command("go", "build", "-o="+outPath) + cmd.Dir = dir + cmd.Env = append(os.Environ(), "GO111MODULE=on", "GOOS="+goos, "GOARCH="+goarch) + stderr := &bytes.Buffer{} + cmd.Stderr = stderr + if err := cmd.Run(); err != nil { + t.Fatalf("failed building test file: %v\n%s", err, stderr.Bytes()) + } + return outPath + } + + buildWithGOPATH := func(t *testing.T, goos, goarch string) string { + gopathDir := t.TempDir() + pkgDir := filepath.Join(gopathDir, "src/example.com/m") + if err := os.MkdirAll(pkgDir, 0777); err != nil { + t.Fatal(err) + } + helloPath := filepath.Join(pkgDir, "hello.go") + helloData := []byte("package main\nfunc main() {}\n") + if err := os.WriteFile(helloPath, helloData, 0666); err != nil { + t.Fatal(err) + } + outPath := filepath.Join(gopathDir, path.Base(t.Name())) + cmd := exec.Command("go", "build", "-o="+outPath) + cmd.Dir = pkgDir + cmd.Env = append(os.Environ(), "GO111MODULE=off", "GOPATH="+gopathDir, "GOOS="+goos, "GOARCH="+goarch) + stderr := &bytes.Buffer{} + cmd.Stderr = stderr + if err := cmd.Run(); err != nil { + t.Fatalf("failed building test file: %v\n%s", err, stderr.Bytes()) + } + return outPath + } + + damageBuildInfo := func(t *testing.T, name string) { + data, err := os.ReadFile(name) + if err != nil { + t.Fatal(err) + } + i := bytes.Index(data, []byte("\xff Go buildinf:")) + if i < 0 { + t.Fatal("Go buildinf not found") + } + data[i+2] = 'N' + if err := os.WriteFile(name, data, 0666); err != nil { + t.Fatal(err) + } + } + + cases := []struct { + name string + build func(t *testing.T, goos, goarch string) string + want string + wantErr string + }{ + { + name: "doesnotexist", + build: func(t *testing.T, goos, goarch string) string { + return "doesnotexist.txt" + }, + wantErr: "doesnotexist", + }, + { + name: "empty", + build: func(t *testing.T, _, _ string) string { + dir := t.TempDir() + name := filepath.Join(dir, "empty") + if err := os.WriteFile(name, nil, 0666); err != nil { + t.Fatal(err) + } + return name + }, + wantErr: "unrecognized file format", + }, + { + name: "valid_modules", + build: buildWithModules, + want: "path\texample.com/m\n" + + "mod\texample.com/m\t(devel)\t\n", + }, + { + name: "invalid_modules", + build: func(t *testing.T, goos, goarch string) string { + name := buildWithModules(t, goos, goarch) + damageBuildInfo(t, name) + return name + }, + wantErr: "not a Go executable", + }, + { + name: "valid_gopath", + build: buildWithGOPATH, + want: "", + }, + { + name: "invalid_gopath", + build: func(t *testing.T, goos, goarch string) string { + name := buildWithGOPATH(t, goos, goarch) + damageBuildInfo(t, name) + return name + }, + wantErr: "not a Go executable", + }, + } + + for _, p := range platforms { + p := p + t.Run(p.goos+"_"+p.goarch, func(t *testing.T) { + if p != runtimePlatform && !*flagAll { + t.Skipf("skipping platforms other than %s_%s because -all was not set", runtimePlatform.goos, runtimePlatform.goarch) + } + for _, tc := range cases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + name := tc.build(t, p.goos, p.goarch) + if info, err := buildinfo.ReadFile(name); err != nil { + if tc.wantErr == "" { + t.Fatalf("unexpected error: %v", err) + } else if errMsg := err.Error(); !strings.Contains(errMsg, tc.wantErr) { + t.Fatalf("got error %q; want error containing %q", errMsg, tc.wantErr) + } + } else { + if tc.wantErr != "" { + t.Fatalf("unexpected success; want error containing %q", tc.wantErr) + } else if got, err := info.MarshalText(); err != nil { + t.Fatalf("unexpected error marshaling BuildInfo: %v", err) + } else { + got := string(got) + if got != tc.want { + t.Fatalf("got:\n%s\nwant:\n%s", got, tc.want) + } + } + } + }) + } + }) + } +} diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 07fbc8b023..a92bb3893b 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -214,7 +214,6 @@ var depsRules = ` mime/quotedprintable, net/internal/socktest, net/url, - runtime/debug, runtime/trace, text/scanner, text/tabwriter; @@ -271,8 +270,10 @@ var depsRules = ` # executable parsing FMT, encoding/binary, compress/zlib + < runtime/debug < debug/dwarf < debug/elf, debug/gosym, debug/macho, debug/pe, debug/plan9obj, internal/xcoff + < debug/buildinfo < DEBUG; # go parser and friends. @@ -510,7 +511,7 @@ var depsRules = ` FMT, flag, math/rand < testing/quick; - FMT, flag, runtime/debug, runtime/trace, internal/sysinfo, math/rand + FMT, DEBUG, flag, runtime/trace, internal/sysinfo, math/rand < testing; FMT, crypto/sha256, encoding/json, go/ast, go/parser, go/token, math/rand, encoding/hex, crypto/sha256 diff --git a/src/runtime/debug/mod.go b/src/runtime/debug/mod.go index 11f995ba75..8c6c48089b 100644 --- a/src/runtime/debug/mod.go +++ b/src/runtime/debug/mod.go @@ -7,7 +7,6 @@ package debug import ( "bytes" "fmt" - "strings" ) // exported from runtime @@ -17,11 +16,19 @@ func modinfo() string // in the running binary. The information is available only // in binaries built with module support. func ReadBuildInfo() (info *BuildInfo, ok bool) { - return readBuildInfo(modinfo()) + data := modinfo() + if len(data) < 32 { + return nil, false + } + data = data[16 : len(data)-16] + bi := &BuildInfo{} + if err := bi.UnmarshalText([]byte(data)); err != nil { + return nil, false + } + return bi, true } -// BuildInfo represents the build information read from -// the running binary. +// BuildInfo represents the build information read from a Go binary. type BuildInfo struct { Path string // The main package path Main Module // The module containing the main package @@ -71,80 +78,85 @@ func (bi *BuildInfo) MarshalText() ([]byte, error) { return buf.Bytes(), nil } -func readBuildInfo(data string) (*BuildInfo, bool) { - if len(data) < 32 { - return nil, false - } - data = data[16 : len(data)-16] +func (bi *BuildInfo) UnmarshalText(data []byte) (err error) { + *bi = BuildInfo{} + lineNum := 1 + defer func() { + if err != nil { + err = fmt.Errorf("could not parse Go build info: line %d: %w", lineNum, err) + } + }() - const ( - pathLine = "path\t" - modLine = "mod\t" - depLine = "dep\t" - repLine = "=>\t" + var ( + pathLine = []byte("path\t") + modLine = []byte("mod\t") + depLine = []byte("dep\t") + repLine = []byte("=>\t") + newline = []byte("\n") + tab = []byte("\t") ) - readEntryFirstLine := func(elem []string) (Module, bool) { + readModuleLine := func(elem [][]byte) (Module, error) { if len(elem) != 2 && len(elem) != 3 { - return Module{}, false + return Module{}, fmt.Errorf("expected 2 or 3 columns; got %d", len(elem)) } sum := "" if len(elem) == 3 { - sum = elem[2] + sum = string(elem[2]) } return Module{ - Path: elem[0], - Version: elem[1], + Path: string(elem[0]), + Version: string(elem[1]), Sum: sum, - }, true + }, nil } var ( - info = &BuildInfo{} last *Module - line string + line []byte ok bool ) - // Reverse of cmd/go/internal/modload.PackageBuildInfo + // Reverse of BuildInfo.String() for len(data) > 0 { - line, data, ok = strings.Cut(data, "\n") + line, data, ok = bytes.Cut(data, newline) if !ok { break } switch { - case strings.HasPrefix(line, pathLine): + case bytes.HasPrefix(line, pathLine): elem := line[len(pathLine):] - info.Path = elem - case strings.HasPrefix(line, modLine): - elem := strings.Split(line[len(modLine):], "\t") - last = &info.Main - *last, ok = readEntryFirstLine(elem) - if !ok { - return nil, false + bi.Path = string(elem) + case bytes.HasPrefix(line, modLine): + elem := bytes.Split(line[len(modLine):], tab) + last = &bi.Main + *last, err = readModuleLine(elem) + if err != nil { + return err } - case strings.HasPrefix(line, depLine): - elem := strings.Split(line[len(depLine):], "\t") + case bytes.HasPrefix(line, depLine): + elem := bytes.Split(line[len(depLine):], tab) last = new(Module) - info.Deps = append(info.Deps, last) - *last, ok = readEntryFirstLine(elem) - if !ok { - return nil, false + bi.Deps = append(bi.Deps, last) + *last, err = readModuleLine(elem) + if err != nil { + return err } - case strings.HasPrefix(line, repLine): - elem := strings.Split(line[len(repLine):], "\t") + case bytes.HasPrefix(line, repLine): + elem := bytes.Split(line[len(repLine):], tab) if len(elem) != 3 { - return nil, false + return fmt.Errorf("expected 3 columns for replacement; got %d", len(elem)) } if last == nil { - return nil, false + return fmt.Errorf("replacement with no module on previous line") } last.Replace = &Module{ - Path: elem[0], - Version: elem[1], - Sum: elem[2], + Path: string(elem[0]), + Version: string(elem[1]), + Sum: string(elem[2]), } last = nil } + lineNum++ } - return info, true + return nil } -- GitLab From 85a068fdf21bd2e4475a87ee049af4fbe797bcbe Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Thu, 30 Sep 2021 10:46:03 -0700 Subject: [PATCH 1599/2500] runtime/debug: add GoVersion to BuildInfo BuildInfo now includes the version of Go used to build a binary, as reported by runtime.Version() or 'go version'. For #37475 Change-Id: Id07dda357dc70599d64a9202dab894c7288de1de Reviewed-on: https://go-review.googlesource.com/c/go/+/353888 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- api/next.txt | 1 + src/cmd/go/internal/load/pkg.go | 3 +++ src/debug/buildinfo/buildinfo.go | 3 ++- src/debug/buildinfo/buildinfo_test.go | 7 ++++--- src/runtime/debug/mod.go | 20 ++++++++++++++++---- 5 files changed, 26 insertions(+), 8 deletions(-) diff --git a/api/next.txt b/api/next.txt index 0a976d7b19..ced738e480 100644 --- a/api/next.txt +++ b/api/next.txt @@ -3,6 +3,7 @@ pkg debug/buildinfo, func ReadFile(string) (*debug.BuildInfo, error) pkg debug/buildinfo, type BuildInfo = debug.BuildInfo pkg runtime/debug, method (*BuildInfo) MarshalText() ([]byte, error) pkg runtime/debug, method (*BuildInfo) UnmarshalText() ([]byte, error) +pkg runtime/debug, type BuildInfo struct, GoVersion string pkg syscall (darwin-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) pkg syscall (darwin-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (darwin-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index a7428ed420..0fc5afbc36 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -2200,6 +2200,9 @@ func (p *Package) collectDeps() { // setBuildInfo should only be called on a main package with no errors. // // This information can be retrieved using debug.ReadBuildInfo. +// +// Note that the GoVersion field is not set here to avoid encoding it twice. +// It is stored separately in the binary, mostly for historical reasons. func (p *Package) setBuildInfo() { setPkgErrorf := func(format string, args ...interface{}) { if p.Error == nil { diff --git a/src/debug/buildinfo/buildinfo.go b/src/debug/buildinfo/buildinfo.go index 8def2eae6e..f84429a342 100644 --- a/src/debug/buildinfo/buildinfo.go +++ b/src/debug/buildinfo/buildinfo.go @@ -71,7 +71,7 @@ func ReadFile(name string) (info *BuildInfo, err error) { // accessed through the given ReaderAt. Most information is only available for // binaries built with module support. func Read(r io.ReaderAt) (*BuildInfo, error) { - _, mod, err := readRawBuildInfo(r) + vers, mod, err := readRawBuildInfo(r) if err != nil { return nil, err } @@ -79,6 +79,7 @@ func Read(r io.ReaderAt) (*BuildInfo, error) { if err := bi.UnmarshalText([]byte(mod)); err != nil { return nil, err } + bi.GoVersion = vers return bi, nil } diff --git a/src/debug/buildinfo/buildinfo_test.go b/src/debug/buildinfo/buildinfo_test.go index 765bf24627..ab307d75c2 100644 --- a/src/debug/buildinfo/buildinfo_test.go +++ b/src/debug/buildinfo/buildinfo_test.go @@ -142,7 +142,8 @@ func TestReadFile(t *testing.T) { { name: "valid_modules", build: buildWithModules, - want: "path\texample.com/m\n" + + want: "go\t$GOVERSION\n" + + "path\texample.com/m\n" + "mod\texample.com/m\t(devel)\t\n", }, { @@ -157,7 +158,7 @@ func TestReadFile(t *testing.T) { { name: "valid_gopath", build: buildWithGOPATH, - want: "", + want: "go\t$GOVERSION\n", }, { name: "invalid_gopath", @@ -193,7 +194,7 @@ func TestReadFile(t *testing.T) { } else if got, err := info.MarshalText(); err != nil { t.Fatalf("unexpected error marshaling BuildInfo: %v", err) } else { - got := string(got) + got := strings.ReplaceAll(string(got), runtime.Version(), "$GOVERSION") if got != tc.want { t.Fatalf("got:\n%s\nwant:\n%s", got, tc.want) } diff --git a/src/runtime/debug/mod.go b/src/runtime/debug/mod.go index 8c6c48089b..0c6488753b 100644 --- a/src/runtime/debug/mod.go +++ b/src/runtime/debug/mod.go @@ -7,6 +7,7 @@ package debug import ( "bytes" "fmt" + "runtime" ) // exported from runtime @@ -25,14 +26,22 @@ func ReadBuildInfo() (info *BuildInfo, ok bool) { if err := bi.UnmarshalText([]byte(data)); err != nil { return nil, false } + + // The go version is stored separately from other build info, mostly for + // historical reasons. It is not part of the modinfo() string, and + // ParseBuildInfo does not recognize it. We inject it here to hide this + // awkwardness from the user. + bi.GoVersion = runtime.Version() + return bi, true } // BuildInfo represents the build information read from a Go binary. type BuildInfo struct { - Path string // The main package path - Main Module // The module containing the main package - Deps []*Module // Module dependencies + GoVersion string // Version of Go that produced this binary. + Path string // The main package path + Main Module // The module containing the main package + Deps []*Module // Module dependencies } // Module represents a module. @@ -45,6 +54,9 @@ type Module struct { func (bi *BuildInfo) MarshalText() ([]byte, error) { buf := &bytes.Buffer{} + if bi.GoVersion != "" { + fmt.Fprintf(buf, "go\t%s\n", bi.GoVersion) + } if bi.Path != "" { fmt.Fprintf(buf, "path\t%s\n", bi.Path) } @@ -116,7 +128,7 @@ func (bi *BuildInfo) UnmarshalText(data []byte) (err error) { line []byte ok bool ) - // Reverse of BuildInfo.String() + // Reverse of BuildInfo.String(), except for go version. for len(data) > 0 { line, data, ok = bytes.Cut(data, newline) if !ok { -- GitLab From a8c5a994d62cc920c134426f7eae892b013ee32d Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Thu, 30 Sep 2021 13:16:33 -0700 Subject: [PATCH 1600/2500] cmd/go: migrate 'go version' to use buildinfo.ReadFile The same code was copied into debug/buildinfo. 'go version' doesn't need its own copy. For #37475 Change-Id: I9e473ce574139a87a5f9c63229f0fc7ffac447a0 Reviewed-on: https://go-review.googlesource.com/c/go/+/353929 Trust: Jay Conrod Run-TryBot: Jay Conrod Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/version/exe.go | 263 ------------------------- src/cmd/go/internal/version/version.go | 92 ++------- 2 files changed, 14 insertions(+), 341 deletions(-) delete mode 100644 src/cmd/go/internal/version/exe.go diff --git a/src/cmd/go/internal/version/exe.go b/src/cmd/go/internal/version/exe.go deleted file mode 100644 index 0e7deef149..0000000000 --- a/src/cmd/go/internal/version/exe.go +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package version - -import ( - "bytes" - "debug/elf" - "debug/macho" - "debug/pe" - "fmt" - "internal/xcoff" - "io" - "os" -) - -// An exe is a generic interface to an OS executable (ELF, Mach-O, PE, XCOFF). -type exe interface { - // Close closes the underlying file. - Close() error - - // ReadData reads and returns up to size byte starting at virtual address addr. - ReadData(addr, size uint64) ([]byte, error) - - // DataStart returns the writable data segment start address. - DataStart() uint64 -} - -// openExe opens file and returns it as an exe. -func openExe(file string) (exe, error) { - f, err := os.Open(file) - if err != nil { - return nil, err - } - data := make([]byte, 16) - if _, err := io.ReadFull(f, data); err != nil { - return nil, err - } - f.Seek(0, 0) - if bytes.HasPrefix(data, []byte("\x7FELF")) { - e, err := elf.NewFile(f) - if err != nil { - f.Close() - return nil, err - } - return &elfExe{f, e}, nil - } - if bytes.HasPrefix(data, []byte("MZ")) { - e, err := pe.NewFile(f) - if err != nil { - f.Close() - return nil, err - } - return &peExe{f, e}, nil - } - if bytes.HasPrefix(data, []byte("\xFE\xED\xFA")) || bytes.HasPrefix(data[1:], []byte("\xFA\xED\xFE")) { - e, err := macho.NewFile(f) - if err != nil { - f.Close() - return nil, err - } - return &machoExe{f, e}, nil - } - if bytes.HasPrefix(data, []byte{0x01, 0xDF}) || bytes.HasPrefix(data, []byte{0x01, 0xF7}) { - e, err := xcoff.NewFile(f) - if err != nil { - f.Close() - return nil, err - } - return &xcoffExe{f, e}, nil - - } - return nil, fmt.Errorf("unrecognized executable format") -} - -// elfExe is the ELF implementation of the exe interface. -type elfExe struct { - os *os.File - f *elf.File -} - -func (x *elfExe) Close() error { - return x.os.Close() -} - -func (x *elfExe) ReadData(addr, size uint64) ([]byte, error) { - for _, prog := range x.f.Progs { - if prog.Vaddr <= addr && addr <= prog.Vaddr+prog.Filesz-1 { - n := prog.Vaddr + prog.Filesz - addr - if n > size { - n = size - } - data := make([]byte, n) - _, err := prog.ReadAt(data, int64(addr-prog.Vaddr)) - if err != nil { - return nil, err - } - return data, nil - } - } - return nil, fmt.Errorf("address not mapped") -} - -func (x *elfExe) DataStart() uint64 { - for _, s := range x.f.Sections { - if s.Name == ".go.buildinfo" { - return s.Addr - } - } - for _, p := range x.f.Progs { - if p.Type == elf.PT_LOAD && p.Flags&(elf.PF_X|elf.PF_W) == elf.PF_W { - return p.Vaddr - } - } - return 0 -} - -// peExe is the PE (Windows Portable Executable) implementation of the exe interface. -type peExe struct { - os *os.File - f *pe.File -} - -func (x *peExe) Close() error { - return x.os.Close() -} - -func (x *peExe) imageBase() uint64 { - switch oh := x.f.OptionalHeader.(type) { - case *pe.OptionalHeader32: - return uint64(oh.ImageBase) - case *pe.OptionalHeader64: - return oh.ImageBase - } - return 0 -} - -func (x *peExe) ReadData(addr, size uint64) ([]byte, error) { - addr -= x.imageBase() - for _, sect := range x.f.Sections { - if uint64(sect.VirtualAddress) <= addr && addr <= uint64(sect.VirtualAddress+sect.Size-1) { - n := uint64(sect.VirtualAddress+sect.Size) - addr - if n > size { - n = size - } - data := make([]byte, n) - _, err := sect.ReadAt(data, int64(addr-uint64(sect.VirtualAddress))) - if err != nil { - return nil, err - } - return data, nil - } - } - return nil, fmt.Errorf("address not mapped") -} - -func (x *peExe) DataStart() uint64 { - // Assume data is first writable section. - const ( - IMAGE_SCN_CNT_CODE = 0x00000020 - IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040 - IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080 - IMAGE_SCN_MEM_EXECUTE = 0x20000000 - IMAGE_SCN_MEM_READ = 0x40000000 - IMAGE_SCN_MEM_WRITE = 0x80000000 - IMAGE_SCN_MEM_DISCARDABLE = 0x2000000 - IMAGE_SCN_LNK_NRELOC_OVFL = 0x1000000 - IMAGE_SCN_ALIGN_32BYTES = 0x600000 - ) - for _, sect := range x.f.Sections { - if sect.VirtualAddress != 0 && sect.Size != 0 && - sect.Characteristics&^IMAGE_SCN_ALIGN_32BYTES == IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE { - return uint64(sect.VirtualAddress) + x.imageBase() - } - } - return 0 -} - -// machoExe is the Mach-O (Apple macOS/iOS) implementation of the exe interface. -type machoExe struct { - os *os.File - f *macho.File -} - -func (x *machoExe) Close() error { - return x.os.Close() -} - -func (x *machoExe) ReadData(addr, size uint64) ([]byte, error) { - for _, load := range x.f.Loads { - seg, ok := load.(*macho.Segment) - if !ok { - continue - } - if seg.Addr <= addr && addr <= seg.Addr+seg.Filesz-1 { - if seg.Name == "__PAGEZERO" { - continue - } - n := seg.Addr + seg.Filesz - addr - if n > size { - n = size - } - data := make([]byte, n) - _, err := seg.ReadAt(data, int64(addr-seg.Addr)) - if err != nil { - return nil, err - } - return data, nil - } - } - return nil, fmt.Errorf("address not mapped") -} - -func (x *machoExe) DataStart() uint64 { - // Look for section named "__go_buildinfo". - for _, sec := range x.f.Sections { - if sec.Name == "__go_buildinfo" { - return sec.Addr - } - } - // Try the first non-empty writable segment. - const RW = 3 - for _, load := range x.f.Loads { - seg, ok := load.(*macho.Segment) - if ok && seg.Addr != 0 && seg.Filesz != 0 && seg.Prot == RW && seg.Maxprot == RW { - return seg.Addr - } - } - return 0 -} - -// xcoffExe is the XCOFF (AIX eXtended COFF) implementation of the exe interface. -type xcoffExe struct { - os *os.File - f *xcoff.File -} - -func (x *xcoffExe) Close() error { - return x.os.Close() -} - -func (x *xcoffExe) ReadData(addr, size uint64) ([]byte, error) { - for _, sect := range x.f.Sections { - if uint64(sect.VirtualAddress) <= addr && addr <= uint64(sect.VirtualAddress+sect.Size-1) { - n := uint64(sect.VirtualAddress+sect.Size) - addr - if n > size { - n = size - } - data := make([]byte, n) - _, err := sect.ReadAt(data, int64(addr-uint64(sect.VirtualAddress))) - if err != nil { - return nil, err - } - return data, nil - } - } - return nil, fmt.Errorf("address not mapped") -} - -func (x *xcoffExe) DataStart() uint64 { - return x.f.SectionByType(xcoff.STYP_DATA).VirtualAddress -} diff --git a/src/cmd/go/internal/version/version.go b/src/cmd/go/internal/version/version.go index e885933ac3..febc7c638a 100644 --- a/src/cmd/go/internal/version/version.go +++ b/src/cmd/go/internal/version/version.go @@ -8,7 +8,8 @@ package version import ( "bytes" "context" - "encoding/binary" + "debug/buildinfo" + "errors" "fmt" "io/fs" "os" @@ -141,90 +142,25 @@ func scanFile(file string, info fs.FileInfo, mustPrint bool) { return } - x, err := openExe(file) + bi, err := buildinfo.ReadFile(file) if err != nil { if mustPrint { - fmt.Fprintf(os.Stderr, "%s: %v\n", file, err) + if pathErr := (*os.PathError)(nil); errors.As(err, &pathErr) && filepath.Clean(pathErr.Path) == filepath.Clean(file) { + fmt.Fprintf(os.Stderr, "%v\n", file) + } else { + fmt.Fprintf(os.Stderr, "%s: %v\n", file, err) + } } - return } - defer x.Close() - vers, mod := findVers(x) - if vers == "" { - if mustPrint { - fmt.Fprintf(os.Stderr, "%s: go version not found\n", file) - } - return - } - - fmt.Printf("%s: %s\n", file, vers) - if *versionM && mod != "" { - fmt.Printf("\t%s\n", strings.ReplaceAll(mod[:len(mod)-1], "\n", "\n\t")) - } -} - -// The build info blob left by the linker is identified by -// a 16-byte header, consisting of buildInfoMagic (14 bytes), -// the binary's pointer size (1 byte), -// and whether the binary is big endian (1 byte). -var buildInfoMagic = []byte("\xff Go buildinf:") - -// findVers finds and returns the Go version and module version information -// in the executable x. -func findVers(x exe) (vers, mod string) { - // Read the first 64kB of text to find the build info blob. - text := x.DataStart() - data, err := x.ReadData(text, 64*1024) + fmt.Printf("%s: %s\n", file, bi.GoVersion) + bi.GoVersion = "" // suppress printing go version again + mod, err := bi.MarshalText() if err != nil { + fmt.Fprintf(os.Stderr, "%s: formatting build info: %v\n", file, err) return } - for ; !bytes.HasPrefix(data, buildInfoMagic); data = data[32:] { - if len(data) < 32 { - return - } - } - - // Decode the blob. - ptrSize := int(data[14]) - bigEndian := data[15] != 0 - var bo binary.ByteOrder - if bigEndian { - bo = binary.BigEndian - } else { - bo = binary.LittleEndian - } - var readPtr func([]byte) uint64 - if ptrSize == 4 { - readPtr = func(b []byte) uint64 { return uint64(bo.Uint32(b)) } - } else { - readPtr = bo.Uint64 - } - vers = readString(x, ptrSize, readPtr, readPtr(data[16:])) - if vers == "" { - return - } - mod = readString(x, ptrSize, readPtr, readPtr(data[16+ptrSize:])) - if len(mod) >= 33 && mod[len(mod)-17] == '\n' { - // Strip module framing. - mod = mod[16 : len(mod)-16] - } else { - mod = "" - } - return -} - -// readString returns the string at address addr in the executable x. -func readString(x exe, ptrSize int, readPtr func([]byte) uint64, addr uint64) string { - hdr, err := x.ReadData(addr, uint64(2*ptrSize)) - if err != nil || len(hdr) < 2*ptrSize { - return "" - } - dataAddr := readPtr(hdr) - dataLen := readPtr(hdr[ptrSize:]) - data, err := x.ReadData(dataAddr, dataLen) - if err != nil || uint64(len(data)) < dataLen { - return "" + if *versionM && len(mod) > 0 { + fmt.Printf("\t%s\n", bytes.ReplaceAll(mod[:len(mod)-1], []byte("\n"), []byte("\n\t"))) } - return string(data) } -- GitLab From a37bebc042672d20837ea348d45e39740568cb77 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Fri, 1 Oct 2021 11:21:49 -0700 Subject: [PATCH 1601/2500] cmd/go: stamp VCS revision and uncommitted status into binaries When the go command builds a binary, it will now stamp the current revision from the local Git or Mercurial repository, and it will also stamp whether there are uncommitted edited or untracked files. Only Git and Mercurial are supported for now. If no repository is found containing the current working directory (where the go command was started), or if either the main package directory or the containing module's root directory is outside the repository, no VCS information will be stamped. If the VCS tool is missing or returns an error, that error is reported on the main package (hinting that -buildvcs may be disabled). This change introduces the -buildvcs flag, which is enabled by default. When disabled, VCS information won't be stamped when it would be otherwise. Stamped information may be read using 'go version -m file' or debug.ReadBuildInfo. For #37475 Change-Id: I4e7d3159e1c270d85869ad99f10502e546e7582d Reviewed-on: https://go-review.googlesource.com/c/go/+/353930 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- api/next.txt | 4 + src/cmd/go/alldocs.go | 6 + src/cmd/go/internal/cfg/cfg.go | 1 + src/cmd/go/internal/get/get.go | 18 ++- src/cmd/go/internal/load/pkg.go | 67 +++++++++ src/cmd/go/internal/vcs/vcs.go | 115 +++++++++++---- src/cmd/go/internal/vcs/vcs_test.go | 16 +-- src/cmd/go/internal/work/build.go | 7 + src/cmd/go/script_test.go | 78 ++++++++++ .../testdata/script/version_buildvcs_git.txt | 135 ++++++++++++++++++ .../testdata/script/version_buildvcs_hg.txt | 81 +++++++++++ .../script/version_buildvcs_nested.txt | 50 +++++++ src/cmd/internal/str/path.go | 14 ++ src/runtime/debug/mod.go | 46 ++++-- 14 files changed, 585 insertions(+), 53 deletions(-) create mode 100644 src/cmd/go/testdata/script/version_buildvcs_git.txt create mode 100644 src/cmd/go/testdata/script/version_buildvcs_hg.txt create mode 100644 src/cmd/go/testdata/script/version_buildvcs_nested.txt diff --git a/api/next.txt b/api/next.txt index ced738e480..9e4bb83cb7 100644 --- a/api/next.txt +++ b/api/next.txt @@ -4,6 +4,10 @@ pkg debug/buildinfo, type BuildInfo = debug.BuildInfo pkg runtime/debug, method (*BuildInfo) MarshalText() ([]byte, error) pkg runtime/debug, method (*BuildInfo) UnmarshalText() ([]byte, error) pkg runtime/debug, type BuildInfo struct, GoVersion string +pkg runtime/debug, type BuildInfo struct, Settings []BuildSetting +pkg runtime/debug, type BuildSetting struct +pkg runtime/debug, type BuildSetting struct, Key string +pkg runtime/debug, type BuildSetting struct, Value string pkg syscall (darwin-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) pkg syscall (darwin-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) pkg syscall (darwin-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index c3e4179025..b6ea5a3701 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -133,6 +133,12 @@ // arguments to pass on each go tool asm invocation. // -buildmode mode // build mode to use. See 'go help buildmode' for more. +// -buildvcs +// Whether to stamp binaries with version control information. By default, +// version control information is stamped into a binary if the main package +// and the main module containing it are in the repository containing the +// current directory (if there is a repository). Use -buildvcs=false to +// omit version control information. // -compiler name // name of compiler to use, as in runtime.Compiler (gccgo or gc). // -gccgoflags '[pattern=]arg list' diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go index c8747d6c11..e1bf11fce2 100644 --- a/src/cmd/go/internal/cfg/cfg.go +++ b/src/cmd/go/internal/cfg/cfg.go @@ -26,6 +26,7 @@ import ( var ( BuildA bool // -a flag BuildBuildmode string // -buildmode flag + BuildBuildvcs bool // -buildvcs flag BuildContext = defaultContext() BuildMod string // -mod flag BuildModExplicit bool // whether -mod was set explicitly diff --git a/src/cmd/go/internal/get/get.go b/src/cmd/go/internal/get/get.go index b79d3ba86f..c96459297a 100644 --- a/src/cmd/go/internal/get/get.go +++ b/src/cmd/go/internal/get/get.go @@ -417,10 +417,10 @@ func download(arg string, parent *load.Package, stk *load.ImportStack, mode int) // to make the first copy of or update a copy of the given package. func downloadPackage(p *load.Package) error { var ( - vcsCmd *vcs.Cmd - repo, rootPath string - err error - blindRepo bool // set if the repo has unusual configuration + vcsCmd *vcs.Cmd + repo, rootPath, repoDir string + err error + blindRepo bool // set if the repo has unusual configuration ) // p can be either a real package, or a pseudo-package whose “import path” is @@ -446,10 +446,18 @@ func downloadPackage(p *load.Package) error { if p.Internal.Build.SrcRoot != "" { // Directory exists. Look for checkout along path to src. - vcsCmd, rootPath, err = vcs.FromDir(p.Dir, p.Internal.Build.SrcRoot) + repoDir, vcsCmd, err = vcs.FromDir(p.Dir, p.Internal.Build.SrcRoot) if err != nil { return err } + if !str.HasFilePathPrefix(repoDir, p.Internal.Build.SrcRoot) { + panic(fmt.Sprintf("repository %q not in source root %q", repo, p.Internal.Build.SrcRoot)) + } + rootPath = str.TrimFilePathPrefix(repoDir, p.Internal.Build.SrcRoot) + if err := vcs.CheckGOVCS(vcsCmd, rootPath); err != nil { + return err + } + repo = "" // should be unused; make distinctive // Double-check where it came from. diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index 0fc5afbc36..473fa7a9d6 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -38,6 +38,7 @@ import ( "cmd/go/internal/par" "cmd/go/internal/search" "cmd/go/internal/trace" + "cmd/go/internal/vcs" "cmd/internal/str" "cmd/internal/sys" @@ -2267,6 +2268,72 @@ func (p *Package) setBuildInfo() { Main: main, Deps: deps, } + + // Add VCS status if all conditions are true: + // + // - -buildvcs is enabled. + // - p is contained within a main module (there may be multiple main modules + // in a workspace, but local replacements don't count). + // - Both the current directory and p's module's root directory are contained + // in the same local repository. + // - We know the VCS commands needed to get the status. + setVCSError := func(err error) { + setPkgErrorf("error obtaining VCS status: %v\n\tUse -buildvcs=false to disable VCS stamping.", err) + } + + var repoDir string + var vcsCmd *vcs.Cmd + var err error + if cfg.BuildBuildvcs && p.Module != nil && p.Module.Version == "" { + repoDir, vcsCmd, err = vcs.FromDir(base.Cwd(), "") + if err != nil && !errors.Is(err, os.ErrNotExist) { + setVCSError(err) + return + } + if !str.HasFilePathPrefix(p.Module.Dir, repoDir) && + !str.HasFilePathPrefix(repoDir, p.Module.Dir) { + // The module containing the main package does not overlap with the + // repository containing the working directory. Don't include VCS info. + // If the repo contains the module or vice versa, but they are not + // the same directory, it's likely an error (see below). + repoDir, vcsCmd = "", nil + } + } + if repoDir != "" && vcsCmd.Status != nil { + // Check that the current directory, package, and module are in the same + // repository. vcs.FromDir allows nested Git repositories, but nesting + // is not allowed for other VCS tools. The current directory may be outside + // p.Module.Dir when a workspace is used. + pkgRepoDir, _, err := vcs.FromDir(p.Dir, "") + if err != nil { + setVCSError(err) + return + } + if pkgRepoDir != repoDir { + setVCSError(fmt.Errorf("main package is in repository %q but current directory is in repository %q", pkgRepoDir, repoDir)) + return + } + modRepoDir, _, err := vcs.FromDir(p.Module.Dir, "") + if err != nil { + setVCSError(err) + return + } + if modRepoDir != repoDir { + setVCSError(fmt.Errorf("main module is in repository %q but current directory is in repository %q", modRepoDir, repoDir)) + return + } + + st, err := vcsCmd.Status(vcsCmd, repoDir) + if err != nil { + setVCSError(err) + return + } + info.Settings = []debug.BuildSetting{ + {Key: vcsCmd.Cmd + "revision", Value: st.Revision}, + {Key: vcsCmd.Cmd + "uncommitted", Value: strconv.FormatBool(st.Uncommitted)}, + } + } + text, err := info.MarshalText() if err != nil { setPkgErrorf("error formatting build info: %v", err) diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go index 97b2a631ae..ebb4850443 100644 --- a/src/cmd/go/internal/vcs/vcs.go +++ b/src/cmd/go/internal/vcs/vcs.go @@ -5,6 +5,7 @@ package vcs import ( + "bytes" "encoding/json" "errors" "fmt" @@ -29,7 +30,7 @@ import ( "golang.org/x/mod/module" ) -// A vcsCmd describes how to use a version control system +// A Cmd describes how to use a version control system // like Mercurial, Git, or Subversion. type Cmd struct { Name string @@ -48,6 +49,13 @@ type Cmd struct { RemoteRepo func(v *Cmd, rootDir string) (remoteRepo string, err error) ResolveRepo func(v *Cmd, rootDir, remoteRepo string) (realRepo string, err error) + Status func(v *Cmd, rootDir string) (Status, error) +} + +// Status is the current state of a local repository. +type Status struct { + Revision string + Uncommitted bool } var defaultSecureScheme = map[string]bool{ @@ -139,6 +147,7 @@ var vcsHg = &Cmd{ Scheme: []string{"https", "http", "ssh"}, PingCmd: "identify -- {scheme}://{repo}", RemoteRepo: hgRemoteRepo, + Status: hgStatus, } func hgRemoteRepo(vcsHg *Cmd, rootDir string) (remoteRepo string, err error) { @@ -149,6 +158,27 @@ func hgRemoteRepo(vcsHg *Cmd, rootDir string) (remoteRepo string, err error) { return strings.TrimSpace(string(out)), nil } +func hgStatus(vcsHg *Cmd, rootDir string) (Status, error) { + out, err := vcsHg.runOutputVerboseOnly(rootDir, "identify -i") + if err != nil { + return Status{}, err + } + rev := strings.TrimSpace(string(out)) + uncommitted := strings.HasSuffix(rev, "+") + if uncommitted { + // "+" means a tracked file is edited. + rev = rev[:len(rev)-len("+")] + } else { + // Also look for untracked files. + out, err = vcsHg.runOutputVerboseOnly(rootDir, "status -u") + if err != nil { + return Status{}, err + } + uncommitted = len(out) > 0 + } + return Status{Revision: rev, Uncommitted: uncommitted}, nil +} + // vcsGit describes how to use Git. var vcsGit = &Cmd{ Name: "Git", @@ -182,6 +212,7 @@ var vcsGit = &Cmd{ PingCmd: "ls-remote {scheme}://{repo}", RemoteRepo: gitRemoteRepo, + Status: gitStatus, } // scpSyntaxRe matches the SCP-like addresses used by Git to access @@ -232,6 +263,20 @@ func gitRemoteRepo(vcsGit *Cmd, rootDir string) (remoteRepo string, err error) { return "", errParse } +func gitStatus(cmd *Cmd, repoDir string) (Status, error) { + out, err := cmd.runOutputVerboseOnly(repoDir, "rev-parse HEAD") + if err != nil { + return Status{}, err + } + rev := string(bytes.TrimSpace(out)) + out, err = cmd.runOutputVerboseOnly(repoDir, "status --porcelain") + if err != nil { + return Status{}, err + } + uncommitted := len(out) != 0 + return Status{Revision: rev, Uncommitted: uncommitted}, nil +} + // vcsBzr describes how to use Bazaar. var vcsBzr = &Cmd{ Name: "Bazaar", @@ -395,6 +440,12 @@ func (v *Cmd) runOutput(dir string, cmd string, keyval ...string) ([]byte, error return v.run1(dir, cmd, keyval, true) } +// runOutputVerboseOnly is like runOutput but only generates error output to +// standard error in verbose mode. +func (v *Cmd) runOutputVerboseOnly(dir string, cmd string, keyval ...string) ([]byte, error) { + return v.run1(dir, cmd, keyval, false) +} + // run1 is the generalized implementation of run and runOutput. func (v *Cmd) run1(dir string, cmdline string, keyval []string, verbose bool) ([]byte, error) { m := make(map[string]string) @@ -550,58 +601,62 @@ type vcsPath struct { // FromDir inspects dir and its parents to determine the // version control system and code repository to use. -// On return, root is the import path -// corresponding to the root of the repository. -func FromDir(dir, srcRoot string) (vcs *Cmd, root string, err error) { +// If no repository is found, FromDir returns an error +// equivalent to os.ErrNotExist. +func FromDir(dir, srcRoot string) (repoDir string, vcsCmd *Cmd, err error) { // Clean and double-check that dir is in (a subdirectory of) srcRoot. dir = filepath.Clean(dir) - srcRoot = filepath.Clean(srcRoot) - if len(dir) <= len(srcRoot) || dir[len(srcRoot)] != filepath.Separator { - return nil, "", fmt.Errorf("directory %q is outside source root %q", dir, srcRoot) + if srcRoot != "" { + srcRoot = filepath.Clean(srcRoot) + if len(dir) <= len(srcRoot) || dir[len(srcRoot)] != filepath.Separator { + return "", nil, fmt.Errorf("directory %q is outside source root %q", dir, srcRoot) + } } - var vcsRet *Cmd - var rootRet string - origDir := dir for len(dir) > len(srcRoot) { for _, vcs := range vcsList { if _, err := os.Stat(filepath.Join(dir, "."+vcs.Cmd)); err == nil { - root := filepath.ToSlash(dir[len(srcRoot)+1:]) // Record first VCS we find, but keep looking, // to detect mistakes like one kind of VCS inside another. - if vcsRet == nil { - vcsRet = vcs - rootRet = root + if vcsCmd == nil { + vcsCmd = vcs + repoDir = dir continue } // Allow .git inside .git, which can arise due to submodules. - if vcsRet == vcs && vcs.Cmd == "git" { + if vcsCmd == vcs && vcs.Cmd == "git" { continue } // Otherwise, we have one VCS inside a different VCS. - return nil, "", fmt.Errorf("directory %q uses %s, but parent %q uses %s", - filepath.Join(srcRoot, rootRet), vcsRet.Cmd, filepath.Join(srcRoot, root), vcs.Cmd) + return "", nil, fmt.Errorf("directory %q uses %s, but parent %q uses %s", + repoDir, vcsCmd.Cmd, dir, vcs.Cmd) } } // Move to parent. ndir := filepath.Dir(dir) if len(ndir) >= len(dir) { - // Shouldn't happen, but just in case, stop. break } dir = ndir } - - if vcsRet != nil { - if err := checkGOVCS(vcsRet, rootRet); err != nil { - return nil, "", err - } - return vcsRet, rootRet, nil + if vcsCmd == nil { + return "", nil, &vcsNotFoundError{dir: origDir} } + return repoDir, vcsCmd, nil +} + +type vcsNotFoundError struct { + dir string +} + +func (e *vcsNotFoundError) Error() string { + return fmt.Sprintf("directory %q is not using a known version control system", e.dir) +} - return nil, "", fmt.Errorf("directory %q is not using a known version control system", origDir) +func (e *vcsNotFoundError) Is(err error) bool { + return err == os.ErrNotExist } // A govcsRule is a single GOVCS rule like private:hg|svn. @@ -707,7 +762,11 @@ var defaultGOVCS = govcsConfig{ {"public", []string{"git", "hg"}}, } -func checkGOVCS(vcs *Cmd, root string) error { +// CheckGOVCS checks whether the policy defined by the environment variable +// GOVCS allows the given vcs command to be used with the given repository +// root path. Note that root may not be a real package or module path; it's +// the same as the root path in the go-import meta tag. +func CheckGOVCS(vcs *Cmd, root string) error { if vcs == vcsMod { // Direct module (proxy protocol) fetches don't // involve an external version control system @@ -885,7 +944,7 @@ func repoRootFromVCSPaths(importPath string, security web.SecurityMode, vcsPaths if vcs == nil { return nil, fmt.Errorf("unknown version control system %q", match["vcs"]) } - if err := checkGOVCS(vcs, match["root"]); err != nil { + if err := CheckGOVCS(vcs, match["root"]); err != nil { return nil, err } var repoURL string @@ -1012,7 +1071,7 @@ func repoRootForImportDynamic(importPath string, mod ModuleMode, security web.Se } } - if err := checkGOVCS(vcs, mmi.Prefix); err != nil { + if err := CheckGOVCS(vcs, mmi.Prefix); err != nil { return nil, err } diff --git a/src/cmd/go/internal/vcs/vcs_test.go b/src/cmd/go/internal/vcs/vcs_test.go index c5c7a3283b..248c541014 100644 --- a/src/cmd/go/internal/vcs/vcs_test.go +++ b/src/cmd/go/internal/vcs/vcs_test.go @@ -8,7 +8,6 @@ import ( "errors" "internal/testenv" "os" - "path" "path/filepath" "strings" "testing" @@ -205,7 +204,8 @@ func TestRepoRootForImportPath(t *testing.T) { } } -// Test that vcsFromDir correctly inspects a given directory and returns the right VCS and root. +// Test that vcs.FromDir correctly inspects a given directory and returns the +// right VCS and repo directory. func TestFromDir(t *testing.T) { tempDir, err := os.MkdirTemp("", "vcstest") if err != nil { @@ -232,18 +232,14 @@ func TestFromDir(t *testing.T) { f.Close() } - want := RepoRoot{ - VCS: vcs, - Root: path.Join("example.com", vcs.Name), - } - var got RepoRoot - got.VCS, got.Root, err = FromDir(dir, tempDir) + wantRepoDir := filepath.Dir(dir) + gotRepoDir, gotVCS, err := FromDir(dir, tempDir) if err != nil { t.Errorf("FromDir(%q, %q): %v", dir, tempDir, err) continue } - if got.VCS.Name != want.VCS.Name || got.Root != want.Root { - t.Errorf("FromDir(%q, %q) = VCS(%s) Root(%s), want VCS(%s) Root(%s)", dir, tempDir, got.VCS, got.Root, want.VCS, want.Root) + if gotRepoDir != wantRepoDir || gotVCS.Name != vcs.Name { + t.Errorf("FromDir(%q, %q) = RepoDir(%s), VCS(%s); want RepoDir(%s), VCS(%s)", dir, tempDir, gotRepoDir, gotVCS.Name, wantRepoDir, vcs.Name) } } } diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go index 55e4954eee..114abab16c 100644 --- a/src/cmd/go/internal/work/build.go +++ b/src/cmd/go/internal/work/build.go @@ -87,6 +87,12 @@ and test commands: arguments to pass on each go tool asm invocation. -buildmode mode build mode to use. See 'go help buildmode' for more. + -buildvcs + Whether to stamp binaries with version control information. By default, + version control information is stamped into a binary if the main package + and the main module containing it are in the repository containing the + current directory (if there is a repository). Use -buildvcs=false to + omit version control information. -compiler name name of compiler to use, as in runtime.Compiler (gccgo or gc). -gccgoflags '[pattern=]arg list' @@ -302,6 +308,7 @@ func AddBuildFlags(cmd *base.Command, mask BuildFlagMask) { cmd.Flag.Var((*base.StringsFlag)(&cfg.BuildToolexec), "toolexec", "") cmd.Flag.BoolVar(&cfg.BuildTrimpath, "trimpath", false, "") cmd.Flag.BoolVar(&cfg.BuildWork, "work", false, "") + cmd.Flag.BoolVar(&cfg.BuildBuildvcs, "buildvcs", true, "") // Undocumented, unstable debugging flags. cmd.Flag.StringVar(&cfg.DebugActiongraph, "debug-actiongraph", "", "") diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go index 17782420c7..ac9764db94 100644 --- a/src/cmd/go/script_test.go +++ b/src/cmd/go/script_test.go @@ -1130,6 +1130,17 @@ func (ts *testScript) startBackground(want simpleStatus, command string, args .. done: done, } + // Use the script's PATH to look up the command if it contains a separator + // instead of the test process's PATH (see lookPath). + // Don't use filepath.Clean, since that changes "./foo" to "foo". + command = filepath.FromSlash(command) + if !strings.Contains(command, string(filepath.Separator)) { + var err error + command, err = ts.lookPath(command) + if err != nil { + return nil, err + } + } cmd := exec.Command(command, args...) cmd.Dir = ts.cd cmd.Env = append(ts.env, "PWD="+ts.cd) @@ -1146,6 +1157,73 @@ func (ts *testScript) startBackground(want simpleStatus, command string, args .. return bg, nil } +// lookPath is (roughly) like exec.LookPath, but it uses the test script's PATH +// instead of the test process's PATH to find the executable. We don't change +// the test process's PATH since it may run scripts in parallel. +func (ts *testScript) lookPath(command string) (string, error) { + var strEqual func(string, string) bool + if runtime.GOOS == "windows" || runtime.GOOS == "darwin" { + // Using GOOS as a proxy for case-insensitive file system. + strEqual = strings.EqualFold + } else { + strEqual = func(a, b string) bool { return a == b } + } + + var pathExt []string + var searchExt bool + var isExecutable func(os.FileInfo) bool + if runtime.GOOS == "windows" { + // Use the test process's PathExt instead of the script's. + // If PathExt is set in the command's environment, cmd.Start fails with + // "parameter is invalid". Not sure why. + // If the command already has an extension in PathExt (like "cmd.exe") + // don't search for other extensions (not "cmd.bat.exe"). + pathExt = strings.Split(os.Getenv("PathExt"), string(filepath.ListSeparator)) + searchExt = true + cmdExt := filepath.Ext(command) + for _, ext := range pathExt { + if strEqual(cmdExt, ext) { + searchExt = false + break + } + } + isExecutable = func(fi os.FileInfo) bool { + return fi.Mode().IsRegular() + } + } else { + isExecutable = func(fi os.FileInfo) bool { + return fi.Mode().IsRegular() && fi.Mode().Perm()&0111 != 0 + } + } + + pathName := "PATH" + if runtime.GOOS == "plan9" { + pathName = "path" + } + + for _, dir := range strings.Split(ts.envMap[pathName], string(filepath.ListSeparator)) { + if searchExt { + ents, err := os.ReadDir(dir) + if err != nil { + continue + } + for _, ent := range ents { + for _, ext := range pathExt { + if !ent.IsDir() && strEqual(ent.Name(), command+ext) { + return dir + string(filepath.Separator) + ent.Name(), nil + } + } + } + } else { + path := dir + string(filepath.Separator) + command + if fi, err := os.Stat(path); err == nil && isExecutable(fi) { + return path, nil + } + } + } + return "", &exec.Error{Name: command, Err: exec.ErrNotFound} +} + // waitOrStop waits for the already-started command cmd by calling its Wait method. // // If cmd does not return before ctx is done, waitOrStop sends it the given interrupt signal. diff --git a/src/cmd/go/testdata/script/version_buildvcs_git.txt b/src/cmd/go/testdata/script/version_buildvcs_git.txt new file mode 100644 index 0000000000..78ce2e835e --- /dev/null +++ b/src/cmd/go/testdata/script/version_buildvcs_git.txt @@ -0,0 +1,135 @@ +# This test checks that VCS information is stamped into Go binaries by default, +# controlled with -buildvcs. This test focuses on Git. Other tests focus on +# other VCS tools but may not cover common functionality. + +[!exec:git] skip +[short] skip +env GOBIN=$WORK/gopath/bin +env oldpath=$PATH +cd repo/a + +# If there's no local repository, there's no VCS info. +go install +go version -m $GOBIN/a$GOEXE +! stdout gitrevision +rm $GOBIN/a$GOEXE + +# If there is a repository, but it can't be used for some reason, +# there should be an error. It should hint about -buildvcs=false. +cd .. +mkdir .git +env PATH=$WORK${/}fakebin${:}$oldpath +chmod 0755 $WORK/fakebin/git +! exec git help +cd a +! go install +stderr '^error obtaining VCS status: exit status 1\n\tUse -buildvcs=false to disable VCS stamping.$' +cd .. +env PATH=$oldpath +rm .git + +# If there is a repository in a parent directory, there should be VCS info. +exec git init +exec git config user.email gopher@golang.org +exec git config user.name 'J.R. Gopher' +exec git add -A +exec git commit -m 'initial commit' +cd a +go install +go version -m $GOBIN/a$GOEXE +stdout '^\tbuild\tgitrevision\t' +stdout '^\tbuild\tgituncommitted\tfalse$' +rm $GOBIN/a$GOEXE + +# Building with -buildvcs=false suppresses the info. +go install -buildvcs=false +go version -m $GOBIN/a$GOEXE +! stdout gitrevision +rm $GOBIN/a$GOEXE + +# An untracked file is shown as uncommitted, even if it isn't part of the build. +cp ../../outside/empty.txt . +go install +go version -m $GOBIN/a$GOEXE +stdout '^\tbuild\tgituncommitted\ttrue$' +rm empty.txt +rm $GOBIN/a$GOEXE + +# An edited file is shown as uncommitted, even if it isn't part of the build. +cp ../../outside/empty.txt ../README +go install +go version -m $GOBIN/a$GOEXE +stdout '^\tbuild\tgituncommitted\ttrue$' +exec git checkout ../README +rm $GOBIN/a$GOEXE + +# If the build doesn't include any packages from the repository, +# there should be no VCS info. +go install example.com/cmd/a@v1.0.0 +go version -m $GOBIN/a$GOEXE +! stdout gitrevision +rm $GOBIN/a$GOEXE + +go mod edit -require=example.com/c@v0.0.0 +go mod edit -replace=example.com/c@v0.0.0=../../outside/c +go install example.com/c +go version -m $GOBIN/c$GOEXE +! stdout gitrevision +rm $GOBIN/c$GOEXE +exec git checkout go.mod + +# If the build depends on a package in the repository, but it's not in the +# main module, there should be no VCS info. +go mod edit -require=example.com/b@v0.0.0 +go mod edit -replace=example.com/b@v0.0.0=../b +go mod edit -require=example.com/d@v0.0.0 +go mod edit -replace=example.com/d@v0.0.0=../../outside/d +go install example.com/d +go version -m $GOBIN/d$GOEXE +! stdout gitrevision +exec git checkout go.mod +rm $GOBIN/d$GOEXE + +-- $WORK/fakebin/git -- +#!/bin/sh +exit 1 +-- $WORK/fakebin/git.bat -- +exit 1 +-- repo/README -- +Far out in the uncharted backwaters of the unfashionable end of the western +spiral arm of the Galaxy lies a small, unregarded yellow sun. +-- repo/a/go.mod -- +module example.com/a + +go 1.18 +-- repo/a/a.go -- +package main + +func main() {} +-- repo/b/go.mod -- +module example.com/b + +go 1.18 +-- repo/b/b.go -- +package b +-- outside/empty.txt -- +-- outside/c/go.mod -- +module example.com/c + +go 1.18 +-- outside/c/main.go -- +package main + +func main() {} +-- outside/d/go.mod -- +module example.com/d + +go 1.18 + +require example.com/b v0.0.0 +-- outside/d/main.go -- +package main + +import _ "example.com/b" + +func main() {} diff --git a/src/cmd/go/testdata/script/version_buildvcs_hg.txt b/src/cmd/go/testdata/script/version_buildvcs_hg.txt new file mode 100644 index 0000000000..9dcb8dd950 --- /dev/null +++ b/src/cmd/go/testdata/script/version_buildvcs_hg.txt @@ -0,0 +1,81 @@ +# This test checks that VCS information is stamped into Go binaries by default, +# controlled with -buildvcs. This test focuses on Mercurial specifics. +# The Git test covers common functionality. + +[!exec:hg] skip +[short] skip +env GOBIN=$WORK/gopath/bin +env oldpath=$PATH +cd repo/a + +# If there's no local repository, there's no VCS info. +go install +go version -m $GOBIN/a$GOEXE +! stdout hgrevision +rm $GOBIN/a$GOEXE + +# If there is a repository, but it can't be used for some reason, +# there should be an error. It should hint about -buildvcs=false. +cd .. +mkdir .hg +env PATH=$WORK${/}fakebin${:}$oldpath +chmod 0755 $WORK/fakebin/hg +! exec hg help +cd a +! go install +stderr '^error obtaining VCS status: exit status 1\n\tUse -buildvcs=false to disable VCS stamping.$' +rm $GOBIN/a$GOEXE +cd .. +env PATH=$oldpath +rm .hg + +# If there is a repository in a parent directory, there should be VCS info. +exec hg init +exec hg add a README +exec hg commit -m 'initial commit' +cd a +go install +go version -m $GOBIN/a$GOEXE +stdout '^\tbuild\thgrevision\t' +stdout '^\tbuild\thguncommitted\tfalse$' +rm $GOBIN/a$GOEXE + +# Building with -buildvcs=false suppresses the info. +go install -buildvcs=false +go version -m $GOBIN/a$GOEXE +! stdout hgrevision +rm $GOBIN/a$GOEXE + +# An untracked file is shown as uncommitted, even if it isn't part of the build. +cp ../../outside/empty.txt . +go install +go version -m $GOBIN/a$GOEXE +stdout '^\tbuild\thguncommitted\ttrue$' +rm empty.txt +rm $GOBIN/a$GOEXE + +# An edited file is shown as uncommitted, even if it isn't part of the build. +cp ../../outside/empty.txt ../README +go install +go version -m $GOBIN/a$GOEXE +stdout '^\tbuild\thguncommitted\ttrue$' +exec hg revert ../README +rm $GOBIN/a$GOEXE + +-- $WORK/fakebin/hg -- +#!/bin/sh +exit 1 +-- $WORK/fakebin/hg.bat -- +exit 1 +-- repo/README -- +Far out in the uncharted backwaters of the unfashionable end of the western +spiral arm of the Galaxy lies a small, unregarded yellow sun. +-- repo/a/go.mod -- +module example.com/a + +go 1.18 +-- repo/a/a.go -- +package main + +func main() {} +-- outside/empty.txt -- diff --git a/src/cmd/go/testdata/script/version_buildvcs_nested.txt b/src/cmd/go/testdata/script/version_buildvcs_nested.txt new file mode 100644 index 0000000000..f904c41bf8 --- /dev/null +++ b/src/cmd/go/testdata/script/version_buildvcs_nested.txt @@ -0,0 +1,50 @@ +[!exec:git] skip +[!exec:hg] skip +env GOFLAGS=-n + +# Create a root module in a root Git repository. +mkdir root +cd root +go mod init example.com/root +exec git init + +# It's an error to build a package from a nested Mercurial repository +# without -buildvcs=false, even if the package is in a separate module. +mkdir hgsub +cd hgsub +exec hg init +cp ../../main.go main.go +! go build +stderr '^error obtaining VCS status: directory ".*hgsub" uses hg, but parent ".*root" uses git$' +stderr '\tUse -buildvcs=false to disable VCS stamping.$' +go mod init example.com/root/hgsub +! go build +stderr '^error obtaining VCS status: directory ".*hgsub" uses hg, but parent ".*root" uses git$' +go build -buildvcs=false +cd .. + +# It's an error to build a package from a nested Git repository if the package +# is in a separate repository from the current directory or from the module +# root directory. However, unlike with other VCS, it's okay for a Git repository +# to be nested within another Git repository. This happens with submodules. +mkdir gitsub +cd gitsub +exec git init +exec git config user.name 'J.R.Gopher' +exec git config user.email 'gopher@golang.org' +cp ../../main.go main.go +! go build +stderr '^error obtaining VCS status: main module is in repository ".*root" but current directory is in repository ".*gitsub"$' +go build -buildvcs=false +go mod init example.com/root/gitsub +exec git commit --allow-empty -m empty # status commands fail without this +go build +rm go.mod +cd .. +! go build ./gitsub +stderr '^error obtaining VCS status: main package is in repository ".*gitsub" but current directory is in repository ".*root"$' +go build -buildvcs=false -o=gitsub${/} ./gitsub + +-- main.go -- +package main +func main() {} diff --git a/src/cmd/internal/str/path.go b/src/cmd/internal/str/path.go index 51ab2af82b..0c8aaeaca1 100644 --- a/src/cmd/internal/str/path.go +++ b/src/cmd/internal/str/path.go @@ -49,3 +49,17 @@ func HasFilePathPrefix(s, prefix string) bool { return s[len(prefix)] == filepath.Separator && s[:len(prefix)] == prefix } } + +// TrimFilePathPrefix returns s without the leading path elements in prefix. +// If s does not start with prefix (HasFilePathPrefix with the same arguments +// returns false), TrimFilePathPrefix returns s. If s equals prefix, +// TrimFilePathPrefix returns "". +func TrimFilePathPrefix(s, prefix string) string { + if !HasFilePathPrefix(s, prefix) { + return s + } + if len(s) == len(prefix) { + return "" + } + return s[len(prefix)+1:] +} diff --git a/src/runtime/debug/mod.go b/src/runtime/debug/mod.go index 0c6488753b..14b99f5735 100644 --- a/src/runtime/debug/mod.go +++ b/src/runtime/debug/mod.go @@ -8,6 +8,7 @@ import ( "bytes" "fmt" "runtime" + "strings" ) // exported from runtime @@ -38,10 +39,11 @@ func ReadBuildInfo() (info *BuildInfo, ok bool) { // BuildInfo represents the build information read from a Go binary. type BuildInfo struct { - GoVersion string // Version of Go that produced this binary. - Path string // The main package path - Main Module // The module containing the main package - Deps []*Module // Module dependencies + GoVersion string // Version of Go that produced this binary. + Path string // The main package path + Main Module // The module containing the main package + Deps []*Module // Module dependencies + Settings []BuildSetting // Other information about the build. } // Module represents a module. @@ -52,6 +54,14 @@ type Module struct { Replace *Module // replaced by this module } +// BuildSetting describes a setting that may be used to understand how the +// binary was built. For example, VCS commit and dirty status is stored here. +type BuildSetting struct { + // Key and Value describe the build setting. They must not contain tabs + // or newlines. + Key, Value string +} + func (bi *BuildInfo) MarshalText() ([]byte, error) { buf := &bytes.Buffer{} if bi.GoVersion != "" { @@ -86,6 +96,12 @@ func (bi *BuildInfo) MarshalText() ([]byte, error) { for _, dep := range bi.Deps { formatMod("dep", *dep) } + for _, s := range bi.Settings { + if strings.ContainsAny(s.Key, "\n\t") || strings.ContainsAny(s.Value, "\n\t") { + return nil, fmt.Errorf("build setting %q contains tab or newline", s.Key) + } + fmt.Fprintf(buf, "build\t%s\t%s\n", s.Key, s.Value) + } return buf.Bytes(), nil } @@ -100,12 +116,13 @@ func (bi *BuildInfo) UnmarshalText(data []byte) (err error) { }() var ( - pathLine = []byte("path\t") - modLine = []byte("mod\t") - depLine = []byte("dep\t") - repLine = []byte("=>\t") - newline = []byte("\n") - tab = []byte("\t") + pathLine = []byte("path\t") + modLine = []byte("mod\t") + depLine = []byte("dep\t") + repLine = []byte("=>\t") + buildLine = []byte("build\t") + newline = []byte("\n") + tab = []byte("\t") ) readModuleLine := func(elem [][]byte) (Module, error) { @@ -167,6 +184,15 @@ func (bi *BuildInfo) UnmarshalText(data []byte) (err error) { Sum: string(elem[2]), } last = nil + case bytes.HasPrefix(line, buildLine): + elem := bytes.Split(line[len(buildLine):], tab) + if len(elem) != 2 { + return fmt.Errorf("expected 2 columns for build setting; got %d", len(elem)) + } + if len(elem[0]) == 0 { + return fmt.Errorf("empty key") + } + bi.Settings = append(bi.Settings, BuildSetting{Key: string(elem[0]), Value: string(elem[1])}) } lineNum++ } -- GitLab From 0fd0639e4c429e147d33bfc42654fcd651f4449f Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 12 Oct 2021 15:08:54 -0700 Subject: [PATCH 1602/2500] cmd/go: stamp tags and flags in build info Toolchain flags (like -gcflags), build tags (including race and msan), and cgo variables (including CGO_ENABLED, CGO_CPPFLAGS and others) are now stamped into binaries. For #37475 Change-Id: I9023e682c0618f91805434946c6bc937536b69bb Reviewed-on: https://go-review.googlesource.com/c/go/+/355493 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/alldocs.go | 7 +- src/cmd/go/go_test.go | 2 +- src/cmd/go/internal/cfg/cfg.go | 1 + src/cmd/go/internal/load/flag.go | 6 +- src/cmd/go/internal/load/pkg.go | 33 +++++++++- src/cmd/go/internal/work/build.go | 8 ++- .../script/version_build_settings.txt | 66 +++++++++++++++++++ 7 files changed, 115 insertions(+), 8 deletions(-) create mode 100644 src/cmd/go/testdata/script/version_build_settings.txt diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index b6ea5a3701..d04ba04a53 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -131,6 +131,11 @@ // // -asmflags '[pattern=]arg list' // arguments to pass on each go tool asm invocation. +// -buildinfo +// Whether to stamp binaries with build flags. By default, the compiler name +// (gc or gccgo), toolchain flags (like -gcflags), and environment variables +// containing flags (like CGO_CFLAGS) are stamped into binaries. Use +// -buildinfo=false to omit build information. See also -buildvcs. // -buildmode mode // build mode to use. See 'go help buildmode' for more. // -buildvcs @@ -138,7 +143,7 @@ // version control information is stamped into a binary if the main package // and the main module containing it are in the repository containing the // current directory (if there is a repository). Use -buildvcs=false to -// omit version control information. +// omit version control information. See also -buildinfo. // -compiler name // name of compiler to use, as in runtime.Compiler (gccgo or gc). // -gccgoflags '[pattern=]arg list' diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index 07e9962896..d67d01aa1e 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -1380,7 +1380,7 @@ func TestLdFlagsLongArgumentsIssue42295(t *testing.T) { for buf.Len() < sys.ExecArgLengthLimit+1 { buf.WriteString(testStr) } - tg.run("run", "-ldflags", fmt.Sprintf(`-X "main.extern=%s"`, buf.String()), tg.path("main.go")) + tg.run("run", "-buildinfo=false", "-ldflags", fmt.Sprintf(`-X "main.extern=%s"`, buf.String()), tg.path("main.go")) if tg.stderr.String() != buf.String() { t.Errorf("strings differ") } diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go index e1bf11fce2..37e9b2666e 100644 --- a/src/cmd/go/internal/cfg/cfg.go +++ b/src/cmd/go/internal/cfg/cfg.go @@ -25,6 +25,7 @@ import ( // These are general "build flags" used by build and other commands. var ( BuildA bool // -a flag + BuildBuildinfo bool // -buildinfo flag BuildBuildmode string // -buildmode flag BuildBuildvcs bool // -buildvcs flag BuildContext = defaultContext() diff --git a/src/cmd/go/internal/load/flag.go b/src/cmd/go/internal/load/flag.go index 4e0cb5bc19..d0d5716c3f 100644 --- a/src/cmd/go/internal/load/flag.go +++ b/src/cmd/go/internal/load/flag.go @@ -22,6 +22,7 @@ var ( // that allows specifying different effective flags for different packages. // See 'go help build' for more details about per-package flags. type PerPackageFlag struct { + raw string present bool values []ppfValue } @@ -39,6 +40,7 @@ func (f *PerPackageFlag) Set(v string) error { // set is the implementation of Set, taking a cwd (current working directory) for easier testing. func (f *PerPackageFlag) set(v, cwd string) error { + f.raw = v f.present = true match := func(p *Package) bool { return p.Internal.CmdlinePkg || p.Internal.CmdlineFiles } // default predicate with no pattern // For backwards compatibility with earlier flag splitting, ignore spaces around flags. @@ -72,9 +74,7 @@ func (f *PerPackageFlag) set(v, cwd string) error { return nil } -// String is required to implement flag.Value. -// It is not used, because cmd/go never calls flag.PrintDefaults. -func (f *PerPackageFlag) String() string { return "" } +func (f *PerPackageFlag) String() string { return f.raw } // Present reports whether the flag appeared on the command line. func (f *PerPackageFlag) Present() bool { diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index 473fa7a9d6..716994b3ad 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -2268,6 +2268,35 @@ func (p *Package) setBuildInfo() { Main: main, Deps: deps, } + appendSetting := func(key, value string) { + info.Settings = append(info.Settings, debug.BuildSetting{Key: key, Value: value}) + } + + // Add command-line flags relevant to the build. + // This is informational, not an exhaustive list. + if cfg.BuildBuildinfo { + appendSetting("compiler", cfg.BuildContext.Compiler) + if BuildAsmflags.present { + appendSetting("asmflags", BuildAsmflags.String()) + } + if BuildGcflags.present && cfg.BuildContext.Compiler == "gc" { + appendSetting("gcflags", BuildGcflags.String()) + } + if BuildGccgoflags.present && cfg.BuildContext.Compiler == "gccgo" { + appendSetting("gccgoflags", BuildGccgoflags.String()) + } + if BuildLdflags.present { + appendSetting("ldflags", BuildLdflags.String()) + } + tags := append(cfg.BuildContext.BuildTags, cfg.BuildContext.ToolTags...) + appendSetting("tags", strings.Join(tags, ",")) + appendSetting("CGO_ENABLED", strconv.FormatBool(cfg.BuildContext.CgoEnabled)) + if cfg.BuildContext.CgoEnabled { + for _, name := range []string{"CGO_CPPFLAGS", "CGO_CFLAGS", "CGO_CXXFLAGS", "CGO_LDFLAGS"} { + appendSetting(name, cfg.Getenv(name)) + } + } + } // Add VCS status if all conditions are true: // @@ -2328,10 +2357,10 @@ func (p *Package) setBuildInfo() { setVCSError(err) return } - info.Settings = []debug.BuildSetting{ + info.Settings = append(info.Settings, []debug.BuildSetting{ {Key: vcsCmd.Cmd + "revision", Value: st.Revision}, {Key: vcsCmd.Cmd + "uncommitted", Value: strconv.FormatBool(st.Uncommitted)}, - } + }...) } text, err := info.MarshalText() diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go index 114abab16c..e10f647a6d 100644 --- a/src/cmd/go/internal/work/build.go +++ b/src/cmd/go/internal/work/build.go @@ -85,6 +85,11 @@ and test commands: -asmflags '[pattern=]arg list' arguments to pass on each go tool asm invocation. + -buildinfo + Whether to stamp binaries with build flags. By default, the compiler name + (gc or gccgo), toolchain flags (like -gcflags), and environment variables + containing flags (like CGO_CFLAGS) are stamped into binaries. Use + -buildinfo=false to omit build information. See also -buildvcs. -buildmode mode build mode to use. See 'go help buildmode' for more. -buildvcs @@ -92,7 +97,7 @@ and test commands: version control information is stamped into a binary if the main package and the main module containing it are in the repository containing the current directory (if there is a repository). Use -buildvcs=false to - omit version control information. + omit version control information. See also -buildinfo. -compiler name name of compiler to use, as in runtime.Compiler (gccgo or gc). -gccgoflags '[pattern=]arg list' @@ -308,6 +313,7 @@ func AddBuildFlags(cmd *base.Command, mask BuildFlagMask) { cmd.Flag.Var((*base.StringsFlag)(&cfg.BuildToolexec), "toolexec", "") cmd.Flag.BoolVar(&cfg.BuildTrimpath, "trimpath", false, "") cmd.Flag.BoolVar(&cfg.BuildWork, "work", false, "") + cmd.Flag.BoolVar(&cfg.BuildBuildinfo, "buildinfo", true, "") cmd.Flag.BoolVar(&cfg.BuildBuildvcs, "buildvcs", true, "") // Undocumented, unstable debugging flags. diff --git a/src/cmd/go/testdata/script/version_build_settings.txt b/src/cmd/go/testdata/script/version_build_settings.txt new file mode 100644 index 0000000000..7e93643b9f --- /dev/null +++ b/src/cmd/go/testdata/script/version_build_settings.txt @@ -0,0 +1,66 @@ +[short] skip + +# Compiler name is always added. +go build +go version -m m$GOEXE +stdout '^\tbuild\tcompiler\tgc$' +! stdout asmflags|gcflags|ldflags|gccgoflags + +# Toolchain flags are added if present. +# The raw flags are included, with package patterns if specified. +go build -asmflags=all=-spectre=all +go version -m m$GOEXE +stdout '^\tbuild\tasmflags\tall=-spectre=all$' + +go build -gcflags=all=-spectre=all +go version -m m$GOEXE +stdout '^\tbuild\tgcflags\tall=-spectre=all$' + +go build -ldflags=-w +go version -m m$GOEXE +stdout '^\tbuild\tldflags\t-w$' + +# gccgoflags are not added when gc is used, and vice versa. +# TODO: test gccgo. +go build -gccgoflags=all=UNUSED +go version -m m$GOEXE +! stdout gccgoflags + +# Build and tool tags are added but not release tags. +# "race" is included with build tags but not "cgo". +go build -tags=a,b +go version -m m$GOEXE +stdout '^\tbuild\ttags\ta,b(,goexperiment\.[a-z0-9]+)*$' +[race] go build -race +[race] go version -m m$GOEXE +[race] stdout '^\tbuild\ttags\t.*race.*$' + +# CGO flags are separate settings. +# CGO_ENABLED is always present. +# Other flags are added if CGO_ENABLED is true. +env CGO_ENABLED=0 +go build +go version -m m$GOEXE +stdout '^\tbuild\tCGO_ENABLED\tfalse$' +! stdout CGO_CPPFLAGS|CGO_CFLAGS|CGO_CXXFLAGS|CGO_LDFLAGS +[cgo] env CGO_ENABLED=1 +[cgo] env CGO_CPPFLAGS=-DFROM_CPPFLAGS=1 +[cgo] env CGO_CFLAGS=-DFROM_CFLAGS=1 +[cgo] env CGO_CXXFLAGS=-DFROM_CXXFLAGS=1 +[cgo] env CGO_LDFLAGS=-L/extra/dir/does/not/exist +[cgo] go build +[cgo] go version -m m$GOEXE +[cgo] stdout '^\tbuild\tCGO_ENABLED\ttrue$' +[cgo] stdout '^\tbuild\tCGO_CPPFLAGS\t-DFROM_CPPFLAGS=1$' +[cgo] stdout '^\tbuild\tCGO_CFLAGS\t-DFROM_CFLAGS=1$' +[cgo] stdout '^\tbuild\tCGO_CXXFLAGS\t-DFROM_CXXFLAGS=1$' +[cgo] stdout '^\tbuild\tCGO_LDFLAGS\t-L/extra/dir/does/not/exist$' + +-- go.mod -- +module example.com/m + +go 1.18 +-- m.go -- +package main + +func main() {} -- GitLab From 4cbc0a555474f59b8600e7e8ecba5c70d619ba0b Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Thu, 14 Oct 2021 11:34:00 -0400 Subject: [PATCH 1603/2500] cmd/go: produce a better error for generic test functions Test functions with type parameters cannot be invoked without type arguments, so cmd/go would previously fail with a type-checking error in the test harness. Avoid this by producing an error explaining that test functions cannot have type parameters. Fixes #48953 Change-Id: I4e39c9b7a06c964fad5f12d74d262aa090c25d79 Reviewed-on: https://go-review.googlesource.com/c/go/+/355889 Trust: Robert Findley Run-TryBot: Bryan C. Mills Reviewed-by: Bryan C. Mills TryBot-Result: Go Bot --- src/cmd/go/internal/load/test.go | 10 ++++++++-- src/cmd/go/testdata/script/list_test_err.txt | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/cmd/go/internal/load/test.go b/src/cmd/go/internal/load/test.go index da6d1cb21d..4cefb62d51 100644 --- a/src/cmd/go/internal/load/test.go +++ b/src/cmd/go/internal/load/test.go @@ -678,10 +678,16 @@ func (t *testFuncs) load(filename, pkg string, doImport, seen *bool) error { } func checkTestFunc(fn *ast.FuncDecl, arg string) error { + var why string if !isTestFunc(fn, arg) { - name := fn.Name.String() + why = fmt.Sprintf("must be: func %s(%s *testing.%s)", fn.Name.String(), strings.ToLower(arg), arg) + } + if fn.Type.TypeParams.NumFields() > 0 { + why = "test functions cannot have type parameters" + } + if why != "" { pos := testFileSet.Position(fn.Pos()) - return fmt.Errorf("%s: wrong signature for %s, must be: func %s(%s *testing.%s)", pos, name, name, strings.ToLower(arg), arg) + return fmt.Errorf("%s: wrong signature for %s, %s", pos, fn.Name.String(), why) } return nil } diff --git a/src/cmd/go/testdata/script/list_test_err.txt b/src/cmd/go/testdata/script/list_test_err.txt index c6f1ecf400..25dbb969b0 100644 --- a/src/cmd/go/testdata/script/list_test_err.txt +++ b/src/cmd/go/testdata/script/list_test_err.txt @@ -44,6 +44,10 @@ stdout 'testdep_b ' stdout 'nameerr\.test "[^"]*wrong signature for TestBad' ! stderr 'wrong signature for TestBad' +# go list prints a useful error for generic test functions +! go list -test -deps genericerr +stderr 'wrong signature for TestGeneric, test functions cannot have type parameters' + # go list prints partial information with error if test has cyclic import ! go list -test -deps cycleerr stdout cycleerr @@ -106,6 +110,16 @@ import ( func TestBad(t *testing.B) {} +-- genericerr/genericerr.go -- +package genericerr + +-- genericerr/genericerr_test.go -- +package genericerr + +import "testing" + +func TestGeneric[T any](t *testing.T) {} + -- cycleerr/cycleerr_test.go -- package cycleerr -- GitLab From 440b63bd6f29ad1efd747db9d137a844a3621bdc Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 14 Oct 2021 12:02:23 -0700 Subject: [PATCH 1604/2500] cmd/compile/internal/types2: remove Config.AllowTypeLists (cleanup) This flag is not used anymore. Change-Id: Id083ffa4f0a3051d3f1905a211db8acaaf525cf4 Reviewed-on: https://go-review.googlesource.com/c/go/+/355931 Trust: Robert Griesemer Reviewed-by: Robert Findley Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/irgen.go | 1 - src/cmd/compile/internal/types2/api.go | 6 ------ 2 files changed, 7 deletions(-) diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index e912f797b2..a3501fb90b 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -44,7 +44,6 @@ func checkFiles(noders []*noder) (posMap, *types2.Package, *types2.Info) { GoVersion: base.Flag.Lang, IgnoreLabels: true, // parser already checked via syntax.CheckBranches mode CompilerErrorMessages: true, // use error strings matching existing compiler errors - AllowTypeLists: true, // remove this line once all tests use type set syntax Error: func(err error) { terr := err.(types2.Error) base.ErrorfAt(m.makeXPos(terr.Pos), "%s", terr.Msg) diff --git a/src/cmd/compile/internal/types2/api.go b/src/cmd/compile/internal/types2/api.go index faf570c32e..e6d28af3c8 100644 --- a/src/cmd/compile/internal/types2/api.go +++ b/src/cmd/compile/internal/types2/api.go @@ -141,12 +141,6 @@ type Config struct { // TODO(gri) Consolidate error messages and remove this flag. CompilerErrorMessages bool - // If AllowTypeLists is set, the type list syntax is permitted - // in an interface in addition to the type set syntax. - // TODO(gri) Remove once type lists are no longer supported by - // the parser. - AllowTypeLists bool - // If go115UsesCgo is set, the type checker expects the // _cgo_gotypes.go file generated by running cmd/cgo to be // provided as a package source file. Qualified identifiers -- GitLab From 0400d536e4f349c8f30777c975af78b6a19e73b4 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 14 Oct 2021 12:41:29 -0700 Subject: [PATCH 1605/2500] go/types, types2: add a test case to ConvertibleTo string(int) conversions are somewhat special and deserve an entry. Change-Id: Ia68d047cfdb2f98e837bf663659f7f46404b16ac Reviewed-on: https://go-review.googlesource.com/c/go/+/355989 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/api_test.go | 4 ++-- src/go/types/api_test.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index 4966848ed4..ecb5a29830 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -1655,6 +1655,7 @@ func TestConvertibleTo(t *testing.T) { }{ {Typ[Int], Typ[Int], true}, {Typ[Int], Typ[Float32], true}, + {Typ[Int], Typ[String], true}, {newDefined(Typ[Int]), Typ[Int], true}, {newDefined(new(Struct)), new(Struct), true}, {newDefined(Typ[Int]), new(Struct), false}, @@ -1662,8 +1663,7 @@ func TestConvertibleTo(t *testing.T) { {NewSlice(Typ[Int]), NewPointer(NewArray(Typ[Int], 10)), true}, {NewSlice(Typ[Int]), NewArray(Typ[Int], 10), false}, {NewSlice(Typ[Int]), NewPointer(NewArray(Typ[Uint], 10)), false}, - // Untyped string values are not permitted by the spec, so the below - // behavior is undefined. + // Untyped string values are not permitted by the spec, so the behavior below is undefined. {Typ[UntypedString], Typ[String], true}, } { if got := ConvertibleTo(test.v, test.t); got != test.want { diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index 9044449e5c..b331ad929b 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -1631,6 +1631,7 @@ func TestConvertibleTo(t *testing.T) { }{ {Typ[Int], Typ[Int], true}, {Typ[Int], Typ[Float32], true}, + {Typ[Int], Typ[String], true}, {newDefined(Typ[Int]), Typ[Int], true}, {newDefined(new(Struct)), new(Struct), true}, {newDefined(Typ[Int]), new(Struct), false}, @@ -1638,8 +1639,7 @@ func TestConvertibleTo(t *testing.T) { {NewSlice(Typ[Int]), NewPointer(NewArray(Typ[Int], 10)), true}, {NewSlice(Typ[Int]), NewArray(Typ[Int], 10), false}, {NewSlice(Typ[Int]), NewPointer(NewArray(Typ[Uint], 10)), false}, - // Untyped string values are not permitted by the spec, so the below - // behavior is undefined. + // Untyped string values are not permitted by the spec, so the behavior below is undefined. {Typ[UntypedString], Typ[String], true}, } { if got := ConvertibleTo(test.v, test.t); got != test.want { -- GitLab From b59467e0365776761c3787a4d541b5e74fe24b24 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Thu, 14 Oct 2021 08:45:16 -0700 Subject: [PATCH 1606/2500] net/http: also use Server.ReadHeaderTimeout for TLS handshake deadline Fixes #48120 Change-Id: I72e89af8aaf3310e348d8ab639925ce0bf84204d Reviewed-on: https://go-review.googlesource.com/c/go/+/355870 Trust: Brad Fitzpatrick Run-TryBot: Brad Fitzpatrick TryBot-Result: Go Bot Reviewed-by: Damien Neil --- src/net/http/server.go | 37 ++++++++++++++++++++++---- src/net/http/server_test.go | 53 +++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 5 deletions(-) diff --git a/src/net/http/server.go b/src/net/http/server.go index 55fd4ae22f..e9b0b4d9bd 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -865,6 +865,28 @@ func (srv *Server) initialReadLimitSize() int64 { return int64(srv.maxHeaderBytes()) + 4096 // bufio slop } +// tlsHandshakeTimeout returns the time limit permitted for the TLS +// handshake, or zero for unlimited. +// +// It returns the minimum of any positive ReadHeaderTimeout, +// ReadTimeout, or WriteTimeout. +func (srv *Server) tlsHandshakeTimeout() time.Duration { + var ret time.Duration + for _, v := range [...]time.Duration{ + srv.ReadHeaderTimeout, + srv.ReadTimeout, + srv.WriteTimeout, + } { + if v <= 0 { + continue + } + if ret == 0 || v < ret { + ret = v + } + } + return ret +} + // wrapper around io.ReadCloser which on first read, sends an // HTTP/1.1 100 Continue header type expectContinueReader struct { @@ -1816,11 +1838,11 @@ func (c *conn) serve(ctx context.Context) { }() if tlsConn, ok := c.rwc.(*tls.Conn); ok { - if d := c.server.ReadTimeout; d > 0 { - c.rwc.SetReadDeadline(time.Now().Add(d)) - } - if d := c.server.WriteTimeout; d > 0 { - c.rwc.SetWriteDeadline(time.Now().Add(d)) + tlsTO := c.server.tlsHandshakeTimeout() + if tlsTO > 0 { + dl := time.Now().Add(tlsTO) + c.rwc.SetReadDeadline(dl) + c.rwc.SetWriteDeadline(dl) } if err := tlsConn.HandshakeContext(ctx); err != nil { // If the handshake failed due to the client not speaking @@ -1834,6 +1856,11 @@ func (c *conn) serve(ctx context.Context) { c.server.logf("http: TLS handshake error from %s: %v", c.rwc.RemoteAddr(), err) return } + // Restore Conn-level deadlines. + if tlsTO > 0 { + c.rwc.SetReadDeadline(time.Time{}) + c.rwc.SetWriteDeadline(time.Time{}) + } c.tlsState = new(tls.ConnectionState) *c.tlsState = tlsConn.ConnectionState() if proto := c.tlsState.NegotiatedProtocol; validNextProto(proto) { diff --git a/src/net/http/server_test.go b/src/net/http/server_test.go index 0132f3ba5f..d17c5c1e7e 100644 --- a/src/net/http/server_test.go +++ b/src/net/http/server_test.go @@ -9,8 +9,61 @@ package http import ( "fmt" "testing" + "time" ) +func TestServerTLSHandshakeTimeout(t *testing.T) { + tests := []struct { + s *Server + want time.Duration + }{ + { + s: &Server{}, + want: 0, + }, + { + s: &Server{ + ReadTimeout: -1, + }, + want: 0, + }, + { + s: &Server{ + ReadTimeout: 5 * time.Second, + }, + want: 5 * time.Second, + }, + { + s: &Server{ + ReadTimeout: 5 * time.Second, + WriteTimeout: -1, + }, + want: 5 * time.Second, + }, + { + s: &Server{ + ReadTimeout: 5 * time.Second, + WriteTimeout: 4 * time.Second, + }, + want: 4 * time.Second, + }, + { + s: &Server{ + ReadTimeout: 5 * time.Second, + ReadHeaderTimeout: 2 * time.Second, + WriteTimeout: 4 * time.Second, + }, + want: 2 * time.Second, + }, + } + for i, tt := range tests { + got := tt.s.tlsHandshakeTimeout() + if got != tt.want { + t.Errorf("%d. got %v; want %v", i, got, tt.want) + } + } +} + func BenchmarkServerMatch(b *testing.B) { fn := func(w ResponseWriter, r *Request) { fmt.Fprintf(w, "OK") -- GitLab From 9e8ed86813dd49c4160dd4813901e2ac03de5abd Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Thu, 14 Oct 2021 14:57:49 -0700 Subject: [PATCH 1607/2500] debug/buildinfo: fix test for build settings This CL fixes the debug/buildinfo test, which did not expect build settings. For #37475 Change-Id: Ie8c15ec633b4eec6a976120c8db64f116589d98e Reviewed-on: https://go-review.googlesource.com/c/go/+/356012 Trust: Jay Conrod Run-TryBot: Jay Conrod Reviewed-by: Bryan C. Mills --- src/debug/buildinfo/buildinfo_test.go | 28 ++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/debug/buildinfo/buildinfo_test.go b/src/debug/buildinfo/buildinfo_test.go index ab307d75c2..44d78a6be0 100644 --- a/src/debug/buildinfo/buildinfo_test.go +++ b/src/debug/buildinfo/buildinfo_test.go @@ -13,6 +13,7 @@ import ( "os/exec" "path" "path/filepath" + "regexp" "runtime" "strings" "testing" @@ -114,6 +115,23 @@ func TestReadFile(t *testing.T) { } } + goVersionRe := regexp.MustCompile("(?m)^go\t.*\n") + buildRe := regexp.MustCompile("(?m)^build\t.*\n") + cleanOutputForComparison := func(got string) string { + // Remove or replace anything that might depend on the test's environment + // so we can check the output afterward with a string comparison. + // We'll remove all build lines except the compiler, just to make sure + // build lines are included. + got = goVersionRe.ReplaceAllString(got, "go\tGOVERSION\n") + got = buildRe.ReplaceAllStringFunc(got, func(match string) string { + if strings.HasPrefix(match, "build\tcompiler\t") { + return match + } + return "" + }) + return got + } + cases := []struct { name string build func(t *testing.T, goos, goarch string) string @@ -142,9 +160,10 @@ func TestReadFile(t *testing.T) { { name: "valid_modules", build: buildWithModules, - want: "go\t$GOVERSION\n" + + want: "go\tGOVERSION\n" + "path\texample.com/m\n" + - "mod\texample.com/m\t(devel)\t\n", + "mod\texample.com/m\t(devel)\t\n" + + "build\tcompiler\tgc\n", }, { name: "invalid_modules", @@ -158,7 +177,7 @@ func TestReadFile(t *testing.T) { { name: "valid_gopath", build: buildWithGOPATH, - want: "go\t$GOVERSION\n", + want: "go\tGOVERSION\n", }, { name: "invalid_gopath", @@ -193,8 +212,7 @@ func TestReadFile(t *testing.T) { t.Fatalf("unexpected success; want error containing %q", tc.wantErr) } else if got, err := info.MarshalText(); err != nil { t.Fatalf("unexpected error marshaling BuildInfo: %v", err) - } else { - got := strings.ReplaceAll(string(got), runtime.Version(), "$GOVERSION") + } else if got := cleanOutputForComparison(string(got)); got != tc.want { if got != tc.want { t.Fatalf("got:\n%s\nwant:\n%s", got, tc.want) } -- GitLab From 0c45ed05612bb315c949229f7b484b4b573af4b0 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 13 Oct 2021 17:11:16 +0700 Subject: [PATCH 1608/2500] cmd/compile: fix irgen reports wrong error message for misuse of //go:embed Fixes #48230 Change-Id: Ic6490e065e7e79793faa0d0201dc94f5fcea694a Reviewed-on: https://go-review.googlesource.com/c/go/+/355529 Trust: Cuong Manh Le Trust: Dan Scales Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/decl.go | 11 +++++++++-- src/cmd/compile/internal/noder/irgen.go | 8 +++++++- src/cmd/compile/internal/types2/stdlib_test.go | 2 +- src/go/types/stdlib_test.go | 1 + test/fixedbugs/issue48230.go | 10 ++++++++++ 5 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 test/fixedbugs/issue48230.go diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go index f2dad9c302..82455f7d4a 100644 --- a/src/cmd/compile/internal/noder/decl.go +++ b/src/cmd/compile/internal/noder/decl.go @@ -132,7 +132,11 @@ func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) { g.target.Inits = append(g.target.Inits, fn) } + haveEmbed := g.haveEmbed g.later(func() { + defer func(b bool) { g.haveEmbed = b }(g.haveEmbed) + + g.haveEmbed = haveEmbed if fn.Type().HasTParam() { g.topFuncIsGeneric = true } @@ -241,12 +245,15 @@ func (g *irgen) varDecl(out *ir.Nodes, decl *syntax.VarDecl) { if decl.Pragma != nil { pragma := decl.Pragma.(*pragmas) - // TODO(mdempsky): Plumb noder.importedEmbed through to here. - varEmbed(g.makeXPos, names[0], decl, pragma, true) + varEmbed(g.makeXPos, names[0], decl, pragma, g.haveEmbed) g.reportUnused(pragma) } + haveEmbed := g.haveEmbed do := func() { + defer func(b bool) { g.haveEmbed = b }(g.haveEmbed) + + g.haveEmbed = haveEmbed values := g.exprList(decl.Values) var as2 *ir.AssignListStmt diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index a3501fb90b..982e811f5f 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -147,6 +147,9 @@ type irgen struct { // laterFuncs records tasks that need to run after all declarations // are processed. laterFuncs []func() + // haveEmbed indicates whether the current node belongs to file that + // imports "embed" package. + haveEmbed bool // exprStmtOK indicates whether it's safe to generate expressions or // statements yet. @@ -254,8 +257,11 @@ Outer: types.ResumeCheckSize() // 3. Process all remaining declarations. - for _, declList := range declLists { + for i, declList := range declLists { + old := g.haveEmbed + g.haveEmbed = noders[i].importedEmbed g.decls((*ir.Nodes)(&g.target.Decls), declList) + g.haveEmbed = old } g.exprStmtOK = true diff --git a/src/cmd/compile/internal/types2/stdlib_test.go b/src/cmd/compile/internal/types2/stdlib_test.go index 6e340d0777..9c22f01673 100644 --- a/src/cmd/compile/internal/types2/stdlib_test.go +++ b/src/cmd/compile/internal/types2/stdlib_test.go @@ -193,7 +193,7 @@ func TestStdFixed(t *testing.T) { "issue42058a.go", // types2 does not have constraints on channel element size "issue42058b.go", // types2 does not have constraints on channel element size "issue48097.go", // go/types doesn't check validity of //go:xxx directives, and non-init bodyless function - + "issue48230.go", // go/types doesn't check validity of //go:xxx directives ) } diff --git a/src/go/types/stdlib_test.go b/src/go/types/stdlib_test.go index 12ed9a54f2..b0d7fdd3d9 100644 --- a/src/go/types/stdlib_test.go +++ b/src/go/types/stdlib_test.go @@ -195,6 +195,7 @@ func TestStdFixed(t *testing.T) { "issue42058a.go", // go/types does not have constraints on channel element size "issue42058b.go", // go/types does not have constraints on channel element size "issue48097.go", // go/types doesn't check validity of //go:xxx directives, and non-init bodyless function + "issue48230.go", // go/types doesn't check validity of //go:xxx directives ) } diff --git a/test/fixedbugs/issue48230.go b/test/fixedbugs/issue48230.go new file mode 100644 index 0000000000..5f213762da --- /dev/null +++ b/test/fixedbugs/issue48230.go @@ -0,0 +1,10 @@ +// errorcheck + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +//go:embed issue48230.go // ERROR `go:embed only allowed in Go files that import "embed"` +var _ string -- GitLab From 3da0ff8e3b05333c378efe17585609598692791e Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Thu, 14 Oct 2021 16:47:47 -0700 Subject: [PATCH 1609/2500] cmd/go: don't stamp build or vcs info for GOROOT binaries Fixes a test failure in cmd/go TestScript/mod_outside. make.bash (cmd/dist) builds everything with -gcflags=all= -ldflags=all= by default. If those no-op flags aren't used, all GOROOT binaries appear stale. It's likely safe to omit those flags in cmd/dist if they're empty. Checking out a new commit in GOROOT would always cause staleness since the VCS info would change. For #37475 Change-Id: Ic9aa0f3b7318e05fbb2f7d2c008ad07a4c61952f Reviewed-on: https://go-review.googlesource.com/c/go/+/356014 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/load/pkg.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index 716994b3ad..58dc242383 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -2205,6 +2205,11 @@ func (p *Package) collectDeps() { // Note that the GoVersion field is not set here to avoid encoding it twice. // It is stored separately in the binary, mostly for historical reasons. func (p *Package) setBuildInfo() { + // TODO: build and vcs information is not embedded for executables in GOROOT. + // cmd/dist uses -gcflags=all= -ldflags=all= by default, which means these + // executables always appear stale unless the user sets the same flags. + // Perhaps it's safe to omit those flags when GO_GCFLAGS and GO_LDFLAGS + // are not set? setPkgErrorf := func(format string, args ...interface{}) { if p.Error == nil { p.Error = &PackageError{Err: fmt.Errorf(format, args...)} @@ -2274,7 +2279,7 @@ func (p *Package) setBuildInfo() { // Add command-line flags relevant to the build. // This is informational, not an exhaustive list. - if cfg.BuildBuildinfo { + if cfg.BuildBuildinfo && !p.Standard { appendSetting("compiler", cfg.BuildContext.Compiler) if BuildAsmflags.present { appendSetting("asmflags", BuildAsmflags.String()) @@ -2313,7 +2318,7 @@ func (p *Package) setBuildInfo() { var repoDir string var vcsCmd *vcs.Cmd var err error - if cfg.BuildBuildvcs && p.Module != nil && p.Module.Version == "" { + if cfg.BuildBuildvcs && p.Module != nil && p.Module.Version == "" && !p.Standard { repoDir, vcsCmd, err = vcs.FromDir(base.Cwd(), "") if err != nil && !errors.Is(err, os.ErrNotExist) { setVCSError(err) -- GitLab From 8dab959a8e3c631e3166eb08ba450bfdbbf56e03 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 14 Oct 2021 17:30:42 -0700 Subject: [PATCH 1610/2500] reflect: rename Mapiter.SetKey to Value.SetIterKey Same for Value. Add a bigger test. Include some shouldPanic checks. Fix a bug in assignment conversion. Fixes #48294 Change-Id: Id863ee5122a5787a7b35574b18586fd24d118788 Reviewed-on: https://go-review.googlesource.com/c/go/+/356049 Trust: Keith Randall Trust: Josh Bleecher Snyder Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Josh Bleecher Snyder --- src/reflect/all_test.go | 90 ++++++++++++++++++++++++++++++++++++++--- src/reflect/value.go | 48 +++++++++++----------- 2 files changed, 108 insertions(+), 30 deletions(-) diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index 5e10cc7a63..58156e0e5f 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -348,8 +348,8 @@ func TestMapIterSet(t *testing.T) { iter := v.MapRange() for iter.Next() { - iter.SetKey(k) - iter.SetValue(e) + k.SetIterKey(iter) + e.SetIterValue(iter) want := m[k.String()] got := e.Interface() if got != want { @@ -366,8 +366,8 @@ func TestMapIterSet(t *testing.T) { got := int(testing.AllocsPerRun(10, func() { iter := v.MapRange() for iter.Next() { - iter.SetKey(k) - iter.SetValue(e) + k.SetIterKey(iter) + e.SetIterValue(iter) } })) // Making a *MapIter allocates. This should be the only allocation. @@ -7475,9 +7475,9 @@ func TestMapIterReset(t *testing.T) { var seenk, seenv uint64 iter.Reset(ValueOf(m3)) for iter.Next() { - iter.SetKey(kv) + kv.SetIterKey(iter) seenk ^= kv.Uint() - iter.SetValue(kv) + kv.SetIterValue(iter) seenv ^= kv.Uint() } if seenk != 0b111 { @@ -7619,3 +7619,81 @@ func TestConvertibleTo(t *testing.T) { t.Fatalf("(%s).ConvertibleTo(%s) = true, want false", t3, t4) } } + +func TestSetIter(t *testing.T) { + data := map[string]int{ + "foo": 1, + "bar": 2, + "baz": 3, + } + + m := ValueOf(data) + i := m.MapRange() + k := New(TypeOf("")).Elem() + v := New(TypeOf(0)).Elem() + shouldPanic("Value.SetIterKey called before Next", func() { + k.SetIterKey(i) + }) + shouldPanic("Value.SetIterValue called before Next", func() { + k.SetIterValue(i) + }) + data2 := map[string]int{} + for i.Next() { + k.SetIterKey(i) + v.SetIterValue(i) + data2[k.Interface().(string)] = v.Interface().(int) + } + if !DeepEqual(data, data2) { + t.Errorf("maps not equal, got %v want %v", data2, data) + } + shouldPanic("Value.SetIterKey called on exhausted iterator", func() { + k.SetIterKey(i) + }) + shouldPanic("Value.SetIterValue called on exhausted iterator", func() { + k.SetIterValue(i) + }) + + i.Reset(m) + i.Next() + shouldPanic("Value.SetIterKey using unaddressable value", func() { + ValueOf("").SetIterKey(i) + }) + shouldPanic("Value.SetIterValue using unaddressable value", func() { + ValueOf(0).SetIterValue(i) + }) + shouldPanic("value of type string is not assignable to type int", func() { + New(TypeOf(0)).Elem().SetIterKey(i) + }) + shouldPanic("value of type int is not assignable to type string", func() { + New(TypeOf("")).Elem().SetIterValue(i) + }) + + // Make sure assignment conversion works. + var x interface{} + y := ValueOf(&x).Elem() + y.SetIterKey(i) + if _, ok := data[x.(string)]; !ok { + t.Errorf("got key %s which is not in map", x) + } + y.SetIterValue(i) + if x.(int) < 1 || x.(int) > 3 { + t.Errorf("got value %d which is not in map", x) + } + + // Try some key/value types which are direct interfaces. + a := 88 + b := 99 + pp := map[*int]*int{ + &a: &b, + } + i = ValueOf(pp).MapRange() + i.Next() + y.SetIterKey(i) + if got := *y.Interface().(*int); got != a { + t.Errorf("pointer incorrect: got %d want %d", got, a) + } + y.SetIterValue(i) + if got := *y.Interface().(*int); got != b { + t.Errorf("pointer incorrect: got %d want %d", got, b) + } +} diff --git a/src/reflect/value.go b/src/reflect/value.go index 39b82a8c01..abcc346de8 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -1651,30 +1651,30 @@ func (iter *MapIter) Key() Value { return copyVal(ktype, iter.m.flag.ro()|flag(ktype.Kind()), iterkey) } -// SetKey assigns dst to the key of iter's current map entry. -// It is equivalent to dst.Set(i.Key()), but it avoids allocating a new Value. -// As in Go, the key must be assignable to dst's type. -func (iter *MapIter) SetKey(dst Value) { +// SetIterKey assigns to v the key of iter's current map entry. +// It is equivalent to v.Set(iter.Key()), but it avoids allocating a new Value. +// As in Go, the key must be assignable to v's type. +func (v Value) SetIterKey(iter *MapIter) { if !iter.hiter.initialized() { - panic("MapIter.SetKey called before Next") + panic("reflect: Value.SetIterKey called before Next") } iterkey := mapiterkey(&iter.hiter) if iterkey == nil { - panic("MapIter.SetKey called on exhausted iterator") + panic("reflect: Value.SetIterKey called on exhausted iterator") } - dst.mustBeAssignable() + v.mustBeAssignable() var target unsafe.Pointer - if dst.kind() == Interface { - target = dst.ptr + if v.kind() == Interface { + target = v.ptr } t := (*mapType)(unsafe.Pointer(iter.m.typ)) ktype := t.key - key := Value{ktype, iterkey, iter.m.flag | flag(ktype.Kind())} - key = key.assignTo("reflect.MapIter.SetKey", dst.typ, target) - typedmemmove(dst.typ, dst.ptr, key.ptr) + key := Value{ktype, iterkey, iter.m.flag | flag(ktype.Kind()) | flagIndir} + key = key.assignTo("reflect.MapIter.SetKey", v.typ, target) + typedmemmove(v.typ, v.ptr, key.ptr) } // Value returns the value of iter's current map entry. @@ -1692,30 +1692,30 @@ func (iter *MapIter) Value() Value { return copyVal(vtype, iter.m.flag.ro()|flag(vtype.Kind()), iterelem) } -// SetValue assigns dst to the value of iter's current map entry. -// It is equivalent to dst.Set(i.Value()), but it avoids allocating a new Value. -// As in Go, the value must be assignable to dst's type. -func (iter *MapIter) SetValue(dst Value) { +// SetIterValue assigns to v the value of iter's current map entry. +// It is equivalent to v.Set(iter.Value()), but it avoids allocating a new Value. +// As in Go, the value must be assignable to v's type. +func (v Value) SetIterValue(iter *MapIter) { if !iter.hiter.initialized() { - panic("MapIter.SetValue called before Next") + panic("reflect: Value.SetIterValue called before Next") } iterelem := mapiterelem(&iter.hiter) if iterelem == nil { - panic("MapIter.SetValue called on exhausted iterator") + panic("reflect: Value.SetIterValue called on exhausted iterator") } - dst.mustBeAssignable() + v.mustBeAssignable() var target unsafe.Pointer - if dst.kind() == Interface { - target = dst.ptr + if v.kind() == Interface { + target = v.ptr } t := (*mapType)(unsafe.Pointer(iter.m.typ)) vtype := t.elem - elem := Value{vtype, iterelem, iter.m.flag | flag(vtype.Kind())} - elem = elem.assignTo("reflect.MapIter.SetValue", dst.typ, target) - typedmemmove(dst.typ, dst.ptr, elem.ptr) + elem := Value{vtype, iterelem, iter.m.flag | flag(vtype.Kind()) | flagIndir} + elem = elem.assignTo("reflect.MapIter.SetValue", v.typ, target) + typedmemmove(v.typ, v.ptr, elem.ptr) } // Next advances the map iterator and reports whether there is another -- GitLab From 81484cf6263461057251bbda825f2c3dc4cdcd09 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 14 Oct 2021 21:08:11 -0700 Subject: [PATCH 1611/2500] doc: document new reflect.SetIter{Key,Value} functions Update #48294 Update #47694 Change-Id: I4d4c01be74a9736d89a4ec92318ce29ff7289a0d Reviewed-on: https://go-review.googlesource.com/c/go/+/356050 Trust: Keith Randall Reviewed-by: Joe Tsai --- doc/go1.18.html | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index a5b47fa261..f4d097d06b 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -127,12 +127,25 @@ Do not send CLs removing the interior tags from such phrases. +
reflect
+
+

+ The new + Value.SetIterKey + and Value.SetIterValue + methods set a Value using a map iterator as the source. They are equivalent to + Value.Set(iter.Key()) and Value.Set(iter.Value()) but + do fewer allocations. +

+
+
+
syscall

The new function SyscallN has been introduced for Windows, allowing for calls with arbitrary number - of arguments. As results, + of arguments. As a result, Syscall, Syscall6, Syscall9, -- GitLab From 1cbec685124b7a40fe899286db697a85da7be28a Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 14 Oct 2021 23:01:34 -0700 Subject: [PATCH 1612/2500] reflect: fix SetIter test Missed one review comment in CL 356049 Change-Id: I05be585d15e77afc1aa57b737cdc8ba7204bab98 Reviewed-on: https://go-review.googlesource.com/c/go/+/356051 Trust: Keith Randall Trust: Josh Bleecher Snyder Run-TryBot: Keith Randall Reviewed-by: Josh Bleecher Snyder TryBot-Result: Go Bot --- src/reflect/all_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index 58156e0e5f..427855b02e 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -7635,7 +7635,7 @@ func TestSetIter(t *testing.T) { k.SetIterKey(i) }) shouldPanic("Value.SetIterValue called before Next", func() { - k.SetIterValue(i) + v.SetIterValue(i) }) data2 := map[string]int{} for i.Next() { @@ -7650,7 +7650,7 @@ func TestSetIter(t *testing.T) { k.SetIterKey(i) }) shouldPanic("Value.SetIterValue called on exhausted iterator", func() { - k.SetIterValue(i) + v.SetIterValue(i) }) i.Reset(m) -- GitLab From fad4a16fd43f6a72b6917eff656be27522809074 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 15 Oct 2021 11:22:03 -0400 Subject: [PATCH 1613/2500] cmd/go: use portable flags in TestScript/version_build_settings This fixes a test failure on the 386-longtest builder. For #37475 Change-Id: Icd1d3474968fcf85ef893190760fb488302abc3a Reviewed-on: https://go-review.googlesource.com/c/go/+/356209 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- .../go/testdata/script/version_build_settings.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cmd/go/testdata/script/version_build_settings.txt b/src/cmd/go/testdata/script/version_build_settings.txt index 7e93643b9f..1ced285ac3 100644 --- a/src/cmd/go/testdata/script/version_build_settings.txt +++ b/src/cmd/go/testdata/script/version_build_settings.txt @@ -8,17 +8,17 @@ stdout '^\tbuild\tcompiler\tgc$' # Toolchain flags are added if present. # The raw flags are included, with package patterns if specified. -go build -asmflags=all=-spectre=all +go build -asmflags=example.com/m=-D=FOO=bar go version -m m$GOEXE -stdout '^\tbuild\tasmflags\tall=-spectre=all$' +stdout '^\tbuild\tasmflags\texample\.com/m=-D=FOO=bar$' -go build -gcflags=all=-spectre=all +go build -gcflags=example.com/m=-N go version -m m$GOEXE -stdout '^\tbuild\tgcflags\tall=-spectre=all$' +stdout '^\tbuild\tgcflags\texample\.com/m=-N$' -go build -ldflags=-w +go build -ldflags=example.com/m=-w go version -m m$GOEXE -stdout '^\tbuild\tldflags\t-w$' +stdout '^\tbuild\tldflags\texample\.com/m=-w$' # gccgoflags are not added when gc is used, and vice versa. # TODO: test gccgo. -- GitLab From a80e53ec43d6ab925bb34d62dd8597a4227af363 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sun, 19 Sep 2021 09:13:47 -0700 Subject: [PATCH 1614/2500] cmd/compile: support new fully-inst types referenced during inlining Modify the phase for creating needed function/method instantiations and modifying functions to use those instantiations, so that the phase is self-contained and can be called again after inlining. This is to deal with the issue that inlining may reveal new fully-instantiated types whose methods must be instantiated. With this change, we have an extra phase for instantiation after inlining, to take care of the new fully-instantiated types that have shown up during inlining. We call inline.InlineCalls() for any new instantiated functions that are created. Change-Id: I4ddf0b1907e5f1f7d45891db7876455a99381133 Reviewed-on: https://go-review.googlesource.com/c/go/+/352870 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Alexander Rakoczy --- src/cmd/compile/internal/gc/main.go | 5 + src/cmd/compile/internal/noder/irgen.go | 32 +- src/cmd/compile/internal/noder/stencil.go | 454 +++++++++++---------- src/cmd/compile/internal/typecheck/subr.go | 11 +- test/typeparam/geninline.dir/a.go | 56 +++ test/typeparam/geninline.dir/main.go | 16 + test/typeparam/geninline.go | 7 + 7 files changed, 356 insertions(+), 225 deletions(-) create mode 100644 test/typeparam/geninline.dir/a.go create mode 100644 test/typeparam/geninline.dir/main.go create mode 100644 test/typeparam/geninline.go diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 8ddef6721f..74b21571b3 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -244,6 +244,11 @@ func Main(archInit func(*ssagen.ArchInfo)) { base.Timer.Start("fe", "inlining") if base.Flag.LowerL != 0 { inline.InlinePackage() + // If any new fully-instantiated types were referenced during + // inlining, we need to create needed instantiations. + if len(typecheck.GetInstTypeList()) > 0 { + noder.BuildInstantiations(false) + } } noder.MakeWrappers(typecheck.Target) // must happen after inlining diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index 982e811f5f..e20939de66 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -158,16 +158,6 @@ type irgen struct { // types which we need to finish, by doing g.fillinMethods. typesToFinalize []*typeDelayInfo - dnum int // for generating unique dictionary variables - - // Map from a name of function that been instantiated to information about - // its instantiated function (including dictionary format). - instInfoMap map[*types.Sym]*instInfo - - // dictionary syms which we need to finish, by writing out any itabconv - // entries. - dictSymsToFinalize []*delayInfo - // True when we are compiling a top-level generic function or method. Use to // avoid adding closures of generic functions/methods to the target.Decls // list. @@ -180,6 +170,23 @@ type irgen struct { curDecl string } +// genInst has the information for creating needed instantiations and modifying +// functions to use instantiations. +type genInst struct { + dnum int // for generating unique dictionary variables + + // Map from the names of all instantiations to information about the + // instantiations. + instInfoMap map[*types.Sym]*instInfo + + // Dictionary syms which we need to finish, by writing out any itabconv + // entries. + dictSymsToFinalize []*delayInfo + + // New instantiations created during this round of buildInstantiations(). + newInsts []ir.Node +} + func (g *irgen) later(fn func()) { g.laterFuncs = append(g.laterFuncs, fn) } @@ -308,8 +315,9 @@ Outer: typecheck.DeclareUniverse() - // Create any needed stencils of generic functions - g.stencil() + // Create any needed instantiations of generic functions and transform + // existing and new functions to use those instantiations. + BuildInstantiations(true) // Remove all generic functions from g.target.Decl, since they have been // used for stenciling, but don't compile. Generic functions will already diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 447fe8a538..cfa90e4399 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -9,6 +9,7 @@ package noder import ( "cmd/compile/internal/base" + "cmd/compile/internal/inline" "cmd/compile/internal/ir" "cmd/compile/internal/objw" "cmd/compile/internal/reflectdata" @@ -37,207 +38,54 @@ func infoPrint(format string, a ...interface{}) { } } -// stencil scans functions for instantiated generic function calls and creates the -// required instantiations for simple generic functions. It also creates -// instantiated methods for all fully-instantiated generic types that have been -// encountered already or new ones that are encountered during the stenciling -// process. -func (g *irgen) stencil() { - g.instInfoMap = make(map[*types.Sym]*instInfo) +var geninst genInst +func BuildInstantiations(preinliningMainScan bool) { + if geninst.instInfoMap == nil { + geninst.instInfoMap = make(map[*types.Sym]*instInfo) + } + geninst.buildInstantiations(preinliningMainScan) +} + +// buildInstantiations scans functions for generic function calls and methods, and +// creates the required instantiations. It also creates instantiated methods for all +// fully-instantiated generic types that have been encountered already or new ones +// that are encountered during the instantiation process. If preinliningMainScan is +// true, it scans all declarations in typecheck.Target.Decls first, before scanning +// any new instantiations created. If preinliningMainScan is false, we do not scan +// any existing decls - we only scan method instantiations for any new +// fully-instantiated types that we saw during inlining. +func (g *genInst) buildInstantiations(preinliningMainScan bool) { // Instantiate the methods of instantiated generic types that we have seen so far. g.instantiateMethods() - // Don't use range(g.target.Decls) - we also want to process any new instantiated - // functions that are created during this loop, in order to handle generic - // functions calling other generic functions. - for i := 0; i < len(g.target.Decls); i++ { - decl := g.target.Decls[i] - - // Look for function instantiations in bodies of non-generic - // functions or in global assignments (ignore global type and - // constant declarations). - switch decl.Op() { - case ir.ODCLFUNC: - if decl.Type().HasTParam() { - // Skip any generic functions - continue - } - // transformCall() below depends on CurFunc being set. - ir.CurFunc = decl.(*ir.Func) - - case ir.OAS, ir.OAS2, ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV, ir.OASOP: - // These are all the various kinds of global assignments, - // whose right-hand-sides might contain a function - // instantiation. - - default: - // The other possible ops at the top level are ODCLCONST - // and ODCLTYPE, which don't have any function - // instantiations. - continue - } - - // For all non-generic code, search for any function calls using - // generic function instantiations. Then create the needed - // instantiated function if it hasn't been created yet, and change - // to calling that function directly. - modified := false - closureRequired := false - // declInfo will be non-nil exactly if we are scanning an instantiated function - declInfo := g.instInfoMap[decl.Sym()] - - ir.Visit(decl, func(n ir.Node) { - if n.Op() == ir.OFUNCINST { - // generic F, not immediately called - closureRequired = true - } - if (n.Op() == ir.OMETHEXPR || n.Op() == ir.OMETHVALUE) && len(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) > 0 && !types.IsInterfaceMethod(n.(*ir.SelectorExpr).Selection.Type) { - // T.M or x.M, where T or x is generic, but not immediately - // called. Not necessary if the method selected is - // actually for an embedded interface field. - closureRequired = true - } - if n.Op() == ir.OCALL && n.(*ir.CallExpr).X.Op() == ir.OFUNCINST { - // We have found a function call using a generic function - // instantiation. - call := n.(*ir.CallExpr) - inst := call.X.(*ir.InstExpr) - nameNode, isMeth := g.getInstNameNode(inst) - targs := typecheck.TypesOf(inst.Targs) - st := g.getInstantiation(nameNode, targs, isMeth).fun - dictValue, usingSubdict := g.getDictOrSubdict(declInfo, n, nameNode, targs, isMeth) - if infoPrintMode { - dictkind := "Main dictionary" - if usingSubdict { - dictkind = "Sub-dictionary" - } - if inst.X.Op() == ir.OMETHVALUE { - fmt.Printf("%s in %v at generic method call: %v - %v\n", dictkind, decl, inst.X, call) - } else { - fmt.Printf("%s in %v at generic function call: %v - %v\n", dictkind, decl, inst.X, call) - } - } - - // Transform the Call now, which changes OCALL to - // OCALLFUNC and does typecheckaste/assignconvfn. Do - // it before installing the instantiation, so we are - // checking against non-shape param types in - // typecheckaste. - transformCall(call, nil) - - // Replace the OFUNCINST with a direct reference to the - // new stenciled function - call.X = st.Nname - if inst.X.Op() == ir.OMETHVALUE { - // When we create an instantiation of a method - // call, we make it a function. So, move the - // receiver to be the first arg of the function - // call. - call.Args.Prepend(inst.X.(*ir.SelectorExpr).X) - } - - // Add dictionary to argument list. - call.Args.Prepend(dictValue) - modified = true - } - if n.Op() == ir.OCALLMETH && n.(*ir.CallExpr).X.Op() == ir.ODOTMETH && len(deref(n.(*ir.CallExpr).X.Type().Recv().Type).RParams()) > 0 { - // Method call on a generic type, which was instantiated by stenciling. - // Method calls on explicitly instantiated types will have an OFUNCINST - // and are handled above. - call := n.(*ir.CallExpr) - meth := call.X.(*ir.SelectorExpr) - targs := deref(meth.Type().Recv().Type).RParams() - - t := meth.X.Type() - baseSym := deref(t).OrigSym() - baseType := baseSym.Def.(*ir.Name).Type() - var gf *ir.Name - for _, m := range baseType.Methods().Slice() { - if meth.Sel == m.Sym { - gf = m.Nname.(*ir.Name) - break - } - } - - // Transform the Call now, which changes OCALL - // to OCALLFUNC and does typecheckaste/assignconvfn. - transformCall(call, nil) - - st := g.getInstantiation(gf, targs, true).fun - dictValue, usingSubdict := g.getDictOrSubdict(declInfo, n, gf, targs, true) - // We have to be using a subdictionary, since this is - // a generic method call. - assert(usingSubdict) - - // Transform to a function call, by appending the - // dictionary and the receiver to the args. - call.SetOp(ir.OCALLFUNC) - call.X = st.Nname - call.Args.Prepend(dictValue, meth.X) - modified = true - } - }) - - // If we found a reference to a generic instantiation that wasn't an - // immediate call, then traverse the nodes of decl again (with - // EditChildren rather than Visit), where we actually change the - // reference to the instantiation to a closure that captures the - // dictionary, then does a direct call. - // EditChildren is more expensive than Visit, so we only do this - // in the infrequent case of an OFUNCINST without a corresponding - // call. - if closureRequired { - modified = true - var edit func(ir.Node) ir.Node - var outer *ir.Func - if f, ok := decl.(*ir.Func); ok { - outer = f - } - edit = func(x ir.Node) ir.Node { - if x.Op() == ir.OFUNCINST { - child := x.(*ir.InstExpr).X - if child.Op() == ir.OMETHEXPR || child.Op() == ir.OMETHVALUE { - // Call EditChildren on child (x.X), - // not x, so that we don't do - // buildClosure() on the - // METHEXPR/METHVALUE nodes as well. - ir.EditChildren(child, edit) - return g.buildClosure(outer, x) - } - } - ir.EditChildren(x, edit) - switch { - case x.Op() == ir.OFUNCINST: - return g.buildClosure(outer, x) - case (x.Op() == ir.OMETHEXPR || x.Op() == ir.OMETHVALUE) && - len(deref(x.(*ir.SelectorExpr).X.Type()).RParams()) > 0 && - !types.IsInterfaceMethod(x.(*ir.SelectorExpr).Selection.Type): - return g.buildClosure(outer, x) - } - return x - } - edit(decl) - } - if base.Flag.W > 1 && modified { - ir.Dump(fmt.Sprintf("\nmodified %v", decl), decl) + if preinliningMainScan { + n := len(typecheck.Target.Decls) + for i := 0; i < n; i++ { + g.scanForGenCalls(typecheck.Target.Decls[i]) } - ir.CurFunc = nil - // We may have seen new fully-instantiated generic types while - // instantiating any needed functions/methods in the above - // function. If so, instantiate all the methods of those types - // (which will then lead to more function/methods to scan in the loop). - g.instantiateMethods() + } + + // Scan all new instantiations created due to g.instantiateMethods() and the + // scan of current decls (if done). This loop purposely runs until no new + // instantiations are created. + for i := 0; i < len(g.newInsts); i++ { + g.scanForGenCalls(g.newInsts[i]) } g.finalizeSyms() // All the instantiations and dictionaries have been created. Now go through - // each instantiation and transform the various operations that need to make + // each new instantiation and transform the various operations that need to make // use of their dictionary. - l := len(g.instInfoMap) - for _, info := range g.instInfoMap { + l := len(g.newInsts) + for _, fun := range g.newInsts { + info := g.instInfoMap[fun.Sym()] g.dictPass(info) + if !preinliningMainScan { + // Prepare for the round of inlining below. + inline.CanInline(fun.(*ir.Func)) + } if doubleCheck { ir.Visit(info.fun, func(n ir.Node) { if n.Op() != ir.OCONVIFACE { @@ -255,13 +103,198 @@ func (g *irgen) stencil() { ir.Dump(fmt.Sprintf("\ndictpass %v", info.fun), info.fun) } } - assert(l == len(g.instInfoMap)) + if !preinliningMainScan { + // Extra round of inlining for the new instantiations (only if + // preinliningMainScan is false, which means we have already done the + // main round of inlining) + for _, fun := range g.newInsts { + inline.InlineCalls(fun.(*ir.Func)) + } + } + assert(l == len(g.newInsts)) + g.newInsts = nil +} + +// scanForGenCalls scans a single function (or global assignment), looking for +// references to generic functions/methods. At each such reference, it creates any +// required instantiation and transforms the reference. +func (g *genInst) scanForGenCalls(decl ir.Node) { + switch decl.Op() { + case ir.ODCLFUNC: + if decl.Type().HasTParam() { + // Skip any generic functions + return + } + // transformCall() below depends on CurFunc being set. + ir.CurFunc = decl.(*ir.Func) + + case ir.OAS, ir.OAS2, ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV, ir.OASOP: + // These are all the various kinds of global assignments, + // whose right-hand-sides might contain a function + // instantiation. + + default: + // The other possible ops at the top level are ODCLCONST + // and ODCLTYPE, which don't have any function + // instantiations. + return + } + + // Search for any function references using generic function/methods. Then + // create the needed instantiated function if it hasn't been created yet, and + // change to calling that function directly. + modified := false + closureRequired := false + // declInfo will be non-nil exactly if we are scanning an instantiated function + declInfo := g.instInfoMap[decl.Sym()] + + ir.Visit(decl, func(n ir.Node) { + if n.Op() == ir.OFUNCINST { + // generic F, not immediately called + closureRequired = true + } + if (n.Op() == ir.OMETHEXPR || n.Op() == ir.OMETHVALUE) && len(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) > 0 && !types.IsInterfaceMethod(n.(*ir.SelectorExpr).Selection.Type) { + // T.M or x.M, where T or x is generic, but not immediately + // called. Not necessary if the method selected is + // actually for an embedded interface field. + closureRequired = true + } + if n.Op() == ir.OCALL && n.(*ir.CallExpr).X.Op() == ir.OFUNCINST { + // We have found a function call using a generic function + // instantiation. + call := n.(*ir.CallExpr) + inst := call.X.(*ir.InstExpr) + nameNode, isMeth := g.getInstNameNode(inst) + targs := typecheck.TypesOf(inst.Targs) + st := g.getInstantiation(nameNode, targs, isMeth).fun + dictValue, usingSubdict := g.getDictOrSubdict(declInfo, n, nameNode, targs, isMeth) + if infoPrintMode { + dictkind := "Main dictionary" + if usingSubdict { + dictkind = "Sub-dictionary" + } + if inst.X.Op() == ir.OMETHVALUE { + fmt.Printf("%s in %v at generic method call: %v - %v\n", dictkind, decl, inst.X, call) + } else { + fmt.Printf("%s in %v at generic function call: %v - %v\n", dictkind, decl, inst.X, call) + } + } + + // Transform the Call now, which changes OCALL to + // OCALLFUNC and does typecheckaste/assignconvfn. Do + // it before installing the instantiation, so we are + // checking against non-shape param types in + // typecheckaste. + transformCall(call, nil) + + // Replace the OFUNCINST with a direct reference to the + // new stenciled function + call.X = st.Nname + if inst.X.Op() == ir.OMETHVALUE { + // When we create an instantiation of a method + // call, we make it a function. So, move the + // receiver to be the first arg of the function + // call. + call.Args.Prepend(inst.X.(*ir.SelectorExpr).X) + } + + // Add dictionary to argument list. + call.Args.Prepend(dictValue) + modified = true + } + if n.Op() == ir.OCALLMETH && n.(*ir.CallExpr).X.Op() == ir.ODOTMETH && len(deref(n.(*ir.CallExpr).X.Type().Recv().Type).RParams()) > 0 { + // Method call on a generic type, which was instantiated by stenciling. + // Method calls on explicitly instantiated types will have an OFUNCINST + // and are handled above. + call := n.(*ir.CallExpr) + meth := call.X.(*ir.SelectorExpr) + targs := deref(meth.Type().Recv().Type).RParams() + + t := meth.X.Type() + baseSym := deref(t).OrigSym() + baseType := baseSym.Def.(*ir.Name).Type() + var gf *ir.Name + for _, m := range baseType.Methods().Slice() { + if meth.Sel == m.Sym { + gf = m.Nname.(*ir.Name) + break + } + } + + // Transform the Call now, which changes OCALL + // to OCALLFUNC and does typecheckaste/assignconvfn. + transformCall(call, nil) + + st := g.getInstantiation(gf, targs, true).fun + dictValue, usingSubdict := g.getDictOrSubdict(declInfo, n, gf, targs, true) + // We have to be using a subdictionary, since this is + // a generic method call. + assert(usingSubdict) + + // Transform to a function call, by appending the + // dictionary and the receiver to the args. + call.SetOp(ir.OCALLFUNC) + call.X = st.Nname + call.Args.Prepend(dictValue, meth.X) + modified = true + } + }) + + // If we found a reference to a generic instantiation that wasn't an + // immediate call, then traverse the nodes of decl again (with + // EditChildren rather than Visit), where we actually change the + // reference to the instantiation to a closure that captures the + // dictionary, then does a direct call. + // EditChildren is more expensive than Visit, so we only do this + // in the infrequent case of an OFUNCINST without a corresponding + // call. + if closureRequired { + modified = true + var edit func(ir.Node) ir.Node + var outer *ir.Func + if f, ok := decl.(*ir.Func); ok { + outer = f + } + edit = func(x ir.Node) ir.Node { + if x.Op() == ir.OFUNCINST { + child := x.(*ir.InstExpr).X + if child.Op() == ir.OMETHEXPR || child.Op() == ir.OMETHVALUE { + // Call EditChildren on child (x.X), + // not x, so that we don't do + // buildClosure() on the + // METHEXPR/METHVALUE nodes as well. + ir.EditChildren(child, edit) + return g.buildClosure(outer, x) + } + } + ir.EditChildren(x, edit) + switch { + case x.Op() == ir.OFUNCINST: + return g.buildClosure(outer, x) + case (x.Op() == ir.OMETHEXPR || x.Op() == ir.OMETHVALUE) && + len(deref(x.(*ir.SelectorExpr).X.Type()).RParams()) > 0 && + !types.IsInterfaceMethod(x.(*ir.SelectorExpr).Selection.Type): + return g.buildClosure(outer, x) + } + return x + } + edit(decl) + } + if base.Flag.W > 1 && modified { + ir.Dump(fmt.Sprintf("\nmodified %v", decl), decl) + } + ir.CurFunc = nil + // We may have seen new fully-instantiated generic types while + // instantiating any needed functions/methods in the above + // function. If so, instantiate all the methods of those types + // (which will then lead to more function/methods to scan in the loop). + g.instantiateMethods() } // buildClosure makes a closure to implement x, a OFUNCINST or OMETHEXPR/OMETHVALUE // of generic type. outer is the containing function (or nil if closure is // in a global assignment instead of a function). -func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { +func (g *genInst) buildClosure(outer *ir.Func, x ir.Node) ir.Node { pos := x.Pos() var target *ir.Func // target instantiated function/method var dictValue ir.Node // dictionary to use @@ -423,8 +456,8 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { rcvrVar.Defn = rcvrAssign if outer == nil { rcvrVar.Class = ir.PEXTERN - g.target.Decls = append(g.target.Decls, rcvrAssign) - g.target.Externs = append(g.target.Externs, rcvrVar) + typecheck.Target.Decls = append(typecheck.Target.Decls, rcvrAssign) + typecheck.Target.Externs = append(typecheck.Target.Externs, rcvrVar) } else { rcvrVar.Class = ir.PAUTO rcvrVar.Curfn = outer @@ -496,7 +529,7 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { ir.FinishCaptureNames(pos, outer, fn) // Make a closure referencing our new internal function. - c := ir.UseClosure(fn.OClosure, g.target) + c := ir.UseClosure(fn.OClosure, typecheck.Target) var init []ir.Node if outer != nil { init = append(init, dictAssign) @@ -510,12 +543,13 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node { // instantiateMethods instantiates all the methods (and associated dictionaries) of // all fully-instantiated generic types that have been added to typecheck.instTypeList. // It continues until no more types are added to typecheck.instTypeList. -func (g *irgen) instantiateMethods() { +func (g *genInst) instantiateMethods() { for { instTypeList := typecheck.GetInstTypeList() if len(instTypeList) == 0 { break } + typecheck.ClearInstTypeList() for _, typ := range instTypeList { assert(!typ.HasShape()) // Mark runtime type as needed, since this ensures that the @@ -548,7 +582,7 @@ func (g *irgen) instantiateMethods() { } // getInstNameNode returns the name node for the method or function being instantiated, and a bool which is true if a method is being instantiated. -func (g *irgen) getInstNameNode(inst *ir.InstExpr) (*ir.Name, bool) { +func (g *genInst) getInstNameNode(inst *ir.InstExpr) (*ir.Name, bool) { if meth, ok := inst.X.(*ir.SelectorExpr); ok { return meth.Selection.Nname.(*ir.Name), true } else { @@ -561,7 +595,7 @@ func (g *irgen) getInstNameNode(inst *ir.InstExpr) (*ir.Name, bool) { // or main/static dictionary, as needed, and also returns a boolean indicating if a // sub-dictionary was accessed. nameNode is the particular function or method being // called/referenced, and targs are the type arguments. -func (g *irgen) getDictOrSubdict(declInfo *instInfo, n ir.Node, nameNode *ir.Name, targs []*types.Type, isMeth bool) (ir.Node, bool) { +func (g *genInst) getDictOrSubdict(declInfo *instInfo, n ir.Node, nameNode *ir.Name, targs []*types.Type, isMeth bool) (ir.Node, bool) { var dict ir.Node usingSubdict := false if declInfo != nil { @@ -603,7 +637,7 @@ func checkFetchBody(nameNode *ir.Name) { // getInstantiation gets the instantiantion and dictionary of the function or method nameNode // with the type arguments shapes. If the instantiated function is not already // cached, then it calls genericSubst to create the new instantiation. -func (g *irgen) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMeth bool) *instInfo { +func (g *genInst) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMeth bool) *instInfo { checkFetchBody(nameNode) // Convert any non-shape type arguments to their shape, so we can reduce the @@ -645,7 +679,8 @@ func (g *irgen) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMeth // This ensures that the linker drops duplicates of this instantiation. // All just works! st.SetDupok(true) - g.target.Decls = append(g.target.Decls, st) + typecheck.Target.Decls = append(typecheck.Target.Decls, st) + g.newInsts = append(g.newInsts, st) } return info } @@ -653,7 +688,7 @@ func (g *irgen) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMeth // Struct containing info needed for doing the substitution as we create the // instantiation of a generic function with specified type arguments. type subster struct { - g *irgen + g *genInst isMethod bool // If a method is being instantiated newf *ir.Func // Func node for the new stenciled function ts typecheck.Tsubster @@ -669,7 +704,7 @@ type subster struct { // function type where the receiver becomes the first parameter. For either a generic // method or function, a dictionary parameter is the added as the very first // parameter. genericSubst fills in info.dictParam and info.tparamToBound. -func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes []*types.Type, isMethod bool, info *instInfo) *ir.Func { +func (g *genInst) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes []*types.Type, isMethod bool, info *instInfo) *ir.Func { var tparams []*types.Type if isMethod { // Get the type params from the method receiver (after skipping @@ -1170,7 +1205,8 @@ func (subst *subster) node(n ir.Node) ir.Node { subst.newf = saveNewf ir.CurFunc = saveNewf - m = ir.UseClosure(newfn.OClosure, subst.g.target) + m = ir.UseClosure(newfn.OClosure, typecheck.Target) + subst.g.newInsts = append(subst.g.newInsts, m.(*ir.ClosureExpr).Func) m.(*ir.ClosureExpr).SetInit(subst.list(x.Init())) } @@ -1182,7 +1218,7 @@ func (subst *subster) node(n ir.Node) ir.Node { // dictPass takes a function instantiation and does the transformations on the // operations that need to make use of the dictionary param. -func (g *irgen) dictPass(info *instInfo) { +func (g *genInst) dictPass(info *instInfo) { savef := ir.CurFunc ir.CurFunc = info.fun @@ -1503,7 +1539,7 @@ func markTypeUsed(t *types.Type, lsym *obj.LSym) { // getDictionarySym returns the dictionary for the named generic function gf, which // is instantiated with the type arguments targs. -func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) *types.Sym { +func (g *genInst) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) *types.Sym { if len(targs) == 0 { base.Fatalf("%s should have type arguments", gf.Sym().Name) } @@ -1678,7 +1714,7 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool) // dictionaries and method instantiations to be complete, so, to avoid recursive // dependencies, we finalize the itab lsyms only after all dictionaries syms and // instantiations have been created. -func (g *irgen) finalizeSyms() { +func (g *genInst) finalizeSyms() { for _, d := range g.dictSymsToFinalize { infoPrint("=== Finalizing dictionary %s\n", d.sym.Name) @@ -1744,7 +1780,7 @@ func (g *irgen) finalizeSyms() { g.dictSymsToFinalize = nil } -func (g *irgen) getDictionaryValue(gf *ir.Name, targs []*types.Type, isMeth bool) ir.Node { +func (g *genInst) getDictionaryValue(gf *ir.Name, targs []*types.Type, isMeth bool) ir.Node { sym := g.getDictionarySym(gf, targs, isMeth) // Make (or reuse) a node referencing the dictionary symbol. @@ -1792,7 +1828,7 @@ func hasShapeTypes(targs []*types.Type) bool { // getInstInfo get the dictionary format for a function instantiation- type params, derived // types, and needed subdictionaries and itabs. -func (g *irgen) getInstInfo(st *ir.Func, shapes []*types.Type, instInfo *instInfo) { +func (g *genInst) getInstInfo(st *ir.Func, shapes []*types.Type, instInfo *instInfo) { info := instInfo.dictInfo info.shapeParams = shapes @@ -2100,7 +2136,7 @@ func assertToBound(info *instInfo, dictVar *ir.Name, pos src.XPos, rcvr ir.Node, // // The returned closure is fully substituted and has already had any needed // transformations done. -func (g *irgen) buildClosure2(info *instInfo, m ir.Node) ir.Node { +func (g *genInst) buildClosure2(info *instInfo, m ir.Node) ir.Node { outer := info.fun pos := m.Pos() typ := m.Type() // type of the closure @@ -2155,5 +2191,5 @@ func (g *irgen) buildClosure2(info *instInfo, m ir.Node) ir.Node { ir.FinishCaptureNames(pos, outer, fn) // Do final checks on closure and return it. - return ir.UseClosure(fn.OClosure, g.target) + return ir.UseClosure(fn.OClosure, typecheck.Target) } diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 6288d15a01..b3fc7459e1 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1007,19 +1007,22 @@ func assert(p bool) { // List of newly fully-instantiated types who should have their methods generated. var instTypeList []*types.Type -// NeedInstType adds a new fully-instantied type to instTypeList. +// NeedInstType adds a new fully-instantiated type to instTypeList. func NeedInstType(t *types.Type) { instTypeList = append(instTypeList, t) } -// GetInstTypeList returns the current contents of instTypeList, and sets -// instTypeList to nil. +// GetInstTypeList returns the current contents of instTypeList. func GetInstTypeList() []*types.Type { r := instTypeList - instTypeList = nil return r } +// ClearInstTypeList clears the contents of instTypeList. +func ClearInstTypeList() { + instTypeList = nil +} + // General type substituter, for replacing typeparams with type args. type Tsubster struct { Tparams []*types.Type diff --git a/test/typeparam/geninline.dir/a.go b/test/typeparam/geninline.dir/a.go new file mode 100644 index 0000000000..fe5ba22f6e --- /dev/null +++ b/test/typeparam/geninline.dir/a.go @@ -0,0 +1,56 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type IVal[T comparable] interface { + check(want T) +} + +type Val[T comparable] struct { + val T +} + +//go:noinline +func (l *Val[T]) check(want T) { + if l.val != want { + panic("hi") + } +} + +func Test1() { + var l Val[int] + if l.val != 0 { + panic("hi") + } + _ = IVal[int](&l) +} + +func Test2() { + var l Val[float64] + l.val = 3.0 + l.check(float64(3)) + _ = IVal[float64](&l) +} + +type privateVal[T comparable] struct { + val T +} + +//go:noinline +func (l *privateVal[T]) check(want T) { + if l.val != want { + panic("hi") + } +} + +type Outer struct { + val privateVal[string] +} + +func Test3() { + var o Outer + o.val.check("") + _ = IVal[string](&o.val) +} diff --git a/test/typeparam/geninline.dir/main.go b/test/typeparam/geninline.dir/main.go new file mode 100644 index 0000000000..6dc36ba8af --- /dev/null +++ b/test/typeparam/geninline.dir/main.go @@ -0,0 +1,16 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "a" + +// Testing inlining of functions that refer to instantiated exported and non-exported +// generic types. + +func main() { + a.Test1() + a.Test2() + a.Test3() +} diff --git a/test/typeparam/geninline.go b/test/typeparam/geninline.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/geninline.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From 8c99421f01aca303240a8f809bc65fa0c56db861 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 13 Oct 2021 18:50:06 -0700 Subject: [PATCH 1615/2500] cmd/compile/internal/types2: add debugging support for delayed actions Add a simple mechanism to provide formatted descriptions for delayed actions. The comment strings are printed when tracing is enabled and the delayed action is executed. This results in more easily decipherable tracing output. Requires debug mode in order to minimize the overhead during normal execution. Use the mechanism in a few places to show typical use. Also cleaned up a few unrelated comments. Change-Id: Ic273c380c3963341500396ec62b694d143c25de2 Reviewed-on: https://go-review.googlesource.com/c/go/+/355871 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/check.go | 40 +++++++++++++++++-- src/cmd/compile/internal/types2/decl.go | 2 +- .../compile/internal/types2/instantiate.go | 3 +- src/cmd/compile/internal/types2/interface.go | 2 +- src/cmd/compile/internal/types2/struct.go | 2 +- src/cmd/compile/internal/types2/typexpr.go | 2 - 6 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go index d89ec3d29f..470376f8e8 100644 --- a/src/cmd/compile/internal/types2/check.go +++ b/src/cmd/compile/internal/types2/check.go @@ -74,6 +74,28 @@ type dotImportKey struct { name string } +// An action describes a (delayed) action. +type action struct { + f func() // action to be executed + desc *actionDesc // action description; may be nil, requires debug to be set +} + +// If debug is set, describef sets a printf-formatted description for action a. +// Otherwise, it is a no-op. +func (a *action) describef(pos poser, format string, args ...interface{}) { + if debug { + a.desc = &actionDesc{pos, format, args} + } +} + +// An actionDesc provides information on an action. +// For debugging only. +type actionDesc struct { + pos poser + format string + args []interface{} +} + // A Checker maintains the state of the type checker. // It must be created with NewChecker. type Checker struct { @@ -108,7 +130,7 @@ type Checker struct { firstErr error // first error encountered methods map[*TypeName][]*Func // maps package scope type names to associated non-blank (non-interface) methods untyped map[syntax.Expr]exprInfo // map of expressions without final type - delayed []func() // stack of delayed action segments; segments are processed in FIFO order + delayed []action // stack of delayed action segments; segments are processed in FIFO order objPath []Object // path of object dependencies during type inference (for cycle reporting) // context within which the current object is type-checked @@ -144,8 +166,12 @@ func (check *Checker) rememberUntyped(e syntax.Expr, lhs bool, mode operandMode, // either at the end of the current statement, or in case of a local constant // or variable declaration, before the constant or variable is in scope // (so that f still sees the scope before any new declarations). -func (check *Checker) later(f func()) { - check.delayed = append(check.delayed, f) +// later returns the pushed action so one can provide a description +// via action.describef for debugging, if desired. +func (check *Checker) later(f func()) *action { + i := len(check.delayed) + check.delayed = append(check.delayed, action{f: f}) + return &check.delayed[i] } // push pushes obj onto the object path and returns its index in the path. @@ -259,6 +285,7 @@ func (check *Checker) checkFiles(files []*syntax.File) (err error) { print := func(msg string) { if check.conf.Trace { + fmt.Println() fmt.Println(msg) } } @@ -309,7 +336,12 @@ func (check *Checker) processDelayed(top int) { // add more actions (such as nested functions), so // this is a sufficiently bounded process. for i := top; i < len(check.delayed); i++ { - check.delayed[i]() // may append to check.delayed + a := &check.delayed[i] + if check.conf.Trace && a.desc != nil { + fmt.Println() + check.trace(a.desc.pos.Pos(), "-- "+a.desc.format, a.desc.args...) + } + a.f() // may append to check.delayed } assert(top <= len(check.delayed)) // stack must not have shrunk check.delayed = check.delayed[:top] diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 9fd60d6aa2..a605057579 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -557,7 +557,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named if check.isImportedConstraint(rhs) && !check.allowVersion(check.pkg, 1, 18) { check.errorf(tdecl.Type.Pos(), "using type constraint %s requires go1.18 or later", rhs) } - }) + }).describef(obj, "validType(%s)", obj.Name()) alias := tdecl.Alias if alias && tdecl.TParamList != nil { diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 5da371f201..5e45ea33ce 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -63,7 +63,6 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, posLis if res != nil { // Calling under() here may lead to endless instantiations. // Test case: type T[P any] T[P] - // TODO(gri) investigate if that's a bug or to be expected. under = safeUnderlying(res) } check.trace(pos, "=> %s (under = %s)", res, under) @@ -115,7 +114,7 @@ func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type, ctxt *Con } } tname := NewTypeName(pos, t.obj.pkg, t.obj.name, nil) - named := check.newNamed(tname, t, nil, nil, nil) // methods and tparams are set when named is resolved + named := check.newNamed(tname, t, nil, nil, nil) // underlying, tparams, and methods are set when named is resolved named.targs = NewTypeList(targs) named.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, []*Func) { return expandNamed(ctxt, n, pos) diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index 0879d29d3d..0704628dc6 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -172,7 +172,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType check.later(func() { computeInterfaceTypeSet(check, iface.Pos(), ityp) ityp.check = nil - }) + }).describef(iface, "compute type set for %s", ityp) } func flattenUnion(list []syntax.Expr, x syntax.Expr) []syntax.Expr { diff --git a/src/cmd/compile/internal/types2/struct.go b/src/cmd/compile/internal/types2/struct.go index f0c27c0150..933d7ef947 100644 --- a/src/cmd/compile/internal/types2/struct.go +++ b/src/cmd/compile/internal/types2/struct.go @@ -154,7 +154,7 @@ func (check *Checker) structType(styp *Struct, e *syntax.StructType) { check.error(embeddedPos, "embedded field type cannot be a pointer to an interface") } } - }) + }).describef(embeddedPos, "check embedded type %s", embeddedTyp) } } diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 746fe78b38..646becbdae 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -214,8 +214,6 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) { if T != nil { // Calling under() here may lead to endless instantiations. // Test case: type T[P any] *T[P] - // TODO(gri) investigate if that's a bug or to be expected - // (see also analogous comment in Checker.instantiate). under = safeUnderlying(T) } if T == under { -- GitLab From 8331f25e96d6120bb0ec212bd03abcae53282769 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Wed, 15 Sep 2021 09:56:09 -0700 Subject: [PATCH 1616/2500] reflect: make Elem panic on bad notinheap pointers This CL fixes the subtle issue that Elem can promote a not-in-heap pointer, which could be any bit pattern, into an unsafe.Pointer, which the garbage collector can see. If that resulting value is bad, it can crash the GC. Make sure that we don't introduce bad pointers that way. We can make Elem() panic, because any such bad pointers are in the Go heap, and not-in-heap pointers are not allowed to point into the Go heap. Update #48399 Change-Id: Ieaf35a611b16b4dfb5e907e229ed4a2aed30e18c Reviewed-on: https://go-review.googlesource.com/c/go/+/350153 Trust: Keith Randall Trust: Ian Lance Taylor Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/reflect/all_test.go | 20 ++++++++++++++++++++ src/reflect/value.go | 17 +++++++++++++++++ src/runtime/mbitmap.go | 9 +++++++++ 3 files changed, 46 insertions(+) diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index 427855b02e..8642d60f8b 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -7697,3 +7697,23 @@ func TestSetIter(t *testing.T) { t.Errorf("pointer incorrect: got %d want %d", got, b) } } + +//go:notinheap +type nih struct{ x int } + +var global_nih = nih{x: 7} + +func TestNotInHeapDeref(t *testing.T) { + // See issue 48399. + v := ValueOf((*nih)(nil)) + v.Elem() + shouldPanic("reflect: call of reflect.Value.Field on zero Value", func() { v.Elem().Field(0) }) + + v = ValueOf(&global_nih) + if got := v.Elem().Field(0).Int(); got != 7 { + t.Fatalf("got %d, want 7", got) + } + + v = ValueOf((*nih)(unsafe.Pointer(new(int)))) + shouldPanic("reflect: reflect.Value.Elem on an invalid notinheap pointer", func() { v.Elem() }) +} diff --git a/src/reflect/value.go b/src/reflect/value.go index abcc346de8..449f3bbb3c 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -1169,6 +1169,21 @@ func (v Value) Elem() Value { case Ptr: ptr := v.ptr if v.flag&flagIndir != 0 { + if ifaceIndir(v.typ) { + // This is a pointer to a not-in-heap object. ptr points to a uintptr + // in the heap. That uintptr is the address of a not-in-heap object. + // In general, pointers to not-in-heap objects can be total junk. + // But Elem() is asking to dereference it, so the user has asserted + // that at least it is a valid pointer (not just an integer stored in + // a pointer slot). So let's check, to make sure that it isn't a pointer + // that the runtime will crash on if it sees it during GC or write barriers. + // Since it is a not-in-heap pointer, all pointers to the heap are + // forbidden! That makes the test pretty easy. + // See issue 48399. + if !verifyNotInHeapPtr(*(*uintptr)(ptr)) { + panic("reflect: reflect.Value.Elem on an invalid notinheap pointer") + } + } ptr = *(*unsafe.Pointer)(ptr) } // The returned value's address is v's value. @@ -3406,6 +3421,8 @@ func typedslicecopy(elemType *rtype, dst, src unsafeheader.Slice) int //go:noescape func typehash(t *rtype, p unsafe.Pointer, h uintptr) uintptr +func verifyNotInHeapPtr(p uintptr) bool + // Dummy annotation marking that the value x escapes, // for use in cases where the reflect code is so clever that // the compiler cannot follow. diff --git a/src/runtime/mbitmap.go b/src/runtime/mbitmap.go index daf1fcfbc0..3330ddd62e 100644 --- a/src/runtime/mbitmap.go +++ b/src/runtime/mbitmap.go @@ -417,6 +417,15 @@ func findObject(p, refBase, refOff uintptr) (base uintptr, s *mspan, objIndex ui return } +// verifyNotInHeapPtr reports whether converting the not-in-heap pointer into a unsafe.Pointer is ok. +//go:linkname reflect_verifyNotInHeapPtr reflect.verifyNotInHeapPtr +func reflect_verifyNotInHeapPtr(p uintptr) bool { + // Conversion to a pointer is ok as long as findObject above does not call badPointer. + // Since we're already promised that p doesn't point into the heap, just disallow heap + // pointers and the special clobbered pointer. + return spanOf(p) == nil && p != clobberdeadPtr +} + // next returns the heapBits describing the next pointer-sized word in memory. // That is, if h describes address p, h.next() describes p+ptrSize. // Note that next does not modify h. The caller must record the result. -- GitLab From cfe6763783615233ec7ae863784b898718d14c40 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Wed, 13 Oct 2021 16:49:27 -0400 Subject: [PATCH 1617/2500] internal/fuzz: fix bugs with minimization This pulls in some code and tests from CL 353355. This change makes some refactors for when we read to and write from memory during minimization. That fixes a bug when minimizing interesting inputs. Now, if an error occurs while minimizing an interesting input, that value will continue to be minimized as a crash, and returned to the user. This change also allows minimization of a crash that occurred during the warmup phase. We don't want to minimize failures in the seed corpus, but if an entry in the cache causes a new failure, then there's no compelling reason why we shouldn't try to minimize it. Fixes #48731 Change-Id: I7262cecd8ea7ae6fdf932f3a36db55fb062a1f2a Reviewed-on: https://go-review.googlesource.com/c/go/+/355691 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Roland Shoemaker --- .../go/testdata/script/test_fuzz_minimize.txt | 112 +++++++++++------- .../testdata/script/test_fuzz_seed_corpus.txt | 38 +++++- src/internal/fuzz/fuzz.go | 6 +- src/internal/fuzz/minimize_test.go | 13 +- src/internal/fuzz/worker.go | 71 +++++------ 5 files changed, 151 insertions(+), 89 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize.txt b/src/cmd/go/testdata/script/test_fuzz_minimize.txt index 0a0359fabb..56abc68104 100644 --- a/src/cmd/go/testdata/script/test_fuzz_minimize.txt +++ b/src/cmd/go/testdata/script/test_fuzz_minimize.txt @@ -7,56 +7,72 @@ env GOCACHE=$WORK/gocache # Test that fuzzminimizetime cannot be negative seconds -! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x -fuzzminimizetime=-1ms minimizer_test.go +! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x -fuzzminimizetime=-1ms . ! stdout '^ok' ! stdout 'contains a non-zero byte' stdout 'invalid duration' stdout FAIL # Test that fuzzminimizetime cannot be negative times -! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x -fuzzminimizetime=-1x minimizer_test.go +! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x -fuzzminimizetime=-1x . ! stdout '^ok' ! stdout 'contains a non-zero byte' stdout 'invalid count' stdout FAIL # Test that fuzzminimizetime can be zero seconds, and minimization is disabled -! go test -fuzz=FuzzMinimizeZeroDurationSet -run=FuzzMinimizeZeroDurationSet -fuzztime=10000x -fuzzminimizetime=0s minimizer_test.go +! go test -fuzz=FuzzMinimizeZeroDurationSet -run=FuzzMinimizeZeroDurationSet -fuzztime=10000x -fuzzminimizetime=0s . ! stdout '^ok' ! stdout 'minimizing' stdout 'there was an Error' stdout FAIL # Test that fuzzminimizetime can be zero times, and minimization is disabled -! go test -fuzz=FuzzMinimizeZeroLimitSet -run=FuzzMinimizeZeroLimitSet -fuzztime=10000x -fuzzminimizetime=0x minimizer_test.go +! go test -fuzz=FuzzMinimizeZeroLimitSet -run=FuzzMinimizeZeroLimitSet -fuzztime=10000x -fuzzminimizetime=0x . ! stdout '^ok' ! stdout 'minimizing' stdout 'there was an Error' stdout FAIL +# Test that minimization occurs for a crash that appears while minimizing a +# newly found interesting input. There must be only one worker for this test to +# be flaky like we want. +! go test -fuzz=FuzzMinimizerCrashInMinimization -run=FuzzMinimizerCrashInMinimization -fuzztime=10000x -parallel=1 . +! stdout '^ok' +stdout 'got the minimum size!' +stdout 'flaky failure' +stdout FAIL + +# Make sure the crash that was written will fail when run with go test +! go test -run=FuzzMinimizerCrashInMinimization . + +# Clear testdata. +rm testdata + # Test that minimization is working for recoverable errors. -! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x minimizer_test.go +! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x . ! stdout '^ok' stdout 'got the minimum size!' -stdout 'contains a non-zero byte' +# The error message that was printed should be for the one written to testdata. +stdout 'contains a non-zero byte of length 50' stdout FAIL # Check that the bytes written to testdata are of length 50 (the minimum size) -go run check_testdata.go FuzzMinimizerRecoverable 50 +go run ./check_testdata FuzzMinimizerRecoverable 50 # Test that re-running the minimized value causes a crash. -! go test -run=FuzzMinimizerRecoverable minimizer_test.go +! go test -run=FuzzMinimizerRecoverable . rm testdata # Test that minimization doesn't run for non-recoverable errors. -! go test -fuzz=FuzzMinimizerNonrecoverable -run=FuzzMinimizerNonrecoverable -fuzztime=10000x minimizer_test.go +! go test -fuzz=FuzzMinimizerNonrecoverable -run=FuzzMinimizerNonrecoverable -fuzztime=10000x . ! stdout '^ok' ! stdout 'minimizing' stdout 'fuzzing process terminated unexpectedly: exit status 99' stdout FAIL # Check that re-running the value causes a crash. -! go test -run=FuzzMinimizerNonrecoverable minimizer_test.go +! go test -run=FuzzMinimizerNonrecoverable . rm testdata # Clear the fuzzing cache. There may already be minimized inputs that would @@ -65,35 +81,43 @@ go clean -fuzzcache # Test that minimization can be cancelled by fuzzminimizetime and the latest # crash will still be logged and written to testdata. -! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=100x -fuzzminimizetime=1x minimizer_test.go +! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=100x -fuzzminimizetime=1x . ! stdout '^ok' stdout 'testdata[/\\]fuzz[/\\]FuzzMinimizerRecoverable[/\\]' ! stdout 'got the minimum size!' # it shouldn't have had enough time to minimize it stdout FAIL # Test that re-running the unminimized value causes a crash. -! go test -run=FuzzMinimizerRecoverable minimizer_test.go - -! go test -fuzz=FuzzMinimizerTooSlow -run=FuzzMinimizerTooSlow -fuzzminimizetime=3s minimizer_test.go -stdout 'fuzz: minimizing' -stdout 'fuzz: elapsed: \d+s, minimizing' -stdout 'testdata[/\\]fuzz[/\\]FuzzMinimizerTooSlow[/\\]' -stdout FAIL +! go test -run=FuzzMinimizerRecoverable . # TODO(jayconrod,katiehockman): add a test which verifies that the right bytes # are written to testdata in the case of an interrupt during minimization. -- go.mod -- -module m +module example.com/y go 1.16 --- minimizer_test.go -- -package fuzz_test +-- y.go -- +package y import ( + "bytes" + "io" +) + +func Y(w io.Writer, b []byte) { + if !bytes.Equal(b, []byte("y")) { + w.Write([]byte("not equal")) + } +} +-- y_test.go -- +package y + +import ( + "bytes" + "io" "os" "testing" - "time" ) func FuzzMinimizeZeroDurationSet(f *testing.F) { @@ -126,42 +150,42 @@ func FuzzMinimizerRecoverable(f *testing.F) { if len(b) == 50 { t.Log("got the minimum size!") } - t.Fatal("contains a non-zero byte") + t.Fatalf("contains a non-zero byte of length %d", len(b)) } } }) } func FuzzMinimizerNonrecoverable(f *testing.F) { - f.Add(make([]byte, 100)) f.Fuzz(func(t *testing.T, b []byte) { - if len(b) < 50 { - // Make sure that b is large enough that it can be minimized - return - } - // Given the randomness of the mutations, this should allow the - // minimizer to trim down the value a bit. - for _, n := range b { - if n != 0 { - t.Log("contains a non-zero byte") - os.Exit(99) - } - } + os.Exit(99) }) } -func FuzzMinimizerTooSlow(f *testing.F) { +func FuzzMinimizerCrashInMinimization(f *testing.F) { + seed := make([]byte, 1000) + f.Add(seed) f.Fuzz(func(t *testing.T, b []byte) { - if len(b) > 50 { - t.Error("error here") - time.Sleep(2 * time.Second) + if len(b) < 50 || len(b) > 1100 { + // Make sure that b is large enough that it can be minimized + return + } + if !bytes.Equal(b, seed) { + // This should have hit a new edge, and the interesting input + // should be attempting minimization + Y(io.Discard, b) + } + if len(b) < 350 { + t.Error("flaky failure") + } + if len(b) == 50 { + t.Log("got the minimum size!") } }) } - --- check_testdata.go -- -// +build ignore - +-- empty/empty.go -- +package empty +-- check_testdata/check_testdata.go -- package main import ( diff --git a/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt b/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt index 5d04d8c022..18f634a3b6 100644 --- a/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt +++ b/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt @@ -47,6 +47,23 @@ cp cache-file $GOCACHE/fuzz/example.com/x/FuzzWithCache/1 stdout 'Crash written to testdata[/\\]fuzz[/\\]FuzzWithCache[/\\]' stdout FAIL +# Write a crashing input to the cache +mkdir $GOCACHE/fuzz/example.com/x/FuzzWithMinimizableCache +cp cache-file-bytes $GOCACHE/fuzz/example.com/x/FuzzWithMinimizableCache/1 + +# Test that fuzzing a target with a failure in the cache minimizes it and writes +# the new crash to testdata/fuzz +! go test -fuzz=FuzzWithMinimizableCache -run=FuzzWithMinimizableCache -fuzztime=10000x +! stdout ^ok +stdout 'gathering baseline coverage' +stdout 'got the minimum size!' +stdout 'contains a non-zero byte of length 10' +stdout 'Crash written to testdata[/\\]fuzz[/\\]FuzzWithMinimizableCache[/\\]' +stdout FAIL +# Make sure this crash didn't come from fuzzing +# (the log line that states fuzzing began shouldn't have printed) +! stdout 'execs' + # Clear the fuzz cache and make sure it's gone go clean -fuzzcache ! exists $GOCACHE/fuzz @@ -158,6 +175,22 @@ func FuzzWithCache(f *testing.F) { }) } +func FuzzWithMinimizableCache(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + if len(b) < 10 { + return + } + for _, n := range b { + if n != 0 { + if len(b) == 10 { + t.Log("got the minimum size!") + } + t.Fatalf("contains a non-zero byte of length %d", len(b)) + } + } + }) +} + func FuzzRunNoneWithCache(f *testing.F) { f.Fuzz(func(t *testing.T, i int) { if i == 10 { @@ -170,4 +203,7 @@ go test fuzz v1 int(10) -- cache-file -- go test fuzz v1 -int(10) \ No newline at end of file +int(10) +-- cache-file-bytes -- +go test fuzz v1 +[]byte("11111111111111111111") \ No newline at end of file diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 03071d5521..5b3819be75 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -875,12 +875,10 @@ func (c *coordinator) updateCoverage(newCoverage []byte) int { } // canMinimize returns whether the coordinator should attempt to find smaller -// inputs that reproduce a crash or new coverage. It shouldn't do this if it -// is in the warmup phase. +// inputs that reproduce a crash or new coverage. func (c *coordinator) canMinimize() bool { return c.minimizationAllowed && - (c.opts.Limit == 0 || c.count+c.countWaiting < c.opts.Limit) && - !c.warmupRun() + (c.opts.Limit == 0 || c.count+c.countWaiting < c.opts.Limit) } func (c *coordinator) elapsed() time.Duration { diff --git a/src/internal/fuzz/minimize_test.go b/src/internal/fuzz/minimize_test.go index 410b78310b..dd76baff51 100644 --- a/src/internal/fuzz/minimize_test.go +++ b/src/internal/fuzz/minimize_test.go @@ -262,13 +262,12 @@ func TestMinimizeInput(t *testing.T) { } } -// TestMinimizeInputCoverageError checks that if we're minimizing an interesting -// input (one that we don't expect to cause an error), and the fuzz function -// returns an error, minimizing fails, and we return the error quickly. -func TestMinimizeInputCoverageError(t *testing.T) { - errOhNo := errors.New("ohno") +// TestMinimizeFlaky checks that if we're minimizing an interesting +// input and a flaky failure occurs, that minimization was not indicated +// to be successful, and the error isn't returned (since it's flaky). +func TestMinimizeFlaky(t *testing.T) { ws := &workerServer{fuzzFn: func(e CorpusEntry) error { - return errOhNo + return errors.New("ohno") }} keepCoverage := make([]byte, len(coverageSnapshot)) count := int64(0) @@ -277,7 +276,7 @@ func TestMinimizeInputCoverageError(t *testing.T) { if success { t.Error("unexpected success") } - if err != errOhNo { + if err != nil { t.Errorf("unexpected error: %v", err) } if count != 1 { diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 0c428ed832..e3827b112a 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -261,8 +261,8 @@ func (w *worker) minimize(ctx context.Context, input fuzzMinimizeInput) (min fuz return fuzzResult{}, fmt.Errorf("fuzzing process terminated unexpectedly while minimizing: %w", w.waitErr) } - if input.crasherMsg != "" && resp.Err == "" && !resp.Success { - return fuzzResult{}, fmt.Errorf("attempted to minimize but could not reproduce") + if input.crasherMsg != "" && resp.Err == "" { + return fuzzResult{}, fmt.Errorf("attempted to minimize a crash but could not reproduce") } return fuzzResult{ @@ -509,12 +509,11 @@ type minimizeArgs struct { // minimizeResponse contains results from workerServer.minimize. type minimizeResponse struct { - // Success is true if the worker found a smaller input, stored in shared - // memory, that was "interesting" for the same reason as the original input. - // If minimizeArgs.KeepCoverage was set, the minimized input preserved at - // least one coverage bit and did not cause an error. Otherwise, the - // minimized input caused some error, recorded in Err. - Success bool + // WroteToMem is true if the worker found a smaller input and wrote it to + // shared memory. If minimizeArgs.KeepCoverage was set, the minimized input + // preserved at least one coverage bit and did not cause an error. + // Otherwise, the minimized input caused some error, recorded in Err. + WroteToMem bool // Err is the error string caused by the value in shared memory, if any. Err string @@ -777,32 +776,31 @@ func (ws *workerServer) minimize(ctx context.Context, args minimizeArgs) (resp m } // Minimize the values in vals, then write to shared memory. We only write - // to shared memory after completing minimization. If the worker terminates - // unexpectedly before then, the coordinator will use the original input. - resp.Success, err = ws.minimizeInput(ctx, vals, &mem.header().count, args.Limit, args.KeepCoverage) - if resp.Success { + // to shared memory after completing minimization. + // TODO(48165): If the worker terminates unexpectedly during minimization, + // the coordinator has no way of retrieving the crashing input. + success, err := ws.minimizeInput(ctx, vals, &mem.header().count, args.Limit, args.KeepCoverage) + if success { writeToMem(vals, mem) - } - if err != nil { - resp.Err = err.Error() - } else if resp.Success { - resp.CoverageData = coverageSnapshot + resp.WroteToMem = true + if err != nil { + resp.Err = err.Error() + } else { + resp.CoverageData = coverageSnapshot + } } return resp } // minimizeInput applies a series of minimizing transformations on the provided -// vals, ensuring that each minimization still causes an error in fuzzFn. Before -// every call to fuzzFn, it marshals the new vals and writes it to the provided -// mem just in case an unrecoverable error occurs. It uses the context to -// determine how long to run, stopping once closed. It returns a bool -// indicating whether minimization was successful and an error if one was found. +// vals, ensuring that each minimization still causes an error in fuzzFn. It +// uses the context to determine how long to run, stopping once closed. It +// returns a bool indicating whether minimization was successful and an error if +// one was found. func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, count *int64, limit int64, keepCoverage []byte) (success bool, retErr error) { - wantError := keepCoverage == nil shouldStop := func() bool { return ctx.Err() != nil || - (limit > 0 && *count >= limit) || - (retErr != nil && !wantError) + (limit > 0 && *count >= limit) } if shouldStop() { return false, nil @@ -812,11 +810,12 @@ func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, c // If not, then whatever caused us to think the value was interesting may // have been a flake, and we can't minimize it. *count++ - if retErr = ws.fuzzFn(CorpusEntry{Values: vals}); retErr == nil && wantError { - return false, nil - } else if retErr != nil && !wantError { - return false, retErr - } else if keepCoverage != nil && !hasCoverageBit(keepCoverage, coverageSnapshot) { + retErr = ws.fuzzFn(CorpusEntry{Values: vals}) + if keepCoverage != nil { + if !hasCoverageBit(keepCoverage, coverageSnapshot) || retErr != nil { + return false, nil + } + } else if retErr == nil { return false, nil } @@ -881,7 +880,13 @@ func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, c err := ws.fuzzFn(CorpusEntry{Values: vals}) if err != nil { retErr = err - return wantError + if keepCoverage != nil { + // Now that we've found a crash, that's more important than any + // minimization of interesting inputs that was being done. Clear out + // keepCoverage to only minimize the crash going forward. + keepCoverage = nil + } + return true } if keepCoverage != nil && hasCoverageBit(keepCoverage, coverageSnapshot) { return true @@ -939,7 +944,7 @@ func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, c panic("unreachable") } } - return (wantError || retErr == nil), retErr + return true, retErr } func writeToMem(vals []interface{}, mem *sharedMem) { @@ -1024,7 +1029,7 @@ func (wc *workerClient) minimize(ctx context.Context, entryIn CorpusEntry, args } defer func() { wc.memMu <- mem }() resp.Count = mem.header().count - if resp.Success { + if resp.WroteToMem { entryOut.Data = mem.valueCopy() entryOut.Values, err = unmarshalCorpusFile(entryOut.Data) h := sha256.Sum256(entryOut.Data) -- GitLab From 22951fbc89a1bc3c5cc38f4e71b4a682f5149361 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 15 Oct 2021 08:06:58 -0700 Subject: [PATCH 1618/2500] cmd/compile: make for loops with range statements not terminating Fixes #49003 Change-Id: If09c6f028dce5440b1be238612653ffdd626113a Reviewed-on: https://go-review.googlesource.com/c/go/+/356189 Trust: Keith Randall Reviewed-by: roger peppe Reviewed-by: Matthew Dempsky Reviewed-by: Robert Griesemer Reviewed-by: Cuong Manh Le --- doc/go_spec.html | 5 +++-- src/cmd/compile/internal/types2/return.go | 5 +++++ test/fixedbugs/issue49003.go | 12 ++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 test/fixedbugs/issue49003.go diff --git a/doc/go_spec.html b/doc/go_spec.html index c8051f58af..46eebb5713 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,6 +1,6 @@ @@ -4598,7 +4598,8 @@ a block. The following statements are terminating: A "for" statement in which:

  • there are no "break" statements referring to the "for" statement, and
  • -
  • the loop condition is absent.
  • +
  • the loop condition is absent, and
  • +
  • the "for" statement does not use a range clause.
diff --git a/src/cmd/compile/internal/types2/return.go b/src/cmd/compile/internal/types2/return.go index 204e456a91..6c3e1842ce 100644 --- a/src/cmd/compile/internal/types2/return.go +++ b/src/cmd/compile/internal/types2/return.go @@ -62,6 +62,11 @@ func (check *Checker) isTerminating(s syntax.Stmt, label string) bool { return true case *syntax.ForStmt: + if _, ok := s.Init.(*syntax.RangeClause); ok { + // Range clauses guarantee that the loop terminates, + // so the loop is not a terminating statement. See issue 49003. + break + } if s.Cond == nil && !hasBreak(s.Body, label, true) { return true } diff --git a/test/fixedbugs/issue49003.go b/test/fixedbugs/issue49003.go new file mode 100644 index 0000000000..da6c19b8cb --- /dev/null +++ b/test/fixedbugs/issue49003.go @@ -0,0 +1,12 @@ +// errorcheck + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func f(s string) int { + for range s { + } +} // ERROR "missing return" -- GitLab From a17b2e865551ebdeccd6aafcdc23c1b63932b258 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Fri, 15 Oct 2021 11:57:58 -0700 Subject: [PATCH 1619/2500] cmd/go: allow nested VCS repositories when preparing build stamp The go command no longer reports an error when invoked in a repository nested inside another. This check is still used by 'go get' in GOPATH mode when locating a repository, but it's not needed when preparing the build stamp. Fixes #49004 Change-Id: I4ed4dcc04174d2d42da8651d47e52ab1d7d66e35 Reviewed-on: https://go-review.googlesource.com/c/go/+/356309 Trust: Jay Conrod Run-TryBot: Jay Conrod Reviewed-by: Bryan C. Mills TryBot-Result: Go Bot --- src/cmd/go/internal/get/get.go | 3 ++- src/cmd/go/internal/load/pkg.go | 7 ++++--- src/cmd/go/internal/vcs/vcs.go | 11 ++++++++--- src/cmd/go/internal/vcs/vcs_test.go | 2 +- .../script/version_buildvcs_nested.txt | 19 ++++++++++--------- 5 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/cmd/go/internal/get/get.go b/src/cmd/go/internal/get/get.go index c96459297a..0412506b9e 100644 --- a/src/cmd/go/internal/get/get.go +++ b/src/cmd/go/internal/get/get.go @@ -446,7 +446,8 @@ func downloadPackage(p *load.Package) error { if p.Internal.Build.SrcRoot != "" { // Directory exists. Look for checkout along path to src. - repoDir, vcsCmd, err = vcs.FromDir(p.Dir, p.Internal.Build.SrcRoot) + const allowNesting = false + repoDir, vcsCmd, err = vcs.FromDir(p.Dir, p.Internal.Build.SrcRoot, allowNesting) if err != nil { return err } diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index 58dc242383..99c4a9c62e 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -2318,8 +2318,9 @@ func (p *Package) setBuildInfo() { var repoDir string var vcsCmd *vcs.Cmd var err error + const allowNesting = true if cfg.BuildBuildvcs && p.Module != nil && p.Module.Version == "" && !p.Standard { - repoDir, vcsCmd, err = vcs.FromDir(base.Cwd(), "") + repoDir, vcsCmd, err = vcs.FromDir(base.Cwd(), "", allowNesting) if err != nil && !errors.Is(err, os.ErrNotExist) { setVCSError(err) return @@ -2338,7 +2339,7 @@ func (p *Package) setBuildInfo() { // repository. vcs.FromDir allows nested Git repositories, but nesting // is not allowed for other VCS tools. The current directory may be outside // p.Module.Dir when a workspace is used. - pkgRepoDir, _, err := vcs.FromDir(p.Dir, "") + pkgRepoDir, _, err := vcs.FromDir(p.Dir, "", allowNesting) if err != nil { setVCSError(err) return @@ -2347,7 +2348,7 @@ func (p *Package) setBuildInfo() { setVCSError(fmt.Errorf("main package is in repository %q but current directory is in repository %q", pkgRepoDir, repoDir)) return } - modRepoDir, _, err := vcs.FromDir(p.Module.Dir, "") + modRepoDir, _, err := vcs.FromDir(p.Module.Dir, "", allowNesting) if err != nil { setVCSError(err) return diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go index ebb4850443..d1272b66e9 100644 --- a/src/cmd/go/internal/vcs/vcs.go +++ b/src/cmd/go/internal/vcs/vcs.go @@ -603,7 +603,7 @@ type vcsPath struct { // version control system and code repository to use. // If no repository is found, FromDir returns an error // equivalent to os.ErrNotExist. -func FromDir(dir, srcRoot string) (repoDir string, vcsCmd *Cmd, err error) { +func FromDir(dir, srcRoot string, allowNesting bool) (repoDir string, vcsCmd *Cmd, err error) { // Clean and double-check that dir is in (a subdirectory of) srcRoot. dir = filepath.Clean(dir) if srcRoot != "" { @@ -617,11 +617,16 @@ func FromDir(dir, srcRoot string) (repoDir string, vcsCmd *Cmd, err error) { for len(dir) > len(srcRoot) { for _, vcs := range vcsList { if _, err := os.Stat(filepath.Join(dir, "."+vcs.Cmd)); err == nil { - // Record first VCS we find, but keep looking, - // to detect mistakes like one kind of VCS inside another. + // Record first VCS we find. + // If allowNesting is false (as it is in GOPATH), keep looking for + // repositories in parent directories and report an error if one is + // found to mitigate VCS injection attacks. if vcsCmd == nil { vcsCmd = vcs repoDir = dir + if allowNesting { + return repoDir, vcsCmd, nil + } continue } // Allow .git inside .git, which can arise due to submodules. diff --git a/src/cmd/go/internal/vcs/vcs_test.go b/src/cmd/go/internal/vcs/vcs_test.go index 248c541014..9ac0a56a07 100644 --- a/src/cmd/go/internal/vcs/vcs_test.go +++ b/src/cmd/go/internal/vcs/vcs_test.go @@ -233,7 +233,7 @@ func TestFromDir(t *testing.T) { } wantRepoDir := filepath.Dir(dir) - gotRepoDir, gotVCS, err := FromDir(dir, tempDir) + gotRepoDir, gotVCS, err := FromDir(dir, tempDir, false) if err != nil { t.Errorf("FromDir(%q, %q): %v", dir, tempDir, err) continue diff --git a/src/cmd/go/testdata/script/version_buildvcs_nested.txt b/src/cmd/go/testdata/script/version_buildvcs_nested.txt index f904c41bf8..08d4c92baf 100644 --- a/src/cmd/go/testdata/script/version_buildvcs_nested.txt +++ b/src/cmd/go/testdata/script/version_buildvcs_nested.txt @@ -1,5 +1,6 @@ [!exec:git] skip [!exec:hg] skip +[short] skip env GOFLAGS=-n # Create a root module in a root Git repository. @@ -8,25 +9,25 @@ cd root go mod init example.com/root exec git init -# It's an error to build a package from a nested Mercurial repository -# without -buildvcs=false, even if the package is in a separate module. +# Nesting repositories in parent directories are ignored, as the current +# directory main package, and containing main module are in the same repository. +# This is an error in GOPATH mode (to prevent VCS injection), but for modules, +# we assume users have control over repositories they've checked out. mkdir hgsub cd hgsub exec hg init cp ../../main.go main.go ! go build -stderr '^error obtaining VCS status: directory ".*hgsub" uses hg, but parent ".*root" uses git$' -stderr '\tUse -buildvcs=false to disable VCS stamping.$' -go mod init example.com/root/hgsub -! go build -stderr '^error obtaining VCS status: directory ".*hgsub" uses hg, but parent ".*root" uses git$' +stderr '^error obtaining VCS status: main module is in repository ".*root" but current directory is in repository ".*hgsub"$' +stderr '^\tUse -buildvcs=false to disable VCS stamping.$' go build -buildvcs=false +go mod init example.com/root/hgsub +go build cd .. # It's an error to build a package from a nested Git repository if the package # is in a separate repository from the current directory or from the module -# root directory. However, unlike with other VCS, it's okay for a Git repository -# to be nested within another Git repository. This happens with submodules. +# root directory. mkdir gitsub cd gitsub exec git init -- GitLab From 85cbdda5a6d8525973580776c835e725452db898 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Thu, 14 Oct 2021 15:40:44 -0700 Subject: [PATCH 1620/2500] doc/go1.18: add release notes for build and VCS info Fixes #37475 For #39301 Change-Id: I765bc667004931ff8973b947f2e95624a4a0375d Reviewed-on: https://go-review.googlesource.com/c/go/+/356013 Reviewed-by: Bryan C. Mills Trust: Jay Conrod --- doc/go1.18.html | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/doc/go1.18.html b/doc/go1.18.html index f4d097d06b..d95e55e1ad 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -65,6 +65,30 @@ Do not send CLs removing the interior tags from such phrases. and installs packages, as before.

+

+ The go command now embeds version control information in + binaries including the currently checked-out revision and a flag indicating + whether edited or untracked files are present. Version control information + is embedded if the go command is invoked in a directory within a + Git or Mercurial repository, and the main package and its + containing main module are in the same repository. This information may be + omitted using the flag -buildvcs=false. +

+ +

+ Additionally, the go command embeds information about the build + including build and tool tags (set with -tags), compiler, + assembler, and linker flags (like -gcflags), whether cgo was + enabled, and if it was, the values of the cgo environment variables + (like CGO_CFLAGS). This information may be omitted using the + flag -buildinfo=false. Both VCS and build information may be + read together with module information using go + version -m file or + runtime/debug.ReadBuildInfo (for the currently running binary) + or the new debug/buildinfo + package. +

+

TODO: complete this section, or delete if not needed

@@ -114,6 +138,19 @@ Do not send CLs removing the interior tags from such phrases. TODO: complete this section

+
debug/buildinfo
+
+

+ This new package provides access to module versions, version control + information, and build flags embedded in executable files built by + the go command. The same information is also available via + runtime/debug.ReadBuildInfo + for the currently running binary and via go + version -m on the command line. +

+
+
+
image/draw

-- GitLab From 1b072b3ed56c18619587354f499fcda5279718a2 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 14 Oct 2021 18:18:49 -0400 Subject: [PATCH 1621/2500] runtime: consistently access pollDesc r/w Gs with atomics Both netpollblock and netpollunblock read gpp using a non-atomic load. When consuming a ready event, netpollblock clears gpp using a non-atomic store, thus skipping a barrier. Thus on systems with weak memory ordering, a sequence like so this is possible: T1 T2 1. netpollblock: read gpp -> pdReady 2. netpollblock: store gpp -> 0 3. netpollunblock: read gpp -> pdReady 4. netpollunblock: return i.e., without a happens-before edge between (2) and (3), netpollunblock may read the stale value of gpp. Switch these access to use atomic loads and stores in order to create these edges. For ease of future maintainance, I've simply changed rg and wg to always be accessed atomically, though I don't believe pollOpen or pollClose require atomics today. Fixes #48925 Change-Id: I903ea667eea320277610b4f969129935731520c3 Reviewed-on: https://go-review.googlesource.com/c/go/+/355952 Trust: Michael Pratt Run-TryBot: Michael Pratt TryBot-Result: Go Bot Reviewed-by: Michael Knyszek Reviewed-by: David Chase --- src/runtime/netpoll.go | 43 +++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/src/runtime/netpoll.go b/src/runtime/netpoll.go index 239371158f..1008b4422c 100644 --- a/src/runtime/netpoll.go +++ b/src/runtime/netpoll.go @@ -78,6 +78,7 @@ type pollDesc struct { // pollReset, pollWait, pollWaitCanceled and runtime·netpollready (IO readiness notification) // proceed w/o taking the lock. So closing, everr, rg, rd, wg and wd are manipulated // in a lock-free way by all operations. + // TODO(golang.org/issue/49008): audit these lock-free fields for continued correctness. // NOTE(dvyukov): the following code uses uintptr to store *g (rg/wg), // that will blow up when GC starts moving objects. lock mutex // protects the following fields @@ -86,11 +87,11 @@ type pollDesc struct { everr bool // marks event scanning error happened user uint32 // user settable cookie rseq uintptr // protects from stale read timers - rg uintptr // pdReady, pdWait, G waiting for read or nil + rg uintptr // pdReady, pdWait, G waiting for read or nil. Accessed atomically. rt timer // read deadline timer (set if rt.f != nil) rd int64 // read deadline wseq uintptr // protects from stale write timers - wg uintptr // pdReady, pdWait, G waiting for write or nil + wg uintptr // pdReady, pdWait, G waiting for write or nil. Accessed atomically. wt timer // write deadline timer wd int64 // write deadline self *pollDesc // storage for indirect interface. See (*pollDesc).makeArg. @@ -147,20 +148,22 @@ func poll_runtime_isPollServerDescriptor(fd uintptr) bool { func poll_runtime_pollOpen(fd uintptr) (*pollDesc, int) { pd := pollcache.alloc() lock(&pd.lock) - if pd.wg != 0 && pd.wg != pdReady { + wg := atomic.Loaduintptr(&pd.wg) + if wg != 0 && wg != pdReady { throw("runtime: blocked write on free polldesc") } - if pd.rg != 0 && pd.rg != pdReady { + rg := atomic.Loaduintptr(&pd.rg) + if rg != 0 && rg != pdReady { throw("runtime: blocked read on free polldesc") } pd.fd = fd pd.closing = false pd.everr = false pd.rseq++ - pd.rg = 0 + atomic.Storeuintptr(&pd.rg, 0) pd.rd = 0 pd.wseq++ - pd.wg = 0 + atomic.Storeuintptr(&pd.wg, 0) pd.wd = 0 pd.self = pd unlock(&pd.lock) @@ -178,10 +181,12 @@ func poll_runtime_pollClose(pd *pollDesc) { if !pd.closing { throw("runtime: close polldesc w/o unblock") } - if pd.wg != 0 && pd.wg != pdReady { + wg := atomic.Loaduintptr(&pd.wg) + if wg != 0 && wg != pdReady { throw("runtime: blocked write on closing polldesc") } - if pd.rg != 0 && pd.rg != pdReady { + rg := atomic.Loaduintptr(&pd.rg) + if rg != 0 && rg != pdReady { throw("runtime: blocked read on closing polldesc") } netpollclose(pd.fd) @@ -205,9 +210,9 @@ func poll_runtime_pollReset(pd *pollDesc, mode int) int { return errcode } if mode == 'r' { - pd.rg = 0 + atomic.Storeuintptr(&pd.rg, 0) } else if mode == 'w' { - pd.wg = 0 + atomic.Storeuintptr(&pd.wg, 0) } return pollNoError } @@ -417,6 +422,8 @@ func netpollgoready(gp *g, traceskip int) { // returns true if IO is ready, or false if timedout or closed // waitio - wait only for completed IO, ignore errors +// Concurrent calls to netpollblock in the same mode are forbidden, as pollDesc +// can hold only a single waiting goroutine for each mode. func netpollblock(pd *pollDesc, mode int32, waitio bool) bool { gpp := &pd.rg if mode == 'w' { @@ -425,17 +432,19 @@ func netpollblock(pd *pollDesc, mode int32, waitio bool) bool { // set the gpp semaphore to pdWait for { - old := *gpp - if old == pdReady { - *gpp = 0 + // Consume notification if already ready. + if atomic.Casuintptr(gpp, pdReady, 0) { return true } - if old != 0 { - throw("runtime: double wait") - } if atomic.Casuintptr(gpp, 0, pdWait) { break } + + // Double check that this isn't corrupt; otherwise we'd loop + // forever. + if v := atomic.Loaduintptr(gpp); v != pdReady && v != 0 { + throw("runtime: double wait") + } } // need to recheck error states after setting gpp to pdWait @@ -459,7 +468,7 @@ func netpollunblock(pd *pollDesc, mode int32, ioready bool) *g { } for { - old := *gpp + old := atomic.Loaduintptr(gpp) if old == pdReady { return nil } -- GitLab From 4a7975e73a2815b93caf6697fec4f4e777e729a1 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Fri, 15 Oct 2021 11:54:25 -0700 Subject: [PATCH 1622/2500] cmd/compile: convert to using a map in getInstInfo, rather than SetImplicit() SetImplicit() has an explicit meaning and really shouldn't be used in this way - its use is left over from early prototype of the dictionary code. Convert from using SetImplicit to just using a map during traversal. Change-Id: I3d257c101a859f000e159d7ced307d1b7cf990d4 Reviewed-on: https://go-review.googlesource.com/c/go/+/356310 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index cfa90e4399..3a1baeae88 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1854,14 +1854,19 @@ func (g *genInst) getInstInfo(st *ir.Func, shapes []*types.Type, instInfo *instI } } + // Map to remember when we have seen an instantiated function value or method + // expression/value as part of a call, so we can determine when we encounter + // an uncalled function value or method expression/value. + callMap := make(map[ir.Node]bool) + var visitFunc func(ir.Node) visitFunc = func(n ir.Node) { - if n.Op() == ir.OFUNCINST && !n.(*ir.InstExpr).Implicit() { + if n.Op() == ir.OFUNCINST && !callMap[n] { if hasShapeNodes(n.(*ir.InstExpr).Targs) { infoPrint(" Closure&subdictionary required at generic function value %v\n", n.(*ir.InstExpr).X) info.subDictCalls = append(info.subDictCalls, n) } - } else if (n.Op() == ir.OMETHEXPR || n.Op() == ir.OMETHVALUE) && !n.(*ir.SelectorExpr).Implicit() && + } else if (n.Op() == ir.OMETHEXPR || n.Op() == ir.OMETHVALUE) && !callMap[n] && !types.IsInterfaceMethod(n.(*ir.SelectorExpr).Selection.Type) && len(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) > 0 { if hasShapeTypes(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) { @@ -1874,16 +1879,15 @@ func (g *genInst) getInstInfo(st *ir.Func, shapes []*types.Type, instInfo *instI } } if n.Op() == ir.OCALL && n.(*ir.CallExpr).X.Op() == ir.OFUNCINST { - n.(*ir.CallExpr).X.(*ir.InstExpr).SetImplicit(true) + callMap[n.(*ir.CallExpr).X] = true if hasShapeNodes(n.(*ir.CallExpr).X.(*ir.InstExpr).Targs) { infoPrint(" Subdictionary at generic function/method call: %v - %v\n", n.(*ir.CallExpr).X.(*ir.InstExpr).X, n) info.subDictCalls = append(info.subDictCalls, n) } } if n.Op() == ir.OCALLMETH && n.(*ir.CallExpr).X.Op() == ir.ODOTMETH && - //n.(*ir.CallExpr).X.(*ir.SelectorExpr).Selection != nil && len(deref(n.(*ir.CallExpr).X.(*ir.SelectorExpr).X.Type()).RParams()) > 0 { - n.(*ir.CallExpr).X.(*ir.SelectorExpr).SetImplicit(true) + callMap[n.(*ir.CallExpr).X] = true if hasShapeTypes(deref(n.(*ir.CallExpr).X.(*ir.SelectorExpr).X.Type()).RParams()) { infoPrint(" Subdictionary at generic method call: %v\n", n) info.subDictCalls = append(info.subDictCalls, n) @@ -1891,7 +1895,7 @@ func (g *genInst) getInstInfo(st *ir.Func, shapes []*types.Type, instInfo *instI } if n.Op() == ir.OCALL && n.(*ir.CallExpr).X.Op() == ir.OXDOT && isShapeDeref(n.(*ir.CallExpr).X.(*ir.SelectorExpr).X.Type()) { - n.(*ir.CallExpr).X.(*ir.SelectorExpr).SetImplicit(true) + callMap[n.(*ir.CallExpr).X] = true infoPrint(" Optional subdictionary at generic bound call: %v\n", n) info.subDictCalls = append(info.subDictCalls, n) } -- GitLab From ed1c8db308029bd82e6de4d547196f7f841236bb Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Fri, 15 Oct 2021 12:31:39 -0700 Subject: [PATCH 1623/2500] cmd/compile: cleanup code in getInstInfo to use switch statement Simple cleanup: convert a bunch of if's to a switch statement in getInstInfo. Also, use a few extra variables to avoid repeated node conversions (such as n.(*ir.CallExpr)) Change-Id: I7a2a4efb569415256a8bc9350fb100bd2d8cfb39 Reviewed-on: https://go-review.googlesource.com/c/go/+/356311 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 115 ++++++++++++---------- 1 file changed, 62 insertions(+), 53 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 3a1baeae88..592de7017f 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -28,8 +28,8 @@ func assert(p bool) { base.Assert(p) } -// Temporary - for outputting information on derived types, dictionaries, sub-dictionaries. -// Turn off when running tests. +// For outputting debug information on dictionary format and instantiated dictionaries +// (type arg, derived types, sub-dictionary, and itab entries). var infoPrintMode = false func infoPrint(format string, a ...interface{}) { @@ -1861,15 +1861,16 @@ func (g *genInst) getInstInfo(st *ir.Func, shapes []*types.Type, instInfo *instI var visitFunc func(ir.Node) visitFunc = func(n ir.Node) { - if n.Op() == ir.OFUNCINST && !callMap[n] { - if hasShapeNodes(n.(*ir.InstExpr).Targs) { + switch n.Op() { + case ir.OFUNCINST: + if !callMap[n] && hasShapeNodes(n.(*ir.InstExpr).Targs) { infoPrint(" Closure&subdictionary required at generic function value %v\n", n.(*ir.InstExpr).X) info.subDictCalls = append(info.subDictCalls, n) } - } else if (n.Op() == ir.OMETHEXPR || n.Op() == ir.OMETHVALUE) && !callMap[n] && - !types.IsInterfaceMethod(n.(*ir.SelectorExpr).Selection.Type) && - len(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) > 0 { - if hasShapeTypes(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) { + case ir.OMETHEXPR, ir.OMETHVALUE: + if !callMap[n] && !types.IsInterfaceMethod(n.(*ir.SelectorExpr).Selection.Type) && + len(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) > 0 && + hasShapeTypes(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) { if n.(*ir.SelectorExpr).X.Op() == ir.OTYPE { infoPrint(" Closure&subdictionary required at generic meth expr %v\n", n) } else { @@ -1877,43 +1878,48 @@ func (g *genInst) getInstInfo(st *ir.Func, shapes []*types.Type, instInfo *instI } info.subDictCalls = append(info.subDictCalls, n) } - } - if n.Op() == ir.OCALL && n.(*ir.CallExpr).X.Op() == ir.OFUNCINST { - callMap[n.(*ir.CallExpr).X] = true - if hasShapeNodes(n.(*ir.CallExpr).X.(*ir.InstExpr).Targs) { - infoPrint(" Subdictionary at generic function/method call: %v - %v\n", n.(*ir.CallExpr).X.(*ir.InstExpr).X, n) - info.subDictCalls = append(info.subDictCalls, n) + case ir.OCALL: + ce := n.(*ir.CallExpr) + if ce.X.Op() == ir.OFUNCINST { + callMap[ce.X] = true + if hasShapeNodes(ce.X.(*ir.InstExpr).Targs) { + infoPrint(" Subdictionary at generic function/method call: %v - %v\n", ce.X.(*ir.InstExpr).X, n) + info.subDictCalls = append(info.subDictCalls, n) + } } - } - if n.Op() == ir.OCALLMETH && n.(*ir.CallExpr).X.Op() == ir.ODOTMETH && - len(deref(n.(*ir.CallExpr).X.(*ir.SelectorExpr).X.Type()).RParams()) > 0 { - callMap[n.(*ir.CallExpr).X] = true - if hasShapeTypes(deref(n.(*ir.CallExpr).X.(*ir.SelectorExpr).X.Type()).RParams()) { - infoPrint(" Subdictionary at generic method call: %v\n", n) + if ce.X.Op() == ir.OXDOT && + isShapeDeref(ce.X.(*ir.SelectorExpr).X.Type()) { + callMap[ce.X] = true + infoPrint(" Optional subdictionary at generic bound call: %v\n", n) info.subDictCalls = append(info.subDictCalls, n) } - } - if n.Op() == ir.OCALL && n.(*ir.CallExpr).X.Op() == ir.OXDOT && - isShapeDeref(n.(*ir.CallExpr).X.(*ir.SelectorExpr).X.Type()) { - callMap[n.(*ir.CallExpr).X] = true - infoPrint(" Optional subdictionary at generic bound call: %v\n", n) - info.subDictCalls = append(info.subDictCalls, n) - } - if n.Op() == ir.OCONVIFACE && n.Type().IsInterface() && - !n.Type().IsEmptyInterface() && - n.(*ir.ConvExpr).X.Type().HasShape() { - infoPrint(" Itab for interface conv: %v\n", n) - info.itabConvs = append(info.itabConvs, n) - } - if n.Op() == ir.OXDOT && n.(*ir.SelectorExpr).X.Type().IsShape() { - infoPrint(" Itab for bound call: %v\n", n) - info.itabConvs = append(info.itabConvs, n) - } - if (n.Op() == ir.ODOTTYPE || n.Op() == ir.ODOTTYPE2) && !n.(*ir.TypeAssertExpr).Type().IsInterface() && !n.(*ir.TypeAssertExpr).X.Type().IsEmptyInterface() { - infoPrint(" Itab for dot type: %v\n", n) - info.itabConvs = append(info.itabConvs, n) - } - if n.Op() == ir.OCLOSURE { + case ir.OCALLMETH: + ce := n.(*ir.CallExpr) + if ce.X.Op() == ir.ODOTMETH && + len(deref(ce.X.(*ir.SelectorExpr).X.Type()).RParams()) > 0 { + callMap[ce.X] = true + if hasShapeTypes(deref(ce.X.(*ir.SelectorExpr).X.Type()).RParams()) { + infoPrint(" Subdictionary at generic method call: %v\n", n) + info.subDictCalls = append(info.subDictCalls, n) + } + } + case ir.OCONVIFACE: + if n.Type().IsInterface() && !n.Type().IsEmptyInterface() && + n.(*ir.ConvExpr).X.Type().HasShape() { + infoPrint(" Itab for interface conv: %v\n", n) + info.itabConvs = append(info.itabConvs, n) + } + case ir.OXDOT: + if n.(*ir.SelectorExpr).X.Type().IsShape() { + infoPrint(" Itab for bound call: %v\n", n) + info.itabConvs = append(info.itabConvs, n) + } + case ir.ODOTTYPE, ir.ODOTTYPE2: + if !n.(*ir.TypeAssertExpr).Type().IsInterface() && !n.(*ir.TypeAssertExpr).X.Type().IsEmptyInterface() { + infoPrint(" Itab for dot type: %v\n", n) + info.itabConvs = append(info.itabConvs, n) + } + case ir.OCLOSURE: // Visit the closure body and add all relevant entries to the // dictionary of the outer function (closure will just use // the dictionary of the outer function). @@ -1924,18 +1930,21 @@ func (g *genInst) getInstInfo(st *ir.Func, shapes []*types.Type, instInfo *instI for _, n := range cfunc.Dcl { n.DictIndex = uint16(findDictType(instInfo, n.Type()) + 1) } - } - if n.Op() == ir.OSWITCH && n.(*ir.SwitchStmt).Tag != nil && n.(*ir.SwitchStmt).Tag.Op() == ir.OTYPESW && !n.(*ir.SwitchStmt).Tag.(*ir.TypeSwitchGuard).X.Type().IsEmptyInterface() { - for _, cc := range n.(*ir.SwitchStmt).Cases { - for _, c := range cc.List { - if c.Op() == ir.OTYPE && c.Type().HasShape() { - // Type switch from a non-empty interface - might need an itab. - infoPrint(" Itab for type switch: %v\n", c) - info.itabConvs = append(info.itabConvs, c) - if info.type2switchType == nil { - info.type2switchType = map[ir.Node]*types.Type{} + case ir.OSWITCH: + ss := n.(*ir.SwitchStmt) + if ss.Tag != nil && ss.Tag.Op() == ir.OTYPESW && + !ss.Tag.(*ir.TypeSwitchGuard).X.Type().IsEmptyInterface() { + for _, cc := range ss.Cases { + for _, c := range cc.List { + if c.Op() == ir.OTYPE && c.Type().HasShape() { + // Type switch from a non-empty interface - might need an itab. + infoPrint(" Itab for type switch: %v\n", c) + info.itabConvs = append(info.itabConvs, c) + if info.type2switchType == nil { + info.type2switchType = map[ir.Node]*types.Type{} + } + info.type2switchType[c] = ss.Tag.(*ir.TypeSwitchGuard).X.Type() } - info.type2switchType[c] = n.(*ir.SwitchStmt).Tag.(*ir.TypeSwitchGuard).X.Type() } } } -- GitLab From 680caf15355057ca84857a2a291b6f5c44e73329 Mon Sep 17 00:00:00 2001 From: Richard Musiol Date: Fri, 3 Sep 2021 21:58:57 +0200 Subject: [PATCH 1624/2500] misc/wasm: expect environment to provide polyfills The list of environments to support with wasm_exec.js was becoming too large to maintain. With this change, wasm_exec.js expects that the environment provides all necessary polyfills. The standardized "globalThis" is used for accessing the environment. wasm_exec.js now only provides stub fallbacks for globalThis.fs and globalThis.process. All code specific to Node.js is now in a separate file. Change-Id: I076febbd94d4d7845260faad972f450f74a7b983 Reviewed-on: https://go-review.googlesource.com/c/go/+/347353 Trust: Richard Musiol Reviewed-by: Cherry Mui --- misc/wasm/go_js_wasm_exec | 2 +- misc/wasm/wasm_exec.js | 115 +++++------------------------------- misc/wasm/wasm_exec_node.js | 49 +++++++++++++++ 3 files changed, 66 insertions(+), 100 deletions(-) create mode 100644 misc/wasm/wasm_exec_node.js diff --git a/misc/wasm/go_js_wasm_exec b/misc/wasm/go_js_wasm_exec index b700722dfe..fcbd0e4fc8 100755 --- a/misc/wasm/go_js_wasm_exec +++ b/misc/wasm/go_js_wasm_exec @@ -11,4 +11,4 @@ while [ -h "$SOURCE" ]; do done DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" -exec node "$DIR/wasm_exec.js" "$@" +exec node "$DIR/wasm_exec_node.js" "$@" diff --git a/misc/wasm/wasm_exec.js b/misc/wasm/wasm_exec.js index e2f3cda995..30044a6f85 100644 --- a/misc/wasm/wasm_exec.js +++ b/misc/wasm/wasm_exec.js @@ -1,49 +1,19 @@ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. + "use strict"; (() => { - // Map multiple JavaScript environments to a single common API, - // preferring web standards over Node.js API. - // - // Environments considered: - // - Browsers - // - Node.js - // - Electron - // - Parcel - // - Webpack - - if (typeof global !== "undefined") { - // global already exists - } else if (typeof window !== "undefined") { - window.global = window; - } else if (typeof self !== "undefined") { - self.global = self; - } else { - throw new Error("cannot export Go (neither global, window nor self is defined)"); - } - - if (!global.require && typeof require !== "undefined") { - global.require = require; - } - - if (!global.fs && global.require) { - const fs = require("fs"); - if (typeof fs === "object" && fs !== null && Object.keys(fs).length !== 0) { - global.fs = fs; - } - } - const enosys = () => { const err = new Error("not implemented"); err.code = "ENOSYS"; return err; }; - if (!global.fs) { + if (!globalThis.fs) { let outputBuf = ""; - global.fs = { + globalThis.fs = { constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused writeSync(fd, buf) { outputBuf += decoder.decode(buf); @@ -88,8 +58,8 @@ }; } - if (!global.process) { - global.process = { + if (!globalThis.process) { + globalThis.process = { getuid() { return -1; }, getgid() { return -1; }, geteuid() { return -1; }, @@ -103,47 +73,26 @@ } } - if (!global.crypto && global.require) { - const nodeCrypto = require("crypto"); - global.crypto = { - getRandomValues(b) { - nodeCrypto.randomFillSync(b); - }, - }; - } - if (!global.crypto) { - throw new Error("global.crypto is not available, polyfill required (getRandomValues only)"); + if (!globalThis.crypto) { + throw new Error("globalThis.crypto is not available, polyfill required (crypto.getRandomValues only)"); } - if (!global.performance) { - global.performance = { - now() { - const [sec, nsec] = process.hrtime(); - return sec * 1000 + nsec / 1000000; - }, - }; + if (!globalThis.performance) { + throw new Error("globalThis.performance is not available, polyfill required (performance.now only)"); } - if (!global.TextEncoder && global.require) { - global.TextEncoder = require("util").TextEncoder; - } - if (!global.TextEncoder) { - throw new Error("global.TextEncoder is not available, polyfill required"); + if (!globalThis.TextEncoder) { + throw new Error("globalThis.TextEncoder is not available, polyfill required"); } - if (!global.TextDecoder && global.require) { - global.TextDecoder = require("util").TextDecoder; + if (!globalThis.TextDecoder) { + throw new Error("globalThis.TextDecoder is not available, polyfill required"); } - if (!global.TextDecoder) { - throw new Error("global.TextDecoder is not available, polyfill required"); - } - - // End of polyfills for common API. const encoder = new TextEncoder("utf-8"); const decoder = new TextDecoder("utf-8"); - global.Go = class { + globalThis.Go = class { constructor() { this.argv = ["js"]; this.env = {}; @@ -518,7 +467,7 @@ null, true, false, - global, + globalThis, this, ]; this._goRefCounts = new Array(this._values.length).fill(Infinity); // number of references that Go has to a JS value, indexed by reference id @@ -527,7 +476,7 @@ [null, 2], [true, 3], [false, 4], - [global, 5], + [globalThis, 5], [this, 6], ]); this._idPool = []; // unused ids that have been garbage collected @@ -602,36 +551,4 @@ }; } } - - if ( - typeof module !== "undefined" && - global.require && - global.require.main === module && - global.process && - global.process.versions && - !global.process.versions.electron - ) { - if (process.argv.length < 3) { - console.error("usage: go_js_wasm_exec [wasm binary] [arguments]"); - process.exit(1); - } - - const go = new Go(); - go.argv = process.argv.slice(2); - go.env = Object.assign({ TMPDIR: require("os").tmpdir() }, process.env); - go.exit = process.exit; - WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => { - process.on("exit", (code) => { // Node.js exits if no event handler is pending - if (code === 0 && !go.exited) { - // deadlock, make Go print error and stack traces - go._pendingEvent = { id: 0 }; - go._resume(); - } - }); - return go.run(result.instance); - }).catch((err) => { - console.error(err); - process.exit(1); - }); - } })(); diff --git a/misc/wasm/wasm_exec_node.js b/misc/wasm/wasm_exec_node.js new file mode 100644 index 0000000000..f9200ca950 --- /dev/null +++ b/misc/wasm/wasm_exec_node.js @@ -0,0 +1,49 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +"use strict"; + +if (process.argv.length < 3) { + console.error("usage: go_js_wasm_exec [wasm binary] [arguments]"); + process.exit(1); +} + +globalThis.require = require; +globalThis.fs = require("fs"); +globalThis.TextEncoder = require("util").TextEncoder; +globalThis.TextDecoder = require("util").TextDecoder; + +globalThis.performance = { + now() { + const [sec, nsec] = process.hrtime(); + return sec * 1000 + nsec / 1000000; + }, +}; + +const crypto = require("crypto"); +globalThis.crypto = { + getRandomValues(b) { + crypto.randomFillSync(b); + }, +}; + +require("./wasm_exec"); + +const go = new Go(); +go.argv = process.argv.slice(2); +go.env = Object.assign({ TMPDIR: require("os").tmpdir() }, process.env); +go.exit = process.exit; +WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => { + process.on("exit", (code) => { // Node.js exits if no event handler is pending + if (code === 0 && !go.exited) { + // deadlock, make Go print error and stack traces + go._pendingEvent = { id: 0 }; + go._resume(); + } + }); + return go.run(result.instance); +}).catch((err) => { + console.error(err); + process.exit(1); +}); -- GitLab From 640a49b8d45760b7c965fc1529dffc8e000cc846 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Fri, 15 Oct 2021 15:05:36 -0700 Subject: [PATCH 1625/2500] test: add a test for parameterized embedded field Make sure that an embedded field like "MyStruct[T]" works and can be referenced via the name MyStruct. Change-Id: I8be1f1184dd42c4e54e4144aff2fd85e30af722f Reviewed-on: https://go-review.googlesource.com/c/go/+/356312 Trust: Dan Scales Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/typecheck/subr.go | 3 -- test/typeparam/genembed2.go | 46 ++++++++++++++++++++++ 2 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 test/typeparam/genembed2.go diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index b3fc7459e1..b4d5302525 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1324,9 +1324,6 @@ func (ts *Tsubster) tstruct(t *types.Type, force bool) *types.Type { } } if newfields != nil { - // TODO(danscales): make sure this works for the field - // names of embedded types (which should keep the name of - // the type param, not the instantiated type). newfields[i] = types.NewField(f.Pos, f.Sym, t2) newfields[i].Embedded = f.Embedded newfields[i].Note = f.Note diff --git a/test/typeparam/genembed2.go b/test/typeparam/genembed2.go new file mode 100644 index 0000000000..6effd2e6bc --- /dev/null +++ b/test/typeparam/genembed2.go @@ -0,0 +1,46 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test for declaration and use of a parameterized embedded field. + +package main + +import ( + "fmt" + "sync" +) + +type MyStruct[T any] struct { + val T +} + +type Lockable[T any] struct { + MyStruct[T] + mu sync.Mutex +} + +// Get returns the value stored in a Lockable. +func (l *Lockable[T]) Get() T { + l.mu.Lock() + defer l.mu.Unlock() + return l.MyStruct.val +} + +// Set sets the value in a Lockable. +func (l *Lockable[T]) Set(v T) { + l.mu.Lock() + defer l.mu.Unlock() + l.MyStruct = MyStruct[T]{v} +} + +func main() { + var li Lockable[int] + + li.Set(5) + if got, want := li.Get(), 5; got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } +} -- GitLab From fa7d11a0e9c0ed469111ba5fdd86f7462a48ef49 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sat, 16 Oct 2021 14:54:42 -0700 Subject: [PATCH 1626/2500] go/types, types2: add test case for missing return The respective issue was fixed in types2 with CL 356189; and the problem didn't exist in go/types. This CL simply adds the test case to the type checkers as well. For #49003. Change-Id: Ib50ee8bb0ad21f2916f2b79d4f77593302899a3e Reviewed-on: https://go-review.googlesource.com/c/go/+/356411 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- .../internal/types2/testdata/fixedbugs/issue49003.go | 10 ++++++++++ src/go/types/testdata/fixedbugs/issue49003.go | 10 ++++++++++ 2 files changed, 20 insertions(+) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue49003.go create mode 100644 src/go/types/testdata/fixedbugs/issue49003.go diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49003.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49003.go new file mode 100644 index 0000000000..ece1a27bb9 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49003.go @@ -0,0 +1,10 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func f(s string) int { + for range s { + } +} // ERROR missing return diff --git a/src/go/types/testdata/fixedbugs/issue49003.go b/src/go/types/testdata/fixedbugs/issue49003.go new file mode 100644 index 0000000000..ece1a27bb9 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue49003.go @@ -0,0 +1,10 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func f(s string) int { + for range s { + } +} // ERROR missing return -- GitLab From cf51fb5d680a9a1ca98af3361e65722d07bff111 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sat, 16 Oct 2021 20:30:12 -0700 Subject: [PATCH 1627/2500] cmd/compile, types2: avoid confusing follow-on error in invalid type assertion This CL avoids a useless follow-on error (that gets reported before the actual error due to source position). This addresses the first part of the issue below. Thanks to @cuonglm for the suggestion for the fix. For #49005. Change-Id: Ifdd83072a05c32e115dc58a0233868a64f336f3f Reviewed-on: https://go-review.googlesource.com/c/go/+/356449 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/types2/typexpr.go | 7 +++++++ test/fixedbugs/issue49005a.go | 13 +++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 test/fixedbugs/issue49005a.go diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 646becbdae..eae9330914 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -312,6 +312,13 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) { typ := new(Pointer) def.setUnderlying(typ) typ.base = check.varType(e.X) + // If typ.base is invalid, it's unlikely that *base is particularly + // useful - even a valid dereferenciation will lead to an invalid + // type again, and in some cases we get unexpected follow-on errors + // (e.g., see #49005). Return an invalid type instead. + if typ.base == Typ[Invalid] { + return Typ[Invalid] + } return typ } diff --git a/test/fixedbugs/issue49005a.go b/test/fixedbugs/issue49005a.go new file mode 100644 index 0000000000..55d92c4650 --- /dev/null +++ b/test/fixedbugs/issue49005a.go @@ -0,0 +1,13 @@ +// errorcheck + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T interface{ M() } + +func F() T + +var _ = F().(*X) // ERROR "undefined: X" -- GitLab From 74acbaf94ab3c7aaa7e22fda4f90920e90f11ead Mon Sep 17 00:00:00 2001 From: wdvxdr Date: Wed, 13 Oct 2021 19:44:38 +0800 Subject: [PATCH 1628/2500] cmd/compile: allow inlining labeled for-statement and switch-statement After CL 349012 and CL 350911, we can fully handle these labeled statements, so we can allow them when inlining. Updates #14768 Change-Id: I0ab3fd3f8d7436b49b1aedd946516b33c63f5747 Reviewed-on: https://go-review.googlesource.com/c/go/+/355497 Run-TryBot: David Chase TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky Reviewed-by: Dan Scales Reviewed-by: David Chase Trust: Dan Scales --- src/cmd/compile/internal/inline/inl.go | 21 --------------------- test/inline.go | 6 ++---- 2 files changed, 2 insertions(+), 25 deletions(-) diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index 51270a3315..a2268a5465 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -390,27 +390,6 @@ func (v *hairyVisitor) doNode(n ir.Node) bool { // These nodes don't produce code; omit from inlining budget. return false - case ir.OFOR, ir.OFORUNTIL: - n := n.(*ir.ForStmt) - if n.Label != nil { - v.reason = "labeled control" - return true - } - case ir.OSWITCH: - n := n.(*ir.SwitchStmt) - if n.Label != nil { - v.reason = "labeled control" - return true - } - // case ir.ORANGE, ir.OSELECT in "unhandled" above - - case ir.OBREAK, ir.OCONTINUE: - n := n.(*ir.BranchStmt) - if n.Label != nil { - // Should have short-circuited due to labeled control error above. - base.Fatalf("unexpected labeled break/continue: %v", n) - } - case ir.OIF: n := n.(*ir.IfStmt) if ir.IsConst(n.Cond, constant.Bool) { diff --git a/test/inline.go b/test/inline.go index a73c0ba7b1..599d5233e0 100644 --- a/test/inline.go +++ b/test/inline.go @@ -135,8 +135,7 @@ func s1(x int) int { // ERROR "can inline s1" return foo() // ERROR "inlining call to s1.func1" } -// can't currently inline functions with a break statement -func switchBreak(x, y int) int { +func switchBreak(x, y int) int { // ERROR "can inline switchBreak" var n int switch x { case 0: @@ -218,8 +217,7 @@ func for1(fn func() bool) { // ERROR "can inline for1" "fn does not escape" } } -// BAD: for2 should be inlineable too. -func for2(fn func() bool) { // ERROR "fn does not escape" +func for2(fn func() bool) { // ERROR "can inline for2" "fn does not escape" Loop: for { if fn() { -- GitLab From c091767d87b7a6ef6016286bc0fae8add59b92de Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 15 Oct 2021 13:52:05 -0700 Subject: [PATCH 1629/2500] cmd/asm: report an error when trying to do spectre on 386 The compiler refuses to do spectre mitigation on 386, but the assembler doesn't. Fix that. Fixes #49006 Change-Id: I887b6f7ed7523a47f463706f06ca4c2c6e828b6b Reviewed-on: https://go-review.googlesource.com/c/go/+/356190 Trust: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/internal/obj/x86/asm6.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go index 43ce832b17..6555756fd3 100644 --- a/src/cmd/internal/obj/x86/asm6.go +++ b/src/cmd/internal/obj/x86/asm6.go @@ -2035,6 +2035,11 @@ type nopPad struct { } func span6(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { + if ctxt.Retpoline && ctxt.Arch.Family == sys.I386 { + ctxt.Diag("-spectre=ret not supported on 386") + ctxt.Retpoline = false // don't keep printing + } + pjc := makePjcCtx(ctxt) if s.P != nil { -- GitLab From 3e5cc4d6f6befb284d7b2a5142a8b576bf5970ea Mon Sep 17 00:00:00 2001 From: wdvxdr Date: Fri, 8 Oct 2021 16:06:42 +0800 Subject: [PATCH 1630/2500] cmd/compile: use MOVBE instruction for GOAMD64>=v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit encoding/binary benchmark on my laptop: name old time/op new time/op delta ReadSlice1000Int32s-8 4.42µs ± 5% 4.20µs ± 1% -4.94% (p=0.046 n=9+8) ReadStruct-8 359ns ± 8% 368ns ± 5% +2.35% (p=0.041 n=9+10) WriteStruct-8 349ns ± 1% 357ns ± 1% +2.15% (p=0.000 n=8+10) ReadInts-8 235ns ± 1% 233ns ± 1% -1.01% (p=0.005 n=10+10) WriteInts-8 265ns ± 1% 274ns ± 1% +3.45% (p=0.000 n=10+10) WriteSlice1000Int32s-8 4.61µs ± 5% 4.59µs ± 5% ~ (p=0.986 n=10+10) PutUint16-8 0.56ns ± 4% 0.57ns ± 4% ~ (p=0.101 n=10+10) PutUint32-8 0.83ns ± 2% 0.56ns ± 6% -32.91% (p=0.000 n=10+10) PutUint64-8 0.81ns ± 3% 0.62ns ± 4% -23.82% (p=0.000 n=10+10) LittleEndianPutUint16-8 0.55ns ± 4% 0.55ns ± 3% ~ (p=0.926 n=10+10) LittleEndianPutUint32-8 0.41ns ± 4% 0.42ns ± 3% ~ (p=0.148 n=10+9) LittleEndianPutUint64-8 0.55ns ± 2% 0.56ns ± 6% ~ (p=0.897 n=10+10) ReadFloats-8 60.4ns ± 4% 59.0ns ± 1% -2.25% (p=0.007 n=10+10) WriteFloats-8 72.3ns ± 2% 71.5ns ± 7% ~ (p=0.089 n=10+10) ReadSlice1000Float32s-8 4.21µs ± 3% 4.18µs ± 2% ~ (p=0.197 n=10+10) WriteSlice1000Float32s-8 4.61µs ± 2% 4.68µs ± 7% ~ (p=1.000 n=8+10) ReadSlice1000Uint8s-8 250ns ± 4% 247ns ± 4% ~ (p=0.324 n=10+10) WriteSlice1000Uint8s-8 227ns ± 5% 229ns ± 2% ~ (p=0.193 n=10+7) PutUvarint32-8 15.3ns ± 2% 15.4ns ± 4% ~ (p=0.782 n=10+10) PutUvarint64-8 38.5ns ± 1% 38.6ns ± 5% ~ (p=0.396 n=8+10) name old speed new speed delta ReadSlice1000Int32s-8 890MB/s ±17% 953MB/s ± 1% +7.00% (p=0.027 n=10+8) ReadStruct-8 209MB/s ± 8% 204MB/s ± 5% -2.42% (p=0.043 n=9+10) WriteStruct-8 214MB/s ± 3% 210MB/s ± 1% -1.75% (p=0.003 n=9+10) ReadInts-8 127MB/s ± 1% 129MB/s ± 1% +1.01% (p=0.006 n=10+10) WriteInts-8 113MB/s ± 1% 109MB/s ± 1% -3.34% (p=0.000 n=10+10) WriteSlice1000Int32s-8 868MB/s ± 5% 872MB/s ± 5% ~ (p=1.000 n=10+10) PutUint16-8 3.55GB/s ± 4% 3.50GB/s ± 4% ~ (p=0.093 n=10+10) PutUint32-8 4.83GB/s ± 2% 7.21GB/s ± 6% +49.16% (p=0.000 n=10+10) PutUint64-8 9.89GB/s ± 3% 12.99GB/s ± 4% +31.26% (p=0.000 n=10+10) LittleEndianPutUint16-8 3.65GB/s ± 4% 3.65GB/s ± 4% ~ (p=0.912 n=10+10) LittleEndianPutUint32-8 9.74GB/s ± 3% 9.63GB/s ± 3% ~ (p=0.222 n=9+9) LittleEndianPutUint64-8 14.4GB/s ± 2% 14.3GB/s ± 5% ~ (p=0.912 n=10+10) ReadFloats-8 199MB/s ± 4% 203MB/s ± 1% +2.27% (p=0.007 n=10+10) WriteFloats-8 166MB/s ± 2% 168MB/s ± 7% ~ (p=0.089 n=10+10) ReadSlice1000Float32s-8 949MB/s ± 3% 958MB/s ± 2% ~ (p=0.218 n=10+10) WriteSlice1000Float32s-8 867MB/s ± 2% 857MB/s ± 6% ~ (p=1.000 n=8+10) ReadSlice1000Uint8s-8 4.00GB/s ± 4% 4.06GB/s ± 4% ~ (p=0.353 n=10+10) WriteSlice1000Uint8s-8 4.40GB/s ± 4% 4.36GB/s ± 2% ~ (p=0.193 n=10+7) PutUvarint32-8 262MB/s ± 2% 260MB/s ± 4% ~ (p=0.739 n=10+10) PutUvarint64-8 208MB/s ± 1% 207MB/s ± 5% ~ (p=0.408 n=8+10) Updates #45453 Change-Id: Ifda0d48d54665cef45d46d3aad974062633142c4 Reviewed-on: https://go-review.googlesource.com/c/go/+/354670 Run-TryBot: Alberto Donizetti TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Matthew Dempsky --- src/cmd/compile/internal/amd64/ssa.go | 7 +- .../compile/internal/amd64/versions_test.go | 27 +- src/cmd/compile/internal/ssa/gen/AMD64.rules | 26 ++ src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 6 + src/cmd/compile/internal/ssa/opGen.go | 64 +++++ src/cmd/compile/internal/ssa/rewriteAMD64.go | 243 ++++++++++++++++++ test/codegen/memcombine.go | 36 ++- 7 files changed, 389 insertions(+), 20 deletions(-) diff --git a/src/cmd/compile/internal/amd64/ssa.go b/src/cmd/compile/internal/amd64/ssa.go index 0e74574422..b0e5c34030 100644 --- a/src/cmd/compile/internal/amd64/ssa.go +++ b/src/cmd/compile/internal/amd64/ssa.go @@ -772,7 +772,9 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.From.Val = math.Float64frombits(uint64(v.AuxInt)) p.To.Type = obj.TYPE_REG p.To.Reg = x - case ssa.OpAMD64MOVQload, ssa.OpAMD64MOVSSload, ssa.OpAMD64MOVSDload, ssa.OpAMD64MOVLload, ssa.OpAMD64MOVWload, ssa.OpAMD64MOVBload, ssa.OpAMD64MOVBQSXload, ssa.OpAMD64MOVWQSXload, ssa.OpAMD64MOVLQSXload, ssa.OpAMD64MOVOload: + case ssa.OpAMD64MOVQload, ssa.OpAMD64MOVLload, ssa.OpAMD64MOVWload, ssa.OpAMD64MOVBload, ssa.OpAMD64MOVOload, + ssa.OpAMD64MOVSSload, ssa.OpAMD64MOVSDload, ssa.OpAMD64MOVBQSXload, ssa.OpAMD64MOVWQSXload, ssa.OpAMD64MOVLQSXload, + ssa.OpAMD64MOVBEQload, ssa.OpAMD64MOVBELload: p := s.Prog(v.Op.Asm()) p.From.Type = obj.TYPE_MEM p.From.Reg = v.Args[0].Reg() @@ -788,7 +790,8 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.To.Reg = v.Reg() case ssa.OpAMD64MOVQstore, ssa.OpAMD64MOVSSstore, ssa.OpAMD64MOVSDstore, ssa.OpAMD64MOVLstore, ssa.OpAMD64MOVWstore, ssa.OpAMD64MOVBstore, ssa.OpAMD64MOVOstore, ssa.OpAMD64ADDQmodify, ssa.OpAMD64SUBQmodify, ssa.OpAMD64ANDQmodify, ssa.OpAMD64ORQmodify, ssa.OpAMD64XORQmodify, - ssa.OpAMD64ADDLmodify, ssa.OpAMD64SUBLmodify, ssa.OpAMD64ANDLmodify, ssa.OpAMD64ORLmodify, ssa.OpAMD64XORLmodify: + ssa.OpAMD64ADDLmodify, ssa.OpAMD64SUBLmodify, ssa.OpAMD64ANDLmodify, ssa.OpAMD64ORLmodify, ssa.OpAMD64XORLmodify, + ssa.OpAMD64MOVBEQstore, ssa.OpAMD64MOVBELstore: p := s.Prog(v.Op.Asm()) p.From.Type = obj.TYPE_REG p.From.Reg = v.Args[1].Reg() diff --git a/src/cmd/compile/internal/amd64/versions_test.go b/src/cmd/compile/internal/amd64/versions_test.go index de677f3a69..ee1a8ca3aa 100644 --- a/src/cmd/compile/internal/amd64/versions_test.go +++ b/src/cmd/compile/internal/amd64/versions_test.go @@ -53,7 +53,9 @@ func TestGoAMD64v1(t *testing.T) { opcodes := map[string]bool{} var features []string for feature, opcodeList := range featureToOpcodes { - features = append(features, fmt.Sprintf("cpu.%s=off", feature)) + if runtimeFeatures[feature] { + features = append(features, fmt.Sprintf("cpu.%s=off", feature)) + } for _, op := range opcodeList { opcodes[op] = true } @@ -204,14 +206,28 @@ func clobber(t *testing.T, src string, dst *os.File, opcodes map[string]bool) { f.Close() } +func setOf(keys ...string) map[string]bool { + m := make(map[string]bool, len(keys)) + for _, key := range keys { + m[key] = true + } + return m +} + +var runtimeFeatures = setOf( + "adx", "aes", "avx", "avx2", "bmi1", "bmi2", "erms", "fma", + "pclmulqdq", "popcnt", "rdtscp", "sse3", "sse41", "sse42", "ssse3", +) + var featureToOpcodes = map[string][]string{ // Note: we include *q, *l, and plain opcodes here. // go tool objdump doesn't include a [QL] on popcnt instructions, until CL 351889 // native objdump doesn't include [QL] on linux. - "popcnt": []string{"popcntq", "popcntl", "popcnt"}, - "bmi1": []string{"andnq", "andnl", "andn", "blsiq", "blsil", "blsi", "blsmskq", "blsmskl", "blsmsk", "blsrq", "blsrl", "blsr", "tzcntq", "tzcntl", "tzcnt"}, - "sse41": []string{"roundsd"}, - "fma": []string{"vfmadd231sd"}, + "popcnt": {"popcntq", "popcntl", "popcnt"}, + "bmi1": {"andnq", "andnl", "andn", "blsiq", "blsil", "blsi", "blsmskq", "blsmskl", "blsmsk", "blsrq", "blsrl", "blsr", "tzcntq", "tzcntl", "tzcnt"}, + "sse41": {"roundsd"}, + "fma": {"vfmadd231sd"}, + "movbe": {"movbeqq", "movbeq", "movbell", "movbel", "movbe"}, } // Test to use POPCNT instruction, if available @@ -364,5 +380,4 @@ func TestFMA(t *testing.T) { t.Errorf("FMA(%f,%f,%f) = %f, want %f", tt.x, tt.y, tt.z, got, tt.want) } } - } diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 8b73ee14ea..507d701999 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -2219,3 +2219,29 @@ (AND(Q|L) x (ADD(Q|L)const [-1] x)) && buildcfg.GOAMD64 >= 3 => (BLSR(Q|L) x) (BSWAP(Q|L) (BSWAP(Q|L) p)) => p + +// CPUID feature: MOVBE. +(MOV(Q|L)store [i] {s} p x:(BSWAP(Q|L) w) mem) && x.Uses == 1 && buildcfg.GOAMD64 >= 3 => (MOVBE(Q|L)store [i] {s} p w mem) +(BSWAP(Q|L) x:(MOV(Q|L)load [i] {s} p mem)) && x.Uses == 1 && buildcfg.GOAMD64 >= 3 => (MOVBE(Q|L)load [i] {s} p mem) +(BSWAP(Q|L) (MOVBE(Q|L)load [i] {s} p m)) => (MOV(Q|L)load [i] {s} p m) +(MOVBE(Q|L)store [i] {s} p (BSWAP(Q|L) x) m) => (MOV(Q|L)store [i] {s} p x m) + +(ORQ x0:(MOVBELload [i0] {s} p mem) + sh:(SHLQconst [32] x1:(MOVBELload [i1] {s} p mem))) + && i0 == i1+4 + && x0.Uses == 1 + && x1.Uses == 1 + && sh.Uses == 1 + && mergePoint(b,x0,x1) != nil + && clobber(x0, x1, sh) + => @mergePoint(b,x0,x1) (MOVBEQload [i1] {s} p mem) + +(ORQ x0:(MOVBELload [i] {s} p0 mem) + sh:(SHLQconst [32] x1:(MOVBELload [i] {s} p1 mem))) + && x0.Uses == 1 + && x1.Uses == 1 + && sh.Uses == 1 + && sequentialAddresses(p1, p0, 4) + && mergePoint(b,x0,x1) != nil + && clobber(x0, x1, sh) + => @mergePoint(b,x0,x1) (MOVBEQload [i] {s} p0 mem) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index 731454c761..e3c94e4b2e 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -922,6 +922,12 @@ func init() { // and BSFQ(0) is undefined. Same for TZCNTL(0)==32 {name: "TZCNTQ", argLength: 1, reg: gp11, asm: "TZCNTQ", clobberFlags: true}, {name: "TZCNTL", argLength: 1, reg: gp11, asm: "TZCNTL", clobberFlags: true}, + + // CPUID feature: MOVBE + {name: "MOVBELload", argLength: 2, reg: gpload, asm: "MOVBEL", aux: "SymOff", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"}, // load and swap 4 bytes from arg0+auxint+aux. arg1=mem. Zero extend. + {name: "MOVBELstore", argLength: 3, reg: gpstore, asm: "MOVBEL", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // swap and store 4 bytes in arg1 to arg0+auxint+aux. arg2=mem + {name: "MOVBEQload", argLength: 2, reg: gpload, asm: "MOVBEQ", aux: "SymOff", typ: "UInt64", faultOnNilArg0: true, symEffect: "Read"}, // load and swap 8 bytes from arg0+auxint+aux. arg1=mem + {name: "MOVBEQstore", argLength: 3, reg: gpstore, asm: "MOVBEQ", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // swap and store 8 bytes in arg1 to arg0+auxint+aux. arg2=mem } var AMD64blocks = []blockData{ diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 640e517fe7..091f43f40a 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -1043,6 +1043,10 @@ const ( OpAMD64BLSRL OpAMD64TZCNTQ OpAMD64TZCNTL + OpAMD64MOVBELload + OpAMD64MOVBELstore + OpAMD64MOVBEQload + OpAMD64MOVBEQstore OpARMADD OpARMADDconst @@ -13780,6 +13784,66 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "MOVBELload", + auxType: auxSymOff, + argLen: 2, + faultOnNilArg0: true, + symEffect: SymRead, + asm: x86.AMOVBEL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB + }, + outputs: []outputInfo{ + {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + }, + }, + }, + { + name: "MOVBELstore", + auxType: auxSymOff, + argLen: 3, + faultOnNilArg0: true, + symEffect: SymWrite, + asm: x86.AMOVBEL, + reg: regInfo{ + inputs: []inputInfo{ + {1, 49151}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15 + {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB + }, + }, + }, + { + name: "MOVBEQload", + auxType: auxSymOff, + argLen: 2, + faultOnNilArg0: true, + symEffect: SymRead, + asm: x86.AMOVBEQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB + }, + outputs: []outputInfo{ + {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + }, + }, + }, + { + name: "MOVBEQstore", + auxType: auxSymOff, + argLen: 3, + faultOnNilArg0: true, + symEffect: SymWrite, + asm: x86.AMOVBEQ, + reg: regInfo{ + inputs: []inputInfo{ + {1, 49151}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15 + {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB + }, + }, + }, { name: "ADD", diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 201fbf2954..88b545a465 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -222,6 +222,10 @@ func rewriteValueAMD64(v *Value) bool { return rewriteValueAMD64_OpAMD64LEAQ4(v) case OpAMD64LEAQ8: return rewriteValueAMD64_OpAMD64LEAQ8(v) + case OpAMD64MOVBELstore: + return rewriteValueAMD64_OpAMD64MOVBELstore(v) + case OpAMD64MOVBEQstore: + return rewriteValueAMD64_OpAMD64MOVBEQstore(v) case OpAMD64MOVBQSX: return rewriteValueAMD64_OpAMD64MOVBQSX(v) case OpAMD64MOVBQSXload: @@ -3623,6 +3627,43 @@ func rewriteValueAMD64_OpAMD64BSWAPL(v *Value) bool { v.copyOf(p) return true } + // match: (BSWAPL x:(MOVLload [i] {s} p mem)) + // cond: x.Uses == 1 && buildcfg.GOAMD64 >= 3 + // result: (MOVBELload [i] {s} p mem) + for { + x := v_0 + if x.Op != OpAMD64MOVLload { + break + } + i := auxIntToInt32(x.AuxInt) + s := auxToSym(x.Aux) + mem := x.Args[1] + p := x.Args[0] + if !(x.Uses == 1 && buildcfg.GOAMD64 >= 3) { + break + } + v.reset(OpAMD64MOVBELload) + v.AuxInt = int32ToAuxInt(i) + v.Aux = symToAux(s) + v.AddArg2(p, mem) + return true + } + // match: (BSWAPL (MOVBELload [i] {s} p m)) + // result: (MOVLload [i] {s} p m) + for { + if v_0.Op != OpAMD64MOVBELload { + break + } + i := auxIntToInt32(v_0.AuxInt) + s := auxToSym(v_0.Aux) + m := v_0.Args[1] + p := v_0.Args[0] + v.reset(OpAMD64MOVLload) + v.AuxInt = int32ToAuxInt(i) + v.Aux = symToAux(s) + v.AddArg2(p, m) + return true + } return false } func rewriteValueAMD64_OpAMD64BSWAPQ(v *Value) bool { @@ -3637,6 +3678,43 @@ func rewriteValueAMD64_OpAMD64BSWAPQ(v *Value) bool { v.copyOf(p) return true } + // match: (BSWAPQ x:(MOVQload [i] {s} p mem)) + // cond: x.Uses == 1 && buildcfg.GOAMD64 >= 3 + // result: (MOVBEQload [i] {s} p mem) + for { + x := v_0 + if x.Op != OpAMD64MOVQload { + break + } + i := auxIntToInt32(x.AuxInt) + s := auxToSym(x.Aux) + mem := x.Args[1] + p := x.Args[0] + if !(x.Uses == 1 && buildcfg.GOAMD64 >= 3) { + break + } + v.reset(OpAMD64MOVBEQload) + v.AuxInt = int32ToAuxInt(i) + v.Aux = symToAux(s) + v.AddArg2(p, mem) + return true + } + // match: (BSWAPQ (MOVBEQload [i] {s} p m)) + // result: (MOVQload [i] {s} p m) + for { + if v_0.Op != OpAMD64MOVBEQload { + break + } + i := auxIntToInt32(v_0.AuxInt) + s := auxToSym(v_0.Aux) + m := v_0.Args[1] + p := v_0.Args[0] + v.reset(OpAMD64MOVQload) + v.AuxInt = int32ToAuxInt(i) + v.Aux = symToAux(s) + v.AddArg2(p, m) + return true + } return false } func rewriteValueAMD64_OpAMD64BTCLconst(v *Value) bool { @@ -9395,6 +9473,52 @@ func rewriteValueAMD64_OpAMD64LEAQ8(v *Value) bool { } return false } +func rewriteValueAMD64_OpAMD64MOVBELstore(v *Value) bool { + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] + // match: (MOVBELstore [i] {s} p (BSWAPL x) m) + // result: (MOVLstore [i] {s} p x m) + for { + i := auxIntToInt32(v.AuxInt) + s := auxToSym(v.Aux) + p := v_0 + if v_1.Op != OpAMD64BSWAPL { + break + } + x := v_1.Args[0] + m := v_2 + v.reset(OpAMD64MOVLstore) + v.AuxInt = int32ToAuxInt(i) + v.Aux = symToAux(s) + v.AddArg3(p, x, m) + return true + } + return false +} +func rewriteValueAMD64_OpAMD64MOVBEQstore(v *Value) bool { + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] + // match: (MOVBEQstore [i] {s} p (BSWAPQ x) m) + // result: (MOVQstore [i] {s} p x m) + for { + i := auxIntToInt32(v.AuxInt) + s := auxToSym(v.Aux) + p := v_0 + if v_1.Op != OpAMD64BSWAPQ { + break + } + x := v_1.Args[0] + m := v_2 + v.reset(OpAMD64MOVQstore) + v.AuxInt = int32ToAuxInt(i) + v.Aux = symToAux(s) + v.AddArg3(p, x, m) + return true + } + return false +} func rewriteValueAMD64_OpAMD64MOVBQSX(v *Value) bool { v_0 := v.Args[0] b := v.Block @@ -12225,6 +12349,28 @@ func rewriteValueAMD64_OpAMD64MOVLstore(v *Value) bool { v.AddArg3(ptr, val, mem) return true } + // match: (MOVLstore [i] {s} p x:(BSWAPL w) mem) + // cond: x.Uses == 1 && buildcfg.GOAMD64 >= 3 + // result: (MOVBELstore [i] {s} p w mem) + for { + i := auxIntToInt32(v.AuxInt) + s := auxToSym(v.Aux) + p := v_0 + x := v_1 + if x.Op != OpAMD64BSWAPL { + break + } + w := x.Args[0] + mem := v_2 + if !(x.Uses == 1 && buildcfg.GOAMD64 >= 3) { + break + } + v.reset(OpAMD64MOVBELstore) + v.AuxInt = int32ToAuxInt(i) + v.Aux = symToAux(s) + v.AddArg3(p, w, mem) + return true + } return false } func rewriteValueAMD64_OpAMD64MOVLstoreconst(v *Value) bool { @@ -13164,6 +13310,28 @@ func rewriteValueAMD64_OpAMD64MOVQstore(v *Value) bool { v.AddArg3(ptr, val, mem) return true } + // match: (MOVQstore [i] {s} p x:(BSWAPQ w) mem) + // cond: x.Uses == 1 && buildcfg.GOAMD64 >= 3 + // result: (MOVBEQstore [i] {s} p w mem) + for { + i := auxIntToInt32(v.AuxInt) + s := auxToSym(v.Aux) + p := v_0 + x := v_1 + if x.Op != OpAMD64BSWAPQ { + break + } + w := x.Args[0] + mem := v_2 + if !(x.Uses == 1 && buildcfg.GOAMD64 >= 3) { + break + } + v.reset(OpAMD64MOVBEQstore) + v.AuxInt = int32ToAuxInt(i) + v.Aux = symToAux(s) + v.AddArg3(p, w, mem) + return true + } return false } func rewriteValueAMD64_OpAMD64MOVQstoreconst(v *Value) bool { @@ -18657,6 +18825,81 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { } break } + // match: (ORQ x0:(MOVBELload [i0] {s} p mem) sh:(SHLQconst [32] x1:(MOVBELload [i1] {s} p mem))) + // cond: i0 == i1+4 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) + // result: @mergePoint(b,x0,x1) (MOVBEQload [i1] {s} p mem) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x0 := v_0 + if x0.Op != OpAMD64MOVBELload { + continue + } + i0 := auxIntToInt32(x0.AuxInt) + s := auxToSym(x0.Aux) + mem := x0.Args[1] + p := x0.Args[0] + sh := v_1 + if sh.Op != OpAMD64SHLQconst || auxIntToInt8(sh.AuxInt) != 32 { + continue + } + x1 := sh.Args[0] + if x1.Op != OpAMD64MOVBELload { + continue + } + i1 := auxIntToInt32(x1.AuxInt) + if auxToSym(x1.Aux) != s { + continue + } + _ = x1.Args[1] + if p != x1.Args[0] || mem != x1.Args[1] || !(i0 == i1+4 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { + continue + } + b = mergePoint(b, x0, x1) + v0 := b.NewValue0(x1.Pos, OpAMD64MOVBEQload, typ.UInt64) + v.copyOf(v0) + v0.AuxInt = int32ToAuxInt(i1) + v0.Aux = symToAux(s) + v0.AddArg2(p, mem) + return true + } + break + } + // match: (ORQ x0:(MOVBELload [i] {s} p0 mem) sh:(SHLQconst [32] x1:(MOVBELload [i] {s} p1 mem))) + // cond: x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p1, p0, 4) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) + // result: @mergePoint(b,x0,x1) (MOVBEQload [i] {s} p0 mem) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x0 := v_0 + if x0.Op != OpAMD64MOVBELload { + continue + } + i := auxIntToInt32(x0.AuxInt) + s := auxToSym(x0.Aux) + mem := x0.Args[1] + p0 := x0.Args[0] + sh := v_1 + if sh.Op != OpAMD64SHLQconst || auxIntToInt8(sh.AuxInt) != 32 { + continue + } + x1 := sh.Args[0] + if x1.Op != OpAMD64MOVBELload || auxIntToInt32(x1.AuxInt) != i || auxToSym(x1.Aux) != s { + continue + } + _ = x1.Args[1] + p1 := x1.Args[0] + if mem != x1.Args[1] || !(x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p1, p0, 4) && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { + continue + } + b = mergePoint(b, x0, x1) + v0 := b.NewValue0(x1.Pos, OpAMD64MOVBEQload, typ.UInt64) + v.copyOf(v0) + v0.AuxInt = int32ToAuxInt(i) + v0.Aux = symToAux(s) + v0.AddArg2(p0, mem) + return true + } + break + } return false } func rewriteValueAMD64_OpAMD64ORQconst(v *Value) bool { diff --git a/test/codegen/memcombine.go b/test/codegen/memcombine.go index 2a0c534df0..97e1d4bdfb 100644 --- a/test/codegen/memcombine.go +++ b/test/codegen/memcombine.go @@ -70,7 +70,8 @@ func load_le16_idx(b []byte, idx int) { } func load_be64(b []byte) { - // amd64:`BSWAPQ`,-`MOV[BWL]\t[^$]`,-`OR` + // amd64/v1,amd64/v2:`BSWAPQ`,-`MOV[BWL]\t[^$]`,-`OR` + // amd64/v3:`MOVBEQ` // s390x:`MOVD\s\(.*\),` // arm64:`REV`,`MOVD\s\(R[0-9]+\),`,-`MOV[BHW]`,-`REVW`,-`REV16W` // ppc64le:`MOVDBR`,-`MOV[BHW]Z` @@ -78,7 +79,8 @@ func load_be64(b []byte) { } func load_be64_idx(b []byte, idx int) { - // amd64:`BSWAPQ`,-`MOV[BWL]\t[^$]`,-`OR` + // amd64/v1,amd64/v2:`BSWAPQ`,-`MOV[BWL]\t[^$]`,-`OR` + // amd64/v3: `MOVBEQ` // s390x:`MOVD\s\(.*\)\(.*\*1\),` // arm64:`REV`,`MOVD\s\(R[0-9]+\)\(R[0-9]+\),`,-`MOV[WHB]`,-`REVW`,-`REV16W` // ppc64le:`MOVDBR`,-`MOV[BHW]Z` @@ -86,7 +88,8 @@ func load_be64_idx(b []byte, idx int) { } func load_be32(b []byte) { - // amd64:`BSWAPL`,-`MOV[BW]`,-`OR` + // amd64/v1,amd64/v2:`BSWAPL`,-`MOV[BW]`,-`OR` + // amd64/v3: `MOVBEL` // s390x:`MOVWZ\s\(.*\),` // arm64:`REVW`,`MOVWU\s\(R[0-9]+\),`,-`MOV[BH]`,-`REV16W` // ppc64le:`MOVWBR`,-`MOV[BH]Z` @@ -94,7 +97,8 @@ func load_be32(b []byte) { } func load_be32_idx(b []byte, idx int) { - // amd64:`BSWAPL`,-`MOV[BW]`,-`OR` + // amd64/v1,amd64/v2:`BSWAPL`,-`MOV[BW]`,-`OR` + // amd64/v3: `MOVBEL` // s390x:`MOVWZ\s\(.*\)\(.*\*1\),` // arm64:`REVW`,`MOVWU\s\(R[0-9]+\)\(R[0-9]+\),`,-`MOV[HB]`,-`REV16W` // ppc64le:`MOVWBR`,-`MOV[BH]Z` @@ -179,7 +183,8 @@ func load_be_byte4_uint32(s []byte) uint32 { func load_be_byte4_uint32_inv(s []byte) uint32 { // arm64:`MOVWU\t\(R[0-9]+\)`,`REVW`,-`ORR`,-`REV16W`,-`MOV[BH]` - // amd64:`MOVL\s\([A-Z]+\)`,`BSWAPL`,-`MOV[BW]`,-`OR` + // amd64/v1,amd64/v2:`MOVL\s\([A-Z]+\)`,`BSWAPL`,-`MOV[BW]`,-`OR` + // amd64/v3: `MOVBEL` return uint32(s[3]) | uint32(s[2])<<8 | uint32(s[1])<<16 | uint32(s[0])<<24 } @@ -191,7 +196,8 @@ func load_be_byte8_uint64(s []byte) uint64 { func load_be_byte8_uint64_inv(s []byte) uint64 { // arm64:`MOVD\t\(R[0-9]+\)`,`REV`,-`ORR`,-`REVW`,-`REV16W`,-`MOV[BHW]` - // amd64:`MOVQ\s\([A-Z]+\),\s[A-Z]+`,`BSWAPQ`,-`MOV[BWL]\t[^$]`,-`OR` + // amd64/v1,amd64/v2:`MOVQ\s\([A-Z]+\),\s[A-Z]+`,`BSWAPQ`,-`MOV[BWL]\t[^$]`,-`OR` + // amd64/v3: `MOVBEQ` // ppc64le:`MOVDBR\t\(R[0-9]+\)`,-`MOV[BHW]Z` return uint64(s[7]) | uint64(s[6])<<8 | uint64(s[5])<<16 | uint64(s[4])<<24 | uint64(s[3])<<32 | uint64(s[2])<<40 | uint64(s[1])<<48 | uint64(s[0])<<56 } @@ -409,7 +415,8 @@ func store_le16_idx(b []byte, idx int) { } func store_be64(b []byte) { - // amd64:`BSWAPQ`,-`SHR.` + // amd64/v1,amd64/v2:`BSWAPQ`,-`SHR.` + // amd64/v3: `MOVBEQ` // arm64:`MOVD`,`REV`,-`MOV[WBH]`,-`REVW`,-`REV16W` // ppc64le:`MOVDBR` // s390x:`MOVD\s.*\(.*\)$`,-`SRW\s`,-`SRD\s` @@ -417,7 +424,8 @@ func store_be64(b []byte) { } func store_be64_idx(b []byte, idx int) { - // amd64:`BSWAPQ`,-`SHR.` + // amd64/v1,amd64/v2:`BSWAPQ`,-`SHR.` + // amd64/v3:`MOVBEQ` // arm64:`REV`,`MOVD\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOV[BHW]`,-`REV16W`,-`REVW` // ppc64le:`MOVDBR` // s390x:`MOVD\s.*\(.*\)\(.*\*1\)$`,-`SRW\s`,-`SRD\s` @@ -425,7 +433,8 @@ func store_be64_idx(b []byte, idx int) { } func store_be32(b []byte) { - // amd64:`BSWAPL`,-`SHR.` + // amd64/v1,amd64/v2:`BSWAPL`,-`SHR.` + // amd64/v3:`MOVBEL` // arm64:`MOVW`,`REVW`,-`MOV[BH]`,-`REV16W` // ppc64le:`MOVWBR` // s390x:`MOVW\s.*\(.*\)$`,-`SRW\s`,-`SRD\s` @@ -445,7 +454,8 @@ func store_be32_load(b, x *[8]byte) { } func store_be32_idx(b []byte, idx int) { - // amd64:`BSWAPL`,-`SHR.` + // amd64/v1,amd64/v2:`BSWAPL`,-`SHR.` + // amd64/v3:`MOVBEL` // arm64:`REVW`,`MOVW\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOV[BH]`,-`REV16W` // ppc64le:`MOVWBR` // s390x:`MOVW\s.*\(.*\)\(.*\*1\)$`,-`SRW\s`,-`SRD\s` @@ -508,14 +518,16 @@ func store_be_byte_2(b []byte, val uint16) { func store_be_byte_4(b []byte, val uint32) { _ = b[4] // arm64:`REVW`,`MOVW\sR[0-9]+,\s1\(R[0-9]+\)`,-`MOVB`,-`MOVH`,-`REV16W` - // amd64:`MOVL\s[A-Z]+,\s1\([A-Z]+\)`,-`MOVB`,-`MOVW` + // amd64/v1,amd64/v2:`MOVL\s[A-Z]+,\s1\([A-Z]+\)`,-`MOVB`,-`MOVW` + // amd64/v3:`MOVBEL\s[A-Z]+,\s1\([A-Z]+\)` b[1], b[2], b[3], b[4] = byte(val>>24), byte(val>>16), byte(val>>8), byte(val) } func store_be_byte_8(b []byte, val uint64) { _ = b[8] // arm64:`REV`,`MOVD\sR[0-9]+,\s1\(R[0-9]+\)`,-`MOVB`,-`MOVH`,-`MOVW`,-`REV16W`,-`REVW` - // amd64:`MOVQ\s[A-Z]+,\s1\([A-Z]+\)`,-`MOVB`,-`MOVW`,-`MOVL` + // amd64/v1,amd64/v2:`MOVQ\s[A-Z]+,\s1\([A-Z]+\)`,-`MOVB`,-`MOVW`,-`MOVL` + // amd64/v3:`MOVBEQ\s[A-Z]+,\s1\([A-Z]+\)`, -`MOVBEL` b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8] = byte(val>>56), byte(val>>48), byte(val>>40), byte(val>>32), byte(val>>24), byte(val>>16), byte(val>>8), byte(val) } -- GitLab From 417100ec1b08bb1046e207fd08de105944668d27 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Mon, 18 Oct 2021 10:24:00 -0400 Subject: [PATCH 1631/2500] cmd/go: fix broken fuzz test Fixes test breakage caused by CL 355691. Change-Id: I85fcb1491dc39c45342f4cae91fdfda6aedecd1a Reviewed-on: https://go-review.googlesource.com/c/go/+/356530 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- .../go/testdata/script/test_fuzz_minimize.txt | 52 ----------------- .../script/test_fuzz_minimize_interesting.txt | 56 ++++++++++++++++++- 2 files changed, 53 insertions(+), 55 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize.txt b/src/cmd/go/testdata/script/test_fuzz_minimize.txt index 56abc68104..8b11621bbd 100644 --- a/src/cmd/go/testdata/script/test_fuzz_minimize.txt +++ b/src/cmd/go/testdata/script/test_fuzz_minimize.txt @@ -34,21 +34,6 @@ stdout FAIL stdout 'there was an Error' stdout FAIL -# Test that minimization occurs for a crash that appears while minimizing a -# newly found interesting input. There must be only one worker for this test to -# be flaky like we want. -! go test -fuzz=FuzzMinimizerCrashInMinimization -run=FuzzMinimizerCrashInMinimization -fuzztime=10000x -parallel=1 . -! stdout '^ok' -stdout 'got the minimum size!' -stdout 'flaky failure' -stdout FAIL - -# Make sure the crash that was written will fail when run with go test -! go test -run=FuzzMinimizerCrashInMinimization . - -# Clear testdata. -rm testdata - # Test that minimization is working for recoverable errors. ! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x . ! stdout '^ok' @@ -97,25 +82,10 @@ stdout FAIL module example.com/y go 1.16 --- y.go -- -package y - -import ( - "bytes" - "io" -) - -func Y(w io.Writer, b []byte) { - if !bytes.Equal(b, []byte("y")) { - w.Write([]byte("not equal")) - } -} -- y_test.go -- package y import ( - "bytes" - "io" "os" "testing" ) @@ -161,28 +131,6 @@ func FuzzMinimizerNonrecoverable(f *testing.F) { os.Exit(99) }) } - -func FuzzMinimizerCrashInMinimization(f *testing.F) { - seed := make([]byte, 1000) - f.Add(seed) - f.Fuzz(func(t *testing.T, b []byte) { - if len(b) < 50 || len(b) > 1100 { - // Make sure that b is large enough that it can be minimized - return - } - if !bytes.Equal(b, seed) { - // This should have hit a new edge, and the interesting input - // should be attempting minimization - Y(io.Discard, b) - } - if len(b) < 350 { - t.Error("flaky failure") - } - if len(b) == 50 { - t.Log("got the minimum size!") - } - }) -} -- empty/empty.go -- package empty -- check_testdata/check_testdata.go -- diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt b/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt index 5e1d90d8d9..fc66201eb3 100644 --- a/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt +++ b/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt @@ -18,22 +18,72 @@ go test -c -fuzz=. # Build using shared build cache for speed. env GOCACHE=$WORK/gocache -exec ./fuzz.test$GOEXE -test.fuzzcachedir=$GOCACHE/fuzz -test.fuzz=. -test.fuzztime=1000x -go run check_cache.go $GOCACHE/fuzz/FuzzMin +exec ./fuzz.test$GOEXE -test.fuzzcachedir=$GOCACHE/fuzz -test.fuzz=FuzzMinCache -test.fuzztime=1000x +go run check_cache.go $GOCACHE/fuzz/FuzzMinCache + +# Test that minimization occurs for a crash that appears while minimizing a +# newly found interesting input. There must be only one worker for this test to +# be flaky like we want. +go test -c -fuzz=. # Build using shared build cache for speed. +env GOCACHE=$WORK/gocache +! exec ./fuzz.test$GOEXE -test.fuzzcachedir=$GOCACHE/fuzz -test.fuzz=FuzzMinimizerCrashInMinimization -test.fuzztime=10000x -test.parallel=1 +! stdout '^ok' +stdout 'got the minimum size!' +stdout 'flaky failure' +stdout FAIL + +# Make sure the crash that was written will fail when run with go test +! go test -run=FuzzMinimizerCrashInMinimization . -- go.mod -- module fuzz go 1.17 +-- y.go -- +package fuzz + +import ( + "bytes" + "io" +) + +func Y(w io.Writer, b []byte) { + if !bytes.Equal(b, []byte("y")) { + w.Write([]byte("not equal")) + } +} -- fuzz_test.go -- package fuzz import ( "bytes" + "io" "testing" ) -func FuzzMin(f *testing.F) { +func FuzzMinimizerCrashInMinimization(f *testing.F) { + seed := make([]byte, 1000) + f.Add(seed) + f.Fuzz(func(t *testing.T, b []byte) { + if len(b) < 50 || len(b) > 1100 { + // Make sure that b is large enough that it can be minimized + return + } + if !bytes.Equal(b, seed) { + // This should have hit a new edge, and the interesting input + // should be attempting minimization + Y(io.Discard, b) + } + if len(b) < 350 { + t.Error("flaky failure") + } + if len(b) == 50 { + t.Log("got the minimum size!") + } + }) +} + +func FuzzMinCache(f *testing.F) { seed := bytes.Repeat([]byte("a"), 20) f.Add(seed) f.Fuzz(func(t *testing.T, buf []byte) { -- GitLab From 42515418a99f2540427a5d32189f6d44fb06939e Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sat, 18 Sep 2021 10:24:31 +0700 Subject: [PATCH 1632/2500] reflect: correct documentation of Value.UnsafeAddr The doc mentions that "UnsafeAddr returns a _pointer_ to v's data", but it returns a uintptr instead, which don't have pointer semantic. Change-Id: I557d5597cbc485356ca803eb496a99d6db8c63ba Reviewed-on: https://go-review.googlesource.com/c/go/+/350690 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Reviewed-by: Matthew Dempsky --- src/reflect/value.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/reflect/value.go b/src/reflect/value.go index 449f3bbb3c..6bc02c1c8c 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -2473,7 +2473,7 @@ func (v Value) Uint() uint64 { // which ensures cmd/compile can recognize unsafe.Pointer(v.UnsafeAddr()) // and make an exception. -// UnsafeAddr returns a pointer to v's data. +// UnsafeAddr returns a pointer to v's data, as a uintptr. // It is for advanced clients that also import the "unsafe" package. // It panics if v is not addressable. func (v Value) UnsafeAddr() uintptr { -- GitLab From 543a513304c35d42b162790a6e70191aac68225c Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sun, 17 Oct 2021 01:18:20 +0700 Subject: [PATCH 1633/2500] reflect: add test that method values have the same code pointers Updates #40592 Change-Id: I16252dd57aceb5c49ddc11d8c12c601ca87ca902 Reviewed-on: https://go-review.googlesource.com/c/go/+/356252 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/reflect/all_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index 8642d60f8b..0370906f7d 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -2511,6 +2511,11 @@ func TestMethodValue(t *testing.T) { p := Point{3, 4} var i int64 + // Check that method value have the same underlying code pointers. + if p1, p2 := ValueOf(Point{1, 1}).Method(1), ValueOf(Point{2, 2}).Method(1); p1.Pointer() != p2.Pointer() { + t.Errorf("methodValueCall mismatched: %v - %v", p1, p2) + } + // Curried method of value. tfunc := TypeOf((func(int) int)(nil)) v := ValueOf(p).Method(1) -- GitLab From 4d550727f8b85e9f8866f22c8a02b8f56fa64159 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sat, 18 Sep 2021 10:32:22 +0700 Subject: [PATCH 1634/2500] reflect: add Value.UnsafePointer Allowing eliminates a class of possible misuse of unsafe.Pointer, and allow callers to migrate from Value.Addr and Value.Pointer, thus they can be now deprecated. Fixes #40592 Change-Id: I798e507c748922cac5cc1c1971c1b2cc7095a068 Reviewed-on: https://go-review.googlesource.com/c/go/+/350691 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Keith Randall Reviewed-by: Ian Lance Taylor --- src/reflect/all_test.go | 22 +++++----- src/reflect/deepequal.go | 6 +-- src/reflect/set_test.go | 6 +-- src/reflect/type.go | 4 +- src/reflect/value.go | 94 ++++++++++++++++++++++++---------------- 5 files changed, 75 insertions(+), 57 deletions(-) diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index 0370906f7d..141cc8f73d 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -3223,11 +3223,11 @@ func (*outer) M() {} func TestNestedMethods(t *testing.T) { typ := TypeOf((*outer)(nil)) - if typ.NumMethod() != 1 || typ.Method(0).Func.Pointer() != ValueOf((*outer).M).Pointer() { + if typ.NumMethod() != 1 || typ.Method(0).Func.UnsafePointer() != ValueOf((*outer).M).UnsafePointer() { t.Errorf("Wrong method table for outer: (M=%p)", (*outer).M) for i := 0; i < typ.NumMethod(); i++ { m := typ.Method(i) - t.Errorf("\t%d: %s %#x\n", i, m.Name, m.Func.Pointer()) + t.Errorf("\t%d: %s %p\n", i, m.Name, m.Func.UnsafePointer()) } } } @@ -3266,11 +3266,11 @@ func (i *InnerInt) M() int { func TestEmbeddedMethods(t *testing.T) { typ := TypeOf((*OuterInt)(nil)) - if typ.NumMethod() != 1 || typ.Method(0).Func.Pointer() != ValueOf((*OuterInt).M).Pointer() { + if typ.NumMethod() != 1 || typ.Method(0).Func.UnsafePointer() != ValueOf((*OuterInt).M).UnsafePointer() { t.Errorf("Wrong method table for OuterInt: (m=%p)", (*OuterInt).M) for i := 0; i < typ.NumMethod(); i++ { m := typ.Method(i) - t.Errorf("\t%d: %s %#x\n", i, m.Name, m.Func.Pointer()) + t.Errorf("\t%d: %s %p\n", i, m.Name, m.Func.UnsafePointer()) } } @@ -3528,11 +3528,11 @@ func TestSlice(t *testing.T) { rv := ValueOf(&xs).Elem() rv = rv.Slice(3, 4) - ptr2 := rv.Pointer() + ptr2 := rv.UnsafePointer() rv = rv.Slice(5, 5) - ptr3 := rv.Pointer() + ptr3 := rv.UnsafePointer() if ptr3 != ptr2 { - t.Errorf("xs.Slice(3,4).Slice3(5,5).Pointer() = %#x, want %#x", ptr3, ptr2) + t.Errorf("xs.Slice(3,4).Slice3(5,5).UnsafePointer() = %p, want %p", ptr3, ptr2) } } @@ -3575,11 +3575,11 @@ func TestSlice3(t *testing.T) { rv = ValueOf(&xs).Elem() rv = rv.Slice3(3, 5, 7) - ptr2 := rv.Pointer() + ptr2 := rv.UnsafePointer() rv = rv.Slice3(4, 4, 4) - ptr3 := rv.Pointer() + ptr3 := rv.UnsafePointer() if ptr3 != ptr2 { - t.Errorf("xs.Slice3(3,5,7).Slice3(4,4,4).Pointer() = %#x, want %#x", ptr3, ptr2) + t.Errorf("xs.Slice3(3,5,7).Slice3(4,4,4).UnsafePointer() = %p, want %p", ptr3, ptr2) } } @@ -6818,7 +6818,7 @@ func verifyGCBitsSlice(t *testing.T, typ Type, cap int, bits []byte) { // repeat a bitmap for a small array or executing a repeat in // a GC program. val := MakeSlice(typ, 0, cap) - data := NewAt(ArrayOf(cap, typ), unsafe.Pointer(val.Pointer())) + data := NewAt(ArrayOf(cap, typ), val.UnsafePointer()) heapBits := GCBits(data.Interface()) // Repeat the bitmap for the slice size, trimming scalars in // the last element. diff --git a/src/reflect/deepequal.go b/src/reflect/deepequal.go index 94174dec04..7f1ecb2809 100644 --- a/src/reflect/deepequal.go +++ b/src/reflect/deepequal.go @@ -102,7 +102,7 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool) bool { if v1.Len() != v2.Len() { return false } - if v1.Pointer() == v2.Pointer() { + if v1.UnsafePointer() == v2.UnsafePointer() { return true } // Special case for []byte, which is common. @@ -121,7 +121,7 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool) bool { } return deepValueEqual(v1.Elem(), v2.Elem(), visited) case Ptr: - if v1.Pointer() == v2.Pointer() { + if v1.UnsafePointer() == v2.UnsafePointer() { return true } return deepValueEqual(v1.Elem(), v2.Elem(), visited) @@ -139,7 +139,7 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool) bool { if v1.Len() != v2.Len() { return false } - if v1.Pointer() == v2.Pointer() { + if v1.UnsafePointer() == v2.UnsafePointer() { return true } for _, k := range v1.MapKeys() { diff --git a/src/reflect/set_test.go b/src/reflect/set_test.go index a633e6eee2..566dc7fb65 100644 --- a/src/reflect/set_test.go +++ b/src/reflect/set_test.go @@ -79,7 +79,7 @@ func TestImplicitMapConversion(t *testing.T) { if x != b2 { t.Errorf("#5 after SetMapIndex(b1, b2): %p (!= %p), %t (map=%v)", x, b2, ok, m) } - if p := mv.MapIndex(ValueOf(b1)).Elem().Pointer(); p != uintptr(unsafe.Pointer(b2)) { + if p := mv.MapIndex(ValueOf(b1)).Elem().UnsafePointer(); p != unsafe.Pointer(b2) { t.Errorf("#5 MapIndex(b1) = %#x want %p", p, b2) } } @@ -94,7 +94,7 @@ func TestImplicitMapConversion(t *testing.T) { if x != c2 { t.Errorf("#6 after SetMapIndex(c1, c2): %p (!= %p), %t (map=%v)", x, c2, ok, m) } - if p := mv.MapIndex(ValueOf(c1)).Pointer(); p != ValueOf(c2).Pointer() { + if p := mv.MapIndex(ValueOf(c1)).UnsafePointer(); p != ValueOf(c2).UnsafePointer() { t.Errorf("#6 MapIndex(c1) = %#x want %p", p, c2) } } @@ -110,7 +110,7 @@ func TestImplicitMapConversion(t *testing.T) { if x != b2 { t.Errorf("#7 after SetMapIndex(b1, b2): %p (!= %p), %t (map=%v)", x, b2, ok, m) } - if p := mv.MapIndex(ValueOf(b1)).Pointer(); p != uintptr(unsafe.Pointer(b2)) { + if p := mv.MapIndex(ValueOf(b1)).UnsafePointer(); p != unsafe.Pointer(b2) { t.Errorf("#7 MapIndex(b1) = %#x want %p", p, b2) } } diff --git a/src/reflect/type.go b/src/reflect/type.go index afb802e641..96f589ca9c 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -2666,8 +2666,8 @@ func StructOf(fields []StructField) Type { {Name: "M", Type: ArrayOf(len(methods), TypeOf(methods[0]))}, })) - typ = (*structType)(unsafe.Pointer(tt.Elem().Field(0).UnsafeAddr())) - ut = (*uncommonType)(unsafe.Pointer(tt.Elem().Field(1).UnsafeAddr())) + typ = (*structType)(tt.Elem().Field(0).Addr().UnsafePointer()) + ut = (*uncommonType)(tt.Elem().Field(1).Addr().UnsafePointer()) copy(tt.Elem().Field(2).Slice(0, len(methods)).Interface().([]method), methods) } diff --git a/src/reflect/value.go b/src/reflect/value.go index 6bc02c1c8c..a272714ac9 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -1933,44 +1933,10 @@ func (v Value) OverflowUint(x uint64) bool { // If v's Kind is Slice, the returned pointer is to the first // element of the slice. If the slice is nil the returned value // is 0. If the slice is empty but non-nil the return value is non-zero. +// +// Deprecated: use uintptr(Value.UnsafePointer()) to get the equivalent result. func (v Value) Pointer() uintptr { - // TODO: deprecate - k := v.kind() - switch k { - case Ptr: - if v.typ.ptrdata == 0 { - // Handle pointers to go:notinheap types directly, - // so we never materialize such pointers as an - // unsafe.Pointer. (Such pointers are always indirect.) - // See issue 42076. - return *(*uintptr)(v.ptr) - } - fallthrough - case Chan, Map, UnsafePointer: - return uintptr(v.pointer()) - case Func: - if v.flag&flagMethod != 0 { - // As the doc comment says, the returned pointer is an - // underlying code pointer but not necessarily enough to - // identify a single function uniquely. All method expressions - // created via reflect have the same underlying code pointer, - // so their Pointers are equal. The function used here must - // match the one used in makeMethodValue. - f := methodValueCall - return **(**uintptr)(unsafe.Pointer(&f)) - } - p := v.pointer() - // Non-nil func value points at data block. - // First word of data block is actual code. - if p != nil { - p = *(*unsafe.Pointer)(p) - } - return uintptr(p) - - case Slice: - return (*SliceHeader)(v.ptr).Data - } - panic(&ValueError{"reflect.Value.Pointer", v.kind()}) + return uintptr(v.UnsafePointer()) } // Recv receives and returns a value from the channel v. @@ -2476,8 +2442,9 @@ func (v Value) Uint() uint64 { // UnsafeAddr returns a pointer to v's data, as a uintptr. // It is for advanced clients that also import the "unsafe" package. // It panics if v is not addressable. +// +// Deprecated: use uintptr(Value.Addr().UnsafePointer()) to get the equivalent result. func (v Value) UnsafeAddr() uintptr { - // TODO: deprecate if v.typ == nil { panic(&ValueError{"reflect.Value.UnsafeAddr", Invalid}) } @@ -2487,6 +2454,57 @@ func (v Value) UnsafeAddr() uintptr { return uintptr(v.ptr) } +// UnsafePointer returns v's value as a unsafe.Pointer. +// It panics if v's Kind is not Chan, Func, Map, Ptr, Slice, or UnsafePointer. +// +// If v's Kind is Func, the returned pointer is an underlying +// code pointer, but not necessarily enough to identify a +// single function uniquely. The only guarantee is that the +// result is zero if and only if v is a nil func Value. +// +// If v's Kind is Slice, the returned pointer is to the first +// element of the slice. If the slice is nil the returned value +// is nil. If the slice is empty but non-nil the return value is non-nil. +func (v Value) UnsafePointer() unsafe.Pointer { + k := v.kind() + switch k { + case Ptr: + if v.typ.ptrdata == 0 { + // Since it is a not-in-heap pointer, all pointers to the heap are + // forbidden! See comment in Value.Elem and issue #48399. + if !verifyNotInHeapPtr(*(*uintptr)(v.ptr)) { + panic("reflect: reflect.Value.UnsafePointer on an invalid notinheap pointer") + } + return *(*unsafe.Pointer)(v.ptr) + } + fallthrough + case Chan, Map, UnsafePointer: + return v.pointer() + case Func: + if v.flag&flagMethod != 0 { + // As the doc comment says, the returned pointer is an + // underlying code pointer but not necessarily enough to + // identify a single function uniquely. All method expressions + // created via reflect have the same underlying code pointer, + // so their Pointers are equal. The function used here must + // match the one used in makeMethodValue. + f := methodValueCall + return **(**unsafe.Pointer)(unsafe.Pointer(&f)) + } + p := v.pointer() + // Non-nil func value points at data block. + // First word of data block is actual code. + if p != nil { + p = *(*unsafe.Pointer)(p) + } + return p + + case Slice: + return (*unsafeheader.Slice)(v.ptr).Data + } + panic(&ValueError{"reflect.Value.UnsafePointer", v.kind()}) +} + // StringHeader is the runtime representation of a string. // It cannot be used safely or portably and its representation may // change in a later release. -- GitLab From 394a1ad2956f0397e83b5f0234ea7e972a307848 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Mon, 18 Oct 2021 10:26:18 -0700 Subject: [PATCH 1635/2500] cmd/compile: allow importing and exporting of ODYANMICDOTTYPE[2] Fixes #49027 Change-Id: I4520b5c754027bfffbc5cd92c9c27002b248c99a Reviewed-on: https://go-review.googlesource.com/c/go/+/356569 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall Reviewed-by: Dan Scales --- src/cmd/compile/internal/typecheck/iexport.go | 8 ++++++ src/cmd/compile/internal/typecheck/iimport.go | 5 ++++ test/typeparam/issue49027.dir/a.go | 21 ++++++++++++++++ test/typeparam/issue49027.dir/main.go | 25 +++++++++++++++++++ test/typeparam/issue49027.go | 7 ++++++ 5 files changed, 66 insertions(+) create mode 100644 test/typeparam/issue49027.dir/a.go create mode 100644 test/typeparam/issue49027.dir/main.go create mode 100644 test/typeparam/issue49027.go diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 3c0b8bc319..e3dd10a56b 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -1888,6 +1888,14 @@ func (w *exportWriter) expr(n ir.Node) { w.expr(n.X) w.typ(n.Type()) + case ir.ODYNAMICDOTTYPE, ir.ODYNAMICDOTTYPE2: + n := n.(*ir.DynamicTypeAssertExpr) + w.op(n.Op()) + w.pos(n.Pos()) + w.expr(n.X) + w.expr(n.T) + w.typ(n.Type()) + case ir.OINDEX, ir.OINDEXMAP: n := n.(*ir.IndexExpr) if go117ExportTypes { diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index df49d74a40..52236ce837 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1457,6 +1457,11 @@ func (r *importReader) node() ir.Node { } return n + case ir.ODYNAMICDOTTYPE, ir.ODYNAMICDOTTYPE2: + n := ir.NewDynamicTypeAssertExpr(r.pos(), op, r.expr(), r.expr()) + n.SetType(r.typ()) + return n + case ir.OINDEX, ir.OINDEXMAP: n := ir.NewIndexExpr(r.pos(), r.expr(), r.expr()) if go117ExportTypes { diff --git a/test/typeparam/issue49027.dir/a.go b/test/typeparam/issue49027.dir/a.go new file mode 100644 index 0000000000..d3ec27deab --- /dev/null +++ b/test/typeparam/issue49027.dir/a.go @@ -0,0 +1,21 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +func Conv(v interface{}) string { + return conv[string](v) +} + +func conv[T any](v interface{}) T { + return v.(T) +} + +func Conv2(v interface{}) (string, bool) { + return conv2[string](v) +} +func conv2[T any](v interface{}) (T, bool) { + x, ok := v.(T) + return x, ok +} diff --git a/test/typeparam/issue49027.dir/main.go b/test/typeparam/issue49027.dir/main.go new file mode 100644 index 0000000000..d0dc33d734 --- /dev/null +++ b/test/typeparam/issue49027.dir/main.go @@ -0,0 +1,25 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "a" + "fmt" +) + +func main() { + s := "foo" + x := a.Conv(s) + if x != s { + panic(fmt.Sprintf("got %s wanted %s", x, s)) + } + y, ok := a.Conv2(s) + if !ok { + panic("conversion failed") + } + if y != s { + panic(fmt.Sprintf("got %s wanted %s", y, s)) + } +} diff --git a/test/typeparam/issue49027.go b/test/typeparam/issue49027.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/issue49027.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From 267abbe3ba9dda96a8694e8aad8892e3ba2be60e Mon Sep 17 00:00:00 2001 From: Gusted Date: Mon, 18 Oct 2021 17:38:22 +0000 Subject: [PATCH 1636/2500] html/template: remove unused `mode` field on `Tree` struct This changes Go, to remove this unused field on the `Tree` struct. Which seems to replaced by the non-private field `Mode`. Change-Id: I5b384424cf60aa0af36eb8aad1d8db3f99b9838e GitHub-Last-Rev: 4b033f967b55ff99df8a969ac1c91c358b82b726 GitHub-Pull-Request: golang/go#48028 Reviewed-on: https://go-review.googlesource.com/c/go/+/345789 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Rob Pike --- src/text/template/parse/parse.go | 1 - 1 file changed, 1 deletion(-) diff --git a/src/text/template/parse/parse.go b/src/text/template/parse/parse.go index d92bed5d3d..64b29a2e16 100644 --- a/src/text/template/parse/parse.go +++ b/src/text/template/parse/parse.go @@ -32,7 +32,6 @@ type Tree struct { treeSet map[string]*Tree actionLine int // line of left delim starting action rangeDepth int - mode Mode } // A mode value is a set of flags (or 0). Modes control parser behavior. -- GitLab From 6c0daa733192031eab23d09ed6515c4cd959aa92 Mon Sep 17 00:00:00 2001 From: Richard Musiol Date: Sat, 16 Oct 2021 17:17:21 +0200 Subject: [PATCH 1637/2500] syscall/js: remove Wrapper interface This change removes the js.Wrapper interface for performance reasons. See proposal #44006 for details. This is a breaking change, but syscall/js is exempt from Go's compatibility promise. Fixes #44006 Change-Id: I968cd14b1e61cc72ea9f84240b6bd29e8b8ae673 Reviewed-on: https://go-review.googlesource.com/c/go/+/356430 Trust: Richard Musiol Reviewed-by: Cherry Mui Reviewed-by: Emmanuel Odeke --- src/syscall/js/func.go | 2 -- src/syscall/js/js.go | 17 +++-------------- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/src/syscall/js/func.go b/src/syscall/js/func.go index ab23e5fbfc..dde1e68100 100644 --- a/src/syscall/js/func.go +++ b/src/syscall/js/func.go @@ -15,8 +15,6 @@ var ( nextFuncID uint32 = 1 ) -var _ Wrapper = Func{} // Func must implement Wrapper - // Func is a wrapped Go function to be called by JavaScript. type Func struct { Value // the JavaScript function that invokes the Go function diff --git a/src/syscall/js/js.go b/src/syscall/js/js.go index d805d69166..0da0ddfa0f 100644 --- a/src/syscall/js/js.go +++ b/src/syscall/js/js.go @@ -28,12 +28,6 @@ type ref uint64 // nanHead are the upper 32 bits of a ref which are set if the value is not encoded as an IEEE 754 number (see above). const nanHead = 0x7FF80000 -// Wrapper is implemented by types that are backed by a JavaScript value. -type Wrapper interface { - // JSValue returns a JavaScript value associated with an object. - JSValue() Value -} - // Value represents a JavaScript value. The zero value is the JavaScript value "undefined". // Values can be checked for equality with the Equal method. type Value struct { @@ -51,11 +45,6 @@ const ( typeFlagFunction ) -// JSValue implements Wrapper interface. -func (v Value) JSValue() Value { - return v -} - func makeValue(r ref) Value { var gcPtr *ref typeFlag := (r >> 32) & 7 @@ -162,10 +151,10 @@ func Global() Value { // Panics if x is not one of the expected types. func ValueOf(x interface{}) Value { switch x := x.(type) { - case Value: // should precede Wrapper to avoid a loop + case Value: return x - case Wrapper: - return x.JSValue() + case Func: + return x.Value case nil: return valueNull case bool: -- GitLab From 33b3260c1e765ef66500ce155c6d5a526d8852e9 Mon Sep 17 00:00:00 2001 From: Lynn Boger Date: Thu, 14 Oct 2021 10:48:08 -0500 Subject: [PATCH 1638/2500] cmd/compile/internal/ssagen: set BitLen32 as intrinsic on PPC64 It was noticed through some other investigation that BitLen32 was not generating the best code and found that it wasn't recognized as an intrinsic. This corrects that and enables the test for PPC64. Change-Id: Iab496a8830c8552f507b7292649b1b660f3848b5 Reviewed-on: https://go-review.googlesource.com/c/go/+/355872 Run-TryBot: Lynn Boger TryBot-Result: Go Bot Trust: Lynn Boger Reviewed-by: Cherry Mui --- src/cmd/compile/internal/ssagen/ssa.go | 4 ++-- test/codegen/mathbits.go | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 08114b7828..5a958a569d 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -4421,7 +4421,7 @@ func InitTables() { func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return s.newValue1(ssa.OpBitLen32, types.Types[types.TINT], args[0]) }, - sys.AMD64, sys.ARM64) + sys.AMD64, sys.ARM64, sys.PPC64) addF("math/bits", "Len32", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { if s.config.PtrSize == 4 { @@ -4430,7 +4430,7 @@ func InitTables() { x := s.newValue1(ssa.OpZeroExt32to64, types.Types[types.TUINT64], args[0]) return s.newValue1(ssa.OpBitLen64, types.Types[types.TINT], x) }, - sys.ARM, sys.S390X, sys.MIPS, sys.PPC64, sys.Wasm) + sys.ARM, sys.S390X, sys.MIPS, sys.Wasm) addF("math/bits", "Len16", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { if s.config.PtrSize == 4 { diff --git a/test/codegen/mathbits.go b/test/codegen/mathbits.go index 2d8790c1de..859490c363 100644 --- a/test/codegen/mathbits.go +++ b/test/codegen/mathbits.go @@ -93,6 +93,8 @@ func Len32(n uint32) int { // arm:"CLZ" arm64:"CLZ" // mips:"CLZ" // wasm:"I64Clz" + // ppc64: "CNTLZW" + // ppc64le: "CNTLZW" return bits.Len32(n) } -- GitLab From 425db64811285fd0b35ed12eaed7568ec547da78 Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Fri, 6 Aug 2021 13:23:13 -0700 Subject: [PATCH 1639/2500] bufio: use underlying ReadFrom even when data is buffered When (*bufio.Writer).ReadFrom is called with a partially filled buffer, fill out and flush the buffer and then call the underlying writer's ReadFrom method if present. Fixes #44815. Change-Id: I15b3ef0746d0d60fd62041189a9b9df11254dd29 Reviewed-on: https://go-review.googlesource.com/c/go/+/340530 Trust: Damien Neil Run-TryBot: Damien Neil TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/bufio/bufio.go | 19 ++++++++-------- src/bufio/bufio_test.go | 48 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/src/bufio/bufio.go b/src/bufio/bufio.go index a58df25494..063a7785f3 100644 --- a/src/bufio/bufio.go +++ b/src/bufio/bufio.go @@ -745,19 +745,14 @@ func (b *Writer) WriteString(s string) (int, error) { } // ReadFrom implements io.ReaderFrom. If the underlying writer -// supports the ReadFrom method, and b has no buffered data yet, -// this calls the underlying ReadFrom without buffering. +// supports the ReadFrom method, this calls the underlying ReadFrom. +// If there is buffered data and an underlying ReadFrom, this fills +// the buffer and writes it before calling ReadFrom. func (b *Writer) ReadFrom(r io.Reader) (n int64, err error) { if b.err != nil { return 0, b.err } - if b.Buffered() == 0 { - if w, ok := b.wr.(io.ReaderFrom); ok { - n, err = w.ReadFrom(r) - b.err = err - return n, err - } - } + readerFrom, readerFromOK := b.wr.(io.ReaderFrom) var m int for { if b.Available() == 0 { @@ -765,6 +760,12 @@ func (b *Writer) ReadFrom(r io.Reader) (n int64, err error) { return n, err1 } } + if readerFromOK && b.Buffered() == 0 { + nn, err := readerFrom.ReadFrom(r) + b.err = err + n += nn + return n, err + } nr := 0 for nr < maxConsecutiveEmptyReads { m, err = r.Read(b.buf[b.n:]) diff --git a/src/bufio/bufio_test.go b/src/bufio/bufio_test.go index 8e8a8a1778..66b3e70053 100644 --- a/src/bufio/bufio_test.go +++ b/src/bufio/bufio_test.go @@ -1351,6 +1351,54 @@ func TestWriterReadFromErrNoProgress(t *testing.T) { } } +type readFromWriter struct { + buf []byte + writeBytes int + readFromBytes int +} + +func (w *readFromWriter) Write(p []byte) (int, error) { + w.buf = append(w.buf, p...) + w.writeBytes += len(p) + return len(p), nil +} + +func (w *readFromWriter) ReadFrom(r io.Reader) (int64, error) { + b, err := io.ReadAll(r) + w.buf = append(w.buf, b...) + w.readFromBytes += len(b) + return int64(len(b)), err +} + +// Test that calling (*Writer).ReadFrom with a partially-filled buffer +// fills the buffer before switching over to ReadFrom. +func TestWriterReadFromWithBufferedData(t *testing.T) { + const bufsize = 16 + + input := createTestInput(64) + rfw := &readFromWriter{} + w := NewWriterSize(rfw, bufsize) + + const writeSize = 8 + if n, err := w.Write(input[:writeSize]); n != writeSize || err != nil { + t.Errorf("w.Write(%v bytes) = %v, %v; want %v, nil", writeSize, n, err, writeSize) + } + n, err := w.ReadFrom(bytes.NewReader(input[writeSize:])) + if wantn := len(input[writeSize:]); int(n) != wantn || err != nil { + t.Errorf("io.Copy(w, %v bytes) = %v, %v; want %v, nil", wantn, n, err, wantn) + } + if err := w.Flush(); err != nil { + t.Errorf("w.Flush() = %v, want nil", err) + } + + if got, want := rfw.writeBytes, bufsize; got != want { + t.Errorf("wrote %v bytes with Write, want %v", got, want) + } + if got, want := rfw.readFromBytes, len(input)-bufsize; got != want { + t.Errorf("wrote %v bytes with ReadFrom, want %v", got, want) + } +} + func TestReadZero(t *testing.T) { for _, size := range []int{100, 2} { t.Run(fmt.Sprintf("bufsize=%d", size), func(t *testing.T) { -- GitLab From 3befaf0cdb18420f45acfa7cee725297aa550faf Mon Sep 17 00:00:00 2001 From: jiahua wang Date: Sat, 16 Oct 2021 23:19:57 +0800 Subject: [PATCH 1640/2500] net/url: fix stale RFC 3986 links The URLs for RFC 3986 have been changed from: http://tools.ietf.org/html/rfc3986 to: https://datatracker.ietf.org/doc/html/rfc3986 Change-Id: I0662557d91bbb7de51d7ca4bc64e838741cd9074 Reviewed-on: https://go-review.googlesource.com/c/go/+/356429 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Emmanuel Odeke Trust: Cherry Mui --- src/net/url/url_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/net/url/url_test.go b/src/net/url/url_test.go index 5059d34bf1..6807d58f1a 100644 --- a/src/net/url/url_test.go +++ b/src/net/url/url_test.go @@ -1172,7 +1172,7 @@ var resolveReferenceTests = []struct { {"http://foo.com/bar/baz", "quux/./dotdot/../dotdot/../dot/./tail/..", "http://foo.com/bar/quux/dot/"}, // Remove any dot-segments prior to forming the target URI. - // http://tools.ietf.org/html/rfc3986#section-5.2.4 + // https://datatracker.ietf.org/doc/html/rfc3986#section-5.2.4 {"http://foo.com/dot/./dotdot/../foo/bar", "../baz", "http://foo.com/dot/baz"}, // Triple dot isn't special @@ -1192,7 +1192,7 @@ var resolveReferenceTests = []struct { {"http://foo.com/foo%2dbar/", "./baz-quux", "http://foo.com/foo%2dbar/baz-quux"}, // RFC 3986: Normal Examples - // http://tools.ietf.org/html/rfc3986#section-5.4.1 + // https://datatracker.ietf.org/doc/html/rfc3986#section-5.4.1 {"http://a/b/c/d;p?q", "g:h", "g:h"}, {"http://a/b/c/d;p?q", "g", "http://a/b/c/g"}, {"http://a/b/c/d;p?q", "./g", "http://a/b/c/g"}, @@ -1218,7 +1218,7 @@ var resolveReferenceTests = []struct { {"http://a/b/c/d;p?q", "../../g", "http://a/g"}, // RFC 3986: Abnormal Examples - // http://tools.ietf.org/html/rfc3986#section-5.4.2 + // https://datatracker.ietf.org/doc/html/rfc3986#section-5.4.2 {"http://a/b/c/d;p?q", "../../../g", "http://a/g"}, {"http://a/b/c/d;p?q", "../../../../g", "http://a/g"}, {"http://a/b/c/d;p?q", "/./g", "http://a/g"}, -- GitLab From 73971784dc586a5db3b81dfdd41954f650d493ac Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Fri, 15 Oct 2021 10:52:55 -0400 Subject: [PATCH 1641/2500] go/types: add support for inferring type instances Add constraint type inference for type instances, to be consistent with inference of function values. Fixes #47990 Change-Id: Ib99b5215cb2da5c10badc4de7e9e60ca0e48489f Reviewed-on: https://go-review.googlesource.com/c/go/+/356489 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/call.go | 32 +++++++- src/go/types/instantiate.go | 50 ------------ src/go/types/named.go | 3 +- .../{tinference.go2 => funcinference.go2} | 30 +++---- src/go/types/testdata/check/typeinference.go2 | 47 +++++++++++ src/go/types/testdata/check/typeinst2.go2 | 4 + .../types/testdata/check/typeinstcycles.go2 | 11 +++ src/go/types/typexpr.go | 79 ++++++++++++++++--- 8 files changed, 175 insertions(+), 81 deletions(-) rename src/go/types/testdata/check/{tinference.go2 => funcinference.go2} (77%) create mode 100644 src/go/types/testdata/check/typeinference.go2 create mode 100644 src/go/types/testdata/check/typeinstcycles.go2 diff --git a/src/go/types/call.go b/src/go/types/call.go index a642f6f295..4731c69619 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -60,7 +60,7 @@ func (check *Checker) funcInst(x *operand, ix *typeparams.IndexExpr) { } // instantiate function signature - res := check.instantiate(x.Pos(), sig, targs, poslist).(*Signature) + res := check.instantiateSignature(x.Pos(), sig, targs, poslist) assert(res.TypeParams().Len() == 0) // signature is not generic anymore check.recordInstance(ix.Orig, targs, res) x.typ = res @@ -68,6 +68,34 @@ func (check *Checker) funcInst(x *operand, ix *typeparams.IndexExpr) { x.expr = ix.Orig } +func (check *Checker) instantiateSignature(pos token.Pos, typ *Signature, targs []Type, posList []token.Pos) (res *Signature) { + assert(check != nil) + assert(len(targs) == typ.TypeParams().Len()) + + if trace { + check.trace(pos, "-- instantiating %s with %s", typ, targs) + check.indent++ + defer func() { + check.indent-- + check.trace(pos, "=> %s (under = %s)", res, res.Underlying()) + }() + } + + inst := check.instance(pos, typ, targs, check.conf.Context).(*Signature) + assert(len(posList) <= len(targs)) + tparams := typ.TypeParams().list() + if i, err := check.verify(pos, tparams, targs); err != nil { + // best position for error reporting + pos := pos + if i < len(posList) { + pos = posList[i] + } + check.softErrorf(atPos(pos), _Todo, err.Error()) + } + + return inst +} + func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { ix := typeparams.UnpackIndexExpr(call.Fun) if ix != nil { @@ -352,7 +380,7 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type } // compute result signature - rsig = check.instantiate(call.Pos(), sig, targs, nil).(*Signature) + rsig = check.instantiateSignature(call.Pos(), sig, targs, nil) assert(rsig.TypeParams().Len() == 0) // signature is not generic anymore check.recordInstance(call.Fun, targs, rsig) diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 2a255bcb87..65c935a192 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -49,56 +49,6 @@ func Instantiate(ctxt *Context, typ Type, targs []Type, validate bool) (Type, er return inst, err } -// instantiate creates an instance and defers verification of constraints to -// later in the type checking pass. For Named types the resulting instance will -// be unexpanded. -func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, posList []token.Pos) (res Type) { - assert(check != nil) - if trace { - check.trace(pos, "-- instantiating %s with %s", typ, NewTypeList(targs)) - check.indent++ - defer func() { - check.indent-- - var under Type - if res != nil { - // Calling under() here may lead to endless instantiations. - // Test case: type T[P any] T[P] - // TODO(gri) investigate if that's a bug or to be expected. - under = safeUnderlying(res) - } - check.trace(pos, "=> %s (under = %s)", res, under) - }() - } - - inst := check.instance(pos, typ, targs, check.conf.Context) - - assert(len(posList) <= len(targs)) - check.later(func() { - // Collect tparams again because lazily loaded *Named types may not have - // had tparams set up above. - var tparams []*TypeParam - switch t := typ.(type) { - case *Named: - tparams = t.TypeParams().list() - case *Signature: - tparams = t.TypeParams().list() - } - // Avoid duplicate errors; instantiate will have complained if tparams - // and targs do not have the same length. - if len(tparams) == len(targs) { - if i, err := check.verify(pos, tparams, targs); err != nil { - // best position for error reporting - pos := pos - if i < len(posList) { - pos = posList[i] - } - check.softErrorf(atPos(pos), _Todo, err.Error()) - } - } - }) - return inst -} - // instance creates a type or function instance using the given original type // typ and arguments targs. For Named types the resulting instance will be // unexpanded. diff --git a/src/go/types/named.go b/src/go/types/named.go index 82b2afcb63..595863a01b 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -241,7 +241,8 @@ func expandNamed(ctxt *Context, n *Named, instPos token.Pos) (tparams *TypeParam check := n.check - if check.validateTArgLen(instPos, n.orig.tparams.Len(), n.targs.Len()) { + // Mismatching arg and tparam length may be checked elsewhere. + if n.orig.tparams.Len() == n.targs.Len() { // We must always have a context, to avoid infinite recursion. ctxt = check.bestContext(ctxt) h := ctxt.typeHash(n.orig, n.targs.list()) diff --git a/src/go/types/testdata/check/tinference.go2 b/src/go/types/testdata/check/funcinference.go2 similarity index 77% rename from src/go/types/testdata/check/tinference.go2 rename to src/go/types/testdata/check/funcinference.go2 index 28516ef639..f04b76ca1a 100644 --- a/src/go/types/testdata/check/tinference.go2 +++ b/src/go/types/testdata/check/funcinference.go2 @@ -2,29 +2,25 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package tinferenceB +package funcInference import "strconv" type any interface{} -// TODO(rFindley) the below partially applied function types should probably -// not be permitted (spec question). +func f0[A any, B interface{~*C}, C interface{~*D}, D interface{~*A}](A, B, C, D) {} +func _() { + f := f0[string] + f("a", nil, nil, nil) + f0("a", nil, nil, nil) +} -// Embedding stand-alone type parameters is not permitted for now. Disabled. -// func f0[A any, B interface{~C}, C interface{~D}, D interface{~A}](A, B, C, D) -// func _() { -// f := f0[string] -// f("a", "b", "c", "d") -// f0("a", "b", "c", "d") -// } -// -// func f1[A any, B interface{~A}](A, B) -// func _() { -// f := f1[int] -// f(int(0), int(0)) -// f1(int(0), int(0)) -// } +func f1[A any, B interface{~*A}](A, B) {} +func _() { + f := f1[int] + f(int(0), new(int)) + f1(int(0), new(int)) +} func f2[A any, B interface{~[]A}](A, B) {} func _() { diff --git a/src/go/types/testdata/check/typeinference.go2 b/src/go/types/testdata/check/typeinference.go2 new file mode 100644 index 0000000000..8876ccaa4e --- /dev/null +++ b/src/go/types/testdata/check/typeinference.go2 @@ -0,0 +1,47 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package typeInference + +// basic inference +type Tb[P ~*Q, Q any] int +func _() { + var x Tb[*int] + var y Tb[*int, int] + x = y + _ = x +} + +// recursive inference +type Tr[A any, B ~*C, C ~*D, D ~*A] int +func _() { + var x Tr[string] + var y Tr[string, ***string, **string, *string] + var z Tr[int, ***int, **int, *int] + x = y + x = z // ERROR cannot use z .* as Tr + _ = x +} + +// other patterns of inference +type To0[A any, B ~[]A] int +type To1[A any, B ~struct{a A}] int +type To2[A any, B ~[][]A] int +type To3[A any, B ~[3]*A] int +type To4[A any, B any, C ~struct{a A; b B}] int +func _() { + var _ To0[int] + var _ To1[int] + var _ To2[int] + var _ To3[int] + var _ To4[int, string] +} + +// failed inference +type Tf0[A, B any] int +type Tf1[A any, B ~struct{a A; c C}, C any] int +func _() { + var _ Tf0 /* ERROR cannot infer B */ /* ERROR got 1 arguments but 2 type parameters */ [int] + var _ Tf1 /* ERROR cannot infer B */ /* ERROR got 1 arguments but 3 type parameters */ [int] +} diff --git a/src/go/types/testdata/check/typeinst2.go2 b/src/go/types/testdata/check/typeinst2.go2 index 95c249d529..88913785c8 100644 --- a/src/go/types/testdata/check/typeinst2.go2 +++ b/src/go/types/testdata/check/typeinst2.go2 @@ -255,3 +255,7 @@ var _ = f0_[int] var _ = f0_[bool /* ERROR does not satisfy I0_ */ ] var _ = f0_[string /* ERROR does not satisfy I0_ */ ] var _ = f0_[float64 /* ERROR does not satisfy I0_ */ ] + +// Using a function instance as a type is an error. +var _ f0 // ERROR not a type +var _ f0 /* ERROR not a type */ [int] diff --git a/src/go/types/testdata/check/typeinstcycles.go2 b/src/go/types/testdata/check/typeinstcycles.go2 new file mode 100644 index 0000000000..74fe19195a --- /dev/null +++ b/src/go/types/testdata/check/typeinstcycles.go2 @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +import "unsafe" + +func F1[T any](_ [unsafe.Sizeof(F1[int])]T) (res T) { return } +func F2[T any](_ T) (res [unsafe.Sizeof(F2[string])]int) { return } +func F3[T any](_ [unsafe.Sizeof(F1[string])]int) {} diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 71623c336e..e812c3d5d5 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -265,7 +265,6 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) { if !check.allowVersion(check.pkg, 1, 18) { check.softErrorf(inNode(e, ix.Lbrack), _Todo, "type instantiation requires go1.18 or later") } - // TODO(rfindley): type instantiation should require go1.18 return check.instantiatedType(ix.X, ix.Indices, def) case *ast.ParenExpr: @@ -375,13 +374,24 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) { return typ } -func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named) Type { +func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named) (res Type) { + if trace { + check.trace(x.Pos(), "-- instantiating %s with %s", x, targsx) + check.indent++ + defer func() { + check.indent-- + // Don't format the underlying here. It will always be nil. + check.trace(x.Pos(), "=> %s", res) + }() + } + gtyp := check.genericType(x, true) if gtyp == Typ[Invalid] { return gtyp // error already reported } - base, _ := gtyp.(*Named) - if base == nil { + + origin, _ := gtyp.(*Named) + if origin == nil { panic(fmt.Sprintf("%v: cannot instantiate %v", x.Pos(), gtyp)) } @@ -398,17 +408,64 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named posList[i] = arg.Pos() } - typ := check.instantiate(x.Pos(), base, targs, posList) - def.setUnderlying(typ) - check.recordInstance(x, targs, typ) + // create the instance + h := check.conf.Context.typeHash(origin, targs) + // targs may be incomplete, and require inference. In any case we should de-duplicate. + inst := check.conf.Context.typeForHash(h, nil) + // If inst is non-nil, we can't just return here. Inst may have been + // constructed via recursive substitution, in which case we wouldn't do the + // validation below. Ensure that the validation (and resulting errors) runs + // for each instantiated type in the source. + if inst == nil { + tname := NewTypeName(x.Pos(), origin.obj.pkg, origin.obj.name, nil) + inst = check.newNamed(tname, origin, nil, nil, nil) // underlying, methods and tparams are set when named is resolved + inst.targs = NewTypeList(targs) + inst = check.conf.Context.typeForHash(h, inst) + } + def.setUnderlying(inst) + + inst.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, []*Func) { + tparams := origin.TypeParams().list() + + inferred := targs + if len(targs) < len(tparams) { + // If inference fails, len(inferred) will be 0, and inst.underlying will + // be set to Typ[Invalid] in expandNamed. + inferred = check.infer(x, tparams, targs, nil, nil) + if len(inferred) > len(targs) { + inst.targs = NewTypeList(inferred) + } + } - // make sure we check instantiation works at least once - // and that the resulting type is valid + check.recordInstance(x, inferred, inst) + return expandNamed(ctxt, n, x.Pos()) + } + + // origin.tparams may not be set up, so we need to do expansion later. check.later(func() { - check.validType(typ, nil) + // This is an instance from the source, not from recursive substitution, + // and so it must be resolved during type-checking so that we can report + // errors. + inst.resolve(check.conf.Context) + // Since check is non-nil, we can still mutate inst. Unpinning the resolver + // frees some memory. + inst.resolver = nil + + if check.validateTArgLen(x.Pos(), inst.tparams.Len(), inst.targs.Len()) { + if i, err := check.verify(x.Pos(), inst.tparams.list(), inst.targs.list()); err != nil { + // best position for error reporting + pos := x.Pos() + if i < len(posList) { + pos = posList[i] + } + check.softErrorf(atPos(pos), _Todo, err.Error()) + } + } + + check.validType(inst, nil) }) - return typ + return inst } // arrayLength type-checks the array length expression e -- GitLab From 323e009c757229bdf58f68fde1c5bf07e9e65b61 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Fri, 15 Oct 2021 16:39:39 -0400 Subject: [PATCH 1642/2500] go/types: ensure named types are expanded after type-checking Rather than using Checker.later in newNamed, add a Checker.defTypes field to track named types that have been created during type-checking, and use this to expand named types as a final phase in type checking. We have encountered several bugs related to infinite recursion while expanding named types, because (I would argue) we have two conflicting requirements in the type checker: ensuring that we eventually collapse underlying chains, and yet allowing lazy substitution of the underlying type in instances. The former is necessary for correctness, and to ensure that we detect cycles during the type-checking pass. The latter is necessary to allow infinitely expanding patterns of instances through underlying or method definitions. I believe this CL reconciles these conflicting requirements, by creating a boundary between types that are encountered in the source during type checking, and instances that are created by recursive evaluation. At the end of the type checking pass, Checker.defTypes should contain all possible origin types for instantiation. Once we compute the true underlying for these origin types, any remaining instances that are unresolved are guaranteed to have an origin with a valid underlying. Therefore, we can return from the type-checking pass without calling under() for these remaining instances. Fixes #48703 Fixes #48974 Change-Id: I1474f514e2ab71c1ad4c3704fe32bfba11d59394 Reviewed-on: https://go-review.googlesource.com/c/go/+/356490 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/check.go | 27 +++++++++++++++++++ src/go/types/named.go | 23 ++++++---------- .../types/testdata/fixedbugs/issue48703.go2 | 27 +++++++++++++++++++ .../types/testdata/fixedbugs/issue48974.go2 | 22 +++++++++++++++ 4 files changed, 84 insertions(+), 15 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue48703.go2 create mode 100644 src/go/types/testdata/fixedbugs/issue48974.go2 diff --git a/src/go/types/check.go b/src/go/types/check.go index 46a0000940..3fc9c03917 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -113,6 +113,7 @@ type Checker struct { untyped map[ast.Expr]exprInfo // map of expressions without final type delayed []func() // stack of delayed action segments; segments are processed in FIFO order objPath []Object // path of object dependencies during type inference (for cycle reporting) + defTypes []*Named // defined types created during type checking, for final validation. // context within which the current object is type-checked // (valid only for the duration of type-checking a specific object) @@ -269,6 +270,8 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) { check.processDelayed(0) // incl. all functions + check.expandDefTypes() + check.initOrder() if !check.conf.DisableUnusedImportCheck { @@ -285,6 +288,7 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) { check.pkgPathMap = nil check.seenPkgMap = nil check.recvTParamMap = nil + check.defTypes = nil // TODO(rFindley) There's more memory we should release at this point. @@ -306,6 +310,29 @@ func (check *Checker) processDelayed(top int) { check.delayed = check.delayed[:top] } +func (check *Checker) expandDefTypes() { + // Ensure that every defined type created in the course of type-checking has + // either non-*Named underlying, or is unresolved. + // + // This guarantees that we don't leak any types whose underlying is *Named, + // because any unresolved instances will lazily compute their underlying by + // substituting in the underlying of their origin. The origin must have + // either been imported or type-checked and expanded here, and in either case + // its underlying will be fully expanded. + for i := 0; i < len(check.defTypes); i++ { + n := check.defTypes[i] + switch n.underlying.(type) { + case nil: + if n.resolver == nil { + panic("nil underlying") + } + case *Named: + n.under() // n.under may add entries to check.defTypes + } + n.check = nil + } +} + func (check *Checker) record(x *operand) { // convert x into a user-friendly set of values // TODO(gri) this code can be simplified diff --git a/src/go/types/named.go b/src/go/types/named.go index 595863a01b..c81383810e 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -65,22 +65,9 @@ func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tpar if obj.typ == nil { obj.typ = typ } - // Ensure that typ is always expanded, at which point the check field can be - // nilled out. - // - // Note that currently we cannot nil out check inside typ.under(), because - // it's possible that typ is expanded multiple times. - // - // TODO(rFindley): clean this up so that under is the only function mutating - // named types. + // Ensure that typ is always expanded and sanity-checked. if check != nil { - check.later(func() { - switch typ.under().(type) { - case *Named: - panic("unexpanded underlying type") - } - typ.check = nil - }) + check.defTypes = append(check.defTypes, typ) } return typ } @@ -241,6 +228,12 @@ func expandNamed(ctxt *Context, n *Named, instPos token.Pos) (tparams *TypeParam check := n.check + if _, unexpanded := n.orig.underlying.(*Named); unexpanded { + // We should only get an unexpanded underlying here during type checking + // (for example, in recursive type declarations). + assert(check != nil) + } + // Mismatching arg and tparam length may be checked elsewhere. if n.orig.tparams.Len() == n.targs.Len() { // We must always have a context, to avoid infinite recursion. diff --git a/src/go/types/testdata/fixedbugs/issue48703.go2 b/src/go/types/testdata/fixedbugs/issue48703.go2 new file mode 100644 index 0000000000..8a32c1ecf2 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue48703.go2 @@ -0,0 +1,27 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +import "unsafe" + +// The actual example from the issue. +type List[P any] struct{} + +func (_ List[P]) m() (_ List[List[P]]) { return } + +// Other types of recursion through methods. +type R[P any] int + +func (*R[R /* ERROR must be an identifier */ [int]]) m0() {} +func (R[P]) m1(R[R[P]]) {} +func (R[P]) m2(R[*P]) {} +func (R[P]) m3([unsafe.Sizeof(new(R[P]))]int) {} +func (R[P]) m4([unsafe.Sizeof(new(R[R[P]]))]int) {} + +// Mutual recursion +type M[P any] int + +func (R[P]) m5(M[M[P]]) {} +func (M[P]) m(R[R[P]]) {} diff --git a/src/go/types/testdata/fixedbugs/issue48974.go2 b/src/go/types/testdata/fixedbugs/issue48974.go2 new file mode 100644 index 0000000000..ca4b6d9321 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue48974.go2 @@ -0,0 +1,22 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type Fooer interface { + Foo() +} + +type Fooable[F Fooer] struct { + ptr F +} + +func (f *Fooable[F]) Adapter() *Fooable[*FooerImpl[F]] { + return &Fooable[*FooerImpl[F]]{&FooerImpl[F]{}} +} + +type FooerImpl[F Fooer] struct { +} + +func (fi *FooerImpl[F]) Foo() {} -- GitLab From eba0e866fafe3f8223d654a29fb953e02c07364a Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sun, 17 Oct 2021 18:27:53 -0400 Subject: [PATCH 1643/2500] go/types: delay expansion of underlying in typeDecl Even after type-checking the RHS of a type declaration, we may not yet be able to expand, if the RHS is itself an instance (see #49043). We can instead rely on the mechanisms we have in place for delayed expansion. Fixes #49043 Change-Id: Ibffa4c1b1163c824b5c7e151aaac35f3e8c84ec7 Reviewed-on: https://go-review.googlesource.com/c/go/+/356533 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer --- src/go/types/decl.go | 23 +++++------------- src/go/types/named.go | 17 ++++++++++++- src/go/types/testdata/check/typeinst.go2 | 2 +- .../types/testdata/fixedbugs/issue49043.go2 | 24 +++++++++++++++++++ 4 files changed, 47 insertions(+), 19 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue49043.go2 diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 4aa49b17ca..3e97fbbccd 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -647,22 +647,11 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { assert(rhs != nil) named.fromRHS = rhs - // The underlying type of named may be itself a named type that is - // incomplete: - // - // type ( - // A B - // B *C - // C A - // ) - // - // The type of C is the (named) type of A which is incomplete, - // and which has as its underlying type the named type B. - // Determine the (final, unnamed) underlying type by resolving - // any forward chain. - // TODO(gri) Investigate if we can just use named.fromRHS here - // and rely on lazy computation of the underlying type. - named.underlying = under(named) + // If the underlying was not set while type-checking the right-hand side, it + // is invalid and an error should have been reported elsewhere. + if named.underlying == nil { + named.underlying = Typ[Invalid] + } // If the RHS is a type parameter, it must be from this type declaration. if tpar, _ := named.underlying.(*TypeParam); tpar != nil && tparamIndex(named.TypeParams().list(), tpar) < 0 { @@ -776,7 +765,7 @@ func (check *Checker) collectMethods(obj *TypeName) { // and field names must be distinct." base := asNamed(obj.typ) // shouldn't fail but be conservative if base != nil { - u := safeUnderlying(base) // base should be expanded, but use safeUnderlying to be conservative + u := base.under() if t, _ := u.(*Struct); t != nil { for _, fld := range t.fields { if fld.name != "_" { diff --git a/src/go/types/named.go b/src/go/types/named.go index c81383810e..393d40b127 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -132,6 +132,18 @@ func (t *Named) String() string { return TypeString(t, nil) } // chain before returning it. If no underlying type is found or a cycle // is detected, the result is Typ[Invalid]. If a cycle is detected and // n0.check != nil, the cycle is reported. +// +// This is necessary because the underlying type of named may be itself a +// named type that is incomplete: +// +// type ( +// A B +// B *C +// C A +// ) +// +// The type of C is the (named) type of A which is incomplete, +// and which has as its underlying type the named type B. func (n0 *Named) under() Type { u := n0.Underlying() @@ -141,7 +153,9 @@ func (n0 *Named) under() Type { var n1 *Named switch u1 := u.(type) { case nil: - return Typ[Invalid] + // After expansion via Underlying(), we should never encounter a nil + // underlying. + panic("nil underlying") default: // common case return u @@ -225,6 +239,7 @@ func (check *Checker) bestContext(ctxt *Context) *Context { // The underlying type will be Typ[Invalid] if there was an error. func expandNamed(ctxt *Context, n *Named, instPos token.Pos) (tparams *TypeParamList, underlying Type, methods []*Func) { n.orig.resolve(ctxt) + assert(n.orig.underlying != nil) check := n.check diff --git a/src/go/types/testdata/check/typeinst.go2 b/src/go/types/testdata/check/typeinst.go2 index 4a8918ab86..f4f6c0264b 100644 --- a/src/go/types/testdata/check/typeinst.go2 +++ b/src/go/types/testdata/check/typeinst.go2 @@ -57,5 +57,5 @@ var _ T3[int] = T3[int](List[int]{1, 2, 3}) // Self-recursive generic types are not permitted -type self1[P any] self1 /* ERROR illegal cycle */ [P] +type self1 /* ERROR illegal cycle */ [P any] self1[P] type self2[P any] *self2[P] // this is ok diff --git a/src/go/types/testdata/fixedbugs/issue49043.go2 b/src/go/types/testdata/fixedbugs/issue49043.go2 new file mode 100644 index 0000000000..c37b0f1267 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue49043.go2 @@ -0,0 +1,24 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +// The example from the issue. +type ( + N /* ERROR illegal cycle */ [P any] M[P] + M[P any] N[P] +) + +// A slightly more complicated case. +type ( + A /* ERROR illegal cycle */ [P any] B[P] + B[P any] C[P] + C[P any] A[P] +) + +// Confusing but valid (note that `type T *T` is valid). +type ( + N1[P any] *M1[P] + M1[P any] *N1[P] +) -- GitLab From 8838a3b53fccc7b3aa83312326bfd38bcb8f2281 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Fri, 8 Oct 2021 20:28:58 +1100 Subject: [PATCH 1644/2500] cmd/internal/obj/riscv: fix and enable test in short mode The branch test only takes a few seconds so enable it in short mode. Also fix a typo that currently prevents the code from compiling. Change-Id: I25fc646b002a66c042c61fb1f56d5efa8e47903c Reviewed-on: https://go-review.googlesource.com/c/go/+/356249 Trust: Joel Sing Reviewed-by: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot --- src/cmd/internal/obj/riscv/asm_test.go | 3 --- src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/cmd/internal/obj/riscv/asm_test.go b/src/cmd/internal/obj/riscv/asm_test.go index f8f7b4f2ce..684c6b61f2 100644 --- a/src/cmd/internal/obj/riscv/asm_test.go +++ b/src/cmd/internal/obj/riscv/asm_test.go @@ -134,9 +134,6 @@ TEXT _stub(SB),$0-0 } func TestBranch(t *testing.T) { - if testing.Short() { - t.Skip("Skipping in short mode") - } if runtime.GOARCH != "riscv64" { t.Skip("Requires riscv64 to run") } diff --git a/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go b/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go index de412c64a7..68d9589bf2 100644 --- a/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go +++ b/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go @@ -32,7 +32,7 @@ func testGoBGTU(a, b int64) bool { return uint64(a) > uint64(b) } func testGoBLE(a, b int64) bool { return a <= b } func testGoBLEU(a, b int64) bool { return uint64(a) <= uint64(b) } func testGoBLT(a, b int64) bool { return a < b } -func testGoBLTZ(a, b int64) bool { return uint64(a) < uint64(b) } +func testGoBLTU(a, b int64) bool { return uint64(a) < uint64(b) } func TestBranchCondition(t *testing.T) { tests := []struct { -- GitLab From ee92daae25029882979eb694bd7246491e364d3c Mon Sep 17 00:00:00 2001 From: Meng Zhuo Date: Mon, 20 Sep 2021 20:44:50 +0800 Subject: [PATCH 1645/2500] runtime: ensure at least 1 tick between events ticks might be same after tick division, although the real cputicks is linear growth Fixes #46737 Change-Id: I1d98866fbf21b426c6c1c96cc9cf802d7f440f18 Reviewed-on: https://go-review.googlesource.com/c/go/+/330849 Trust: Meng Zhuo Trust: Bryan C. Mills Run-TryBot: Meng Zhuo Reviewed-by: Michael Knyszek TryBot-Result: Go Bot --- src/runtime/trace.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/runtime/trace.go b/src/runtime/trace.go index 00544e4283..5b14a5f553 100644 --- a/src/runtime/trace.go +++ b/src/runtime/trace.go @@ -551,8 +551,15 @@ func traceEventLocked(extraBytes int, mp *m, pid int32, bufp *traceBufPtr, ev by bufp.set(buf) } + // NOTE: ticks might be same after tick division, although the real cputicks is + // linear growth. ticks := uint64(cputicks()) / traceTickDiv tickDiff := ticks - buf.lastTicks + if tickDiff == 0 { + ticks = buf.lastTicks + 1 + tickDiff = 1 + } + buf.lastTicks = ticks narg := byte(len(args)) if skip >= 0 { @@ -653,6 +660,9 @@ func traceFlush(buf traceBufPtr, pid int32) traceBufPtr { // initialize the buffer for a new batch ticks := uint64(cputicks()) / traceTickDiv + if ticks == bufp.lastTicks { + ticks = bufp.lastTicks + 1 + } bufp.lastTicks = ticks bufp.byte(traceEvBatch | 1< Date: Thu, 9 Sep 2021 00:32:03 +0800 Subject: [PATCH 1646/2500] encoding/base64: add examples for Encode/Decode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #37595 Change-Id: I83e5f6105748a0a9238322a4f7ec4b0bbf61a263 Reviewed-on: https://go-review.googlesource.com/c/go/+/348394 Reviewed-by: Daniel Martí Reviewed-by: Ian Lance Taylor Trust: Daniel Martí Trust: Cherry Mui --- src/encoding/base64/example_test.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/encoding/base64/example_test.go b/src/encoding/base64/example_test.go index 73f119ac5e..61a3adc5ad 100644 --- a/src/encoding/base64/example_test.go +++ b/src/encoding/base64/example_test.go @@ -35,6 +35,15 @@ func ExampleEncoding_EncodeToString() { // YW55ICsgb2xkICYgZGF0YQ== } +func ExampleEncoding_Encode() { + data := []byte("Hello, world!") + dst := make([]byte, base64.StdEncoding.EncodedLen(len(data))) + base64.StdEncoding.Encode(dst, data) + fmt.Println(string(dst)) + // Output: + // SGVsbG8sIHdvcmxkIQ== +} + func ExampleEncoding_DecodeString() { str := "c29tZSBkYXRhIHdpdGggACBhbmQg77u/" data, err := base64.StdEncoding.DecodeString(str) @@ -47,6 +56,20 @@ func ExampleEncoding_DecodeString() { // "some data with \x00 and \ufeff" } +func ExampleEncoding_Decode() { + str := "SGVsbG8sIHdvcmxkIQ==" + dst := make([]byte, base64.StdEncoding.DecodedLen(len(str))) + n, err := base64.StdEncoding.Decode(dst, []byte(str)) + if err != nil { + fmt.Println("decode error:", err) + return + } + dst = dst[:n] + fmt.Printf("%q\n", dst) + // Output: + // "Hello, world!" +} + func ExampleNewEncoder() { input := []byte("foo\x00bar") encoder := base64.NewEncoder(base64.StdEncoding, os.Stdout) -- GitLab From b0351bfd7d5f0d367c27aa07789b2e6317442ece Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Tue, 19 Oct 2021 09:09:55 +0000 Subject: [PATCH 1647/2500] Revert "cmd/compile: use MOVBE instruction for GOAMD64>=v3" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts CL 354670. Reason for revert: broke make.bash with GOAMD64=v3. Fixes #49061. Change-Id: I7f2ed99b7c10100c4e0c1462ea91c4c9d8c609b2 Reviewed-on: https://go-review.googlesource.com/c/go/+/356790 Trust: Daniel Martí Run-TryBot: Daniel Martí TryBot-Result: Go Bot Reviewed-by: Koichi Shiraishi Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/amd64/ssa.go | 7 +- .../compile/internal/amd64/versions_test.go | 27 +- src/cmd/compile/internal/ssa/gen/AMD64.rules | 26 -- src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 6 - src/cmd/compile/internal/ssa/opGen.go | 64 ----- src/cmd/compile/internal/ssa/rewriteAMD64.go | 243 ------------------ test/codegen/memcombine.go | 36 +-- 7 files changed, 20 insertions(+), 389 deletions(-) diff --git a/src/cmd/compile/internal/amd64/ssa.go b/src/cmd/compile/internal/amd64/ssa.go index b0e5c34030..0e74574422 100644 --- a/src/cmd/compile/internal/amd64/ssa.go +++ b/src/cmd/compile/internal/amd64/ssa.go @@ -772,9 +772,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.From.Val = math.Float64frombits(uint64(v.AuxInt)) p.To.Type = obj.TYPE_REG p.To.Reg = x - case ssa.OpAMD64MOVQload, ssa.OpAMD64MOVLload, ssa.OpAMD64MOVWload, ssa.OpAMD64MOVBload, ssa.OpAMD64MOVOload, - ssa.OpAMD64MOVSSload, ssa.OpAMD64MOVSDload, ssa.OpAMD64MOVBQSXload, ssa.OpAMD64MOVWQSXload, ssa.OpAMD64MOVLQSXload, - ssa.OpAMD64MOVBEQload, ssa.OpAMD64MOVBELload: + case ssa.OpAMD64MOVQload, ssa.OpAMD64MOVSSload, ssa.OpAMD64MOVSDload, ssa.OpAMD64MOVLload, ssa.OpAMD64MOVWload, ssa.OpAMD64MOVBload, ssa.OpAMD64MOVBQSXload, ssa.OpAMD64MOVWQSXload, ssa.OpAMD64MOVLQSXload, ssa.OpAMD64MOVOload: p := s.Prog(v.Op.Asm()) p.From.Type = obj.TYPE_MEM p.From.Reg = v.Args[0].Reg() @@ -790,8 +788,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.To.Reg = v.Reg() case ssa.OpAMD64MOVQstore, ssa.OpAMD64MOVSSstore, ssa.OpAMD64MOVSDstore, ssa.OpAMD64MOVLstore, ssa.OpAMD64MOVWstore, ssa.OpAMD64MOVBstore, ssa.OpAMD64MOVOstore, ssa.OpAMD64ADDQmodify, ssa.OpAMD64SUBQmodify, ssa.OpAMD64ANDQmodify, ssa.OpAMD64ORQmodify, ssa.OpAMD64XORQmodify, - ssa.OpAMD64ADDLmodify, ssa.OpAMD64SUBLmodify, ssa.OpAMD64ANDLmodify, ssa.OpAMD64ORLmodify, ssa.OpAMD64XORLmodify, - ssa.OpAMD64MOVBEQstore, ssa.OpAMD64MOVBELstore: + ssa.OpAMD64ADDLmodify, ssa.OpAMD64SUBLmodify, ssa.OpAMD64ANDLmodify, ssa.OpAMD64ORLmodify, ssa.OpAMD64XORLmodify: p := s.Prog(v.Op.Asm()) p.From.Type = obj.TYPE_REG p.From.Reg = v.Args[1].Reg() diff --git a/src/cmd/compile/internal/amd64/versions_test.go b/src/cmd/compile/internal/amd64/versions_test.go index ee1a8ca3aa..de677f3a69 100644 --- a/src/cmd/compile/internal/amd64/versions_test.go +++ b/src/cmd/compile/internal/amd64/versions_test.go @@ -53,9 +53,7 @@ func TestGoAMD64v1(t *testing.T) { opcodes := map[string]bool{} var features []string for feature, opcodeList := range featureToOpcodes { - if runtimeFeatures[feature] { - features = append(features, fmt.Sprintf("cpu.%s=off", feature)) - } + features = append(features, fmt.Sprintf("cpu.%s=off", feature)) for _, op := range opcodeList { opcodes[op] = true } @@ -206,28 +204,14 @@ func clobber(t *testing.T, src string, dst *os.File, opcodes map[string]bool) { f.Close() } -func setOf(keys ...string) map[string]bool { - m := make(map[string]bool, len(keys)) - for _, key := range keys { - m[key] = true - } - return m -} - -var runtimeFeatures = setOf( - "adx", "aes", "avx", "avx2", "bmi1", "bmi2", "erms", "fma", - "pclmulqdq", "popcnt", "rdtscp", "sse3", "sse41", "sse42", "ssse3", -) - var featureToOpcodes = map[string][]string{ // Note: we include *q, *l, and plain opcodes here. // go tool objdump doesn't include a [QL] on popcnt instructions, until CL 351889 // native objdump doesn't include [QL] on linux. - "popcnt": {"popcntq", "popcntl", "popcnt"}, - "bmi1": {"andnq", "andnl", "andn", "blsiq", "blsil", "blsi", "blsmskq", "blsmskl", "blsmsk", "blsrq", "blsrl", "blsr", "tzcntq", "tzcntl", "tzcnt"}, - "sse41": {"roundsd"}, - "fma": {"vfmadd231sd"}, - "movbe": {"movbeqq", "movbeq", "movbell", "movbel", "movbe"}, + "popcnt": []string{"popcntq", "popcntl", "popcnt"}, + "bmi1": []string{"andnq", "andnl", "andn", "blsiq", "blsil", "blsi", "blsmskq", "blsmskl", "blsmsk", "blsrq", "blsrl", "blsr", "tzcntq", "tzcntl", "tzcnt"}, + "sse41": []string{"roundsd"}, + "fma": []string{"vfmadd231sd"}, } // Test to use POPCNT instruction, if available @@ -380,4 +364,5 @@ func TestFMA(t *testing.T) { t.Errorf("FMA(%f,%f,%f) = %f, want %f", tt.x, tt.y, tt.z, got, tt.want) } } + } diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 507d701999..8b73ee14ea 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -2219,29 +2219,3 @@ (AND(Q|L) x (ADD(Q|L)const [-1] x)) && buildcfg.GOAMD64 >= 3 => (BLSR(Q|L) x) (BSWAP(Q|L) (BSWAP(Q|L) p)) => p - -// CPUID feature: MOVBE. -(MOV(Q|L)store [i] {s} p x:(BSWAP(Q|L) w) mem) && x.Uses == 1 && buildcfg.GOAMD64 >= 3 => (MOVBE(Q|L)store [i] {s} p w mem) -(BSWAP(Q|L) x:(MOV(Q|L)load [i] {s} p mem)) && x.Uses == 1 && buildcfg.GOAMD64 >= 3 => (MOVBE(Q|L)load [i] {s} p mem) -(BSWAP(Q|L) (MOVBE(Q|L)load [i] {s} p m)) => (MOV(Q|L)load [i] {s} p m) -(MOVBE(Q|L)store [i] {s} p (BSWAP(Q|L) x) m) => (MOV(Q|L)store [i] {s} p x m) - -(ORQ x0:(MOVBELload [i0] {s} p mem) - sh:(SHLQconst [32] x1:(MOVBELload [i1] {s} p mem))) - && i0 == i1+4 - && x0.Uses == 1 - && x1.Uses == 1 - && sh.Uses == 1 - && mergePoint(b,x0,x1) != nil - && clobber(x0, x1, sh) - => @mergePoint(b,x0,x1) (MOVBEQload [i1] {s} p mem) - -(ORQ x0:(MOVBELload [i] {s} p0 mem) - sh:(SHLQconst [32] x1:(MOVBELload [i] {s} p1 mem))) - && x0.Uses == 1 - && x1.Uses == 1 - && sh.Uses == 1 - && sequentialAddresses(p1, p0, 4) - && mergePoint(b,x0,x1) != nil - && clobber(x0, x1, sh) - => @mergePoint(b,x0,x1) (MOVBEQload [i] {s} p0 mem) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index e3c94e4b2e..731454c761 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -922,12 +922,6 @@ func init() { // and BSFQ(0) is undefined. Same for TZCNTL(0)==32 {name: "TZCNTQ", argLength: 1, reg: gp11, asm: "TZCNTQ", clobberFlags: true}, {name: "TZCNTL", argLength: 1, reg: gp11, asm: "TZCNTL", clobberFlags: true}, - - // CPUID feature: MOVBE - {name: "MOVBELload", argLength: 2, reg: gpload, asm: "MOVBEL", aux: "SymOff", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"}, // load and swap 4 bytes from arg0+auxint+aux. arg1=mem. Zero extend. - {name: "MOVBELstore", argLength: 3, reg: gpstore, asm: "MOVBEL", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // swap and store 4 bytes in arg1 to arg0+auxint+aux. arg2=mem - {name: "MOVBEQload", argLength: 2, reg: gpload, asm: "MOVBEQ", aux: "SymOff", typ: "UInt64", faultOnNilArg0: true, symEffect: "Read"}, // load and swap 8 bytes from arg0+auxint+aux. arg1=mem - {name: "MOVBEQstore", argLength: 3, reg: gpstore, asm: "MOVBEQ", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // swap and store 8 bytes in arg1 to arg0+auxint+aux. arg2=mem } var AMD64blocks = []blockData{ diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 091f43f40a..640e517fe7 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -1043,10 +1043,6 @@ const ( OpAMD64BLSRL OpAMD64TZCNTQ OpAMD64TZCNTL - OpAMD64MOVBELload - OpAMD64MOVBELstore - OpAMD64MOVBEQload - OpAMD64MOVBEQstore OpARMADD OpARMADDconst @@ -13784,66 +13780,6 @@ var opcodeTable = [...]opInfo{ }, }, }, - { - name: "MOVBELload", - auxType: auxSymOff, - argLen: 2, - faultOnNilArg0: true, - symEffect: SymRead, - asm: x86.AMOVBEL, - reg: regInfo{ - inputs: []inputInfo{ - {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB - }, - outputs: []outputInfo{ - {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 - }, - }, - }, - { - name: "MOVBELstore", - auxType: auxSymOff, - argLen: 3, - faultOnNilArg0: true, - symEffect: SymWrite, - asm: x86.AMOVBEL, - reg: regInfo{ - inputs: []inputInfo{ - {1, 49151}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15 - {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB - }, - }, - }, - { - name: "MOVBEQload", - auxType: auxSymOff, - argLen: 2, - faultOnNilArg0: true, - symEffect: SymRead, - asm: x86.AMOVBEQ, - reg: regInfo{ - inputs: []inputInfo{ - {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB - }, - outputs: []outputInfo{ - {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 - }, - }, - }, - { - name: "MOVBEQstore", - auxType: auxSymOff, - argLen: 3, - faultOnNilArg0: true, - symEffect: SymWrite, - asm: x86.AMOVBEQ, - reg: regInfo{ - inputs: []inputInfo{ - {1, 49151}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15 - {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB - }, - }, - }, { name: "ADD", diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 88b545a465..201fbf2954 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -222,10 +222,6 @@ func rewriteValueAMD64(v *Value) bool { return rewriteValueAMD64_OpAMD64LEAQ4(v) case OpAMD64LEAQ8: return rewriteValueAMD64_OpAMD64LEAQ8(v) - case OpAMD64MOVBELstore: - return rewriteValueAMD64_OpAMD64MOVBELstore(v) - case OpAMD64MOVBEQstore: - return rewriteValueAMD64_OpAMD64MOVBEQstore(v) case OpAMD64MOVBQSX: return rewriteValueAMD64_OpAMD64MOVBQSX(v) case OpAMD64MOVBQSXload: @@ -3627,43 +3623,6 @@ func rewriteValueAMD64_OpAMD64BSWAPL(v *Value) bool { v.copyOf(p) return true } - // match: (BSWAPL x:(MOVLload [i] {s} p mem)) - // cond: x.Uses == 1 && buildcfg.GOAMD64 >= 3 - // result: (MOVBELload [i] {s} p mem) - for { - x := v_0 - if x.Op != OpAMD64MOVLload { - break - } - i := auxIntToInt32(x.AuxInt) - s := auxToSym(x.Aux) - mem := x.Args[1] - p := x.Args[0] - if !(x.Uses == 1 && buildcfg.GOAMD64 >= 3) { - break - } - v.reset(OpAMD64MOVBELload) - v.AuxInt = int32ToAuxInt(i) - v.Aux = symToAux(s) - v.AddArg2(p, mem) - return true - } - // match: (BSWAPL (MOVBELload [i] {s} p m)) - // result: (MOVLload [i] {s} p m) - for { - if v_0.Op != OpAMD64MOVBELload { - break - } - i := auxIntToInt32(v_0.AuxInt) - s := auxToSym(v_0.Aux) - m := v_0.Args[1] - p := v_0.Args[0] - v.reset(OpAMD64MOVLload) - v.AuxInt = int32ToAuxInt(i) - v.Aux = symToAux(s) - v.AddArg2(p, m) - return true - } return false } func rewriteValueAMD64_OpAMD64BSWAPQ(v *Value) bool { @@ -3678,43 +3637,6 @@ func rewriteValueAMD64_OpAMD64BSWAPQ(v *Value) bool { v.copyOf(p) return true } - // match: (BSWAPQ x:(MOVQload [i] {s} p mem)) - // cond: x.Uses == 1 && buildcfg.GOAMD64 >= 3 - // result: (MOVBEQload [i] {s} p mem) - for { - x := v_0 - if x.Op != OpAMD64MOVQload { - break - } - i := auxIntToInt32(x.AuxInt) - s := auxToSym(x.Aux) - mem := x.Args[1] - p := x.Args[0] - if !(x.Uses == 1 && buildcfg.GOAMD64 >= 3) { - break - } - v.reset(OpAMD64MOVBEQload) - v.AuxInt = int32ToAuxInt(i) - v.Aux = symToAux(s) - v.AddArg2(p, mem) - return true - } - // match: (BSWAPQ (MOVBEQload [i] {s} p m)) - // result: (MOVQload [i] {s} p m) - for { - if v_0.Op != OpAMD64MOVBEQload { - break - } - i := auxIntToInt32(v_0.AuxInt) - s := auxToSym(v_0.Aux) - m := v_0.Args[1] - p := v_0.Args[0] - v.reset(OpAMD64MOVQload) - v.AuxInt = int32ToAuxInt(i) - v.Aux = symToAux(s) - v.AddArg2(p, m) - return true - } return false } func rewriteValueAMD64_OpAMD64BTCLconst(v *Value) bool { @@ -9473,52 +9395,6 @@ func rewriteValueAMD64_OpAMD64LEAQ8(v *Value) bool { } return false } -func rewriteValueAMD64_OpAMD64MOVBELstore(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVBELstore [i] {s} p (BSWAPL x) m) - // result: (MOVLstore [i] {s} p x m) - for { - i := auxIntToInt32(v.AuxInt) - s := auxToSym(v.Aux) - p := v_0 - if v_1.Op != OpAMD64BSWAPL { - break - } - x := v_1.Args[0] - m := v_2 - v.reset(OpAMD64MOVLstore) - v.AuxInt = int32ToAuxInt(i) - v.Aux = symToAux(s) - v.AddArg3(p, x, m) - return true - } - return false -} -func rewriteValueAMD64_OpAMD64MOVBEQstore(v *Value) bool { - v_2 := v.Args[2] - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MOVBEQstore [i] {s} p (BSWAPQ x) m) - // result: (MOVQstore [i] {s} p x m) - for { - i := auxIntToInt32(v.AuxInt) - s := auxToSym(v.Aux) - p := v_0 - if v_1.Op != OpAMD64BSWAPQ { - break - } - x := v_1.Args[0] - m := v_2 - v.reset(OpAMD64MOVQstore) - v.AuxInt = int32ToAuxInt(i) - v.Aux = symToAux(s) - v.AddArg3(p, x, m) - return true - } - return false -} func rewriteValueAMD64_OpAMD64MOVBQSX(v *Value) bool { v_0 := v.Args[0] b := v.Block @@ -12349,28 +12225,6 @@ func rewriteValueAMD64_OpAMD64MOVLstore(v *Value) bool { v.AddArg3(ptr, val, mem) return true } - // match: (MOVLstore [i] {s} p x:(BSWAPL w) mem) - // cond: x.Uses == 1 && buildcfg.GOAMD64 >= 3 - // result: (MOVBELstore [i] {s} p w mem) - for { - i := auxIntToInt32(v.AuxInt) - s := auxToSym(v.Aux) - p := v_0 - x := v_1 - if x.Op != OpAMD64BSWAPL { - break - } - w := x.Args[0] - mem := v_2 - if !(x.Uses == 1 && buildcfg.GOAMD64 >= 3) { - break - } - v.reset(OpAMD64MOVBELstore) - v.AuxInt = int32ToAuxInt(i) - v.Aux = symToAux(s) - v.AddArg3(p, w, mem) - return true - } return false } func rewriteValueAMD64_OpAMD64MOVLstoreconst(v *Value) bool { @@ -13310,28 +13164,6 @@ func rewriteValueAMD64_OpAMD64MOVQstore(v *Value) bool { v.AddArg3(ptr, val, mem) return true } - // match: (MOVQstore [i] {s} p x:(BSWAPQ w) mem) - // cond: x.Uses == 1 && buildcfg.GOAMD64 >= 3 - // result: (MOVBEQstore [i] {s} p w mem) - for { - i := auxIntToInt32(v.AuxInt) - s := auxToSym(v.Aux) - p := v_0 - x := v_1 - if x.Op != OpAMD64BSWAPQ { - break - } - w := x.Args[0] - mem := v_2 - if !(x.Uses == 1 && buildcfg.GOAMD64 >= 3) { - break - } - v.reset(OpAMD64MOVBEQstore) - v.AuxInt = int32ToAuxInt(i) - v.Aux = symToAux(s) - v.AddArg3(p, w, mem) - return true - } return false } func rewriteValueAMD64_OpAMD64MOVQstoreconst(v *Value) bool { @@ -18825,81 +18657,6 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { } break } - // match: (ORQ x0:(MOVBELload [i0] {s} p mem) sh:(SHLQconst [32] x1:(MOVBELload [i1] {s} p mem))) - // cond: i0 == i1+4 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) - // result: @mergePoint(b,x0,x1) (MOVBEQload [i1] {s} p mem) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - x0 := v_0 - if x0.Op != OpAMD64MOVBELload { - continue - } - i0 := auxIntToInt32(x0.AuxInt) - s := auxToSym(x0.Aux) - mem := x0.Args[1] - p := x0.Args[0] - sh := v_1 - if sh.Op != OpAMD64SHLQconst || auxIntToInt8(sh.AuxInt) != 32 { - continue - } - x1 := sh.Args[0] - if x1.Op != OpAMD64MOVBELload { - continue - } - i1 := auxIntToInt32(x1.AuxInt) - if auxToSym(x1.Aux) != s { - continue - } - _ = x1.Args[1] - if p != x1.Args[0] || mem != x1.Args[1] || !(i0 == i1+4 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { - continue - } - b = mergePoint(b, x0, x1) - v0 := b.NewValue0(x1.Pos, OpAMD64MOVBEQload, typ.UInt64) - v.copyOf(v0) - v0.AuxInt = int32ToAuxInt(i1) - v0.Aux = symToAux(s) - v0.AddArg2(p, mem) - return true - } - break - } - // match: (ORQ x0:(MOVBELload [i] {s} p0 mem) sh:(SHLQconst [32] x1:(MOVBELload [i] {s} p1 mem))) - // cond: x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p1, p0, 4) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) - // result: @mergePoint(b,x0,x1) (MOVBEQload [i] {s} p0 mem) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - x0 := v_0 - if x0.Op != OpAMD64MOVBELload { - continue - } - i := auxIntToInt32(x0.AuxInt) - s := auxToSym(x0.Aux) - mem := x0.Args[1] - p0 := x0.Args[0] - sh := v_1 - if sh.Op != OpAMD64SHLQconst || auxIntToInt8(sh.AuxInt) != 32 { - continue - } - x1 := sh.Args[0] - if x1.Op != OpAMD64MOVBELload || auxIntToInt32(x1.AuxInt) != i || auxToSym(x1.Aux) != s { - continue - } - _ = x1.Args[1] - p1 := x1.Args[0] - if mem != x1.Args[1] || !(x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p1, p0, 4) && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { - continue - } - b = mergePoint(b, x0, x1) - v0 := b.NewValue0(x1.Pos, OpAMD64MOVBEQload, typ.UInt64) - v.copyOf(v0) - v0.AuxInt = int32ToAuxInt(i) - v0.Aux = symToAux(s) - v0.AddArg2(p0, mem) - return true - } - break - } return false } func rewriteValueAMD64_OpAMD64ORQconst(v *Value) bool { diff --git a/test/codegen/memcombine.go b/test/codegen/memcombine.go index 97e1d4bdfb..2a0c534df0 100644 --- a/test/codegen/memcombine.go +++ b/test/codegen/memcombine.go @@ -70,8 +70,7 @@ func load_le16_idx(b []byte, idx int) { } func load_be64(b []byte) { - // amd64/v1,amd64/v2:`BSWAPQ`,-`MOV[BWL]\t[^$]`,-`OR` - // amd64/v3:`MOVBEQ` + // amd64:`BSWAPQ`,-`MOV[BWL]\t[^$]`,-`OR` // s390x:`MOVD\s\(.*\),` // arm64:`REV`,`MOVD\s\(R[0-9]+\),`,-`MOV[BHW]`,-`REVW`,-`REV16W` // ppc64le:`MOVDBR`,-`MOV[BHW]Z` @@ -79,8 +78,7 @@ func load_be64(b []byte) { } func load_be64_idx(b []byte, idx int) { - // amd64/v1,amd64/v2:`BSWAPQ`,-`MOV[BWL]\t[^$]`,-`OR` - // amd64/v3: `MOVBEQ` + // amd64:`BSWAPQ`,-`MOV[BWL]\t[^$]`,-`OR` // s390x:`MOVD\s\(.*\)\(.*\*1\),` // arm64:`REV`,`MOVD\s\(R[0-9]+\)\(R[0-9]+\),`,-`MOV[WHB]`,-`REVW`,-`REV16W` // ppc64le:`MOVDBR`,-`MOV[BHW]Z` @@ -88,8 +86,7 @@ func load_be64_idx(b []byte, idx int) { } func load_be32(b []byte) { - // amd64/v1,amd64/v2:`BSWAPL`,-`MOV[BW]`,-`OR` - // amd64/v3: `MOVBEL` + // amd64:`BSWAPL`,-`MOV[BW]`,-`OR` // s390x:`MOVWZ\s\(.*\),` // arm64:`REVW`,`MOVWU\s\(R[0-9]+\),`,-`MOV[BH]`,-`REV16W` // ppc64le:`MOVWBR`,-`MOV[BH]Z` @@ -97,8 +94,7 @@ func load_be32(b []byte) { } func load_be32_idx(b []byte, idx int) { - // amd64/v1,amd64/v2:`BSWAPL`,-`MOV[BW]`,-`OR` - // amd64/v3: `MOVBEL` + // amd64:`BSWAPL`,-`MOV[BW]`,-`OR` // s390x:`MOVWZ\s\(.*\)\(.*\*1\),` // arm64:`REVW`,`MOVWU\s\(R[0-9]+\)\(R[0-9]+\),`,-`MOV[HB]`,-`REV16W` // ppc64le:`MOVWBR`,-`MOV[BH]Z` @@ -183,8 +179,7 @@ func load_be_byte4_uint32(s []byte) uint32 { func load_be_byte4_uint32_inv(s []byte) uint32 { // arm64:`MOVWU\t\(R[0-9]+\)`,`REVW`,-`ORR`,-`REV16W`,-`MOV[BH]` - // amd64/v1,amd64/v2:`MOVL\s\([A-Z]+\)`,`BSWAPL`,-`MOV[BW]`,-`OR` - // amd64/v3: `MOVBEL` + // amd64:`MOVL\s\([A-Z]+\)`,`BSWAPL`,-`MOV[BW]`,-`OR` return uint32(s[3]) | uint32(s[2])<<8 | uint32(s[1])<<16 | uint32(s[0])<<24 } @@ -196,8 +191,7 @@ func load_be_byte8_uint64(s []byte) uint64 { func load_be_byte8_uint64_inv(s []byte) uint64 { // arm64:`MOVD\t\(R[0-9]+\)`,`REV`,-`ORR`,-`REVW`,-`REV16W`,-`MOV[BHW]` - // amd64/v1,amd64/v2:`MOVQ\s\([A-Z]+\),\s[A-Z]+`,`BSWAPQ`,-`MOV[BWL]\t[^$]`,-`OR` - // amd64/v3: `MOVBEQ` + // amd64:`MOVQ\s\([A-Z]+\),\s[A-Z]+`,`BSWAPQ`,-`MOV[BWL]\t[^$]`,-`OR` // ppc64le:`MOVDBR\t\(R[0-9]+\)`,-`MOV[BHW]Z` return uint64(s[7]) | uint64(s[6])<<8 | uint64(s[5])<<16 | uint64(s[4])<<24 | uint64(s[3])<<32 | uint64(s[2])<<40 | uint64(s[1])<<48 | uint64(s[0])<<56 } @@ -415,8 +409,7 @@ func store_le16_idx(b []byte, idx int) { } func store_be64(b []byte) { - // amd64/v1,amd64/v2:`BSWAPQ`,-`SHR.` - // amd64/v3: `MOVBEQ` + // amd64:`BSWAPQ`,-`SHR.` // arm64:`MOVD`,`REV`,-`MOV[WBH]`,-`REVW`,-`REV16W` // ppc64le:`MOVDBR` // s390x:`MOVD\s.*\(.*\)$`,-`SRW\s`,-`SRD\s` @@ -424,8 +417,7 @@ func store_be64(b []byte) { } func store_be64_idx(b []byte, idx int) { - // amd64/v1,amd64/v2:`BSWAPQ`,-`SHR.` - // amd64/v3:`MOVBEQ` + // amd64:`BSWAPQ`,-`SHR.` // arm64:`REV`,`MOVD\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOV[BHW]`,-`REV16W`,-`REVW` // ppc64le:`MOVDBR` // s390x:`MOVD\s.*\(.*\)\(.*\*1\)$`,-`SRW\s`,-`SRD\s` @@ -433,8 +425,7 @@ func store_be64_idx(b []byte, idx int) { } func store_be32(b []byte) { - // amd64/v1,amd64/v2:`BSWAPL`,-`SHR.` - // amd64/v3:`MOVBEL` + // amd64:`BSWAPL`,-`SHR.` // arm64:`MOVW`,`REVW`,-`MOV[BH]`,-`REV16W` // ppc64le:`MOVWBR` // s390x:`MOVW\s.*\(.*\)$`,-`SRW\s`,-`SRD\s` @@ -454,8 +445,7 @@ func store_be32_load(b, x *[8]byte) { } func store_be32_idx(b []byte, idx int) { - // amd64/v1,amd64/v2:`BSWAPL`,-`SHR.` - // amd64/v3:`MOVBEL` + // amd64:`BSWAPL`,-`SHR.` // arm64:`REVW`,`MOVW\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOV[BH]`,-`REV16W` // ppc64le:`MOVWBR` // s390x:`MOVW\s.*\(.*\)\(.*\*1\)$`,-`SRW\s`,-`SRD\s` @@ -518,16 +508,14 @@ func store_be_byte_2(b []byte, val uint16) { func store_be_byte_4(b []byte, val uint32) { _ = b[4] // arm64:`REVW`,`MOVW\sR[0-9]+,\s1\(R[0-9]+\)`,-`MOVB`,-`MOVH`,-`REV16W` - // amd64/v1,amd64/v2:`MOVL\s[A-Z]+,\s1\([A-Z]+\)`,-`MOVB`,-`MOVW` - // amd64/v3:`MOVBEL\s[A-Z]+,\s1\([A-Z]+\)` + // amd64:`MOVL\s[A-Z]+,\s1\([A-Z]+\)`,-`MOVB`,-`MOVW` b[1], b[2], b[3], b[4] = byte(val>>24), byte(val>>16), byte(val>>8), byte(val) } func store_be_byte_8(b []byte, val uint64) { _ = b[8] // arm64:`REV`,`MOVD\sR[0-9]+,\s1\(R[0-9]+\)`,-`MOVB`,-`MOVH`,-`MOVW`,-`REV16W`,-`REVW` - // amd64/v1,amd64/v2:`MOVQ\s[A-Z]+,\s1\([A-Z]+\)`,-`MOVB`,-`MOVW`,-`MOVL` - // amd64/v3:`MOVBEQ\s[A-Z]+,\s1\([A-Z]+\)`, -`MOVBEL` + // amd64:`MOVQ\s[A-Z]+,\s1\([A-Z]+\)`,-`MOVB`,-`MOVW`,-`MOVL` b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8] = byte(val>>56), byte(val>>48), byte(val>>40), byte(val>>32), byte(val>>24), byte(val>>16), byte(val>>8), byte(val) } -- GitLab From bde0463da3f31934791b0bb2ccacdf6206314073 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Sat, 16 Oct 2021 03:59:41 +1100 Subject: [PATCH 1648/2500] cmd/internal/obj/riscv: fix trampoline calls from large functions On riscv64, the JAL instruction is only capable of reaching +/-1MB. In the case where a single function and its trampolines exceeds this size, it is possible that the JAL is unable to reach the trampoline, which is laid down after the function text. In the case of large functions, switch back to using a AUIPC+JALR pairs rather than using trampolines. Fixes #48791 Change-Id: I119cf3bc20ce4933a9b7ab41a8e514437c6addb9 Reviewed-on: https://go-review.googlesource.com/c/go/+/356250 Trust: Joel Sing Reviewed-by: Cherry Mui --- src/cmd/internal/obj/riscv/asm_test.go | 95 ++++++++++++++++++++++---- src/cmd/internal/obj/riscv/obj.go | 36 ++++++++-- 2 files changed, 113 insertions(+), 18 deletions(-) diff --git a/src/cmd/internal/obj/riscv/asm_test.go b/src/cmd/internal/obj/riscv/asm_test.go index 684c6b61f2..b23142dbe8 100644 --- a/src/cmd/internal/obj/riscv/asm_test.go +++ b/src/cmd/internal/obj/riscv/asm_test.go @@ -16,32 +16,30 @@ import ( "testing" ) -// TestLarge generates a very large file to verify that large -// program builds successfully, in particular, too-far -// conditional branches are fixed. -func TestLarge(t *testing.T) { +// TestLargeBranch generates a large function with a very far conditional +// branch, in order to ensure that it assembles successfully. +func TestLargeBranch(t *testing.T) { if testing.Short() { - t.Skip("Skip in short mode") + t.Skip("Skipping test in short mode") } testenv.MustHaveGoBuild(t) - dir, err := ioutil.TempDir("", "testlarge") + dir, err := ioutil.TempDir("", "testlargebranch") if err != nil { - t.Fatalf("could not create directory: %v", err) + t.Fatalf("Could not create directory: %v", err) } defer os.RemoveAll(dir) // Generate a very large function. buf := bytes.NewBuffer(make([]byte, 0, 7000000)) - gen(buf) + genLargeBranch(buf) tmpfile := filepath.Join(dir, "x.s") - err = ioutil.WriteFile(tmpfile, buf.Bytes(), 0644) - if err != nil { - t.Fatalf("can't write output: %v\n", err) + if err := ioutil.WriteFile(tmpfile, buf.Bytes(), 0644); err != nil { + t.Fatalf("Failed to write file: %v", err) } - // Build generated file. + // Assemble generated file. cmd := exec.Command(testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), tmpfile) cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux") out, err := cmd.CombinedOutput() @@ -50,8 +48,7 @@ func TestLarge(t *testing.T) { } } -// gen generates a very large program, with a very far conditional branch. -func gen(buf *bytes.Buffer) { +func genLargeBranch(buf *bytes.Buffer) { fmt.Fprintln(buf, "TEXT f(SB),0,$0-0") fmt.Fprintln(buf, "BEQ X0, X0, label") for i := 0; i < 1<<19; i++ { @@ -61,6 +58,76 @@ func gen(buf *bytes.Buffer) { fmt.Fprintln(buf, "ADD $0, X0, X0") } +// TestLargeCall generates a large function (>1MB of text) with a call to +// a following function, in order to ensure that it assembles and links +// correctly. +func TestLargeCall(t *testing.T) { + if testing.Short() { + t.Skip("Skipping test in short mode") + } + testenv.MustHaveGoBuild(t) + + dir, err := ioutil.TempDir("", "testlargecall") + if err != nil { + t.Fatalf("could not create directory: %v", err) + } + defer os.RemoveAll(dir) + + if err := ioutil.WriteFile(filepath.Join(dir, "go.mod"), []byte("module largecall"), 0644); err != nil { + t.Fatalf("Failed to write file: %v\n", err) + } + main := `package main +func main() { + x() +} + +func x() +func y() +` + if err := ioutil.WriteFile(filepath.Join(dir, "x.go"), []byte(main), 0644); err != nil { + t.Fatalf("failed to write main: %v\n", err) + } + + // Generate a very large function with call. + buf := bytes.NewBuffer(make([]byte, 0, 7000000)) + genLargeCall(buf) + + if err := ioutil.WriteFile(filepath.Join(dir, "x.s"), buf.Bytes(), 0644); err != nil { + t.Fatalf("Failed to write file: %v\n", err) + } + + // Build generated files. + cmd := exec.Command(testenv.GoToolPath(t), "build", "-ldflags=-linkmode=internal") + cmd.Dir = dir + cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux") + out, err := cmd.CombinedOutput() + if err != nil { + t.Errorf("Build failed: %v, output: %s", err, out) + } + + if runtime.GOARCH == "riscv64" && testenv.HasCGO() { + cmd := exec.Command(testenv.GoToolPath(t), "build", "-ldflags=-linkmode=external") + cmd.Dir = dir + cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux") + out, err := cmd.CombinedOutput() + if err != nil { + t.Errorf("Build failed: %v, output: %s", err, out) + } + } +} + +func genLargeCall(buf *bytes.Buffer) { + fmt.Fprintln(buf, "TEXT ·x(SB),0,$0-0") + fmt.Fprintln(buf, "CALL ·y(SB)") + for i := 0; i < 1<<19; i++ { + fmt.Fprintln(buf, "ADD $0, X0, X0") + } + fmt.Fprintln(buf, "RET") + fmt.Fprintln(buf, "TEXT ·y(SB),0,$0-0") + fmt.Fprintln(buf, "ADD $0, X0, X0") + fmt.Fprintln(buf, "RET") +} + // Issue 20348. func TestNoRet(t *testing.T) { dir, err := ioutil.TempDir("", "testnoret") diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index b346b13577..d98806edb5 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -280,14 +280,15 @@ func containsCall(sym *obj.LSym) bool { } // setPCs sets the Pc field in all instructions reachable from p. -// It uses pc as the initial value. -func setPCs(p *obj.Prog, pc int64) { +// It uses pc as the initial value and returns the next available pc. +func setPCs(p *obj.Prog, pc int64) int64 { for ; p != nil; p = p.Link { p.Pc = pc for _, ins := range instructionsForProg(p) { pc += int64(ins.length()) } } + return pc } // stackOffset updates Addr offsets based on the current stack size. @@ -582,17 +583,26 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { } } + var callCount int for p := cursym.Func().Text; p != nil; p = p.Link { markRelocs(p) + if p.Mark&NEED_CALL_RELOC == NEED_CALL_RELOC { + callCount++ + } } + const callTrampSize = 8 // 2 machine instructions. + maxTrampSize := int64(callCount * callTrampSize) // Compute instruction addresses. Once we do that, we need to check for // overextended jumps and branches. Within each iteration, Pc differences // are always lower bounds (since the program gets monotonically longer, // a fixed point will be reached). No attempt to handle functions > 2GiB. for { - rescan := false - setPCs(cursym.Func().Text, 0) + big, rescan := false, false + maxPC := setPCs(cursym.Func().Text, 0) + if maxPC+maxTrampSize > (1 << 20) { + big = true + } for p := cursym.Func().Text; p != nil; p = p.Link { switch p.As { @@ -619,6 +629,24 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { case AJAL: // Linker will handle the intersymbol case and trampolines. if p.To.Target() == nil { + if !big { + break + } + // This function is going to be too large for JALs + // to reach trampolines. Replace with AUIPC+JALR. + jmp := obj.Appendp(p, newprog) + jmp.As = AJALR + jmp.From = p.From + jmp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP} + + p.As = AAUIPC + p.Mark = (p.Mark &^ NEED_CALL_RELOC) | NEED_PCREL_ITYPE_RELOC + p.SetFrom3(obj.Addr{Type: obj.TYPE_CONST, Offset: p.To.Offset, Sym: p.To.Sym}) + p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: 0} + p.Reg = obj.REG_NONE + p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP} + + rescan = true break } offset := p.To.Target().Pc - p.Pc -- GitLab From 6294207a1c79e318124850155c7b6c23997c8c13 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 18 Oct 2021 16:15:43 -0400 Subject: [PATCH 1649/2500] cmd/go: skip flaky fuzz tests (Temporarily, until they can be fixed.) For #49046 For #49047 Change-Id: Ib580a5e45a0955aabdfc1899ed38a262a37f66ab Reviewed-on: https://go-review.googlesource.com/c/go/+/356649 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Roland Shoemaker Reviewed-by: Katie Hockman --- src/cmd/go/testdata/script/test_fuzz_fuzztime.txt | 2 ++ src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt index 9c9972f9e9..6264aca17d 100644 --- a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt +++ b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt @@ -1,3 +1,5 @@ +skip # Flaky: https://golang.org/issue/49046 + # TODO(jayconrod): support shared memory on more platforms. [!darwin] [!linux] [!windows] skip diff --git a/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt b/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt index 0924ed37e6..f2952c349b 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt @@ -1,3 +1,5 @@ +skip # Flaky: https://golang.org/issue/49047 + # TODO(jayconrod): support shared memory on more platforms. [!darwin] [!linux] [!windows] skip -- GitLab From 067d796549242bec2d33226c9da1e67f092a7be2 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Thu, 14 Oct 2021 12:32:58 -0400 Subject: [PATCH 1650/2500] testing: write output to buffer when fuzzing Fixes #48709 Change-Id: Ia6376a2f792946498d6565a53605b3e6c985ea7c Reviewed-on: https://go-review.googlesource.com/c/go/+/355909 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Jay Conrod Reviewed-by: Roland Shoemaker Reviewed-by: Bryan C. Mills --- .../go/testdata/script/test_fuzz_minimize.txt | 20 +++++++++++-- .../script/test_fuzz_minimize_interesting.txt | 2 +- src/testing/fuzz.go | 28 +++++++++++++------ 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize.txt b/src/cmd/go/testdata/script/test_fuzz_minimize.txt index 8b11621bbd..3293e878bb 100644 --- a/src/cmd/go/testdata/script/test_fuzz_minimize.txt +++ b/src/cmd/go/testdata/script/test_fuzz_minimize.txt @@ -31,7 +31,7 @@ stdout FAIL ! go test -fuzz=FuzzMinimizeZeroLimitSet -run=FuzzMinimizeZeroLimitSet -fuzztime=10000x -fuzzminimizetime=0x . ! stdout '^ok' ! stdout 'minimizing' -stdout 'there was an Error' +stdout -count=1 'there was an Error' stdout FAIL # Test that minimization is working for recoverable errors. @@ -49,11 +49,27 @@ go run ./check_testdata FuzzMinimizerRecoverable 50 ! go test -run=FuzzMinimizerRecoverable . rm testdata +# Test that minimization is working for recoverable errors. Run it with -v this +# time to ensure the command line output still looks right. +! go test -v -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x . +! stdout '^ok' +stdout 'got the minimum size!' +# The error message that was printed should be for the one written to testdata. +stdout 'contains a non-zero byte of length 50' +stdout FAIL + +# Check that the bytes written to testdata are of length 50 (the minimum size) +go run ./check_testdata FuzzMinimizerRecoverable 50 + +# Test that re-running the minimized value causes a crash. +! go test -run=FuzzMinimizerRecoverable . +rm testdata + # Test that minimization doesn't run for non-recoverable errors. ! go test -fuzz=FuzzMinimizerNonrecoverable -run=FuzzMinimizerNonrecoverable -fuzztime=10000x . ! stdout '^ok' ! stdout 'minimizing' -stdout 'fuzzing process terminated unexpectedly: exit status 99' +stdout -count=1 'fuzzing process terminated unexpectedly: exit status 99' stdout FAIL # Check that re-running the value causes a crash. diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt b/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt index fc66201eb3..8ea4cdb8a5 100644 --- a/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt +++ b/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt @@ -29,7 +29,7 @@ env GOCACHE=$WORK/gocache ! exec ./fuzz.test$GOEXE -test.fuzzcachedir=$GOCACHE/fuzz -test.fuzz=FuzzMinimizerCrashInMinimization -test.fuzztime=10000x -test.parallel=1 ! stdout '^ok' stdout 'got the minimum size!' -stdout 'flaky failure' +stdout -count=1 'flaky failure' stdout FAIL # Make sure the crash that was written will fail when run with go test diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 0429f8243d..d5cb5e853f 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -5,6 +5,7 @@ package testing import ( + "bytes" "errors" "flag" "fmt" @@ -367,14 +368,14 @@ func (f *F) Fuzz(ff interface{}) { // run calls fn on a given input, as a subtest with its own T. // run is analogous to T.Run. The test filtering and cleanup works similarly. // fn is called in its own goroutine. - run := func(e corpusEntry) error { + run := func(captureOut io.Writer, e corpusEntry) (ok bool) { if e.Values == nil { // The corpusEntry must have non-nil Values in order to run the // test. If Values is nil, it is a bug in our code. panic(fmt.Sprintf("corpus file %q was not unmarshaled", e.Path)) } if shouldFailFast() { - return nil + return true } testName := f.name if e.Path != "" { @@ -405,6 +406,10 @@ func (f *F) Fuzz(ff interface{}) { }, context: f.testContext, } + if captureOut != nil { + // t.parent aliases f.common. + t.parent.w = captureOut + } t.w = indenter{&t.common} if t.chatty != nil { // TODO(#48132): adjust this to work with test2json. @@ -426,10 +431,7 @@ func (f *F) Fuzz(ff interface{}) { }) <-t.signal f.inFuzzFn = false - if t.Failed() { - return errors.New(string(f.output)) - } - return nil + return !t.Failed() } switch f.fuzzContext.mode { @@ -466,7 +468,17 @@ func (f *F) Fuzz(ff interface{}) { case fuzzWorker: // Fuzzing is enabled, and this is a worker process. Follow instructions // from the coordinator. - if err := f.fuzzContext.deps.RunFuzzWorker(run); err != nil { + if err := f.fuzzContext.deps.RunFuzzWorker(func(e corpusEntry) error { + // Don't write to f.w (which points to Stdout) if running from a + // fuzz worker. This would become very verbose, particularly during + // minimization. Return the error instead, and let the caller deal + // with the output. + var buf bytes.Buffer + if ok := run(&buf, e); !ok { + return errors.New(buf.String()) + } + return nil + }); err != nil { // Internal errors are marked with f.Fail; user code may call this too, before F.Fuzz. // The worker will exit with fuzzWorkerExitCode, indicating this is a failure // (and 'go test' should exit non-zero) but a crasher should not be recorded. @@ -479,7 +491,7 @@ func (f *F) Fuzz(ff interface{}) { for _, e := range f.corpus { name := fmt.Sprintf("%s/%s", f.name, filepath.Base(e.Path)) if _, ok, _ := f.testContext.match.fullName(nil, name); ok { - run(e) + run(f.w, e) } } } -- GitLab From fe7df4c4d043fc65800bbec7f575c1ba50327aa9 Mon Sep 17 00:00:00 2001 From: wdvxdr Date: Tue, 19 Oct 2021 19:39:21 +0800 Subject: [PATCH 1651/2500] cmd/compile: use MOVBE instruction for GOAMD64>=v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In CL 354670, I copied some existing rules for convenience but forgot to update the last rule which broke `GOAMD64=v3 ./make.bat` Revive CL 354670 Change-Id: Ic1e2047c603f0122482a4b293ce1ef74d806c019 Reviewed-on: https://go-review.googlesource.com/c/go/+/356810 Reviewed-by: Daniel Martí Reviewed-by: Keith Randall Trust: Daniel Martí Run-TryBot: Daniel Martí TryBot-Result: Go Bot --- src/cmd/compile/internal/amd64/ssa.go | 7 +- .../compile/internal/amd64/versions_test.go | 27 +- src/cmd/compile/internal/ssa/gen/AMD64.rules | 26 ++ src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 6 + src/cmd/compile/internal/ssa/opGen.go | 64 +++++ src/cmd/compile/internal/ssa/rewriteAMD64.go | 243 ++++++++++++++++++ test/codegen/memcombine.go | 36 ++- 7 files changed, 389 insertions(+), 20 deletions(-) diff --git a/src/cmd/compile/internal/amd64/ssa.go b/src/cmd/compile/internal/amd64/ssa.go index 0e74574422..b0e5c34030 100644 --- a/src/cmd/compile/internal/amd64/ssa.go +++ b/src/cmd/compile/internal/amd64/ssa.go @@ -772,7 +772,9 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.From.Val = math.Float64frombits(uint64(v.AuxInt)) p.To.Type = obj.TYPE_REG p.To.Reg = x - case ssa.OpAMD64MOVQload, ssa.OpAMD64MOVSSload, ssa.OpAMD64MOVSDload, ssa.OpAMD64MOVLload, ssa.OpAMD64MOVWload, ssa.OpAMD64MOVBload, ssa.OpAMD64MOVBQSXload, ssa.OpAMD64MOVWQSXload, ssa.OpAMD64MOVLQSXload, ssa.OpAMD64MOVOload: + case ssa.OpAMD64MOVQload, ssa.OpAMD64MOVLload, ssa.OpAMD64MOVWload, ssa.OpAMD64MOVBload, ssa.OpAMD64MOVOload, + ssa.OpAMD64MOVSSload, ssa.OpAMD64MOVSDload, ssa.OpAMD64MOVBQSXload, ssa.OpAMD64MOVWQSXload, ssa.OpAMD64MOVLQSXload, + ssa.OpAMD64MOVBEQload, ssa.OpAMD64MOVBELload: p := s.Prog(v.Op.Asm()) p.From.Type = obj.TYPE_MEM p.From.Reg = v.Args[0].Reg() @@ -788,7 +790,8 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.To.Reg = v.Reg() case ssa.OpAMD64MOVQstore, ssa.OpAMD64MOVSSstore, ssa.OpAMD64MOVSDstore, ssa.OpAMD64MOVLstore, ssa.OpAMD64MOVWstore, ssa.OpAMD64MOVBstore, ssa.OpAMD64MOVOstore, ssa.OpAMD64ADDQmodify, ssa.OpAMD64SUBQmodify, ssa.OpAMD64ANDQmodify, ssa.OpAMD64ORQmodify, ssa.OpAMD64XORQmodify, - ssa.OpAMD64ADDLmodify, ssa.OpAMD64SUBLmodify, ssa.OpAMD64ANDLmodify, ssa.OpAMD64ORLmodify, ssa.OpAMD64XORLmodify: + ssa.OpAMD64ADDLmodify, ssa.OpAMD64SUBLmodify, ssa.OpAMD64ANDLmodify, ssa.OpAMD64ORLmodify, ssa.OpAMD64XORLmodify, + ssa.OpAMD64MOVBEQstore, ssa.OpAMD64MOVBELstore: p := s.Prog(v.Op.Asm()) p.From.Type = obj.TYPE_REG p.From.Reg = v.Args[1].Reg() diff --git a/src/cmd/compile/internal/amd64/versions_test.go b/src/cmd/compile/internal/amd64/versions_test.go index de677f3a69..ee1a8ca3aa 100644 --- a/src/cmd/compile/internal/amd64/versions_test.go +++ b/src/cmd/compile/internal/amd64/versions_test.go @@ -53,7 +53,9 @@ func TestGoAMD64v1(t *testing.T) { opcodes := map[string]bool{} var features []string for feature, opcodeList := range featureToOpcodes { - features = append(features, fmt.Sprintf("cpu.%s=off", feature)) + if runtimeFeatures[feature] { + features = append(features, fmt.Sprintf("cpu.%s=off", feature)) + } for _, op := range opcodeList { opcodes[op] = true } @@ -204,14 +206,28 @@ func clobber(t *testing.T, src string, dst *os.File, opcodes map[string]bool) { f.Close() } +func setOf(keys ...string) map[string]bool { + m := make(map[string]bool, len(keys)) + for _, key := range keys { + m[key] = true + } + return m +} + +var runtimeFeatures = setOf( + "adx", "aes", "avx", "avx2", "bmi1", "bmi2", "erms", "fma", + "pclmulqdq", "popcnt", "rdtscp", "sse3", "sse41", "sse42", "ssse3", +) + var featureToOpcodes = map[string][]string{ // Note: we include *q, *l, and plain opcodes here. // go tool objdump doesn't include a [QL] on popcnt instructions, until CL 351889 // native objdump doesn't include [QL] on linux. - "popcnt": []string{"popcntq", "popcntl", "popcnt"}, - "bmi1": []string{"andnq", "andnl", "andn", "blsiq", "blsil", "blsi", "blsmskq", "blsmskl", "blsmsk", "blsrq", "blsrl", "blsr", "tzcntq", "tzcntl", "tzcnt"}, - "sse41": []string{"roundsd"}, - "fma": []string{"vfmadd231sd"}, + "popcnt": {"popcntq", "popcntl", "popcnt"}, + "bmi1": {"andnq", "andnl", "andn", "blsiq", "blsil", "blsi", "blsmskq", "blsmskl", "blsmsk", "blsrq", "blsrl", "blsr", "tzcntq", "tzcntl", "tzcnt"}, + "sse41": {"roundsd"}, + "fma": {"vfmadd231sd"}, + "movbe": {"movbeqq", "movbeq", "movbell", "movbel", "movbe"}, } // Test to use POPCNT instruction, if available @@ -364,5 +380,4 @@ func TestFMA(t *testing.T) { t.Errorf("FMA(%f,%f,%f) = %f, want %f", tt.x, tt.y, tt.z, got, tt.want) } } - } diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 8b73ee14ea..47a6af003c 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -2219,3 +2219,29 @@ (AND(Q|L) x (ADD(Q|L)const [-1] x)) && buildcfg.GOAMD64 >= 3 => (BLSR(Q|L) x) (BSWAP(Q|L) (BSWAP(Q|L) p)) => p + +// CPUID feature: MOVBE. +(MOV(Q|L)store [i] {s} p x:(BSWAP(Q|L) w) mem) && x.Uses == 1 && buildcfg.GOAMD64 >= 3 => (MOVBE(Q|L)store [i] {s} p w mem) +(BSWAP(Q|L) x:(MOV(Q|L)load [i] {s} p mem)) && x.Uses == 1 && buildcfg.GOAMD64 >= 3 => (MOVBE(Q|L)load [i] {s} p mem) +(BSWAP(Q|L) (MOVBE(Q|L)load [i] {s} p m)) => (MOV(Q|L)load [i] {s} p m) +(MOVBE(Q|L)store [i] {s} p (BSWAP(Q|L) x) m) => (MOV(Q|L)store [i] {s} p x m) + +(ORQ x0:(MOVBELload [i0] {s} p mem) + sh:(SHLQconst [32] x1:(MOVBELload [i1] {s} p mem))) + && i0 == i1+4 + && x0.Uses == 1 + && x1.Uses == 1 + && sh.Uses == 1 + && mergePoint(b,x0,x1) != nil + && clobber(x0, x1, sh) + => @mergePoint(b,x0,x1) (MOVBEQload [i1] {s} p mem) + +(ORQ x0:(MOVBELload [i] {s} p0 mem) + sh:(SHLQconst [32] x1:(MOVBELload [i] {s} p1 mem))) + && x0.Uses == 1 + && x1.Uses == 1 + && sh.Uses == 1 + && sequentialAddresses(p1, p0, 4) + && mergePoint(b,x0,x1) != nil + && clobber(x0, x1, sh) + => @mergePoint(b,x0,x1) (MOVBEQload [i] {s} p1 mem) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index 731454c761..e3c94e4b2e 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -922,6 +922,12 @@ func init() { // and BSFQ(0) is undefined. Same for TZCNTL(0)==32 {name: "TZCNTQ", argLength: 1, reg: gp11, asm: "TZCNTQ", clobberFlags: true}, {name: "TZCNTL", argLength: 1, reg: gp11, asm: "TZCNTL", clobberFlags: true}, + + // CPUID feature: MOVBE + {name: "MOVBELload", argLength: 2, reg: gpload, asm: "MOVBEL", aux: "SymOff", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"}, // load and swap 4 bytes from arg0+auxint+aux. arg1=mem. Zero extend. + {name: "MOVBELstore", argLength: 3, reg: gpstore, asm: "MOVBEL", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // swap and store 4 bytes in arg1 to arg0+auxint+aux. arg2=mem + {name: "MOVBEQload", argLength: 2, reg: gpload, asm: "MOVBEQ", aux: "SymOff", typ: "UInt64", faultOnNilArg0: true, symEffect: "Read"}, // load and swap 8 bytes from arg0+auxint+aux. arg1=mem + {name: "MOVBEQstore", argLength: 3, reg: gpstore, asm: "MOVBEQ", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // swap and store 8 bytes in arg1 to arg0+auxint+aux. arg2=mem } var AMD64blocks = []blockData{ diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 640e517fe7..091f43f40a 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -1043,6 +1043,10 @@ const ( OpAMD64BLSRL OpAMD64TZCNTQ OpAMD64TZCNTL + OpAMD64MOVBELload + OpAMD64MOVBELstore + OpAMD64MOVBEQload + OpAMD64MOVBEQstore OpARMADD OpARMADDconst @@ -13780,6 +13784,66 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "MOVBELload", + auxType: auxSymOff, + argLen: 2, + faultOnNilArg0: true, + symEffect: SymRead, + asm: x86.AMOVBEL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB + }, + outputs: []outputInfo{ + {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + }, + }, + }, + { + name: "MOVBELstore", + auxType: auxSymOff, + argLen: 3, + faultOnNilArg0: true, + symEffect: SymWrite, + asm: x86.AMOVBEL, + reg: regInfo{ + inputs: []inputInfo{ + {1, 49151}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15 + {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB + }, + }, + }, + { + name: "MOVBEQload", + auxType: auxSymOff, + argLen: 2, + faultOnNilArg0: true, + symEffect: SymRead, + asm: x86.AMOVBEQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB + }, + outputs: []outputInfo{ + {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 + }, + }, + }, + { + name: "MOVBEQstore", + auxType: auxSymOff, + argLen: 3, + faultOnNilArg0: true, + symEffect: SymWrite, + asm: x86.AMOVBEQ, + reg: regInfo{ + inputs: []inputInfo{ + {1, 49151}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R15 + {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 g R15 SB + }, + }, + }, { name: "ADD", diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 201fbf2954..0c789d6b49 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -222,6 +222,10 @@ func rewriteValueAMD64(v *Value) bool { return rewriteValueAMD64_OpAMD64LEAQ4(v) case OpAMD64LEAQ8: return rewriteValueAMD64_OpAMD64LEAQ8(v) + case OpAMD64MOVBELstore: + return rewriteValueAMD64_OpAMD64MOVBELstore(v) + case OpAMD64MOVBEQstore: + return rewriteValueAMD64_OpAMD64MOVBEQstore(v) case OpAMD64MOVBQSX: return rewriteValueAMD64_OpAMD64MOVBQSX(v) case OpAMD64MOVBQSXload: @@ -3623,6 +3627,43 @@ func rewriteValueAMD64_OpAMD64BSWAPL(v *Value) bool { v.copyOf(p) return true } + // match: (BSWAPL x:(MOVLload [i] {s} p mem)) + // cond: x.Uses == 1 && buildcfg.GOAMD64 >= 3 + // result: (MOVBELload [i] {s} p mem) + for { + x := v_0 + if x.Op != OpAMD64MOVLload { + break + } + i := auxIntToInt32(x.AuxInt) + s := auxToSym(x.Aux) + mem := x.Args[1] + p := x.Args[0] + if !(x.Uses == 1 && buildcfg.GOAMD64 >= 3) { + break + } + v.reset(OpAMD64MOVBELload) + v.AuxInt = int32ToAuxInt(i) + v.Aux = symToAux(s) + v.AddArg2(p, mem) + return true + } + // match: (BSWAPL (MOVBELload [i] {s} p m)) + // result: (MOVLload [i] {s} p m) + for { + if v_0.Op != OpAMD64MOVBELload { + break + } + i := auxIntToInt32(v_0.AuxInt) + s := auxToSym(v_0.Aux) + m := v_0.Args[1] + p := v_0.Args[0] + v.reset(OpAMD64MOVLload) + v.AuxInt = int32ToAuxInt(i) + v.Aux = symToAux(s) + v.AddArg2(p, m) + return true + } return false } func rewriteValueAMD64_OpAMD64BSWAPQ(v *Value) bool { @@ -3637,6 +3678,43 @@ func rewriteValueAMD64_OpAMD64BSWAPQ(v *Value) bool { v.copyOf(p) return true } + // match: (BSWAPQ x:(MOVQload [i] {s} p mem)) + // cond: x.Uses == 1 && buildcfg.GOAMD64 >= 3 + // result: (MOVBEQload [i] {s} p mem) + for { + x := v_0 + if x.Op != OpAMD64MOVQload { + break + } + i := auxIntToInt32(x.AuxInt) + s := auxToSym(x.Aux) + mem := x.Args[1] + p := x.Args[0] + if !(x.Uses == 1 && buildcfg.GOAMD64 >= 3) { + break + } + v.reset(OpAMD64MOVBEQload) + v.AuxInt = int32ToAuxInt(i) + v.Aux = symToAux(s) + v.AddArg2(p, mem) + return true + } + // match: (BSWAPQ (MOVBEQload [i] {s} p m)) + // result: (MOVQload [i] {s} p m) + for { + if v_0.Op != OpAMD64MOVBEQload { + break + } + i := auxIntToInt32(v_0.AuxInt) + s := auxToSym(v_0.Aux) + m := v_0.Args[1] + p := v_0.Args[0] + v.reset(OpAMD64MOVQload) + v.AuxInt = int32ToAuxInt(i) + v.Aux = symToAux(s) + v.AddArg2(p, m) + return true + } return false } func rewriteValueAMD64_OpAMD64BTCLconst(v *Value) bool { @@ -9395,6 +9473,52 @@ func rewriteValueAMD64_OpAMD64LEAQ8(v *Value) bool { } return false } +func rewriteValueAMD64_OpAMD64MOVBELstore(v *Value) bool { + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] + // match: (MOVBELstore [i] {s} p (BSWAPL x) m) + // result: (MOVLstore [i] {s} p x m) + for { + i := auxIntToInt32(v.AuxInt) + s := auxToSym(v.Aux) + p := v_0 + if v_1.Op != OpAMD64BSWAPL { + break + } + x := v_1.Args[0] + m := v_2 + v.reset(OpAMD64MOVLstore) + v.AuxInt = int32ToAuxInt(i) + v.Aux = symToAux(s) + v.AddArg3(p, x, m) + return true + } + return false +} +func rewriteValueAMD64_OpAMD64MOVBEQstore(v *Value) bool { + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] + // match: (MOVBEQstore [i] {s} p (BSWAPQ x) m) + // result: (MOVQstore [i] {s} p x m) + for { + i := auxIntToInt32(v.AuxInt) + s := auxToSym(v.Aux) + p := v_0 + if v_1.Op != OpAMD64BSWAPQ { + break + } + x := v_1.Args[0] + m := v_2 + v.reset(OpAMD64MOVQstore) + v.AuxInt = int32ToAuxInt(i) + v.Aux = symToAux(s) + v.AddArg3(p, x, m) + return true + } + return false +} func rewriteValueAMD64_OpAMD64MOVBQSX(v *Value) bool { v_0 := v.Args[0] b := v.Block @@ -12225,6 +12349,28 @@ func rewriteValueAMD64_OpAMD64MOVLstore(v *Value) bool { v.AddArg3(ptr, val, mem) return true } + // match: (MOVLstore [i] {s} p x:(BSWAPL w) mem) + // cond: x.Uses == 1 && buildcfg.GOAMD64 >= 3 + // result: (MOVBELstore [i] {s} p w mem) + for { + i := auxIntToInt32(v.AuxInt) + s := auxToSym(v.Aux) + p := v_0 + x := v_1 + if x.Op != OpAMD64BSWAPL { + break + } + w := x.Args[0] + mem := v_2 + if !(x.Uses == 1 && buildcfg.GOAMD64 >= 3) { + break + } + v.reset(OpAMD64MOVBELstore) + v.AuxInt = int32ToAuxInt(i) + v.Aux = symToAux(s) + v.AddArg3(p, w, mem) + return true + } return false } func rewriteValueAMD64_OpAMD64MOVLstoreconst(v *Value) bool { @@ -13164,6 +13310,28 @@ func rewriteValueAMD64_OpAMD64MOVQstore(v *Value) bool { v.AddArg3(ptr, val, mem) return true } + // match: (MOVQstore [i] {s} p x:(BSWAPQ w) mem) + // cond: x.Uses == 1 && buildcfg.GOAMD64 >= 3 + // result: (MOVBEQstore [i] {s} p w mem) + for { + i := auxIntToInt32(v.AuxInt) + s := auxToSym(v.Aux) + p := v_0 + x := v_1 + if x.Op != OpAMD64BSWAPQ { + break + } + w := x.Args[0] + mem := v_2 + if !(x.Uses == 1 && buildcfg.GOAMD64 >= 3) { + break + } + v.reset(OpAMD64MOVBEQstore) + v.AuxInt = int32ToAuxInt(i) + v.Aux = symToAux(s) + v.AddArg3(p, w, mem) + return true + } return false } func rewriteValueAMD64_OpAMD64MOVQstoreconst(v *Value) bool { @@ -18657,6 +18825,81 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool { } break } + // match: (ORQ x0:(MOVBELload [i0] {s} p mem) sh:(SHLQconst [32] x1:(MOVBELload [i1] {s} p mem))) + // cond: i0 == i1+4 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) + // result: @mergePoint(b,x0,x1) (MOVBEQload [i1] {s} p mem) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x0 := v_0 + if x0.Op != OpAMD64MOVBELload { + continue + } + i0 := auxIntToInt32(x0.AuxInt) + s := auxToSym(x0.Aux) + mem := x0.Args[1] + p := x0.Args[0] + sh := v_1 + if sh.Op != OpAMD64SHLQconst || auxIntToInt8(sh.AuxInt) != 32 { + continue + } + x1 := sh.Args[0] + if x1.Op != OpAMD64MOVBELload { + continue + } + i1 := auxIntToInt32(x1.AuxInt) + if auxToSym(x1.Aux) != s { + continue + } + _ = x1.Args[1] + if p != x1.Args[0] || mem != x1.Args[1] || !(i0 == i1+4 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { + continue + } + b = mergePoint(b, x0, x1) + v0 := b.NewValue0(x1.Pos, OpAMD64MOVBEQload, typ.UInt64) + v.copyOf(v0) + v0.AuxInt = int32ToAuxInt(i1) + v0.Aux = symToAux(s) + v0.AddArg2(p, mem) + return true + } + break + } + // match: (ORQ x0:(MOVBELload [i] {s} p0 mem) sh:(SHLQconst [32] x1:(MOVBELload [i] {s} p1 mem))) + // cond: x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p1, p0, 4) && mergePoint(b,x0,x1) != nil && clobber(x0, x1, sh) + // result: @mergePoint(b,x0,x1) (MOVBEQload [i] {s} p1 mem) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x0 := v_0 + if x0.Op != OpAMD64MOVBELload { + continue + } + i := auxIntToInt32(x0.AuxInt) + s := auxToSym(x0.Aux) + mem := x0.Args[1] + p0 := x0.Args[0] + sh := v_1 + if sh.Op != OpAMD64SHLQconst || auxIntToInt8(sh.AuxInt) != 32 { + continue + } + x1 := sh.Args[0] + if x1.Op != OpAMD64MOVBELload || auxIntToInt32(x1.AuxInt) != i || auxToSym(x1.Aux) != s { + continue + } + _ = x1.Args[1] + p1 := x1.Args[0] + if mem != x1.Args[1] || !(x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && sequentialAddresses(p1, p0, 4) && mergePoint(b, x0, x1) != nil && clobber(x0, x1, sh)) { + continue + } + b = mergePoint(b, x0, x1) + v0 := b.NewValue0(x1.Pos, OpAMD64MOVBEQload, typ.UInt64) + v.copyOf(v0) + v0.AuxInt = int32ToAuxInt(i) + v0.Aux = symToAux(s) + v0.AddArg2(p1, mem) + return true + } + break + } return false } func rewriteValueAMD64_OpAMD64ORQconst(v *Value) bool { diff --git a/test/codegen/memcombine.go b/test/codegen/memcombine.go index 2a0c534df0..97e1d4bdfb 100644 --- a/test/codegen/memcombine.go +++ b/test/codegen/memcombine.go @@ -70,7 +70,8 @@ func load_le16_idx(b []byte, idx int) { } func load_be64(b []byte) { - // amd64:`BSWAPQ`,-`MOV[BWL]\t[^$]`,-`OR` + // amd64/v1,amd64/v2:`BSWAPQ`,-`MOV[BWL]\t[^$]`,-`OR` + // amd64/v3:`MOVBEQ` // s390x:`MOVD\s\(.*\),` // arm64:`REV`,`MOVD\s\(R[0-9]+\),`,-`MOV[BHW]`,-`REVW`,-`REV16W` // ppc64le:`MOVDBR`,-`MOV[BHW]Z` @@ -78,7 +79,8 @@ func load_be64(b []byte) { } func load_be64_idx(b []byte, idx int) { - // amd64:`BSWAPQ`,-`MOV[BWL]\t[^$]`,-`OR` + // amd64/v1,amd64/v2:`BSWAPQ`,-`MOV[BWL]\t[^$]`,-`OR` + // amd64/v3: `MOVBEQ` // s390x:`MOVD\s\(.*\)\(.*\*1\),` // arm64:`REV`,`MOVD\s\(R[0-9]+\)\(R[0-9]+\),`,-`MOV[WHB]`,-`REVW`,-`REV16W` // ppc64le:`MOVDBR`,-`MOV[BHW]Z` @@ -86,7 +88,8 @@ func load_be64_idx(b []byte, idx int) { } func load_be32(b []byte) { - // amd64:`BSWAPL`,-`MOV[BW]`,-`OR` + // amd64/v1,amd64/v2:`BSWAPL`,-`MOV[BW]`,-`OR` + // amd64/v3: `MOVBEL` // s390x:`MOVWZ\s\(.*\),` // arm64:`REVW`,`MOVWU\s\(R[0-9]+\),`,-`MOV[BH]`,-`REV16W` // ppc64le:`MOVWBR`,-`MOV[BH]Z` @@ -94,7 +97,8 @@ func load_be32(b []byte) { } func load_be32_idx(b []byte, idx int) { - // amd64:`BSWAPL`,-`MOV[BW]`,-`OR` + // amd64/v1,amd64/v2:`BSWAPL`,-`MOV[BW]`,-`OR` + // amd64/v3: `MOVBEL` // s390x:`MOVWZ\s\(.*\)\(.*\*1\),` // arm64:`REVW`,`MOVWU\s\(R[0-9]+\)\(R[0-9]+\),`,-`MOV[HB]`,-`REV16W` // ppc64le:`MOVWBR`,-`MOV[BH]Z` @@ -179,7 +183,8 @@ func load_be_byte4_uint32(s []byte) uint32 { func load_be_byte4_uint32_inv(s []byte) uint32 { // arm64:`MOVWU\t\(R[0-9]+\)`,`REVW`,-`ORR`,-`REV16W`,-`MOV[BH]` - // amd64:`MOVL\s\([A-Z]+\)`,`BSWAPL`,-`MOV[BW]`,-`OR` + // amd64/v1,amd64/v2:`MOVL\s\([A-Z]+\)`,`BSWAPL`,-`MOV[BW]`,-`OR` + // amd64/v3: `MOVBEL` return uint32(s[3]) | uint32(s[2])<<8 | uint32(s[1])<<16 | uint32(s[0])<<24 } @@ -191,7 +196,8 @@ func load_be_byte8_uint64(s []byte) uint64 { func load_be_byte8_uint64_inv(s []byte) uint64 { // arm64:`MOVD\t\(R[0-9]+\)`,`REV`,-`ORR`,-`REVW`,-`REV16W`,-`MOV[BHW]` - // amd64:`MOVQ\s\([A-Z]+\),\s[A-Z]+`,`BSWAPQ`,-`MOV[BWL]\t[^$]`,-`OR` + // amd64/v1,amd64/v2:`MOVQ\s\([A-Z]+\),\s[A-Z]+`,`BSWAPQ`,-`MOV[BWL]\t[^$]`,-`OR` + // amd64/v3: `MOVBEQ` // ppc64le:`MOVDBR\t\(R[0-9]+\)`,-`MOV[BHW]Z` return uint64(s[7]) | uint64(s[6])<<8 | uint64(s[5])<<16 | uint64(s[4])<<24 | uint64(s[3])<<32 | uint64(s[2])<<40 | uint64(s[1])<<48 | uint64(s[0])<<56 } @@ -409,7 +415,8 @@ func store_le16_idx(b []byte, idx int) { } func store_be64(b []byte) { - // amd64:`BSWAPQ`,-`SHR.` + // amd64/v1,amd64/v2:`BSWAPQ`,-`SHR.` + // amd64/v3: `MOVBEQ` // arm64:`MOVD`,`REV`,-`MOV[WBH]`,-`REVW`,-`REV16W` // ppc64le:`MOVDBR` // s390x:`MOVD\s.*\(.*\)$`,-`SRW\s`,-`SRD\s` @@ -417,7 +424,8 @@ func store_be64(b []byte) { } func store_be64_idx(b []byte, idx int) { - // amd64:`BSWAPQ`,-`SHR.` + // amd64/v1,amd64/v2:`BSWAPQ`,-`SHR.` + // amd64/v3:`MOVBEQ` // arm64:`REV`,`MOVD\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOV[BHW]`,-`REV16W`,-`REVW` // ppc64le:`MOVDBR` // s390x:`MOVD\s.*\(.*\)\(.*\*1\)$`,-`SRW\s`,-`SRD\s` @@ -425,7 +433,8 @@ func store_be64_idx(b []byte, idx int) { } func store_be32(b []byte) { - // amd64:`BSWAPL`,-`SHR.` + // amd64/v1,amd64/v2:`BSWAPL`,-`SHR.` + // amd64/v3:`MOVBEL` // arm64:`MOVW`,`REVW`,-`MOV[BH]`,-`REV16W` // ppc64le:`MOVWBR` // s390x:`MOVW\s.*\(.*\)$`,-`SRW\s`,-`SRD\s` @@ -445,7 +454,8 @@ func store_be32_load(b, x *[8]byte) { } func store_be32_idx(b []byte, idx int) { - // amd64:`BSWAPL`,-`SHR.` + // amd64/v1,amd64/v2:`BSWAPL`,-`SHR.` + // amd64/v3:`MOVBEL` // arm64:`REVW`,`MOVW\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOV[BH]`,-`REV16W` // ppc64le:`MOVWBR` // s390x:`MOVW\s.*\(.*\)\(.*\*1\)$`,-`SRW\s`,-`SRD\s` @@ -508,14 +518,16 @@ func store_be_byte_2(b []byte, val uint16) { func store_be_byte_4(b []byte, val uint32) { _ = b[4] // arm64:`REVW`,`MOVW\sR[0-9]+,\s1\(R[0-9]+\)`,-`MOVB`,-`MOVH`,-`REV16W` - // amd64:`MOVL\s[A-Z]+,\s1\([A-Z]+\)`,-`MOVB`,-`MOVW` + // amd64/v1,amd64/v2:`MOVL\s[A-Z]+,\s1\([A-Z]+\)`,-`MOVB`,-`MOVW` + // amd64/v3:`MOVBEL\s[A-Z]+,\s1\([A-Z]+\)` b[1], b[2], b[3], b[4] = byte(val>>24), byte(val>>16), byte(val>>8), byte(val) } func store_be_byte_8(b []byte, val uint64) { _ = b[8] // arm64:`REV`,`MOVD\sR[0-9]+,\s1\(R[0-9]+\)`,-`MOVB`,-`MOVH`,-`MOVW`,-`REV16W`,-`REVW` - // amd64:`MOVQ\s[A-Z]+,\s1\([A-Z]+\)`,-`MOVB`,-`MOVW`,-`MOVL` + // amd64/v1,amd64/v2:`MOVQ\s[A-Z]+,\s1\([A-Z]+\)`,-`MOVB`,-`MOVW`,-`MOVL` + // amd64/v3:`MOVBEQ\s[A-Z]+,\s1\([A-Z]+\)`, -`MOVBEL` b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8] = byte(val>>56), byte(val>>48), byte(val>>40), byte(val>>32), byte(val>>24), byte(val>>16), byte(val>>8), byte(val) } -- GitLab From f92a3589fa04285dccab3ca7454eaaf2d0e7cde3 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Tue, 19 Oct 2021 16:34:43 +0700 Subject: [PATCH 1652/2500] reflect: fix methodValueCall code pointer mismatched CL 322350 changed how to take address of assembly functions, using abi.FuncPCABI0 intrinsic. But we forgot to update the code in Value.UnsafePointer (was Value.Pointer) to reflect that change. This CL fixes that bug, and also add a test to make sure the code pointer is in sync. Change-Id: I05ae7df31c706583a0f374d8af027066528f5ceb Reviewed-on: https://go-review.googlesource.com/c/go/+/356809 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/reflect/all_test.go | 8 ++++++++ src/reflect/export_test.go | 2 ++ src/reflect/makefunc.go | 6 +++++- src/reflect/value.go | 4 ++-- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index 141cc8f73d..91aac9cccb 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -7722,3 +7722,11 @@ func TestNotInHeapDeref(t *testing.T) { v = ValueOf((*nih)(unsafe.Pointer(new(int)))) shouldPanic("reflect: reflect.Value.Elem on an invalid notinheap pointer", func() { v.Elem() }) } + +func TestMethodCallValueCodePtr(t *testing.T) { + p := ValueOf(Point{}).Method(1).UnsafePointer() + want := MethodValueCallCodePtr() + if got := uintptr(p); got != want { + t.Errorf("methodValueCall code pointer mismatched, want: %v, got: %v", want, got) + } +} diff --git a/src/reflect/export_test.go b/src/reflect/export_test.go index 01749e30d8..ba7fb68067 100644 --- a/src/reflect/export_test.go +++ b/src/reflect/export_test.go @@ -161,3 +161,5 @@ func SetArgRegs(ints, floats int, floatSize uintptr) (oldInts, oldFloats int, ol clearLayoutCache() return } + +var MethodValueCallCodePtr = methodValueCallCodePtr diff --git a/src/reflect/makefunc.go b/src/reflect/makefunc.go index 588be8bcc1..d0b0935cb8 100644 --- a/src/reflect/makefunc.go +++ b/src/reflect/makefunc.go @@ -107,7 +107,7 @@ func makeMethodValue(op string, v Value) Value { // v.Type returns the actual type of the method value. ftyp := (*funcType)(unsafe.Pointer(v.Type().(*rtype))) - code := abi.FuncPCABI0(methodValueCall) + code := methodValueCallCodePtr() // methodValue contains a stack map for use by the runtime _, _, abi := funcLayout(ftyp, nil) @@ -130,6 +130,10 @@ func makeMethodValue(op string, v Value) Value { return Value{&ftyp.rtype, unsafe.Pointer(fv), v.flag&flagRO | flag(Func)} } +func methodValueCallCodePtr() uintptr { + return abi.FuncPCABI0(methodValueCall) +} + // methodValueCall is an assembly function that is the code half of // the function returned from makeMethodValue. It expects a *methodValue // as its context register, and its job is to invoke callMethod(ctxt, frame) diff --git a/src/reflect/value.go b/src/reflect/value.go index a272714ac9..1d385f6bf9 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -2488,8 +2488,8 @@ func (v Value) UnsafePointer() unsafe.Pointer { // created via reflect have the same underlying code pointer, // so their Pointers are equal. The function used here must // match the one used in makeMethodValue. - f := methodValueCall - return **(**unsafe.Pointer)(unsafe.Pointer(&f)) + code := methodValueCallCodePtr() + return *(*unsafe.Pointer)(unsafe.Pointer(&code)) } p := v.pointer() // Non-nil func value points at data block. -- GitLab From 254c497e5c5628be115b966808d6e76d335313a3 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 18 Oct 2021 14:56:08 -0700 Subject: [PATCH 1653/2500] cmd/compile, types2: better error message for invalid type assertion This CL addresses the 2nd part of the issue below. - For types2, now use the same error messages as the compiler in this case. - Make the mechanism for reporting clarifying error messages handle the case where we don't have additional position information. - Provide context information (type assertion vs type switch). Fixes #49005. Change-Id: I4eeaf4f0c3f2f8735b63993778f58d713fef21ee Reviewed-on: https://go-review.googlesource.com/c/go/+/356512 Trust: Robert Griesemer Reviewed-by: Cuong Manh Le Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/errors.go | 5 ++- .../compile/internal/types2/errors_test.go | 2 +- src/cmd/compile/internal/types2/expr.go | 22 +++++++----- src/cmd/compile/internal/types2/stmt.go | 4 +-- .../internal/types2/testdata/check/expr3.src | 4 +-- .../internal/types2/testdata/check/issues.src | 4 +-- .../internal/types2/testdata/check/stmt0.src | 2 +- .../types2/testdata/fixedbugs/issue49005.go | 34 +++++++++++++++++++ test/fixedbugs/issue49005b.go | 15 ++++++++ test/switch6.go | 4 +-- 10 files changed, 77 insertions(+), 19 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue49005.go create mode 100644 test/fixedbugs/issue49005b.go diff --git a/src/cmd/compile/internal/types2/errors.go b/src/cmd/compile/internal/types2/errors.go index ea43fab178..0c8a4a90ff 100644 --- a/src/cmd/compile/internal/types2/errors.go +++ b/src/cmd/compile/internal/types2/errors.go @@ -61,7 +61,10 @@ func (err *error_) msg(qf Qualifier) string { for i := range err.desc { p := &err.desc[i] if i > 0 { - fmt.Fprintf(&buf, "\n\t%s: ", p.pos) + fmt.Fprint(&buf, "\n\t") + if p.pos.IsKnown() { + fmt.Fprintf(&buf, "%s: ", p.pos) + } } buf.WriteString(sprintf(qf, p.format, p.args...)) } diff --git a/src/cmd/compile/internal/types2/errors_test.go b/src/cmd/compile/internal/types2/errors_test.go index 72a2ce3655..ac73ca4650 100644 --- a/src/cmd/compile/internal/types2/errors_test.go +++ b/src/cmd/compile/internal/types2/errors_test.go @@ -19,7 +19,7 @@ func TestError(t *testing.T) { t.Errorf("simple error: got %q, want %q", got, want) } - want = ": foo 42\n\t: bar 43" + want = ": foo 42\n\tbar 43" err.errorf(nopos, "bar %d", 43) if got := err.String(); got != want { t.Errorf("simple error: got %q, want %q", got, want) diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 3a3a139156..2d22c027eb 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -1463,7 +1463,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin if T == Typ[Invalid] { goto Error } - check.typeAssertion(posFor(x), x, xtyp, T) + check.typeAssertion(e, x, xtyp, T, false) x.mode = commaok x.typ = T @@ -1605,26 +1605,32 @@ func keyVal(x constant.Value) interface{} { } // typeAssertion checks that x.(T) is legal; xtyp must be the type of x. -func (check *Checker) typeAssertion(pos syntax.Pos, x *operand, xtyp *Interface, T Type) { +func (check *Checker) typeAssertion(e syntax.Expr, x *operand, xtyp *Interface, T Type, typeSwitch bool) { method, wrongType := check.assertableTo(xtyp, T) if method == nil { return } + var msg string if wrongType != nil { if Identical(method.typ, wrongType.typ) { - msg = fmt.Sprintf("missing method %s (%s has pointer receiver)", method.name, method.name) + msg = fmt.Sprintf("%s method has pointer receiver", method.name) } else { - msg = fmt.Sprintf("wrong type for method %s (have %s, want %s)", method.name, wrongType.typ, method.typ) + msg = fmt.Sprintf("wrong type for method %s: have %s, want %s", method.name, wrongType.typ, method.typ) } } else { - msg = "missing method " + method.name + msg = fmt.Sprintf("missing %s method", method.name) } - if check.conf.CompilerErrorMessages { - check.errorf(pos, "impossible type assertion: %s (%s)", x, msg) + + var err error_ + if typeSwitch { + err.errorf(e.Pos(), "impossible type switch case: %s", e) + err.errorf(nopos, "%s cannot have dynamic type %s (%s)", x, T, msg) } else { - check.errorf(pos, "%s cannot have dynamic type %s (%s)", x, T, msg) + err.errorf(e.Pos(), "impossible type assertion: %s", e) + err.errorf(nopos, "%s does not implement %s (%s)", T, x.typ, msg) } + check.report(&err) } // expr typechecks expression e and initializes x with the expression value. diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index f3f345fd2f..e826f35105 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -306,7 +306,7 @@ L: } seen[T] = e if T != nil { - check.typeAssertion(e.Pos(), x, xtyp, T) + check.typeAssertion(e, x, xtyp, T, true) } } return @@ -347,7 +347,7 @@ L: // } // seen[hash] = e // if T != nil { -// check.typeAssertion(e.Pos(), x, xtyp, T) +// check.typeAssertion(e, x, xtyp, T, true) // } // } // return diff --git a/src/cmd/compile/internal/types2/testdata/check/expr3.src b/src/cmd/compile/internal/types2/testdata/check/expr3.src index fd28421dc8..df4cf6a840 100644 --- a/src/cmd/compile/internal/types2/testdata/check/expr3.src +++ b/src/cmd/compile/internal/types2/testdata/check/expr3.src @@ -459,9 +459,9 @@ func type_asserts() { var t I _ = t /* ERROR "use of .* outside type switch" */ .(type) - _ = t /* ERROR "missing method m" */ .(T) + _ = t /* ERROR "m method has pointer receiver" */ .(T) _ = t.(*T) - _ = t /* ERROR "missing method m" */ .(T1) + _ = t /* ERROR "missing m method" */ .(T1) _ = t /* ERROR "wrong type for method m" */ .(T2) _ = t /* STRICT "wrong type for method m" */ .(I2) // only an error in strict mode (issue 8561) diff --git a/src/cmd/compile/internal/types2/testdata/check/issues.src b/src/cmd/compile/internal/types2/testdata/check/issues.src index d83a95af0e..dfd51006b9 100644 --- a/src/cmd/compile/internal/types2/testdata/check/issues.src +++ b/src/cmd/compile/internal/types2/testdata/check/issues.src @@ -132,12 +132,12 @@ func issue10260() { var x I1 x = T1 /* ERROR cannot use .*: missing method foo \(foo has pointer receiver\) */ {} - _ = x /* ERROR .* cannot have dynamic type T1 \(missing method foo \(foo has pointer receiver\)\) */ .(T1) + _ = x. /* ERROR impossible type assertion: x.\(T1\)\n\tT1 does not implement I1 \(foo method has pointer receiver\) */ (T1) T1{}.foo /* ERROR cannot call pointer method foo on T1 */ () x.Foo /* ERROR "x.Foo undefined \(type I1 has no field or method Foo, but does have foo\)" */ () - _ = i2 /* ERROR i2 .* cannot have dynamic type \*T1 \(wrong type for method foo \(have func\(\), want func\(x int\)\)\) */ .(*T1) + _ = i2. /* ERROR impossible type assertion: i2.\(\*T1\)\n\t\*T1 does not implement I2 \(wrong type for method foo: have func\(\), want func\(x int\)\) */ (*T1) i1 = i0 /* ERROR cannot use .* missing method foo */ i1 = t0 /* ERROR cannot use .* missing method foo */ diff --git a/src/cmd/compile/internal/types2/testdata/check/stmt0.src b/src/cmd/compile/internal/types2/testdata/check/stmt0.src index d744f2ba81..5ec37b4ace 100644 --- a/src/cmd/compile/internal/types2/testdata/check/stmt0.src +++ b/src/cmd/compile/internal/types2/testdata/check/stmt0.src @@ -715,7 +715,7 @@ func typeswitches() { var t I switch t.(type) { case T: - case T1 /* ERROR "missing method m" */ : + case T1 /* ERROR "missing m method" */ : case T2 /* ERROR "wrong type for method m" */ : case I2 /* STRICT "wrong type for method m" */ : // only an error in strict mode (issue 8561) } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49005.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49005.go new file mode 100644 index 0000000000..6225e68488 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49005.go @@ -0,0 +1,34 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file is tested when running "go test -run Manual" +// without source arguments. Use for one-off debugging. + +package p + +type T1 interface{ M() } + +func F1() T1 + +var _ = F1().(*X1 /* ERROR undeclared name: X1 */) + +func _() { + switch F1().(type) { + case *X1 /* ERROR undeclared name: X1 */ : + } +} + +type T2 interface{ M() } + +func F2() T2 + +var _ = F2(). /* ERROR impossible type assertion: F2\(\).\(\*X2\)\n\t\*X2 does not implement T2 \(missing M method\) */ (*X2) + +type X2 struct{} + +func _() { + switch F2().(type) { + case * /* ERROR impossible type switch case: \*X2\n\tF2\(\) \(value of type T2\) cannot have dynamic type \*X2 \(missing M method\) */ X2: + } +} diff --git a/test/fixedbugs/issue49005b.go b/test/fixedbugs/issue49005b.go new file mode 100644 index 0000000000..9bff4e9d18 --- /dev/null +++ b/test/fixedbugs/issue49005b.go @@ -0,0 +1,15 @@ +// errorcheck + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T interface{ M() } + +func F() T + +var _ = F().(*X) // ERROR "impossible type assertion:( F\(\).\(\*X\))?\n\t\*X does not implement T \(missing M method\)" + +type X struct{} diff --git a/test/switch6.go b/test/switch6.go index 4f95d02615..b9d9800391 100644 --- a/test/switch6.go +++ b/test/switch6.go @@ -15,7 +15,7 @@ package main // Verify that type switch statements with impossible cases are detected by the compiler. func f0(e error) { switch e.(type) { - case int: // ERROR "impossible type switch case: e \(type error\) cannot have dynamic type int \(missing Error method\)|impossible type assertion" + case int: // ERROR "impossible type switch case: (int\n\t)?e \(.*type error\) cannot have dynamic type int \(missing Error method\)" } } @@ -41,6 +41,6 @@ func (*X) Foo() {} func f2() { var i I switch i.(type) { - case X: // ERROR "impossible type switch case: i \(type I\) cannot have dynamic type X \(Foo method has pointer receiver\)|impossible type assertion" + case X: // ERROR "impossible type switch case: (X\n\t)?i \(.*type I\) cannot have dynamic type X \(Foo method has pointer receiver\)" } } -- GitLab From 3a07ab70a2d63e3ac1fc126529dde29852a972f5 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 18 Oct 2021 17:17:08 -0700 Subject: [PATCH 1654/2500] cmd/compile/internal/types2: add support for inferring type instances This is an essentially clean port of CL 356489 from go/types to types2, with minor adjustments due to the different AST packages and error reporting. Fixes #47990. Change-Id: I52187872474bfc1fb49eb77905f22fc820b7295b Reviewed-on: https://go-review.googlesource.com/c/go/+/356514 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/call.go | 32 +++++++- .../compile/internal/types2/instantiate.go | 49 ------------ src/cmd/compile/internal/types2/named.go | 3 +- .../{tinference.go2 => funcinference.go2} | 29 ++++--- .../types2/testdata/check/typeinference.go2 | 47 +++++++++++ .../types2/testdata/check/typeinst2.go2 | 4 + .../types2/testdata/check/typeinstcycles.go2 | 11 +++ src/cmd/compile/internal/types2/typexpr.go | 80 ++++++++++++++++--- 8 files changed, 177 insertions(+), 78 deletions(-) rename src/cmd/compile/internal/types2/testdata/check/{tinference.go2 => funcinference.go2} (82%) create mode 100644 src/cmd/compile/internal/types2/testdata/check/typeinference.go2 create mode 100644 src/cmd/compile/internal/types2/testdata/check/typeinstcycles.go2 diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 8b45b28017..3859e39550 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -57,7 +57,7 @@ func (check *Checker) funcInst(x *operand, inst *syntax.IndexExpr) { } // instantiate function signature - res := check.instantiate(x.Pos(), sig, targs, poslist).(*Signature) + res := check.instantiateSignature(x.Pos(), sig, targs, poslist) assert(res.TypeParams().Len() == 0) // signature is not generic anymore check.recordInstance(inst.X, targs, res) x.typ = res @@ -65,6 +65,34 @@ func (check *Checker) funcInst(x *operand, inst *syntax.IndexExpr) { x.expr = inst } +func (check *Checker) instantiateSignature(pos syntax.Pos, typ *Signature, targs []Type, posList []syntax.Pos) (res *Signature) { + assert(check != nil) + assert(len(targs) == typ.TypeParams().Len()) + + if check.conf.Trace { + check.trace(pos, "-- instantiating %s with %s", typ, targs) + check.indent++ + defer func() { + check.indent-- + check.trace(pos, "=> %s (under = %s)", res, res.Underlying()) + }() + } + + inst := check.instance(pos, typ, targs, check.conf.Context).(*Signature) + assert(len(posList) <= len(targs)) + tparams := typ.TypeParams().list() + if i, err := check.verify(pos, tparams, targs); err != nil { + // best position for error reporting + pos := pos + if i < len(posList) { + pos = posList[i] + } + check.softErrorf(pos, err.Error()) + } + + return inst +} + func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { var inst *syntax.IndexExpr // function instantiation, if any if iexpr, _ := call.Fun.(*syntax.IndexExpr); iexpr != nil { @@ -345,7 +373,7 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T } // compute result signature - rsig = check.instantiate(call.Pos(), sig, targs, nil).(*Signature) + rsig = check.instantiateSignature(call.Pos(), sig, targs, nil) assert(rsig.TypeParams().Len() == 0) // signature is not generic anymore check.recordInstance(call.Fun, targs, rsig) diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 5e45ea33ce..d6cefb4bfe 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -49,55 +49,6 @@ func Instantiate(ctxt *Context, typ Type, targs []Type, validate bool) (Type, er return inst, err } -// instantiate creates an instance and defers verification of constraints to -// later in the type checking pass. For Named types the resulting instance will -// be unexpanded. -func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, posList []syntax.Pos) (res Type) { - assert(check != nil) - if check.conf.Trace { - check.trace(pos, "-- instantiating %s with %s", typ, NewTypeList(targs)) - check.indent++ - defer func() { - check.indent-- - var under Type - if res != nil { - // Calling under() here may lead to endless instantiations. - // Test case: type T[P any] T[P] - under = safeUnderlying(res) - } - check.trace(pos, "=> %s (under = %s)", res, under) - }() - } - - inst := check.instance(pos, typ, targs, check.conf.Context) - - assert(len(posList) <= len(targs)) - check.later(func() { - // Collect tparams again because lazily loaded *Named types may not have - // had tparams set up above. - var tparams []*TypeParam - switch t := typ.(type) { - case *Named: - tparams = t.TypeParams().list() - case *Signature: - tparams = t.TypeParams().list() - } - // Avoid duplicate errors; instantiate will have complained if tparams - // and targs do not have the same length. - if len(tparams) == len(targs) { - if i, err := check.verify(pos, tparams, targs); err != nil { - // best position for error reporting - pos := pos - if i < len(posList) { - pos = posList[i] - } - check.softErrorf(pos, err.Error()) - } - } - }) - return inst -} - // instance creates a type or function instance using the given original type // typ and arguments targs. For Named types the resulting instance will be // unexpanded. diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index 3971e03179..8f2a52b4f2 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -239,7 +239,8 @@ func expandNamed(ctxt *Context, n *Named, instPos syntax.Pos) (tparams *TypePara check := n.check - if check.validateTArgLen(instPos, n.orig.tparams.Len(), n.targs.Len()) { + // Mismatching arg and tparam length may be checked elsewhere. + if n.orig.tparams.Len() == n.targs.Len() { // We must always have a context, to avoid infinite recursion. ctxt = check.bestContext(ctxt) h := ctxt.TypeHash(n.orig, n.targs.list()) diff --git a/src/cmd/compile/internal/types2/testdata/check/tinference.go2 b/src/cmd/compile/internal/types2/testdata/check/funcinference.go2 similarity index 82% rename from src/cmd/compile/internal/types2/testdata/check/tinference.go2 rename to src/cmd/compile/internal/types2/testdata/check/funcinference.go2 index 2409fef4ae..7160e18b19 100644 --- a/src/cmd/compile/internal/types2/testdata/check/tinference.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/funcinference.go2 @@ -2,26 +2,25 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package tinferenceB +package funcInference import "strconv" type any interface{} -// Embedding stand-alone type parameters is not permitted for now. Disabled. -// func f0[A any, B interface{~C}, C interface{~D}, D interface{~A}](A, B, C, D) -// func _() { -// f := f0[string] -// f("a", "b", "c", "d") -// f0("a", "b", "c", "d") -// } -// -// func f1[A any, B interface{~A}](A, B) -// func _() { -// f := f1[int] -// f(int(0), int(0)) -// f1(int(0), int(0)) -// } +func f0[A any, B interface{~*C}, C interface{~*D}, D interface{~*A}](A, B, C, D) {} +func _() { + f := f0[string] + f("a", nil, nil, nil) + f0("a", nil, nil, nil) +} + +func f1[A any, B interface{~*A}](A, B) {} +func _() { + f := f1[int] + f(int(0), new(int)) + f1(int(0), new(int)) +} func f2[A any, B interface{~[]A}](A, B) {} func _() { diff --git a/src/cmd/compile/internal/types2/testdata/check/typeinference.go2 b/src/cmd/compile/internal/types2/testdata/check/typeinference.go2 new file mode 100644 index 0000000000..8876ccaa4e --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/check/typeinference.go2 @@ -0,0 +1,47 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package typeInference + +// basic inference +type Tb[P ~*Q, Q any] int +func _() { + var x Tb[*int] + var y Tb[*int, int] + x = y + _ = x +} + +// recursive inference +type Tr[A any, B ~*C, C ~*D, D ~*A] int +func _() { + var x Tr[string] + var y Tr[string, ***string, **string, *string] + var z Tr[int, ***int, **int, *int] + x = y + x = z // ERROR cannot use z .* as Tr + _ = x +} + +// other patterns of inference +type To0[A any, B ~[]A] int +type To1[A any, B ~struct{a A}] int +type To2[A any, B ~[][]A] int +type To3[A any, B ~[3]*A] int +type To4[A any, B any, C ~struct{a A; b B}] int +func _() { + var _ To0[int] + var _ To1[int] + var _ To2[int] + var _ To3[int] + var _ To4[int, string] +} + +// failed inference +type Tf0[A, B any] int +type Tf1[A any, B ~struct{a A; c C}, C any] int +func _() { + var _ Tf0 /* ERROR cannot infer B */ /* ERROR got 1 arguments but 2 type parameters */ [int] + var _ Tf1 /* ERROR cannot infer B */ /* ERROR got 1 arguments but 3 type parameters */ [int] +} diff --git a/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 b/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 index 49f48c7283..ecf4b0f714 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 @@ -252,3 +252,7 @@ var _ = f0_[int] var _ = f0_[bool /* ERROR does not satisfy I0_ */ ] var _ = f0_[string /* ERROR does not satisfy I0_ */ ] var _ = f0_[float64 /* ERROR does not satisfy I0_ */ ] + +// Using a function instance as a type is an error. +var _ f0 // ERROR not a type +var _ f0 /* ERROR not a type */ [int] diff --git a/src/cmd/compile/internal/types2/testdata/check/typeinstcycles.go2 b/src/cmd/compile/internal/types2/testdata/check/typeinstcycles.go2 new file mode 100644 index 0000000000..74fe19195a --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/check/typeinstcycles.go2 @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +import "unsafe" + +func F1[T any](_ [unsafe.Sizeof(F1[int])]T) (res T) { return } +func F2[T any](_ T) (res [unsafe.Sizeof(F2[string])]int) { return } +func F3[T any](_ [unsafe.Sizeof(F1[string])]int) {} diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index eae9330914..20e56caf1e 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -396,13 +396,24 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) { return typ } -func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def *Named) Type { +func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def *Named) (res Type) { + if check.conf.Trace { + check.trace(x.Pos(), "-- instantiating %s with %s", x, targsx) + check.indent++ + defer func() { + check.indent-- + // Don't format the underlying here. It will always be nil. + check.trace(x.Pos(), "=> %s", res) + }() + } + gtyp := check.genericType(x, true) if gtyp == Typ[Invalid] { return gtyp // error already reported } - base, _ := gtyp.(*Named) - if base == nil { + + origin, _ := gtyp.(*Named) + if origin == nil { panic(fmt.Sprintf("%v: cannot instantiate %v", x.Pos(), gtyp)) } @@ -416,20 +427,67 @@ func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def // determine argument positions posList := make([]syntax.Pos, len(targs)) for i, arg := range targsx { - posList[i] = syntax.StartPos(arg) + posList[i] = arg.Pos() } - typ := check.instantiate(x.Pos(), base, targs, posList) - def.setUnderlying(typ) - check.recordInstance(x, targs, typ) + // create the instance + h := check.conf.Context.TypeHash(origin, targs) + // targs may be incomplete, and require inference. In any case we should de-duplicate. + inst := check.conf.Context.typeForHash(h, nil) + // If inst is non-nil, we can't just return here. Inst may have been + // constructed via recursive substitution, in which case we wouldn't do the + // validation below. Ensure that the validation (and resulting errors) runs + // for each instantiated type in the source. + if inst == nil { + tname := NewTypeName(x.Pos(), origin.obj.pkg, origin.obj.name, nil) + inst = check.newNamed(tname, origin, nil, nil, nil) // underlying, methods and tparams are set when named is resolved + inst.targs = NewTypeList(targs) + inst = check.conf.Context.typeForHash(h, inst) + } + def.setUnderlying(inst) + + inst.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, []*Func) { + tparams := origin.TypeParams().list() + + inferred := targs + if len(targs) < len(tparams) { + // If inference fails, len(inferred) will be 0, and inst.underlying will + // be set to Typ[Invalid] in expandNamed. + inferred = check.infer(x.Pos(), tparams, targs, nil, nil) + if len(inferred) > len(targs) { + inst.targs = NewTypeList(inferred) + } + } - // make sure we check instantiation works at least once - // and that the resulting type is valid + check.recordInstance(x, inferred, inst) + return expandNamed(ctxt, n, x.Pos()) + } + + // origin.tparams may not be set up, so we need to do expansion later. check.later(func() { - check.validType(typ, nil) + // This is an instance from the source, not from recursive substitution, + // and so it must be resolved during type-checking so that we can report + // errors. + inst.resolve(check.conf.Context) + // Since check is non-nil, we can still mutate inst. Unpinning the resolver + // frees some memory. + inst.resolver = nil + + if check.validateTArgLen(x.Pos(), inst.tparams.Len(), inst.targs.Len()) { + if i, err := check.verify(x.Pos(), inst.tparams.list(), inst.targs.list()); err != nil { + // best position for error reporting + pos := x.Pos() + if i < len(posList) { + pos = posList[i] + } + check.softErrorf(pos, err.Error()) + } + } + + check.validType(inst, nil) }) - return typ + return inst } // arrayLength type-checks the array length expression e -- GitLab From a73c6cf762560b458eb938e4461cd8debc479fd9 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 18 Oct 2021 17:31:23 -0700 Subject: [PATCH 1655/2500] cmd/compile/internal/types2: ensure named types are expanded after type-checking This is a clean port of CL 356490 from go/types to types2. Fixes #48703. Fixes #48974. Change-Id: I08c0db0b92250cbb043325541b21a577726b40ca Reviewed-on: https://go-review.googlesource.com/c/go/+/356515 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/check.go | 28 +++++++++++++++++++ src/cmd/compile/internal/types2/named.go | 23 ++++++--------- .../types2/testdata/fixedbugs/issue48703.go2 | 27 ++++++++++++++++++ .../types2/testdata/fixedbugs/issue48974.go2 | 22 +++++++++++++++ 4 files changed, 85 insertions(+), 15 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue48703.go2 create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue48974.go2 diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go index 470376f8e8..6e8883e5de 100644 --- a/src/cmd/compile/internal/types2/check.go +++ b/src/cmd/compile/internal/types2/check.go @@ -132,6 +132,7 @@ type Checker struct { untyped map[syntax.Expr]exprInfo // map of expressions without final type delayed []action // stack of delayed action segments; segments are processed in FIFO order objPath []Object // path of object dependencies during type inference (for cycle reporting) + defTypes []*Named // defined types created during type checking, for final validation. // context within which the current object is type-checked // (valid only for the duration of type-checking a specific object) @@ -302,6 +303,9 @@ func (check *Checker) checkFiles(files []*syntax.File) (err error) { print("== processDelayed ==") check.processDelayed(0) // incl. all functions + print("== expandDefTypes ==") + check.expandDefTypes() + print("== initOrder ==") check.initOrder() @@ -321,6 +325,7 @@ func (check *Checker) checkFiles(files []*syntax.File) (err error) { check.pkgPathMap = nil check.seenPkgMap = nil check.recvTParamMap = nil + check.defTypes = nil // TODO(gri) There's more memory we should release at this point. @@ -347,6 +352,29 @@ func (check *Checker) processDelayed(top int) { check.delayed = check.delayed[:top] } +func (check *Checker) expandDefTypes() { + // Ensure that every defined type created in the course of type-checking has + // either non-*Named underlying, or is unresolved. + // + // This guarantees that we don't leak any types whose underlying is *Named, + // because any unresolved instances will lazily compute their underlying by + // substituting in the underlying of their origin. The origin must have + // either been imported or type-checked and expanded here, and in either case + // its underlying will be fully expanded. + for i := 0; i < len(check.defTypes); i++ { + n := check.defTypes[i] + switch n.underlying.(type) { + case nil: + if n.resolver == nil { + panic("nil underlying") + } + case *Named: + n.under() // n.under may add entries to check.defTypes + } + n.check = nil + } +} + func (check *Checker) record(x *operand) { // convert x into a user-friendly set of values // TODO(gri) this code can be simplified diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index 8f2a52b4f2..eb8b5d1ba8 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -65,22 +65,9 @@ func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tpar if obj.typ == nil { obj.typ = typ } - // Ensure that typ is always expanded, at which point the check field can be - // nilled out. - // - // Note that currently we cannot nil out check inside typ.under(), because - // it's possible that typ is expanded multiple times. - // - // TODO(gri): clean this up so that under is the only function mutating - // named types. + // Ensure that typ is always expanded and sanity-checked. if check != nil { - check.later(func() { - switch typ.under().(type) { - case *Named: - panic("unexpanded underlying type") - } - typ.check = nil - }) + check.defTypes = append(check.defTypes, typ) } return typ } @@ -239,6 +226,12 @@ func expandNamed(ctxt *Context, n *Named, instPos syntax.Pos) (tparams *TypePara check := n.check + if _, unexpanded := n.orig.underlying.(*Named); unexpanded { + // We should only get an unexpanded underlying here during type checking + // (for example, in recursive type declarations). + assert(check != nil) + } + // Mismatching arg and tparam length may be checked elsewhere. if n.orig.tparams.Len() == n.targs.Len() { // We must always have a context, to avoid infinite recursion. diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48703.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48703.go2 new file mode 100644 index 0000000000..8a32c1ecf2 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48703.go2 @@ -0,0 +1,27 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +import "unsafe" + +// The actual example from the issue. +type List[P any] struct{} + +func (_ List[P]) m() (_ List[List[P]]) { return } + +// Other types of recursion through methods. +type R[P any] int + +func (*R[R /* ERROR must be an identifier */ [int]]) m0() {} +func (R[P]) m1(R[R[P]]) {} +func (R[P]) m2(R[*P]) {} +func (R[P]) m3([unsafe.Sizeof(new(R[P]))]int) {} +func (R[P]) m4([unsafe.Sizeof(new(R[R[P]]))]int) {} + +// Mutual recursion +type M[P any] int + +func (R[P]) m5(M[M[P]]) {} +func (M[P]) m(R[R[P]]) {} diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48974.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48974.go2 new file mode 100644 index 0000000000..ca4b6d9321 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48974.go2 @@ -0,0 +1,22 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type Fooer interface { + Foo() +} + +type Fooable[F Fooer] struct { + ptr F +} + +func (f *Fooable[F]) Adapter() *Fooable[*FooerImpl[F]] { + return &Fooable[*FooerImpl[F]]{&FooerImpl[F]{}} +} + +type FooerImpl[F Fooer] struct { +} + +func (fi *FooerImpl[F]) Foo() {} -- GitLab From 99fad12e4788fdf67e49dadd16571238f935b408 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 18 Oct 2021 17:42:21 -0700 Subject: [PATCH 1656/2500] cmd/compile/internal/types2: delay expansion of underlying in typeDecl This is a clean port of CL 356533 from go/types to types2. Fixes #49043. Change-Id: If389b94ece28042b0c8b436959dd21f26147a144 Reviewed-on: https://go-review.googlesource.com/c/go/+/356517 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/decl.go | 24 ++++++------------- src/cmd/compile/internal/types2/named.go | 17 ++++++++++++- .../types2/testdata/check/typeinst.go2 | 2 +- .../types2/testdata/fixedbugs/issue49043.go2 | 24 +++++++++++++++++++ 4 files changed, 48 insertions(+), 19 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue49043.go2 diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index a605057579..63be4b3223 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -597,22 +597,12 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named rhs = check.definedType(tdecl.Type, named) assert(rhs != nil) named.fromRHS = rhs - // The underlying type of named may be itself a named type that is - // incomplete: - // - // type ( - // A B - // B *C - // C A - // ) - // - // The type of C is the (named) type of A which is incomplete, - // and which has as its underlying type the named type B. - // Determine the (final, unnamed) underlying type by resolving - // any forward chain. - // TODO(gri) Investigate if we can just use named.fromRHS here - // and rely on lazy computation of the underlying type. - named.underlying = under(named) + + // If the underlying was not set while type-checking the right-hand side, it + // is invalid and an error should have been reported elsewhere. + if named.underlying == nil { + named.underlying = Typ[Invalid] + } // If the RHS is a type parameter, it must be from this type declaration. if tpar, _ := named.underlying.(*TypeParam); tpar != nil && tparamIndex(named.TypeParams().list(), tpar) < 0 { @@ -711,7 +701,7 @@ func (check *Checker) collectMethods(obj *TypeName) { // and field names must be distinct." base := asNamed(obj.typ) // shouldn't fail but be conservative if base != nil { - u := safeUnderlying(base) // base should be expanded, but use safeUnderlying to be conservative + u := base.under() if t, _ := u.(*Struct); t != nil { for _, fld := range t.fields { if fld.name != "_" { diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index eb8b5d1ba8..6ebad8fbb5 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -130,6 +130,18 @@ func (t *Named) String() string { return TypeString(t, nil) } // chain before returning it. If no underlying type is found or a cycle // is detected, the result is Typ[Invalid]. If a cycle is detected and // n0.check != nil, the cycle is reported. +// +// This is necessary because the underlying type of named may be itself a +// named type that is incomplete: +// +// type ( +// A B +// B *C +// C A +// ) +// +// The type of C is the (named) type of A which is incomplete, +// and which has as its underlying type the named type B. func (n0 *Named) under() Type { u := n0.Underlying() @@ -139,7 +151,9 @@ func (n0 *Named) under() Type { var n1 *Named switch u1 := u.(type) { case nil: - return Typ[Invalid] + // After expansion via Underlying(), we should never encounter a nil + // underlying. + panic("nil underlying") default: // common case return u @@ -223,6 +237,7 @@ func (check *Checker) bestContext(ctxt *Context) *Context { // The underlying type will be Typ[Invalid] if there was an error. func expandNamed(ctxt *Context, n *Named, instPos syntax.Pos) (tparams *TypeParamList, underlying Type, methods []*Func) { n.orig.resolve(ctxt) + assert(n.orig.underlying != nil) check := n.check diff --git a/src/cmd/compile/internal/types2/testdata/check/typeinst.go2 b/src/cmd/compile/internal/types2/testdata/check/typeinst.go2 index 3fab2cb9ad..14f1b07ee2 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeinst.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeinst.go2 @@ -57,5 +57,5 @@ var _ T3[int] = T3[int](List[int]{1, 2, 3}) // Self-recursive generic types are not permitted -type self1[P any] self1 /* ERROR illegal cycle */ [P] +type self1 /* ERROR illegal cycle */ [P any] self1[P] type self2[P any] *self2[P] // this is ok diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49043.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49043.go2 new file mode 100644 index 0000000000..c37b0f1267 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49043.go2 @@ -0,0 +1,24 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +// The example from the issue. +type ( + N /* ERROR illegal cycle */ [P any] M[P] + M[P any] N[P] +) + +// A slightly more complicated case. +type ( + A /* ERROR illegal cycle */ [P any] B[P] + B[P any] C[P] + C[P any] A[P] +) + +// Confusing but valid (note that `type T *T` is valid). +type ( + N1[P any] *M1[P] + M1[P any] *N1[P] +) -- GitLab From 404f84d417ceed0f47e51d2c4f933a6dee96dca5 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 15 Oct 2021 23:24:28 +0000 Subject: [PATCH 1657/2500] runtime: remove reference to crypto/tls GODEBUG usage crypto/tls briefly used GODEBUG. That usage was removed in CL 191999. Change-Id: I759b6f1b02db8160075cba30d73823018e19ad9d GitHub-Last-Rev: 12d2a4a82b1467e4c2214aa78eb9a0af4938a9de GitHub-Pull-Request: golang/go#49012 Reviewed-on: https://go-review.googlesource.com/c/go/+/356313 Reviewed-by: Austin Clements Trust: Michael Pratt --- src/runtime/extern.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/extern.go b/src/runtime/extern.go index eca4062e68..b2003ba543 100644 --- a/src/runtime/extern.go +++ b/src/runtime/extern.go @@ -144,7 +144,7 @@ It is a comma-separated list of name=val pairs setting these named variables: because it also disables the conservative stack scanning used for asynchronously preempted goroutines. -The net, net/http, and crypto/tls packages also refer to debugging variables in GODEBUG. +The net and net/http packages also refer to debugging variables in GODEBUG. See the documentation for those packages for details. The GOMAXPROCS variable limits the number of operating system threads that -- GitLab From 982060203c26b60fd74e4fa2fd967600c65ee7fc Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Fri, 15 Oct 2021 11:16:54 -0400 Subject: [PATCH 1658/2500] testing: don't allow f.Log/Logf or f.Skipped inside f.Fuzz This change also does some refactors around how we prevent many (*F) methods from being called inside (*F).Fuzz. Previously, there was a lot of comment/code duplication, which was going to be difficult to maintain and brittle. The refactor lessens this duplication. Previously, the methods Log, Logf, Failed, Name and Skipped were the only (*common) methods that were allowed to be called inside (*F).Fuzz. After this change, Failed and Name are still allowed, but Log, Logf, and Skipped are not (t.Log, t.Logf, or t.Skipped should be used instead). Fixes #48988 Change-Id: I4066247d551ea1908e8a2ca2889509fc68e3bb44 Reviewed-on: https://go-review.googlesource.com/c/go/+/356151 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills Reviewed-by: Jay Conrod --- src/cmd/go/testdata/script/test_fuzz.txt | 39 ++++++ src/testing/fuzz.go | 147 ++++------------------- src/testing/testing.go | 28 ++++- 3 files changed, 87 insertions(+), 127 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt index c9930aa37e..4665202bf0 100644 --- a/src/cmd/go/testdata/script/test_fuzz.txt +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -70,6 +70,12 @@ stdout 'f.Fuzz function' stdout FAIL stdout 'f.Fuzz function' +# Test that f.Fail within f.Fuzz panics +! go test fail_fuzz_fn_fuzz_test.go +! stdout ^ok +stdout FAIL +stdout 'f.Fuzz function' + # Test that f.Skip within f.Fuzz panics ! go test skip_fuzz_fn_fuzz_test.go ! stdout ^ok @@ -77,6 +83,14 @@ stdout 'f.Fuzz function' stdout FAIL stdout 'f.Fuzz function' +# Test that f.Skipped within f.Fuzz panics +! go test skipped_fuzz_fn_fuzz_test.go +! stdout ^ok +! stdout 'f.Skipped is' +stdout FAIL +stdout 'f.Fuzz function' +stdout 't.Skipped is false' + # Test that runtime.Goexit within the fuzz function is an error. ! go test goexit_fuzz_fn_fuzz_test.go ! stdout ^ok @@ -260,6 +274,18 @@ func Fuzz(f *testing.F) { }) } +-- fail_fuzz_fn_fuzz_test.go -- +package skip_fuzz_fn_fuzz + +import "testing" + +func Fuzz(f *testing.F) { + f.Add([]byte("aa")) + f.Fuzz(func(t *testing.T, b []byte) { + f.Fail() + }) +} + -- skip_fuzz_fn_fuzz_test.go -- package skip_fuzz_fn_fuzz @@ -272,6 +298,19 @@ func Fuzz(f *testing.F) { }) } +-- skipped_fuzz_fn_fuzz_test.go -- +package skipped_fuzz_fn_fuzz + +import "testing" + +func Fuzz(f *testing.F) { + f.Add([]byte("aa")) + f.Fuzz(func(t *testing.T, b []byte) { + t.Logf("t.Skipped is %t\n", t.Skipped()) + t.Logf("f.Skipped is %t\n", f.Skipped()) + }) +} + -- goexit_fuzz_fn_fuzz_test.go -- package goexit_fuzz_fn_fuzz diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index d5cb5e853f..10665168f4 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -57,6 +57,10 @@ type InternalFuzzTarget struct { // call F.Fuzz once to provide a fuzz function. See the testing package // documentation for an example, and see the F.Fuzz and F.Add method // documentation for details. +// +// *F methods can only be called before (*F).Fuzz. Once inside the function +// passed to (*F).Fuzz, only (*T) methods can be used. The only *F methods that +// are allowed in the (*F).Fuzz function are (*F).Failed and (*F).Name. type F struct { common fuzzContext *fuzzContext @@ -88,78 +92,6 @@ type corpusEntry = struct { IsSeed bool } -// Cleanup registers a function to be called after the fuzz function has been -// called on all seed corpus entries, and after fuzzing completes (if enabled). -// Cleanup functions will be called in last added, first called order. -func (f *F) Cleanup(fn func()) { - if f.inFuzzFn { - panic("testing: f.Cleanup was called inside the f.Fuzz function, use t.Cleanup instead") - } - f.common.Helper() - f.common.Cleanup(fn) -} - -// Error is equivalent to Log followed by Fail. -func (f *F) Error(args ...interface{}) { - if f.inFuzzFn { - panic("testing: f.Error was called inside the f.Fuzz function, use t.Error instead") - } - f.common.Helper() - f.common.Error(args...) -} - -// Errorf is equivalent to Logf followed by Fail. -func (f *F) Errorf(format string, args ...interface{}) { - if f.inFuzzFn { - panic("testing: f.Errorf was called inside the f.Fuzz function, use t.Errorf instead") - } - f.common.Helper() - f.common.Errorf(format, args...) -} - -// Fail marks the function as having failed but continues execution. -func (f *F) Fail() { - if f.inFuzzFn { - panic("testing: f.Fail was called inside the f.Fuzz function, use t.Fail instead") - } - f.common.Helper() - f.common.Fail() -} - -// FailNow marks the function as having failed and stops its execution -// by calling runtime.Goexit (which then runs all deferred calls in the -// current goroutine). -// Execution will continue at the next test, benchmark, or fuzz function. -// FailNow must be called from the goroutine running the -// fuzz target, not from other goroutines -// created during the test. Calling FailNow does not stop -// those other goroutines. -func (f *F) FailNow() { - if f.inFuzzFn { - panic("testing: f.FailNow was called inside the f.Fuzz function, use t.FailNow instead") - } - f.common.Helper() - f.common.FailNow() -} - -// Fatal is equivalent to Log followed by FailNow. -func (f *F) Fatal(args ...interface{}) { - if f.inFuzzFn { - panic("testing: f.Fatal was called inside the f.Fuzz function, use t.Fatal instead") - } - f.common.Helper() - f.common.Fatal(args...) -} - -// Fatalf is equivalent to Logf followed by FailNow. -func (f *F) Fatalf(format string, args ...interface{}) { - if f.inFuzzFn { - panic("testing: f.Fatalf was called inside the f.Fuzz function, use t.Fatalf instead") - } - f.common.Helper() - f.common.Fatalf(format, args...) -} - // Helper marks the calling function as a test helper function. // When printing file and line information, that function will be skipped. // Helper may be called simultaneously from multiple goroutines. @@ -188,65 +120,26 @@ func (f *F) Helper() { } } -// Setenv calls os.Setenv(key, value) and uses Cleanup to restore the -// environment variable to its original value after the test. -// -// When fuzzing is enabled, the fuzzing engine spawns worker processes running -// the test binary. Each worker process inherits the environment of the parent -// process, including environment variables set with F.Setenv. -func (f *F) Setenv(key, value string) { - if f.inFuzzFn { - panic("testing: f.Setenv was called inside the f.Fuzz function, use t.Setenv instead") - } - f.common.Helper() - f.common.Setenv(key, value) -} - -// Skip is equivalent to Log followed by SkipNow. -func (f *F) Skip(args ...interface{}) { - if f.inFuzzFn { - panic("testing: f.Skip was called inside the f.Fuzz function, use t.Skip instead") - } - f.common.Helper() - f.common.Skip(args...) -} - -// SkipNow marks the test as having been skipped and stops its execution -// by calling runtime.Goexit. -// If a test fails (see Error, Errorf, Fail) and is then skipped, -// it is still considered to have failed. -// Execution will continue at the next test or benchmark. See also FailNow. -// SkipNow must be called from the goroutine running the test, not from -// other goroutines created during the test. Calling SkipNow does not stop -// those other goroutines. -func (f *F) SkipNow() { - if f.inFuzzFn { - panic("testing: f.SkipNow was called inside the f.Fuzz function, use t.SkipNow instead") - } - f.common.Helper() - f.common.SkipNow() -} - -// Skipf is equivalent to Logf followed by SkipNow. -func (f *F) Skipf(format string, args ...interface{}) { +// Fail marks the function as having failed but continues execution. +func (f *F) Fail() { + // (*F).Fail may be called by (*T).Fail, which we should allow. However, we + // shouldn't allow direct (*F).Fail calls from inside the (*F).Fuzz function. if f.inFuzzFn { - panic("testing: f.Skipf was called inside the f.Fuzz function, use t.Skipf instead") + panic("testing: f.Fail was called inside the f.Fuzz function, use t.Fail instead") } f.common.Helper() - f.common.Skipf(format, args...) + f.common.Fail() } -// TempDir returns a temporary directory for the test to use. -// The directory is automatically removed by Cleanup when the test and -// all its subtests complete. -// Each subsequent call to t.TempDir returns a unique directory; -// if the directory creation fails, TempDir terminates the test by calling Fatal. -func (f *F) TempDir() string { +// Skipped reports whether the test was skipped. +func (f *F) Skipped() bool { + // (*F).Skipped may be called by tRunner, which we should allow. However, we + // shouldn't allow direct (*F).Skipped calls from inside the (*F).Fuzz function. if f.inFuzzFn { - panic("testing: f.TempDir was called inside the f.Fuzz function, use t.TempDir instead") + panic("testing: f.Skipped was called inside the f.Fuzz function, use t.Skipped instead") } f.common.Helper() - return f.common.TempDir() + return f.common.Skipped() } // Add will add the arguments to the seed corpus for the fuzz target. This will @@ -297,6 +190,10 @@ var supportedTypes = map[reflect.Type]bool{ // float64, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64. // More types may be supported in the future. // +// ff must not call any *F methods, e.g. (*F).Log, (*F).Error, (*F).Skip. Use +// the corresponding *T method instead. The only *F methods that are allowed in +// the (*F).Fuzz function are (*F).Failed and (*F).Name. +// // This function sould be fast and deterministic, and its behavior should not // depend on shared state. No mutatable input arguments, or pointers to them, // should be retained between executions of the fuzz function, as the memory @@ -415,7 +312,7 @@ func (f *F) Fuzz(ff interface{}) { // TODO(#48132): adjust this to work with test2json. t.chatty.Updatef(t.name, "=== RUN %s\n", t.name) } - f.inFuzzFn = true + f.common.inFuzzFn, f.inFuzzFn = true, true go tRunner(t, func(t *T) { args := []reflect.Value{reflect.ValueOf(t)} for _, v := range e.Values { @@ -430,7 +327,7 @@ func (f *F) Fuzz(ff interface{}) { fn.Call(args) }) <-t.signal - f.inFuzzFn = false + f.common.inFuzzFn, f.inFuzzFn = false, false return !t.Failed() } diff --git a/src/testing/testing.go b/src/testing/testing.go index 57ac580051..d03c0b1cf9 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -492,6 +492,7 @@ type common struct { cleanupName string // Name of the cleanup function. cleanupPc []uintptr // The stack trace at the point where Cleanup was called. finished bool // Test function has completed. + inFuzzFn bool // Whether the fuzz function, if this is one, is running. chatty *chattyPrinter // A copy of chattyPrinter, if the chatty flag is set. bench bool // Whether the current test is a benchmark. @@ -547,6 +548,12 @@ func Verbose() bool { return *chatty } +func (c *common) checkFuzzFn(name string) { + if c.inFuzzFn { + panic(fmt.Sprintf("testing: f.%s was called inside the f.Fuzz function, use t.%s instead", name, name)) + } +} + // frameSkip searches, starting after skip frames, for the first caller frame // in a function not marked as a helper and returns that frame. // The search stops if it finds a tRunner function that @@ -821,6 +828,7 @@ func (c *common) Failed() bool { // created during the test. Calling FailNow does not stop // those other goroutines. func (c *common) FailNow() { + c.checkFuzzFn("FailNow") c.Fail() // Calling runtime.Goexit will exit the goroutine, which @@ -889,47 +897,59 @@ func (c *common) logDepth(s string, depth int) { // and records the text in the error log. For tests, the text will be printed only if // the test fails or the -test.v flag is set. For benchmarks, the text is always // printed to avoid having performance depend on the value of the -test.v flag. -func (c *common) Log(args ...interface{}) { c.log(fmt.Sprintln(args...)) } +func (c *common) Log(args ...interface{}) { + c.checkFuzzFn("Log") + c.log(fmt.Sprintln(args...)) +} // Logf formats its arguments according to the format, analogous to Printf, and // records the text in the error log. A final newline is added if not provided. For // tests, the text will be printed only if the test fails or the -test.v flag is // set. For benchmarks, the text is always printed to avoid having performance // depend on the value of the -test.v flag. -func (c *common) Logf(format string, args ...interface{}) { c.log(fmt.Sprintf(format, args...)) } +func (c *common) Logf(format string, args ...interface{}) { + c.checkFuzzFn("Logf") + c.log(fmt.Sprintf(format, args...)) +} // Error is equivalent to Log followed by Fail. func (c *common) Error(args ...interface{}) { + c.checkFuzzFn("Error") c.log(fmt.Sprintln(args...)) c.Fail() } // Errorf is equivalent to Logf followed by Fail. func (c *common) Errorf(format string, args ...interface{}) { + c.checkFuzzFn("Errorf") c.log(fmt.Sprintf(format, args...)) c.Fail() } // Fatal is equivalent to Log followed by FailNow. func (c *common) Fatal(args ...interface{}) { + c.checkFuzzFn("Fatal") c.log(fmt.Sprintln(args...)) c.FailNow() } // Fatalf is equivalent to Logf followed by FailNow. func (c *common) Fatalf(format string, args ...interface{}) { + c.checkFuzzFn("Fatalf") c.log(fmt.Sprintf(format, args...)) c.FailNow() } // Skip is equivalent to Log followed by SkipNow. func (c *common) Skip(args ...interface{}) { + c.checkFuzzFn("Skip") c.log(fmt.Sprintln(args...)) c.SkipNow() } // Skipf is equivalent to Logf followed by SkipNow. func (c *common) Skipf(format string, args ...interface{}) { + c.checkFuzzFn("Skipf") c.log(fmt.Sprintf(format, args...)) c.SkipNow() } @@ -943,6 +963,7 @@ func (c *common) Skipf(format string, args ...interface{}) { // other goroutines created during the test. Calling SkipNow does not stop // those other goroutines. func (c *common) SkipNow() { + c.checkFuzzFn("SkipNow") c.mu.Lock() c.skipped = true c.finished = true @@ -982,6 +1003,7 @@ func (c *common) Helper() { // subtests complete. Cleanup functions will be called in last added, // first called order. func (c *common) Cleanup(f func()) { + c.checkFuzzFn("Cleanup") var pc [maxStackLen]uintptr // Skip two extra frames to account for this function and runtime.Callers itself. n := runtime.Callers(2, pc[:]) @@ -1015,6 +1037,7 @@ func (c *common) Cleanup(f func()) { // Each subsequent call to t.TempDir returns a unique directory; // if the directory creation fails, TempDir terminates the test by calling Fatal. func (c *common) TempDir() string { + c.checkFuzzFn("TempDir") // Use a single parent directory for all the temporary directories // created by a test, each numbered sequentially. c.tempDirMu.Lock() @@ -1080,6 +1103,7 @@ func (c *common) TempDir() string { // // This cannot be used in parallel tests. func (c *common) Setenv(key, value string) { + c.checkFuzzFn("Setenv") prevValue, ok := os.LookupEnv(key) if err := os.Setenv(key, value); err != nil { -- GitLab From ad7db1f90fb66f00f5b020360aabd9f27d1c764f Mon Sep 17 00:00:00 2001 From: Carlo Alberto Ferraris Date: Thu, 14 Oct 2021 16:50:41 +0900 Subject: [PATCH 1659/2500] sync: avoid a dynamic check in WaitGroup on 64-bit architectures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit uint64 is guaranteed by the compiler to be aligned on 64-bit archs. By using uint64+uint32 instead of [3]uint32 we can make use of the guaranteed alignment to avoid the run-time alignment check. On linux/amd64: name old time/op new time/op delta WaitGroupUncontended-4 8.84ns ± 3% 7.62ns ± 4% -13.72% (p=0.000 n=17+18) WaitGroupAddDone-4 66.8ns ± 3% 45.9ns ± 2% -31.31% (p=0.000 n=20+18) WaitGroupAddDoneWork-4 79.2ns ± 1% 56.6ns ± 1% -28.54% (p=0.000 n=17+20) WaitGroupWait-4 2.83ns ± 2% 2.58ns ± 2% -9.05% (p=0.000 n=18+20) WaitGroupWaitWork-4 16.8ns ± 6% 16.5ns ± 6% ~ (p=0.072 n=20+18) WaitGroupActuallyWait-4 263ns ± 2% 261ns ± 5% ~ (p=0.063 n=18+20) Change-Id: I314340f2ed8a47d8b9c15f8a3b07e41f252f4831 Reviewed-on: https://go-review.googlesource.com/c/go/+/189837 Reviewed-by: Cherry Mui Reviewed-by: Ian Lance Taylor Run-TryBot: Cherry Mui TryBot-Result: Go Bot --- src/sync/waitgroup.go | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/sync/waitgroup.go b/src/sync/waitgroup.go index e81a493dea..9c6662d04b 100644 --- a/src/sync/waitgroup.go +++ b/src/sync/waitgroup.go @@ -22,18 +22,24 @@ type WaitGroup struct { // 64-bit value: high 32 bits are counter, low 32 bits are waiter count. // 64-bit atomic operations require 64-bit alignment, but 32-bit - // compilers do not ensure it. So we allocate 12 bytes and then use - // the aligned 8 bytes in them as state, and the other 4 as storage - // for the sema. - state1 [3]uint32 + // compilers only guarantee that 64-bit fields are 32-bit aligned. + // For this reason on 32 bit architectures we need to check in state() + // if state1 is aligned or not, and dynamically "swap" the field order if + // needed. + state1 uint64 + state2 uint32 } -// state returns pointers to the state and sema fields stored within wg.state1. +// state returns pointers to the state and sema fields stored within wg.state*. func (wg *WaitGroup) state() (statep *uint64, semap *uint32) { - if uintptr(unsafe.Pointer(&wg.state1))%8 == 0 { - return (*uint64)(unsafe.Pointer(&wg.state1)), &wg.state1[2] + if unsafe.Alignof(wg.state1) == 8 || uintptr(unsafe.Pointer(&wg.state1))%8 == 0 { + // state1 is 64-bit aligned: nothing to do. + return &wg.state1, &wg.state2 } else { - return (*uint64)(unsafe.Pointer(&wg.state1[1])), &wg.state1[0] + // state1 is 32-bit aligned but not 64-bit aligned: this means that + // (&state1)+4 is 64-bit aligned. + state := (*[3]uint32)(unsafe.Pointer(&wg.state1)) + return (*uint64)(unsafe.Pointer(&state[1])), &state[0] } } -- GitLab From 6c3cd5d2eb7149c9c1ced7d70c3f4157f27c1588 Mon Sep 17 00:00:00 2001 From: Archana R Date: Wed, 13 Oct 2021 03:50:06 -0500 Subject: [PATCH 1660/2500] internal/bytealg: port bytes.Index and bytes.Count to reg ABI on ppc64x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change adds support for the reg ABI to the Index and Count functions for ppc64/ppc64le. Most Index and Count benchmarks show improvement in performance on POWER9 with this change. Similar numbers observed on POWER8 and POWER10. name old time/op new time/op delta Index/32 71.0ns ± 0% 67.9ns ± 0% -4.42% (p=0.001 n=7+6) IndexEasy/10 17.5ns ± 0% 17.2ns ± 0% -1.30% (p=0.001 n=7+7) name old time/op new time/op delta Count/10 26.6ns ± 0% 25.0ns ± 1% -6.02% (p=0.001 n=7+7) Count/32 78.6ns ± 0% 74.7ns ± 0% -4.97% (p=0.001 n=7+7) Count/4K 5.03µs ± 0% 5.03µs ± 0% -0.07% (p=0.000 n=6+7) CountEasy/10 26.9ns ± 0% 25.2ns ± 1% -6.31% (p=0.001 n=7+7) CountSingle/32 11.8ns ± 0% 9.9ns ± 0% -15.70% (p=0.002 n=6+6) Change-Id: Ibd146c04f8107291c55f9e6100b8264dfccc41ae Reviewed-on: https://go-review.googlesource.com/c/go/+/355509 Reviewed-by: Cherry Mui Reviewed-by: Lynn Boger Run-TryBot: Cherry Mui TryBot-Result: Go Bot --- src/internal/bytealg/count_ppc64x.s | 24 +++++++++++++++--- src/internal/bytealg/index_ppc64x.s | 39 +++++++++++++++++++++++++++-- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/src/internal/bytealg/count_ppc64x.s b/src/internal/bytealg/count_ppc64x.s index 94163cbd8a..dbafd06edc 100644 --- a/src/internal/bytealg/count_ppc64x.s +++ b/src/internal/bytealg/count_ppc64x.s @@ -8,24 +8,37 @@ #include "go_asm.h" #include "textflag.h" -TEXT ·Count(SB), NOSPLIT|NOFRAME, $0-40 +TEXT ·Count(SB),NOSPLIT|NOFRAME,$0-40 +#ifdef GOEXPERIMENT_regabiargs +// R3 = byte array pointer +// R4 = length + MOVBZ R6,R5 // R5 = byte +#else + MOVD b_base+0(FP), R3 // R3 = byte array pointer MOVD b_len+8(FP), R4 // R4 = length MOVBZ c+24(FP), R5 // R5 = byte MOVD $ret+32(FP), R14 // R14 = &ret +#endif BR countbytebody<>(SB) -TEXT ·CountString(SB), NOSPLIT|NOFRAME, $0-32 +TEXT ·CountString(SB), NOSPLIT|NOFRAME, $0-32 +#ifdef GOEXPERIMENT_regabiargs +// R3 = byte array pointer +// R4 = length + MOVBZ R5,R5 // R5 = byte +#else MOVD s_base+0(FP), R3 // R3 = string MOVD s_len+8(FP), R4 // R4 = length MOVBZ c+16(FP), R5 // R5 = byte MOVD $ret+24(FP), R14 // R14 = &ret +#endif BR countbytebody<>(SB) // R3: addr of string // R4: len of string // R5: byte to count -// R14: addr for return value +// R14: addr for return value when not regabi // endianness shouldn't matter since we are just counting and order // is irrelevant TEXT countbytebody<>(SB), NOSPLIT|NOFRAME, $0-0 @@ -94,5 +107,10 @@ next2: BR small done: +#ifdef GOEXPERIMENT_regabiargs + MOVD R18, R3 // return count +#else MOVD R18, (R14) // return count +#endif + RET diff --git a/src/internal/bytealg/index_ppc64x.s b/src/internal/bytealg/index_ppc64x.s index 3ed9442125..f587a8ae25 100644 --- a/src/internal/bytealg/index_ppc64x.s +++ b/src/internal/bytealg/index_ppc64x.s @@ -46,12 +46,20 @@ DATA byteswap<>+8(SB)/8, $0x0f0e0d0c0b0a0908 GLOBL byteswap<>+0(SB), RODATA, $16 -TEXT ·Index(SB), NOSPLIT|NOFRAME, $0-56 +TEXT ·Index(SB),NOSPLIT|NOFRAME,$0-56 +#ifdef GOEXPERIMENT_regabiargs +// R3 = byte array pointer +// R4 = length + MOVD R6,R5 // R5 = separator pointer + MOVD R7,R6 // R6 = separator length +#else MOVD a_base+0(FP), R3 // R3 = byte array pointer MOVD a_len+8(FP), R4 // R4 = length MOVD b_base+24(FP), R5 // R5 = separator pointer MOVD b_len+32(FP), R6 // R6 = separator length MOVD $ret+48(FP), R14 // R14 = &ret +#endif + #ifdef GOARCH_ppc64le MOVBZ internal∕cpu·PPC64+const_offsetPPC64HasPOWER9(SB), R7 @@ -63,12 +71,15 @@ TEXT ·Index(SB), NOSPLIT|NOFRAME, $0-56 power8: BR indexbody<>(SB) -TEXT ·IndexString(SB), NOSPLIT|NOFRAME, $0-40 +TEXT ·IndexString(SB),NOSPLIT|NOFRAME,$0-40 +#ifndef GOEXPERIMENT_regabiargs MOVD a_base+0(FP), R3 // R3 = string MOVD a_len+8(FP), R4 // R4 = length MOVD b_base+16(FP), R5 // R5 = separator pointer MOVD b_len+24(FP), R6 // R6 = separator length MOVD $ret+32(FP), R14 // R14 = &ret +#endif + #ifdef GOARCH_ppc64le MOVBZ internal∕cpu·PPC64+const_offsetPPC64HasPOWER9(SB), R7 @@ -420,8 +431,12 @@ next17: BR index17to32loop // Continue notfound: +#ifdef GOEXPERIMENT_regabiargs + MOVD $-1, R3 // Return -1 if not found +#else MOVD $-1, R8 // Return -1 if not found MOVD R8, (R14) +#endif RET index33plus: @@ -432,12 +447,20 @@ foundR25: SRD $3, R25 // Convert from bits to bytes ADD R25, R7 // Add to current string address SUB R3, R7 // Subtract from start of string +#ifdef GOEXPERIMENT_regabiargs + MOVD R7, R3 // Return byte where found +#else MOVD R7, (R14) // Return byte where found +#endif RET found: SUB R3, R7 // Return byte where found +#ifdef GOEXPERIMENT_regabiargs + MOVD R7, R3 +#else MOVD R7, (R14) +#endif RET TEXT indexbodyp9<>(SB), NOSPLIT|NOFRAME, $0 @@ -746,8 +769,12 @@ next17: BR index17to32loop // Continue notfound: +#ifdef GOEXPERIMENT_regabiargs + MOVD $-1, R3 // Return -1 if not found +#else MOVD $-1, R8 // Return -1 if not found MOVD R8, (R14) +#endif RET index33plus: @@ -758,11 +785,19 @@ foundR25: SRD $3, R25 // Convert from bits to bytes ADD R25, R7 // Add to current string address SUB R3, R7 // Subtract from start of string +#ifdef GOEXPERIMENT_regabiargs + MOVD R7, R3 // Return byte where found +#else MOVD R7, (R14) // Return byte where found +#endif RET found: SUB R3, R7 // Return byte where found +#ifdef GOEXPERIMENT_regabiargs + MOVD R7, R3 +#else MOVD R7, (R14) +#endif RET -- GitLab From 7999fd4710e7f987e86d7b32dd9af31ced4810ba Mon Sep 17 00:00:00 2001 From: "Matt T. Proud" Date: Tue, 19 Oct 2021 10:09:06 +0200 Subject: [PATCH 1661/2500] errors: mention Is methods should not call Unwrap errors.Is internally unwraps the error until the error matches the target. Because of this, a user-authored Is method on an error type need not call errors.Unwrap on itself or the target, because that would make the unwrapping operation O(N^2). It is a subtle detail to remind authors for resource efficiency reasons. Change-Id: Ic1ba59a5bdbfe2c7cb51a2cba2537ab6de4a13ff Reviewed-on: https://go-review.googlesource.com/c/go/+/356789 Reviewed-by: Jean de Klerk Reviewed-by: Damien Neil Trust: Jean de Klerk Trust: Damien Neil Run-TryBot: Jean de Klerk TryBot-Result: Go Bot --- src/errors/wrap.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/errors/wrap.go b/src/errors/wrap.go index 4eb4f9ae37..b73d5a8ce2 100644 --- a/src/errors/wrap.go +++ b/src/errors/wrap.go @@ -35,7 +35,8 @@ func Unwrap(err error) error { // func (m MyError) Is(target error) bool { return target == fs.ErrExist } // // then Is(MyError{}, fs.ErrExist) returns true. See syscall.Errno.Is for -// an example in the standard library. +// an example in the standard library. An Is method should only shallowly +// compare err and the target and not call Unwrap on either. func Is(err, target error) bool { if target == nil { return err == target -- GitLab From 1d63052782a7535a3d4ce4557fd23fd97699b249 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Fri, 17 Sep 2021 19:38:33 -0400 Subject: [PATCH 1662/2500] cmd/go: support replaces in the go.work file Add support for replace directives in the go.work file. If there are conflicting replaces in go.mod files, suggest that users add an overriding replace in the go.work file. Add HighestReplaced to MainModules so that it accounts for the replacements in the go.work file. (Reviewers: I'm not totally sure that HighestReplace is computed correctly. Could you take a closer look at that?) For #45713 Change-Id: I1d789219ca1dd065ba009ce5d38db9a1fc38ba83 Reviewed-on: https://go-review.googlesource.com/c/go/+/352812 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/modcmd/vendor.go | 2 +- src/cmd/go/internal/modget/get.go | 4 +- src/cmd/go/internal/modload/build.go | 14 +- src/cmd/go/internal/modload/import.go | 58 ++++--- src/cmd/go/internal/modload/init.go | 157 ++++++++++++------ src/cmd/go/internal/modload/load.go | 6 +- src/cmd/go/internal/modload/modfile.go | 157 ++++++++++-------- src/cmd/go/internal/modload/query.go | 40 +---- src/cmd/go/internal/modload/vendor.go | 2 +- src/cmd/go/testdata/script/work_edit.txt | 2 +- src/cmd/go/testdata/script/work_replace.txt | 55 ++++++ .../testdata/script/work_replace_conflict.txt | 53 ++++++ .../script/work_replace_conflict_override.txt | 57 +++++++ 13 files changed, 408 insertions(+), 199 deletions(-) create mode 100644 src/cmd/go/testdata/script/work_replace.txt create mode 100644 src/cmd/go/testdata/script/work_replace_conflict.txt create mode 100644 src/cmd/go/testdata/script/work_replace_conflict_override.txt diff --git a/src/cmd/go/internal/modcmd/vendor.go b/src/cmd/go/internal/modcmd/vendor.go index 92348b8897..57189b4607 100644 --- a/src/cmd/go/internal/modcmd/vendor.go +++ b/src/cmd/go/internal/modcmd/vendor.go @@ -128,7 +128,7 @@ func runVendor(ctx context.Context, cmd *base.Command, args []string) { } for _, m := range vendorMods { - replacement, _ := modload.Replacement(m) + replacement := modload.Replacement(m) line := moduleLine(m, replacement) io.WriteString(w, line) diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index c634512072..2c48c3c444 100644 --- a/src/cmd/go/internal/modget/get.go +++ b/src/cmd/go/internal/modget/get.go @@ -1575,7 +1575,7 @@ func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []strin i := i m := r.buildList[i] mActual := m - if mRepl, _ := modload.Replacement(m); mRepl.Path != "" { + if mRepl := modload.Replacement(m); mRepl.Path != "" { mActual = mRepl } old := module.Version{Path: m.Path, Version: r.initialVersion[m.Path]} @@ -1583,7 +1583,7 @@ func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []strin continue } oldActual := old - if oldRepl, _ := modload.Replacement(old); oldRepl.Path != "" { + if oldRepl := modload.Replacement(old); oldRepl.Path != "" { oldActual = oldRepl } if mActual == oldActual || mActual.Version == "" || !modfetch.HaveSum(oldActual) { diff --git a/src/cmd/go/internal/modload/build.go b/src/cmd/go/internal/modload/build.go index da50743138..0e0292ec15 100644 --- a/src/cmd/go/internal/modload/build.go +++ b/src/cmd/go/internal/modload/build.go @@ -239,7 +239,7 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li } // completeFromModCache fills in the extra fields in m using the module cache. - completeFromModCache := func(m *modinfo.ModulePublic, replacedFrom string) { + completeFromModCache := func(m *modinfo.ModulePublic) { checksumOk := func(suffix string) bool { return rs == nil || m.Version == "" || cfg.BuildMod == "mod" || modfetch.HaveSum(module.Version{Path: m.Path, Version: m.Version + suffix}) @@ -258,7 +258,7 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li if m.GoVersion == "" && checksumOk("/go.mod") { // Load the go.mod file to determine the Go version, since it hasn't // already been populated from rawGoVersion. - if summary, err := rawGoModSummary(mod, replacedFrom); err == nil && summary.goVersion != "" { + if summary, err := rawGoModSummary(mod); err == nil && summary.goVersion != "" { m.GoVersion = summary.goVersion } } @@ -288,11 +288,11 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li if rs == nil { // If this was an explicitly-versioned argument to 'go mod download' or // 'go list -m', report the actual requested version, not its replacement. - completeFromModCache(info, "") // Will set m.Error in vendor mode. + completeFromModCache(info) // Will set m.Error in vendor mode. return info } - r, replacedFrom := Replacement(m) + r := Replacement(m) if r.Path == "" { if cfg.BuildMod == "vendor" { // It's tempting to fill in the "Dir" field to point within the vendor @@ -301,7 +301,7 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li // interleave packages from different modules if one module path is a // prefix of the other. } else { - completeFromModCache(info, "") + completeFromModCache(info) } return info } @@ -321,12 +321,12 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li if filepath.IsAbs(r.Path) { info.Replace.Dir = r.Path } else { - info.Replace.Dir = filepath.Join(replacedFrom, r.Path) + info.Replace.Dir = filepath.Join(replaceRelativeTo(), r.Path) } info.Replace.GoMod = filepath.Join(info.Replace.Dir, "go.mod") } if cfg.BuildMod != "vendor" { - completeFromModCache(info.Replace, replacedFrom) + completeFromModCache(info.Replace) info.Dir = info.Replace.Dir info.GoMod = info.Replace.GoMod info.Retracted = info.Replace.Retracted diff --git a/src/cmd/go/internal/modload/import.go b/src/cmd/go/internal/modload/import.go index e64677acd0..bc2b0a0230 100644 --- a/src/cmd/go/internal/modload/import.go +++ b/src/cmd/go/internal/modload/import.go @@ -426,35 +426,33 @@ func queryImport(ctx context.Context, path string, rs *Requirements) (module.Ver // To avoid spurious remote fetches, try the latest replacement for each // module (golang.org/issue/26241). var mods []module.Version - for _, v := range MainModules.Versions() { - if index := MainModules.Index(v); index != nil { - for mp, mv := range index.highestReplaced { - if !maybeInModule(path, mp) { - continue - } - if mv == "" { - // The only replacement is a wildcard that doesn't specify a version, so - // synthesize a pseudo-version with an appropriate major version and a - // timestamp below any real timestamp. That way, if the main module is - // used from within some other module, the user will be able to upgrade - // the requirement to any real version they choose. - if _, pathMajor, ok := module.SplitPathVersion(mp); ok && len(pathMajor) > 0 { - mv = module.ZeroPseudoVersion(pathMajor[1:]) - } else { - mv = module.ZeroPseudoVersion("v0") - } - } - mg, err := rs.Graph(ctx) - if err != nil { - return module.Version{}, err - } - if cmpVersion(mg.Selected(mp), mv) >= 0 { - // We can't resolve the import by adding mp@mv to the module graph, - // because the selected version of mp is already at least mv. - continue + if MainModules != nil { // TODO(#48912): Ensure MainModules exists at this point, and remove the check. + for mp, mv := range MainModules.HighestReplaced() { + if !maybeInModule(path, mp) { + continue + } + if mv == "" { + // The only replacement is a wildcard that doesn't specify a version, so + // synthesize a pseudo-version with an appropriate major version and a + // timestamp below any real timestamp. That way, if the main module is + // used from within some other module, the user will be able to upgrade + // the requirement to any real version they choose. + if _, pathMajor, ok := module.SplitPathVersion(mp); ok && len(pathMajor) > 0 { + mv = module.ZeroPseudoVersion(pathMajor[1:]) + } else { + mv = module.ZeroPseudoVersion("v0") } - mods = append(mods, module.Version{Path: mp, Version: mv}) } + mg, err := rs.Graph(ctx) + if err != nil { + return module.Version{}, err + } + if cmpVersion(mg.Selected(mp), mv) >= 0 { + // We can't resolve the import by adding mp@mv to the module graph, + // because the selected version of mp is already at least mv. + continue + } + mods = append(mods, module.Version{Path: mp, Version: mv}) } } @@ -485,7 +483,7 @@ func queryImport(ctx context.Context, path string, rs *Requirements) (module.Ver // The package path is not valid to fetch remotely, // so it can only exist in a replaced module, // and we know from the above loop that it is not. - replacement, _ := Replacement(mods[0]) + replacement := Replacement(mods[0]) return module.Version{}, &PackageNotInModuleError{ Mod: mods[0], Query: "latest", @@ -659,11 +657,11 @@ func fetch(ctx context.Context, mod module.Version, needSum bool) (dir string, i if modRoot := MainModules.ModRoot(mod); modRoot != "" { return modRoot, true, nil } - if r, replacedFrom := Replacement(mod); r.Path != "" { + if r := Replacement(mod); r.Path != "" { if r.Version == "" { dir = r.Path if !filepath.IsAbs(dir) { - dir = filepath.Join(replacedFrom, dir) + dir = filepath.Join(replaceRelativeTo(), dir) } // Ensure that the replacement directory actually exists: // dirInModule does not report errors for missing modules, diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 621099beb3..0602aee0cc 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -69,9 +69,8 @@ var ( // roots are required but MainModules hasn't been initialized yet. Set to // the modRoots of the main modules. // modRoots != nil implies len(modRoots) > 0 - modRoots []string - gopath string - workFileGoVersion string + modRoots []string + gopath string ) // Variable set in InitWorkfile @@ -104,6 +103,10 @@ type MainModuleSet struct { workFileGoVersion string + workFileReplaceMap map[module.Version]module.Version + // highest replaced version of each module path; empty string for wildcard-only replacements + highestReplaced map[string]string + indexMu sync.Mutex indices map[module.Version]*modFileIndex } @@ -203,6 +206,10 @@ func (mms *MainModuleSet) ModContainingCWD() module.Version { return mms.modContainingCWD } +func (mms *MainModuleSet) HighestReplaced() map[string]string { + return mms.highestReplaced +} + // GoVersion returns the go version set on the single module, in module mode, // or the go.work file in workspace mode. func (mms *MainModuleSet) GoVersion() string { @@ -217,6 +224,10 @@ func (mms *MainModuleSet) GoVersion() string { return v } +func (mms *MainModuleSet) WorkFileReplaceMap() map[module.Version]module.Version { + return mms.workFileReplaceMap +} + var MainModules *MainModuleSet type Root int @@ -275,6 +286,9 @@ func InitWorkfile() { case "", "auto": workFilePath = findWorkspaceFile(base.Cwd()) default: + if !filepath.IsAbs(cfg.WorkFile) { + base.Errorf("the path provided to -workfile must be an absolute path") + } workFilePath = cfg.WorkFile } } @@ -403,37 +417,6 @@ func Init() { base.Fatalf("$GOPATH/go.mod exists but should not") } } - - if inWorkspaceMode() { - var err error - workFileGoVersion, modRoots, err = loadWorkFile(workFilePath) - if err != nil { - base.Fatalf("reading go.work: %v", err) - } - _ = TODOWorkspaces("Support falling back to individual module go.sum " + - "files for sums not in the workspace sum file.") - modfetch.GoSumFile = workFilePath + ".sum" - } else if modRoots == nil { - // We're in module mode, but not inside a module. - // - // Commands like 'go build', 'go run', 'go list' have no go.mod file to - // read or write. They would need to find and download the latest versions - // of a potentially large number of modules with no way to save version - // information. We can succeed slowly (but not reproducibly), but that's - // not usually a good experience. - // - // Instead, we forbid resolving import paths to modules other than std and - // cmd. Users may still build packages specified with .go files on the - // command line, but they'll see an error if those files import anything - // outside std. - // - // This can be overridden by calling AllowMissingModuleImports. - // For example, 'go get' does this, since it is expected to resolve paths. - // - // See golang.org/issue/32027. - } else { - modfetch.GoSumFile = strings.TrimSuffix(modFilePath(modRoots[0]), ".mod") + ".sum" - } } // WillBeEnabled checks whether modules should be enabled but does not @@ -568,16 +551,16 @@ func (goModDirtyError) Error() string { var errGoModDirty error = goModDirtyError{} -func loadWorkFile(path string) (goVersion string, modRoots []string, err error) { +func loadWorkFile(path string) (goVersion string, modRoots []string, replaces []*modfile.Replace, err error) { _ = TODOWorkspaces("Clean up and write back the go.work file: add module paths for workspace modules.") workDir := filepath.Dir(path) workData, err := lockedfile.Read(path) if err != nil { - return "", nil, err + return "", nil, nil, err } wf, err := modfile.ParseWork(path, workData, nil) if err != nil { - return "", nil, err + return "", nil, nil, err } if wf.Go != nil { goVersion = wf.Go.Version @@ -589,12 +572,12 @@ func loadWorkFile(path string) (goVersion string, modRoots []string, err error) modRoot = filepath.Join(workDir, modRoot) } if seen[modRoot] { - return "", nil, fmt.Errorf("path %s appears multiple times in workspace", modRoot) + return "", nil, nil, fmt.Errorf("path %s appears multiple times in workspace", modRoot) } seen[modRoot] = true modRoots = append(modRoots, modRoot) } - return goVersion, modRoots, nil + return goVersion, modRoots, wf.Replace, nil } // LoadModFile sets Target and, if there is a main module, parses the initial @@ -621,10 +604,44 @@ func LoadModFile(ctx context.Context) *Requirements { } Init() + var ( + workFileGoVersion string + workFileReplaces []*modfile.Replace + ) + if inWorkspaceMode() { + var err error + workFileGoVersion, modRoots, workFileReplaces, err = loadWorkFile(workFilePath) + if err != nil { + base.Fatalf("reading go.work: %v", err) + } + _ = TODOWorkspaces("Support falling back to individual module go.sum " + + "files for sums not in the workspace sum file.") + modfetch.GoSumFile = workFilePath + ".sum" + } else if modRoots == nil { + // We're in module mode, but not inside a module. + // + // Commands like 'go build', 'go run', 'go list' have no go.mod file to + // read or write. They would need to find and download the latest versions + // of a potentially large number of modules with no way to save version + // information. We can succeed slowly (but not reproducibly), but that's + // not usually a good experience. + // + // Instead, we forbid resolving import paths to modules other than std and + // cmd. Users may still build packages specified with .go files on the + // command line, but they'll see an error if those files import anything + // outside std. + // + // This can be overridden by calling AllowMissingModuleImports. + // For example, 'go get' does this, since it is expected to resolve paths. + // + // See golang.org/issue/32027. + } else { + modfetch.GoSumFile = strings.TrimSuffix(modFilePath(modRoots[0]), ".mod") + ".sum" + } if len(modRoots) == 0 { _ = TODOWorkspaces("Instead of creating a fake module with an empty modroot, make MainModules.Len() == 0 mean that we're in module mode but not inside any module.") mainModule := module.Version{Path: "command-line-arguments"} - MainModules = makeMainModules([]module.Version{mainModule}, []string{""}, []*modfile.File{nil}, []*modFileIndex{nil}, "") + MainModules = makeMainModules([]module.Version{mainModule}, []string{""}, []*modfile.File{nil}, []*modFileIndex{nil}, "", nil) goVersion := LatestGoVersion() rawGoVersion.Store(mainModule, goVersion) requirements = newRequirements(pruningForGoVersion(goVersion), nil, nil) @@ -655,7 +672,7 @@ func LoadModFile(ctx context.Context) *Requirements { } } - MainModules = makeMainModules(mainModules, modRoots, modFiles, indices, workFileGoVersion) + MainModules = makeMainModules(mainModules, modRoots, modFiles, indices, workFileGoVersion, workFileReplaces) setDefaultBuildMod() // possibly enable automatic vendoring rs := requirementsFromModFiles(ctx, modFiles) @@ -758,7 +775,7 @@ func CreateModFile(ctx context.Context, modPath string) { fmt.Fprintf(os.Stderr, "go: creating new go.mod: module %s\n", modPath) modFile := new(modfile.File) modFile.AddModuleStmt(modPath) - MainModules = makeMainModules([]module.Version{modFile.Module.Mod}, []string{modRoot}, []*modfile.File{modFile}, []*modFileIndex{nil}, "") + MainModules = makeMainModules([]module.Version{modFile.Module.Mod}, []string{modRoot}, []*modfile.File{modFile}, []*modFileIndex{nil}, "", nil) addGoStmt(modFile, modFile.Module.Mod, LatestGoVersion()) // Add the go directive before converted module requirements. convertedFrom, err := convertLegacyConfig(modFile, modRoot) @@ -893,7 +910,7 @@ func AllowMissingModuleImports() { // makeMainModules creates a MainModuleSet and associated variables according to // the given main modules. -func makeMainModules(ms []module.Version, rootDirs []string, modFiles []*modfile.File, indices []*modFileIndex, workFileGoVersion string) *MainModuleSet { +func makeMainModules(ms []module.Version, rootDirs []string, modFiles []*modfile.File, indices []*modFileIndex, workFileGoVersion string, workFileReplaces []*modfile.Replace) *MainModuleSet { for _, m := range ms { if m.Version != "" { panic("mainModulesCalled with module.Version with non empty Version field: " + fmt.Sprintf("%#v", m)) @@ -901,13 +918,25 @@ func makeMainModules(ms []module.Version, rootDirs []string, modFiles []*modfile } modRootContainingCWD := findModuleRoot(base.Cwd()) mainModules := &MainModuleSet{ - versions: ms[:len(ms):len(ms)], - inGorootSrc: map[module.Version]bool{}, - pathPrefix: map[module.Version]string{}, - modRoot: map[module.Version]string{}, - modFiles: map[module.Version]*modfile.File{}, - indices: map[module.Version]*modFileIndex{}, - workFileGoVersion: workFileGoVersion, + versions: ms[:len(ms):len(ms)], + inGorootSrc: map[module.Version]bool{}, + pathPrefix: map[module.Version]string{}, + modRoot: map[module.Version]string{}, + modFiles: map[module.Version]*modfile.File{}, + indices: map[module.Version]*modFileIndex{}, + workFileGoVersion: workFileGoVersion, + workFileReplaceMap: toReplaceMap(workFileReplaces), + highestReplaced: map[string]string{}, + } + replacedByWorkFile := make(map[string]bool) + replacements := make(map[module.Version]module.Version) + for _, r := range workFileReplaces { + replacedByWorkFile[r.Old.Path] = true + v, ok := mainModules.highestReplaced[r.Old.Path] + if !ok || semver.Compare(r.Old.Version, v) > 0 { + mainModules.highestReplaced[r.Old.Path] = r.Old.Version + } + replacements[r.Old] = r.New } for i, m := range ms { mainModules.pathPrefix[m] = m.Path @@ -933,6 +962,24 @@ func makeMainModules(ms []module.Version, rootDirs []string, modFiles []*modfile mainModules.pathPrefix[m] = "" } } + + if modFiles[i] != nil { + curModuleReplaces := make(map[module.Version]bool) + for _, r := range modFiles[i].Replace { + if replacedByWorkFile[r.Old.Path] { + continue + } else if prev, ok := replacements[r.Old]; ok && !curModuleReplaces[r.Old] { + base.Fatalf("go: conflicting replacements for %v:\n\t%v\n\t%v\nuse \"go mod editwork -replace %v=[override]\" to resolve", r.Old, prev, r.New, r.Old) + } + curModuleReplaces[r.Old] = true + replacements[r.Old] = r.New + + v, ok := mainModules.highestReplaced[r.Old.Path] + if !ok || semver.Compare(r.Old.Version, v) > 0 { + mainModules.highestReplaced[r.Old.Path] = r.Old.Version + } + } + } } return mainModules } @@ -1471,7 +1518,7 @@ func keepSums(ctx context.Context, ld *loader, rs *Requirements, which whichSums for prefix := pkg.path; prefix != "."; prefix = path.Dir(prefix) { if v, ok := rs.rootSelected(prefix); ok && v != "none" { m := module.Version{Path: prefix, Version: v} - r, _ := resolveReplacement(m) + r := resolveReplacement(m) keep[r] = true } } @@ -1483,7 +1530,7 @@ func keepSums(ctx context.Context, ld *loader, rs *Requirements, which whichSums for prefix := pkg.path; prefix != "."; prefix = path.Dir(prefix) { if v := mg.Selected(prefix); v != "none" { m := module.Version{Path: prefix, Version: v} - r, _ := resolveReplacement(m) + r := resolveReplacement(m) keep[r] = true } } @@ -1495,7 +1542,7 @@ func keepSums(ctx context.Context, ld *loader, rs *Requirements, which whichSums // Save sums for the root modules (or their replacements), but don't // incur the cost of loading the graph just to find and retain the sums. for _, m := range rs.rootModules { - r, _ := resolveReplacement(m) + r := resolveReplacement(m) keep[modkey(r)] = true if which == addBuildListZipSums { keep[r] = true @@ -1508,14 +1555,14 @@ func keepSums(ctx context.Context, ld *loader, rs *Requirements, which whichSums // The requirements from m's go.mod file are present in the module graph, // so they are relevant to the MVS result regardless of whether m was // actually selected. - r, _ := resolveReplacement(m) + r := resolveReplacement(m) keep[modkey(r)] = true } }) if which == addBuildListZipSums { for _, m := range mg.BuildList() { - r, _ := resolveReplacement(m) + r := resolveReplacement(m) keep[r] = true } } diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index 3498c662f3..0f5b015000 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -607,10 +607,10 @@ func pathInModuleCache(ctx context.Context, dir string, rs *Requirements) string tryMod := func(m module.Version) (string, bool) { var root string var err error - if repl, replModRoot := Replacement(m); repl.Path != "" && repl.Version == "" { + if repl := Replacement(m); repl.Path != "" && repl.Version == "" { root = repl.Path if !filepath.IsAbs(root) { - root = filepath.Join(replModRoot, root) + root = filepath.Join(replaceRelativeTo(), root) } } else if repl.Path != "" { root, err = modfetch.DownloadDir(repl) @@ -1834,7 +1834,7 @@ func (ld *loader) checkMultiplePaths() { firstPath := map[module.Version]string{} for _, mod := range mods { - src, _ := resolveReplacement(mod) + src := resolveReplacement(mod) if prev, ok := firstPath[src]; !ok { firstPath[src] = mod.Path } else if prev != mod.Path { diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index bf05e92ba2..87e8a5e83d 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -99,14 +99,13 @@ func modFileGoVersion(modFile *modfile.File) string { // A modFileIndex is an index of data corresponding to a modFile // at a specific point in time. type modFileIndex struct { - data []byte - dataNeedsFix bool // true if fixVersion applied a change while parsing data - module module.Version - goVersionV string // GoVersion with "v" prefix - require map[module.Version]requireMeta - replace map[module.Version]module.Version - highestReplaced map[string]string // highest replaced version of each module path; empty string for wildcard-only replacements - exclude map[module.Version]bool + data []byte + dataNeedsFix bool // true if fixVersion applied a change while parsing data + module module.Version + goVersionV string // GoVersion with "v" prefix + require map[module.Version]requireMeta + replace map[module.Version]module.Version + exclude map[module.Version]bool } type requireMeta struct { @@ -187,7 +186,7 @@ func CheckRetractions(ctx context.Context, m module.Version) (err error) { // Cannot be retracted. return nil } - if repl, _ := Replacement(module.Version{Path: m.Path}); repl.Path != "" { + if repl := Replacement(module.Version{Path: m.Path}); repl.Path != "" { // All versions of the module were replaced. // Don't load retractions, since we'd just load the replacement. return nil @@ -204,11 +203,11 @@ func CheckRetractions(ctx context.Context, m module.Version) (err error) { // We load the raw file here: the go.mod file may have a different module // path that we expect if the module or its repository was renamed. // We still want to apply retractions to other aliases of the module. - rm, replacedFrom, err := queryLatestVersionIgnoringRetractions(ctx, m.Path) + rm, err := queryLatestVersionIgnoringRetractions(ctx, m.Path) if err != nil { return err } - summary, err := rawGoModSummary(rm, replacedFrom) + summary, err := rawGoModSummary(rm) if err != nil { return err } @@ -306,66 +305,107 @@ func CheckDeprecation(ctx context.Context, m module.Version) (deprecation string // Don't look up deprecation. return "", nil } - if repl, _ := Replacement(module.Version{Path: m.Path}); repl.Path != "" { + if repl := Replacement(module.Version{Path: m.Path}); repl.Path != "" { // All versions of the module were replaced. // We'll look up deprecation separately for the replacement. return "", nil } - latest, replacedFrom, err := queryLatestVersionIgnoringRetractions(ctx, m.Path) + latest, err := queryLatestVersionIgnoringRetractions(ctx, m.Path) if err != nil { return "", err } - summary, err := rawGoModSummary(latest, replacedFrom) + summary, err := rawGoModSummary(latest) if err != nil { return "", err } return summary.deprecated, nil } -func replacement(mod module.Version, index *modFileIndex) (fromVersion string, to module.Version, ok bool) { - if r, ok := index.replace[mod]; ok { +func replacement(mod module.Version, replace map[module.Version]module.Version) (fromVersion string, to module.Version, ok bool) { + if r, ok := replace[mod]; ok { return mod.Version, r, true } - if r, ok := index.replace[module.Version{Path: mod.Path}]; ok { + if r, ok := replace[module.Version{Path: mod.Path}]; ok { return "", r, true } return "", module.Version{}, false } -// Replacement returns the replacement for mod, if any, and and the module root -// directory of the main module containing the replace directive. -// If there is no replacement for mod, Replacement returns -// a module.Version with Path == "". -func Replacement(mod module.Version) (module.Version, string) { - _ = TODOWorkspaces("Support replaces in the go.work file.") +// Replacement returns the replacement for mod, if any. If the path in the +// module.Version is relative it's relative to the single main module outside +// workspace mode, or the workspace's directory in workspace mode. +func Replacement(mod module.Version) module.Version { foundFrom, found, foundModRoot := "", module.Version{}, "" + if MainModules == nil { + return module.Version{} + } + if _, r, ok := replacement(mod, MainModules.WorkFileReplaceMap()); ok { + return r + } for _, v := range MainModules.Versions() { if index := MainModules.Index(v); index != nil { - if from, r, ok := replacement(mod, index); ok { + if from, r, ok := replacement(mod, index.replace); ok { modRoot := MainModules.ModRoot(v) if foundModRoot != "" && foundFrom != from && found != r { - _ = TODOWorkspaces("once the go.work file supports replaces, recommend them as a way to override conflicts") base.Errorf("conflicting replacements found for %v in workspace modules defined by %v and %v", mod, modFilePath(foundModRoot), modFilePath(modRoot)) - return found, foundModRoot + return canonicalizeReplacePath(found, foundModRoot) } found, foundModRoot = r, modRoot } } } - return found, foundModRoot + return canonicalizeReplacePath(found, foundModRoot) +} + +func replaceRelativeTo() string { + if workFilePath := WorkFilePath(); workFilePath != "" { + return filepath.Dir(workFilePath) + } + return MainModules.ModRoot(MainModules.mustGetSingleMainModule()) +} + +// canonicalizeReplacePath ensures that relative, on-disk, replaced module paths +// are relative to the workspace directory (in workspace mode) or to the module's +// directory (in module mode, as they already are). +func canonicalizeReplacePath(r module.Version, modRoot string) module.Version { + if filepath.IsAbs(r.Path) || r.Version != "" { + return r + } + workFilePath := WorkFilePath() + if workFilePath == "" { + return r + } + abs := filepath.Join(modRoot, r.Path) + if rel, err := filepath.Rel(workFilePath, abs); err == nil { + return module.Version{Path: rel, Version: r.Version} + } + // We couldn't make the version's path relative to the workspace's path, + // so just return the absolute path. It's the best we can do. + return module.Version{Path: abs, Version: r.Version} } // resolveReplacement returns the module actually used to load the source code // for m: either m itself, or the replacement for m (iff m is replaced). // It also returns the modroot of the module providing the replacement if // one was found. -func resolveReplacement(m module.Version) (module.Version, string) { - if r, replacedFrom := Replacement(m); r.Path != "" { - return r, replacedFrom +func resolveReplacement(m module.Version) module.Version { + if r := Replacement(m); r.Path != "" { + return r + } + return m +} + +func toReplaceMap(replacements []*modfile.Replace) map[module.Version]module.Version { + replaceMap := make(map[module.Version]module.Version, len(replacements)) + for _, r := range replacements { + if prev, dup := replaceMap[r.Old]; dup && prev != r.New { + base.Fatalf("go: conflicting replacements for %v:\n\t%v\n\t%v", r.Old, prev, r.New) + } + replaceMap[r.Old] = r.New } - return m, "" + return replaceMap } // indexModFile rebuilds the index of modFile. @@ -396,21 +436,7 @@ func indexModFile(data []byte, modFile *modfile.File, mod module.Version, needsF i.require[r.Mod] = requireMeta{indirect: r.Indirect} } - i.replace = make(map[module.Version]module.Version, len(modFile.Replace)) - for _, r := range modFile.Replace { - if prev, dup := i.replace[r.Old]; dup && prev != r.New { - base.Fatalf("go: conflicting replacements for %v:\n\t%v\n\t%v", r.Old, prev, r.New) - } - i.replace[r.Old] = r.New - } - - i.highestReplaced = make(map[string]string) - for _, r := range modFile.Replace { - v, ok := i.highestReplaced[r.Old.Path] - if !ok || semver.Compare(r.Old.Version, v) > 0 { - i.highestReplaced[r.Old.Path] = r.Old.Version - } - } + i.replace = toReplaceMap(modFile.Replace) i.exclude = make(map[module.Version]bool, len(modFile.Exclude)) for _, x := range modFile.Exclude { @@ -552,7 +578,7 @@ func goModSummary(m module.Version) (*modFileSummary, error) { return summary, nil } - actual, replacedFrom := resolveReplacement(m) + actual := resolveReplacement(m) if HasModRoot() && cfg.BuildMod == "readonly" && !inWorkspaceMode() && actual.Version != "" { key := module.Version{Path: actual.Path, Version: actual.Version + "/go.mod"} if !modfetch.HaveSum(key) { @@ -560,7 +586,7 @@ func goModSummary(m module.Version) (*modFileSummary, error) { return nil, module.VersionError(actual, &sumMissingError{suggestion: suggestion}) } } - summary, err := rawGoModSummary(actual, replacedFrom) + summary, err := rawGoModSummary(actual) if err != nil { return nil, err } @@ -625,22 +651,21 @@ func goModSummary(m module.Version) (*modFileSummary, error) { // // rawGoModSummary cannot be used on the Target module. -func rawGoModSummary(m module.Version, replacedFrom string) (*modFileSummary, error) { +func rawGoModSummary(m module.Version) (*modFileSummary, error) { if m.Path == "" && MainModules.Contains(m.Path) { panic("internal error: rawGoModSummary called on the Target module") } type key struct { - m module.Version - replacedFrom string + m module.Version } type cached struct { summary *modFileSummary err error } - c := rawGoModSummaryCache.Do(key{m, replacedFrom}, func() interface{} { + c := rawGoModSummaryCache.Do(key{m}, func() interface{} { summary := new(modFileSummary) - name, data, err := rawGoModData(m, replacedFrom) + name, data, err := rawGoModData(m) if err != nil { return cached{nil, err} } @@ -690,15 +715,12 @@ var rawGoModSummaryCache par.Cache // module.Version → rawGoModSummary result // // Unlike rawGoModSummary, rawGoModData does not cache its results in memory. // Use rawGoModSummary instead unless you specifically need these bytes. -func rawGoModData(m module.Version, replacedFrom string) (name string, data []byte, err error) { +func rawGoModData(m module.Version) (name string, data []byte, err error) { if m.Version == "" { // m is a replacement module with only a file path. dir := m.Path if !filepath.IsAbs(dir) { - if replacedFrom == "" { - panic(fmt.Errorf("missing module root of main module providing replacement with relative path: %v", dir)) - } - dir = filepath.Join(replacedFrom, dir) + dir = filepath.Join(replaceRelativeTo(), dir) } name = filepath.Join(dir, "go.mod") if gomodActual, ok := fsys.OverlayPath(name); ok { @@ -733,20 +755,19 @@ func rawGoModData(m module.Version, replacedFrom string) (name string, data []by // // If the queried latest version is replaced, // queryLatestVersionIgnoringRetractions returns the replacement. -func queryLatestVersionIgnoringRetractions(ctx context.Context, path string) (latest module.Version, replacedFrom string, err error) { +func queryLatestVersionIgnoringRetractions(ctx context.Context, path string) (latest module.Version, err error) { type entry struct { - latest module.Version - replacedFrom string // if latest is a replacement - err error + latest module.Version + err error } e := latestVersionIgnoringRetractionsCache.Do(path, func() interface{} { ctx, span := trace.StartSpan(ctx, "queryLatestVersionIgnoringRetractions "+path) defer span.Done() - if repl, replFrom := Replacement(module.Version{Path: path}); repl.Path != "" { + if repl := Replacement(module.Version{Path: path}); repl.Path != "" { // All versions of the module were replaced. // No need to query. - return &entry{latest: repl, replacedFrom: replFrom} + return &entry{latest: repl} } // Find the latest version of the module. @@ -758,12 +779,12 @@ func queryLatestVersionIgnoringRetractions(ctx context.Context, path string) (la return &entry{err: err} } latest := module.Version{Path: path, Version: rev.Version} - if repl, replFrom := resolveReplacement(latest); repl.Path != "" { - latest, replacedFrom = repl, replFrom + if repl := resolveReplacement(latest); repl.Path != "" { + latest = repl } - return &entry{latest: latest, replacedFrom: replacedFrom} + return &entry{latest: latest} }).(*entry) - return e.latest, e.replacedFrom, e.err + return e.latest, e.err } var latestVersionIgnoringRetractionsCache par.Cache // path → queryLatestVersionIgnoringRetractions result diff --git a/src/cmd/go/internal/modload/query.go b/src/cmd/go/internal/modload/query.go index 82979fbda1..c9ed129dbf 100644 --- a/src/cmd/go/internal/modload/query.go +++ b/src/cmd/go/internal/modload/query.go @@ -513,7 +513,7 @@ func QueryPackages(ctx context.Context, pattern, query string, current func(stri pkgMods, modOnly, err := QueryPattern(ctx, pattern, query, current, allowed) if len(pkgMods) == 0 && err == nil { - replacement, _ := Replacement(modOnly.Mod) + replacement := Replacement(modOnly.Mod) return nil, &PackageNotInModuleError{ Mod: modOnly.Mod, Replacement: replacement, @@ -669,7 +669,7 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin if err := firstError(m); err != nil { return r, err } - replacement, _ := Replacement(r.Mod) + replacement := Replacement(r.Mod) return r, &PackageNotInModuleError{ Mod: r.Mod, Replacement: replacement, @@ -969,7 +969,7 @@ func moduleHasRootPackage(ctx context.Context, m module.Version) (bool, error) { // we don't need to verify it in go.sum. This makes 'go list -m -u' faster // and simpler. func versionHasGoMod(_ context.Context, m module.Version) (bool, error) { - _, data, err := rawGoModData(m, "") + _, data, err := rawGoModData(m) if err != nil { return false, err } @@ -996,15 +996,10 @@ func lookupRepo(proxy, path string) (repo versionRepo, err error) { repo = emptyRepo{path: path, err: err} } - // TODO(#45713): Join all the highestReplaced fields into a single value. - for _, mm := range MainModules.Versions() { - index := MainModules.Index(mm) - if index == nil { - continue - } - if _, ok := index.highestReplaced[path]; ok { - return &replacementRepo{repo: repo}, nil - } + if MainModules == nil { + return repo, err + } else if _, ok := MainModules.HighestReplaced()[path]; ok { + return &replacementRepo{repo: repo}, nil } return repo, err @@ -1098,7 +1093,7 @@ func (rr *replacementRepo) Stat(rev string) (*modfetch.RevInfo, error) { } } - if r, _ := Replacement(module.Version{Path: path, Version: v}); r.Path == "" { + if r := Replacement(module.Version{Path: path, Version: v}); r.Path == "" { return info, err } return rr.replacementStat(v) @@ -1108,24 +1103,7 @@ func (rr *replacementRepo) Latest() (*modfetch.RevInfo, error) { info, err := rr.repo.Latest() path := rr.ModulePath() - highestReplaced, found := "", false - for _, mm := range MainModules.Versions() { - if index := MainModules.Index(mm); index != nil { - if v, ok := index.highestReplaced[path]; ok { - if !found { - highestReplaced, found = v, true - continue - } - if semver.Compare(v, highestReplaced) > 0 { - highestReplaced = v - } - } - } - } - - if found { - v := highestReplaced - + if v, ok := MainModules.HighestReplaced()[path]; ok { if v == "" { // The only replacement is a wildcard that doesn't specify a version, so // synthesize a pseudo-version with an appropriate major version and a diff --git a/src/cmd/go/internal/modload/vendor.go b/src/cmd/go/internal/modload/vendor.go index daa5888075..a735cad905 100644 --- a/src/cmd/go/internal/modload/vendor.go +++ b/src/cmd/go/internal/modload/vendor.go @@ -209,7 +209,7 @@ func checkVendorConsistency(index *modFileIndex, modFile *modfile.File) { } for _, mod := range vendorReplaced { - r, _ := Replacement(mod) + r := Replacement(mod) if r == (module.Version{}) { vendErrorf(mod, "is marked as replaced in vendor/modules.txt, but not replaced in go.mod") continue diff --git a/src/cmd/go/testdata/script/work_edit.txt b/src/cmd/go/testdata/script/work_edit.txt index 001ac7f65c..979c1f98e0 100644 --- a/src/cmd/go/testdata/script/work_edit.txt +++ b/src/cmd/go/testdata/script/work_edit.txt @@ -30,7 +30,7 @@ cmp stdout go.work.want_print go mod editwork -json -go 1.19 -directory b -dropdirectory c -replace 'x.1@v1.4.0 = ../z' -dropreplace x.1 -dropreplace x.1@v1.3.0 cmp stdout go.work.want_json -go mod editwork -print -fmt -workfile unformatted +go mod editwork -print -fmt -workfile $GOPATH/src/unformatted cmp stdout formatted -- m/go.mod -- diff --git a/src/cmd/go/testdata/script/work_replace.txt b/src/cmd/go/testdata/script/work_replace.txt new file mode 100644 index 0000000000..5a4cb0eebb --- /dev/null +++ b/src/cmd/go/testdata/script/work_replace.txt @@ -0,0 +1,55 @@ +# Support replace statement in go.work file + +# Replacement in go.work file, and none in go.mod file. +go list -m example.com/dep +stdout 'example.com/dep v1.0.0 => ./dep' + +# Wildcard replacement in go.work file overrides version replacement in go.mod +# file. +go list -m example.com/other +stdout 'example.com/other v1.0.0 => ./other2' + +-- go.work -- +directory m + +replace example.com/dep => ./dep +replace example.com/other => ./other2 + +-- m/go.mod -- +module example.com/m + +require example.com/dep v1.0.0 +require example.com/other v1.0.0 + +replace example.com/other v1.0.0 => ./other +-- m/m.go -- +package m + +import "example.com/dep" +import "example.com/other" + +func F() { + dep.G() + other.H() +} +-- dep/go.mod -- +module example.com/dep +-- dep/dep.go -- +package dep + +func G() { +} +-- other/go.mod -- +module example.com/other +-- other/dep.go -- +package other + +func G() { +} +-- other2/go.mod -- +module example.com/other +-- other2/dep.go -- +package other + +func G() { +} \ No newline at end of file diff --git a/src/cmd/go/testdata/script/work_replace_conflict.txt b/src/cmd/go/testdata/script/work_replace_conflict.txt new file mode 100644 index 0000000000..a2f76d13a0 --- /dev/null +++ b/src/cmd/go/testdata/script/work_replace_conflict.txt @@ -0,0 +1,53 @@ +# Conflicting replaces in workspace modules returns error that suggests +# overriding it in the go.work file. + +! go list -m example.com/dep +stderr 'go: conflicting replacements for example.com/dep@v1.0.0:\n\t./dep1\n\t./dep2\nuse "go mod editwork -replace example.com/dep@v1.0.0=\[override\]" to resolve' +go mod editwork -replace example.com/dep@v1.0.0=./dep1 +go list -m example.com/dep +stdout 'example.com/dep v1.0.0 => ./dep1' + +-- foo -- +-- go.work -- +directory m +directory n +-- m/go.mod -- +module example.com/m + +require example.com/dep v1.0.0 +replace example.com/dep v1.0.0 => ./dep1 +-- m/m.go -- +package m + +import "example.com/dep" + +func F() { + dep.G() +} +-- n/go.mod -- +module example.com/n + +require example.com/dep v1.0.0 +replace example.com/dep v1.0.0 => ./dep2 +-- n/n.go -- +package n + +import "example.com/dep" + +func F() { + dep.G() +} +-- dep1/go.mod -- +module example.com/dep +-- dep1/dep.go -- +package dep + +func G() { +} +-- dep2/go.mod -- +module example.com/dep +-- dep2/dep.go -- +package dep + +func G() { +} diff --git a/src/cmd/go/testdata/script/work_replace_conflict_override.txt b/src/cmd/go/testdata/script/work_replace_conflict_override.txt new file mode 100644 index 0000000000..ebb517dd7c --- /dev/null +++ b/src/cmd/go/testdata/script/work_replace_conflict_override.txt @@ -0,0 +1,57 @@ +# Conflicting workspace module replaces can be overridden by a replace in the +# go.work file. + +go list -m example.com/dep +stdout 'example.com/dep v1.0.0 => ./dep3' + +-- go.work -- +directory m +directory n +replace example.com/dep => ./dep3 +-- m/go.mod -- +module example.com/m + +require example.com/dep v1.0.0 +replace example.com/dep => ./dep1 +-- m/m.go -- +package m + +import "example.com/dep" + +func F() { + dep.G() +} +-- n/go.mod -- +module example.com/n + +require example.com/dep v1.0.0 +replace example.com/dep => ./dep2 +-- n/n.go -- +package n + +import "example.com/dep" + +func F() { + dep.G() +} +-- dep1/go.mod -- +module example.com/dep +-- dep1/dep.go -- +package dep + +func G() { +} +-- dep2/go.mod -- +module example.com/dep +-- dep2/dep.go -- +package dep + +func G() { +} +-- dep3/go.mod -- +module example.com/dep +-- dep3/dep.go -- +package dep + +func G() { +} -- GitLab From d94498470bb09bb0606b0eff3248cb5b35e1a145 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Fri, 17 Sep 2021 19:38:33 -0400 Subject: [PATCH 1663/2500] cmd/go: add GOWORK to go env command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GOWORK will be set to the go.work file's path, if in workspace mode or will be empty otherwise. For #45713 Fixes #48589 Change-Id: I163ffaf274e0a41469c1f3b8514d6f90e20423b0 Reviewed-on: https://go-review.googlesource.com/c/go/+/355689 Trust: Michael Matloob Trust: Daniel Martí Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/envcmd/env.go | 5 ++++- src/cmd/go/testdata/script/work.txt | 4 ++++ src/cmd/go/testdata/script/work_env.txt | 24 ++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/cmd/go/testdata/script/work_env.txt diff --git a/src/cmd/go/internal/envcmd/env.go b/src/cmd/go/internal/envcmd/env.go index 1eb773407e..181d2a2ca1 100644 --- a/src/cmd/go/internal/envcmd/env.go +++ b/src/cmd/go/internal/envcmd/env.go @@ -152,8 +152,11 @@ func ExtraEnvVars() []cfg.EnvVar { } else if modload.Enabled() { gomod = os.DevNull } + modload.InitWorkfile() + gowork := modload.WorkFilePath() return []cfg.EnvVar{ {Name: "GOMOD", Value: gomod}, + {Name: "GOWORK", Value: gowork}, } } @@ -431,7 +434,7 @@ func getOrigEnv(key string) string { func checkEnvWrite(key, val string) error { switch key { - case "GOEXE", "GOGCCFLAGS", "GOHOSTARCH", "GOHOSTOS", "GOMOD", "GOTOOLDIR", "GOVERSION": + case "GOEXE", "GOGCCFLAGS", "GOHOSTARCH", "GOHOSTOS", "GOMOD", "GOWORK", "GOTOOLDIR", "GOVERSION": return fmt.Errorf("%s cannot be modified", key) case "GOENV": return fmt.Errorf("%s can only be set using the OS environment", key) diff --git a/src/cmd/go/testdata/script/work.txt b/src/cmd/go/testdata/script/work.txt index 657cd060cc..613f037615 100644 --- a/src/cmd/go/testdata/script/work.txt +++ b/src/cmd/go/testdata/script/work.txt @@ -1,8 +1,12 @@ ! go mod initwork doesnotexist stderr 'go: creating workspace file: no go.mod file exists in directory doesnotexist' +go env GOWORK +! stdout . go mod initwork ./a ./b cmp go.work go.work.want +go env GOWORK +stdout '^'$WORK'(\\|/)gopath(\\|/)src(\\|/)go.work$' ! go run example.com/b stderr 'a(\\|/)a.go:4:8: no required module provides package rsc.io/quote; to add it:\n\tcd '$WORK(\\|/)gopath(\\|/)src(\\|/)a'\n\tgo get rsc.io/quote' diff --git a/src/cmd/go/testdata/script/work_env.txt b/src/cmd/go/testdata/script/work_env.txt new file mode 100644 index 0000000000..de67255696 --- /dev/null +++ b/src/cmd/go/testdata/script/work_env.txt @@ -0,0 +1,24 @@ +go env GOWORK +stdout '^'$GOPATH'[\\/]src[\\/]go.work$' +go env +stdout '^(set )?GOWORK="?'$GOPATH'[\\/]src[\\/]go.work"?$' + +cd .. +go env GOWORK +! stdout . +go env +stdout 'GOWORK=("")?' + +cd src +go env GOWORK +stdout 'go.work' + +! go env -w GOWORK=off +stderr '^go: GOWORK cannot be modified$' + +-- go.work -- +go 1.18 + +directory a +-- a/go.mod -- +module example.com/a -- GitLab From d7149e502dfb13fdc94439eebaf1823a6c6dd84f Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 20 Oct 2021 00:09:09 +0700 Subject: [PATCH 1664/2500] reflect: restore Value.Pointer implementation CL 350691 added Value.UnsafePointer and make Value.Pointer call it internally. It has a downside that Value.Pointer can now eligible to be inlined, thus making un-intentional side effect, like the test in fixedbugs/issue15329.go becomes flaky. This CL restore Value.Pointer original implementation, pre CL 350691, with the deprecation TODO removed. Fixes #49067 Change-Id: I735af182f8e729294333ca906ffc062f477cfc99 Reviewed-on: https://go-review.googlesource.com/c/go/+/356949 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/reflect/value.go | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/reflect/value.go b/src/reflect/value.go index 1d385f6bf9..63faa04964 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -1936,7 +1936,42 @@ func (v Value) OverflowUint(x uint64) bool { // // Deprecated: use uintptr(Value.UnsafePointer()) to get the equivalent result. func (v Value) Pointer() uintptr { - return uintptr(v.UnsafePointer()) + k := v.kind() + switch k { + case Ptr: + if v.typ.ptrdata == 0 { + // Handle pointers to go:notinheap types directly, + // so we never materialize such pointers as an + // unsafe.Pointer. (Such pointers are always indirect.) + // See issue 42076. + return *(*uintptr)(v.ptr) + } + fallthrough + case Chan, Map, UnsafePointer: + return uintptr(v.pointer()) + case Func: + if v.flag&flagMethod != 0 { + // As the doc comment says, the returned pointer is an + // underlying code pointer but not necessarily enough to + // identify a single function uniquely. All method expressions + // created via reflect have the same underlying code pointer, + // so their Pointers are equal. The function used here must + // match the one used in makeMethodValue. + f := methodValueCall + return **(**uintptr)(unsafe.Pointer(&f)) + } + p := v.pointer() + // Non-nil func value points at data block. + // First word of data block is actual code. + if p != nil { + p = *(*unsafe.Pointer)(p) + } + return uintptr(p) + + case Slice: + return (*SliceHeader)(v.ptr).Data + } + panic(&ValueError{"reflect.Value.Pointer", v.kind()}) } // Recv receives and returns a value from the channel v. -- GitLab From 07e5527249cb0b152a3807d67ea83bafd71d2496 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 20 Oct 2021 00:16:23 +0700 Subject: [PATCH 1665/2500] reflect: fix methodValueCall code pointer mismatch in Value.Pointer This is the port of CL 356809 for Value.Pointer to fix the mismatch of methodValueCall code pointer. Change-Id: I080ac41b94b44d878cd5896207a76a28c57fd48b Reviewed-on: https://go-review.googlesource.com/c/go/+/356950 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/reflect/all_test.go | 7 +++++-- src/reflect/value.go | 3 +-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index 91aac9cccb..fcd0e15f0a 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -7724,9 +7724,12 @@ func TestNotInHeapDeref(t *testing.T) { } func TestMethodCallValueCodePtr(t *testing.T) { - p := ValueOf(Point{}).Method(1).UnsafePointer() + m := ValueOf(Point{}).Method(1) want := MethodValueCallCodePtr() - if got := uintptr(p); got != want { + if got := uintptr(m.UnsafePointer()); got != want { + t.Errorf("methodValueCall code pointer mismatched, want: %v, got: %v", want, got) + } + if got := m.Pointer(); got != want { t.Errorf("methodValueCall code pointer mismatched, want: %v, got: %v", want, got) } } diff --git a/src/reflect/value.go b/src/reflect/value.go index 63faa04964..7bb8ae5b97 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -1957,8 +1957,7 @@ func (v Value) Pointer() uintptr { // created via reflect have the same underlying code pointer, // so their Pointers are equal. The function used here must // match the one used in makeMethodValue. - f := methodValueCall - return **(**uintptr)(unsafe.Pointer(&f)) + return methodValueCallCodePtr() } p := v.pointer() // Non-nil func value points at data block. -- GitLab From 1b24c9e42e527b93a39b6a6b16c20672dd2d9a03 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 19 Oct 2021 13:44:01 -0700 Subject: [PATCH 1666/2500] go/types, types2: always accept type parameters when running Manual test This makes it easier to run tests on existing generic code that is not using the `.go2` ending currently used by type checker tests. For #49074. Change-Id: I1501463c55dbe1d709918786e1a43b6d1bf1629a Reviewed-on: https://go-review.googlesource.com/c/go/+/357050 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley TryBot-Result: Go Bot --- src/cmd/compile/internal/types2/check_test.go | 2 +- src/go/types/check_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/types2/check_test.go b/src/cmd/compile/internal/types2/check_test.go index bc68e76407..e71df87f2c 100644 --- a/src/cmd/compile/internal/types2/check_test.go +++ b/src/cmd/compile/internal/types2/check_test.go @@ -99,7 +99,7 @@ func testFiles(t *testing.T, filenames []string, colDelta uint, manual bool) { } var mode syntax.Mode - if strings.HasSuffix(filenames[0], ".go2") { + if strings.HasSuffix(filenames[0], ".go2") || manual { mode |= syntax.AllowGenerics } // parse files and collect parser errors diff --git a/src/go/types/check_test.go b/src/go/types/check_test.go index e9df90c4ea..e6176738d1 100644 --- a/src/go/types/check_test.go +++ b/src/go/types/check_test.go @@ -210,7 +210,7 @@ func testFiles(t *testing.T, sizes Sizes, filenames []string, srcs [][]byte, man } mode := parser.AllErrors - if !strings.HasSuffix(filenames[0], ".go2") { + if !strings.HasSuffix(filenames[0], ".go2") && !manual { mode |= typeparams.DisallowParsing } -- GitLab From 9fa85518ff84420af644b1dd82ff311a39cd99c1 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Mon, 18 Oct 2021 12:19:07 -0700 Subject: [PATCH 1667/2500] cmd/compile: substitute "". prefix with package in more import locations The "" stand-in for the current package needs to be substituted in more places when importing, because of generics. ""..dict.conv4["".MyString] when imported in main and then exported, this becomes a..dict.conv4["".MyString] and then the linker makes that into a..dict.conv4[main.MyString] Which isn't correct. We need to replace on import not just function names, but also globals, which this CL does. Change-Id: Ia04a23b5ffd60aeeaba72c807f69261105670f8e Reviewed-on: https://go-review.googlesource.com/c/go/+/356570 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/typecheck/iimport.go | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 52236ce837..6351fc37de 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -176,7 +176,7 @@ func ReadImports(pkg *types.Pkg, data string) { } for nSyms := ird.uint64(); nSyms > 0; nSyms-- { - s := pkg.Lookup(p.stringAt(ird.uint64())) + s := pkg.Lookup(p.nameAt(ird.uint64())) off := ird.uint64() if _, ok := DeclImporter[s]; !ok { @@ -188,18 +188,9 @@ func ReadImports(pkg *types.Pkg, data string) { // Inline body index. for nPkgs := ird.uint64(); nPkgs > 0; nPkgs-- { pkg := p.pkgAt(ird.uint64()) - pkgPrefix := pkg.Prefix + "." for nSyms := ird.uint64(); nSyms > 0; nSyms-- { - s2 := p.stringAt(ird.uint64()) - // Function/method instantiation names may include "" to - // represent the path name of the imported package (in type - // names), so replace "" with pkg.Prefix. The "" in the names - // will get replaced by the linker as well, so will not - // appear in the executable. Include the dot to avoid - // matching with struct tags ending in '"'. - s2 = strings.Replace(s2, "\"\".", pkgPrefix, -1) - s := pkg.Lookup(s2) + s := pkg.Lookup(p.nameAt(ird.uint64())) off := ird.uint64() if _, ok := inlineImporter[s]; !ok { @@ -233,6 +224,22 @@ func (p *iimporter) stringAt(off uint64) string { return p.stringData[spos : spos+slen] } +// nameAt is the same as stringAt, except it replaces instances +// of "" with the path of the package being imported. +func (p *iimporter) nameAt(off uint64) string { + s := p.stringAt(off) + // Names of objects (functions, methods, globals) may include "" + // to represent the path name of the imported package. + // Replace "" with the imported package prefix. This occurs + // specifically for generics where the names of instantiations + // and dictionaries contain package-qualified type names. + // Include the dot to avoid matching with struct tags ending in '"'. + if strings.Contains(s, "\"\".") { + s = strings.Replace(s, "\"\".", p.ipkg.Prefix+".", -1) + } + return s +} + func (p *iimporter) posBaseAt(off uint64) *src.PosBase { if posBase, ok := p.posBaseCache[off]; ok { return posBase @@ -288,6 +295,7 @@ func (p *iimporter) newReader(off uint64, pkg *types.Pkg) *importReader { } func (r *importReader) string() string { return r.p.stringAt(r.uint64()) } +func (r *importReader) name() string { return r.p.nameAt(r.uint64()) } func (r *importReader) posBase() *src.PosBase { return r.p.posBaseAt(r.uint64()) } func (r *importReader) pkg() *types.Pkg { return r.p.pkgAt(r.uint64()) } @@ -539,7 +547,7 @@ func (r *importReader) localIdent() *types.Sym { return r.ident(false) } func (r *importReader) selector() *types.Sym { return r.ident(true) } func (r *importReader) qualifiedIdent() *ir.Ident { - name := r.string() + name := r.name() pkg := r.pkg() sym := pkg.Lookup(name) return ir.NewIdent(src.NoXPos, sym) -- GitLab From 2be5b846650aa4674a4eca7c11f303673b69a35a Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Mon, 18 Oct 2021 10:59:29 -0700 Subject: [PATCH 1668/2500] cmd/compile: allow importing and exporting of ODYNAMICTYPE Change-Id: I2fca7a801c85ed93c002c23bfcb0cf9593f1bdf4 Reviewed-on: https://go-review.googlesource.com/c/go/+/356571 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/typecheck/iexport.go | 13 +++++++ src/cmd/compile/internal/typecheck/iimport.go | 8 +++++ test/typeparam/issue49027.dir/a.go | 34 +++++++++++++++++++ test/typeparam/issue49027.dir/main.go | 8 +++++ 4 files changed, 63 insertions(+) diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index e3dd10a56b..46865ba3fa 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -1763,6 +1763,19 @@ func (w *exportWriter) expr(n ir.Node) { w.op(ir.OTYPE) w.typ(n.Type()) + case ir.ODYNAMICTYPE: + n := n.(*ir.DynamicType) + w.op(ir.ODYNAMICTYPE) + w.pos(n.Pos()) + w.expr(n.X) + if n.ITab != nil { + w.bool(true) + w.expr(n.ITab) + } else { + w.bool(false) + } + w.typ(n.Type()) + case ir.OTYPESW: n := n.(*ir.TypeSwitchGuard) w.op(ir.OTYPESW) diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 6351fc37de..cb1e56bf51 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1312,6 +1312,14 @@ func (r *importReader) node() ir.Node { case ir.OTYPE: return ir.TypeNode(r.typ()) + case ir.ODYNAMICTYPE: + n := ir.NewDynamicType(r.pos(), r.expr()) + if r.bool() { + n.ITab = r.expr() + } + n.SetType(r.typ()) + return n + case ir.OTYPESW: pos := r.pos() var tag *ir.Ident diff --git a/test/typeparam/issue49027.dir/a.go b/test/typeparam/issue49027.dir/a.go index d3ec27deab..da88297965 100644 --- a/test/typeparam/issue49027.dir/a.go +++ b/test/typeparam/issue49027.dir/a.go @@ -15,7 +15,41 @@ func conv[T any](v interface{}) T { func Conv2(v interface{}) (string, bool) { return conv2[string](v) } + func conv2[T any](v interface{}) (T, bool) { x, ok := v.(T) return x, ok } + +func Conv3(v interface{}) string { + return conv3[string](v) +} + +func conv3[T any](v interface{}) T { + switch v := v.(type) { + case T: + return v + default: + var z T + return z + } +} + +type Mystring string + +func (Mystring) Foo() { +} + +func Conv4(v interface{Foo()}) Mystring { + return conv4[Mystring](v) +} + +func conv4[T interface{Foo()}](v interface{Foo()}) T { + switch v := v.(type) { + case T: + return v + default: + var z T + return z + } +} diff --git a/test/typeparam/issue49027.dir/main.go b/test/typeparam/issue49027.dir/main.go index d0dc33d734..aa20a2fdfb 100644 --- a/test/typeparam/issue49027.dir/main.go +++ b/test/typeparam/issue49027.dir/main.go @@ -22,4 +22,12 @@ func main() { if y != s { panic(fmt.Sprintf("got %s wanted %s", y, s)) } + z := a.Conv3(s) + if z != s { + panic(fmt.Sprintf("got %s wanted %s", z, s)) + } + w := a.Conv4(a.Mystring(s)) + if w != a.Mystring(s) { + panic(fmt.Sprintf("got %s wanted %s", w, s)) + } } -- GitLab From 4cc6a919077f27d9255536d6539118e65c1650a2 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 14 Oct 2021 10:04:10 -0700 Subject: [PATCH 1669/2500] cmd/compile/internal/types2: implement generic conversions Fixes #47150. Change-Id: I7531ca5917d4e52ca0b9211d6f2114495b19ba09 Reviewed-on: https://go-review.googlesource.com/c/go/+/356010 Trust: Robert Griesemer Reviewed-by: Robert Findley --- .../compile/internal/types2/conversions.go | 33 +++++ .../types2/testdata/examples/conversions.go2 | 130 ++++++++++++++++++ 2 files changed, 163 insertions(+) create mode 100644 src/cmd/compile/internal/types2/testdata/examples/conversions.go2 diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go index 6c26a4c446..8cd74b8f9a 100644 --- a/src/cmd/compile/internal/types2/conversions.go +++ b/src/cmd/compile/internal/types2/conversions.go @@ -89,6 +89,39 @@ func (x *operand) convertibleTo(check *Checker, T Type) bool { return true } + // TODO(gri) consider passing under(x.typ), under(T) into convertibleToImpl (optimization) + Vp, _ := under(x.typ).(*TypeParam) + Tp, _ := under(T).(*TypeParam) + + // generic cases + // (generic operands cannot be constants, so we can ignore x.val) + switch { + case Vp != nil && Tp != nil: + x := *x // don't modify outer x + return Vp.underIs(func(V Type) bool { + x.typ = V + return Tp.underIs(func(T Type) bool { + return x.convertibleToImpl(check, T) + }) + }) + case Vp != nil: + x := *x // don't modify outer x + return Vp.underIs(func(V Type) bool { + x.typ = V + return x.convertibleToImpl(check, T) + }) + case Tp != nil: + return Tp.underIs(func(T Type) bool { + return x.convertibleToImpl(check, T) + }) + } + + // non-generic case + return x.convertibleToImpl(check, T) +} + +// convertibleToImpl should only be called by convertibleTo +func (x *operand) convertibleToImpl(check *Checker, T Type) bool { // "x's type and T have identical underlying types if tags are ignored" V := x.typ Vu := under(V) diff --git a/src/cmd/compile/internal/types2/testdata/examples/conversions.go2 b/src/cmd/compile/internal/types2/testdata/examples/conversions.go2 new file mode 100644 index 0000000000..7e9e9745bb --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/examples/conversions.go2 @@ -0,0 +1,130 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package conversions + +import "unsafe" + +// "x is assignable to T" +// - tested via assignability tests + +// "x's type and T have identical underlying types if tags are ignored" + +func _[X ~int, T ~int](x X) T { return T(x) } +func _[X struct{f int "foo"}, T struct{f int "bar"}](x X) T { return T(x) } + +type Foo struct{f int "foo"} +type Bar struct{f int "bar"} +type Far struct{f float64 } + +func _[X Foo, T Bar](x X) T { return T(x) } +func _[X Foo|Bar, T Bar](x X) T { return T(x) } +func _[X Foo, T Foo|Bar](x X) T { return T(x) } +func _[X Foo, T Far](x X) T { return T(x /* ERROR cannot convert */ ) } + +// "x's type and T are unnamed pointer types and their pointer base types +// have identical underlying types if tags are ignored" + +func _[X ~*Foo, T ~*Bar](x X) T { return T(x) } +func _[X ~*Foo|~*Bar, T ~*Bar](x X) T { return T(x) } +func _[X ~*Foo, T ~*Foo|~*Bar](x X) T { return T(x) } +func _[X ~*Foo, T ~*Far](x X) T { return T(x /* ERROR cannot convert */ ) } + +// "x's type and T are both integer or floating point types" + +func _[X Integer, T Integer](x X) T { return T(x) } +func _[X Unsigned, T Integer](x X) T { return T(x) } +func _[X Float, T Integer](x X) T { return T(x) } + +func _[X Integer, T Unsigned](x X) T { return T(x) } +func _[X Unsigned, T Unsigned](x X) T { return T(x) } +func _[X Float, T Unsigned](x X) T { return T(x) } + +func _[X Integer, T Float](x X) T { return T(x) } +func _[X Unsigned, T Float](x X) T { return T(x) } +func _[X Float, T Float](x X) T { return T(x) } + +func _[X, T Integer|Unsigned|Float](x X) T { return T(x) } +func _[X, T Integer|~string](x X) T { return T(x /* ERROR cannot convert */ ) } + +// "x's type and T are both complex types" + +func _[X, T Complex](x X) T { return T(x) } +func _[X, T Float|Complex](x X) T { return T(x /* ERROR cannot convert */ ) } + +// "x is an integer or a slice of bytes or runes and T is a string type" + +type myInt int +type myString string + +func _[T ~string](x int) T { return T(x) } +func _[T ~string](x myInt) T { return T(x) } +func _[X Integer](x X) string { return string(x) } +func _[X Integer](x X) myString { return myString(x) } +func _[X Integer](x X) *string { return (*string)(x /* ERROR cannot convert */ ) } + +func _[T ~string](x []byte) T { return T(x) } +func _[T ~string](x []rune) T { return T(x) } +func _[X ~[]byte, T ~string](x X) T { return T(x) } +func _[X ~[]rune, T ~string](x X) T { return T(x) } +func _[X Integer|~[]byte|~[]rune, T ~string](x X) T { return T(x) } +func _[X Integer|~[]byte|~[]rune, T ~*string](x X) T { return T(x /* ERROR cannot convert */ ) } + +// "x is a string and T is a slice of bytes or runes" + +func _[T ~[]byte](x string) T { return T(x) } +func _[T ~[]rune](x string) T { return T(x) } +func _[T ~[]rune](x *string) T { return T(x /* ERROR cannot convert */ ) } + +func _[X ~string, T ~[]byte](x X) T { return T(x) } +func _[X ~string, T ~[]rune](x X) T { return T(x) } +func _[X ~string, T ~[]byte|~[]rune](x X) T { return T(x) } +func _[X ~*string, T ~[]byte|~[]rune](x X) T { return T(x /* ERROR cannot convert */ ) } + +// package unsafe: +// "any pointer or value of underlying type uintptr can be converted into a unsafe.Pointer" + +type myUintptr uintptr + +func _[X ~uintptr](x X) unsafe.Pointer { return unsafe.Pointer(x) } +func _[T unsafe.Pointer](x myUintptr) T { return T(x) } +func _[T unsafe.Pointer](x int64) T { return T(x /* ERROR cannot convert */ ) } + +// "and vice versa" + +func _[T ~uintptr](x unsafe.Pointer) T { return T(x) } +func _[X unsafe.Pointer](x X) uintptr { return uintptr(x) } +func _[X unsafe.Pointer](x X) myUintptr { return myUintptr(x) } +func _[X unsafe.Pointer](x X) int64 { return int64(x /* ERROR cannot convert */ ) } + +// "x is a slice, T is a pointer-to-array type, +// and the slice and array types have identical element types." + +func _[X ~[]E, T ~*[10]E, E any](x X) T { return T(x) } +func _[X ~[]E, T ~[10]E, E any](x X) T { return T(x /* ERROR cannot convert */ ) } + +// ---------------------------------------------------------------------------- +// The following declarations can be replaced by the exported types of the +// constraints package once all builders support importing interfaces with +// type constraints. + +type Signed interface { + ~int | ~int8 | ~int16 | ~int32 | ~int64 +} + +type Unsigned interface { + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr +} + +type Integer interface { + Signed | Unsigned +} + +type Float interface { + ~float32 | ~float64 +} + +type Complex interface { + ~complex64 | ~complex128 +} -- GitLab From b091189762980836527c4aa50e3693632aea5144 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 20 Oct 2021 09:55:26 +0700 Subject: [PATCH 1670/2500] cmd/compile/internal/types2: print assignment operation for invalid operation errors When invoking check.binary for assignment operation, the expression will be nil, thus for printing the assignment operation error message, we need to reconstruct the statement from lhs, op, rhs. Fixes #48472 Change-Id: Ie38c3dd8069b47e508968d6e43cedcf7536559ef Reviewed-on: https://go-review.googlesource.com/c/go/+/357229 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/expr.go | 6 +++++- .../internal/types2/testdata/fixedbugs/issue48472.go2 | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 2d22c027eb..1001554739 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -1025,7 +1025,11 @@ func (check *Checker) binary(x *operand, e syntax.Expr, lhs, rhs syntax.Expr, op // only report an error if we have valid types // (otherwise we had an error reported elsewhere already) if x.typ != Typ[Invalid] && y.typ != Typ[Invalid] { - check.errorf(x, invalidOp+"%s (mismatched types %s and %s)", e, x.typ, y.typ) + if e != nil { + check.errorf(x, invalidOp+"%s (mismatched types %s and %s)", e, x.typ, y.typ) + } else { + check.errorf(x, invalidOp+"%s %s= %s (mismatched types %s and %s)", lhs, op, rhs, x.typ, y.typ) + } } x.mode = invalid return diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48472.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48472.go2 index 5fefcaf22b..2d908f4c8b 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48472.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48472.go2 @@ -9,3 +9,8 @@ func g() { var i int _ = s /* ERROR invalid operation: s \+ i \(mismatched types string and int\) */ + i } + +func f(i int) int { + i /* ERROR invalid operation: i \+= "1" \(mismatched types int and untyped string\) */ += "1" + return i +} -- GitLab From d9421cec00a5e171699b00966bebc85a36593bf2 Mon Sep 17 00:00:00 2001 From: Alexander Yastrebov Date: Sat, 16 Oct 2021 02:19:20 +0000 Subject: [PATCH 1671/2500] net/http/internal: return unexpected EOF on incomplete chunk read MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #48861 Change-Id: I3f55bfbdc4f2cf5b33d1ab2d76e01335bb497c6f GitHub-Last-Rev: 0ecd790b87ddd31d0cf08e8f2726f918a2edd1fb GitHub-Pull-Request: golang/go#48903 Reviewed-on: https://go-review.googlesource.com/c/go/+/355029 Trust: Damien Neil Trust: Daniel Martí Run-TryBot: Damien Neil TryBot-Result: Go Bot Reviewed-by: Damien Neil --- src/net/http/internal/chunked.go | 7 +++++++ src/net/http/internal/chunked_test.go | 28 +++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/net/http/internal/chunked.go b/src/net/http/internal/chunked.go index 923e6a6d2c..37a72e9031 100644 --- a/src/net/http/internal/chunked.go +++ b/src/net/http/internal/chunked.go @@ -81,6 +81,11 @@ func (cr *chunkedReader) Read(b []uint8) (n int, err error) { cr.err = errors.New("malformed chunked encoding") break } + } else { + if cr.err == io.EOF { + cr.err = io.ErrUnexpectedEOF + } + break } cr.checkEnd = false } @@ -109,6 +114,8 @@ func (cr *chunkedReader) Read(b []uint8) (n int, err error) { // bytes to verify they are "\r\n". if cr.n == 0 && cr.err == nil { cr.checkEnd = true + } else if cr.err == io.EOF { + cr.err = io.ErrUnexpectedEOF } } return n, cr.err diff --git a/src/net/http/internal/chunked_test.go b/src/net/http/internal/chunked_test.go index 08152ed1e2..5e29a786dd 100644 --- a/src/net/http/internal/chunked_test.go +++ b/src/net/http/internal/chunked_test.go @@ -11,6 +11,7 @@ import ( "io" "strings" "testing" + "testing/iotest" ) func TestChunk(t *testing.T) { @@ -211,3 +212,30 @@ func TestChunkReadPartial(t *testing.T) { } } + +// Issue 48861: ChunkedReader should report incomplete chunks +func TestIncompleteChunk(t *testing.T) { + const valid = "4\r\nabcd\r\n" + "5\r\nabc\r\n\r\n" + "0\r\n" + + for i := 0; i < len(valid); i++ { + incomplete := valid[:i] + r := NewChunkedReader(strings.NewReader(incomplete)) + if _, err := io.ReadAll(r); err != io.ErrUnexpectedEOF { + t.Errorf("expected io.ErrUnexpectedEOF for %q, got %v", incomplete, err) + } + } + + r := NewChunkedReader(strings.NewReader(valid)) + if _, err := io.ReadAll(r); err != nil { + t.Errorf("unexpected error for %q: %v", valid, err) + } +} + +func TestChunkEndReadError(t *testing.T) { + readErr := fmt.Errorf("chunk end read error") + + r := NewChunkedReader(io.MultiReader(strings.NewReader("4\r\nabcd"), iotest.ErrReader(readErr))) + if _, err := io.ReadAll(r); err != readErr { + t.Errorf("expected %v, got %v", readErr, err) + } +} -- GitLab From d2ec73c1bfb556c5736f900a8e4a07e281450eb2 Mon Sep 17 00:00:00 2001 From: andig Date: Wed, 20 Oct 2021 07:46:23 +0000 Subject: [PATCH 1672/2500] math/big: remove stray whitespace in addMulVVW on amd64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Minor leftover from CL 74851. Change-Id: I1b56afcde3c505ba77a0f79e8ae9b01000362298 GitHub-Last-Rev: 87e97571a58d5eadd63a28226543aaf1510a7b02 GitHub-Pull-Request: golang/go#48942 Reviewed-on: https://go-review.googlesource.com/c/go/+/355629 Reviewed-by: Robert Griesemer Trust: Daniel Martí Trust: Alexander Rakoczy --- src/math/big/arith_amd64.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/math/big/arith_amd64.s b/src/math/big/arith_amd64.s index 59be952200..5c72a27d8d 100644 --- a/src/math/big/arith_amd64.s +++ b/src/math/big/arith_amd64.s @@ -379,7 +379,7 @@ E5: CMPQ BX, R11 // i < n // func addMulVVW(z, x []Word, y Word) (c Word) TEXT ·addMulVVW(SB),NOSPLIT,$0 - CMPB ·support_adx(SB), $1 + CMPB ·support_adx(SB), $1 JEQ adx MOVQ z+0(FP), R10 MOVQ x+24(FP), R8 -- GitLab From 27a1454ee09b1923ddcf0cdc5e17b4dd7de8ea2a Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Wed, 20 Oct 2021 10:43:43 -0400 Subject: [PATCH 1673/2500] cmd/internal/goobj: minor dead code cleanup Remove a bit of dead code from the Go object file reader (io.ReaderAt no longer needed in goobj.Reader). Change-Id: I04150d37fb90b59c9dbe930878d4dd21cdcd7ca7 Reviewed-on: https://go-review.googlesource.com/c/go/+/357309 Trust: Than McIntosh Run-TryBot: Than McIntosh Reviewed-by: Cherry Mui TryBot-Result: Go Bot --- src/cmd/internal/goobj/objfile.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/cmd/internal/goobj/objfile.go b/src/cmd/internal/goobj/objfile.go index 2c44696f84..4dfea84539 100644 --- a/src/cmd/internal/goobj/objfile.go +++ b/src/cmd/internal/goobj/objfile.go @@ -19,14 +19,12 @@ package goobj import ( - "bytes" "cmd/internal/bio" "crypto/sha1" "encoding/binary" "errors" "fmt" "internal/unsafeheader" - "io" "unsafe" ) @@ -594,13 +592,12 @@ type Reader struct { b []byte // mmapped bytes, if not nil readonly bool // whether b is backed with read-only memory - rd io.ReaderAt start uint32 h Header // keep block offsets } func NewReaderFromBytes(b []byte, readonly bool) *Reader { - r := &Reader{b: b, readonly: readonly, rd: bytes.NewReader(b), start: 0} + r := &Reader{b: b, readonly: readonly, start: 0} err := r.h.Read(r) if err != nil { return nil -- GitLab From 4e565f7372494c9c46e33a35e84f0fe4fc7d2774 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Mon, 18 Oct 2021 14:31:48 +0700 Subject: [PATCH 1674/2500] cmd/compile: fix crawling of embeddable types during inline In CL 327872, there's a fix for crawling of embeddable types directly reached by the user, so all of its methods need to be re-exported. But we missed the cased when an un-exported type may be reachable by embedding in exported type. Example: type t struct {} func (t) M() {} func F() interface{} { return struct{ t }{} } We generate the wrapper for "struct{ t }".M, and when inlining call to "struct{ t }".M makes "t.M" reachable. It works well, and only be revealed in CL 327871, when we changed methodWrapper to always call inline.InlineCalls, thus causes the crash in #49016, which involve dot type in inlined function. Fixes #49016 Change-Id: If174fa5575132da5cf60e4bd052f7011c4e76c5d Reviewed-on: https://go-review.googlesource.com/c/go/+/356254 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/typecheck/crawler.go | 33 ++++++++++++----- test/fixedbugs/issue49016.dir/a.go | 36 +++++++++++++++++++ test/fixedbugs/issue49016.dir/b.go | 13 +++++++ test/fixedbugs/issue49016.dir/c.go | 9 +++++ test/fixedbugs/issue49016.dir/d.go | 9 +++++ test/fixedbugs/issue49016.dir/e.go | 11 ++++++ test/fixedbugs/issue49016.dir/f.go | 9 +++++ test/fixedbugs/issue49016.dir/g.go | 9 +++++ test/fixedbugs/issue49016.go | 7 ++++ 9 files changed, 128 insertions(+), 8 deletions(-) create mode 100644 test/fixedbugs/issue49016.dir/a.go create mode 100644 test/fixedbugs/issue49016.dir/b.go create mode 100644 test/fixedbugs/issue49016.dir/c.go create mode 100644 test/fixedbugs/issue49016.dir/d.go create mode 100644 test/fixedbugs/issue49016.dir/e.go create mode 100644 test/fixedbugs/issue49016.dir/f.go create mode 100644 test/fixedbugs/issue49016.dir/g.go create mode 100644 test/fixedbugs/issue49016.go diff --git a/src/cmd/compile/internal/typecheck/crawler.go b/src/cmd/compile/internal/typecheck/crawler.go index 667e76e130..b214ef2279 100644 --- a/src/cmd/compile/internal/typecheck/crawler.go +++ b/src/cmd/compile/internal/typecheck/crawler.go @@ -195,18 +195,35 @@ func (p *crawler) markInlBody(n *ir.Name) { var doFlood func(n ir.Node) doFlood = func(n ir.Node) { t := n.Type() - if t != nil && (t.HasTParam() || t.IsFullyInstantiated()) { - // Ensure that we call markType() on any base generic type - // that is written to the export file (even if not explicitly - // marked for export), so we will call markInlBody on its - // methods, and the methods will be available for - // instantiation if needed. - p.markType(t) + if t != nil { + if t.HasTParam() || t.IsFullyInstantiated() { + // Ensure that we call markType() on any base generic type + // that is written to the export file (even if not explicitly + // marked for export), so we will call markInlBody on its + // methods, and the methods will be available for + // instantiation if needed. + p.markType(t) + } + if base.Debug.Unified == 0 { + // If a method of un-exported type is promoted and accessible by + // embedding in an exported type, it makes that type reachable. + // + // Example: + // + // type t struct {} + // func (t) M() {} + // + // func F() interface{} { return struct{ t }{} } + // + // We generate the wrapper for "struct{ t }".M, and inline call + // to "struct{ t }".M, which makes "t.M" reachable. + p.markEmbed(t) + } } + switch n.Op() { case ir.OMETHEXPR, ir.ODOTMETH: p.markInlBody(ir.MethodExprName(n)) - case ir.ONAME: n := n.(*ir.Name) switch n.Class { diff --git a/test/fixedbugs/issue49016.dir/a.go b/test/fixedbugs/issue49016.dir/a.go new file mode 100644 index 0000000000..36639b73d4 --- /dev/null +++ b/test/fixedbugs/issue49016.dir/a.go @@ -0,0 +1,36 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type Node interface { + Position() +} + +type noder struct{} + +func (noder) Position() {} + +type Scope map[int][]Node + +func (s Scope) M1() Scope { + if x, ok := s[0]; ok { + return x[0].(struct { + noder + Scope + }).Scope + } + return nil +} + +func (s Scope) M2() Scope { + if x, ok := s[0]; ok { + st, _ := x[0].(struct { + noder + Scope + }) + return st.Scope + } + return nil +} diff --git a/test/fixedbugs/issue49016.dir/b.go b/test/fixedbugs/issue49016.dir/b.go new file mode 100644 index 0000000000..1dd63f87b6 --- /dev/null +++ b/test/fixedbugs/issue49016.dir/b.go @@ -0,0 +1,13 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package b + +type t int + +func (t) m() {} + +func F1() interface{} { return struct{ t }{} } +func F2() interface{} { return *new(struct{ t }) } +func F3() interface{} { var x [1]struct{ t }; return x[0] } diff --git a/test/fixedbugs/issue49016.dir/c.go b/test/fixedbugs/issue49016.dir/c.go new file mode 100644 index 0000000000..2cc6681b95 --- /dev/null +++ b/test/fixedbugs/issue49016.dir/c.go @@ -0,0 +1,9 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package c + +import "./a" + +var _ = (&a.Scope{}).M1() diff --git a/test/fixedbugs/issue49016.dir/d.go b/test/fixedbugs/issue49016.dir/d.go new file mode 100644 index 0000000000..e933dc08e4 --- /dev/null +++ b/test/fixedbugs/issue49016.dir/d.go @@ -0,0 +1,9 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package d + +import "./a" + +var _ = (&a.Scope{}).M2() diff --git a/test/fixedbugs/issue49016.dir/e.go b/test/fixedbugs/issue49016.dir/e.go new file mode 100644 index 0000000000..5f43179c37 --- /dev/null +++ b/test/fixedbugs/issue49016.dir/e.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package e + +import ( + "./b" +) + +var _ = b.F1() diff --git a/test/fixedbugs/issue49016.dir/f.go b/test/fixedbugs/issue49016.dir/f.go new file mode 100644 index 0000000000..2cd978eace --- /dev/null +++ b/test/fixedbugs/issue49016.dir/f.go @@ -0,0 +1,9 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package f + +import "./b" + +var _ = b.F2() diff --git a/test/fixedbugs/issue49016.dir/g.go b/test/fixedbugs/issue49016.dir/g.go new file mode 100644 index 0000000000..b90353fcff --- /dev/null +++ b/test/fixedbugs/issue49016.dir/g.go @@ -0,0 +1,9 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package g + +import "./b" + +var _ = b.F3() diff --git a/test/fixedbugs/issue49016.go b/test/fixedbugs/issue49016.go new file mode 100644 index 0000000000..b83fbd7af1 --- /dev/null +++ b/test/fixedbugs/issue49016.go @@ -0,0 +1,7 @@ +// compiledir + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From 4320949f36f5f523a08ce8da6bdcd35ef51b8941 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 20 Oct 2021 14:54:13 -0400 Subject: [PATCH 1675/2500] go/internal/gcimporter: avoid setting unnecessary lines in fakeFileSet This is a clean port of CL 357291 from x/tools. For #46586 Change-Id: Ib22087ae7fe8477d368acd230b263b83cdad4d36 Reviewed-on: https://go-review.googlesource.com/c/go/+/357429 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Matthew Dempsky TryBot-Result: Go Bot --- src/go/internal/gcimporter/iimport.go | 3 +- src/go/internal/gcimporter/support.go | 47 +++++++++++++++++---------- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go index 9aae2a31f3..0771fa3c26 100644 --- a/src/go/internal/gcimporter/iimport.go +++ b/src/go/internal/gcimporter/iimport.go @@ -135,9 +135,10 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, dataRea fake: fakeFileSet{ fset: fset, - files: make(map[string]*token.File), + files: make(map[string]*fileInfo), }, } + defer p.fake.setLines() // set lines for files in fset for i, pt := range predeclared { p.typCache[uint64(i)] = pt diff --git a/src/go/internal/gcimporter/support.go b/src/go/internal/gcimporter/support.go index 09810dd85b..5aef63ec1e 100644 --- a/src/go/internal/gcimporter/support.go +++ b/src/go/internal/gcimporter/support.go @@ -25,37 +25,50 @@ const deltaNewFile = -64 // Synthesize a token.Pos type fakeFileSet struct { fset *token.FileSet - files map[string]*token.File + files map[string]*fileInfo } +type fileInfo struct { + file *token.File + lastline int +} + +const maxlines = 64 * 1024 + func (s *fakeFileSet) pos(file string, line, column int) token.Pos { // TODO(mdempsky): Make use of column. - // Since we don't know the set of needed file positions, we - // reserve maxlines positions per file. - const maxlines = 64 * 1024 + // Since we don't know the set of needed file positions, we reserve + // maxlines positions per file. We delay calling token.File.SetLines until + // all positions have been calculated (by way of fakeFileSet.setLines), so + // that we can avoid setting unnecessary lines. See also golang/go#46586. f := s.files[file] if f == nil { - f = s.fset.AddFile(file, -1, maxlines) + f = &fileInfo{file: s.fset.AddFile(file, -1, maxlines)} s.files[file] = f - // Allocate the fake linebreak indices on first use. - // TODO(adonovan): opt: save ~512KB using a more complex scheme? - fakeLinesOnce.Do(func() { - fakeLines = make([]int, maxlines) - for i := range fakeLines { - fakeLines[i] = i - } - }) - f.SetLines(fakeLines) } if line > maxlines { line = 1 } + if line > f.lastline { + f.lastline = line + } - // Treat the file as if it contained only newlines - // and column=1: use the line number as the offset. - return f.Pos(line - 1) + // Return a fake position assuming that f.file consists only of newlines. + return token.Pos(f.file.Base() + line - 1) +} + +func (s *fakeFileSet) setLines() { + fakeLinesOnce.Do(func() { + fakeLines = make([]int, maxlines) + for i := range fakeLines { + fakeLines[i] = i + } + }) + for _, f := range s.files { + f.file.SetLines(fakeLines[:f.lastline]) + } } var ( -- GitLab From 3ff39c5eda6aa869cbc3a19237750fa7cf495832 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 20 Oct 2021 12:18:40 -0700 Subject: [PATCH 1676/2500] cmd/compile/internal/types2: use correct types when checking generic conversions Iterate through the actual, possibly defined types of constraints when type-checking generic conversions, not the underlying types. For #47150. Change-Id: Ia7af313bf46d6f6b0ad5292ff793b030b8e2d3d8 Reviewed-on: https://go-review.googlesource.com/c/go/+/357333 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/conversions.go | 16 ++++++++-------- .../types2/testdata/examples/conversions.go2 | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go index 8cd74b8f9a..112d728188 100644 --- a/src/cmd/compile/internal/types2/conversions.go +++ b/src/cmd/compile/internal/types2/conversions.go @@ -98,21 +98,21 @@ func (x *operand) convertibleTo(check *Checker, T Type) bool { switch { case Vp != nil && Tp != nil: x := *x // don't modify outer x - return Vp.underIs(func(V Type) bool { - x.typ = V - return Tp.underIs(func(T Type) bool { - return x.convertibleToImpl(check, T) + return Vp.is(func(V *term) bool { + x.typ = V.typ + return Tp.is(func(T *term) bool { + return x.convertibleToImpl(check, T.typ) }) }) case Vp != nil: x := *x // don't modify outer x - return Vp.underIs(func(V Type) bool { - x.typ = V + return Vp.is(func(V *term) bool { + x.typ = V.typ return x.convertibleToImpl(check, T) }) case Tp != nil: - return Tp.underIs(func(T Type) bool { - return x.convertibleToImpl(check, T) + return Tp.is(func(T *term) bool { + return x.convertibleToImpl(check, T.typ) }) } diff --git a/src/cmd/compile/internal/types2/testdata/examples/conversions.go2 b/src/cmd/compile/internal/types2/testdata/examples/conversions.go2 index 7e9e9745bb..5c1b30a2b5 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/conversions.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/conversions.go2 @@ -31,6 +31,20 @@ func _[X ~*Foo|~*Bar, T ~*Bar](x X) T { return T(x) } func _[X ~*Foo, T ~*Foo|~*Bar](x X) T { return T(x) } func _[X ~*Foo, T ~*Far](x X) T { return T(x /* ERROR cannot convert */ ) } +// Verify that the defined types in constraints are considered for the rule above. + +type ( + B int + C int + X0 *B + T0 *C +) + +func _(x X0) T0 { return T0(x /* ERROR cannot convert */ ) } // non-generic reference +func _[X X0, T T0](x X) T { return T(x /* ERROR cannot convert */ ) } +func _[T T0](x X0) T { return T(x /* ERROR cannot convert */ ) } +func _[X X0](x X) T0 { return T0(x /* ERROR cannot convert */ ) } + // "x's type and T are both integer or floating point types" func _[X Integer, T Integer](x X) T { return T(x) } -- GitLab From 3ec8d4b5ed5db74f84f8d493e4160e97481e436d Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Fri, 24 Sep 2021 16:01:03 +0000 Subject: [PATCH 1677/2500] runtime/internal/atomic: add atomic types for all functions Change-Id: I74f365316484feb819c31c77fbffd78fadfe32a9 Reviewed-on: https://go-review.googlesource.com/c/go/+/356169 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Austin Clements Reviewed-by: Michael Pratt --- src/runtime/internal/atomic/doc.go | 18 + src/runtime/internal/atomic/types.go | 395 +++++++++++++++++++++ src/runtime/internal/atomic/types_64bit.go | 30 ++ 3 files changed, 443 insertions(+) create mode 100644 src/runtime/internal/atomic/doc.go create mode 100644 src/runtime/internal/atomic/types.go create mode 100644 src/runtime/internal/atomic/types_64bit.go diff --git a/src/runtime/internal/atomic/doc.go b/src/runtime/internal/atomic/doc.go new file mode 100644 index 0000000000..08e6b6ce0b --- /dev/null +++ b/src/runtime/internal/atomic/doc.go @@ -0,0 +1,18 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package atomic provides atomic operations, independent of sync/atomic, +to the runtime. + +On most platforms, the compiler is aware of the functions defined +in this package, and they're replaced with platform-specific intrinsics. +On other platforms, generic implementations are made available. + +Unless otherwise noted, operations defined in this package are sequentially +consistent across threads with respect to the values they manipulate. More +specifically, operations that happen in a specific order on one thread, +will always be observed to happen in exactly that order by another thread. +*/ +package atomic diff --git a/src/runtime/internal/atomic/types.go b/src/runtime/internal/atomic/types.go new file mode 100644 index 0000000000..1a240d7c91 --- /dev/null +++ b/src/runtime/internal/atomic/types.go @@ -0,0 +1,395 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package atomic + +import "unsafe" + +// Int32 is an atomically accessed int32 value. +// +// An Int32 must not be copied. +type Int32 struct { + noCopy noCopy + value int32 +} + +// Load accesses and returns the value atomically. +func (i *Int32) Load() int32 { + return Loadint32(&i.value) +} + +// Store updates the value atomically. +func (i *Int32) Store(value int32) { + Storeint32(&i.value, value) +} + +// CompareAndSwap atomically compares i's value with old, +// and if they're equal, swaps i's value with new. +// +// Returns true if the operation succeeded. +func (i *Int32) CompareAndSwap(old, new int32) bool { + return Casint32(&i.value, old, new) +} + +// Swap replaces i's value with new, returning +// i's value before the replacement. +func (i *Int32) Swap(new int32) int32 { + return Xchgint32(&i.value, new) +} + +// Add adds delta to i atomically, returning +// the new updated value. +// +// This operation wraps around in the usual +// two's-complement way. +func (i *Int32) Add(delta int32) int32 { + return Xaddint32(&i.value, delta) +} + +// Int64 is an atomically accessed int64 value. +// +// An Int64 must not be copied. +type Int64 struct { + noCopy noCopy + value int64 +} + +// Load accesses and returns the value atomically. +func (i *Int64) Load() int64 { + return Loadint64(&i.value) +} + +// Store updates the value atomically. +func (i *Int64) Store(value int64) { + Storeint64(&i.value, value) +} + +// CompareAndSwap atomically compares i's value with old, +// and if they're equal, swaps i's value with new. +// +// Returns true if the operation succeeded. +func (i *Int64) CompareAndSwap(old, new int64) bool { + return Casint64(&i.value, old, new) +} + +// Swap replaces i's value with new, returning +// i's value before the replacement. +func (i *Int64) Swap(new int64) int64 { + return Xchgint64(&i.value, new) +} + +// Add adds delta to i atomically, returning +// the new updated value. +// +// This operation wraps around in the usual +// two's-complement way. +func (i *Int64) Add(delta int64) int64 { + return Xaddint64(&i.value, delta) +} + +// Uint8 is an atomically accessed uint8 value. +// +// A Uint8 must not be copied. +type Uint8 struct { + noCopy noCopy + value uint8 +} + +// Load accesses and returns the value atomically. +func (u *Uint8) Load() uint8 { + return Load8(&u.value) +} + +// Store updates the value atomically. +func (u *Uint8) Store(value uint8) { + Store8(&u.value, value) +} + +// And takes value and performs a bit-wise +// "and" operation with the value of u, storing +// the result into u. +// +// The full process is performed atomically. +func (u *Uint8) And(value uint8) { + And8(&u.value, value) +} + +// Or takes value and performs a bit-wise +// "or" operation with the value of u, storing +// the result into u. +// +// The full process is performed atomically. +func (u *Uint8) Or(value uint8) { + Or8(&u.value, value) +} + +// Uint32 is an atomically accessed uint32 value. +// +// A Uint32 must not be copied. +type Uint32 struct { + noCopy noCopy + value uint32 +} + +// Load accesses and returns the value atomically. +func (u *Uint32) Load() uint32 { + return Load(&u.value) +} + +// LoadAcquire is a partially unsynchronized version +// of Load that relaxes ordering constraints. Other threads +// may observe operations that precede this operation to +// occur after it, but no operation that occurs after it +// on this thread can be observed to occur before it. +// +// WARNING: Use sparingly and with great care. +func (u *Uint32) LoadAcquire() uint32 { + return LoadAcq(&u.value) +} + +// Store updates the value atomically. +func (u *Uint32) Store(value uint32) { + Store(&u.value, value) +} + +// StoreRelease is a partially unsynchronized version +// of Store that relaxes ordering constraints. Other threads +// may observe operations that occur after this operation to +// precede it, but no operation that precedes it +// on this thread can be observed to occur after it. +// +// WARNING: Use sparingly and with great care. +func (u *Uint32) StoreRelease(value uint32) { + StoreRel(&u.value, value) +} + +// CompareAndSwap atomically compares u's value with old, +// and if they're equal, swaps u's value with new. +// +// Returns true if the operation succeeded. +func (u *Uint32) CompareAndSwap(old, new uint32) bool { + return Cas(&u.value, old, new) +} + +// CompareAndSwapRelease is a partially unsynchronized version +// of Cas that relaxes ordering constraints. Other threads +// may observe operations that occur after this operation to +// precede it, but no operation that precedes it +// on this thread can be observed to occur after it. +// +// Returns true if the operation succeeded. +// +// WARNING: Use sparingly and with great care. +func (u *Uint32) CompareAndSwapRelease(old, new uint32) bool { + return CasRel(&u.value, old, new) +} + +// Swap replaces u's value with new, returning +// u's value before the replacement. +func (u *Uint32) Swap(value uint32) uint32 { + return Xchg(&u.value, value) +} + +// And takes value and performs a bit-wise +// "and" operation with the value of u, storing +// the result into u. +// +// The full process is performed atomically. +func (u *Uint32) And(value uint32) { + And(&u.value, value) +} + +// Or takes value and performs a bit-wise +// "or" operation with the value of u, storing +// the result into u. +// +// The full process is performed atomically. +func (u *Uint32) Or(value uint32) { + Or(&u.value, value) +} + +// Add adds delta to u atomically, returning +// the new updated value. +// +// This operation wraps around in the usual +// two's-complement way. +func (u *Uint32) Add(delta int32) uint32 { + return Xadd(&u.value, delta) +} + +// Uint64 is an atomically accessed uint64 value. +// +// A Uint64 must not be copied. +type Uint64 struct { + noCopy noCopy + value uint64 +} + +// Load accesses and returns the value atomically. +func (u *Uint64) Load() uint64 { + return Load64(&u.value) +} + +// Store updates the value atomically. +func (u *Uint64) Store(value uint64) { + Store64(&u.value, value) +} + +// CompareAndSwap atomically compares u's value with old, +// and if they're equal, swaps u's value with new. +// +// Returns true if the operation succeeded. +func (u *Uint64) CompareAndSwap(old, new uint64) bool { + return Cas64(&u.value, old, new) +} + +// Swap replaces u's value with new, returning +// u's value before the replacement. +func (u *Uint64) Swap(value uint64) uint64 { + return Xchg64(&u.value, value) +} + +// Add adds delta to u atomically, returning +// the new updated value. +// +// This operation wraps around in the usual +// two's-complement way. +func (u *Uint64) Add(delta int64) uint64 { + return Xadd64(&u.value, delta) +} + +// Uintptr is an atomically accessed uintptr value. +// +// A Uintptr must not be copied. +type Uintptr struct { + noCopy noCopy + value uintptr +} + +// Load accesses and returns the value atomically. +func (u *Uintptr) Load() uintptr { + return Loaduintptr(&u.value) +} + +// LoadAcquire is a partially unsynchronized version +// of Load that relaxes ordering constraints. Other threads +// may observe operations that precede this operation to +// occur after it, but no operation that occurs after it +// on this thread can be observed to occur before it. +// +// WARNING: Use sparingly and with great care. +func (u *Uintptr) LoadAcquire() uintptr { + return LoadAcquintptr(&u.value) +} + +// Store updates the value atomically. +func (u *Uintptr) Store(value uintptr) { + Storeuintptr(&u.value, value) +} + +// StoreRelease is a partially unsynchronized version +// of Store that relaxes ordering constraints. Other threads +// may observe operations that occur after this operation to +// precede it, but no operation that precedes it +// on this thread can be observed to occur after it. +// +// WARNING: Use sparingly and with great care. +func (u *Uintptr) StoreRelease(value uintptr) { + StoreReluintptr(&u.value, value) +} + +// CompareAndSwap atomically compares u's value with old, +// and if they're equal, swaps u's value with new. +// +// Returns true if the operation succeeded. +func (u *Uintptr) CompareAndSwap(old, new uintptr) bool { + return Casuintptr(&u.value, old, new) +} + +// Swap replaces u's value with new, returning +// u's value before the replacement. +func (u *Uintptr) Swap(value uintptr) uintptr { + return Xchguintptr(&u.value, value) +} + +// Add adds delta to u atomically, returning +// the new updated value. +// +// This operation wraps around in the usual +// two's-complement way. +func (u *Uintptr) Add(delta uintptr) uintptr { + return Xadduintptr(&u.value, delta) +} + +// Float64 is an atomically accessed float64 value. +// +// A Float64 must not be copied. +type Float64 struct { + u Uint64 +} + +// Load accesses and returns the value atomically. +func (f *Float64) Load() float64 { + r := f.u.Load() + return *(*float64)(unsafe.Pointer(&r)) +} + +// Store updates the value atomically. +func (f *Float64) Store(value float64) { + f.u.Store(*(*uint64)(unsafe.Pointer(&value))) +} + +// UnsafePointer is an atomically accessed unsafe.Pointer value. +// +// Note that because of the atomicity guarantees, stores to values +// of this type never trigger a write barrier, and the relevant +// methods are suffixed with "NoWB" to indicate that explicitly. +// As a result, this type should be used carefully, and sparingly, +// mostly with values that do not live in the Go heap anyway. +// +// An UnsafePointer must not be copied. +type UnsafePointer struct { + noCopy noCopy + value unsafe.Pointer +} + +// Load accesses and returns the value atomically. +func (u *UnsafePointer) Load() unsafe.Pointer { + return Loadp(unsafe.Pointer(&u.value)) +} + +// StoreNoWB updates the value atomically. +// +// WARNING: As the name implies this operation does *not* +// perform a write barrier on value, and so this operation may +// hide pointers from the GC. Use with care and sparingly. +// It is safe to use with values not found in the Go heap. +func (u *UnsafePointer) StoreNoWB(value unsafe.Pointer) { + StorepNoWB(unsafe.Pointer(&u.value), value) +} + +// CompareAndSwapNoWB atomically (with respect to other methods) +// compares u's value with old, and if they're equal, +// swaps u's value with new. +// +// Returns true if the operation succeeded. +// +// WARNING: As the name implies this operation does *not* +// perform a write barrier on value, and so this operation may +// hide pointers from the GC. Use with care and sparingly. +// It is safe to use with values not found in the Go heap. +func (u *UnsafePointer) CompareAndSwapNoWB(old, new unsafe.Pointer) bool { + return Casp1(&u.value, old, new) +} + +// noCopy may be embedded into structs which must not be copied +// after the first use. +// +// See https://golang.org/issues/8005#issuecomment-190753527 +// for details. +type noCopy struct{} + +// Lock is a no-op used by -copylocks checker from `go vet`. +func (*noCopy) Lock() {} +func (*noCopy) Unlock() {} diff --git a/src/runtime/internal/atomic/types_64bit.go b/src/runtime/internal/atomic/types_64bit.go new file mode 100644 index 0000000000..9e5ed68419 --- /dev/null +++ b/src/runtime/internal/atomic/types_64bit.go @@ -0,0 +1,30 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build amd64 || arm64 || mips64 || mips64le || ppc64 || ppc64le || riscv64 || s390x || wasm +// +build amd64 arm64 mips64 mips64le ppc64 ppc64le riscv64 s390x wasm + +package atomic + +// LoadAcquire is a partially unsynchronized version +// of Load that relaxes ordering constraints. Other threads +// may observe operations that precede this operation to +// occur after it, but no operation that occurs after it +// on this thread can be observed to occur before it. +// +// WARNING: Use sparingly and with great care. +func (u *Uint64) LoadAcquire() uint64 { + return LoadAcq64(&u.value) +} + +// StoreRelease is a partially unsynchronized version +// of Store that relaxes ordering constraints. Other threads +// may observe operations that occur after this operation to +// precede it, but no operation that precedes it +// on this thread can be observed to occur after it. +// +// WARNING: Use sparingly and with great care. +func (u *Uint64) StoreRelease(value uint64) { + StoreRel64(&u.value, value) +} -- GitLab From 75b73d68b332a90e05cf45fa2c850667b3a0f777 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Fri, 24 Sep 2021 16:06:07 +0000 Subject: [PATCH 1678/2500] runtime: use atomic.Float64 for assist ratio Change-Id: Ie7f09a7c9545ef9dd1860b1e332c4edbcbf8165e Reviewed-on: https://go-review.googlesource.com/c/go/+/356170 Reviewed-by: Austin Clements Trust: Michael Knyszek --- src/runtime/mgcmark.go | 10 +++++----- src/runtime/mgcpacer.go | 20 +++++--------------- src/runtime/proc.go | 2 +- 3 files changed, 11 insertions(+), 21 deletions(-) diff --git a/src/runtime/mgcmark.go b/src/runtime/mgcmark.go index 246907e538..efda65fe1e 100644 --- a/src/runtime/mgcmark.go +++ b/src/runtime/mgcmark.go @@ -400,8 +400,8 @@ retry: // balance positive. When the required amount of work is low, // we over-assist to build up credit for future allocations // and amortize the cost of assisting. - assistWorkPerByte := float64frombits(atomic.Load64(&gcController.assistWorkPerByte)) - assistBytesPerWork := float64frombits(atomic.Load64(&gcController.assistBytesPerWork)) + assistWorkPerByte := gcController.assistWorkPerByte.Load() + assistBytesPerWork := gcController.assistBytesPerWork.Load() debtBytes := -gp.gcAssistBytes scanWork := int64(assistWorkPerByte * float64(debtBytes)) if scanWork < gcOverAssistWork { @@ -545,7 +545,7 @@ func gcAssistAlloc1(gp *g, scanWork int64) { // this scan work counts for. The "1+" is a poor man's // round-up, to ensure this adds credit even if // assistBytesPerWork is very low. - assistBytesPerWork := float64frombits(atomic.Load64(&gcController.assistBytesPerWork)) + assistBytesPerWork := gcController.assistBytesPerWork.Load() gp.gcAssistBytes += 1 + int64(assistBytesPerWork*float64(workDone)) // If this is the last worker and we ran out of work, @@ -638,7 +638,7 @@ func gcFlushBgCredit(scanWork int64) { return } - assistBytesPerWork := float64frombits(atomic.Load64(&gcController.assistBytesPerWork)) + assistBytesPerWork := gcController.assistBytesPerWork.Load() scanBytes := int64(float64(scanWork) * assistBytesPerWork) lock(&work.assistQueue.lock) @@ -672,7 +672,7 @@ func gcFlushBgCredit(scanWork int64) { if scanBytes > 0 { // Convert from scan bytes back to work. - assistWorkPerByte := float64frombits(atomic.Load64(&gcController.assistWorkPerByte)) + assistWorkPerByte := gcController.assistWorkPerByte.Load() scanWork = int64(float64(scanBytes) * assistWorkPerByte) atomic.Xaddint64(&gcController.bgScanCredit, scanWork) } diff --git a/src/runtime/mgcpacer.go b/src/runtime/mgcpacer.go index 9338359de7..342ea419fe 100644 --- a/src/runtime/mgcpacer.go +++ b/src/runtime/mgcpacer.go @@ -222,24 +222,14 @@ type gcControllerState struct { // bytes that should be performed by mutator assists. This is // computed at the beginning of each cycle and updated every // time heapScan is updated. - // - // Stored as a uint64, but it's actually a float64. Use - // float64frombits to get the value. - // - // Read and written atomically. - assistWorkPerByte uint64 + assistWorkPerByte atomic.Float64 // assistBytesPerWork is 1/assistWorkPerByte. // - // Stored as a uint64, but it's actually a float64. Use - // float64frombits to get the value. - // - // Read and written atomically. - // // Note that because this is read and written independently // from assistWorkPerByte users may notice a skew between // the two values, and such a state should be safe. - assistBytesPerWork uint64 + assistBytesPerWork atomic.Float64 // fractionalUtilizationGoal is the fraction of wall clock // time that should be spent in the fractional mark worker on @@ -333,7 +323,7 @@ func (c *gcControllerState) startCycle() { c.revise() if debug.gcpacertrace > 0 { - assistRatio := float64frombits(atomic.Load64(&c.assistWorkPerByte)) + assistRatio := c.assistWorkPerByte.Load() print("pacer: assist ratio=", assistRatio, " (scan ", gcController.heapScan>>20, " MB in ", work.initialHeapLive>>20, "->", @@ -439,8 +429,8 @@ func (c *gcControllerState) revise() { // cycle. assistWorkPerByte := float64(scanWorkRemaining) / float64(heapRemaining) assistBytesPerWork := float64(heapRemaining) / float64(scanWorkRemaining) - atomic.Store64(&c.assistWorkPerByte, float64bits(assistWorkPerByte)) - atomic.Store64(&c.assistBytesPerWork, float64bits(assistBytesPerWork)) + c.assistWorkPerByte.Store(assistWorkPerByte) + c.assistBytesPerWork.Store(assistBytesPerWork) } // endCycle computes the trigger ratio for the next cycle. diff --git a/src/runtime/proc.go b/src/runtime/proc.go index c14a1f143c..b80f09f993 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -3646,7 +3646,7 @@ func goexit0(gp *g) { // Flush assist credit to the global pool. This gives // better information to pacing if the application is // rapidly creating an exiting goroutines. - assistWorkPerByte := float64frombits(atomic.Load64(&gcController.assistWorkPerByte)) + assistWorkPerByte := gcController.assistWorkPerByte.Load() scanCredit := int64(assistWorkPerByte * float64(gp.gcAssistBytes)) atomic.Xaddint64(&gcController.bgScanCredit, scanCredit) gp.gcAssistBytes = 0 -- GitLab From d419a80bc76cf18d321f9bf37c2deb2b8c0a1415 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Fri, 15 Oct 2021 19:22:10 +0000 Subject: [PATCH 1679/2500] runtime: retype mheap.pagesInUse as atomic.Uint64 [git-generate] cd src/runtime mv export_test.go export.go GOROOT=$(dirname $(dirname $PWD)) rf ' add mheap.pagesInUse \ // Proportional sweep \ // \ // These parameters represent a linear function from gcController.heapLive \ // to page sweep count. The proportional sweep system works to \ // stay in the black by keeping the current page sweep count \ // above this line at the current gcController.heapLive. \ // \ // The line has slope sweepPagesPerByte and passes through a \ // basis point at (sweepHeapLiveBasis, pagesSweptBasis). At \ // any given time, the system is at (gcController.heapLive, \ // pagesSwept) in this space. \ // \ // It is important that the line pass through a point we \ // control rather than simply starting at a 0,0 origin \ // because that lets us adjust sweep pacing at any time while \ // accounting for current progress. If we could only adjust \ // the slope, it would create a discontinuity in debt if any \ // progress has already been made. \ pagesInUse_ atomic.Uint64 // pages of spans in stats mSpanInUse ex { import "runtime/internal/atomic" var t mheap var v, w uint64 var d int64 t.pagesInUse -> t.pagesInUse_.Load() t.pagesInUse = v -> t.pagesInUse_.Store(v) atomic.Load64(&t.pagesInUse) -> t.pagesInUse_.Load() atomic.LoadAcq64(&t.pagesInUse) -> t.pagesInUse_.LoadAcquire() atomic.Store64(&t.pagesInUse, v) -> t.pagesInUse_.Store(v) atomic.StoreRel64(&t.pagesInUse, v) -> t.pagesInUse_.StoreRelease(v) atomic.Cas64(&t.pagesInUse, v, w) -> t.pagesInUse_.CompareAndSwap(v, w) atomic.Xchg64(&t.pagesInUse, v) -> t.pagesInUse_.Swap(v) atomic.Xadd64(&t.pagesInUse, d) -> t.pagesInUse_.Add(d) } rm mheap.pagesInUse mv mheap.pagesInUse_ mheap.pagesInUse ' mv export.go export_test.go Change-Id: I495d188683dba0778518563c46755b5ad43be298 Reviewed-on: https://go-review.googlesource.com/c/go/+/356549 Trust: Michael Knyszek Reviewed-by: Austin Clements --- src/runtime/export_test.go | 2 +- src/runtime/mgcpacer.go | 2 +- src/runtime/mheap.go | 18 +++++++++--------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index 01fd1dbd97..01f917bded 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -263,7 +263,7 @@ var ReadUnaligned64 = readUnaligned64 func CountPagesInUse() (pagesInUse, counted uintptr) { stopTheWorld("CountPagesInUse") - pagesInUse = uintptr(mheap_.pagesInUse) + pagesInUse = uintptr(mheap_.pagesInUse.Load()) for _, s := range mheap_.allspans { if s.state.get() == mSpanInUse { diff --git a/src/runtime/mgcpacer.go b/src/runtime/mgcpacer.go index 342ea419fe..3cd4ea2fde 100644 --- a/src/runtime/mgcpacer.go +++ b/src/runtime/mgcpacer.go @@ -752,7 +752,7 @@ func (c *gcControllerState) commit(triggerRatio float64) { heapDistance = _PageSize } pagesSwept := atomic.Load64(&mheap_.pagesSwept) - pagesInUse := atomic.Load64(&mheap_.pagesInUse) + pagesInUse := mheap_.pagesInUse.Load() sweepDistancePages := int64(pagesInUse) - int64(pagesSwept) if sweepDistancePages <= 0 { mheap_.sweepPagesPerByte = 0 diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go index b78f752ded..a787f67460 100644 --- a/src/runtime/mheap.go +++ b/src/runtime/mheap.go @@ -96,17 +96,17 @@ type mheap struct { // any given time, the system is at (gcController.heapLive, // pagesSwept) in this space. // - // It's important that the line pass through a point we - // control rather than simply starting at a (0,0) origin + // It is important that the line pass through a point we + // control rather than simply starting at a 0,0 origin // because that lets us adjust sweep pacing at any time while // accounting for current progress. If we could only adjust // the slope, it would create a discontinuity in debt if any // progress has already been made. - pagesInUse uint64 // pages of spans in stats mSpanInUse; updated atomically - pagesSwept uint64 // pages swept this cycle; updated atomically - pagesSweptBasis uint64 // pagesSwept to use as the origin of the sweep ratio; updated atomically - sweepHeapLiveBasis uint64 // value of gcController.heapLive to use as the origin of sweep ratio; written with lock, read without - sweepPagesPerByte float64 // proportional sweep ratio; written with lock, read without + pagesInUse atomic.Uint64 // pages of spans in stats mSpanInUse + pagesSwept uint64 // pages swept this cycle; updated atomically + pagesSweptBasis uint64 // pagesSwept to use as the origin of the sweep ratio; updated atomically + sweepHeapLiveBasis uint64 // value of gcController.heapLive to use as the origin of sweep ratio; written with lock, read without + sweepPagesPerByte float64 // proportional sweep ratio; written with lock, read without // TODO(austin): pagesInUse should be a uintptr, but the 386 // compiler can't 8-byte align fields. @@ -1311,7 +1311,7 @@ HaveSpan: atomic.Or8(&arena.pageInUse[pageIdx], pageMask) // Update related page sweeper stats. - atomic.Xadd64(&h.pagesInUse, int64(npages)) + h.pagesInUse.Add(int64(npages)) } // Make sure the newly allocated span will be observed @@ -1468,7 +1468,7 @@ func (h *mheap) freeSpanLocked(s *mspan, typ spanAllocType) { print("mheap.freeSpanLocked - span ", s, " ptr ", hex(s.base()), " allocCount ", s.allocCount, " sweepgen ", s.sweepgen, "/", h.sweepgen, "\n") throw("mheap.freeSpanLocked - invalid free") } - atomic.Xadd64(&h.pagesInUse, -int64(s.npages)) + h.pagesInUse.Add(-int64(s.npages)) // Clear in-use bit in arena page bitmap. arena, pageIdx, pageMask := pageIndexOf(s.base()) -- GitLab From e90492882a7fd580b7dac88675a1c907a7441b40 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 18 Oct 2021 23:07:59 +0000 Subject: [PATCH 1680/2500] runtime: retype mheap.pagesSwept as atomic.Uint64 [git-generate] cd src/runtime mv export_test.go export.go GOROOT=$(dirname $(dirname $PWD)) rf ' add mheap.pagesSwept pagesSwept_ atomic.Uint64 // pages swept this cycle ex { import "runtime/internal/atomic" var t mheap var v, w uint64 var d int64 t.pagesSwept -> t.pagesSwept_.Load() t.pagesSwept = v -> t.pagesSwept_.Store(v) atomic.Load64(&t.pagesSwept) -> t.pagesSwept_.Load() atomic.LoadAcq64(&t.pagesSwept) -> t.pagesSwept_.LoadAcquire() atomic.Store64(&t.pagesSwept, v) -> t.pagesSwept_.Store(v) atomic.StoreRel64(&t.pagesSwept, v) -> t.pagesSwept_.StoreRelease(v) atomic.Cas64(&t.pagesSwept, v, w) -> t.pagesSwept_.CompareAndSwap(v, w) atomic.Xchg64(&t.pagesSwept, v) -> t.pagesSwept_.Swap(v) atomic.Xadd64(&t.pagesSwept, d) -> t.pagesSwept_.Add(d) } rm mheap.pagesSwept mv mheap.pagesSwept_ mheap.pagesSwept ' mv export.go export_test.go Change-Id: Ife99893d90a339655f604bc3a64ee3decec645ea Reviewed-on: https://go-review.googlesource.com/c/go/+/356709 Trust: Michael Knyszek Reviewed-by: Austin Clements --- src/runtime/mgc.go | 2 +- src/runtime/mgcpacer.go | 2 +- src/runtime/mgcsweep.go | 6 +++--- src/runtime/mheap.go | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go index 34b5b482a3..654fa4118a 100644 --- a/src/runtime/mgc.go +++ b/src/runtime/mgc.go @@ -1457,7 +1457,7 @@ func gcSweep(mode gcMode) { lock(&mheap_.lock) mheap_.sweepgen += 2 mheap_.sweepDrained = 0 - mheap_.pagesSwept = 0 + mheap_.pagesSwept.Store(0) mheap_.sweepArenas = mheap_.allArenas mheap_.reclaimIndex = 0 mheap_.reclaimCredit = 0 diff --git a/src/runtime/mgcpacer.go b/src/runtime/mgcpacer.go index 3cd4ea2fde..f858ab08d0 100644 --- a/src/runtime/mgcpacer.go +++ b/src/runtime/mgcpacer.go @@ -751,7 +751,7 @@ func (c *gcControllerState) commit(triggerRatio float64) { // Avoid setting the sweep ratio extremely high heapDistance = _PageSize } - pagesSwept := atomic.Load64(&mheap_.pagesSwept) + pagesSwept := mheap_.pagesSwept.Load() pagesInUse := mheap_.pagesInUse.Load() sweepDistancePages := int64(pagesInUse) - int64(pagesSwept) if sweepDistancePages <= 0 { diff --git a/src/runtime/mgcsweep.go b/src/runtime/mgcsweep.go index 1812644623..78d1f33925 100644 --- a/src/runtime/mgcsweep.go +++ b/src/runtime/mgcsweep.go @@ -245,7 +245,7 @@ func (l *sweepLocker) dispose() { func (l *sweepLocker) sweepIsDone() { if debug.gcpacertrace > 0 { - print("pacer: sweep done at heap size ", gcController.heapLive>>20, "MB; allocated ", (gcController.heapLive-mheap_.sweepHeapLiveBasis)>>20, "MB during sweep; swept ", mheap_.pagesSwept, " pages at ", mheap_.sweepPagesPerByte, " pages/byte\n") + print("pacer: sweep done at heap size ", gcController.heapLive>>20, "MB; allocated ", (gcController.heapLive-mheap_.sweepHeapLiveBasis)>>20, "MB during sweep; swept ", mheap_.pagesSwept.Load(), " pages at ", mheap_.sweepPagesPerByte, " pages/byte\n") } } @@ -408,7 +408,7 @@ func (sl *sweepLocked) sweep(preserve bool) bool { traceGCSweepSpan(s.npages * _PageSize) } - atomic.Xadd64(&mheap_.pagesSwept, int64(s.npages)) + mheap_.pagesSwept.Add(int64(s.npages)) spc := s.spanclass size := s.elemsize @@ -724,7 +724,7 @@ retry: // Fix debt if necessary. newHeapLive := uintptr(atomic.Load64(&gcController.heapLive)-mheap_.sweepHeapLiveBasis) + spanBytes pagesTarget := int64(mheap_.sweepPagesPerByte*float64(newHeapLive)) - int64(callerSweepPages) - for pagesTarget > int64(atomic.Load64(&mheap_.pagesSwept)-sweptBasis) { + for pagesTarget > int64(mheap_.pagesSwept.Load()-sweptBasis) { if sweepone() == ^uintptr(0) { mheap_.sweepPagesPerByte = 0 break diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go index a787f67460..27f60771eb 100644 --- a/src/runtime/mheap.go +++ b/src/runtime/mheap.go @@ -103,7 +103,7 @@ type mheap struct { // the slope, it would create a discontinuity in debt if any // progress has already been made. pagesInUse atomic.Uint64 // pages of spans in stats mSpanInUse - pagesSwept uint64 // pages swept this cycle; updated atomically + pagesSwept atomic.Uint64 // pages swept this cycle pagesSweptBasis uint64 // pagesSwept to use as the origin of the sweep ratio; updated atomically sweepHeapLiveBasis uint64 // value of gcController.heapLive to use as the origin of sweep ratio; written with lock, read without sweepPagesPerByte float64 // proportional sweep ratio; written with lock, read without -- GitLab From 1dff8f0a056517f0a8adfda663402ffb2e089281 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 18 Oct 2021 23:10:43 +0000 Subject: [PATCH 1681/2500] runtime: retype mheap.pagesSweptBasis as atomic.Uint64 [git-generate] cd src/runtime mv export_test.go export.go GOROOT=$(dirname $(dirname $PWD)) rf ' add mheap.pagesSweptBasis pagesSweptBasis_ atomic.Uint64 // pagesSwept to use as the origin of the sweep ratio ex { import "runtime/internal/atomic" var t mheap var v, w uint64 var d int64 t.pagesSweptBasis -> t.pagesSweptBasis_.Load() t.pagesSweptBasis = v -> t.pagesSweptBasis_.Store(v) atomic.Load64(&t.pagesSweptBasis) -> t.pagesSweptBasis_.Load() atomic.LoadAcq64(&t.pagesSweptBasis) -> t.pagesSweptBasis_.LoadAcquire() atomic.Store64(&t.pagesSweptBasis, v) -> t.pagesSweptBasis_.Store(v) atomic.StoreRel64(&t.pagesSweptBasis, v) -> t.pagesSweptBasis_.StoreRelease(v) atomic.Cas64(&t.pagesSweptBasis, v, w) -> t.pagesSweptBasis_.CompareAndSwap(v, w) atomic.Xchg64(&t.pagesSweptBasis, v) -> t.pagesSweptBasis_.Swap(v) atomic.Xadd64(&t.pagesSweptBasis, d) -> t.pagesSweptBasis_.Add(d) } rm mheap.pagesSweptBasis mv mheap.pagesSweptBasis_ mheap.pagesSweptBasis ' mv export.go export_test.go Change-Id: Id9438184b9bd06d96894c02376385bad45dee154 Reviewed-on: https://go-review.googlesource.com/c/go/+/356710 Reviewed-by: Austin Clements Trust: Michael Knyszek --- src/runtime/mgcpacer.go | 2 +- src/runtime/mgcsweep.go | 4 ++-- src/runtime/mheap.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/runtime/mgcpacer.go b/src/runtime/mgcpacer.go index f858ab08d0..55f3bc926d 100644 --- a/src/runtime/mgcpacer.go +++ b/src/runtime/mgcpacer.go @@ -762,7 +762,7 @@ func (c *gcControllerState) commit(triggerRatio float64) { // Write pagesSweptBasis last, since this // signals concurrent sweeps to recompute // their debt. - atomic.Store64(&mheap_.pagesSweptBasis, pagesSwept) + mheap_.pagesSweptBasis.Store(pagesSwept) } } diff --git a/src/runtime/mgcsweep.go b/src/runtime/mgcsweep.go index 78d1f33925..aedd6c316e 100644 --- a/src/runtime/mgcsweep.go +++ b/src/runtime/mgcsweep.go @@ -719,7 +719,7 @@ func deductSweepCredit(spanBytes uintptr, callerSweepPages uintptr) { } retry: - sweptBasis := atomic.Load64(&mheap_.pagesSweptBasis) + sweptBasis := mheap_.pagesSweptBasis.Load() // Fix debt if necessary. newHeapLive := uintptr(atomic.Load64(&gcController.heapLive)-mheap_.sweepHeapLiveBasis) + spanBytes @@ -729,7 +729,7 @@ retry: mheap_.sweepPagesPerByte = 0 break } - if atomic.Load64(&mheap_.pagesSweptBasis) != sweptBasis { + if mheap_.pagesSweptBasis.Load() != sweptBasis { // Sweep pacing changed. Recompute debt. goto retry } diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go index 27f60771eb..90e55315a6 100644 --- a/src/runtime/mheap.go +++ b/src/runtime/mheap.go @@ -104,7 +104,7 @@ type mheap struct { // progress has already been made. pagesInUse atomic.Uint64 // pages of spans in stats mSpanInUse pagesSwept atomic.Uint64 // pages swept this cycle - pagesSweptBasis uint64 // pagesSwept to use as the origin of the sweep ratio; updated atomically + pagesSweptBasis atomic.Uint64 // pagesSwept to use as the origin of the sweep ratio sweepHeapLiveBasis uint64 // value of gcController.heapLive to use as the origin of sweep ratio; written with lock, read without sweepPagesPerByte float64 // proportional sweep ratio; written with lock, read without // TODO(austin): pagesInUse should be a uintptr, but the 386 -- GitLab From a91e976fd2cc6f1c156877eae40262d7e47c745c Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 18 Oct 2021 23:12:16 +0000 Subject: [PATCH 1682/2500] runtime: retype mheap.reclaimIndex as atomic.Uint64 [git-generate] cd src/runtime mv export_test.go export.go GOROOT=$(dirname $(dirname $PWD)) rf ' add mheap.reclaimIndex \ // reclaimIndex is the page index in allArenas of next page to \ // reclaim. Specifically, it refers to page (i % \ // pagesPerArena) of arena allArenas[i / pagesPerArena]. \ // \ // If this is >= 1<<63, the page reclaimer is done scanning \ // the page marks. \ reclaimIndex_ atomic.Uint64 ex { import "runtime/internal/atomic" var t mheap var v, w uint64 var d int64 t.reclaimIndex -> t.reclaimIndex_.Load() t.reclaimIndex = v -> t.reclaimIndex_.Store(v) atomic.Load64(&t.reclaimIndex) -> t.reclaimIndex_.Load() atomic.LoadAcq64(&t.reclaimIndex) -> t.reclaimIndex_.LoadAcquire() atomic.Store64(&t.reclaimIndex, v) -> t.reclaimIndex_.Store(v) atomic.StoreRel64(&t.reclaimIndex, v) -> t.reclaimIndex_.StoreRelease(v) atomic.Cas64(&t.reclaimIndex, v, w) -> t.reclaimIndex_.CompareAndSwap(v, w) atomic.Xchg64(&t.reclaimIndex, v) -> t.reclaimIndex_.Swap(v) atomic.Xadd64(&t.reclaimIndex, d) -> t.reclaimIndex_.Add(d) } rm mheap.reclaimIndex mv mheap.reclaimIndex_ mheap.reclaimIndex ' mv export.go export_test.go Change-Id: I1d619e3ac032285b5f7eb6c563a5188c8e36d089 Reviewed-on: https://go-review.googlesource.com/c/go/+/356711 Reviewed-by: Austin Clements Trust: Michael Knyszek --- src/runtime/mgc.go | 2 +- src/runtime/mheap.go | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go index 654fa4118a..56ef1c4e38 100644 --- a/src/runtime/mgc.go +++ b/src/runtime/mgc.go @@ -1459,7 +1459,7 @@ func gcSweep(mode gcMode) { mheap_.sweepDrained = 0 mheap_.pagesSwept.Store(0) mheap_.sweepArenas = mheap_.allArenas - mheap_.reclaimIndex = 0 + mheap_.reclaimIndex.Store(0) mheap_.reclaimCredit = 0 unlock(&mheap_.lock) diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go index 90e55315a6..fc86023f4d 100644 --- a/src/runtime/mheap.go +++ b/src/runtime/mheap.go @@ -123,9 +123,7 @@ type mheap struct { // // If this is >= 1<<63, the page reclaimer is done scanning // the page marks. - // - // This is accessed atomically. - reclaimIndex uint64 + reclaimIndex atomic.Uint64 // reclaimCredit is spare credit for extra pages swept. Since // the page reclaimer works in large chunks, it may reclaim // more than requested. Any spare pages released go to this @@ -739,7 +737,7 @@ func (h *mheap) reclaim(npage uintptr) { // batching heap frees. // Bail early if there's no more reclaim work. - if atomic.Load64(&h.reclaimIndex) >= 1<<63 { + if h.reclaimIndex.Load() >= 1<<63 { return } @@ -769,10 +767,10 @@ func (h *mheap) reclaim(npage uintptr) { } // Claim a chunk of work. - idx := uintptr(atomic.Xadd64(&h.reclaimIndex, pagesPerReclaimerChunk) - pagesPerReclaimerChunk) + idx := uintptr(h.reclaimIndex.Add(pagesPerReclaimerChunk) - pagesPerReclaimerChunk) if idx/pagesPerArena >= uintptr(len(arenas)) { // Page reclaiming is done. - atomic.Store64(&h.reclaimIndex, 1<<63) + h.reclaimIndex.Store(1 << 63) break } -- GitLab From 016d5eea118445f5b3ca46f85b65c6afd180c946 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 18 Oct 2021 23:14:20 +0000 Subject: [PATCH 1683/2500] runtime: retype mheap.reclaimCredit as atomic.Uintptr [git-generate] cd src/runtime mv export_test.go export.go GOROOT=$(dirname $(dirname $PWD)) rf ' add mheap.reclaimCredit \ // reclaimCredit is spare credit for extra pages swept. Since \ // the page reclaimer works in large chunks, it may reclaim \ // more than requested. Any spare pages released go to this \ // credit pool. \ reclaimCredit_ atomic.Uintptr ex { import "runtime/internal/atomic" var t mheap var v, w uintptr var d uintptr t.reclaimCredit -> t.reclaimCredit_.Load() t.reclaimCredit = v -> t.reclaimCredit_.Store(v) atomic.Loaduintptr(&t.reclaimCredit) -> t.reclaimCredit_.Load() atomic.LoadAcquintptr(&t.reclaimCredit) -> t.reclaimCredit_.LoadAcquire() atomic.Storeuintptr(&t.reclaimCredit, v) -> t.reclaimCredit_.Store(v) atomic.StoreReluintptr(&t.reclaimCredit, v) -> t.reclaimCredit_.StoreRelease(v) atomic.Casuintptr(&t.reclaimCredit, v, w) -> t.reclaimCredit_.CompareAndSwap(v, w) atomic.Xchguintptr(&t.reclaimCredit, v) -> t.reclaimCredit_.Swap(v) atomic.Xadduintptr(&t.reclaimCredit, d) -> t.reclaimCredit_.Add(d) } rm mheap.reclaimCredit mv mheap.reclaimCredit_ mheap.reclaimCredit ' mv export.go export_test.go Change-Id: I2c567781a28f5d8c2275ff18f2cf605b82f22d09 Reviewed-on: https://go-review.googlesource.com/c/go/+/356712 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Austin Clements --- src/runtime/mgc.go | 2 +- src/runtime/mgcsweep.go | 2 +- src/runtime/mheap.go | 11 +++++------ 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go index 56ef1c4e38..6f8463c253 100644 --- a/src/runtime/mgc.go +++ b/src/runtime/mgc.go @@ -1460,7 +1460,7 @@ func gcSweep(mode gcMode) { mheap_.pagesSwept.Store(0) mheap_.sweepArenas = mheap_.allArenas mheap_.reclaimIndex.Store(0) - mheap_.reclaimCredit = 0 + mheap_.reclaimCredit.Store(0) unlock(&mheap_.lock) sweep.centralIndex.clear() diff --git a/src/runtime/mgcsweep.go b/src/runtime/mgcsweep.go index aedd6c316e..9c7f9d340d 100644 --- a/src/runtime/mgcsweep.go +++ b/src/runtime/mgcsweep.go @@ -291,7 +291,7 @@ func sweepone() uintptr { // Whole span was freed. Count it toward the // page reclaimer credit since these pages can // now be used for span allocation. - atomic.Xadduintptr(&mheap_.reclaimCredit, npages) + mheap_.reclaimCredit.Add(npages) } else { // Span is still in-use, so this returned no // pages to the heap and the span needs to diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go index fc86023f4d..0e7694aab7 100644 --- a/src/runtime/mheap.go +++ b/src/runtime/mheap.go @@ -124,13 +124,12 @@ type mheap struct { // If this is >= 1<<63, the page reclaimer is done scanning // the page marks. reclaimIndex atomic.Uint64 + // reclaimCredit is spare credit for extra pages swept. Since // the page reclaimer works in large chunks, it may reclaim // more than requested. Any spare pages released go to this // credit pool. - // - // This is accessed atomically. - reclaimCredit uintptr + reclaimCredit atomic.Uintptr // arenas is the heap arena map. It points to the metadata for // the heap for every arena frame of the entire usable virtual @@ -754,13 +753,13 @@ func (h *mheap) reclaim(npage uintptr) { locked := false for npage > 0 { // Pull from accumulated credit first. - if credit := atomic.Loaduintptr(&h.reclaimCredit); credit > 0 { + if credit := h.reclaimCredit.Load(); credit > 0 { take := credit if take > npage { // Take only what we need. take = npage } - if atomic.Casuintptr(&h.reclaimCredit, credit, credit-take) { + if h.reclaimCredit.CompareAndSwap(credit, credit-take) { npage -= take } continue @@ -786,7 +785,7 @@ func (h *mheap) reclaim(npage uintptr) { npage -= nfound } else { // Put spare pages toward global credit. - atomic.Xadduintptr(&h.reclaimCredit, nfound-npage) + h.reclaimCredit.Add(nfound - npage) npage = 0 } } -- GitLab From 73652af80d9f33de946fc3a91c6900a81247df18 Mon Sep 17 00:00:00 2001 From: hkhere <33268704+hkhere@users.noreply.github.com> Date: Wed, 20 Oct 2021 17:26:41 +0000 Subject: [PATCH 1684/2500] cmd/compile: use `else if` for mutually exclusive `if` statements Change-Id: I43e5bb778fbba1398c8006b1644524a9885157db GitHub-Last-Rev: fa76473ab8b207b8cfc350ca8a26de37dfe57f82 GitHub-Pull-Request: golang/go#47155 Reviewed-on: https://go-review.googlesource.com/c/go/+/334169 Trust: Keith Randall Trust: Robert Griesemer Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/typecheck/dcl.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/typecheck/dcl.go b/src/cmd/compile/internal/typecheck/dcl.go index 76fc6de621..68ab05a538 100644 --- a/src/cmd/compile/internal/typecheck/dcl.go +++ b/src/cmd/compile/internal/typecheck/dcl.go @@ -360,8 +360,7 @@ func funcargs(nt *ir.FuncType) { if n.Sym == nil { // Name so that escape analysis can track it. ~r stands for 'result'. n.Sym = LookupNum("~r", i) - } - if n.Sym.IsBlank() { + } else if n.Sym.IsBlank() { // Give it a name so we can assign to it during return. ~b stands for 'blank'. // The name must be different from ~r above because if you have // func f() (_ int) -- GitLab From fca46d0b36c10250713ec0f4c9bf13d626f358d1 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 20 Oct 2021 12:31:53 +0700 Subject: [PATCH 1685/2500] go/types: print assignment operation for invalid operation errors This is port of CL 357229 for types2 to go/types. Change-Id: I35ed6b784969210a00ea5b36238df7d6b7fa18bc Reviewed-on: https://go-review.googlesource.com/c/go/+/357230 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/go/types/expr.go | 6 +++++- src/go/types/testdata/fixedbugs/issue48472.go2 | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/go/types/expr.go b/src/go/types/expr.go index fac5a5e31d..3a09dfd85f 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -1000,7 +1000,11 @@ func (check *Checker) binary(x *operand, e ast.Expr, lhs, rhs ast.Expr, op token if e != nil { posn = e } - check.invalidOp(posn, _MismatchedTypes, "%s (mismatched types %s and %s)", e, x.typ, y.typ) + if e != nil { + check.invalidOp(posn, _MismatchedTypes, "%s (mismatched types %s and %s)", e, x.typ, y.typ) + } else { + check.invalidOp(posn, _MismatchedTypes, "%s %s= %s (mismatched types %s and %s)", lhs, op, rhs, x.typ, y.typ) + } } x.mode = invalid return diff --git a/src/go/types/testdata/fixedbugs/issue48472.go2 b/src/go/types/testdata/fixedbugs/issue48472.go2 index 5fefcaf22b..2d908f4c8b 100644 --- a/src/go/types/testdata/fixedbugs/issue48472.go2 +++ b/src/go/types/testdata/fixedbugs/issue48472.go2 @@ -9,3 +9,8 @@ func g() { var i int _ = s /* ERROR invalid operation: s \+ i \(mismatched types string and int\) */ + i } + +func f(i int) int { + i /* ERROR invalid operation: i \+= "1" \(mismatched types int and untyped string\) */ += "1" + return i +} -- GitLab From 8b9c0d1a79251969e46731e46e72e4e8f8998817 Mon Sep 17 00:00:00 2001 From: Archana R Date: Wed, 20 Oct 2021 04:11:57 -0500 Subject: [PATCH 1686/2500] test/codegen: updated comparison test to verify on ppc64,ppc64le Updated test/codegen/comparison.go to verify memequal is inlined as implemented in CL 328291. Change-Id: If7824aed37ee1f8640e54fda0f9b7610582ba316 Reviewed-on: https://go-review.googlesource.com/c/go/+/357289 Run-TryBot: Lynn Boger TryBot-Result: Go Bot Trust: Lynn Boger Reviewed-by: Cherry Mui --- test/codegen/comparisons.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/codegen/comparisons.go b/test/codegen/comparisons.go index 35a181f83b..fd32ea335c 100644 --- a/test/codegen/comparisons.go +++ b/test/codegen/comparisons.go @@ -546,6 +546,8 @@ func equalConstString1() bool { b := string("Z") // amd64:-".*memequal" // arm64:-".*memequal" + // ppc64:-".*memequal" + // ppc64le:-".*memequal" return a == b } @@ -553,6 +555,8 @@ func equalVarString1(a string) bool { b := string("Z") // amd64:-".*memequal" // arm64:-".*memequal" + // ppc64:-".*memequal" + // ppc64le:-".*memequal" return a[:1] == b } @@ -561,6 +565,8 @@ func equalConstString2() bool { b := string("ZZ") // amd64:-".*memequal" // arm64:-".*memequal" + // ppc64:-".*memequal" + // ppc64le:-".*memequal" return a == b } @@ -568,6 +574,8 @@ func equalVarString2(a string) bool { b := string("ZZ") // amd64:-".*memequal" // arm64:-".*memequal" + // ppc64:-".*memequal" + // ppc64le:-".*memequal" return a[:2] == b } @@ -576,6 +584,8 @@ func equalConstString4() bool { b := string("ZZZZ") // amd64:-".*memequal" // arm64:-".*memequal" + // ppc64:-".*memequal" + // ppc64le:-".*memequal" return a == b } @@ -583,6 +593,8 @@ func equalVarString4(a string) bool { b := string("ZZZZ") // amd64:-".*memequal" // arm64:-".*memequal" + // ppc64:-".*memequal" + // ppc64le:-".*memequal" return a[:4] == b } @@ -591,6 +603,8 @@ func equalConstString8() bool { b := string("ZZZZZZZZ") // amd64:-".*memequal" // arm64:-".*memequal" + // ppc64:-".*memequal" + // ppc64le:-".*memequal" return a == b } @@ -598,5 +612,7 @@ func equalVarString8(a string) bool { b := string("ZZZZZZZZ") // amd64:-".*memequal" // arm64:-".*memequal" + // ppc64:-".*memequal" + // ppc64le:-".*memequal" return a[:8] == b } -- GitLab From 8b0bea993d452ef7861642a9c04bae213246ded1 Mon Sep 17 00:00:00 2001 From: Lynn Boger Date: Thu, 14 Oct 2021 12:55:43 -0500 Subject: [PATCH 1687/2500] cmd/compile/internal/ssa/gen: eliminate unnecessary neg and xori on PPC64 This adds a few rules to PPC64 to eliminate some instructions: - when an isel is used to generate a boolean value based on a condition and followed by an xori to flip the result, it can instead flip the operands in the isel and avoid the xori. = when a neg follows a sub the operands to the sub can be swapped and the neg avoided. There are several opportunities in reflect.DeepEqual to omit xori which improves some of its benchmarks by as much as 5% Change-Id: I81bbc02c0f16995c65934b6f045867b731ab302b Reviewed-on: https://go-review.googlesource.com/c/go/+/357509 Trust: Lynn Boger Reviewed-by: Cherry Mui --- src/cmd/compile/internal/ssa/gen/PPC64.rules | 6 +- src/cmd/compile/internal/ssa/gen/PPC64Ops.go | 2 +- src/cmd/compile/internal/ssa/rewritePPC64.go | 68 ++++++++++++++++++++ 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/ssa/gen/PPC64.rules b/src/cmd/compile/internal/ssa/gen/PPC64.rules index 8e42bae215..ccca72a416 100644 --- a/src/cmd/compile/internal/ssa/gen/PPC64.rules +++ b/src/cmd/compile/internal/ssa/gen/PPC64.rules @@ -848,6 +848,7 @@ (ADDconst [c] (SUBFCconst [d] x)) && is32Bit(c+d) => (SUBFCconst [c+d] x) (NEG (ADDconst [c] x)) && is32Bit(-c) => (SUBFCconst [-c] x) (NEG (SUBFCconst [c] x)) && is32Bit(-c) => (ADDconst [-c] x) +(NEG (SUB x y)) => (SUB y x) // Use register moves instead of stores and loads to move int<=>float values // Common with math Float64bits, Float64frombits @@ -1087,7 +1088,7 @@ ((CMP|CMPW|CMPU|CMPWU) x y) && canonLessThan(x,y) => (InvertFlags ((CMP|CMPW|CMPU|CMPWU) y x)) // ISEL auxInt values 0=LT 1=GT 2=EQ arg2 ? arg0 : arg1 -// ISEL auxInt values 4=GE 5=LE 6=NE arg2 ? arg1 : arg0 +// ISEL auxInt values 4=GE 5=LE 6=NE !arg2 ? arg1 : arg0 // ISELB special case where arg0, arg1 values are 0, 1 (Equal cmp) => (ISELB [2] (MOVDconst [1]) cmp) @@ -1138,6 +1139,9 @@ (ISEL [n] x y (InvertFlags bool)) && n%4 == 0 => (ISEL [n+1] x y bool) (ISEL [n] x y (InvertFlags bool)) && n%4 == 1 => (ISEL [n-1] x y bool) (ISEL [n] x y (InvertFlags bool)) && n%4 == 2 => (ISEL [n] x y bool) +(XORconst [1] (ISELB [6] (MOVDconst [1]) cmp)) => (ISELB [2] (MOVDconst [1]) cmp) +(XORconst [1] (ISELB [5] (MOVDconst [1]) cmp)) => (ISELB [1] (MOVDconst [1]) cmp) +(XORconst [1] (ISELB [4] (MOVDconst [1]) cmp)) => (ISELB [0] (MOVDconst [1]) cmp) // A particular pattern seen in cgo code: (AND (MOVDconst [c]) x:(MOVBZload _ _)) => (ANDconst [c&0xFF] x) diff --git a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go index ff9ce64e18..42775fa3c2 100644 --- a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go @@ -396,7 +396,7 @@ func init() { {name: "CMPWUconst", argLength: 1, reg: gp1cr, asm: "CMPWU", aux: "Int32", typ: "Flags"}, // ISEL auxInt values 0=LT 1=GT 2=EQ arg2 ? arg0 : arg1 - // ISEL auxInt values 4=GE 5=LE 6=NE arg2 ? arg1 : arg0 + // ISEL auxInt values 4=GE 5=LE 6=NE !arg2 ? arg1 : arg0 // ISELB special case where arg0, arg1 values are 0, 1 for boolean result {name: "ISEL", argLength: 3, reg: crgp21, asm: "ISEL", aux: "Int32", typ: "Int32"}, // see above {name: "ISELB", argLength: 2, reg: crgp11, asm: "ISEL", aux: "Int32", typ: "Int32"}, // see above diff --git a/src/cmd/compile/internal/ssa/rewritePPC64.go b/src/cmd/compile/internal/ssa/rewritePPC64.go index 1e6624e906..ea1c1fa60a 100644 --- a/src/cmd/compile/internal/ssa/rewritePPC64.go +++ b/src/cmd/compile/internal/ssa/rewritePPC64.go @@ -11372,6 +11372,18 @@ func rewriteValuePPC64_OpPPC64NEG(v *Value) bool { v.AddArg(x) return true } + // match: (NEG (SUB x y)) + // result: (SUB y x) + for { + if v_0.Op != OpPPC64SUB { + break + } + y := v_0.Args[1] + x := v_0.Args[0] + v.reset(OpPPC64SUB) + v.AddArg2(y, x) + return true + } return false } func rewriteValuePPC64_OpPPC64NOR(v *Value) bool { @@ -13912,6 +13924,8 @@ func rewriteValuePPC64_OpPPC64XOR(v *Value) bool { } func rewriteValuePPC64_OpPPC64XORconst(v *Value) bool { v_0 := v.Args[0] + b := v.Block + typ := &b.Func.Config.Types // match: (XORconst [c] (XORconst [d] x)) // result: (XORconst [c^d] x) for { @@ -13936,6 +13950,60 @@ func rewriteValuePPC64_OpPPC64XORconst(v *Value) bool { v.copyOf(x) return true } + // match: (XORconst [1] (ISELB [6] (MOVDconst [1]) cmp)) + // result: (ISELB [2] (MOVDconst [1]) cmp) + for { + if auxIntToInt64(v.AuxInt) != 1 || v_0.Op != OpPPC64ISELB || auxIntToInt32(v_0.AuxInt) != 6 { + break + } + cmp := v_0.Args[1] + v_0_0 := v_0.Args[0] + if v_0_0.Op != OpPPC64MOVDconst || auxIntToInt64(v_0_0.AuxInt) != 1 { + break + } + v.reset(OpPPC64ISELB) + v.AuxInt = int32ToAuxInt(2) + v0 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64) + v0.AuxInt = int64ToAuxInt(1) + v.AddArg2(v0, cmp) + return true + } + // match: (XORconst [1] (ISELB [5] (MOVDconst [1]) cmp)) + // result: (ISELB [1] (MOVDconst [1]) cmp) + for { + if auxIntToInt64(v.AuxInt) != 1 || v_0.Op != OpPPC64ISELB || auxIntToInt32(v_0.AuxInt) != 5 { + break + } + cmp := v_0.Args[1] + v_0_0 := v_0.Args[0] + if v_0_0.Op != OpPPC64MOVDconst || auxIntToInt64(v_0_0.AuxInt) != 1 { + break + } + v.reset(OpPPC64ISELB) + v.AuxInt = int32ToAuxInt(1) + v0 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64) + v0.AuxInt = int64ToAuxInt(1) + v.AddArg2(v0, cmp) + return true + } + // match: (XORconst [1] (ISELB [4] (MOVDconst [1]) cmp)) + // result: (ISELB [0] (MOVDconst [1]) cmp) + for { + if auxIntToInt64(v.AuxInt) != 1 || v_0.Op != OpPPC64ISELB || auxIntToInt32(v_0.AuxInt) != 4 { + break + } + cmp := v_0.Args[1] + v_0_0 := v_0.Args[0] + if v_0_0.Op != OpPPC64MOVDconst || auxIntToInt64(v_0_0.AuxInt) != 1 { + break + } + v.reset(OpPPC64ISELB) + v.AuxInt = int32ToAuxInt(0) + v0 := b.NewValue0(v.Pos, OpPPC64MOVDconst, typ.Int64) + v0.AuxInt = int64ToAuxInt(1) + v.AddArg2(v0, cmp) + return true + } return false } func rewriteValuePPC64_OpPanicBounds(v *Value) bool { -- GitLab From 6ec9a1da2d48fdc94093feb0ea3465129e11fc24 Mon Sep 17 00:00:00 2001 From: Archana R Date: Tue, 19 Oct 2021 04:11:46 -0500 Subject: [PATCH 1688/2500] internal/bytealg: fix Separator length check for Index/ppc64le Modified condition in the ASM implementation of indexbody to determine if separator length crosses 16 bytes to BGT from BGE to avoid incorrectly crossing a page. Also fixed IndexString to invoke indexbodyp9 when on the POWER9 platform Change-Id: I0602a797cc75287990eea1972e9e473744f6f5a9 Reviewed-on: https://go-review.googlesource.com/c/go/+/356849 Run-TryBot: Lynn Boger TryBot-Result: Go Bot Reviewed-by: Lynn Boger Trust: Keith Randall --- src/internal/bytealg/index_ppc64x.s | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/internal/bytealg/index_ppc64x.s b/src/internal/bytealg/index_ppc64x.s index f587a8ae25..ab47495427 100644 --- a/src/internal/bytealg/index_ppc64x.s +++ b/src/internal/bytealg/index_ppc64x.s @@ -85,7 +85,7 @@ TEXT ·IndexString(SB),NOSPLIT|NOFRAME,$0-40 MOVBZ internal∕cpu·PPC64+const_offsetPPC64HasPOWER9(SB), R7 CMP R7, $1 BNE power8 - BR indexbody<>(SB) + BR indexbodyp9<>(SB) #endif power8: @@ -152,7 +152,7 @@ loadge16: ANDCC $15, R5, R9 // Find byte offset of sep ADD R9, R6, R10 // Add sep len CMP R10, $16 // Check if sep len+offset > 16 - BGE sepcross16 // Sep crosses 16 byte boundary + BGT sepcross16 // Sep crosses 16 byte boundary RLDICR $0, R5, $59, R8 // Adjust addr to 16 byte container VLOADSWAP(R8, R0, V0, V0_)// Load 16 bytes @R8 into V0 @@ -490,7 +490,7 @@ loadge16: ANDCC $15, R5, R9 // Find byte offset of sep ADD R9, R6, R10 // Add sep len CMP R10, $16 // Check if sep len+offset > 16 - BGE sepcross16 // Sep crosses 16 byte boundary + BGT sepcross16 // Sep crosses 16 byte boundary RLDICR $0, R5, $59, R8 // Adjust addr to 16 byte container LXVB16X (R8)(R0), V0_ // Load 16 bytes @R8 into V0 -- GitLab From 02a36668aa13c3182d29da678764c8f4f5a9499b Mon Sep 17 00:00:00 2001 From: emahiro Date: Fri, 22 Oct 2021 00:34:33 +0900 Subject: [PATCH 1689/2500] runtime: fix typo of pushBackAll MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: #49081 Change-Id: Ie6742f1e7a60c2d92ce1283bcfaa3eac521440a1 Reviewed-on: https://go-review.googlesource.com/c/go/+/357629 Reviewed-by: Daniel Martí Trust: Daniel Martí Trust: Cherry Mui --- src/runtime/proc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index b80f09f993..990637e21a 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -6123,7 +6123,7 @@ func (q *gQueue) pushBack(gp *g) { q.tail.set(gp) } -// pushBackAll adds all Gs in l2 to the tail of q. After this q2 must +// pushBackAll adds all Gs in q2 to the tail of q. After this q2 must // not be used. func (q *gQueue) pushBackAll(q2 gQueue) { if q2.tail == 0 { -- GitLab From 24999c3a8a811807ce096c5a39c5e2f2f213d2e3 Mon Sep 17 00:00:00 2001 From: Amelia Downs Date: Mon, 18 Oct 2021 13:06:58 -0400 Subject: [PATCH 1690/2500] net/url: add testable examples for url pkg funcs Change-Id: I61011b75128478aa50308d84f4cba23b3e241b3f Reviewed-on: https://go-review.googlesource.com/c/go/+/356536 Trust: Damien Neil Trust: Cherry Mui Run-TryBot: Damien Neil TryBot-Result: Go Bot Reviewed-by: Damien Neil --- src/net/url/example_test.go | 40 +++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/net/url/example_test.go b/src/net/url/example_test.go index 476132a1c9..dfce2fc11c 100644 --- a/src/net/url/example_test.go +++ b/src/net/url/example_test.go @@ -12,6 +12,46 @@ import ( "strings" ) +func ExamplePathEscape() { + path := url.PathEscape("my/cool+blog&about,stuff") + fmt.Println(path) + + // Output: + // my%2Fcool+blog&about%2Cstuff +} + +func ExamplePathUnescape() { + escapedPath := "my%2Fcool+blog&about%2Cstuff" + path, err := url.PathUnescape(escapedPath) + if err != nil { + log.Fatal(err) + } + fmt.Println(path) + + // Output: + // my/cool+blog&about,stuff +} + +func ExampleQueryEscape() { + query := url.QueryEscape("my/cool+blog&about,stuff") + fmt.Println(query) + + // Output: + // my%2Fcool%2Bblog%26about%2Cstuff +} + +func ExampleQueryUnescape() { + escapedQuery := "my%2Fcool%2Bblog%26about%2Cstuff" + query, err := url.QueryUnescape(escapedQuery) + if err != nil { + log.Fatal(err) + } + fmt.Println(query) + + // Output: + // my/cool+blog&about,stuff +} + func ExampleValues() { v := url.Values{} v.Set("name", "Ava") -- GitLab From 392bb0677cfe6e6058d4f11953de80cdc20c52a8 Mon Sep 17 00:00:00 2001 From: Amelia Downs Date: Mon, 18 Oct 2021 12:36:07 -0400 Subject: [PATCH 1691/2500] net/url: add testable examples for Values funcs Change-Id: Id71f3d8d7c1ef7910d5d9497167dc677f2f0a2ef Reviewed-on: https://go-review.googlesource.com/c/go/+/356535 Trust: Damien Neil Trust: Cherry Mui Run-TryBot: Damien Neil TryBot-Result: Go Bot Reviewed-by: Damien Neil --- src/net/url/example_test.go | 78 +++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/src/net/url/example_test.go b/src/net/url/example_test.go index dfce2fc11c..87b6e74a85 100644 --- a/src/net/url/example_test.go +++ b/src/net/url/example_test.go @@ -68,6 +68,84 @@ func ExampleValues() { // [Jess Sarah Zoe] } +func ExampleValues_Add() { + v := url.Values{} + v.Add("cat sounds", "meow") + v.Add("cat sounds", "mew") + v.Add("cat sounds", "mau") + fmt.Println(v["cat sounds"]) + + // Output: + // [meow mew mau] +} + +func ExampleValues_Del() { + v := url.Values{} + v.Add("cat sounds", "meow") + v.Add("cat sounds", "mew") + v.Add("cat sounds", "mau") + fmt.Println(v["cat sounds"]) + + v.Del("cat sounds") + fmt.Println(v["cat sounds"]) + + // Output: + // [meow mew mau] + // [] +} + +func ExampleValues_Encode() { + v := url.Values{} + v.Add("cat sounds", "meow") + v.Add("cat sounds", "mew/") + v.Add("cat sounds", "mau$") + fmt.Println(v.Encode()) + + // Output: + // cat+sounds=meow&cat+sounds=mew%2F&cat+sounds=mau%24 +} + +func ExampleValues_Get() { + v := url.Values{} + v.Add("cat sounds", "meow") + v.Add("cat sounds", "mew") + v.Add("cat sounds", "mau") + fmt.Printf("%q\n", v.Get("cat sounds")) + fmt.Printf("%q\n", v.Get("dog sounds")) + + // Output: + // "meow" + // "" +} + +func ExampleValues_Has() { + v := url.Values{} + v.Add("cat sounds", "meow") + v.Add("cat sounds", "mew") + v.Add("cat sounds", "mau") + fmt.Println(v.Has("cat sounds")) + fmt.Println(v.Has("dog sounds")) + + // Output: + // true + // false +} + +func ExampleValues_Set() { + v := url.Values{} + v.Add("cat sounds", "meow") + v.Add("cat sounds", "mew") + v.Add("cat sounds", "mau") + fmt.Println(v["cat sounds"]) + + v.Set("cat sounds", "meow") + fmt.Println(v["cat sounds"]) + + // Output: + // [meow mew mau] + // [meow] +} + func ExampleURL() { u, err := url.Parse("http://bing.com/search?q=dotnet") if err != nil { -- GitLab From 8151b56c5d1de8f654a6e6789a0e607b55845c1e Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Thu, 21 Oct 2021 13:23:29 -0400 Subject: [PATCH 1692/2500] go/types, types2: always return an underlying type from optype Optype should never return a defined type. Change-Id: I37b29e0c958e127e75e834e71d6392ea80827773 Reviewed-on: https://go-review.googlesource.com/c/go/+/357694 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- .../compile/internal/types2/testdata/examples/types.go2 | 8 ++++++++ src/cmd/compile/internal/types2/type.go | 2 +- src/go/types/testdata/examples/types.go2 | 8 ++++++++ src/go/types/type.go | 2 +- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/types2/testdata/examples/types.go2 b/src/cmd/compile/internal/types2/testdata/examples/types.go2 index 55b1b0da57..f177c78d06 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/types.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/types.go2 @@ -304,3 +304,11 @@ func _[P interface{ ~[]E }, E interface{ map[string]P } ]() P { return P{E{"foo": x}} return P{{"foo": x}, {}} } + +// This is a degenerate case with a singleton type set, but we can create +// composite literals even if the structural type is a defined type. +type MyInts []int + +func _[P MyInts]() P { + return P{} +} diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 400d6f7128..3fb05e9d63 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -57,7 +57,7 @@ func optype(typ Type) Type { // See also issue #39680. if u := t.structuralType(); u != nil { assert(u != typ) // "naked" type parameters cannot be embedded - return u + return under(u) // optype should always return an underlying type } return theTop } diff --git a/src/go/types/testdata/examples/types.go2 b/src/go/types/testdata/examples/types.go2 index 2e6eeb2204..807c03238f 100644 --- a/src/go/types/testdata/examples/types.go2 +++ b/src/go/types/testdata/examples/types.go2 @@ -310,3 +310,11 @@ func _[P interface{ ~[]E }, E interface{ map[string]P } ]() P { return P{E{"foo": x}} return P{{"foo": x}, {}} } + +// This is a degenerate case with a singleton type set, but we can create +// composite literals even if the structural type is a defined type. +type MyInts []int + +func _[P MyInts]() P { + return P{} +} diff --git a/src/go/types/type.go b/src/go/types/type.go index 31149cfd36..502c9b2d52 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -57,7 +57,7 @@ func optype(typ Type) Type { // See also issue #39680. if u := t.structuralType(); u != nil { assert(u != typ) // "naked" type parameters cannot be embedded - return u + return under(u) // optype should always return an underlying type } return theTop } -- GitLab From 6508fdad9d83d6792314639c9819a15894728682 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Thu, 8 Apr 2021 21:07:02 +0000 Subject: [PATCH 1693/2500] runtime: formalize and fix gcPercent synchronization Currently gcController.gcPercent is read non-atomically by gcControllerState.revise and gcTrigger.test, but these users may execute concurrently with an update to gcPercent. Although revise's results are best-effort, reading it directly in this way is, generally speaking, unsafe. This change makes gcPercent atomically updated for concurrent readers and documents the complete synchronization semantics. Because gcPercent otherwise only updated with the heap lock held or the world stopped, all other reads can remain unsynchronized. For #44167. Change-Id: If09af103aae84a1e133e2d4fed8ab888d4b8f457 Reviewed-on: https://go-review.googlesource.com/c/go/+/308690 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Michael Pratt --- src/runtime/mgc.go | 2 +- src/runtime/mgcpacer.go | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go index 6f8463c253..f937287281 100644 --- a/src/runtime/mgc.go +++ b/src/runtime/mgc.go @@ -545,7 +545,7 @@ func (t gcTrigger) test() bool { // own write. return gcController.heapLive >= gcController.trigger case gcTriggerTime: - if gcController.gcPercent < 0 { + if atomic.Loadint32(&gcController.gcPercent) < 0 { return false } lastgc := int64(atomic.Load64(&memstats.last_gc_nanotime)) diff --git a/src/runtime/mgcpacer.go b/src/runtime/mgcpacer.go index 55f3bc926d..44b870446f 100644 --- a/src/runtime/mgcpacer.go +++ b/src/runtime/mgcpacer.go @@ -73,6 +73,10 @@ var gcController gcControllerState type gcControllerState struct { // Initialized from $GOGC. GOGC=off means no GC. + // + // Updated atomically with mheap_.lock held or during a STW. + // Safe to read atomically at any time, or non-atomically with + // mheap_.lock or STW. gcPercent int32 _ uint32 // padding so following 64-bit values are 8-byte aligned @@ -355,7 +359,7 @@ func (c *gcControllerState) startCycle() { // is when assists are enabled and the necessary statistics are // available). func (c *gcControllerState) revise() { - gcPercent := c.gcPercent + gcPercent := atomic.Loadint32(&c.gcPercent) if gcPercent < 0 { // If GC is disabled but we're running a forced GC, // act like GOGC is huge for the below calculations. @@ -800,7 +804,8 @@ func (c *gcControllerState) setGCPercent(in int32) int32 { if in < 0 { in = -1 } - c.gcPercent = in + // Write it atomically so readers like revise() can read it safely. + atomic.Storeint32(&c.gcPercent, in) c.heapMinimum = defaultHeapMinimum * uint64(c.gcPercent) / 100 // Update pacing in response to gcPercent change. c.commit(c.triggerRatio) -- GitLab From f99e40aac023d818e8c2594e5b8c075786087132 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Thu, 8 Apr 2021 22:01:13 +0000 Subject: [PATCH 1694/2500] runtime: detangle gcPaceScavenger from the pacer Currently gcPaceScavenger is called by gcControllerState.commit, but it manipulates global state which precludes testing. This change detangles the two. Change-Id: I10d8ebdf426d99ba49d2f2cb4fb64891e9fd6091 Reviewed-on: https://go-review.googlesource.com/c/go/+/309272 Reviewed-by: Michael Pratt Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot --- src/runtime/mgc.go | 1 + src/runtime/mgcpacer.go | 5 +++-- src/runtime/mgcscavenge.go | 13 +++++++++---- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go index f937287281..429b907322 100644 --- a/src/runtime/mgc.go +++ b/src/runtime/mgc.go @@ -971,6 +971,7 @@ func gcMarkTermination(nextTriggerRatio float64) { // Update GC trigger and pacing for the next cycle. gcController.commit(nextTriggerRatio) + gcPaceScavenger(gcController.heapGoal, gcController.lastHeapGoal) // Update timing memstats now := nanotime() diff --git a/src/runtime/mgcpacer.go b/src/runtime/mgcpacer.go index 44b870446f..73fe6e15e4 100644 --- a/src/runtime/mgcpacer.go +++ b/src/runtime/mgcpacer.go @@ -769,8 +769,6 @@ func (c *gcControllerState) commit(triggerRatio float64) { mheap_.pagesSweptBasis.Store(pagesSwept) } } - - gcPaceScavenger() } // effectiveGrowthRatio returns the current effective heap growth @@ -796,6 +794,8 @@ func (c *gcControllerState) effectiveGrowthRatio() float64 { // setGCPercent updates gcPercent and all related pacer state. // Returns the old value of gcPercent. // +// Calls gcControllerState.commit. +// // The world must be stopped, or mheap_.lock must be held. func (c *gcControllerState) setGCPercent(in int32) int32 { assertWorldStoppedOrLockHeld(&mheap_.lock) @@ -819,6 +819,7 @@ func setGCPercent(in int32) (out int32) { systemstack(func() { lock(&mheap_.lock) out = gcController.setGCPercent(in) + gcPaceScavenger(gcController.heapGoal, gcController.lastHeapGoal) unlock(&mheap_.lock) }) diff --git a/src/runtime/mgcscavenge.go b/src/runtime/mgcscavenge.go index 2bb19985db..fb9b5c8694 100644 --- a/src/runtime/mgcscavenge.go +++ b/src/runtime/mgcscavenge.go @@ -105,7 +105,8 @@ func heapRetained() uint64 { } // gcPaceScavenger updates the scavenger's pacing, particularly -// its rate and RSS goal. +// its rate and RSS goal. For this, it requires the current heapGoal, +// and the heapGoal for the previous GC cycle. // // The RSS goal is based on the current heap goal with a small overhead // to accommodate non-determinism in the allocator. @@ -113,18 +114,22 @@ func heapRetained() uint64 { // The pacing is based on scavengePageRate, which applies to both regular and // huge pages. See that constant for more information. // +// Must be called whenever GC pacing is updated. +// // mheap_.lock must be held or the world must be stopped. -func gcPaceScavenger() { +func gcPaceScavenger(heapGoal, lastHeapGoal uint64) { + assertWorldStoppedOrLockHeld(&mheap_.lock) + // If we're called before the first GC completed, disable scavenging. // We never scavenge before the 2nd GC cycle anyway (we don't have enough // information about the heap yet) so this is fine, and avoids a fault // or garbage data later. - if gcController.lastHeapGoal == 0 { + if lastHeapGoal == 0 { mheap_.scavengeGoal = ^uint64(0) return } // Compute our scavenging goal. - goalRatio := float64(atomic.Load64(&gcController.heapGoal)) / float64(gcController.lastHeapGoal) + goalRatio := float64(heapGoal) / float64(lastHeapGoal) retainedGoal := uint64(float64(memstats.last_heap_inuse) * goalRatio) // Add retainExtraPercent overhead to retainedGoal. This calculation // looks strange but the purpose is to arrive at an integer division -- GitLab From b8da7e4c4c9e97b3d1ebfb07506acdd61277b988 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 20 Oct 2021 13:56:15 -0700 Subject: [PATCH 1695/2500] cmd/compile: fix inlining of labeled for loops There is already a mechanism using inlgen to rename labels insided inlined functions so that they are unique and don't clash with loops in the outer function. This is used for OLABEL and OGOTO. Now that we are doing inlining of OFOR loops, we need to do this translation for OBREAK, OCONTINUE, and OFOR. I also added the translation for ORANGE loops, in anticipation of a CL that will allow inlining of ORANGE for loops. Fixes #49100 Change-Id: I2ccddc3350370825c386965f4a1e4bc54d3c369b Reviewed-on: https://go-review.googlesource.com/c/go/+/357649 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky Trust: Dan Scales --- src/cmd/compile/internal/inline/inl.go | 35 +++++++++++++++++++++----- test/fixedbugs/issue49100.go | 27 ++++++++++++++++++++ test/fixedbugs/issue49100.out | 12 +++++++++ 3 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 test/fixedbugs/issue49100.go create mode 100644 test/fixedbugs/issue49100.out diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index a2268a5465..fb6cf53155 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -1223,7 +1223,7 @@ func (subst *inlsubst) node(n ir.Node) ir.Node { // Don't do special substitutions if inside a closure break } - // Since we don't handle bodies with closures, + // Because of the above test for subst.newclofn, // this return is guaranteed to belong to the current inlined function. n := n.(*ir.ReturnStmt) init := subst.list(n.Init()) @@ -1251,7 +1251,7 @@ func (subst *inlsubst) node(n ir.Node) ir.Node { typecheck.Stmts(init) return ir.NewBlockStmt(base.Pos, init) - case ir.OGOTO: + case ir.OGOTO, ir.OBREAK, ir.OCONTINUE: if subst.newclofn != nil { // Don't do special substitutions if inside a closure break @@ -1260,8 +1260,7 @@ func (subst *inlsubst) node(n ir.Node) ir.Node { m := ir.Copy(n).(*ir.BranchStmt) m.SetPos(subst.updatedPos(m.Pos())) *m.PtrInit() = nil - p := fmt.Sprintf("%s·%d", n.Label.Name, inlgen) - m.Label = typecheck.Lookup(p) + m.Label = translateLabel(n.Label) return m case ir.OLABEL: @@ -1273,8 +1272,7 @@ func (subst *inlsubst) node(n ir.Node) ir.Node { m := ir.Copy(n).(*ir.LabelStmt) m.SetPos(subst.updatedPos(m.Pos())) *m.PtrInit() = nil - p := fmt.Sprintf("%s·%d", n.Label.Name, inlgen) - m.Label = typecheck.Lookup(p) + m.Label = translateLabel(n.Label) return m case ir.OCLOSURE: @@ -1286,6 +1284,21 @@ func (subst *inlsubst) node(n ir.Node) ir.Node { m.SetPos(subst.updatedPos(m.Pos())) ir.EditChildren(m, subst.edit) + if subst.newclofn == nil { + // Translate any label on FOR or RANGE loops + if m.Op() == ir.OFOR { + m := m.(*ir.ForStmt) + m.Label = translateLabel(m.Label) + return m + } + + if m.Op() == ir.ORANGE { + m := m.(*ir.RangeStmt) + m.Label = translateLabel(m.Label) + return m + } + } + switch m := m.(type) { case *ir.AssignStmt: if lhs, ok := m.X.(*ir.Name); ok && lhs.Defn == &subst.defnMarker { @@ -1302,6 +1315,16 @@ func (subst *inlsubst) node(n ir.Node) ir.Node { return m } +// translateLabel makes a label from an inlined function (if non-nil) be unique by +// adding "·inlgen". +func translateLabel(l *types.Sym) *types.Sym { + if l == nil { + return nil + } + p := fmt.Sprintf("%s·%d", l.Name, inlgen) + return typecheck.Lookup(p) +} + func (subst *inlsubst) updatedPos(xpos src.XPos) src.XPos { if subst.noPosUpdate { return xpos diff --git a/test/fixedbugs/issue49100.go b/test/fixedbugs/issue49100.go new file mode 100644 index 0000000000..3a2e972751 --- /dev/null +++ b/test/fixedbugs/issue49100.go @@ -0,0 +1,27 @@ +// run + +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func f(j int) { +loop: + for i := 0; i < 4; i++ { + if i == 1 { + continue loop + } + println(j, i) + } +} + +func main() { +loop: + for j := 0; j < 5; j++ { + f(j) + if j == 3 { + break loop + } + } +} diff --git a/test/fixedbugs/issue49100.out b/test/fixedbugs/issue49100.out new file mode 100644 index 0000000000..326d41365a --- /dev/null +++ b/test/fixedbugs/issue49100.out @@ -0,0 +1,12 @@ +0 0 +0 2 +0 3 +1 0 +1 2 +1 3 +2 0 +2 2 +2 3 +3 0 +3 2 +3 3 -- GitLab From 5a3d0f5a6361a2a1ccba19ad8d8da8b4367ea2c9 Mon Sep 17 00:00:00 2001 From: "Paul E. Murphy" Date: Mon, 9 Aug 2021 11:17:08 -0500 Subject: [PATCH 1696/2500] cmd/internal/obj/ppc64: rework argument classifications This introduces a number of new classifications which will make it easier to generate functions to assemble the new instructions of ISA 3.1, and potentially earlier versions. No code generation changes should occur as a result of these. These allow finer control over how an opcode is matched to an optab entry. Literal values are now classified based on the smallest number of bits needed to encode, and matching rules will accept a literal if it can be zero/sign extended to fit a larger literal class. Likewise, support classifying even register numbers for GPR, VSX, and FPR instructions. Some instructions require and even/odd register pair, and these are usually represented by specifying the even register, and similarly encoded. Likewise, add a unit test for the argument classifier function (aclass). This caught an off-by-one bug in aclass which is also fixed. Updates #44549 Change-Id: Ia03013aea8b56c4d59b7c3812cdd67ddb3b720b9 Reviewed-on: https://go-review.googlesource.com/c/go/+/350152 Reviewed-by: Cherry Mui Reviewed-by: Lynn Boger Run-TryBot: Cherry Mui TryBot-Result: Go Bot --- src/cmd/internal/obj/ppc64/a.out.go | 89 +++++---- src/cmd/internal/obj/ppc64/anames9.go | 22 ++- src/cmd/internal/obj/ppc64/asm9.go | 250 +++++++++++++------------ src/cmd/internal/obj/ppc64/asm_test.go | 114 +++++++++++ 4 files changed, 316 insertions(+), 159 deletions(-) diff --git a/src/cmd/internal/obj/ppc64/a.out.go b/src/cmd/internal/obj/ppc64/a.out.go index dd6d903e28..fe18296034 100644 --- a/src/cmd/internal/obj/ppc64/a.out.go +++ b/src/cmd/internal/obj/ppc64/a.out.go @@ -350,41 +350,64 @@ const ( ) const ( - C_NONE = iota - C_REG - C_FREG - C_VREG - C_VSREG - C_CREG - C_SPR /* special processor register */ - C_ZCON - C_SCON /* 16 bit signed */ - C_UCON /* 32 bit signed, low 16 bits 0 */ - C_ADDCON /* -0x8000 <= v < 0 */ - C_ANDCON /* 0 < v <= 0xFFFF */ - C_LCON /* other 32 */ - C_DCON /* other 64 (could subdivide further) */ - C_SACON /* $n(REG) where n <= int16 */ - C_LACON /* $n(REG) where int16 < n <= int32 */ - C_DACON /* $n(REG) where int32 < n */ - C_SBRA - C_LBRA - C_LBRAPIC - C_ZOREG // conjecture: either (1) register + zeroed offset, or (2) "R0" implies zero or C_REG - C_SOREG // D/DS form memory operation - C_LOREG // 32 bit addis + D/DS-form memory operation - C_FPSCR - C_XER - C_LR - C_CTR - C_ANY - C_GOK - C_ADDR - C_TLS_LE - C_TLS_IE - C_TEXTSIZE + C_NONE = iota + C_REGP /* An even numbered gpr which can be used a gpr pair argument */ + C_REG /* Any gpr register */ + C_FREGP /* An even numbered fpr which can be used a fpr pair argument */ + C_FREG /* Any fpr register */ + C_VREG /* Any vector register */ + C_VSREGP /* An even numbered vsx register which can be used as a vsx register pair argument */ + C_VSREG /* Any vector-scalar register */ + C_CREG /* The condition registor (CR) or a condition register field (CRx) */ + C_SPR /* special processor register */ + C_ZCON /* The constant zero */ + C_U1CON /* 1 bit unsigned constant */ + C_U2CON /* 2 bit unsigned constant */ + C_U3CON /* 3 bit unsigned constant */ + C_U4CON /* 4 bit unsigned constant */ + C_U5CON /* 5 bit unsigned constant */ + C_U8CON /* 8 bit unsigned constant */ + C_U15CON /* 15 bit unsigned constant */ + C_S16CON /* 16 bit signed constant */ + C_U16CON /* 16 bit unsigned constant */ + C_32S16CON /* Any 32 bit constant of the form 0x....0000, signed or unsigned */ + C_32CON /* Any constant which fits into 32 bits. Can be signed or unsigned */ + C_S34CON /* 34 bit signed constant */ + C_64CON /* Any constant which fits into 64 bits. Can be signed or unsigned */ + C_SACON /* $n(REG) where n <= int16 */ + C_LACON /* $n(REG) where n <= int32 */ + C_DACON /* $n(REG) where n <= int64 */ + C_SBRA /* A short offset argument to a branching instruction */ + C_LBRA /* A long offset argument to a branching instruction */ + C_LBRAPIC /* Like C_LBRA, but requires an extra NOP for potential TOC restore by the linker. */ + C_ZOREG /* An reg+reg memory arg, or a $0+reg memory op */ + C_SOREG /* An $n+reg memory arg where n is a 16 bit signed offset */ + C_LOREG /* An $n+reg memory arg where n is a 32 bit signed offset */ + C_FPSCR /* The fpscr register */ + C_XER /* The xer, holds the carry bit */ + C_LR /* The link register */ + C_CTR /* The count register */ + C_ANY /* Any argument */ + C_GOK /* A non-matched argument */ + C_ADDR /* A symbolic memory location */ + C_TLS_LE /* A thread local, local-exec, type memory arg */ + C_TLS_IE /* A thread local, initial-exec, type memory arg */ + C_TEXTSIZE /* An argument with Type obj.TYPE_TEXTSIZE */ C_NCLASS /* must be the last */ + + /* Aliased names which should be cleaned up, or integrated. */ + C_SCON = C_U15CON + C_UCON = C_32S16CON + C_ADDCON = C_S16CON + C_ANDCON = C_U16CON + C_LCON = C_32CON + + /* Aliased names which may be generated by ppc64map for the optab. */ + C_S3216CON = C_32S16CON // TODO: these should be treated differently (e.g xoris vs addis) + C_U3216CON = C_32S16CON + C_S32CON = C_32CON + C_U32CON = C_32CON ) const ( diff --git a/src/cmd/internal/obj/ppc64/anames9.go b/src/cmd/internal/obj/ppc64/anames9.go index b2632aa9ed..3b2aba77ab 100644 --- a/src/cmd/internal/obj/ppc64/anames9.go +++ b/src/cmd/internal/obj/ppc64/anames9.go @@ -6,19 +6,29 @@ package ppc64 var cnames9 = []string{ "NONE", + "REGP", "REG", + "FREGP", "FREG", "VREG", + "VSREGP", "VSREG", "CREG", "SPR", "ZCON", - "SCON", - "UCON", - "ADDCON", - "ANDCON", - "LCON", - "DCON", + "U1CON", + "U2CON", + "U3CON", + "U4CON", + "U5CON", + "U8CON", + "U15CON", + "S16CON", + "U16CON", + "32S16CON", + "32CON", + "S34CON", + "64CON", "SACON", "LACON", "DACON", diff --git a/src/cmd/internal/obj/ppc64/asm9.go b/src/cmd/internal/obj/ppc64/asm9.go index 6ed11b3f7e..08fb5118f0 100644 --- a/src/cmd/internal/obj/ppc64/asm9.go +++ b/src/cmd/internal/obj/ppc64/asm9.go @@ -307,8 +307,7 @@ var optab = []Optab{ {as: ABC, a6: C_ZOREG, type_: 15, size: 8}, {as: ASYNC, type_: 46, size: 4}, {as: AWORD, a1: C_LCON, type_: 40, size: 4}, - {as: ADWORD, a1: C_LCON, type_: 31, size: 8}, - {as: ADWORD, a1: C_DCON, type_: 31, size: 8}, + {as: ADWORD, a1: C_64CON, type_: 31, size: 8}, {as: ADWORD, a1: C_LACON, type_: 31, size: 8}, {as: AADDME, a1: C_REG, a6: C_REG, type_: 47, size: 4}, {as: AEXTSB, a1: C_REG, a6: C_REG, type_: 48, size: 4}, @@ -336,7 +335,7 @@ var optab = []Optab{ {as: ALDMX, a1: C_SOREG, a6: C_REG, type_: 45, size: 4}, /* load doubleword monitored, x-form */ {as: AMADDHD, a1: C_REG, a2: C_REG, a3: C_REG, a6: C_REG, type_: 83, size: 4}, /* multiply-add high/low doubleword, va-form */ {as: AADDEX, a1: C_REG, a2: C_REG, a3: C_SCON, a6: C_REG, type_: 94, size: 4}, /* add extended using alternate carry, z23-form */ - {as: ACRAND, a1: C_CREG, a6: C_CREG, type_: 2, size: 4}, /* logical ops for condition registers xl-form */ + {as: ACRAND, a1: C_CREG, a2: C_CREG, a6: C_CREG, type_: 2, size: 4}, /* logical ops for condition register bits xl-form */ /* Vector instructions */ @@ -485,15 +484,15 @@ var optab = []Optab{ {as: AXVCVSXDDP, a1: C_VSREG, a6: C_VSREG, type_: 89, size: 4}, /* vsx vector integer-fp conversion, xx2-form */ {as: ACMP, a1: C_REG, a6: C_REG, type_: 70, size: 4}, - {as: ACMP, a1: C_REG, a2: C_REG, a6: C_REG, type_: 70, size: 4}, + {as: ACMP, a1: C_REG, a2: C_CREG, a6: C_REG, type_: 70, size: 4}, {as: ACMP, a1: C_REG, a6: C_ADDCON, type_: 71, size: 4}, - {as: ACMP, a1: C_REG, a2: C_REG, a6: C_ADDCON, type_: 71, size: 4}, + {as: ACMP, a1: C_REG, a2: C_CREG, a6: C_ADDCON, type_: 71, size: 4}, {as: ACMPU, a1: C_REG, a6: C_REG, type_: 70, size: 4}, - {as: ACMPU, a1: C_REG, a2: C_REG, a6: C_REG, type_: 70, size: 4}, + {as: ACMPU, a1: C_REG, a2: C_CREG, a6: C_REG, type_: 70, size: 4}, {as: ACMPU, a1: C_REG, a6: C_ANDCON, type_: 71, size: 4}, - {as: ACMPU, a1: C_REG, a2: C_REG, a6: C_ANDCON, type_: 71, size: 4}, + {as: ACMPU, a1: C_REG, a2: C_CREG, a6: C_ANDCON, type_: 71, size: 4}, {as: AFCMPO, a1: C_FREG, a6: C_FREG, type_: 70, size: 4}, - {as: AFCMPO, a1: C_FREG, a2: C_REG, a6: C_FREG, type_: 70, size: 4}, + {as: AFCMPO, a1: C_FREG, a2: C_CREG, a6: C_FREG, type_: 70, size: 4}, {as: ATW, a1: C_LCON, a2: C_REG, a6: C_REG, type_: 60, size: 4}, {as: ATW, a1: C_LCON, a2: C_REG, a6: C_ADDCON, type_: 61, size: 4}, {as: ADCBF, a1: C_ZOREG, type_: 43, size: 4}, @@ -584,9 +583,11 @@ func addpad(pc, a int64, ctxt *obj.Link, cursym *obj.LSym) int { // or "MOVD R5, foo+10(SP) or pseudo-register is used. The other common case is when // generating constants in register like "MOVD $constant, Rx". func (c *ctxt9) getimpliedreg(a *obj.Addr, p *obj.Prog) int { - switch oclass(a) { - case C_ADDCON, C_ANDCON, C_UCON, C_LCON, C_SCON, C_ZCON: + class := oclass(a) + if class >= C_ZCON && class <= C_64CON { return REGZERO + } + switch class { case C_SACON, C_LACON: return REGSP case C_LOREG, C_SOREG, C_ZOREG: @@ -839,45 +840,49 @@ func isuint32(v uint64) bool { return uint64(uint32(v)) == v } +func (c *ctxt9) aclassreg(reg int16) int { + if REG_R0 <= reg && reg <= REG_R31 { + return C_REGP + int(reg&1) + } + if REG_F0 <= reg && reg <= REG_F31 { + return C_FREGP + int(reg&1) + } + if REG_V0 <= reg && reg <= REG_V31 { + return C_VREG + } + if REG_VS0 <= reg && reg <= REG_VS63 { + return C_VSREGP + int(reg&1) + } + if REG_CR0 <= reg && reg <= REG_CR7 || reg == REG_CR { + return C_CREG + } + if REG_SPR0 <= reg && reg <= REG_SPR0+1023 { + switch reg { + case REG_LR: + return C_LR + + case REG_XER: + return C_XER + + case REG_CTR: + return C_CTR + } + + return C_SPR + } + if reg == REG_FPSCR { + return C_FPSCR + } + return C_GOK +} + func (c *ctxt9) aclass(a *obj.Addr) int { switch a.Type { case obj.TYPE_NONE: return C_NONE case obj.TYPE_REG: - if REG_R0 <= a.Reg && a.Reg <= REG_R31 { - return C_REG - } - if REG_F0 <= a.Reg && a.Reg <= REG_F31 { - return C_FREG - } - if REG_V0 <= a.Reg && a.Reg <= REG_V31 { - return C_VREG - } - if REG_VS0 <= a.Reg && a.Reg <= REG_VS63 { - return C_VSREG - } - if REG_CR0 <= a.Reg && a.Reg <= REG_CR7 || a.Reg == REG_CR { - return C_CREG - } - if REG_SPR0 <= a.Reg && a.Reg <= REG_SPR0+1023 { - switch a.Reg { - case REG_LR: - return C_LR - - case REG_XER: - return C_XER - - case REG_CTR: - return C_CTR - } - - return C_SPR - } - if a.Reg == REG_FPSCR { - return C_FPSCR - } - return C_GOK + return c.aclassreg(a.Reg) case obj.TYPE_MEM: switch a.Name { @@ -948,7 +953,7 @@ func (c *ctxt9) aclass(a *obj.Addr) int { case obj.NAME_NONE: c.instoffset = a.Offset if a.Reg != 0 { - if -BIG <= c.instoffset && c.instoffset <= BIG { + if -BIG <= c.instoffset && c.instoffset < BIG { return C_SACON } if isint32(c.instoffset) { @@ -985,35 +990,47 @@ func (c *ctxt9) aclass(a *obj.Addr) int { } if c.instoffset >= 0 { - if c.instoffset == 0 { - return C_ZCON - } - if c.instoffset <= 0x7fff { - return C_SCON - } - if c.instoffset <= 0xffff { - return C_ANDCON - } - if c.instoffset&0xffff == 0 && isuint32(uint64(c.instoffset)) { /* && (instoffset & (1<<31)) == 0) */ - return C_UCON + sbits := bits.Len64(uint64(c.instoffset)) + switch { + case sbits <= 5: + return C_ZCON + sbits + case sbits <= 8: + return C_U8CON + case sbits <= 15: + return C_U15CON + case sbits <= 16: + return C_U16CON + case sbits <= 31: + // Special case, a positive int32 value which is a multiple of 2^16 + if c.instoffset&0xFFFF == 0 { + return C_U3216CON + } + return C_U32CON + case sbits <= 32: + return C_U32CON + case sbits <= 33: + return C_S34CON + default: + return C_64CON } - if isint32(c.instoffset) || isuint32(uint64(c.instoffset)) { - return C_LCON + } else { + sbits := bits.Len64(uint64(^c.instoffset)) + switch { + case sbits <= 15: + return C_S16CON + case sbits <= 31: + // Special case, a negative int32 value which is a multiple of 2^16 + if c.instoffset&0xFFFF == 0 { + return C_S3216CON + } + return C_S32CON + case sbits <= 33: + return C_S34CON + default: + return C_64CON } - return C_DCON } - if c.instoffset >= -0x8000 { - return C_ADDCON - } - if c.instoffset&0xffff == 0 && isint32(c.instoffset) { - return C_UCON - } - if isint32(c.instoffset) { - return C_LCON - } - return C_DCON - case obj.TYPE_BRANCH: if a.Sym != nil && c.ctxt.Flag_dynlink { return C_LBRAPIC @@ -1062,15 +1079,7 @@ func (c *ctxt9) oplook(p *obj.Prog) *Optab { a2 := C_NONE if p.Reg != 0 { - if REG_R0 <= p.Reg && p.Reg <= REG_R31 { - a2 = C_REG - } else if REG_V0 <= p.Reg && p.Reg <= REG_V31 { - a2 = C_VREG - } else if REG_VS0 <= p.Reg && p.Reg <= REG_VS63 { - a2 = C_VSREG - } else if REG_F0 <= p.Reg && p.Reg <= REG_F31 { - a2 = C_FREG - } + a2 = c.aclassreg(p.Reg) } // c.ctxt.Logf("oplook %v %d %d %d %d\n", p, a1, a2, a3, a4, a5, a6) @@ -1097,71 +1106,72 @@ func (c *ctxt9) oplook(p *obj.Prog) *Optab { return &ops[0] } +// Compare two operand types (ex C_REG, or C_SCON) +// and return true if b is compatible with a. +// +// Argument comparison isn't reflexitive, so care must be taken. +// a is the argument type as found in optab, b is the argument as +// fitted by aclass. func cmp(a int, b int) bool { if a == b { return true } switch a { - case C_LCON: - if b == C_ZCON || b == C_SCON || b == C_UCON || b == C_ADDCON || b == C_ANDCON { - return true - } - - case C_ADDCON: - if b == C_ZCON || b == C_SCON { - return true - } - - case C_ANDCON: - if b == C_ZCON || b == C_SCON { - return true - } case C_SPR: if b == C_LR || b == C_XER || b == C_CTR { return true } - case C_UCON: - if b == C_ZCON { - return true - } - - case C_SCON: - if b == C_ZCON { - return true - } + case C_U1CON: + return cmp(C_ZCON, b) + case C_U2CON: + return cmp(C_U1CON, b) + case C_U3CON: + return cmp(C_U2CON, b) + case C_U4CON: + return cmp(C_U3CON, b) + case C_U5CON: + return cmp(C_U4CON, b) + case C_U8CON: + return cmp(C_U5CON, b) + case C_U15CON: + return cmp(C_U8CON, b) + case C_U16CON: + return cmp(C_U15CON, b) + + case C_S16CON: + return cmp(C_U15CON, b) + case C_32CON: + return cmp(C_S16CON, b) || cmp(C_U16CON, b) || cmp(C_32S16CON, b) + case C_S34CON: + return cmp(C_32CON, b) + case C_64CON: + return cmp(C_S34CON, b) + + case C_32S16CON: + return cmp(C_ZCON, b) case C_LACON: - if b == C_SACON { - return true - } + return cmp(C_SACON, b) case C_LBRA: - if b == C_SBRA { - return true - } + return cmp(C_SBRA, b) case C_SOREG: - if b == C_ZOREG { - return true - } + return cmp(C_ZOREG, b) case C_LOREG: - if b == C_SOREG || b == C_ZOREG { - return true - } + return cmp(C_SOREG, b) + // An even/odd register input always matches the regular register types. case C_REG: - if b == C_ZCON { - return r0iszero != 0 /*TypeKind(100016)*/ - } - + return cmp(C_REGP, b) || (b == C_ZCON && r0iszero != 0) + case C_FREG: + return cmp(C_FREGP, b) case C_VSREG: /* Allow any VR argument as a VSR operand. */ - if b == C_VREG { - return true - } + return cmp(C_VSREGP, b) || cmp(C_VREG, b) case C_ANY: return true diff --git a/src/cmd/internal/obj/ppc64/asm_test.go b/src/cmd/internal/obj/ppc64/asm_test.go index ec0ba19e37..3a9b87363c 100644 --- a/src/cmd/internal/obj/ppc64/asm_test.go +++ b/src/cmd/internal/obj/ppc64/asm_test.go @@ -6,9 +6,12 @@ package ppc64 import ( "bytes" + "cmd/internal/obj" + "cmd/internal/objabi" "fmt" "internal/testenv" "io/ioutil" + "math" "os" "os/exec" "path/filepath" @@ -437,3 +440,114 @@ func TestRegValueAlignment(t *testing.T) { tstFunc(t.rstart, t.rend, t.msk, t.rout) } } + +// Verify interesting obj.Addr arguments are classified correctly. +func TestAddrClassifier(t *testing.T) { + type cmplx struct { + pic int + pic_dyn int + dyn int + nonpic int + } + tsts := [...]struct { + arg obj.Addr + output interface{} + }{ + // Supported register type args + {obj.Addr{Type: obj.TYPE_REG, Reg: REG_R1}, C_REG}, + {obj.Addr{Type: obj.TYPE_REG, Reg: REG_R2}, C_REGP}, + {obj.Addr{Type: obj.TYPE_REG, Reg: REG_F1}, C_FREG}, + {obj.Addr{Type: obj.TYPE_REG, Reg: REG_F2}, C_FREGP}, + {obj.Addr{Type: obj.TYPE_REG, Reg: REG_V2}, C_VREG}, + {obj.Addr{Type: obj.TYPE_REG, Reg: REG_VS1}, C_VSREG}, + {obj.Addr{Type: obj.TYPE_REG, Reg: REG_VS2}, C_VSREGP}, + {obj.Addr{Type: obj.TYPE_REG, Reg: REG_CR}, C_CREG}, + {obj.Addr{Type: obj.TYPE_REG, Reg: REG_CR1}, C_CREG}, + {obj.Addr{Type: obj.TYPE_REG, Reg: REG_SPR0}, C_SPR}, + {obj.Addr{Type: obj.TYPE_REG, Reg: REG_SPR0 + 1}, C_XER}, + {obj.Addr{Type: obj.TYPE_REG, Reg: REG_SPR0 + 8}, C_LR}, + {obj.Addr{Type: obj.TYPE_REG, Reg: REG_SPR0 + 9}, C_CTR}, + {obj.Addr{Type: obj.TYPE_REG, Reg: REG_FPSCR}, C_FPSCR}, + + // Memory type arguments. + {obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_GOTREF}, C_ADDR}, + {obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_TOCREF}, C_ADDR}, + {obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_EXTERN, Sym: &obj.LSym{Type: objabi.STLSBSS}}, cmplx{C_TLS_IE, C_TLS_IE, C_TLS_LE, C_TLS_LE}}, + {obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_EXTERN, Sym: &obj.LSym{Type: objabi.SDATA}}, C_ADDR}, + {obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_AUTO}, C_SOREG}, + {obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_AUTO, Offset: BIG}, C_LOREG}, + {obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_AUTO, Offset: -BIG - 1}, C_LOREG}, + {obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_PARAM}, C_SOREG}, + {obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_PARAM, Offset: BIG}, C_LOREG}, + {obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_PARAM, Offset: -BIG - 33}, C_LOREG}, // 33 is FixedFrameSize-1 + {obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_NONE}, C_ZOREG}, + {obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_NONE, Offset: 1}, C_SOREG}, + {obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_NONE, Offset: BIG}, C_LOREG}, + {obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_NONE, Offset: -BIG - 33}, C_LOREG}, + + // Misc (golang initializes -0.0 to 0.0, hence the obfuscation below) + {obj.Addr{Type: obj.TYPE_TEXTSIZE}, C_TEXTSIZE}, + {obj.Addr{Type: obj.TYPE_FCONST, Val: 0.0}, C_ZCON}, + {obj.Addr{Type: obj.TYPE_FCONST, Val: math.Float64frombits(0x8000000000000000)}, C_S16CON}, + + // Address type arguments + {obj.Addr{Type: obj.TYPE_ADDR, Reg: REG_R0, Name: obj.NAME_NONE, Offset: 1}, C_SACON}, + {obj.Addr{Type: obj.TYPE_ADDR, Reg: REG_R0, Name: obj.NAME_NONE, Offset: BIG}, C_LACON}, + {obj.Addr{Type: obj.TYPE_ADDR, Reg: REG_R0, Name: obj.NAME_NONE, Offset: -BIG - 1}, C_LACON}, + {obj.Addr{Type: obj.TYPE_ADDR, Reg: REG_R0, Name: obj.NAME_NONE, Offset: 1 << 32}, C_DACON}, + {obj.Addr{Type: obj.TYPE_ADDR, Name: obj.NAME_EXTERN, Sym: &obj.LSym{Type: objabi.SDATA}}, C_LACON}, + {obj.Addr{Type: obj.TYPE_ADDR, Name: obj.NAME_STATIC, Sym: &obj.LSym{Type: objabi.SDATA}}, C_LACON}, + {obj.Addr{Type: obj.TYPE_ADDR, Reg: REG_R0, Name: obj.NAME_AUTO, Offset: 1}, C_SACON}, + {obj.Addr{Type: obj.TYPE_ADDR, Reg: REG_R0, Name: obj.NAME_AUTO, Offset: BIG}, C_LACON}, + {obj.Addr{Type: obj.TYPE_ADDR, Reg: REG_R0, Name: obj.NAME_AUTO, Offset: -BIG - 1}, C_LACON}, + {obj.Addr{Type: obj.TYPE_ADDR, Reg: REG_R0, Name: obj.NAME_PARAM, Offset: 1}, C_SACON}, + {obj.Addr{Type: obj.TYPE_ADDR, Reg: REG_R0, Name: obj.NAME_PARAM, Offset: BIG}, C_LACON}, + {obj.Addr{Type: obj.TYPE_ADDR, Reg: REG_R0, Name: obj.NAME_PARAM, Offset: -BIG - 33}, C_LACON}, // 33 is FixedFrameSize-1 + + // Constant type arguments + {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 0}, C_ZCON}, + {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 1}, C_U1CON}, + {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 2}, C_U2CON}, + {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 4}, C_U3CON}, + {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 8}, C_U4CON}, + {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 16}, C_U5CON}, + {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 32}, C_U8CON}, + {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 1 << 14}, C_U15CON}, + {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 1 << 15}, C_U16CON}, + {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 1 << 16}, C_U3216CON}, + {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 1 + 1<<16}, C_U32CON}, + {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 1 << 32}, C_S34CON}, + {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 1 << 33}, C_64CON}, + {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: -1}, C_S16CON}, + {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: -0x10000}, C_S3216CON}, + {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: -0x10001}, C_S32CON}, + {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: -(1 << 33)}, C_S34CON}, + {obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: -(1 << 34)}, C_64CON}, + + // Branch like arguments + {obj.Addr{Type: obj.TYPE_BRANCH, Sym: &obj.LSym{Type: objabi.SDATA}}, cmplx{C_SBRA, C_LBRAPIC, C_LBRAPIC, C_SBRA}}, + {obj.Addr{Type: obj.TYPE_BRANCH}, C_SBRA}, + } + + pic_ctxt9 := ctxt9{ctxt: &obj.Link{Flag_shared: true, Arch: &Linkppc64}, autosize: 0} + pic_dyn_ctxt9 := ctxt9{ctxt: &obj.Link{Flag_shared: true, Flag_dynlink: true, Arch: &Linkppc64}, autosize: 0} + dyn_ctxt9 := ctxt9{ctxt: &obj.Link{Flag_dynlink: true, Arch: &Linkppc64}, autosize: 0} + nonpic_ctxt9 := ctxt9{ctxt: &obj.Link{Arch: &Linkppc64}, autosize: 0} + ctxts := [...]*ctxt9{&pic_ctxt9, &pic_dyn_ctxt9, &dyn_ctxt9, &nonpic_ctxt9} + name := [...]string{"pic", "pic_dyn", "dyn", "nonpic"} + for _, tst := range tsts { + var expect []int + switch tst.output.(type) { + case cmplx: + v := tst.output.(cmplx) + expect = []int{v.pic, v.pic_dyn, v.dyn, v.nonpic} + case int: + expect = []int{tst.output.(int), tst.output.(int), tst.output.(int), tst.output.(int)} + } + for i, _ := range ctxts { + if output := ctxts[i].aclass(&tst.arg); output != expect[i] { + t.Errorf("%s.aclass(%v) = %v, expected %v\n", name[i], tst.arg, DRconv(output), DRconv(expect[i])) + } + } + } +} -- GitLab From 3beab0cd71e9e4fedba13d762ed35db04851f1be Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Thu, 21 Oct 2021 18:59:10 -0400 Subject: [PATCH 1697/2500] go/types, types2: add the Interface.MarkImplicit method Add a new interface method, MarkImplicit, to allow marking interfaces as implicit from outside the type-checker. This is necessary so that we can capture the implicit bit in export data, and use it from importers. For #48424 For #49040 Change-Id: I999aba2a298f92432326d7ccbd87fe133a2e1a72 Reviewed-on: https://go-review.googlesource.com/c/go/+/357796 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/interface.go | 8 ++++++++ src/go/types/interface.go | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index 0704628dc6..048fcab024 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -54,6 +54,14 @@ func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface { return typ } +// MarkImplicit marks the interface t as implicit, meaning this interface +// corresponds to a constraint literal such as ~T or A|B without explicit +// interface embedding. MarkImplicit should be called before any concurrent use +// of implicit interfaces. +func (t *Interface) MarkImplicit() { + t.implicit = true +} + // NumExplicitMethods returns the number of explicitly declared methods of interface t. func (t *Interface) NumExplicitMethods() int { return len(t.methods) } diff --git a/src/go/types/interface.go b/src/go/types/interface.go index 2f4f10d45f..3d5573373f 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -73,6 +73,14 @@ func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface { return typ } +// MarkImplicit marks the interface t as implicit, meaning this interface +// corresponds to a constraint literal such as ~T or A|B without explicit +// interface embedding. MarkImplicit should be called before any concurrent use +// of implicit interfaces. +func (t *Interface) MarkImplicit() { + t.implicit = true +} + // NumExplicitMethods returns the number of explicitly declared methods of interface t. func (t *Interface) NumExplicitMethods() int { return len(t.methods) } -- GitLab From 23e57e59556f42d6935b65be63b59a8b0fc0e6ad Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 21 Oct 2021 23:35:05 +0700 Subject: [PATCH 1698/2500] reflect: make Value.Pointer panic on bad notinheap pointers Same as CL 350153 did for Value.Elem to panic on bad notinheap pointers. While at it, also add more tests for notinheap deref. Change-Id: Id7d9d12ad8467de5926b6a7e8f9d659fea5fedb5 Reviewed-on: https://go-review.googlesource.com/c/go/+/357630 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/reflect/all_test.go | 2 ++ src/reflect/value.go | 12 +++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index fcd0e15f0a..922998125b 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -7721,6 +7721,8 @@ func TestNotInHeapDeref(t *testing.T) { v = ValueOf((*nih)(unsafe.Pointer(new(int)))) shouldPanic("reflect: reflect.Value.Elem on an invalid notinheap pointer", func() { v.Elem() }) + shouldPanic("reflect: reflect.Value.Pointer on an invalid notinheap pointer", func() { v.Pointer() }) + shouldPanic("reflect: reflect.Value.UnsafePointer on an invalid notinheap pointer", func() { v.UnsafePointer() }) } func TestMethodCallValueCodePtr(t *testing.T) { diff --git a/src/reflect/value.go b/src/reflect/value.go index 7bb8ae5b97..3e723e82a4 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -1940,11 +1940,13 @@ func (v Value) Pointer() uintptr { switch k { case Ptr: if v.typ.ptrdata == 0 { - // Handle pointers to go:notinheap types directly, - // so we never materialize such pointers as an - // unsafe.Pointer. (Such pointers are always indirect.) - // See issue 42076. - return *(*uintptr)(v.ptr) + val := *(*uintptr)(v.ptr) + // Since it is a not-in-heap pointer, all pointers to the heap are + // forbidden! See comment in Value.Elem and issue #48399. + if !verifyNotInHeapPtr(val) { + panic("reflect: reflect.Value.Pointer on an invalid notinheap pointer") + } + return val } fallthrough case Chan, Map, UnsafePointer: -- GitLab From 9ff91b90988945c7bbe85fdef4a16d5f1af6b2c2 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 21 Oct 2021 14:31:40 +0700 Subject: [PATCH 1699/2500] cmd/compile: only look for struct type when crawling inline body CL 356254 fixed crawling of embeddable types during inline. However, we are too agressive, since when we call markEmbed for every type seen during inlining function body. That leads to false positive that for a non-embedded type, its unexported methods are also marked inline. Instead, we should only look at struct type that we seen during inlining function body, and calling markEmbed for all of its embedded fields. Fixes #49094 Change-Id: I6ef9a8bf1fc649ec6bf75e4883f6031ec8560ba1 Reviewed-on: https://go-review.googlesource.com/c/go/+/357232 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/typecheck/crawler.go | 8 +++++++- test/fixedbugs/issue49094.dir/a.go | 11 +++++++++++ test/fixedbugs/issue49094.dir/b.go | 11 +++++++++++ test/fixedbugs/issue49094.dir/p.go | 15 +++++++++++++++ test/fixedbugs/issue49094.go | 7 +++++++ 5 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 test/fixedbugs/issue49094.dir/a.go create mode 100644 test/fixedbugs/issue49094.dir/b.go create mode 100644 test/fixedbugs/issue49094.dir/p.go create mode 100644 test/fixedbugs/issue49094.go diff --git a/src/cmd/compile/internal/typecheck/crawler.go b/src/cmd/compile/internal/typecheck/crawler.go index b214ef2279..e1489ceedd 100644 --- a/src/cmd/compile/internal/typecheck/crawler.go +++ b/src/cmd/compile/internal/typecheck/crawler.go @@ -217,7 +217,13 @@ func (p *crawler) markInlBody(n *ir.Name) { // // We generate the wrapper for "struct{ t }".M, and inline call // to "struct{ t }".M, which makes "t.M" reachable. - p.markEmbed(t) + if t.IsStruct() { + for _, f := range t.FieldSlice() { + if f.Embedded != 0 { + p.markEmbed(f.Type) + } + } + } } } diff --git a/test/fixedbugs/issue49094.dir/a.go b/test/fixedbugs/issue49094.dir/a.go new file mode 100644 index 0000000000..9ec0fd9f93 --- /dev/null +++ b/test/fixedbugs/issue49094.dir/a.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type A struct{} + +func (a *A) f() bool { + return true +} diff --git a/test/fixedbugs/issue49094.dir/b.go b/test/fixedbugs/issue49094.dir/b.go new file mode 100644 index 0000000000..f2361958ac --- /dev/null +++ b/test/fixedbugs/issue49094.dir/b.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package b + +import "./a" + +func M(r *a.A) string { + return "" +} diff --git a/test/fixedbugs/issue49094.dir/p.go b/test/fixedbugs/issue49094.dir/p.go new file mode 100644 index 0000000000..581faf19ac --- /dev/null +++ b/test/fixedbugs/issue49094.dir/p.go @@ -0,0 +1,15 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +import ( + "./b" +) + +type S struct{} + +func (S) M() { + b.M(nil) +} diff --git a/test/fixedbugs/issue49094.go b/test/fixedbugs/issue49094.go new file mode 100644 index 0000000000..b83fbd7af1 --- /dev/null +++ b/test/fixedbugs/issue49094.go @@ -0,0 +1,7 @@ +// compiledir + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From ff8115d1a1b3bcaadfea10f6913e9fe083013799 Mon Sep 17 00:00:00 2001 From: Andy Pan Date: Fri, 22 Oct 2021 15:29:41 +0800 Subject: [PATCH 1700/2500] internal/poll: fix a few function names on comments Change-Id: I5b1dfeeb0ae5ac32667633151ef83bcf4654c43f Reviewed-on: https://go-review.googlesource.com/c/go/+/357957 Reviewed-by: Tobias Klauser Reviewed-by: Emmanuel Odeke Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot --- src/internal/poll/fd_unix.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/internal/poll/fd_unix.go b/src/internal/poll/fd_unix.go index 60b59df2e3..5489662889 100644 --- a/src/internal/poll/fd_unix.go +++ b/src/internal/poll/fd_unix.go @@ -230,7 +230,7 @@ func (fd *FD) ReadFrom(p []byte) (int, syscall.Sockaddr, error) { } } -// ReadFrom wraps the recvfrom network call for IPv4. +// ReadFromInet4 wraps the recvfrom network call for IPv4. func (fd *FD) ReadFromInet4(p []byte, from *syscall.SockaddrInet4) (int, error) { if err := fd.readLock(); err != nil { return 0, err @@ -257,7 +257,7 @@ func (fd *FD) ReadFromInet4(p []byte, from *syscall.SockaddrInet4) (int, error) } } -// ReadFrom wraps the recvfrom network call for IPv6. +// ReadFromInet6 wraps the recvfrom network call for IPv6. func (fd *FD) ReadFromInet6(p []byte, from *syscall.SockaddrInet6) (int, error) { if err := fd.readLock(); err != nil { return 0, err -- GitLab From 76dd01f45786757a08f1e070245d174cd64559be Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 20 Oct 2021 13:12:43 -0700 Subject: [PATCH 1701/2500] cmd/compile/internal/types2: reduce output when describing type parameters There's no need to say "type parameter" for a type parameter. The name is sufficient (they are always named), and the prose is followed by "constrained by". Change-Id: I98df8caa1432b8b7a874e58da6e3ed6be102b4a0 Reviewed-on: https://go-review.googlesource.com/c/go/+/357410 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/operand.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/types2/operand.go b/src/cmd/compile/internal/types2/operand.go index 19326b8342..a5b2729451 100644 --- a/src/cmd/compile/internal/types2/operand.go +++ b/src/cmd/compile/internal/types2/operand.go @@ -176,17 +176,14 @@ func operandString(x *operand, qf Qualifier) string { if hasType { if x.typ != Typ[Invalid] { var intro string - var tpar *TypeParam if isGeneric(x.typ) { intro = " of parameterized type " - } else if tpar = asTypeParam(x.typ); tpar != nil { - intro = " of type parameter " } else { intro = " of type " } buf.WriteString(intro) WriteType(&buf, x.typ, qf) - if tpar != nil { + if tpar := asTypeParam(x.typ); tpar != nil { buf.WriteString(" constrained by ") WriteType(&buf, tpar.bound, qf) // do not compute interface type sets here } -- GitLab From 5d414d180bfb631d3835f819f7f524ec271f11eb Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 19 Oct 2021 18:09:30 -0700 Subject: [PATCH 1702/2500] cmd/compile/internal/types2: more detailed error messages for generic conversions - slightly refactor convertibleTo and convertibleToImpl - provide ability to return a conversion failure cause - add detailed cause for generic conversions For #47150. Change-Id: Ie97d89be0234414ef4df22a6920e18acc944a102 Reviewed-on: https://go-review.googlesource.com/c/go/+/357249 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/api.go | 2 +- .../compile/internal/types2/conversions.go | 84 ++++++++++++------- src/cmd/compile/internal/types2/operand.go | 1 + .../types2/testdata/examples/conversions.go2 | 22 ++--- 4 files changed, 67 insertions(+), 42 deletions(-) diff --git a/src/cmd/compile/internal/types2/api.go b/src/cmd/compile/internal/types2/api.go index e6d28af3c8..f13fa95b62 100644 --- a/src/cmd/compile/internal/types2/api.go +++ b/src/cmd/compile/internal/types2/api.go @@ -438,7 +438,7 @@ func AssignableTo(V, T Type) bool { // ConvertibleTo reports whether a value of type V is convertible to a value of type T. func ConvertibleTo(V, T Type) bool { x := operand{mode: value, typ: V} - return x.convertibleTo(nil, T) // check not needed for non-constant x + return x.convertibleTo(nil, T, nil) // check not needed for non-constant x; if check == nil, cause can be nil } // Implements reports whether type V implements interface T. diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go index 112d728188..a4fba28fce 100644 --- a/src/cmd/compile/internal/types2/conversions.go +++ b/src/cmd/compile/internal/types2/conversions.go @@ -17,6 +17,7 @@ func (check *Checker) conversion(x *operand, T Type) { constArg := x.mode == constant_ var ok bool + var cause string switch { case constArg && isConstType(T): // constant conversion @@ -31,17 +32,20 @@ func (check *Checker) conversion(x *operand, T Type) { x.val = constant.MakeString(string(codepoint)) ok = true } - case x.convertibleTo(check, T): + case x.convertibleTo(check, T, &cause): // non-constant conversion x.mode = value ok = true } if !ok { - if x.mode != invalid { - check.errorf(x, "cannot convert %s to %s", x, T) - x.mode = invalid + var err error_ + err.errorf(x, "cannot convert %s to %s", x, T) + if cause != "" { + err.errorf(nopos, cause) } + check.report(&err) + x.mode = invalid return } @@ -80,57 +84,74 @@ func (check *Checker) conversion(x *operand, T Type) { // is tricky because we'd have to run updateExprType on the argument first. // (Issue #21982.) -// convertibleTo reports whether T(x) is valid. +// convertibleTo reports whether T(x) is valid. In the failure case, *cause +// may be set to the cause for the failure. // The check parameter may be nil if convertibleTo is invoked through an // exported API call, i.e., when all methods have been type-checked. -func (x *operand) convertibleTo(check *Checker, T Type) bool { +func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { // "x is assignable to T" - if ok, _ := x.assignableTo(check, T, nil); ok { + if ok, _ := x.assignableTo(check, T, cause); ok { return true } - // TODO(gri) consider passing under(x.typ), under(T) into convertibleToImpl (optimization) Vp, _ := under(x.typ).(*TypeParam) Tp, _ := under(T).(*TypeParam) + errorf := func(format string, args ...interface{}) { + if check != nil && cause != nil { + msg := check.sprintf(format, args...) + if *cause != "" { + msg += "\n\t" + *cause + } + *cause = msg + } + } + // generic cases // (generic operands cannot be constants, so we can ignore x.val) switch { case Vp != nil && Tp != nil: - x := *x // don't modify outer x return Vp.is(func(V *term) bool { - x.typ = V.typ return Tp.is(func(T *term) bool { - return x.convertibleToImpl(check, T.typ) + if !convertibleToImpl(check, V.typ, T.typ, cause) { + errorf("cannot convert %s (in %s) to %s (in %s)", V.typ, Vp, T.typ, Tp) + return false + } + return true }) }) case Vp != nil: - x := *x // don't modify outer x return Vp.is(func(V *term) bool { - x.typ = V.typ - return x.convertibleToImpl(check, T) + if !convertibleToImpl(check, V.typ, T, cause) { + errorf("cannot convert %s (in %s) to %s", V.typ, Vp, T) + return false + } + return true }) case Tp != nil: return Tp.is(func(T *term) bool { - return x.convertibleToImpl(check, T.typ) + if !convertibleToImpl(check, x.typ, T.typ, cause) { + errorf("cannot convert %s to %s (in %s)", x.typ, T.typ, Tp) + return false + } + return true }) } // non-generic case - return x.convertibleToImpl(check, T) + return convertibleToImpl(check, x.typ, T, cause) } // convertibleToImpl should only be called by convertibleTo -func (x *operand) convertibleToImpl(check *Checker, T Type) bool { - // "x's type and T have identical underlying types if tags are ignored" - V := x.typ +func convertibleToImpl(check *Checker, V, T Type, cause *string) bool { + // "V and T have identical underlying types if tags are ignored" Vu := under(V) Tu := under(T) if IdenticalIgnoreTags(Vu, Tu) { return true } - // "x's type and T are unnamed pointer types and their pointer base types + // "V and T are unnamed pointer types and their pointer base types // have identical underlying types if tags are ignored" if V, ok := V.(*Pointer); ok { if T, ok := T.(*Pointer); ok { @@ -140,22 +161,22 @@ func (x *operand) convertibleToImpl(check *Checker, T Type) bool { } } - // "x's type and T are both integer or floating point types" + // "V and T are both integer or floating point types" if isIntegerOrFloat(V) && isIntegerOrFloat(T) { return true } - // "x's type and T are both complex types" + // "V and T are both complex types" if isComplex(V) && isComplex(T) { return true } - // "x is an integer or a slice of bytes or runes and T is a string type" + // "V an integer or a slice of bytes or runes and T is a string type" if (isInteger(V) || isBytesOrRunes(Vu)) && isString(T) { return true } - // "x is a string and T is a slice of bytes or runes" + // "V a string and T is a slice of bytes or runes" if isString(V) && isBytesOrRunes(Tu) { return true } @@ -170,7 +191,7 @@ func (x *operand) convertibleToImpl(check *Checker, T Type) bool { return true } - // "x is a slice, T is a pointer-to-array type, + // "V a slice, T is a pointer-to-array type, // and the slice and array types have identical element types." if s := asSlice(V); s != nil { if p := asPointer(T); p != nil { @@ -180,12 +201,15 @@ func (x *operand) convertibleToImpl(check *Checker, T Type) bool { return true } // check != nil - if check.conf.CompilerErrorMessages { - check.error(x, "conversion of slices to array pointers only supported as of -lang=go1.17") - } else { - check.error(x, "conversion of slices to array pointers requires go1.17 or later") + if cause != nil { + if check.conf.CompilerErrorMessages { + // compiler error message assumes a -lang flag + *cause = "conversion of slices to array pointers only supported as of -lang=go1.17" + } else { + *cause = "conversion of slices to array pointers requires go1.17 or later" + } } - x.mode = invalid // avoid follow-up error + return false } } } diff --git a/src/cmd/compile/internal/types2/operand.go b/src/cmd/compile/internal/types2/operand.go index a5b2729451..5c8654dbf1 100644 --- a/src/cmd/compile/internal/types2/operand.go +++ b/src/cmd/compile/internal/types2/operand.go @@ -296,6 +296,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er if Ti, ok := Tu.(*Interface); ok { if m, wrongType := check.missingMethod(V, Ti, true); m != nil /* Implements(V, Ti) */ { if reason != nil { + // TODO(gri) the error messages here should follow the style in Checker.typeAssertion (factor!) if wrongType != nil { if Identical(m.typ, wrongType.typ) { *reason = fmt.Sprintf("missing method %s (%s has pointer receiver)", m.name, m.name) diff --git a/src/cmd/compile/internal/types2/testdata/examples/conversions.go2 b/src/cmd/compile/internal/types2/testdata/examples/conversions.go2 index 5c1b30a2b5..0acd2762a1 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/conversions.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/conversions.go2 @@ -21,7 +21,7 @@ type Far struct{f float64 } func _[X Foo, T Bar](x X) T { return T(x) } func _[X Foo|Bar, T Bar](x X) T { return T(x) } func _[X Foo, T Foo|Bar](x X) T { return T(x) } -func _[X Foo, T Far](x X) T { return T(x /* ERROR cannot convert */ ) } +func _[X Foo, T Far](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by Foo\) to T\n\tcannot convert Foo \(in X\) to Far \(in T\) */ ) } // "x's type and T are unnamed pointer types and their pointer base types // have identical underlying types if tags are ignored" @@ -29,7 +29,7 @@ func _[X Foo, T Far](x X) T { return T(x /* ERROR cannot convert */ ) } func _[X ~*Foo, T ~*Bar](x X) T { return T(x) } func _[X ~*Foo|~*Bar, T ~*Bar](x X) T { return T(x) } func _[X ~*Foo, T ~*Foo|~*Bar](x X) T { return T(x) } -func _[X ~*Foo, T ~*Far](x X) T { return T(x /* ERROR cannot convert */ ) } +func _[X ~*Foo, T ~*Far](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by ~\*Foo\) to T\n\tcannot convert \*Foo \(in X\) to \*Far \(in T\) */ ) } // Verify that the defined types in constraints are considered for the rule above. @@ -60,12 +60,12 @@ func _[X Unsigned, T Float](x X) T { return T(x) } func _[X Float, T Float](x X) T { return T(x) } func _[X, T Integer|Unsigned|Float](x X) T { return T(x) } -func _[X, T Integer|~string](x X) T { return T(x /* ERROR cannot convert */ ) } +func _[X, T Integer|~string](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by Integer\|~string\) to T\n\tcannot convert string \(in X\) to int \(in T\) */ ) } // "x's type and T are both complex types" func _[X, T Complex](x X) T { return T(x) } -func _[X, T Float|Complex](x X) T { return T(x /* ERROR cannot convert */ ) } +func _[X, T Float|Complex](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by Float\|Complex\) to T\n\tcannot convert float32 \(in X\) to complex64 \(in T\) */ ) } // "x is an integer or a slice of bytes or runes and T is a string type" @@ -76,25 +76,25 @@ func _[T ~string](x int) T { return T(x) } func _[T ~string](x myInt) T { return T(x) } func _[X Integer](x X) string { return string(x) } func _[X Integer](x X) myString { return myString(x) } -func _[X Integer](x X) *string { return (*string)(x /* ERROR cannot convert */ ) } +func _[X Integer](x X) *string { return (*string)(x /* ERROR cannot convert x \(variable of type X constrained by Integer\) to \*string\n\tcannot convert int \(in X\) to \*string */ ) } func _[T ~string](x []byte) T { return T(x) } func _[T ~string](x []rune) T { return T(x) } func _[X ~[]byte, T ~string](x X) T { return T(x) } func _[X ~[]rune, T ~string](x X) T { return T(x) } func _[X Integer|~[]byte|~[]rune, T ~string](x X) T { return T(x) } -func _[X Integer|~[]byte|~[]rune, T ~*string](x X) T { return T(x /* ERROR cannot convert */ ) } +func _[X Integer|~[]byte|~[]rune, T ~*string](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by Integer\|~\[\]byte\|~\[\]rune\) to T\n\tcannot convert int \(in X\) to \*string \(in T\) */ ) } // "x is a string and T is a slice of bytes or runes" func _[T ~[]byte](x string) T { return T(x) } func _[T ~[]rune](x string) T { return T(x) } -func _[T ~[]rune](x *string) T { return T(x /* ERROR cannot convert */ ) } +func _[T ~[]rune](x *string) T { return T(x /* ERROR cannot convert x \(variable of type \*string\) to T\n\tcannot convert \*string to \[\]rune \(in T\) */ ) } func _[X ~string, T ~[]byte](x X) T { return T(x) } func _[X ~string, T ~[]rune](x X) T { return T(x) } func _[X ~string, T ~[]byte|~[]rune](x X) T { return T(x) } -func _[X ~*string, T ~[]byte|~[]rune](x X) T { return T(x /* ERROR cannot convert */ ) } +func _[X ~*string, T ~[]byte|~[]rune](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by ~\*string\) to T\n\tcannot convert \*string \(in X\) to \[\]byte \(in T\) */ ) } // package unsafe: // "any pointer or value of underlying type uintptr can be converted into a unsafe.Pointer" @@ -103,20 +103,20 @@ type myUintptr uintptr func _[X ~uintptr](x X) unsafe.Pointer { return unsafe.Pointer(x) } func _[T unsafe.Pointer](x myUintptr) T { return T(x) } -func _[T unsafe.Pointer](x int64) T { return T(x /* ERROR cannot convert */ ) } +func _[T unsafe.Pointer](x int64) T { return T(x /* ERROR cannot convert x \(variable of type int64\) to T\n\tcannot convert int64 to unsafe\.Pointer \(in T\) */ ) } // "and vice versa" func _[T ~uintptr](x unsafe.Pointer) T { return T(x) } func _[X unsafe.Pointer](x X) uintptr { return uintptr(x) } func _[X unsafe.Pointer](x X) myUintptr { return myUintptr(x) } -func _[X unsafe.Pointer](x X) int64 { return int64(x /* ERROR cannot convert */ ) } +func _[X unsafe.Pointer](x X) int64 { return int64(x /* ERROR cannot convert x \(variable of type X constrained by unsafe\.Pointer\) to int64\n\tcannot convert unsafe\.Pointer \(in X\) to int64 */ ) } // "x is a slice, T is a pointer-to-array type, // and the slice and array types have identical element types." func _[X ~[]E, T ~*[10]E, E any](x X) T { return T(x) } -func _[X ~[]E, T ~[10]E, E any](x X) T { return T(x /* ERROR cannot convert */ ) } +func _[X ~[]E, T ~[10]E, E any](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by ~\[\]E\) to T\n\tcannot convert \[\]E \(in X\) to \[10\]E \(in T\) */ ) } // ---------------------------------------------------------------------------- // The following declarations can be replaced by the exported types of the -- GitLab From ae4d67c89dfef1cf9f30921e8f717ed5f56b6866 Mon Sep 17 00:00:00 2001 From: fanzha02 Date: Mon, 4 Jan 2021 16:23:01 +0800 Subject: [PATCH 1703/2500] cmd/link: add -asan option The -asan option causes the linker to link against the runtime/asan package in order to use the C/C++ address sanitizer. This CL passes tests but is not usable by itself. The actual runtime/asan package, and support for -asan in the go tool and the compiler, and tests, are in separate CLs. Updates #44853. Change-Id: Ifc6046c1f75ba52777cbb3d937a4b66e91d5798d Reviewed-on: https://go-review.googlesource.com/c/go/+/298610 Trust: fannie zhang Reviewed-by: Ian Lance Taylor --- src/cmd/link/doc.go | 2 ++ src/cmd/link/internal/ld/config.go | 4 ++++ src/cmd/link/internal/ld/lib.go | 7 +++++++ src/cmd/link/internal/ld/main.go | 1 + 4 files changed, 14 insertions(+) diff --git a/src/cmd/link/doc.go b/src/cmd/link/doc.go index 604675caec..98c954f0f1 100644 --- a/src/cmd/link/doc.go +++ b/src/cmd/link/doc.go @@ -45,6 +45,8 @@ Flags: Note that before Go 1.5 this option took two separate arguments. -a Disassemble output. + -asan + Link with C/C++ address sanitizer support. -buildid id Record id as Go toolchain build id. -buildmode mode diff --git a/src/cmd/link/internal/ld/config.go b/src/cmd/link/internal/ld/config.go index 4045c97dd7..72616ff62f 100644 --- a/src/cmd/link/internal/ld/config.go +++ b/src/cmd/link/internal/ld/config.go @@ -193,6 +193,10 @@ func mustLinkExternal(ctxt *Link) (res bool, reason string) { return true, "msan" } + if *flagAsan { + return true, "asan" + } + // Internally linking cgo is incomplete on some architectures. // https://golang.org/issue/14449 if iscgo && ctxt.Arch.InFamily(sys.MIPS64, sys.MIPS, sys.RISCV64) { diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 3221d60f80..01ab6474b8 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -385,6 +385,9 @@ func libinit(ctxt *Link) { } else if *flagMsan { suffixsep = "_" suffix = "msan" + } else if *flagAsan { + suffixsep = "_" + suffix = "asan" } Lflag(ctxt, filepath.Join(buildcfg.GOROOT, "pkg", fmt.Sprintf("%s_%s%s%s", buildcfg.GOOS, buildcfg.GOARCH, suffixsep, suffix))) @@ -529,6 +532,9 @@ func (ctxt *Link) loadlib() { if *flagMsan { loadinternal(ctxt, "runtime/msan") } + if *flagAsan { + loadinternal(ctxt, "runtime/asan") + } loadinternal(ctxt, "runtime") for ; i < len(ctxt.Library); i++ { lib := ctxt.Library[i] @@ -1015,6 +1021,7 @@ var internalpkg = []string{ "runtime/cgo", "runtime/race", "runtime/msan", + "runtime/asan", } func ldhostobj(ld func(*Link, *bio.Reader, string, int64, string), headType objabi.HeadType, f *bio.Reader, pkg string, length int64, pn string, file string) *Hostobj { diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go index 4d3b8b904c..a5a5a71250 100644 --- a/src/cmd/link/internal/ld/main.go +++ b/src/cmd/link/internal/ld/main.go @@ -69,6 +69,7 @@ var ( flagDumpDep = flag.Bool("dumpdep", false, "dump symbol dependency graph") flagRace = flag.Bool("race", false, "enable race detector") flagMsan = flag.Bool("msan", false, "enable MSan interface") + flagAsan = flag.Bool("asan", false, "enable ASan interface") flagAslr = flag.Bool("aslr", true, "enable ASLR for buildmode=c-shared on windows") flagFieldTrack = flag.String("k", "", "set field tracking `symbol`") -- GitLab From 6c200017bf0ad9987453d5c265e5a3063ad72dc5 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Mon, 18 Oct 2021 23:54:02 +0700 Subject: [PATCH 1704/2500] doc: document new reflect.UnsafePointer function Updates #40592 Change-Id: If66629e47ca9859128ee3ad8fb584e022d7a6982 Reviewed-on: https://go-review.googlesource.com/c/go/+/356255 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le Reviewed-by: Keith Randall TryBot-Result: Go Bot --- doc/go1.18.html | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/go1.18.html b/doc/go1.18.html index d95e55e1ad..087a06c280 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -175,6 +175,16 @@ Do not send CLs removing the interior tags from such phrases. do fewer allocations.

+
+

+ The new + Value.UnsafePointer + method returns the Value's value as an unsafe.Pointer. + This allows callers to migrate from Value.UnsafeAddr + and Value.Pointer + to eliminate the need to perform uintptr to unsafe.Pointer conversions at the callsite (as unsafe.Pointer rules require). +

+
syscall
-- GitLab From 85d2751d2ea38b10127df0b27d04b1a26f54bcfa Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Fri, 22 Oct 2021 17:05:35 +0700 Subject: [PATCH 1705/2500] cmd/compile: prevent compiling closures more than once Since CL 282892, functions are always compiled before closures. To do that, when walking the closure, it is added to its outer function queue for scheduling compilation later. Thus, a closure may be added to queue more than once, causing the ICE dues to being compiled twice. To fix this, catching the re-walking of the closure expression and do not add it to the compilation queue. Fixes #49029 Change-Id: I7d188e8f5b4d5c4248a0d8e6389da26f1084e464 Reviewed-on: https://go-review.googlesource.com/c/go/+/357960 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/walk/closure.go | 11 ++++++++++- test/fixedbugs/issue49029.go | 25 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 test/fixedbugs/issue49029.go diff --git a/src/cmd/compile/internal/walk/closure.go b/src/cmd/compile/internal/walk/closure.go index 40535afa7a..4d1c5621fe 100644 --- a/src/cmd/compile/internal/walk/closure.go +++ b/src/cmd/compile/internal/walk/closure.go @@ -107,7 +107,16 @@ func walkClosure(clo *ir.ClosureExpr, init *ir.Nodes) ir.Node { // The closure is not trivial or directly called, so it's going to stay a closure. ir.ClosureDebugRuntimeCheck(clo) clofn.SetNeedctxt(true) - ir.CurFunc.Closures = append(ir.CurFunc.Closures, clofn) + + // The closure expression may be walked more than once if it appeared in composite + // literal initialization (e.g, see issue #49029). + // + // Don't add the closure function to compilation queue more than once, since when + // compiling a function twice would lead to an ICE. + if !clofn.Walked() { + clofn.SetWalked(true) + ir.CurFunc.Closures = append(ir.CurFunc.Closures, clofn) + } typ := typecheck.ClosureType(clo) diff --git a/test/fixedbugs/issue49029.go b/test/fixedbugs/issue49029.go new file mode 100644 index 0000000000..51c9a78cfc --- /dev/null +++ b/test/fixedbugs/issue49029.go @@ -0,0 +1,25 @@ +// compile + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type s struct { + f func() +} + +func f() { + ch := make(chan struct{}, 1) + _ = [...]struct{ slice []s }{ + {}, {}, {}, {}, + { + slice: []s{ + { + f: func() { ch <- struct{}{} }, + }, + }, + }, + } +} -- GitLab From b0f7eb6c0dee68c91d622cc5fcba1074626753b3 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 22 Oct 2021 16:57:58 -0700 Subject: [PATCH 1706/2500] cmd/go: update test script for reformatted error message (fix long builds) TBR=iant Change-Id: Ic72af52e5ff8d28f8102c07b03e4930df61445ca Reviewed-on: https://go-review.googlesource.com/c/go/+/358115 Trust: Robert Griesemer Trust: Cuong Manh Le Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le Reviewed-by: Robert Findley --- src/cmd/go/testdata/script/mod_vendor_goversion.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/go/testdata/script/mod_vendor_goversion.txt b/src/cmd/go/testdata/script/mod_vendor_goversion.txt index 7f1966c8e8..b4489dae7e 100644 --- a/src/cmd/go/testdata/script/mod_vendor_goversion.txt +++ b/src/cmd/go/testdata/script/mod_vendor_goversion.txt @@ -26,7 +26,7 @@ go mod vendor ! grep 1.17 vendor/modules.txt ! go build example.net/need117 -stderr '^vendor[/\\]example\.net[/\\]need117[/\\]need117.go:5:1[89]: .*conversion of slices to array pointers only supported as of -lang=go1\.17' +stderr '^vendor[/\\]example\.net[/\\]need117[/\\]need117.go:5:1[89]:.*\n\tconversion of slices to array pointers only supported as of -lang=go1\.17' ! grep 1.13 vendor/modules.txt go build example.net/bad114 -- GitLab From 3cd28baffd2c97d53cbc703a8787365e68050466 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 20 Oct 2021 15:06:35 -0700 Subject: [PATCH 1707/2500] cmd/compile/internal/types2: factor out slice elem computation for copy built-in Implement singleUnder[String] which determines a single underlying type for a given type: either the underlying type, or the single underlying type for a type parameter, if it exists. Use singleUnder[String] instead of optype for copy built-in. This CL removes a dependency on optype and also makes the copy built-in slighty more general for generic arguments (the source argument may be constrained by a slice or string simultaneously). Change-Id: Ia329e96afc69a09d2ca3b1f82fe712d4f7ba1d9f Reviewed-on: https://go-review.googlesource.com/c/go/+/357413 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/builtins.go | 59 ++++++++++++++----- .../types2/testdata/check/builtins.go2 | 10 +++- 2 files changed, 52 insertions(+), 17 deletions(-) diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index cb4d93c6c4..154395cddb 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -325,33 +325,22 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( case _Copy: // copy(x, y []T) int - var dst Type - if t := asSlice(x.typ); t != nil { - dst = t.elem - } + dst, _ := singleUnder(x.typ).(*Slice) var y operand arg(&y, 1) if y.mode == invalid { return } - var src Type - switch t := optype(y.typ).(type) { - case *Basic: - if isString(y.typ) { - src = universeByte - } - case *Slice: - src = t.elem - } + src, _ := singleUnderString(y.typ).(*Slice) if dst == nil || src == nil { check.errorf(x, invalidArg+"copy expects slice arguments; found %s and %s", x, &y) return } - if !Identical(dst, src) { - check.errorf(x, invalidArg+"arguments to copy %s and %s have different element types %s and %s", x, &y, dst, src) + if !Identical(dst.elem, src.elem) { + check.errorf(x, invalidArg+"arguments to copy %s and %s have different element types %s and %s", x, &y, dst.elem, src.elem) return } @@ -774,6 +763,46 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( return true } +// If typ is a type parameter, single under returns the single underlying +// type of all types in the corresponding type constraint if it exists, or +// nil if it doesn't exist. If typ is not a type parameter, singleUnder +// just returns the underlying type. +func singleUnder(typ Type) Type { + var su Type + if underIs(typ, func(u Type) bool { + if su != nil && !Identical(su, u) { + return false + } + // su == nil || Identical(su, u) + su = u + return true + }) { + return su + } + return nil +} + +// singleUnderString is like singleUnder but also considers []byte and +// string as "identical". In this case, if successful, the result is always +// []byte. +func singleUnderString(typ Type) Type { + var su Type + if underIs(typ, func(u Type) bool { + if isString(u) { + u = NewSlice(universeByte) + } + if su != nil && !Identical(su, u) { + return false + } + // su == nil || Identical(su, u) + su = u + return true + }) { + return su + } + return nil +} + // hasVarSize reports if the size of type t is variable due to type parameters. func hasVarSize(t Type) bool { switch t := under(t).(type) { diff --git a/src/cmd/compile/internal/types2/testdata/check/builtins.go2 b/src/cmd/compile/internal/types2/testdata/check/builtins.go2 index 243e888ff7..8376440439 100644 --- a/src/cmd/compile/internal/types2/testdata/check/builtins.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/builtins.go2 @@ -78,8 +78,14 @@ func _[T ~string](x []byte, y T) { func _[T ~[]byte|~string](x T, y []byte) { copy(x /* ERROR expects slice arguments */ , y) - // TODO(gri) should this be valid? - copy(y /* ERROR expects slice arguments */ , x) + copy(y, x) +} + +type L0 []int +type L1 []int + +func _[T L0 | L1](x, y T) { + copy(x, y) } // delete -- GitLab From 2d205ebb96460b500480d144b99d2d5f5d4c06ed Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 21 Oct 2021 13:29:00 -0700 Subject: [PATCH 1708/2500] cmd/compile/internal/types2: make built-in to accept type sets with single underlying types This generalizes make the same way copy was generalized and eliminates a use of optype. Change-Id: I8221abd53d77dde8ead47c0075c13fd2a3221642 Reviewed-on: https://go-review.googlesource.com/c/go/+/357776 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/builtins.go | 6 ++--- .../types2/testdata/check/builtins.go2 | 22 +++++++++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 154395cddb..37e1f00d26 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -460,13 +460,13 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( } var min int // minimum number of arguments - switch optype(T).(type) { + switch singleUnder(T).(type) { case *Slice: min = 2 case *Map, *Chan: min = 1 - case *top: - check.errorf(arg0, invalidArg+"cannot make %s; type parameter has no structural type", arg0) + case nil: + check.errorf(arg0, invalidArg+"cannot make %s; type set has no single underlying type", arg0) return default: check.errorf(arg0, invalidArg+"cannot make %s; type must be slice, map, or channel", arg0) diff --git a/src/cmd/compile/internal/types2/testdata/check/builtins.go2 b/src/cmd/compile/internal/types2/testdata/check/builtins.go2 index 8376440439..d1067a190f 100644 --- a/src/cmd/compile/internal/types2/testdata/check/builtins.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/builtins.go2 @@ -127,15 +127,18 @@ func _[T M4[K, V], K comparable, V any](m T) { // make +type myChan chan int + func _[ - S1 interface{ []int }, - S2 interface{ []int | chan int }, + S1 ~[]int, + S2 ~[]int | ~chan int, - M1 interface{ map[string]int }, - M2 interface{ map[string]int | chan int }, + M1 ~map[string]int, + M2 ~map[string]int | ~chan int, - C1 interface{ chan int }, - C2 interface{ chan int | chan string }, + C1 ~chan int, + C2 ~chan int | ~chan string, + C3 chan int | myChan, // single underlying type ]() { type S0 []int _ = make([]int, 10) @@ -145,7 +148,7 @@ func _[ _ = make /* ERROR expects 2 or 3 arguments */ (S1) _ = make(S1, 10, 20) _ = make /* ERROR expects 2 or 3 arguments */ (S1, 10, 20, 30) - _ = make(S2 /* ERROR cannot make .* no structural type */ , 10) + _ = make(S2 /* ERROR cannot make .* no single underlying type */ , 10) type M0 map[string]int _ = make(map[string]int) @@ -153,7 +156,7 @@ func _[ _ = make(M1) _ = make(M1, 10) _ = make/* ERROR expects 1 or 2 arguments */(M1, 10, 20) - _ = make(M2 /* ERROR cannot make .* no structural type */ ) + _ = make(M2 /* ERROR cannot make .* no single underlying type */ ) type C0 chan int _ = make(chan int) @@ -161,7 +164,8 @@ func _[ _ = make(C1) _ = make(C1, 10) _ = make/* ERROR expects 1 or 2 arguments */(C1, 10, 20) - _ = make(C2 /* ERROR cannot make .* no structural type */ ) + _ = make(C2 /* ERROR cannot make .* no single underlying type */ ) + _ = make(C3) } // unsafe.Alignof -- GitLab From c526cf8c1ea535de6a30fc8c553c377bda4d6781 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 21 Oct 2021 15:56:08 -0700 Subject: [PATCH 1709/2500] cmd/compile/internal/types2: range clause to accept type sets with single underlying types This generalizes range clauses. Removed some dead code and cleaned up the surrounding bits. Change-Id: Icd8384205afa3f52b7e7df9abed5de2bb556861d Reviewed-on: https://go-review.googlesource.com/c/go/+/357778 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/stmt.go | 70 ++++++++----------- .../types2/testdata/check/typeparams.go2 | 12 ++-- 2 files changed, 35 insertions(+), 47 deletions(-) diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index e826f35105..10741a90e2 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -834,19 +834,28 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s // determine key/value types var key, val Type if x.mode != invalid { - // Ranging over a type parameter is permitted if it has a structural type. - typ := optype(x.typ) - if _, ok := typ.(*Chan); ok && sValue != nil { - check.softErrorf(sValue, "range over %s permits only one iteration variable", &x) - // ok to continue + // Ranging over a type parameter is permitted if it has a single underlying type. + var cause string + u := singleUnder(x.typ) + switch t := u.(type) { + case nil: + cause = "type set has no single underlying type" + case *Chan: + if sValue != nil { + check.softErrorf(sValue, "range over %s permits only one iteration variable", &x) + // ok to continue + } + if t.dir == SendOnly { + cause = "receive from send-only channel" + } } - var msg string - key, val, msg = rangeKeyVal(typ, isVarName(sKey), isVarName(sValue)) - if key == nil || msg != "" { - if msg != "" { - msg = ": " + msg + key, val = rangeKeyVal(u) + if key == nil || cause != "" { + if cause == "" { + check.softErrorf(&x, "cannot range over %s", &x) + } else { + check.softErrorf(&x, "cannot range over %s (%s)", &x, cause) } - check.softErrorf(&x, "cannot range over %s%s", &x, msg) // ok to continue } } @@ -927,44 +936,23 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s check.stmt(inner, s.Body) } -// isVarName reports whether x is a non-nil, non-blank (_) expression. -func isVarName(x syntax.Expr) bool { - if x == nil { - return false - } - ident, _ := unparen(x).(*syntax.Name) - return ident == nil || ident.Value != "_" -} - // rangeKeyVal returns the key and value type produced by a range clause -// over an expression of type typ, and possibly an error message. If the -// range clause is not permitted the returned key is nil or msg is not -// empty (in that case we still may have a non-nil key type which can be -// used to reduce the chance for follow-on errors). -// The wantKey, wantVal, and hasVal flags indicate which of the iteration -// variables are used or present; this matters if we range over a generic -// type where not all keys or values are of the same type. -func rangeKeyVal(typ Type, wantKey, wantVal bool) (Type, Type, string) { +// over an expression of type typ. If the range clause is not permitted +// the results are nil. +func rangeKeyVal(typ Type) (key, val Type) { switch typ := arrayPtrDeref(typ).(type) { case *Basic: if isString(typ) { - return Typ[Int], universeRune, "" // use 'rune' name + return Typ[Int], universeRune // use 'rune' name } case *Array: - return Typ[Int], typ.elem, "" + return Typ[Int], typ.elem case *Slice: - return Typ[Int], typ.elem, "" + return Typ[Int], typ.elem case *Map: - return typ.key, typ.elem, "" + return typ.key, typ.elem case *Chan: - var msg string - if typ.dir == SendOnly { - msg = "receive from send-only channel" - } - return typ.elem, Typ[Invalid], msg - case *top: - // we have a type parameter with no structural type - return nil, nil, "no structural type" + return typ.elem, Typ[Invalid] } - return nil, nil, "" + return } diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 index 29c25b0bb4..d1f07a20d4 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 @@ -184,7 +184,7 @@ func _[ for _, _ = range b1 {} var b2 B2 - for range b2 /* ERROR cannot range over b2 .* no structural type */ {} + for range b2 {} var c0 chan int for range c0 {} @@ -197,7 +197,7 @@ func _[ for _, _ /* ERROR permits only one iteration variable */ = range c1 {} var c2 C2 - for range c2 /* ERROR cannot range over c2 .* no structural type */ {} + for range c2 /* ERROR cannot range over c2.*no single underlying type */ {} var c3 C3 for range c3 /* ERROR receive from send-only channel */ {} @@ -213,7 +213,7 @@ func _[ for _, _ = range s1 {} var s2 S2 - for range s2 /* ERROR cannot range over s2 .* no structural type */ {} + for range s2 /* ERROR cannot range over s2.*no single underlying type */ {} var a0 []int for range a0 {} @@ -226,7 +226,7 @@ func _[ for _, _ = range a1 {} var a2 A2 - for range a2 /* ERROR cannot range over a2 .* no structural type */ {} + for range a2 /* ERROR cannot range over a2.*no single underlying type */ {} var p0 *[10]int for range p0 {} @@ -239,7 +239,7 @@ func _[ for _, _ = range p1 {} var p2 P2 - for range p2 /* ERROR cannot range over p2 .* no structural type */ {} + for range p2 /* ERROR cannot range over p2.*no single underlying type */ {} var m0 map[string]int for range m0 {} @@ -252,7 +252,7 @@ func _[ for _, _ = range m1 {} var m2 M2 - for range m2 /* ERROR cannot range over m2 .* no structural type */ {} + for range m2 /* ERROR cannot range over m2.*no single underlying type */ {} } // type inference checks -- GitLab From 12e4404a0a0f03cee4fd29a6eb80379824d4aeb6 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 21 Oct 2021 16:17:07 -0700 Subject: [PATCH 1710/2500] cmd/compile/internal/types2: slice exprs to accept type sets with single underlying types Change-Id: Ib9bd08ab6153129aaf8b77b41fc6ea302d0c1589 Reviewed-on: https://go-review.googlesource.com/c/go/+/357779 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/index.go | 21 ++++++++++++------- .../types2/testdata/check/typeparams.go2 | 5 +++++ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index 47a5e50f62..62f49b95da 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -207,9 +207,14 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { valid := false length := int64(-1) // valid if >= 0 - switch typ := optype(x.typ).(type) { + switch u := singleUnder(x.typ).(type) { + case nil: + check.errorf(x, invalidOp+"cannot slice %s: type set has no single underlying type", x) + x.mode = invalid + return + case *Basic: - if isString(typ) { + if isString(u) { if e.Full { check.error(x, invalidOp+"3-index slice of string") x.mode = invalid @@ -221,26 +226,26 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { } // spec: "For untyped string operands the result // is a non-constant value of type string." - if typ.kind == UntypedString { + if u.kind == UntypedString { x.typ = Typ[String] } } case *Array: valid = true - length = typ.len + length = u.len if x.mode != variable { check.errorf(x, invalidOp+"%s (slice of unaddressable value)", x) x.mode = invalid return } - x.typ = &Slice{elem: typ.elem} + x.typ = &Slice{elem: u.elem} case *Pointer: - if typ := asArray(typ.base); typ != nil { + if u := asArray(u.base); u != nil { valid = true - length = typ.len - x.typ = &Slice{elem: typ.elem} + length = u.len + x.typ = &Slice{elem: u.elem} } case *Slice: diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 index d1f07a20d4..1200a6e874 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 @@ -123,6 +123,11 @@ func _[T interface{ ~[]byte }] (x T, i, j, k int) { var _ T = x[i:j:k] } func _[T interface{ ~string }] (x T, i, j, k int) { var _ T = x[i:j] } func _[T interface{ ~string }] (x T, i, j, k int) { var _ T = x /* ERROR 3-index slice of string */ [i:j:k] } +type myByte1 []byte +type myByte2 []byte +func _[T interface{ []byte | myByte1 | myByte2 }] (x T, i, j, k int) { var _ T = x[i:j:k] } +func _[T interface{ []byte | myByte1 | []int }] (x T, i, j, k int) { var _ T = x[ /* ERROR no single underlying type */ i:j:k] } + // len/cap built-ins func _[T any](x T) { _ = len(x /* ERROR invalid argument */ ) } -- GitLab From 16318df4a225928c2f24874f6fcd11c3e13a112e Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 21 Oct 2021 20:01:51 -0700 Subject: [PATCH 1711/2500] cmd/compile/internal/types2: comp literals to accept type sets with single underlying types Change-Id: Ib51bcdf023910d244739ec176880a16e700851e7 Reviewed-on: https://go-review.googlesource.com/c/go/+/357915 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/expr.go | 2 +- .../types2/testdata/check/compliterals.go2 | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/cmd/compile/internal/types2/testdata/check/compliterals.go2 diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 1001554739..3a39de7406 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -1253,7 +1253,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin goto Error } - switch utyp := optype(base).(type) { + switch utyp := singleUnder(base).(type) { case *Struct: if len(e.ElemList) == 0 { break diff --git a/src/cmd/compile/internal/types2/testdata/check/compliterals.go2 b/src/cmd/compile/internal/types2/testdata/check/compliterals.go2 new file mode 100644 index 0000000000..60eac97a3f --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/check/compliterals.go2 @@ -0,0 +1,22 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Composite literals with parameterized types + +package comp_literals + +type myStruct struct { + f int +} + +type slice[E any] []E + +func struct_literals[S struct{f int}|myStruct]() { + _ = S{} + _ = S{0} + _ = S{f: 0} + + _ = slice[int]{1, 2, 3} + _ = slice[S]{{}, {0}, {f:0}} +} -- GitLab From 8dbf3e9393400d72d313e5616c88873e07692c70 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Sat, 23 Oct 2021 10:16:41 -0700 Subject: [PATCH 1712/2500] cmd/compile: fix fuse pass to do CFG surgery correctly removePred and removeArg do different things. removePred moves the last predecessor to index k, whereas removeArg slides all the args k or greater down by 1 index. Kind of unfortunate different behavior in things named similarly. Fixes #49122 Change-Id: I9ae409bdac744e713f4c121f948e43db6fdc8542 Reviewed-on: https://go-review.googlesource.com/c/go/+/358117 Trust: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- .../compile/internal/ssa/fuse_branchredirect.go | 6 +++++- test/fixedbugs/issue49122.go | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 test/fixedbugs/issue49122.go diff --git a/src/cmd/compile/internal/ssa/fuse_branchredirect.go b/src/cmd/compile/internal/ssa/fuse_branchredirect.go index 1b8b307bca..ba5220bd87 100644 --- a/src/cmd/compile/internal/ssa/fuse_branchredirect.go +++ b/src/cmd/compile/internal/ssa/fuse_branchredirect.go @@ -78,7 +78,11 @@ func fuseBranchRedirect(f *Func) bool { if v.Op != OpPhi { continue } - v.RemoveArg(k) + n := len(v.Args) + v.Args[k].Uses-- + v.Args[k] = v.Args[n-1] + v.Args[n-1] = nil + v.Args = v.Args[:n-1] phielimValue(v) } // Fix up child to have one more predecessor. diff --git a/test/fixedbugs/issue49122.go b/test/fixedbugs/issue49122.go new file mode 100644 index 0000000000..c62a627dae --- /dev/null +++ b/test/fixedbugs/issue49122.go @@ -0,0 +1,16 @@ +// compile + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +var B []bool +var N int + +func f(p bool, m map[bool]bool) bool { + var q bool + _ = p || N&N < N || B[0] || B[0] + return p && q && m[q] +} -- GitLab From f686f6a963cdfa66b6087993663f53a10272d262 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Mon, 25 Oct 2021 01:02:12 +0700 Subject: [PATCH 1713/2500] cmd/compile: remove Value.RemoveArg It's only used in two places: - The one in regalloc.go can be replaced with v.resetArgs() - The one in rewrite.go can be open coded and can cause wrong usage like the bug that CL 358117 fixed. Change-Id: I125baf237db159d056fe4b1c73072331eea4d06a Reviewed-on: https://go-review.googlesource.com/c/go/+/357965 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/ssa/regalloc.go | 2 +- src/cmd/compile/internal/ssa/rewrite.go | 6 +++++- src/cmd/compile/internal/ssa/value.go | 6 ------ 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index 28fac6ccd0..431059ae69 100644 --- a/src/cmd/compile/internal/ssa/regalloc.go +++ b/src/cmd/compile/internal/ssa/regalloc.go @@ -1840,7 +1840,7 @@ func (s *regAllocState) regalloc(f *Func) { if s.f.pass.debug > regDebug { fmt.Printf("delete copied value %s\n", c.LongString()) } - c.RemoveArg(0) + c.resetArgs() f.freeValue(c) delete(s.copies, c) progress = true diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index 2fe0ca64c8..9136c59e65 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -816,7 +816,11 @@ func devirtLECall(v *Value, sym *obj.LSym) *Value { v.Op = OpStaticLECall auxcall := v.Aux.(*AuxCall) auxcall.Fn = sym - v.RemoveArg(0) + // Remove first arg + v.Args[0].Uses-- + copy(v.Args[0:], v.Args[1:]) + v.Args[len(v.Args)-1] = nil // aid GC + v.Args = v.Args[:len(v.Args)-1] return v } diff --git a/src/cmd/compile/internal/ssa/value.go b/src/cmd/compile/internal/ssa/value.go index 630143cc50..7b411a4612 100644 --- a/src/cmd/compile/internal/ssa/value.go +++ b/src/cmd/compile/internal/ssa/value.go @@ -302,12 +302,6 @@ func (v *Value) SetArg(i int, w *Value) { v.Args[i] = w w.Uses++ } -func (v *Value) RemoveArg(i int) { - v.Args[i].Uses-- - copy(v.Args[i:], v.Args[i+1:]) - v.Args[len(v.Args)-1] = nil // aid GC - v.Args = v.Args[:len(v.Args)-1] -} func (v *Value) SetArgs1(a *Value) { v.resetArgs() v.AddArg(a) -- GitLab From 7b554575e46d1df9b68f71e051c8133aaf953fb7 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sun, 24 Oct 2021 13:46:54 +0700 Subject: [PATCH 1714/2500] cmd/compile: factor out code to remove phi argument CL 358117 fixed a bug that Phi's argument wasn't updated correctly after removing a predecessor of Block. This CL factor out the code that updates phi argument into a Block's method, so it's easier to use, maintain and hopefully prevent that kind of bug in the future. Change-Id: Ie9741e19ea28f56860425089b6093a381aa10f5b Reviewed-on: https://go-review.googlesource.com/c/go/+/357964 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/ssa/block.go | 25 ++++++++++++++++++- src/cmd/compile/internal/ssa/critical.go | 11 ++++---- src/cmd/compile/internal/ssa/deadcode.go | 6 +---- .../internal/ssa/fuse_branchredirect.go | 6 +---- src/cmd/compile/internal/ssa/shortcircuit.go | 6 +---- 5 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/cmd/compile/internal/ssa/block.go b/src/cmd/compile/internal/ssa/block.go index 71ca774431..6ff3188f9b 100644 --- a/src/cmd/compile/internal/ssa/block.go +++ b/src/cmd/compile/internal/ssa/block.go @@ -279,7 +279,8 @@ func (b *Block) AddEdgeTo(c *Block) { // removePred removes the ith input edge from b. // It is the responsibility of the caller to remove -// the corresponding successor edge. +// the corresponding successor edge, and adjust any +// phi values by calling b.removePhiArg(v, i). func (b *Block) removePred(i int) { n := len(b.Preds) - 1 if i != n { @@ -322,6 +323,28 @@ func (b *Block) swapSuccessors() { b.Likely *= -1 } +// removePhiArg removes the ith arg from phi. +// It must be called after calling b.removePred(i) to +// adjust the corresponding phi value of the block: +// +// b.removePred(i) +// for _, v := range b.Values { +// if v.Op != OpPhi { +// continue +// } +// b.removeArg(v, i) +// } +func (b *Block) removePhiArg(phi *Value, i int) { + n := len(b.Preds) + if numPhiArgs := len(phi.Args); numPhiArgs-1 != n { + b.Fatalf("inconsistent state, num predecessors: %d, num phi args: %d", n, numPhiArgs) + } + phi.Args[i].Uses-- + phi.Args[i] = phi.Args[n] + phi.Args[n] = nil + phi.Args = phi.Args[:n] +} + // LackingPos indicates whether b is a block whose position should be inherited // from its successors. This is true if all the values within it have unreliable positions // and if it is "plain", meaning that there is no control flow that is also very likely diff --git a/src/cmd/compile/internal/ssa/critical.go b/src/cmd/compile/internal/ssa/critical.go index b85721eba4..500ce3ae61 100644 --- a/src/cmd/compile/internal/ssa/critical.go +++ b/src/cmd/compile/internal/ssa/critical.go @@ -91,14 +91,13 @@ func critical(f *Func) { b.removePred(i) // Update corresponding phi args - n := len(b.Preds) - phi.Args[i].Uses-- - phi.Args[i] = phi.Args[n] - phi.Args[n] = nil - phi.Args = phi.Args[:n] + b.removePhiArg(phi, i) + // splitting occasionally leads to a phi having // a single argument (occurs with -N) - if n == 1 { + // TODO(cuonglm,khr): replace this with phielimValue, and + // make removePhiArg incorporates that. + if len(b.Preds) == 1 { phi.Op = OpCopy } // Don't increment i in this case because we moved diff --git a/src/cmd/compile/internal/ssa/deadcode.go b/src/cmd/compile/internal/ssa/deadcode.go index 5d10dfe025..b47b106975 100644 --- a/src/cmd/compile/internal/ssa/deadcode.go +++ b/src/cmd/compile/internal/ssa/deadcode.go @@ -348,15 +348,11 @@ func (b *Block) removeEdge(i int) { c.removePred(j) // Remove phi args from c's phis. - n := len(c.Preds) for _, v := range c.Values { if v.Op != OpPhi { continue } - v.Args[j].Uses-- - v.Args[j] = v.Args[n] - v.Args[n] = nil - v.Args = v.Args[:n] + c.removePhiArg(v, j) phielimValue(v) // Note: this is trickier than it looks. Replacing // a Phi with a Copy can in general cause problems because diff --git a/src/cmd/compile/internal/ssa/fuse_branchredirect.go b/src/cmd/compile/internal/ssa/fuse_branchredirect.go index ba5220bd87..751dca7468 100644 --- a/src/cmd/compile/internal/ssa/fuse_branchredirect.go +++ b/src/cmd/compile/internal/ssa/fuse_branchredirect.go @@ -78,11 +78,7 @@ func fuseBranchRedirect(f *Func) bool { if v.Op != OpPhi { continue } - n := len(v.Args) - v.Args[k].Uses-- - v.Args[k] = v.Args[n-1] - v.Args[n-1] = nil - v.Args = v.Args[:n-1] + b.removePhiArg(v, k) phielimValue(v) } // Fix up child to have one more predecessor. diff --git a/src/cmd/compile/internal/ssa/shortcircuit.go b/src/cmd/compile/internal/ssa/shortcircuit.go index 29abf3c591..c0b9eacf41 100644 --- a/src/cmd/compile/internal/ssa/shortcircuit.go +++ b/src/cmd/compile/internal/ssa/shortcircuit.go @@ -196,11 +196,7 @@ func shortcircuitBlock(b *Block) bool { // Remove b's incoming edge from p. b.removePred(cidx) - n := len(b.Preds) - ctl.Args[cidx].Uses-- - ctl.Args[cidx] = ctl.Args[n] - ctl.Args[n] = nil - ctl.Args = ctl.Args[:n] + b.removePhiArg(ctl, cidx) // Redirect p's outgoing edge to t. p.Succs[pi] = Edge{t, len(t.Preds)} -- GitLab From fcd2d9cd75e6307b5b72fed2201044e231bef40a Mon Sep 17 00:00:00 2001 From: Olivier Wulveryck Date: Mon, 31 May 2021 08:03:57 +0200 Subject: [PATCH 1715/2500] image/draw: improve performances if mask is *image.Alpha MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The existing DrawMask method is generic and is therefore calling the At().RGBA() method for every pixel of the mask and the source. Do a specific implementation when the mask is *image.Alpha (which is common) and use use the PixOffset method to increase performances. name old time/op new time/op delta RGBA2-12 1.60ms ± 0% 1.13ms ± 1% -29.16% (p=0.008 n=5+5) GenericMaskOver-12 915µs ± 4% 926µs ± 1% ~ (p=0.190 n=5+4) RGBA64Over-12 1.53ms ± 3% 1.21ms ± 2% -20.74% (p=0.008 n=5+5) GrayOver-12 1.36ms ± 2% 1.01ms ± 7% -26.27% (p=0.008 n=5+5) Fixes: #46395 Change-Id: Iaeaa8cfcc6a3fe93eb19b361f3bf076e41cac5b6 Reviewed-on: https://go-review.googlesource.com/c/go/+/323749 Reviewed-by: Nigel Tao Trust: Nigel Tao Trust: Andrew Gerrand Run-TryBot: Nigel Tao --- src/image/draw/bench_test.go | 8 ++ src/image/draw/draw.go | 159 +++++++++++++++++++++++++++++++++++ src/image/draw/draw_test.go | 4 + 3 files changed, 171 insertions(+) diff --git a/src/image/draw/bench_test.go b/src/image/draw/bench_test.go index 524ead2b8e..2b7c6d6ac4 100644 --- a/src/image/draw/bench_test.go +++ b/src/image/draw/bench_test.go @@ -266,3 +266,11 @@ func BenchmarkGenericSrc(b *testing.B) { func BenchmarkGenericMaskSrc(b *testing.B) { bench(b, color.RGBA64Model, color.RGBA64Model, color.AlphaModel, Src) } + +func BenchmarkRGBA64Over(b *testing.B) { + bench(b, color.RGBAModel, color.RGBA64Model, color.AlphaModel, Over) +} + +func BenchmarkGrayOver(b *testing.B) { + bench(b, color.RGBAModel, color.GrayModel, color.AlphaModel, Over) +} diff --git a/src/image/draw/draw.go b/src/image/draw/draw.go index 5e81ddc395..d3c5b29097 100644 --- a/src/image/draw/draw.go +++ b/src/image/draw/draw.go @@ -160,6 +160,15 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas case *image.Uniform: drawGlyphOver(dst0, r, src0, mask0, mp) return + case *image.RGBA: + drawRGBAMaskOver(dst0, r, src0, sp, mask0, mp) + return + case *image.Gray: + drawGrayMaskOver(dst0, r, src0, sp, mask0, mp) + return + case image.RGBA64Image: + drawRGBA64ImageMaskOver(dst0, r, src0, sp, mask0, mp) + return } } } else { @@ -602,6 +611,156 @@ func drawGlyphOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform, mask } } +func drawGrayMaskOver(dst *image.RGBA, r image.Rectangle, src *image.Gray, sp image.Point, mask *image.Alpha, mp image.Point) { + x0, x1, dx := r.Min.X, r.Max.X, 1 + y0, y1, dy := r.Min.Y, r.Max.Y, 1 + if r.Overlaps(r.Add(sp.Sub(r.Min))) { + if sp.Y < r.Min.Y || sp.Y == r.Min.Y && sp.X < r.Min.X { + x0, x1, dx = x1-1, x0-1, -1 + y0, y1, dy = y1-1, y0-1, -1 + } + } + + sy := sp.Y + y0 - r.Min.Y + my := mp.Y + y0 - r.Min.Y + sx0 := sp.X + x0 - r.Min.X + mx0 := mp.X + x0 - r.Min.X + sx1 := sx0 + (x1 - x0) + i0 := dst.PixOffset(x0, y0) + di := dx * 4 + for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy { + for i, sx, mx := i0, sx0, mx0; sx != sx1; i, sx, mx = i+di, sx+dx, mx+dx { + mi := mask.PixOffset(mx, my) + ma := uint32(mask.Pix[mi]) + ma |= ma << 8 + si := src.PixOffset(sx, sy) + sy := uint32(src.Pix[si]) + sy |= sy << 8 + sa := uint32(0xffff) + + d := dst.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857 + dr := uint32(d[0]) + dg := uint32(d[1]) + db := uint32(d[2]) + da := uint32(d[3]) + + // dr, dg, db and da are all 8-bit color at the moment, ranging in [0,255]. + // We work in 16-bit color, and so would normally do: + // dr |= dr << 8 + // and similarly for dg, db and da, but instead we multiply a + // (which is a 16-bit color, ranging in [0,65535]) by 0x101. + // This yields the same result, but is fewer arithmetic operations. + a := (m - (sa * ma / m)) * 0x101 + + d[0] = uint8((dr*a + sy*ma) / m >> 8) + d[1] = uint8((dg*a + sy*ma) / m >> 8) + d[2] = uint8((db*a + sy*ma) / m >> 8) + d[3] = uint8((da*a + sa*ma) / m >> 8) + } + i0 += dy * dst.Stride + } +} + +func drawRGBAMaskOver(dst *image.RGBA, r image.Rectangle, src *image.RGBA, sp image.Point, mask *image.Alpha, mp image.Point) { + x0, x1, dx := r.Min.X, r.Max.X, 1 + y0, y1, dy := r.Min.Y, r.Max.Y, 1 + if dst == src && r.Overlaps(r.Add(sp.Sub(r.Min))) { + if sp.Y < r.Min.Y || sp.Y == r.Min.Y && sp.X < r.Min.X { + x0, x1, dx = x1-1, x0-1, -1 + y0, y1, dy = y1-1, y0-1, -1 + } + } + + sy := sp.Y + y0 - r.Min.Y + my := mp.Y + y0 - r.Min.Y + sx0 := sp.X + x0 - r.Min.X + mx0 := mp.X + x0 - r.Min.X + sx1 := sx0 + (x1 - x0) + i0 := dst.PixOffset(x0, y0) + di := dx * 4 + for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy { + for i, sx, mx := i0, sx0, mx0; sx != sx1; i, sx, mx = i+di, sx+dx, mx+dx { + mi := mask.PixOffset(mx, my) + ma := uint32(mask.Pix[mi]) + ma |= ma << 8 + si := src.PixOffset(sx, sy) + sr := uint32(src.Pix[si+0]) + sg := uint32(src.Pix[si+1]) + sb := uint32(src.Pix[si+2]) + sa := uint32(src.Pix[si+3]) + sr |= sr << 8 + sg |= sg << 8 + sb |= sb << 8 + sa |= sa << 8 + d := dst.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857 + dr := uint32(d[0]) + dg := uint32(d[1]) + db := uint32(d[2]) + da := uint32(d[3]) + + // dr, dg, db and da are all 8-bit color at the moment, ranging in [0,255]. + // We work in 16-bit color, and so would normally do: + // dr |= dr << 8 + // and similarly for dg, db and da, but instead we multiply a + // (which is a 16-bit color, ranging in [0,65535]) by 0x101. + // This yields the same result, but is fewer arithmetic operations. + a := (m - (sa * ma / m)) * 0x101 + + d[0] = uint8((dr*a + sr*ma) / m >> 8) + d[1] = uint8((dg*a + sg*ma) / m >> 8) + d[2] = uint8((db*a + sb*ma) / m >> 8) + d[3] = uint8((da*a + sa*ma) / m >> 8) + } + i0 += dy * dst.Stride + } +} + +func drawRGBA64ImageMaskOver(dst *image.RGBA, r image.Rectangle, src image.RGBA64Image, sp image.Point, mask *image.Alpha, mp image.Point) { + x0, x1, dx := r.Min.X, r.Max.X, 1 + y0, y1, dy := r.Min.Y, r.Max.Y, 1 + if image.Image(dst) == src && r.Overlaps(r.Add(sp.Sub(r.Min))) { + if sp.Y < r.Min.Y || sp.Y == r.Min.Y && sp.X < r.Min.X { + x0, x1, dx = x1-1, x0-1, -1 + y0, y1, dy = y1-1, y0-1, -1 + } + } + + sy := sp.Y + y0 - r.Min.Y + my := mp.Y + y0 - r.Min.Y + sx0 := sp.X + x0 - r.Min.X + mx0 := mp.X + x0 - r.Min.X + sx1 := sx0 + (x1 - x0) + i0 := dst.PixOffset(x0, y0) + di := dx * 4 + for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy { + for i, sx, mx := i0, sx0, mx0; sx != sx1; i, sx, mx = i+di, sx+dx, mx+dx { + mi := mask.PixOffset(mx, my) + ma := uint32(mask.Pix[mi]) + ma |= ma << 8 + srgba := src.RGBA64At(sx, sy) + d := dst.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857 + dr := uint32(d[0]) + dg := uint32(d[1]) + db := uint32(d[2]) + da := uint32(d[3]) + + // dr, dg, db and da are all 8-bit color at the moment, ranging in [0,255]. + // We work in 16-bit color, and so would normally do: + // dr |= dr << 8 + // and similarly for dg, db and da, but instead we multiply a + // (which is a 16-bit color, ranging in [0,65535]) by 0x101. + // This yields the same result, but is fewer arithmetic operations. + a := (m - (uint32(srgba.A) * ma / m)) * 0x101 + + d[0] = uint8((dr*a + uint32(srgba.R)*ma) / m >> 8) + d[1] = uint8((dg*a + uint32(srgba.G)*ma) / m >> 8) + d[2] = uint8((db*a + uint32(srgba.B)*ma) / m >> 8) + d[3] = uint8((da*a + uint32(srgba.A)*ma) / m >> 8) + } + i0 += dy * dst.Stride + } +} + func drawRGBA(dst *image.RGBA, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op) { x0, x1, dx := r.Min.X, r.Max.X, 1 y0, y1, dy := r.Min.Y, r.Max.Y, 1 diff --git a/src/image/draw/draw_test.go b/src/image/draw/draw_test.go index 8a51409526..75a2896631 100644 --- a/src/image/draw/draw_test.go +++ b/src/image/draw/draw_test.go @@ -397,6 +397,10 @@ var drawTests = []drawTest{ Over, color.RGBA{81, 0, 102, 255}}, {"genericSrcSlowest", fillBlue(255), convertToSlowestRGBA(vgradAlpha(192)), Src, color.RGBA{0, 0, 102, 102}}, + // The source pixel is {0, 48, 0, 90}. + {"rgbaVariableMaskOver", vgradGreen(255), vgradAlpha(192), Over, color.RGBA{81, 54, 0, 255}}, + // The source pixel is {136} in Gray-space, which is {136, 136, 136, 255} in RGBA-space. + {"grayVariableMaskOver", vgradGray(), vgradAlpha(192), Over, color.RGBA{136, 54, 54, 255}}, } func makeGolden(dst image.Image, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op) image.Image { -- GitLab From 1ed060cf87ec887ad76c51e3f7a2148cc2a7bf9b Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 21 Oct 2021 11:11:13 -0400 Subject: [PATCH 1716/2500] testing: reference benchmark format spec This updates the testing package documentation to reference the specification for the benchmark format, and points users to our standard tools for working with benchmark data. (It's somewhat remarkable how widely used benchstat appears to be given that we don't mention it anywhere!) Change-Id: Idbb4416d2fde9606ea7e6c15595f3b9e6a38f3b0 Reviewed-on: https://go-review.googlesource.com/c/go/+/357589 Trust: Austin Clements Reviewed-by: Ian Lance Taylor --- src/testing/testing.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/testing/testing.go b/src/testing/testing.go index d03c0b1cf9..6fb1a71d43 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -75,6 +75,14 @@ // }) // } // +// A detailed specification of the benchmark results format is given +// in https://golang.org/design/14313-benchmark-format. +// +// There are standard tools for working with benchmark results at +// https://golang.org/x/perf/cmd. +// In particular, https://golang.org/x/perf/cmd/benchstat performs +// statistically robust A/B comparisons. +// // Examples // // The package also runs and verifies example code. Example functions may -- GitLab From 89cc528e430c18c6c36b8e8bbfb1bab26ed110e3 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sat, 23 Oct 2021 16:39:32 -0700 Subject: [PATCH 1717/2500] cmd/compile/internal/types2: better error messages for empty type sets - change _TypeSet.hasTerms() to report if a type set has actual types (excluding a "universe" term) - handle empty type set type arguments correctly - bring comments up-to-date in Checker.satisfies Change-Id: I87f9a1096ebb21a1b08c87a9b59f400f3bc2f040 Reviewed-on: https://go-review.googlesource.com/c/go/+/358175 Trust: Robert Griesemer Reviewed-by: Robert Findley --- .../compile/internal/types2/instantiate.go | 32 +++++++++++++------ .../types2/testdata/check/typeinst2.go2 | 28 +++++++++++++--- .../types2/testdata/fixedbugs/issue47411.go2 | 2 +- src/cmd/compile/internal/types2/typeset.go | 2 +- 4 files changed, 48 insertions(+), 16 deletions(-) diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index d6cefb4bfe..8228ef2c31 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -135,8 +135,16 @@ func (check *Checker) verify(pos syntax.Pos, tparams []*TypeParam, targs []Type) // TODO(gri) This should be a method of interfaces or type sets. func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap substMap) error { iface := tpar.iface() + + // Every type argument satisfies interface{}. if iface.Empty() { - return nil // no type bound + return nil + } + + // A type argument that is a type parameter with an empty type set satisfies any constraint. + // (The empty set is a subset of any set.) + if targ := asTypeParam(targ); targ != nil && targ.iface().typeSet().IsEmpty() { + return nil } // TODO(rfindley): it would be great if users could pass in a qualifier here, @@ -150,6 +158,11 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap return errors.New(sprintf(qf, format, args...)) } + // No type argument with non-empty type set satisfies the empty type set. + if iface.typeSet().IsEmpty() { + return errorf("%s does not satisfy %s (constraint type set is empty)", targ, tpar.bound) + } + // The type parameter bound is parameterized with the same type parameters // as the instantiated type; before we can use it for bounds checking we // need to instantiate it with the type arguments with which we instantiate @@ -190,28 +203,27 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap } } - // targ's underlying type must also be one of the interface types listed, if any + // targ must also be in the set of types of iface, if any. + // Constraints with empty type sets were already excluded above. if !iface.typeSet().hasTerms() { return nil // nothing to do } - // If targ is itself a type parameter, each of its possible types, but at least one, must be in the - // list of iface types (i.e., the targ type list must be a non-empty subset of the iface types). + // If targ is itself a type parameter, each of its possible types must be in the set + // of iface types (i.e., the targ type set must be a subset of the iface type set). + // Type arguments with empty type sets were already excluded above. if targ := asTypeParam(targ); targ != nil { targBound := targ.iface() - if !targBound.typeSet().hasTerms() { - return errorf("%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ) - } if !targBound.typeSet().subsetOf(iface.typeSet()) { - // TODO(gri) need better error message + // TODO(gri) report which type is missing return errorf("%s does not satisfy %s", targ, tpar.bound) } return nil } - // Otherwise, targ's type or underlying type must also be one of the interface types listed, if any. + // Otherwise, targ's type must be included in the iface type set. if !iface.typeSet().includes(targ) { - // TODO(gri) better error message + // TODO(gri) report which type is missing return errorf("%s does not satisfy %s", targ, tpar.bound) } diff --git a/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 b/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 index ecf4b0f714..783ff346c9 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 @@ -226,10 +226,10 @@ type I012 interface { } func f012[T I012]() {} -var _ = f012[int /* ERROR does not satisfy I012 */ ] -var _ = f012[bool /* ERROR does not satisfy I012 */ ] -var _ = f012[string /* ERROR does not satisfy I012 */ ] -var _ = f012[float64 /* ERROR does not satisfy I012 */ ] +var _ = f012[int /* ERROR does not satisfy I012.*type set is empty */ ] +var _ = f012[bool /* ERROR does not satisfy I012.*type set is empty */ ] +var _ = f012[string /* ERROR does not satisfy I012.*type set is empty */ ] +var _ = f012[float64 /* ERROR does not satisfy I012.*type set is empty */ ] type I12 interface { E1 @@ -256,3 +256,23 @@ var _ = f0_[float64 /* ERROR does not satisfy I0_ */ ] // Using a function instance as a type is an error. var _ f0 // ERROR not a type var _ f0 /* ERROR not a type */ [int] + +// Empty type sets can only be satisfied by empty type sets. +type none interface { + // force an empty type set + int + string +} + +func ff[T none]() {} +func gg[T any]() {} +func hh[T ~int]() {} + +func _[T none]() { + _ = ff[int /* ERROR int does not satisfy none \(constraint type set is empty\) */ ] + _ = ff[T] // pathological but ok because T's type set is empty, too + _ = gg[int] + _ = gg[T] + _ = hh[int] + _ = hh[T] +} \ No newline at end of file diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go2 index 77281a19a2..ccf4bcf782 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go2 @@ -19,7 +19,7 @@ func _[P comparable, _ = f[R /* ERROR R has no constraints */ ] _ = g[int] - _ = g[P /* ERROR P has no type constraints */ ] + _ = g[P /* ERROR P does not satisfy interface{interface{comparable; ~int\|~string} */ ] _ = g[Q] _ = g[func( /* ERROR does not satisfy comparable */ )] _ = g[R /* ERROR R has no constraints */ ] diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index 8eb43a27e5..f9e3af7ba8 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -101,7 +101,7 @@ func (s *_TypeSet) String() string { // ---------------------------------------------------------------------------- // Implementation -func (s *_TypeSet) hasTerms() bool { return !s.terms.isAll() } +func (s *_TypeSet) hasTerms() bool { return !s.terms.isEmpty() && !s.terms.isAll() } func (s *_TypeSet) structuralType() Type { return s.terms.structuralType() } func (s *_TypeSet) includes(t Type) bool { return s.terms.includes(t) } func (s1 *_TypeSet) subsetOf(s2 *_TypeSet) bool { return s1.terms.subsetOf(s2.terms) } -- GitLab From 2c66cab8a7b569b2dc5a7ab112ba4579f39c5dbb Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Mon, 18 Oct 2021 18:34:24 -0400 Subject: [PATCH 1718/2500] testing: skip extra -count iterations if there are no tests When running benchmarks with high -count and no tests (either at all or filtered with -run), the time for runTests to check for tests -count times can add a significant delay to starting benchmarks. To avoid this delay, make runTests bail out on the second iteration if the first found no tests to run. We expect the same tests to run every time, so there is no reason to duplicate work. One caveat: the testing docs do not explicitly require the same subtests to be run on every call, so this could break tests that depend on multiple runs to actually run all tests. I consider such tests invalid, but some may exist. Fixes #49050 Change-Id: I7b34f3832b31493cc089ee0555e231f4dc690154 Reviewed-on: https://go-review.googlesource.com/c/go/+/356669 Trust: Michael Pratt Run-TryBot: Michael Pratt TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/testing/testing.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/testing/testing.go b/src/testing/testing.go index 6fb1a71d43..2ad2266e2d 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1785,6 +1785,12 @@ func runTests(matchString func(pat, str string) (bool, error), tests []InternalT if shouldFailFast() { break } + if i > 0 && !ran { + // There were no tests to run on the first + // iteration. This won't change, so no reason + // to keep trying. + break + } ctx := newTestContext(*parallel, newMatcher(matchString, *match, "-test.run")) ctx.deadline = deadline t := &T{ -- GitLab From c6e82e5808f4fb6da0fcc9754e29a220451a0dfd Mon Sep 17 00:00:00 2001 From: wdvxdr Date: Mon, 25 Oct 2021 17:54:11 +0800 Subject: [PATCH 1719/2500] cmd/compile: fix inlining labeled switch statements CL 357649 fixes inlining labeled FOR/RANGE loops, we should do same translation for inlined SWITCH's label Fixes #49145 Change-Id: I9a6f365f57e974271a1eb279b38e81f9b5148788 Reviewed-on: https://go-review.googlesource.com/c/go/+/358315 Trust: Cuong Manh Le Trust: Dan Scales Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Keith Randall Reviewed-by: Dan Scales --- src/cmd/compile/internal/inline/inl.go | 14 +++++++++---- test/fixedbugs/issue49145.go | 27 ++++++++++++++++++++++++++ test/fixedbugs/issue49145.out | 3 +++ 3 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 test/fixedbugs/issue49145.go create mode 100644 test/fixedbugs/issue49145.out diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index fb6cf53155..1ae6a58de0 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -1285,18 +1285,24 @@ func (subst *inlsubst) node(n ir.Node) ir.Node { ir.EditChildren(m, subst.edit) if subst.newclofn == nil { - // Translate any label on FOR or RANGE loops - if m.Op() == ir.OFOR { + // Translate any label on FOR, RANGE loops or SWITCH + switch m.Op() { + case ir.OFOR: m := m.(*ir.ForStmt) m.Label = translateLabel(m.Label) return m - } - if m.Op() == ir.ORANGE { + case ir.ORANGE: m := m.(*ir.RangeStmt) m.Label = translateLabel(m.Label) return m + + case ir.OSWITCH: + m := m.(*ir.SwitchStmt) + m.Label = translateLabel(m.Label) + return m } + } switch m := m.(type) { diff --git a/test/fixedbugs/issue49145.go b/test/fixedbugs/issue49145.go new file mode 100644 index 0000000000..d66668196e --- /dev/null +++ b/test/fixedbugs/issue49145.go @@ -0,0 +1,27 @@ +// run + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func f(j int) { +loop: + switch j { + case 1: + break loop + default: + println(j) + } +} + +func main() { +loop: + for j := 0; j < 5; j++ { + f(j) + if j == 3 { + break loop + } + } +} diff --git a/test/fixedbugs/issue49145.out b/test/fixedbugs/issue49145.out new file mode 100644 index 0000000000..1556c06ea8 --- /dev/null +++ b/test/fixedbugs/issue49145.out @@ -0,0 +1,3 @@ +0 +2 +3 -- GitLab From 52b10ab79451df78797b87e40eb9371127bad260 Mon Sep 17 00:00:00 2001 From: Charlotte Brandhorst-Satzkorn Date: Fri, 22 Oct 2021 22:46:46 -0400 Subject: [PATCH 1720/2500] net/http: correct Content-Length parsing for js/wasm The Content-Length was incorrectly set to 0 for ill-formed and invalid values. In these cases, return an error. If the Content-Length header was omitted, it was incorrectly set to 0. In this case, set the Content-Length value to -1. Fixes #49108 Change-Id: I24fe9a31ed5b6ddb53f2b2bd10f2c84e428823e3 Reviewed-on: https://go-review.googlesource.com/c/go/+/358134 Run-TryBot: Johan Brandhorst-Satzkorn Run-TryBot: Brad Fitzpatrick TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick Trust: Brad Fitzpatrick Trust: David Crawshaw --- src/net/http/roundtrip_js.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/net/http/roundtrip_js.go b/src/net/http/roundtrip_js.go index 74c83a9172..362dbcbdde 100644 --- a/src/net/http/roundtrip_js.go +++ b/src/net/http/roundtrip_js.go @@ -131,8 +131,24 @@ func (t *Transport) RoundTrip(req *Request) (*Response, error) { } contentLength := int64(0) - if cl, err := strconv.ParseInt(header.Get("Content-Length"), 10, 64); err == nil { + clHeader := header.Get("Content-Length") + switch { + case clHeader != "": + cl, err := strconv.ParseInt(clHeader, 10, 64) + if err != nil { + errCh <- fmt.Errorf("net/http: ill-formed Content-Length header: %v", err) + return nil + } + if cl < 0 { + // Content-Length values less than 0 are invalid. + // See: https://datatracker.ietf.org/doc/html/rfc2616/#section-14.13 + errCh <- fmt.Errorf("net/http: invalid Content-Length header: %q", clHeader) + return nil + } contentLength = cl + default: + // If the response length is not declared, set it to -1. + contentLength = -1 } b := result.Get("body") -- GitLab From 70ffd852cc85f1c782f4f2e70518d4861939cd1b Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Thu, 21 Oct 2021 18:36:14 -0400 Subject: [PATCH 1721/2500] go/types: remove subscripts from type parameter names Now that we've removed the necessity for subscripts in importers, we can effectively eliminate them from the the type parameter API by removing them from the type string. Change-Id: Ic4491b0dea27b0e0ce2d0636dccfaf05168ef9e5 Reviewed-on: https://go-review.googlesource.com/c/go/+/357814 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/types/api_test.go | 12 ++++++------ src/go/types/builtins_test.go | 6 +++--- src/go/types/errors.go | 10 +++++----- src/go/types/instantiate.go | 2 +- src/go/types/typestring.go | 26 ++++++++++++++++++-------- 5 files changed, 33 insertions(+), 23 deletions(-) diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index b331ad929b..7407426979 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -345,18 +345,18 @@ func TestTypesInfo(t *testing.T) { {broken + `x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string][-1]int`}, // parameterized functions - {genericPkg + `p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[generic_p0.T₁ interface{}](generic_p0.T₁)`}, + {genericPkg + `p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[generic_p0.T interface{}](generic_p0.T)`}, {genericPkg + `p1; func f[T any](T) {}; var _ = f[int]`, `f[int]`, `func(int)`}, {genericPkg + `p2; func f[T any](T) {}; func _() { f(42) }`, `f`, `func(int)`}, {genericPkg + `p3; func f[T any](T) {}; func _() { f[int](42) }`, `f[int]`, `func(int)`}, - {genericPkg + `p4; func f[T any](T) {}; func _() { f[int](42) }`, `f`, `func[generic_p4.T₁ interface{}](generic_p4.T₁)`}, + {genericPkg + `p4; func f[T any](T) {}; func _() { f[int](42) }`, `f`, `func[generic_p4.T interface{}](generic_p4.T)`}, {genericPkg + `p5; func f[T any](T) {}; func _() { f(42) }`, `f(42)`, `()`}, // type parameters {genericPkg + `t0; type t[] int; var _ t`, `t`, `generic_t0.t`}, // t[] is a syntax error that is ignored in this test in favor of t - {genericPkg + `t1; type t[P any] int; var _ t[int]`, `t`, `generic_t1.t[generic_t1.P₁ interface{}]`}, - {genericPkg + `t2; type t[P interface{}] int; var _ t[int]`, `t`, `generic_t2.t[generic_t2.P₁ interface{}]`}, - {genericPkg + `t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `generic_t3.t[generic_t3.P₁, generic_t3.Q₂ interface{}]`}, + {genericPkg + `t1; type t[P any] int; var _ t[int]`, `t`, `generic_t1.t[generic_t1.P interface{}]`}, + {genericPkg + `t2; type t[P interface{}] int; var _ t[int]`, `t`, `generic_t2.t[generic_t2.P interface{}]`}, + {genericPkg + `t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `generic_t3.t[generic_t3.P, generic_t3.Q interface{}]`}, // TODO (rFindley): compare with types2, which resolves the type broken_t4.t[P₁, Q₂ interface{m()}] here {broken + `t4; type t[P, Q interface{ m() }] int; var _ t[int, int]`, `t`, `broken_t4.t`}, @@ -365,7 +365,7 @@ func TestTypesInfo(t *testing.T) { {genericPkg + `g0; type t[P any] int; var x struct{ f t[int] }; var _ = x.f`, `x.f`, `generic_g0.t[int]`}, // issue 45096 - {genericPkg + `issue45096; func _[T interface{ ~int8 | ~int16 | ~int32 }](x T) { _ = x < 0 }`, `0`, `generic_issue45096.T₁`}, + {genericPkg + `issue45096; func _[T interface{ ~int8 | ~int16 | ~int32 }](x T) { _ = x < 0 }`, `0`, `generic_issue45096.T`}, // issue 47895 {`package p; import "unsafe"; type S struct { f int }; var s S; var _ = unsafe.Offsetof(s.f)`, `s.f`, `int`}, diff --git a/src/go/types/builtins_test.go b/src/go/types/builtins_test.go index cee3d315e5..db56aea3fe 100644 --- a/src/go/types/builtins_test.go +++ b/src/go/types/builtins_test.go @@ -113,15 +113,15 @@ var builtinCalls = []struct { {"Alignof", `_ = unsafe.Alignof(0)`, `invalid type`}, // constant {"Alignof", `var x struct{}; _ = unsafe.Alignof(x)`, `invalid type`}, // constant - {"Alignof", `var x P; _ = unsafe.Alignof(x)`, `func(p.P₁) uintptr`}, + {"Alignof", `var x P; _ = unsafe.Alignof(x)`, `func(p.P) uintptr`}, {"Offsetof", `var x struct{f bool}; _ = unsafe.Offsetof(x.f)`, `invalid type`}, // constant {"Offsetof", `var x struct{_ int; f bool}; _ = unsafe.Offsetof((&x).f)`, `invalid type`}, // constant - {"Offsetof", `var x struct{_ int; f P}; _ = unsafe.Offsetof((&x).f)`, `func(p.P₁) uintptr`}, + {"Offsetof", `var x struct{_ int; f P}; _ = unsafe.Offsetof((&x).f)`, `func(p.P) uintptr`}, {"Sizeof", `_ = unsafe.Sizeof(0)`, `invalid type`}, // constant {"Sizeof", `var x struct{}; _ = unsafe.Sizeof(x)`, `invalid type`}, // constant - {"Sizeof", `var x P; _ = unsafe.Sizeof(x)`, `func(p.P₁) uintptr`}, + {"Sizeof", `var x P; _ = unsafe.Sizeof(x)`, `func(p.P) uintptr`}, {"Slice", `var p *int; _ = unsafe.Slice(p, 1)`, `func(*int, int) []int`}, {"Slice", `var p *byte; var n uintptr; _ = unsafe.Slice(p, n)`, `func(*byte, uintptr) []byte`}, diff --git a/src/go/types/errors.go b/src/go/types/errors.go index 2d48fe14da..92002add13 100644 --- a/src/go/types/errors.go +++ b/src/go/types/errors.go @@ -63,10 +63,10 @@ func (check *Checker) markImports(pkg *Package) { } func (check *Checker) sprintf(format string, args ...interface{}) string { - return sprintf(check.fset, check.qualifier, format, args...) + return sprintf(check.fset, check.qualifier, false, format, args...) } -func sprintf(fset *token.FileSet, qf Qualifier, format string, args ...interface{}) string { +func sprintf(fset *token.FileSet, qf Qualifier, debug bool, format string, args ...interface{}) string { for i, arg := range args { switch a := arg.(type) { case nil: @@ -84,7 +84,7 @@ func sprintf(fset *token.FileSet, qf Qualifier, format string, args ...interface case Object: arg = ObjectString(a, qf) case Type: - arg = TypeString(a, qf) + arg = typeString(a, qf, debug) } args[i] = arg } @@ -95,13 +95,13 @@ func (check *Checker) trace(pos token.Pos, format string, args ...interface{}) { fmt.Printf("%s:\t%s%s\n", check.fset.Position(pos), strings.Repeat(". ", check.indent), - check.sprintf(format, args...), + sprintf(check.fset, check.qualifier, true, format, args...), ) } // dump is only needed for debugging func (check *Checker) dump(format string, args ...interface{}) { - fmt.Println(check.sprintf(format, args...)) + fmt.Println(sprintf(check.fset, check.qualifier, true, format, args...)) } func (check *Checker) err(err error) { diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 65c935a192..2bb31b17ee 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -146,7 +146,7 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap qf = check.qualifier } errorf := func(format string, args ...interface{}) error { - return errors.New(sprintf(nil, qf, format, args...)) + return errors.New(sprintf(nil, qf, false, format, args...)) } // The type parameter bound is parameterized with the same type parameters diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index a0c78e8cc3..2feaf627d6 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -44,8 +44,14 @@ func RelativeTo(pkg *Package) Qualifier { // The Qualifier controls the printing of // package-level objects, and may be nil. func TypeString(typ Type, qf Qualifier) string { + return typeString(typ, qf, false) +} + +func typeString(typ Type, qf Qualifier, debug bool) string { var buf bytes.Buffer - WriteType(&buf, typ, qf) + w := newTypeWriter(&buf, qf) + w.debug = debug + w.typ(typ) return buf.String() } @@ -65,19 +71,20 @@ func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) { } type typeWriter struct { - buf *bytes.Buffer - seen map[Type]bool - qf Qualifier - ctxt *Context // if non-nil, we are type hashing + buf *bytes.Buffer + seen map[Type]bool + qf Qualifier + ctxt *Context // if non-nil, we are type hashing + debug bool // if true, write debug annotations } func newTypeWriter(buf *bytes.Buffer, qf Qualifier) *typeWriter { - return &typeWriter{buf, make(map[Type]bool), qf, nil} + return &typeWriter{buf, make(map[Type]bool), qf, nil, false} } func newTypeHasher(buf *bytes.Buffer, ctxt *Context) *typeWriter { assert(ctxt != nil) - return &typeWriter{buf, make(map[Type]bool), nil, ctxt} + return &typeWriter{buf, make(map[Type]bool), nil, ctxt, false} } func (w *typeWriter) byte(b byte) { @@ -274,7 +281,10 @@ func (w *typeWriter) typ(typ Type) { if t.obj.pkg != nil { writePackage(w.buf, t.obj.pkg, w.qf) } - w.string(t.obj.name + subscript(t.id)) + w.string(t.obj.name) + if w.debug || w.ctxt != nil { + w.string(subscript(t.id)) + } case *top: w.error("⊤") -- GitLab From bc0eb5789e01817823fd9707d2d4857691f898ad Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 19 Oct 2021 18:40:27 -0400 Subject: [PATCH 1722/2500] cmd/compile/internal/typecheck: record whether an interface is implicit In preparation for capturing the implicit interface bit in export data, thread through the IsImplicit property from types2 into typecheck. Change-Id: I9b46fe73de102935a127e6ececaacd76738b557e Reviewed-on: https://go-review.googlesource.com/c/go/+/357109 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/noder/reader.go | 2 +- src/cmd/compile/internal/noder/stencil.go | 2 +- src/cmd/compile/internal/noder/types.go | 2 +- src/cmd/compile/internal/test/abiutils_test.go | 2 +- src/cmd/compile/internal/typecheck/iimport.go | 2 +- src/cmd/compile/internal/typecheck/subr.go | 4 ++-- src/cmd/compile/internal/typecheck/type.go | 2 +- src/cmd/compile/internal/types/sizeof_test.go | 2 +- src/cmd/compile/internal/types/type.go | 13 +++++++++++-- src/cmd/compile/internal/types/universe.go | 8 ++++---- 10 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 48f4368113..0bc9135999 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -466,7 +466,7 @@ func (r *reader) interfaceType() *types.Type { if len(fields) == 0 { return types.Types[types.TINTER] // empty interface } - return types.NewInterface(tpkg, fields) + return types.NewInterface(tpkg, fields, false) } func (r *reader) structType() *types.Type { diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 592de7017f..474a05973a 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -881,7 +881,7 @@ func (subst *subster) checkDictionary(name *ir.Name, targs []*types.Type) (code cond := ir.NewBinaryExpr(pos, ir.ONE, want, got) typed(types.Types[types.TBOOL], cond) panicArg := ir.NewNilExpr(pos) - typed(types.NewInterface(types.LocalPkg, nil), panicArg) + typed(types.NewInterface(types.LocalPkg, nil, false), panicArg) then := ir.NewUnaryExpr(pos, ir.OPANIC, panicArg) then.SetTypecheck(1) x := ir.NewIfStmt(pos, cond, []ir.Node{then}, nil) diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index 1a7cef4aa3..f035e0da97 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -213,7 +213,7 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { methods[i] = types.NewField(g.pos(m), g.selector(m), mtyp) } - return types.NewInterface(g.tpkg(typ), append(embeddeds, methods...)) + return types.NewInterface(g.tpkg(typ), append(embeddeds, methods...), typ.IsImplicit()) case *types2.TypeParam: // Save the name of the type parameter in the sym of the type. diff --git a/src/cmd/compile/internal/test/abiutils_test.go b/src/cmd/compile/internal/test/abiutils_test.go index f26cb89c6d..12b4a0c361 100644 --- a/src/cmd/compile/internal/test/abiutils_test.go +++ b/src/cmd/compile/internal/test/abiutils_test.go @@ -313,7 +313,7 @@ func TestABIUtilsInterfaces(t *testing.T) { fldt := mkFuncType(types.FakeRecvType(), []*types.Type{}, []*types.Type{types.Types[types.TSTRING]}) field := types.NewField(src.NoXPos, typecheck.Lookup("F"), fldt) - nei := types.NewInterface(types.LocalPkg, []*types.Field{field}) + nei := types.NewInterface(types.LocalPkg, []*types.Field{field}, false) i16 := types.Types[types.TINT16] tb := types.Types[types.TBOOL] s1 := mkstruct([]*types.Type{i16, i16, tb}) diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index cb1e56bf51..fcfadc146c 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -815,7 +815,7 @@ func (r *importReader) typ1() *types.Type { return types.Types[types.TINTER] } - t := types.NewInterface(r.currPkg, append(embeddeds, methods...)) + t := types.NewInterface(r.currPkg, append(embeddeds, methods...), false) // Ensure we expand the interface in the frontend (#25055). types.CheckSize(t) diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index b4d5302525..9ebd8f1423 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1369,7 +1369,7 @@ func (ts *Tsubster) tinter(t *types.Type, force bool) *types.Type { // For an empty interface, we need to return a new type, // since it may now be fully instantiated (HasTParam // becomes false). - return types.NewInterface(t.Pkg(), nil) + return types.NewInterface(t.Pkg(), nil, false) } return t } @@ -1390,7 +1390,7 @@ func (ts *Tsubster) tinter(t *types.Type, force bool) *types.Type { } } if newfields != nil { - return types.NewInterface(t.Pkg(), newfields) + return types.NewInterface(t.Pkg(), newfields, false) } return t } diff --git a/src/cmd/compile/internal/typecheck/type.go b/src/cmd/compile/internal/typecheck/type.go index af694c2d94..c4c1ef58ca 100644 --- a/src/cmd/compile/internal/typecheck/type.go +++ b/src/cmd/compile/internal/typecheck/type.go @@ -108,7 +108,7 @@ func tcInterfaceType(n *ir.InterfaceType) ir.Node { methods := tcFields(n.Methods, nil) base.Pos = lno - n.SetOTYPE(types.NewInterface(types.LocalPkg, methods)) + n.SetOTYPE(types.NewInterface(types.LocalPkg, methods, false)) return n } diff --git a/src/cmd/compile/internal/types/sizeof_test.go b/src/cmd/compile/internal/types/sizeof_test.go index 7349e52a73..d37c173058 100644 --- a/src/cmd/compile/internal/types/sizeof_test.go +++ b/src/cmd/compile/internal/types/sizeof_test.go @@ -26,7 +26,7 @@ func TestSizeof(t *testing.T) { {Forward{}, 20, 32}, {Func{}, 28, 48}, {Struct{}, 16, 32}, - {Interface{}, 4, 8}, + {Interface{}, 8, 16}, {Chan{}, 8, 16}, {Array{}, 12, 16}, {FuncArgs{}, 4, 8}, diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 392c54ba79..ec17fe8704 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -417,7 +417,8 @@ func (t *Type) StructType() *Struct { // Interface contains Type fields specific to interface types. type Interface struct { - pkg *Pkg + pkg *Pkg + implicit bool } // Typeparam contains Type fields specific to typeparam types. @@ -1820,7 +1821,7 @@ func newBasic(kind Kind, obj Object) *Type { // NewInterface returns a new interface for the given methods and // embedded types. Embedded types are specified as fields with no Sym. -func NewInterface(pkg *Pkg, methods []*Field) *Type { +func NewInterface(pkg *Pkg, methods []*Field, implicit bool) *Type { t := newType(TINTER) t.SetInterface(methods) for _, f := range methods { @@ -1838,6 +1839,7 @@ func NewInterface(pkg *Pkg, methods []*Field) *Type { t.SetBroke(true) } t.extra.(*Interface).pkg = pkg + t.extra.(*Interface).implicit = implicit return t } @@ -1875,6 +1877,13 @@ func (t *Type) Bound() *Type { return t.extra.(*Typeparam).bound } +// IsImplicit reports whether an interface is implicit (i.e. elided from a type +// parameter constraint). +func (t *Type) IsImplicit() bool { + t.wantEtype(TINTER) + return t.extra.(*Interface).implicit +} + // NewUnion returns a new union with the specified set of terms (types). If // tildes[i] is true, then terms[i] represents ~T, rather than just T. func NewUnion(terms []*Type, tildes []bool) *Type { diff --git a/src/cmd/compile/internal/types/universe.go b/src/cmd/compile/internal/types/universe.go index 8fa4b7cd20..d5239eb10c 100644 --- a/src/cmd/compile/internal/types/universe.go +++ b/src/cmd/compile/internal/types/universe.go @@ -58,7 +58,7 @@ func InitTypes(defTypeName func(sym *Sym, typ *Type) Object) { } Types[TANY] = newType(TANY) - Types[TINTER] = NewInterface(LocalPkg, nil) + Types[TINTER] = NewInterface(LocalPkg, nil, false) defBasic := func(kind Kind, pkg *Pkg, name string) *Type { typ := newType(kind) @@ -111,7 +111,7 @@ func InitTypes(defTypeName func(sym *Sym, typ *Type) Object) { if base.Flag.G > 0 { DeferCheckSize() AnyType = defBasic(TFORW, BuiltinPkg, "any") - AnyType.SetUnderlying(NewInterface(NoPkg, []*Field{})) + AnyType.SetUnderlying(NewInterface(NoPkg, []*Field{}, false)) ResumeCheckSize() } @@ -145,11 +145,11 @@ func makeErrorInterface() *Type { NewField(src.NoXPos, nil, Types[TSTRING]), }) method := NewField(src.NoXPos, LocalPkg.Lookup("Error"), sig) - return NewInterface(NoPkg, []*Field{method}) + return NewInterface(NoPkg, []*Field{method}, false) } func makeComparableInterface() *Type { sig := NewSignature(NoPkg, FakeRecv(), nil, nil, nil) method := NewField(src.NoXPos, LocalPkg.Lookup("=="), sig) - return NewInterface(NoPkg, []*Field{method}) + return NewInterface(NoPkg, []*Field{method}, false) } -- GitLab From 95372efc4d300c54738406fb81d84a72bd8149cc Mon Sep 17 00:00:00 2001 From: wdvxdr Date: Mon, 25 Oct 2021 18:15:43 +0800 Subject: [PATCH 1723/2500] cmd/compile: use SetInit instead of *PtrInit Change-Id: Ie802ff27b611ed248d7b14f6e972e6300c181f43 Reviewed-on: https://go-review.googlesource.com/c/go/+/358316 Trust: Cuong Manh Le Trust: Dan Scales Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/inline/inl.go | 4 ++-- src/cmd/compile/internal/noder/noder.go | 4 ++-- src/cmd/compile/internal/walk/complit.go | 2 +- src/cmd/compile/internal/walk/select.go | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index 1ae6a58de0..483b3d5d46 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -1259,7 +1259,7 @@ func (subst *inlsubst) node(n ir.Node) ir.Node { n := n.(*ir.BranchStmt) m := ir.Copy(n).(*ir.BranchStmt) m.SetPos(subst.updatedPos(m.Pos())) - *m.PtrInit() = nil + m.SetInit(nil) m.Label = translateLabel(n.Label) return m @@ -1271,7 +1271,7 @@ func (subst *inlsubst) node(n ir.Node) ir.Node { n := n.(*ir.LabelStmt) m := ir.Copy(n).(*ir.LabelStmt) m.SetPos(subst.updatedPos(m.Pos())) - *m.PtrInit() = nil + m.SetInit(nil) m.Label = translateLabel(n.Label) return m diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index 7c14fcf041..fc1541f74e 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -1238,7 +1238,7 @@ func (p *noder) ifStmt(stmt *syntax.IfStmt) ir.Node { init := p.stmt(stmt.Init) n := ir.NewIfStmt(p.pos(stmt), p.expr(stmt.Cond), p.blockStmt(stmt.Then), nil) if init != nil { - *n.PtrInit() = []ir.Node{init} + n.SetInit([]ir.Node{init}) } if stmt.Else != nil { e := p.stmt(stmt.Else) @@ -1285,7 +1285,7 @@ func (p *noder) switchStmt(stmt *syntax.SwitchStmt) ir.Node { init := p.stmt(stmt.Init) n := ir.NewSwitchStmt(p.pos(stmt), p.expr(stmt.Tag), nil) if init != nil { - *n.PtrInit() = []ir.Node{init} + n.SetInit([]ir.Node{init}) } var tswitch *ir.TypeSwitchGuard diff --git a/src/cmd/compile/internal/walk/complit.go b/src/cmd/compile/internal/walk/complit.go index ad54fa7b96..b985b4caeb 100644 --- a/src/cmd/compile/internal/walk/complit.go +++ b/src/cmd/compile/internal/walk/complit.go @@ -482,7 +482,7 @@ func maplit(n *ir.CompLitExpr, m ir.Node, init *ir.Nodes) { loop := ir.NewForStmt(base.Pos, nil, cond, incr, nil) loop.Body = []ir.Node{body} - *loop.PtrInit() = []ir.Node{zero} + loop.SetInit([]ir.Node{zero}) appendWalkStmt(init, loop) return diff --git a/src/cmd/compile/internal/walk/select.go b/src/cmd/compile/internal/walk/select.go index d2b67ddf55..fde8f50895 100644 --- a/src/cmd/compile/internal/walk/select.go +++ b/src/cmd/compile/internal/walk/select.go @@ -105,7 +105,7 @@ func walkSelectCases(cases []*ir.CommClause) []ir.Node { n := cas.Comm ir.SetPos(n) r := ir.NewIfStmt(base.Pos, nil, nil, nil) - *r.PtrInit() = cas.Init() + r.SetInit(cas.Init()) var cond ir.Node switch n.Op() { default: -- GitLab From 9012996a9a127fd566c72baac5e7d8ba45b4865e Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Mon, 25 Oct 2021 11:51:25 -0400 Subject: [PATCH 1724/2500] cmd/compile: don't clobber LR for tail calls When doing a tail call the link register is live as the callee will directly return to the caller (of the function that does the tail call). Don't allocate or clobber the link register. Fixes #49032. Change-Id: I2d60f2354e5b6c14aa285c8983a9786687b90223 Reviewed-on: https://go-review.googlesource.com/c/go/+/358435 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: Cuong Manh Le TryBot-Result: Go Bot --- src/cmd/compile/internal/ssa/gen/386Ops.go | 2 +- src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 2 +- src/cmd/compile/internal/ssa/gen/ARM64Ops.go | 2 +- src/cmd/compile/internal/ssa/gen/ARMOps.go | 2 +- src/cmd/compile/internal/ssa/gen/MIPS64Ops.go | 2 +- src/cmd/compile/internal/ssa/gen/MIPSOps.go | 2 +- src/cmd/compile/internal/ssa/gen/PPC64Ops.go | 2 +- .../compile/internal/ssa/gen/RISCV64Ops.go | 8 +++--- src/cmd/compile/internal/ssa/gen/S390XOps.go | 2 +- src/cmd/compile/internal/ssa/gen/WasmOps.go | 2 +- src/cmd/compile/internal/ssa/gen/main.go | 5 ++++ src/cmd/compile/internal/ssa/op.go | 1 + src/cmd/compile/internal/ssa/opGen.go | 27 +++++++++++++------ src/cmd/compile/internal/ssa/regalloc.go | 3 ++- 14 files changed, 40 insertions(+), 22 deletions(-) diff --git a/src/cmd/compile/internal/ssa/gen/386Ops.go b/src/cmd/compile/internal/ssa/gen/386Ops.go index a6da7a5fce..f4c89b0bb3 100644 --- a/src/cmd/compile/internal/ssa/gen/386Ops.go +++ b/src/cmd/compile/internal/ssa/gen/386Ops.go @@ -455,7 +455,7 @@ func init() { }, {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem - {name: "CALLtail", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // tail call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLtail", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true, tailCall: true}, // tail call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("DX"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index e3c94e4b2e..a6906bec7c 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -765,7 +765,7 @@ func init() { // With a register ABI, the actual register info for these instructions (i.e., what is used in regalloc) is augmented with per-call-site bindings of additional arguments to specific in and out registers. {name: "CALLstatic", argLength: -1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). last arg=mem, auxint=argsize, returns mem - {name: "CALLtail", argLength: -1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // tail call static function aux.(*obj.LSym). last arg=mem, auxint=argsize, returns mem + {name: "CALLtail", argLength: -1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true, tailCall: true}, // tail call static function aux.(*obj.LSym). last arg=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: -1, reg: regInfo{inputs: []regMask{gpsp, buildReg("DX"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, last arg=mem, auxint=argsize, returns mem {name: "CALLinter", argLength: -1, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, last arg=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go index a4a5b9bdcd..e052ce09f4 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go @@ -492,7 +492,7 @@ func init() { // function calls {name: "CALLstatic", argLength: -1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). last arg=mem, auxint=argsize, returns mem - {name: "CALLtail", argLength: -1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // tail call static function aux.(*obj.LSym). last arg=mem, auxint=argsize, returns mem + {name: "CALLtail", argLength: -1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true, tailCall: true}, // tail call static function aux.(*obj.LSym). last arg=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: -1, reg: regInfo{inputs: []regMask{gpsp, buildReg("R26"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, last arg=mem, auxint=argsize, returns mem {name: "CALLinter", argLength: -1, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, last arg=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/ARMOps.go b/src/cmd/compile/internal/ssa/gen/ARMOps.go index 75ba769724..2f004205a5 100644 --- a/src/cmd/compile/internal/ssa/gen/ARMOps.go +++ b/src/cmd/compile/internal/ssa/gen/ARMOps.go @@ -432,7 +432,7 @@ func init() { // function calls {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem - {name: "CALLtail", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // tail call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLtail", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true, tailCall: true}, // tail call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R7"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/MIPS64Ops.go b/src/cmd/compile/internal/ssa/gen/MIPS64Ops.go index 54c0741efd..7b18c42ffb 100644 --- a/src/cmd/compile/internal/ssa/gen/MIPS64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/MIPS64Ops.go @@ -276,7 +276,7 @@ func init() { // function calls {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem - {name: "CALLtail", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // tail call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLtail", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true, tailCall: true}, // tail call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R22"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/MIPSOps.go b/src/cmd/compile/internal/ssa/gen/MIPSOps.go index 5f73e9f2dc..523847badc 100644 --- a/src/cmd/compile/internal/ssa/gen/MIPSOps.go +++ b/src/cmd/compile/internal/ssa/gen/MIPSOps.go @@ -258,7 +258,7 @@ func init() { // function calls {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem - {name: "CALLtail", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // tail call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLtail", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true, tailCall: true}, // tail call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R22"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go index 42775fa3c2..59d8af1a9d 100644 --- a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go @@ -434,7 +434,7 @@ func init() { {name: "LoweredRound64F", argLength: 1, reg: fp11, resultInArg0: true, zeroWidth: true}, {name: "CALLstatic", argLength: -1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem - {name: "CALLtail", argLength: -1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // tail call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLtail", argLength: -1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true, tailCall: true}, // tail call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: -1, reg: regInfo{inputs: []regMask{callptr, ctxt, 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "CALLinter", argLength: -1, reg: regInfo{inputs: []regMask{callptr}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go index 8a3fdf75f7..880fad1c49 100644 --- a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go @@ -240,10 +240,10 @@ func init() { {name: "MOVconvert", argLength: 2, reg: gp11, asm: "MOV"}, // arg0, but converted to int/ptr as appropriate; arg1=mem // Calls - {name: "CALLstatic", argLength: 1, reg: call, aux: "CallOff", call: true}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem - {name: "CALLtail", argLength: 1, reg: call, aux: "CallOff", call: true}, // tail call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem - {name: "CALLclosure", argLength: 3, reg: callClosure, aux: "CallOff", call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem - {name: "CALLinter", argLength: 2, reg: callInter, aux: "CallOff", call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem + {name: "CALLstatic", argLength: 1, reg: call, aux: "CallOff", call: true}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem + {name: "CALLtail", argLength: 1, reg: call, aux: "CallOff", call: true, tailCall: true}, // tail call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem + {name: "CALLclosure", argLength: 3, reg: callClosure, aux: "CallOff", call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem + {name: "CALLinter", argLength: 2, reg: callInter, aux: "CallOff", call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem // duffzero // arg0 = address of memory to zero (in X10, changed as side effect) diff --git a/src/cmd/compile/internal/ssa/gen/S390XOps.go b/src/cmd/compile/internal/ssa/gen/S390XOps.go index 9b6ac2bfb6..cd7bad7acb 100644 --- a/src/cmd/compile/internal/ssa/gen/S390XOps.go +++ b/src/cmd/compile/internal/ssa/gen/S390XOps.go @@ -480,7 +480,7 @@ func init() { {name: "CLEAR", argLength: 2, reg: regInfo{inputs: []regMask{ptr, 0}}, asm: "CLEAR", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Write"}, {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem - {name: "CALLtail", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // tail call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "CALLtail", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true, tailCall: true}, // tail call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{ptrsp, buildReg("R12"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{ptr}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/WasmOps.go b/src/cmd/compile/internal/ssa/gen/WasmOps.go index 0d7327109a..edfba4ee99 100644 --- a/src/cmd/compile/internal/ssa/gen/WasmOps.go +++ b/src/cmd/compile/internal/ssa/gen/WasmOps.go @@ -124,7 +124,7 @@ func init() { var WasmOps = []opData{ {name: "LoweredStaticCall", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", call: true}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem - {name: "LoweredTailCall", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", call: true}, // tail call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem + {name: "LoweredTailCall", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", call: true, tailCall: true}, // tail call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem {name: "LoweredClosureCall", argLength: 3, reg: regInfo{inputs: []regMask{gp, gp, 0}, clobbers: callerSave}, aux: "CallOff", call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "LoweredInterCall", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/gen/main.go b/src/cmd/compile/internal/ssa/gen/main.go index 8e5997b25a..2cf0a919fa 100644 --- a/src/cmd/compile/internal/ssa/gen/main.go +++ b/src/cmd/compile/internal/ssa/gen/main.go @@ -63,6 +63,7 @@ type opData struct { resultNotInArgs bool // outputs must not be allocated to the same registers as inputs clobberFlags bool // this op clobbers flags register call bool // is a function call + tailCall bool // is a tail call nilCheck bool // this op is a nil check on arg0 faultOnNilArg0 bool // this op will fault if arg0 is nil (and aux encodes a small offset) faultOnNilArg1 bool // this op will fault if arg1 is nil (and aux encodes a small offset) @@ -307,6 +308,9 @@ func genOp() { if v.call { fmt.Fprintln(w, "call: true,") } + if v.tailCall { + fmt.Fprintln(w, "tailCall: true,") + } if v.nilCheck { fmt.Fprintln(w, "nilCheck: true,") } @@ -405,6 +409,7 @@ func genOp() { fmt.Fprintln(w, "func (o Op) SymEffect() SymEffect { return opcodeTable[o].symEffect }") fmt.Fprintln(w, "func (o Op) IsCall() bool { return opcodeTable[o].call }") + fmt.Fprintln(w, "func (o Op) IsTailCall() bool { return opcodeTable[o].tailCall }") fmt.Fprintln(w, "func (o Op) HasSideEffects() bool { return opcodeTable[o].hasSideEffects }") fmt.Fprintln(w, "func (o Op) UnsafePoint() bool { return opcodeTable[o].unsafePoint }") fmt.Fprintln(w, "func (o Op) ResultInArg0() bool { return opcodeTable[o].resultInArg0 }") diff --git a/src/cmd/compile/internal/ssa/op.go b/src/cmd/compile/internal/ssa/op.go index 6f7b9fa8e9..421d856a4f 100644 --- a/src/cmd/compile/internal/ssa/op.go +++ b/src/cmd/compile/internal/ssa/op.go @@ -34,6 +34,7 @@ type opInfo struct { resultNotInArgs bool // outputs must not be allocated to the same registers as inputs clobberFlags bool // this op clobbers flags register call bool // is a function call + tailCall bool // is a tail call nilCheck bool // this op is a nil check on arg0 faultOnNilArg0 bool // this op will fault if arg0 is nil (and aux encodes a small offset) faultOnNilArg1 bool // this op will fault if arg1 is nil (and aux encodes a small offset) diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 091f43f40a..ed10f35fb9 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -5948,6 +5948,7 @@ var opcodeTable = [...]opInfo{ argLen: 1, clobberFlags: true, call: true, + tailCall: true, reg: regInfo{ clobbers: 65519, // AX CX DX BX BP SI DI X0 X1 X2 X3 X4 X5 X6 X7 }, @@ -13153,6 +13154,7 @@ var opcodeTable = [...]opInfo{ argLen: -1, clobberFlags: true, call: true, + tailCall: true, reg: regInfo{ clobbers: 2147483631, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 g R15 X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 }, @@ -17201,6 +17203,7 @@ var opcodeTable = [...]opInfo{ argLen: 1, clobberFlags: true, call: true, + tailCall: true, reg: regInfo{ clobbers: 4294924287, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 }, @@ -21094,6 +21097,7 @@ var opcodeTable = [...]opInfo{ argLen: -1, clobberFlags: true, call: true, + tailCall: true, reg: regInfo{ clobbers: 9223372035512336383, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, @@ -23045,6 +23049,7 @@ var opcodeTable = [...]opInfo{ argLen: 1, clobberFlags: true, call: true, + tailCall: true, reg: regInfo{ clobbers: 140737421246462, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31 F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30 HI LO }, @@ -24614,6 +24619,7 @@ var opcodeTable = [...]opInfo{ argLen: 1, clobberFlags: true, call: true, + tailCall: true, reg: regInfo{ clobbers: 4611686018393833470, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 HI LO }, @@ -27464,6 +27470,7 @@ var opcodeTable = [...]opInfo{ argLen: -1, clobberFlags: true, call: true, + tailCall: true, reg: regInfo{ clobbers: 576460745860964344, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 g F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 }, @@ -28875,10 +28882,11 @@ var opcodeTable = [...]opInfo{ }, }, { - name: "CALLtail", - auxType: auxCallOff, - argLen: 1, - call: true, + name: "CALLtail", + auxType: auxCallOff, + argLen: 1, + call: true, + tailCall: true, reg: regInfo{ clobbers: 9223372035781033972, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, @@ -32644,6 +32652,7 @@ var opcodeTable = [...]opInfo{ argLen: 1, clobberFlags: true, call: true, + tailCall: true, reg: regInfo{ clobbers: 4294933503, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 g R14 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 }, @@ -33319,10 +33328,11 @@ var opcodeTable = [...]opInfo{ }, }, { - name: "LoweredTailCall", - auxType: auxCallOff, - argLen: 1, - call: true, + name: "LoweredTailCall", + auxType: auxCallOff, + argLen: 1, + call: true, + tailCall: true, reg: regInfo{ clobbers: 844424930131967, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 g }, @@ -36890,6 +36900,7 @@ func (o Op) Scale() int16 { return int16(opcodeTable[o].scale) } func (o Op) String() string { return opcodeTable[o].name } func (o Op) SymEffect() SymEffect { return opcodeTable[o].symEffect } func (o Op) IsCall() bool { return opcodeTable[o].call } +func (o Op) IsTailCall() bool { return opcodeTable[o].tailCall } func (o Op) HasSideEffects() bool { return opcodeTable[o].hasSideEffects } func (o Op) UnsafePoint() bool { return opcodeTable[o].unsafePoint } func (o Op) ResultInArg0() bool { return opcodeTable[o].resultInArg0 } diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index 431059ae69..126973a6e1 100644 --- a/src/cmd/compile/internal/ssa/regalloc.go +++ b/src/cmd/compile/internal/ssa/regalloc.go @@ -559,7 +559,8 @@ func (s *regAllocState) allocValToReg(v *Value, mask regMask, nospill bool, pos func isLeaf(f *Func) bool { for _, b := range f.Blocks { for _, v := range b.Values { - if opcodeTable[v.Op].call { + if v.Op.IsCall() && !v.Op.IsTailCall() { + // tail call is not counted as it does not save retur PC or need a frame return false } } -- GitLab From f47335e653ac37f68ada2b265ce4a2c869a27cae Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Sat, 5 Jun 2021 11:04:37 +0530 Subject: [PATCH 1725/2500] crypto/tls: add Conn.NetConn method NetConn method gives us access to the underlying net.Conn value. Fixes #29257 Change-Id: I68b2a92ed9dab4be9900807c94184f8c0aeb4f72 Reviewed-on: https://go-review.googlesource.com/c/go/+/325250 Reviewed-by: Filippo Valsorda Trust: Agniva De Sarker Trust: Katie Hockman --- src/crypto/tls/conn.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/crypto/tls/conn.go b/src/crypto/tls/conn.go index 969f357834..300e9a233c 100644 --- a/src/crypto/tls/conn.go +++ b/src/crypto/tls/conn.go @@ -151,6 +151,13 @@ func (c *Conn) SetWriteDeadline(t time.Time) error { return c.conn.SetWriteDeadline(t) } +// NetConn returns the underlying connection that is wrapped by c. +// Note that writing to or reading from this connection directly will corrupt the +// TLS session. +func (c *Conn) NetConn() net.Conn { + return c.conn +} + // A halfConn represents one direction of the record layer // connection, either sending or receiving. type halfConn struct { -- GitLab From 8c94aa40e6f5e61e8a570e9d20b7d0d4ad8c382d Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Fri, 22 Oct 2021 11:56:23 -0400 Subject: [PATCH 1726/2500] cmd/go/testdata/script: fix flaky test_fuzz_fuzztime test Previously, the test would panic if the short timeout was reached before fuzzing began. Increasing the timeout should stop this test from being flaky. Fixes #49046 Change-Id: Iaa0b3b3e8ea29d9a42ab5fc1c801fc73fffe1675 Reviewed-on: https://go-review.googlesource.com/c/go/+/358055 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/testdata/script/test_fuzz_fuzztime.txt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt index 6264aca17d..c3933bc7e2 100644 --- a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt +++ b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt @@ -1,5 +1,3 @@ -skip # Flaky: https://golang.org/issue/49046 - # TODO(jayconrod): support shared memory on more platforms. [!darwin] [!linux] [!windows] skip @@ -9,11 +7,11 @@ skip # Flaky: https://golang.org/issue/49046 go test # Fuzzing should exit 0 after fuzztime, even if timeout is short. -go test -timeout=10ms -fuzz=FuzzFast -fuzztime=5s +go test -timeout=3s -fuzz=FuzzFast -fuzztime=5s # We should see the same behavior when invoking the test binary directly. go test -c -exec ./fuzz.test$GOEXE -test.timeout=10ms -test.fuzz=FuzzFast -test.fuzztime=5s -test.parallel=1 -test.fuzzcachedir=$WORK/cache +exec ./fuzz.test$GOEXE -test.timeout=3s -test.fuzz=FuzzFast -test.fuzztime=5s -test.parallel=1 -test.fuzzcachedir=$WORK/cache # Timeout should not cause inputs to be written as crashers. ! exists testdata/fuzz -- GitLab From 252324e879e32f948d885f787decf8af06f82be9 Mon Sep 17 00:00:00 2001 From: Richard Musiol Date: Sun, 24 Oct 2021 12:28:18 +0200 Subject: [PATCH 1727/2500] cmd/link: increase reserved space for passing env on wasm On wasm, the wasm_exec.js helper passes the command line arguments and environment variables via a reserved space in the wasm linear memory. Increase this reserved space from 4096 to 8192 bytes so more environment variables can fit into the limit. Later, after https://golang.org/cl/350737 landed, we can switch to the WASI interface for getting the arguments and environment. This would remove the limit entirely. Fixes #49011 Change-Id: I48a6e952a97d33404ed692c98e9b49c5cd6b269b Reviewed-on: https://go-review.googlesource.com/c/go/+/358194 Trust: Richard Musiol Run-TryBot: Richard Musiol TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- misc/wasm/wasm_exec.js | 4 ++-- src/cmd/link/internal/ld/data.go | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/misc/wasm/wasm_exec.js b/misc/wasm/wasm_exec.js index 30044a6f85..9ce6a20c3f 100644 --- a/misc/wasm/wasm_exec.js +++ b/misc/wasm/wasm_exec.js @@ -519,9 +519,9 @@ // The linker guarantees global data starts from at least wasmMinDataAddr. // Keep in sync with cmd/link/internal/ld/data.go:wasmMinDataAddr. - const wasmMinDataAddr = 4096 + 4096; + const wasmMinDataAddr = 4096 + 8192; if (offset >= wasmMinDataAddr) { - throw new Error("command line too long"); + throw new Error("total length of command line and environment variables exceeds limit"); } this._inst.exports.run(argc, argv); diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 45e0e08793..0513a0d10b 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -2442,10 +2442,11 @@ func splitTextSections(ctxt *Link) bool { return (ctxt.IsPPC64() || (ctxt.IsARM64() && ctxt.IsDarwin())) && ctxt.IsExternal() } -// On Wasm, we reserve 4096 bytes for zero page, then 4096 bytes for wasm_exec.js -// to store command line args. Data sections starts from at least address 8192. +// On Wasm, we reserve 4096 bytes for zero page, then 8192 bytes for wasm_exec.js +// to store command line args and environment variables. +// Data sections starts from at least address 12288. // Keep in sync with wasm_exec.js. -const wasmMinDataAddr = 4096 + 4096 +const wasmMinDataAddr = 4096 + 8192 // address assigns virtual addresses to all segments and sections and // returns all segments in file order. -- GitLab From c26a32a5004afd4598f844ab49332c25d7613133 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 21 Oct 2021 18:04:55 -0700 Subject: [PATCH 1728/2500] cmd/compile,cmd/link: introduce generic interface call relocations To capture the fact that a method was called on a generic interface, so we can make sure the linker doesn't throw away any implementations that might be the method called. See the comment in reflect.go for details. Fixes #49049 Change-Id: I0be74b6e727c1ecefedae072b149f59d539dc1e9 Reviewed-on: https://go-review.googlesource.com/c/go/+/357835 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Cherry Mui Reviewed-by: Dan Scales Reviewed-by: Cuong Manh Le --- .../compile/internal/reflectdata/reflect.go | 28 ++++++- src/cmd/compile/internal/walk/expr.go | 12 +-- src/cmd/internal/objabi/reloctype.go | 5 ++ src/cmd/internal/objabi/reloctype_string.go | 79 ++++++++++--------- src/cmd/link/internal/ld/deadcode.go | 24 ++++-- test/typeparam/issue49049.go | 27 +++++++ 6 files changed, 119 insertions(+), 56 deletions(-) create mode 100644 test/typeparam/issue49049.go diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 27e6188ab7..369ee75422 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -18,6 +18,7 @@ import ( "cmd/compile/internal/inline" "cmd/compile/internal/ir" "cmd/compile/internal/objw" + "cmd/compile/internal/staticdata" "cmd/compile/internal/typebits" "cmd/compile/internal/typecheck" "cmd/compile/internal/types" @@ -1995,8 +1996,33 @@ func MarkUsedIfaceMethod(n *ir.CallExpr) { dot := n.X.(*ir.SelectorExpr) ityp := dot.X.Type() if ityp.HasShape() { - base.Fatalf("marking method of shape type used %+v %s", ityp, dot.Sel.Name) + // Here we're calling a method on a generic interface. Something like: + // + // type I[T any] interface { foo() T } + // func f[T any](x I[T]) { + // ... = x.foo() + // } + // f[int](...) + // f[string](...) + // + // In this case, in f we're calling foo on a generic interface. + // Which method could that be? Normally we could match the method + // both by name and by type. But in this case we don't really know + // the type of the method we're calling. It could be func()int + // or func()string. So we match on just the function name, instead + // of both the name and the type used for the non-generic case below. + // TODO: instantiations at least know the shape of the instantiated + // type, and the linker could do more complicated matching using + // some sort of fuzzy shape matching. For now, only use the name + // of the method for matching. + r := obj.Addrel(ir.CurFunc.LSym) + // We use a separate symbol just to tell the linker the method name. + // (The symbol itself is not needed in the final binary.) + r.Sym = staticdata.StringSym(src.NoXPos, dot.Sel.Name) + r.Type = objabi.R_USEGENERICIFACEMETHOD + return } + tsym := TypeLinksym(ityp) r := obj.Addrel(ir.CurFunc.LSym) r.Sym = tsym diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go index c452cecbed..e5bf6cf0b5 100644 --- a/src/cmd/compile/internal/walk/expr.go +++ b/src/cmd/compile/internal/walk/expr.go @@ -506,17 +506,7 @@ func walkCall(n *ir.CallExpr, init *ir.Nodes) ir.Node { usemethod(n) } if n.Op() == ir.OCALLINTER { - if n.X.(*ir.SelectorExpr).X.Type().HasShape() { - // There should be an entry in n.KeepAlive to keep the - // dictionary alive (added in ../noder/transformCall). - // The dictionary in turn marks the method as used. - if len(n.KeepAlive) == 0 { - // TODO(khr): this fails for issue44688.go. - //base.Fatalf("KeepAlive of dictionary arg missing") - } - } else { - reflectdata.MarkUsedIfaceMethod(n) - } + reflectdata.MarkUsedIfaceMethod(n) } if n.Op() == ir.OCALLFUNC && n.X.Op() == ir.OCLOSURE { diff --git a/src/cmd/internal/objabi/reloctype.go b/src/cmd/internal/objabi/reloctype.go index 0cc60fbe3b..a9c3030181 100644 --- a/src/cmd/internal/objabi/reloctype.go +++ b/src/cmd/internal/objabi/reloctype.go @@ -93,6 +93,11 @@ const ( // This is a marker relocation (0-sized), for the linker's reachabililty // analysis. R_USEIFACEMETHOD + // Similar to R_USEIFACEMETHOD, except instead of indicating a type + + // method offset with Sym+Add, Sym points to a symbol containing the name + // of the method being called. See the description in + // cmd/compile/internal/reflectdata/reflect.go:MarkUsedIfaceMethod for details. + R_USEGENERICIFACEMETHOD // R_METHODOFF resolves to a 32-bit offset from the beginning of the section // holding the data being relocated to the referenced symbol. // It is a variant of R_ADDROFF used when linking from the uncommonType of a diff --git a/src/cmd/internal/objabi/reloctype_string.go b/src/cmd/internal/objabi/reloctype_string.go index f2e06a5b21..d1b15b5a19 100644 --- a/src/cmd/internal/objabi/reloctype_string.go +++ b/src/cmd/internal/objabi/reloctype_string.go @@ -32,48 +32,49 @@ func _() { _ = x[R_USETYPE-22] _ = x[R_USEIFACE-23] _ = x[R_USEIFACEMETHOD-24] - _ = x[R_METHODOFF-25] - _ = x[R_KEEP-26] - _ = x[R_POWER_TOC-27] - _ = x[R_GOTPCREL-28] - _ = x[R_JMPMIPS-29] - _ = x[R_DWARFSECREF-30] - _ = x[R_DWARFFILEREF-31] - _ = x[R_ARM64_TLS_LE-32] - _ = x[R_ARM64_TLS_IE-33] - _ = x[R_ARM64_GOTPCREL-34] - _ = x[R_ARM64_GOT-35] - _ = x[R_ARM64_PCREL-36] - _ = x[R_ARM64_LDST8-37] - _ = x[R_ARM64_LDST16-38] - _ = x[R_ARM64_LDST32-39] - _ = x[R_ARM64_LDST64-40] - _ = x[R_ARM64_LDST128-41] - _ = x[R_POWER_TLS_LE-42] - _ = x[R_POWER_TLS_IE-43] - _ = x[R_POWER_TLS-44] - _ = x[R_ADDRPOWER_DS-45] - _ = x[R_ADDRPOWER_GOT-46] - _ = x[R_ADDRPOWER_PCREL-47] - _ = x[R_ADDRPOWER_TOCREL-48] - _ = x[R_ADDRPOWER_TOCREL_DS-49] - _ = x[R_RISCV_CALL-50] - _ = x[R_RISCV_CALL_TRAMP-51] - _ = x[R_RISCV_PCREL_ITYPE-52] - _ = x[R_RISCV_PCREL_STYPE-53] - _ = x[R_RISCV_TLS_IE_ITYPE-54] - _ = x[R_RISCV_TLS_IE_STYPE-55] - _ = x[R_PCRELDBL-56] - _ = x[R_ADDRMIPSU-57] - _ = x[R_ADDRMIPSTLS-58] - _ = x[R_ADDRCUOFF-59] - _ = x[R_WASMIMPORT-60] - _ = x[R_XCOFFREF-61] + _ = x[R_USEGENERICIFACEMETHOD-25] + _ = x[R_METHODOFF-26] + _ = x[R_KEEP-27] + _ = x[R_POWER_TOC-28] + _ = x[R_GOTPCREL-29] + _ = x[R_JMPMIPS-30] + _ = x[R_DWARFSECREF-31] + _ = x[R_DWARFFILEREF-32] + _ = x[R_ARM64_TLS_LE-33] + _ = x[R_ARM64_TLS_IE-34] + _ = x[R_ARM64_GOTPCREL-35] + _ = x[R_ARM64_GOT-36] + _ = x[R_ARM64_PCREL-37] + _ = x[R_ARM64_LDST8-38] + _ = x[R_ARM64_LDST16-39] + _ = x[R_ARM64_LDST32-40] + _ = x[R_ARM64_LDST64-41] + _ = x[R_ARM64_LDST128-42] + _ = x[R_POWER_TLS_LE-43] + _ = x[R_POWER_TLS_IE-44] + _ = x[R_POWER_TLS-45] + _ = x[R_ADDRPOWER_DS-46] + _ = x[R_ADDRPOWER_GOT-47] + _ = x[R_ADDRPOWER_PCREL-48] + _ = x[R_ADDRPOWER_TOCREL-49] + _ = x[R_ADDRPOWER_TOCREL_DS-50] + _ = x[R_RISCV_CALL-51] + _ = x[R_RISCV_CALL_TRAMP-52] + _ = x[R_RISCV_PCREL_ITYPE-53] + _ = x[R_RISCV_PCREL_STYPE-54] + _ = x[R_RISCV_TLS_IE_ITYPE-55] + _ = x[R_RISCV_TLS_IE_STYPE-56] + _ = x[R_PCRELDBL-57] + _ = x[R_ADDRMIPSU-58] + _ = x[R_ADDRMIPSTLS-59] + _ = x[R_ADDRCUOFF-60] + _ = x[R_WASMIMPORT-61] + _ = x[R_XCOFFREF-62] } -const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_METHODOFFR_KEEPR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_RISCV_CALLR_RISCV_CALL_TRAMPR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IE_ITYPER_RISCV_TLS_IE_STYPER_PCRELDBLR_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREF" +const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_USEGENERICIFACEMETHODR_METHODOFFR_KEEPR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_RISCV_CALLR_RISCV_CALL_TRAMPR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IE_ITYPER_RISCV_TLS_IE_STYPER_PCRELDBLR_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREF" -var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 53, 59, 68, 79, 88, 99, 109, 116, 123, 131, 139, 147, 153, 159, 165, 175, 184, 194, 210, 221, 227, 238, 248, 257, 270, 284, 298, 312, 328, 339, 352, 365, 379, 393, 407, 422, 436, 450, 461, 475, 490, 507, 525, 546, 558, 576, 595, 614, 634, 654, 664, 675, 688, 699, 711, 721} +var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 53, 59, 68, 79, 88, 99, 109, 116, 123, 131, 139, 147, 153, 159, 165, 175, 184, 194, 210, 233, 244, 250, 261, 271, 280, 293, 307, 321, 335, 351, 362, 375, 388, 402, 416, 430, 445, 459, 473, 484, 498, 513, 530, 548, 569, 581, 599, 618, 637, 657, 677, 687, 698, 711, 722, 734, 744} func (i RelocType) String() string { i -= 1 diff --git a/src/cmd/link/internal/ld/deadcode.go b/src/cmd/link/internal/ld/deadcode.go index 79acd73387..7b57a85cde 100644 --- a/src/cmd/link/internal/ld/deadcode.go +++ b/src/cmd/link/internal/ld/deadcode.go @@ -22,10 +22,11 @@ type deadcodePass struct { ldr *loader.Loader wq heap // work queue, using min-heap for better locality - ifaceMethod map[methodsig]bool // methods declared in reached interfaces - markableMethods []methodref // methods of reached types - reflectSeen bool // whether we have seen a reflect method call - dynlink bool + ifaceMethod map[methodsig]bool // methods called from reached interface call sites + genericIfaceMethod map[string]bool // names of methods called from reached generic interface call sites + markableMethods []methodref // methods of reached types + reflectSeen bool // whether we have seen a reflect method call + dynlink bool methodsigstmp []methodsig // scratch buffer for decoding method signatures } @@ -33,6 +34,7 @@ type deadcodePass struct { func (d *deadcodePass) init() { d.ldr.InitReachable() d.ifaceMethod = make(map[methodsig]bool) + d.genericIfaceMethod = make(map[string]bool) if buildcfg.Experiment.FieldTrack { d.ldr.Reachparent = make([]loader.Sym, d.ldr.NSym()) } @@ -197,6 +199,13 @@ func (d *deadcodePass) flood() { } d.ifaceMethod[m] = true continue + case objabi.R_USEGENERICIFACEMETHOD: + name := d.decodeGenericIfaceMethod(d.ldr, r.Sym()) + if d.ctxt.Debugvlog > 1 { + d.ctxt.Logf("reached generic iface method: %s\n", name) + } + d.genericIfaceMethod[name] = true + continue // don't mark referenced symbol - it is not needed in the final binary. } rs := r.Sym() if isgotype && usedInIface && d.ldr.IsGoType(rs) && !d.ldr.AttrUsedInIface(rs) { @@ -352,7 +361,7 @@ func deadcode(ctxt *Link) { // in the last pass. rem := d.markableMethods[:0] for _, m := range d.markableMethods { - if (d.reflectSeen && m.isExported()) || d.ifaceMethod[m.m] { + if (d.reflectSeen && m.isExported()) || d.ifaceMethod[m.m] || d.genericIfaceMethod[m.m.name] { d.markMethod(m) } else { rem = append(rem, m) @@ -425,6 +434,11 @@ func (d *deadcodePass) decodeIfaceMethod(ldr *loader.Loader, arch *sys.Arch, sym return m } +// Decode the method name stored in symbol symIdx. The symbol should contain just the bytes of a method name. +func (d *deadcodePass) decodeGenericIfaceMethod(ldr *loader.Loader, symIdx loader.Sym) string { + return string(ldr.Data(symIdx)) +} + func (d *deadcodePass) decodetypeMethods(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, relocs *loader.Relocs) []methodsig { p := ldr.Data(symIdx) if !decodetypeHasUncommon(arch, p) { diff --git a/test/typeparam/issue49049.go b/test/typeparam/issue49049.go new file mode 100644 index 0000000000..f4fdd05d85 --- /dev/null +++ b/test/typeparam/issue49049.go @@ -0,0 +1,27 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type A[T any] interface { + m() +} + +type Z struct { + a,b int +} + +func (z *Z) m() { +} + +func test[T any]() { + var a A[T] = &Z{} + f := a.m + f() +} +func main() { + test[string]() +} -- GitLab From 0ae0d5c62eae1a4043d1d9cb41acc563a5e75daa Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 21 Oct 2021 19:15:24 -0700 Subject: [PATCH 1729/2500] cmd/compile: remove MarkUsedIfaceMethodIndex mechanism We don't need it any more, after CL 357835. Change-Id: I1ff5f24b5540c3e80c4b35be8215a1c378952274 Reviewed-on: https://go-review.googlesource.com/c/go/+/357894 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 28 ++++--------------- .../compile/internal/reflectdata/reflect.go | 10 ------- 2 files changed, 5 insertions(+), 33 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 474a05973a..fc5b0eefd4 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1523,18 +1523,12 @@ func deref(t *types.Type) *types.Type { // needed methods. func markTypeUsed(t *types.Type, lsym *obj.LSym) { if t.IsInterface() { - // Mark all the methods of the interface as used. - // TODO: we should really only mark the interface methods - // that are actually called in the application. - for i, _ := range t.AllMethods().Slice() { - reflectdata.MarkUsedIfaceMethodIndex(lsym, t, i) - } - } else { - // TODO: This is somewhat overkill, we really only need it - // for types that are put into interfaces. - // Note: this relocation is also used in cmd/link/internal/ld/dwarf.go - reflectdata.MarkTypeUsedInInterface(t, lsym) + return } + // TODO: This is somewhat overkill, we really only need it + // for types that are put into interfaces. + // Note: this relocation is also used in cmd/link/internal/ld/dwarf.go + reflectdata.MarkTypeUsedInInterface(t, lsym) } // getDictionarySym returns the dictionary for the named generic function gf, which @@ -1735,18 +1729,6 @@ func (g *genInst) finalizeSyms() { se := n.(*ir.SelectorExpr) srctype = subst.Typ(se.X.Type()) dsttype = subst.Typ(info.shapeToBound[se.X.Type()]) - found := false - for i, m := range dsttype.AllMethods().Slice() { - if se.Sel == m.Sym { - // Mark that this method se.Sel is - // used for the dsttype interface, so - // it won't get deadcoded. - reflectdata.MarkUsedIfaceMethodIndex(lsym, dsttype, i) - found = true - break - } - } - assert(found) case ir.ODOTTYPE, ir.ODOTTYPE2: srctype = subst.Typ(n.(*ir.TypeAssertExpr).Type()) dsttype = subst.Typ(n.(*ir.TypeAssertExpr).X.Type()) diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 369ee75422..b4ed96c18a 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -2033,16 +2033,6 @@ func MarkUsedIfaceMethod(n *ir.CallExpr) { r.Type = objabi.R_USEIFACEMETHOD } -// MarkUsedIfaceMethodIndex marks that that method number ix (in the AllMethods list) -// of interface type ityp is used, and should be attached to lsym. -func MarkUsedIfaceMethodIndex(lsym *obj.LSym, ityp *types.Type, ix int) { - tsym := TypeLinksym(ityp) - r := obj.Addrel(lsym) - r.Sym = tsym - r.Add = InterfaceMethodOffset(ityp, int64(ix)) - r.Type = objabi.R_USEIFACEMETHOD -} - // getDictionary returns the dictionary for the given named generic function // or method, with the given type arguments. func getDictionary(gf *types.Sym, targs []*types.Type) ir.Node { -- GitLab From 72b6a89ca5cd3c3bfd13b9b17be976e8feb91ecc Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 21 Oct 2021 18:09:07 -0700 Subject: [PATCH 1730/2500] cmd/compile: revert most of CL 349169 The method of using references to dictionaries to hold methods live during linker deadcode elimination wasn't working very well. I implemented a new scheme in the CL below this, so this CL strips out the old method. The new method has the added benefit of having 0 runtime overhead (unlike the stuff we're ripping out here, which does have a small overhead). Update #48047 Change-Id: I68ac57119792d53c58f1480f407de6ab2bb53211 Reviewed-on: https://go-review.googlesource.com/c/go/+/357836 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/helpers.go | 2 +- src/cmd/compile/internal/noder/stencil.go | 20 ++++++++++---------- src/cmd/compile/internal/noder/transform.go | 15 +-------------- 3 files changed, 12 insertions(+), 25 deletions(-) diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index adb5a0e89f..5524673e66 100644 --- a/src/cmd/compile/internal/noder/helpers.go +++ b/src/cmd/compile/internal/noder/helpers.go @@ -183,7 +183,7 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) // If no type params, do the normal call transformations. This // will convert OCALL to OCALLFUNC. typed(typ, n) - transformCall(n, nil) + transformCall(n) return n } diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index fc5b0eefd4..68032e7082 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -185,7 +185,7 @@ func (g *genInst) scanForGenCalls(decl ir.Node) { // it before installing the instantiation, so we are // checking against non-shape param types in // typecheckaste. - transformCall(call, nil) + transformCall(call) // Replace the OFUNCINST with a direct reference to the // new stenciled function @@ -223,7 +223,7 @@ func (g *genInst) scanForGenCalls(decl ir.Node) { // Transform the Call now, which changes OCALL // to OCALLFUNC and does typecheckaste/assignconvfn. - transformCall(call, nil) + transformCall(call) st := g.getInstantiation(gf, targs, true).fun dictValue, usingSubdict := g.getDictOrSubdict(declInfo, n, gf, targs, true) @@ -1089,14 +1089,14 @@ func (subst *subster) node(n ir.Node) ir.Node { // transform the call. call.X.(*ir.SelectorExpr).SetOp(ir.OXDOT) transformDot(call.X.(*ir.SelectorExpr), true) - transformCall(call, subst.info.dictParam) + transformCall(call) case ir.ODOT, ir.ODOTPTR: // An OXDOT for a generic receiver was resolved to // an access to a field which has a function // value. Transform the call to that function, now // that the OXDOT was resolved. - transformCall(call, subst.info.dictParam) + transformCall(call) case ir.ONAME: name := call.X.Name() @@ -1113,24 +1113,24 @@ func (subst *subster) node(n ir.Node) ir.Node { // This is the case of a function value that was a // type parameter (implied to be a function via a // structural constraint) which is now resolved. - transformCall(call, subst.info.dictParam) + transformCall(call) } case ir.OCLOSURE: - transformCall(call, subst.info.dictParam) + transformCall(call) case ir.ODEREF, ir.OINDEX, ir.OINDEXMAP, ir.ORECV: // Transform a call that was delayed because of the // use of typeparam inside an expression that required // a pointer dereference, array indexing, map indexing, // or channel receive to compute function value. - transformCall(call, subst.info.dictParam) + transformCall(call) case ir.OCALL, ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER: - transformCall(call, subst.info.dictParam) + transformCall(call) case ir.OCONVNOP: - transformCall(call, subst.info.dictParam) + transformCall(call) case ir.OFUNCINST: // A call with an OFUNCINST will get transformed @@ -1276,7 +1276,7 @@ func (g *genInst) dictPass(info *instInfo) { m.(*ir.CallExpr).X.(*ir.SelectorExpr).SetOp(ir.OXDOT) transformDot(m.(*ir.CallExpr).X.(*ir.SelectorExpr), true) } - transformCall(m.(*ir.CallExpr), info.dictParam) + transformCall(m.(*ir.CallExpr)) } case ir.OCONVIFACE: diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index 29ee601d82..47e6397206 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -132,9 +132,7 @@ func transformConvCall(n *ir.CallExpr) ir.Node { // transformCall transforms a normal function/method call. Corresponds to last half // (non-conversion, non-builtin part) of typecheck.tcCall. This code should work even // in the case of OCALL/OFUNCINST. -// The dict parameter is used for OCALLINTER nodes to ensure that the called method -// is retained by the linker. -func transformCall(n *ir.CallExpr, dict *ir.Name) { +func transformCall(n *ir.CallExpr) { // n.Type() can be nil for calls with no return value assert(n.Typecheck() == 1) transformArgs(n) @@ -144,17 +142,6 @@ func transformCall(n *ir.CallExpr, dict *ir.Name) { switch l.Op() { case ir.ODOTINTER: n.SetOp(ir.OCALLINTER) - if n.X.(*ir.SelectorExpr).X.Type().HasShape() { - if dict == nil { - base.Fatalf("calls on shape interfaces need a dictionary reference") - } - dict.SetAddrtaken(true) - // KeepAlive isn't exactly the right thing here, as we only - // need to keep the dictionary live in the linker-deadcode - // sense, not the at-runtime sense. But the at-runtime sense - // is stronger, so it works. See issue 48047. - n.KeepAlive = append(n.KeepAlive, dict) - } case ir.ODOTMETH: l := l.(*ir.SelectorExpr) -- GitLab From f92c8f07ace7ae67b95e59bbb6ae6928dd6e4773 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 21 Oct 2021 18:28:50 -0700 Subject: [PATCH 1731/2500] cmd/link: escape % characters in symbols when reporting errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generic function symbols sometimes have % in them, like: main.B2[%2eshape.string_0].m2·f Which confuses this code because it doesn't esacpe % when using this string as a format string, instead of a format argument. Or could we get rid of the . -> %2e rewrite somehow? I think it comes from LinkString. Change-Id: I3275501f44cf30485e9d4577e0dfa77996d4939e Reviewed-on: https://go-review.googlesource.com/c/go/+/357837 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/link/internal/loader/loader.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index 9b7888e940..34c1c6a4c8 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -2592,7 +2592,9 @@ type ErrorReporter struct { // func (reporter *ErrorReporter) Errorf(s Sym, format string, args ...interface{}) { if s != 0 && reporter.ldr.SymName(s) != "" { - format = reporter.ldr.SymName(s) + ": " + format + // Note: Replace is needed here because symbol names might have % in them, + // due to the use of LinkString for names of instantiating types. + format = strings.Replace(reporter.ldr.SymName(s), "%", "%%", -1) + ": " + format } else { format = fmt.Sprintf("sym %d: %s", s, format) } -- GitLab From e35b5b25d976efb7c00b871cac452b84193e6179 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Mon, 25 Oct 2021 16:48:07 -0400 Subject: [PATCH 1732/2500] cmd/compile: fix typo in comment in CL 358435 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I0d8128668fc7a80b29aabc58dbc9a2929b889ec9 Reviewed-on: https://go-review.googlesource.com/c/go/+/358614 Trust: Cherry Mui Trust: Daniel Martí Reviewed-by: Daniel Martí --- src/cmd/compile/internal/ssa/regalloc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index 126973a6e1..91b04e99f4 100644 --- a/src/cmd/compile/internal/ssa/regalloc.go +++ b/src/cmd/compile/internal/ssa/regalloc.go @@ -560,7 +560,7 @@ func isLeaf(f *Func) bool { for _, b := range f.Blocks { for _, v := range b.Values { if v.Op.IsCall() && !v.Op.IsTailCall() { - // tail call is not counted as it does not save retur PC or need a frame + // tail call is not counted as it does not save the return PC or need a frame return false } } -- GitLab From 60c3069dd82eee30c00f2a8d829ba74b11bcf07e Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 22 Oct 2021 14:19:34 -0700 Subject: [PATCH 1733/2500] internal/poll: avoid tiny allocator for splicePipe We want to set a finalizer on splicePipe, so make it large enough to not use the tiny allocator. Otherwise the finalizer will not run until the rest of the tiny allocation can be freed. This only matters on 32-bit systems. Fixes #48968 Change-Id: I8eb3c9f48fdccab7dc79c5b918d4257b6151ee91 Reviewed-on: https://go-review.googlesource.com/c/go/+/358114 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/internal/poll/splice_linux.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/internal/poll/splice_linux.go b/src/internal/poll/splice_linux.go index 8062d98fae..6869a40b24 100644 --- a/src/internal/poll/splice_linux.go +++ b/src/internal/poll/splice_linux.go @@ -158,6 +158,10 @@ type splicePipe struct { rfd int wfd int data int + + // We want to use a finalizer, so ensure that the size is + // large enough to not use the tiny allocator. + _ [24 - 3*unsafe.Sizeof(int(0))]byte } // splicePipePool caches pipes to avoid high-frequency construction and destruction of pipe buffers. -- GitLab From 85b3b4ee036e7460bf7621f64c6781e5dd0eed98 Mon Sep 17 00:00:00 2001 From: fanzha02 Date: Mon, 4 Jan 2021 17:14:35 +0800 Subject: [PATCH 1734/2500] cmd/compile: add -asan option The -asan option causes the compiler to add instrumentation for the C/C++ address sanitizer. Every memory read/write will be replaced by a call to asanread/asanwrite. This CL also inserts asan instrumentation during SSA building. This CL passes tests but is not usable by itself. The actual implementation of asanread/asanwrite in the runtime package, and support for -asan in the go tool and tests, will follow in subsequent CLs. Updates #44853. Change-Id: Ia18c9c5d5c351857420d2f6835f0daec2ad31096 Reviewed-on: https://go-review.googlesource.com/c/go/+/298611 Trust: fannie zhang Run-TryBot: fannie zhang TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/cmd/compile/doc.go | 2 ++ src/cmd/compile/internal/base/base.go | 1 + src/cmd/compile/internal/base/flag.go | 16 ++++++++++++---- src/cmd/compile/internal/gc/main.go | 5 +++-- src/cmd/compile/internal/ir/func.go | 2 +- src/cmd/compile/internal/ir/symtab.go | 2 ++ src/cmd/compile/internal/noder/import.go | 2 ++ .../compile/internal/reflectdata/reflect.go | 3 +++ src/cmd/compile/internal/ssagen/ssa.go | 18 +++++++++++++++--- src/cmd/compile/internal/typecheck/builtin.go | 2 ++ .../internal/typecheck/builtin/runtime.go | 4 ++++ src/cmd/internal/sys/supported.go | 11 +++++++++++ 12 files changed, 58 insertions(+), 10 deletions(-) diff --git a/src/cmd/compile/doc.go b/src/cmd/compile/doc.go index b68ef274f3..ef7fa86749 100644 --- a/src/cmd/compile/doc.go +++ b/src/cmd/compile/doc.go @@ -44,6 +44,8 @@ Flags: Print compiler version and exit. -asmhdr file Write assembly header to file. + -asan + Insert calls to C/C++ address sanitizer. -buildid id Record id as the build id in the export metadata. -blockprofile file diff --git a/src/cmd/compile/internal/base/base.go b/src/cmd/compile/internal/base/base.go index 4c2516f60e..be6d49fac7 100644 --- a/src/cmd/compile/internal/base/base.go +++ b/src/cmd/compile/internal/base/base.go @@ -67,6 +67,7 @@ var NoInstrumentPkgs = []string{ "runtime", "runtime/race", "runtime/msan", + "runtime/asan", "internal/cpu", } diff --git a/src/cmd/compile/internal/base/flag.go b/src/cmd/compile/internal/base/flag.go index 241f5da185..51938e8fd5 100644 --- a/src/cmd/compile/internal/base/flag.go +++ b/src/cmd/compile/internal/base/flag.go @@ -84,6 +84,7 @@ type CmdFlags struct { // Longer names AsmHdr string "help:\"write assembly header to `file`\"" + ASan bool "help:\"build code compatible with C/C++ address sanitizer\"" Bench string "help:\"append benchmark times to `file`\"" BlockProfile string "help:\"write block profile to `file`\"" BuildID string "help:\"record `id` as the build id in the export metadata\"" @@ -177,6 +178,9 @@ func ParseFlags() { if Flag.MSan && !sys.MSanSupported(buildcfg.GOOS, buildcfg.GOARCH) { log.Fatalf("%s/%s does not support -msan", buildcfg.GOOS, buildcfg.GOARCH) } + if Flag.ASan && !sys.ASanSupported(buildcfg.GOOS, buildcfg.GOARCH) { + log.Fatalf("%s/%s does not support -asan", buildcfg.GOOS, buildcfg.GOARCH) + } if Flag.Race && !sys.RaceDetectorSupported(buildcfg.GOOS, buildcfg.GOARCH) { log.Fatalf("%s/%s does not support -race", buildcfg.GOOS, buildcfg.GOARCH) } @@ -217,12 +221,16 @@ func ParseFlags() { } Flag.LowerO = p + suffix } - - if Flag.Race && Flag.MSan { + switch { + case Flag.Race && Flag.MSan: log.Fatal("cannot use both -race and -msan") + case Flag.Race && Flag.ASan: + log.Fatal("cannot use both -race and -asan") + case Flag.MSan && Flag.ASan: + log.Fatal("cannot use both -msan and -asan") } - if Flag.Race || Flag.MSan { - // -race and -msan imply -d=checkptr for now. + if Flag.Race || Flag.MSan || Flag.ASan { + // -race, -msan and -asan imply -d=checkptr for now. if Debug.Checkptr == -1 { // if not set explicitly Debug.Checkptr = 1 } diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 74b21571b3..ed81ef7bc0 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -107,7 +107,7 @@ func Main(archInit func(*ssagen.ArchInfo)) { // Record flags that affect the build result. (And don't // record flags that don't, since that would cause spurious // changes in the binary.) - dwarfgen.RecordFlags("B", "N", "l", "msan", "race", "shared", "dynlink", "dwarf", "dwarflocationlists", "dwarfbasentries", "smallframes", "spectre") + dwarfgen.RecordFlags("B", "N", "l", "msan", "race", "asan", "shared", "dynlink", "dwarf", "dwarflocationlists", "dwarfbasentries", "smallframes", "spectre") if !base.EnableTrace && base.Flag.LowerT { log.Fatalf("compiler not built with support for -t") @@ -149,11 +149,12 @@ func Main(archInit func(*ssagen.ArchInfo)) { if base.Compiling(base.NoInstrumentPkgs) { base.Flag.Race = false base.Flag.MSan = false + base.Flag.ASan = false } ssagen.Arch.LinkArch.Init(base.Ctxt) startProfile() - if base.Flag.Race || base.Flag.MSan { + if base.Flag.Race || base.Flag.MSan || base.Flag.ASan { base.Flag.Cfg.Instrumenting = true } if base.Flag.Dwarf { diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go index 18d0b023ad..41c96079f7 100644 --- a/src/cmd/compile/internal/ir/func.go +++ b/src/cmd/compile/internal/ir/func.go @@ -201,7 +201,7 @@ const ( funcNilCheckDisabled // disable nil checks when compiling this function funcInlinabilityChecked // inliner has already determined whether the function is inlinable funcExportInline // include inline body in export data - funcInstrumentBody // add race/msan instrumentation during SSA construction + funcInstrumentBody // add race/msan/asan instrumentation during SSA construction funcOpenCodedDeferDisallowed // can't do open-coded defers funcClosureCalled // closure is only immediately called; used by escape analysis ) diff --git a/src/cmd/compile/internal/ir/symtab.go b/src/cmd/compile/internal/ir/symtab.go index 1435e4313e..b204a1d544 100644 --- a/src/cmd/compile/internal/ir/symtab.go +++ b/src/cmd/compile/internal/ir/symtab.go @@ -15,6 +15,8 @@ var Syms struct { AssertE2I2 *obj.LSym AssertI2I *obj.LSym AssertI2I2 *obj.LSym + Asanread *obj.LSym + Asanwrite *obj.LSym CheckPtrAlignment *obj.LSym Deferproc *obj.LSym DeferprocStack *obj.LSym diff --git a/src/cmd/compile/internal/noder/import.go b/src/cmd/compile/internal/noder/import.go index 0aaf894641..58dffbad1e 100644 --- a/src/cmd/compile/internal/noder/import.go +++ b/src/cmd/compile/internal/noder/import.go @@ -127,6 +127,8 @@ func openPackage(path string) (*os.File, error) { suffix = "_race" } else if base.Flag.MSan { suffix = "_msan" + } else if base.Flag.ASan { + suffix = "_asan" } if file, err := os.Open(fmt.Sprintf("%s/pkg/%s_%s%s/%s.a", buildcfg.GOROOT, buildcfg.GOOS, buildcfg.GOARCH, suffix, path)); err == nil { diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index b4ed96c18a..ce41b8c934 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -1413,6 +1413,9 @@ func WriteBasicTypes() { if base.Flag.MSan { dimportpath(types.NewPkg("runtime/msan", "")) } + if base.Flag.ASan { + dimportpath(types.NewPkg("runtime/asan", "")) + } dimportpath(types.NewPkg("main", "")) } diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 5a958a569d..6b595ea75d 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -108,6 +108,8 @@ func InitConfig() { ir.Syms.Msanread = typecheck.LookupRuntimeFunc("msanread") ir.Syms.Msanwrite = typecheck.LookupRuntimeFunc("msanwrite") ir.Syms.Msanmove = typecheck.LookupRuntimeFunc("msanmove") + ir.Syms.Asanread = typecheck.LookupRuntimeFunc("asanread") + ir.Syms.Asanwrite = typecheck.LookupRuntimeFunc("asanwrite") ir.Syms.Newobject = typecheck.LookupRuntimeFunc("newobject") ir.Syms.Newproc = typecheck.LookupRuntimeFunc("newproc") ir.Syms.Panicdivide = typecheck.LookupRuntimeFunc("panicdivide") @@ -1245,10 +1247,10 @@ func (s *state) instrument(t *types.Type, addr *ssa.Value, kind instrumentKind) } // instrumentFields instruments a read/write operation on addr. -// If it is instrumenting for MSAN and t is a struct type, it instruments +// If it is instrumenting for MSAN or ASAN and t is a struct type, it instruments // operation for each field, instead of for the whole struct. func (s *state) instrumentFields(t *types.Type, addr *ssa.Value, kind instrumentKind) { - if !base.Flag.MSan || !t.IsStruct() { + if !(base.Flag.MSan || base.Flag.ASan) || !t.IsStruct() { s.instrument(t, addr, kind) return } @@ -1327,6 +1329,16 @@ func (s *state) instrument2(t *types.Type, addr, addr2 *ssa.Value, kind instrume default: panic("unreachable") } + } else if base.Flag.ASan { + switch kind { + case instrumentRead: + fn = ir.Syms.Asanread + case instrumentWrite: + fn = ir.Syms.Asanwrite + default: + panic("unreachable") + } + needWidth = true } else { panic("unreachable") } @@ -3002,7 +3014,7 @@ func (s *state) exprCheckPtr(n ir.Node, checkPtrOK bool) *ssa.Value { } // If n is addressable and can't be represented in // SSA, then load just the selected field. This - // prevents false memory dependencies in race/msan + // prevents false memory dependencies in race/msan/asan // instrumentation. if ir.IsAddressable(n) && !s.canSSA(n) { p := s.addr(n) diff --git a/src/cmd/compile/internal/typecheck/builtin.go b/src/cmd/compile/internal/typecheck/builtin.go index 524360e8df..67597cebb4 100644 --- a/src/cmd/compile/internal/typecheck/builtin.go +++ b/src/cmd/compile/internal/typecheck/builtin.go @@ -192,6 +192,8 @@ var runtimeDecls = [...]struct { {"msanread", funcTag, 140}, {"msanwrite", funcTag, 140}, {"msanmove", funcTag, 141}, + {"asanread", funcTag, 140}, + {"asanwrite", funcTag, 140}, {"checkptrAlignment", funcTag, 142}, {"checkptrArithmetic", funcTag, 144}, {"libfuzzerTraceCmp1", funcTag, 145}, diff --git a/src/cmd/compile/internal/typecheck/builtin/runtime.go b/src/cmd/compile/internal/typecheck/builtin/runtime.go index 66641fb5aa..04ae4f23a3 100644 --- a/src/cmd/compile/internal/typecheck/builtin/runtime.go +++ b/src/cmd/compile/internal/typecheck/builtin/runtime.go @@ -250,6 +250,10 @@ func msanread(addr, size uintptr) func msanwrite(addr, size uintptr) func msanmove(dst, src, size uintptr) +// address sanitizer +func asanread(addr, size uintptr) +func asanwrite(addr, size uintptr) + func checkptrAlignment(unsafe.Pointer, *byte, uintptr) func checkptrArithmetic(unsafe.Pointer, []unsafe.Pointer) diff --git a/src/cmd/internal/sys/supported.go b/src/cmd/internal/sys/supported.go index 0d2bad9612..e6c56fbc56 100644 --- a/src/cmd/internal/sys/supported.go +++ b/src/cmd/internal/sys/supported.go @@ -34,6 +34,17 @@ func MSanSupported(goos, goarch string) bool { } } +// ASanSupported reports whether goos/goarch supports the address +// sanitizer option. +func ASanSupported(goos, goarch string) bool { + switch goos { + case "linux": + return goarch == "arm64" || goarch == "amd64" + default: + return false + } +} + // MustLinkExternal reports whether goos/goarch requires external linking. // (This is the opposite of internal/testenv.CanInternalLink. Keep them in sync.) func MustLinkExternal(goos, goarch string) bool { -- GitLab From fd2f4b58b34effdbdacba41e0c36fa701c6dfa27 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 19 Oct 2021 13:28:54 -0700 Subject: [PATCH 1735/2500] cmd/compile: update the export version for generics Bump the export version to a new value iexportVersionGo1_18 (2). This will give a better error message when old compilers/tools encounter the new export format (that includes parameterized types and functions). We are also making a breaking change in the format: - a 'kind' byte is added to constant values Also updated tinter() to pass the implicit bit through during type substitution. Tested that all tests still pass if the iexportVersionCurrent is changed back to 1 in typecheck/iexport.go, iimporter/iimport.go, and gcimporter/iimport.go Updates #47654 Change-Id: I1dbeb167a97f6c7e0b7e0c011d6bada5db312b36 Reviewed-on: https://go-review.googlesource.com/c/go/+/357049 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Robert Findley Trust: Dan Scales --- src/cmd/compile/internal/importer/iimport.go | 36 ++++++++++++------ src/cmd/compile/internal/typecheck/iexport.go | 38 ++++++++++++------- src/cmd/compile/internal/typecheck/iimport.go | 32 ++++++++++------ src/cmd/compile/internal/typecheck/subr.go | 2 +- src/cmd/compile/internal/types/type.go | 6 +++ src/go/internal/gcimporter/iimport.go | 36 ++++++++++++------ 6 files changed, 101 insertions(+), 49 deletions(-) diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index cbc78539fd..d04ef5c34d 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -43,12 +43,12 @@ func (r *intReader) uint64() uint64 { // Keep this in sync with constants in iexport.go. const ( - iexportVersionGo1_11 = 0 - iexportVersionPosCol = 1 - // TODO: before release, change this back to 2. - iexportVersionGenerics = iexportVersionPosCol + iexportVersionGo1_11 = 0 + iexportVersionPosCol = 1 + iexportVersionGenerics = 1 // probably change to 2 before release + iexportVersionGo1_18 = 2 - iexportVersionCurrent = iexportVersionGenerics + iexportVersionCurrent = 2 ) type ident struct { @@ -99,13 +99,9 @@ func ImportData(imports map[string]*types2.Package, data, path string) (pkg *typ version = int64(r.uint64()) switch version { - case /* iexportVersionGenerics, */ iexportVersionPosCol, iexportVersionGo1_11: + case iexportVersionGo1_18, iexportVersionPosCol, iexportVersionGo1_11: default: - if version > iexportVersionGenerics { - errorf("unstable iexport format version %d, just rebuild compiler and std library", version) - } else { - errorf("unknown iexport format version %d", version) - } + errorf("unknown iexport format version %d", version) } sLen := int64(r.uint64()) @@ -374,7 +370,19 @@ func (r *importReader) obj(name string) { id := ident{r.currPkg.Name(), name} r.p.tparamIndex[id] = t - t.SetConstraint(r.typ()) + var implicit bool + if r.p.exportVersion >= iexportVersionGo1_18 { + implicit = r.bool() + } + constraint := r.typ() + if implicit { + iface, _ := constraint.(*types2.Interface) + if iface == nil { + errorf("non-interface constraint marked implicit") + } + iface.MarkImplicit() + } + t.SetConstraint(constraint) case 'V': typ := r.typ() @@ -392,6 +400,10 @@ func (r *importReader) declare(obj types2.Object) { func (r *importReader) value() (typ types2.Type, val constant.Value) { typ = r.typ() + if r.p.exportVersion >= iexportVersionGo1_18 { + // TODO: add support for using the kind + _ = constant.Kind(r.int64()) + } switch b := typ.Underlying().(*types2.Basic); b.Info() & types2.IsConstType { case types2.IsBoolean: diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 46865ba3fa..6057000a5d 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -254,15 +254,16 @@ import ( // Current indexed export format version. Increase with each format change. // 0: Go1.11 encoding // 1: added column details to Pos -// 2: added information for generic function/types (currently unstable) +// 2: added information for generic function/types. The export of non-generic +// functions/types remains largely backward-compatible. Breaking changes include: +// - a 'kind' byte is added to constant values const ( - iexportVersionGo1_11 = 0 - iexportVersionPosCol = 1 - // TODO: before release, change this back to 2. Kept at previous version - // for now (for testing). - iexportVersionGenerics = iexportVersionPosCol + iexportVersionGo1_11 = 0 + iexportVersionPosCol = 1 + iexportVersionGenerics = 1 // probably change to 2 before release + iexportVersionGo1_18 = 2 - iexportVersionCurrent = iexportVersionGenerics + iexportVersionCurrent = 2 ) // predeclReserved is the number of type offsets reserved for types @@ -561,6 +562,10 @@ func (p *iexporter) doDecl(n *ir.Name) { // A typeparam has a name, and has a type bound rather // than an underlying type. w.pos(n.Pos()) + if iexportVersionCurrent >= iexportVersionGo1_18 { + implicit := n.Type().Bound().IsImplicit() + w.bool(implicit) + } w.typ(n.Type().Bound()) break } @@ -1137,17 +1142,24 @@ func constTypeOf(typ *types.Type) constant.Kind { func (w *exportWriter) value(typ *types.Type, v constant.Value) { w.typ(typ) + + if iexportVersionCurrent >= iexportVersionGo1_18 { + w.int64(int64(v.Kind())) + } + var kind constant.Kind var valType *types.Type if typ.IsTypeParam() { - // A constant will have a TYPEPARAM type if it appears in a place - // where it must match that typeparam type (e.g. in a binary - // operation with a variable of that typeparam type). If so, then - // we must write out its actual constant kind as well, so its - // constant val can be read in properly during import. kind = v.Kind() - w.int64(int64(kind)) + if iexportVersionCurrent < iexportVersionGo1_18 { + // A constant will have a TYPEPARAM type if it appears in a place + // where it must match that typeparam type (e.g. in a binary + // operation with a variable of that typeparam type). If so, then + // we must write out its actual constant kind as well, so its + // constant val can be read in properly during import. + w.int64(int64(kind)) + } switch kind { case constant.Int: diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index fcfadc146c..7c6c23e737 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -118,13 +118,9 @@ func ReadImports(pkg *types.Pkg, data string) { version := ird.uint64() switch version { - case /* iexportVersionGenerics, */ iexportVersionPosCol, iexportVersionGo1_11: + case iexportVersionGo1_18, iexportVersionPosCol, iexportVersionGo1_11: default: - if version > iexportVersionGenerics { - base.Errorf("import %q: unstable export format version %d, just recompile", pkg.Path, version) - } else { - base.Errorf("import %q: unknown export format version %d", pkg.Path, version) - } + base.Errorf("import %q: unknown export format version %d", pkg.Path, version) base.ErrorExit() } @@ -408,8 +404,15 @@ func (r *importReader) doDecl(sym *types.Sym) *ir.Name { sym.Def = nname nname.SetType(t) t.SetNod(nname) - - t.SetBound(r.typ()) + implicit := false + if r.p.exportVersion >= iexportVersionGo1_18 { + implicit = r.bool() + } + bound := r.typ() + if implicit { + bound.MarkImplicit() + } + t.SetBound(bound) return nname case 'V': @@ -429,10 +432,17 @@ func (r *importReader) value(typ *types.Type) constant.Value { var kind constant.Kind var valType *types.Type - if typ.IsTypeParam() { - // If a constant had a typeparam type, then we wrote out its - // actual constant kind as well. + if r.p.exportVersion >= iexportVersionGo1_18 { + // TODO: add support for using the kind in the non-typeparam case. kind = constant.Kind(r.int64()) + } + + if typ.IsTypeParam() { + if r.p.exportVersion < iexportVersionGo1_18 { + // If a constant had a typeparam type, then we wrote out its + // actual constant kind as well. + kind = constant.Kind(r.int64()) + } switch kind { case constant.Int: valType = types.Types[types.TINT64] diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 9ebd8f1423..96e120fe03 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1390,7 +1390,7 @@ func (ts *Tsubster) tinter(t *types.Type, force bool) *types.Type { } } if newfields != nil { - return types.NewInterface(t.Pkg(), newfields, false) + return types.NewInterface(t.Pkg(), newfields, t.IsImplicit()) } return t } diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index ec17fe8704..c3efbc9f07 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -1884,6 +1884,12 @@ func (t *Type) IsImplicit() bool { return t.extra.(*Interface).implicit } +// MarkImplicit marks the interface as implicit. +func (t *Type) MarkImplicit() { + t.wantEtype(TINTER) + t.extra.(*Interface).implicit = true +} + // NewUnion returns a new union with the specified set of terms (types). If // tildes[i] is true, then terms[i] represents ~T, rather than just T. func NewUnion(terms []*Type, tildes []bool) *Type { diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go index 0771fa3c26..49ea64392a 100644 --- a/src/go/internal/gcimporter/iimport.go +++ b/src/go/internal/gcimporter/iimport.go @@ -44,12 +44,12 @@ func (r *intReader) uint64() uint64 { // Keep this in sync with constants in iexport.go. const ( - iexportVersionGo1_11 = 0 - iexportVersionPosCol = 1 - // TODO: before release, change this back to 2. - iexportVersionGenerics = iexportVersionPosCol + iexportVersionGo1_11 = 0 + iexportVersionPosCol = 1 + iexportVersionGenerics = 1 // probably change to 2 before release + iexportVersionGo1_18 = 2 - iexportVersionCurrent = iexportVersionGenerics + iexportVersionCurrent = 2 ) type ident struct { @@ -98,13 +98,9 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, dataRea version = int64(r.uint64()) switch version { - case /* iexportVersionGenerics, */ iexportVersionPosCol, iexportVersionGo1_11: + case iexportVersionGo1_18, iexportVersionPosCol, iexportVersionGo1_11: default: - if version > iexportVersionGenerics { - errorf("unstable iexport format version %d, just rebuild compiler and std library", version) - } else { - errorf("unknown iexport format version %d", version) - } + errorf("unknown iexport format version %d", version) } sLen := int64(r.uint64()) @@ -367,7 +363,19 @@ func (r *importReader) obj(name string) { id := ident{r.currPkg.Name(), name} r.p.tparamIndex[id] = t - t.SetConstraint(r.typ()) + var implicit bool + if r.p.exportVersion >= iexportVersionGo1_18 { + implicit = r.bool() + } + constraint := r.typ() + if implicit { + iface, _ := constraint.(*types.Interface) + if iface == nil { + errorf("non-interface constraint marked implicit") + } + iface.MarkImplicit() + } + t.SetConstraint(constraint) case 'V': typ := r.typ() @@ -385,6 +393,10 @@ func (r *importReader) declare(obj types.Object) { func (r *importReader) value() (typ types.Type, val constant.Value) { typ = r.typ() + if r.p.exportVersion >= iexportVersionGo1_18 { + // TODO: add support for using the kind + _ = constant.Kind(r.int64()) + } switch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType { case types.IsBoolean: -- GitLab From e9eb66da307ec2da922a05b890b13363ea4e830e Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Mon, 25 Oct 2021 12:18:40 -0400 Subject: [PATCH 1736/2500] cmd/internal/obj/riscv: don't split ADD to SP to two adds When adding a large constant to a register we generate two adds, we may generate two ADD instructions if the constant does not fit in one ADD but does fit in two. This is generally fine except that if the target register is SP (such as in function prologues or epilogues for functions with large frames), this creates an intermediate state that the SP is not 0 nor the full frame size. For signal safety (preemption signal and profiling signal) we require that the frame is either not created at all or fully created, meaning that the SP must be written in a single instruction. Splitting to two adds breaks the requirement. So not splitting it. (We could mark such instructions not async-preemptible. But profiling signal can still cause problems.) (We could generate "ADD $c1, SP, Rtmp; ADD $c2; Rtmp; SP" to save an instruction if that is desired, while still ensuring that SP is written in a single instruction.) May fix flaky failures like https://build.golang.org/log/11537ec020a902b0ec0fc065f61161b729eb9880 Change-Id: I5cf38a6a028afe01aa3b6eeb163487bbd504b64f Reviewed-on: https://go-review.googlesource.com/c/go/+/358436 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: Joel Sing TryBot-Result: Go Bot --- src/cmd/internal/obj/riscv/obj.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index d98806edb5..c27ad99b2d 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -1610,7 +1610,8 @@ func instructionsForOpImmediate(p *obj.Prog, as obj.As, rs int16) []*instruction } // Split into two additions, if possible. - if ins.as == AADDI && ins.imm >= -(1<<12) && ins.imm < 1<<12-1 { + // Do not split SP-writing instructions, as otherwise the recorded SP delta may be wrong. + if p.Spadj == 0 && ins.as == AADDI && ins.imm >= -(1<<12) && ins.imm < 1<<12-1 { imm0 := ins.imm / 2 imm1 := ins.imm - imm0 -- GitLab From b36b001ff13768fd1f9664b34c6d2b7948f66d4d Mon Sep 17 00:00:00 2001 From: Gusted Date: Tue, 26 Oct 2021 01:45:44 +0200 Subject: [PATCH 1737/2500] container/list: remove unnecessary code Remove a unnecessary statement in the test function, the variables aren't checked afterwards. Also remove return statements in helper functions and remove the declaration that a the helper function return a value. The return value isn't used in the current state of code Change-Id: I5bc384104c1002c4138e0894938778ae9710ce4d Reviewed-on: https://go-review.googlesource.com/c/go/+/358714 Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Griesemer Trust: Ian Lance Taylor --- src/container/list/list.go | 13 +++++-------- src/container/list/list_test.go | 1 - 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/container/list/list.go b/src/container/list/list.go index 210424ceed..aa89b7f599 100644 --- a/src/container/list/list.go +++ b/src/container/list/list.go @@ -104,21 +104,20 @@ func (l *List) insertValue(v interface{}, at *Element) *Element { return l.insert(&Element{Value: v}, at) } -// remove removes e from its list, decrements l.len, and returns e. -func (l *List) remove(e *Element) *Element { +// remove removes e from its list, decrements l.len +func (l *List) remove(e *Element) { e.prev.next = e.next e.next.prev = e.prev e.next = nil // avoid memory leaks e.prev = nil // avoid memory leaks e.list = nil l.len-- - return e } -// move moves e to next to at and returns e. -func (l *List) move(e, at *Element) *Element { +// move moves e to next to at. +func (l *List) move(e, at *Element) { if e == at { - return e + return } e.prev.next = e.next e.next.prev = e.prev @@ -127,8 +126,6 @@ func (l *List) move(e, at *Element) *Element { e.next = at.next e.prev.next = e e.next.prev = e - - return e } // Remove removes e from l if e is an element of list l. diff --git a/src/container/list/list_test.go b/src/container/list/list_test.go index 99e006f39f..c74724b398 100644 --- a/src/container/list/list_test.go +++ b/src/container/list/list_test.go @@ -283,7 +283,6 @@ func TestMove(t *testing.T) { l.MoveAfter(e2, e3) checkListPointers(t, l, []*Element{e1, e3, e2, e4}) - e2, e3 = e3, e2 } // Test PushFront, PushBack, PushFrontList, PushBackList with uninitialized List -- GitLab From 0ec1b62ee28c633265036664c21a5cb22086f231 Mon Sep 17 00:00:00 2001 From: gosoon Date: Wed, 20 Oct 2021 11:13:29 +0000 Subject: [PATCH 1738/2500] doc/go1.18.html: fix a typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gofmt -> gofmt Change-Id: Idc01b01d8eb185f5e378000d11d622935b14db6e GitHub-Last-Rev: 8d55dc7b86ce0f7dfbdbd57c349b4c472eccf907 GitHub-Pull-Request: golang/go#49084 Reviewed-on: https://go-review.googlesource.com/c/go/+/357251 Reviewed-by: Daniel Martí Reviewed-by: Ian Lance Taylor Trust: Daniel Martí --- doc/go1.18.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 087a06c280..985689cf31 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -98,7 +98,7 @@ Do not send CLs removing the interior tags from such phrases.

gofmt now reads and formats input files concurrently, with a memory limit proportional to GOMAXPROCS. On a machine with - multiple CPUs, gofmt should now be significantly faster. + multiple CPUs, gofmt should now be significantly faster.

-- GitLab From 41f74079a982dae05da1860a5f195ac08d067bdd Mon Sep 17 00:00:00 2001 From: fanzha02 Date: Wed, 17 Mar 2021 14:52:27 +0800 Subject: [PATCH 1739/2500] cmd/internal/obj/arm64: add a restriction on move constant instructions For MOVK/MOVN/MOVZ instructions, the assembler does not accept zero shifts, and the CL 275812 added the error check. This CL adds this restriction to the document. Change-Id: I8818d76ca2f11dade2307f3678ca521f4e64d164 Reviewed-on: https://go-review.googlesource.com/c/go/+/312210 Trust: fannie zhang Run-TryBot: fannie zhang TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/internal/obj/arm64/doc.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/cmd/internal/obj/arm64/doc.go b/src/cmd/internal/obj/arm64/doc.go index efd4577f56..14f0f4c616 100644 --- a/src/cmd/internal/obj/arm64/doc.go +++ b/src/cmd/internal/obj/arm64/doc.go @@ -96,6 +96,19 @@ And for a 128-bit interger, it take two 64-bit operands, for the high and low pa VMOVD $0x1122334455667788, V1 VMOVQ $0x1122334455667788, $8877665544332211, V2 // V2=0x11223344556677888877665544332211 +8. Move an optionally-shifted 16-bit immediate value to a register. + +The instructions are MOVK(W), MOVZ(W) and MOVN(W), the assembly syntax is "op $(uimm16<". The +is the 16-bit unsigned immediate, in the range 0 to 65535; For the 32-bit variant, the is 0 or 16, for the +64-bit variant, the is 0, 16, 32 or 48. + +The current Go assembler does not accept zero shifts, such as "op $0, Rd" and "op $(0<<(16|32|48)), Rd" instructions. + + Examples: + MOVK $(10<<32), R20 <=> movk x20, #10, lsl #32 + MOVZW $(20<<16), R8 <=> movz w8, #20, lsl #16 + MOVK $(0<<16), R10 will be reported as an error by the assembler. + Special Cases. (1) umov is written as VMOV. -- GitLab From 49fda9e4f5cd3a05fd5fa0b3a2047a9d24873bd6 Mon Sep 17 00:00:00 2001 From: Fannie Zhang Date: Wed, 6 Jan 2021 08:57:44 +0000 Subject: [PATCH 1740/2500] cmd/go: add -asan option The -asan option compiles Go code to use the address sanitizer. This is intended for use when linking with C/C++ code compiled with -fsanitize=address. When memory blocks are passed back and forth between C/C++ and Go, code in both languages will agree as to whether the memory is validly allocated or not, and will report errors for any use of invalid memory. Updates #44853. Change-Id: I0209002ef795cc1c823daae557fb80c906158db3 Reviewed-on: https://go-review.googlesource.com/c/go/+/298612 Trust: fannie zhang Reviewed-by: Bryan C. Mills --- src/cmd/go/alldocs.go | 7 +++-- src/cmd/go/go_test.go | 2 ++ src/cmd/go/internal/cfg/cfg.go | 1 + src/cmd/go/internal/load/pkg.go | 5 ++++ src/cmd/go/internal/work/build.go | 8 +++-- src/cmd/go/internal/work/exec.go | 6 +++- src/cmd/go/internal/work/init.go | 30 ++++++++++++++----- src/cmd/go/script_test.go | 2 ++ src/cmd/go/testdata/script/README | 2 +- src/cmd/go/testdata/script/goflags.txt | 2 +- .../install_msan_and_race_require_cgo.txt | 6 ++-- 11 files changed, 55 insertions(+), 16 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index d04ba04a53..8178073103 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -121,6 +121,9 @@ // Supported only on linux/amd64, linux/arm64 // and only with Clang/LLVM as the host C compiler. // On linux/arm64, pie build mode will be used. +// -asan +// enable interoperation with address sanitizer. +// Supported only on linux/arm64, linux/amd64. // -v // print the names of packages as they are compiled. // -work @@ -155,8 +158,8 @@ // in order to keep output separate from default builds. // If using the -race flag, the install suffix is automatically set to race // or, if set explicitly, has _race appended to it. Likewise for the -msan -// flag. Using a -buildmode option that requires non-default compile flags -// has a similar effect. +// and -asan flags. Using a -buildmode option that requires non-default compile +// flags has a similar effect. // -ldflags '[pattern=]arg list' // arguments to pass on each go tool link invocation. // -linkshared diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index d67d01aa1e..339014e94e 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -46,6 +46,7 @@ var ( canRace = false // whether we can run the race detector canCgo = false // whether we can use cgo canMSan = false // whether we can run the memory sanitizer + canASan = false // whether we can run the address sanitizer ) var exeSuffix string = func() string { @@ -197,6 +198,7 @@ func TestMain(m *testing.M) { testGOCACHE = strings.TrimSpace(string(out)) canMSan = canCgo && sys.MSanSupported(runtime.GOOS, runtime.GOARCH) + canASan = canCgo && sys.ASanSupported(runtime.GOOS, runtime.GOARCH) canRace = canCgo && sys.RaceDetectorSupported(runtime.GOOS, runtime.GOARCH) // The race detector doesn't work on Alpine Linux: // golang.org/issue/14481 diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go index 37e9b2666e..351c3ee6a5 100644 --- a/src/cmd/go/internal/cfg/cfg.go +++ b/src/cmd/go/internal/cfg/cfg.go @@ -35,6 +35,7 @@ var ( BuildI bool // -i flag BuildLinkshared bool // -linkshared flag BuildMSan bool // -msan flag + BuildASan bool // -asan flag BuildN bool // -n flag BuildO string // -o flag BuildP = runtime.GOMAXPROCS(0) // -p flag diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index 99c4a9c62e..a5be48a49b 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -1625,6 +1625,7 @@ var cgoSyscallExclude = map[string]bool{ "runtime/cgo": true, "runtime/race": true, "runtime/msan": true, + "runtime/asan": true, } var foldPath = make(map[string]string) @@ -2415,6 +2416,10 @@ func LinkerDeps(p *Package) []string { if cfg.BuildMSan { deps = append(deps, "runtime/msan") } + // Using address sanitizer forces an import of runtime/asan. + if cfg.BuildASan { + deps = append(deps, "runtime/asan") + } return deps } diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go index e10f647a6d..ffe33bfa4d 100644 --- a/src/cmd/go/internal/work/build.go +++ b/src/cmd/go/internal/work/build.go @@ -75,6 +75,9 @@ and test commands: Supported only on linux/amd64, linux/arm64 and only with Clang/LLVM as the host C compiler. On linux/arm64, pie build mode will be used. + -asan + enable interoperation with address sanitizer. + Supported only on linux/arm64, linux/amd64. -v print the names of packages as they are compiled. -work @@ -109,8 +112,8 @@ and test commands: in order to keep output separate from default builds. If using the -race flag, the install suffix is automatically set to race or, if set explicitly, has _race appended to it. Likewise for the -msan - flag. Using a -buildmode option that requires non-default compile flags - has a similar effect. + and -asan flags. Using a -buildmode option that requires non-default compile + flags has a similar effect. -ldflags '[pattern=]arg list' arguments to pass on each go tool link invocation. -linkshared @@ -309,6 +312,7 @@ func AddBuildFlags(cmd *base.Command, mask BuildFlagMask) { cmd.Flag.StringVar(&cfg.BuildPkgdir, "pkgdir", "", "") cmd.Flag.BoolVar(&cfg.BuildRace, "race", false, "") cmd.Flag.BoolVar(&cfg.BuildMSan, "msan", false, "") + cmd.Flag.BoolVar(&cfg.BuildASan, "asan", false, "") cmd.Flag.Var((*tagsFlag)(&cfg.BuildContext.BuildTags), "tags", "") cmd.Flag.Var((*base.StringsFlag)(&cfg.BuildToolexec), "toolexec", "") cmd.Flag.BoolVar(&cfg.BuildTrimpath, "trimpath", false, "") diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index d4e24d4cd1..62d8143828 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -2736,6 +2736,10 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo cgoCFLAGS = append([]string{"-fsanitize=memory"}, cgoCFLAGS...) cgoLDFLAGS = append([]string{"-fsanitize=memory"}, cgoLDFLAGS...) } + if cfg.BuildASan { + cgoCFLAGS = append([]string{"-fsanitize=address"}, cgoCFLAGS...) + cgoLDFLAGS = append([]string{"-fsanitize=address"}, cgoLDFLAGS...) + } // Allows including _cgo_export.h, as well as the user's .h files, // from .[ch] files in the package. @@ -2757,7 +2761,7 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo if p.Standard && p.ImportPath == "runtime/cgo" { cgoflags = append(cgoflags, "-import_runtime_cgo=false") } - if p.Standard && (p.ImportPath == "runtime/race" || p.ImportPath == "runtime/msan" || p.ImportPath == "runtime/cgo") { + if p.Standard && (p.ImportPath == "runtime/race" || p.ImportPath == "runtime/msan" || p.ImportPath == "runtime/cgo" || p.ImportPath == "runtime/asan") { cgoflags = append(cgoflags, "-import_syscall=false") } diff --git a/src/cmd/go/internal/work/init.go b/src/cmd/go/internal/work/init.go index 6a29abb03b..56e39f8c52 100644 --- a/src/cmd/go/internal/work/init.go +++ b/src/cmd/go/internal/work/init.go @@ -87,7 +87,7 @@ func fuzzInstrumentFlags() []string { } func instrumentInit() { - if !cfg.BuildRace && !cfg.BuildMSan { + if !cfg.BuildRace && !cfg.BuildMSan && !cfg.BuildASan { return } if cfg.BuildRace && cfg.BuildMSan { @@ -95,17 +95,30 @@ func instrumentInit() { base.SetExitStatus(2) base.Exit() } + if cfg.BuildRace && cfg.BuildASan { + fmt.Fprintf(os.Stderr, "go: may not use -race and -asan simultaneously\n") + base.SetExitStatus(2) + base.Exit() + } + if cfg.BuildMSan && cfg.BuildASan { + fmt.Fprintf(os.Stderr, "go: may not use -msan and -asan simultaneously\n") + base.SetExitStatus(2) + base.Exit() + } if cfg.BuildMSan && !sys.MSanSupported(cfg.Goos, cfg.Goarch) { fmt.Fprintf(os.Stderr, "-msan is not supported on %s/%s\n", cfg.Goos, cfg.Goarch) base.SetExitStatus(2) base.Exit() } - if cfg.BuildRace { - if !sys.RaceDetectorSupported(cfg.Goos, cfg.Goarch) { - fmt.Fprintf(os.Stderr, "go: -race is only supported on linux/amd64, linux/ppc64le, linux/arm64, freebsd/amd64, netbsd/amd64, darwin/amd64, darwin/arm64, and windows/amd64\n") - base.SetExitStatus(2) - base.Exit() - } + if cfg.BuildRace && !sys.RaceDetectorSupported(cfg.Goos, cfg.Goarch) { + fmt.Fprintf(os.Stderr, "-race is not supported on %s/%s\n", cfg.Goos, cfg.Goarch) + base.SetExitStatus(2) + base.Exit() + } + if cfg.BuildASan && !sys.ASanSupported(cfg.Goos, cfg.Goarch) { + fmt.Fprintf(os.Stderr, "-asan is not supported on %s/%s\n", cfg.Goos, cfg.Goarch) + base.SetExitStatus(2) + base.Exit() } mode := "race" if cfg.BuildMSan { @@ -116,6 +129,9 @@ func instrumentInit() { cfg.BuildBuildmode = "pie" } } + if cfg.BuildASan { + mode = "asan" + } modeFlag := "-" + mode if !cfg.BuildContext.CgoEnabled { diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go index ac9764db94..acb1f91b44 100644 --- a/src/cmd/go/script_test.go +++ b/src/cmd/go/script_test.go @@ -353,6 +353,8 @@ Script: ok = canCgo case "msan": ok = canMSan + case "asan": + ok = canASan case "race": ok = canRace case "net": diff --git a/src/cmd/go/testdata/script/README b/src/cmd/go/testdata/script/README index 48e4055b0b..2b88e880c9 100644 --- a/src/cmd/go/testdata/script/README +++ b/src/cmd/go/testdata/script/README @@ -79,7 +79,7 @@ should only run when the condition is satisfied. The available conditions are: - Compiler names, like [gccgo], [gc]. - Test environment details: - [short] for testing.Short() - - [cgo], [msan], [race] for whether cgo, msan, and the race detector can be used + - [cgo], [msan], [asan], [race] for whether cgo, msan, asan, and the race detector can be used - [net] for whether the external network can be used - [link] for testenv.HasLink() - [root] for os.Geteuid() == 0 diff --git a/src/cmd/go/testdata/script/goflags.txt b/src/cmd/go/testdata/script/goflags.txt index 686d1138b8..f4872ffd35 100644 --- a/src/cmd/go/testdata/script/goflags.txt +++ b/src/cmd/go/testdata/script/goflags.txt @@ -9,7 +9,7 @@ stdout '[\\/]runtime$' env GOFLAGS=-race OLDGOARCH=$GOARCH OLDGOOS=$GOOS GOARCH=386 GOOS=linux ! go list runtime -stderr 'race is only supported on' +stderr 'race is not supported on linux/386' env GOARCH=$OLDGOARCH GOOS=$OLDGOOS diff --git a/src/cmd/go/testdata/script/install_msan_and_race_require_cgo.txt b/src/cmd/go/testdata/script/install_msan_and_race_require_cgo.txt index 7985cd2ab2..5e88f7b8db 100644 --- a/src/cmd/go/testdata/script/install_msan_and_race_require_cgo.txt +++ b/src/cmd/go/testdata/script/install_msan_and_race_require_cgo.txt @@ -1,7 +1,5 @@ # Tests Issue #21895 -[!msan] [!race] skip 'skipping because both msan and the race detector are not supported' - env CGO_ENABLED=0 [race] ! go install -race triv.go @@ -12,6 +10,10 @@ env CGO_ENABLED=0 [msan] stderr '-msan requires cgo' [msan] ! stderr '-race' +[asan] ! go install -asan triv.go +[asan] stderr '-asan requires cgo' +[asan] ! stderr '-msan' + -- triv.go -- package main -- GitLab From adfb85b3150d5ebe36440f82d83be88403951319 Mon Sep 17 00:00:00 2001 From: fanzha02 Date: Mon, 4 Jan 2021 17:53:37 +0800 Subject: [PATCH 1741/2500] runtime, runtime/asan: add asan runtime support These are the runtime support functions for letting Go code interoperate with the C/C++ address sanitizer. Calls to asanread/asanwrite are now inserted by the compiler with the -asan option. Calls to asanunpoison/asanpoison will be from other runtime functions in a subsequent CL. Updates #44853. Change-Id: I9e8fc0ce937828bc7f4a8b6637453ddc3862c47b Reviewed-on: https://go-review.googlesource.com/c/go/+/298613 Trust: fannie zhang Run-TryBot: fannie zhang TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/go/build/deps_test.go | 2 +- src/runtime/asan.go | 43 ++++++++++++++++++++++ src/runtime/asan/asan.go | 52 +++++++++++++++++++++++++++ src/runtime/asan0.go | 23 ++++++++++++ src/runtime/asan_amd64.s | 76 +++++++++++++++++++++++++++++++++++++++ src/runtime/asan_arm64.s | 63 ++++++++++++++++++++++++++++++++ 6 files changed, 258 insertions(+), 1 deletion(-) create mode 100644 src/runtime/asan.go create mode 100644 src/runtime/asan/asan.go create mode 100644 src/runtime/asan0.go create mode 100644 src/runtime/asan_amd64.s create mode 100644 src/runtime/asan_arm64.s diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index a92bb3893b..64f084152a 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -331,7 +331,7 @@ var depsRules = ` < C < runtime/cgo < CGO - < runtime/race, runtime/msan; + < runtime/race, runtime/msan, runtime/asan; # Bulk of the standard library must not use cgo. # The prohibition stops at net and os/user. diff --git a/src/runtime/asan.go b/src/runtime/asan.go new file mode 100644 index 0000000000..7ff5f26bfb --- /dev/null +++ b/src/runtime/asan.go @@ -0,0 +1,43 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build asan +// +build asan + +package runtime + +import ( + "unsafe" +) + +// Public address sanitizer API. + +func ASanRead(addr unsafe.Pointer, len int) { + asanread(addr, uintptr(len)) +} + +func ASanWrite(addr unsafe.Pointer, len int) { + asanwrite(addr, uintptr(len)) +} + +// Private interface for the runtime. +const asanenabled = true + +//go:noescape +func asanread(addr unsafe.Pointer, sz uintptr) + +//go:noescape +func asanwrite(addr unsafe.Pointer, sz uintptr) + +//go:noescape +func asanunpoison(addr unsafe.Pointer, sz uintptr) + +//go:noescape +func asanpoison(addr unsafe.Pointer, sz uintptr) + +// These are called from asan_GOARCH.s +//go:cgo_import_static __asan_read_go +//go:cgo_import_static __asan_write_go +//go:cgo_import_static __asan_unpoison_go +//go:cgo_import_static __asan_poison_go diff --git a/src/runtime/asan/asan.go b/src/runtime/asan/asan.go new file mode 100644 index 0000000000..40ebf96824 --- /dev/null +++ b/src/runtime/asan/asan.go @@ -0,0 +1,52 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build asan && linux && (arm64 || amd64) +// +build asan +// +build linux +// +build arm64 amd64 + +package asan + +/* +#cgo CFLAGS: -fsanitize=address +#cgo LDFLAGS: -fsanitize=address + +#include +#include + +void __asan_read_go(void *addr, uintptr_t sz) { + if (__asan_region_is_poisoned(addr, sz)) { + switch (sz) { + case 1: __asan_report_load1(addr); break; + case 2: __asan_report_load2(addr); break; + case 4: __asan_report_load4(addr); break; + case 8: __asan_report_load8(addr); break; + default: __asan_report_load_n(addr, sz); break; + } + } +} + +void __asan_write_go(void *addr, uintptr_t sz) { + if (__asan_region_is_poisoned(addr, sz)) { + switch (sz) { + case 1: __asan_report_store1(addr); break; + case 2: __asan_report_store2(addr); break; + case 4: __asan_report_store4(addr); break; + case 8: __asan_report_store8(addr); break; + default: __asan_report_store_n(addr, sz); break; + } + } +} + +void __asan_unpoison_go(void *addr, uintptr_t sz) { + __asan_unpoison_memory_region(addr, sz); +} + +void __asan_poison_go(void *addr, uintptr_t sz) { + __asan_poison_memory_region(addr, sz); +} + +*/ +import "C" diff --git a/src/runtime/asan0.go b/src/runtime/asan0.go new file mode 100644 index 0000000000..dad069bbe6 --- /dev/null +++ b/src/runtime/asan0.go @@ -0,0 +1,23 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !asan +// +build !asan + +// Dummy ASan support API, used when not built with -asan. + +package runtime + +import ( + "unsafe" +) + +const asanenabled = false + +// Because asanenabled is false, none of these functions should be called. + +func asanread(addr unsafe.Pointer, sz uintptr) { throw("asan") } +func asanwrite(addr unsafe.Pointer, sz uintptr) { throw("asan") } +func asanunpoison(addr unsafe.Pointer, sz uintptr) { throw("asan") } +func asanpoison(addr unsafe.Pointer, sz uintptr) { throw("asan") } diff --git a/src/runtime/asan_amd64.s b/src/runtime/asan_amd64.s new file mode 100644 index 0000000000..01bd612dc3 --- /dev/null +++ b/src/runtime/asan_amd64.s @@ -0,0 +1,76 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build asan +// +build asan + +#include "go_asm.h" +#include "go_tls.h" +#include "funcdata.h" +#include "textflag.h" + +// This is like race_amd64.s, but for the asan calls. +// See race_amd64.s for detailed comments. + +#ifdef GOOS_windows +#define RARG0 CX +#define RARG1 DX +#else +#define RARG0 DI +#define RARG1 SI +#endif + +// Called from intrumented code. +// func runtime·asanread(addr unsafe.Pointer, sz uintptr) +TEXT runtime·asanread(SB), NOSPLIT, $0-16 + MOVQ addr+0(FP), RARG0 + MOVQ size+8(FP), RARG1 + // void __asan_read_go(void *addr, uintptr_t sz); + MOVQ $__asan_read_go(SB), AX + JMP asancall<>(SB) + +// func runtime·asanwrite(addr unsafe.Pointer, sz uintptr) +TEXT runtime·asanwrite(SB), NOSPLIT, $0-16 + MOVQ addr+0(FP), RARG0 + MOVQ size+8(FP), RARG1 + // void __asan_write_go(void *addr, uintptr_t sz); + MOVQ $__asan_write_go(SB), AX + JMP asancall<>(SB) + +// func runtime·asanunpoison(addr unsafe.Pointer, sz uintptr) +TEXT runtime·asanunpoison(SB), NOSPLIT, $0-16 + MOVQ addr+0(FP), RARG0 + MOVQ size+8(FP), RARG1 + // void __asan_unpoison_go(void *addr, uintptr_t sz); + MOVQ $__asan_unpoison_go(SB), AX + JMP asancall<>(SB) + +// func runtime·asanpoison(addr unsafe.Pointer, sz uintptr) +TEXT runtime·asanpoison(SB), NOSPLIT, $0-16 + MOVQ addr+0(FP), RARG0 + MOVQ size+8(FP), RARG1 + // void __asan_poison_go(void *addr, uintptr_t sz); + MOVQ $__asan_poison_go(SB), AX + JMP asancall<>(SB) + +// Switches SP to g0 stack and calls (AX). Arguments already set. +TEXT asancall<>(SB), NOSPLIT, $0-0 + get_tls(R12) + MOVQ g(R12), R14 + MOVQ SP, R12 // callee-saved, preserved across the CALL + CMPQ R14, $0 + JE call // no g; still on a system stack + + MOVQ g_m(R14), R13 + // Switch to g0 stack. + MOVQ m_g0(R13), R10 + CMPQ R10, R14 + JE call // already on g0 + + MOVQ (g_sched+gobuf_sp)(R10), SP +call: + ANDQ $~15, SP // alignment for gcc ABI + CALL AX + MOVQ R12, SP + RET diff --git a/src/runtime/asan_arm64.s b/src/runtime/asan_arm64.s new file mode 100644 index 0000000000..eb0f9bd71e --- /dev/null +++ b/src/runtime/asan_arm64.s @@ -0,0 +1,63 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build asan +// +build asan + +#include "go_asm.h" +#include "textflag.h" + +#define RARG0 R0 +#define RARG1 R1 +#define FARG R3 + +// Called from instrumented code. +// func runtime·asanread(addr unsafe.Pointer, sz uintptr) +TEXT runtime·asanread(SB), NOSPLIT, $0-16 + MOVD addr+0(FP), RARG0 + MOVD size+8(FP), RARG1 + // void __asan_read_go(void *addr, uintptr_t sz); + MOVD $__asan_read_go(SB), FARG + JMP asancall<>(SB) + +// func runtime·asanwrite(addr unsafe.Pointer, sz uintptr) +TEXT runtime·asanwrite(SB), NOSPLIT, $0-16 + MOVD addr+0(FP), RARG0 + MOVD size+8(FP), RARG1 + // void __asan_write_go(void *addr, uintptr_t sz); + MOVD $__asan_write_go(SB), FARG + JMP asancall<>(SB) + +// func runtime·asanunpoison(addr unsafe.Pointer, sz uintptr) +TEXT runtime·asanunpoison(SB), NOSPLIT, $0-16 + MOVD addr+0(FP), RARG0 + MOVD size+8(FP), RARG1 + // void __asan_unpoison_go(void *addr, uintptr_t sz); + MOVD $__asan_unpoison_go(SB), FARG + JMP asancall<>(SB) + +// func runtime·asanpoison(addr unsafe.Pointer, sz uintptr) +TEXT runtime·asanpoison(SB), NOSPLIT, $0-16 + MOVD addr+0(FP), RARG0 + MOVD size+8(FP), RARG1 + // void __asan_poison_go(void *addr, uintptr_t sz); + MOVD $__asan_poison_go(SB), FARG + JMP asancall<>(SB) + +// Switches SP to g0 stack and calls (FARG). Arguments already set. +TEXT asancall<>(SB), NOSPLIT, $0-0 + MOVD RSP, R19 // callee-saved + CBZ g, g0stack // no g, still on a system stack + MOVD g_m(g), R10 + MOVD m_g0(R10), R11 + CMP R11, g + BEQ g0stack + + MOVD (g_sched+gobuf_sp)(R11), R4 + MOVD R4, RSP + +g0stack: + BL (FARG) + MOVD R19, RSP + RET -- GitLab From ec6c00418c83aa4f68a5afc9803831f43f8d794f Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 25 Oct 2021 13:37:29 +0200 Subject: [PATCH 1742/2500] syscall: use fcntl F_DUP2FD_CLOEXEC in forkAndExecInChild on illumos Use fcntl(oldfd, F_DUP2FD_CLOEXEC, newfd) to duplicate the file descriptor and mark is as close-on-exec instead of dup2 & fcntl. Illumos implements dup3 like this in libc. Change-Id: I9782bce553ffb832e9b1a12bbf3c0a40c821f56e Reviewed-on: https://go-review.googlesource.com/c/go/+/358374 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/syscall/exec_libc.go | 26 ++++++++++++++++++++------ src/syscall/syscall_aix.go | 2 ++ src/syscall/syscall_solaris.go | 2 ++ 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/syscall/exec_libc.go b/src/syscall/exec_libc.go index 8a84954051..b14abd4e63 100644 --- a/src/syscall/exec_libc.go +++ b/src/syscall/exec_libc.go @@ -10,6 +10,7 @@ package syscall import ( + "runtime" "unsafe" ) @@ -197,11 +198,19 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr // Pass 1: look for fd[i] < i and move those up above len(fd) // so that pass 2 won't stomp on an fd it needs later. if pipe < nextfd { - _, err1 = dup2child(uintptr(pipe), uintptr(nextfd)) + switch runtime.GOOS { + case "illumos": + _, err1 = fcntl1(uintptr(pipe), _F_DUP2FD_CLOEXEC, uintptr(nextfd)) + default: + _, err1 = dup2child(uintptr(pipe), uintptr(nextfd)) + if err1 != 0 { + goto childerror + } + _, err1 = fcntl1(uintptr(nextfd), F_SETFD, FD_CLOEXEC) + } if err1 != 0 { goto childerror } - fcntl1(uintptr(nextfd), F_SETFD, FD_CLOEXEC) pipe = nextfd nextfd++ } @@ -210,11 +219,16 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr if nextfd == pipe { // don't stomp on pipe nextfd++ } - _, err1 = dup2child(uintptr(fd[i]), uintptr(nextfd)) - if err1 != 0 { - goto childerror + switch runtime.GOOS { + case "illumos": + _, err1 = fcntl1(uintptr(fd[i]), _F_DUP2FD_CLOEXEC, uintptr(nextfd)) + default: + _, err1 = dup2child(uintptr(fd[i]), uintptr(nextfd)) + if err1 != 0 { + goto childerror + } + _, err1 = fcntl1(uintptr(nextfd), F_SETFD, FD_CLOEXEC) } - _, err1 = fcntl1(uintptr(nextfd), F_SETFD, FD_CLOEXEC) if err1 != 0 { goto childerror } diff --git a/src/syscall/syscall_aix.go b/src/syscall/syscall_aix.go index 9c6afba442..20e77ac875 100644 --- a/src/syscall/syscall_aix.go +++ b/src/syscall/syscall_aix.go @@ -31,6 +31,8 @@ const ( F_DUPFD_CLOEXEC = 0 // AF_LOCAL doesn't exist on AIX AF_LOCAL = AF_UNIX + + _F_DUP2FD_CLOEXEC = 0 ) func (ts *StTimespec_t) Unix() (sec int64, nsec int64) { diff --git a/src/syscall/syscall_solaris.go b/src/syscall/syscall_solaris.go index daa4b88a71..dedfbd03c0 100644 --- a/src/syscall/syscall_solaris.go +++ b/src/syscall/syscall_solaris.go @@ -14,6 +14,8 @@ package syscall import "unsafe" +const _F_DUP2FD_CLOEXEC = F_DUP2FD_CLOEXEC + // Implemented in asm_solaris_amd64.s. func rawSysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) -- GitLab From 23fdd7f0f75bca03a092faeeef60d8b0b804bf8d Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 25 Oct 2021 07:48:12 +0200 Subject: [PATCH 1743/2500] syscall: add utimensat libc wrapper on darwin Add utimensat as a wrapper around the libc function of the same name. utimensat was added in macOS 10.13 which is the minimum supported release since Go 1.17 dropped support for macOS 10.12. This also allows to drop the fallback to setattrlistTimes which was used to set timestamps with nanosecond resolution before utimensat could be used, see #22528 and CL 74952. Updates #22528 Change-Id: I87b6a76acf1d642ceede9254f7d9d06dddc3fd71 Reviewed-on: https://go-review.googlesource.com/c/go/+/358274 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/syscall/syscall_bsd.go | 7 +--- src/syscall/syscall_darwin.go | 53 +--------------------------- src/syscall/syscall_dragonfly.go | 5 --- src/syscall/syscall_freebsd.go | 5 --- src/syscall/syscall_netbsd.go | 5 --- src/syscall/syscall_openbsd.go | 5 --- src/syscall/zsyscall_darwin_amd64.go | 19 ++++++++++ src/syscall/zsyscall_darwin_amd64.s | 4 +-- src/syscall/zsyscall_darwin_arm64.go | 19 ++++++++++ src/syscall/zsyscall_darwin_arm64.s | 4 +-- 10 files changed, 44 insertions(+), 82 deletions(-) diff --git a/src/syscall/syscall_bsd.go b/src/syscall/syscall_bsd.go index 595e705856..40b1c07a90 100644 --- a/src/syscall/syscall_bsd.go +++ b/src/syscall/syscall_bsd.go @@ -524,12 +524,7 @@ func UtimesNano(path string, ts []Timespec) error { if len(ts) != 2 { return EINVAL } - // Darwin setattrlist can set nanosecond timestamps - err := setattrlistTimes(path, ts) - if err != ENOSYS { - return err - } - err = utimensat(_AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) + err := utimensat(_AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) if err != ENOSYS { return err } diff --git a/src/syscall/syscall_darwin.go b/src/syscall/syscall_darwin.go index a4fe4f1962..5bb34e300c 100644 --- a/src/syscall/syscall_darwin.go +++ b/src/syscall/syscall_darwin.go @@ -72,22 +72,6 @@ func direntNamlen(buf []byte) (uint64, bool) { func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) } func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) } -const ( - attrBitMapCount = 5 - attrCmnModtime = 0x00000400 - attrCmnAcctime = 0x00001000 -) - -type attrList struct { - bitmapCount uint16 - _ uint16 - CommonAttr uint32 - VolAttr uint32 - DirAttr uint32 - FileAttr uint32 - Forkattr uint32 -} - //sysnb pipe(p *[2]int32) (err error) func Pipe(p []int) (err error) { @@ -120,42 +104,7 @@ func libc_getfsstat_trampoline() //go:cgo_import_dynamic libc_getfsstat getfsstat "/usr/lib/libSystem.B.dylib" -func setattrlistTimes(path string, times []Timespec) error { - _p0, err := BytePtrFromString(path) - if err != nil { - return err - } - - var attrList attrList - attrList.bitmapCount = attrBitMapCount - attrList.CommonAttr = attrCmnModtime | attrCmnAcctime - - // order is mtime, atime: the opposite of Chtimes - attributes := [2]Timespec{times[1], times[0]} - const options = 0 - _, _, e1 := syscall6( - abi.FuncPCABI0(libc_setattrlist_trampoline), - uintptr(unsafe.Pointer(_p0)), - uintptr(unsafe.Pointer(&attrList)), - uintptr(unsafe.Pointer(&attributes)), - uintptr(unsafe.Sizeof(attributes)), - uintptr(options), - 0, - ) - if e1 != 0 { - return e1 - } - return nil -} - -func libc_setattrlist_trampoline() - -//go:cgo_import_dynamic libc_setattrlist setattrlist "/usr/lib/libSystem.B.dylib" - -func utimensat(dirfd int, path string, times *[2]Timespec, flag int) error { - // Darwin doesn't support SYS_UTIMENSAT - return ENOSYS -} +//sys utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) /* * Wrapped diff --git a/src/syscall/syscall_dragonfly.go b/src/syscall/syscall_dragonfly.go index b01a4ada67..16adf306d5 100644 --- a/src/syscall/syscall_dragonfly.go +++ b/src/syscall/syscall_dragonfly.go @@ -156,11 +156,6 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { return } -func setattrlistTimes(path string, times []Timespec) error { - // used on Darwin for UtimesNano - return ENOSYS -} - /* * Exposed directly */ diff --git a/src/syscall/syscall_freebsd.go b/src/syscall/syscall_freebsd.go index 7c7b89aab9..6f44b25cb9 100644 --- a/src/syscall/syscall_freebsd.go +++ b/src/syscall/syscall_freebsd.go @@ -176,11 +176,6 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { return } -func setattrlistTimes(path string, times []Timespec) error { - // used on Darwin for UtimesNano - return ENOSYS -} - func Stat(path string, st *Stat_t) (err error) { var oldStat stat_freebsd11_t if supportsABI(_ino64First) { diff --git a/src/syscall/syscall_netbsd.go b/src/syscall/syscall_netbsd.go index fc13b706b5..6f05b0d43d 100644 --- a/src/syscall/syscall_netbsd.go +++ b/src/syscall/syscall_netbsd.go @@ -146,11 +146,6 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e return -1, ENOSYS } -func setattrlistTimes(path string, times []Timespec) error { - // used on Darwin for UtimesNano - return ENOSYS -} - /* * Exposed directly */ diff --git a/src/syscall/syscall_openbsd.go b/src/syscall/syscall_openbsd.go index 5a5ba5a51b..195cf8617c 100644 --- a/src/syscall/syscall_openbsd.go +++ b/src/syscall/syscall_openbsd.go @@ -121,11 +121,6 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { return } -func setattrlistTimes(path string, times []Timespec) error { - // used on Darwin for UtimesNano - return ENOSYS -} - /* * Exposed directly */ diff --git a/src/syscall/zsyscall_darwin_amd64.go b/src/syscall/zsyscall_darwin_amd64.go index 07a519d7d6..ff88fef74e 100644 --- a/src/syscall/zsyscall_darwin_amd64.go +++ b/src/syscall/zsyscall_darwin_amd64.go @@ -345,6 +345,25 @@ func libc_pipe_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall6(abi.FuncPCABI0(libc_utimensat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_utimensat_trampoline() + +//go:cgo_import_dynamic libc_utimensat utimensat "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func kill(pid int, signum int, posix int) (err error) { _, _, e1 := syscall(abi.FuncPCABI0(libc_kill_trampoline), uintptr(pid), uintptr(signum), uintptr(posix)) if e1 != 0 { diff --git a/src/syscall/zsyscall_darwin_amd64.s b/src/syscall/zsyscall_darwin_amd64.s index 492f947855..563083d441 100644 --- a/src/syscall/zsyscall_darwin_amd64.s +++ b/src/syscall/zsyscall_darwin_amd64.s @@ -3,8 +3,6 @@ #include "textflag.h" TEXT ·libc_getfsstat_trampoline(SB),NOSPLIT,$0-0 JMP libc_getfsstat(SB) -TEXT ·libc_setattrlist_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setattrlist(SB) TEXT ·libc_fdopendir_trampoline(SB),NOSPLIT,$0-0 JMP libc_fdopendir(SB) TEXT ·libc_sendfile_trampoline(SB),NOSPLIT,$0-0 @@ -53,6 +51,8 @@ TEXT ·libc_fcntl_trampoline(SB),NOSPLIT,$0-0 JMP libc_fcntl(SB) TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0 JMP libc_pipe(SB) +TEXT ·libc_utimensat_trampoline(SB),NOSPLIT,$0-0 + JMP libc_utimensat(SB) TEXT ·libc_kill_trampoline(SB),NOSPLIT,$0-0 JMP libc_kill(SB) TEXT ·libc_access_trampoline(SB),NOSPLIT,$0-0 diff --git a/src/syscall/zsyscall_darwin_arm64.go b/src/syscall/zsyscall_darwin_arm64.go index 5ae096730e..b096b5e662 100644 --- a/src/syscall/zsyscall_darwin_arm64.go +++ b/src/syscall/zsyscall_darwin_arm64.go @@ -345,6 +345,25 @@ func libc_pipe_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall6(abi.FuncPCABI0(libc_utimensat_trampoline), uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_utimensat_trampoline() + +//go:cgo_import_dynamic libc_utimensat utimensat "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func kill(pid int, signum int, posix int) (err error) { _, _, e1 := syscall(abi.FuncPCABI0(libc_kill_trampoline), uintptr(pid), uintptr(signum), uintptr(posix)) if e1 != 0 { diff --git a/src/syscall/zsyscall_darwin_arm64.s b/src/syscall/zsyscall_darwin_arm64.s index b606c6e49e..0567a42fa3 100644 --- a/src/syscall/zsyscall_darwin_arm64.s +++ b/src/syscall/zsyscall_darwin_arm64.s @@ -3,8 +3,6 @@ #include "textflag.h" TEXT ·libc_getfsstat_trampoline(SB),NOSPLIT,$0-0 JMP libc_getfsstat(SB) -TEXT ·libc_setattrlist_trampoline(SB),NOSPLIT,$0-0 - JMP libc_setattrlist(SB) TEXT ·libc_fdopendir_trampoline(SB),NOSPLIT,$0-0 JMP libc_fdopendir(SB) TEXT ·libc_sendfile_trampoline(SB),NOSPLIT,$0-0 @@ -53,6 +51,8 @@ TEXT ·libc_fcntl_trampoline(SB),NOSPLIT,$0-0 JMP libc_fcntl(SB) TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0 JMP libc_pipe(SB) +TEXT ·libc_utimensat_trampoline(SB),NOSPLIT,$0-0 + JMP libc_utimensat(SB) TEXT ·libc_kill_trampoline(SB),NOSPLIT,$0-0 JMP libc_kill(SB) TEXT ·libc_access_trampoline(SB),NOSPLIT,$0-0 -- GitLab From 1e2820a6d72b606eb4070eda6cc626bde122f9c8 Mon Sep 17 00:00:00 2001 From: "Paul E. Murphy" Date: Tue, 10 Aug 2021 09:50:56 -0500 Subject: [PATCH 1744/2500] cmd/internal/obj/ppc64: fix usage of CR bit arguments CR bits and CR fields should be treated separately. Some instructions modify an entire CR, a CR field, or a single CR bit. Add a new argument class for CR bits, and teach the assembler the recognize them as names like CR0LT or CR2SO, and update the CR bit logic instructions to use them. They will no longer accept register field (CRn) type arguments. Fixes #46422 Change-Id: Iaba127d88abada0c2a49b8d3b07a976180565ae4 Reviewed-on: https://go-review.googlesource.com/c/go/+/357774 Run-TryBot: Paul Murphy Trust: Lynn Boger TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/asm/internal/arch/arch.go | 3 ++ src/cmd/asm/internal/asm/testdata/ppc64.s | 16 +++++----- src/cmd/internal/obj/ppc64/a.out.go | 39 +++++++++++++++++++++-- src/cmd/internal/obj/ppc64/anames9.go | 1 + src/cmd/internal/obj/ppc64/asm9.go | 5 ++- src/cmd/internal/obj/ppc64/asm_test.go | 2 ++ src/cmd/internal/obj/ppc64/doc.go | 6 ++++ src/cmd/internal/obj/ppc64/list9.go | 5 +++ 8 files changed, 66 insertions(+), 11 deletions(-) diff --git a/src/cmd/asm/internal/arch/arch.go b/src/cmd/asm/internal/arch/arch.go index cffa9a26a4..8c71b79965 100644 --- a/src/cmd/asm/internal/arch/arch.go +++ b/src/cmd/asm/internal/arch/arch.go @@ -378,6 +378,9 @@ func archPPC64(linkArch *obj.LinkArch) *Arch { for i := ppc64.REG_MSR; i <= ppc64.REG_CR; i++ { register[obj.Rconv(i)] = int16(i) } + for i := ppc64.REG_CR0LT; i <= ppc64.REG_CR7SO; i++ { + register[obj.Rconv(i)] = int16(i) + } register["CR"] = ppc64.REG_CR register["XER"] = ppc64.REG_XER register["LR"] = ppc64.REG_LR diff --git a/src/cmd/asm/internal/asm/testdata/ppc64.s b/src/cmd/asm/internal/asm/testdata/ppc64.s index b9da48acdd..c140fd025a 100644 --- a/src/cmd/asm/internal/asm/testdata/ppc64.s +++ b/src/cmd/asm/internal/asm/testdata/ppc64.s @@ -342,14 +342,14 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0 NOP F2 NOP $4 - CRAND CR1, CR2, CR3 // 4c620a02 - CRANDN CR1, CR2, CR3 // 4c620902 - CREQV CR1, CR2, CR3 // 4c620a42 - CRNAND CR1, CR2, CR3 // 4c6209c2 - CRNOR CR1, CR2, CR3 // 4c620842 - CROR CR1, CR2, CR3 // 4c620b82 - CRORN CR1, CR2, CR3 // 4c620b42 - CRXOR CR1, CR2, CR3 // 4c620982 + CRAND CR0GT, CR0EQ, CR0SO // 4c620a02 + CRANDN CR0GT, CR0EQ, CR0SO // 4c620902 + CREQV CR0GT, CR0EQ, CR0SO // 4c620a42 + CRNAND CR0GT, CR0EQ, CR0SO // 4c6209c2 + CRNOR CR0GT, CR0EQ, CR0SO // 4c620842 + CROR CR0GT, CR0EQ, CR0SO // 4c620b82 + CRORN CR0GT, CR0EQ, CR0SO // 4c620b42 + CRXOR CR0GT, CR0EQ, CR0SO // 4c620982 ISEL $1, R3, R4, R5 // 7ca3205e ISEL $0, R3, R4, R5 // 7ca3201e diff --git a/src/cmd/internal/obj/ppc64/a.out.go b/src/cmd/internal/obj/ppc64/a.out.go index fe18296034..1e74e64a29 100644 --- a/src/cmd/internal/obj/ppc64/a.out.go +++ b/src/cmd/internal/obj/ppc64/a.out.go @@ -79,10 +79,44 @@ const ( REG_R30 REG_R31 + // CR bits. Use Book 1, chapter 2 naming for bits. Keep aligned to 32 + REG_CR0LT + REG_CR0GT + REG_CR0EQ + REG_CR0SO + REG_CR1LT + REG_CR1GT + REG_CR1EQ + REG_CR1SO + REG_CR2LT + REG_CR2GT + REG_CR2EQ + REG_CR2SO + REG_CR3LT + REG_CR3GT + REG_CR3EQ + REG_CR3SO + REG_CR4LT + REG_CR4GT + REG_CR4EQ + REG_CR4SO + REG_CR5LT + REG_CR5GT + REG_CR5EQ + REG_CR5SO + REG_CR6LT + REG_CR6GT + REG_CR6EQ + REG_CR6SO + REG_CR7LT + REG_CR7GT + REG_CR7EQ + REG_CR7SO + /* Align FPR and VSR vectors such that when masked with 0x3F they produce an equivalent VSX register. */ /* F0=4160 ... F31=4191 */ - REG_F0 = obj.RBasePPC64 + iota + 32 + REG_F0 REG_F1 REG_F2 REG_F3 @@ -358,7 +392,8 @@ const ( C_VREG /* Any vector register */ C_VSREGP /* An even numbered vsx register which can be used as a vsx register pair argument */ C_VSREG /* Any vector-scalar register */ - C_CREG /* The condition registor (CR) or a condition register field (CRx) */ + C_CREG /* The condition registor (CR) */ + C_CRBIT /* A single bit of the CR register (0-31) */ C_SPR /* special processor register */ C_ZCON /* The constant zero */ C_U1CON /* 1 bit unsigned constant */ diff --git a/src/cmd/internal/obj/ppc64/anames9.go b/src/cmd/internal/obj/ppc64/anames9.go index 3b2aba77ab..05bfd944d1 100644 --- a/src/cmd/internal/obj/ppc64/anames9.go +++ b/src/cmd/internal/obj/ppc64/anames9.go @@ -14,6 +14,7 @@ var cnames9 = []string{ "VSREGP", "VSREG", "CREG", + "CRBIT", "SPR", "ZCON", "U1CON", diff --git a/src/cmd/internal/obj/ppc64/asm9.go b/src/cmd/internal/obj/ppc64/asm9.go index 08fb5118f0..31fbb7f7bf 100644 --- a/src/cmd/internal/obj/ppc64/asm9.go +++ b/src/cmd/internal/obj/ppc64/asm9.go @@ -335,7 +335,7 @@ var optab = []Optab{ {as: ALDMX, a1: C_SOREG, a6: C_REG, type_: 45, size: 4}, /* load doubleword monitored, x-form */ {as: AMADDHD, a1: C_REG, a2: C_REG, a3: C_REG, a6: C_REG, type_: 83, size: 4}, /* multiply-add high/low doubleword, va-form */ {as: AADDEX, a1: C_REG, a2: C_REG, a3: C_SCON, a6: C_REG, type_: 94, size: 4}, /* add extended using alternate carry, z23-form */ - {as: ACRAND, a1: C_CREG, a2: C_CREG, a6: C_CREG, type_: 2, size: 4}, /* logical ops for condition register bits xl-form */ + {as: ACRAND, a1: C_CRBIT, a2: C_CRBIT, a6: C_CRBIT, type_: 2, size: 4}, /* logical ops for condition register bits xl-form */ /* Vector instructions */ @@ -856,6 +856,9 @@ func (c *ctxt9) aclassreg(reg int16) int { if REG_CR0 <= reg && reg <= REG_CR7 || reg == REG_CR { return C_CREG } + if REG_CR0LT <= reg && reg <= REG_CR7SO { + return C_CRBIT + } if REG_SPR0 <= reg && reg <= REG_SPR0+1023 { switch reg { case REG_LR: diff --git a/src/cmd/internal/obj/ppc64/asm_test.go b/src/cmd/internal/obj/ppc64/asm_test.go index 3a9b87363c..ee2e5962f7 100644 --- a/src/cmd/internal/obj/ppc64/asm_test.go +++ b/src/cmd/internal/obj/ppc64/asm_test.go @@ -435,6 +435,7 @@ func TestRegValueAlignment(t *testing.T) { {REG_F0, REG_F31, 63, 0}, {REG_SPR0, REG_SPR0 + 1023, 1023, 0}, {REG_CR0, REG_CR7, 7, 0}, + {REG_CR0LT, REG_CR7SO, 31, 0}, } for _, t := range testType { tstFunc(t.rstart, t.rend, t.msk, t.rout) @@ -463,6 +464,7 @@ func TestAddrClassifier(t *testing.T) { {obj.Addr{Type: obj.TYPE_REG, Reg: REG_VS2}, C_VSREGP}, {obj.Addr{Type: obj.TYPE_REG, Reg: REG_CR}, C_CREG}, {obj.Addr{Type: obj.TYPE_REG, Reg: REG_CR1}, C_CREG}, + {obj.Addr{Type: obj.TYPE_REG, Reg: REG_CR1SO}, C_CRBIT}, {obj.Addr{Type: obj.TYPE_REG, Reg: REG_SPR0}, C_SPR}, {obj.Addr{Type: obj.TYPE_REG, Reg: REG_SPR0 + 1}, C_XER}, {obj.Addr{Type: obj.TYPE_REG, Reg: REG_SPR0 + 8}, C_LR}, diff --git a/src/cmd/internal/obj/ppc64/doc.go b/src/cmd/internal/obj/ppc64/doc.go index 6e601df82e..a9d89c93b4 100644 --- a/src/cmd/internal/obj/ppc64/doc.go +++ b/src/cmd/internal/obj/ppc64/doc.go @@ -239,6 +239,12 @@ Register naming VSn is used for vector-scalar registers. V0-V31 overlap with VS32-VS63. (0-63) CTR represents the count register. LR represents the link register. + CR represents the condition register + CRn represents a condition register field. (0-7) + CRnLT represents CR bit 0 of CR field n. (0-7) + CRnGT represents CR bit 1 of CR field n. (0-7) + CRnEQ represents CR bit 2 of CR field n. (0-7) + CRnSO represents CR bit 3 of CR field n. (0-7) */ package ppc64 diff --git a/src/cmd/internal/obj/ppc64/list9.go b/src/cmd/internal/obj/ppc64/list9.go index 8b0b36f375..ea0dae9e02 100644 --- a/src/cmd/internal/obj/ppc64/list9.go +++ b/src/cmd/internal/obj/ppc64/list9.go @@ -62,6 +62,11 @@ func rconv(r int) string { if REG_CR0 <= r && r <= REG_CR7 { return fmt.Sprintf("CR%d", r-REG_CR0) } + if REG_CR0LT <= r && r <= REG_CR7SO { + bits := [4]string{"LT", "GT", "EQ", "SO"} + crf := (r - REG_CR0LT) / 4 + return fmt.Sprintf("CR%d%s", crf, bits[r%4]) + } if r == REG_CR { return "CR" } -- GitLab From a2b8c186f616db92f9812e09fb2c44b0e753f8a7 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Tue, 26 Oct 2021 00:27:27 -0400 Subject: [PATCH 1745/2500] all: update vendored golang.org/x/tools Pull in CL 358034 (and some more changes with passing tests) with: go get -d golang.org/x/tools@f916b54 go mod tidy go mod vendor This teaches x/tools/cmd/bundle and the package loader it uses about the new export data version. Fixes #49159. Change-Id: Icc36e77e602b1cd2da03708f20d05a66fcf693cd Reviewed-on: https://go-review.googlesource.com/c/go/+/358620 Trust: Dmitri Shuralyov Run-TryBot: Dmitri Shuralyov TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 +- .../go/analysis/passes/composite/composite.go | 66 +++--- .../tools/go/analysis/passes/printf/printf.go | 3 +- .../go/analysis/unitchecker/unitchecker.go | 3 + .../x/tools/internal/typeparams/normalize.go | 212 ++++++++++++++++++ .../x/tools/internal/typeparams/termlist.go | 172 ++++++++++++++ .../internal/typeparams/typeparams_go117.go | 46 +++- .../internal/typeparams/typeparams_go118.go | 25 ++- .../x/tools/internal/typeparams/typeterm.go | 170 ++++++++++++++ src/cmd/vendor/modules.txt | 2 +- 11 files changed, 653 insertions(+), 52 deletions(-) create mode 100644 src/cmd/vendor/golang.org/x/tools/internal/typeparams/normalize.go create mode 100644 src/cmd/vendor/golang.org/x/tools/internal/typeparams/termlist.go create mode 100644 src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeterm.go diff --git a/src/cmd/go.mod b/src/cmd/go.mod index b2ec091292..e6fdc902dd 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -8,7 +8,7 @@ require ( golang.org/x/mod v0.5.1-0.20210913215816-37dd6891021a golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b - golang.org/x/tools v0.1.8-0.20211011152358-18fa84021695 + golang.org/x/tools v0.1.8-0.20211025211149-f916b54a1784 ) require ( diff --git a/src/cmd/go.sum b/src/cmd/go.sum index ff8df7b749..4993128d1a 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -18,7 +18,7 @@ golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e h1:XMgFehsDnnLGtjvjOfqWSUzt0 golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/tools v0.1.8-0.20211011152358-18fa84021695 h1:H+g8CC6T05IOoW6fXaWvb5N3XBYQElWwgDS/7Yxg8dU= -golang.org/x/tools v0.1.8-0.20211011152358-18fa84021695/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/tools v0.1.8-0.20211025211149-f916b54a1784 h1:+xP+QoP2SEPgbn+07I/yJTzP+gavj0XKGS6+JU5tlck= +golang.org/x/tools v0.1.8-0.20211025211149-f916b54a1784/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/composite/composite.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/composite/composite.go index 4c3ac6647f..025952ed50 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/composite/composite.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/composite/composite.go @@ -14,6 +14,7 @@ import ( "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis/passes/inspect" "golang.org/x/tools/go/ast/inspector" + "golang.org/x/tools/internal/typeparams" ) const Doc = `check for unkeyed composite literals @@ -67,41 +68,52 @@ func run(pass *analysis.Pass) (interface{}, error) { // skip whitelisted types return } - under := typ.Underlying() - for { - ptr, ok := under.(*types.Pointer) - if !ok { - break - } - under = ptr.Elem().Underlying() - } - if _, ok := under.(*types.Struct); !ok { - // skip non-struct composite literals - return - } - if isLocalType(pass, typ) { - // allow unkeyed locally defined composite literal - return + terms, err := typeparams.StructuralTerms(typ) + if err != nil { + return // invalid type } + for _, term := range terms { + under := deref(term.Type().Underlying()) + if _, ok := under.(*types.Struct); !ok { + // skip non-struct composite literals + continue + } + if isLocalType(pass, term.Type()) { + // allow unkeyed locally defined composite literal + continue + } - // check if the CompositeLit contains an unkeyed field - allKeyValue := true - for _, e := range cl.Elts { - if _, ok := e.(*ast.KeyValueExpr); !ok { - allKeyValue = false - break + // check if the CompositeLit contains an unkeyed field + allKeyValue := true + for _, e := range cl.Elts { + if _, ok := e.(*ast.KeyValueExpr); !ok { + allKeyValue = false + break + } } - } - if allKeyValue { - // all the composite literal fields are keyed + if allKeyValue { + // all the composite literal fields are keyed + continue + } + + pass.ReportRangef(cl, "%s composite literal uses unkeyed fields", typeName) return } - - pass.ReportRangef(cl, "%s composite literal uses unkeyed fields", typeName) }) return nil, nil } +func deref(typ types.Type) types.Type { + for { + ptr, ok := typ.(*types.Pointer) + if !ok { + break + } + typ = ptr.Elem().Underlying() + } + return typ +} + func isLocalType(pass *analysis.Pass, typ types.Type) bool { switch x := typ.(type) { case *types.Struct: @@ -112,6 +124,8 @@ func isLocalType(pass *analysis.Pass, typ types.Type) bool { case *types.Named: // names in package foo are local to foo_test too return strings.TrimSuffix(x.Obj().Pkg().Path(), "_test") == strings.TrimSuffix(pass.Pkg.Path(), "_test") + case *typeparams.TypeParam: + return strings.TrimSuffix(x.Obj().Pkg().Path(), "_test") == strings.TrimSuffix(pass.Pkg.Path(), "_test") } return false } diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go index de0369a428..4169d30e4f 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go @@ -834,8 +834,9 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, state *formatState) (o } // Could current arg implement fmt.Formatter? + // Skip check for the %w verb, which requires an error. formatter := false - if state.argNum < len(call.Args) { + if v.typ != argError && state.argNum < len(call.Args) { if tv, ok := pass.TypesInfo.Types[call.Args[state.argNum]]; ok { formatter = isFormatter(tv.Type) } diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go index 5424489f8b..b539866ddd 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go @@ -51,6 +51,7 @@ import ( "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis/internal/analysisflags" "golang.org/x/tools/go/analysis/internal/facts" + "golang.org/x/tools/internal/typeparams" ) // A Config describes a compilation unit to be analyzed. @@ -233,6 +234,8 @@ func run(fset *token.FileSet, cfg *Config, analyzers []*analysis.Analyzer) ([]re Scopes: make(map[ast.Node]*types.Scope), Selections: make(map[*ast.SelectorExpr]*types.Selection), } + typeparams.InitInstanceInfo(info) + pkg, err := tc.Check(cfg.ImportPath, fset, files, info) if err != nil { if cfg.SucceedOnTypecheckFailure { diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/normalize.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/normalize.go new file mode 100644 index 0000000000..29373508e9 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/normalize.go @@ -0,0 +1,212 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package typeparams + +import ( + "errors" + "fmt" + "go/types" + "os" + "strings" +) + +//go:generate go run copytermlist.go + +const debug = false + +// NormalizeInterface returns the normal form of the interface iface, or nil if iface +// has an empty type set (i.e. there are no types that satisfy iface). If the +// resulting interface is non-nil, it will be identical to iface. +// +// An error is returned if the interface type is invalid, or too complicated to +// reasonably normalize (for example, contains unions with more than a hundred +// terms). +// +// An interface is in normal form if and only if: +// - it has 0 or 1 embedded types. +// - its embedded type is either a types.Union or has a concrete +// (non-interface) underlying type +// - if the embedded type is a union, each term of the union has a concrete +// underlying type, and no terms may be removed without changing the type set +// of the interface +func NormalizeInterface(iface *types.Interface) (*types.Interface, error) { + var methods []*types.Func + for i := 0; i < iface.NumMethods(); i++ { + methods = append(methods, iface.Method(i)) + } + var embeddeds []types.Type + tset, err := computeTermSet(iface, make(map[types.Type]*termSet), 0) + if err != nil { + return nil, err + } + switch { + case tset.terms.isEmpty(): + // Special case: as documented + return nil, nil + + case tset.terms.isAll(): + // No embeddeds. + + case len(tset.terms) == 1: + if !tset.terms[0].tilde { + embeddeds = append(embeddeds, tset.terms[0].typ) + break + } + fallthrough + default: + var terms []*Term + for _, term := range tset.terms { + terms = append(terms, NewTerm(term.tilde, term.typ)) + } + embeddeds = append(embeddeds, NewUnion(terms)) + } + + return types.NewInterfaceType(methods, embeddeds), nil +} + +var ErrEmptyTypeSet = errors.New("empty type set") + +// StructuralTerms returns the normalized structural type restrictions of a +// type, if any. For types that are not type parameters, it returns term slice +// containing a single non-tilde term holding the given type. For type +// parameters, it returns the normalized term list of the type parameter's +// constraint. See NormalizeInterface for more information on the normal form +// of a constraint interface. +// +// StructuralTerms returns an error if the structural term list cannot be +// computed. If the type set of typ is empty, it returns ErrEmptyTypeSet. +func StructuralTerms(typ types.Type) ([]*Term, error) { + switch typ := typ.(type) { + case *TypeParam: + iface, _ := typ.Constraint().(*types.Interface) + if iface == nil { + return nil, fmt.Errorf("constraint is %T, not *types.Interface", typ) + } + tset, err := computeTermSet(iface, make(map[types.Type]*termSet), 0) + if err != nil { + return nil, err + } + if tset.terms.isEmpty() { + return nil, ErrEmptyTypeSet + } + if tset.terms.isAll() { + return nil, nil + } + var terms []*Term + for _, term := range tset.terms { + terms = append(terms, NewTerm(term.tilde, term.typ)) + } + return terms, nil + default: + return []*Term{NewTerm(false, typ)}, nil + } +} + +// A termSet holds the normalized set of terms for a given type. +// +// The name termSet is intentionally distinct from 'type set': a type set is +// all types that implement a type (and includes method restrictions), whereas +// a term set just represents the structural restrictions on a type. +type termSet struct { + complete bool + terms termlist +} + +func indentf(depth int, format string, args ...interface{}) { + fmt.Fprintf(os.Stderr, strings.Repeat(".", depth)+format+"\n", args...) +} + +func computeTermSet(t types.Type, seen map[types.Type]*termSet, depth int) (res *termSet, err error) { + if t == nil { + panic("nil type") + } + + if debug { + indentf(depth, "%s", t.String()) + defer func() { + if err != nil { + indentf(depth, "=> %s", err) + } else { + indentf(depth, "=> %s", res.terms.String()) + } + }() + } + + const maxTermCount = 100 + if tset, ok := seen[t]; ok { + if !tset.complete { + return nil, fmt.Errorf("cycle detected in the declaration of %s", t) + } + return tset, nil + } + + // Mark the current type as seen to avoid infinite recursion. + tset := new(termSet) + defer func() { + tset.complete = true + }() + seen[t] = tset + + switch u := t.Underlying().(type) { + case *types.Interface: + // The term set of an interface is the intersection of the term sets of its + // embedded types. + tset.terms = allTermlist + for i := 0; i < u.NumEmbeddeds(); i++ { + embedded := u.EmbeddedType(i) + if _, ok := embedded.Underlying().(*TypeParam); ok { + return nil, fmt.Errorf("invalid embedded type %T", embedded) + } + tset2, err := computeTermSet(embedded, seen, depth+1) + if err != nil { + return nil, err + } + tset.terms = tset.terms.intersect(tset2.terms) + } + case *Union: + // The term set of a union is the union of term sets of its terms. + tset.terms = nil + for i := 0; i < u.Len(); i++ { + t := u.Term(i) + var terms termlist + switch t.Type().Underlying().(type) { + case *types.Interface: + tset2, err := computeTermSet(t.Type(), seen, depth+1) + if err != nil { + return nil, err + } + terms = tset2.terms + case *TypeParam, *Union: + // A stand-alone type parameter or union is not permitted as union + // term. + return nil, fmt.Errorf("invalid union term %T", t) + default: + if t.Type() == types.Typ[types.Invalid] { + continue + } + terms = termlist{{t.Tilde(), t.Type()}} + } + tset.terms = tset.terms.union(terms) + if len(tset.terms) > maxTermCount { + return nil, fmt.Errorf("exceeded max term count %d", maxTermCount) + } + } + case *TypeParam: + panic("unreachable") + default: + // For all other types, the term set is just a single non-tilde term + // holding the type itself. + if u != types.Typ[types.Invalid] { + tset.terms = termlist{{false, t}} + } + } + return tset, nil +} + +// under is a facade for the go/types internal function of the same name. It is +// used by typeterm.go. +func under(t types.Type) types.Type { + return t.Underlying() +} diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/termlist.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/termlist.go new file mode 100644 index 0000000000..10857d504c --- /dev/null +++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/termlist.go @@ -0,0 +1,172 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by copytermlist.go DO NOT EDIT. + +package typeparams + +import ( + "bytes" + "go/types" +) + +// A termlist represents the type set represented by the union +// t1 ∪ y2 ∪ ... tn of the type sets of the terms t1 to tn. +// A termlist is in normal form if all terms are disjoint. +// termlist operations don't require the operands to be in +// normal form. +type termlist []*term + +// allTermlist represents the set of all types. +// It is in normal form. +var allTermlist = termlist{new(term)} + +// String prints the termlist exactly (without normalization). +func (xl termlist) String() string { + if len(xl) == 0 { + return "∅" + } + var buf bytes.Buffer + for i, x := range xl { + if i > 0 { + buf.WriteString(" ∪ ") + } + buf.WriteString(x.String()) + } + return buf.String() +} + +// isEmpty reports whether the termlist xl represents the empty set of types. +func (xl termlist) isEmpty() bool { + // If there's a non-nil term, the entire list is not empty. + // If the termlist is in normal form, this requires at most + // one iteration. + for _, x := range xl { + if x != nil { + return false + } + } + return true +} + +// isAll reports whether the termlist xl represents the set of all types. +func (xl termlist) isAll() bool { + // If there's a 𝓤 term, the entire list is 𝓤. + // If the termlist is in normal form, this requires at most + // one iteration. + for _, x := range xl { + if x != nil && x.typ == nil { + return true + } + } + return false +} + +// norm returns the normal form of xl. +func (xl termlist) norm() termlist { + // Quadratic algorithm, but good enough for now. + // TODO(gri) fix asymptotic performance + used := make([]bool, len(xl)) + var rl termlist + for i, xi := range xl { + if xi == nil || used[i] { + continue + } + for j := i + 1; j < len(xl); j++ { + xj := xl[j] + if xj == nil || used[j] { + continue + } + if u1, u2 := xi.union(xj); u2 == nil { + // If we encounter a 𝓤 term, the entire list is 𝓤. + // Exit early. + // (Note that this is not just an optimization; + // if we continue, we may end up with a 𝓤 term + // and other terms and the result would not be + // in normal form.) + if u1.typ == nil { + return allTermlist + } + xi = u1 + used[j] = true // xj is now unioned into xi - ignore it in future iterations + } + } + rl = append(rl, xi) + } + return rl +} + +// If the type set represented by xl is specified by a single (non-𝓤) term, +// structuralType returns that type. Otherwise it returns nil. +func (xl termlist) structuralType() types.Type { + if nl := xl.norm(); len(nl) == 1 { + return nl[0].typ // if nl.isAll() then typ is nil, which is ok + } + return nil +} + +// union returns the union xl ∪ yl. +func (xl termlist) union(yl termlist) termlist { + return append(xl, yl...).norm() +} + +// intersect returns the intersection xl ∩ yl. +func (xl termlist) intersect(yl termlist) termlist { + if xl.isEmpty() || yl.isEmpty() { + return nil + } + + // Quadratic algorithm, but good enough for now. + // TODO(gri) fix asymptotic performance + var rl termlist + for _, x := range xl { + for _, y := range yl { + if r := x.intersect(y); r != nil { + rl = append(rl, r) + } + } + } + return rl.norm() +} + +// equal reports whether xl and yl represent the same type set. +func (xl termlist) equal(yl termlist) bool { + // TODO(gri) this should be more efficient + return xl.subsetOf(yl) && yl.subsetOf(xl) +} + +// includes reports whether t ∈ xl. +func (xl termlist) includes(t types.Type) bool { + for _, x := range xl { + if x.includes(t) { + return true + } + } + return false +} + +// supersetOf reports whether y ⊆ xl. +func (xl termlist) supersetOf(y *term) bool { + for _, x := range xl { + if y.subsetOf(x) { + return true + } + } + return false +} + +// subsetOf reports whether xl ⊆ yl. +func (xl termlist) subsetOf(yl termlist) bool { + if yl.isEmpty() { + return xl.isEmpty() + } + + // each term x of xl must be a subset of yl + for _, x := range xl { + if !yl.supersetOf(x) { + return false // x is not a subset yl + } + } + return true +} diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go index d22899d29e..6ad3a43a2c 100644 --- a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go +++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go @@ -132,6 +132,15 @@ func IsMethodSet(*types.Interface) bool { return true } +// IsImplicit returns false, as no interfaces are implicit at this Go version. +func IsImplicit(*types.Interface) bool { + return false +} + +// MarkImplicit does nothing, because this Go version does not have implicit +// interfaces. +func MarkImplicit(*types.Interface) {} + // ForNamed returns an empty type parameter list, as type parameters are not // supported at this Go version. func ForNamed(*types.Named) *TypeParamList { @@ -155,19 +164,25 @@ func NamedTypeOrigin(named *types.Named) types.Type { return named } -// Term is a placeholder type, as type parameters are not supported at this Go -// version. Its methods panic on use. -type Term struct{} +// Term holds information about a structural type restriction. +type Term struct { + tilde bool + typ types.Type +} -func (*Term) Tilde() bool { unsupported(); return false } -func (*Term) Type() types.Type { unsupported(); return nil } -func (*Term) String() string { unsupported(); return "" } -func (*Term) Underlying() types.Type { unsupported(); return nil } +func (m *Term) Tilde() bool { return m.tilde } +func (m *Term) Type() types.Type { return m.typ } +func (m *Term) String() string { + pre := "" + if m.tilde { + pre = "~" + } + return pre + m.typ.String() +} // NewTerm is unsupported at this Go version, and panics. func NewTerm(tilde bool, typ types.Type) *Term { - unsupported() - return nil + return &Term{tilde, typ} } // Union is a placeholder type, as type parameters are not supported at this Go @@ -186,9 +201,16 @@ func NewUnion(terms []*Term) *Union { // InitInstanceInfo is a noop at this Go version. func InitInstanceInfo(*types.Info) {} -// GetInstance returns nothing, as type parameters are not supported at this Go -// version. -func GetInstance(*types.Info, *ast.Ident) (*TypeList, types.Type) { return nil, nil } +// Instance is a placeholder type, as type parameters are not supported at this +// Go version. +type Instance struct { + TypeArgs *TypeList + Type types.Type +} + +// GetInstances returns a nil map, as type parameters are not supported at this +// Go version. +func GetInstances(info *types.Info) map[*ast.Ident]Instance { return nil } // Context is a placeholder type, as type parameters are not supported at // this Go version. diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go index a252183411..e45896fb02 100644 --- a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go +++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go @@ -125,6 +125,16 @@ func IsMethodSet(iface *types.Interface) bool { return iface.IsMethodSet() } +// IsImplicit calls iface.IsImplicit(). +func IsImplicit(iface *types.Interface) bool { + return iface.IsImplicit() +} + +// MarkImplicit calls iface.MarkImplicit(). +func MarkImplicit(iface *types.Interface) { + iface.MarkImplicit() +} + // ForNamed extracts the (possibly empty) type parameter object list from // named. func ForNamed(named *types.Named) *TypeParamList { @@ -169,15 +179,12 @@ func InitInstanceInfo(info *types.Info) { info.Instances = make(map[*ast.Ident]types.Instance) } -// GetInstance extracts information about the instantiation occurring at the -// identifier id. id should be the identifier denoting a parameterized type or -// function in an instantiation expression or function call. -func GetInstance(info *types.Info, id *ast.Ident) (*TypeList, types.Type) { - if info.Instances != nil { - inf := info.Instances[id] - return inf.TypeArgs, inf.Type - } - return nil, nil +// Instance is an alias for types.Instance. +type Instance = types.Instance + +// GetInstances returns info.Instances. +func GetInstances(info *types.Info) map[*ast.Ident]Instance { + return info.Instances } // Context is an alias for types.Context. diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeterm.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeterm.go new file mode 100644 index 0000000000..7ddee28d98 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeterm.go @@ -0,0 +1,170 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by copytermlist.go DO NOT EDIT. + +package typeparams + +import "go/types" + +// A term describes elementary type sets: +// +// ∅: (*term)(nil) == ∅ // set of no types (empty set) +// 𝓤: &term{} == 𝓤 // set of all types (𝓤niverse) +// T: &term{false, T} == {T} // set of type T +// ~t: &term{true, t} == {t' | under(t') == t} // set of types with underlying type t +// +type term struct { + tilde bool // valid if typ != nil + typ types.Type +} + +func (x *term) String() string { + switch { + case x == nil: + return "∅" + case x.typ == nil: + return "𝓤" + case x.tilde: + return "~" + x.typ.String() + default: + return x.typ.String() + } +} + +// equal reports whether x and y represent the same type set. +func (x *term) equal(y *term) bool { + // easy cases + switch { + case x == nil || y == nil: + return x == y + case x.typ == nil || y.typ == nil: + return x.typ == y.typ + } + // ∅ ⊂ x, y ⊂ 𝓤 + + return x.tilde == y.tilde && types.Identical(x.typ, y.typ) +} + +// union returns the union x ∪ y: zero, one, or two non-nil terms. +func (x *term) union(y *term) (_, _ *term) { + // easy cases + switch { + case x == nil && y == nil: + return nil, nil // ∅ ∪ ∅ == ∅ + case x == nil: + return y, nil // ∅ ∪ y == y + case y == nil: + return x, nil // x ∪ ∅ == x + case x.typ == nil: + return x, nil // 𝓤 ∪ y == 𝓤 + case y.typ == nil: + return y, nil // x ∪ 𝓤 == 𝓤 + } + // ∅ ⊂ x, y ⊂ 𝓤 + + if x.disjoint(y) { + return x, y // x ∪ y == (x, y) if x ∩ y == ∅ + } + // x.typ == y.typ + + // ~t ∪ ~t == ~t + // ~t ∪ T == ~t + // T ∪ ~t == ~t + // T ∪ T == T + if x.tilde || !y.tilde { + return x, nil + } + return y, nil +} + +// intersect returns the intersection x ∩ y. +func (x *term) intersect(y *term) *term { + // easy cases + switch { + case x == nil || y == nil: + return nil // ∅ ∩ y == ∅ and ∩ ∅ == ∅ + case x.typ == nil: + return y // 𝓤 ∩ y == y + case y.typ == nil: + return x // x ∩ 𝓤 == x + } + // ∅ ⊂ x, y ⊂ 𝓤 + + if x.disjoint(y) { + return nil // x ∩ y == ∅ if x ∩ y == ∅ + } + // x.typ == y.typ + + // ~t ∩ ~t == ~t + // ~t ∩ T == T + // T ∩ ~t == T + // T ∩ T == T + if !x.tilde || y.tilde { + return x + } + return y +} + +// includes reports whether t ∈ x. +func (x *term) includes(t types.Type) bool { + // easy cases + switch { + case x == nil: + return false // t ∈ ∅ == false + case x.typ == nil: + return true // t ∈ 𝓤 == true + } + // ∅ ⊂ x ⊂ 𝓤 + + u := t + if x.tilde { + u = under(u) + } + return types.Identical(x.typ, u) +} + +// subsetOf reports whether x ⊆ y. +func (x *term) subsetOf(y *term) bool { + // easy cases + switch { + case x == nil: + return true // ∅ ⊆ y == true + case y == nil: + return false // x ⊆ ∅ == false since x != ∅ + case y.typ == nil: + return true // x ⊆ 𝓤 == true + case x.typ == nil: + return false // 𝓤 ⊆ y == false since y != 𝓤 + } + // ∅ ⊂ x, y ⊂ 𝓤 + + if x.disjoint(y) { + return false // x ⊆ y == false if x ∩ y == ∅ + } + // x.typ == y.typ + + // ~t ⊆ ~t == true + // ~t ⊆ T == false + // T ⊆ ~t == true + // T ⊆ T == true + return !x.tilde || y.tilde +} + +// disjoint reports whether x ∩ y == ∅. +// x.typ and y.typ must not be nil. +func (x *term) disjoint(y *term) bool { + if debug && (x.typ == nil || y.typ == nil) { + panic("invalid argument(s)") + } + ux := x.typ + if y.tilde { + ux = under(ux) + } + uy := y.typ + if x.tilde { + uy = under(uy) + } + return !types.Identical(ux, uy) +} diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index e0e116a634..ecb170d290 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -51,7 +51,7 @@ golang.org/x/sys/windows # golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b ## explicit; go 1.17 golang.org/x/term -# golang.org/x/tools v0.1.8-0.20211011152358-18fa84021695 +# golang.org/x/tools v0.1.8-0.20211025211149-f916b54a1784 ## explicit; go 1.17 golang.org/x/tools/cover golang.org/x/tools/go/analysis -- GitLab From 283d8a3d53ac1c7e1d7e297497480bf0071b6300 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Mon, 25 Oct 2021 23:00:56 +0700 Subject: [PATCH 1746/2500] all: use reflect.{Pointer,PointerTo} Updates #47651 Updates #48665 Change-Id: I69a87b45a5cad7a07fbd855040cd9935cf874554 Reviewed-on: https://go-review.googlesource.com/c/go/+/358454 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/cmd/fix/cftype.go | 2 +- src/cmd/fix/typecheck.go | 2 +- src/cmd/gofmt/rewrite.go | 2 +- src/database/sql/convert.go | 6 ++-- src/database/sql/driver/types.go | 4 +-- src/encoding/asn1/asn1.go | 4 +-- src/encoding/binary/binary.go | 2 +- src/encoding/gob/decode.go | 14 ++++---- src/encoding/gob/decoder.go | 4 +-- src/encoding/gob/encode.go | 8 ++--- src/encoding/gob/encoder.go | 2 +- src/encoding/gob/type.go | 12 +++---- src/encoding/gob/type_test.go | 2 +- src/encoding/json/decode.go | 18 +++++----- src/encoding/json/decode_test.go | 2 +- src/encoding/json/encode.go | 24 ++++++------- src/encoding/xml/marshal.go | 10 +++--- src/encoding/xml/read.go | 10 +++--- src/encoding/xml/typeinfo.go | 6 ++-- src/flag/flag.go | 2 +- src/fmt/print.go | 6 ++-- src/fmt/scan.go | 2 +- src/fmt/scan_test.go | 4 +-- src/go/ast/print.go | 4 +-- src/html/template/content.go | 6 ++-- src/html/template/js.go | 2 +- src/internal/fmtsort/sort.go | 2 +- src/internal/reflectlite/tostring_test.go | 2 +- src/net/rpc/server.go | 8 ++--- src/reflect/abi.go | 2 +- src/reflect/all_test.go | 32 ++++++++--------- src/reflect/deepequal.go | 8 ++--- src/reflect/tostring_test.go | 2 +- src/reflect/type.go | 2 +- src/reflect/value.go | 44 +++++++++++------------ src/reflect/visiblefields.go | 2 +- src/runtime/gc_test.go | 2 +- src/testing/quick/quick.go | 2 +- src/text/template/exec.go | 18 +++++----- test/fixedbugs/issue32901.dir/main.go | 9 +++-- test/reflectmethod7.go | 2 +- 41 files changed, 150 insertions(+), 147 deletions(-) diff --git a/src/cmd/fix/cftype.go b/src/cmd/fix/cftype.go index b47b06682a..3d292bdeba 100644 --- a/src/cmd/fix/cftype.go +++ b/src/cmd/fix/cftype.go @@ -63,7 +63,7 @@ func typefix(f *ast.File, badType func(string) bool) bool { return } v := reflect.ValueOf(n) - if v.Type().Kind() != reflect.Ptr { + if v.Type().Kind() != reflect.Pointer { return } if v.IsNil() { diff --git a/src/cmd/fix/typecheck.go b/src/cmd/fix/typecheck.go index 8c4beb4b65..b7ec72e116 100644 --- a/src/cmd/fix/typecheck.go +++ b/src/cmd/fix/typecheck.go @@ -383,7 +383,7 @@ func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string, a if n == nil { return } - if false && reflect.TypeOf(n).Kind() == reflect.Ptr { // debugging trace + if false && reflect.TypeOf(n).Kind() == reflect.Pointer { // debugging trace defer func() { if t := typeof[n]; t != "" { pos := fset.Position(n.(ast.Node).Pos()) diff --git a/src/cmd/gofmt/rewrite.go b/src/cmd/gofmt/rewrite.go index 0e736e6132..a98c6a0cd9 100644 --- a/src/cmd/gofmt/rewrite.go +++ b/src/cmd/gofmt/rewrite.go @@ -292,7 +292,7 @@ func subst(m map[string]reflect.Value, pattern reflect.Value, pos reflect.Value) } return v - case reflect.Ptr: + case reflect.Pointer: v := reflect.New(p.Type()).Elem() if elem := p.Elem(); elem.IsValid() { v.Set(subst(m, elem, pos).Addr()) diff --git a/src/database/sql/convert.go b/src/database/sql/convert.go index b966ef970c..c0997b7fc5 100644 --- a/src/database/sql/convert.go +++ b/src/database/sql/convert.go @@ -386,7 +386,7 @@ func convertAssignRows(dest, src interface{}, rows *Rows) error { } dpv := reflect.ValueOf(dest) - if dpv.Kind() != reflect.Ptr { + if dpv.Kind() != reflect.Pointer { return errors.New("destination not a pointer") } if dpv.IsNil() { @@ -419,7 +419,7 @@ func convertAssignRows(dest, src interface{}, rows *Rows) error { // This also allows scanning into user defined types such as "type Int int64". // For symmetry, also check for string destination types. switch dv.Kind() { - case reflect.Ptr: + case reflect.Pointer: if src == nil { dv.Set(reflect.Zero(dv.Type())) return nil @@ -551,7 +551,7 @@ var valuerReflectType = reflect.TypeOf((*driver.Valuer)(nil)).Elem() // // This function is mirrored in the database/sql/driver package. func callValuerValue(vr driver.Valuer) (v driver.Value, err error) { - if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Ptr && + if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Pointer && rv.IsNil() && rv.Type().Elem().Implements(valuerReflectType) { return nil, nil diff --git a/src/database/sql/driver/types.go b/src/database/sql/driver/types.go index 24c3a45483..3337c2e0bc 100644 --- a/src/database/sql/driver/types.go +++ b/src/database/sql/driver/types.go @@ -225,7 +225,7 @@ var valuerReflectType = reflect.TypeOf((*Valuer)(nil)).Elem() // // This function is mirrored in the database/sql package. func callValuerValue(vr Valuer) (v Value, err error) { - if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Ptr && + if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Pointer && rv.IsNil() && rv.Type().Elem().Implements(valuerReflectType) { return nil, nil @@ -256,7 +256,7 @@ func (defaultConverter) ConvertValue(v interface{}) (Value, error) { rv := reflect.ValueOf(v) switch rv.Kind() { - case reflect.Ptr: + case reflect.Pointer: // indirect pointers if rv.IsNil() { return nil, nil diff --git a/src/encoding/asn1/asn1.go b/src/encoding/asn1/asn1.go index cffc06dc9c..d0e1c6b176 100644 --- a/src/encoding/asn1/asn1.go +++ b/src/encoding/asn1/asn1.go @@ -1101,7 +1101,7 @@ func (e *invalidUnmarshalError) Error() string { return "asn1: Unmarshal recipient value is nil" } - if e.Type.Kind() != reflect.Ptr { + if e.Type.Kind() != reflect.Pointer { return "asn1: Unmarshal recipient value is non-pointer " + e.Type.String() } return "asn1: Unmarshal recipient value is nil " + e.Type.String() @@ -1111,7 +1111,7 @@ func (e *invalidUnmarshalError) Error() string { // top-level element. The form of the params is the same as the field tags. func UnmarshalWithParams(b []byte, val interface{}, params string) (rest []byte, err error) { v := reflect.ValueOf(val) - if v.Kind() != reflect.Ptr || v.IsNil() { + if v.Kind() != reflect.Pointer || v.IsNil() { return nil, &invalidUnmarshalError{reflect.TypeOf(val)} } offset, err := parseField(v.Elem(), b, 0, parseFieldParameters(params)) diff --git a/src/encoding/binary/binary.go b/src/encoding/binary/binary.go index a31149979d..52417a7933 100644 --- a/src/encoding/binary/binary.go +++ b/src/encoding/binary/binary.go @@ -243,7 +243,7 @@ func Read(r io.Reader, order ByteOrder, data interface{}) error { v := reflect.ValueOf(data) size := -1 switch v.Kind() { - case reflect.Ptr: + case reflect.Pointer: v = v.Elem() size = dataSize(v) case reflect.Slice: diff --git a/src/encoding/gob/decode.go b/src/encoding/gob/decode.go index f92556f8ab..34f302a5cf 100644 --- a/src/encoding/gob/decode.go +++ b/src/encoding/gob/decode.go @@ -228,7 +228,7 @@ func ignoreTwoUints(i *decInstr, state *decoderState, v reflect.Value) { // The callers to the individual decoders are expected to have used decAlloc. // The individual decoders don't need to it. func decAlloc(v reflect.Value) reflect.Value { - for v.Kind() == reflect.Ptr { + for v.Kind() == reflect.Pointer { if v.IsNil() { v.Set(reflect.New(v.Type().Elem())) } @@ -464,7 +464,7 @@ func (dec *Decoder) decodeStruct(engine *decEngine, value reflect.Value) { if instr.index != nil { // Otherwise the field is unknown to us and instr.op is an ignore op. field = value.FieldByIndex(instr.index) - if field.Kind() == reflect.Ptr { + if field.Kind() == reflect.Pointer { field = decAlloc(field) } } @@ -518,7 +518,7 @@ func (dec *Decoder) decodeArrayHelper(state *decoderState, value reflect.Value, return } instr := &decInstr{elemOp, 0, nil, ovfl} - isPtr := value.Type().Elem().Kind() == reflect.Ptr + isPtr := value.Type().Elem().Kind() == reflect.Pointer for i := 0; i < length; i++ { if state.b.Len() == 0 { errorf("decoding array or slice: length exceeds input size (%d elements)", length) @@ -561,8 +561,8 @@ func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, value refl if value.IsNil() { value.Set(reflect.MakeMapWithSize(mtyp, n)) } - keyIsPtr := mtyp.Key().Kind() == reflect.Ptr - elemIsPtr := mtyp.Elem().Kind() == reflect.Ptr + keyIsPtr := mtyp.Key().Kind() == reflect.Pointer + elemIsPtr := mtyp.Elem().Kind() == reflect.Pointer keyInstr := &decInstr{keyOp, 0, nil, ovfl} elemInstr := &decInstr{elemOp, 0, nil, ovfl} keyP := reflect.New(mtyp.Key()) @@ -945,7 +945,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp) func (dec *Decoder) gobDecodeOpFor(ut *userTypeInfo) *decOp { rcvrType := ut.user if ut.decIndir == -1 { - rcvrType = reflect.PtrTo(rcvrType) + rcvrType = reflect.PointerTo(rcvrType) } else if ut.decIndir > 0 { for i := int8(0); i < ut.decIndir; i++ { rcvrType = rcvrType.Elem() @@ -954,7 +954,7 @@ func (dec *Decoder) gobDecodeOpFor(ut *userTypeInfo) *decOp { var op decOp op = func(i *decInstr, state *decoderState, value reflect.Value) { // We now have the base type. We need its address if the receiver is a pointer. - if value.Kind() != reflect.Ptr && rcvrType.Kind() == reflect.Ptr { + if value.Kind() != reflect.Pointer && rcvrType.Kind() == reflect.Pointer { value = value.Addr() } state.dec.decodeGobDecoder(ut, state, value) diff --git a/src/encoding/gob/decoder.go b/src/encoding/gob/decoder.go index 5e4ed5a7d7..96e215eb8c 100644 --- a/src/encoding/gob/decoder.go +++ b/src/encoding/gob/decoder.go @@ -193,7 +193,7 @@ func (dec *Decoder) Decode(e interface{}) error { value := reflect.ValueOf(e) // If e represents a value as opposed to a pointer, the answer won't // get back to the caller. Make sure it's a pointer. - if value.Type().Kind() != reflect.Ptr { + if value.Type().Kind() != reflect.Pointer { dec.err = errors.New("gob: attempt to decode into a non-pointer") return dec.err } @@ -208,7 +208,7 @@ func (dec *Decoder) Decode(e interface{}) error { // does not modify v. func (dec *Decoder) DecodeValue(v reflect.Value) error { if v.IsValid() { - if v.Kind() == reflect.Ptr && !v.IsNil() { + if v.Kind() == reflect.Pointer && !v.IsNil() { // That's okay, we'll store through the pointer. } else if !v.CanSet() { return errors.New("gob: DecodeValue of unassignable value") diff --git a/src/encoding/gob/encode.go b/src/encoding/gob/encode.go index f1f5f3862d..e49b452f6c 100644 --- a/src/encoding/gob/encode.go +++ b/src/encoding/gob/encode.go @@ -279,7 +279,7 @@ func valid(v reflect.Value) bool { switch v.Kind() { case reflect.Invalid: return false - case reflect.Ptr: + case reflect.Pointer: return !v.IsNil() } return true @@ -386,7 +386,7 @@ func (enc *Encoder) encodeInterface(b *encBuffer, iv reflect.Value) { // Gobs can encode nil interface values but not typed interface // values holding nil pointers, since nil pointers point to no value. elem := iv.Elem() - if elem.Kind() == reflect.Ptr && elem.IsNil() { + if elem.Kind() == reflect.Pointer && elem.IsNil() { errorf("gob: cannot encode nil pointer of type %s inside interface", iv.Elem().Type()) } state := enc.newEncoderState(b) @@ -446,7 +446,7 @@ func isZero(val reflect.Value) bool { return !val.Bool() case reflect.Complex64, reflect.Complex128: return val.Complex() == 0 - case reflect.Chan, reflect.Func, reflect.Interface, reflect.Ptr: + case reflect.Chan, reflect.Func, reflect.Interface, reflect.Pointer: return val.IsNil() case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return val.Int() == 0 @@ -600,7 +600,7 @@ func encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp, building map[ func gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) { rt := ut.user if ut.encIndir == -1 { - rt = reflect.PtrTo(rt) + rt = reflect.PointerTo(rt) } else if ut.encIndir > 0 { for i := int8(0); i < ut.encIndir; i++ { rt = rt.Elem() diff --git a/src/encoding/gob/encoder.go b/src/encoding/gob/encoder.go index 53e2cace16..32865a7ede 100644 --- a/src/encoding/gob/encoder.go +++ b/src/encoding/gob/encoder.go @@ -219,7 +219,7 @@ func (enc *Encoder) EncodeValue(value reflect.Value) error { if value.Kind() == reflect.Invalid { return errors.New("gob: cannot encode nil value") } - if value.Kind() == reflect.Ptr && value.IsNil() { + if value.Kind() == reflect.Pointer && value.IsNil() { panic("gob: cannot encode nil pointer of type " + value.Type().String()) } diff --git a/src/encoding/gob/type.go b/src/encoding/gob/type.go index 31c0ef7af1..412a348137 100644 --- a/src/encoding/gob/type.go +++ b/src/encoding/gob/type.go @@ -61,7 +61,7 @@ func validUserType(rt reflect.Type) (*userTypeInfo, error) { slowpoke := ut.base // walks half as fast as ut.base for { pt := ut.base - if pt.Kind() != reflect.Ptr { + if pt.Kind() != reflect.Pointer { break } ut.base = pt.Elem() @@ -126,7 +126,7 @@ func implementsInterface(typ, gobEncDecType reflect.Type) (success bool, indir i if rt.Implements(gobEncDecType) { return true, indir } - if p := rt; p.Kind() == reflect.Ptr { + if p := rt; p.Kind() == reflect.Pointer { indir++ if indir > 100 { // insane number of indirections return false, 0 @@ -137,9 +137,9 @@ func implementsInterface(typ, gobEncDecType reflect.Type) (success bool, indir i break } // No luck yet, but if this is a base type (non-pointer), the pointer might satisfy. - if typ.Kind() != reflect.Ptr { + if typ.Kind() != reflect.Pointer { // Not a pointer, but does the pointer work? - if reflect.PtrTo(typ).Implements(gobEncDecType) { + if reflect.PointerTo(typ).Implements(gobEncDecType) { return true, -1 } } @@ -569,7 +569,7 @@ func isSent(field *reflect.StructField) bool { // If the field is a chan or func or pointer thereto, don't send it. // That is, treat it like an unexported field. typ := field.Type - for typ.Kind() == reflect.Ptr { + for typ.Kind() == reflect.Pointer { typ = typ.Elem() } if typ.Kind() == reflect.Chan || typ.Kind() == reflect.Func { @@ -842,7 +842,7 @@ func Register(value interface{}) { // Dereference one pointer looking for a named type. star := "" if rt.Name() == "" { - if pt := rt; pt.Kind() == reflect.Ptr { + if pt := rt; pt.Kind() == reflect.Pointer { star = "*" // NOTE: The following line should be rt = pt.Elem() to implement // what the comment above claims, but fixing it would break compatibility diff --git a/src/encoding/gob/type_test.go b/src/encoding/gob/type_test.go index 934270eedd..fa3e802d4e 100644 --- a/src/encoding/gob/type_test.go +++ b/src/encoding/gob/type_test.go @@ -184,7 +184,7 @@ func TestRegistrationNaming(t *testing.T) { t.Errorf("nameToConcreteType[%q] = %v, want %v", tc.name, ct, tct) } // concreteTypeToName is keyed off the base type. - if tct.Kind() == reflect.Ptr { + if tct.Kind() == reflect.Pointer { tct = tct.Elem() } if n, _ := concreteTypeToName.Load(tct); n != tc.name { diff --git a/src/encoding/json/decode.go b/src/encoding/json/decode.go index a9917e72c7..df4c5e1a16 100644 --- a/src/encoding/json/decode.go +++ b/src/encoding/json/decode.go @@ -161,7 +161,7 @@ func (e *InvalidUnmarshalError) Error() string { return "json: Unmarshal(nil)" } - if e.Type.Kind() != reflect.Ptr { + if e.Type.Kind() != reflect.Pointer { return "json: Unmarshal(non-pointer " + e.Type.String() + ")" } return "json: Unmarshal(nil " + e.Type.String() + ")" @@ -169,7 +169,7 @@ func (e *InvalidUnmarshalError) Error() string { func (d *decodeState) unmarshal(v interface{}) error { rv := reflect.ValueOf(v) - if rv.Kind() != reflect.Ptr || rv.IsNil() { + if rv.Kind() != reflect.Pointer || rv.IsNil() { return &InvalidUnmarshalError{reflect.TypeOf(v)} } @@ -440,7 +440,7 @@ func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnm // If v is a named type and is addressable, // start with its address, so that if the type has pointer methods, // we find them. - if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() { + if v.Kind() != reflect.Pointer && v.Type().Name() != "" && v.CanAddr() { haveAddr = true v = v.Addr() } @@ -449,14 +449,14 @@ func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnm // usefully addressable. if v.Kind() == reflect.Interface && !v.IsNil() { e := v.Elem() - if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) { + if e.Kind() == reflect.Pointer && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Pointer) { haveAddr = false v = e continue } } - if v.Kind() != reflect.Ptr { + if v.Kind() != reflect.Pointer { break } @@ -641,7 +641,7 @@ func (d *decodeState) object(v reflect.Value) error { reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: default: - if !reflect.PtrTo(t.Key()).Implements(textUnmarshalerType) { + if !reflect.PointerTo(t.Key()).Implements(textUnmarshalerType) { d.saveError(&UnmarshalTypeError{Value: "object", Type: t, Offset: int64(d.off)}) d.skip() return nil @@ -717,7 +717,7 @@ func (d *decodeState) object(v reflect.Value) error { subv = v destring = f.quoted for _, i := range f.index { - if subv.Kind() == reflect.Ptr { + if subv.Kind() == reflect.Pointer { if subv.IsNil() { // If a struct embeds a pointer to an unexported type, // it is not possible to set a newly allocated value @@ -782,7 +782,7 @@ func (d *decodeState) object(v reflect.Value) error { kt := t.Key() var kv reflect.Value switch { - case reflect.PtrTo(kt).Implements(textUnmarshalerType): + case reflect.PointerTo(kt).Implements(textUnmarshalerType): kv = reflect.New(kt) if err := d.literalStore(item, kv, true); err != nil { return err @@ -907,7 +907,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool break } switch v.Kind() { - case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: + case reflect.Interface, reflect.Pointer, reflect.Map, reflect.Slice: v.Set(reflect.Zero(v.Type())) // otherwise, ignore null for primitives/string } diff --git a/src/encoding/json/decode_test.go b/src/encoding/json/decode_test.go index 219e845c7b..96bf9fb5ff 100644 --- a/src/encoding/json/decode_test.go +++ b/src/encoding/json/decode_test.go @@ -1103,7 +1103,7 @@ func TestUnmarshal(t *testing.T) { } typ := reflect.TypeOf(tt.ptr) - if typ.Kind() != reflect.Ptr { + if typ.Kind() != reflect.Pointer { t.Errorf("#%d: unmarshalTest.ptr %T is not a pointer type", i, tt.ptr) continue } diff --git a/src/encoding/json/encode.go b/src/encoding/json/encode.go index e473e615a9..4f40197797 100644 --- a/src/encoding/json/encode.go +++ b/src/encoding/json/encode.go @@ -350,7 +350,7 @@ func isEmptyValue(v reflect.Value) bool { return v.Uint() == 0 case reflect.Float32, reflect.Float64: return v.Float() == 0 - case reflect.Interface, reflect.Ptr: + case reflect.Interface, reflect.Pointer: return v.IsNil() } return false @@ -419,13 +419,13 @@ func newTypeEncoder(t reflect.Type, allowAddr bool) encoderFunc { // Marshaler with a value receiver, then we're better off taking // the address of the value - otherwise we end up with an // allocation as we cast the value to an interface. - if t.Kind() != reflect.Ptr && allowAddr && reflect.PtrTo(t).Implements(marshalerType) { + if t.Kind() != reflect.Pointer && allowAddr && reflect.PointerTo(t).Implements(marshalerType) { return newCondAddrEncoder(addrMarshalerEncoder, newTypeEncoder(t, false)) } if t.Implements(marshalerType) { return marshalerEncoder } - if t.Kind() != reflect.Ptr && allowAddr && reflect.PtrTo(t).Implements(textMarshalerType) { + if t.Kind() != reflect.Pointer && allowAddr && reflect.PointerTo(t).Implements(textMarshalerType) { return newCondAddrEncoder(addrTextMarshalerEncoder, newTypeEncoder(t, false)) } if t.Implements(textMarshalerType) { @@ -455,7 +455,7 @@ func newTypeEncoder(t reflect.Type, allowAddr bool) encoderFunc { return newSliceEncoder(t) case reflect.Array: return newArrayEncoder(t) - case reflect.Ptr: + case reflect.Pointer: return newPtrEncoder(t) default: return unsupportedTypeEncoder @@ -467,7 +467,7 @@ func invalidValueEncoder(e *encodeState, v reflect.Value, _ encOpts) { } func marshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) { - if v.Kind() == reflect.Ptr && v.IsNil() { + if v.Kind() == reflect.Pointer && v.IsNil() { e.WriteString("null") return } @@ -504,7 +504,7 @@ func addrMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) { } func textMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) { - if v.Kind() == reflect.Ptr && v.IsNil() { + if v.Kind() == reflect.Pointer && v.IsNil() { e.WriteString("null") return } @@ -738,7 +738,7 @@ FieldLoop: // Find the nested struct field by following f.index. fv := v for _, i := range f.index { - if fv.Kind() == reflect.Ptr { + if fv.Kind() == reflect.Pointer { if fv.IsNil() { continue FieldLoop } @@ -893,7 +893,7 @@ func (se sliceEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) { func newSliceEncoder(t reflect.Type) encoderFunc { // Byte slices get special treatment; arrays don't. if t.Elem().Kind() == reflect.Uint8 { - p := reflect.PtrTo(t.Elem()) + p := reflect.PointerTo(t.Elem()) if !p.Implements(marshalerType) && !p.Implements(textMarshalerType) { return encodeByteSlice } @@ -989,7 +989,7 @@ func isValidTag(s string) bool { func typeByIndex(t reflect.Type, index []int) reflect.Type { for _, i := range index { - if t.Kind() == reflect.Ptr { + if t.Kind() == reflect.Pointer { t = t.Elem() } t = t.Field(i).Type @@ -1009,7 +1009,7 @@ func (w *reflectWithString) resolve() error { return nil } if tm, ok := w.k.Interface().(encoding.TextMarshaler); ok { - if w.k.Kind() == reflect.Ptr && w.k.IsNil() { + if w.k.Kind() == reflect.Pointer && w.k.IsNil() { return nil } buf, err := tm.MarshalText() @@ -1243,7 +1243,7 @@ func typeFields(t reflect.Type) structFields { sf := f.typ.Field(i) if sf.Anonymous { t := sf.Type - if t.Kind() == reflect.Ptr { + if t.Kind() == reflect.Pointer { t = t.Elem() } if !sf.IsExported() && t.Kind() != reflect.Struct { @@ -1269,7 +1269,7 @@ func typeFields(t reflect.Type) structFields { index[len(f.index)] = i ft := sf.Type - if ft.Name() == "" && ft.Kind() == reflect.Ptr { + if ft.Name() == "" && ft.Kind() == reflect.Pointer { // Follow pointer. ft = ft.Elem() } diff --git a/src/encoding/xml/marshal.go b/src/encoding/xml/marshal.go index a8c8f659ca..1f0eb76341 100644 --- a/src/encoding/xml/marshal.go +++ b/src/encoding/xml/marshal.go @@ -420,7 +420,7 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplat // Drill into interfaces and pointers. // This can turn into an infinite loop given a cyclic chain, // but it matches the Go 1 behavior. - for val.Kind() == reflect.Interface || val.Kind() == reflect.Ptr { + for val.Kind() == reflect.Interface || val.Kind() == reflect.Pointer { if val.IsNil() { return nil } @@ -603,7 +603,7 @@ func (p *printer) marshalAttr(start *StartElement, name Name, val reflect.Value) // Dereference or skip nil pointer, interface values. switch val.Kind() { - case reflect.Ptr, reflect.Interface: + case reflect.Pointer, reflect.Interface: if val.IsNil() { return nil } @@ -797,7 +797,7 @@ var ddBytes = []byte("--") // This can turn into an infinite loop given a cyclic chain, // but it matches the Go 1 behavior. func indirect(vf reflect.Value) reflect.Value { - for vf.Kind() == reflect.Interface || vf.Kind() == reflect.Ptr { + for vf.Kind() == reflect.Interface || vf.Kind() == reflect.Pointer { if vf.IsNil() { return vf } @@ -946,7 +946,7 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error { return err } if len(finfo.parents) > len(s.stack) { - if vf.Kind() != reflect.Ptr && vf.Kind() != reflect.Interface || !vf.IsNil() { + if vf.Kind() != reflect.Pointer && vf.Kind() != reflect.Interface || !vf.IsNil() { if err := s.push(finfo.parents[len(s.stack):]); err != nil { return err } @@ -1055,7 +1055,7 @@ func isEmptyValue(v reflect.Value) bool { return v.Uint() == 0 case reflect.Float32, reflect.Float64: return v.Float() == 0 - case reflect.Interface, reflect.Ptr: + case reflect.Interface, reflect.Pointer: return v.IsNil() } return false diff --git a/src/encoding/xml/read.go b/src/encoding/xml/read.go index ef5df3f7f6..48b0ec055c 100644 --- a/src/encoding/xml/read.go +++ b/src/encoding/xml/read.go @@ -145,7 +145,7 @@ func (d *Decoder) Decode(v interface{}) error { // but also wants to defer to Unmarshal for some elements. func (d *Decoder) DecodeElement(v interface{}, start *StartElement) error { val := reflect.ValueOf(v) - if val.Kind() != reflect.Ptr { + if val.Kind() != reflect.Pointer { return errors.New("non-pointer passed to Unmarshal") } return d.unmarshal(val.Elem(), start) @@ -244,7 +244,7 @@ func (d *Decoder) unmarshalTextInterface(val encoding.TextUnmarshaler) error { // unmarshalAttr unmarshals a single XML attribute into val. func (d *Decoder) unmarshalAttr(val reflect.Value, attr Attr) error { - if val.Kind() == reflect.Ptr { + if val.Kind() == reflect.Pointer { if val.IsNil() { val.Set(reflect.New(val.Type().Elem())) } @@ -324,12 +324,12 @@ func (d *Decoder) unmarshal(val reflect.Value, start *StartElement) error { // usefully addressable. if val.Kind() == reflect.Interface && !val.IsNil() { e := val.Elem() - if e.Kind() == reflect.Ptr && !e.IsNil() { + if e.Kind() == reflect.Pointer && !e.IsNil() { val = e } } - if val.Kind() == reflect.Ptr { + if val.Kind() == reflect.Pointer { if val.IsNil() { val.Set(reflect.New(val.Type().Elem())) } @@ -602,7 +602,7 @@ Loop: func copyValue(dst reflect.Value, src []byte) (err error) { dst0 := dst - if dst.Kind() == reflect.Ptr { + if dst.Kind() == reflect.Pointer { if dst.IsNil() { dst.Set(reflect.New(dst.Type().Elem())) } diff --git a/src/encoding/xml/typeinfo.go b/src/encoding/xml/typeinfo.go index 51e976cf01..6b399b9a0e 100644 --- a/src/encoding/xml/typeinfo.go +++ b/src/encoding/xml/typeinfo.go @@ -67,7 +67,7 @@ func getTypeInfo(typ reflect.Type) (*typeInfo, error) { // For embedded structs, embed its fields. if f.Anonymous { t := f.Type - if t.Kind() == reflect.Ptr { + if t.Kind() == reflect.Pointer { t = t.Elem() } if t.Kind() == reflect.Struct { @@ -229,7 +229,7 @@ func structFieldInfo(typ reflect.Type, f *reflect.StructField) (*fieldInfo, erro // in case it exists and has a valid xml field tag, otherwise // it returns nil. func lookupXMLName(typ reflect.Type) (xmlname *fieldInfo) { - for typ.Kind() == reflect.Ptr { + for typ.Kind() == reflect.Pointer { typ = typ.Elem() } if typ.Kind() != reflect.Struct { @@ -358,7 +358,7 @@ func (finfo *fieldInfo) value(v reflect.Value, shouldInitNilPointers bool) refle for i, x := range finfo.idx { if i > 0 { t := v.Type() - if t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct { + if t.Kind() == reflect.Pointer && t.Elem().Kind() == reflect.Struct { if v.IsNil() { if !shouldInitNilPointers { return reflect.Value{} diff --git a/src/flag/flag.go b/src/flag/flag.go index 885a4c8369..86e16e5a61 100644 --- a/src/flag/flag.go +++ b/src/flag/flag.go @@ -456,7 +456,7 @@ func isZeroValue(flag *Flag, value string) bool { // This works unless the Value type is itself an interface type. typ := reflect.TypeOf(flag.Value) var z reflect.Value - if typ.Kind() == reflect.Ptr { + if typ.Kind() == reflect.Pointer { z = reflect.New(typ.Elem()) } else { z = reflect.Zero(typ) diff --git a/src/fmt/print.go b/src/fmt/print.go index 8bc225f548..698ab557a4 100644 --- a/src/fmt/print.go +++ b/src/fmt/print.go @@ -498,7 +498,7 @@ func (p *pp) fmtBytes(v []byte, verb rune, typeString string) { func (p *pp) fmtPointer(value reflect.Value, verb rune) { var u uintptr switch value.Kind() { - case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer: + case reflect.Chan, reflect.Func, reflect.Map, reflect.Pointer, reflect.Slice, reflect.UnsafePointer: u = value.Pointer() default: p.badVerb(verb) @@ -538,7 +538,7 @@ func (p *pp) catchPanic(arg interface{}, verb rune, method string) { // If it's a nil pointer, just say "". The likeliest causes are a // Stringer that fails to guard against nil or a nil pointer for a // value receiver, and in either case, "" is a nice result. - if v := reflect.ValueOf(arg); v.Kind() == reflect.Ptr && v.IsNil() { + if v := reflect.ValueOf(arg); v.Kind() == reflect.Pointer && v.IsNil() { p.buf.writeString(nilAngleString) return } @@ -866,7 +866,7 @@ func (p *pp) printValue(value reflect.Value, verb rune, depth int) { } p.buf.writeByte(']') } - case reflect.Ptr: + case reflect.Pointer: // pointer to array or slice or struct? ok at top level // but not embedded (avoid loops) if depth == 0 && f.Pointer() != 0 { diff --git a/src/fmt/scan.go b/src/fmt/scan.go index 381577049c..18cb608f43 100644 --- a/src/fmt/scan.go +++ b/src/fmt/scan.go @@ -1017,7 +1017,7 @@ func (s *ss) scanOne(verb rune, arg interface{}) { default: val := reflect.ValueOf(v) ptr := val - if ptr.Kind() != reflect.Ptr { + if ptr.Kind() != reflect.Pointer { s.errorString("type not a pointer: " + val.Type().String()) return } diff --git a/src/fmt/scan_test.go b/src/fmt/scan_test.go index 1cc469ce36..6b71b792ed 100644 --- a/src/fmt/scan_test.go +++ b/src/fmt/scan_test.go @@ -516,7 +516,7 @@ func testScan(t *testing.T, f func(string) io.Reader, scan func(r io.Reader, a . } // The incoming value may be a pointer v := reflect.ValueOf(test.in) - if p := v; p.Kind() == reflect.Ptr { + if p := v; p.Kind() == reflect.Pointer { v = p.Elem() } val := v.Interface() @@ -561,7 +561,7 @@ func TestScanf(t *testing.T) { } // The incoming value may be a pointer v := reflect.ValueOf(test.in) - if p := v; p.Kind() == reflect.Ptr { + if p := v; p.Kind() == reflect.Pointer { v = p.Elem() } val := v.Interface() diff --git a/src/go/ast/print.go b/src/go/ast/print.go index d86d9ba64b..b58683075c 100644 --- a/src/go/ast/print.go +++ b/src/go/ast/print.go @@ -21,7 +21,7 @@ type FieldFilter func(name string, value reflect.Value) bool // it returns false otherwise. func NotNilFilter(_ string, v reflect.Value) bool { switch v.Kind() { - case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: + case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Pointer, reflect.Slice: return !v.IsNil() } return true @@ -165,7 +165,7 @@ func (p *printer) print(x reflect.Value) { } p.printf("}") - case reflect.Ptr: + case reflect.Pointer: p.printf("*") // type-checked ASTs may contain cycles - use ptrmap // to keep track of objects that have been printed diff --git a/src/html/template/content.go b/src/html/template/content.go index 6ba87a9550..232ba199f3 100644 --- a/src/html/template/content.go +++ b/src/html/template/content.go @@ -116,12 +116,12 @@ func indirect(a interface{}) interface{} { if a == nil { return nil } - if t := reflect.TypeOf(a); t.Kind() != reflect.Ptr { + if t := reflect.TypeOf(a); t.Kind() != reflect.Pointer { // Avoid creating a reflect.Value if it's not a pointer. return a } v := reflect.ValueOf(a) - for v.Kind() == reflect.Ptr && !v.IsNil() { + for v.Kind() == reflect.Pointer && !v.IsNil() { v = v.Elem() } return v.Interface() @@ -140,7 +140,7 @@ func indirectToStringerOrError(a interface{}) interface{} { return nil } v := reflect.ValueOf(a) - for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() { + for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Pointer && !v.IsNil() { v = v.Elem() } return v.Interface() diff --git a/src/html/template/js.go b/src/html/template/js.go index 32a4fbd30a..7e919c48e6 100644 --- a/src/html/template/js.go +++ b/src/html/template/js.go @@ -132,7 +132,7 @@ func indirectToJSONMarshaler(a interface{}) interface{} { } v := reflect.ValueOf(a) - for !v.Type().Implements(jsonMarshalType) && v.Kind() == reflect.Ptr && !v.IsNil() { + for !v.Type().Implements(jsonMarshalType) && v.Kind() == reflect.Pointer && !v.IsNil() { v = v.Elem() } return v.Interface() diff --git a/src/internal/fmtsort/sort.go b/src/internal/fmtsort/sort.go index 7127ba6ac3..34c1f477f0 100644 --- a/src/internal/fmtsort/sort.go +++ b/src/internal/fmtsort/sort.go @@ -130,7 +130,7 @@ func compare(aVal, bVal reflect.Value) int { default: return -1 } - case reflect.Ptr, reflect.UnsafePointer: + case reflect.Pointer, reflect.UnsafePointer: a, b := aVal.Pointer(), bVal.Pointer() switch { case a < b: diff --git a/src/internal/reflectlite/tostring_test.go b/src/internal/reflectlite/tostring_test.go index a1e5dae09d..966b0bd849 100644 --- a/src/internal/reflectlite/tostring_test.go +++ b/src/internal/reflectlite/tostring_test.go @@ -44,7 +44,7 @@ func valueToStringImpl(val reflect.Value) string { } else { return "false" } - case reflect.Ptr: + case reflect.Pointer: v := val str = typ.String() + "(" if v.IsNil() { diff --git a/src/net/rpc/server.go b/src/net/rpc/server.go index bfc19ac97c..223a53cfa7 100644 --- a/src/net/rpc/server.go +++ b/src/net/rpc/server.go @@ -203,7 +203,7 @@ var DefaultServer = NewServer() // Is this type exported or a builtin? func isExportedOrBuiltinType(t reflect.Type) bool { - for t.Kind() == reflect.Ptr { + for t.Kind() == reflect.Pointer { t = t.Elem() } // PkgPath will be non-empty even for an exported type, @@ -262,7 +262,7 @@ func (server *Server) register(rcvr interface{}, name string, useName bool) erro str := "" // To help the user, see if a pointer receiver would work. - method := suitableMethods(reflect.PtrTo(s.typ), false) + method := suitableMethods(reflect.PointerTo(s.typ), false) if len(method) != 0 { str = "rpc.Register: type " + sname + " has no exported methods of suitable type (hint: pass a pointer to value of that type)" } else { @@ -307,7 +307,7 @@ func suitableMethods(typ reflect.Type, logErr bool) map[string]*methodType { } // Second arg must be a pointer. replyType := mtype.In(2) - if replyType.Kind() != reflect.Ptr { + if replyType.Kind() != reflect.Pointer { if logErr { log.Printf("rpc.Register: reply type of method %q is not a pointer: %q\n", mname, replyType) } @@ -556,7 +556,7 @@ func (server *Server) readRequest(codec ServerCodec) (service *service, mtype *m // Decode the argument value. argIsValue := false // if true, need to indirect before calling. - if mtype.ArgType.Kind() == reflect.Ptr { + if mtype.ArgType.Kind() == reflect.Pointer { argv = reflect.New(mtype.ArgType.Elem()) } else { argv = reflect.New(mtype.ArgType) diff --git a/src/reflect/abi.go b/src/reflect/abi.go index 2ce7ca2615..28204b8193 100644 --- a/src/reflect/abi.go +++ b/src/reflect/abi.go @@ -198,7 +198,7 @@ func (a *abiSeq) addRcvr(rcvr *rtype) (*abiStep, bool) { // complete register-assignment algorithm for the Go ABI. func (a *abiSeq) regAssign(t *rtype, offset uintptr) bool { switch t.Kind() { - case UnsafePointer, Ptr, Chan, Map, Func: + case UnsafePointer, Pointer, Chan, Map, Func: return a.assignIntN(offset, t.size, 1, 0b1) case Bool, Int, Uint, Int8, Uint8, Int16, Uint16, Int32, Uint32, Uintptr: return a.assignIntN(offset, t.size, 1, 0b0) diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index 922998125b..725be28bf0 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -546,7 +546,7 @@ func TestCanSetField(t *testing.T) { for _, tc := range tt.cases { f := tt.val for _, i := range tc.index { - if f.Kind() == Ptr { + if f.Kind() == Pointer { f = f.Elem() } if i == -1 { @@ -1373,7 +1373,7 @@ func TestIsZero(t *testing.T) { {(map[string]string)(nil), true}, {map[string]string{}, false}, {make(map[string]string), false}, - // Ptr + // Pointer {(*func())(nil), true}, {(*int)(nil), true}, {new(int), false}, @@ -3313,20 +3313,20 @@ func TestPtrTo(t *testing.T) { typ := TypeOf(z) for i = 0; i < 100; i++ { - typ = PtrTo(typ) + typ = PointerTo(typ) } for i = 0; i < 100; i++ { typ = typ.Elem() } if typ != TypeOf(z) { - t.Errorf("after 100 PtrTo and Elem, have %s, want %s", typ, TypeOf(z)) + t.Errorf("after 100 PointerTo and Elem, have %s, want %s", typ, TypeOf(z)) } } func TestPtrToGC(t *testing.T) { type T *uintptr tt := TypeOf(T(nil)) - pt := PtrTo(tt) + pt := PointerTo(tt) const n = 100 var x []interface{} for i := 0; i < n; i++ { @@ -3360,11 +3360,11 @@ func BenchmarkPtrTo(b *testing.B) { } b.ResetTimer() - // Now benchmark calling PtrTo on it: we'll have to hit the ptrMap cache on + // Now benchmark calling PointerTo on it: we'll have to hit the ptrMap cache on // every call. b.RunParallel(func(pb *testing.PB) { for pb.Next() { - PtrTo(t) + PointerTo(t) } }) } @@ -4896,7 +4896,7 @@ func TestArrayOfDirectIface(t *testing.T) { v1 := ValueOf(&i1).Elem() p1 := v1.InterfaceData()[1] - i2 := Zero(ArrayOf(1, PtrTo(TypeOf(int8(0))))).Interface() + i2 := Zero(ArrayOf(1, PointerTo(TypeOf(int8(0))))).Interface() v2 := ValueOf(&i2).Elem() p2 := v2.InterfaceData()[1] @@ -4914,7 +4914,7 @@ func TestArrayOfDirectIface(t *testing.T) { v1 := ValueOf(&i1).Elem() p1 := v1.InterfaceData()[1] - i2 := Zero(ArrayOf(0, PtrTo(TypeOf(int8(0))))).Interface() + i2 := Zero(ArrayOf(0, PointerTo(TypeOf(int8(0))))).Interface() v2 := ValueOf(&i2).Elem() p2 := v2.InterfaceData()[1] @@ -5615,7 +5615,7 @@ func TestStructOfWithInterface(t *testing.T) { }, { name: "StructI", - typ: PtrTo(TypeOf(StructI(want))), + typ: PointerTo(TypeOf(StructI(want))), val: ValueOf(func() interface{} { v := StructI(want) return &v @@ -5624,7 +5624,7 @@ func TestStructOfWithInterface(t *testing.T) { }, { name: "StructIPtr", - typ: PtrTo(TypeOf(StructIPtr(want))), + typ: PointerTo(TypeOf(StructIPtr(want))), val: ValueOf(func() interface{} { v := StructIPtr(want) return &v @@ -5713,7 +5713,7 @@ func TestStructOfWithInterface(t *testing.T) { fields := []StructField{{ Name: "StructIPtr", Anonymous: true, - Type: PtrTo(TypeOf(StructIPtr(want))), + Type: PointerTo(TypeOf(StructIPtr(want))), }} rt := StructOf(fields) rv := New(rt).Elem() @@ -5727,7 +5727,7 @@ func TestStructOfWithInterface(t *testing.T) { fields = []StructField{{ Name: "SettableStruct", Anonymous: true, - Type: PtrTo(TypeOf(SettableStruct{})), + Type: PointerTo(TypeOf(SettableStruct{})), }} rt = StructOf(fields) rv = New(rt).Elem() @@ -5743,7 +5743,7 @@ func TestStructOfWithInterface(t *testing.T) { { Name: "SettableStruct", Anonymous: true, - Type: PtrTo(TypeOf(SettableStruct{})), + Type: PointerTo(TypeOf(SettableStruct{})), }, { Name: "EmptyStruct", @@ -6959,7 +6959,7 @@ func TestGCBits(t *testing.T) { verifyGCBits(t, MapOf(ArrayOf(10000, Tscalarptr), Tscalar), lit(1)) verifyGCBits(t, TypeOf((*[10000]Xscalar)(nil)), lit(1)) - verifyGCBits(t, PtrTo(ArrayOf(10000, Tscalar)), lit(1)) + verifyGCBits(t, PointerTo(ArrayOf(10000, Tscalar)), lit(1)) verifyGCBits(t, TypeOf(([][10000]Xscalar)(nil)), lit(1)) verifyGCBits(t, SliceOf(ArrayOf(10000, Tscalar)), lit(1)) @@ -7028,7 +7028,7 @@ func TestTypeOfTypeOf(t *testing.T) { check("ChanOf", ChanOf(BothDir, TypeOf(T{}))) check("FuncOf", FuncOf([]Type{TypeOf(T{})}, nil, false)) check("MapOf", MapOf(TypeOf(T{}), TypeOf(T{}))) - check("PtrTo", PtrTo(TypeOf(T{}))) + check("PtrTo", PointerTo(TypeOf(T{}))) check("SliceOf", SliceOf(TypeOf(T{}))) } diff --git a/src/reflect/deepequal.go b/src/reflect/deepequal.go index 7f1ecb2809..b71504fa21 100644 --- a/src/reflect/deepequal.go +++ b/src/reflect/deepequal.go @@ -38,7 +38,7 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool) bool { // and it's safe and valid to get Value's internal pointer. hard := func(v1, v2 Value) bool { switch v1.Kind() { - case Ptr: + case Pointer: if v1.typ.ptrdata == 0 { // go:notinheap pointers can't be cyclic. // At least, all of our current uses of go:notinheap have @@ -56,13 +56,13 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool) bool { } if hard(v1, v2) { - // For a Ptr or Map value, we need to check flagIndir, + // For a Pointer or Map value, we need to check flagIndir, // which we do by calling the pointer method. // For Slice or Interface, flagIndir is always set, // and using v.ptr suffices. ptrval := func(v Value) unsafe.Pointer { switch v.Kind() { - case Ptr, Map: + case Pointer, Map: return v.pointer() default: return v.ptr @@ -120,7 +120,7 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool) bool { return v1.IsNil() == v2.IsNil() } return deepValueEqual(v1.Elem(), v2.Elem(), visited) - case Ptr: + case Pointer: if v1.UnsafePointer() == v2.UnsafePointer() { return true } diff --git a/src/reflect/tostring_test.go b/src/reflect/tostring_test.go index e416fd84da..193484a01b 100644 --- a/src/reflect/tostring_test.go +++ b/src/reflect/tostring_test.go @@ -39,7 +39,7 @@ func valueToString(val Value) string { } else { return "false" } - case Ptr: + case Pointer: v := val str = typ.String() + "(" if v.IsNil() { diff --git a/src/reflect/type.go b/src/reflect/type.go index 96f589ca9c..2bb2438381 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -1425,7 +1425,7 @@ func TypeOf(i interface{}) Type { var ptrMap sync.Map // map[*rtype]*ptrType // PtrTo returns the pointer type with element t. -// For example, if t represents type Foo, PtrTo(t) represents *Foo. +// For example, if t represents type Foo, PointerTo(t) represents *Foo. // // Deprecated: use PointerTo. PtrTo is the old spelling. // The two functions behave identically. diff --git a/src/reflect/value.go b/src/reflect/value.go index 3e723e82a4..5d9964eb9d 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -90,8 +90,8 @@ func (f flag) ro() flag { } // pointer returns the underlying pointer represented by v. -// v.Kind() must be Ptr, Map, Chan, Func, or UnsafePointer -// if v.Kind() == Ptr, the base type must not be go:notinheap. +// v.Kind() must be Pointer, Map, Chan, Func, or UnsafePointer +// if v.Kind() == Pointer, the base type must not be go:notinheap. func (v Value) pointer() unsafe.Pointer { if v.typ.size != goarch.PtrSize || !v.typ.pointers() { panic("can't call pointer on a non-pointer Value") @@ -274,7 +274,7 @@ func (v Value) Addr() Value { // Preserve flagRO instead of using v.flag.ro() so that // v.Addr().Elem() is equivalent to v (#32772) fl := v.flag & flagRO - return Value{v.typ.ptrTo(), v.ptr, fl | flag(Ptr)} + return Value{v.typ.ptrTo(), v.ptr, fl | flag(Pointer)} } // Bool returns v's underlying value. @@ -1147,7 +1147,7 @@ func (v Value) Complex() complex128 { // Elem returns the value that the interface v contains // or that the pointer v points to. -// It panics if v's Kind is not Interface or Ptr. +// It panics if v's Kind is not Interface or Pointer. // It returns the zero Value if v is nil. func (v Value) Elem() Value { k := v.kind() @@ -1166,7 +1166,7 @@ func (v Value) Elem() Value { x.flag |= v.flag.ro() } return x - case Ptr: + case Pointer: ptr := v.ptr if v.flag&flagIndir != 0 { if ifaceIndir(v.typ) { @@ -1240,7 +1240,7 @@ func (v Value) FieldByIndex(index []int) Value { v.mustBe(Struct) for i, x := range index { if i > 0 { - if v.Kind() == Ptr && v.typ.Elem().Kind() == Struct { + if v.Kind() == Pointer && v.typ.Elem().Kind() == Struct { if v.IsNil() { panic("reflect: indirection through nil pointer to embedded struct") } @@ -1321,7 +1321,7 @@ func (v Value) Index(i int) Value { return Value{typ, val, fl} case Slice: - // Element flag same as Elem of Ptr. + // Element flag same as Elem of Pointer. // Addressable, indirect, possibly read-only. s := (*unsafeheader.Slice)(v.ptr) if uint(i) >= uint(s.Len) { @@ -1451,7 +1451,7 @@ func (v Value) InterfaceData() [2]uintptr { func (v Value) IsNil() bool { k := v.kind() switch k { - case Chan, Func, Map, Ptr, UnsafePointer: + case Chan, Func, Map, Pointer, UnsafePointer: if v.flag&flagMethod != 0 { return false } @@ -1499,7 +1499,7 @@ func (v Value) IsZero() bool { } } return true - case Chan, Func, Interface, Map, Ptr, Slice, UnsafePointer: + case Chan, Func, Interface, Map, Pointer, Slice, UnsafePointer: return v.IsNil() case String: return v.Len() == 0 @@ -1923,7 +1923,7 @@ func (v Value) OverflowUint(x uint64) bool { // It returns uintptr instead of unsafe.Pointer so that // code using reflect cannot obtain unsafe.Pointers // without importing the unsafe package explicitly. -// It panics if v's Kind is not Chan, Func, Map, Ptr, Slice, or UnsafePointer. +// It panics if v's Kind is not Chan, Func, Map, Pointer, Slice, or UnsafePointer. // // If v's Kind is Func, the returned pointer is an underlying // code pointer, but not necessarily enough to identify a @@ -1938,7 +1938,7 @@ func (v Value) OverflowUint(x uint64) bool { func (v Value) Pointer() uintptr { k := v.kind() switch k { - case Ptr: + case Pointer: if v.typ.ptrdata == 0 { val := *(*uintptr)(v.ptr) // Since it is a not-in-heap pointer, all pointers to the heap are @@ -2491,7 +2491,7 @@ func (v Value) UnsafeAddr() uintptr { } // UnsafePointer returns v's value as a unsafe.Pointer. -// It panics if v's Kind is not Chan, Func, Map, Ptr, Slice, or UnsafePointer. +// It panics if v's Kind is not Chan, Func, Map, Pointer, Slice, or UnsafePointer. // // If v's Kind is Func, the returned pointer is an underlying // code pointer, but not necessarily enough to identify a @@ -2504,7 +2504,7 @@ func (v Value) UnsafeAddr() uintptr { func (v Value) UnsafePointer() unsafe.Pointer { k := v.kind() switch k { - case Ptr: + case Pointer: if v.typ.ptrdata == 0 { // Since it is a not-in-heap pointer, all pointers to the heap are // forbidden! See comment in Value.Elem and issue #48399. @@ -2908,7 +2908,7 @@ func MakeMapWithSize(typ Type, n int) Value { // If v is a nil pointer, Indirect returns a zero Value. // If v is not a pointer, Indirect returns v. func Indirect(v Value) Value { - if v.Kind() != Ptr { + if v.Kind() != Pointer { return v } return v.Elem() @@ -2960,7 +2960,7 @@ const maxZero = 1024 var zeroVal [maxZero]byte // New returns a Value representing a pointer to a new zero value -// for the specified type. That is, the returned Value's Type is PtrTo(typ). +// for the specified type. That is, the returned Value's Type is PointerTo(typ). func New(typ Type) Value { if typ == nil { panic("reflect: New(nil)") @@ -2972,14 +2972,14 @@ func New(typ Type) Value { panic("reflect: New of type that may not be allocated in heap (possibly undefined cgo C type)") } ptr := unsafe_New(t) - fl := flag(Ptr) + fl := flag(Pointer) return Value{pt, ptr, fl} } // NewAt returns a Value representing a pointer to a value of the // specified type, using p as that pointer. func NewAt(typ Type, p unsafe.Pointer) Value { - fl := flag(Ptr) + fl := flag(Pointer) t := typ.(*rtype) return Value{t.ptrTo(), p, fl} } @@ -3048,7 +3048,7 @@ func (v Value) CanConvert(t Type) bool { // Currently the only conversion that is OK in terms of type // but that can panic depending on the value is converting // from slice to pointer-to-array. - if vt.Kind() == Slice && t.Kind() == Ptr && t.Elem().Kind() == Array { + if vt.Kind() == Slice && t.Kind() == Pointer && t.Elem().Kind() == Array { n := t.Elem().Len() if n > v.Len() { return false @@ -3118,7 +3118,7 @@ func convertOp(dst, src *rtype) func(Value, Type) Value { } // "x is a slice, T is a pointer-to-array type, // and the slice and array types have identical element types." - if dst.Kind() == Ptr && dst.Elem().Kind() == Array && src.Elem() == dst.Elem().Elem() { + if dst.Kind() == Pointer && dst.Elem().Kind() == Array && src.Elem() == dst.Elem().Elem() { return cvtSliceArrayPtr } @@ -3134,8 +3134,8 @@ func convertOp(dst, src *rtype) func(Value, Type) Value { } // dst and src are non-defined pointer types with same underlying base type. - if dst.Kind() == Ptr && dst.Name() == "" && - src.Kind() == Ptr && src.Name() == "" && + if dst.Kind() == Pointer && dst.Name() == "" && + src.Kind() == Pointer && src.Name() == "" && haveIdenticalUnderlyingType(dst.Elem().common(), src.Elem().common(), false) { return cvtDirect } @@ -3321,7 +3321,7 @@ func cvtSliceArrayPtr(v Value, t Type) Value { panic("reflect: cannot convert slice with length " + itoa.Itoa(v.Len()) + " to pointer to array with length " + itoa.Itoa(n)) } h := (*unsafeheader.Slice)(v.ptr) - return Value{t.common(), h.Data, v.flag&^(flagIndir|flagAddr|flagKindMask) | flag(Ptr)} + return Value{t.common(), h.Data, v.flag&^(flagIndir|flagAddr|flagKindMask) | flag(Pointer)} } // convertOp: direct copy diff --git a/src/reflect/visiblefields.go b/src/reflect/visiblefields.go index 1a2b53570b..9375faa110 100644 --- a/src/reflect/visiblefields.go +++ b/src/reflect/visiblefields.go @@ -92,7 +92,7 @@ func (w *visibleFieldsWalker) walk(t Type) { w.fields = append(w.fields, f) } if f.Anonymous { - if f.Type.Kind() == Ptr { + if f.Type.Kind() == Pointer { f.Type = f.Type.Elem() } if f.Type.Kind() == Struct { diff --git a/src/runtime/gc_test.go b/src/runtime/gc_test.go index 0ec5331534..7b979afd55 100644 --- a/src/runtime/gc_test.go +++ b/src/runtime/gc_test.go @@ -458,7 +458,7 @@ func benchSetType(b *testing.B, x interface{}) { v := reflect.ValueOf(x) t := v.Type() switch t.Kind() { - case reflect.Ptr: + case reflect.Pointer: b.SetBytes(int64(t.Elem().Size())) case reflect.Slice: b.SetBytes(int64(t.Elem().Size()) * int64(v.Len())) diff --git a/src/testing/quick/quick.go b/src/testing/quick/quick.go index c01647ecf0..777338bb37 100644 --- a/src/testing/quick/quick.go +++ b/src/testing/quick/quick.go @@ -113,7 +113,7 @@ func sizedValue(t reflect.Type, rand *rand.Rand, size int) (value reflect.Value, } v.SetMapIndex(key, value) } - case reflect.Ptr: + case reflect.Pointer: if rand.Intn(size) == 0 { v.Set(reflect.Zero(concrete)) // Generate nil pointer. } else { diff --git a/src/text/template/exec.go b/src/text/template/exec.go index 9ae6fdc3cc..7e44497530 100644 --- a/src/text/template/exec.go +++ b/src/text/template/exec.go @@ -327,7 +327,7 @@ func isTrue(val reflect.Value) (truth, ok bool) { truth = val.Bool() case reflect.Complex64, reflect.Complex128: truth = val.Complex() != 0 - case reflect.Chan, reflect.Func, reflect.Ptr, reflect.Interface: + case reflect.Chan, reflect.Func, reflect.Pointer, reflect.Interface: truth = !val.IsNil() case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: truth = val.Int() != 0 @@ -623,7 +623,7 @@ func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node, // Unless it's an interface, need to get to a value of type *T to guarantee // we see all methods of T and *T. ptr := receiver - if ptr.Kind() != reflect.Interface && ptr.Kind() != reflect.Ptr && ptr.CanAddr() { + if ptr.Kind() != reflect.Interface && ptr.Kind() != reflect.Pointer && ptr.CanAddr() { ptr = ptr.Addr() } if method := ptr.MethodByName(fieldName); method.IsValid() { @@ -665,7 +665,7 @@ func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node, } return result } - case reflect.Ptr: + case reflect.Pointer: etyp := receiver.Type().Elem() if etyp.Kind() == reflect.Struct { if _, ok := etyp.FieldByName(fieldName); !ok { @@ -788,7 +788,7 @@ func (s *state) evalCall(dot, fun reflect.Value, isBuiltin bool, node parse.Node // canBeNil reports whether an untyped nil can be assigned to the type. See reflect.Zero. func canBeNil(typ reflect.Type) bool { switch typ.Kind() { - case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: + case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Pointer, reflect.Slice: return true case reflect.Struct: return typ == reflectValueType @@ -825,12 +825,12 @@ func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Valu // are much more constrained, so it makes more sense there than here. // Besides, one is almost always all you need. switch { - case value.Kind() == reflect.Ptr && value.Type().Elem().AssignableTo(typ): + case value.Kind() == reflect.Pointer && value.Type().Elem().AssignableTo(typ): value = value.Elem() if !value.IsValid() { s.errorf("dereference of nil pointer of type %s", typ) } - case reflect.PtrTo(value.Type()).AssignableTo(typ) && value.CanAddr(): + case reflect.PointerTo(value.Type()).AssignableTo(typ) && value.CanAddr(): value = value.Addr() default: s.errorf("wrong type for value; expected %s; got %s", typ, value.Type()) @@ -982,7 +982,7 @@ func (s *state) evalEmptyInterface(dot reflect.Value, n parse.Node) reflect.Valu // if it's nil. If the returned bool is true, the returned value's kind will be // either a pointer or interface. func indirect(v reflect.Value) (rv reflect.Value, isNil bool) { - for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() { + for ; v.Kind() == reflect.Pointer || v.Kind() == reflect.Interface; v = v.Elem() { if v.IsNil() { return v, true } @@ -1021,7 +1021,7 @@ func (s *state) printValue(n parse.Node, v reflect.Value) { // printableValue returns the, possibly indirected, interface value inside v that // is best for a call to formatted printer. func printableValue(v reflect.Value) (interface{}, bool) { - if v.Kind() == reflect.Ptr { + if v.Kind() == reflect.Pointer { v, _ = indirect(v) // fmt.Fprint handles nil. } if !v.IsValid() { @@ -1029,7 +1029,7 @@ func printableValue(v reflect.Value) (interface{}, bool) { } if !v.Type().Implements(errorType) && !v.Type().Implements(fmtStringerType) { - if v.CanAddr() && (reflect.PtrTo(v.Type()).Implements(errorType) || reflect.PtrTo(v.Type()).Implements(fmtStringerType)) { + if v.CanAddr() && (reflect.PointerTo(v.Type()).Implements(errorType) || reflect.PointerTo(v.Type()).Implements(fmtStringerType)) { v = v.Addr() } else { switch v.Kind() { diff --git a/test/fixedbugs/issue32901.dir/main.go b/test/fixedbugs/issue32901.dir/main.go index 28bb8cde28..673c6ab3e0 100644 --- a/test/fixedbugs/issue32901.dir/main.go +++ b/test/fixedbugs/issue32901.dir/main.go @@ -4,13 +4,16 @@ package main -import "./c" -import "reflect" +import ( + "reflect" + + "./c" +) func main() { x := c.F() p := c.P() - t := reflect.PtrTo(reflect.TypeOf(x)) + t := reflect.PointerTo(reflect.TypeOf(x)) tp := reflect.TypeOf(p) if t != tp { panic("FAIL") diff --git a/test/reflectmethod7.go b/test/reflectmethod7.go index 42429978b4..688238c511 100644 --- a/test/reflectmethod7.go +++ b/test/reflectmethod7.go @@ -16,7 +16,7 @@ func (s S) M() {} func main() { t := reflect.TypeOf(S(0)) - fn, ok := reflect.PtrTo(t).MethodByName("M") + fn, ok := reflect.PointerTo(t).MethodByName("M") if !ok { panic("FAIL") } -- GitLab From 1b2362bb83de47188e7c60a69f46950de542f017 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 26 Oct 2021 09:47:18 -0400 Subject: [PATCH 1747/2500] cmd/compile/internal/typecheck: update doc for the 1.18 export format Update the documentation in iexport.go to use the word 'Constraint' rather than 'Bound', and to account for recent changes to the export format. Change-Id: I83fbcd336d5f865af804bc8bef4f5d997cd9f325 Reviewed-on: https://go-review.googlesource.com/c/go/+/358547 Trust: Robert Findley Trust: Dan Scales Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/typecheck/iexport.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 6057000a5d..f685851e40 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -97,9 +97,10 @@ // // // "Automatic" declaration of each typeparam // type TypeParam struct { -// Tag byte // 'P' -// Pos Pos -// Bound typeOff +// Tag byte // 'P' +// Pos Pos +// Implicit bool +// Constraint typeOff // } // // typeOff means a uvarint that either indicates a predeclared type, @@ -108,7 +109,7 @@ // types list (see predeclared in bexport.go for order). Otherwise, // subtracting predeclReserved yields the offset of a type descriptor. // -// Value means a type and type-specific value. See +// Value means a type, kind, and type-specific value. See // (*exportWriter).value for details. // // -- GitLab From 76cef81bcff371c88d277f17c712ecf22b8c83e7 Mon Sep 17 00:00:00 2001 From: Mark Pulford Date: Sat, 16 Oct 2021 17:53:31 +1100 Subject: [PATCH 1748/2500] cmd/go: stamp VCS commit time into binaries Only Git and Mercurial are supported for now. This CL also: - Skips tagging "revision" and "committime" for empty repositories. - Stores the full Mercurial changeset ID instead of the short form. Fixes #37475 Change-Id: I62ab7a986d1ddb2a0e7166a6404b5aa80c2ee387 Reviewed-on: https://go-review.googlesource.com/c/go/+/356251 Reviewed-by: Bryan C. Mills Trust: Bryan C. Mills Trust: Michael Matloob Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot --- src/cmd/go/internal/load/pkg.go | 13 ++- src/cmd/go/internal/vcs/vcs.go | 86 ++++++++++++++----- .../testdata/script/version_buildvcs_git.txt | 13 ++- .../testdata/script/version_buildvcs_hg.txt | 12 ++- 4 files changed, 97 insertions(+), 27 deletions(-) diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index a5be48a49b..dfe7849516 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -25,6 +25,7 @@ import ( "sort" "strconv" "strings" + "time" "unicode" "unicode/utf8" @@ -2364,10 +2365,14 @@ func (p *Package) setBuildInfo() { setVCSError(err) return } - info.Settings = append(info.Settings, []debug.BuildSetting{ - {Key: vcsCmd.Cmd + "revision", Value: st.Revision}, - {Key: vcsCmd.Cmd + "uncommitted", Value: strconv.FormatBool(st.Uncommitted)}, - }...) + if st.Revision != "" { + appendSetting(vcsCmd.Cmd+"revision", st.Revision) + } + if !st.CommitTime.IsZero() { + stamp := st.CommitTime.UTC().Format(time.RFC3339Nano) + appendSetting(vcsCmd.Cmd+"committime", stamp) + } + appendSetting(vcsCmd.Cmd+"uncommitted", strconv.FormatBool(st.Uncommitted)) } text, err := info.MarshalText() diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go index d1272b66e9..941bd57147 100644 --- a/src/cmd/go/internal/vcs/vcs.go +++ b/src/cmd/go/internal/vcs/vcs.go @@ -18,8 +18,10 @@ import ( "os" "path/filepath" "regexp" + "strconv" "strings" "sync" + "time" "cmd/go/internal/base" "cmd/go/internal/cfg" @@ -54,8 +56,9 @@ type Cmd struct { // Status is the current state of a local repository. type Status struct { - Revision string - Uncommitted bool + Revision string // Optional. + CommitTime time.Time // Optional. + Uncommitted bool // Required. } var defaultSecureScheme = map[string]bool{ @@ -159,24 +162,52 @@ func hgRemoteRepo(vcsHg *Cmd, rootDir string) (remoteRepo string, err error) { } func hgStatus(vcsHg *Cmd, rootDir string) (Status, error) { - out, err := vcsHg.runOutputVerboseOnly(rootDir, "identify -i") + // Output changeset ID and seconds since epoch. + out, err := vcsHg.runOutputVerboseOnly(rootDir, `log -l1 -T {node}:{date(date,"%s")}`) if err != nil { return Status{}, err } - rev := strings.TrimSpace(string(out)) - uncommitted := strings.HasSuffix(rev, "+") - if uncommitted { - // "+" means a tracked file is edited. - rev = rev[:len(rev)-len("+")] - } else { - // Also look for untracked files. - out, err = vcsHg.runOutputVerboseOnly(rootDir, "status -u") + + // Successful execution without output indicates an empty repo (no commits). + var rev string + var commitTime time.Time + if len(out) > 0 { + rev, commitTime, err = parseRevTime(out) if err != nil { return Status{}, err } - uncommitted = len(out) > 0 } - return Status{Revision: rev, Uncommitted: uncommitted}, nil + + // Also look for untracked files. + out, err = vcsHg.runOutputVerboseOnly(rootDir, "status") + if err != nil { + return Status{}, err + } + uncommitted := len(out) > 0 + + return Status{ + Revision: rev, + CommitTime: commitTime, + Uncommitted: uncommitted, + }, nil +} + +// parseRevTime parses commit details in "revision:seconds" format. +func parseRevTime(out []byte) (string, time.Time, error) { + buf := string(bytes.TrimSpace(out)) + + i := strings.IndexByte(buf, ':') + if i < 1 { + return "", time.Time{}, errors.New("unrecognized VCS tool output") + } + rev := buf[:i] + + secs, err := strconv.ParseInt(string(buf[i+1:]), 10, 64) + if err != nil { + return "", time.Time{}, fmt.Errorf("unrecognized VCS tool output: %v", err) + } + + return rev, time.Unix(secs, 0), nil } // vcsGit describes how to use Git. @@ -263,18 +294,33 @@ func gitRemoteRepo(vcsGit *Cmd, rootDir string) (remoteRepo string, err error) { return "", errParse } -func gitStatus(cmd *Cmd, repoDir string) (Status, error) { - out, err := cmd.runOutputVerboseOnly(repoDir, "rev-parse HEAD") +func gitStatus(vcsGit *Cmd, rootDir string) (Status, error) { + out, err := vcsGit.runOutputVerboseOnly(rootDir, "status --porcelain") if err != nil { return Status{}, err } - rev := string(bytes.TrimSpace(out)) - out, err = cmd.runOutputVerboseOnly(repoDir, "status --porcelain") - if err != nil { + uncommitted := len(out) > 0 + + // "git status" works for empty repositories, but "git show" does not. + // Assume there are no commits in the repo when "git show" fails with + // uncommitted files and skip tagging revision / committime. + var rev string + var commitTime time.Time + out, err = vcsGit.runOutputVerboseOnly(rootDir, "show -s --format=%H:%ct") + if err != nil && !uncommitted { return Status{}, err + } else if err == nil { + rev, commitTime, err = parseRevTime(out) + if err != nil { + return Status{}, err + } } - uncommitted := len(out) != 0 - return Status{Revision: rev, Uncommitted: uncommitted}, nil + + return Status{ + Revision: rev, + CommitTime: commitTime, + Uncommitted: uncommitted, + }, nil } // vcsBzr describes how to use Bazaar. diff --git a/src/cmd/go/testdata/script/version_buildvcs_git.txt b/src/cmd/go/testdata/script/version_buildvcs_git.txt index 78ce2e835e..3d56c6d8b4 100644 --- a/src/cmd/go/testdata/script/version_buildvcs_git.txt +++ b/src/cmd/go/testdata/script/version_buildvcs_git.txt @@ -28,16 +28,25 @@ cd .. env PATH=$oldpath rm .git -# If there is a repository in a parent directory, there should be VCS info. +# If there is an empty repository in a parent directory, only "uncommitted" is tagged. exec git init exec git config user.email gopher@golang.org exec git config user.name 'J.R. Gopher' +cd a +go install +go version -m $GOBIN/a$GOEXE +! stdout gitrevision +! stdout gitcommittime +stdout '^\tbuild\tgituncommitted\ttrue$' +rm $GOBIN/a$GOEXE + +# Revision and commit time are tagged for repositories with commits. exec git add -A exec git commit -m 'initial commit' -cd a go install go version -m $GOBIN/a$GOEXE stdout '^\tbuild\tgitrevision\t' +stdout '^\tbuild\tgitcommittime\t' stdout '^\tbuild\tgituncommitted\tfalse$' rm $GOBIN/a$GOEXE diff --git a/src/cmd/go/testdata/script/version_buildvcs_hg.txt b/src/cmd/go/testdata/script/version_buildvcs_hg.txt index 9dcb8dd950..df4938742d 100644 --- a/src/cmd/go/testdata/script/version_buildvcs_hg.txt +++ b/src/cmd/go/testdata/script/version_buildvcs_hg.txt @@ -29,14 +29,24 @@ cd .. env PATH=$oldpath rm .hg -# If there is a repository in a parent directory, there should be VCS info. +# If there is an empty repository in a parent directory, only "uncommitted" is tagged. exec hg init +cd a +go install +go version -m $GOBIN/a$GOEXE +! stdout hgrevision +! stdout hgcommittime +stdout '^\tbuild\thguncommitted\ttrue$' +cd .. + +# Revision and commit time are tagged for repositories with commits. exec hg add a README exec hg commit -m 'initial commit' cd a go install go version -m $GOBIN/a$GOEXE stdout '^\tbuild\thgrevision\t' +stdout '^\tbuild\thgcommittime\t' stdout '^\tbuild\thguncommitted\tfalse$' rm $GOBIN/a$GOEXE -- GitLab From 1dc77a38d293763b9de50110dd72edd755ce72b7 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Fri, 22 Oct 2021 11:37:28 -0400 Subject: [PATCH 1749/2500] internal/fuzz: tiny refactor+fix Change-Id: I8db9c31ead3e5905b7f9d1faed36555e8aaa00cd Reviewed-on: https://go-review.googlesource.com/c/go/+/358054 Trust: Katie Hockman Run-TryBot: Katie Hockman Reviewed-by: Julie Qiu TryBot-Result: Go Bot --- src/internal/fuzz/fuzz.go | 2 +- src/internal/fuzz/worker.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 5b3819be75..5008927f0e 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -702,7 +702,7 @@ func (c *coordinator) logStats() { interestingTotalCount := int64(c.warmupInputCount-len(c.opts.Seed)) + c.interestingCount fmt.Fprintf(c.opts.Log, "fuzz: elapsed: %s, execs: %d (%.0f/sec), new interesting: %d (total: %d)\n", c.elapsed(), c.count, rate, c.interestingCount, interestingTotalCount) } else { - fmt.Fprintf(c.opts.Log, "fuzz: elapsed: %s, execs: %d (%.0f/sec)", c.elapsed(), c.count, rate) + fmt.Fprintf(c.opts.Log, "fuzz: elapsed: %s, execs: %d (%.0f/sec)\n", c.elapsed(), c.count, rate) } } c.countLastLog = c.count diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index e3827b112a..b36ebe2a7e 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -1088,7 +1088,7 @@ func (wc *workerClient) fuzz(ctx context.Context, entryIn CorpusEntry, args fuzz wc.m.r.restore(mem.header().randState, mem.header().randInc) if !args.Warmup { // Only mutate the valuesOut if fuzzing actually occurred. - for i := int64(0); i < mem.header().count; i++ { + for i := int64(0); i < resp.Count; i++ { wc.m.mutate(valuesOut, cap(mem.valueRef())) } } -- GitLab From b54bdd281e62a4658ea4edb5e0a6139006938c9a Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 18 Oct 2021 18:11:48 -0700 Subject: [PATCH 1750/2500] cmd/compile: clean up the switch statements in (*genInst).node() There were two main outer switch statements in node() that can just be combined. Also, for simplicity, changed an IsCmp() conditional into just another case in the switch statement. Also, the inner OCALL switch statement had a bunch of fairly duplicate cases. Combined the cases that all had no special semantics, into a single default case calling transformCall(). In the OCALL case in dictPass(), got rid of a check for OFUNCINST (which will always have been removed by this point). Also, eliminated an assert that could cause unneded failures. transformCall() should always be called if the node op is still OCALL, so no need to assert on the ops of call.X. Added an extra test in issue47078.go, to explicitly check for case where the X argument of a call is a DOTTYPE. Change-Id: Ifb3f812ce12820a4ce08afe2887f00f7fc00cd2f Reviewed-on: https://go-review.googlesource.com/c/go/+/358596 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 161 ++++++++++------------ test/typeparam/issue47878.go | 10 ++ 2 files changed, 85 insertions(+), 86 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 68032e7082..56010a356e 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -928,8 +928,9 @@ func getDictionaryType(info *instInfo, dictParam *ir.Name, pos src.XPos, i int) } // node is like DeepCopy(), but substitutes ONAME nodes based on subst.ts.vars, and -// also descends into closures. It substitutes type arguments for type parameters -// in all the new nodes. +// also descends into closures. It substitutes type arguments for type parameters in +// all the new nodes and does the transformations that were delayed on the generic +// function. func (subst *subster) node(n ir.Node) ir.Node { // Use closure to capture all state needed by the ir.EditChildren argument. var edit func(ir.Node) ir.Node @@ -973,15 +974,15 @@ func (subst *subster) node(n ir.Node) ir.Node { if _, isExpr := m.(ir.Expr); isExpr { t := x.Type() if t == nil { - // t can be nil only if this is a call that has no - // return values, so allow that and otherwise give - // an error. + // Check for known cases where t can be nil (call + // that has no return values, and key expressions) + // and otherwise cause a fatal error. _, isCallExpr := m.(*ir.CallExpr) _, isStructKeyExpr := m.(*ir.StructKeyExpr) _, isKeyExpr := m.(*ir.KeyExpr) if !isCallExpr && !isStructKeyExpr && !isKeyExpr && x.Op() != ir.OPANIC && x.Op() != ir.OCLOSE { - base.Fatalf(fmt.Sprintf("Nil type for %v", x)) + base.FatalfAt(m.Pos(), "Nil type for %v", x) } } else if x.Op() != ir.OCLOSURE { m.SetType(subst.ts.Typ(x.Type())) @@ -991,56 +992,55 @@ func (subst *subster) node(n ir.Node) ir.Node { ir.EditChildren(m, edit) m.SetTypecheck(1) - if x.Op().IsCmp() { + + // Do the transformations that we delayed on the generic function + // node, now that we have substituted in the type args. + switch x.Op() { + case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE: transformCompare(m.(*ir.BinaryExpr)) - } else { - switch x.Op() { - case ir.OSLICE, ir.OSLICE3: - transformSlice(m.(*ir.SliceExpr)) - - case ir.OADD: - m = transformAdd(m.(*ir.BinaryExpr)) - - case ir.OINDEX: - transformIndex(m.(*ir.IndexExpr)) - - case ir.OAS2: - as2 := m.(*ir.AssignListStmt) - transformAssign(as2, as2.Lhs, as2.Rhs) - - case ir.OAS: - as := m.(*ir.AssignStmt) - if as.Y != nil { - // transformAssign doesn't handle the case - // of zeroing assignment of a dcl (rhs[0] is nil). - lhs, rhs := []ir.Node{as.X}, []ir.Node{as.Y} - transformAssign(as, lhs, rhs) - as.X, as.Y = lhs[0], rhs[0] - } - case ir.OASOP: - as := m.(*ir.AssignOpStmt) - transformCheckAssign(as, as.X) + case ir.OSLICE, ir.OSLICE3: + transformSlice(m.(*ir.SliceExpr)) - case ir.ORETURN: - transformReturn(m.(*ir.ReturnStmt)) + case ir.OADD: + m = transformAdd(m.(*ir.BinaryExpr)) - case ir.OSEND: - transformSend(m.(*ir.SendStmt)) + case ir.OINDEX: + transformIndex(m.(*ir.IndexExpr)) - case ir.OSELECT: - transformSelect(m.(*ir.SelectStmt)) + case ir.OAS2: + as2 := m.(*ir.AssignListStmt) + transformAssign(as2, as2.Lhs, as2.Rhs) - case ir.OCOMPLIT: - transformCompLit(m.(*ir.CompLitExpr)) + case ir.OAS: + as := m.(*ir.AssignStmt) + if as.Y != nil { + // transformAssign doesn't handle the case + // of zeroing assignment of a dcl (rhs[0] is nil). + lhs, rhs := []ir.Node{as.X}, []ir.Node{as.Y} + transformAssign(as, lhs, rhs) + as.X, as.Y = lhs[0], rhs[0] + } - case ir.OADDR: - transformAddr(m.(*ir.AddrExpr)) + case ir.OASOP: + as := m.(*ir.AssignOpStmt) + transformCheckAssign(as, as.X) - } - } + case ir.ORETURN: + transformReturn(m.(*ir.ReturnStmt)) + + case ir.OSEND: + transformSend(m.(*ir.SendStmt)) + + case ir.OSELECT: + transformSelect(m.(*ir.SelectStmt)) + + case ir.OCOMPLIT: + transformCompLit(m.(*ir.CompLitExpr)) + + case ir.OADDR: + transformAddr(m.(*ir.AddrExpr)) - switch x.Op() { case ir.OLITERAL: t := m.Type() if t != x.Type() { @@ -1058,16 +1058,13 @@ func (subst *subster) node(n ir.Node) ir.Node { } case ir.OXDOT: - // A method value/call via a type param will have been - // left as an OXDOT. When we see this during stenciling, - // finish the transformation, now that we have the - // instantiated receiver type. We need to do this now, - // since the access/selection to the method for the real - // type is very different from the selection for the type - // param. m will be transformed to an OMETHVALUE node. It - // will be transformed to an ODOTMETH or ODOTINTER node if - // we find in the OCALL case below that the method value - // is actually called. + // Finish the transformation of an OXDOT, unless this was a + // bound call (a direct call on a type param). A bound call + // will be transformed during the dictPass. Otherwise, m + // will be transformed to an OMETHVALUE node. It will be + // transformed to an ODOTMETH or ODOTINTER node if we find in + // the OCALL case below that the method value is actually + // called. mse := m.(*ir.SelectorExpr) if src := mse.X.Type(); !src.IsShape() { transformDot(mse, false) @@ -1080,7 +1077,7 @@ func (subst *subster) node(n ir.Node) ir.Node { // Transform the conversion, now that we know the // type argument. m = transformConvCall(call) - // CONVIFACE transformation was already done in node2 + // CONVIFACE transformation was already done in noder2 assert(m.Op() != ir.OCONVIFACE) case ir.OMETHVALUE, ir.OMETHEXPR: @@ -1116,34 +1113,29 @@ func (subst *subster) node(n ir.Node) ir.Node { transformCall(call) } - case ir.OCLOSURE: - transformCall(call) - - case ir.ODEREF, ir.OINDEX, ir.OINDEXMAP, ir.ORECV: - // Transform a call that was delayed because of the - // use of typeparam inside an expression that required - // a pointer dereference, array indexing, map indexing, - // or channel receive to compute function value. - transformCall(call) - - case ir.OCALL, ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER: - transformCall(call) - - case ir.OCONVNOP: - transformCall(call) - case ir.OFUNCINST: // A call with an OFUNCINST will get transformed // in stencil() once we have created & attached the // instantiation to be called. // We must transform the arguments of the call now, though, // so that any needed CONVIFACE nodes are exposed, - // so the dictionary format is correct + // so the dictionary format is correct. transformEarlyCall(call) - case ir.OXDOT, ir.ODOTTYPE, ir.ODOTTYPE2: + case ir.OXDOT: + // This is the case of a bound call on a typeparam, + // which will be handled in the dictPass. + + case ir.ODOTTYPE, ir.ODOTTYPE2: + // These are DOTTYPEs that could get transformed into + // ODYNAMIC DOTTYPEs by the dict pass. + default: - base.FatalfAt(call.Pos(), fmt.Sprintf("Unexpected op with CALL during stenciling: %v", call.X.Op())) + // Transform a call for all other values of + // call.X.Op() that don't require any special + // handling. + transformCall(call) + } case ir.OCLOSURE: @@ -1268,16 +1260,13 @@ func (g *genInst) dictPass(info *instInfo) { } case ir.OCALL: op := m.(*ir.CallExpr).X.Op() - if op != ir.OFUNCINST { - assert(op == ir.OMETHVALUE || op == ir.OCLOSURE || op == ir.ODYNAMICDOTTYPE || op == ir.ODYNAMICDOTTYPE2) - if op == ir.OMETHVALUE { - // Redo the transformation of OXDOT, now that we - // know the method value is being called. - m.(*ir.CallExpr).X.(*ir.SelectorExpr).SetOp(ir.OXDOT) - transformDot(m.(*ir.CallExpr).X.(*ir.SelectorExpr), true) - } - transformCall(m.(*ir.CallExpr)) + if op == ir.OMETHVALUE { + // Redo the transformation of OXDOT, now that we + // know the method value is being called. + m.(*ir.CallExpr).X.(*ir.SelectorExpr).SetOp(ir.OXDOT) + transformDot(m.(*ir.CallExpr).X.(*ir.SelectorExpr), true) } + transformCall(m.(*ir.CallExpr)) case ir.OCONVIFACE: if m.Type().IsEmptyInterface() && m.(*ir.ConvExpr).X.Type().IsEmptyInterface() { diff --git a/test/typeparam/issue47878.go b/test/typeparam/issue47878.go index cb1043a440..6ad183d221 100644 --- a/test/typeparam/issue47878.go +++ b/test/typeparam/issue47878.go @@ -31,6 +31,13 @@ func (s Src4[T]) Next() { _ = (<-s)() } +type Src5[T any] func() Src5[T] + +func (s Src5[T]) Next() { + var x interface{} = s + _ = (x.(Src5[T]))() +} + func main() { var src1 Src1[int] src1.Next() @@ -43,4 +50,7 @@ func main() { var src4 Src4[int] src4.Next() + + var src5 Src5[int] + src5.Next() } -- GitLab From f8779b9e757e38810bec2284e06fea20bbf09bf4 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 1 Apr 2021 17:01:51 -0400 Subject: [PATCH 1751/2500] runtime: rename _m_ to mp [generated] _g_, _p_, and _m_ are primarily vestiges of the C version of the runtime, while today we prefer Go-style variable names (generally gp, pp, and mp). This change replaces all remaining uses of _m_ with mp. There are very few remaining and all replacements are trivial. [git-generate] cd src/runtime rf 'mv canpanic._m_ canpanic.mp' GOOS=solaris \ rf 'mv semasleep._m_ semasleep.mp' GOOS=aix GOARCH=ppc64 \ rf 'mv semasleep._m_ semasleep.mp' Change-Id: I83690f7b4d4dc57557963100e9a2560ff343f3e8 Reviewed-on: https://go-review.googlesource.com/c/go/+/307813 Trust: Michael Pratt Run-TryBot: Michael Pratt TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/runtime/os3_solaris.go | 42 +++++++++++++++++++------------------- src/runtime/os_aix.go | 8 ++++---- src/runtime/panic.go | 8 ++++---- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/runtime/os3_solaris.go b/src/runtime/os3_solaris.go index 3149d13869..2e946656d0 100644 --- a/src/runtime/os3_solaris.go +++ b/src/runtime/os3_solaris.go @@ -329,20 +329,20 @@ func semacreate(mp *m) { //go:nosplit func semasleep(ns int64) int32 { - _m_ := getg().m + mp := getg().m if ns >= 0 { - _m_.ts.tv_sec = ns / 1000000000 - _m_.ts.tv_nsec = ns % 1000000000 - - _m_.libcall.fn = uintptr(unsafe.Pointer(&libc_sem_reltimedwait_np)) - _m_.libcall.n = 2 - _m_.scratch = mscratch{} - _m_.scratch.v[0] = _m_.waitsema - _m_.scratch.v[1] = uintptr(unsafe.Pointer(&_m_.ts)) - _m_.libcall.args = uintptr(unsafe.Pointer(&_m_.scratch)) - asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&_m_.libcall)) - if *_m_.perrno != 0 { - if *_m_.perrno == _ETIMEDOUT || *_m_.perrno == _EAGAIN || *_m_.perrno == _EINTR { + mp.ts.tv_sec = ns / 1000000000 + mp.ts.tv_nsec = ns % 1000000000 + + mp.libcall.fn = uintptr(unsafe.Pointer(&libc_sem_reltimedwait_np)) + mp.libcall.n = 2 + mp.scratch = mscratch{} + mp.scratch.v[0] = mp.waitsema + mp.scratch.v[1] = uintptr(unsafe.Pointer(&mp.ts)) + mp.libcall.args = uintptr(unsafe.Pointer(&mp.scratch)) + asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&mp.libcall)) + if *mp.perrno != 0 { + if *mp.perrno == _ETIMEDOUT || *mp.perrno == _EAGAIN || *mp.perrno == _EINTR { return -1 } throw("sem_reltimedwait_np") @@ -350,16 +350,16 @@ func semasleep(ns int64) int32 { return 0 } for { - _m_.libcall.fn = uintptr(unsafe.Pointer(&libc_sem_wait)) - _m_.libcall.n = 1 - _m_.scratch = mscratch{} - _m_.scratch.v[0] = _m_.waitsema - _m_.libcall.args = uintptr(unsafe.Pointer(&_m_.scratch)) - asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&_m_.libcall)) - if _m_.libcall.r1 == 0 { + mp.libcall.fn = uintptr(unsafe.Pointer(&libc_sem_wait)) + mp.libcall.n = 1 + mp.scratch = mscratch{} + mp.scratch.v[0] = mp.waitsema + mp.libcall.args = uintptr(unsafe.Pointer(&mp.scratch)) + asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&mp.libcall)) + if mp.libcall.r1 == 0 { break } - if *_m_.perrno == _EINTR { + if *mp.perrno == _EINTR { continue } throw("sem_wait") diff --git a/src/runtime/os_aix.go b/src/runtime/os_aix.go index 54e0cfbb8d..c21da4ddaa 100644 --- a/src/runtime/os_aix.go +++ b/src/runtime/os_aix.go @@ -49,7 +49,7 @@ func semacreate(mp *m) { //go:nosplit func semasleep(ns int64) int32 { - _m_ := getg().m + mp := getg().m if ns >= 0 { var ts timespec @@ -63,17 +63,17 @@ func semasleep(ns int64) int32 { ts.tv_nsec -= 1e9 } - if r, err := sem_timedwait((*semt)(unsafe.Pointer(_m_.waitsema)), &ts); r != 0 { + if r, err := sem_timedwait((*semt)(unsafe.Pointer(mp.waitsema)), &ts); r != 0 { if err == _ETIMEDOUT || err == _EAGAIN || err == _EINTR { return -1 } - println("sem_timedwait err ", err, " ts.tv_sec ", ts.tv_sec, " ts.tv_nsec ", ts.tv_nsec, " ns ", ns, " id ", _m_.id) + println("sem_timedwait err ", err, " ts.tv_sec ", ts.tv_sec, " ts.tv_nsec ", ts.tv_nsec, " ns ", ns, " id ", mp.id) throw("sem_timedwait") } return 0 } for { - r1, err := sem_wait((*semt)(unsafe.Pointer(_m_.waitsema))) + r1, err := sem_wait((*semt)(unsafe.Pointer(mp.waitsema))) if r1 == 0 { break } diff --git a/src/runtime/panic.go b/src/runtime/panic.go index 942898716e..c4f3f41ff5 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -1190,22 +1190,22 @@ func canpanic(gp *g) bool { // Note also that g->m can change at preemption, so m can go stale // if this function ever makes a function call. _g_ := getg() - _m_ := _g_.m + mp := _g_.m // Is it okay for gp to panic instead of crashing the program? // Yes, as long as it is running Go code, not runtime code, // and not stuck in a system call. - if gp == nil || gp != _m_.curg { + if gp == nil || gp != mp.curg { return false } - if _m_.locks != 0 || _m_.mallocing != 0 || _m_.throwing != 0 || _m_.preemptoff != "" || _m_.dying != 0 { + if mp.locks != 0 || mp.mallocing != 0 || mp.throwing != 0 || mp.preemptoff != "" || mp.dying != 0 { return false } status := readgstatus(gp) if status&^_Gscan != _Grunning || gp.syscallsp != 0 { return false } - if GOOS == "windows" && _m_.libcallsp != 0 { + if GOOS == "windows" && mp.libcallsp != 0 { return false } return true -- GitLab From 3a0cd1121413ad02172784114318ac6b0c2801c1 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 9 Jul 2020 09:13:34 -0700 Subject: [PATCH 1752/2500] sync/atomic: use a better first-store-in-progress marker Unlike what the comment says, the GC can see this pointer. Might as well make it a real pointer, even though ^uintptr(0) isn't currently causing problems. Removed the comment about GC not seeing the pointer. Change-Id: I04bc1fd4848698bec6afb79bd5fda671dfc9a073 Reviewed-on: https://go-review.googlesource.com/c/go/+/241661 Run-TryBot: Keith Randall Reviewed-by: Colin Arnott Reviewed-by: Dmitry Vyukov TryBot-Result: Go Bot Trust: Keith Randall --- src/sync/atomic/value.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/sync/atomic/value.go b/src/sync/atomic/value.go index 3500cd22f4..af6295de91 100644 --- a/src/sync/atomic/value.go +++ b/src/sync/atomic/value.go @@ -28,7 +28,7 @@ type ifaceWords struct { func (v *Value) Load() (val interface{}) { vp := (*ifaceWords)(unsafe.Pointer(v)) typ := LoadPointer(&vp.typ) - if typ == nil || uintptr(typ) == ^uintptr(0) { + if typ == nil || typ == unsafe.Pointer(&firstStoreInProgress) { // First store not yet completed. return nil } @@ -39,6 +39,8 @@ func (v *Value) Load() (val interface{}) { return } +var firstStoreInProgress byte + // Store sets the value of the Value to x. // All calls to Store for a given Value must use values of the same concrete type. // Store of an inconsistent type panics, as does Store(nil). @@ -53,10 +55,9 @@ func (v *Value) Store(val interface{}) { if typ == nil { // Attempt to start first store. // Disable preemption so that other goroutines can use - // active spin wait to wait for completion; and so that - // GC does not see the fake type accidentally. + // active spin wait to wait for completion. runtime_procPin() - if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(^uintptr(0))) { + if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(&firstStoreInProgress)) { runtime_procUnpin() continue } @@ -66,7 +67,7 @@ func (v *Value) Store(val interface{}) { runtime_procUnpin() return } - if uintptr(typ) == ^uintptr(0) { + if typ == unsafe.Pointer(&firstStoreInProgress) { // First store in progress. Wait. // Since we disable preemption around the first store, // we can wait with active spinning. -- GitLab From 091db6392da5913e4bd4806215102e461dc5649c Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Wed, 4 Aug 2021 11:24:28 -0400 Subject: [PATCH 1753/2500] runtime: fix cgo signals detection CL 64070 removed lockOSThread from the cgocall path, but didn't update the signal-in-cgo detection in sighandler. As a result, signals that arrive during a cgo call are treated like they arrived during Go execution, breaking the traceback. Update the cgo detection to fix the backtrace. Fixes #47522 Change-Id: I61d77ba6465f55e3e6187246d79675ba8467ec23 Reviewed-on: https://go-review.googlesource.com/c/go/+/339989 Trust: Michael Pratt Run-TryBot: Michael Pratt TryBot-Result: Go Bot Reviewed-by: Cherry Mui Reviewed-by: Ian Lance Taylor Reviewed-by: Austin Clements --- src/runtime/crash_cgo_test.go | 45 ++++++++++++++++++++ src/runtime/signal_unix.go | 6 ++- src/runtime/signal_windows.go | 4 +- src/runtime/testdata/testprogcgo/panic.go | 29 +++++++++++++ src/runtime/testdata/testprogcgo/sigthrow.go | 20 +++++++++ 5 files changed, 100 insertions(+), 4 deletions(-) create mode 100644 src/runtime/testdata/testprogcgo/panic.go create mode 100644 src/runtime/testdata/testprogcgo/sigthrow.go diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go index ce7bed920f..9df6fcd48b 100644 --- a/src/runtime/crash_cgo_test.go +++ b/src/runtime/crash_cgo_test.go @@ -536,6 +536,29 @@ func TestCgoTracebackSigpanic(t *testing.T) { } } +func TestCgoPanicCallback(t *testing.T) { + t.Parallel() + got := runTestProg(t, "testprogcgo", "PanicCallback") + t.Log(got) + want := "panic: runtime error: invalid memory address or nil pointer dereference" + if !strings.Contains(got, want) { + t.Errorf("did not see %q in output", want) + } + want = "panic_callback" + if !strings.Contains(got, want) { + t.Errorf("did not see %q in output", want) + } + want = "PanicCallback" + if !strings.Contains(got, want) { + t.Errorf("did not see %q in output", want) + } + // No runtime errors like "runtime: unexpected return pc". + nowant := "runtime: " + if strings.Contains(got, nowant) { + t.Errorf("did not see %q in output", want) + } +} + // Test that C code called via cgo can use large Windows thread stacks // and call back in to Go without crashing. See issue #20975. // @@ -603,6 +626,28 @@ func TestSegv(t *testing.T) { } } +func TestAbortInCgo(t *testing.T) { + switch runtime.GOOS { + case "plan9", "windows": + // N.B. On Windows, C abort() causes the program to exit + // without going through the runtime at all. + t.Skipf("no signals on %s", runtime.GOOS) + } + + t.Parallel() + got := runTestProg(t, "testprogcgo", "Abort") + t.Log(got) + want := "SIGABRT" + if !strings.Contains(got, want) { + t.Errorf("did not see %q in output", want) + } + // No runtime errors like "runtime: unknown pc". + nowant := "runtime: " + if strings.Contains(got, nowant) { + t.Errorf("did not see %q in output", want) + } +} + // TestEINTR tests that we handle EINTR correctly. // See issue #20400 and friends. func TestEINTR(t *testing.T) { diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go index 07f371cefe..8854629224 100644 --- a/src/runtime/signal_unix.go +++ b/src/runtime/signal_unix.go @@ -688,9 +688,11 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) { } print("PC=", hex(c.sigpc()), " m=", _g_.m.id, " sigcode=", c.sigcode(), "\n") - if _g_.m.lockedg != 0 && _g_.m.ncgo > 0 && gp == _g_.m.g0 { + if _g_.m.incgo && gp == _g_.m.g0 && _g_.m.curg != nil { print("signal arrived during cgo execution\n") - gp = _g_.m.lockedg.ptr() + // Switch to curg so that we get a traceback of the Go code + // leading up to the cgocall, which switched from curg to g0. + gp = _g_.m.curg } if sig == _SIGILL || sig == _SIGFPE { // It would be nice to know how long the instruction is. diff --git a/src/runtime/signal_windows.go b/src/runtime/signal_windows.go index 3fe352ef57..16c36d07f1 100644 --- a/src/runtime/signal_windows.go +++ b/src/runtime/signal_windows.go @@ -218,11 +218,11 @@ func winthrow(info *exceptionrecord, r *context, gp *g) { print("Exception ", hex(info.exceptioncode), " ", hex(info.exceptioninformation[0]), " ", hex(info.exceptioninformation[1]), " ", hex(r.ip()), "\n") print("PC=", hex(r.ip()), "\n") - if _g_.m.lockedg != 0 && _g_.m.ncgo > 0 && gp == _g_.m.g0 { + if _g_.m.incgo && gp == _g_.m.g0 && _g_.m.curg != nil { if iscgo { print("signal arrived during external code execution\n") } - gp = _g_.m.lockedg.ptr() + gp = _g_.m.curg } print("\n") diff --git a/src/runtime/testdata/testprogcgo/panic.go b/src/runtime/testdata/testprogcgo/panic.go new file mode 100644 index 0000000000..4ddef3abcd --- /dev/null +++ b/src/runtime/testdata/testprogcgo/panic.go @@ -0,0 +1,29 @@ +package main + +import "C" + +// This program will crash. +// We want to test unwinding from a cgo callback. + +/* +void panic_callback(); + +static void call_callback(void) { + panic_callback(); +} +*/ +import "C" + +func init() { + register("PanicCallback", PanicCallback) +} + +//export panic_callback +func panic_callback() { + var i *int + *i = 42 +} + +func PanicCallback() { + C.call_callback() +} diff --git a/src/runtime/testdata/testprogcgo/sigthrow.go b/src/runtime/testdata/testprogcgo/sigthrow.go new file mode 100644 index 0000000000..665e3b02df --- /dev/null +++ b/src/runtime/testdata/testprogcgo/sigthrow.go @@ -0,0 +1,20 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +// This program will abort. + +/* +#include +*/ +import "C" + +func init() { + register("Abort", Abort) +} + +func Abort() { + C.abort() +} -- GitLab From 86f6bf18b013d570e89f57c2decaddca5ce2a847 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Wed, 4 Aug 2021 17:33:50 -0400 Subject: [PATCH 1754/2500] runtime: handle async fatal signals in VDSO If we receive an async signal while running in the VDSO, such as a SIGABRT or SIGSEGV sent from another process, we fail to print the stacktrace with "runtime: unknown pc ". We already have machinery to handle SIGPROF in the VDSO, but it isn't hooked up for other signals. Add it to the general signal traceback path. This case is covered by TestSegv by making the test more strict w.r.t. accepted output. Fixes #47537 Change-Id: I755585f70e0c23e207e135bc6bd2aa68298e5d24 Reviewed-on: https://go-review.googlesource.com/c/go/+/339990 Trust: Michael Pratt Run-TryBot: Michael Pratt TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/crash_cgo_test.go | 18 +++++++++++++----- src/runtime/traceback.go | 11 +++++++++-- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go index 9df6fcd48b..0ccfe8580a 100644 --- a/src/runtime/crash_cgo_test.go +++ b/src/runtime/crash_cgo_test.go @@ -526,13 +526,15 @@ func TestCgoTracebackSigpanic(t *testing.T) { } t.Parallel() got := runTestProg(t, "testprogcgo", "TracebackSigpanic") + t.Log(got) want := "runtime.sigpanic" if !strings.Contains(got, want) { - t.Fatalf("want failure containing %q. output:\n%s\n", want, got) + t.Errorf("did not see %q in output", want) } - nowant := "unexpected return pc" + // No runtime errors like "runtime: unexpected return pc". + nowant := "runtime: " if strings.Contains(got, nowant) { - t.Fatalf("failure incorrectly contains %q. output:\n%s\n", nowant, got) + t.Errorf("unexpectedly saw %q in output", want) } } @@ -619,8 +621,14 @@ func TestSegv(t *testing.T) { t.Parallel() got := runTestProg(t, "testprogcgo", test) t.Log(got) - if !strings.Contains(got, "SIGSEGV") { - t.Errorf("expected crash from signal") + want := "SIGSEGV" + if !strings.Contains(got, want) { + t.Errorf("did not see %q in output", want) + } + // No runtime errors like "runtime: unknown pc". + nowant := "runtime: " + if strings.Contains(got, nowant) { + t.Errorf("unexpectedly saw %q in output", want) } }) } diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go index 530d572095..7e1b14ccf2 100644 --- a/src/runtime/traceback.go +++ b/src/runtime/traceback.go @@ -777,16 +777,23 @@ func traceback1(pc, sp, lr uintptr, gp *g, flags uint) { printCgoTraceback(&cgoCallers) } - var n int if readgstatus(gp)&^_Gscan == _Gsyscall { // Override registers if blocked in system call. pc = gp.syscallpc sp = gp.syscallsp flags &^= _TraceTrap } + if gp.m != nil && gp.m.vdsoSP != 0 { + // Override registers if running in VDSO. This comes after the + // _Gsyscall check to cover VDSO calls after entersyscall. + pc = gp.m.vdsoPC + sp = gp.m.vdsoSP + flags &^= _TraceTrap + } + // Print traceback. By default, omits runtime frames. // If that means we print nothing at all, repeat forcing all frames printed. - n = gentraceback(pc, sp, lr, gp, 0, nil, _TracebackMaxFrames, nil, nil, flags) + n := gentraceback(pc, sp, lr, gp, 0, nil, _TracebackMaxFrames, nil, nil, flags) if n == 0 && (flags&_TraceRuntimeFrames) == 0 { n = gentraceback(pc, sp, lr, gp, 0, nil, _TracebackMaxFrames, nil, nil, flags|_TraceRuntimeFrames) } -- GitLab From 80be4a4f90836a33ab5b3d09c6f529de8ee628ea Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 26 Oct 2021 14:47:07 -0700 Subject: [PATCH 1755/2500] crypto/x509: generate new-style build tags for iOS Make the input match gofmt's output, to make our lives easier as we phase out old style build tags. Change-Id: I95dc5a77058bf17cb02e289703f60784616db006 Reviewed-on: https://go-review.googlesource.com/c/go/+/358934 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder Reviewed-by: Brad Fitzpatrick TryBot-Result: Go Bot --- src/crypto/x509/root_ios_gen.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/crypto/x509/root_ios_gen.go b/src/crypto/x509/root_ios_gen.go index 05bd672d5d..3c98de5bb6 100644 --- a/src/crypto/x509/root_ios_gen.go +++ b/src/crypto/x509/root_ios_gen.go @@ -164,8 +164,8 @@ func main() { const header = `// Code generated by root_ios_gen.go -version %s; DO NOT EDIT. // Update the version in root.go and regenerate with "go generate". -// +build ios -// +build !x509omitbundledroots +//go:build ios && !x509omitbundledroots +// +build ios,!x509omitbundledroots package x509 -- GitLab From e5c512520bd0a51d59b39556795a47db888d69b5 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Wed, 28 Jul 2021 11:59:01 -0700 Subject: [PATCH 1756/2500] crypto/elliptic: use a const string for precomputed P256 table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Const strings can be marked readonly. This is particularly important for this relatively large table (88kb). This is a follow-up to CL 315189. The generation script is a bit awkward. It needs access to crypto/elliptic internals, but also needs to be package main. Work around this by exporting those internals with the "tablegen" build tag. This requires changing the function signature at the Go-asm bridge. As long as we're here, shrink the point argument type as well; the net result is three fewer words of params. Performance impact is probably noise. name old time/op new time/op delta ScalarBaseMult/P256-8 11.4µs ± 2% 11.3µs ± 1% -1.32% (p=0.000 n=19+16) ScalarBaseMult/P224-8 579µs ± 1% 577µs ± 0% -0.30% (p=0.024 n=19+20) ScalarBaseMult/P384-8 2.31ms ± 4% 2.34ms ± 4% +1.25% (p=0.033 n=20+20) ScalarBaseMult/P521-8 1.33ms ± 0% 1.33ms ± 1% ~ (p=0.173 n=18+17) ScalarMult/P256-8 42.7µs ± 0% 42.7µs ± 2% ~ (p=0.989 n=20+20) ScalarMult/P224-8 579µs ± 0% 579µs ± 0% ~ (p=0.538 n=19+18) ScalarMult/P384-8 2.32ms ± 3% 2.34ms ± 5% ~ (p=0.235 n=19+20) ScalarMult/P521-8 1.33ms ± 1% 1.34ms ± 2% ~ (p=0.141 n=17+20) Change-Id: I3bee56df34ae61ca8829791d2e67e058ecc8ddbe Reviewed-on: https://go-review.googlesource.com/c/go/+/339591 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder Reviewed-by: Roland Shoemaker Reviewed-by: Brad Fitzpatrick Reviewed-by: Filippo Valsorda TryBot-Result: Go Bot --- src/crypto/elliptic/export_generate.go | 17 + src/crypto/elliptic/gen_p256_table.go | 112 + src/crypto/elliptic/p256_asm.go | 8 +- src/crypto/elliptic/p256_asm_amd64.s | 6 +- src/crypto/elliptic/p256_asm_arm64.s | 6 +- src/crypto/elliptic/p256_asm_table.go | 2886 ++++++++++---------- src/crypto/elliptic/p256_asm_table_test.go | 8 +- 7 files changed, 1569 insertions(+), 1474 deletions(-) create mode 100644 src/crypto/elliptic/export_generate.go create mode 100644 src/crypto/elliptic/gen_p256_table.go diff --git a/src/crypto/elliptic/export_generate.go b/src/crypto/elliptic/export_generate.go new file mode 100644 index 0000000000..5fe3025cf8 --- /dev/null +++ b/src/crypto/elliptic/export_generate.go @@ -0,0 +1,17 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build tablegen +// +build tablegen + +package elliptic + +// This block exports p256-related internals for the p256 table generator in internal/gen. +var ( + P256PointDoubleAsm = p256PointDoubleAsm + P256PointAddAsm = p256PointAddAsm + P256Inverse = p256Inverse + P256Sqr = p256Sqr + P256Mul = p256Mul +) diff --git a/src/crypto/elliptic/gen_p256_table.go b/src/crypto/elliptic/gen_p256_table.go new file mode 100644 index 0000000000..cdcddcb736 --- /dev/null +++ b/src/crypto/elliptic/gen_p256_table.go @@ -0,0 +1,112 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ignore +// +build ignore + +package main + +import ( + "bytes" + "crypto/elliptic" + "encoding/binary" + "fmt" + "go/format" + "log" + "os" +) + +func main() { + buf := new(bytes.Buffer) + fmt.Fprint(buf, ` +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Generated by gen_p256_table.go. DO NOT EDIT. + +//go:build amd64 || arm64 +// +build amd64 arm64 + +package elliptic + +`[1:]) + + // Generate precomputed p256 tables. + var pre [43][32 * 8]uint64 + basePoint := []uint64{ + 0x79e730d418a9143c, 0x75ba95fc5fedb601, 0x79fb732b77622510, 0x18905f76a53755c6, + 0xddf25357ce95560a, 0x8b4ab8e4ba19e45c, 0xd2e88688dd21f325, 0x8571ff1825885d85, + 0x0000000000000001, 0xffffffff00000000, 0xffffffffffffffff, 0x00000000fffffffe, + } + t1 := make([]uint64, 12) + t2 := make([]uint64, 12) + copy(t2, basePoint) + zInv := make([]uint64, 4) + zInvSq := make([]uint64, 4) + for j := 0; j < 32; j++ { + copy(t1, t2) + for i := 0; i < 43; i++ { + // The window size is 6 so we need to double 6 times. + if i != 0 { + for k := 0; k < 6; k++ { + elliptic.P256PointDoubleAsm(t1, t1) + } + } + // Convert the point to affine form. (Its values are + // still in Montgomery form however.) + elliptic.P256Inverse(zInv, t1[8:12]) + elliptic.P256Sqr(zInvSq, zInv, 1) + elliptic.P256Mul(zInv, zInv, zInvSq) + elliptic.P256Mul(t1[:4], t1[:4], zInvSq) + elliptic.P256Mul(t1[4:8], t1[4:8], zInv) + copy(t1[8:12], basePoint[8:12]) + // Update the table entry + copy(pre[i][j*8:], t1[:8]) + } + if j == 0 { + elliptic.P256PointDoubleAsm(t2, basePoint) + } else { + elliptic.P256PointAddAsm(t2, t2, basePoint) + } + } + + fmt.Fprint(buf, "const p256Precomputed = \"\" +\n\n") + + // Dump the precomputed tables, flattened, little-endian. + // These tables are used directly by assembly on little-endian platforms. + // Putting the data in a const string lets it be stored readonly. + for i := range &pre { + for j, v := range &pre[i] { + fmt.Fprintf(buf, "\"") + var u8 [8]byte + binary.LittleEndian.PutUint64(u8[:], v) + for _, b := range &u8 { + fmt.Fprintf(buf, "\\x%02x", b) + } + fmt.Fprintf(buf, "\"") + if i < len(pre)-1 || j < len(pre[i])-1 { + fmt.Fprint(buf, "+") + } + if j%8 == 7 { + fmt.Fprint(buf, "\n") + } + } + fmt.Fprint(buf, "\n") + } + + src := buf.Bytes() + fmtsrc, fmterr := format.Source(src) + // If formatting failed, keep the original source for debugging. + if fmterr == nil { + src = fmtsrc + } + err := os.WriteFile("p256_asm_table.go", src, 0644) + if err != nil { + log.Fatal(err) + } + if fmterr != nil { + log.Fatal(fmterr) + } +} diff --git a/src/crypto/elliptic/p256_asm.go b/src/crypto/elliptic/p256_asm.go index 9a808f260a..d46b809125 100644 --- a/src/crypto/elliptic/p256_asm.go +++ b/src/crypto/elliptic/p256_asm.go @@ -19,6 +19,8 @@ import ( "math/big" ) +//go:generate go run -tags=tablegen gen_p256_table.go + type ( p256Curve struct { *CurveParams @@ -79,7 +81,7 @@ func p256LittleToBig(res []byte, in []uint64) func p256Select(point, table []uint64, idx int) //go:noescape -func p256SelectBase(point, table []uint64, idx int) +func p256SelectBase(point *[12]uint64, table string, idx int) // Montgomery multiplication modulo Ord(G) //go:noescape @@ -410,7 +412,7 @@ func boothW6(in uint) (int, int) { func (p *p256Point) p256BaseMult(scalar []uint64) { wvalue := (scalar[0] << 1) & 0x7f sel, sign := boothW6(uint(wvalue)) - p256SelectBase(p.xyz[0:8], p256Precomputed[0][0:], sel) + p256SelectBase(&p.xyz, p256Precomputed, sel) p256NegCond(p.xyz[4:8], sign) // (This is one, in the Montgomery domain.) @@ -437,7 +439,7 @@ func (p *p256Point) p256BaseMult(scalar []uint64) { } index += 6 sel, sign = boothW6(uint(wvalue)) - p256SelectBase(t0.xyz[0:8], p256Precomputed[i][0:], sel) + p256SelectBase(&t0.xyz, p256Precomputed[i*32*8*8:], sel) p256PointAddAffineAsm(p.xyz[0:12], p.xyz[0:12], t0.xyz[0:8], sign, sel, zero) zero |= sel } diff --git a/src/crypto/elliptic/p256_asm_amd64.s b/src/crypto/elliptic/p256_asm_amd64.s index c77b11bcf2..bd16add241 100644 --- a/src/crypto/elliptic/p256_asm_amd64.s +++ b/src/crypto/elliptic/p256_asm_amd64.s @@ -668,10 +668,10 @@ loop_select: RET /* ---------------------------------------*/ // Constant time point access to base point table. -// func p256SelectBase(point, table []uint64, idx int) +// func p256SelectBase(point *[12]uint64, table string, idx int) TEXT ·p256SelectBase(SB),NOSPLIT,$0 - MOVQ idx+48(FP),AX - MOVQ table+24(FP),DI + MOVQ idx+24(FP),AX + MOVQ table+8(FP),DI MOVQ point+0(FP),DX PXOR X15, X15 // X15 = 0 diff --git a/src/crypto/elliptic/p256_asm_arm64.s b/src/crypto/elliptic/p256_asm_arm64.s index f571c50342..2b2355d57c 100644 --- a/src/crypto/elliptic/p256_asm_arm64.s +++ b/src/crypto/elliptic/p256_asm_arm64.s @@ -324,10 +324,10 @@ loop_select: RET /* ---------------------------------------*/ // Constant time point access to base point table. -// func p256SelectBase(point, table []uint64, idx int) +// func p256SelectBase(point *[12]uint64, table string, idx int) TEXT ·p256SelectBase(SB),NOSPLIT,$0 - MOVD idx+48(FP), t0 - MOVD table+24(FP), t1 + MOVD idx+24(FP), t0 + MOVD table_base+8(FP), t1 MOVD point+0(FP), res_ptr EOR x0, x0, x0 diff --git a/src/crypto/elliptic/p256_asm_table.go b/src/crypto/elliptic/p256_asm_table.go index 16a4b4f224..7f81cb6b3f 100644 --- a/src/crypto/elliptic/p256_asm_table.go +++ b/src/crypto/elliptic/p256_asm_table.go @@ -2,1472 +2,1430 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// Generated by gen_p256_table.go. DO NOT EDIT. + //go:build amd64 || arm64 // +build amd64 arm64 package elliptic -var p256Precomputed = &[43][32 * 8]uint64{ - { - 8784043285714375740, 8483257759279461889, 8789745728267363600, 1770019616739251654, 15992936863339206154, 10037038012062884956, 15197544864945402661, 9615747158586711429, - 9583737883674400333, 12279877754802111101, 8296198976379850969, 17778859909846088251, 3401986641240187301, 1525831644595056632, 1849003687033449918, 8702493044913179195, - 18423170064697770279, 12693387071620743675, 7398701556189346968, 2779682216903406718, 12703629940499916779, 6358598532389273114, 8683512038509439374, 15415938252666293255, - 8408419572923862476, 5066733120953500019, 926242532005776114, 6301489109130024811, 3285079390283344806, 1685054835664548935, 7740622190510199342, 9561507292862134371, - 13698695174800826869, 10442832251048252285, 10672604962207744524, 14485711676978308040, 16947216143812808464, 8342189264337602603, 3837253281927274344, 8331789856935110934, - 4627808394696681034, 6174000022702321214, 15351247319787348909, 1371147458593240691, 10651965436787680331, 2998319090323362997, 17592419471314886417, 11874181791118522207, - 524165018444839759, 3157588572894920951, 17599692088379947784, 1421537803477597699, 2902517390503550285, 7440776657136679901, 17263207614729765269, 16928425260420958311, - 2878166099891431311, 5056053391262430293, 10345032411278802027, 13214556496570163981, 17698482058276194679, 2441850938900527637, 1314061001345252336, 6263402014353842038, - 8487436533858443496, 12386798851261442113, 3224748875345095424, 16166568617729909099, 2213369110503306004, 6246347469485852131, 3129440554298978074, 605269941184323483, - 3177531230451277512, 11022989490494865721, 8321856985295555401, 14727273563873821327, 876865438755954294, 14139765236890058248, 6880705719513638354, 8678887646434118325, - 16896703203004244996, 11377226897030111200, 2302364246994590389, 4499255394192625779, 1906858144627445384, 2670515414718439880, 868537809054295101, 7535366755622172814, - 339769604981749608, 12384581172556225075, 2596838235904096350, 5684069910326796630, 913125548148611907, 1661497269948077623, 2892028918424825190, 9220412792897768138, - 14754959387565938441, 1023838193204581133, 13599978343236540433, 8323909593307920217, 3852032956982813055, 7526785533690696419, 8993798556223495105, 18140648187477079959, - 11692087196810962506, 1328079167955601379, 1664008958165329504, 18063501818261063470, 2861243404839114859, 13702578580056324034, 16781565866279299035, 1524194541633674171, - 8267721299596412251, 273633183929630283, 17164190306640434032, 16332882679719778825, 4663567915067622493, 15521151801790569253, 7273215397645141911, 2324445691280731636, - 9262509587234749312, 6377906816499461739, 15415592259881792841, 6113140067088447267, 17505803833889144731, 3922849788840338823, 6180172597177093790, 7272741317181956640, - 10883262735810583709, 17399134577381480315, 12750035195491397119, 13953097270363313998, 2485196748577282439, 393430759246706702, 3408702096065201083, 16993508724217005008, - 6863012803048745338, 5403358912802668606, 12029756355518540153, 7447472859343023066, 7395681837001497117, 5416243410959797052, 2749045697176435642, 7813683613416962381, - 18350218749545913064, 7509253999860752750, 13295789896366834092, 18326374111226872828, 3258048562491844971, 6342797029666289605, 9612474478300039361, 17807494771134060923, - 9986610307523639857, 6419466267862117340, 324428332031706042, 16344106992423140174, 9434790811884847197, 11733262517030341550, 10475871084940451430, 6836751077061091536, - 6209985515928007176, 8422208926220809341, 7866188125456775984, 17071696982741312252, 17482363193291892153, 1949968206030126177, 8823961512355572132, 13873010936602132387, - 1136614876084383862, 14528605954969250458, 7641208364604111421, 18286716654189762724, 10711679476846124804, 7209187038097309348, 11378652158954714549, 8736575389915992180, - 17651988839102959720, 4019365809979531118, 15024676458991206505, 12622721674297982786, 243375780477240745, 16572583194372185930, 5189991834753707889, 9498206494038386287, - 7870185149723322393, 7858065912377481781, 7050328012468471455, 17977001023138181397, 11912539230960339911, 1290924823368819542, 8532615064753763585, 6439520053123840906, - 11863354073576605599, 8052916203396229040, 16399182063316628399, 10837704607074036270, 5444229620349428264, 10866168931038804304, 1298875461760659950, 8904898233335519592, - 7053953350607273992, 16629865408105641272, 1929728580699289339, 11046110151029488400, 9569890690274721816, 6501378768832742664, 1512621765961532661, 17084264658609527495, - 300662505135603380, 15234062183651308307, 5319536121171934679, 11496182741145732970, 10520610739189276272, 4310163027157056344, 3285324287508696251, 3261468597637865009, - 5427469457023618335, 8296698312021944466, 10882999905197052907, 16825284839961451415, 2106903142647479713, 12008841566652934760, 5361688498494289694, 12228623597691228792, - 6799789383171367218, 17419525584795621504, 10685476378747845090, 16314000862057872712, 11014509959317588121, 10396318154903722147, 9986284919279346079, 4005974039875805723, - 12980531573372269379, 11790791377897350561, 14264262096731994829, 14999393269362129980, 15405842559289002684, 13147503876582120266, 15449556979080143937, 5047767509783027570, - 16354606995222167433, 15941889353688553446, 10301254747221876749, 10704428461746587572, 15702361407127630489, 3283718562982354984, 18081088275079496700, 17549094608770385733, - 15620168851912893400, 13762314693487747007, 13577625382054330775, 4116976667540664996, 712200332640207605, 9098568002202933512, 8905476951567380032, 7075673514150314660, - }, - { - 15811459837282651008, 4038049993244767161, 9054218236388056577, 10807376403937048775, 11113869110590438959, 10336442539492421506, 9228056645601479672, 2983388754829658480, - 7189376137127712298, 9147574701720272724, 3983921661449444789, 12479790317447783959, 13221020976679959405, 13001868979553711359, 17918176319017234744, 18030393246529651080, - 13903368497828271814, 8050546449078305498, 6932373216915935575, 16010012759059004304, 15451708272653450375, 211711129247219149, 10435723642185827585, 17790507800712341232, - 5218985848865375996, 5835476376320976237, 9096499658845542933, 8952489298840360492, 16605895184424459659, 505731104315931813, 17784248872812610986, 4151555707609374291, - 2650786429127545939, 15186825834659456704, 6983758297535957561, 1268007525252235269, 11433489869282443481, 12352824209154665189, 14555720778982121964, 3578659908492218328, - 4038120750249579469, 8304001815287976437, 251700810512667658, 17170873737273596918, 12809642145843734737, 5765073376623244019, 7923401246629348462, 5401634486288115286, - 12830329023522940651, 1302336131164509751, 7011936976469244509, 8446680306499168806, 1386043952588989461, 9057741950701319559, 6719607413978812889, 17371065020414280890, - 4963953120977916566, 6585250545846301109, 4490972754776862709, 10674499592300479120, 17494988318349821345, 1814042777264686189, 8938395423478059768, 9062966010283426056, - 4683683785459765575, 8782133909400988812, 7201726172249963453, 16855412996123591560, 12016536526053703526, 6004686128951599125, 4323130180079993082, 7578596978943754924, - 13272384473390546409, 15052793429857194942, 3597944793474963009, 5659515835454510338, 18013102402609680655, 15096936721974473248, 9096406212198787674, 948405832772983882, - 7533214627823316056, 8009521942734148665, 15370181949218639901, 17395801240657257383, 13217990616373936619, 16323510521919428293, 10737557422966235859, 11113837024463125316, - 3879469818714011415, 11493820457829716643, 10091807027724827301, 5032134849078736052, 18015749204009276046, 9667758283246223357, 4629693773460610802, 3807196436109718946, - 3214144211600931504, 9454007581819416365, 15275469051811991033, 18196204074031746058, 14853793468372596948, 7707818604949749658, 3266782539036976530, 12810995382868348472, - 17461133192060813135, 16870745208936545685, 5903437034120721004, 9683544852742219696, 7903581348090948266, 13461951083275541722, 2454715926022970060, 11781268272016425522, - 3026443193966185195, 8027125782547146632, 17998666917527163386, 17214321347454260227, 10230244243647560419, 8728893474426972780, 16205038544687771303, 13771356055080873468, - 5724217930909760221, 15420221591912350415, 9910465013739250802, 12511683773790779491, 2841532862707547306, 16614426471009646589, 407574220261191228, 17422057170120224031, - 17151505459068312604, 2041124098660595410, 3221606782120899146, 1382742171848704850, 17222534050501711510, 3195635935311449393, 17295393886051199723, 6296241746423654238, - 16510537668852450348, 15650518534057329304, 475704671950317376, 782416820485820540, 10970369699990900408, 16601298147057372792, 1599283701215392453, 8464446359559369186, - 602848212987973622, 9275953159572178443, 15133444738457385545, 7264639569553811785, 14831517002293569763, 4277078717758211028, 12880437544322007232, 16339691585101354857, - 3725101809714764432, 2995111022132376824, 9338883729618021504, 8824923738291347476, 3745497072215538317, 3576446898425965872, 2350077748663612773, 15793255155885543355, - 8020669822852194733, 5865488997462325879, 13508617967776537887, 12934930135071898613, 11708185641249600577, 14265801329217514207, 10451671488560352734, 13251349632343744236, - 10155392082337432799, 16725751190167983672, 17791070776350679280, 6653785531179322348, 10087876256887835780, 8422365820961469204, 13614411778251983480, 11687935452237305960, - 6094298050768263419, 13949448434836272414, 14194554169090099223, 2625524360834828424, 2823844915913169919, 14077211807091283985, 15592587505996634401, 6562949920171518305, - 12904339001067417585, 1972265247859388742, 8908590936681392405, 10320719400504224158, 8298368064038407143, 2105745729886511647, 16509751074757847095, 15156289751671616565, - 13922601558154971179, 10541544592627074316, 9996345160543671471, 2956094548427827774, 3384122842786043431, 7003441038438960180, 11945730502649377204, 14797331669618433927, - 533287349958250211, 13929395807878461602, 10036169742264959424, 18402398814900480008, 8793706913568807269, 4438954128288889267, 13996827050589647592, 6637236830429213437, - 4308464751705576538, 12193581114161194913, 7322672375339219540, 329737085274484939, 15312435499764491079, 1530264129038944128, 1545025965426980152, 14559433923601957161, - 885617946245226760, 17871561572095909264, 16413308527330544768, 2938750343525834336, 6332736376778563648, 16772687696658236231, 9760470695949399178, 17420556823805232882, - 15040671962589188567, 5841393164221253498, 8923415548773111750, 17449640982747951473, 541686588805328549, 9579487672246868564, 12793813917570150236, 5744918442591934533, - 12406806484060734474, 4655292039647906135, 5745141229449178147, 12923621608907306732, 1329768221522217568, 16293616079741201891, 16309603918079351385, 8282635243638078478, - 10842935462043546322, 9397166878596340773, 5807145729199489911, 17083242467628861919, 11473470924584853882, 15220945465200609206, 10470712526179658906, 8129601297261864071, - 4407657041250297528, 13832960959347315977, 15056546959967740939, 4350443362134191429, 8013419913016572733, 8888684099801298477, 15401479253620745715, 18279947201669400847, - }, - { - 7454214833719424418, 2128900810399984335, 8254953962723841408, 5341529923812819418, 11486532916552139238, 4528331821405917357, 5048485034448492541, 4189495710753944825, - 9223539587116638677, 879142711399260546, 2878829560233905572, 13081522393987952773, 3067261963348061547, 16008150780594711643, 5466468631453287640, 16659147898971349582, - 8047766502132608624, 8715815570878148809, 9093649079884580138, 3437267783531715968, 17562225708466062266, 3512667182749067601, 9223059995161026858, 1366690634827047376, - 17929132376737482163, 5565926714491294456, 5252303555134107501, 8169975563698132305, 1829326230943509100, 13780918661853274468, 17736665596871232627, 4246797342334307384, - 5113556452592134569, 7304867793218750141, 6016631926489320290, 16471860203547627727, 3444471410714850041, 16571738096215232488, 2003912224952639024, 4203884000388032492, - 16858425223672505353, 3192567884201479579, 1688923188642613263, 4159042130811153987, 14900413503869744297, 7521485042788722327, 14038093805562042641, 14713051866364662650, - 3738774192924465076, 14037618828827556145, 12882915396530927286, 10882862194263941815, 13115222579444494605, 18244214260845794346, 17217867059738274194, 2458870331386500577, - 8768788172344064509, 2761897497254272960, 1400167175024837359, 2591319596670212133, 1499652044223484974, 6820326453941021707, 9701009499879906773, 6897435972338565418, - 8314355711464256163, 8435944020779763783, 1814803522962187872, 1875253356755380905, 8214588085484192137, 18062045700553127821, 6649947905482043494, 3119726140944397531, - 11881571666857493523, 6300786026612414187, 4928573492087752294, 18343550313462089203, 6770642120472453960, 11296815027803718740, 17312916793783562794, 13028515123652649961, - 583508939637547757, 3195115082527873085, 8497784022800549923, 15135719419829981016, 1180291993378114150, 5447281494912347899, 4710517655176242215, 606503081693490000, - 17732293765863716052, 853971165248416821, 2022886284923413326, 7522564752651732633, 1417954193520965954, 5046659528429172066, 11426939225844711305, 17687206690616539318, - 6518552374736169438, 7940416740434530770, 15228615103587329007, 10662504584317997513, 18370800756791469891, 5564085264882124489, 51043856061444814, 11996026931884728651, - 7009195269496826002, 18330778751427846129, 7903886241001925539, 8198930484643879628, 5453546027419466587, 10378692433982210944, 2242412603379120569, 14762161396393277464, - 6146718865488327808, 8559779132928137805, 14001994895150170346, 9915701789711858841, 17119408219089522083, 4345363585985782988, 7559492126634131602, 17074565022279033371, - 1081257522368061155, 16144982029632101790, 2280210790959566458, 5000326950136078873, 10441086845859171982, 5717080014740953823, 16816253740467637151, 5185838557034755093, - 5835900675852976641, 14850646160621635240, 7784412869482958370, 2550282385659033114, 5102457400165153071, 16480738116286616710, 10726825595752219296, 3297564208881065856, - 1801069609044825811, 12940364451588241698, 11725236374887225564, 4731241880784054295, 8874695411069669852, 10719836334830130110, 12983549127094653526, 3498884940869443564, - 5044718241380586525, 9152928988998314956, 13274353997717834972, 5731942246653336838, 9453579625340936273, 6013700107129234092, 8535405089994224035, 12024982282827680252, - 8296339816955798913, 17352704937535250450, 11768204246645005024, 263391795317009517, 6622964609352808474, 14563414288208376628, 17887389278697258458, 1552357122641071119, - 13193447428787140357, 6701071088186218635, 17090465712567125397, 13844922841372559745, 4526664599449630663, 11321311100342816810, 2490532976442445147, 12506579957986846905, - 15880983134955361922, 12396434033732989105, 16113831675045409693, 2288598422068078002, 2992425583703267972, 5056435264545116829, 12961420259857080621, 3600697676136115398, - 12817090821406743193, 18109694174173693756, 17050997692981853333, 15796663317536421728, 15462568940214327094, 15151767385082666402, 17711108405932879054, 4030072071760424157, - 15725012875727498089, 7622633481063722008, 2241559275264867670, 4018985714167034871, 6507661741395512701, 13435865773135624096, 9564553262368888543, 2283482276790194513, - 2968718708369505078, 5001470555537559034, 985353756026354700, 3145435598301843880, 16410370922030326027, 13981261173663429189, 12565590835494971812, 222252377400865123, - 3096505383227168071, 9129898186148780825, 13266305466206099845, 16135309871416543685, 17993464782237414425, 8124413037611692960, 8497190057115012501, 16568064870411415344, - 7703394153241465824, 2740794419858297964, 4228931976096177316, 11207299659959318490, 3319492324515199082, 15611937984154016609, 3431896575019701337, 10686234123352138088, - 9979039962499030832, 11759414020433216431, 15164411293105859178, 2834464820255498467, 10716371968480406389, 2722055037405581557, 9240657586762413776, 267811388229104916, - 8385388272348876655, 16035999427286017211, 11255427708348651444, 18402964994101916340, 17964277099260928049, 16377129731672778885, 12034488763192562427, 15854195461740399790, - 14134352329607480415, 2406779189916280288, 1148342927890148438, 15859735140823564382, 12055096645840568482, 16044304241162505738, 7466809979198503617, 4519925955244504432, - 576546655711744206, 7729660311499709518, 16864252562359023573, 10537888397995064025, 11828992107618549830, 875843272290362538, 5328675038336932433, 3162100370899364658, - 3897734650128449985, 3892478283047854402, 153850176068596076, 4448963435449755938, 9911011406822436713, 6379744721342779297, 360324666931028426, 8002086405015565067, - }, - { - 18068291112584812890, 10288580446655316879, 16866690514199445805, 15458664010538199871, 17175925202246173890, 12208778610361755998, 927739404697616036, 10330183209424493139, - 17095781462759061506, 13984950766342782369, 7038608479806172868, 7073471193601880894, 9212126909381119712, 15865851343492198107, 3874039137971369196, 15366505242302572319, - 3235058267792568155, 8030551941244615429, 12851363585510555514, 9786973022560471711, 4901414898060251968, 13240438628487941170, 4707852389766057435, 6503805666511566831, - 12081034000518110752, 2773740877021737013, 6429475399936543899, 6804412599792308979, 16082860502313571182, 10013838454082912732, 7176778953927883654, 8065751639278576331, - 2577328127707636877, 17299987330349518428, 15104751346159263209, 15422444943335124822, 7934601464470854115, 2803659700354182364, 186161376356596699, 10049927908892587253, - 14226302346438044875, 11259466681405724608, 3945860952925292329, 3287876564263331089, 9461394118536996000, 12404803552046013762, 16569223065554335449, 15881973563254196893, - 6665552777203645232, 5302850683863152336, 7778922028047389493, 14212904863357452615, 15966527672828304861, 3802704091320278344, 10517530714917238300, 3742971938824724276, - 17741525051518363144, 1374267330336191942, 4677891169679898540, 9639823611685431337, 5482431056894095950, 6629146695374718376, 3884574854221819712, 13266790928096813258, - 16028684877412556061, 13405436055762225966, 12268280467958284214, 17956874998292211440, 8610745336676661311, 2945210828327041653, 7889492068658434371, 8032335517518163423, - 17096678157067198548, 11751872841896846778, 14951591239724148110, 14946797103632354342, 15001812923533485850, 1354666869219009884, 15934246013528228877, 17674533676709494379, - 5120889077991995845, 1349360562851394781, 7965752316528770369, 16276575673105864366, 16613052983770261287, 11454051240568463780, 16146905806612132291, 15806571503343623359, - 17505459029376928465, 14087658194607915364, 12240552390931686885, 1809009366037859941, 9468395484396723291, 9446052656478984520, 3720796795453397330, 18035355127900871187, - 10937782812576841853, 2203021845094443505, 9622750764486021477, 5518948515641487288, 8021555402800950130, 8884074473434139094, 3925095588129480413, 6199533424090268508, - 3824657730049729815, 4646911366274335188, 5283751816651713473, 16396970607630079440, 9102362834410101425, 3641728106404110497, 5923630184251416230, 13179374259571264822, - 656781601862662976, 13284523818709348938, 14255949685810234815, 17662122984572331094, 14005272187244763785, 2769973460677437621, 9745740172208222044, 4399769039990314590, - 18221138344920380175, 16761112742545021198, 14421639991115588619, 9419167563943683547, 6237248361283446238, 889754338720059891, 2289880386545166424, 4280148734121099084, - 8456687949810928719, 6224977199672540221, 9826855484829367341, 10345583292656523462, 715642447678891171, 10791247680314230673, 4390153264475025171, 6710036254773432312, - 11434352627810350015, 2720291857616706675, 15035363195148805272, 2358906741960696657, 9439888337759970778, 9654563570832962181, 6013570511081660799, 12742404245236356978, - 16538557679183724426, 6137267799072203525, 13879005145532324670, 14569289845201353615, 13784903266526414562, 1051135786146476033, 9343275973150690259, 18338317230916899584, - 5259165122317589354, 6306061166879114159, 2622163270351284906, 15212813592118086979, 11497359168652342849, 7085380391293263482, 11799059272489792659, 4912160901181298022, - 10956239956289671191, 12649697329483184719, 17174497942073298839, 16454040570484021598, 1964314354536023134, 15533681501854792750, 11384243972598433754, 14387731385073008825, - 1627256545355657442, 9010013556811110994, 14616120598404631231, 8391972858400276155, 244817907132802237, 1484397967210729699, 2663560284299448875, 4820353472962713985, - 6567121006858416952, 17119959301239619281, 3965303761563489817, 10211688306206007722, 724618943950031080, 16749575186941231354, 9181397347361086360, 470616631211702666, - 10512473611770099290, 11735037909076331019, 2922606398008539984, 2599799834378751770, 10226702495047936424, 6109026252412854338, 15572556822827169237, 11993701786788749663, - 12951512375864063487, 9270845327881823041, 13198171264747338719, 9240466821667660686, 14918848310897324032, 10111918274408213257, 9869937817792431868, 11316967879062014936, - 5691364106926740802, 2782311978438620206, 13067832493996441150, 12682941211395745221, 10515041347274706648, 9910726429809603026, 10540072260993990483, 15078586909891471233, - 10892036011159420575, 9833543566604313963, 15176473361412960115, 14504845496732895720, 15845034940445278100, 5364672156984348678, 308167090528488415, 12390239901799634313, - 5106897453764491321, 10540479232768400094, 3938246597140945859, 13156157265138481529, 4932443191001849637, 11374218582626530502, 2907557293167002437, 6807344711257391317, - 5413712686694380670, 13147753106081951274, 2960292187746417883, 13977097845105551070, 17642067093469099040, 7699556298723812469, 11597002672863564976, 12392265705126521509, - 4607947077536257852, 17763906282816835996, 11288463953418287893, 18299911648497821660, 3194698850612319839, 13371221457376435780, 10047718724723936081, 4488868185988157408, - 13742985513958274859, 14201726926009534105, 2183997556320958457, 2564950343266657518, 8846625471673389624, 10147673280504740463, 186524308060896613, 16409126738088317791, - 3993197157612782947, 14810882170056329119, 3476738916713041107, 1512933700383846542, 17820889751141311776, 9132720567660500233, 17598924894608972696, 9704537908665702455, - }, - { - 15695265447782578013, 15506558718447241194, 12341861439298989232, 18400958156300100845, 13704811286967591150, 5802260047239067846, 3266013253411255445, 9892957742319181954, - 6053458788987550519, 3243549259991905443, 17990025476026266205, 3918149716414968130, 562225565996136148, 12175287017902713154, 16317970834262634990, 5431198806775607012, - 15123186170178367264, 3054913246068400920, 8130663466272395280, 2852812622149318730, 6747630551931917110, 18302049774259156971, 3663865061939346221, 12340091610704678811, - 17453312277789785069, 1148609799196055657, 5931758962926317381, 5297597381576544508, 9136842287749269744, 3007653173299649609, 12364677607049679091, 3656932227466449489, - 17732801126130995365, 16093023291975796560, 17028512234142609413, 6293028118993952199, 4019599708379609715, 3557632583507755601, 16737140015288442165, 7041678499288317736, - 5187842645752673199, 14914432544387315508, 4944360914161982641, 4177329533692612281, 18423887817846407126, 11935898134550505219, 9191754399457615042, 962223885189306707, - 5467152559317256227, 13407023128339380091, 656806207084558176, 10823228592509573890, 282802378108427873, 13003319652664166176, 11501612671901244594, 8595770155487539951, - 1805255869285898834, 11676967700876044626, 3486630203654875772, 8366336693945605431, 17874084888474647879, 8803709150655606891, 680993178667234696, 1603785777136148315, - 3637712241808318043, 1673622542455477465, 14468899013751477571, 6607241816357171779, 2332200248940843815, 14077155355848738174, 17298155509321457563, 13624623885136011130, - 12550073596584561722, 13898852145577133829, 31360866049197404, 12629522544897401454, 4563446134761510332, 7272813487383198495, 16767195814334178362, 13600498026689482359, - 5170414136067325373, 10875290278133558518, 7331268231382198947, 4082234313337835514, 11725295114019619895, 6488017511603508543, 11399466652931338200, 2898113599278666684, - 7553418756944942759, 2324485560009697358, 16004009784734101843, 8345371056076551939, 7377284629098981027, 11049718262343754276, 8021605820736410979, 8175349759714152494, - 805625092558946929, 11996029844853502332, 1725029464967101849, 8189609560660709539, 10396089572662865065, 1756007811373736605, 7645529329516777410, 2608132938055260111, - 17014595621244604813, 1574499958190108567, 8684546755761322906, 9997538531915911005, 5652402150243592363, 6315865356369667235, 8687115108443972047, 12369176255146729475, - 5117004045853299762, 2238407612548002914, 12392667457861900490, 10614312910576266709, 6446577503758597410, 3767883614425995197, 17954966454260719539, 5233322901463099, - 9194523390605857831, 2335161171394626054, 12290490336543843159, 12464172604156286188, 15842196578033029974, 9081285134201585379, 6123406461662038242, 5504260508195082396, - 5345718195770885739, 10397124463462860788, 13439280718993427040, 15556816356929214653, 17286785976489019906, 13891416634083443852, 16346644312573564447, 917629419222512011, - 7892626957952656865, 11229871638807701267, 5249460237065799805, 9529842808650392581, 11803106868201977918, 4600784567377577444, 7178870186583927975, 13829108773971861655, - 1289703927368007546, 16175369390684210381, 2195306032582966573, 11284704298115036296, 4385727852306374408, 6915138269030006111, 13440775052829788601, 7742359656861485339, - 1418252737937945274, 10664598666472920539, 5146625453081549320, 7716408631061669307, 15481216546649435253, 9087869057854823101, 8438781502742166926, 16066665509570633845, - 13091912700111633391, 15443255616678375884, 11338466119311799740, 9641919445273031117, 12359044485240987114, 7665168466660756789, 13845183791692700257, 10700410793152785934, - 8528578803314347534, 18126789418189181716, 6819229450418907940, 10542951903574211724, 10335954505229790439, 773396809431100386, 763679854573261611, 7782804492252573047, - 14102889564247144327, 15479515297699126743, 6400257822506917934, 12400211936189844586, 8190162441518233318, 16489757979266243333, 11074854544980782334, 5650848136444824725, - 49299995316533601, 1658812626798186796, 14321322055030354, 1062750633396640947, 11458188738562323084, 10319462683954522885, 15398455357851813321, 9473384090828584828, - 17723857482947114516, 17563952877363564604, 3160294749187111891, 15485369139883303866, 7487527166185553604, 9661144290316674030, 16387431126208996705, 7499766964252214921, - 18331281993562501191, 16034836629143884193, 11149238385567891503, 1413880911197321245, 513884082842080653, 462183409527465946, 404977499728878854, 1459875951423441439, - 17249202826373649180, 11151860661862313351, 13606113651347187963, 13653298062695357606, 12346841931589648448, 10659825520992339734, 17857177794617595021, 12846976930859175746, - 7421386827645898229, 4567141110780940726, 9022716764262477732, 7287282267953917487, 12950322172330872807, 2675202024861592519, 18339036521791481203, 7003909904344391740, - 13539440097944399044, 7108271818419613260, 13229113021954558930, 14920952138366964142, 11082363944167072746, 16156446445495173622, 15515349862819133984, 12359827931233605745, - 17013104138257181849, 6982996767213561282, 16259302607976830987, 1579942890487532721, 8635464047344487404, 10435012080572068738, 2976844365866972753, 9471858478345924179, - 2347775782107812070, 311367032040459687, 10852128873404113998, 1338612296059509077, 1599132038614432432, 11533828746166635650, 14264087792956755961, 13004615331499537807, - 9599159247384506427, 13011559959971256245, 6331802547989957841, 2642320882309956905, 9140255367820630480, 6883541786494880896, 9560822438260750771, 9273862677291701694, - }, - { - 6185067974942684922, 6452325785873503452, 15247257292915812252, 3689324664200339196, 3264129576054154137, 14977721630214750038, 10720913377937894256, 15914487080763816378, - 5498621600689515064, 11498885804037952971, 12697073118321478539, 13999008478737234463, 4324885099420360642, 14021182496192299466, 10763088992583373843, 12898585157666243299, - 11622402383521841588, 18271726976204770291, 4805501248621435402, 13483122453682180759, 9288143526654965614, 4688427612851085031, 3280806057528512375, 2249349779106893174, - 2317249352525369754, 15030797481081533168, 12237590576308284360, 15660076992611440873, 11341015819700735887, 8280257602754365719, 9212501234696283343, 9673375202141178099, - 1576552382781604867, 14644873134348781157, 9860879950368557094, 12941927431704225849, 11959666739052502184, 16171152369226594315, 18364294470656574060, 15172859394935215584, - 7521577570681641021, 410124023045579310, 13806534589183327176, 2731801491329207875, 9959087943014269549, 16205635445474657221, 12069145915768935630, 14906463509471682144, - 13803661539609326912, 3233094883493439444, 13409742688319755923, 4298169788674760921, 12847636671560067434, 6702365884489797170, 5650404576647289813, 7380374625644226212, - 9762534010701623728, 15349113802811029024, 8305297169667044246, 18013018210154476198, 18414050009163335761, 2190126859433916996, 5444481274452218807, 13415988647365667724, - 12538763466834894269, 1385338113050483955, 17489001033590767373, 12734464941837886525, 5762578105750980174, 1466528690684075875, 4231060025049573530, 11218444849081704286, - 13520439252664960951, 3770430920651384098, 18274623217805904547, 11545267616883260257, 4084783424859113779, 13863968977657663867, 10237835480648574698, 7395611844854084274, - 12891185742908997266, 2889148203703402614, 663579373261619221, 7616112456816883701, 9002890885722034437, 10753730807791931375, 3553894671829778441, 4368240432504457389, - 11641532224340210206, 71261001011952801, 2321745415903209397, 6595984444855093239, 10341299657770272718, 11529878689049370930, 14381510695605158203, 6869272773579747365, - 18407769999912340511, 13801873415230385184, 8080153703167941484, 14143463895182697871, 5248006623352376562, 9271982788122934275, 11225161179021692620, 5076519449784098178, - 2388868518767189674, 381125256886459269, 11316805024982236485, 11671355336111917711, 3564177948445768908, 5245093046097324328, 16144139891410041039, 1201010948447708436, - 16591032462856670656, 533850935988668408, 2263232738784171066, 5572124915367282948, 12583782854491678471, 15015562207264407653, 1167486851113549964, 2987176661273439670, - 1073778278665127828, 301289653767944933, 11482324780950168317, 10626716202328004967, 7258024014655363102, 12597648090458567878, 2617914106162603499, 12324652644266476584, - 3803745429517922765, 1699256829990081513, 2179986933466617785, 4330084096014112280, 10403896221616386733, 11682369673591069651, 3879392495596713886, 17249085256521020624, - 13938687445393525296, 13822790166673492712, 13216892716897321740, 2165870280409061482, 9147830602451471293, 16339144108911449834, 17837507766320968023, 15340710005345158245, - 4485838034764604283, 8426970493386126530, 7709201418726935942, 13468796449943783583, 16441091014185628843, 2374269830239737237, 13423059086148485716, 17132218391020520330, - 13957732574177025801, 1100344278733481546, 12156946932617203965, 2007756425747006287, 16454508610548016441, 18058668363064769203, 15619001054652658323, 1201476243910931863, - 1292412381963708933, 10908631677673353277, 15138649576688192753, 10741579086621436813, 16534963566169304684, 10228646729525192055, 4256608246548223655, 16176814322718522963, - 3012125536603284881, 5466178753014623970, 16598422155702380175, 9902071731736699653, 13861556771123036741, 9534711573278556274, 9805898455743897538, 14683694395093520838, - 9125214754744730198, 143353181770418225, 8976042597473555858, 13405481215779362056, 2863125481657826330, 12333764090388731260, 15250359513836914002, 5086706595778559056, - 16341334571424533804, 4657494880554316004, 18092783076286521475, 19832895869027143, 8667365497283429486, 11501953273367138162, 5832487631687776985, 664754160781757174, - 13604774408440609080, 12660956565879820101, 4535452877362385626, 8063311919592303330, 4591511734775484245, 5164119991271568303, 5282209033000495913, 15181017218549722334, - 5070228782679699429, 277881850788922387, 17424210585510719837, 13586569401109299583, 16661809787463692974, 11543434536078774133, 2062889565117549061, 14261113517104795690, - 17683343658262519228, 13727986689138309987, 9352982220536939533, 7578301410191413286, 7970586266869249410, 14357824150096386968, 4381700479561442130, 13217807763329274501, - 13524719886605363170, 11553593166914861649, 12034020205580665813, 985175984881624722, 11040631342644137311, 12107496606245418129, 7328748654066365904, 14741972847454326011, - 9790251609380109406, 2449588380962781369, 4694893010228180943, 5172145489692928848, 5411277023198532852, 12752098113265127406, 4559500999103209672, 14921033543082064351, - 2248082728820243864, 8720404853152831367, 12431505213690884811, 14883031570121462817, 2278273022936639560, 14988529405400451352, 16732922988142595529, 1071232319627396164, - 8793441611217807824, 13198147137434605751, 8167936709747999601, 7685928882032231744, 8779182451658438210, 8059106577297479923, 18394590909567718507, 15508315617300242773, - 12828567388121500364, 2264959796189127526, 6222205589523394088, 8827682270015065013, 2619170858745203321, 14835030117099398518, 5960028394532808010, 2233397097850889639, - }, - { - 16319476863352440541, 10283930715856640343, 17675054544532098447, 11261132162985242084, 13712716897981761400, 2681907143459288706, 6930256922080133347, 1445069157579547822, - 16928574868467385886, 166417019993787654, 5882811520342817815, 14106304179344008065, 3747123724781081800, 197109533566874475, 14303280595714789450, 15457633026018307066, - 10773597511592584859, 12552868588431074640, 13500771767160426835, 8002499270056378440, 13792839099998553174, 12949371255843262119, 1713974340992291550, 16150173130483658061, - 14745984256428057001, 9333707338036985191, 15365925315303462, 11789129028059619744, 7873100217437235208, 5289763977161829145, 17731215200358323788, 8876377479309635703, - 265950821974454804, 5047467530470542278, 17523044368516619801, 10054436503372765176, 10321185867287373431, 1212061937729015591, 15311258419138633926, 11236518538207084768, - 10904693956407098222, 9013418755007070130, 15510005599846320670, 995378633446250700, 12234095025518917836, 6689106237771514188, 2809193993744369126, 548124799387888260, - 267350765778774337, 2853877351938464055, 3677119082593358544, 7685335121077514739, 6491980094762370981, 1384870316654548002, 10568872345228996498, 241629538659623878, - 5839400175629113441, 5238299193248381245, 16787876416022887315, 6051613843621920008, 9219569873668974552, 5916753090530931032, 13390630214643423749, 3265335490455191268, - 1507475744849985303, 2597075068965622770, 14968669113917266926, 597606442423659891, 44293923912414886, 3832651144752540816, 17438860065613195810, 782112340603343331, - 9050896199196733903, 6427608033444590004, 13787696679536621857, 9682087046920409188, 4519093754155995429, 13564098392055667371, 10512507082236058799, 5289934424008191746, - 3477191607403300916, 18283244229745029067, 8462159792484018099, 3056576498976014760, 7259283167233712785, 12530251965039903998, 10232104933720625111, 14190745998092156987, - 15759362035410895911, 16075598437961371531, 4651513528876405575, 7694151626503869614, 14468862724637972284, 1838601521755586245, 4168957446435305706, 8694905613027663664, - 14825552838983151434, 8639609968952840931, 15547914584352392016, 2313507499500708287, 6902543375698033684, 9987468886016348918, 9068175779860656258, 6899641689193116297, - 7449110402827616954, 5689206471789540768, 12722069021950813669, 16017131401246233663, 2240977975275954837, 4794705713606614946, 5734937900461809607, 118285984764445639, - 13917685647531721740, 2432096911145792817, 17733637484624159521, 3848601825403209903, 8192433211051054683, 17388066421914150767, 14336306308847565282, 7501625553608785022, - 9844707592410952215, 8167497709587672711, 18115463401502884199, 8471563375691441535, 17525405040226359165, 2460181803833371342, 3375780580907171205, 3024376384135966552, - 15446204978718816914, 10131769697256428720, 10937168660849553757, 12174257400309926241, 4774490771219074715, 13764876998736771340, 14299051476546774038, 11409551629093945893, - 5471366060803425265, 5927845172343647238, 13321967429805195545, 1981489848211999240, 3657997933879283852, 1341488083977381854, 11001000434984172675, 12666440712128450303, - 2127920575549495889, 8861781778185702064, 10501256952986753134, 8967441017586595593, 12224364761159418844, 11856305587178745520, 8176487286367052930, 4988165299911239066, - 12279712962388998309, 7552494563001503282, 7388800608466198128, 15704167671257743517, 17781278773093632973, 6688613358271814698, 12261263098366698895, 2585757657252460656, - 17064077609211627595, 14437064866605257652, 14386408901468621215, 14935685266532365200, 16350265985491822570, 5195856143474093260, 4623415440658404410, 2936315929072503688, - 18399447684263070219, 11294713679768342649, 1600242588657342501, 2841752419388937826, 15111313732750279467, 8179471361906256467, 10611923788752807866, 10823997080784081293, - 15607034385960553579, 6934034624930683639, 13318618594774430459, 7552865293216027192, 13692640408995992185, 11143313220936824014, 16721999332340829387, 6993089466645938014, - 1749509641415861857, 8597876492914031095, 17942224190138398306, 1760222146515426983, 1030117883582412628, 6655464189981098460, 14222900139576809037, 13041171493967200019, - 12415333505074758067, 16988669193263876033, 10482573641416551070, 368049292090348794, 16109255925523895167, 4949934055388640387, 12038479532506656790, 10829864449693781036, - 8355401100656399994, 16963696462538033761, 10131652431024537917, 4166156454906166144, 12888240412190236596, 8396312458335953166, 445297814986468978, 10512295830234020744, - 14405236772348157690, 6950094157338825845, 13379457125020057613, 11396720859761560260, 14063367153572826959, 4476298515903789197, 12708437873915498860, 8163633089770520638, - 6432708226771955694, 7524978005081948959, 6442046223716866789, 4082077252385606982, 13626979819841658005, 4264573835620574342, 14788317690584235128, 4710414518172449402, - 9592766374657389840, 3206081438027351157, 16013702689312533501, 15788528722601567812, 18314198451066123850, 13236688692074994659, 3229858297074852748, 2968037605940641303, - 148470760067500612, 10319937899190593880, 7185467485673911733, 13041030391924988650, 17119842693824847662, 10989053172849710331, 16048294708726813099, 6612710923681979611, - 17408606709137505005, 4263600430695220256, 8941719936291239640, 6115030817534063286, 838024703679813150, 9772071103323550178, 14394690179107421621, 8621372196164819917, - 18138724984190926809, 4154767406604950048, 5209478936276366634, 15469512148904762872, 3613429290324777670, 12631812917445459751, 10280179062385049041, 19656860716268566, - }, - { - 12030193727051241373, 13981191132445467472, 18205169646206905593, 12162181194046583886, 10929925499200074058, 15291772758590352491, 8452344520852919320, 8199821440451878776, - 9876482463501409337, 17331045017548147052, 17542726936580732548, 8299195336372136083, 12891767721269002608, 14062358772374813347, 4165127680073507756, 16350672737379495431, - 7595271959296927018, 15286771623821390629, 980612661413312852, 5738158184597378995, 6972117550390447038, 6246497134979772260, 2935831443692029059, 12837371529160496660, - 10228366644420455452, 12084265406352277347, 10265869676493821892, 3560143954870272139, 14368775225608592689, 13173522067191372913, 3592475039513249949, 11243554718624931135, - 15959892157814064696, 1882528744932347842, 3354709518288681174, 14147909176429982637, 12969888425264095514, 12509610747258602648, 10437226619684632037, 7605683691113295811, - 5697384515599291245, 14896081221061315030, 4329502046122948975, 16301954510440819492, 5191621061031169335, 12944691824816066027, 8080452646904372453, 793075614214301908, - 2662373477940179766, 8950125653339535995, 15717799081080898304, 7088593450282143511, 11723351531494404904, 38673945663198753, 5289769381065195334, 1742280067441486108, - 6543255501112359319, 6063422531520498671, 17228726254778244409, 7570754775709645369, 18222396492501523182, 14903937974816691813, 1216646642383641441, 7602781158453005929, - 3007861146695764376, 8267227185027440857, 3177625538211272080, 3144345182124760000, 9215753228267875296, 1342253891473772992, 8185239004636232247, 14951188427081280984, - 10569785547248986188, 3109435167722572449, 13661123218513357442, 4646373703143839998, 9712828426076586682, 11389514152975496268, 9796826623781200498, 234067627740956181, - 2188380882990542468, 9914251329861595119, 13616219875099353594, 16135919125023820218, 10732193797566088293, 7172996278550642736, 8531638916719074975, 14749121691457005349, - 14568782576170814716, 17582848432122737506, 1079387064102681806, 17278567874821675408, 3094302191119669899, 3730448048895347901, 3508894590334961422, 14091660942919228106, - 8414395549498864629, 370884714015114625, 9859130251236103342, 17120282094084970181, 15213286581037020029, 2737545283554254673, 12422648607044275574, 10601123825482591606, - 7332173975514924017, 6689389428877729175, 15162654177270425320, 17333672210015736765, 10717615330136876266, 15245080807947386155, 9830331968044142933, 16156512094344185621, - 9151817936103586393, 3495709317444898385, 10881665308947458223, 7087755261386867019, 18372828768905212167, 12873774245490293443, 12750361906770763255, 17688389897350887716, - 13329033749048978810, 4765695903433858377, 4452680451529163940, 5638854187414651620, 7897503022043776206, 17187635538005569019, 17766753195497526986, 13201529234556380285, - 3638940913491383692, 16533217388164981609, 4668956005988168087, 14053696531704823982, 12029006663244142834, 12043309283447175601, 7840964186868745782, 5691369519440953069, - 8500871974974230561, 6371833132372813539, 4002756625312698938, 7281624589760047276, 8813214993155334737, 7738842112797657395, 12616064385239668311, 11875709199633531753, - 13080663957403320059, 7305658810888170771, 12002632153917673214, 14713338572031413494, 11629178662016777533, 11669230410217642326, 6563025945717173284, 15889630204666511658, - 8934119620399766972, 4226481091885914732, 16000709195004445297, 14687868180928846933, 16269913392757896907, 18294005838441325342, 17625669613551023126, 10864307042201644469, - 1539179629859629979, 3357767843775461146, 2101360073251832751, 17234081431682678130, 10847284171622250162, 2314478515498414576, 17530153382031867644, 16210890762511619844, - 16932765725476234252, 17974885539458965712, 40892050255466590, 13934027942808790590, 6621543269907021363, 11796852321134174354, 16673775773384613137, 3370296079966463186, - 16962514259432373133, 4639769064050336100, 16965148588326727680, 2922022742538957808, 16752379982369550296, 12896050752492664079, 2708685629936199207, 17894058559833424187, - 14722530431277419104, 12333728409662476827, 4162946257347548625, 7052045338975163666, 16435875989376103923, 527141841571514699, 8480360258792897962, 4322786951393806781, - 17366230017999184054, 3121469063237497918, 16903979375392804254, 8204447732627807538, 10469007462907301028, 1938243801077680483, 10156223751968769092, 14290141776757271674, - 2576841693080637380, 17952976066680364360, 4927209893946473523, 12406446420948698970, 18104668447274679200, 11321546081935789882, 11763004760954725540, 7488613143173641394, - 7566233859107262691, 14065899052643539237, 17156645465457086529, 11936850757897686493, 17529993825395532749, 17145245039398670236, 17597009579379584432, 3472628483897995694, - 14380803034817149259, 11042134597430846555, 9992762805140200547, 9895143575678511242, 3228768306004664915, 16153114680219541243, 12036181641761325912, 491369524302296324, - 6378343037075212083, 4634622317247307316, 3415247351446435530, 5939760313513758783, 9540802244218497398, 2134082884335789009, 15623633842188443713, 6824600547587227473, - 2021901489047050575, 4365578779519871721, 8603845379677060773, 8929020214929242215, 13010370953605249273, 8071113541575997356, 10681914788594101574, 13369522272664029829, - 4241327321249984516, 12810477007632864750, 16880581634097860698, 3630333431846970294, 3439918565119627078, 6613942714960548236, 8647431674406387604, 13352599355545805355, - 12320933424684960076, 8906954611339502145, 16931708732547376267, 6446897311644431583, 13749563256713530203, 11522599770043814384, 14455556215959342791, 9022955938835504923, - }, - { - 14734199666349771791, 4159865781008764547, 4413963548436270853, 4489431649937855880, 2824856157476907519, 5111945927271461159, 9825486821405155220, 7657332565522279292, - 8798422177670065832, 1250388939918922012, 5145324733132743026, 3716299737175574168, 14387202892738514375, 10255681359895407489, 8563822744122397080, 18430417713920116013, - 7857399215288147901, 2593284350589299949, 10086687882410147351, 14407837835956327624, 4469878646287387405, 6845712208092605310, 3019047164798827279, 2760591274816994522, - 10930605176025081830, 5850835312463207607, 9603163404664606781, 15623771803942139684, 4096748595672894276, 13060617166821837740, 11222939712741281346, 18445178894593253710, - 7976335583419810431, 16568954524837045521, 5581116346602990350, 18369129318179031997, 1930478946186473631, 14255806344323769850, 5302512325798050097, 10008570767203424472, - 929118050943456183, 445163760697913504, 7208246135487165437, 13565354217377841149, 3835063466770003968, 8214155842021576753, 2078717035803259674, 12502657820500987763, - 17741004372977419914, 16320851348541958575, 11853008901690968430, 9954777341381304447, 14274892887030297417, 10721339848307167540, 8731332510371325649, 13676383433520290197, - 6251805914672095769, 1063060143452094078, 16647397170554915088, 15454955736319919321, 11509235104607349098, 8441647766544589978, 956121464218389431, 10752793912033728149, - 14879603883666664508, 11158422912437249402, 8667988090392051507, 12702057193823135575, 13234479167199208223, 13752955092077643608, 1117550756888145931, 1184967682872965330, - 7004802666964716824, 395433501626287206, 16674151908279399004, 2279551165611331131, 18032555740803644790, 3573953642384243989, 9892480504006025100, 2397759375236735831, - 15032723931727013905, 4176673226777913017, 7270920367565154969, 8867675920919464620, 8174119413251699506, 15030539680120439131, 12325981936900309518, 2932283844656871802, - 3227890727136855788, 10772277744280338071, 10065219931092397730, 17233706446636791341, 1372997838851103811, 14430098741859995846, 3290287064497023581, 13054133915521430696, - 3404625123065318735, 11884832674715736469, 16513753127836546671, 2355202492840722899, 2182039060332057784, 17942518439766613327, 16731345075928062112, 5501869092504492134, - 15704211025163561149, 14596679078416770266, 10262177146233936833, 12443005669252298316, 1541294166390346144, 2952804996209068760, 15358481016273272880, 1321729586231860999, - 6862865331233391228, 15106279167311639122, 3283008666555627541, 13405610967904725343, 9845239597399801983, 10764942720093673542, 6506992344666983370, 2483131164245259278, - 9508384588323002196, 4786531415304518048, 2690306308552249535, 12208815515689370850, 5145548243685871201, 1536915039528215765, 709289946127949333, 7152734178531880864, - 1555309551759198315, 13156609441579560529, 3264147002083956017, 13629162110016732793, 10295903344220946201, 13835148808782379287, 15646840234722388037, 5850505683234532491, - 13348528763144385986, 8174978337870000956, 261860806345683810, 4561309263594732686, 973813267913726588, 5812176512716041479, 14361848397565071235, 9009461390894364897, - 4179825720483458009, 3146850391122074949, 16612045757277946305, 5253713786583408340, 5426943015912173764, 17275032103121420023, 8467860410750483621, 18150546576917688519, - 12762630566060098764, 9762645120146998728, 3635705124656800121, 3295681695622364165, 1764654124266477879, 16610065552429288987, 12182970194869512424, 1144643512390613083, - 10286763540130161498, 3400614528650953395, 16801086752981339314, 5746334081386875705, 4489937467701177898, 9249554406360134002, 8258038249111147700, 1922443676251769427, - 5981893063992017591, 11780456280008557800, 6865399120670384939, 6192294124015342683, 12388377965276278882, 754882660516751393, 13476094069874573591, 1000347292494612314, - 12753947115797128456, 1864834899756446490, 12873792436322150068, 15420857687427067065, 6214698061215951246, 11174167031334850459, 16378107708672199269, 13073812080094584194, - 3531275996684891316, 11764951512033875164, 12239314899306115751, 12701224435273087197, 152051042384837402, 47099568832954431, 766394328496626388, 666084094458729910, - 145223485883456390, 2445564470200462527, 6482144922631612251, 2316071592874761856, 16548688346252111305, 342430477320199814, 17819268336019413198, 9112976726726029531, - 8272548370610798443, 13910434751574602849, 4252192981011400377, 9590519351704710983, 4172183866405471444, 5567646223402949380, 6059725713353637560, 7169982539312028092, - 8422701298619809502, 5749403137850675219, 16696307763582818287, 7683947097864552851, 8685161999810728314, 15931494353777534155, 21629333141204286, 14374464903502564030, - 2354260355218724624, 2822702976206523812, 15817484232297668127, 8389777239766813455, 7962301702220496539, 8489354871723216960, 6637394823950686331, 5853452396705295777, - 5949957329602421631, 18059540496274524007, 301304345046470155, 15775279105880040289, 15979581939040500554, 7142046514802237176, 9965619645220287167, 14369754349691428035, - 8777708254369249245, 17882304730732025188, 3127583543205765491, 17274466425160820249, 12870181470212293464, 5881181695848312122, 15338161852429951632, 7245877162563127935, - 2634466441339054819, 13057158409330115380, 7410310056430957860, 16362149248469660371, 1435827663585128427, 8005375008235415486, 10865470829924734253, 3177600727860863968, - 9627905753364576437, 12776456422166281355, 2851899644189834214, 16998174196920379994, 9001602524188761177, 8960294999163663712, 6580949973363012183, 7568306074815116797, - }, - { - 13345381996769253014, 6278048669175242345, 15990349685835870151, 16358261962292186792, 8505261070637963021, 9396725065098564446, 15331953351049782155, 16194796339208321205, - 7076257175157660597, 13221730879315432464, 4499548735964119085, 7559253754663705944, 10196808438730350168, 2391718471837563931, 914409564589897387, 6649744842278078706, - 5502356275170104522, 12750322860129485966, 9581277511584938955, 3872282844937972630, 13668854758739140874, 15020438121087800965, 4581631138384430657, 13296613956093963588, - 14380343880230315251, 6834909096379668102, 15975839936772635678, 7738230945027714388, 7971648870467745046, 8320128435052726628, 10820026056424631461, 7058118462476293754, - 7264036154081699231, 1304060579978677195, 18166928140052040308, 12593450560996175288, 16027666629366472835, 3677101504316839585, 1477956412235870359, 11566116495906585190, - 5990066097615398579, 2092999434824845091, 774626818169813708, 12815491981614523669, 6993666706115136402, 17707947501239782961, 4907798919001453899, 8644498548438963907, - 10893744790193607860, 5425031394266373727, 7829758685118664025, 11448863214220512751, 12538690882574195219, 5021176303769859871, 5820297470465439264, 5119144562842414323, - 11165438517321289842, 8661037418831619311, 4401480924846865713, 9355650368902126256, 14352422544185763829, 12268031594529744663, 17607497268577344783, 12698954426769962214, - 5383780168621648368, 3613813760948797485, 5757643543708300439, 11434310585555684688, 2345981080034027974, 17817292757133028083, 18327982597027759229, 3812144950722314021, - 8792386854586041066, 18039588893139878329, 5501406599000558473, 17117814302557684702, 7341401626090786647, 13233670006052290433, 2192568639640447778, 8946253989965365943, - 16557600339807647183, 3024845786116641335, 415867109882960964, 5024769423994345740, 6707880221250244075, 1889203596997453159, 2063004021323938442, 15149146696320496954, - 5091534986326281709, 8005812102849517353, 17366496686564185717, 3658878980438307796, 8455810244524637026, 7649393961871195909, 8629386422022530934, 507133797409068858, - 8757568869745664865, 18237318628906764926, 3340648953867756474, 561136277959994100, 7271097445297070958, 2011054670254573698, 5452809131990689118, 13469888024447314143, - 609640447772904263, 18299734743899574512, 9082773418653747144, 17312950936823165983, 8565594704932296493, 366163155689429929, 12596423288683198842, 6787120926470876217, - 18404298100226778075, 8425329164435445437, 7431919288426595458, 10680902470574406179, 7944931189168061880, 9822761000408762356, 794258562727155839, 14627123549563592012, - 10098955144981013765, 4095621933458866623, 313357785962326778, 14880249056209398407, 10605627454111004262, 7841561005378789988, 5015399193497762029, 5818383539901203899, - 486788682374900660, 17535646661984222270, 10786441143551223569, 9744277172896797168, 3600223448942144865, 8847805713765285452, 15255336563751266306, 14792236445425212896, - 1569380763811592357, 16850350231819425451, 14974316825768144065, 2974893813338477794, 16726324408135381195, 15000665607479486464, 886632233152598796, 3783793991897659851, - 17267037371866619240, 16498595171305365582, 6453906744948258368, 17267405673163971478, 1676214913570622682, 5051819157163581842, 4315279707026326708, 15525840981760267164, - 829322392873083372, 3459913121476606612, 4547714508342797986, 5801286056105229312, 11591136160675314269, 17965845487226778560, 7022309609363885527, 5990586084398664157, - 17415594387520595717, 1453256163777911406, 8242859112004661961, 17561205531134219898, 4881570838375824387, 8392772608437744175, 8797957464506597080, 3142154188155936579, - 6248409301753564092, 912147011448492506, 10413108318416902948, 3349445377400918439, 15887909530347096066, 5138859116738406557, 10990929831134698266, 5911273060564729281, - 5197581879950405305, 3001975514736631403, 1919678782193534342, 16811100109848336275, 13086769249238533805, 4351245282425706500, 18281601243717625371, 16799537683941038764, - 6288277991521986035, 12231480617236286340, 8633990423689180869, 13535190275290488690, 13419223868164389899, 17622732596713666209, 10071779220640400024, 9451660464882303005, - 14029940454474238624, 4957972603307996503, 6311878080193524221, 7485203809274562760, 14450074580092843779, 16845073066403496624, 15870387052570816676, 15700883809468229388, - 6623653867803819118, 1037643671564549885, 1236506073247459642, 2997396263933967582, 6182371056378366305, 9773995232878719062, 3356495419149379609, 10710833980055523526, - 9965766500412107699, 16895652751136174589, 7310937934566947318, 17649841370865305295, 5052693369483848536, 8093060855248113928, 15777336335257114359, 4642979535698186085, - 11761084765182152401, 9226969173242076459, 5445719591917489914, 9371133174853825566, 18381867235964583187, 17262888224001222346, 1934253649802391267, 3574888052111089863, - 7862401495691359736, 674970329153306547, 14447324101549742216, 15408908436196428001, 5339840774639473099, 15542473999923245378, 17353380999887736706, 17787369898686553525, - 2301964326759931592, 17775852221342579469, 345763078096690431, 5079606662887837532, 14863722102334084051, 8905941255852264870, 3806200576416892831, 6668327519801544161, - 3672519063263749482, 11898207454593385701, 2364050348970898536, 3761861796987022528, 8159458273489411574, 3231262679605967088, 17179214124164291006, 8770284079122589350, - 15270079546607712667, 8471883658965202468, 10333206241569264742, 7414741159725097798, 7709713706668701850, 4461310100162632915, 10099194304024685274, 4760203118683828795, - }, - { - 7237168574323016859, 17908810107504968137, 16225708127838178121, 11127095986977103648, 9346291308317410251, 7381283458277047010, 15168602815371846943, 9193719743691734294, - 9607254959726458411, 16837156817186931862, 16178143308706847393, 10970721795101931539, 10840376278605273092, 8298765077094727469, 15520543037910966843, 11484620381947762562, - 17395070963094117711, 7608132718922490881, 6531178971071758016, 1302814667007331361, 4002629363862769670, 14649492495298089937, 6868174210142585697, 15456170652716048683, - 3688308493559609536, 5123828159813683938, 6245436817220183971, 13062234263274605325, 1313395302496832996, 4961840797708687855, 4990192311341859196, 5283131006216350959, - 16952735659396950704, 1249482796824289329, 17859504101404809981, 13260403650830168625, 1583343855370236084, 11389120333403185826, 13676599385745755008, 5066667130137739346, - 4799264864906918301, 18347145714884655971, 17034125441088681346, 11828378178487279470, 1759038296522081901, 9582407833575609381, 4195817009050503354, 12618256395967210055, - 6486755100213398364, 5270923715575268322, 9268255346880651103, 3147724493117082267, 16710318779269985633, 1240462642985509644, 2400811796254219369, 13670743068809614358, - 11437779990773246594, 13609113239383378152, 31268927496646090, 11618772705165035208, 3078024460365036167, 12138983306908962712, 4779157919015181380, 11901698850260672002, - 14642787507945832432, 16258081639927585935, 2560321462542164242, 16286882196975458174, 4328159372518768969, 14313553865397841147, 13769372656320240568, 8950675126435331579, - 1309709344837422378, 18403288028608342631, 17102350491414677993, 1133523394849437315, 12526496222782003755, 5447309058259018864, 17311120581405946631, 3760058661125144368, - 17891474172606596407, 320094264574086461, 93927075222964142, 14355817838636249140, 1777882427773785068, 8237021421587560510, 11520559469641852991, 10567910693910023157, - 9164300764173563614, 12322279811717869943, 2768902015676238485, 7761799112151133995, 5740162933856370894, 8043946608495226840, 8923704438836381869, 15189322655373943849, - 12046275966378825708, 5909386969214935556, 1201990704907881028, 12128549009950617306, 10773478878317625320, 4554854625564648958, 14029736945871573056, 1353247251064221090, - 11909123603272307101, 5517949035179831783, 3295386484950432959, 5605137795524476293, 10718654547602473221, 4984952409581272095, 883267724006996723, 17328431094026829348, - 13671210467347025770, 9980617617519781731, 8339868735163579231, 2150724314757661915, 8571153021065445899, 9146903697769397191, 9122246102814640373, 7744779513085605450, - 5733697799130763963, 962857090393715865, 10538932452511329419, 3413281437172590207, 6635428480179771287, 4404718679994229138, 329074170931436370, 17746708206910902139, - 465623292609655544, 12740391094094156750, 15600221933467635716, 10712500242632508096, 4760789577759901270, 408323003115848014, 464706673403009712, 11801112998381624421, - 5545681129476190458, 8725689673989867696, 2143812364199804063, 12133065347666807143, 14072918710585286097, 9027361966934517640, 12608281386782336413, 2053972384317260152, - 11862793362110657447, 2615766363986534825, 5065170482898519596, 2878903691735623036, 5204682974850023849, 3382494556217615091, 15421437169807703253, 14936317525837021790, - 12363228588136583724, 15035239525394825264, 16312817933687103988, 5294641777817034798, 1197907056067071148, 13084871057903003628, 5240492218216802394, 13798739245031559476, - 16167519903361647970, 13106036157861122437, 2112866661358918425, 941609107359251234, 7240286582201258992, 17783018133711208779, 10433192833270769862, 4303514224506582113, - 1549168540255262874, 7958641388293572779, 17867057222043259063, 1752211085999288773, 11828273580240483781, 11712913016012991853, 2373360154803731890, 6779610934665321824, - 6633997178003959408, 145323909693817907, 2198452664824754574, 2920221908918689777, 11047294234593305837, 16840329825128198329, 5479733463453508239, 14054694221361300990, - 7908792292118068471, 2703859967221946473, 6268006869726038724, 9406994672213611166, 12424098071734234719, 11900750387777467409, 10724482893673149484, 3191937460539390989, - 7635348735946750413, 15019610708452651937, 107671898858364780, 16808612119435524257, 6120109999123152232, 2251481693156523545, 10792076820325151003, 12924551065805570215, - 11225852067204798645, 7665324911993544151, 10402215331683389905, 2856131542917118235, 14152013119539822346, 12731746180172488022, 16402457225039188820, 11129045951416314666, - 13009066459618795885, 9636541685854928780, 4783713672495759319, 13224924194053497016, 8044695420996588716, 4054951559323242873, 8718047667110955699, 13479622910466265834, - 4333570709684826136, 3188483692974505359, 17976757824852085147, 12585927226835238762, 16665346689006249776, 14033419552450595393, 12216049696243171604, 447536030797427204, - 14100792221456700414, 11757964686555543320, 3971513799111193530, 224065891283865758, 1282520657830780512, 9120233956471705454, 13711191981326748211, 3725543277190035504, - 12094220323799678341, 16876894723130932646, 14806566188177921577, 2283878370700345373, 12254260799985999571, 12764268124075139223, 2425316412794046071, 2088679341162220742, - 172600248248909168, 4338060849169481673, 12046085844143054569, 16220699277291497444, 10358794035289405365, 6739081270984238196, 16079387007561085178, 13471688054064884318, - 179238781994802586, 9017860544212172426, 16179187983079961859, 1380105261896053495, 6187003332254463653, 9896593306091975718, 17181949235068293496, 6820143159816507763, - }, - { - 11156900805411912784, 1737275748212365168, 16993486692205800040, 12538938066475152524, 13167476167764338790, 17373319366642541595, 6054831428930905282, 7118452124011953000, - 743288751022377974, 9226164090128370715, 17669221687181604232, 1117842260351396541, 17697784451833850722, 14382209306891991103, 16951372733687268016, 188390802712613066, - 13268209255833199938, 16633146482265079265, 6044233937395578074, 1733872861371247406, 14239198956565602758, 4036306057099495106, 1778912298053970082, 6174082695927204648, - 6390361653475754940, 1093882175267357438, 3784079074949811167, 17343872969822169769, 3359715652121662979, 16808529787251986583, 5169730697018536870, 52766949850965558, - 1403521870654810721, 11668153767441183906, 12890534559297323775, 13255750643204945388, 8838011266491753399, 8488733891344199335, 7468199299966346977, 10645543722243906719, - 17019046551094178629, 3055711824867115856, 10841870683594132444, 382072777978364200, 725450988418371589, 12501774248954630111, 10130164067258601487, 7823254091037946722, - 1866199290196467180, 554488389245696218, 15654194385091454776, 6131785419830586829, 17856850737824439617, 17602611196814472081, 18244498160243832872, 5819736122106091373, - 13147212495082910072, 5628914243538540648, 439989514095330941, 7620472329041817834, 4272251824771633288, 16564977601507013119, 5441117136715882317, 5622571730905974389, - 8706277077547369587, 4848592786700984858, 11350018329458740004, 143688324288835298, 16536982722430328270, 6522962371020150117, 9511378862712142567, 18221873727623821967, - 3985496688414455558, 11118602672015528143, 5383196298446424580, 6116994806363767576, 4051800833472889243, 12236802048340231756, 2619572929682123355, 6008593592518397571, - 18159379849046931840, 11283007389905902377, 7465803490016928282, 7730454089227756796, 3569936088077890000, 2804205711716327520, 14107136042131448408, 12050401455009236937, - 4207421531032215145, 7924589143024019458, 5496622772676523695, 7061817399179278712, 7371689806847905735, 8282663810521090335, 11422487361383982601, 6397294642072086677, - 15924576759579234055, 9923512276109397968, 6142441356128988365, 11189756906743802872, 17790684027455851021, 14143953977451478354, 4002828116425422775, 7521923183240026608, - 8349314793194266723, 8850246337652136896, 16635419760398709839, 12466509089914036008, 2686508850003621675, 15822032015692543407, 2211302095278204426, 12550915236378020964, - 3844358527917324404, 15045102416646491178, 558560187822263769, 119801275176287297, 15593003307431898979, 12817356186703401527, 531419248069516921, 7957931139148417935, - 960381383357168877, 16774709963697143275, 17896181076874992240, 1150415168189819777, 5498481130530161530, 6895900060791069290, 2079514944189747822, 3428689507902936354, - 8525743843643076774, 6014251588524085384, 16423924202355808346, 2605496565158241796, 16676209604549923678, 4870342652354143869, 8337072895802905281, 2478197702680510974, - 17076629945963768258, 7647523525256473652, 3999707005939039144, 9578933944626939348, 10469359763046002307, 17515033080264359276, 14272203721184987484, 9979666177276073145, - 3896303254672567310, 17167309259158926479, 13231865857998180315, 2260217573257466310, 15465674863730076330, 4460025914284098438, 718707264700157542, 7215235109325196153, - 12056920178557394302, 5131253251712581899, 16251877995882633963, 10883064494054484051, 9473274815269607947, 8874308005470196739, 4412709653190846630, 16469366225886156991, - 13309932065155297376, 11504232979548718747, 14366229841750030472, 12797870458094162590, 12894694064456675527, 16977997035748966590, 15080606548583635864, 9292471759789693596, - 1226107676031264801, 2683510924831720521, 4344623677417870872, 6581244316153602113, 12516966236091151915, 6758725397469564403, 3190083750600883646, 13018714111448482165, - 877612159223846777, 1550479938877814973, 11850498481046386377, 18144061425551419288, 6811504328538189985, 16351446194603329949, 14495016749549056145, 15394017693349630053, - 3547198835521135552, 9940690805769919242, 15170549880149605690, 10701681269101530298, 5914809102954412895, 15790219349994701461, 13664049285300230863, 5735249081148743651, - 12395092509541605535, 2320592554345067500, 14213227630916688382, 12847883717490005600, 10192971941898238362, 18392117086623245662, 14369915478097042954, 9636190568462370402, - 13308009076055104849, 9679299541833059768, 1512845037409468381, 18211703514703978816, 8337549295001075127, 15882458005321062689, 1212364284844818969, 13856780176955551126, - 7602636613718406141, 2678224565451628558, 6976331354727208830, 7414684104929828967, 13536889690553324858, 13086024708711030952, 3748455179863046304, 1853373561223967487, - 14753645881295168970, 9410794713982813264, 13485977523338061503, 14267793994973767571, 15813187206361118954, 16449603969001878152, 17705410933007144731, 10960511750491378082, - 42380674434071200, 10068881872338405083, 14327149378182272744, 18264050153181932597, 8600790433943161385, 2952021171158508784, 13461070885471956301, 9633226987835715039, - 10360728550079953555, 8471248683929284652, 6673003382103023756, 8972723925695500528, 5941683993959582947, 13500073059240140624, 17856131583218769324, 16799784995825923732, - 7292102941225494742, 4807816512907139693, 11271815982004383122, 1065441269547643077, 5279915279332961503, 12100441009657772185, 10448964764090871372, 2944169874578456259, - 4669722990542640772, 10017368027073540045, 13392819319228640800, 1070815632453829996, 7274130058405640448, 4460835865761538026, 15283885107956150892, 5815884817303156137, - }, - { - 987127652983079722, 6872208513691823695, 10110578719299008714, 16457381243184327116, 10779072738879347999, 5965282398006505989, 18251577267494363268, 9321323379108563422, - 6119049170407437179, 12938407708038792521, 10105420405825346383, 3416306788177016826, 330648587825212481, 125568991290568141, 13857127346570918649, 4376080986981308805, - 5930434126597036589, 11240994623469578584, 839346533006694594, 10015087329724081709, 6285097815938761787, 17244606485954860090, 11523249727882012981, 7178451948850151803, - 16733615335426327004, 14833564736134873977, 15736159435317472941, 17560193966711884894, 4670172300306758374, 9477713670983496835, 14243955354032737980, 6459864769649694970, - 16053517698989562256, 2069464650596796670, 18305730134729303993, 1090863611964008044, 10595928817546105363, 11743183506441120484, 8584767248013363683, 9187452830514379903, - 6938579711827578880, 16268282168771714072, 4567473305742437221, 754548046014059669, 7773636946295303572, 8132380485366854656, 5054542590195827722, 6074347500754248128, - 3955857908381474930, 11852678900999621852, 13783017203403417097, 13616745777931267488, 13189924588414196918, 14519927295809952876, 9334100965942760501, 15172548734242885286, - 4869852132020793901, 14921212823114724347, 14342559113353033349, 13336827701782657309, 11168346789878684452, 9790480725902426052, 9171116079841529936, 9268902731763220711, - 4417372365016540659, 17280138652899703220, 6650972319709075180, 11252221422799491438, 6825784270383052414, 18308562203755695191, 4237445205082731447, 8485872406483449772, - 11718726714045105993, 2624508790343569765, 5794111482300008213, 12819216567095091385, 285329842793152354, 17257707863943097374, 16912487373614458842, 9501952033607497057, - 13074643344738491288, 8505193022029238118, 9932652098552590323, 267408114280737600, 14802861246220332716, 17506028737327736269, 15929083591675282371, 10937680132245212187, - 16688733766460131050, 12777635326299184071, 7769405825716531061, 12435979606514844725, 2767987141420672349, 6723940414217341603, 16114182069580717377, 4541113259200434040, - 8506371389960537559, 18031198550689409305, 11510251852995503442, 1923472385053944821, 6189904387119195613, 345664413118550356, 6439003191582953600, 18344385760549575361, - 5320548958745018096, 8341561189829530680, 3327828110998403156, 17981346269177513223, 14254804273025688074, 11111147827704077234, 9093333670517437191, 7272552282364063165, - 7587268797387514088, 4402481408866840263, 11260815389095334885, 14391444701764948710, 4224880318604689771, 2472148458660279030, 961218007313548745, 13826356220879831691, - 4477325369345373420, 299141931133875776, 6787652129916359301, 2498016036564260464, 13342319943892943548, 11124287719737492205, 2456333599771808442, 5084719026388755304, - 11208298545009109072, 9361672558653085726, 11597473974277116433, 9123409098329262113, 2315750487079392743, 14788891796020803799, 16477373474431052867, 6394267218565388055, - 15099803091969065643, 7815556206466442264, 10304177785190927723, 6493522556494567776, 14386173575053274652, 4399768637448990408, 2996083572119906777, 9762267038999270167, - 204205141115459509, 15145142808374731170, 1678672167166598389, 12032976094920574395, 7472791648310888425, 3687068899306742850, 2661021646792225638, 13705804163602287184, - 9320611303424530507, 7295004960403065170, 15749376924513664173, 11543669941217924178, 3710258597217352196, 11371260298937340150, 3902566672028686120, 17983841473999282668, - 11814188798674654097, 13017429106091059634, 11079902218909650978, 9064898043690914606, 12023954026861289442, 3592879256613061321, 9997625973577562433, 16073808232708438680, - 15365030910001289574, 8789654976305207659, 3460532362538090307, 12992239135084766157, 11449242863169591803, 5418502644558230048, 7981056000757137731, 13021725301900406539, - 7782773734814780443, 9390379677704432300, 7130223982341575476, 6496906770393189740, 5095392170846288421, 11058865093605824851, 11021902438459302094, 6088242418938968652, - 5966014717657529537, 5136588784988696205, 6360472729290909457, 4447169061266082500, 12506934948427595318, 16433395045878253504, 5116318868244944213, 6640832565780621049, - 4132920736998081103, 11827975663170283136, 379030309731223785, 3149051804072184938, 12035317616979166548, 9642536337674500310, 15531497803043399747, 14399049832547796531, - 5493097462539196248, 1629980144571354138, 13641173578972112594, 11096917099468924214, 10934169048860132281, 11269991112518485434, 11206050457519414207, 7939067479736521906, - 3806755078949823895, 15988975666336042818, 8246267395645554105, 9703363749164024623, 7795606269507901456, 451102251659512683, 5865831186929065346, 81064915983990550, - 5810137226573964106, 8424253088401255706, 4543883508937971494, 7386148745257823512, 1348150366217548727, 2103092839740150931, 8353010273955146981, 16831854467863536537, - 5095778754322493440, 16577416628492146129, 12288076721910512064, 10563487622054214075, 14620553808255752273, 8159958565993701874, 6712100880095874267, 13203797993773281759, - 9640010815039549413, 17460773950401928956, 18229977265837445092, 9252634318278265623, 16798979334068219458, 11731856767337519419, 1551975378671663669, 14320102155496153821, - 10528988339881191052, 3808685834232068820, 1064376960475785008, 6466670187430364599, 16860839938395945578, 8876458447995837267, 7897541112736965607, 10283235741250763328, - 12246932755942887931, 10842213418139067847, 1827392608284960926, 6961756951208563550, 14626966634382828071, 12653808277900379805, 3359368990539585596, 1190255644328095727, - }, - { - 10836955050615624183, 6228108794259714192, 3769609579318360527, 1481673673659326756, 301329772189110029, 3574710782304999603, 3037244905687722509, 14442941761397229485, - 7739110373965523311, 11019153332996240080, 7346010155518751797, 14853737521111213548, 2542883237207113209, 11015136828834421504, 1998601666328316353, 1540417751495800469, - 599034134015360884, 11263317530774995092, 6667501365379084069, 9844276013103312691, 7566306886180438990, 13702768345615509363, 12525031963170717968, 8463786212988210464, - 16430555432520738762, 11225321696360643709, 11777973654353154098, 13133115227828884393, 17678738157022850345, 1586660156856830642, 840647763693221003, 8645742354464326466, - 8067725618510810414, 6229041032854057836, 8025364837156161898, 1290443646630661359, 10991323655842003728, 9346782840170054789, 8939059450584871902, 4772347025802041241, - 8187379062828795656, 14744366698824202673, 17014663804743197103, 7704635785366672415, 17162645929628468457, 12942442527592695216, 13291710923558633295, 5800071247768119960, - 3552067877931717181, 590108493628737243, 497390871097272557, 12785795808441396281, 5561451613221796230, 14263823913216836845, 10481729699001112354, 7818094022046194698, - 3598736754916501501, 4827022662021197854, 8203180748141933720, 10283251600632599041, 16186680658340956808, 15183393398087319142, 8714402370450665212, 13217902016653171217, - 13766344083396522552, 3843491774288631026, 1174164282483810421, 6398024882371290634, 5459580537585379131, 5871096222069618377, 9611875286525007701, 1940221124144536452, - 11598781954647517543, 15695098933552070478, 14976427118847622464, 7147358677856872160, 17135524627354123951, 8338407198954935663, 18099467407613897492, 9025371359994313919, - 11451018285787631498, 11710749546511767589, 12969419493657624536, 2338911230088800542, 17492614411321910750, 15274296072504110502, 1258801445108685875, 15178229640559232741, - 11743016372336018414, 6125536020759642301, 16563280170798047733, 14529052521060111789, 15253502329174644388, 1556763737841306861, 3041940064290508531, 18020881359462953336, - 3035547704692483898, 462291414338050452, 4209186193642705826, 929930084709639338, 5246348806539841852, 16407585218848843770, 6076996892610687611, 16547395936238439809, - 7781914900266335582, 17967080065814694611, 14677062197599091614, 6667353926398988267, 5658765839564756939, 15807817354312473921, 7476371642206655552, 1194561222317134506, - 10645607622061780068, 11583886495890779582, 6879987349345299140, 5119348262235800038, 6546217876212430196, 5534845503308945424, 2003680599532879233, 2824480091030475274, - 2297585344913389180, 13965959247788377604, 11341378863608387800, 9890953382689640379, 10443523266835246852, 9631856696811288063, 6944503116553031744, 10030824122780966395, - 2699238910420203023, 13176131497943324759, 2961070701879546988, 1511208990650977146, 13153451530298458944, 254163587562261430, 6668642257003911712, 9040693998431169077, - 5596789796292416136, 10505785820531892681, 3803057245175025164, 13601446877323203658, 7939638174866660891, 14141848241206986005, 13782885912650943563, 6287188921995938212, - 12999700407775352603, 2664314004284450753, 7085329252118415126, 17472483363754271126, 15550759073378819069, 7572177503239633527, 15705617684783232308, 8586972133880335199, - 6636244234467769744, 18284390012667441869, 722929822219329257, 3274166388651987221, 13177791837760949480, 2568122970128111127, 3477167651270374316, 11371867850093288299, - 4065583279544717744, 15575999213135020408, 1319417044854511604, 14713082471342741360, 9399053450949627084, 8900637792268080986, 13511414538589410393, 601556817111475086, - 9243142430859561073, 14638657859832212223, 15324499241122936340, 14477761753578941934, 14699832840191454785, 5114873517253108658, 7427057898915535537, 12536800031182849473, - 11775949216482616439, 9736654184925478086, 2941126957776086651, 11331303510371804917, 3535865528819665754, 2488682969529955908, 922100556888217739, 17904958255578472855, - 12876460969864886954, 4692925517843901006, 17390372170975588763, 14692578774429957295, 1759864963511373267, 12016553435172103063, 13015881292003590351, 16187569590073958370, - 15154092100094191059, 8103665941237580228, 3265383210728928809, 8341136973870067643, 17281635732314163959, 16433737305161442677, 9130496888060417111, 7070932927684908859, - 2129695226164849659, 15163429615374108928, 2225893409909150746, 7870945454511315288, 11525457118388411301, 10519485231888976311, 17601979933176863246, 5257431126828903605, - 8898009465920717074, 9418463821940622934, 3166596280515383312, 14529914354665032916, 17743784337460844568, 15964972678726654742, 17116339264937332927, 17098426671353029801, - 5868176722765418764, 8429364877332796959, 7785756492654137899, 14975349488807886278, 3272010964035218775, 8946396491617515063, 3774503492701710541, 2113917870331282160, - 8185651664029868180, 7343199417670698200, 16586532029502206227, 1531724981369431299, 5596507566645246686, 1033673521199123313, 6075312368002387319, 6988496924054716781, - 4604669688530289732, 1867259042549585024, 16180237500272383882, 3296394050993129267, 4326520583229998770, 6557569103657179065, 4126356691591689646, 8674328613473447843, - 18057076842177382833, 13020419432300857029, 13646402493577420410, 16962268104464192344, 5358581430340252761, 16443104373870300795, 10099216829282619724, 14890543634568831960, - 13276631120161396750, 16968574704982977753, 2376454925072971568, 9477134218094425043, 13784622991820528988, 2074505569780291922, 14294803056569335889, 8759684036994631222, - }, - { - 16549155412115374305, 75977962737081600, 8870825488941031605, 7403557657089993256, 5825394234709429518, 11978746413791918409, 1876293130790608838, 9416631623519692610, - 12346821858361333862, 6352722970730511156, 9920942104315084988, 10492373916708072181, 11163323626947992791, 17035282992056675772, 835685192553490421, 12792459312570503983, - 10447922451077327640, 1515090998837129975, 13498807582085718212, 1212623301098019779, 11573518650162536086, 4823461685803772444, 7289704908733783271, 13167881392748327839, - 16959954449957105311, 11051594981465026138, 16062472412226411858, 1976004115345602080, 3630495248560019222, 12698191555196404138, 10107923614229901155, 1597725222698864118, - 3416019089997140849, 3011417601086561495, 6275242351124667286, 14197557183081060761, 5633711018871057458, 9723496411345030748, 13910057756335530832, 7285051335492395815, - 16774605620279328247, 10223834398868957807, 15781733027568799739, 2607095622729296315, 16499590296954181006, 7576646116121533069, 16638313875339315529, 14296194207652471696, - 12874411821611501068, 1998417862388106640, 13882642435422318946, 5791129521978463837, 7512934139125398199, 6966283273373526248, 5475728301311080129, 13542211842758381589, - 7798993150530415596, 3288770257171840452, 13373286069558329631, 9784279046496345014, 15725032660238528813, 16038931923358478835, 6921788930154218900, 6093507035435214187, - 12194839527972802101, 8376199250979271449, 9055995864116790217, 8125030124567662718, 1070812422878398727, 3950906148308170707, 10121516919638719072, 813471384549762068, - 7610605259962047827, 14617655900985224117, 16089669078196617440, 10594009761533811214, 3425971360520359121, 1245021768718221594, 16690372892586114152, 9933179766195044175, - 15142732720676276463, 17435583143726694663, 6030257647680338377, 243683009289621849, 3064238900429394982, 7655019927497549159, 4484400084400458429, 11650860345018651068, - 16203650576183697977, 17614744533772112337, 1119292890050870301, 4574885263986729787, 8108207498737924504, 9708434439316056191, 10676823369888368482, 1078311554675991883, - 6876202174636220158, 18057502510666060150, 7821730895845187783, 8882321799602877790, 16220624224336230256, 15562800387021280583, 3043825293109091520, 697130162105054983, - 5394549491776704087, 14795348078061113966, 14206080764200897220, 4623073019242398493, 5850602047109930316, 13783531993760979209, 14764346975698048641, 8951680172224205890, - 7302725075484262769, 12572584665857403749, 6499691362933905099, 14476353114356185371, 7381716148644532401, 1573798302334388880, 8128390307766282880, 14547454176248589604, - 12109367644744157376, 18037756988516427980, 814572839386760074, 913616818805172815, 12974490864633240943, 5228203788953366069, 11458421156905635350, 14534725545904442520, - 7717994192616957513, 12204841747568567286, 3911093871228418198, 11236736110419819217, 3283907124458179474, 11742518530965881218, 15033771683298452989, 5201173013910789542, - 13950307561490203211, 2109530041534182225, 16966608361725322273, 17050013487213560977, 6582524050666171954, 8348662591649610062, 18257068567217206885, 12084557407109908164, - 18134052713971906645, 13522834551049471624, 11796035797088472898, 4408384297249203940, 13184035659663315829, 10318594606381671372, 43784547091343099, 5864759723778872652, - 273751009786971880, 17433500308695913052, 14095169299451888252, 9384697581863180516, 3670310635026975567, 7512955195757960238, 1061441390592395566, 8687976820410979119, - 5847434943730572861, 6139588162124989313, 16640425042872222986, 2868461478718351559, 4582082172412426839, 15999623457772192080, 3911979819012561187, 2157661418664981538, - 1679437503202036379, 3357369754420384657, 14227038694942012893, 10849243658636382261, 14698996273665673323, 15473144682787301630, 12886363027445513063, 4218522843946321369, - 4305571301049736163, 7569433164869749160, 9286896219015408706, 3061813620853218759, 13836461093317197944, 12893856993043908140, 17368798334120212403, 3507360881370918016, - 17887381848254057882, 5080557806347717197, 10977337278063191668, 13725230338861893934, 12618602415751234016, 7913767807930932665, 7119689779124353718, 14253582440914432409, - 16180079775228731323, 7952167928403988663, 17529082815577219791, 14568667835887326401, 80331144542697157, 16190739578357987369, 8688615216852085496, 16668129019590270615, - 7430615013050690552, 16490141830322172211, 9793941851666815428, 12678643730925993658, 248986629347794843, 14250412400606998841, 7671639316274744213, 198890803142183275, - 14099347485199617889, 10490379547566026579, 2979540189595374423, 1947868558918413664, 14807112327541983728, 2275659819146309375, 14464189275380358394, 11448352451702208893, - 6508543885912264241, 11768683250765503158, 10952591955476802447, 13816638967602836229, 15422608700909569544, 2270147616630940233, 11179267547770249728, 10448962907285827304, - 16734703714440778657, 5221611440144584595, 14517195248502569256, 17256223341936104100, 13260411672715241049, 15406026631864099983, 13737383554048659263, 15455560302156741675, - 1751310744149771156, 13066379976997527874, 3353407191478085130, 1488844206746128853, 5630044290904406795, 14205180196532348798, 10021323252656730909, 4177092513333669169, - 16120743770319899284, 12307096057555293266, 15459231763664176764, 889710173957193674, 4419259815443372538, 17256024223837463177, 6105822529166486288, 14459703836399905847, - 13918155529832261002, 12953608416498491778, 4285102780598248527, 15853935066983430239, 2610351403194505517, 14905969693015035277, 12043976761492019990, 3883507340167876094, - }, - { - 10994470105201067642, 16033352651464686189, 15774427704233149170, 4596106024708523955, 8854068685612048031, 13529126595187822090, 11509928293490788309, 11620850709434334690, - 2068337952936280662, 6856444059219131741, 17213926210819196459, 513413453513211652, 5520465604253824995, 12970886588014924605, 12296275668437451137, 16808287251356954962, - 3413637388791433603, 16937929882486384885, 11215805046681294327, 11559398419268924015, 11697258172757450737, 6137795229387768085, 3190984692021653574, 15347236891154706739, - 17955247196574331290, 285928599571507431, 11902987704297070981, 2841167725097799100, 9281167410796848363, 16444340476026142274, 3423202423051178709, 9101021305726472246, - 7129792976024548817, 11116052691850916690, 13765136177550464799, 15815419857669199536, 3490265904262366633, 3075105190264147815, 13090337405102529529, 3772589223509323910, - 1865569627339845981, 14405510401062639678, 16548248891153314376, 18134729633170718083, 7342289204282809135, 13678804825671892797, 11309594694670555920, 6482941613725556691, - 15861081392207208208, 8373665453512079014, 1489270058265748447, 3594001972161344915, 1115942979837741628, 11080512787291988167, 8129036993725083225, 3358115086982889477, - 8869273893561412239, 10349812081309865197, 8913824872487209090, 3148808685596180274, 530908416884501807, 10284103744075805979, 13606889938905754722, 2418062398586758364, - 12413212040240282991, 7478703750955930147, 1623142090654002287, 3800351594986125089, 483782039790230646, 7823394007049468275, 7643246613581822171, 15001087565682987468, - 4027740097060141621, 11299467443664320327, 11151439614540606708, 866223440636939151, 3440384894029167420, 3873155505711856537, 5954029035616033594, 15381861683078360474, - 536906646315848696, 4762701494256722953, 3244970900590282998, 13809219136128336072, 6259009038800226590, 15448401588227595780, 5228638796256712654, 52817644221507266, - 2298603653884322501, 601221199968240092, 1285112712738261659, 13882709760355308533, 13563254433762438170, 13447718334658435053, 13493687958886238103, 11032778298151679283, - 17130548285854289846, 13389656739579236890, 11825243553071488462, 3295650559395515332, 5681593832990094932, 1986112566735995333, 6900923912677810734, 12885634718618182763, - 5991348986251844787, 10652959958005297329, 4727138097613835700, 11665606181484659859, 17818486388489237050, 17381457056943650121, 11483713831771420728, 14346336385265122549, - 6806904066777263417, 13464056321884738018, 6982639430167685380, 7669355554060154277, 5859444273628884163, 13073052226541367148, 9082949662405155834, 12390918296713433257, - 8626760324117733843, 16403951745962159364, 5837394731212322914, 6847167719031297053, 2888142337636247281, 3409818743436360750, 1677113113408664401, 1222157560539217476, - 2099068961815044779, 12562181036171628906, 16101890713848274666, 6017764396716978009, 13064414845499489050, 8419967306079989759, 18212218073753486044, 1008986649080828268, - 14883940931343463293, 12319376897638542821, 12367185247284838739, 5861252096374912155, 10018798299303262817, 6422772579819453330, 2070123940915480886, 12141302052520620302, - 7347211048650261526, 4324486111460763452, 1238262417801832007, 7620393213816116173, 13629115925647807355, 17975185632155863015, 6751253893269214002, 3530207280414557051, - 2294668553308381923, 17165287249067859297, 9897724011823072967, 17409851874231284314, 13888575318617508639, 12092766090379658603, 8412268183255186961, 8046572777745318483, - 4493498909328627892, 14652253245762410953, 5345262207345951514, 3970988687199074488, 2208768899312608620, 1510839623981662369, 642580537527653605, 14940785106713466054, - 12480576687390709541, 11249304546887636239, 6075047530003410694, 6121669232248820705, 10309256543424460776, 101796817907499847, 2110451750984093184, 10778335615512351243, - 2885395260584376454, 612553588199732392, 17978615338185945515, 10414937982597482385, 6078565000469652304, 11381998957121196965, 1536418226678270090, 15114446343888525079, - 13178439025428734594, 16388038968589028071, 16165750006742628176, 17903639397633243161, 9560319088110737392, 7888974492854359310, 16116323630343158496, 10177829649622711030, - 12866004572891901059, 10190228418101288877, 4717913135317392922, 13460871068228811018, 4756401774767581561, 7711771325649205249, 13695132008344052711, 13361851345229950778, - 938191787235564236, 14328703178349042628, 10217257468952800498, 10415924210674864240, 7171739159943819214, 6502538915112206091, 3300616451202954689, 9576887970605726107, - 17259872866446195810, 3694244894150718459, 3214322135693408389, 15571503654130046642, 2332159362399220208, 14087696453363417437, 14318693886833071484, 6131092646618026480, - 2378363646789710539, 494954399989334038, 6915496914984330558, 757197055392642378, 9097171378505823650, 12104288338329241488, 1905673690814481722, 13011078677095066032, - 8123217305309052526, 2527408826476194625, 10072980201182378784, 15489255866670747761, 12978131276673936002, 8312787524887306087, 13561211528259491689, 6311660759462081662, - 16247831307849916845, 8654394682758927217, 1180998443932568506, 3847327552938166714, 17658215545137701161, 11975413369861829206, 10679985684889599173, 14928266362876119222, - 7605162785889302718, 5718899840342120733, 6057249397801266401, 9486440247354542717, 10618370743126190918, 16153494357430969850, 16785070420314699787, 11277000340020413902, - 12712274459771886808, 15748114764509451764, 1994630377849062253, 564390855806287868, 135493276425567450, 4305883520257541088, 4842008929542073044, 7035106970720249617, - }, - { - 5757832545805155636, 17609080533053427627, 13855662030602089892, 9622498683452213297, 12281586442064581946, 610529441714948581, 14740357477019436626, 16983190111725558863, - 8470173855499872166, 15915210069852758660, 12368087246231545517, 3867174158581293223, 9082358201271846042, 16663463402757176964, 13740908859955866819, 7748969412274962298, - 13375424826931892789, 8508645806391261552, 18359272328758476903, 16433208398005282080, 13071423254987294580, 7999383023651164492, 14514701556577587750, 4848295889377673720, - 1020519568493754982, 10467781020270669620, 17607771250627508499, 6620300538436640218, 3858527175523168333, 13798129597334232823, 12495322651937391008, 3926713306087152023, - 5116038770086590715, 9943789276328255827, 13715439407309914230, 4887040860130243503, 18288477612078228131, 7640050573721350378, 14537362862524718973, 1658575506924200900, - 18400486168653423966, 18026904540891591040, 2037921821724043966, 18010956304511658647, 3751340308708032971, 16275459031633957091, 17177866831427164840, 1635431811339422016, - 3897330996014812355, 14347736534650088376, 16862404119462964612, 12216005411754788835, 11561909516001453735, 6261639657930189859, 9101978764314050064, 12280333151331067982, - 910276569977357717, 2872810615152156462, 1942106118995935911, 8734004121981822024, 13862118436432879698, 1912639548162720505, 13060137938875924732, 10642216911059510120, - 5132232031613377471, 3053931945527415993, 2695169719602504430, 11855046366025891084, 16462491222215366712, 16664416596202206835, 3077124688577987843, 7109495326459366311, - 3858762384693274897, 7520194928987242278, 4496744297661574884, 16159343214247089321, 6441167128044578145, 3604951495694157848, 3072075325567814428, 1964798869371174506, - 13689578474000942304, 8998724267038772595, 3350174507425430811, 15015413657749135511, 4848907595494161497, 7935644131326131098, 385849363817229511, 10087353746314516691, - 6067717601858189468, 10438404859927821308, 9991403870358837471, 17728358586134467771, 13476949968946830198, 7311235997042381570, 4429835371823736972, 17463216455983091974, - 3446799583712077997, 6763499387263152328, 9231082163128267527, 7733182914440272884, 17225092062157610409, 8163842076250628108, 14230171836718858439, 8195740716303697476, - 57759226194841354, 14962480748390190557, 2047254208877381876, 2830450574091058648, 14905486147404440754, 15792397930637469157, 16383409053580142957, 8686506861607761226, - 11120178572139812895, 11534611317577597022, 10437856602660752754, 13925966850017814278, 16776862023867799947, 17362554889424346260, 3408825299914455645, 2606150045870067742, - 1119490156854665483, 16772836556735128526, 8607715508817325509, 9931017263385440911, 8799481055779587022, 11740562709785257943, 1956849872282864970, 595288629437737005, - 2281206023740505682, 9926719762453358166, 4061056930877891291, 15576657447058286418, 2614863633636977404, 2206334532799385250, 3474210873232711865, 8477734925846980028, - 3340305349427486363, 5188523629566097463, 6160790887356413747, 9863988255192204305, 14066826366866912046, 11932779567129411871, 12863116515340321220, 15222969978942513045, - 12758642615291604404, 3209096496454847183, 11182564090025111575, 1931382908005123647, 15151007707308352245, 5954868822601995640, 15742433078711209582, 3347972315985628205, - 16490337555999239547, 8990885971520264447, 10360258506616249745, 6630482203535351500, 16999397485942558889, 6788531264412870316, 7229988042452941955, 9856917486277085502, - 10734804718395003162, 14385908274213668346, 6022876926209575383, 371182857232839872, 7412466195447558077, 7961511694540082231, 8030758761844457080, 8046696009323575767, - 6399666206029163609, 17663811097734928631, 11470778017516778751, 17702646621253134508, 14876192013866833082, 12935280981291312476, 1467399042175927183, 8848908916563618579, - 14359906986235888744, 4587839368531771442, 10497105860390751463, 14244616431904836676, 14906421794748569105, 7955760173743833219, 17152550002849021490, 138081467951201370, - 2349932829525749283, 14749355610935637731, 14751838563606808702, 18058355029195133983, 8461199524627795693, 4219910612621001507, 12776964042319070094, 15905069451612157329, - 1355498131832429384, 15975585519420207244, 15757549940022310945, 11357394570768845273, 8197697208897202922, 1901621009956576265, 4290101364365692172, 11947148614241269523, - 5840762872471677309, 7514977007446174348, 1527060545570586419, 16609099121469101859, 9320342325870097548, 13965331598495025936, 9683433385601741715, 8845290689278472178, - 14119395813630029665, 8634138112335652518, 4658233985292819043, 9622846971166516113, 996353694479629398, 7404001202059682426, 18145845493517798921, 6449664057746980028, - 16521775738375440178, 14142357232938693849, 10990147202113110230, 9959066954415780230, 13034621383041722634, 5025797339352139456, 10322111864643366459, 2614961497496501105, - 12557910439954509999, 12230084394391362713, 8427020226737465235, 12518021396913122088, 7134271418642259845, 3905501389650646356, 15707807001177039585, 2909191175572717037, - 769225015796913609, 8753059944613840368, 1611869096690868003, 11449828005116201197, 11517191665323762104, 2697717476879599241, 11188965056705006770, 6249359019890699508, - 15594613737645580981, 3037156291483237329, 5604071908229825169, 1604475019228431078, 7766918222574600204, 9339455406279970318, 16266564745812517195, 4799424886612563329, - 11601570184515356415, 11247678357869162156, 8415095559389686315, 9625816053586466047, 11807876143163335372, 15690209134241397733, 8684637224468015605, 15974968144193406020, - }, - { - 11275984449259340674, 14922638629881602958, 17186426309348732477, 2094500549052461127, 1245672419927595636, 7529921141299797945, 3181089597449057707, 7749529014968942143, - 12842581296013847382, 7845624487558348664, 8747439372999364825, 849305823897878133, 2217292264321907974, 8173534404179332054, 3588643190593022889, 12047811416592660080, - 6959527445237219799, 17170778245769606301, 807762173031474321, 9151445233487017286, 15103411489939446333, 7976669669591851659, 14824323986579638641, 1535817133122800221, - 2365455792963674834, 2249234228455309648, 5237136544555745182, 8814246419234451463, 13017813702607013347, 2241193992640629733, 17982226236989862510, 9800528153239873634, - 14106286229675768856, 13210380707737857536, 8049798856134302097, 9734560649539497957, 1623205786926824588, 14287958304696241706, 1800854015662052826, 1212925137572581937, - 3026947385483276729, 13169758424754896088, 6834174387382969128, 7206544572805916922, 6934064062491731757, 10620406409375153308, 5194048681860016706, 1469688754160716493, - 12993558037376222988, 4669474265806332952, 4832324179281001408, 4413085485243863075, 5405837906169635761, 10091776239975644239, 5290719555562061144, 4213669820858776415, - 17271890190678399664, 284117971978206043, 14999643475704678808, 6264699496666119083, 8859934981351804429, 8300880062060532031, 3667839168820458685, 17133003164910522197, - 2997449698566957466, 7884833253198684528, 12498695470674374226, 3115564300965505022, 13376506794876055601, 17895331353362057251, 16990581103090492269, 4674862843410794096, - 5006430925084708381, 16053115139414023422, 7049813739763202517, 6676629839394309180, 2410666182773729148, 8945309185393628712, 17674821778351929167, 2683163960153153804, - 14505459891908974624, 1849503921080779239, 13990490450160111440, 5181610498614712941, 8653117877167770474, 8814499350344722617, 5343755460620184433, 243401361005198353, - 17791633957402883820, 5938849497629314459, 8356801465373786047, 3163889445599730677, 9723709910898285412, 2841967670768995554, 10896757438566636700, 7434996874241771203, - 7372440365321345784, 2862880403174214663, 8420116322934238724, 2818552325655576635, 111342786192022359, 74705672003306783, 6591511741514218962, 13124391319573921957, - 9931074113040228488, 15362193958291437280, 6613002366394890474, 5258448208225327677, 5126245224005997831, 8755434042915330962, 4405830479557957055, 13343591337768921462, - 9242810916685205316, 2838356272544913798, 10099476622515682546, 15551100165305852662, 737838832976059770, 11188026425234857295, 10166119013055947704, 8628233674684143419, - 14086272070125896854, 12009239107306499026, 6592816798466831203, 11371087141421707743, 16277593907837607793, 16449564916599232060, 17471042072158213549, 11953382410698485455, - 823047236880870350, 7830286704456953572, 6464058012664717582, 15521380082330968365, 10182202815901986450, 18143527955004661429, 3207725716803325445, 3193887560605396493, - 15569872930692175382, 5346306686087630019, 6632365629111827330, 15865883909120927399, 7200040798106687333, 5723169387900917854, 15027071603483375844, 11018037359110138454, - 741009114382240162, 13879961246490269823, 4790141947869766711, 4479737908710468090, 4979904969974036721, 634413885118778288, 101727670723732801, 3160663692354720401, - 14613304240735929191, 7658770973133328064, 3028731168325633068, 1486737152001467114, 16715835021406106944, 15214200823642287507, 18441898204110447697, 5669963154424393607, - 4313074171267006471, 16217697149498819074, 2027993870023154350, 18018610229517524263, 117205923522590215, 1784380715025232199, 307956084870608716, 4140912860495129528, - 3938313265660748839, 13018885466029447230, 12461354215832959401, 14495299413345669177, 16234805331742830462, 1578184208291171741, 17168468892394781152, 12575003872292801090, - 10424668870965277693, 8952352824982702795, 18017430252932614600, 14101949308713937413, 16342352613992153502, 6862842966642668923, 7238655696295295374, 11216037980129705353, - 8381651800836461905, 275661552864412688, 5548629401959193001, 7174991431295718071, 7441251258233899268, 14052832476485122412, 301250917807487282, 17797202428295526090, - 5173263645506172639, 7621852612520351243, 4670271322283433581, 8663786927624336026, 14433502423455668413, 6926265712671351075, 9776903322968672826, 542207238644018218, - 9588056942118198784, 14024040464098859998, 17712446698584877455, 17945455593410056285, 18104078100936060946, 9565731894604896153, 13213845893767817606, 16043575675737450101, - 3436179376183792489, 8124476612946977721, 2169106928994773725, 8589833084708985039, 15137137534993478994, 12789920909097626916, 6767184505234754407, 8369097443031908183, - 16448089571044203401, 1396460397790470601, 9796571033221459545, 8162511506983092708, 13893406727199803081, 16188892369453405032, 16023105002157964343, 7061289566170423383, - 10448117565485426152, 8145533940921335838, 1579413779055052019, 14761309857236492983, 9815666466018583851, 15131106965446764630, 16986514923298225288, 3751380281663155649, - 2224143503200162255, 9410177163066991107, 7157489123570995878, 13420515130397093319, 2675717750075873421, 6702938999067232257, 394050047437199204, 11922372120263518221, - 9930837889018815244, 11397955329795684905, 6931891256005909739, 516538601500853702, 923444815286512108, 16665363217941733257, 1377231042965759902, 8439923996651310778, - 8743817608749172620, 7804846024944300667, 507107926259802795, 5258061329638283805, 15071070675288472598, 1848743106176521296, 16295570828486620412, 7409462376590083349, - }, - { - 10223936123327786454, 2321887803300626936, 13607747528117965743, 10456421630388400123, 3266519591187534953, 1053691207967834494, 7151443045753788549, 18124688636664828399, - 6946488664257064464, 9775328903143754150, 58700362449753229, 7901817271072273406, 5074738678159003249, 18397239731906005785, 15911102965988125888, 9277654580204145348, - 1874700306906525099, 7337351570334852732, 7954195906114335343, 17230226427261850070, 5181329498860909261, 107167242193237170, 4364856176182710332, 14611171841443342914, - 10990327814895720476, 16588412771027628390, 2850177278998422188, 11569813740328484871, 3922148781422941186, 3581659216490446242, 3646872304052351376, 10887870617200051198, - 8175121141368087217, 15079393830876652065, 16766987879267543828, 10582796406546815217, 16832256009371376870, 10042650470778064892, 17867163453935683780, 7123418345572641116, - 1782651072016504775, 11033882508408412333, 11105300284232190625, 3276372405089292929, 6399472468041061588, 15319690780388315076, 4928530863063375966, 11596222198340277418, - 5452424185619067445, 12050433097586021281, 15018766900844679217, 273234254926088220, 15426383635547379531, 5213762666043737626, 2829185842069118470, 3230799283770935127, - 280030342772428106, 17354882606189694746, 17455445295460080284, 18076709382926018941, 9895982528034548913, 13681172423928175330, 1656433131309057012, 11935757350437721114, - 14437472586336929440, 17387041914242263390, 14861577074379746687, 5146556788377906297, 13036814755814090195, 15108836859245573802, 1667563994642521213, 14722845469958372258, - 7781061995240980266, 2066078418484154391, 4089376589847114892, 2434843609506038666, 18376509832460312721, 7187709121160627756, 2455436656049651823, 14419116837518875372, - 1270185079976403265, 9214436628411717184, 15450450827683432913, 2880014804806096082, 15448799931519826757, 10080240282127928735, 10673974088219619287, 12998944469117087518, - 18028691745165748687, 8931519595829275195, 18379893031942930865, 12120980098075498008, 9596371470855895261, 4133427878071274570, 13159312399982591699, 1639865074052258019, - 1661696187746428348, 2656198437014978712, 13769477291975851694, 12512848714492869444, 5980926616932344693, 15821983893144953005, 5816015630031200526, 15887565799959254415, - 16463929919291729278, 14920112063826664828, 10056471508435050704, 10696267144984026763, 12049530292963090991, 11926086636123189182, 9464890378472966538, 9719194510330239601, - 18110249193861022779, 5612784685592189906, 11360454032996393150, 6795401682138043705, 1961398978248902107, 8999847457729547905, 8941741619641401180, 6086938661427918241, - 10153847769616409178, 16591913677701651064, 11369151065084080884, 9493662847124813178, 14299126668179023903, 2451525064998641745, 16055696673728703463, 7600736037142850105, - 3331094657189179723, 8579232659787725167, 11007434086335446933, 7488529659250917009, 17217317841029490639, 7202184784979805220, 10955913831459448069, 9000508720500651545, - 12966352809478736412, 9643078159289928329, 1577471789984999485, 3065864601417367655, 13683627106599504109, 12782093364215596525, 12883456287502344466, 384144415368165580, - 2010495664660209855, 15520744321638216967, 5385447087428594566, 12897496516555487055, 7343279016502952747, 11323820480524965410, 3414484402519450292, 2497721392671865580, - 16065061175628739123, 13981641072236579791, 6942197664821630380, 1667302033233547783, 11254994815452647404, 5265777633437443003, 1242523090981771320, 11333562630675377559, - 13967113064180443992, 10679621597408504672, 16223869620849920309, 8813286726524283182, 2000697484240530777, 5417120625530117302, 12109041278382745291, 13257693171778388584, - 11737174095432286870, 13459661128718998448, 4655386724404378836, 3119616752887818891, 13324285182058113375, 1078137740985006431, 1610820303976884986, 10433300853468291587, - 13552049979590080822, 4379357932546858489, 7594644709024650108, 7268811721525297059, 6728671136192921869, 8183021491392757516, 6569378188404015319, 6481294988812800823, - 6071501855022377789, 3805172128285889052, 6802689634429908933, 11713310861536728752, 18291420299754708339, 7582277238191809023, 6183429490206797252, 10452668103640934631, - 16083971675285095468, 2965035896159234764, 9379493912871845724, 13109394112987303523, 231416620515766991, 630445729708227114, 10015412267172773636, 18104521419340860951, - 13169770634232644390, 12462964563528956096, 2689434882719314440, 5936289129999384022, 17773436345927091892, 2631892834965929605, 8167719122803587721, 2458223071457452931, - 10744932251818515465, 13367480890778627284, 15909410072235544918, 9252559547875570290, 16355895225285344183, 5115003811789024567, 7369371640924666845, 4586532908333332092, - 15999516281080615520, 10972478396135936147, 9002100275598932738, 9043399249857967875, 4975188939801806064, 14240375126510021504, 4497218436093285729, 899858725260616391, - 4788026362409273347, 8940774760122210910, 66616358927988247, 13054723206705508289, 6256911511259454580, 589353691478007084, 17831732841616807303, 10847300659030294141, - 3016120727980669767, 340560476433708073, 10516500208515875331, 14933811541787518485, 9941997565508314935, 9752941942651093949, 1928238223054143159, 16147782066840428568, - 8953947187833770878, 6627103431982157573, 1279114735725952920, 5378128106441279737, 15447712974588571571, 10552843735673449739, 14956126644414569830, 1994513099978508850, - 3339871688614476269, 2937156932445032796, 2071344655111136329, 509603454456841298, 10929109734329673813, 4531629375826317764, 1802431569220697099, 7971315018970882891, - }, - { - 4307546666223047416, 13914498777427309061, 6812156124789414732, 1680174913762530491, 6756325174405757110, 2535144759174364990, 11263393915003278429, 14767595249676286403, - 6981289090623415465, 8930069945493884157, 8223216504978132408, 796477795300774057, 3120155459209743472, 14825603392456550470, 3711879425019804830, 11041054473536223927, - 14135544350792474553, 6171419888118563156, 12495035851387242130, 2843310747449412555, 5668766087526340552, 10117858698838396246, 5181027414039980750, 13247490124270426, - 10847249691051757241, 13332329214721571156, 12457628412284474075, 17044657510482764070, 5218221397478351943, 6922630493693541156, 6207927102810766143, 5644846665334649748, - 3169200533952511826, 13123046990387029463, 10303462306703730135, 3315008874027436174, 12427067008037332041, 13190195608614554888, 11930408619792340463, 12881268563913740396, - 6700154625941523096, 796110091507466427, 5388163944686450548, 3113104467109529928, 12930558649635882086, 7536049463980825715, 11851825635055645132, 2654888532632283214, - 17530163750522835336, 9722612350417778827, 13244522480616169491, 13740964907388846002, 793235549667461791, 1998252773625399730, 9697911491069876538, 3365596945186794622, - 6506371904134856034, 9541373683805144018, 3149037850125132851, 7111810601994573897, 16732445693192247884, 4994069681898274622, 7223719243730104348, 5649174084086150712, - 4640203560336739679, 9900565149463137003, 1093715346388527458, 17169722430093991108, 14911871124664548213, 8091096017016862097, 2911569128494944136, 10192934055727569503, - 13251895658744991883, 18083873142202267221, 8241707078409323349, 5240943892375002838, 7329419846032881810, 17784005510850539551, 14034072243705748841, 10459194866755836024, - 16396304393792022741, 510358226971662693, 2002127643935690257, 14681425695950046262, 481902649451190280, 1717807040845239061, 3358903321435525144, 12361252150277163759, - 16562962997045986629, 1977585352264948582, 15588655103333244279, 253344970359156714, 12939363813291366775, 12548224526376199974, 14450582788883748364, 5869541533939881460, - 15346378007864735078, 9904337403373774864, 17933855382993937953, 9391248304932723816, 2250334275383247202, 5978804056136420670, 1528238852592364099, 6491566547950141733, - 8439860020828526478, 8674532462170555517, 13889716766953024111, 1166696901054897271, 3599113965286446905, 3276801695553601157, 6631284861504552600, 757022358659145685, - 1117291222568805017, 7148845117809308441, 4044258438241699262, 16593433123496068718, 13992202310165134218, 2998204381658279116, 11137382784909083266, 11972581616612094469, - 13970586842647892965, 3680317572634289692, 3416494470839852757, 8341497967750607131, 5522860734580749818, 6847292760525096386, 9317394708872196559, 8522252330730808934, - 7951036477225560362, 3718789111033607646, 11667291286820266731, 6927579620295878614, 6796746225018555970, 2070061401518338268, 2452626412419851405, 6130352643925327785, - 128317967134069640, 18241952544586374251, 10689311587315723515, 16537482248073764435, 15914436258832414511, 15518344078557945167, 15883120902045970449, 16251109112716994957, - 11957637677355945602, 8965882791601648704, 9390723380463051523, 15025038333096274711, 14983844148312808973, 14488574793452236487, 15795526425513195718, 11651978879566144360, - 6838341670149165895, 12326189699069923388, 9258908232339348843, 17297038041466207989, 5242182985453021593, 9648294165629935142, 9715128265517308395, 2662662536493743894, - 11289660454922592938, 470300170724369955, 4571871646010841181, 8724229358245178735, 10173959190953118810, 3611286966550223594, 10810806064515103403, 13571898391208639897, - 6782514579206442308, 893150666351200058, 2099535232722538223, 300696716419619813, 4778737709473194628, 16786610674618434170, 1751624209281870237, 1677055321500839173, - 8950755642341912951, 1974922263791844623, 5333377426024439800, 13909803085973342843, 7639604505882407937, 16195074617613125552, 8954461446680048430, 6823359994465290754, - 6790869670806738567, 4499989093713728199, 17496748050437205626, 7194829324969293638, 18432532588985091708, 12041300075343806904, 7788543067151959941, 13703334460383638224, - 15088053026772564466, 18172984562199594382, 3119317310593433742, 13835498717175822656, 10015747176747842576, 11008571041665092033, 9377877781626879674, 10465443099481589185, - 8933481722931715231, 10811948483433850165, 16314247813274714890, 503147444786527544, 2533443680646505069, 7617720894972668760, 12477410920355308950, 422423516920457876, - 1501843276089632258, 18180777013307233967, 2535426997299341256, 5318958493284100856, 16758265544916918856, 8118598628492446123, 2511013049335776232, 11181447982017705826, - 5996381448168274884, 8108757135223610234, 8067369725584584297, 7184925262427750366, 8199341143188441284, 13031376443169557016, 16036606349050125404, 11958720833222295864, - 15336831835795822898, 6806921200736832713, 5959923980569572002, 16835674225684329982, 9985579070716031367, 6517360043741716503, 16609518082836868591, 15878184747124924573, - 4786224758360153905, 10283234398763800487, 13695837902615591472, 7260571034197533442, 9225062953237806971, 5969706575516748564, 6537573986766117532, 15754484267739133126, - 5004791824134844360, 4971286291135250424, 1811371968353107289, 15772458387007519716, 17381493577383518445, 14326903440006940586, 14237922492359728234, 6234116464684325431, - 9293668142017263584, 17134656749295164870, 5879480323258506465, 4788695233340705697, 17809277710857366810, 15157733645094688870, 14143869691462709080, 3162286338158090229, - }, - { - 4471613312912718060, 13601785177495103328, 8083849806888905297, 9053545412554844461, 1876605639999952155, 6124537911475118673, 16877891074567085688, 16541720065079132344, - 18138305348849897995, 11498878557125400853, 14125346336359365201, 11991638807788804369, 13935355764550912568, 16209147067155729660, 11086190285777019292, 16727288863943596410, - 8873152377611229668, 6260821826956744083, 11489383533808918262, 6585112195310961861, 7365821041919648819, 1936165695028211587, 16164747634991415711, 17957320776652490392, - 13065030057172289846, 7278765836407486850, 383827150208081081, 7832055893191054601, 5249323286889945617, 1631661912887095912, 4431088469837785451, 2866263172993336891, - 6140213328062333551, 16704025329777067037, 5839832043209342792, 9196354634862869885, 2735762290983671190, 5323501742548818139, 3199127466610501482, 6719610946615763192, - 4032564124345275293, 240208626666701335, 10264845378648897042, 15608289126091352415, 17866864241918154829, 6207477318890336372, 491708931325462670, 7002400618323099260, - 11507747783030541234, 13683043390668171754, 9924966309328785763, 5549516466627385909, 3724001483041449858, 2408778220985427590, 10510707601023430105, 12862520912519186496, - 5012372868660694231, 12033652755433827667, 5960732801180177919, 6089487525155575261, 18400192045204062277, 12754175136438960528, 6170965736016609163, 10141374482047067946, - 11781193922347227447, 16937876011211881637, 2982972111293427964, 1728244726890919596, 3327997232304084768, 4754833121145407334, 5871027825507908591, 15772493911709624273, - 5862944033912881884, 11132730978666088350, 12167180155548291888, 16449838286695349787, 14399676610730016345, 17071083123672650337, 13727728787831175379, 7507765123422748291, - 4883057314704644529, 6606742732149784343, 16070555141087563722, 8408294891669305261, 4298316003054547788, 1573237855902568238, 5357176885445018289, 5855732582172939202, - 11721126538980357625, 7216004194033429913, 12765889884935948315, 6003399149613653734, 4571046290325663920, 15023470461830485075, 11463513436288928362, 16135217522406374542, - 14300855104129153291, 11491527690078786162, 5674183453812271017, 5044682546652747711, 9153978680942338831, 400454762074409409, 12351470849648616331, 10559229320903248832, - 11839166519633311143, 16489041153719856002, 4820713204385149226, 13768001962143023630, 13107713406478328396, 15471245828032402460, 6733652296473831544, 7665657127090105428, - 6114372925011600760, 13061069979571997963, 12156991017966837826, 12403009591138383583, 5761958709898299258, 1907771304051897263, 3007439379929412593, 18410854883912163962, - 14408045416865494124, 2442199381796557002, 10475326303775862953, 13637445125954159957, 3778313603630758744, 9247460369874272772, 17572237597883145087, 11338350096360776602, - 16486104352829691584, 11856560607954368882, 7574789609701925021, 12240083183242127118, 9872957337376856275, 11508929285199799229, 12084460294902152451, 5537978390111837838, - 17987471707896681874, 13038244305326284081, 6130570860032709721, 13697749322780057427, 15250226813583295859, 11214437899623632196, 11227424166765094355, 16073863048822462466, - 12399110995748365941, 8259021120978314016, 13249466772279340115, 11201772702582865107, 6680428295197296613, 14825065014187212998, 11638499193934854444, 13944483483619391536, - 12792956896156056673, 17521293339475028823, 5738513258925006248, 7070317930523546296, 11175557000762820214, 15356683721815441509, 3038847573301969409, 3712495274059632476, - 9703339902904468931, 6903532388259237787, 6598718994389707957, 3524767540333384210, 17230409287786477986, 398508689507908728, 12956323124513250470, 3050411724956364887, - 9936181795041159997, 16502578966693139346, 12331385558134766329, 16368402633574222539, 17549179704234998175, 16732353056786161257, 7018642409136068141, 13907639522324102590, - 3202436334590923936, 10521323531132496064, 17087322194145514933, 2557934785422493682, 1054672647095378624, 13197226692868722325, 1089249862965154915, 6479925079582112772, - 3880905381896902231, 16702686708922296685, 9815623322445801304, 3275100382267252573, 6882533095211022198, 11000715667767797665, 17615808190378608947, 7418883369171949489, - 15109802007060416273, 6172716471862133951, 10675428021956965140, 5719399515177959211, 13414568332401128475, 15437234656470291881, 15174397947571718085, 15093134682110367825, - 12767354263003560893, 9423701226679222965, 15980976879563466685, 16370172902785037004, 8843543841582241065, 16817827501960591898, 1524531339915785994, 11624580276885598157, - 17147068462804570503, 413038056092618151, 5178874804057490245, 6267545065511948977, 17573054445714024932, 7120476833739422223, 5707115123830922617, 10971108972695387841, - 12546478152711337402, 3213958910433616233, 1066524299473173792, 6276669942370566610, 14816818963020520773, 7372806616674468946, 12220278123497641030, 4953625488417522128, - 9443607421568920607, 2583030461169574647, 9900905053299561307, 15892418329702922907, 1184158607153919924, 17842123060489837980, 2681791639846598155, 14394984710894548047, - 17363678829105605076, 3907856148144141388, 7535915338133892356, 4354053943074081189, 9644954727645503986, 6816908226661921388, 15867806610099035654, 13874346146744695721, - 2654416582410062512, 9232324386948815478, 13864516581612906345, 17132638924861000235, 16875312639179645137, 11536057026563830119, 1090137303802556590, 15667188983774010898, - 4336697789732072031, 16054848662858822197, 17934449813415035557, 14518380622432694666, 14100582434152190048, 6262866632984449325, 18069160441815400774, 9798342103009260692, - }, - { - 687104890149081183, 1938816743979859301, 11342071981175913904, 4270322127259097184, 4964776270155503160, 17849333582861534767, 15814479527332819692, 8083943565773123408, - 3986890035154628803, 15316660330065019741, 11560940574529263780, 12576851520091035878, 10883944418224886092, 9908329441525486205, 11238684990962507809, 12900626758810151662, - 4077800412543228484, 7173833470188867493, 4604439809988262876, 8090706047559948234, 6117166546062912279, 15748537214854486946, 16719594636199001564, 563850925691991999, - 7109145612337154341, 10502845970727626855, 6527587047878193251, 7049690136888681718, 16750703006415156202, 2559311261501721445, 1222802194566919230, 18019462938525560766, - 322982839910423931, 2590270731903609206, 14012397059804449007, 4254569016772908483, 8508420263334539908, 9175848619353159735, 9777676085150569067, 51565612432741329, - 10233009747926770582, 4858065366607044068, 17837971428933010861, 10016544790726166742, 15260359301638740999, 5101999662344938158, 8809855615759524306, 15369468763003019252, - 4549989329927399868, 4866130696079291940, 2784467031729859937, 12617898982021887868, 2721301974598150044, 1014232218549205942, 5446756626431953863, 7315134179045561903, - 2592184418896595488, 1723751460114310463, 11198512454461769811, 6203707848404803677, 2601731234271436477, 18186700975610533226, 4757569424831899615, 13359873383138312209, - 7339520839328992093, 3349084091338116256, 16532710170417471614, 4425958052714174548, 16833748535746803845, 12665172019028452441, 11274971974705134171, 6504206221872290467, - 17921256304121537300, 16573867650874642543, 18439217559900658467, 2917797231317530012, 2415475159165597656, 2027542924210178369, 13542535558170959524, 9428931592662127870, - 17821420552135083528, 332847653840014838, 11832506312426064436, 8314663852639826188, 5744960486691350299, 8069724388577179929, 7949740770152910898, 7431049632429535950, - 13904640252203718708, 10747313134117021792, 14667070697514384141, 2600977347774743546, 15498986940124021079, 14740645313274577011, 17403811028932224808, 8060102076475954685, - 3517334016249952489, 10826317205305313746, 9664766330892822745, 4145357045596983962, 123566849370572650, 6452080295201963409, 15558941970553263818, 1191650177320171029, - 13303794914626036653, 12135860919529132656, 3620217653879289461, 5443663950311568399, 9020744500355505374, 11953955628401776228, 2101814526784564259, 18218598416910848525, - 306945432061418036, 3150552227215797902, 12928374347433953916, 13299101042862573370, 13702883318367407795, 4879985767563062391, 17591048490944890593, 5088664549487213106, - 12990649636107730851, 13002224935892458030, 4380799638612122791, 7935443787987894924, 10438069978940053126, 302419699431148366, 551508078777729872, 366155636877501719, - 1657628676376133571, 11398060401420699070, 15376723048512638551, 9875623386041366116, 9978954704196888739, 13768323245406799962, 3568095027938899541, 11120740210192996096, - 15561317952331530901, 10479759083279078649, 16536004935523752634, 2928518661531554130, 736056663469575928, 6131440330717529370, 11275149343392851570, 9601030074480228347, - 2397968519718544666, 7793046606567840651, 8971792946996316712, 16581860514259510747, 9067804351225143661, 12322425857061932421, 10680196669251962457, 7226521395530060461, - 14734735764746786753, 1378251478826083755, 13509550209468602124, 14458158239096821346, 5681313138148713219, 9054039627425609375, 4235536482830620712, 1502753755874778370, - 10053374816829223121, 5956370573575798562, 6842782625116195714, 6646143553705917790, 10487617951080656190, 3930886288654953669, 13141858447548326172, 6966039733711006320, - 3565931266726110263, 10142260659118036168, 18315406451571961983, 16857333990691080595, 6889519058362658033, 11812045051361479600, 12503117299646153207, 7223531498406875484, - 15243128568488310595, 13798032762330794140, 4456440673105474920, 17896260893739107970, 5519537045179649847, 11908888770632658821, 5444504459295913107, 5588728973482930155, - 8914021876030553161, 9071747156187788379, 14974736924255494885, 17070198435868341999, 3643991391224035758, 260637732328275649, 17609644917816078225, 2302996326941944665, - 1293835161492069734, 5795029109259991590, 6978986253519330084, 10360755458408067486, 9467742127861782141, 9197981630801498774, 6297600026339958279, 1375635441408481019, - 16875086338187280639, 18188722331528885957, 2047282716697647836, 17808297209051779725, 4756860180475663362, 16103863616340614471, 4416311024167936572, 6340715229216403079, - 14261984008515151673, 8778722476581699445, 1624620854396291363, 8490568310899028272, 6147263592092458803, 3717414274397202281, 3449154725620836174, 13526832985450537957, - 5888744936142942064, 17277140802638358763, 10290028650289820825, 1940657436863195045, 10796401239257150661, 7788083050548605852, 13474393003015663489, 8961936186303685357, - 81364364291228199, 11636155122637141142, 927710893705810893, 1403208391464987879, 4332234662194589819, 7913319387647351094, 2589089673930123808, 5387282875974124558, - 10611669207938469024, 4491327257859270050, 14129391883837344111, 13924810848449766461, 8792187899775727862, 15048142623570073200, 3933861866144269656, 1162055633060412126, - 6883724061714130987, 10416279294253729103, 12247033224345499651, 10291073256885105234, 4480789666471481188, 6022169887991948086, 3778647272347441051, 9527380466585130391, - 16407225233842256953, 13423683834633513951, 17454464203550700633, 6033758555290610449, 5063673994339442907, 12250392784929419939, 5954485814444410119, 10099095370725442279, - }, - { - 7669790431656261769, 2776517632462593286, 11694025667665633506, 9533794089008895277, 2895611631120558023, 11551410655448788956, 10026541900772270925, 6243136875017000843, - 9434484992529186384, 16435748047660609525, 16190660694150989986, 7083965852434071085, 4216306437741910756, 2698742177539497614, 5199793642504009017, 17298424769819019160, - 4041169394784902550, 5699517344009382913, 5306272267462320559, 15846674482556330025, 2606351264228884283, 4162585980422107281, 3715151019132039005, 6607223447043258693, - 8168579295855409503, 16727569921530031841, 6182114460261837773, 8940603165471931374, 6081572078077526926, 5890840443923124563, 11215305828294759727, 2875117534361804712, - 9045974983664041829, 905036705033699463, 6962033946652121779, 3027264198782618401, 13786415307358010100, 3643342525745067473, 13641958783381681886, 15675065537779359584, - 7507377696839752642, 1061259379811757443, 10276590160392917813, 6889137095037822679, 16373913505782725550, 12287733095803524526, 5695917172259210496, 6360958736925918808, - 7459854586357006968, 702429387211615855, 8231296036461604410, 628323703857882004, 1059802628602873385, 12517208225099517507, 2368172548334856593, 4792344750094708709, - 18352334786472886037, 7096021570596476676, 17045407505128867173, 2467670847537319400, 2225663888244226889, 1876713214939672742, 5329943993157142620, 12168650975912182188, - 6639850268372381409, 2284514769224558945, 15390110317831975716, 13933785559694229008, 12787641603764341997, 793886210532292741, 3222136169196008839, 11104892506868626444, - 12660547967989039787, 2109392063597767300, 9889743271997754037, 11803327596624324036, 6940409327849314286, 1466399127363116843, 2572333022681966275, 4216097356402537802, - 16858757460581672909, 5838407119753001493, 4453405435911954669, 2828665451507432751, 13657966632733241760, 6875986784381874300, 2390233934255482553, 17386653779125555159, - 2976756344404126744, 17032556609402836559, 16348907464011574182, 2196781021202618892, 8270822867494340805, 4738372358350764889, 6088256422707334932, 17121369334507507505, - 2081729301541563384, 5577186154173396778, 1865152567701500436, 1422284589642218069, 2489023909725140903, 276494395149046869, 17420927169263487236, 8292343688801608074, - 7819174654675104600, 12778055482430336726, 14615848543490171611, 17498415175263742825, 4785899184222234034, 5227136636239697699, 1570704808469050246, 2858953380860123257, - 4323577007857413306, 10524228743339400397, 5418808897687027557, 5939367271366264075, 3569359126353670574, 12961495213964770607, 8906990808988099905, 261084295374207271, - 13937553904380032591, 9165760362893872288, 14159606902675650669, 7794101517494576908, 11994596892880464164, 16211278212275417034, 1568324133241165712, 6579463633356173526, - 3784436423124943604, 14504130598322564217, 13343318845201913758, 2617267381187565844, 10063945174501910869, 8584806992850354016, 17494557973113338328, 16987450461117846543, - 3191556545349441897, 4780077336463115599, 102121356289129288, 18353108394754479957, 10099934050411322327, 10323433488737585897, 1480832277301232858, 8304664509429164326, - 16494820005379860880, 1719281141269927630, 2983529566257876158, 15928721259545722550, 3714203000118655889, 15922105900709017310, 17662263539397115758, 1577461381995722723, - 3426958921435818822, 395886748655323570, 280632942609884625, 4361473570148050146, 6600885194277340683, 16668323952296831943, 10057749804882861513, 5701592287343868424, - 6951585494335471689, 15680855848517030170, 9776921814538436791, 17640230976984644473, 5777838393869379647, 2176689364164694052, 10884627395386092313, 17656310368333301757, - 215205608065278414, 15361057989137229644, 6756215047166430628, 12215084297877052825, 7185815532109454500, 3394755837885079236, 1778980761557523977, 1861969072415300655, - 1535235777601157298, 8875662482214652105, 15404846185148709157, 6538418983879634448, 8341745508628160868, 7582603669233291629, 13003716464169800826, 13309194956036155778, - 4791947847339351337, 15204996809755844932, 11672964318683763318, 13067259871945801803, 2139419248113049376, 18195694858089271989, 7208559250123396675, 4671149208567820584, - 7276586425415793787, 14549539461274532692, 7381249250982432115, 3215735370879771405, 9197833835152018601, 17236122023193655371, 5029275100388702506, 10829687080866991082, - 15533362570521057331, 6942829144635570952, 9572990445468151820, 6294042535380467396, 9052929167426522790, 18293430694900525497, 9076155092724374912, 6410242671697688127, - 16930844972313552415, 9009509357611549679, 10722442939705348974, 4686888495512108749, 6326319203058274828, 2590592779822711917, 12876493112068819735, 12372064322375408146, - 11938822647496400962, 15333527667419199710, 2385985954862343680, 14776415112244140169, 12817753724474105460, 5129368568396757194, 607898027127847045, 3917240453172744497, - 47211231428738650, 9333275559955619158, 7534434473427098199, 8557232404317963052, 11597011861056629671, 15926835677212702441, 17943276685960195536, 2513989430679125485, - 2903417389682946131, 15905578940823611094, 4910425097773753648, 10817415382143821768, 16356392378927186116, 1174713154793914656, 9176413825070952738, 17779105524945038711, - 18302140065591767046, 6334261306636966429, 4203057092695998640, 2740754645452686340, 10020911575632378009, 5906713384548665207, 13902791548718280892, 2505591245136304093, - 369660229032730089, 11851915833529805698, 13485269529443969890, 1270120511649175022, 9128783725626301238, 6173048611666804214, 14151404531169195672, 18241008099921643437, - }, - { - 16226789363155700046, 13734705589524056856, 9629995513492843231, 2636144377026081617, 1233405076007260313, 2119672919365858964, 4932766292290315579, 4185117177904214366, - 16996170392430604056, 2476294162951949891, 6677439492116109133, 1649550562276235959, 7307278264575968221, 17128676264244010843, 9768062299436691373, 3825325732056225433, - 5861627228365499618, 5011684805137210454, 1579621475012951778, 11535371650014354624, 12847902922833318241, 4997014846790385136, 9875988184618650628, 13094082946822736823, - 17224650011872599657, 11430188086182976152, 12892063618843720029, 5912993124689510433, 7069617917494051681, 1298012103142698333, 7943359430865057535, 9329776843721719539, - 9091412025380293893, 8622355764644651307, 8718353412518918238, 12338548766610785709, 5241721208413391572, 6315749100915178625, 17919741546105181107, 13677847475856526539, - 17388254638056933809, 5422523708003180288, 16851423629233109043, 5504298365310420423, 15145549220326540137, 5184279399795985462, 2201159255780420815, 12506121988996036804, - 4460258780042860751, 1816027820333214126, 7778555198679811350, 8155451943744426012, 18392325810806023014, 3955295139981696248, 17141295608995204052, 14206938573418983337, - 9464085603669036454, 7848014338005901108, 2368914226155404065, 11578416111848517850, 6323647866244499941, 14399589996703947996, 2824522520842155768, 391310842153371124, - 17489550078249576530, 13418700716683405568, 8265132837103985034, 8386855948619700037, 4642739669076635265, 1941217860224507563, 7402267177254210690, 9863923110146355168, - 6176679707488254741, 4307819088229734202, 7082712522654871200, 14603822721598353371, 4115674343542702663, 4132348830250348245, 5992042367418590636, 15937819366199058986, - 11008669567537833607, 14841150752801539889, 5253470025479549456, 5665837575328478629, 4601810548582757669, 6173003636576141170, 6899193615399367692, 968231402917393055, - 9948650801233133770, 5836115460383443197, 11404170696974449207, 4791020823967734476, 423024247809958592, 11251668387880260801, 5562546584223492723, 578572156618131794, - 13456676488167240303, 17121749146829956377, 17370555398500311209, 5041791432274350681, 4009412063225388868, 2407629981571159579, 13052555280728877038, 11483117063845312302, - 13421089948800544371, 5001604265596626568, 15312985179876036482, 16032805766802337150, 12508684642650694186, 10422897636519090240, 3970071218688010847, 17419166239676042564, - 400453640980208069, 15220637399286523210, 17321057148174216619, 14860227640908306879, 8047994708253288483, 10174040071518845057, 3280567772472213687, 5651529697807929627, - 13988854693674964723, 10817154032069031941, 3171651998645961547, 5518712225783687705, 14706905091132091970, 13960758460934966876, 12141035142079693145, 3149939820435101269, - 17047631647660916802, 11327141967045825261, 6773994317182166280, 5064726840218426586, 11921340002806613391, 9067034595359929709, 16499225867422892436, 9333282251383805811, - 16851791401266483516, 3629537449474963381, 9616439067014312078, 17691280261538133313, 13915291913519800282, 4229243823856128517, 5998682815524220834, 18293451622818510596, - 13740317056016164038, 15410121987858832401, 12080671504470100936, 11635316325777860129, 2584464163154495637, 9849046399519426256, 7991103215010751716, 2109987257001640948, - 2505301881938098126, 9962323478923652140, 9312199523950444342, 12957822502673689705, 8060810607849163143, 737408553843844193, 8143568733429881786, 18003168270780769476, - 18361695650419575705, 15964191128341330249, 14834821085064012697, 12512940671502931238, 11592194993753547188, 14358438239394059598, 2876909840522954216, 13154864917311376528, - 1919485747906370662, 5250174270363591951, 6270889482486194520, 726576673961648732, 5067680336545953003, 3152041783219682891, 15674051618916413369, 12438966377512424334, - 7755405178378312585, 2001220826274540277, 13276328134279740680, 5464764824709243977, 5374818714652367118, 7988129049563289676, 13996688354532099099, 14091540329663446637, - 4460927228453411137, 16058422703785787527, 8016770980039986075, 11450941100964860520, 2742597710491507274, 16940752978671801273, 5897441526901650840, 5926672707007682446, - 11513132526446047688, 2371334524276946445, 2461552185903242316, 2195417192784351355, 8821293936856062699, 17392142102281287994, 4066797133115509650, 10704373174879556404, - 15778536817306082589, 5755579035239870289, 2105368957367433938, 16043807797277162048, 14990960263520315004, 15618512283659189876, 1020703273079622517, 9735594589053383212, - 11529096471626785524, 13217557548494128192, 6973227637542883184, 17901194406865837244, 2414269359614891938, 9165268075797348071, 1013041849562373861, 17525420894350269712, - 5772778048593061508, 15424756817708323928, 11842041259277183807, 17669952685051160523, 5405007811515938363, 4415223809135251038, 2223192286456742546, 15742105795795272774, - 2844957165101842208, 5188198001787563362, 17071130520794983821, 6691797472842348899, 4294126956896299534, 5788827614077663481, 16267876196920424765, 10795461545625002360, - 4405006158507706423, 8343317561528812223, 7851955346465616798, 14568481075913348758, 4391527082463073614, 13997921112025001396, 15259963045788570485, 6787776208020191083, - 4002627348223514978, 16231148554725644698, 9578235186329928114, 14741034641204805809, 14651073646349829984, 1797163177099497214, 982043220105120238, 9027434646723092211, - 11809342655313500273, 16822704101813284237, 13097372075606737923, 5463281428453250615, 11967866991673525562, 6828790575157689223, 12568831962097805646, 8385980093725157349, - }, - { - 9246769514475702626, 5788284997389507365, 15857897362850327403, 13864676801095094218, 12881526722328523267, 2620841421323221200, 12599981775316397124, 12820989846844560040, - 13066648645100247757, 16727492115601921665, 15749471761440498106, 937594351871983779, 8381111811209734349, 10884357918725639691, 781591570669492079, 12778743765298428266, - 1797915488494232282, 17274756142259274463, 14207994319179101777, 9405903752538915237, 9001743317941152797, 15048752608061590843, 4925745663463425863, 17143694017177138485, - 11613437975225156304, 8619196433402562266, 11907033287998837424, 5056904365610561965, 7637552956459333558, 2827449950719061527, 9998507085256853501, 9238562885525900325, - 13246436769495027717, 5445015753017977819, 16266739009580878036, 15566606095998238977, 12196078605380432771, 4854324313875295137, 10974170498288217052, 6425550765546527417, - 14574824159194628650, 16992289415800830701, 3499062703303067574, 11220872042664151226, 18135860701984580530, 13630928571014923388, 2913126838766947469, 15869180955632349704, - 10621010745328025245, 14637275395423748577, 12928463178963493980, 3270672471462681194, 11765440832075775157, 8138439106739837848, 10004644076263261924, 12582897670868871780, - 9605391611675301152, 14014632424042523224, 4638465078692570733, 3013469722048440965, 10972600060210514686, 4497572559400894366, 2652629676209366276, 15827846806499715082, - 216774559418075105, 7056732230404238374, 4342481467357759950, 16143194646968227790, 12304857685680249595, 5021239809847286634, 745754913624924064, 1603290801266214539, - 2784418922013631805, 3554650219010546629, 8896448905401216908, 13445015286698819482, 6508982623352460996, 3322529327934132311, 18417788670080975365, 17554108945303789353, - 17620122226715347133, 9738429733440215024, 15577771434516492888, 12422193389576942718, 18383756008252443605, 12736926759685644351, 16981429110294392086, 11999528928951986433, - 14489177617081844909, 15995916840320959685, 6361381313838994395, 11146176143708648759, 17190512001934479207, 8406914945663974955, 18073221191428103088, 14075266763636071788, - 11493260321718935244, 7134447477334726345, 10489281872281557152, 6145540581503915475, 4002857892747271740, 5167943945955725680, 2892864850826359384, 16887114279977647596, - 16493058314197913501, 14642843949567816202, 8421201635021034279, 3645913604138483317, 6127272877310948153, 3660286308390076870, 14343325047340052700, 5355450922054278073, - 8426383571761073988, 17627146217941553397, 7396223609641674418, 2402241526082789613, 4067059813672963823, 10306840429023537942, 18342506396531908477, 7249869764848707701, - 17055119974261943875, 6266720893662254540, 13102139953381148874, 5249314164321788611, 7157525732140787612, 15381277459195914226, 17265025258266710353, 17573500432599548120, - 11703325491493519624, 6756922948215553472, 10849241105791329449, 4442124988071574400, 13193138084274485850, 11408181130174894537, 16602978650637017500, 4282478513876287613, - 15849352004835856215, 7022332658299393045, 2753527422472509447, 2508636546397160815, 18156018186852519542, 13445036260276495365, 6279372959444826452, 4487789154840943220, - 6912674041294744283, 18177825269025993506, 2129493844567951509, 6833453501368177831, 1878514166200306112, 12873954541639117785, 7984716702294892278, 1590286870058148425, - 13310953099825480439, 942949035351116482, 7073926138905956784, 7700580694019269362, 3135382872993338421, 14860196563555722941, 10662854588851556233, 5736680857908686906, - 3285730769783013255, 5648284582450022694, 16712547815126338303, 16508335566005209527, 12272617736405465053, 6690178916455692547, 3481505327914964440, 9148348679521508925, - 5445751308732564169, 15671537507319596886, 17721221564106627243, 379590599139121791, 11923849517192812255, 11794879354344258105, 4802202540817083733, 9502952511912834734, - 10387170863530151921, 5325952605083195756, 9255511257002170523, 413412942592261158, 2693041233704004652, 14135620291598275670, 11595337134421837671, 1965085859594934829, - 10567751951694288416, 10466024270444644770, 17138727632883910786, 12652567654757797118, 13864111438265559205, 2552332838857882141, 3739570066357761968, 1439381288436968019, - 14926469836092482784, 1974273958550553776, 10770915481273902280, 4033929759715842024, 15461883773070197251, 5631323369668498153, 13319268013678629907, 16483196656661792008, - 5825598074470439590, 15514383036808278765, 836600073173284669, 17006029483641514808, 2253041172677940136, 10109282146738215012, 2050330973627959134, 13783991480192211446, - 7361422649689322835, 16012782899552425604, 10324124765039044621, 12319908523309013390, 17065808121376215422, 14844145564675640794, 2754581529304803758, 1149534055082731343, - 5371192675994106473, 15892724499541682278, 3862864290653799361, 15759456296270265029, 12018492462347307225, 11503979417352537931, 1894695486127847219, 15184833349947874986, - 14711143160318482298, 15515618319260581947, 10015362293284733112, 1169298538214120845, 14481541537099551545, 10304547737174682912, 9351439436434829996, 15807708290724844107, - 16946643895530263911, 6110142153011856496, 6857516759047242219, 2026267735072107620, 10338469980804248611, 8224240981205716101, 12739986350836865860, 6828408496869642385, - 18199296108774357398, 10154672256889745380, 1190269705881674139, 2317654455984851716, 6948704988682993246, 7864433505284017226, 12371653445644439372, 16432795124971446509, - 940679263188661008, 14653357165718140350, 15439920797347843673, 9415587255510557494, 18115037054677722678, 8165849408798239027, 17369387099667572407, 17619066457126678815, - }, - { - 11047138821675365077, 8918121441180891972, 26692501222219426, 15248413052700323978, 7305399157133896461, 7065644238942265367, 3949166834387057064, 14178248206708015607, - 69860179712677448, 15464996655458230480, 15095351218136595554, 3792171085643513009, 3187131848664503636, 12713332789590787064, 6278731049699775392, 1597379696359884724, - 3952205381894147962, 11371446109407143937, 7231851263356642380, 11612512368538303138, 5227214975837085115, 10737565048439707166, 6333629542995218640, 12386725921557807638, - 3631886121917081375, 14286411187847401959, 1546298555066841633, 4790996540037176549, 9541492152219486842, 12304868498960755609, 11426775785781090329, 10793898029125361155, - 16970032026045908366, 4739834790205788500, 11604777595337607879, 7222013010088766249, 5472916641327283117, 4172262758310864960, 5724466588558015820, 1116300519629843659, - 15795014995613238211, 14290583239597353888, 2490895887909073495, 11130992987297321872, 17554999787604367088, 3420129662095546057, 11472786435923282727, 16869713476687852227, - 15035061229930585935, 453017670704522761, 13269498238801130975, 9381945743239523058, 2560842189862328725, 6461599464735341542, 12067824007347016987, 254830492191366350, - 10932352970046201499, 5875690226460998551, 3699681560657289718, 8665743594825198441, 10232089728487302472, 15664572298733091969, 7267222702489958195, 10552093353886118696, - 15492342672675114391, 415437554733257587, 12890781990283079094, 13204935186176658494, 16394061615709463286, 5115734945762570776, 10421418042968619739, 5523853293632283162, - 11813086056645720947, 8830149648607040713, 12579056778157665738, 8379445845509747387, 11968812374998926933, 7579079245215672446, 18392522237039663466, 14209436550919930092, - 10567400467353853420, 12039111362360014956, 9752698954159464580, 974455144078370581, 16749750902684349652, 7431880327875076520, 16572811640260132367, 197121614392940749, - 4008236965647744142, 8547116629188387980, 13874587567755370880, 12696453513706541959, 10752386832421030566, 365775083075323708, 14295272684753058141, 11024897725724291722, - 9389823976782902582, 12987864137510618346, 14351996708263571593, 9397276818616280108, 8943695845699072910, 16761881794918812428, 14395546039428720745, 9608138420173912436, - 1876375509629583057, 3290820252719995988, 488255726920613097, 12524692306565281959, 1588481057230489293, 2737168321842385117, 3787136521155591587, 2297952115270241626, - 14002797112021507101, 15941913959379016886, 13373428680779564378, 905956693320605119, 14911807685762669378, 13046351903511292109, 5010776430112230246, 13569296078340893444, - 2399232949134869057, 16408469118941953277, 17229778225562184411, 15990256768949242309, 10694906341686584836, 2816242351659628719, 10794163145486835660, 15601904974333104002, - 11025280186920123511, 2638544612389113264, 14138782464677956897, 8182901095979048555, 11304014986311338849, 5418181013691186545, 4702887342992202530, 10901371551431733592, - 7470028071605003558, 15552389775050890646, 8285175978626575302, 11755261053723122966, 10951094485216236078, 5507384267235142469, 13239757172982680465, 16153920989213321821, - 18058993449364903238, 13898361855323379776, 4830208064835445821, 2108287244297002782, 403367259355957679, 5208097191763320114, 5105753392567780820, 6874403921011777407, - 1158521281204350113, 6232098057848694897, 12517518152351190341, 17852831094628421272, 11653774695260269881, 4420518556213490728, 13835371272800239099, 12119809446886544909, - 13202632776652821767, 12444449950521044637, 11128589812117041029, 13640351754206364654, 12210309609173025143, 2998033188714623978, 2790558847086549679, 1412882974937756344, - 8872627396983903111, 13010748252899511409, 9503554222158928531, 17266043773425260257, 14299273669130129568, 8206060595465248374, 2391269797717981426, 11490348680137544215, - 5625434013536513462, 11006046905736534335, 12974260386406529669, 9092861657954444193, 9064784322822166467, 388172762639483312, 7975459140038679785, 16519143691087724914, - 5143546864201185527, 6400878864024957342, 15513803558106064076, 6712861984922181478, 15623960351786428150, 3094277713920675576, 6184647748693682810, 7857605928718754519, - 17306606255667524897, 5112741148301782470, 12807238528895999857, 15137864759480529337, 14604908573844046691, 17945466774813936069, 8840495514948749443, 11197321446299638637, - 17220811598578674405, 4438480777123093236, 3563461541688367236, 3111403934731489046, 16319666149508644048, 11775149819643332554, 6467838040542164752, 1567553021477840718, - 5384669083154912160, 17619132083131362037, 8938889855576647487, 9107335704092137106, 10077424566800668390, 15550874273916351174, 15171215175982142697, 15277375103802490853, - 2219152199405421709, 5367881810186787185, 9606063680551349934, 18233690822105957780, 9941441403610160291, 14996958158691873775, 4936282940888570414, 16608409936766385729, - 3344228690528365773, 14741103791830625697, 12105806333035047780, 4814603778329751458, 15692542571489717296, 4074467482166609769, 11583878004635312071, 15057041878895842153, - 12046059187840675577, 1106267261822046486, 4800396230944794513, 6983782857932290361, 12630891077786998995, 18331269049237387531, 8843236455524152484, 8233277245902259517, - 4072376012468301087, 15956856707868364136, 6651399164294705117, 9169559249495366525, 8774931051408681195, 7328702764302633441, 3821510551720221090, 13559321821383641691, - 13270099407878039596, 11569032926557804346, 7759575992876193458, 8239088820951102451, 9633607727685959064, 9775909232917811341, 12297921731498614906, 14756100221590046549, - }, - { - 5228416958727036186, 12534300056259911378, 6859045937063682340, 16561718753727911412, 9427589074776024847, 4167904055656501509, 10156691045253563236, 17557096561606923049, - 12847261474293104380, 15935635664155479706, 11956861064550631146, 11743590506948225647, 15973092866215748716, 8269726904881958353, 15639962392523441528, 15171417818360069012, - 2605212343977737441, 18393471024186189813, 2302707671753008158, 8606549841034095192, 3842822953634987820, 3094721493917442423, 6408313759447502937, 13486364200254727287, - 2191808101092881088, 128992526124656216, 738676021426139131, 10157323147642681558, 11221959943853120586, 18255489816550713347, 10885231659068427649, 12104397395119665023, - 7707807226411417919, 16609863548699265350, 17639371636697428128, 8755472387723764172, 164779854477783265, 9714199241756765614, 3491355372893948450, 17683742455036967163, - 13595758632462338296, 14515163666150177917, 6720823780841221770, 15071435664343609336, 9016075014492765983, 16881277609836316886, 6969993988115170067, 15419704786434737070, - 14933348768149415725, 8499210770493553168, 6778840616148281272, 13282837866452012488, 12007326272174861053, 11172739862019218274, 15202495365302649711, 8797477675597086120, - 17862558746132168231, 4941846130090682869, 17131557654945008226, 5312800819142473968, 5818269467205924209, 13458582047859447022, 2683428091382447153, 12956887954464730664, - 11820752998821943867, 5623379642132478491, 11666807493120740820, 7241997274572162616, 17165010508995490690, 1769225877906480182, 3814296306467163522, 1913823003062817434, - 11936813336110488997, 3878433838529606580, 6540053284493149566, 10610279324743393563, 14079852809920102066, 9176732841330794388, 14287311909822853963, 7146204303626670196, - 1222343790928490335, 2199405396044383670, 14080919887213592148, 7341303626667347624, 11784881532696657518, 17307742911086150556, 6036132721599132043, 12167106497065306941, - 13817073203406999359, 7220729284169210756, 14908407498603601482, 13536224989620701632, 1615171540711527931, 2063856048260214664, 10622581435417474559, 16378505765730768032, - 6855676470217754770, 9517149712286624325, 11080380031068971680, 667425509348698033, 6136243307299269825, 5326577850303193160, 16120190278345757447, 1982981965726975383, - 15399454106099176868, 3988744407816581672, 3596277710300384050, 15129113714633923498, 1554582462382333698, 3164553872715651710, 12729140363982748426, 16366728035709811784, - 11647936211409428873, 14704462653811533865, 10005129575282387925, 1526194796943187368, 10906326807488904308, 18256878690674435807, 13093574545395154003, 12352810226542367406, - 15290817014272444879, 8012864091692295774, 7591940515496590516, 9299619125326026848, 7297256232167521068, 17861204372399797627, 3100022958796565106, 15313770879200204613, - 10190931844127971311, 4449277895844944513, 18060903840299422620, 5786504870079014862, 13877878835839147302, 17536010013969819055, 12266576574650233794, 3344384108564085445, - 10406231172694378191, 12785551100938284935, 12210880209800471137, 16615829503150405150, 11718424737227538631, 2245674303359461903, 9283401225508960391, 7699506693893764319, - 2278745583218618906, 10638058115573097116, 5685140621618740987, 7758115175926730915, 9043786871908073988, 11442680114439652875, 15805407285446479015, 17615595308217319903, - 17127838629068819444, 14692086977823146619, 2491742894643214379, 3238012827598604955, 4066194902402629617, 3613111175737094005, 3296022969960608152, 4860674720288543209, - 3753308721541654311, 13160824061458819791, 11298768140351857216, 14042645015841972579, 10518697187157549363, 9641851844202952198, 9254393371864075771, 11429987449073904258, - 2566815986599406395, 7824829323439900657, 14465315986665451243, 2957504741164666523, 2280672126115151165, 14999624386740200468, 6090063205272921919, 3478652904863279960, - 18131467168461028363, 16471039226156513736, 14133684792391617163, 7137732710914086892, 17299189471163637576, 17270681183882183871, 9046519354210103502, 16091721986926209161, - 6572875037492082093, 18318192911446580882, 18107990043035854610, 13573958681720538720, 2821064027974708708, 13000417359062035623, 18286430707379660800, 13070676610179458046, - 8521670721910745896, 7440450230382417926, 13794050882540606099, 3657777690979179248, 15466400576048586018, 7802926536345945651, 11932698778931413693, 4291944108972289013, - 16729016738422946915, 4082443597391481873, 2238453914102498318, 1806710580451019071, 18305396377745213463, 2262209146853870557, 17240603302299977012, 1540474707615687112, - 16013022710115947086, 8748688582020024424, 10921431579160628425, 2228053349060750948, 7024441100951863599, 15816203310189470753, 9078141084316010447, 9841344410499582933, - 13377311905703150010, 6352753896568161822, 11086576920416079356, 7629848369702522073, 5472036379742160857, 6535781794177956975, 7671272114437903042, 5056286897725243410, - 14579350500102276494, 5882738271691348624, 7188200631561491668, 3605286077046581049, 8957701412704914688, 10347270272487533128, 5995825272041784807, 18321189862831103872, - 2376178340116743056, 2263593380938083722, 1990228394694589285, 13477447633165073333, 9023956677421314778, 7820910817739139038, 5288765314200405868, 13070699273589738968, - 6765952613794178887, 347733275422001747, 7640026333627494061, 12925707101320796635, 5670472934143686904, 15041817307271371058, 18176041895529109656, 6838891343875575060, - 9902363248877274636, 15776195244792726061, 1935342462634574355, 16572507349421626602, 7503944294807242065, 7454248748618678609, 2837392985175901475, 16494567631149775512, - }, - { - 12299242278498309265, 117303082144788574, 18382936515565701803, 7941141688858846015, 14923823358299367958, 15681089039073030752, 16878721085421212785, 3933697483394042011, - 2878536922988449879, 8819365314325664735, 2696760638950720974, 11357179421800829605, 14730809809256560583, 16277258726425730599, 13189689275745970592, 13769784951430309444, - 10292669945637125918, 13595563061674492799, 18301330068714272653, 16981073598172019270, 4022713583718555211, 847970754090163894, 12867993617169467387, 10021141621864633865, - 15254713655124736464, 6283719686609422435, 5417864180357938798, 14010638809605797246, 10873690600705871523, 15014239467130590294, 15765460219545280655, 6048061577845125750, - 13465802402879986040, 12777495579796377113, 11251142258511736751, 8312965145580158560, 223338793373356823, 813747086573652373, 534790745256052224, 3658554932030960904, - 223170064814687698, 12938716002978051117, 3848816111228150666, 17463649319617382466, 12886402189488467296, 9605942357133455486, 12272689261734151433, 9916808458308982839, - 2879267873712146919, 1770061136847768757, 3497337219301780129, 17065005588401306579, 7675751531915094916, 4337540836976665798, 12505868586426061855, 16929961945120117126, - 12012729503226546642, 4811951115754240681, 2652621264600062520, 1108958391967017223, 2508980100759035797, 9023233544151778447, 11183557587641545146, 10726727280840759519, - 7189877122763725514, 14656082750550993666, 13508306914749420120, 4564443784575285318, 15450566991657647015, 14019683331552104148, 7751003035652012225, 960642801291306739, - 4621870789074053275, 2699296606556701282, 17510056683561737074, 14554735156054608866, 9556940770704438829, 10801168482998872433, 2280142648958056556, 4982572404720159279, - 14621729774738200671, 16850208728798178903, 2650832773786164628, 8325244333065591089, 17692120343646193143, 2242845836784335580, 9386711085286369304, 517979059098779699, - 396296174223428093, 16763788748988621834, 10606803701784640909, 2399987183687936561, 3641562114746393614, 8536687357022564742, 14532545286961725758, 14658331097531946901, - 13237433907493396869, 4990918623816750268, 17673032790739307275, 15907935024302716062, 8613470231259845273, 9346326052910147032, 17747177708802561938, 4490130127498754807, - 13867405496809412712, 7002613759387491643, 13033935552806967378, 67437088702121131, 1528641041740753990, 7001198041125832592, 6102137699349551632, 11527483925092226802, - 5535652777947676324, 1216916140919282417, 343617165825197489, 10806931059627863289, 3212291315152120591, 3351900116486367965, 8595828725191802110, 15621077401736893558, - 2386026063595321071, 9144724461940169335, 13121187420621518554, 17351696676224980491, 143495028693925520, 4590642171152119027, 8655406817079059692, 10005507077955932112, - 6982427644490593208, 5211219672384700779, 14348546115682624722, 5876199850746516331, 18396840586595761484, 1465795856184232635, 9374516147960853174, 11803025633575966436, - 16374709377982692229, 2545295070586009694, 17366393861359867323, 18067336234259281315, 9181658491221440805, 16188192004088261717, 13669686513572099673, 2044092029751770484, - 7308293641399229883, 9813539775451467496, 4837144575100457648, 14073521030008335794, 12371724228966966456, 9185074727660313894, 7387427551441329556, 1866580457929037678, - 2047964090310465728, 14133690277069748515, 8287749071957055844, 16821270580974431218, 10324684883587585565, 9652498187344172497, 2461802306013063247, 15048850312040680643, - 9659170831875656345, 4251587871822599596, 12391279033133774782, 7346556824831912968, 2133114137534468833, 8694105814921565301, 1000087733076615381, 3478818915231998954, - 15832320183998834886, 898251865651859288, 16874504161383651033, 18425166917936355349, 13387271833996394553, 808054572728974308, 2281828182196149100, 14620221246129351423, - 2755242181069093228, 16155597320469161129, 17375128328249992589, 13376690667170223367, 12825454052191060221, 13625129606409283552, 5627148592782580041, 3092789333954796605, - 105705035058376953, 7541598459498134635, 6627685529861836787, 5724525771392188178, 13865897118300842617, 627652561624109853, 167084371112939132, 14192831153344015422, - 15618434900514973465, 14267977447705810206, 8823759714826430108, 7918740515193061263, 1664424041430494212, 9076733744947861202, 12010737794701759719, 13920688631446302868, - 14823160144680924028, 15690572793903331709, 1101762466949115887, 19462496059060771, 6099422315003219574, 4300077459158116870, 1282001407902323746, 5792772971400374848, - 11488321122368726901, 14632273370344181937, 12984850848826263218, 1857014998357880446, 13897135914532207935, 15925630222053677390, 11992050787349110965, 10072349923584966035, - 12837696619944805389, 13470316523008526719, 3074966674353053986, 2630814767089382743, 13353767941686870870, 11405513520090968568, 3071969598389884693, 8212421686942839224, - 7866179127856055582, 11874624506147226333, 5793384221044709375, 4411967221310302622, 3004913667339358722, 12230878672003882045, 7395980261120250376, 5188846147165419817, - 16160221386626609076, 2876994290210606255, 6065036384672004173, 14696333348949573335, 2667009584785381424, 12100192661844794919, 12401945669155059163, 12847772853650923808, - 2286437117905535902, 3130250324287833414, 3662253455746154641, 13229041365675585947, 3663813013822489770, 3093300797589723687, 11507645566517710232, 3715061633580408995, - 3464453985305889088, 7486900500389940957, 8944303108517222303, 18319933556403836918, 6782476025105836770, 12822840946923377510, 2799592944286097404, 8737598030273298051, - }, - { - 2754563581284692865, 11257360722362829387, 8254261291934606879, 10023569920325096229, 7980898855627864603, 17162063449612285703, 9275759455936104363, 15936804738099638644, - 303387668469489035, 7978391052264888020, 15413722057350324494, 508608987485166058, 5585753287556892522, 1344134516582665443, 15144279405777509214, 17014353449841567149, - 12518577022215294774, 11347384788122950558, 17122718824958020364, 5431993665805279177, 1445831254446028321, 9845654210244803480, 18315778529692612284, 930563922336183289, - 4894710987714215219, 15704993603878996107, 1606204036324478223, 14308635149530198932, 5026736228773269251, 2911689442372084137, 9004077539360196849, 7770049130277452000, - 2745120518194234905, 17255944807561408883, 7371907591838942770, 11781525288383871227, 7814952754785494862, 15022715213812536212, 4112388658963418656, 13703771908397991335, - 17455440140812341569, 16738670164475421762, 13259904130186215994, 2168106064304872507, 1969289843772256992, 9025317999701057831, 5835661391798891929, 3826587698101558069, - 9149648374608464235, 7248346993716635643, 17283919168525322365, 10107681064815728795, 12176813938029507719, 15110337574289033068, 2436453685316043712, 5876967059744625564, - 6197919059881189313, 3300993078638782623, 9357667752372201437, 17688129755135009447, 5477090746558113696, 12602024521188880300, 15889961935507293355, 7135039746373941272, - 12561063426893244305, 3079971284510744316, 15695857190375815873, 16730673956207425338, 12065477821845465116, 13846158368121919228, 2126156187526559500, 3005167441915916768, - 3858987859895327040, 17043903959888117395, 5861237635520080595, 3292646198413575902, 14286644557048422360, 14346409530388980974, 12583555046601155161, 4665981927428063991, - 7657686120974201842, 2388299767028319466, 17934808017791217639, 16708640707026372313, 14122341266134976486, 9547124998857374491, 11194069918436025923, 14657538980930727877, - 18115789712912297420, 6543740714573413570, 1955886376702349613, 14736853369719086334, 3914330395250768396, 7607848156418885173, 18220633528980056514, 11930952850158858930, - 17010681753474701341, 6961088634819162945, 18395881317121515295, 11611411242007267179, 7996717433149311639, 2687736005475404867, 15340214362731923149, 7116441414289074727, - 14302198697220662403, 11915041511943922518, 12363437164440173650, 4047410026894059083, 11439743031696133447, 8776097395071907030, 6851061783357383945, 16484733576581941012, - 2861660066704264713, 16453202148771053225, 10039035813504063627, 6275446616881871868, 7150609984920482782, 11100941755544354363, 6219760433202580646, 2875377482232912143, - 16477698187919702699, 2757160833848759781, 5976267476122243443, 7375951277779829055, 6525111513935493528, 9969722922172879681, 12582700753056539952, 3861958159147836631, - 4207324524057007052, 13478421263392765917, 13318275642734768006, 8504333045658265535, 3960720256367501697, 1601661680373853468, 7704205542213854353, 1552780884856863914, - 11788483659211580527, 8739274750400900816, 17562450707643849072, 2113004873311762141, 8542099133996522813, 5273956141012313478, 15661081976505113338, 2290009483289921559, - 7730337285529332076, 910421998453976119, 1242962796308775978, 15931313183507922513, 296811920445331257, 5821874870466240960, 3843405649348506130, 9007082448812181532, - 7200777231000974420, 15816416455380831370, 12932038056359512011, 16422801186386616731, 489979647738684819, 8269568123908387407, 11617965045895762979, 10069799398667455631, - 8245819835927284113, 5237630684564909794, 16572245571184457585, 13396211619915630497, 9177789877937729597, 7598297211302983411, 3133511073496333246, 16553020037702090576, - 13441991323065749602, 15441570013111011986, 291172418860690999, 765089869758770890, 15943751395897588683, 1887511823199710563, 15452188663399676440, 15028027691170546376, - 11009923302693800320, 5465227554242327455, 6511134004216481185, 2187999546010819375, 8387421071023131689, 174295266381833460, 6010935117399493668, 3340537243300033200, - 270646782953286316, 6635640130829923909, 12717598479778596267, 3198506535831522029, 2605714695474737827, 14548588937126505914, 10448279824323025574, 16008560590494788290, - 11460241048816176102, 6557818897531989327, 6948658872009630691, 12506263743501199667, 1813031030961999507, 18320107449706503757, 16783076453582799039, 10113937529079967843, - 3096618551325580575, 16427990761832670936, 11792441105446619028, 682188988823121368, 15606025696371121549, 15395362449248397023, 10158149307437310549, 4442375503593769727, - 5486499432056098253, 3811951715772590831, 3856863699598204250, 559724736042732093, 13251752681229681959, 3173330346541355882, 3597530263899943500, 11567248716558420280, - 12822024566847931229, 14487146762942136806, 1361688279016339671, 2776885758026394514, 13616222293131162973, 4629388276054227930, 8304132204812769256, 15188275451670510949, - 3676452641243730693, 10839008248003066479, 7676518604603740317, 18384275325050378660, 7827069556104560937, 14335741841451672783, 1145975213382205474, 13691620069378415495, - 2513451633312793643, 17331457978938147928, 11588204658848186728, 8824497684232939293, 5956154520546906549, 14434958079241686709, 11798870987920360447, 5875117843056165993, - 11313908033360767461, 14678575871510948417, 8479250768537158849, 13854183783158898926, 9413525381201650053, 10077438283140087199, 11413783222317729281, 4418417663988371635, - 6001837395299394988, 7545846298204709215, 6662102781970969966, 12696054550672669874, 7436995610194789060, 9042605089262227561, 11621508125069628605, 7289479057360149973, - }, - { - 15555649500689005370, 7857014165815014600, 4664069234996337119, 8058230521837307501, 18090421626009183450, 9278179697462444898, 17138879353097908770, 18285223269807746171, - 12741225973381753432, 5461579923265799106, 4348015554411389960, 14970536173310927872, 11568371199139699619, 11748662751675667230, 15495664823061891700, 670495577617908409, - 9865772269601493999, 7325690007062740244, 18437964667185475354, 9546360111100619473, 6266116854923135821, 295905071295541234, 16037468634731642095, 16602609756229843150, - 13266892287530449189, 2232961926857263527, 5934654989155432442, 5415975493246016158, 17117784386882463158, 3875398271691758986, 15755743581177209843, 11380746535012415659, - 2047267291755864302, 5637045342080349843, 15779859211873634959, 2415175423642772217, 8664113127182901077, 3032959071705433205, 4250761979529656864, 8729259992491925346, - 16559648310139278090, 4796731467175572814, 9267555165184254828, 1400425639375650333, 5199035239208036114, 7994153995816640929, 15677746297407711038, 16338895562326287438, - 1740700879164022194, 8442598604870387302, 14969965175291161450, 3086786406508018865, 12097766404705693713, 3199218739761578935, 1744290654371906763, 3672816528005113908, - 10162459499000477259, 7534168794800651527, 6320985751131807192, 9263840233901040421, 12178625283764017250, 13143797113231152006, 13089053551699608219, 13480464010111258056, - 6572275813002629593, 15328678880838895837, 4281489161088939969, 17996597009627631572, 10405019085582914256, 4773602940383417103, 1455403777441353089, 14766164051850429812, - 3886207141264898075, 4215113531127552656, 14283840761174092490, 11161507022796293343, 11235510295695006534, 2260082644337974884, 3781681413610409735, 5577127823856153222, - 15609337727165147542, 5725010295752332028, 10091444858515990726, 16162855978360002823, 2478705273652882251, 11394669968372227148, 512641267828429208, 581410050368207889, - 11426681347395118622, 17135867298562042628, 10870734720453621112, 13803364322975322217, 9740527283062276630, 13765238480893165263, 4792349632705804116, 18359029140065847048, - 15215482935039834459, 3553551735757600990, 2471323651039083728, 11355669733892999598, 15830640053604899661, 1625382463038435804, 11969247519895019474, 14372668755409420943, - 11113773299077372683, 16618589175113863833, 12580653821785550146, 8264195478884998326, 13569468260761711850, 16539804400793525042, 14464540796871846551, 7710175783216723569, - 17565888320840294282, 12018783137972195797, 12159604578082686310, 3210316551614996638, 7700243787046971168, 8307491254792612954, 18022719331150542511, 15890872243361196004, - 1420251412241033168, 6449255753238336368, 7468624722117319576, 5716072259994197219, 8165015263320602150, 4757529151848960259, 2040364517493350115, 11069642333484542749, - 6861520668253090597, 14998859189233167760, 4851545815068976365, 594940747993801912, 8473464707442482665, 2316305389548210767, 3995416902578245152, 15770229481630179441, - 7316766449463697051, 1410976281384361962, 2878678490331118371, 17638505404208445694, 1130528985192221086, 7544558337870473835, 12071909234624857373, 436426448500115731, - 17436263074416557505, 4339627812592344328, 1076653379358004720, 4996950998108333398, 8528954985898069924, 8259369611572362613, 7869239207308554342, 3592003501289265534, - 9434687670958330812, 4808705744496679962, 13910334628239183613, 2628594509406050235, 10055911465166862298, 8069256921143792190, 11886968715847498191, 6351594160398684406, - 9865961381837093259, 9590584894285774485, 10674927452501376239, 13861388033657872936, 808108663597281834, 16581187679405825998, 490312642991375167, 11352102610468872412, - 12888468148530619065, 542846015600866106, 2086677842713697080, 2758534484095407635, 15767123419143795297, 7077908316515201321, 10297306681753168866, 4641656730233236179, - 104445550853777927, 3829969899624802332, 4713997522991885393, 677661257782477991, 12383280183673921457, 4373178143111769979, 6375181113677777933, 18335077047046332699, - 5472832021993175857, 6120966193470238758, 13156950075464061259, 14833372202848630444, 5760885723102571027, 18022572190906170343, 9870918995920897221, 9546055667466056471, - 9516299398994303577, 11139435630263588724, 7364473923787049608, 15378275072059759415, 7378721410182635028, 2461490895435109307, 2579531356642691202, 11061693189962996686, - 17380308085259417126, 12584808641030185141, 15485460243194852460, 16172215807782473427, 690761937231979275, 17570908286361380250, 3347059970688467328, 10404397759606846636, - 1302709369035452282, 7149637102192386111, 11659118804203241786, 13909758997057192683, 4361167997834561257, 2300569874961985919, 1609719848856066643, 9866395233709297503, - 17124591880405051324, 3379747334483646957, 2084957978131092947, 2413497199486596627, 2867893699156486423, 1357836849049583382, 13607307985344221035, 18039194570940763745, - 831259058391834318, 12782538711785697535, 12640197944141330321, 11004378265133697847, 13622812183191119169, 5878590957416415562, 4810392157669422629, 11128662835376944411, - 2248775486830407244, 1550340755758127506, 8399436463450785695, 11063895076440303538, 2168511054719571959, 12238498894267955838, 10824266376477587807, 1073243669335517712, - 13568560319245254019, 17615770913976878569, 13214159705850440913, 7542574047209989510, 7392331519546111377, 2685908847786414772, 14835825677444128105, 11347648758435372538, - 13230815692170010235, 10662664037814374845, 10120384214921531334, 8892863196093018212, 4443096401408136417, 1896901619181196514, 739574867683694091, 11233952771600927581, - }, - { - 10708602749843635238, 8046488591192123621, 11391158257016334553, 2512908912806916201, 14760224624269838038, 2631910198880826809, 2387247811669872033, 2048193899742148806, - 17392983665205025720, 12603331233691760840, 3752711326309791976, 8281544857330094164, 17004651346561270106, 10399322540256775923, 9721299450284863176, 3725182263994944884, - 13643198694788276032, 8127425924819487897, 14165945065582850538, 16520977003164405917, 1941948502806705647, 12390949208067741787, 17112117376594486408, 10232906951259490042, - 74190110112564319, 11227229657066745164, 10151080599595091944, 16591051376074591375, 8256332495682655293, 7127985739945537626, 5708687346183367016, 18310921046455023281, - 10040565835468209502, 3986586816478505371, 7957179672896506016, 13347112914739722590, 14099734293320932556, 13921950344400895005, 17478414833301838037, 961445463330402797, - 10553899634420153414, 4215979268474142438, 3643081140297634139, 11620906704125380460, 17733628678553828301, 137473878710304143, 6211837577294956591, 13926110616399428016, - 15203257341351417031, 11597829209697937782, 17317571979811895272, 15929491640570317745, 5731227916276913121, 17093153916149088230, 3908757069480556294, 18211818355208735794, - 6887629766078662088, 15330755394432598442, 14144608177273202986, 13258654996547018856, 8975611270007504091, 16869834856279102361, 12707970875852047823, 8520055680055874514, - 1643407997152867899, 5400650551136488814, 14663391437159245064, 4743209938058826866, 1728998201888511561, 11238331920657195520, 11617984741897247805, 13858029141809651878, - 14003691155137683825, 14641672309228817657, 4031783205073356111, 7414359968614421153, 8166814052414482491, 5209260157266028169, 17555696996149558694, 9780166780476833956, - 16029688335186691281, 4244772808651443261, 6450459413414527821, 695875191412722741, 11104054226249884864, 146461617619843327, 17480214580411209436, 11285418463967817315, - 4922928863857449168, 7226901725606965824, 7568276305032368752, 6253457805758596797, 14345040877576203078, 1718759302498746946, 3544444746772280646, 17880302727399449566, - 10693864548794383214, 736148233485985101, 5241869061152863453, 7166954323782542739, 16861482585847848251, 11483636939866570861, 5950529069765100144, 700887039653157350, - 3906969739692830848, 5546431121705298614, 10491799900914853406, 5871175286230239238, 2851574662174517162, 5511397532379144624, 17409985391224790540, 319012646822749823, - 15269778527761027251, 16471737837294177924, 8830398856035267114, 8206807757132984992, 1421214226977370752, 14233751335943482739, 9668238787333455452, 8700964319357541954, - 17561670470565298976, 9524122142014309347, 12619871254022879995, 4098610542031538614, 8338691110372464881, 4378598564044777665, 16435680634249352743, 12067828180476756532, - 17102475410743425567, 16244272017711449252, 17598420420289880464, 17858587557620312875, 7275673248698358659, 13952444068457447282, 14004356855576602555, 15776401868125266614, - 9848210305813205280, 13777844361911806961, 874096498600831552, 6286216140019341540, 1229781121487503670, 1221366673976886811, 4534525466071627057, 12966848050780717673, - 14890015174575641658, 7082696407720868596, 14546372439063914434, 18306301153433516531, 14360952638570231274, 5387283652784509262, 7246876761413034655, 4917620254108676720, - 16572428185201836512, 15535161956998457706, 3118508753345802652, 1036719175817464914, 9929541174185476740, 17658764424885337186, 3038747611544544975, 9299826573437432057, - 4068144934809412921, 10422353259330469599, 10820596685747357573, 18174251490011716747, 14838047097904304200, 6494279871501263445, 10908514990777375627, 2395220126873880030, - 8963350163641627638, 7331858013030906816, 15047142507680204097, 6113080618647404016, 7520779807516814683, 10255234845683676901, 12010823325949652354, 4005195924244758895, - 14455661618497189876, 980858168361168621, 5057114595071838088, 9447128440518577562, 17115933446433165191, 2063106073840638313, 5944852338857186064, 14601740796836275216, - 12750698494453238590, 822220438401342753, 12735466470750534773, 15168985403101776640, 17837672477921333079, 5413174218886573483, 8340507718774735027, 3796235681866322764, - 3366536195244539993, 13901131415620358879, 9146606194544531067, 7568835872371146677, 7101767951356426039, 1958938171972212156, 3871412404872561111, 6437054924013233533, - 12849284342518738377, 6061751293342567452, 15168528907847693260, 2071752334274992986, 338461453751559028, 17270401493472349305, 14152214298057413781, 14074152302209367061, - 3814267663972523036, 16047424572869508620, 328411057776532579, 2321721854548154476, 14950895796162035951, 2381867458906113095, 3121132178592915484, 11019696935452271225, - 17929201703034060485, 15478512769360046037, 11652099424221007544, 8436785170867890275, 16340404489137765730, 13705192502407972039, 9464924753010269658, 17372624212933856135, - 11237648987477338397, 850109691127167972, 6566350160877169296, 8028073340740368222, 4445151747345891893, 7753144690511205475, 7551118086710031441, 16785474804106433438, - 3919851124685189663, 16028223238454025712, 9008783533564802058, 15647028843636411071, 2029953422298604024, 361326896057539567, 7653333452646403127, 9211397293968688243, - 1817762546790624760, 15025271080704836746, 5761603182050280401, 10355268146728370750, 12900583599325924868, 1488036927944469046, 3405173852255315327, 5600132277974719103, - 12574920924242276218, 18146097977073890534, 18281543194137545725, 4432773597060264867, 797962164984225968, 13432184750641235201, 12394976215803938078, 3054137600383896411, - }, - { - 18270562314314829224, 17574550722906577917, 15522987576586641271, 4200899284963891561, 15719788437321868967, 18390235318178988753, 17371818886753265385, 4583380351670429228, - 10102001197913431240, 6211688443233768420, 1986665099237206297, 9248907879269017005, 3081890249882755206, 7828527646248386813, 12676034092230326487, 14655968027461080131, - 11464797300361906821, 1444449385286554508, 12433005157477847389, 964895564896662942, 8457290958728547067, 7044433897330872257, 12292673928275053405, 13679355097865192207, - 5841260956815214452, 9461234662498869948, 4761949640006529525, 18229823346336752572, 16055957459773168413, 4272222475092786627, 18249888117586812770, 4531982814021269346, - 6528332072572425694, 15678657170585498065, 14462305190193144746, 10159286562616704237, 8919172138248087686, 13247073064443362933, 3056992278576665488, 8216417459286092432, - 15095644792163717355, 9931529712396800935, 8608932369590222253, 17019087735655287783, 17120516184457264144, 16412592485673181957, 11221555966650765276, 6815162077372858604, - 2239262553722461896, 16518231021003046485, 12875479040073845800, 5243141733462514317, 12216971859495819530, 8917663622006068692, 2606734295032613674, 11237688605489138628, - 7270238601276019194, 7318279377964882079, 5226788506940171017, 16838449902078450273, 3375184937745100689, 16320655850583231520, 2173229791272659780, 9816381971766204380, - 11061652864259684005, 3625039563689831268, 4435107405432574197, 17570841169180914890, 13981724030179216670, 4992487505540472327, 12893808204753555435, 12899171569920731024, - 12002788024483301555, 629439982201171214, 13749214763651595011, 7164215996082938159, 63895081825959000, 7006379700570403491, 11929054672290963822, 14290981753366049931, - 13554823979828564217, 15627748053816803157, 12924111102804720301, 3165135223777020148, 16345805559363705538, 17656153856991335888, 5211305829410935273, 17846236012427517420, - 17113448198982970082, 8879656883528014268, 15215762680430094206, 15232212751792759071, 13699137317730183483, 11815206710130297569, 12298409691055054593, 2192455093917691024, - 6973243752017383665, 15334919534387330350, 12203459507012560294, 1880762698376948842, 13008085926447766632, 11695961991328184563, 1311309249708428072, 11981691262998313807, - 9209757463013140118, 6782250604095077195, 7896297860376631775, 11500117438976638113, 9099678680126826621, 11908588510950302487, 16863479726536938776, 6368086884375751995, - 6220904427249143299, 4501361418756965744, 13907877383736656540, 4499586229279778873, 7233050316216252450, 2775027076708404645, 5669561106187108564, 13951461080947060780, - 9742819322069712752, 8779224519997661749, 2591205872359340025, 9144644967919881415, 10495832103710459914, 4557264342687723360, 935865282128150338, 7120324256648044882, - 10780007491891304021, 14382731247791652187, 3296810302419712004, 12567831906993651128, 13933396378746555124, 9754754796778422405, 2905077741505886450, 1522919492210831578, - 7282056954663740402, 4915867300034445627, 234865561845141598, 8874426225092097899, 196269165389812019, 8951904020835594063, 6908903359164319029, 14062039535595890356, - 17922518107542393156, 17388335427727081004, 9077910363057082196, 15157438705071651749, 5615196861086779767, 17404239261681991687, 9772161835068093639, 8380484042808490346, - 4683169301229531061, 14940390399739549639, 13128742567354398401, 15222231511210090535, 7352694898928671332, 1221555526903686446, 8697118143614336514, 14515400523185205597, - 1119145169329993209, 3453487026721044641, 13723232966162256192, 15282444658208236515, 17806849942057939434, 158876409507122147, 11954364486113732203, 17566268785944006600, - 1443798830844295330, 5744920153630226551, 15739845606128975055, 10458513157123726949, 14711103578835123416, 13886988522344422595, 4454455988362290346, 3507977514728491242, - 15328194945269186082, 16398971046683442289, 16293780909421539295, 14488637138080135219, 1108438550767062231, 16291467684905586857, 11891067917592351245, 10459212739896579624, - 10239864229747754958, 12477284975467600510, 14054830413782031834, 17752968481181892755, 16082713391521411762, 17191329716867535304, 11245514405315337909, 15159733745232554536, - 4102022129275956496, 9361580273813141387, 13824110615577377618, 17115977884930866990, 15058705994968389537, 8039281695081359531, 7179945727911625126, 17628825480910826356, - 2477336341361304271, 18030759410783456479, 1164757311756325043, 14195508307731677040, 9794350654156795137, 1135232100348022155, 16693007636113380448, 17770308235375345497, - 7064407865619227176, 13284912648471743270, 9099541805618279168, 7383718461788433067, 3311987567268438113, 10943963018398042859, 8038765968977300792, 11039205462473399718, - 15444441705629456398, 12030687282161152512, 16500102437404896225, 11467410246278043769, 14031300093087427598, 14458597378298191386, 9434445586505481169, 18221119130471329822, - 2269899977501467759, 9674818903084386596, 11781166634280447465, 11752600152694102168, 14011747753002945247, 1084585411243442928, 15614695372212325691, 17196679090968022414, - 5062812993852092949, 13193601915773858975, 12910718608861476282, 447390754333146274, 18393090736120037653, 13231946117349235609, 13365030203093499221, 9724404925244523782, - 18064151108813428175, 3928735035534454387, 186686833744587171, 18406101378699384605, 16477405641027895528, 697258480673566897, 8958117283476321666, 6970167016227017231, - 12694666558858009121, 10992313774737315187, 6046508760845509477, 16818819584649823054, 10464090160691032219, 1221502600750419478, 8658907655588546849, 16110628890984509877, - }, - { - 6266830413981331818, 10890859480409122410, 738708598357264321, 9241173142142102299, 9152169484987657321, 12122430118903337055, 14270062735458703743, 13877635605034675649, - 4572419849863661964, 16330741525817240677, 5456771007607263420, 8798510164381810403, 16547183593064549865, 11355135595370359779, 17581910791451710925, 11684604415749005488, - 2766130068233451740, 15909689412657372214, 3272828023364980896, 12907534005596438003, 7065629942275705493, 10609982651084321649, 17330343421617897811, 1746246157222856918, - 13168953859078137190, 9072500190247791267, 11090199374278127099, 3503847851309060744, 14395788825673846582, 15073993563711333791, 12879874391706003251, 15417028700542288171, - 2686132933630431595, 334448852204016400, 5636563341880055087, 3897420469445246068, 10569177829735084588, 8244586887721364305, 17973493209847502315, 18083956436923498083, - 15514509130323617046, 9833490355170899102, 12028021566105512521, 6349458533674010018, 13470024118569549588, 7867188201997717819, 6110792121234766402, 9917858515766574695, - 8273062939911446888, 1936638151089648185, 44602505720759914, 7839132833110815763, 13045756168264521992, 5375972549477973022, 16964151563535745964, 2871770426902555432, - 14164643693563803212, 6386904235704679249, 931435629437735510, 4496152555914735639, 820099532545743339, 13419988718062417698, 8948965620484833159, 7238410427920554862, - 4387941928212462673, 8023190031094282215, 12322462122895470016, 17311901330042910195, 16445894183838823370, 690424095855074674, 12820742226551488738, 227935274674223825, - 17437729542205914525, 8439533239207225162, 2862942422640746698, 7340866642549630610, 6770451500989398335, 17262212260581413381, 2156505157624055602, 12195119268846383898, - 13685370053507732180, 8304030489296890211, 7042719123662732989, 12115154796394040286, 10496877583013829980, 8909625177349683785, 5268451666475070682, 8910488385056259560, - 8874918984373509240, 6652428549855789281, 14866714872885601270, 12093494664302554643, 10149999253136441007, 1611873554177023520, 10271627298853910516, 15171882630355491729, - 17085353800722834618, 3271271583189511718, 9338466116389304614, 4685545953421459012, 5059702655119414343, 201476627889215522, 6388612869673101372, 8357217932305360896, - 1836621694151238424, 11438765101326043062, 5537182303007083642, 2657011195641217678, 15370176245454161308, 1478361893117141052, 8729368992402422055, 4807782542738120272, - 5084555197036037383, 500829604818691390, 8128181767026348964, 17895639808733462562, 4138748420878083709, 267892430674902987, 8954358455330696651, 1946224964877667668, - 9440495138081785154, 17328162383695942099, 1870751290505230781, 17987066187778049275, 9952223038481207705, 10126409487298126876, 1181369784146909444, 8158422380540037915, - 13005094963168549814, 7254364757817833162, 3708127625424981603, 13214729399033107803, 14306349749849146051, 6983270854272831328, 14340019638575491596, 704963281855585401, - 14561080905697443279, 7640393429462623622, 15685656608213407004, 6317405842945074950, 4586197269496115618, 4352991463721324184, 18421865732314202847, 13679296167045126011, - 5024751682397066348, 16464187416447039066, 17561916915150311869, 1553872229528720506, 3971081625989469183, 16363381852589102144, 270446294712200212, 4668332646727035585, - 4623922898967168175, 14927682190770218553, 18082407698612059245, 8156136453512346914, 17256761355350416250, 16185397881787027880, 15277309552707416345, 5991448876439153037, - 1334994484802978518, 6876293985013000163, 4439518198423905531, 18287119869714109760, 10942138263490204506, 13981840082343935999, 186527448590996253, 11759869552919496944, - 12652601656062843187, 3947181446273381189, 6235196886760030384, 10531746495897900463, 13249616872107073217, 7937663398525899211, 8701780810784627798, 5901496026068341468, - 1059285256835989485, 18284969105568513488, 8222225088165109003, 1178299600673068913, 16068875143685216551, 17849596766342630525, 1648308197824141718, 6344465813776674352, - 13850247359965870279, 17391106451201459411, 9882112511974412840, 9027485913083134379, 2654737707750698953, 2829872619210764000, 10765067664204983675, 6008367494734883394, - 3596754664049660092, 4049565277418079196, 14294713401434678004, 682517403208603499, 13234861305501540306, 2878761138137340816, 7563571058666806838, 10752984583868770507, - 16399575624290910947, 4698193514990054887, 16222170007882213172, 6300376482027477465, 11587700570984519002, 4408509191665524069, 8909599698892352923, 15110169407475815879, - 13814725956725513903, 11675366986709837701, 8008867936756292473, 9627238521208818281, 500674066787171963, 7307892989752288627, 16701476208533897826, 13745712031279374379, - 14988991093658383268, 6586109441484875615, 1456715231981080716, 10587865765103526958, 7439504550868615754, 430398141621608230, 17710495017725824018, 1267747579289674850, - 7939033276966801601, 2952159422351169438, 10439776924885737877, 13630489377585028212, 1779349587540144503, 17209739673050012100, 4174716919431642272, 4986592555205663040, - 7110204405213656469, 5225260473696365908, 13544564684169074596, 10807318789744351361, 16301252682064971136, 5046748520130689465, 7049174921499294642, 433785658536711265, - 14622798677938552282, 10254953149954221954, 2609148400899865119, 8197897294400569748, 11784700166516996756, 18107483989994737564, 5332550435198791193, 13389061302706010047, - 10892870009313407934, 5709686117526627488, 16343828906887149047, 16063790174205876315, 9076070192754075075, 4639156357669822592, 4904064385440242264, 5942264027390072320, - }, - { - 17271984572727555145, 2097715321690717305, 5328035183708920909, 13206781766168781008, 5915693606819932446, 3870849056297265622, 18070792155150730518, 7786839743829304936, - 7939886940063870939, 3597929036186322512, 12732772396498766041, 13300425267730247515, 2345112231224079293, 12327614629296314761, 17106102937162407683, 1702694317559034053, - 8821632341545057929, 16708916351043551467, 9171560460858577216, 5711973041149612575, 15808302665077457285, 8412173943543358851, 12602476370021215716, 4778674887660148537, - 2707032230021934480, 14943945588296447659, 13333962501998857701, 10603744732015256400, 3386903941135274495, 8507451908469049716, 9231176235773710950, 995464562185179329, - 1251633503842168929, 8646405730060859011, 7525758827556699239, 12781503299321323139, 3762059070509735358, 12904588764985510882, 518456268741331092, 2752400776174997580, - 2965193395248314453, 17005383961540689211, 2510904953800463288, 14582093408745785683, 14930278391247460535, 15319775861672772086, 7915822626743762260, 10481055458185028303, - 750419144665626202, 4009275022270511551, 4810013488865977907, 13090697535304919393, 17408171061427940566, 13469810562978287715, 3952372983235223818, 12596642250700034956, - 1497127512412966214, 11292269970549257426, 13920714718237672232, 1363993524078475237, 3687544717271789391, 14097532154250414203, 8367320351336033564, 11089672460564007700, - 3927746316404254574, 9973240942982210953, 14122301504960485144, 13249357693517290445, 4259646940372475995, 13156585130751616020, 424701295260668232, 13006066175253059189, - 10308406270137410351, 18444509448482991837, 12509509048086126555, 8343613342319774737, 7902938427788958534, 9924925722974851885, 3762983399809982874, 3397026083592781307, - 2116063253535766674, 12792173758770945620, 11357854367169339661, 4502375174987631263, 11374536277081101446, 718846097450449491, 6555869089578359747, 8571702699293548804, - 16993953276024768829, 12025590727803527383, 2672535181364381995, 2183111709986676538, 14822521615475063339, 10618745739454592027, 9957515072444869664, 4797521918890127374, - 4582720743315312164, 18280419827142252016, 13380629421749133990, 16786942173448683921, 5929601960379909803, 6715621236552343797, 11192523517069751956, 228125323996215945, - 11861176681909235996, 830114321507110720, 13132205092670772295, 15318287322892364044, 9027539547229346224, 17629383881225964174, 17167841317952050345, 2169650970520181403, - 11366374573920831312, 81590945660392134, 3339836125719372590, 6176339191258224503, 13498384602634172923, 17380518646558253069, 6505222573402454298, 3404196177841425416, - 18097777493026370528, 398882723487597643, 10462164796529820357, 7704526739683689547, 12438059168025171393, 8163001730991802064, 3319372757738711275, 11518015261707325261, - 11235814273447729629, 17827792960634604769, 10951458440780869321, 13957342734404907932, 7344502969085321880, 15052563297577817908, 9276707332138855229, 16077312904856138176, - 10945312442787809330, 8353703025227023259, 2523779015225839136, 5997809042199398051, 5595238423081509301, 1901941038793828090, 983256298544496123, 929860142706986099, - 1859865867925261002, 7171610585558961405, 1708769301690637951, 1669524125723022855, 1126574755172968332, 2284167219201068318, 14925928881489847288, 4349400324295146347, - 7809927122217534998, 6003738786706135597, 16541272992243715653, 11352602417510156921, 6070703545889058045, 3742828100079104877, 9416263310824977145, 1406892456840131842, - 15907861713154660116, 1789008941779432664, 1086909323248385272, 5337878342158043460, 16405416607888113885, 8262005873603178297, 12775015438669465500, 18394022127507526579, - 9832954710628449545, 14612341389215489179, 8860090710725054989, 501948203387806263, 9969784653624607958, 8524029089859194791, 18028069685553315869, 7863046312587606086, - 940114737935470576, 15661699274328042324, 2496303902262203344, 17900779334646110602, 10928989106385540880, 11160326060698033088, 6591628982832414200, 12860480197090465356, - 4005088727670892586, 10215872293486093012, 7634075494800881158, 7707144163086802537, 7085702388211248163, 12168208652772836726, 16347414703478252736, 9386623607672009940, - 10720163442173876242, 185901255673735804, 189524655270248212, 17937598483325200462, 9672767027914841820, 10911520298114954717, 17238190140596785520, 12302850034563751398, - 1819872496749425461, 5856173707582412777, 8519855762092470428, 16315722646681962500, 11554620938156340375, 11822224388003836169, 8221825485736638318, 8413608007099273503, - 16265754830488408124, 13716061973016396515, 6050948709307262401, 7654402024031530787, 149712175032162058, 8319305312043679388, 6115793437696694706, 9669523344165801010, - 16530167766100505402, 14672843572926881623, 10752276706209340624, 6888427606311779724, 9060900993058482991, 10439396339124215720, 17640982730425880863, 12916411341252677116, - 13182242421100666863, 5267519287044706312, 1780278156705475292, 12839545421803851420, 9724873776343820617, 11742602593528879231, 7598735248774560112, 4512374343657017031, - 15080601286098047668, 6570749562833033851, 17494147260115946401, 4878559727303047850, 2259644365338981526, 4232993783633913284, 3035566741498855042, 4306414296080197928, - 3878740698199360708, 1631626027682263021, 10479957065093850273, 1678395573475248815, 9964111965340163993, 8992208313996775841, 8147773940555378986, 6205594793300838098, - 11776245660806714247, 18129100488268011560, 15389929343761297429, 14544292652959164154, 18063319363114104433, 13433144948667100183, 462314076175867487, 1862686058702915115, - }, - { - 17596113920958619489, 11920824479658301378, 3786905428099710821, 11112764289322906111, 8817260450068629272, 6518847791514184438, 14593687325057339783, 18018581321332807475, - 2056254186648603335, 12143016575009965669, 3290271983033386616, 4338404082685850854, 12660444972475266123, 6345409453044955404, 13278869140778657354, 10063005167581762786, - 5303950317664091150, 17409642188139937758, 12135894348302287058, 16444741243419918751, 13935885817311324323, 8496908197501732703, 12163317723288843510, 16891353436915314685, - 4168420842704770545, 338440394515115377, 2102734009665481092, 9772725684473416465, 1247616337419130000, 4222072446972129729, 4836898447189504007, 9154346000276664999, - 14649401370738987318, 10044081678892811795, 1306517740393103656, 16586067283450489622, 8211832777731897494, 12849393859171286949, 17327526552807783018, 14171704619529498238, - 12849053390245557890, 12693731077061619694, 5891211584023409476, 1008960642219209210, 15593393872187214387, 7381248773473326001, 16559656086795428559, 2106025108820858934, - 4347667984894353308, 2129883711661222690, 1076488804494872856, 15059968377755299195, 12380937310378496242, 16425480883270944108, 4769192332535557551, 10388305045430499744, - 8553482596123775980, 12627020622203381515, 10774788686070344669, 6271789114731522097, 6270586844349642345, 5584690155569770537, 9478526526319537174, 3405597782572827563, - 10255408065071335198, 2384996481315588922, 10679447117297819075, 3734157461055440416, 1635042286365643780, 11321809677772938996, 2373960964139986040, 4869129159740273704, - 16681657814739017038, 2045405432090866328, 9473434018957974472, 5549808619751464269, 3650191693776946828, 15805634549736708741, 16764187297356548667, 6849534466635874363, - 15295973549776084894, 8150873746601283651, 8017271980921908229, 4899654767305073834, 15257501950484641691, 17365331272978440066, 14582514748324426172, 14727798284858071666, - 3180828552573045472, 17698570278585440462, 8986722854533057232, 4518665117523514004, 1718699978312382231, 16973074530347269964, 5684175730451960274, 17228649521631238473, - 2897180423141326703, 13691273076814343144, 2967066815351306232, 1032540647518716635, 16365716239989474776, 9503666134295232767, 4599017511227366879, 14475021161770955579, - 4512626226592149712, 13575110216387069176, 13488662643497927183, 9673147324484250604, 143936220816719815, 2307325398241477161, 468315224038772027, 17743582630124600591, - 1476494936296433813, 3408612621327299295, 11632756669813257564, 14296719897220703576, 2241234207239321749, 12237974399755684219, 16253635131573079566, 11892871179872526079, - 8492025373682814159, 9341562763134230960, 10104358220305514878, 17545404790574939459, 15737064134098795026, 3880597485411313924, 388663918823974597, 15032915458906101183, - 965170717686924337, 17890763357610871180, 17588999527212997589, 13975763809893342952, 5109669798963414493, 7891916061794044612, 4789971769354067287, 13049661741280223048, - 13047125712251887103, 6463859133854403980, 12163714608926575519, 1018022589444930561, 1736262463418943433, 15665908585957261569, 8814123147308650486, 4798595000205497714, - 7506024921976923590, 5624217973379693717, 1727881279508834884, 6843292805721229768, 14721392495779901462, 15739256886195814859, 4955780690636679890, 7941019297099640360, - 1679075860853192334, 11512607379850785303, 8606478479964129549, 11355506676698290554, 8638706560448426692, 11314948425220125007, 192055228531777598, 1407009579456262795, - 13286048494307428802, 9003344338654830342, 14153483128501604993, 18443414499226619410, 1307798988667786279, 4422280407538765508, 1295189585361403916, 13026087054487841568, - 2784400402546744378, 15890015749743051151, 2721137876244951114, 5096506081391833837, 7797931926335359630, 11689452583898581132, 14104784079353186010, 3188967683935096888, - 11330231400343362000, 12540174755074499088, 10360616188128925049, 3458938550662172118, 9983547038346979353, 14986318734459319551, 6345635939240236679, 6320686366534231970, - 14746231842102190633, 3622710091833101572, 12626649920759262265, 7005023704205322451, 8825692535315999015, 4515463777365688013, 9604411949030284505, 440641657645532650, - 15551627195111259367, 17849357920181562395, 12870839822102241674, 13056924324197787476, 15109676201265834798, 12974964680406025093, 12841612415554457877, 2986633967268013902, - 16172780290314506283, 6024364507532794579, 11981052290745212925, 14235100278052078327, 12912505872017936022, 4228821405313065812, 2097279962856941481, 5542690235350104224, - 6815123236701278368, 6160442936745831892, 8260371745376005388, 715614132817606668, 7741929556783214361, 6266561134278568728, 13996537792746468394, 13116379830815883328, - 2212637711439965528, 14217650183061928416, 540869510933311267, 6195450915592159668, 14904187357299823445, 5215400274033728644, 6907285779833076435, 15804222685871187391, - 11124404141552478131, 15318338152189072517, 4067893425297764249, 1697503410612817642, 219476584157335935, 13106826093753036522, 13049745208482785760, 11832231199490391669, - 10493328169052594634, 10627081887813813659, 11388663495964140754, 1823051796271862577, 12476400584366298768, 13709148086980681224, 4023418280354022922, 7805776130903851852, - 11989040498741265687, 10985482710426001838, 598034896692782488, 12230542700168560619, 1496676485546951232, 6833695919100964828, 527254545105454187, 6276811762216173921, - 9452334891928331309, 15207477416486363718, 8081596400773698461, 7528187414539292243, 4773782664413845594, 9435822414884353799, 2722451711480791323, 13642248100035410269, - }, - { - 16570512961992288509, 15784840936011612960, 17797638261217375128, 10589124475671334830, 16848440972121709899, 697679021479737566, 1456738239410270672, 7214966028857473701, - 11434157439953722433, 9090860151661100670, 8407869262026581159, 17882547383849407986, 5277257988019769029, 11463853580825342183, 13607489835500075467, 16878800997498950751, - 16059297404709367406, 8426877510924536482, 15269952608796785555, 6256768900860981984, 13142655793714702073, 14566340391957173918, 17147065283704191109, 879106195264399, - 1169887957113173798, 4936710663791789838, 8029349457377894665, 3317691225106441967, 3622769674498678594, 1954144360900150482, 1432045977341997899, 934737636789214593, - 3519438486034584001, 16935008858078961013, 11197550931955434437, 14100007087636813411, 11096181469792598416, 1355325916242161182, 3003143504356161310, 5855778258533244174, - 3469569649879539425, 2734409579230557820, 11243101718460963222, 14449395552625174865, 2832531264658408884, 12736053595733579053, 8514265014627300817, 4646556172848350801, - 1035318057221356651, 16671259128991069733, 933190532640544326, 10073090919720429370, 16298191828003546946, 89465711115503243, 1726024123088964037, 6293688775358665990, - 9646181593082190523, 16068017411165381498, 13319927590045936565, 6113055520205251774, 5576373032696512038, 13880344501714804196, 12022206929479211261, 7387979357081975315, - 14353322331225872624, 14137906560696321406, 9597841809127146330, 14479164716385450316, 18390885446667453601, 13789601367024187697, 10599569472420906075, 2183893278236533867, - 17984045804937170919, 3008713646989855019, 11485907798025297413, 14380740919052976941, 3447658178143557676, 9095585806057103587, 698302327819557146, 7922185712178340950, - 12592522203651044465, 1491459000495558958, 16988036704095888812, 4620491143241098446, 3378886739158384486, 4601357523445825298, 7994566595487207192, 4507705687201434902, - 13553890993911526641, 1237937561304731611, 11053651340854998814, 8737874920379363783, 15414508226001886918, 9311523317130687807, 12080742822716708234, 4715194040021784977, - 11413808093931937231, 8917864246709968658, 13554307490245863526, 2827250138133094370, 7637229863299622584, 6947884496333162143, 4815638417787805223, 10291803792760846879, - 12634048591085853546, 14321728045924893987, 12328747445286182403, 436433860116637979, 5910966881246245784, 11478152401127002379, 15956760875311888867, 9580341487614973173, - 5405380974793160831, 17240616607222875763, 18407061562244315632, 1777973921117407170, 6264824459040652928, 18267228171835175724, 1278124974392461846, 16099414790431742315, - 17182132836049601530, 1486820395924546410, 14089047182364760490, 5375431386740917568, 2352352269256972682, 6220398075470064021, 11444733678216077372, 8173002234516562536, - 2862732059898640615, 16485439906762588046, 8431038226899400253, 8931540904642954995, 792388953489761723, 9296018986570869365, 406447163304028453, 13270392174836298982, - 7772216409762031099, 334915652033124323, 9705063888720244418, 9829080877134570370, 13800256788887079067, 6121678265481939341, 11747955988727867922, 15561904257519022219, - 11919247213871390231, 15058232650937578711, 16509435050946309716, 4585646383560577121, 7109079914182671169, 11070600764446172401, 13212464399509938674, 18057628120939602025, - 7896339057146013415, 17613745684396593735, 4238258305077796259, 15438639564771394288, 1482402451684594916, 3104492350488980260, 5195487229736262641, 1361150797580203482, - 16473144777827648385, 1226441665397311636, 11587851779002173636, 5723433682141598491, 3818559725806959172, 9177247615754603193, 9531025756553277601, 1716800965379459594, - 10276432666086031385, 14627452075834666747, 18000674623336885291, 15328386422432799237, 18139556051577750412, 2213209867616444127, 9597214736611625280, 2458176131336755868, - 17117806110792423322, 15887422186644000204, 18208397717053970445, 7361598408210891485, 13818554723430207838, 12816010025806087198, 17883064936092688211, 1716893191215908273, - 15949855327936545010, 15892613064802301412, 7776232754624386979, 2193423430757249310, 10751855334513902678, 13772090376350944100, 5644047706587449960, 370992037484721524, - 10797607675141630710, 16625594903133516890, 4419277245854893028, 2258389314023537326, 16758443963306613299, 15289730903996513589, 17124263661185245991, 15862017582286958991, - 12272869926038995590, 4569089761627301260, 6495211060884501138, 11124576322292919277, 18314798224925096163, 13232331582712038213, 4402693571738173484, 9384301049965683996, - 9611026793910805538, 11152002731283498747, 12528844591327054806, 1485961507414531975, 12820893906402770618, 16248407567081091370, 15794078730898691457, 18231302945982292403, - 16329953561108738383, 14553061366216182492, 5112198484879130320, 1893048255589705004, 11469678860036344015, 8992526488267920066, 18208245559304821518, 8980963391041920447, - 17694621707784163170, 16317870945177246022, 9173265111786762052, 761657177655159269, 4876597178189658673, 8185879737091523833, 7520213092991049248, 6827963030155074898, - 4104149897263226969, 1008830393844825523, 1692548451180187046, 10984924503299463085, 3526468436911084942, 18012043951628458646, 15181223987778535698, 18016160796635284569, - 1524865955503524054, 7479709667052337482, 1064851658558537015, 14404181438374010311, 192685278892740648, 38546070651855709, 17006752915941498851, 7120034574635007914, - 5783711159088718530, 3503029393593618754, 10736192136662142256, 15443859608128978668, 271805305647187927, 8244170003029416464, 17017071503038388446, 2536084345379259313, - }, - { - 11535283160083833975, 15102917952496589829, 12909095696891909745, 4611119212602854744, 4195756524232932570, 3754603965149529000, 11539276962358607816, 4401424391553230481, - 6842993463058627120, 2708745114617181146, 3832382691810282630, 10333834458057320812, 15028197197004077388, 7681293343255119354, 16227537691626587485, 6703363869832495607, - 17567108285065737529, 8693245930330183070, 4025672038042952121, 3491067119247522844, 2100799837993193702, 9579542950705774054, 5091525285265581997, 1806757015709820088, - 7757354840118131559, 16227348978414023262, 5800861674805516343, 16486235803248700961, 15646700163023677309, 504258765210816549, 13724147899924699697, 13588899538317277096, - 15895596198730294923, 12513494396374459899, 13552575153453342654, 11312160635199213507, 12446618129881485796, 11286186116805515445, 1584191291800429567, 10188741008566636830, - 10157626021970320469, 6580688164585715207, 17158416694471177787, 2873484006255074946, 14852216457444863041, 7463041347566136496, 2190030775722958628, 1116223035803602728, - 8598875756176012541, 2146658618778432566, 17575736667490551813, 3602654209723135985, 7223347129734689099, 7256921024940026570, 12249118963297692963, 18168532365040819099, - 7585174044375463988, 2491923406404093282, 9355733262044036112, 11484079611349577325, 13145030009254943291, 1234932884591406048, 479845670619308618, 87735010308690865, - 17307641427543377277, 5862898330718319545, 485176909118483750, 9845223919324484076, 4293549583740204024, 12765124043303931186, 17870894781132657382, 6508172378961793849, - 14234156373312856400, 16210939788814051708, 6478880037923038392, 10435512103812909561, 18142844321802359753, 3243996803126554757, 395603619159523019, 10213589535656704607, - 13256075137060741204, 991285459654295161, 7857174835799942102, 16201105040554625727, 18398612085349994216, 4512860776717176840, 3521452275695011919, 10622137733045360311, - 14993897771652736376, 3320388672992783302, 18421556740970114213, 7438967127794745135, 15048397725789819354, 12721899159423777001, 1135125102123667189, 6637485660805148630, - 205606553319362431, 15484041062449893984, 12896720585684759529, 16675624014916513672, 7579112430564108390, 4602460356900251082, 2677787525524280838, 16723483619407414479, - 17981939084373319995, 3989926231875116241, 15342509934701840045, 12999252495311233519, 15389919024942778009, 6136335679373143315, 4117381415379544275, 13342256463740646775, - 7622769999043907199, 15227992053145045634, 2719412067263856950, 17811161335980566241, 15036003689029442301, 4919601685231030712, 6756893600905532338, 18029567067112075531, - 15804957839814547154, 7924193945337173678, 1080401129055171214, 10816444561878528576, 13171610473229361771, 8099842733764406841, 9284741070210451667, 9245195215372025289, - 7352706423771400643, 11698139248518535945, 12836997796963939813, 5747451345763534394, 7572033904536738295, 17752330422795919668, 16404760947165813434, 13477251724246705199, - 13700661979310397040, 11172816633936827025, 7087232997755437759, 601317374152115944, 16028751590837491967, 2749566595186093629, 4445248645671399873, 14714182958477634997, - 9630153311383545953, 6436885924177487891, 2150319761793765423, 3799049242167098053, 13902640603080497957, 13121685068446422901, 10099985117244683905, 10692630753099650856, - 15680946025356791729, 10935239212262708062, 15255596602338430716, 15502989798538458360, 906862139952472300, 16128362872146694687, 9038121313842477036, 18304772087255114926, - 16961332967315316395, 2872796507989583018, 18145413156795763341, 6377517922859730669, 3543621377523624979, 10701607653242580646, 17747200374013876449, 15987594633077120628, - 3487728992359467218, 11271201736509774853, 5968332690756574092, 3519182420015237550, 17144214368301394415, 1805926423542721773, 13696269518209159134, 942126126861202483, - 16211326119697754410, 9043490763746629445, 13119640043033532883, 9720862297941999125, 12662669665140843415, 2188499520755532048, 2671631563874698813, 621164898587943254, - 4804461736506692241, 10698651491947798952, 3524135800884470917, 11451653751986650957, 10424912129082359813, 6912080226482239953, 10357808719970986526, 11757540241185558439, - 1841157911016607198, 17522398974331009019, 17392843956059453556, 10510758656389762948, 7666344868273530034, 10739409534839380580, 18010518965344703872, 14478457810678500914, - 1617286442811984718, 4008909641875477702, 9328654790542709745, 12015676532404599710, 1763241944305573436, 9348325841675336084, 4072126498552363080, 17245688939115723821, - 17277555838655940279, 16604852268187595492, 11674181070138727191, 9847423407697994070, 13562477602392929772, 8181792789545038731, 6999326623175714057, 1227784795779857129, - 14923095901189736698, 90760593075377861, 11732533481504731510, 6000651333412910877, 7847865090059184838, 16859539404919901595, 2709105957383645337, 10263820965340474390, - 3161036642361826348, 5744405044938832483, 8939741099437920817, 9766097724147073614, 12117283480449144394, 14632688836103128438, 9491651214417380913, 13676064073123352224, - 4673738700738845848, 2758750364605631228, 16596306154038523740, 4124917668203310922, 2170509910405778957, 4178077301639210933, 5109055439238993109, 9627760120514410208, - 7259236533647228872, 9608619771663043870, 4148523959415435806, 8831501534166306825, 7919036824652396994, 13625969543100731176, 2546426055029800579, 14852443398434563210, - 7185947197544988797, 13306809398790059447, 11440959253278285287, 15084384140482244570, 5059824327869316332, 7585354587200615362, 6801884469610571467, 6427162399794357267, - }, - { - 1453348772281274490, 13028088570940491471, 16100623112750251840, 5210244400259879874, 9443916155735416174, 16869520919318450506, 7479400208826706574, 14374970913352602458, - 10149597276931117465, 5778043705364022356, 13888443605241209218, 6889225091714429810, 16209363638493043975, 8516350006446457646, 9214830076046105138, 8894115046323798175, - 13026208197163596446, 1935567165776196957, 17296090833026336866, 8461284827078097590, 14545382879887213077, 3302103559307506085, 16026840048628844803, 4599071908983273604, - 16375505785562641226, 4903074653735993511, 10355787845763031761, 3188849033041803587, 3145147452182864049, 13878747873108378466, 2798650520315922121, 2325962694441538199, - 3587824003578414733, 14942115314012282784, 5312737955169054323, 12478174640832111702, 7866537714619856949, 1076672758151595875, 12163513815501875048, 8343003998956997868, - 1392855790923554429, 928317148609633070, 18064469091536763974, 13446092366984636072, 1975222540660444795, 15443703204026028192, 4016450768356916736, 16656367700821047808, - 11505659892372808762, 10322665279031813234, 16948868760451861492, 13706671779256832515, 1968671033447691229, 2446599110590827903, 13721045634744350023, 11053432744256776013, - 11530583608023224967, 15979155166527001287, 592931868138800645, 5361781029549479856, 11246418752830406096, 11882251984248471436, 12026389461944629423, 12289077922798223820, - 7685868633977346753, 12528120620943035447, 18394735788313062922, 8523101916703102094, 14261596878655792929, 6364753027040158382, 6433482955677830548, 11538026548937002170, - 16221339092185577802, 2285289075757313223, 1151823739515800834, 1010537560193450047, 10651328720714490261, 426599792903611671, 7181136719074122463, 15350479907287263858, - 7559201271967630136, 3561344874280275357, 16379496429080959327, 9662226613694502966, 10995850494788192620, 14875349277152338391, 730989400822814422, 14352408679782573731, - 1328339467113622233, 13374824154992864223, 12057132015324007824, 8507647484414695512, 9286016370798146986, 9083798709648036612, 4312959727577073260, 3732271624824420608, - 13007262390446754395, 5631627784562092966, 2644488352265945851, 15340614364643014664, 6692152810984634488, 3903120388658969320, 2513009101887784188, 11999681442010831364, - 8301343575202991577, 7108394080005777057, 3477086484634015274, 8772644795325835021, 14747670046873500269, 11068536909552811695, 12349879357573378133, 8898863927320049679, - 5231654281125841638, 5181061730027800171, 10657176101406080919, 2548241936122768256, 17140253194139059526, 17961047717804458883, 12407260567549658707, 1464243167234637194, - 14129872794455315922, 16354810591314135702, 3177417010197743958, 16494351130927698692, 16557765056328447818, 3139394196704738651, 16891813998271303650, 7374470997276173905, - 18244279644122204437, 10097660526910786400, 9270181538098732492, 362243376823712218, 12369863141977485111, 2550957813014523686, 7768963959853738595, 470330801228165919, - 14632133560934390222, 13844843545192224059, 12232948338847787315, 18223343336729121487, 5219716370019749202, 2729037467284418866, 4546118556621109595, 12191675540034649671, - 15868991745937371466, 12686820201922367283, 14799186526268126508, 1241626948050017911, 7080072468753824165, 10793537086099229143, 7855065677501047369, 9747396305344084667, - 1547814412223404746, 14194709348405912167, 15771028929623393801, 10945048172868684389, 11234483878611528405, 9542605377580701681, 4555391547268120796, 14916872217451960022, - 398873176015355134, 17609838001051405497, 3752252377312468061, 10441993652683449973, 5218696730429184844, 6514361533063264268, 16024112124035725701, 13453525984055386124, - 3452753233449684767, 8937677805622461008, 15346651759545553711, 17055791435062851045, 7025089132368408239, 7345356702153522862, 17760529714295220737, 10772604293313163303, - 9940223451501501487, 13671810088603813912, 1432075826781639138, 8145669182511487125, 852664959675237493, 11640273224943853609, 16220508798123490173, 12787926729706993802, - 15490131882364039637, 5140304620645573547, 9403655757498826823, 9824850954989176893, 6366139388903157264, 1981838834216345294, 14659870286877979556, 12091578124492612524, - 9672198938588933438, 1848525214318852627, 6500329435429402369, 8547555101599185897, 4282139019453982058, 13391782461875853462, 956960429753408730, 1865393350316759140, - 9155847368519787501, 17397005067762861574, 9943535970799289809, 16365250691105460494, 13595148040475375224, 8300668237654861875, 7149654787413440141, 9226755501324961219, - 9359301870380673800, 9344500253098672841, 282669288080771734, 1996492472861301505, 4777949892950526502, 1374151996531969836, 1529729047243522545, 3371309923165192567, - 6832171775190531128, 7903951882621813138, 13717573220828409267, 15400575122727850054, 6101307565293576434, 17226772767105983314, 3485283905347036760, 18439321272895583847, - 5095761409418784463, 15484673138064200869, 7743962634971666154, 9119597914470879266, 17978461537972396088, 11490423388734028778, 6537551181013090408, 11706370534703673937, - 6635008658379780815, 11428304571924124070, 392068559161657302, 16314310970878215293, 13769492864572584674, 16880907685897496637, 2877983831559338706, 10391660973242662710, - 16861266984653213659, 1968749328591656132, 13301499995824894911, 14523175695360471336, 15130688872832023531, 1794208537894703529, 10525607764904270704, 14288604199111912452, - 6289130721434350290, 16129337673129720846, 6648351866142453445, 7705983837166554199, 8120136556582544814, 7924417299222764443, 7821995671300500892, 17697662726179084739, - }, - { - 14086745261650819748, 17953107869776717888, 1777725846494438428, 2765314406831814212, 2603997194371852991, 2223517025105045134, 15579901335531749634, 6571733615332171148, - 5478465698516556930, 287443454357750768, 12201204663663129285, 782849770204658255, 11270045035009204251, 18152683972363144337, 10463300037926642739, 14363641589598863851, - 3790592075869665284, 5120320091554329756, 15361581282394028709, 14360464660911164915, 15249656958991931940, 2563751872827049233, 13745792006936646733, 14572943674933168173, - 3167679014977537749, 3417445004776702290, 1709246158507866266, 5861367897285174360, 8437429877561342262, 17231607446243478748, 16047596399306766948, 17656438585829685897, - 12977336347094692192, 13723871955002954132, 17399919575273038847, 16163973860244779675, 14997921584659740746, 6543247361992425067, 4675926398794487109, 17580512382853194054, - 10778828023580771765, 9812611440536367405, 14168149065325522570, 6692229110872358750, 11010962724400581057, 13055203605065073902, 11396463140731730116, 16969789651736772232, - 3285258013801327520, 14114268241282882888, 5367399533198476395, 17277410244918727028, 2751895479568588421, 751309667192066167, 13038472116718581917, 16013586354334596135, - 12364168614988940500, 13194367252463423118, 12223406606527741280, 5014139294736037086, 11244699482831816093, 5336498572491451990, 14268404582568856142, 14502318820969599316, - 13295673091232554814, 313981772853781347, 11829785736449464030, 13341198421333360997, 16787450350663111566, 6525407229623764159, 2012189087039636323, 2110887590404698758, - 16984895766311549717, 1057465499230843916, 13565444352859773343, 1019268943988786852, 2190009140530404855, 10045598732295352970, 4789803496780829836, 10700158388954091321, - 14840255112988420500, 10066628133368048408, 6527354835873855384, 16106607076894419125, 3989024604987083046, 10713316697020150694, 16811389107269552264, 11294596059797019619, - 622403023838932676, 11423409007234191765, 17086830255702454786, 1213655124481948199, 3976593910085142945, 6315875935390432543, 17947502153968859628, 18031540937011531543, - 342675887578148289, 18366454547938469828, 3853530442390999217, 7499455395579634652, 768597405171336502, 1636271570683567151, 16786205337983572309, 13056241332863199715, - 15991153618414855143, 803325462494472241, 5709347424437559249, 10138502962472290727, 4675124205115228106, 9599016746550345197, 2769443894695609085, 12311020551315051087, - 11470964304318784059, 17313372553735202469, 10686997186364536871, 9228453594798060121, 57933324335302024, 8931389936300346353, 17823596478938529898, 1126996688113949835, - 10457697409306668434, 7830477435299250296, 7772379952622394912, 6109610138112185532, 4382803614711332911, 286231563340803504, 14408860285425706036, 9445290615796219321, - 17536503470234411585, 10755841521760916925, 15905055604395954066, 10842889504280336728, 10780689817551616331, 12490302644719656914, 14399349211478895553, 6458867531104408547, - 18263696007238300109, 14344529985676987842, 12351733186419515951, 14648750128188787544, 3817061805140294292, 13460439592176294955, 2651602395003150964, 17613970291099197676, - 1107162420032075035, 14270134754120385897, 4090584027509443635, 16066949131129832709, 10961641187652236678, 5480069976143996625, 8549185711954755645, 3125346629140152790, - 18337941236561689695, 2899707239319273137, 10519944305927777790, 6913088845356962577, 13796383125935684169, 2756403850320695444, 10018647980137529204, 15185795467001072323, - 678732289042224133, 4682655677430115166, 4806112367076139288, 7101473987708012826, 9907594813802528406, 5572757906434657546, 17819688309930892783, 8734990255058630746, - 4831187103439262344, 8323117365987697459, 10690753367486223100, 8744079000061869982, 12737295198832254982, 8667406752954112119, 7942221205780634447, 12612313636795726189, - 16544756691464009983, 3413196415113664237, 18442955254149959801, 10193439941306925215, 15178607176290875326, 10962146035584651400, 11757614026658646304, 16241528460556234026, - 9593194029396792148, 6376573619820601945, 14694667798662125868, 473733746941891591, 662607401339043361, 12105576520816361855, 16629740468317868384, 12416206001206121129, - 6655696780366945398, 12313066500177107654, 15308290012322636383, 2159880960357061128, 12374858353753840133, 11331956329091160239, 11794840094276473821, 14170553661155653327, - 3336445037682266403, 3746885541049520962, 12688476435907418892, 7399089272376853858, 4625608774712059624, 1535040330210000507, 6878676093546636363, 14533846142831376645, - 6250279356724130049, 3901672557903829499, 4884397030724371499, 17385695093365573379, 1240675257703364805, 9703149291204612490, 10295741452056015824, 7249917314998921510, - 3336800790505577062, 319907795530586958, 15852045830964927276, 5538471989976998401, 16558766045222360422, 3135574045680866961, 7590873965560972285, 17191236425969884848, - 542161999237385999, 11197034618748267807, 9595673564043235773, 16351524685431643264, 17127456926935032059, 15448416181819692483, 2035065584045934249, 10976830957530152324, - 3230012351101746458, 1662948417350421518, 16062645290454019168, 6021730506322388306, 9903225699788133023, 8549278993611431648, 16267339446315716903, 9759051179942016620, - 14281696762614162345, 14970002486407845832, 14940104843292093805, 7021313216295048550, 18131586729996841512, 13957742754718859034, 14322894803959804982, 12861731196696133597, - 8838210194055479741, 16190279688839291456, 16520121358582757556, 16768959728701970634, 17279896910204983538, 3582816187015369256, 372137484481226748, 12972230207718993241, - }, - { - 11480031272463364121, 2525856087688686375, 5875255653057452580, 5606696614467440464, 12094715534218447962, 6173479337351577758, 18244015404482482803, 13199349349511499695, - 6097225965006328457, 2630336000831717722, 7049638698786526134, 4203465038263485233, 4677974565964393904, 16044036678123636261, 7266049959100300634, 11339674070148504929, - 1979992348876614621, 7494083465935166973, 16035723662722831744, 6820849908885211777, 16740735239901023053, 2017530162004533409, 3087262288875984227, 9072904925376793991, - 1830819081327272165, 11951292080860646547, 18002500803418629938, 13317986695217403840, 5005574200470766330, 10138179785738652504, 1610518863105278224, 13309443265578956954, - 8383241685301818332, 6629521234420338478, 8997316634951392497, 9976633096395028594, 5171570735720385772, 8129153749198218776, 10596302915145665067, 3726383961188926740, - 14494271933981109919, 9056473564311980628, 10557807473422306929, 1549747977888697589, 4534184223615087698, 12977118933167042558, 11930457930026683843, 8346041661496792064, - 7756665146227128459, 15140824521273386708, 693427108108819556, 14819189462601222526, 4507393341357475468, 8710020646873218244, 4535796033535410044, 11884504632761707946, - 14192194428653714479, 11578618567931657764, 6032668189933768881, 15981535562386193924, 8925792218631314923, 9408714146004183681, 8859017894477140398, 1675606340537058506, - 13447287279335601133, 7792625320709870803, 5347956615552953057, 335662974452886013, 892825083599137885, 1017154417323307505, 11923254597349925339, 13818364932306372202, - 15945578153358602744, 6304522416189552358, 2545503746231186920, 14563857419242252397, 9711931929315762229, 7949505077082864287, 8780199792032437102, 10109661610848827442, - 1628958128919487289, 9818701341087940523, 16480240737841185501, 12633108361335093100, 7982147509828265471, 17959437456356197928, 14370416793872407673, 3577532534573396628, - 3265119697568866078, 13753322853248061974, 15435163376825672274, 13646180516491714938, 15620545622955090250, 18241486585498394565, 459566729126467878, 9728217493753855944, - 3187267754295885454, 7928049460349917700, 737484733736740002, 16459695106656291329, 13000947522838718027, 11933371771659873912, 4720706464557996274, 7997020276574823784, - 12655797542121172150, 16574741514838026101, 13532097913031715162, 13578832971779600350, 18171552525916232035, 1516234640889581592, 13625693062693291889, 3869929504544890755, - 5134589228918179333, 5186584327613952853, 4114726195152833642, 578924708883784650, 9128473117392713984, 17390547319520768186, 15077700332150016764, 8707446714183162237, - 9883406233903270985, 17184231210468300584, 5498903678702785900, 6903833261382863389, 11489138095102981636, 9021901931786177471, 3227433089132150317, 16639455550797627042, - 2873811051246262545, 12759149028054319339, 17920917684786397179, 2576455203420292139, 3181713670456310447, 1109589489775958300, 8920119044838278090, 16056330702164227666, - 14277712977137303378, 3896132440952049994, 13252040000848248790, 7844779060499908154, 8651912177362107995, 5527615699397299219, 17688189207278018869, 14560189235973121390, - 10861951673021959044, 16820848382034483641, 6761027571816469843, 3555385088072119757, 9363319138244920099, 14172742116400795253, 9535965929584057049, 15628517769546199992, - 839045372102318861, 2032615141683118500, 1921816835840256924, 504869150737570005, 15932184001422473505, 7849475855313305697, 1189994394722618598, 9874798350548229684, - 11973862230325381876, 7670835358390713178, 2113918814334481709, 2289514490388170400, 4570586695077036349, 9449360682811675838, 16506880875578470116, 13723444740920888736, - 14210428465641691143, 15330786835024186142, 14173742373807858721, 15041216914246450688, 6027140311333696225, 17929849776014561356, 3955935517651718925, 12080548003455651805, - 1974142217308765297, 2347591555456293560, 9029256828390326937, 15561672734848339972, 4719329765359230610, 1924866103348851009, 4950258359754995181, 3245952633715281425, - 4636201671610663345, 16662311204732135584, 12398897461787695675, 1355753199357412657, 14695655628527768564, 1692838776852698754, 7346906782826540912, 14869028424564984700, - 7242751356102425321, 7770223857340282376, 14976092066160539655, 389604327668352376, 3472336298605227213, 11456496863560248128, 14597769228654187922, 17838672631901123288, - 10997764239928568735, 16648935573721932916, 13735964592293716412, 1364388817619955667, 2511134998006929958, 811167458534120344, 9371523327214092569, 9359553283016173792, - 15311627918891973770, 17170652974122329165, 12620036374776436604, 17439165699070911984, 18124482726761033947, 18390083820175794165, 5492125340791896125, 16506113603670143446, - 14240080119980315297, 4751983902385717684, 7941412103662252178, 4796803816695225123, 9327986654018000413, 15111345676387005726, 3582558555283734415, 11913156735178831102, - 2000999613038609412, 1070613390669459171, 595743672188217500, 9169968884291187666, 17960105939867090032, 13927107353795575459, 17872593051171658925, 11087013461789649235, - 2280207936513065312, 11704149285124951522, 2138093032627822381, 6816805886026674440, 12141709925796155041, 12164596600353477920, 5711177504477877148, 17211856235678509153, - 6061025098309340877, 4060747063380827182, 15186975689243681841, 18380882388949786706, 927262408801716090, 7447789770541113239, 14074172896745727729, 15372475239996145400, - 12915868875134296756, 3071143582305760275, 10848717856747030010, 10973183887638314967, 5983269487036236823, 9885184706933333413, 14509493669845681951, 9669608065801379977, - }, - { - 1190044221726873109, 732025666411072563, 7781096808432277694, 13079879637655900365, 9048680577986693793, 12528346194104542124, 10575369576322629835, 14068913038053465964, - 3297775431071502652, 7947266993949467566, 6161673381820779563, 10604626734847205996, 17669018066064502925, 2386071939136502354, 1076023928806956187, 16075459682742916440, - 12387028018538599950, 5791681577936683396, 7536922194386052138, 15377770247350254336, 6564316170002440575, 10629371267149545956, 16125760269901494382, 16051398044897962024, - 6237354803374899565, 1782400080026955610, 16115027077529639342, 17907259814836219524, 13179234383592426160, 7302978467158243198, 13607720993463749225, 6693531817169120736, - 9659467198848065929, 13765104107473534739, 820057324758632016, 16604163594878267405, 15321524555426147294, 14524167419333362957, 157291234996957911, 3689488130722730671, - 13896531645245568605, 13598412639648980920, 3875086557856143664, 9242105512956135595, 17410265178284161091, 14904754836127450463, 2354327747158525902, 3858493849578874654, - 17288438225198818690, 15275190140700748774, 14532856272428522409, 2192294551011758591, 4275966798014984695, 13252812474545742114, 8604705074440591847, 504054699541924162, - 3623027910997185067, 15957466839356832933, 3504133700071704955, 4135728439139397021, 1160600455691338871, 4431928072859292239, 1542956305318065546, 14109181184369694855, - 9135041378474229537, 15626265487594878380, 2645257479784082878, 8105679948445763432, 8579715781576202730, 13437359533149316300, 4344754720520585005, 13326372852934103673, - 11341622086474305983, 17104958945811183278, 8154944722722765678, 6696975609844549775, 10895966360082878017, 2277686037575837054, 12236842881540344526, 2086470279064067791, - 2942668817124399651, 11439025398519255779, 17477264434671471242, 9606507094132585461, 1771475584689465869, 10791261379080046759, 12901998265727968789, 16423426725595035468, - 555419805011031621, 13715683285513290290, 15526654591995532751, 7023761423093873354, 15093366433178982304, 8625749648874372840, 6412297471587129206, 12161114204724955762, - 9362623422820895267, 6491356159483508885, 8543224082493101588, 17290929683278258587, 17348088672546490894, 3323350644823701753, 398525379151271104, 17794417664139368677, - 5880914635028486784, 2898124605786107494, 7953506026198179840, 2189477357380899574, 11207122442953694293, 9288539232660208671, 13527697625010979453, 448462453367651162, - 11262205719433170585, 7539606872920196479, 492385789142086954, 16036594120332851267, 8084547797138041354, 10063336189771527714, 2484395715469739911, 4879298610504146231, - 194633990068625151, 1028128699653523895, 7436102537486268753, 1855520454959348468, 5098690958966904466, 3342676718901330604, 6942212660412942406, 16510188838209674083, - 8847926418142642416, 13342814936333556870, 7082971165114489981, 9307541560233171550, 3013250253632606412, 289291445038948658, 2146586262066552853, 17331519863134074479, - 13747350589043267381, 6342477793304440894, 10087817302474912962, 18076409030930122816, 240893790090129194, 16364025156922886538, 13518167316464590136, 8034023137744309866, - 14013962864860194917, 5900268096329749317, 578665371390927342, 1407477069341362927, 15142181569643383319, 5217173950329651840, 7999234477517614232, 14722759409199120103, - 857809728583972424, 12785911478120621636, 11351522624307635957, 6288237507210579634, 15030282678317951238, 5521516375915920991, 1243458350248005764, 3567973108073272461, - 2834660673354035229, 10728451420162645120, 13396052377701115268, 5730788601228223475, 1616452754395208882, 18236419625072278846, 1179103743668306981, 9179882267624091153, - 14087439523312437665, 7814060325531094731, 16777382811045908592, 16916500419494378884, 16312259370378381991, 15848836870251345077, 16352246673954213424, 5228629139249919486, - 16889782864065172884, 4486233301301317202, 12424854171669138635, 12490430652425390015, 17335301435940798099, 9685877269515541824, 8728054940414220990, 12781228698496150916, - 15949574575791239459, 10394047428873141717, 15915386168603191086, 11400139144838475744, 17198578050070482368, 10505386377385262682, 11269920026804647377, 6796664536515856824, - 3285292208372623455, 3132524240856145976, 9712372580979649457, 10523781046601368064, 4797168047433466290, 11748687702182632788, 4177442610271848350, 8549047039673741703, - 6897143822689085584, 12727238507037725105, 12692443686524496083, 1187606781546544862, 11016254758711515442, 15622643445771261724, 16669571628491989170, 7099030384210775042, - 3541342827520921014, 12596176563952906070, 5209816272233406534, 17158219989390045881, 9096207539532607151, 12291463442559161708, 5188945441827912424, 12721126884401346746, - 8137171114112655022, 6980210601071561830, 10156197453074241467, 4481350962546197264, 1902625885079226055, 18310954340184922140, 10624840172920793227, 121304340390125189, - 5261036238619130144, 1418912875050883205, 4741122621962383610, 17995804738511375239, 15493968366750472633, 8417505178158780382, 14685111207483504618, 9729483826733360559, - 13434828863770210135, 2940287993177646896, 18241509923298296610, 7613631401252601295, 16815829390381900683, 8566309323681786413, 11094402941539790077, 8442864581771174862, - 17650059733379916650, 4260524072883785227, 8351659371377110706, 710338300032970720, 5512358883882849029, 15533759462039713914, 14352344066268876816, 16708588250954382269, - 7963995066277321795, 14986230345162551366, 10616366460602472778, 16186943329215681149, 9522855644164647723, 9858336437877021178, 16344942402271072884, 18027353494090590022, - }, - { - 13175608910844763921, 11168387468381338510, 5555873864224342205, 17780559602571640345, 1582669533588472814, 8145133762789622706, 1625372887980692455, 4576809104068554285, - 2900978533555060931, 1749946807863203576, 11705734511931072459, 4446980691693419424, 14437524160594907241, 12795912566640000773, 10400036254697939154, 8356113088668925361, - 8900726473285671992, 890209742292473781, 16059468388719373167, 16577940938542233221, 17381766864962227733, 231915274132518769, 16477817024012878700, 15646021286310268545, - 17511864284462479051, 4391315454785363822, 16633389246499252566, 4290325975494843430, 15912670649662225191, 14172733821603328367, 12709802627494541709, 9648238681838878635, - 4196883387800999444, 11261069840079702254, 7135968036494594517, 14537849011631244070, 1930221875891546479, 3029378442249928630, 6219774718328347890, 5922417028077454069, - 12470404961188516783, 10420863874252801995, 1369334550763670666, 4781925915058005676, 13086538845357988031, 11031029468188842766, 15252022305121561855, 10497770692868889659, - 8808726441417268278, 8201526072266158452, 1136378216494101481, 15014143365043073153, 9752793532008788265, 18423606089906807282, 12708377698545978413, 13697405528655748691, - 12840624483048662115, 13614226123606379619, 15087571995173849344, 1395488309690794621, 7173958427217959878, 1198561064176820332, 16821886260165681626, 10019479169661217935, - 8089335244564816024, 4652396396372834438, 8473523796721514770, 4493469844513366216, 5448577418901909194, 13487502520341193870, 17978888920023381084, 13125222810420128122, - 11369140159803973135, 8391820975236191093, 4865145203995472561, 14899728882581231165, 11169032718524058736, 14532440521453562763, 7464998467530340358, 14981246381757614771, - 1242992129726403300, 2014928170416925311, 6341058783517690890, 11690291498253019630, 15951586247597589423, 14033993236702971559, 16963725291567059464, 15075124616754319226, - 9901328250515532535, 12796305315632203942, 10819069447660403847, 12542238242508661240, 17077777737462854238, 4364294351375777648, 8335244153165894685, 8863541604979427311, - 12648774127830238318, 5576880401343711606, 11786867566889606858, 7421038047404952574, 1037620897405863409, 16680872357246325645, 10443290127564886223, 9718182896013830581, - 15199007294286606824, 10225517367964809030, 12827778649823141649, 16046039393887815140, 284741135347255597, 4015036609703147909, 3902771329647468314, 5128707935422024078, - 16953148044626345363, 5101833106541998042, 7655361325113312133, 15948906743291877728, 11619404274756349415, 7521254459857915559, 14978040810149334918, 18392994517091959591, - 11029520456752683158, 2297291237551781454, 7934683676555855479, 1563954733146546128, 2252805128528536255, 10523375695822939112, 4598652721256818062, 17493379105069761435, - 1717382065475436420, 12444276194160330384, 3605273785657402256, 17503422605669121015, 12066457002913396306, 18109827202111882684, 11555238022219952400, 1993655497207863497, - 14852223665677610379, 4743851404709775958, 8525514757892437524, 10402777181498591725, 17096034999928466604, 4289543339828736175, 4306145672261807290, 15366124999227707930, - 9159996652502914864, 10301349423202296392, 13530090903323000632, 4082840779249202050, 8824726775176314063, 16033767772359951785, 9181204573557660412, 7582747879080399183, - 2747551692916263132, 3151123035150683281, 13938314333309683791, 11970864255483579560, 7894236725861110998, 10515613623232567716, 10445557830757066839, 11155097727742050955, - 511773909731247800, 2463012923954369656, 15859141716591041471, 4940781664379556792, 12435624343534748284, 10278084527750129328, 13178135781125832492, 5930328346313533490, - 9122100956633732655, 4007876149211873275, 8339438668849688737, 7791075492023424820, 1771434463088769532, 17441254147665904787, 9470298561063283873, 16552350513326886351, - 2842235074681099572, 6045955093828210410, 12534027406207583719, 9023829328537353058, 1661393615224515538, 3265308219651631507, 14825441620546235307, 6190486519065164472, - 9569762631377921701, 10341967309273270300, 4697570564829842013, 16684762125903667303, 5281929071085172097, 13027961546412671127, 18398764602992176314, 3872796039504642974, - 3625046733403850478, 18072436321985678348, 12926724831909767455, 17260889391923475120, 2205546675974800411, 4823605748727161314, 11756378320036258430, 12725625915588142865, - 3620769638269480452, 531680461898170, 10213227252513668871, 15446816035938502695, 15189868868814686765, 8689079054027125562, 10767300823767661010, 12185259819280811201, - 2954211398425891878, 887045055614004603, 17024961552904496644, 11183183814128062689, 2275500228939836642, 8454621353771976628, 13706050871317440521, 13152782683288296426, - 5035609627965208105, 6338722048255995169, 11594969687968475335, 5639340633771742838, 6928934109570365590, 11589609913085167707, 18353534295019770247, 6879412911232288750, - 13223374340976842384, 5803903047180226505, 10382392856292138950, 6807712794865416975, 7273350714698980002, 16071615116869102753, 11130104866208195846, 17099222713467268806, - 4288395624114587260, 10186593737807119648, 5970871638851383523, 17274628153010076591, 11083355019391773968, 15571651381840416650, 7269503864920933911, 34314525388851272, - 13518907013113787435, 13799188114963266222, 10949327997049617616, 12851874981220611149, 14245323937486085594, 18324803746062213911, 13224741762315864830, 15910543010675195930, - 10042008593756684008, 6713471518385846030, 10961845838926538977, 855334359173719954, 7598642325962297361, 18006511265377032901, 6844179774752820363, 248341098560552116, - }, - { - 9259451175701532574, 15597985540941612547, 4541553034987877619, 8927802479718285609, 14672230714928802576, 14284617950605306700, 13339970812390782046, 787078889494395850, - 18165439414433063919, 14693282888419586094, 14992616289789993230, 13232208150801553912, 16850347485914337693, 223364064845089224, 7302899015436300563, 4391216311540396088, - 12558388403188680537, 10687978569513354810, 9373570856564649772, 4079327722512691465, 5372437374337150740, 3297421622932790851, 9326853593823854687, 8305371884938201251, - 13121472331750731303, 323745485980480220, 15110308702528119977, 4696302365805118372, 9859094500834571602, 5315656270700787939, 4187063204400651801, 1695695129564818327, - 12817586844019849804, 15425488216915741929, 15293562913126043054, 11770898970765978555, 6806103820345670787, 17789094149138630459, 3807781571713999192, 5823254011289457198, - 10112524230916015604, 13571143908656270599, 6031089010487808103, 5774558171390644848, 1808959243244841573, 14071312530426692155, 9241399242704553402, 9836150050655369231, - 14083007972403535491, 16009534514129505275, 12481249112231139039, 10309390659262581143, 5782517315325366794, 16717384553294759530, 4578392002424884134, 239005024949492645, - 1836857790164349346, 11263074778654917115, 4786985732596838094, 10525445084936097674, 1484357665966453236, 3110871407036679558, 1668700683093601768, 2736269131339849752, - 9249362594190920246, 8088172462140746331, 4080107866285682736, 16205599538438551353, 18312943145606312277, 9100632964181080418, 3969991115337154345, 5340098959750368315, - 12122448407048035645, 2891250339380982359, 12794212052932523400, 7166035112141500392, 15777441312724841162, 4552528682229856831, 2210391301762911476, 16410254680957321386, - 6910044784455706429, 11951245774670922855, 207795885948948810, 3884359690300962405, 4578772752480772344, 2948797025787714138, 16774444535658202808, 1388183483009000463, - 16561979129019905420, 1881862411760441386, 15441950514711322010, 12933020223458438856, 5570341451312029630, 18172638959728259059, 9074261777549091198, 6171200053222754816, - 10126435102176037237, 1545112930055760251, 11563139991870561593, 10766754172364938834, 5116781688621052838, 14471715119500781375, 4724882615229687192, 10031687030722046325, - 15016829467434780812, 6777508689306592732, 3811682306063049290, 11475361222871876387, 6080948654298953274, 11612742274762615033, 5268311600240325047, 9147351973710519861, - 12130203770930472759, 3880998309361490881, 8807462332494735511, 9291388074337055133, 18165312304248982432, 12733144434841535979, 18090195697688236271, 5825342884125782172, - 13034385644450400616, 16498936039876211302, 13019014556329727588, 17911110193068084415, 2034190024798401134, 1526884555531436223, 8108814142164064795, 4075908755148182733, - 6404489603451030675, 16601749455344583377, 12907740667428956072, 8446383351289364752, 698035388979141580, 3593914367189873571, 6744392605914028800, 18168078953147292456, - 14484703498492722699, 6030798911934842161, 15931002029256202288, 13491601992324491240, 8585568434702372483, 9113555433818303018, 6375455514164501736, 1476639189214882947, - 5209683814158663472, 16895526973128357178, 10457488910391635027, 17530003042232440701, 4030542539553991812, 9445656287872984963, 4212489101708176016, 837886727556721620, - 2983790309644332360, 11276772732994425347, 1310621139116895737, 3131558545024164284, 3529698629777893989, 13271773334458143370, 8171825923423406479, 305718858162497191, - 12347543988562572522, 4315642616923374215, 17586477762860427847, 1037334149869395772, 18311071546005132724, 1489505092175764848, 8926409949339059078, 10260307609945070716, - 1253128470325829265, 917180526219408600, 10471425074479693158, 12658678264459355332, 8502334428811982364, 3789675096428271759, 4531393894096863308, 12176495757901795513, - 15081766794595471636, 3944913291385975654, 14507832069904091484, 3624606168811123851, 11476968507677098110, 1056328247986567681, 15246608002200052960, 6566558379177875405, - 652315099041528631, 4287214618428297946, 11730560225433863449, 7935915607867430686, 15979159466809939008, 9209839549459543141, 9501045239358734673, 15490773728258884277, - 14281001444503113096, 9253803478538227873, 3842669056581745692, 18399990656305827164, 11841387504710944221, 16052361836589007383, 831115622826254867, 8219898649601530197, - 2339128600785774471, 1426373723429876004, 3299581455481810683, 16966544600853047157, 8419320331267538738, 8376963013864643226, 1996128805959565963, 2376766970819731241, - 10963611841695254911, 2914831079289063424, 15884256460390936367, 8724520571578171796, 329402220949313078, 8905943304651682982, 1280899166177109409, 6980213851983339340, - 5524321102331478758, 2149164875175284006, 10897639484514200325, 14605181792035620644, 316829907946955098, 13776780818927038502, 18167912441745301047, 16845612593885106452, - 15817940025107036888, 14405005201957074368, 11647077937228007305, 13795438792777593442, 9813339145840642083, 13196196205982926907, 5981408724994946624, 12303812818084690125, - 11821409230485627325, 1934768678832528678, 15798397330147151183, 2089418311766868031, 16206123311846842647, 10276976147555604745, 14858750786699873336, 2500482310681473276, - 9502861285700748804, 12163827978530279544, 9383068907817479934, 5717811606328725851, 12416198015020836733, 15689586164720677894, 14337921697724349521, 9392403465642971279, - 6696074876763293236, 10302972695440286968, 16647054763285662245, 7841147641486000427, 10612636854719975349, 3592516733641215266, 14172459823963607855, 1290213042793222575, - }, -} +const p256Precomputed = "" + + + "\x3c\x14\xa9\x18\xd4\x30\xe7\x79" + "\x01\xb6\xed\x5f\xfc\x95\xba\x75" + "\x10\x25\x62\x77\x2b\x73\xfb\x79" + "\xc6\x55\x37\xa5\x76\x5f\x90\x18" + "\x0a\x56\x95\xce\x57\x53\xf2\xdd" + "\x5c\xe4\x19\xba\xe4\xb8\x4a\x8b" + "\x25\xf3\x21\xdd\x88\x86\xe8\xd2" + "\x85\x5d\x88\x25\x18\xff\x71\x85" + + "\x4d\xd6\xdd\x10\xd4\x46\x00\x85" + "\x7d\x82\x33\xa4\xc1\xe3\x6a\xaa" + "\xd9\x90\x14\x8d\x03\x05\x22\x73" + "\x3b\x3a\xcf\x3d\xe4\x32\xbb\xf6" + "\xa5\xe1\xbe\x61\xd3\x48\x36\x2f" + "\xf8\x6f\x23\xeb\xcb\xd7\x2c\x15" + "\xbe\x2d\x04\x92\x0e\xfb\xa8\x19" + "\x3b\x8a\x5b\x0a\x51\x77\xc5\x78" + + "\x27\xc1\xeb\x4e\x90\x3f\xac\xff" + "\xfb\x81\x7d\x08\x4a\xf8\x27\xb0" + "\x98\xbc\xcb\x87\xdd\x77\xad\x66" + "\x7e\x74\xff\xb6\x3f\x6a\x93\x26" + "\xeb\xa7\x83\xc9\x1f\x5c\x4c\xb0" + "\x1a\xfe\x61\x08\xad\x47\x3e\x58" + "\x8e\xe9\x2e\x1a\x31\x08\x82\x78" + "\x07\xcc\x87\xe5\x29\x6a\xf0\xd5" + + "\xcc\x8d\x91\x46\x0d\xb5\xb0\x74" + "\x73\xc1\x23\xc6\xed\xa6\x50\x46" + "\xf2\x0a\x10\xe8\xac\xac\xda\x0c" + "\x6b\x17\xb0\x41\xf5\x62\x73\x57" + "\xa6\xab\xcb\xe4\x4c\xf2\x96\x2d" + "\x47\xf4\xd6\xfa\x71\x84\x62\x17" + "\x2e\xd2\xdd\xe5\xde\x36\x6c\x6b" + "\x63\xb8\x5a\x4c\x39\x4c\xb1\x84" + + "\xf5\x61\x5c\xc4\xae\x8a\x1b\xbe" + "\x7d\x53\xb9\x94\x9a\x64\xec\x90" + "\x0c\xc2\x76\xd0\xaa\xb5\x1c\x94" + "\xc8\x23\x05\x89\x05\x96\x07\xc9" + "\x10\x4f\xba\xe7\x4a\x9b\x30\xeb" + "\x2b\x88\xeb\xe5\xef\x68\xc5\x73" + "\x68\x1f\x7a\x7e\x87\xa9\x40\x35" + "\x16\xe9\xd1\x2d\xbb\x76\xa0\x73" + + "\x4a\x66\x77\x3e\x37\x47\x39\x40" + "\x3e\xee\x6c\x34\x4f\x74\xae\x55" + "\xad\xa3\x17\x5b\x1a\x96\x0a\xd5" + "\x73\x36\x21\x54\x59\x4b\x07\x13" + "\x4b\xe4\x77\xd3\x20\x62\xd3\x93" + "\xb5\x14\xff\xad\x53\x2b\x9c\x29" + "\x11\x9f\x63\xef\x4c\xd4\x24\xf4" + "\x5f\xf7\x07\x4a\x6d\x91\xc9\xa4" + + "\x4f\x3b\x17\xa0\x4e\x35\x46\x07" + "\xf7\x00\x3c\xd2\x13\x02\xd2\x2b" + "\x08\xbb\x23\x0c\xb5\xaa\x3e\xf4" + "\x03\x3e\x12\xc3\x19\x51\xba\x13" + "\x4d\x9d\x5b\x3f\x30\xd0\x47\x28" + "\xdd\x7b\xa6\x5d\xf2\xf2\x42\x67" + "\x95\x41\xc9\x77\xdc\x3b\x93\xef" + "\x67\x08\x24\x6e\x15\xd9\xed\xea" + + "\x8f\xa7\x99\x94\xd1\x4c\xf1\x27" + "\x55\x34\x9b\x6f\xc5\xb5\x2a\x46" + "\x6b\xfc\x2c\xf0\x2a\xf0\x90\x8f" + "\x0d\x23\x65\xb2\x1e\x89\x63\xb7" + "\x77\x49\x2d\x53\xa9\xa3\x9d\xf5" + "\x15\xba\x9e\xcf\x7d\x32\xe3\x21" + "\xf0\xbb\x60\xbe\x84\x7b\x3c\x12" + "\x76\xdf\x06\x77\xf2\x12\xec\x56" + + "\xe8\x20\x4e\x26\x8f\x6e\xc9\x75" + "\x41\xa8\xa7\x59\xed\xbf\xe6\xab" + "\x00\xeb\xc8\x44\x04\x9c\xc0\x2c" + "\x6b\xe1\xc4\xf0\x80\x30\x5b\xe0" + "\x14\x33\x5f\xa4\x7a\x77\xb7\x1e" + "\xe3\x45\x5d\xce\xed\x7b\xaf\x56" + "\x1a\x2f\xb1\x88\x9a\x01\x6e\x2b" + "\x9b\x5f\x83\xfd\xcd\x59\x66\x08" + + "\xc8\x1e\xc2\x9d\xd1\xdb\x18\x2c" + "\x39\x81\xcf\x0f\x8a\x86\xf9\x98" + "\x49\x0b\x25\x48\xd6\x2c\x7d\x73" + "\x8f\x42\xb3\x24\x47\xc9\x61\xcc" + "\x76\x9e\xdd\x80\x78\x40\x2b\x0c" + "\x08\xbe\x3f\x38\x91\x89\x3a\xc4" + "\xd2\xe5\x9b\x77\x65\x2d\x7d\x5f" + "\xb5\x4a\x3b\xeb\x54\x9a\x71\x78" + + "\x04\xe4\x45\x62\x0a\x26\x7d\xea" + "\xe0\xdf\x7f\x6e\x95\x07\xe4\x9d" + "\xb5\x1a\xac\x8d\x15\xa4\xf3\x1f" + "\x73\x90\x9c\x64\xf1\x90\x70\x3e" + "\x88\x4e\x94\x2b\x61\x85\x76\x1a" + "\xc8\x61\x7f\xe5\x9e\x93\x0f\x25" + "\x3d\x64\xad\x1e\x89\xaa\x0d\x0c" + "\x8e\xb8\x25\xe1\x23\x00\x93\x68" + + "\x68\x77\x69\xd2\xa7\x1a\xb7\x04" + "\x33\x5a\x34\xca\xf5\xde\xde\xab" + "\x5e\x38\x37\xee\x9d\xd2\x09\x24" + "\x56\xe1\x83\xcb\x77\xdf\xe1\x4e" + "\x43\x5b\xbb\x1c\xd9\x12\xac\x0c" + "\x37\x56\x89\xca\xf6\xd2\x0e\x17" + "\x66\x6d\xde\x8a\xfa\x8c\x22\x28" + "\xca\x8a\x23\x53\x95\x7c\xf5\x7f" + + "\x09\xd7\x2e\x4b\x63\x25\xc4\xcc" + "\x0d\xd3\x6f\x85\x69\x67\x35\x0e" + "\x11\x98\x9e\x55\x3f\xd4\xbc\xbc" + "\x59\xb7\x95\x53\xac\x77\x84\x73" + "\x7f\xe1\x0e\xc0\x90\x2b\x75\x35" + "\xe3\xd2\x2e\x74\x90\x83\x74\x68" + "\xc1\x5b\x1f\xbd\x22\x64\xd0\x7c" + "\x97\xb7\xe7\xc9\x69\x87\xc0\xfb" + + "\x4a\x66\xcf\xb0\x5b\xa3\x42\xa2" + "\xe3\x07\x97\x7f\xf7\x48\x6e\x12" + "\x60\x26\x83\xc6\x54\xbf\x17\x17" + "\x2e\xc7\x12\xfd\x32\x73\xae\xfa" + "\x6b\x58\x5d\x99\xb7\x2d\xb5\x27" + "\xc2\x37\x22\x83\x9e\x56\x29\xbe" + "\xdb\xe7\x65\x2a\x3e\x19\xe4\xe8" + "\xbb\x1b\xaa\x2e\xdc\x06\x27\x15" + + "\x5b\x05\x60\xbc\xb7\xd8\xbc\x72" + "\x4b\x7e\xe2\x56\xee\x23\xcc\x03" + "\x70\x93\x81\xe4\x24\x74\x33\xee" + "\x09\xda\xd3\x0a\x43\x0e\xaa\xe2" + "\x5d\xc4\x83\x63\x4f\x52\xb8\x40" + "\x25\x1b\xa4\x42\x54\x35\x66\xd7" + "\x97\x47\x8a\x77\xde\xa6\xef\x64" + "\xf4\xad\x79\x70\x0a\x17\x42\x20" + + "\x80\xfb\xc6\x0b\x65\x0b\x8b\x80" + "\x6b\x2e\xfe\x3f\x75\xe0\x82\x58" + "\x49\xf5\x83\x2c\x7c\x2f\xef\xd5" + "\x23\xb7\x03\x91\x80\x3c\xd6\x54" + "\x9b\x3f\xa2\x52\xd6\x1b\xf1\xf2" + "\x87\x65\x0b\x4b\x19\xc3\x70\x36" + "\x9e\x0e\x58\xb1\x3b\x62\xc4\x55" + "\x20\xe2\xef\x01\xb2\xf7\xed\x64" + + "\x9d\x5c\x3c\xd5\xcb\x1d\x09\x97" + "\x7b\x17\x0a\xac\xb6\x24\x76\xf1" + "\xff\x2d\xfe\x2c\x75\x39\xf1\xb0" + "\x4e\x57\x7a\x6c\x0a\x5c\xa3\xc1" + "\x87\x99\xe7\x93\x46\x31\x7d\x22" + "\x0e\xb8\x9c\xe8\x30\xbf\x75\x05" + "\xbb\x83\x18\x0d\x7f\x24\x4e\x2f" + "\xd0\xc3\x74\x32\x26\x12\xd5\xeb" + + "\x7a\xa9\xad\x56\xc8\x51\x3e\x5f" + "\x3e\x40\x8b\x8f\x4d\x96\xfc\x4a" + "\x79\x29\x2e\x41\xab\x47\xf2\xa6" + "\xda\xeb\x80\x6f\x1b\xbd\x5a\x67" + "\x1d\x5a\x48\x5e\x72\xbd\xa2\x66" + "\x3c\x0b\x4f\x8f\xaf\x5c\x2a\x4b" + "\xba\x7b\x84\x1b\x7f\x92\x26\x26" + "\x4d\x39\x02\x05\xd9\xc7\x6f\x6c" + + "\xe8\x9a\x65\xa5\xba\x12\xa9\xfe" + "\x6e\xa1\xe1\x25\xba\x3a\x36\x68" + "\xac\x41\x2c\x75\x77\x22\x84\xb8" + "\xfc\xc3\x97\x28\x28\x5c\x54\xfe" + "\x6b\x69\x4c\xdc\xe7\xe9\x36\x2d" + "\xc5\x77\xa9\xfb\x4a\x24\x06\x58" + "\xc1\x08\x95\xe3\x9b\x5e\x66\x85" + "\x7b\x59\x12\x6d\x25\xee\x20\xf7" + + "\x31\x7a\x33\xd2\x29\x91\x97\x8a" + "\xdc\x2b\x86\x0f\x8f\x86\x16\x59" + "\xba\x83\xd2\x5d\xd9\x99\x80\x04" + "\x4e\xfb\x5b\xfe\xb6\xee\xd1\xe2" + "\x5d\x00\x84\x78\x41\x1c\xef\x82" + "\xae\xcb\xff\xff\x17\xec\xd4\xa2" + "\x66\x5e\xa9\x8a\x3f\xc5\x61\x91" + "\xd0\xe0\xfe\xc5\xe1\x04\xe1\x5e" + + "\x08\xb2\x35\xc1\xec\x4c\x2e\x56" + "\x7d\xf4\x83\x47\x65\xb2\xe1\x74" + "\x30\x3b\x3f\x5a\x6c\x50\x2a\x6d" + "\xfc\x62\x67\xc1\xf4\xd9\xea\xec" + "\xb9\xe5\x86\xe2\xb2\xd4\x9d\xf2" + "\x61\x3c\xbb\x83\xc0\xad\x0f\x1b" + "\xa4\x29\xac\x7f\x3e\x02\x75\x7a" + "\xa3\x7f\x47\xc9\xf1\xd5\x86\xc0" + + "\x76\x30\x6f\x2f\x35\x11\xc6\x0f" + "\x9a\x2a\x91\xe3\x23\xfa\x9f\xc9" + "\x3d\xba\xf8\xd2\x85\x06\x0b\x6a" + "\xa4\x58\x33\xe9\xe8\x77\xc7\xfd" + "\x04\x5f\x41\x35\xbb\x87\xa7\x94" + "\xa4\xfe\x23\x4d\x6a\x2d\x0c\x64" + "\xb5\x35\x3a\x15\xda\x17\xe9\x9d" + "\x74\xd0\x5c\x5d\x07\x8d\x3e\x79" + + "\x68\x50\xe4\x2d\x53\x76\xf8\xf4" + "\x6e\x1f\x2e\x9e\xe8\xa7\xc7\x37" + "\x69\x40\x58\xa3\xa2\x5f\x82\xd0" + "\x42\xbf\x27\x17\x7c\xea\x2c\xaf" + "\xa9\x85\x47\x9e\xfb\xa4\x60\x03" + "\x4a\x9f\x29\x27\x9c\xa4\xfd\xe5" + "\x71\x2f\xac\x71\x13\x8e\x06\x48" + "\x6f\x66\x77\x90\x7b\x68\xd0\x83" + + "\x19\x28\xd0\x15\xb2\x83\x38\x6d" + "\x35\x9a\xdd\x40\x50\x75\x0d\x6d" + "\x9f\x46\x2b\x1d\xf9\xcb\xd7\x61" + "\x15\x31\xfc\x2e\x2f\x23\x7b\xf9" + "\xc7\xcb\x4b\xb2\x50\xd7\x51\xa5" + "\x56\xe3\xa1\x88\x49\x49\xea\x11" + "\x01\x75\xcb\x93\x31\xf0\x69\x76" + "\x8a\x7b\x73\xca\x5e\xc5\x5d\x59" + + "\x9f\x87\x37\xd8\xac\x19\xa3\xa4" + "\xb0\x67\x6b\xed\x9e\xb4\xc1\x6f" + "\xaf\xf3\xf1\x32\x33\x99\x95\xe3" + "\x2e\x2a\x43\x65\xeb\x42\x67\x96" + "\x28\x62\x96\xb4\xfe\xc9\x8d\x4b" + "\x50\x39\xf4\x43\x12\x63\xcc\x96" + "\xee\x31\xb7\xc9\x59\x88\x06\x12" + "\x68\x99\xf7\x56\xc3\x8d\x94\x7b" + + "\x08\x80\x1f\xed\x32\xad\xe4\x61" + "\x38\x75\xb1\xd8\x7a\x26\xc9\xe6" + "\xfb\xf6\x7f\x85\xeb\xc5\xc7\x1a" + "\x10\xfb\xf2\x55\xa8\xaa\x4b\x99" + "\x18\x80\x24\x1d\xe1\x14\xcf\x84" + "\x08\xc5\x8a\x62\x8b\x89\x39\x5a" + "\xf5\x44\xa9\x5f\x7b\xe9\xfd\x14" + "\xc7\x5a\x2e\xd1\x30\x80\x17\xed" + + "\xb4\xfe\xe2\x97\xf4\x2a\x2c\x04" + "\x13\x73\xbf\xae\xd7\x42\x6a\xd3" + "\xd7\xfd\x4f\x08\xeb\xc9\xd2\x49" + "\x6a\xc7\xf7\x2e\x4b\xa5\x8a\x9f" + "\x70\x5e\x89\x09\xba\xb7\x00\x92" + "\x58\xfb\xb7\xdd\x6f\xc6\xd0\x3b" + "\xbb\x4c\xeb\x78\x08\xd1\x97\x2d" + "\x31\xde\x4b\xd8\x68\x10\x43\x2d" + + "\x1f\xcd\x2c\x17\xb7\x3e\x52\x4b" + "\x92\xa8\xa6\x30\x28\xcb\x23\x73" + "\xeb\x53\xe1\xcf\xc0\x2e\x08\x97" + "\x97\xdb\xaa\xf2\x6a\x6b\x7f\xe9" + "\xa1\x3d\xa8\xd1\x3e\x39\x3d\x1d" + "\x68\x2a\x4b\x80\xc7\xf9\xa7\xa6" + "\x1e\xb7\x0c\x2d\x48\x8b\x68\x4a" + "\x78\x52\x58\x40\x5f\xcc\xb4\xa9" + + "\x32\xe1\x66\xcb\x6a\xb4\x5d\x5e" + "\x80\x58\x92\x0d\x3a\x96\xbe\xf1" + "\xe2\xb9\x17\x03\x27\x70\x4a\x94" + "\x48\x3d\x60\x48\x59\xf9\x66\xe2" + "\x99\x88\x20\x5c\x73\x66\xdb\x98" + "\xa3\x18\xfb\xa2\x47\x24\x47\x90" + "\x9f\x61\x7c\x77\x39\x69\x96\x8a" + "\x1b\xe2\x3b\x2a\x2a\x14\x98\x37" + + "\x43\xb3\x98\x32\xb1\x1c\x24\xb4" + "\xa1\x65\x4f\xb4\x49\x4e\xa1\xa3" + "\xcd\x7a\xc7\x3a\xcd\xd6\xf4\xc5" + "\x3c\xfc\xb6\x52\xb5\x8c\x28\xd0" + "\xbc\x0a\x04\x1c\x2f\x8c\xcc\xd5" + "\x4a\x9b\xbf\x06\x1e\x51\x75\xb6" + "\x41\xa4\x3a\x9b\x37\xda\x67\xd6" + "\x72\x1f\x60\x51\xce\x45\x0d\x46" + + "\x89\xff\x55\x67\x69\x3c\xf7\xe2" + "\xe6\x17\x30\x47\xe7\xf7\x3c\xdd" + "\x0d\x60\xf7\x3c\x9d\x68\xf5\x8e" + "\xb4\x87\xfc\xb1\xf8\xc4\x8d\x94" + "\x99\x32\xa5\x4e\x81\xfe\xe9\xd9" + "\x28\x60\xeb\x98\xa2\x1c\x92\x2d" + "\xfc\x03\x98\x0c\xfd\xed\xec\xfa" + "\x45\x47\x7b\x4d\x91\xe8\x8a\xf3" + + "\xd8\xa3\xe3\xc5\xcf\xfc\xc5\xd8" + "\xbf\xdf\x79\x40\x4c\x90\xfd\xbe" + "\x97\x01\xad\xfe\x58\x6a\x6d\xbc" + "\xa4\x32\x55\x69\x77\x70\x22\x39" + "\xf5\x42\xef\xdb\x6d\x3e\xe2\x09" + "\x08\x99\x0a\x48\x64\x9b\x44\x7e" + "\x40\x2e\x9a\xad\x1a\x9c\x96\x7b" + "\xa4\xc2\x91\x95\x92\xd7\x31\x62" + + + "\x80\x8b\x96\x05\xf3\x96\x6d\xdb" + "\xb9\x73\x9f\x08\x13\x09\x0a\x38" + "\x01\x1e\xc6\xc2\x83\x0b\xa7\x7d" + "\xc7\x38\x9b\x56\x94\x83\xfb\x95" + "\x2f\xfe\xed\x80\x12\x65\x3c\x9a" + "\x82\xaf\xae\x8f\xb9\x6b\x72\x8f" + "\xf8\x4b\x42\x78\xa0\xa4\x10\x80" + "\x70\x49\x84\x0e\x44\x20\x67\x29" + + "\x2a\xd6\x2a\x7a\x81\xcb\xc5\x63" + "\x54\xff\x62\xac\xb9\xb6\xf2\x7e" + "\xb5\x9d\xad\xb3\xa4\xbb\x49\x37" + "\x17\xa6\xd5\x46\x2c\x1f\x31\xad" + "\x6d\x3b\xff\xc2\x87\x80\x7a\xb7" + "\xff\x34\x78\x36\xf3\xea\x6f\xb4" + "\x38\xb1\xd6\x75\x6d\x26\xaa\xf8" + "\x88\x81\x00\xec\x20\xd3\x38\xfa" + + "\xc6\x16\x69\x4e\xfc\xaf\xf2\xc0" + "\xda\x42\x18\x81\x57\x49\xb9\x6f" + "\x57\xd1\xb4\x24\xb6\xbc\x34\x60" + "\x90\xfb\x2e\x99\xc7\xfd\x2e\xde" + "\x87\x3c\x79\xac\xce\x7e\x6f\xd6" + "\xcd\xfd\xc6\x7d\x26\x26\xf0\x02" + "\x01\xc5\xa1\x9a\x5c\x23\xd3\x90" + "\xf0\x66\x46\x2b\x96\x94\xe4\xf6" + + "\xfc\x46\x69\x69\xfa\x8f\x6d\x48" + "\x6d\xa5\xcb\xb9\xd8\xc6\xfb\x50" + "\x15\x5a\xf3\x90\x3e\x42\x3d\x7e" + "\x2c\x96\xdd\xc0\x95\xa1\x3d\x7c" + "\x8b\x5d\xfd\x3c\xb0\xfd\x73\xe6" + "\xa5\xfc\x9d\x88\xc2\xb7\x04\x07" + "\xaa\x05\x23\xf5\x1f\x58\xce\xf6" + "\x53\x5e\x4d\x91\xeb\x49\x9d\x39" + + "\x53\xd4\x92\x7b\x36\x7c\xc9\x24" + "\xc0\x26\x9a\x24\xa2\x71\xc2\xd2" + "\x39\x4a\xd1\x89\x2b\x4b\xeb\x60" + "\x05\x80\x2e\x43\x20\xde\x98\x11" + "\xd9\x80\x9b\x79\x75\xea\xab\x9e" + "\xe5\x6a\x82\x8f\x2b\x0c\x6e\xab" + "\xec\x61\x00\xd1\xed\x4e\x00\xca" + "\xd8\x4f\x9c\xe9\x39\xf4\xa9\x31" + + "\xcd\x93\xc2\x6e\x6d\x49\x0a\x38" + "\xf5\x51\x70\x8e\xa7\xbd\x3d\x73" + "\x0a\x14\x49\xb8\x8d\x38\x7e\x03" + "\xf6\xdb\x46\x59\xb0\x32\x4b\xee" + "\xd1\x68\xe3\xca\xa9\xfd\xc4\xb1" + "\xf3\xb2\xb0\xfd\xb0\xa7\x01\x50" + "\x6e\xc4\x3a\x2e\x74\x93\xf5\x6d" + "\x56\xe6\xb3\x39\xf2\x75\xf6\x4a" + + "\xeb\x26\x78\xd6\x44\x7c\x0e\xb2" + "\x37\x96\x37\xac\xcf\xd3\x12\x12" + "\x5d\x3a\xe0\x7d\x87\x67\x4f\x61" + "\x26\xaa\x2b\x80\xfc\xa2\x38\x75" + "\x15\x24\x25\x9d\xa1\x37\x3c\x13" + "\x87\xb5\xb4\x6e\x50\x90\xb3\x7d" + "\xd9\xd1\x49\x4c\x57\xd7\x40\x5d" + "\xba\xc4\x01\xa8\x99\x6b\x12\xf1" + + "\x96\x92\x94\x39\x10\x81\xe3\x44" + "\xb5\xb1\x1d\x36\x7b\x82\x63\x5b" + "\xf5\xaf\x6e\x20\xed\x23\x53\x3e" + "\x90\x42\x1f\xc2\xd2\x70\x23\x94" + "\xa1\x85\xd9\xe0\x2e\xaf\xca\xf2" + "\x6d\x84\x39\x72\x4b\xc6\x2c\x19" + "\xf8\x12\x63\xae\x47\x8f\x0b\x7c" + "\x08\x01\x62\x96\x91\x1f\xc6\x7d" + + "\x47\x11\x96\x70\x96\xc9\xff\x40" + "\x8c\x2c\xc2\xc7\x42\x68\xe0\x79" + "\xbd\xbb\x97\x1a\xcc\xab\xf1\x63" + "\x88\x03\x73\xf0\xd0\x74\xea\xe9" + "\x66\xff\xef\xd9\x4d\x50\xc3\xa6" + "\x15\x20\xe0\x57\x38\xee\x54\x53" + "\xfa\x40\x70\x6d\xfe\xd7\xfe\x3b" + "\xac\x82\xca\x99\xcc\x95\x2c\x69" + + "\xe9\x7d\xda\xc2\x5b\xfb\x30\xb8" + "\xbe\xd3\xf8\x0f\xdf\x43\xe6\xd0" + "\x41\x96\x8a\x18\xba\x77\xee\x31" + "\x02\xd5\xf6\xbc\xaa\xa3\x8a\x4e" + "\x0f\x11\x49\x9a\x32\x65\xfb\xf9" + "\x20\xb2\xd6\x2d\xf6\x17\x83\xd1" + "\x5a\xea\xc3\x52\x41\xed\x3c\x7e" + "\x4a\x9c\x57\x7d\x14\x6a\x29\x0d" + + "\x58\x6c\x2f\x94\xca\x5a\x8b\x68" + "\x39\x94\x5d\x49\xc5\x89\x27\x6f" + "\x1d\x50\x4c\x50\x0c\xdb\x4d\xd5" + "\xa7\xe3\xac\xbc\x0f\x4d\x6a\xf1" + "\xeb\x41\x6a\x05\x6f\xbc\x6f\xb7" + "\xc5\xd6\x5b\x82\x55\xc2\x88\xe2" + "\xd3\xe2\x42\x0f\x96\x77\x03\x95" + "\x44\x7b\xb5\xde\xe3\x47\x3c\x9a" + + "\x17\x37\x4c\xed\x3e\xa5\xd6\x35" + "\xa3\xd2\x0e\x3d\xcf\x40\x82\x9f" + "\xa5\x3a\x54\xe5\x05\x4d\x0d\x8c" + "\xb4\xb4\x33\xdd\xfb\xbb\xd5\x45" + "\x8e\xd2\x7f\x13\x73\xcc\x04\xfa" + "\xfd\x3f\x3b\xc7\xef\xc6\x2a\x86" + "\xf2\x1e\xf5\x31\xf5\xf9\x3f\x40" + "\xa2\xf5\x73\xbc\xfc\xe0\xd5\x34" + + "\xb0\xfa\x59\x95\x21\xef\x9a\x2c" + "\x2d\x2f\x32\x62\xce\x61\x33\x83" + "\xf9\x0d\xba\x72\x2b\x5e\xfd\xd3" + "\x0a\x8c\x2d\x9d\x32\xe7\x85\xfc" + "\xd4\xb8\x5d\xf1\x75\x46\x23\xce" + "\x9a\x3f\x2d\xf5\x2e\xac\xf7\x6a" + "\x92\x65\xbf\x3d\x69\xf1\x55\x2d" + "\x38\x8e\x09\xd7\x6c\xcc\xc9\xb1" + + "\x4f\x3f\x91\x08\x20\x68\x52\xf2" + "\x95\x3d\xc9\xea\x61\xed\x20\xea" + "\x6c\xb2\xa6\x6c\xb4\x38\xed\x51" + "\xb0\x27\x43\xea\xbc\xdc\x62\x86" + "\xaa\x2a\x5d\x72\x5c\x29\xaf\x6d" + "\xda\xdc\x52\x8e\x2f\x75\xd2\xba" + "\xcc\xda\x17\x0b\x21\xe7\x10\x22" + "\x32\x82\x1e\xd5\x12\x79\x7f\xa3" + + "\xeb\xca\x40\xd5\x0c\x16\x00\x2a" + "\x88\x27\x1a\xa4\x5e\x14\x66\x6f" + "\xfa\x11\xc8\x51\x33\x1c\xc8\xf9" + "\x03\x54\x6f\x64\x0f\x8e\xe5\xee" + "\xe3\xfa\x18\xfc\xef\x20\xf9\x8d" + "\x6c\xea\x71\x09\x5e\x42\x23\x79" + "\xa7\xae\xa0\xcb\xb2\xdc\xe3\xe0" + "\xfc\x2d\x85\x4a\x5e\xaf\x1d\xbf" + + "\xdd\x3a\xcc\x44\xe1\x81\x70\x4f" + "\xcf\x82\xbe\x87\xd6\xa1\xff\xd5" + "\x72\x64\xdd\x0e\x6c\x0b\x89\x89" + "\x63\x78\xd1\x3e\x1a\x6e\xa2\xad" + "\xaa\x3c\x48\x63\x15\x27\x6f\x27" + "\xfd\x77\x60\x2f\xd9\x4c\x92\xe6" + "\x3c\x6e\x46\x0a\x98\xfe\xa7\x05" + "\x1f\x2d\x90\xb1\xb0\x94\xc7\xf1" + + "\x1c\x9c\xf0\xaa\x57\x63\x06\xee" + "\xd2\x76\x27\xab\x8d\x87\x53\x1c" + "\x4a\x32\x4e\xae\x4c\x72\xb5\x2c" + "\x52\x83\xfe\xe0\xad\x7c\x30\x13" + "\x96\x56\x39\x54\x78\xbb\x02\xef" + "\x31\x4d\xb6\xb3\xf3\x2d\x59\x2c" + "\xeb\x6a\x8b\xbc\x1a\x95\x05\xf0" + "\x5e\x27\x91\x6b\x82\xbe\x60\x57" + + "\x2c\x04\xa8\x82\x88\x36\x21\xe5" + "\x98\x82\x27\xcd\xaf\xcf\x31\xd9" + "\x40\xa7\x97\xf5\xe0\x0a\x9a\x06" + "\x7c\x10\x59\xeb\xf3\xb3\xdb\x0a" + "\xb8\x8e\xaa\x5e\x1e\x95\x3e\x98" + "\x78\x8e\xb4\x11\xb5\xa8\x63\xe6" + "\xc5\xf2\x03\x8a\x0d\xcc\x31\x16" + "\xe2\x71\xe2\x11\x1e\xc1\x77\x75" + + "\xf6\x8f\xa0\x74\x41\xbf\x5d\x08" + "\x0b\x46\x76\xa5\x40\xce\xba\x80" + "\x49\xba\xc1\x27\xcf\xcb\x04\xd2" + "\x49\x69\x80\xe4\x32\x2f\xd1\x64" + "\xe3\xe8\xdf\x01\x22\x22\xd4\xcd" + "\xd4\x83\x5c\xd0\x6e\x3c\x5b\x3b" + "\xc0\x00\xeb\xfc\xb3\x81\xc0\xb2" + "\x69\xd7\x67\xdd\xec\x3e\xc2\xe2" + + "\x90\x9a\x36\x08\x5c\x38\xb2\x33" + "\xf8\xb4\x0e\x19\x9b\xc5\x90\x29" + "\x80\xac\x8e\xc6\x45\x61\x9a\x81" + "\x14\xa0\xc4\x2e\x62\x6d\x78\x7a" + "\x8d\x3a\xac\x20\xbe\xad\xfa\x33" + "\x30\x2d\xba\x5a\x81\x17\xa2\x31" + "\x65\xf5\xa4\xdb\x42\x27\x9d\x20" + "\xbb\x0f\xaa\x55\xe3\xe9\x2c\xdb" + + "\xad\xe1\xcc\x63\xb5\x24\x4f\x6f" + "\x77\x3a\xb4\x9f\x2a\x67\x66\x51" + "\x1f\x9d\xc7\x4f\x78\x40\x78\xbb" + "\xf5\xbb\x74\xf7\x6c\x1a\x82\xb3" + "\x41\xf4\x02\xdf\xce\xd4\x7b\xa2" + "\xdf\x2a\x4e\xb8\xb9\x4e\xfa\xc5" + "\xde\xcd\xb7\xf0\xd7\xcb\x0b\x91" + "\xec\x1e\x5a\x2e\x48\x40\xe6\xb7" + + "\xdf\x84\x89\x16\x4b\x33\xef\x8c" + "\x38\x96\x87\x33\x17\xce\x1d\xe8" + "\xf0\x20\x37\x26\x9c\x94\xe6\xf6" + "\xec\xcb\x93\xf5\xaf\xfe\x56\x5c" + "\x84\x8c\xe5\xfd\x01\x56\xff\x8b" + "\x14\xb3\xcc\x2e\x17\x41\xe2\x74" + "\x78\x8a\x9a\x4c\x61\x1b\xf0\xbc" + "\x68\x98\x4c\x54\x5e\xe3\x33\xa2" + + "\xfb\xd8\x65\xc7\xc9\x4b\x93\x54" + "\x1e\x75\x0b\xb3\x71\x65\x96\xc1" + "\x17\xc8\xa7\x91\xcf\x2f\xfd\xc4" + "\x88\xc8\xb1\xdc\x7e\xbc\x6f\x24" + "\xff\x1b\xcc\x59\xfd\x4f\x30\x27" + "\x11\x58\x9c\xe5\x8d\x4d\x5c\xc3" + "\x21\x99\x1f\x40\xb9\xff\x63\xd8" + "\x61\x69\x80\x2e\x2e\x48\x14\x5b" + + "\xf1\xaf\xd7\x8b\xf3\x6b\x15\xb3" + "\x46\xb1\x81\x1d\xcb\xe4\x5e\x1b" + "\x15\xa9\x28\xd6\x41\xac\xa1\x7b" + "\x9e\x69\x89\xfd\x9c\x8f\x3a\x8f" + "\xe7\x8b\x74\xa0\xc9\xb9\x29\x73" + "\x1f\x62\x2e\xa9\x95\x1c\x39\x1d" + "\x37\xa8\x10\x4d\x21\x6b\x1e\xe5" + "\x35\xb4\x47\x49\x3a\xf5\x55\xd2" + + "\x2b\x88\x20\x1f\x5a\x04\x37\xc1" + "\x0c\x05\x7a\x9b\xf4\x16\x4b\x92" + "\xaf\x94\x66\xea\xf5\x26\xba\x8a" + "\x3e\x6a\x82\x69\x54\x28\x06\x29" + "\x27\x16\x8c\xb0\xcb\xd1\xf6\x2e" + "\x34\x0c\x8c\xc5\x84\x38\x31\x61" + "\xb4\xf1\xf6\xd8\x99\xc2\xc7\xa5" + "\x87\x9f\x3e\xff\xc0\xae\x5a\xcd" + + "\xe3\x8e\x78\xf1\x04\x9e\x66\x07" + "\xa2\x38\x69\xa8\xaf\x27\x4f\xc1" + "\xc0\x01\x3a\xe9\x34\xa3\x47\x8b" + "\x08\x68\x36\xd9\x38\x74\x62\xff" + "\x65\x59\x2a\xca\xd8\x85\x09\x7a" + "\xb3\xb9\xe9\xd6\x42\x55\x9a\x3d" + "\xe8\x72\xf9\x4c\x0b\xb8\x3e\xc2" + "\xfd\x72\xdf\x4f\xbb\x33\x1c\x5c" + + "\x5a\xd4\xb3\x4c\xdd\xbd\xca\x3b" + "\xa1\x67\x7d\x41\x6b\x4d\x38\xa9" + "\x54\xfa\xa8\x6a\xba\x5b\x9f\x65" + "\xcb\xf0\x0e\xcd\x21\x76\x93\x04" + "\x47\x23\x8b\x51\xf5\xb2\x80\xd4" + "\x80\x87\xe3\x1f\x1e\x97\x3c\x15" + "\x38\xb5\x07\xfe\xed\x08\x71\x15" + "\x29\x01\x11\xab\x03\x80\x0d\xca" + + "\x08\x61\xa8\x74\xd4\x58\x4a\x0c" + "\x90\x5d\x4c\xee\x8f\x8a\x04\xf8" + "\x80\x4c\x6d\xe8\x24\xc9\xc7\xe3" + "\x60\x1e\x6a\x05\xde\x89\xc8\x28" + "\x40\xa0\x14\xb2\x2e\x66\xe2\x57" + "\x47\x03\xe1\x37\x98\x8e\xc4\xe8" + "\x8a\x74\xac\x80\x62\x28\x74\x87" + "\xf2\x06\x6b\x18\x22\x40\xc2\xf1" + + "\xd7\x51\x4e\x09\x76\x33\xbb\xd0" + "\x7a\x87\xcd\x42\x22\xcc\x10\x51" + "\xc6\x97\xd1\xcf\x29\x57\xd6\x7b" + "\x71\x31\xca\x8a\x05\x94\x29\xf2" + "\xa5\xae\x55\x21\x15\x75\x84\x07" + "\x54\x1a\x82\x9a\x48\x2d\xf1\x84" + "\x5c\xaf\x37\x37\xf9\xc1\x8c\xb1" + "\x45\x58\x48\xba\xe2\x0c\xba\x4f" + + "\x0a\x04\x74\x5f\xc3\xd4\x2d\xac" + "\x57\xc9\xea\xfc\x71\xeb\x9a\x40" + "\x23\xec\xc4\x55\x82\xd7\xba\x4f" + "\xec\x76\x7b\x8a\x61\xed\x59\xb3" + "\x60\x4a\x6f\xed\x26\x49\x74\x12" + "\xe3\x2d\x91\x4b\x7f\x8d\x1e\xe2" + "\x59\x5a\x70\xfc\x59\x5a\x57\xe2" + "\x0e\xbc\x2d\xed\xde\xd4\xf1\x72" + + "\xd2\x72\x97\xb9\x5a\xd8\x79\x96" + "\x25\x1c\xcd\xdd\x7c\x71\x69\x82" + "\x77\xc3\xdc\xeb\x45\x20\x97\x50" + "\xdf\xc9\xe2\x6e\x83\xde\x13\xed" + "\x7a\x21\xa7\x50\x04\xf5\x39\x9f" + "\xb6\x07\xe0\xae\x41\xa9\x3b\xd3" + "\x9a\xec\x2b\xfc\x90\x71\x4f\x91" + "\x87\x24\xd9\xb0\x4e\x25\xd2\x70" + + "\xb8\x26\x79\xeb\xb9\x24\x2b\x3d" + "\x09\x55\xbe\xcd\xb3\x8c\xf8\xbf" + "\x0b\x64\xdd\xe4\xaf\x99\xf3\xd0" + "\x45\xed\x76\x2f\x30\xe1\x5f\x3c" + "\x3d\xfb\x64\x37\xf4\x62\x35\x6f" + "\x2d\xb6\x51\x31\x18\xf3\x5a\x7b" + "\xf3\xe5\x9c\xd7\xc7\x0b\xbd\xd5" + "\x0f\x89\x66\xec\x20\x6b\xaf\xfd" + + + "\xa2\x35\x4b\xab\xe5\xb0\x72\x67" + "\xcf\xaa\xee\xf5\x01\x60\x8b\x1d" + "\x80\x95\x5b\x79\xe4\x7c\x8f\x72" + "\xda\x81\xfb\x41\x2a\xed\x20\x4a" + "\xe6\x01\xec\x4f\xd4\x5c\x68\x9f" + "\xad\x50\xff\xa7\xcc\xdd\xd7\x3e" + "\xfd\x97\x2d\x0c\x64\xd2\x0f\x46" + "\xf9\xf4\x82\xeb\x26\x14\x24\x3a" + + "\xd5\x21\xd7\xd5\x62\x98\x00\x80" + "\x82\xa1\xd3\x5b\xa3\x57\x33\x0c" + "\xa4\xcd\xa2\x7a\x3b\xa8\xf3\x27" + "\x85\x30\xf8\xf6\x4e\xe7\x8a\xb5" + "\x6b\xad\x6d\x2e\x81\x1a\x91\x2a" + "\x5b\x6c\x3d\xf4\x51\x60\x28\xde" + "\xd8\xc4\x96\xf9\x41\xcc\xdc\x4b" + "\x4e\xe2\xe1\x0a\xc0\x2e\x31\xe7" + + "\x70\xee\xe6\xaa\xfe\x68\xaf\x6f" + "\xc9\xb0\x02\x56\x15\xcc\xf4\x78" + "\x2a\x05\x94\x6e\xa8\x21\x33\x7e" + "\x80\x5d\x4d\x73\xd6\xa0\xb3\x2f" + "\xba\x43\x5a\xb2\x3b\x8f\xb9\xf3" + "\x51\x29\xee\x19\x31\x80\xbf\x30" + "\x2a\x61\xb0\x21\x33\xe4\xfe\x7f" + "\xd0\x21\xb8\x2e\xe4\x75\xf7\x12" + + "\xb3\x85\x64\x6e\xe7\x12\xd1\xf8" + "\xf8\x52\x1c\x77\xdb\x24\x3e\x4d" + "\x6d\x2f\x4a\x68\x41\xee\xe3\x48" + "\x51\x55\xd9\x21\x7d\x95\x61\x71" + "\x6c\x2a\xb1\xcd\x83\x12\x63\x19" + "\x64\xe1\x50\x2e\x82\xa8\x3f\xbf" + "\x73\xcc\x66\x31\x63\x4b\x25\xf6" + "\x38\xcc\xe8\xae\xae\xa7\xef\x3a" + + "\xa9\x29\xa9\x37\x80\x00\xf7\x46" + "\xbd\xc6\xfe\x19\x8e\x1a\x60\x65" + "\x62\x8b\xab\x12\xdc\x5e\x7f\x53" + "\xcf\x90\x59\x5e\x95\xcd\x97\xe4" + "\xf9\xb2\xa5\x9a\x7f\x38\xcd\x2f" + "\xe8\x8f\xb7\x67\xff\xa3\xfa\xe5" + "\x30\x5e\x5d\x29\x8d\x53\xcf\x1b" + "\xec\xa7\x13\xa8\x39\x32\x57\x3a" + + "\x09\x24\x7c\xd1\x6b\x28\xf5\xe9" + "\x9b\x4d\x26\x63\x93\x47\x4e\x2c" + "\x0f\x88\xf6\x17\xb1\x42\x70\x17" + "\x43\xee\xe1\x4c\xc8\xe2\xb7\x39" + "\xa9\xf4\x96\xd0\x22\xe7\xc8\xce" + "\x97\xe6\xd5\xbe\xcb\xae\x61\x68" + "\x11\x19\x23\x6c\xf0\x53\xd1\xc2" + "\x7a\x53\x90\x28\xb8\x42\x2f\xcc" + + "\xb4\x17\xa9\xd0\x51\xcb\xe2\x33" + "\x31\xf9\x99\x48\xf3\xa3\xcf\xc2" + "\xb6\xf6\xa2\xe9\x4b\x4f\xc9\xb2" + "\xb7\x62\xa1\x7c\x81\xb1\x07\x97" + "\x0d\xb1\xf8\xd5\x72\xa1\x02\xb6" + "\x2a\x54\xd4\x4f\x35\x78\x30\xfd" + "\x92\x69\x99\xdd\xdd\x26\xf2\xee" + "\xe1\x15\x0a\xeb\x89\xa9\x1f\x22" + + "\xfd\xf9\x36\x3b\x62\xfe\xb0\x79" + "\xc0\x9f\xe1\xfd\x23\x3b\x54\x26" + "\xef\x82\x84\x95\xa0\x64\x6e\x13" + "\x25\x58\x09\x9b\x71\x37\xf6\x23" + "\x2e\x14\xa1\xb6\x96\xd5\xcf\x14" + "\x0b\xac\x5a\x33\xc6\xaa\xa6\x5e" + "\xd5\x1d\x08\xf3\xbd\xe8\xa0\x86" + "\x2a\xc1\x3d\x00\x79\x9d\xb8\x5f" + + "\xa3\x32\x11\xde\x77\x86\x62\x73" + "\x47\x88\xa8\x2f\x64\x7e\x12\x75" + "\x60\xe6\x49\x5b\x30\x7a\x2f\x19" + "\xa9\x6a\x43\x11\xfe\x3c\x06\x1a" + "\x89\x01\x71\x4b\x57\x14\x00\x72" + "\x8d\x37\x57\x2a\xde\x46\xa9\xfa" + "\x66\x30\x1c\x19\x63\x5c\x49\x5c" + "\xdb\xb4\x7d\x6b\x65\x7e\x4b\x2b" + + "\x13\x04\x63\xd0\x7a\xd2\xe3\xa4" + "\xeb\x56\xfa\x19\x82\xe3\x70\x57" + "\x66\x06\x4c\x75\x7a\xcf\x65\x44" + "\xf3\xc5\x69\x61\xd2\x61\x91\xfe" + "\x48\xe3\x0e\xdc\x22\x27\xf6\x5d" + "\x54\x04\x89\x29\x6a\x59\xc6\x9c" + "\x2a\x32\x5d\x9f\x18\xd6\x43\xf0" + "\xe9\xe3\x1e\x18\x7a\x95\xce\xb4" + + "\xed\x62\x5c\xfe\x49\x0a\x19\x08" + "\x3d\x18\x91\x36\x3d\x54\x57\x2c" + "\x23\x48\x04\xa9\x8b\x31\xee\x75" + "\x58\x8f\xf2\xae\x9e\xe0\x0c\xd2" + "\x66\x4a\x8a\x84\x50\x3d\x61\x10" + "\xfb\x2e\xcf\x9f\xa8\xa1\x98\x4b" + "\x27\x64\xfc\x98\xd9\x1e\x5f\x41" + "\x50\x2b\x85\xe3\x56\xbb\x6a\x08" + + "\xd4\x34\x2e\xf7\x3a\xc3\x15\xf6" + "\x35\xec\x0e\x11\x40\xea\xd9\x0b" + "\x4e\xa3\xde\xc1\x5b\xbc\x12\x1c" + "\x99\x46\xae\x49\xc9\x84\x65\x68" + "\x42\xb9\x97\x8c\xd3\x95\xad\x13" + "\x62\x75\x5c\x4e\x1a\x56\x09\x46" + "\x89\x7f\x73\xf2\xae\xa4\x94\x9e" + "\xb6\x78\x1c\x37\xc6\x94\x75\xf5" + + "\xde\xa9\xed\x19\xd9\x8c\x76\x5a" + "\xd2\x51\x2a\x8e\xf4\x06\x32\x6e" + "\xef\xa3\x78\x86\xc0\xe8\x56\xd3" + "\xc9\x91\x3f\x54\x6d\xd3\xf8\x93" + "\x43\x67\x08\xa4\xf4\x31\xf2\xfe" + "\xc9\xc6\x48\x91\x11\x9a\x37\x4d" + "\xce\x32\x82\xdc\x1d\x58\xb5\x00" + "\x4b\x21\x02\xd7\xef\x72\x7a\xa6" + + "\x92\xe8\xb4\x17\xf6\xa9\x45\x61" + "\xf1\x9f\x22\x5f\x27\x02\x64\xfe" + "\xa3\x6b\x04\xdc\xa8\x3e\xb0\x6d" + "\xcc\xda\x51\x03\xd6\x73\xc8\x71" + "\x5b\x7b\x94\xc2\x37\xe3\xae\x4b" + "\x80\x43\x8b\xb0\xc7\x85\x08\x90" + "\xb9\x79\x45\xc8\x61\xa6\x1e\x1f" + "\x18\x78\x01\xa5\x93\xbb\xdd\xcc" + + "\x80\xb4\x9f\xcf\x3d\x88\x4d\x55" + "\x4d\x9a\xfb\x0d\xc5\x71\xca\x76" + "\xea\x40\x42\xe0\x2b\x14\x51\xc2" + "\x99\xfc\x7a\xfa\x3d\xa6\x9b\x89" + "\xa3\xcd\xbb\x9f\x12\x5b\x94\xed" + "\xcc\xa4\x99\xa2\x28\xd5\x4d\x3c" + "\x92\xc0\x63\x8a\x09\xb6\xe8\x68" + "\x1b\x62\x40\x3f\x6c\x0a\xf5\xec" + + "\xe3\x9e\x77\xe3\xfc\x65\x01\x0f" + "\x9e\x5d\x49\xbd\x9d\x7f\x0e\xe0" + "\x7a\x4e\x28\x20\xa2\xef\xa4\x1f" + "\x19\x62\xac\x47\xde\xba\x64\x45" + "\x8e\x8e\x70\xc4\x2a\x31\xe6\x90" + "\xdf\x9a\x1e\xa7\xfb\x25\x57\x4f" + "\x9f\x4b\x68\x3d\xae\x55\x5f\xe9" + "\x15\xb4\x94\x1e\xb1\xcc\xf7\x47" + + "\x01\xc2\xad\xa8\xbe\x48\xfd\x50" + "\xa8\x06\xdf\x40\x00\x18\x18\xce" + "\x22\xce\x82\xde\x42\xca\x07\x6c" + "\x1a\x76\x24\x5a\x51\x6c\x64\x23" + "\x2f\x39\x68\xb2\xf8\x91\xcf\x46" + "\x86\x14\x81\x81\xff\x57\xb7\xe4" + "\xa0\x02\x61\xd2\x0b\x57\xdd\x94" + "\x80\xdf\x65\x3e\x2d\x4d\xc3\x2d" + + "\xd3\x56\xde\x56\x44\xaf\xfe\x18" + "\x22\x79\x02\x61\xe8\x68\x95\xb3" + "\xdc\x58\xa4\x28\x5c\x68\xb8\xa2" + "\x17\xa8\x95\x62\x6c\xbf\xa8\x41" + "\xdc\xd1\x98\xca\x74\x40\x29\x7b" + "\xbe\x13\xe0\xb3\x59\x82\xc4\x94" + "\x56\x52\x4f\x2c\x24\xd5\x2e\xb4" + "\xec\x9f\x7c\xda\x50\x89\x8e\x30" + + "\x1d\x54\x6c\x31\x83\x70\x02\x46" + "\xcc\xab\x9e\xd3\x6b\xbc\x05\x7f" + "\xdc\x0c\xc2\x60\xa1\xfa\x37\xb8" + "\x06\x9d\xd3\xac\x1a\xf3\x8b\x4f" + "\x51\x20\x51\x00\x95\xdc\x31\x83" + "\xac\xa2\x2a\xaf\x62\xf4\x74\x53" + "\xa3\xb1\x2a\xf3\xb4\xd9\x73\x76" + "\xfc\x49\x4f\xd6\xac\x51\xe1\xa6" + + "\x81\x65\x94\x8d\x1b\x85\x22\x73" + "\x12\xa0\xf4\xbd\x33\x31\xd1\xf0" + "\xe0\xda\x84\x65\x69\x0f\x51\xa3" + "\x6d\x6c\x9f\x3c\x71\xc1\xa7\x03" + "\x1a\x38\x75\xe4\x38\x7f\xe9\x5b" + "\x34\x33\x82\x85\x22\xa4\x1b\xca" + "\xda\x7d\xe1\x0b\xc7\xc5\x3c\xf8" + "\x0f\x8c\x91\x0b\x94\x14\x8b\x15" + + "\x05\xf7\xa5\xdb\x88\x8a\x18\xb7" + "\x8b\xd8\xfa\xa1\xa6\xfc\xfe\x5c" + "\x95\x85\x8e\x33\x04\x88\x2d\xed" + "\x81\x09\xb4\x7e\xf8\x0b\x23\xc0" + "\xc7\xf7\x87\x4b\x78\xf1\xd1\x3e" + "\x2a\xd0\x9e\x7f\x76\x60\x1d\x9d" + "\x5b\x8d\x3f\xf2\x8b\x26\x90\x22" + "\xb9\x68\xd3\x86\x35\x4c\x90\xad" + + "\x82\xd6\xfb\x2a\x05\x96\x64\xdc" + "\xb1\xb0\x37\x16\x13\xfb\x08\xac" + "\x9d\xf3\x84\xa1\x88\xd4\x9f\xdf" + "\xb2\x25\xe3\xac\x23\xbc\xc2\x1f" + "\x84\x9a\x6c\xbd\x36\x3b\x87\x29" + "\x9d\x52\xf8\x3c\x15\x11\x2c\x46" + "\x2d\x21\x55\xc5\x0d\x37\xe0\xb3" + "\xc6\xec\xaa\x89\x75\x3f\xf8\x31" + + "\x99\x5a\xde\xb7\x31\x74\xdf\xb1" + "\x3c\x87\x95\xf2\xe6\x8e\x52\xfb" + "\x95\x3c\x30\xcc\x0f\x50\xa1\xec" + "\x60\xb7\x33\xce\x97\x05\x39\xdb" + "\x36\x97\x76\xe4\x86\x14\x96\xd6" + "\xa2\x9d\x33\xc3\x28\xe4\x45\xd2" + "\xce\x6c\x10\xfa\x41\x7f\xca\xf5" + "\xdd\xac\x80\x70\x32\xb1\xed\x37" + + "\x69\x6b\x2e\x52\xe5\x77\x3a\xda" + "\x18\x6c\xcd\xbb\xc3\x08\xc9\x69" + "\x56\xfd\x24\xd9\x48\x9e\x1b\x1f" + "\xf7\xb3\x4b\xaa\x36\x4e\xc6\x37" + "\x7d\x8d\x47\xee\xdf\xdb\x4f\x5a" + "\xa0\xf7\x93\x01\xbc\xc8\x75\xba" + "\xdf\x16\xcd\x56\x84\x1e\xbc\x84" + "\x51\xd1\xfa\x46\x08\x8f\xb0\x1f" + + "\x36\xbb\x6b\xb2\xef\x01\x33\x29" + "\xfa\x4d\x64\xa9\xf8\xca\x68\x45" + "\x0c\x3c\x0c\x3e\x05\xae\xac\x0d" + "\xa8\x51\xa6\xec\x02\xd5\xa6\x2b" + "\x0b\x61\x04\x60\x68\x59\xbd\xe3" + "\x45\x72\x2b\x28\xf6\x6a\x07\xc2" + "\xa4\xe9\x94\x1e\x4a\xf2\x61\xae" + "\x63\xf1\x76\x15\x5c\x99\x15\x03" + + "\x47\x15\x57\x74\x3d\xff\xf8\x2a" + "\x19\x9b\xe1\x2c\x07\xea\xb3\x7e" + "\x85\x99\x09\x9b\x88\x62\x1b\xb8" + "\xc5\x09\xa3\xea\xd6\x22\xec\xdf" + "\x19\x34\xc3\xcf\xe2\xa0\xb5\xf9" + "\xa0\xb3\x65\xdb\x9c\xb6\xbf\x70" + "\x95\x4d\x52\x3f\x56\x15\xec\x75" + "\x30\x2f\x80\xe0\x37\x97\xed\xe5" + + "\xe0\x53\xc7\x04\x2b\xf4\xe7\x6a" + "\x6c\xd4\x06\xe6\x00\x42\x09\x26" + "\xa4\xdc\x80\xf6\x39\x2f\xb0\x3a" + "\xda\x37\x3b\x73\xa9\x53\x88\x9b" + "\x6a\x38\x5d\x85\xae\x34\x11\x2e" + "\x61\x9b\xed\x88\xe1\xbe\xa8\xd8" + "\x59\xd4\xed\x83\xc0\x8b\xa0\x2f" + "\x68\xe1\x0f\x2d\x51\x21\x4d\x94" + + "\x30\x9f\x2e\x84\xf9\xab\x7c\x8a" + "\xaf\x83\xab\x5e\xbf\xd4\x31\xa3" + "\x6a\x2a\x7f\x01\xba\xcf\x72\xd2" + "\xe3\xa0\xab\x83\xbc\x0a\x56\x27" + "\x75\x6b\x3a\x0e\x87\x33\xb8\x94" + "\xf5\x50\x9f\x6b\xa2\xae\xc6\x25" + "\xd0\xf6\xfd\xb5\x1d\x69\x3d\x80" + "\x14\x35\x33\xe6\x09\x75\xb7\x03" + + "\x6f\xcf\x14\xbd\x34\xe2\x5e\x74" + "\xbb\x24\xc0\x49\x84\x50\x8b\xde" + "\xb4\xd7\x35\xef\xdd\x4f\x33\x9c" + "\xb4\xb2\x64\xb7\x28\x77\x64\xff" + "\x31\xe0\x21\xcc\xd7\xee\x4d\xf9" + "\x85\x28\xd8\xa0\xb8\x40\x47\xe3" + "\xfb\xd2\x85\xc7\xc4\x17\x03\xa7" + "\xae\x8c\xa5\xf8\xc5\x6a\x05\xdc" + + "\x5f\x04\x78\x88\x8e\x4e\x27\xc4" + "\xe0\x25\xc3\xeb\xeb\x98\x66\x21" + "\x56\x6c\x39\x09\xcf\xbb\xef\x0f" + "\x5e\x80\x91\x04\x15\x19\x19\xdc" + "\xa2\x80\x54\x5c\x87\x4e\x4c\xa7" + "\x0a\xce\xc8\x72\xb3\xd1\xa8\xde" + "\xc1\xfa\x77\x7f\x1d\x70\x9f\x67" + "\x70\xb5\x6a\x6d\xb5\x00\xba\x3e" + + "\xce\x50\x23\xf2\x20\x4e\x00\x08" + "\x4e\x1c\x60\x8d\x19\x45\x45\x6b" + "\xd5\x77\xe1\xd5\x5a\xdc\x09\xea" + "\xd9\xba\x34\x75\xaa\x19\x3e\x92" + "\x46\xc0\x80\x31\xa6\x05\x29\xa4" + "\xaa\x64\xc8\xd3\xd0\x9e\x27\x0c" + "\x51\x5a\x90\xff\xb6\x41\xf3\x49" + "\x32\x6b\x96\xa7\x88\x09\xe2\x2b" + + "\xc1\x41\xa3\x61\x03\x89\x17\x36" + "\x42\x61\xfd\x0c\x60\xdc\x04\x36" + "\x6c\x31\x33\x85\xeb\x95\x22\x02" + "\x22\x29\xaf\x44\xac\xe4\xbd\x3d" + "\x69\xef\x7e\x1c\x5d\xfc\x8a\x89" + "\xa1\x4f\x4f\xd1\x05\x68\x89\x58" + "\xca\x21\x3c\x20\x60\x21\x00\x05" + "\x0b\x73\xef\x40\x30\x1f\x0d\x6f" + + + "\x5a\x19\xf7\x77\x09\x77\xbf\xfa" + "\x8f\x83\xeb\xad\x67\x61\xc8\x8e" + "\x2d\x01\x4f\xbb\xa8\x85\x12\xea" + "\x3f\xab\x3e\x9a\x03\x35\x88\xd6" + "\xc2\x04\x90\x30\xf8\x24\x5d\xee" + "\x5e\xe9\xff\x13\x76\x4b\x6e\xa9" + "\xa4\x3e\x22\xbd\x12\xfe\xdf\x0c" + "\x53\x9a\x73\xb6\xe5\x2e\x5c\x8f" + + "\x02\x38\x76\xbd\xa9\x6a\x40\xed" + "\xa1\x3d\x30\x65\xa0\x86\x14\xc2" + "\xc4\x2e\xe6\xc7\x1e\x29\xae\x61" + "\x3e\x33\x99\xdf\x92\x04\x2a\x62" + "\xe0\x8e\x7a\xbb\x9d\x0c\xd8\x7f" + "\xdb\xae\x01\x6c\xbc\xd3\x2e\xdc" + "\xec\x74\xbe\x08\x12\x5a\xc3\x35" + "\x1f\x67\x9f\x46\x1a\xcb\x40\xd5" + + "\x5b\x6f\x77\xbf\x5a\x3c\xe5\x2c" + "\x05\x7b\x35\x60\x71\x40\x72\x6f" + "\x7a\x3f\xbf\x71\x17\x37\x59\xb2" + "\x9f\x4a\x0c\x44\x1c\x50\xd2\x87" + "\x40\x53\xb0\x87\xe1\x52\x05\x44" + "\x32\x4c\x62\x21\xc8\x7c\xbf\xb7" + "\xdb\xcd\xfa\x22\xce\xa6\x55\x41" + "\xef\x37\x98\x88\xcb\x28\x42\x5a" + + "\x20\x5e\x4c\x58\x6a\x74\xa8\xa7" + "\x35\x70\xdc\xb9\xa1\x4e\x7e\x26" + "\x9b\x8c\x54\xb9\xcf\x15\x3a\x59" + "\xf3\x12\xd0\x4b\x35\x21\x6e\x5e" + "\x6e\x93\x8f\x8c\x6a\xcc\x31\xdf" + "\xdc\x41\xc2\xb5\x04\x4d\xf8\x8a" + "\x86\xfb\x5e\x34\x6f\x0a\x99\x63" + "\xcb\x62\xb9\xb9\x61\x4e\xef\x6f" + + "\x8d\xe4\xa2\xe1\x46\x82\xc4\x23" + "\x5c\xce\x3d\x54\xd1\xe6\x15\xf0" + "\xe9\x1d\x6d\x28\x52\xdb\x9e\xd1" + "\x56\x6f\x82\xdf\xf6\x87\x07\xd6" + "\xe3\x59\x14\x1c\xfe\x5d\x1d\x6e" + "\xdc\x6c\xb0\x9e\xa4\x99\xe8\x26" + "\xdb\xfb\xa1\x14\xc9\x60\x95\x02" + "\xf5\xb4\xd3\xb3\x2f\x84\x78\x8b" + + "\xcb\xec\xbe\x22\x9c\xfa\x6d\xc5" + "\xc0\xd7\x88\xa1\x4a\xa9\x41\x9c" + "\x29\x47\x32\x70\xa1\x83\xc2\x36" + "\x11\x65\x3f\xb6\x50\xe2\xa0\x2d" + "\xa0\x24\x5e\x7b\xd2\x9f\x4d\x83" + "\x42\xdd\x34\x6c\x1b\xb7\x26\xac" + "\xd9\x36\x93\x32\x97\xb4\xf1\xe5" + "\x9d\x4a\xe9\x39\xcf\x1a\x68\xdc" + + "\x30\x7b\xd7\x6c\xef\xcc\x80\x5c" + "\xd0\xb6\x99\xec\x99\x82\x97\x49" + "\x35\xd3\x39\xb9\x5e\x48\xf4\x6b" + "\x47\xc1\xd7\x86\xab\x61\x3e\xc5" + "\xdd\x1d\x60\xfb\x52\x80\x94\xdd" + "\x48\xdd\x11\x35\x39\xeb\xc5\x34" + "\x1c\xf6\xe6\x00\x76\xc6\xf5\x91" + "\x34\x1f\xe7\xb1\x25\xb5\xf1\x33" + + "\x08\x26\x72\x25\x09\x8f\x36\xf6" + "\xc6\xf5\x1c\x13\xdb\x60\x12\x13" + "\xac\xf7\xb4\xfa\x3b\x35\xeb\x40" + "\x29\xe8\xee\x37\x80\x88\xc7\x85" + "\x4e\xf2\xbd\xc3\xff\x81\x15\x4c" + "\xa8\xc5\xc3\xf5\xcb\x75\xff\x5b" + "\x40\x6f\x4e\xa1\x3f\xc8\xe8\x35" + "\xca\xe0\x95\x02\x0f\x1c\x1d\xb8" + + "\x1d\xdd\xd9\xee\xf8\x53\x71\xde" + "\x2e\xcb\xeb\x52\x11\xad\x09\xba" + "\xb6\x3f\x84\xe1\x15\xb0\x41\xaa" + "\xf0\xe6\x4c\xdd\xab\xa2\x33\xf9" + "\x3f\xb8\xf6\x13\x43\x83\x7f\x77" + "\x75\x3a\x11\xdb\xa4\x7d\xdf\x28" + "\x43\xd1\xa5\x72\x3c\x1b\x7d\x6d" + "\xdf\x6d\x6c\x96\x98\x96\x78\x6f" + + "\x54\xa0\x2b\xa7\x33\x9a\x43\xed" + "\xba\x65\xd2\xea\x15\x0a\x17\xa3" + "\x8e\xa5\x99\xfe\x03\xb9\x7e\xcf" + "\x26\x0c\xd8\x33\xc6\xb0\x6d\xcf" + "\x1a\xe7\x13\xf6\x5e\x25\x31\xd0" + "\x5c\x25\xca\x18\x57\xbe\xcc\x12" + "\x0d\xc4\x08\x78\x53\xd0\x21\xdd" + "\x6b\xbe\xf2\x3a\xbc\x8e\x48\xf5" + + "\xc5\xf9\xe3\x1b\x7c\x0d\x11\x47" + "\xdd\xb4\xad\x5e\x48\xe4\xb9\x12" + "\x41\x3d\x71\x0b\x87\x09\x8c\x6e" + "\xae\x56\x3d\x73\x56\x03\xe2\xe1" + "\x27\xa7\x5e\x44\xab\x6b\x8d\xe6" + "\xa4\xa1\x34\xc9\xea\xf6\xf4\x9e" + "\xc3\xf1\xce\xf8\x47\x55\x15\xe0" + "\xbf\xdc\x9b\x15\x09\x39\x5c\xdb" + + "\xd1\x8a\x2a\x44\x3d\xe2\xef\xf2" + "\x64\xc1\xb9\x06\x7d\x6a\x81\xc3" + "\xe5\xa5\x0a\xdc\x8b\x2d\xdf\xa9" + "\x65\x8e\x0a\x12\x6f\xe4\x1a\x19" + "\x5b\x1c\x61\x00\x87\x7f\x66\x83" + "\x48\x99\x10\xff\xd7\x1e\x17\x83" + "\x52\x59\x69\xca\xf8\xec\xa2\x33" + "\x13\x1a\x8d\xf4\xee\x73\x4a\xfa" + + "\x7d\x00\x04\x66\x84\xcf\xca\x97" + "\xf1\xa9\x47\x2d\xb2\xb4\x92\x1e" + "\x65\xd1\x4e\x37\xd6\xe0\x8a\x85" + "\xb8\xef\x7a\x30\x6f\x3e\x97\x4c" + "\x72\xeb\x10\x8a\x23\x4a\x52\x6f" + "\xd6\x49\x28\xeb\xa9\x92\x4a\x7b" + "\xdd\x1e\xe9\x2f\xa4\xbd\x78\x36" + "\x5c\xc3\x0f\x7c\xcd\x2a\x09\x56" + + "\x17\xe5\x10\x0b\xf1\xe9\x13\x35" + "\xd4\xc1\x81\x69\x44\x25\x7d\x40" + "\xc1\xab\xd9\x60\x48\xa8\x53\x49" + "\xd0\xd5\x4f\x8c\xe4\xbd\x8d\xe3" + "\xb1\x5a\xbb\x81\xc5\x16\x52\x7e" + "\xa1\xe0\xc5\x06\x6b\x04\x8a\x32" + "\xa6\x5e\x16\x91\x44\xf6\x34\x52" + "\x36\x0d\xac\xcf\x0f\x8b\xe6\xb6" + + "\x40\x3b\x09\x1a\x63\x5b\x1d\x09" + "\x4a\xf2\x62\x58\x07\x1c\x5c\xb8" + "\xbf\x85\x8f\x3e\xb5\x4e\xd7\xc5" + "\x56\x24\xb2\xca\x46\x77\x1c\xf5" + "\x89\xda\x61\xe7\xd9\xb8\x5c\xc2" + "\xb5\x28\xf0\xc0\x2f\xec\x70\x26" + "\x5c\xaf\xb9\x2d\x0d\xd3\x3f\x87" + "\x5e\x56\x62\x82\xa1\x1e\x0f\x3d" + + "\x0f\x73\x3a\xf4\xc8\x7c\xde\xfc" + "\x0e\x59\xab\x33\x3c\x6f\x9b\xe8" + "\x0b\x24\x03\xad\x29\xf5\x23\xc8" + "\xdb\xa5\xbe\x98\xfe\x9a\xb7\x82" + "\xde\xe5\x2f\x96\x56\x28\x8f\x56" + "\xf3\x91\xc5\x60\xdb\x0a\x59\x0c" + "\x58\xa8\x28\x4a\x14\x4a\xc7\x1f" + "\x4c\x3f\x20\xb3\x98\x24\x66\x3b" + + "\x4f\x8c\xce\x88\xe2\x30\x5c\x75" + "\x3d\x3c\x63\x21\xc8\x8f\x63\x56" + "\x2d\x7c\x5a\xa0\xff\x00\x60\x88" + "\xc6\x18\x02\x01\x31\xe5\x92\x8f" + "\xa3\x64\x17\xb8\x03\x79\xee\x09" + "\x91\x47\x63\x3c\x97\x36\xc2\x95" + "\x13\x2f\x8e\x4e\x22\xf5\xec\x3c" + "\xf8\x4f\xc3\x23\x6c\xd6\x1e\x5d" + + "\xbf\xb3\x30\x19\x22\xfb\xae\x9e" + "\x73\x9c\xa1\x22\x08\x6b\xc0\x25" + "\x98\xa4\xd3\x4b\x2a\x57\xa8\xd0" + "\x51\x63\xd7\x0c\x2f\x85\xbc\x20" + "\xda\x25\x89\xb3\x6d\x38\x01\x83" + "\x85\xf2\xec\x64\x6a\xe6\xfb\x85" + "\x7f\x61\xc9\xc0\x84\x7e\x74\x53" + "\x72\x17\xbe\x1d\x26\x1d\xd6\xb0" + + "\x8a\xff\x0d\x8d\x95\xc2\x84\xe5" + "\x05\x63\x24\xef\x8b\xf4\x2b\x55" + "\x3e\xdb\x45\x4f\xa5\x21\x9c\xc0" + "\x8f\xbb\xee\x3c\xec\x83\x30\xca" + "\xe2\xc6\x6d\x40\x7c\xd0\x4d\xbf" + "\x01\x30\xf6\xa7\x6d\x62\x96\x0e" + "\xd3\xcb\x16\xaa\xfe\xfb\xa9\x81" + "\x00\x13\x3a\x67\x5c\xca\x7e\xfe" + + "\x6a\x1b\xdd\x82\xd0\x4e\xfc\x48" + "\xaf\x03\xb7\x67\x38\xa1\x83\x57" + "\xaa\x6a\x5d\x00\x9a\xcb\x63\x24" + "\x43\xcd\x6e\x70\x5c\xc5\x1e\xd3" + "\x41\x76\x9a\x8e\x3f\xd3\x8e\x9f" + "\x7a\x9e\x8d\x09\xed\x53\x54\x62" + "\x93\x74\x88\xec\xe4\xad\xbe\xa3" + "\x66\x55\x79\x5a\x50\x80\x2b\x44" + + "\x17\x50\x96\x0c\x31\x62\x0c\x98" + "\x4f\x7a\x0d\x40\xb3\xc0\x8c\xaf" + "\x97\xcf\xf4\x48\xe2\x12\x58\xee" + "\x5e\xd9\x90\xbb\xb8\x7e\x58\xe4" + "\x5e\x04\x52\x81\x7f\xa5\x42\x1b" + "\x2e\x7c\x1c\x64\x06\xb9\x92\xd7" + "\xda\x87\x1c\xa7\x93\xf5\xfc\x9d" + "\xb9\x00\x04\x1b\x77\x7d\xab\xc7" + + "\xe2\x70\x5a\xd8\x34\x2d\x95\x16" + "\x52\x1a\x2e\xc3\x97\xff\x09\x7d" + "\xbf\x8a\x2d\xa6\x3e\xe4\xd6\xca" + "\xbb\xfe\xaa\x25\xda\x46\x76\x74" + "\xbd\x24\x4e\xe5\x96\xc4\x65\x03" + "\xe3\x50\xe8\x24\x16\xa4\x99\x14" + "\x2b\xd2\x81\x67\xf7\xdd\xf6\x24" + "\x81\x59\xc3\xbf\xf1\x55\xe5\x42" + + "\x38\x33\xcd\xfa\xc2\x19\x23\x5b" + "\xd1\x3e\x88\x6f\x47\x50\x96\xed" + "\x19\x16\x83\x16\xc3\x96\x07\x37" + "\xaa\x61\x6b\x20\x69\x34\xb7\x8d" + "\xe8\x08\xa9\x1f\x17\x5d\x0e\x0a" + "\xfa\x40\x54\xb4\xe3\x71\x72\xe8" + "\x98\xdb\x2b\x07\x3e\xe0\x6a\x7f" + "\x8a\xb9\xc3\x28\x55\xf7\x87\x06" + + "\x5a\x76\x39\x6c\x0d\xcf\xe3\x91" + "\x0b\xca\x3c\xac\xcd\x3a\xdb\xa2" + "\x50\x3b\x95\xcb\x08\x2f\x8f\x28" + "\x1a\xcf\x43\xcf\x2c\x58\x14\x24" + "\xa8\xe9\xee\x60\xbc\x8b\xec\x8d" + "\x42\xa0\x9a\x72\x02\x9f\xc7\x54" + "\xd5\xf5\x32\x65\xec\xd5\x1c\xd8" + "\x5f\xe1\x82\xcf\x3a\x30\x72\xa6" + + "\xff\xf5\x73\xc3\xe2\x03\xbd\xb3" + "\x41\x63\xfc\xe7\xb4\xa8\xa8\x80" + "\xdf\x7b\x08\xa0\xd6\x52\x29\xb7" + "\x8e\xa3\x48\xc0\x9d\xbb\x3c\x80" + "\x00\xb0\xf8\xcc\x7e\x65\x0a\xcf" + "\x09\xeb\xe1\x67\x18\xc0\x54\x8c" + "\xfc\x46\xb6\xf0\x26\x10\xf9\x88" + "\xd8\x4b\xff\x7d\x53\xf2\x0d\x9d" + + "\x42\xd5\xc6\x48\x80\xc9\xfb\x4e" + "\x2e\xf4\x25\xc9\x00\xc2\x9c\x26" + "\x3e\xfe\xf6\xbc\x6a\x44\x5a\xb5" + "\xc5\xe5\x67\xac\xd5\xdb\x02\xb0" + "\xd8\x8e\xda\xee\x64\xee\xec\x91" + "\xd2\x71\xe0\xba\x2d\xf9\x89\x89" + "\x53\xbf\x7e\xaf\xe0\xdb\x45\x92" + "\x81\xa7\xef\x9e\xe7\xe6\x41\xd1" + + "\x9f\x7e\xeb\x2d\x0b\x49\x28\x97" + "\x6b\x25\xc7\x02\xc6\xc3\x77\x88" + "\x73\xaf\x32\x22\x1d\xaa\x9d\xd2" + "\xe8\x49\xb0\x1a\x21\x90\x4b\xc9" + "\x94\xbf\xe4\xe6\x53\xdf\xe4\xdb" + "\x06\x10\x7b\x4d\xe7\x24\x73\x4a" + "\xdf\x8b\x6a\x0a\x56\xd4\x46\x04" + "\x89\x55\xa3\x5c\x8b\xf9\xf2\xab" + + "\x39\xb8\xfa\x3b\x2d\x58\xdf\x46" + "\xde\xda\x8a\x2f\x04\x4e\x47\x92" + "\xc3\x1b\x7a\x14\x6a\x76\xa7\x36" + "\x79\xf9\xc0\x0d\x54\x0f\x94\xb6" + "\x25\x9f\x75\xf2\xf2\x8e\x73\x44" + "\xc6\xf4\x19\xa7\x89\x57\xd9\x9d" + "\x45\xc3\x50\x07\xf4\xb7\x59\x28" + "\xd5\x80\x21\xb2\xf2\x8b\x78\x5e" + + "\x7e\xb4\x71\x66\x01\x5f\x21\x4b" + "\x2a\xae\x8d\x4a\xca\x33\x76\xb6" + "\xdb\x3c\xfd\x79\x0f\x12\x15\x29" + "\xde\xe6\x64\xb0\x6f\xa0\xf8\xc1" + "\x20\x74\xd5\xc1\x8c\x36\xd5\xf4" + "\x75\xe4\x8d\xe1\xa8\x51\xda\x6a" + "\xb0\xd4\x49\xc7\x7c\xd4\xf0\xa0" + "\xa5\x6a\x52\x74\x00\x2c\xfa\xab" + + "\x3c\x17\x59\xfc\x73\xb7\xf2\x3f" + "\x9c\x91\xa0\xa2\xa5\x12\x86\xf6" + "\x15\x7b\x4c\x23\x28\xae\xa8\x9c" + "\xdc\xe7\xbe\xed\xaf\x58\xf6\xfd" + "\x5f\x96\x18\xab\xad\xd9\x55\x2c" + "\x44\xde\x00\x5c\x12\x1f\x90\xb9" + "\x51\x0b\x36\xee\xf1\xaa\x70\x8b" + "\xe0\x4f\x60\x05\xd5\xa9\x4b\x3e" + + "\x2b\x77\xd2\xf0\x82\xe4\xb8\xbe" + "\x99\x06\xe6\x2d\x65\xab\x16\xc5" + "\xf9\xf7\xd4\xc6\x34\x1e\x4f\x1e" + "\xee\xe4\xec\x5c\xbf\x88\x98\x23" + "\x38\xd2\x03\xbc\xfe\x86\xc5\x7a" + "\x6f\x3a\x35\x7d\x15\xc7\xd3\x8c" + "\x65\xfd\xf1\xb3\xde\xaa\x96\x02" + "\x5f\x53\x1e\x3a\xd4\xed\xb8\xe3" + + "\x63\x05\x9c\x71\xa8\xaf\x6a\x37" + "\x9f\xc7\x5f\xbc\xdc\xd2\x8a\xcd" + "\xd3\x0c\x75\xcb\x9f\xdb\x3f\x30" + "\x8e\xb0\x18\x44\x2f\x05\xff\x14" + "\x20\x65\x2d\x3e\xcf\x84\x50\xf7" + "\x09\xd5\x4e\x14\xf8\xf0\xbd\x7e" + "\x98\x5b\xf2\xd3\xf2\xf0\x3b\xf4" + "\x37\xd8\x54\xa3\xcf\x71\xad\x86" + + + "\x5d\xf7\x8a\x86\xc4\xc8\xd0\xd9" + "\xea\xc7\xc8\x45\xff\x5c\x32\xd7" + "\xb0\xec\x81\xcc\x96\x19\x47\xab" + "\xed\x24\x18\x61\xf3\x55\x5d\xff" + "\xee\xa0\x77\x19\x41\x45\x31\xbe" + "\xc6\x38\x20\x72\xc5\xc4\x85\x50" + "\x95\xb4\x4b\xf9\xbf\x35\x53\x2d" + "\x82\xa0\xe2\xc8\xa6\xd8\x4a\x89" + + "\x37\xbb\x11\x2c\xb2\x34\x02\x54" + "\xa3\x74\x4c\xed\xdd\x66\x03\x2d" + "\x5d\xf2\xc5\xee\xda\x68\xa9\xf9" + "\x42\x31\xb6\x67\x68\x10\x60\x36" + "\xd4\xb6\xd7\x68\x2c\x6d\xcd\x07" + "\x42\x29\x84\x0c\x09\x4f\xf7\xa8" + "\xee\xb1\x68\x77\x04\x14\x75\xe2" + "\xe4\xae\x62\xfe\x89\x7e\x5f\x4b" + + "\x20\xef\x94\x19\xb2\x59\xe0\xd1" + "\x18\xe3\x8a\x63\x69\x3b\x65\x2a" + "\x10\x90\x69\x2f\x58\xeb\xd5\x70" + "\x4a\xf8\xf5\x09\xf7\x39\x97\x27" + "\x36\x93\x79\x8b\x3c\x66\xa4\x5d" + "\xeb\x37\x3c\x20\x4d\xf1\xfd\xfd" + "\x2d\xfb\xdb\xa1\xdc\xa9\xd8\x32" + "\x9b\x8f\xd4\x77\xf0\xcf\x40\xab" + + "\xed\xbb\x9f\x87\x0b\x9f\x36\xf2" + "\x69\x18\x9d\xda\x86\xae\xf0\x0f" + "\x45\x6f\x76\x56\x59\xd7\x51\x52" + "\xfc\xd0\xe8\x2b\xc0\xd8\x84\x49" + "\xf0\x08\x10\xd2\xa6\x95\xcc\x7e" + "\x49\x1c\x1a\x3a\xa0\x54\xbd\x29" + "\xf3\x50\x6c\xd2\xc5\x28\x98\xab" + "\x51\xd2\xd0\x51\x7c\x08\xc0\x32" + + "\xa5\x50\xaf\xfb\xab\x90\x17\xf6" + "\x50\x07\x4e\x68\x6b\xe7\x55\xdf" + "\x05\xb0\x76\xf1\xa7\x6d\x51\xec" + "\xc7\xdd\x2d\x7a\xbb\x53\x55\x57" + "\x73\xfa\x3a\x55\xa3\x7c\xc8\x37" + "\x51\xc2\x55\x4d\xfc\x3f\x5f\x31" + "\x35\x5d\x3e\xaf\x2a\x44\x46\xe8" + "\x28\xff\x95\x64\x49\x11\xb9\x61" + + "\xaf\xf3\xb5\x62\x66\xeb\xfe\x47" + "\x34\x37\xbb\x0a\x61\xb5\xfa\xce" + "\xb1\x5c\xf3\x19\x0e\xe6\x9d\x44" + "\xb9\x0e\x7f\x15\x14\xdb\xf8\x39" + "\xd6\xbf\x61\x3c\x5b\xcc\xae\xff" + "\x03\x67\x21\x41\x1d\xd4\xa4\xa5" + "\xc2\x1c\x4e\x22\xed\xab\x8f\x7f" + "\x53\xd9\x1a\x87\x86\x81\x5a\x0d" + + "\x23\x08\xf9\x56\x49\x3a\xdf\x4b" + "\x7b\x77\x1d\x74\x80\x50\x0f\xba" + "\x60\xf7\x8b\xf3\xc3\x71\x1d\x09" + "\x02\x5b\x62\x9b\x0f\xd5\x33\x96" + "\x61\xde\xc9\xb8\x43\xb7\xec\x03" + "\x20\x47\xe7\x5d\x54\x12\x75\xb4" + "\xb2\x1c\xce\x74\xc9\xef\x9d\x9f" + "\xef\x32\xbd\x00\x6a\x4f\x4a\x77" + + "\x52\x9a\x79\x01\xa6\x8e\x0d\x19" + "\x52\x29\x6d\xb8\x41\xec\x0c\xa2" + "\x7c\x2a\xff\x7f\xb2\xff\x62\x30" + "\x37\x9d\xf1\x79\xe5\x32\x1b\x74" + "\x47\x7d\xb5\x4e\x81\x81\x0d\xf8" + "\x6b\xf0\xae\x16\xd4\x0e\x2d\x7a" + "\x88\xb5\xec\x1c\xb0\x5f\x73\x09" + "\x5b\x1f\x06\xc6\xaa\xca\x41\x16" + + "\x5b\x1e\x13\xb0\x02\xc0\x7b\x32" + "\xd9\x14\x25\xcb\xd5\xe6\x39\x17" + "\x43\x15\xa8\x55\xfe\xda\xcb\xc8" + "\x43\x72\x13\xe1\x6c\xa3\xb1\x5b" + "\x27\x53\x32\x17\xc5\xa3\x5d\x20" + "\x7e\x05\x5a\x51\x36\x1a\x5c\xc3" + "\x9b\x5f\x92\x42\xc9\x64\x0f\xf0" + "\x7a\x9f\xd5\xb7\x3c\x63\x14\xbd" + + "\x3a\x8c\x6e\x65\x71\xd1\x2a\xae" + "\x05\x07\xcd\x1a\x63\xa4\xe2\xc0" + "\x5c\x05\xb6\xa0\x8a\x6a\x6f\x00" + "\x6e\xa2\x65\x2b\xd7\x13\x45\xaf" + "\xbc\xd5\x16\xd6\x14\x9e\x54\x3f" + "\x1f\x3b\x25\x71\x55\x39\xee\x64" + "\x3a\x24\xce\xb8\xc1\x0b\xb1\xe8" + "\x77\x4e\x3a\x91\xe5\xac\xbe\xbc" + + "\xbd\x7d\xf3\x41\x43\x00\xc1\x47" + "\xf6\xec\x68\x61\xe3\xca\xec\x96" + "\xa3\x6a\xa4\x1c\x9d\xe5\xbd\x65" + "\xfa\x8f\x69\xb8\x7a\x02\xa7\x38" + "\x37\x44\xc3\x6d\xc8\x9d\xb8\xa2" + "\x3f\x15\xa4\x43\x8d\x11\x0a\x5a" + "\xd8\x2f\xe2\x1c\x86\x0a\x33\x9e" + "\xbc\xd3\xbb\xb3\xf6\x2a\x38\x28" + + "\xa7\xd6\x79\xf7\x56\x22\xd3\x68" + "\x4e\x28\xe7\x19\x4d\x3b\x42\x20" + "\x53\xb1\xf3\x38\x1b\xaa\x19\xde" + "\x03\xf7\x44\x84\xc2\xb6\xd0\x73" + "\xa3\xe6\x64\x9c\x48\x61\x61\x66" + "\x24\x62\x25\x37\x37\x7c\x58\x99" + "\x63\x15\x33\x61\xfe\x77\x52\x6f" + "\x2e\x50\x56\xa6\x4a\xad\x74\x71" + + "\x71\x02\x1e\xd8\xc0\x27\x2e\x0b" + "\x7c\x31\x7a\x11\x96\x75\x7a\xa6" + "\x99\x3d\x72\xa6\x28\x89\xf0\x17" + "\xa3\x10\x53\x48\x81\x56\xa7\x71" + "\xa9\x6c\xb6\xaf\x62\x54\x46\x90" + "\x9d\x22\xbe\xfb\xcc\x97\x5e\x18" + "\xc2\x8f\xad\xdd\x6a\x60\x1a\x6a" + "\xcf\x97\xc7\xb3\x16\xf3\x31\x24" + + "\x8d\x91\x33\x01\x92\xfc\x1f\xec" + "\x97\xef\xc9\xb2\x5e\xbf\xd9\x15" + "\x9a\xbb\x6c\xfc\x42\xb5\x85\x78" + "\x5d\xcf\x20\x57\x53\x64\xbe\x8a" + "\xab\x68\xec\xd4\xce\x5d\x71\x4e" + "\xa3\x24\x9c\x27\x14\x76\xa6\x57" + "\xcf\x61\xbb\x31\x2a\xd5\x8e\x78" + "\x03\xa0\x37\xf4\x44\x24\xa8\xab" + + "\x32\x94\x52\x93\x11\x40\x03\x47" + "\x62\x34\x74\x30\xdd\x6b\x10\x1f" + "\xca\xd8\x66\xcd\x64\x99\xfb\xab" + "\xd5\xad\xbd\xe9\x5a\x9d\x4d\x93" + "\x22\x3d\x8e\x90\x15\xd8\x76\x59" + "\xbd\x57\xe0\x28\x2f\x36\x4a\x34" + "\xb3\xdf\x43\x54\xdc\xda\x2c\xf9" + "\x3b\x60\x89\xf0\xad\x97\x12\x00" + + "\x27\x14\x15\x20\x4f\x82\x99\x7f" + "\x06\x02\x43\x92\xb6\x28\x68\x20" + "\x57\x23\x11\xe1\xd7\x97\x90\xaa" + "\xec\x14\xe4\x09\xf2\xa2\xf9\xac" + "\x56\x53\x91\x27\xda\xc9\xda\xdb" + "\xe3\xfe\x1e\x00\xb7\x34\x07\x7e" + "\xe2\x88\xb2\xd2\xbb\xb5\xfa\x54" + "\x9c\xd0\x2d\xf6\xc4\x0f\x63\x4c" + + "\x6b\x06\x44\x50\x60\xce\x2f\x4a" + "\xf4\x47\x3a\xfa\x9c\x01\x4a\x90" + "\x60\x0a\x5c\x0c\x9c\xea\x81\xba" + "\xbd\x98\xc0\x96\x0d\xea\xe4\xd7" + "\x02\x0a\xd5\x9c\x41\x00\xe7\xef" + "\x8c\x04\x7f\x2d\xd4\x39\xc8\xc0" + "\x1f\x56\x9b\xe0\x64\xf2\xda\xe2" + "\x8b\xb1\x34\x50\x18\x13\xbc\x0c" + + "\xe1\xa5\x70\xbd\x66\x3e\x88\x6d" + "\x13\xe7\x5d\xd0\xc1\x84\xd8\x9b" + "\x7d\x48\xd8\xd4\x45\xd4\xd9\x48" + "\x05\xe4\xea\x0e\x8b\xcd\x40\x84" + "\x3e\xf8\x26\x3d\x29\x0f\xcd\xa3" + "\xe4\xc5\xa3\x22\x30\x45\xd9\x3f" + "\xa7\x2c\xfa\x3f\x66\x78\xa0\x63" + "\x97\xa0\xd4\x00\x29\xdd\xea\xbf" + + "\x7a\x3f\x32\x88\xe3\xf2\xe5\x11" + "\xcd\x84\x75\x92\xc2\x74\x7a\xe0" + "\x2d\x3d\x61\x95\x34\x4b\x77\x1e" + "\x88\x74\x78\x2c\xc5\x52\x9b\x9c" + "\x08\x1f\x42\xbe\x3e\x3c\xdd\x3c" + "\x5f\x3d\x3e\x22\x9e\x81\xf7\x5f" + "\xb9\x09\xda\xc1\xb2\x39\x87\xba" + "\x1b\x49\x8b\x4e\x16\x63\x72\x6b" + + "\xba\x32\x84\xd6\x59\xa5\xae\x13" + "\xdb\x15\x39\xd3\xfb\x43\x00\x94" + "\x08\xda\xe8\xe2\x94\x7c\x6c\x47" + "\xbb\x65\x30\x44\xc4\x30\x16\x6b" + "\x75\x6c\xf0\x19\x6d\x54\xd8\xd6" + "\xbd\x5a\xb3\x2e\xc2\x98\x1e\x7e" + "\x8e\x7d\x15\xf0\x10\x93\x1c\x75" + "\x75\x60\xfa\xf6\x27\x43\xf8\xde" + + "\xef\x3b\x94\xa0\x3c\xd1\xaf\xb5" + "\xcc\xb1\xab\x57\x29\x77\x51\xd6" + "\xbc\xb5\x61\x9b\xdc\x52\x5a\x9d" + "\xcd\x31\x6e\x80\xa6\xfa\xce\x85" + "\xea\x1d\x0a\x72\x7a\x25\x84\xab" + "\x35\x0d\xd7\xce\x1b\x26\x60\x6a" + "\x61\xda\xd6\xb9\x4d\xf9\x23\xc0" + "\x0e\xae\xa0\x54\xec\x7e\x7f\x94" + + "\x0e\x4e\x7a\x3a\x3c\x99\x5b\x76" + "\x14\xd3\x79\x9d\xef\x4a\x8f\xfb" + "\x24\xeb\x19\x2a\x0e\xc5\xa2\x5e" + "\x8c\xbc\x91\xb8\xe5\x16\x50\x92" + "\xe7\xec\xd1\x3a\xdc\xaf\x70\x8f" + "\xe2\xab\x8f\xf0\x4c\xa8\xbb\x0a" + "\x2b\x13\xf6\x15\xc8\x22\x99\x0a" + "\x77\x6d\x07\x5d\x73\x13\x02\x6c" + + "\x87\xb7\x83\x9f\x56\x87\xb7\xc3" + "\xd7\xdd\x94\x36\x26\x49\xd2\xd6" + "\x2e\xa0\x70\x5d\x94\x48\xd2\x58" + "\x6a\x8c\x27\x8c\x0e\x67\x16\xac" + "\xe6\xb6\x70\xe3\x58\x4d\xa9\x71" + "\x05\xdb\x53\x02\x84\x63\xd7\xe4" + "\xfe\x2c\xb3\x14\x88\xc9\xb1\x99" + "\x95\xcc\x78\xcc\x70\xd8\x6b\x4e" + + "\x61\x39\x45\xa4\x15\x26\xaf\x00" + "\x2c\x11\x3d\x99\x4b\x49\x05\x17" + "\x52\xd6\xcd\xa1\x2a\xe1\x32\x00" + "\xb3\x9c\x6d\x04\x12\xa6\xbf\x0e" + "\x8c\x72\x63\x1b\xf3\xa9\x03\x9f" + "\x05\x2b\x02\xde\xa2\x18\x36\x8f" + "\xc9\xc5\x77\x3e\x90\x4d\xb2\xd5" + "\x7c\xb7\xac\x72\xa3\x38\x78\x83" + + "\x14\x36\xb6\xc8\x79\xca\xf7\xf5" + "\x3c\x90\xf4\x8a\x15\xb2\xbf\xf3" + "\xd3\x7b\xd4\x96\x54\x9f\xdb\x2b" + "\xba\x63\x8a\x0e\x30\x15\xe7\xd6" + "\xc4\xbe\x93\x7a\x49\x0a\xe9\x67" + "\xee\x63\x1e\x8c\x8b\x47\x13\x86" + "\x61\xe5\xdd\xf2\xc8\xd9\x6b\xe3" + "\x89\x86\x76\x8a\x51\x86\x14\x68" + + "\x47\xb0\xce\x8f\xd9\xcb\x65\xfe" + "\xa1\x11\x8b\x3f\xf5\x2e\x87\xde" + "\x2f\x80\xec\x8f\x3d\x0d\xba\x9a" + "\x1d\x38\x9f\x9a\x32\x1d\x9f\x13" + "\x8d\x95\x87\xc5\xd9\xae\x21\x07" + "\xda\xa7\xf6\xb9\x5c\x01\x6a\x06" + "\x06\x9d\x5d\xed\xe3\xc4\x9e\x05" + "\x1f\xca\xba\x6c\x71\x85\x42\x14" + + "\x1c\x53\xaa\x94\x94\x7a\x61\xef" + "\x87\xad\xf4\xd6\x2f\x5e\xc3\x9a" + "\xfb\x68\x24\x12\x47\xa0\xd2\xbc" + "\xa6\x5c\x7c\xef\x3f\x42\x7a\xbd" + "\x40\x80\x4c\x06\x52\xcb\x58\xab" + "\x16\x47\x64\x4a\xd5\x4e\xef\x93" + "\x8d\xd4\x2c\xc3\x97\x70\xd1\xf7" + "\x42\xcf\x7f\xd1\x73\xa1\x49\xb2" + + "\xf5\xcd\x98\xe2\xff\x0f\xfe\x66" + "\xb6\x51\x2e\x7b\xa4\xbe\x61\x3f" + "\xa4\xaf\xd3\xba\x17\x21\x37\x7d" + "\x2f\x6e\x65\xef\x9c\xa0\x21\x65" + "\xe7\x8f\xa5\xe8\x66\xc9\xb8\xb3" + "\xc7\xeb\x47\x5a\x11\x3a\x20\x25" + "\x73\xe5\x4b\x5c\x8d\x58\x81\xfe" + "\x3c\xa0\x49\x1f\xf3\xe2\x32\x61" + + "\xc4\xec\xa7\xb7\x08\xc1\xe5\xbb" + "\x4c\x2e\xd2\xbf\x8e\xa7\xa5\x62" + "\xd2\x8b\x18\xdf\x33\x40\x97\xb7" + "\xae\xd1\xf7\x4d\xea\xde\x11\xcf" + "\xea\xe3\xac\x53\x4a\x77\xcc\x99" + "\xf6\xc1\x5c\x10\x71\x3a\x37\xe0" + "\x20\x7a\x3d\x13\x7f\x98\x51\xd7" + "\x71\x58\x21\xae\x04\xee\x86\xab" + + "\x99\x2c\x8c\x0f\x13\xb0\x1a\xec" + "\xc2\x25\x77\xf1\x8f\x96\xe8\x60" + "\x0b\x98\x0a\x94\x93\xa5\xa4\xe1" + "\xb1\xcc\xe9\x20\xb0\x15\xed\x15" + "\xec\x0b\xa0\x64\xcc\x54\xd7\x77" + "\x82\x73\x68\x41\x33\x9c\xd0\x90" + "\x51\xb6\x1f\xc3\x2d\xe0\x4f\x29" + "\x53\xae\x94\x1c\x1a\xcd\x72\x83" + + "\xe6\x10\xcd\x80\xa2\xf9\x94\x20" + "\xa7\x0d\x8a\x7b\xaa\x32\x52\x04" + "\x4e\x24\x03\x9c\xb6\x81\x9a\x96" + "\x55\xd9\x98\x7e\xca\xb4\x93\x12" + "\xb0\x3a\x8f\xd6\x1d\x42\x31\x16" + "\x82\x8c\x73\xc3\x22\x64\x10\xa0" + "\xf9\x4f\x2c\xf8\x45\x38\xf4\xc5" + "\x8f\xf5\xa0\x1a\xbe\xac\x79\xb4" + + "\x3b\x70\xc2\x1a\x7a\x10\x37\x85" + "\xb5\x57\xc8\x6b\xd8\x58\x92\xb4" + "\xd1\xcc\xda\xbc\xde\x14\xdf\x57" + "\x29\x85\xae\xc4\xd7\x68\xab\x24" + "\xd0\x59\x4e\x73\xd4\xb5\xd8\x7e" + "\x80\xcc\x95\xc4\xc8\x40\x87\x5f" + "\xb3\xb9\x1d\x29\x5a\xdd\xae\x84" + "\xbe\x95\xb9\x4f\xf8\x60\xb3\x80" + + + "\xfa\x76\x1a\xa6\x8d\xc6\xd5\x55" + "\xdc\x54\x15\xca\x1d\x44\x8b\x59" + "\x9c\x27\x3b\x77\xb9\x23\x99\xd3" + "\xfc\x9e\xbf\x36\x3c\x1d\x33\x33" + "\x99\xe3\x8d\x29\x8e\x84\x4c\x2d" + "\x56\x7f\xa2\xa1\x77\x8e\xdb\xcf" + "\x70\xab\xb8\x57\xea\x55\xc8\x94" + "\xba\x79\x78\x6f\xae\x9d\xdb\xdc" + + "\x38\x6a\x63\x7f\x36\x07\x4f\x4c" + "\xcb\xd5\x76\x0e\xb7\x3f\x94\x9f" + "\x8b\x8b\xb6\xa8\xba\x10\x35\xb0" + "\x1f\x7a\xd0\x9e\x0a\x78\x46\xc2" + "\xc2\x9f\x54\x6d\x15\x14\x05\x3c" + "\xca\x81\x77\x60\x31\x3f\x95\xc2" + "\x13\x54\xd9\xd8\x69\x2c\x5e\x95" + "\xe3\x82\xd2\x7b\xdc\xfa\x00\xb3" + + "\xb4\x01\x79\xc2\x63\x11\x4b\xa1" + "\xf3\x8b\x9b\x89\xe0\x36\x92\xfd" + "\x0a\xda\xc6\xcb\xec\x91\xb0\x42" + "\x97\xd2\xd1\x5a\x6f\xac\x1d\xbb" + "\x6e\xf7\x1c\xa9\x53\x1d\xe6\x80" + "\xe7\x1e\x1f\xd3\x12\xa4\x10\x41" + "\x77\xcf\xef\x13\xba\xc3\x87\x2d" + "\x76\x0d\x45\xdf\xb4\x4b\x37\x1f" + + "\x9a\x51\x47\x41\x02\x86\x28\x20" + "\xf0\x72\xb3\x26\xac\x1e\x98\xd0" + "\xc8\xeb\x85\xa7\xca\xa7\xd4\xa9" + "\xe9\x58\xdf\xdb\x0d\xc5\x53\xd9" + "\x8f\x0f\x59\xfd\xcc\x61\x63\x9d" + "\x17\xc9\xe6\x44\x6b\x62\xe9\x72" + "\xcf\x64\xeb\x22\x10\x61\xd9\x7f" + "\xf3\x88\xb2\x9e\x7e\xbb\x3e\x86" + + "\x03\x44\x7e\x09\x0a\x0a\xe1\x15" + "\x65\x46\x85\x19\x86\x0a\x3d\xcb" + "\x26\x48\x7d\xd6\x11\xe2\xd8\x88" + "\x39\x28\x9d\x0b\x6e\xf6\x9a\xb3" + "\xa8\x5c\x47\xbd\x88\x45\xf9\xa5" + "\x0b\xb8\x77\xc0\x66\x79\x6b\xe0" + "\x6c\xc2\x27\xda\x85\x14\xdb\xfe" + "\xe0\xd5\x0f\xfe\x3a\xd3\x90\xd2" + + "\x3d\x58\x06\x13\xf3\x02\x62\x68" + "\x2e\x62\x7c\x43\xa0\x0d\xb1\x05" + "\xc8\x7b\x6a\x07\x0f\xaa\x9a\xbf" + "\x43\x4e\x8f\x8f\xfb\x4e\xe9\x25" + "\x6d\xc2\x3d\xfa\xb7\xc9\x35\x8a" + "\xc5\x03\xff\x96\x93\xfb\xe5\xe0" + "\xce\x94\xc3\xeb\x43\x38\x7e\xa7" + "\x60\xde\x61\x83\x95\x65\xde\xce" + + "\x40\xb5\x22\x0c\x09\x75\x90\xbf" + "\xd4\x67\xc2\xb7\xaa\x42\xde\x2c" + "\x93\xd6\xb0\x5a\xed\xf9\x18\xba" + "\xd9\x60\x46\x6e\xa6\x2a\xa6\x3b" + "\x6a\xa9\x9e\xab\x7b\xf9\x4b\xb2" + "\x32\x0e\xb6\xe3\x42\x96\x03\x5d" + "\xd5\x9b\x4d\x7c\x06\x45\x6a\x4e" + "\xa4\xa6\xd4\x7e\x9e\x5b\x6c\x66" + + "\xb0\x31\x8a\x67\xf5\x7c\x7b\x87" + "\x20\xb6\x98\x39\xae\x01\x03\xd5" + "\x96\xb3\x0f\xc0\xc5\x57\x42\x73" + "\xa6\x72\xe6\x04\xa0\x18\xfb\xf9" + "\x51\x88\x75\xe8\xeb\xd8\x8b\xff" + "\x44\xba\x99\x5d\xc6\xe4\x64\x1e" + "\xb7\x93\xfd\x7d\xdf\xae\x8e\x4b" + "\x8c\x6b\xe7\x04\x98\x2a\x2f\xba" + + "\xbd\xdd\x56\x9b\xf0\xa2\x02\xae" + "\xf3\x1c\x2f\x8a\xac\xb5\x39\x13" + "\x0d\xff\x9d\x83\xc7\x69\xb5\xf2" + "\x3d\xa4\xe9\xfe\x64\xe8\xb9\xb0" + "\x4e\x06\xbb\x77\x41\xca\xf8\x4f" + "\x63\x9f\x24\xfd\x12\x28\x5a\x14" + "\x9a\x68\x6f\xf8\xac\xbe\xb7\x3a" + "\x5e\x5f\xd3\x01\x27\xec\xaf\x9b" + + "\xb7\xc7\x57\xae\xdd\x3f\xa2\xbb" + "\x22\x25\x93\x1b\xf2\x42\x53\x34" + "\xa3\x4a\x6d\x55\xfe\x80\x9c\xfd" + "\x61\xbb\x25\x65\xba\x07\x39\xa0" + "\x33\x89\x21\xff\xe1\x10\xb0\x38" + "\x7b\x11\x52\xaa\x54\xb6\x66\xc0" + "\xea\xe6\xf2\x94\x20\x19\x14\x8e" + "\xb2\xf2\x32\x0d\xca\x7d\xa2\x66" + + "\x92\xbe\xab\xfb\x21\xb1\xe6\xb2" + "\x76\x00\x33\xe1\xfb\x50\x18\x28" + "\x15\x00\x89\x97\xec\x81\x35\x09" + "\xf5\x77\xff\x75\xed\xdd\xb1\x69" + "\x05\x51\x10\xab\x8f\xb1\xf0\x7c" + "\xef\xcf\x9c\xa8\x31\xed\x3c\x95" + "\x09\x40\x91\xeb\x5f\xf8\x51\x31" + "\xad\x48\xed\x88\x87\x1b\x9f\x3c" + + "\x1e\xb2\x0f\xe9\xe0\x07\x8f\xa1" + "\xa1\xfc\xa7\xbb\x80\x2b\xfd\x00" + "\xb5\x67\xcd\x95\x27\x7f\x38\x20" + "\xf7\x07\x97\xd3\xe7\xa4\x89\x5b" + "\xce\x07\x44\x89\x3f\xad\x83\x8f" + "\x32\x61\x22\x6c\x94\x5b\x02\xa0" + "\x3b\xc1\x06\xf9\xc7\x63\x95\xc7" + "\x25\xb0\x7b\x4e\x31\x8f\x54\x5f" + + "\x1f\x0c\xde\x4f\x49\x89\x75\xff" + "\x20\xec\xb6\xe5\xbe\x1a\x8a\xbf" + "\x6c\xdb\xe1\x87\xfb\x78\x22\x70" + "\x8f\x65\xed\x35\x7a\xad\x47\xc4" + "\xf2\xcc\xd0\x03\x38\xaa\xd4\x48" + "\x03\x7c\x9a\x81\x38\xb3\xac\x80" + "\xcc\xce\x17\x6e\x9e\xc8\xc7\x9b" + "\x82\x1d\xbe\x03\x8b\x6b\x73\x46" + + "\xaa\x5e\x3b\xd4\x42\xf7\x26\x21" + "\x85\x9b\xa5\xdf\x66\x07\x4a\x05" + "\x45\xfd\x6b\x12\x36\x5e\x0d\x9d" + "\x8f\x8a\x4f\x38\xd7\xfb\xf8\xa1" + "\xcc\xfc\x63\xd5\xf5\x80\x76\x31" + "\x28\xa9\x80\xf2\x55\x50\xca\x48" + "\xcf\x78\xb5\x27\xb2\x81\x0b\xe0" + "\x14\xa5\x94\x29\x18\xd9\xaa\x10" + + "\xc0\xcd\x8b\x35\x1f\x30\x3f\xe6" + "\xf8\x47\x9d\x0a\x99\x9e\x68\x07" + "\x3a\xd4\x43\x4f\x2f\x9e\x68\x1f" + "\x04\x09\x92\x90\x16\x2a\x54\x4d" + "\x07\xa7\xa0\x9c\xd5\x93\xa2\xae" + "\x65\x80\xc6\x8a\x45\xfe\x61\xd0" + "\x8c\x00\x90\x00\x1b\xbf\x33\x10" + "\xb6\x6d\x8a\xc0\x58\x95\x74\x29" + + "\x94\x87\x5d\xc3\xa7\xd3\xe6\x0e" + "\xe5\xba\x56\x03\x58\x65\x2e\x04" + "\xfd\x22\x33\x64\x8d\x69\x59\x9f" + "\x67\x19\xa6\x50\x15\xae\x79\x93" + "\x1e\x98\xc9\xfc\x62\xae\xb9\x64" + "\xc6\x34\x29\x6d\x31\xd6\xd3\xae" + "\xeb\x65\x4e\x5e\x02\xb3\x54\x24" + "\x28\x04\x95\xf9\x47\xf6\x09\xab" + + "\xcd\x71\x6e\xa6\x50\x9e\xc9\x34" + "\xe9\x13\xb7\x75\x15\xf9\x94\x17" + "\xb9\x57\x45\xe0\x90\xde\x40\x1e" + "\x18\x56\x7d\x26\x8b\x8c\x17\x3c" + "\xad\x32\x79\xc9\x7d\x10\x62\x90" + "\xd3\x1b\x31\x81\x52\x1d\x20\xa2" + "\x9e\xb7\x5b\xbc\xeb\x5e\xd6\x35" + "\xd0\xf4\x5c\xb7\xa6\x0f\x61\xef" + + "\x30\xca\xe0\x99\x61\x2a\x70\xc1" + "\xe8\x0a\x56\x99\x6b\x6a\xd4\xbf" + "\x0c\xc3\x1c\x61\xe6\xd5\x6b\xb7" + "\x6a\x98\x5b\x75\x8b\xb7\x0e\x1e" + "\xbd\x4b\x91\x34\x77\x9f\xf3\x7e" + "\xea\x56\x95\xa1\xff\x4c\xc0\xe2" + "\x57\x31\xd5\x69\xce\x8e\x8b\xf7" + "\x65\x04\xe1\xa6\x78\x26\xe5\xd4" + + "\x7b\xa3\x14\xf6\xec\xe5\x40\x3e" + "\xc2\x74\xfa\x06\x04\x9d\xf2\x74" + "\x86\x0d\x28\x61\xd8\x95\xfc\x6a" + "\x9f\x08\xf1\xae\x02\xc7\xea\xba" + "\xab\xb4\x66\x34\x2b\x7d\x2a\xe4" + "\x95\xd5\x5d\xc8\xd4\x19\xf3\x20" + "\x54\xc2\xf5\xd4\x1e\x49\x48\xba" + "\x8a\x43\x31\x33\xdb\xdd\xc1\xed" + + "\x09\x5f\xb8\x31\xd3\xd3\xb3\xc1" + "\x4a\xe6\x8a\xa8\x4a\x35\x45\x0f" + "\xfd\x50\xec\x2f\xd3\x26\xb6\xa8" + "\x4f\x83\x28\xe8\xd4\xfb\xdc\x1b" + "\x39\x25\x52\xcd\x66\x28\x5a\xe4" + "\xb3\x7a\x0f\x81\x32\x47\x9d\xfa" + "\x93\xf2\x05\xc9\xb4\xd6\xc1\xd8" + "\x97\xb5\x61\x34\x47\x80\xac\x10" + + "\x05\x6a\x43\xc2\x36\x92\xef\x11" + "\x3d\x30\x4b\xe5\xb6\x3e\x63\x97" + "\xf1\x0c\x9e\xfd\x94\x49\x17\xd2" + "\x8d\xeb\xd5\x98\x44\xc1\x11\x95" + "\x6c\x2e\x8c\xe7\xc1\xfd\x77\xe5" + "\x77\x65\x4f\xbe\x01\x74\xf3\x8d" + "\xa7\x56\x81\xd3\xa5\x82\x12\x3b" + "\x53\xbe\x16\x07\xeb\x96\x7f\xe0" + + "\x91\x25\x1f\x74\x37\x38\xcd\x29" + "\xe2\x6e\x39\x64\x9d\xc4\xdb\x4b" + "\x8f\x26\x9d\x26\x02\x71\x59\xe6" + "\x05\x63\x9a\xce\xc6\x39\x6b\x89" + "\x45\x02\xb3\x10\x71\x24\x5e\xc0" + "\x72\x00\x13\xa9\xa8\x19\x52\x84" + "\xc2\x9f\x2a\x0e\xb1\x8c\x15\x88" + "\xc6\x91\xf1\x39\x41\xf6\xc6\xcb" + + "\x56\x82\xb6\xd3\x78\x46\xa3\x7e" + "\x31\x08\xd9\x94\xf5\x4a\xfd\x01" + "\x92\x95\x2f\x6f\x2f\x4f\x91\x7c" + "\x08\x55\xb3\xf5\x23\xd6\x09\xba" + "\x1a\x7c\x95\xc1\x74\xdd\xbb\x27" + "\x7c\xd5\x16\xd7\x17\x55\x2a\xab" + "\x52\x85\x3f\x8f\x2d\x29\xa4\xd3" + "\x50\x7c\x04\xc6\xb2\x9c\x97\x46" + + "\x2c\xcd\x91\x6d\x36\x15\xc8\xe2" + "\xe4\xf0\xa3\xda\xea\xbe\xa2\x40" + "\x83\xe0\x41\x24\x59\x7a\x16\xfb" + "\x47\x03\x24\xe9\xe9\x75\x46\x00" + "\x6e\x44\x0e\x84\xff\xaa\x48\x78" + "\x72\x8f\x30\xea\x8f\x25\x9f\x9f" + "\xd9\xfa\x9b\x63\x99\x28\xf1\x50" + "\xf6\x0a\x5c\x20\x63\xae\x39\x09" + + "\x38\x79\x6d\x48\x3e\xde\xcd\xbc" + "\x45\x8f\xea\x81\xea\xc0\xb4\xaf" + "\xda\x52\xb5\xb2\x5c\x2a\xf1\x3e" + "\xe2\xea\x78\x38\x78\xa3\xe6\x6f" + "\x55\x8f\x54\x8d\x98\x53\xb8\x3f" + "\xaf\x33\x3c\x79\xc5\xa3\xaa\x47" + "\x29\xab\x5a\x11\x21\x2d\x4e\x49" + "\xde\xac\xbe\x50\xba\xce\xad\xd2" + + "\xe5\xaf\x95\xf1\x36\x12\x5d\x46" + "\x13\x44\xcd\x2d\x12\x3c\xdb\x03" + "\x5d\xb1\xf7\xc8\x35\x3b\xcf\xf1" + "\x7f\xc1\x4f\xb5\xe2\x30\x8d\xbc" + "\xae\x72\xe6\x40\xb9\xa3\x3a\xe7" + "\x75\x8f\xf3\x02\x8d\x84\x32\xa0" + "\x05\x0a\xb1\x3b\x21\xdb\xa0\x1c" + "\x2a\x90\x8d\x68\x2f\xa7\xe9\xc5" + + "\xbc\xdd\xe4\xe7\x5d\xdb\x67\xf5" + "\x63\x3b\x61\xe7\x28\x9b\x83\xbe" + "\x0d\x04\xa6\x7d\xc6\x77\xcc\x81" + "\x26\x10\x4d\x23\xfb\x88\x2b\x69" + "\x82\x35\x59\xd0\xfa\x35\x9d\x6e" + "\x98\x1b\x05\x56\xfe\x3c\x41\xc7" + "\x52\x23\x6b\xf4\x5e\xed\xce\x3c" + "\x85\x52\xa4\x3a\x21\x16\x6f\xb7" + + "\xe2\x27\xc6\x6f\x14\x75\xb1\xbb" + "\x51\x3a\x57\x91\xc5\x9b\x56\xa0" + "\xd5\x43\x82\x35\x9e\x6d\x01\xa7" + "\x92\x66\x1d\xac\x56\x0c\xac\x0d" + "\x5f\x0d\x59\xda\xb5\x33\x38\x99" + "\x91\x74\x81\xde\x03\x78\x06\xa8" + "\xd0\x75\xbf\x4d\x12\xf2\xb4\x65" + "\xfb\x0c\xf8\xcc\x32\x02\x96\xcc" + + "\x5e\x3c\xcc\xbe\xf7\xf5\xdd\x87" + "\xb9\xf8\x35\x6d\xa7\xaf\xfe\x21" + "\xcf\x77\x1d\x75\x51\x9c\x27\x41" + "\x50\x2b\xc9\x6f\xeb\x26\xc7\x47" + "\xf4\x54\xfb\x4c\xc8\xb7\x18\x4b" + "\xee\xcf\x18\xa6\xab\x8d\xf8\xb0" + "\xc8\xe0\x95\x5c\x00\x9a\x46\x3f" + "\xdf\x39\x18\xd1\xf3\x28\x12\xcf" + + "\x98\x7d\x05\xbd\x54\xcb\x32\x1f" + "\x87\x57\xc4\xe1\x02\x1a\x05\x79" + "\xcb\x32\x76\x7d\x20\x94\x85\xac" + "\x21\x94\x03\xfe\x5b\x26\x8b\xce" + "\x48\x68\x7e\x59\x3e\x0d\x9e\x1f" + "\x18\x09\x64\xe2\x14\xf4\x01\xd0" + "\xc9\x0d\x35\x8a\xcd\x48\x37\xe8" + "\x44\x04\x4f\x7b\x1e\xc8\xdd\x0e" + + "\xd0\xa9\xc6\x45\x8e\x94\x08\x7a" + "\xb7\xd8\x20\x0c\xe5\x3c\x29\xb7" + "\x71\x03\x67\x74\x29\x57\x5a\x71" + "\x40\x45\x72\xae\x98\xe7\xa9\x6a" + "\x42\xb6\x71\xf9\xec\xeb\xd5\x79" + "\xf3\x98\xd4\xaa\xbb\xb2\xd7\x6f" + "\x6b\xd4\x69\x39\xf9\xb6\x46\xff" + "\x55\xe1\xd2\x29\xe3\x9a\x38\xd7" + + "\xcc\x8a\x24\x22\x12\x3a\x08\xb2" + "\x66\xe3\x64\x32\xef\xc0\x6e\x1f" + "\x28\xee\xfd\x5a\x04\xb7\x59\x56" + "\xb5\x0b\x43\xe6\x40\x3a\x82\x7a" + "\x79\x0a\x90\xe1\x04\x2a\x59\x24" + "\x76\x65\xee\xc9\x4a\x9d\xe0\xcd" + "\x4a\xa5\x5e\x4b\x3f\x46\xb6\x52" + "\xa7\x65\xca\xd3\xd3\x9e\xfe\x1e" + + + "\xdd\x06\x54\x30\xbe\x6d\x7a\xe2" + "\x57\x19\x5d\xdd\x7f\xdc\xb7\x8e" + "\x8f\x4d\x7d\x38\x76\x68\x4a\xf5" + "\xe4\x2d\x76\xc7\x09\x94\x47\x9c" + "\x78\x07\xb3\x99\x5d\x5b\x4d\xbe" + "\x82\x36\x79\x6e\x56\x0c\x38\x25" + "\xe3\x40\xc7\xda\xf3\x37\x2d\x60" + "\xae\xe4\x66\x15\xbe\xea\x0d\x14" + + "\x1e\x86\x9a\xc4\x26\x61\xee\xea" + "\x06\x0d\x4f\xe1\x65\x3b\x4f\x02" + "\x17\xfc\x9b\xc6\xe8\xf1\xa3\x51" + "\x81\x63\x68\xa7\xe9\xa8\xc3\xc3" + "\xc8\xd4\x03\xb1\x2c\x75\x00\x34" + "\x6b\xb3\x18\x92\x13\x46\xbc\x02" + "\x4a\x50\x51\x76\xeb\x75\x7f\xc6" + "\xfa\xeb\x2a\xd0\x56\x8b\x84\xd6" + + "\x9b\x26\x82\x17\xdb\x81\x83\x95" + "\x50\xe5\x97\x25\x79\xbf\x34\xae" + "\x53\x51\x38\x5f\x64\x60\x5c\xbb" + "\x48\x80\x08\xe3\xaf\x96\x0e\x6f" + "\x56\x44\x88\x77\x15\x02\x6a\xbf" + "\xa7\x0e\x31\x69\x8c\x68\xb5\xb3" + "\xde\xd2\xfa\x04\x95\x42\xc9\x17" + "\x4d\x6d\x89\x17\xe5\xf0\x20\xe0" + + "\xa9\xa1\xe5\xbb\x8d\x42\xa4\xcc" + "\x67\xbd\x26\x31\x5f\xfd\x87\x81" + "\x26\x58\x10\x48\x3a\x97\x36\x00" + "\xa0\x61\xbd\xb8\x63\x66\x9b\xa3" + "\x08\xa8\x65\x2d\xef\xde\x42\x6d" + "\x19\x6b\x63\x94\x4f\x04\x69\x49" + "\x4c\x56\x5d\xdd\x47\xee\x11\xf6" + "\x77\x30\x87\xd2\x49\x3a\x2f\x7b" + + "\x14\xb2\x82\x0f\xdd\xd8\xb0\x03" + "\xc6\xcb\x03\xf1\xf9\x34\x0c\x46" + "\x19\x9e\xd7\x18\x03\x5c\x2e\xf3" + "\xf8\x17\x41\xa8\xba\x88\x88\x8b" + "\x77\x26\x72\xc0\xdc\x37\x3c\x8f" + "\x27\x0f\x1c\x1c\xe9\x1b\xd2\x10" + "\xc6\xa0\xf7\xe0\x68\x84\x7c\xd4" + "\xe0\xc0\xec\xad\x13\x22\xf0\x9b" + + "\x6e\x7b\xfe\xb7\x60\x41\x55\x97" + "\xb2\x3f\x0a\x40\x9a\x18\x16\x7d" + "\x1e\xca\x28\xe3\xea\x9b\x3e\xd7" + "\xcc\xd8\x93\xe7\x97\x4b\xd0\x0d" + "\xcc\xb8\x6d\x50\x9b\x3c\xc8\xa9" + "\x4c\x81\x38\xcf\xae\x7a\xd4\x5c" + "\xe6\x45\x4b\xb6\x0d\x43\xfc\x26" + "\x84\xea\x18\xd8\x99\x54\x9b\x07" + + "\x41\x29\xac\xe0\x1a\xd2\xb5\x03" + "\x37\x19\xd3\xc2\x54\x02\x9b\x27" + "\xd0\x92\xc9\xca\x52\xc0\x07\x33" + "\xf3\xb1\xa8\xef\x92\xcb\xa7\x6a" + "\xa5\xc7\x37\x0d\x80\x25\x18\x5a" + "\x22\x54\x2d\x34\x37\x0c\x38\x13" + "\x92\xef\xd2\xd5\x66\x2d\xac\x92" + "\xc6\x63\x0c\x03\xc9\x70\x5a\x03" + + "\x61\x18\xba\x71\x85\xb7\x09\x51" + "\x3d\xf9\xc8\xd0\x5c\x2d\xb2\x48" + "\x93\xbb\x33\x86\xa7\x84\xfa\xe8" + "\x08\xbd\xeb\x5a\xba\xa6\xfb\x53" + "\xd8\xa7\xee\xe5\xf3\x7d\xf2\x7f" + "\x58\x71\xca\x68\x96\x87\x1c\x52" + "\x05\x1a\x6f\xce\x3b\x13\xd5\xb9" + "\xe4\xbe\x0e\xfd\x53\xcd\x50\x2d" + + "\x17\xff\x4c\xf7\x33\xa1\xeb\x14" + "\xf2\x13\xb8\xec\x03\xaa\x0a\x24" + "\xee\x5b\x66\x6f\x40\x65\xbb\xcf" + "\x73\xad\x25\xa4\xe4\x1f\x4b\x08" + "\xa6\xf6\x81\xd0\x16\x5d\x9d\x00" + "\x90\x2c\xf8\xee\xe8\x4f\x30\x35" + "\x22\xaa\x9e\xaa\xd5\x46\x03\xf2" + "\xe3\x91\x1c\xac\x07\x9f\xda\x0a" + + "\xcf\xf1\x0d\xb4\x23\x3e\x9b\x7d" + "\xb4\x71\xe9\x94\x73\x73\x33\x59" + "\x21\xf9\x9c\x66\x14\xbd\x57\xbf" + "\x64\x10\x1a\x0c\xdf\xae\x5d\x86" + "\x25\x91\x27\x83\xd3\x0b\xb7\x3e" + "\xab\xda\xec\x34\x9f\x5b\x3d\xbc" + "\xaf\x5c\x75\x5f\x7e\xed\xe3\x91" + "\x02\x6f\x1e\xd4\x54\x9f\x69\x49" + + "\x34\x48\x3e\x0f\x58\x77\x41\x30" + "\xcb\xaf\xa9\x17\xc2\x21\xbb\xfd" + "\xb3\x67\x9a\x2f\x7f\xa1\x6f\x75" + "\xa8\xc1\x45\xa2\x21\x24\x6b\x2a" + "\x91\x22\xf0\x4a\x94\x27\xbe\x64" + "\xfe\x04\x58\x2a\xc6\x65\xe4\xad" + "\xd7\x8f\xf0\xa6\x39\xbd\xff\x8d" + "\x3b\x40\x14\xaa\x4c\xa8\xef\xc4" + + "\x27\x84\x71\x47\x46\x80\xb4\xda" + "\x8b\x0f\x83\x6e\x9b\xff\x17\xdf" + "\x47\x13\x9a\xe4\xe8\x7e\x8d\x40" + "\xae\xd4\xc1\x91\x23\x1e\xc7\x6a" + "\x3c\xd7\xef\x1d\xfd\xb9\xcb\xc8" + "\xc5\xfe\xbb\xbb\x57\x06\x84\x19" + "\xea\xf8\x7e\x9e\xb5\x1c\xdb\x39" + "\x30\x5f\x10\x64\x96\x82\xaa\x78" + + "\x4a\xef\x5f\x06\xc2\xf1\xbe\xcd" + "\xe3\x92\x5b\xfd\x7d\x0f\xe6\x77" + "\x50\x83\x70\x26\xf0\x49\xc5\xd7" + "\xbf\x21\xf1\x34\xd0\x3a\x1b\x20" + "\x14\xfc\x34\x03\xa1\xc2\xca\x5f" + "\xf6\x52\x45\x34\x09\x9e\x9a\x8a" + "\x82\x30\x65\x97\xd3\xa1\xd8\x7d" + "\x89\xf2\xd4\x79\x8f\x73\xc0\x5f" + + "\xba\x02\x35\xbd\x71\x8e\x60\x67" + "\xa0\x75\xde\xb4\x24\x1f\xf4\x4e" + "\xe5\x25\x61\xfd\x5e\xde\x8d\xb0" + "\x3f\x54\x09\xa4\x25\x48\x48\xde" + "\x95\x22\xcc\x65\x98\x8d\x19\x1f" + "\xa2\xdf\x0e\x6e\x71\x37\x8a\x42" + "\xc7\x5f\xf3\xad\xa2\x97\x96\x4f" + "\xc7\xc3\xca\xf7\x79\x3c\xa4\x01" + + "\x0c\x44\xae\x7c\x5b\x8d\x25\xc1" + "\x31\x75\x2b\x40\x41\x8b\xc0\x21" + "\x21\x23\x93\xde\x55\x89\x1a\xf6" + "\xaf\x08\x14\x2d\xf8\xfa\x68\x35" + "\x5b\x96\xcf\x9e\x99\x5e\xb1\x71" + "\x6f\x27\x17\xe9\x48\xd2\x4e\xf1" + "\xe2\xf9\x0c\x82\xa1\xca\xf4\xc6" + "\x7e\x3c\xd8\x18\xb2\x20\x1b\x68" + + "\x17\xf2\x3e\x53\x65\x6d\x9f\x88" + "\x87\x2e\xca\xc3\xe4\xc7\x58\x71" + "\x67\x41\x2b\xdc\xfb\x0d\x67\xfb" + "\x7f\x25\x4c\x84\x01\x0a\x91\x75" + "\x7d\x57\x88\xcf\x07\xbf\x36\xf3" + "\xce\x2a\x5e\xe4\x50\x52\x24\x22" + "\x85\x3d\xa2\x7c\x8d\x2e\xd9\x2e" + "\x58\x2f\x81\x2b\x4c\xbe\xf8\x29" + + "\x92\xba\x67\x34\x97\xf1\x5b\xd6" + "\xb0\x54\x09\xf7\xdb\x46\x9b\x8c" + "\x5d\xf1\x78\x0e\xf3\xa0\xc8\x97" + "\x61\xc9\xa4\x85\x9a\xa6\xf3\xa8" + "\x9b\xce\xe4\x61\x0f\x66\x42\x42" + "\x0c\x79\xa6\x6e\xb3\xaa\x06\xbf" + "\x16\x64\x98\xec\x8e\x6f\x70\xc6" + "\x25\xc2\x9f\x9a\xc1\xde\x56\x9e" + + "\xf1\x03\x51\x9a\x71\x32\xee\x4b" + "\x06\xac\x0e\xf5\xc6\xef\x43\x52" + "\x19\xc1\xdc\x6a\xcb\x22\xe1\xb8" + "\x08\x0a\xb8\xc0\x84\xaa\x7f\x1b" + "\x8c\xd0\xfc\x6d\xbd\xd1\xc3\x32" + "\xde\x27\xe4\x0b\x4e\xec\x9d\x12" + "\x83\x3c\x26\x1d\x9c\x67\xab\x98" + "\xff\x4e\xf6\xce\xb7\x3c\xc8\xaf" + + "\x51\x5a\xdf\x3f\x7d\xe4\x87\x1d" + "\xb0\xca\xc9\x55\x93\x5f\xfb\x7a" + "\x6e\x58\xe0\x89\x8f\xf5\xbb\x91" + "\x09\x37\x84\x0d\x18\xc0\x72\x7c" + "\xdc\xc3\xb5\x99\xfb\xaa\xa5\xa9" + "\xb0\xae\x44\x38\x1d\x0f\x8a\xa4" + "\x82\xe4\x67\xb6\xdd\xb7\x78\x71" + "\x9a\xa5\x23\x6e\xe9\x85\x39\x45" + + "\xa5\xb8\xf4\xea\xe0\x4d\x6a\xaa" + "\x32\x0e\xc6\x4b\xca\xd9\xcf\x68" + "\x70\x5e\xd1\x7f\x01\x4b\x8a\x66" + "\x9d\xc0\x7d\xf2\x4a\x69\xf0\xd9" + "\xcd\x8b\x70\xba\xd5\xca\xc3\xf6" + "\x2a\x5c\xb9\x5b\x69\xba\xd2\x5c" + "\x8f\xa5\xc0\x33\xd3\xc1\x28\xaa" + "\x70\x78\xc7\xab\xe3\x74\xe2\x23" + + "\x4b\x88\xc1\x1c\x2d\xc8\xcf\xec" + "\xb4\x53\x47\x5d\x01\xc2\x5a\xc8" + "\x9f\x09\x8e\x65\xac\xca\xa6\xc7" + "\x90\x73\xb2\x04\x9e\x36\x46\xcf" + "\xea\x67\x64\x50\x49\xd0\xe7\xe2" + "\xcc\xec\xcd\x37\xa2\x63\x1b\x48" + "\x3a\x14\x80\xed\xd8\xab\x29\x40" + "\x88\x0b\xb0\xbc\xc7\xe3\xbf\x28" + + "\x0b\x4a\xe2\x33\x2f\xf8\x57\xff" + "\x79\x50\x56\xf2\x3f\xe2\xbe\x9c" + "\x25\x58\x5f\xeb\x27\x34\x35\x16" + "\x62\xd6\x48\xe9\xc4\xee\x6f\x27" + "\x2b\x03\x10\xda\xc6\x2b\xb6\xd1" + "\x53\x2a\xe7\xf0\xdd\x51\x83\x71" + "\xba\xe7\x20\x24\x76\x20\x45\x93" + "\x8d\x11\x00\x3a\xff\x8f\x36\x96" + + "\x6b\x4c\x7c\x9c\x15\x53\x97\xd8" + "\xf7\x9a\x40\xd7\xc0\xa3\x3a\x60" + "\xfb\x32\x71\x00\x0c\x3d\xd5\xb8" + "\x38\x92\x84\xa6\xf7\x2a\xd1\x68" + "\x79\x92\x5d\xbf\xe7\x07\x06\xbe" + "\xce\x74\xda\xaa\x55\x00\xa5\x9a" + "\xcb\x8c\x7e\xba\xcb\x79\x10\xe8" + "\x5e\xff\xf4\xa5\xd1\x71\x0c\x61" + + "\x61\xa6\xb6\xe3\xbf\x81\x47\x18" + "\xf7\x79\xd2\xe6\x1d\xcb\x51\x77" + "\x62\xb6\x9e\xc5\xd6\x95\xff\xf8" + "\xa7\xde\xd3\x58\xb7\x90\x6d\x18" + "\x54\xf7\xb4\xdf\xc1\xb6\x4b\x0e" + "\xdc\x01\x28\x2b\x6b\xf5\x5c\x5c" + "\x4d\x56\x54\x1f\x52\xe4\x61\xc5" + "\x13\x7f\xdd\xf0\x60\x8c\xfb\xb4" + + "\xb3\x81\xfc\x29\x0b\x20\x4c\xac" + "\xc1\x87\x1d\x17\x9f\xe0\xc3\xeb" + "\x9e\xaa\x81\x14\x30\x95\x79\x91" + "\xfa\x14\xe1\x92\xe1\x92\x1b\x05" + "\x7f\x53\xb5\xec\xe9\x92\x8f\xdf" + "\x83\x74\x0c\x29\xcc\xb2\xb1\x44" + "\x16\xb0\xde\x2a\x5a\x45\x11\xa7" + "\x2c\x0c\xa1\x81\x56\x68\x4b\x96" + + "\x7a\x56\x88\x40\x08\x59\xf4\x73" + "\x61\x4a\x21\x1f\x0e\x28\x6b\xeb" + "\x3d\xc1\xf0\xca\x34\xdc\x9a\x8c" + "\x80\xfb\x61\xf5\x38\x29\xd1\x39" + "\xb4\xdf\x6e\xbc\x5e\x3a\xdc\xb2" + "\x0e\x21\x4d\xfe\xb1\xb1\x85\x74" + "\x72\xae\x86\xe1\x00\x04\x2e\x06" + "\x88\x3b\xeb\x6e\x5c\x2d\xe3\x91" + + "\xfa\xde\x34\xb1\x85\xae\xe9\xc7" + "\x75\xd4\xb2\x1b\xd0\xb1\x73\x60" + "\x0d\xc0\x63\x28\x5e\x61\xad\xb9" + "\xc4\x4a\x5f\x52\x3d\x49\x29\x9e" + "\x4f\xcf\x9a\x4e\xea\x1d\x2b\xc3" + "\x8d\xb8\x0d\xa5\xc8\x01\x1f\x3e" + "\x6c\x91\xda\x04\xea\x70\x5d\xb0" + "\x3e\x80\x65\xd8\x0a\x0d\x4b\x71" + + "\xee\xaf\x79\xe0\x0c\x92\x45\x59" + "\x1f\x83\x89\x67\xa0\x17\x6e\x68" + "\xe5\x5a\x4a\xb7\xe8\xbe\x66\x59" + "\x46\x8d\x25\x1e\xa2\x73\xa6\x38" + "\x95\x1c\x14\x83\xf2\xc1\x1c\xbd" + "\x86\xe4\x96\x0e\x4f\xcf\x2e\x3b" + "\x78\xfc\xe5\x74\x96\xa8\x3a\xcd" + "\x7a\xfa\x82\x24\x0c\xc1\x5e\x41" + + "\x10\xf5\xc3\x6e\x31\x5a\x20\x85" + "\x75\x04\x98\xd2\x14\x4a\x7e\x2c" + "\xfd\xeb\x30\x6f\xc0\x19\x3c\xde" + "\x44\xe6\xb7\xd4\x38\x1f\x1c\xdb" + "\x4a\x36\xce\x5d\x75\x1a\x29\xfe" + "\xe3\x5b\x8f\x05\x3c\x2a\xb2\xb7" + "\x8c\xa3\xfe\x37\x02\xc3\xd2\x2c" + "\x17\xbe\x17\x2e\x7a\x96\x30\x29" + + "\x44\x0a\x5b\xa1\x5e\x79\x0f\x02" + "\x58\xa9\x58\x89\xd7\xc8\x37\x8f" + "\xb5\x75\xb6\xa4\x9b\xe8\xb7\x63" + "\xea\x1a\xc3\x0f\x0c\x0c\xfb\xb4" + "\x2e\x1f\xff\xa7\x39\xe6\x95\xed" + "\xfb\x14\x96\x61\xa3\xf5\x80\x98" + "\xab\x51\x71\x94\x02\xff\xb6\xde" + "\xdb\xdc\x68\xa8\x8c\x11\xc5\x5b" + + "\xed\x7a\x9f\x34\x91\xcb\x97\xf1" + "\x20\x84\xca\x8f\x00\x5a\x2b\x3b" + "\xd8\xf6\xaa\x23\xe8\x5e\x17\x7c" + "\xb6\x32\xaf\x35\x21\xf4\xdc\x54" + "\x1e\x56\xd6\x27\x07\x43\xa1\x0b" + "\xe2\xb1\x75\xd1\xe4\x5e\x9d\x87" + "\xb5\x7d\x80\x99\x73\x36\xc4\xc7" + "\xcd\x5b\xd5\x9c\x55\x44\xa5\x77" + + "\xd9\xff\x33\x21\x45\xb2\xb9\xfb" + "\x20\x1a\x0f\x83\xf1\xb2\xa8\x39" + "\x2a\xf5\xa1\xd5\x7d\xc9\x4b\x48" + "\xf8\xdd\x0e\xa4\x56\xbf\xae\xd6" + "\xc6\xda\xcc\x76\xcb\x7a\x25\x32" + "\x27\xff\x86\x15\xec\x36\x4d\xaf" + "\xd1\x7d\xde\xf8\x63\x88\xaa\x8e" + "\x16\x7c\x64\x88\xcf\xd5\x45\x00" + + + "\x9d\x97\x05\xc0\x74\xd5\xf3\xa6" + "\x50\xe3\x40\x6a\x42\x2b\x07\xc2" + "\xf9\xec\xe2\x8d\x56\xc1\xa5\xfc" + "\x4e\x34\x15\xa5\x5b\xbf\xc8\xa8" + "\x4a\xf1\x4d\x11\x55\xe5\xae\x97" + "\x6b\xec\xc5\xfd\x4d\x4a\x37\xd4" + "\x18\x54\xa8\x2c\x8f\xc2\x4c\x75" + "\x78\x1f\xc4\xd3\x27\x9e\xcb\x71" + + "\x39\x5c\x60\x03\x79\x50\x10\x89" + "\x6c\xc9\x42\xa1\x9e\x3d\x84\xf0" + "\x84\x36\x92\x16\x34\x49\x74\xf3" + "\x93\x28\x0a\xfa\x2f\xaa\x2c\x73" + "\x70\x01\x16\x61\x70\xc2\xe8\xb2" + "\xa3\xba\x7f\x43\xcc\x88\x27\xc3" + "\xac\xa3\xed\xa6\x8e\x81\xcd\x39" + "\x07\x2e\x2b\x9e\x39\x42\xe9\xe2" + + "\x2a\xe5\x60\x02\x9b\xd3\x67\x69" + "\x25\x33\x65\x90\xcc\x85\x25\xd4" + "\x54\x79\xca\x21\x05\xd6\x9b\x0d" + "\xb3\x57\xed\x81\x77\x08\xa2\x4f" + "\xbe\x0b\x4a\xe3\xf8\xef\xc1\x60" + "\x64\xef\xf6\x84\x0c\x04\xb0\x56" + "\x83\x84\xaf\xb1\x24\x2b\xbe\x28" + "\x14\x16\x53\xf5\x63\x81\x27\xb2" + + "\x1c\xac\x22\x59\x45\x75\xf2\x8d" + "\x63\x3f\x2b\xa5\x5c\xef\xb3\xa7" + "\xc4\x57\xde\x71\x14\xb2\x77\x8e" + "\x8b\x00\x4c\x83\x10\x2c\x68\x31" + "\x31\x5d\xd5\x4b\xf0\x24\x68\xc7" + "\x71\x1c\xb6\x17\x86\xc0\xd1\xb6" + "\x9d\x08\xa5\xc2\x03\x09\xdb\x31" + "\x3f\x5d\x4e\x18\x72\x21\x09\x9c" + + "\x38\xc6\x0c\xc0\x5b\xed\x7c\xdd" + "\xc2\x8f\x27\x61\xeb\x15\x20\x1a" + "\xd6\xf8\x37\x6a\x88\x52\x8e\x2e" + "\xad\x33\x99\xe7\x6f\x78\x57\xc4" + "\x1a\x21\x51\x2c\xce\x4c\xfe\xb3" + "\x98\x04\xc2\x24\xb2\x10\x9b\xad" + "\xe5\xb5\x8d\xd2\x4f\x7a\xd8\x90" + "\xc3\x2f\xca\x3a\x05\xd1\x8c\x69" + + "\x6d\x53\x1b\xe9\x07\x2d\x11\x4f" + "\xd6\x09\xba\x9e\xf2\x82\xb9\xce" + "\x6f\x39\x7c\x19\x2c\x7b\x15\x3c" + "\x24\xeb\x66\x7b\x41\x2d\x3c\xe2" + "\x37\x0d\x33\x3f\xd9\x57\x0c\x48" + "\xeb\x8d\x10\x79\xa1\xc8\xa4\xb3" + "\xe5\x9c\x19\xcb\xde\x88\x23\x70" + "\xd4\xa8\x44\xb9\x11\x92\x01\x0b" + + "\x36\xb3\x0b\x84\x92\xa6\xf2\x24" + "\x7b\xfa\x69\xa6\xdc\x3b\x35\x7c" + "\x00\xc3\xc9\xde\xfc\xd6\x20\xda" + "\x17\x4f\x3a\xa1\x2f\xbe\x5f\x62" + "\x28\x73\xc1\xdb\x1a\xb6\xb1\xa2" + "\x21\x56\x51\xa9\xbf\x65\x89\x00" + "\x46\xff\x20\xc6\x39\x09\x69\x49" + "\x1c\xe9\x17\x87\x7d\xd2\x2d\x18" + + "\x97\x39\x6c\xea\x35\x50\xce\x5a" + "\xef\x0b\x61\xc2\xaa\x9a\x25\x54" + "\x39\xdd\x80\x3c\x3f\xbb\x18\xef" + "\x39\xfa\xc3\x5f\x5b\xb9\x10\x69" + "\xee\x9a\xe0\x43\x10\xf5\xe2\xfc" + "\x65\x56\x67\xa7\x9f\x6c\xd5\xce" + "\x61\xdb\x72\xd8\xac\x65\xe2\x10" + "\x69\xce\x9f\xae\x2e\x81\x82\x69" + + "\x98\x09\x80\xce\xc6\x11\xbe\x29" + "\xd9\x60\x03\xb9\x52\x17\xbb\x72" + "\x90\xd5\x4a\x5a\x97\x31\x19\x2c" + "\xc0\xdb\xc1\x9f\x48\xf5\xa2\x2b" + "\xe0\xeb\x90\xe4\xbb\xee\xe4\x7f" + "\xc0\x11\xae\x7f\xcd\xa4\xa0\x12" + "\x37\xba\x03\xe9\x81\xcf\x97\x71" + "\xd8\x6d\x1c\xde\xa8\x4a\x7d\xcf" + + "\x4c\x68\xd5\x3f\xf4\x6b\xaf\x92" + "\xa1\x0a\x36\x80\xcf\xee\x26\x2b" + "\x82\x6a\x54\x00\x30\x0f\x96\xbd" + "\xfe\xd8\x9a\xf5\x43\x3c\x7b\x40" + "\xba\x82\x9c\x24\xfe\xe5\xca\x86" + "\x4c\x74\x63\x24\xc7\xae\x0f\x9e" + "\x72\x62\x91\x94\xe8\x51\xf5\x87" + "\x15\x06\xeb\x6c\x44\x93\x3f\x03" + + "\x84\x2e\xe8\x8b\xd1\xb0\x5e\x1e" + "\xef\x2f\x58\x7a\x0e\x7f\x96\x89" + "\xfa\x21\xe9\xa6\xd5\x87\xf6\xbc" + "\xba\x09\x7a\xd3\xf3\x4c\xee\xdf" + "\x65\xc4\x93\xb4\x65\x69\xf0\x94" + "\x30\xc0\x35\x76\x1c\x9a\x8b\x63" + "\x9f\x5e\xf0\x66\x64\x78\x66\x76" + "\x25\xa7\x4d\xc0\x08\x68\xaf\xcc" + + "\xfc\xcc\x8f\x76\x90\xb6\x2e\xca" + "\x62\xb3\x35\xb8\x7d\xd3\x02\xf4" + "\xce\xfc\xfd\xe2\xd0\xc0\xfa\x0e" + "\x90\xd9\x38\xb6\xef\xcd\xc9\xef" + "\x8b\x9a\x66\xd1\x72\x2b\xf1\x2a" + "\xbd\xcc\x74\x57\xbc\x36\xc5\x33" + "\x0e\x87\x34\xfb\x09\x19\xb2\x30" + "\xca\x5a\xf2\x7d\xf7\xa2\x8f\xc3" + + "\xf5\xf3\x81\xbf\x2b\xf0\xc5\x74" + "\x81\x45\x7e\xaf\xae\xa5\x25\x05" + "\xae\x54\x3c\x43\xba\xaa\xd2\x88" + "\xc5\x56\x6a\x80\xdb\x75\x97\xed" + "\x7d\xb3\xed\xc0\x8a\x73\x20\xd3" + "\x51\x1f\xcc\x66\xee\xb6\xfd\x25" + "\x76\x0d\x60\x10\x17\x1d\x66\xac" + "\x76\xed\xd1\xbd\xf3\xc1\x1e\x93" + + "\xf1\x43\xee\x19\x62\x1d\xc1\x65" + "\x97\x9d\x82\x60\x3e\x7c\xd5\x5c" + "\xe8\xe6\x4b\x98\xa3\x91\x6c\xd2" + "\xbd\x53\x0c\x8b\x09\x93\x8d\xf0" + "\xea\xe4\x16\xc0\x5b\x9e\xbc\x94" + "\x2b\x3d\xd4\x11\x39\x68\x91\xd3" + "\x55\x11\x70\x73\xd7\x5a\x6c\x88" + "\x15\x07\xb0\x20\x26\x76\x37\xe0" + + "\x59\xba\x80\xaa\xec\xc9\x01\x7f" + "\x51\x8e\x53\x68\x1a\x41\x83\x30" + "\xaf\x28\x81\xe8\xf1\x70\x03\x97" + "\x4b\xc1\xde\x91\xdb\xc3\x5c\x62" + "\x07\x31\xac\x01\x6c\x66\xf9\xfe" + "\xc3\x7a\x05\xd5\x77\xd5\xa8\xb2" + "\xf7\x5d\xbe\x92\x99\x62\xf2\xb0" + "\x24\x39\x35\x00\xe5\xc8\x79\xf5" + + "\x7a\xed\x41\x13\x93\x3d\xfa\xb8" + "\x49\x9d\xb5\xa7\x2c\x27\x23\x42" + "\xa4\xc4\xb8\x83\x47\x19\xcb\x3d" + "\xe4\x02\x13\xed\x01\x3c\x41\x4e" + "\xce\x44\x7e\xe1\x27\x91\x99\x6d" + "\xfb\xad\xb3\x33\x75\xbf\x86\xee" + "\xca\x96\xaa\x25\xe6\x2f\x90\xf6" + "\x7d\xe4\xaa\xe5\xe4\x40\x35\xb7" + + "\x8c\x15\x4a\x1b\x7b\x1d\x80\x32" + "\x69\xa3\xe2\x27\x9e\xc9\x71\xe5" + "\x97\xf1\xd9\x10\xc0\x76\xcb\x40" + "\xae\xc0\x67\x31\x89\xc2\x08\xc3" + "\xf2\x58\x79\xeb\xd3\x9d\xef\xa6" + "\xb1\x79\x08\x30\xfc\x6d\x22\xa7" + "\x36\x06\xdf\x7e\x62\xb3\xd0\x6c" + "\xed\x7e\xc3\x7b\x6c\xce\xfb\x4e" + + "\x21\x90\x69\x8d\x05\x2a\xf9\x75" + "\xe3\x66\x25\x77\x79\x4c\x6d\x58" + "\x3a\xd2\x1a\x76\xf1\xa5\x8c\x37" + "\xac\xa8\x65\x14\xfc\x86\x0d\x65" + "\x51\xa2\x2b\x84\x57\xd4\x4e\x7a" + "\x33\x49\x23\x42\xe6\xe3\x65\x6b" + "\x57\xd6\xaa\x31\xb7\x43\x15\xaf" + "\x69\xc3\xfe\xcb\x98\xfe\xce\xa4" + + "\xfb\xbe\x47\x9f\x90\xda\x87\xb5" + "\x13\x2d\x31\x41\xfb\xe9\x62\x65" + "\xfe\xce\xf1\xef\x59\xea\x91\xa6" + "\xf6\x4c\xfc\x05\x7a\x47\x30\xcc" + "\x3d\xfd\x0f\x0b\x61\x24\x63\xa1" + "\x56\x59\x35\x5b\x3b\x6f\xf1\xa1" + "\x24\xec\x24\x42\x53\x8d\x14\x5b" + "\x2a\x01\x77\xf9\x7b\x4e\x83\xdc" + + "\xbc\x9d\xc6\xb2\x75\x5e\xfc\x7b" + "\x6c\xda\xc3\x03\x29\x7a\xa7\x3a" + "\x71\x02\x91\xca\x3c\xf0\x0d\xde" + "\x55\xdc\x06\x78\x4a\xca\xd5\xcb" + "\xcb\x76\xb4\x6d\x07\x58\xca\xe1" + "\x1e\xa3\x37\x5f\x62\x5d\xe1\xfd" + "\x16\xf4\x1a\xf4\x20\xf5\x9a\xf4" + "\xb5\x2d\x34\x7d\xb1\xc5\xc5\x96" + + "\x9b\xeb\x4c\xeb\xb7\x43\x5c\x15" + "\x1a\x37\x77\x4e\x10\x30\x99\x2e" + "\xaf\x43\x5d\x67\xda\x87\x29\x1d" + "\x72\xfd\x99\x85\xc0\xc1\x2b\xef" + "\xb2\xf6\x42\x93\x7b\x4b\x89\x96" + "\xf0\x71\x8e\x7c\xf2\xad\x1e\x20" + "\xfc\x3e\x1f\x4a\x9f\x9d\x47\xf3" + "\x04\x97\x2a\x70\x42\xa7\xf8\xe0" + + "\x0c\xa4\xeb\xb3\xb6\x44\xfd\xea" + "\xd0\xe0\xc1\xc1\x29\x9f\x73\xf9" + "\x5e\x50\x9d\x61\x1a\x47\x91\x00" + "\x3e\x26\x7c\x9d\x96\x9c\x5f\xc1" + "\x33\xbe\xaf\x83\x85\x72\xe4\x5b" + "\x92\xe0\xf1\x04\xaf\xd6\xb6\xa3" + "\x11\x9d\x1a\x75\xb9\x26\x65\xe7" + "\xd2\xe4\x4a\x9a\x6d\xb2\xc5\x2e" + + "\x8d\xfb\xf6\x02\xd9\xf4\x66\xeb" + "\x64\x21\x91\x96\x61\xc5\x63\x40" + "\x00\x30\xef\x80\xc1\x50\x70\xeb" + "\xf0\xb3\xa5\xea\x33\x1c\x8d\x28" + "\xd8\x6f\x80\x07\xd6\x68\x7c\xe8" + "\x0f\xf5\xbb\x4b\xd5\xf9\xf7\xb2" + "\x27\x66\x8d\xac\x3a\x2f\x97\x25" + "\x3b\xc1\xe8\x10\x74\x77\x54\xf8" + + "\x60\x4a\x2b\x87\x6c\xef\x50\xcc" + "\x1b\x52\x13\x46\xa4\x34\x2a\xab" + "\xd1\x15\x3e\x98\x90\xc1\xc5\x39" + "\x12\x55\x90\x59\xdf\xe5\xdd\x61" + "\xf3\x75\x22\x9f\x21\xf6\x17\xe4" + "\x4b\x89\x1d\x45\xb6\xc8\x50\x07" + "\xaa\xbd\xb0\x78\xb9\x4a\xb0\x75" + "\xbd\x89\x85\x45\xd4\x9f\xfd\x3b" + + "\xb6\x20\x91\xee\x30\x3e\x01\xf1" + "\x3e\x74\xa4\x23\x93\xaf\x51\x2b" + "\x9e\x4d\xd1\x48\xae\xff\x96\xea" + "\x32\x1d\x8a\x69\xbe\x0d\xdc\x71" + "\xa4\xcc\x80\x01\xd2\x62\x49\x91" + "\x63\x89\x56\xc3\x77\x06\xe6\x1a" + "\x44\xc4\x7b\x43\xb1\x27\xf2\x8c" + "\x7a\x2c\x96\xc9\x3b\xc8\x50\xc6" + + "\xc4\xcf\x7c\xfe\xdd\xc7\xc2\x23" + "\x48\x9d\x92\x1b\x9d\xc8\x25\xf9" + "\x33\x3c\x78\x06\x4b\xf7\x60\x44" + "\x5a\x47\x90\xa5\x49\x8d\x2c\xac" + "\xa0\xbb\x07\xb8\x07\xb4\x40\xfb" + "\x3a\x8f\xff\x69\x2d\x36\x1e\x9d" + "\xa4\x64\xef\xcb\x81\x96\x3e\xa3" + "\xb2\xb4\x2f\x33\xfa\xe5\xec\x67" + + "\xe3\x10\x9f\x73\x9b\xa9\x00\x69" + "\x25\x59\x52\xff\xa9\x1c\x34\xc3" + "\x41\xd0\xe2\xa9\x26\xa6\x18\xee" + "\xdd\x0d\x58\x29\x85\x36\xa8\xa5" + "\xcd\xe3\x7d\x9d\x81\x0c\x47\xf3" + "\x9c\xcf\x62\x20\x86\x25\xf0\xed" + "\xb0\xed\x10\xc0\xfa\x22\x35\xf4" + "\xae\xb1\xa4\x13\x35\x41\x31\x30" + + "\x4b\xb9\x22\xdb\x2a\xe0\x92\xc7" + "\x5b\xa4\xea\xa1\xe9\x8a\x3d\x99" + "\x63\x1c\x1e\xcd\xd3\x6c\xad\x8a" + "\x8a\x68\xce\xc5\xa7\x9c\x52\x89" + "\x53\xa2\x72\xe5\xaa\xe3\xce\x2c" + "\xfb\x1e\xa2\x02\x38\x64\x2b\xe0" + "\x58\x03\x43\xc9\x6e\x1b\x09\xa7" + "\x04\xb5\x7d\x9d\xfa\xb1\xd1\x06" + + "\x33\x47\x74\xc4\x32\x6d\x84\x58" + "\x34\x9e\x9f\x37\x71\x7c\x51\x40" + "\xca\xf6\x0e\x13\x5f\x65\x65\x2f" + "\x3f\x50\xf3\xf1\x88\x44\x6e\x52" + "\x76\xa9\xe4\x7e\x17\xbd\x67\x84" + "\xd1\x63\x13\x92\x13\xc9\x9d\x1d" + "\x41\xe0\x69\xb0\x33\x4c\xd2\xd8" + "\x51\x7f\xdf\x2c\x0a\xda\xb5\x5e" + + "\x4f\x99\x7b\x19\xb1\x3c\x0f\x1c" + "\xe9\xea\x43\x28\xc5\xa6\x95\x3c" + "\xa5\x7e\x09\xa6\xc9\xff\x66\x77" + "\x67\xb8\x23\xd7\x93\x40\xea\x7b" + "\xf9\x78\xb3\x4d\x73\x1f\x8e\xb4" + "\xac\x77\x7b\xe3\x00\x5b\x02\x70" + "\x46\xad\x24\xaf\xe7\xc8\x3d\x94" + "\x85\x0a\xd0\x16\xac\x15\x8a\xb9" + + "\x04\xb0\x43\x27\xba\x38\xdc\x3a" + "\xee\x15\x44\x33\xf7\xf4\xc7\xb1" + "\x5a\xd0\x62\x1e\x8f\xdf\x43\xea" + "\xb6\xa3\x76\x9d\x05\x89\x61\x32" + "\x46\x0f\x3a\xa2\xb5\x0b\xbd\x2f" + "\x8c\x91\x01\x6a\xdb\x71\xc9\x5b" + "\x94\x3f\x74\xb4\x4a\xd9\x01\x78" + "\x2b\xe2\x6a\x67\x5e\xf6\x4d\xb9" + + "\x4c\x89\x95\xaf\xab\xbf\xfc\xaa" + "\x41\x22\x6b\x27\x07\xdc\x9b\x7b" + "\x8b\xa4\xdd\x5b\x62\x83\xf9\xea" + "\xdf\xb4\xfc\xa3\xf2\xfa\x77\x59" + "\x5b\x4b\x2c\x05\xef\x42\xd0\xbe" + "\xf0\x91\x75\x06\x71\x7f\xe8\x9f" + "\xc7\x4e\xf2\x22\xca\x73\x9c\xc8" + "\x1b\x9f\x4a\xe6\x9e\xfa\x37\x7d" + + + "\x0f\x0c\x75\x0a\x88\x64\x7a\xcc" + "\x83\x8e\x54\x4e\xe3\xcf\xba\x39" + "\x05\x0f\x11\x0c\x76\x8c\x41\x3d" + "\x88\x15\xf1\xb1\x4c\xaa\x4d\x3e" + "\xff\x69\xfc\x5f\xb5\xe7\x33\x27" + "\x27\x31\x05\x92\xbc\x47\xf1\x46" + "\x94\xdf\x22\xd7\x34\x24\x5b\x88" + "\x7c\x6b\xfc\xe6\x65\x4f\x44\x6a" + + "\xa8\x6e\xf1\xc3\x5a\x46\x1a\x7a" + "\x1c\xd1\xf1\xb2\x1d\x46\x5a\x11" + "\x72\xa1\x68\x6c\x95\xdd\x67\x47" + "\x98\x46\x3a\xd1\xeb\xf2\x92\x33" + "\xc7\xcd\x26\xe5\xcd\x9c\xa9\xc7" + "\x81\x2b\x29\x22\xdc\x7f\x53\x8e" + "\x98\x91\xd3\xa6\x69\xcf\xd8\x76" + "\x2d\x85\x46\x24\x43\xff\xc5\xff" + + "\xbd\xdf\xae\xbd\xf4\x16\x0b\x6d" + "\xed\x6c\x74\x86\x60\x32\xfd\x23" + "\x17\x3e\x4b\xff\x2f\x1d\xfb\x8b" + "\xc8\x14\x9c\x01\x2d\xec\xf2\xc7" + "\x0d\x4b\x10\x45\xf2\x32\x08\x3e" + "\x7e\x2b\xea\xad\xfb\xda\x00\x5f" + "\x0f\xfb\xfb\x99\x66\xcf\xe5\x29" + "\xda\x7c\x82\x61\x23\x97\x4f\x26" + + "\xe6\x67\x05\xa9\x7e\x4f\xb1\x97" + "\xb7\x5c\xae\xb6\xb7\x57\x32\x51" + "\x3d\x90\x10\x9f\x3c\x4a\x45\x85" + "\x24\x37\xbc\x69\xad\xc9\xd2\xd8" + "\x44\xcb\x29\x6b\x24\x93\xda\x38" + "\xac\xcb\xc8\x77\x1d\xa2\x40\xb5" + "\x42\x8e\x91\x01\x35\xe4\xbf\x9b" + "\x4e\x61\xc3\x56\x7a\x70\xfa\xff" + + "\x7f\xc2\x0b\xe3\xf3\xa2\xb1\x6e" + "\x11\x65\x83\xb0\x5a\xc0\xf0\xe5" + "\x0e\xab\x65\x49\xbf\x1b\x74\x4d" + "\xbd\x4b\x46\x83\xca\x41\xec\xfe" + "\x9f\xb0\xd0\x99\x5f\x70\xca\x1a" + "\xfa\xa5\x2d\xf4\x56\xcc\xd6\xc5" + "\x31\xb9\x52\xcc\xdd\x4e\x96\x49" + "\xd8\xd8\x84\xc8\x15\x96\xe5\x8a" + + "\xb7\x53\xe3\xd4\xf1\xe3\xe4\x0c" + "\xa0\xb0\x46\xef\x14\x8a\x2d\x06" + "\xfd\x73\x4b\x57\xab\xd5\x08\x64" + "\xfd\x3f\x27\xd3\xc9\xd1\x41\xbc" + "\x00\x78\xe7\x6b\xe7\xe1\x38\x35" + "\x31\x50\x65\xc5\x37\x8b\xfe\x71" + "\x1a\x33\x9b\x6b\x21\x16\xd9\x1c" + "\x73\x8f\x38\xbb\x0b\x5d\x82\xad" + + "\x8a\x86\xf8\x39\x7b\xb5\x34\xf6" + "\xaf\x69\xcc\x75\xd4\x4f\x7f\xe2" + "\x6e\x49\xd5\xd0\xcb\x58\x7e\xa4" + "\x7f\xe0\x23\xd3\x3f\x79\x26\x8a" + "\x49\xf3\x30\xfa\x72\x9b\x1a\xc6" + "\x34\xd1\x96\xb6\xc9\xd9\xc9\x94" + "\xd1\xa6\x80\x58\xa8\xec\x2b\x79" + "\x95\x99\x03\xaf\x45\x46\xcc\xbd" + + "\x19\x62\xb7\x1c\x5b\xe0\xc2\x56" + "\x7e\x7e\x56\x71\x91\xbf\xc0\x0e" + "\x10\xc9\xc4\x61\x86\x6f\x07\xe7" + "\xd9\x04\xbc\xba\x5b\x08\x7b\xd6" + "\x6a\xa9\x93\x5e\x59\x04\xb9\x9f" + "\x9a\x24\xdc\xfb\xea\xc1\x26\x75" + "\xb7\x0b\xdd\xec\x67\xd3\x44\x0d" + "\x95\xd6\xc0\x9d\x17\x99\x39\x95" + + "\x3c\x6c\x79\x8c\xe5\xf8\x7e\xce" + "\x7a\xe5\x66\xdd\x84\xae\xda\x9a" + "\x33\x7f\x22\x45\x3e\xe1\x4a\x78" + "\x57\xe7\x85\x2a\xb8\xc5\x46\xb0" + "\x1f\x63\x37\xec\xae\x50\xaa\xb7" + "\x58\x07\x30\x3b\xca\x4f\xdc\xbe" + "\x0b\x70\xc9\x0a\x7e\x56\x82\x0f" + "\xd2\xf8\xf5\x4f\xd4\xd9\x71\x10" + + "\x18\x0d\x24\x9e\xe9\x0e\x36\x61" + "\x66\x44\xb9\xb4\xac\xdc\x7c\x05" + "\x5c\x32\xe5\x2f\xd1\x7c\x66\xe7" + "\x3b\x4e\x97\x21\xb5\x97\xa2\x1f" + "\x76\x3d\x08\xdb\xe7\x81\x40\xfa" + "\x15\xbd\x06\xf2\xe6\x3b\x99\x31" + "\x8c\x9f\xc1\x14\x9b\x26\x49\x89" + "\x57\x23\xd9\xa9\x72\x8d\x46\x21" + + "\x11\x28\x1a\xe5\xc4\xf6\x9e\xd0" + "\xb9\x66\xfb\xb8\x2b\x86\xf6\x39" + "\x99\xaa\xdf\x22\x8d\x7f\xe7\x64" + "\xac\x8a\xb0\x61\x44\x50\x10\x7b" + "\x32\xf3\x7d\x4a\x4c\x4e\x70\x71" + "\x5b\x01\xfe\x2f\x34\x34\x97\xd0" + "\x0e\x02\xd3\x08\x44\xaf\x0e\xab" + "\x7a\xb9\x63\xed\x9e\x90\xb1\x28" + + "\xec\x06\xc5\xa4\x83\xc5\xcb\x2c" + "\x97\xfe\xac\xd1\x88\xd1\x7e\x95" + "\xa2\xae\xf1\x12\x33\xd8\xae\x8b" + "\x2d\x36\x25\x83\xb4\x6c\x2a\xef" + "\x43\x5c\x19\x8e\x42\xde\x0d\x13" + "\xc6\x50\x60\x0e\x5a\x02\x42\xc8" + "\x5d\x6a\x68\x08\xa7\x72\xa9\x2d" + "\xa8\xb4\x08\xe5\xa1\x99\x29\xb5" + + "\x4f\xcd\xad\xcd\x82\xa8\x3f\x2f" + "\x95\x19\x63\x5f\x59\x68\xef\xa4" + "\x6f\x76\x31\xe5\xf9\xa2\x2c\xe5" + "\xd3\xc1\xe2\x57\x30\x5c\xaf\x20" + "\xb8\x94\x1e\xe5\xf6\x28\x48\x1e" + "\x4f\x5d\x2f\x1a\x75\xa1\x00\xf9" + "\xa0\x58\x2c\x39\xb3\xad\x31\xe8" + "\x66\x58\x6e\x1b\xca\x90\x5a\x4c" + + "\xbd\xa8\xa5\x10\xb9\x90\xf0\xd9" + "\xda\x64\x68\x09\x49\xd2\x91\xca" + "\xc1\xdb\x67\x3f\xbe\x93\x6a\x8e" + "\x4c\x76\xf4\xf5\xba\x6f\xae\xac" + "\xa0\x11\x14\xd2\xe0\xc6\x63\x15" + "\xd8\x4a\x0a\xda\x7f\x78\xfa\x28" + "\x30\x80\x8c\x90\x1c\x49\x24\xd5" + "\x07\x5f\x79\x4c\x0e\xba\x57\x12" + + "\x7c\x82\x82\x61\xa8\xcb\x3d\x5f" + "\x52\x72\x7e\xbd\xdd\x48\xa4\xd1" + "\x15\xb8\x93\xf4\xfc\x96\x8f\x2d" + "\x5f\xa9\x0a\x3b\x26\x4c\x0a\xba" + "\x7f\x00\xa0\x63\x40\x51\xa1\x88" + "\x46\x58\x9c\x6a\x5e\xc2\x64\x95" + "\xca\xcb\x0f\xdc\x0f\x7b\x4d\x5a" + "\x0e\x74\x8a\x3f\xa3\xda\x75\x22" + + "\x54\x97\xca\xce\x67\x91\xf4\x83" + "\xa0\x39\x79\x4b\xf6\x2c\x6d\x42" + "\xbf\xd0\x3f\x72\x55\xe3\x55\x25" + "\xe2\x44\xf1\xc4\x06\x6d\x6e\xa9" + "\x61\x0e\x88\x87\xdd\xa8\x68\x47" + "\xd5\xe4\x08\xe5\x15\x38\x54\x15" + "\x15\x5e\xb6\xb1\x72\xe7\xd7\x09" + "\xa0\x2f\x30\xac\xd6\x9d\x43\x63" + + "\x6b\x08\x61\x04\xcc\x91\x95\x15" + "\x51\x6e\xe6\x95\x94\xaa\x95\xb6" + "\x31\xd5\xde\x79\x67\x94\x4c\x2d" + "\x79\xbe\xc2\x89\xba\x82\x24\xbd" + "\x19\xbf\x0b\xa2\x8a\x65\xe2\x8e" + "\x17\x79\x24\x32\x8a\x52\x00\xc0" + "\x45\xe8\xea\xff\x4a\xbe\x24\xd9" + "\x8b\x2c\x99\xed\xeb\x2b\x31\x51" + + "\xc2\x35\x4e\xc1\x2f\x80\x3f\xb9" + "\x3c\x33\x41\x43\x7c\x5b\x73\x71" + "\x62\xf3\xd4\x16\x04\x51\xa2\x03" + "\x8e\x3c\x43\xbf\x9b\x06\x4d\x3f" + "\x7c\x5a\x8f\xf7\x01\xae\x83\x0d" + "\x07\xed\x4e\x7c\xbe\xff\xa8\x50" + "\x83\x0f\xe1\x76\x06\x89\x4f\xc7" + "\xe1\xf8\xda\x9d\x66\x09\x08\x7d" + + "\xd9\x2b\x75\xdc\x58\xb9\x01\x3a" + "\x45\x5d\x21\x0c\xc2\xdb\xab\x2b" + "\xc1\x41\x16\x13\x9a\xd7\x89\xe6" + "\xd4\x5e\xe0\x80\xda\xf0\xe8\x48" + "\xc4\x70\xbb\x77\xeb\x5f\x50\x4b" + "\xf7\x7e\x05\xb6\x2b\x3e\xbd\xef" + "\xa5\x3c\x60\xce\x2d\xe2\x83\x75" + "\xc7\x70\x5c\x2c\xf2\xb1\xe3\xfb" + + "\xcc\x04\x8e\x69\xe1\xf8\x1d\xb1" + "\xc8\x05\x90\x16\x03\xe2\x7b\x87" + "\x79\x61\x3c\x4f\x8c\x9e\x74\x32" + "\x05\xfc\x53\x78\x0a\x9d\xbc\x2d" + "\x37\xd9\x54\x94\x93\x4f\x7d\x18" + "\x1b\x0e\x80\xb4\x9d\xce\x82\xe6" + "\xe8\x68\x5e\x16\xd8\x9a\x12\xa9" + "\x5b\x78\x7f\xbe\x35\x97\xe2\x0f" + + "\x5a\xe3\xe5\x29\xf0\xec\xc1\x8e" + "\xb3\xc2\x45\x86\xe5\x68\x31\x2f" + "\xb2\x4c\xf9\xc7\x62\x73\x29\xe9" + "\x39\x0b\xc9\xd1\x66\x14\xbf\x4f" + "\x2a\xae\x0b\x92\x56\x76\x4f\x3e" + "\x72\xb1\xbe\xf1\xb9\x04\x5d\x80" + "\xb4\xd4\xdb\xdb\x08\x72\x9a\x72" + "\x53\xca\xae\x87\x56\xe4\xad\x1a" + + "\xb7\x02\x9e\x5b\x0c\xf4\x03\x53" + "\xe8\x04\xee\x35\x92\x96\x7c\xa3" + "\x2b\x63\xd6\x34\x20\xcc\x46\x5f" + "\x5b\x54\xac\x96\xb2\x72\xef\x55" + "\x62\xb0\x91\x7b\x1f\x5c\xec\xab" + "\x21\xe8\x33\xbb\xc7\xe1\x79\x0a" + "\x17\x41\x9f\x3a\x28\xb4\x04\xbb" + "\x5a\x47\x2a\xfd\x8f\xf2\xe1\x0d" + + "\x08\xa5\x34\x19\x54\x1f\xff\xb0" + "\x1a\xf3\xbb\x04\x76\x39\xe1\x19" + "\xb4\xa6\x17\x37\x03\xe6\xa8\xb2" + "\xb9\x2c\xf1\x0e\x5d\xe4\x01\xd6" + "\x8e\xe9\x15\xb5\xf5\x0a\x3f\x56" + "\x9b\x4f\x98\x33\xb6\x9d\x12\x9b" + "\x65\x4a\x7e\xa4\x2f\xba\x4a\xe3" + "\x82\x9d\x3f\x9e\xd1\x82\x6f\xb5" + + "\xb4\x34\x44\x3a\xcf\x9c\x01\x31" + "\xdc\x54\x79\x1a\x11\x81\x45\xa3" + "\xa7\x72\x49\xe3\x0d\xc8\xda\xa9" + "\xdd\xb8\xf6\x74\x54\xd0\x43\xb0" + "\x1a\x7b\x13\x11\x9e\x31\x1c\x02" + "\x3f\xc0\x5c\xed\xce\x54\xa7\x00" + "\xd4\x5a\xea\xcb\x94\xc7\xa2\x0a" + "\xb6\x15\xc0\x70\xf4\x67\x3e\x09" + + "\x86\x9b\x20\xb1\xfd\xef\x03\x02" + "\xbf\x6c\x9d\xb1\xed\x63\xf0\x21" + "\x5b\x27\x0f\x98\x76\x34\xf5\x59" + "\x80\x5e\xac\xb7\xd7\x56\x24\x20" + "\xc9\xed\x00\x49\x5f\xc0\xa8\xe5" + "\x86\x1e\xf0\x70\xb4\x8e\xc0\x04" + "\xce\x98\xcd\x1d\x24\xc2\x4a\xf7" + "\xdb\x30\xe8\xe2\x0c\xcc\x77\x7e" + + "\x6b\x3f\x7e\xc9\xe9\xfe\xcd\x72" + "\x61\x74\xda\xb6\xb4\xca\x0b\xc1" + "\xb9\x06\x98\xb5\xfc\xd2\x02\x3b" + "\x47\x6f\xde\xa1\x89\x5e\x18\x85" + "\xd4\xc4\xb6\x0e\x1f\x93\xe6\x39" + "\x04\x5b\xfa\xd4\xbd\x40\x44\x4d" + "\xb8\x7e\xbe\x34\x6e\x78\x18\x54" + "\xbc\x59\x72\x9d\x21\xe5\x80\x63" + + "\xde\x7e\x74\xa9\x34\x72\xe3\x74" + "\x13\x10\x1b\x36\xb1\xfb\xc9\x4f" + "\xef\x57\xf3\x3c\x73\x33\xb5\xe7" + "\x93\x41\x1c\x99\x2c\xdd\xa2\x6a" + "\x7a\x91\x70\xa7\xd2\xe4\x87\x78" + "\xcb\x24\x0d\xc2\xb4\x09\x18\xdd" + "\x3e\x2d\x9c\x8e\xc3\xd7\x4c\x00" + "\xbe\x0a\x97\xa9\xab\x5b\x7c\xc7" + + "\x10\xd7\x98\xd5\x51\x03\xac\x20" + "\xa4\x4d\x3a\xcb\x66\x41\x2c\x27" + "\x1f\xde\x71\xca\x1a\xfe\x82\xdb" + "\x0f\x4b\xf5\xd8\xf2\x79\x6e\x74" + "\x9b\x3e\x57\x4b\x36\xc7\x7f\x6e" + "\x40\x50\x4b\xfd\x46\x3f\xd0\x75" + "\x7b\xd8\x98\x0b\x6d\xc3\x1c\x5c" + "\xa1\x2d\x47\x1f\xf1\xa3\x3b\x51" + + "\x7f\x23\xaf\xc3\xaa\x7e\x92\x52" + "\x67\x87\x39\xd7\x65\x60\xa0\xfa" + "\x0b\xce\xc6\x97\xb4\x72\x2e\x04" + "\x61\x23\x9f\x0a\xc4\x0c\xed\xda" + "\x4a\xbb\xc1\x2f\x1c\xe1\xc2\xdd" + "\xf8\x9e\x1a\x0c\x77\xa5\x1d\x63" + "\xbf\x72\x02\x68\x44\xfe\x4c\x8a" + "\xc3\x5c\xfb\x62\x72\x9f\x6b\xc7" + + "\xdd\x77\xb1\xab\x26\xaf\xd0\x79" + "\x64\xd5\x91\x78\x68\xb5\x2a\xf8" + "\x73\x21\x23\x72\xa9\x68\x67\x2b" + "\x19\x66\x1f\x8c\xb0\x3b\xbb\xef" + "\x58\x83\xd1\xa6\xdb\x11\x9c\xb2" + "\x3a\x6d\x91\xb0\x97\x27\x9e\x51" + "\x90\xe2\x88\x91\xf0\x18\xdc\xd4" + "\x7f\xca\xb0\x98\xe3\x86\x8e\x64" + + "\xe3\xaa\xb3\x38\x45\x81\x8f\x24" + "\x34\x43\x20\xbc\x64\x58\x34\xb5" + "\x24\x75\x12\x1d\xbc\xb5\xd6\x66" + "\xd3\x72\xf5\x14\x0d\x08\x12\xe3" + "\xeb\xaf\xab\x16\xa7\x15\xed\x13" + "\xbe\x67\xa9\xdb\x27\xce\x18\x6f" + "\x2d\x55\x08\xef\x26\xe8\xc9\x96" + "\xe0\x63\x2b\xbe\x06\x1b\x19\x2c" + + "\xb5\x38\x3c\x98\x45\x31\x9d\x85" + "\x8b\xbc\x7a\x63\x6c\x17\x4f\xb1" + "\xe6\x7b\xff\xca\x9d\xfb\x93\x27" + "\x5a\x6a\xa6\x35\x5f\xa5\xe5\xeb" + "\x59\xdc\x87\x9f\xcd\x1d\xec\x7c" + "\x60\xf5\xdb\xfb\xd3\x5c\x59\x7c" + "\x57\x32\xeb\x26\x22\x3b\x54\x5b" + "\xfd\x35\xc9\xc4\x46\x06\x08\x69" + + + "\x96\x16\x53\x1d\x38\x52\x34\xb9" + "\x69\xde\xcd\x88\x00\x1c\x20\x57" + "\xc7\xaf\x86\x9a\x51\x22\xe9\xdd" + "\xa8\xce\x35\xbd\x95\x38\x04\xe3" + "\x0d\x97\x55\x85\xe1\xc1\x08\x76" + "\x5e\x93\x35\x25\xa9\xdf\x67\x82" + "\x8b\xa3\x2e\x32\x57\x0a\xc6\xd4" + "\xb5\xf8\x4e\x80\x77\x79\xbf\xe0" + + "\xb5\xdb\x94\xc0\x68\xea\x33\x62" + "\x10\xd4\x68\xd9\x2e\x06\x7d\xb7" + "\x2d\x00\xb3\x58\xbc\x9b\x71\x3e" + "\x58\x9d\xc4\x3d\x3d\xdd\xe7\x68" + "\x58\x5e\x3a\x01\x40\x57\x82\x8d" + "\x1b\x3c\x9e\x3c\x47\x17\x31\x21" + "\xab\xb6\x99\x7c\xa7\xa2\xb0\x0c" + "\xf2\x88\xf8\xc2\xb3\xa3\x48\x5c" + + "\xca\xd4\x27\x29\xe1\x4b\x5c\x4c" + "\x8e\x84\x8f\x51\x16\x3f\xf2\xb0" + "\xcb\x7b\x75\x0c\x22\x89\xf7\x84" + "\x96\xeb\x5d\x32\xbb\x1c\xbd\x35" + "\x0a\xe1\x0d\x7d\xfb\x86\xb1\xbd" + "\x85\x96\x2c\xb2\xe3\x50\x73\xd0" + "\x41\xc6\x45\xef\x3e\x39\x95\x3f" + "\x44\x6d\x7b\xd0\xf1\x0f\x87\xb8" + + "\xf3\x24\x17\x99\x91\x3e\x91\xc7" + "\x86\xd6\xcb\x39\x9c\x79\xda\x5e" + "\x1e\xfc\xd4\x63\xc7\x95\xb5\xdd" + "\x54\xed\x4f\xac\x0b\xb8\x63\x6b" + "\x16\xb5\x5f\x7e\x69\xfc\xa0\x6e" + "\x64\xc9\xf1\xd0\xba\x08\x77\x73" + "\xa5\x2c\xa9\x11\x5f\x74\x28\x96" + "\x7a\x96\x86\x9a\x58\x79\xf3\x61" + + "\x9f\x65\xa2\x47\x65\x0a\xcf\x64" + "\xcb\x0b\x38\x33\x30\xf4\x18\x12" + "\x74\x8a\xd9\x0f\xe4\xe4\x1d\xfc" + "\xb8\xed\x9e\xf0\x8f\xec\xc4\xae" + "\x83\x60\xc5\x95\xe1\xb5\x6d\xde" + "\xa1\x16\xdc\x07\x56\xb0\x07\x33" + "\x97\x70\xd4\xc0\x86\xc1\x82\x14" + "\x66\x3a\x4c\x51\xac\x19\x83\xa0" + + "\xb3\xe6\x79\x09\x61\xfd\x20\x53" + "\x23\x07\xd4\x93\xe5\xd3\x0b\x1d" + "\xcc\xba\x80\xaa\xfc\x06\xc0\x0a" + "\x15\x25\x00\xd2\x0e\xc6\xd9\xb1" + "\x92\x0b\x78\xaf\xd0\x7e\x0e\x61" + "\x31\xce\xa9\x80\x6e\x44\xbf\xf5" + "\x4b\xb5\x20\x3c\x1d\x01\x1c\x44" + "\xc3\x96\x15\x19\xa1\x6d\xf7\x77" + + "\xb4\x94\x40\x4d\x2b\x5b\x2e\x97" + "\x5f\xde\x96\x5e\x4f\x95\x49\x4b" + "\x59\x0d\x87\x4f\x0a\xe4\xa8\x6c" + "\xef\x8d\xa6\x45\x6f\x88\xe2\x9e" + "\x13\x9a\x43\xc4\xec\x60\x02\xae" + "\x1f\xb7\xcf\xb4\x3e\xcd\xae\x45" + "\x20\x76\x32\x4e\xb6\xd9\xc5\x50" + "\xf3\x2c\x18\x86\xdb\xda\x0a\x47" + + "\x72\x50\x66\xaa\x2c\x9b\xf3\x9a" + "\xef\x24\xd3\xef\xa4\x2f\x32\x78" + "\x31\xbd\x27\xc3\x94\x33\x15\x3d" + "\xb0\xda\x29\x31\x71\xf2\xd5\x81" + "\xf5\x27\x80\xf4\x42\x0c\x2e\xc7" + "\x17\xe7\x36\x85\xbc\xcd\x40\xaa" + "\x0f\x9d\x36\x2d\x7a\x65\x5a\xf4" + "\xe6\x74\x7f\xea\xc4\xbf\x3b\xb0" + + "\xf0\x69\x7c\xf3\x89\x07\xb7\x4a" + "\x2d\x80\xc5\x01\x78\xd8\x26\x32" + "\x97\xf4\x0d\x36\x4c\x42\xe7\x4f" + "\x50\x0d\x89\x5f\xe5\xd4\xae\x9e" + "\xc6\x29\x37\xdd\x5c\x99\x8e\x20" + "\xf3\xea\x0d\xd0\x5c\xbd\x43\xf7" + "\x7d\x84\x61\xf1\x10\x13\x5a\xfe" + "\x25\x3f\x1a\x94\xa2\x75\xe7\x34" + + "\xea\x42\x6a\x9b\x42\xd5\x04\x7a" + "\xb9\x41\xaf\x3d\x85\x7e\x59\xfa" + "\x89\x0b\x6b\x72\x27\xec\x58\x4c" + "\xde\x43\x0d\x03\x6a\xb1\x8e\xed" + "\x57\xcf\x9d\xec\xe1\xe5\xe1\x65" + "\x81\xff\x7c\x69\xc1\x70\xa7\xb7" + "\x22\x2b\x6e\x9f\x8f\x91\x6d\x1e" + "\xb7\x82\x4e\xc6\x9a\x7a\x27\x7c" + + "\xcf\x35\x1f\x7b\xc8\x69\xc8\xe5" + "\x37\xd2\xd1\x55\x37\x69\xfa\x29" + "\x44\x9c\x57\xde\xee\x74\xc5\x05" + "\x0c\x59\x6d\x33\x2b\x91\xbb\x45" + "\xeb\x4d\x7d\x77\x85\x2d\x17\x5d" + "\x67\x65\x6c\x7b\xa9\xcc\x37\x1a" + "\x8a\x3a\x37\x25\x3a\x43\xa1\x1c" + "\x3a\x35\x77\x1c\xa8\x94\x3c\xd2" + + "\xed\x8d\x73\x0d\x18\xc4\xa8\x46" + "\x29\x57\xde\xe0\xb0\x5b\x1a\x6f" + "\x75\x16\xa8\x8b\xb9\x30\x02\xf1" + "\xd4\x33\x2b\x11\x0c\xf3\xc6\x32" + "\x62\xfb\xff\xd8\x9d\x12\x59\x75" + "\x05\xbf\x59\xb4\x47\x1b\x28\x6a" + "\x76\x67\x3b\xfa\x3a\xbd\xc1\x77" + "\x3a\x97\x29\x78\x80\xb3\x09\x07" + + "\x61\xa3\x35\xc9\x7c\x22\x89\x79" + "\x7e\x0a\x9a\xe3\xaa\xf8\x17\xfd" + "\xba\x63\x91\x26\x86\x5e\x5c\x2e" + "\xf4\xea\x63\xc6\x78\x8e\xc9\x07" + "\x6e\xa3\x2e\x42\x9a\x20\xe8\x64" + "\x82\x08\x6a\x4c\x91\xb3\xe8\x1b" + "\x5e\xa5\x4f\xec\x03\x45\xac\x4b" + "\xdf\x68\x78\xad\xca\xa7\xee\xba" + + "\x47\xcb\x36\xda\xc1\xe0\x75\x08" + "\xf0\x10\x02\x1e\xcb\xb7\xf5\xfd" + "\xc8\x87\x37\x3a\x4d\x7e\x0c\x7e" + "\x1f\x74\x1c\x2b\x26\xf5\x43\xf0" + "\x2d\xd7\x74\x6d\x00\x1b\xdf\x76" + "\xa9\x5b\xb4\x38\x73\xdf\x14\x05" + "\x7a\x79\x6b\x0a\x3e\x7c\xcf\xae" + "\x39\xac\xea\xdd\x85\xb2\x30\x5e" + + "\xdb\xe3\x69\xac\x9c\x33\x69\xff" + "\xbd\xd6\xe9\x59\x3c\xc8\xec\x74" + "\x82\x84\x0a\x82\x37\x7b\x23\x67" + "\x23\xfa\x2d\x07\x35\x30\x3a\x94" + "\xb8\xbd\x48\x8f\xd2\x10\x42\x6e" + "\xf4\xc7\xec\x2e\x16\x75\x51\x88" + "\x7f\x18\x2a\x63\xf4\xc5\x05\x0b" + "\x4c\x1d\x7d\xd9\x5e\xfb\xfd\xca" + + "\x05\x65\x32\xa3\x32\xb2\x26\x8c" + "\xbf\x41\x1d\xee\x72\x92\xd6\x38" + "\xfa\x2a\xe3\xff\x3e\x45\x59\x04" + "\x87\xea\xb3\x7c\xad\x43\x81\xce" + "\x66\xb6\x6a\x7e\xfa\xc1\x2e\x93" + "\x64\x62\x28\x22\x30\xd2\xd2\x6c" + "\xed\xf8\x36\x67\xfe\x46\x9a\x45" + "\xbb\x85\xca\x9e\x00\x0d\xbf\x50" + + "\xb4\xeb\xa2\x3d\xba\x6b\xc1\x06" + "\x3e\x7c\x55\x32\xbb\x21\x5b\xf3" + "\x11\x67\x07\x30\x12\x23\xb1\x95" + "\xf0\x11\x76\x1b\x76\xa0\x3a\x87" + "\x61\x6d\x3a\xea\x26\x90\xf6\x31" + "\x4c\xbe\xa6\x42\x6b\xb8\xc9\x7a" + "\x02\x28\x6c\x4b\xc7\xd7\xb5\xd3" + "\xe0\x1d\x28\xab\xac\x94\x48\xcd" + + "\xa5\x38\x52\x60\x7d\x8f\xc7\x15" + "\xab\x96\x84\x44\x42\x78\xd8\xe9" + "\xc1\xac\x10\xd2\xd0\x75\xcf\xcf" + "\xe2\x14\x8c\x5c\x29\xf2\x48\x29" + "\xcb\xf0\xda\xe8\x6d\xd7\x1f\xe8" + "\x00\xe8\x3b\xa0\xe4\x11\x2d\xd0" + "\x0c\xd3\x78\x87\x51\xf3\x4d\x0c" + "\xcb\x39\x51\x96\x96\xbc\x82\x34" + + "\x68\x1d\x81\x49\x01\xd7\xa0\xef" + "\x4e\xa0\xa1\x1e\xe5\xc8\xf6\xe4" + "\x40\x76\x23\x82\xfd\xe1\x90\x59" + "\x96\xdb\x80\x1d\xf9\x25\xa2\xef" + "\xda\xcc\x96\x3a\x95\x1c\x43\x17" + "\x92\xa1\x3f\xfc\xc1\xaa\x1b\x46" + "\xb4\x84\xc1\xbb\x07\xf4\xe2\x3b" + "\x9c\xd3\x05\x0d\x1d\xde\x76\xd7" + + "\xec\x21\x7a\x87\x52\x58\x82\x0b" + "\x94\x7a\x53\x0f\xa7\x14\x04\x30" + "\xa2\xa6\xa9\x21\x40\xba\x1c\x3f" + "\x00\x3c\x94\x76\xee\x4e\x82\x50" + "\x5d\xba\x3c\xf8\xec\xfc\xdb\xa0" + "\xc0\xf3\xb4\x93\x48\x81\x53\xf9" + "\xd7\x4d\xf2\x48\x62\x41\x74\x61" + "\xdd\x09\xfb\xe4\x4d\xd6\x22\x53" + + "\x05\xa7\x73\xdc\xd2\x9e\xb0\xf1" + "\x6e\x1a\xa1\x01\xc8\x00\x2b\x14" + "\xc9\x32\xa1\x98\xb0\x84\x64\x72" + "\x7a\x56\xe1\x26\x63\xef\xb5\xf3" + "\x03\xfc\x4b\x57\xd0\xd2\xbe\x43" + "\x2f\x72\x8f\x76\x38\x1e\x79\x74" + "\xd8\x7e\xe9\x4c\xb3\x9f\x18\x7a" + "\x43\x5f\x8a\x16\x96\x2c\x9b\x2b" + + "\xbc\x8b\x44\x8a\x27\xcf\xb6\x56" + "\xda\x51\x52\xc8\xdf\x98\xa8\x0c" + "\x24\x9b\xe7\x36\xd8\xca\x82\x90" + "\xa7\x51\x8e\x1a\xd3\x9e\x7b\x2e" + "\x02\xc8\xe1\x43\x8a\x31\x7d\xdc" + "\x9d\x68\xf8\xcb\x23\xe5\x50\x47" + "\x1a\x1b\x07\xf0\x72\xa0\x87\x98" + "\xc1\xfd\x4b\x81\x87\x0f\x09\x52" + + "\xb9\x6e\x73\x8d\x2e\x85\x21\x48" + "\x6b\x1e\x4c\x54\xd3\x28\xa9\x29" + "\x86\x05\x80\x77\xae\x11\xa4\x1a" + "\x93\x57\x0a\x1b\x7b\x06\x4d\xe9" + "\xad\x46\x5e\xa6\x4b\x8b\x9d\xb5" + "\x04\x18\x94\xcd\x87\xba\x62\x3c" + "\x1b\xe6\x20\x99\x78\x4b\xb5\xfd" + "\xac\x1a\x18\x0a\x84\xf2\x23\xe9" + + "\xf3\x25\x93\x3d\x84\x73\x44\x57" + "\x84\xcb\x71\xf3\xd0\xf2\xbe\xa9" + "\xc5\x36\x1e\xa6\x8b\x18\xd2\x77" + "\x72\xdf\x02\xc6\xd7\xa7\xd6\xbb" + "\x0b\xbc\x61\x8f\x02\xa9\x3a\xba" + "\xa1\xb6\xd0\x6e\xed\x85\x90\xf4" + "\x98\x82\x6e\xae\xd6\x25\xc6\x8b" + "\x1d\xc0\xe9\xa2\x1d\x0b\x2b\x83" + + "\xa0\xca\xd1\x70\x82\x5c\xb4\xc2" + "\x57\xb5\x4a\x72\xd0\x41\xce\x44" + "\xfd\x71\x82\x13\xac\x4b\x98\x57" + "\xc8\x08\x36\xcb\x34\xc9\xe0\x67" + "\x03\xf7\x55\x54\x45\xfa\x88\xc8" + "\xb0\x02\x7b\x72\xb4\xb8\xc5\xe9" + "\xa4\x30\x71\x7c\xf0\xf0\x3e\xdc" + "\x0c\x27\x09\x4b\xa3\xbe\xe4\xd9" + + "\x6e\xbc\x96\x61\x19\xf2\xeb\x5b" + "\xfd\x7e\x09\xef\x6b\x73\x66\x0e" + "\x3a\x29\x87\xea\xb8\xf3\x28\x11" + "\xde\xfc\xdd\x6a\x05\xe4\x98\x29" + "\x61\xc9\x16\x5d\xb8\x31\xcc\x55" + "\x56\xf0\x18\x24\xe1\x34\xa4\x87" + "\x19\xe8\x9f\xdc\xcc\xaa\x94\x2e" + "\xc6\x90\x64\xa5\xc1\x86\xa4\x94" + + "\xb3\x2b\x8d\xcb\xd4\x83\x4d\x8a" + "\xfd\xb1\xd2\xff\xa8\x6a\x79\xea" + "\xf6\x79\xca\x04\x51\xab\x75\x65" + "\xcf\x86\x6b\xc4\x36\xd5\xf0\xf4" + "\x58\x6b\x0e\x67\xd9\xc5\x1e\x46" + "\x08\xd1\xae\x0e\xf8\x53\x50\x70" + "\xf7\x16\xdd\x14\xce\x5b\xf4\xda" + "\x65\xcf\xb2\xc4\x49\x2d\x6f\x40" + + "\xd1\xce\xf0\xf1\x47\xc4\x37\xa3" + "\x2b\xdd\x92\x94\x93\xc7\x0c\x80" + "\xfa\x8e\xa0\xbe\x1d\x15\x93\x4b" + "\x1e\x74\x0a\xde\xf8\xf3\x0c\x82" + "\x13\x7d\x0f\x1c\xdc\x82\x19\xff" + "\xca\xe6\xdd\x84\x60\x19\x92\xef" + "\xe3\x6e\xf9\x45\x72\xd9\xd7\x1a" + "\xc7\xa0\xde\x29\xbe\x8d\x9c\x31" + + "\xf8\xf5\x2e\xe8\x80\xdc\x1c\x6d" + "\xb3\x7f\x1c\x2f\xf0\xf9\x5d\x09" + "\x88\xd8\xcf\xa3\xb9\x34\x7f\xc8" + "\xe1\x08\x02\x34\x95\x70\xd7\xd5" + "\xcb\x51\x88\x91\xe4\xec\x1a\x4a" + "\x42\x71\x2b\x60\xc1\xf5\xb1\xd7" + "\x82\x4f\x52\xc6\x13\x98\xd3\xf0" + "\xb5\x1d\xb0\x6b\xae\x6e\xd9\xf6" + + "\xc8\x9e\x25\xde\x5b\x38\xf2\x1f" + "\x0d\x7b\xf6\x30\x6a\x83\xb0\xf6" + "\xff\x1c\x66\x06\xb0\x65\xcc\x04" + "\x5c\x0f\x23\xd4\x58\x63\x7e\x46" + "\xd3\xd3\xbe\x2d\x80\x8c\x46\xce" + "\xa6\x0d\x92\xf1\x62\x42\x98\x7b" + "\x9f\x47\x37\x15\x42\x57\xd2\x34" + "\xe1\x8d\xbb\x87\x8c\xa8\x8a\x5c" + + "\x6a\xa5\xaf\x54\xa1\x68\xf7\x32" + "\xe5\x84\xf1\xfa\xa3\xec\x1e\xa5" + "\x68\x74\x8c\x61\x44\xcb\xce\x20" + "\xc0\x2c\x86\x87\x5f\xd1\x34\x34" + "\xf6\x5d\xf5\xae\x11\x38\x3c\x71" + "\xf0\xf8\xe3\x81\x49\xc0\xd7\x2c" + "\xbe\x99\x2f\xff\x39\xd4\x68\xee" + "\xa6\xa6\x5d\x2b\xe7\x4e\xb6\x79" + + "\x9b\xb9\x82\x7b\x71\x38\xea\xd3" + "\x24\xb6\x0e\x47\x4d\x2d\x92\x75" + "\x66\xd4\x95\x3b\x54\xec\x66\x8f" + "\x46\xe3\xe1\xbe\xcc\x73\xe6\x66" + "\x9a\xb8\xf2\xb5\xc4\x67\xfe\x6a" + "\xd3\x5c\x0e\x29\xe6\xc1\xe9\x3d" + "\xda\x2a\x0a\x31\xb6\x8b\x27\x8c" + "\x3b\x32\xdb\x0b\x84\xa3\x0f\x42" + + + "\x9b\xc4\x24\x64\x79\x96\x6f\x64" + "\xc9\x41\xc2\x67\xe8\xdf\x88\xf8" + "\x49\x8b\xf6\x24\x93\x4b\x2d\xe1" + "\x20\xdf\x71\xa5\xd8\x62\x6b\x9a" + "\xcb\x83\x94\x17\x6d\xb2\xb4\x81" + "\xe2\xfa\x11\x95\x32\x96\x6f\x66" + "\x1f\xa5\x3a\xd5\xe4\xb3\x81\xd2" + "\x16\xbd\x3d\x7f\x65\xa7\x96\x7f" + + "\x2b\xf6\x1a\x05\x7c\xd3\x53\x85" + "\x96\x44\xf9\x0b\xeb\x98\xa9\xe9" + "\xa1\x9a\xd5\xb0\x9f\x4f\x84\xe0" + "\x13\xb8\xaf\xe6\x58\xd5\x3f\x98" + "\x04\x98\xd6\x65\xca\xc0\x70\x96" + "\x2d\xff\xa5\x6e\xde\x22\x2b\x73" + "\x3b\x62\xd8\x5f\xa9\x0b\x64\xd7" + "\x82\x17\x35\xa6\x63\x91\x61\x9f" + + "\x4f\xdd\xef\xbd\xe0\xb4\x67\xf1" + "\x01\xe4\x66\xf3\x65\x84\x95\x69" + "\xc0\xbe\x3b\xa7\xab\x68\xa3\x5a" + "\x21\x0c\x24\x7b\x09\x87\x14\x12" + "\x06\x90\x96\x18\x33\x32\x8c\x37" + "\xd1\x53\xfe\xe1\xce\x73\x4d\xcb" + "\x61\x43\x0c\x13\x0e\xa8\x50\x5f" + "\x2b\x21\xf5\x7e\x51\x59\x7f\xd6" + + "\xc0\x38\xad\x8c\x08\x81\x2f\x33" + "\xe2\x8a\xd6\x6b\x90\x7e\x1b\x47" + "\xa3\x27\x8e\x0d\xb2\x3f\xac\x56" + "\x0d\x4b\x6b\x13\xdb\x60\x46\xb5" + "\xe4\x8d\xfd\xa6\x11\x1e\x3a\x12" + "\xef\x99\x77\xa3\xea\xff\xdb\x44" + "\x7c\xc1\x6a\xce\x77\xb9\x40\x45" + "\xef\xac\x60\xaf\xa8\x73\x51\x49" + + "\xb0\xea\x73\x45\x43\x37\x44\xeb" + "\x31\x60\xac\xd1\xfb\x0d\x57\x11" + "\xfd\x9a\xdd\x44\x5b\xb4\xd9\xf7" + "\x31\x72\x06\x22\xdd\x6a\x06\xb8" + "\xb4\xf0\xa3\xf8\xd8\x2a\xf9\x15" + "\xa2\xe2\xac\xe0\x99\x48\x0e\x9e" + "\x80\x8b\xb3\xfa\xad\x0a\xcd\xbd" + "\x52\x00\x02\x17\xe9\x6a\x50\x46" + + "\x9d\x39\xca\x8f\xf7\x69\x9a\x42" + "\x63\xbb\x07\x02\xd2\x27\x9e\xfe" + "\x82\xf5\x88\x87\xd6\x5e\x65\xec" + "\x6e\x5f\xb7\xad\x48\xd7\x26\xa4" + "\x6d\xc6\x81\xca\x02\x5c\x69\x18" + "\x25\xd4\x31\xa5\x27\x8d\xfb\x84" + "\xba\x48\xff\xde\x56\x89\x3a\x3a" + "\x47\x22\x6d\x76\x56\x0d\x1d\xaf" + + "\x5c\x4b\x2c\x35\x65\x95\x05\x5a" + "\xe2\xc3\x0b\x59\x31\x15\x26\x49" + "\x5f\x9f\x6f\xf6\x21\x75\x9f\x80" + "\x9b\x4a\x0a\xc7\xbf\xf6\xae\x2b" + "\x61\x35\xed\x09\x65\xfa\xe6\xe7" + "\x0c\x23\x4b\x98\x33\x02\x37\x11" + "\x69\xdc\x4c\xd0\x9b\x65\x51\x21" + "\x16\xd4\x07\xf0\x63\x3c\xb8\xbd" + + "\x82\x2a\x1c\x39\x4d\x28\xbb\x9e" + "\xe8\x08\x83\x15\x63\x48\xdd\xbc" + "\xca\xed\xf1\x83\xec\x16\x6f\x00" + "\xc8\xc6\x5d\x69\x37\x2c\x3e\xa1" + "\x87\x7a\x05\x4a\xf0\x56\xb7\x2a" + "\x98\x8f\xb4\xa6\x00\x55\x76\xa8" + "\x44\x1c\x65\x68\xce\xfa\x52\x42" + "\x02\x5e\x76\xe1\x0b\x54\x2b\xa5" + + "\xf0\x7f\xa3\x5c\xa8\xa1\x35\xcb" + "\x8f\x1c\x2f\xcd\x1c\x4f\xa0\xe1" + "\x12\x61\xa2\x15\xce\x16\x88\x23" + "\x7e\x17\x5b\x09\x11\xa1\x06\xe2" + "\x49\x41\x42\x8a\x04\xb6\x10\x3c" + "\xfb\x2c\x75\x74\x67\xf5\xa3\xc6" + "\xb8\xdb\xf1\x47\x7a\xa3\x16\xbf" + "\xfb\x3d\x1a\xd3\x9a\x2f\x37\x7c" + + "\x2a\x4d\x0b\xc2\xb5\x05\x2d\x12" + "\x67\x2a\x66\x0c\xf5\x9c\x65\xff" + "\xe9\xc9\xff\xe8\x28\xc1\x57\xed" + "\x83\x76\x98\x9e\x85\x15\xbb\x0f" + "\x2b\x9a\x31\x47\xf2\x0d\xd7\xad" + "\x70\xe4\x4b\x37\xba\xba\x98\x4b" + "\x07\xb3\xa7\x56\x73\x74\x3d\xf0" + "\x30\xbf\xfe\x3e\x6e\x69\x2e\x34" + + "\x37\xc5\x4a\x86\xf7\x48\x4b\xf8" + "\x3d\x0d\x94\xa6\x09\x34\x71\x04" + "\xae\xc7\x74\x61\x2d\xb2\x4d\x01" + "\x34\x30\x21\x8c\x43\x1c\x3a\xc7" + "\xec\x93\xdd\xff\xa5\x4e\xac\x18" + "\x3e\x78\x02\x61\x57\xc7\x4f\x72" + "\x3f\xe8\xc3\x91\xcc\x3f\xe1\x9f" + "\xf5\x0b\x8f\xf0\xc8\xc2\xa8\x92" + + "\xde\xf6\x67\x8f\xfd\x22\x2e\x7f" + "\x77\x31\x69\xd8\x33\x88\x01\xab" + "\x95\xca\x3e\x86\xb6\x1d\x6d\x26" + "\x2b\xef\xb5\x31\x2b\x73\xb7\x6b" + "\xce\x80\x5f\x91\xc6\x27\xa9\x4f" + "\xd8\xef\x90\x5f\xd2\xd6\xa1\x6f" + "\xad\x48\x6b\x45\xe8\x5d\xd7\x7b" + "\x29\x64\x5b\x84\x7a\x50\xcb\xd2" + + "\xec\xd7\x55\xe2\x2a\xf8\x2c\xa7" + "\x04\xe2\x60\xa4\x23\x5c\x02\x52" + "\x44\x0a\x5b\x7d\x2d\x54\xae\x10" + "\xda\xae\x05\x93\x10\x43\x51\xa8" + "\xe8\xbf\x4b\xa1\xf5\x15\x83\x95" + "\xfe\x65\x53\x38\x26\x18\x36\x3f" + "\x40\x50\xd9\x66\x6b\xa3\xb3\xc2" + "\xa2\xed\xf4\x7c\x34\xb3\xc7\x12" + + "\x9d\x11\x44\xe7\xd1\xb4\x45\xa5" + "\xe7\x71\x9a\x82\x69\xb1\x93\x4c" + "\xbf\xfc\x17\x61\x8c\x90\xbb\x2d" + "\x85\x3d\x5a\xb3\x20\x73\xc9\x4d" + "\x05\x81\xf8\x6b\x85\x4f\xc0\x94" + "\x1f\xbc\x51\x1b\xce\x1b\x2e\x45" + "\xf3\x3a\x01\xb3\x50\xff\x41\x0c" + "\x24\x7e\x4d\x22\x45\xf4\x7a\xf0" + + "\x6a\x4f\xd2\xa3\x7c\xe5\xb9\xbd" + "\x63\xa7\x45\xf3\xd7\x46\x82\x8a" + "\x5f\xbb\xcf\x98\x6d\x2a\xbd\x73" + "\xdb\x04\xed\x86\x5e\xe8\xd8\x1d" + "\x0b\x42\x1f\xc0\x42\xda\xf2\x76" + "\xc7\x7b\x40\x64\x73\x54\xf0\x7e" + "\xf5\x48\xf5\xaf\x7f\xba\x98\x7e" + "\x4a\xb6\x30\xfd\xee\xfb\x7a\x6b" + + "\xbb\xd2\xa0\x16\xc5\x2f\x92\x4f" + "\x99\x34\x62\x1a\x6c\xc1\x5c\x0d" + "\x8b\x2c\xc6\x57\x3a\xcf\x41\x92" + "\x7f\x66\x1b\xfd\x61\x69\x5e\x2f" + "\x97\x17\xa0\xf5\x0b\xc7\x15\x5c" + "\x92\x61\x95\x60\x4d\xb4\x20\x3d" + "\x52\xdb\x1f\x07\x37\x1b\x91\x04" + "\x7b\x0f\x6f\x8d\x16\xf9\x48\xf6" + + "\xf8\x72\x25\xeb\xea\x39\x76\x06" + "\xce\x53\x08\xd7\x32\xf6\xce\xb0" + "\x04\x90\x98\xe9\x31\x1f\x7f\xd8" + "\xc0\x82\x65\xa2\x36\x72\xaa\x94" + "\x56\xc6\xc2\xb0\xe5\xb8\x11\x42" + "\x4e\x41\x57\xa2\x9b\xa7\xaa\x05" + "\xb0\x9a\xf0\xe0\x41\xf8\x72\x06" + "\x65\x1c\xc8\x3e\xbf\xf9\xc5\xa3" + + "\xfa\xf0\x03\xe0\x9a\x37\xf6\x4c" + "\xb0\xc8\x75\x1e\x87\xe0\x17\x79" + "\x9f\x3c\x38\xa1\xfc\x59\xc0\x1d" + "\x67\x09\x48\x64\xa6\x4e\x61\xa8" + "\xd1\x5d\x62\x79\x01\x0d\x4d\xc3" + "\x88\xe7\x00\x42\xe1\xa1\x47\x7d" + "\x9d\xa5\x54\xa7\x1e\x9d\xf9\xae" + "\x78\x41\xb1\x49\x00\x2d\x81\x1c" + + "\xa7\xb3\x77\x08\xb6\x1b\xa1\xa4" + "\xa9\x21\xd5\x2c\xa6\x11\x4d\x24" + "\x2c\xc6\xf5\xbf\xb7\x19\x4b\x46" + "\x7c\x65\x76\x90\xa7\xeb\xf3\x27" + "\xa9\x81\x75\x0c\x97\xbf\x3a\x48" + "\xf3\x22\x0b\xae\xe0\x08\xf1\x2e" + "\xd5\xbc\x64\x50\x66\xf3\x03\xd6" + "\x5e\x02\xf5\x5b\xa7\x75\x48\xcf" + + "\x2c\xd2\xd5\xd0\xe5\x02\x93\xab" + "\x30\x40\x12\x30\xb0\xe6\xa7\xd0" + "\xf4\xa1\x0a\x4f\x7b\xc5\x62\xe2" + "\x2e\x20\xba\x0b\xa5\x58\x7a\x49" + "\xac\xcc\xcf\xe6\x1e\xd2\x9f\x10" + "\xec\x27\x19\x8a\xe6\xcc\x96\xb5" + "\x5a\xe8\x02\x3b\xe8\xf7\xb9\x48" + "\x34\x11\x59\x08\x3c\xf8\x7e\xbf" + + "\x62\xc5\xed\x62\xb1\x91\x5e\xe0" + "\x85\xd1\xbc\x62\x72\xfe\xe1\xb5" + "\x19\x5b\x10\xb8\x08\x69\x52\x1d" + "\x22\xbb\x6b\x89\x7e\x44\x11\x0d" + "\xf0\x13\x22\x2c\x49\xaa\x7a\x64" + "\x4b\xc1\x2f\x2e\xc6\xf8\xc9\xf6" + "\xc6\x68\x41\xbc\x9a\x25\xca\x90" + "\x61\x34\x8e\xdd\x62\x27\xb9\x3b" + + "\x9a\x18\x20\x5b\x94\xc0\x7f\x15" + "\xab\xc8\xf5\x0b\x2d\xc6\x72\x6e" + "\xb7\x50\x77\x35\xe1\x89\xf4\xf7" + "\xc5\x31\x7d\xf8\xb2\x1a\x51\x18" + "\xc5\x35\x5f\x00\x27\x78\x26\xa4" + "\x6d\xed\x80\x94\x54\xa0\x8c\xa2" + "\xb2\x7d\x24\x77\x7c\xde\xef\x20" + "\x60\x9d\x14\xa4\x39\x04\x16\x5e" + + "\x70\xae\xde\xf3\x48\xb1\x10\x5c" + "\x33\xc4\xab\x6e\x53\x4b\x04\x02" + "\x8e\xf1\x63\xfe\x0c\x79\x82\x1e" + "\xf1\x5f\x69\xaa\x5a\xb6\x86\x28" + "\xed\xa4\x27\x46\x93\xdf\x4f\x99" + "\xb9\xb0\x2e\x87\xc0\xde\xb4\xe9" + "\x8f\xa2\xf7\x58\x8d\xec\x0b\x4c" + "\xfe\xc5\xf9\xea\xed\x4d\x0c\xc3" + + "\xf7\x7c\x0b\xe6\xaf\xac\xc1\x6d" + "\x69\xd8\xa9\x84\x50\x0a\x86\x25" + "\xc4\x8a\xba\xe7\x09\x6f\xfc\x56" + "\x9e\xd2\x48\x61\xd0\x5b\x8c\x82" + "\x5f\xae\x55\xdc\x5e\x43\x6b\xac" + "\x11\x74\x11\xc0\x6c\xf5\x27\xa5" + "\x2c\x34\x24\xfd\x5e\x04\xd5\x94" + "\x0d\x7c\xb6\x70\x35\x0a\x4c\x2c" + + "\xcd\x79\x55\xb6\x38\x35\xf6\x69" + "\xa1\x33\xf9\xad\x5c\x60\x70\xd0" + "\x6c\x9f\xbe\x83\x05\x87\x7e\x01" + "\xa1\xb8\x47\xb2\xaa\x2f\x44\xe9" + "\x68\x3d\x0d\x54\x9e\xff\xee\x54" + "\x19\xbe\xe3\xca\xab\xde\x3e\x1f" + "\x1b\x31\x35\x70\xb0\x28\xc5\x95" + "\xa7\xc0\xbc\x96\xb7\x3a\x5d\xb3" + + "\xb5\x98\xd3\x5e\xfa\x3c\xca\x9b" + "\xd7\xdd\x53\x13\x65\xb4\x60\x6a" + "\xd1\x51\x1c\x1a\xbb\x17\x5c\x90" + "\x1b\xf9\x5c\x7f\x81\x04\xa3\x27" + "\x0a\xbf\xd6\x9e\xf3\x0c\x66\xc4" + "\x56\x1d\x9e\xf7\xb1\x3f\xb0\xb0" + "\x54\x13\x00\x36\xf1\x3b\xa1\xe3" + "\x2a\x2b\x2b\x1f\x54\x50\x72\x9a" + + "\x6d\xe1\x06\x21\x05\x7d\x89\xb4" + "\x8c\x7f\xa0\x50\x9b\xdf\xbb\x85" + "\xd7\xff\x49\x6c\x3d\x2a\x63\x42" + "\xb8\x20\x07\x60\x7c\x5e\x88\xb7" + "\xac\x94\xb6\xde\xdc\x7f\xa4\x6f" + "\x79\xd1\xe0\x8a\xf5\x14\x46\x38" + "\xb3\x4a\x12\xbd\x29\xba\xfc\x78" + "\xea\x12\x8f\x74\x9e\x3d\x11\xbb" + + "\x18\x30\xcd\xa7\x99\xef\x23\x3c" + "\x8f\xfd\xde\x83\x06\xc5\x3f\x2c" + "\x9b\x49\x88\x2b\xff\x45\x7a\xf9" + "\x6a\x7f\x6e\x34\x21\x32\xaa\xae" + "\x30\x27\xf3\x50\x84\x34\x47\xe7" + "\x41\xca\xd6\x0f\xbb\xb8\xc0\xc2" + "\x14\xc1\x17\xaf\x79\x20\x88\xa9" + "\x04\x72\xde\x1b\xa6\xf7\x35\x06" + + "\xfe\x93\x84\xf3\xd0\x13\xb0\xc3" + "\x18\xf7\xba\x07\x96\xae\x2c\xa3" + "\xba\xb3\x95\x20\xc2\xa6\x1d\x37" + "\x9e\x90\x41\xb0\xbd\x0a\x1c\x03" + "\x60\x9e\x1a\x43\xbe\x6d\xcc\x11" + "\x6e\x8f\xf3\x5b\x76\x94\x91\x7e" + "\x33\x4a\x2a\x46\x76\xf0\x47\xbe" + "\x30\xb8\x41\x30\xdf\xc9\xb3\x33" + + "\x85\xbd\x63\x7b\x4e\x4d\xd7\xa7" + "\xa6\x3d\xe2\x43\x55\xc6\x36\xea" + "\x29\x96\xa7\xe5\x7f\x7d\x7b\xcd" + "\x1d\xc0\xca\x13\x47\xf7\xb1\x1f" + "\xd3\xde\x28\x90\x45\xe1\x0f\xaa" + "\x97\x20\x57\x19\x3b\xca\x23\xb1" + "\x77\x86\x83\x74\x6d\x74\xa8\x21" + "\xc6\xcc\xab\x63\xcb\x7a\xfc\x1c" + + "\x70\x3d\x05\xe5\x02\x33\x65\x02" + "\xc9\xbf\xc6\xb8\x5b\xe3\x33\x3c" + "\xe9\x1e\x02\x9a\x40\x4b\x2c\xa7" + "\xe4\x27\x65\x3f\x0d\x80\x1b\xe1" + "\xb5\x37\xdc\xb6\x4a\xd4\xc1\x8f" + "\x74\xe4\x80\xf5\xb5\x06\x86\x5d" + "\xfa\xb0\xb5\x87\x4a\x75\x25\xdf" + "\x5e\x2a\x69\xbb\xe8\x0c\xf5\xba" + + "\x9a\x1d\xc6\xfa\xb8\xc8\x7c\x02" + "\x8a\xfe\xc6\xe3\x62\xe0\x25\x7d" + "\x03\xf5\xbf\xe5\xbf\x05\x88\xe0" + "\xf7\x32\xf6\x6f\x6c\x1e\x27\x13" + "\xa5\x76\x2f\x23\xc0\xa6\xdc\x55" + "\x26\xf4\x1e\x70\x2d\xc3\x57\x89" + "\x78\x51\x0a\xa1\xcb\x8b\x72\xee" + "\x73\x51\x2c\xb6\x11\x04\xa6\x5e" + + + "\x50\xbc\xd8\xb4\x2b\x46\xd5\x9a" + "\x70\x57\x19\xa9\x16\x0b\x1c\x18" + "\x68\x2a\x41\x78\x1c\xfe\xd4\xeb" + "\x8c\xf4\xdf\xc0\xbc\x41\x03\xae" + "\x66\xe8\x03\x70\xcf\x45\xbc\xb6" + "\x1b\xa4\x24\x8a\xea\x6d\x1a\xf1" + "\xc2\x24\x4c\xd0\x1a\x15\x07\x54" + "\x68\x7b\x5b\xda\x7d\xd2\xc9\x62" + + "\xf6\x8b\x3b\x52\x2e\xb1\x50\x0a" + "\x1b\x0c\x91\x8f\x5b\xeb\x09\x80" + "\x88\x75\x16\x4a\x82\xaf\x35\xf5" + "\xbd\x2a\x2a\xfb\x9c\x5f\x83\x0f" + "\x62\xeb\xfc\x2a\x31\x29\x9b\xf5" + "\x3f\x38\x9d\x16\x2a\xdf\x97\xc7" + "\xb0\x02\xac\x66\xb0\x5f\x3f\xeb" + "\xca\xd0\xa2\xda\x6f\x4c\x9d\x02" + + "\x42\xe5\x7c\x2b\x05\x26\x22\xb8" + "\xe1\xbd\x72\x74\x99\xce\xd4\xe6" + "\xda\xf4\xd2\x09\xbe\x6e\xe1\x53" + "\x2e\x2b\xb9\x53\x2e\xf4\x0f\x18" + "\xc6\xa1\x34\x2c\x02\xcc\x9b\xc5" + "\xc2\x46\x2c\x42\xf9\xd6\x03\x38" + "\xa2\xa8\x14\x5c\x4f\xf7\xaf\x18" + "\x28\x8b\xa0\x10\x80\xbf\xae\x55" + + "\xbc\x43\xb3\xf5\x10\x20\xaf\x58" + "\xfe\x42\xf1\xf2\x0a\x40\x2e\x0f" + "\xdf\x4b\x5f\xa8\xde\xbf\x83\x34" + "\xa9\xea\xbf\x03\x93\xd0\xb1\xf0" + "\x03\x16\x08\xc7\x95\x1b\xa0\x2e" + "\x97\x10\xba\x3d\xc9\xe4\x43\xe9" + "\xa6\xf3\x38\xb4\xad\x92\xbe\x47" + "\x36\x66\xbf\xe5\x42\x77\xbb\x00" + + "\x61\x2a\xdf\x86\xb4\x4f\x7a\x13" + "\xa2\xb4\xf7\xec\x07\x9c\xed\xa1" + "\xff\x42\xd0\x7b\xe2\x60\xe4\xb2" + "\xec\xf5\x62\x5f\xfa\xe2\xf5\xb7" + "\xb7\x23\x24\xcc\x6b\xec\xa6\x7a" + "\xa7\xee\x63\xba\x7f\x0a\xce\x75" + "\xe1\xa6\x50\xf2\xb1\x5f\xa4\x67" + "\x9f\xdc\x3c\xe5\x9c\x91\xbc\x93" + + "\x45\x33\xce\xdd\xaa\xcc\x2f\xec" + "\x50\x43\x2a\x01\xb7\x11\x68\x2a" + "\xdc\x8b\x59\xac\xf1\x0f\x76\x96" + "\x28\x41\xbf\xd1\x2a\x65\x4d\x05" + "\x05\x10\xa2\x92\xd4\x51\x11\x0a" + "\xdf\x0f\x11\x33\x71\x39\x7f\xad" + "\x0f\x10\x60\x19\x8c\x92\x95\x8c" + "\x62\x33\xf0\x7b\x25\xc8\x91\x6c" + + "\xec\x1d\x3f\xec\x5d\x12\xe6\x19" + "\xda\x78\x11\x91\x40\xf0\xb1\x07" + "\x38\x67\x4a\x90\xda\xde\x3e\xd9" + "\xcd\xed\xeb\x0b\x5a\x7a\x18\x55" + "\x41\x9d\x32\xeb\x22\x47\xd0\xf7" + "\x91\xb3\x70\xf1\x9e\x09\x49\xf4" + "\x28\xf8\x99\xca\x69\x7a\x31\xfd" + "\x6d\x97\xa4\x34\x2b\xdb\xc3\x50" + + "\x78\x71\xfe\x7b\x1b\x48\x74\xb6" + "\x68\x58\x40\x65\xae\xeb\x1d\x4e" + "\x7d\x86\x8c\xc4\x21\x28\x1b\x06" + "\xea\x30\x3b\x51\x35\x5b\xc1\x69" + "\x88\x10\x87\x36\x66\x16\x4a\x3b" + "\xff\xb1\x20\x12\x5d\x9f\xe2\xe5" + "\x4d\x9f\x3d\x23\x35\xbb\x82\x4b" + "\x75\xc6\xcd\x18\x33\x63\x07\x4e" + + "\x73\x44\x56\xcb\xdf\xe8\xd2\x78" + "\x1a\x62\xd5\x57\x73\xa9\x49\x43" + "\x24\x8b\x8f\x21\x89\x5d\x83\x9d" + "\xe2\x6e\x9b\x07\xc5\x7b\xfe\x01" + "\xce\x5d\x3b\x5b\x2b\x2a\x7f\xe5" + "\x65\x55\xe5\x5f\xb7\x37\x86\x5a" + "\xe7\xba\x1d\xa4\xae\x34\xff\x83" + "\x8f\x7a\x0a\x95\x9c\x19\xe1\xfc" + + "\x06\x77\x70\x3e\x1f\x54\x4f\x37" + "\xcf\xd0\x31\xa8\x38\x36\x4d\x9a" + "\x04\xca\x18\x15\x83\xf4\xb4\x4a" + "\x18\xc3\x38\xfe\x5d\xee\xe3\x54" + "\x9b\x81\xc8\x03\x64\xe3\x3a\x38" + "\x4c\x86\x17\x2e\xa1\xda\xd1\xa9" + "\x5b\xaa\xee\x50\xb3\x97\x5a\x24" + "\x83\x4e\xbf\x99\x09\xd0\x62\x53" + + "\x80\x39\xd4\x9b\xc2\x13\x03\xfc" + "\x29\xdb\x72\xf1\x70\x4b\x95\x9c" + "\x1a\xa2\x54\xf9\xb7\xdc\x9b\x67" + "\xfc\xe4\xe2\x54\x09\x17\x48\x6b" + "\xd0\xf1\xba\x30\xf5\xf5\x8a\x31" + "\x60\x20\xf9\xcb\x3c\x8a\xea\x26" + "\x58\xe2\x5a\xcd\x7c\x9d\xc6\xc3" + "\xc9\x07\xad\x0e\x47\xa0\x3b\xa7" + + "\x69\x5e\x81\x31\x97\xc3\x63\x3a" + "\x02\x28\xdd\xdc\xd6\xcb\xf9\x6d" + "\xaf\xf6\xb4\x15\x4a\xed\x47\x4c" + "\x78\xf9\xc0\x6a\x82\x9d\x00\x62" + "\xc7\x8f\x89\x8b\xd2\x80\x4d\x66" + "\x1f\xc9\x17\x2c\xda\xee\xf1\x72" + "\x09\x66\xae\x7a\xbc\xd3\x84\x9e" + "\x95\x68\x37\x28\x95\xc1\xc7\x58" + + "\x07\x4f\x29\xd9\x30\x76\xff\xdc" + "\xd0\x8f\xba\x8d\xd6\x65\xb7\x89" + "\xcd\xac\xbc\x8d\xde\x55\x3e\x55" + "\xf8\x2b\x70\xed\x9e\x00\x4a\x9b" + "\x0d\xca\xb8\x27\xdd\x34\xe5\xf6" + "\x52\xfd\x77\x61\x34\x6b\x49\xc4" + "\xb7\xb7\x7b\xc8\xf6\xe6\x8c\x37" + "\xf0\x19\xcc\x44\x48\x3d\x63\x68" + + "\x63\x20\x42\x5e\x91\xb9\xde\x73" + "\xc0\x1b\x75\x4a\x27\x64\xd2\x7a" + "\x4f\x34\x14\x44\x22\xe2\xdc\xe6" + "\x28\x1f\x81\x85\xf7\xef\x01\xad" + "\x2b\xb7\x68\xba\x90\x65\x48\x25" + "\xaf\x35\x36\x20\x4a\x26\x93\xdb" + "\x0a\x66\x22\x28\x8a\x1f\xb0\x1e" + "\x64\x8c\x59\xee\xe8\xce\x2d\xae" + + "\x74\x78\xc1\x7d\xb6\xe7\x59\x35" + "\x2a\xcc\x95\x81\xef\xf0\xca\xd0" + "\xd9\x4d\xd2\x0c\x88\x67\xc0\x07" + "\x41\x7c\x85\x02\xa0\x9e\xa9\x01" + "\x63\x2f\xf8\x90\xe4\x79\x65\xd8" + "\x37\x92\x1c\xe4\x8a\x65\xe0\xb1" + "\x79\x1e\xfd\x93\xfd\xfa\x5f\x07" + "\x8f\x0b\xf6\x47\x35\x40\x70\x6e" + + "\xed\xfc\xe6\xa3\xc7\xf5\x53\x0d" + "\xeb\xbd\x5f\xf4\xd5\xbd\xcb\xe8" + "\x70\x9a\x33\x13\xdf\x01\x5c\xf8" + "\x81\xeb\x2c\x14\x80\x18\xf7\x0f" + "\x7a\x43\x70\xbd\x74\x87\x4e\x4c" + "\x6a\xda\x0b\xba\x91\x28\xb3\x5f" + "\x6e\xd2\x8b\xf1\xd2\xeb\xdb\x1c" + "\x22\xd5\xa9\x03\xf1\x26\x95\x2f" + + "\xa6\xb0\x51\xbe\xda\x86\x51\x76" + "\x88\x90\xce\x73\xf4\xe9\x76\x53" + "\x5a\xd8\x5b\x5b\x0b\x80\xed\xe3" + "\x04\xe6\xc1\x4d\x52\x95\x28\x24" + "\x5e\xd3\x27\xef\x47\xcc\x6d\xe7" + "\x7d\xa6\x00\x90\xd6\xee\x96\x43" + "\xc1\x92\xde\x84\xa0\x3b\xb3\x73" + "\xfe\x01\x76\x37\xae\x53\x64\x22" + + "\xc2\xe9\xf7\xc1\x75\x60\xfc\xec" + "\x34\xec\x5a\xbe\x20\x76\x21\x6a" + "\xa8\x3b\xa3\x9e\x54\xd0\x81\x37" + "\xd4\x85\x6b\xd8\xab\x35\xef\x84" + "\x83\xee\x1f\x46\x3c\xa3\x4a\x91" + "\x6c\x7d\x5f\xb2\xc9\xe5\x11\xf3" + "\x5c\x49\x3d\xc3\xaa\x0d\x11\xc6" + "\xb9\x54\x85\x81\x83\xe5\x7e\x8a" + + "\x0e\xec\xf4\xa7\x2a\x73\x12\x36" + "\x8f\x34\x71\x9d\xd0\x88\x3e\xee" + "\xdb\xcf\x99\x75\xe4\x07\xa1\xb7" + "\xc6\x51\x1b\x61\xe8\xe7\x5d\x1f" + "\xaa\xaa\x51\x10\x59\x1d\xa1\xd6" + "\x86\xc3\xf0\x55\xf0\x31\xe5\x3d" + "\x66\x0e\xf2\x09\x73\x5c\xf9\x09" + "\x79\x4b\x41\x9e\x1a\xaa\x21\x64" + + "\x7e\x1d\x27\xa8\x05\xc9\x52\xa7" + "\x0b\x81\xe5\x58\xa5\xdf\x35\x47" + "\xeb\x5a\x92\x5d\xee\x44\x8a\xe1" + "\x53\xa8\xc8\x13\x7f\x69\x08\x97" + "\x0b\x9a\xcc\xbf\x40\xd5\x77\x83" + "\x03\xd4\x74\xe5\x1c\xe0\x27\x7b" + "\xa6\xa8\x60\xcf\x0c\x18\x3d\x3d" + "\xbf\x98\xc2\xf1\x52\xf1\x8e\xe4" + + "\x60\xb0\x29\xb8\xb1\x60\xb6\xb8" + "\x9b\xc6\x55\x5f\xf1\x3e\xa7\x9f" + "\x88\x78\x20\xef\xec\x19\x5f\xc7" + "\x9e\x12\x2b\x28\x60\x2b\x9b\xb1" + "\xc7\x30\x47\xbf\xee\x27\xf3\xb2" + "\xbe\xc0\x73\xc9\x59\xf6\x9d\xeb" + "\x98\xdb\xc1\x65\xc1\x13\x49\xd1" + "\x9c\x1a\x9d\xf7\xd4\x7d\xf5\x80" + + "\x21\x28\x39\x66\x6f\x02\x04\x11" + "\x49\x84\x79\xe1\xf7\xbe\x3d\x25" + "\x18\x56\x3e\x3f\x37\x34\x4b\x3c" + "\x41\xe0\x64\x2c\xd6\x46\x55\x5b" + "\x2b\x76\xc5\x57\x79\x32\xb5\xad" + "\xf3\x8d\x95\x92\xf0\xd0\xcb\x5d" + "\xbe\xbd\x4f\xf6\x44\x74\x45\x2c" + "\x75\x81\x40\x1d\x82\xc3\xab\xb4" + + "\x79\xd7\x19\xe9\x9b\xe7\x2d\x0c" + "\xbd\x78\x2e\x24\x4a\x69\x84\x15" + "\xc9\x76\x13\xf6\x94\x6d\x75\xa4" + "\x98\x27\xdc\x34\xbc\xa7\xcc\xfb" + "\xa1\xf0\x8d\x10\x19\x53\x87\x5e" + "\x9d\x89\x3e\x29\xae\x01\xec\xe2" + "\x91\x70\x35\x92\xef\xa4\x28\xc9" + "\x65\xd0\x2e\xf6\x87\x89\xa2\xd5" + + "\xc0\xa3\xea\x0a\x8c\x2e\x3a\x31" + "\x0a\x5b\xe8\xab\x9e\x6d\xf4\x89" + "\x3a\x7d\xa9\x2d\xbd\x9e\x88\xd2" + "\xba\x8c\x3f\x10\x6a\x02\x84\x94" + "\x5f\x3b\xd8\x87\x8a\x9f\x15\x52" + "\x95\x02\xef\xb1\xd6\x20\x22\xdb" + "\xcf\x1a\xc0\x03\x6e\x74\xa0\xbd" + "\xe3\x9f\x41\x14\xa7\xb2\x97\x4f" + + "\x9f\x20\x55\x25\xf7\x36\x04\xac" + "\xec\x73\x27\x16\xa2\x66\x34\x20" + "\xfe\x59\x8e\xb4\x39\x87\x3f\xc5" + "\x60\x56\x84\x88\x2b\xda\x4c\xb2" + "\x9a\x39\x5e\xfa\xf9\xb5\x74\x8d" + "\x5e\x25\x92\x6f\x0b\xed\x3d\xff" + "\x0a\x9e\x5c\x04\xfe\x31\x6c\xc7" + "\x62\x46\x2b\x6d\x44\xa0\xba\x85" + + "\x51\x5d\xf0\xed\xbe\x8b\xaf\xb8" + "\xb8\x8d\x8f\x71\xa6\xc7\x53\x86" + "\xdd\xff\x00\xcf\x8b\xb4\xfe\x14" + "\x40\xe1\xa9\x5c\xdb\xf7\xbc\xfc" + "\xb7\xfd\xd8\xd9\xe8\xec\xb4\x73" + "\x21\x99\x38\x2f\x68\xd3\x69\xdc" + "\x19\xc2\x8b\xc8\xe4\x2e\xd3\x10" + "\x96\x2d\x1c\x92\x27\x2c\x4d\xc0" + + "\xfd\x73\x10\x3d\xb8\xfd\x81\x69" + "\x0e\x20\x78\x6c\x0d\xf7\x2a\x25" + "\x7e\x57\xef\xa9\x67\xe8\xd0\x60" + "\x67\xe0\x13\xa4\xe8\x3f\xe6\x66" + "\x3a\x15\x14\xb9\x73\xb1\xdc\xbb" + "\xa8\xa0\xb4\xcc\x23\xe6\x9a\xb5" + "\xa0\xb8\x35\x3c\x20\x30\x05\x34" + "\xff\xf2\xda\x30\x6f\x81\xb8\x19" + + "\xca\xe5\x80\xc8\xc2\x7a\xbf\xcc" + "\x50\xc4\x11\x8d\xee\xdb\x99\x82" + "\xbf\xa6\x77\x0f\x1b\xd1\x27\xbb" + "\x93\xe7\xdc\x5e\x0b\x63\x01\xc6" + "\xea\xf8\xe7\x79\xfb\xb9\x73\xdb" + "\x88\x72\x36\xf4\xa7\xbb\x48\xe4" + "\x1b\x57\x35\xb0\x6f\x41\xb6\xf5" + "\xa2\x91\x88\xa4\x5d\x8f\x1b\x98" + + "\xa0\xfa\xfb\xb4\xff\x90\x96\x00" + "\xdb\xc6\x19\x36\xb7\xda\xbb\x8b" + "\xe8\x56\x83\x72\x73\x42\xd4\xc6" + "\x35\xec\x53\xe4\xd8\xf0\x76\xfd" + "\x29\x8a\xc2\xaa\x54\x25\x5c\x77" + "\xf0\xe4\x55\x5c\x9d\xaf\xf7\x28" + "\x4d\xad\xe8\x88\xa6\x54\xcf\xba" + "\xdf\x6d\xa7\x0a\xe8\x18\xb0\x85" + + "\x93\x7a\xc3\x09\xb9\xb3\xc8\x8f" + "\x2c\xb0\x99\xa1\xcb\xeb\x8f\x75" + "\x8c\x20\x3b\x8f\x38\x45\x9b\x5c" + "\xf0\x90\xba\xf2\xde\x84\x85\x7c" + "\xe3\xcc\x95\xb3\x1c\x1a\x75\x52" + "\x50\x5f\xd4\xc1\xeb\xe4\x59\xbb" + "\xac\x5d\x63\xb0\x11\xb9\xcd\xf7" + "\x94\x36\x24\xd3\x71\xd3\x24\xe9" + + "\xd6\xa8\x53\x65\xfd\xc0\x32\x65" + "\x6d\x5a\x16\x45\xa5\xcb\xb8\x42" + "\x92\x2d\xf1\x3c\xea\x88\x6d\x9c" + "\xc5\xb0\x6d\x90\x30\x35\xc9\x0e" + "\xdf\x6c\xcc\xec\xf8\x06\x46\x49" + "\x99\x78\x38\xc6\xfc\x66\xed\xa7" + "\x4c\xae\x35\x8a\x17\x2e\x02\x91" + "\xc3\xbe\xa7\xec\xe6\xca\xdb\x28" + + "\x84\xd6\xc4\x92\x51\x30\xce\x40" + "\xcd\xef\x12\x76\x25\xd7\x04\x8b" + "\x20\xae\x9c\x6f\x36\xda\xdc\xb9" + "\x6c\x85\x58\xf0\x24\x4d\xdc\x0e" + "\x00\x79\x42\x85\xbf\xe6\xf2\x64" + "\xea\xdf\x09\xdc\x95\x12\xe8\x3d" + "\x6c\xf2\x9b\x37\x87\x44\x1b\xd4" + "\xa9\x35\xf1\x6d\x6d\x2c\xb6\x50" + + + "\x2a\x83\x05\xd0\x5e\xfb\xb2\x0d" + "\x4f\x2e\x04\x91\x3b\xfd\x5e\x5f" + "\xca\xf8\x70\xed\xc6\xfd\x4f\x8c" + "\xcc\xa9\x2d\xb5\x0b\x5d\x64\xe4" + "\x1f\x1d\x00\xc9\x8b\xf5\x96\x95" + "\x05\x72\x11\x4e\xbc\xf0\xc8\x52" + "\x84\xa0\x98\xe3\xd2\xa0\x4a\xfd" + "\xde\x49\x4f\x10\x3a\xfe\x5b\x81" + + "\x7b\xb3\x48\xe5\xcc\x3a\xeb\x54" + "\x49\x05\xd4\x84\x42\x75\x8e\xb3" + "\x4f\x1b\x34\x7b\x51\xaa\x3d\x8c" + "\xfa\xf7\x0b\x69\xec\x28\x69\x2f" + "\x41\x6c\xce\x86\x23\xb3\x96\x04" + "\xcd\xad\xad\x10\x55\x1c\xbe\x01" + "\xf9\xfa\xb5\x4b\xe7\x67\x4e\xc0" + "\x85\x99\x5c\xe1\x78\xf6\xba\x3c" + + "\x2d\x9a\xab\xd7\x6a\x22\x4d\x52" + "\x58\xe9\xfa\x7d\x0d\x09\x00\x9c" + "\xc2\xd8\x51\x87\x39\xf5\xa5\x0b" + "\x2d\x26\xb8\x3a\xdd\xbc\xfc\x8a" + "\x3b\x04\x9d\xe9\x29\x27\x39\x57" + "\x3a\x94\xbc\xae\x3b\x26\x51\xef" + "\x35\x29\x86\x20\x93\xce\xea\x9f" + "\x7b\x81\x6c\xb0\x03\xfc\x9e\x63" + + "\xdc\x81\x1d\x34\x7d\xbe\x39\xe8" + "\x79\x83\x14\x32\x89\x68\xdb\xcd" + "\xad\x6e\x02\xf7\xa1\x11\x62\xda" + "\x5e\xcc\xd1\xf4\x5f\x57\xb2\xf3" + "\xe6\x3a\xa7\xa7\xf6\xc8\xcf\x40" + "\x83\xb4\xd5\x61\x5e\x9a\x87\x83" + "\xbc\x0e\xa5\x41\xed\xb1\xac\xc5" + "\xfa\xd8\x07\x3c\xc8\x0c\xa6\x59" + + "\x90\x19\xb8\xc3\x4a\x8d\xc9\xde" + "\xfe\xc8\x0c\x9e\x22\x37\xb8\x1c" + "\xb9\x27\xb4\xd2\x91\x04\x0b\xfe" + "\x6c\xa6\x83\xe9\xac\x86\x23\x0f" + "\x13\x12\x29\xb3\x1e\x4d\x0c\x93" + "\xe4\x2a\xa6\x59\x2e\x2b\xf8\xa2" + "\xe3\x89\x3e\xf9\x53\x38\x23\x77" + "\x7f\x7c\x77\x11\xac\x63\x80\x7f" + + "\x00\x10\x37\x59\x7c\xc9\x4a\x60" + "\x18\x9c\x75\x7f\x70\x8c\xc4\xe1" + "\x65\x6b\xdb\xa5\xc5\xec\x62\x3f" + "\x95\x14\xa2\x38\x73\xb1\x78\x0a" + "\x94\xad\xc8\xbc\x9d\x81\xe1\x6b" + "\x00\x34\x9c\xd8\xf6\x04\xdc\x70" + "\x0a\x84\xb4\xa6\xb4\x57\x25\x46" + "\xc0\x21\xbd\x60\xde\x6a\x4c\x54" + + "\x72\x60\xff\x02\xcf\x07\xe6\x36" + "\xdc\x8c\xd9\x8a\xa9\x2c\x7d\xa4" + "\x09\x66\xf5\xf5\x1e\x1d\x47\xbf" + "\xa0\xad\x64\xf2\x23\x66\xf8\xbc" + "\xb6\x5c\x9e\xaa\x87\x06\x0c\xb7" + "\x6c\x1c\x40\x17\xf2\x24\x81\xc9" + "\x35\x14\xa6\xd4\x5f\x63\x89\x81" + "\xa6\x8e\xd9\xa9\xaf\xb8\x8f\xd2" + + "\x2d\x32\xc7\x65\xb6\x30\x95\x43" + "\xfb\xb3\xc1\xb3\x01\xcc\x12\xcf" + "\x85\xf6\x72\x01\x86\x01\x0b\xc7" + "\x1d\x39\x58\x1b\x22\xee\x15\xb9" + "\x24\xdb\x17\xa3\x3b\xf0\xfd\x9a" + "\xc4\xff\xb8\x17\x59\xc6\xde\x87" + "\x50\xd0\xd3\xe4\x7b\x59\x46\x7f" + "\xe7\x00\x65\x00\xed\xc1\xa1\x80" + + "\xf3\x25\x70\x01\xc3\xa8\x4d\x3d" + "\xb4\x79\x95\xfb\x8c\x62\xcf\xef" + "\xec\x16\x37\x1f\x16\x00\x4d\x5c" + "\x6e\x11\x01\x68\xc4\xeb\x27\x9c" + "\x7e\x76\xa1\x1d\xa1\x0e\xba\x5e" + "\x57\x4c\x00\x47\x52\x14\x15\xfe" + "\xb7\x73\x23\x8c\xf6\x6d\xce\x3a" + "\xac\x37\xbc\x5d\xfe\xdf\xc3\x75" + + "\x49\x07\x8a\xa2\xdb\x47\xa1\xa2" + "\x65\x91\x51\xee\xd6\x20\x6c\x24" + "\x15\x07\x81\xd3\xb1\xd1\x68\x50" + "\xb9\x60\x81\x74\x8c\x01\xe7\xb1" + "\x62\xff\x80\xf3\xfa\xb1\xf5\x03" + "\x1e\x2c\xcb\xf3\xdd\xb1\x7f\xef" + "\xda\xa7\x91\xfc\xa8\x39\xb5\xea" + "\x61\xb5\xf9\xf3\x07\xb7\xdd\x83" + + "\x98\x1b\x10\x80\xd9\x76\x72\xb5" + "\x66\x0f\x2f\xb8\xfd\x83\x08\x76" + "\xf3\xef\xc3\x4b\x75\xde\xd7\x89" + "\x40\xab\xc2\x5d\x43\x06\xb6\x03" + "\xac\xee\x5b\xe0\xdf\x53\x6e\xcd" + "\xcd\x25\x33\xbc\x62\xe8\xf1\xf2" + "\xc3\x03\x4f\x77\x21\x79\x0f\xdd" + "\x1b\xcc\x52\x45\x21\x72\xca\x97" + + "\xea\x46\xec\x9c\xf0\x4a\x9a\xe7" + "\xc7\x9b\x8b\x65\xa1\x47\x53\xb1" + "\x75\x2f\xaf\x35\x6f\x79\xd2\x6b" + "\x35\xc4\x51\x40\x90\x79\x95\xac" + "\x5d\x65\x3a\xc3\xa3\xdd\x69\x26" + "\xa3\x4a\x51\x88\x2e\x3c\x50\x5d" + "\x41\xdd\x53\x37\x37\x13\xa1\xdf" + "\x78\x4f\x75\x0b\x73\x46\x05\x3f" + + "\xd7\xc5\x24\xe2\xb5\xb3\x0c\x76" + "\x19\x69\x61\x68\x8c\xaf\x3b\xfa" + "\x52\x25\x14\x8d\x13\xa1\xbc\x9f" + "\xf5\xeb\x69\x76\xf1\x8b\xb1\x1a" + "\xdd\x25\xdf\x9b\x3e\xf5\xe6\x55" + "\x54\xd1\x6c\xcb\xf3\x0b\xcc\x04" + "\x80\x90\xe8\x95\x49\xef\x5b\x59" + "\xc1\x9a\x4a\x10\xa8\x59\x94\xfe" + + "\xf0\x3e\x12\xa8\x16\x63\xd6\x49" + "\x38\x54\xf9\xe7\xb4\x2d\xc3\x73" + "\x54\x78\x9e\x0d\x09\xd2\x2e\x2e" + "\x07\x05\x9f\x9d\x29\x93\x8a\xf9" + "\x0a\xa2\x6a\x0c\xf6\x3c\xd3\xc5" + "\xb2\x9b\x27\x75\x14\xba\x32\x9a" + "\x07\x73\x4a\x77\xcb\x02\x32\x7e" + "\xbd\x2d\xc4\xe8\xc4\x4b\xed\x64" + + "\xe8\x20\xb0\xab\xc5\x64\x4b\x69" + "\xc7\xee\xc4\x19\x84\xc1\x18\x3d" + "\xe5\x93\x47\x1c\xef\x73\x46\x9c" + "\xe6\x92\x60\x05\xb5\xae\xb8\xc7" + "\x6b\xc1\xf8\xf0\x43\xca\xa1\x3a" + "\xf6\xb2\x79\xd6\xec\xd5\x4e\x22" + "\xc9\x05\xa2\x55\xaf\xee\x56\x0d" + "\x8b\x02\x8e\x4b\xba\x15\xe1\xbf" + + "\xec\xf4\xac\x97\xb3\xa7\x22\x3e" + "\x40\xb6\xa8\x5e\x00\xc4\x26\x04" + "\x85\x92\x96\x4e\xa6\x95\x32\x5e" + "\x70\x56\xa4\xa6\x59\xbc\xaa\x22" + "\xbc\x42\x59\x5f\x4c\x71\x29\xb9" + "\xed\x82\x31\xfa\xbd\x68\x61\x9a" + "\xba\x52\x41\x10\x65\xa6\x16\x22" + "\x68\x63\x92\xb6\x03\x8d\x90\x46" + + "\x50\xa8\xcb\x7f\x24\xe0\x8b\x9b" + "\x1e\x18\x0a\x82\x97\x57\xeb\x81" + "\x11\x12\xa0\x30\x22\x81\xf2\xa0" + "\x21\x88\x7b\xae\x3c\xdc\x9c\x7e" + "\xe7\x15\xce\x72\xcc\x32\x23\x20" + "\xd7\x38\x82\xcb\xbb\xb2\x3c\xcd" + "\x43\x2c\xe8\xc6\xdf\x63\xab\xe4" + "\x17\xd7\x83\x31\x28\x00\xbd\x58" + + "\xab\x42\x29\xf3\xe8\x46\x8d\xd1" + "\x18\x24\x88\x10\xf6\x6e\x76\x6c" + "\x6b\xcd\xc6\x0c\x1a\xcb\xff\x8e" + "\x60\x59\xd8\x68\x5c\xa0\x1d\x5a" + "\x1c\x6e\x29\x32\xa5\xf4\xa5\xc7" + "\xc8\x2e\x0d\xc9\x43\x1e\x0f\x3d" + "\xd9\x29\x97\x89\x22\x3a\x94\x29" + "\x17\x53\x0e\x36\x26\x8a\x7a\x87" + + "\xb5\xd7\x7e\x71\x7e\x7b\xd5\x02" + "\xa2\xe1\xbc\x4d\x24\x5b\x2e\xd2" + "\xf5\xdc\x4c\x2a\x71\xd7\x4b\x17" + "\xbb\x05\x82\x40\x01\xb8\xfd\xa6" + "\xe9\x87\x13\x5e\x69\xb0\xb4\x67" + "\x42\xa4\x91\x05\xa1\x19\x2b\x33" + "\x66\xf3\xac\xcc\x16\xd9\xed\x24" + "\x50\x8a\x95\x34\x45\xcc\x34\xbe" + + "\x4b\x18\x1c\x06\x99\x76\x59\x81" + "\x52\x89\x89\x63\x5c\x10\x3d\x65" + "\xad\xfc\x5e\x7b\xde\x06\x91\xda" + "\x52\x14\xa6\x8a\xa6\x5a\x33\xa0" + "\x04\xba\xfa\x4f\x89\x7c\x7d\x33" + "\xf6\x90\xa9\x8e\xfe\xd4\xce\x9d" + "\x28\x57\x8c\x26\xb6\xb3\x28\x36" + "\xec\x21\xaa\xc2\x89\x70\x93\xf9" + + "\x91\xd3\x66\x3e\x1e\x6e\xf4\xa3" + "\xb2\x69\x63\x7d\xcd\x32\xa7\xb4" + "\x22\x10\x2c\x40\x5d\xb8\xc3\x99" + "\x2e\x93\x54\x2b\xbe\xfc\xcc\x7d" + "\xe2\xdf\xb1\x56\x7b\xaa\xdd\xa6" + "\xc9\x82\x4a\xe3\xa5\x78\xdc\x31" + "\x41\x39\x4f\x70\xda\xb3\xbe\x8a" + "\x98\xfa\x55\xca\x6c\xa3\x11\xdf" + + "\x66\x19\x86\x89\x34\x8e\x3b\xd5" + "\x6b\x99\xea\xa0\xa1\x20\xfb\x79" + "\x43\x7f\xd3\x5a\xd9\x47\x06\x30" + "\xcd\xe3\xa7\x53\xa8\xb4\x4d\xb4" + "\xfb\x59\x66\x2e\xb9\xe1\xe3\x9e" + "\x20\x72\x68\x5f\x72\x63\x32\x4b" + "\x43\x01\xa1\xb1\x25\x68\xc2\x6e" + "\x0b\x6f\x7d\x86\x2b\x76\xb6\xb4" + + "\x1b\x0c\xe0\x16\x7a\xf7\x01\x6c" + "\xac\xaa\x9e\x83\x90\x54\x51\x82" + "\x34\xd3\x70\x34\xef\xa4\xf3\x62" + "\x6c\xcd\x1d\x1c\x49\xa6\x29\x5a" + "\x25\x7a\x99\xce\x2e\x78\xb6\x46" + "\x53\x99\x57\xd3\x35\xfb\x78\x99" + "\xce\xe0\x60\x09\xdf\xa9\xf5\x98" + "\x4c\x7a\x52\x1f\x39\xc8\x7d\x54" + + "\xc1\xbc\xba\xc2\xc6\x8a\xcb\x52" + "\x8d\xae\x81\xfe\x48\xd4\x48\x47" + "\x11\xa7\xf1\x80\x3f\xf0\x44\x58" + "\xc4\x4a\xdf\xf8\xb2\x84\xb7\x3d" + "\x36\xfe\xf1\x2d\x12\x8f\x91\xad" + "\xc0\xc7\x3c\xf3\xb9\x25\x0f\xe4" + "\x55\x55\x5e\x3b\xe7\xd0\x00\x47" + "\xf9\x26\x33\xb0\x08\xfa\x28\x5c" + + "\x4f\xc2\x9d\x5d\x83\x15\x5b\x39" + "\x80\xe6\x3a\xc7\x32\x69\x25\xa4" + "\xe9\xc8\xa2\xfa\x0e\x96\x42\x05" + "\x6a\x8c\x06\x71\xee\xad\xb3\x2b" + "\x54\x45\x0b\x57\x9b\x09\x06\xa7" + "\xd6\x78\xe2\xf4\xb5\x2b\xd1\x85" + "\x43\x68\x29\x64\xf6\xf6\x8a\xd7" + "\x33\xc6\x28\x84\x88\xb3\xd3\xc7" + + "\x58\x97\x3f\xdb\x09\x67\x3b\x4c" + "\x1a\x8c\x1d\x34\x4e\xda\x9e\x16" + "\xd2\xa6\x13\x96\x18\x2f\x4f\xbd" + "\x36\xa5\xcd\xd7\x4e\x2b\x00\x9a" + "\xb9\x03\x61\x77\xd1\xf8\xbd\x97" + "\xba\x45\x79\xb3\x34\x0d\x67\x9c" + "\xbf\x5b\x8c\xd7\x84\xe3\x83\x9b" + "\xb2\x14\x8d\x51\xcf\x3b\x2d\x6e" + + "\x97\xe5\xb7\x43\x93\x4f\xd4\x34" + "\x42\x0f\x53\xc2\xa7\x40\xe4\xdd" + "\xb9\xbd\x56\x78\x81\xa0\x70\x72" + "\x2f\x03\x53\x53\xeb\x45\xa9\x86" + "\x10\x98\xd3\x66\x99\x8e\x2f\x6c" + "\x6b\x4b\x8b\x9b\x1b\xa3\x42\x06" + "\x82\x9d\x50\xd1\x62\x9e\x67\x51" + "\x16\xff\xf8\x90\x1c\x00\x20\x01" + + "\x4a\xe3\x36\x2e\x06\xc1\xa1\x50" + "\x1a\xed\x24\xe0\x8c\xf5\xe8\x74" + "\x26\xd7\x00\x13\xfa\x1d\x0f\x3f" + "\x18\x2d\x4a\x7b\x26\xdf\x80\x66" + "\xb7\xb3\x35\x82\x9d\x97\xb5\x12" + "\x93\x14\x61\x8a\xcb\xaf\x2f\x1d" + "\xe5\xec\x48\x88\x96\xda\xeb\x73" + "\x99\xe3\x13\xa4\x75\xc2\x96\xe9" + + "\x00\xf0\x5f\x49\xc7\xd7\xb7\x46" + "\xd1\x95\xed\xba\x97\xd0\x0e\xe6" + "\xc0\xf9\x38\x6e\xac\x04\x88\xaa" + "\xbb\xf9\xc6\x45\x06\x0c\x99\x92" + "\x51\x98\x91\xc0\x39\xa4\xe6\xca" + "\xf2\xe1\xf5\x1b\x15\xff\x3d\x71" + "\xdb\x8c\xb3\x2e\x30\x2c\x26\x5d" + "\xdf\x31\xdf\x90\x51\x50\x3d\xb7" + + "\xe5\x2f\x5b\xe5\xc2\x32\xc8\x85" + "\xfc\xde\x19\x91\x65\x21\x51\xf2" + "\xe4\x0f\xb0\x99\xbc\xe3\xfd\xfc" + "\x17\x8b\x90\xd1\xe3\xf5\x67\x80" + "\x42\xae\x43\x14\xb3\xf6\x21\xe9" + "\x3b\x59\xea\x64\x92\xed\xcf\xa2" + "\x35\x7a\xe0\x59\x62\xb9\x89\x15" + "\xdd\x62\xa7\x0d\x0a\x39\xbb\xc6" + + "\x8c\x26\xd9\x32\x1c\x7b\x1e\x92" + "\xd4\xfa\x76\x42\x96\x2b\xdb\x34" + "\x30\xe7\x44\xcc\x34\x6d\xc5\x0e" + "\xb7\x45\x65\x09\x46\x3a\xbe\x59" + "\x6a\x3a\xcf\x66\x97\xbc\xfd\xe9" + "\x53\x9b\x4e\xd0\xed\x83\x2f\x7b" + "\xe7\xe3\xba\x8f\xcc\xb3\x99\x6d" + "\x40\x3a\xda\x7a\x6c\x64\xb5\x8e" + + "\xfb\x51\x12\x5a\x74\xd8\xf5\xa9" + "\xc7\x25\x27\xc7\xa8\x47\x77\x96" + "\x9e\xe8\xff\x31\xe5\x33\x5c\x19" + "\x5e\x93\x64\xe9\x0f\x21\x9d\x60" + "\x27\x22\xe1\x2f\xa8\x6c\xfd\xca" + "\x9d\x46\x26\x04\x96\x5b\x9b\xaf" + "\x3c\x18\x93\x56\x4c\xe0\x9e\x2e" + "\xef\x6f\x14\xc8\x33\xa3\x84\x10" + + + "\xf7\xd1\xd1\xae\x33\x99\x64\x96" + "\x90\x30\x56\x50\xf3\xaf\x6e\x56" + "\xcf\x39\x2e\xad\xf0\x57\x50\x34" + "\x24\x21\x83\x1f\x5b\xf6\x8f\x14" + "\x0d\xcf\x94\xcf\xd4\x89\x2e\x04" + "\xb3\x58\x0c\x52\x84\xec\x9b\x31" + "\x0d\xaa\x61\x53\x26\x76\x26\x2a" + "\xad\x87\xbc\x8f\x02\xa3\x6f\xc8" + + "\x6f\x69\xc1\xad\xe1\xd7\x66\x6b" + "\xd0\x72\xcd\x0a\x93\xe5\xeb\x98" + "\x35\x74\x1b\xcc\x50\x45\xf2\x65" + "\xec\xa5\xb9\xb4\x93\x13\x23\xce" + "\xf9\x7d\x06\xdb\xd4\x22\x4a\x23" + "\x00\x9b\xff\xca\x95\xa0\xdd\x98" + "\xc1\xc9\x00\x61\xa0\x75\xbc\x1b" + "\x95\xf6\x9c\x93\xc8\xa9\x60\x15" + + "\x74\xbf\x51\xfe\x5e\x32\x50\x08" + "\x94\x00\x46\x5e\x9e\x57\x4f\x9c" + "\x25\x2f\xda\x76\x2a\xb9\x87\x5c" + "\x33\xef\xeb\x6f\xe0\xe4\x9d\x88" + "\xce\x83\x60\x64\x06\xec\x00\x69" + "\x73\x27\xe1\xbf\x35\x03\x2a\xbe" + "\x10\x41\x34\xc5\x35\xda\xd1\xad" + "\x20\xcd\x02\xb8\xb7\x68\x75\x75" + + "\xca\x67\xc3\xf1\x1c\x0f\x05\xe4" + "\x7d\xbc\x0f\xc9\x9b\x5a\xc8\x9b" + "\x32\x10\xa1\xe1\xa2\xc4\x73\xa3" + "\xa9\x93\x03\xad\xb7\x32\x42\xb6" + "\x29\xad\x7d\x16\xb0\x7e\x57\xf5" + "\xb2\x8a\xb7\x94\x01\xf3\x04\x16" + "\x8b\x34\x29\xe8\xaf\x94\xaa\x0b" + "\x42\x43\x65\x41\xdd\xd8\xfb\x77" + + "\x2e\xcd\xa7\x94\xb4\x51\xf6\x6f" + "\x6c\x33\x99\x06\xd1\xff\x71\x56" + "\x6a\x89\x9a\x97\xcc\xd2\x5f\x6f" + "\xef\x8c\x14\xd8\xa8\x93\xe8\x11" + "\x10\x7b\xcf\x65\xa1\x06\x89\x98" + "\x85\x84\x0d\xc5\x78\x71\xb6\x81" + "\xde\xb3\x35\x8a\x35\xeb\x0d\x7c" + "\x99\x97\xd2\xc1\x55\xc8\x3a\x42" + + "\x08\x87\x61\x09\xe1\x69\x9f\x71" + "\xb1\xf9\x83\xc1\x64\x83\x9e\xcc" + "\xaf\x21\x6a\x36\x95\x3a\x20\xec" + "\x1f\x14\x8b\x06\x6d\x5d\xec\x6a" + "\xe9\x04\x4f\x99\x8a\xf7\x2d\xee" + "\xb0\x45\x12\x27\xe8\xca\x9c\xb3" + "\x4f\x3f\xe4\x97\xa9\xa4\x75\xb8" + "\x98\xea\x2c\xdb\x11\xfe\x7d\x50" + + "\x3d\x12\x32\x52\xea\x7a\x4b\x31" + "\xdb\x86\xae\x65\x8c\x7c\x30\x08" + "\xed\x68\x46\xaa\x5c\x16\xe7\x06" + "\x39\xec\xd3\xb4\x8b\x45\x70\xb1" + "\x86\xb9\x9b\xc1\xc6\x3e\x2e\x4d" + "\xed\x04\x03\xae\x46\x48\xf3\xc5" + "\x22\x97\x9f\x6c\xa0\x95\x76\x91" + "\x0a\x1c\xab\x4c\x17\x73\x7f\x6c" + + "\xfd\xa7\xf0\xfc\x02\x48\xf1\x31" + "\x1e\xb0\x88\x54\x89\x07\xfd\x42" + "\x98\xb4\x52\x99\x6d\x8d\xd7\x71" + "\x01\x52\xac\x07\xd9\x72\xb5\x8e" + "\x88\x4a\x19\x4d\x4c\xa4\xa2\xe0" + "\x66\x7e\x01\xba\xd9\x3f\xb6\xd2" + "\xfc\xae\x88\xf8\xc8\xc6\xef\x78" + "\x11\x1a\x88\x4a\xda\x6b\x6f\xb7" + + "\x38\x72\xa6\xb2\x01\xe1\x0b\xbf" + "\xf2\x14\x9c\xaf\x67\xd3\x56\x35" + "\x75\x20\x66\xa5\x31\x78\x4b\x10" + "\x0a\xe6\xd9\x79\xbb\x59\xca\x58" + "\x3b\xa7\x69\xa5\x92\x53\xc4\x4b" + "\xc9\xf6\x98\x56\xe8\x52\x7a\x51" + "\x55\xd7\xad\xae\xa5\x3d\x64\x85" + "\x84\x1b\x58\x2a\xd5\x0c\xed\x1a" + + "\x67\xe9\xf9\x19\xbc\x26\xf7\xa0" + "\x4e\xbf\xfb\xe8\x52\x31\xd0\xd9" + "\x40\x7d\x70\xb7\x1d\xf5\xd6\xcf" + "\xe0\xe6\xf6\x63\xd9\x84\x30\x63" + "\xaf\x7e\x66\x55\xdc\x9c\xcd\xed" + "\x6f\xd5\x44\x2e\x2b\xf9\xb7\x73" + "\x14\x2b\x96\x4e\xb6\x39\x2e\xfb" + "\xbf\xfc\x71\xf6\x6e\x8f\x40\x7d" + + "\x8a\xcf\xdf\xf8\x75\x30\xea\x9e" + "\x25\x98\x66\x95\xaa\xf0\x84\xa2" + "\xd8\x3f\x7d\x86\x50\xa2\xfc\xb3" + "\x1e\x69\x9d\x26\x5f\x7b\x75\x20" + "\xde\xa5\xb8\x93\x20\x40\xc2\xf2" + "\xa6\x6d\xc0\xeb\x59\x33\xf9\xd3" + "\x33\x9c\x73\xb2\x3e\x29\x78\x11" + "\xe5\x86\xd6\xbc\x70\xe7\xa3\xd2" + + "\xee\x43\xaf\x68\x2c\x93\xf7\xa2" + "\xbd\x00\x3d\x70\x8e\x46\x02\x55" + "\xf5\x61\xb0\x2f\x8f\x97\xdc\xe5" + "\xad\x15\xc8\x28\x4a\x90\xa1\xc9" + "\xa4\x56\x0c\x47\x8d\x53\xaf\xd3" + "\xed\x8c\x3d\x19\x5f\xbc\x9a\x15" + "\xf3\x8e\x10\x20\x5f\x24\x37\x2a" + "\x78\x71\x3f\x22\x1e\x08\x17\xfa" + + "\x3a\xa7\xf2\xec\x8d\x6e\x20\x2a" + "\x94\x19\x55\x8e\x97\x63\x6a\x06" + "\xa2\x53\x8d\xb9\x8a\x08\x6a\x3a" + "\xaa\x24\x11\x2d\x7c\xc6\xe7\x0c" + "\x3c\x11\x9a\x75\x71\xc6\xce\x48" + "\xfa\x67\x6f\x4f\xd3\x73\xb3\xe3" + "\x7b\x72\x36\xfd\x79\xd4\x55\x54" + "\x81\x0d\x3c\xa1\xee\x28\xa4\xe5" + + "\x5e\xbd\xb1\x16\x5f\xea\xfe\x6b" + "\xd3\x0a\xe3\x4d\x20\xe4\x57\xf9" + "\x9e\x3b\x35\x6a\x4e\x66\xaf\xcb" + "\xeb\x4f\xd1\x26\x12\x33\x87\x5c" + "\xcb\x57\x5f\xb6\x8c\xf9\x87\x4e" + "\x41\xdd\x0c\x5e\x21\xa6\x60\xdb" + "\x40\x14\x88\xa6\x65\x68\xc1\x67" + "\xaa\x52\xab\x46\x1a\xef\x93\x10" + + "\x64\xec\x2e\xbb\xba\xcb\xbc\x93" + "\xbe\xad\x03\xda\x64\x3b\xc2\xa0" + "\xc4\x6a\xe8\xe0\x0a\xa0\x7a\x5f" + "\xe6\x01\x14\xfc\x1e\x94\x0b\x47" + "\x74\x35\xf4\x9d\x79\xd6\xd8\x5a" + "\x10\xd8\x65\x0f\xa9\xb8\xcf\x4c" + "\x81\xbd\x7f\xaa\xe3\x80\xce\x1b" + "\x0a\xd2\x08\x95\xad\x91\x32\x27" + + "\x7c\xb6\xb4\xb4\xb2\xa9\xe2\x1f" + "\x04\x06\x02\xe8\xf0\x0d\xd1\xc1" + "\xd8\x58\x80\xbc\xfc\xab\x64\x9d" + "\xbb\x0f\x2a\x71\xb2\xb9\x43\x89" + "\x04\xef\x3d\x3b\x14\xd9\xee\x90" + "\xff\x75\xe7\x4c\xa2\x3a\xab\x85" + "\x40\x90\xbc\x7b\xca\xd4\x5f\x60" + "\xfb\x5d\xc7\xe2\x64\xa5\x34\x8b" + + "\x0f\x36\x82\xe3\x7c\x9f\x75\x25" + "\x57\x58\xbf\x88\xc9\x05\xdb\xb6" + "\x6c\xd4\x58\x6c\x1d\xd6\x17\x29" + "\x7a\xcb\x20\xfd\x91\xe4\xf8\x14" + "\x40\x03\xc2\x11\x7a\x72\x8a\xb6" + "\xb6\xcb\x7c\xaf\x6f\xf8\x86\x03" + "\x20\x9a\xe0\xfe\xcc\xc6\x8b\x5c" + "\x35\xea\x7e\xbb\x4a\xff\x76\x7d" + + "\x88\x52\x8a\xaa\xaa\xca\xab\x4d" + "\xc9\xa1\x23\xaf\x8a\x0c\xcc\x91" + "\x0c\x0e\x22\x3f\x6a\x2c\xc7\x34" + "\x4a\x14\x32\x12\xdf\x0b\xc2\xbc" + "\x1b\xde\x0e\xa2\xda\x42\x2f\x6e" + "\x15\x05\xa0\x74\x0c\xf0\x41\xc4" + "\x4b\x8c\x4b\x73\xb6\xa5\x46\xbf" + "\xa4\xc9\x56\x7b\x03\x95\x40\x57" + + "\x1b\x57\xf3\x3f\xa5\x36\x68\xb4" + "\xc1\x27\x79\x83\x78\x8b\xf9\x24" + "\x16\xc7\x33\x45\x6a\x25\x54\x62" + "\x96\xe1\x7e\xd0\x0b\xbb\x7a\xf2" + "\xfd\x5b\x6d\x5c\xfc\x64\xcf\xd7" + "\x77\x7a\xcd\xf0\x51\xc7\x15\x69" + "\x34\xf5\x98\x87\x12\x90\xf5\xd9" + "\x5f\x8b\x1d\xf8\xa8\x0d\x2b\x77" + + "\x90\x7d\x2f\x8e\xf8\xac\x18\x5c" + "\xcd\x32\xbe\x77\xd7\x33\xbf\xfd" + "\xe9\x5e\xeb\xd2\xd7\x5c\x08\x0a" + "\x15\x11\x20\xb3\xfb\x2c\x70\x2d" + "\xe8\x8c\xc8\x85\xdb\xeb\xe0\xb6" + "\x17\xd6\x01\x1e\x3c\xce\xa3\x23" + "\xac\x33\x73\x56\x8e\x61\x41\x30" + "\x6b\xdb\x7e\x15\x8f\xfd\xd0\x9d" + + "\xb0\xd1\x07\xce\x73\xda\x6b\x38" + "\x78\x41\xad\x58\xc2\x10\x29\xd8" + "\xf4\x17\x26\xcd\xcf\x82\x4f\x12" + "\x70\x17\x69\xef\x8d\x5e\x2f\xcc" + "\xcc\x0c\xc3\xb8\x50\x25\x70\x82" + "\x5a\x57\x8e\x1a\xea\x6a\x85\x7b" + "\x59\x94\xab\xb1\xef\x2f\x82\xbb" + "\x8e\xe3\x24\xec\xbc\x28\x59\x08" + + "\x71\x88\xb9\x8f\x11\x3d\x46\x80" + "\xff\x6a\xc7\xbb\xc3\xf5\x26\xcb" + "\x14\x36\xe0\xfb\xdd\x8e\xab\xd4" + "\xee\x2d\xcf\xc0\x9b\x57\xeb\xc8" + "\x41\xae\x3b\xc9\x15\x4c\x00\xcc" + "\xb2\xa3\xec\x3a\x5d\xae\xfb\x46" + "\xb1\x9a\x1e\x0f\xcf\x35\x12\x67" + "\xc1\x85\xc2\x9e\x34\xa9\xfb\xad" + + "\x77\x64\x7c\xb5\x6b\x93\x6c\xa3" + "\xc6\xbc\x4d\xe9\x64\x8b\x1f\x87" + "\x7b\xa6\x91\xa5\x62\xfb\xd0\x28" + "\xf5\x26\xd9\xc1\x81\xe0\x40\x9d" + "\x5a\x4b\xd8\xf2\xf6\xea\x11\x31" + "\x44\xb6\x65\xa5\xf9\x93\x89\x22" + "\x8b\x18\x83\x2c\x92\xf5\xcb\x0c" + "\x97\xe1\xf3\x3d\xab\x30\x7b\xf8" + + "\xaa\x7a\xfa\x98\x07\x61\xb2\xb2" + "\x4e\xaa\x73\xf0\xe4\x9e\x20\x41" + "\x9b\xb1\xd6\xf2\x59\x03\x57\xf1" + "\xaf\x7c\x57\xfc\x8c\x86\xe6\xcb" + "\xd3\x4d\xc0\x32\xdc\x4b\x6c\x18" + "\x97\xe3\xee\xcf\xae\x5f\xc3\xa6" + "\xcf\xc0\x86\xf0\x12\xb3\xa1\xb4" + "\xe2\x1f\x46\xd9\xc6\xcc\xa5\xe0" + + "\xd3\xe5\xaa\xa7\x79\x26\x4e\xd2" + "\xc4\xc1\xe5\x0d\x3d\x01\x76\x70" + "\x29\xb6\x05\xbb\xba\xf8\x50\x2d" + "\xbb\xef\x66\x6e\xe2\xab\xc1\x73" + "\xf7\x8a\x48\xf2\x22\xb4\xd4\xef" + "\x75\xa5\x3b\x66\x02\x5d\x10\xe4" + "\x57\x94\xa6\x53\x8b\x0a\xb6\x7e" + "\x3b\x97\x45\xc9\x08\x00\x21\x62" + + "\xfb\xab\x66\x4b\x86\x32\x8e\x1d" + "\x00\x09\x03\x59\xe5\x52\x6f\xd2" + "\x1a\x94\x84\x55\x43\xf6\xe3\x1e" + "\x58\x59\x9f\x56\x30\x37\x3b\x6d" + "\xa5\xdb\x89\x47\x2f\xa6\xf2\x9f" + "\xb7\xc9\xb5\x72\x15\xb8\xfc\x91" + "\x0e\x9a\x8f\x6c\x7d\xcb\x46\xf4" + "\xb5\xec\xb7\x39\xc1\x25\xf6\x48" + + "\x12\x81\x44\x30\x77\x14\x7c\x7b" + "\x56\x86\xa3\xe4\xf1\x1a\xb5\x82" + "\x10\x50\x31\x2f\x8a\x02\xf2\x2b" + "\xd4\x8c\xa8\x6e\x1f\xa0\xa4\xc9" + "\x18\x58\x7e\x25\xd8\x95\x3e\xf6" + "\x16\x9b\x51\xb4\x10\xfa\x8e\xdd" + "\xbf\x10\xa9\x0d\xe0\x73\x89\xed" + "\xa9\xe4\x0f\x5c\x77\xd0\x49\xed" + + "\x0c\x11\xa6\x6f\xa3\xf3\x6f\x51" + "\x1f\x56\x93\xfb\xb1\x1e\xfb\x74" + "\x2b\x52\x57\x84\x47\x90\x0c\x6c" + "\xc6\xbd\xb8\x6b\x04\x21\xd3\xcf" + "\x57\xad\x80\xcc\xa2\x84\x68\x2d" + "\x37\xb6\xa9\x86\x35\xfc\x27\x7c" + "\xcd\xe8\xf4\xad\xed\xba\x61\x34" + "\xf0\x42\x72\x61\x1a\x25\x56\x1d" + + "\x94\xe0\x95\xa9\xd1\x46\x99\x71" + "\xd8\x04\x1e\xe5\xf6\x48\xe8\x65" + "\x13\x31\x1e\x6a\x00\x33\x2f\xe6" + "\x03\xe5\x1d\x50\xc1\xc7\x41\x15" + "\xde\xfa\xac\xf4\xfa\xc9\xaa\x4d" + "\x71\x0b\xcd\x44\x97\x58\x58\x0e" + "\x77\xcd\x51\x0a\x69\xd8\x4f\x54" + "\x6d\x01\x31\x00\xed\x20\xfc\x60" + + "\x44\x44\xdb\x64\xaf\x12\xe7\x3f" + "\x80\xd4\xcd\xbe\x34\xd6\xe9\x19" + "\x8a\x97\x30\xa9\x47\xc0\x8b\xe0" + "\x33\x07\x28\xa1\xec\x24\xbf\x2d" + "\xb2\x06\xd7\x2c\x8c\xe3\x0a\x3c" + "\xb9\x17\x90\x35\x5b\x2a\x01\x5b" + "\xae\xf5\xe0\x72\x8c\xc3\x43\x39" + "\xa3\x6f\x17\x57\xea\x67\x61\x78" + + "\xb1\x49\xea\xab\xb7\x9f\x97\xfa" + "\xc5\xc6\xe2\x10\x7d\xd2\xb1\xb4" + "\x7a\xde\xaf\x23\xc4\xc2\x61\xbd" + "\x58\xd3\x86\x97\xf8\x14\x66\xeb" + "\x59\x74\x6f\x7f\x6b\x81\x5d\x4a" + "\x7b\x0e\x36\x09\x4f\xa4\x31\xe4" + "\x4c\x91\x09\xc3\x32\xa0\x27\x8c" + "\xd8\xe3\xed\xca\x8a\xd6\xa5\xce" + + "\x0e\xd8\x1d\x43\xa9\x11\x40\xb8" + "\xd9\x6c\x30\x73\xca\x7c\x7c\xeb" + "\x30\xb7\xb3\xd1\x29\xdd\xfa\x20" + "\xd3\xb3\x37\xfe\x5b\x8b\x85\x83" + "\x5c\x1d\x25\xb6\x93\xd1\x4c\xbf" + "\x52\xd9\x52\x13\xd3\x1f\xca\x1c" + "\x51\xc0\xfb\x90\xa4\x57\x61\xc6" + "\x36\x86\xb9\x89\x38\xa6\x90\x79" + + + "\xe1\xc0\xde\x87\x2a\x69\xaa\xe5" + "\x00\x9d\xb3\xf7\x8d\xed\x0d\x01" + "\xb5\xa0\xcf\x54\xc8\x80\x1b\x7b" + "\x28\xea\xf8\xa0\x76\xb8\xbe\x66" + "\x0e\xcd\x76\x34\x31\xf5\xd7\x50" + "\x49\x39\x8d\xb0\x65\x0e\x3d\xa6" + "\xc6\x9f\x47\x53\xa9\xee\x09\x1a" + "\x42\xe7\x99\xf4\x91\x98\xae\x82" + + "\x66\xd8\xa7\x5c\x10\xb9\x58\xab" + "\x34\x3b\xdb\x3a\xe2\x67\x29\x58" + "\xbc\xc0\xea\xcc\x47\x44\xae\x89" + "\xf5\x6a\xf5\x7b\x7c\x66\x9c\x91" + "\xd7\xdc\xf5\x60\xb1\x17\xec\x9a" + "\xbc\xad\xca\xdd\x9f\x7b\x69\xec" + "\xf5\x67\x34\x46\x41\xf3\x98\x0b" + "\x2f\x13\x67\xa9\xf7\xf1\x87\xb1" + + "\x18\xeb\x4a\x21\x1d\x7a\xfe\x90" + "\xf7\x32\x14\x74\x3c\xaf\x06\x15" + "\xc4\xa0\x91\xe5\xf9\x65\x55\xbb" + "\xc3\x1b\x4f\xb4\x77\x1a\xd4\x10" + "\x96\xde\x4b\xa8\xe4\x65\x9d\xa0" + "\x1c\x6a\x0a\xf2\xd8\x60\xf0\x42" + "\xe7\x9c\x7f\xf2\xfd\x3b\x2a\x65" + "\x9f\x73\x3d\x3b\x5c\xb6\xbd\xb6" + + "\x9f\xae\x7f\xec\xb6\xdc\x5d\xeb" + "\x5a\x6e\xb6\xef\x14\x27\x5f\x99" + "\x52\x5d\x44\x69\x8e\x5d\xe9\xde" + "\x20\x76\xe2\x09\x46\x2d\x6c\x1b" + "\x16\xd7\x29\x81\x31\x1c\x62\x32" + "\xaa\xc1\x58\x09\xf1\x09\x39\xb0" + "\x63\xaf\xf4\x1a\xf9\x8e\x46\x8c" + "\xf6\xcd\xa5\xfb\x9f\x42\x2c\x16" + + "\x71\x93\x3b\x75\x43\x23\x68\x2f" + "\xd7\x9c\x1f\x5f\x5a\xb4\xca\x29" + "\x96\xdb\x45\xb2\xab\x23\x16\x57" + "\x99\x99\xd7\x3f\x09\xdb\x07\xc5" + "\x32\x6c\x03\xaf\x52\xf6\x2e\x4e" + "\x5c\x8e\x01\x05\x78\xcc\xf0\x86" + "\x50\xe3\x8b\xab\xd4\x73\x0a\xc1" + "\x27\x63\x82\x7e\x97\xb3\x19\x65" + + "\xf7\x3d\x05\x9c\xef\x5e\xcb\xe8" + "\x6f\xea\x00\xb3\x37\x5b\xe2\x8d" + "\xfb\xcf\x49\xc8\x92\xfa\x03\xdb" + "\xbb\x69\x41\xe8\xa7\x43\x2e\x24" + "\x8e\x95\x6f\xdd\xf4\x51\xfa\xe4" + "\x8d\x5a\x44\xf4\x7f\xa7\x25\x69" + "\x49\x89\x0d\xe9\x50\x2a\xe7\xe6" + "\x90\x63\x1f\x2b\xe3\x48\x66\xc6" + + "\x0c\x46\x3e\x17\x57\x19\xab\xb2" + "\x90\x45\x70\x30\x75\xce\xbb\x1b" + "\x62\x71\x1c\xdb\xbd\x0d\xa9\xc0" + "\x5d\xd6\xcd\x15\x9e\x39\x5e\x50" + "\xb7\x7a\x79\x57\xcb\x4d\x43\x68" + "\xe8\xa8\x2c\x6a\xba\x35\xad\x60" + "\xc1\x36\x33\xde\xe0\xb1\xfd\x4b" + "\x15\x90\xb3\xd8\xeb\x99\xef\xbb" + + "\xec\xeb\x11\x17\xf3\x96\x3b\x6c" + "\xc4\xfd\x98\xce\x1f\x0f\xa4\x2d" + "\x1f\x41\xb4\x57\xd3\x74\x97\xb9" + "\xb6\x5b\xb6\x15\xf4\xbd\xc8\x87" + "\x2d\xf1\xee\xc2\xe3\x89\x3a\xda" + "\xf3\x71\x74\x3c\x9b\xbb\x95\xde" + "\x94\xc5\x12\xd8\x5b\x22\x0f\x60" + "\x6b\xa5\x75\x2b\x5d\x7c\x90\x54" + + "\x35\x0e\xb6\x8d\xf0\xc5\x3c\xa9" + "\x19\x33\x83\xfa\xd6\x3c\x3e\x74" + "\xc9\x83\x16\xf8\x41\x5c\xad\x7d" + "\x7e\x10\x34\x9c\xd9\xe7\xc1\x70" + "\x07\x09\xbe\xa6\x39\x4a\xdc\x0e" + "\xd3\xb7\xd0\x86\x35\x70\xd4\x36" + "\x60\xfa\x2b\x27\x03\xda\x76\x8c" + "\x14\xa4\x08\x0f\xea\x07\x4a\x0b" + + "\x53\xdd\xc1\x45\x29\x4d\x9e\x69" + "\xb5\xeb\x1d\x23\x98\x58\xdc\xca" + "\xe0\x00\x7f\xa7\xc7\xfc\x49\xdf" + "\x0e\x5a\x3e\xa7\xbf\x7b\x05\x93" + "\xd1\x4c\x7a\x02\xcd\x7e\x8b\x2f" + "\x1a\x01\x14\xc6\xb3\x34\x47\x11" + "\x68\x7c\x67\x67\xb7\x1d\xa0\xe7" + "\x4f\x3f\x27\x7e\x5e\xbe\xd9\x89" + + "\xef\x08\x98\x08\x2e\xcb\x25\xd2" + "\x07\x41\x9e\xd5\x7d\xa2\xf7\xf1" + "\xc9\xb9\x11\x82\x61\xc7\xaf\x53" + "\x59\x91\x81\xe6\x67\xbc\x61\x03" + "\x26\x14\x07\x7f\x0b\x5d\x86\x2a" + "\x67\x25\x07\xe7\x10\x18\x3c\x6a" + "\xbd\xca\x6b\x0d\x1e\xca\x3b\x3e" + "\xbc\x91\x85\x40\xc1\x2b\xb0\xa1" + + "\x39\xa2\xfb\x31\x59\xee\xde\xe0" + "\xd1\x91\xbd\x98\xd3\x24\x74\xf4" + "\x1d\x3c\x1a\x07\xf4\x86\x88\x0f" + "\x3b\x23\x19\xa8\xe8\x41\x7d\x3f" + "\x98\xb9\x6e\xcf\xc2\x23\x86\x70" + "\x7f\x28\x9a\x60\xaf\x49\xbb\x86" + "\x62\x07\xc9\x63\x49\xb2\x2b\x94" + "\x4b\x65\xa9\x55\xa5\xee\xf6\x0e" + + "\xfe\xde\xf5\x36\x72\x2d\x6d\x5f" + "\x76\x91\xf9\x56\xdc\x22\x99\xfa" + "\xc7\xe0\x8c\xf7\xce\x5e\x8c\x6c" + "\x5e\xb5\x09\xbe\x9d\x58\x44\x7b" + "\x70\x37\xa8\x9e\xca\x3b\x1b\xe1" + "\x47\x15\xb7\x2a\x7f\x2c\xfa\xd7" + "\xc0\xdc\x1d\x2a\xfa\xd6\x3d\x2a" + "\x07\x77\x7b\x5a\x30\xb4\xac\x09" + + "\x57\x4e\x9d\x64\x2e\x4a\xdd\x4a" + "\x6e\x52\x17\x19\xb0\xa2\x53\xcd" + "\xc4\x4a\xb4\x20\x30\x23\x26\xc5" + "\x1d\xc3\xa2\xba\x6a\x74\x28\x40" + "\x4c\x1d\x29\x64\x90\x83\x31\x51" + "\x09\xd9\x5a\xee\x51\xf1\x48\xbf" + "\x81\x56\x18\x7b\x59\x7f\xe5\xcc" + "\x42\xd4\x54\x48\xb0\xc1\x3a\x7c" + + "\x71\xc1\x93\xc0\xc3\x7d\x58\x65" + "\x65\x2b\xf4\x24\x24\xcb\x7a\xae" + "\xcb\x96\x59\x95\xdb\x8a\x33\x5a" + "\x1b\xf9\x51\x60\x75\x56\xe6\xc8" + "\xb1\xd0\xb8\x28\xba\x1f\x71\x66" + "\x90\x0a\xc1\xb6\x37\x41\xd7\x15" + "\x80\x2a\x23\x3a\xeb\xd7\xcd\x70" + "\x24\xed\x91\x61\x7f\xf0\xe2\xc9" + + "\xc0\x88\x95\xf7\xb6\x1d\x0d\xa8" + "\xcc\x68\x57\xb5\x69\xfc\x52\xfa" + "\x8a\x43\x54\x7f\xae\xf1\x4d\x0b" + "\x4f\x6a\xb4\xf9\xa7\xd1\xad\x0c" + "\x6f\xdd\x03\x18\xb3\xa6\x0e\xb4" + "\x35\xae\xea\x55\xa5\x4f\x8e\x48" + "\x16\x4e\x2e\x38\x55\x7d\x04\x9f" + "\x98\x0c\x6e\x2f\xe0\xb7\xb5\xc9" + + "\x49\x26\x76\x95\xd3\xd2\x1b\x6b" + "\xf6\xa3\xae\xc7\xe7\x4e\x60\xa9" + "\x96\xf8\xc6\x6d\x27\xff\x46\x36" + "\xd1\xba\x60\x28\xf5\xe7\xf0\x9b" + "\x92\x4b\xb4\x7c\x21\xc8\x92\x2d" + "\x82\xc1\xa9\xae\x63\xce\xf5\xa2" + "\xfd\xa5\x54\x91\xb1\xaf\xa2\xd0" + "\xa6\x1d\x80\x95\x4c\x47\x2e\x48" + + "\x4b\xc2\x11\xb6\xd0\x72\x99\xc1" + "\x51\xf3\xa8\x60\x65\x8e\x46\x1d" + "\x21\x64\xcf\x7b\x69\x80\x75\xeb" + "\x91\xc4\xfb\x88\xee\xd0\x9d\xec" + "\x32\x2e\x6c\x95\xbf\xd2\x59\x5b" + "\x4e\xf9\xdd\xdc\x64\x68\xdc\x73" + "\x65\x76\xee\xbc\x21\x23\x5e\xfd" + "\xc4\x06\x9a\x5e\xef\xf8\xb4\xa7" + + "\x55\xf8\x80\x72\xdd\x18\xa9\xfb" + "\x88\xc6\xae\x8b\x60\xc2\xaa\xbb" + "\x42\x0f\x40\x33\x0f\xf0\xb3\xa3" + "\xe4\xe6\xf2\x66\x29\xba\x2d\x3d" + "\x75\x93\x50\x98\x94\x1a\xf7\xb6" + "\xcc\x23\xa4\xce\x1f\x03\x33\x8f" + "\xfb\xe6\x07\x48\xd0\x8d\x9b\x00" + "\x4c\x95\xdb\x5c\xe5\xcf\x63\x51" + + "\xe8\xc6\x41\xcf\x17\x8f\xcc\x03" + "\x5c\x92\x7b\x03\x2a\x3c\xf0\xf1" + "\x7c\x42\xd2\x66\xcc\x19\x9c\xc3" + "\xe4\x18\x6c\x7b\xba\x24\x3d\x82" + "\x4f\x0b\x1f\x90\x13\x90\xef\x32" + "\x2e\x1c\x94\xf8\xf1\x60\x43\x68" + "\x2e\x09\x28\x2c\x52\xff\xba\x0e" + "\x2f\x93\x6c\x25\xe3\xe4\x91\x78" + + "\x3d\x5e\x44\xac\x19\x43\x26\x51" + "\x81\x43\xa7\x8e\xe7\x32\x34\x55" + "\x0a\xc5\xe9\x67\x69\xaa\xee\xe6" + "\xc7\x28\xe6\x62\x84\xd2\xce\x27" + "\x57\xfa\x4a\x7a\x75\xd3\x96\x3f" + "\x50\xc1\x84\xe4\xc3\x14\x0a\xde" + "\x23\x99\xbd\x38\xeb\x24\x4a\x36" + "\x22\x74\x17\xe5\xa0\x8d\xf1\x1d" + + "\x9b\x8a\xd3\xd8\x82\x8f\x4e\x17" + "\x91\x13\xde\xe7\x00\xc6\x97\x2e" + "\xdd\x75\xc1\xa1\x50\x98\x70\xc5" + "\x35\x50\xae\x32\xa0\x41\x90\x96" + "\x6b\x08\xa2\x76\x3b\x53\xfd\xcb" + "\xfe\xe8\xc2\xd7\x1b\xa7\xbb\xd6" + "\x67\xfb\x9d\x09\xe6\x8e\xd5\xb2" + "\xd9\x85\x4a\x06\x2d\x34\x8b\x3a" + + "\xe3\x9b\x2f\x52\x49\x76\xc0\x3b" + "\xa8\x49\x1f\xdf\x5b\x07\x0c\x69" + "\x42\xec\x54\x38\xe8\xae\xe1\x80" + "\xc7\x9d\x68\x17\x44\xbf\x7d\x2a" + "\x78\x40\xaf\x3f\x0e\xfc\x04\xc0" + "\x2c\x86\x11\xdf\x9e\x2e\xf0\xb2" + "\xb3\xb7\xa1\xa0\x0f\x5e\x0a\xf1" + "\x80\xec\x36\x89\x23\xa6\xac\x30" + + "\x9a\x0d\xf4\x02\x05\xbf\x3c\xf8" + "\x4d\x8a\x31\x2c\x68\xc4\x81\x46" + "\x74\x26\x9c\x0e\x18\x56\x57\x98" + "\x2e\x09\x47\x18\x46\xd0\x79\xbe" + "\xe0\x01\xbd\x78\x0a\x48\x1e\xaf" + "\xb9\x1d\xa5\x72\xe4\x59\xd3\x6d" + "\xb6\xba\xaf\xe3\x21\x38\xce\x62" + "\x99\x31\x73\x17\xb6\xe5\xce\xc5" + + "\xbb\x9f\xfd\x6f\xd4\x30\x8b\xe0" + "\xb7\x10\xc6\x36\x99\xc6\x5b\x6e" + "\xcf\x62\xe2\x9c\xf2\xcf\x43\xf3" + "\xc1\x14\xb9\x68\x35\x4e\x2e\xca" + "\xc5\x36\xde\x16\xc0\x64\x1d\x01" + "\x29\xb8\xe2\x42\xdd\x0f\xb1\xe0" + "\xf8\xaa\x85\x66\x81\x29\x94\x78" + "\x97\xde\x0e\x23\x08\x17\x51\xe7" + + "\xf8\x2b\x92\x3b\xfc\xd8\x1e\x67" + "\x33\xb1\x29\x4c\xa0\xc0\xd8\xe4" + "\xc4\x99\x6e\x3b\x39\x12\xeb\x87" + "\xba\xbe\x93\x87\x4c\x97\xf3\xaf" + "\x9b\xdf\x18\x2c\x05\x94\x74\x03" + "\x39\x71\x00\x91\x93\xa2\xc3\xc5" + "\x95\x0b\x7a\xe3\x4f\x23\x77\x6a" + "\x6b\xc9\x61\xb6\x21\x9a\xc2\x02" + + "\x61\xcf\x1e\x14\xd6\xf1\xaa\xc3" + "\x53\x2f\xb2\x3b\x9e\x50\x95\x91" + "\x57\x13\xd5\x22\x04\x74\x59\x29" + "\x60\xed\x7b\x53\x22\x38\x08\x1b" + "\xf0\x89\x72\xe0\x35\x6e\x7d\xcd" + "\xff\x6e\xd8\x6d\x8c\xc4\x94\x1f" + "\xfa\x9c\x0f\xeb\x82\x1f\xbb\xc8" + "\x7d\xb9\x2e\x1b\xe6\xb7\xe0\x9e" + + "\x31\x4e\xd7\x34\x2e\xfe\x52\x5a" + "\xb6\x9a\xf7\x3b\x10\xc3\x52\xa3" + "\x8f\xeb\xfe\xab\x5a\x6c\xff\x97" + "\x05\x73\xc9\xf5\xef\x8f\xbe\xbf" + "\x08\x46\x90\xa7\xe6\x1c\x08\xd6" + "\x49\xa2\xfc\xc4\x3a\x2f\x81\x1f" + "\x00\xe2\xe5\xb9\x9a\xbc\x24\x9b" + "\xe8\x2e\x01\x38\x67\x2c\x02\x91" + + "\xa1\x13\xa7\x30\x5d\x9c\x3d\xe8" + "\x93\x0f\xef\x84\xf0\xe3\x76\x48" + "\x28\xf9\xfb\xc1\x29\x70\x77\xc9" + "\xa4\xd2\xe7\xbc\xb3\x6b\x7a\xef" + "\x59\xa6\xa2\xdf\x28\x72\x06\xb8" + "\x8f\xa4\x77\xd8\x98\x33\xcd\xd5" + "\x3f\x0f\x5d\x02\x8f\xfd\xa4\xbe" + "\x2b\x7c\xae\x2e\x35\x2e\x7d\xd6" + + "\x94\x43\x5f\xcc\xd7\xe7\x4d\x18" + "\x42\xe1\x36\x45\x5c\x1b\x55\xb5" + "\x0a\xa6\x4a\xd3\x12\xb2\x89\x2e" + "\xd5\x51\x00\xf5\xea\x6f\xa9\x14" + "\x0b\xbb\x12\x0d\x74\xef\x21\x4e" + "\x7e\x67\xb9\x60\x20\xf0\x22\xc5" + "\x1d\x73\xf7\x2d\x67\xe4\x12\x8b" + "\x31\x6d\x32\x7b\x82\x03\xf8\x39" + + "\x94\x4a\x02\x39\x0c\x63\xb8\xdf" + "\x52\x94\x31\x97\xa8\x96\xcb\xaa" + "\x7c\x86\xa3\xed\x61\x39\x8a\xd6" + "\xca\xff\xc4\x77\xb0\xe2\x58\x0c" + "\xfa\x19\xa9\x4d\x63\x5d\x54\x3d" + "\x89\x22\x5e\xf1\x9a\xb6\x79\xef" + "\x10\xab\x8b\x80\x3d\x3d\xbc\x54" + "\x37\x2c\xf8\x45\x07\x30\xab\xc8" + + "\x8a\x65\x4a\x7c\xb6\x38\x27\xc1" + "\x82\x21\xe7\x40\x39\x76\xc4\xb3" + "\x4f\xe4\x98\x87\x46\xbe\x77\x3b" + "\x5f\xf8\xa7\x17\xf2\x7d\x04\xdc" + "\x2d\xd9\x59\x5e\xc5\xd4\x39\x24" + "\x8d\x4d\xe6\xe8\x75\xa4\xdc\xce" + "\x16\x9b\xca\x87\x0d\xcd\x24\xa7" + "\xfe\x0d\x54\xa5\x59\xfd\xe4\x35" + + + "\x7a\x46\x29\x3a\x4f\x34\x94\x98" + "\x6d\xba\x1e\xc5\x49\xe9\x81\xde" + "\xf2\xc2\xe5\xa5\x6b\x06\xea\xda" + "\xb3\xc7\xc8\x08\x14\xa6\xc8\x3f" + "\x9f\xde\xd0\x06\x8f\xf8\xdf\x7a" + "\x0a\xce\x75\x3b\xf5\x1c\xc1\xbb" + "\xd5\x87\xbc\xfb\xcc\x7a\xbb\x9f" + "\xe2\xfd\xad\x7b\x26\x8e\x45\xa1" + + "\x56\xc2\x39\xe0\x68\x36\xb4\x1c" + "\x5d\xfd\x17\x7c\x8b\xfb\x26\x5f" + "\x2b\x06\xaa\x79\xaf\x26\xe4\xee" + "\x04\xbf\x8f\xd7\xd0\x02\x20\x07" + "\xe3\xb7\x4f\xe8\x37\xa2\x9c\x4c" + "\x3d\x13\x82\x0c\xa1\xd8\x01\xb4" + "\x81\x41\x7e\x6d\x92\x25\xa5\xaa" + "\x52\xb1\xdb\x73\x33\x08\x43\xe9" + + "\x83\xc9\xe7\x6e\x1e\xad\x5f\x2f" + "\xf5\x28\x13\xb4\x7c\x9d\x0f\xeb" + "\xf7\xd5\x78\x1d\x44\x8b\xa6\x9b" + "\x6f\x72\xbc\x35\x9e\x3b\x6b\xa0" + "\xf1\x1f\x3e\x59\x55\x02\x55\xa2" + "\x15\xc1\xbe\xdf\x3d\xd4\x2d\x55" + "\x46\xf0\xa8\xbb\xab\xa7\x48\x2c" + "\x33\xf1\x0b\xad\xa3\x56\xfc\xd4" + + "\x9a\x31\x24\xbe\x31\xda\x2d\xf9" + "\xe7\xa8\x95\xe0\x8b\xd2\xf7\x03" + "\x85\x21\x78\x98\x40\xe8\x2f\xa5" + "\xbc\x4d\xc2\x29\xfe\xda\x6d\x27" + "\xeb\x64\x7a\x1d\x96\x54\xcd\x80" + "\x42\xbe\x1d\x7f\x89\x08\x36\xe4" + "\xd5\xd2\x38\x84\x77\xa8\x81\x2f" + "\x36\x90\x16\x85\xa8\x52\x4d\x7e" + + "\xd1\xb5\x04\xba\xef\x1c\xf2\x62" + "\x52\x73\x4c\x22\x07\x27\x44\x9a" + "\x1f\x17\xc6\x33\x6c\x96\x07\xbf" + "\xb0\x16\x08\x1e\x91\xa8\x7b\xdb" + "\xa9\x45\x37\x03\x59\xea\x6f\x30" + "\x67\x8f\xa7\xc0\xe0\xf7\xac\x2a" + "\xf9\x1b\x25\xad\x83\x38\xaa\xb5" + "\x86\x70\xbd\x26\xe9\xed\x5a\x34" + + "\x5d\x71\x59\x1d\xb1\xd5\xe3\x19" + "\x3e\x98\x88\xd7\x62\xa7\xea\xc7" + "\x48\xf2\xf1\xab\xb0\x30\xa7\xe5" + "\x83\xfd\xe3\xfa\x84\x80\xab\xfb" + "\x2f\x5b\x76\x53\x21\x0d\xe5\x65" + "\x3d\x7f\x12\xfa\x83\xe0\xd4\xbd" + "\x10\x1b\x7b\x39\x74\xc0\xf3\x9c" + "\xd3\x9f\xb5\xb1\x0c\x09\xf8\x59" + + "\x10\x9f\x11\x98\x7d\xe1\x1d\xdc" + "\xa6\x36\x8c\x48\x5d\x3c\x35\x74" + "\xdf\x23\x8e\x3d\x3a\xf3\xaa\x14" + "\x93\xf5\xba\x78\xc0\x75\xe0\x31" + "\x3c\xca\xd1\x46\x3a\xa0\x7c\x0f" + "\xc7\x60\xb6\x47\xac\xe3\xc5\x99" + "\x59\x2e\xfe\x88\x13\x24\xd0\x70" + "\x05\xc0\x7e\x2a\xe1\x6b\x9a\x2e" + + "\x8f\xaa\x5f\x61\x9d\xfd\x15\x7b" + "\xed\x54\x85\x96\x40\xeb\xa1\x8f" + "\x82\x48\xa4\x7a\x7e\x44\xb4\x7b" + "\x32\xff\x9f\x02\xd1\xd0\xb2\x2b" + "\x2f\x6d\xaa\x6c\x64\x2a\x5e\x07" + "\x1b\x35\xe7\x22\xde\x79\xb8\x8e" + "\x62\x6c\x50\x9a\x4e\x62\xd5\xbc" + "\xdc\x24\x7e\xa8\xf0\xae\x8e\x21" + + "\x6f\xbd\x1f\x24\x95\x96\x44\xac" + "\x23\x12\x1c\x08\x70\xb1\xc9\x67" + "\x6f\xac\x6a\xb5\x21\x8f\x86\x16" + "\x21\xb7\xbc\xf8\xa3\x8f\xbd\x34" + "\x76\x1c\x69\xb6\x33\xbd\xb6\x06" + "\x73\x79\x1a\x38\x66\x47\x92\x6c" + "\xdb\x78\x40\xa5\x4c\x44\x12\x6a" + "\xcc\x51\x10\x6d\xa9\x91\x2e\xd0" + + "\x35\xfa\xdd\x44\x47\x68\xe5\x37" + "\x47\xf7\xb3\xda\xc5\xc5\xcf\x9c" + "\xf4\x6c\xe9\x1e\x3f\xdf\xc1\x9a" + "\x8f\x0b\x48\x3b\xa1\x71\x05\x0c" + "\x3c\x7b\x3a\x4b\xd5\xb3\xbe\x2f" + "\x99\xbb\xcd\x5d\x69\x36\xc0\x35" + "\x3a\x5b\x41\xb2\xdc\xf5\xa0\x52" + "\x9a\xed\x13\x44\xb4\x59\x77\xd5" + + "\xf8\xd3\x33\x0b\xc0\x79\x73\x07" + "\x09\xe4\x64\x70\xc6\x83\x18\x42" + "\xf6\xc8\x29\x6c\xd7\x73\x08\x2d" + "\xc8\xc0\x74\xd2\xa3\x33\xa4\xbf" + "\x1e\x89\xa5\x23\x8f\x77\xdc\x56" + "\x04\xde\xe2\x35\x65\xbf\x63\xd6" + "\xce\x17\xb5\x5d\x48\xdb\x8f\x48" + "\xc2\x26\xb2\x19\x5e\xa5\xbb\x00" + + "\xc5\xa2\x30\x3d\xd8\x47\xe6\x1f" + "\xdc\x81\x8a\xf7\x7e\xf7\x57\x08" + "\x9b\x4a\x1a\x13\x34\xa3\xd5\x11" + "\xf5\x93\xd3\x29\xf9\x4a\xa9\xc0" + "\x1a\xec\xa6\xda\x0b\x5c\x3a\xbc" + "\xed\xd7\xd2\x88\x93\xe4\x9f\xba" + "\x97\x47\x61\xbb\xb4\x35\x43\xbb" + "\x33\x35\xf8\x72\x68\x4d\x1c\x99" + + "\xb6\x8f\x05\x8a\xe7\xee\xbb\xed" + "\x1a\x12\x09\xfb\xdc\x9d\xd1\xb9" + "\xce\xdd\x4d\xd3\x5b\xb4\x1b\xa4" + "\xc4\x4b\x96\x00\xb9\x80\xbc\x2d" + "\x54\xb6\x6c\x1d\x7d\x13\xd9\x4e" + "\xc5\x01\x3d\x48\xdb\x16\x90\x1b" + "\x2e\xe2\x28\x65\xbc\x01\xc5\x5f" + "\x6b\x64\xad\x6c\x81\xf8\xd2\xb2" + + "\xb3\x1c\xf0\xd2\x28\x8c\x25\x53" + "\xb1\xb0\x5d\xd7\xa3\xea\xd6\x93" + "\xb4\x0d\x7d\xe8\x0d\x2b\x9a\x41" + "\x93\x84\xfe\xd8\x03\x8f\xe4\xa1" + "\x3a\xb2\x08\xc5\xf6\xfa\x47\xf7" + "\x49\x35\xd5\x35\x1a\x57\x37\xf1" + "\x38\xb8\xf9\xfc\xe2\x58\x5e\x9f" + "\xf5\x3c\xfd\xa7\xee\x6c\x18\xc7" + + "\x39\xad\x6b\x28\x2f\xfb\x76\x5e" + "\xe2\xd1\xca\x9d\xe3\xef\xd9\xba" + "\x04\xe9\xc7\xed\x90\x51\xe7\x60" + "\xa5\xb5\xec\x0f\x3e\x06\x6f\x6a" + "\xc3\xac\xd8\xae\x85\xed\x50\x51" + "\x6c\xaf\x20\x6d\xbc\xcf\x6c\xb5" + "\xfa\xdb\x69\x2c\x98\x1e\x0d\x7e" + "\xa9\x10\x7e\x7c\x8a\x62\xf5\xab" + + "\xd3\xa1\x78\xe9\xce\x68\xb8\x77" + "\x04\x2d\xb9\x7a\x33\x8b\xa6\xe3" + "\x62\xb8\xa5\x87\x94\x97\x02\x51" + "\x1d\xd4\x61\x3a\xc3\x06\x06\x5f" + "\xf1\x26\x93\x6f\x27\xbe\x14\x28" + "\x2e\x3c\xfe\xc6\x14\x1c\x52\x2f" + "\x51\x73\xdf\xac\x7d\x4d\x46\x17" + "\x44\x7e\x7f\x77\xd3\xf9\xf5\x10" + + "\xab\xa2\x08\x74\x19\x64\x21\x1d" + "\x6a\x91\x28\x59\x18\xd5\x55\xae" + "\xea\x5e\x16\xf3\x4a\x68\x75\xdf" + "\x59\xef\x4e\xd8\xd5\x64\x83\x53" + "\x1a\x3b\x56\x70\x15\x20\x4e\xb5" + "\xff\xef\x4c\x6b\xa7\xbb\xd9\x74" + "\xdc\x82\x06\x7a\xd8\xcb\xbe\xfc" + "\x6c\x11\x93\xf1\x02\xa4\x00\x0e" + + "\x7d\xb3\x9f\x26\x6b\x61\x8e\xce" + "\xe5\x2d\xe6\x7d\x04\x38\xf7\xaa" + "\x53\x41\xdd\x4f\x75\x11\xa1\xab" + "\x9b\xb4\x70\x37\xba\x59\x57\x51" + "\x61\x3a\x42\xaa\xf8\xeb\x09\x8b" + "\x92\xfb\x41\xcd\xa1\x45\x22\x59" + "\x36\x89\x4c\x9b\xc1\x8e\xba\x1c" + "\x0e\x71\x36\xaf\xe3\x91\x7e\xa8" + + "\x16\xc4\x9f\x84\x85\x89\xf6\x65" + "\x3c\xa7\xba\xcd\x34\xa9\x03\x3c" + "\x47\x66\xcb\xbf\x1b\x31\x2f\x11" + "\xcd\x93\x4e\xde\x40\x13\xc1\x69" + "\x7b\x53\xdb\x66\xb9\x58\x24\xbd" + "\xe7\x07\x5b\x88\x18\xb0\x74\xf9" + "\x32\xd3\xc8\x70\xa5\x45\xb1\x5d" + "\x7b\x83\x9b\x54\xd1\xd0\xfd\x30" + + "\xe3\xa2\x34\x3d\xe4\x4c\xd8\x1f" + "\x61\x5d\x3b\xb4\xce\x59\x37\xee" + "\xc7\x86\x91\x61\x8c\xc7\x5b\x89" + "\x5a\x72\xb9\xcb\x09\x38\x9c\xf1" + "\x1f\x4b\x74\xde\xaa\x21\xbe\xc0" + "\x6b\x05\xf8\x60\xb0\x22\xd2\xa7" + "\x11\xfe\x3e\xb2\x57\x61\xbe\x74" + "\x53\x82\xd6\x0c\x4f\x2b\xab\x6f" + + "\xb4\x58\x23\x51\x73\x1d\x5c\x3e" + "\xc9\x99\xbb\x30\xb2\x42\x57\xcb" + "\x1a\x03\x2d\x3c\xa8\x2f\x2e\x4a" + "\xb8\x78\x98\xfb\x2b\xc9\x1b\x37" + "\x6c\x65\x75\x82\x9c\x1f\xa7\x1e" + "\xa1\x00\x03\x1c\xa2\x94\xf7\x14" + "\xe5\x54\xea\x26\x98\xe7\xea\x08" + "\xc6\x54\x1a\x17\xe5\x54\x58\xcf" + + "\x25\xd7\xf1\x4b\x5f\xea\x33\xad" + "\x0f\x95\x6c\x4f\xe2\x8e\x1d\x9c" + "\x06\xaf\x77\xa3\x8a\xe7\x4e\x54" + "\xe1\x13\xa1\x94\xbb\x89\xf4\x54" + "\xe8\xb7\x2f\x99\x34\xd6\x11\x8f" + "\x47\x43\xa4\xa2\xaa\xa7\x69\x01" + "\x00\x0e\x02\x95\xaf\xd4\x49\x1d" + "\x0b\x12\x8e\xe0\x22\x57\x94\x95" + + "\x86\x38\xba\xb7\xb3\xfb\x0a\x28" + "\xa8\x34\x89\x36\x3e\x3a\x80\x08" + "\xab\x71\xf6\x31\x65\xdf\x80\xf9" + "\x91\x47\x72\x1a\xea\x4a\x89\x90" + "\x50\xa3\x1d\x8d\xa9\x66\x5b\x54" + "\xa5\x53\x13\x41\xbf\xfb\xf4\x9d" + "\x8a\x08\x98\xa3\x3c\x74\x52\x15" + "\x17\x57\x2d\xb8\xde\x4c\xc1\xd1" + + "\x82\x22\xd3\xa4\x78\x38\xe3\xb6" + "\xe7\x0a\x02\x48\x9d\x02\x6e\xe3" + "\x50\xb7\xa9\x37\xfb\x47\x58\xe0" + "\x19\x38\x9e\xb2\x2c\x81\x76\xf8" + "\xf0\x17\x3a\xd2\x8e\x13\xad\x84" + "\x0e\x95\xb3\xf0\x80\x44\x7b\x6d" + "\xe0\x7a\xd6\x2f\xf4\xae\xa8\xdf" + "\xf6\x3a\x33\x52\x24\xea\x3e\x8d" + + "\x83\xec\xc5\xf5\xfd\x3a\x8d\xb2" + "\xad\x9f\x04\x91\xc1\xf6\x6a\x8d" + "\x1a\x1e\xbe\xff\xff\x64\x79\x41" + "\x0a\x79\x1c\xf5\xea\x9e\xce\xba" + "\x79\x29\x0f\xb2\x36\x22\x02\x42" + "\x01\x38\x5d\x76\x29\xb7\x05\x6b" + "\xe7\xe3\x6d\x6d\x00\xe2\x0e\xbe" + "\x3a\xaf\x01\x1e\x01\xd5\x6e\xb9" + + "\xcc\x5a\x5d\xb1\x75\x20\x05\x0d" + "\xc4\x5b\x81\xbd\x9f\xc7\xd9\xc6" + "\xf2\x6c\xa3\xdf\x88\xfd\xca\x8d" + "\x70\x90\xaa\x38\xe2\xcb\x8c\x90" + "\xce\xaf\x35\xba\xc4\x22\x87\x63" + "\x0b\xbf\x6a\xfd\xb0\xa8\x3d\x5a" + "\xc1\x35\xc3\xc9\x2c\x25\xce\x2d" + "\x9b\x79\xaa\x65\xde\xf0\xe7\x84" + + "\x62\xbc\xed\xe0\xec\x62\x87\xef" + "\xfb\x73\x27\x85\x28\x98\x44\x33" + "\x85\x38\xae\xc3\xf3\x90\x9b\x2c" + "\xb2\x56\x1e\x73\x12\x18\x19\xd8" + "\xf0\x31\x68\x73\x95\x7e\x5d\x20" + "\x5d\xc1\x41\xd6\x48\x8d\x81\xc3" + "\x7c\x15\x3e\xf4\x39\x38\xb6\xc6" + "\xf0\x51\xad\x36\x47\x04\x16\x55" + + "\xcb\x72\x9a\xb9\x22\xa5\x01\x21" + "\x16\x80\x61\x87\x67\x6e\xde\x06" + "\x3e\x65\xf3\xe6\xcd\xc7\xf8\x5f" + "\x4a\x75\xa6\xc7\xb5\x1a\x82\x0a" + "\xa2\xb5\xb0\x7c\x2b\xa5\x3f\x7e" + "\x90\x87\x04\xc9\x1c\x12\xfb\xa7" + "\x3a\x05\xce\x06\x20\x50\x72\x1a" + "\xb0\x29\xe9\x04\x1f\xa3\x90\xb4" + + "\x6e\x7e\x40\xbc\x19\x77\xbb\x70" + "\x41\xeb\x4c\xd8\xef\x28\x13\x23" + "\x20\xbb\x04\xc1\x1f\x6a\xca\x8b" + "\x71\x90\x0b\x28\x25\xe4\xf4\xd6" + "\x82\x6a\x89\x92\xa2\x95\x1b\xb4" + "\x67\xdf\x34\xfa\x35\xf4\x5c\x73" + "\x69\xd7\xd6\xd9\x08\x1a\x33\xbc" + "\x7e\x74\x82\x26\x05\x86\x97\x57" + + "\xad\x61\xdd\x62\x7d\xe4\x7b\xe1" + "\x71\x13\xe0\x6b\x1c\x96\x1a\x78" + "\xba\xcb\xe3\xda\xd3\xbf\x63\x10" + "\xba\xc9\x73\x7f\x06\x74\x64\x35" + "\x29\xa1\x36\x27\x7b\x95\x0e\xf5" + "\x56\xf2\x13\xed\x02\x37\x31\xa6" + "\xc5\xfc\x19\x3a\x65\xee\x36\x94" + "\xb6\xc8\xa4\xe7\x29\xdb\x2b\xcf" + + "\xbe\xb8\xf3\x87\x42\xf7\x8a\x69" + "\x1d\x59\xa1\xd1\x1a\x9d\x5d\x4f" + "\xe1\xac\xe4\x0f\x3c\xac\x0f\x54" + "\x7d\x4a\x89\xc6\x24\x9b\xa6\x83" + "\x46\xeb\x6f\xad\xee\x07\x5c\x93" + "\xfa\x25\xf3\x7f\x88\xbd\x2c\xe0" + "\x0b\x38\xc6\xbc\x9d\x8c\xf0\xe8" + "\xce\x45\xe0\xa6\x0f\xf4\x7f\x9c" + + "\xd8\x5c\xf9\xc5\x44\x12\x6b\xb0" + "\xf4\x95\xab\xf4\xf0\x8a\x8c\xda" + "\x6d\x83\xe5\xb9\xc2\x59\xae\x1b" + "\xfc\xff\xcf\x3a\x7e\x1e\xd5\x07" + "\xda\xbc\xcc\xc2\x6a\x5e\xe1\x01" + "\xe0\xc3\x28\x85\x3f\x92\xc1\x3b" + "\xd4\xea\x9f\xa4\x77\x45\x32\x43" + "\x11\xa7\xa7\x2a\x84\xb8\xa1\x61" + + + "\x34\x3d\xe6\xb0\x31\xee\xe7\x4f" + "\xab\x4f\xe5\xa9\x72\x05\x60\xf4" + "\xa4\xb5\xe7\xd5\x34\x33\x49\xc0" + "\x31\x48\xd5\x06\x92\xfb\x89\x85" + "\x3a\x55\x83\x65\xcc\xf5\x70\xaa" + "\xe5\x49\x56\xe2\x4a\x09\x79\x08" + "\x52\x46\x04\x10\x07\x45\x90\xcc" + "\x4f\x1c\x54\x02\x6d\x69\xb0\xeb" + + "\xa6\xe7\xde\xa2\x3e\x1a\x8c\x75" + "\x84\x22\x4b\x73\x3c\x2f\xde\xdc" + "\xad\xa6\xab\x4e\xd2\x45\xa4\xab" + "\xa7\xe0\xce\x76\x68\xf6\xaa\x35" + "\x9a\x04\xaa\xe5\xa9\x04\x0b\x7e" + "\x84\x3e\x10\x91\xad\x83\x40\xe7" + "\xc3\xec\xaf\x40\xce\x83\xb1\xbe" + "\x7a\x3f\x04\xea\x9f\xde\x89\x6b" + + "\x35\x52\x37\x99\x03\x0e\x9f\xb9" + "\x70\x79\x91\xb9\x47\xc8\x14\x76" + "\x67\xc0\x4e\x52\xe9\x3c\xc9\xfe" + "\x20\x25\x12\x9b\xf8\x7b\x0e\xe4" + "\x74\x47\x4c\xee\x31\x06\x67\xb5" + "\x4c\x91\x04\x3b\x7a\x84\x03\x6f" + "\x26\xd2\x9d\xdc\x29\x94\x6e\xc9" + "\xf8\xc1\x57\x8c\x6c\x9b\x48\x43" + + "\x66\xba\x67\xfe\x23\x9d\x29\x0e" + "\x34\x2f\xcf\x93\x60\x07\x45\x91" + "\x13\xf9\xfc\x97\xa9\x5e\x5b\xf4" + "\xda\xdd\xd7\x8b\x43\x08\xe0\x5b" + "\x4d\xf0\x3f\xd5\x05\x3e\x8c\x35" + "\xf7\x1e\xe9\x5d\xc3\xcd\x7c\xbf" + "\xa0\xc1\x9e\xb6\xbf\x4d\x68\xad" + "\x97\xd9\x1f\x80\xf2\x7c\x7e\x36" + + "\xfb\x38\x23\xcc\x27\xd2\xff\x46" + "\x53\x61\xe2\x90\xa9\x6f\xff\x89" + "\x76\x00\x1a\x33\x79\x07\x57\xbe" + "\xaf\xf3\xe1\x06\xc5\x41\xd2\x43" + "\xa3\x62\x9b\xde\x7d\xb9\xcd\xfd" + "\xea\x30\xae\xa0\x84\xe9\x06\x6a" + "\x7d\xdf\xbd\x4f\x80\x16\xbf\xc9" + "\xc4\x63\x61\xd3\xa2\x71\x04\x17" + + "\x5e\x65\x13\x31\xae\xa8\x5b\xff" + "\x80\x31\xb8\x57\x2b\x6e\x2c\xfa" + "\xbe\xea\xe0\x77\x19\x27\x48\x1c" + "\x97\xea\x7f\x33\x55\xc5\xf3\xf9" + "\xcb\x81\x25\xa4\x22\x70\x0f\x34" + "\xe3\x10\xf7\x18\xc2\x0b\xde\xe1" + "\xa8\x5a\x2e\xf6\xde\x0a\x64\xee" + "\x40\x89\x42\x49\x91\x38\xb2\x16" + + "\xc3\x0c\x95\x55\xe4\x19\x16\x36" + "\xb8\x6b\xb6\x56\x5c\x66\x1d\xc7" + "\x84\x6d\xac\xaf\x34\x4b\x03\xea" + "\xe3\xc7\xe4\xe5\x32\xf8\x87\xa9" + "\xa7\xa6\x79\x7a\x72\x27\x74\xa0" + "\x23\x6c\x6d\xe2\x17\xd0\xe5\x56" + "\x10\x7e\x16\x38\x76\xb9\x50\x7e" + "\x4e\xa8\x8a\xe8\xef\x81\x6c\xaa" + + "\x95\x85\xdc\xb0\xb7\xf3\xa1\x0c" + "\x2e\x9f\x1d\x9f\x08\x46\xde\x27" + "\xa7\x82\xdd\xba\x39\xbf\xf3\x1a" + "\x48\x24\x86\x65\x79\x6a\x35\x79" + "\x52\xa0\xf9\xf5\x45\x23\x60\xc0" + "\xf9\x42\x9a\x13\x89\x0f\x8b\x1a" + "\xfc\x40\x4d\x84\x42\xee\x3e\xb5" + "\x68\x63\x5b\x4e\xe5\xbf\xb0\x93" + + "\xbf\x5b\x32\x4d\xd7\x59\x39\x47" + "\xb9\x14\x61\x8d\xec\xbe\x61\x2a" + "\xee\xe2\x4b\x92\x94\x2a\x67\x25" + "\x0c\x3d\xc2\xf2\xdb\x95\x85\xa4" + "\x38\x18\x22\x6a\x8b\x84\x76\xe4" + "\x73\xb6\xc1\x35\x9a\xe6\x43\xe7" + "\x03\x85\x46\xd8\x99\x24\xb4\x2a" + "\xa7\x0b\xe9\xe9\x54\x00\xaa\x62" + + "\x11\x29\x48\xbc\xf1\x13\x8d\x35" + "\x26\x7f\xfa\xb7\x71\x19\x5d\x68" + "\xe4\xae\xe1\x2b\x1d\xa5\x67\x3e" + "\xa9\x14\xd1\x98\x09\x85\x41\xe0" + "\x61\x25\x05\x4e\x60\x9f\x63\x59" + "\x18\x08\x5d\x15\x49\x5c\x07\x32" + "\x1c\x4b\xb6\x67\x3b\x34\xa2\x2a" + "\x6a\x3e\xf5\x67\x29\x5e\x44\x1b" + + "\xe0\x04\xa9\x73\x17\x27\xfb\xbd" + "\x73\x8d\x88\x28\x0b\xe4\xe1\x7c" + "\x1b\x7d\xa9\xea\xf6\x35\x7e\x2e" + "\x97\xa0\xaf\xa9\x2a\x77\x61\xd0" + "\x59\x7c\x1f\x7a\xc4\xc7\x4a\x43" + "\x9a\x7b\x9b\xe7\x4a\x12\x21\x6e" + "\xc7\xec\x22\xbb\xf3\xcf\x5a\x05" + "\xd3\x58\xc8\x84\xc9\x7a\xfd\x8b" + + "\x9c\x78\x24\xc0\x02\xdd\x34\x54" + "\xfc\x7b\xb5\x41\xea\xa9\xdc\x90" + "\xdf\x98\x33\x24\xe2\x98\xa8\x8a" + "\xbb\x94\x4a\x89\x34\xc8\x07\xf6" + "\x76\x9b\xc9\xc2\x97\xbe\x07\xbb" + "\x02\x93\xc2\x18\x67\xba\x76\x65" + "\x8c\xa8\x03\xe7\xcc\xef\x79\x3d" + "\x06\xd1\xa0\xb6\xd7\xce\x59\xf2" + + "\xad\x68\x1f\x9f\xf5\x7d\xd5\x2f" + "\xc8\x70\x64\xb0\xdb\xc6\xdc\x5d" + "\x07\x73\xb4\xa9\x51\x64\x1b\x80" + "\xf4\x1b\x55\x76\xe3\xc8\x51\x6b" + "\xa9\x1d\x4e\xd4\xf7\xd1\x0b\xef" + "\x0c\x60\x4e\x4d\x1d\xcb\x4b\x71" + "\xc7\x40\x65\x0c\xe4\xb9\x7b\xc5" + "\x44\xc6\x7c\x32\xc2\x1e\xbd\x71" + + "\x0a\x4f\xd8\xcf\xb5\x33\xcd\x00" + "\xdd\x0d\x6b\x4e\xf7\x68\xa5\xcf" + "\xf4\x48\x0f\x2d\xdb\x4e\x69\x1c" + "\xd8\x7d\xff\xfe\xcc\xc7\x47\x27" + "\xb2\x24\x8c\xac\xad\xec\xda\xce" + "\xe5\xa5\x42\x07\x3f\xde\x29\xdb" + "\x6d\x29\x90\x30\xbb\x8f\x5d\xe3" + "\x4a\xb5\x1f\xb1\xf7\xab\x8c\x78" + + "\x1f\xd8\x4d\x7f\x7e\xcf\x52\x9a" + "\x5e\xc0\x69\x5e\xe1\x2b\x13\xa0" + "\x72\x4d\x0f\x2a\x47\xb7\xda\x90" + "\x06\x67\x2d\x31\x11\xf9\x42\xc1" + "\x8b\x99\x61\x82\x1f\x63\xd3\xe8" + "\x94\x1c\x5c\x61\xae\x2f\xf4\xf0" + "\x5d\xfa\xc3\xae\x8c\x94\x4e\x2f" + "\x1e\x10\x74\xa3\xa8\xe7\x2a\x24" + + "\x0b\x61\xde\xc8\x5d\x3a\x89\x0f" + "\xce\x23\xe2\x67\xfb\x15\xc5\xe8" + "\xc5\x6d\xad\x4e\xa6\xbf\x74\x77" + "\x8f\x72\x5c\x92\x95\x0f\xd2\x89" + "\xce\x83\x85\x09\x66\x09\x1e\x7a" + "\xd7\xa7\xf2\x93\x94\xdb\xee\xa2" + "\x4a\x4d\x30\x4c\x97\x20\x28\x1b" + "\x2d\x28\x77\xc0\xda\xe3\x42\x08" + + "\x52\xbe\x88\xd0\xca\x78\xa8\x1f" + "\x56\xe6\xe1\xa9\x07\xcb\xc2\x89" + "\xdb\x62\x9d\x21\xc3\xc5\x5b\x38" + "\x52\x27\xda\x5f\x6b\x67\x2b\xd8" + "\xfc\xea\x04\xe3\x9e\xdc\x49\x24" + "\xa2\x4e\x2f\x63\x91\x79\x9e\x1e" + "\xb9\xe0\xd5\xcd\x61\xe0\x36\x30" + "\xbc\x25\x08\x83\xff\xf6\xa6\x75" + + "\x9b\x5e\xf6\x81\x04\x26\x5b\x2e" + "\x37\xf8\x01\x49\xc0\x56\x01\x48" + "\x33\xb7\x57\xb8\xab\x86\x7f\x55" + "\x11\x44\x5b\x73\x0e\xed\xe3\x88" + "\x2e\x73\x33\x2a\x0d\x68\x37\xc3" + "\x1f\xc1\xc9\x31\xcb\xbf\x99\xa5" + "\xc4\x01\x52\xa9\x51\xf8\x82\xb2" + "\x95\xdf\x4d\x85\x8a\xda\x42\xd3" + + "\xb4\xed\x9d\x44\xdc\xcd\x0f\xb1" + "\xcf\x4a\x24\xd1\x42\x00\x89\x2c" + "\x17\x70\xfc\xc7\xca\x72\x30\x9b" + "\x3f\x06\xe8\x9c\x85\xa6\xcd\x1a" + "\xf5\xe2\x51\x7f\x3c\x31\x43\xd2" + "\x78\x95\x3d\xd7\xa4\xf1\xa3\x52" + "\x6e\xce\xf0\x64\x7a\x5b\x78\xda" + "\x2d\x4c\x2a\x44\x15\x63\x76\x2e" + + "\x7b\x2d\x9e\x3b\xa3\x72\xd9\xe4" + "\xff\x18\x82\xc4\x27\x0b\xc6\x7c" + "\x91\x9d\x14\x84\x38\x08\xc7\x8f" + "\xcc\x1e\x46\x2f\x6f\x34\x04\x5c" + "\xa9\x50\x46\x61\xf2\xfd\xe9\xeb" + "\xac\x66\xf6\xc1\x37\xb5\x35\x5e" + "\x83\xbc\xba\x88\xd1\x13\x56\x64" + "\x3e\xc9\xe1\xc5\x3a\xce\xca\x88" + + "\x1a\x11\x1f\x15\x04\xb0\xf9\x94" + "\xfa\xc5\xdb\x07\x5b\x03\xa5\xc7" + "\xd7\x49\x9e\x60\xa7\x8e\x95\x53" + "\xc0\xf4\x13\x90\xd7\xb4\x26\x05" + "\xbd\x2f\x3e\x59\xbb\x5e\xde\x66" + "\x37\x0c\x2e\x4c\xb4\xf8\x7c\x6e" + "\x78\x3e\x98\x8c\x8b\xfc\x72\x6f" + "\xd7\xf9\x48\x23\x63\x9b\xab\x6f" + + "\x59\xac\x70\xeb\x81\x2e\xd0\x58" + "\xf7\xd8\x17\x44\x9b\x76\x22\xf5" + "\xff\x74\x72\x07\xd5\x63\x30\x9f" + "\xac\xe8\x0f\x34\x4f\x6f\xac\xf5" + "\xba\x14\x09\xb5\xd1\xd9\x72\xce" + "\x5c\x25\xbc\xb7\x84\x59\x83\xb3" + "\x8f\x03\xa5\x7c\xa7\x3f\x5d\x14" + "\x13\xab\x8f\xad\xc6\xa3\xcd\x7a" + + "\x68\x84\x3d\x6a\x52\xa3\x48\xc7" + "\x32\x80\xe3\x27\x99\x47\xab\x3f" + "\xe7\x0c\x43\xfa\x29\x36\xad\x91" + "\x44\x4c\x61\x71\x2c\x0b\xaf\xc5" + "\x11\x16\x21\x0c\xa5\x3f\xde\xce" + "\x83\x80\x33\x02\xba\x89\x68\x6e" + "\x32\xfe\xf0\x77\x59\x19\x0a\xee" + "\x5a\xbc\x4b\x0f\x5d\x90\xea\x01" + + "\x23\x2e\xe9\x3d\x75\xa3\x9c\x20" + "\xe3\xb6\xbb\x5f\xc8\x3c\xb0\xcc" + "\x7e\x48\xb1\xd7\x03\x0f\xb9\xcc" + "\x1f\x94\x10\xc7\x38\x2a\x9c\xfa" + "\xed\xce\x24\x67\x23\x38\x6c\x75" + "\x23\x03\x2d\x19\x58\x22\x90\x3a" + "\x8e\x03\x5e\xea\x19\xe5\x50\xb1" + "\x91\x75\x42\xc7\x65\x28\xba\xdc" + + "\x48\xdb\x93\x81\x5e\xb2\xcf\x12" + "\x8c\x70\xea\x3b\x63\xae\xb4\xdd" + "\x21\xf8\x81\xf1\x2e\x10\xae\xda" + "\xd9\x89\xa0\x24\x30\x92\x9d\x9d" + "\xea\x6a\x87\xa0\x2d\x12\xc4\x71" + "\x09\x9c\xe1\xbb\x3b\xea\x63\x1a" + "\x0c\x8d\x6f\x01\x76\x80\x89\x3b" + "\x13\xb7\xa6\xae\x5d\xcc\xcc\xa5" + + "\x7d\xe9\xf6\x06\xe3\x8e\x0e\x51" + "\x8c\xaa\x0e\xb0\xc5\x8f\x4a\x68" + "\x33\xbf\x3f\xb9\x79\x35\x31\x15" + "\x23\x17\x6b\xf6\xa6\x5f\x7f\xe6" + "\x8c\x74\x86\xce\xf6\x81\x58\x81" + "\x10\x8b\xd5\xea\x18\xd3\xce\xc1" + "\x93\x33\xf3\xf2\x5b\x77\x62\x86" + "\xf2\x6f\x83\x7d\x04\xc9\xc0\x7a" + + "\x61\x2f\x8e\x4a\xaf\x2b\xf2\xc3" + "\xa6\xa6\x6d\x17\xde\x9e\xd2\x77" + "\x63\xda\x07\x16\x21\x5f\xa5\x40" + "\x91\xe3\x52\x14\x56\x38\x8b\x85" + "\x56\x3c\x1b\xfe\x67\xc2\xd3\x0d" + "\x7a\x22\x55\x7d\xdd\x4b\xc0\x66" + "\x09\x4e\x40\xe6\x55\xfe\xd2\xfb" + "\xbc\xfc\x9c\xea\x49\xcf\x81\x59" + + "\x32\x07\x89\x78\x7f\x23\x49\xe5" + "\xd9\xb4\xfc\x53\xf9\xbe\x43\xc4" + "\xd6\x80\x34\xeb\xa6\xd8\x84\x98" + "\x86\xb1\x48\x30\xa1\xb6\x35\x8a" + "\x0a\xa9\xe9\x65\x16\x47\xe4\xb4" + "\xc0\x06\x30\x65\x0d\x38\xbf\x45" + "\x3b\xae\xe9\x4f\x0d\x82\x3f\x8f" + "\x71\x3b\x9a\x97\xa0\x35\x4a\x24" + + "\xaf\x70\xa8\xae\x02\xa9\x46\xae" + "\x99\xdc\xbe\x7c\xf5\xfc\xb9\xa9" + "\x93\xe7\xb7\x79\x3f\xca\xf2\x74" + "\x28\xeb\xbe\x1d\x23\xf2\xb8\xad" + "\x85\xdf\x64\x67\x0e\x06\x02\x63" + "\x54\xd5\xeb\x57\xd2\x20\x33\x36" + "\xe1\x22\x8d\x79\x3e\x57\xfd\xd9" + "\xed\x7d\xb6\xeb\xf5\x85\x5f\x28" + + "\xc9\x55\xeb\x8a\x13\xd6\xac\x0a" + "\xf0\x85\x68\xd8\xa4\x1d\x79\x79" + "\x23\x5f\xb0\x44\x67\x82\x5e\x16" + "\xed\x48\x45\x28\xe8\xf5\xe5\x9e" + "\xb8\x61\xb6\x85\xcc\x48\xd5\x9f" + "\x89\x86\xc5\x89\xc0\x37\x70\x25" + "\xb2\x0c\x29\xf9\x6f\x30\x47\x9b" + "\xf4\xec\x77\x06\xeb\x2e\xba\x56" + + "\xb5\xa2\xca\x11\x92\x32\x6b\xd8" + "\xd1\x7b\x33\x39\x8e\x25\x26\x2a" + "\x91\xc2\xc8\x79\xb5\xa9\xc5\x4d" + "\xe6\x42\x19\x74\x87\x3d\x44\x16" + "\x0c\x40\x11\xf8\xf8\xa2\xc9\x6b" + "\x0e\x4e\xeb\x9e\x35\x69\x9c\x81" + "\x4b\x21\x0c\xce\x73\x72\xbe\xe1" + "\x81\x15\xb6\x84\x81\xfb\x9a\x42" + + "\xff\x06\xcd\x74\x9d\x0e\x01\xa1" + "\xac\xee\xa3\xac\xdf\xc7\x17\x9c" + "\x2b\xaa\x63\x80\xd3\x6c\xc8\x74" + "\xff\x14\x46\x73\xb3\xc4\x95\x85" + "\xcc\x62\x0f\x99\xca\x00\xde\xa3" + "\xe5\x3b\x0c\xca\x13\xd2\xbe\xd9" + "\xf5\xe9\x8c\xdf\x8a\x07\x86\x78" + "\x44\x44\xd4\x5c\xe3\x7c\xb2\xdd" + + + "\x82\x83\xee\x26\x1d\x58\x7c\x9c" + "\x8e\x63\x9d\x35\xc5\xdc\x17\xcf" + "\x3d\xae\x28\xb7\xab\x73\x82\xee" + "\x47\xf0\x21\xf8\x26\x29\x11\x1d" + "\x74\x1a\x49\x50\x77\x84\x49\x11" + "\xb9\xdf\xe0\xfd\x61\xa7\x7f\x68" + "\xab\x35\xa4\x7e\x22\x80\x25\x2c" + "\x3f\x7e\xce\x91\x94\xdb\x8b\x6b" + + "\x56\x2b\xfb\x53\xa5\x03\x3a\xb2" + "\x78\x7f\x05\x4e\xe7\x41\xe1\x6c" + "\xd9\x90\xe4\x89\xc3\x25\x65\x79" + "\x75\x7e\x1a\xa3\x25\x57\xc9\x0b" + "\x06\xfd\x20\x12\x91\x67\xc5\x1e" + "\xd6\x0b\x8b\x40\x3c\x3a\x6e\x71" + "\xa9\xeb\xeb\xe8\xf7\x6b\xcd\x31" + "\x70\xb6\xe6\xbe\xa6\x6c\x32\xa7" + + "\xd7\x41\xf2\x99\x56\x35\x95\x60" + "\x9d\x34\x1a\x00\xd7\xdb\x4a\xee" + "\x91\xe4\x89\xaa\x6a\xbf\x35\x0b" + "\x46\x75\x6f\x13\xf4\x76\x00\x7f" + "\x3d\xda\x64\x92\xba\x18\x9a\xd1" + "\x8b\xa2\xa7\x62\xcd\xd2\xb2\x6e" + "\x71\xc9\x61\x87\x1f\x94\xba\xcd" + "\x5d\x4a\xbe\xa3\x8b\x51\x50\x15" + + "\xd2\x62\x7d\xcf\x82\xc9\xd3\x20" + "\x50\x81\xba\x23\x9d\xe2\x36\x1f" + "\x9e\x3f\x76\x92\xf0\x0b\xae\x48" + "\x07\x70\x3a\x1d\x6b\x7e\x52\x7a" + "\xe3\x85\x1a\x58\x97\x90\xa8\xb4" + "\xe5\x8b\x15\xdc\x0f\x52\x1a\x1f" + "\x6e\x72\x7d\x16\x7d\xb3\x8d\xf9" + "\x62\xe8\x13\x11\x6e\x78\x02\x88" + + "\x18\xfc\xce\x6b\x96\x98\xc3\xc3" + "\x00\x6e\x63\x18\x43\xb3\x54\xb7" + "\x91\x19\x3b\xf5\x68\xa1\xb6\x6f" + "\xe5\x2f\x4c\xb8\x55\x1b\x18\x87" + "\x8c\xbc\x21\x27\x10\xc9\x86\x16" + "\x2a\x0e\x03\x95\x60\x06\x49\xc6" + "\xda\x55\xdf\x97\x2f\xeb\xfd\x18" + "\x31\xd2\x27\x7c\xfc\x2c\xd5\x10" + + "\xb9\x31\x87\x11\x9c\xe0\x01\x2a" + "\xd8\x3c\x39\xcd\x82\x61\xc4\xb6" + "\x28\xe3\x08\x75\x65\xdd\xd7\x5e" + "\xfa\xa8\x1d\x68\x1b\xca\x02\x64" + "\x2d\x27\x9f\xce\x86\xbe\x3a\x60" + "\x9c\x7c\x16\x29\x5c\x43\x63\x93" + "\x42\x2a\x5a\xc4\xc1\xf7\x14\x48" + "\xcd\xca\x22\x9a\x22\x62\x65\x14" + + "\x0c\x47\x3b\x32\x31\x64\x52\xb4" + "\x18\xe4\x36\xd5\x1a\x4e\xcd\x40" + "\xc0\x3b\x93\x01\x3d\xdd\x0f\x43" + "\x23\x90\x64\x07\xde\x6d\x3e\x3d" + "\xb1\x23\x95\x2e\xef\x64\x05\x4b" + "\x4f\xbc\x79\x90\x05\x31\x0d\x8c" + "\x58\x3d\x7d\x83\x67\x69\x6c\x49" + "\x5f\x3b\x12\x89\x60\xf6\x79\x3a" + + "\xb0\x9a\xf0\x36\x9e\x14\xb2\xef" + "\x5b\xbb\x10\x4a\xca\x63\xf1\x03" + "\x98\x09\xe2\x06\x45\x70\x29\xd0" + "\xab\x3b\x5a\x1b\x00\xaf\xf0\x56" + "\x0d\x0e\x88\x70\xec\xcf\xf4\x7a" + "\x3f\x91\x3d\xbe\x6f\xa6\x32\x73" + "\xbd\xb4\xce\x7e\x4a\xc8\xe6\x32" + "\x55\x8f\x22\x9c\x9a\xa7\xc4\xed" + + "\x9a\x69\x2f\xa3\x9e\x14\x99\x29" + "\x70\x61\x18\x72\x11\x8e\x6c\x6d" + "\x52\x6e\x54\x45\x4f\x49\x74\xad" + "\xfe\xe7\xef\x89\x39\xb5\x3c\x2b" + "\x31\xb0\x2f\xe4\x0e\xe6\xa2\xb9" + "\x23\x48\x0e\x67\x0d\xfd\x58\xf8" + "\x6d\x63\x2c\x49\x7e\xab\xca\xeb" + "\x70\x46\x2c\xd3\xfc\x72\xe0\x40" + + "\x1d\x4e\x34\xb2\x66\x6a\x7a\x45" + "\xfe\xdc\x37\x8f\x2a\x1f\xc8\xde" + "\xd5\xf9\x40\xab\x3e\xf8\xd5\x61" + "\x3c\x04\xdf\xf1\x76\x27\xa8\x5c" + "\x7c\x67\x46\xf8\x1e\x68\x74\x21" + "\x28\x16\x6d\x51\x4f\x1f\x24\x7c" + "\x4f\x37\x01\x1f\xc3\x94\x49\xf5" + "\x0c\x21\x0f\xdf\x67\x83\x3c\x25" + + "\x20\x18\xe9\x20\xeb\xbe\x4d\xc9" + "\xe7\x41\xb6\x62\x04\xc2\xaa\x19" + "\x50\xcf\x49\x8b\xf0\x34\x28\xc2" + "\x6d\x5a\x5d\x8e\x4b\xc7\xe8\x47" + "\x6a\xcb\x2a\xf4\xdc\x0c\x16\x78" + "\xb9\x68\x35\x3a\x75\x64\x53\x7a" + "\x71\xeb\xd1\x6c\x47\xd5\x28\x4a" + "\x11\xbc\x8f\x8c\x3f\xbc\x60\x03" + + "\xec\xb6\xc6\xf4\xd1\x94\xe8\xf6" + "\x9b\xcd\xb3\x18\x27\x08\x6b\x52" + "\xbf\x7f\x11\x12\xa8\x52\xf9\x73" + "\xf5\x5b\x94\x11\xb0\x64\xe8\x2b" + "\x64\x9b\x09\x42\xa5\x8e\xf1\x86" + "\xe2\x8c\x54\x07\x8a\xb2\x70\x27" + "\x9c\x1c\x5c\x29\x28\x0f\x39\x97" + "\xc3\x06\x52\xcb\x43\x6a\x2e\x67" + + "\xf8\xda\xba\x8e\x73\x2b\x50\x66" + "\x07\x4c\xa0\xf9\x8e\xfe\xba\x27" + "\x04\xae\xf6\x1b\x2f\x43\xda\x74" + "\x3b\x40\x8d\x27\x68\x82\x1d\x27" + "\x57\x1b\x47\x93\xac\x91\x8b\x01" + "\x1f\xc5\x76\xb2\x69\x68\x09\x01" + "\xd2\x7d\xc5\x6d\x01\xc1\x79\x5b" + "\xa5\x80\x6c\x80\x5e\x34\x23\xb6" + + "\x88\x20\xd7\xe9\x49\x43\xd2\x89" + "\xe0\xf6\x9c\x3e\x03\x7a\x31\xd5" + "\xea\xf8\xc8\x73\x9d\x1a\xc6\x5b" + "\x3d\x5a\x0f\xf1\xc8\xc2\xf9\x48" + "\x07\x95\x6b\x08\xdf\x14\x24\x47" + "\x92\x9b\x54\xae\xdf\x8c\x81\x79" + "\xbf\x15\xa4\x62\x7a\xa7\x24\x3d" + "\x76\x29\xb2\xd3\x9f\xf5\x2d\xb9" + + "\x44\xcf\x1f\xe7\x8e\x0f\x45\x80" + "\x86\x99\x0a\xdb\xfd\xdd\x63\x27" + "\xf2\xbc\x68\x96\x7a\x8c\x28\x8c" + "\xf6\xe2\x92\x03\x35\x9b\xd0\xd7" + "\x7a\xdd\x06\x65\x82\x54\x3d\x0a" + "\x4f\x9d\xce\xcd\xc1\xda\x43\x9b" + "\xb8\x63\x8b\x45\x61\x4f\x15\x8d" + "\x3b\x97\x9c\x12\xd0\xa4\xbd\x77" + + "\x96\x44\x5c\xc5\xd0\x7d\x7c\xc3" + "\xd2\xab\xbb\x25\x57\x63\xa9\xa6" + "\x63\xf3\xd7\xad\xf2\x63\x7e\x5b" + "\xdf\xf1\x73\x2e\x82\x37\xce\x9d" + "\x71\x1f\xb9\xb2\x6a\xa1\xe5\xe1" + "\x3c\x16\xa0\x5b\x23\x98\x48\xe4" + "\xad\x15\xe5\xf6\x32\x9c\x75\xf2" + "\xcf\xee\x15\x86\xf8\xf1\xe2\xa5" + + "\xce\xab\xa6\xeb\x19\x0d\x6c\x0b" + "\xe4\xee\x9e\x64\x45\xc4\xaa\x6c" + "\x0e\xe1\x65\xb4\x83\xf2\xb4\x59" + "\x2d\x21\x29\xf7\xf2\x04\x67\xd7" + "\x92\xee\xd1\x70\x83\x73\x4e\x8d" + "\xb5\x1e\x6c\xea\x8b\xc2\xca\xfb" + "\x05\x8e\xf2\x4e\x8b\x21\x84\x2c" + "\x0d\x6e\x6c\x7e\xd0\xf7\x52\x2c" + + "\x16\x96\xe0\x0f\xf0\x4c\x13\xd8" + "\xc3\x8c\x8c\xe4\x9a\xe5\x31\x4a" + "\x82\x7b\xb8\x5f\x66\xe5\x0a\x5c" + "\xa7\x26\xbd\xb2\x5a\xf1\x2e\xdc" + "\x65\x17\x78\x5b\xf5\xae\xeb\x63" + "\x5e\x58\x39\x53\x3c\xc8\x6c\x4f" + "\xe4\x78\xfc\xab\x01\xe2\x8a\xd0" + "\x56\x2a\xbe\x1f\x9a\xee\xe7\x98" + + "\xa2\x89\x14\x0e\xdd\x97\x48\x0a" + "\x7f\x98\x3d\xe9\x36\x87\x9f\xc0" + "\x37\xa4\x79\xea\xb8\x00\x7a\x42" + "\xfa\xe9\x89\xaf\xe4\x39\x2b\x3e" + "\xf1\x38\x81\x7e\x2f\x2d\x1c\x45" + "\xb0\x8b\x14\x37\x11\xe4\xcd\x08" + "\x41\xe5\x50\x0d\xc7\x68\x69\x01" + "\x91\x12\x47\xdd\xe1\xee\xdc\x2b" + + "\x67\x43\xc6\x47\xc8\xe2\xcc\xca" + "\xc0\x4e\xaf\x45\x9f\x6b\x49\x6a" + "\x2c\x04\x34\x60\xf3\x36\x08\x2a" + "\xea\x62\x6c\x0b\x90\xf3\xa1\x14" + "\x40\xf5\xf1\x3e\x63\x93\xfa\xe7" + "\x93\x6d\xa7\x72\x0a\xb3\x23\xd3" + "\x51\xe4\xea\x0f\xb5\xc8\xee\xff" + "\x87\xef\x04\xbd\x72\xc1\xaf\x4e" + + "\x07\x40\x48\x6c\x1b\x1e\xdb\x3b" + "\x02\x02\xbe\xe6\xa1\xd5\x10\xe1" + "\xae\x5a\x66\x15\xae\xe1\x24\x1c" + "\x27\x9d\x9c\x7c\x89\xf6\x0e\xfa" + "\x07\xb6\x22\x9d\x2a\x66\xa0\x01" + "\x47\xf1\x22\x67\xce\x64\xc3\x18" + "\x4c\xf7\x21\x75\x6d\x14\x46\x04" + "\xb8\xab\xa8\x9f\x4e\x7a\x77\x39" + + "\x27\xe4\xea\x8d\x0c\xb3\xa7\x36" + "\x3e\x58\x2e\xb6\x5a\x5f\xac\xb4" + "\xa9\x39\x0a\xdf\xa2\x9f\xef\xac" + "\x39\x90\x65\x5d\x04\xa6\x29\xc9" + "\x7e\x2f\x26\xfc\x6e\x9d\x4d\xe1" + "\x9d\x8d\x53\x05\x2d\xd6\xe6\x15" + "\xe0\xf9\x88\xc4\x7e\xa7\x42\xee" + "\x42\x8a\x2c\x89\x65\x63\x83\xae" + + "\xfd\x33\xf5\x1a\x1b\xdd\xab\x90" + "\xcb\x0a\x0f\x75\x76\x25\x3d\x7c" + "\xc8\xc9\x6c\xc7\x5a\xc5\x0a\xfa" + "\x05\xaa\x75\x52\x2e\x30\xb4\xc3" + "\x9e\xc1\x2d\xef\x1d\xb3\xcb\xe2" + "\x7b\x35\x06\x38\x51\xb7\x3d\x5f" + "\x8e\xf9\x09\xf5\x00\xdf\x74\x64" + "\x89\xbd\xeb\x28\x1e\x5f\xa7\x9b" + + "\x51\xd5\xde\xab\xe7\x9b\x51\x74" + "\x10\x44\xb7\xc8\xb8\x58\xd3\x03" + "\xa9\xd9\x10\x0e\x0b\xb1\x00\x4d" + "\xb7\x52\xda\x28\xb1\xb0\x92\x63" + "\x04\xc9\x75\x0b\x98\xa2\x44\x67" + "\x6c\xf9\xf7\xa8\xae\xb0\x05\xc3" + "\x32\xf9\x2c\x18\x1d\x42\x2e\x04" + "\xca\x36\x46\x9e\x50\x5d\xfc\xf6" + + "\xdf\x76\xd6\x5f\xe0\x1f\xcb\x47" + "\x0b\x96\xa8\x9b\x91\x42\xc6\x69" + "\x6d\xde\x65\x01\x06\x23\xd0\x40" + "\x9a\xb2\xb8\xd6\x4e\xf4\x3b\x78" + "\xbd\x98\xd0\x6e\xfb\x19\x4e\xc8" + "\x23\x61\xbe\xff\xf7\x09\x1f\x60" + "\x3a\x4a\xe2\xa0\xc5\x89\xae\x87" + "\x2a\xac\x05\x5e\x9c\x4e\x86\x07" + + "\x00\x5e\x2c\x39\xfd\x9e\x0f\x85" + "\xde\x1b\x51\xe2\x7f\x66\x9f\xc2" + "\x8f\x29\x31\x84\x6d\x40\xcf\xf5" + "\x5d\xd0\xc0\x79\xc8\x10\x0b\xf9" + "\x12\xf0\x38\x00\x1d\x9b\x3e\xfb" + "\x99\x97\x8c\x0a\x7a\x4e\xc0\x84" + "\x86\xe9\xc8\x96\xd4\x02\x61\xb7" + "\x75\xa6\x6d\x17\x13\x3b\xa6\xde" + + "\x69\x53\xf5\xdd\xef\xc2\xaf\x2f" + "\xb9\x63\xac\x24\x6f\xf0\xbf\x70" + "\xdd\x6a\x92\x6e\x42\x37\x1a\x1e" + "\xcf\x18\xfa\xfd\xad\x37\x35\x77" + "\x52\xb5\x84\x59\x63\xea\x11\xd2" + "\x24\xed\x1a\x8c\x4d\xed\x7e\xb1" + "\x67\x8b\x0b\x14\x74\xde\xe9\x5d" + "\x57\xff\x8b\x76\xc8\x01\x25\x74" + + "\x89\x9b\xe5\xb3\x51\x5a\x43\xe4" + "\xc9\xa1\x33\x41\x55\x39\x61\x13" + "\x59\xee\x0b\x44\x73\x69\xf4\x87" + "\xe4\x01\xc4\x00\xf8\x10\x47\x71" + "\xc9\x46\xc4\xd6\xce\x4b\xcf\xc0" + "\x68\x53\x4d\x6c\xd6\x7f\xaa\xe0" + "\x37\xfc\x68\xfc\x1a\x81\x5d\xde" + "\x57\xa0\xc2\xb7\x72\xbd\xfe\x61" + + "\xe8\x25\x47\xbe\x91\x2b\xff\x90" + "\x1e\x00\x81\x5e\xf6\xbf\x0a\x71" + "\xf3\x04\xef\xc5\x76\x34\xeb\x15" + "\xb7\xa2\x0d\x3c\x1b\xb5\xda\xcc" + "\x2b\x65\xc0\x2c\xa5\x40\x38\x88" + "\x56\xa8\xe4\xf5\x9d\x7d\xfc\xd1" + "\x88\xfc\x0f\x07\x53\x39\xbc\xeb" + "\xc1\xed\xef\x91\x7d\x94\x0f\x34" + + "\xcf\x11\xbd\x6d\xbb\xbe\xdd\x1e" + "\x03\xe2\x19\xc6\x45\xaa\x97\x82" + "\xa6\xd2\x2b\x96\x6f\x82\x54\x63" + "\xc7\xed\x12\xfa\x67\x3f\x3f\xba" + "\x8d\xd8\x7a\xfc\x1d\x0f\x22\x25" + "\x01\xc8\x83\x86\x81\x9f\x05\x5d" + "\x64\x57\x38\x2d\x6e\xf2\x77\x05" + "\x0d\xe8\x53\xa4\x46\xc6\x74\xa5" + + "\x0c\xe3\xf4\xb8\x71\x6c\xd1\x89" + "\x29\xfa\x3d\xc6\xfb\xab\x2d\x9e" + "\xeb\x5c\xde\xdf\x5e\x06\x33\x60" + "\xc6\x45\x3c\x0f\x1f\x1d\x2b\x07" + "\xec\x29\xd4\xb8\x2a\xbc\xd0\x0c" + "\x89\x1f\x47\xc2\x8c\x43\x47\xe7" + "\x9e\x67\x9d\x31\x56\xe8\x1c\x13" + "\xba\x4e\xb2\x87\x28\xa2\x20\x75" + + "\x8c\xc7\x4c\xd6\xc9\x47\x58\x79" + "\x7b\xb2\x6c\x9b\x1b\x62\x50\x6c" + "\xab\x22\x80\xdf\xf8\x9b\x09\x07" + "\x1d\xda\x4e\xc0\xeb\x62\xf8\x48" + "\x16\x3c\x60\xe1\xed\x32\x27\xd1" + "\x50\x94\x9a\x5c\x0f\x0e\xa8\x19" + "\xfc\xb4\x29\xb4\x54\x7f\x25\xe2" + "\x15\x05\x46\x45\xc6\xb2\xd3\x66" + + + "\xd6\xad\x3c\x45\xbc\xb7\xe2\x8d" + "\xf8\xc1\x0b\xbc\xa7\x00\x39\x20" + "\xaf\xd3\xab\xa6\x47\x6e\xd8\xbc" + "\xfb\xef\x02\x85\x12\xac\x1c\x91" + "\x69\x54\x96\xec\x42\x02\x55\x2d" + "\x7e\x01\xe0\x29\x92\x76\x9f\x0e" + "\x85\x98\x97\x65\x8f\x07\x3f\x63" + "\xef\x51\xf7\x4c\x49\xd4\x87\xfb" + + "\x10\xee\x51\xd5\xa2\xe2\x66\x60" + "\xa6\x09\x7e\x72\xd8\xf1\xa8\x87" + "\x8d\x14\x01\x2c\xab\x8b\xd0\x00" + "\xfe\x33\x4f\x42\xf1\xe4\xa8\x6d" + "\x71\x4e\x9a\xcf\xf0\x17\x6d\x46" + "\x19\xcb\xf5\x3b\x10\x20\x50\xff" + "\xc0\xec\x62\xd0\xd8\x97\xcf\xdc" + "\xc4\x0a\xd8\x81\xaf\xd9\xc0\x80" + + "\xab\xad\x7a\x1d\xff\x45\x04\x1a" + "\x7c\xa6\xf6\xd5\x60\x82\xd3\x65" + "\x6f\xb2\xcf\x91\x08\xfb\x62\x6e" + "\xd6\x91\x7d\x5c\xa5\x0f\x1e\xef" + "\xcd\x72\xdb\x33\xba\xc7\xe7\x47" + "\xb2\x74\x7c\xfa\x09\xbc\x7c\x01" + "\x3c\x50\x0a\xf5\x90\x15\x93\x3c" + "\x42\xaa\x6b\x61\x60\x4f\xc5\xca" + + "\x1c\x58\xf4\x1b\xeb\x7c\x85\x98" + "\x66\xb1\xa7\xac\x86\xe1\x35\xe6" + "\xac\x22\x97\x65\x22\xdd\x8d\x27" + "\x07\x80\xb6\x1d\x4c\x3c\x90\xa0" + "\x02\x14\xf2\x48\x89\x45\x6e\x36" + "\xa2\xbd\x6a\xb9\x14\x9c\xb4\x31" + "\x90\x31\x40\xe0\x09\x4b\x9c\x32" + "\xfe\x43\x9f\xd2\xa3\x7c\x19\x97" + + "\xb1\xe2\x07\x4b\x5d\xdd\x73\x71" + "\x21\xa2\x9e\x8d\xcb\xc4\x44\xd1" + "\x14\xab\x05\x11\xa4\x4e\xb0\xe8" + "\xf1\xd8\x80\xfe\x42\xa5\xdd\x92" + "\xe6\xdc\x03\xcf\xa8\x2f\x98\xe9" + "\xfc\xcf\x22\x1a\x65\xa9\x5e\x8b" + "\xc4\x88\xad\x3f\x7f\xea\xf4\xf7" + "\x5c\xa9\x5b\x6a\x3e\x77\xdb\x62" + + "\xc7\x57\x03\x82\xb4\x3f\xbd\x18" + "\xad\x58\x14\x6f\xae\x39\x20\x99" + "\xa1\x4a\xb4\x25\xc5\xf3\x1d\x9a" + "\x81\x52\x3d\xed\x57\x03\x78\x2d" + "\xd4\xd4\x7a\xc7\x4d\x7e\xcf\x58" + "\xc4\x4f\xdf\xf9\x98\x79\x9a\xd4" + "\x5e\x20\x71\x1d\xb5\xa8\x65\x44" + "\xaa\x54\x92\x64\xa6\x0e\xee\xa0" + + "\x35\xb2\x92\x9c\xe8\xe6\xaa\x4b" + "\xa1\x93\x39\x6b\x0e\xbd\x3b\xa7" + "\x31\xd0\x3d\x69\xec\x60\x6d\xd0" + "\x1c\x88\x56\x71\x1b\xb9\xca\x03" + "\x4b\x57\xb3\x1d\x2f\x86\x15\xd6" + "\x1a\x06\xbb\x64\x85\x01\x5b\x48" + "\x06\x1e\x18\xa0\x88\x49\x43\x27" + "\x57\xc7\xc0\xc1\xd4\x1a\xd6\x2c" + + "\x4a\x0d\x48\xf3\x1c\xde\xe2\x03" + "\x1a\xcf\x8a\xbc\xc7\xed\xd8\xf0" + "\x9c\x5a\x29\x68\x03\x33\x3e\xf2" + "\x7d\xa9\x46\xc5\x68\x5f\xdd\xfa" + "\xb1\xac\xf8\x96\xad\x97\x55\x89" + "\xe2\xda\x1b\x67\xd5\x49\xdd\xbd" + "\xf4\x43\xdd\x21\x28\xd5\xfc\x16" + "\x1a\x14\x19\x66\x12\x54\xa4\xa5" + + "\xa0\x86\x0d\x03\xd3\x34\x5c\xc8" + "\x5e\xe9\x3c\x21\x80\x2e\x4b\xf1" + "\x7f\x6d\x7e\xf0\x9b\xed\x3e\xce" + "\x79\xec\xa3\xa3\x21\x3e\x6c\x47" + "\xd3\xa5\xde\xca\xf2\x11\xec\xb4" + "\xaa\x36\xa9\xcc\x12\x5f\xad\xd1" + "\x7d\x1c\xe6\x34\x9e\x60\x24\x17" + "\xa2\x7b\xd6\x2f\xf3\x0d\x52\xcc" + + "\x2a\x7f\xa1\xa9\xa8\xe2\xfb\x6b" + "\x17\x50\xd9\x03\x60\x2f\xac\x1c" + "\x8c\xb4\xa2\x8e\x57\x62\xc0\x38" + "\x8a\xc3\x3c\xcc\x5c\x4d\xca\x21" + "\x91\x20\x45\x67\x54\x7a\x06\xff" + "\x2c\x46\x9d\x13\x5d\xdf\xbf\x63" + "\x6f\x00\x50\x14\xa1\x76\x13\x22" + "\xec\x9a\x2a\x33\x5e\xfe\x1a\xc8" + + "\x41\xa1\xfe\xba\x99\x9a\xa0\x11" + "\x40\x16\xd4\x19\x4b\x41\xe0\x7f" + "\xd1\x09\xb6\xf3\x2a\x07\x6b\xd6" + "\xd2\x54\x55\xbc\x34\xde\xf7\x27" + "\x45\x7b\x51\xbc\xaf\x29\x65\xd6" + "\x9f\x8d\xd1\x12\x21\x35\xe4\x8b" + "\xd7\xef\x0d\x4e\xe1\x92\x21\x94" + "\x1e\xaf\xc0\x90\x1f\x87\x65\xb4" + + "\xcf\x29\x9f\x43\x9f\xc7\x32\xfa" + "\x3b\x2a\xd8\x4d\xc0\x21\xf3\x7b" + "\xb1\xc1\xa2\xea\x54\x7f\x12\xff" + "\x18\x96\x5e\xf3\x2d\x5f\x36\xa8" + "\xdd\xf8\x0e\x4d\x02\x29\x2d\x85" + "\x4a\x8c\x22\x59\xc1\xe2\x5c\x39" + "\xd3\xfe\x5a\x21\xe8\x44\x9f\xb6" + "\xe3\x58\x74\xb2\x98\xf8\xc1\x16" + + "\xbc\x25\x3f\xf3\xe0\x87\x0f\x17" + "\x98\xc0\x39\xc3\x67\xb6\xdc\x24" + "\xae\x3e\x07\xab\xa4\x02\x17\xbf" + "\x44\xfb\x8c\x23\x9c\x91\xa6\xad" + "\x75\x63\xee\xdd\x11\x85\x00\x53" + "\xad\x60\xdb\xb8\x85\xfa\x92\xdb" + "\x0e\x21\x21\xa4\x66\xa3\xb6\x50" + "\x8f\x55\x37\x4c\xeb\xf8\x7b\xdc" + + "\x7e\x25\x4f\x2e\x08\xa1\x7b\xe4" + "\x7c\x9d\x68\x35\xdf\xe2\x0e\xcf" + "\xd0\xa0\x1b\x32\x8e\xc3\x8f\x8b" + "\x8b\x5e\x74\x0f\x4c\xc6\x70\x94" + "\x2f\xa2\x5f\xd6\xf5\x87\x38\xa7" + "\xbe\xef\xa7\xc2\x9b\xf8\x81\xa5" + "\x8a\xc9\xe4\xee\xa6\x0b\x5a\x83" + "\x71\x1a\x29\xa3\xe9\x83\xe1\x86" + + "\x3b\x04\xe4\x89\xb0\x87\x54\xfb" + "\xd2\x9b\x79\x09\xef\x9d\xe4\x4d" + "\xbe\x60\xe7\xb3\xc0\x70\xa8\x9d" + "\x39\x15\xee\x89\xd3\x1d\x4e\x5e" + "\xdb\x05\x57\x91\xfa\x49\x38\x1b" + "\x81\x0e\xac\x5e\x94\xe1\xe5\x7c" + "\x5c\x3f\x0d\xb0\xa0\x72\x17\x7c" + "\xa1\xb5\x00\x6c\x76\x26\x79\x54" + + "\x5a\xe2\x60\xc3\xbf\xb6\xe9\x8c" + "\x78\x1a\x5a\x07\x95\x51\x42\xe6" + "\xf4\x32\x17\x48\xa8\x56\xc7\x9d" + "\x7a\xb5\x32\x54\x0f\x44\xc0\x83" + "\x1f\x28\x20\xd7\xf1\xb3\x70\xc6" + "\x51\xe0\x35\xd1\x0e\x91\x05\x22" + "\xe7\x2b\x05\xdb\x0e\x4b\xd1\xde" + "\x39\xea\x68\xc5\x27\x3d\x7b\x69" + + "\x4b\x71\xf6\x1a\xf1\x6c\x3a\x2e" + "\x6f\xb9\x13\x3c\xa6\x8e\x0f\x77" + "\x95\xff\x8c\x4c\xfb\x42\xc2\x98" + "\x91\xbe\xa0\x95\x0c\x9a\xec\x67" + "\xcf\xe7\x8e\xeb\x5a\x33\xf0\xee" + "\x24\xc4\x71\x33\xe7\x4c\xf3\x63" + "\x05\xe5\xed\x31\x95\x39\x0b\x98" + "\x19\x36\x3f\x9b\xfe\x3a\xe8\x7c" + + "\x1c\x4a\x5e\x79\x2e\xbd\xf1\xb3" + "\x89\xca\xcd\xa1\x7e\x18\xd3\x85" + "\x3d\x68\x41\x35\x3c\x4e\xe4\x15" + "\x67\x40\xed\x80\x9c\x23\x8c\x2a" + "\xed\x08\xc5\xbf\x5a\x02\xe6\xbd" + "\xed\xc5\xf2\x3b\x31\x1e\x63\xb1" + "\x12\xa1\xd9\xe7\x3b\x3b\xcb\xb2" + "\xcc\x38\x78\x7c\x4f\xc1\x54\x05" + + "\xbf\xe0\x88\xaa\x27\xb7\xe6\x1b" + "\x07\x35\xe8\x64\xba\xc2\x64\xd7" + "\x86\xeb\xd7\xba\x97\xf3\xbc\x4a" + "\x4f\xb7\x20\x79\xbf\x1c\xfd\xb2" + "\x2b\x03\x3d\xf1\x5b\x91\xe8\x65" + "\x22\xd6\xfb\x19\xbb\x4a\x26\x9d" + "\xb4\xa2\x48\x2f\x79\xaf\x62\x2f" + "\xec\xba\x19\x86\x5f\xb0\xa9\x22" + + "\x33\x32\x45\xdc\x05\x90\xf2\xde" + "\xcf\x4b\xac\x2f\x7a\xc4\x08\xc2" + "\xac\x55\x3d\xac\xfe\xa3\x57\x60" + "\x07\x12\x2c\x90\x5d\x72\x23\x17" + "\xec\x0f\xeb\x33\x27\xc6\x31\x9c" + "\xbb\x63\x3c\xbb\xdb\xcc\x13\x49" + "\x38\x58\x30\x07\x2b\x54\x3e\x11" + "\x97\x2d\x0c\x31\x2a\xe7\x48\x9d" + + "\x58\x6b\x31\xb8\x54\x27\xd5\xc1" + "\x60\xab\x1f\x81\x42\xa3\x35\x94" + "\x35\xc9\x02\x61\x76\xc3\x26\xe1" + "\x2e\x29\x25\x3e\x95\x15\x4f\x7a" + "\x59\xad\x2c\x03\xc3\xe7\xc3\x1b" + "\xb6\x1c\x2a\xfe\x81\x7a\x2d\x4b" + "\xcb\xa6\x8b\xe0\xe2\xf4\x0b\xa8" + "\x68\x02\xf9\x8c\xb2\xc9\xfc\xb7" + + "\x96\x82\x28\x51\xa7\xd1\xe2\xa2" + "\xb0\xdb\x6d\xf6\x7b\x52\xca\xba" + "\xd4\x3c\x31\x80\x8f\x41\x9b\x40" + "\x8b\x6a\x3c\x87\xe8\x1a\x4b\x2b" + "\x5f\x29\x93\x2a\xc7\x5e\xe9\xb8" + "\x5f\x79\x5a\x2e\x90\x50\xf6\x0e" + "\xfa\x6a\x87\x2f\x88\xc8\x5a\x16" + "\x03\xe2\xc1\x25\xd9\x87\xca\x90" + + "\x36\x79\xce\x93\xa7\x8d\x12\xbc" + "\xf9\x9d\xbe\x39\xd6\x9a\xc6\x3c" + "\x7c\xd3\xb6\xec\x1f\x99\x65\x69" + "\xa3\xff\xb5\xb8\xbf\x01\xe0\x64" + "\x0d\x01\x34\x93\xbf\x0a\x61\x5d" + "\x0c\x3f\xda\xdf\xb0\xee\x8f\x71" + "\xd7\x40\x05\x03\xa8\x1e\x2b\x5b" + "\x37\xd3\xb4\xf4\x73\x2f\xf2\x59" + + "\x3d\xeb\xbb\xd9\xc4\x4e\x42\x54" + "\x1c\x92\xb2\xd7\xe3\xaf\xce\x34" + "\xc5\x37\x6d\x29\x2e\x02\x68\x5e" + "\xb0\x16\x9f\x35\x2b\x0a\x8e\xa2" + "\x73\x9d\x3f\xbc\xd9\x2d\xd8\xfd" + "\xff\xe1\xf3\xba\xf9\xa8\x39\x69" + "\xc4\x6d\x73\x31\x5c\xf4\xcf\x55" + "\xe7\xe8\x92\x78\x42\x56\x0f\x91" + + "\x2c\x04\xd0\xaa\x05\xbf\x35\xdf" + "\xcc\x6a\xda\x28\x70\xec\x25\x29" + "\x5c\x3f\xaa\xe1\x04\xa8\x2a\x82" + "\x63\x8e\x34\x3d\x7d\xec\xed\xb5" + "\xcf\xb2\xf6\xb4\x30\x28\x36\x03" + "\x2a\xba\x6b\x09\x0d\xcb\xbf\x08" + "\x04\x3f\xec\x9f\x64\xe4\xfd\x8a" + "\x17\x4e\x43\x1c\x4f\x2e\x40\xfb" + + "\x26\xc3\xce\x8a\x9d\x6c\xc4\xb6" + "\xc0\xb8\x6c\x29\x3d\x58\xf5\xac" + "\x08\x72\x07\xcf\xc6\xca\x52\x25" + "\xd6\x3d\xa0\x0d\x83\xef\x61\x52" + "\xb4\x46\x00\x5d\x30\xee\xa7\xf6" + "\x85\x3e\x0a\xcb\x96\x5c\x86\x24" + "\x89\x7a\xdf\x8b\x44\x91\x59\x71" + "\x83\x23\xe4\xf8\xdb\x5c\x1d\x22" + + "\x09\xdc\x47\x35\xf4\xaa\x1d\x95" + "\xd4\xac\xae\xd4\x0b\xd5\x82\xb9" + "\x56\x11\x9f\x45\x2b\x94\xc9\xdc" + "\x72\xb2\x45\xfa\xe2\xb1\x67\x80" + "\xb7\xfb\xa3\xd6\x0c\xd0\xfb\xe2" + "\x37\x2d\x74\xca\xdd\x24\xfc\x46" + "\xdd\xfb\x26\x7b\x76\x44\x45\x66" + "\x7c\xf6\xd8\x2f\x61\xa3\xa6\x3f" + + "\x60\x92\xe3\xdf\x49\xb3\x09\xde" + "\x93\x90\x54\x73\xf7\x12\x46\x98" + "\x02\x3b\x85\x67\x81\xe2\xed\x7c" + "\x03\x77\xd1\x29\xb4\x9b\x80\x7d" + "\xf0\xc4\x56\x27\xfb\x6b\x0b\x45" + "\x80\x2b\xf0\x93\xba\xf9\x9f\xc5" + "\x61\x95\xad\x20\x57\x54\x69\x3e" + "\xc7\xe2\x31\x33\xbe\xf0\x7c\x0c" + + "\x03\x48\x9c\xca\x9b\x7c\x72\x42" + "\x5e\xda\xdc\x29\x46\x03\x14\x7c" + "\x17\xf6\x21\xba\x39\xab\xec\x00" + "\xc1\xef\xba\xf0\x96\xb1\x2b\xb5" + "\x74\x1c\xac\x73\xde\x03\xd5\x56" + "\x2c\x9d\x9c\x53\x0f\xce\x2d\x08" + "\x87\x95\x3c\xfa\x8a\x0a\x77\xf7" + "\x7d\x7e\x5c\x59\x7a\x5a\x89\x96" + + "\x47\xfb\xfa\x6e\xd2\x69\xdb\x29" + "\x29\x74\x5e\xee\xf2\xe9\xb9\x04" + "\x03\x02\xe9\x88\x38\x1d\xf2\x91" + "\x15\xa6\xdf\x7a\x79\x8e\x3f\xcf" + "\x37\xe7\xeb\x61\x1c\x12\xf9\x89" + "\xbd\x03\xba\x06\x06\x69\x59\x87" + "\xb7\xfe\x78\x97\x72\x7a\xc2\x1a" + "\x18\x60\x72\x34\x3c\x72\x18\xe0" + + "\x7e\x93\x70\xfc\x86\xcf\x42\x7c" + "\x05\x8f\x11\xa1\x75\x33\xf8\x5b" + "\x98\xbf\xe9\x39\x13\x54\xc0\x11" + "\xf9\x08\xfa\xac\x04\xf3\xa2\x4a" + "\xb3\x6f\x8b\xda\x1a\x4d\x61\xd6" + "\x0b\xad\x05\x5b\x77\x3b\x73\x92" + "\x66\xdd\x15\x30\xf1\xd5\x8e\xcf" + "\x32\x0a\x15\xd8\x18\xef\xad\x1b" + + "\xed\xf9\x3f\xfb\x9a\x9b\x59\x2e" + "\x5c\x51\xf6\x17\xab\xe0\xc2\x28" + "\x49\xa4\x4d\x47\xfd\xe4\xbe\x1c" + "\x52\x44\x36\x4f\xa4\x79\x12\x07" + "\x55\xe8\xfb\x01\x66\xff\xab\x97" + "\xc4\x51\xda\x5f\xe8\x94\xe3\x3e" + "\x0b\x7c\x59\x67\xf6\x85\x03\x19" + "\x4b\xe3\x7e\xa2\xc6\xcc\x9f\x6e" + + + "\xf8\x92\xa4\xdd\xde\x7a\xc7\x3b" + "\x05\x72\x29\x78\xea\x3a\x1a\xc1" + "\x4c\x1b\x93\x34\xe7\xa3\x89\x5e" + "\xbb\x94\x56\x9f\x2e\x2e\x51\x17" + "\xb6\xf8\x7b\x17\xf3\x49\xc3\x5d" + "\x3e\xff\xc7\x08\xba\xa4\x2e\x23" + "\x5d\x14\x11\xf5\x16\x9d\x4f\x9c" + "\xc3\x79\xb3\x33\xa3\x09\xf1\xcc" + + "\xa9\x24\xeb\x80\x70\x85\xe2\x60" + "\xfd\x0c\x8e\x48\x4d\xfb\xed\x7b" + "\xb8\xcd\x59\xc2\xd7\xbb\x1e\x72" + "\xa9\x90\x63\xbc\x55\xa8\x0d\x0b" + "\x70\x4c\x31\xde\xdb\x04\x4d\x2b" + "\x46\xe8\x32\x6c\xbc\x1f\xbf\xcd" + "\x9e\xfc\x62\xb1\xab\x3e\x83\x33" + "\xb7\x3a\xdd\xb0\x8b\xb4\x39\x99" + + "\xb9\xdf\xc3\x97\xb1\x8a\x2b\xc4" + "\x54\x81\x16\xcf\xb0\x49\xa5\x55" + "\x92\x06\xb5\xc1\xe7\x48\x67\xad" + "\xcb\xcb\xc5\x6f\x0f\x78\x75\x27" + "\xc8\xd7\xc9\xe1\xb8\x80\xab\x4e" + "\x56\xcd\xdb\x3f\xe1\xda\x69\x8c" + "\xce\xea\x69\x99\xfb\xb4\xe6\x47" + "\x5a\xcb\x05\xa7\x85\x10\x2f\x00" + + "\xb9\x0e\x1b\x71\x1f\x2c\x89\x96" + "\x54\xb9\x0a\x78\xc8\xf2\x05\xb9" + "\xdb\x92\x07\xa2\x09\x63\xe2\xac" + "\x26\xe1\x84\x06\xb3\xc9\x8a\xec" + "\x47\x24\x0a\xb4\xb6\xd8\x6a\x48" + "\x24\xfb\xe3\x9f\xc1\x1f\x12\x60" + "\x3f\x3b\x8e\x1a\xcf\xfc\x26\x56" + "\x94\xf3\xd1\x6a\x22\x86\x56\x4e" + + "\x52\xbf\x37\x30\x18\x43\xfb\x2b" + "\xd7\x25\xc7\x78\xb5\x6d\x1e\xb6" + "\xd7\xe5\xb3\xbb\x60\x40\xfd\x8e" + "\x8e\x48\xac\xdb\x01\x47\x01\x2e" + "\x49\xa4\x0a\x36\x9a\xcf\x75\xac" + "\x08\x4d\x63\x79\x05\xfd\x0c\xb7" + "\xef\x15\xfb\xff\x6d\x53\x91\xa5" + "\x6c\x10\x7c\xd0\x82\x75\xc3\xb2" + + "\x98\x4a\x6f\x23\x22\xbb\xfb\x5c" + "\xbb\x00\x68\x06\xe9\x59\x0c\x0b" + "\x74\x77\x9a\x5a\x8f\x9a\xc6\x4a" + "\x48\xc9\xbe\xd6\x04\xf8\x33\x2b" + "\x66\xc4\xe6\x32\x95\x92\x72\xb3" + "\x73\x9c\x59\x4e\x0f\x6d\x95\x68" + "\xcc\x31\x5c\x15\x9f\x24\x7a\xa4" + "\x4e\x28\xce\xe1\x0d\x0f\xd8\x24" + + "\x88\xd1\x57\x64\x0d\xa7\x47\xf3" + "\x8b\x38\x7a\x8b\x6b\xa8\xed\x86" + "\x13\x60\xcd\x0c\x06\xff\xcd\xb7" + "\xb2\x3f\x05\xd0\xc7\xb6\xb1\xbe" + "\x9f\x0a\x24\x99\x87\x23\x02\x0b" + "\xb2\x89\x61\x77\x4f\x38\xbb\x1b" + "\x3a\x19\x66\x90\x1e\xe7\x95\x86" + "\x7e\xac\xff\x06\x97\x00\xb5\x2e" + + "\x62\x3d\x8a\x4a\xc6\x46\x4b\x5a" + "\xd2\x43\x77\x24\xd0\xc4\x69\x84" + "\x33\xe4\xf7\x88\x3d\xa1\xb3\x2b" + "\x49\x58\xbe\x01\x10\x3a\xb2\x62" + "\x4c\x1a\x3d\xa6\xb4\x96\x35\xe8" + "\x3e\x3f\x18\x7d\xea\x7f\x4e\x45" + "\x1c\xb0\xaf\x17\x61\xce\x3f\x64" + "\x38\x36\x4c\x1c\xe6\xe5\x65\x4e" + + "\x5f\xcd\x5f\xa3\x8d\x50\x65\x40" + "\xeb\xca\x5c\x49\x8c\xdf\x65\x89" + "\x62\xa9\xe1\x12\x50\xa8\x2d\x0f" + "\xc4\x1c\xcf\xc1\x94\x1b\x47\xee" + "\x75\xfb\x08\x0a\xc8\x9b\xf1\xce" + "\x91\x35\xde\x81\xf5\x58\x49\x70" + "\x88\x4f\xef\x3a\xb2\xf8\x67\x28" + "\x5f\x9a\x9f\xea\x84\x93\x74\x8d" + + "\x8b\x50\x09\xdc\xe3\x30\xe8\xb7" + "\x55\x76\x31\x74\xcf\xd2\xf6\xfa" + "\x55\x03\x69\xdf\xeb\x6c\x60\x72" + "\xd6\xde\xc3\xd0\xb3\x92\xbb\x48" + "\x92\xf8\x7c\x5c\x84\x54\xb7\x65" + "\x1f\xf0\xd5\xd5\xc9\x7a\xcd\xf6" + "\x69\x1d\x40\x96\x59\x0a\xc3\xc2" + "\x78\x18\x92\xed\x50\x86\x26\x91" + + "\xd5\x68\x26\x8d\xf9\x5f\x8b\xe3" + "\x65\x19\xd8\x7a\x1a\x28\x15\x07" + "\x11\xce\xc6\x03\x7c\xfc\xc8\x1b" + "\x36\x04\x65\x8b\xe2\xe6\xbe\xcb" + "\x08\x98\xdb\x0c\xe8\x0f\xb0\x06" + "\x15\xd3\x3e\xfe\x66\xe0\xd6\x17" + "\x18\x50\x0b\x4d\xc6\x38\x9d\x2e" + "\xef\xca\x4d\x84\x56\xfd\x8b\xab" + + "\x45\x85\xdd\x6a\x17\x77\xdb\xe5" + "\x66\x9b\xc4\x72\x66\xcb\x71\x1b" + "\x77\x1d\x42\x68\x39\x07\x56\xd8" + "\xea\xaf\xe3\x83\xe8\x0f\x84\x03" + "\x77\x99\xc6\x1e\xd5\xda\x91\xb3" + "\x26\x67\x7f\x30\xb9\x3f\x24\xae" + "\x0c\x16\xca\xe8\x7b\xc8\x8a\xc8" + "\xf4\x55\xe3\x4c\xed\xcc\x74\x51" + + "\x66\xf5\xa4\x53\x7d\x49\xf9\xd4" + "\x10\x68\xb5\x97\x64\x46\x73\x89" + "\x21\xa6\x94\x04\x74\xda\xe1\xf8" + "\x68\x1c\x01\x8d\x93\x6a\x54\x82" + "\x62\xc1\x1a\xc6\x19\xcb\x3a\x1f" + "\x3e\x0d\xad\xab\x9c\xfa\xf8\x52" + "\x43\xea\xb7\xb4\x23\x65\x35\x15" + "\x25\x81\x60\xae\x61\xad\x16\x5a" + + "\x8e\x57\x81\xff\xf8\x67\x20\x75" + "\x7d\x44\x45\x90\x50\x21\x62\x78" + "\x6f\xaa\x05\x05\xcf\x2f\xc2\xc0" + "\x77\x1c\xed\x6b\xa6\xf0\x30\x10" + "\x39\xd7\x0b\x1f\x15\x9f\xf2\x31" + "\x85\xbe\xde\xe6\xc7\x89\x79\x2d" + "\x98\x7e\x67\x8e\x72\x0e\x07\x5c" + "\xd5\x1f\xe8\x06\xd3\x7b\x81\x0a" + + "\x99\x22\xe0\x7f\x72\x6a\x81\x0f" + "\x19\x33\x4f\x29\xc2\xcc\x35\x63" + "\xbe\xc5\x45\x47\x9f\x17\x20\x38" + "\x6e\x06\x2f\x92\x82\xb7\x47\xe6" + "\x8a\xfb\xca\x02\xde\x49\x2e\xc2" + "\xcc\xec\xc2\xfc\xff\xc2\x9b\x29" + "\x82\x82\x0e\x6e\xa2\xee\x8f\x9a" + "\x05\x32\x89\xfe\x8b\x27\x27\xa6" + + "\xe5\x13\xc6\xcb\xb6\x7e\xe1\xc1" + "\x1c\xa6\x7e\x49\x55\x1d\x13\x33" + "\xd5\xde\x7e\xaf\x9e\xd3\x69\x2f" + "\x1b\xf1\x6a\xde\x34\xf4\xc2\x73" + "\xfa\x75\xa3\xa4\x93\x24\xa5\x4c" + "\xc2\xc5\x33\xb8\x7c\x78\x06\x5f" + "\xcf\x71\x6e\x3e\x1f\x09\x4e\x81" + "\x66\x66\x74\x8b\x57\x1f\x45\x76" + + "\x2a\xe9\x33\xb5\x8c\xc1\x57\x6e" + "\xde\xb5\xbf\x55\xfe\xca\x9b\x33" + "\xeb\xa2\xee\x01\x9c\x8b\xea\xa1" + "\xd6\xa7\xf8\xf4\xf5\xb4\x23\x60" + "\x42\x4e\xb5\x52\xae\xe4\x52\x5e" + "\xdc\x70\xbf\x84\xe0\x55\xba\x1c" + "\x8d\xa4\x06\x3f\xba\x7a\x09\x22" + "\xa9\xbf\x0b\xe9\x3f\x63\x13\x55" + + "\x88\x93\x53\xe1\x82\xe0\xc7\x01" + "\x6b\x9c\x9a\x75\x30\x6f\x28\xfd" + "\xfb\xac\x6b\x17\x41\x10\x58\x94" + "\x53\xde\xc3\x3b\x7c\xf0\x80\xe5" + "\x2f\x77\x4d\x88\x75\x6f\xdb\xdc" + "\x4f\x9d\xbb\x40\xb8\x3b\x5c\xd7" + "\x11\x30\x08\xdb\x4e\x2e\x6c\xdc" + "\x8d\x29\x9c\xcd\xa2\x89\x87\xe1" + + "\x82\xce\xa0\xff\x1c\x10\xf2\xa5" + "\x40\x34\x34\x4b\xe5\x36\x6d\x7c" + "\x03\xa3\x74\x0c\x29\x8d\x52\x82" + "\x17\xab\xd4\x04\xc2\xa8\x83\xd0" + "\x0d\x1e\x00\x76\xdd\x4e\xf1\xcf" + "\xc7\x2e\x66\xc9\x02\xc2\x11\xc9" + "\xc6\x78\x02\x81\x98\xfb\x34\xdb" + "\x68\xe3\xe4\x5e\x0e\x25\xb4\xa1" + + "\x47\x13\xfe\x95\x84\xab\xe6\x5e" + "\x3c\x50\x24\x6f\x39\x6c\x0f\xab" + "\x6b\xdd\x86\x44\xfb\x3f\x7e\x80" + "\xf5\xfe\x02\x80\x74\x6c\x0b\xf0" + "\x99\x29\x86\xa7\xa6\xf9\xbf\x48" + "\x26\x9e\xd8\xbe\x6c\xa0\xe5\x85" + "\xeb\x19\x84\x3d\xaf\x11\xd3\x86" + "\x16\x3f\x73\x34\x78\xad\xf3\x24" + + "\xaa\xa2\x6f\x5a\x5e\xee\xac\x9c" + "\x23\xe6\xd4\x75\x83\xd7\x86\x06" + "\x5d\x18\x28\x0b\x0a\x8d\x72\x3f" + "\x6f\xed\x3c\xdd\x60\xb0\x12\x79" + "\x5a\xcc\x14\xf0\xfa\x29\x31\x8d" + "\xea\x5a\x39\xd7\x5c\xde\x1d\x32" + "\xab\xba\x0f\x6b\xd6\xb2\x07\x96" + "\x99\xbd\xaf\x07\xae\x11\x59\xbc" + + "\x44\x0d\x82\x11\x13\x55\x20\x5e" + "\x3a\x47\xc4\x86\xcc\x1b\x65\x0c" + "\xef\x0e\xd8\x9b\x2b\x0c\x23\x1d" + "\xe5\x5b\x51\x07\x12\x4a\x2c\x04" + "\x84\xe2\xe9\xbf\xa0\x7c\x51\x42" + "\x7a\x82\x69\x23\x78\x05\xf6\xe8" + "\x9d\x69\x38\x16\xf0\x04\x4f\x18" + "\x05\x6d\xbc\xf2\xed\x18\x46\x17" + + "\x77\xf1\x1c\x65\xd5\x78\x37\x7c" + "\x0f\xbd\x52\xd8\x55\x55\x68\x1b" + "\xf8\x1f\x46\xf3\x82\xf6\x03\x4a" + "\x7b\xca\x12\x9b\x35\x8c\x09\xc1" + "\x01\x34\x98\x5d\xd2\x53\x05\x6a" + "\xb0\x87\xc6\x3d\x8f\x76\xc0\xe0" + "\x2e\x73\x4b\x34\x3e\xa3\x44\x7c" + "\x02\x0a\xb7\x64\xc3\x71\xb1\x5e" + + "\x87\xd6\x68\x6c\xfc\x03\x3e\x5e" + "\xc7\x52\xf0\x1f\x3d\x2c\x73\x3e" + "\x7a\x6e\xd1\x6e\xa6\xef\xd0\xf2" + "\x46\xb7\x5b\xb6\x26\x2b\xd9\x63" + "\x7c\x86\x44\xdd\xba\x82\xcd\xff" + "\xb8\x81\xc0\xf8\x9e\x4a\x1b\xa7" + "\x85\x87\x6c\x73\xa7\x76\x16\x6c" + "\xd0\x32\x89\x9d\x16\x06\x2c\xbe" + + "\xf2\x39\x09\xb5\x49\x88\x63\xd1" + "\x8e\x85\x90\xba\x2c\x69\x33\xfc" + "\x8e\x00\xa6\x2f\x91\x0a\x4a\x2b" + "\x40\x39\xa3\x97\xc7\x90\x01\xc0" + "\x10\x3c\x2d\xd6\xfd\x14\xff\x8a" + "\xc1\x89\x19\x57\x09\x4d\xc6\x98" + "\xba\xfe\xe5\x00\x28\xea\x24\x82" + "\xc1\xc5\xa9\xf9\x0c\xb9\x3c\x91" + + "\x9f\x1c\xca\x9e\x4b\x1a\xfa\x7b" + "\x35\xe5\xe5\x8c\xdc\xc1\x0b\x96" + "\x0a\xc3\xee\x17\xf3\xd9\x67\xe2" + "\x38\x7d\x25\x6c\xef\x89\xfb\x06" + "\x6d\xa2\x64\xd3\x9a\x99\x28\x23" + "\x58\xab\xea\x26\xcb\x94\xb7\x69" + "\x96\xa5\x5b\xb8\x1f\xab\x28\xad" + "\x94\xaa\xd0\x56\xf3\xbf\xdc\x05" + + "\x02\xa6\xa1\xa3\x80\x9e\xd7\x14" + "\xaf\xd6\xc3\x22\x5e\x18\x4f\xfc" + "\xc8\x67\xf6\xb7\x6b\xa5\x2f\x23" + "\xf8\xea\x3e\x8f\x91\xbc\xd0\x49" + "\x48\xe2\x70\x58\xb9\x51\x91\xe8" + "\xab\x09\x44\x3d\x70\x0e\xab\x70" + "\xe8\x83\x07\x80\x10\xe9\xd8\x22" + "\x62\x77\xac\xa2\xb2\x7b\x2c\x9b" + + "\xc4\xfb\xcf\x2b\x28\x6d\x37\x53" + "\x7a\xdb\xea\x06\xa7\x17\x88\x70" + "\x69\xae\x35\xcd\x05\x0e\xf5\x6f" + "\xde\x7f\xbc\x74\x75\xfb\xb5\x63" + "\xc4\x08\xfe\xe7\x53\xe9\xc9\x71" + "\x18\xca\x83\xf5\xd4\xbf\xd8\xb4" + "\x5c\x1c\xe8\x45\x82\x78\x8d\xde" + "\x38\x41\x47\xe0\x3c\xe9\xf5\xa5" + + "\x32\x19\x83\xf0\x4b\x5f\xd7\xd4" + "\xc9\x8c\xfe\x77\xc4\x0a\x77\x5e" + "\xa2\x72\x2e\x86\x48\xe7\xb5\x52" + "\xfe\x35\x1d\x50\x82\x54\xa4\xe9" + "\x87\xb1\x9a\x4a\x42\xe7\x93\x8a" + "\x17\xa0\x8c\xe8\x6d\x50\x72\x5a" + "\xef\x2d\xeb\x01\xb2\xdc\x80\xe6" + "\x9d\x20\x68\xba\xe6\xa4\x5a\xdc" + + "\x31\x9f\x3c\x29\x0f\x16\x6c\x42" + "\xa7\xd7\x64\xe8\x33\x63\xb5\x8e" + "\x30\xba\xbb\x3e\x02\x64\x11\xbe" + "\x02\xa3\xd5\x2f\xe3\xba\xc2\x64" + "\x7b\xff\x5a\x26\xe1\x01\x06\x80" + "\x14\x4b\xfd\x66\x80\xa8\xd8\x52" + "\x9c\x5a\x07\x46\xe7\x20\xba\x5a" + "\xc6\x34\x12\x7e\xf8\x2b\xa3\xda" + + "\xc8\x2f\x56\xc4\xa5\x97\x74\x45" + "\xf8\xbf\xe2\xf3\x8a\x8e\xfd\x44" + "\x59\x7d\xc9\x49\x35\x49\x23\x19" + "\xe4\xbb\x36\x40\x56\x07\xe3\xda" + "\xed\xa0\xad\x49\x51\x78\x37\xf1" + "\xaa\x87\xef\x80\xc5\x62\xd3\xc6" + "\x6a\x5c\xa5\x30\x12\x43\x97\xc5" + "\x37\x5a\xec\x15\xe5\x07\x84\x56" + + "\xe0\xb7\x4d\x69\xef\xbd\xf9\x80" + "\xc6\xdd\xfc\xb9\x87\x87\xca\xed" + "\xe1\xdc\xb8\x03\x34\x1c\x98\x51" + "\xa1\x0b\xe1\x70\xf1\xdc\x74\x42" + "\x1a\x6d\xef\x6d\xb8\x43\x27\xf7" + "\x66\x18\xdb\xeb\x70\x16\x5b\xd2" + "\x58\x6f\x0c\x05\x8c\x1e\x49\xc4" + "\xf5\xd7\xfb\x87\xab\xb2\xe2\x2b" + + + "\xec\xf8\x11\xd1\x9d\x5c\x0e\x3e" + "\x60\xe7\xc4\xb7\x8d\x3f\xc3\xbc" + "\x51\x2a\x39\xbd\x91\x9a\x2f\x70" + "\x2d\xe9\x32\xc1\x95\xa7\xa4\x7d" + "\x1b\x15\xb1\x0b\xe3\x0a\x0b\x1a" + "\x51\x22\xe3\x02\xc8\xba\xfe\x54" + "\x78\x9e\x4e\x69\x82\x50\x3a\xea" + "\xb8\x40\xfe\xe4\xc1\xfe\x8f\xe5" + + "\x0b\x12\xc4\x29\x9d\x34\xb8\xfb" + "\x15\xd9\xd0\xc0\x1f\x39\x94\x9f" + "\x51\xba\x10\x54\xa7\x4f\x07\xc4" + "\x11\x59\x0a\x15\xf6\xdb\x6a\xa6" + "\x38\xca\xbf\x34\x3c\x54\x64\xc1" + "\xfc\xcc\xe1\xb9\x60\x75\xf2\xe0" + "\x9c\x21\x20\xe8\x53\x0f\xda\x99" + "\x7a\x99\xb4\xc6\x98\x44\x23\xe8" + + "\xe4\x19\x6e\x51\x13\xc5\x23\x7b" + "\x93\xd5\xc4\xc5\x47\xe8\xe2\x56" + "\xf6\x1e\xe7\x5c\x73\x7d\x72\x9f" + "\xc5\x44\x9a\xf7\xa6\x04\x63\x5b" + "\x33\xe4\xb7\x3a\x36\xa7\x38\x66" + "\x83\x2f\x74\xfe\x70\xa4\xde\x1a" + "\x9f\xc1\x7f\x5b\x54\xb8\x54\xe0" + "\x98\x06\x1d\xba\x1a\x38\x35\xf9" + + "\x36\x49\x8e\x91\x9d\x4f\x50\xb5" + "\x82\x39\x51\xb2\xf6\x5e\x03\x65" + "\xb9\x9c\x4d\x6f\xc2\xa0\x53\x05" + "\x09\x55\xa8\xbe\x56\x0d\xb1\x6c" + "\x11\xda\x42\xa2\xb7\x57\xd9\x48" + "\x68\x72\x2b\x67\xdd\xd3\xa4\x16" + "\x6b\xa9\x02\x85\x7c\x63\x7e\x3d" + "\x3b\x46\x0d\x73\x2b\x03\xc7\x27" + + "\x6f\x42\x46\x58\x7d\x6b\x36\x55" + "\x1d\x44\x7d\x24\x89\x9e\xd0\xe7" + "\x48\xbf\x6f\x73\x4d\x40\x0b\x51" + "\x7d\xbd\x84\xe7\xd0\x03\xa0\x7f" + "\x96\x95\xfd\x17\x4f\x61\xf7\x25" + "\xdb\x98\xcb\x35\xa1\xe0\xe0\x49" + "\x6a\xa7\x83\x2e\x7b\x95\x65\x2c" + "\xf8\xe0\xdb\xcd\x8d\xda\x40\x5d" + + "\x9d\x93\x95\xa5\xb4\x8b\xf6\x37" + "\x17\x02\x74\x28\x79\x64\x55\x03" + "\x12\x76\xad\x84\x7c\x0e\x74\x8e" + "\x5f\x69\x44\x90\x43\xc8\x9b\xd8" + "\x4d\x18\xa9\x85\x5d\xda\xf3\xf7" + "\x74\xb0\xc0\x9f\xbb\x63\x25\x56" + "\x8e\x88\x8a\xf8\xaa\xe6\xd2\x06" + "\x7c\xbe\x1f\x16\x43\x86\x2d\x61" + + "\xb2\x0b\x53\x54\xa3\xbb\xb3\x9f" + "\xea\x69\x08\xcb\x77\xef\xe3\xbd" + "\x63\x11\x43\x0b\x46\x90\xbc\x89" + "\x35\x9a\x81\xe4\xd2\xd7\x03\x4d" + "\x82\xa7\xb6\x43\x9e\x4f\xae\x33" + "\x86\xa6\x88\x9c\x07\xb3\x6d\x21" + "\xd9\xed\xff\x00\xe0\x88\xdd\x91" + "\x40\x48\xbd\x12\x9f\xda\x80\xb2" + + "\xd7\x8c\x53\x3e\x91\x86\x8f\x45" + "\x53\xad\x08\x8e\x6c\x1f\x00\xa7" + "\xff\x15\x5d\xbf\xe6\xc6\xb8\x52" + "\xdd\x15\x12\x01\xa4\x34\x82\x54" + "\x45\x40\x5b\x3d\x2d\x9d\x5a\xff" + "\x90\x41\x90\x4a\xb6\xee\xff\xb0" + "\x8b\x7f\x60\x48\xa4\xac\xa3\x55" + "\x2a\x67\xa0\x30\x5c\x66\xbd\x8c" + + "\x37\x59\x7f\xf3\x73\x35\x7f\xa3" + "\xa5\xfc\xe4\xd1\x7d\x6c\x0f\xeb" + "\xfc\xb0\x8a\xac\x54\xa5\x65\x29" + "\xac\x76\x46\x27\x6c\xf5\xfb\x17" + "\x20\xd7\xf7\xac\xd9\x6b\x2f\x2e" + "\x66\x47\x22\x10\x88\x8f\xfc\x41" + "\xef\x3b\xd5\x85\xb3\x14\x7a\x51" + "\xd1\xa7\x76\x7d\xa5\x27\xe3\xda" + + "\xdc\x82\x5f\x1f\x89\x5c\x5d\x51" + "\x9e\x07\x61\x63\xd7\x67\x7f\x9a" + "\x30\x53\xa3\x11\xe3\x81\xda\xa8" + "\x1b\xbe\x18\x4b\xc4\x90\x49\xe4" + "\x59\x3e\x10\xaf\x95\xed\xd5\xc7" + "\x61\x92\xac\x8d\xa7\xab\xe8\xec" + "\xd3\xb8\x94\x93\x99\xb0\x82\xbe" + "\x83\xfe\xad\x16\x9a\xf0\x30\x68" + + "\xb1\xd9\xd7\x94\xc1\x1a\xc4\x43" + "\x17\x7f\x2e\xc8\x82\xdd\xaf\x5b" + "\xca\x0f\xda\x5f\xc1\x14\x06\xdf" + "\xad\x37\xae\xa8\xa7\x43\xb0\x74" + "\x4c\x73\x71\x9e\xa1\xaf\xa6\x3b" + "\x2e\x0f\x45\x9c\x7e\x43\xd5\x15" + "\xb1\x42\xe2\x67\xfe\x83\x58\x4a" + "\xc2\x53\x19\x2c\xc2\xbd\x43\x51" + + "\xf9\xf5\x53\x6b\x7c\xce\xa9\xa2" + "\x99\x6d\x17\x1b\x95\x65\x24\x64" + "\x1b\x08\x5c\xb9\x36\x8d\x29\xb1" + "\xe6\x9e\x9a\x1d\xb8\x5b\x50\x53" + "\xb0\x70\xba\xf2\x61\x9e\x6f\x3f" + "\x53\xd4\xfa\x8a\xc9\x16\x7e\xd0" + "\x6a\x4a\xeb\xe7\xbb\x94\x16\x9f" + "\x8e\xbc\xb0\x3c\xd9\xce\xeb\xdf" + + "\x0b\x39\xf3\xb1\xf2\xd7\x76\xc6" + "\x72\x12\xb6\xa5\x8c\x1b\x7a\x9f" + "\xa9\x27\xe1\xc2\xc9\xbf\xbe\x4e" + "\xbf\x97\xd9\x5d\x0c\x50\x02\x46" + "\x0f\x23\x11\x47\x1c\x77\x09\x7f" + "\xc1\x09\x0f\x02\x7c\xb3\x8e\x05" + "\x8b\xe3\xe5\xfe\x4b\x3d\x69\xab" + "\xc0\xcb\x53\x46\x1f\xeb\x89\x92" + + "\xa7\xf5\x70\x17\x39\x2b\x4d\xa4" + "\x82\xeb\x44\x0e\x91\xd7\xd4\xe4" + "\x2a\x71\x69\x3f\x1e\x9d\xe6\x42" + "\x0e\x82\x6a\xac\xd6\xc4\x11\xbf" + "\x4c\x22\xc4\x42\xe5\xf3\xe7\xb5" + "\x1c\x94\x9d\x44\x1c\xe8\xb4\xd6" + "\x78\xe8\x50\x54\x16\xbd\x72\x5d" + "\x54\xac\x25\xee\x8a\xe2\x61\x6a" + + "\x78\x25\x95\xab\xc7\x9d\xda\x54" + "\x0b\x4d\xe8\x26\xf2\x3d\x42\xb5" + "\x42\x20\x87\x9b\xeb\x4e\xb6\xa8" + "\xdf\xf6\x90\x59\x82\x57\x20\xac" + "\x7a\xc7\xf4\x21\xeb\x96\xf6\x4f" + "\xaf\x73\xb2\xaa\xe4\xc3\x79\x1a" + "\xf1\xb3\x36\x94\x2e\x92\xbc\x29" + "\x7a\xa2\xd9\xd6\xf8\x7e\x80\xff" + + "\x6c\x74\xf6\x33\xf8\xa8\xf3\xc7" + "\xca\x90\xa9\xfe\x65\x6f\xe4\x21" + "\xa9\xb0\xdd\xca\xc5\xd5\x5f\x91" + "\x55\x45\x61\x78\x16\xf0\x41\xbd" + "\x58\xfb\x6f\x42\x34\x44\x6f\x34" + "\x04\xc2\xdb\x14\x36\x94\x55\x80" + "\x7f\x9b\x96\x5a\xfe\x20\xdd\xf3" + "\x9a\xa3\x99\xe8\x56\xe9\x59\x9d" + + "\xc0\x56\x6f\xd0\x8f\x68\xca\xe4" + "\x72\x79\x02\xdf\x0d\xf7\x8a\xa4" + "\x9d\x60\x9a\x5e\x04\x0f\x1f\x69" + "\x0e\x27\x61\xee\xcd\x82\xdd\xa9" + "\xd3\x18\xef\xa0\x63\xca\x03\x89" + "\xbd\xa3\x6c\x3d\x35\xee\xb7\x9f" + "\x03\x7d\xf4\xab\x9c\xa0\xb4\xa7" + "\x8e\xde\x67\x1c\x01\xda\xda\x4c" + + "\x92\x15\x92\x74\x37\x56\xa0\xf9" + "\x31\x9d\xbb\xb9\x1d\x26\xf1\xb4" + "\x59\x54\x9c\x4e\xb7\x29\x14\x55" + "\x53\x1f\xa7\x6e\x6f\x2e\x18\xbe" + "\x73\x05\xc5\xdf\x7c\xb0\xa3\xd3" + "\x44\x8d\xbe\x62\xda\xaf\xa1\x9b" + "\xd3\x65\xab\x52\xcb\xd2\xcf\x9b" + "\x02\x18\x57\xa9\x47\xd5\x11\xdf" + + "\x75\xa6\x38\xe0\xc1\x7d\x12\xac" + "\x20\x63\x5c\x8c\xf3\xef\x9d\x72" + "\x53\x2c\x0d\xa9\xd4\x8f\xdf\xb7" + "\xd3\x7c\x1e\x68\xec\xb0\x74\x9b" + "\xe5\x07\xb4\xda\x23\xa6\xb5\x5c" + "\xc6\x40\xb3\x76\x15\x36\xbd\xcd" + "\x2c\x39\x28\x7d\x5a\x41\x84\xa1" + "\x30\x78\x6f\xe9\xd8\xc1\x84\xc1" + + "\x61\xfc\x43\x5e\x84\xb6\x89\xb1" + "\x57\xab\xd3\xe0\x75\x23\x28\xf3" + "\xa8\x1d\x18\xb1\x67\x4b\xa3\x4f" + "\xb8\x52\xee\x99\xb2\xd0\x1e\x62" + "\x76\x06\x99\xad\xe1\x8d\x17\x9b" + "\x65\x40\xd5\x56\x7b\xe6\x1d\xd5" + "\x01\xc2\x38\x75\xc4\x27\x2c\x2a" + "\x5c\x0f\xa4\x38\xc8\x6e\x85\x33" + + "\xc3\x85\x7e\x2f\x3b\x30\xa9\x86" + "\x9b\x8f\x98\x71\x21\x46\xce\x5f" + "\xb5\xac\x38\xc1\xf6\x5b\x93\x5b" + "\x12\x12\x66\x25\x67\x7d\xea\x30" + "\xa2\xb9\x1a\xe5\xf4\xb5\x1e\xef" + "\x78\x7c\x06\xae\x8a\xc9\x87\x05" + "\xa6\x9c\xca\x77\x3c\x1b\xce\xb3" + "\x57\xf0\xb5\x54\x4d\x3d\x55\x2a" + + "\x3d\xab\x21\xcd\xb2\x68\xe4\x89" + "\x92\xd3\x93\xc3\x22\xf0\x04\xe5" + "\xf9\x3a\x01\xa5\xd4\xe1\x21\xab" + "\xcb\x8a\xc2\xc2\x78\x3f\x28\xe3" + "\x9f\xf9\x6b\x22\xf6\x35\x8b\xf3" + "\x69\x1e\x29\x0e\x74\x42\x35\xe8" + "\x2d\x16\x0c\xb2\x15\x3a\x67\x61" + "\xbe\xbd\x4f\xb0\x75\xdc\x01\xc1" + + "\xa0\x94\x18\x0b\xe1\x56\x71\x2c" + "\xc0\x68\x1c\xd8\x01\x40\x03\x92" + "\xb5\x15\xb1\xc8\x00\x5d\x22\xed" + "\xf2\x07\xb9\x83\x22\x9c\x7f\x23" + "\xc0\xe2\x70\x44\x2f\xf3\xa2\x0e" + "\x95\x4e\xbe\x58\xc1\xf7\x25\xb7" + "\x63\x54\xae\xb1\xfa\xca\x1d\x0f" + "\x04\xfc\xa2\x1b\x87\x51\xed\x59" + + "\x57\xd6\xdd\x06\xe2\xbe\xdb\x35" + "\x6d\xa9\xf3\x2f\x11\xdd\xcb\xe7" + "\x58\xe7\x6b\x07\x68\x19\x38\x88" + "\x5d\x1f\xc9\x08\x72\x7e\x73\x2d" + "\x76\x37\xec\x86\x62\xab\x83\x5f" + "\xa1\xa7\x5f\x94\x9d\x64\xaa\x98" + "\x33\x09\xef\x72\x37\xec\x77\xf4" + "\xb1\x17\x8c\x09\x1e\x2b\xf5\x66" + + "\x11\x07\x52\xc9\xde\xcc\xb0\xd1" + "\xbf\x84\x8b\x3c\xed\xe4\xa9\x55" + "\x14\xf3\xfe\xa1\x39\xbd\x26\x94" + "\x2b\x3f\xb9\x6e\x8e\x63\x5f\x4f" + "\x1b\x34\xf9\x2b\xd3\x1e\x2a\xba" + "\xa9\xd5\x42\x4d\x21\x13\x3c\xd6" + "\xc5\xc7\x6d\x31\x89\x4a\x96\xd2" + "\x51\x18\x51\xca\x06\x96\x75\xd1" + + "\xbd\x7b\xe5\xcf\x0e\xc1\x2e\xb1" + "\xb5\xc2\xa0\x35\x56\xb6\xc7\x82" + "\xbd\x67\x1c\x16\xcd\xd5\xc7\xdd" + "\xcc\x32\x3a\xae\x85\x89\x2e\xe3" + "\x29\x55\x1a\xd1\x44\x94\xba\x7a" + "\x1a\xfa\x27\x24\x02\xed\x64\xe9" + "\x0a\x77\xa1\x24\x2d\x39\x28\x15" + "\xcd\x2f\xc7\x12\x2c\xce\x52\xa1" + + "\x87\x11\xc5\xf8\xea\x9f\xf6\xed" + "\xa7\x4d\x1e\x74\xec\x67\xbb\x05" + "\x45\x43\x11\x08\x32\x0f\xdf\x47" + "\xb1\x92\x97\xbb\x07\xcb\xfa\x56" + "\xe4\x29\x62\x8f\xe9\x07\xe0\xf3" + "\x0f\xba\x6f\x52\xf4\x03\xd1\x62" + "\x79\x9d\x33\xb0\xf7\xbe\x33\x4f" + "\xc1\xfe\x9b\xb5\x7b\x35\x41\x98" + + "\xba\xf5\x8e\xe2\x67\x0b\x1e\xae" + "\x69\xe1\x18\xcb\x99\x46\x9a\x2c" + "\x20\xbd\x6b\x1e\x33\x0e\xcd\x0e" + "\xd2\x81\x5e\xaf\x0e\x36\x1b\x57" + "\x45\x1d\x1c\x10\x58\xea\x9f\xcd" + "\x52\x04\x88\x18\x8e\x78\x51\x66" + "\x46\xd4\x8d\x1f\x35\x26\x97\xa9" + "\xd0\x81\x72\xe3\x22\xd0\xbe\x44" + + "\x1f\xac\xdb\x60\xea\x6e\x0e\x83" + "\xf7\xa2\x06\xda\x84\xc4\xd8\x23" + "\x5b\x53\xca\x50\xb0\x14\x67\x89" + "\x9b\x7a\xd9\xeb\x44\x36\x8d\xdc" + "\xb4\x77\x21\xb1\xfa\xf9\x6e\x10" + "\x9c\x5d\x4d\x53\x64\xf4\x9b\xf7" + "\x0b\x36\xab\xa6\x49\xa3\x37\x25" + "\x4f\x74\x0c\xa0\x53\x42\xc5\xc7" + + "\xd4\x69\xcf\xfa\xe5\x2d\xf8\xf0" + "\x4c\x34\x75\x47\x76\x7e\x3b\x36" + "\x04\x6d\xe3\xb2\x12\xf3\x94\x68" + "\xa5\xc9\xd1\x11\xfe\xb4\x6c\x3c" + "\xf2\xe1\x08\x40\x39\xc3\xd9\x85" + "\x6c\x32\x9f\x24\xea\x85\x9a\x5e" + "\x06\x5e\x8c\x67\x0a\xc6\x35\xdc" + "\xa9\xfb\x86\x9f\x4f\x94\x8b\xc0" + + "\xb0\x4a\x75\x68\xd1\x61\xd6\x24" + "\x76\x9a\x42\x6f\x1d\xce\x1f\x80" + "\x69\xe7\x8c\xa5\x5f\xa8\x68\xc0" + "\x2b\xca\x5e\x5d\x54\x5c\xc3\xed" + "\xd1\x60\xf6\xa3\x6f\x27\x31\xea" + "\x67\x71\xfc\xb8\xbe\x4e\x18\xa0" + "\xae\xb0\x8d\x1d\x1a\xf2\x20\x0f" + "\x12\x5e\xc3\x56\x5f\x09\x6d\xd9" + + "\x5f\xaa\x33\xb7\xa9\x0b\x2f\x3c" + "\x35\xf2\x5a\xf0\xcb\x47\xce\xde" + "\xa5\x82\xac\xa2\x15\xf7\xe3\xf8" + "\x8a\xf1\x03\x22\x41\xa6\x7b\xc9" + "\x60\x10\xc1\x09\x04\x55\xaf\xc3" + "\x2d\x51\xaf\x46\x05\x2c\xea\x56" + "\x46\x81\xf2\xf3\xaf\x8d\xc2\xfa" + "\x94\xf4\x9e\x95\x3a\xb4\xfa\x87" + + + "\x5f\x10\xc5\xd4\x41\x16\x89\x09" + "\x65\xbd\x7f\x6d\x8e\x0f\xe8\x1a" + "\xb0\xbd\xe6\xbe\x5f\x22\x67\x9d" + "\x60\xd8\xc4\x7f\x59\x3b\x43\x3b" + "\x38\x56\xe8\x93\xb6\x6d\xe6\x44" + "\x2f\x86\xe9\xe3\x52\x92\xb5\xf7" + "\xec\x32\x5c\x66\x57\x51\x78\xdb" + "\x50\x2f\x36\xae\xd7\xef\x2f\x70" + + "\xc3\xb0\xef\x0f\x5d\x47\x54\x37" + "\x5d\xc3\xd7\x46\x6b\xb5\x8f\xd4" + "\xa4\x98\x37\x36\x33\xb6\x70\xa0" + "\xe6\x98\xdb\x8f\xd2\xf3\x89\xae" + "\x4c\xd1\x63\x63\xc8\x89\x0b\x97" + "\x7d\xd2\xab\x67\x21\x75\x81\x89" + "\x21\xa0\xd5\x44\x74\xd4\xf7\x9b" + "\xee\x2a\xc7\xca\xaf\x3b\x08\xb3" + + "\x44\x9a\x94\xbe\xde\x41\x97\x38" + "\xa5\x4f\x6a\x54\x88\x93\x8e\x63" + "\xdc\x7b\x04\xa0\x9c\x41\xe6\x3f" + "\xca\x57\xea\xaa\x48\xf6\x47\x70" + "\x17\xab\xfb\x41\x90\x8a\xe4\x54" + "\xa2\xdb\x6b\x57\x28\x0b\x8e\xda" + "\xdc\xfd\x2a\xc7\xbc\xee\x07\xe8" + "\xbf\x77\x25\xf4\x6d\x33\xd3\x07" + + "\x25\x09\xe2\xbf\x44\xc2\xa8\x62" + "\x67\xe8\xdc\x8f\xc3\x9a\xc1\x91" + "\x63\x70\x38\xdd\xd5\xa5\x96\x5a" + "\xf6\x24\xd3\x21\xd4\x87\xd5\x61" + "\xea\x73\x71\xa3\xa2\x73\x76\xe8" + "\x65\x8b\x77\x53\x08\x80\x84\x23" + "\x3e\xb4\xba\x05\x1e\x44\xf8\x10" + "\xbe\xef\x21\x46\x12\xfe\x11\xfa" + + "\x7b\x5d\x68\x81\x2e\x77\x7b\x04" + "\x76\xa9\x34\xbf\x81\x7d\xf2\x23" + "\xef\x48\x5f\x91\xe2\x08\x76\xc2" + "\xc3\xd5\x21\xa5\xfa\x43\x0b\x3b" + "\x84\x72\xca\x63\x26\xfb\x13\x76" + "\x37\xb8\x4d\x1d\xb4\x29\x57\x7f" + "\x6b\x52\x3b\x58\x98\x48\xb1\x87" + "\xd1\xd3\xad\xbb\xa6\x32\xb7\x00" + + "\x96\xe3\x48\x20\x26\xf4\x02\x8e" + "\xe4\x9d\x3d\x38\xb6\x50\x6b\x43" + "\xad\x85\x1e\x47\x81\x34\x8d\xf7" + "\xd6\xc8\x05\xd0\x6a\xea\x01\x8b" + "\x07\x5c\x01\x97\xee\xaf\xc7\xd3" + "\xae\xa2\x3b\x4e\xa9\xf1\xcd\x46" + "\xd2\xa1\xd3\x83\x01\xe5\x42\x7a" + "\xf4\xdf\x41\xb5\x68\x52\x4b\xd5" + + "\xbc\xe9\x23\x4e\x30\xcf\x24\x3f" + "\x24\x36\x6e\x12\x16\xf8\x87\x43" + "\x61\x6d\x0b\x3b\x03\x6a\xa4\x26" + "\x7c\x77\x2d\x8b\x45\xc8\x1b\xaf" + "\x9c\xe7\x7d\x52\xba\x01\xc4\x25" + "\xb6\xbb\x61\x42\xd4\x46\x13\x0e" + "\xc7\x4b\x7b\x28\x4b\xc4\x96\x4b" + "\x2f\x56\x54\x52\xc7\x93\x84\x65" + + "\x20\x4a\xa2\xb8\xfe\x49\xf9\x23" + "\x3f\xa5\x2c\xf5\xd1\xfe\xeb\x17" + "\x53\x48\xfb\xbc\xbe\x1b\x69\x9b" + "\x5d\xa0\x78\x62\x6b\xff\x17\x56" + "\xbd\x9e\xc9\xe3\xc5\x34\x1b\x24" + "\x6a\x15\x84\x17\x2e\x24\x64\xfc" + "\xdf\x67\x5d\x69\x2f\x48\x06\x42" + "\x11\xc0\x27\xee\x0e\xce\x67\xb9" + + "\x5d\x0b\xc8\x21\x51\x37\xdb\x65" + "\xa0\xcc\x1e\xa3\x3c\x56\x7a\x2e" + "\x7e\xa0\x38\x52\x4e\xfc\x6f\xe5" + "\x54\xd8\xce\x32\x66\x29\x6c\x3d" + "\x85\xb8\x70\xaf\x1a\x7d\x9d\xe9" + "\x59\x64\x68\x2d\xd9\xba\xc3\xaf" + "\x5b\xba\xc8\x0c\x46\xbf\x78\x9c" + "\xa3\x5a\x95\x18\x19\x95\x43\x5a" + + "\x14\xe3\xe4\x5f\xa8\x17\xb5\xf8" + "\x6f\x90\xb8\xfc\xd0\x34\x02\xe6" + "\x23\x1b\x06\xf2\xac\x42\xe5\xff" + "\x9c\xb5\x4c\x6b\x1f\x19\x7e\x28" + "\xd8\x77\xd8\x09\xdc\x7d\x85\x21" + "\x41\x89\x67\x14\x8c\x47\x23\x1c" + "\xa4\x5e\xe0\xb6\x56\xc0\xf0\xbb" + "\xfe\x94\x15\xb0\x53\x4b\xda\x82" + + "\x08\x86\xdb\xfa\x91\x67\x52\xf7" + "\xf6\xcd\x74\x7b\x2d\x83\x9e\x04" + "\x34\x0a\xb9\xc2\xcc\x81\x35\xa4" + "\x0c\xb1\x60\x93\xb8\x9e\x63\x73" + "\x1b\xa7\xe4\xe1\x1f\x33\xba\x4f" + "\x19\xf9\x72\x80\x93\x6b\xfd\x6f" + "\x32\x90\x67\x65\x1c\x27\x53\x6e" + "\xce\x72\x42\xf1\x44\x64\x20\x67" + + "\x34\x58\x33\xb2\xa3\x34\xf7\xc0" + "\x60\x68\xef\x90\x5a\x20\x26\x95" + "\x0d\xbb\xe2\x04\x17\xe7\x8b\xcb" + "\xfa\x83\xf3\x02\x1e\x87\x18\x24" + "\x57\xc1\x82\x40\x81\x76\x17\xd7" + "\x73\x00\xc2\x29\xd0\x4a\x91\xcc" + "\x28\xe7\x87\xe5\xeb\xc1\x86\xf1" + "\xfd\xd5\xbc\x61\x22\x3c\xdb\x6f" + + "\xe9\xf8\xf9\xf2\xa6\x14\xd0\x30" + "\xd2\x49\xec\x4f\x23\xce\x3e\x96" + "\xd9\xa8\x05\x96\xc5\x25\x20\x86" + "\x9a\x92\xf8\x19\x45\x44\x87\x39" + "\x6a\x47\xbf\x12\x65\xff\xb6\x01" + "\x91\x7d\xcf\x09\xd8\x64\x8a\x59" + "\xca\x56\xbe\x93\x49\x77\xec\xd7" + "\x15\x36\xb3\xcb\x85\x97\x89\x10" + + "\xad\xe3\xee\x02\xfd\x92\xa0\xb8" + "\x70\x52\x14\x30\x35\x3d\x6b\xa8" + "\x75\xb6\x12\x85\xc6\x98\x3d\x32" + "\x0f\xb4\xeb\x62\x85\xc7\x8b\x4b" + "\xde\x9c\x3f\x41\x54\x1f\x30\x7d" + "\x64\x56\xab\x2b\x4f\xfb\xe4\xa5" + "\x23\xec\xbf\x1c\x2d\x25\x2b\x1d" + "\x0d\x12\x77\xe1\xbb\x76\xd5\xfc" + + "\x34\x1a\x73\x83\x3e\x7d\x42\x04" + "\x8e\x6e\x83\xed\x8e\x02\xb9\x2b" + "\x7c\xca\x12\xb6\xf8\xcf\x6a\xb3" + "\x3a\xc7\xd9\xd3\xef\xe5\x8f\xb8" + "\xb3\x4e\xea\xed\xc6\x6b\x2a\xbe" + "\x77\xec\x8e\x48\x33\x31\xb9\x43" + "\xe1\x06\x71\xb1\x66\xf5\x1f\xf4" + "\x32\xfa\x4e\x65\x72\x91\x9e\x46" + + "\xa3\x3f\xc2\x41\x04\x0f\x48\xb4" + "\x2e\x9a\x98\xc1\xb0\x2e\x71\xb4" + "\xa7\x9c\xa2\x93\x0f\xba\xcb\x3c" + "\x8c\x42\x19\xd6\x14\x5c\x20\x6e" + "\x86\x16\x64\xb3\x57\x79\xdb\x90" + "\x4e\x8b\xac\x45\x1d\x69\x32\x04" + "\x50\x03\x4e\xf6\xac\x59\xa7\x07" + "\x17\x25\x97\x9c\x9c\xd8\x14\x05" + + "\xc3\x7f\xe6\xa8\x7f\x14\x01\x17" + "\xbe\x85\x20\xab\x8b\x0b\x2e\x9e" + "\x57\x4e\x28\xac\x24\x18\x65\xd5" + "\x64\x36\x89\x74\x25\x43\x0d\x89" + "\xa3\x68\x5e\xc5\x6e\x5e\x7c\x8a" + "\x5a\xc8\x39\x43\x0b\xe9\x12\xbf" + "\x55\xb6\x22\xf9\x85\x6b\x84\x31" + "\x00\xd7\xf4\x0b\x4d\xce\x54\x9a" + + "\x95\x42\xa1\xf1\x3a\xe8\xf4\xd7" + "\xf9\xd4\x85\xb2\x5c\x95\x6f\x91" + "\xba\xda\xff\x99\xe0\xb0\x7b\xe5" + "\x52\xd1\xb0\xea\x34\x30\xa4\x28" + "\xf8\xce\xa9\xb8\xa2\xff\x36\x0a" + "\x1a\x05\xec\xb9\x7e\x40\x17\x55" + "\x72\xe6\x68\xea\x96\x60\x79\x9c" + "\xfb\x77\x3c\xfb\xfb\xb5\x3d\x85" + + "\x1a\xa5\x64\xe8\xa9\x4b\x47\x21" + "\x8b\x1b\x8a\x6e\x99\x76\x26\x6c" + "\x28\x0a\x12\x94\x26\x36\x82\x7c" + "\xdb\xa5\x83\x83\x48\x9a\x1e\xe6" + "\x6d\x21\x84\x9f\x03\x50\xd7\x7d" + "\x85\xcd\x43\xad\x07\x0d\x02\xab" + "\x59\xc6\x12\xda\x48\xae\x37\x94" + "\xad\x52\x54\xe6\xeb\xc2\x49\x64" + + "\xc1\xd7\xf9\x2c\x1c\x4c\x7c\xcc" + "\xab\xe5\x95\xee\x6a\x88\x20\x13" + "\x0c\x17\xae\xbe\x56\x90\x7b\xbb" + "\x62\xd6\xc0\xdb\x50\xb2\xa5\xc8" + "\x03\x23\x1d\xc1\x32\x14\xd8\x4e" + "\x9f\x76\x03\x1f\x12\x69\xa6\x7d" + "\x28\x98\x53\x84\xfd\xa5\xc7\x3a" + "\x02\xdd\xcc\x3b\x94\xda\xda\x14" + + "\xd1\xb0\xf6\x7e\x21\xc3\x84\x8b" + "\x22\x3f\x93\x7c\x7a\x47\xa9\x52" + "\x82\x0b\x44\xfd\x8a\x72\xf6\x5e" + "\x5e\xbd\xe4\x6c\x59\xd8\x3b\x5c" + "\x3e\x2d\x2c\xf2\xf5\x80\x8b\x91" + "\xc5\x6c\xbb\xb7\x40\x50\x8d\x36" + "\x1c\xa1\x95\x26\xa1\x42\x61\xb6" + "\x70\xea\x19\xeb\x3a\x58\xac\x60" + + "\x37\x24\xab\x0e\x98\xbb\x7c\x31" + "\xc8\x54\x26\x5e\x55\x8c\xc0\x8c" + "\x7f\x30\xd8\xe6\x20\x65\x2d\xfe" + "\x93\x89\x42\x57\xf3\x47\xf1\xe9" + "\xf1\x6c\xfd\xd2\x14\x7d\x9c\x5f" + "\xb0\xcb\x4f\x2d\x64\xd0\xec\xa3" + "\xf7\x41\x73\x8e\xf0\xfe\x83\xad" + "\x5c\x11\x63\x3a\xa0\x23\x3f\x64" + + "\x43\xb7\x5a\xe6\xab\x78\x8a\xd3" + "\x9c\xc8\xed\x35\xb1\x75\x7c\xbf" + "\x68\xf5\x0d\x53\x2e\x75\xd8\x3d" + "\x82\xc6\x08\xe3\x76\x4a\x5c\xf8" + "\x37\xcf\x8a\xe6\xb2\x55\x99\x4c" + "\x85\xaf\x32\xab\x3d\xdf\x44\xa5" + "\x93\xf4\x5c\xa2\xf5\xc3\x8e\x4b" + "\xeb\x2f\x62\x1a\x64\x27\x8f\x4d" + + "\x49\xbc\xdc\xf0\xaa\xf7\xb4\x7b" + "\x5b\xb4\xbb\x70\xf9\x51\xe5\x7d" + "\xe5\xa2\x2c\x9f\xe4\xf3\xd0\xcf" + "\xef\x76\x5c\x1f\x09\x87\xe5\xec" + "\xae\x79\x7d\x16\xdd\x0e\x92\x32" + "\xc1\x7e\x7d\xfa\xa2\xf8\x9d\x03" + "\x91\xaf\x30\xbb\xc0\x06\x62\xf4" + "\x59\x6b\x67\x22\xf5\xe2\xf5\x1f" + + "\x66\x1d\xa5\x6e\x39\xa0\xf4\x11" + "\x26\x7a\x7d\x80\x45\x14\x6c\x50" + "\x24\x9b\x5a\x75\x05\x57\xda\x60" + "\x9e\x31\x1a\x1f\x32\xcc\xc8\x8f" + "\x7d\xd6\x33\x94\x4d\x2d\x64\x83" + "\x96\xd2\x7d\x6a\x8f\xcb\xa5\x7f" + "\x07\xde\x7b\x9b\xdb\x91\x65\x57" + "\xfb\x16\x97\x41\x25\x3d\x17\x13" + + "\xff\x40\xb3\xd5\x9d\x59\x30\xea" + "\xc5\x76\xfe\xb0\x97\x52\x6b\xfc" + "\xdc\x5a\x8f\xab\xc8\x68\x69\x1c" + "\x8d\x92\x1c\x90\xf5\xc7\x23\xf7" + "\x02\xd4\x73\x97\x21\xc3\x03\x42" + "\x47\xdd\x51\x1b\xa3\x6a\x7c\xdf" + "\x3c\xe2\x2b\x55\x7a\xe3\x49\x3d" + "\x87\x6e\x5a\x0b\xe8\xbe\xfe\x57" + + "\x39\xe7\xd8\x7b\xe4\xbe\xec\xc5" + "\x75\xbf\x63\xae\x94\x49\xd4\x79" + "\x23\x89\xfb\x38\x0f\xd0\x8b\x16" + "\x30\x31\x53\xd0\xe4\x8e\xd4\x75" + "\x33\xdf\x5c\xdb\xaa\x77\x4f\x55" + "\x69\x67\x69\x3c\x96\xe8\x96\x33" + "\x4e\x67\xfd\xd3\xf2\xdb\xdd\x2f" + "\xe5\xe3\xd0\x99\xee\xf6\xb8\xbb" + + "\x70\x2f\xae\xcb\x51\x06\xb9\x51" + "\xeb\xa8\xaa\x93\x05\xbc\xc4\xef" + "\x99\xf4\x1d\xdd\x89\x86\xcd\x8e" + "\xa5\x67\xf3\x22\xa8\x99\xee\x1a" + "\xc5\x74\x82\xae\xb9\x85\xd4\x95" + "\x9c\xb3\x30\x7d\x45\xd4\x14\x6c" + "\x81\xef\xc1\xbc\x0b\xa9\xfe\xba" + "\xed\xa2\x59\xa4\x7a\x31\x5f\x7c" + + "\x27\x42\xf4\x4e\x75\x10\x21\x01" + "\x96\xf4\x20\xdc\x6e\xed\x7b\xa1" + "\xcd\x53\x98\x81\x24\xe4\xdf\x0c" + "\xe7\x2c\x1e\xf7\x98\x32\x79\x13" + "\x7b\x30\xbe\xdb\x78\x30\x1f\x3c" + "\x36\x99\xee\x76\x0e\xc2\xd1\x6d" + "\x20\xaa\x3c\x42\x57\x4b\xee\x23" + "\x0e\x84\xfb\x8e\x3b\x79\xc3\x4a" + + "\xa0\x8c\x1f\xed\xeb\x38\x44\x93" + "\xa2\x25\xbb\x4e\x58\x66\x54\x3e" + "\x6f\x89\x69\xc0\x0e\xaf\x15\xc4" + "\x3d\xa4\x5a\x9a\xb0\xdd\x3e\xc1" + "\xf6\xb8\x9e\xd4\x4f\x20\x04\x7a" + "\x70\x16\x4f\xd7\xfc\xbd\xd5\xd0" + "\x58\x05\xfc\x56\x86\xe2\x97\x36" + "\xde\xba\xce\x01\x71\x73\x20\x10" + + "\x2b\xa8\x47\x06\x90\xe6\x87\x5f" + "\x4f\x05\x40\x8f\xd4\x0e\x8e\x90" + "\x03\x38\x85\x79\xd4\x33\xf6\xa9" + "\x52\xb2\x28\x4a\x9a\x3c\xd1\x8e" + "\x64\x0f\x46\x1f\x76\xf6\x2e\x3e" + "\x36\x63\xd0\x36\x9b\x0b\x93\x53" + "\x9b\x97\xc4\x8f\xac\x73\x70\x34" + "\x97\x55\xcd\x5e\x0e\x0e\x38\x84" + + "\x39\x3c\xfe\xc4\x6b\x2c\xb2\xe3" + "\xdf\xeb\x7b\x6c\x53\x81\x4a\xba" + "\x59\x34\x69\x25\xb7\xb6\x3a\xf2" + "\x11\x2b\x92\x14\x70\x37\xbc\x53" + "\xdb\x60\xfc\x5a\xab\xc8\x45\x46" + "\xa3\xf2\xb9\x20\x55\x23\x02\xaa" + "\x07\xc5\x0f\xce\x4c\x95\xa2\x52" + "\xe7\xc2\xe1\x7c\xbb\x31\x27\x8c" + + + "\x89\xb8\x8f\xe4\xc2\x91\x70\x6a" + "\x06\x9d\x8a\x7b\x13\x2c\x88\x26" + "\xe2\xa0\x82\x1b\x63\x86\x49\xa2" + "\x2d\x15\x18\x35\x36\xd7\x4e\x84" + "\xc7\x27\x6e\xd8\x6f\x47\x2f\x28" + "\xdc\xef\xaf\x04\xca\xda\x4e\xa0" + "\x4d\xe3\x19\x61\xbc\x6e\x25\x8b" + "\x8b\xd7\x87\x07\xe9\x13\xa4\x56" + + "\x50\xbe\x74\x5a\x1d\x06\xee\x82" + "\xf5\x6f\xa1\xde\xc4\x81\x17\xe4" + "\xa2\xc8\xbf\x99\x1e\xc8\xb0\xe0" + "\x2d\x7e\x54\x0b\x69\x4d\x4f\x62" + "\xe4\x9a\xcc\xbd\x5d\x54\x83\x3a" + "\x8e\x1e\x9b\x40\xb6\xdb\x73\x25" + "\x39\x35\xc9\xa6\xc4\x60\x29\x48" + "\x98\x87\xe1\x5a\xad\x59\x10\xf0" + + "\x96\x9d\x55\x4d\x27\x1e\x15\x38" + "\x01\x6c\xdb\xb8\xd3\xc0\x18\x4f" + "\xaf\x21\x99\x6f\x83\xaa\xa3\x49" + "\x29\x60\x04\x8c\x7b\xb2\xea\xdb" + "\x3b\xbf\x40\x70\xaa\x9e\x2b\x24" + "\x91\xb0\x14\x16\xe5\x79\xc4\x39" + "\x5d\xaf\x4b\x0e\x2b\xde\x8e\x33" + "\x45\x39\xa5\xf0\xb7\x92\xb1\x5b" + + "\x5f\x79\x12\x31\x97\x9f\x5c\x71" + "\xe1\x6e\x4e\x98\x37\x44\x24\xe8" + "\xcd\x6b\xb6\xec\x58\x48\xcb\x55" + "\xee\xfb\xaf\xab\x35\x67\x13\x7c" + "\x8e\xc3\xbe\x5d\x95\x15\x66\x54" + "\x53\xd1\x8a\x38\x2c\x78\xc0\x51" + "\x2f\x95\xe0\xc6\x3a\xc5\xa4\x9b" + "\xa8\xdf\x21\x1b\x2a\x78\xe6\x27" + + "\x65\x7f\x5d\xec\x51\xc2\x89\x7d" + "\x87\x40\x39\x90\x16\x56\x8f\x0c" + "\xb3\x1a\x69\xf0\xfc\x1c\x9e\x60" + "\x21\x0b\xb2\xe9\xbf\x00\x03\x2a" + "\xf4\xfa\x14\xb1\xad\x2f\x53\xbf" + "\xd1\xf5\x1b\x52\xb9\xc0\x8f\x32" + "\xde\x36\xfc\x3b\x3c\xf9\x51\xbd" + "\x60\x5f\x4e\x7a\x0e\x05\x89\xd9" + + "\xc2\xdb\xd2\x4e\x3d\x90\x2f\x68" + "\x83\x2d\x3b\x7c\xc8\x59\xba\x0e" + "\x35\x93\x7e\x9c\x4d\xc8\x9d\x8e" + "\xd7\x26\xb2\x0e\xb0\x21\x9b\x5f" + "\xae\x7b\x26\xaf\x94\xd3\x3b\xe3" + "\xae\x15\x2e\xbe\x25\xcc\x86\xaa" + "\x00\xc5\x8e\x6a\x7d\xf6\x0b\x4f" + "\x58\x06\x63\xf9\x44\xaa\x46\x58" + + "\x78\xc2\xe0\xe7\x38\xba\x86\x67" + "\x6f\x2e\x8b\x58\xce\x87\xbf\x09" + "\x3a\xee\x5f\x46\x22\x70\x3b\x72" + "\x94\x23\x68\x64\x14\x41\xb8\x08" + "\x29\x46\xe6\x29\xe0\x2c\xb5\x0e" + "\x43\x8e\xa7\xcc\x8f\x0e\xb6\xad" + "\x91\xa9\x54\xb6\x62\x70\xdd\x20" + "\xe5\x6f\x9a\xc6\x28\xd4\x81\x42" + + "\x15\xbf\xc2\xe2\x40\x97\xb0\xfe" + "\x04\x97\xe9\xa9\x05\x22\x7a\x62" + "\x65\xc5\xfb\xc2\xd0\x73\x8d\xec" + "\xe8\x8d\x0c\xc2\x8f\xed\x3e\x22" + "\x49\x3b\x36\xa8\x83\x25\xe3\x1e" + "\xa6\xb0\xc2\xc9\xb9\x6c\x0b\x1a" + "\x5c\xc8\xdb\x90\xd2\xc3\xf7\x49" + "\xac\xc1\xf4\x1e\x97\xbb\xdf\xa8" + + "\xe1\x2e\x1e\xc0\xa3\x7c\x25\x5c" + "\x61\x69\xc3\x27\x14\x3a\xb4\x1f" + "\x24\xf3\x72\x34\xcb\xa7\x94\xd5" + "\x10\xbe\x0a\x66\x24\xc0\x5e\xc1" + "\xed\x4c\x61\x6b\x49\xd4\x76\xb1" + "\x85\xb8\xdb\x62\x4d\x73\x04\x0b" + "\x87\xb5\xdd\x36\xc6\x53\xb7\x2c" + "\x0c\x34\xcd\x14\xe6\x80\x1c\x9a" + + "\xab\xc2\xc7\x65\x4c\x4d\xb3\xaf" + "\x84\xea\xc5\xe2\xe7\x10\x46\x1d" + "\xb5\x4a\x3c\x97\x1b\x6d\x3f\x89" + "\xc4\xa5\x5b\x94\xe9\xd7\xcd\xa3" + "\xee\x17\x44\x06\x83\x49\x51\x60" + "\x2b\xdf\x6b\xad\x3c\xb2\x59\x14" + "\xc3\x26\xf7\x5c\x41\xc3\xb2\x23" + "\x4a\x35\xd6\x32\x35\x96\x82\x3a" + + "\xcd\xe7\x6f\xc0\x96\x56\xf6\xe9" + "\x15\x3a\xfd\x9a\x57\x30\x06\x51" + "\xed\x60\x53\x18\xa6\xac\xcd\x3d" + "\x2f\x3d\x85\xc1\x3d\x70\x41\x27" + "\xa0\xf1\x33\x1a\x4a\xd8\x8a\xbd" + "\x7c\xb0\x5c\xc3\x8c\x69\x6c\x5f" + "\xb9\xe6\x61\x65\x19\xd1\x2b\x21" + "\xd7\x4f\x7b\x61\x7e\xcd\x49\xf1" + + "\x18\x2c\x19\xab\x1f\x90\x4f\x29" + "\x4f\x16\x30\x70\xfe\xcb\x5f\xec" + "\xa6\x6b\x24\xe2\xb7\xfc\xe2\xe2" + "\x0c\x1a\x1a\x22\xb3\x88\x7c\x1e" + "\xc5\x88\x2d\xc9\x93\xdd\xc7\x72" + "\x59\xfb\x06\x11\x8e\x14\xc2\x41" + "\x14\x0f\xf6\xa0\xf5\xd4\x7d\x54" + "\x31\x0f\x96\x63\xb2\x52\x9b\xed" + + "\xf8\x2b\xe8\x30\xc5\xc9\xe3\x1c" + "\x2a\x77\xbb\x0d\x42\x25\x66\x4d" + "\x14\x72\xc1\xd9\x60\x5a\xe2\x19" + "\x55\xfa\x22\x77\x4c\xf8\xbc\x13" + "\xa7\xf7\x9e\xf8\x0e\xca\x8a\x22" + "\x55\xd4\x3e\xfd\x2f\x4e\xd6\x03" + "\x04\xc9\xe6\xdd\xf5\x90\xc3\xf1" + "\x8a\xe1\x78\x76\xa6\x52\x14\x73" + + "\x58\xb3\xa5\xb0\xeb\x49\x83\x6c" + "\xd6\x2e\x7e\x9e\xc2\xc5\x54\xb1" + "\xdb\x62\xa4\xed\xcf\xec\xd5\xca" + "\x69\x6b\xe6\x2d\xe4\xdb\xd6\xf2" + "\xb2\xe5\x65\x86\xf3\xed\x6a\x42" + "\x23\x57\x7f\x7b\x13\x85\x8a\x48" + "\x86\xb3\xcb\x8b\xb3\x43\xcc\x15" + "\x79\xd8\x91\xd7\xf3\x0a\xad\x27" + + "\xba\x2c\x63\xa0\x61\x6e\x00\x3c" + "\xcd\x5c\xb3\x45\x48\x92\x0d\x92" + "\x65\x7f\x5c\x7c\xfb\x79\x33\x4b" + "\x0b\x05\x5e\xb0\x10\xdf\x6c\x52" + "\xae\xf1\x1b\xd2\x36\xe9\x88\x31" + "\x2f\xbd\x4b\x62\x39\x7b\xe0\xb3" + "\x41\xa5\x67\x13\xf3\xfc\x9b\x7b" + "\x27\x79\x36\x8a\xc8\x8e\x9f\x03" + + "\x4f\x36\x6e\x84\x6e\x23\x6c\xc1" + "\xa0\x0c\xa5\xde\x7c\x52\x33\x7f" + "\x6d\xb8\x26\x09\x75\x07\x81\xc4" + "\x0c\xe7\x98\x05\x09\x36\x2a\x6c" + "\x24\xe9\x24\xf0\x52\x5e\x75\xa6" + "\xca\xaf\xb4\x9d\xa4\x07\xfa\xe0" + "\x90\x17\x83\x66\x7d\xce\xc3\x15" + "\xd6\xb0\xcb\xa6\x50\xf3\x4e\x5b" + + "\xf4\x82\x69\x43\xe0\x04\x85\x34" + "\x79\xec\xe3\xd8\xee\x05\x49\xc9" + "\x9e\x17\x09\x35\xcb\xfd\x2c\xb9" + "\x14\xd9\xe6\xf9\xd0\x66\x52\x24" + "\x55\x69\x31\xad\xd0\x50\xaa\x8b" + "\x60\x7f\x22\xca\x79\x5c\x23\x77" + "\xd8\xf9\xe5\x51\xc9\x27\xc9\xf2" + "\x0f\x94\x79\xe6\x30\x8c\xbf\xeb" + + "\x69\x59\x20\xb6\xc4\xaf\x4a\x2c" + "\x4f\x85\xc7\xf6\x02\x3f\x56\x42" + "\x48\x3b\x98\x1d\xd5\xce\x6a\x01" + "\x55\x97\x94\x99\xd8\x56\xb3\xfe" + "\xd7\x9b\xa3\xd1\x81\x2c\x2a\x8c" + "\xe9\x4a\x93\xe6\x0f\x34\x44\x8f" + "\xda\x04\x79\x44\x1c\xf9\x8c\x14" + "\x26\xa9\x51\x0f\x5f\x18\x40\x73" + + "\x90\x69\xac\xce\x66\x5f\xe9\xe4" + "\xce\x16\x6c\xbe\x16\x1d\xdc\x17" + "\xbe\x0c\xad\x45\x55\xa0\x67\x29" + "\xb6\x7e\x6f\x71\x97\x2f\x0e\xdd" + "\x91\x3b\xc3\x2d\xf3\x7f\x8b\x33" + "\xde\x76\xe9\x2f\xf5\xae\xf6\xdc" + "\x6e\x3f\x19\x43\x1c\xf7\x1c\xf5" + "\xe3\x77\xc0\xe8\xc4\x44\xe4\x15" + + "\x46\xab\x09\x74\xfb\x00\x8f\x2f" + "\xb2\x89\xe2\x80\xe6\x78\x7e\x05" + "\xd1\xe5\x88\xa8\x2c\x02\xe5\x03" + "\xe2\xe4\xed\x9d\x1a\x11\x87\x3c" + "\x0b\x46\x09\x78\x1c\x0e\x9b\x5b" + "\xc7\xab\xc9\x71\x52\xc8\x51\xe7" + "\xc9\x1d\xcc\xc7\x28\x4e\x94\x8b" + "\x08\xfa\x3c\x1d\xfa\x1f\x20\x4f" + + "\x49\xc0\x9f\x0f\x2d\xfe\x78\x60" + "\x1a\xd1\xf6\x40\x50\x97\x9d\xd9" + "\xb7\xc0\x54\x08\x97\x9a\xae\x87" + "\x79\xfb\x02\x93\x9c\xb0\xce\xf4" + "\x3f\xa8\x32\x2c\x68\x01\x2f\x50" + "\x24\x50\x68\xb1\x71\x27\x35\x1e" + "\x19\x2b\x79\x66\xf2\xf6\x0d\x97" + "\xfd\x87\x8d\x9c\xbb\xd0\x07\xf5" + + "\xce\x21\x67\x3e\x5c\x90\xfc\x02" + "\x4c\x67\xb3\xd0\xda\x70\x2d\xd5" + "\xa4\x0d\x81\x18\xca\xe5\xc2\x5d" + "\x99\xdd\x69\x5c\x73\xb2\x84\xa9" + "\xa4\x5c\xde\x84\x27\x25\xb9\x63" + "\xc4\xde\x52\xc8\x72\x98\x1c\x2f" + "\x09\xde\xe3\xc2\x93\x35\xb0\x18" + "\x2f\xdc\x13\x98\x01\x0b\xd7\x19" + + "\xb2\x38\x63\x42\xce\x40\x4e\x15" + "\xc9\x88\xaa\x96\x00\xb0\x2c\x7b" + "\x25\xf9\x51\xad\xfc\x01\xc9\xd5" + "\x10\xee\xd0\x7e\x6c\x21\xbd\x5a" + "\x64\xe1\x7d\xf8\x57\xd5\xc3\x73" + "\x6d\x51\x39\xe1\xdc\xd1\x3a\x69" + "\x7a\x54\xbd\x3e\x3a\x7b\x76\xb4" + "\x82\xa9\xf4\x20\x4c\xc2\xb3\xb8" + + "\x29\x1d\xdc\xa6\x2d\x6b\x80\x42" + "\x44\xe1\x71\xf8\x09\x00\x03\xd3" + "\x76\x92\xf4\xaa\x33\xb3\xfe\xa1" + "\x4b\xc0\x0b\xc7\x9e\x3b\x58\xb5" + "\x20\x5f\x69\x95\x78\xbe\xb0\x1d" + "\xb5\x12\xd0\x89\x11\x18\x84\xfc" + "\x43\x16\xf6\x05\x72\xf2\x09\x64" + "\x28\x31\x88\xd5\x74\x41\xd3\x40" + + "\x7b\x7c\x56\x08\xcd\xa0\xfb\x64" + "\x54\xfb\xcb\xa2\x0d\x59\xea\xc9" + "\x73\x0d\x6d\x13\x16\x77\x6f\x66" + "\x0d\xa3\xf2\x38\x48\x96\xa0\x2c" + "\xa9\x0c\x4e\x0f\x24\x45\xa5\x7f" + "\x4b\xb8\xbe\xc1\xa8\x01\x33\xef" + "\x2a\xb9\x62\xbc\x0e\x93\xcb\x45" + "\xea\xcb\xb6\x9b\x05\xc7\x4a\x96" + + "\x33\x98\x41\x67\xf5\x96\x91\xd7" + "\x08\x7b\x3b\x86\x52\xe2\x59\x60" + "\x0c\x70\x56\x1c\x17\x18\xda\x84" + "\xc4\x3e\x8d\xb2\x56\xee\x58\x57" + "\xa6\x0e\x3b\x01\x1d\x77\xa2\x7d" + "\xb9\xe9\xc5\x54\x4b\x52\xdf\xfd" + "\x80\x5d\x30\x24\xf8\xfa\xf4\x7d" + "\x3f\x76\x97\x3a\xbf\xc1\xf5\x58" + + "\x1f\x26\xf5\x81\xcc\x71\xf6\xea" + "\xef\x83\xfe\xbc\x06\x35\x08\x7d" + "\x6e\x53\x88\x31\x0b\xc5\xcd\x94" + "\xcd\x3e\xdd\x24\x41\x2c\x0b\x41" + "\x0c\x52\x05\x02\xcc\x99\xcb\x57" + "\x6d\x44\x06\x5f\x68\xa2\xf3\x23" + "\x17\x4b\xa0\x49\x43\x7e\xb2\xb2" + "\x12\x5a\x78\x81\xf3\x66\xb2\xab" + + "\x42\x60\x69\x7c\xf1\x37\xaf\xa5" + "\xde\x38\x25\x4a\x2c\xa2\xcb\xd4" + "\x00\x26\xa4\x9e\x95\xb9\x1c\x21" + "\x89\x98\x06\x7b\x41\x5f\x10\xcd" + "\x74\x1e\xb8\xdd\x19\xcf\xe1\xb1" + "\xca\xb8\x57\x51\x89\x2d\x2f\x47" + "\x85\xb8\x9d\xee\x08\xb0\x6f\x08" + "\x31\xd1\x26\x0f\x70\xd5\x5c\x36" + + "\x5a\xfe\xb7\x66\x5d\xba\xa7\x00" + "\x56\x5d\xfd\x05\xac\x74\x86\x81" + "\x57\x5a\x14\x04\x3c\xb0\x8f\x68" + "\x2c\x83\xd5\x97\x88\x65\xc1\x76" + "\xa7\xab\x45\x12\xd8\xdc\xf0\xa0" + "\xe9\xf6\x47\x18\xaa\x7c\x07\xdd" + "\xd0\xad\x34\x0d\x14\x53\x03\xf9" + "\xed\x3d\xb7\x48\x11\x7c\xe3\x22" + + "\x53\x70\xbe\xa2\xbb\x02\x4b\x28" + "\xd6\xa6\xb9\x7a\xc6\xf7\xbb\xdc" + "\x30\xa5\xf7\x20\x9c\x55\x25\x44" + "\xc8\x67\x87\x18\xfa\x2d\x1f\x96" + "\xc4\x80\xdc\x70\x35\x94\xfd\xe2" + "\x20\x41\x78\xf0\x63\x6b\x4d\x10" + "\x22\x71\x56\x53\xc1\x2b\x59\x7f" + "\x77\xad\x88\xf6\x46\x12\xbc\xf6" + + "\x06\xb0\x0a\xb7\x6b\x43\xfe\xfd" + "\x1d\x1a\x99\x18\x19\xd1\xe7\x57" + "\xb0\xc0\xd4\x34\x28\x42\x54\x3a" + "\x04\x84\xb5\x32\xd4\x1d\x09\x26" + "\x99\xf8\x2a\x27\xfc\x6d\x11\x8b" + "\x77\x87\x11\x34\x87\xdc\xf8\x51" + "\xbc\xf0\xa7\xdf\x40\xa3\xf0\xc0" + "\xdd\x97\xad\x56\xf6\xa5\xc5\x22" + + "\xe9\xdd\x15\x0f\x05\x4c\x21\x05" + "\x82\x2b\x5f\x0d\xa8\x76\x7a\xa4" + "\x62\x2b\xe8\x62\x30\x4d\x25\xbb" + "\xee\x55\xc9\x3e\xe0\x5f\xa0\x11" + "\x36\x9b\x52\x9d\x6e\xf4\xaf\x7e" + "\xf6\x3d\x9e\x8f\x01\x13\xab\x55" + "\x98\x76\x31\x99\x71\xe3\x63\xc4" + "\xad\x47\xda\xcc\x38\x14\x25\xfd" + + + "\x4e\x89\xfb\xdb\xf3\x22\x31\xe1" + "\x18\x4b\x27\xce\xf6\x79\x9b\xbe" + "\xdf\xaa\x58\xca\xe5\x9d\xa4\x85" + "\x51\x73\x48\x11\x58\x77\x95\x24" + "\x99\x90\x93\xbb\x61\xef\x1d\x11" + "\x94\x36\xd1\x26\x4a\x97\x6a\x1d" + "\x3b\x25\xfc\xd3\xce\xb4\x74\x44" + "\x5e\xb1\x5d\x4c\xe6\x85\x14\x3a" + + "\x18\x6f\xd6\x1e\xec\x86\xde\xeb" + "\x43\xce\x1f\xd6\x6b\x90\x5d\x22" + "\x4d\xd7\xbe\xe8\xd6\x07\xab\x5c" + "\xb7\x5a\x85\x27\x7f\x61\xe4\x16" + "\xdd\xc3\xfb\xb2\xdd\xaa\x68\x65" + "\x5b\xdf\xed\x8a\x4f\x48\xb5\xed" + "\xad\x2f\xcf\x6d\xe8\x20\x8f\x87" + "\x99\x56\x5f\x61\x7c\x49\x16\x35" + + "\xe2\xac\x7b\x70\xe8\xae\x58\x51" + "\x56\x1c\x6d\xf8\xc6\x14\x8d\x45" + "\xe2\xbe\xb9\xc1\x5c\xf1\xeb\x15" + "\xc0\x9c\x37\x0f\x66\xdf\x15\xa0" + "\x61\xd1\x2e\x20\xa3\xeb\x4c\xb2" + "\xf0\x3d\x4b\x20\x87\xf6\x58\x45" + "\x04\x4c\x26\xbe\xed\x8e\x0e\x89" + "\xb7\x8b\xde\x90\x10\x87\xb7\xb5" + + "\x69\x1e\x18\xfa\xec\x3f\x0a\xef" + "\x98\x9a\xd6\x30\x81\x2f\xa0\x9e" + "\x5d\xb9\xea\x66\x8e\xcf\xe9\xb2" + "\x21\x00\x72\x24\xeb\x2b\x0f\x52" + "\x61\x43\xf8\x1d\x0a\x54\x1c\x62" + "\x5d\x6d\xfa\x71\x21\x77\x03\x12" + "\xff\xf6\xf5\x0f\x51\x7b\x3c\x6e" + "\xf3\xbe\xb2\xab\x9b\x06\x7a\x81" + + "\x05\xcd\x81\x97\x11\x2f\x2b\x7e" + "\x2b\xa1\xaf\x7e\xe2\xc2\xa8\x77" + "\x5e\x38\x81\xa3\x3c\xd0\xfd\x78" + "\xad\x85\xab\x15\xbb\x54\x3b\xab" + "\xd4\x8a\x1c\xcf\xaa\x55\xbe\x48" + "\x81\xbc\x8a\x52\x58\x0c\xa6\x57" + "\xb3\x93\x68\x4a\xfe\xb5\xaf\xf8" + "\xcb\xcc\x66\x9a\xcf\x79\xd1\xbd" + + "\xb1\x09\x6c\x65\x77\x7d\x4f\xf1" + "\x00\xdf\xa9\x29\x95\xac\x40\x4b" + "\x33\x38\x10\x14\x82\x48\xdc\xe9" + "\xc7\x45\x17\x42\x33\x32\x63\x4c" + "\x69\x03\xc2\x75\xc5\xcc\x2f\xd2" + "\x36\x0c\x37\x89\xa5\x42\xf2\x47" + "\xcf\xec\xda\x4e\xae\x16\x8c\x1e" + "\xc4\x78\xcf\x4f\xb0\xab\x8e\xad" + + "\xcf\x98\xc5\x9e\xba\x05\xe6\x3d" + "\xae\x29\x30\x4d\xae\xd3\x33\x19" + "\x16\x05\x14\x9b\xbd\xfa\xf2\x6b" + "\x1c\xd0\xa7\x59\x55\xfc\x2d\x71" + "\x66\x63\x57\xd2\xe0\xaa\x3e\xff" + "\xf8\x1c\x70\x48\xf9\x07\xe4\x36" + "\xd4\x4b\x1f\xb4\x89\x1d\xe2\xed" + "\xa9\xef\x6e\x66\x5c\x2f\x29\xc5" + + "\xa6\xcd\x94\xb2\xb6\x2f\x57\x83" + "\x34\x9f\x03\xb9\x75\xbf\xe9\x6c" + "\x21\xbb\x5c\x09\xf0\x12\xe0\x20" + "\xda\xf0\x63\xd0\x1b\xcc\xae\xa0" + "\xe5\x09\x29\xf0\x3a\x1c\xc2\x57" + "\xdc\x9c\xce\x48\xcf\x9e\xd5\xc7" + "\xf8\x36\xe3\x8a\x44\xb8\x32\x27" + "\xf4\x85\x4f\x3f\x23\x37\x6e\x05" + + "\x52\xa8\x78\xef\x21\x5d\xb7\xf2" + "\x00\xa9\x31\xdd\x34\xcd\x38\xba" + "\x8a\xe1\xff\x58\x86\xa6\xb3\x72" + "\x45\x57\xd9\xbf\x0c\x19\x64\x74" + "\x81\x6e\xed\x77\x21\x53\x6e\x40" + "\xab\x5e\x53\xde\x5b\x97\xf0\x1a" + "\x82\x4c\xc5\x60\xc7\x22\xba\x66" + "\xe0\x2f\x0a\xb0\xce\xb1\xe3\x88" + + "\x15\x7b\x33\xf0\x77\xf9\xb7\x55" + "\x3a\x97\x94\x0e\xa3\x72\xc8\x3b" + "\xa0\xee\x0d\x77\x83\xd9\x4a\x62" + "\xdb\xef\xa5\x13\x64\x33\xab\xca" + "\x47\x42\x0d\x7a\x02\xd0\x1d\x39" + "\xd5\xae\x12\xf3\x5d\x0d\x59\x39" + "\xac\x65\x13\x35\xc9\x02\x28\x53" + "\x2a\xe2\xa2\x78\x45\x82\x2e\xdd" + + "\x87\xe6\xbe\x2e\xa5\xa6\xc6\x98" + "\x31\xc7\xc1\x56\xfa\x5b\xf6\xcd" + "\x10\xf2\xde\x72\x27\x13\xe8\x48" + "\xa5\xb5\x83\x80\x41\x19\xa1\x4e" + "\x25\xb5\xeb\xff\x4f\xea\xdc\x3f" + "\x72\xbf\x50\xfb\x19\xea\xaa\x55" + "\x0c\xb4\x85\x2a\x0a\xdc\xbe\x5f" + "\x9f\xf2\x44\xbf\x54\xd9\x6f\x0d" + + "\xca\x00\xe8\x89\x31\xb5\x10\x8a" + "\xfd\x08\x52\x14\x17\x0c\xfe\x50" + "\x37\xba\x14\xb7\xd3\xc0\x43\x9e" + "\xcc\x9a\x18\x34\x0e\x20\x7d\x42" + "\xc0\xe2\x16\xe6\x4f\xe2\xde\x05" + "\xc1\x54\x18\xee\xc8\xf4\x25\x9c" + "\x73\x2a\x34\x8f\xa5\x22\x32\x4d" + "\x52\xc9\x27\xa0\x4f\x80\x07\x08" + + "\x6f\x32\x8f\x2e\xf8\xb7\xbf\xba" + "\x19\xa5\x25\x56\x22\xac\x9c\xed" + "\xa9\xe0\xda\x0e\x1a\x9c\x10\xf1" + "\x59\x12\x52\x58\x98\x0a\xf8\x45" + "\x44\x1f\xb7\x5a\x07\x4b\xa4\x37" + "\x1b\x16\x21\x4a\xb6\x9e\x69\x21" + "\xee\x67\xfe\x56\xdf\xfd\x23\xb5" + "\x2e\xf7\xb9\x20\x21\x3a\x5c\x9f" + + "\x73\x6e\xd2\x50\x33\x4a\x41\xba" + "\x88\x26\xf7\x75\x94\x44\x69\x45" + "\x82\x0f\x55\xb1\xe3\xa6\x82\xd4" + "\x7e\x6d\x16\x43\xe6\xf7\x7f\xde" + "\x2a\x22\x94\x9c\x68\xc6\x97\xad" + "\x40\x98\xfa\x72\x2d\x92\xa5\x90" + "\x5f\xaa\xe6\x32\xbd\x86\x18\x37" + "\x44\x0d\x5e\x7f\x67\x4f\xbd\xf1" + + "\xc5\x19\xa3\xfb\x76\xb2\x8e\x05" + "\x4a\xa5\x7f\x7f\x12\x91\x3a\xd3" + "\xab\x2d\x2a\x93\xb4\xc1\x60\xf0" + "\xbf\xd9\xc7\x79\x4e\x22\x3a\xce" + "\x23\x28\xa9\x0b\x8c\x38\xb0\x6f" + "\x81\x78\x78\x69\x8a\x73\x31\x8d" + "\xb7\x00\xcd\x03\x02\xeb\x86\x2d" + "\x1b\x91\x69\x2b\x51\x44\x6e\x4e" + + "\xf3\x56\x0d\x4f\x3a\x65\x22\xc2" + "\x05\xb8\x28\xca\x47\x40\x1e\x96" + "\x4b\x43\x73\x4a\xb0\xf8\x03\x2c" + "\x19\x2a\x71\xab\x87\x67\x96\x4c" + "\x42\xee\x4f\x86\x42\x6c\x19\xcc" + "\x5c\xce\x0e\x5b\xda\x93\xbe\xc1" + "\x59\xc1\x31\xc1\x22\x9f\x7d\xa8" + "\x55\x56\xe4\xdc\x93\xd5\xb6\x2b" + + "\x42\x40\x89\x4c\xa9\x5a\x95\xec" + "\xed\x92\x2f\xf2\x9a\x17\x32\x9d" + "\x08\x65\x28\xfa\xf0\x0f\x02\x5e" + "\xda\x1c\x9b\x23\x3a\x86\x49\x46" + "\x8f\x45\xf1\x11\x92\x1b\x71\xa5" + "\x6d\x35\x9b\xde\xec\x93\xd4\x7d" + "\x94\x81\xad\x80\x82\x06\xf9\xe4" + "\x73\x97\x30\xfe\xc1\x7a\x86\x81" + + "\x3c\x91\x78\xad\xfe\x96\xdd\xe9" + "\xb5\xb7\xee\x86\x14\xb5\x5e\x32" + "\x8e\xb0\x93\xa1\x61\x74\x74\x85" + "\x41\x35\xdc\x5a\xaa\x0d\x84\xf5" + "\xda\x9f\x36\xdb\x44\x0c\x1d\xc1" + "\x05\x92\x75\xad\xd9\x4a\xb1\x3a" + "\xa2\xaf\x8f\x03\x3d\x9a\x3f\x53" + "\x04\xf7\xe3\xfd\x53\x65\xdf\xfd" + + "\xc6\xa4\x15\x29\x90\x69\xaf\xbe" + "\x11\x1c\xc3\x37\x4d\xc0\xdb\xd5" + "\xc8\xcb\x1f\x28\xba\x2a\xa7\xa7" + "\x21\xe6\x4a\x3f\x8d\xf2\x78\xa1" + "\x95\x08\x8d\x9b\x76\xdc\xdd\x23" + "\xd0\x06\xb2\x93\x84\xd7\xae\x88" + "\xe4\xa4\x32\x0e\x09\x1a\xe6\x6e" + "\xf4\x03\x2f\x26\x3b\x2e\x48\x1d" + + "\xce\xb7\x09\xb8\xc9\x9e\xc4\x22" + "\x2c\x2c\xc7\xe2\x6b\x48\x41\x8a" + "\x36\xbf\xa0\xfe\x20\x94\x3b\x81" + "\x69\xac\x6d\xa6\xe9\x6e\xd3\xb3" + "\x87\xc9\x8c\x32\x8a\xc0\xdd\x6f" + "\x61\x64\x32\x3a\x2c\xcd\x3b\x0a" + "\xba\xdb\x10\xd8\x9d\xc4\x03\x71" + "\xc4\xa4\x78\x4b\x28\x1a\xd8\xf9" + + "\x99\x0b\x18\xdd\xe8\xd8\xd1\xfe" + "\x49\x39\x3a\xd3\x3f\x33\x8c\xdd" + "\x99\x23\xb7\xb9\x2d\xdf\xdf\xcd" + "\x26\x55\x78\x8c\x3e\xe5\xa6\xad" + "\xb4\xe1\xbd\xc1\xed\xbf\xdf\xa0" + "\x4e\xd5\x77\x24\x81\x6b\x43\xc7" + "\xe8\x45\x32\xe7\x41\xd6\xec\x27" + "\x90\xcc\x97\xe0\xf1\x77\x8f\xb6" + + "\x66\x5c\x62\x2b\x1e\x62\xa3\x1a" + "\x0f\xe5\xea\xa9\xae\x5d\xdc\x48" + "\x58\xa1\x52\x7d\xc2\xac\x06\x57" + "\x5c\xa2\x91\xa9\xa2\x51\x15\x0a" + "\xeb\xb4\x0d\x97\x6a\x04\x54\x46" + "\x4b\x7e\xff\x35\x4d\x4d\xbe\x2b" + "\xb9\x2f\xa6\x18\xe7\x6a\x85\xd9" + "\x8e\xd3\xa7\x10\x04\x16\xa0\xac" + + "\x89\xdb\x76\x7a\xeb\xbb\xa0\x6b" + "\xf5\x2a\x35\x13\xbd\xc3\xc5\x1b" + "\x08\xbd\x44\xdd\x18\xfe\x3e\xb8" + "\x49\x24\xd8\x8d\xa7\xbe\xd6\x4b" + "\x0e\xd9\xf9\xda\x24\x31\x97\x4a" + "\x4c\xd8\x32\x33\x0c\x89\xdb\x6e" + "\x1b\x84\xbb\x9b\xe6\x39\x3e\xc2" + "\x6d\x3e\xae\x07\x45\x35\x8f\xc3" + + "\x41\x59\xd5\xe4\xad\x65\xe8\x3d" + "\x87\x40\x38\x30\x5e\xfa\xda\xde" + "\x9b\x8b\xf1\x4e\xbb\x4a\x41\x6f" + "\x68\x52\xee\xfa\x42\xea\xe9\x9e" + "\x4a\x5a\xa5\x37\x16\xaa\x0f\x26" + "\xb9\x93\x5f\x01\x14\xa5\x19\xeb" + "\x98\x35\x9c\x9e\xd2\xeb\xd7\x51" + "\x8e\x17\x32\x19\x6d\xc5\x3f\x52" + + "\xc8\xf1\xcf\x9a\x08\xdd\xc6\x9f" + "\x0d\xb6\x25\x9b\x2f\xac\xe8\x20" + "\x4c\x5c\xd9\xd4\xab\x30\x29\x22" + "\x7b\x50\xb2\x15\x4e\xb0\x77\x1e" + "\xeb\xda\x9c\x2d\x19\x88\x6b\x7a" + "\x3a\x79\x97\x31\x18\x4d\x5d\xf1" + "\x92\x4b\xed\x1c\x72\x2a\x70\x38" + "\x34\x93\xea\x37\xb0\x92\x8d\x94" + + "\x1d\x9d\xf3\x16\xa3\x9f\xf8\xda" + "\x51\x6f\x28\x60\xa3\xec\xdf\x4f" + "\xd2\x3a\x05\x79\xe9\xc5\x37\x1d" + "\x40\xfa\x58\x19\x30\x0e\xa7\xde" + "\x7c\xe6\x1f\x25\xef\x96\x0a\xd0" + "\x74\xbe\x94\xeb\x2b\x1a\xc0\xd8" + "\x75\x4b\xfd\x0c\x38\x44\x2a\x0e" + "\x2c\xf2\xbd\x85\xb2\xc7\x1b\x87" + + "\xf4\x22\x86\x3c\x28\x94\xff\x9f" + "\x40\x84\x46\x8c\x8f\x32\x6e\xb7" + "\x70\x0f\xae\x31\x97\xe1\xc5\x60" + "\xbc\x9c\x72\xec\x77\xd1\x6d\xf8" + "\xa2\x97\xf4\xf3\x30\x35\x81\x21" + "\xe7\xfe\x20\x59\xc1\x92\x31\x7f" + "\xe5\x1e\xc5\xe1\x31\x0c\x0f\x0e" + "\x10\xdd\xf4\x22\x73\xcd\x36\xf3" + + "\x84\xe6\x8f\xb9\x0c\x07\x1d\x50" + "\x58\x14\x4a\x12\x9a\xbe\x0f\xd6" + "\x3f\x6b\xbc\x92\xc8\x61\x57\xa4" + "\xcb\x27\x6f\xfe\x58\x48\x38\xf5" + "\x3b\x76\x9e\xb5\xf7\x71\x02\x4b" + "\x5e\x8e\x5a\x5b\xa9\x06\x46\x3d" + "\x92\x82\xa4\x05\x9b\x5d\xda\x1e" + "\x46\xc4\xfe\xe6\xd0\x31\x77\xda" + + "\x20\xff\x18\xeb\x77\x51\x7b\x27" + "\x62\x6d\xf0\x28\x98\x2e\x00\x48" + "\x8d\x6d\x50\x0e\xc3\xd6\xe8\xec" + "\x63\xf9\x9f\xcd\x58\x0a\xde\x5c" + "\x0e\xaa\x3b\x4e\xb7\xcd\x97\x3b" + "\xf9\x38\x12\x63\x0b\x0c\x56\x50" + "\x3d\x79\x79\xcf\x35\x1b\xc3\xe1" + "\x78\x21\x5e\x35\x14\x2f\xd1\x95" + + "\x37\x88\x42\x2f\xc3\xb9\x21\x3d" + "\xbf\x02\x34\x0f\x1e\x6b\xc9\x73" + "\x9e\xf3\x4f\x42\xc9\xbf\xf7\x6c" + "\x96\xd6\xd0\xf6\x59\xa4\x2d\xca" + "\x4e\x15\xb8\x3b\x9d\xd6\xf1\x3c" + "\xb4\xed\x30\x54\x16\x9b\x42\xc2" + "\x75\xd3\xd0\x15\x8a\x47\xc6\xd3" + "\x6b\x37\xe4\x7d\x7f\x06\x33\x5e" + + "\x62\x59\x20\xcb\x5d\x30\x8c\x37" + "\x9a\x59\x04\x3d\x9d\x9f\x40\xe1" + "\xb2\xc1\x57\x80\x27\xba\xec\x84" + "\xb1\x80\xbd\xa2\xe7\xac\x92\xcc" + "\x60\xc7\xc4\x4c\xdb\x11\x53\xcb" + "\xfe\x8e\x6d\x46\x63\xce\xf0\x18" + "\xee\x49\x72\x08\x1b\xeb\xa0\x0d" + "\xf3\xde\xfb\x56\xfb\xe3\x47\x7d" + + "\x71\x58\xd4\x90\x93\x36\xe3\xa3" + "\x8d\x6d\x16\x06\x40\x40\x76\xe9" + "\x03\x04\xa9\x89\x82\x36\xc3\xb5" + "\x37\xd6\xf1\x72\x83\x79\xd1\x4b" + "\x3a\xc5\xd2\xd5\x9e\x67\x16\xa6" + "\x87\x3b\xcf\xfd\xd8\xbc\xc4\x5e" + "\x4e\x69\x6a\xb6\x13\x76\x6d\xae" + "\xe5\x27\xfc\xe3\x76\xfc\x60\x74" + + + "\x62\x49\x3c\xc6\xe1\x1f\x53\x80" + "\x25\xdb\x1f\x98\x89\x1e\x54\x50" + "\x6b\x2b\x4c\xfd\xa1\x91\x12\xdc" + "\xca\x4f\xdf\xa6\x17\x3a\x69\xc0" + "\x03\xf2\x17\x01\x4e\x60\xc4\xb2" + "\xd0\xb8\x99\x0a\x63\x19\x5f\x24" + "\x44\x2c\x21\xc6\xaa\x20\xdc\xae" + "\xa8\x52\x0f\x52\x56\x4e\xed\xb1" + + "\xcd\x1a\x0a\x70\xb6\x0f\x56\xb5" + "\x81\x96\x99\xfd\x73\xfd\x23\xe8" + "\xba\xe1\xb4\x6c\x1f\x5d\x91\xda" + "\xa3\x00\xbe\x6e\x18\x01\x03\x0d" + "\xcd\xa8\xfc\x89\xc9\xb0\x4f\x74" + "\x0b\x0e\xda\xf9\xdb\x01\x0d\x97" + "\x6f\xd7\x31\x79\x64\xc5\xd8\x0a" + "\x6a\xb9\x59\xf6\xbf\x37\x57\xb1" + + "\xda\x22\xdf\x6b\x9c\x7a\xf3\x18" + "\xdf\x82\xdc\x90\x2f\x43\xbc\xef" + "\x51\x36\x70\x5d\x8e\xef\x2c\xc5" + "\xa5\x81\x98\xd9\xa0\x7b\x88\x82" + "\x1d\xec\x20\xb9\xda\x9d\xec\x7c" + "\x3b\x8d\x3e\xec\xc3\xe8\xd7\xd0" + "\x47\x87\xa8\x4c\x95\xc3\x5b\x44" + "\x35\x35\xd5\x9f\xe0\xa2\xea\xed" + + "\xd0\xc2\x53\xce\x4e\x38\x2b\xa1" + "\xda\x06\x46\x5e\x7d\x89\x9d\x77" + "\xb0\x12\xec\x73\xb0\x47\x3e\xa5" + "\xad\xf1\x56\x57\xba\xbb\x2d\x46" + "\xb6\x37\xfe\xca\xf2\x09\xfe\x69" + "\x17\x2e\xce\xec\xbf\x1e\x3d\x27" + "\xfd\x07\xf6\x3c\x38\xd5\xc1\x8a" + "\x25\x0c\xe1\x12\xff\xf7\x35\x80" + + "\x05\x90\x6c\x29\x0f\xcc\xd4\xb7" + "\xdb\xeb\x0a\x7b\xfa\x94\x90\x4b" + "\xd4\xc8\x0e\xc0\xf1\x10\xbf\xe1" + "\x01\xc1\x67\xd6\xc4\xb1\x07\xd8" + "\x83\x33\x71\xbe\xdf\x2c\x41\xa9" + "\xa1\x2b\x14\x81\x3e\x06\x5e\x43" + "\xdc\x6b\x0a\xaf\xec\x15\x4c\x98" + "\xb9\xda\xa3\x92\x60\x24\x2c\x59" + + "\x2a\xc2\x93\x20\x5a\x2d\x44\xca" + "\xed\x3a\x70\xd5\x31\xbd\xd0\xeb" + "\xb6\x87\x32\x65\xfd\x2a\x8f\x30" + "\xba\xc8\x1b\x0d\xac\x8b\xb8\x9b" + "\xb2\xe3\xc1\x75\x38\x85\xaf\xfb" + "\x7c\x44\x11\xca\x50\xc9\x2a\xbd" + "\x8d\x4c\x5c\xea\x6c\x81\x6d\x28" + "\x08\x32\xdc\x28\x00\xa8\x3a\xdc" + + "\x9d\x3e\xe2\x16\x00\x69\x65\x93" + "\xe1\x41\xcc\xa7\x6b\x0c\x22\xcb" + "\x5c\x24\xd6\x69\xc3\x20\x6b\xb3" + "\x6a\x9a\x2e\xb6\x48\xc3\x63\x2d" + "\xb5\xbc\xc0\xcd\x19\x3e\x47\xa3" + "\x98\x1b\x60\x8f\x3f\x8b\xf1\x70" + "\xe4\x46\xe3\xcd\xc7\xa2\xd7\x8a" + "\x64\xaa\x3a\xbd\xc3\x6e\x9f\xae" + + "\x20\x55\x6c\x7e\xc7\x34\x4d\x85" + "\x58\xea\xb9\xdc\xef\xf9\x7d\xc2" + "\x6d\x66\x86\xd6\x69\x23\x5f\x40" + "\x85\xaa\x17\x04\xbf\xfe\xd1\x29" + "\xfe\x0a\x47\x93\x9e\x81\x46\x98" + "\x9e\x7f\xa2\xe2\x69\x96\x6a\x3e" + "\x04\x65\x1e\xe3\xa2\x08\xd0\x24" + "\x0a\x68\xb7\x9c\xcf\xce\xa7\xdb" + + "\xe1\xc7\x74\x32\x50\x23\x02\x03" + "\x26\x6c\x4b\x4c\x93\x8c\xee\x61" + "\xce\x89\x93\x19\xe3\x97\x43\x3c" + "\xce\x57\x87\x48\x00\x26\x08\xe0" + "\xfb\xda\xb4\x06\xdf\xa2\xc3\xaa" + "\x6a\x5b\xff\xdd\x00\x07\xaf\x45" + "\xa0\x9f\x1d\x8c\x24\x74\x59\x0a" + "\x8b\xc6\x1f\x39\x7d\x08\x40\x16" + + "\x3d\xa5\x7f\xd0\x41\x3e\xa4\x26" + "\xc5\x5b\xe3\x74\x8a\xa7\x54\x31" + "\x8c\x2f\xda\xe0\x24\x89\x76\x7b" + "\x9a\x3f\x61\x23\x2b\x4a\x96\xba" + "\xc4\x16\x1d\xba\x35\x8d\x54\x5a" + "\x57\xd0\x54\xfb\xd1\xfe\x1b\x2e" + "\x05\x02\x64\xbc\x36\x21\x99\xff" + "\x29\xdf\x56\x81\x14\xb9\x9c\xf3" + + "\xbd\x48\x55\x4e\xcf\x3f\x87\xf4" + "\xf0\x57\xce\x03\x3f\xda\x25\x87" + "\x58\x32\x95\xca\x95\x5c\x2f\xd8" + "\x7e\x74\xf0\x7c\x12\x7f\x64\xac" + "\xd5\x0b\x57\x2d\xb0\x38\x20\xff" + "\x3f\xe0\x3a\xa1\x67\xa7\xc2\xb0" + "\x16\x2d\x93\xe9\xcd\x27\xaa\xeb" + "\x01\xe9\x34\x12\xfc\xe3\x86\xa6" + + "\xad\x44\xb4\x99\x46\xe6\x13\xc9" + "\xc5\x04\x05\xc4\x9d\xe9\xfc\xdd" + "\xdb\x53\x2e\xd4\x99\x2a\x48\x58" + "\x37\xf5\xaf\xd1\x25\x2c\xaf\x9a" + "\x67\xcf\x64\x26\x96\xf7\x90\xee" + "\x2b\x3e\x39\xf1\x99\x5c\xab\x74" + "\xb0\x5b\x22\xe6\xea\xfa\xd0\xfa" + "\x6c\xdd\x63\x2d\x8c\x64\x55\xc3" + + "\xcc\x1e\x26\x63\x5e\x43\x80\x9f" + "\xc9\xd6\x37\x43\x2e\xa6\x02\x63" + "\xa0\x58\x49\xca\x49\x6a\x91\x91" + "\xd3\xd5\x49\x31\x99\x58\x49\x55" + "\x3c\xde\x91\x9f\x0b\x02\x8d\x37" + "\x70\x51\xd2\x4d\xa3\x39\xb8\x47" + "\x58\xf2\xb7\x38\x41\x85\x25\x28" + "\xec\x7d\x7e\x43\xf7\x14\x5b\xea" + + "\x9d\xcf\x91\x1d\x27\x1d\xe3\xe4" + "\x0a\xb2\x77\xb3\xfd\xd4\x35\xcb" + "\x27\x13\x5e\x05\x45\x1e\xde\x74" + "\x75\x3e\x70\x28\x1b\xe3\x98\x32" + "\x39\x33\x01\xde\x37\x72\x08\x55" + "\xc6\x01\xd1\x23\x01\xf3\xcb\x32" + "\xdc\xb0\xaa\xe8\x22\xba\x0d\xc7" + "\xb9\x5b\x15\x3d\x3d\x62\x52\x4a" + + "\x44\x8f\x01\xb0\x36\x87\xf0\x74" + "\xf5\xd0\x46\xb4\x17\x34\xa0\xf4" + "\xb2\xa6\x0c\xa4\x2f\xaa\xa4\x66" + "\xed\x60\xdb\xba\xf0\x79\x56\x21" + "\xef\x4e\x3e\x32\x5a\x19\x71\x38" + "\x16\x2b\x95\x20\xc3\x40\x09\x8f" + "\x7d\x5f\x9d\x87\x62\xac\x8d\xfe" + "\x75\xe8\xa6\xc1\x23\xb6\x9c\x64" + + "\x43\x6e\x8d\x33\x41\xf5\xaf\xec" + "\xcc\xd5\x41\x45\x73\xdd\xf7\x56" + "\xca\x88\xbc\x96\xde\x26\xd4\xb5" + "\xc3\xa2\xd3\x9e\x6b\x4f\xd9\x48" + "\x9c\x27\xf8\x2e\xbb\xa3\x54\x63" + "\xf2\x67\x18\x0b\x5b\x46\x75\xd5" + "\x51\x51\x22\x95\xff\xb0\x99\xef" + "\xd8\x00\x45\xf9\x88\x9d\xe1\xf3" + + "\x08\xc1\x3e\x13\x87\x90\x6a\xa2" + "\xc0\xbd\x12\x27\x9f\x69\xc5\x5d" + "\xa9\x24\x42\xd1\x4d\x3f\x90\x96" + "\x80\x7b\xe4\x29\x24\x99\xa5\x3d" + "\x5a\xba\xdb\xf9\x2f\x71\x17\xb7" + "\xc9\x91\x63\x75\x4b\x00\x52\x9e" + "\x9c\x21\x9d\xcc\x1d\xa1\x69\xe6" + "\x7d\xc0\xd6\xd1\x84\x6b\x6e\x3b" + + "\x57\xcf\x5d\xc8\xac\x35\xf4\xdb" + "\x15\x54\x8f\xc8\x58\x56\x74\x61" + "\x07\x58\xc5\x17\x9a\x7e\x36\x26" + "\x6f\xc5\x90\xca\xa5\x77\xd0\x22" + "\x76\x4e\xe0\xa2\x58\x22\xf7\xfb" + "\x05\xe4\x06\x6e\x3e\x5d\x96\xba" + "\x54\xf9\xe6\xe3\x6f\xd0\x24\x57" + "\x74\x1a\x25\x81\x75\xd4\x47\x3e" + + "\xdb\xea\x6f\x67\x6a\xc0\xee\x5f" + "\x22\xf3\x69\x9d\xc5\x9b\x44\xfc" + "\x95\x88\xda\x7c\x5e\x7b\x8d\x1d" + "\xa7\x14\x33\x1a\xc1\x4d\xd5\x5e" + "\xc0\x89\xe8\x6d\xae\xd2\x11\x1a" + "\xd9\x2b\xed\x4c\x72\x79\xa9\xb2" + "\xf6\x5e\x6a\x30\x89\x69\xcf\x6e" + "\x49\xa2\xc8\x8c\x7b\xd5\x11\x16" + + "\xf7\x82\xfb\xe0\x51\x01\xba\xb8" + "\xc2\x8a\x66\xd5\x26\x07\x16\x0d" + "\xb0\x11\xd7\x14\x58\xa2\x2b\x62" + "\xf2\xe2\x3f\x7f\x57\xf5\xdd\x6a" + "\x35\x94\x9c\x6b\x1c\x1e\x83\x2b" + "\xbd\x26\x38\xb7\x0a\x06\x3a\xce" + "\x89\x0f\x24\x1c\xc1\x11\xfa\x93" + "\x3a\x30\x6e\x95\xd8\xc8\x9c\x4f" + + "\x87\xbf\x7c\x00\xba\x42\x99\x2d" + "\x26\xc9\x3f\xdf\xe6\xbc\x62\x4e" + "\xff\x0a\x56\xe4\xb0\xe5\xee\xe7" + "\xb7\x09\xb0\x7c\xbb\x63\x19\xe5" + "\xdd\x37\x9b\xe2\xce\x18\x51\xaa" + "\x03\x39\x26\x47\x47\x4a\xd8\x5c" + "\xd8\x55\x00\x62\xa6\xca\x50\x30" + "\x3d\x1e\x4b\x6c\xa7\x76\xf5\x7e" + + "\xc9\x82\x1f\x64\xf6\x31\x93\x4b" + "\x56\xc7\xfe\xdf\x54\x7c\x7c\xd9" + "\xab\x58\x91\x1a\x1f\x6d\xee\xf5" + "\x7f\xda\xc3\x85\xa3\x93\x44\x05" + "\xdf\x96\x7d\xeb\xf5\x05\x7a\xa5" + "\x39\x3a\x47\xe4\x47\xd4\xaf\xa3" + "\x55\x6d\xe1\x88\xc4\xd9\xa4\x42" + "\xae\x76\xf8\xf5\xf5\x44\xe1\x83" + + "\xf1\x8f\x00\xe6\xdd\xa4\x26\x90" + "\x6c\xd9\x8c\x1c\xad\x95\xe9\x49" + "\x9b\x58\x3e\x50\x73\x2e\x72\x80" + "\x26\xbc\xc2\x84\xe1\xbc\xbc\x05" + "\x2c\x2c\x68\xd4\xbb\x9a\x5f\x25" + "\x56\xd4\x84\xf0\xc2\xcf\x2b\xc4" + "\x67\x07\x1c\x64\xb0\xe9\xea\xa0" + "\x2d\x9a\x4c\x86\x2d\x63\x45\x1b" + + "\x20\xd6\x2d\xe3\x68\x32\xa8\x92" + "\xa2\x49\x78\x62\x9f\xc9\x3e\x91" + "\x82\x88\x37\x2c\xfa\xfd\xd8\xed" + "\xfe\x8c\x6f\xee\x3e\xf3\x96\xaf" + "\xa5\xa8\x3f\xdc\xe5\x37\x67\xc0" + "\x1d\x3a\xb0\xb0\x31\xb5\x6b\x23" + "\xb0\x37\xf0\x89\x29\x9f\xe5\x33" + "\x53\x2a\xa1\xd9\xa7\xb5\xf9\x13" + + "\xe0\x24\xe0\x6a\x3b\x79\x25\xcf" + "\xb0\xc4\xb5\x84\xb4\x07\x66\x1b" + "\xc8\x24\x16\x3f\x90\xfa\x79\x95" + "\xe8\x57\xbd\x68\xbe\x65\xfb\x37" + "\x03\xc2\x39\xfc\x5e\xa5\x93\xd6" + "\xe9\x52\x72\xc8\xc4\x7a\x26\x4e" + "\x13\x94\x89\x9f\xb0\x8b\xd7\xb8" + "\x08\x85\x3b\x0b\x07\x14\xc0\xe4" + + "\xa6\x9a\x02\x59\x95\xae\xd8\x50" + "\xed\xb2\x4d\x5a\x2c\x29\x4e\xd7" + "\x3d\x37\x8f\x84\x55\x33\x9c\x0b" + "\x38\xab\x45\xac\xb6\x8d\x01\xec" + "\xa8\x53\xcc\x69\x02\x69\x44\x1f" + "\x64\x98\x87\x1a\x8d\x62\x4b\x8c" + "\x5e\x47\x13\x4b\x28\x3d\x74\x1c" + "\xf6\x19\xde\x73\x38\x93\x4a\xbf" + + "\x53\x35\x3f\xbc\xe5\x06\x29\x66" + "\x84\x96\x45\x31\x35\xd5\x38\xde" + "\x0d\x28\xf7\x34\xc6\xa8\x46\x8f" + "\x8e\x19\x24\x3d\x87\x1b\xf9\xaa" + "\x7e\x11\x9b\x5f\x11\xee\xd5\xec" + "\xda\x8d\xae\x50\xbe\xff\x00\xce" + "\xae\xa9\x10\x77\x4e\x3d\x3a\x26" + "\x4f\xa7\x6b\xf2\x21\xf7\xf3\x0f" + + "\x69\xfa\xce\xf0\x47\x4f\x8a\x4a" + "\x66\x68\x54\xa4\xba\x4c\x8e\xdc" + "\xc1\x03\xf6\x23\x9b\xa6\x9b\x35" + "\xc5\x7a\x7b\x18\x01\xd6\xb4\xda" + "\xd9\xc8\xeb\xc1\x37\x43\xca\xa6" + "\x4b\x07\xb4\x52\x54\x58\xa6\x9f" + "\x33\xb7\x2f\x90\x81\x4f\x4b\x1a" + "\xaa\xde\x25\xa5\x7a\x5d\xbb\xd2" + + "\x7a\x57\xb3\xe6\xc2\x7a\x28\xcc" + "\x3b\x00\x12\xf6\xa7\x8c\x52\xd7" + "\xb8\x00\x14\x2c\xf1\xb6\xfd\x8a" + "\x8d\xdd\xa2\x46\xd3\x2e\x3a\x10" + "\x39\x13\xe2\x2e\x4d\xc5\xf8\xc8" + "\x20\x2d\x5a\x35\x92\x1b\x01\x8f" + "\xac\xf2\x46\x13\x9f\xfc\xc6\x81" + "\x4b\xd2\xa6\x05\xf0\x42\x60\xdb" + + "\x67\x95\x1f\xf8\xd5\x92\x2e\xeb" + "\x70\x84\x69\x4d\xea\x95\xcb\x54" + "\xeb\x81\x4c\xe0\x28\xcb\x2a\x5f" + "\x64\xec\xce\xf8\xc4\xbf\x1e\x1c" + "\x23\x74\xe0\x06\xac\x9f\x79\x8f" + "\x85\x0c\xfa\x37\x99\x5f\x22\x72" + "\x44\xdb\xf4\x34\x16\x86\xcd\xb0" + "\x91\x90\x2c\x75\x59\x61\xc3\x5e" + + "\x96\xf9\xa4\x0d\x63\xe3\x90\xfc" + "\xe4\x6f\x6d\xaa\x9d\xa4\xec\x8c" + "\x9b\x61\xfc\xbd\xfd\xaf\x84\x10" + "\x04\x0b\x14\xc1\x72\xf6\x29\x20" + "\x5e\x3e\x6f\x13\x5f\xc2\x6e\x60" + "\x4a\x4c\x22\x02\x9b\x14\x24\x6d" + "\x4c\xcf\xdf\xcf\x42\xf1\xb0\xab" + "\xed\xa0\xb1\xfa\x19\x04\x0d\xe4" + + "\x10\xb3\xef\x51\xce\xf6\x0d\x0d" + "\xbe\xf5\x8d\x95\xb4\x2e\x5b\xcb" + "\x59\x8e\x15\x36\x29\x9e\x45\xd6" + "\x36\xe3\x66\x14\xb9\xe2\xaa\x82" + "\x36\xa6\x1a\x41\x39\x8a\x65\xfb" + "\x33\xa9\xc0\xd4\xc5\xec\x52\x71" + "\xb7\x26\xf0\x49\x8a\x75\x0c\xf1" + "\x1f\x31\x09\xcb\x97\x7f\x83\xf4" + + + "\xd5\x32\x63\x62\x3a\x52\x4f\x99" + "\x44\xbb\x61\x55\x33\x88\xc3\x7b" + "\xa2\x5e\x84\x3d\xb0\xd4\x5e\x00" + "\x8a\xf0\xa1\xc2\xe1\x3e\x9d\xd3" + "\x0d\x6b\x67\xe7\xd3\xfd\x61\x65" + "\x17\x60\x70\xfb\xff\x35\x0e\x62" + "\xa8\xf9\x64\xf2\x4f\x42\xce\x36" + "\xf7\x81\x26\xda\x9f\x41\xc3\xc4" + + "\x48\x16\xb8\x9b\x76\x31\xf8\x00" + "\xd0\x20\x31\x65\x85\xb4\x9e\xd6" + "\x62\xbc\xca\x4c\xf4\x75\x7d\xd1" + "\xb1\xfc\x49\xb7\x82\x7f\xa0\x34" + "\x54\x55\xfb\xbb\x87\xf7\x3a\x2c" + "\xf8\x83\xe2\x62\xd0\xd4\x6e\xb0" + "\xa0\x13\x92\xa1\x9f\x88\x22\x57" + "\xb4\xc7\xf3\xdc\x5e\x08\x2b\x16" + + "\x7a\x0f\x30\xeb\xda\x0d\xd9\x36" + "\x01\xe8\xb5\xed\xfc\x7d\xcf\x9d" + "\x4c\x24\xd5\x74\x68\xb2\x5c\x64" + "\xa2\x3a\x8e\x34\x79\xee\x27\xa1" + "\xbb\x1d\x5f\x57\x53\xcc\x8a\x48" + "\x1e\x16\xe6\x80\x85\x7e\x03\x95" + "\xd0\x50\x26\x29\x83\x92\xe5\x57" + "\x16\x82\x93\x14\x99\x7d\xe6\xab" + + "\x1f\xe7\x89\x71\x2f\x0d\x67\x32" + "\xe7\x91\xcf\x5e\x48\x87\x43\xc6" + "\x21\x7a\x75\xdb\x57\x8e\x75\x15" + "\xe5\x9c\x0a\x29\xf8\x09\x7d\x42" + "\x7a\x4a\x38\x38\x8f\x30\x6a\x84" + "\x99\x2b\x73\xb0\xb4\xac\xc3\xaa" + "\x19\x58\x84\x17\x09\x10\x94\x9e" + "\x03\x5e\xce\xa7\x11\xa1\xcb\x95" + + "\x8e\x05\x78\x73\x37\xaa\x81\xeb" + "\x54\x11\x41\x04\xa1\x46\xc7\x41" + "\xc7\x8a\x82\xfb\xbc\x73\x0c\xa1" + "\x29\x2b\x97\x9d\x91\xbe\x39\x64" + "\xad\xfb\xa2\x43\xb0\xb4\xf3\x4b" + "\x40\xe8\xb5\x82\xdf\xda\xe6\x39" + "\x4c\xbd\x97\x63\x08\x64\x71\x4f" + "\xcb\xec\x1e\x7f\x68\xe5\x7d\x0f" + + "\xc3\xc3\x7e\xf3\x73\x2a\x33\xdb" + "\xa0\xeb\x59\xdd\xbd\x59\x52\xc6" + "\x57\x32\x4d\xdb\x9c\x70\x91\x22" + "\x90\x93\x38\xbd\x25\x3b\x79\x9a" + "\xf0\x56\x37\xe4\x4b\xe3\x9f\xf3" + "\xc9\x56\xfb\x9a\xce\xbd\x76\x2f" + "\x27\x8b\x20\x61\x7a\x86\x37\x9f" + "\xc3\x72\x99\x08\x07\x43\x1d\xea" + + "\x4f\x9f\x42\x8a\x87\x44\xa7\xd0" + "\x09\x66\x51\xdb\x2b\x71\x49\x06" + "\xdf\xb5\x69\xe7\x57\xba\x26\xb8" + "\xf2\xaa\xc7\x1f\xf2\x5d\x33\x82" + "\x95\xd9\x93\x5c\x67\xf0\x89\x23" + "\xe6\x7b\x67\x68\x7a\x36\xac\x59" + "\x1b\x95\xd9\x21\xff\x85\x79\xa7" + "\xce\x1c\x01\x85\xfb\x56\x89\x03" + + "\x9b\x5e\xca\xaa\x1a\x85\xb7\x97" + "\x97\x3b\x71\x56\x21\xa5\x8a\x51" + "\xf6\x61\x0a\x15\xc7\xe8\x57\x33" + "\x69\x2b\x2c\xec\xe2\xe7\x42\x78" + "\x48\xa5\x68\x68\x65\xaf\xff\x8d" + "\x81\xfc\x68\xe0\x82\xbd\x63\xd9" + "\x33\x77\x91\x65\x8b\x5c\xda\x64" + "\x28\x73\x24\x7b\xff\x90\x70\x92" + + "\x97\x0d\x6d\x2f\x94\xdb\xff\xd6" + "\x73\x93\x3b\x44\x41\xee\xc3\x05" + "\xb6\x6d\xd3\xff\xeb\x41\xe5\xb2" + "\x3e\xcc\x1d\xce\x96\x5a\x41\xb7" + "\xf6\xa2\x3a\x16\x2e\x68\x83\xe3" + "\x18\xf2\x3a\x2f\xd4\xbd\xfe\x46" + "\xdb\xba\xfd\xba\x7e\x50\xa0\x90" + "\x1a\xe2\x52\xce\x4d\xab\xa8\x4c" + + "\x73\xfb\x7c\x1b\x2e\x83\xf0\xa3" + "\xc9\x54\xc3\x3e\x52\xfe\x8a\x7a" + "\xca\xad\x8e\x37\x7e\xc9\x91\xae" + "\xbb\x32\x3b\xac\x99\xc5\x49\x74" + "\x55\x46\x1c\x0b\x71\xc3\x19\xa6" + "\x7e\xa8\x9d\xf7\x6a\x4c\x2e\x69" + "\x6a\xd9\x38\xde\x86\x5d\x3f\xff" + "\xec\xc0\x08\x1c\x42\x0f\x32\xc5" + + "\xec\x5d\xec\x8f\xbc\xf2\xa6\x92" + "\x6c\x78\xd6\x84\xff\x83\x13\xa7" + "\x84\xa0\xff\xdb\x06\x8c\x58\x87" + "\x15\xe7\x57\x68\xca\xf5\x85\x0d" + "\xd4\x74\xc7\xb6\xb3\x11\x73\xe8" + "\xa8\x21\x35\x4c\xc8\x57\x23\x67" + "\x0f\xfe\x29\x5b\x61\x74\xfe\xe5" + "\xcd\x58\x71\x5b\x10\x51\xbc\x02" + + "\x8e\xfc\x05\xa1\x48\x1e\xa0\x37" + "\x8c\xa4\x9b\x28\x4a\x75\x9d\x76" + "\x80\x21\x1c\xd5\xe1\x6f\x8c\xc0" + "\x87\x13\xbd\xb7\x33\xdd\x32\xb0" + "\xa6\x0a\x0b\x02\xdb\x26\x38\x95" + "\x3c\xc7\x64\x06\x80\x7e\x13\x05" + "\x5d\xf9\x0c\x66\xc4\x02\x63\xc6" + "\x8a\xf2\xce\xb2\x11\x4e\x00\x99" + + "\x36\x35\x97\x4f\x28\x5b\x4f\x82" + "\xea\x04\x5b\xd3\x9e\x29\x3e\xb4" + "\x89\x30\xa0\x4d\xf7\x88\x2c\xc7" + "\x2c\xe4\xa2\x45\x7a\xd5\x69\x82" + "\x8e\xb3\x07\x66\xfc\x63\x1e\x7c" + "\x0c\x0b\x39\x29\xaf\x2a\x9e\xe8" + "\x69\x28\xee\x1b\xda\x40\xc7\xc7" + "\x74\xb9\x3f\xaf\xfc\xf6\x56\x85" + + "\xd1\xbe\xb6\xa4\x95\x39\x0a\x1a" + "\x54\x5c\x09\x97\x95\x57\xab\x2d" + "\xe9\x3c\xa7\x2a\xff\xa1\xc6\x06" + "\xa7\x38\xe4\x4d\x4b\xa5\xd0\xad" + "\xcd\x06\xa9\xfc\x1a\x6b\x0b\x16" + "\xdd\x10\xde\x29\x16\x60\xfc\x25" + "\xa3\x3d\x63\xd3\x99\x9c\x8e\x34" + "\x5a\x4d\x8a\x15\x46\xf7\xe3\x1f" + + "\x1d\x5c\xe8\x8b\xc8\xed\x53\xc2" + "\xb6\x9c\xa0\x3c\x48\x0e\x3d\xdd" + "\x5a\x05\xe3\x9a\x87\xf6\x97\xb9" + "\xbf\x1d\x43\x07\xd0\x9a\x92\x0c" + "\x42\xdb\xd2\x84\x15\x62\xf1\xce" + "\xcd\x28\x88\x07\xef\xf3\x0d\xb5" + "\x66\x4b\xbd\x6d\x9d\xda\x89\x45" + "\x04\x2b\x9c\xd9\xe3\xd2\x4f\xbc" + + "\x41\xc2\x98\xd2\xa7\xc9\x4b\x21" + "\xfd\x7c\x80\x56\xba\x97\xb6\xe3" + "\xdb\xea\x64\x45\x02\x78\x1c\xef" + "\xc5\x49\x81\xb4\xcf\xcd\xe8\xdd" + "\x04\x26\x4d\x5a\xa7\xf0\x6b\x94" + "\xaf\x38\x15\x6c\x7f\x4d\x15\x27" + "\xcc\x1f\x5b\xde\x30\x92\xcc\x95" + "\x82\x4f\x86\x66\xe9\x19\x85\xd8" + + "\x77\xbc\x86\x62\xea\xa9\x01\x99" + "\xb0\x4d\x79\x69\x58\xfe\x9d\x24" + "\x21\xcd\xa6\xbb\xbd\x0b\x37\xc4" + "\x6b\x5e\xfc\x21\x31\x81\x8f\x71" + "\x61\x8b\xc7\x22\xbd\xed\xdf\x9c" + "\x71\x3d\xd4\xd9\xec\x3e\x31\x4b" + "\x22\x1b\xbb\x19\x1f\x03\x44\x41" + "\x58\x31\xa3\x07\xab\x73\x49\x97" + + "\x26\x65\x36\x06\xf4\xde\xaa\x67" + "\x96\x5d\x53\xae\x19\x30\xd5\xd7" + "\xc6\xeb\xa2\xe3\xa7\xdb\xfa\x72" + "\x16\x9d\x26\x75\xa5\x13\x23\xa3" + "\x2e\x92\x0d\xb5\x69\x1a\xfa\x97" + "\x45\x2b\x20\xca\xcf\x28\x6e\x4c" + "\x91\x0b\x10\x68\x00\x11\xbd\xb7" + "\x5d\x6a\xc9\x73\x8d\x41\x2e\xe0" + + "\x46\x55\x80\x8e\xdc\x6e\x9e\xfa" + "\x40\x98\x63\x82\x78\xe6\xe0\xc0" + "\x3d\x64\xbe\xb7\xa4\x58\x08\x43" + "\x1e\x5f\xcf\x18\x14\x24\x42\x1d" + "\xaf\x49\xef\x9f\x62\x0c\x99\x05" + "\x32\x1d\xc3\x5e\xcd\xe0\x46\x48" + "\xd4\x85\xbf\xba\xa8\x47\xdb\x46" + "\x7f\x9f\x75\xaa\xf1\xc9\x66\x5f" + + "\xa1\x6c\xea\x96\xf7\xe4\x13\x10" + "\x71\x28\x79\x1f\x2a\xdc\x7c\x56" + "\x45\x8d\x65\x5c\x70\x28\xb7\xad" + "\x98\x0e\x60\xce\x4a\xff\xc1\xf7" + "\x39\xad\x6c\x4b\x57\x86\xba\xa1" + "\x28\xb4\x20\xba\x34\xd6\x58\x3d" + "\xfb\xfd\xe6\xa2\xde\x1c\x01\xc0" + "\x0d\x96\x18\x7b\x7a\x36\x32\xa8" + + "\x07\x15\x52\x50\x8f\x2c\x39\xb7" + "\x9d\x2e\xef\xe5\x4b\x91\xb3\xac" + "\x85\x6f\x44\xea\x78\xb1\x70\x9a" + "\xee\xc3\xd8\x98\xa6\x43\x4c\xbd" + "\x77\x01\x4c\x84\xe5\xbb\x73\xa9" + "\xea\xb3\x2a\x06\x4d\x27\x9b\x29" + "\xaf\xda\x6a\x85\x7c\x0e\xba\x26" + "\xb8\xb2\x5c\x76\x94\x91\x9b\x13" + + "\x87\xd3\x9f\xbd\x9b\xe7\x21\x7b" + "\x71\x0c\x1c\x24\x9a\x76\x8f\xb4" + "\x93\x5a\x72\x8b\x36\x68\xe3\x83" + "\xe1\x96\x5b\x1f\x55\x4f\x9d\xef" + "\xa0\x10\x99\x2a\xa4\x39\x71\xc6" + "\x76\x5e\x09\x4e\xa2\xc8\xe1\x71" + "\xf2\xb8\x19\x27\x36\x7f\x2f\x21" + "\x17\x12\xfa\x00\x3f\xeb\x75\x9f" + + "\xb6\x6d\x3e\x34\x6e\x8e\x11\x4e" + "\x3f\x99\xb6\x25\x59\x55\xbd\x98" + "\x85\xfa\x2e\xb3\x14\xd5\x0d\xb4" + "\xa1\xe3\x24\x7a\x80\x55\x30\x7e" + "\xc3\x57\x58\x77\x50\x95\xcc\x7d" + "\xb0\xc1\x9b\x2c\x12\x11\x63\x05" + "\xe9\xdc\xa5\x02\xd5\x85\xae\x6e" + "\x72\x41\xeb\x34\xaa\xc9\x3f\xe5" + + "\xf7\x38\x49\x0e\x9f\x8c\x61\x47" + "\x9e\x71\x83\xdc\x69\x7d\xd4\x58" + "\xcc\x64\x1a\xf4\x23\x1a\x4c\xd7" + "\x66\x9f\x82\xb5\x68\xe0\x28\x5d" + "\xf6\x66\x04\x21\x29\x75\xd3\xd8" + "\xf8\x4e\xa6\xc6\x2f\x15\xf1\x2a" + "\x7a\x6a\xce\x19\x5c\x48\xd4\x55" + "\xd7\xe2\x48\xf6\xf5\xd2\x0b\x6d" + + "\x21\xb5\x9d\xf8\xb1\x6a\x2d\xf0" + "\xc6\xed\x0c\x65\xfc\x1a\xf4\x46" + "\x71\xdf\x8a\x1c\x96\x73\xbc\xb1" + "\xb9\xb1\xbd\x7e\xcb\x7f\x14\xd2" + "\x63\x03\x08\xc1\xf7\x0e\xaf\xca" + "\xc5\x09\x5c\xd9\xf3\x1a\x0b\xf9" + "\x83\x48\xf4\xf6\xd4\xbf\xaf\x7a" + "\x6d\x9b\x8d\x8a\x87\xe0\x64\x9b" + + "\xe5\x6a\x35\xbd\xe8\x9c\xfc\xee" + "\xf4\x5a\xd2\x2e\xc0\xa6\x98\x3d" + "\x84\xd8\x19\x63\x64\xf5\x73\x31" + "\x16\x4f\x6c\xca\x64\xed\x2d\x2b" + "\xd0\xfc\x6d\xce\xe5\x19\x7b\xe2" + "\xca\x87\xd8\xa0\x5f\xbc\x69\xa3" + "\x10\x37\x46\x07\x6e\x60\xc2\x59" + "\x4e\xe7\xc6\xf3\x2a\x11\xc1\x15" + + "\xa0\x13\x7a\x7e\x00\x30\xba\x4a" + "\xf5\xaa\xbb\x89\x47\xbb\x83\xf4" + "\x3f\x27\xfd\x9f\xf6\x50\x0d\x7c" + "\x92\xd6\xa4\xf4\x91\xc1\x63\x7e" + "\xe6\xd6\xf2\x42\x40\x34\xda\x8b" + "\xc6\x72\x8b\x93\xc2\xcd\xcf\xd7" + "\xe9\x54\x6e\x6f\xd2\xfb\x8a\xd2" + "\xe5\x3f\x8b\xc2\xb6\x23\x04\xd4" + + "\x8d\x44\x16\xf4\x2a\x03\xcc\x1e" + "\x71\xd9\x76\xec\x10\x8c\x7e\x4a" + "\xae\x6e\x0b\xb9\x05\x98\x4f\x85" + "\x94\x05\xed\x4b\x32\x15\x0b\xfd" + "\xa3\x5c\x8b\xd9\x48\x18\xf7\x89" + "\xef\xb3\x39\xf0\xfc\xe5\x1f\xd0" + "\x2e\xda\x7b\x62\x2e\x33\x81\x44" + "\x41\x3e\x07\xa5\xd7\xec\x7c\xe6" + + "\xcd\xec\x9c\x8a\x46\x16\x69\x2e" + "\xa1\x6d\x3a\x05\xcc\xeb\x92\xcc" + "\x64\x6b\x3a\x78\xb8\x76\x00\xa8" + "\xa2\x2f\x99\xa5\xa0\xe8\xd0\x42" + "\x30\xec\x56\x7c\x53\x1c\xc7\xd9" + "\x69\xc7\x6b\x6b\x96\x6a\x8b\x38" + "\xc7\x9f\xbf\xd3\xab\x33\xc2\xa0" + "\x69\x53\xc4\x2f\xd0\x5b\xf5\xd0" + + "\xf9\xee\x92\x32\x02\x33\x2c\xa7" + "\x16\x11\x8c\x9f\x36\x40\x5a\x0f" + "\x91\xa7\x96\x3e\xf0\x6e\x9e\x42" + "\x39\x39\x84\xf3\x81\x61\xeb\x60" + "\xd3\x18\x25\x90\x83\xf0\x49\xaf" + "\x0b\x39\xe8\xb9\x13\xc0\x65\xfe" + "\xa4\x34\x4d\xec\xb3\x7c\xb9\x7a" + "\x3d\x85\x4f\x8b\x08\x7a\x42\x72" + + "\x1f\xad\xfe\x2e\x68\xfc\x83\x38" + "\x68\x8d\x4d\xfc\xa1\x24\x72\xdd" + "\xdd\xaf\x1d\x9f\x4c\x84\x4e\x5c" + "\x7d\x9b\x11\x15\x8e\xd1\x40\x7f" + "\xeb\x68\xc2\xb7\x4c\xd1\xc6\x79" + "\xe1\x89\xae\xc2\x55\xc8\xb4\x65" + "\xa2\xd9\xb0\x7c\x99\xbb\x08\x35" + "\x5b\x4a\xc6\x2e\x5b\x63\x2c\xbc" + + "\x2c\x28\xb1\x7c\x1a\xdd\x28\xb8" + "\x3a\x97\x46\xbe\x26\x76\x8d\xa0" + "\xb2\xd6\x08\xe7\x40\x8d\xaf\x6b" + "\xf3\xb3\xae\x4d\xa1\x1f\x57\x72" + "\x98\xfd\x2d\xf2\x2f\x73\xb1\x85" + "\x8d\x10\x87\x00\xa7\x01\xab\x87" + "\x7a\x20\x88\x59\xa8\xfe\xaa\xaa" + "\x55\x07\xf0\x69\xf8\x32\xc8\xcc" + + + "\x1a\x9d\x8d\xca\x85\x11\x8f\x48" + "\xd2\xde\x87\xd9\x7d\xc7\xf2\xad" + "\x24\x61\xc4\x60\xf0\x39\x30\x5f" + "\xf4\x95\xe0\x71\x75\x0b\xd7\xe5" + "\x0f\xe7\x60\x62\x50\x86\xd5\x82" + "\x05\xd1\x50\xf7\xa7\x5e\xd7\x39" + "\x64\xc3\xba\x75\xb1\xd0\xf3\x8c" + "\x29\x13\xd0\x21\x4d\x56\xa7\xf3" + + "\xfc\x3e\xcd\x3f\x3e\xa4\x4a\xb2" + "\x9a\x8e\x08\xb8\x34\xc0\x26\xdd" + "\xea\x46\x3d\xbd\xc9\x4d\xef\xa5" + "\x6f\x6a\x4c\x8a\x58\x9d\xf9\xa2" + "\x6c\xa4\x1d\x2f\x55\xd3\xab\xdd" + "\xd1\xcd\xfa\x1a\xce\xf8\xc3\x72" + "\x78\x05\xd4\x92\xee\x4e\x0c\xd9" + "\x94\x3b\x62\xca\x1f\xb4\x8b\xd2" + + "\xe1\x7c\x41\xe7\xd2\x92\x27\x24" + "\xf5\xe7\x0e\x97\x71\xbc\x42\xff" + "\x1e\xa4\x67\x5c\x6d\xdc\xf4\x1f" + "\x58\x2a\x88\x20\x7b\x9b\x70\x77" + "\x2c\x7f\x21\xbe\x1d\x73\x54\x35" + "\x77\x21\xb7\x5b\xcd\xa8\xf2\x2a" + "\x59\xd0\x1d\x59\x69\xe7\xee\x58" + "\x77\x64\xba\x4b\xc9\x30\x29\xbb" + + "\xc0\xf2\x76\xf1\xda\xdd\x6a\x1e" + "\x58\x26\x57\xe2\x04\x46\xca\x01" + "\xfb\x2f\x34\x85\xed\x4d\x40\x0a" + "\xd6\x38\x18\x44\x96\x0f\xf6\x8c" + "\x4a\x1c\x07\xc9\x1c\x69\xbc\x9b" + "\x03\x28\x44\x34\x44\x87\x58\xfd" + "\x81\x0d\x9c\x80\x85\x1c\x10\x97" + "\x7f\x6f\x45\x8c\x4c\x75\xfb\xa7" + + "\x3f\x01\x71\xaf\xd5\xa1\xf7\x6a" + "\x46\xc9\xed\x0b\xe5\x16\x82\xe6" + "\xa0\x70\x73\xd2\x0b\xa3\xcb\xf4" + "\xcc\x21\x04\x87\xbf\xaf\x81\x79" + "\xe1\xf0\x49\x94\x67\x6a\x49\x02" + "\xae\xed\x47\x0a\xbe\xc4\xcf\x86" + "\x22\xca\xfe\xb1\x36\xc9\x73\x30" + "\xfb\xf8\xf8\x03\x12\x46\x69\xf5" + + "\xf8\x48\xde\x5b\x71\xd6\xad\xbc" + "\x7d\xbc\x89\x21\x73\x38\x70\xc9" + "\x8a\xee\x09\xc7\x9e\x29\x45\x5d" + "\xf8\xaf\x5a\x84\xe2\x7e\x28\xd1" + "\x1f\xbf\x1d\xdb\x74\x88\x1f\x7d" + "\xd6\x88\x0c\x99\x8b\x58\x46\xea" + "\x13\x83\x36\x84\x9a\x64\xba\x60" + "\xae\x43\xd5\x60\xce\xcb\xfd\xd5" + + "\x2d\x27\x90\x98\x95\xe9\x3d\xcf" + "\x10\x3a\x71\x3e\x2a\x43\xf3\x75" + "\xb8\x27\x82\xe2\x9f\x47\x13\x5e" + "\xc8\xcd\xfa\xfe\xa9\x1e\x56\xb8" + "\xfd\xaa\x32\x83\xa0\x97\xa2\xa6" + "\x62\x9b\x80\x73\xb5\x8b\x0d\x9b" + "\x6f\x03\x63\x0c\xfd\x1c\xfa\xd2" + "\xa8\xbd\x64\xbd\x55\xeb\x16\x7a" + + "\x27\x3e\xc1\x2a\x8a\x8e\xe4\xf7" + "\xf5\xa9\xb1\x4e\xdf\xf6\x94\x44" + "\x62\x0a\x1f\x98\xeb\x84\xbf\xed" + "\xf0\x38\x64\x53\x32\xdc\xba\x49" + "\x71\x75\x4f\x00\x41\xa5\xbe\x50" + "\xee\x94\x1c\xdf\x10\x7d\xc6\xba" + "\x31\xbc\x27\xb7\xa1\x73\x3d\x25" + "\x28\x6e\x68\x30\xf2\x1c\xd0\xb3" + + "\x3b\x5a\x6a\x30\x39\xc0\x0b\xa4" + "\x1b\x3a\x78\x96\xfd\x41\x0a\x4e" + "\xd4\xcd\x53\x02\x9a\xd3\xe8\xa1" + "\x38\x86\x38\xc7\x26\xbe\x80\x64" + "\x82\xf3\x85\x22\x1d\x5e\x36\xee" + "\x36\x5c\x0b\xec\x8f\x8d\x8d\x18" + "\x82\x4d\x0f\x1f\x48\x1a\xef\x34" + "\x9a\xd2\x87\xa4\xe1\x43\x8f\x1a" + + "\xa5\xdd\x02\x39\x7c\x14\xa8\xa5" + "\xb4\x73\x69\xfe\x06\xf7\xd2\x35" + "\x7e\x45\x57\xc2\xcf\xef\xc2\x5a" + "\x1b\x61\x00\x87\xd4\x48\x3f\x93" + "\xb2\xbe\x12\x49\x88\xaf\x65\xc3" + "\x94\xdf\x2e\x16\xe6\x4d\x5a\x7f" + "\x4b\xf3\x32\x0c\x7c\xba\x46\xc6" + "\x74\x10\x09\xb2\xf3\x6a\x2c\x63" + + "\x5f\x6f\xb2\x9b\x33\xa3\xf6\x10" + "\xb6\x85\x4d\x04\x8e\xdb\x85\x1e" + "\x54\x7e\x19\x94\x08\x7a\x69\xc3" + "\xa8\x4e\xcb\xa7\xc0\x8c\xe1\x65" + "\x6e\xfe\x71\xa4\x50\x4f\x8c\xa3" + "\x9c\x43\x13\x2f\x7a\x74\x31\xf0" + "\x8b\x31\x07\xc0\xba\xa6\xc4\x53" + "\x3d\xcb\xec\x1d\xe5\x3e\xda\xa8" + + "\x3f\x8f\xa4\x5c\xdf\x1a\xc0\xbf" + "\x84\x9b\x2a\xe2\x06\x2f\x35\x64" + "\x4a\x9e\x09\xc1\xa1\x4d\xe5\xce" + "\xc0\x89\x1b\xfa\xe8\x54\xda\xbb" + "\xfb\x55\x6e\x6f\xf5\x3d\x6a\x16" + "\x88\x6f\x17\x20\x24\x4a\xa4\x1c" + "\xff\xb5\xb7\xdf\x88\xfd\x6a\x93" + "\xa0\xd4\x11\x86\x37\x24\x4c\xe3" + + "\x92\x48\x55\x3e\x6d\x41\x24\x5f" + "\x45\x2a\x0e\x43\x3d\xb5\x13\x84" + "\xa0\xa2\x32\x90\xee\x6a\xc5\x99" + "\xb1\x67\xc3\xee\xf6\x2b\x43\x09" + "\xc1\xec\xf0\xda\xc6\x50\x28\x55" + "\x48\x20\xc9\x5b\x55\xce\xeb\x49" + "\x07\x13\x81\x54\xa6\x6b\xb6\xdf" + "\x97\x85\x29\x6f\x97\xf7\x84\x1b" + + "\xa4\xd5\xf8\x70\xeb\xd9\xb5\xd5" + "\x28\xb2\xbb\xd7\xe7\xdd\x5a\x37" + "\x32\x0b\x1c\x0c\x86\x8b\xe8\x31" + "\xaa\xdb\x3e\x17\xc4\x68\xf5\xd1" + "\x02\xdf\x59\x54\x83\xfc\x92\x15" + "\x7e\x9a\xcd\x0f\xfb\xc0\xea\x2b" + "\x0a\x3b\x47\x1b\xb8\xfd\xa6\xb0" + "\x48\xfc\xe8\x0f\x6f\x4c\x22\xe3" + + "\x89\xe1\x77\x57\x45\xc8\xa5\xa1" + "\x29\x28\x6f\x45\xe0\xbe\x10\xcc" + "\xd5\x2b\x76\xda\x56\x5c\xd9\x8a" + "\xa8\x1d\xd9\xe9\x14\x22\x2e\x15" + "\x74\x3c\xb2\x7c\x72\x0e\x5b\x97" + "\xdf\x66\x0c\xa9\x70\x76\x5d\xfd" + "\x53\xfc\x5f\x22\xad\xb8\xb5\xb5" + "\xae\xd2\xde\xfa\x73\xff\x6d\xab" + + "\xcf\x49\x35\x6d\x0f\xe5\x33\xd4" + "\x5e\x66\xcd\xfa\x6f\x69\x33\x6f" + "\xb4\xfc\x11\xce\xac\xfd\x5b\x69" + "\x60\x98\x7c\xaf\x52\xe2\x0e\x81" + "\x2c\xbb\x59\x71\xe1\x0f\x45\x65" + "\x7b\x35\x8b\x75\xbe\xbe\xdf\xf7" + "\x72\xea\x9f\xd6\x74\x7e\x05\x2b" + "\x45\x17\x73\x92\x7a\x71\x85\xd4" + + "\xef\xd7\x76\xb3\x84\x76\x6d\x8d" + "\x81\xda\xd5\x48\xac\x02\xbf\x3d" + "\x9c\x13\x89\x1b\x5a\x38\xa5\xfa" + "\xce\xa7\x20\x68\x85\xcb\x4d\x50" + "\x26\x9d\x1a\xe6\x45\x21\x98\xc0" + "\xaf\x25\x5d\xac\x32\x6c\x5c\xf3" + "\xc2\xb3\x27\x4e\x67\xa2\x3b\xaa" + "\xc5\x7a\x6c\x9f\xa0\xa3\x69\x2e" + + "\xcf\x86\x0b\xf3\x1d\x5c\x6a\x90" + "\x87\xef\x07\x4d\xfc\x66\x6f\xb1" + "\x61\x22\x01\xd4\xda\xc2\x75\xa9" + "\x1e\x36\xbc\x0f\xe6\x48\x97\xe6" + "\xc7\x00\x99\x2d\x36\x35\xa0\xa2" + "\x0f\xaa\xf6\x7c\xe1\x3c\x2a\x1f" + "\x87\x38\xe3\xa1\x3a\x44\xd5\x80" + "\xdf\xb4\x47\x5b\x8b\x24\xda\x6a" + + "\x1a\x72\x3c\xdd\x08\xbb\x9f\x1f" + "\x9c\x22\xb2\x46\x7e\xf9\xa1\x93" + "\xfb\x7e\xba\x31\x46\xad\xe5\x4e" + "\xa3\x10\xae\xf3\xa5\x5c\xaa\x6b" + "\x04\x02\x6c\x74\x3e\xfc\x81\x7d" + "\x0b\x06\x9a\x2b\xf0\x90\xcc\x9e" + "\xa7\x8c\x68\x7b\x2f\x16\x58\xdb" + "\xdf\xc1\x54\xf5\x99\x2a\x77\xf4" + + "\xf4\x4b\xdc\x67\x7c\x4e\xb2\xed" + "\x7b\x82\x4a\xaa\x43\xc7\xe4\xcb" + "\x2b\xf8\xcf\xfa\xf5\x72\x94\x22" + "\x9b\x4a\x2c\xcf\x82\xbb\xef\x2c" + "\xf1\x7f\x36\x59\xb8\x06\x6e\x38" + "\x75\xaf\xcd\xa3\x78\x59\x24\x32" + "\x98\xb1\x07\x98\x6d\xd3\xbd\x2d" + "\xe9\x11\x85\xb7\xe7\x95\x74\x43" + + "\x27\xa7\xdd\x77\x65\x6e\x16\x34" + "\xcf\xaa\xaa\x3e\xc1\xa3\xa4\xb6" + "\x40\x62\x2c\x9d\xc2\x49\xcd\x9c" + "\x63\xa1\x2b\xa4\x3d\x7f\xe1\xc2" + "\x33\x21\x6d\x7c\x5c\xeb\xf9\x91" + "\x06\x76\xa9\xe6\x2a\xbd\xce\x85" + "\xfb\x0d\xb0\x65\xbd\x35\x6e\x80" + "\x82\x2a\x39\xb9\x06\x79\x9f\x9e" + + "\x3b\x2b\x0d\x4d\x8a\x29\x9f\x23" + "\xf1\x07\xb2\xdb\xcf\x60\x97\x6c" + "\xeb\x2e\xf9\xd4\x3f\x20\xbf\xc8" + "\x9b\x4e\xa7\x7e\xe4\x2a\x0b\x29" + "\x3d\x7d\x3a\x16\x37\x93\xa6\x1f" + "\x14\xa4\xef\x87\xe8\x5e\x29\xd0" + "\x3f\x27\xf8\xf9\x37\x40\x84\x54" + "\x58\xab\x41\xe3\x62\xa8\x46\x30" + + "\x0b\xfc\xc6\x38\x53\xe9\x9f\xfb" + "\xc8\x79\x95\xac\xe8\xe2\x94\xe4" + "\x8b\xca\xd7\x69\x6f\xef\x24\xc4" + "\xec\x57\xb8\x4f\x15\x52\x0e\x63" + "\x48\xdf\xe2\x42\x2b\x11\x13\xf0" + "\xbf\x04\x52\x62\x08\xc9\xad\xef" + "\xce\xb0\x63\x11\x6c\xb1\x8b\x7d" + "\x89\x68\x14\xb7\xe3\x47\x51\xdf" + + "\xad\x75\xbf\xa2\x05\x8b\x37\x5b" + "\x92\x1e\xda\x25\x66\x4b\x37\xfe" + "\x12\x67\x76\xff\x00\x81\x4c\xfb" + "\x60\x46\xc8\xcb\x80\x63\x60\xbc" + "\xe4\xad\x10\x6c\xc9\x6e\x26\x27" + "\xa7\xec\xb6\x7a\xb5\xc2\x6a\xb4" + "\x00\xe8\x28\xbb\xd7\x73\xc6\xfd" + "\xfe\xe3\xc0\x23\x20\x5f\x64\xb5" + + "\x28\x2b\x56\x30\x5f\x0e\x43\x76" + "\x06\xd8\xea\x36\x10\xca\x41\x67" + "\x93\x12\x7f\x93\x31\x50\x6e\xbf" + "\xf0\x9a\x29\x22\x6e\x09\xc3\x32" + "\x22\xdd\x45\x21\x61\xb1\xa3\xd6" + "\x33\x86\x5e\xd7\x57\x90\x49\x6c" + "\xbd\xc2\xf1\x39\x51\x76\x99\xa5" + "\xf5\xab\x1f\x6b\x6d\x0c\x90\x3b" + + "\x63\x7c\x43\xe7\x16\x68\x29\xe8" + "\x11\x4c\x16\x76\xd2\xc0\xa7\x38" + "\x0e\x84\x29\x9c\xf9\x95\x10\x1f" + "\x3f\x09\xb9\x57\xb3\xb9\x12\x19" + "\x17\xc8\x39\xf8\x04\xd5\x09\xfe" + "\xdd\x4b\xdd\xbd\x3b\xfb\x64\x1f" + "\x34\x45\x04\xdb\x5b\xed\x42\xef" + "\xc8\x21\xe8\xb4\x95\xdd\x60\x15" + + "\x4e\x52\xb9\x70\x50\xaf\x39\xde" + "\x68\xc8\xd1\xad\xe9\x95\x69\x79" + "\xc9\x4c\x9a\x32\x28\xb8\x90\x97" + "\x64\xae\x62\x5b\xb7\xa2\xeb\x1e" + "\x2f\xc1\xe3\xd7\xf6\xd3\x7b\x61" + "\x21\x64\x33\xdf\x1c\x71\x7e\xdb" + "\xcf\x07\x89\xd7\x37\x09\xfc\x7d" + "\xd5\x8b\x1a\x84\x99\x7a\x93\x88" + + "\xba\x41\x0a\x5d\x4d\xc2\xa5\xb9" + "\x1e\x86\x6c\xb6\x02\x84\x29\x58" + "\xfc\xcd\x71\x4c\xf8\x6e\xdb\x99" + "\xd9\x4c\x36\xe6\xaa\xaa\xe2\x69" + "\xd9\xc7\x8b\x64\x18\x94\xf0\x4b" + "\x6f\x3c\x71\xeb\xe9\xc2\xb3\x5a" + "\xc2\x52\x6e\x0c\x58\xd5\x75\x6a" + "\x12\x00\x60\xe5\x24\x8a\x2b\x46" + + "\x8e\x85\x82\xfe\x08\x42\x54\xca" + "\x90\x1a\xc2\x3e\x4a\xaf\xa3\x51" + "\xd4\x14\x76\xc2\x63\x9e\xc1\x63" + "\x39\xe7\x05\xe0\x95\x8c\x08\x32" + "\x00\x8d\x4a\x94\xf9\x25\x50\x7c" + "\x48\x2a\x94\x9a\x7d\xe3\x98\x8f" + "\xe7\x45\x5c\x53\x51\x73\x35\x53" + "\x80\x1f\x89\x44\x1c\xf1\x41\xfe" + + "\x90\xc3\xa2\x5d\x9c\xe1\xf9\x20" + "\x8a\x6d\xbd\xda\x2f\xe6\x69\x1f" + "\x65\xbb\xaa\x27\x2e\xb6\x9e\x1b" + "\xb5\xbb\xbb\x3d\x37\x83\x09\xbb" + "\xda\x32\x36\x82\xc9\x88\x3b\x7d" + "\xde\xe7\x59\xa7\xf3\x74\x89\x6c" + "\x6c\x87\x52\x3d\x08\x78\x65\x49" + "\xd8\xcd\x45\xe0\xbc\x73\x64\xb5" + + "\x47\xe7\x53\x00\x0e\x7e\xe5\x5d" + "\x53\x8a\x1c\x56\x92\x65\xd3\x04" + "\xad\x2e\x7f\xca\x78\xd3\x06\x6a" + "\xdb\x59\xf8\x14\x20\x56\x61\xb3" + "\xf8\xf8\x19\x14\x17\x91\xb1\x4e" + "\x32\x99\x3b\x60\x25\x45\xbf\xd0" + "\x98\x58\xa1\x9d\xcd\x45\x3e\xfc" + "\x14\x8d\x32\x79\x71\x9f\xe8\x5e" + + "\x0c\x86\x36\xee\xe8\x42\x6c\x89" + "\x2d\xc2\x13\x41\xfd\x4d\xf0\xda" + "\x13\x42\x10\x44\xb7\xb7\xdb\x1a" + "\xea\x94\xd3\x1f\xa1\x5f\xfd\xe5" + "\x51\x05\x4e\x1a\x94\x5d\x23\x68" + "\x51\x01\xd1\x18\xbe\xcf\x72\x67" + "\x23\x45\x98\x09\xe3\x71\x60\x27" + "\x98\xba\x56\x5a\xde\x79\xe8\xe4" + + + "\x91\x94\x5b\x28\xb0\xaf\xaf\xaa" + "\x5e\x70\x4c\x1e\x88\xbe\xa0\x01" + "\xab\xca\xd9\x2a\x5d\x4f\x1d\xff" + "\x3f\x23\x7a\xc3\x4a\x9a\x34\x6e" + "\x16\x6a\x1c\x4a\x46\x12\x1c\xcf" + "\x60\x32\x38\x29\x66\x6b\x9e\xd9" + "\x71\x54\x6d\x5f\x66\x43\x3d\xea" + "\x9b\xc8\x8c\xff\x04\x4d\x97\x36" + + "\x57\x90\x92\x8f\x14\x9e\xf2\x27" + "\xdf\x53\xc8\xc0\x06\xae\x64\x7a" + "\xce\xc5\xe9\x58\x83\xd1\x6c\x25" + "\xa5\x92\xd0\xde\x82\xce\x9c\x9d" + "\xc7\xb7\x93\x6e\x79\x59\x6e\xcc" + "\x27\x9e\xbb\x31\x92\x70\xe4\xe1" + "\xa0\x29\x9e\xaa\x83\x30\x0b\xb7" + "\x44\xe6\x85\x37\x75\x1a\x18\xbf" + + "\x1e\x3f\x0a\x5c\xc8\xe8\xd6\x8e" + "\x7f\xc3\x87\x7c\x92\x24\xad\xbc" + "\x8d\xb7\xe3\x9e\xbb\x62\xfb\xfd" + "\x46\xba\xce\xcb\x77\xe4\xa8\xeb" + "\x4b\xde\xae\xee\xb0\x8c\xd3\x37" + "\xb6\xde\x76\x79\xe8\x98\xc4\x0b" + "\xfb\x47\x61\x6b\x04\x4c\x94\xb2" + "\x09\x96\x1f\xf7\x35\x3f\x12\x8b" + + "\xd0\xb9\x02\x14\x3f\xa1\xb3\xd3" + "\x63\xc8\x7b\x2c\xc3\x41\x34\x57" + "\x6e\x3e\x8c\x57\xc4\x1e\x30\x4b" + "\x7e\xf5\xda\x0a\xc4\xc9\x6f\xc2" + "\xa3\xce\x93\x74\xfd\x1b\xe7\x96" + "\x56\x14\xf8\x1a\x3f\x4b\x5d\xd0" + "\x8f\x60\x8c\x6a\x8a\x2a\xca\xda" + "\x76\xb2\x25\x07\xf6\x07\xef\x53" + + "\x78\x59\x43\xc7\xf0\x23\xe0\xba" + "\x19\x0e\xe3\x20\x88\xc8\x52\xb1" + "\xaf\x6f\xfa\xe3\x45\x16\x24\x9c" + "\x60\x3e\x82\x84\xc1\x95\x5d\x73" + "\x17\x53\x95\x03\x73\x75\x19\x03" + "\x95\x49\x3b\xf0\xa9\x02\x4b\x0b" + "\x00\x46\x27\x70\x59\xf5\x6b\x07" + "\x08\x75\xf5\xaa\x53\xcc\xc5\x32" + + "\xd2\xc5\xc7\xd5\xfd\xdb\x18\x03" + "\x2d\x34\x2b\x07\xa7\x8d\x8f\xb3" + "\x8a\xe3\x8d\x7b\xdc\xbd\x69\x35" + "\x42\x48\xc9\xa1\x87\x58\x5b\xf2" + "\x60\xad\x46\x29\x84\xb2\xd5\xb2" + "\x7e\x70\xd1\xe9\xad\x29\x4f\x85" + "\x09\x45\x6a\x2c\xdc\x59\x51\xaa" + "\x37\x98\x18\x57\xc0\x94\x9f\x89" + + "\xe7\x89\xce\x49\xe0\x36\xf5\x27" + "\xb5\x0c\x89\xcc\x39\x85\x90\x18" + "\xa1\x2a\x3c\xd8\xab\x09\x89\x30" + "\xd3\x3b\xb7\x1a\x2b\x14\xd3\xec" + "\x84\xab\xf5\xb3\x59\xbf\x85\x6a" + "\xc6\xa4\xbe\xf2\x68\x0a\x32\x3c" + "\x1f\x54\xa4\x6d\x38\xc5\x8d\xad" + "\x86\x11\xc4\xb7\xb0\x4e\xf3\xea" + + "\xd2\x49\xac\x46\xd6\xc9\xb5\xa6" + "\xa9\x7a\x13\x83\x0b\x7c\xc7\x42" + "\x38\x5a\x22\x68\xfc\x00\xd0\x24" + "\x07\xe9\xe1\x2f\xc8\xcf\x63\x0f" + "\x95\x1f\x44\xc6\x1b\xb0\xd1\x22" + "\x8f\x44\x8e\xec\x19\xf7\x38\x7d" + "\xba\xb1\x7f\x78\x5f\xfa\x33\x9b" + "\xdf\x58\x01\x19\xa1\xfd\xdc\x94" + + "\xca\x1a\x0a\x49\x26\x93\xc7\x63" + "\x02\x6b\x52\x41\x9c\xdd\x64\xcb" + "\x58\x92\x97\xa2\x91\x25\x77\xbb" + "\x46\x78\xd9\x48\x70\x29\x58\x3f" + "\xa7\x3b\x21\x7c\xd1\x70\x6b\xd6" + "\xd4\xce\xa0\xe8\xb5\xeb\x8f\xc2" + "\xc1\x38\x03\xc1\x31\x18\x91\x6b" + "\xf3\x26\x01\xbf\x89\xe3\x54\x0d" + + "\x9b\x68\x83\xb4\xfe\x2e\x24\x40" + "\x62\xc2\x3a\x51\xf6\xd3\x75\x25" + "\x72\xdb\xa6\x0c\xc8\x37\x00\xf3" + "\xe2\x4b\x86\x98\x82\xce\xfc\xc9" + "\x2d\x36\x49\x01\xff\x12\xa1\x84" + "\x71\xe9\x4a\x1c\x82\x75\xe5\x95" + "\x6c\xf8\x5c\x94\xa8\xb1\xa4\x1f" + "\x2f\x4a\x02\x0b\x34\xa7\x25\x45" + + "\x5f\xd8\x05\xc9\xc2\xd1\xea\xca" + "\x57\xae\x33\x07\x90\xf7\xd7\xe9" + "\x94\xdd\x7c\xf0\x5c\xa6\xc9\x24" + "\x31\x59\xb5\xa4\x9c\x35\x89\x73" + "\xf7\x45\x7e\x36\xb7\x09\x87\xf5" + "\xdc\x7a\x7e\xcb\x67\x30\x20\x1f" + "\x18\x28\xb7\xc7\xff\x4b\x44\x82" + "\x33\x80\xac\xba\x35\x3b\x30\x07" + + "\xfd\x09\x6f\x52\x45\xed\x7f\x05" + "\x0a\x24\x28\x81\x0c\xf1\xa4\xe8" + "\x8d\xfd\x2b\xff\xc4\xef\x32\x93" + "\x31\xaa\x35\xbd\xa0\x77\x4e\x21" + "\x0e\xa4\xfa\x14\x73\x6d\x89\x32" + "\x86\xf1\xe5\x01\xec\x67\x78\x76" + "\x3e\x81\xa1\x17\xf1\xf8\xad\xc9" + "\x95\x17\x74\x54\x78\xda\x6c\xcb" + + "\x85\xe1\xda\x01\x01\xd0\xb4\xb7" + "\xbc\x94\x7a\x9b\x0b\x4e\x43\x45" + "\x0b\xcb\xd8\xfb\xaf\x39\x43\xf5" + "\x9e\xf4\x8e\xe9\x9e\x56\xc4\xdc" + "\x99\x12\xa5\x09\x8a\x31\x89\x77" + "\xd8\x25\xb0\xb2\x06\xd2\xb4\x81" + "\x92\x57\xe8\xfa\x18\xa4\x4a\xf6" + "\xf7\xba\xd7\xac\x8f\x25\x50\x3e" + + "\x68\xd8\x9f\xa1\xd3\xeb\x72\xc0" + "\x3b\xdd\x8d\xdb\x1c\x48\x2e\x61" + "\x52\xd8\x64\x1a\x54\xd7\xe1\xb4" + "\xab\xc4\xc6\xc4\xac\x95\xef\x00" + "\x46\x6c\x0a\xaa\xed\xd2\x36\x15" + "\x90\x47\x77\x43\x86\x40\x29\x61" + "\x10\xda\x3f\x34\xe8\x25\xaf\x54" + "\xf2\xd6\x25\xfd\x8d\xd9\xf9\x9f" + + "\xa4\xbe\x79\x55\xdf\x96\xd2\x4c" + "\xf1\xda\xee\x5c\xc8\x5a\xe3\x10" + "\xb1\xc5\xbc\xe3\xfd\xc5\xc4\x04" + "\xf9\x2c\x41\x89\x8a\xee\xf9\x95" + "\x0f\xeb\xb6\x82\xee\x59\x94\x2c" + "\xdd\xaa\xc2\x95\x65\x57\x84\x2e" + "\xfe\xfc\x27\xd3\xae\x84\x4a\x77" + "\x76\xd4\x68\x03\x22\x37\xc9\xd8" + + "\xef\x36\x6c\x29\x10\xde\x1c\x21" + "\x77\xda\xc4\x82\x72\x96\xe8\x7e" + "\xda\x36\x78\xa5\x70\xd2\x17\xb6" + "\x0b\x56\xb7\x9c\x31\x9c\xcd\xf0" + "\x90\xfe\x55\xe4\xf7\xcb\xfd\x01" + "\xf3\x34\x73\x7e\xbb\x3c\xb5\x3f" + "\xec\xe4\x7d\x4e\xa4\x2e\x1e\x78" + "\xd0\x4f\x38\x0b\xad\xb3\xda\x8a" + + "\xb8\xb3\xba\xbb\xf2\x90\xe6\x60" + "\x6b\x81\x04\x8b\xae\xf8\x51\x48" + "\xd2\xe4\x92\x9c\xab\x46\x20\xc7" + "\x6b\x13\xf3\x7c\xa1\x74\x8c\x51" + "\x4c\x7d\x87\xf9\x0a\xb5\x4e\xff" + "\xbb\xca\x19\xa9\x90\x8d\x57\x14" + "\xb6\xb2\x5e\xac\xc4\xf8\x18\x82" + "\xe4\x16\x20\x54\x47\xc5\xcc\xa3" + + "\x85\x7b\xea\x1e\x6c\xa7\x3e\xe3" + "\x5e\xf8\xd4\x92\x61\xb4\x52\x23" + "\xbb\x15\xe1\xaf\x34\xd3\x01\xf1" + "\xa3\x75\x91\x88\x94\x12\xbc\xfa" + "\x25\xf9\x33\x52\xc0\xcd\x6b\x7f" + "\x55\xec\x7f\xe7\xdb\x02\xa8\xe0" + "\x59\xb6\x69\x80\x75\x7b\xb4\xbd" + "\x74\xbd\x8f\xf9\xde\x12\x5e\x1c" + + "\xbb\xdd\xd8\x89\x58\x46\x6c\x65" + "\xe8\x8e\xf3\x70\x6e\xb2\x30\x88" + "\xb0\x12\x12\xde\x5c\xfd\x20\x43" + "\xb2\xed\xa2\xe4\xcf\x30\x4f\xc3" + "\xb8\x64\xab\x56\xa3\x31\xb1\xab" + "\x26\x5d\x9c\xd9\xcc\xf0\x77\x7f" + "\x94\x1d\x98\xbf\x37\x6a\x85\x66" + "\x6e\xd7\x8b\x73\x09\x6d\xe7\x19" + + "\xc0\x18\xb6\x53\x7d\xd4\x6b\x1c" + "\x23\x79\x22\x6a\x6c\xf4\x24\xc4" + "\x64\xd9\x92\xdd\xde\xff\x03\x73" + "\xf2\xab\xb5\x71\x78\x28\x71\xe9" + "\x1d\x56\x15\xf8\x32\xa6\x48\x8f" + "\xd1\x55\xc0\xd3\xf5\x8f\xf4\x85" + "\x4f\x68\x25\x75\x27\x14\x2a\x22" + "\xc3\x0c\x36\x67\xa0\x41\xd8\xd0" + + "\x99\x4a\xc3\xf2\xb1\x44\x0c\x86" + "\xac\x55\x58\xbf\xa4\xac\x00\x3b" + "\xbe\x37\xaf\xfa\xa0\xaa\xf6\xab" + "\x08\xec\x53\x2a\x82\x36\xf4\x65" + "\xe1\x12\x1b\xa1\x01\x58\x9a\x1d" + "\x75\xd4\x0e\xe2\x2c\xab\xa7\x78" + "\xd5\xe0\x41\x9a\x7e\x06\xe1\x0d" + "\xea\x23\x50\x30\x5f\x3f\x47\x30" + + "\xc6\x68\x7f\xf9\x52\xb3\xb7\xdb" + "\x58\xcf\x02\x0b\x50\x3b\x77\x0c" + "\xd9\x96\x1f\x3c\x21\x48\x2e\xea" + "\x15\x18\xe0\xee\xb0\x57\xb3\xff" + "\x39\x80\xf2\xe0\xcd\x24\xc9\xb9" + "\xe4\xfb\xa3\x46\x5a\xc9\x36\x0b" + "\x6c\xdb\x46\x5e\xa4\xae\xaa\x1f" + "\xff\xaa\x28\x19\xc3\x75\xe5\xca" + + "\x6c\xb9\xcb\x70\x2a\x96\x3c\x26" + "\xa9\x24\xd1\xbc\x2a\x36\x34\xe0" + "\x8d\xe5\x2a\x3c\x28\xdb\x20\xf1" + "\x07\xd5\xf6\xfe\x49\x8d\xa3\xb9" + "\xfd\x40\xf1\x1f\x82\x2a\xfd\xb1" + "\xe0\xe7\xae\x20\x30\x2f\x16\xbd" + "\x49\x19\x25\xcb\xd4\xa5\x17\x4e" + "\x3d\x1c\x7e\x4f\x83\xcb\xeb\x2a" + + "\xf9\xf0\x9f\x59\x2b\x8a\x77\x01" + "\x6b\xfc\x04\x81\xd7\x23\xa9\x68" + "\xf3\x4f\x69\xda\xdf\x44\xfa\x5b" + "\x12\x7f\x66\xf7\xdb\x99\x71\x4f" + "\x79\x2a\x6f\xe4\xf6\x8f\x6d\xc0" + "\x1d\x13\xf8\xe9\xad\xde\xb5\x08" + "\x7c\xce\xb4\xab\x59\x9a\x51\x02" + "\x3e\xec\x2a\xb4\xbc\x10\xf7\xc4" + + "\x19\x27\xc2\xc0\xca\xd3\xbf\xd8" + "\x1e\x15\xca\xc9\xe4\x09\x02\xc6" + "\x9c\xa6\xa1\xd9\xb5\x4a\x74\x7a" + "\x8f\x7f\x93\x14\x8b\x04\xe5\x6d" + "\x04\xac\x15\xe1\xd8\x38\x19\x17" + "\xd2\x16\x6b\x1c\x40\x09\xf7\x7d" + "\xe7\x94\x8e\x7f\x63\xb6\xae\xa6" + "\x94\xf0\x2c\x2a\x8e\x38\x30\xc1" + + "\x7c\x33\x6f\x78\x9d\x71\xb6\xcd" + "\x7d\x39\x04\xe7\xd2\x1c\xc0\xd9" + "\xef\x2f\x5c\x55\x20\x3f\x4a\x0f" + "\x23\xf2\x0a\x7c\x09\x25\x45\x00" + "\x76\x8e\xdb\x84\x47\x80\xa5\x54" + "\x06\xaa\xc8\x93\xaa\xf1\xac\x3b" + "\x22\x94\x91\xf7\x7c\x95\xca\x11" + "\x40\xaa\xcd\x78\x53\x10\x64\x50" + + "\x75\xa7\x67\x6c\x31\xb7\x6e\x9f" + "\xb1\xd0\xc5\xef\x1a\x47\x10\xcb" + "\xb2\x06\xb8\xe1\x0c\x75\x33\xb4" + "\x7e\xae\xb1\x57\x4d\x71\xc5\x19" + "\x3f\xfd\x03\xed\x7b\x8b\xdc\xc0" + "\x4e\x19\xbc\x31\x4f\x34\x03\xdd" + "\xb5\x20\x63\x8c\xa7\x52\x6c\xa6" + "\x93\xfd\xb6\xd0\xe3\x2c\xc8\x8b" + + "\x0d\x04\x0b\x0e\x0f\xa9\x28\xb2" + "\x7f\x89\xff\x45\x82\x2d\xf0\xba" + "\x22\x61\xfa\x00\xe6\x79\xac\x2a" + "\x57\xf5\x36\x8e\x17\x88\x82\x24" + "\x56\xc3\x3e\x11\x31\x1d\x52\xb9" + "\xf8\xf1\xef\x15\x1e\x86\x48\x9e" + "\x15\x17\xd4\xe0\x12\xd4\xa1\x2a" + "\xb8\x31\xf1\x53\x03\x62\xf8\x71" + + "\x1e\xc5\x73\x6f\x3d\x48\x2a\x6d" + "\xdd\xc2\x0d\xea\x12\x24\xcb\xa4" + "\xff\x17\xb9\x1e\x41\x3c\x66\x50" + "\x9e\x29\xde\xea\xcf\x74\x3a\x3d" + "\x02\x92\x7a\x4a\x0f\x99\xb3\x29" + "\x3d\x5c\xb1\xa7\x59\xcf\xbc\xa9" + "\x08\x92\xdf\xa5\xdc\xcc\xa3\x66" + "\x29\xf9\xf2\x43\x14\x7c\x02\x48" + + "\xb4\xaf\x8c\x09\xbb\xa3\x44\xe0" + "\xaf\x8c\xd4\x60\x10\x23\xed\x27" + "\x4d\xb8\x31\x3a\x75\x56\x2b\x54" + "\xd7\xbe\xdd\xfc\x50\xdd\xf3\xcb" + "\x30\xd8\xb1\x41\x16\x1f\x03\x25" + "\x27\x1e\x0c\xcb\x1d\x85\xec\xa7" + "\xdb\x75\xae\xb5\xe0\x8f\x1c\xac" + "\x20\x21\xc5\x08\x57\x75\x4c\xb2" + + "\x9e\x03\x07\xd6\x71\x0e\xbb\x1f" + "\x46\x45\x3a\xcd\x15\xe2\x70\x2b" + "\x91\x40\x32\x53\x1d\xf0\xd2\x32" + "\x9b\xb1\x0a\x18\x08\xff\x96\xb7" + "\xaa\xc4\x57\x3c\x86\x7a\xd8\x32" + "\x27\x9a\xc4\xb7\xaf\x9c\xed\x2a" + "\x98\x0d\x63\x31\xac\x5e\xb3\x9f" + "\xa3\x20\x3e\x5c\xdf\x8c\x8e\x33" + + "\x40\x09\xd8\x4e\x8b\x36\x14\x30" + "\xdd\xce\x6f\x7a\x56\xd0\xe6\x67" + "\x9f\x57\x97\xca\x49\x8c\x20\x7c" + "\xf6\x97\x35\xa2\x81\x7a\x3d\xfe" + "\xe2\x6a\x09\x7e\x02\x32\x20\x5e" + "\x66\x93\xb3\x24\xe7\xe1\xf3\xb1" + "\xfc\xdf\xdc\x2f\xf3\x26\xda\x26" + "\x83\xbe\x97\x60\x1d\x2f\x42\x79" + + + "\x81\xb3\xb3\x9d\xfb\x2c\x3a\x26" + "\x4b\x0a\xdf\xd4\xee\x2d\x3a\x9c" + "\x1f\xe6\x04\x7d\xe9\x06\x8d\x72" + "\x25\x93\x44\x42\xbc\xdf\x1a\x8b" + "\x1b\x3a\x05\x7e\x39\xd9\xc1\x6e" + "\x07\xf7\xda\x66\xc7\xe5\x2b\xee" + "\xab\xc7\x0a\x81\x14\x1e\xba\x80" + "\x74\xf1\x30\xf5\x78\xe7\x2a\xdd" + + "\x8b\x9d\x5b\x20\x7a\xd9\x35\x04" + "\xd4\x56\x67\x05\x64\xf0\xb8\x6e" + "\x0e\x21\xf8\xb6\x8b\x8a\xe8\xd5" + "\xea\xd9\x9f\xec\x2d\xf1\x0e\x07" + "\x6a\x87\xcc\x3b\x05\x95\x84\x4d" + "\xe3\x4c\x40\xa7\x38\x53\xa7\x12" + "\x5e\xdb\xa1\xb8\xe1\x49\x2b\xd2" + "\xad\xa5\xbf\x14\x51\x20\x1f\xec" + + "\x36\x8f\x82\xb6\x79\xeb\xba\xad" + "\x9e\x5b\xbd\x01\x58\x02\x7a\x9d" + "\x0c\x4b\x84\x1e\x0d\x1e\xa0\xed" + "\xc9\xdf\x7e\x88\x75\x51\x62\x4b" + "\x21\xb6\x69\x96\xdd\x9f\x10\x14" + "\x98\x7b\xf8\xf6\x56\xca\xa2\x88" + "\xbc\xf6\x0d\x17\x88\xb7\x2e\xfe" + "\xf9\x73\xa4\xff\xf4\x06\xea\x0c" + + "\x33\x3d\xe8\xc4\xb5\x81\xed\x43" + "\x8b\x48\xfd\x5e\x79\x58\xf3\xd9" + "\x0f\x4d\xeb\x9d\x0f\x62\x4a\x16" + "\x94\x73\x6a\xac\xdb\x7b\x92\xc6" + "\x03\x0f\x9e\x9f\xf7\x8d\xc2\x45" + "\xa9\xe1\xd7\xfc\x1e\x66\x68\x28" + "\xf1\x48\xa3\xff\xd0\xe8\xf4\x7c" + "\xe0\x38\x85\x39\x84\xc2\xd4\x6b" + + "\x19\x86\x9a\x28\x91\xa0\x18\x26" + "\x73\xb1\x71\x66\x60\x6e\x79\xef" + "\x32\xc6\x90\x90\xe5\x46\x4e\x66" + "\xfb\xf8\x66\x1e\xd4\x62\x80\xa3" + "\x4e\x27\x73\x05\x20\x4a\x74\x6c" + "\x94\x13\x27\xa9\xe4\x67\x7b\xd0" + "\x20\x0e\xdc\x6b\xb2\x23\x12\x39" + "\xa7\x05\x0a\xeb\xf1\x93\x2d\xbe" + + "\x41\xd1\x36\x3f\x53\x2e\x3e\xf2" + "\x42\xa4\xfc\x4d\xd4\xb3\x4b\xe8" + "\x3a\x02\x7c\x6b\x8d\xa4\x04\xb8" + "\x3b\x1c\x43\x76\xfa\xa8\x16\x1e" + "\xe0\x72\xd4\xdd\xad\x52\x54\x1b" + "\x27\xe1\x1e\x0d\xe7\x5e\x40\x7d" + "\x99\x75\xa2\xff\x1d\x6f\xfc\x50" + "\x35\x1b\x39\xbf\x3c\xc5\x1a\x35" + + "\x6b\x89\x44\x44\xb8\x14\xfa\x7e" + "\xfb\x27\x40\xf9\x2f\x4d\x97\x64" + "\x7d\x48\x84\xde\xe8\xd0\xdc\xef" + "\x9b\x98\x48\x2b\x60\xb2\x45\x8c" + "\x87\x34\x46\xd8\xc2\xbb\xfc\xa8" + "\x6c\x47\xbc\x3f\xf7\xb3\xb2\xd1" + "\xc0\x43\xf4\xc8\xb7\x05\xd0\x21" + "\x9c\x13\xc0\x40\x67\x2e\x8f\x51" + + "\xc1\x5f\xd7\x06\x8c\x6e\x03\x56" + "\x9f\xa8\x49\x32\xb7\x7b\xcf\x2d" + "\xdd\xe7\x45\xe2\x3d\x1d\xdd\x81" + "\xa7\xe2\xd6\xeb\x4b\xdc\x78\xf5" + "\xa0\xe7\x2c\xdf\x03\x89\x02\x4c" + "\xac\xaf\x39\x9c\x88\x62\xe3\xae" + "\xab\x04\x64\x14\x31\x7c\x84\xdc" + "\x18\x78\xe9\xa4\xd8\xc0\x04\x63" + + "\x91\x67\x1f\xa9\xa2\xdc\x51\xae" + "\xfc\x9e\xaa\x9b\x90\x41\xbe\x2a" + "\xc1\x7a\x9c\x55\xf4\xe2\xd2\xd9" + "\x3a\x77\x9f\xfc\x51\x4b\x2f\xe8" + "\x1c\xe8\x73\x40\x27\x30\x71\xa7" + "\xfc\x96\xb5\xfb\xac\x6f\x27\xc0" + "\x0c\xf7\x84\xa6\xc9\x9f\x81\x1d" + "\xe0\xb1\xf7\xc9\xdd\x7f\xb4\x29" + + "\x40\x19\x9b\x45\x03\xe1\x8d\x35" + "\x93\x3e\x01\x5b\x59\x1c\x88\xec" + "\xd3\x2a\x53\x49\x93\x4c\x57\x51" + "\xde\x46\x7b\xb3\x45\xd4\xb1\x2d" + "\xd8\x9f\x23\xdf\x87\x5b\x44\xc6" + "\xee\x24\x1d\x15\x75\xaf\x18\xc7" + "\x59\x62\x3c\xf4\xa4\xc4\xa1\xae" + "\xf7\x02\xbe\x70\xd7\xe5\xc0\x40" + + "\xf2\x33\x1b\x72\xf4\x90\x45\x6a" + "\xea\x04\xdf\xfe\xfb\xf1\x24\x21" + "\xe7\xef\x45\x97\xde\x3c\xe5\xf8" + "\xd9\x46\xf0\x65\x32\x04\xe1\xe7" + "\xe6\xc7\xd0\xe4\x8e\xa2\xfc\xc3" + "\x1b\x3b\x25\x87\x9a\x33\x7e\x84" + "\x43\xe6\x43\x37\x48\x53\x59\x9b" + "\xc5\x2f\xd1\x4f\x0b\x0a\x6a\xcb" + + "\xcc\x2d\xd0\x27\xc3\x36\x68\xfb" + "\xc2\xbc\x68\x7a\x82\x09\xd0\x5a" + "\x2d\x91\x5e\x00\x4c\xb4\x24\x1b" + "\xfe\xdc\x1f\x81\x0f\xd2\x83\xcc" + "\x0c\xba\x6f\x66\xc1\x7e\x52\x36" + "\x35\x46\x75\x14\x97\x81\x94\x69" + "\xc2\xa9\x6d\x55\xa8\xb1\xdc\xfc" + "\xb2\x32\xa7\x81\x67\x42\x93\xa5" + + "\x1d\x18\x14\xa7\xed\x14\x12\xec" + "\x41\xb3\x67\x60\x3b\xc1\x9a\x60" + "\x1f\xdf\x45\xa5\x97\x4c\x4b\xff" + "\x6b\x07\xd2\x34\x01\x05\x24\xa1" + "\x97\xca\x09\x14\x23\x0c\xfa\x6e" + "\x43\x8c\x63\x20\xa8\xc1\x4c\x25" + "\xcd\x46\xfb\xdc\xaf\x63\xe3\xd4" + "\x27\x2a\x94\x03\xc3\xad\xc2\x62" + + "\x83\x64\xe4\x56\xf0\x9d\x7b\xc6" + "\x56\x63\x73\x63\x20\xbb\x5a\xa5" + "\x52\xbc\x51\xc5\x98\xc0\x93\xab" + "\x4b\xe6\x5f\xb1\xf9\x49\x2b\x38" + "\x47\x8d\xff\x4d\xad\x21\xc2\x9e" + "\xd6\xf4\x7d\x43\x15\xf6\xca\x79" + "\x09\x65\x45\xbb\x64\xdc\x13\x5f" + "\x14\x07\x1f\x19\xd9\x89\xc5\xe4" + + "\x09\x0e\xd4\x3f\xab\xa8\xb6\x27" + "\xa9\x3e\x31\x77\x2e\x84\x55\xe4" + "\x8b\x98\x55\x1f\xe2\xd1\x51\x8b" + "\xfc\xbb\x2b\x06\x73\xdd\x16\x57" + "\xde\xf3\x8b\x4e\xe5\x11\x3c\x63" + "\x3b\xbe\x85\x1b\xb6\x77\x0e\x9a" + "\xa6\xcc\x11\x09\x29\x07\x51\x56" + "\x0f\x59\xa6\xef\x95\x64\xe7\x27" + + "\xab\x3a\x0d\x07\x33\x8b\xac\xe4" + "\xe5\xd5\x2c\x9a\x2b\x67\x43\x26" + "\x73\x91\xfc\x1c\x9b\xf7\xef\x52" + "\x3f\xc1\xa7\x90\x9b\xa4\x5c\x66" + "\x98\xb9\xef\xb3\x59\xda\x8d\x5a" + "\x41\x13\x2f\x05\x2d\x92\x5b\x8a" + "\x30\xa5\xf9\x3c\xab\xbb\x9e\xae" + "\xd7\xa4\x6d\xf5\x7b\x6e\x98\x35" + + "\xcc\x13\x35\xff\x5c\x6b\x63\x3a" + "\xdd\xf7\x98\x31\xba\xf8\x0c\xbb" + "\x86\x6f\xf1\x41\x22\x05\xd4\xb8" + "\xbf\xa7\x13\xde\xd8\x75\x05\x76" + "\x81\xa1\x7a\x9f\x16\x4e\xf7\x36" + "\x1c\xed\x09\xf5\xcf\x3e\x3a\x16" + "\x91\xa4\x40\x3c\x1f\xd6\xea\x6a" + "\xaa\xfc\xe8\xdf\xfc\x95\x8c\x15" + + "\x6f\xa4\xcd\x13\x6e\x1b\x99\xa3" + "\xd0\xae\x2f\x34\x15\x24\x48\x79" + "\x70\x59\x6b\x66\xde\x5b\xba\xf3" + "\xdd\xb6\x6a\xb2\xbc\xe6\x52\x1d" + "\x3d\xdd\x08\x86\xe7\xa1\x8b\x76" + "\x86\x65\x07\xea\x2a\xdb\x30\x49" + "\xfa\x1a\xdc\xe7\x14\x57\x57\xd9" + "\x17\x88\xc5\xf7\x7d\xbf\xc7\x1f" + + "\x6c\xe9\xee\xd9\xcd\xac\x47\x6b" + "\x37\xec\x8c\xe5\xfb\x77\xa2\x0c" + "\x2a\xc4\x02\xe7\x13\xe4\x3f\x11" + "\x51\xbe\x7c\xc4\xee\x64\x17\xdd" + "\x39\xd7\x3e\x7b\xde\x7c\x1e\x04" + "\xc0\xe1\xe9\x5c\x59\x74\xcb\x50" + "\x12\xb2\x25\x29\x13\x85\x56\x35" + "\x1c\x08\x1b\x00\xc4\x95\xff\x7c" + + "\x54\xb4\x88\x80\xbd\x4c\xee\x63" + "\x8a\x0c\x9e\x9a\xf7\x32\x7f\xdb" + "\xcb\x47\x24\x6b\x18\xd4\x77\xb3" + "\x9b\x21\x70\xd3\xaa\x82\xe9\xe3" + "\x93\xa5\xa2\xc2\xe4\xc1\xcc\x06" + "\x4f\xf2\x73\x07\x65\x68\xc3\x72" + "\x23\x94\x85\x95\xa7\x4d\x3b\xa1" + "\x8f\x0c\x04\x75\x33\x1d\xbf\x8b" + + "\x91\xc9\x50\xda\x73\x09\x6f\x72" + "\xe2\x6e\x2d\x82\x5b\xcd\xaf\x48" + "\x71\x77\xfd\x20\x8b\x71\xfc\xe5" + "\xa1\x07\x08\xfd\x7d\xe7\xe8\xb9" + "\x3d\x70\xa7\x99\x44\x0f\x5e\x7f" + "\xf3\x36\x8e\x61\x0e\x93\x72\x69" + "\xbe\x7b\x80\x23\xb8\x77\x7c\x2b" + "\x50\xff\x27\xcb\x05\x24\xb8\xe5" + + "\x62\x90\x37\xbd\xe3\x8b\x8b\xba" + "\x92\x4a\xce\x2d\x1d\x7a\x4b\xd6" + "\x37\x2e\x95\xb2\xc5\x73\x0a\x04" + "\xca\xae\x38\xd4\x2e\x25\x9e\x0a" + "\xcb\x3b\x9d\xc3\x6b\x95\x43\xdd" + "\x63\x2d\x2b\xb3\x00\xca\x31\x1a" + "\x18\x7a\x41\x5c\xb8\x33\x71\xd6" + "\xc8\x42\xf4\x2e\x90\x47\x8e\xd0" + + "\x80\x09\x5c\x25\xe9\x1a\xcb\x98" + "\x9f\x73\x4a\x2b\x81\x63\xd8\x4b" + "\xa1\x45\x4a\x1e\xe1\x31\x5c\x5a" + "\x2f\xdb\xb0\x9c\xfe\x55\x5d\x1e" + "\x29\xcc\xf5\x8f\x06\x1b\x66\x74" + "\xf4\xa4\xb8\x0e\x9f\x38\x6b\x02" + "\x24\x8c\x84\x58\xa4\x21\x6b\x53" + "\xb0\x72\xdc\x81\xec\xf8\x5b\x2e" + + "\xac\x6a\x88\xad\xd0\x87\xc1\x03" + "\x45\xb6\x71\xb7\x8a\x87\x16\x5c" + "\xab\x45\x40\xc7\x6f\xfc\x7d\xb0" + "\xed\xca\x00\x78\xbf\x60\x63\x2c" + "\xa3\x72\xc9\xb9\xb5\x5b\x29\x24" + "\xba\x6d\x9a\x7c\x8e\xf8\xe6\xc9" + "\xa6\x9a\xa7\x92\x24\xbf\xff\x90" + "\xc2\x6a\xc2\x41\x0a\xd5\x29\xde" + + "\xe6\xcb\x09\xd3\x83\xf4\x0a\x9f" + "\x4f\xed\xbc\xe0\x8a\x0d\x02\x5b" + "\xe3\x23\x80\xb3\x6d\x98\x6e\x60" + "\x33\x69\xbc\x1a\x9d\x2c\x8f\xad" + "\x93\x0e\x40\xe7\x1d\x2e\x29\x19" + "\x4d\x5e\xbe\x52\xa9\x18\x3e\xfe" + "\xbf\x80\x06\x2e\x1d\x77\xe9\xe8" + "\x63\xb0\x4d\xc5\x98\xec\x5b\x8c" + + "\x1f\x5d\xa5\x74\x2a\x66\xf9\x2a" + "\xd8\x66\x6f\x04\x8f\xf2\xfb\xe3" + "\x94\x47\xdc\xd4\xb4\x2a\xa7\xa3" + "\xd8\x2d\x7c\x5c\x45\x9f\x77\x09" + "\x8d\x9d\xd1\xc3\xaf\xbd\x93\xd8" + "\xdf\xa6\xd6\x57\x94\x50\xa7\xd5" + "\x55\x62\x2e\x95\xf9\xfe\xf8\x8c" + "\xff\x8a\x9a\xda\xfb\x7c\xa6\x3d" + + "\xcd\x0d\x16\x2c\x2a\xf6\x23\x4c" + "\xef\xea\x90\x8f\xe3\xc5\xe6\x34" + "\x5a\x5d\xa6\xa9\x19\x55\x86\x35" + "\x3d\x8a\xd3\x8f\xae\x8a\xc4\x07" + "\x27\x85\x06\x50\xda\xae\xe7\xb7" + "\x6a\x93\x90\x1c\x23\xef\x09\x2c" + "\x4c\x32\x79\xe8\xb6\xfe\xec\x31" + "\x38\xc9\x0e\xfb\x6b\x1f\x87\xa0" + + "\x5d\x83\x4d\xd8\x68\xfb\xf0\xb1" + "\xe6\xc1\x1d\x86\x39\xaf\x0c\xc9" + "\xd7\xf8\x94\x75\x46\xb0\xe5\x12" + "\x92\x2b\x01\x65\xe2\x7a\x89\x26" + "\x5d\x75\xd6\xa4\x08\x8a\xf6\xbc" + "\xda\xfb\x91\x09\x1c\xe4\x3e\x40" + "\xe8\x17\xbf\x3b\x3e\x34\x3e\x73" + "\x65\x3d\x9b\x67\x0d\x98\xc7\xd2" + + "\x05\x13\xe1\xd2\x32\x62\x05\x33" + "\x6f\x7a\xc0\xf3\x92\xe4\x6b\x96" + "\x9d\x50\x15\xbb\xff\x78\x88\x6a" + "\xa4\x59\x9b\x0a\x01\x11\x22\xff" + "\x29\x01\xe3\xab\x4a\x56\x9f\x6c" + "\xcf\x64\x6e\x33\x40\xc9\xf2\xc6" + "\x22\x80\x0c\x8b\x62\x52\xe7\x0f" + "\x87\xdb\xe8\x6a\xe9\x67\x02\xbe" + + "\x2b\x04\xbc\x93\xf1\x92\xe1\x22" + "\x58\xc4\x37\xb2\x34\xb5\x85\xf0" + "\x68\x41\x2c\x83\xbd\x92\xd1\xa0" + "\x1d\x27\xf6\xbd\xe3\xe9\x76\x7a" + "\xb5\x11\x89\xb8\xfa\x82\xa8\x52" + "\xb5\x0e\xdb\xb4\xe4\x45\x53\xc8" + "\xff\xc3\xa7\x81\xa6\x02\xbe\xa3" + "\x69\x04\xec\xf0\x8c\x9c\x88\x51" + + "\xe5\x29\xe8\xa5\x69\x13\x03\x9d" + "\x41\xaa\x07\x16\xfc\xc6\xb4\xcb" + "\xc1\x84\x1d\x24\xa6\x59\xac\x75" + "\xee\xe0\x29\x88\xbf\xf2\x43\xc0" + "\x85\xe1\xa5\x8e\x75\x8f\xa3\x82" + "\x9f\xbd\x7c\xd8\xb9\x40\xda\x8b" + "\x01\xc6\x8f\x2d\x5e\xe7\x65\x9e" + "\xb3\x90\x56\xa3\x74\x5f\x51\x3d" + + "\xac\xe5\x79\xda\x4f\xcf\x4a\x53" + "\x5f\x21\x30\x86\x3a\x3b\xb8\x68" + "\x6e\x75\x85\xd0\x2e\x8b\x74\x5c" + "\xb2\x7c\xd3\xe5\x58\x72\x31\xb0" + "\xc4\xc2\xcc\xc5\x1a\x84\x35\x67" + "\x69\x50\x9d\x3d\x6b\xc9\x7d\x7d" + "\xbd\x54\x17\xfd\x10\xe4\x47\xa1" + "\xd5\xdd\x99\xd3\x94\x6e\x29\x65" + + + "\x3a\xfb\x0c\xb3\xcd\xc4\xe0\xd7" + "\xc8\xb4\x9d\x6c\xc1\xb8\x09\x6d" + "\xdf\xd9\xc8\x07\x42\x1a\xba\x40" + "\x6d\xc6\x52\x1c\xf7\x95\xd4\x6f" + "\xda\x64\x52\x27\x9f\x16\x0e\xfb" + "\x62\x83\x7d\xe5\x46\xb7\xc2\x80" + "\x22\x72\xad\x49\xf7\x87\xd9\xed" + "\x7b\xec\x98\x43\xaf\x29\xc2\xfd" + + "\x58\x6a\x66\x52\x84\xed\xd1\xb0" + "\xc2\xc3\xa9\xe6\x00\x6e\xcb\x4b" + "\x08\x64\x90\x26\x1c\x41\x57\x3c" + "\x00\x64\x55\x13\x55\x07\xc2\xcf" + "\xa3\xdb\x94\x52\x50\x1c\x8b\xa0" + "\x1e\xd3\x7d\x8b\x86\xa2\x0b\xa3" + "\x74\xca\x1e\x99\x0e\xa9\x0b\xd7" + "\xb9\xc2\x62\xe7\x2c\x14\x4e\x09" + + "\xef\x13\x7f\xac\x9b\x43\xea\x88" + "\x14\x7d\x9a\x8d\x3f\x14\xaa\x65" + "\x1a\x2f\xcb\x20\x2d\xcf\xe0\xff" + "\xd1\x6a\x1c\x38\xf1\x7b\x7b\x84" + "\x4d\x0b\xc8\x8a\x14\xb8\xf5\x56" + "\xf2\xaf\xce\x35\x18\x44\x1b\x04" + "\xef\xfc\xa5\xcd\xc0\x88\x90\xde" + "\xce\xb8\x83\xe0\x9b\x51\x68\xe6" + + "\x25\x39\x9f\x97\x3e\x78\x1d\xb8" + "\xa7\x89\x4c\xaf\x0a\x13\xfd\x1e" + "\xfa\xf7\x1b\xfd\x44\x21\x5c\x52" + "\x9e\x5a\x26\x1b\x04\x69\x29\x4b" + "\xb6\x65\xdb\xb9\x34\x96\x8e\xed" + "\x8a\x9d\x59\x03\x32\x2e\xc8\x35" + "\xf3\x63\x35\x40\x4f\xa5\xa7\xda" + "\xab\x38\x2c\x02\xad\x88\xf0\x9d" + + "\xee\x60\x62\x45\xc1\x5a\x69\x1c" + "\x93\x36\x78\x4d\xdf\xce\x3a\x4e" + "\x8f\x4a\x67\x11\x59\x52\xfd\xda" + "\xf9\x22\x7b\x6c\x40\x6d\x84\x21" + "\x55\x1f\x89\x17\xfc\x1c\x3d\x78" + "\x75\x04\x4d\xd7\x34\x3c\x17\x2a" + "\x20\xfa\x99\xb6\x7f\xbd\xfd\x3a" + "\x62\x9f\x82\xac\xb6\x8f\x24\x79" + + "\x0a\xd3\x3f\xbb\x66\xb0\xcf\xe5" + "\x4e\x35\xf0\xef\xda\x69\x91\x42" + "\x6c\xe3\x24\x35\x52\xf8\x9c\x80" + "\x1d\xbe\x55\x01\xb3\x4f\x6f\x13" + "\x12\xa7\xbb\x1f\x01\xaf\x26\x48" + "\xa1\xa1\x6b\x50\xb4\xf0\xf0\x6e" + "\x3e\xa7\xae\x77\x31\x8b\x92\xd9" + "\x4e\x24\xaa\x5e\xf2\x6a\xbf\xe2" + + "\xb2\x1d\xc8\x1a\x3a\x36\x28\x18" + "\x66\x06\x82\x48\xb3\x22\x2a\x75" + "\x6a\xab\x32\x3d\x03\x00\xc0\xcf" + "\xb1\x3c\x6a\xd9\xe1\x77\xd6\x2a" + "\x11\x30\x23\xc8\x72\xe6\xe3\xa7" + "\xb7\x03\x43\x5e\x7e\xe8\x65\x2c" + "\xcb\x04\xdf\xc6\x1b\xf7\x34\x18" + "\x34\xa8\xed\x3c\x2c\x77\xf8\x32" + + "\x4b\xb6\x37\x42\x12\x4f\x08\x8d" + "\x07\xfd\xec\xe3\x99\xbe\x8e\x68" + "\xd8\x5d\x84\xf6\x0c\xa7\xb8\x57" + "\x25\xa3\xa4\x5d\x9c\xc5\x8f\x80" + "\x62\x58\x58\xa3\x2b\x2b\x03\xa9" + "\x86\x93\xf2\xed\xd5\x25\x68\xb6" + "\x9b\xc2\x1e\x43\xdb\xa8\xa5\xb5" + "\xc8\x8d\x1e\x3a\x98\x3a\x14\xbb" + + "\xd9\xd1\xe9\xcf\x07\x6a\x35\x5b" + "\xdd\x48\x6f\x30\x3a\x68\xba\xd4" + "\xc1\x37\x64\x2c\xb5\xe7\x6a\x3b" + "\xd4\x4f\xb6\x54\xa1\xc1\xc0\xf9" + "\xd0\x52\x54\xed\xba\x0d\x66\x90" + "\x0f\x53\x50\x28\x95\x3e\x3f\x42" + "\x81\x4d\x27\x47\x06\xa2\x32\x14" + "\x74\x05\xb0\x7d\xf8\xf3\xeb\xcc" + + "\x1b\x38\xae\x12\xce\x94\xee\x35" + "\x90\xda\xcc\x86\x6c\x17\x7f\x3a" + "\xca\xea\x06\x46\x7e\x65\x3a\xc6" + "\xdf\x04\xcd\x43\x80\xa3\xe5\x9a" + "\x46\x1b\x25\xed\x15\x8d\xec\x9b" + "\x64\x5e\xca\xca\x30\x6d\x5d\x1f" + "\x07\x0f\xf2\x9f\x35\x3b\x7b\x34" + "\x86\xb2\xe4\xf7\x34\xf0\x65\x4d" + + "\x96\x29\xc8\x06\xf6\x81\x9f\xd8" + "\xfc\x92\xc5\x15\x88\x52\x73\x4f" + "\xc6\xa8\x49\xce\xa1\x03\x0c\x8c" + "\x07\x59\xf2\xb9\xe0\xff\x4d\xe0" + "\x4b\xab\xf7\x4a\x50\x21\x66\x22" + "\x4c\x5c\xa3\xf5\xf6\xff\x21\x9e" + "\x98\x91\x1e\x5a\x84\x44\x1d\x07" + "\x11\xfc\x09\x41\x5c\x95\x11\x08" + + "\x1e\x66\x11\xf1\x24\xba\x93\x9e" + "\x04\xeb\x05\xb1\x84\xd4\xce\xed" + "\x78\xb5\x24\xf4\xa1\x9b\xdc\x96" + "\x69\x90\x3e\xe8\xb7\x66\x8f\xbf" + "\x16\x82\xed\xd7\xf4\x4d\x2d\x87" + "\xcf\xbe\x2c\x8e\x77\xf3\x07\xbf" + "\x54\x37\xe7\x98\x99\xd8\x81\x42" + "\x08\x87\xab\x8a\xbb\x5f\xc8\xfe" + + "\x5b\x39\x11\x45\x1d\x41\x28\xd3" + "\xde\xf8\xcd\xe4\x79\xc0\x50\x31" + "\xd0\xbc\x34\x59\xc4\xe7\x4b\x22" + "\xae\xc9\x58\x43\x75\x71\x97\x9d" + "\x4d\xdb\x30\x22\x41\xbb\xb1\xdb" + "\xdc\x31\x8e\x0d\xbd\x84\x8e\x16" + "\xd2\x5f\x11\x1c\x34\x4f\x1b\xa6" + "\x8f\xc2\x88\x58\x15\xfa\x75\xc7" + + "\x0b\x5b\xba\xa5\xee\x0d\x3c\x9a" + "\x99\x52\xd0\x42\xce\x16\xa1\xe6" + "\x42\x2d\xb0\xe9\xfe\x75\x97\xae" + "\xb6\x5c\x54\xa1\x00\x52\xb0\x72" + "\xea\xb4\xa3\x31\x7d\x6f\x50\xbc" + "\x32\x9b\xbd\x8b\x78\x30\x89\xe5" + "\x97\x2a\xb1\xe4\x37\x5f\xbc\xc8" + "\x71\xb6\x73\x4a\x06\x0c\x00\x6b" + + "\x8a\x5f\xde\x17\x5c\x92\xc6\xf3" + "\xd5\x91\x49\xf3\x95\x4b\xcb\xa6" + "\x66\x05\xd5\x7d\xf0\x97\xbf\xa8" + "\x9e\xa0\x91\x0b\xe5\x55\x8d\x2c" + "\x20\xe7\xd7\x3a\xed\xc2\xdc\x6a" + "\x5a\xec\x93\x00\x48\x23\x4a\x73" + "\xaf\x36\xcb\x43\xbe\x8f\x1d\xfa" + "\xe4\xa7\xa8\xa4\x1c\xb8\x87\xdc" + + "\xd0\xa7\x5f\x76\x22\xbf\xb5\x13" + "\x70\x53\x6a\x1d\xf0\x5b\x80\x59" + "\x98\xdb\x80\x42\x9d\xe2\xa5\x67" + "\xe3\x1c\x6b\x77\x6f\x91\x53\x4f" + "\x26\xf6\xdd\x33\x1f\xf6\x4f\x71" + "\x03\xd1\x85\xa0\x8e\x23\x06\x42" + "\xe3\x9e\x80\xe5\xb7\xd4\x50\x1c" + "\x1d\xeb\xf8\x85\x0d\x45\x9f\x99" + + "\x25\xf3\x39\xa2\xb1\x04\x39\x5f" + "\x90\xad\x58\x1a\xf7\xa6\x26\xd0" + "\xed\x24\xb8\xd6\x36\x27\x54\x43" + "\xb8\x64\x93\x4a\x75\xa7\x41\x08" + "\xe9\x1d\xeb\xcf\x41\xcb\x97\x75" + "\x4f\x0a\x58\xbf\x7a\x2b\x25\x20" + "\x20\x8e\xc4\x17\x81\x92\x72\x37" + "\x71\xa0\xf5\xc6\x28\x1c\xdb\xda" + + "\x9b\x9e\xc7\xe4\x51\x60\x8a\x65" + "\xea\x9f\x6a\xc6\x73\xcb\x94\x13" + "\x23\x7b\xbe\xc6\xd5\x1e\xf3\x27" + "\xfe\xf8\xa6\x5a\x36\x8f\xc8\xf4" + "\x9e\x49\xaa\x4a\x1f\x72\xb0\x0f" + "\x6b\x2a\xfb\xe3\xd5\xa7\xb3\x68" + "\x1d\x85\x92\x3a\x7d\x09\x88\xa7" + "\x13\x49\x6f\xe9\x8a\x7f\x0e\x06" + + "\xc1\xfd\xdb\x88\xe2\x0c\xfa\xf1" + "\x08\xdd\xf8\xd2\x80\x74\x39\x3c" + "\xf0\x95\xdb\x4e\x8b\x0a\xf1\x0e" + "\x56\xe5\x47\x32\x75\xbc\x58\x45" + "\xa4\x4f\xc0\x0f\x5f\xef\x5c\x76" + "\x75\x3d\x6d\xd6\xe6\x2c\x9f\x72" + "\x66\xf0\x33\xb4\x5d\x27\x35\x6d" + "\x7e\x59\x4e\x36\x27\x5c\xd9\x31" + + "\xbc\x93\x3a\x1a\x73\xbe\xee\x82" + "\x1a\xdc\x1a\xa2\x65\xf4\xbb\x42" + "\xfd\x0e\x03\xef\xa4\x6f\x0b\xc1" + "\xbb\x97\xb0\x87\xc7\xa4\x7a\x24" + "\xda\x77\x0c\xf6\x32\xc6\x8d\x8b" + "\x3e\x52\x23\xc2\x6a\xc2\xfb\x6f" + "\xcf\x79\x45\x34\x11\xff\xf6\xa4" + "\xf6\x50\x02\x98\x3c\x65\x25\x58" + + "\x8b\x39\x1f\xcc\x9a\xef\xea\x88" + "\x95\x7e\x21\xf4\x25\x9a\x18\x85" + "\xef\xfc\x68\xb9\xf5\xf5\x24\x94" + "\x28\x22\x07\xd0\xf9\x8a\x5d\xc0" + "\x2a\xb2\xa1\x49\x8c\xfa\x36\x0b" + "\xce\x5f\x11\xf1\x57\x36\x1c\xe6" + "\x3f\x43\x62\x42\xc0\xf0\xcd\x06" + "\xdc\x20\xc8\x9e\x2d\xc5\x8a\x9d" + + "\xb9\xa2\x1a\xbc\x7e\x09\xdd\xb2" + "\x3a\x33\xa0\x37\x93\x93\x88\x07" + "\x38\xdb\xa0\x37\x71\x5e\xf5\x1c" + "\x13\x16\x2c\x79\x7f\x48\x48\x26" + "\x61\xf2\xce\x3f\x36\x13\xd0\xda" + "\x29\xf1\xab\x0e\x1d\xc8\x39\x62" + "\xe2\x6b\x27\x9d\xde\x61\xe7\x8e" + "\xd3\x6a\xda\x1e\x34\x7a\x6a\x40" + + "\x07\x6a\x02\xd5\xac\x10\x73\x01" + "\x1c\x28\x93\xe7\x54\xc9\x26\x35" + "\x51\xac\x00\x76\xc5\x7b\x6b\x41" + "\xa7\x44\x2b\xd4\x52\x89\x67\x09" + "\xb1\x9f\x04\xb6\xb7\x3f\xda\xab" + "\x7b\xef\xad\xdf\x59\xa6\xb0\x3c" + "\x0d\x0c\x8b\x1b\x72\x31\x79\x58" + "\x1b\x61\x9d\x4e\x6e\x47\x73\xfe" + + "\x31\x3b\x49\x4a\xba\x67\xf3\x4b" + "\x26\xf0\xf7\x9b\x52\x0a\xf2\x54" + "\x4b\x91\x95\x97\x62\xe0\x96\xb6" + "\xac\x36\xf2\x8b\x6d\xb9\xda\xcd" + "\x13\xea\x25\xed\x0a\xc7\xf2\x4f" + "\xe7\xbb\xcb\x81\xeb\x09\x1d\xfa" + "\xc5\x44\x85\x46\x87\x8c\xfc\x88" + "\x17\x33\x6b\x69\x0d\x67\x7a\x84" + + "\x59\x9a\x51\x45\xe2\xaf\x10\x84" + "\x74\xd7\x30\xbc\xaf\x39\x97\x9a" + "\x88\x4a\xf4\xd8\x03\xde\x33\x66" + "\x37\xdb\x5d\x50\xb3\x9b\x6a\xd5" + "\x14\x5e\x81\x46\x07\x7c\x66\x66" + "\xbb\x93\x44\x88\xed\xf8\x28\x22" + "\x82\x48\xab\x17\x1a\x56\xcc\x23" + "\xce\x1b\x1a\x52\x59\x07\x83\x99" + + "\x26\xb6\xbc\x64\x1e\x42\x33\xf1" + "\xb5\xe0\xde\x26\xc8\x38\xa6\xae" + "\x6c\x34\x10\xb3\x0b\x68\xe7\xd6" + "\xd3\xce\xd4\xd5\x97\x40\x6f\xe0" + "\x0b\xa3\x12\x75\x52\x14\x96\x09" + "\x9a\xa5\x89\xe5\xfd\x67\xd8\xf3" + "\x80\xc1\xd0\x52\x4f\x25\x73\x2e" + "\xac\x74\x3c\x33\xa3\xd8\x63\x90" + + "\x7a\x6f\xee\xe2\x44\x27\x14\x12" + "\x3f\x60\x21\x65\x10\x9d\x38\x63" + "\x3a\x81\x9c\x9e\xc7\x82\xcd\xa1" + "\xeb\x42\xe3\x5a\x1c\x64\x09\xc1" + "\xe9\x06\xbb\x04\x30\xfb\x85\x3c" + "\x7f\xf1\x12\xc2\x1c\x44\xed\x1f" + "\x53\x1a\xf6\x82\xac\xdf\x56\x16" + "\x5f\x8f\xd9\xce\x30\x7a\xec\x88" + + "\xbc\xe7\x14\xd3\x95\xc5\xa6\xed" + "\xed\x99\x78\x46\x4b\x46\xe7\x2e" + "\xd3\xd5\x1e\x0a\x3c\x42\xef\x1c" + "\x13\x76\xcc\x69\xea\x76\x7e\x21" + "\x17\xa9\xcd\xe7\x1f\xce\xcc\x27" + "\x16\x3f\x89\x8a\x6b\x01\xd8\x12" + "\x6b\x4f\xc7\x9f\x84\xde\xd6\xbc" + "\x61\x4e\x14\xf3\xe2\x17\x58\xfa" + + "\xce\x5e\xc5\x9b\xb5\x39\x89\x0b" + "\xff\x70\xaa\xcb\x3b\xb3\x64\xb1" + "\x91\xb7\x2a\x3f\x0f\x01\x6b\xaf" + "\x37\xcb\x52\x7b\xba\x67\xb7\x98" + "\x41\x65\xf8\xfc\x80\xf3\x0d\xbd" + "\x4a\x01\xa1\x64\x54\xf3\x94\x51" + "\x25\xf6\x35\x4c\x2e\xf2\xc1\x42" + "\x1b\xf5\xbb\xf7\xe2\xf3\x70\x9a" + + "\x4c\xee\x21\x08\x64\x41\x35\x1f" + "\x92\x19\xc6\x0b\xb4\xea\x83\x15" + "\x9f\x87\x72\x1d\xf6\xca\x90\x74" + "\xb2\xe7\x6a\xf7\xf3\xd9\x8a\x99" + "\xf7\x57\x11\xa4\x50\x19\x18\x1e" + "\x7e\x3a\xda\xe8\xe6\xe1\xd7\xa9" + "\x5f\xb9\x26\x84\xeb\x84\x37\x96" + "\x10\x2a\x2e\x54\x6e\xed\xe4\x0e" + + "\x83\xfd\x12\x96\xb8\x35\x4d\xbc" + "\xe9\x05\x40\x5c\x50\xca\x77\xf4" + "\xd1\xec\x7e\xa8\x3d\x20\x62\xb7" + "\x86\x25\x08\x38\x22\x9b\xac\x68" + "\x91\x35\x78\xcc\x59\xd6\x96\x66" + "\xb4\x52\x63\xd3\xdd\x43\x46\x25" + "\x69\x1d\xad\x9d\xd9\x70\xe3\xcd" + "\xfa\x5d\x71\x62\x6c\xf2\x7a\x9d" + + "\x7b\x1e\x75\xac\xc5\x4c\x9d\xb7" + "\xbd\x11\x42\xfd\x72\x64\xf9\x93" + "\xc6\x4f\xde\xc8\xd2\xd3\x72\x8c" + "\x64\xf0\x44\xdf\xf5\xcb\x69\x7b" + "\xe1\x94\xbf\xf4\xa2\x0c\xa9\x3d" + "\xe2\x94\x28\xf1\xf8\x25\x53\x1a" + "\x0b\xd6\x17\x79\x6c\x7f\x43\x0a" + "\x5d\xcb\xc9\x96\x86\x04\xe7\x9b" + + + "\x26\x7c\x33\xe1\x76\x99\x9c\x94" + "\xe5\x68\x3d\xd7\xbd\xde\xaa\x6f" + "\xd9\x68\xb7\xf1\x14\x86\x15\x9e" + "\x69\xf0\xc4\x9c\x57\xa5\xdf\x22" + "\xd6\xc6\x93\xbe\x17\xda\xd6\xcc" + "\xb9\xf5\x04\xa5\x61\x6c\x86\x24" + "\xa1\x4d\x69\x8d\x3c\x35\x21\x21" + "\xc6\xb8\x40\x01\x80\xa5\x6c\x1c" + + "\xb8\x9b\xb7\xd4\x7d\x4a\x60\xf1" + "\xc8\x78\xc8\x52\xfb\x06\xe8\xae" + "\xe8\xb8\x47\x8d\x11\x4f\x14\x34" + "\x54\x90\x9f\x94\x2b\xf5\xed\x72" + "\x5a\x01\x27\x21\x4e\xa8\xfc\xeb" + "\xf3\xce\xb7\x9c\xc0\xd0\x51\x90" + "\xc8\xee\x6d\x29\x58\xfe\xe8\x86" + "\x74\x0d\x01\x41\x88\x81\xb2\x33" + + "\x40\x9f\xed\x9a\xed\x60\x56\xbd" + "\x99\x8c\x2a\x53\xd1\x6a\xca\x70" + "\xea\x71\xc3\x95\xfb\x8b\x97\xc4" + "\x9d\x10\x03\x70\x0d\x4d\x46\xe5" + "\xef\x35\xe5\xd9\xdf\x2f\xf3\x1a" + "\x5b\x18\xc9\x98\xa7\x7e\xf5\xab" + "\x88\x24\xb4\x12\x17\x74\x7a\xed" + "\xfa\x86\x72\xe9\xa7\x96\x02\x8e" + + "\x5f\x44\x1b\x17\x83\x93\x07\x01" + "\x4c\xad\x31\x81\xe3\x21\xcf\x9b" + "\xe8\x87\x39\xc9\x05\xe2\xdf\x8c" + "\x8f\x8c\x2e\xc9\x52\x41\x3f\xe6" + "\x3d\xd4\xad\x30\xa9\x62\x94\x72" + "\x5a\xf0\x80\xc9\x43\xb1\xeb\x62" + "\x68\xe9\x06\x3b\xe5\x54\x39\x4f" + "\xb1\xf6\x2c\x24\xad\x75\x1d\xfe" + + "\x5e\x7d\x01\x1f\x6e\x41\x57\x8b" + "\x9b\xe9\x74\x76\x96\x33\x53\x37" + "\xa0\x88\xf4\xe8\xc0\x94\x6d\x6e" + "\x5e\xf9\x16\xdc\x7a\x78\x3a\xb9" + "\xcc\x9c\xc9\xdc\xa2\x51\xac\xc3" + "\x1d\x7c\xa4\x9a\x13\xb4\x34\xc1" + "\xd5\xd8\xdf\xaf\xaf\xcd\x8f\xf2" + "\xed\x31\xb8\x10\x8e\xbd\x57\x0d" + + "\x46\xfc\xbc\xf0\xcc\xfb\x76\x92" + "\xe6\xfe\xcf\xb5\xce\x2a\x82\x3a" + "\x5b\x91\x5d\xc7\xfe\xd2\x8e\x32" + "\x6c\x47\x59\xc3\x13\xc1\x45\xa1" + "\xcd\x7b\xe1\x8b\x53\x81\x1a\xf6" + "\x8f\x3d\x6c\xaa\xc3\x67\xe8\x01" + "\x2f\xc8\x16\x65\x5d\xe1\x34\x56" + "\xb0\xb9\x48\x69\xd2\x7b\x43\xc1" + + "\xc7\xd4\x19\x6c\x00\xd2\xfc\xd2" + "\x76\xe9\xb1\xe1\x37\xc4\xf3\xa0" + "\xe8\x37\xf2\x94\xf6\x5f\x54\xf0" + "\xb1\x8b\xbf\xc0\x3f\xec\x10\xdd" + "\xe1\xd3\x7c\xac\x6c\x69\x89\x4f" + "\xe6\xbf\x24\x5f\xec\x14\x37\xed" + "\x06\x77\xaf\x5f\xd8\xb1\x3e\x36" + "\x32\xcc\x27\xc0\x4d\x60\xbd\xfc" + + "\xc8\x85\x86\xaf\xc7\xc6\x95\x5f" + "\xaa\x01\x8f\x2f\xce\xc8\xc1\xd4" + "\x2a\x69\x74\x25\x32\xbe\x4b\xc4" + "\x68\xa0\xa4\xd4\x78\x34\x00\xb8" + "\xdb\x3c\xca\x2e\xe5\xc6\x8f\x7c" + "\x99\xd3\x04\xec\x6b\xb1\x1d\xea" + "\xcf\xc5\x2b\x8f\x2e\xc8\x5b\xb0" + "\xd2\x93\x47\xf4\x7f\x51\x3d\x76" + + "\x3b\x36\x55\xc3\xdd\x8e\xce\x16" + "\x6e\x0d\x82\xf8\x0f\xf7\xf2\x4a" + "\x08\xa5\x61\x76\xd2\xd4\x7e\xcb" + "\x72\x54\x19\xdd\x4e\x44\xd3\x41" + "\x49\x96\xda\x38\xb4\xa2\xfe\x17" + "\x00\xa2\xb4\xae\x56\x93\xf6\x9b" + "\x3d\x9c\xb1\x6a\x91\x5f\x3b\xa1" + "\xa6\x60\x93\xdc\x14\x9c\x51\xc0" + + "\x71\xe1\x42\x2e\xe9\x1a\x57\xc2" + "\xf9\xcc\x41\xed\x63\xab\x31\xcb" + "\x4f\x85\xc8\xb5\x76\xc5\xf3\x37" + "\xa1\x92\x23\xc6\x1b\x19\xe5\x66" + "\x3b\x68\xd5\x6c\x1c\x5a\x56\x71" + "\x89\xe6\x6f\x60\x83\x02\x4b\x48" + "\xa6\xfd\xe2\x67\x67\x5d\xa2\xf3" + "\xa4\xc0\x65\x8a\xde\x21\xba\x87" + + "\xd1\x84\x06\xa7\x9c\xe4\x74\xde" + "\x3d\x0c\xe8\x33\x61\x76\xe8\x3a" + "\x4d\xc3\xa5\x16\xa9\xa2\x84\x59" + "\x35\x8c\x29\xb8\xcc\x3e\xa8\x09" + "\xc0\xa4\x4c\xaa\x7c\x86\x19\x9a" + "\xff\xb8\x75\xb3\x10\x56\x08\x02" + "\xdc\x96\x03\xf7\x8b\x32\x96\xf2" + "\x63\xae\x6f\xde\x4c\xdc\x9d\x9c" + + "\xd0\x98\xbd\x08\xb8\xc1\x51\x44" + "\x40\xf2\x75\x65\xd4\x1c\x4b\x64" + "\x70\xd2\x75\x73\x33\xeb\x07\x69" + "\xbd\x86\x22\xfa\xbd\xbe\xc8\x56" + "\x46\x2b\x63\xc4\xac\xd2\x13\xc7" + "\x42\x02\xd6\xaf\x7a\x42\xda\x17" + "\x46\x75\x5c\xc9\xb7\x65\x30\x31" + "\xde\xa3\x17\xbf\x98\x98\x23\xf8" + + "\x6e\x3b\x08\x0b\x26\x3d\x68\x94" + "\x4d\xa5\xf6\x06\xeb\x52\x37\x0a" + "\xdd\x74\x20\x75\x23\xdc\xbe\x48" + "\x93\x25\x82\x3e\xfc\x22\x76\x63" + "\x3b\x5d\xe5\x6b\x13\x05\x00\xea" + "\x6d\x00\x4d\x32\xf4\x12\x5e\x9f" + "\x70\x02\xfc\x64\xa9\x86\x94\x52" + "\xe6\x99\x33\x92\x0c\x0d\xba\x09" + + "\x80\x70\x97\x3a\x47\x58\x38\x36" + "\xb6\x6a\x6a\x0c\xb8\xe1\xf8\x4c" + "\x1e\x26\x82\x04\x6c\x5c\x9a\x91" + "\x06\x48\xce\xe5\xd0\x9a\x7a\x51" + "\xaa\xa7\x6a\x05\x0c\xd4\x92\x27" + "\xb0\x61\x6c\xe5\xda\x6a\x7c\x4c" + "\x0c\x9e\xb1\xa4\x78\xb1\x9c\xf1" + "\x7f\x26\xba\xe4\x4f\x5c\x6d\x04" + + "\xb3\x50\x15\x12\xab\x26\xe9\xd3" + "\x84\xce\x47\xc1\x4a\x5e\x97\xe4" + "\x2a\x72\xff\x5e\xf9\xe0\x8b\x7a" + "\xa0\xf2\xd4\x6f\x2c\x70\xe4\x71" + "\x80\xb2\xb7\x3c\xcf\x2a\xb9\x13" + "\x73\x2d\x27\x28\x6d\x71\x88\xc5" + "\x5c\xfe\xa9\xda\xf3\x7b\x2c\x86" + "\x42\x9e\xa7\xe2\xf2\x08\xc0\x78" + + "\x20\x03\x83\x4c\x3f\x96\xb7\xf3" + "\xe3\x03\x32\x90\xa0\x7a\x2c\x84" + "\xfb\x7a\x32\xe7\x0a\xca\x22\xaf" + "\xb6\x09\x76\x96\x92\x30\xe1\x38" + "\xf1\x58\x75\x75\x62\xfb\xb8\x73" + "\xc1\xa8\xec\xf7\x31\xe8\xc3\x3c" + "\x27\x16\x33\xf6\x74\x44\x17\xe4" + "\x34\x02\xc4\xc3\xca\x89\x79\xa7" + + "\x1f\xfa\x36\xf5\xc5\x32\x58\xed" + "\xa4\x44\x82\x92\x55\x3f\x6f\xe1" + "\x90\xe1\x5b\xbf\x21\x26\x3a\xf4" + "\x2b\x6b\x2b\xca\xc3\x72\xd6\xf7" + "\x83\x5b\x7a\x82\x45\x62\xf8\x64" + "\x72\x7f\xe9\x00\xf5\x09\xa1\xc1" + "\xbb\x27\x73\xa4\x5c\x78\x59\xc2" + "\xb6\x62\x6a\x7f\xe9\x09\xf1\xda" + + "\x20\x51\x56\x57\x18\xdf\xab\x88" + "\xf1\x2b\x5f\xf2\x72\xbc\x34\xbf" + "\x40\xea\x83\x62\x22\x6a\x21\x0c" + "\xe4\x18\x2e\x07\x46\x20\x3d\x57" + "\x36\x81\xbe\x11\x6a\x0f\x11\x11" + "\x1b\x86\xe4\xd6\x84\x2a\xf3\x10" + "\x31\x75\x29\xee\xe2\xde\xed\x3e" + "\x69\x42\x40\xd3\x99\x7f\xf3\xb3" + + "\x3a\xd4\xc1\x1c\xe9\xf5\xa3\xce" + "\xf4\x3a\x23\x6a\xdb\xca\x4a\x62" + "\xc2\xe7\xef\xd0\xa9\x18\xdf\xc9" + "\xf3\x79\xba\x79\xe8\x0b\x0d\xfe" + "\xea\xf5\x2f\x52\x56\x5a\x4c\xc7" + "\x4e\x51\x7d\x6c\xf0\x79\xc3\x4a" + "\x9f\xa2\x0e\xd7\x04\x14\x92\x64" + "\x70\xf2\x69\x02\x91\xe5\x3e\x44" + + "\xe0\x81\xa0\x44\xa1\x17\xfd\xe5" + "\x6a\x29\x0e\xb7\x7d\xfb\x97\xd7" + "\x9c\x71\x1f\x48\x30\x2b\x47\x2b" + "\x52\x8c\x6f\xfe\x98\x2a\x63\x0e" + "\x84\xc2\xf0\xc5\x16\xd1\xcc\x89" + "\x62\x7c\x98\x2d\xaf\x88\x10\xf5" + "\xcf\xe6\x2d\x4c\xda\xcc\x2b\x2a" + "\xf9\xf0\x79\xf6\xfe\x9e\x0f\x81" + + "\x39\xa5\x1e\xa6\x43\xf4\x74\x38" + "\xdf\xfe\x06\xc2\x11\xa3\xa3\x90" + "\x85\x87\xbd\x0f\x5b\x7b\x2a\x96" + "\x8b\x1c\xc3\x58\x70\xe9\x37\xfc" + "\x48\x10\x1a\x5f\x38\x55\xeb\xcd" + "\x55\x62\xcd\x8c\x22\x51\x20\x5a" + "\x8b\x1b\x4f\x9c\x96\xd4\x62\x97" + "\xde\x05\x2f\xd5\x03\x88\x3d\x21" + + "\xf6\x73\x4c\xe5\x7b\x37\x64\x7c" + "\xc0\xfb\x4e\x5a\x04\xfe\xbf\x65" + "\x41\x85\xf5\x36\x63\x30\xd2\xd0" + "\xf0\xbd\xcd\x25\x6f\x06\xd6\x54" + "\x5b\x6d\xf8\x5c\x63\x2d\x5f\x68" + "\xe5\xf6\x2e\xf1\xc1\xe9\x51\x8e" + "\x82\x6d\x34\xcb\x2d\x04\xaf\xa6" + "\x6f\x81\x73\x00\x79\x50\x95\x37" + + "\xf4\xf7\xc5\x13\xa7\xd3\x9c\xc8" + "\xed\x2e\x35\xac\x4e\xb5\x9c\x0d" + "\x88\x47\xb3\x33\xee\x7a\x2e\x46" + "\x9a\x8d\x99\x7c\x43\xf1\x1a\x83" + "\x87\x4f\xe0\x11\xc9\x02\x88\xed" + "\x69\xd9\x38\x19\x0b\xa0\xa1\x1c" + "\x10\x93\xbb\x7b\xb4\x5b\x80\x52" + "\x10\x64\xc1\x31\xe4\xcd\xa3\xca" + + "\x3e\x4b\xfe\x7f\xb9\x94\xf3\xb0" + "\x21\x5d\xfa\xe5\x21\x1d\x69\x0b" + "\x75\xbc\xfb\x9d\x47\x77\xbd\xb0" + "\x00\x8b\xf7\xfa\xda\x0f\x83\xd2" + "\x57\x4f\x43\x52\x9c\x24\x8c\xf7" + "\xab\x6d\x09\x98\x45\x75\x1f\x4b" + "\xb3\xc0\xf8\x8f\x94\x6f\xbf\x73" + "\x4c\x13\x4e\x45\x3d\xf0\xae\x34" + + "\x59\xc0\x0b\x39\xd5\x56\xb8\x2e" + "\xdf\x12\x13\x04\x5f\xbd\xea\xc0" + "\x7b\xd6\x36\x86\xdf\x45\xef\x7e" + "\xb5\x7f\xea\xdf\x1f\xe8\x09\x69" + "\x37\x77\xda\x31\x53\x8c\x8e\x62" + "\xbc\x55\x5b\x75\xe3\x8b\x2f\x1b" + "\xd7\x41\x78\x13\x12\x05\xba\x35" + "\x7d\xe5\x7c\x31\x59\x03\x55\x59" + + "\xc9\x6d\xd1\xf5\x07\xd4\x51\xb2" + "\x1c\xcc\x72\x4c\xaf\xaa\x1f\x54" + "\xcc\x73\x81\xe5\xac\x70\x81\xd2" + "\x5a\x1b\x0c\x7b\xc5\x57\xc0\x1c" + "\x74\x23\x06\x21\xe6\x74\xb2\x04" + "\x79\x8c\xcb\xe2\xa7\xca\xac\xef" + "\x95\x94\xea\x24\xec\xc3\x66\xc4" + "\x15\x7c\xef\x67\xf3\x6e\x51\xc3" + + "\x1c\x5c\x57\x45\x3b\x00\xef\x34" + "\x0c\xfe\xc2\x49\xa0\xe7\xb3\xde" + "\x63\x9c\x14\xf7\x1d\xc0\x8e\x04" + "\x6c\x98\x9a\xc7\xb9\x69\x38\x20" + "\xef\x80\x1e\x6c\x83\x40\x7c\xcf" + "\x47\x44\x29\x8e\xd5\x17\x0e\x21" + "\x1c\x60\x12\x12\x2e\x7d\x50\x2b" + "\x79\xe2\x17\x5a\xfa\xd3\xed\x98" + + "\xc5\x7e\xac\xb7\xf4\x51\xd1\xf8" + "\xd5\xa7\x0d\xe5\x5a\xb9\xce\xd6" + "\xb8\x0e\x3a\xdc\xb0\x92\xb4\xa1" + "\x63\x28\xdd\xb3\x69\x7b\x15\x75" + "\x62\x3d\x41\xc5\x4e\xc7\xc4\xe2" + "\xc7\xc4\x5f\xbc\xf7\x9f\x32\xbe" + "\xda\x9d\xfa\x60\xea\x2a\x5a\x83" + "\x87\xcb\x45\x74\xad\xf5\x17\xf1" + + "\x1d\x69\x1d\xe9\x36\x26\xf4\x9b" + "\xe4\x7b\xc0\x8f\x42\x32\xcc\x0b" + "\x90\xaa\xe9\x69\xae\x5c\x20\x5b" + "\x5e\xf7\x9c\x39\x2b\x72\x69\x6f" + "\x35\x42\x42\x79\xf6\x59\xb0\x3d" + "\x63\x54\x20\xa2\x04\xb4\x98\x6b" + "\x51\xf4\x60\x6f\xe4\xf5\xca\x68" + "\x9e\x93\x08\xad\x66\xfc\xf1\xe8" + + "\x1f\xb2\x46\x63\xd4\x1b\x66\x36" + "\xf0\x9d\xb6\x3c\x1d\xb0\x6f\xde" + "\x0a\xb4\x84\xa8\xe4\xa0\x05\x7d" + "\xbf\x4a\x3d\xef\xd4\x69\x25\xd9" + "\xf8\x61\xb2\xe6\xe1\xd7\x2b\x1c" + "\xef\xdb\x4d\xc7\xe5\xb0\x03\x05" + "\x37\x4c\x9a\xe0\x39\x1a\x36\x6a" + "\x73\x84\xff\xe7\x08\x75\xd5\x7f" + + "\xf8\xed\x76\xc7\x67\xfd\x39\x19" + "\x8a\x84\x5c\xcb\x70\x7c\x84\xd0" + "\xd1\x03\xde\x5a\x91\x53\xf5\x4f" + "\x3e\x82\xa9\xcf\x83\x4d\xb5\x8f" + "\x04\x4e\x0d\xf1\x6e\x14\x08\xb3" + "\x36\x2a\xcb\xb6\xb3\x91\xa6\x14" + "\x7f\x65\x20\xc6\x93\x9b\x41\x2f" + "\x7f\xda\xe1\xd3\xa2\xaa\xb7\x4d" + + "\x7a\x6f\x16\xb0\xf4\x17\x83\xae" + "\xe6\x74\xec\xce\xf7\xe3\xd3\xfb" + "\xfd\x4b\x87\xe0\xac\x16\xb5\xfd" + "\xa3\xf3\x81\xc6\x19\x60\x84\x3d" + "\xb0\x20\x16\x7c\x5c\xee\x12\x0b" + "\x01\xc5\x63\x2b\xdd\xb4\x68\xba" + "\x1e\xc5\x68\x66\x32\xcd\x03\xac" + "\x5b\xcb\x0b\x4e\xf7\x79\x62\x2a" + + + "\xa8\xcd\x5f\x8f\x9f\x13\x8e\xfd" + "\xfd\x5b\xee\xbd\xc4\x58\xe5\xf3" + "\x77\x9f\x3f\xe3\xf4\xba\x6c\xd7" + "\x69\x19\x77\x71\xa4\x97\x4c\x3a" + "\xa7\xe6\xdc\xf6\x4b\xe8\x27\xda" + "\xd1\xc2\xe6\x13\x96\x3d\x37\xff" + "\xe9\xa6\x59\xd7\x3c\x19\x15\xf1" + "\x2c\x26\xd2\x63\x25\x70\x9b\x3f" + + "\xc8\x5c\x33\x1a\x91\x84\x31\x8c" + "\xe4\x13\x59\x6a\xba\x59\x34\x56" + "\x19\x29\xb3\xc7\x61\x0d\x92\x1b" + "\xad\x25\x24\xa0\xb6\xb8\x5a\x80" + "\x86\x60\x00\x8d\xda\x12\xc5\x2a" + "\xfd\xc0\xf5\xbc\x6a\x84\xa4\x6c" + "\xd7\x38\x21\xac\xd8\x51\xea\xaf" + "\x43\xd4\x4c\x34\x45\x75\x64\xcb" + + "\x85\xca\xed\xcd\x66\x24\x1b\x9f" + "\x8c\x53\x09\x1a\x10\xb7\x0b\x14" + "\x5d\x11\x11\x5e\x51\xe8\x8a\xac" + "\x9e\xf5\x03\x6f\x67\xff\x63\x0d" + "\xfb\x4a\x23\x7d\x51\x55\x5e\x75" + "\xc1\x8f\x20\x7e\x4e\xdb\xc2\x61" + "\x5d\x4b\x8a\xf2\xce\x59\x98\xaa" + "\x0f\x03\xaf\x34\xfc\xd4\xd6\xbd" + + "\x74\x47\x54\x53\xe4\x53\x10\x51" + "\xbc\xa2\xdb\x3a\xcc\x0e\x4d\x83" + "\xf5\x71\xe3\xba\xf7\xd7\x15\x42" + "\xbc\x63\x86\x6c\xbf\x57\xfd\xfc" + "\x1d\x1b\x90\xd6\x3d\x38\xd2\xde" + "\xc3\x7d\x58\xb5\xb4\xfb\x49\x3b" + "\x62\x5f\x62\x07\x8d\xa0\x44\xfd" + "\x62\xb7\xe9\x9d\x5b\xd6\xe4\x3e" + + "\xde\x15\x78\x71\x6e\x4b\x99\x5a" + "\xd1\x31\xe1\xa7\xa0\xc7\x95\xd9" + "\xaa\x23\xc0\x26\xf2\x6d\xb4\xc8" + "\xed\xfc\x2a\x70\x4d\x09\xfd\x8c" + "\x86\xa8\xd6\xce\xcd\x43\xc7\x7b" + "\x75\xbe\xca\x1f\xc4\x0e\xd7\xb7" + "\x90\x93\xac\xdd\x47\x9e\x6c\x2a" + "\x90\xaa\x10\x93\x25\x94\x06\x72" + + "\xeb\xd0\x64\x54\xf5\x80\x7e\xd1" + "\xa7\x13\xa6\x67\xa7\xe1\xd3\x89" + "\xad\x7d\xc9\xc8\x60\x12\x79\x77" + "\xe7\xcb\xf0\xe4\x1f\xf2\x2f\xec" + "\x10\xbc\xe6\xe9\xc2\x4a\x98\xed" + "\x05\xa3\xcb\x77\xe8\x3d\xc5\xe3" + "\xdc\x4f\x62\x83\xb2\xf9\xba\x9b" + "\xec\xc0\x85\x14\xcd\x51\x94\x5e" + + "\xc8\x1e\x76\xb1\x6d\x75\x13\x1f" + "\x55\x7e\xb9\xa4\x98\x8b\x3c\xe5" + "\x28\xcc\x96\x40\xf8\xe3\xae\xb2" + "\x8d\x1a\x0f\x92\xa0\x61\xc3\x48" + "\x0a\x19\x31\x8c\x2d\x67\x8b\xa9" + "\xd4\x55\x18\x00\xd1\xe7\xc1\x7b" + "\x2a\x4b\x3f\xbf\x07\xfb\x2c\x24" + "\xc4\x8b\xa2\x32\x3f\x4a\xf4\x9b" + + "\xfa\xd1\x63\x0d\x7d\x13\xe5\x64" + "\x9f\xd8\xa9\x02\x52\xc0\x8f\x65" + "\x09\x63\x43\x50\x74\x48\x89\x48" + "\x61\xda\x98\xd5\xf8\x30\xae\xe9" + "\x91\xaf\x8b\x81\xd1\x10\xd7\x2e" + "\x20\x0c\x6a\x8b\x06\x9e\x7e\xe2" + "\x44\x6b\x1a\x1c\xfb\xdc\x28\x1e" + "\xdc\x57\xac\xd6\x64\xcb\x3a\x88" + + "\xa5\x76\xe1\x42\xac\xe2\x82\x99" + "\x64\x2b\x78\xe2\x46\xba\x4e\x32" + "\xf5\x50\x83\xe1\xaf\xaa\x8c\x3d" + "\xca\x74\xd6\xf5\xf2\x2a\xd8\xf3" + "\x1e\x0d\x60\x56\xed\x0f\x09\xc2" + "\x07\xde\x50\x59\xef\xe0\x48\x45" + "\xeb\x4f\x5a\x76\x3f\x02\xf0\xb2" + "\x90\x67\xf1\x39\x33\x10\x03\xb3" + + "\xb3\xc8\xa3\x61\x1d\x78\x92\xa6" + "\x0e\x6d\x87\x32\x54\x38\xbc\x08" + "\x03\x7b\x02\x28\xfb\x05\xcf\xbe" + "\x2f\xe1\xb1\xa4\x7d\x68\x6c\x63" + "\x58\x7c\x21\x07\x3d\x00\xe3\x00" + "\xa3\xb2\x01\x5e\x37\xa9\x3b\x61" + "\x6e\xe1\x1d\x88\x05\x84\x8c\xa5" + "\x8b\xf4\xf8\x14\x30\xc4\x53\xc6" + + "\xf9\xd0\xa0\xd6\x97\x68\x1c\xbc" + "\x55\x7f\x0d\x3b\x0e\xea\xe0\xd8" + "\xad\x7a\x5b\xb8\x92\xaa\x5b\xb3" + "\xf4\x48\x4e\x67\xb7\xd1\xec\x2b" + "\xc2\x9a\x7a\x6d\x8d\xf7\xd7\xe2" + "\xd0\x95\x9c\xf9\x62\x42\x07\xf5" + "\xe9\x11\xf6\x89\x0a\x47\x52\x48" + "\xec\x9d\x86\x92\x19\x91\xaa\xf7" + + "\xe2\xaa\x6d\x4e\x77\x2e\x7f\xed" + "\xbc\x19\x0a\x9e\xe3\xe0\x3a\x7b" + "\x7e\x67\xae\x91\x8a\x3f\x29\xd3" + "\x1f\x61\xc8\x45\xcb\xb0\x63\xd3" + "\x3b\xe9\x9a\x30\xcf\x1c\x1d\xbe" + "\xe1\xca\x20\x39\xe7\x0b\xf8\xa3" + "\x01\xdf\x8e\x49\x74\xba\xac\xaa" + "\x90\xac\xf5\xb2\x4a\x2a\x6d\x1e" + + "\xf1\x50\x35\x23\x3f\xf0\xc5\x60" + "\x2e\xfd\x5a\x92\x11\x94\xd0\xd4" + "\xa6\xe5\x58\xd2\xc3\x65\x5b\xa9" + "\x6a\x2c\x90\x9f\xb5\xcf\x19\x1a" + "\x68\x5c\xad\xf5\x3a\x01\x86\xb4" + "\xf3\x38\x96\x97\x76\x67\x50\xa2" + "\x28\x0b\x8e\xa3\xd0\xb4\x32\x12" + "\x4f\x7b\x6a\xd3\xb8\x84\x47\xa6" + + "\x96\xa6\x66\x02\x9e\xa1\xcf\x7f" + "\x4b\xfb\xc3\x92\xfd\x64\x1f\x5e" + "\xdf\x19\x6d\x50\x11\x49\x95\x6d" + "\xa1\x3c\x7a\x69\xe1\x9f\x98\x9f" + "\x7d\xa8\x27\x23\x8c\x8d\x48\x7e" + "\x17\xa3\x7d\x03\x28\xce\x43\xa5" + "\x18\x55\x3c\xf9\x76\x1d\x07\xea" + "\x3b\x6d\x0a\x22\x48\xfd\x5f\x58" + + "\x03\x0e\xd7\xe7\x9d\x17\x55\x56" + "\x70\x45\xa8\x72\x5c\x0c\x78\x3e" + "\x9c\x02\x50\x1d\xcb\xb4\x02\xc1" + "\x39\xe8\x75\xf0\xd5\xbd\x71\x3e" + "\x22\xb8\x98\xb4\xf0\xf4\x60\x64" + "\xa5\x8d\x4b\x6d\x6c\xe0\x82\x26" + "\xd4\x40\xa7\x96\xc9\x53\xae\x4e" + "\x2c\x70\x89\x63\xef\x8b\x9d\xc1" + + "\x70\xff\xc6\xc2\x8d\x72\x35\x87" + "\x35\x22\xdc\xc5\x2f\x12\xd6\x79" + "\xf9\x77\xe2\x19\x03\xd0\xf5\x23" + "\xc7\x8c\xed\xdd\x25\x4e\xe8\x7e" + "\x0a\x88\xcd\x63\xb0\xaf\xa8\x91" + "\x60\xaf\x74\x35\xc6\xa7\x3e\x3f" + "\x42\x7f\xde\x02\x84\xdc\xfc\x0c" + "\x52\xa1\x1a\xb3\x2f\x79\xd0\x62" + + "\x55\x16\x3b\xee\xb2\x47\x9a\x95" + "\x5b\x3d\x88\xec\xdd\xb9\x99\xc7" + "\x04\x38\x93\xb7\x80\x9f\xc0\x2d" + "\xb8\x3d\x2d\x3d\x88\xe8\x69\xae" + "\xf4\x0a\xe7\x25\x2f\x5e\x5d\xc1" + "\x85\x00\x04\x05\xce\xd9\x5f\x87" + "\xf2\x38\x5a\x6b\xd0\xe8\x50\x28" + "\xda\xb0\xbe\x9a\x35\x7f\x22\x15" + + "\xf2\x23\xe5\xe0\x37\x10\x0f\x65" + "\x3b\x01\x83\x95\x43\xab\x38\x44" + "\x5e\x90\xc0\xef\xfb\x68\x42\x03" + "\x6b\x77\x06\x0c\xa2\x4b\x28\x7b" + "\x33\x11\x6c\x1b\xc4\x49\xb9\x02" + "\x4f\xef\x4b\x19\x47\x8d\x3b\x7c" + "\x35\x05\x7e\x0e\x00\x5b\xe1\x5f" + "\xb4\x26\xb1\x28\x74\x66\x26\xc3" + + "\x44\x11\x92\xe0\x42\x93\xb9\xf8" + "\x2c\x3e\x03\xb5\xf1\xc6\x4f\xf1" + "\x54\xcf\xda\xdc\x60\x37\xfb\x7d" + "\xa5\x7b\x8d\xd8\x31\x0a\x5a\xd2" + "\x77\x49\xf7\x68\xcb\x2f\xed\x4d" + "\x07\x40\x76\x9a\x65\x47\x88\xf1" + "\xc7\xf4\xdc\xf2\x69\xb1\x9d\x87" + "\x6a\xf9\x6d\xd1\xd5\x75\x4d\x74" + + "\xb5\xef\xcc\xbe\xaa\xf5\xfd\x40" + "\xc7\xd7\x21\x36\xe9\xed\x56\xcf" + "\xc1\x76\xb5\x52\xce\xa9\x32\xb6" + "\x27\x60\x6f\x9a\xe8\x3a\x40\xd3" + "\x64\x5a\x78\xe8\x0d\x05\x0a\x66" + "\x2e\x65\x82\x96\x47\xd6\xf3\x10" + "\x02\xbe\xbc\x4f\xdf\x5e\xb2\x78" + "\x5d\x31\xf9\xb4\xde\x0f\x71\xc9" + + "\xf9\x35\x02\x1e\x9a\x00\x88\x0f" + "\xa1\xb8\x20\x48\x27\x40\xed\x2f" + "\x40\x11\x08\x86\xac\xb7\x72\xbe" + "\xe3\x63\x11\x60\x72\x26\x16\xd4" + "\xea\x71\x0c\x75\xad\xa3\x1e\xf7" + "\xe3\x8b\xdc\xaf\x40\x71\x34\x02" + "\x6b\xa6\x5a\xc6\x29\x6f\xe6\xa5" + "\xc8\x8f\x39\x07\x64\xec\xc7\xf3" + + "\xa2\x38\x99\x17\x63\x67\x09\x14" + "\x77\xb8\x1c\x1c\x71\x0e\xba\x4f" + "\xcf\x7c\xcf\x7c\x2f\x2a\x6f\xda" + "\x65\xde\x1b\x09\x4e\x1a\x24\x91" + "\xd8\xfc\x71\x1e\xc3\x56\x28\xcc" + "\xc3\x1c\x44\x12\x7c\x7e\xb8\xc0" + "\xaa\x24\xf2\xe5\x1e\x68\xd1\x3d" + "\xea\x08\x73\xad\xf6\xd6\xae\x30" + + "\x22\x3e\xb5\x28\x17\xb0\xb8\xd4" + "\x71\x7c\x7b\x0f\x48\xd9\x94\xe3" + "\xdf\xaf\x1c\xb2\x68\x23\x1f\xe2" + "\x33\x78\xcc\x86\xb6\xfa\x11\xc9" + "\xd7\xcc\xd1\x39\xfd\xf6\x61\x0f" + "\xa9\x90\x8d\x24\x8b\xeb\x16\xe2" + "\x0d\xd2\x22\xfc\x44\x8f\x05\xa5" + "\x28\x96\xc6\x57\x92\x96\x26\x91" + + "\xce\x07\x58\x8a\x43\x4e\x1b\x8e" + "\x7e\x9a\x10\xe4\x93\x38\x28\xad" + "\xda\x9d\xd5\xaf\xcb\xc9\x0c\xc3" + "\x93\x80\x8d\x3d\xc6\x36\x5f\xf6" + "\xb2\x32\x0d\xa6\x9e\x46\x31\xdf" + "\xc8\x91\x81\x3e\x4b\xdf\x93\xee" + "\xb5\xde\x5b\x35\xc5\x17\x10\x9c" + "\x28\xaa\x16\x86\x85\x31\x62\xd2" + + "\x10\xed\x48\xa4\x64\x4f\xed\x38" + "\x8b\xb7\xef\xc4\xa8\x03\xeb\x81" + "\x52\x3b\x32\x91\x5c\x1b\xd9\xbf" + "\x2e\xff\xbe\xb6\x33\x2b\x88\xed" + "\xa1\xd7\x22\x67\x51\x45\xfb\xd0" + "\xab\xe8\x9f\x94\x1b\x44\x91\x6f" + "\xa6\x81\xc1\x3a\x99\x4a\xa4\x63" + "\x74\x6b\x0b\x95\x5f\x2b\xa6\xf4" + + "\xcf\xa2\x01\xe8\x46\x44\x61\x22" + "\xdf\x8c\x47\x2e\x27\x20\x3a\xfa" + "\xb3\x50\xc6\x98\x9a\x0c\x2a\x10" + "\x70\xff\x73\x48\x98\x93\x00\xc5" + "\x01\x6d\xa1\xfa\x06\x86\xec\x87" + "\x8b\x4d\xdd\x9e\x94\x27\xc1\x0f" + "\x60\xd4\x6b\x6f\x00\x7a\xa9\xe7" + "\x59\xff\xbe\x5e\x30\xd1\x9c\xf6" + + "\x28\xa2\xb5\x62\x86\xd1\x09\x62" + "\x26\x8b\x40\xd4\xaa\x7d\x5d\xb8" + "\x00\xb3\xb1\x8e\x0f\x11\x48\x7e" + "\xab\xaa\x64\x04\xd2\x3c\x78\x66" + "\x61\xa0\x8b\x0f\x25\x8b\xf6\x2d" + "\xeb\x8a\xa0\xb2\x61\xc4\xe0\x97" + "\x38\x0d\x64\xbd\x0e\x6f\x8f\x6f" + "\xa6\x5d\x47\x41\xe1\x22\x33\x99" + + "\x0e\x98\x45\x32\xe7\xad\x55\xd6" + "\x00\x72\x06\x81\x57\x96\xf5\xa6" + "\xe1\x6b\x13\xdb\xbe\x23\xfc\xe4" + "\x79\xd8\x13\xaf\xdc\x6c\x24\x9f" + "\x0e\xac\x61\xf9\x17\x31\xb9\xc2" + "\x1a\x9e\xdb\xeb\xb5\x41\xa7\xc8" + "\xd1\x3b\x69\x6c\x46\xe2\xed\x82" + "\x1e\x70\xd1\x3d\x4f\x6b\xde\xfc" + + "\x6f\x64\xa4\xca\x00\x4e\x80\x1f" + "\x24\x49\x94\x70\x88\xdc\x43\x86" + "\xe9\x6d\xf8\x73\xa2\x1c\x7f\xa3" + "\x98\x98\x88\x28\x92\x9f\x19\xa3" + "\xdf\x4a\x1e\x0c\x58\xba\x73\xc2" + "\xf0\x82\xbc\x65\xaf\x38\x0d\x0f" + "\x3b\xcd\xa6\xf8\xb5\x8a\xb2\xd8" + "\x8e\x4d\x89\x75\x85\xe0\xa6\xee" + + "\x15\x32\xc9\x0e\x98\xb9\x42\x46" + "\x9f\x34\x9d\x29\x0a\x17\x19\xb7" + "\xba\xb5\x36\xbc\x2b\x16\x2c\xb3" + "\xa2\x3c\xd2\x4b\x85\x73\x35\x06" + "\x15\x81\xf6\xdf\x92\x62\x41\xff" + "\x99\xdb\xb5\x4b\xe3\x50\xa1\xb7" + "\x55\x3d\xc1\xa3\x28\x20\x7a\xb9" + "\x06\x45\x42\xe5\xc1\x06\xf4\x86" + + "\xcf\x95\xcd\xb9\xb9\xc1\xb0\xfa" + "\x73\xae\xa9\x11\xb3\xab\x85\x36" + "\xa3\xa9\x96\xa9\xaf\x3e\x97\x02" + "\x1d\x57\x34\x29\xaf\x9b\x6f\xff" + "\xe8\x40\x7c\x25\x21\x81\xab\xe4" + "\xb1\x30\x2d\xd9\xe4\x28\xad\x09" + "\x82\xb5\xe4\x09\x35\xa0\x51\x7c" + "\x0f\x12\x5b\xc3\xf8\x01\xbb\x60" + + "\x21\x1a\xc3\xde\xf9\x83\x2c\xb0" + "\x73\xd5\xd9\x6a\x23\x8b\x8c\x98" + "\x65\xe3\x7b\xa5\xae\x83\xe9\x53" + "\x4e\x83\x6f\x64\x4d\x73\x68\xe9" + "\x9b\x30\xa6\x5d\x8f\xea\x37\x91" + "\x16\xce\xf1\xc1\x24\xa6\xf3\x10" + "\x21\x09\x44\xca\xa2\x9e\x2a\x78" + "\xb5\xf1\x46\x5b\x9e\x73\x94\xdf" + + + "\x6a\xb1\xf8\xf4\x0e\x41\xf8\x56" + "\x6a\x26\x7b\xc4\xfe\x1a\x24\x97" + "\xc1\x87\x9c\x6d\x8e\x6b\x40\x0a" + "\x1b\xab\x42\xcd\x02\x3e\x3f\x80" + "\x69\xec\xdb\x04\xa8\x09\x03\x7f" + "\x5f\xd0\xba\x3b\xf7\x85\x3b\xa8" + "\x7f\x19\x8e\xad\x73\x72\x09\xc6" + "\xc1\xad\x67\x50\x0e\x44\x97\xc0" + + "\x8c\x89\x11\xb3\xa0\x7f\x74\x3f" + "\x65\xac\x0e\xcd\xe4\x72\xa2\xe2" + "\xbc\xd0\x14\xf9\x51\x58\xba\x4b" + "\xe3\x3e\xa4\xc4\x60\x96\x1a\x7a" + "\xe9\xcd\xc8\xa1\xce\x67\xa3\xe5" + "\xe3\xab\x71\x72\xa9\x8b\x95\x9d" + "\xcd\x15\x16\x3d\xb6\x7e\xff\xf3" + "\xb0\x20\xae\xf5\xce\x0d\x28\xa2" + + "\xdc\xf8\x94\x37\xa4\x44\x63\x26" + "\x36\x5c\x3c\x48\x3a\x92\xca\xdc" + "\xa0\x10\x9d\x3f\xbf\x6b\x6b\x2d" + "\xf3\xbd\xd9\x81\xca\xc5\x20\xb3" + "\x95\x0a\xb5\x47\xff\x28\x0e\x62" + "\x71\x33\xf0\xce\x01\x3b\x3e\x93" + "\x53\x01\x10\x99\x85\xbf\x81\xf0" + "\xd6\xc8\xa8\xc3\xa0\xe9\x3b\x18" + + "\x66\xa5\xdc\x41\xc3\x85\xc1\xb6" + "\xa3\x2a\x62\xd8\xda\xfe\xe7\x7d" + "\xfb\x6d\x1b\x90\x92\x4d\xe8\x99" + "\x88\xd2\x4a\x7c\x0e\x2b\xa0\x30" + "\x36\xcf\xd3\x2f\xaa\x1d\xc8\xc7" + "\x9f\xe5\x89\xdf\x47\x95\x31\xd1" + "\x33\x67\x49\xcd\x84\x81\xbe\xb2" + "\x2b\x41\xd3\x93\xeb\x49\xf4\xd5" + + "\x6b\x11\x85\xe0\xab\x0f\x47\x25" + "\x10\x53\x28\x87\x75\x33\xa4\x04" + "\x2f\xd5\xbf\xe2\x7e\x18\x39\x4e" + "\x74\xbc\x9e\x7d\x44\x6b\x16\x36" + "\x2c\x32\x4b\xfd\x3c\x43\xad\x92" + "\x51\xab\x79\xba\x17\xa8\x6a\x72" + "\xeb\x15\xdb\xc1\xd8\xac\x6e\xf9" + "\x63\xbe\x76\x04\x91\x1e\xf7\xfa" + + "\x16\x65\x7e\xc9\xda\x9b\x4e\xd7" + "\x9e\xf4\x30\xc2\x60\x93\x77\x88" + "\x49\xea\x74\x1e\xe3\x1d\xec\xa6" + "\xa2\x45\xb6\x3f\xe5\xce\x1d\x58" + "\x14\x3f\x48\x8f\x91\x23\xef\xba" + "\x3b\xd1\x37\xd1\xfc\xdd\x2d\x6d" + "\x42\x3a\x74\xd2\x0e\xe5\xcd\x54" + "\x67\x7e\xd9\xe4\xc5\x4f\xa3\x89" + + "\x68\xe1\xde\x49\xe9\xd2\xcf\x72" + "\x39\xf2\x2a\x3e\x23\x52\xe0\x1a" + "\x6a\x06\x94\x1d\xbe\x75\x9e\x00" + "\x13\xf4\xab\x38\xc7\x31\xca\x6c" + "\x08\x99\xc4\x9b\x1d\xd6\x0b\xb5" + "\x1e\xbc\xe2\xf5\x8c\x4a\x9b\x4a" + "\xac\x83\x6f\x94\xf7\xc5\x6c\xeb" + "\x28\xab\xff\xeb\xfc\x93\xda\x27" + + "\x4c\xf6\xd8\x4c\x64\xec\x92\xc4" + "\x51\x7b\x9d\x27\x90\xd7\xa2\x58" + "\x56\x52\xc7\x1f\xc5\x1f\xed\x0c" + "\x17\x30\x43\x8f\xed\x8a\x65\x3e" + "\xeb\x59\xda\x05\x2e\x94\x61\x0b" + "\x22\x37\xdc\x0d\xa3\x60\x3d\xba" + "\x87\x7f\x2e\x74\xd1\x1c\x31\x7c" + "\x6e\x1b\xb0\xf6\xee\xff\x73\x64" + + "\x51\x7c\x25\x76\xef\x19\xe5\x3c" + "\xe7\x77\xd4\x18\xd3\x18\x58\x6f" + "\xc0\xed\x63\x79\x03\x2e\x02\xab" + "\xf3\xf5\xd1\x8b\x89\x3a\x40\xf0" + "\xca\x33\x60\x49\xa0\x8d\x3b\xe4" + "\x72\xdd\xcf\xa1\x0e\xe1\x94\x09" + "\xe2\xc0\x73\xba\x20\x6d\xec\xb1" + "\xd1\xfa\xbc\xb6\xec\xc9\x29\x03" + + "\x9d\xbd\x84\x2c\xa1\x42\xff\xf1" + "\x4a\x67\x0c\x39\xc4\x3e\x1f\x75" + "\xca\xe0\xe5\x01\xf7\x36\xbb\x27" + "\x92\x66\xaf\x5c\x51\xff\xdf\x65" + "\x3f\xbd\x7b\xcd\xc4\x79\xf5\x5d" + "\x05\x12\x59\x85\x97\xb2\x8f\xef" + "\x32\xc7\x7a\xe4\x03\x72\xed\x1d" + "\x1a\x33\x1c\xcd\x5c\xc4\x3d\xa9" + + "\xd4\xd2\x18\x33\x8e\x33\xec\xbd" + "\x63\xe9\x8d\xbe\xbb\xd7\x3d\x73" + "\xbd\x7e\xc4\xa2\xba\xc3\xbc\x61" + "\xde\xcb\xef\x35\x19\xad\x21\xa8" + "\x5c\xdd\x4c\x02\x8c\x66\xac\x91" + "\x49\xfa\xcd\xc1\xe4\x58\xa5\x7b" + "\xda\xb4\x8f\x90\xe0\x4c\x1d\x49" + "\xe8\xbd\x85\xf6\xf9\x69\xa8\x7b" + + "\x78\x1c\xf4\x81\xcb\x0b\x2a\x7b" + "\xe1\x40\xd2\x1f\x85\x2c\x52\x5c" + "\xf6\xe3\x5c\xdf\x68\x2e\x51\xce" + "\x13\xee\xd5\xb6\x52\xb9\xd4\xa7" + "\xaf\x7e\xad\x31\x8b\x0a\xdc\x8c" + "\x20\x5e\x91\x1b\x75\x86\x5e\x16" + "\xf4\x77\x64\x5d\x9b\x26\x8c\x8e" + "\x91\x1b\x42\x44\xde\x5a\x8d\xd2" + + "\xba\x64\xf4\x79\xc2\x5e\x1b\xed" + "\x26\x2e\xd7\x47\x2c\xe4\x65\x2d" + "\x26\xf9\x67\x9e\x74\xe5\x98\x81" + "\x44\x7e\x74\x34\x38\x67\x06\x41" + "\x47\x54\x7e\xe3\xc1\xac\x37\x46" + "\x22\x58\xe1\xf3\xec\xc9\xcb\x02" + "\x3c\xa8\x5a\x80\x8e\xe9\xa8\x58" + "\x00\xe8\x95\x55\x6e\xcd\xfa\x73" + + "\x18\x23\xa9\x32\xb3\xfd\x7c\x19" + "\xb6\x87\xac\x25\x41\xa8\xbe\x9e" + "\x7a\x0c\x51\xa3\xf7\x05\xd8\x4c" + "\x8e\x42\x6e\xe0\x9a\x99\xdf\x24" + "\x9c\x45\x71\x4d\xdc\xd5\x4d\xd5" + "\x3c\xa0\xb8\x20\x4f\x32\x84\x14" + "\x27\xb9\x74\x31\xd9\xf2\x24\x79" + "\x50\xde\x3a\xf9\xbf\xac\xb8\x42" + + "\x07\x05\x33\x38\x03\xf8\x8f\x46" + "\x3e\xa5\x37\x40\xdf\x4d\xf3\x06" + "\xa4\x93\x69\x8d\x40\x1a\xcd\x70" + "\x22\xc0\xe5\x43\x97\x15\x5a\xf8" + "\x7d\xa6\x25\xc1\xc2\xc9\x6f\x39" + "\xcb\xbf\x64\x10\xbf\xbe\xb7\x03" + "\xcb\x6d\x80\xa9\x92\x45\x44\x7c" + "\x54\xcd\x87\x44\x4b\x61\x02\x1b" + + "\x42\xc5\x2a\x69\x4f\x60\x03\x83" + "\xd3\x91\x7b\x22\xe1\xff\x79\xf0" + "\xbd\xf9\xaa\x15\x63\x3e\xf6\x19" + "\xfb\x44\xf3\xf1\x65\xe5\x9e\xf9" + "\x99\x91\x21\xd6\x1f\x66\x1d\x8a" + "\x1c\xe4\x8c\xd4\xc6\x3b\x88\x8c" + "\x04\xd9\x74\x3c\x8f\x11\x65\x10" + "\x1b\x8b\xaf\x0f\xee\x89\x38\x71" + + "\xb6\x1b\xe2\x0d\xf7\x60\x7b\xb4" + "\xca\x36\xd8\xdc\x4f\xae\xac\x64" + "\x63\xce\x44\xc7\x6d\xea\x75\x33" + "\x5b\x95\x47\xb0\x5f\x26\x64\xb7" + "\xc3\xc2\x41\x98\x4c\x5d\x8a\xc6" + "\x60\x4f\x45\xcf\xd7\x8f\xe9\x60" + "\x0c\xea\x6a\x75\xe2\xfb\x01\xc7" + "\x79\x1c\xb2\xaa\x5e\x88\xc8\x09" + + "\xcf\xbd\xd1\x91\xef\x59\x13\xca" + "\x86\x25\x59\xf3\x57\x21\x08\x6a" + "\x1c\x95\x51\x39\x94\xa5\xae\xd9" + "\x06\xe7\xb7\xa2\x24\xef\xab\x57" + "\xa2\xb1\x2e\x2e\x1e\x72\xa5\x3f" + "\x98\xce\x6a\x51\xac\xee\x68\x3c" + "\xdf\x82\x87\xc2\x47\x9d\xa7\xff" + "\x7b\x57\x16\x4e\x63\x9f\xd6\xbd" + + "\x6c\xd4\xd2\x69\x08\x81\xbb\x45" + "\x5a\x36\xc8\x68\x39\x8b\x7c\xe4" + "\xbd\x51\x75\x26\x63\x76\xb8\xf3" + "\x7a\x54\x67\x5b\x8f\x76\x90\x15" + "\xff\xd3\x2e\xfb\xb2\x1d\x1c\x37" + "\x40\x94\xa5\x17\x19\x69\x16\xe3" + "\x14\x2c\x24\xdf\x78\xd1\xc0\x03" + "\xc1\x2a\x86\xed\xce\x3f\xc9\x40" + + "\xaf\x84\xbb\xc5\x60\x79\x2b\x40" + "\x39\xa6\xc8\xbc\xdc\xc7\x29\xcf" + "\x6d\x7c\x8f\x47\xff\x9d\xf1\xfa" + "\x22\xbd\x37\x33\xe4\x6a\x30\x71" + "\x7a\x9b\x59\xbf\x05\x55\x7c\xef" + "\xa8\x91\x46\x9c\x9e\x15\x9e\xe0" + "\x19\xb1\xce\x74\x18\xe8\x03\xd4" + "\x8d\xa9\x11\x52\x02\xe7\x25\x53" + + "\xd6\x82\xc9\x2b\x69\xda\x86\x12" + "\xe3\xe7\xda\x7b\xf2\x80\x6d\x5f" + "\xfb\x64\xf0\xa6\x47\x56\x9c\x3d" + "\x40\x15\x4c\xd7\xa1\xe6\xc8\xfd" + "\x5a\x13\x8b\xd6\xc6\x48\xda\x97" + "\xff\xbf\x6d\xd6\x79\x79\x09\xc2" + "\x1d\x53\x20\xea\xb9\xad\x96\x02" + "\xf0\xc8\xb2\x4a\x0d\x73\x33\xa3" + + "\x33\x19\x25\x7a\x2b\x12\x97\xaf" + "\x45\x33\x23\xc1\x9c\x34\xc7\x36" + "\xb0\x00\xf4\x73\x88\xde\x87\x56" + "\xaf\x95\x75\x70\xa3\x47\x28\x92" + "\xc1\xde\xf6\x7f\x58\x18\xe0\xb7" + "\xcb\x91\xc1\x2f\xce\x3e\x28\x6e" + "\x56\xdc\x20\x1c\x8b\xef\xc2\x78" + "\xdc\xd2\x2e\x45\x5e\x53\xe6\x51" + + "\xed\x7f\x84\x29\x54\x56\xb3\x0e" + "\xd0\x3d\x67\x0a\x86\x42\xc1\xfd" + "\x0b\xdd\x62\x8b\x27\x36\x1b\x72" + "\x71\x57\x1a\x71\x3e\x29\x5a\x10" + "\x27\x19\x76\x7f\xce\x1c\x00\xdf" + "\x7d\x4c\xd0\x11\xb0\x81\xb6\xf7" + "\x96\x19\xac\xa3\x92\xf7\xdf\x16" + "\x30\xae\xc4\x0f\x0b\x12\x0c\x58" + + "\xc7\xb8\x0e\x96\x97\xf6\x35\xc0" + "\xd3\x04\xde\xe2\x2c\x9f\x59\xf1" + "\x28\x92\xad\xd2\xf8\x50\x24\x89" + "\xab\xc1\x29\xb8\x9b\x12\x48\x7d" + "\xc9\xaf\x50\x3a\xe1\x85\xd7\x24" + "\xe0\x6e\xa9\x63\x27\xba\x45\x27" + "\x7b\x6d\xfb\x3b\x01\x34\x65\x95" + "\x42\x2a\xad\x1b\x67\x02\x62\x53" + + "\xbc\xd0\xe8\x7e\x4f\x3d\xea\x31" + "\xdc\xc3\x42\x0f\x2a\xf2\x32\x38" + "\xf4\xa2\x87\x1a\x1a\x06\x61\xc6" + "\x6b\x57\x45\x4b\xf6\xc9\x78\x09" + "\xd2\x5f\xfb\x6d\x3c\xac\xab\xb7" + "\x90\x1b\xe0\xb7\x00\x6a\xf3\x27" + "\x36\x9e\x42\xe9\xcd\x33\xf7\x68" + "\xcb\xe8\xbf\xdc\x81\x46\x3a\x95" + + "\xe3\xc2\x03\x41\x24\xff\x96\xe3" + "\xe7\xad\x06\x1b\x1c\x56\x33\x41" + "\x34\xa7\xd0\x65\xac\xb9\x20\xe1" + "\xd9\x19\x79\x92\x07\x6f\x6f\x57" + "\x5a\x95\x1f\x69\x46\xc8\xcf\xa0" + "\x65\x9d\x44\xa6\xc0\x2b\x2e\x3d" + "\x9b\xed\x67\x97\xb8\x41\xa5\x7b" + "\xc7\x15\x92\xdc\x04\x1b\xb2\xd1" + + "\xaf\x1e\xfe\x67\x10\xc4\xb7\xbf" + "\x85\xa7\x29\x69\x6a\x3c\x07\xa2" + "\x79\xdb\x5f\xa7\xf4\x36\x25\x6f" + "\x69\xca\x9b\x80\x6d\xd2\x9a\x85" + "\x7b\x7e\x19\x3b\x69\xc0\xf2\x06" + "\x73\xa5\xc0\x8e\xf4\xd9\x6a\x65" + "\x62\x02\x4d\x9a\x1f\x90\xc7\xe7" + "\x2b\x60\x38\xb9\x43\x94\xc2\xbe" + + "\xa4\x73\x00\x0f\xfc\x97\x03\xd0" + "\x5f\x67\x8d\x6f\xa4\x8f\x66\x5b" + "\x8c\x10\x22\x15\xc9\x4a\x37\x14" + "\x2e\xe4\x83\x02\xd1\xa7\xef\x92" + "\x4a\x02\x6d\x0b\xf9\x6d\x3e\x67" + "\x26\x1f\x58\x57\xd4\x14\xf9\x05" + "\x12\x8c\xdf\x67\x62\x51\xc8\xf5" + "\x62\x24\x6c\xe0\xb4\xf1\x97\x11" + + "\xc1\x90\x9c\xdd\xb3\x1c\x2d\x6e" + "\x9e\x57\x90\x79\x5a\x2d\xf8\x28" + "\x95\x61\x22\x06\xcd\x89\xe1\x90" + "\x74\xdc\xb0\x19\xdf\x39\x29\xbd" + "\x77\x71\x91\xc0\x05\x85\xb1\x18" + "\xc4\xd9\x17\x31\x0d\x47\xd5\xee" + "\xa0\x3c\x89\x6c\xeb\x92\xef\x39" + "\x40\x19\xa4\x44\x82\xef\x33\x45" + + "\x95\x75\x2d\x2d\x3c\x85\xac\x62" + "\x54\xad\x8f\x59\xb7\xda\x83\x48" + "\xa4\xd7\x32\x6d\xd1\xf5\xf7\xbb" + "\x81\xd8\x1d\xfd\x2d\x4f\xfb\x95" + "\x80\xc5\x5d\x54\xf2\xae\x39\xe2" + "\xb9\x39\x1e\x4d\x0a\xa7\x09\x46" + "\xb2\xbb\x8e\x33\x3e\xb3\xd3\x61" + "\x61\x54\xbd\x15\xc2\x1d\x05\x06" + + "\xda\x3d\x94\x34\xec\x9d\xee\xca" + "\x82\x67\x4b\x8b\x8e\xe9\x50\x8e" + "\x1f\x3a\xea\x91\xa5\x8e\x35\x24" + "\x94\xc1\xe1\xa9\x27\xc8\xc4\x71" + "\x94\x7a\xbb\x09\x5d\xaa\x8b\xa3" + "\x9c\x8f\xb5\x57\xc0\xb4\x4a\xfb" + "\x19\xee\xe0\x24\x5e\x06\x01\x4a" + "\xbf\x77\xb8\x07\x51\x80\xcf\xb9" + + "\xbe\xb3\xa1\x81\x8f\x3f\x2b\x97" + "\xa0\x64\x27\xce\x45\xe1\x3c\x4f" + "\xf7\xf5\xc4\x28\xcc\xf1\xd0\xe2" + "\x5b\x98\xf3\xc7\x0d\x0c\xee\xde" + "\xc3\x25\x9e\xd3\xc0\xad\xf4\x7d" + "\x80\xa0\x67\xc4\x20\x98\x61\x40" + "\x58\x5a\xcf\x61\x93\xbc\x0e\x44" + "\x00\xd6\x2a\x42\xa6\x29\x77\x52" + + + "\x49\xf4\x73\x3f\x75\x6a\xb2\xef" + "\x79\xfc\x44\x8d\xf8\x94\x1c\x1d" + "\x4d\xdc\xc0\x3b\xc5\xfb\xf0\x49" + "\xd0\xa0\x98\x36\x0b\xea\x47\xb7" + "\x1e\x29\x8d\x22\xfe\xc3\x18\x52" + "\xd6\x29\xc1\x43\xb5\x04\xb8\x35" + "\x16\xc5\xac\xd1\xb8\x59\xc8\xfa" + "\x68\xe6\xd6\x95\x7d\x69\x10\x6c" + + "\xdb\x2f\x45\xcb\x1a\x25\x30\x6e" + "\x50\x06\xf3\x50\x65\x69\xee\x31" + "\xd9\x48\x35\x93\x08\xe5\xb3\xb0" + "\x5b\xef\xb0\xf4\x4f\x9a\x94\xb8" + "\xbd\xf3\x88\x3c\x26\x83\x8b\x20" + "\x89\x99\x1d\xdb\x30\x7c\x14\xab" + "\x03\xdf\xd4\x44\xfd\x15\x65\xed" + "\xc5\xb0\x2e\xe7\x75\x2f\xa1\x17" + + "\x89\xfe\xe3\x28\xe0\xbb\x6c\x7a" + "\xeb\xc0\xaa\xc5\xe4\xfe\xe1\xe7" + "\x40\x51\x7e\x69\xa5\xed\x47\x7f" + "\x1f\x92\x54\xb4\x37\x01\x45\x4f" + "\x85\x81\xcd\x95\x84\x5f\x62\xdb" + "\x83\xe5\xb2\xcd\xa1\x0b\xbe\x74" + "\xe4\x6d\x5e\xdd\x7c\xfd\xe4\xae" + "\x39\x17\x10\xe8\x7d\x43\x51\x42" + + "\x90\xad\xfd\x81\x78\x4f\x91\x25" + "\xab\xf6\x2c\x0d\x56\x8f\x63\xcf" + "\xe5\x4d\x05\xcc\x3f\xc0\x0b\xb9" + "\x50\x63\xb0\x18\xa7\x11\x28\x93" + "\xff\x11\xbd\x9b\x30\xb3\x00\x2f" + "\x74\x49\x04\xb4\x6f\x8a\x10\x76" + "\x66\xd2\x51\xa8\xe0\xb9\x1b\x80" + "\xc1\x90\x89\xbf\xbe\x99\xd0\x0d" + + "\x61\x70\x7d\x51\x0a\xb2\x5e\x11" + "\x83\xf6\x2d\x6c\x33\x34\xfe\x77" + "\x67\xfc\xc6\xcd\xc7\xdd\x70\x68" + "\x83\xde\x87\x0b\x88\x05\x61\xb1" + "\xbe\xdd\xc4\xd9\xca\x84\x35\x34" + "\xe2\x4b\x75\x3d\x1c\x4f\x16\xb3" + "\x94\xc8\xe6\xc1\x3a\xed\x31\x07" + "\x4c\x90\x6b\x4f\xec\x7d\x32\x26" + + "\x55\x38\x1c\xc6\xae\x7b\x26\x29" + "\x3b\xfd\xc1\x58\x9d\x42\xff\xeb" + "\xb8\x93\x0b\x8c\xc0\x86\xd8\x22" + "\x53\x89\xdb\x2d\xb2\x00\x5e\xca" + "\xb7\xd8\xfe\xc3\x17\x01\x33\xcf" + "\xf6\x01\x9c\x81\xfa\xc6\x9a\xd4" + "\x54\xbd\x0f\x3c\xbd\xa6\xda\x6d" + "\xcf\xa2\x49\x80\x68\x30\x74\x91" + + "\x5a\x76\x72\x76\x3c\x06\x6a\x0a" + "\xbf\xb9\x47\x05\x64\xce\xa3\x37" + "\x33\xa6\xb1\x98\xc8\x99\xc0\x42" + "\x61\x69\xee\x05\x0d\x80\xab\xb5" + "\xd6\xac\xa5\x11\x59\x3f\x96\xf1" + "\x63\x10\x20\x46\x57\x61\xee\xba" + "\x0a\x21\x96\xa5\x49\xa6\xd9\x36" + "\x8c\x13\xa7\x1b\x63\x43\xd0\xae" + + "\x46\xcd\xd6\x58\x8a\xdd\xc6\x14" + "\xd2\x34\x66\x8e\xb5\x33\xb6\x9c" + "\x28\xc3\x1b\xf8\x47\x50\x30\xc1" + "\xe5\x77\xa1\x26\xe2\xe0\xed\x12" + "\x4f\x6f\x5a\x06\x62\xca\x2c\x33" + "\x7b\x48\xbe\x67\xcd\x7e\xa4\xc3" + "\x1c\xed\x47\x0f\x87\xb1\x1e\x74" + "\x14\x8b\x59\xe7\x58\x6e\xe6\x99" + + "\x6e\xe7\x1f\xf5\x76\x28\x82\x36" + "\x89\x25\xd6\x11\xcc\x11\x68\x8a" + "\x18\x57\x22\x46\x65\x7e\xfc\xc3" + "\xcd\xdb\x2f\xc8\x9f\x2c\xdf\xb7" + "\x5b\x20\x7b\xdd\x52\x4e\x1d\x3b" + "\x14\xe4\xa2\x47\x78\x94\x95\xb6" + "\x48\x11\xa9\xef\x93\xd7\xe4\x05" + "\x75\x96\x2e\xfd\x46\xd4\x7e\xb4" + + "\x2f\x23\xf3\xeb\xe2\xd0\x0e\x8f" + "\xdd\x2e\x2a\xc5\x9e\x0f\xf8\xff" + "\xdb\x5f\xb5\x75\x33\xb4\x9a\xad" + "\x11\x0c\x2e\xe4\x20\x78\xca\x73" + "\x46\x1b\x25\xe6\xa0\xe0\xac\x6d" + "\x2d\x93\x0d\x4c\x5c\x6b\xbc\x89" + "\x9a\xa1\x5d\x09\x77\xcd\x38\x34" + "\xfb\xbd\x48\x8d\x39\xa9\x24\x2f" + + "\x92\xb8\x41\x55\x51\xc4\x5d\x1d" + "\x54\x9e\x9d\xfc\x41\xee\x86\xb1" + "\x0d\x61\xbf\xd5\x5e\x34\x9f\x9d" + "\x9f\xca\xac\xf6\x5d\xa6\x7b\x3e" + "\x86\x94\x36\xa8\x7a\x78\xda\x9d" + "\x53\xba\xb5\x8e\xb7\xda\xf9\x09" + "\xc3\x1b\x48\xd6\x33\x20\xfb\x5a" + "\x04\x21\xa6\xaf\x30\xce\xf4\x76" + + "\x3d\xc9\x0a\x7b\x77\xa6\xd6\xeb" + "\xd7\xe0\xf5\x78\x0d\x7b\xe3\xa6" + "\x2b\x49\xf5\x76\x96\xc0\x16\x25" + "\x3a\x5f\xc0\x9a\x88\xf8\x4b\x1e" + "\x2b\xba\xf0\x4d\xe0\x2c\xb4\xcd" + "\x1b\x34\x62\x50\xfd\x5c\x5d\x93" + "\x20\xac\xac\x82\x33\x33\x30\x8a" + "\x0e\xb0\x98\x51\xc4\x38\x94\x42" + + "\x24\x8e\x1f\x5a\x3c\x18\x99\x3f" + "\xf0\x55\xd2\x9d\xfa\x18\xb1\xfd" + "\xa6\x62\x7f\xc2\x90\x8b\xb1\xb9" + "\x91\xc1\x6e\x39\xf7\x32\xf7\xe8" + "\xab\x86\xe7\x0b\x91\x2d\x4a\x52" + "\xf5\xa0\xc5\x0a\xef\xad\x32\x5d" + "\x94\xf6\x25\x97\xd6\xd4\x53\x9b" + "\x89\xba\x10\x05\xc6\x76\x2a\x03" + + "\x1c\xb1\x58\x57\x59\x5d\x9b\xa4" + "\x40\x4f\x65\xc8\x93\x28\x85\x0b" + "\x47\x94\x37\x52\xf4\xf6\x3e\xb6" + "\x0c\x69\x5e\x10\x29\x7d\x95\xd4" + "\xb0\x59\x65\x64\x63\x43\x48\x7d" + "\x8e\x8a\x78\x49\x3c\x27\xa8\xf4" + "\xa9\x54\xce\x34\xb8\x6c\x40\xee" + "\x9b\xda\x6f\xf8\x0f\x26\x1c\x1e" + + "\x50\x47\x95\x0e\x74\x79\xbd\x9d" + "\xc6\xd2\xf9\x64\x88\xde\x21\x01" + "\x2e\x23\x85\xd9\x42\x7b\x59\x2e" + "\x77\x17\x45\x53\xc5\xc3\xb6\x55" + "\xfb\xb9\x9c\x51\x47\xe5\x53\xbb" + "\x0d\x60\x28\x84\x9f\x01\x34\xf1" + "\x1a\x79\x81\xe0\x76\x31\x47\x5a" + "\x08\x0c\xfb\x35\x63\x22\x3e\x2f" + + "\xe0\x73\xe5\x67\xbe\x38\x28\xfb" + "\x4b\xc4\x84\x40\xb9\x1d\x89\x05" + "\xc5\xc2\xc1\x96\x73\x13\x31\x91" + "\x4b\x44\x58\xd9\x3f\xfa\xeb\x6a" + "\xc1\x55\x6e\xe5\xe9\xdc\x9c\xac" + "\xd0\x46\xaa\x2c\xd3\xce\x48\x71" + "\xeb\xe8\x1f\xb6\xef\xc7\x10\x2e" + "\x4d\xcf\x97\xff\xda\x35\xd8\x9f" + + "\xdd\x99\x1d\x43\x8d\xa1\xed\x9b" + "\xe1\xcc\xd5\xf3\x3d\x0b\x69\xf7" + "\xc9\x6e\x32\xb7\x6d\x65\xfb\x97" + "\x9c\x73\x95\x8c\x44\x71\xb2\xc1" + "\x98\xe2\x21\x9c\x89\xea\xec\x65" + "\x34\x57\x35\x37\x91\x72\xe5\xd0" + "\x3d\xeb\x65\x21\x2b\x7c\xbd\x80" + "\xc0\xf1\xc0\xdc\xe7\x16\x1e\xdf" + + "\x32\xc8\x07\x0c\xad\x8f\xe5\x97" + "\x9b\x43\xc3\x41\xa4\x50\xee\x73" + "\x20\x0e\x1f\x8e\xa4\x43\x06\x23" + "\xa3\xc6\xeb\xce\x8b\x7f\x3c\x53" + "\xb5\xe1\x63\x71\xb3\x47\xa6\x4d" + "\xfa\x26\x0b\x41\x4c\x0d\x65\x1a" + "\xfb\xfd\xe8\xdd\x64\x3a\xa5\x0d" + "\x73\x0c\xd8\x88\xdf\x86\xe7\x0c" + + "\xca\x0a\x8f\x23\x27\x92\xcf\x19" + "\xfd\x4c\xac\xab\xd4\xad\x86\x63" + "\x7f\xde\x5c\x5e\xa0\xc4\xb6\x17" + "\x07\x56\xaa\xc9\x58\x57\x2b\x17" + "\x8c\xe7\x01\x5f\xc5\x65\xa2\x0f" + "\x1e\x4d\x12\xdc\xfb\xfd\xb2\x1f" + "\xf8\x23\xf2\x9b\x3c\x8d\x23\xcf" + "\x6b\xbb\x94\x03\x8d\x2c\x5c\x3c" + + "\x16\x06\x77\xc1\x56\x6f\x62\x6c" + "\x2d\x9a\xda\x09\x9e\x90\x51\x53" + "\x45\x0e\x73\xa3\x25\x68\x8e\xe5" + "\x79\x0a\xef\x03\xc0\x8b\x8c\x9d" + "\xfd\xec\x6b\x05\xb6\x78\x3f\x54" + "\x6d\xb3\x90\xa0\x53\x32\xf1\x33" + "\xf9\x32\x44\x79\x97\x49\xad\x82" + "\x02\xf5\x21\x47\x3c\x49\x86\x13" + + "\x14\xd7\x9e\xd4\xf1\x13\xc4\xdc" + "\xd8\xb4\xc2\x6a\x27\xd6\xd3\x18" + "\xf8\xbc\x47\x53\x45\x7a\x15\x0f" + "\x44\xc9\x94\x26\x12\xf4\x13\x4a" + "\xdd\x00\x77\x39\x7c\xbf\xab\xe3" + "\x39\xef\x4e\x6c\x91\x8a\xa8\x72" + "\x9c\x47\x06\x46\xdb\xf8\x49\xb1" + "\xb3\xd3\xc2\x54\xab\xb1\x44\xff" + + "\x09\x3d\x83\x4b\x36\xac\x75\x88" + "\x9b\x5c\xed\xf0\x12\x77\xc9\xca" + "\x0d\x52\x81\x02\x8f\x5d\xf5\x7a" + "\x37\x62\x93\x46\x3b\x47\xf7\x06" + "\xd6\x84\x6f\xfe\x51\xca\x5b\x8a" + "\xa7\x4f\x27\x84\x4b\x6f\x4b\x76" + "\x1d\xc0\x64\xb9\xdc\x91\x30\xfa" + "\x46\xb8\x3a\x0a\xf6\x26\x1f\x6d" + + "\xf0\xcf\xc0\x8a\x5f\xf5\x0b\x0d" + "\x54\xeb\x50\xc1\x82\x88\x59\xd9" + "\xd0\x93\xc2\x51\x2c\xa7\xa4\x22" + "\x8a\x19\x3c\x64\xf6\x57\x6c\xf8" + "\x10\x57\x39\x20\xb0\x91\xab\x97" + "\xc0\xdb\x70\x19\x6c\x71\xe1\x9a" + "\xf8\x3d\xe5\xcc\xa2\x2b\x7a\x5b" + "\x4c\xd6\x85\xfc\x99\x9a\x79\xb2" + + "\x2a\xa8\xbe\x5a\xfa\xee\x94\x37" + "\xd4\x62\xfe\x93\xb9\x11\xc6\x8d" + "\x06\xf6\x1e\x28\x37\xaf\xf1\x69" + "\x69\x9e\x83\x39\xc8\x46\xf5\x6a" + "\x23\xec\x77\xc9\xc7\x78\x55\x62" + "\x76\x05\x5c\xbd\x4c\x29\xde\xa8" + "\xc0\xa4\xd1\x7c\x0f\xaf\xdd\xe2" + "\xd4\xf4\x95\x4f\x70\xfc\x43\x82" + + "\x12\x18\xe7\x50\xda\xab\xc5\x94" + "\x7c\x6a\xbb\x03\x35\x74\x94\x02" + "\x14\xbf\x8f\x79\xab\x53\xa1\x02" + "\x4e\x28\x2f\x7a\xc8\x26\xef\xf8" + "\xdc\x9e\xf9\x05\x5d\x92\x3c\x86" + "\xdd\x35\x9b\x40\xe6\x81\x6d\x97" + "\x70\x91\xe9\xdc\x99\x5a\x3a\xef" + "\xe6\x1d\x13\x53\xec\x80\xbc\xaa" + + "\x35\xb3\x40\xc9\x64\x7c\x41\x19" + "\xe9\x97\x6e\xaf\xf5\x4e\x45\x51" + "\x9c\x30\x16\xed\xac\x9b\x3c\x76" + "\x04\x48\x46\x81\x4d\x17\x6d\xe2" + "\x97\x74\x19\x35\x86\x42\x5a\xa0" + "\x09\xb1\xed\xad\x71\xfa\x10\xa4" + "\x6e\xf7\x95\xda\xb7\xca\x19\x72" + "\x1f\xd1\x88\xbe\xe7\x23\xc3\x74" + + "\x3c\x10\xdb\xb2\xd6\x91\xbb\xe1" + "\xe3\xc2\xe2\x92\xb1\x3d\x59\xbe" + "\xc1\x25\x5e\xb4\xca\x49\xf9\x53" + "\x23\x2f\x6e\x0a\x16\xe6\x39\x6a" + "\x0a\xd7\x57\x13\x6e\xe2\x13\x02" + "\x9c\x3e\x62\x8e\x1a\x1c\x74\x73" + "\xb2\x99\x93\x8d\xba\xa9\xdf\x54" + "\x32\x8c\x59\x0c\x40\x0c\x31\x86" + + "\x3a\x73\x08\xb0\x00\xf4\x66\xe5" + "\x57\x1f\x2e\x51\x7d\x69\xa0\xcb" + "\xd0\x9c\x50\x40\xb2\xc2\x37\x95" + "\x8c\x3d\x35\x57\x69\x9c\x98\x5f" + "\x2f\x2b\x3c\x4c\x72\xc9\xbe\x7d" + "\xa8\x1f\x03\xff\xa8\x2f\xe0\x90" + "\x1f\xd1\xd5\xcf\x53\x5c\xd1\xf4" + "\xfc\x4d\x31\x48\xae\x4f\x40\xb3" + + "\xef\x5f\xca\xb4\xa3\xbb\xf0\xb6" + "\x08\x90\xd1\x0f\xe2\xfc\x19\x49" + "\xdc\x2a\xd1\x1b\x8d\xd1\xb4\x18" + "\x9c\x8e\x1c\xc8\x88\x3a\x2f\xb2" + "\x49\x29\x7c\xcc\x2c\xb1\xf5\x86" + "\x7f\x98\xde\x05\xd8\x1a\xf6\xa2" + "\x70\x79\x72\xed\x72\x21\x74\x69" + "\xc7\x4e\x43\xd7\x8e\x2c\x9f\x3e" + + "\xb4\x52\x2c\x21\xf8\x0e\x49\xd1" + "\x7b\x5a\xb7\x00\xea\xfd\x2f\x5b" + "\xa1\x8b\x95\xbf\x3e\xb2\xc7\xf2" + "\xaa\xba\x6c\x69\x39\x20\xb4\x43" + "\x96\x34\xbe\x02\x94\xde\x5b\x1f" + "\xc4\xa5\xef\x39\x6b\x9d\xbe\x3a" + "\x82\x7e\x07\x47\xde\x7f\x20\x2a" + "\x28\x29\x86\x65\xfc\x74\xc3\x3b" + + "\xc4\x04\x06\x54\x1d\x0e\xd4\x35" + "\xed\x6f\x48\x3a\x3a\xb3\xa4\x16" + "\xa1\xa4\x43\xee\x6c\x49\x70\x91" + "\xaf\x8a\x94\xad\xe1\xdb\x4a\x17" + "\x99\xdf\x51\x54\x0a\xa3\x47\x8a" + "\xa1\x91\x17\x9e\xd1\xbd\xca\x7c" + "\x2a\xf1\xfc\xec\x3a\xb5\x12\x71" + "\xd2\xc6\xb5\xfa\x95\xb3\x1e\x56" + + "\x87\x93\x1e\x08\x09\xa1\x6d\xa3" + "\x28\x58\x93\x8c\xd7\x80\x97\xfb" + "\x15\xb0\x40\xe5\x32\x03\x94\xd5" + "\xfa\x66\xf4\xe0\x1b\xb5\xd7\xc9" + "\x71\xf6\xd9\xd6\x41\xcd\xad\xfa" + "\x17\xac\xa2\xb1\x28\x1e\x6c\xba" + "\x5f\x1e\x20\xed\x33\x78\x6a\x06" + "\x2b\x46\x0f\xf9\x19\x97\xd9\x19" + + + "\x61\x5f\x0b\x06\x62\xf4\x31\xf4" + "\xc2\x57\xd0\x7b\xb4\x46\x6f\xa5" + "\x65\xbf\xe1\x47\x6c\xca\x8d\x34" + "\xff\xf1\xbc\x41\x3e\x78\x38\x9a" + "\x18\x07\x71\xda\xa9\x33\x5d\x7a" + "\xf6\xea\x0a\x2e\x87\x99\x77\x5a" + "\x87\xd1\x29\x2d\x4d\x31\x87\xca" + "\x33\xd7\x87\xc6\x3e\xdc\x0e\xfa" + + "\xc7\x8a\x19\xcb\x49\x48\x89\x1c" + "\x65\x46\x26\x0f\x3d\xa9\x84\xa8" + "\x78\x06\x20\x9b\xef\x64\xa9\x2d" + "\xe6\x34\x98\x00\x87\x1b\x35\x3c" + "\x4b\xb4\xc4\xe2\x9f\xef\xb2\xaf" + "\x0c\x79\x26\x33\x47\x6c\x0f\x58" + "\x4a\x26\x02\x0b\x21\x05\x48\xb8" + "\xe2\x94\xa1\x42\xe2\xf9\xa6\x8b" + + "\x0e\x3c\xb0\x5e\xb6\x6a\x9b\x49" + "\xde\x3f\xbc\x72\x54\x79\x9b\xf1" + "\xd2\x80\x3a\x6e\x9c\x5b\x6b\xa8" + "\x9f\x81\x42\x6d\x08\x75\x37\xe4" + "\xa3\xe8\x3e\xbb\x50\x36\x66\xc1" + "\x5f\x07\x32\xb1\xfc\x14\xeb\x75" + "\xf6\x34\xd8\x7a\x06\xc9\xcc\xa8" + "\xfd\x2f\xe9\xe6\x74\x24\x6a\xea" + + "\xf1\x95\xc0\xd3\xab\x34\xd9\x39" + "\x71\x6d\xb7\xe4\xbe\x61\xb2\x04" + "\x84\x69\x3e\xe7\x70\x69\x2e\x1d" + "\x11\xcb\x5f\x5e\x3b\xb2\x9f\x87" + "\x90\x54\xd7\xdf\x72\x6c\x50\x11" + "\xc1\xf1\xbc\x61\x85\xd0\x97\x3a" + "\x07\x70\x5e\xbf\x82\x1d\x20\x43" + "\xa7\x32\x82\x79\x2f\xc5\x0a\x7f" + + "\x36\x91\x04\x4b\xee\x20\x4d\xcb" + "\x13\x46\x6a\x35\x12\xbf\x63\x8b" + "\x28\x81\xe0\x70\xf6\xae\x21\x12" + "\x16\x6b\xcb\x4a\x51\x8c\x2d\xe6" + "\x96\x78\x9e\x37\x67\x4a\xf6\x71" + "\xa5\x7f\xfd\xca\xa2\x37\x52\xb2" + "\x6a\xba\x41\x38\x98\xbd\x77\xf0" + "\x7e\x6e\xd1\x3c\x44\x02\xac\xc4" + + "\x82\x76\x9d\x31\xfb\x01\x51\xb2" + "\xee\x2f\x98\x0a\x29\x31\x29\xb0" + "\x44\xb3\x61\x02\xb9\xc9\xc1\x51" + "\xfa\x71\xd3\xbf\x5b\x8c\x00\x0e" + "\x33\xca\x78\x02\x1c\xdd\x66\xd8" + "\xb1\x53\xaa\xe5\xa6\x76\x6f\x66" + "\xcf\xa2\x13\x60\x79\xb7\xcf\xe5" + "\x36\x18\x52\xa3\xad\x1a\x3a\x1d" + + "\x9c\x5f\xf7\x50\xff\x04\x56\x3c" + "\x22\x2b\x75\x7e\xf3\xdd\x8e\x1d" + "\x18\x11\x9a\x3c\xdd\x74\xf0\x0e" + "\x7b\x6d\xb8\xcc\x72\xc1\xff\xd0" + "\xf2\x90\x7d\x03\xe3\xec\xd1\xab" + "\x6c\x85\x55\x60\xd6\x07\xf3\xe3" + "\xaf\x6d\x4c\x7e\x28\x93\x2f\x42" + "\xa0\x79\x48\x33\x66\xac\x2a\x90" + + "\xec\x93\x71\x56\x1a\x13\xb4\x76" + "\x0b\xe7\xf6\xe5\x5a\x30\x3c\xaf" + "\xdd\xeb\x1e\x03\x39\xbd\x87\x95" + "\x31\xe8\xbb\x71\xf8\xde\x09\x57" + "\x69\xb6\xb2\x0e\x83\x99\x05\x57" + "\x29\x70\x5b\x87\x1b\xce\x80\x4d" + "\x16\xac\x64\x03\xa8\x7d\x8a\x83" + "\xab\x83\x1c\xbe\x23\x1d\x43\x2f" + + "\x1e\xc7\x40\xb9\x4c\x87\x52\x8e" + "\x3a\x4b\x5f\xdb\xa9\x35\x19\x21" + "\xc3\x1d\x1b\x30\x92\x04\x35\x94" + "\x20\x86\x95\x29\x6d\x64\xd2\x33" + "\x04\x14\x91\xef\x4b\xd6\xb0\x16" + "\xf4\x5e\x3c\x9a\xea\x25\x1f\x9d" + "\x78\x2c\x35\x4a\xeb\x00\xf2\x20" + "\x28\xb4\xd0\x4b\x2c\x9f\x92\x43" + + "\x4e\x5d\x23\x38\x66\x27\x81\xe7" + "\x98\x32\x6e\x49\x67\xbd\x62\x1c" + "\xc8\x5b\x17\x3f\x0c\x66\x78\x83" + "\x4d\xdd\xaf\x17\x89\xe1\x04\x4d" + "\x8c\x06\xa8\x85\x01\x16\xa8\x32" + "\x85\x9a\xb2\x92\xe1\xe4\x58\xdb" + "\x3b\x8a\x0d\xc7\x86\x5b\xa6\xe8" + "\x3b\x40\xa0\x98\x4e\x6f\x0e\x5f" + + "\x9e\x9f\x2c\xe8\xe6\x36\x46\xd4" + "\x43\x10\x3a\xc3\x7c\xb8\x1d\x71" + "\x05\xec\x8a\xaa\x63\x12\x43\x6f" + "\xaa\xa4\x44\x27\x0d\x12\xff\x43" + "\x9b\x77\x77\xae\x2f\x89\xbd\xd3" + "\x82\x9f\xdc\x8c\xc9\x0c\xfe\xf0" + "\xbc\xb1\xc5\xf1\xe6\x7f\x5f\xca" + "\x72\x9a\x92\x44\x82\xa6\x63\xcc" + + "\xe0\x4a\x89\x3f\xb7\x92\x24\x2c" + "\xce\x18\x5f\xb7\xe5\xf3\x9d\xf5" + "\xd0\xca\x53\x8f\xd2\x40\xb7\x7c" + "\x94\x12\xf0\xc4\xfb\x85\xb5\x3e" + "\x17\xf7\xc7\x32\x86\x0c\xda\x17" + "\x4c\x3f\x94\xaf\x5b\x79\x8c\xeb" + "\xd2\x51\x7c\xf6\xb5\x3f\xe2\x4e" + "\x49\x99\x88\x68\x75\x75\x18\xef" + + "\x6f\xff\x8d\xb3\x3e\xda\x34\x28" + "\xe8\x6b\x63\xea\x52\x2c\x01\xbe" + "\xf8\x37\xdd\x61\x8c\x23\x2d\x29" + "\xdb\x42\x81\x8f\x3f\x52\x54\x0e" + "\xd8\x05\x6a\x03\x36\xb4\x1e\xe3" + "\xff\xc0\x93\x1e\xff\xcd\xe3\x83" + "\xdf\x1d\x82\x50\x0f\xfe\xd2\x3f" + "\x3b\xb3\x9e\xff\x0d\x9b\xe1\xc8" + + "\xd0\xf0\x22\xe8\xa4\x11\xa0\x3e" + "\xf8\x04\x87\x5a\xd1\x7a\x64\xbc" + "\x0f\x82\xc6\x50\x35\x5b\x31\xbb" + "\xec\x6b\xe7\xb7\x3d\xec\x3d\x86" + "\xc7\xbf\x17\xf0\x3a\x5d\xff\x01" + "\x29\x82\x6b\x97\x39\x44\x05\x20" + "\x3b\x0d\xbd\x0b\x37\xca\x7f\x06" + "\x0f\x3d\x5e\x7f\x64\xde\x3d\xf6" + + "\x95\xa8\x9c\x5e\x52\x90\x7d\x14" + "\xdf\x72\x20\x97\x1e\xd3\x4d\x2f" + "\x5c\x75\xc6\xe6\x8e\xda\x6f\xa1" + "\x58\x65\x19\xcf\xff\x26\x68\xc6" + "\x95\x38\xf4\x0c\xa3\x76\x1a\x1f" + "\x7b\x09\xc3\x83\xe0\x04\xd6\xa9" + "\x0e\x0e\x39\x66\x09\x83\x90\xe1" + "\xff\x5e\xc8\xb3\x53\xf7\x0b\xa5" + + "\xcf\xcc\xf7\xad\x15\xbc\xd9\x75" + "\xb0\xe1\xa1\xdf\xd6\xe5\xa3\x81" + "\x7e\xc1\x9b\x24\x44\xe4\x39\x8c" + "\x43\xfd\xa7\x8e\xb2\xcc\x7d\xf3" + "\x12\xba\x7f\x90\x73\x48\x65\xda" + "\x04\x29\x37\x4a\xda\xa6\xda\x35" + "\xc5\xa6\x83\x62\xc6\xcf\x64\x05" + "\xbf\x95\x93\x4a\xf6\xa4\x9f\xd0" + + "\x31\x84\x56\x6f\xa7\xf9\x64\x0d" + "\x8c\x89\xf8\x02\x7c\xc2\x48\xf8" + "\xd5\x5b\x0b\x26\xe1\xad\x18\xf4" + "\xe8\xde\x73\x69\x23\xe3\xf3\xc1" + "\xdd\x85\xc1\x26\x9c\x31\xe9\x46" + "\xc4\x0a\x6f\x54\xd8\xb7\x85\x6d" + "\x57\x9d\x7f\x24\xf2\x65\x79\x42" + "\x48\x5f\x03\xb0\x36\xb6\x19\xb5" + + "\xff\x9d\xa3\x6a\xb5\xb3\x10\xb5" + "\x8c\x4d\x8e\x9f\xa2\x3d\xb4\x59" + "\x9f\x4b\x4c\x9e\xfd\x31\xce\xa8" + "\x01\x3c\x30\xc1\x26\xbe\x20\x0e" + "\xc9\x47\xee\xe8\x82\x71\x18\x18" + "\x01\x81\xb9\x7d\xdb\x7c\x68\xd9" + "\xf6\x4f\xe1\xa1\x4d\x0e\x52\x7a" + "\x72\xd5\x36\x88\xba\x08\x98\x42" + + "\xc6\xe5\xa9\xdd\xe5\xc1\x2a\x68" + "\x95\xfc\xa9\xca\x72\x3c\x0d\x4e" + "\x44\xea\x2b\x77\xde\xaa\xfa\x17" + "\xc8\x09\x00\xab\x8c\x42\xf8\x5e" + "\x16\xf0\x0f\x46\x7a\xe4\x4c\xcc" + "\xcb\x81\x52\x72\xbf\x12\x6d\xda" + "\xd2\xaa\x23\x02\x48\x78\xc6\x44" + "\x28\x6e\x25\x36\xfa\x2a\x34\x6e" + + "\x8e\x76\x16\x6d\x99\x46\x4d\x17" + "\x17\xf2\x8b\x62\x6a\xff\xc4\x9f" + "\x0d\x49\x4e\x15\x94\x5a\x70\x77" + "\x7a\x99\x2d\x8d\x28\xdd\x96\x9d" + "\xc4\x72\x5d\xce\xd8\xd9\xe2\x77" + "\x4f\x71\x1c\xc1\xa4\xc5\x06\x9d" + "\x3e\xa0\xe4\x79\x36\x51\xaa\x02" + "\x8b\xf2\x0f\x03\xc2\xb3\x86\x13" + + "\xc2\xc9\xce\x8b\xb6\x86\x61\xb8" + "\x06\x9f\x0b\x68\xf9\x4d\xf2\x7c" + "\x81\x92\xd2\xc0\xea\x45\x6b\xc4" + "\x12\x0e\xb1\x07\xc5\x2b\xf4\xff" + "\x27\x94\x28\x4d\x40\x3c\x26\x12" + "\xc4\x8e\x84\xb4\x99\x18\x5f\x3d" + "\x0c\x80\x40\xd0\x10\x70\xf9\x11" + "\x20\xeb\x0f\x30\x29\xf5\xc5\xb4" + + "\x3a\xdc\x40\xea\x69\x2d\xa4\x26" + "\x8f\x01\xcc\xae\x22\xad\x84\xdc" + "\x4a\xf0\x70\x32\x7b\x6c\xc3\x25" + "\xed\x72\xfa\x50\x47\x6d\xba\x46" + "\x8e\x8a\xe5\x93\xc5\xd1\x37\x6c" + "\x8c\x08\x0c\x12\x31\x47\x39\xa2" + "\xda\x86\x6e\xcb\x63\x42\xbe\xc3" + "\x38\xd0\x26\x71\x36\x7d\x41\x2c" + + "\xd0\x59\x71\xb0\x6d\x11\x3d\x9d" + "\x10\x62\x89\xc1\x7f\xa6\x07\xae" + "\x79\x15\x96\xbb\x87\x4d\xc8\x8f" + "\xd6\x8d\x1f\x1c\x49\x9e\x00\x30" + "\x19\x28\x13\xe3\x22\xaf\x8c\x8a" + "\xff\xb4\x3a\xf2\x7c\x19\xfa\xcf" + "\x87\xd6\x5d\x20\x44\x3a\x10\x58" + "\xa2\x67\xed\x0d\xc3\x96\xb7\x57" + + "\x29\x22\x0e\x44\xbb\x23\xa5\xcc" + "\x04\x4d\xef\x73\xa2\x73\x46\x32" + "\x39\xec\x11\x3e\x34\xdf\x3a\xaf" + "\xd3\x68\x59\xdc\xf1\xd7\x36\x61" + "\x27\xa9\x53\xb0\x99\x28\x7b\x7a" + "\xcd\x7e\x06\xae\x61\x26\xaa\x3e" + "\xd9\x9c\x77\x02\xc8\xb9\x49\x85" + "\xea\x85\x33\xc5\x40\x79\x1d\x06" + + "\xe7\x3c\xe9\xb3\x89\x7a\xd2\xd7" + "\x1b\x2c\x3a\x5d\x75\xa8\xb5\xf7" + "\x8a\x21\x5b\x25\xa0\x68\x9e\xb2" + "\x54\x67\xf7\x8a\x7e\x83\x33\xb5" + "\x2e\xab\x9f\x57\x73\x5a\xb0\xd1" + "\x85\x43\xd7\xec\xa1\x55\x10\xb4" + "\x15\x91\x5e\x44\x74\x92\x36\xb2" + "\x4e\x27\x20\xf5\xc4\xa7\x72\x29" + + "\x2b\x90\xa2\xaa\xfc\x41\x71\xe0" + "\xd3\x9a\xf6\xe4\x99\xd7\x9a\x53" + "\xfd\x9f\x3f\x81\x94\x3f\x45\xa6" + "\xf7\xc2\x5b\x37\x48\x3c\x8d\xc5" + "\x96\x4e\xc6\x5d\xad\x6f\x32\xb3" + "\x54\xe3\x40\xb2\xa9\xca\xaf\x3a" + "\xa9\xe7\xa1\xac\x03\x09\x1b\x1d" + "\xa0\xb8\x11\x12\x67\x97\xeb\x4c" + + "\xa0\x10\x17\xc8\x79\x2e\x94\x5e" + "\xd4\xad\xcc\x27\x36\x4a\x7e\x55" + "\x0c\x6d\xcf\x4b\x56\xbc\xa2\x72" + "\x0c\xb8\xd7\x26\x43\x5f\xee\x09" + "\x19\x2f\x29\xd4\xe9\xdb\x70\x6b" + "\x18\x6b\xf1\x63\x26\x4c\xf7\x56" + "\x2a\xb4\xfb\x35\xf7\xb0\x3d\xc2" + "\x40\x00\xe1\x6a\xf6\xbd\x06\xb6" + + "\x58\x2d\x03\x87\x46\xde\xb4\x1e" + "\xe0\x79\x2c\x5e\x83\x3d\x4f\xc5" + "\x23\xef\x04\x5d\xf4\x8d\x81\x07" + "\xb4\x41\x3d\x67\xc8\xa9\xfa\x55" + "\x55\x53\xb9\x89\x6f\x4f\xd6\xce" + "\x84\x5c\x41\xb7\xea\xd2\x60\x48" + "\xd3\xba\x0e\x05\xd2\x9b\xdb\x5f" + "\xbf\xa5\x85\x66\xcc\xe0\x53\xdb" + + "\xb3\xa7\x1e\x8b\xa0\xd2\x61\x9a" + "\x85\x14\x8b\xae\x63\xab\x95\xd4" + "\x99\x2f\x05\x87\x84\x0f\x74\x38" + "\xea\x4e\x97\xb2\x5b\xbe\x8e\x17" + "\x7f\xd1\x36\x5b\xca\xbc\x0b\x03" + "\xea\x6e\xf8\xaa\xe3\xcc\xe4\xb5" + "\xe0\xe9\xf8\x68\x20\x02\x1a\xb5" + "\x75\x3e\xeb\x09\x96\x87\x34\xa4" + + "\xca\xe1\xfa\xab\x5f\xca\x9f\x91" + "\x9b\x45\x21\x1a\xac\xfa\x7a\x93" + "\xd2\xa4\x66\x1f\x1c\xa9\x0c\x9e" + "\x31\x13\xec\x23\xf3\xc7\x4c\x19" + "\x90\x16\xa1\x8a\x3a\x14\x25\xad" + "\x08\x9e\xb5\x09\x8d\xad\x40\xbe" + "\x0a\x86\x50\xe7\x9b\x0d\xd6\x37" + "\x4c\x43\xbf\xc6\x08\xb0\x53\x6c" + + "\x17\xc5\x3e\x1d\xd0\xa0\x61\xa6" + "\xae\x21\x23\x51\x52\x46\x74\x98" + "\x98\x25\xa9\xec\x91\xa5\x4c\x08" + "\xeb\x3f\xcb\x1d\xc9\x9d\xbb\xa9" + "\x40\xc2\xb4\x78\x55\x43\xc5\x14" + "\xdc\xaf\x0c\x61\x3b\x2a\xd6\x5e" + "\x6b\x84\x38\x1b\x37\x2f\x51\x07" + "\x61\x81\xe3\xb0\x0a\xb7\x1b\x57" + + "\x2d\x24\x6b\xeb\x80\x70\x2d\x83" + "\x46\xe2\x71\x3b\x23\xd0\x0b\xd3" + "\x9d\x13\x31\xbe\x1b\x99\x27\x70" + "\x53\x4e\x2e\x46\x91\x7e\x79\x68" + "\x5a\x18\x4e\x6b\x0a\xe2\x3f\x42" + "\x07\xb7\xd9\x42\x7e\xc6\xf2\x82" + "\x1b\x81\xf7\x4c\x68\x17\xc8\x25" + "\x5d\xb9\x5b\x04\x5e\x00\x53\xbd" + + + "\xfd\x68\x8e\x9d\xbe\x49\xf6\xe5" + "\x20\x43\x04\x1b\x33\x05\x0f\xdb" + "\x98\x33\xc3\xe0\xb3\xe9\xfd\xf6" + "\xae\xcf\xc8\x66\x9b\x20\xf4\x92" + "\x4b\x9d\x73\x1a\xcc\xaf\xd1\xe9" + "\xde\xb8\x8a\xa2\x5f\xa7\xae\x09" + "\xd0\xf1\xc6\xea\xb5\x5f\x37\x14" + "\xa5\x7a\x8f\x70\x60\xb5\x20\x64" + + "\x41\xdc\x54\x62\x9c\x49\xae\x9e" + "\x7e\x7e\x83\x7a\x24\x39\x29\x7e" + "\xa7\x24\x05\x09\x8c\xc0\xae\x74" + "\xf2\x55\x6f\x8d\x19\x92\x2b\xf8" + "\xc5\xce\x02\x14\x2e\x96\x3c\x49" + "\xe7\x30\x2f\xfa\x17\xca\x17\x9f" + "\xcb\x79\xb8\xe9\xe8\x83\xd7\xbc" + "\x5f\x14\x6f\x5a\x14\x8c\x3d\xea" + + "\x6e\xee\x0d\x5e\xe7\x15\xde\xde" + "\xa2\x8a\x62\xdc\x72\x48\xf2\x74" + "\x93\xbb\x61\x78\xfe\xc4\xe9\xd3" + "\xe0\xb2\x87\x61\x2a\x82\xd4\x56" + "\xf9\x26\x98\xc5\xcf\x17\x64\xb6" + "\x9e\x16\x08\x24\x69\x09\x26\xca" + "\x85\xf8\x9e\xc7\x06\x9d\xf6\xed" + "\x8f\x13\x7d\xdc\x8a\x1f\x03\x00" + + "\x26\xf7\xbc\x0e\xe6\x46\x3c\x10" + "\x0e\x47\x31\x62\x31\xb8\x82\x44" + "\x09\x21\x7c\x48\xca\xfa\x6d\x6f" + "\xef\x66\xe6\x62\x97\xce\x0a\x2e" + "\x42\x1f\x8d\x1f\xd3\xa9\x46\x32" + "\xd2\x44\x49\x57\xf1\x83\x1e\x1b" + "\x4b\x33\x7f\xa5\x3a\xa6\xdf\x13" + "\x81\x5d\x02\x9f\xed\xda\xf8\x0c" + + "\xc1\x11\xee\x00\xa8\x8e\xd7\x30" + "\x75\xdd\xe3\xb5\xd4\x3c\x05\xeb" + "\xc5\x43\x8c\xd5\x3e\xb1\x65\x9b" + "\x63\x16\x15\xbd\xbd\x49\xad\xc3" + "\x90\x79\x42\xb6\x41\x8e\xfd\x99" + "\x1e\xae\x7e\x70\xbd\x15\xcf\x12" + "\x1e\xb7\xab\x1a\x1b\x4f\xad\x29" + "\x0e\x5d\x54\x07\x4d\xe7\x43\x51" + + "\xe1\xde\x8b\xc8\x36\x63\x26\x30" + "\x7c\x76\x76\x58\x06\x93\xf2\x25" + "\x96\x19\x73\xc6\x71\x85\x07\x9c" + "\x51\x29\x55\xed\xb2\x90\x86\xc8" + "\xb4\x05\x27\x85\x2d\x2c\x4f\x27" + "\x2d\x55\x09\x4e\x44\x8d\xbf\xb0" + "\xd1\x75\x65\x98\xeb\xbe\x28\x76" + "\x51\x46\x86\x7f\x38\xe2\x7b\x40" + + "\x6b\xfc\x39\xa6\x49\x30\x5e\x0e" + "\x25\x36\x00\x86\xd9\x35\x5c\xe7" + "\x46\x16\xcc\x5d\xd8\x5b\xf3\x0c" + "\x3a\x27\x26\x6c\xd2\xce\xca\x8b" + "\x42\x67\x53\xb5\x1d\xcf\x2e\xe2" + "\x8b\x06\x9e\x1a\x97\xd8\x3d\x01" + "\xc5\x09\x79\x8a\xcb\x11\xf4\x17" + "\x06\xd5\x1d\x86\x98\xac\x57\x57" + + "\xbb\x5a\x93\x1e\x0d\x1f\xde\x85" + "\x7a\xe3\x4d\x15\xb4\x10\xfd\xde" + "\xb5\xeb\x9c\x36\x92\xe3\xd9\xb8" + "\xbe\x24\x13\x76\x9b\xef\xd5\x54" + "\x26\x7e\xf1\x74\xba\x41\x63\x4d" + "\xe4\xdd\xc1\x78\xc8\xe3\xa0\xc0" + "\xfd\x18\xd9\x87\x81\x75\xd7\xa6" + "\x13\x3a\xca\x02\x15\x60\x87\x66" + + "\xf0\x58\x66\xf3\x9c\x3e\x31\xc7" + "\x7e\x05\xf8\x71\x1c\xef\x33\xc4" + "\x5a\x83\x6a\x1b\x46\x62\x32\x85" + "\x4c\x39\x86\x7c\x98\x53\xf0\xc8" + "\xa1\xc4\x83\xe9\xdf\x8c\x39\xff" + "\x31\xb9\xb7\x03\x62\x81\x5e\xbf" + "\x5b\x04\xb9\xb7\x46\x3c\x19\x93" + "\x6b\xe4\xa6\xa4\x5d\xbf\x4e\x1e" + + "\xe7\x4f\xa2\x43\x60\x2a\x94\xf9" + "\x2b\x49\xb3\xff\x1e\x19\xc1\x29" + "\x05\xde\x2f\x90\x49\x24\x66\x9f" + "\x2d\xc3\x13\x67\xac\xa7\x92\xc7" + "\x2c\x98\x37\xb7\xd8\x8a\xd8\x2f" + "\xe3\x60\x1e\xa2\x19\x03\x3a\x7e" + "\x1a\x59\x83\x73\x44\xde\xb0\x09" + "\x56\xa4\x10\x83\xee\x41\xf1\x6d" + + "\x71\xf4\xd6\xe6\x39\xa0\xc1\xae" + "\x2e\xd1\x98\x11\x0f\xba\xb2\x14" + "\xac\xe5\xee\x3a\x60\xa1\xc1\xeb" + "\xce\x64\xb9\xe0\x36\x48\x1f\x40" + "\x66\x3f\xd0\x4f\x96\x37\xe4\x2e" + "\x12\x3f\x8f\xdd\x49\x4e\xdb\x3f" + "\x18\x0f\x38\x29\xf6\x67\xf2\x6e" + "\x16\x4d\xa6\x8d\x70\x96\x8e\x3e" + + "\xf1\x74\x76\x20\x0c\x18\x19\xbc" + "\xdb\x8f\xae\x33\xa7\x09\x2e\x11" + "\x1e\xb7\xae\x6a\x54\x75\x66\x99" + "\xc7\xb1\x01\xe1\xf1\x2a\x43\x79" + "\xc6\xde\x2d\xde\x8f\x55\xeb\xd5" + "\x3f\x75\x57\x53\x1f\x2d\x39\x81" + "\x8a\x15\xe1\x3a\x97\x6b\xa7\xa7" + "\x91\x99\x89\x4a\xff\xbb\x6f\x41" + + "\xcf\x9d\x4a\x0d\xfd\xfd\x65\x9e" + "\x12\xdf\x4d\x94\x48\x9e\xc2\x7b" + "\x66\x68\x85\x3c\xd9\x92\x1a\xbc" + "\xe2\xdf\x98\x6e\x05\x69\x3c\x27" + "\xb8\xa6\xfa\xcd\x18\xe4\xfc\x69" + "\x9f\xc6\x61\x50\x23\xd8\x6b\x60" + "\x27\x5e\xf7\x6a\xa0\x95\xd4\x42" + "\x1f\x3a\x87\x6d\x05\xd5\xd3\x8e" + + "\x6a\x5b\xb2\x6a\x41\x28\x55\xaf" + "\x23\x45\x1a\x2b\xc7\xff\xc0\xc6" + "\x03\x9e\xc9\x21\x7b\x82\x18\xab" + "\x1b\x69\x34\x90\x48\x86\x0e\x06" + "\x98\xf3\xc7\x93\x0f\xf9\x07\x52" + "\x0b\xd1\xf8\x82\xcb\x96\x4a\x9f" + "\xe3\xf9\xd0\x3a\x79\xcd\x71\xdd" + "\xf5\x54\x3a\xfc\xd2\x35\xf4\x84" + + "\x7f\x78\x33\x8e\x5b\xc5\x03\x4b" + "\x73\x46\x38\xa6\x75\xf9\x42\xef" + "\xf0\xb9\x51\x50\xf7\x04\x73\xff" + "\xc2\x87\x1c\x74\xdc\xa1\xac\x18" + "\x80\xfe\x4b\x2d\xa7\x20\xf1\x56" + "\x2c\x73\x3e\x05\x3d\x3b\x82\xfd" + "\x16\xca\x37\x75\xe4\xcf\xbc\x11" + "\x6b\x99\x5a\x1b\x74\x9c\x6c\xdf" + + "\xfa\xc3\x4f\x90\xc7\x32\x73\xee" + "\x6a\x63\xe3\xc7\x45\x3f\xa2\x14" + "\xaa\xd9\x91\xf0\xc3\x59\x86\xc3" + "\x40\x85\x2d\xb1\x5d\x5e\x99\x4a" + "\x8a\x59\xa5\xf3\xec\x3b\xa5\x20" + "\x95\xa9\xea\xb1\x17\x4b\x53\x56" + "\x3c\xe0\x04\xbf\xa4\xdc\xd3\x9e" + "\x68\x62\xd5\xd8\x3a\x56\x6c\x71" + + "\xe7\x78\x61\x1d\xa4\x77\xba\x27" + "\x8e\xff\xa1\x68\x40\x0c\xc8\xe4" + "\x3d\xf6\x13\x0a\x99\x10\x01\x75" + "\xf3\x46\x1d\xa6\x21\x35\xf3\x7b" + "\xbb\x65\xb3\x10\x8e\x21\xff\x0a" + "\x75\xea\xd7\x0f\x04\x18\x02\x81" + "\x25\xa9\xb3\xa4\x8a\xfd\xa3\x05" + "\xe6\xb4\x3d\x9b\x5f\xe7\x29\xb8" + + "\xfb\xe5\x53\x4d\xa5\x75\xdc\x6b" + "\xe3\x17\x27\xd5\x02\xdc\xa5\x04" + "\xc2\x2e\xa4\xe9\x2f\x50\xaf\x86" + "\x82\xe3\x30\x26\xfb\xe8\x67\x88" + "\x9b\x88\xc9\xbe\x6e\x5c\x84\xbf" + "\x8d\xc9\x47\xcb\xf2\x91\xf4\x54" + "\x12\x2a\x0c\x79\xba\x1f\x09\xa3" + "\x8b\x70\x0f\xc2\x78\xfd\xf6\xd7" + + "\x17\x5e\xde\xac\x30\xac\x69\xa5" + "\xd7\xb4\x52\x68\xd0\x96\xf9\xd0" + "\x54\xae\x09\x46\xb5\x4b\x1d\xe5" + "\x61\xd0\xae\x0d\x17\x7d\xa3\x3f" + "\x41\xfb\xb8\x34\x84\x86\xa8\x62" + "\xf1\x64\xfb\x9e\xbd\xac\xa2\x99" + "\xf2\xe1\x48\x64\x5e\x1a\x5c\xb7" + "\x69\xa0\xb5\x42\x1a\x95\x99\xfa" + + "\xe7\x26\x3b\x2f\x89\x6e\x95\x6d" + "\x47\x52\x87\xda\x60\x98\x70\xf4" + "\xa3\xdd\x82\x24\x79\x51\xd1\x3a" + "\xf0\x82\x7d\x01\xe3\x10\x41\xd6" + "\xe4\x14\xd4\xfa\x2c\x8d\x92\x14" + "\x24\x2b\xd0\x2e\x58\x5f\x15\x2b" + "\xf1\x1b\x82\xcb\x1b\x14\x1a\x48" + "\xda\xf5\x81\x4f\x70\xc7\xe3\x12" + + "\x81\x83\xff\x9f\xe5\x5d\x9c\xe4" + "\x94\xc8\xbe\x5b\x32\x32\x05\x11" + "\xc4\x88\x4d\x45\xcc\x51\xd0\xa0" + "\x1b\x53\x8e\x1f\x9c\xb8\x6d\x4f" + "\x44\x3a\x56\xca\xd6\x3f\xfe\x34" + "\xb9\x8a\xda\x58\x15\x22\x5c\x7f" + "\xa1\xf0\x74\x94\x6d\x01\x45\x84" + "\x0a\x8a\x7d\xcb\x61\x4d\xd3\x17" + + "\x19\x40\x47\x1c\x10\x39\x9d\x8e" + "\xfb\xee\x2c\xd5\x29\x26\xff\xca" + "\x2b\x2c\x62\xc1\x32\x3e\xcf\xf9" + "\x05\x1a\x07\xe9\x3c\x5e\xb9\xd4" + "\x8c\x43\x94\x15\x1f\xa6\xbc\xfb" + "\xdf\xde\xaa\x04\xa6\xe6\xb6\x1e" + "\x40\x49\xe1\x68\xf4\x27\x30\x85" + "\x9c\xda\xab\xdf\x2a\x32\x1d\x22" + + "\x9a\x17\xcb\xb7\xf6\xa9\x8e\xed" + "\xcc\x4d\x93\xb7\x4d\x76\x7b\xdc" + "\x0d\x18\x09\x5e\x40\x39\xb1\xfc" + "\xdd\xc2\x7d\xb4\xbf\xa6\x29\x66" + "\x5e\x91\x5a\x9f\x4e\x5e\xc5\xbf" + "\x1e\x44\x04\x62\x37\x9d\xdb\xb1" + "\x53\x5f\x0c\x93\xcf\x68\x2d\xf8" + "\xb1\x05\xb6\xcb\x42\xa1\xd3\x17" + + "\xf2\x80\x87\x30\xea\x44\x59\xdd" + "\xe4\xf5\x45\x38\x61\xe7\x8d\xdc" + "\xa3\xd7\x24\x76\x7d\xba\xea\x6b" + "\x1e\xf1\x4d\x30\xfd\x9a\x70\x1e" + "\x56\x04\x17\x02\x76\x43\x36\x95" + "\x64\x4b\xf9\xc8\x3a\x4b\x20\xbf" + "\x68\xca\x80\x56\x7c\xaf\x53\x4e" + "\x74\x75\xc6\xe0\x4a\x07\x26\x05" + + "\xf6\x2a\xd9\xec\xf8\xce\xd8\x95" + "\x5a\x74\xd1\x6c\x7a\xfa\xb9\xe6" + "\xe4\xc3\x25\xa3\x3d\x6d\x54\x3d" + "\xae\x3a\xe9\x9a\x1d\x69\x57\x1f" + "\x33\x1a\x2e\x9d\xfe\xf3\x91\xe8" + "\x35\x3d\x06\xac\x3f\x09\x30\xd4" + "\x27\xa3\x13\x55\x12\x9b\xa5\xed" + "\x8f\xf1\x36\x55\xf3\x34\x21\xdc" + + "\x86\x02\x21\x5c\x2c\xfe\x51\xaa" + "\x8c\x65\xab\x1c\xee\xaa\x68\x3f" + "\x92\x72\x35\xf9\x0b\xa0\x23\x5a" + "\xed\xab\xfd\x7e\x39\x6f\x62\x9a" + "\xe3\x78\x9d\x19\xf3\x3b\x2b\xfe" + "\x45\xc3\xbb\x71\x77\xaf\xa2\xb7" + "\x2c\x80\x59\x1e\x7a\x82\x19\x3d" + "\x1c\xa5\x87\xb4\x15\xbc\x3b\x82" + + "\x22\xa4\xd0\x99\xf2\x39\x61\x85" + "\xfb\xc6\x56\xf4\x65\xdf\xc3\x9a" + "\xd6\x8b\x1f\x70\xc6\x65\xdf\xad" + "\x87\xdf\x58\x37\x1e\x32\x9f\x14" + "\xba\x7e\x1b\x72\x14\xf7\xec\xb1" + "\x2a\x31\xa3\x31\x98\xf0\x7d\xe1" + "\x81\xd5\xc4\xd5\xec\xd6\x2f\xdb" + "\xb3\xa1\xce\x8f\x6f\x99\x02\xfd" + + "\x4f\xf1\x82\x78\x3e\xa6\x9f\xe2" + "\xdc\xca\xc6\x07\x35\xdc\xf6\xc9" + "\xd0\xbe\x82\xb8\x6f\x2d\xf2\x46" + "\x2c\xe5\x18\xd1\x5b\x75\x45\x1a" + "\xcf\x08\x46\x7c\x27\x7c\x2c\x9f" + "\xc2\x12\x80\x56\x32\xdf\xcb\x7c" + "\x0e\x9b\x72\x61\xdd\xae\xb0\xfc" + "\xbf\x5d\xd7\xf7\x9e\xca\xa2\x7c" + + "\x62\x0f\x64\x6f\xb1\xec\x8f\xf5" + "\x46\x19\xf5\x39\x2b\xb9\x74\xe2" + "\x44\xaf\x88\x62\x04\xfc\x4d\x7f" + "\xe5\x29\xc3\xea\x2a\xf3\x91\x0a" + "\x31\xba\xaa\xd6\x4b\x27\xad\x43" + "\xf9\x84\x68\x0f\x40\x16\x9a\x71" + "\x20\x1e\xf9\xda\xf6\x29\x5d\x68" + "\x52\x9d\xe4\x27\x33\xcc\xc1\x5e" + + "\x59\xa0\x54\x3b\x96\xde\xf4\x38" + "\xb3\xfd\xbc\xef\xe5\x15\x00\x0e" + "\xa6\x8d\xbb\x4d\xd9\x23\x7d\x17" + "\xad\x17\xa6\x97\xa2\x4a\x72\x98" + "\x8e\x55\xb6\xfd\x5b\x88\xf0\x30" + "\x96\x9a\x89\xc7\x8a\xa2\xf7\xf9" + "\x12\xc1\x2d\x87\xc8\x8a\xae\xd2" + "\x59\xc4\xc3\x73\xca\x42\x06\xfa" + + "\xd6\xc8\xdf\xe7\x81\x69\x29\x15" + "\x4a\xb9\xb5\x1f\x50\x44\xcd\x67" + "\x37\xfd\xdd\x0e\xf1\x1c\xc7\x0e" + "\xc7\xdd\x8e\x9a\xb3\xee\xe5\xc7" + "\x28\x50\xd9\x81\x3d\x8e\xac\x02" + "\x5d\xe3\xb0\x70\x72\xf1\x88\x00" + "\xe3\x1f\x88\xe1\xab\x1f\x04\xec" + "\xaa\x7f\x9e\xd9\xb8\x71\xcf\x62" + + "\xc2\x22\xf2\xe0\xa7\xde\x43\x50" + "\x42\x51\xe6\x72\xac\x42\x9d\x30" + "\x30\xcd\x16\x92\xdd\x9d\xfe\x94" + "\xec\xfe\x87\x0f\x7d\x9c\x53\xd6" + "\xd7\xc7\x2a\x43\x7c\xa5\xc5\x03" + "\x10\xda\x7f\x32\xf0\x2c\x69\x72" + "\xde\x98\x06\x28\x5f\xc8\x28\xec" + "\xb1\x83\xc2\x7e\x46\xfb\x31\x23" + + + "\x77\xa4\x57\xe4\xea\x8e\x15\xa0" + "\x05\xdc\x6d\xee\xdb\x57\x98\xd1" + "\x71\x16\xc4\x18\x24\x52\x26\xb3" + "\x58\x0d\x2c\x3c\x7e\xfc\xfd\x3f" + "\xda\x7c\xee\x26\x54\x52\x3a\x3a" + "\xa8\xc3\x02\xdf\x69\x08\x1b\x34" + "\xc8\xbf\x3b\x72\x42\xbf\x23\xa0" + "\x91\x26\x45\x14\x2a\x00\x15\x3d" + + "\x30\xfa\xed\x85\x4c\x32\xf7\x5e" + "\xda\xf3\xd4\x87\x54\x65\x97\x25" + "\x86\x0c\xb5\xdc\xc0\x5b\x2f\x35" + "\x6c\xa9\x32\x48\xb0\x27\x69\x8f" + "\x4c\xf9\xf2\x55\xba\xe1\x8e\xd0" + "\xfa\x45\x4b\x34\x99\x6f\x99\x6a" + "\x5d\x45\xaa\xa8\x8d\xcb\x33\xe1" + "\xf7\xc1\x8d\x75\xec\x21\x07\x5d" + + "\x39\x35\x2a\x26\xe9\xe7\xca\xf3" + "\x9e\xd5\x70\x66\x1d\x9d\xa4\x78" + "\xb9\xe1\xc5\xc1\x63\x0f\xde\x37" + "\x1c\x7c\xcb\x69\x0c\xc3\x72\x30" + "\xe6\x50\xc8\x77\x52\x8a\x27\x1d" + "\xe6\x3d\x6a\x1f\x8f\x5f\xf1\x84" + "\xad\xa7\x2c\x59\x45\xbb\xa8\x46" + "\xb8\x24\xd4\xe4\xee\xe3\x12\x19" + + "\x67\xfb\xe5\x79\x20\xa9\xa7\x6b" + "\x5e\x72\xaa\x70\xeb\x1f\x33\xe1" + "\x37\xd8\xf5\x7d\xf5\xcc\x80\x50" + "\x21\x2e\xf7\x7f\x1d\xe0\xca\xe4" + "\x7d\xa7\x12\x04\xe6\x3e\x24\xd9" + "\x25\x90\x44\xdf\xac\x7c\xff\x06" + "\x31\x5a\xef\x23\xcd\xf7\x75\xbe" + "\xa8\xf7\xde\x0d\x22\x78\x95\xbc" + + "\x8b\x66\x5e\x36\x86\x80\x98\xdc" + "\xfb\xa5\xbd\xaa\xda\xdc\xa8\xad" + "\xbe\x1f\x5f\x25\x4c\x6b\x14\xbc" + "\xc3\xcf\x34\xcf\x29\xde\xfc\x9c" + "\xe4\xd1\x85\x7e\x3e\x45\xbb\xac" + "\xb5\x58\x23\xf9\x79\x96\xa0\x9c" + "\xff\x23\x08\x24\x96\x2d\xfc\x15" + "\x1e\xd1\x11\x0c\xf7\xad\x65\x8d" + + "\x55\x1c\xce\xb0\x0c\x23\xf7\x8c" + "\x07\xb6\xbf\x0b\x05\x4d\x53\x5b" + "\x3b\x36\x16\x0e\x13\xf1\x1e\xee" + "\x82\x9e\x99\xb4\x7a\xaa\xe0\x27" + "\x41\x2c\x36\x79\x2d\xac\x1d\xce" + "\xb0\x6c\xbb\x91\x90\x0c\x92\x67" + "\x24\xdf\x23\x22\x63\x8d\x64\x1e" + "\x28\x8f\x2e\xe3\xef\x9e\x7d\x0f" + + "\xfd\xf4\x96\x02\xf1\x57\x55\x77" + "\x36\xb4\x51\xea\xa3\x76\xca\x1d" + "\x05\x08\x95\xfb\x60\x8f\xe9\xf3" + "\xf1\xf7\x1c\x83\xea\x32\xff\x31" + "\x4b\x71\x2c\x8d\xf1\x7b\x3e\x64" + "\xca\x2a\x9d\x2e\x39\xc3\xb5\x64" + "\x23\x2d\xdc\x6a\xcc\x9c\xfd\xa9" + "\x9b\x1b\x72\xcc\xec\x97\x23\xfc" + + "\x34\x38\x83\xfa\x9a\xf3\x43\x69" + "\x62\x85\x32\xa6\x22\x17\x95\x22" + "\x10\xfc\x70\x41\xd5\x3d\xd6\x81" + "\x6d\x2e\xcc\xae\x8f\xa5\x5f\x9f" + "\x3b\x9a\x7d\xe7\x25\x87\x6c\xb6" + "\xe0\xeb\x84\x63\xea\x5c\x23\x11" + "\x4a\xe2\x45\x58\x18\xc1\xa8\x06" + "\xb1\x93\xd0\xeb\x86\xb2\x37\x01" + + "\x7d\xc5\x8e\xb4\x2d\x18\x31\xf0" + "\xb9\x33\xb2\x04\xf8\x32\x5d\x51" + "\x26\xad\x3a\x09\xd4\xb1\xbb\x06" + "\xec\xd1\x83\x0d\xfe\x42\xa1\x88" + "\xf8\x73\x5c\x24\x99\xc0\x95\x3b" + "\x32\xcd\xed\x52\xaf\xd4\x26\xb1" + "\xe6\x52\xcb\x8f\x1e\x2c\x02\xf8" + "\x39\xd3\x06\x01\x4c\xac\x51\x5a" + + "\x50\xe1\xac\x44\xce\xe1\x89\xc5" + "\x7c\xe9\x81\x43\xd9\xd3\xf8\xe0" + "\xb8\xa4\xc5\x62\x11\x9b\xe9\x59" + "\xf9\xc9\x0e\xfd\xf7\x62\xd2\x90" + "\xc9\x13\x3e\x28\xc9\x54\xc8\xfb" + "\x85\x70\xdc\xae\xe7\xfd\x04\x2d" + "\xcb\xbe\xdc\x47\x65\x77\x7d\x05" + "\x5f\xfa\x76\x9a\x91\xf5\xbd\x8d" + + "\x54\xa0\x64\x7c\x1a\x0a\xf7\xb7" + "\x79\x3e\xb4\x9d\xdf\xc0\xc1\x0d" + "\xd6\x63\xfe\x51\xe2\x4a\x0a\x6d" + "\xbf\x8a\x0c\x7f\x32\xe3\xd5\xe0" + "\xe8\xce\x7e\x2b\x36\x00\x55\xff" + "\x08\x50\x05\x5d\xf7\xe6\xa0\x3e" + "\x4f\xc8\x4a\xf2\x2f\xb6\xde\x30" + "\xb7\x16\x71\x5d\xfd\x69\x69\x93" + + "\x78\xe5\xe1\x0d\x95\x06\x15\xd0" + "\xc6\x2b\xf7\xe9\xe7\x63\x14\x2e" + "\xa5\xec\x39\x1b\x41\x84\xa6\xff" + "\x2f\x7f\x03\x7c\x30\x85\x3c\x67" + "\xda\x91\x7f\x74\x00\xa6\xd6\xd0" + "\xe9\x78\xcb\xc9\xe1\x43\x8d\xb0" + "\xf5\xce\xb5\x27\x44\xc6\xc0\x0f" + "\xd6\x2f\x0a\xa6\x0a\x16\x1d\x5c" + + "\x7f\xcf\x17\x26\x12\x76\xda\x02" + "\x60\x52\xe3\xee\x4e\x5d\xe2\xd6" + "\xe9\x33\x35\xfd\x0a\x5b\xfa\xb2" + "\x88\x6f\x12\xb9\xb0\xb7\x6b\xe7" + "\x66\x68\x85\x88\x99\x6a\x2e\x69" + "\xca\x65\xdb\x49\x4f\x39\xdf\x3f" + "\x06\xd6\xd8\x22\x91\x69\x29\x25" + "\xcf\xc4\xd7\x3d\xbf\xbf\x15\xe8" + + "\x3b\xe1\xc8\x28\x53\xae\x8c\xf9" + "\xd1\xdc\xed\xb2\xc4\x10\x5f\x37" + "\xad\x06\xce\x5c\x7f\x8b\xeb\xd4" + "\xef\xe1\xa2\x80\x45\x9f\x66\xb4" + "\x99\x86\xbd\x5b\xd0\xf9\x93\xd5" + "\x13\x6d\x97\xe7\xc9\xa4\x28\x55" + "\xd3\x28\x7e\x1c\x95\xe0\x23\x39" + "\x77\xb5\x6b\x3f\x90\x37\x29\xb9" + + "\x7f\x4e\x84\x4d\xed\x84\xc9\x69" + "\x82\x8a\x2e\x4a\x17\xb2\x54\xd3" + "\x36\x41\x2c\xfb\xdd\x4a\xbd\x25" + "\xe1\x26\x4b\x14\xde\xf4\x2d\xf7" + "\xfd\x1a\x10\xe6\xb0\x9d\xaa\xd0" + "\xb8\xd1\x9b\xe4\xaa\xef\x45\x44" + "\xb2\x93\x15\x33\xee\x4e\xc5\x5d" + "\x0b\xf1\x4b\x09\xb9\xe3\x35\xfa" + + "\xd2\xd6\x2b\xc4\x6a\x7d\x56\xdb" + "\xae\x96\x1f\xbb\x68\x64\xf8\x6d" + "\x8e\xb2\x43\x48\x1a\x5b\xfe\x0e" + "\x40\xb2\x79\x63\x05\xbb\x1b\x96" + "\x6b\xa2\xa6\x70\xf0\xf5\xca\xb6" + "\x39\x6e\x8e\x32\x0d\x6c\x68\x70" + "\xd3\xc8\x5f\x89\xcf\x06\xda\x80" + "\xc9\xfd\x63\xb3\x10\x88\x4d\x80" + + "\xc3\x89\xa0\x3e\x89\x0f\x0a\x66" + "\x09\x9b\x00\xc9\xaa\x23\x58\xa2" + "\xe5\xf5\x81\xa6\x7b\x2d\x26\xb2" + "\x3a\x86\x13\x34\x8c\x0c\xc3\x4f" + "\xf7\x59\x20\xc3\xb7\x44\x15\x69" + "\x34\x61\x1c\xb2\x76\xf2\x5c\xf6" + "\xba\xda\x04\x51\x2a\x6b\xa9\xe3" + "\x2f\xe4\x3e\xa4\x09\xd1\x08\xbb" + + "\x70\x16\x7f\x20\x7b\x87\x22\xbe" + "\x91\x52\x61\x4e\x88\xd1\x0d\x9b" + "\xbf\xc2\xa3\x97\xdc\xe8\x5a\x62" + "\xe8\x86\x9b\x43\xf7\x4e\x58\x08" + "\xff\x98\xd8\xdc\xa5\x90\x71\xde" + "\x3d\xee\x58\x20\x40\x6c\x28\x26" + "\xc1\xb1\x87\x5f\x17\xb2\xb0\x3d" + "\xb5\x6d\x2a\x10\x71\x47\x33\xcc" + + "\x61\x68\x91\xf9\x69\x2d\xa5\x85" + "\x13\xa8\x4f\xda\xa4\x69\x54\x59" + "\x2f\x50\x38\x33\x6e\x78\xd7\x1d" + "\xc5\x3a\x96\x53\x28\xef\xb8\x34" + "\x25\x1b\x89\x1a\xf8\x19\xf0\xc0" + "\x75\xd7\x4b\x4f\x0c\x97\x19\xb6" + "\x81\xf6\x19\xbe\xf3\x5a\x2a\x8c" + "\x28\x17\xec\x98\x04\xdb\x63\x94" + + "\xb1\x0f\x77\x2f\x54\xe9\x9d\xd9" + "\x5e\x53\xd7\x4c\x20\xc6\xc1\x97" + "\xfc\xce\x09\x3f\x48\xc4\xb6\xd3" + "\xf8\xb4\x63\x5a\x15\xaf\x25\xd7" + "\xec\x20\x1e\xc0\x4f\xd2\x95\x0c" + "\x1f\x12\xe7\x9a\x94\x74\xd3\xdf" + "\xec\xb7\x77\xec\x72\xdb\x6d\x7d" + "\xae\xa4\x53\x03\x3b\x9d\x07\xfe" + + "\xab\x9e\xf3\x01\x78\xc2\x62\xeb" + "\xaa\xa4\xb3\x0a\x34\x39\xde\x27" + "\x8d\xca\x82\xa9\x20\x75\xd1\xfb" + "\xed\xc6\xbd\xe4\xc2\x7e\x81\x58" + "\x13\xac\xc6\x31\xde\x78\x2d\x31" + "\xa6\x2e\x20\x09\x76\xbf\x83\x94" + "\xe1\xd8\xc6\x22\xb6\xb8\x4a\xf6" + "\x74\xde\x80\xe5\x9c\x58\xdf\xdd" + + "\xd2\xc8\x6a\x2e\x0a\xe7\x66\x30" + "\x05\x5c\x6e\x10\x43\x5a\x6b\x9c" + "\x8c\x9b\xe5\xed\xf5\xc6\xd3\x52" + "\xae\xc9\xce\xfc\xc3\xa5\xd6\x30" + "\xef\xa9\xc0\x4f\x22\x7c\xec\xed" + "\xed\x6c\xc1\x95\x83\xf0\x0f\x19" + "\xde\x0f\xde\x94\x8f\xec\x12\xbe" + "\x33\x34\x2d\x85\xb8\x1a\x13\x0d" + + "\x2a\xa9\x98\xee\x36\x33\xfa\xe0" + "\x45\xd7\xa4\x66\xef\xee\x80\x7d" + "\xd3\x19\x01\xba\x1b\x53\x12\xb6" + "\x15\xfe\x51\xb3\xc1\x70\xe7\x86" + "\x97\xa3\xd5\x82\xf8\xd6\xba\xaf" + "\x10\x01\xbf\x0d\xb8\x1c\x5f\x1e" + "\x3d\x06\x79\x9f\xc0\x8a\x13\x25" + "\x56\xa1\x46\x27\x2f\xd2\x9e\x08" + + "\x91\x12\x70\x85\x7e\xe0\xac\x42" + "\xa8\x61\x40\x19\xd9\x3e\x79\x94" + "\x85\xa4\xf4\xd7\xd6\x3e\xe8\x30" + "\x4d\xff\xee\xf9\x69\x72\xec\x9e" + "\x05\x80\x9d\x0c\x59\xba\xac\x90" + "\xd1\xb9\x79\x1e\x58\xa4\xec\x5f" + "\x1e\x6a\x50\x1d\x27\x54\xbe\x8f" + "\xa7\xcf\x39\x24\x8e\x2c\x2b\xa3" + + "\xde\x8d\x8b\x7d\x5d\x1b\x8d\x19" + "\xfb\x37\xab\x8d\x07\x11\x2c\xf3" + "\x74\x38\xb9\x42\x6d\xcb\x5f\xf1" + "\x84\x4f\xf9\x41\x4f\xb7\xdd\x91" + "\xb2\x24\x15\x27\x0a\x54\x64\x6a" + "\x64\x5a\x8b\x75\x12\x0c\x0a\x95" + "\x80\x95\xce\x3d\x93\x37\xf2\xf9" + "\x32\xce\xf8\x2c\xab\xd0\xed\xc8" + + "\x4e\x0b\xdd\x73\x73\xc1\x71\x16" + "\xc6\x54\xa0\x44\x14\x82\xa2\x37" + "\xf1\x53\x8b\x4e\x1b\x0a\x76\x81" + "\x9e\x3b\xf9\xf9\x24\x42\xc0\xa6" + "\x3c\x1e\x67\xcf\x34\x4b\x78\x18" + "\x94\xb9\xa9\xcd\xd2\xec\xbb\x81" + "\x48\x38\xab\xb2\x79\x19\x83\x38" + "\x2d\x3c\xe0\xf2\xb7\xfe\x54\xef" + + "\xb7\x46\x10\xae\x7e\x35\xc6\xef" + "\xe4\x32\x29\x61\x29\x49\x70\xe6" + "\x17\x5b\x35\xb1\xd4\x05\x03\xa2" + "\x56\xa1\xb4\x58\x6a\x13\xa9\x88" + "\xec\x75\xd2\xb4\x85\x99\x37\xbc" + "\x8b\x33\xaf\x6e\x31\x91\x8b\x71" + "\x09\xa5\x52\xd1\x7a\x9a\x22\x61" + "\xe9\x7a\x15\x45\xc4\xf7\x09\x11" + + "\xfa\x88\x80\xfb\xa7\x7c\x19\xcf" + "\xc5\x96\xdc\x4d\x47\x72\x42\x01" + "\x76\x71\x77\x30\x0a\x55\xd2\xa2" + "\x1d\xf7\x0c\x4d\x98\x98\x46\x53" + "\xc6\xaa\x2a\x3a\xb8\x37\xe9\x6c" + "\x9b\x8d\xf3\x5a\xc3\x1d\xf9\xe9" + "\x99\x28\xbf\xc8\x83\xad\x98\x25" + "\x16\x6c\x53\xb5\xc9\x6a\x70\x8e" + + "\x2c\x5c\xf8\x0d\x14\x42\xde\x2b" + "\x63\x7a\x8a\x05\xf4\x39\xb8\x4f" + "\x31\x12\xf5\x47\x2a\x57\x10\x7c" + "\x4e\x82\x89\x19\x23\x26\x88\x87" + "\x4a\x56\xe1\x16\x20\x3d\x29\xa8" + "\x76\x45\xc0\x18\xf8\xc0\x11\xcb" + "\x31\xc6\x40\x97\x7d\x1e\xb9\x83" + "\xa0\xce\xff\xcb\xd0\x23\xcb\xbd" + + "\x98\xdc\x88\xf6\x95\x74\xdc\x40" + "\xfc\x4a\x4c\x12\xd7\x0c\x49\x26" + "\x5c\x77\x18\x1f\x84\xec\x51\xe6" + "\x4a\xaf\xfd\xb4\xc3\xa6\x3e\x39" + "\x0d\x8e\x33\x7f\x43\x33\x1f\x1e" + "\xb5\xe7\x53\x60\x2b\x83\xfb\x39" + "\xd5\x14\x9e\x61\xda\x02\xe7\x46" + "\xe0\xf6\xee\xcd\xd1\xac\x9c\x85" + + "\xc8\xbf\x94\x90\x2a\xfd\xbd\x64" + "\x1e\x4d\xc5\x0f\xc6\xac\x58\x85" + "\x1e\x72\x27\xaf\x8f\x84\x92\x39" + "\x09\xd0\x4c\xa1\xda\xcb\x8f\x7a" + "\xc2\xb9\xa4\x00\x09\x12\xe6\x6d" + "\x28\x8f\xcf\x20\x1b\x2b\x19\xbd" + "\x83\xbe\xd9\x68\x01\xb9\x56\x23" + "\x8a\xa4\x49\x4a\x94\x7a\x1e\xce" + + "\x7d\x00\x62\x44\xe7\x9c\xb9\x63" + "\xb7\xf5\xb5\x4c\xa5\x48\xab\xb8" + "\xe7\xdd\x5e\xf5\xd2\x73\xc6\x9e" + "\xda\xef\xfa\x8c\x74\x7f\x56\xd1" + "\xec\xbc\x87\x08\x6b\x1b\x38\x46" + "\xc2\xf3\x78\xe1\xce\x97\x44\x69" + "\xcb\x66\x62\x1e\xe3\x25\x65\x5e" + "\x13\x64\x7d\x69\x26\xde\x31\x59" + + + "\x7a\x50\x93\x1a\x02\x55\x2b\x14" + "\xcf\x06\x3c\x8d\x87\x11\xcd\xb4" + "\x40\x3f\xec\x91\x6a\xe7\x70\xdf" + "\xc2\x53\x75\x4e\xad\x81\x4e\x48" + "\x6e\x9d\x2e\x27\xb5\x87\x0f\x83" + "\x4a\x51\xff\xc6\xe5\x93\x1c\xea" + "\x8e\x2a\x19\xc4\xdc\x2a\xcc\x67" + "\x5a\x53\xf4\x42\xe2\x27\x7e\xc7" + + "\x99\x51\xc0\xd0\xf2\x9c\xda\x8c" + "\x54\x84\xe7\xfa\x22\xbc\x2f\x50" + "\x82\xa1\x72\xf5\xdf\xa9\xbd\xc0" + "\x72\xb3\x58\x61\xb8\x71\x9b\x5f" + "\x07\xdd\x82\x2b\x59\x3a\xf3\xe0" + "\x2e\x03\x23\x95\x35\x27\x30\x76" + "\x32\x5a\x50\xc4\x21\xa7\xe1\x7f" + "\x9f\x40\x96\xf7\x82\x3e\x6e\x7b" + + "\x9e\xba\x37\xea\x56\x63\xc6\xb4" + "\x5d\xf5\xff\x0a\x15\x84\xdc\x1a" + "\x62\xc8\x6c\x59\xf9\x0e\x08\xf0" + "\xb6\x7a\x64\x6d\xb8\x85\x6c\x75" + "\x15\xc2\xb9\x1d\xaa\x94\xdb\xc9" + "\xa5\xb1\x13\x20\xb1\x6d\xd3\x2d" + "\x03\xc9\x86\x42\x1c\xc6\x6a\xde" + "\x84\xf8\x6c\xc7\x88\x2f\xd3\x3f" + + "\x4a\xb3\xd0\x35\xc0\x7b\x41\xe3" + "\xa7\xc0\x27\x83\x6b\x38\x0b\x44" + "\xd1\x62\x03\xac\x2d\x26\xb7\x8f" + "\x43\xf9\xcd\xe0\x4c\x11\x41\x2c" + "\xb1\xa0\x95\xad\xf1\xce\xa5\x2b" + "\x62\x43\xd5\x67\xa8\x37\x9b\xc0" + "\xc9\x86\xe4\x01\xd2\xcd\xd6\x26" + "\x97\x92\xff\x42\xbf\x7a\x47\x20" + + "\x8d\x46\xe9\x11\xec\x82\xca\x31" + "\xa0\x5f\xa0\x1c\xb6\x0e\x5d\xcf" + "\x73\x2e\x96\xaa\x05\xa3\xba\x49" + "\x56\xe4\x15\x40\xb9\x61\x2b\xad" + "\x35\x38\x21\x6c\x5f\x8e\x2b\x6d" + "\x63\x47\xf7\x48\x2b\x1c\xf1\x0e" + "\x68\xa7\x8b\xc1\x5e\x7b\xcd\xa8" + "\xec\xcc\x7e\x15\xef\x4d\xc8\x73" + + "\x7d\x1e\x58\x51\xf6\x6a\x54\x13" + "\x2e\xdb\xc7\x39\x87\x0b\xe2\x0c" + "\x46\x7c\x12\xd9\xed\xe2\xb1\xfa" + "\xa8\xe6\x35\x6f\xc4\x1d\x9a\xba" + "\x7b\x0e\x69\x80\x6f\x66\x69\x1b" + "\xa0\x90\x88\x64\x3d\x0e\x53\xd6" + "\x00\x3e\xc2\x99\xb1\x4c\xbd\x37" + "\x00\x7a\xba\xb7\x2c\x4e\x27\xe7" + + "\x3a\x24\x57\x67\xb6\x50\xac\x9f" + "\x72\x24\xf3\x23\x61\x79\x41\x8f" + "\xf4\xcb\x72\xb3\x56\x7a\x36\xeb" + "\x03\x92\x79\xb7\x5c\xe1\x37\xbe" + "\xdd\x33\x40\xdc\xdf\x1f\x52\x1b" + "\x7f\x8d\x8d\xae\xed\x10\xf4\x21" + "\x47\x75\xdc\xbd\x4e\xf2\x6a\xbe" + "\x4d\xa7\x18\x6e\x84\xae\x65\x99" + + "\x87\x92\x2a\x29\xb3\xdc\x04\xa0" + "\xc7\x92\xb0\x77\xf6\x5c\xc1\xdd" + "\x05\x06\x6c\x80\x64\x84\x3a\x08" + "\xb0\x97\xb9\x3d\x70\xdf\x68\x4a" + "\xd0\x7d\xbf\x05\x45\x4e\x13\x9c" + "\x8c\x7f\xcf\x8c\x39\x3d\xe6\xa4" + "\xaf\xf8\xb5\x41\x7f\x51\xe6\xa6" + "\xcc\xc1\x7b\xad\x42\x93\x8b\xaa" + + "\xc1\x5a\x89\x16\xcd\xb0\xa9\x6a" + "\x37\x4c\x8e\xf2\x53\xd3\xdc\xad" + "\x0a\xae\x90\x6f\xbd\x3a\x47\xff" + "\x8e\x14\x8a\x31\x09\x24\x48\x76" + "\x21\x27\x19\xca\xcc\x5e\xeb\xc5" + "\xae\x22\xd2\xfb\x27\x25\x54\x58" + "\x94\x0d\xb5\x81\xa9\x52\x48\x59" + "\xba\x8c\x6a\xe2\x03\x4e\x1f\xa0" + + "\x4a\xf9\xe0\xc2\xf5\xc5\x1d\xe1" + "\xc7\x6c\x98\x71\x4e\xfa\xb6\x1f" + "\x02\x8d\xb3\xa5\x96\x19\xfc\x0f" + "\x3f\x40\x85\x93\x8e\x26\x06\x0e" + "\x95\x61\x1a\xd0\x09\x1f\xd1\x93" + "\x17\x65\x46\x5d\x40\x96\xeb\x05" + "\xdf\x5a\xed\x77\xcc\x85\xa8\x63" + "\x72\xea\xa0\x35\x25\xdc\x07\xd5" + + "\x38\xc3\x4f\xa9\x81\xad\xe7\x68" + "\x9d\x4d\x22\x5a\x4b\x70\x6c\x31" + "\x5f\x59\x26\x4f\x38\xa9\x4f\xe3" + "\x36\x18\x96\x98\xe9\x1f\x17\x86" + "\x6c\x49\x27\x39\xc4\x1b\x99\x98" + "\xd7\x61\x87\xc6\x5a\xdb\x6f\xce" + "\xd6\x96\x9e\xb2\xfc\xfe\x24\x0a" + "\xa3\x66\xac\xe5\xa6\xff\x2d\xc7" + + "\xd9\x6a\x70\x1e\xb5\x35\x6f\x12" + "\xdf\xeb\xa9\xc3\xb4\xeb\x9c\xb9" + "\x90\x8d\x60\xbf\xaf\x89\x53\xa7" + "\x58\x98\xc8\xc6\x4f\x3c\x11\x76" + "\xaa\xb5\xe2\x97\xb0\x8e\xde\x80" + "\x04\x13\xb9\x63\xcc\x22\x10\x7e" + "\x6c\x06\xcc\x6c\x05\xb6\xda\x3b" + "\x00\xf9\xed\xb2\x44\xb1\xcb\x33" + + "\x5b\x8a\xe0\x8a\x3a\x14\x83\xb4" + "\xa6\x2b\x0b\xe6\xa1\x8f\x27\x4e" + "\xfb\x42\x78\x31\x25\x1c\xb3\x24" + "\x08\x38\xcd\x90\x7c\xcf\xe4\xd4" + "\x78\xf8\x5e\x69\x86\x4d\xdf\x5c" + "\xe8\x3a\x9a\x59\x50\xab\x2a\x36" + "\xfc\x44\x58\xb3\x76\x00\xe0\x22" + "\x04\x1a\xe7\xc8\xb1\x6e\x87\xa6" + + "\xd9\x0d\x72\xce\xff\x4b\x34\x73" + "\xa1\xe6\x3b\xfe\xc0\x16\xa6\x62" + "\x2a\x16\xec\x41\xbc\x17\x41\x30" + "\x0d\x67\x13\x3e\xf6\xb1\xbe\x79" + "\x6d\x3a\x90\x68\xc5\x3f\xaa\xcc" + "\xaf\xfe\x31\xf5\xac\x57\x9b\x99" + "\x55\x30\x17\xdf\xd7\x95\x63\xab" + "\x0f\xf8\x72\xfc\x97\x1d\x7f\x7b" + + "\xe6\x4a\x28\xa6\xd9\x91\x9a\x48" + "\x6b\x86\xad\x69\x31\xd4\xe6\x47" + "\x97\x7f\x17\x39\x33\xe5\xe5\x93" + "\x80\xeb\x59\x2c\x8a\x2c\x5d\x23" + "\x46\xc5\xe9\x94\x77\x69\xde\xed" + "\x83\x43\x93\xd5\xbc\x75\x42\xf9" + "\x53\x46\x82\xec\xbf\x71\x2f\xac" + "\x8a\x3d\xd0\x17\x67\x09\x52\x14" + + "\xd2\x15\xf7\x7a\x71\x64\x17\xc4" + "\x96\x4a\x13\xd0\x94\xf5\xf7\xe2" + "\x56\xc9\x1e\xa4\xef\x73\x18\x2c" + "\x04\x13\x82\x77\xf6\xb4\xe7\xe4" + "\x4a\x37\xd5\x88\x97\xff\xc8\xe5" + "\x5b\x3d\x82\x80\x63\x5e\x91\x2b" + "\xe2\x8f\xee\xb2\x55\xc7\x6b\xea" + "\x51\x26\x11\xe7\x4c\x62\x57\x66" + + "\x15\x49\xcb\x8a\xac\xb3\x30\xfd" + "\x60\x4b\x00\xe1\xbf\x18\x22\x8c" + "\xcc\x5d\xc2\x4d\xfe\x4c\xa6\x80" + "\xda\xb9\xd0\x95\x6e\xf2\x06\x05" + "\x37\xef\xc3\x41\xfd\x94\xaa\xab" + "\x26\xef\xbc\x89\x9d\xd2\x66\x23" + "\x63\xea\xe4\x4b\x8f\xe7\xd0\x6b" + "\x1f\x33\x21\x2e\x5f\xf3\x86\x06" + + "\xce\xd9\x90\x05\xf3\xc7\x0f\xcb" + "\x3b\xd5\x0a\xea\xd9\xc3\x22\xc0" + "\x33\x29\xba\x84\xb3\x29\xc4\xa9" + "\xcf\x92\xb8\x9d\x36\x52\xe6\xfc" + "\x52\x8d\x51\x1f\x62\x28\x70\x48" + "\x32\x31\x38\x10\x1e\x7d\xdf\x25" + "\x5b\x79\x36\xaa\xbd\x0e\x17\x3f" + "\x47\x7e\x95\x34\x4f\x88\x31\xa9" + + "\x4a\xf1\x33\x58\xea\xfb\x39\xdc" + "\x33\x0f\xd5\x88\xc1\xa3\x10\xb0" + "\x2c\x75\xf5\x76\xbc\x45\x61\xcd" + "\x77\xde\x12\x7e\x21\x25\x3b\x11" + "\xa5\x39\x18\x04\x66\x78\x41\x62" + "\xd7\x09\xf3\x0e\xcb\x58\xca\x95" + "\x49\x22\xd0\xa2\x9d\xcc\x02\x6d" + "\xbb\x3a\xfd\xb8\x4b\xb5\x45\x87" + + "\xca\x5a\xce\xda\x01\xf1\x7a\x15" + "\x67\xa2\xa6\x11\xf2\xbc\xfd\xc4" + "\x09\x86\x9c\xc4\x40\xf3\xdd\xda" + "\x65\x4a\x60\xe9\x52\x9f\xe4\x97" + "\xd5\x2a\x7e\x93\x90\xe7\xe8\x9b" + "\xf1\x17\x6e\x32\x08\x25\x6e\x84" + "\xdc\xc0\xbb\x0b\x7a\x00\x38\x3f" + "\xd6\x16\x1e\xb1\x3f\x60\x03\xcf" + + "\xfe\xbc\xd3\x4e\x0a\x15\x89\x05" + "\xb9\x0c\xd8\x6c\x5c\xb6\x62\xf4" + "\x5d\x1c\x53\x29\xa8\xad\x12\x34" + "\x75\xa6\x14\x2f\xe7\x69\xe9\x90" + "\x4c\x5b\xb9\xc7\x06\x89\x6c\x48" + "\x0c\x78\xb4\xbc\x4c\xa9\x67\x5a" + "\x85\xf9\x2d\xd2\x13\x15\x61\xde" + "\x0c\xe0\x1b\x48\x9a\x86\xb4\xba" + + "\x1f\x8f\xd9\xb8\xc5\xa4\xea\x2f" + "\x50\x02\x05\x41\x9c\x02\x09\x7c" + "\x2f\x13\x56\x1b\x77\x42\xfa\xd4" + "\xe5\x35\x12\xda\xf1\x57\xb2\xec" + "\xaf\xae\x46\x6a\x58\x21\x7e\x61" + "\xae\x3e\x65\xd4\x00\xf3\xef\x65" + "\x01\x2a\x56\x03\xad\x13\x7a\xf6" + "\x27\x70\xc7\x70\x87\xfa\x7f\x95" + + "\x2f\x1c\xc1\x46\x90\xc4\xf2\x89" + "\x18\x08\xd5\xd7\xd6\x06\xbc\xbd" + "\xe2\x51\xbe\x82\x60\xc1\xdf\x13" + "\x95\x98\x71\xc1\xf6\x3a\x0b\x71" + "\x75\x84\xdd\x61\x43\x46\xd5\x0b" + "\x29\xe0\x44\x45\xd3\x8e\x8a\xa1" + "\x7d\xbb\x3f\xdc\xcf\xd2\x1a\xe1" + "\x8a\x78\xe8\x79\x9b\xd7\x77\xb1" + + "\xd5\xf1\x42\x74\xe0\x00\xf8\xd6" + "\xab\xe3\xe0\x66\xd1\x07\x56\x47" + "\x47\x40\xc6\xb7\x16\x7f\x80\x82" + "\x3d\x88\x49\xa7\xe3\xe1\x58\x88" + "\x10\xee\x31\x82\x0b\x12\x59\x58" + "\xce\x1e\x8a\x63\xeb\xe7\x80\x1b" + "\xa4\x73\xaa\xc6\x5a\x52\x72\xcb" + "\xac\x23\x44\x84\x3d\xea\xcd\xa7" + + "\x3e\xed\x80\x6b\xb0\x8d\x3a\x86" + "\x13\xfa\xd3\x75\xe3\x47\xa7\x19" + "\x01\xf7\xc8\x69\x2e\xcf\x35\x5a" + "\xe9\xbb\xe5\xf8\x13\x04\x9f\x76" + "\x6a\xe5\x64\x1d\xc0\x36\x6d\x3b" + "\x96\x98\x6a\x45\x32\x2b\xd9\xb9" + "\xda\x9c\x8e\xcf\x70\xce\x47\x0d" + "\x64\x98\x01\x6c\x5e\x35\xe3\x19" + + "\xed\x23\x51\x02\xac\x1a\x10\x7f" + "\x06\x06\xad\x93\xef\x93\x6e\xf1" + "\xd1\x85\xcf\x46\x48\x89\xfe\x89" + "\x0e\x91\x8e\xf7\xcb\x0c\x1d\xe3" + "\x78\xf6\x61\xd5\x1c\xab\xab\xbc" + "\x33\x28\xc9\x87\xc8\xe5\x31\x73" + "\x8d\xf6\x72\x0e\x26\xad\x38\x63" + "\xc3\x05\xdb\x35\x3e\x05\x0c\x80" + + "\x08\x6b\xb0\xa1\x76\xeb\xe2\x81" + "\xc9\x82\x7e\x8d\x78\x55\xae\x81" + "\x96\x8a\xf7\x48\x38\x3e\xec\x03" + "\x01\x9b\xa3\x81\x53\xf7\xb4\x1b" + "\x26\x8a\xee\xeb\x1c\xb0\x4e\x42" + "\x2c\x8f\xae\xd4\xf5\xf7\x11\x13" + "\xf1\x01\x8c\xaf\x76\xb0\x3a\x15" + "\x77\xc1\x02\x5e\x83\x4c\xc9\x2e" + + "\x38\x7c\xae\xf8\x07\xc0\xd0\x5e" + "\x92\x01\x74\x3d\x5c\x7a\xb0\x6d" + "\xb3\x6d\xe3\x5f\x2a\x9c\x5e\xbe" + "\x46\x50\xe9\x76\x7a\xd5\xb9\xd5" + "\xf2\x20\xba\x8e\xe7\x32\xac\x54" + "\x52\xa3\xb9\x71\x8f\xca\x11\xef" + "\x58\xa6\x98\xff\x3e\x37\x5e\x30" + "\x67\xb6\x3e\x82\x00\xa1\xe5\xff" + + "\xcf\xee\x8c\xdc\x00\xc8\xb7\x46" + "\xa5\x94\x59\x81\x2d\x9c\xe4\xd6" + "\xea\x56\x62\xbb\xfc\x14\x78\x6b" + "\x22\x10\x6e\x4a\xfc\x51\x8f\x7e" + "\x38\x20\xde\xca\x83\x53\x80\xf9" + "\xea\xfb\x54\x74\x31\x2f\x76\x9f" + "\x68\x80\x38\x65\x29\x0c\xba\x5a" + "\x51\xb2\x1c\x72\xfa\x61\x75\xa2" + + "\xcf\x32\x5e\x94\x38\x49\x14\x5c" + "\xa6\x91\x82\x5a\x75\x7e\x99\x9e" + "\xd6\x07\x6e\xfc\x46\xe8\x70\x05" + "\x7d\x44\x74\x1e\x64\x13\x68\xe2" + "\xe2\xf2\x1f\x72\xce\x10\x17\xbf" + "\x3d\xe8\x14\xf8\x19\x08\x45\xea" + "\xd2\x7a\x69\xed\x0b\xa7\xf0\x27" + "\x36\x3f\x6b\x08\x99\x98\x36\x90" + + "\xdb\xcf\x46\xdb\xfc\x40\xff\xe9" + "\xc4\x94\x7e\x5e\x15\x67\x52\x1b" + "\xbf\xb3\x00\x97\xc5\x6b\x98\xb8" + "\x28\x31\x8c\x0c\x59\xaf\x8c\xc9" + "\xeb\xbb\x1b\x30\x5d\x01\xfb\xd1" + "\xa9\xd1\x2f\xba\x28\x4f\xe6\x18" + "\x70\x5b\x36\xc0\x7e\x78\x12\x92" + "\x04\x6c\x38\x98\xd0\x51\x4b\xc6" + + "\xd2\x32\x17\xe5\x11\x7b\x47\x57" + "\x0e\xfc\x38\x25\x28\xeb\xd6\xdf" + "\xc5\xee\x39\x3b\xcc\xb0\x43\x5c" + "\x57\xcc\x36\xcb\x78\x27\xf1\x6a" + "\xae\x25\xc4\x06\x2d\x85\xb0\x70" + "\x9b\x1b\x22\x5c\x8c\x2f\xf9\x6d" + "\x9c\x6d\x82\xce\x9e\x4f\x8d\x6c" + "\xc3\x59\x93\xb4\x7b\xba\x9a\xf5" + + + "\xa4\x3a\x1d\x42\x2e\x2c\x7e\xc3" + "\x40\xa8\x4f\xe8\x7c\x40\x26\xf9" + "\x1c\xe4\x54\x14\x3d\xc0\xab\x18" + "\x44\xf6\x7a\x3f\xcd\x5e\x60\x26" + "\xbf\xea\xa5\xd6\xa6\x41\x23\x24" + "\x8e\x66\x6b\x21\xf4\x84\xdb\x1e" + "\x02\x01\x01\x04\xb8\xed\x36\xd8" + "\x8c\x1d\x5e\x94\xe7\x7c\x33\x5b" + + "\x82\xdc\x3d\xd2\x86\x6b\x07\x4c" + "\xf0\x43\x01\x7e\x4c\x34\xfd\x03" + "\xc5\xf2\x7a\x31\xff\x62\x53\xa9" + "\x4f\x7a\x8b\xe1\xb7\x3d\xdd\x0a" + "\x1b\xe0\x60\x82\x3f\x3e\x67\x9c" + "\x91\xcc\xa1\x54\xe5\x49\xeb\xfb" + "\x33\xe4\xf2\x92\xf2\x1b\x35\x91" + "\xeb\x41\x11\x85\xec\xe7\x55\xc7" + + "\x04\x38\x9f\xda\x68\xe3\x9a\x34" + "\x9c\x34\x64\xa1\xfe\x07\x0f\x47" + "\xa5\xba\x62\x85\xc9\x4c\x2f\xd5" + "\xf3\x0d\x29\x2b\x86\x9e\x4a\xc7" + "\x24\x1a\x47\x43\x35\xaa\xa1\xd3" + "\x11\x45\x19\xb8\xbe\x46\x94\x23" + "\x4d\xd4\xdc\x81\x00\xdd\xc2\xbe" + "\x2d\xc8\x2a\xc4\x0f\x7f\x3d\xca" + + "\xd5\x06\x32\xf2\x47\xdb\xf5\x2b" + "\x52\x01\x26\x1d\x20\x34\x6d\x2f" + "\x9a\xf8\x8f\x3f\x53\x76\xb8\x17" + "\x58\xa4\x8f\x37\x0c\xc3\x57\x51" + "\x36\xb9\x4f\x2d\xc5\xc5\x17\x75" + "\xdc\x8c\x51\xe6\xac\xf7\x22\xef" + "\x64\x7a\x84\xbf\xe6\x83\xb4\xde" + "\x89\xfa\xe0\x92\x58\x45\x08\xf5" + + "\x60\x31\x58\x9b\xa6\xc2\x18\xb4" + "\x94\x91\xe5\xb4\xd4\xfc\x74\xbe" + "\xff\xe3\x83\x3c\xaa\xee\x78\xf1" + "\x9b\xf2\x96\xe2\x95\xf8\x51\xe0" + "\x4a\xb8\xce\x06\x38\x52\x23\xd0" + "\x6b\xfe\x11\xe1\xce\x48\xce\x5a" + "\x45\x55\x04\x1c\x49\x3a\xe4\x40" + "\x46\x21\x52\xdd\xdd\x86\xfa\xf3" + + "\xb5\xc5\x8e\x90\xfa\x16\x96\x95" + "\x2d\xb1\x1a\xa0\x1d\x66\x2d\x88" + "\x8a\xae\x82\x43\x82\x60\x9f\xc4" + "\x5e\x3f\x13\x5d\xeb\x92\xdf\x5c" + "\xc1\xc9\xf6\x5e\x42\xcc\xce\x98" + "\xee\x84\x4d\x66\x82\x66\x2d\xb5" + "\xc4\xb8\x25\x6f\xd8\x5e\x28\x9e" + "\x88\xbe\xde\x48\xc7\xcd\x80\xeb" + + "\xa0\x2b\x22\xec\xc1\x94\x97\x2d" + "\x48\x5d\x3e\x52\x2f\xf4\xdf\xc3" + "\x6b\x84\xe4\x0f\x70\xd5\x7c\x4a" + "\x74\x51\x13\xff\x13\xb1\xc5\xef" + "\x85\x5e\xb0\xc6\x5b\xb2\x30\x26" + "\x77\xd0\x4c\x65\x29\x30\x6d\x0a" + "\x9d\xb8\xd8\x32\x4f\xf5\xf1\xb4" + "\x27\xfc\x27\x16\xf2\xaf\x3b\xde" + + "\xd4\x04\x73\xdf\xd8\x59\x96\xab" + "\x8e\x0e\x21\xff\x1b\xcf\x1b\xb7" + "\x60\xbd\x3f\xd7\x8b\x43\xa2\xa9" + "\xde\xb4\x11\x5d\x1f\xcd\x95\x45" + "\x9d\x85\x35\x48\x9a\x32\x0d\x9c" + "\x56\x6e\xbb\x7d\x2d\x0d\x0f\x4a" + "\x4e\x8a\x92\xdf\x5e\x8e\x03\xc6" + "\x54\xd1\x5a\x8f\x21\x96\x42\xc9" + + "\x3e\xdf\xa2\xa4\x3b\xb8\x83\xb8" + "\x63\xa3\xe5\x44\xc2\x7c\x5b\x04" + "\xde\x96\x0d\x4e\x73\xd7\x2b\xa4" + "\x65\xc1\x93\x8d\x47\x75\x25\xb9" + "\x8e\x13\xc8\x73\x26\x01\xf9\xe8" + "\xbf\x84\x7d\x60\x4d\xe7\x8e\x5a" + "\x63\x43\xea\x49\x50\xbb\xec\x1b" + "\x86\x32\xda\x5a\x14\x61\x4b\x1d" + + "\x15\x3b\x09\xaa\xb5\x78\xb6\xeb" + "\x0c\xb4\xe2\xd3\x44\xdf\xac\x0e" + "\x9f\x19\x89\x20\xc4\x23\x42\xbc" + "\xa4\x06\x0a\x49\xb4\x2b\x25\x0e" + "\xf7\x5d\x2c\xcc\xb5\x79\x64\x1e" + "\x8a\x32\x94\xba\xd2\x22\x69\x8b" + "\x8c\x94\x8b\x21\xe7\xcc\x78\x42" + "\x39\x4f\x06\xe6\x5c\x99\x7e\x94" + + "\x94\x69\xd9\xf1\x65\x2d\xf3\xcd" + "\x18\x2b\x5b\xb7\xf3\xd8\xb3\x8b" + "\x98\x77\x30\xcb\xa3\xd2\x95\x5a" + "\xb5\xa8\x15\xcb\xcc\x29\x86\xdf" + "\x26\x49\x8c\x54\xbe\xdc\x5b\x37" + "\xa6\xb3\x25\x3c\xc6\x58\xad\x94" + "\x88\x48\xac\x8f\x52\x0d\x4e\xe9" + "\xe3\x5b\xba\x69\x46\x77\xbe\x9c" + + "\xc4\x6e\x0c\xa7\x40\x38\xa3\x08" + "\x95\x11\x31\xe0\xf7\x19\x88\x9e" + "\x02\xb2\x8a\x70\x96\x9d\x20\xed" + "\x27\x3a\x94\xce\xe7\xc4\xd7\x10" + "\xa1\x49\x9b\xa2\x17\xb3\x2f\x37" + "\x1f\x7d\x62\x46\xb3\x7f\xa6\x57" + "\xec\x39\xdf\x7c\x1e\x56\x12\xf9" + "\x17\x8f\x7c\x6f\xf2\xe6\x3c\xfa" + + "\xc1\xed\x2f\x78\xe7\x6d\xc1\x04" + "\xc4\xe7\x3a\x09\x1a\xc1\xe2\xfe" + "\xb1\x90\xde\x3d\x85\x7d\x7a\x35" + "\xdc\x23\x69\xce\xf2\x6a\x13\x68" + "\x36\x45\x86\x8e\x44\x9b\xaa\x0a" + "\x2f\x1c\xaa\xfe\x52\x34\xb5\x16" + "\x55\xd9\x46\x59\xd1\x94\xf4\xe8" + "\xe3\x69\x15\x3b\x51\x16\x31\xb5" + + "\xe7\xe3\x51\xbe\x7d\xfd\xeb\xdd" + "\x31\x68\x02\x7f\x40\xfc\x25\x0b" + "\xd1\x5f\xe4\xac\x3b\xad\x3b\x4f" + "\xa7\x09\x68\x70\xba\x32\xb3\x8c" + "\xca\x3f\xb9\xd6\xb1\x60\xe1\x40" + "\xed\xbd\x28\x8b\xdf\x8e\x36\x85" + "\xfd\xc2\xb4\x90\x8c\x0a\x6f\x26" + "\x4f\xd2\xaa\xff\xf6\x87\xd9\xaa" + + "\x3b\x62\x1b\x4e\x42\x0d\x31\x9f" + "\xa5\x66\x62\x81\x9b\x74\x45\xf0" + "\x27\x78\xdb\xa0\x51\xd7\x4f\x94" + "\x59\x72\x1d\x68\xa6\x0d\x12\x80" + "\x88\xc5\xa9\x31\x0d\xd2\xcd\x00" + "\xf1\x4b\xae\x97\xd3\xab\xf2\x7b" + "\x6a\xc0\x08\x6b\x90\x22\x5a\xf7" + "\x8b\xdc\x12\x4a\x84\xe5\xa3\x0f" + + "\x92\x2d\x3f\xf2\x62\x34\x21\x91" + "\x78\x40\xb9\x60\xbd\x71\xab\x6c" + "\x20\xde\x6c\x17\x63\x0a\xdd\x6b" + "\xbc\x54\x4d\xee\x0c\xb2\xc9\x54" + "\x2f\xc0\x2a\x9f\xaa\xd8\xd2\x3c" + "\xb0\xed\x6e\x20\x17\xe6\xf8\x03" + "\x34\x64\x08\x93\x16\x8e\xf6\xc7" + "\xb9\x3d\xdd\x92\xc5\x69\x14\x83" + + "\x41\x22\xba\x69\xfe\x2c\x5e\xf3" + "\xbd\xd5\xf4\x8c\xe0\x6c\x44\x95" + "\x92\x4f\xdb\xb8\xcd\x1b\xba\xdc" + "\x58\xd9\x70\x59\x8e\xae\x79\x96" + "\x4b\xb9\xd5\x40\x45\xb4\x9c\x95" + "\xd2\x1f\xa3\x33\x14\x78\x56\xad" + "\xc1\x2b\x00\x1b\xd1\xc3\xd4\xc7" + "\xe3\x53\xc8\x8a\xcc\x81\xa2\x59" + + "\xcd\xb1\x28\xdd\xc0\xae\x75\xfd" + "\xc2\x4d\x37\x7a\x05\x02\x12\xc7" + "\x2f\x62\xf0\x08\xe4\x2b\x6a\xab" + "\x58\x8b\x26\x12\xa1\xd0\x4a\xcb" + "\x94\x3a\x19\xf5\x7c\xed\xf8\x34" + "\x2b\x9c\x45\x1c\x7e\x16\xcd\xba" + "\x74\xe2\xbc\x57\x54\x62\xcc\x24" + "\xec\x60\x40\x2d\xa8\x64\x71\xf4" + + "\x1b\x75\xac\xe2\x5a\x6e\x5d\x0f" + "\x69\x45\x4d\xd4\xf3\xb3\x09\xc6" + "\x33\x4c\x96\x0b\x80\xac\xc4\x38" + "\x05\xc5\x43\xc1\x1b\x45\xf9\xde" + "\x86\x75\x4d\x39\x95\x92\x1f\x98" + "\xd1\xa6\x58\xd0\x9b\x1e\x0d\x4c" + "\x3d\x80\xe8\x07\x1c\xcf\xa4\x76" + "\xd6\x01\xdd\x4d\x33\x76\x5f\x2b" + + "\x5f\x3c\x3f\x65\x65\x74\x7d\xfe" + "\xb1\xfe\x40\xf0\x5e\xd4\x3d\x28" + "\xfe\xed\xb7\xf3\x9b\x59\xfe\x91" + "\x11\x93\x37\x80\xad\x39\xf0\x5f" + "\x49\xfa\x96\x4e\x5b\x99\x76\xbf" + "\x94\x50\xe2\xa3\xb2\xb6\x40\x26" + "\x74\x3f\xc8\xc1\x41\x63\x09\x8b" + "\xc3\x0a\x56\xfa\x84\xc8\xbe\xd2" + + "\x05\x14\xf3\xb9\x6b\x57\x6b\x09" + "\x5e\x2b\xb0\x62\x87\x22\xfc\x40" + "\x18\x61\x2f\xe6\xbb\xbd\xb2\x42" + "\x1a\x49\x03\x73\xf7\x80\x8d\x62" + "\x96\xbe\x33\x8f\xfd\xd8\x7e\x89" + "\x0a\x8d\x49\x48\xca\x69\x56\x4d" + "\xef\x9d\x9c\xe9\x1a\x40\x4c\xf7" + "\x5a\xb8\x44\x65\x5b\xeb\x38\x79" + + "\x88\x12\xf2\xe7\x12\xd3\x0b\x43" + "\x33\xe3\x94\x87\x25\xa7\x81\x73" + "\xfc\xd2\x53\xb2\x8b\x2f\x5d\x94" + "\x9e\xff\xa3\xbe\x85\x35\x59\x79" + "\x06\x60\xaf\x8d\x7f\xf6\xc3\xb0" + "\x77\xd8\xa6\x19\x85\xd0\x48\x78" + "\x4f\x1b\x21\x62\x1b\x70\x38\x6e" + "\x6d\x39\x06\x05\x6e\xf0\x07\xaf" + + "\xff\xb8\xfa\x91\x8d\xc8\x9a\xe5" + "\xed\x96\x7c\x3f\x0e\x1c\x5e\x2f" + "\x79\x50\x08\xb4\x16\x8a\xf2\xff" + "\x9f\xc0\xe0\x94\x9e\x5f\x76\x8d" + "\xbe\x37\x03\xa0\xce\x3e\xa5\xd2" + "\x88\xd0\xfa\x4a\xbd\x5d\x21\x98" + "\x20\x89\x23\xa9\xa9\x6f\x2b\xa3" + "\x2a\xed\xd9\x64\x15\x80\x65\xe1" + + "\x54\x13\x98\x8f\x24\xdf\x21\x85" + "\x59\xa2\x88\x35\xec\x23\x7e\x58" + "\x2c\x99\xa0\xd7\x81\xf2\xed\xcb" + "\x07\x14\x96\x38\x55\x0a\x93\x06" + "\x21\xbe\x5b\xbe\xeb\x0d\x32\x09" + "\x7f\x81\x91\x24\xb5\xa5\xff\xa7" + "\x60\x51\x06\x09\xd9\xb4\xc8\xe6" + "\xa9\xd2\xf6\xff\x92\x39\x4f\xac" + + "\x76\x9c\x7b\x56\xf5\xc8\x5d\x5c" + "\xc6\x9a\xd1\x96\xbe\xcc\xe0\xaa" + "\x5f\xa2\x26\xcf\xa8\xf8\x71\xd4" + "\x08\x52\x36\x37\x4a\x70\xf9\x1d" + "\x05\xda\x45\xa1\x1b\x54\xbc\xab" + "\xaf\xd8\xb7\xf5\x3d\x32\x43\x9d" + "\xdd\x53\xe2\xf1\x92\xb0\xaf\xa3" + "\xcf\x36\xcb\xdb\x79\xeb\xa7\xc4" + + "\x23\x91\xaa\xa3\x15\x6f\x4d\x2e" + "\x42\xd3\x4d\x38\x8c\x9c\xff\x33" + "\x0c\x1b\x2d\x8f\x17\x86\x16\xb0" + "\x62\x05\x6d\xbd\x7d\xd8\xae\x66" + "\xe8\x66\xa4\x4e\xac\x76\x31\x40" + "\x7b\xbe\x10\x1e\x0c\x8f\x4d\x15" + "\x4b\xa4\xd1\x58\x76\xf7\x75\x5f" + "\x05\x39\xa5\x33\x10\x98\xb2\xc9" + + "\x01\xb1\x7f\xa4\xf5\x73\xbd\x56" + "\xfb\x59\xbf\xfb\x84\x86\x25\x36" + "\x2b\x84\x4c\x86\x38\xdd\xc8\x43" + "\x03\x87\x4e\xf5\x92\x65\x46\xf1" + "\xc5\x78\x06\xd1\x92\xc3\x37\x11" + "\x8a\x91\xd5\xf0\xde\x82\xa8\x86" + "\xd0\x33\x10\x2d\x4d\xd2\xe1\x8e" + "\x26\xe9\x76\xe3\x62\xe1\x9c\x64" + + "\x66\xda\x53\xcc\xa3\xb2\x4e\x2e" + "\x4e\x9b\x7a\xf1\x71\x8a\x70\x04" + "\x2c\x5b\xe0\x0d\xb2\xc7\xfd\xdb" + "\x01\xa2\x07\x49\xee\x9a\xdc\x4c" + "\x66\x55\x47\x6c\xfc\x8d\xcc\xe5" + "\x91\x16\xbe\x47\xfb\xcb\x83\x2b" + "\xfd\xc3\x05\x4c\xa7\x33\x58\x69" + "\xb0\xde\xb0\x43\x72\x8a\x93\xee" + + "\x0f\x8f\x42\x3f\x77\x25\x86\x07" + "\x1f\xed\x3d\x4c\xa9\xdb\x63\x9b" + "\xbd\x51\x67\x35\x44\xae\x2a\x85" + "\x80\x1c\x2f\x3b\x11\x49\xec\xe2" + "\xfb\x20\xc4\x73\x54\xf3\xb0\xed" + "\xc3\x55\xc2\x0b\xab\xcc\x63\xd6" + "\xa9\x46\xae\xcf\x5d\x01\x3e\x1c" + "\x84\x7d\x18\x1f\x99\x89\x55\x98" + + "\x1a\x3d\x8b\xb7\x1e\x4f\xd3\x2c" + "\x0e\x4c\xf8\x5f\xc6\xfa\x13\x17" + "\x60\xec\x9c\xc2\xc9\xfa\xe9\xde" + "\x52\xa5\x7a\xb2\xfd\x7b\x91\x53" + "\x9f\x12\x64\xee\x4d\x53\x6f\x89" + "\xe0\x1e\xeb\xdb\xf2\x23\xa5\x76" + "\x27\x11\x59\xd2\x09\x33\xc1\xe1" + "\x6c\xf6\x4c\xad\x57\x1d\x6f\x87" + + "\xa9\xa3\x76\xb5\x89\xc7\x32\xc6" + "\xc8\xd7\x0d\x69\xf2\x21\xc0\xcf" + "\x6d\xad\x84\xeb\x32\xea\x55\xcf" + "\x66\x95\x05\x72\x2b\xb7\x70\x61" + "\x28\xf2\xa5\xcf\x10\x56\xa0\xfb" + "\x1a\xbf\x4c\x89\x15\xdd\xb3\xc1" + "\x36\xf4\x4f\x31\xf0\x24\xc5\xc6" + "\xdd\xff\xa1\x07\x61\x0c\x7e\xb2" + + "\xbd\xc1\xe9\x3a\x58\xa1\xa7\x7a" + "\x40\xe2\x7c\xe3\x98\x6d\xaf\xe0" + "\xb4\x38\xab\x28\xd9\x42\x43\xe5" + "\xca\x98\x1c\x0a\x07\x50\xb7\xe8" + "\xf2\x58\x23\xe0\xaf\x86\xce\xef" + "\x28\x12\x92\xea\x56\xb8\xb8\x31" + "\xfc\x67\x1c\x0a\x12\x19\x2a\x05" + "\x59\xad\xae\xe3\xa4\x9e\x06\xb4" + + + "\x19\xf0\x8d\x55\x9e\x43\x51\x9f" + "\x27\x2b\x71\xac\xba\xa4\x0d\x23" + "\x24\x5a\x18\x55\xe3\x19\x89\x51" + "\x50\x8f\xb7\x84\xdd\xfc\xce\x4d" + "\x5a\x4c\x7d\xa4\xb2\x0f\xd9\xa7" + "\x9e\x00\x0e\xb3\xbf\x9a\xac\x55" + "\x73\xd2\xee\x74\x59\xc3\x2f\xfd" + "\xaf\x8f\xea\xdb\x4c\x82\x2d\xb7" + + "\x89\x92\x7d\xef\xb5\xb2\x9d\x54" + "\x5a\x01\x7f\x19\xa8\xd4\x80\x24" + "\xb6\x93\x04\xc4\x0b\x59\xd5\x61" + "\x31\x03\x78\x6f\x2e\xb5\x55\x3a" + "\xb0\xad\x9e\x30\x15\x81\xeb\x40" + "\x25\xc6\xe5\x92\x5a\xde\xa7\xde" + "\x5a\x3d\x6a\xcc\xf0\x31\xd6\x64" + "\x61\xdd\xe8\x93\x7c\x9d\x5e\x9d" + + "\xdd\x2b\xc8\x04\x8d\x58\x7a\x1b" + "\xfd\x9d\x31\xf8\x34\x55\x00\x68" + "\x80\x95\xeb\xd8\xb5\x55\x8a\xde" + "\x81\xca\x5b\x8d\xda\x86\xa8\x5e" + "\x4d\x0b\x2a\x25\x01\x0a\x53\xe8" + "\xa1\xa0\xea\x35\xfe\xb4\xff\x1b" + "\x63\x95\xe9\xd8\xb1\x28\xd8\x2a" + "\x87\xcd\xf9\x95\xf5\x6e\xe9\x7d" + + "\xe5\xe0\x84\x1e\x41\x60\x68\x19" + "\x93\x4c\xa3\xae\xd3\x84\xdb\xa5" + "\x32\xa7\x73\x70\x19\xbb\xd5\xf9" + "\xc0\xd7\xcf\x6b\x56\xfe\xd2\xb8" + "\xfa\x82\xeb\xf3\x36\x5f\x77\x45" + "\x58\x8b\xff\xfd\xcc\x0c\xb2\x8c" + "\x10\xc1\x74\x83\x5f\xb6\x59\x16" + "\x9a\x78\x0c\x33\x22\xa4\xb4\xb8" + + "\xdc\x73\xa9\x7e\xe5\x41\x57\x74" + "\x2e\x8f\x88\x20\x70\xca\x00\x5c" + "\xf1\x9c\xfd\x45\xcf\xe3\xdc\x7c" + "\x72\xf8\x07\x55\xf1\x1e\x74\x8a" + "\xec\x4c\x6b\x19\x2f\x1c\xc5\x47" + "\x18\xa6\x7e\xc9\x43\x8e\xd0\x70" + "\x2b\x8a\xb1\x15\x5c\xa1\x0d\x93" + "\x14\x05\x61\x2f\x78\xc6\xb6\x33" + + "\x9f\xae\xdb\xae\x87\xff\x25\xc9" + "\x54\x0a\x88\x36\xb9\x0e\xaf\x7d" + "\x71\x0e\x4d\x9c\xf5\xdd\x84\x92" + "\xf5\x8c\x6f\x31\x93\xcf\x81\x15" + "\x52\xf4\xc1\x3a\x87\xa8\xec\x3e" + "\xfe\xef\x6a\xfb\xe9\xfc\x17\xb4" + "\xc3\x8d\xfb\xee\x46\x80\x91\xa5" + "\x00\x94\x20\x02\xac\x18\xd3\x73" + + "\x8b\x78\x85\x9a\xda\x35\xa5\x6b" + "\xd4\x26\x06\xbd\xae\x03\x1f\xd2" + "\x64\xdc\x73\xe8\x47\x8c\x9f\x09" + "\x7e\xc9\x8e\x01\x4d\x56\xa8\xcd" + "\x8c\xc6\x92\xde\x5c\x7a\x8d\x3e" + "\xc4\x3c\x32\x73\xa1\x35\xe0\x78" + "\x7c\xff\x80\xf8\x75\x62\xf2\x3e" + "\xaa\xed\x3e\x27\xff\x3d\xee\xa4" + + "\x2f\xbc\x2e\xaf\xa3\xcd\xf4\xc4" + "\x24\xfe\x4e\xcb\x3d\x84\xaf\xa0" + "\xb1\x10\xcd\x9c\xc1\x57\xb8\x53" + "\x04\x3e\x4d\x91\xeb\xd1\xc9\xdd" + "\xeb\x1d\x77\x62\xbb\xc8\xde\x7b" + "\x81\xaa\xc5\x91\xaa\x77\x92\x82" + "\xae\x91\x23\x83\xd6\x8d\xf1\x7a" + "\xca\x84\x1a\xc7\x16\xf3\x40\x17" + + "\xed\x73\x6d\xa5\x88\x5c\x9e\xba" + "\xd3\x54\xa0\x2c\x71\xf7\x24\x6c" + "\xe1\xea\x3b\x08\x35\xc2\x37\x4a" + "\xfd\xe9\x83\x64\xb2\x83\xa8\x04" + "\x5d\x2c\x7c\xe2\xae\xf3\x63\x0c" + "\xf1\x71\x46\xae\x8d\xa8\x1d\x0e" + "\xdb\xe1\x95\x59\xe2\xe8\x77\xa5" + "\x6a\x06\xd6\x6e\xb1\xb1\xc4\xbf" + + "\xf8\x31\x2b\xe1\xd8\x12\x4a\xdd" + "\xe6\x36\x77\x17\xbc\x29\x7e\x57" + "\xe8\x35\x89\xa8\x2b\x72\x53\x23" + "\x6d\x28\x5f\x01\x29\x37\x1d\xca" + "\x35\xe0\xa3\x39\xa2\xb6\xc7\x86" + "\x9f\x3a\xb0\xd3\xbf\x50\x52\x6e" + "\x6e\x53\x0d\xfd\x30\x89\xd9\x79" + "\x32\x38\x0c\xfa\xab\xbb\x4c\x8c" + + "\x39\x23\x3b\xa4\xc9\x38\x9b\x16" + "\xab\xbf\x32\x17\xd9\x08\x43\x88" + "\xdd\x02\xf2\x8f\xa2\x93\xb5\xe4" + "\x6c\x37\x65\x1e\x1f\xd1\x51\xaf" + "\xff\x25\x15\x74\xde\x48\xc6\x6e" + "\x28\xc6\xf4\x9f\x36\xbd\x3c\xf9" + "\x79\x9c\x12\xb1\xef\xf9\x6d\xc7" + "\x94\x72\xa6\xb7\xe2\xf2\xa5\x31" + + "\x1e\x1f\xb9\xca\x10\x09\x50\x2d" + "\x16\xd2\x1c\x4d\x44\x9e\xdd\xbe" + "\x52\x22\xd0\xed\x4f\xb7\x34\xd6" + "\x7a\x61\x58\x12\xe1\xf8\x60\xbd" + "\x4a\x61\x05\x9e\x7b\x53\xc7\xd8" + "\xc5\x5f\xaf\xe7\x66\xc7\x26\xfd" + "\x26\xd9\x2b\x58\x81\xb5\x60\x06" + "\xc8\x7f\xf0\xac\x44\x92\x01\x87" + + "\x8e\xfe\xdc\xba\x22\x73\x3b\x2c" + "\x04\x5a\xe2\xc5\xfa\x16\x06\x6e" + "\xa2\xe4\xa6\x3d\x75\x12\x3c\x0a" + "\x01\xca\x7b\x07\x7e\x95\x6c\xe4" + "\x4b\xe6\x4b\xda\xe3\xa4\x6c\xb4" + "\x78\xee\x75\x8e\x66\xda\x9b\xa5" + "\xf2\x98\xde\xa4\x84\x51\x83\x41" + "\x68\xa5\xd6\x4e\x92\x1f\xfb\x6e" + + "\xb6\xec\x64\xaf\xcf\x6c\xa2\xaf" + "\x75\x27\xd7\x4b\x97\x4f\x05\xe6" + "\x5a\x69\x0f\x14\x5b\xab\xcb\xbb" + "\xde\xef\x48\xe3\xa4\xb4\x71\xbc" + "\x63\xd9\x96\xcc\xbe\x52\x2e\xfc" + "\x18\x90\x5d\x5e\x5f\xbf\x0a\x15" + "\x71\x87\x56\x04\xa6\x2f\x18\xbd" + "\x83\x9f\x33\x70\x61\xc0\xb4\x35" + + "\x05\x06\x37\x11\xb3\xb9\x41\x47" + "\x55\xb3\x09\x5d\xf7\x72\xfa\x47" + "\x6a\x4c\x14\x7a\xac\x71\x1a\x39" + "\xca\xe3\xb6\x98\xf4\xc0\x08\x08" + "\x00\x39\xe5\x7f\xef\xd9\xae\x7e" + "\xba\x30\xa8\xe5\xa5\xa2\x57\xf1" + "\xfc\x4a\x97\x27\x91\xc0\x3e\xd1" + "\x7d\x99\x87\x0b\xa7\x10\xd7\x78" + + "\x49\x8c\xaf\xee\x9a\xe9\x28\x89" + "\x28\xd7\x24\x6e\x3d\xa7\x7a\xee" + "\x6c\x15\x2b\xe7\xc2\x07\x50\x4c" + "\x1d\x8a\x40\xed\xc5\x57\xcf\x5f" + "\x04\x76\x05\xb6\x39\x9e\x71\x9f" + "\xbf\x8b\x86\xc2\x01\x3c\x34\x7d" + "\x2d\x3e\x10\x7e\x4b\x25\xca\x2c" + "\xa2\xbe\x31\xf1\xa9\x38\xeb\xe6" + + "\x11\x19\x20\xcd\xec\xd3\xe1\x27" + "\xeb\xc0\x72\xad\x70\x9a\x11\xb1" + "\xfb\x7f\xb5\x6a\xaf\xe3\xb3\xf8" + "\x2b\xc4\x92\x5b\x5b\x68\xc1\x23" + "\xaf\x7a\x8d\xd0\xb9\xb7\x27\x2c" + "\x1c\x59\x9a\x18\xc3\x0d\x66\x0f" + "\xca\x43\xc8\xad\x02\xa1\xca\x7b" + "\x52\x76\xb2\x1a\xb4\x8b\xd3\xde" + + "\x52\xff\x40\x5f\x4e\xa0\x24\xc6" + "\x4a\x91\xd2\xfc\xcf\xd7\x11\x36" + "\xd6\xbf\xd3\x1f\x2b\xb4\xe8\xb7" + "\x3a\x06\x85\xfa\xfd\x40\xde\x6c" + "\x5b\x7e\x8b\x17\x49\xc4\x11\x78" + "\x13\xcc\x72\x29\x31\x09\xb6\x4c" + "\x35\x61\xb4\x33\x5e\x12\x79\xf5" + "\x6e\xe5\xa4\x88\xf7\x2e\x10\xca" + + "\x84\x0b\xef\x5d\x7f\x67\xbd\x96" + "\xb9\x99\xde\x97\x7b\xa8\x6f\xe9" + "\x53\x15\xbe\x4e\xc1\xfe\xd3\x5d" + "\xcd\x75\x42\x7e\xe6\x43\x57\x31" + "\x23\x83\xb4\xb1\x25\x31\xf1\x81" + "\x75\x8e\x49\x4d\xdd\xb1\xaf\xc4" + "\xd9\xda\x15\x3f\x7d\x8e\x56\x84" + "\xb8\x73\xae\xa3\x1b\xa6\xe3\xd8" + + "\x0d\x1b\x98\x0a\x52\xe3\xa4\x0b" + "\xa4\x41\x1a\xbd\xb3\x4c\x35\x1c" + "\x9c\xab\x9f\xdf\x3a\xaa\xab\x1a" + "\xd5\x18\xc4\x53\xd1\xa7\x01\x07" + "\x21\xb9\xf2\xdc\xef\x7c\x1a\xdd" + "\x61\x80\xf4\xbc\xb3\xf0\xee\x6c" + "\xe6\xcc\x25\xde\x98\xb5\x83\x10" + "\x34\x5e\x0a\xe9\xc7\x54\x0a\x89" + + "\xf4\xca\x02\x1c\x42\xb4\x2b\xa6" + "\x5a\x7b\x62\xdb\x1d\x48\x74\x6a" + "\x2d\xf5\x6b\x2c\xf6\x25\x56\x1d" + "\xa0\x46\xb2\x73\x4c\xfd\xc5\x1f" + "\x3d\x81\x31\x17\x62\xfc\x6d\x3f" + "\xbe\x54\x88\xe5\x79\xdf\x22\x83" + "\xe4\x2e\x8b\xfa\xb2\x38\x14\xe5" + "\xa0\xcd\x4a\x2d\x48\x78\x73\xbe" + + "\x07\x18\xac\x40\x66\x95\x35\xc5" + "\x1e\x0b\xda\x84\x66\xe5\xc1\xd4" + "\x21\x24\xb8\xe0\x97\x3f\xb3\xc4" + "\x00\xbe\x41\x7b\x17\x23\xbd\xd0" + "\xe1\x72\x7b\x14\x2e\xb4\xa4\x53" + "\x4c\x10\x77\xf7\x5f\x9f\xd3\xf8" + "\x0d\x53\xfb\xd3\x64\x4e\xe6\x36" + "\xdd\x4f\x07\x56\x67\xba\xa6\xa7" + + "\x71\x7c\xca\x1e\xe3\x8f\x65\x1b" + "\xb8\xda\xad\xe4\x14\x52\x94\x20" + "\x99\xc2\xf9\x11\x3f\x5d\x4e\x7d" + "\x04\x50\x84\x2f\xe7\x2a\xf6\xd7" + "\x92\x1e\x2a\xe2\x6a\x6d\x7e\x41" + "\x41\x71\x4c\xca\x85\x7f\xb6\x1a" + "\xed\xb5\x9a\x27\xc0\xd9\xb2\x44" + "\x11\xce\x57\xfa\xb8\xf0\x0b\x2d" + + "\xb1\x01\x6d\x4f\xdb\x18\x57\x40" + "\xa0\xe8\x11\x8f\xc2\x6b\x3c\xe7" + "\x3b\x1a\x59\xa0\x8c\xbb\x11\xac" + "\x31\x45\xcc\x0a\x5a\x9a\xd0\x12" + "\xf4\x13\xde\xe7\xee\x74\xf1\xcb" + "\x82\xd6\x4f\x04\xe6\x2b\x7e\x17" + "\x70\xaf\x48\x1c\xcb\x74\xf5\x65" + "\x7c\xcb\x61\x99\x92\x66\x59\xce" + + "\xe9\xba\xf6\x10\xfc\x6b\x83\x64" + "\x08\x76\x08\x0a\x6e\x61\xd5\x6b" + "\x07\x78\x0b\x2f\x63\xc4\xd5\xcf" + "\x78\x85\xa0\x61\x12\x27\x68\x05" + "\xcd\x2c\x0f\x63\x77\x37\x30\x30" + "\x40\xab\xe2\xc2\x32\xa7\xfd\x9e" + "\x92\x95\x0f\x6b\xc5\xb1\x95\xca" + "\xd8\xf2\xf2\xd0\x3e\xb2\x8f\xf7" + + "\x9f\xab\x6f\xbc\x4e\xe8\x9f\x98" + "\x74\x64\x0f\xc8\xb1\xe6\x0c\xe7" + "\xbc\xa1\x02\x3b\x05\xf3\x9f\xbe" + "\xd3\xaf\xc0\x99\x66\x48\xef\x12" + "\x26\x1a\x41\xe3\xf9\x57\xd9\x22" + "\x98\x5b\x48\x7b\x81\xd8\x41\x0b" + "\x19\x01\xe2\x4a\xd0\x56\x0e\x82" + "\xe0\x28\x85\x32\x1f\xd0\xe3\x81" + + "\x8a\x7c\x82\xbe\x77\xd4\x7d\xd4" + "\x4d\xe4\x10\xec\xe7\x69\x4a\xee" + "\x7c\xd7\x0e\x13\x38\x60\x23\xaf" + "\xf0\x65\x4c\x80\xce\x5c\x04\xf2" + "\xdb\x70\x4b\x2a\x03\x19\x87\xfb" + "\xf5\x9f\x3c\xb3\xcc\xb3\x36\xff" + "\x3d\x78\xd2\x1f\xe6\xf2\x37\x4c" + "\xd6\x71\x00\x91\xde\x7e\x11\xe5" + + "\xa1\x52\x87\x04\x6c\xed\x9e\xc5" + "\xb4\x41\x13\xa0\x2e\x70\xf2\x41" + "\x92\xb0\xc6\x9d\x3b\x90\x35\x6e" + "\x23\x5b\x5b\x1f\xa8\xab\x91\x42" + "\x1d\xd6\x53\xa6\x70\xaa\x73\x81" + "\x1e\xb5\x2e\x4f\xd4\x48\xb6\xd1" + "\x8f\x3f\xb9\x5a\x06\xce\xb7\x31" + "\xfe\xf4\xe2\x99\xee\x08\x54\xa5" + + "\x04\x44\xdc\xda\x8b\xfa\xc4\x1b" + "\xe3\x2e\xa1\xda\x34\x95\xdb\x0e" + "\x9c\x28\xf7\xa5\xb6\x81\x44\x08" + "\xd2\xb3\x8f\x9d\x1d\x46\x42\x7f" + "\x70\x3c\x29\x12\x32\x1d\x3f\xf9" + "\xa3\x3e\xb7\x6b\x59\x06\x47\xc1" + "\xad\x9c\x33\xde\xaf\x34\x08\xf8" + "\x53\x29\xf2\x81\x00\xfc\xdc\x99" + + "\x60\x41\xe3\x85\x09\xed\xa4\x1f" + "\xe2\xcd\x03\x7a\xc3\x7d\x6d\xa2" + "\x2d\xdf\x84\xfa\x48\x08\xac\x1d" + "\x08\x71\x69\x1b\xd6\x28\x9a\x5e" + "\xa1\x0e\xea\x14\xd9\x04\x80\xa8" + "\x20\x55\xfe\x3f\x28\x54\xd1\xa8" + "\x9c\x13\x9b\x63\xae\x2d\x42\x4f" + "\x61\xa8\xb5\xd4\x0d\xcc\xdc\xee" + + "\xcd\x8e\x74\xd7\x36\x16\x1d\x54" + "\x2e\x5c\x86\x7b\xf0\xab\x5a\x38" + "\x31\xe4\xdc\xe1\xec\xf9\xc2\xd2" + "\x52\xe0\x95\x8b\x25\x03\x16\xff" + "\x7a\x07\x33\x7a\x3f\x4c\xde\x0c" + "\x97\x1f\xe4\x12\x56\xdd\x5b\x67" + "\xf1\xa6\xf5\x71\xae\x81\x51\xc3" + "\xf8\x3e\x75\xae\xc8\x00\x56\xd5" + + "\xb4\x62\xe7\x8b\x4f\x62\x3e\xb3" + "\x13\x34\x8e\x05\xd1\xe4\x9e\x2a" + "\xfa\x05\xd8\x67\x69\x63\x8e\x96" + "\xd7\xbf\xb8\x7d\x9b\x94\x48\x98" + "\x17\x84\x3a\xd2\xe5\xd7\x08\x53" + "\xa5\x9d\xe2\xf3\x1d\x3b\x2f\x89" + "\x1f\x47\xee\x3d\x9e\x13\x5c\xc9" + "\x89\xe0\x57\xd7\x4d\x59\x31\x86" + + + "\x15\x56\x09\x1f\xea\xe2\x83\x10" + "\x33\x8c\xe6\x14\x77\xad\x28\x0a" + "\xbe\x18\x88\x3d\x52\x02\xfc\x6b" + "\xcd\x50\x58\xf3\x3a\x11\x85\xb5" + "\xa1\x8a\xdf\x30\x0b\x5f\x93\x7d" + "\xac\xe3\xb7\x4a\x7c\xa0\xdd\xad" + "\xcb\x00\x2f\x55\x99\x42\xc3\x92" + "\x6c\xdf\x09\x29\xde\xd1\x3e\xc3" + + "\x3c\x11\x07\x3e\x48\x0d\xc4\x2d" + "\xae\x63\x8b\x7d\x39\x5d\x4a\x6e" + "\x2b\x4c\x68\x79\x4b\xa9\x82\x55" + "\x6c\xa2\x2d\x62\xd4\x33\x2b\x93" + "\x8d\xf0\xbb\x0d\x51\xf6\x34\xf5" + "\x52\x3a\xc2\x64\xc9\x07\x1d\x21" + "\x9b\xdc\x5b\xee\x0f\xce\xee\x0e" + "\x58\x55\x01\xf7\x68\x81\x17\xdf" + + "\x0e\xd6\xcd\x83\x5a\x90\xe7\xab" + "\x84\x01\x17\xa1\xb5\x2f\x60\x50" + "\x2a\x64\x23\xb0\xcd\x86\x98\x68" + "\x00\xfb\xe1\xa6\x90\xd0\x68\xd5" + "\x7f\x21\x59\x02\xc7\x22\x19\x5b" + "\xe4\x41\x31\xc4\xd9\x1c\x83\x93" + "\x6e\xf8\x95\x0c\x87\x35\xca\xdf" + "\x28\xe8\x8a\x56\x7a\x05\xc2\xde" + + "\x6d\xc1\x3c\x91\x25\x89\x8f\x56" + "\x5a\x6f\xa2\xe1\x6d\x5b\xbc\x18" + "\xae\x99\xf4\xf5\xbe\x13\xa4\xdf" + "\x84\xae\xf0\xc3\xec\x5d\x83\xf8" + "\xb0\x0a\xa4\x65\xd8\x0b\xe6\xb6" + "\x7e\x37\x4b\x19\x39\x64\x59\x65" + "\x69\x4a\x08\x92\x25\x56\xd8\xbc" + "\xe0\xed\x23\x4f\xb9\x33\xe4\x5c" + + "\x89\x61\xe0\x42\x3d\x52\x0d\x86" + "\x13\xff\x3a\x4e\x41\x79\x07\xbf" + "\x50\x06\xb2\xc1\xca\x6d\x61\x0b" + "\x0d\x30\x31\x21\xd1\xd6\x6d\xe6" + "\xde\xab\x99\xff\x67\xfd\xa0\xd4" + "\x0d\xc5\xaa\xc7\x50\x35\x90\xc9" + "\xd7\xb2\x46\x7c\x8b\xcf\x2e\x02" + "\xaf\x92\xbf\x3a\xe8\xb1\x33\x33" + + "\x5d\x36\xd6\x84\xe7\x65\xda\xc0" + "\xb8\x9f\x75\x8f\x3f\x44\xb7\xbc" + "\x30\x19\xe8\x7a\xb1\x12\xc7\x35" + "\xab\x08\x6e\x4c\xff\x8d\x42\x80" + "\x43\xf8\xfa\xa4\xef\xaf\x9d\xf1" + "\x5f\x85\xa9\xff\x8d\x53\xd8\xce" + "\xce\xc7\x3a\xbe\x9c\x40\xac\x20" + "\x1e\xa7\x2d\x88\xb6\x1f\x8c\x35" + + "\x82\xa5\x42\xbe\xf7\xde\xec\xef" + "\xe6\x6b\x04\x65\x80\x60\xfc\xd3" + "\xa9\xdb\xe8\x09\xc8\x13\xaf\xc9" + "\xff\x91\x14\x64\x47\x98\x6c\x1e" + "\xf7\x31\x0c\xd3\x25\x49\x57\x3b" + "\x22\x21\x2a\xac\xba\x72\xeb\xb7" + "\xe7\x59\x08\xef\xac\x0d\x6a\x77" + "\x42\x09\x90\x21\x14\xc3\xfe\x06" + + "\x2b\x12\x50\x7e\xb0\x94\x47\x32" + "\xa5\x7c\xf0\x4a\x8b\x4f\x74\xdd" + "\x7b\xc9\x3f\xd6\x08\x2f\xa1\x30" + "\x9d\x6d\x62\x76\x1a\x0f\x65\x39" + "\x77\x84\xa3\x1f\xf7\x47\x1b\x10" + "\x4f\x12\xdc\xd4\x19\x5f\x81\x3d" + "\x8a\xb5\x6e\xb2\x95\xae\x69\x15" + "\x87\x18\xfb\x95\x88\xe1\xcd\xc3" + + "\x21\x7f\x73\xf4\xbb\x2f\xc6\x7e" + "\xac\xf5\x09\x62\xab\xa5\xdb\xd8" + "\xbe\xad\xf9\xa5\xa9\xd7\xb5\x24" + "\x68\xc7\x1d\xa6\xf7\x28\x7d\x70" + "\xea\x99\xa9\xca\x0b\x46\x11\x77" + "\xcc\xe4\x92\x1c\x4d\x17\x7b\xba" + "\x2d\xbf\xd4\x18\x66\xab\x4b\x3c" + "\x79\xd2\x8b\xeb\x80\xc9\xf0\xb8" + + "\xbf\x91\x06\x79\x32\x89\x65\x9d" + "\xae\x36\xb7\x06\x89\x05\x61\xed" + "\x6e\x3b\xd6\xc0\x04\x2f\x2c\x71" + "\x8f\x48\x3d\xc6\xd5\x6f\xf0\x5c" + "\x41\x8e\x58\xd9\xac\x3f\x36\x97" + "\x7e\x25\x93\x2b\x62\xf7\x9b\x1f" + "\xce\xca\x7a\x66\xc4\xff\xd1\xa9" + "\xcf\x1e\x06\x0a\xaa\xa1\xf4\x1c" + + "\x23\x9a\x51\xc0\xb2\x75\xd6\x28" + "\xe3\x52\x69\x4f\xfe\x94\xbf\x9e" + "\x8a\x4a\x29\xa2\x67\xb7\x8b\xf2" + "\xf5\xf3\x0a\xfe\x4d\x2b\x51\x85" + "\x0d\x6a\xb1\x99\xa8\x8b\x95\x18" + "\xa7\x48\x75\xba\x0c\x43\xc2\x95" + "\x15\xe6\x6b\xa1\x10\x1b\x0d\xb3" + "\x4c\xb7\xbf\x85\x97\xbb\xeb\xe3" + + "\x45\x36\xe6\xb2\x5e\x3f\xb5\x07" + "\x32\x42\xc8\x84\x47\xe5\x57\xbe" + "\xcf\xd5\x14\x72\x16\xc2\x79\xd7" + "\xca\x3a\x9a\x02\xcd\x69\x79\x61" + "\xa0\x17\x70\x8a\xcd\x68\x76\xd1" + "\xe8\x7e\x9b\xbe\x9a\xd1\xb4\x77" + "\x76\x17\x16\x9c\x93\x0e\xfd\x58" + "\x72\x8a\x96\xd5\xef\xf4\xc4\xa8" + + "\x23\xca\xfd\xd2\x65\xb8\xee\x81" + "\x95\xf8\x8e\xcc\x08\xee\x15\x5a" + "\x14\x56\x90\x01\x0a\xa1\x8f\x76" + "\x9b\xe1\x0e\x88\xef\xb8\xf5\xef" + "\x0e\x8a\x1c\xcb\xbb\xca\xc0\xf0" + "\xf9\x38\xc8\xb8\xcd\xe9\x1e\x2e" + "\xc0\x14\x4a\x8a\xb8\xd8\x87\x05" + "\xe5\x98\xf6\x2f\x96\x78\xf2\xf6" + + "\x80\xda\x44\xbf\xb3\x34\x9d\x51" + "\x66\x2e\xb3\x5a\xf9\x34\x38\x28" + "\x00\xa0\x78\x62\x97\x87\x60\x6e" + "\xf6\x12\x73\x62\x0e\x96\x62\x1e" + "\x55\x1c\x90\xe6\x7b\xb2\x87\x9b" + "\x1f\xbc\xfd\x24\x38\x85\xe7\x80" + "\x7d\xc2\xac\x2f\x51\x09\xbc\xbb" + "\x5a\x3b\x14\xac\x39\x42\x39\x06" + + "\x99\xce\x2f\x9e\x6e\x64\x4b\x9c" + "\x7f\x85\x80\x1e\x81\x10\xa2\x68" + "\x2a\xb5\x43\x36\x44\x4e\xd5\x06" + "\x43\xb8\x8e\x0d\x63\x6d\x8d\xde" + "\x0a\x6a\x14\x42\x63\x15\x32\x70" + "\x22\x36\xaa\x5e\xf2\x26\xa8\x8b" + "\x87\x87\x13\x86\xbd\x58\x7a\x22" + "\x37\x1d\x28\x10\x3c\xc0\xb6\x43" + + "\xff\xde\x41\x2f\x95\x7a\xb3\x02" + "\xb7\x89\x3b\xe6\x9a\xa5\x44\x0e" + "\x51\xf9\x3f\x14\xdc\x57\x32\x67" + "\xf4\xba\x52\xd7\x05\x22\xc0\x19" + "\x92\xd6\xb7\xc4\x69\x30\xc2\x46" + "\xac\x02\x15\xfd\xc3\x92\x63\x2e" + "\x46\x08\x22\x1b\xa2\xb1\x57\x60" + "\x63\x5b\x1b\x0c\x46\xf9\x1f\xe5" + + "\xf0\xc0\x2f\xf0\x32\x26\xca\x7a" + "\x86\x1c\xf0\xc7\x7d\x33\x2b\xb9" + "\x7d\xdc\xfb\x5a\xbf\xc4\x4b\x62" + "\x5e\x1a\xe2\x4d\xbc\x07\x2b\x81" + "\xcc\x90\x20\x0b\x24\x37\xd1\x29" + "\x32\x21\x1b\x5a\x09\xc5\x03\x04" + "\x15\xe0\x35\x0e\xd5\x34\xca\x1d" + "\x6f\xb6\xbb\x3b\x7d\xed\x85\xf0" + + "\x35\x57\xae\x2e\x86\x66\xc8\xbe" + "\x3e\xf0\xb6\xf9\xf2\x01\x05\x58" + "\xc2\x74\x0e\x99\x63\x20\xff\x8b" + "\x40\xc8\x40\x9f\x3d\x4e\xdc\xfa" + "\x2a\x6f\xeb\x32\xa0\xd3\x57\x03" + "\x8a\xc9\xf1\x0d\x2e\xb2\x18\xe3" + "\x38\xdd\x2a\x50\x8d\x2d\x9a\xbb" + "\x6a\xce\x84\x4a\x7a\x95\x7e\x6f" + + "\x65\xe8\x81\xf7\xf9\x98\x7b\xc2" + "\x45\x13\x4e\x99\x92\xf6\xe1\x51" + "\xee\x61\x93\xe1\x16\xd5\x07\x08" + "\xef\x8a\x99\xfb\xef\x5c\x88\x13" + "\x17\x8a\x0f\x2f\xe9\xd5\x23\xd2" + "\x80\x02\xd2\xe8\x10\x20\x67\x48" + "\x98\xac\x7e\x23\x60\xfd\x02\x6f" + "\xe7\x7e\xda\x9a\xad\xbf\x51\xcc" + + "\x48\x36\x1f\x3d\x67\x8d\xe7\x0b" + "\x44\x26\xf8\x26\xbf\xae\x70\xb1" + "\xf5\xa6\xaa\x11\xaf\xb5\x88\x9d" + "\xb2\x0e\x93\x40\xb2\x4e\x44\x57" + "\x06\x29\xd9\x4a\x76\x4a\x96\xd0" + "\x5f\x7e\xf8\xbf\xe3\x5d\xa0\x4c" + "\x84\x90\x86\x0b\xc8\xa6\x41\x11" + "\x8d\x94\xda\x4a\xa3\xfc\x83\x31" + + "\x1d\x70\x09\x1e\xdd\xbc\x56\x27" + "\x80\x5c\xd4\x90\xb9\x1d\xe3\x94" + "\x84\xe5\x66\x85\xa9\x56\xe8\xb9" + "\xf3\xe3\x10\xab\xde\xd9\x87\x4f" + "\xb2\x9c\xed\x3d\x37\xcb\x6e\x16" + "\x3e\x3d\x65\x3f\x07\xc7\x14\xfd" + "\x25\xc4\xae\x92\x9b\x04\x5d\x10" + "\x11\x2e\xa4\x09\x49\x7e\x65\x7f" + + "\xa1\x09\xd6\xa5\x9b\xa3\x80\xc3" + "\xcb\x0e\xc1\x24\x77\x1e\x71\x6c" + "\x70\xd0\x22\xb9\xc6\x3c\xd5\xe8" + "\x84\x7d\xb5\x0a\x81\x7b\xc3\xea" + "\xa7\xca\x70\xa7\x78\xc9\x60\xe2" + "\xb5\xf4\x71\xaa\x29\x61\xf2\xdb" + "\x30\x8e\x9a\x48\xb6\xd9\xee\xe2" + "\xfe\x75\x3f\xeb\x7f\xd2\x8f\x48" + + "\x94\x95\x15\x6a\x07\x90\x64\xea" + "\x52\xce\x97\x1f\x6b\x4d\x42\x3e" + "\xcb\x8c\x5e\x18\x0a\xf3\x6d\xac" + "\xbf\x47\x77\x51\x80\xec\x56\xad" + "\x93\xfe\x91\x43\xcf\x5c\x93\xf0" + "\x40\x1d\x81\x03\x0f\x26\x6b\x86" + "\xbe\x9a\x7b\x9f\xb9\x47\x20\x79" + "\x84\x2d\xe4\x8e\xc8\x0b\x60\xb1" + + "\x23\x71\xa3\x7c\x92\x45\x58\xdd" + "\xd5\xbd\x8b\x08\x11\x13\x3f\x90" + "\x2e\x27\xc2\xa2\x65\xcf\xde\xdc" + "\xe0\x6f\x1f\xd6\x26\x6e\x35\x9e" + "\xc0\x0d\x48\x54\x9d\x9f\xad\xee" + "\x5a\xbe\x46\x14\x40\xa1\xca\x91" + "\xd1\x75\xc0\xc4\x8d\xcc\x66\x9c" + "\xb8\xc9\x85\xbc\x62\x9a\x52\x5e" + + "\x5f\xa8\x68\x77\xdb\xb3\x97\x2d" + "\x38\xe0\x87\x42\x33\xf6\x78\x2b" + "\xb1\x2b\x89\x6f\x67\x47\xc9\x86" + "\x00\xc2\xa9\xc0\x1a\xfb\x0b\x92" + "\xb2\x41\x20\x33\xec\xf6\x92\x42" + "\x54\x9d\x98\xc9\x37\xb9\x0b\xa3" + "\x9e\x87\xd5\xc6\xeb\x41\xf9\x39" + "\x87\xb1\xdb\xdf\xfc\x50\xa4\x76" + + "\x90\xa8\x29\x9c\xc3\x93\xb7\x5f" + "\xb1\x11\xa8\x87\xfd\x3b\xa0\xb0" + "\xd3\x28\xf1\x12\x49\x9e\x24\xb0" + "\xde\x3e\xed\x5a\x13\x3a\x7b\x10" + "\x32\xd9\x34\x20\x56\x99\xe1\x98" + "\x1c\xd7\xc7\x0d\x71\xc7\xce\xd8" + "\xb2\xe0\x31\xb2\x13\x37\x56\xe7" + "\x02\x8c\x96\xac\x85\xd2\x84\x62" + + "\xb6\x0d\x43\xee\x89\x60\x25\x31" + "\x56\x6f\x83\xf6\xd8\x9b\xce\xae" + "\x46\xa0\x85\xfb\x4b\xfc\x4c\x48" + "\xb9\xb2\x99\x15\x2c\x3e\x1e\xee" + "\xaf\x2e\x12\x3d\x90\x38\x3c\x7e" + "\x6c\x55\x70\xc7\xe0\x0c\x94\xaa" + "\xe8\xfa\x08\x1b\x63\xd6\x02\x48" + "\xba\xf8\x69\x7f\x80\x85\x8a\xb0" + + "\xae\x1e\x41\x05\x04\x0a\xed\x70" + "\x66\x4c\x49\x16\x8f\xb0\xde\x60" + "\xbb\x97\x37\x13\xc6\x0f\xf2\x8c" + "\x10\xc3\x6b\x0c\xf5\xf4\x30\x3e" + "\xc7\x46\x9c\x74\x29\x7c\x67\x1a" + "\x1c\x98\x1e\xf1\xf4\x93\x1d\xfe" + "\x8b\x68\x3e\x2e\xd8\x03\x73\x93" + "\x85\x9e\xaa\xa6\xa7\xf5\xae\x01" + + "\x20\xb9\x59\xb9\x95\xf4\x02\x49" + "\x85\xd8\xa2\xfc\xbd\xfd\xb0\x13" + "\xfa\xf0\xa2\xb6\xe7\xd9\xcb\x41" + "\x87\x0b\x43\x56\x10\xf1\xbd\xf9" + "\xb9\x19\x4d\x95\x23\xa2\x05\xd7" + "\xde\x4f\x2a\x97\x5c\xfc\xd0\x74" + "\xea\x77\x29\x91\xd6\xfe\xcb\xcb" + "\xaf\xa5\x59\xcc\xfd\x11\x06\x87" + + "\x57\x2f\x30\xbb\xab\x19\x72\xba" + "\x30\x27\xb3\xfa\x59\x00\xce\x28" + "\x22\x43\xf5\xa8\xa0\xdc\x26\xfd" + "\xcf\xbd\x6b\xb2\x6b\x0d\xa9\x69" + "\x8b\x63\x49\x89\xbc\xd3\x5d\xe9" + "\x2d\x6a\x2b\x92\xf1\xa4\xe1\x76" + "\xfd\x2c\x87\xd5\xb1\x3c\xf7\x99" + "\xce\xa3\x32\xdb\x9a\x14\x2b\x75" + + "\x6a\x23\x89\x40\xd0\x9b\xf1\xf4" + "\x0b\x0e\x3d\x31\x12\x6c\x20\x3b" + "\xb2\xae\xfe\x03\xf3\x0d\xe7\x73" + "\xe0\xef\xd1\x9b\xeb\xa0\xdb\x09" + "\x05\x53\x4e\xfc\x32\xd5\x7f\x4c" + "\x7a\x78\x3d\xe9\xed\xff\x92\xd7" + "\x10\x50\x24\xe4\xe2\xc4\x2d\xc7" + "\xbd\xbb\x66\x04\x7d\xd4\xe0\xe7" + + "\x43\x5c\x6c\x56\x51\xcb\x85\x6e" + "\x46\xf0\x97\x35\x19\xc9\xf9\xcf" + "\x4a\xd9\x94\x49\x0c\xe9\x54\x93" + "\x7d\x92\x47\x21\x32\x93\xa3\xe0" + "\x2b\xeb\xc1\x0d\xc1\xfa\x27\x84" + "\xfa\x19\xf3\x2f\xc2\xd8\xcf\x88" + "\x74\x52\x96\x01\x84\xe6\xd4\xe2" + "\x46\xa7\xaa\x67\x7d\x06\x2e\xfa" + + + "\x11\x9f\x5f\x3e\x7f\x2a\xd9\xb6" + "\x8e\x3b\xcb\xd6\x3a\x15\xfe\x9a" + "\xbd\x00\xf8\xdd\xd7\x6d\x1a\x4d" + "\x19\x7e\xf1\xca\xc0\x3c\xc1\xf6" + "\xee\xc3\x5f\x32\x8e\xc5\xf6\x15" + "\xb2\xc3\x1d\xa3\x00\x54\x09\x71" + "\xe7\xd3\xa3\xaf\x07\x7c\x8e\x16" + "\x2d\xae\xc7\x94\xa1\x17\x84\x3f" + + "\xc3\x40\x95\x31\x9b\x58\x42\x28" + "\xf8\xd6\x83\xa2\x59\x0f\x49\x18" + "\xcb\x9f\xae\xda\x84\x1f\x73\xa2" + "\xa0\x3b\x68\xc3\x60\xd9\xb6\x3d" + "\x69\x10\x61\x14\xbb\x63\x5c\xc8" + "\x05\xbf\x88\x07\xaf\x36\x94\xb1" + "\xd2\x60\x74\x34\xdf\x59\x54\x90" + "\xb1\x7d\x1a\xe1\x94\xe0\xf6\x73" + + "\x38\x9c\x1b\xc3\x91\xbb\x85\x7b" + "\xb5\x57\xef\x48\x0b\xa9\x5a\x0c" + "\x6f\xab\x3b\xaf\x69\xb1\xde\xde" + "\x85\x36\x37\x2d\x73\xad\x10\xe6" + "\x15\x8e\xba\x02\xdf\x70\x38\xf1" + "\x71\xf7\xa7\x8c\xb6\xed\x37\x03" + "\x6c\x03\x2c\xb6\x47\xf7\xac\xe4" + "\x81\x4e\xb9\xb6\x76\xd5\x21\xd9" + + "\xcb\x76\x3c\xee\xc8\xa3\x06\xf3" + "\x6e\x1f\x2a\xd3\x23\x16\xf1\x3c" + "\x56\xe9\x63\x68\x64\xab\xd5\xe6" + "\x26\x5c\x00\x5c\xbe\x4c\x8a\x3b" + "\x27\xbb\xe6\x9c\xa5\x29\xd5\xdc" + "\x6f\xb1\xd4\x04\x52\xaa\xaf\xc4" + "\x8d\x79\x23\x79\x26\x4a\x62\xb0" + "\xab\x7f\x30\x6b\xf6\x6d\xe5\x85" + + "\x14\xd6\x9d\x85\x34\x53\x3e\x3a" + "\xee\xc8\xd0\x18\x5b\x5b\x47\x9c" + "\xd5\x51\xcd\x07\x1f\x0d\x08\x63" + "\x26\x43\x8b\xb8\xa6\xd0\xc0\xc9" + "\x6f\x29\x34\xc2\x91\x86\xc9\x1a" + "\xb6\x7f\x88\x94\xa4\x83\x0a\x2a" + "\xf2\x9c\xea\x0c\x27\x14\x51\x56" + "\xf5\x02\x48\xa2\xe8\xa6\x30\x52" + + "\xaf\x13\xe9\xbc\x3d\xc7\x0f\xad" + "\xcb\x07\x8a\x45\x7b\x58\x9e\x90" + "\x8a\x0c\xf0\xd4\x84\xda\x00\x13" + "\xac\x66\x44\xb5\x48\xd0\x5c\x42" + "\xbf\xd8\xe9\x90\xbe\xb9\x9c\xb5" + "\x0e\x1b\x43\x3e\xdb\x16\x16\x99" + "\xff\xec\x1a\x53\x7a\x11\xaa\xd3" + "\x3b\xdc\xf4\x59\xd3\x92\xaf\x91" + + "\x36\x5c\x44\x20\x07\xe2\x3e\x7a" + "\x74\x71\x87\x59\x82\xac\xd1\x71" + "\xe9\x73\x9f\x94\xf7\x39\xc5\x0f" + "\x81\x30\x2e\x98\xd7\xf3\x5c\xd0" + "\x29\x71\x1c\x7b\x0b\xe2\x58\x87" + "\xf2\x61\x9e\x56\x20\xcc\xad\xff" + "\x2d\x4c\x54\x59\x2f\x3a\x5d\xb0" + "\x53\x5e\xff\x9f\xc1\xf5\x16\xbe" + + "\x63\xa4\x4c\x4e\xef\x0f\x33\xb2" + "\x63\xcc\x66\x35\x87\x72\xef\xbc" + "\x00\x09\x78\xcf\xca\xd2\x61\xd1" + "\x7d\x82\x54\x5b\x39\xc5\x5d\x13" + "\xc6\x1b\xbf\x27\x2e\x05\x8f\x63" + "\x6c\xa0\xdf\x07\xf0\x24\xa2\x10" + "\xda\x21\x33\x6d\x6d\x58\x73\xe9" + "\x8f\x2c\x15\x26\x38\x57\x0c\x8b" + + "\x98\x60\x55\xb9\x8b\x17\x43\x70" + "\x86\x38\x1c\x80\xdf\xa1\x90\x40" + "\x12\xb9\x67\x9b\xff\x00\x98\x75" + "\xc8\x20\x26\x23\x04\x03\x5c\x3e" + "\xca\xee\xdc\x70\x4b\x3c\x9d\x4b" + "\x8e\x64\x1f\x18\x15\x3c\x2d\xbb" + "\x5c\x34\x33\x6e\x37\xd8\x81\xf9" + "\x7a\x29\xf2\x0c\x9b\x28\x26\xb6" + + "\x0f\x5e\xbe\x32\xbd\x4c\xc7\x9d" + "\x75\x13\xa0\x17\xb7\xbc\x75\x74" + "\xb1\x72\xd8\x50\xc9\x77\x84\x43" + "\x3d\xd6\xe1\xff\x79\x78\xc6\xce" + "\x70\x8c\x57\xd8\x14\x60\x00\x9b" + "\x8b\x6b\xbb\x78\xa8\x99\xad\xc9" + "\x06\x38\xfb\x11\x8e\x00\x99\x67" + "\xb3\xca\x44\xcd\x35\x14\xe8\xcf" + + "\xe4\xd2\xf2\x9e\xc1\xfe\x3f\x11" + "\x7f\xea\xa0\xd5\x7e\x76\xf6\x1b" + "\x0a\x4c\x71\x03\x5e\xf7\xff\x57" + "\xee\xe9\x23\x0a\x2e\x42\x3c\xa2" + "\xaf\x83\x0f\x54\x2d\x6b\x5f\xdd" + "\xa7\x46\xea\x55\x7e\xc2\xc2\xc2" + "\x08\x12\x2a\x67\x46\x42\x6b\xeb" + "\x7a\x4f\x63\xae\xf7\x99\x35\xd1" + + "\xf7\xaa\x84\x98\x95\x95\x68\x89" + "\xa6\x48\xb3\x07\xe3\x9b\x95\xb1" + "\x87\x7c\x14\x3c\x57\x0e\x25\x96" + "\xf8\x61\x0c\xdd\x3a\xfb\x0e\xae" + "\x5e\x32\x8c\xca\x5e\x74\x00\xed" + "\x70\x3f\xff\xec\x96\x16\x91\x3c" + "\x1d\xd4\x9a\x31\x65\xbc\xac\x73" + "\xef\xc7\xb1\xf0\x20\xa0\x01\x7b" + + "\x6e\x04\x79\x9d\x0d\x79\x89\xaf" + "\x76\x09\xee\x6c\x2d\x0f\x65\x4d" + "\xca\x1e\x07\x43\x9a\x5d\x93\xa3" + "\xfe\x0b\x3b\x28\xc9\xd2\xfc\x66" + "\xf1\x05\x66\x69\xb5\x5e\x66\x0e" + "\x8d\xd3\x4c\xa5\x07\x5d\x7e\xe7" + "\xcf\x50\xd9\x43\x0a\x05\xee\x90" + "\xb5\x69\x2e\xd3\xda\xeb\xdd\x86" + + "\xe8\x31\x86\x3a\x9b\xb8\xed\xd2" + "\x46\x37\x21\x7a\xde\x55\xe8\x8d" + "\x11\x5f\x0c\xb0\xb7\x6c\x05\xb2" + "\xe4\x85\x9b\x2c\xd0\xfb\xae\xde" + "\x2d\x89\x50\xd1\x8d\x9a\xf3\x03" + "\x85\x79\x8b\x21\x86\x46\xb8\x37" + "\x1a\x5f\x37\xb7\xd8\x6d\x29\x36" + "\x8e\x89\x8e\xb7\xb1\xd4\x2c\x47" + + "\x93\xbd\x8f\x30\x53\xae\x45\xeb" + "\xda\x6f\xc3\x02\x2e\x5a\xcd\x46" + "\x85\x83\xa4\xba\x90\x4e\x3d\x6a" + "\x60\x99\xbe\x9d\x2e\xe6\x55\xdd" + "\xe7\xed\x81\x2a\xa0\x6a\x40\xa1" + "\xa7\x4e\x27\xf9\x14\xdd\x60\x68" + "\x86\x4f\x41\x80\xc2\xb0\xdc\xcf" + "\x27\x43\xf9\x22\x10\x0b\x41\xff" + + "\x96\xd8\xa5\x23\x6b\xba\x10\x99" + "\x4e\x36\xe4\x7f\x35\x9e\xe1\x1f" + "\x77\xc6\x33\x9a\xc3\xa8\x1d\x6e" + "\xd0\x9f\xfd\x29\x8b\x48\xb4\x15" + "\xbf\x22\x1f\x1a\x54\x92\x43\x1f" + "\xe8\x63\x81\xab\x70\x8a\x0a\x92" + "\x8e\x65\xe5\x07\x49\xb2\xd1\x3f" + "\x9b\x83\xec\xb6\x9c\xf7\xc4\xf2" + + "\x84\x3f\x4a\xb4\xe3\x5d\xd5\x17" + "\x90\xc6\xc6\x17\x44\xf3\xb2\xac" + "\x90\x23\x23\x10\x68\x81\x08\x32" + "\xf7\x3b\x73\x6c\x1f\xa6\xe8\xf2" + "\x52\x76\x2d\x9c\xb6\xaa\x74\xa7" + "\xbc\xc5\x95\xed\xe3\x07\x53\xfb" + "\x10\xf1\x81\x49\xc2\x73\x5c\xa0" + "\xc9\x58\x94\xa3\x1c\xe3\xaa\x1b" + + "\x8b\x2d\x5d\xc5\xbb\xb2\x1d\xce" + "\x56\xca\xf6\xf4\xb7\x8b\xd5\x41" + "\x14\x76\x87\x8f\x80\xb6\x50\x76" + "\xed\x49\xc3\xf4\xba\x16\x5e\x90" + "\xac\xac\x61\xf6\x40\x51\x41\xed" + "\xaf\x70\x22\xcb\xf0\x84\x87\x3b" + "\xba\x2c\x40\x8a\xac\x80\xc2\x3b" + "\x1a\x92\x37\x09\x46\x71\x3f\xd5" + + "\x30\x17\x34\x78\x6c\xd8\x1e\x7f" + "\x48\xe2\x25\xb5\xb8\xbe\xf5\x8e" + "\x38\xbf\x4f\xb7\xfd\x89\xc4\xbb" + "\x82\xb3\xa0\x91\x0e\x2a\xa9\x38" + "\xcf\x3c\x43\x22\x3f\xba\x77\x7a" + "\xa9\x05\x9f\xa2\xd6\x62\x83\xde" + "\xfc\x9a\x18\x61\xea\x30\x6a\x7f" + "\x4f\x11\xef\x59\x05\x55\x3b\x69" + + "\xdc\x08\x4c\x22\xb5\x43\x21\x26" + "\x91\x0c\xb5\x81\xb4\x09\xbb\x2b" + "\x4f\xc8\xa8\xac\x09\xd7\x6e\xc1" + "\xa8\x0c\x85\xb2\x9d\x0d\x21\xa6" + "\xd6\x54\xcb\x09\x7a\xf6\x8d\x6d" + "\xa4\x19\x09\x50\xe0\xf6\xee\x91" + "\x57\x28\x13\x0f\x81\x13\xf6\x90" + "\x8b\x02\xd5\xf8\x47\xde\xce\x9a" + + "\xb8\x06\xd8\xce\xa8\x2f\x1a\x07" + "\x78\x14\x7f\x69\x34\x61\x2e\x22" + "\xbf\xdb\xfc\xab\x5d\xfd\x16\xdc" + "\xb8\x53\x1b\x12\xbf\x2e\x91\x44" + "\x7c\xc2\x96\x24\x74\x36\x94\xac" + "\xb0\x26\xfc\x1f\x6c\x17\xa3\x8e" + "\x2c\xbf\xde\x13\xac\x24\xe2\xb6" + "\x32\xa8\x72\xf3\x35\xc2\x4c\x52" + + "\x2f\x96\x67\x35\x7d\x36\x98\x7e" + "\xfb\xbf\x88\x81\x1f\xd6\x9e\x37" + "\xa1\x30\xf1\xfa\x48\xa3\xbb\x73" + "\x34\xd7\x4e\x90\xe1\x75\x1f\x6c" + "\xfc\x79\x4a\x3b\x42\x66\x95\x18" + "\x93\x44\xef\x54\x3d\xc8\x0b\xf2" + "\xa1\xec\x11\x91\x5d\x42\x6d\x83" + "\xcf\x8d\x9a\x00\x18\xc3\xb5\xe5" + + "\x34\xd5\x85\xda\xbd\xa5\x71\x27" + "\xea\x0e\x98\xff\x1f\x8c\xe7\x53" + "\xe7\x85\x03\x90\x84\xcf\xf1\xad" + "\x62\x7b\x38\xc9\xf6\x14\x3b\x7d" + "\xd2\x2b\x8f\xcb\xb0\x74\x0e\x17" + "\x93\xa9\x7f\x82\x86\xb4\x50\x2d" + "\xab\x2b\xf3\xf6\x9a\x8c\xbe\xcd" + "\xb8\x3a\xb9\xc3\xb0\x06\xe9\x55" + + "\xa5\xa6\x16\x14\x69\xa0\xce\x84" + "\x1c\x88\xef\x43\x79\x0c\x86\x8f" + "\x5d\x8a\x03\x38\x8a\x1f\x31\x41" + "\x67\x20\x61\xfc\xc0\x2e\x8c\xe7" + "\x81\x35\xd7\x5a\x81\x2e\x4d\x49" + "\x97\x40\x60\x59\x00\x9e\xcc\xb4" + "\xba\x2c\x61\xf3\xec\x8a\x55\xff" + "\x9e\xc3\x36\x9e\x7a\xef\xbe\x35" + + "\xee\x06\xba\x36\xcc\xc0\x4e\x32" + "\x0c\xcc\xd2\x3d\x15\x31\xce\xfa" + "\x1f\xe9\x33\xf3\xbe\xf3\x64\xb3" + "\xb0\x32\xe8\x28\x73\xff\x8a\xef" + "\x1b\x84\x05\x2d\x04\xad\x9b\x1e" + "\xe2\x21\x6a\x35\xdf\xe3\xf0\x42" + "\x7e\x62\xdd\x4a\xcb\x0b\x27\xa3" + "\x11\xe7\x22\xd3\x58\x81\x9a\xb0" + + "\x04\x6e\x92\x66\xcd\x8e\x3f\x32" + "\xba\xc1\x10\x81\x8f\xe3\x01\x00" + "\x07\x7f\x6a\xfc\x12\xac\xbc\x8d" + "\x27\x08\xec\x0c\x58\x1d\x5e\xd6" + "\x2d\xca\x76\xbe\x41\x41\xcd\xd2" + "\x3a\xf3\x92\xe8\x5c\xcf\x95\x78" + "\xd2\x39\x71\x36\x0d\x23\x6d\x95" + "\xc1\xc4\x12\xd0\x3e\xbd\x1a\xa9" + + "\x26\xd4\x95\x62\x9d\x77\xff\x28" + "\x7b\xad\xa3\x3f\xc7\x6a\x4f\x0c" + "\x04\x26\x8e\x8b\x54\xd0\x44\xec" + "\xe1\x50\x00\x8b\x6d\xa6\x32\x9b" + "\xe2\x6c\x47\xf0\x66\x33\x94\x1f" + "\xb4\xc7\x02\xa6\x53\xd9\x54\x75" + "\x09\x28\x4f\x52\xa6\xac\x35\xbe" + "\xea\xdb\x4e\xfd\x29\x12\x88\xb6" + + "\x29\x36\x67\xde\x46\x14\xe2\x45" + "\x21\x2d\x3c\x70\x1e\xaa\xf7\x57" + "\xc7\x68\xc8\x98\x7f\x9b\xe9\xa0" + "\x76\x16\x64\x8b\x6d\xf6\x42\x4e" + "\x96\x78\x07\x91\xdc\x84\x28\x60" + "\x5b\x88\xc9\xc2\xcf\x90\xd6\xa0" + "\x87\x51\x9a\x3b\x33\xda\xb4\xfe" + "\xee\x87\x3c\x15\x98\x95\x78\x5f" + + "\x90\x96\xf0\x15\xe7\xdc\x82\xb7" + "\xc9\x0f\xfc\x2d\x12\x9b\x8b\x50" + "\xc6\x9f\xd8\x65\x4b\xab\x15\x90" + "\x0f\xbb\xd5\xd6\xb7\xda\x79\x5e" + "\xa2\x5a\x77\x6c\xf0\x21\xf0\x64" + "\xa1\xec\xc7\x37\xcc\xd8\x09\xdf" + "\x06\xa5\x2f\xef\x67\x13\x76\x9a" + "\xc6\xee\x81\x5b\x76\xa4\x4c\xed" + + "\x7c\x86\xb0\x67\x19\x71\x83\x3b" + "\x20\x45\x36\x9d\x08\x0d\x5e\x8d" + "\xe3\xf0\x30\xd9\x1e\xcc\xdc\x52" + "\xaf\xbb\x20\xbf\xc7\xce\xbb\xef" + "\x10\xad\x63\x02\xab\xfc\xcf\x99" + "\x8a\x8f\xd1\xfc\x6d\x9e\x19\xd8" + "\x17\x06\xf1\xe9\x3f\x77\xe2\x64" + "\x48\x48\x70\x08\xe1\xe8\x79\x00" + + "\x2b\x34\x2f\x5c\x4d\xce\x9c\xbb" + "\xae\x7a\x2d\xb5\x7a\x90\x80\xbf" + "\xd0\xbc\x61\x21\xcd\xd3\xf3\x97" + "\x4d\x74\x62\x09\x34\x08\x5b\xb2" + "\xda\x1d\x3a\x6c\xa5\x8e\xb1\xc5" + "\x17\x23\xc9\x06\xeb\xc7\x4e\xfe" + "\xfe\x4a\x1c\xad\x90\xb8\x87\xb7" + "\x1a\x80\xde\x0e\x92\x9a\xcd\xdc" + + "\xe8\x7e\x49\x76\x9c\x61\x5c\x8b" + "\x0e\x37\x17\xc7\xc6\x0a\x2b\x5d" + "\xe1\x68\xcf\x4f\xb6\x4c\x20\x98" + "\x92\x67\xbc\x62\x11\xc2\xde\x0b" + "\x11\x10\x3b\xa6\xef\xcc\x73\x69" + "\xc5\x1a\xde\xe0\x97\xfa\xe3\xf9" + "\x8b\x0c\x0e\x3d\x3e\x69\xfb\x5e" + "\xb4\xfc\xd4\xd2\xe9\x48\x72\x03" + + + "\x9e\x4f\xc3\x1e\xc9\x2d\x80\x80" + "\x03\x06\x81\x33\x35\x2d\x77\xd8" + "\xf3\xb4\x0c\x53\x6c\xd6\x06\x3f" + "\x29\xc1\x75\xc4\x0d\xed\xe5\x7b" + "\x10\x2b\xe8\x31\x19\x3c\x9e\xcb" + "\x4c\x6b\xff\xc9\x57\x28\x3d\xc6" + "\x5e\xb4\xa1\x92\xc6\x18\x21\xb9" + "\xca\xbb\x85\x72\x14\x44\xec\x0a" + + "\xef\xa3\x29\x1e\xe7\x9a\x18\xfc" + "\x2e\x30\x93\x4c\xf0\x06\xe9\xcb" + "\x0e\xe1\xaa\xce\x14\x79\x10\xd0" + "\xf8\x19\x8e\xb6\x34\x3f\xa2\xb7" + "\x9d\x11\xd2\xef\xc2\x75\xd8\xe9" + "\xc8\xc9\xad\xfc\x6e\x8c\x19\x03" + "\x13\x71\xa1\x4d\xf6\x1b\x59\x65" + "\x38\x30\x44\x3d\xf8\xbb\xf0\x3c" + + "\x59\x47\x72\x2b\xb7\x5b\x48\xae" + "\x3a\xc6\xd4\xb2\xe1\x53\x53\x94" + "\x2c\x6f\x7d\xde\x07\x9d\x15\x82" + "\x09\xb1\xc5\x4e\xf3\xae\x9c\x38" + "\x14\xef\x65\xdb\x53\xbb\x8e\x4a" + "\x43\xde\x99\xdd\x7e\xcb\xc2\x2d" + "\x5f\x40\xf2\x83\xed\xa3\x6f\x81" + "\xa3\x08\x42\xc1\xb9\x9b\x42\x73" + + "\x27\x6e\x1e\xb0\x90\xd5\x18\xb6" + "\xdc\xb2\x80\xe1\xcd\x2c\x7e\x04" + "\xa9\xa4\xae\x04\xb5\x99\xb2\xd1" + "\xa4\x03\xa4\x9f\x1e\x9e\x2c\x41" + "\x52\x75\x40\x79\x36\x8a\xd2\x88" + "\xe3\xb8\x32\xf3\x36\x01\xc5\x49" + "\x19\xde\x68\xe6\xcc\x6f\x1b\x3a" + "\x97\x2b\x12\x75\xbc\x51\x88\x17" + + "\x4c\xfa\x85\xfb\x52\x37\xe1\xb1" + "\xe9\x8c\x3c\x38\xce\x57\x12\xd6" + "\xae\x4d\xf7\xd2\x70\xa6\x3d\xd4" + "\xbb\x6b\x84\xbf\x3f\xa2\x5a\xa3" + "\x83\xfc\x21\x44\x5d\x23\x74\x5e" + "\x3b\x47\x63\xc3\xe0\x8e\xdf\xf6" + "\x58\xa1\x4a\x3c\x2a\xf5\xd7\x34" + "\x2e\xd2\xc6\x9b\xab\x5a\xd0\x50" + + "\xf4\x85\x47\xa6\x35\xe7\x56\x8c" + "\x07\xcd\x29\x5f\x7b\x63\x56\xbc" + "\x67\x50\xe3\x3e\x80\xbb\xb2\x53" + "\x70\x92\x91\xdc\x0f\x5a\x23\x50" + "\x65\xaa\xc4\xf2\xd8\xb6\x1a\x19" + "\x3b\x02\x96\x83\x31\x58\x47\xc3" + "\xba\x05\xf8\xf0\xa5\x0b\x40\x80" + "\x0f\xf8\xc0\x5e\x5b\x06\x81\x88" + + "\x83\x5e\x1b\xcc\x22\xe5\x70\xc3" + "\xfb\x8b\x0b\x86\xd1\x4a\x2d\xde" + "\xdf\x56\xb2\x67\xf0\x4d\x36\xad" + "\x97\x89\x13\xe0\x2e\x50\x12\x8f" + "\x0a\x92\x83\x77\xdc\xa0\x3f\x50" + "\x6a\x86\xbc\xc0\xad\x14\x00\xe8" + "\xa6\x4b\x06\xd3\x44\xb7\x89\x3f" + "\xa5\xdb\xa5\xcb\xcd\x1d\x51\x03" + + "\xa2\xb1\xa7\x95\x6d\xd4\x7d\x19" + "\xfb\x41\x63\x3c\xd6\x7a\x4e\x9c" + "\xce\x2e\x4c\x48\x29\xca\x6e\x42" + "\x8a\x4f\x7f\xde\x89\xe4\x11\x92" + "\xf4\xf1\x8e\xc7\x6e\x7f\x99\x14" + "\x86\x45\x57\x06\x10\x09\x2c\x2b" + "\xe8\xed\x3e\x1c\x6e\x6a\x28\x17" + "\x18\xe0\x60\x0f\x47\x2e\xf9\x25" + + "\x36\x0a\x89\x31\x46\x56\x5c\x80" + "\x5b\xea\xfe\x57\x00\xf6\x3e\x70" + "\x30\x30\x3c\xaf\x7c\x74\x9f\x38" + "\x39\x37\xdd\x54\xeb\xda\xe5\xe0" + "\x55\xf1\xc9\xc9\xc3\xa4\x24\xfe" + "\x62\x39\x39\xb5\x76\xf1\x4b\x7e" + "\x29\xbf\x20\xaf\xe2\x3d\x18\x37" + "\x3b\x8c\x5a\xf9\xb5\xd7\x1b\x4a" + + "\x3d\x1d\x19\x46\x99\x96\x3b\xa8" + "\x57\xf2\x87\x7b\xdd\xc8\x1f\x28" + "\x88\x75\x10\x54\x13\x2c\x8e\xb1" + "\xe8\xaf\x2b\x9b\xf7\xde\x72\x63" + "\xca\x72\x89\x0d\x48\xbb\xf4\xda" + "\x3f\x7a\x16\x56\xb7\xd4\x2d\x3f" + "\xf4\x0c\x31\x84\x2d\xe3\xac\x1e" + "\xaa\x00\x27\xe4\xaf\xef\xbc\xe3" + + "\x3d\xe7\x85\xd7\x1e\x69\xe5\x5f" + "\x67\x04\xa6\x2e\xb6\x5a\xdb\xa5" + "\x4a\x51\xc6\xdf\x41\x3d\xe2\x02" + "\x65\x36\x3c\xe0\x8e\x04\xe8\x35" + "\xf8\xa0\xda\x1a\x8f\x11\x8b\x3f" + "\x5a\x1a\xce\x84\x45\x3b\xec\x28" + "\xb8\x46\x66\x2c\x6e\xcc\xca\xe8" + "\x0f\xe4\xd0\xdb\x85\xd1\x43\x13" + + "\x8c\x35\xaa\xca\x44\xf8\xd7\xe5" + "\x2a\x18\x24\x99\xe4\xb7\x1d\x1a" + "\x9a\x5d\x87\x9c\x2d\xd4\x4c\xd6" + "\xc8\xee\x2e\x04\x5f\x51\x7b\xb3" + "\xbe\x5f\x16\x7b\x09\xd4\x4d\x4d" + "\xf3\xef\x06\xe2\xd9\x2e\x32\xfc" + "\x7e\xe1\xb7\x59\x02\x41\xee\x7d" + "\x00\xca\x36\x82\xc0\x81\xa4\x55" + + "\x75\xc9\x3f\xc2\x12\x53\x88\x8c" + "\x7b\x29\xd6\x05\x06\x58\x71\x15" + "\x39\xdd\x8e\xf7\x8e\x86\x78\xa0" + "\x52\x5e\xc4\x03\xe0\x31\x6b\x95" + "\xa6\x33\x7b\xff\xd5\x75\x02\x47" + "\x3f\x67\x7e\x0c\x3a\xdc\xd5\xc8" + "\x98\x25\x2f\x7e\xb4\x27\x92\x41" + "\x75\xa9\x14\x4c\x34\xb6\x37\x8b" + + "\x8c\x88\x11\x8b\xd6\x7e\x66\xd0" + "\xdc\x25\x3e\x80\x3e\x8c\x0e\x5e" + "\x4a\xa2\x87\xb9\xdc\xd0\xe5\x34" + "\x23\x03\x92\xae\x3b\xac\x40\x9f" + "\x3a\xf6\xe0\x34\x95\xde\x63\x54" + "\xf9\x28\x63\x6b\x92\xbf\x28\xa1" + "\xb7\xf1\x64\xda\x7c\xcd\x1c\x49" + "\x35\xde\x7b\xc4\x27\xec\xf1\x7e" + + "\x37\x27\x6a\xa3\x0f\x24\x57\xa8" + "\xc1\x1b\x62\x63\x66\x13\xdc\x35" + "\x97\x68\xfb\xd4\x53\x64\x3a\x7a" + "\x9d\x31\x29\xc9\x39\xa4\xf1\x80" + "\xa0\x0b\xcb\xf8\x4b\x27\x18\xfc" + "\xeb\xc5\x78\x80\x66\x37\xb5\xb0" + "\xef\xd0\x01\x1e\x24\x49\x0d\xfb" + "\x9c\xb0\x2a\x37\x7d\xc6\xd7\x50" + + "\x68\xc9\xea\x3a\xaf\x70\xe3\xb4" + "\x66\x32\xb6\xc4\xe9\xfe\xf7\xe4" + "\x64\x56\xac\xe3\xc2\xd4\xac\xb4" + "\xbf\x8c\xb3\xce\xd2\x0b\x91\xf8" + "\x6e\x72\xc0\xc9\x0c\xe5\x3a\x1c" + "\xbf\x40\x7b\xd9\x69\x95\x30\x15" + "\x1b\x5a\x5a\xfd\x7f\x4b\x88\x70" + "\xcd\x14\x83\xef\x6a\x89\x90\x38" + + "\x93\x8c\x61\xa5\x5c\x51\xe1\x58" + "\xd1\x42\xd9\x77\x2b\x43\x65\xe6" + "\xa8\x67\xf7\xb6\xbf\x81\x21\xb3" + "\x10\x41\x60\x3a\xe8\x94\x37\x75" + "\xcc\xdb\xc0\xe8\x7c\xeb\xaf\x09" + "\xa3\x73\x86\x59\x13\x26\xe0\x31" + "\x00\xdb\x46\x7d\x57\xe5\x98\x5d" + "\x28\x5b\x98\x9d\x8c\xfb\x21\xfc" + + "\x0b\x3e\x84\xb0\x16\x01\x04\xc9" + "\x31\x45\xb0\x69\xa8\xb3\xb1\x53" + "\x30\xd8\xd7\x85\xf0\x49\x16\xdd" + "\xe8\x27\x74\xcb\x87\xcc\x3b\xbb" + "\x83\xce\x3d\xc9\x00\x11\x26\x77" + "\x2a\x2a\x92\xa1\x61\xda\x79\x7e" + "\xe8\x9c\x14\xf3\x02\x2b\x7a\x58" + "\x83\xec\x92\xde\x84\x13\x7e\x14" + + "\x30\x7f\x07\xaf\xd3\x83\x4c\x48" + "\x3a\xb5\x58\x06\x44\xf8\x78\xea" + "\x53\xec\x7a\x02\xc2\x76\x20\x91" + "\x7d\x17\xc8\x93\xe3\x14\x47\xf3" + "\x84\x6c\x37\xc2\x15\x5d\xef\x37" + "\x83\xa7\x1a\x3d\x59\xb6\x15\x83" + "\x90\x2a\x85\xef\x84\xc4\x75\x3a" + "\xd4\x6b\x08\x16\x8a\xc5\xa0\x0b" + + "\x48\x6d\x9a\x52\x7a\x8d\x68\x29" + "\x03\x92\xf1\xc2\x0d\x25\x7f\x9c" + "\xf9\x2d\x2e\x68\xfb\x42\x30\x12" + "\xbc\x21\x81\xad\xe7\x87\x75\x2b" + "\x65\x2a\x18\xe0\x33\x02\xfc\x30" + "\x8a\x12\xe1\xe3\x87\xcf\x2e\xb8" + "\x8f\x09\xfb\x93\x61\x28\x68\x71" + "\xa7\xe6\xe9\x85\xae\x21\x3e\x04" + + "\xea\x34\xc8\x66\xd6\x49\x5b\xab" + "\x87\x42\x41\x47\x18\x3e\xe4\x3b" + "\x47\x2a\x9a\x21\x59\xb8\x0f\xf4" + "\x3c\xdf\x58\xcc\xe9\x59\x65\x0e" + "\xb4\x15\x66\x0c\x8e\xfe\x1d\xfe" + "\x70\x9d\x45\x56\xfd\xc8\xab\x14" + "\x86\x03\xde\x05\x8e\xfa\xe0\x7b" + "\x7c\x5c\x03\xe9\x68\xef\x63\x8e" + + "\x91\x1e\xb3\x53\xb4\x01\x64\x11" + "\xd8\xb4\x36\x44\xd4\x7a\xba\x0c" + "\x66\xfd\x7a\x10\xa0\xf9\x51\x91" + "\xc4\xe4\x0e\x1f\xd0\xa8\xac\xaf" + "\x1c\x76\xe9\x9e\x1d\x5c\xfe\x75" + "\x8f\x58\xc0\xf0\x6b\xa1\x97\x34" + "\x4c\x80\x04\x03\xbd\xbe\xe2\x3e" + "\xb9\x90\xc9\xc2\x60\x9a\xfb\xa8" + + "\x14\x11\x25\x39\xfe\x32\x4d\xd1" + "\x66\x33\xc7\xca\xbc\x25\xbf\x36" + "\x5c\x49\xa7\xdb\x66\x2c\x56\xc9" + "\x8b\x34\xad\x46\x1b\x30\x4d\x32" + "\x7e\x40\x70\xd6\x0c\x62\x46\x9f" + "\x01\x3a\x73\xe3\xf1\xd4\xa8\x0e" + "\xe0\x24\xc3\xb0\x32\xd5\x96\xd3" + "\xcd\x17\xc3\x03\x0e\x1a\x21\x5b" + + "\x37\x7b\xfe\x5f\x20\x7d\x0d\x09" + "\xda\xd2\x47\x17\xfb\x3e\x7f\x3b" + "\x19\xc5\x4f\xb5\x5f\x52\xcb\xa2" + "\x1e\x97\x6a\xf6\x32\x09\x22\x6e" + "\x40\xd4\x86\xb4\xdf\x60\xc1\xdd" + "\x65\x34\xe1\x3f\x46\xec\xcf\x7f" + "\x51\xc1\xe4\x76\x4e\x7e\xda\x83" + "\xb5\x02\xd3\xd8\xa1\x48\xfa\xd6" + + "\x88\xcd\x72\x58\x26\x4f\x30\xc6" + "\xa1\x90\x8b\x27\x3c\x1d\x6c\x80" + "\x1c\xbc\xf0\xca\x25\xe7\x53\x35" + "\x5c\x8d\x9d\xbb\x03\xe6\x59\xff" + "\xdd\x85\x0b\x7a\x32\x0f\x55\xa4" + "\x17\xc2\xec\x93\x0a\x72\xc5\xde" + "\x13\x22\xd6\x69\x41\xb7\x88\x0b" + "\x55\x59\x36\x5b\x45\xf2\x12\x72" + + "\x87\xe7\xca\xb5\x11\x41\x76\x20" + "\x24\x31\xfd\x1d\x58\x7f\xcb\x13" + "\xfb\xae\x75\x11\xda\x77\xca\x2d" + "\x75\xe7\xaa\xff\x6b\x46\x75\xeb" + "\x32\xff\x6c\xdb\x3b\x6f\xd7\x74" + "\x9a\xda\xfc\x61\x7a\xf3\x40\x74" + "\x8b\x02\x25\xb5\x92\xac\xb3\x1b" + "\x29\x5f\x97\xa1\xf7\xf8\xfb\x20" + + "\x7f\x09\x83\xdf\xe1\x92\x26\x98" + "\x00\x08\x4b\x55\x6c\x8f\x73\x28" + "\x2f\x2f\xce\xa2\x17\x37\x70\xdc" + "\x94\x41\x81\x40\x3c\xb9\x13\x79" + "\x36\x96\xe8\x1f\x93\x45\x92\x04" + "\xa6\x34\x88\xf7\x3f\x44\x98\x7b" + "\xa1\xa5\x14\x51\x01\xab\xc6\x11" + "\x4c\x5f\xba\xff\x83\xb3\xde\x60" + + "\xe6\x82\xa9\x01\xc6\x54\xaa\x4c" + "\x26\xcd\x91\x34\x11\x5e\xd3\x1d" + "\x05\x6b\xbd\x7c\x5f\x31\x3c\x97" + "\x24\x47\x49\x52\x75\x07\xb0\xca" + "\x5a\xe1\x65\x65\x1f\x9b\x65\x04" + "\x26\xb0\x8f\x8c\x29\xf5\x30\xbf" + "\x37\xde\xa0\xa8\x1b\x64\x21\xfc" + "\x14\x51\x5e\xfa\x66\xa3\xc7\xe9" + + "\xd8\x3a\xf0\x52\xa5\x9c\x84\xdb" + "\xc0\x35\x4e\x02\xe9\xdb\xe8\xc7" + "\x89\xc7\xc3\xcf\xac\xbb\xa2\xa1" + "\x62\xf2\x26\x9c\x7d\x3e\x73\xbf" + "\x23\x48\x44\xb8\xf5\xfb\x2f\x88" + "\x3b\x48\xf8\x6b\x88\x4e\x22\xb7" + "\x40\xf6\xbe\x65\x8b\x3b\x02\x53" + "\xcd\xf8\xd5\xd4\x91\xec\xbf\xaa" + + "\xbd\xa1\x9e\x07\x10\x15\x0e\xa4" + "\x26\x5d\x5d\xd0\xdc\xad\xd9\x1a" + "\x4f\x8d\xe6\x13\xab\x2e\x3f\xdb" + "\x3f\x80\x0f\x64\xe2\x1a\xff\x1c" + "\x17\xe1\xce\xd4\x49\xb7\xe7\xe0" + "\x09\xd9\x36\x40\x5b\x27\x9f\x8e" + "\x38\x4c\x4d\x8f\x1d\xe3\x34\xce" + "\xfc\x30\x51\xd7\x69\x7f\xb3\x22" + + "\x04\x46\x01\xb4\xfd\xf1\xe0\x83" + "\x78\x50\x41\x89\x19\x99\xce\xa8" + "\xfe\x2e\x79\x41\x75\x5b\x37\x82" + "\x5b\x51\xd4\x97\x5c\xbf\x59\x4f" + "\x7d\x27\x3a\x92\x4f\x32\x4f\xac" + "\x06\x34\x0f\x65\x7d\x9b\xbc\xd9" + "\x51\xbc\x39\x8a\xd1\x87\xfa\xc6" + "\x8f\x10\xcc\x5c\x30\x85\x58\x82" + + "\x34\xc6\xe4\x82\x9f\x3c\xed\x5c" + "\xf8\x64\x44\x3a\x14\x83\xfb\x8e" + "\x25\xca\x1d\x7a\x1b\x38\x06\xe7" + "\x2b\x41\x2a\x5a\x3c\x5a\xd1\x6c" + "\xb5\x8f\xcd\xbf\xfd\xa8\x47\x93" + "\x22\xcd\x54\x6e\xef\x2e\xdb\x31" + "\x2f\x93\xd8\xf8\x1e\xb1\xae\xc4" + "\xaf\x11\x44\x34\xed\xc1\xe7\x11" diff --git a/src/crypto/elliptic/p256_asm_table_test.go b/src/crypto/elliptic/p256_asm_table_test.go index 6b64f26286..d704dae299 100644 --- a/src/crypto/elliptic/p256_asm_table_test.go +++ b/src/crypto/elliptic/p256_asm_table_test.go @@ -8,6 +8,7 @@ package elliptic import ( + "encoding/binary" "reflect" "testing" ) @@ -45,7 +46,12 @@ func TestP256PrecomputedTable(t *testing.T) { copy(t1[8:12], basePoint[8:12]) - if got, want := p256Precomputed[i][j*8:(j*8)+8], t1[:8]; !reflect.DeepEqual(got, want) { + buf := make([]byte, 8*8) + for i, u := range t1[:8] { + binary.LittleEndian.PutUint64(buf[i*8:i*8+8], u) + } + start := i*32*8*8 + j*8*8 + if got, want := p256Precomputed[start:start+64], string(buf); !reflect.DeepEqual(got, want) { t.Fatalf("Unexpected table entry at [%d][%d:%d]: got %v, want %v", i, j*8, (j*8)+8, got, want) } } -- GitLab From 13eccaa9902f3bb17999f1f7f14b7da39d60e0ea Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 26 Oct 2021 09:01:34 -0700 Subject: [PATCH 1757/2500] embed/internal/embedtest: use parenthesized vars for one test The gofrontend code mishandled this case, so add it to the test. Change-Id: I183b8fab57552320b04c4826c590b7c6d36b6548 Reviewed-on: https://go-review.googlesource.com/c/go/+/358836 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/embed/internal/embedtest/embed_test.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/embed/internal/embedtest/embed_test.go b/src/embed/internal/embedtest/embed_test.go index b41359f4c2..bfd94af69d 100644 --- a/src/embed/internal/embedtest/embed_test.go +++ b/src/embed/internal/embedtest/embed_test.go @@ -89,11 +89,13 @@ func TestDir(t *testing.T) { testDir(t, all, "testdata/i/j/k", "k8s.txt") } -//go:embed testdata -var testHiddenDir embed.FS +var ( + //go:embed testdata + testHiddenDir embed.FS -//go:embed testdata/* -var testHiddenStar embed.FS + //go:embed testdata/* + testHiddenStar embed.FS +) func TestHidden(t *testing.T) { dir := testHiddenDir -- GitLab From ca5f65d771bc24b9717dca615fa4ad25dcd94fad Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Mon, 25 Oct 2021 14:16:53 +0700 Subject: [PATCH 1758/2500] cmd/compile: fix generic type handling when crawling inline body For base generic type that is written to export file, we need to mark all of its methods, include exported+unexported methods, as reachable, so they can be available for instantiation if necessary. But markType only looks for exported methods, thus causing the crash in #49143. To fix this, we introduce new method p.markGeneric, to mark all methods of the base generic type. This issue has happend for a while (maybe since we add generic import/export during go1.18 cycle), and was un-intentionally "fixed" in CL 356254, when we agresssively call p.markEmbed(t). CL 357232 fixed that wrong agressive behavior, thus reproduce the bug on tip. Fixes #49143 Change-Id: Ie64574a05fffb282e9dcc8739df4378c5b6b0468 Reviewed-on: https://go-review.googlesource.com/c/go/+/358814 Trust: Cuong Manh Le Trust: Dan Scales Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Keith Randall Reviewed-by: Dan Scales --- src/cmd/compile/internal/typecheck/crawler.go | 33 +++++++++++++++---- test/fixedbugs/issue49143.dir/a.go | 24 ++++++++++++++ test/fixedbugs/issue49143.dir/b.go | 16 +++++++++ test/fixedbugs/issue49143.dir/c.go | 15 +++++++++ test/fixedbugs/issue49143.dir/p.go | 11 +++++++ test/fixedbugs/issue49143.go | 7 ++++ 6 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 test/fixedbugs/issue49143.dir/a.go create mode 100644 test/fixedbugs/issue49143.dir/b.go create mode 100644 test/fixedbugs/issue49143.dir/c.go create mode 100644 test/fixedbugs/issue49143.dir/p.go create mode 100644 test/fixedbugs/issue49143.go diff --git a/src/cmd/compile/internal/typecheck/crawler.go b/src/cmd/compile/internal/typecheck/crawler.go index e1489ceedd..ae2b3b1df4 100644 --- a/src/cmd/compile/internal/typecheck/crawler.go +++ b/src/cmd/compile/internal/typecheck/crawler.go @@ -20,6 +20,7 @@ func crawlExports(exports []*ir.Name) { p := crawler{ marked: make(map[*types.Type]bool), embedded: make(map[*types.Type]bool), + generic: make(map[*types.Type]bool), } for _, n := range exports { p.markObject(n) @@ -29,6 +30,7 @@ func crawlExports(exports []*ir.Name) { type crawler struct { marked map[*types.Type]bool // types already seen by markType embedded map[*types.Type]bool // types already seen by markEmbed + generic map[*types.Type]bool // types already seen by markGeneric } // markObject visits a reachable object (function, method, global type, or global variable) @@ -168,6 +170,30 @@ func (p *crawler) markEmbed(t *types.Type) { } } +// markGeneric takes an instantiated type or a base generic type t, and +// marks all the methods of the base generic type of t. If a base generic +// type is written to export file, even if not explicitly marked for export, +// all of its methods need to be available for instantiation if needed. +func (p *crawler) markGeneric(t *types.Type) { + if t.IsPtr() { + t = t.Elem() + } + if t.OrigSym() != nil { + // Convert to the base generic type. + t = t.OrigSym().Def.Type() + } + if p.generic[t] { + return + } + p.generic[t] = true + + if t.Sym() != nil && t.Kind() != types.TINTER { + for _, m := range t.Methods().Slice() { + p.markObject(m.Nname.(*ir.Name)) + } + } +} + // markInlBody marks n's inline body for export and recursively // ensures all called functions are marked too. func (p *crawler) markInlBody(n *ir.Name) { @@ -197,12 +223,7 @@ func (p *crawler) markInlBody(n *ir.Name) { t := n.Type() if t != nil { if t.HasTParam() || t.IsFullyInstantiated() { - // Ensure that we call markType() on any base generic type - // that is written to the export file (even if not explicitly - // marked for export), so we will call markInlBody on its - // methods, and the methods will be available for - // instantiation if needed. - p.markType(t) + p.markGeneric(t) } if base.Debug.Unified == 0 { // If a method of un-exported type is promoted and accessible by diff --git a/test/fixedbugs/issue49143.dir/a.go b/test/fixedbugs/issue49143.dir/a.go new file mode 100644 index 0000000000..5aefcd8780 --- /dev/null +++ b/test/fixedbugs/issue49143.dir/a.go @@ -0,0 +1,24 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +import "sync" + +type Loader[K comparable, R any] struct { + batch *LoaderBatch[K, R] +} + +func (l *Loader[K, R]) Load() error { + l.batch.f() + return nil +} + +type LoaderBatch[K comparable, R any] struct { + once *sync.Once +} + +func (b *LoaderBatch[K, R]) f() { + b.once.Do(func() {}) +} diff --git a/test/fixedbugs/issue49143.dir/b.go b/test/fixedbugs/issue49143.dir/b.go new file mode 100644 index 0000000000..48eecdbaaf --- /dev/null +++ b/test/fixedbugs/issue49143.dir/b.go @@ -0,0 +1,16 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package b + +import "./a" + + +type Loaders struct { + Loader *a.Loader[int, int] +} + +func NewLoaders() *Loaders { + return new(Loaders) +} diff --git a/test/fixedbugs/issue49143.dir/c.go b/test/fixedbugs/issue49143.dir/c.go new file mode 100644 index 0000000000..89262e374a --- /dev/null +++ b/test/fixedbugs/issue49143.dir/c.go @@ -0,0 +1,15 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package c + +import "./b" + +type Resolver struct{} + +type todoResolver struct{ *Resolver } + +func (r *todoResolver) F() { + b.NewLoaders().Loader.Load() +} diff --git a/test/fixedbugs/issue49143.dir/p.go b/test/fixedbugs/issue49143.dir/p.go new file mode 100644 index 0000000000..f11d2f22eb --- /dev/null +++ b/test/fixedbugs/issue49143.dir/p.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +import ( + "./c" +) + +var _ = &c.Resolver{} diff --git a/test/fixedbugs/issue49143.go b/test/fixedbugs/issue49143.go new file mode 100644 index 0000000000..87b4ff46c1 --- /dev/null +++ b/test/fixedbugs/issue49143.go @@ -0,0 +1,7 @@ +// compiledir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From 5786a54cfe34069c865fead1b6d9c9e3485a40a5 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Tue, 26 Oct 2021 09:13:16 +0200 Subject: [PATCH 1759/2500] syscall: use dup3 in forkAndExecInChild on NetBSD Use dup3(oldfd, newfd, O_CLOEXEC) to atomically duplicate the file descriptor and mark is as close-on-exec instead of dup2 & fcntl. The dup3 syscall was added in NetBSD 6.0. Change-Id: I01a4f8c62bfa8fb7f9f3166070380dd2002bb564 Reviewed-on: https://go-review.googlesource.com/c/go/+/358755 Trust: Tobias Klauser Trust: Benny Siegert Run-TryBot: Tobias Klauser Reviewed-by: Benny Siegert TryBot-Result: Go Bot --- src/syscall/exec_bsd.go | 33 ++++++++++++++++++++------- src/syscall/syscall_dragonfly.go | 2 ++ src/syscall/syscall_netbsd.go | 2 ++ src/syscall/syscall_openbsd_mips64.go | 2 ++ 4 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/syscall/exec_bsd.go b/src/syscall/exec_bsd.go index 4c36f9ec13..d2e50e3dd3 100644 --- a/src/syscall/exec_bsd.go +++ b/src/syscall/exec_bsd.go @@ -8,6 +8,7 @@ package syscall import ( + "runtime" "unsafe" ) @@ -181,11 +182,19 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr // Pass 1: look for fd[i] < i and move those up above len(fd) // so that pass 2 won't stomp on an fd it needs later. if pipe < nextfd { - _, _, err1 = RawSyscall(SYS_DUP2, uintptr(pipe), uintptr(nextfd), 0) - if err1 != 0 { - goto childerror + switch runtime.GOOS { + case "netbsd": + _, _, err1 = RawSyscall(_SYS_DUP3, uintptr(pipe), uintptr(nextfd), O_CLOEXEC) + if err1 != 0 { + goto childerror + } + default: + _, _, err1 = RawSyscall(SYS_DUP2, uintptr(pipe), uintptr(nextfd), 0) + if err1 != 0 { + goto childerror + } + RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC) } - RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC) pipe = nextfd nextfd++ } @@ -194,11 +203,19 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr if nextfd == pipe { // don't stomp on pipe nextfd++ } - _, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(nextfd), 0) - if err1 != 0 { - goto childerror + switch runtime.GOOS { + case "netbsd": + _, _, err1 = RawSyscall(_SYS_DUP3, uintptr(fd[i]), uintptr(nextfd), O_CLOEXEC) + if err1 != 0 { + goto childerror + } + default: + _, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(nextfd), 0) + if err1 != 0 { + goto childerror + } + RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC) } - RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC) fd[i] = nextfd nextfd++ } diff --git a/src/syscall/syscall_dragonfly.go b/src/syscall/syscall_dragonfly.go index 16adf306d5..cc92c4a93e 100644 --- a/src/syscall/syscall_dragonfly.go +++ b/src/syscall/syscall_dragonfly.go @@ -17,6 +17,8 @@ import ( "unsafe" ) +const _SYS_DUP3 = 0 + // See version list in https://github.com/DragonFlyBSD/DragonFlyBSD/blob/master/sys/sys/param.h var ( osreldateOnce sync.Once diff --git a/src/syscall/syscall_netbsd.go b/src/syscall/syscall_netbsd.go index 6f05b0d43d..cebef10be8 100644 --- a/src/syscall/syscall_netbsd.go +++ b/src/syscall/syscall_netbsd.go @@ -14,6 +14,8 @@ package syscall import "unsafe" +const _SYS_DUP3 = SYS_DUP3 + type SockaddrDatalink struct { Len uint8 Family uint8 diff --git a/src/syscall/syscall_openbsd_mips64.go b/src/syscall/syscall_openbsd_mips64.go index b259dc6975..e8ae2e9911 100644 --- a/src/syscall/syscall_openbsd_mips64.go +++ b/src/syscall/syscall_openbsd_mips64.go @@ -4,6 +4,8 @@ package syscall +const _SYS_DUP3 = 0 + func setTimespec(sec, nsec int64) Timespec { return Timespec{Sec: sec, Nsec: nsec} } -- GitLab From bdefb77309fdc6e47102a8d6272fd2293aefa1d9 Mon Sep 17 00:00:00 2001 From: Andy Pan Date: Tue, 26 Oct 2021 09:15:17 +0800 Subject: [PATCH 1760/2500] internal/poll: improve the padding calculation inside struct splicePipe Updates #48968 and CL 358114 Change-Id: Ic68b4c5420c1c32f78b56874b53d717fa9af1f74 Reviewed-on: https://go-review.googlesource.com/c/go/+/358734 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Tobias Klauser --- src/internal/poll/splice_linux.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/internal/poll/splice_linux.go b/src/internal/poll/splice_linux.go index 6869a40b24..2d87c3d023 100644 --- a/src/internal/poll/splice_linux.go +++ b/src/internal/poll/splice_linux.go @@ -154,14 +154,18 @@ func splice(out int, in int, max int, flags int) (int, error) { return int(n), err } -type splicePipe struct { +type splicePipeFields struct { rfd int wfd int data int +} + +type splicePipe struct { + splicePipeFields // We want to use a finalizer, so ensure that the size is // large enough to not use the tiny allocator. - _ [24 - 3*unsafe.Sizeof(int(0))]byte + _ [24 - unsafe.Sizeof(splicePipeFields{})%24]byte } // splicePipePool caches pipes to avoid high-frequency construction and destruction of pipe buffers. @@ -222,7 +226,7 @@ func newPipe() (sp *splicePipe) { return nil } - sp = &splicePipe{rfd: fds[0], wfd: fds[1]} + sp = &splicePipe{splicePipeFields: splicePipeFields{rfd: fds[0], wfd: fds[1]}} if p == nil { p = new(bool) -- GitLab From cfb532158fc5b5cd6b9c35bbc2ff7c203fe5f09b Mon Sep 17 00:00:00 2001 From: Cholerae Hu Date: Wed, 27 Oct 2021 11:41:47 +0800 Subject: [PATCH 1761/2500] cmd/go: add darwin/arm64 in the list of supported systems in help message Fixes #49173. Change-Id: I71270b4ff7e9ede3cdfa5946b73142a731752adf Reviewed-on: https://go-review.googlesource.com/c/go/+/358901 Reviewed-by: Alberto Donizetti Reviewed-by: Keith Randall Trust: Alberto Donizetti Run-TryBot: Alberto Donizetti TryBot-Result: Go Bot --- src/cmd/go/alldocs.go | 2 +- src/cmd/go/internal/work/build.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 8178073103..9d8c321307 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -114,7 +114,7 @@ // The default is GOMAXPROCS, normally the number of CPUs available. // -race // enable data race detection. -// Supported only on linux/amd64, freebsd/amd64, darwin/amd64, windows/amd64, +// Supported only on linux/amd64, freebsd/amd64, darwin/amd64, darwin/arm64, windows/amd64, // linux/ppc64le and linux/arm64 (only for 48-bit VMA). // -msan // enable interoperation with memory sanitizer. diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go index ffe33bfa4d..9d0ad27f0d 100644 --- a/src/cmd/go/internal/work/build.go +++ b/src/cmd/go/internal/work/build.go @@ -68,7 +68,7 @@ and test commands: The default is GOMAXPROCS, normally the number of CPUs available. -race enable data race detection. - Supported only on linux/amd64, freebsd/amd64, darwin/amd64, windows/amd64, + Supported only on linux/amd64, freebsd/amd64, darwin/amd64, darwin/arm64, windows/amd64, linux/ppc64le and linux/arm64 (only for 48-bit VMA). -msan enable interoperation with memory sanitizer. -- GitLab From 4f73fd05a91a9b8ceced6b7f89d35f363c414ec8 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 11 Oct 2021 11:57:24 -0400 Subject: [PATCH 1762/2500] cmd: move internal/str back to cmd/go cmd/go is not subject to all the same restrictions as most of cmd. In particular it need not be buildable with the bootstrap toolchain. So it is better to keep as little code shared between cmd/go and cmd/compile, cmd/link, cmd/cgo as possible. cmd/internal/str started as cmd/go/internal/str but was moved to cmd/internal in order to make use of the quoted string code. Move that code to cmd/internal/quoted and then move the rest of cmd/internal/str back to cmd/go/internal/str. Change-Id: I3a98f754d545cc3af7e9a32c2b77a5a035ea7b9a Reviewed-on: https://go-review.googlesource.com/c/go/+/355010 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/cgo/gcc.go | 4 +- .../compile/internal/ssa/stmtlines_test.go | 4 +- src/cmd/dist/buildtool.go | 2 +- src/cmd/go/internal/base/base.go | 2 +- src/cmd/go/internal/base/flag.go | 4 +- src/cmd/go/internal/envcmd/env.go | 4 +- src/cmd/go/internal/fix/fix.go | 2 +- src/cmd/go/internal/generate/generate.go | 2 +- src/cmd/go/internal/get/get.go | 2 +- src/cmd/go/internal/list/list.go | 2 +- src/cmd/go/internal/load/flag.go | 4 +- src/cmd/go/internal/load/pkg.go | 2 +- src/cmd/go/internal/load/test.go | 2 +- src/cmd/go/internal/modcmd/vendor.go | 2 +- .../go/internal/modfetch/codehost/codehost.go | 2 +- src/cmd/go/internal/modfetch/codehost/vcs.go | 2 +- src/cmd/go/internal/modget/query.go | 2 +- src/cmd/go/internal/modload/load.go | 2 +- src/cmd/go/internal/modload/query.go | 2 +- src/cmd/go/internal/run/run.go | 2 +- src/cmd/{ => go}/internal/str/path.go | 0 src/cmd/go/internal/str/str.go | 111 +++++++++ src/cmd/go/internal/str/str_test.go | 29 +++ src/cmd/go/internal/test/test.go | 2 +- src/cmd/go/internal/vcs/vcs.go | 2 +- src/cmd/go/internal/work/buildid.go | 2 +- src/cmd/go/internal/work/exec.go | 5 +- src/cmd/go/internal/work/gc.go | 5 +- src/cmd/go/internal/work/gccgo.go | 2 +- src/cmd/go/internal/work/init.go | 4 +- src/cmd/internal/quoted/quoted.go | 127 ++++++++++ .../str_test.go => quoted/quoted_test.go} | 30 +-- src/cmd/internal/str/str.go | 227 ------------------ src/cmd/link/dwarf_test.go | 4 +- src/cmd/link/internal/ld/main.go | 6 +- 35 files changed, 314 insertions(+), 292 deletions(-) rename src/cmd/{ => go}/internal/str/path.go (100%) create mode 100644 src/cmd/go/internal/str/str.go create mode 100644 src/cmd/go/internal/str/str_test.go create mode 100644 src/cmd/internal/quoted/quoted.go rename src/cmd/internal/{str/str_test.go => quoted/quoted_test.go} (79%) delete mode 100644 src/cmd/internal/str/str.go diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index c78197896c..997a830994 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -29,7 +29,7 @@ import ( "unicode" "unicode/utf8" - "cmd/internal/str" + "cmd/internal/quoted" ) var debugDefine = flag.Bool("debug-define", false, "print relevant #defines") @@ -1568,7 +1568,7 @@ func checkGCCBaseCmd() ([]string, error) { if value == "" { value = defaultCC(goos, goarch) } - args, err := str.SplitQuotedFields(value) + args, err := quoted.Split(value) if err != nil { return nil, err } diff --git a/src/cmd/compile/internal/ssa/stmtlines_test.go b/src/cmd/compile/internal/ssa/stmtlines_test.go index 843db8c07e..90dd261c55 100644 --- a/src/cmd/compile/internal/ssa/stmtlines_test.go +++ b/src/cmd/compile/internal/ssa/stmtlines_test.go @@ -2,7 +2,7 @@ package ssa_test import ( cmddwarf "cmd/internal/dwarf" - "cmd/internal/str" + "cmd/internal/quoted" "debug/dwarf" "debug/elf" "debug/macho" @@ -58,7 +58,7 @@ func TestStmtLines(t *testing.T) { if extld == "" { extld = "gcc" } - extldArgs, err := str.SplitQuotedFields(extld) + extldArgs, err := quoted.Split(extld) if err != nil { t.Fatal(err) } diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go index 320c62f850..75f04a975c 100644 --- a/src/cmd/dist/buildtool.go +++ b/src/cmd/dist/buildtool.go @@ -46,8 +46,8 @@ var bootstrapDirs = []string{ "cmd/internal/obj/...", "cmd/internal/objabi", "cmd/internal/pkgpath", + "cmd/internal/quoted", "cmd/internal/src", - "cmd/internal/str", "cmd/internal/sys", "cmd/link", "cmd/link/internal/...", diff --git a/src/cmd/go/internal/base/base.go b/src/cmd/go/internal/base/base.go index 0144525e30..954ce47a98 100644 --- a/src/cmd/go/internal/base/base.go +++ b/src/cmd/go/internal/base/base.go @@ -17,7 +17,7 @@ import ( "sync" "cmd/go/internal/cfg" - "cmd/internal/str" + "cmd/go/internal/str" ) // A Command is an implementation of a go command diff --git a/src/cmd/go/internal/base/flag.go b/src/cmd/go/internal/base/flag.go index 7e5121bffb..2c72c7e562 100644 --- a/src/cmd/go/internal/base/flag.go +++ b/src/cmd/go/internal/base/flag.go @@ -9,7 +9,7 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/fsys" - "cmd/internal/str" + "cmd/internal/quoted" ) // A StringsFlag is a command-line flag that interprets its argument @@ -18,7 +18,7 @@ type StringsFlag []string func (v *StringsFlag) Set(s string) error { var err error - *v, err = str.SplitQuotedFields(s) + *v, err = quoted.Split(s) if *v == nil { *v = []string{} } diff --git a/src/cmd/go/internal/envcmd/env.go b/src/cmd/go/internal/envcmd/env.go index 181d2a2ca1..e56dd8223f 100644 --- a/src/cmd/go/internal/envcmd/env.go +++ b/src/cmd/go/internal/envcmd/env.go @@ -26,7 +26,7 @@ import ( "cmd/go/internal/load" "cmd/go/internal/modload" "cmd/go/internal/work" - "cmd/internal/str" + "cmd/internal/quoted" ) var CmdEnv = &base.Command{ @@ -470,7 +470,7 @@ func checkEnvWrite(key, val string) error { if val == "" { break } - args, err := str.SplitQuotedFields(val) + args, err := quoted.Split(val) if err != nil { return fmt.Errorf("invalid %s: %v", key, err) } diff --git a/src/cmd/go/internal/fix/fix.go b/src/cmd/go/internal/fix/fix.go index cc5940fccd..988d45e71c 100644 --- a/src/cmd/go/internal/fix/fix.go +++ b/src/cmd/go/internal/fix/fix.go @@ -10,7 +10,7 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/load" "cmd/go/internal/modload" - "cmd/internal/str" + "cmd/go/internal/str" "context" "fmt" "os" diff --git a/src/cmd/go/internal/generate/generate.go b/src/cmd/go/internal/generate/generate.go index 5981e5ecdb..a3873d1138 100644 --- a/src/cmd/go/internal/generate/generate.go +++ b/src/cmd/go/internal/generate/generate.go @@ -26,7 +26,7 @@ import ( "cmd/go/internal/load" "cmd/go/internal/modload" "cmd/go/internal/work" - "cmd/internal/str" + "cmd/go/internal/str" ) var CmdGenerate = &base.Command{ diff --git a/src/cmd/go/internal/get/get.go b/src/cmd/go/internal/get/get.go index 0412506b9e..f46313dcff 100644 --- a/src/cmd/go/internal/get/get.go +++ b/src/cmd/go/internal/get/get.go @@ -20,7 +20,7 @@ import ( "cmd/go/internal/vcs" "cmd/go/internal/web" "cmd/go/internal/work" - "cmd/internal/str" + "cmd/go/internal/str" "golang.org/x/mod/module" ) diff --git a/src/cmd/go/internal/list/list.go b/src/cmd/go/internal/list/list.go index 821e622abb..8c85ddcf21 100644 --- a/src/cmd/go/internal/list/list.go +++ b/src/cmd/go/internal/list/list.go @@ -24,7 +24,7 @@ import ( "cmd/go/internal/modinfo" "cmd/go/internal/modload" "cmd/go/internal/work" - "cmd/internal/str" + "cmd/go/internal/str" ) var CmdList = &base.Command{ diff --git a/src/cmd/go/internal/load/flag.go b/src/cmd/go/internal/load/flag.go index d0d5716c3f..de079decdf 100644 --- a/src/cmd/go/internal/load/flag.go +++ b/src/cmd/go/internal/load/flag.go @@ -6,7 +6,7 @@ package load import ( "cmd/go/internal/base" - "cmd/internal/str" + "cmd/internal/quoted" "fmt" "strings" ) @@ -63,7 +63,7 @@ func (f *PerPackageFlag) set(v, cwd string) error { match = MatchPackage(pattern, cwd) v = v[i+1:] } - flags, err := str.SplitQuotedFields(v) + flags, err := quoted.Split(v) if err != nil { return err } diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index dfe7849516..c6c5fb00a8 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -38,9 +38,9 @@ import ( "cmd/go/internal/modload" "cmd/go/internal/par" "cmd/go/internal/search" + "cmd/go/internal/str" "cmd/go/internal/trace" "cmd/go/internal/vcs" - "cmd/internal/str" "cmd/internal/sys" "golang.org/x/mod/modfile" diff --git a/src/cmd/go/internal/load/test.go b/src/cmd/go/internal/load/test.go index 4cefb62d51..8a18dfbe93 100644 --- a/src/cmd/go/internal/load/test.go +++ b/src/cmd/go/internal/load/test.go @@ -23,7 +23,7 @@ import ( "cmd/go/internal/fsys" "cmd/go/internal/trace" - "cmd/internal/str" + "cmd/go/internal/str" ) var TestMainDeps = []string{ diff --git a/src/cmd/go/internal/modcmd/vendor.go b/src/cmd/go/internal/modcmd/vendor.go index 57189b4607..484e095cc7 100644 --- a/src/cmd/go/internal/modcmd/vendor.go +++ b/src/cmd/go/internal/modcmd/vendor.go @@ -24,7 +24,7 @@ import ( "cmd/go/internal/imports" "cmd/go/internal/load" "cmd/go/internal/modload" - "cmd/internal/str" + "cmd/go/internal/str" "golang.org/x/mod/module" "golang.org/x/mod/semver" diff --git a/src/cmd/go/internal/modfetch/codehost/codehost.go b/src/cmd/go/internal/modfetch/codehost/codehost.go index efb4b1516a..378fbae34f 100644 --- a/src/cmd/go/internal/modfetch/codehost/codehost.go +++ b/src/cmd/go/internal/modfetch/codehost/codehost.go @@ -21,7 +21,7 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/lockedfile" - "cmd/internal/str" + "cmd/go/internal/str" ) // Downloaded size limits. diff --git a/src/cmd/go/internal/modfetch/codehost/vcs.go b/src/cmd/go/internal/modfetch/codehost/vcs.go index 5d810d2621..c2cca084e3 100644 --- a/src/cmd/go/internal/modfetch/codehost/vcs.go +++ b/src/cmd/go/internal/modfetch/codehost/vcs.go @@ -20,7 +20,7 @@ import ( "cmd/go/internal/lockedfile" "cmd/go/internal/par" - "cmd/internal/str" + "cmd/go/internal/str" ) // A VCSError indicates an error using a version control system. diff --git a/src/cmd/go/internal/modget/query.go b/src/cmd/go/internal/modget/query.go index d7341e7813..887cb51b31 100644 --- a/src/cmd/go/internal/modget/query.go +++ b/src/cmd/go/internal/modget/query.go @@ -14,7 +14,7 @@ import ( "cmd/go/internal/base" "cmd/go/internal/modload" "cmd/go/internal/search" - "cmd/internal/str" + "cmd/go/internal/str" "golang.org/x/mod/module" ) diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index 0f5b015000..845bf2f8a2 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -119,7 +119,7 @@ import ( "cmd/go/internal/mvs" "cmd/go/internal/par" "cmd/go/internal/search" - "cmd/internal/str" + "cmd/go/internal/str" "golang.org/x/mod/module" "golang.org/x/mod/semver" diff --git a/src/cmd/go/internal/modload/query.go b/src/cmd/go/internal/modload/query.go index c9ed129dbf..1eb484de9d 100644 --- a/src/cmd/go/internal/modload/query.go +++ b/src/cmd/go/internal/modload/query.go @@ -22,7 +22,7 @@ import ( "cmd/go/internal/modfetch" "cmd/go/internal/search" "cmd/go/internal/trace" - "cmd/internal/str" + "cmd/go/internal/str" "golang.org/x/mod/module" "golang.org/x/mod/semver" diff --git a/src/cmd/go/internal/run/run.go b/src/cmd/go/internal/run/run.go index 11e2c81b9a..03895d27eb 100644 --- a/src/cmd/go/internal/run/run.go +++ b/src/cmd/go/internal/run/run.go @@ -19,7 +19,7 @@ import ( "cmd/go/internal/load" "cmd/go/internal/modload" "cmd/go/internal/work" - "cmd/internal/str" + "cmd/go/internal/str" ) var CmdRun = &base.Command{ diff --git a/src/cmd/internal/str/path.go b/src/cmd/go/internal/str/path.go similarity index 100% rename from src/cmd/internal/str/path.go rename to src/cmd/go/internal/str/path.go diff --git a/src/cmd/go/internal/str/str.go b/src/cmd/go/internal/str/str.go new file mode 100644 index 0000000000..5bc521b9df --- /dev/null +++ b/src/cmd/go/internal/str/str.go @@ -0,0 +1,111 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package str provides string manipulation utilities. +package str + +import ( + "bytes" + "fmt" + "unicode" + "unicode/utf8" +) + +// StringList flattens its arguments into a single []string. +// Each argument in args must have type string or []string. +func StringList(args ...interface{}) []string { + var x []string + for _, arg := range args { + switch arg := arg.(type) { + case []string: + x = append(x, arg...) + case string: + x = append(x, arg) + default: + panic("stringList: invalid argument of type " + fmt.Sprintf("%T", arg)) + } + } + return x +} + +// ToFold returns a string with the property that +// strings.EqualFold(s, t) iff ToFold(s) == ToFold(t) +// This lets us test a large set of strings for fold-equivalent +// duplicates without making a quadratic number of calls +// to EqualFold. Note that strings.ToUpper and strings.ToLower +// do not have the desired property in some corner cases. +func ToFold(s string) string { + // Fast path: all ASCII, no upper case. + // Most paths look like this already. + for i := 0; i < len(s); i++ { + c := s[i] + if c >= utf8.RuneSelf || 'A' <= c && c <= 'Z' { + goto Slow + } + } + return s + +Slow: + var buf bytes.Buffer + for _, r := range s { + // SimpleFold(x) cycles to the next equivalent rune > x + // or wraps around to smaller values. Iterate until it wraps, + // and we've found the minimum value. + for { + r0 := r + r = unicode.SimpleFold(r0) + if r <= r0 { + break + } + } + // Exception to allow fast path above: A-Z => a-z + if 'A' <= r && r <= 'Z' { + r += 'a' - 'A' + } + buf.WriteRune(r) + } + return buf.String() +} + +// FoldDup reports a pair of strings from the list that are +// equal according to strings.EqualFold. +// It returns "", "" if there are no such strings. +func FoldDup(list []string) (string, string) { + clash := map[string]string{} + for _, s := range list { + fold := ToFold(s) + if t := clash[fold]; t != "" { + if s > t { + s, t = t, s + } + return s, t + } + clash[fold] = s + } + return "", "" +} + +// Contains reports whether x contains s. +func Contains(x []string, s string) bool { + for _, t := range x { + if t == s { + return true + } + } + return false +} + +// Uniq removes consecutive duplicate strings from ss. +func Uniq(ss *[]string) { + if len(*ss) <= 1 { + return + } + uniq := (*ss)[:1] + for _, s := range *ss { + if s != uniq[len(uniq)-1] { + uniq = append(uniq, s) + } + } + *ss = uniq +} diff --git a/src/cmd/go/internal/str/str_test.go b/src/cmd/go/internal/str/str_test.go new file mode 100644 index 0000000000..8ea758e0a8 --- /dev/null +++ b/src/cmd/go/internal/str/str_test.go @@ -0,0 +1,29 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package str + +import ( + "testing" +) + +var foldDupTests = []struct { + list []string + f1, f2 string +}{ + {StringList("math/rand", "math/big"), "", ""}, + {StringList("math", "strings"), "", ""}, + {StringList("strings"), "", ""}, + {StringList("strings", "strings"), "strings", "strings"}, + {StringList("Rand", "rand", "math", "math/rand", "math/Rand"), "Rand", "rand"}, +} + +func TestFoldDup(t *testing.T) { + for _, tt := range foldDupTests { + f1, f2 := FoldDup(tt.list) + if f1 != tt.f1 || f2 != tt.f2 { + t.Errorf("foldDup(%q) = %q, %q, want %q, %q", tt.list, f1, f2, tt.f1, tt.f2) + } + } +} diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index dc1bea505b..ea1d4ff20e 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -33,7 +33,7 @@ import ( "cmd/go/internal/search" "cmd/go/internal/trace" "cmd/go/internal/work" - "cmd/internal/str" + "cmd/go/internal/str" "cmd/internal/test2json" ) diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go index 941bd57147..c4853d7ae3 100644 --- a/src/cmd/go/internal/vcs/vcs.go +++ b/src/cmd/go/internal/vcs/vcs.go @@ -27,7 +27,7 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/search" "cmd/go/internal/web" - "cmd/internal/str" + "cmd/go/internal/str" "golang.org/x/mod/module" ) diff --git a/src/cmd/go/internal/work/buildid.go b/src/cmd/go/internal/work/buildid.go index 15f944d2af..d4f2a716d7 100644 --- a/src/cmd/go/internal/work/buildid.go +++ b/src/cmd/go/internal/work/buildid.go @@ -16,7 +16,7 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/fsys" "cmd/internal/buildid" - "cmd/internal/str" + "cmd/go/internal/str" ) // Build IDs diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index 62d8143828..03f8866cf2 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -34,8 +34,9 @@ import ( "cmd/go/internal/fsys" "cmd/go/internal/load" "cmd/go/internal/modload" + "cmd/go/internal/str" "cmd/go/internal/trace" - "cmd/internal/str" + "cmd/internal/quoted" "cmd/internal/sys" ) @@ -2666,7 +2667,7 @@ func envList(key, def string) []string { if v == "" { v = def } - args, err := str.SplitQuotedFields(v) + args, err := quoted.Split(v) if err != nil { panic(fmt.Sprintf("could not parse environment variable %s with value %q: %v", key, v, err)) } diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go index 3eb9b35f40..e3b4a817e7 100644 --- a/src/cmd/go/internal/work/gc.go +++ b/src/cmd/go/internal/work/gc.go @@ -20,8 +20,9 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/fsys" "cmd/go/internal/load" + "cmd/go/internal/str" "cmd/internal/objabi" - "cmd/internal/str" + "cmd/internal/quoted" "cmd/internal/sys" "crypto/sha1" ) @@ -565,7 +566,7 @@ func setextld(ldflags []string, compiler []string) ([]string, error) { return ldflags, nil } } - joined, err := str.JoinAndQuoteFields(compiler) + joined, err := quoted.Join(compiler) if err != nil { return nil, err } diff --git a/src/cmd/go/internal/work/gccgo.go b/src/cmd/go/internal/work/gccgo.go index 3cb7b64183..60181b99e4 100644 --- a/src/cmd/go/internal/work/gccgo.go +++ b/src/cmd/go/internal/work/gccgo.go @@ -17,7 +17,7 @@ import ( "cmd/go/internal/fsys" "cmd/go/internal/load" "cmd/internal/pkgpath" - "cmd/internal/str" + "cmd/go/internal/str" ) // The Gccgo toolchain. diff --git a/src/cmd/go/internal/work/init.go b/src/cmd/go/internal/work/init.go index 56e39f8c52..4dbbd2a13f 100644 --- a/src/cmd/go/internal/work/init.go +++ b/src/cmd/go/internal/work/init.go @@ -11,7 +11,7 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/fsys" "cmd/go/internal/modload" - "cmd/internal/str" + "cmd/internal/quoted" "cmd/internal/sys" "fmt" "os" @@ -46,7 +46,7 @@ func BuildInit() { // Make sure CC, CXX, and FC are absolute paths. for _, key := range []string{"CC", "CXX", "FC"} { value := cfg.Getenv(key) - args, err := str.SplitQuotedFields(value) + args, err := quoted.Split(value) if err != nil { base.Fatalf("go: %s environment variable could not be parsed: %v", key, err) } diff --git a/src/cmd/internal/quoted/quoted.go b/src/cmd/internal/quoted/quoted.go new file mode 100644 index 0000000000..e7575dfc66 --- /dev/null +++ b/src/cmd/internal/quoted/quoted.go @@ -0,0 +1,127 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package quoted provides string manipulation utilities. +package quoted + +import ( + "flag" + "fmt" + "strings" + "unicode" +) + +func isSpaceByte(c byte) bool { + return c == ' ' || c == '\t' || c == '\n' || c == '\r' +} + +// Split splits s into a list of fields, +// allowing single or double quotes around elements. +// There is no unescaping or other processing within +// quoted fields. +func Split(s string) ([]string, error) { + // Split fields allowing '' or "" around elements. + // Quotes further inside the string do not count. + var f []string + for len(s) > 0 { + for len(s) > 0 && isSpaceByte(s[0]) { + s = s[1:] + } + if len(s) == 0 { + break + } + // Accepted quoted string. No unescaping inside. + if s[0] == '"' || s[0] == '\'' { + quote := s[0] + s = s[1:] + i := 0 + for i < len(s) && s[i] != quote { + i++ + } + if i >= len(s) { + return nil, fmt.Errorf("unterminated %c string", quote) + } + f = append(f, s[:i]) + s = s[i+1:] + continue + } + i := 0 + for i < len(s) && !isSpaceByte(s[i]) { + i++ + } + f = append(f, s[:i]) + s = s[i:] + } + return f, nil +} + +// Join joins a list of arguments into a string that can be parsed +// with Split. Arguments are quoted only if necessary; arguments +// without spaces or quotes are kept as-is. No argument may contain both +// single and double quotes. +func Join(args []string) (string, error) { + var buf []byte + for i, arg := range args { + if i > 0 { + buf = append(buf, ' ') + } + var sawSpace, sawSingleQuote, sawDoubleQuote bool + for _, c := range arg { + switch { + case c > unicode.MaxASCII: + continue + case isSpaceByte(byte(c)): + sawSpace = true + case c == '\'': + sawSingleQuote = true + case c == '"': + sawDoubleQuote = true + } + } + switch { + case !sawSpace && !sawSingleQuote && !sawDoubleQuote: + buf = append(buf, []byte(arg)...) + + case !sawSingleQuote: + buf = append(buf, '\'') + buf = append(buf, []byte(arg)...) + buf = append(buf, '\'') + + case !sawDoubleQuote: + buf = append(buf, '"') + buf = append(buf, []byte(arg)...) + buf = append(buf, '"') + + default: + return "", fmt.Errorf("argument %q contains both single and double quotes and cannot be quoted", arg) + } + } + return string(buf), nil +} + +// A Flag parses a list of string arguments encoded with Join. +// It is useful for flags like cmd/link's -extldflags. +type Flag []string + +var _ flag.Value = (*Flag)(nil) + +func (f *Flag) Set(v string) error { + fs, err := Split(v) + if err != nil { + return err + } + *f = fs[:len(fs):len(fs)] + return nil +} + +func (f *Flag) String() string { + if f == nil { + return "" + } + s, err := Join(*f) + if err != nil { + return strings.Join(*f, " ") + } + return s +} diff --git a/src/cmd/internal/str/str_test.go b/src/cmd/internal/quoted/quoted_test.go similarity index 79% rename from src/cmd/internal/str/str_test.go rename to src/cmd/internal/quoted/quoted_test.go index 3609af6a06..d76270c87b 100644 --- a/src/cmd/internal/str/str_test.go +++ b/src/cmd/internal/quoted/quoted_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package str +package quoted import ( "reflect" @@ -10,27 +10,7 @@ import ( "testing" ) -var foldDupTests = []struct { - list []string - f1, f2 string -}{ - {StringList("math/rand", "math/big"), "", ""}, - {StringList("math", "strings"), "", ""}, - {StringList("strings"), "", ""}, - {StringList("strings", "strings"), "strings", "strings"}, - {StringList("Rand", "rand", "math", "math/rand", "math/Rand"), "Rand", "rand"}, -} - -func TestFoldDup(t *testing.T) { - for _, tt := range foldDupTests { - f1, f2 := FoldDup(tt.list) - if f1 != tt.f1 || f2 != tt.f2 { - t.Errorf("foldDup(%q) = %q, %q, want %q, %q", tt.list, f1, f2, tt.f1, tt.f2) - } - } -} - -func TestSplitQuotedFields(t *testing.T) { +func TestSplit(t *testing.T) { for _, test := range []struct { name string value string @@ -54,7 +34,7 @@ func TestSplitQuotedFields(t *testing.T) { {name: "quote_unclosed", value: `'a`, wantErr: "unterminated ' string"}, } { t.Run(test.name, func(t *testing.T) { - got, err := SplitQuotedFields(test.value) + got, err := Split(test.value) if err != nil { if test.wantErr == "" { t.Fatalf("unexpected error: %v", err) @@ -73,7 +53,7 @@ func TestSplitQuotedFields(t *testing.T) { } } -func TestJoinAndQuoteFields(t *testing.T) { +func TestJoin(t *testing.T) { for _, test := range []struct { name string args []string @@ -88,7 +68,7 @@ func TestJoinAndQuoteFields(t *testing.T) { {name: "unquoteable", args: []string{`'"`}, wantErr: "contains both single and double quotes and cannot be quoted"}, } { t.Run(test.name, func(t *testing.T) { - got, err := JoinAndQuoteFields(test.args) + got, err := Join(test.args) if err != nil { if test.wantErr == "" { t.Fatalf("unexpected error: %v", err) diff --git a/src/cmd/internal/str/str.go b/src/cmd/internal/str/str.go deleted file mode 100644 index 409cf8f7b4..0000000000 --- a/src/cmd/internal/str/str.go +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package str provides string manipulation utilities. -package str - -import ( - "bytes" - "flag" - "fmt" - "strings" - "unicode" - "unicode/utf8" -) - -// StringList flattens its arguments into a single []string. -// Each argument in args must have type string or []string. -func StringList(args ...interface{}) []string { - var x []string - for _, arg := range args { - switch arg := arg.(type) { - case []string: - x = append(x, arg...) - case string: - x = append(x, arg) - default: - panic("stringList: invalid argument of type " + fmt.Sprintf("%T", arg)) - } - } - return x -} - -// ToFold returns a string with the property that -// strings.EqualFold(s, t) iff ToFold(s) == ToFold(t) -// This lets us test a large set of strings for fold-equivalent -// duplicates without making a quadratic number of calls -// to EqualFold. Note that strings.ToUpper and strings.ToLower -// do not have the desired property in some corner cases. -func ToFold(s string) string { - // Fast path: all ASCII, no upper case. - // Most paths look like this already. - for i := 0; i < len(s); i++ { - c := s[i] - if c >= utf8.RuneSelf || 'A' <= c && c <= 'Z' { - goto Slow - } - } - return s - -Slow: - var buf bytes.Buffer - for _, r := range s { - // SimpleFold(x) cycles to the next equivalent rune > x - // or wraps around to smaller values. Iterate until it wraps, - // and we've found the minimum value. - for { - r0 := r - r = unicode.SimpleFold(r0) - if r <= r0 { - break - } - } - // Exception to allow fast path above: A-Z => a-z - if 'A' <= r && r <= 'Z' { - r += 'a' - 'A' - } - buf.WriteRune(r) - } - return buf.String() -} - -// FoldDup reports a pair of strings from the list that are -// equal according to strings.EqualFold. -// It returns "", "" if there are no such strings. -func FoldDup(list []string) (string, string) { - clash := map[string]string{} - for _, s := range list { - fold := ToFold(s) - if t := clash[fold]; t != "" { - if s > t { - s, t = t, s - } - return s, t - } - clash[fold] = s - } - return "", "" -} - -// Contains reports whether x contains s. -func Contains(x []string, s string) bool { - for _, t := range x { - if t == s { - return true - } - } - return false -} - -// Uniq removes consecutive duplicate strings from ss. -func Uniq(ss *[]string) { - if len(*ss) <= 1 { - return - } - uniq := (*ss)[:1] - for _, s := range *ss { - if s != uniq[len(uniq)-1] { - uniq = append(uniq, s) - } - } - *ss = uniq -} - -func isSpaceByte(c byte) bool { - return c == ' ' || c == '\t' || c == '\n' || c == '\r' -} - -// SplitQuotedFields splits s into a list of fields, -// allowing single or double quotes around elements. -// There is no unescaping or other processing within -// quoted fields. -func SplitQuotedFields(s string) ([]string, error) { - // Split fields allowing '' or "" around elements. - // Quotes further inside the string do not count. - var f []string - for len(s) > 0 { - for len(s) > 0 && isSpaceByte(s[0]) { - s = s[1:] - } - if len(s) == 0 { - break - } - // Accepted quoted string. No unescaping inside. - if s[0] == '"' || s[0] == '\'' { - quote := s[0] - s = s[1:] - i := 0 - for i < len(s) && s[i] != quote { - i++ - } - if i >= len(s) { - return nil, fmt.Errorf("unterminated %c string", quote) - } - f = append(f, s[:i]) - s = s[i+1:] - continue - } - i := 0 - for i < len(s) && !isSpaceByte(s[i]) { - i++ - } - f = append(f, s[:i]) - s = s[i:] - } - return f, nil -} - -// JoinAndQuoteFields joins a list of arguments into a string that can be parsed -// with SplitQuotedFields. Arguments are quoted only if necessary; arguments -// without spaces or quotes are kept as-is. No argument may contain both -// single and double quotes. -func JoinAndQuoteFields(args []string) (string, error) { - var buf []byte - for i, arg := range args { - if i > 0 { - buf = append(buf, ' ') - } - var sawSpace, sawSingleQuote, sawDoubleQuote bool - for _, c := range arg { - switch { - case c > unicode.MaxASCII: - continue - case isSpaceByte(byte(c)): - sawSpace = true - case c == '\'': - sawSingleQuote = true - case c == '"': - sawDoubleQuote = true - } - } - switch { - case !sawSpace && !sawSingleQuote && !sawDoubleQuote: - buf = append(buf, []byte(arg)...) - - case !sawSingleQuote: - buf = append(buf, '\'') - buf = append(buf, []byte(arg)...) - buf = append(buf, '\'') - - case !sawDoubleQuote: - buf = append(buf, '"') - buf = append(buf, []byte(arg)...) - buf = append(buf, '"') - - default: - return "", fmt.Errorf("argument %q contains both single and double quotes and cannot be quoted", arg) - } - } - return string(buf), nil -} - -// A QuotedStringListFlag parses a list of string arguments encoded with -// JoinAndQuoteFields. It is useful for flags like cmd/link's -extldflags. -type QuotedStringListFlag []string - -var _ flag.Value = (*QuotedStringListFlag)(nil) - -func (f *QuotedStringListFlag) Set(v string) error { - fs, err := SplitQuotedFields(v) - if err != nil { - return err - } - *f = fs[:len(fs):len(fs)] - return nil -} - -func (f *QuotedStringListFlag) String() string { - if f == nil { - return "" - } - s, err := JoinAndQuoteFields(*f) - if err != nil { - return strings.Join(*f, " ") - } - return s -} diff --git a/src/cmd/link/dwarf_test.go b/src/cmd/link/dwarf_test.go index f7bbb014d9..78ef3cfe97 100644 --- a/src/cmd/link/dwarf_test.go +++ b/src/cmd/link/dwarf_test.go @@ -8,7 +8,7 @@ import ( "bytes" cmddwarf "cmd/internal/dwarf" "cmd/internal/objfile" - "cmd/internal/str" + "cmd/internal/quoted" "debug/dwarf" "internal/testenv" "os" @@ -68,7 +68,7 @@ func testDWARF(t *testing.T, buildmode string, expectDWARF bool, env ...string) if extld == "" { extld = "gcc" } - extldArgs, err := str.SplitQuotedFields(extld) + extldArgs, err := quoted.Split(extld) if err != nil { t.Fatal(err) } diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go index a5a5a71250..a1d86965e4 100644 --- a/src/cmd/link/internal/ld/main.go +++ b/src/cmd/link/internal/ld/main.go @@ -34,7 +34,7 @@ import ( "bufio" "cmd/internal/goobj" "cmd/internal/objabi" - "cmd/internal/str" + "cmd/internal/quoted" "cmd/internal/sys" "cmd/link/internal/benchmark" "flag" @@ -76,8 +76,8 @@ var ( flagLibGCC = flag.String("libgcc", "", "compiler support lib for internal linking; use \"none\" to disable") flagTmpdir = flag.String("tmpdir", "", "use `directory` for temporary files") - flagExtld str.QuotedStringListFlag - flagExtldflags str.QuotedStringListFlag + flagExtld quoted.Flag + flagExtldflags quoted.Flag flagExtar = flag.String("extar", "", "archive program for buildmode=c-archive") flagA = flag.Bool("a", false, "no-op (deprecated)") -- GitLab From c0ac39c70eeeaadbebe13efb407a1a272a926d30 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 25 Oct 2021 13:26:54 -0400 Subject: [PATCH 1763/2500] go/types: remove a stale comment Clean up a comment that was deleted in types2 in CL 353135. Change-Id: If339efa133e2a3d1eaa3b1e69458471677018261 Reviewed-on: https://go-review.googlesource.com/c/go/+/358517 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/typestring.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 2feaf627d6..9154ebc406 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -275,9 +275,6 @@ func (w *typeWriter) typ(typ Type) { break } // Optionally write out package for typeparams (like Named). - // TODO(danscales): this is required for import/export, so - // we maybe need a separate function that won't be changed - // for debugging purposes. if t.obj.pkg != nil { writePackage(w.buf, t.obj.pkg, w.qf) } -- GitLab From bb49eb3e6a464fbbebd425c4b84c32609b27ecf2 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 26 Oct 2021 21:12:31 -0700 Subject: [PATCH 1764/2500] cmd/compile/internal/syntax: fix constraint literal parsing for generic functions Fixes #49174. Change-Id: I943c370f7abd5f50a541e682f130b3526c3b5bdb Reviewed-on: https://go-review.googlesource.com/c/go/+/359014 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/syntax/parser.go | 14 +++++++++++++- .../compile/internal/syntax/testdata/typeset.go2 | 13 ++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index e78e77561d..af5a505cdb 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -588,19 +588,24 @@ func (p *parser) typeDecl(group *Group) Decl { d.Name = p.name() if p.tok == _Lbrack { // array/slice or generic type + // name "[" ... pos := p.pos() p.next() switch p.tok { case _Rbrack: + // name "[" "]" ... p.next() d.Type = p.sliceType(pos) case _Name: // array or generic type + // name "[" name ... p.xnest++ + // TODO(gri) p.expr may consume an opening "[" when it shouldn't (issue #49175) x := p.expr() p.xnest-- if name0, ok := x.(*Name); p.allowGenerics() && ok && p.tok != _Rbrack { // generic type + // name "[" name ... d.TParamList = p.paramList(name0, _Rbrack, true) pos := p.pos() if p.gotAssign() { @@ -609,12 +614,14 @@ func (p *parser) typeDecl(group *Group) Decl { d.Type = p.typeOrNil() } else { // x is the array length expression + // name "[" x ... if debug && x == nil { panic("length expression is nil") } d.Type = p.arrayType(pos, x) } default: + // name "[" ... d.Type = p.arrayType(pos, nil) } } else { @@ -1816,7 +1823,7 @@ func (p *parser) embeddedTerm() Expr { // ParameterDecl = [ IdentifierList ] [ "..." ] Type . func (p *parser) paramDeclOrNil(name *Name, follow token) *Field { if trace { - defer p.trace("paramDecl")() + defer p.trace("paramDeclOrNil")() } // type set notation is ok in type parameter lists @@ -1849,6 +1856,11 @@ func (p *parser) paramDeclOrNil(name *Name, follow token) *Field { // name "[" n "]" E f.Name = name } + if typeSetsOk && p.tok == _Operator && p.op == Or { + // name "[" ... "]" "|" ... + // name "[" n "]" E "|" ... + f = p.embeddedElem(f) + } return f } diff --git a/src/cmd/compile/internal/syntax/testdata/typeset.go2 b/src/cmd/compile/internal/syntax/testdata/typeset.go2 index a173bb1d4f..78d3fe1ae5 100644 --- a/src/cmd/compile/internal/syntax/testdata/typeset.go2 +++ b/src/cmd/compile/internal/syntax/testdata/typeset.go2 @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. // This file contains test cases for typeset-only constraint elements. -// TODO(gri) gofmt once/if gofmt supports this notation. package p @@ -44,8 +43,20 @@ type ( _[_ ~t|struct{}] t _[_ t|~struct{}] t _[_ ~t|~struct{}] t + + // TODO(gri) fix this (issue #49175) + // _[_ []t]t + _[_ ~[]t]t ) +// test cases for issue #49174 +func _[_ t]() {} +func _[_ []t]() {} +func _[_ []t | t]() {} +func _[_ t | []t]() {} +func _[_ []t | []t]() {} +func _[_ t[t] | t[t]]() {} + // Single-expression type parameter lists and those that don't start // with a (type parameter) name are considered array sizes. // The term must be a valid expression (it could be a type - and then -- GitLab From 259735f97a2dfd33849eacef15047f5a0964498e Mon Sep 17 00:00:00 2001 From: "Paul E. Murphy" Date: Tue, 24 Aug 2021 14:09:26 -0500 Subject: [PATCH 1765/2500] cmd/compile: enable branchelim pass on ppc64 and fix/cleanup lowering of the SSA operator created by the pass. Change-Id: I7e6153194fd16013e3b24da8aa40683adafa3d15 Reviewed-on: https://go-review.googlesource.com/c/go/+/344573 Run-TryBot: Paul Murphy TryBot-Result: Go Bot Reviewed-by: Lynn Boger Reviewed-by: Cherry Mui Trust: Josh Bleecher Snyder --- src/cmd/compile/internal/ssa/branchelim.go | 2 +- src/cmd/compile/internal/ssa/gen/PPC64.rules | 7 ++- src/cmd/compile/internal/ssa/rewritePPC64.go | 51 +++++++++++++------- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/src/cmd/compile/internal/ssa/branchelim.go b/src/cmd/compile/internal/ssa/branchelim.go index 1d34f8160b..be5f9e0a8b 100644 --- a/src/cmd/compile/internal/ssa/branchelim.go +++ b/src/cmd/compile/internal/ssa/branchelim.go @@ -22,7 +22,7 @@ import "cmd/internal/src" func branchelim(f *Func) { // FIXME: add support for lowering CondSelects on more architectures switch f.Config.arch { - case "arm64", "amd64", "wasm": + case "arm64", "ppc64le", "ppc64", "amd64", "wasm": // implemented default: return diff --git a/src/cmd/compile/internal/ssa/gen/PPC64.rules b/src/cmd/compile/internal/ssa/gen/PPC64.rules index ccca72a416..c3f07a4e22 100644 --- a/src/cmd/compile/internal/ssa/gen/PPC64.rules +++ b/src/cmd/compile/internal/ssa/gen/PPC64.rules @@ -561,8 +561,10 @@ ((EQ|NE|LT|LE|GT|GE) (CMPconst [0] z:(OR x y)) yes no) && z.Uses == 1 => ((EQ|NE|LT|LE|GT|GE) (ORCC x y) yes no) ((EQ|NE|LT|LE|GT|GE) (CMPconst [0] z:(XOR x y)) yes no) && z.Uses == 1 => ((EQ|NE|LT|LE|GT|GE) (XORCC x y) yes no) -(CondSelect x y bool) && flagArg(bool) != nil => (ISEL [2] x y bool) -(CondSelect x y bool) && flagArg(bool) == nil => (ISEL [2] x y (CMPWconst [0] bool)) +// Only lower after bool is lowered. It should always lower. This helps ensure the folding below happens reliably. +(CondSelect x y bool) && flagArg(bool) == nil => (ISEL [6] x y (CMPWconst [0] bool)) +// Fold any CR -> GPR -> CR transfers when applying the above rule. +(ISEL [6] x y (CMPWconst [0] (ISELB [c] one cmp))) => (ISEL [c] x y cmp) // Lowering loads (Load ptr mem) && (is64BitInt(t) || isPtr(t)) => (MOVDload ptr mem) @@ -849,6 +851,7 @@ (NEG (ADDconst [c] x)) && is32Bit(-c) => (SUBFCconst [-c] x) (NEG (SUBFCconst [c] x)) && is32Bit(-c) => (ADDconst [-c] x) (NEG (SUB x y)) => (SUB y x) +(NEG (NEG x)) => x // Use register moves instead of stores and loads to move int<=>float values // Common with math Float64bits, Float64frombits diff --git a/src/cmd/compile/internal/ssa/rewritePPC64.go b/src/cmd/compile/internal/ssa/rewritePPC64.go index ea1c1fa60a..7592b4f505 100644 --- a/src/cmd/compile/internal/ssa/rewritePPC64.go +++ b/src/cmd/compile/internal/ssa/rewritePPC64.go @@ -1168,23 +1168,8 @@ func rewriteValuePPC64_OpCondSelect(v *Value) bool { v_0 := v.Args[0] b := v.Block // match: (CondSelect x y bool) - // cond: flagArg(bool) != nil - // result: (ISEL [2] x y bool) - for { - x := v_0 - y := v_1 - bool := v_2 - if !(flagArg(bool) != nil) { - break - } - v.reset(OpPPC64ISEL) - v.AuxInt = int32ToAuxInt(2) - v.AddArg3(x, y, bool) - return true - } - // match: (CondSelect x y bool) // cond: flagArg(bool) == nil - // result: (ISEL [2] x y (CMPWconst [0] bool)) + // result: (ISEL [6] x y (CMPWconst [0] bool)) for { x := v_0 y := v_1 @@ -1193,7 +1178,7 @@ func rewriteValuePPC64_OpCondSelect(v *Value) bool { break } v.reset(OpPPC64ISEL) - v.AuxInt = int32ToAuxInt(2) + v.AuxInt = int32ToAuxInt(6) v0 := b.NewValue0(v.Pos, OpPPC64CMPWconst, types.TypeFlags) v0.AuxInt = int32ToAuxInt(0) v0.AddArg(bool) @@ -5910,6 +5895,28 @@ func rewriteValuePPC64_OpPPC64ISEL(v *Value) bool { v.AddArg(y) return true } + // match: (ISEL [6] x y (CMPWconst [0] (ISELB [c] one cmp))) + // result: (ISEL [c] x y cmp) + for { + if auxIntToInt32(v.AuxInt) != 6 { + break + } + x := v_0 + y := v_1 + if v_2.Op != OpPPC64CMPWconst || auxIntToInt32(v_2.AuxInt) != 0 { + break + } + v_2_0 := v_2.Args[0] + if v_2_0.Op != OpPPC64ISELB { + break + } + c := auxIntToInt32(v_2_0.AuxInt) + cmp := v_2_0.Args[1] + v.reset(OpPPC64ISEL) + v.AuxInt = int32ToAuxInt(c) + v.AddArg3(x, y, cmp) + return true + } // match: (ISEL [2] x _ (FlagEQ)) // result: x for { @@ -11384,6 +11391,16 @@ func rewriteValuePPC64_OpPPC64NEG(v *Value) bool { v.AddArg2(y, x) return true } + // match: (NEG (NEG x)) + // result: x + for { + if v_0.Op != OpPPC64NEG { + break + } + x := v_0.Args[0] + v.copyOf(x) + return true + } return false } func rewriteValuePPC64_OpPPC64NOR(v *Value) bool { -- GitLab From 514ebaec358488d1dcf7253b9d05b4ad8c76c390 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Fri, 22 Oct 2021 15:59:15 -0400 Subject: [PATCH 1766/2500] internal/fuzz: don't deflake coverage found while fuzzing Previously, the worker would attempt to deflake an input that was reported to have caused new coverage. The chances of a flake causing new coverage seem pretty low to me, and even if it was a flake that caused it, adding that input to the cache doesn't seem like a bad thing. The input is already going to be deflaked during minimization anyway. If by some off-chance the code is causing a lot of flaky coverage increases, and the user doesn't want minimization to occur, then setting -fuzzminimizetime=1x will deflake in the way they want without minimizing. This can be documented as needed. This fixes a bug where the mem.header().count could have been one too large if an unrecoverable crash occured while deflaking an input that caused code coverage. Fixes #49047 Change-Id: Ibdf893d7a89a46dd700702afb09e35623615390e Reviewed-on: https://go-review.googlesource.com/c/go/+/358094 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Julie Qiu Reviewed-by: Roland Shoemaker Reviewed-by: Bryan C. Mills --- .../script/test_fuzz_mutator_repeat.txt | 24 ++++++++++++------- src/internal/fuzz/worker.go | 17 +++---------- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt b/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt index f2952c349b..15d7cb6b32 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt @@ -1,5 +1,3 @@ -skip # Flaky: https://golang.org/issue/49047 - # TODO(jayconrod): support shared memory on more platforms. [!darwin] [!linux] [!windows] skip @@ -9,11 +7,11 @@ skip # Flaky: https://golang.org/issue/49047 [short] skip -# Start fuzzing. The worker crashes after ~100 iterations. +# Start fuzzing. The worker crashes after 100 iterations. # The fuzz function writes the crashing input to "want" before exiting. # The fuzzing engine reconstructs the crashing input and saves it to testdata. ! exists want -! go test -fuzz=. -parallel=1 +! go test -fuzz=. -parallel=1 -fuzztime=110x -fuzzminimizetime=10x -v stdout 'fuzzing process terminated unexpectedly' stdout 'Crash written to testdata' @@ -46,12 +44,20 @@ func FuzzRepeat(f *testing.F) { if i == 100 { f, err := os.OpenFile("want", os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666) if err != nil { - // Couldn't create the file, probably because it already exists, - // and we're minimizing now. Return without crashing. - return + // Couldn't create the file. Return without crashing, and try + // again. + i-- + t.Skip(err) + } + if _, err := f.Write(b); err != nil { + // We already created the file, so if we failed to write it + // there's not much we can do. The test will fail anyway, but + // at least make sure the error is logged to stdout. + t.Fatal(err) + } + if err := f.Close(); err != nil { + t.Fatal(err) } - f.Write(b) - f.Close() os.Exit(1) // crash without communicating } diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index b36ebe2a7e..388675f713 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -738,20 +738,9 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo return resp } if cov != nil { - // Found new coverage. Before reporting to the coordinator, - // run the same values once more to deflake. - if !shouldStop() { - dur, cov, errMsg = fuzzOnce(entry) - if errMsg != "" { - resp.Err = errMsg - return resp - } - } - if cov != nil { - resp.CoverageData = cov - resp.InterestingDuration = dur - return resp - } + resp.CoverageData = cov + resp.InterestingDuration = dur + return resp } if shouldStop() { return resp -- GitLab From ffd2284db06d433d60aa75ea413f407b90e583b6 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 27 Oct 2021 15:06:23 -0400 Subject: [PATCH 1767/2500] cmd/go: fix testdata/script/mod_vendor_goversion for new compiler output The message is now a single line, but I couldn't get '\n?' to work. (This test does not run in short mode.) Change-Id: I3d7033f78ac2bf41db7fdfe96cbb988c4533d834 Reviewed-on: https://go-review.googlesource.com/c/go/+/359095 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/testdata/script/mod_vendor_goversion.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/go/testdata/script/mod_vendor_goversion.txt b/src/cmd/go/testdata/script/mod_vendor_goversion.txt index b4489dae7e..a92eb73d27 100644 --- a/src/cmd/go/testdata/script/mod_vendor_goversion.txt +++ b/src/cmd/go/testdata/script/mod_vendor_goversion.txt @@ -3,7 +3,6 @@ [short] skip - # Control case: without a vendor directory, need117 builds and bad114 doesn't. go build example.net/need117 @@ -26,7 +25,8 @@ go mod vendor ! grep 1.17 vendor/modules.txt ! go build example.net/need117 -stderr '^vendor[/\\]example\.net[/\\]need117[/\\]need117.go:5:1[89]:.*\n\tconversion of slices to array pointers only supported as of -lang=go1\.17' +stderr '^vendor[/\\]example\.net[/\\]need117[/\\]need117.go:5:1[89]:' +stderr 'conversion of slices to array pointers only supported as of -lang=go1\.17' ! grep 1.13 vendor/modules.txt go build example.net/bad114 -- GitLab From 68bd5121ee8954cfd7e3f7edb5d035f0e8b1bccc Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Wed, 27 Oct 2021 14:29:29 -0400 Subject: [PATCH 1768/2500] cmd/go: remove support for -buildmode=shared It never worked in module mode (or with a read-only GOROOT). A proposal to drop it was filed (and approved) in https://golang.org/issue/47788. Fixes #47788 Change-Id: I0c12f38eb0c5dfe9384fbdb49ed202301fa4273d Reviewed-on: https://go-review.googlesource.com/c/go/+/359096 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- doc/go1.18.html | 7 + misc/cgo/testshared/overlaydir_test.go | 78 -- misc/cgo/testshared/shared_test.go | 1080 ----------------- misc/cgo/testshared/testdata/dep2/dep2.go | 15 - misc/cgo/testshared/testdata/dep3/dep3.go | 22 - misc/cgo/testshared/testdata/depBase/asm.s | 10 - misc/cgo/testshared/testdata/depBase/dep.go | 37 - misc/cgo/testshared/testdata/depBase/gccgo.go | 9 - misc/cgo/testshared/testdata/depBase/stubs.go | 9 - .../testshared/testdata/division/division.go | 17 - misc/cgo/testshared/testdata/exe/exe.go | 45 - misc/cgo/testshared/testdata/exe2/exe2.go | 8 - misc/cgo/testshared/testdata/exe3/exe3.go | 7 - misc/cgo/testshared/testdata/execgo/exe.go | 8 - .../testshared/testdata/explicit/explicit.go | 9 - .../testshared/testdata/gcdata/main/main.go | 37 - misc/cgo/testshared/testdata/gcdata/p/p.go | 7 - misc/cgo/testshared/testdata/global/main.go | 71 -- .../testshared/testdata/globallib/global.go | 17 - misc/cgo/testshared/testdata/iface/main.go | 17 - misc/cgo/testshared/testdata/iface_a/a.go | 17 - misc/cgo/testshared/testdata/iface_b/b.go | 17 - misc/cgo/testshared/testdata/iface_i/i.go | 17 - .../testshared/testdata/implicit/implicit.go | 5 - .../testdata/implicitcmd/implicitcmd.go | 10 - misc/cgo/testshared/testdata/issue25065/a.go | 20 - .../testdata/issue30768/issue30768lib/lib.go | 11 - .../testshared/testdata/issue30768/x_test.go | 22 - .../cgo/testshared/testdata/issue39777/a/a.go | 9 - .../cgo/testshared/testdata/issue39777/b/b.go | 7 - .../cgo/testshared/testdata/issue44031/a/a.go | 9 - .../cgo/testshared/testdata/issue44031/b/b.go | 17 - .../testdata/issue44031/main/main.go | 20 - .../cgo/testshared/testdata/issue47837/a/a.go | 19 - .../testdata/issue47837/main/main.go | 14 - .../testshared/testdata/trivial/trivial.go | 9 - src/cmd/dist/test.go | 9 - src/cmd/go/alldocs.go | 9 - src/cmd/go/internal/help/helpdoc.go | 5 - src/cmd/go/internal/list/list.go | 3 +- src/cmd/go/internal/work/build.go | 3 - src/cmd/go/internal/work/init.go | 31 +- .../go/testdata/script/list_linkshared.txt | 16 - src/cmd/internal/sys/supported.go | 7 - 44 files changed, 30 insertions(+), 1786 deletions(-) delete mode 100644 misc/cgo/testshared/overlaydir_test.go delete mode 100644 misc/cgo/testshared/shared_test.go delete mode 100644 misc/cgo/testshared/testdata/dep2/dep2.go delete mode 100644 misc/cgo/testshared/testdata/dep3/dep3.go delete mode 100644 misc/cgo/testshared/testdata/depBase/asm.s delete mode 100644 misc/cgo/testshared/testdata/depBase/dep.go delete mode 100644 misc/cgo/testshared/testdata/depBase/gccgo.go delete mode 100644 misc/cgo/testshared/testdata/depBase/stubs.go delete mode 100644 misc/cgo/testshared/testdata/division/division.go delete mode 100644 misc/cgo/testshared/testdata/exe/exe.go delete mode 100644 misc/cgo/testshared/testdata/exe2/exe2.go delete mode 100644 misc/cgo/testshared/testdata/exe3/exe3.go delete mode 100644 misc/cgo/testshared/testdata/execgo/exe.go delete mode 100644 misc/cgo/testshared/testdata/explicit/explicit.go delete mode 100644 misc/cgo/testshared/testdata/gcdata/main/main.go delete mode 100644 misc/cgo/testshared/testdata/gcdata/p/p.go delete mode 100644 misc/cgo/testshared/testdata/global/main.go delete mode 100644 misc/cgo/testshared/testdata/globallib/global.go delete mode 100644 misc/cgo/testshared/testdata/iface/main.go delete mode 100644 misc/cgo/testshared/testdata/iface_a/a.go delete mode 100644 misc/cgo/testshared/testdata/iface_b/b.go delete mode 100644 misc/cgo/testshared/testdata/iface_i/i.go delete mode 100644 misc/cgo/testshared/testdata/implicit/implicit.go delete mode 100644 misc/cgo/testshared/testdata/implicitcmd/implicitcmd.go delete mode 100644 misc/cgo/testshared/testdata/issue25065/a.go delete mode 100644 misc/cgo/testshared/testdata/issue30768/issue30768lib/lib.go delete mode 100644 misc/cgo/testshared/testdata/issue30768/x_test.go delete mode 100644 misc/cgo/testshared/testdata/issue39777/a/a.go delete mode 100644 misc/cgo/testshared/testdata/issue39777/b/b.go delete mode 100644 misc/cgo/testshared/testdata/issue44031/a/a.go delete mode 100644 misc/cgo/testshared/testdata/issue44031/b/b.go delete mode 100644 misc/cgo/testshared/testdata/issue44031/main/main.go delete mode 100644 misc/cgo/testshared/testdata/issue47837/a/a.go delete mode 100644 misc/cgo/testshared/testdata/issue47837/main/main.go delete mode 100644 misc/cgo/testshared/testdata/trivial/trivial.go delete mode 100644 src/cmd/go/testdata/script/list_linkshared.txt diff --git a/doc/go1.18.html b/doc/go1.18.html index 985689cf31..63a6ed8fcd 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -89,6 +89,13 @@ Do not send CLs removing the interior tags from such phrases. package.

+

+ The go command no longer supports -linkshared + and -buildmode=shared. + (shared building and linking has never worked in module mode or + when GOROOT is not writable.) +

+

TODO: complete this section, or delete if not needed

diff --git a/misc/cgo/testshared/overlaydir_test.go b/misc/cgo/testshared/overlaydir_test.go deleted file mode 100644 index eb587a2d44..0000000000 --- a/misc/cgo/testshared/overlaydir_test.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package shared_test - -import ( - "io" - "os" - "path/filepath" - "strings" -) - -// overlayDir makes a minimal-overhead copy of srcRoot in which new files may be added. -// -// TODO: Once we no longer need to support the misc module in GOPATH mode, -// factor this function out into a package to reduce duplication. -func overlayDir(dstRoot, srcRoot string) error { - dstRoot = filepath.Clean(dstRoot) - if err := os.MkdirAll(dstRoot, 0777); err != nil { - return err - } - - srcRoot, err := filepath.Abs(srcRoot) - if err != nil { - return err - } - - return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error { - if err != nil || srcPath == srcRoot { - return err - } - - suffix := strings.TrimPrefix(srcPath, srcRoot) - for len(suffix) > 0 && suffix[0] == filepath.Separator { - suffix = suffix[1:] - } - dstPath := filepath.Join(dstRoot, suffix) - - perm := info.Mode() & os.ModePerm - if info.Mode()&os.ModeSymlink != 0 { - info, err = os.Stat(srcPath) - if err != nil { - return err - } - perm = info.Mode() & os.ModePerm - } - - // Always copy directories (don't symlink them). - // If we add a file in the overlay, we don't want to add it in the original. - if info.IsDir() { - return os.MkdirAll(dstPath, perm|0200) - } - - // If the OS supports symlinks, use them instead of copying bytes. - if err := os.Symlink(srcPath, dstPath); err == nil { - return nil - } - - // Otherwise, copy the bytes. - src, err := os.Open(srcPath) - if err != nil { - return err - } - defer src.Close() - - dst, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm) - if err != nil { - return err - } - - _, err = io.Copy(dst, src) - if closeErr := dst.Close(); err == nil { - err = closeErr - } - return err - }) -} diff --git a/misc/cgo/testshared/shared_test.go b/misc/cgo/testshared/shared_test.go deleted file mode 100644 index 672811fe0e..0000000000 --- a/misc/cgo/testshared/shared_test.go +++ /dev/null @@ -1,1080 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package shared_test - -import ( - "bufio" - "bytes" - "debug/elf" - "encoding/binary" - "flag" - "fmt" - "go/build" - "io" - "log" - "os" - "os/exec" - "path/filepath" - "regexp" - "runtime" - "sort" - "strings" - "testing" - "time" -) - -var gopathInstallDir, gorootInstallDir string - -// This is the smallest set of packages we can link into a shared -// library (runtime/cgo is built implicitly). -var minpkgs = []string{"runtime", "sync/atomic"} -var soname = "libruntime,sync-atomic.so" - -var testX = flag.Bool("testx", false, "if true, pass -x to 'go' subcommands invoked by the test") -var testWork = flag.Bool("testwork", false, "if true, log and do not delete the temporary working directory") - -// run runs a command and calls t.Errorf if it fails. -func run(t *testing.T, msg string, args ...string) { - runWithEnv(t, msg, nil, args...) -} - -// runWithEnv runs a command under the given environment and calls t.Errorf if it fails. -func runWithEnv(t *testing.T, msg string, env []string, args ...string) { - c := exec.Command(args[0], args[1:]...) - if len(env) != 0 { - c.Env = append(os.Environ(), env...) - } - if output, err := c.CombinedOutput(); err != nil { - t.Errorf("executing %s (%s) failed %s:\n%s", strings.Join(args, " "), msg, err, output) - } -} - -// goCmd invokes the go tool with the installsuffix set up by TestMain. It calls -// t.Fatalf if the command fails. -func goCmd(t *testing.T, args ...string) string { - newargs := []string{args[0]} - if *testX { - newargs = append(newargs, "-x") - } - newargs = append(newargs, args[1:]...) - c := exec.Command("go", newargs...) - stderr := new(strings.Builder) - c.Stderr = stderr - - if testing.Verbose() && t == nil { - fmt.Fprintf(os.Stderr, "+ go %s\n", strings.Join(args, " ")) - c.Stderr = os.Stderr - } - output, err := c.Output() - - if err != nil { - if t != nil { - t.Helper() - t.Fatalf("executing %s failed %v:\n%s", strings.Join(c.Args, " "), err, stderr) - } else { - // Panic instead of using log.Fatalf so that deferred cleanup may run in testMain. - log.Panicf("executing %s failed %v:\n%s", strings.Join(c.Args, " "), err, stderr) - } - } - if testing.Verbose() && t != nil { - t.Logf("go %s", strings.Join(args, " ")) - if stderr.Len() > 0 { - t.Logf("%s", stderr) - } - } - return string(bytes.TrimSpace(output)) -} - -// TestMain calls testMain so that the latter can use defer (TestMain exits with os.Exit). -func testMain(m *testing.M) (int, error) { - workDir, err := os.MkdirTemp("", "shared_test") - if err != nil { - return 0, err - } - if *testWork || testing.Verbose() { - fmt.Printf("+ mkdir -p %s\n", workDir) - } - if !*testWork { - defer os.RemoveAll(workDir) - } - - // Some tests need to edit the source in GOPATH, so copy this directory to a - // temporary directory and chdir to that. - gopath := filepath.Join(workDir, "gopath") - modRoot, err := cloneTestdataModule(gopath) - if err != nil { - return 0, err - } - if testing.Verbose() { - fmt.Printf("+ export GOPATH=%s\n", gopath) - fmt.Printf("+ cd %s\n", modRoot) - } - os.Setenv("GOPATH", gopath) - // Explicitly override GOBIN as well, in case it was set through a GOENV file. - os.Setenv("GOBIN", filepath.Join(gopath, "bin")) - os.Chdir(modRoot) - os.Setenv("PWD", modRoot) - - // The test also needs to install libraries into GOROOT/pkg, so copy the - // subset of GOROOT that we need. - // - // TODO(golang.org/issue/28553): Rework -buildmode=shared so that it does not - // need to write to GOROOT. - goroot := filepath.Join(workDir, "goroot") - if err := cloneGOROOTDeps(goroot); err != nil { - return 0, err - } - if testing.Verbose() { - fmt.Fprintf(os.Stderr, "+ export GOROOT=%s\n", goroot) - } - os.Setenv("GOROOT", goroot) - - myContext := build.Default - myContext.GOROOT = goroot - myContext.GOPATH = gopath - runtimeP, err := myContext.Import("runtime", ".", build.ImportComment) - if err != nil { - return 0, fmt.Errorf("import failed: %v", err) - } - gorootInstallDir = runtimeP.PkgTargetRoot + "_dynlink" - - // All tests depend on runtime being built into a shared library. Because - // that takes a few seconds, do it here and have all tests use the version - // built here. - goCmd(nil, append([]string{"install", "-buildmode=shared"}, minpkgs...)...) - - myContext.InstallSuffix = "_dynlink" - depP, err := myContext.Import("./depBase", ".", build.ImportComment) - if err != nil { - return 0, fmt.Errorf("import failed: %v", err) - } - if depP.PkgTargetRoot == "" { - gopathInstallDir = filepath.Dir(goCmd(nil, "list", "-buildmode=shared", "-f", "{{.Target}}", "./depBase")) - } else { - gopathInstallDir = filepath.Join(depP.PkgTargetRoot, "testshared") - } - return m.Run(), nil -} - -func TestMain(m *testing.M) { - log.SetFlags(log.Lshortfile) - flag.Parse() - - exitCode, err := testMain(m) - if err != nil { - log.Fatal(err) - } - os.Exit(exitCode) -} - -// cloneTestdataModule clones the packages from src/testshared into gopath. -// It returns the directory within gopath at which the module root is located. -func cloneTestdataModule(gopath string) (string, error) { - modRoot := filepath.Join(gopath, "src", "testshared") - if err := overlayDir(modRoot, "testdata"); err != nil { - return "", err - } - if err := os.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module testshared\n"), 0644); err != nil { - return "", err - } - return modRoot, nil -} - -// cloneGOROOTDeps copies (or symlinks) the portions of GOROOT/src and -// GOROOT/pkg relevant to this test into the given directory. -// It must be run from within the testdata module. -func cloneGOROOTDeps(goroot string) error { - oldGOROOT := strings.TrimSpace(goCmd(nil, "env", "GOROOT")) - if oldGOROOT == "" { - return fmt.Errorf("go env GOROOT returned an empty string") - } - - // Before we clone GOROOT, figure out which packages we need to copy over. - listArgs := []string{ - "list", - "-deps", - "-f", "{{if and .Standard (not .ForTest)}}{{.ImportPath}}{{end}}", - } - stdDeps := goCmd(nil, append(listArgs, minpkgs...)...) - testdataDeps := goCmd(nil, append(listArgs, "-test", "./...")...) - - pkgs := append(strings.Split(strings.TrimSpace(stdDeps), "\n"), - strings.Split(strings.TrimSpace(testdataDeps), "\n")...) - sort.Strings(pkgs) - var pkgRoots []string - for _, pkg := range pkgs { - parentFound := false - for _, prev := range pkgRoots { - if strings.HasPrefix(pkg, prev) { - // We will copy in the source for pkg when we copy in prev. - parentFound = true - break - } - } - if !parentFound { - pkgRoots = append(pkgRoots, pkg) - } - } - - gorootDirs := []string{ - "pkg/tool", - "pkg/include", - } - for _, pkg := range pkgRoots { - gorootDirs = append(gorootDirs, filepath.Join("src", pkg)) - } - - for _, dir := range gorootDirs { - if testing.Verbose() { - fmt.Fprintf(os.Stderr, "+ cp -r %s %s\n", filepath.Join(oldGOROOT, dir), filepath.Join(goroot, dir)) - } - if err := overlayDir(filepath.Join(goroot, dir), filepath.Join(oldGOROOT, dir)); err != nil { - return err - } - } - - return nil -} - -// The shared library was built at the expected location. -func TestSOBuilt(t *testing.T) { - _, err := os.Stat(filepath.Join(gorootInstallDir, soname)) - if err != nil { - t.Error(err) - } -} - -func hasDynTag(f *elf.File, tag elf.DynTag) bool { - ds := f.SectionByType(elf.SHT_DYNAMIC) - if ds == nil { - return false - } - d, err := ds.Data() - if err != nil { - return false - } - for len(d) > 0 { - var t elf.DynTag - switch f.Class { - case elf.ELFCLASS32: - t = elf.DynTag(f.ByteOrder.Uint32(d[0:4])) - d = d[8:] - case elf.ELFCLASS64: - t = elf.DynTag(f.ByteOrder.Uint64(d[0:8])) - d = d[16:] - } - if t == tag { - return true - } - } - return false -} - -// The shared library does not have relocations against the text segment. -func TestNoTextrel(t *testing.T) { - sopath := filepath.Join(gorootInstallDir, soname) - f, err := elf.Open(sopath) - if err != nil { - t.Fatal("elf.Open failed: ", err) - } - defer f.Close() - if hasDynTag(f, elf.DT_TEXTREL) { - t.Errorf("%s has DT_TEXTREL set", soname) - } -} - -// The shared library does not contain symbols called ".dup" -// (See golang.org/issue/14841.) -func TestNoDupSymbols(t *testing.T) { - sopath := filepath.Join(gorootInstallDir, soname) - f, err := elf.Open(sopath) - if err != nil { - t.Fatal("elf.Open failed: ", err) - } - defer f.Close() - syms, err := f.Symbols() - if err != nil { - t.Errorf("error reading symbols %v", err) - return - } - for _, s := range syms { - if s.Name == ".dup" { - t.Fatalf("%s contains symbol called .dup", sopath) - } - } -} - -// The install command should have created a "shlibname" file for the -// listed packages (and runtime/cgo, and math on arm) indicating the -// name of the shared library containing it. -func TestShlibnameFiles(t *testing.T) { - pkgs := append([]string{}, minpkgs...) - pkgs = append(pkgs, "runtime/cgo") - if runtime.GOARCH == "arm" { - pkgs = append(pkgs, "math") - } - for _, pkg := range pkgs { - shlibnamefile := filepath.Join(gorootInstallDir, pkg+".shlibname") - contentsb, err := os.ReadFile(shlibnamefile) - if err != nil { - t.Errorf("error reading shlibnamefile for %s: %v", pkg, err) - continue - } - contents := strings.TrimSpace(string(contentsb)) - if contents != soname { - t.Errorf("shlibnamefile for %s has wrong contents: %q", pkg, contents) - } - } -} - -// Is a given offset into the file contained in a loaded segment? -func isOffsetLoaded(f *elf.File, offset uint64) bool { - for _, prog := range f.Progs { - if prog.Type == elf.PT_LOAD { - if prog.Off <= offset && offset < prog.Off+prog.Filesz { - return true - } - } - } - return false -} - -func rnd(v int32, r int32) int32 { - if r <= 0 { - return v - } - v += r - 1 - c := v % r - if c < 0 { - c += r - } - v -= c - return v -} - -func readwithpad(r io.Reader, sz int32) ([]byte, error) { - data := make([]byte, rnd(sz, 4)) - _, err := io.ReadFull(r, data) - if err != nil { - return nil, err - } - data = data[:sz] - return data, nil -} - -type note struct { - name string - tag int32 - desc string - section *elf.Section -} - -// Read all notes from f. As ELF section names are not supposed to be special, one -// looks for a particular note by scanning all SHT_NOTE sections looking for a note -// with a particular "name" and "tag". -func readNotes(f *elf.File) ([]*note, error) { - var notes []*note - for _, sect := range f.Sections { - if sect.Type != elf.SHT_NOTE { - continue - } - r := sect.Open() - for { - var namesize, descsize, tag int32 - err := binary.Read(r, f.ByteOrder, &namesize) - if err != nil { - if err == io.EOF { - break - } - return nil, fmt.Errorf("read namesize failed: %v", err) - } - err = binary.Read(r, f.ByteOrder, &descsize) - if err != nil { - return nil, fmt.Errorf("read descsize failed: %v", err) - } - err = binary.Read(r, f.ByteOrder, &tag) - if err != nil { - return nil, fmt.Errorf("read type failed: %v", err) - } - name, err := readwithpad(r, namesize) - if err != nil { - return nil, fmt.Errorf("read name failed: %v", err) - } - desc, err := readwithpad(r, descsize) - if err != nil { - return nil, fmt.Errorf("read desc failed: %v", err) - } - notes = append(notes, ¬e{name: string(name), tag: tag, desc: string(desc), section: sect}) - } - } - return notes, nil -} - -func dynStrings(t *testing.T, path string, flag elf.DynTag) []string { - t.Helper() - f, err := elf.Open(path) - if err != nil { - t.Fatalf("elf.Open(%q) failed: %v", path, err) - } - defer f.Close() - dynstrings, err := f.DynString(flag) - if err != nil { - t.Fatalf("DynString(%s) failed on %s: %v", flag, path, err) - } - return dynstrings -} - -func AssertIsLinkedToRegexp(t *testing.T, path string, re *regexp.Regexp) { - t.Helper() - for _, dynstring := range dynStrings(t, path, elf.DT_NEEDED) { - if re.MatchString(dynstring) { - return - } - } - t.Errorf("%s is not linked to anything matching %v", path, re) -} - -func AssertIsLinkedTo(t *testing.T, path, lib string) { - t.Helper() - AssertIsLinkedToRegexp(t, path, regexp.MustCompile(regexp.QuoteMeta(lib))) -} - -func AssertHasRPath(t *testing.T, path, dir string) { - t.Helper() - for _, tag := range []elf.DynTag{elf.DT_RPATH, elf.DT_RUNPATH} { - for _, dynstring := range dynStrings(t, path, tag) { - for _, rpath := range strings.Split(dynstring, ":") { - if filepath.Clean(rpath) == filepath.Clean(dir) { - return - } - } - } - } - t.Errorf("%s does not have rpath %s", path, dir) -} - -// Build a trivial program that links against the shared runtime and check it runs. -func TestTrivialExecutable(t *testing.T) { - goCmd(t, "install", "-linkshared", "./trivial") - run(t, "trivial executable", "../../bin/trivial") - AssertIsLinkedTo(t, "../../bin/trivial", soname) - AssertHasRPath(t, "../../bin/trivial", gorootInstallDir) - checkSize(t, "../../bin/trivial", 100000) // it is 19K on linux/amd64, 100K should be enough -} - -// Build a trivial program in PIE mode that links against the shared runtime and check it runs. -func TestTrivialExecutablePIE(t *testing.T) { - goCmd(t, "build", "-buildmode=pie", "-o", "trivial.pie", "-linkshared", "./trivial") - run(t, "trivial executable", "./trivial.pie") - AssertIsLinkedTo(t, "./trivial.pie", soname) - AssertHasRPath(t, "./trivial.pie", gorootInstallDir) - checkSize(t, "./trivial.pie", 100000) // it is 19K on linux/amd64, 100K should be enough -} - -// Check that the file size does not exceed a limit. -func checkSize(t *testing.T, f string, limit int64) { - fi, err := os.Stat(f) - if err != nil { - t.Fatalf("stat failed: %v", err) - } - if sz := fi.Size(); sz > limit { - t.Errorf("file too large: got %d, want <= %d", sz, limit) - } -} - -// Build a division test program and check it runs. -func TestDivisionExecutable(t *testing.T) { - goCmd(t, "install", "-linkshared", "./division") - run(t, "division executable", "../../bin/division") -} - -// Build an executable that uses cgo linked against the shared runtime and check it -// runs. -func TestCgoExecutable(t *testing.T) { - goCmd(t, "install", "-linkshared", "./execgo") - run(t, "cgo executable", "../../bin/execgo") -} - -func checkPIE(t *testing.T, name string) { - f, err := elf.Open(name) - if err != nil { - t.Fatal("elf.Open failed: ", err) - } - defer f.Close() - if f.Type != elf.ET_DYN { - t.Errorf("%s has type %v, want ET_DYN", name, f.Type) - } - if hasDynTag(f, elf.DT_TEXTREL) { - t.Errorf("%s has DT_TEXTREL set", name) - } -} - -func TestTrivialPIE(t *testing.T) { - name := "trivial_pie" - goCmd(t, "build", "-buildmode=pie", "-o="+name, "./trivial") - defer os.Remove(name) - run(t, name, "./"+name) - checkPIE(t, name) -} - -func TestCgoPIE(t *testing.T) { - name := "cgo_pie" - goCmd(t, "build", "-buildmode=pie", "-o="+name, "./execgo") - defer os.Remove(name) - run(t, name, "./"+name) - checkPIE(t, name) -} - -// Build a GOPATH package into a shared library that links against the goroot runtime -// and an executable that links against both. -func TestGopathShlib(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase") - shlib := goCmd(t, "list", "-f", "{{.Shlib}}", "-buildmode=shared", "-linkshared", "./depBase") - AssertIsLinkedTo(t, shlib, soname) - goCmd(t, "install", "-linkshared", "./exe") - AssertIsLinkedTo(t, "../../bin/exe", soname) - AssertIsLinkedTo(t, "../../bin/exe", filepath.Base(shlib)) - AssertHasRPath(t, "../../bin/exe", gorootInstallDir) - AssertHasRPath(t, "../../bin/exe", filepath.Dir(gopathInstallDir)) - // And check it runs. - run(t, "executable linked to GOPATH library", "../../bin/exe") -} - -// The shared library contains a note listing the packages it contains in a section -// that is not mapped into memory. -func testPkgListNote(t *testing.T, f *elf.File, note *note) { - if note.section.Flags != 0 { - t.Errorf("package list section has flags %v, want 0", note.section.Flags) - } - if isOffsetLoaded(f, note.section.Offset) { - t.Errorf("package list section contained in PT_LOAD segment") - } - if note.desc != "testshared/depBase\n" { - t.Errorf("incorrect package list %q, want %q", note.desc, "testshared/depBase\n") - } -} - -// The shared library contains a note containing the ABI hash that is mapped into -// memory and there is a local symbol called go.link.abihashbytes that points 16 -// bytes into it. -func testABIHashNote(t *testing.T, f *elf.File, note *note) { - if note.section.Flags != elf.SHF_ALLOC { - t.Errorf("abi hash section has flags %v, want SHF_ALLOC", note.section.Flags) - } - if !isOffsetLoaded(f, note.section.Offset) { - t.Errorf("abihash section not contained in PT_LOAD segment") - } - var hashbytes elf.Symbol - symbols, err := f.Symbols() - if err != nil { - t.Errorf("error reading symbols %v", err) - return - } - for _, sym := range symbols { - if sym.Name == "go.link.abihashbytes" { - hashbytes = sym - } - } - if hashbytes.Name == "" { - t.Errorf("no symbol called go.link.abihashbytes") - return - } - if elf.ST_BIND(hashbytes.Info) != elf.STB_LOCAL { - t.Errorf("%s has incorrect binding %v, want STB_LOCAL", hashbytes.Name, elf.ST_BIND(hashbytes.Info)) - } - if f.Sections[hashbytes.Section] != note.section { - t.Errorf("%s has incorrect section %v, want %s", hashbytes.Name, f.Sections[hashbytes.Section].Name, note.section.Name) - } - if hashbytes.Value-note.section.Addr != 16 { - t.Errorf("%s has incorrect offset into section %d, want 16", hashbytes.Name, hashbytes.Value-note.section.Addr) - } -} - -// A Go shared library contains a note indicating which other Go shared libraries it -// was linked against in an unmapped section. -func testDepsNote(t *testing.T, f *elf.File, note *note) { - if note.section.Flags != 0 { - t.Errorf("package list section has flags %v, want 0", note.section.Flags) - } - if isOffsetLoaded(f, note.section.Offset) { - t.Errorf("package list section contained in PT_LOAD segment") - } - // libdepBase.so just links against the lib containing the runtime. - if note.desc != soname { - t.Errorf("incorrect dependency list %q, want %q", note.desc, soname) - } -} - -// The shared library contains notes with defined contents; see above. -func TestNotes(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase") - shlib := goCmd(t, "list", "-f", "{{.Shlib}}", "-buildmode=shared", "-linkshared", "./depBase") - f, err := elf.Open(shlib) - if err != nil { - t.Fatal(err) - } - defer f.Close() - notes, err := readNotes(f) - if err != nil { - t.Fatal(err) - } - pkgListNoteFound := false - abiHashNoteFound := false - depsNoteFound := false - for _, note := range notes { - if note.name != "Go\x00\x00" { - continue - } - switch note.tag { - case 1: // ELF_NOTE_GOPKGLIST_TAG - if pkgListNoteFound { - t.Error("multiple package list notes") - } - testPkgListNote(t, f, note) - pkgListNoteFound = true - case 2: // ELF_NOTE_GOABIHASH_TAG - if abiHashNoteFound { - t.Error("multiple abi hash notes") - } - testABIHashNote(t, f, note) - abiHashNoteFound = true - case 3: // ELF_NOTE_GODEPS_TAG - if depsNoteFound { - t.Error("multiple dependency list notes") - } - testDepsNote(t, f, note) - depsNoteFound = true - } - } - if !pkgListNoteFound { - t.Error("package list note not found") - } - if !abiHashNoteFound { - t.Error("abi hash note not found") - } - if !depsNoteFound { - t.Error("deps note not found") - } -} - -// Build a GOPATH package (depBase) into a shared library that links against the goroot -// runtime, another package (dep2) that links against the first, and an -// executable that links against dep2. -func TestTwoGopathShlibs(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase") - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./dep2") - goCmd(t, "install", "-linkshared", "./exe2") - run(t, "executable linked to GOPATH library", "../../bin/exe2") -} - -func TestThreeGopathShlibs(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase") - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./dep2") - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./dep3") - goCmd(t, "install", "-linkshared", "./exe3") - run(t, "executable linked to GOPATH library", "../../bin/exe3") -} - -// If gccgo is not available or not new enough, call t.Skip. -func requireGccgo(t *testing.T) { - t.Helper() - - gccgoName := os.Getenv("GCCGO") - if gccgoName == "" { - gccgoName = "gccgo" - } - gccgoPath, err := exec.LookPath(gccgoName) - if err != nil { - t.Skip("gccgo not found") - } - cmd := exec.Command(gccgoPath, "-dumpversion") - output, err := cmd.CombinedOutput() - if err != nil { - t.Fatalf("%s -dumpversion failed: %v\n%s", gccgoPath, err, output) - } - if string(output) < "5" { - t.Skipf("gccgo too old (%s)", strings.TrimSpace(string(output))) - } - - gomod, err := exec.Command("go", "env", "GOMOD").Output() - if err != nil { - t.Fatalf("go env GOMOD: %v", err) - } - if len(bytes.TrimSpace(gomod)) > 0 { - t.Skipf("gccgo not supported in module mode; see golang.org/issue/30344") - } -} - -// Build a GOPATH package into a shared library with gccgo and an executable that -// links against it. -func TestGoPathShlibGccgo(t *testing.T) { - requireGccgo(t) - - libgoRE := regexp.MustCompile("libgo.so.[0-9]+") - - goCmd(t, "install", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "./depBase") - - // Run 'go list' after 'go install': with gccgo, we apparently don't know the - // shlib location until after we've installed it. - shlib := goCmd(t, "list", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "-f", "{{.Shlib}}", "./depBase") - - AssertIsLinkedToRegexp(t, shlib, libgoRE) - goCmd(t, "install", "-compiler=gccgo", "-linkshared", "./exe") - AssertIsLinkedToRegexp(t, "../../bin/exe", libgoRE) - AssertIsLinkedTo(t, "../../bin/exe", filepath.Base(shlib)) - AssertHasRPath(t, "../../bin/exe", filepath.Dir(shlib)) - // And check it runs. - run(t, "gccgo-built", "../../bin/exe") -} - -// The gccgo version of TestTwoGopathShlibs: build a GOPATH package into a shared -// library with gccgo, another GOPATH package that depends on the first and an -// executable that links the second library. -func TestTwoGopathShlibsGccgo(t *testing.T) { - requireGccgo(t) - - libgoRE := regexp.MustCompile("libgo.so.[0-9]+") - - goCmd(t, "install", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "./depBase") - goCmd(t, "install", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "./dep2") - goCmd(t, "install", "-compiler=gccgo", "-linkshared", "./exe2") - - // Run 'go list' after 'go install': with gccgo, we apparently don't know the - // shlib location until after we've installed it. - dep2 := goCmd(t, "list", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "-f", "{{.Shlib}}", "./dep2") - depBase := goCmd(t, "list", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "-f", "{{.Shlib}}", "./depBase") - - AssertIsLinkedToRegexp(t, depBase, libgoRE) - AssertIsLinkedToRegexp(t, dep2, libgoRE) - AssertIsLinkedTo(t, dep2, filepath.Base(depBase)) - AssertIsLinkedToRegexp(t, "../../bin/exe2", libgoRE) - AssertIsLinkedTo(t, "../../bin/exe2", filepath.Base(dep2)) - AssertIsLinkedTo(t, "../../bin/exe2", filepath.Base(depBase)) - - // And check it runs. - run(t, "gccgo-built", "../../bin/exe2") -} - -// Testing rebuilding of shared libraries when they are stale is a bit more -// complicated that it seems like it should be. First, we make everything "old": but -// only a few seconds old, or it might be older than gc (or the runtime source) and -// everything will get rebuilt. Then define a timestamp slightly newer than this -// time, which is what we set the mtime to of a file to cause it to be seen as new, -// and finally another slightly even newer one that we can compare files against to -// see if they have been rebuilt. -var oldTime = time.Now().Add(-9 * time.Second) -var nearlyNew = time.Now().Add(-6 * time.Second) -var stampTime = time.Now().Add(-3 * time.Second) - -// resetFileStamps makes "everything" (bin, src, pkg from GOPATH and the -// test-specific parts of GOROOT) appear old. -func resetFileStamps() { - chtime := func(path string, info os.FileInfo, err error) error { - return os.Chtimes(path, oldTime, oldTime) - } - reset := func(path string) { - if err := filepath.Walk(path, chtime); err != nil { - log.Panicf("resetFileStamps failed: %v", err) - } - - } - reset("../../bin") - reset("../../pkg") - reset("../../src") - reset(gorootInstallDir) -} - -// touch changes path and returns a function that changes it back. -// It also sets the time of the file, so that we can see if it is rewritten. -func touch(t *testing.T, path string) (cleanup func()) { - t.Helper() - data, err := os.ReadFile(path) - if err != nil { - t.Fatal(err) - } - old := make([]byte, len(data)) - copy(old, data) - if bytes.HasPrefix(data, []byte("!\n")) { - // Change last digit of build ID. - // (Content ID in the new content-based build IDs.) - const marker = `build id "` - i := bytes.Index(data, []byte(marker)) - if i < 0 { - t.Fatal("cannot find build id in archive") - } - j := bytes.IndexByte(data[i+len(marker):], '"') - if j < 0 { - t.Fatal("cannot find build id in archive") - } - i += len(marker) + j - 1 - if data[i] == 'a' { - data[i] = 'b' - } else { - data[i] = 'a' - } - } else { - // assume it's a text file - data = append(data, '\n') - } - - // If the file is still a symlink from an overlay, delete it so that we will - // replace it with a regular file instead of overwriting the symlinked one. - fi, err := os.Lstat(path) - if err == nil && !fi.Mode().IsRegular() { - fi, err = os.Stat(path) - if err := os.Remove(path); err != nil { - t.Fatal(err) - } - } - if err != nil { - t.Fatal(err) - } - - // If we're replacing a symlink to a read-only file, make the new file - // user-writable. - perm := fi.Mode().Perm() | 0200 - - if err := os.WriteFile(path, data, perm); err != nil { - t.Fatal(err) - } - if err := os.Chtimes(path, nearlyNew, nearlyNew); err != nil { - t.Fatal(err) - } - return func() { - if err := os.WriteFile(path, old, perm); err != nil { - t.Fatal(err) - } - } -} - -// isNew returns if the path is newer than the time stamp used by touch. -func isNew(t *testing.T, path string) bool { - t.Helper() - fi, err := os.Stat(path) - if err != nil { - t.Fatal(err) - } - return fi.ModTime().After(stampTime) -} - -// Fail unless path has been rebuilt (i.e. is newer than the time stamp used by -// isNew) -func AssertRebuilt(t *testing.T, msg, path string) { - t.Helper() - if !isNew(t, path) { - t.Errorf("%s was not rebuilt (%s)", msg, path) - } -} - -// Fail if path has been rebuilt (i.e. is newer than the time stamp used by isNew) -func AssertNotRebuilt(t *testing.T, msg, path string) { - t.Helper() - if isNew(t, path) { - t.Errorf("%s was rebuilt (%s)", msg, path) - } -} - -func TestRebuilding(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase") - goCmd(t, "install", "-linkshared", "./exe") - info := strings.Fields(goCmd(t, "list", "-buildmode=shared", "-linkshared", "-f", "{{.Target}} {{.Shlib}}", "./depBase")) - if len(info) != 2 { - t.Fatalf("go list failed to report Target and/or Shlib") - } - target := info[0] - shlib := info[1] - - // If the source is newer than both the .a file and the .so, both are rebuilt. - t.Run("newsource", func(t *testing.T) { - resetFileStamps() - cleanup := touch(t, "./depBase/dep.go") - defer func() { - cleanup() - goCmd(t, "install", "-linkshared", "./exe") - }() - goCmd(t, "install", "-linkshared", "./exe") - AssertRebuilt(t, "new source", target) - AssertRebuilt(t, "new source", shlib) - }) - - // If the .a file is newer than the .so, the .so is rebuilt (but not the .a) - t.Run("newarchive", func(t *testing.T) { - resetFileStamps() - AssertNotRebuilt(t, "new .a file before build", target) - goCmd(t, "list", "-linkshared", "-f={{.ImportPath}} {{.Stale}} {{.StaleReason}} {{.Target}}", "./depBase") - AssertNotRebuilt(t, "new .a file before build", target) - cleanup := touch(t, target) - defer func() { - cleanup() - goCmd(t, "install", "-v", "-linkshared", "./exe") - }() - goCmd(t, "install", "-v", "-linkshared", "./exe") - AssertNotRebuilt(t, "new .a file", target) - AssertRebuilt(t, "new .a file", shlib) - }) -} - -func appendFile(t *testing.T, path, content string) { - t.Helper() - f, err := os.OpenFile(path, os.O_WRONLY|os.O_APPEND, 0660) - if err != nil { - t.Fatalf("os.OpenFile failed: %v", err) - } - defer func() { - err := f.Close() - if err != nil { - t.Fatalf("f.Close failed: %v", err) - } - }() - _, err = f.WriteString(content) - if err != nil { - t.Fatalf("f.WriteString failed: %v", err) - } -} - -func createFile(t *testing.T, path, content string) { - t.Helper() - f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644) - if err != nil { - t.Fatalf("os.OpenFile failed: %v", err) - } - _, err = f.WriteString(content) - if closeErr := f.Close(); err == nil { - err = closeErr - } - if err != nil { - t.Fatalf("WriteString failed: %v", err) - } -} - -func TestABIChecking(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase") - goCmd(t, "install", "-linkshared", "./exe") - - // If we make an ABI-breaking change to depBase and rebuild libp.so but not exe, - // exe will abort with a complaint on startup. - // This assumes adding an exported function breaks ABI, which is not true in - // some senses but suffices for the narrow definition of ABI compatibility the - // toolchain uses today. - resetFileStamps() - - createFile(t, "./depBase/break.go", "package depBase\nfunc ABIBreak() {}\n") - defer os.Remove("./depBase/break.go") - - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase") - c := exec.Command("../../bin/exe") - output, err := c.CombinedOutput() - if err == nil { - t.Fatal("executing exe did not fail after ABI break") - } - scanner := bufio.NewScanner(bytes.NewReader(output)) - foundMsg := false - const wantPrefix = "abi mismatch detected between the executable and lib" - for scanner.Scan() { - if strings.HasPrefix(scanner.Text(), wantPrefix) { - foundMsg = true - break - } - } - if err = scanner.Err(); err != nil { - t.Errorf("scanner encountered error: %v", err) - } - if !foundMsg { - t.Fatalf("exe failed, but without line %q; got output:\n%s", wantPrefix, output) - } - - // Rebuilding exe makes it work again. - goCmd(t, "install", "-linkshared", "./exe") - run(t, "rebuilt exe", "../../bin/exe") - - // If we make a change which does not break ABI (such as adding an unexported - // function) and rebuild libdepBase.so, exe still works, even if new function - // is in a file by itself. - resetFileStamps() - createFile(t, "./depBase/dep2.go", "package depBase\nfunc noABIBreak() {}\n") - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase") - run(t, "after non-ABI breaking change", "../../bin/exe") -} - -// If a package 'explicit' imports a package 'implicit', building -// 'explicit' into a shared library implicitly includes implicit in -// the shared library. Building an executable that imports both -// explicit and implicit builds the code from implicit into the -// executable rather than fetching it from the shared library. The -// link still succeeds and the executable still runs though. -func TestImplicitInclusion(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./explicit") - goCmd(t, "install", "-linkshared", "./implicitcmd") - run(t, "running executable linked against library that contains same package as it", "../../bin/implicitcmd") -} - -// Tests to make sure that the type fields of empty interfaces and itab -// fields of nonempty interfaces are unique even across modules, -// so that interface equality works correctly. -func TestInterface(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./iface_a") - // Note: iface_i gets installed implicitly as a dependency of iface_a. - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./iface_b") - goCmd(t, "install", "-linkshared", "./iface") - run(t, "running type/itab uniqueness tester", "../../bin/iface") -} - -// Access a global variable from a library. -func TestGlobal(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./globallib") - goCmd(t, "install", "-linkshared", "./global") - run(t, "global executable", "../../bin/global") - AssertIsLinkedTo(t, "../../bin/global", soname) - AssertHasRPath(t, "../../bin/global", gorootInstallDir) -} - -// Run a test using -linkshared of an installed shared package. -// Issue 26400. -func TestTestInstalledShared(t *testing.T) { - goCmd(t, "test", "-linkshared", "-test.short", "sync/atomic") -} - -// Test generated pointer method with -linkshared. -// Issue 25065. -func TestGeneratedMethod(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue25065") -} - -// Test use of shared library struct with generated hash function. -// Issue 30768. -func TestGeneratedHash(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue30768/issue30768lib") - goCmd(t, "test", "-linkshared", "./issue30768") -} - -// Test that packages can be added not in dependency order (here a depends on b, and a adds -// before b). This could happen with e.g. go build -buildmode=shared std. See issue 39777. -func TestPackageOrder(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue39777/a", "./issue39777/b") -} - -// Test that GC data are generated correctly by the linker when it needs a type defined in -// a shared library. See issue 39927. -func TestGCData(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./gcdata/p") - goCmd(t, "build", "-linkshared", "./gcdata/main") - runWithEnv(t, "running gcdata/main", []string{"GODEBUG=clobberfree=1"}, "./main") -} - -// Test that we don't decode type symbols from shared libraries (which has no data, -// causing panic). See issue 44031. -func TestIssue44031(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue44031/a") - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue44031/b") - goCmd(t, "run", "-linkshared", "./issue44031/main") -} - -// Test that we use a variable from shared libraries (which implement an -// interface in shared libraries.). A weak reference is used in the itab -// in main process. It can cause unreacheble panic. See issue 47873. -func TestIssue47873(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue47837/a") - goCmd(t, "run", "-linkshared", "./issue47837/main") -} diff --git a/misc/cgo/testshared/testdata/dep2/dep2.go b/misc/cgo/testshared/testdata/dep2/dep2.go deleted file mode 100644 index 94f38cf507..0000000000 --- a/misc/cgo/testshared/testdata/dep2/dep2.go +++ /dev/null @@ -1,15 +0,0 @@ -package dep2 - -import "testshared/depBase" - -var W int = 1 - -var hasProg depBase.HasProg - -type Dep2 struct { - depBase.Dep -} - -func G() int { - return depBase.F() + 1 -} diff --git a/misc/cgo/testshared/testdata/dep3/dep3.go b/misc/cgo/testshared/testdata/dep3/dep3.go deleted file mode 100644 index 6b02ad2ee5..0000000000 --- a/misc/cgo/testshared/testdata/dep3/dep3.go +++ /dev/null @@ -1,22 +0,0 @@ -package dep3 - -// The point of this test file is that it references a type from -// depBase that is also referenced in dep2, but dep2 is loaded by the -// linker before depBase (because it is earlier in the import list). -// There was a bug in the linker where it would not correctly read out -// the type data in this case and later crash. - -import ( - "testshared/dep2" - "testshared/depBase" -) - -type Dep3 struct { - dep depBase.Dep - dep2 dep2.Dep2 -} - -func D3() int { - var x Dep3 - return x.dep.X + x.dep2.X -} diff --git a/misc/cgo/testshared/testdata/depBase/asm.s b/misc/cgo/testshared/testdata/depBase/asm.s deleted file mode 100644 index 0f1111f392..0000000000 --- a/misc/cgo/testshared/testdata/depBase/asm.s +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build gc - -#include "textflag.h" - -TEXT ·ImplementedInAsm(SB),NOSPLIT,$0-0 - RET diff --git a/misc/cgo/testshared/testdata/depBase/dep.go b/misc/cgo/testshared/testdata/depBase/dep.go deleted file mode 100644 index e7cc7c81eb..0000000000 --- a/misc/cgo/testshared/testdata/depBase/dep.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package depBase - -import ( - "os" - "reflect" -) - -var SlicePtr interface{} = &[]int{} - -var V int = 1 - -var HasMask []string = []string{"hi"} - -type HasProg struct { - array [1024]*byte -} - -type Dep struct { - X int -} - -func (d *Dep) Method() int { - // This code below causes various go.itab.* symbols to be generated in - // the shared library. Similar code in ../exe/exe.go results in - // exercising https://golang.org/issues/17594 - reflect.TypeOf(os.Stdout).Elem() - return 10 -} - -func F() int { - defer func() {}() - return V -} diff --git a/misc/cgo/testshared/testdata/depBase/gccgo.go b/misc/cgo/testshared/testdata/depBase/gccgo.go deleted file mode 100644 index 2b02a1e83b..0000000000 --- a/misc/cgo/testshared/testdata/depBase/gccgo.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build gccgo - -package depBase - -func ImplementedInAsm() {} diff --git a/misc/cgo/testshared/testdata/depBase/stubs.go b/misc/cgo/testshared/testdata/depBase/stubs.go deleted file mode 100644 index c77953803b..0000000000 --- a/misc/cgo/testshared/testdata/depBase/stubs.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build gc - -package depBase - -func ImplementedInAsm() diff --git a/misc/cgo/testshared/testdata/division/division.go b/misc/cgo/testshared/testdata/division/division.go deleted file mode 100644 index bb5fc98460..0000000000 --- a/misc/cgo/testshared/testdata/division/division.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package main - -//go:noinline -func div(x, y uint32) uint32 { - return x / y -} - -func main() { - a := div(97, 11) - if a != 8 { - panic("FAIL") - } -} diff --git a/misc/cgo/testshared/testdata/exe/exe.go b/misc/cgo/testshared/testdata/exe/exe.go deleted file mode 100644 index ee95f97bc9..0000000000 --- a/misc/cgo/testshared/testdata/exe/exe.go +++ /dev/null @@ -1,45 +0,0 @@ -package main - -import ( - "os" - "reflect" - "runtime" - - "testshared/depBase" -) - -// Having a function declared in the main package triggered -// golang.org/issue/18250 -func DeclaredInMain() { -} - -type C struct { -} - -func F() *C { - return nil -} - -var slicePtr interface{} = &[]int{} - -func main() { - defer depBase.ImplementedInAsm() - // This code below causes various go.itab.* symbols to be generated in - // the executable. Similar code in ../depBase/dep.go results in - // exercising https://golang.org/issues/17594 - reflect.TypeOf(os.Stdout).Elem() - runtime.GC() - depBase.V = depBase.F() + 1 - - var c *C - if reflect.TypeOf(F).Out(0) != reflect.TypeOf(c) { - panic("bad reflection results, see golang.org/issue/18252") - } - - sp := reflect.New(reflect.TypeOf(slicePtr).Elem()) - s := sp.Interface() - - if reflect.TypeOf(s) != reflect.TypeOf(slicePtr) { - panic("bad reflection results, see golang.org/issue/18729") - } -} diff --git a/misc/cgo/testshared/testdata/exe2/exe2.go b/misc/cgo/testshared/testdata/exe2/exe2.go deleted file mode 100644 index 433f331e36..0000000000 --- a/misc/cgo/testshared/testdata/exe2/exe2.go +++ /dev/null @@ -1,8 +0,0 @@ -package main - -import "testshared/dep2" - -func main() { - d := &dep2.Dep2{} - dep2.W = dep2.G() + 1 + d.Method() -} diff --git a/misc/cgo/testshared/testdata/exe3/exe3.go b/misc/cgo/testshared/testdata/exe3/exe3.go deleted file mode 100644 index 533e3a9e3d..0000000000 --- a/misc/cgo/testshared/testdata/exe3/exe3.go +++ /dev/null @@ -1,7 +0,0 @@ -package main - -import "testshared/dep3" - -func main() { - dep3.D3() -} diff --git a/misc/cgo/testshared/testdata/execgo/exe.go b/misc/cgo/testshared/testdata/execgo/exe.go deleted file mode 100644 index 0427be8bdf..0000000000 --- a/misc/cgo/testshared/testdata/execgo/exe.go +++ /dev/null @@ -1,8 +0,0 @@ -package main - -/* - */ -import "C" - -func main() { -} diff --git a/misc/cgo/testshared/testdata/explicit/explicit.go b/misc/cgo/testshared/testdata/explicit/explicit.go deleted file mode 100644 index af969fcb23..0000000000 --- a/misc/cgo/testshared/testdata/explicit/explicit.go +++ /dev/null @@ -1,9 +0,0 @@ -package explicit - -import ( - "testshared/implicit" -) - -func E() int { - return implicit.I() -} diff --git a/misc/cgo/testshared/testdata/gcdata/main/main.go b/misc/cgo/testshared/testdata/gcdata/main/main.go deleted file mode 100644 index 394862fd94..0000000000 --- a/misc/cgo/testshared/testdata/gcdata/main/main.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Test that GC data is generated correctly for global -// variables with types defined in a shared library. -// See issue 39927. - -// This test run under GODEBUG=clobberfree=1. The check -// *x[i] == 12345 depends on this debug mode to clobber -// the value if the object is freed prematurely. - -package main - -import ( - "fmt" - "runtime" - "testshared/gcdata/p" -) - -var x p.T - -func main() { - for i := range x { - x[i] = new(int) - *x[i] = 12345 - } - runtime.GC() - runtime.GC() - runtime.GC() - for i := range x { - if *x[i] != 12345 { - fmt.Printf("x[%d] == %d, want 12345\n", i, *x[i]) - panic("FAIL") - } - } -} diff --git a/misc/cgo/testshared/testdata/gcdata/p/p.go b/misc/cgo/testshared/testdata/gcdata/p/p.go deleted file mode 100644 index 1fee75429e..0000000000 --- a/misc/cgo/testshared/testdata/gcdata/p/p.go +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package p - -type T [10]*int diff --git a/misc/cgo/testshared/testdata/global/main.go b/misc/cgo/testshared/testdata/global/main.go deleted file mode 100644 index f43e7c3fb3..0000000000 --- a/misc/cgo/testshared/testdata/global/main.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package main - -import ( - "testshared/globallib" -) - -//go:noinline -func testLoop() { - for i, s := range globallib.Data { - if s != int64(i) { - panic("testLoop: mismatch") - } - } -} - -//go:noinline -func ptrData() *[1<<20 + 10]int64 { - return &globallib.Data -} - -//go:noinline -func testMediumOffset() { - for i, s := range globallib.Data[1<<16-2:] { - if s != int64(i)+1<<16-2 { - panic("testMediumOffset: index mismatch") - } - } - - x := globallib.Data[1<<16-1] - if x != 1<<16-1 { - panic("testMediumOffset: direct mismatch") - } - - y := &globallib.Data[1<<16-3] - if y != &ptrData()[1<<16-3] { - panic("testMediumOffset: address mismatch") - } -} - -//go:noinline -func testLargeOffset() { - for i, s := range globallib.Data[1<<20:] { - if s != int64(i)+1<<20 { - panic("testLargeOffset: index mismatch") - } - } - - x := globallib.Data[1<<20+1] - if x != 1<<20+1 { - panic("testLargeOffset: direct mismatch") - } - - y := &globallib.Data[1<<20+2] - if y != &ptrData()[1<<20+2] { - panic("testLargeOffset: address mismatch") - } -} - -func main() { - testLoop() - - // SSA rules commonly merge offsets into addresses. These - // tests access global data in different ways to try - // and exercise different SSA rules. - testMediumOffset() - testLargeOffset() -} diff --git a/misc/cgo/testshared/testdata/globallib/global.go b/misc/cgo/testshared/testdata/globallib/global.go deleted file mode 100644 index b4372a2e9e..0000000000 --- a/misc/cgo/testshared/testdata/globallib/global.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package globallib - -// Data is large enough to that offsets into it do not fit into -// 16-bit or 20-bit immediates. Ideally we'd also try and overrun -// 32-bit immediates, but that requires the test machine to have -// too much memory. -var Data [1<<20 + 10]int64 - -func init() { - for i := range Data { - Data[i] = int64(i) - } -} diff --git a/misc/cgo/testshared/testdata/iface/main.go b/misc/cgo/testshared/testdata/iface/main.go deleted file mode 100644 index d26ebbcc9c..0000000000 --- a/misc/cgo/testshared/testdata/iface/main.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package main - -import "testshared/iface_a" -import "testshared/iface_b" - -func main() { - if iface_a.F() != iface_b.F() { - panic("empty interfaces not equal") - } - if iface_a.G() != iface_b.G() { - panic("non-empty interfaces not equal") - } -} diff --git a/misc/cgo/testshared/testdata/iface_a/a.go b/misc/cgo/testshared/testdata/iface_a/a.go deleted file mode 100644 index e2cef1ecda..0000000000 --- a/misc/cgo/testshared/testdata/iface_a/a.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package iface_a - -import "testshared/iface_i" - -//go:noinline -func F() interface{} { - return (*iface_i.T)(nil) -} - -//go:noinline -func G() iface_i.I { - return (*iface_i.T)(nil) -} diff --git a/misc/cgo/testshared/testdata/iface_b/b.go b/misc/cgo/testshared/testdata/iface_b/b.go deleted file mode 100644 index dd3e027b37..0000000000 --- a/misc/cgo/testshared/testdata/iface_b/b.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package iface_b - -import "testshared/iface_i" - -//go:noinline -func F() interface{} { - return (*iface_i.T)(nil) -} - -//go:noinline -func G() iface_i.I { - return (*iface_i.T)(nil) -} diff --git a/misc/cgo/testshared/testdata/iface_i/i.go b/misc/cgo/testshared/testdata/iface_i/i.go deleted file mode 100644 index 31c80387c7..0000000000 --- a/misc/cgo/testshared/testdata/iface_i/i.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package iface_i - -type I interface { - M() -} - -type T struct { -} - -func (t *T) M() { -} - -// *T implements I diff --git a/misc/cgo/testshared/testdata/implicit/implicit.go b/misc/cgo/testshared/testdata/implicit/implicit.go deleted file mode 100644 index 5360188c56..0000000000 --- a/misc/cgo/testshared/testdata/implicit/implicit.go +++ /dev/null @@ -1,5 +0,0 @@ -package implicit - -func I() int { - return 42 -} diff --git a/misc/cgo/testshared/testdata/implicitcmd/implicitcmd.go b/misc/cgo/testshared/testdata/implicitcmd/implicitcmd.go deleted file mode 100644 index 4d4296738e..0000000000 --- a/misc/cgo/testshared/testdata/implicitcmd/implicitcmd.go +++ /dev/null @@ -1,10 +0,0 @@ -package main - -import ( - "testshared/explicit" - "testshared/implicit" -) - -func main() { - println(implicit.I() + explicit.E()) -} diff --git a/misc/cgo/testshared/testdata/issue25065/a.go b/misc/cgo/testshared/testdata/issue25065/a.go deleted file mode 100644 index 979350ff24..0000000000 --- a/misc/cgo/testshared/testdata/issue25065/a.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package issue25065 has a type with a method that is -// 1) referenced in a method expression -// 2) not called -// 3) not converted to an interface -// 4) is a value method but the reference is to the pointer method -// These cases avoid the call to makefuncsym from typecheckfunc, but we -// still need to call makefuncsym somehow or the symbol will not be defined. -package issue25065 - -type T int - -func (t T) M() {} - -func F() func(*T) { - return (*T).M -} diff --git a/misc/cgo/testshared/testdata/issue30768/issue30768lib/lib.go b/misc/cgo/testshared/testdata/issue30768/issue30768lib/lib.go deleted file mode 100644 index 9e45ebe683..0000000000 --- a/misc/cgo/testshared/testdata/issue30768/issue30768lib/lib.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package issue30768lib - -// S is a struct that requires a generated hash function. -type S struct { - A string - B int -} diff --git a/misc/cgo/testshared/testdata/issue30768/x_test.go b/misc/cgo/testshared/testdata/issue30768/x_test.go deleted file mode 100644 index 1bbd139d3e..0000000000 --- a/misc/cgo/testshared/testdata/issue30768/x_test.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package issue30768_test - -import ( - "testing" - - "testshared/issue30768/issue30768lib" -) - -type s struct { - s issue30768lib.S -} - -func Test30768(t *testing.T) { - // Calling t.Log will convert S to an empty interface, - // which will force a reference to the generated hash function, - // defined in the shared library. - t.Log(s{}) -} diff --git a/misc/cgo/testshared/testdata/issue39777/a/a.go b/misc/cgo/testshared/testdata/issue39777/a/a.go deleted file mode 100644 index c7bf835951..0000000000 --- a/misc/cgo/testshared/testdata/issue39777/a/a.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package a - -import "testshared/issue39777/b" - -func F() { b.F() } diff --git a/misc/cgo/testshared/testdata/issue39777/b/b.go b/misc/cgo/testshared/testdata/issue39777/b/b.go deleted file mode 100644 index 4e681965e6..0000000000 --- a/misc/cgo/testshared/testdata/issue39777/b/b.go +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package b - -func F() {} diff --git a/misc/cgo/testshared/testdata/issue44031/a/a.go b/misc/cgo/testshared/testdata/issue44031/a/a.go deleted file mode 100644 index 48827e682f..0000000000 --- a/misc/cgo/testshared/testdata/issue44031/a/a.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package a - -type ATypeWithALoooooongName interface { // a long name, so the type descriptor symbol name is mangled - M() -} diff --git a/misc/cgo/testshared/testdata/issue44031/b/b.go b/misc/cgo/testshared/testdata/issue44031/b/b.go deleted file mode 100644 index ad3ebec2b9..0000000000 --- a/misc/cgo/testshared/testdata/issue44031/b/b.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package b - -import "testshared/issue44031/a" - -type T int - -func (T) M() {} - -var i = a.ATypeWithALoooooongName(T(0)) - -func F() { - i.M() -} diff --git a/misc/cgo/testshared/testdata/issue44031/main/main.go b/misc/cgo/testshared/testdata/issue44031/main/main.go deleted file mode 100644 index 47f2e3a98e..0000000000 --- a/misc/cgo/testshared/testdata/issue44031/main/main.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package main - -import "testshared/issue44031/b" - -type t int - -func (t) m() {} - -type i interface{ m() } // test that unexported method is correctly marked - -var v interface{} = t(0) - -func main() { - b.F() - v.(i).m() -} diff --git a/misc/cgo/testshared/testdata/issue47837/a/a.go b/misc/cgo/testshared/testdata/issue47837/a/a.go deleted file mode 100644 index 68588eda2f..0000000000 --- a/misc/cgo/testshared/testdata/issue47837/a/a.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package a - -type A interface { - M() -} - -//go:noinline -func TheFuncWithArgA(a A) { - a.M() -} - -type ImplA struct{} - -//go:noinline -func (A *ImplA) M() {} diff --git a/misc/cgo/testshared/testdata/issue47837/main/main.go b/misc/cgo/testshared/testdata/issue47837/main/main.go deleted file mode 100644 index 77c6f34379..0000000000 --- a/misc/cgo/testshared/testdata/issue47837/main/main.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package main - -import ( - "testshared/issue47837/a" -) - -func main() { - var vara a.ImplA - a.TheFuncWithArgA(&vara) -} diff --git a/misc/cgo/testshared/testdata/trivial/trivial.go b/misc/cgo/testshared/testdata/trivial/trivial.go deleted file mode 100644 index 6ade47ce36..0000000000 --- a/misc/cgo/testshared/testdata/trivial/trivial.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -func main() { - // This is enough to make sure that the executable references - // a type descriptor, which was the cause of - // https://golang.org/issue/25970. - c := make(chan int) - _ = c -} diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index 5935011e19..87238cc74f 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -762,9 +762,6 @@ func (t *tester) registerTests() { if t.supportedBuildmode("c-shared") { t.registerHostTest("testcshared", "../misc/cgo/testcshared", "misc/cgo/testcshared", ".") } - if t.supportedBuildmode("shared") { - t.registerTest("testshared", "../misc/cgo/testshared", t.goTest(), t.timeout(600), ".") - } if t.supportedBuildmode("plugin") { t.registerTest("testplugin", "../misc/cgo/testplugin", t.goTest(), t.timeout(600), ".") } @@ -1047,12 +1044,6 @@ func (t *tester) supportedBuildmode(mode string) bool { return true } return false - case "shared": - switch pair { - case "linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le", "linux-s390x": - return true - } - return false case "plugin": // linux-arm64 is missing because it causes the external linker // to crash, see https://golang.org/issue/17138 diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 9d8c321307..685ccac826 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -162,9 +162,6 @@ // flags has a similar effect. // -ldflags '[pattern=]arg list' // arguments to pass on each go tool link invocation. -// -linkshared -// build code that will be linked against shared libraries previously -// created with -buildmode=shared. // -mod mode // module download mode to use: readonly, vendor, or mod. // By default, if a vendor directory is present and the go version in go.mod @@ -778,7 +775,6 @@ // Name string // package name // Doc string // package documentation string // Target string // install path -// Shlib string // the shared library that contains this package (only set when -linkshared) // Goroot bool // is this package in the Go root? // Standard bool // is this package part of the standard Go library? // Stale bool // would 'go install' do anything for this package? @@ -1799,11 +1795,6 @@ // non-main packages are built into .a files (the default // behavior). // -// -buildmode=shared -// Combine all the listed non-main packages into a single shared -// library that will be used when building with the -linkshared -// option. Packages named main are ignored. -// // -buildmode=exe // Build the listed main packages and everything they import into // executables. Packages not named main are ignored. diff --git a/src/cmd/go/internal/help/helpdoc.go b/src/cmd/go/internal/help/helpdoc.go index 035235fe1b..2bb3584eba 100644 --- a/src/cmd/go/internal/help/helpdoc.go +++ b/src/cmd/go/internal/help/helpdoc.go @@ -726,11 +726,6 @@ are: non-main packages are built into .a files (the default behavior). - -buildmode=shared - Combine all the listed non-main packages into a single shared - library that will be used when building with the -linkshared - option. Packages named main are ignored. - -buildmode=exe Build the listed main packages and everything they import into executables. Packages not named main are ignored. diff --git a/src/cmd/go/internal/list/list.go b/src/cmd/go/internal/list/list.go index 8c85ddcf21..f23fbe5fea 100644 --- a/src/cmd/go/internal/list/list.go +++ b/src/cmd/go/internal/list/list.go @@ -23,8 +23,8 @@ import ( "cmd/go/internal/load" "cmd/go/internal/modinfo" "cmd/go/internal/modload" - "cmd/go/internal/work" "cmd/go/internal/str" + "cmd/go/internal/work" ) var CmdList = &base.Command{ @@ -56,7 +56,6 @@ to -f '{{.ImportPath}}'. The struct being passed to the template is: Name string // package name Doc string // package documentation string Target string // install path - Shlib string // the shared library that contains this package (only set when -linkshared) Goroot bool // is this package in the Go root? Standard bool // is this package part of the standard Go library? Stale bool // would 'go install' do anything for this package? diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go index 9d0ad27f0d..e39ffcbd50 100644 --- a/src/cmd/go/internal/work/build.go +++ b/src/cmd/go/internal/work/build.go @@ -116,9 +116,6 @@ and test commands: flags has a similar effect. -ldflags '[pattern=]arg list' arguments to pass on each go tool link invocation. - -linkshared - build code that will be linked against shared libraries previously - created with -buildmode=shared. -mod mode module download mode to use: readonly, vendor, or mod. By default, if a vendor directory is present and the go version in go.mod diff --git a/src/cmd/go/internal/work/init.go b/src/cmd/go/internal/work/init.go index 4dbbd2a13f..b2ee00d53c 100644 --- a/src/cmd/go/internal/work/init.go +++ b/src/cmd/go/internal/work/init.go @@ -246,16 +246,20 @@ func buildModeInit() { } ldBuildmode = "pie" case "shared": - pkgsFilter = pkgsNotMain - if gccgo { - codegenArg = "-fPIC" - } else { - codegenArg = "-dynlink" - } - if cfg.BuildO != "" { - base.Fatalf("-buildmode=shared and -o not supported together") + if cfg.Goos == "linux" { + switch cfg.Goarch { + case "386", "amd64", "arm", "arm64", "ppc64le", "s390x": + // -buildmode=shared was supported on these platforms at one point, but + // never really worked in module mode. + // Support was officially dropped as of Go 1.18. + // (See https://golang.org/issue/47788.) + base.Fatalf("-buildmode=shared no longer supported as of Go 1.18") + + // TODO(#47788): Remove supporting code for -buildmode=shared. + // (For the Go 1.18 release, we will keep most of the code around but + // disabled to avoid merge conflicts in case we need to revert quickly.) + } } - ldBuildmode = "shared" case "plugin": pkgsFilter = oneMainPkg if gccgo { @@ -274,6 +278,15 @@ func buildModeInit() { } if cfg.BuildLinkshared { + if cfg.Goos == "linux" { + switch cfg.Goarch { + case "386", "amd64", "arm", "arm64", "ppc64le", "s390x": + base.Fatalf("-linkshared no longer supported as of Go 1.18") + // TODO(#47788): Remove supporting code for linkshared. + // (For the Go 1.18 release, we will keep most of the code around but + // disabled to avoid merge conflicts in case we need to revert quickly.) + } + } if !sys.BuildModeSupported(cfg.BuildToolchainName, "shared", cfg.Goos, cfg.Goarch) { base.Fatalf("-linkshared not supported on %s/%s\n", cfg.Goos, cfg.Goarch) } diff --git a/src/cmd/go/testdata/script/list_linkshared.txt b/src/cmd/go/testdata/script/list_linkshared.txt deleted file mode 100644 index baae1e2be8..0000000000 --- a/src/cmd/go/testdata/script/list_linkshared.txt +++ /dev/null @@ -1,16 +0,0 @@ -env GO111MODULE=on - -# golang.org/issue/35759: 'go list -linkshared' -# panicked if invoked on a test-only package. - -[!buildmode:shared] skip - -go list -f '{{.ImportPath}}: {{.Target}} {{.Shlib}}' -linkshared . -stdout '^example.com: $' - --- go.mod -- -module example.com - -go 1.14 --- x.go -- -package x diff --git a/src/cmd/internal/sys/supported.go b/src/cmd/internal/sys/supported.go index e6c56fbc56..473e390587 100644 --- a/src/cmd/internal/sys/supported.go +++ b/src/cmd/internal/sys/supported.go @@ -109,13 +109,6 @@ func BuildModeSupported(compiler, buildmode, goos, goarch string) bool { } return false - case "shared": - switch platform { - case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x": - return true - } - return false - case "plugin": switch platform { case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/s390x", "linux/ppc64le", -- GitLab From 3f1b0ce6bb4f2e7d44791c5532728f86e24f1f1f Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 25 Oct 2021 09:13:16 -0700 Subject: [PATCH 1769/2500] cmd/compile/internal/types2: clarify is/underIs semantics and implementation The behavior of is/underIs was murky with the presence of a top type term (corresponding to a type set that is not constrained by any types, yet the function argument f of is/underIs was called with that term). Change is/underIs to call f explicitly for existing specific type terms, otherwise return the result of f(nil). Review all uses of is/underIs and variants. This makes the conversion code slightly more complicated because we need to explicitly exclude type parameters without specific types; but the code is clearer now. Change-Id: I6115cb46f7f2a8d0f54799aafff9a67c4cca5e30 Reviewed-on: https://go-review.googlesource.com/c/go/+/358594 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/builtins.go | 5 +- .../compile/internal/types2/conversions.go | 11 ++++- src/cmd/compile/internal/types2/expr.go | 2 + src/cmd/compile/internal/types2/infer.go | 2 +- src/cmd/compile/internal/types2/operand.go | 3 ++ src/cmd/compile/internal/types2/typeparam.go | 11 +++++ src/cmd/compile/internal/types2/typeset.go | 46 ++++++++++--------- 7 files changed, 54 insertions(+), 26 deletions(-) diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 37e1f00d26..318894b69b 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -834,7 +834,10 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { // Test if t satisfies the requirements for the argument // type and collect possible result types at the same time. var terms []*Term - if !tp.iface().typeSet().is(func(t *term) bool { + if !tp.is(func(t *term) bool { + if t == nil { + return false + } if r := f(t.typ); r != nil { terms = append(terms, NewTerm(t.tilde, r)) return true diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go index a4fba28fce..8389770ce5 100644 --- a/src/cmd/compile/internal/types2/conversions.go +++ b/src/cmd/compile/internal/types2/conversions.go @@ -20,7 +20,7 @@ func (check *Checker) conversion(x *operand, T Type) { var cause string switch { case constArg && isConstType(T): - // constant conversion + // constant conversion (T cannot be a type parameter) switch t := asBasic(T); { case representableConst(x.val, check, t, &x.val): ok = true @@ -94,8 +94,15 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { return true } + // determine type parameter operands with specific type terms Vp, _ := under(x.typ).(*TypeParam) Tp, _ := under(T).(*TypeParam) + if Vp != nil && !Vp.hasTerms() { + Vp = nil + } + if Tp != nil && !Tp.hasTerms() { + Tp = nil + } errorf := func(format string, args ...interface{}) { if check != nil && cause != nil { @@ -107,7 +114,7 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { } } - // generic cases + // generic cases with specific type terms // (generic operands cannot be constants, so we can ignore x.val) switch { case Vp != nil && Tp != nil: diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 3a39de7406..9afe3b7f01 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -155,6 +155,8 @@ var op2str2 = [...]string{ syntax.Shl: "shift", } +// If typ is a type parameter, underIs returns the result of typ.underIs(f). +// Otherwise, underIs returns the result of f(under(typ)). func underIs(typ Type, f func(Type) bool) bool { u := under(typ) if tpar, _ := u.(*TypeParam); tpar != nil { diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index ad8c6ac412..142ae6cb33 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -320,7 +320,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { } } return tset.is(func(t *term) bool { - return w.isParameterized(t.typ) + return t != nil && w.isParameterized(t.typ) }) case *Map: diff --git a/src/cmd/compile/internal/types2/operand.go b/src/cmd/compile/internal/types2/operand.go index 5c8654dbf1..69426f4d03 100644 --- a/src/cmd/compile/internal/types2/operand.go +++ b/src/cmd/compile/internal/types2/operand.go @@ -273,6 +273,9 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er if t, ok := under(T).(*TypeParam); ok { return t.is(func(t *term) bool { // TODO(gri) this could probably be more efficient + if t == nil { + return false + } if t.tilde { // TODO(gri) We need to check assignability // for the underlying type of x. diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index f7cdff0180..75e2fe8f0e 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -119,10 +119,21 @@ func (t *TypeParam) structuralType() Type { return t.iface().typeSet().structuralType() } +// hasTerms reports whether the type parameter constraint has specific type terms. +func (t *TypeParam) hasTerms() bool { + return t.iface().typeSet().hasTerms() +} + +// is calls f with the specific type terms of t's constraint and reports whether +// all calls to f returned true. If there are no specific terms, is +// returns the result of f(nil). func (t *TypeParam) is(f func(*term) bool) bool { return t.iface().typeSet().is(f) } +// underIs calls f with the underlying types of the specific type terms +// of t's constraint and reports whether all calls to f returned true. +// If there are no specific terms, underIs returns the result of f(nil). func (t *TypeParam) underIs(f func(Type) bool) bool { return t.iface().typeSet().underIs(f) } diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index f9e3af7ba8..c99d02744b 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -39,7 +39,7 @@ func (s *_TypeSet) IsComparable() bool { return s.comparable } return s.is(func(t *term) bool { - return Comparable(t.typ) + return t != nil && Comparable(t.typ) }) } @@ -101,27 +101,29 @@ func (s *_TypeSet) String() string { // ---------------------------------------------------------------------------- // Implementation -func (s *_TypeSet) hasTerms() bool { return !s.terms.isEmpty() && !s.terms.isAll() } -func (s *_TypeSet) structuralType() Type { return s.terms.structuralType() } -func (s *_TypeSet) includes(t Type) bool { return s.terms.includes(t) } +// hasTerms reports whether the type set has specific type terms. +func (s *_TypeSet) hasTerms() bool { return !s.terms.isEmpty() && !s.terms.isAll() } + +// structuralType returns the single type in s if there is exactly one; otherwise the result is nil. +func (s *_TypeSet) structuralType() Type { return s.terms.structuralType() } + +// includes reports whether t ∈ s. +func (s *_TypeSet) includes(t Type) bool { return s.terms.includes(t) } + +// subsetOf reports whether s1 ⊆ s2. func (s1 *_TypeSet) subsetOf(s2 *_TypeSet) bool { return s1.terms.subsetOf(s2.terms) } // TODO(gri) TypeSet.is and TypeSet.underIs should probably also go into termlist.go -var topTerm = term{false, theTop} - +// is calls f with the specific type terms of s and reports whether +// all calls to f returned true. If there are no specific terms, is +// returns the result of f(nil). func (s *_TypeSet) is(f func(*term) bool) bool { - if len(s.terms) == 0 { - return false + if !s.hasTerms() { + return f(nil) } for _, t := range s.terms { - // Terms represent the top term with a nil type. - // The rest of the type checker uses the top type - // instead. Convert. - // TODO(gri) investigate if we can do without this - if t.typ == nil { - t = &topTerm - } + assert(t.typ != nil) if !f(t) { return false } @@ -129,17 +131,17 @@ func (s *_TypeSet) is(f func(*term) bool) bool { return true } +// underIs calls f with the underlying types of the specific type terms +// of s and reports whether all calls to f returned true. If there are +// no specific terms, is returns the result of f(nil). func (s *_TypeSet) underIs(f func(Type) bool) bool { - if len(s.terms) == 0 { - return false + if !s.hasTerms() { + return f(nil) } for _, t := range s.terms { - // see corresponding comment in TypeSet.is + assert(t.typ != nil) + // x == under(x) for ~x terms u := t.typ - if u == nil { - u = theTop - } - // t == under(t) for ~t terms if !t.tilde { u = under(u) } -- GitLab From 56dcf976561ff6c666d9d1fe6231557ac2072883 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 22 Oct 2021 09:49:15 -0700 Subject: [PATCH 1770/2500] cmd/compile/internal/types2: generalize assignability to generic types Similar to conversions, handle ordinary cases first, followed by type-by-type assignability tests in case of type parameters with specific types in their type sets. Add a new class of type checker tests, in testdata/spec, which I hope we can populate over time with tests following the spec organization. Moved the conversions.go2 tests in the same dir. Change-Id: Iac253ae375c08022bdc39e92e3951ec3f509e432 Reviewed-on: https://go-review.googlesource.com/c/go/+/357917 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/check_test.go | 1 + src/cmd/compile/internal/types2/operand.go | 107 ++++++-- .../types2/testdata/spec/assignability.go2 | 234 ++++++++++++++++++ .../{examples => spec}/conversions.go2 | 0 4 files changed, 316 insertions(+), 26 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/spec/assignability.go2 rename src/cmd/compile/internal/types2/testdata/{examples => spec}/conversions.go2 (100%) diff --git a/src/cmd/compile/internal/types2/check_test.go b/src/cmd/compile/internal/types2/check_test.go index e71df87f2c..d4c7b7b39b 100644 --- a/src/cmd/compile/internal/types2/check_test.go +++ b/src/cmd/compile/internal/types2/check_test.go @@ -278,6 +278,7 @@ func TestManual(t *testing.T) { // TODO(gri) go/types has extra TestLongConstants and TestIndexRepresentability tests func TestCheck(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/check", 75, false) } // TODO(gri) narrow column tolerance +func TestSpec(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/spec", 0, false) } func TestExamples(t *testing.T) { testDirFiles(t, "testdata/examples", 0, false) } func TestFixedbugs(t *testing.T) { testDirFiles(t, "testdata/fixedbugs", 0, false) } diff --git a/src/cmd/compile/internal/types2/operand.go b/src/cmd/compile/internal/types2/operand.go index 69426f4d03..92ae0a95fc 100644 --- a/src/cmd/compile/internal/types2/operand.go +++ b/src/cmd/compile/internal/types2/operand.go @@ -249,53 +249,46 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er V := x.typ - const debugAssignableTo = false - if debugAssignableTo && check != nil { - check.dump("V = %s", V) - check.dump("T = %s", T) - } - // x's type is identical to T if Identical(V, T) { return true, 0 } - Vu := optype(V) - Tu := optype(T) - - if debugAssignableTo && check != nil { - check.dump("Vu = %s", Vu) - check.dump("Tu = %s", Tu) - } + Vu := under(V) + Tu := under(T) + Vp, _ := Vu.(*TypeParam) + Tp, _ := Tu.(*TypeParam) // x is an untyped value representable by a value of type T. if isUntyped(Vu) { - if t, ok := under(T).(*TypeParam); ok { - return t.is(func(t *term) bool { - // TODO(gri) this could probably be more efficient + assert(Vp == nil) + if Tp != nil { + // T is a type parameter: x is assignable to T if it is + // representable by each specific type in the type set of T. + return Tp.is(func(t *term) bool { if t == nil { return false } - if t.tilde { - // TODO(gri) We need to check assignability - // for the underlying type of x. - } - ok, _ := x.assignableTo(check, t.typ, reason) - return ok + // A term may be a tilde term but the underlying + // type of an untyped value doesn't change so we + // don't need to do anything special. + newType, _, _ := check.implicitTypeAndValue(x, t.typ) + return newType != nil }), _IncompatibleAssign } - newType, _, _ := check.implicitTypeAndValue(x, Tu) + newType, _, _ := check.implicitTypeAndValue(x, T) return newType != nil, _IncompatibleAssign } // Vu is typed // x's type V and T have identical underlying types // and at least one of V or T is not a named type - if Identical(Vu, Tu) && (!isNamed(V) || !isNamed(T)) { + // and neither is a type parameter. + if Identical(Vu, Tu) && (!isNamed(V) || !isNamed(T)) && Vp == nil && Tp == nil { return true, 0 } - // T is an interface type and x implements T + // T is an interface type and x implements T and T is not a type parameter if Ti, ok := Tu.(*Interface); ok { if m, wrongType := check.missingMethod(V, Ti, true); m != nil /* Implements(V, Ti) */ { if reason != nil { @@ -325,7 +318,69 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er } } - return false, _IncompatibleAssign + // common case: if we don't have type parameters, we're done + if Vp == nil && Tp == nil { + return false, _IncompatibleAssign + } + + // determine type parameter operands with specific type terms + if Vp != nil && !Vp.hasTerms() { + Vp = nil + } + if Tp != nil && !Tp.hasTerms() { + Tp = nil + } + + errorf := func(format string, args ...interface{}) { + if check != nil && reason != nil { + msg := check.sprintf(format, args...) + if *reason != "" { + msg += "\n\t" + *reason + } + *reason = msg + } + } + + ok := false + code := _IncompatibleAssign + switch { + case Vp != nil && Tp != nil: + x := *x // don't clobber outer x + ok = Vp.is(func(V *term) bool { + x.typ = V.typ + return Tp.is(func(T *term) bool { + ok, code = x.assignableTo(check, T.typ, reason) + if !ok { + errorf("cannot assign %s (in %s) to %s (in %s)", V.typ, Vp, T.typ, Tp) + return false + } + return true + }) + }) + case Vp != nil: + x := *x // don't clobber outer x + ok = Vp.is(func(V *term) bool { + x.typ = V.typ + ok, code = x.assignableTo(check, T, reason) + if !ok { + errorf("cannot assign %s (in %s) to %s", V.typ, Vp, T) + return false + } + return true + }) + case Tp != nil: + x := *x // don't clobber outer x + ok = Tp.is(func(T *term) bool { + ok, code = x.assignableTo(check, T.typ, reason) + if !ok { + errorf("cannot assign %s to %s (in %s)", x.typ, T.typ, Tp) + return false + } + return true + }) + } + + return ok, code } // kind2tok translates syntax.LitKinds into token.Tokens. diff --git a/src/cmd/compile/internal/types2/testdata/spec/assignability.go2 b/src/cmd/compile/internal/types2/testdata/spec/assignability.go2 new file mode 100644 index 0000000000..1507cabb1d --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/spec/assignability.go2 @@ -0,0 +1,234 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package assignability + +// See the end of this package for the declarations +// of the types and variables used in these tests. + +// "x's type is identical to T" +func _[TP any](X TP) { + b = b + a = a + l = l + s = s + p = p + f = f + i = i + m = m + c = c + d = d + + B = B + A = A + L = L + S = S + P = P + F = F + I = I + M = M + C = C + D = D + X = X +} + +// "x's type V and T have identical underlying types and at least one +// of V or T is not a defined type and neither is a type parameter" +func _[TP1, TP2 Interface](X1 TP1, X2 TP2) { + b = B // ERROR cannot use B .* as int value + a = A + l = L + s = S + p = P + f = F + i = I + m = M + c = C + d = D + + B = b // ERROR cannot use b .* as Basic value + A = a + L = l + S = s + P = p + F = f + I = i + M = m + C = c + D = d + X1 = i // ERROR cannot use i .* as TP1 value + X1 = X2 // ERROR cannot use X2 .* as TP1 value +} + +// "T is an interface type and x implements T and T is not a type parameter" +func _[TP Interface](X TP) { + i = d // ERROR missing method m + i = D + i = X + X = i // ERROR cannot use i .* as TP value +} + +// "x is a bidirectional channel value, T is a channel type, x's type V and T have identical element types, and at least one of V or T is not a defined type" +type ( + _SendChan = chan<- int + _RecvChan = <-chan int + + SendChan _SendChan + RecvChan _RecvChan +) + +func _[ + _CC ~_Chan, + _SC ~_SendChan, + _RC ~_RecvChan, + + CC Chan, + SC SendChan, + RC RecvChan, +]() { + var ( + _ _SendChan = c + _ _RecvChan = c + _ _Chan = c + + _ _SendChan = C + _ _RecvChan = C + _ _Chan = C + + _ SendChan = c + _ RecvChan = c + _ Chan = c + + _ SendChan = C // ERROR cannot use C .* as SendChan value + _ RecvChan = C // ERROR cannot use C .* as RecvChan value + _ Chan = C + _ Chan = make /* ERROR cannot use make\(chan Basic\) .* as Chan value */ (chan Basic) + ) + + var ( + _ _CC = C + _ _SC = C + _ _RC = C + + _ CC = _CC(nil) + _ SC = _CC(nil) + _ RC = _CC(nil) + + _ CC = C + _ SC = C // ERROR cannot use C .* as SC value .* cannot assign Chan to SendChan + _ RC = C // ERROR cannot use C .* as RC value .* cannot assign Chan to RecvChan + ) +} + +// "x is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type" +func _[TP Interface](X TP) { + b = nil // ERROR cannot use untyped nil + a = nil // ERROR cannot use untyped nil + l = nil + s = nil // ERROR cannot use untyped nil + p = nil + f = nil + i = nil + m = nil + c = nil + d = nil // ERROR cannot use untyped nil + + B = nil // ERROR cannot use untyped nil + A = nil // ERROR cannot use untyped nil + L = nil + S = nil // ERROR cannot use untyped nil + P = nil + F = nil + I = nil + M = nil + C = nil + D = nil // ERROR cannot use untyped nil + X = nil // ERROR cannot use untyped nil +} + +// "x is an untyped constant representable by a value of type T" +func _[ + Int8 ~int8, + Int16 ~int16, + Int32 ~int32, + Int64 ~int64, + Int8_16 ~int8 | ~int16, +]( + i8 Int8, + i16 Int16, + i32 Int32, + i64 Int64, + i8_16 Int8_16, +) { + b = 42 + b = 42.0 + // etc. + + i8 = -1 << 7 + i8 = 1<<7 - 1 + i16 = -1 << 15 + i16 = 1<<15 - 1 + i32 = -1 << 31 + i32 = 1<<31 - 1 + i64 = -1 << 63 + i64 = 1<<63 - 1 + + i8_16 = -1 << 7 + i8_16 = 1<<7 - 1 + i8_16 = - /* ERROR cannot use .* as Int8_16 */ 1 << 15 + i8_16 = 1 /* ERROR cannot use .* as Int8_16 */ <<15 - 1 +} + +// proto-types for tests + +type ( + _Basic = int + _Array = [10]int + _Slice = []int + _Struct = struct{ f int } + _Pointer = *int + _Func = func(x int) string + _Interface = interface{ m() int } + _Map = map[string]int + _Chan = chan int + + Basic _Basic + Array _Array + Slice _Slice + Struct _Struct + Pointer _Pointer + Func _Func + Interface _Interface + Map _Map + Chan _Chan + Defined _Struct +) + +func (Defined) m() int + +// proto-variables for tests + +var ( + b _Basic + a _Array + l _Slice + s _Struct + p _Pointer + f _Func + i _Interface + m _Map + c _Chan + d _Struct + + B Basic + A Array + L Slice + S Struct + P Pointer + F Func + I Interface + M Map + C Chan + D Defined +) diff --git a/src/cmd/compile/internal/types2/testdata/examples/conversions.go2 b/src/cmd/compile/internal/types2/testdata/spec/conversions.go2 similarity index 100% rename from src/cmd/compile/internal/types2/testdata/examples/conversions.go2 rename to src/cmd/compile/internal/types2/testdata/spec/conversions.go2 -- GitLab From d611f092001f76942251f68023dba137b8a3e821 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 25 Oct 2021 17:22:55 -0700 Subject: [PATCH 1771/2500] cmd/compile/internal/types2: clean up asT converters (step 1 of 2) This CL changes the convenience converters asT to use under instead of optype. To make sure the effect is well understood, in a first step, all asT functions are renamed to toT so that we can see which call sites are affected. In almost all places, the change is what we want. In some places we may get more conservative behavior (which is easy to relax if need be). In some places (function calls through a type parameter, append built-in) we now use singleUnder instead, for a more general behavior, matching other primary expressions or built- ins. This change removes the last use of optype and thus also theTop and top, all of which have been deleted from the code. The next CL renames the toT converters back to their asT form. Change-Id: I35d1ad866ce46de175a055b36ef577d99bb9de22 Reviewed-on: https://go-review.googlesource.com/c/go/+/358597 Trust: Robert Griesemer Reviewed-by: Robert Findley --- .../compile/internal/types2/assignments.go | 2 +- src/cmd/compile/internal/types2/builtins.go | 29 +++-- src/cmd/compile/internal/types2/call.go | 7 +- .../compile/internal/types2/conversions.go | 24 +++-- src/cmd/compile/internal/types2/expr.go | 8 +- src/cmd/compile/internal/types2/index.go | 6 +- src/cmd/compile/internal/types2/infer.go | 4 +- src/cmd/compile/internal/types2/lookup.go | 8 +- src/cmd/compile/internal/types2/predicates.go | 10 +- .../compile/internal/types2/sizeof_test.go | 1 - src/cmd/compile/internal/types2/sizes.go | 2 +- src/cmd/compile/internal/types2/subst.go | 2 +- .../internal/types2/testdata/check/issues.go2 | 7 ++ src/cmd/compile/internal/types2/type.go | 100 +++++------------- src/cmd/compile/internal/types2/typestring.go | 5 +- src/cmd/compile/internal/types2/typexpr.go | 4 +- 16 files changed, 90 insertions(+), 129 deletions(-) diff --git a/src/cmd/compile/internal/types2/assignments.go b/src/cmd/compile/internal/types2/assignments.go index bfc5578683..0d647a493d 100644 --- a/src/cmd/compile/internal/types2/assignments.go +++ b/src/cmd/compile/internal/types2/assignments.go @@ -71,7 +71,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { // x.typ is typed // A generic (non-instantiated) function value cannot be assigned to a variable. - if sig := asSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { + if sig := toSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { check.errorf(x, "cannot use generic function %s without instantiation in %s", x, context) } diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 318894b69b..b08a1343f3 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -82,7 +82,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( // of S and the respective parameter passing rules apply." S := x.typ var T Type - if s := asSlice(S); s != nil { + if s, _ := singleUnder(S).(*Slice); s != nil { T = s.elem } else { check.errorf(x, invalidArg+"%s is not a slice", x) @@ -291,8 +291,10 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( } // the argument types must be of floating-point type - f := func(x Type) Type { - if t := asBasic(x); t != nil { + // (applyTypeFunc never calls f with a type parameter) + f := func(typ Type) Type { + assert(asTypeParam(typ) == nil) + if t := toBasic(typ); t != nil { switch t.kind { case Float32: return Typ[Complex64] @@ -413,8 +415,10 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( } // the argument must be of complex type - f := func(x Type) Type { - if t := asBasic(x); t != nil { + // (applyTypeFunc never calls f with a type parameter) + f := func(typ Type) Type { + assert(asTypeParam(typ) == nil) + if t := toBasic(typ); t != nil { switch t.kind { case Complex64: return Typ[Float32] @@ -700,7 +704,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( return } - typ := asPointer(x.typ) + typ := toPointer(x.typ) if typ == nil { check.errorf(x, invalidArg+"%s is not a pointer", x) return @@ -816,7 +820,7 @@ func hasVarSize(t Type) bool { } case *TypeParam: return true - case *Named, *Union, *top: + case *Named, *Union: unreachable() } return false @@ -847,13 +851,8 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { return nil } - // TODO(gri) Would it be ok to return just the one type - // if len(rtypes) == 1? What about top-level - // uses of real() where the result is used to - // define type and initialize a variable? - - // Construct a suitable new type parameter for the sum type. The - // type param is placed in the current package so export/import + // Construct a suitable new type parameter for the result type. + // The type parameter is placed in the current package so export/import // works as expected. tpar := NewTypeName(nopos, check.pkg, "", nil) ptyp := check.newTypeParam(tpar, NewInterfaceType(nil, []Type{NewUnion(terms)})) // assigns type to tpar as a side-effect @@ -885,7 +884,7 @@ func makeSig(res Type, args ...Type) *Signature { // otherwise it returns typ. func arrayPtrDeref(typ Type) Type { if p, ok := typ.(*Pointer); ok { - if a := asArray(p.base); a != nil { + if a := toArray(p.base); a != nil { return a } } diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 3859e39550..e4d57d4543 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -130,9 +130,9 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { case 1: check.expr(x, call.ArgList[0]) if x.mode != invalid { - if t := asInterface(T); t != nil { + if t := toInterface(T); t != nil { if !t.IsMethodSet() { - check.errorf(call, "cannot use interface %s in conversion (contains type list or is comparable)", T) + check.errorf(call, "cannot use interface %s in conversion (contains specific type constraints or is comparable)", T) break } } @@ -167,7 +167,8 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { // signature may be generic cgocall := x.mode == cgofunc - sig := asSignature(x.typ) + // a type parameter may be "called" if all types have the same signature + sig, _ := singleUnder(x.typ).(*Signature) if sig == nil { check.errorf(x, invalidOp+"cannot call non-function %s", x) x.mode = invalid diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go index 8389770ce5..8897a15c4f 100644 --- a/src/cmd/compile/internal/types2/conversions.go +++ b/src/cmd/compile/internal/types2/conversions.go @@ -21,7 +21,7 @@ func (check *Checker) conversion(x *operand, T Type) { switch { case constArg && isConstType(T): // constant conversion (T cannot be a type parameter) - switch t := asBasic(T); { + switch t := toBasic(T); { case representableConst(x.val, check, t, &x.val): ok = true case isInteger(x.typ) && isString(t): @@ -200,9 +200,9 @@ func convertibleToImpl(check *Checker, V, T Type, cause *string) bool { // "V a slice, T is a pointer-to-array type, // and the slice and array types have identical element types." - if s := asSlice(V); s != nil { - if p := asPointer(T); p != nil { - if a := asArray(p.Elem()); a != nil { + if s := toSlice(V); s != nil { + if p := toPointer(T); p != nil { + if a := toArray(p.Elem()); a != nil { if Identical(s.Elem(), a.Elem()) { if check == nil || check.allowVersion(check.pkg, 1, 17) { return true @@ -225,27 +225,31 @@ func convertibleToImpl(check *Checker, V, T Type, cause *string) bool { return false } +// Helper predicates for convertibleToImpl. The types provided to convertibleToImpl +// may be type parameters but they won't have specific type terms. Thus it is ok to +// use the toT convenience converters in the predicates below. + func isUintptr(typ Type) bool { - t := asBasic(typ) + t := toBasic(typ) return t != nil && t.kind == Uintptr } func isUnsafePointer(typ Type) bool { - // TODO(gri): Is this asBasic(typ) instead of typ.(*Basic) correct? + // TODO(gri): Is this toBasic(typ) instead of typ.(*Basic) correct? // (The former calls under(), while the latter doesn't.) // The spec does not say so, but gc claims it is. See also // issue 6326. - t := asBasic(typ) + t := toBasic(typ) return t != nil && t.kind == UnsafePointer } func isPointer(typ Type) bool { - return asPointer(typ) != nil + return toPointer(typ) != nil } func isBytesOrRunes(typ Type) bool { - if s := asSlice(typ); s != nil { - t := asBasic(s.elem) + if s := toSlice(typ); s != nil { + t := toBasic(s.elem) return t != nil && (t.kind == Byte || t.kind == Rune) } return false diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 9afe3b7f01..c87e7fba82 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -113,8 +113,10 @@ func (check *Checker) overflow(x *operand) { // Typed constants must be representable in // their type after each constant operation. + // x.typ cannot be a type parameter (type + // parameters cannot be constant types). if isTyped(x.typ) { - check.representable(x, asBasic(x.typ)) + check.representable(x, toBasic(x.typ)) return } @@ -615,7 +617,7 @@ func (check *Checker) updateExprType(x syntax.Expr, typ Type, final bool) { // If the new type is not final and still untyped, just // update the recorded type. if !final && isUntyped(typ) { - old.typ = asBasic(typ) + old.typ = toBasic(typ) check.untyped[x] = old return } @@ -1385,7 +1387,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin duplicate := false // if the key is of interface type, the type is also significant when checking for duplicates xkey := keyVal(x.val) - if asInterface(utyp.key) != nil { + if toInterface(utyp.key) != nil { for _, vtyp := range visited[xkey] { if Identical(vtyp, x.typ) { duplicate = true diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index 62f49b95da..325d3c2585 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -34,7 +34,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo return false case value: - if sig := asSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { + if sig := toSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { // function instantiation return true } @@ -72,7 +72,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo x.typ = typ.elem case *Pointer: - if typ := asArray(typ.base); typ != nil { + if typ := toArray(typ.base); typ != nil { valid = true length = typ.len x.mode = variable @@ -242,7 +242,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { x.typ = &Slice{elem: u.elem} case *Pointer: - if u := asArray(u.base); u != nil { + if u := toArray(u.base); u != nil { valid = true length = u.len x.typ = &Slice{elem: u.elem} diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index 142ae6cb33..9b892029f9 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -275,7 +275,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { }() switch t := typ.(type) { - case nil, *top, *Basic: // TODO(gri) should nil be handled here? + case nil, *Basic: // TODO(gri) should nil be handled here? break case *Array: @@ -504,7 +504,7 @@ func (w *cycleFinder) typ(typ Type) { defer delete(w.seen, typ) switch t := typ.(type) { - case *Basic, *top: + case *Basic: // nothing to do case *Array: diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index e0fd74482a..652a04a6e3 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -306,7 +306,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, return } - if ityp := asInterface(V); ityp != nil { + if ityp := toInterface(V); ityp != nil { // TODO(gri) the methods are sorted - could do this more efficiently for _, m := range T.typeSet().methods { _, f := ityp.typeSet().LookupMethod(m.pkg, m.name) @@ -417,7 +417,7 @@ func (check *Checker) assertableTo(V *Interface, T Type) (method, wrongType *Fun // no static check is required if T is an interface // spec: "If T is an interface type, x.(T) asserts that the // dynamic type of x implements the interface T." - if asInterface(T) != nil && !forceStrict { + if toInterface(T) != nil && !forceStrict { return } return check.missingMethod(T, V, false) @@ -435,8 +435,8 @@ func deref(typ Type) (Type, bool) { // derefStructPtr dereferences typ if it is a (named or unnamed) pointer to a // (named or unnamed) struct and returns its base. Otherwise it returns typ. func derefStructPtr(typ Type) Type { - if p := asPointer(typ); p != nil { - if asStruct(p.base) != nil { + if p := toPointer(typ); p != nil { + if toStruct(p.base) != nil { return p.base } } diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 74ad3da72c..f89575b24c 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -56,7 +56,7 @@ func isNumericOrString(typ Type) bool { return is(typ, IsNumeric|IsString) } // are not fully set up. func isTyped(typ Type) bool { // isTyped is called with types that are not fully - // set up. Must not call asBasic()! + // set up. Must not call toBasic()! t, _ := typ.(*Basic) return t == nil || t.info&IsUntyped == 0 } @@ -70,13 +70,13 @@ func isOrdered(typ Type) bool { return is(typ, IsOrdered) } func isConstType(typ Type) bool { // Type parameters are never const types. - t, _ := under(typ).(*Basic) + t := toBasic(typ) return t != nil && t.info&IsConstType != 0 } // IsInterface reports whether typ is an interface type. func IsInterface(typ Type) bool { - return asInterface(typ) != nil + return toInterface(typ) != nil } // Comparable reports whether values of type T are comparable. @@ -339,10 +339,6 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { case *TypeParam: // nothing to do (x and y being equal is caught in the very beginning of this function) - case *top: - // Either both types are theTop in which case the initial x == y check - // will have caught them. Otherwise they are not identical. - case nil: // avoid a crash in case of nil type diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go index d47e23f735..99b846b80b 100644 --- a/src/cmd/compile/internal/types2/sizeof_test.go +++ b/src/cmd/compile/internal/types2/sizeof_test.go @@ -34,7 +34,6 @@ func TestSizeof(t *testing.T) { {Named{}, 68, 128}, {TypeParam{}, 28, 48}, {term{}, 12, 24}, - {top{}, 0, 0}, // Objects {PkgName{}, 64, 104}, diff --git a/src/cmd/compile/internal/types2/sizes.go b/src/cmd/compile/internal/types2/sizes.go index 6a3d19d8ea..28597340e3 100644 --- a/src/cmd/compile/internal/types2/sizes.go +++ b/src/cmd/compile/internal/types2/sizes.go @@ -243,7 +243,7 @@ func (conf *Config) offsetsof(T *Struct) []int64 { func (conf *Config) offsetof(typ Type, index []int) int64 { var o int64 for _, i := range index { - s := asStruct(typ) + s := toStruct(typ) o += conf.offsetsof(s)[i] typ = s.fields[i].typ } diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index a5ebd416aa..269b284ac4 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -74,7 +74,7 @@ func (subst *subster) typ(typ Type) Type { // Call typOrNil if it's possible that typ is nil. panic("nil typ") - case *Basic, *top: + case *Basic: // nothing to do case *Array: diff --git a/src/cmd/compile/internal/types2/testdata/check/issues.go2 b/src/cmd/compile/internal/types2/testdata/check/issues.go2 index 7c5659ba17..8608473135 100644 --- a/src/cmd/compile/internal/types2/testdata/check/issues.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/issues.go2 @@ -223,6 +223,13 @@ func _[T interface{ ~func() }](f T) { go f() } +type F1 func() +type F2 func() +func _[T interface{ func()|F1|F2 }](f T) { + f() + go f() +} + // We must compare against the underlying type of type list entries // when checking if a constraint is satisfied by a type. The under- // lying type of each type list entry must be computed after the diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 3fb05e9d63..9ff8ad57d2 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -9,26 +9,13 @@ package types2 type Type interface { // Underlying returns the underlying type of a type // w/o following forwarding chains. Only used by - // client packages (here for backward-compatibility). + // client packages. Underlying() Type // String returns a string representation of a type. String() string } -// top represents the top of the type lattice. -// It is the underlying type of a type parameter that -// can be satisfied by any type (ignoring methods), -// because its type constraint contains no restrictions -// besides methods. -type top struct{} - -// theTop is the singleton top type. -var theTop = &top{} - -func (t *top) Underlying() Type { return t } -func (t *top) String() string { return TypeString(t, nil) } - // under returns the true expanded underlying type. // If it doesn't exist, the result is Typ[Invalid]. // under must only be called when a type is known @@ -40,78 +27,47 @@ func under(t Type) Type { return t } -// optype returns a type's operational type. Except for -// type parameters, the operational type is the same -// as the underlying type (as returned by under). For -// Type parameters, the operational type is the structural -// type, if any; otherwise it's the top type. -// The result is never the incoming type parameter. -func optype(typ Type) Type { - if t := asTypeParam(typ); t != nil { - // TODO(gri) review accuracy of this comment - // If the optype is typ, return the top type as we have - // no information. It also prevents infinite recursion - // via the asTypeParam converter function. This can happen - // for a type parameter list of the form: - // (type T interface { type T }). - // See also issue #39680. - if u := t.structuralType(); u != nil { - assert(u != typ) // "naked" type parameters cannot be embedded - return under(u) // optype should always return an underlying type - } - return theTop - } - return under(typ) -} +// Convenience converters -// Converters -// -// A converter must only be called when a type is -// known to be fully set up. A converter returns -// a type's operational type (see comment for optype) -// or nil if the type argument is not of the -// respective type. - -func asBasic(t Type) *Basic { - op, _ := optype(t).(*Basic) - return op +func toBasic(t Type) *Basic { + u, _ := under(t).(*Basic) + return u } -func asArray(t Type) *Array { - op, _ := optype(t).(*Array) - return op +func toArray(t Type) *Array { + u, _ := under(t).(*Array) + return u } -func asSlice(t Type) *Slice { - op, _ := optype(t).(*Slice) - return op +func toSlice(t Type) *Slice { + u, _ := under(t).(*Slice) + return u } -func asStruct(t Type) *Struct { - op, _ := optype(t).(*Struct) - return op +func toStruct(t Type) *Struct { + u, _ := under(t).(*Struct) + return u } -func asPointer(t Type) *Pointer { - op, _ := optype(t).(*Pointer) - return op +func toPointer(t Type) *Pointer { + u, _ := under(t).(*Pointer) + return u } -func asSignature(t Type) *Signature { - op, _ := optype(t).(*Signature) - return op +func toSignature(t Type) *Signature { + u, _ := under(t).(*Signature) + return u } -// If the argument to asInterface, asNamed, or asTypeParam is of the respective type -// (possibly after expanding an instance type), these methods return that type. -// Otherwise the result is nil. - -// asInterface does not need to look at optype (type sets don't contain interfaces) -func asInterface(t Type) *Interface { +func toInterface(t Type) *Interface { u, _ := under(t).(*Interface) return u } +// If the argument to asNamed, or asTypeParam is of the respective type +// (possibly after expanding resolving a *Named type), these methods return that type. +// Otherwise the result is nil. + func asNamed(t Type) *Named { e, _ := t.(*Named) if e != nil { @@ -127,8 +83,8 @@ func asTypeParam(t Type) *TypeParam { // Exported for the compiler. -func AsPointer(t Type) *Pointer { return asPointer(t) } +func AsPointer(t Type) *Pointer { return toPointer(t) } func AsNamed(t Type) *Named { return asNamed(t) } -func AsSignature(t Type) *Signature { return asSignature(t) } -func AsInterface(t Type) *Interface { return asInterface(t) } +func AsSignature(t Type) *Signature { return toSignature(t) } +func AsInterface(t Type) *Interface { return toInterface(t) } func AsTypeParam(t Type) *TypeParam { return asTypeParam(t) } diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 61c8a9158c..1804df2d99 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -272,9 +272,6 @@ func (w *typeWriter) typ(typ Type) { } w.string(t.obj.name + subscript(t.id)) - case *top: - w.error("⊤") - default: // For externally defined implementations of Type. // Note: In this case cycles won't be caught. @@ -358,7 +355,7 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) { } else { // special case: // append(s, "foo"...) leads to signature func([]byte, string...) - if t := asBasic(typ); t == nil || t.kind != String { + if t := toBasic(typ); t == nil || t.kind != String { w.error("expected string type") continue } diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 20e56caf1e..3704cda6a8 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -144,11 +144,11 @@ func (check *Checker) typ(e syntax.Expr) Type { func (check *Checker) varType(e syntax.Expr) Type { typ := check.definedType(e, nil) - // We don't want to call under() (via asInterface) or complete interfaces while we + // We don't want to call under() (via toInterface) or complete interfaces while we // are in the middle of type-checking parameter declarations that might belong to // interface methods. Delay this check to the end of type-checking. check.later(func() { - if t := asInterface(typ); t != nil { + if t := toInterface(typ); t != nil { pos := syntax.StartPos(e) tset := computeInterfaceTypeSet(check, pos, t) // TODO(gri) is this the correct position? if !tset.IsMethodSet() { -- GitLab From a155a307fbeda88fd44c5399d4fb7ea9e34db545 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 25 Oct 2021 20:54:05 -0700 Subject: [PATCH 1772/2500] cmd/compile/internal/types2: clean up asT converters (step 2 of 2) This CL renames the toT converters back to their asT names. Change-Id: If4bda5a78525f9722f044f5544f400fa8bb6f437 Reviewed-on: https://go-review.googlesource.com/c/go/+/358774 Trust: Robert Griesemer Reviewed-by: Robert Findley --- .../compile/internal/types2/assignments.go | 2 +- src/cmd/compile/internal/types2/builtins.go | 8 ++++---- src/cmd/compile/internal/types2/call.go | 2 +- .../compile/internal/types2/conversions.go | 20 +++++++++---------- src/cmd/compile/internal/types2/expr.go | 6 +++--- src/cmd/compile/internal/types2/index.go | 6 +++--- src/cmd/compile/internal/types2/lookup.go | 8 ++++---- src/cmd/compile/internal/types2/predicates.go | 6 +++--- src/cmd/compile/internal/types2/sizes.go | 2 +- src/cmd/compile/internal/types2/type.go | 20 +++++++++---------- src/cmd/compile/internal/types2/typestring.go | 2 +- src/cmd/compile/internal/types2/typexpr.go | 2 +- 12 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/cmd/compile/internal/types2/assignments.go b/src/cmd/compile/internal/types2/assignments.go index 0d647a493d..bfc5578683 100644 --- a/src/cmd/compile/internal/types2/assignments.go +++ b/src/cmd/compile/internal/types2/assignments.go @@ -71,7 +71,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { // x.typ is typed // A generic (non-instantiated) function value cannot be assigned to a variable. - if sig := toSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { + if sig := asSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { check.errorf(x, "cannot use generic function %s without instantiation in %s", x, context) } diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index b08a1343f3..7897dafa46 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -294,7 +294,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( // (applyTypeFunc never calls f with a type parameter) f := func(typ Type) Type { assert(asTypeParam(typ) == nil) - if t := toBasic(typ); t != nil { + if t := asBasic(typ); t != nil { switch t.kind { case Float32: return Typ[Complex64] @@ -418,7 +418,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( // (applyTypeFunc never calls f with a type parameter) f := func(typ Type) Type { assert(asTypeParam(typ) == nil) - if t := toBasic(typ); t != nil { + if t := asBasic(typ); t != nil { switch t.kind { case Complex64: return Typ[Float32] @@ -704,7 +704,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( return } - typ := toPointer(x.typ) + typ := asPointer(x.typ) if typ == nil { check.errorf(x, invalidArg+"%s is not a pointer", x) return @@ -884,7 +884,7 @@ func makeSig(res Type, args ...Type) *Signature { // otherwise it returns typ. func arrayPtrDeref(typ Type) Type { if p, ok := typ.(*Pointer); ok { - if a := toArray(p.base); a != nil { + if a := asArray(p.base); a != nil { return a } } diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index e4d57d4543..1618e88fef 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -130,7 +130,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { case 1: check.expr(x, call.ArgList[0]) if x.mode != invalid { - if t := toInterface(T); t != nil { + if t := asInterface(T); t != nil { if !t.IsMethodSet() { check.errorf(call, "cannot use interface %s in conversion (contains specific type constraints or is comparable)", T) break diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go index 8897a15c4f..a456f89f7e 100644 --- a/src/cmd/compile/internal/types2/conversions.go +++ b/src/cmd/compile/internal/types2/conversions.go @@ -21,7 +21,7 @@ func (check *Checker) conversion(x *operand, T Type) { switch { case constArg && isConstType(T): // constant conversion (T cannot be a type parameter) - switch t := toBasic(T); { + switch t := asBasic(T); { case representableConst(x.val, check, t, &x.val): ok = true case isInteger(x.typ) && isString(t): @@ -200,9 +200,9 @@ func convertibleToImpl(check *Checker, V, T Type, cause *string) bool { // "V a slice, T is a pointer-to-array type, // and the slice and array types have identical element types." - if s := toSlice(V); s != nil { - if p := toPointer(T); p != nil { - if a := toArray(p.Elem()); a != nil { + if s := asSlice(V); s != nil { + if p := asPointer(T); p != nil { + if a := asArray(p.Elem()); a != nil { if Identical(s.Elem(), a.Elem()) { if check == nil || check.allowVersion(check.pkg, 1, 17) { return true @@ -230,26 +230,26 @@ func convertibleToImpl(check *Checker, V, T Type, cause *string) bool { // use the toT convenience converters in the predicates below. func isUintptr(typ Type) bool { - t := toBasic(typ) + t := asBasic(typ) return t != nil && t.kind == Uintptr } func isUnsafePointer(typ Type) bool { - // TODO(gri): Is this toBasic(typ) instead of typ.(*Basic) correct? + // TODO(gri): Is this asBasic(typ) instead of typ.(*Basic) correct? // (The former calls under(), while the latter doesn't.) // The spec does not say so, but gc claims it is. See also // issue 6326. - t := toBasic(typ) + t := asBasic(typ) return t != nil && t.kind == UnsafePointer } func isPointer(typ Type) bool { - return toPointer(typ) != nil + return asPointer(typ) != nil } func isBytesOrRunes(typ Type) bool { - if s := toSlice(typ); s != nil { - t := toBasic(s.elem) + if s := asSlice(typ); s != nil { + t := asBasic(s.elem) return t != nil && (t.kind == Byte || t.kind == Rune) } return false diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index c87e7fba82..9142eee85c 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -116,7 +116,7 @@ func (check *Checker) overflow(x *operand) { // x.typ cannot be a type parameter (type // parameters cannot be constant types). if isTyped(x.typ) { - check.representable(x, toBasic(x.typ)) + check.representable(x, asBasic(x.typ)) return } @@ -617,7 +617,7 @@ func (check *Checker) updateExprType(x syntax.Expr, typ Type, final bool) { // If the new type is not final and still untyped, just // update the recorded type. if !final && isUntyped(typ) { - old.typ = toBasic(typ) + old.typ = asBasic(typ) check.untyped[x] = old return } @@ -1387,7 +1387,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin duplicate := false // if the key is of interface type, the type is also significant when checking for duplicates xkey := keyVal(x.val) - if toInterface(utyp.key) != nil { + if asInterface(utyp.key) != nil { for _, vtyp := range visited[xkey] { if Identical(vtyp, x.typ) { duplicate = true diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index 325d3c2585..62f49b95da 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -34,7 +34,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo return false case value: - if sig := toSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { + if sig := asSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { // function instantiation return true } @@ -72,7 +72,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo x.typ = typ.elem case *Pointer: - if typ := toArray(typ.base); typ != nil { + if typ := asArray(typ.base); typ != nil { valid = true length = typ.len x.mode = variable @@ -242,7 +242,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { x.typ = &Slice{elem: u.elem} case *Pointer: - if u := toArray(u.base); u != nil { + if u := asArray(u.base); u != nil { valid = true length = u.len x.typ = &Slice{elem: u.elem} diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index 652a04a6e3..e0fd74482a 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -306,7 +306,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, return } - if ityp := toInterface(V); ityp != nil { + if ityp := asInterface(V); ityp != nil { // TODO(gri) the methods are sorted - could do this more efficiently for _, m := range T.typeSet().methods { _, f := ityp.typeSet().LookupMethod(m.pkg, m.name) @@ -417,7 +417,7 @@ func (check *Checker) assertableTo(V *Interface, T Type) (method, wrongType *Fun // no static check is required if T is an interface // spec: "If T is an interface type, x.(T) asserts that the // dynamic type of x implements the interface T." - if toInterface(T) != nil && !forceStrict { + if asInterface(T) != nil && !forceStrict { return } return check.missingMethod(T, V, false) @@ -435,8 +435,8 @@ func deref(typ Type) (Type, bool) { // derefStructPtr dereferences typ if it is a (named or unnamed) pointer to a // (named or unnamed) struct and returns its base. Otherwise it returns typ. func derefStructPtr(typ Type) Type { - if p := toPointer(typ); p != nil { - if toStruct(p.base) != nil { + if p := asPointer(typ); p != nil { + if asStruct(p.base) != nil { return p.base } } diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index f89575b24c..4faa09ebd0 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -56,7 +56,7 @@ func isNumericOrString(typ Type) bool { return is(typ, IsNumeric|IsString) } // are not fully set up. func isTyped(typ Type) bool { // isTyped is called with types that are not fully - // set up. Must not call toBasic()! + // set up. Must not call asBasic()! t, _ := typ.(*Basic) return t == nil || t.info&IsUntyped == 0 } @@ -70,13 +70,13 @@ func isOrdered(typ Type) bool { return is(typ, IsOrdered) } func isConstType(typ Type) bool { // Type parameters are never const types. - t := toBasic(typ) + t := asBasic(typ) return t != nil && t.info&IsConstType != 0 } // IsInterface reports whether typ is an interface type. func IsInterface(typ Type) bool { - return toInterface(typ) != nil + return asInterface(typ) != nil } // Comparable reports whether values of type T are comparable. diff --git a/src/cmd/compile/internal/types2/sizes.go b/src/cmd/compile/internal/types2/sizes.go index 28597340e3..6a3d19d8ea 100644 --- a/src/cmd/compile/internal/types2/sizes.go +++ b/src/cmd/compile/internal/types2/sizes.go @@ -243,7 +243,7 @@ func (conf *Config) offsetsof(T *Struct) []int64 { func (conf *Config) offsetof(typ Type, index []int) int64 { var o int64 for _, i := range index { - s := toStruct(typ) + s := asStruct(typ) o += conf.offsetsof(s)[i] typ = s.fields[i].typ } diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 9ff8ad57d2..33d3d3642c 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -29,37 +29,37 @@ func under(t Type) Type { // Convenience converters -func toBasic(t Type) *Basic { +func asBasic(t Type) *Basic { u, _ := under(t).(*Basic) return u } -func toArray(t Type) *Array { +func asArray(t Type) *Array { u, _ := under(t).(*Array) return u } -func toSlice(t Type) *Slice { +func asSlice(t Type) *Slice { u, _ := under(t).(*Slice) return u } -func toStruct(t Type) *Struct { +func asStruct(t Type) *Struct { u, _ := under(t).(*Struct) return u } -func toPointer(t Type) *Pointer { +func asPointer(t Type) *Pointer { u, _ := under(t).(*Pointer) return u } -func toSignature(t Type) *Signature { +func asSignature(t Type) *Signature { u, _ := under(t).(*Signature) return u } -func toInterface(t Type) *Interface { +func asInterface(t Type) *Interface { u, _ := under(t).(*Interface) return u } @@ -83,8 +83,8 @@ func asTypeParam(t Type) *TypeParam { // Exported for the compiler. -func AsPointer(t Type) *Pointer { return toPointer(t) } +func AsPointer(t Type) *Pointer { return asPointer(t) } func AsNamed(t Type) *Named { return asNamed(t) } -func AsSignature(t Type) *Signature { return toSignature(t) } -func AsInterface(t Type) *Interface { return toInterface(t) } +func AsSignature(t Type) *Signature { return asSignature(t) } +func AsInterface(t Type) *Interface { return asInterface(t) } func AsTypeParam(t Type) *TypeParam { return asTypeParam(t) } diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 1804df2d99..709499792b 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -355,7 +355,7 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) { } else { // special case: // append(s, "foo"...) leads to signature func([]byte, string...) - if t := toBasic(typ); t == nil || t.kind != String { + if t := asBasic(typ); t == nil || t.kind != String { w.error("expected string type") continue } diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 3704cda6a8..d8183bfd9c 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -148,7 +148,7 @@ func (check *Checker) varType(e syntax.Expr) Type { // are in the middle of type-checking parameter declarations that might belong to // interface methods. Delay this check to the end of type-checking. check.later(func() { - if t := toInterface(typ); t != nil { + if t := asInterface(typ); t != nil { pos := syntax.StartPos(e) tset := computeInterfaceTypeSet(check, pos, t) // TODO(gri) is this the correct position? if !tset.IsMethodSet() { -- GitLab From 5c4d7c50c7266bfbce3f43f04a0fb622b9e45805 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 25 Oct 2021 21:43:07 -0700 Subject: [PATCH 1773/2500] cmd/compile/internal/types2: rename isNamed predicate to hasName isNamed(t) is easily confused with asNamed(t) != nil (e.g., we have isPointer(t) that is defined as asPointer(t) != nil). This rename also helped clarifying a couple of places in the assignability rules where it makes sense to simply look for types that have names. Change-Id: Ie995908613a26883ffe0562343d297a1e981e9ef Reviewed-on: https://go-review.googlesource.com/c/go/+/358621 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/operand.go | 9 ++++----- src/cmd/compile/internal/types2/predicates.go | 7 ++++--- .../internal/types2/testdata/spec/assignability.go2 | 8 +++++--- src/cmd/compile/internal/types2/unify.go | 6 +++--- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/cmd/compile/internal/types2/operand.go b/src/cmd/compile/internal/types2/operand.go index 92ae0a95fc..e4db0554f3 100644 --- a/src/cmd/compile/internal/types2/operand.go +++ b/src/cmd/compile/internal/types2/operand.go @@ -282,9 +282,8 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er // Vu is typed // x's type V and T have identical underlying types - // and at least one of V or T is not a named type - // and neither is a type parameter. - if Identical(Vu, Tu) && (!isNamed(V) || !isNamed(T)) && Vp == nil && Tp == nil { + // and at least one of V or T is not a named type. + if Identical(Vu, Tu) && (!hasName(V) || !hasName(T)) { return true, 0 } @@ -311,10 +310,10 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er // x is a bidirectional channel value, T is a channel // type, x's type V and T have identical element types, - // and at least one of V or T is not a named type + // and at least one of V or T is not a named type. if Vc, ok := Vu.(*Chan); ok && Vc.dir == SendRecv { if Tc, ok := Tu.(*Chan); ok && Identical(Vc.elem, Tc.elem) { - return !isNamed(V) || !isNamed(T), _InvalidChanAssign + return !hasName(V) || !hasName(T), _InvalidChanAssign } } diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 4faa09ebd0..409715ad9d 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -6,9 +6,10 @@ package types2 -// isNamed reports whether typ has a name. -// isNamed may be called with types that are not fully set up. -func isNamed(typ Type) bool { +// hasName reports whether typ has a name. This includes +// predeclared types, defined types, and type parameters. +// hasName may be called with types that are not fully set up. +func hasName(typ Type) bool { switch typ.(type) { case *Basic, *Named, *TypeParam: return true diff --git a/src/cmd/compile/internal/types2/testdata/spec/assignability.go2 b/src/cmd/compile/internal/types2/testdata/spec/assignability.go2 index 1507cabb1d..ab8f9c08b2 100644 --- a/src/cmd/compile/internal/types2/testdata/spec/assignability.go2 +++ b/src/cmd/compile/internal/types2/testdata/spec/assignability.go2 @@ -33,8 +33,9 @@ func _[TP any](X TP) { X = X } -// "x's type V and T have identical underlying types and at least one -// of V or T is not a defined type and neither is a type parameter" +// "x's type V and T have identical underlying types +// and at least one of V or T is not a named type." +// (here a named type is a type with a name) func _[TP1, TP2 Interface](X1 TP1, X2 TP2) { b = B // ERROR cannot use B .* as int value a = A @@ -69,7 +70,8 @@ func _[TP Interface](X TP) { X = i // ERROR cannot use i .* as TP value } -// "x is a bidirectional channel value, T is a channel type, x's type V and T have identical element types, and at least one of V or T is not a defined type" +// "x is a bidirectional channel value, T is a channel type, x's type V and T have identical element types, and at least one of V or T is not a named type" +// (here a named type is a type with a name) type ( _SendChan = chan<- int _RecvChan = <-chan int diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index a252c5e1a5..7f636c30d3 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -235,13 +235,13 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { // If exact unification is known to fail because we attempt to // match a type name against an unnamed type literal, consider // the underlying type of the named type. - // (Subtle: We use isNamed to include any type with a name (incl. + // (Subtle: We use hasName to include any type with a name (incl. // basic types and type parameters. We use asNamed because we only // want *Named types.) switch { - case !isNamed(x) && y != nil && asNamed(y) != nil: + case !hasName(x) && y != nil && asNamed(y) != nil: return u.nify(x, under(y), p) - case x != nil && asNamed(x) != nil && !isNamed(y): + case x != nil && asNamed(x) != nil && !hasName(y): return u.nify(under(x), y, p) } } -- GitLab From 6a7eb56cd1837b961ea815105235a3fd96fda94b Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 26 Oct 2021 13:55:53 -0700 Subject: [PATCH 1774/2500] cmd/compile/internal/types2: remove unused position computation (cleanup) The position computation was needed for type list support. With that gone, we don't need this code anymore. Change-Id: I3f36b3d108a1fae9947fd259d4892e0287cb78ef Reviewed-on: https://go-review.googlesource.com/c/go/+/358701 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/union.go | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/src/cmd/compile/internal/types2/union.go b/src/cmd/compile/internal/types2/union.go index 87985dd133..5379bde02c 100644 --- a/src/cmd/compile/internal/types2/union.go +++ b/src/cmd/compile/internal/types2/union.go @@ -75,28 +75,16 @@ func parseUnion(check *Checker, tlist []syntax.Expr) Type { continue } - x := tlist[i] - pos := syntax.StartPos(x) - // We may not know the position of x if it was a typechecker- - // introduced ~T term for a type list entry T. Use the position - // of T instead. - // TODO(gri) remove this test once we don't support type lists anymore - if !pos.IsKnown() { - if op, _ := x.(*syntax.Operation); op != nil { - pos = syntax.StartPos(op.X) - } - } - u := under(t.typ) f, _ := u.(*Interface) if t.tilde { if f != nil { - check.errorf(x, "invalid use of ~ (%s is an interface)", t.typ) + check.errorf(tlist[i], "invalid use of ~ (%s is an interface)", t.typ) continue // don't report another error for t } if !Identical(u, t.typ) { - check.errorf(x, "invalid use of ~ (underlying type of %s is %s)", t.typ, u) + check.errorf(tlist[i], "invalid use of ~ (underlying type of %s is %s)", t.typ, u) continue // don't report another error for t } } @@ -105,14 +93,14 @@ func parseUnion(check *Checker, tlist []syntax.Expr) Type { // in the beginning. Embedded interfaces with tilde are excluded above. If we reach // here, we must have at least two terms in the union. if f != nil && !f.typeSet().IsTypeSet() { - check.errorf(pos, "cannot use %s in union (interface contains methods)", t) + check.errorf(tlist[i], "cannot use %s in union (interface contains methods)", t) continue // don't report another error for t } // Report overlapping (non-disjoint) terms such as // a|a, a|~a, ~a|~a, and ~a|A (where under(A) == a). if j := overlappingTerm(terms[:i], t); j >= 0 { - check.softErrorf(pos, "overlapping terms %s and %s", t, terms[j]) + check.softErrorf(tlist[i], "overlapping terms %s and %s", t, terms[j]) } } }) -- GitLab From bbc059572d599a414653e4ac659b4738d434e1f1 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 26 Oct 2021 17:07:32 -0700 Subject: [PATCH 1775/2500] cmd/compile/internal/types2: implement singleType and structure (type) Rename structuralType to singleType throughout. This reflects more closely what the function does: if a type set consists of exactly one type term, singleType returns the corresponding type. Rename singleUnder to structure. The structure function returns the "type structure" of a type, either its underlying type for a non-type parameter, or the single underlying type (if it exists) for a type parameter. Change constraint type inference to use the structure type for inference, unless the structure type is the underlying type of a single defined type, in which case it uses the latter. This preserves existing behavior while making constraint type inference slightly more flexible. Change-Id: I38ee89ffdabd12bfeaa0be2ad6af8fb373c11fc9 Reviewed-on: https://go-review.googlesource.com/c/go/+/359015 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/builtins.go | 26 +++++++++---------- src/cmd/compile/internal/types2/call.go | 2 +- src/cmd/compile/internal/types2/expr.go | 2 +- src/cmd/compile/internal/types2/index.go | 2 +- src/cmd/compile/internal/types2/infer.go | 13 +++++++--- src/cmd/compile/internal/types2/stmt.go | 2 +- src/cmd/compile/internal/types2/termlist.go | 4 +-- .../compile/internal/types2/termlist_test.go | 6 ++--- .../types2/testdata/examples/inference.go2 | 23 ++++++++++++++++ src/cmd/compile/internal/types2/typeparam.go | 6 ++--- src/cmd/compile/internal/types2/typeset.go | 4 +-- 11 files changed, 59 insertions(+), 31 deletions(-) diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 7897dafa46..e8de0077d4 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -82,7 +82,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( // of S and the respective parameter passing rules apply." S := x.typ var T Type - if s, _ := singleUnder(S).(*Slice); s != nil { + if s, _ := structure(S).(*Slice); s != nil { T = s.elem } else { check.errorf(x, invalidArg+"%s is not a slice", x) @@ -327,14 +327,14 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( case _Copy: // copy(x, y []T) int - dst, _ := singleUnder(x.typ).(*Slice) + dst, _ := structure(x.typ).(*Slice) var y operand arg(&y, 1) if y.mode == invalid { return } - src, _ := singleUnderString(y.typ).(*Slice) + src, _ := structureString(y.typ).(*Slice) if dst == nil || src == nil { check.errorf(x, invalidArg+"copy expects slice arguments; found %s and %s", x, &y) @@ -464,7 +464,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( } var min int // minimum number of arguments - switch singleUnder(T).(type) { + switch structure(T).(type) { case *Slice: min = 2 case *Map, *Chan: @@ -767,11 +767,11 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( return true } -// If typ is a type parameter, single under returns the single underlying -// type of all types in the corresponding type constraint if it exists, or -// nil if it doesn't exist. If typ is not a type parameter, singleUnder -// just returns the underlying type. -func singleUnder(typ Type) Type { +// If typ is a type parameter, structure returns the single underlying +// type of all types in the corresponding type constraint if it exists, +// or nil otherwise. If typ is not a type parameter, structure returns +// the underlying type. +func structure(typ Type) Type { var su Type if underIs(typ, func(u Type) bool { if su != nil && !Identical(su, u) { @@ -786,10 +786,10 @@ func singleUnder(typ Type) Type { return nil } -// singleUnderString is like singleUnder but also considers []byte and -// string as "identical". In this case, if successful, the result is always -// []byte. -func singleUnderString(typ Type) Type { +// structureString is like structure but also considers []byte and +// string as "identical". In this case, if successful, the result +// is always []byte. +func structureString(typ Type) Type { var su Type if underIs(typ, func(u Type) bool { if isString(u) { diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 1618e88fef..220ba940b3 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -168,7 +168,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { cgocall := x.mode == cgofunc // a type parameter may be "called" if all types have the same signature - sig, _ := singleUnder(x.typ).(*Signature) + sig, _ := structure(x.typ).(*Signature) if sig == nil { check.errorf(x, invalidOp+"cannot call non-function %s", x) x.mode = invalid diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 9142eee85c..ae7b205e53 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -1257,7 +1257,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin goto Error } - switch utyp := singleUnder(base).(type) { + switch utyp := structure(base).(type) { case *Struct: if len(e.ElemList) == 0 { break diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index 62f49b95da..23e433ac6a 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -207,7 +207,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { valid := false length := int64(-1) // valid if >= 0 - switch u := singleUnder(x.typ).(type) { + switch u := structure(x.typ).(type) { case nil: check.errorf(x, invalidOp+"cannot slice %s: type set has no single underlying type", x) x.mode = invalid diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index 9b892029f9..156c2290f7 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -363,7 +363,7 @@ func (w *tpWalker) isParameterizedTypeList(list []Type) bool { func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type, index int) { assert(len(tparams) >= len(targs) && len(targs) > 0) - // Setup bidirectional unification between those structural bounds + // Setup bidirectional unification between constraints // and the corresponding type arguments (which may be nil!). u := newUnifier(false) u.x.init(tparams) @@ -376,11 +376,16 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type, } } - // Unify type parameters with their structural constraints, if any. + // If a constraint has a structural type, unify the corresponding type parameter with it. for _, tpar := range tparams { typ := tpar - sbound := typ.structuralType() + sbound := structure(tpar) if sbound != nil { + // If the structural type is the underlying type of a single + // defined type in the constraint, use that defined type instead. + if named, _ := tpar.singleType().(*Named); named != nil { + sbound = named + } if !u.unify(typ, sbound) { check.errorf(tpar.obj, "%s does not match %s", tpar.obj, sbound) return nil, 0 @@ -389,7 +394,7 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type, } // u.x.types() now contains the incoming type arguments plus any additional type - // arguments for which there were structural constraints. The newly inferred non- + // arguments which were inferred from structural types. The newly inferred non- // nil entries may still contain references to other type parameters. // For instance, for [A any, B interface{ []C }, C interface{ *A }], if A == int // was given, unification produced the type list [int, []C, *A]. We eliminate the diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index 10741a90e2..dd2100f711 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -836,7 +836,7 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s if x.mode != invalid { // Ranging over a type parameter is permitted if it has a single underlying type. var cause string - u := singleUnder(x.typ) + u := structure(x.typ) switch t := u.(type) { case nil: cause = "type set has no single underlying type" diff --git a/src/cmd/compile/internal/types2/termlist.go b/src/cmd/compile/internal/types2/termlist.go index 378ba6b8f4..844e39e3bf 100644 --- a/src/cmd/compile/internal/types2/termlist.go +++ b/src/cmd/compile/internal/types2/termlist.go @@ -93,8 +93,8 @@ func (xl termlist) norm() termlist { } // If the type set represented by xl is specified by a single (non-𝓤) term, -// structuralType returns that type. Otherwise it returns nil. -func (xl termlist) structuralType() Type { +// singleType returns that type. Otherwise it returns nil. +func (xl termlist) singleType() Type { if nl := xl.norm(); len(nl) == 1 { return nl[0].typ // if nl.isAll() then typ is nil, which is ok } diff --git a/src/cmd/compile/internal/types2/termlist_test.go b/src/cmd/compile/internal/types2/termlist_test.go index ed1330d26f..1bdf9e1386 100644 --- a/src/cmd/compile/internal/types2/termlist_test.go +++ b/src/cmd/compile/internal/types2/termlist_test.go @@ -106,7 +106,7 @@ func TestTermlistNorm(t *testing.T) { } } -func TestTermlistStructuralType(t *testing.T) { +func TestTermlistSingleType(t *testing.T) { // helper to deal with nil types tstring := func(typ Type) string { if typ == nil { @@ -128,9 +128,9 @@ func TestTermlistStructuralType(t *testing.T) { "∅ ∪ ~int ∪ string": "nil", } { xl := maketl(test) - got := tstring(xl.structuralType()) + got := tstring(xl.singleType()) if got != want { - t.Errorf("(%v).structuralType() == %v; want %v", test, got, want) + t.Errorf("(%v).singleType() == %v; want %v", test, got, want) } } } diff --git a/src/cmd/compile/internal/types2/testdata/examples/inference.go2 b/src/cmd/compile/internal/types2/testdata/examples/inference.go2 index e169aec746..4eb18eb239 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/inference.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/inference.go2 @@ -99,3 +99,26 @@ func _() { related2(1.0, []int{}) related2( /* ERROR does not satisfy */ float64(1.0), []int{}) // TODO(gri) fix error position } + +type List[P any] []P + +func related3[Elem any, Slice []Elem | List[Elem]]() Slice { return nil } + +func _() { + // related3 can be instantiated explicitly + related3[int, []int]() + related3[byte, List[byte]]() + + // Alternatively, the 2nd type argument can be inferred + // from the first one through constraint type inference. + related3[int]() + + // The inferred type is the structural type of the Slice + // type parameter. + var _ []int = related3[int]() + + // It is not the defined parameterized type List. + type anotherList []float32 + var _ anotherList = related3[float32]() // valid + var _ anotherList = related3 /* ERROR cannot use .* \(value of type List\[float32\]\) as anotherList */ [float32, List[float32]]() +} diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index 75e2fe8f0e..099bc429c3 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -114,9 +114,9 @@ func (t *TypeParam) iface() *Interface { return ityp } -// structuralType returns the structural type of the type parameter's constraint; or nil. -func (t *TypeParam) structuralType() Type { - return t.iface().typeSet().structuralType() +// singleType returns the single type of the type parameter constraint; or nil. +func (t *TypeParam) singleType() Type { + return t.iface().typeSet().singleType() } // hasTerms reports whether the type parameter constraint has specific type terms. diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index c99d02744b..445a62f9e0 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -104,8 +104,8 @@ func (s *_TypeSet) String() string { // hasTerms reports whether the type set has specific type terms. func (s *_TypeSet) hasTerms() bool { return !s.terms.isEmpty() && !s.terms.isAll() } -// structuralType returns the single type in s if there is exactly one; otherwise the result is nil. -func (s *_TypeSet) structuralType() Type { return s.terms.structuralType() } +// singleType returns the single type in s if there is exactly one; otherwise the result is nil. +func (s *_TypeSet) singleType() Type { return s.terms.singleType() } // includes reports whether t ∈ s. func (s *_TypeSet) includes(t Type) bool { return s.terms.includes(t) } -- GitLab From 30a82efcf403fed76bf1542e9477047660d5f54d Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 24 Sep 2021 16:46:05 -0400 Subject: [PATCH 1776/2500] cmd/compile, runtime: track argument stack slot liveness Currently, for stack traces (e.g. at panic or when runtime.Stack is called), we print argument values from the stack. With register ABI, we may never store the argument to stack therefore the argument value on stack may be meaningless. This causes confusion. This CL makes the compiler keep trace of which argument stack slots are meaningful. If it is meaningful, it will be printed in stack traces as before. If it may not be meaningful, it will be printed as the stack value with a question mark ("?"). In general, the value could be meaningful on some code paths but not others depending on the execution, and the compiler couldn't know statically, so we still print the stack value, instead of not printing it at all. Also note that if the argument variable is updated in the function body the printed value may be stale (like before register ABI) but still considered meaningful. Arguments passed on stack are always meaningful therefore always printed without a question mark. Results are never printed, as before. (Due to a bug in the compiler we sometimes don't spill args into their dedicated spill slots (as we should), causing it having fewer meaningful values than it should be.) This increases binary sizes a bit: old new hello 1129760 1142080 +1.09% cmd/go 13932320 14088016 +1.12% cmd/link 6267696 6329168 +0.98% Fixes #45728. Change-Id: I308a0402e5c5ab94ca0953f8bd85a56acd28f58c Reviewed-on: https://go-review.googlesource.com/c/go/+/352057 Trust: Cherry Mui Reviewed-by: Michael Knyszek --- src/cmd/compile/internal/bitvec/bv.go | 11 + src/cmd/compile/internal/gc/obj.go | 7 +- src/cmd/compile/internal/liveness/arg.go | 339 +++++++++++++++++++++ src/cmd/compile/internal/liveness/bvset.go | 11 +- src/cmd/compile/internal/liveness/plive.go | 5 +- src/cmd/compile/internal/ssa/op.go | 4 + src/cmd/compile/internal/ssagen/ssa.go | 17 ++ src/cmd/internal/obj/link.go | 1 + src/cmd/internal/obj/objfile.go | 4 +- src/cmd/internal/objabi/funcdata.go | 2 + src/cmd/link/internal/ld/symtab.go | 1 + src/runtime/funcdata.h | 2 + src/runtime/symtab.go | 2 + src/runtime/traceback.go | 33 +- src/runtime/traceback_test.go | 113 +++++++ 15 files changed, 538 insertions(+), 14 deletions(-) create mode 100644 src/cmd/compile/internal/liveness/arg.go diff --git a/src/cmd/compile/internal/bitvec/bv.go b/src/cmd/compile/internal/bitvec/bv.go index bcac1fe351..ad7ed0a196 100644 --- a/src/cmd/compile/internal/bitvec/bv.go +++ b/src/cmd/compile/internal/bitvec/bv.go @@ -128,10 +128,21 @@ func (bv BitVec) IsEmpty() bool { return true } +func (bv BitVec) Count() int { + n := 0 + for _, x := range bv.B { + n += bits.OnesCount32(x) + } + return n +} + func (bv BitVec) Not() { for i, x := range bv.B { bv.B[i] = ^x } + if bv.N%wordBits != 0 { + bv.B[len(bv.B)-1] &= 1< 0xff { + // We only print a limited number of args, with stack + // offsets no larger than 255. + continue + } + lv.args = append(lv.args, nameOff{n, off}) + } + } + if len(lv.args) > 10 { + lv.args = lv.args[:10] // We print no more than 10 args. + } + + // We spill address-taken or non-SSA-able value upfront, so they are always live. + alwaysLive := func(n *ir.Name) bool { return n.Addrtaken() || !f.Frontend().CanSSA(n.Type()) } + + // We'll emit the smallest offset for the slots that need liveness info. + // No need to include a slot with a lower offset if it is always live. + for len(lv.args) > 0 && alwaysLive(lv.args[0].n) { + lv.args = lv.args[1:] + } + if len(lv.args) == 0 { + return // everything is always live + } + + for i, a := range lv.args { + lv.idx[a] = int32(i) + } + + nargs := int32(len(lv.args)) + bulk := bitvec.NewBulk(nargs, int32(len(f.Blocks)*2)) + for _, b := range f.Blocks { + be := &lv.be[b.ID] + be.livein = bulk.Next() + be.liveout = bulk.Next() + + // initialize to all 1s, so we can AND them + be.livein.Not() + be.liveout.Not() + } + + entrybe := &lv.be[f.Entry.ID] + entrybe.livein.Clear() + for i, a := range lv.args { + if alwaysLive(a.n) { + entrybe.livein.Set(int32(i)) + } + } + + // Visit blocks in reverse-postorder, compute block effects. + po := f.Postorder() + for i := len(po) - 1; i >= 0; i-- { + b := po[i] + be := &lv.be[b.ID] + + // A slot is live at block entry if it is live in all predecessors. + for _, pred := range b.Preds { + pb := pred.Block() + be.livein.And(be.livein, lv.be[pb.ID].liveout) + } + + be.liveout.Copy(be.livein) + for _, v := range b.Values { + lv.valueEffect(v, be.liveout) + } + } + + // Coalesce identical live vectors. Compute liveness indices at each PC + // where it changes. + live := bitvec.New(nargs) + addToSet := func(bv bitvec.BitVec) (int, bool) { + if bv.Count() == int(nargs) { // special case for all live + return allLiveIdx, false + } + return lv.bvset.add(bv) + } + for _, b := range lv.f.Blocks { + be := &lv.be[b.ID] + lv.blockIdx[b.ID], _ = addToSet(be.livein) + + live.Copy(be.livein) + var lastv *ssa.Value + for i, v := range b.Values { + if lv.valueEffect(v, live) { + // Record that liveness changes but not emit a map now. + // For a sequence of StoreRegs we only need to emit one + // at last. + lastv = v + } + if lastv != nil && (mayFault(v) || i == len(b.Values)-1) { + // Emit the liveness map if it may fault or at the end of + // the block. We may need a traceback if the instruction + // may cause a panic. + var added bool + lv.valueIdx[lastv.ID], added = addToSet(live) + if added { + // live is added to bvset and we cannot modify it now. + // Make a copy. + t := live + live = bitvec.New(nargs) + live.Copy(t) + } + lastv = nil + } + } + + // Sanity check. + if !live.Eq(be.liveout) { + panic("wrong arg liveness map at block end") + } + } + + // Emit funcdata symbol, update indices to offsets in the symbol data. + lsym := lv.emit() + fn.LSym.Func().ArgLiveInfo = lsym + + //lv.print() + + p := pp.Prog(obj.AFUNCDATA) + p.From.SetConst(objabi.FUNCDATA_ArgLiveInfo) + p.To.Type = obj.TYPE_MEM + p.To.Name = obj.NAME_EXTERN + p.To.Sym = lsym + + return lv.blockIdx, lv.valueIdx +} + +// valueEffect applies the effect of v to live, return whether it is changed. +func (lv *argLiveness) valueEffect(v *ssa.Value, live bitvec.BitVec) bool { + if v.Op != ssa.OpStoreReg { // TODO: include other store instructions? + return false + } + n, off := ssa.AutoVar(v) + if n.Class != ir.PPARAM { + return false + } + i, ok := lv.idx[nameOff{n, off}] + if !ok || live.Get(i) { + return false + } + live.Set(i) + return true +} + +func mayFault(v *ssa.Value) bool { + switch v.Op { + case ssa.OpLoadReg, ssa.OpStoreReg, ssa.OpCopy, ssa.OpPhi, + ssa.OpVarDef, ssa.OpVarKill, ssa.OpVarLive, ssa.OpKeepAlive, + ssa.OpSelect0, ssa.OpSelect1, ssa.OpSelectN, ssa.OpMakeResult, + ssa.OpConvert, ssa.OpInlMark, ssa.OpGetG: + return false + } + if len(v.Args) == 0 { + return false // assume constant op cannot fault + } + return true // conservatively assume all other ops could fault +} + +func (lv *argLiveness) print() { + fmt.Println("argument liveness:", lv.f.Name) + live := bitvec.New(int32(len(lv.args))) + for _, b := range lv.f.Blocks { + be := &lv.be[b.ID] + + fmt.Printf("%v: live in: ", b) + lv.printLivenessVec(be.livein) + if idx, ok := lv.blockIdx[b.ID]; ok { + fmt.Printf(" #%d", idx) + } + fmt.Println() + + for _, v := range b.Values { + if lv.valueEffect(v, live) { + fmt.Printf(" %v: ", v) + lv.printLivenessVec(live) + if idx, ok := lv.valueIdx[v.ID]; ok { + fmt.Printf(" #%d", idx) + } + fmt.Println() + } + } + + fmt.Printf("%v: live out: ", b) + lv.printLivenessVec(be.liveout) + fmt.Println() + } + fmt.Println("liveness maps data:", lv.fn.LSym.Func().ArgLiveInfo.P) +} + +func (lv *argLiveness) printLivenessVec(bv bitvec.BitVec) { + for i, a := range lv.args { + if bv.Get(int32(i)) { + fmt.Printf("%v ", a) + } + } +} + +func (lv *argLiveness) emit() *obj.LSym { + livenessMaps := lv.bvset.extractUnique() + + // stack offsets of register arg spill slots + argOffsets := make([]uint8, len(lv.args)) + for i, a := range lv.args { + off := a.FrameOffset() + if off > 0xff { + panic("offset too large") + } + argOffsets[i] = uint8(off) + } + + idx2off := make([]int, len(livenessMaps)) + + lsym := base.Ctxt.Lookup(lv.fn.LSym.Name + ".argliveinfo") + lsym.Set(obj.AttrContentAddressable, true) + + off := objw.Uint8(lsym, 0, argOffsets[0]) // smallest offset that needs liveness info. + for idx, live := range livenessMaps { + idx2off[idx] = off + off = objw.BitVec(lsym, off, live) + } + + // Update liveness indices to offsets. + for i, x := range lv.blockIdx { + if x != allLiveIdx { + lv.blockIdx[i] = idx2off[x] + } + } + for i, x := range lv.valueIdx { + if x != allLiveIdx { + lv.valueIdx[i] = idx2off[x] + } + } + + return lsym +} diff --git a/src/cmd/compile/internal/liveness/bvset.go b/src/cmd/compile/internal/liveness/bvset.go index 3431f54ede..60b2593867 100644 --- a/src/cmd/compile/internal/liveness/bvset.go +++ b/src/cmd/compile/internal/liveness/bvset.go @@ -47,9 +47,10 @@ func (m *bvecSet) grow() { m.index = newIndex } -// add adds bv to the set and returns its index in m.extractUnique. -// The caller must not modify bv after this. -func (m *bvecSet) add(bv bitvec.BitVec) int { +// add adds bv to the set and returns its index in m.extractUnique, +// and whether it is newly added. +// If it is newly added, the caller must not modify bv after this. +func (m *bvecSet) add(bv bitvec.BitVec) (int, bool) { if len(m.uniq)*4 >= len(m.index) { m.grow() } @@ -62,12 +63,12 @@ func (m *bvecSet) add(bv bitvec.BitVec) int { // New bvec. index[h] = len(m.uniq) m.uniq = append(m.uniq, bv) - return len(m.uniq) - 1 + return len(m.uniq) - 1, true } jlive := m.uniq[j] if bv.Eq(jlive) { // Existing bvec. - return j + return j, false } h++ diff --git a/src/cmd/compile/internal/liveness/plive.go b/src/cmd/compile/internal/liveness/plive.go index 56580d11b5..3202e506c8 100644 --- a/src/cmd/compile/internal/liveness/plive.go +++ b/src/cmd/compile/internal/liveness/plive.go @@ -854,8 +854,9 @@ func (lv *liveness) epilogue() { if lv.fn.OpenCodedDeferDisallowed() { lv.livenessMap.DeferReturn = objw.LivenessDontCare } else { + idx, _ := lv.stackMapSet.add(livedefer) lv.livenessMap.DeferReturn = objw.LivenessIndex{ - StackMapIndex: lv.stackMapSet.add(livedefer), + StackMapIndex: idx, IsUnsafePoint: false, } } @@ -902,7 +903,7 @@ func (lv *liveness) compact(b *ssa.Block) { isUnsafePoint := lv.allUnsafe || v.Op != ssa.OpClobber && lv.unsafePoints.Get(int32(v.ID)) idx := objw.LivenessIndex{StackMapIndex: objw.StackMapDontCare, IsUnsafePoint: isUnsafePoint} if hasStackMap { - idx.StackMapIndex = lv.stackMapSet.add(lv.livevars[pos]) + idx.StackMapIndex, _ = lv.stackMapSet.add(lv.livevars[pos]) pos++ } if hasStackMap || isUnsafePoint { diff --git a/src/cmd/compile/internal/ssa/op.go b/src/cmd/compile/internal/ssa/op.go index 421d856a4f..a1835dcd30 100644 --- a/src/cmd/compile/internal/ssa/op.go +++ b/src/cmd/compile/internal/ssa/op.go @@ -103,6 +103,10 @@ func (a *AuxNameOffset) String() string { return fmt.Sprintf("%s+%d", a.Name.Sym().Name, a.Offset) } +func (a *AuxNameOffset) FrameOffset() int64 { + return a.Name.FrameOffset() + a.Offset +} + type AuxCall struct { Fn *obj.LSym reg *regInfo // regInfo for this call diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 6b595ea75d..b84199790f 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -6729,6 +6729,7 @@ func genssa(f *ssa.Func, pp *objw.Progs) { s.livenessMap, s.partLiveArgs = liveness.Compute(e.curfn, f, e.stkptrsize, pp) emitArgInfo(e, f, pp) + argLiveBlockMap, argLiveValueMap := liveness.ArgLiveness(e.curfn, f, pp) openDeferInfo := e.curfn.LSym.Func().OpenCodedDeferInfo if openDeferInfo != nil { @@ -6786,6 +6787,8 @@ func genssa(f *ssa.Func, pp *objw.Progs) { // Progs that are in the set above and have that source position. var inlMarksByPos map[src.XPos][]*obj.Prog + var argLiveIdx int = -1 // argument liveness info index + // Emit basic blocks for i, b := range f.Blocks { s.bstart[b.ID] = s.pp.Next @@ -6799,6 +6802,13 @@ func genssa(f *ssa.Func, pp *objw.Progs) { // preemptible, unless this function is "all unsafe". s.pp.NextLive = objw.LivenessIndex{StackMapIndex: -1, IsUnsafePoint: liveness.IsUnsafe(f)} + if idx, ok := argLiveBlockMap[b.ID]; ok && idx != argLiveIdx { + argLiveIdx = idx + p := s.pp.Prog(obj.APCDATA) + p.From.SetConst(objabi.PCDATA_ArgLiveIndex) + p.To.SetConst(int64(idx)) + } + // Emit values in block Arch.SSAMarkMoves(&s, b) for _, v := range b.Values { @@ -6855,6 +6865,13 @@ func genssa(f *ssa.Func, pp *objw.Progs) { Arch.SSAGenValue(&s, v) } + if idx, ok := argLiveValueMap[v.ID]; ok && idx != argLiveIdx { + argLiveIdx = idx + p := s.pp.Prog(obj.APCDATA) + p.From.SetConst(objabi.PCDATA_ArgLiveIndex) + p.To.SetConst(int64(idx)) + } + if base.Ctxt.Flag_locationlists { valueToProgAfter[v.ID] = s.pp.Next } diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index abb37416cc..4bcfb05a5e 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -486,6 +486,7 @@ type FuncInfo struct { StackObjects *LSym OpenCodedDeferInfo *LSym ArgInfo *LSym // argument info for traceback + ArgLiveInfo *LSym // argument liveness info for traceback FuncInfoSym *LSym } diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index a590549f52..fa616691eb 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -347,7 +347,8 @@ func (w *writer) Sym(s *LSym) { strings.HasPrefix(name, "runtime.gcbits."), strings.HasSuffix(name, ".opendefer"), strings.HasSuffix(name, ".arginfo0"), - strings.HasSuffix(name, ".arginfo1"): + strings.HasSuffix(name, ".arginfo1"), + strings.HasSuffix(name, ".argliveinfo"): // These are just bytes, or varints. align = 1 case strings.HasPrefix(name, "gclocals·"): @@ -415,6 +416,7 @@ func contentHashSection(s *LSym) byte { strings.HasSuffix(name, ".opendefer") || strings.HasSuffix(name, ".arginfo0") || strings.HasSuffix(name, ".arginfo1") || + strings.HasSuffix(name, ".argliveinfo") || strings.HasSuffix(name, ".args_stackmap") || strings.HasSuffix(name, ".stkobj") { return 'F' // go.func.* or go.funcrel.* diff --git a/src/cmd/internal/objabi/funcdata.go b/src/cmd/internal/objabi/funcdata.go index 4ff0ebe13d..4d49a8d548 100644 --- a/src/cmd/internal/objabi/funcdata.go +++ b/src/cmd/internal/objabi/funcdata.go @@ -14,6 +14,7 @@ const ( PCDATA_UnsafePoint = 0 PCDATA_StackMapIndex = 1 PCDATA_InlTreeIndex = 2 + PCDATA_ArgLiveIndex = 3 FUNCDATA_ArgsPointerMaps = 0 FUNCDATA_LocalsPointerMaps = 1 @@ -21,6 +22,7 @@ const ( FUNCDATA_InlTree = 3 FUNCDATA_OpenCodedDeferInfo = 4 FUNCDATA_ArgInfo = 5 + FUNCDATA_ArgLiveInfo = 6 // ArgsSizeUnknown is set in Func.argsize to mark all functions // whose argument size is unknown (C vararg functions, and diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index 7b1a0b7d1a..720c03afd2 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -566,6 +566,7 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { strings.HasSuffix(name, ".opendefer"), strings.HasSuffix(name, ".arginfo0"), strings.HasSuffix(name, ".arginfo1"), + strings.HasSuffix(name, ".argliveinfo"), strings.HasSuffix(name, ".args_stackmap"), strings.HasSuffix(name, ".stkobj"): ldr.SetAttrNotInSymbolTable(s, true) diff --git a/src/runtime/funcdata.h b/src/runtime/funcdata.h index 15f1b5c9a1..a454dcaa69 100644 --- a/src/runtime/funcdata.h +++ b/src/runtime/funcdata.h @@ -11,6 +11,7 @@ #define PCDATA_UnsafePoint 0 #define PCDATA_StackMapIndex 1 #define PCDATA_InlTreeIndex 2 +#define PCDATA_ArgLiveIndex 3 #define FUNCDATA_ArgsPointerMaps 0 /* garbage collector blocks */ #define FUNCDATA_LocalsPointerMaps 1 @@ -18,6 +19,7 @@ #define FUNCDATA_InlTree 3 #define FUNCDATA_OpenCodedDeferInfo 4 /* info for func with open-coded defers */ #define FUNCDATA_ArgInfo 5 +#define FUNCDATA_ArgLiveInfo 6 // Pseudo-assembly statements. diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index ced39026c9..41161d6f90 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -301,6 +301,7 @@ const ( _PCDATA_UnsafePoint = 0 _PCDATA_StackMapIndex = 1 _PCDATA_InlTreeIndex = 2 + _PCDATA_ArgLiveIndex = 3 _FUNCDATA_ArgsPointerMaps = 0 _FUNCDATA_LocalsPointerMaps = 1 @@ -308,6 +309,7 @@ const ( _FUNCDATA_InlTree = 3 _FUNCDATA_OpenCodedDeferInfo = 4 _FUNCDATA_ArgInfo = 5 + _FUNCDATA_ArgLiveInfo = 6 _ArgsSizeUnknown = -0x80000000 ) diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go index 7e1b14ccf2..5de1abce9a 100644 --- a/src/runtime/traceback.go +++ b/src/runtime/traceback.go @@ -427,7 +427,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in } print(name, "(") argp := unsafe.Pointer(frame.argp) - printArgs(f, argp) + printArgs(f, argp, tracepc) print(")\n") print("\t", file, ":", line) if frame.pc > f.entry() { @@ -540,7 +540,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in } // printArgs prints function arguments in traceback. -func printArgs(f funcInfo, argp unsafe.Pointer) { +func printArgs(f funcInfo, argp unsafe.Pointer, pc uintptr) { // The "instruction" of argument printing is encoded in _FUNCDATA_ArgInfo. // See cmd/compile/internal/ssagen.emitArgInfo for the description of the // encoding. @@ -564,7 +564,25 @@ func printArgs(f funcInfo, argp unsafe.Pointer) { return } - print1 := func(off, sz uint8) { + liveInfo := funcdata(f, _FUNCDATA_ArgLiveInfo) + liveIdx := pcdatavalue(f, _PCDATA_ArgLiveIndex, pc, nil) + startOffset := uint8(0xff) // smallest offset that needs liveness info (slots with a lower offset is always live) + if liveInfo != nil { + startOffset = *(*uint8)(liveInfo) + } + + isLive := func(off, slotIdx uint8) bool { + if liveInfo == nil || liveIdx <= 0 { + return true // no liveness info, always live + } + if off < startOffset { + return true + } + bits := *(*uint8)(add(liveInfo, uintptr(liveIdx)+uintptr(slotIdx/8))) + return bits&(1<<(slotIdx%8)) != 0 + } + + print1 := func(off, sz, slotIdx uint8) { x := readUnaligned64(add(argp, uintptr(off))) // mask out irrelevant bits if sz < 8 { @@ -576,6 +594,9 @@ func printArgs(f funcInfo, argp unsafe.Pointer) { } } print(hex(x)) + if !isLive(off, slotIdx) { + print("?") + } } start := true @@ -585,6 +606,7 @@ func printArgs(f funcInfo, argp unsafe.Pointer) { } } pi := 0 + slotIdx := uint8(0) // register arg spill slot index printloop: for { o := p[pi] @@ -609,7 +631,10 @@ printloop: printcomma() sz := p[pi] pi++ - print1(o, sz) + print1(o, sz, slotIdx) + if o >= startOffset { + slotIdx++ + } } start = false } diff --git a/src/runtime/traceback_test.go b/src/runtime/traceback_test.go index 83b86a7e90..de9580ae53 100644 --- a/src/runtime/traceback_test.go +++ b/src/runtime/traceback_test.go @@ -6,6 +6,7 @@ package runtime_test import ( "bytes" + "internal/goexperiment" "runtime" "testing" ) @@ -13,6 +14,13 @@ import ( var testTracebackArgsBuf [1000]byte func TestTracebackArgs(t *testing.T) { + abiSel := func(x, y string) string { // select expected output based on ABI + if goexperiment.RegabiArgs { + return x + } + return y + } + tests := []struct { fn func() int expect string @@ -105,6 +113,52 @@ func TestTracebackArgs(t *testing.T) { func() int { return testTracebackArgs8d(testArgsType8d{1, 2, 3, 4, 5, 6, 7, 8, [3]int{9, 10, 11}, 12}) }, "testTracebackArgs8d({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, {0x9, 0xa, ...}, ...})", }, + + // Register argument liveness. + // 1, 3 are used and live, 2, 4 are dead (in register ABI). + // Address-taken (7) and stack ({5, 6}) args are always live. + { + func() int { + poisonStack() // poison arg area to make output deterministic + return testTracebackArgs9(1, 2, 3, 4, [2]int{5, 6}, 7) + }, + abiSel( + "testTracebackArgs9(0x1, 0xffffffff?, 0x3, 0xff?, {0x5, 0x6}, 0x7)", + "testTracebackArgs9(0x1, 0x2, 0x3, 0x4, {0x5, 0x6}, 0x7)"), + }, + // No live. + // (Note: this assume at least 5 int registers if register ABI is used.) + { + func() int { + poisonStack() // poison arg area to make output deterministic + return testTracebackArgs10(1, 2, 3, 4, 5) + }, + abiSel( + "testTracebackArgs10(0xffffffff?, 0xffffffff?, 0xffffffff?, 0xffffffff?, 0xffffffff?)", + "testTracebackArgs10(0x1, 0x2, 0x3, 0x4, 0x5)"), + }, + // Conditional spills. + // Spill in conditional, not executed. + { + func() int { + poisonStack() // poison arg area to make output deterministic + return testTracebackArgs11a(1, 2, 3) + }, + abiSel( + "testTracebackArgs11a(0xffffffff?, 0xffffffff?, 0xffffffff?)", + "testTracebackArgs11a(0x1, 0x2, 0x3)"), + }, + // 2 spills in conditional, not executed; 3 spills in conditional, executed, but not statically known. + // So print 0x3?. + { + func() int { + poisonStack() // poison arg area to make output deterministic + return testTracebackArgs11b(1, 2, 3, 4) + }, + abiSel( + "testTracebackArgs11b(0xffffffff?, 0xffffffff?, 0x3?, 0x4)", + "testTracebackArgs11b(0x1, 0x2, 0x3, 0x4)"), + }, } for _, test := range tests { n := test.fn() @@ -290,3 +344,62 @@ func testTracebackArgs8d(a testArgsType8d) int { } return n } + +//go:noinline +func testTracebackArgs9(a int64, b int32, c int16, d int8, x [2]int, y int) int { + if a < 0 { + println(&y) // take address, make y live, even if no longer used at traceback + } + n := runtime.Stack(testTracebackArgsBuf[:], false) + if a < 0 { + // use half of in-reg args to keep them alive, the other half are dead + return int(a) + int(c) + } + return n +} + +//go:noinline +func testTracebackArgs10(a, b, c, d, e int32) int { + // no use of any args + return runtime.Stack(testTracebackArgsBuf[:], false) +} + +// norace to avoid race instrumentation changing spill locations. +// +//go:norace +//go:noinline +func testTracebackArgs11a(a, b, c int32) int { + if a < 0 { + println(a, b, c) // spill in a conditional, may not execute + } + if b < 0 { + return int(a + b + c) + } + return runtime.Stack(testTracebackArgsBuf[:], false) +} + +// norace to avoid race instrumentation changing spill locations. +// +//go:norace +//go:noinline +func testTracebackArgs11b(a, b, c, d int32) int { + var x int32 + if a < 0 { + print() // spill b in a conditional + x = b + } else { + print() // spill c in a conditional + x = c + } + if d < 0 { // d is always needed + return int(x + d) + } + return runtime.Stack(testTracebackArgsBuf[:], false) +} + +// Poison the arg area with deterministic values. +// +//go:noinline +func poisonStack() [20]int { + return [20]int{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1} +} -- GitLab From 51be206114b559f7ea26fe2290f8ed274a2080c3 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 28 Oct 2021 01:55:10 +0700 Subject: [PATCH 1777/2500] runtime/testdata/testprogcgo: fix TestCgoPanicCallback A cgo file with "//export" declarations is not permitted to have function definitions in the cgo comments. Fixes #49188 Change-Id: I5c24b62b259871473ee984cea96a0edd7d42d23a Reviewed-on: https://go-review.googlesource.com/c/go/+/359195 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/runtime/testdata/testprogcgo/panic.c | 9 +++++++++ src/runtime/testdata/testprogcgo/panic.go | 8 +------- 2 files changed, 10 insertions(+), 7 deletions(-) create mode 100644 src/runtime/testdata/testprogcgo/panic.c diff --git a/src/runtime/testdata/testprogcgo/panic.c b/src/runtime/testdata/testprogcgo/panic.c new file mode 100644 index 0000000000..deb5ed5a60 --- /dev/null +++ b/src/runtime/testdata/testprogcgo/panic.c @@ -0,0 +1,9 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +extern void panic_callback(); + +void call_callback(void) { + panic_callback(); +} diff --git a/src/runtime/testdata/testprogcgo/panic.go b/src/runtime/testdata/testprogcgo/panic.go index 4ddef3abcd..57ac89540e 100644 --- a/src/runtime/testdata/testprogcgo/panic.go +++ b/src/runtime/testdata/testprogcgo/panic.go @@ -1,16 +1,10 @@ package main -import "C" - // This program will crash. // We want to test unwinding from a cgo callback. /* -void panic_callback(); - -static void call_callback(void) { - panic_callback(); -} +void call_callback(void); */ import "C" -- GitLab From 4fefd439a4087ec4a4cb7a61cfe15801115321d2 Mon Sep 17 00:00:00 2001 From: Mark Pulford Date: Fri, 22 Oct 2021 12:36:00 +1100 Subject: [PATCH 1778/2500] cmd/go: fix recognition of Fossil checkout directories Use ".fslckout" or "_FOSSIL_" files to correctly identify the root of Fossil checkout directories. Previously, Go has assumed VCS checkouts are indicated by a dot-file named after the VCS command (eg, .git, .hg, .fossil). This is not normally true for Fossil, but has worked so far since Go downloads repositories into a ".fossil" file before opening (checking out). Using the incorrect path prevents Go identifying Fossil checkouts and correctly tagging with -buildvcs (to be added in a follow up CL). Change-Id: I3c030a0b600dfe7f4b3fcf1551b1d7cb84629b81 Reviewed-on: https://go-review.googlesource.com/c/go/+/357954 Trust: Ian Lance Taylor Reviewed-by: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot --- src/cmd/go/internal/vcs/vcs.go | 53 +++++++++++++++++++++-------- src/cmd/go/internal/vcs/vcs_test.go | 48 ++++++++++++++------------ 2 files changed, 65 insertions(+), 36 deletions(-) diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go index c4853d7ae3..990e1d4248 100644 --- a/src/cmd/go/internal/vcs/vcs.go +++ b/src/cmd/go/internal/vcs/vcs.go @@ -35,8 +35,9 @@ import ( // A Cmd describes how to use a version control system // like Mercurial, Git, or Subversion. type Cmd struct { - Name string - Cmd string // name of binary to invoke command + Name string + Cmd string // name of binary to invoke command + RootNames []string // filename indicating the root of a checkout directory CreateCmd []string // commands to download a fresh copy of a repository DownloadCmd []string // commands to download updates into an existing repository @@ -129,8 +130,9 @@ func vcsByCmd(cmd string) *Cmd { // vcsHg describes how to use Mercurial. var vcsHg = &Cmd{ - Name: "Mercurial", - Cmd: "hg", + Name: "Mercurial", + Cmd: "hg", + RootNames: []string{".hg"}, CreateCmd: []string{"clone -U -- {repo} {dir}"}, DownloadCmd: []string{"pull"}, @@ -212,8 +214,9 @@ func parseRevTime(out []byte) (string, time.Time, error) { // vcsGit describes how to use Git. var vcsGit = &Cmd{ - Name: "Git", - Cmd: "git", + Name: "Git", + Cmd: "git", + RootNames: []string{".git"}, CreateCmd: []string{"clone -- {repo} {dir}", "-go-internal-cd {dir} submodule update --init --recursive"}, DownloadCmd: []string{"pull --ff-only", "submodule update --init --recursive"}, @@ -325,8 +328,9 @@ func gitStatus(vcsGit *Cmd, rootDir string) (Status, error) { // vcsBzr describes how to use Bazaar. var vcsBzr = &Cmd{ - Name: "Bazaar", - Cmd: "bzr", + Name: "Bazaar", + Cmd: "bzr", + RootNames: []string{".bzr"}, CreateCmd: []string{"branch -- {repo} {dir}"}, @@ -387,8 +391,9 @@ func bzrResolveRepo(vcsBzr *Cmd, rootDir, remoteRepo string) (realRepo string, e // vcsSvn describes how to use Subversion. var vcsSvn = &Cmd{ - Name: "Subversion", - Cmd: "svn", + Name: "Subversion", + Cmd: "svn", + RootNames: []string{".svn"}, CreateCmd: []string{"checkout -- {repo} {dir}"}, DownloadCmd: []string{"update"}, @@ -437,8 +442,9 @@ const fossilRepoName = ".fossil" // vcsFossil describes how to use Fossil (fossil-scm.org) var vcsFossil = &Cmd{ - Name: "Fossil", - Cmd: "fossil", + Name: "Fossil", + Cmd: "fossil", + RootNames: []string{".fslckout", "_FOSSIL_"}, CreateCmd: []string{"-go-internal-mkdir {dir} clone -- {repo} " + filepath.Join("{dir}", fossilRepoName), "-go-internal-cd {dir} open .fossil"}, DownloadCmd: []string{"up"}, @@ -662,7 +668,7 @@ func FromDir(dir, srcRoot string, allowNesting bool) (repoDir string, vcsCmd *Cm origDir := dir for len(dir) > len(srcRoot) { for _, vcs := range vcsList { - if _, err := os.Stat(filepath.Join(dir, "."+vcs.Cmd)); err == nil { + if _, err := statAny(dir, vcs.RootNames); err == nil { // Record first VCS we find. // If allowNesting is false (as it is in GOPATH), keep looking for // repositories in parent directories and report an error if one is @@ -698,6 +704,25 @@ func FromDir(dir, srcRoot string, allowNesting bool) (repoDir string, vcsCmd *Cm return repoDir, vcsCmd, nil } +// statAny provides FileInfo for the first filename found in the directory. +// Otherwise, it returns the last error seen. +func statAny(dir string, filenames []string) (os.FileInfo, error) { + if len(filenames) == 0 { + return nil, errors.New("invalid argument: no filenames provided") + } + + var err error + var fi os.FileInfo + for _, name := range filenames { + fi, err = os.Stat(filepath.Join(dir, name)) + if err == nil { + return fi, nil + } + } + + return nil, err +} + type vcsNotFoundError struct { dir string } @@ -855,7 +880,7 @@ func CheckNested(vcs *Cmd, dir, srcRoot string) error { otherDir := dir for len(otherDir) > len(srcRoot) { for _, otherVCS := range vcsList { - if _, err := os.Stat(filepath.Join(otherDir, "."+otherVCS.Cmd)); err == nil { + if _, err := statAny(otherDir, otherVCS.RootNames); err == nil { // Allow expected vcs in original dir. if otherDir == dir && otherVCS == vcs { continue diff --git a/src/cmd/go/internal/vcs/vcs_test.go b/src/cmd/go/internal/vcs/vcs_test.go index 9ac0a56a07..c4e4f4d3c6 100644 --- a/src/cmd/go/internal/vcs/vcs_test.go +++ b/src/cmd/go/internal/vcs/vcs_test.go @@ -6,6 +6,7 @@ package vcs import ( "errors" + "fmt" "internal/testenv" "os" "path/filepath" @@ -214,32 +215,35 @@ func TestFromDir(t *testing.T) { defer os.RemoveAll(tempDir) for j, vcs := range vcsList { - dir := filepath.Join(tempDir, "example.com", vcs.Name, "."+vcs.Cmd) - if j&1 == 0 { - err := os.MkdirAll(dir, 0755) - if err != nil { - t.Fatal(err) + for r, rootName := range vcs.RootNames { + vcsName := fmt.Sprint(vcs.Name, r) + dir := filepath.Join(tempDir, "example.com", vcsName, rootName) + if j&1 == 0 { + err := os.MkdirAll(dir, 0755) + if err != nil { + t.Fatal(err) + } + } else { + err := os.MkdirAll(filepath.Dir(dir), 0755) + if err != nil { + t.Fatal(err) + } + f, err := os.Create(dir) + if err != nil { + t.Fatal(err) + } + f.Close() } - } else { - err := os.MkdirAll(filepath.Dir(dir), 0755) + + wantRepoDir := filepath.Dir(dir) + gotRepoDir, gotVCS, err := FromDir(dir, tempDir, false) if err != nil { - t.Fatal(err) + t.Errorf("FromDir(%q, %q): %v", dir, tempDir, err) + continue } - f, err := os.Create(dir) - if err != nil { - t.Fatal(err) + if gotRepoDir != wantRepoDir || gotVCS.Name != vcs.Name { + t.Errorf("FromDir(%q, %q) = RepoDir(%s), VCS(%s); want RepoDir(%s), VCS(%s)", dir, tempDir, gotRepoDir, gotVCS.Name, wantRepoDir, vcs.Name) } - f.Close() - } - - wantRepoDir := filepath.Dir(dir) - gotRepoDir, gotVCS, err := FromDir(dir, tempDir, false) - if err != nil { - t.Errorf("FromDir(%q, %q): %v", dir, tempDir, err) - continue - } - if gotRepoDir != wantRepoDir || gotVCS.Name != vcs.Name { - t.Errorf("FromDir(%q, %q) = RepoDir(%s), VCS(%s); want RepoDir(%s), VCS(%s)", dir, tempDir, gotRepoDir, gotVCS.Name, wantRepoDir, vcs.Name) } } } -- GitLab From de1abf76fb69739c6cad463454a55fe9c33f63ac Mon Sep 17 00:00:00 2001 From: Mark Pulford Date: Fri, 22 Oct 2021 11:21:28 +1100 Subject: [PATCH 1779/2500] cmd/go: stamp Fossil VCS status into binaries For #37475 Change-Id: I09fa1344051088ce37727176d9ec6b38891d1a9f Reviewed-on: https://go-review.googlesource.com/c/go/+/357955 Trust: Ian Lance Taylor Trust: Bryan C. Mills Reviewed-by: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot --- src/cmd/go/internal/vcs/vcs.go | 55 ++++++++++++ .../script/version_buildvcs_fossil.txt | 90 +++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 src/cmd/go/testdata/script/version_buildvcs_fossil.txt diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go index 990e1d4248..6d2996e17a 100644 --- a/src/cmd/go/internal/vcs/vcs.go +++ b/src/cmd/go/internal/vcs/vcs.go @@ -455,6 +455,7 @@ var vcsFossil = &Cmd{ Scheme: []string{"https", "http"}, RemoteRepo: fossilRemoteRepo, + Status: fossilStatus, } func fossilRemoteRepo(vcsFossil *Cmd, rootDir string) (remoteRepo string, err error) { @@ -465,6 +466,60 @@ func fossilRemoteRepo(vcsFossil *Cmd, rootDir string) (remoteRepo string, err er return strings.TrimSpace(string(out)), nil } +var errFossilInfo = errors.New("unable to parse output of fossil info") + +func fossilStatus(vcsFossil *Cmd, rootDir string) (Status, error) { + outb, err := vcsFossil.runOutputVerboseOnly(rootDir, "info") + if err != nil { + return Status{}, err + } + out := string(outb) + + // Expect: + // ... + // checkout: 91ed71f22c77be0c3e250920f47bfd4e1f9024d2 2021-09-21 12:00:00 UTC + // ... + + // Extract revision and commit time. + // Ensure line ends with UTC (known timezone offset). + const prefix = "\ncheckout:" + const suffix = " UTC" + i := strings.Index(out, prefix) + if i < 0 { + return Status{}, errFossilInfo + } + checkout := out[i+len(prefix):] + i = strings.Index(checkout, suffix) + if i < 0 { + return Status{}, errFossilInfo + } + checkout = strings.TrimSpace(checkout[:i]) + + i = strings.IndexByte(checkout, ' ') + if i < 0 { + return Status{}, errFossilInfo + } + rev := checkout[:i] + + commitTime, err := time.ParseInLocation("2006-01-02 15:04:05", checkout[i+1:], time.UTC) + if err != nil { + return Status{}, fmt.Errorf("%v: %v", errFossilInfo, err) + } + + // Also look for untracked changes. + outb, err = vcsFossil.runOutputVerboseOnly(rootDir, "changes --differ") + if err != nil { + return Status{}, err + } + uncommitted := len(outb) > 0 + + return Status{ + Revision: rev, + CommitTime: commitTime, + Uncommitted: uncommitted, + }, nil +} + func (v *Cmd) String() string { return v.Name } diff --git a/src/cmd/go/testdata/script/version_buildvcs_fossil.txt b/src/cmd/go/testdata/script/version_buildvcs_fossil.txt new file mode 100644 index 0000000000..3a4bde883f --- /dev/null +++ b/src/cmd/go/testdata/script/version_buildvcs_fossil.txt @@ -0,0 +1,90 @@ +# This test checks that VCS information is stamped into Go binaries by default, +# controlled with -buildvcs. This test focuses on Fossil specifics. +# The Git test covers common functionality. + +# "fossil" is the Fossil file server on Plan 9. +[plan9] skip +[!exec:fossil] skip +[short] skip +env GOBIN=$WORK/gopath/bin +env oldpath=$PATH +env HOME=$WORK +env USER=gopher +[!windows] env fslckout=.fslckout +[windows] env fslckout=_FOSSIL_ +exec pwd +exec fossil init repo.fossil +cd repo/a + +# If there's no local repository, there's no VCS info. +go install +go version -m $GOBIN/a$GOEXE +! stdout fossilrevision +rm $GOBIN/a$GOEXE + +# If there is a repository, but it can't be used for some reason, +# there should be an error. It should hint about -buildvcs=false. +cd .. +mkdir $fslckout +env PATH=$WORK${/}fakebin${:}$oldpath +chmod 0755 $WORK/fakebin/fossil +! exec fossil help +cd a +! go install +stderr '^error obtaining VCS status: exit status 1\n\tUse -buildvcs=false to disable VCS stamping.$' +rm $GOBIN/a$GOEXE +cd .. +env PATH=$oldpath +rm $fslckout + +# Revision and commit time are tagged for repositories with commits. +exec fossil open ../repo.fossil -f +exec fossil add a README +exec fossil commit -m 'initial commit' +cd a +go install +go version -m $GOBIN/a$GOEXE +stdout '^\tbuild\tfossilrevision\t' +stdout '^\tbuild\tfossilcommittime\t' +stdout '^\tbuild\tfossiluncommitted\tfalse$' +rm $GOBIN/a$GOEXE + +# Building with -buildvcs=false suppresses the info. +go install -buildvcs=false +go version -m $GOBIN/a$GOEXE +! stdout fossilrevision +rm $GOBIN/a$GOEXE + +# An untracked file is shown as uncommitted, even if it isn't part of the build. +cp ../../outside/empty.txt . +go install +go version -m $GOBIN/a$GOEXE +stdout '^\tbuild\tfossiluncommitted\ttrue$' +rm empty.txt +rm $GOBIN/a$GOEXE + +# An edited file is shown as uncommitted, even if it isn't part of the build. +cp ../../outside/empty.txt ../README +go install +go version -m $GOBIN/a$GOEXE +stdout '^\tbuild\tfossiluncommitted\ttrue$' +exec fossil revert ../README +rm $GOBIN/a$GOEXE + +-- $WORK/fakebin/fossil -- +#!/bin/sh +exit 1 +-- $WORK/fakebin/fossil.bat -- +exit 1 +-- repo/README -- +Far out in the uncharted backwaters of the unfashionable end of the western +spiral arm of the Galaxy lies a small, unregarded yellow sun. +-- repo/a/go.mod -- +module example.com/a + +go 1.18 +-- repo/a/a.go -- +package main + +func main() {} +-- outside/empty.txt -- -- GitLab From a3c4ac0fbca51fc2e3369c93738419fc947bda77 Mon Sep 17 00:00:00 2001 From: zhouguangyuan Date: Fri, 22 Oct 2021 17:00:46 +0800 Subject: [PATCH 1780/2500] reflect: skip duplicate check in StructOf when the name of a field is "_" Fixes #49110 Change-Id: I32c2cb26cca067a4a676ce4bbc3e51f1e0cdb259 Reviewed-on: https://go-review.googlesource.com/c/go/+/357959 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Reviewed-by: Dan Kortschak Reviewed-by: Sebastien Binet Trust: Cuong Manh Le --- src/reflect/type.go | 2 +- test/fixedbugs/issue49110.go | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 test/fixedbugs/issue49110.go diff --git a/src/reflect/type.go b/src/reflect/type.go index 2bb2438381..0896949d7e 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -2606,7 +2606,7 @@ func StructOf(fields []StructField) Type { } } } - if _, dup := fset[name]; dup { + if _, dup := fset[name]; dup && name != "_" { panic("reflect.StructOf: duplicate field " + name) } fset[name] = struct{}{} diff --git a/test/fixedbugs/issue49110.go b/test/fixedbugs/issue49110.go new file mode 100644 index 0000000000..5e1bde9f00 --- /dev/null +++ b/test/fixedbugs/issue49110.go @@ -0,0 +1,16 @@ +// run + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "reflect" + +func main() { + _ = reflect.StructOf([]reflect.StructField{ + {Name: "_", PkgPath: "main", Type: reflect.TypeOf(int(0))}, + {Name: "_", PkgPath: "main", Type: reflect.TypeOf(int(0))}, + }) +} -- GitLab From 063ff7f7a0fb41442916d0eda3fc128ca779d424 Mon Sep 17 00:00:00 2001 From: Mark Pulford Date: Fri, 22 Oct 2021 18:23:18 +1100 Subject: [PATCH 1781/2500] cmd/go: stamp Bazaar VCS status into binaries For #37475 Change-Id: I728b7aeee5c38ec337e9a5b073050c3b0afc720d Reviewed-on: https://go-review.googlesource.com/c/go/+/357956 Trust: Ian Lance Taylor Reviewed-by: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot --- src/cmd/go/internal/vcs/vcs.go | 58 ++++++++++ .../testdata/script/version_buildvcs_bzr.txt | 104 ++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 src/cmd/go/testdata/script/version_buildvcs_bzr.txt diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go index 6d2996e17a..b2ce80325a 100644 --- a/src/cmd/go/internal/vcs/vcs.go +++ b/src/cmd/go/internal/vcs/vcs.go @@ -346,6 +346,7 @@ var vcsBzr = &Cmd{ PingCmd: "info -- {scheme}://{repo}", RemoteRepo: bzrRemoteRepo, ResolveRepo: bzrResolveRepo, + Status: bzrStatus, } func bzrRemoteRepo(vcsBzr *Cmd, rootDir string) (remoteRepo string, err error) { @@ -389,6 +390,63 @@ func bzrResolveRepo(vcsBzr *Cmd, rootDir, remoteRepo string) (realRepo string, e return strings.TrimSpace(out), nil } +func bzrStatus(vcsBzr *Cmd, rootDir string) (Status, error) { + outb, err := vcsBzr.runOutputVerboseOnly(rootDir, "version-info") + if err != nil { + return Status{}, err + } + out := string(outb) + + // Expect (non-empty repositories only): + // + // revision-id: gopher@gopher.net-20211021072330-qshok76wfypw9lpm + // date: 2021-09-21 12:00:00 +1000 + // ... + var rev string + var commitTime time.Time + + for _, line := range strings.Split(out, "\n") { + i := strings.IndexByte(line, ':') + if i < 0 { + continue + } + key := line[:i] + value := strings.TrimSpace(line[i+1:]) + + switch key { + case "revision-id": + rev = value + case "date": + var err error + commitTime, err = time.Parse("2006-01-02 15:04:05 -0700", value) + if err != nil { + return Status{}, errors.New("unable to parse output of bzr version-info") + } + } + } + + outb, err = vcsBzr.runOutputVerboseOnly(rootDir, "status") + if err != nil { + return Status{}, err + } + + // Skip warning when working directory is set to an older revision. + if bytes.HasPrefix(outb, []byte("working tree is out of date")) { + i := bytes.IndexByte(outb, '\n') + if i < 0 { + i = len(outb) + } + outb = outb[:i] + } + uncommitted := len(outb) > 0 + + return Status{ + Revision: rev, + CommitTime: commitTime, + Uncommitted: uncommitted, + }, nil +} + // vcsSvn describes how to use Subversion. var vcsSvn = &Cmd{ Name: "Subversion", diff --git a/src/cmd/go/testdata/script/version_buildvcs_bzr.txt b/src/cmd/go/testdata/script/version_buildvcs_bzr.txt new file mode 100644 index 0000000000..83069713d7 --- /dev/null +++ b/src/cmd/go/testdata/script/version_buildvcs_bzr.txt @@ -0,0 +1,104 @@ +# This test checks that VCS information is stamped into Go binaries by default, +# controlled with -buildvcs. This test focuses on Bazaar specifics. +# The Git test covers common functionality. + +[!exec:bzr] skip +[short] skip +env GOBIN=$WORK/gopath/bin +env oldpath=$PATH +env HOME=$WORK +cd repo/a +exec bzr whoami 'J.R. Gopher ' + +# If there's no local repository, there's no VCS info. +go install +go version -m $GOBIN/a$GOEXE +! stdout bzrrevision +rm $GOBIN/a$GOEXE + +# If there is a repository, but it can't be used for some reason, +# there should be an error. It should hint about -buildvcs=false. +cd .. +mkdir .bzr +env PATH=$WORK${/}fakebin${:}$oldpath +chmod 0755 $WORK/fakebin/bzr +! exec bzr help +cd a +! go install +stderr '^error obtaining VCS status: exit status 1\n\tUse -buildvcs=false to disable VCS stamping.$' +rm $GOBIN/a$GOEXE +cd .. +env PATH=$oldpath +rm .bzr + +# If there is an empty repository in a parent directory, only "uncommitted" is tagged. +exec bzr init +cd a +go install +go version -m $GOBIN/a$GOEXE +! stdout bzrrevision +! stdout bzrcommittime +stdout '^\tbuild\tbzruncommitted\ttrue$' +cd .. + +# Revision and commit time are tagged for repositories with commits. +exec bzr add a README +exec bzr commit -m 'initial commit' +cd a +go install +go version -m $GOBIN/a$GOEXE +stdout '^\tbuild\tbzrrevision\t' +stdout '^\tbuild\tbzrcommittime\t' +stdout '^\tbuild\tbzruncommitted\tfalse$' +rm $GOBIN/a$GOEXE + +# Building an earlier commit should still build clean. +cp ../../outside/empty.txt ../NEWS +exec bzr add ../NEWS +exec bzr commit -m 'add NEWS' +exec bzr update -r1 +go install +go version -m $GOBIN/a$GOEXE +stdout '^\tbuild\tbzrrevision\t' +stdout '^\tbuild\tbzrcommittime\t' +stdout '^\tbuild\tbzruncommitted\tfalse$' + +# Building with -buildvcs=false suppresses the info. +go install -buildvcs=false +go version -m $GOBIN/a$GOEXE +! stdout bzrrevision +rm $GOBIN/a$GOEXE + +# An untracked file is shown as uncommitted, even if it isn't part of the build. +cp ../../outside/empty.txt . +go install +go version -m $GOBIN/a$GOEXE +stdout '^\tbuild\tbzruncommitted\ttrue$' +rm empty.txt +rm $GOBIN/a$GOEXE + +# An edited file is shown as uncommitted, even if it isn't part of the build. +cp ../../outside/empty.txt ../README +go install +go version -m $GOBIN/a$GOEXE +stdout '^\tbuild\tbzruncommitted\ttrue$' +exec bzr revert ../README +rm $GOBIN/a$GOEXE + +-- $WORK/fakebin/bzr -- +#!/bin/sh +exit 1 +-- $WORK/fakebin/bzr.bat -- +exit 1 +-- repo/README -- +Far out in the uncharted backwaters of the unfashionable end of the western +spiral arm of the Galaxy lies a small, unregarded yellow sun. +-- repo/a/go.mod -- +module example.com/a + +go 1.18 +-- repo/a/a.go -- +package main + +func main() {} +-- outside/empty.txt -- -- GitLab From 749f6e9eb6d101ef2ea4b7228a966391a80aa89b Mon Sep 17 00:00:00 2001 From: Mark Pulford Date: Fri, 22 Oct 2021 18:41:41 +1100 Subject: [PATCH 1782/2500] doc/go1.18: document Fossil/Bazaar and commit time build tag support Change-Id: I032791a3cda1916099b0fd2955dcca4e69763660 Reviewed-on: https://go-review.googlesource.com/c/go/+/357958 Trust: Ian Lance Taylor Reviewed-by: Bryan C. Mills --- doc/go1.18.html | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 63a6ed8fcd..875577fd10 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -67,12 +67,13 @@ Do not send CLs removing the interior tags from such phrases.

The go command now embeds version control information in - binaries including the currently checked-out revision and a flag indicating - whether edited or untracked files are present. Version control information - is embedded if the go command is invoked in a directory within a - Git or Mercurial repository, and the main package and its - containing main module are in the same repository. This information may be - omitted using the flag -buildvcs=false. + binaries including the currently checked-out revision, commit time, and a + flag indicating whether edited or untracked files are present. Version + control information is embedded if the go command is invoked in + a directory within a Git, Mercurial, Fossil, or Bazaar repository, and the + main package and its containing main module are in the same + repository. This information may be omitted using the flag + -buildvcs=false.

-- GitLab From 79ff663754f4238bd1fe2e56f460c2f603c71b80 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 27 Oct 2021 14:11:33 -0700 Subject: [PATCH 1783/2500] constraints: remove Slice/Map/Chan Now that we permit arbitrary types as constraints, we no longer need them. For #48424 Change-Id: I15fef26a563988074650cb0801895b002c44148a Reviewed-on: https://go-review.googlesource.com/c/go/+/359258 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Robert Griesemer --- src/constraints/constraints.go | 15 ------- src/constraints/constraints_test.go | 62 ++++++----------------------- test/typeparam/issue48609.go | 4 +- 3 files changed, 13 insertions(+), 68 deletions(-) diff --git a/src/constraints/constraints.go b/src/constraints/constraints.go index 2a5f673a7e..2c033dff47 100644 --- a/src/constraints/constraints.go +++ b/src/constraints/constraints.go @@ -48,18 +48,3 @@ type Complex interface { type Ordered interface { Integer | Float | ~string } - -// Slice is a constraint that matches slices of any element type. -type Slice[Elem any] interface { - ~[]Elem -} - -// Map is a constraint that matches maps of any element and value type. -type Map[Key comparable, Val any] interface { - ~map[Key]Val -} - -// Chan is a constraint that matches channels of any element type. -type Chan[Elem any] interface { - ~chan Elem -} diff --git a/src/constraints/constraints_test.go b/src/constraints/constraints_test.go index db5a957313..538dc843cc 100644 --- a/src/constraints/constraints_test.go +++ b/src/constraints/constraints_test.go @@ -15,15 +15,12 @@ import ( ) type ( - testSigned[T Signed] struct{ f T } - testUnsigned[T Unsigned] struct{ f T } - testInteger[T Integer] struct{ f T } - testFloat[T Float] struct{ f T } - testComplex[T Complex] struct{ f T } - testOrdered[T Ordered] struct{ f T } - testSlice[T Slice[E], E any] struct{ f T } - testMap[T Map[K, V], K comparable, V any] struct{ f T } - testChan[T Chan[E], E any] struct{ f T } + testSigned[T Signed] struct{ f T } + testUnsigned[T Unsigned] struct{ f T } + testInteger[T Integer] struct{ f T } + testFloat[T Float] struct{ f T } + testComplex[T Complex] struct{ f T } + testOrdered[T Ordered] struct{ f T } ) // TestTypes passes if it compiles. @@ -40,35 +37,6 @@ type TestTypes struct { _ testOrdered[int] _ testOrdered[float64] _ testOrdered[string] - _ testSlice[[]int, int] - _ testMap[map[int]bool, int, bool] - _ testChan[chan int, int] -} - -func infer1[S Slice[E], E any](s S, v E) S { return s } -func infer2[M Map[K, V], K comparable, V any](m M, k K, v V) M { return m } -func infer3[C Chan[E], E any](c C, v E) C { return c } - -func TestInference(t *testing.T) { - var empty interface{} - - type S []int - empty = infer1(S{}, 0) - if _, ok := empty.(S); !ok { - t.Errorf("infer1(S) returned %T, expected S", empty) - } - - type M map[int]bool - empty = infer2(M{}, 0, false) - if _, ok := empty.(M); !ok { - t.Errorf("infer2(M) returned %T, expected M", empty) - } - - type C chan bool - empty = infer3(make(C), true) - if _, ok := empty.(C); !ok { - t.Errorf("infer3(C) returned %T, expected C", empty) - } } var prolog = []byte(` @@ -77,15 +45,12 @@ package constrainttest import "constraints" type ( - testSigned[T constraints.Signed] struct{ f T } - testUnsigned[T constraints.Unsigned] struct{ f T } - testInteger[T constraints.Integer] struct{ f T } - testFloat[T constraints.Float] struct{ f T } - testComplex[T constraints.Complex] struct{ f T } - testOrdered[T constraints.Ordered] struct{ f T } - testSlice[T constraints.Slice[E], E any] struct{ f T } - testMap[T constraints.Map[K, V], K comparable, V any] struct{ f T } - testChan[T constraints.Chan[E], E any] struct{ f T } + testSigned[T constraints.Signed] struct{ f T } + testUnsigned[T constraints.Unsigned] struct{ f T } + testInteger[T constraints.Integer] struct{ f T } + testFloat[T constraints.Float] struct{ f T } + testComplex[T constraints.Complex] struct{ f T } + testOrdered[T constraints.Ordered] struct{ f T } ) `) @@ -115,9 +80,6 @@ func TestFailure(t *testing.T) { {"testFloat", "int8"}, {"testComplex", "float64"}, {"testOrdered", "bool"}, - {"testSlice", "int, int"}, - {"testMap", "string, string, string"}, - {"testChan", "[]int, int"}, } { i := i test := test diff --git a/test/typeparam/issue48609.go b/test/typeparam/issue48609.go index 3ca9d6e7d6..6cf6908291 100644 --- a/test/typeparam/issue48609.go +++ b/test/typeparam/issue48609.go @@ -6,9 +6,7 @@ package p -import "constraints" - -func f[T constraints.Chan[E], E any](e E) T { +func f[T ~chan E, E any](e E) T { ch := make(T) go func() { defer close(ch) -- GitLab From a91d0b649c9ee8c64328fb124eff94dfca300d39 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 27 Oct 2021 13:55:15 -0700 Subject: [PATCH 1784/2500] cmd/compile/internal/types2: disallow lone type parameter on RHS of type declaration We may revisit this decision in a future release. By disallowing this for Go 1.18 we are ensuring that we don't lock in the generics design in a place that may need to change later. (Type declarations are the primary construct where it crucially matters what the underlying type of a type parameter is.) Comment out all tests that rely on this feature; add comments referring to issue so we can find all places easily should we change our minds. Fixes #45639. Change-Id: I730510e4da66d3716d455a9071c7778a1e4a1152 Reviewed-on: https://go-review.googlesource.com/c/go/+/359177 Trust: Robert Griesemer Trust: Dan Scales Reviewed-by: Dan Scales --- src/cmd/compile/internal/types2/api_test.go | 14 --- src/cmd/compile/internal/types2/decl.go | 9 +- .../internal/types2/testdata/check/linalg.go2 | 61 +++++----- .../types2/testdata/check/typeinst.go2 | 5 +- .../types2/testdata/check/typeinst2.go2 | 30 ++--- .../types2/testdata/check/typeparams.go2 | 19 ++-- .../types2/testdata/examples/methods.go2 | 31 +++--- .../types2/testdata/examples/types.go2 | 13 ++- .../types2/testdata/fixedbugs/issue39634.go2 | 7 +- .../types2/testdata/fixedbugs/issue39768.go2 | 17 +-- .../types2/testdata/fixedbugs/issue39938.go2 | 2 +- .../types2/testdata/fixedbugs/issue45639.go2 | 13 ++- .../types2/testdata/fixedbugs/issue47747.go2 | 67 +++++------ test/typeparam/absdiff.go | 105 +++++++++--------- test/typeparam/absdiffimp.dir/a.go | 71 ++++++------ test/typeparam/absdiffimp.dir/main.go | 38 +++---- test/typeparam/boundmethod.go | 34 +++--- test/typeparam/issue47708.go | 45 ++++---- test/typeparam/issue47740.go | 23 ++-- test/typeparam/issue47740.out | 2 - 20 files changed, 297 insertions(+), 309 deletions(-) diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index ecb5a29830..26652f3e74 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -622,13 +622,6 @@ func TestDefsInfo(t *testing.T) { {`package p3; type x int`, `x`, `type p3.x int`}, {`package p4; func f()`, `f`, `func p4.f()`}, {`package p5; func f() int { x, _ := 1, 2; return x }`, `_`, `var _ int`}, - - // generic types must be sanitized - // (need to use sufficiently nested types to provoke unexpanded types) - {genericPkg + `g0; type t[P any] P; const x = t[int](42)`, `x`, `const generic_g0.x generic_g0.t[int]`}, - {genericPkg + `g1; type t[P any] P; var x = t[int](42)`, `x`, `var generic_g1.x generic_g1.t[int]`}, - {genericPkg + `g2; type t[P any] P; type x struct{ f t[int] }`, `x`, `type generic_g2.x struct{f generic_g2.t[int]}`}, - {genericPkg + `g3; type t[P any] P; func f(x struct{ f t[string] }); var g = f`, `g`, `var generic_g3.g func(x struct{f generic_g3.t[string]})`}, } for _, test := range tests { @@ -667,13 +660,6 @@ func TestUsesInfo(t *testing.T) { {`package p2; func _() { _ = x }; var x int`, `x`, `var p2.x int`}, {`package p3; func _() { type _ x }; type x int`, `x`, `type p3.x int`}, {`package p4; func _() { _ = f }; func f()`, `f`, `func p4.f()`}, - - // generic types must be sanitized - // (need to use sufficiently nested types to provoke unexpanded types) - {genericPkg + `g0; func _() { _ = x }; type t[P any] P; const x = t[int](42)`, `x`, `const generic_g0.x generic_g0.t[int]`}, - {genericPkg + `g1; func _() { _ = x }; type t[P any] P; var x = t[int](42)`, `x`, `var generic_g1.x generic_g1.t[int]`}, - {genericPkg + `g2; func _() { type _ x }; type t[P any] P; type x struct{ f t[int] }`, `x`, `type generic_g2.x struct{f generic_g2.t[int]}`}, - {genericPkg + `g3; func _() { _ = f }; type t[P any] P; func f(x struct{ f t[string] })`, `f`, `func generic_g3.f(x struct{f generic_g3.t[string]})`}, } for _, test := range tests { diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 63be4b3223..5d2a6c531b 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -604,9 +604,12 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named named.underlying = Typ[Invalid] } - // If the RHS is a type parameter, it must be from this type declaration. - if tpar, _ := named.underlying.(*TypeParam); tpar != nil && tparamIndex(named.TypeParams().list(), tpar) < 0 { - check.errorf(tdecl.Type, "cannot use function type parameter %s as RHS in type declaration", tpar) + // Disallow a lone type parameter as the RHS of a type declaration (issue #45639). + // We can look directly at named.underlying because even if it is still a *Named + // type (underlying not fully resolved yet) it cannot become a type parameter due + // to this very restriction. + if tpar, _ := named.underlying.(*TypeParam); tpar != nil { + check.error(tdecl.Type, "cannot use a type parameter as RHS in type declaration") named.underlying = Typ[Invalid] } } diff --git a/src/cmd/compile/internal/types2/testdata/check/linalg.go2 b/src/cmd/compile/internal/types2/testdata/check/linalg.go2 index efc090a1d1..f02e773dbe 100644 --- a/src/cmd/compile/internal/types2/testdata/check/linalg.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/linalg.go2 @@ -4,8 +4,6 @@ package linalg -import "math" - // Numeric is type bound that matches any numeric type. // It would likely be in a constraints package in the standard library. type Numeric interface { @@ -52,32 +50,33 @@ type Complex interface { ~complex64 | ~complex128 } -// OrderedAbs is a helper type that defines an Abs method for -// ordered numeric types. -type OrderedAbs[T OrderedNumeric] T - -func (a OrderedAbs[T]) Abs() OrderedAbs[T] { - if a < 0 { - return -a - } - return a -} - -// ComplexAbs is a helper type that defines an Abs method for -// complex types. -type ComplexAbs[T Complex] T - -func (a ComplexAbs[T]) Abs() ComplexAbs[T] { - r := float64(real(a)) - i := float64(imag(a)) - d := math.Sqrt(r * r + i * i) - return ComplexAbs[T](complex(d, 0)) -} - -func OrderedAbsDifference[T OrderedNumeric](a, b T) T { - return T(AbsDifference(OrderedAbs[T](a), OrderedAbs[T](b))) -} - -func ComplexAbsDifference[T Complex](a, b T) T { - return T(AbsDifference(ComplexAbs[T](a), ComplexAbs[T](b))) -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// // OrderedAbs is a helper type that defines an Abs method for +// // ordered numeric types. +// type OrderedAbs[T OrderedNumeric] T +// +// func (a OrderedAbs[T]) Abs() OrderedAbs[T] { +// if a < 0 { +// return -a +// } +// return a +// } +// +// // ComplexAbs is a helper type that defines an Abs method for +// // complex types. +// type ComplexAbs[T Complex] T +// +// func (a ComplexAbs[T]) Abs() ComplexAbs[T] { +// r := float64(real(a)) +// i := float64(imag(a)) +// d := math.Sqrt(r * r + i * i) +// return ComplexAbs[T](complex(d, 0)) +// } +// +// func OrderedAbsDifference[T OrderedNumeric](a, b T) T { +// return T(AbsDifference(OrderedAbs[T](a), OrderedAbs[T](b))) +// } +// +// func ComplexAbsDifference[T Complex](a, b T) T { +// return T(AbsDifference(ComplexAbs[T](a), ComplexAbs[T](b))) +// } diff --git a/src/cmd/compile/internal/types2/testdata/check/typeinst.go2 b/src/cmd/compile/internal/types2/testdata/check/typeinst.go2 index 14f1b07ee2..a3d1b5e28f 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeinst.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeinst.go2 @@ -8,7 +8,8 @@ type myInt int // Parameterized type declarations -type T1[P any] P +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +type T1[P any] P // ERROR cannot use a type parameter as RHS in type declaration type T2[P any] struct { f P @@ -19,7 +20,7 @@ type List[P any] []P // Alias type declarations cannot have type parameters. // Issue #46477 proposses to change that. -type A1[P any] = /* ERROR cannot be alias */ P +type A1[P any] = /* ERROR cannot be alias */ struct{} // Pending clarification of #46477 we disallow aliases // of generic types. diff --git a/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 b/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 index 783ff346c9..5529bd093d 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 @@ -87,25 +87,27 @@ type NumericAbs[T any] interface { func AbsDifference[T NumericAbs[T]](x T) { panic(0) } -type OrderedAbs[T any] T - -func (a OrderedAbs[T]) Abs() OrderedAbs[T] - -func OrderedAbsDifference[T any](x T) { - AbsDifference(OrderedAbs[T](x)) -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// type OrderedAbs[T any] T +// +// func (a OrderedAbs[T]) Abs() OrderedAbs[T] +// +// func OrderedAbsDifference[T any](x T) { +// AbsDifference(OrderedAbs[T](x)) +// } // same code, reduced to essence func g[P interface{ m() P }](x P) { panic(0) } -type T4[P any] P - -func (_ T4[P]) m() T4[P] - -func _[Q any](x Q) { - g(T4[Q](x)) -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// type T4[P any] P +// +// func (_ T4[P]) m() T4[P] +// +// func _[Q any](x Q) { +// g(T4[Q](x)) +// } // Another test case that caused problems in the past diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 index 1200a6e874..11adb21d95 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 @@ -353,15 +353,16 @@ func _() { // the previous example was extracted from -func f12[T interface{m() T}]() {} - -type A[T any] T - -func (a A[T]) m() A[T] - -func _[T any]() { - f12[A[T]]() -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// func f12[T interface{m() T}]() {} +// +// type A[T any] T +// +// func (a A[T]) m() A[T] +// +// func _[T any]() { +// f12[A[T]]() +// } // method expressions diff --git a/src/cmd/compile/internal/types2/testdata/examples/methods.go2 b/src/cmd/compile/internal/types2/testdata/examples/methods.go2 index 4e87041e54..1d76d553dc 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/methods.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/methods.go2 @@ -6,8 +6,6 @@ package p -import "unsafe" - // Parameterized types may have methods. type T1[A any] struct{ a A } @@ -97,17 +95,18 @@ type T0 struct{} func (T0) _() {} func (T1[A]) _() {} -// A generic receiver type may constrain its type parameter such -// that it must be a pointer type. Such receiver types are not -// permitted. -type T3a[P interface{ ~int | ~string | ~float64 }] P - -func (T3a[_]) m() {} // this is ok - -type T3b[P interface{ ~unsafe.Pointer }] P - -func (T3b /* ERROR invalid receiver */ [_]) m() {} - -type T3c[P interface{ *int | *string }] P - -func (T3c /* ERROR invalid receiver */ [_]) m() {} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// // A generic receiver type may constrain its type parameter such +// // that it must be a pointer type. Such receiver types are not +// // permitted. +// type T3a[P interface{ ~int | ~string | ~float64 }] P +// +// func (T3a[_]) m() {} // this is ok +// +// type T3b[P interface{ ~unsafe.Pointer }] P +// +// func (T3b /* ERROR invalid receiver */ [_]) m() {} +// +// type T3c[P interface{ *int | *string }] P +// +// func (T3c /* ERROR invalid receiver */ [_]) m() {} diff --git a/src/cmd/compile/internal/types2/testdata/examples/types.go2 b/src/cmd/compile/internal/types2/testdata/examples/types.go2 index f177c78d06..72b74cee01 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/types.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/types.go2 @@ -185,12 +185,13 @@ type _ struct { // _ = y < 0 // } -// It is not permitted to declare a local type whose underlying -// type is a type parameter not declared by that type declaration. -func _[T any]() { - type _ T // ERROR cannot use function type parameter T as RHS in type declaration - type _ [_ any] T // ERROR cannot use function type parameter T as RHS in type declaration -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// // It is not permitted to declare a local type whose underlying +// // type is a type parameter not declared by that type declaration. +// func _[T any]() { +// type _ T // ERROR cannot use function type parameter T as RHS in type declaration +// type _ [_ any] T // ERROR cannot use function type parameter T as RHS in type declaration +// } // As a special case, an explicit type argument may be omitted // from a type parameter bound if the type bound expects exactly diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 index 200484b6d9..9a98f7f955 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39634.go2 @@ -74,9 +74,10 @@ func F20[t Z20]() { F20(t /* ERROR invalid composite literal type */ {}) } type Z21 /* ERROR illegal cycle */ interface{ Z21 } func F21[T Z21]() { ( /* ERROR not used */ F21[Z21]) } -// crash 24 -type T24[P any] P -func (r T24[P]) m() { T24 /* ERROR without instantiation */ .m() } +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// // crash 24 +// type T24[P any] P +// func (r T24[P]) m() { T24 /* ERROR without instantiation */ .m() } // crash 25 type T25[A any] int diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39768.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39768.go2 index fb522733e0..696d9d9bee 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39768.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39768.go2 @@ -4,14 +4,15 @@ package p -type T[P any] P -type A = T // ERROR cannot use generic type -var x A[int] -var _ A - -type B = T[int] -var y B = x -var _ B /* ERROR not a generic type */ [int] +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// type T[P any] P +// type A = T // ERROR cannot use generic type +// var x A[int] +// var _ A +// +// type B = T[int] +// var y B = x +// var _ B /* ERROR not a generic type */ [int] // test case from issue diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39938.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39938.go2 index 31bec5fb01..114646786d 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39938.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39938.go2 @@ -8,7 +8,7 @@ package p -type E0[P any] P +type E0[P any] []P type E1[P any] *P type E2[P any] struct{ _ P } type E3[P any] struct{ _ *P } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45639.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45639.go2 index 441fb4cb34..80148fe481 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45639.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45639.go2 @@ -4,9 +4,10 @@ package P -// It is not permitted to declare a local type whose underlying -// type is a type parameters not declared by that type declaration. -func _[T any]() { - type _ T // ERROR cannot use function type parameter T as RHS in type declaration - type _ [_ any] T // ERROR cannot use function type parameter T as RHS in type declaration -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// // It is not permitted to declare a local type whose underlying +// // type is a type parameters not declared by that type declaration. +// func _[T any]() { +// type _ T // ERROR cannot use function type parameter T as RHS in type declaration +// type _ [_ any] T // ERROR cannot use function type parameter T as RHS in type declaration +// } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47747.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47747.go2 index af52056bef..6a2e787bf9 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47747.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47747.go2 @@ -4,15 +4,16 @@ package p -type T1[P any] P - -func (T1[_]) m() {} - -func _[P any](x *T1[P]) { - // x.m exists because x is of type *T1 where T1 is a defined type - // (even though under(T1) is a type parameter) - x.m() -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// type T1[P any] P +// +// func (T1[_]) m() {} +// +// func _[P any](x *T1[P]) { +// // x.m exists because x is of type *T1 where T1 is a defined type +// // (even though under(T1) is a type parameter) +// x.m() +// } func _[P interface{ m() }](x P) { @@ -40,29 +41,31 @@ type Barer[t any] interface { Bar(t) } -type Foo1[t any] t -type Bar[t any] t - -func (l Foo1[t]) Foo(v Barer[t]) { v.Bar(t(l)) } -func (b *Bar[t]) Bar(l t) { *b = Bar[t](l) } - -func _[t any](f Fooer1[t]) t { - var b Bar[t] - f.Foo(&b) - return t(b) -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// type Foo1[t any] t +// type Bar[t any] t +// +// func (l Foo1[t]) Foo(v Barer[t]) { v.Bar(t(l)) } +// func (b *Bar[t]) Bar(l t) { *b = Bar[t](l) } +// +// func _[t any](f Fooer1[t]) t { +// var b Bar[t] +// f.Foo(&b) +// return t(b) +// } // Test case 2 from issue -type Fooer2[t any] interface { - Foo() -} - -type Foo2[t any] t - -func (f *Foo2[t]) Foo() {} - -func _[t any](v t) { - var f = Foo2[t](v) - _ = Fooer2[t](&f) -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// type Fooer2[t any] interface { +// Foo() +// } +// +// type Foo2[t any] t +// +// func (f *Foo2[t]) Foo() {} +// +// func _[t any](v t) { +// var f = Foo2[t](v) +// _ = Fooer2[t](&f) +// } diff --git a/test/typeparam/absdiff.go b/test/typeparam/absdiff.go index cad6e84c4e..f1822831b2 100644 --- a/test/typeparam/absdiff.go +++ b/test/typeparam/absdiff.go @@ -6,11 +6,6 @@ package main -import ( - "fmt" - "math" -) - type Numeric interface { ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | @@ -43,55 +38,57 @@ type Complex interface { ~complex64 | ~complex128 } -// orderedAbs is a helper type that defines an Abs method for -// ordered numeric types. -type orderedAbs[T orderedNumeric] T - -func (a orderedAbs[T]) Abs() orderedAbs[T] { - if a < 0 { - return -a - } - return a -} - -// complexAbs is a helper type that defines an Abs method for -// complex types. -type complexAbs[T Complex] T - -func (a complexAbs[T]) Abs() complexAbs[T] { - r := float64(real(a)) - i := float64(imag(a)) - d := math.Sqrt(r*r + i*i) - return complexAbs[T](complex(d, 0)) -} - -// OrderedAbsDifference returns the absolute value of the difference -// between a and b, where a and b are of an ordered type. -func orderedAbsDifference[T orderedNumeric](a, b T) T { - return T(absDifference(orderedAbs[T](a), orderedAbs[T](b))) -} - -// ComplexAbsDifference returns the absolute value of the difference -// between a and b, where a and b are of a complex type. -func complexAbsDifference[T Complex](a, b T) T { - return T(absDifference(complexAbs[T](a), complexAbs[T](b))) -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// // orderedAbs is a helper type that defines an Abs method for +// // ordered numeric types. +// type orderedAbs[T orderedNumeric] T +// +// func (a orderedAbs[T]) Abs() orderedAbs[T] { +// if a < 0 { +// return -a +// } +// return a +// } +// +// // complexAbs is a helper type that defines an Abs method for +// // complex types. +// type complexAbs[T Complex] T +// +// func (a complexAbs[T]) Abs() complexAbs[T] { +// r := float64(real(a)) +// i := float64(imag(a)) +// d := math.Sqrt(r*r + i*i) +// return complexAbs[T](complex(d, 0)) +// } +// +// // OrderedAbsDifference returns the absolute value of the difference +// // between a and b, where a and b are of an ordered type. +// func orderedAbsDifference[T orderedNumeric](a, b T) T { +// return T(absDifference(orderedAbs[T](a), orderedAbs[T](b))) +// } +// +// // ComplexAbsDifference returns the absolute value of the difference +// // between a and b, where a and b are of a complex type. +// func complexAbsDifference[T Complex](a, b T) T { +// return T(absDifference(complexAbs[T](a), complexAbs[T](b))) +// } func main() { - if got, want := orderedAbsDifference(1.0, -2.0), 3.0; got != want { - panic(fmt.Sprintf("got = %v, want = %v", got, want)) - } - if got, want := orderedAbsDifference(-1.0, 2.0), 3.0; got != want { - panic(fmt.Sprintf("got = %v, want = %v", got, want)) - } - if got, want := orderedAbsDifference(-20, 15), 35; got != want { - panic(fmt.Sprintf("got = %v, want = %v", got, want)) - } - - if got, want := complexAbsDifference(5.0+2.0i, 2.0-2.0i), 5+0i; got != want { - panic(fmt.Sprintf("got = %v, want = %v", got, want)) - } - if got, want := complexAbsDifference(2.0-2.0i, 5.0+2.0i), 5+0i; got != want { - panic(fmt.Sprintf("got = %v, want = %v", got, want)) - } + // // For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). + // if got, want := orderedAbsDifference(1.0, -2.0), 3.0; got != want { + // panic(fmt.Sprintf("got = %v, want = %v", got, want)) + // } + // if got, want := orderedAbsDifference(-1.0, 2.0), 3.0; got != want { + // panic(fmt.Sprintf("got = %v, want = %v", got, want)) + // } + // if got, want := orderedAbsDifference(-20, 15), 35; got != want { + // panic(fmt.Sprintf("got = %v, want = %v", got, want)) + // } + // + // if got, want := complexAbsDifference(5.0+2.0i, 2.0-2.0i), 5+0i; got != want { + // panic(fmt.Sprintf("got = %v, want = %v", got, want)) + // } + // if got, want := complexAbsDifference(2.0-2.0i, 5.0+2.0i), 5+0i; got != want { + // panic(fmt.Sprintf("got = %v, want = %v", got, want)) + // } } diff --git a/test/typeparam/absdiffimp.dir/a.go b/test/typeparam/absdiffimp.dir/a.go index 7b5bfbe2ac..60822fdb8b 100644 --- a/test/typeparam/absdiffimp.dir/a.go +++ b/test/typeparam/absdiffimp.dir/a.go @@ -4,10 +4,6 @@ package a -import ( - "math" -) - type Numeric interface { ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | @@ -40,36 +36,37 @@ type Complex interface { ~complex64 | ~complex128 } -// orderedAbs is a helper type that defines an Abs method for -// ordered numeric types. -type orderedAbs[T orderedNumeric] T - -func (a orderedAbs[T]) Abs() orderedAbs[T] { - if a < 0 { - return -a - } - return a -} - -// complexAbs is a helper type that defines an Abs method for -// complex types. -type complexAbs[T Complex] T - -func (a complexAbs[T]) Abs() complexAbs[T] { - r := float64(real(a)) - i := float64(imag(a)) - d := math.Sqrt(r*r + i*i) - return complexAbs[T](complex(d, 0)) -} - -// OrderedAbsDifference returns the absolute value of the difference -// between a and b, where a and b are of an ordered type. -func OrderedAbsDifference[T orderedNumeric](a, b T) T { - return T(absDifference(orderedAbs[T](a), orderedAbs[T](b))) -} - -// ComplexAbsDifference returns the absolute value of the difference -// between a and b, where a and b are of a complex type. -func ComplexAbsDifference[T Complex](a, b T) T { - return T(absDifference(complexAbs[T](a), complexAbs[T](b))) -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// // orderedAbs is a helper type that defines an Abs method for +// // ordered numeric types. +// type orderedAbs[T orderedNumeric] T +// +// func (a orderedAbs[T]) Abs() orderedAbs[T] { +// if a < 0 { +// return -a +// } +// return a +// } +// +// // complexAbs is a helper type that defines an Abs method for +// // complex types. +// type complexAbs[T Complex] T +// +// func (a complexAbs[T]) Abs() complexAbs[T] { +// r := float64(real(a)) +// i := float64(imag(a)) +// d := math.Sqrt(r*r + i*i) +// return complexAbs[T](complex(d, 0)) +// } +// +// // OrderedAbsDifference returns the absolute value of the difference +// // between a and b, where a and b are of an ordered type. +// func OrderedAbsDifference[T orderedNumeric](a, b T) T { +// return T(absDifference(orderedAbs[T](a), orderedAbs[T](b))) +// } +// +// // ComplexAbsDifference returns the absolute value of the difference +// // between a and b, where a and b are of a complex type. +// func ComplexAbsDifference[T Complex](a, b T) T { +// return T(absDifference(complexAbs[T](a), complexAbs[T](b))) +// } diff --git a/test/typeparam/absdiffimp.dir/main.go b/test/typeparam/absdiffimp.dir/main.go index 8eefdbdf38..c648013327 100644 --- a/test/typeparam/absdiffimp.dir/main.go +++ b/test/typeparam/absdiffimp.dir/main.go @@ -4,26 +4,22 @@ package main -import ( - "a" - "fmt" -) - func main() { - if got, want := a.OrderedAbsDifference(1.0, -2.0), 3.0; got != want { - panic(fmt.Sprintf("got = %v, want = %v", got, want)) - } - if got, want := a.OrderedAbsDifference(-1.0, 2.0), 3.0; got != want { - panic(fmt.Sprintf("got = %v, want = %v", got, want)) - } - if got, want := a.OrderedAbsDifference(-20, 15), 35; got != want { - panic(fmt.Sprintf("got = %v, want = %v", got, want)) - } - - if got, want := a.ComplexAbsDifference(5.0+2.0i, 2.0-2.0i), 5+0i; got != want { - panic(fmt.Sprintf("got = %v, want = %v", got, want)) - } - if got, want := a.ComplexAbsDifference(2.0-2.0i, 5.0+2.0i), 5+0i; got != want { - panic(fmt.Sprintf("got = %v, want = %v", got, want)) - } + // For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). + // if got, want := a.OrderedAbsDifference(1.0, -2.0), 3.0; got != want { + // panic(fmt.Sprintf("got = %v, want = %v", got, want)) + // } + // if got, want := a.OrderedAbsDifference(-1.0, 2.0), 3.0; got != want { + // panic(fmt.Sprintf("got = %v, want = %v", got, want)) + // } + // if got, want := a.OrderedAbsDifference(-20, 15), 35; got != want { + // panic(fmt.Sprintf("got = %v, want = %v", got, want)) + // } + // + // if got, want := a.ComplexAbsDifference(5.0+2.0i, 2.0-2.0i), 5+0i; got != want { + // panic(fmt.Sprintf("got = %v, want = %v", got, want)) + // } + // if got, want := a.ComplexAbsDifference(2.0-2.0i, 5.0+2.0i), 5+0i; got != want { + // panic(fmt.Sprintf("got = %v, want = %v", got, want)) + // } } diff --git a/test/typeparam/boundmethod.go b/test/typeparam/boundmethod.go index 22f416422d..a14eb544ce 100644 --- a/test/typeparam/boundmethod.go +++ b/test/typeparam/boundmethod.go @@ -59,12 +59,13 @@ type Ints interface { ~int32 | ~int } -type StringInt[T Ints] T - -//go:noinline -func (m StringInt[T]) String() string { - return strconv.Itoa(int(m)) -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// type StringInt[T Ints] T +// +// //go:noinline +// func (m StringInt[T]) String() string { +// return strconv.Itoa(int(m)) +// } type StringStruct[T Ints] struct { f T @@ -84,22 +85,23 @@ func main() { panic(fmt.Sprintf("got %s, want %s", got, want)) } - x2 := []StringInt[myint]{StringInt[myint](5), StringInt[myint](7), StringInt[myint](6)} - - // stringify on an instantiated type, whose bound method is associated with - // the generic type StringInt[T], which maps directly to T. - got2 := stringify(x2) - want2 := []string{ "5", "7", "6" } - if !reflect.DeepEqual(got2, want2) { - panic(fmt.Sprintf("got %s, want %s", got2, want2)) - } + // For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). + // x2 := []StringInt[myint]{StringInt[myint](5), StringInt[myint](7), StringInt[myint](6)} + // + // // stringify on an instantiated type, whose bound method is associated with + // // the generic type StringInt[T], which maps directly to T. + // got2 := stringify(x2) + // want2 := []string{"5", "7", "6"} + // if !reflect.DeepEqual(got2, want2) { + // panic(fmt.Sprintf("got %s, want %s", got2, want2)) + // } // stringify on an instantiated type, whose bound method is associated with // the generic type StringStruct[T], which maps to a struct containing T. x3 := []StringStruct[myint]{StringStruct[myint]{f: 11}, StringStruct[myint]{f: 10}, StringStruct[myint]{f: 9}} got3 := stringify(x3) - want3 := []string{ "11", "10", "9" } + want3 := []string{"11", "10", "9"} if !reflect.DeepEqual(got3, want3) { panic(fmt.Sprintf("got %s, want %s", got3, want3)) } diff --git a/test/typeparam/issue47708.go b/test/typeparam/issue47708.go index 261d6efb61..35d57c8a64 100644 --- a/test/typeparam/issue47708.go +++ b/test/typeparam/issue47708.go @@ -6,35 +6,32 @@ package main -import ( - "fmt" -) - type FooType[T any] interface { - Foo(BarType[T])string + Foo(BarType[T]) string } type BarType[T any] interface { - Bar(FooType[T])string -} - -type Baz[T any] T -func (l Baz[T]) Foo(v BarType[T]) string { - return v.Bar(l) -} -type Bob[T any] T -func (l Bob[T]) Bar(v FooType[T]) string { - if v,ok := v.(Baz[T]);ok{ - return fmt.Sprintf("%v%v",v,l) - } - return "" + Bar(FooType[T]) string } +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// type Baz[T any] T +// func (l Baz[T]) Foo(v BarType[T]) string { +// return v.Bar(l) +// } +// type Bob[T any] T +// func (l Bob[T]) Bar(v FooType[T]) string { +// if v,ok := v.(Baz[T]);ok{ +// return fmt.Sprintf("%v%v",v,l) +// } +// return "" +// } func main() { - var baz Baz[int] = 123 - var bob Bob[int] = 456 - - if got, want := baz.Foo(bob), "123456"; got != want { - panic(fmt.Sprintf("got %s want %s", got, want)) - } + // For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). + // var baz Baz[int] = 123 + // var bob Bob[int] = 456 + // + // if got, want := baz.Foo(bob), "123456"; got != want { + // panic(fmt.Sprintf("got %s want %s", got, want)) + // } } diff --git a/test/typeparam/issue47740.go b/test/typeparam/issue47740.go index a8c6839de3..ea1168f4e6 100644 --- a/test/typeparam/issue47740.go +++ b/test/typeparam/issue47740.go @@ -12,10 +12,11 @@ type Exp[Ty any] interface { Eval() Ty } -type Lit[Ty any] Ty - -func (lit Lit[Ty]) Eval() Ty { return Ty(lit) } -func (lit Lit[Ty]) String() string { return fmt.Sprintf("(lit %v)", Ty(lit)) } +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// type Lit[Ty any] Ty +// +// func (lit Lit[Ty]) Eval() Ty { return Ty(lit) } +// func (lit Lit[Ty]) String() string { return fmt.Sprintf("(lit %v)", Ty(lit)) } type Eq[Ty any] struct { a Exp[Ty] @@ -26,12 +27,14 @@ func (e Eq[Ty]) String() string { return fmt.Sprintf("(eq %v %v)", e.a, e.b) } -var ( - e0 = Eq[int]{Lit[int](128), Lit[int](64)} - e1 = Eq[bool]{Lit[bool](true), Lit[bool](true)} -) +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// var ( +// e0 = Eq[int]{Lit[int](128), Lit[int](64)} +// e1 = Eq[bool]{Lit[bool](true), Lit[bool](true)} +// ) func main() { - fmt.Printf("%v\n", e0) - fmt.Printf("%v\n", e1) + // For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). + // fmt.Printf("%v\n", e0) + // fmt.Printf("%v\n", e1) } diff --git a/test/typeparam/issue47740.out b/test/typeparam/issue47740.out index f23c310f66..e69de29bb2 100644 --- a/test/typeparam/issue47740.out +++ b/test/typeparam/issue47740.out @@ -1,2 +0,0 @@ -(eq (lit 128) (lit 64)) -(eq (lit true) (lit true)) -- GitLab From 12dc48fd54d4bfc0c25e2a96aa7fecfacb9087ca Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 27 Oct 2021 17:28:36 -0700 Subject: [PATCH 1785/2500] cmd/compile/internal/types2: export Structure function For #48538. Change-Id: I258b0c8af5801692ad238e47397dde0b4e3c44c1 Reviewed-on: https://go-review.googlesource.com/c/go/+/359275 Trust: Robert Griesemer Trust: Dan Scales Reviewed-by: Dan Scales --- src/cmd/compile/internal/types2/builtins.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index e8de0077d4..c5c6bdf0a5 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -767,6 +767,16 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( return true } +// Structure is exported for the compiler. + +// If typ is a type parameter, Structure returns the single underlying +// type of all types in the corresponding type constraint if it exists, +// or nil otherwise. If typ is not a type parameter, Structure returns +// the underlying type. +func Structure(typ Type) Type { + return structure(typ) +} + // If typ is a type parameter, structure returns the single underlying // type of all types in the corresponding type constraint if it exists, // or nil otherwise. If typ is not a type parameter, structure returns -- GitLab From b2fe2ebab6e66a453a0137e37d2c639a613a852b Mon Sep 17 00:00:00 2001 From: Leonard Wang Date: Wed, 7 Jul 2021 22:33:09 +0800 Subject: [PATCH 1786/2500] cmd/compile: resolve the TODO of processPragmas Change-Id: Id723ecc2480aea2d8acb4d3e05db4a6c8eef9cc8 Reviewed-on: https://go-review.googlesource.com/c/go/+/333109 Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky Trust: Matthew Dempsky Trust: Cherry Mui --- src/cmd/compile/internal/noder/noder.go | 3 +-- src/cmd/cover/testdata/test.go | 1 + test/linkname2.go | 7 ++----- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index fc1541f74e..b36db67a50 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -323,8 +323,7 @@ func (p *noder) processPragmas() { } n := ir.AsNode(typecheck.Lookup(l.local).Def) if n == nil || n.Op() != ir.ONAME { - // TODO(mdempsky): Change to p.errorAt before Go 1.17 release. - // base.WarnfAt(p.makeXPos(l.pos), "//go:linkname must refer to declared function or variable (will be an error in Go 1.17)") + p.errorAt(l.pos, "//go:linkname must refer to declared function or variable") continue } if n.Sym().Linkname != "" { diff --git a/src/cmd/cover/testdata/test.go b/src/cmd/cover/testdata/test.go index b794962205..703fba57a4 100644 --- a/src/cmd/cover/testdata/test.go +++ b/src/cmd/cover/testdata/test.go @@ -13,6 +13,7 @@ package main import _ "unsafe" // for go:linkname //go:linkname some_name some_name +var some_name int const anything = 1e9 // Just some unlikely value that means "we got here, don't care how often" diff --git a/test/linkname2.go b/test/linkname2.go index 43e66a5849..cb7f9be345 100644 --- a/test/linkname2.go +++ b/test/linkname2.go @@ -16,13 +16,10 @@ var x, y int //go:linkname x ok // ERROR "//go:linkname requires linkname argument or -p compiler flag" -// BAD: want error "//go:linkname must refer to declared function or variable" -// BAD: want error "//go:linkname must refer to declared function or variable" +// ERROR "//go:linkname must refer to declared function or variable" +// ERROR "//go:linkname must refer to declared function or variable" // ERROR "duplicate //go:linkname for x" -// The two BAD lines are just waiting for #42938 before we can -// re-enable the errors. - //line linkname2.go:18 //go:linkname y //go:linkname nonexist nonexist -- GitLab From 056dfe6ff34fd479ec5c86d9b26a03c639b3f3f7 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 28 Oct 2021 00:33:19 +0700 Subject: [PATCH 1787/2500] reflect: undeprecate Value.{Pointer,UnsafeAddr} Fixes #49187 Change-Id: I4d8c87af8a709f1b909dd4fae3734d422eb36900 Reviewed-on: https://go-review.googlesource.com/c/go/+/359194 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/reflect/value.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/reflect/value.go b/src/reflect/value.go index 5d9964eb9d..618d38893e 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -1934,7 +1934,7 @@ func (v Value) OverflowUint(x uint64) bool { // element of the slice. If the slice is nil the returned value // is 0. If the slice is empty but non-nil the return value is non-zero. // -// Deprecated: use uintptr(Value.UnsafePointer()) to get the equivalent result. +// It's preferred to use uintptr(Value.UnsafePointer()) to get the equivalent result. func (v Value) Pointer() uintptr { k := v.kind() switch k { @@ -2479,7 +2479,7 @@ func (v Value) Uint() uint64 { // It is for advanced clients that also import the "unsafe" package. // It panics if v is not addressable. // -// Deprecated: use uintptr(Value.Addr().UnsafePointer()) to get the equivalent result. +// It's preferred to use uintptr(Value.Addr().UnsafePointer()) to get the equivalent result. func (v Value) UnsafeAddr() uintptr { if v.typ == nil { panic(&ValueError{"reflect.Value.UnsafeAddr", Invalid}) -- GitLab From 5a3a9d87ed97f197aabcb868f6c0031c888d6122 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 27 Oct 2021 18:53:02 -0400 Subject: [PATCH 1788/2500] cmd/dist: implement //go:build parsing The bootstrap directories are built with the Go 1.4 go command, and they will retain the // +build lines until we bump the bootstrap toolchain to Go 1.17 or later. cmd/dist builds cmd/go and all its dependencies, using the assembler, compiler, and linker that were built using Go 1.4. We don't want to have to keep // +build lines in cmd/go and all its dependencies, so this CL changes cmd/dist to understand the //go:build lines. cmd/dist is a standalone Go program that must itself build with very old Go releases, so we cannot assume go/build/constraint is available. Instead, implement a trivial parser/evaluator. For #41184. Change-Id: I84e259dec3bd3daec3f82024eb3500120f53096d Reviewed-on: https://go-review.googlesource.com/c/go/+/359314 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/cmd/dist/build.go | 47 ++++---------- src/cmd/dist/buildtag.go | 133 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+), 34 deletions(-) create mode 100644 src/cmd/dist/buildtag.go diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go index 39f016e315..d37c3f83ef 100644 --- a/src/cmd/dist/build.go +++ b/src/cmd/dist/build.go @@ -812,6 +812,9 @@ func runInstall(pkg string, ch chan struct{}) { importMap := make(map[string]string) for _, p := range gofiles { for _, imp := range readimports(p) { + if imp == "C" { + fatalf("%s imports C", p) + } importMap[imp] = resolveVendor(imp, dir) } } @@ -822,6 +825,9 @@ func runInstall(pkg string, ch chan struct{}) { sort.Strings(sortedImports) for _, dep := range importMap { + if dep == "C" { + fatalf("%s imports C", pkg) + } startInstall(dep) } for _, dep := range importMap { @@ -970,28 +976,8 @@ func packagefile(pkg string) string { return pathf("%s/pkg/%s_%s/%s.a", goroot, goos, goarch, pkg) } -// matchfield reports whether the field (x,y,z) matches this build. -// all the elements in the field must be satisfied. -func matchfield(f string) bool { - for _, tag := range strings.Split(f, ",") { - if !matchtag(tag) { - return false - } - } - return true -} - -// matchtag reports whether the tag (x or !x) matches this build. +// matchtag reports whether the tag matches this build. func matchtag(tag string) bool { - if tag == "" { - return false - } - if tag[0] == '!' { - if len(tag) == 1 || tag[1] == '!' { - return false - } - return !matchtag(tag[1:]) - } return tag == "gc" || tag == goos || tag == goarch || tag == "cmd_go_bootstrap" || tag == "go1.1" || (goos == "android" && tag == "linux") || (goos == "illumos" && tag == "solaris") || @@ -1032,7 +1018,7 @@ func shouldbuild(file, pkg string) bool { return false } - // Check file contents for // +build lines. + // Check file contents for //go:build lines. for _, p := range strings.Split(readfile(file), "\n") { p = strings.TrimSpace(p) if p == "" { @@ -1052,20 +1038,13 @@ func shouldbuild(file, pkg string) bool { if !strings.HasPrefix(p, "//") { break } - if !strings.Contains(p, "+build") { - continue - } - fields := strings.Fields(p[2:]) - if len(fields) < 1 || fields[0] != "+build" { - continue - } - for _, p := range fields[1:] { - if matchfield(p) { - goto fieldmatch + if strings.HasPrefix(p, "//go:build ") { + matched, err := matchexpr(p[len("//go:build "):]) + if err != nil { + errprintf("%s: %v", file, err) } + return matched } - return false - fieldmatch: } return true diff --git a/src/cmd/dist/buildtag.go b/src/cmd/dist/buildtag.go new file mode 100644 index 0000000000..24776a0aaf --- /dev/null +++ b/src/cmd/dist/buildtag.go @@ -0,0 +1,133 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + "strings" +) + +// exprParser is a //go:build expression parser and evaluator. +// The parser is a trivial precedence-based parser which is still +// almost overkill for these very simple expressions. +type exprParser struct { + x string + t exprToken // upcoming token +} + +// val is the value type result of parsing. +// We don't keep a parse tree, just the value of the expression. +type val bool + +// exprToken describes a single token in the input. +// Prefix operators define a prefix func that parses the +// upcoming value. Binary operators define an infix func +// that combines two values according to the operator. +// In that case, the parsing loop parses the two values. +type exprToken struct { + tok string + prec int + prefix func(*exprParser) val + infix func(val, val) val +} + +var exprTokens []exprToken + +func init() { // init to break init cycle + exprTokens = []exprToken{ + {tok: "&&", prec: 1, infix: func(x, y val) val { return x && y }}, + {tok: "||", prec: 2, infix: func(x, y val) val { return x || y }}, + {tok: "!", prec: 3, prefix: (*exprParser).not}, + {tok: "(", prec: 3, prefix: (*exprParser).paren}, + {tok: ")"}, + } +} + +// matchexpr parses and evaluates the //go:build expression x. +func matchexpr(x string) (matched bool, err error) { + defer func() { + if e := recover(); e != nil { + matched = false + err = fmt.Errorf("parsing //go:build line: %v", e) + } + }() + + p := &exprParser{x: x} + p.next() + v := p.parse(0) + if p.t.tok != "end of expression" { + panic("unexpected " + p.t.tok) + } + return bool(v), nil +} + +// parse parses an expression, including binary operators at precedence >= prec. +func (p *exprParser) parse(prec int) val { + if p.t.prefix == nil { + panic("unexpected " + p.t.tok) + } + v := p.t.prefix(p) + for p.t.prec >= prec && p.t.infix != nil { + t := p.t + p.next() + v = t.infix(v, p.parse(t.prec+1)) + } + return v +} + +// not is the prefix parser for a ! token. +func (p *exprParser) not() val { + p.next() + return !p.parse(100) +} + +// paren is the prefix parser for a ( token. +func (p *exprParser) paren() val { + p.next() + v := p.parse(0) + if p.t.tok != ")" { + panic("missing )") + } + p.next() + return v +} + +// next advances the parser to the next token, +// leaving the token in p.t. +func (p *exprParser) next() { + p.x = strings.TrimSpace(p.x) + if p.x == "" { + p.t = exprToken{tok: "end of expression"} + return + } + for _, t := range exprTokens { + if strings.HasPrefix(p.x, t.tok) { + p.x = p.x[len(t.tok):] + p.t = t + return + } + } + + i := 0 + for i < len(p.x) && validtag(p.x[i]) { + i++ + } + if i == 0 { + panic(fmt.Sprintf("syntax error near %#q", rune(p.x[i]))) + } + tag := p.x[:i] + p.x = p.x[i:] + p.t = exprToken{ + tok: "tag", + prefix: func(p *exprParser) val { + p.next() + return val(matchtag(tag)) + }, + } +} + +func validtag(c byte) bool { + return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '.' || c == '_' +} -- GitLab From b8f928b05264cbd75a0d0dbd02d979847ac237f9 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 27 Oct 2021 20:21:07 -0400 Subject: [PATCH 1789/2500] go/build: update for //go:build lines Look for //go:build ignore, not // +build ignore, in deps_test.go. For #41184. Change-Id: Iba8617230aa620223e2bc170f18d0c54557318c4 Reviewed-on: https://go-review.googlesource.com/c/go/+/359315 Trust: Russ Cox Trust: Josh Bleecher Snyder Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Josh Bleecher Snyder --- src/go/build/deps_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 64f084152a..ab85c99602 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -621,7 +621,7 @@ func TestDependencies(t *testing.T) { } } -var buildIgnore = []byte("\n// +build ignore") +var buildIgnore = []byte("\n//go:build ignore") func findImports(pkg string) ([]string, error) { vpkg := pkg -- GitLab From 2ff1074f5ac48e67ee079dafc9f0e314bc454510 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 27 Oct 2021 10:13:50 -0700 Subject: [PATCH 1790/2500] reflect: undeprecate Ptr, PtrTo Fixes #48665 Change-Id: Id838f7508f6e93c4546a2aeefc2db194e647db77 Reviewed-on: https://go-review.googlesource.com/c/go/+/359175 Trust: Brad Fitzpatrick Reviewed-by: Ian Lance Taylor --- src/reflect/type.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/reflect/type.go b/src/reflect/type.go index 0896949d7e..4701e06c49 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -269,8 +269,6 @@ const ( ) // Ptr is the old name for the Pointer kind. -// -// Deprecated: use the new spelling, Pointer. const Ptr = Pointer // tflag is used by an rtype to signal what extra type information is @@ -1425,9 +1423,9 @@ func TypeOf(i interface{}) Type { var ptrMap sync.Map // map[*rtype]*ptrType // PtrTo returns the pointer type with element t. -// For example, if t represents type Foo, PointerTo(t) represents *Foo. +// For example, if t represents type Foo, PtrTo(t) represents *Foo. // -// Deprecated: use PointerTo. PtrTo is the old spelling. +// PtrTo is the old spelling of PointerTo. // The two functions behave identically. func PtrTo(t Type) Type { return PointerTo(t) } -- GitLab From a3bb28e5ffee83c30a2c65963ef032cc2ab73a3c Mon Sep 17 00:00:00 2001 From: nimelehin Date: Tue, 19 Oct 2021 18:59:34 +0300 Subject: [PATCH 1791/2500] cmd/compile: allow inlining of ORANGE Updates #14768 Change-Id: I33831f616eae5eeb099033e2b9cf90fa70d6ca86 Reviewed-on: https://go-review.googlesource.com/c/go/+/356869 Run-TryBot: Alberto Donizetti TryBot-Result: Go Bot Reviewed-by: Dan Scales Trust: Dan Scales Trust: Alberto Donizetti --- src/cmd/compile/internal/inline/inl.go | 3 +-- test/fixedbugs/issue49100b.go | 27 ++++++++++++++++++++++++++ test/fixedbugs/issue49100b.out | 6 ++++++ test/inline.go | 13 +++++++++++++ test/linkname.dir/linkname1.go | 2 +- 5 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 test/fixedbugs/issue49100b.go create mode 100644 test/fixedbugs/issue49100b.out diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index 483b3d5d46..da905bd627 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -358,8 +358,7 @@ func (v *hairyVisitor) doNode(n ir.Node) bool { return true } - case ir.ORANGE, - ir.OSELECT, + case ir.OSELECT, ir.OGO, ir.ODEFER, ir.ODCLTYPE, // can't print yet diff --git a/test/fixedbugs/issue49100b.go b/test/fixedbugs/issue49100b.go new file mode 100644 index 0000000000..992ff96d54 --- /dev/null +++ b/test/fixedbugs/issue49100b.go @@ -0,0 +1,27 @@ +// run + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func r(j int) { +loop: + for i, c := range "goclang" { + if i == 2 { + continue loop + } + println(string(c)) + } +} + +func main() { +loop: + for j := 0; j < 4; j++ { + r(j) + if j == 0 { + break loop + } + } +} diff --git a/test/fixedbugs/issue49100b.out b/test/fixedbugs/issue49100b.out new file mode 100644 index 0000000000..d5abb928ee --- /dev/null +++ b/test/fixedbugs/issue49100b.out @@ -0,0 +1,6 @@ +g +o +l +a +n +g diff --git a/test/inline.go b/test/inline.go index 599d5233e0..d0ebe84aa5 100644 --- a/test/inline.go +++ b/test/inline.go @@ -160,6 +160,19 @@ func switchType(x interface{}) int { // ERROR "can inline switchType" "x does no } } +func inlineRangeIntoMe(data []int) { // ERROR "can inline inlineRangeIntoMe" "data does not escape" + rangeFunc(data, 12) // ERROR "inlining call to rangeFunc" +} + +func rangeFunc(xs []int, b int) int { // ERROR "can inline rangeFunc" "xs does not escape" + for i, x := range xs { + if x == b { + return i + } + } + return -1 +} + type T struct{} func (T) meth(int, int) {} // ERROR "can inline T.meth" diff --git a/test/linkname.dir/linkname1.go b/test/linkname.dir/linkname1.go index c61a0d7d95..7d51b94802 100644 --- a/test/linkname.dir/linkname1.go +++ b/test/linkname.dir/linkname1.go @@ -1,6 +1,6 @@ package x -func indexByte(xs []byte, b byte) int { // ERROR "xs does not escape" +func indexByte(xs []byte, b byte) int { // ERROR "xs does not escape" "can inline indexByte" for i, x := range xs { if x == b { return i -- GitLab From 5c98bcb7d43e1dcf60d3799afc30f4d56e5e3cc4 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 28 Oct 2021 10:40:54 +0700 Subject: [PATCH 1792/2500] runtime: fix noopt builder CL 352057 added track argument stack slot liveness, and updated TestTracebackArgs for argument liveness. But when optimization is disabled, all arguments are considered lived. The abiSel does not consider this case and return wrong expected result. To fix this, checking if we are running in a noopt builder and return the correct expected result. Also, skipping TestTracebackArgs in quick mode, since when quick mode run the test without optimization disable. Updates #45728 Change-Id: I3737a1b1a5fa0c711fbb3218205f2f6e34f36260 Reviewed-on: https://go-review.googlesource.com/c/go/+/359196 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le Reviewed-by: Cherry Mui TryBot-Result: Go Bot --- src/runtime/traceback_test.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/runtime/traceback_test.go b/src/runtime/traceback_test.go index de9580ae53..0333b85c56 100644 --- a/src/runtime/traceback_test.go +++ b/src/runtime/traceback_test.go @@ -7,15 +7,23 @@ package runtime_test import ( "bytes" "internal/goexperiment" + "internal/testenv" "runtime" + "strings" "testing" ) var testTracebackArgsBuf [1000]byte func TestTracebackArgs(t *testing.T) { - abiSel := func(x, y string) string { // select expected output based on ABI - if goexperiment.RegabiArgs { + if *flagQuick { + t.Skip("-quick") + } + optimized := !strings.HasSuffix(testenv.Builder(), "-noopt") + abiSel := func(x, y string) string { + // select expected output based on ABI + // In noopt build we always spill arguments so the output is the same as stack ABI. + if optimized && goexperiment.RegabiArgs { return x } return y -- GitLab From a5a423e0e809e451b06771eb6a7b95cc9255f9fd Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 27 Oct 2021 09:19:50 -0400 Subject: [PATCH 1793/2500] go/parser: fix parsing of array or slice constraint types Now that we allow eliding 'interface' from constraint types, we need to be a bit more careful about not consuming a '[' when parsing the next expression after "type T [". We want to check if the next expression is an identifier not followed by ']', in which case we're in a generic type, but need to avoid parsing index or slice expressions. Such expressions aren't valid array lengths because these expressions are never constant, so when encountering a following '[' we can instead assume that this is a type parameter field with array or slice type constraint. Test cases are added for the related issues #49174 and #49175, along with a flag to enable tracing error tests. For #49174 For #49175 Change-Id: I0476ef20c4c134ac537118272f20caaf123ee70e Reviewed-on: https://go-review.googlesource.com/c/go/+/359134 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/parser/error_test.go | 6 ++ src/go/parser/parser.go | 81 +++++++++++++++++---------- src/go/parser/testdata/issue49174.go2 | 8 +++ src/go/parser/testdata/issue49175.go2 | 13 +++++ 4 files changed, 79 insertions(+), 29 deletions(-) create mode 100644 src/go/parser/testdata/issue49174.go2 create mode 100644 src/go/parser/testdata/issue49175.go2 diff --git a/src/go/parser/error_test.go b/src/go/parser/error_test.go index f35ba0b501..a45c897da3 100644 --- a/src/go/parser/error_test.go +++ b/src/go/parser/error_test.go @@ -23,6 +23,7 @@ package parser import ( + "flag" "go/internal/typeparams" "go/scanner" "go/token" @@ -33,6 +34,8 @@ import ( "testing" ) +var traceErrs = flag.Bool("trace_errs", false, "whether to enable tracing for error tests") + const testdata = "testdata" // getFile assumes that each filename occurs at most once @@ -192,6 +195,9 @@ func TestErrors(t *testing.T) { if !strings.HasSuffix(name, ".go2") { mode |= typeparams.DisallowParsing } + if *traceErrs { + mode |= Trace + } checkErrors(t, filepath.Join(testdata, name), nil, mode, true) } }) diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go index 4f7a498780..999663b98c 100644 --- a/src/go/parser/parser.go +++ b/src/go/parser/parser.go @@ -455,10 +455,10 @@ func (p *parser) parseExprList() (list []ast.Expr) { defer un(trace(p, "ExpressionList")) } - list = append(list, p.checkExpr(p.parseExpr())) + list = append(list, p.checkExpr(p.parseExpr(nil))) for p.tok == token.COMMA { p.next() - list = append(list, p.checkExpr(p.parseExpr())) + list = append(list, p.checkExpr(p.parseExpr(nil))) } return @@ -996,7 +996,7 @@ func (p *parser) parseMethodSpec() *ast.Field { lbrack := p.pos p.next() p.exprLev++ - x := p.parseExpr() + x := p.parseExpr(nil) p.exprLev-- if name0, _ := x.(*ast.Ident); name0 != nil && p.tok != token.COMMA && p.tok != token.RBRACK { // generic method m[T any] @@ -1538,7 +1538,7 @@ func (p *parser) parseValue() ast.Expr { return p.parseLiteralValue(nil) } - x := p.checkExpr(p.parseExpr()) + x := p.checkExpr(p.parseExpr(nil)) return x } @@ -1648,12 +1648,14 @@ func (p *parser) checkExprOrType(x ast.Expr) ast.Expr { return x } -func (p *parser) parsePrimaryExpr() (x ast.Expr) { +func (p *parser) parsePrimaryExpr(x ast.Expr) ast.Expr { if p.trace { defer un(trace(p, "PrimaryExpr")) } - x = p.parseOperand() + if x == nil { + x = p.parseOperand() + } for { switch p.tok { case token.PERIOD: @@ -1689,18 +1691,18 @@ func (p *parser) parsePrimaryExpr() (x ast.Expr) { switch t.(type) { case *ast.BadExpr, *ast.Ident, *ast.SelectorExpr: if p.exprLev < 0 { - return + return x } // x is possibly a composite literal type case *ast.IndexExpr, *ast.IndexListExpr: if p.exprLev < 0 { - return + return x } // x is possibly a composite literal type case *ast.ArrayType, *ast.StructType, *ast.MapType: // x is a composite literal type default: - return + return x } if t != x { p.error(t.Pos(), "cannot parenthesize type in composite literal") @@ -1708,7 +1710,7 @@ func (p *parser) parsePrimaryExpr() (x ast.Expr) { } x = p.parseLiteralValue(x) default: - return + return x } } } @@ -1779,7 +1781,7 @@ func (p *parser) parseUnaryExpr() ast.Expr { return &ast.StarExpr{Star: pos, X: p.checkExprOrType(x)} } - return p.parsePrimaryExpr() + return p.parsePrimaryExpr(nil) } func (p *parser) tokPrec() (token.Token, int) { @@ -1790,19 +1792,21 @@ func (p *parser) tokPrec() (token.Token, int) { return tok, tok.Precedence() } -func (p *parser) parseBinaryExpr(prec1 int) ast.Expr { +func (p *parser) parseBinaryExpr(x ast.Expr, prec1 int) ast.Expr { if p.trace { defer un(trace(p, "BinaryExpr")) } - x := p.parseUnaryExpr() + if x == nil { + x = p.parseUnaryExpr() + } for { op, oprec := p.tokPrec() if oprec < prec1 { return x } pos := p.expect(op) - y := p.parseBinaryExpr(oprec + 1) + y := p.parseBinaryExpr(nil, oprec+1) x = &ast.BinaryExpr{X: p.checkExpr(x), OpPos: pos, Op: op, Y: p.checkExpr(y)} } } @@ -1810,18 +1814,18 @@ func (p *parser) parseBinaryExpr(prec1 int) ast.Expr { // The result may be a type or even a raw type ([...]int). Callers must // check the result (using checkExpr or checkExprOrType), depending on // context. -func (p *parser) parseExpr() ast.Expr { +func (p *parser) parseExpr(lhs ast.Expr) ast.Expr { if p.trace { defer un(trace(p, "Expression")) } - return p.parseBinaryExpr(token.LowestPrec + 1) + return p.parseBinaryExpr(lhs, token.LowestPrec+1) } func (p *parser) parseRhs() ast.Expr { old := p.inRhs p.inRhs = true - x := p.checkExpr(p.parseExpr()) + x := p.checkExpr(p.parseExpr(nil)) p.inRhs = old return x } @@ -1829,7 +1833,7 @@ func (p *parser) parseRhs() ast.Expr { func (p *parser) parseRhsOrType() ast.Expr { old := p.inRhs p.inRhs = true - x := p.checkExprOrType(p.parseExpr()) + x := p.checkExprOrType(p.parseExpr(nil)) p.inRhs = old return x } @@ -2539,6 +2543,10 @@ func (p *parser) parseValueSpec(doc *ast.CommentGroup, _ token.Pos, keyword toke } func (p *parser) parseGenericType(spec *ast.TypeSpec, openPos token.Pos, name0 *ast.Ident) { + if p.trace { + defer un(trace(p, "parseGenericType")) + } + list := p.parseParameterList(name0, token.RBRACK) closePos := p.expect(token.RBRACK) spec.TypeParams = &ast.FieldList{Opening: openPos, List: list, Closing: closePos} @@ -2563,19 +2571,34 @@ func (p *parser) parseTypeSpec(doc *ast.CommentGroup, _ token.Pos, _ token.Token lbrack := p.pos p.next() if p.tok == token.IDENT { - // array type or generic type [T any] - p.exprLev++ - x := p.parseExpr() - p.exprLev-- - if name0, _ := x.(*ast.Ident); p.allowGenerics() && name0 != nil && p.tok != token.RBRACK { - // generic type [T any]; + // array type or generic type: [name0... + name0 := p.parseIdent() + + if p.allowGenerics() && p.tok == token.LBRACK { + // Index or slice expressions are not valid array lengths, so we can + // parse as though we are in a generic type with array or slice + // constraint: [T [... p.parseGenericType(spec, lbrack, name0) + break } else { - // array type - // TODO(rfindley) should resolve all identifiers in x. - p.expect(token.RBRACK) - elt := p.parseType() - spec.Type = &ast.ArrayType{Lbrack: lbrack, Len: x, Elt: elt} + + // We may still have either an array type or generic type -- check if + // name0 is the entire expr. + p.exprLev++ + lhs := p.parsePrimaryExpr(name0) + x := p.parseExpr(lhs) + p.exprLev-- + + if name1, _ := x.(*ast.Ident); p.allowGenerics() && name1 != nil && p.tok != token.RBRACK { + // generic type [T any]; + p.parseGenericType(spec, lbrack, name1) + } else { + // array type + // TODO(rfindley) should resolve all identifiers in x. + p.expect(token.RBRACK) + elt := p.parseType() + spec.Type = &ast.ArrayType{Lbrack: lbrack, Len: x, Elt: elt} + } } } else { // array type diff --git a/src/go/parser/testdata/issue49174.go2 b/src/go/parser/testdata/issue49174.go2 new file mode 100644 index 0000000000..77c195083f --- /dev/null +++ b/src/go/parser/testdata/issue49174.go2 @@ -0,0 +1,8 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func _[_ []int | int]() {} +func _[_ int | []int]() {} diff --git a/src/go/parser/testdata/issue49175.go2 b/src/go/parser/testdata/issue49175.go2 new file mode 100644 index 0000000000..a5ad30f14c --- /dev/null +++ b/src/go/parser/testdata/issue49175.go2 @@ -0,0 +1,13 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type _[_ []t]t +type _[_ [1]t]t + +func _[_ []t]() {} +func _[_ [1]t]() {} + +type t [t /* ERROR "all type parameters must be named" */ [0]]t -- GitLab From 925ea2dfc4911188d47cca5c5534916e39dc1463 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 27 Oct 2021 11:14:24 -0400 Subject: [PATCH 1794/2500] go/types, types2, go/ast, go/parser: remove support for type lists This is a rough port of CL 354131 to go/* libraries, though in practice I just tried to reconcile any places where the phrase "type list" occurred in the source. This resulted in adjusting quite a bit more code than initially expected, including a few lingering cases in the compiler. Change-Id: Ie62a9e1aeb831b73931bc4c78bbb6ccb24f53fb0 Reviewed-on: https://go-review.googlesource.com/c/go/+/359135 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/interface.go | 2 +- src/cmd/compile/internal/types2/predicates.go | 2 +- .../types2/testdata/check/typeinst2.go2 | 10 ++--- .../types2/testdata/examples/types.go2 | 4 +- .../types2/testdata/fixedbugs/issue39711.go2 | 4 +- src/cmd/gofmt/testdata/typeparams.golden | 2 +- src/cmd/gofmt/testdata/typeparams.input | 2 +- src/go/ast/ast.go | 8 +--- src/go/parser/parser.go | 12 ------ src/go/parser/resolver.go | 13 ++---- src/go/parser/short_test.go | 3 +- src/go/parser/testdata/interface.go2 | 8 +--- src/go/parser/testdata/linalg.go2 | 16 ++++---- .../parser/testdata/resolution/typeparams.go2 | 4 +- src/go/printer/nodes.go | 34 +++------------- src/go/printer/testdata/generics.golden | 10 +---- src/go/printer/testdata/generics.input | 8 +--- src/go/types/call.go | 1 + src/go/types/exprstring.go | 23 +---------- src/go/types/exprstring_test.go | 11 +---- src/go/types/interface.go | 40 +------------------ src/go/types/predicates.go | 2 +- src/go/types/testdata/check/issues.go2 | 14 +++---- src/go/types/testdata/check/typeinst2.go2 | 13 +++--- .../types/testdata/examples/constraints.go2 | 12 ------ src/go/types/testdata/examples/types.go2 | 4 +- .../types/testdata/fixedbugs/issue39711.go2 | 4 +- src/go/types/union.go | 20 ++-------- 28 files changed, 66 insertions(+), 220 deletions(-) diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index 048fcab024..96c92ccaec 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -116,7 +116,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType } // f.Name != nil - // We have a method with name f.Name, or a type of a type list (f.Name.Value == "type"). + // We have a method with name f.Name. name := f.Name.Value if name == "_" { if check.conf.CompilerErrorMessages { diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 409715ad9d..380fb6489c 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -44,7 +44,7 @@ func isNumeric(typ Type) bool { return is(typ, IsNumeric) } func isString(typ Type) bool { return is(typ, IsString) } // Note that if typ is a type parameter, isInteger(typ) || isFloat(typ) does not -// produce the expected result because a type list that contains both an integer +// produce the expected result because a type set that contains both an integer // and a floating-point type is neither (all) integers, nor (all) floats. // Use isIntegerOrFloat instead. func isIntegerOrFloat(typ Type) bool { return is(typ, IsInteger|IsFloat) } diff --git a/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 b/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 index 5529bd093d..cd56c81bb9 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 @@ -172,7 +172,7 @@ type _ interface { ~struct{f int} | ~struct{g int} | ~struct /* ERROR overlapping terms */ {f int} } -// Interface type lists can contain any type, incl. *Named types. +// Interface term lists can contain any type, incl. *Named types. // Verify that we use the underlying type to compute the operational type. type MyInt int func add1[T interface{MyInt}](x T) T { @@ -184,9 +184,9 @@ func double[T interface{MyInt|MyString}](x T) T { return x + x } -// Embedding of interfaces with type lists leads to interfaces -// with type lists that are the intersection of the embedded -// type lists. +// Embedding of interfaces with term lists leads to interfaces +// with term lists that are the intersection of the embedded +// term lists. type E0 interface { ~int | ~bool | ~string @@ -277,4 +277,4 @@ func _[T none]() { _ = gg[T] _ = hh[int] _ = hh[T] -} \ No newline at end of file +} diff --git a/src/cmd/compile/internal/types2/testdata/examples/types.go2 b/src/cmd/compile/internal/types2/testdata/examples/types.go2 index 72b74cee01..077fcfdbb7 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/types.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/types.go2 @@ -276,8 +276,8 @@ func _() { // Type parameters are never const types, i.e., it's // not possible to declare a constant of type parameter type. -// (If a type list contains just a single const type, we could -// allow it, but such type lists don't make much sense in the +// (If a type set contains just a single const type, we could +// allow it, but such type sets don't make much sense in the // first place.) func _[T interface{~int|~float64}]() { // not valid diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39711.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39711.go2 index 85eb0a78fe..8f31012354 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39711.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39711.go2 @@ -4,10 +4,10 @@ package p -// Do not report a duplicate type error for this type list. +// Do not report a duplicate type error for this term list. // (Check types after interfaces have been completed.) type _ interface { // TODO(gri) Once we have full type sets we can enable this again. - // Fow now we don't permit interfaces in type lists. + // Fow now we don't permit interfaces in term lists. // type interface{ Error() string }, interface{ String() string } } diff --git a/src/cmd/gofmt/testdata/typeparams.golden b/src/cmd/gofmt/testdata/typeparams.golden index f71bd130db..d57a2ba59b 100644 --- a/src/cmd/gofmt/testdata/typeparams.golden +++ b/src/cmd/gofmt/testdata/typeparams.golden @@ -21,7 +21,7 @@ func f[P1, P2, P3 any](x1 P1, x2 P2, x3 P3) struct{} func f[P interface{}](x P) func f[P1, P2, P3 interface { m1(P1) - type P2, P3 + ~P2 | ~P3 }](x1 P1, x2 P2, x3 P3) struct{} func f[P any](T1[P], T2[P]) T3[P] diff --git a/src/cmd/gofmt/testdata/typeparams.input b/src/cmd/gofmt/testdata/typeparams.input index 5d4c53d9f7..775cf9eb7b 100644 --- a/src/cmd/gofmt/testdata/typeparams.input +++ b/src/cmd/gofmt/testdata/typeparams.input @@ -19,7 +19,7 @@ func f[P any](x P) func f[P1, P2, P3 any](x1 P1, x2 P2, x3 P3) struct{} func f[P interface{}](x P) -func f[P1, P2, P3 interface{ m1(P1); type P2, P3 }](x1 P1, x2 P2, x3 P3) struct{} +func f[P1, P2, P3 interface{ m1(P1); ~P2|~P3 }](x1 P1, x2 P2, x3 P3) struct{} func f[P any](T1[P], T2[P]) T3[P] func (x T[P]) m() diff --git a/src/go/ast/ast.go b/src/go/ast/ast.go index 38b6de57d3..bc140473d5 100644 --- a/src/go/ast/ast.go +++ b/src/go/ast/ast.go @@ -193,14 +193,10 @@ func isDirective(c string) bool { // in a signature. // Field.Names is nil for unnamed parameters (parameter lists which only contain types) // and embedded struct fields. In the latter case, the field name is the type name. -// Field.Names contains a single name "type" for elements of interface type lists. -// Types belonging to the same type list share the same "type" identifier which also -// records the position of that keyword. -// type Field struct { Doc *CommentGroup // associated documentation; or nil - Names []*Ident // field/method/(type) parameter names, or type "type"; or nil - Type Expr // field/method/parameter type, type list type; or nil + Names []*Ident // field/method/(type) parameter names; or nil + Type Expr // field/method/parameter type; or nil Tag *BasicLit // field tag; or nil Comment *CommentGroup // line comments; or nil } diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go index 999663b98c..792fe4141c 100644 --- a/src/go/parser/parser.go +++ b/src/go/parser/parser.go @@ -1128,18 +1128,6 @@ parseElements: p.expectSemi() comment := p.lineComment list = append(list, &ast.Field{Type: typ, Comment: comment}) - case p.tok == token.TYPE && p.allowGenerics(): - // TODO(rfindley): remove TypeList syntax and refactor the clauses above. - - // all types in a type list share the same field name "type" - // (since type is a keyword, a Go program cannot have that field name) - name := []*ast.Ident{{NamePos: p.pos, Name: "type"}} - p.next() - // add each type as a field named "type" - for _, typ := range p.parseTypeList() { - list = append(list, &ast.Field{Names: name, Type: typ}) - } - p.expectSemi() case p.allowGenerics(): if t := p.tryIdentOrType(); t != nil { typ := p.embeddedElem(t) diff --git a/src/go/parser/resolver.go b/src/go/parser/resolver.go index 527f1691bd..54732a7fd6 100644 --- a/src/go/parser/resolver.go +++ b/src/go/parser/resolver.go @@ -117,12 +117,6 @@ func (r *resolver) closeLabelScope() { func (r *resolver) declare(decl, data interface{}, scope *ast.Scope, kind ast.ObjKind, idents ...*ast.Ident) { for _, ident := range idents { - // "type" is used for type lists in interfaces, and is otherwise an invalid - // identifier. The 'type' identifier is also artificially duplicated in the - // type list, so could cause panics below if we were to proceed. - if ident.Name == "type" { - continue - } assert(ident.Obj == nil, "identifier already declared or resolved") obj := ast.NewObj(kind, ident.Name) // remember the corresponding declaration for redeclaration @@ -188,10 +182,9 @@ func (r *resolver) resolve(ident *ast.Ident, collectUnresolved bool) { if ident.Obj != nil { panic(fmt.Sprintf("%s: identifier %s already declared or resolved", r.handle.Position(ident.Pos()), ident.Name)) } - // '_' and 'type' should never refer to existing declarations: '_' because it - // has special handling in the spec, and 'type' because it is a keyword, and - // only valid in an interface type list. - if ident.Name == "_" || ident.Name == "type" { + // '_' should never refer to existing declarations, because it has special + // handling in the spec. + if ident.Name == "_" { return } for s := r.topScope; s != nil; s = s.Outer { diff --git a/src/go/parser/short_test.go b/src/go/parser/short_test.go index bfc6f6714b..20450bfe8e 100644 --- a/src/go/parser/short_test.go +++ b/src/go/parser/short_test.go @@ -119,8 +119,7 @@ var validWithTParamsOnly = []string{ `package p; func _(T[P] /* ERROR "missing element type" */ ) T[P]`, `package p; type _ struct{ T[P] /* ERROR "missing element type" */ }`, `package p; type _ struct{ T[struct /* ERROR "expected expression" */ {a, b, c int}] }`, - `package p; type _ interface{type /* ERROR "expected '}', found 'type'" */ int}`, - `package p; type _ interface{type /* ERROR "expected '}', found 'type'" */ int, float32; type bool; m(); type string;}`, + `package p; type _ interface{int| /* ERROR "expected ';'" */ float32; bool; m(); string;}`, `package p; type I1[T any /* ERROR "expected ']', found any" */ ] interface{}; type I2 interface{ I1[int] }`, `package p; type I1[T any /* ERROR "expected ']', found any" */ ] interface{}; type I2[T any] interface{ I1[T] }`, `package p; type _ interface { f[ /* ERROR "expected ';', found '\['" */ T any]() }`, diff --git a/src/go/parser/testdata/interface.go2 b/src/go/parser/testdata/interface.go2 index b399d75148..2ed9339c52 100644 --- a/src/go/parser/testdata/interface.go2 +++ b/src/go/parser/testdata/interface.go2 @@ -4,16 +4,13 @@ // This file contains test cases for interfaces containing // constraint elements. -// -// For now, we accept both ordinary type lists and the -// more complex constraint elements. package p type _ interface { m() - type int - type int, string + ~int + ~int|string E } @@ -31,7 +28,6 @@ type _ interface { T[int, string] | string int | ~T[string, struct{}] ~int | ~string - type bool, int, float64 } type _ interface { diff --git a/src/go/parser/testdata/linalg.go2 b/src/go/parser/testdata/linalg.go2 index fba0d02eb2..7ccb19c08d 100644 --- a/src/go/parser/testdata/linalg.go2 +++ b/src/go/parser/testdata/linalg.go2 @@ -9,10 +9,10 @@ import "math" // Numeric is type bound that matches any numeric type. // It would likely be in a constraints package in the standard library. type Numeric interface { - type int, int8, int16, int32, int64, - uint, uint8, uint16, uint32, uint64, uintptr, - float32, float64, - complex64, complex128 + ~int|~int8|~int16|~int32|~int64| + ~uint|~uint8|~uint16|~uint32|~uint64|~uintptr| + ~float32|~float64| + ~complex64|~complex128 } func DotProduct[T Numeric](s1, s2 []T) T { @@ -42,14 +42,14 @@ func AbsDifference[T NumericAbs](a, b T) T { // OrderedNumeric is a type bound that matches numeric types that support the < operator. type OrderedNumeric interface { - type int, int8, int16, int32, int64, - uint, uint8, uint16, uint32, uint64, uintptr, - float32, float64 + ~int|~int8|~int16|~int32|~int64| + ~uint|~uint8|~uint16|~uint32|~uint64|~uintptr| + ~float32|~float64 } // Complex is a type bound that matches the two complex types, which do not have a < operator. type Complex interface { - type complex64, complex128 + ~complex64|~complex128 } // OrderedAbs is a helper type that defines an Abs method for diff --git a/src/go/parser/testdata/resolution/typeparams.go2 b/src/go/parser/testdata/resolution/typeparams.go2 index 0ffecd69b5..8c243afda7 100644 --- a/src/go/parser/testdata/resolution/typeparams.go2 +++ b/src/go/parser/testdata/resolution/typeparams.go2 @@ -15,7 +15,7 @@ type Pair /* =@Pair */ [L /* =@L */, R /* =@R */ any] struct { var _ = Pair /* @Pair */ [int, string]{} type Addable /* =@Addable */ interface { - type int64, float64 + ~int64|~float64 } func Add /* =@AddDecl */[T /* =@T */ Addable /* @Addable */](l /* =@l */, r /* =@r */ T /* @T */) T /* @T */ { @@ -30,7 +30,7 @@ type Receiver /* =@Receiver */[P /* =@P */ any] struct {} // parameter below. func (r /* =@recv */ Receiver /* @Receiver */ [P]) m() P {} -func f /* =@f */[T1 /* =@T1 */ interface{type []T2 /* @T2 */}, T2 /* =@T2 */ any]( +func f /* =@f */[T1 /* =@T1 */ interface{~[]T2 /* @T2 */}, T2 /* =@T2 */ any]( x /* =@x */ T1 /* @T1 */, T1 /* =@T1_duplicate */ y, // Note that this is a bug: // the duplicate T1 should // not be allowed. diff --git a/src/go/printer/nodes.go b/src/go/printer/nodes.go index 567b2339b4..19d4ab6663 100644 --- a/src/go/printer/nodes.go +++ b/src/go/printer/nodes.go @@ -471,17 +471,9 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) p.expr(f.Type) } else { // interface if len(f.Names) > 0 { - // type list type or method - name := f.Names[0] // "type" or method name + name := f.Names[0] // method name p.expr(name) - if name.Name == "type" { - // type list type - p.print(blank) - p.expr(f.Type) - } else { - // method - p.signature(f.Type.(*ast.FuncType)) // don't print "func" - } + p.signature(f.Type.(*ast.FuncType)) // don't print "func" } else { // embedded interface p.expr(f.Type) @@ -568,24 +560,10 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) p.setComment(f.Doc) p.recordLine(&line) if name != nil { - // type list type or method - if name.Name == "type" { - // type list type - if name == prev { - // type is part of a list of types - p.print(token.COMMA, blank) - } else { - // type starts a new list of types - p.print(name, blank) - } - p.expr(f.Type) - prev = name - } else { - // method - p.expr(name) - p.signature(f.Type.(*ast.FuncType)) // don't print "func" - prev = nil - } + // method + p.expr(name) + p.signature(f.Type.(*ast.FuncType)) // don't print "func" + prev = nil } else { // embedded interface p.expr(f.Type) diff --git a/src/go/printer/testdata/generics.golden b/src/go/printer/testdata/generics.golden index 31ab7716dd..3d95eda5b2 100644 --- a/src/go/printer/testdata/generics.golden +++ b/src/go/printer/testdata/generics.golden @@ -22,7 +22,7 @@ func f[P1, P2, P3 any](x1 P1, x2 P2, x3 P3) struct{} func f[P interface{}](x P) func f[P1, P2, P3 interface { m1(P1) - type P2, P3 + ~P2 | ~P3 }](x1 P1, x2 P2, x3 P3) struct{} func f[P any](T1[P], T2[P]) T3[P] @@ -35,14 +35,6 @@ func _() { _ = []T[P]{} } -// properly format one-line type lists -// TODO(rfindley): remove support for type lists -type _ interface{ type a } - -type _ interface { - type a, b, c -} - // type constraint literals with elided interfaces func _[P ~int, Q int | string]() {} func _[P struct{ f int }, Q *P]() {} diff --git a/src/go/printer/testdata/generics.input b/src/go/printer/testdata/generics.input index 11431c5a0a..746dfdd235 100644 --- a/src/go/printer/testdata/generics.input +++ b/src/go/printer/testdata/generics.input @@ -20,7 +20,7 @@ func f[P any](x P) func f[P1, P2, P3 any](x1 P1, x2 P2, x3 P3) struct{} func f[P interface{}](x P) -func f[P1, P2, P3 interface{ m1(P1); type P2, P3 }](x1 P1, x2 P2, x3 P3) struct{} +func f[P1, P2, P3 interface{ m1(P1); ~P2|~P3 }](x1 P1, x2 P2, x3 P3) struct{} func f[P any](T1[P], T2[P]) T3[P] func (x T[P]) m() @@ -32,12 +32,6 @@ func _() { _ = []T[P]{} } -// properly format one-line type lists -// TODO(rfindley): remove support for type lists -type _ interface { type a } - -type _ interface { type a,b,c } - // type constraint literals with elided interfaces func _[P ~int, Q int | string]() {} func _[P struct{f int}, Q *P]() {} diff --git a/src/go/types/call.go b/src/go/types/call.go index 4731c69619..6894f1c182 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -141,6 +141,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { } if t := asInterface(T); t != nil { if !t.IsMethodSet() { + // TODO(rfindley): remove the phrase "type list" from this error. check.errorf(call, _Todo, "cannot use interface %s in conversion (contains type list or is comparable)", T) break } diff --git a/src/go/types/exprstring.go b/src/go/types/exprstring.go index 06e7a9dcb4..aa4f403c1f 100644 --- a/src/go/types/exprstring.go +++ b/src/go/types/exprstring.go @@ -145,29 +145,8 @@ func WriteExpr(buf *bytes.Buffer, x ast.Expr) { writeSigExpr(buf, x) case *ast.InterfaceType: - // separate type list types from method list - // TODO(gri) we can get rid of this extra code if writeExprList does the separation - var types []ast.Expr - var methods []*ast.Field - for _, f := range x.Methods.List { - if len(f.Names) > 1 && f.Names[0].Name == "type" { - // type list type - types = append(types, f.Type) - } else { - // method or embedded interface - methods = append(methods, f) - } - } - buf.WriteString("interface{") - writeFieldList(buf, methods, "; ", true) - if len(types) > 0 { - if len(methods) > 0 { - buf.WriteString("; ") - } - buf.WriteString("type ") - writeExprList(buf, types) - } + writeFieldList(buf, x.Methods.List, "; ", true) buf.WriteByte('}') case *ast.MapType: diff --git a/src/go/types/exprstring_test.go b/src/go/types/exprstring_test.go index a67f6a978a..27cd532c97 100644 --- a/src/go/types/exprstring_test.go +++ b/src/go/types/exprstring_test.go @@ -36,15 +36,8 @@ var testExprs = []testEntry{ dup("func(int, float32) string"), dup("interface{m()}"), dup("interface{m() string; n(x int)}"), - dup("interface{type int}"), - - // The following exprs do not get formatted correctly: each element in the - // type list is printed on a separate line. This is left as a placeholder - // until type lists are removed. - // TODO(rfindley): remove this once type lists are gone. - // dup("interface{type int, float64, string}"), - // dup("interface{type int; m()}"), - // dup("interface{type int, float64, string; m() string; n(x int)}"), + dup("interface{~int}"), + dup("map[string]int"), dup("chan E"), dup("<-chan E"), diff --git a/src/go/types/interface.go b/src/go/types/interface.go index 3d5573373f..c170ed4a60 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -142,9 +142,6 @@ func (t *Interface) String() string { return TypeString(t, nil) } // Implementation func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, def *Named) { - var tlist []ast.Expr - var tname *ast.Ident // "type" name of first entry in a type list declaration - addEmbedded := func(pos token.Pos, typ Type) { ityp.embeddeds = append(ityp.embeddeds, typ) if ityp.embedPos == nil { @@ -158,41 +155,15 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d addEmbedded(f.Type.Pos(), parseUnion(check, flattenUnion(nil, f.Type))) continue } + // f.Name != nil - // We have a method with name f.Names[0], or a type - // of a type list (name.Name == "type"). - // (The parser ensures that there's only one method - // and we don't care if a constructed AST has more.) + // We have a method with name f.Names[0]. name := f.Names[0] if name.Name == "_" { check.errorf(name, _BlankIfaceMethod, "invalid method name _") continue // ignore } - // TODO(rfindley) Remove type list handling once the parser doesn't accept type lists anymore. - if name.Name == "type" { - // Report an error for the first type list per interface - // if we don't allow type lists, but continue. - if !allowTypeLists && tlist == nil { - check.softErrorf(name, _Todo, "use generalized embedding syntax instead of a type list") - } - // For now, collect all type list entries as if it - // were a single union, where each union element is - // of the form ~T. - // TODO(rfindley) remove once we disallow type lists - op := new(ast.UnaryExpr) - op.Op = token.TILDE - op.X = f.Type - tlist = append(tlist, op) - // Report an error if we have multiple type lists in an - // interface, but only if they are permitted in the first place. - if allowTypeLists && tname != nil && tname != name { - check.errorf(name, _Todo, "cannot have multiple type lists in an interface") - } - tname = name - continue - } - typ := check.typ(f.Type) sig, _ := typ.(*Signature) if sig == nil { @@ -225,13 +196,6 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d ityp.methods = append(ityp.methods, m) } - // type constraints - if tlist != nil { - // TODO(rfindley): this differs from types2 due to the use of Pos() below, - // which should actually be on the ~. Confirm that this position is correct. - addEmbedded(tlist[0].Pos(), parseUnion(check, tlist)) - } - // All methods and embedded elements for this interface are collected; // i.e., this interface may be used in a type set computation. ityp.complete = true diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index a5d4be9bcc..b687c151c7 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -45,7 +45,7 @@ func isNumeric(typ Type) bool { return is(typ, IsNumeric) } func isString(typ Type) bool { return is(typ, IsString) } // Note that if typ is a type parameter, isInteger(typ) || isFloat(typ) does not -// produce the expected result because a type list that contains both an integer +// produce the expected result because a type set that contains both an integer // and a floating-point type is neither (all) integers, nor (all) floats. // Use isIntegerOrFloat instead. func isIntegerOrFloat(typ Type) bool { return is(typ, IsInteger|IsFloat) } diff --git a/src/go/types/testdata/check/issues.go2 b/src/go/types/testdata/check/issues.go2 index c46a34e2eb..6a93bcc9ac 100644 --- a/src/go/types/testdata/check/issues.go2 +++ b/src/go/types/testdata/check/issues.go2 @@ -53,8 +53,8 @@ func _() { } // When a type parameter is used as an argument to instantiate a parameterized -// type with a type list constraint, all of the type argument's types in its -// bound, but at least one (!), must be in the type list of the bound of the +// type with a type set constraint, all of the type argument's types in its +// bound, but at least one (!), must be in the type set of the bound of the // corresponding parameterized type's type parameter. type T1[P interface{~uint}] struct{} @@ -152,7 +152,7 @@ type inf2 /* ERROR illegal cycle */ [T any] struct{ inf2[T] } // The implementation of conversions T(x) between integers and floating-point // numbers checks that both T and x have either integer or floating-point // type. When the type of T or x is a type parameter, the respective simple -// predicate disjunction in the implementation was wrong because if a type list +// predicate disjunction in the implementation was wrong because if a term list // contains both an integer and a floating-point type, the type parameter is // neither an integer or a floating-point number. func convert[T1, T2 interface{~int | ~uint | ~float32}](v T1) T2 { @@ -185,13 +185,13 @@ func _[T interface{}, PT interface{~*T}] (x T) PT { return &x } -// Indexing of generic types containing type parameters in their type list: +// Indexing of generic types containing type parameters in their term list: func at[T interface{ ~[]E }, E interface{}](x T, i int) E { return x[i] } // A generic type inside a function acts like a named type. Its underlying -// type is itself, its "operational type" is defined by the type list in +// type is itself, its "operational type" is defined by the term list in // the tybe bound, if any. func _[T interface{~int}](x T) { type myint int @@ -224,9 +224,9 @@ func _[T interface{ ~func() }](f T) { go f() } -// We must compare against the underlying type of type list entries +// We must compare against the underlying type of term list entries // when checking if a constraint is satisfied by a type. The under- -// lying type of each type list entry must be computed after the +// lying type of each term list entry must be computed after the // interface has been instantiated as its typelist may contain a // type parameter that was substituted with a defined type. // Test case from an (originally) failing example. diff --git a/src/go/types/testdata/check/typeinst2.go2 b/src/go/types/testdata/check/typeinst2.go2 index 88913785c8..37d32263d4 100644 --- a/src/go/types/testdata/check/typeinst2.go2 +++ b/src/go/types/testdata/check/typeinst2.go2 @@ -159,10 +159,7 @@ type _ interface { ~rune } -// Interface type lists may contain each type at most once. -// (If there are multiple lists, we assume the author intended -// for them to be all in a single list, and we report the error -// as well.) +// Type sets may contain each type at most once. type _ interface { ~int|~ /* ERROR overlapping terms ~int */ int ~int|int /* ERROR overlapping terms int */ @@ -173,7 +170,7 @@ type _ interface { ~struct{f int} | ~struct{g int} | ~ /* ERROR overlapping terms */ struct {f int} } -// Interface type lists can contain any type, incl. *Named types. +// Interface term lists can contain any type, incl. *Named types. // Verify that we use the underlying type to compute the operational type. type MyInt int func add1[T interface{MyInt}](x T) T { @@ -185,9 +182,9 @@ func double[T interface{MyInt|MyString}](x T) T { return x + x } -// Embedding of interfaces with type lists leads to interfaces -// with type lists that are the intersection of the embedded -// type lists. +// Embedding of interfaces with term lists leads to interfaces +// with term lists that are the intersection of the embedded +// term lists. type E0 interface { ~int | ~bool | ~string diff --git a/src/go/types/testdata/examples/constraints.go2 b/src/go/types/testdata/examples/constraints.go2 index ecc75c1a46..4d7f70313a 100644 --- a/src/go/types/testdata/examples/constraints.go2 +++ b/src/go/types/testdata/examples/constraints.go2 @@ -6,18 +6,6 @@ package p -type ( - // Type lists are processed as unions but an error is reported. - // TODO(gri) remove this once the parser doesn't accept type lists anymore. - _ interface{ - type /* ERROR use generalized embedding syntax instead of a type list */ int - } - _ interface{ - type /* ERROR use generalized embedding syntax instead of a type list */ int - type float32 - } -) - type MyInt int type ( diff --git a/src/go/types/testdata/examples/types.go2 b/src/go/types/testdata/examples/types.go2 index 807c03238f..367b73120c 100644 --- a/src/go/types/testdata/examples/types.go2 +++ b/src/go/types/testdata/examples/types.go2 @@ -281,8 +281,8 @@ func _() { // Type parameters are never const types, i.e., it's // not possible to declare a constant of type parameter type. -// (If a type list contains just a single const type, we could -// allow it, but such type lists don't make much sense in the +// (If a type set contains just a single const type, we could +// allow it, but such type sets don't make much sense in the // first place.) func _[T interface {~int|~float64}]() { // not valid diff --git a/src/go/types/testdata/fixedbugs/issue39711.go2 b/src/go/types/testdata/fixedbugs/issue39711.go2 index cf1f90545f..d85fa03fc4 100644 --- a/src/go/types/testdata/fixedbugs/issue39711.go2 +++ b/src/go/types/testdata/fixedbugs/issue39711.go2 @@ -4,10 +4,10 @@ package p -// Do not report a duplicate type error for this type list. +// Do not report a duplicate type error for this term list. // (Check types after interfaces have been completed.) type _ interface { // TODO(rfindley) Once we have full type sets we can enable this again. - // Fow now we don't permit interfaces in type lists. + // Fow now we don't permit interfaces in term lists. // type interface{ Error() string }, interface{ String() string } } diff --git a/src/go/types/union.go b/src/go/types/union.go index 88b2a9ff8f..c715839315 100644 --- a/src/go/types/union.go +++ b/src/go/types/union.go @@ -78,28 +78,16 @@ func parseUnion(check *Checker, tlist []ast.Expr) Type { continue } - x := tlist[i] - pos := x.Pos() - // We may not know the position of x if it was a typechecker- - // introduced ~T term for a type list entry T. Use the position - // of T instead. - // TODO(rfindley) remove this test once we don't support type lists anymore - if !pos.IsValid() { - if op, _ := x.(*ast.UnaryExpr); op != nil { - pos = op.X.Pos() - } - } - u := under(t.typ) f, _ := u.(*Interface) if t.tilde { if f != nil { - check.errorf(x, _Todo, "invalid use of ~ (%s is an interface)", t.typ) + check.errorf(tlist[i], _Todo, "invalid use of ~ (%s is an interface)", t.typ) continue // don't report another error for t } if !Identical(u, t.typ) { - check.errorf(x, _Todo, "invalid use of ~ (underlying type of %s is %s)", t.typ, u) + check.errorf(tlist[i], _Todo, "invalid use of ~ (underlying type of %s is %s)", t.typ, u) continue // don't report another error for t } } @@ -108,14 +96,14 @@ func parseUnion(check *Checker, tlist []ast.Expr) Type { // in the beginning. Embedded interfaces with tilde are excluded above. If we reach // here, we must have at least two terms in the union. if f != nil && !f.typeSet().IsTypeSet() { - check.errorf(atPos(pos), _Todo, "cannot use %s in union (interface contains methods)", t) + check.errorf(tlist[i], _Todo, "cannot use %s in union (interface contains methods)", t) continue // don't report another error for t } // Report overlapping (non-disjoint) terms such as // a|a, a|~a, ~a|~a, and ~a|A (where under(A) == a). if j := overlappingTerm(terms[:i], t); j >= 0 { - check.softErrorf(atPos(pos), _Todo, "overlapping terms %s and %s", t, terms[j]) + check.softErrorf(tlist[i], _Todo, "overlapping terms %s and %s", t, terms[j]) } } }) -- GitLab From 4f1c9aace00277914e080170237ae381e05683c5 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 27 Oct 2021 11:23:06 -0400 Subject: [PATCH 1795/2500] go/types: add debugging support for delayed actions This is a port of CL 355871 to go/types. Change-Id: I2dbc3c625c16b545a271a19606ef34ce04a4a6df Reviewed-on: https://go-review.googlesource.com/c/go/+/359136 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/check.go | 39 +++++++++++++++++++++++++++++++++---- src/go/types/decl.go | 2 +- src/go/types/instantiate.go | 2 +- src/go/types/interface.go | 2 +- src/go/types/struct.go | 2 +- src/go/types/typexpr.go | 2 -- 6 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/go/types/check.go b/src/go/types/check.go index 3fc9c03917..2b8ef9f061 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -76,6 +76,28 @@ type dotImportKey struct { name string } +// An action describes a (delayed) action. +type action struct { + f func() // action to be executed + desc *actionDesc // action description; may be nil, requires debug to be set +} + +// If debug is set, describef sets a printf-formatted description for action a. +// Otherwise, it is a no-op. +func (a *action) describef(pos positioner, format string, args ...interface{}) { + if debug { + a.desc = &actionDesc{pos, format, args} + } +} + +// An actionDesc provides information on an action. +// For debugging only. +type actionDesc struct { + pos positioner + format string + args []interface{} +} + // A Checker maintains the state of the type checker. // It must be created with NewChecker. type Checker struct { @@ -111,7 +133,7 @@ type Checker struct { firstErr error // first error encountered methods map[*TypeName][]*Func // maps package scope type names to associated non-blank (non-interface) methods untyped map[ast.Expr]exprInfo // map of expressions without final type - delayed []func() // stack of delayed action segments; segments are processed in FIFO order + delayed []action // stack of delayed action segments; segments are processed in FIFO order objPath []Object // path of object dependencies during type inference (for cycle reporting) defTypes []*Named // defined types created during type checking, for final validation. @@ -148,8 +170,12 @@ func (check *Checker) rememberUntyped(e ast.Expr, lhs bool, mode operandMode, ty // either at the end of the current statement, or in case of a local constant // or variable declaration, before the constant or variable is in scope // (so that f still sees the scope before any new declarations). -func (check *Checker) later(f func()) { - check.delayed = append(check.delayed, f) +// later returns the pushed action so one can provide a description +// via action.describef for debugging, if desired. +func (check *Checker) later(f func()) *action { + i := len(check.delayed) + check.delayed = append(check.delayed, action{f: f}) + return &check.delayed[i] } // push pushes obj onto the object path and returns its index in the path. @@ -304,7 +330,12 @@ func (check *Checker) processDelayed(top int) { // add more actions (such as nested functions), so // this is a sufficiently bounded process. for i := top; i < len(check.delayed); i++ { - check.delayed[i]() // may append to check.delayed + a := &check.delayed[i] + if trace && a.desc != nil { + fmt.Println() + check.trace(a.desc.pos.Pos(), "-- "+a.desc.format, a.desc.args...) + } + a.f() // may append to check.delayed } assert(top <= len(check.delayed)) // stack must not have shrunk check.delayed = check.delayed[:top] diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 3e97fbbccd..6982fed0b8 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -610,7 +610,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { if check.isImportedConstraint(rhs) && !check.allowVersion(check.pkg, 1, 18) { check.errorf(tdecl.Type, _Todo, "using type constraint %s requires go1.18 or later", rhs) } - }) + }).describef(obj, "validType(%s)", obj.Name()) alias := tdecl.Assign.IsValid() if alias && tdecl.TypeParams.NumFields() != 0 { diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 2bb31b17ee..3720cb725a 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -65,7 +65,7 @@ func (check *Checker) instance(pos token.Pos, typ Type, targs []Type, ctxt *Cont } } tname := NewTypeName(pos, t.obj.pkg, t.obj.name, nil) - named := check.newNamed(tname, t, nil, nil, nil) // methods and tparams are set when named is resolved + named := check.newNamed(tname, t, nil, nil, nil) // underlying, tparams, and methods are set when named is resolved named.targs = NewTypeList(targs) named.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, []*Func) { return expandNamed(ctxt, n, pos) diff --git a/src/go/types/interface.go b/src/go/types/interface.go index c170ed4a60..78813e665b 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -221,7 +221,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d check.later(func() { computeInterfaceTypeSet(check, iface.Pos(), ityp) ityp.check = nil - }) + }).describef(iface, "compute type set for %s", ityp) } func flattenUnion(list []ast.Expr, x ast.Expr) []ast.Expr { diff --git a/src/go/types/struct.go b/src/go/types/struct.go index 24a2435ff7..442c7a66e3 100644 --- a/src/go/types/struct.go +++ b/src/go/types/struct.go @@ -155,7 +155,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) { check.error(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a pointer to an interface") } } - }) + }).describef(embeddedPos, "check embedded type %s", embeddedTyp) } } diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index e812c3d5d5..092e355b38 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -210,8 +210,6 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) { if T != nil { // Calling under() here may lead to endless instantiations. // Test case: type T[P any] *T[P] - // TODO(gri) investigate if that's a bug or to be expected - // (see also analogous comment in Checker.instantiate). under = safeUnderlying(T) } if T == under { -- GitLab From 278b9b3a4c7c01929133737e960335afa18eeec3 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 27 Oct 2021 12:06:46 -0400 Subject: [PATCH 1796/2500] go/types: implement generic conversions This is a port of 4 CLs from types2: CL 356010, CL 357333, CL 357410, and CL 357249. These 4 CLs are all related to implementing conversions, and porting them together saved time (particularly because go/types was already threading a *reason argument in some places). Change-Id: Ic89b608d7096b61bfb9f7d71fdae2cc50b0ed70e Reviewed-on: https://go-review.googlesource.com/c/go/+/359137 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/api.go | 2 +- .../compile/internal/types2/conversions.go | 4 +- src/go/types/conversions.go | 86 ++++++++--- src/go/types/operand.go | 6 +- .../types/testdata/examples/conversions.go2 | 144 ++++++++++++++++++ 5 files changed, 218 insertions(+), 24 deletions(-) create mode 100644 src/go/types/testdata/examples/conversions.go2 diff --git a/src/cmd/compile/internal/types2/api.go b/src/cmd/compile/internal/types2/api.go index f13fa95b62..83c4b02abf 100644 --- a/src/cmd/compile/internal/types2/api.go +++ b/src/cmd/compile/internal/types2/api.go @@ -438,7 +438,7 @@ func AssignableTo(V, T Type) bool { // ConvertibleTo reports whether a value of type V is convertible to a value of type T. func ConvertibleTo(V, T Type) bool { x := operand{mode: value, typ: V} - return x.convertibleTo(nil, T, nil) // check not needed for non-constant x; if check == nil, cause can be nil + return x.convertibleTo(nil, T, nil) // check not needed for non-constant x } // Implements reports whether type V implements interface T. diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go index a456f89f7e..bc33b3a44b 100644 --- a/src/cmd/compile/internal/types2/conversions.go +++ b/src/cmd/compile/internal/types2/conversions.go @@ -178,12 +178,12 @@ func convertibleToImpl(check *Checker, V, T Type, cause *string) bool { return true } - // "V an integer or a slice of bytes or runes and T is a string type" + // "V is an integer or a slice of bytes or runes and T is a string type" if (isInteger(V) || isBytesOrRunes(Vu)) && isString(T) { return true } - // "V a string and T is a slice of bytes or runes" + // "V is a string and T is a slice of bytes or runes" if isString(V) && isBytesOrRunes(Tu) { return true } diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go index a1fcdd4fd8..fe62adbf10 100644 --- a/src/go/types/conversions.go +++ b/src/go/types/conversions.go @@ -17,7 +17,7 @@ func (check *Checker) conversion(x *operand, T Type) { constArg := x.mode == constant_ var ok bool - var reason string + var cause string switch { case constArg && isConstType(T): // constant conversion @@ -32,15 +32,16 @@ func (check *Checker) conversion(x *operand, T Type) { x.val = constant.MakeString(string(codepoint)) ok = true } - case x.convertibleTo(check, T, &reason): + case x.convertibleTo(check, T, &cause): // non-constant conversion x.mode = value ok = true } if !ok { - if reason != "" { - check.errorf(x, _InvalidConversion, "cannot convert %s to %s (%s)", x, T, reason) + // TODO(rfindley): use types2-style error reporting here. + if cause != "" { + check.errorf(x, _InvalidConversion, "cannot convert %s to %s (%s)", x, T, cause) } else { check.errorf(x, _InvalidConversion, "cannot convert %s to %s", x, T) } @@ -81,24 +82,75 @@ func (check *Checker) conversion(x *operand, T Type) { // is tricky because we'd have to run updateExprType on the argument first. // (Issue #21982.) -// convertibleTo reports whether T(x) is valid. +// convertibleTo reports whether T(x) is valid. In the failure case, *cause +// may be set to the cause for the failure. // The check parameter may be nil if convertibleTo is invoked through an // exported API call, i.e., when all methods have been type-checked. -func (x *operand) convertibleTo(check *Checker, T Type, reason *string) bool { +func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { // "x is assignable to T" - if ok, _ := x.assignableTo(check, T, nil); ok { + if ok, _ := x.assignableTo(check, T, cause); ok { return true } - // "x's type and T have identical underlying types if tags are ignored" - V := x.typ + errorf := func(format string, args ...interface{}) { + if check != nil && cause != nil { + msg := check.sprintf(format, args...) + if *cause != "" { + msg += "\n\t" + *cause + } + *cause = msg + } + } + + // TODO(gri) consider passing under(x.typ), under(T) into convertibleToImpl (optimization) + Vp, _ := under(x.typ).(*TypeParam) + Tp, _ := under(T).(*TypeParam) + + // generic cases + // (generic operands cannot be constants, so we can ignore x.val) + switch { + case Vp != nil && Tp != nil: + return Vp.is(func(V *term) bool { + return Tp.is(func(T *term) bool { + if !convertibleToImpl(check, V.typ, T.typ, cause) { + errorf("cannot convert %s (in %s) to %s (in %s)", V.typ, Vp, T.typ, Tp) + return false + } + return true + }) + }) + case Vp != nil: + return Vp.is(func(V *term) bool { + if !convertibleToImpl(check, V.typ, T, cause) { + errorf("cannot convert %s (in %s) to %s", V.typ, Vp, T) + return false + } + return true + }) + case Tp != nil: + return Tp.is(func(T *term) bool { + if !convertibleToImpl(check, x.typ, T.typ, cause) { + errorf("cannot convert %s to %s (in %s)", x.typ, T.typ, Tp) + return false + } + return true + }) + } + + // non-generic case + return convertibleToImpl(check, x.typ, T, cause) +} + +// convertibleToImpl should only be called by convertibleTo +func convertibleToImpl(check *Checker, V, T Type, cause *string) bool { + // "V and T have identical underlying types if tags are ignored" Vu := under(V) Tu := under(T) if IdenticalIgnoreTags(Vu, Tu) { return true } - // "x's type and T are unnamed pointer types and their pointer base types + // "V and T are unnamed pointer types and their pointer base types // have identical underlying types if tags are ignored" if V, ok := V.(*Pointer); ok { if T, ok := T.(*Pointer); ok { @@ -108,22 +160,22 @@ func (x *operand) convertibleTo(check *Checker, T Type, reason *string) bool { } } - // "x's type and T are both integer or floating point types" + // "V and T are both integer or floating point types" if isIntegerOrFloat(V) && isIntegerOrFloat(T) { return true } - // "x's type and T are both complex types" + // "V and T are both complex types" if isComplex(V) && isComplex(T) { return true } - // "x is an integer or a slice of bytes or runes and T is a string type" + // "V is an integer or a slice of bytes or runes and T is a string type" if (isInteger(V) || isBytesOrRunes(Vu)) && isString(T) { return true } - // "x is a string and T is a slice of bytes or runes" + // "V is a string and T is a slice of bytes or runes" if isString(V) && isBytesOrRunes(Tu) { return true } @@ -138,7 +190,7 @@ func (x *operand) convertibleTo(check *Checker, T Type, reason *string) bool { return true } - // "x is a slice, T is a pointer-to-array type, + // "V is a slice, T is a pointer-to-array type, // and the slice and array types have identical element types." if s := asSlice(V); s != nil { if p := asPointer(T); p != nil { @@ -147,8 +199,8 @@ func (x *operand) convertibleTo(check *Checker, T Type, reason *string) bool { if check == nil || check.allowVersion(check.pkg, 1, 17) { return true } - if reason != nil { - *reason = "conversion of slices to array pointers requires go1.17 or later" + if cause != nil { + *cause = "conversion of slices to array pointers requires go1.17 or later" } } } diff --git a/src/go/types/operand.go b/src/go/types/operand.go index a54802defc..855dac66aa 100644 --- a/src/go/types/operand.go +++ b/src/go/types/operand.go @@ -159,17 +159,14 @@ func operandString(x *operand, qf Qualifier) string { if hasType { if x.typ != Typ[Invalid] { var intro string - var tpar *TypeParam if isGeneric(x.typ) { intro = " of parameterized type " - } else if tpar = asTypeParam(x.typ); tpar != nil { - intro = " of type parameter " } else { intro = " of type " } buf.WriteString(intro) WriteType(&buf, x.typ, qf) - if tpar != nil { + if tpar := asTypeParam(x.typ); tpar != nil { buf.WriteString(" constrained by ") WriteType(&buf, tpar.bound, qf) // do not compute interface type sets here } @@ -284,6 +281,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er if Ti, ok := Tu.(*Interface); ok { if m, wrongType := check.missingMethod(V, Ti, true); m != nil /* Implements(V, Ti) */ { if reason != nil { + // TODO(gri) the error messages here should follow the style in Checker.typeAssertion (factor!) if wrongType != nil { if Identical(m.typ, wrongType.typ) { *reason = fmt.Sprintf("missing method %s (%s has pointer receiver)", m.name, m.name) diff --git a/src/go/types/testdata/examples/conversions.go2 b/src/go/types/testdata/examples/conversions.go2 new file mode 100644 index 0000000000..eb988ffed1 --- /dev/null +++ b/src/go/types/testdata/examples/conversions.go2 @@ -0,0 +1,144 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package conversions + +import "unsafe" + +// "x is assignable to T" +// - tested via assignability tests + +// "x's type and T have identical underlying types if tags are ignored" + +func _[X ~int, T ~int](x X) T { return T(x) } +func _[X struct{f int "foo"}, T struct{f int "bar"}](x X) T { return T(x) } + +type Foo struct{f int "foo"} +type Bar struct{f int "bar"} +type Far struct{f float64 } + +func _[X Foo, T Bar](x X) T { return T(x) } +func _[X Foo|Bar, T Bar](x X) T { return T(x) } +func _[X Foo, T Foo|Bar](x X) T { return T(x) } +func _[X Foo, T Far](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by Foo\) to T.*cannot convert Foo \(in X\) to Far \(in T\) */ ) } + +// "x's type and T are unnamed pointer types and their pointer base types +// have identical underlying types if tags are ignored" + +func _[X ~*Foo, T ~*Bar](x X) T { return T(x) } +func _[X ~*Foo|~*Bar, T ~*Bar](x X) T { return T(x) } +func _[X ~*Foo, T ~*Foo|~*Bar](x X) T { return T(x) } +func _[X ~*Foo, T ~*Far](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by ~\*Foo\) to T.*cannot convert \*Foo \(in X\) to \*Far \(in T\) */ ) } + +// Verify that the defined types in constraints are considered for the rule above. + +type ( + B int + C int + X0 *B + T0 *C +) + +func _(x X0) T0 { return T0(x /* ERROR cannot convert */ ) } // non-generic reference +func _[X X0, T T0](x X) T { return T(x /* ERROR cannot convert */ ) } +func _[T T0](x X0) T { return T(x /* ERROR cannot convert */ ) } +func _[X X0](x X) T0 { return T0(x /* ERROR cannot convert */ ) } + +// "x's type and T are both integer or floating point types" + +func _[X Integer, T Integer](x X) T { return T(x) } +func _[X Unsigned, T Integer](x X) T { return T(x) } +func _[X Float, T Integer](x X) T { return T(x) } + +func _[X Integer, T Unsigned](x X) T { return T(x) } +func _[X Unsigned, T Unsigned](x X) T { return T(x) } +func _[X Float, T Unsigned](x X) T { return T(x) } + +func _[X Integer, T Float](x X) T { return T(x) } +func _[X Unsigned, T Float](x X) T { return T(x) } +func _[X Float, T Float](x X) T { return T(x) } + +func _[X, T Integer|Unsigned|Float](x X) T { return T(x) } +func _[X, T Integer|~string](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by Integer\|~string\) to T.*cannot convert string \(in X\) to int \(in T\) */ ) } + +// "x's type and T are both complex types" + +func _[X, T Complex](x X) T { return T(x) } +func _[X, T Float|Complex](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by Float\|Complex\) to T.*cannot convert float32 \(in X\) to complex64 \(in T\) */ ) } + +// "x is an integer or a slice of bytes or runes and T is a string type" + +type myInt int +type myString string + +func _[T ~string](x int) T { return T(x) } +func _[T ~string](x myInt) T { return T(x) } +func _[X Integer](x X) string { return string(x) } +func _[X Integer](x X) myString { return myString(x) } +func _[X Integer](x X) *string { return (*string)(x /* ERROR cannot convert x \(variable of type X constrained by Integer\) to \*string.*cannot convert int \(in X\) to \*string */ ) } + +func _[T ~string](x []byte) T { return T(x) } +func _[T ~string](x []rune) T { return T(x) } +func _[X ~[]byte, T ~string](x X) T { return T(x) } +func _[X ~[]rune, T ~string](x X) T { return T(x) } +func _[X Integer|~[]byte|~[]rune, T ~string](x X) T { return T(x) } +func _[X Integer|~[]byte|~[]rune, T ~*string](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by Integer\|~\[\]byte\|~\[\]rune\) to T.*cannot convert int \(in X\) to \*string \(in T\) */ ) } + +// "x is a string and T is a slice of bytes or runes" + +func _[T ~[]byte](x string) T { return T(x) } +func _[T ~[]rune](x string) T { return T(x) } +func _[T ~[]rune](x *string) T { return T(x /* ERROR cannot convert x \(variable of type \*string\) to T.*cannot convert \*string to \[\]rune \(in T\) */ ) } + +func _[X ~string, T ~[]byte](x X) T { return T(x) } +func _[X ~string, T ~[]rune](x X) T { return T(x) } +func _[X ~string, T ~[]byte|~[]rune](x X) T { return T(x) } +func _[X ~*string, T ~[]byte|~[]rune](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by ~\*string\) to T.*cannot convert \*string \(in X\) to \[\]byte \(in T\) */ ) } + +// package unsafe: +// "any pointer or value of underlying type uintptr can be converted into a unsafe.Pointer" + +type myUintptr uintptr + +func _[X ~uintptr](x X) unsafe.Pointer { return unsafe.Pointer(x) } +func _[T unsafe.Pointer](x myUintptr) T { return T(x) } +func _[T unsafe.Pointer](x int64) T { return T(x /* ERROR cannot convert x \(variable of type int64\) to T.*cannot convert int64 to unsafe\.Pointer \(in T\) */ ) } + +// "and vice versa" + +func _[T ~uintptr](x unsafe.Pointer) T { return T(x) } +func _[X unsafe.Pointer](x X) uintptr { return uintptr(x) } +func _[X unsafe.Pointer](x X) myUintptr { return myUintptr(x) } +func _[X unsafe.Pointer](x X) int64 { return int64(x /* ERROR cannot convert x \(variable of type X constrained by unsafe\.Pointer\) to int64.*cannot convert unsafe\.Pointer \(in X\) to int64 */ ) } + +// "x is a slice, T is a pointer-to-array type, +// and the slice and array types have identical element types." + +func _[X ~[]E, T ~*[10]E, E any](x X) T { return T(x) } +func _[X ~[]E, T ~[10]E, E any](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by ~\[\]E\) to T.*cannot convert \[\]E \(in X\) to \[10\]E \(in T\) */ ) } + +// ---------------------------------------------------------------------------- +// The following declarations can be replaced by the exported types of the +// constraints package once all builders support importing interfaces with +// type constraints. + +type Signed interface { + ~int | ~int8 | ~int16 | ~int32 | ~int64 +} + +type Unsigned interface { + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr +} + +type Integer interface { + Signed | Unsigned +} + +type Float interface { + ~float32 | ~float64 +} + +type Complex interface { + ~complex64 | ~complex128 +} -- GitLab From 61536ec03063b4951163bd09609c86d82631fa27 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Thu, 14 Oct 2021 13:02:01 -0700 Subject: [PATCH 1797/2500] debug/macho: fail on invalid dynamic symbol table command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fail out when loading a file that contains a dynamic symbol table command that indicates a larger number of symbols than exist in the loaded symbol table. Thanks to Burak Çarıkçı - Yunus Yıldırım (CT-Zer0 Crypttech) for reporting this issue. Fixes #48990 Fixes CVE-2021-41771 Change-Id: Ic3d6e6529241afcc959544b326b21b663262bad5 Reviewed-on: https://go-review.googlesource.com/c/go/+/355990 Reviewed-by: Julie Qiu Reviewed-by: Katie Hockman Reviewed-by: Emmanuel Odeke Run-TryBot: Roland Shoemaker TryBot-Result: Go Bot Trust: Katie Hockman --- src/debug/macho/file.go | 9 +++++++++ src/debug/macho/file_test.go | 7 +++++++ .../testdata/gcc-amd64-darwin-exec-with-bad-dysym.base64 | 1 + 3 files changed, 17 insertions(+) create mode 100644 src/debug/macho/testdata/gcc-amd64-darwin-exec-with-bad-dysym.base64 diff --git a/src/debug/macho/file.go b/src/debug/macho/file.go index 085b0c8219..73cfce3c76 100644 --- a/src/debug/macho/file.go +++ b/src/debug/macho/file.go @@ -345,6 +345,15 @@ func NewFile(r io.ReaderAt) (*File, error) { if err := binary.Read(b, bo, &hdr); err != nil { return nil, err } + if hdr.Iundefsym > uint32(len(f.Symtab.Syms)) { + return nil, &FormatError{offset, fmt.Sprintf( + "undefined symbols index in dynamic symbol table command is greater than symbol table length (%d > %d)", + hdr.Iundefsym, len(f.Symtab.Syms)), nil} + } else if hdr.Iundefsym+hdr.Nundefsym > uint32(len(f.Symtab.Syms)) { + return nil, &FormatError{offset, fmt.Sprintf( + "number of undefined symbols after index in dynamic symbol table command is greater than symbol table length (%d > %d)", + hdr.Iundefsym+hdr.Nundefsym, len(f.Symtab.Syms)), nil} + } dat := make([]byte, hdr.Nindirectsyms*4) if _, err := r.ReadAt(dat, int64(hdr.Indirectsymoff)); err != nil { return nil, err diff --git a/src/debug/macho/file_test.go b/src/debug/macho/file_test.go index 03915c86e2..9beeb80dd2 100644 --- a/src/debug/macho/file_test.go +++ b/src/debug/macho/file_test.go @@ -416,3 +416,10 @@ func TestTypeString(t *testing.T) { t.Errorf("got %v, want %v", TypeExec.GoString(), "macho.Exec") } } + +func TestOpenBadDysymCmd(t *testing.T) { + _, err := openObscured("testdata/gcc-amd64-darwin-exec-with-bad-dysym.base64") + if err == nil { + t.Fatal("openObscured did not fail when opening a file with an invalid dynamic symbol table command") + } +} diff --git a/src/debug/macho/testdata/gcc-amd64-darwin-exec-with-bad-dysym.base64 b/src/debug/macho/testdata/gcc-amd64-darwin-exec-with-bad-dysym.base64 new file mode 100644 index 0000000000..8e0436639c --- /dev/null +++ b/src/debug/macho/testdata/gcc-amd64-darwin-exec-with-bad-dysym.base64 @@ -0,0 +1 @@ +z/rt/gcAAAEDAACAAgAAAAsAAABoBQAAhQAAAAAAAAAZAAAASAAAAF9fUEFHRVpFUk8AAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAA2AEAAF9fVEVYVAAAAAAAAAAAAAAAAAAAAQAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAcAAAAFAAAABQAAAAAAAABfX3RleHQAAAAAAAAAAAAAX19URVhUAAAAAAAAAAAAABQPAAABAAAAbQAAAAAAAAAUDwAAAgAAAAAAAAAAAAAAAAQAgAAAAAAAAAAAAAAAAF9fc3ltYm9sX3N0dWIxAABfX1RFWFQAAAAAAAAAAAAAgQ8AAAEAAAAMAAAAAAAAAIEPAAAAAAAAAAAAAAAAAAAIBACAAAAAAAYAAAAAAAAAX19zdHViX2hlbHBlcgAAAF9fVEVYVAAAAAAAAAAAAACQDwAAAQAAABgAAAAAAAAAkA8AAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABfX2NzdHJpbmcAAAAAAAAAX19URVhUAAAAAAAAAAAAAKgPAAABAAAADQAAAAAAAACoDwAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAF9fZWhfZnJhbWUAAAAAAABfX1RFWFQAAAAAAAAAAAAAuA8AAAEAAABIAAAAAAAAALgPAAADAAAAAAAAAAAAAAALAABgAAAAAAAAAAAAAAAAGQAAADgBAABfX0RBVEEAAAAAAAAAAAAAABAAAAEAAAAAEAAAAAAAAAAQAAAAAAAAABAAAAAAAAAHAAAAAwAAAAMAAAAAAAAAX19kYXRhAAAAAAAAAAAAAF9fREFUQQAAAAAAAAAAAAAAEAAAAQAAABwAAAAAAAAAABAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABfX2R5bGQAAAAAAAAAAAAAX19EQVRBAAAAAAAAAAAAACAQAAABAAAAOAAAAAAAAAAgEAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF9fbGFfc3ltYm9sX3B0cgBfX0RBVEEAAAAAAAAAAAAAWBAAAAEAAAAQAAAAAAAAAFgQAAACAAAAAAAAAAAAAAAHAAAAAgAAAAAAAAAAAAAAGQAAAEgAAABfX0xJTktFRElUAAAAAAAAACAAAAEAAAAAEAAAAAAAAAAgAAAAAAAAQAEAAAAAAAAHAAAAAQAAAAAAAAAAAAAAAgAAABgAAAAAIAAACwAAAMAgAACAAAAACwAAAFAAAAAAAAAAAgAAAAIAAAAHAAAACQAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwIAAABAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAIAAAAAwAAAAvdXNyL2xpYi9keWxkAAAAAAAAABsAAAAYAAAAOyS4cg5FdtQoqu6JsMEhXQUAAAC4AAAABAAAACoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQPAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAOAAAABgAAAACAAAAAAABAAAAAQAvdXNyL2xpYi9saWJnY2Nfcy4xLmR5bGliAAAAAAAAAAwAAAA4AAAAGAAAAAIAAAAEAW8AAAABAC91c3IvbGliL2xpYlN5c3RlbS5CLmR5bGliAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABqAEiJ5UiD5PBIi30ISI11EIn6g8IBweIDSAHySInR6wRIg8EISIM5AHX2SIPBCOgiAAAAicfoMgAAAPRBU0yNHafw//9BU/8lvwAAAA8fAP8lvgAAAFVIieVIjT0zAAAA6A0AAAC4AAAAAMnD/yXRAAAA/yXTAAAAAAAATI0dwQAAAOm0////TI0dvQAAAOmo////aGVsbG8sIHdvcmxkAAAAABQAAAAAAAAAAXpSAAF4EAEQDAcIkAEAACwAAAAcAAAAkv////////8XAAAAAAAAAAAEAQAAAA4QhgIEAwAAAA0GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABDAX/9/AAAIEMBf/38AAAAAAAABAAAAGBAAAAEAAAAQEAAAAQAAAAgQAAABAAAAABAAAAEAAACQDwAAAQAAAJwPAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAHgEAAFAPAAABAAAAGwAAAB4BAABkDwAAAQAAAC4AAAAPBgAAGBAAAAEAAAA2AAAADwYAABAQAAABAAAAPgAAAA8GAAAAEAAAAQAAAEoAAAADABAAAAAAAAEAAABeAAAADwYAAAgQAAABAAAAZwAAAA8BAABqDwAAAQAAAG0AAAAPAQAAFA8AAAEAAABzAAAAAQABAgAAAAAAAAAAeQAAAAEAAQIAAAAAAAAAAAkAAAAKAAAACQAAAAoAAAAgAGR5bGRfc3R1Yl9iaW5kaW5nX2hlbHBlcgBfX2R5bGRfZnVuY19sb29rdXAAX05YQXJnYwBfTlhBcmd2AF9fX3Byb2duYW1lAF9fbWhfZXhlY3V0ZV9oZWFkZXIAX2Vudmlyb24AX21haW4Ac3RhcnQAX2V4aXQAX3B1dHMAAA== \ No newline at end of file -- GitLab From 6f0185bf38a679f468b6a4209f15188a11662eb5 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 27 Oct 2021 12:17:21 -0400 Subject: [PATCH 1798/2500] go/types: factor out slice elem computation for copy built-in This is a port of CL 357413 to go/types. Some test constraints are also updated to remove 'interface', to coincide with the corresponding test data file in types2. Change-Id: I5248190501c2e4381eb7625f8d4fb269301d6e16 Reviewed-on: https://go-review.googlesource.com/c/go/+/359138 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/builtins.go | 59 ++++++++++++++++++------ src/go/types/testdata/check/builtins.go2 | 18 +++++--- 2 files changed, 56 insertions(+), 21 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 3e2c994b09..29a8339f3e 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -330,33 +330,22 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b case _Copy: // copy(x, y []T) int - var dst Type - if t := asSlice(x.typ); t != nil { - dst = t.elem - } + dst, _ := singleUnder(x.typ).(*Slice) var y operand arg(&y, 1) if y.mode == invalid { return } - var src Type - switch t := optype(y.typ).(type) { - case *Basic: - if isString(y.typ) { - src = universeByte - } - case *Slice: - src = t.elem - } + src, _ := singleUnderString(y.typ).(*Slice) if dst == nil || src == nil { check.invalidArg(x, _InvalidCopy, "copy expects slice arguments; found %s and %s", x, &y) return } - if !Identical(dst, src) { - check.invalidArg(x, _InvalidCopy, "arguments to copy %s and %s have different element types %s and %s", x, &y, dst, src) + if !Identical(dst.elem, src.elem) { + check.errorf(x, _InvalidCopy, "arguments to copy %s and %s have different element types %s and %s", x, &y, dst.elem, src.elem) return } @@ -783,6 +772,46 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b return true } +// If typ is a type parameter, single under returns the single underlying +// type of all types in the corresponding type constraint if it exists, or +// nil if it doesn't exist. If typ is not a type parameter, singleUnder +// just returns the underlying type. +func singleUnder(typ Type) Type { + var su Type + if underIs(typ, func(u Type) bool { + if su != nil && !Identical(su, u) { + return false + } + // su == nil || Identical(su, u) + su = u + return true + }) { + return su + } + return nil +} + +// singleUnderString is like singleUnder but also considers []byte and +// string as "identical". In this case, if successful, the result is always +// []byte. +func singleUnderString(typ Type) Type { + var su Type + if underIs(typ, func(u Type) bool { + if isString(u) { + u = NewSlice(universeByte) + } + if su != nil && !Identical(su, u) { + return false + } + // su == nil || Identical(su, u) + su = u + return true + }) { + return su + } + return nil +} + // hasVarSize reports if the size of type t is variable due to type parameters. func hasVarSize(t Type) bool { switch t := under(t).(type) { diff --git a/src/go/types/testdata/check/builtins.go2 b/src/go/types/testdata/check/builtins.go2 index fb912a1918..f9b6ec7926 100644 --- a/src/go/types/testdata/check/builtins.go2 +++ b/src/go/types/testdata/check/builtins.go2 @@ -51,7 +51,7 @@ func _[T any](x, y T) { copy(x /* ERROR copy expects slice arguments */ , y) } -func _[T interface{~[]byte}](x, y T) { +func _[T ~[]byte](x, y T) { copy(x, y) copy(x, "foo") copy("foo" /* ERROR expects slice arguments */ , y) @@ -66,20 +66,26 @@ func _[T interface{~[]byte}](x, y T) { copy(y /* ERROR different element types */ , x3) } -func _[T interface{~[]E}, E any](x T, y []E) { +func _[T ~[]E, E any](x T, y []E) { copy(x, y) copy(x /* ERROR different element types */ , "foo") } -func _[T interface{~string}](x []byte, y T) { +func _[T ~string](x []byte, y T) { copy(x, y) copy(y /* ERROR expects slice arguments */ , x) } -func _[T interface{~[]byte|~string}](x T, y []byte) { +func _[T ~[]byte|~string](x T, y []byte) { copy(x /* ERROR expects slice arguments */ , y) - // TODO(gri) should this be valid? - copy(y /* ERROR expects slice arguments */ , x) + copy(y, x) +} + +type L0 []int +type L1 []int + +func _[T L0 | L1](x, y T) { + copy(x, y) } // delete -- GitLab From 5fce1d96137e1079c393c94febfac49d1e2979b0 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Wed, 27 Oct 2021 16:07:40 -0400 Subject: [PATCH 1799/2500] runtime: disable TestSegv panic check on darwin, illumos, solaris CL 339990 made this test more strict, exposing pre-existing issues on these OSes. Skip for now until they can be resolved. Updates #49182 Change-Id: I3ac400dcd21b801bf4ab4eeb630e23b5c66ba563 Reviewed-on: https://go-review.googlesource.com/c/go/+/359254 Trust: Michael Pratt Run-TryBot: Michael Pratt Reviewed-by: Cherry Mui Reviewed-by: Bryan C. Mills TryBot-Result: Go Bot --- src/runtime/crash_cgo_test.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go index 0ccfe8580a..8485b6a1a5 100644 --- a/src/runtime/crash_cgo_test.go +++ b/src/runtime/crash_cgo_test.go @@ -625,10 +625,18 @@ func TestSegv(t *testing.T) { if !strings.Contains(got, want) { t.Errorf("did not see %q in output", want) } + // No runtime errors like "runtime: unknown pc". - nowant := "runtime: " - if strings.Contains(got, nowant) { - t.Errorf("unexpectedly saw %q in output", want) + switch runtime.GOOS { + case "darwin", "illumos", "solaris": + // TODO(golang.org/issue/49182): Skip, runtime + // throws while attempting to generate + // traceback. + default: + nowant := "runtime: " + if strings.Contains(got, nowant) { + t.Errorf("unexpectedly saw %q in output", nowant) + } } }) } -- GitLab From 6bd0e7fa8a2cb5c8de9d4566c900233715d8cf0e Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Wed, 27 Oct 2021 16:09:59 -0400 Subject: [PATCH 1800/2500] runtime: fix backward error message This was added in CL 339990. Change-Id: I4b0f97bf1a3926e37a42f77e149dcab3b7b75a63 Reviewed-on: https://go-review.googlesource.com/c/go/+/359255 Trust: Michael Pratt Run-TryBot: Michael Pratt TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/crash_cgo_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go index 8485b6a1a5..c0d4569462 100644 --- a/src/runtime/crash_cgo_test.go +++ b/src/runtime/crash_cgo_test.go @@ -534,7 +534,7 @@ func TestCgoTracebackSigpanic(t *testing.T) { // No runtime errors like "runtime: unexpected return pc". nowant := "runtime: " if strings.Contains(got, nowant) { - t.Errorf("unexpectedly saw %q in output", want) + t.Errorf("unexpectedly saw %q in output", nowant) } } -- GitLab From 31249688487ca3a60f856ad082d4e84c4d5f79fb Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 29 Jun 2020 14:29:09 -0400 Subject: [PATCH 1801/2500] cmd/fix: add buildtag fix Now that Go 1.17 is out and Go 1.15 is unsupported, removing // +build lines can be done safely: in the worst case, if code is compiled using Go 1.16 the toolchain will detect the presence of a //go:build without // +build and fail the build. (It will not silently choose the wrong files.) Note that +build lines will continue to work in Go sources forever. This just provides a mechanism for users who are done with Go 1.16 to remove them easily, by running "go fix". Also update for new generics AST. For #41184. Fixes #48978. Change-Id: I11a432c319e5abd05ad68dda9ccd7a7fdcc8bbb8 Reviewed-on: https://go-review.googlesource.com/c/go/+/240611 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/fix/buildtag.go | 51 ++++++++++++++++++++++++++++++++++ src/cmd/fix/buildtag_test.go | 34 +++++++++++++++++++++++ src/cmd/fix/fix.go | 9 ++++++ src/cmd/fix/main.go | 28 ++++++++++++++++++- src/cmd/fix/main_test.go | 23 +++++++++++---- src/cmd/go/alldocs.go | 8 ++++-- src/cmd/go/internal/fix/fix.go | 30 +++++++++++++++++--- 7 files changed, 171 insertions(+), 12 deletions(-) create mode 100644 src/cmd/fix/buildtag.go create mode 100644 src/cmd/fix/buildtag_test.go diff --git a/src/cmd/fix/buildtag.go b/src/cmd/fix/buildtag.go new file mode 100644 index 0000000000..5f4fbfef16 --- /dev/null +++ b/src/cmd/fix/buildtag.go @@ -0,0 +1,51 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "go/ast" + "strings" +) + +func init() { + register(buildtagFix) +} + +const buildtagGoVersionCutoff = 1_18 + +var buildtagFix = fix{ + name: "buildtag", + date: "2021-08-25", + f: buildtag, + desc: `Remove +build comments from modules using Go 1.18 or later`, +} + +func buildtag(f *ast.File) bool { + if goVersion < buildtagGoVersionCutoff { + return false + } + + // File is already gofmt-ed, so we know that if there are +build lines, + // they are in a comment group that starts with a //go:build line followed + // by a blank line. While we cannot delete comments from an AST and + // expect consistent output in general, this specific case - deleting only + // some lines from a comment block - does format correctly. + fixed := false + for _, g := range f.Comments { + sawGoBuild := false + for i, c := range g.List { + if strings.HasPrefix(c.Text, "//go:build ") { + sawGoBuild = true + } + if sawGoBuild && strings.HasPrefix(c.Text, "// +build ") { + g.List = g.List[:i] + fixed = true + break + } + } + } + + return fixed +} diff --git a/src/cmd/fix/buildtag_test.go b/src/cmd/fix/buildtag_test.go new file mode 100644 index 0000000000..1c6efbe9e0 --- /dev/null +++ b/src/cmd/fix/buildtag_test.go @@ -0,0 +1,34 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func init() { + addTestCases(buildtagTests, buildtag) +} + +var buildtagTests = []testCase{ + { + Name: "buildtag.oldGo", + Version: 1_10, + In: `//go:build yes +// +build yes + +package main +`, + }, + { + Name: "buildtag.new", + Version: 1_99, + In: `//go:build yes +// +build yes + +package main +`, + Out: `//go:build yes + +package main +`, + }, +} diff --git a/src/cmd/fix/fix.go b/src/cmd/fix/fix.go index b49db37571..b9980c17b9 100644 --- a/src/cmd/fix/fix.go +++ b/src/cmd/fix/fix.go @@ -125,6 +125,9 @@ func walkBeforeAfter(x interface{}, before, after func(interface{})) { case *ast.IndexExpr: walkBeforeAfter(&n.X, before, after) walkBeforeAfter(&n.Index, before, after) + case *ast.IndexListExpr: + walkBeforeAfter(&n.X, before, after) + walkBeforeAfter(&n.Indices, before, after) case *ast.SliceExpr: walkBeforeAfter(&n.X, before, after) if n.Low != nil { @@ -156,6 +159,9 @@ func walkBeforeAfter(x interface{}, before, after func(interface{})) { case *ast.StructType: walkBeforeAfter(&n.Fields, before, after) case *ast.FuncType: + if n.TypeParams != nil { + walkBeforeAfter(&n.TypeParams, before, after) + } walkBeforeAfter(&n.Params, before, after) if n.Results != nil { walkBeforeAfter(&n.Results, before, after) @@ -231,6 +237,9 @@ func walkBeforeAfter(x interface{}, before, after func(interface{})) { walkBeforeAfter(&n.Values, before, after) walkBeforeAfter(&n.Names, before, after) case *ast.TypeSpec: + if n.TypeParams != nil { + walkBeforeAfter(&n.TypeParams, before, after) + } walkBeforeAfter(&n.Type, before, after) case *ast.BadDecl: diff --git a/src/cmd/fix/main.go b/src/cmd/fix/main.go index d055929aac..b5f7b901d6 100644 --- a/src/cmd/fix/main.go +++ b/src/cmd/fix/main.go @@ -18,6 +18,7 @@ import ( "os" "path/filepath" "sort" + "strconv" "strings" "cmd/internal/diff" @@ -36,7 +37,12 @@ var forceRewrites = flag.String("force", "", var allowed, force map[string]bool -var doDiff = flag.Bool("diff", false, "display diffs instead of rewriting files") +var ( + doDiff = flag.Bool("diff", false, "display diffs instead of rewriting files") + goVersionStr = flag.String("go", "", "go language version for files") + + goVersion int // 115 for go1.15 +) // enable for debugging fix failures const debug = false // display incorrectly reformatted source and exit @@ -63,6 +69,26 @@ func main() { flag.Usage = usage flag.Parse() + if *goVersionStr != "" { + if !strings.HasPrefix(*goVersionStr, "go") { + report(fmt.Errorf("invalid -go=%s", *goVersionStr)) + os.Exit(exitCode) + } + majorStr := (*goVersionStr)[len("go"):] + minorStr := "0" + if i := strings.Index(majorStr, "."); i >= 0 { + majorStr, minorStr = majorStr[:i], majorStr[i+len("."):] + } + major, err1 := strconv.Atoi(majorStr) + minor, err2 := strconv.Atoi(minorStr) + if err1 != nil || err2 != nil || major < 0 || major >= 100 || minor < 0 || minor >= 100 { + report(fmt.Errorf("invalid -go=%s", *goVersionStr)) + os.Exit(exitCode) + } + + goVersion = major*100 + minor + } + sort.Sort(byDate(fixes)) if *allowedRewrites != "" { diff --git a/src/cmd/fix/main_test.go b/src/cmd/fix/main_test.go index af16bcaa31..1baa95c545 100644 --- a/src/cmd/fix/main_test.go +++ b/src/cmd/fix/main_test.go @@ -14,10 +14,11 @@ import ( ) type testCase struct { - Name string - Fn func(*ast.File) bool - In string - Out string + Name string + Fn func(*ast.File) bool + Version int + In string + Out string } var testCases []testCase @@ -78,7 +79,16 @@ func TestRewrite(t *testing.T) { for _, tt := range testCases { tt := tt t.Run(tt.Name, func(t *testing.T) { - t.Parallel() + if tt.Version == 0 { + t.Parallel() + } else { + old := goVersion + goVersion = tt.Version + defer func() { + goVersion = old + }() + } + // Apply fix: should get tt.Out. out, fixed, ok := parseFixPrint(t, tt.Fn, tt.Name, tt.In, true) if !ok { @@ -91,6 +101,9 @@ func TestRewrite(t *testing.T) { return } + if tt.Out == "" { + tt.Out = tt.In + } if out != tt.Out { t.Errorf("incorrect output.\n") if !strings.HasPrefix(tt.Name, "testdata/") { diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 685ccac826..537f800944 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -464,14 +464,18 @@ // // Usage: // -// go fix [packages] +// go fix [-fix list] [packages] // // Fix runs the Go fix command on the packages named by the import paths. // +// The -fix flag sets a comma-separated list of fixes to run. +// The default is all known fixes. +// (Its value is passed to 'go tool fix -r'.) +// // For more about fix, see 'go doc cmd/fix'. // For more about specifying packages, see 'go help packages'. // -// To run fix with specific options, run 'go tool fix'. +// To run fix with other options, run 'go tool fix'. // // See also: go fmt, go vet. // diff --git a/src/cmd/go/internal/fix/fix.go b/src/cmd/go/internal/fix/fix.go index 988d45e71c..d8ba353de6 100644 --- a/src/cmd/go/internal/fix/fix.go +++ b/src/cmd/go/internal/fix/fix.go @@ -11,27 +11,39 @@ import ( "cmd/go/internal/load" "cmd/go/internal/modload" "cmd/go/internal/str" + "cmd/go/internal/work" "context" "fmt" + "go/build" "os" ) var CmdFix = &base.Command{ - Run: runFix, - UsageLine: "go fix [packages]", + UsageLine: "go fix [-fix list] [packages]", Short: "update packages to use new APIs", Long: ` Fix runs the Go fix command on the packages named by the import paths. +The -fix flag sets a comma-separated list of fixes to run. +The default is all known fixes. +(Its value is passed to 'go tool fix -r'.) + For more about fix, see 'go doc cmd/fix'. For more about specifying packages, see 'go help packages'. -To run fix with specific options, run 'go tool fix'. +To run fix with other options, run 'go tool fix'. See also: go fmt, go vet. `, } +var fixes = CmdFix.Flag.String("fix", "", "comma-separated list of fixes to apply") + +func init() { + work.AddBuildFlags(CmdFix, work.DefaultBuildFlags) + CmdFix.Run = runFix // fix cycle +} + func runFix(ctx context.Context, cmd *base.Command, args []string) { pkgs := load.PackagesAndErrors(ctx, load.PackageOpts{}, args) w := 0 @@ -58,6 +70,16 @@ func runFix(ctx context.Context, cmd *base.Command, args []string) { // the command only applies to this package, // not to packages in subdirectories. files := base.RelPaths(pkg.InternalAllGoFiles()) - base.Run(str.StringList(cfg.BuildToolexec, base.Tool("fix"), files)) + goVersion := "" + if pkg.Module != nil { + goVersion = "go" + pkg.Module.GoVersion + } else if pkg.Standard { + goVersion = build.Default.ReleaseTags[len(build.Default.ReleaseTags)-1] + } + var fixArg []string + if *fixes != "" { + fixArg = []string{"-r=" + *fixes} + } + base.Run(str.StringList(cfg.BuildToolexec, base.Tool("fix"), "-go="+goVersion, fixArg, files)) } } -- GitLab From 266626211e40d1f2c3a34fa4cd2023f5310cbd7d Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Fri, 3 Sep 2021 21:07:22 +0000 Subject: [PATCH 1802/2500] net/http: guarantee that the Transport dial functions are respected in js/wasm The net/http package has a documented contract that if DialContext, DialDLSContext, Dial or DialTLS are specified in an instance of Transport, that they will be used to set up the connection. If they are not specified, then a reasonable fallback is made (e.g. using the net package). This is ordinarily true, except for when compiling for the js/wasm target, where the browser's Fetch API is preferred in all cases (except for when it is undefined/unavailable) and therefore the dial functions are all ignored. As a result, the http.Transport implementation under js/wasm doesn't meet that contract. This PR updates the RoundTrip behaviour of http.Transport so that if DialContext, DialTLSContext, Dial or DialTLS are specified, they are used as expected. The Fetch API will be used as a fallback if they are not specified. Fixes #27495 Change-Id: I88c6eb6ffdd077827b421d606f3e60ebdafd538f GitHub-Last-Rev: 948a0ed97ec4661f03cd346335f1d3d180f4c1ae GitHub-Pull-Request: golang/go#46923 Reviewed-on: https://go-review.googlesource.com/c/go/+/330852 Reviewed-by: Damien Neil Trust: Damien Neil Trust: Carlos Amedee Run-TryBot: Damien Neil TryBot-Result: Go Bot --- AUTHORS | 1 + CONTRIBUTORS | 1 + src/net/http/roundtrip_js.go | 12 ++++++++++-- src/net/http/transport.go | 4 ++-- src/net/http/transport_default_js.go | 17 +++++++++++++++++ src/net/http/transport_default_other.go | 17 +++++++++++++++++ 6 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 src/net/http/transport_default_js.go create mode 100644 src/net/http/transport_default_other.go diff --git a/AUTHORS b/AUTHORS index 8d8d83605e..ad907967b4 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1015,6 +1015,7 @@ Nathan Youngman Nathaniel Cook Naveen Kumar Sangi Neelesh Chandola +Neil Alexander Neil Lyons Netflix, Inc. Neuman Vong diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 74d4687373..706d630193 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -1901,6 +1901,7 @@ Naveen Kumar Sangi Neeilan Selvalingam Neelesh Chandola Nehal J Wani +Neil Alexander Neil Lyons Neuman Vong Neven Sajko diff --git a/src/net/http/roundtrip_js.go b/src/net/http/roundtrip_js.go index 362dbcbdde..4a8595ebcf 100644 --- a/src/net/http/roundtrip_js.go +++ b/src/net/http/roundtrip_js.go @@ -41,11 +41,19 @@ const jsFetchCreds = "js.fetch:credentials" // Reference: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters const jsFetchRedirect = "js.fetch:redirect" -var useFakeNetwork = js.Global().Get("fetch").IsUndefined() +// jsFetchMissing will be true if the Fetch API is not present in +// the browser globals. +var jsFetchMissing = js.Global().Get("fetch").IsUndefined() // RoundTrip implements the RoundTripper interface using the WHATWG Fetch API. func (t *Transport) RoundTrip(req *Request) (*Response, error) { - if useFakeNetwork { + // The Transport has a documented contract that states that if the DialContext or + // DialTLSContext functions are set, they will be used to set up the connections. + // If they aren't set then the documented contract is to use Dial or DialTLS, even + // though they are deprecated. Therefore, if any of these are set, we should obey + // the contract and dial using the regular round-trip instead. Otherwise, we'll try + // to fall back on the Fetch API, unless it's not available. + if t.Dial != nil || t.DialContext != nil || t.DialTLS != nil || t.DialTLSContext != nil || jsFetchMissing { return t.roundTrip(req) } diff --git a/src/net/http/transport.go b/src/net/http/transport.go index 17f0047b59..0e60992e6c 100644 --- a/src/net/http/transport.go +++ b/src/net/http/transport.go @@ -42,10 +42,10 @@ import ( // $no_proxy) environment variables. var DefaultTransport RoundTripper = &Transport{ Proxy: ProxyFromEnvironment, - DialContext: (&net.Dialer{ + DialContext: defaultTransportDialContext(&net.Dialer{ Timeout: 30 * time.Second, KeepAlive: 30 * time.Second, - }).DialContext, + }), ForceAttemptHTTP2: true, MaxIdleConns: 100, IdleConnTimeout: 90 * time.Second, diff --git a/src/net/http/transport_default_js.go b/src/net/http/transport_default_js.go new file mode 100644 index 0000000000..c07d35ef86 --- /dev/null +++ b/src/net/http/transport_default_js.go @@ -0,0 +1,17 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build js && wasm +// +build js,wasm + +package http + +import ( + "context" + "net" +) + +func defaultTransportDialContext(dialer *net.Dialer) func(context.Context, string, string) (net.Conn, error) { + return nil +} diff --git a/src/net/http/transport_default_other.go b/src/net/http/transport_default_other.go new file mode 100644 index 0000000000..8a2f1cc42b --- /dev/null +++ b/src/net/http/transport_default_other.go @@ -0,0 +1,17 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !(js && wasm) +// +build !js !wasm + +package http + +import ( + "context" + "net" +) + +func defaultTransportDialContext(dialer *net.Dialer) func(context.Context, string, string) (net.Conn, error) { + return dialer.DialContext +} -- GitLab From 2bc8ed8e9c5d8ae303b42bbd8c65f2c5dc38352a Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Tue, 26 Oct 2021 16:18:52 -0400 Subject: [PATCH 1803/2500] runtime: normalize sigprof traceback flags Each gentraceback call uses a different set of flags. Combine these into a common variable, only adjusted as necessary. The effective changes here are: * cgo traceback now has _TraceJumpStack. This is a no-op since it already passes curg. * libcall traceback now has _TraceJumpStack. This is a behavior change and will allow following stack transitions if a libcall is performed on g0. * VDSO traceback drops _TraceTrap. vdsoPC is a return address, so _TraceTrap was not necessary. Change-Id: I351b3cb8dc77df7466795d5fbf2bd8f30bba2d37 Reviewed-on: https://go-review.googlesource.com/c/go/+/358900 Trust: Michael Pratt Run-TryBot: Michael Pratt TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/proc.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 990637e21a..bd7dacd440 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -4645,6 +4645,7 @@ func sigprof(pc, sp, lr uintptr, gp *g, mp *m) { getg().m.mallocing++ var stk [maxCPUProfStack]uintptr + flags := uint(_TraceJumpStack) n := 0 if mp.ncgo > 0 && mp.curg != nil && mp.curg.syscallpc != 0 && mp.curg.syscallsp != 0 { cgoOff := 0 @@ -4662,12 +4663,12 @@ func sigprof(pc, sp, lr uintptr, gp *g, mp *m) { } // Collect Go stack that leads to the cgo call. - n = gentraceback(mp.curg.syscallpc, mp.curg.syscallsp, 0, mp.curg, 0, &stk[cgoOff], len(stk)-cgoOff, nil, nil, 0) + n = gentraceback(mp.curg.syscallpc, mp.curg.syscallsp, 0, mp.curg, 0, &stk[cgoOff], len(stk)-cgoOff, nil, nil, flags) if n > 0 { n += cgoOff } } else { - n = gentraceback(pc, sp, lr, gp, 0, &stk[0], len(stk), nil, nil, _TraceTrap|_TraceJumpStack) + n = gentraceback(pc, sp, lr, gp, 0, &stk[0], len(stk), nil, nil, _TraceTrap|flags) } if n <= 0 { @@ -4677,10 +4678,10 @@ func sigprof(pc, sp, lr uintptr, gp *g, mp *m) { if usesLibcall() && mp.libcallg != 0 && mp.libcallpc != 0 && mp.libcallsp != 0 { // Libcall, i.e. runtime syscall on windows. // Collect Go stack that leads to the call. - n = gentraceback(mp.libcallpc, mp.libcallsp, 0, mp.libcallg.ptr(), 0, &stk[0], len(stk), nil, nil, 0) + n = gentraceback(mp.libcallpc, mp.libcallsp, 0, mp.libcallg.ptr(), 0, &stk[0], len(stk), nil, nil, flags) } if n == 0 && mp != nil && mp.vdsoSP != 0 { - n = gentraceback(mp.vdsoPC, mp.vdsoSP, 0, gp, 0, &stk[0], len(stk), nil, nil, _TraceTrap|_TraceJumpStack) + n = gentraceback(mp.vdsoPC, mp.vdsoSP, 0, gp, 0, &stk[0], len(stk), nil, nil, flags) } if n == 0 { // If all of the above has failed, account it against abstract "System" or "GC". -- GitLab From ed475fe53ba41c0c15b11565f8b9d00165345bc2 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 27 Oct 2021 22:59:55 -0400 Subject: [PATCH 1804/2500] cmd/go: update for //go:build lines cmd/go has its own //go:build evaluator, which is needed for patterns like 'all'. The code is a modified copy of some unexported routines from the go/build package. Update it by copying those again and re-modifying them. The modifications are primarily the new func eval and also ignoring errors. This CL will need to be backported to Go 1.17, or else Go 1.17 will break when faced with certain //go:build-only repos during 'go list all' or 'go mod tidy'. For #41184. Fixes #49198. Change-Id: Ie0fe3caa8d49004935ecd76d7977f767fe50e317 Reviewed-on: https://go-review.googlesource.com/c/go/+/359355 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/imports/build.go | 216 ++++++++++++------ .../go/testdata/script/list_all_gobuild.txt | 41 ++++ 2 files changed, 192 insertions(+), 65 deletions(-) create mode 100644 src/cmd/go/testdata/script/list_all_gobuild.txt diff --git a/src/cmd/go/internal/imports/build.go b/src/cmd/go/internal/imports/build.go index 50aeabc578..ff6bea6777 100644 --- a/src/cmd/go/internal/imports/build.go +++ b/src/cmd/go/internal/imports/build.go @@ -2,17 +2,51 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Copied from Go distribution src/go/build/build.go, syslist.go +// Copied from Go distribution src/go/build/build.go, syslist.go. +// That package does not export the ability to process raw file data, +// although we could fake it with an appropriate build.Context +// and a lot of unwrapping. +// More importantly, that package does not implement the tags["*"] +// special case, in which both tag and !tag are considered to be true +// for essentially all tags (except "ignore"). +// +// If we added this API to go/build directly, we wouldn't need this +// file anymore, but this API is not terribly general-purpose and we +// don't really want to commit to any public form of it, nor do we +// want to move the core parts of go/build into a top-level internal package. +// These details change very infrequently, so the copy is fine. package imports import ( "bytes" + "errors" + "fmt" + "go/build/constraint" "strings" "unicode" ) -var slashslash = []byte("//") +var ( + bSlashSlash = []byte("//") + bStarSlash = []byte("*/") + bSlashStar = []byte("/*") + bPlusBuild = []byte("+build") + + goBuildComment = []byte("//go:build") + + errGoBuildWithoutBuild = errors.New("//go:build comment without // +build comment") + errMultipleGoBuild = errors.New("multiple //go:build comments") +) + +func isGoBuildComment(line []byte) bool { + if !bytes.HasPrefix(line, goBuildComment) { + return false + } + line = bytes.TrimSpace(line) + rest := line[len(goBuildComment):] + return len(rest) == 0 || len(bytes.TrimSpace(rest)) < len(rest) +} // ShouldBuild reports whether it is okay to use this file, // The rule is that in the file's leading run of // comments @@ -34,10 +68,61 @@ var slashslash = []byte("//") // in any build. // func ShouldBuild(content []byte, tags map[string]bool) bool { - // Pass 1. Identify leading run of // comments and blank lines, + // Identify leading run of // comments and blank lines, // which must be followed by a blank line. + // Also identify any //go:build comments. + content, goBuild, _, err := parseFileHeader(content) + if err != nil { + return false + } + + // If //go:build line is present, it controls. + // Otherwise fall back to +build processing. + var shouldBuild bool + switch { + case goBuild != nil: + x, err := constraint.Parse(string(goBuild)) + if err != nil { + return false + } + shouldBuild = eval(x, tags, true) + + default: + shouldBuild = true + p := content + for len(p) > 0 { + line := p + if i := bytes.IndexByte(line, '\n'); i >= 0 { + line, p = line[:i], p[i+1:] + } else { + p = p[len(p):] + } + line = bytes.TrimSpace(line) + if !bytes.HasPrefix(line, bSlashSlash) || !bytes.Contains(line, bPlusBuild) { + continue + } + text := string(line) + if !constraint.IsPlusBuild(text) { + continue + } + if x, err := constraint.Parse(text); err == nil { + if !eval(x, tags, true) { + shouldBuild = false + } + } + } + } + + return shouldBuild +} + +func parseFileHeader(content []byte) (trimmed, goBuild []byte, sawBinaryOnly bool, err error) { end := 0 p := content + ended := false // found non-blank, non-// line, so stopped accepting // +build lines + inSlashStar := false // in /* */ comment + +Lines: for len(p) > 0 { line := p if i := bytes.IndexByte(line, '\n'); i >= 0 { @@ -46,78 +131,61 @@ func ShouldBuild(content []byte, tags map[string]bool) bool { p = p[len(p):] } line = bytes.TrimSpace(line) - if len(line) == 0 { // Blank line + if len(line) == 0 && !ended { // Blank line + // Remember position of most recent blank line. + // When we find the first non-blank, non-// line, + // this "end" position marks the latest file position + // where a // +build line can appear. + // (It must appear _before_ a blank line before the non-blank, non-// line. + // Yes, that's confusing, which is part of why we moved to //go:build lines.) + // Note that ended==false here means that inSlashStar==false, + // since seeing a /* would have set ended==true. end = len(content) - len(p) - continue + continue Lines } - if !bytes.HasPrefix(line, slashslash) { // Not comment line - break + if !bytes.HasPrefix(line, bSlashSlash) { // Not comment line + ended = true } - } - content = content[:end] - // Pass 2. Process each line in the run. - p = content - allok := true - for len(p) > 0 { - line := p - if i := bytes.IndexByte(line, '\n'); i >= 0 { - line, p = line[:i], p[i+1:] - } else { - p = p[len(p):] - } - line = bytes.TrimSpace(line) - if !bytes.HasPrefix(line, slashslash) { - continue + if !inSlashStar && isGoBuildComment(line) { + if goBuild != nil { + return nil, nil, false, errMultipleGoBuild + } + goBuild = line } - line = bytes.TrimSpace(line[len(slashslash):]) - if len(line) > 0 && line[0] == '+' { - // Looks like a comment +line. - f := strings.Fields(string(line)) - if f[0] == "+build" { - ok := false - for _, tok := range f[1:] { - if matchTags(tok, tags) { - ok = true - } - } - if !ok { - allok = false + + Comments: + for len(line) > 0 { + if inSlashStar { + if i := bytes.Index(line, bStarSlash); i >= 0 { + inSlashStar = false + line = bytes.TrimSpace(line[i+len(bStarSlash):]) + continue Comments } + continue Lines } + if bytes.HasPrefix(line, bSlashSlash) { + continue Lines + } + if bytes.HasPrefix(line, bSlashStar) { + inSlashStar = true + line = bytes.TrimSpace(line[len(bSlashStar):]) + continue Comments + } + // Found non-comment text. + break Lines } } - return allok -} - -// matchTags reports whether the name is one of: -// -// tag (if tags[tag] is true) -// !tag (if tags[tag] is false) -// a comma-separated list of any of these -// -func matchTags(name string, tags map[string]bool) bool { - if name == "" { - return false - } - if i := strings.Index(name, ","); i >= 0 { - // comma-separated list - ok1 := matchTags(name[:i], tags) - ok2 := matchTags(name[i+1:], tags) - return ok1 && ok2 - } - if strings.HasPrefix(name, "!!") { // bad syntax, reject always - return false - } - if strings.HasPrefix(name, "!") { // negation - return len(name) > 1 && matchTag(name[1:], tags, false) - } - return matchTag(name, tags, true) + return content[:end], goBuild, sawBinaryOnly, nil } -// matchTag reports whether the tag name is valid and satisfied by tags[name]==want. -func matchTag(name string, tags map[string]bool, want bool) bool { +// matchTag reports whether the tag name is valid and tags[name] is true. +// As a special case, if tags["*"] is true and name is not empty or ignore, +// then matchTag will return prefer instead of the actual answer, +// which allows the caller to pretend in that case that most tags are +// both true and false. +func matchTag(name string, tags map[string]bool, prefer bool) bool { // Tags must be letters, digits, underscores or dots. // Unlike in Go identifiers, all digits are fine (e.g., "386"). for _, c := range name { @@ -131,7 +199,7 @@ func matchTag(name string, tags map[string]bool, want bool) bool { // if we put * in the tags map then all tags // except "ignore" are considered both present and not // (so we return true no matter how 'want' is set). - return true + return prefer } have := tags[name] @@ -144,7 +212,25 @@ func matchTag(name string, tags map[string]bool, want bool) bool { if name == "darwin" { have = have || tags["ios"] } - return have == want + return have +} + +// eval is like +// x.Eval(func(tag string) bool { return matchTag(tag, tags) }) +// except that it implements the special case for tags["*"] meaning +// all tags are both true and false at the same time. +func eval(x constraint.Expr, tags map[string]bool, prefer bool) bool { + switch x := x.(type) { + case *constraint.TagExpr: + return matchTag(x.Tag, tags, prefer) + case *constraint.NotExpr: + return !eval(x.X, tags, !prefer) + case *constraint.AndExpr: + return eval(x.X, tags, prefer) && eval(x.Y, tags, prefer) + case *constraint.OrExpr: + return eval(x.X, tags, prefer) || eval(x.Y, tags, prefer) + } + panic(fmt.Sprintf("unexpected constraint expression %T", x)) } // MatchFile returns false if the name contains a $GOOS or $GOARCH diff --git a/src/cmd/go/testdata/script/list_all_gobuild.txt b/src/cmd/go/testdata/script/list_all_gobuild.txt new file mode 100644 index 0000000000..e0a47398bb --- /dev/null +++ b/src/cmd/go/testdata/script/list_all_gobuild.txt @@ -0,0 +1,41 @@ +# go list all should work with GOOS=linux because all packages build on Linux +env GOOS=linux +go list all + +# go list all should work with GOOS=darwin, but it used to fail because +# in the absence of //go:build support, p looked like it needed q +# (p_test.go was not properly excluded), and q was Linux-only. +# +# Also testing with r and s that +build lines keep working. +env GOOS=darwin +go list all + +-- go.mod -- +go 1.17 +module m + +-- p/p.go -- +package p + +-- p/p_test.go -- +//go:build linux + +package p + +import "m/q" + +-- q/q_linux.go -- +package q + +-- r/r.go -- +package r + +-- r/r_test.go -- +// +build linux + +package r + +import "m/s" + +-- s/s_linux.go -- +package s -- GitLab From f229e7031a6efb2f23241b5da000c3b3203081d6 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 25 Aug 2021 12:48:26 -0400 Subject: [PATCH 1805/2500] all: go fix -fix=buildtag std cmd (except for bootstrap deps, vendor) When these packages are released as part of Go 1.18, Go 1.16 will no longer be supported, so we can remove the +build tags in these files. Ran go fix -fix=buildtag std cmd and then reverted the bootstrapDirs as defined in src/cmd/dist/buildtool.go, which need to continue to build with Go 1.4 for now. Also reverted src/vendor and src/cmd/vendor, which will need to be updated in their own repos first. Manual changes in runtime/pprof/mprof_test.go to adjust line numbers. For #41184. Change-Id: Ic0f93f7091295b6abc76ed5cd6e6746e1280861e Reviewed-on: https://go-review.googlesource.com/c/go/+/344955 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/archive/tar/stat_actime1.go | 1 - src/archive/tar/stat_actime2.go | 1 - src/archive/tar/stat_unix.go | 1 - src/bytes/boundary_test.go | 1 - src/cmd/api/run.go | 1 - src/cmd/go/go11.go | 1 - src/cmd/go/go_unix_test.go | 1 - src/cmd/go/internal/base/signal_notunix.go | 1 - src/cmd/go/internal/base/signal_unix.go | 1 - .../internal/filelock/filelock_fcntl.go | 1 - .../internal/filelock/filelock_other.go | 1 - .../internal/filelock/filelock_plan9.go | 1 - .../internal/filelock/filelock_test.go | 1 - .../internal/filelock/filelock_unix.go | 1 - .../internal/filelock/filelock_windows.go | 1 - .../lockedfile/lockedfile_filelock.go | 1 - .../internal/lockedfile/lockedfile_plan9.go | 1 - .../go/internal/lockedfile/lockedfile_test.go | 1 - .../go/internal/lockedfile/transform_test.go | 1 - src/cmd/go/internal/modfetch/bootstrap.go | 1 - .../go/internal/modfetch/codehost/shell.go | 1 - src/cmd/go/internal/modfetch/sumdb.go | 1 - src/cmd/go/internal/modload/stat_openfile.go | 1 - src/cmd/go/internal/modload/stat_unix.go | 1 - src/cmd/go/internal/modload/stat_windows.go | 1 - .../go/internal/robustio/robustio_flaky.go | 1 - .../go/internal/robustio/robustio_other.go | 1 - src/cmd/go/internal/test/genflags.go | 1 - src/cmd/go/internal/web/bootstrap.go | 1 - src/cmd/go/internal/web/http.go | 1 - src/cmd/go/internal/web/url_other.go | 1 - src/cmd/go/internal/web/url_other_test.go | 1 - src/cmd/go/internal/work/testgo.go | 1 - src/cmd/go/stop_other_test.go | 9 --------- src/cmd/go/stop_unix_test.go | 1 - src/cmd/nm/nm_cgo_test.go | 1 - src/cmd/pprof/readlineui.go | 3 --- src/cmd/trace/annotations_test.go | 1 - src/cmd/trace/trace_test.go | 1 - src/cmd/trace/trace_unix_test.go | 1 - src/crypto/aes/aes_gcm.go | 1 - src/crypto/aes/cipher_asm.go | 1 - src/crypto/aes/cipher_generic.go | 1 - src/crypto/aes/gcm_ppc64le.go | 1 - src/crypto/cipher/xor_generic.go | 1 - src/crypto/cipher/xor_ppc64x.go | 1 - src/crypto/ecdsa/ecdsa_noasm.go | 1 - src/crypto/ecdsa/ecdsa_s390x_test.go | 1 - .../internal/edwards25519/field/fe_amd64.go | 1 - .../edwards25519/field/fe_amd64_noasm.go | 1 - .../internal/edwards25519/field/fe_arm64.go | 1 - .../edwards25519/field/fe_arm64_noasm.go | 1 - src/crypto/elliptic/export_generate.go | 1 - src/crypto/elliptic/fuzz_test.go | 1 - src/crypto/elliptic/gen_p256_table.go | 1 - src/crypto/elliptic/p256.go | 1 - src/crypto/elliptic/p256_asm.go | 1 - src/crypto/elliptic/p256_asm_table.go | 1 - src/crypto/elliptic/p256_asm_table_test.go | 1 - src/crypto/elliptic/p256_generic.go | 1 - src/crypto/elliptic/p256_ppc64le.go | 1 - src/crypto/elliptic/p256_s390x.go | 1 - src/crypto/internal/subtle/aliasing.go | 1 - .../internal/subtle/aliasing_appengine.go | 1 - src/crypto/md5/gen.go | 1 - src/crypto/md5/md5block_decl.go | 1 - src/crypto/md5/md5block_generic.go | 1 - src/crypto/rand/eagain.go | 1 - src/crypto/rand/rand_batched.go | 1 - src/crypto/rand/rand_batched_test.go | 1 - src/crypto/rand/rand_getentropy.go | 1 - src/crypto/rand/rand_js.go | 1 - src/crypto/rand/rand_unix.go | 1 - src/crypto/sha1/fallback_test.go | 1 - src/crypto/sha1/issue15617_test.go | 2 -- src/crypto/sha1/sha1block_decl.go | 1 - src/crypto/sha1/sha1block_generic.go | 1 - src/crypto/sha256/fallback_test.go | 1 - src/crypto/sha256/sha256block_decl.go | 1 - src/crypto/sha256/sha256block_generic.go | 1 - src/crypto/sha512/fallback_test.go | 1 - src/crypto/sha512/sha512block_amd64.go | 1 - src/crypto/sha512/sha512block_decl.go | 1 - src/crypto/sha512/sha512block_generic.go | 1 - src/crypto/tls/generate_cert.go | 1 - src/crypto/tls/handshake_unix_test.go | 1 - .../x509/internal/macos/corefoundation.go | 1 - src/crypto/x509/internal/macos/security.go | 1 - src/crypto/x509/root_bsd.go | 1 - src/crypto/x509/root_darwin.go | 1 - src/crypto/x509/root_ios.go | 1 - src/crypto/x509/root_ios_gen.go | 1 - src/crypto/x509/root_js.go | 1 - src/crypto/x509/root_omit.go | 2 -- src/crypto/x509/root_omit_test.go | 2 -- src/crypto/x509/root_plan9.go | 1 - src/crypto/x509/root_unix.go | 1 - src/crypto/x509/root_unix_test.go | 1 - src/crypto/x509/x509_test_import.go | 1 - src/encoding/csv/fuzz.go | 1 - src/encoding/gob/debug.go | 1 - src/encoding/gob/decgen.go | 1 - src/encoding/gob/dump.go | 1 - src/encoding/gob/encgen.go | 1 - src/encoding/json/fuzz.go | 1 - src/go/build/gc.go | 1 - src/go/build/gccgo.go | 1 - src/go/doc/headscan.go | 1 - src/go/types/example_test.go | 1 - src/go/types/gotype.go | 1 - src/hash/crc32/crc32_otherarch.go | 1 - src/hash/crc32/gen_const_ppc64le.go | 1 - src/html/fuzz.go | 1 - src/image/color/palette/gen.go | 1 - src/image/internal/imageutil/gen.go | 1 - src/image/png/fuzz.go | 1 - src/index/suffixarray/gen.go | 1 - src/internal/abi/abi_arm64.go | 1 - src/internal/abi/abi_generic.go | 1 - src/internal/abi/abi_ppc64x.go | 2 -- src/internal/bytealg/compare_generic.go | 1 - src/internal/bytealg/compare_native.go | 1 - src/internal/bytealg/count_generic.go | 1 - src/internal/bytealg/count_native.go | 1 - src/internal/bytealg/index_generic.go | 1 - src/internal/bytealg/index_native.go | 1 - src/internal/bytealg/index_ppc64x.go | 2 -- src/internal/bytealg/indexbyte_generic.go | 1 - src/internal/bytealg/indexbyte_native.go | 1 - src/internal/cpu/cpu_arm64_android.go | 1 - src/internal/cpu/cpu_arm64_darwin.go | 1 - src/internal/cpu/cpu_arm64_freebsd.go | 1 - src/internal/cpu/cpu_arm64_hwcap.go | 1 - src/internal/cpu/cpu_arm64_linux.go | 1 - src/internal/cpu/cpu_arm64_other.go | 5 ----- src/internal/cpu/cpu_mips64x.go | 1 - src/internal/cpu/cpu_no_name.go | 1 - src/internal/cpu/cpu_ppc64x.go | 1 - src/internal/cpu/cpu_ppc64x_aix.go | 1 - src/internal/cpu/cpu_ppc64x_linux.go | 1 - src/internal/cpu/cpu_x86.go | 1 - src/internal/cpu/cpu_x86_test.go | 1 - src/internal/fuzz/minimize_test.go | 1 - src/internal/fuzz/sys_posix.go | 1 - src/internal/fuzz/sys_unimplemented.go | 1 - src/internal/fuzz/trace.go | 1 - src/internal/goarch/gengoarch.go | 1 - src/internal/goarch/zgoarch_386.go | 1 - src/internal/goarch/zgoarch_amd64.go | 1 - src/internal/goarch/zgoarch_arm.go | 1 - src/internal/goarch/zgoarch_arm64.go | 1 - src/internal/goarch/zgoarch_arm64be.go | 1 - src/internal/goarch/zgoarch_armbe.go | 1 - src/internal/goarch/zgoarch_loong64.go | 1 - src/internal/goarch/zgoarch_mips.go | 1 - src/internal/goarch/zgoarch_mips64.go | 1 - src/internal/goarch/zgoarch_mips64le.go | 1 - src/internal/goarch/zgoarch_mips64p32.go | 1 - src/internal/goarch/zgoarch_mips64p32le.go | 1 - src/internal/goarch/zgoarch_mipsle.go | 1 - src/internal/goarch/zgoarch_ppc.go | 1 - src/internal/goarch/zgoarch_ppc64.go | 1 - src/internal/goarch/zgoarch_ppc64le.go | 1 - src/internal/goarch/zgoarch_riscv.go | 1 - src/internal/goarch/zgoarch_riscv64.go | 1 - src/internal/goarch/zgoarch_s390.go | 1 - src/internal/goarch/zgoarch_s390x.go | 1 - src/internal/goarch/zgoarch_sparc.go | 1 - src/internal/goarch/zgoarch_sparc64.go | 1 - src/internal/goarch/zgoarch_wasm.go | 1 - src/internal/goos/gengoos.go | 1 - src/internal/goos/zgoos_aix.go | 1 - src/internal/goos/zgoos_android.go | 1 - src/internal/goos/zgoos_darwin.go | 1 - src/internal/goos/zgoos_dragonfly.go | 1 - src/internal/goos/zgoos_freebsd.go | 1 - src/internal/goos/zgoos_hurd.go | 1 - src/internal/goos/zgoos_illumos.go | 1 - src/internal/goos/zgoos_ios.go | 1 - src/internal/goos/zgoos_js.go | 1 - src/internal/goos/zgoos_linux.go | 1 - src/internal/goos/zgoos_netbsd.go | 1 - src/internal/goos/zgoos_openbsd.go | 1 - src/internal/goos/zgoos_plan9.go | 1 - src/internal/goos/zgoos_solaris.go | 1 - src/internal/goos/zgoos_windows.go | 1 - src/internal/goos/zgoos_zos.go | 1 - src/internal/goroot/gc.go | 1 - src/internal/goroot/gccgo.go | 1 - src/internal/poll/errno_unix.go | 1 - src/internal/poll/errno_windows.go | 1 - src/internal/poll/error_stub_test.go | 1 - src/internal/poll/export_posix_test.go | 1 - src/internal/poll/fcntl_js.go | 1 - src/internal/poll/fcntl_libc.go | 1 - src/internal/poll/fcntl_syscall.go | 1 - src/internal/poll/fd_fsync_posix.go | 1 - src/internal/poll/fd_poll_js.go | 1 - src/internal/poll/fd_poll_runtime.go | 1 - src/internal/poll/fd_posix.go | 1 - src/internal/poll/fd_posix_test.go | 1 - src/internal/poll/fd_unix.go | 1 - src/internal/poll/fd_writev_darwin.go | 1 - src/internal/poll/fd_writev_illumos.go | 1 - src/internal/poll/fd_writev_unix.go | 1 - src/internal/poll/hook_cloexec.go | 1 - src/internal/poll/hook_unix.go | 1 - src/internal/poll/iovec_illumos.go | 1 - src/internal/poll/iovec_unix.go | 1 - src/internal/poll/sendfile_bsd.go | 1 - src/internal/poll/sock_cloexec.go | 1 - src/internal/poll/sockopt.go | 1 - src/internal/poll/sockopt_unix.go | 1 - src/internal/poll/sockoptip.go | 1 - src/internal/poll/strconv.go | 1 - src/internal/poll/sys_cloexec.go | 1 - src/internal/poll/writev.go | 1 - .../syscall/execenv/execenv_default.go | 1 - .../syscall/execenv/execenv_windows.go | 1 - src/internal/syscall/unix/at.go | 1 - src/internal/syscall/unix/at_libc.go | 1 - .../syscall/unix/at_sysnum_fstatat64_linux.go | 1 - .../syscall/unix/at_sysnum_fstatat_linux.go | 1 - .../unix/at_sysnum_newfstatat_linux.go | 1 - .../syscall/unix/fcntl_linux_32bit.go | 1 - .../syscall/unix/getentropy_darwin.go | 1 - src/internal/syscall/unix/getrandom.go | 1 - src/internal/syscall/unix/nonblocking.go | 1 - src/internal/syscall/unix/nonblocking_js.go | 1 - src/internal/syscall/unix/nonblocking_libc.go | 1 - src/internal/syscall/unix/pipe2_illumos.go | 1 - .../syscall/unix/sysnum_linux_generic.go | 2 -- .../syscall/unix/sysnum_linux_mips64x.go | 1 - .../syscall/unix/sysnum_linux_mipsx.go | 1 - .../syscall/unix/sysnum_linux_ppc64x.go | 1 - src/internal/syscall/unix/writev_illumos.go | 1 - src/internal/testenv/testenv_cgo.go | 1 - src/internal/testenv/testenv_notwin.go | 1 - src/log/syslog/example_test.go | 1 - src/log/syslog/syslog.go | 1 - src/log/syslog/syslog_test.go | 1 - src/log/syslog/syslog_unix.go | 1 - src/math/cmplx/huge_test.go | 1 - src/math/dim_asm.go | 1 - src/math/dim_noasm.go | 1 - src/math/exp2_asm.go | 1 - src/math/exp2_noasm.go | 1 - src/math/exp_amd64.go | 1 - src/math/exp_asm.go | 1 - src/math/exp_noasm.go | 1 - src/math/floor_asm.go | 1 - src/math/floor_noasm.go | 1 - src/math/huge_test.go | 1 - src/math/hypot_asm.go | 1 - src/math/hypot_noasm.go | 1 - src/math/log_asm.go | 1 - src/math/log_stub.go | 1 - src/math/modf_asm.go | 1 - src/math/modf_noasm.go | 1 - src/math/rand/gen_cooked.go | 1 - src/math/sqrt_asm.go | 1 - src/math/sqrt_noasm.go | 1 - src/math/stubs.go | 1 - src/mime/type_unix.go | 1 - src/mime/type_unix_test.go | 1 - src/net/addrselect.go | 1 - src/net/addrselect_test.go | 1 - src/net/cgo_aix.go | 1 - src/net/cgo_android.go | 1 - src/net/cgo_bsd.go | 3 --- src/net/cgo_linux.go | 1 - src/net/cgo_netbsd.go | 1 - src/net/cgo_openbsd.go | 1 - src/net/cgo_resnew.go | 3 --- src/net/cgo_resold.go | 3 --- src/net/cgo_socknew.go | 3 --- src/net/cgo_sockold.go | 3 --- src/net/cgo_solaris.go | 1 - src/net/cgo_stub.go | 1 - src/net/cgo_unix.go | 3 --- src/net/cgo_unix_test.go | 3 --- src/net/cgo_windows.go | 1 - src/net/conf.go | 1 - src/net/conf_netcgo.go | 1 - src/net/conf_test.go | 1 - src/net/conn_test.go | 1 - src/net/dial_test.go | 1 - src/net/dial_unix_test.go | 1 - src/net/dnsclient_unix.go | 1 - src/net/dnsclient_unix_test.go | 1 - src/net/dnsconfig_unix.go | 1 - src/net/dnsconfig_unix_test.go | 1 - src/net/dnsname_test.go | 1 - src/net/error_posix.go | 1 - src/net/error_posix_test.go | 1 - src/net/error_test.go | 1 - src/net/error_unix.go | 1 - src/net/error_unix_test.go | 1 - src/net/external_test.go | 1 - src/net/fcntl_libc_test.go | 1 - src/net/fcntl_syscall_test.go | 1 - src/net/fd_posix.go | 1 - src/net/fd_unix.go | 1 - src/net/file_stub.go | 1 - src/net/file_test.go | 1 - src/net/file_unix.go | 1 - src/net/hook_unix.go | 1 - src/net/http/cgi/plan9_test.go | 1 - src/net/http/cgi/posix_test.go | 1 - src/net/http/h2_bundle.go | 1 - src/net/http/omithttp2.go | 1 - src/net/http/roundtrip.go | 1 - src/net/http/roundtrip_js.go | 1 - src/net/http/triv.go | 1 - src/net/interface_bsd.go | 1 - src/net/interface_bsd_test.go | 1 - src/net/interface_bsdvar.go | 1 - src/net/interface_stub.go | 1 - src/net/interface_test.go | 1 - src/net/interface_unix_test.go | 1 - src/net/internal/socktest/main_test.go | 1 - src/net/internal/socktest/main_unix_test.go | 1 - src/net/internal/socktest/switch_posix.go | 1 - src/net/internal/socktest/switch_stub.go | 1 - src/net/internal/socktest/switch_unix.go | 1 - src/net/internal/socktest/sys_cloexec.go | 1 - src/net/internal/socktest/sys_unix.go | 1 - src/net/ip_test.go | 1 - src/net/iprawsock_posix.go | 1 - src/net/iprawsock_test.go | 1 - src/net/ipsock_posix.go | 1 - src/net/listen_test.go | 1 - src/net/lookup_fake.go | 1 - src/net/lookup_test.go | 1 - src/net/lookup_unix.go | 1 - src/net/main_cloexec_test.go | 1 - src/net/main_conf_test.go | 1 - src/net/main_noconf_test.go | 1 - src/net/main_posix_test.go | 1 - src/net/main_test.go | 1 - src/net/main_unix_test.go | 1 - src/net/mockserver_test.go | 1 - src/net/net_fake.go | 1 - src/net/net_test.go | 1 - src/net/netgo_unix_test.go | 2 -- src/net/nss.go | 1 - src/net/nss_test.go | 1 - src/net/packetconn_test.go | 1 - src/net/port_unix.go | 1 - src/net/protoconn_test.go | 1 - src/net/rawconn_stub_test.go | 1 - src/net/rawconn_test.go | 1 - src/net/rawconn_unix_test.go | 1 - src/net/sendfile_stub.go | 1 - src/net/sendfile_test.go | 1 - src/net/sendfile_unix_alt.go | 1 - src/net/server_test.go | 1 - src/net/sock_bsd.go | 1 - src/net/sock_cloexec.go | 1 - src/net/sock_posix.go | 1 - src/net/sock_stub.go | 1 - src/net/sockaddr_posix.go | 1 - src/net/sockopt_bsd.go | 1 - src/net/sockopt_posix.go | 1 - src/net/sockopt_stub.go | 1 - src/net/sockoptip_bsdvar.go | 1 - src/net/sockoptip_posix.go | 1 - src/net/sockoptip_stub.go | 1 - src/net/splice_stub.go | 1 - src/net/splice_test.go | 1 - src/net/sys_cloexec.go | 1 - src/net/tcpsock_posix.go | 1 - src/net/tcpsock_test.go | 1 - src/net/tcpsock_unix_test.go | 1 - src/net/tcpsockopt_posix.go | 1 - src/net/tcpsockopt_stub.go | 1 - src/net/tcpsockopt_unix.go | 1 - src/net/timeout_test.go | 1 - src/net/udpsock_posix.go | 1 - src/net/udpsock_test.go | 1 - src/net/unixsock_posix.go | 1 - src/net/unixsock_readmsg_cloexec.go | 1 - src/net/unixsock_readmsg_cmsg_cloexec.go | 1 - src/net/unixsock_readmsg_other.go | 1 - src/net/unixsock_readmsg_test.go | 1 - src/net/unixsock_test.go | 1 - src/net/unixsock_windows_test.go | 1 - src/net/write_unix_test.go | 1 - src/net/writev_test.go | 1 - src/net/writev_unix.go | 1 - src/os/dir_unix.go | 1 - src/os/endian_big.go | 1 - src/os/endian_little.go | 1 - src/os/env_unix_test.go | 1 - src/os/error_errno.go | 1 - src/os/error_posix.go | 1 - src/os/error_unix_test.go | 1 - src/os/error_windows_test.go | 1 - src/os/exec/exec_linux_test.go | 1 - src/os/exec/exec_posix_test.go | 1 - src/os/exec/exec_unix.go | 1 - src/os/exec/exec_windows_test.go | 1 - src/os/exec/lp_js.go | 1 - src/os/exec/lp_unix.go | 1 - src/os/exec/lp_unix_test.go | 1 - src/os/exec/read3.go | 1 - src/os/exec_posix.go | 1 - src/os/exec_unix.go | 1 - src/os/exec_unix_test.go | 1 - src/os/executable_path.go | 1 - src/os/executable_plan9.go | 1 - src/os/executable_procfs.go | 1 - src/os/executable_sysctl.go | 1 - src/os/export_unix_test.go | 1 - src/os/fifo_test.go | 1 - src/os/file_posix.go | 1 - src/os/file_unix.go | 1 - src/os/os_unix_test.go | 1 - src/os/path_unix.go | 1 - src/os/pipe2_bsd.go | 1 - src/os/pipe2_illumos.go | 1 - src/os/pipe_bsd.go | 1 - src/os/pipe_test.go | 1 - src/os/rawconn.go | 1 - src/os/rawconn_test.go | 1 - src/os/readfrom_stub.go | 1 - src/os/removeall_at.go | 1 - src/os/removeall_noat.go | 1 - src/os/signal/example_unix_test.go | 1 - src/os/signal/internal/pty/pty.go | 2 -- src/os/signal/signal_cgo_test.go | 2 -- src/os/signal/signal_linux_test.go | 1 - src/os/signal/signal_test.go | 1 - src/os/signal/signal_unix.go | 1 - src/os/stat_js.go | 1 - src/os/stat_unix.go | 1 - src/os/sticky_bsd.go | 1 - src/os/sticky_notbsd.go | 8 -------- src/os/sys_bsd.go | 1 - src/os/sys_js.go | 1 - src/os/sys_unix.go | 1 - src/os/timeout_test.go | 1 - src/os/types_unix.go | 1 - src/os/user/cgo_listgroups_unix.go | 3 --- src/os/user/cgo_lookup_unix.go | 3 --- src/os/user/cgo_unix_test.go | 3 --- src/os/user/getgrouplist_darwin.go | 1 - src/os/user/getgrouplist_unix.go | 3 --- src/os/user/listgroups_stub.go | 1 - src/os/user/lookup_android.go | 1 - src/os/user/lookup_stubs.go | 1 - src/os/user/lookup_unix.go | 2 -- src/os/user/lookup_unix_test.go | 2 -- src/os/wait_unimp.go | 1 - src/os/wait_wait6.go | 1 - src/os/wait_waitid.go | 1 - src/path/filepath/example_unix_test.go | 1 - src/path/filepath/example_unix_walk_test.go | 1 - src/path/filepath/path_unix.go | 1 - src/path/filepath/symlink_unix.go | 1 - src/plugin/plugin_dlopen.go | 1 - src/plugin/plugin_stubs.go | 1 - src/plugin/plugin_test.go | 1 - src/reflect/abi_test.go | 1 - src/reflect/float32reg_generic.go | 1 - src/reflect/stubs_ppc64x.go | 1 - src/regexp/exec2_test.go | 1 - src/runtime/abi_test.go | 1 - src/runtime/asan.go | 1 - src/runtime/asan0.go | 1 - src/runtime/auxv_none.go | 1 - src/runtime/cgo/callbacks_traceback.go | 1 - src/runtime/cgo/dragonfly.go | 1 - src/runtime/cgo/freebsd.go | 1 - src/runtime/cgo/linux.go | 1 - src/runtime/cgo/mmap.go | 1 - src/runtime/cgo/netbsd.go | 1 - src/runtime/cgo/openbsd.go | 1 - src/runtime/cgo/setenv.go | 1 - src/runtime/cgo/sigaction.go | 1 - src/runtime/cgo_mmap.go | 1 - src/runtime/cgo_ppc64x.go | 1 - src/runtime/cgo_sigaction.go | 1 - src/runtime/cputicks.go | 1 - src/runtime/crash_cgo_test.go | 1 - src/runtime/crash_nonunix_test.go | 1 - src/runtime/crash_unix_test.go | 1 - src/runtime/debug/panic_test.go | 1 - src/runtime/debug_test.go | 1 - src/runtime/debugcall.go | 1 - src/runtime/debuglog_off.go | 1 - src/runtime/debuglog_on.go | 1 - src/runtime/defs1_linux.go | 1 - src/runtime/defs2_linux.go | 1 - src/runtime/defs3_linux.go | 1 - src/runtime/defs_aix.go | 1 - src/runtime/defs_aix_ppc64.go | 1 - src/runtime/defs_arm_linux.go | 1 - src/runtime/defs_darwin.go | 1 - src/runtime/defs_dragonfly.go | 1 - src/runtime/defs_freebsd.go | 1 - src/runtime/defs_linux.go | 1 - src/runtime/defs_linux_mips64x.go | 2 -- src/runtime/defs_linux_mipsx.go | 2 -- src/runtime/defs_netbsd.go | 1 - src/runtime/defs_netbsd_386.go | 1 - src/runtime/defs_netbsd_amd64.go | 1 - src/runtime/defs_netbsd_arm.go | 1 - src/runtime/defs_openbsd.go | 1 - src/runtime/defs_solaris.go | 1 - src/runtime/defs_solaris_amd64.go | 1 - src/runtime/env_posix.go | 1 - .../export_debug_regabiargs_off_test.go | 1 - .../export_debug_regabiargs_on_test.go | 1 - src/runtime/export_debug_test.go | 1 - src/runtime/export_futex_test.go | 1 - src/runtime/export_mmap_test.go | 1 - src/runtime/export_pipe2_test.go | 1 - src/runtime/export_pipe_test.go | 1 - src/runtime/export_unix_test.go | 1 - src/runtime/futex_test.go | 2 -- src/runtime/hash32.go | 1 - src/runtime/hash64.go | 1 - src/runtime/internal/atomic/atomic_386.go | 1 - src/runtime/internal/atomic/atomic_arm.go | 1 - src/runtime/internal/atomic/atomic_arm64.go | 1 - src/runtime/internal/atomic/atomic_mips64x.go | 1 - src/runtime/internal/atomic/atomic_mipsx.go | 1 - src/runtime/internal/atomic/atomic_ppc64x.go | 1 - src/runtime/internal/atomic/stubs.go | 1 - src/runtime/internal/atomic/types_64bit.go | 1 - src/runtime/internal/sys/intrinsics.go | 1 - src/runtime/internal/sys/intrinsics_stubs.go | 1 - src/runtime/lfstack_32bit.go | 1 - src/runtime/lfstack_64bit.go | 1 - src/runtime/libfuzzer.go | 1 - src/runtime/lock_futex.go | 1 - src/runtime/lock_js.go | 1 - src/runtime/lock_sema.go | 1 - src/runtime/lockrank_off.go | 1 - src/runtime/lockrank_on.go | 1 - src/runtime/mem_bsd.go | 1 - src/runtime/mem_js.go | 1 - src/runtime/mkduff.go | 1 - src/runtime/mkfastlog2table.go | 1 - src/runtime/mkpreempt.go | 1 - src/runtime/mksizeclasses.go | 1 - src/runtime/mmap.go | 9 --------- src/runtime/mpagealloc_32bit.go | 1 - src/runtime/mpagealloc_64bit.go | 1 - src/runtime/msan.go | 1 - src/runtime/msan0.go | 1 - src/runtime/nbpipe_fcntl_libc_test.go | 1 - src/runtime/nbpipe_fcntl_unix_test.go | 1 - src/runtime/nbpipe_pipe.go | 1 - src/runtime/nbpipe_pipe2.go | 1 - src/runtime/nbpipe_test.go | 1 - src/runtime/netpoll.go | 1 - src/runtime/netpoll_epoll.go | 1 - src/runtime/netpoll_fake.go | 1 - src/runtime/netpoll_kqueue.go | 1 - src/runtime/netpoll_stub.go | 1 - src/runtime/norace_linux_test.go | 1 - src/runtime/norace_test.go | 1 - src/runtime/os_aix.go | 1 - src/runtime/os_freebsd2.go | 1 - src/runtime/os_freebsd_noauxv.go | 1 - src/runtime/os_js.go | 1 - src/runtime/os_linux_arm64.go | 1 - src/runtime/os_linux_be64.go | 2 -- src/runtime/os_linux_generic.go | 1 - src/runtime/os_linux_mips64x.go | 2 -- src/runtime/os_linux_mipsx.go | 2 -- src/runtime/os_linux_noauxv.go | 1 - src/runtime/os_linux_novdso.go | 1 - src/runtime/os_linux_ppc64x.go | 2 -- src/runtime/os_linux_x86.go | 2 -- src/runtime/os_nonopenbsd.go | 1 - src/runtime/os_only_solaris.go | 1 - src/runtime/os_openbsd_libc.go | 1 - src/runtime/os_openbsd_syscall.go | 1 - src/runtime/os_openbsd_syscall1.go | 1 - src/runtime/os_openbsd_syscall2.go | 1 - src/runtime/panic32.go | 1 - src/runtime/pprof/mprof_test.go | 19 +++++++++---------- src/runtime/pprof/pprof_norusage.go | 1 - src/runtime/pprof/pprof_rusage.go | 1 - src/runtime/pprof/pprof_test.go | 1 - src/runtime/pprof/rusage_test.go | 1 - src/runtime/preempt_nonwindows.go | 1 - src/runtime/race.go | 1 - src/runtime/race/output_test.go | 1 - src/runtime/race/race.go | 1 - src/runtime/race/race_linux_test.go | 1 - src/runtime/race/race_test.go | 1 - src/runtime/race/race_unix_test.go | 2 -- src/runtime/race/race_windows_test.go | 1 - src/runtime/race/sched_test.go | 1 - src/runtime/race/syso_test.go | 1 - src/runtime/race/timer_test.go | 1 - src/runtime/race0.go | 1 - src/runtime/relax_stub.go | 1 - src/runtime/runtime_mmap_test.go | 1 - src/runtime/runtime_unix_test.go | 1 - src/runtime/semasleep_test.go | 1 - src/runtime/sigaction.go | 1 - src/runtime/signal_386.go | 1 - src/runtime/signal_aix_ppc64.go | 1 - src/runtime/signal_amd64.go | 2 -- src/runtime/signal_arm.go | 1 - src/runtime/signal_arm64.go | 1 - src/runtime/signal_linux_mips64x.go | 2 -- src/runtime/signal_linux_mipsx.go | 2 -- src/runtime/signal_linux_ppc64x.go | 2 -- src/runtime/signal_mips64x.go | 2 -- src/runtime/signal_mipsx.go | 2 -- src/runtime/signal_ppc64x.go | 2 -- src/runtime/signal_riscv64.go | 1 - src/runtime/signal_unix.go | 1 - src/runtime/signal_windows_test.go | 1 - src/runtime/sigqueue.go | 1 - src/runtime/sigqueue_note.go | 1 - src/runtime/sigtab_linux_generic.go | 1 - src/runtime/sigtab_linux_mipsx.go | 2 -- src/runtime/stubs2.go | 1 - src/runtime/stubs3.go | 1 - src/runtime/stubs_linux.go | 1 - src/runtime/stubs_mips64x.go | 1 - src/runtime/stubs_mipsx.go | 1 - src/runtime/stubs_nonlinux.go | 1 - src/runtime/stubs_ppc64.go | 1 - src/runtime/stubs_ppc64x.go | 1 - src/runtime/sys_libc.go | 1 - src/runtime/sys_mips64x.go | 1 - src/runtime/sys_mipsx.go | 1 - src/runtime/sys_nonppc64x.go | 1 - src/runtime/sys_openbsd.go | 1 - src/runtime/sys_openbsd1.go | 1 - src/runtime/sys_openbsd2.go | 1 - src/runtime/sys_openbsd3.go | 1 - src/runtime/sys_ppc64x.go | 1 - src/runtime/sys_x86.go | 1 - src/runtime/time_fake.go | 1 - src/runtime/time_nofake.go | 1 - src/runtime/timeasm.go | 2 -- src/runtime/timestub.go | 3 --- src/runtime/timestub2.go | 7 ------- src/runtime/tls_stub.go | 1 - src/runtime/vdso_elf32.go | 2 -- src/runtime/vdso_elf64.go | 2 -- src/runtime/vdso_freebsd.go | 1 - src/runtime/vdso_freebsd_x86.go | 2 -- src/runtime/vdso_in_none.go | 1 - src/runtime/vdso_linux.go | 2 -- src/runtime/vdso_linux_mips64x.go | 2 -- src/runtime/vdso_linux_ppc64x.go | 2 -- src/runtime/vlrt.go | 1 - src/runtime/wincallback.go | 1 - src/runtime/write_err.go | 1 - src/sync/pool_test.go | 1 - src/sync/runtime2.go | 1 - src/sync/runtime2_lockrank.go | 1 - src/syscall/bpf_bsd.go | 1 - src/syscall/creds_test.go | 1 - src/syscall/dirent.go | 1 - src/syscall/dirent_test.go | 1 - src/syscall/endian_big.go | 1 - src/syscall/endian_little.go | 1 - src/syscall/env_unix.go | 1 - src/syscall/exec_aix_test.go | 1 - src/syscall/exec_bsd.go | 1 - src/syscall/exec_libc.go | 1 - src/syscall/exec_libc2.go | 1 - src/syscall/exec_linux.go | 1 - src/syscall/exec_linux_test.go | 1 - src/syscall/exec_pdeathsig_test.go | 1 - src/syscall/exec_solaris_test.go | 1 - src/syscall/exec_unix.go | 1 - src/syscall/exec_unix_test.go | 1 - src/syscall/export_unix_test.go | 1 - src/syscall/flock.go | 1 - src/syscall/flock_linux_32bit.go | 1 - src/syscall/forkpipe.go | 1 - src/syscall/forkpipe2.go | 1 - src/syscall/fs_js.go | 1 - src/syscall/getdirentries_test.go | 1 - src/syscall/mkasm.go | 1 - src/syscall/mkpost.go | 1 - src/syscall/mksyscall_windows.go | 1 - src/syscall/mmap_unix_test.go | 1 - src/syscall/msan.go | 1 - src/syscall/msan0.go | 1 - src/syscall/net_js.go | 1 - src/syscall/ptrace_darwin.go | 1 - src/syscall/ptrace_ios.go | 1 - src/syscall/route_bsd.go | 1 - src/syscall/route_freebsd_32bit.go | 1 - src/syscall/route_freebsd_64bit.go | 1 - src/syscall/setuidgid_32_linux.go | 2 -- src/syscall/setuidgid_linux.go | 1 - src/syscall/sockcmsg_unix.go | 1 - src/syscall/sockcmsg_unix_other.go | 1 - src/syscall/syscall_bsd.go | 1 - src/syscall/syscall_bsd_test.go | 1 - src/syscall/syscall_freebsd_test.go | 1 - src/syscall/syscall_illumos.go | 1 - src/syscall/syscall_js.go | 1 - src/syscall/syscall_linux_mips64x.go | 2 -- src/syscall/syscall_linux_mipsx.go | 2 -- src/syscall/syscall_linux_ppc64x.go | 2 -- src/syscall/syscall_openbsd1.go | 1 - src/syscall/syscall_openbsd_libc.go | 1 - src/syscall/syscall_ptrace_test.go | 1 - src/syscall/syscall_unix.go | 1 - src/syscall/syscall_unix_test.go | 1 - src/syscall/tables_js.go | 1 - src/syscall/time_fake.go | 1 - src/syscall/time_nofake.go | 1 - src/syscall/timestruct.go | 1 - src/syscall/types_aix.go | 1 - src/syscall/types_darwin.go | 1 - src/syscall/types_dragonfly.go | 1 - src/syscall/types_freebsd.go | 1 - src/syscall/types_illumos_amd64.go | 1 - src/syscall/types_linux.go | 1 - src/syscall/types_netbsd.go | 1 - src/syscall/types_openbsd.go | 1 - src/syscall/types_solaris.go | 1 - src/syscall/zerrors_darwin_amd64.go | 1 - src/syscall/zerrors_darwin_arm64.go | 1 - src/syscall/zerrors_dragonfly_amd64.go | 1 - src/syscall/zerrors_freebsd_386.go | 1 - src/syscall/zerrors_freebsd_amd64.go | 1 - src/syscall/zerrors_freebsd_arm.go | 1 - src/syscall/zerrors_freebsd_arm64.go | 1 - src/syscall/zerrors_linux_386.go | 1 - src/syscall/zerrors_linux_amd64.go | 1 - src/syscall/zerrors_linux_arm.go | 1 - src/syscall/zerrors_linux_arm64.go | 1 - src/syscall/zerrors_linux_ppc64.go | 1 - src/syscall/zerrors_linux_ppc64le.go | 1 - src/syscall/zerrors_netbsd_386.go | 1 - src/syscall/zerrors_netbsd_amd64.go | 1 - src/syscall/zerrors_netbsd_arm.go | 1 - src/syscall/zerrors_netbsd_arm64.go | 1 - src/syscall/zerrors_openbsd_386.go | 1 - src/syscall/zerrors_openbsd_amd64.go | 1 - src/syscall/zerrors_openbsd_arm.go | 1 - src/syscall/zerrors_solaris_amd64.go | 1 - src/syscall/zsyscall_aix_ppc64.go | 1 - src/syscall/zsyscall_darwin_amd64.go | 1 - src/syscall/zsyscall_darwin_arm64.go | 1 - src/syscall/zsyscall_dragonfly_amd64.go | 1 - src/syscall/zsyscall_freebsd_386.go | 1 - src/syscall/zsyscall_freebsd_amd64.go | 1 - src/syscall/zsyscall_freebsd_arm.go | 1 - src/syscall/zsyscall_freebsd_arm64.go | 1 - src/syscall/zsyscall_linux_386.go | 1 - src/syscall/zsyscall_linux_amd64.go | 1 - src/syscall/zsyscall_linux_arm.go | 1 - src/syscall/zsyscall_linux_arm64.go | 1 - src/syscall/zsyscall_linux_mips.go | 1 - src/syscall/zsyscall_linux_mips64.go | 1 - src/syscall/zsyscall_linux_mips64le.go | 1 - src/syscall/zsyscall_linux_mipsle.go | 1 - src/syscall/zsyscall_linux_ppc64.go | 1 - src/syscall/zsyscall_linux_ppc64le.go | 1 - src/syscall/zsyscall_linux_riscv64.go | 1 - src/syscall/zsyscall_linux_s390x.go | 1 - src/syscall/zsyscall_netbsd_386.go | 1 - src/syscall/zsyscall_netbsd_amd64.go | 1 - src/syscall/zsyscall_netbsd_arm.go | 1 - src/syscall/zsyscall_netbsd_arm64.go | 1 - src/syscall/zsyscall_openbsd_386.go | 1 - src/syscall/zsyscall_openbsd_amd64.go | 1 - src/syscall/zsyscall_openbsd_arm.go | 1 - src/syscall/zsyscall_openbsd_arm64.go | 1 - src/syscall/zsyscall_openbsd_mips64.go | 1 - src/syscall/zsyscall_plan9_386.go | 1 - src/syscall/zsyscall_plan9_amd64.go | 1 - src/syscall/zsyscall_plan9_arm.go | 1 - src/syscall/zsyscall_solaris_amd64.go | 1 - src/syscall/zsysnum_darwin_amd64.go | 1 - src/syscall/zsysnum_darwin_arm64.go | 1 - src/syscall/zsysnum_dragonfly_amd64.go | 1 - src/syscall/zsysnum_freebsd_386.go | 1 - src/syscall/zsysnum_freebsd_amd64.go | 1 - src/syscall/zsysnum_freebsd_arm.go | 1 - src/syscall/zsysnum_freebsd_arm64.go | 1 - src/syscall/zsysnum_linux_386.go | 1 - src/syscall/zsysnum_linux_amd64.go | 1 - src/syscall/zsysnum_linux_arm.go | 1 - src/syscall/zsysnum_linux_arm64.go | 1 - src/syscall/zsysnum_linux_ppc64.go | 1 - src/syscall/zsysnum_linux_ppc64le.go | 1 - src/syscall/zsysnum_netbsd_386.go | 1 - src/syscall/zsysnum_netbsd_amd64.go | 1 - src/syscall/zsysnum_netbsd_arm.go | 1 - src/syscall/zsysnum_netbsd_arm64.go | 1 - src/syscall/zsysnum_openbsd_386.go | 1 - src/syscall/zsysnum_openbsd_amd64.go | 1 - src/syscall/zsysnum_openbsd_arm.go | 1 - src/syscall/zsysnum_solaris_amd64.go | 1 - src/syscall/ztypes_darwin_amd64.go | 1 - src/syscall/ztypes_darwin_arm64.go | 1 - src/syscall/ztypes_dragonfly_amd64.go | 1 - src/syscall/ztypes_freebsd_386.go | 1 - src/syscall/ztypes_freebsd_amd64.go | 1 - src/syscall/ztypes_freebsd_arm.go | 1 - src/syscall/ztypes_freebsd_arm64.go | 1 - src/syscall/ztypes_linux_386.go | 1 - src/syscall/ztypes_linux_amd64.go | 1 - src/syscall/ztypes_linux_arm.go | 1 - src/syscall/ztypes_linux_arm64.go | 1 - src/syscall/ztypes_linux_ppc64.go | 1 - src/syscall/ztypes_linux_ppc64le.go | 1 - src/syscall/ztypes_netbsd_386.go | 1 - src/syscall/ztypes_netbsd_amd64.go | 1 - src/syscall/ztypes_netbsd_arm.go | 1 - src/syscall/ztypes_netbsd_arm64.go | 1 - src/syscall/ztypes_openbsd_386.go | 1 - src/syscall/ztypes_openbsd_amd64.go | 1 - src/syscall/ztypes_solaris_amd64.go | 1 - src/testing/run_example.go | 1 - src/testing/run_example_js.go | 1 - src/time/embed.go | 1 - src/time/genzabbrs.go | 1 - src/time/sys_plan9.go | 1 - src/time/sys_unix.go | 1 - src/time/tzdata/generate_zipdata.go | 1 - src/time/zoneinfo_ios.go | 1 - src/time/zoneinfo_js.go | 1 - src/time/zoneinfo_unix.go | 1 - src/time/zoneinfo_unix_test.go | 1 - 834 files changed, 9 insertions(+), 941 deletions(-) diff --git a/src/archive/tar/stat_actime1.go b/src/archive/tar/stat_actime1.go index 4fdf2a04b3..c4c2480fee 100644 --- a/src/archive/tar/stat_actime1.go +++ b/src/archive/tar/stat_actime1.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || linux || dragonfly || openbsd || solaris -// +build aix linux dragonfly openbsd solaris package tar diff --git a/src/archive/tar/stat_actime2.go b/src/archive/tar/stat_actime2.go index 5a9a35cbb4..f76d6be220 100644 --- a/src/archive/tar/stat_actime2.go +++ b/src/archive/tar/stat_actime2.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || freebsd || netbsd -// +build darwin freebsd netbsd package tar diff --git a/src/archive/tar/stat_unix.go b/src/archive/tar/stat_unix.go index 3957349d6e..717a0b3abc 100644 --- a/src/archive/tar/stat_unix.go +++ b/src/archive/tar/stat_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || linux || darwin || dragonfly || freebsd || openbsd || netbsd || solaris -// +build aix linux darwin dragonfly freebsd openbsd netbsd solaris package tar diff --git a/src/bytes/boundary_test.go b/src/bytes/boundary_test.go index 5a47526593..8dac751866 100644 --- a/src/bytes/boundary_test.go +++ b/src/bytes/boundary_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. // //go:build linux -// +build linux package bytes_test diff --git a/src/cmd/api/run.go b/src/cmd/api/run.go index 81979de191..1b94a1b883 100644 --- a/src/cmd/api/run.go +++ b/src/cmd/api/run.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore // The run program is invoked via the dist tool. // To invoke manually: go tool dist test -run api --no-rebuild diff --git a/src/cmd/go/go11.go b/src/cmd/go/go11.go index a1f2727825..9faa7cba42 100644 --- a/src/cmd/go/go11.go +++ b/src/cmd/go/go11.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build go1.1 -// +build go1.1 package main diff --git a/src/cmd/go/go_unix_test.go b/src/cmd/go/go_unix_test.go index 7d5ff9bbb7..bab9494401 100644 --- a/src/cmd/go/go_unix_test.go +++ b/src/cmd/go/go_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build darwin dragonfly freebsd linux netbsd openbsd solaris package main_test diff --git a/src/cmd/go/internal/base/signal_notunix.go b/src/cmd/go/internal/base/signal_notunix.go index 5cc0b0f101..682705f9b2 100644 --- a/src/cmd/go/internal/base/signal_notunix.go +++ b/src/cmd/go/internal/base/signal_notunix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build plan9 || windows -// +build plan9 windows package base diff --git a/src/cmd/go/internal/base/signal_unix.go b/src/cmd/go/internal/base/signal_unix.go index cdc2658372..657ff38584 100644 --- a/src/cmd/go/internal/base/signal_unix.go +++ b/src/cmd/go/internal/base/signal_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || js || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd js linux netbsd openbsd solaris package base diff --git a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go index a37b2ad6d1..09354d2306 100644 --- a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go +++ b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || (solaris && !illumos) -// +build aix solaris,!illumos // This code implements the filelock API using POSIX 'fcntl' locks, which attach // to an (inode, process) pair rather than a file descriptor. To avoid unlocking diff --git a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_other.go b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_other.go index 70f5d7a688..491bec39af 100644 --- a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_other.go +++ b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_other.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !plan9 && !solaris && !windows -// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!plan9,!solaris,!windows package filelock diff --git a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_plan9.go b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_plan9.go index 908afb6c8c..54b2c946e0 100644 --- a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_plan9.go +++ b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_plan9.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build plan9 -// +build plan9 package filelock diff --git a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_test.go b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_test.go index 640d4406f4..7bd7bd28f5 100644 --- a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_test.go +++ b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js && !plan9 -// +build !js,!plan9 package filelock_test diff --git a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_unix.go b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_unix.go index 878a1e770d..d7778d05de 100644 --- a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_unix.go +++ b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || illumos || linux || netbsd || openbsd -// +build darwin dragonfly freebsd illumos linux netbsd openbsd package filelock diff --git a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_windows.go b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_windows.go index dd27ce92bd..e2ca538304 100644 --- a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_windows.go +++ b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_windows.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows -// +build windows package filelock diff --git a/src/cmd/go/internal/lockedfile/lockedfile_filelock.go b/src/cmd/go/internal/lockedfile/lockedfile_filelock.go index e4923f6876..1a677a7fe4 100644 --- a/src/cmd/go/internal/lockedfile/lockedfile_filelock.go +++ b/src/cmd/go/internal/lockedfile/lockedfile_filelock.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !plan9 -// +build !plan9 package lockedfile diff --git a/src/cmd/go/internal/lockedfile/lockedfile_plan9.go b/src/cmd/go/internal/lockedfile/lockedfile_plan9.go index 979118b10a..35669388e0 100644 --- a/src/cmd/go/internal/lockedfile/lockedfile_plan9.go +++ b/src/cmd/go/internal/lockedfile/lockedfile_plan9.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build plan9 -// +build plan9 package lockedfile diff --git a/src/cmd/go/internal/lockedfile/lockedfile_test.go b/src/cmd/go/internal/lockedfile/lockedfile_test.go index 3acc6695a7..c9907db46c 100644 --- a/src/cmd/go/internal/lockedfile/lockedfile_test.go +++ b/src/cmd/go/internal/lockedfile/lockedfile_test.go @@ -4,7 +4,6 @@ // js does not support inter-process file locking. //go:build !js -// +build !js package lockedfile_test diff --git a/src/cmd/go/internal/lockedfile/transform_test.go b/src/cmd/go/internal/lockedfile/transform_test.go index b753346e7d..3c1caa334e 100644 --- a/src/cmd/go/internal/lockedfile/transform_test.go +++ b/src/cmd/go/internal/lockedfile/transform_test.go @@ -4,7 +4,6 @@ // js does not support inter-process file locking. //go:build !js -// +build !js package lockedfile_test diff --git a/src/cmd/go/internal/modfetch/bootstrap.go b/src/cmd/go/internal/modfetch/bootstrap.go index ed694581a7..e23669fb00 100644 --- a/src/cmd/go/internal/modfetch/bootstrap.go +++ b/src/cmd/go/internal/modfetch/bootstrap.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build cmd_go_bootstrap -// +build cmd_go_bootstrap package modfetch diff --git a/src/cmd/go/internal/modfetch/codehost/shell.go b/src/cmd/go/internal/modfetch/codehost/shell.go index 0e9f381966..eaa01950b9 100644 --- a/src/cmd/go/internal/modfetch/codehost/shell.go +++ b/src/cmd/go/internal/modfetch/codehost/shell.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore // Interactive debugging shell for codehost.Repo implementations. diff --git a/src/cmd/go/internal/modfetch/sumdb.go b/src/cmd/go/internal/modfetch/sumdb.go index 79961b4324..492b03bd84 100644 --- a/src/cmd/go/internal/modfetch/sumdb.go +++ b/src/cmd/go/internal/modfetch/sumdb.go @@ -5,7 +5,6 @@ // Go checksum database lookup //go:build !cmd_go_bootstrap -// +build !cmd_go_bootstrap package modfetch diff --git a/src/cmd/go/internal/modload/stat_openfile.go b/src/cmd/go/internal/modload/stat_openfile.go index 368f893198..ff7c124af5 100644 --- a/src/cmd/go/internal/modload/stat_openfile.go +++ b/src/cmd/go/internal/modload/stat_openfile.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build (js && wasm) || plan9 -// +build js,wasm plan9 // On plan9, per http://9p.io/magic/man2html/2/access: “Since file permissions // are checked by the server and group information is not known to the client, diff --git a/src/cmd/go/internal/modload/stat_unix.go b/src/cmd/go/internal/modload/stat_unix.go index e079d73990..8a3653ba80 100644 --- a/src/cmd/go/internal/modload/stat_unix.go +++ b/src/cmd/go/internal/modload/stat_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package modload diff --git a/src/cmd/go/internal/modload/stat_windows.go b/src/cmd/go/internal/modload/stat_windows.go index 825e60b27a..f29a99165e 100644 --- a/src/cmd/go/internal/modload/stat_windows.go +++ b/src/cmd/go/internal/modload/stat_windows.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows -// +build windows package modload diff --git a/src/cmd/go/internal/robustio/robustio_flaky.go b/src/cmd/go/internal/robustio/robustio_flaky.go index d5c241857b..c56e36ca62 100644 --- a/src/cmd/go/internal/robustio/robustio_flaky.go +++ b/src/cmd/go/internal/robustio/robustio_flaky.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows || darwin -// +build windows darwin package robustio diff --git a/src/cmd/go/internal/robustio/robustio_other.go b/src/cmd/go/internal/robustio/robustio_other.go index 3a20cac6cf..da9a46e4fa 100644 --- a/src/cmd/go/internal/robustio/robustio_other.go +++ b/src/cmd/go/internal/robustio/robustio_other.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !windows && !darwin -// +build !windows,!darwin package robustio diff --git a/src/cmd/go/internal/test/genflags.go b/src/cmd/go/internal/test/genflags.go index cba366062f..10f290090c 100644 --- a/src/cmd/go/internal/test/genflags.go +++ b/src/cmd/go/internal/test/genflags.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore package main diff --git a/src/cmd/go/internal/web/bootstrap.go b/src/cmd/go/internal/web/bootstrap.go index 08686cdfcf..ab88e9e478 100644 --- a/src/cmd/go/internal/web/bootstrap.go +++ b/src/cmd/go/internal/web/bootstrap.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build cmd_go_bootstrap -// +build cmd_go_bootstrap // This code is compiled only into the bootstrap 'go' binary. // These stubs avoid importing packages with large dependency diff --git a/src/cmd/go/internal/web/http.go b/src/cmd/go/internal/web/http.go index 81f841d2c6..a92326db01 100644 --- a/src/cmd/go/internal/web/http.go +++ b/src/cmd/go/internal/web/http.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !cmd_go_bootstrap -// +build !cmd_go_bootstrap // This code is compiled into the real 'go' binary, but it is not // compiled into the binary that is built during all.bash, so as diff --git a/src/cmd/go/internal/web/url_other.go b/src/cmd/go/internal/web/url_other.go index 453af402b4..84bbd72820 100644 --- a/src/cmd/go/internal/web/url_other.go +++ b/src/cmd/go/internal/web/url_other.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !windows -// +build !windows package web diff --git a/src/cmd/go/internal/web/url_other_test.go b/src/cmd/go/internal/web/url_other_test.go index 4d6ed2ec7f..5c197de800 100644 --- a/src/cmd/go/internal/web/url_other_test.go +++ b/src/cmd/go/internal/web/url_other_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !windows -// +build !windows package web diff --git a/src/cmd/go/internal/work/testgo.go b/src/cmd/go/internal/work/testgo.go index 8b77871b23..a09b65a23c 100644 --- a/src/cmd/go/internal/work/testgo.go +++ b/src/cmd/go/internal/work/testgo.go @@ -5,7 +5,6 @@ // This file contains extra hooks for testing the go command. //go:build testgo -// +build testgo package work diff --git a/src/cmd/go/stop_other_test.go b/src/cmd/go/stop_other_test.go index e1cc6cf8ba..35c12858c1 100644 --- a/src/cmd/go/stop_other_test.go +++ b/src/cmd/go/stop_other_test.go @@ -3,15 +3,6 @@ // license that can be found in the LICENSE file. //go:build !(aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris) -// +build !aix -// +build !darwin -// +build !dragonfly -// +build !freebsd -// +build !js !wasm -// +build !linux -// +build !netbsd -// +build !openbsd -// +build !solaris package main_test diff --git a/src/cmd/go/stop_unix_test.go b/src/cmd/go/stop_unix_test.go index ac35b240f0..5939f0d40d 100644 --- a/src/cmd/go/stop_unix_test.go +++ b/src/cmd/go/stop_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris package main_test diff --git a/src/cmd/nm/nm_cgo_test.go b/src/cmd/nm/nm_cgo_test.go index 1544be041a..0c826738ec 100644 --- a/src/cmd/nm/nm_cgo_test.go +++ b/src/cmd/nm/nm_cgo_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build cgo -// +build cgo package main diff --git a/src/cmd/pprof/readlineui.go b/src/cmd/pprof/readlineui.go index f46e934e0f..7ad712cd60 100644 --- a/src/cmd/pprof/readlineui.go +++ b/src/cmd/pprof/readlineui.go @@ -6,9 +6,6 @@ // that provides the readline functionality if possible. //go:build (darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || windows) && !appengine && !android -// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows -// +build !appengine -// +build !android package main diff --git a/src/cmd/trace/annotations_test.go b/src/cmd/trace/annotations_test.go index acd5693c7d..9f1c8e3b3b 100644 --- a/src/cmd/trace/annotations_test.go +++ b/src/cmd/trace/annotations_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js -// +build !js package main diff --git a/src/cmd/trace/trace_test.go b/src/cmd/trace/trace_test.go index 2b1a68d7f3..87fd3a3515 100644 --- a/src/cmd/trace/trace_test.go +++ b/src/cmd/trace/trace_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js -// +build !js package main diff --git a/src/cmd/trace/trace_unix_test.go b/src/cmd/trace/trace_unix_test.go index 8dc56a8c7b..f35061ec63 100644 --- a/src/cmd/trace/trace_unix_test.go +++ b/src/cmd/trace/trace_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build darwin dragonfly freebsd linux netbsd openbsd solaris package main diff --git a/src/crypto/aes/aes_gcm.go b/src/crypto/aes/aes_gcm.go index 1de0e457a2..98fb6d8e9b 100644 --- a/src/crypto/aes/aes_gcm.go +++ b/src/crypto/aes/aes_gcm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 || arm64 -// +build amd64 arm64 package aes diff --git a/src/crypto/aes/cipher_asm.go b/src/crypto/aes/cipher_asm.go index 4251805ef9..c948f1a579 100644 --- a/src/crypto/aes/cipher_asm.go +++ b/src/crypto/aes/cipher_asm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 || arm64 -// +build amd64 arm64 package aes diff --git a/src/crypto/aes/cipher_generic.go b/src/crypto/aes/cipher_generic.go index 22ce3be7f3..bff21ae54b 100644 --- a/src/crypto/aes/cipher_generic.go +++ b/src/crypto/aes/cipher_generic.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !amd64 && !s390x && !ppc64le && !arm64 -// +build !amd64,!s390x,!ppc64le,!arm64 package aes diff --git a/src/crypto/aes/gcm_ppc64le.go b/src/crypto/aes/gcm_ppc64le.go index 01b4e08757..cba6c8873f 100644 --- a/src/crypto/aes/gcm_ppc64le.go +++ b/src/crypto/aes/gcm_ppc64le.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64le -// +build ppc64le package aes diff --git a/src/crypto/cipher/xor_generic.go b/src/crypto/cipher/xor_generic.go index 03208402d7..43517a8e20 100644 --- a/src/crypto/cipher/xor_generic.go +++ b/src/crypto/cipher/xor_generic.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !amd64 && !ppc64 && !ppc64le && !arm64 -// +build !amd64,!ppc64,!ppc64le,!arm64 package cipher diff --git a/src/crypto/cipher/xor_ppc64x.go b/src/crypto/cipher/xor_ppc64x.go index f520208a37..f81eec531d 100644 --- a/src/crypto/cipher/xor_ppc64x.go +++ b/src/crypto/cipher/xor_ppc64x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le package cipher diff --git a/src/crypto/ecdsa/ecdsa_noasm.go b/src/crypto/ecdsa/ecdsa_noasm.go index 68670a4f93..7fbca10b56 100644 --- a/src/crypto/ecdsa/ecdsa_noasm.go +++ b/src/crypto/ecdsa/ecdsa_noasm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !s390x -// +build !s390x package ecdsa diff --git a/src/crypto/ecdsa/ecdsa_s390x_test.go b/src/crypto/ecdsa/ecdsa_s390x_test.go index f5633fb8a6..fd1dc7c060 100644 --- a/src/crypto/ecdsa/ecdsa_s390x_test.go +++ b/src/crypto/ecdsa/ecdsa_s390x_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build s390x -// +build s390x package ecdsa diff --git a/src/crypto/ed25519/internal/edwards25519/field/fe_amd64.go b/src/crypto/ed25519/internal/edwards25519/field/fe_amd64.go index 8fe583939f..363020bd6b 100644 --- a/src/crypto/ed25519/internal/edwards25519/field/fe_amd64.go +++ b/src/crypto/ed25519/internal/edwards25519/field/fe_amd64.go @@ -1,7 +1,6 @@ // Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT. //go:build amd64 && gc && !purego -// +build amd64,gc,!purego package field diff --git a/src/crypto/ed25519/internal/edwards25519/field/fe_amd64_noasm.go b/src/crypto/ed25519/internal/edwards25519/field/fe_amd64_noasm.go index ddb6c9b8f7..9da280d1d8 100644 --- a/src/crypto/ed25519/internal/edwards25519/field/fe_amd64_noasm.go +++ b/src/crypto/ed25519/internal/edwards25519/field/fe_amd64_noasm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !amd64 || !gc || purego -// +build !amd64 !gc purego package field diff --git a/src/crypto/ed25519/internal/edwards25519/field/fe_arm64.go b/src/crypto/ed25519/internal/edwards25519/field/fe_arm64.go index af459ef515..075fe9b925 100644 --- a/src/crypto/ed25519/internal/edwards25519/field/fe_arm64.go +++ b/src/crypto/ed25519/internal/edwards25519/field/fe_arm64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm64 && gc && !purego -// +build arm64,gc,!purego package field diff --git a/src/crypto/ed25519/internal/edwards25519/field/fe_arm64_noasm.go b/src/crypto/ed25519/internal/edwards25519/field/fe_arm64_noasm.go index 234a5b2e5d..fc029ac12d 100644 --- a/src/crypto/ed25519/internal/edwards25519/field/fe_arm64_noasm.go +++ b/src/crypto/ed25519/internal/edwards25519/field/fe_arm64_noasm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !arm64 || !gc || purego -// +build !arm64 !gc purego package field diff --git a/src/crypto/elliptic/export_generate.go b/src/crypto/elliptic/export_generate.go index 5fe3025cf8..f15b302d8c 100644 --- a/src/crypto/elliptic/export_generate.go +++ b/src/crypto/elliptic/export_generate.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build tablegen -// +build tablegen package elliptic diff --git a/src/crypto/elliptic/fuzz_test.go b/src/crypto/elliptic/fuzz_test.go index 8ff3bf3cc2..2b5ddae1d9 100644 --- a/src/crypto/elliptic/fuzz_test.go +++ b/src/crypto/elliptic/fuzz_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 || arm64 || ppc64le -// +build amd64 arm64 ppc64le package elliptic diff --git a/src/crypto/elliptic/gen_p256_table.go b/src/crypto/elliptic/gen_p256_table.go index cdcddcb736..54aafa2c38 100644 --- a/src/crypto/elliptic/gen_p256_table.go +++ b/src/crypto/elliptic/gen_p256_table.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore package main diff --git a/src/crypto/elliptic/p256.go b/src/crypto/elliptic/p256.go index b2b12c8f13..7747de7a50 100644 --- a/src/crypto/elliptic/p256.go +++ b/src/crypto/elliptic/p256.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !amd64 && !arm64 -// +build !amd64,!arm64 package elliptic diff --git a/src/crypto/elliptic/p256_asm.go b/src/crypto/elliptic/p256_asm.go index d46b809125..ff0c1596aa 100644 --- a/src/crypto/elliptic/p256_asm.go +++ b/src/crypto/elliptic/p256_asm.go @@ -11,7 +11,6 @@ // https://eprint.iacr.org/2013/816.pdf //go:build amd64 || arm64 -// +build amd64 arm64 package elliptic diff --git a/src/crypto/elliptic/p256_asm_table.go b/src/crypto/elliptic/p256_asm_table.go index 7f81cb6b3f..ad2c6c2c51 100644 --- a/src/crypto/elliptic/p256_asm_table.go +++ b/src/crypto/elliptic/p256_asm_table.go @@ -5,7 +5,6 @@ // Generated by gen_p256_table.go. DO NOT EDIT. //go:build amd64 || arm64 -// +build amd64 arm64 package elliptic diff --git a/src/crypto/elliptic/p256_asm_table_test.go b/src/crypto/elliptic/p256_asm_table_test.go index d704dae299..6abd8cb11b 100644 --- a/src/crypto/elliptic/p256_asm_table_test.go +++ b/src/crypto/elliptic/p256_asm_table_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 || arm64 -// +build amd64 arm64 package elliptic diff --git a/src/crypto/elliptic/p256_generic.go b/src/crypto/elliptic/p256_generic.go index 25762a8f76..7f8fab5398 100644 --- a/src/crypto/elliptic/p256_generic.go +++ b/src/crypto/elliptic/p256_generic.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !amd64 && !s390x && !arm64 && !ppc64le -// +build !amd64,!s390x,!arm64,!ppc64le package elliptic diff --git a/src/crypto/elliptic/p256_ppc64le.go b/src/crypto/elliptic/p256_ppc64le.go index 40d9ed9d40..e9a6a067a2 100644 --- a/src/crypto/elliptic/p256_ppc64le.go +++ b/src/crypto/elliptic/p256_ppc64le.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64le -// +build ppc64le package elliptic diff --git a/src/crypto/elliptic/p256_s390x.go b/src/crypto/elliptic/p256_s390x.go index 91e613b631..735e9f57f1 100644 --- a/src/crypto/elliptic/p256_s390x.go +++ b/src/crypto/elliptic/p256_s390x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build s390x -// +build s390x package elliptic diff --git a/src/crypto/internal/subtle/aliasing.go b/src/crypto/internal/subtle/aliasing.go index 86e0f3cfe7..16e2fcab12 100644 --- a/src/crypto/internal/subtle/aliasing.go +++ b/src/crypto/internal/subtle/aliasing.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !appengine -// +build !appengine // Package subtle implements functions that are often useful in cryptographic // code but require careful thought to use correctly. diff --git a/src/crypto/internal/subtle/aliasing_appengine.go b/src/crypto/internal/subtle/aliasing_appengine.go index 35b442f7a2..90ac4b61cc 100644 --- a/src/crypto/internal/subtle/aliasing_appengine.go +++ b/src/crypto/internal/subtle/aliasing_appengine.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build appengine -// +build appengine // Package subtle implements functions that are often useful in cryptographic // code but require careful thought to use correctly. diff --git a/src/crypto/md5/gen.go b/src/crypto/md5/gen.go index 29729fad01..cd2700a5cf 100644 --- a/src/crypto/md5/gen.go +++ b/src/crypto/md5/gen.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore // This program generates md5block.go // Invoke as diff --git a/src/crypto/md5/md5block_decl.go b/src/crypto/md5/md5block_decl.go index bc2d58c069..6716a0c9db 100644 --- a/src/crypto/md5/md5block_decl.go +++ b/src/crypto/md5/md5block_decl.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 || 386 || arm || ppc64le || ppc64 || s390x || arm64 -// +build amd64 386 arm ppc64le ppc64 s390x arm64 package md5 diff --git a/src/crypto/md5/md5block_generic.go b/src/crypto/md5/md5block_generic.go index 23ed75304f..c929c2b84a 100644 --- a/src/crypto/md5/md5block_generic.go +++ b/src/crypto/md5/md5block_generic.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !amd64 && !386 && !arm && !ppc64le && !ppc64 && !s390x && !arm64 -// +build !amd64,!386,!arm,!ppc64le,!ppc64,!s390x,!arm64 package md5 diff --git a/src/crypto/rand/eagain.go b/src/crypto/rand/eagain.go index 85d4d9d47f..f018e75931 100644 --- a/src/crypto/rand/eagain.go +++ b/src/crypto/rand/eagain.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package rand diff --git a/src/crypto/rand/rand_batched.go b/src/crypto/rand/rand_batched.go index d7c5bf3562..3e8e620382 100644 --- a/src/crypto/rand/rand_batched.go +++ b/src/crypto/rand/rand_batched.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux || freebsd || dragonfly || solaris -// +build linux freebsd dragonfly solaris package rand diff --git a/src/crypto/rand/rand_batched_test.go b/src/crypto/rand/rand_batched_test.go index 2d20922c82..28e45aa689 100644 --- a/src/crypto/rand/rand_batched_test.go +++ b/src/crypto/rand/rand_batched_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux || freebsd || dragonfly || solaris -// +build linux freebsd dragonfly solaris package rand diff --git a/src/crypto/rand/rand_getentropy.go b/src/crypto/rand/rand_getentropy.go index dd725372ad..2bf2f52032 100644 --- a/src/crypto/rand/rand_getentropy.go +++ b/src/crypto/rand/rand_getentropy.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build (darwin && !ios) || openbsd -// +build darwin,!ios openbsd package rand diff --git a/src/crypto/rand/rand_js.go b/src/crypto/rand/rand_js.go index 7ddc2b6169..91e69fae5d 100644 --- a/src/crypto/rand/rand_js.go +++ b/src/crypto/rand/rand_js.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm package rand diff --git a/src/crypto/rand/rand_unix.go b/src/crypto/rand/rand_unix.go index 81277eb6a5..40347874c5 100644 --- a/src/crypto/rand/rand_unix.go +++ b/src/crypto/rand/rand_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || plan9 || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd plan9 solaris // Unix cryptographically secure pseudorandom number // generator. diff --git a/src/crypto/sha1/fallback_test.go b/src/crypto/sha1/fallback_test.go index 4bb8b3324f..45d1f57d39 100644 --- a/src/crypto/sha1/fallback_test.go +++ b/src/crypto/sha1/fallback_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build s390x -// +build s390x package sha1 diff --git a/src/crypto/sha1/issue15617_test.go b/src/crypto/sha1/issue15617_test.go index 436f78c745..df4e28f64e 100644 --- a/src/crypto/sha1/issue15617_test.go +++ b/src/crypto/sha1/issue15617_test.go @@ -1,6 +1,4 @@ //go:build amd64 && (linux || darwin) -// +build amd64 -// +build linux darwin // Copyright 2016 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/src/crypto/sha1/sha1block_decl.go b/src/crypto/sha1/sha1block_decl.go index 93054efa7c..518a4b6b67 100644 --- a/src/crypto/sha1/sha1block_decl.go +++ b/src/crypto/sha1/sha1block_decl.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm || 386 || s390x -// +build arm 386 s390x package sha1 diff --git a/src/crypto/sha1/sha1block_generic.go b/src/crypto/sha1/sha1block_generic.go index 105aa31832..ba35155d0b 100644 --- a/src/crypto/sha1/sha1block_generic.go +++ b/src/crypto/sha1/sha1block_generic.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !amd64 && !386 && !arm && !s390x && !arm64 -// +build !amd64,!386,!arm,!s390x,!arm64 package sha1 diff --git a/src/crypto/sha256/fallback_test.go b/src/crypto/sha256/fallback_test.go index 7ce88cbb2a..3f561aadd6 100644 --- a/src/crypto/sha256/fallback_test.go +++ b/src/crypto/sha256/fallback_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build s390x -// +build s390x package sha256 diff --git a/src/crypto/sha256/sha256block_decl.go b/src/crypto/sha256/sha256block_decl.go index a6bb396f13..c9c1194487 100644 --- a/src/crypto/sha256/sha256block_decl.go +++ b/src/crypto/sha256/sha256block_decl.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build 386 || amd64 || s390x || ppc64le -// +build 386 amd64 s390x ppc64le package sha256 diff --git a/src/crypto/sha256/sha256block_generic.go b/src/crypto/sha256/sha256block_generic.go index 0f2bf8b231..a8878c2eee 100644 --- a/src/crypto/sha256/sha256block_generic.go +++ b/src/crypto/sha256/sha256block_generic.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !amd64 && !386 && !s390x && !ppc64le && !arm64 -// +build !amd64,!386,!s390x,!ppc64le,!arm64 package sha256 diff --git a/src/crypto/sha512/fallback_test.go b/src/crypto/sha512/fallback_test.go index faf732670a..db5b13c38c 100644 --- a/src/crypto/sha512/fallback_test.go +++ b/src/crypto/sha512/fallback_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build s390x -// +build s390x package sha512 diff --git a/src/crypto/sha512/sha512block_amd64.go b/src/crypto/sha512/sha512block_amd64.go index e2386f29ab..8da3e1473f 100644 --- a/src/crypto/sha512/sha512block_amd64.go +++ b/src/crypto/sha512/sha512block_amd64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 -// +build amd64 package sha512 diff --git a/src/crypto/sha512/sha512block_decl.go b/src/crypto/sha512/sha512block_decl.go index 6c22f44801..c6dcdf5db6 100644 --- a/src/crypto/sha512/sha512block_decl.go +++ b/src/crypto/sha512/sha512block_decl.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build s390x || ppc64le -// +build s390x ppc64le package sha512 diff --git a/src/crypto/sha512/sha512block_generic.go b/src/crypto/sha512/sha512block_generic.go index 865a7356f1..62ea237867 100644 --- a/src/crypto/sha512/sha512block_generic.go +++ b/src/crypto/sha512/sha512block_generic.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !amd64 && !s390x && !ppc64le -// +build !amd64,!s390x,!ppc64le package sha512 diff --git a/src/crypto/tls/generate_cert.go b/src/crypto/tls/generate_cert.go index 7ea90f8a7b..58fdd025db 100644 --- a/src/crypto/tls/generate_cert.go +++ b/src/crypto/tls/generate_cert.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore // Generate a self-signed X.509 certificate for a TLS server. Outputs to // 'cert.pem' and 'key.pem' and will overwrite existing files. diff --git a/src/crypto/tls/handshake_unix_test.go b/src/crypto/tls/handshake_unix_test.go index 19fc698676..b61e7c24ef 100644 --- a/src/crypto/tls/handshake_unix_test.go +++ b/src/crypto/tls/handshake_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package tls diff --git a/src/crypto/x509/internal/macos/corefoundation.go b/src/crypto/x509/internal/macos/corefoundation.go index fcfbc1e561..a91131ac98 100644 --- a/src/crypto/x509/internal/macos/corefoundation.go +++ b/src/crypto/x509/internal/macos/corefoundation.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin && !ios -// +build darwin,!ios // Package macOS provides cgo-less wrappers for Core Foundation and // Security.framework, similarly to how package syscall provides access to diff --git a/src/crypto/x509/internal/macos/security.go b/src/crypto/x509/internal/macos/security.go index 0f6fa42b7b..a560248e8b 100644 --- a/src/crypto/x509/internal/macos/security.go +++ b/src/crypto/x509/internal/macos/security.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin && !ios -// +build darwin,!ios package macOS diff --git a/src/crypto/x509/root_bsd.go b/src/crypto/x509/root_bsd.go index 6712ea32a6..8ac205faa9 100644 --- a/src/crypto/x509/root_bsd.go +++ b/src/crypto/x509/root_bsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd || netbsd || openbsd -// +build dragonfly freebsd netbsd openbsd package x509 diff --git a/src/crypto/x509/root_darwin.go b/src/crypto/x509/root_darwin.go index 05593bb105..164ad9dc77 100644 --- a/src/crypto/x509/root_darwin.go +++ b/src/crypto/x509/root_darwin.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !ios -// +build !ios package x509 diff --git a/src/crypto/x509/root_ios.go b/src/crypto/x509/root_ios.go index 9bc62f8abb..c5e3fc0b72 100644 --- a/src/crypto/x509/root_ios.go +++ b/src/crypto/x509/root_ios.go @@ -2,7 +2,6 @@ // Update the version in root.go and regenerate with "go generate". //go:build ios && !x509omitbundledroots -// +build ios,!x509omitbundledroots package x509 diff --git a/src/crypto/x509/root_ios_gen.go b/src/crypto/x509/root_ios_gen.go index 3c98de5bb6..15eb1592ca 100644 --- a/src/crypto/x509/root_ios_gen.go +++ b/src/crypto/x509/root_ios_gen.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore // Generates root_ios.go. // diff --git a/src/crypto/x509/root_js.go b/src/crypto/x509/root_js.go index f2c2c0af38..9593038517 100644 --- a/src/crypto/x509/root_js.go +++ b/src/crypto/x509/root_js.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm package x509 diff --git a/src/crypto/x509/root_omit.go b/src/crypto/x509/root_omit.go index 81f2f112d0..299d74835e 100644 --- a/src/crypto/x509/root_omit.go +++ b/src/crypto/x509/root_omit.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build ((darwin && arm64) || (darwin && amd64 && ios)) && x509omitbundledroots -// +build darwin,arm64 darwin,amd64,ios -// +build x509omitbundledroots // This file provides the loadSystemRoots func when the // "x509omitbundledroots" build tag has disabled bundling a copy, diff --git a/src/crypto/x509/root_omit_test.go b/src/crypto/x509/root_omit_test.go index 158bd7f91a..1709e2ea8b 100644 --- a/src/crypto/x509/root_omit_test.go +++ b/src/crypto/x509/root_omit_test.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build ((darwin && arm64) || (darwin && amd64 && ios)) && x509omitbundledroots -// +build darwin,arm64 darwin,amd64,ios -// +build x509omitbundledroots package x509 diff --git a/src/crypto/x509/root_plan9.go b/src/crypto/x509/root_plan9.go index 2bdb2fe713..3bd06fe50d 100644 --- a/src/crypto/x509/root_plan9.go +++ b/src/crypto/x509/root_plan9.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build plan9 -// +build plan9 package x509 diff --git a/src/crypto/x509/root_unix.go b/src/crypto/x509/root_unix.go index dede825edd..aa54f891ca 100644 --- a/src/crypto/x509/root_unix.go +++ b/src/crypto/x509/root_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris -// +build aix dragonfly freebsd js,wasm linux netbsd openbsd solaris package x509 diff --git a/src/crypto/x509/root_unix_test.go b/src/crypto/x509/root_unix_test.go index 7118f12d74..7197a0de3b 100644 --- a/src/crypto/x509/root_unix_test.go +++ b/src/crypto/x509/root_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build dragonfly freebsd linux netbsd openbsd solaris package x509 diff --git a/src/crypto/x509/x509_test_import.go b/src/crypto/x509/x509_test_import.go index ef3ee807bf..2474e3d810 100644 --- a/src/crypto/x509/x509_test_import.go +++ b/src/crypto/x509/x509_test_import.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore // This file is run by the x509 tests to ensure that a program with minimal // imports can sign certificates without errors resulting from missing hash diff --git a/src/encoding/csv/fuzz.go b/src/encoding/csv/fuzz.go index a03fa83d8c..5f5cdfcbf8 100644 --- a/src/encoding/csv/fuzz.go +++ b/src/encoding/csv/fuzz.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gofuzz -// +build gofuzz package csv diff --git a/src/encoding/gob/debug.go b/src/encoding/gob/debug.go index 5965fea921..5ceb2bfac7 100644 --- a/src/encoding/gob/debug.go +++ b/src/encoding/gob/debug.go @@ -4,7 +4,6 @@ // Delete the next line to include in the gob package. //go:build ignore -// +build ignore package gob diff --git a/src/encoding/gob/decgen.go b/src/encoding/gob/decgen.go index 994be877d9..e40816eb86 100644 --- a/src/encoding/gob/decgen.go +++ b/src/encoding/gob/decgen.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore // encgen writes the helper functions for encoding. Intended to be // used with go generate; see the invocation in encode.go. diff --git a/src/encoding/gob/dump.go b/src/encoding/gob/dump.go index 8c0bbc4ff2..f4b1bebfba 100644 --- a/src/encoding/gob/dump.go +++ b/src/encoding/gob/dump.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore package main diff --git a/src/encoding/gob/encgen.go b/src/encoding/gob/encgen.go index b562da177d..e5f68786a0 100644 --- a/src/encoding/gob/encgen.go +++ b/src/encoding/gob/encgen.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore // encgen writes the helper functions for encoding. Intended to be // used with go generate; see the invocation in encode.go. diff --git a/src/encoding/json/fuzz.go b/src/encoding/json/fuzz.go index d3fa2d1113..f00898a798 100644 --- a/src/encoding/json/fuzz.go +++ b/src/encoding/json/fuzz.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gofuzz -// +build gofuzz package json diff --git a/src/go/build/gc.go b/src/go/build/gc.go index e16e186e0d..434991f66e 100644 --- a/src/go/build/gc.go +++ b/src/go/build/gc.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gc -// +build gc package build diff --git a/src/go/build/gccgo.go b/src/go/build/gccgo.go index c8ec7041fb..f806729f7e 100644 --- a/src/go/build/gccgo.go +++ b/src/go/build/gccgo.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gccgo -// +build gccgo package build diff --git a/src/go/doc/headscan.go b/src/go/doc/headscan.go index df54b4bd61..320895e43a 100644 --- a/src/go/doc/headscan.go +++ b/src/go/doc/headscan.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore /* The headscan command extracts comment headings from package files; diff --git a/src/go/types/example_test.go b/src/go/types/example_test.go index 32a25a4117..2702567486 100644 --- a/src/go/types/example_test.go +++ b/src/go/types/example_test.go @@ -6,7 +6,6 @@ // access to compiled packages for import. // //go:build !arm && !arm64 -// +build !arm,!arm64 package types_test diff --git a/src/go/types/gotype.go b/src/go/types/gotype.go index ca1d42c14d..1126b73810 100644 --- a/src/go/types/gotype.go +++ b/src/go/types/gotype.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore // Build this command explicitly: go build gotype.go diff --git a/src/hash/crc32/crc32_otherarch.go b/src/hash/crc32/crc32_otherarch.go index 936e5bf3e0..762515257d 100644 --- a/src/hash/crc32/crc32_otherarch.go +++ b/src/hash/crc32/crc32_otherarch.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !amd64 && !s390x && !ppc64le && !arm64 -// +build !amd64,!s390x,!ppc64le,!arm64 package crc32 diff --git a/src/hash/crc32/gen_const_ppc64le.go b/src/hash/crc32/gen_const_ppc64le.go index c98454c685..2f15a60b50 100644 --- a/src/hash/crc32/gen_const_ppc64le.go +++ b/src/hash/crc32/gen_const_ppc64le.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore // Generate the constant table associated with the poly used by the // vpmsumd crc32 algorithm. diff --git a/src/html/fuzz.go b/src/html/fuzz.go index ecaf4f9069..cd70f97106 100644 --- a/src/html/fuzz.go +++ b/src/html/fuzz.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gofuzz -// +build gofuzz package html diff --git a/src/image/color/palette/gen.go b/src/image/color/palette/gen.go index 7bb257d865..be46c57020 100644 --- a/src/image/color/palette/gen.go +++ b/src/image/color/palette/gen.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore package main diff --git a/src/image/internal/imageutil/gen.go b/src/image/internal/imageutil/gen.go index 38f41303fa..65e1e30b64 100644 --- a/src/image/internal/imageutil/gen.go +++ b/src/image/internal/imageutil/gen.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore package main diff --git a/src/image/png/fuzz.go b/src/image/png/fuzz.go index 6508533f44..688b6c9936 100644 --- a/src/image/png/fuzz.go +++ b/src/image/png/fuzz.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gofuzz -// +build gofuzz package png diff --git a/src/index/suffixarray/gen.go b/src/index/suffixarray/gen.go index 3bc9b1e2ae..d6eb32e2ae 100644 --- a/src/index/suffixarray/gen.go +++ b/src/index/suffixarray/gen.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore // Gen generates sais2.go by duplicating functions in sais.go // using different input types. diff --git a/src/internal/abi/abi_arm64.go b/src/internal/abi/abi_arm64.go index 7544d7506e..5c3dd6cbe2 100644 --- a/src/internal/abi/abi_arm64.go +++ b/src/internal/abi/abi_arm64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build goexperiment.regabireflect -// +build goexperiment.regabireflect package abi diff --git a/src/internal/abi/abi_generic.go b/src/internal/abi/abi_generic.go index e8f94f805f..a36745f402 100644 --- a/src/internal/abi/abi_generic.go +++ b/src/internal/abi/abi_generic.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !goexperiment.regabireflect && !amd64 -// +build !goexperiment.regabireflect,!amd64 package abi diff --git a/src/internal/abi/abi_ppc64x.go b/src/internal/abi/abi_ppc64x.go index e38653224a..d47271d1a1 100644 --- a/src/internal/abi/abi_ppc64x.go +++ b/src/internal/abi/abi_ppc64x.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build goexperiment.regabireflect && (ppc64 || ppc64le) -// +build goexperiment.regabireflect -// +build ppc64 ppc64le package abi diff --git a/src/internal/bytealg/compare_generic.go b/src/internal/bytealg/compare_generic.go index 0690d0cf31..eaea168f2d 100644 --- a/src/internal/bytealg/compare_generic.go +++ b/src/internal/bytealg/compare_generic.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !386 && !amd64 && !s390x && !arm && !arm64 && !ppc64 && !ppc64le && !mips && !mipsle && !wasm && !mips64 && !mips64le -// +build !386,!amd64,!s390x,!arm,!arm64,!ppc64,!ppc64le,!mips,!mipsle,!wasm,!mips64,!mips64le package bytealg diff --git a/src/internal/bytealg/compare_native.go b/src/internal/bytealg/compare_native.go index baa188ff7a..21ff8fe786 100644 --- a/src/internal/bytealg/compare_native.go +++ b/src/internal/bytealg/compare_native.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build 386 || amd64 || s390x || arm || arm64 || ppc64 || ppc64le || mips || mipsle || wasm || mips64 || mips64le -// +build 386 amd64 s390x arm arm64 ppc64 ppc64le mips mipsle wasm mips64 mips64le package bytealg diff --git a/src/internal/bytealg/count_generic.go b/src/internal/bytealg/count_generic.go index 1891d29b24..932a7c584c 100644 --- a/src/internal/bytealg/count_generic.go +++ b/src/internal/bytealg/count_generic.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !amd64 && !arm && !arm64 && !ppc64le && !ppc64 && !riscv64 && !s390x -// +build !amd64,!arm,!arm64,!ppc64le,!ppc64,!riscv64,!s390x package bytealg diff --git a/src/internal/bytealg/count_native.go b/src/internal/bytealg/count_native.go index a19a6f8223..90189c9fe0 100644 --- a/src/internal/bytealg/count_native.go +++ b/src/internal/bytealg/count_native.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 || arm || arm64 || ppc64le || ppc64 || riscv64 || s390x -// +build amd64 arm arm64 ppc64le ppc64 riscv64 s390x package bytealg diff --git a/src/internal/bytealg/index_generic.go b/src/internal/bytealg/index_generic.go index 0a6eb90d2d..a59e32938e 100644 --- a/src/internal/bytealg/index_generic.go +++ b/src/internal/bytealg/index_generic.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !amd64 && !arm64 && !s390x && !ppc64le && !ppc64 -// +build !amd64,!arm64,!s390x,!ppc64le,!ppc64 package bytealg diff --git a/src/internal/bytealg/index_native.go b/src/internal/bytealg/index_native.go index 9547a5d8e2..6e4a2f39e4 100644 --- a/src/internal/bytealg/index_native.go +++ b/src/internal/bytealg/index_native.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 || arm64 || s390x || ppc64le || ppc64 -// +build amd64 arm64 s390x ppc64le ppc64 package bytealg diff --git a/src/internal/bytealg/index_ppc64x.go b/src/internal/bytealg/index_ppc64x.go index c9b2b5a59f..ab3cbe5e96 100644 --- a/src/internal/bytealg/index_ppc64x.go +++ b/src/internal/bytealg/index_ppc64x.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (aix || linux) && (ppc64 || ppc64le) -// +build aix linux -// +build ppc64 ppc64le package bytealg diff --git a/src/internal/bytealg/indexbyte_generic.go b/src/internal/bytealg/indexbyte_generic.go index 6ef639fafd..0a45f90384 100644 --- a/src/internal/bytealg/indexbyte_generic.go +++ b/src/internal/bytealg/indexbyte_generic.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !386 && !amd64 && !s390x && !arm && !arm64 && !ppc64 && !ppc64le && !mips && !mipsle && !mips64 && !mips64le && !riscv64 && !wasm -// +build !386,!amd64,!s390x,!arm,!arm64,!ppc64,!ppc64le,!mips,!mipsle,!mips64,!mips64le,!riscv64,!wasm package bytealg diff --git a/src/internal/bytealg/indexbyte_native.go b/src/internal/bytealg/indexbyte_native.go index 965f38fe52..2101021e2d 100644 --- a/src/internal/bytealg/indexbyte_native.go +++ b/src/internal/bytealg/indexbyte_native.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build 386 || amd64 || s390x || arm || arm64 || ppc64 || ppc64le || mips || mipsle || mips64 || mips64le || riscv64 || wasm -// +build 386 amd64 s390x arm arm64 ppc64 ppc64le mips mipsle mips64 mips64le riscv64 wasm package bytealg diff --git a/src/internal/cpu/cpu_arm64_android.go b/src/internal/cpu/cpu_arm64_android.go index ac6eee54b2..fbdf7baca2 100644 --- a/src/internal/cpu/cpu_arm64_android.go +++ b/src/internal/cpu/cpu_arm64_android.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm64 -// +build arm64 package cpu diff --git a/src/internal/cpu/cpu_arm64_darwin.go b/src/internal/cpu/cpu_arm64_darwin.go index ce1b250a18..730e14caff 100644 --- a/src/internal/cpu/cpu_arm64_darwin.go +++ b/src/internal/cpu/cpu_arm64_darwin.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm64 && darwin && !ios -// +build arm64,darwin,!ios package cpu diff --git a/src/internal/cpu/cpu_arm64_freebsd.go b/src/internal/cpu/cpu_arm64_freebsd.go index 8c481370da..c25e021c68 100644 --- a/src/internal/cpu/cpu_arm64_freebsd.go +++ b/src/internal/cpu/cpu_arm64_freebsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm64 -// +build arm64 package cpu diff --git a/src/internal/cpu/cpu_arm64_hwcap.go b/src/internal/cpu/cpu_arm64_hwcap.go index 8ac04fd8f9..0baa39f9cf 100644 --- a/src/internal/cpu/cpu_arm64_hwcap.go +++ b/src/internal/cpu/cpu_arm64_hwcap.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm64 && linux -// +build arm64,linux package cpu diff --git a/src/internal/cpu/cpu_arm64_linux.go b/src/internal/cpu/cpu_arm64_linux.go index c3a3f9a8e9..d746bdb063 100644 --- a/src/internal/cpu/cpu_arm64_linux.go +++ b/src/internal/cpu/cpu_arm64_linux.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm64 && linux && !android -// +build arm64,linux,!android package cpu diff --git a/src/internal/cpu/cpu_arm64_other.go b/src/internal/cpu/cpu_arm64_other.go index e8b5d529a4..d313648cb7 100644 --- a/src/internal/cpu/cpu_arm64_other.go +++ b/src/internal/cpu/cpu_arm64_other.go @@ -3,11 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm64 && !linux && !freebsd && !android && (!darwin || ios) -// +build arm64 -// +build !linux -// +build !freebsd -// +build !android -// +build !darwin ios package cpu diff --git a/src/internal/cpu/cpu_mips64x.go b/src/internal/cpu/cpu_mips64x.go index d2f9d4499b..c452ffd8b3 100644 --- a/src/internal/cpu/cpu_mips64x.go +++ b/src/internal/cpu/cpu_mips64x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips64 || mips64le -// +build mips64 mips64le package cpu diff --git a/src/internal/cpu/cpu_no_name.go b/src/internal/cpu/cpu_no_name.go index 8d563b536c..37de951ba6 100644 --- a/src/internal/cpu/cpu_no_name.go +++ b/src/internal/cpu/cpu_no_name.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !386 && !amd64 -// +build !386,!amd64 package cpu diff --git a/src/internal/cpu/cpu_ppc64x.go b/src/internal/cpu/cpu_ppc64x.go index 2e7fd3ebb9..83687d6ed3 100644 --- a/src/internal/cpu/cpu_ppc64x.go +++ b/src/internal/cpu/cpu_ppc64x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le package cpu diff --git a/src/internal/cpu/cpu_ppc64x_aix.go b/src/internal/cpu/cpu_ppc64x_aix.go index 3d17a9c730..d518edcf49 100644 --- a/src/internal/cpu/cpu_ppc64x_aix.go +++ b/src/internal/cpu/cpu_ppc64x_aix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le package cpu diff --git a/src/internal/cpu/cpu_ppc64x_linux.go b/src/internal/cpu/cpu_ppc64x_linux.go index b7c7345111..7999656f01 100644 --- a/src/internal/cpu/cpu_ppc64x_linux.go +++ b/src/internal/cpu/cpu_ppc64x_linux.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le package cpu diff --git a/src/internal/cpu/cpu_x86.go b/src/internal/cpu/cpu_x86.go index 1582e832a4..81d5ceed61 100644 --- a/src/internal/cpu/cpu_x86.go +++ b/src/internal/cpu/cpu_x86.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build 386 || amd64 -// +build 386 amd64 package cpu diff --git a/src/internal/cpu/cpu_x86_test.go b/src/internal/cpu/cpu_x86_test.go index de1c5fb3b0..0fef065f20 100644 --- a/src/internal/cpu/cpu_x86_test.go +++ b/src/internal/cpu/cpu_x86_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build 386 || amd64 -// +build 386 amd64 package cpu_test diff --git a/src/internal/fuzz/minimize_test.go b/src/internal/fuzz/minimize_test.go index dd76baff51..13385e14d6 100644 --- a/src/internal/fuzz/minimize_test.go +++ b/src/internal/fuzz/minimize_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || linux || windows -// +build darwin linux windows package fuzz diff --git a/src/internal/fuzz/sys_posix.go b/src/internal/fuzz/sys_posix.go index ca6b1456e2..89c86c1ebb 100644 --- a/src/internal/fuzz/sys_posix.go +++ b/src/internal/fuzz/sys_posix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || linux -// +build darwin linux package fuzz diff --git a/src/internal/fuzz/sys_unimplemented.go b/src/internal/fuzz/sys_unimplemented.go index 827e36cf32..05954bb07f 100644 --- a/src/internal/fuzz/sys_unimplemented.go +++ b/src/internal/fuzz/sys_unimplemented.go @@ -4,7 +4,6 @@ // TODO(jayconrod): support more platforms. //go:build !darwin && !linux && !windows -// +build !darwin,!linux,!windows package fuzz diff --git a/src/internal/fuzz/trace.go b/src/internal/fuzz/trace.go index ab0aeb41bd..cab0838fab 100644 --- a/src/internal/fuzz/trace.go +++ b/src/internal/fuzz/trace.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !libfuzzer -// +build !libfuzzer package fuzz diff --git a/src/internal/goarch/gengoarch.go b/src/internal/goarch/gengoarch.go index af15518ad8..d146cc5bc9 100644 --- a/src/internal/goarch/gengoarch.go +++ b/src/internal/goarch/gengoarch.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore package main diff --git a/src/internal/goarch/zgoarch_386.go b/src/internal/goarch/zgoarch_386.go index 364367722f..4a9b0e67c4 100644 --- a/src/internal/goarch/zgoarch_386.go +++ b/src/internal/goarch/zgoarch_386.go @@ -1,7 +1,6 @@ // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build 386 -// +build 386 package goarch diff --git a/src/internal/goarch/zgoarch_amd64.go b/src/internal/goarch/zgoarch_amd64.go index 8169580857..7926392b77 100644 --- a/src/internal/goarch/zgoarch_amd64.go +++ b/src/internal/goarch/zgoarch_amd64.go @@ -1,7 +1,6 @@ // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build amd64 -// +build amd64 package goarch diff --git a/src/internal/goarch/zgoarch_arm.go b/src/internal/goarch/zgoarch_arm.go index edc69f3349..6c03b8b060 100644 --- a/src/internal/goarch/zgoarch_arm.go +++ b/src/internal/goarch/zgoarch_arm.go @@ -1,7 +1,6 @@ // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build arm -// +build arm package goarch diff --git a/src/internal/goarch/zgoarch_arm64.go b/src/internal/goarch/zgoarch_arm64.go index 0459376349..ad342d79c9 100644 --- a/src/internal/goarch/zgoarch_arm64.go +++ b/src/internal/goarch/zgoarch_arm64.go @@ -1,7 +1,6 @@ // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build arm64 -// +build arm64 package goarch diff --git a/src/internal/goarch/zgoarch_arm64be.go b/src/internal/goarch/zgoarch_arm64be.go index b9439c147e..0f26003090 100644 --- a/src/internal/goarch/zgoarch_arm64be.go +++ b/src/internal/goarch/zgoarch_arm64be.go @@ -1,7 +1,6 @@ // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build arm64be -// +build arm64be package goarch diff --git a/src/internal/goarch/zgoarch_armbe.go b/src/internal/goarch/zgoarch_armbe.go index bbb07603d6..6092fee751 100644 --- a/src/internal/goarch/zgoarch_armbe.go +++ b/src/internal/goarch/zgoarch_armbe.go @@ -1,7 +1,6 @@ // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build armbe -// +build armbe package goarch diff --git a/src/internal/goarch/zgoarch_loong64.go b/src/internal/goarch/zgoarch_loong64.go index 4d2cd70a00..21c67e1176 100644 --- a/src/internal/goarch/zgoarch_loong64.go +++ b/src/internal/goarch/zgoarch_loong64.go @@ -1,7 +1,6 @@ // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build loong64 -// +build loong64 package goarch diff --git a/src/internal/goarch/zgoarch_mips.go b/src/internal/goarch/zgoarch_mips.go index 25a8071727..0db1974655 100644 --- a/src/internal/goarch/zgoarch_mips.go +++ b/src/internal/goarch/zgoarch_mips.go @@ -1,7 +1,6 @@ // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build mips -// +build mips package goarch diff --git a/src/internal/goarch/zgoarch_mips64.go b/src/internal/goarch/zgoarch_mips64.go index 907ae30ec4..738806f0ae 100644 --- a/src/internal/goarch/zgoarch_mips64.go +++ b/src/internal/goarch/zgoarch_mips64.go @@ -1,7 +1,6 @@ // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build mips64 -// +build mips64 package goarch diff --git a/src/internal/goarch/zgoarch_mips64le.go b/src/internal/goarch/zgoarch_mips64le.go index 3f4c369d16..8de5beb881 100644 --- a/src/internal/goarch/zgoarch_mips64le.go +++ b/src/internal/goarch/zgoarch_mips64le.go @@ -1,7 +1,6 @@ // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build mips64le -// +build mips64le package goarch diff --git a/src/internal/goarch/zgoarch_mips64p32.go b/src/internal/goarch/zgoarch_mips64p32.go index d03e503c59..ea461bed70 100644 --- a/src/internal/goarch/zgoarch_mips64p32.go +++ b/src/internal/goarch/zgoarch_mips64p32.go @@ -1,7 +1,6 @@ // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build mips64p32 -// +build mips64p32 package goarch diff --git a/src/internal/goarch/zgoarch_mips64p32le.go b/src/internal/goarch/zgoarch_mips64p32le.go index bbaa010ada..15473ce6c7 100644 --- a/src/internal/goarch/zgoarch_mips64p32le.go +++ b/src/internal/goarch/zgoarch_mips64p32le.go @@ -1,7 +1,6 @@ // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build mips64p32le -// +build mips64p32le package goarch diff --git a/src/internal/goarch/zgoarch_mipsle.go b/src/internal/goarch/zgoarch_mipsle.go index b22be64d6e..4955142e87 100644 --- a/src/internal/goarch/zgoarch_mipsle.go +++ b/src/internal/goarch/zgoarch_mipsle.go @@ -1,7 +1,6 @@ // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build mipsle -// +build mipsle package goarch diff --git a/src/internal/goarch/zgoarch_ppc.go b/src/internal/goarch/zgoarch_ppc.go index ed50bf8275..ec01763b3c 100644 --- a/src/internal/goarch/zgoarch_ppc.go +++ b/src/internal/goarch/zgoarch_ppc.go @@ -1,7 +1,6 @@ // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build ppc -// +build ppc package goarch diff --git a/src/internal/goarch/zgoarch_ppc64.go b/src/internal/goarch/zgoarch_ppc64.go index 26b921d343..39be3925c8 100644 --- a/src/internal/goarch/zgoarch_ppc64.go +++ b/src/internal/goarch/zgoarch_ppc64.go @@ -1,7 +1,6 @@ // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build ppc64 -// +build ppc64 package goarch diff --git a/src/internal/goarch/zgoarch_ppc64le.go b/src/internal/goarch/zgoarch_ppc64le.go index de4fe0fb80..5f959e0e02 100644 --- a/src/internal/goarch/zgoarch_ppc64le.go +++ b/src/internal/goarch/zgoarch_ppc64le.go @@ -1,7 +1,6 @@ // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build ppc64le -// +build ppc64le package goarch diff --git a/src/internal/goarch/zgoarch_riscv.go b/src/internal/goarch/zgoarch_riscv.go index 3eff474467..8d81a14dd9 100644 --- a/src/internal/goarch/zgoarch_riscv.go +++ b/src/internal/goarch/zgoarch_riscv.go @@ -1,7 +1,6 @@ // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build riscv -// +build riscv package goarch diff --git a/src/internal/goarch/zgoarch_riscv64.go b/src/internal/goarch/zgoarch_riscv64.go index d99ab9dc29..1df989c2a6 100644 --- a/src/internal/goarch/zgoarch_riscv64.go +++ b/src/internal/goarch/zgoarch_riscv64.go @@ -1,7 +1,6 @@ // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build riscv64 -// +build riscv64 package goarch diff --git a/src/internal/goarch/zgoarch_s390.go b/src/internal/goarch/zgoarch_s390.go index 6d4ff71cc9..56815b9f43 100644 --- a/src/internal/goarch/zgoarch_s390.go +++ b/src/internal/goarch/zgoarch_s390.go @@ -1,7 +1,6 @@ // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build s390 -// +build s390 package goarch diff --git a/src/internal/goarch/zgoarch_s390x.go b/src/internal/goarch/zgoarch_s390x.go index 6c215060a3..e61e9bd593 100644 --- a/src/internal/goarch/zgoarch_s390x.go +++ b/src/internal/goarch/zgoarch_s390x.go @@ -1,7 +1,6 @@ // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build s390x -// +build s390x package goarch diff --git a/src/internal/goarch/zgoarch_sparc.go b/src/internal/goarch/zgoarch_sparc.go index 029e790fb0..ee5b746566 100644 --- a/src/internal/goarch/zgoarch_sparc.go +++ b/src/internal/goarch/zgoarch_sparc.go @@ -1,7 +1,6 @@ // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build sparc -// +build sparc package goarch diff --git a/src/internal/goarch/zgoarch_sparc64.go b/src/internal/goarch/zgoarch_sparc64.go index bcd7b6f7df..519aaa10c1 100644 --- a/src/internal/goarch/zgoarch_sparc64.go +++ b/src/internal/goarch/zgoarch_sparc64.go @@ -1,7 +1,6 @@ // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build sparc64 -// +build sparc64 package goarch diff --git a/src/internal/goarch/zgoarch_wasm.go b/src/internal/goarch/zgoarch_wasm.go index 0816c85a11..25567a1b64 100644 --- a/src/internal/goarch/zgoarch_wasm.go +++ b/src/internal/goarch/zgoarch_wasm.go @@ -1,7 +1,6 @@ // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. //go:build wasm -// +build wasm package goarch diff --git a/src/internal/goos/gengoos.go b/src/internal/goos/gengoos.go index 1860cd700d..f8ddfcc7ff 100644 --- a/src/internal/goos/gengoos.go +++ b/src/internal/goos/gengoos.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore package main diff --git a/src/internal/goos/zgoos_aix.go b/src/internal/goos/zgoos_aix.go index 063e698b82..ff861550c4 100644 --- a/src/internal/goos/zgoos_aix.go +++ b/src/internal/goos/zgoos_aix.go @@ -1,7 +1,6 @@ // Code generated by gengoos.go using 'go generate'. DO NOT EDIT. //go:build aix -// +build aix package goos diff --git a/src/internal/goos/zgoos_android.go b/src/internal/goos/zgoos_android.go index e9e4864978..e8aaa12428 100644 --- a/src/internal/goos/zgoos_android.go +++ b/src/internal/goos/zgoos_android.go @@ -1,7 +1,6 @@ // Code generated by gengoos.go using 'go generate'. DO NOT EDIT. //go:build android -// +build android package goos diff --git a/src/internal/goos/zgoos_darwin.go b/src/internal/goos/zgoos_darwin.go index 309d6a2717..decdd49642 100644 --- a/src/internal/goos/zgoos_darwin.go +++ b/src/internal/goos/zgoos_darwin.go @@ -1,7 +1,6 @@ // Code generated by gengoos.go using 'go generate'. DO NOT EDIT. //go:build !ios && darwin -// +build !ios,darwin package goos diff --git a/src/internal/goos/zgoos_dragonfly.go b/src/internal/goos/zgoos_dragonfly.go index 4e8711b94c..2224baa230 100644 --- a/src/internal/goos/zgoos_dragonfly.go +++ b/src/internal/goos/zgoos_dragonfly.go @@ -1,7 +1,6 @@ // Code generated by gengoos.go using 'go generate'. DO NOT EDIT. //go:build dragonfly -// +build dragonfly package goos diff --git a/src/internal/goos/zgoos_freebsd.go b/src/internal/goos/zgoos_freebsd.go index f312bd1608..3ee5bf998e 100644 --- a/src/internal/goos/zgoos_freebsd.go +++ b/src/internal/goos/zgoos_freebsd.go @@ -1,7 +1,6 @@ // Code generated by gengoos.go using 'go generate'. DO NOT EDIT. //go:build freebsd -// +build freebsd package goos diff --git a/src/internal/goos/zgoos_hurd.go b/src/internal/goos/zgoos_hurd.go index 0f0dd28b81..8a3d34304d 100644 --- a/src/internal/goos/zgoos_hurd.go +++ b/src/internal/goos/zgoos_hurd.go @@ -1,7 +1,6 @@ // Code generated by gengoos.go using 'go generate'. DO NOT EDIT. //go:build hurd -// +build hurd package goos diff --git a/src/internal/goos/zgoos_illumos.go b/src/internal/goos/zgoos_illumos.go index 17e7c53a40..fc1b9a9e22 100644 --- a/src/internal/goos/zgoos_illumos.go +++ b/src/internal/goos/zgoos_illumos.go @@ -1,7 +1,6 @@ // Code generated by gengoos.go using 'go generate'. DO NOT EDIT. //go:build illumos -// +build illumos package goos diff --git a/src/internal/goos/zgoos_ios.go b/src/internal/goos/zgoos_ios.go index e4745ca413..746e769ef7 100644 --- a/src/internal/goos/zgoos_ios.go +++ b/src/internal/goos/zgoos_ios.go @@ -1,7 +1,6 @@ // Code generated by gengoos.go using 'go generate'. DO NOT EDIT. //go:build ios -// +build ios package goos diff --git a/src/internal/goos/zgoos_js.go b/src/internal/goos/zgoos_js.go index bd2417e9ce..6cf2a5d9e2 100644 --- a/src/internal/goos/zgoos_js.go +++ b/src/internal/goos/zgoos_js.go @@ -1,7 +1,6 @@ // Code generated by gengoos.go using 'go generate'. DO NOT EDIT. //go:build js -// +build js package goos diff --git a/src/internal/goos/zgoos_linux.go b/src/internal/goos/zgoos_linux.go index 476702f442..cb9d6e8afa 100644 --- a/src/internal/goos/zgoos_linux.go +++ b/src/internal/goos/zgoos_linux.go @@ -1,7 +1,6 @@ // Code generated by gengoos.go using 'go generate'. DO NOT EDIT. //go:build !android && linux -// +build !android,linux package goos diff --git a/src/internal/goos/zgoos_netbsd.go b/src/internal/goos/zgoos_netbsd.go index 97b7564bab..8285928d35 100644 --- a/src/internal/goos/zgoos_netbsd.go +++ b/src/internal/goos/zgoos_netbsd.go @@ -1,7 +1,6 @@ // Code generated by gengoos.go using 'go generate'. DO NOT EDIT. //go:build netbsd -// +build netbsd package goos diff --git a/src/internal/goos/zgoos_openbsd.go b/src/internal/goos/zgoos_openbsd.go index 384a96480d..3f739a4a2f 100644 --- a/src/internal/goos/zgoos_openbsd.go +++ b/src/internal/goos/zgoos_openbsd.go @@ -1,7 +1,6 @@ // Code generated by gengoos.go using 'go generate'. DO NOT EDIT. //go:build openbsd -// +build openbsd package goos diff --git a/src/internal/goos/zgoos_plan9.go b/src/internal/goos/zgoos_plan9.go index fcc279a79e..d4c1c651f7 100644 --- a/src/internal/goos/zgoos_plan9.go +++ b/src/internal/goos/zgoos_plan9.go @@ -1,7 +1,6 @@ // Code generated by gengoos.go using 'go generate'. DO NOT EDIT. //go:build plan9 -// +build plan9 package goos diff --git a/src/internal/goos/zgoos_solaris.go b/src/internal/goos/zgoos_solaris.go index 3f366cf710..69e3285ab6 100644 --- a/src/internal/goos/zgoos_solaris.go +++ b/src/internal/goos/zgoos_solaris.go @@ -1,7 +1,6 @@ // Code generated by gengoos.go using 'go generate'. DO NOT EDIT. //go:build !illumos && solaris -// +build !illumos,solaris package goos diff --git a/src/internal/goos/zgoos_windows.go b/src/internal/goos/zgoos_windows.go index dfa55339d3..16158be78b 100644 --- a/src/internal/goos/zgoos_windows.go +++ b/src/internal/goos/zgoos_windows.go @@ -1,7 +1,6 @@ // Code generated by gengoos.go using 'go generate'. DO NOT EDIT. //go:build windows -// +build windows package goos diff --git a/src/internal/goos/zgoos_zos.go b/src/internal/goos/zgoos_zos.go index 714f24963a..fb6165c7a1 100644 --- a/src/internal/goos/zgoos_zos.go +++ b/src/internal/goos/zgoos_zos.go @@ -1,7 +1,6 @@ // Code generated by gengoos.go using 'go generate'. DO NOT EDIT. //go:build zos -// +build zos package goos diff --git a/src/internal/goroot/gc.go b/src/internal/goroot/gc.go index 2338b78f3a..8c66cd13a8 100644 --- a/src/internal/goroot/gc.go +++ b/src/internal/goroot/gc.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gc -// +build gc package goroot diff --git a/src/internal/goroot/gccgo.go b/src/internal/goroot/gccgo.go index b1041da11d..62841222a7 100644 --- a/src/internal/goroot/gccgo.go +++ b/src/internal/goroot/gccgo.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gccgo -// +build gccgo package goroot diff --git a/src/internal/poll/errno_unix.go b/src/internal/poll/errno_unix.go index 55c548824f..c177519732 100644 --- a/src/internal/poll/errno_unix.go +++ b/src/internal/poll/errno_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package poll diff --git a/src/internal/poll/errno_windows.go b/src/internal/poll/errno_windows.go index c55f5f0df5..3679aa8c4c 100644 --- a/src/internal/poll/errno_windows.go +++ b/src/internal/poll/errno_windows.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows -// +build windows package poll diff --git a/src/internal/poll/error_stub_test.go b/src/internal/poll/error_stub_test.go index bcc25dd666..48e095254d 100644 --- a/src/internal/poll/error_stub_test.go +++ b/src/internal/poll/error_stub_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !linux -// +build !linux package poll_test diff --git a/src/internal/poll/export_posix_test.go b/src/internal/poll/export_posix_test.go index f59c1f6dfa..3fcafac002 100644 --- a/src/internal/poll/export_posix_test.go +++ b/src/internal/poll/export_posix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || windows -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows // Export guts for testing on posix. // Since testing imports os and os imports internal/poll, diff --git a/src/internal/poll/fcntl_js.go b/src/internal/poll/fcntl_js.go index 7bf0ddc792..0f42ef61a5 100644 --- a/src/internal/poll/fcntl_js.go +++ b/src/internal/poll/fcntl_js.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm package poll diff --git a/src/internal/poll/fcntl_libc.go b/src/internal/poll/fcntl_libc.go index cc609e48ad..f503d7a336 100644 --- a/src/internal/poll/fcntl_libc.go +++ b/src/internal/poll/fcntl_libc.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || solaris -// +build aix darwin solaris package poll diff --git a/src/internal/poll/fcntl_syscall.go b/src/internal/poll/fcntl_syscall.go index 8db5b66504..accff5e043 100644 --- a/src/internal/poll/fcntl_syscall.go +++ b/src/internal/poll/fcntl_syscall.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd || linux || netbsd || openbsd -// +build dragonfly freebsd linux netbsd openbsd package poll diff --git a/src/internal/poll/fd_fsync_posix.go b/src/internal/poll/fd_fsync_posix.go index 651a5ecd8b..6f17019e73 100644 --- a/src/internal/poll/fd_fsync_posix.go +++ b/src/internal/poll/fd_fsync_posix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris -// +build aix dragonfly freebsd js,wasm linux netbsd openbsd solaris package poll diff --git a/src/internal/poll/fd_poll_js.go b/src/internal/poll/fd_poll_js.go index 760e24802e..84bfcae633 100644 --- a/src/internal/poll/fd_poll_js.go +++ b/src/internal/poll/fd_poll_js.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm package poll diff --git a/src/internal/poll/fd_poll_runtime.go b/src/internal/poll/fd_poll_runtime.go index b072af00ea..4a4dddfd27 100644 --- a/src/internal/poll/fd_poll_runtime.go +++ b/src/internal/poll/fd_poll_runtime.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || windows || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd windows solaris package poll diff --git a/src/internal/poll/fd_posix.go b/src/internal/poll/fd_posix.go index 487f3285ee..dc1e29c6b7 100644 --- a/src/internal/poll/fd_posix.go +++ b/src/internal/poll/fd_posix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris || windows -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows package poll diff --git a/src/internal/poll/fd_posix_test.go b/src/internal/poll/fd_posix_test.go index 1dcf51d419..0b7ef7a577 100644 --- a/src/internal/poll/fd_posix_test.go +++ b/src/internal/poll/fd_posix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || windows -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows package poll_test diff --git a/src/internal/poll/fd_unix.go b/src/internal/poll/fd_unix.go index 5489662889..d4c32e4d41 100644 --- a/src/internal/poll/fd_unix.go +++ b/src/internal/poll/fd_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris package poll diff --git a/src/internal/poll/fd_writev_darwin.go b/src/internal/poll/fd_writev_darwin.go index 805fa2ccd9..8137510c8b 100644 --- a/src/internal/poll/fd_writev_darwin.go +++ b/src/internal/poll/fd_writev_darwin.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin -// +build darwin package poll diff --git a/src/internal/poll/fd_writev_illumos.go b/src/internal/poll/fd_writev_illumos.go index a0b11ed5ae..79190c2f63 100644 --- a/src/internal/poll/fd_writev_illumos.go +++ b/src/internal/poll/fd_writev_illumos.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build illumos -// +build illumos package poll diff --git a/src/internal/poll/fd_writev_unix.go b/src/internal/poll/fd_writev_unix.go index 87f284a56a..aa96d104c8 100644 --- a/src/internal/poll/fd_writev_unix.go +++ b/src/internal/poll/fd_writev_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd || linux || netbsd || openbsd -// +build dragonfly freebsd linux netbsd openbsd package poll diff --git a/src/internal/poll/hook_cloexec.go b/src/internal/poll/hook_cloexec.go index d519f602c1..c941cb5235 100644 --- a/src/internal/poll/hook_cloexec.go +++ b/src/internal/poll/hook_cloexec.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd || illumos || linux || netbsd || openbsd -// +build dragonfly freebsd illumos linux netbsd openbsd package poll diff --git a/src/internal/poll/hook_unix.go b/src/internal/poll/hook_unix.go index c88d65cdc8..c9aa4b4ca2 100644 --- a/src/internal/poll/hook_unix.go +++ b/src/internal/poll/hook_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris package poll diff --git a/src/internal/poll/iovec_illumos.go b/src/internal/poll/iovec_illumos.go index f4058b298f..00a65d7995 100644 --- a/src/internal/poll/iovec_illumos.go +++ b/src/internal/poll/iovec_illumos.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build illumos -// +build illumos package poll diff --git a/src/internal/poll/iovec_unix.go b/src/internal/poll/iovec_unix.go index 6fd5d86630..c1500840ac 100644 --- a/src/internal/poll/iovec_unix.go +++ b/src/internal/poll/iovec_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd -// +build darwin dragonfly freebsd linux netbsd openbsd package poll diff --git a/src/internal/poll/sendfile_bsd.go b/src/internal/poll/sendfile_bsd.go index 5531e533c5..89315a8c67 100644 --- a/src/internal/poll/sendfile_bsd.go +++ b/src/internal/poll/sendfile_bsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd -// +build darwin dragonfly freebsd package poll diff --git a/src/internal/poll/sock_cloexec.go b/src/internal/poll/sock_cloexec.go index b3038290b9..d849fda0b0 100644 --- a/src/internal/poll/sock_cloexec.go +++ b/src/internal/poll/sock_cloexec.go @@ -6,7 +6,6 @@ // setting SetNonblock and CloseOnExec. //go:build dragonfly || freebsd || illumos || linux || netbsd || openbsd -// +build dragonfly freebsd illumos linux netbsd openbsd package poll diff --git a/src/internal/poll/sockopt.go b/src/internal/poll/sockopt.go index 4f2e2fb455..2d354700c5 100644 --- a/src/internal/poll/sockopt.go +++ b/src/internal/poll/sockopt.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || windows -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows package poll diff --git a/src/internal/poll/sockopt_unix.go b/src/internal/poll/sockopt_unix.go index 4fb9600dee..54be1cc4b6 100644 --- a/src/internal/poll/sockopt_unix.go +++ b/src/internal/poll/sockopt_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package poll diff --git a/src/internal/poll/sockoptip.go b/src/internal/poll/sockoptip.go index d86c4c1f81..7fc9aeefb3 100644 --- a/src/internal/poll/sockoptip.go +++ b/src/internal/poll/sockoptip.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || windows -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows package poll diff --git a/src/internal/poll/strconv.go b/src/internal/poll/strconv.go index c98332d3da..2b052fa174 100644 --- a/src/internal/poll/strconv.go +++ b/src/internal/poll/strconv.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build plan9 -// +build plan9 package poll diff --git a/src/internal/poll/sys_cloexec.go b/src/internal/poll/sys_cloexec.go index 7e6d422d62..312ed24a44 100644 --- a/src/internal/poll/sys_cloexec.go +++ b/src/internal/poll/sys_cloexec.go @@ -6,7 +6,6 @@ // setting SetNonblock and CloseOnExec. //go:build aix || darwin || (js && wasm) || (solaris && !illumos) -// +build aix darwin js,wasm solaris,!illumos package poll diff --git a/src/internal/poll/writev.go b/src/internal/poll/writev.go index 824de7569e..cd600b63d7 100644 --- a/src/internal/poll/writev.go +++ b/src/internal/poll/writev.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || illumos || linux || netbsd || openbsd -// +build darwin dragonfly freebsd illumos linux netbsd openbsd package poll diff --git a/src/internal/syscall/execenv/execenv_default.go b/src/internal/syscall/execenv/execenv_default.go index 73289f1cd0..335647c638 100644 --- a/src/internal/syscall/execenv/execenv_default.go +++ b/src/internal/syscall/execenv/execenv_default.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !windows -// +build !windows package execenv diff --git a/src/internal/syscall/execenv/execenv_windows.go b/src/internal/syscall/execenv/execenv_windows.go index 6c0654943e..a8aa1a644e 100644 --- a/src/internal/syscall/execenv/execenv_windows.go +++ b/src/internal/syscall/execenv/execenv_windows.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows -// +build windows package execenv diff --git a/src/internal/syscall/unix/at.go b/src/internal/syscall/unix/at.go index 9b08864f7f..447d48e198 100644 --- a/src/internal/syscall/unix/at.go +++ b/src/internal/syscall/unix/at.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux || openbsd || netbsd || dragonfly -// +build linux openbsd netbsd dragonfly package unix diff --git a/src/internal/syscall/unix/at_libc.go b/src/internal/syscall/unix/at_libc.go index 4cc351ea27..f48d3791e3 100644 --- a/src/internal/syscall/unix/at_libc.go +++ b/src/internal/syscall/unix/at_libc.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || solaris -// +build aix solaris package unix diff --git a/src/internal/syscall/unix/at_sysnum_fstatat64_linux.go b/src/internal/syscall/unix/at_sysnum_fstatat64_linux.go index 050d401bc0..445b0c3854 100644 --- a/src/internal/syscall/unix/at_sysnum_fstatat64_linux.go +++ b/src/internal/syscall/unix/at_sysnum_fstatat64_linux.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm || mips || mipsle || 386 -// +build arm mips mipsle 386 package unix diff --git a/src/internal/syscall/unix/at_sysnum_fstatat_linux.go b/src/internal/syscall/unix/at_sysnum_fstatat_linux.go index e53a2d1b75..73a3da5bff 100644 --- a/src/internal/syscall/unix/at_sysnum_fstatat_linux.go +++ b/src/internal/syscall/unix/at_sysnum_fstatat_linux.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm64 || riscv64 -// +build arm64 riscv64 package unix diff --git a/src/internal/syscall/unix/at_sysnum_newfstatat_linux.go b/src/internal/syscall/unix/at_sysnum_newfstatat_linux.go index 4cb4a5976b..76edf67522 100644 --- a/src/internal/syscall/unix/at_sysnum_newfstatat_linux.go +++ b/src/internal/syscall/unix/at_sysnum_newfstatat_linux.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 || mips64 || mips64le || ppc64 || ppc64le || s390x -// +build amd64 mips64 mips64le ppc64 ppc64le s390x package unix diff --git a/src/internal/syscall/unix/fcntl_linux_32bit.go b/src/internal/syscall/unix/fcntl_linux_32bit.go index 46a4f6b030..7b39ee72bc 100644 --- a/src/internal/syscall/unix/fcntl_linux_32bit.go +++ b/src/internal/syscall/unix/fcntl_linux_32bit.go @@ -6,7 +6,6 @@ // If you change the build tags here, see syscall/flock_linux_32bit.go. //go:build (linux && 386) || (linux && arm) || (linux && mips) || (linux && mipsle) -// +build linux,386 linux,arm linux,mips linux,mipsle package unix diff --git a/src/internal/syscall/unix/getentropy_darwin.go b/src/internal/syscall/unix/getentropy_darwin.go index c75006bf8b..7bab1f27b0 100644 --- a/src/internal/syscall/unix/getentropy_darwin.go +++ b/src/internal/syscall/unix/getentropy_darwin.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin && !ios -// +build darwin,!ios package unix diff --git a/src/internal/syscall/unix/getrandom.go b/src/internal/syscall/unix/getrandom.go index d2c58c0f6f..a6659331e4 100644 --- a/src/internal/syscall/unix/getrandom.go +++ b/src/internal/syscall/unix/getrandom.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd || linux -// +build dragonfly freebsd linux package unix diff --git a/src/internal/syscall/unix/nonblocking.go b/src/internal/syscall/unix/nonblocking.go index a22986cb8a..9e5f0fb4a2 100644 --- a/src/internal/syscall/unix/nonblocking.go +++ b/src/internal/syscall/unix/nonblocking.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd || linux || netbsd || openbsd -// +build dragonfly freebsd linux netbsd openbsd package unix diff --git a/src/internal/syscall/unix/nonblocking_js.go b/src/internal/syscall/unix/nonblocking_js.go index a5a5080d46..8ed40f3f91 100644 --- a/src/internal/syscall/unix/nonblocking_js.go +++ b/src/internal/syscall/unix/nonblocking_js.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm package unix diff --git a/src/internal/syscall/unix/nonblocking_libc.go b/src/internal/syscall/unix/nonblocking_libc.go index d9565efcb6..75c6e92a6e 100644 --- a/src/internal/syscall/unix/nonblocking_libc.go +++ b/src/internal/syscall/unix/nonblocking_libc.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || solaris -// +build aix darwin solaris package unix diff --git a/src/internal/syscall/unix/pipe2_illumos.go b/src/internal/syscall/unix/pipe2_illumos.go index b0aac89580..c6280f85e5 100644 --- a/src/internal/syscall/unix/pipe2_illumos.go +++ b/src/internal/syscall/unix/pipe2_illumos.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build illumos -// +build illumos package unix diff --git a/src/internal/syscall/unix/sysnum_linux_generic.go b/src/internal/syscall/unix/sysnum_linux_generic.go index a76025454c..3c5394a96b 100644 --- a/src/internal/syscall/unix/sysnum_linux_generic.go +++ b/src/internal/syscall/unix/sysnum_linux_generic.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (arm64 || riscv64) -// +build linux -// +build arm64 riscv64 package unix diff --git a/src/internal/syscall/unix/sysnum_linux_mips64x.go b/src/internal/syscall/unix/sysnum_linux_mips64x.go index f353d4d73e..bca526d2b9 100644 --- a/src/internal/syscall/unix/sysnum_linux_mips64x.go +++ b/src/internal/syscall/unix/sysnum_linux_mips64x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips64 || mips64le -// +build mips64 mips64le package unix diff --git a/src/internal/syscall/unix/sysnum_linux_mipsx.go b/src/internal/syscall/unix/sysnum_linux_mipsx.go index 4ed471532a..c86195e496 100644 --- a/src/internal/syscall/unix/sysnum_linux_mipsx.go +++ b/src/internal/syscall/unix/sysnum_linux_mipsx.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips || mipsle -// +build mips mipsle package unix diff --git a/src/internal/syscall/unix/sysnum_linux_ppc64x.go b/src/internal/syscall/unix/sysnum_linux_ppc64x.go index b484ffef80..a4dcf2bc9d 100644 --- a/src/internal/syscall/unix/sysnum_linux_ppc64x.go +++ b/src/internal/syscall/unix/sysnum_linux_ppc64x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le package unix diff --git a/src/internal/syscall/unix/writev_illumos.go b/src/internal/syscall/unix/writev_illumos.go index f60949f662..ee31be1302 100644 --- a/src/internal/syscall/unix/writev_illumos.go +++ b/src/internal/syscall/unix/writev_illumos.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build illumos -// +build illumos package unix diff --git a/src/internal/testenv/testenv_cgo.go b/src/internal/testenv/testenv_cgo.go index 02f08f57c7..7426a29c1a 100644 --- a/src/internal/testenv/testenv_cgo.go +++ b/src/internal/testenv/testenv_cgo.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build cgo -// +build cgo package testenv diff --git a/src/internal/testenv/testenv_notwin.go b/src/internal/testenv/testenv_notwin.go index 846ec93856..81171fd193 100644 --- a/src/internal/testenv/testenv_notwin.go +++ b/src/internal/testenv/testenv_notwin.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !windows -// +build !windows package testenv diff --git a/src/log/syslog/example_test.go b/src/log/syslog/example_test.go index 993976569e..4df29c0af0 100644 --- a/src/log/syslog/example_test.go +++ b/src/log/syslog/example_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !windows && !plan9 -// +build !windows,!plan9 package syslog_test diff --git a/src/log/syslog/syslog.go b/src/log/syslog/syslog.go index 6abd4ad124..8c6ba72135 100644 --- a/src/log/syslog/syslog.go +++ b/src/log/syslog/syslog.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !windows && !plan9 -// +build !windows,!plan9 package syslog diff --git a/src/log/syslog/syslog_test.go b/src/log/syslog/syslog_test.go index 62c6250845..26530480ee 100644 --- a/src/log/syslog/syslog_test.go +++ b/src/log/syslog/syslog_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !windows && !plan9 && !js -// +build !windows,!plan9,!js package syslog diff --git a/src/log/syslog/syslog_unix.go b/src/log/syslog/syslog_unix.go index 2e45f0764f..f9cdcdc273 100644 --- a/src/log/syslog/syslog_unix.go +++ b/src/log/syslog/syslog_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !windows && !plan9 -// +build !windows,!plan9 package syslog diff --git a/src/math/cmplx/huge_test.go b/src/math/cmplx/huge_test.go index 78b42316de..e794cf281a 100644 --- a/src/math/cmplx/huge_test.go +++ b/src/math/cmplx/huge_test.go @@ -6,7 +6,6 @@ // accurate for huge arguments. //go:build !s390x -// +build !s390x package cmplx diff --git a/src/math/dim_asm.go b/src/math/dim_asm.go index 9ba742a407..f4adbd0ae5 100644 --- a/src/math/dim_asm.go +++ b/src/math/dim_asm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 || arm64 || riscv64 || s390x -// +build amd64 arm64 riscv64 s390x package math diff --git a/src/math/dim_noasm.go b/src/math/dim_noasm.go index ea46577d8d..5b9e06fed3 100644 --- a/src/math/dim_noasm.go +++ b/src/math/dim_noasm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !amd64 && !arm64 && !riscv64 && !s390x -// +build !amd64,!arm64,!riscv64,!s390x package math diff --git a/src/math/exp2_asm.go b/src/math/exp2_asm.go index 76d258f125..c26b2c3fab 100644 --- a/src/math/exp2_asm.go +++ b/src/math/exp2_asm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm64 -// +build arm64 package math diff --git a/src/math/exp2_noasm.go b/src/math/exp2_noasm.go index 1b0ac87ebf..c2b409329f 100644 --- a/src/math/exp2_noasm.go +++ b/src/math/exp2_noasm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !arm64 -// +build !arm64 package math diff --git a/src/math/exp_amd64.go b/src/math/exp_amd64.go index 654ccce481..0f701b1d6d 100644 --- a/src/math/exp_amd64.go +++ b/src/math/exp_amd64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 -// +build amd64 package math diff --git a/src/math/exp_asm.go b/src/math/exp_asm.go index a1673ea1dd..424442845b 100644 --- a/src/math/exp_asm.go +++ b/src/math/exp_asm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 || arm64 || s390x -// +build amd64 arm64 s390x package math diff --git a/src/math/exp_noasm.go b/src/math/exp_noasm.go index b757e6e230..bd3f02412a 100644 --- a/src/math/exp_noasm.go +++ b/src/math/exp_noasm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !amd64 && !arm64 && !s390x -// +build !amd64,!arm64,!s390x package math diff --git a/src/math/floor_asm.go b/src/math/floor_asm.go index 1265e5171e..fb419d6da2 100644 --- a/src/math/floor_asm.go +++ b/src/math/floor_asm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build 386 || amd64 || arm64 || ppc64 || ppc64le || s390x || wasm -// +build 386 amd64 arm64 ppc64 ppc64le s390x wasm package math diff --git a/src/math/floor_noasm.go b/src/math/floor_noasm.go index 821af21020..5641c7ea0a 100644 --- a/src/math/floor_noasm.go +++ b/src/math/floor_noasm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !386 && !amd64 && !arm64 && !ppc64 && !ppc64le && !s390x && !wasm -// +build !386,!amd64,!arm64,!ppc64,!ppc64le,!s390x,!wasm package math diff --git a/src/math/huge_test.go b/src/math/huge_test.go index ec81a4a31d..bc28c6ff69 100644 --- a/src/math/huge_test.go +++ b/src/math/huge_test.go @@ -6,7 +6,6 @@ // accurate for huge arguments. //go:build !s390x -// +build !s390x package math_test diff --git a/src/math/hypot_asm.go b/src/math/hypot_asm.go index 9435af41cf..852691037f 100644 --- a/src/math/hypot_asm.go +++ b/src/math/hypot_asm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build 386 || amd64 -// +build 386 amd64 package math diff --git a/src/math/hypot_noasm.go b/src/math/hypot_noasm.go index bc41b136e5..8b64812a1c 100644 --- a/src/math/hypot_noasm.go +++ b/src/math/hypot_noasm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !386 && !amd64 -// +build !386,!amd64 package math diff --git a/src/math/log_asm.go b/src/math/log_asm.go index 4d3b7ee065..848cce13b2 100644 --- a/src/math/log_asm.go +++ b/src/math/log_asm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 || s390x -// +build amd64 s390x package math diff --git a/src/math/log_stub.go b/src/math/log_stub.go index e169716436..d35992bf37 100644 --- a/src/math/log_stub.go +++ b/src/math/log_stub.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !amd64 && !s390x -// +build !amd64,!s390x package math diff --git a/src/math/modf_asm.go b/src/math/modf_asm.go index ce431a9d8d..c63be6cf36 100644 --- a/src/math/modf_asm.go +++ b/src/math/modf_asm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm64 || ppc64 || ppc64le -// +build arm64 ppc64 ppc64le package math diff --git a/src/math/modf_noasm.go b/src/math/modf_noasm.go index 9607a0894b..55c6a7f6e2 100644 --- a/src/math/modf_noasm.go +++ b/src/math/modf_noasm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !arm64 && !ppc64 && !ppc64le -// +build !arm64,!ppc64,!ppc64le package math diff --git a/src/math/rand/gen_cooked.go b/src/math/rand/gen_cooked.go index 7950e09fd7..782bb6671d 100644 --- a/src/math/rand/gen_cooked.go +++ b/src/math/rand/gen_cooked.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore // This program computes the value of rngCooked in rng.go, // which is used for seeding all instances of rand.Source. diff --git a/src/math/sqrt_asm.go b/src/math/sqrt_asm.go index b9102568ed..2cec1a5903 100644 --- a/src/math/sqrt_asm.go +++ b/src/math/sqrt_asm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build 386 || amd64 || arm64 || arm || mips || mipsle || ppc64 || ppc64le || s390x || riscv64 || wasm -// +build 386 amd64 arm64 arm mips mipsle ppc64 ppc64le s390x riscv64 wasm package math diff --git a/src/math/sqrt_noasm.go b/src/math/sqrt_noasm.go index 7b546b7e8c..3979622023 100644 --- a/src/math/sqrt_noasm.go +++ b/src/math/sqrt_noasm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !386 && !amd64 && !arm64 && !arm && !mips && !mipsle && !ppc64 && !ppc64le && !s390x && !riscv64 && !wasm -// +build !386,!amd64,!arm64,!arm,!mips,!mipsle,!ppc64,!ppc64le,!s390x,!riscv64,!wasm package math diff --git a/src/math/stubs.go b/src/math/stubs.go index e1345eb841..c4350d4b87 100644 --- a/src/math/stubs.go +++ b/src/math/stubs.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !s390x -// +build !s390x // This is a large group of functions that most architectures don't // implement in assembly. diff --git a/src/mime/type_unix.go b/src/mime/type_unix.go index f954bc8a1f..3abc1fa10e 100644 --- a/src/mime/type_unix.go +++ b/src/mime/type_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris package mime diff --git a/src/mime/type_unix_test.go b/src/mime/type_unix_test.go index 6e2988225c..4d109aa71a 100644 --- a/src/mime/type_unix_test.go +++ b/src/mime/type_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris package mime diff --git a/src/net/addrselect.go b/src/net/addrselect.go index ae93c595af..29e4ed85ab 100644 --- a/src/net/addrselect.go +++ b/src/net/addrselect.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris // Minimal RFC 6724 address selection. diff --git a/src/net/addrselect_test.go b/src/net/addrselect_test.go index dc13917018..2894d5d846 100644 --- a/src/net/addrselect_test.go +++ b/src/net/addrselect_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build darwin dragonfly freebsd linux netbsd openbsd solaris package net diff --git a/src/net/cgo_aix.go b/src/net/cgo_aix.go index a94405ecc0..f3478148b4 100644 --- a/src/net/cgo_aix.go +++ b/src/net/cgo_aix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build cgo && !netgo -// +build cgo,!netgo package net diff --git a/src/net/cgo_android.go b/src/net/cgo_android.go index 4b1a2e3e1d..5ab8b5fede 100644 --- a/src/net/cgo_android.go +++ b/src/net/cgo_android.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build cgo && !netgo -// +build cgo,!netgo package net diff --git a/src/net/cgo_bsd.go b/src/net/cgo_bsd.go index 23be72140b..1456289b06 100644 --- a/src/net/cgo_bsd.go +++ b/src/net/cgo_bsd.go @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build cgo && !netgo && (darwin || dragonfly || freebsd) -// +build cgo -// +build !netgo -// +build darwin dragonfly freebsd package net diff --git a/src/net/cgo_linux.go b/src/net/cgo_linux.go index 1bd6be93f7..de6e87f176 100644 --- a/src/net/cgo_linux.go +++ b/src/net/cgo_linux.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !android && cgo && !netgo -// +build !android,cgo,!netgo package net diff --git a/src/net/cgo_netbsd.go b/src/net/cgo_netbsd.go index 3714793a52..03392e8ff3 100644 --- a/src/net/cgo_netbsd.go +++ b/src/net/cgo_netbsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build cgo && !netgo -// +build cgo,!netgo package net diff --git a/src/net/cgo_openbsd.go b/src/net/cgo_openbsd.go index 3714793a52..03392e8ff3 100644 --- a/src/net/cgo_openbsd.go +++ b/src/net/cgo_openbsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build cgo && !netgo -// +build cgo,!netgo package net diff --git a/src/net/cgo_resnew.go b/src/net/cgo_resnew.go index 154405270f..fa6e68770c 100644 --- a/src/net/cgo_resnew.go +++ b/src/net/cgo_resnew.go @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build cgo && !netgo && (darwin || (linux && !android) || netbsd || solaris) -// +build cgo -// +build !netgo -// +build darwin linux,!android netbsd solaris package net diff --git a/src/net/cgo_resold.go b/src/net/cgo_resold.go index c4aab33eaa..37c75527f9 100644 --- a/src/net/cgo_resold.go +++ b/src/net/cgo_resold.go @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build cgo && !netgo && (android || freebsd || dragonfly || openbsd) -// +build cgo -// +build !netgo -// +build android freebsd dragonfly openbsd package net diff --git a/src/net/cgo_socknew.go b/src/net/cgo_socknew.go index f9cfad9909..fbb9e10f34 100644 --- a/src/net/cgo_socknew.go +++ b/src/net/cgo_socknew.go @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build cgo && !netgo && (android || linux || solaris) -// +build cgo -// +build !netgo -// +build android linux solaris package net diff --git a/src/net/cgo_sockold.go b/src/net/cgo_sockold.go index 22c67252f5..4d9869de04 100644 --- a/src/net/cgo_sockold.go +++ b/src/net/cgo_sockold.go @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build cgo && !netgo && (aix || darwin || dragonfly || freebsd || netbsd || openbsd) -// +build cgo -// +build !netgo -// +build aix darwin dragonfly freebsd netbsd openbsd package net diff --git a/src/net/cgo_solaris.go b/src/net/cgo_solaris.go index a84f5b0d34..cde9c957fe 100644 --- a/src/net/cgo_solaris.go +++ b/src/net/cgo_solaris.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build cgo && !netgo -// +build cgo,!netgo package net diff --git a/src/net/cgo_stub.go b/src/net/cgo_stub.go index 039e4be88b..cc84ca47ae 100644 --- a/src/net/cgo_stub.go +++ b/src/net/cgo_stub.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !cgo || netgo -// +build !cgo netgo package net diff --git a/src/net/cgo_unix.go b/src/net/cgo_unix.go index 5bf6fd84bc..6fc2c1930e 100644 --- a/src/net/cgo_unix.go +++ b/src/net/cgo_unix.go @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build cgo && !netgo && (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris) -// +build cgo -// +build !netgo -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package net diff --git a/src/net/cgo_unix_test.go b/src/net/cgo_unix_test.go index 1f3d9ea207..b4da25b84c 100644 --- a/src/net/cgo_unix_test.go +++ b/src/net/cgo_unix_test.go @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build cgo && !netgo && (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris) -// +build cgo -// +build !netgo -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package net diff --git a/src/net/cgo_windows.go b/src/net/cgo_windows.go index 1fd1f29787..6bb6cbbb2f 100644 --- a/src/net/cgo_windows.go +++ b/src/net/cgo_windows.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build cgo && !netgo -// +build cgo,!netgo package net diff --git a/src/net/conf.go b/src/net/conf.go index 6b9569cd92..1115699ab0 100644 --- a/src/net/conf.go +++ b/src/net/conf.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package net diff --git a/src/net/conf_netcgo.go b/src/net/conf_netcgo.go index 8f387ebc03..82d1bb643e 100644 --- a/src/net/conf_netcgo.go +++ b/src/net/conf_netcgo.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build netcgo -// +build netcgo package net diff --git a/src/net/conf_test.go b/src/net/conf_test.go index b1f2c55ea5..5ae7055086 100644 --- a/src/net/conf_test.go +++ b/src/net/conf_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build darwin dragonfly freebsd linux netbsd openbsd solaris package net diff --git a/src/net/conn_test.go b/src/net/conn_test.go index 45e271c264..e3cb0c5ec7 100644 --- a/src/net/conn_test.go +++ b/src/net/conn_test.go @@ -6,7 +6,6 @@ // tag. //go:build !js -// +build !js package net diff --git a/src/net/dial_test.go b/src/net/dial_test.go index 723038c7a2..8967892197 100644 --- a/src/net/dial_test.go +++ b/src/net/dial_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js -// +build !js package net diff --git a/src/net/dial_unix_test.go b/src/net/dial_unix_test.go index 108b973099..1113aaca90 100644 --- a/src/net/dial_unix_test.go +++ b/src/net/dial_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package net diff --git a/src/net/dnsclient_unix.go b/src/net/dnsclient_unix.go index 50e9bb0f20..21aa91f665 100644 --- a/src/net/dnsclient_unix.go +++ b/src/net/dnsclient_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris // DNS client: see RFC 1035. // Has to be linked into package net for Dial. diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go index 350ad5def7..1d704d021e 100644 --- a/src/net/dnsclient_unix_test.go +++ b/src/net/dnsclient_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package net diff --git a/src/net/dnsconfig_unix.go b/src/net/dnsconfig_unix.go index db9213a13f..5ad254cd7c 100644 --- a/src/net/dnsconfig_unix.go +++ b/src/net/dnsconfig_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris // Read system DNS config from /etc/resolv.conf diff --git a/src/net/dnsconfig_unix_test.go b/src/net/dnsconfig_unix_test.go index 0e2317c469..4d35221497 100644 --- a/src/net/dnsconfig_unix_test.go +++ b/src/net/dnsconfig_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package net diff --git a/src/net/dnsname_test.go b/src/net/dnsname_test.go index d851bf7566..28b7c680fe 100644 --- a/src/net/dnsname_test.go +++ b/src/net/dnsname_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js -// +build !js package net diff --git a/src/net/error_posix.go b/src/net/error_posix.go index 50eb66fc61..10e3caa67b 100644 --- a/src/net/error_posix.go +++ b/src/net/error_posix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris || windows -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows package net diff --git a/src/net/error_posix_test.go b/src/net/error_posix_test.go index ea52a45ee8..081176f771 100644 --- a/src/net/error_posix_test.go +++ b/src/net/error_posix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !plan9 -// +build !plan9 package net diff --git a/src/net/error_test.go b/src/net/error_test.go index c304390819..30f8af3aee 100644 --- a/src/net/error_test.go +++ b/src/net/error_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js -// +build !js package net diff --git a/src/net/error_unix.go b/src/net/error_unix.go index d0b5e2ce96..0e64b40ea1 100644 --- a/src/net/error_unix.go +++ b/src/net/error_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || js || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd js linux netbsd openbsd solaris package net diff --git a/src/net/error_unix_test.go b/src/net/error_unix_test.go index 533a45e648..1334aa86b6 100644 --- a/src/net/error_unix_test.go +++ b/src/net/error_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !plan9 && !windows -// +build !plan9,!windows package net diff --git a/src/net/external_test.go b/src/net/external_test.go index b8753cc092..3a97011fe8 100644 --- a/src/net/external_test.go +++ b/src/net/external_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js -// +build !js package net diff --git a/src/net/fcntl_libc_test.go b/src/net/fcntl_libc_test.go index 0320d63a86..3478ce7231 100644 --- a/src/net/fcntl_libc_test.go +++ b/src/net/fcntl_libc_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || solaris -// +build aix darwin solaris package net diff --git a/src/net/fcntl_syscall_test.go b/src/net/fcntl_syscall_test.go index 0f04bb4ed6..2d1f7e22a4 100644 --- a/src/net/fcntl_syscall_test.go +++ b/src/net/fcntl_syscall_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd || linux || netbsd || openbsd -// +build dragonfly freebsd linux netbsd openbsd package net diff --git a/src/net/fd_posix.go b/src/net/fd_posix.go index 38e5a8d61d..1887a45186 100644 --- a/src/net/fd_posix.go +++ b/src/net/fd_posix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || windows -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows package net diff --git a/src/net/fd_unix.go b/src/net/fd_unix.go index a7bbdd26b4..1bb029d370 100644 --- a/src/net/fd_unix.go +++ b/src/net/fd_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package net diff --git a/src/net/file_stub.go b/src/net/file_stub.go index 9f988fe899..91df926a57 100644 --- a/src/net/file_stub.go +++ b/src/net/file_stub.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm package net diff --git a/src/net/file_test.go b/src/net/file_test.go index a70ef1b312..e86c15fac7 100644 --- a/src/net/file_test.go +++ b/src/net/file_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js -// +build !js package net diff --git a/src/net/file_unix.go b/src/net/file_unix.go index 4520d4b839..68d7eb9ca0 100644 --- a/src/net/file_unix.go +++ b/src/net/file_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package net diff --git a/src/net/hook_unix.go b/src/net/hook_unix.go index b9153d1947..7c36b0d6e3 100644 --- a/src/net/hook_unix.go +++ b/src/net/hook_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris package net diff --git a/src/net/http/cgi/plan9_test.go b/src/net/http/cgi/plan9_test.go index f998bac6ea..b7ace3f81c 100644 --- a/src/net/http/cgi/plan9_test.go +++ b/src/net/http/cgi/plan9_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build plan9 -// +build plan9 package cgi diff --git a/src/net/http/cgi/posix_test.go b/src/net/http/cgi/posix_test.go index bc58ea94cc..49b9470d4a 100644 --- a/src/net/http/cgi/posix_test.go +++ b/src/net/http/cgi/posix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !plan9 -// +build !plan9 package cgi diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go index 29226d4065..df98232824 100644 --- a/src/net/http/h2_bundle.go +++ b/src/net/http/h2_bundle.go @@ -1,5 +1,4 @@ //go:build !nethttpomithttp2 -// +build !nethttpomithttp2 // Code generated by golang.org/x/tools/cmd/bundle. DO NOT EDIT. // $ bundle -o=h2_bundle.go -prefix=http2 -tags=!nethttpomithttp2 golang.org/x/net/http2 diff --git a/src/net/http/omithttp2.go b/src/net/http/omithttp2.go index 79599d006a..63c0e92d6a 100644 --- a/src/net/http/omithttp2.go +++ b/src/net/http/omithttp2.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build nethttpomithttp2 -// +build nethttpomithttp2 package http diff --git a/src/net/http/roundtrip.go b/src/net/http/roundtrip.go index eef7c79293..c4c5d3b6eb 100644 --- a/src/net/http/roundtrip.go +++ b/src/net/http/roundtrip.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js || !wasm -// +build !js !wasm package http diff --git a/src/net/http/roundtrip_js.go b/src/net/http/roundtrip_js.go index 4a8595ebcf..dd042e9a01 100644 --- a/src/net/http/roundtrip_js.go +++ b/src/net/http/roundtrip_js.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm package http diff --git a/src/net/http/triv.go b/src/net/http/triv.go index 4dc62407c6..11b19ab30c 100644 --- a/src/net/http/triv.go +++ b/src/net/http/triv.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore package main diff --git a/src/net/interface_bsd.go b/src/net/interface_bsd.go index 7578b1a16a..db7bc756d8 100644 --- a/src/net/interface_bsd.go +++ b/src/net/interface_bsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || netbsd || openbsd -// +build darwin dragonfly freebsd netbsd openbsd package net diff --git a/src/net/interface_bsd_test.go b/src/net/interface_bsd_test.go index 8d0d9c3671..ce59962f61 100644 --- a/src/net/interface_bsd_test.go +++ b/src/net/interface_bsd_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || netbsd || openbsd -// +build darwin dragonfly freebsd netbsd openbsd package net diff --git a/src/net/interface_bsdvar.go b/src/net/interface_bsdvar.go index 6230e0bfee..e9bea3d379 100644 --- a/src/net/interface_bsdvar.go +++ b/src/net/interface_bsdvar.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || netbsd || openbsd -// +build dragonfly netbsd openbsd package net diff --git a/src/net/interface_stub.go b/src/net/interface_stub.go index efe67c24d3..2d4475f63e 100644 --- a/src/net/interface_stub.go +++ b/src/net/interface_stub.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm package net diff --git a/src/net/interface_test.go b/src/net/interface_test.go index 754db36e3c..f6c9868418 100644 --- a/src/net/interface_test.go +++ b/src/net/interface_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js -// +build !js package net diff --git a/src/net/interface_unix_test.go b/src/net/interface_unix_test.go index 0d69fa5da4..92ec13a909 100644 --- a/src/net/interface_unix_test.go +++ b/src/net/interface_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd -// +build darwin dragonfly freebsd linux netbsd openbsd package net diff --git a/src/net/internal/socktest/main_test.go b/src/net/internal/socktest/main_test.go index 8af85d382e..c7c8d16d4c 100644 --- a/src/net/internal/socktest/main_test.go +++ b/src/net/internal/socktest/main_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js && !plan9 -// +build !js,!plan9 package socktest_test diff --git a/src/net/internal/socktest/main_unix_test.go b/src/net/internal/socktest/main_unix_test.go index 6aa8875b66..7d21f6f99f 100644 --- a/src/net/internal/socktest/main_unix_test.go +++ b/src/net/internal/socktest/main_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js && !plan9 && !windows -// +build !js,!plan9,!windows package socktest_test diff --git a/src/net/internal/socktest/switch_posix.go b/src/net/internal/socktest/switch_posix.go index cda74e8639..fcad4ceae3 100644 --- a/src/net/internal/socktest/switch_posix.go +++ b/src/net/internal/socktest/switch_posix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !plan9 -// +build !plan9 package socktest diff --git a/src/net/internal/socktest/switch_stub.go b/src/net/internal/socktest/switch_stub.go index 5aa2ecec08..8a2fc353f0 100644 --- a/src/net/internal/socktest/switch_stub.go +++ b/src/net/internal/socktest/switch_stub.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build plan9 -// +build plan9 package socktest diff --git a/src/net/internal/socktest/switch_unix.go b/src/net/internal/socktest/switch_unix.go index bfe9d4dbd3..77d68f6112 100644 --- a/src/net/internal/socktest/switch_unix.go +++ b/src/net/internal/socktest/switch_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris package socktest diff --git a/src/net/internal/socktest/sys_cloexec.go b/src/net/internal/socktest/sys_cloexec.go index c7f8331c2e..cc7cefbe2c 100644 --- a/src/net/internal/socktest/sys_cloexec.go +++ b/src/net/internal/socktest/sys_cloexec.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd || illumos || linux || netbsd || openbsd -// +build dragonfly freebsd illumos linux netbsd openbsd package socktest diff --git a/src/net/internal/socktest/sys_unix.go b/src/net/internal/socktest/sys_unix.go index e7cc45922e..0424164ed3 100644 --- a/src/net/internal/socktest/sys_unix.go +++ b/src/net/internal/socktest/sys_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris package socktest diff --git a/src/net/ip_test.go b/src/net/ip_test.go index 5bbda6024d..10e77f3bdb 100644 --- a/src/net/ip_test.go +++ b/src/net/ip_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js -// +build !js package net diff --git a/src/net/iprawsock_posix.go b/src/net/iprawsock_posix.go index b94eec0e18..74f977e1ef 100644 --- a/src/net/iprawsock_posix.go +++ b/src/net/iprawsock_posix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris || windows -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows package net diff --git a/src/net/iprawsock_test.go b/src/net/iprawsock_test.go index a96448ee6c..ca5ab480c0 100644 --- a/src/net/iprawsock_test.go +++ b/src/net/iprawsock_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js -// +build !js package net diff --git a/src/net/ipsock_posix.go b/src/net/ipsock_posix.go index 50003ac446..0910f63d48 100644 --- a/src/net/ipsock_posix.go +++ b/src/net/ipsock_posix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris || windows -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows package net diff --git a/src/net/listen_test.go b/src/net/listen_test.go index 50355de1ac..7aaebe8fa1 100644 --- a/src/net/listen_test.go +++ b/src/net/listen_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js && !plan9 -// +build !js,!plan9 package net diff --git a/src/net/lookup_fake.go b/src/net/lookup_fake.go index f4fcaed5cf..c27eae4ba5 100644 --- a/src/net/lookup_fake.go +++ b/src/net/lookup_fake.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm package net diff --git a/src/net/lookup_test.go b/src/net/lookup_test.go index 7ca6ac16ec..7bcc5c5be8 100644 --- a/src/net/lookup_test.go +++ b/src/net/lookup_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js -// +build !js package net diff --git a/src/net/lookup_unix.go b/src/net/lookup_unix.go index 8030e3d99e..255a19dfdb 100644 --- a/src/net/lookup_unix.go +++ b/src/net/lookup_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package net diff --git a/src/net/main_cloexec_test.go b/src/net/main_cloexec_test.go index 742be2fcd8..ca7fc78491 100644 --- a/src/net/main_cloexec_test.go +++ b/src/net/main_cloexec_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd || illumos || linux || netbsd || openbsd -// +build dragonfly freebsd illumos linux netbsd openbsd package net diff --git a/src/net/main_conf_test.go b/src/net/main_conf_test.go index 645b267b78..41b78eda1d 100644 --- a/src/net/main_conf_test.go +++ b/src/net/main_conf_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js && !plan9 && !windows -// +build !js,!plan9,!windows package net diff --git a/src/net/main_noconf_test.go b/src/net/main_noconf_test.go index bcea630cd3..ab050fac2b 100644 --- a/src/net/main_noconf_test.go +++ b/src/net/main_noconf_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build (js && wasm) || plan9 || windows -// +build js,wasm plan9 windows package net diff --git a/src/net/main_posix_test.go b/src/net/main_posix_test.go index c804c4e755..8899aa9c94 100644 --- a/src/net/main_posix_test.go +++ b/src/net/main_posix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js && !plan9 -// +build !js,!plan9 package net diff --git a/src/net/main_test.go b/src/net/main_test.go index 4f004071f0..1ee8c2efe7 100644 --- a/src/net/main_test.go +++ b/src/net/main_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js -// +build !js package net diff --git a/src/net/main_unix_test.go b/src/net/main_unix_test.go index c8cff2d305..2ed0615ad8 100644 --- a/src/net/main_unix_test.go +++ b/src/net/main_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package net diff --git a/src/net/mockserver_test.go b/src/net/mockserver_test.go index b50a1e59a1..43b11a7218 100644 --- a/src/net/mockserver_test.go +++ b/src/net/mockserver_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js -// +build !js package net diff --git a/src/net/net_fake.go b/src/net/net_fake.go index 48419be670..d58bd82029 100644 --- a/src/net/net_fake.go +++ b/src/net/net_fake.go @@ -5,7 +5,6 @@ // Fake networking for js/wasm. It is intended to allow tests of other package to pass. //go:build js && wasm -// +build js,wasm package net diff --git a/src/net/net_test.go b/src/net/net_test.go index 6e7be4db23..35acac509b 100644 --- a/src/net/net_test.go +++ b/src/net/net_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js -// +build !js package net diff --git a/src/net/netgo_unix_test.go b/src/net/netgo_unix_test.go index 5551e47de7..019772aa6a 100644 --- a/src/net/netgo_unix_test.go +++ b/src/net/netgo_unix_test.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (!cgo || netgo) && (darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris) -// +build !cgo netgo -// +build darwin dragonfly freebsd linux netbsd openbsd solaris package net diff --git a/src/net/nss.go b/src/net/nss.go index 85177cab9b..ee5568883f 100644 --- a/src/net/nss.go +++ b/src/net/nss.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package net diff --git a/src/net/nss_test.go b/src/net/nss_test.go index 4b73886c51..c9ccc60cb7 100644 --- a/src/net/nss_test.go +++ b/src/net/nss_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build darwin dragonfly freebsd linux netbsd openbsd solaris package net diff --git a/src/net/packetconn_test.go b/src/net/packetconn_test.go index aeb9845fa7..b3b1715655 100644 --- a/src/net/packetconn_test.go +++ b/src/net/packetconn_test.go @@ -6,7 +6,6 @@ // tag. //go:build !js -// +build !js package net diff --git a/src/net/port_unix.go b/src/net/port_unix.go index a9a96a2323..102722b2ca 100644 --- a/src/net/port_unix.go +++ b/src/net/port_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris // Read system port mappings from /etc/services diff --git a/src/net/protoconn_test.go b/src/net/protoconn_test.go index fc9b386256..9f7d8ee4ef 100644 --- a/src/net/protoconn_test.go +++ b/src/net/protoconn_test.go @@ -6,7 +6,6 @@ // tag. //go:build !js -// +build !js package net diff --git a/src/net/rawconn_stub_test.go b/src/net/rawconn_stub_test.go index 975aa8d956..ff3d829893 100644 --- a/src/net/rawconn_stub_test.go +++ b/src/net/rawconn_stub_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build (js && wasm) || plan9 -// +build js,wasm plan9 package net diff --git a/src/net/rawconn_test.go b/src/net/rawconn_test.go index 3ef7af33b7..645d82a1a6 100644 --- a/src/net/rawconn_test.go +++ b/src/net/rawconn_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js -// +build !js package net diff --git a/src/net/rawconn_unix_test.go b/src/net/rawconn_unix_test.go index 75bbab8b27..e6e1ad771a 100644 --- a/src/net/rawconn_unix_test.go +++ b/src/net/rawconn_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package net diff --git a/src/net/sendfile_stub.go b/src/net/sendfile_stub.go index c079064262..4ddae852e1 100644 --- a/src/net/sendfile_stub.go +++ b/src/net/sendfile_stub.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || (js && wasm) || netbsd || openbsd -// +build aix js,wasm netbsd openbsd package net diff --git a/src/net/sendfile_test.go b/src/net/sendfile_test.go index 54e51fa0ab..492333d0c8 100644 --- a/src/net/sendfile_test.go +++ b/src/net/sendfile_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js -// +build !js package net diff --git a/src/net/sendfile_unix_alt.go b/src/net/sendfile_unix_alt.go index cd63dcc32c..8845a981f5 100644 --- a/src/net/sendfile_unix_alt.go +++ b/src/net/sendfile_unix_alt.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || solaris -// +build darwin dragonfly freebsd solaris package net diff --git a/src/net/server_test.go b/src/net/server_test.go index 7cbf152298..5192c1e0af 100644 --- a/src/net/server_test.go +++ b/src/net/server_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js -// +build !js package net diff --git a/src/net/sock_bsd.go b/src/net/sock_bsd.go index 4c883ada78..27daf722b5 100644 --- a/src/net/sock_bsd.go +++ b/src/net/sock_bsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || netbsd || openbsd -// +build darwin dragonfly freebsd netbsd openbsd package net diff --git a/src/net/sock_cloexec.go b/src/net/sock_cloexec.go index 6861c4bf63..56dab31b14 100644 --- a/src/net/sock_cloexec.go +++ b/src/net/sock_cloexec.go @@ -6,7 +6,6 @@ // setting SetNonblock and CloseOnExec. //go:build dragonfly || freebsd || illumos || linux || netbsd || openbsd -// +build dragonfly freebsd illumos linux netbsd openbsd package net diff --git a/src/net/sock_posix.go b/src/net/sock_posix.go index 9b1e7880ae..98a48229c7 100644 --- a/src/net/sock_posix.go +++ b/src/net/sock_posix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || windows -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows package net diff --git a/src/net/sock_stub.go b/src/net/sock_stub.go index d804bfaacc..4b73e575fe 100644 --- a/src/net/sock_stub.go +++ b/src/net/sock_stub.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || (js && wasm) || solaris -// +build aix js,wasm solaris package net diff --git a/src/net/sockaddr_posix.go b/src/net/sockaddr_posix.go index 9d77cb569b..c8e91936ad 100644 --- a/src/net/sockaddr_posix.go +++ b/src/net/sockaddr_posix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris || windows -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows package net diff --git a/src/net/sockopt_bsd.go b/src/net/sockopt_bsd.go index ee1f98b834..ff99811980 100644 --- a/src/net/sockopt_bsd.go +++ b/src/net/sockopt_bsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || netbsd || openbsd -// +build darwin dragonfly freebsd netbsd openbsd package net diff --git a/src/net/sockopt_posix.go b/src/net/sockopt_posix.go index 50b9bfa0a7..645080f988 100644 --- a/src/net/sockopt_posix.go +++ b/src/net/sockopt_posix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || windows -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows package net diff --git a/src/net/sockopt_stub.go b/src/net/sockopt_stub.go index 99b5277ed0..98e23714d9 100644 --- a/src/net/sockopt_stub.go +++ b/src/net/sockopt_stub.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm package net diff --git a/src/net/sockoptip_bsdvar.go b/src/net/sockoptip_bsdvar.go index 56022fd1a5..3e9ba1ee78 100644 --- a/src/net/sockoptip_bsdvar.go +++ b/src/net/sockoptip_bsdvar.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd netbsd openbsd solaris package net diff --git a/src/net/sockoptip_posix.go b/src/net/sockoptip_posix.go index a2143aec2c..22031df22c 100644 --- a/src/net/sockoptip_posix.go +++ b/src/net/sockoptip_posix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || windows -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows package net diff --git a/src/net/sockoptip_stub.go b/src/net/sockoptip_stub.go index 92349d88ba..2c993eb719 100644 --- a/src/net/sockoptip_stub.go +++ b/src/net/sockoptip_stub.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm package net diff --git a/src/net/splice_stub.go b/src/net/splice_stub.go index ce2e9046a9..3cdadb11c5 100644 --- a/src/net/splice_stub.go +++ b/src/net/splice_stub.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !linux -// +build !linux package net diff --git a/src/net/splice_test.go b/src/net/splice_test.go index be13cc924d..43e0b926f7 100644 --- a/src/net/splice_test.go +++ b/src/net/splice_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux -// +build linux package net diff --git a/src/net/sys_cloexec.go b/src/net/sys_cloexec.go index a32483e2df..26eac5585a 100644 --- a/src/net/sys_cloexec.go +++ b/src/net/sys_cloexec.go @@ -6,7 +6,6 @@ // for setting SetNonblock and CloseOnExec. //go:build aix || darwin || (solaris && !illumos) -// +build aix darwin solaris,!illumos package net diff --git a/src/net/tcpsock_posix.go b/src/net/tcpsock_posix.go index 7c4523c5ee..ed6b18b551 100644 --- a/src/net/tcpsock_posix.go +++ b/src/net/tcpsock_posix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris || windows -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows package net diff --git a/src/net/tcpsock_test.go b/src/net/tcpsock_test.go index 9c9f1eae93..fdf5c330a9 100644 --- a/src/net/tcpsock_test.go +++ b/src/net/tcpsock_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js -// +build !js package net diff --git a/src/net/tcpsock_unix_test.go b/src/net/tcpsock_unix_test.go index 41bd229132..b1f2876d4e 100644 --- a/src/net/tcpsock_unix_test.go +++ b/src/net/tcpsock_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js && !plan9 && !windows -// +build !js,!plan9,!windows package net diff --git a/src/net/tcpsockopt_posix.go b/src/net/tcpsockopt_posix.go index d08832adc0..73754b1a0f 100644 --- a/src/net/tcpsockopt_posix.go +++ b/src/net/tcpsockopt_posix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || windows -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows package net diff --git a/src/net/tcpsockopt_stub.go b/src/net/tcpsockopt_stub.go index 028d5fd29c..0fe91829c0 100644 --- a/src/net/tcpsockopt_stub.go +++ b/src/net/tcpsockopt_stub.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm package net diff --git a/src/net/tcpsockopt_unix.go b/src/net/tcpsockopt_unix.go index a945889e00..bdcdc40239 100644 --- a/src/net/tcpsockopt_unix.go +++ b/src/net/tcpsockopt_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || freebsd || linux || netbsd -// +build aix freebsd linux netbsd package net diff --git a/src/net/timeout_test.go b/src/net/timeout_test.go index 6c8e9cf76e..82069b347a 100644 --- a/src/net/timeout_test.go +++ b/src/net/timeout_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js -// +build !js package net diff --git a/src/net/udpsock_posix.go b/src/net/udpsock_posix.go index 3a333ca243..c3f7ddb77e 100644 --- a/src/net/udpsock_posix.go +++ b/src/net/udpsock_posix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris || windows -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows package net diff --git a/src/net/udpsock_test.go b/src/net/udpsock_test.go index 0e8c3511c3..0f8f463100 100644 --- a/src/net/udpsock_test.go +++ b/src/net/udpsock_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js -// +build !js package net diff --git a/src/net/unixsock_posix.go b/src/net/unixsock_posix.go index 99a89c827b..1b69df53bf 100644 --- a/src/net/unixsock_posix.go +++ b/src/net/unixsock_posix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris || windows -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows package net diff --git a/src/net/unixsock_readmsg_cloexec.go b/src/net/unixsock_readmsg_cloexec.go index 716484cc6c..fa4fd7d933 100644 --- a/src/net/unixsock_readmsg_cloexec.go +++ b/src/net/unixsock_readmsg_cloexec.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || freebsd || solaris -// +build aix darwin freebsd solaris package net diff --git a/src/net/unixsock_readmsg_cmsg_cloexec.go b/src/net/unixsock_readmsg_cmsg_cloexec.go index bb851b89c0..6b0de875ad 100644 --- a/src/net/unixsock_readmsg_cmsg_cloexec.go +++ b/src/net/unixsock_readmsg_cmsg_cloexec.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || linux || netbsd || openbsd -// +build dragonfly linux netbsd openbsd package net diff --git a/src/net/unixsock_readmsg_other.go b/src/net/unixsock_readmsg_other.go index 329076183a..b3d19fe73d 100644 --- a/src/net/unixsock_readmsg_other.go +++ b/src/net/unixsock_readmsg_other.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build (js && wasm) || windows -// +build js,wasm windows package net diff --git a/src/net/unixsock_readmsg_test.go b/src/net/unixsock_readmsg_test.go index a4d2fca69c..c3bfbf9af2 100644 --- a/src/net/unixsock_readmsg_test.go +++ b/src/net/unixsock_readmsg_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package net diff --git a/src/net/unixsock_test.go b/src/net/unixsock_test.go index 71092e88fb..a75578235f 100644 --- a/src/net/unixsock_test.go +++ b/src/net/unixsock_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js && !plan9 && !windows -// +build !js,!plan9,!windows package net diff --git a/src/net/unixsock_windows_test.go b/src/net/unixsock_windows_test.go index 29244f6471..dedd761c56 100644 --- a/src/net/unixsock_windows_test.go +++ b/src/net/unixsock_windows_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows -// +build windows package net diff --git a/src/net/write_unix_test.go b/src/net/write_unix_test.go index f79f2d0865..23e8befa92 100644 --- a/src/net/write_unix_test.go +++ b/src/net/write_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build darwin dragonfly freebsd linux netbsd openbsd solaris package net diff --git a/src/net/writev_test.go b/src/net/writev_test.go index bf40ca2023..b752295862 100644 --- a/src/net/writev_test.go +++ b/src/net/writev_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js -// +build !js package net diff --git a/src/net/writev_unix.go b/src/net/writev_unix.go index a0fedc2f99..51ab29dc31 100644 --- a/src/net/writev_unix.go +++ b/src/net/writev_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || illumos || linux || netbsd || openbsd -// +build darwin dragonfly freebsd illumos linux netbsd openbsd package net diff --git a/src/os/dir_unix.go b/src/os/dir_unix.go index 5589c9c682..4eeb9ab86c 100644 --- a/src/os/dir_unix.go +++ b/src/os/dir_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris -// +build aix dragonfly freebsd js,wasm linux netbsd openbsd solaris package os diff --git a/src/os/endian_big.go b/src/os/endian_big.go index 0529dccd6f..0375e53372 100644 --- a/src/os/endian_big.go +++ b/src/os/endian_big.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. // //go:build ppc64 || s390x || mips || mips64 -// +build ppc64 s390x mips mips64 package os diff --git a/src/os/endian_little.go b/src/os/endian_little.go index 6be6020f53..10643a804e 100644 --- a/src/os/endian_little.go +++ b/src/os/endian_little.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. // //go:build 386 || amd64 || arm || arm64 || ppc64le || mips64le || mipsle || riscv64 || wasm -// +build 386 amd64 arm arm64 ppc64le mips64le mipsle riscv64 wasm package os diff --git a/src/os/env_unix_test.go b/src/os/env_unix_test.go index d45e1deb83..75225d8547 100644 --- a/src/os/env_unix_test.go +++ b/src/os/env_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package os_test diff --git a/src/os/error_errno.go b/src/os/error_errno.go index 580e915b73..c8140461a4 100644 --- a/src/os/error_errno.go +++ b/src/os/error_errno.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !plan9 -// +build !plan9 package os diff --git a/src/os/error_posix.go b/src/os/error_posix.go index 268b3a923a..234f4eb692 100644 --- a/src/os/error_posix.go +++ b/src/os/error_posix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris || windows -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows package os diff --git a/src/os/error_unix_test.go b/src/os/error_unix_test.go index e45282a0fd..81bccebedb 100644 --- a/src/os/error_unix_test.go +++ b/src/os/error_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris package os_test diff --git a/src/os/error_windows_test.go b/src/os/error_windows_test.go index aa0c14b7d4..86c8a985bb 100644 --- a/src/os/error_windows_test.go +++ b/src/os/error_windows_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows -// +build windows package os_test diff --git a/src/os/exec/exec_linux_test.go b/src/os/exec/exec_linux_test.go index 3cfa30ee72..4a37c96e63 100644 --- a/src/os/exec/exec_linux_test.go +++ b/src/os/exec/exec_linux_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && cgo -// +build linux,cgo // On systems that use glibc, calling malloc can create a new arena, // and creating a new arena can read /sys/devices/system/cpu/online. diff --git a/src/os/exec/exec_posix_test.go b/src/os/exec/exec_posix_test.go index 7b2c0c0c11..fd7fb42d36 100644 --- a/src/os/exec/exec_posix_test.go +++ b/src/os/exec/exec_posix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package exec_test diff --git a/src/os/exec/exec_unix.go b/src/os/exec/exec_unix.go index 467c069e1c..c20f35276c 100644 --- a/src/os/exec/exec_unix.go +++ b/src/os/exec/exec_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !plan9 && !windows -// +build !plan9,!windows package exec diff --git a/src/os/exec/exec_windows_test.go b/src/os/exec/exec_windows_test.go index bd4dfb31da..8e31e47190 100644 --- a/src/os/exec/exec_windows_test.go +++ b/src/os/exec/exec_windows_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows -// +build windows package exec_test diff --git a/src/os/exec/lp_js.go b/src/os/exec/lp_js.go index 4eac25fe6f..54ddc4d5b4 100644 --- a/src/os/exec/lp_js.go +++ b/src/os/exec/lp_js.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm package exec diff --git a/src/os/exec/lp_unix.go b/src/os/exec/lp_unix.go index d1d246accf..38b9fc7c27 100644 --- a/src/os/exec/lp_unix.go +++ b/src/os/exec/lp_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package exec diff --git a/src/os/exec/lp_unix_test.go b/src/os/exec/lp_unix_test.go index 9fded0eb0a..52e401e580 100644 --- a/src/os/exec/lp_unix_test.go +++ b/src/os/exec/lp_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package exec diff --git a/src/os/exec/read3.go b/src/os/exec/read3.go index a8c71831d8..8aae5735c4 100644 --- a/src/os/exec/read3.go +++ b/src/os/exec/read3.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore // This is a test program that verifies that it can read from // descriptor 3 and that no other descriptors are open. diff --git a/src/os/exec_posix.go b/src/os/exec_posix.go index e8736f7c54..07e2b36f62 100644 --- a/src/os/exec_posix.go +++ b/src/os/exec_posix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris || windows -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows package os diff --git a/src/os/exec_unix.go b/src/os/exec_unix.go index d1bbeb7529..250c5c6402 100644 --- a/src/os/exec_unix.go +++ b/src/os/exec_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris package os diff --git a/src/os/exec_unix_test.go b/src/os/exec_unix_test.go index f14b3519fb..fa332bf1ed 100644 --- a/src/os/exec_unix_test.go +++ b/src/os/exec_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package os_test diff --git a/src/os/executable_path.go b/src/os/executable_path.go index 625430ecfc..d6161bcb08 100644 --- a/src/os/executable_path.go +++ b/src/os/executable_path.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || openbsd -// +build aix openbsd package os diff --git a/src/os/executable_plan9.go b/src/os/executable_plan9.go index ad7a4410dc..8d8c83260f 100644 --- a/src/os/executable_plan9.go +++ b/src/os/executable_plan9.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build plan9 -// +build plan9 package os diff --git a/src/os/executable_procfs.go b/src/os/executable_procfs.go index 76ba0e6d08..18348eab91 100644 --- a/src/os/executable_procfs.go +++ b/src/os/executable_procfs.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux || netbsd || (js && wasm) -// +build linux netbsd js,wasm package os diff --git a/src/os/executable_sysctl.go b/src/os/executable_sysctl.go index 039448b557..3c2aeacf7d 100644 --- a/src/os/executable_sysctl.go +++ b/src/os/executable_sysctl.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build freebsd || dragonfly -// +build freebsd dragonfly package os diff --git a/src/os/export_unix_test.go b/src/os/export_unix_test.go index 10f8312831..d4eb7a4fb1 100644 --- a/src/os/export_unix_test.go +++ b/src/os/export_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris package os diff --git a/src/os/fifo_test.go b/src/os/fifo_test.go index 007ed29129..de70927961 100644 --- a/src/os/fifo_test.go +++ b/src/os/fifo_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd -// +build darwin dragonfly freebsd linux netbsd openbsd package os_test diff --git a/src/os/file_posix.go b/src/os/file_posix.go index 211f2a1798..0dc6da0908 100644 --- a/src/os/file_posix.go +++ b/src/os/file_posix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris || windows -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows package os diff --git a/src/os/file_unix.go b/src/os/file_unix.go index a2531b9656..a38db18954 100644 --- a/src/os/file_unix.go +++ b/src/os/file_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris package os diff --git a/src/os/os_unix_test.go b/src/os/os_unix_test.go index 9b4c0ab290..3ec3dee24b 100644 --- a/src/os/os_unix_test.go +++ b/src/os/os_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris package os_test diff --git a/src/os/path_unix.go b/src/os/path_unix.go index db38359492..d1ffe2c187 100644 --- a/src/os/path_unix.go +++ b/src/os/path_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris package os diff --git a/src/os/pipe2_bsd.go b/src/os/pipe2_bsd.go index bf6d081db5..7eb1350d02 100644 --- a/src/os/pipe2_bsd.go +++ b/src/os/pipe2_bsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd || netbsd || openbsd -// +build dragonfly freebsd netbsd openbsd package os diff --git a/src/os/pipe2_illumos.go b/src/os/pipe2_illumos.go index 71b8cb8e25..354b35cc46 100644 --- a/src/os/pipe2_illumos.go +++ b/src/os/pipe2_illumos.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build illumos -// +build illumos package os diff --git a/src/os/pipe_bsd.go b/src/os/pipe_bsd.go index 097b32e7eb..554d62111a 100644 --- a/src/os/pipe_bsd.go +++ b/src/os/pipe_bsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || (js && wasm) || (solaris && !illumos) -// +build aix darwin js,wasm solaris,!illumos package os diff --git a/src/os/pipe_test.go b/src/os/pipe_test.go index 41a1e9c78a..ab6d1ce2b6 100644 --- a/src/os/pipe_test.go +++ b/src/os/pipe_test.go @@ -4,7 +4,6 @@ // Test broken pipes on Unix systems. //go:build !plan9 && !js -// +build !plan9,!js package os_test diff --git a/src/os/rawconn.go b/src/os/rawconn.go index ffc598b061..14a495d9c0 100644 --- a/src/os/rawconn.go +++ b/src/os/rawconn.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !plan9 -// +build !plan9 package os diff --git a/src/os/rawconn_test.go b/src/os/rawconn_test.go index 8aebaf87a6..fd2038a233 100644 --- a/src/os/rawconn_test.go +++ b/src/os/rawconn_test.go @@ -4,7 +4,6 @@ // Test use of raw connections. //go:build !plan9 && !js -// +build !plan9,!js package os_test diff --git a/src/os/readfrom_stub.go b/src/os/readfrom_stub.go index 826760f3df..8b7d5fb8f9 100644 --- a/src/os/readfrom_stub.go +++ b/src/os/readfrom_stub.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !linux -// +build !linux package os diff --git a/src/os/removeall_at.go b/src/os/removeall_at.go index d04540bc63..da804c436f 100644 --- a/src/os/removeall_at.go +++ b/src/os/removeall_at.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package os diff --git a/src/os/removeall_noat.go b/src/os/removeall_noat.go index 853e0eddfc..a0332e8c35 100644 --- a/src/os/removeall_noat.go +++ b/src/os/removeall_noat.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris -// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris package os diff --git a/src/os/signal/example_unix_test.go b/src/os/signal/example_unix_test.go index 3f7795b8cf..b279ee9491 100644 --- a/src/os/signal/example_unix_test.go +++ b/src/os/signal/example_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package signal_test diff --git a/src/os/signal/internal/pty/pty.go b/src/os/signal/internal/pty/pty.go index 8d2eac7103..537febba55 100644 --- a/src/os/signal/internal/pty/pty.go +++ b/src/os/signal/internal/pty/pty.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (aix || darwin || dragonfly || freebsd || (linux && !android) || netbsd || openbsd) && cgo -// +build aix darwin dragonfly freebsd linux,!android netbsd openbsd -// +build cgo // Package pty is a simple pseudo-terminal package for Unix systems, // implemented by calling C functions via cgo. diff --git a/src/os/signal/signal_cgo_test.go b/src/os/signal/signal_cgo_test.go index e1e4509e2a..67bad66e0b 100644 --- a/src/os/signal/signal_cgo_test.go +++ b/src/os/signal/signal_cgo_test.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (darwin || dragonfly || freebsd || (linux && !android) || netbsd || openbsd) && cgo -// +build darwin dragonfly freebsd linux,!android netbsd openbsd -// +build cgo // Note that this test does not work on Solaris: issue #22849. // Don't run the test on Android because at least some versions of the diff --git a/src/os/signal/signal_linux_test.go b/src/os/signal/signal_linux_test.go index 7abe1ec5a0..f70f108442 100644 --- a/src/os/signal/signal_linux_test.go +++ b/src/os/signal/signal_linux_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux -// +build linux package signal diff --git a/src/os/signal/signal_test.go b/src/os/signal/signal_test.go index 649854b746..3e85d936f8 100644 --- a/src/os/signal/signal_test.go +++ b/src/os/signal/signal_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package signal diff --git a/src/os/signal/signal_unix.go b/src/os/signal/signal_unix.go index 9e241c43ac..e2e5c4ae97 100644 --- a/src/os/signal/signal_unix.go +++ b/src/os/signal/signal_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris || windows -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows package signal diff --git a/src/os/stat_js.go b/src/os/stat_js.go index 3badf5ba57..c3e9b5b5e5 100644 --- a/src/os/stat_js.go +++ b/src/os/stat_js.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm package os diff --git a/src/os/stat_unix.go b/src/os/stat_unix.go index 8c17805f71..eb15db5453 100644 --- a/src/os/stat_unix.go +++ b/src/os/stat_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris package os diff --git a/src/os/sticky_bsd.go b/src/os/sticky_bsd.go index ab23d8111d..e71daf7c74 100644 --- a/src/os/sticky_bsd.go +++ b/src/os/sticky_bsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd js,wasm netbsd openbsd solaris package os diff --git a/src/os/sticky_notbsd.go b/src/os/sticky_notbsd.go index 9979b43e8e..9a87fbde92 100644 --- a/src/os/sticky_notbsd.go +++ b/src/os/sticky_notbsd.go @@ -3,14 +3,6 @@ // license that can be found in the LICENSE file. //go:build !aix && !darwin && !dragonfly && !freebsd && (!js || !wasm) && !netbsd && !openbsd && !solaris -// +build !aix -// +build !darwin -// +build !dragonfly -// +build !freebsd -// +build !js !wasm -// +build !netbsd -// +build !openbsd -// +build !solaris package os diff --git a/src/os/sys_bsd.go b/src/os/sys_bsd.go index 1e245eb53a..e272c24571 100644 --- a/src/os/sys_bsd.go +++ b/src/os/sys_bsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || (js && wasm) || netbsd || openbsd -// +build darwin dragonfly freebsd js,wasm netbsd openbsd package os diff --git a/src/os/sys_js.go b/src/os/sys_js.go index 4d6a64e8eb..4fd0e2d7c7 100644 --- a/src/os/sys_js.go +++ b/src/os/sys_js.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm package os diff --git a/src/os/sys_unix.go b/src/os/sys_unix.go index e316eaf06c..5ff39780e5 100644 --- a/src/os/sys_unix.go +++ b/src/os/sys_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package os diff --git a/src/os/timeout_test.go b/src/os/timeout_test.go index 6d65e420f0..2ff58110d6 100644 --- a/src/os/timeout_test.go +++ b/src/os/timeout_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js && !plan9 && !windows -// +build !js,!plan9,!windows package os_test diff --git a/src/os/types_unix.go b/src/os/types_unix.go index e9b8b8ba3a..105bb78765 100644 --- a/src/os/types_unix.go +++ b/src/os/types_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !windows && !plan9 -// +build !windows,!plan9 package os diff --git a/src/os/user/cgo_listgroups_unix.go b/src/os/user/cgo_listgroups_unix.go index 38aa7653b0..0d937da334 100644 --- a/src/os/user/cgo_listgroups_unix.go +++ b/src/os/user/cgo_listgroups_unix.go @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build (dragonfly || darwin || freebsd || (!android && linux) || netbsd || openbsd || (solaris && !illumos)) && cgo && !osusergo -// +build dragonfly darwin freebsd !android,linux netbsd openbsd solaris,!illumos -// +build cgo -// +build !osusergo package user diff --git a/src/os/user/cgo_lookup_unix.go b/src/os/user/cgo_lookup_unix.go index 5c972e77cf..523269086e 100644 --- a/src/os/user/cgo_lookup_unix.go +++ b/src/os/user/cgo_lookup_unix.go @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build (aix || darwin || dragonfly || freebsd || (!android && linux) || netbsd || openbsd || solaris) && cgo && !osusergo -// +build aix darwin dragonfly freebsd !android,linux netbsd openbsd solaris -// +build cgo -// +build !osusergo package user diff --git a/src/os/user/cgo_unix_test.go b/src/os/user/cgo_unix_test.go index 9ec32b3a78..6d16aa20b3 100644 --- a/src/os/user/cgo_unix_test.go +++ b/src/os/user/cgo_unix_test.go @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build (darwin || dragonfly || freebsd || (!android && linux) || netbsd || openbsd || solaris) && cgo && !osusergo -// +build darwin dragonfly freebsd !android,linux netbsd openbsd solaris -// +build cgo -// +build !osusergo package user diff --git a/src/os/user/getgrouplist_darwin.go b/src/os/user/getgrouplist_darwin.go index 23d12e3247..db6fb87e23 100644 --- a/src/os/user/getgrouplist_darwin.go +++ b/src/os/user/getgrouplist_darwin.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build cgo && !osusergo -// +build cgo,!osusergo package user diff --git a/src/os/user/getgrouplist_unix.go b/src/os/user/getgrouplist_unix.go index fd66961ccf..104c2243df 100644 --- a/src/os/user/getgrouplist_unix.go +++ b/src/os/user/getgrouplist_unix.go @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build (dragonfly || freebsd || (!android && linux) || netbsd || openbsd || (solaris && !illumos)) && cgo && !osusergo -// +build dragonfly freebsd !android,linux netbsd openbsd solaris,!illumos -// +build cgo -// +build !osusergo package user diff --git a/src/os/user/listgroups_stub.go b/src/os/user/listgroups_stub.go index a066c6db71..4cf808b65d 100644 --- a/src/os/user/listgroups_stub.go +++ b/src/os/user/listgroups_stub.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build android || (js && !wasm) -// +build android js,!wasm package user diff --git a/src/os/user/lookup_android.go b/src/os/user/lookup_android.go index 151aab49c2..0ae31fd818 100644 --- a/src/os/user/lookup_android.go +++ b/src/os/user/lookup_android.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build android -// +build android package user diff --git a/src/os/user/lookup_stubs.go b/src/os/user/lookup_stubs.go index efaa92923d..ce1617d250 100644 --- a/src/os/user/lookup_stubs.go +++ b/src/os/user/lookup_stubs.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build (!cgo && !windows && !plan9) || android || (osusergo && !windows && !plan9) -// +build !cgo,!windows,!plan9 android osusergo,!windows,!plan9 package user diff --git a/src/os/user/lookup_unix.go b/src/os/user/lookup_unix.go index 1cabdb5b71..e25323fbad 100644 --- a/src/os/user/lookup_unix.go +++ b/src/os/user/lookup_unix.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (aix || darwin || dragonfly || freebsd || (js && wasm) || (!android && linux) || netbsd || openbsd || solaris) && (!cgo || osusergo) -// +build aix darwin dragonfly freebsd js,wasm !android,linux netbsd openbsd solaris -// +build !cgo osusergo package user diff --git a/src/os/user/lookup_unix_test.go b/src/os/user/lookup_unix_test.go index 05d23567c3..77917677fc 100644 --- a/src/os/user/lookup_unix_test.go +++ b/src/os/user/lookup_unix_test.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (aix || darwin || dragonfly || freebsd || (!android && linux) || netbsd || openbsd || solaris) && !cgo -// +build aix darwin dragonfly freebsd !android,linux netbsd openbsd solaris -// +build !cgo package user diff --git a/src/os/wait_unimp.go b/src/os/wait_unimp.go index c1f66ca155..721b9f9f7e 100644 --- a/src/os/wait_unimp.go +++ b/src/os/wait_unimp.go @@ -7,7 +7,6 @@ // failures, see issue #48789. //go:build aix || darwin || (js && wasm) || netbsd || openbsd || solaris -// +build aix darwin js,wasm netbsd openbsd solaris package os diff --git a/src/os/wait_wait6.go b/src/os/wait_wait6.go index 51193401f9..d395dac40b 100644 --- a/src/os/wait_wait6.go +++ b/src/os/wait_wait6.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd -// +build dragonfly freebsd package os diff --git a/src/os/wait_waitid.go b/src/os/wait_waitid.go index 44962c8534..c0503b209c 100644 --- a/src/os/wait_waitid.go +++ b/src/os/wait_waitid.go @@ -6,7 +6,6 @@ // waitid returns if the process is stopped, even when using WEXITED. //go:build linux -// +build linux package os diff --git a/src/path/filepath/example_unix_test.go b/src/path/filepath/example_unix_test.go index 4ce10095e6..b364cf0608 100644 --- a/src/path/filepath/example_unix_test.go +++ b/src/path/filepath/example_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !windows && !plan9 -// +build !windows,!plan9 package filepath_test diff --git a/src/path/filepath/example_unix_walk_test.go b/src/path/filepath/example_unix_walk_test.go index d72efcebe6..86146dba5b 100644 --- a/src/path/filepath/example_unix_walk_test.go +++ b/src/path/filepath/example_unix_walk_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !windows && !plan9 -// +build !windows,!plan9 package filepath_test diff --git a/src/path/filepath/path_unix.go b/src/path/filepath/path_unix.go index d4b6f967a3..dcf1d187e7 100644 --- a/src/path/filepath/path_unix.go +++ b/src/path/filepath/path_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris package filepath diff --git a/src/path/filepath/symlink_unix.go b/src/path/filepath/symlink_unix.go index 657945a81a..7bfe17e2fd 100644 --- a/src/path/filepath/symlink_unix.go +++ b/src/path/filepath/symlink_unix.go @@ -1,5 +1,4 @@ //go:build !windows -// +build !windows package filepath diff --git a/src/plugin/plugin_dlopen.go b/src/plugin/plugin_dlopen.go index aa85d4831c..5fff329fc5 100644 --- a/src/plugin/plugin_dlopen.go +++ b/src/plugin/plugin_dlopen.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build (linux && cgo) || (darwin && cgo) || (freebsd && cgo) -// +build linux,cgo darwin,cgo freebsd,cgo package plugin diff --git a/src/plugin/plugin_stubs.go b/src/plugin/plugin_stubs.go index 67855bed4b..2e9492e7c6 100644 --- a/src/plugin/plugin_stubs.go +++ b/src/plugin/plugin_stubs.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build (!linux && !freebsd && !darwin) || !cgo -// +build !linux,!freebsd,!darwin !cgo package plugin diff --git a/src/plugin/plugin_test.go b/src/plugin/plugin_test.go index 4ce912132c..8185095f85 100644 --- a/src/plugin/plugin_test.go +++ b/src/plugin/plugin_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !linux || (linux && !arm64) -// +build !linux linux,!arm64 package plugin_test diff --git a/src/reflect/abi_test.go b/src/reflect/abi_test.go index 873febbad2..41cfd9d082 100644 --- a/src/reflect/abi_test.go +++ b/src/reflect/abi_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build goexperiment.regabireflect && goexperiment.regabiargs -// +build goexperiment.regabireflect,goexperiment.regabiargs package reflect_test diff --git a/src/reflect/float32reg_generic.go b/src/reflect/float32reg_generic.go index bfceb9ecaa..307c0bb33c 100644 --- a/src/reflect/float32reg_generic.go +++ b/src/reflect/float32reg_generic.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !ppc64 && !ppc64le -// +build !ppc64,!ppc64le package reflect diff --git a/src/reflect/stubs_ppc64x.go b/src/reflect/stubs_ppc64x.go index dbd3f9e748..06c8bf5483 100644 --- a/src/reflect/stubs_ppc64x.go +++ b/src/reflect/stubs_ppc64x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64le || ppc64 -// +build ppc64le ppc64 package reflect diff --git a/src/regexp/exec2_test.go b/src/regexp/exec2_test.go index 6444bc12f9..b6dac4a058 100644 --- a/src/regexp/exec2_test.go +++ b/src/regexp/exec2_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !race -// +build !race package regexp diff --git a/src/runtime/abi_test.go b/src/runtime/abi_test.go index f69d3a9d50..5c1f1f4067 100644 --- a/src/runtime/abi_test.go +++ b/src/runtime/abi_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build goexperiment.regabireflect -// +build goexperiment.regabireflect // This file contains tests specific to making sure the register ABI // works in a bunch of contexts in the runtime. diff --git a/src/runtime/asan.go b/src/runtime/asan.go index 7ff5f26bfb..a22b56bb07 100644 --- a/src/runtime/asan.go +++ b/src/runtime/asan.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build asan -// +build asan package runtime diff --git a/src/runtime/asan0.go b/src/runtime/asan0.go index dad069bbe6..d5478d6bee 100644 --- a/src/runtime/asan0.go +++ b/src/runtime/asan0.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !asan -// +build !asan // Dummy ASan support API, used when not built with -asan. diff --git a/src/runtime/auxv_none.go b/src/runtime/auxv_none.go index 3178f1a154..5d473cab5c 100644 --- a/src/runtime/auxv_none.go +++ b/src/runtime/auxv_none.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !linux && !darwin && !dragonfly && !freebsd && !netbsd && !solaris -// +build !linux,!darwin,!dragonfly,!freebsd,!netbsd,!solaris package runtime diff --git a/src/runtime/cgo/callbacks_traceback.go b/src/runtime/cgo/callbacks_traceback.go index 7302c1eedf..dae31a8fcd 100644 --- a/src/runtime/cgo/callbacks_traceback.go +++ b/src/runtime/cgo/callbacks_traceback.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || linux -// +build darwin linux package cgo diff --git a/src/runtime/cgo/dragonfly.go b/src/runtime/cgo/dragonfly.go index cfa6fe86e2..36d70e34e2 100644 --- a/src/runtime/cgo/dragonfly.go +++ b/src/runtime/cgo/dragonfly.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly -// +build dragonfly package cgo diff --git a/src/runtime/cgo/freebsd.go b/src/runtime/cgo/freebsd.go index d56702ec70..2d9f6245b5 100644 --- a/src/runtime/cgo/freebsd.go +++ b/src/runtime/cgo/freebsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build freebsd -// +build freebsd package cgo diff --git a/src/runtime/cgo/linux.go b/src/runtime/cgo/linux.go index 070d531bee..1d6fe03917 100644 --- a/src/runtime/cgo/linux.go +++ b/src/runtime/cgo/linux.go @@ -6,7 +6,6 @@ // corresponding cgo->libc (nptl) wrappers for various system calls. //go:build linux -// +build linux package cgo diff --git a/src/runtime/cgo/mmap.go b/src/runtime/cgo/mmap.go index 347ae6b363..eae0a9e7cc 100644 --- a/src/runtime/cgo/mmap.go +++ b/src/runtime/cgo/mmap.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build (linux && amd64) || (linux && arm64) -// +build linux,amd64 linux,arm64 package cgo diff --git a/src/runtime/cgo/netbsd.go b/src/runtime/cgo/netbsd.go index 7e17d1fcd2..8a8018b7a8 100644 --- a/src/runtime/cgo/netbsd.go +++ b/src/runtime/cgo/netbsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build netbsd -// +build netbsd package cgo diff --git a/src/runtime/cgo/openbsd.go b/src/runtime/cgo/openbsd.go index f6215613c3..872d02e334 100644 --- a/src/runtime/cgo/openbsd.go +++ b/src/runtime/cgo/openbsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build openbsd -// +build openbsd package cgo diff --git a/src/runtime/cgo/setenv.go b/src/runtime/cgo/setenv.go index e6e8040ae0..0f4780a945 100644 --- a/src/runtime/cgo/setenv.go +++ b/src/runtime/cgo/setenv.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package cgo diff --git a/src/runtime/cgo/sigaction.go b/src/runtime/cgo/sigaction.go index 692fd2675f..dc714f7ef4 100644 --- a/src/runtime/cgo/sigaction.go +++ b/src/runtime/cgo/sigaction.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build (linux && amd64) || (freebsd && amd64) || (linux && arm64) || (linux && ppc64le) -// +build linux,amd64 freebsd,amd64 linux,arm64 linux,ppc64le package cgo diff --git a/src/runtime/cgo_mmap.go b/src/runtime/cgo_mmap.go index 17d26b4cc8..0cb25bdcda 100644 --- a/src/runtime/cgo_mmap.go +++ b/src/runtime/cgo_mmap.go @@ -5,7 +5,6 @@ // Support for memory sanitizer. See runtime/cgo/mmap.go. //go:build (linux && amd64) || (linux && arm64) -// +build linux,amd64 linux,arm64 package runtime diff --git a/src/runtime/cgo_ppc64x.go b/src/runtime/cgo_ppc64x.go index 4dc92ea321..97b962e40f 100644 --- a/src/runtime/cgo_ppc64x.go +++ b/src/runtime/cgo_ppc64x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le package runtime diff --git a/src/runtime/cgo_sigaction.go b/src/runtime/cgo_sigaction.go index 6099d1b746..7e8ae28275 100644 --- a/src/runtime/cgo_sigaction.go +++ b/src/runtime/cgo_sigaction.go @@ -5,7 +5,6 @@ // Support for sanitizers. See runtime/cgo/sigaction.go. //go:build (linux && amd64) || (freebsd && amd64) || (linux && arm64) || (linux && ppc64le) -// +build linux,amd64 freebsd,amd64 linux,arm64 linux,ppc64le package runtime diff --git a/src/runtime/cputicks.go b/src/runtime/cputicks.go index 7c926f4a2b..2cf3240333 100644 --- a/src/runtime/cputicks.go +++ b/src/runtime/cputicks.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !arm && !arm64 && !mips64 && !mips64le && !mips && !mipsle && !wasm -// +build !arm,!arm64,!mips64,!mips64le,!mips,!mipsle,!wasm package runtime diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go index c0d4569462..e6d1742a38 100644 --- a/src/runtime/crash_cgo_test.go +++ b/src/runtime/crash_cgo_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build cgo -// +build cgo package runtime_test diff --git a/src/runtime/crash_nonunix_test.go b/src/runtime/crash_nonunix_test.go index 5f61476f21..73c1cd3101 100644 --- a/src/runtime/crash_nonunix_test.go +++ b/src/runtime/crash_nonunix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows || plan9 || (js && wasm) -// +build windows plan9 js,wasm package runtime_test diff --git a/src/runtime/crash_unix_test.go b/src/runtime/crash_unix_test.go index 694cc3d138..0d9d22aa49 100644 --- a/src/runtime/crash_unix_test.go +++ b/src/runtime/crash_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package runtime_test diff --git a/src/runtime/debug/panic_test.go b/src/runtime/debug/panic_test.go index 65f9555f37..ec5294ce4c 100644 --- a/src/runtime/debug/panic_test.go +++ b/src/runtime/debug/panic_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd -// +build aix darwin dragonfly freebsd linux netbsd openbsd // TODO: test on Windows? diff --git a/src/runtime/debug_test.go b/src/runtime/debug_test.go index f74383457f..b5db7a55f1 100644 --- a/src/runtime/debug_test.go +++ b/src/runtime/debug_test.go @@ -10,7 +10,6 @@ // point. //go:build amd64 && linux && !race -// +build amd64,linux,!race package runtime_test diff --git a/src/runtime/debugcall.go b/src/runtime/debugcall.go index a1440f7649..005a259f28 100644 --- a/src/runtime/debugcall.go +++ b/src/runtime/debugcall.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 -// +build amd64 package runtime diff --git a/src/runtime/debuglog_off.go b/src/runtime/debuglog_off.go index dd38156999..fa3be39c70 100644 --- a/src/runtime/debuglog_off.go +++ b/src/runtime/debuglog_off.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !debuglog -// +build !debuglog package runtime diff --git a/src/runtime/debuglog_on.go b/src/runtime/debuglog_on.go index 2fcdbe70d1..b815020225 100644 --- a/src/runtime/debuglog_on.go +++ b/src/runtime/debuglog_on.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build debuglog -// +build debuglog package runtime diff --git a/src/runtime/defs1_linux.go b/src/runtime/defs1_linux.go index df9c05dd5e..709f19e599 100644 --- a/src/runtime/defs1_linux.go +++ b/src/runtime/defs1_linux.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore /* Input to cgo -cdefs diff --git a/src/runtime/defs2_linux.go b/src/runtime/defs2_linux.go index d016db7d02..41ad73576f 100644 --- a/src/runtime/defs2_linux.go +++ b/src/runtime/defs2_linux.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore /* * Input to cgo -cdefs diff --git a/src/runtime/defs3_linux.go b/src/runtime/defs3_linux.go index 0a06aa2370..99479aad06 100644 --- a/src/runtime/defs3_linux.go +++ b/src/runtime/defs3_linux.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore /* Input to cgo -cdefs diff --git a/src/runtime/defs_aix.go b/src/runtime/defs_aix.go index 1605002ea2..b794cd5de8 100644 --- a/src/runtime/defs_aix.go +++ b/src/runtime/defs_aix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore /* Input to cgo -godefs diff --git a/src/runtime/defs_aix_ppc64.go b/src/runtime/defs_aix_ppc64.go index f84ff1160d..4e20c85841 100644 --- a/src/runtime/defs_aix_ppc64.go +++ b/src/runtime/defs_aix_ppc64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix -// +build aix package runtime diff --git a/src/runtime/defs_arm_linux.go b/src/runtime/defs_arm_linux.go index f6b6dd2c09..805735bd0e 100644 --- a/src/runtime/defs_arm_linux.go +++ b/src/runtime/defs_arm_linux.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore /* Input to cgo. diff --git a/src/runtime/defs_darwin.go b/src/runtime/defs_darwin.go index 2d41a97b57..59b81cf713 100644 --- a/src/runtime/defs_darwin.go +++ b/src/runtime/defs_darwin.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore /* Input to cgo. diff --git a/src/runtime/defs_dragonfly.go b/src/runtime/defs_dragonfly.go index aca2bf9001..47a2e4d123 100644 --- a/src/runtime/defs_dragonfly.go +++ b/src/runtime/defs_dragonfly.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore /* Input to cgo. diff --git a/src/runtime/defs_freebsd.go b/src/runtime/defs_freebsd.go index c258759549..9ba97c8459 100644 --- a/src/runtime/defs_freebsd.go +++ b/src/runtime/defs_freebsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore /* Input to cgo. diff --git a/src/runtime/defs_linux.go b/src/runtime/defs_linux.go index 7c3167032f..fa94e388f4 100644 --- a/src/runtime/defs_linux.go +++ b/src/runtime/defs_linux.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore /* Input to cgo -cdefs diff --git a/src/runtime/defs_linux_mips64x.go b/src/runtime/defs_linux_mips64x.go index 1743bbce41..63433cb9be 100644 --- a/src/runtime/defs_linux_mips64x.go +++ b/src/runtime/defs_linux_mips64x.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (mips64 || mips64le) && linux -// +build mips64 mips64le -// +build linux package runtime diff --git a/src/runtime/defs_linux_mipsx.go b/src/runtime/defs_linux_mipsx.go index e84d4979e1..ffbf5051eb 100644 --- a/src/runtime/defs_linux_mipsx.go +++ b/src/runtime/defs_linux_mipsx.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (mips || mipsle) && linux -// +build mips mipsle -// +build linux package runtime diff --git a/src/runtime/defs_netbsd.go b/src/runtime/defs_netbsd.go index 755992d18e..df8bc579f2 100644 --- a/src/runtime/defs_netbsd.go +++ b/src/runtime/defs_netbsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore /* Input to cgo. diff --git a/src/runtime/defs_netbsd_386.go b/src/runtime/defs_netbsd_386.go index 03c9c2de59..2943ea3f13 100644 --- a/src/runtime/defs_netbsd_386.go +++ b/src/runtime/defs_netbsd_386.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore /* Input to cgo. diff --git a/src/runtime/defs_netbsd_amd64.go b/src/runtime/defs_netbsd_amd64.go index 9fda1d7d22..33d80ff53c 100644 --- a/src/runtime/defs_netbsd_amd64.go +++ b/src/runtime/defs_netbsd_amd64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore /* Input to cgo. diff --git a/src/runtime/defs_netbsd_arm.go b/src/runtime/defs_netbsd_arm.go index e7f4f6cece..74b37527df 100644 --- a/src/runtime/defs_netbsd_arm.go +++ b/src/runtime/defs_netbsd_arm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore /* Input to cgo. diff --git a/src/runtime/defs_openbsd.go b/src/runtime/defs_openbsd.go index f818dc4453..ec7d82a33c 100644 --- a/src/runtime/defs_openbsd.go +++ b/src/runtime/defs_openbsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore /* Input to cgo. diff --git a/src/runtime/defs_solaris.go b/src/runtime/defs_solaris.go index e644f9c6dd..ec16c9dcce 100644 --- a/src/runtime/defs_solaris.go +++ b/src/runtime/defs_solaris.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore /* Input to cgo. diff --git a/src/runtime/defs_solaris_amd64.go b/src/runtime/defs_solaris_amd64.go index a0b38319a5..56e4b38c5e 100644 --- a/src/runtime/defs_solaris_amd64.go +++ b/src/runtime/defs_solaris_amd64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore /* Input to cgo. diff --git a/src/runtime/env_posix.go b/src/runtime/env_posix.go index 95517b2a95..44086c1d63 100644 --- a/src/runtime/env_posix.go +++ b/src/runtime/env_posix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris || windows || plan9 -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows plan9 package runtime diff --git a/src/runtime/export_debug_regabiargs_off_test.go b/src/runtime/export_debug_regabiargs_off_test.go index 5009003d27..81f73925d5 100644 --- a/src/runtime/export_debug_regabiargs_off_test.go +++ b/src/runtime/export_debug_regabiargs_off_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 && linux && !goexperiment.regabiargs -// +build amd64,linux,!goexperiment.regabiargs package runtime diff --git a/src/runtime/export_debug_regabiargs_on_test.go b/src/runtime/export_debug_regabiargs_on_test.go index e1b72efd0f..7d1ab6888e 100644 --- a/src/runtime/export_debug_regabiargs_on_test.go +++ b/src/runtime/export_debug_regabiargs_on_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 && linux && goexperiment.regabiargs -// +build amd64,linux,goexperiment.regabiargs package runtime diff --git a/src/runtime/export_debug_test.go b/src/runtime/export_debug_test.go index a2cef02cf8..032a9b9725 100644 --- a/src/runtime/export_debug_test.go +++ b/src/runtime/export_debug_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 && linux -// +build amd64,linux package runtime diff --git a/src/runtime/export_futex_test.go b/src/runtime/export_futex_test.go index 34c970d6d2..03157d8eed 100644 --- a/src/runtime/export_futex_test.go +++ b/src/runtime/export_futex_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd || linux -// +build dragonfly freebsd linux package runtime diff --git a/src/runtime/export_mmap_test.go b/src/runtime/export_mmap_test.go index bf4a815899..f9c3229316 100644 --- a/src/runtime/export_mmap_test.go +++ b/src/runtime/export_mmap_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris // Export guts for testing. diff --git a/src/runtime/export_pipe2_test.go b/src/runtime/export_pipe2_test.go index 26d8b7d185..bdf39c60df 100644 --- a/src/runtime/export_pipe2_test.go +++ b/src/runtime/export_pipe2_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build dragonfly freebsd linux netbsd openbsd solaris package runtime diff --git a/src/runtime/export_pipe_test.go b/src/runtime/export_pipe_test.go index a0c6c0440d..0583039982 100644 --- a/src/runtime/export_pipe_test.go +++ b/src/runtime/export_pipe_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin -// +build aix darwin package runtime diff --git a/src/runtime/export_unix_test.go b/src/runtime/export_unix_test.go index 215e234286..9f046b95e0 100644 --- a/src/runtime/export_unix_test.go +++ b/src/runtime/export_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package runtime diff --git a/src/runtime/futex_test.go b/src/runtime/futex_test.go index 10a735327a..188d0c6525 100644 --- a/src/runtime/futex_test.go +++ b/src/runtime/futex_test.go @@ -7,8 +7,6 @@ // the test. //go:build (dragonfly || freebsd || linux) && !race -// +build dragonfly freebsd linux -// +build !race package runtime_test diff --git a/src/runtime/hash32.go b/src/runtime/hash32.go index 7c22c76b87..0616c7dd05 100644 --- a/src/runtime/hash32.go +++ b/src/runtime/hash32.go @@ -6,7 +6,6 @@ // wyhash: https://github.com/wangyi-fudan/wyhash/blob/ceb019b530e2c1c14d70b79bfa2bc49de7d95bc1/Modern%20Non-Cryptographic%20Hash%20Function%20and%20Pseudorandom%20Number%20Generator.pdf //go:build 386 || arm || mips || mipsle -// +build 386 arm mips mipsle package runtime diff --git a/src/runtime/hash64.go b/src/runtime/hash64.go index 5f7d00bf7f..f773eb929c 100644 --- a/src/runtime/hash64.go +++ b/src/runtime/hash64.go @@ -6,7 +6,6 @@ // wyhash: https://github.com/wangyi-fudan/wyhash //go:build amd64 || arm64 || mips64 || mips64le || ppc64 || ppc64le || riscv64 || s390x || wasm -// +build amd64 arm64 mips64 mips64le ppc64 ppc64le riscv64 s390x wasm package runtime diff --git a/src/runtime/internal/atomic/atomic_386.go b/src/runtime/internal/atomic/atomic_386.go index d4aed6b671..27a77ec37a 100644 --- a/src/runtime/internal/atomic/atomic_386.go +++ b/src/runtime/internal/atomic/atomic_386.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build 386 -// +build 386 package atomic diff --git a/src/runtime/internal/atomic/atomic_arm.go b/src/runtime/internal/atomic/atomic_arm.go index 2e9374ca26..e2539b6c7e 100644 --- a/src/runtime/internal/atomic/atomic_arm.go +++ b/src/runtime/internal/atomic/atomic_arm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm -// +build arm package atomic diff --git a/src/runtime/internal/atomic/atomic_arm64.go b/src/runtime/internal/atomic/atomic_arm64.go index dbb1796ec0..459fb9978d 100644 --- a/src/runtime/internal/atomic/atomic_arm64.go +++ b/src/runtime/internal/atomic/atomic_arm64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm64 -// +build arm64 package atomic diff --git a/src/runtime/internal/atomic/atomic_mips64x.go b/src/runtime/internal/atomic/atomic_mips64x.go index 5b407ebc7a..1e12b83801 100644 --- a/src/runtime/internal/atomic/atomic_mips64x.go +++ b/src/runtime/internal/atomic/atomic_mips64x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips64 || mips64le -// +build mips64 mips64le package atomic diff --git a/src/runtime/internal/atomic/atomic_mipsx.go b/src/runtime/internal/atomic/atomic_mipsx.go index 80cd65b333..e552e57495 100644 --- a/src/runtime/internal/atomic/atomic_mipsx.go +++ b/src/runtime/internal/atomic/atomic_mipsx.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips || mipsle -// +build mips mipsle // Export some functions via linkname to assembly in sync/atomic. //go:linkname Xadd64 diff --git a/src/runtime/internal/atomic/atomic_ppc64x.go b/src/runtime/internal/atomic/atomic_ppc64x.go index 98101e3287..998d16e3f6 100644 --- a/src/runtime/internal/atomic/atomic_ppc64x.go +++ b/src/runtime/internal/atomic/atomic_ppc64x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le package atomic diff --git a/src/runtime/internal/atomic/stubs.go b/src/runtime/internal/atomic/stubs.go index e7544ba448..7df8d9c863 100644 --- a/src/runtime/internal/atomic/stubs.go +++ b/src/runtime/internal/atomic/stubs.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !wasm -// +build !wasm package atomic diff --git a/src/runtime/internal/atomic/types_64bit.go b/src/runtime/internal/atomic/types_64bit.go index 9e5ed68419..43c1ba2709 100644 --- a/src/runtime/internal/atomic/types_64bit.go +++ b/src/runtime/internal/atomic/types_64bit.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 || arm64 || mips64 || mips64le || ppc64 || ppc64le || riscv64 || s390x || wasm -// +build amd64 arm64 mips64 mips64le ppc64 ppc64le riscv64 s390x wasm package atomic diff --git a/src/runtime/internal/sys/intrinsics.go b/src/runtime/internal/sys/intrinsics.go index e76d8dd064..5af49011e9 100644 --- a/src/runtime/internal/sys/intrinsics.go +++ b/src/runtime/internal/sys/intrinsics.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !386 -// +build !386 // TODO finish intrinsifying 386, deadcode the assembly, remove build tags, merge w/ intrinsics_common // TODO replace all uses of CtzXX with TrailingZerosXX; they are the same. diff --git a/src/runtime/internal/sys/intrinsics_stubs.go b/src/runtime/internal/sys/intrinsics_stubs.go index bf1494d48a..a020652f76 100644 --- a/src/runtime/internal/sys/intrinsics_stubs.go +++ b/src/runtime/internal/sys/intrinsics_stubs.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build 386 -// +build 386 package sys diff --git a/src/runtime/lfstack_32bit.go b/src/runtime/lfstack_32bit.go index c00f0965bd..405923cc34 100644 --- a/src/runtime/lfstack_32bit.go +++ b/src/runtime/lfstack_32bit.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build 386 || arm || mips || mipsle -// +build 386 arm mips mipsle package runtime diff --git a/src/runtime/lfstack_64bit.go b/src/runtime/lfstack_64bit.go index 4812dd1156..3f0e480897 100644 --- a/src/runtime/lfstack_64bit.go +++ b/src/runtime/lfstack_64bit.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 || arm64 || mips64 || mips64le || ppc64 || ppc64le || riscv64 || s390x || wasm -// +build amd64 arm64 mips64 mips64le ppc64 ppc64le riscv64 s390x wasm package runtime diff --git a/src/runtime/libfuzzer.go b/src/runtime/libfuzzer.go index 578bce0414..e7b3cdc46a 100644 --- a/src/runtime/libfuzzer.go +++ b/src/runtime/libfuzzer.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build libfuzzer -// +build libfuzzer package runtime diff --git a/src/runtime/lock_futex.go b/src/runtime/lock_futex.go index e4c8d01941..575df7a1d5 100644 --- a/src/runtime/lock_futex.go +++ b/src/runtime/lock_futex.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd || linux -// +build dragonfly freebsd linux package runtime diff --git a/src/runtime/lock_js.go b/src/runtime/lock_js.go index 0ca3512baf..80ee50da35 100644 --- a/src/runtime/lock_js.go +++ b/src/runtime/lock_js.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm package runtime diff --git a/src/runtime/lock_sema.go b/src/runtime/lock_sema.go index 7a6af28b56..db36df1f37 100644 --- a/src/runtime/lock_sema.go +++ b/src/runtime/lock_sema.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || netbsd || openbsd || plan9 || solaris || windows -// +build aix darwin netbsd openbsd plan9 solaris windows package runtime diff --git a/src/runtime/lockrank_off.go b/src/runtime/lockrank_off.go index f3d2c00914..daa45b542d 100644 --- a/src/runtime/lockrank_off.go +++ b/src/runtime/lockrank_off.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !goexperiment.staticlockranking -// +build !goexperiment.staticlockranking package runtime diff --git a/src/runtime/lockrank_on.go b/src/runtime/lockrank_on.go index fc8d2dc8d1..3c8c367c19 100644 --- a/src/runtime/lockrank_on.go +++ b/src/runtime/lockrank_on.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build goexperiment.staticlockranking -// +build goexperiment.staticlockranking package runtime diff --git a/src/runtime/mem_bsd.go b/src/runtime/mem_bsd.go index dcbb9a1d51..b152571792 100644 --- a/src/runtime/mem_bsd.go +++ b/src/runtime/mem_bsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd || netbsd || openbsd || solaris -// +build dragonfly freebsd netbsd openbsd solaris package runtime diff --git a/src/runtime/mem_js.go b/src/runtime/mem_js.go index fe940360c0..4ca486ac4b 100644 --- a/src/runtime/mem_js.go +++ b/src/runtime/mem_js.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm package runtime diff --git a/src/runtime/mkduff.go b/src/runtime/mkduff.go index f3c3d8dfb5..d05158975f 100644 --- a/src/runtime/mkduff.go +++ b/src/runtime/mkduff.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore // runtime·duffzero is a Duff's device for zeroing memory. // The compiler jumps to computed addresses within diff --git a/src/runtime/mkfastlog2table.go b/src/runtime/mkfastlog2table.go index 8d78a3923a..a55f54751c 100644 --- a/src/runtime/mkfastlog2table.go +++ b/src/runtime/mkfastlog2table.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore // fastlog2Table contains log2 approximations for 5 binary digits. // This is used to implement fastlog2, which is used for heap sampling. diff --git a/src/runtime/mkpreempt.go b/src/runtime/mkpreempt.go index d87446d036..acfb518d10 100644 --- a/src/runtime/mkpreempt.go +++ b/src/runtime/mkpreempt.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore // mkpreempt generates the asyncPreempt functions for each // architecture. diff --git a/src/runtime/mksizeclasses.go b/src/runtime/mksizeclasses.go index b1b10e9e02..64ed844329 100644 --- a/src/runtime/mksizeclasses.go +++ b/src/runtime/mksizeclasses.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore // Generate tables for small malloc size classes. // diff --git a/src/runtime/mmap.go b/src/runtime/mmap.go index 7460eb3104..3280a62e8d 100644 --- a/src/runtime/mmap.go +++ b/src/runtime/mmap.go @@ -3,15 +3,6 @@ // license that can be found in the LICENSE file. //go:build !aix && !darwin && !js && (!linux || !amd64) && (!linux || !arm64) && !openbsd && !plan9 && !solaris && !windows -// +build !aix -// +build !darwin -// +build !js -// +build !linux !amd64 -// +build !linux !arm64 -// +build !openbsd -// +build !plan9 -// +build !solaris -// +build !windows package runtime diff --git a/src/runtime/mpagealloc_32bit.go b/src/runtime/mpagealloc_32bit.go index fceb4e7a18..1d863f2fda 100644 --- a/src/runtime/mpagealloc_32bit.go +++ b/src/runtime/mpagealloc_32bit.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build 386 || arm || mips || mipsle || wasm || (ios && arm64) -// +build 386 arm mips mipsle wasm ios,arm64 // wasm is a treated as a 32-bit architecture for the purposes of the page // allocator, even though it has 64-bit pointers. This is because any wasm diff --git a/src/runtime/mpagealloc_64bit.go b/src/runtime/mpagealloc_64bit.go index 16577346a7..782628c91d 100644 --- a/src/runtime/mpagealloc_64bit.go +++ b/src/runtime/mpagealloc_64bit.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 || (!ios && arm64) || mips64 || mips64le || ppc64 || ppc64le || riscv64 || s390x -// +build amd64 !ios,arm64 mips64 mips64le ppc64 ppc64le riscv64 s390x // See mpagealloc_32bit.go for why ios/arm64 is excluded here. diff --git a/src/runtime/msan.go b/src/runtime/msan.go index 25aaf94e26..902a1e9e74 100644 --- a/src/runtime/msan.go +++ b/src/runtime/msan.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build msan -// +build msan package runtime diff --git a/src/runtime/msan0.go b/src/runtime/msan0.go index b1096a6750..2f5fd2d982 100644 --- a/src/runtime/msan0.go +++ b/src/runtime/msan0.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !msan -// +build !msan // Dummy MSan support API, used when not built with -msan. diff --git a/src/runtime/nbpipe_fcntl_libc_test.go b/src/runtime/nbpipe_fcntl_libc_test.go index 076a722eb7..a9c8987438 100644 --- a/src/runtime/nbpipe_fcntl_libc_test.go +++ b/src/runtime/nbpipe_fcntl_libc_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || solaris -// +build aix darwin solaris package runtime_test diff --git a/src/runtime/nbpipe_fcntl_unix_test.go b/src/runtime/nbpipe_fcntl_unix_test.go index 6d5e4ff021..97607fa2cf 100644 --- a/src/runtime/nbpipe_fcntl_unix_test.go +++ b/src/runtime/nbpipe_fcntl_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd || linux || netbsd || openbsd -// +build dragonfly freebsd linux netbsd openbsd package runtime_test diff --git a/src/runtime/nbpipe_pipe.go b/src/runtime/nbpipe_pipe.go index b17257e9ec..408e1ec410 100644 --- a/src/runtime/nbpipe_pipe.go +++ b/src/runtime/nbpipe_pipe.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin -// +build aix darwin package runtime diff --git a/src/runtime/nbpipe_pipe2.go b/src/runtime/nbpipe_pipe2.go index f22b2b591f..6a555bcd99 100644 --- a/src/runtime/nbpipe_pipe2.go +++ b/src/runtime/nbpipe_pipe2.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build dragonfly freebsd linux netbsd openbsd solaris package runtime diff --git a/src/runtime/nbpipe_test.go b/src/runtime/nbpipe_test.go index 1d6a9b525c..36342cfde8 100644 --- a/src/runtime/nbpipe_test.go +++ b/src/runtime/nbpipe_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package runtime_test diff --git a/src/runtime/netpoll.go b/src/runtime/netpoll.go index 1008b4422c..f60e62dec7 100644 --- a/src/runtime/netpoll.go +++ b/src/runtime/netpoll.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris || windows -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris windows package runtime diff --git a/src/runtime/netpoll_epoll.go b/src/runtime/netpoll_epoll.go index 371ac59f8e..e0fb877d50 100644 --- a/src/runtime/netpoll_epoll.go +++ b/src/runtime/netpoll_epoll.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux -// +build linux package runtime diff --git a/src/runtime/netpoll_fake.go b/src/runtime/netpoll_fake.go index 8366f28914..de1dcae7ac 100644 --- a/src/runtime/netpoll_fake.go +++ b/src/runtime/netpoll_fake.go @@ -6,7 +6,6 @@ // Should never be used, because wasm/js network connections do not honor "SetNonblock". //go:build js && wasm -// +build js,wasm package runtime diff --git a/src/runtime/netpoll_kqueue.go b/src/runtime/netpoll_kqueue.go index 80d1b0cf18..2f7f2848d2 100644 --- a/src/runtime/netpoll_kqueue.go +++ b/src/runtime/netpoll_kqueue.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || netbsd || openbsd -// +build darwin dragonfly freebsd netbsd openbsd package runtime diff --git a/src/runtime/netpoll_stub.go b/src/runtime/netpoll_stub.go index 33ab8eba58..d0a63bca86 100644 --- a/src/runtime/netpoll_stub.go +++ b/src/runtime/netpoll_stub.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build plan9 -// +build plan9 package runtime diff --git a/src/runtime/norace_linux_test.go b/src/runtime/norace_linux_test.go index b199aa633c..b188a2e88b 100644 --- a/src/runtime/norace_linux_test.go +++ b/src/runtime/norace_linux_test.go @@ -4,7 +4,6 @@ // The file contains tests that cannot run under race detector for some reason. //go:build !race -// +build !race package runtime_test diff --git a/src/runtime/norace_test.go b/src/runtime/norace_test.go index 9ad5dde382..d49f2ec0df 100644 --- a/src/runtime/norace_test.go +++ b/src/runtime/norace_test.go @@ -4,7 +4,6 @@ // The file contains tests that cannot run under race detector for some reason. //go:build !race -// +build !race package runtime_test diff --git a/src/runtime/os_aix.go b/src/runtime/os_aix.go index c21da4ddaa..aeff593d50 100644 --- a/src/runtime/os_aix.go +++ b/src/runtime/os_aix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix -// +build aix package runtime diff --git a/src/runtime/os_freebsd2.go b/src/runtime/os_freebsd2.go index 7e266dc27e..3eaedf0b8b 100644 --- a/src/runtime/os_freebsd2.go +++ b/src/runtime/os_freebsd2.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build freebsd && !amd64 -// +build freebsd,!amd64 package runtime diff --git a/src/runtime/os_freebsd_noauxv.go b/src/runtime/os_freebsd_noauxv.go index 8fe0cb6718..1d9452bda5 100644 --- a/src/runtime/os_freebsd_noauxv.go +++ b/src/runtime/os_freebsd_noauxv.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build freebsd && !arm -// +build freebsd,!arm package runtime diff --git a/src/runtime/os_js.go b/src/runtime/os_js.go index 52b64e7602..9ed916705b 100644 --- a/src/runtime/os_js.go +++ b/src/runtime/os_js.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm package runtime diff --git a/src/runtime/os_linux_arm64.go b/src/runtime/os_linux_arm64.go index 5260f22f57..2daa56fce7 100644 --- a/src/runtime/os_linux_arm64.go +++ b/src/runtime/os_linux_arm64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm64 -// +build arm64 package runtime diff --git a/src/runtime/os_linux_be64.go b/src/runtime/os_linux_be64.go index 498d7cec6d..537515fcf2 100644 --- a/src/runtime/os_linux_be64.go +++ b/src/runtime/os_linux_be64.go @@ -5,8 +5,6 @@ // The standard Linux sigset type on big-endian 64-bit machines. //go:build linux && (ppc64 || s390x) -// +build linux -// +build ppc64 s390x package runtime diff --git a/src/runtime/os_linux_generic.go b/src/runtime/os_linux_generic.go index fe1973dbde..bed9e66e15 100644 --- a/src/runtime/os_linux_generic.go +++ b/src/runtime/os_linux_generic.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !mips && !mipsle && !mips64 && !mips64le && !s390x && !ppc64 && linux -// +build !mips,!mipsle,!mips64,!mips64le,!s390x,!ppc64,linux package runtime diff --git a/src/runtime/os_linux_mips64x.go b/src/runtime/os_linux_mips64x.go index bd76442dbd..188db01034 100644 --- a/src/runtime/os_linux_mips64x.go +++ b/src/runtime/os_linux_mips64x.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (mips64 || mips64le) -// +build linux -// +build mips64 mips64le package runtime diff --git a/src/runtime/os_linux_mipsx.go b/src/runtime/os_linux_mipsx.go index ef8b3f7d43..73016f81d9 100644 --- a/src/runtime/os_linux_mipsx.go +++ b/src/runtime/os_linux_mipsx.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (mips || mipsle) -// +build linux -// +build mips mipsle package runtime diff --git a/src/runtime/os_linux_noauxv.go b/src/runtime/os_linux_noauxv.go index 59b5aacaeb..7b84f713d6 100644 --- a/src/runtime/os_linux_noauxv.go +++ b/src/runtime/os_linux_noauxv.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && !arm && !arm64 && !mips && !mipsle && !mips64 && !mips64le && !s390x && !ppc64 && !ppc64le -// +build linux,!arm,!arm64,!mips,!mipsle,!mips64,!mips64le,!s390x,!ppc64,!ppc64le package runtime diff --git a/src/runtime/os_linux_novdso.go b/src/runtime/os_linux_novdso.go index 7e93d2ba83..b06716dc6a 100644 --- a/src/runtime/os_linux_novdso.go +++ b/src/runtime/os_linux_novdso.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && !386 && !amd64 && !arm && !arm64 && !mips64 && !mips64le && !ppc64 && !ppc64le && !riscv64 -// +build linux,!386,!amd64,!arm,!arm64,!mips64,!mips64le,!ppc64,!ppc64le,!riscv64 package runtime diff --git a/src/runtime/os_linux_ppc64x.go b/src/runtime/os_linux_ppc64x.go index c093d2ec0f..25d7ccc035 100644 --- a/src/runtime/os_linux_ppc64x.go +++ b/src/runtime/os_linux_ppc64x.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (ppc64 || ppc64le) -// +build linux -// +build ppc64 ppc64le package runtime diff --git a/src/runtime/os_linux_x86.go b/src/runtime/os_linux_x86.go index 5667774d82..c88f61fa2e 100644 --- a/src/runtime/os_linux_x86.go +++ b/src/runtime/os_linux_x86.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (386 || amd64) -// +build linux -// +build 386 amd64 package runtime diff --git a/src/runtime/os_nonopenbsd.go b/src/runtime/os_nonopenbsd.go index 6134b6c02f..a5775961e8 100644 --- a/src/runtime/os_nonopenbsd.go +++ b/src/runtime/os_nonopenbsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !openbsd -// +build !openbsd package runtime diff --git a/src/runtime/os_only_solaris.go b/src/runtime/os_only_solaris.go index 3829683c80..0c72500674 100644 --- a/src/runtime/os_only_solaris.go +++ b/src/runtime/os_only_solaris.go @@ -5,7 +5,6 @@ // Solaris code that doesn't also apply to illumos. //go:build !illumos -// +build !illumos package runtime diff --git a/src/runtime/os_openbsd_libc.go b/src/runtime/os_openbsd_libc.go index 981e49827f..ff21eccb4b 100644 --- a/src/runtime/os_openbsd_libc.go +++ b/src/runtime/os_openbsd_libc.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build openbsd && !mips64 -// +build openbsd,!mips64 package runtime diff --git a/src/runtime/os_openbsd_syscall.go b/src/runtime/os_openbsd_syscall.go index 1ddee1864e..8128c20453 100644 --- a/src/runtime/os_openbsd_syscall.go +++ b/src/runtime/os_openbsd_syscall.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build openbsd && mips64 -// +build openbsd,mips64 package runtime diff --git a/src/runtime/os_openbsd_syscall1.go b/src/runtime/os_openbsd_syscall1.go index c20ee8300e..d32894ba6a 100644 --- a/src/runtime/os_openbsd_syscall1.go +++ b/src/runtime/os_openbsd_syscall1.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build openbsd && mips64 -// +build openbsd,mips64 package runtime diff --git a/src/runtime/os_openbsd_syscall2.go b/src/runtime/os_openbsd_syscall2.go index af1997131f..99542fb2de 100644 --- a/src/runtime/os_openbsd_syscall2.go +++ b/src/runtime/os_openbsd_syscall2.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build openbsd && mips64 -// +build openbsd,mips64 package runtime diff --git a/src/runtime/panic32.go b/src/runtime/panic32.go index acbdd1ff45..fa3f2bf2f8 100644 --- a/src/runtime/panic32.go +++ b/src/runtime/panic32.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build 386 || arm || mips || mipsle -// +build 386 arm mips mipsle package runtime diff --git a/src/runtime/pprof/mprof_test.go b/src/runtime/pprof/mprof_test.go index b4680fbdee..b44b32aed2 100644 --- a/src/runtime/pprof/mprof_test.go +++ b/src/runtime/pprof/mprof_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js -// +build !js package pprof @@ -105,31 +104,31 @@ func TestMemoryProfiler(t *testing.T) { }{{ stk: []string{"runtime/pprof.allocatePersistent1K", "runtime/pprof.TestMemoryProfiler"}, legacy: fmt.Sprintf(`%v: %v \[%v: %v\] @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ -# 0x[0-9,a-f]+ runtime/pprof\.allocatePersistent1K\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test\.go:48 -# 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test\.go:83 +# 0x[0-9,a-f]+ runtime/pprof\.allocatePersistent1K\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test\.go:47 +# 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test\.go:82 `, 32*memoryProfilerRun, 1024*memoryProfilerRun, 32*memoryProfilerRun, 1024*memoryProfilerRun), }, { stk: []string{"runtime/pprof.allocateTransient1M", "runtime/pprof.TestMemoryProfiler"}, legacy: fmt.Sprintf(`0: 0 \[%v: %v\] @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ -# 0x[0-9,a-f]+ runtime/pprof\.allocateTransient1M\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:25 -# 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:80 +# 0x[0-9,a-f]+ runtime/pprof\.allocateTransient1M\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:24 +# 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:79 `, (1<<10)*memoryProfilerRun, (1<<20)*memoryProfilerRun), }, { stk: []string{"runtime/pprof.allocateTransient2M", "runtime/pprof.TestMemoryProfiler"}, legacy: fmt.Sprintf(`0: 0 \[%v: %v\] @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ -# 0x[0-9,a-f]+ runtime/pprof\.allocateTransient2M\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:31 -# 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:81 +# 0x[0-9,a-f]+ runtime/pprof\.allocateTransient2M\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:30 +# 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:80 `, memoryProfilerRun, (2<<20)*memoryProfilerRun), }, { stk: []string{"runtime/pprof.allocateTransient2MInline", "runtime/pprof.TestMemoryProfiler"}, legacy: fmt.Sprintf(`0: 0 \[%v: %v\] @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ -# 0x[0-9,a-f]+ runtime/pprof\.allocateTransient2MInline\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:35 -# 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:82 +# 0x[0-9,a-f]+ runtime/pprof\.allocateTransient2MInline\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:34 +# 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:81 `, memoryProfilerRun, (2<<20)*memoryProfilerRun), }, { stk: []string{"runtime/pprof.allocateReflectTransient"}, legacy: fmt.Sprintf(`0: 0 \[%v: %v\] @( 0x[0-9,a-f]+)+ -# 0x[0-9,a-f]+ runtime/pprof\.allocateReflectTransient\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:56 +# 0x[0-9,a-f]+ runtime/pprof\.allocateReflectTransient\+0x[0-9,a-f]+ .*/runtime/pprof/mprof_test.go:55 `, memoryProfilerRun, (2<<20)*memoryProfilerRun), }} diff --git a/src/runtime/pprof/pprof_norusage.go b/src/runtime/pprof/pprof_norusage.go index e175dd380c..cbc5176cfa 100644 --- a/src/runtime/pprof/pprof_norusage.go +++ b/src/runtime/pprof/pprof_norusage.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !darwin && !linux -// +build !darwin,!linux package pprof diff --git a/src/runtime/pprof/pprof_rusage.go b/src/runtime/pprof/pprof_rusage.go index 269f21bc2f..46263fedd9 100644 --- a/src/runtime/pprof/pprof_rusage.go +++ b/src/runtime/pprof/pprof_rusage.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || linux -// +build darwin linux package pprof diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go index 03ff55b541..06e0274e9a 100644 --- a/src/runtime/pprof/pprof_test.go +++ b/src/runtime/pprof/pprof_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js -// +build !js package pprof diff --git a/src/runtime/pprof/rusage_test.go b/src/runtime/pprof/rusage_test.go index 66b1b3bbe1..b0d651e0eb 100644 --- a/src/runtime/pprof/rusage_test.go +++ b/src/runtime/pprof/rusage_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || freebsd || linux || netbsd || openbsd -// +build darwin freebsd linux netbsd openbsd package pprof diff --git a/src/runtime/preempt_nonwindows.go b/src/runtime/preempt_nonwindows.go index 365e86a611..d6a2408cb7 100644 --- a/src/runtime/preempt_nonwindows.go +++ b/src/runtime/preempt_nonwindows.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !windows -// +build !windows package runtime diff --git a/src/runtime/race.go b/src/runtime/race.go index 7eaa9d2b72..e019923bb5 100644 --- a/src/runtime/race.go +++ b/src/runtime/race.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build race -// +build race package runtime diff --git a/src/runtime/race/output_test.go b/src/runtime/race/output_test.go index 63fcd847dc..46cdfcd0e9 100644 --- a/src/runtime/race/output_test.go +++ b/src/runtime/race/output_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build race -// +build race package race_test diff --git a/src/runtime/race/race.go b/src/runtime/race/race.go index 84050e8771..63fa83ff14 100644 --- a/src/runtime/race/race.go +++ b/src/runtime/race/race.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build (race && linux && amd64) || (race && freebsd && amd64) || (race && netbsd && amd64) || (race && darwin && amd64) || (race && windows && amd64) || (race && linux && ppc64le) || (race && linux && arm64) || (race && darwin && arm64) || (race && openbsd && amd64) -// +build race,linux,amd64 race,freebsd,amd64 race,netbsd,amd64 race,darwin,amd64 race,windows,amd64 race,linux,ppc64le race,linux,arm64 race,darwin,arm64 race,openbsd,amd64 package race diff --git a/src/runtime/race/race_linux_test.go b/src/runtime/race/race_linux_test.go index 9c0d48d6bd..e8a2d0fd8c 100644 --- a/src/runtime/race/race_linux_test.go +++ b/src/runtime/race/race_linux_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && race -// +build linux,race package race_test diff --git a/src/runtime/race/race_test.go b/src/runtime/race/race_test.go index 8c880b8570..1677e13986 100644 --- a/src/runtime/race/race_test.go +++ b/src/runtime/race/race_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build race -// +build race // This program is used to verify the race detector // by running the tests and parsing their output. diff --git a/src/runtime/race/race_unix_test.go b/src/runtime/race/race_unix_test.go index acd6e47f98..6cc0730589 100644 --- a/src/runtime/race/race_unix_test.go +++ b/src/runtime/race/race_unix_test.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build race && (darwin || freebsd || linux) -// +build race -// +build darwin freebsd linux package race_test diff --git a/src/runtime/race/race_windows_test.go b/src/runtime/race/race_windows_test.go index e490d766dd..143b483f97 100644 --- a/src/runtime/race/race_windows_test.go +++ b/src/runtime/race/race_windows_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows && race -// +build windows,race package race_test diff --git a/src/runtime/race/sched_test.go b/src/runtime/race/sched_test.go index e904ebd20d..9fe83ea11d 100644 --- a/src/runtime/race/sched_test.go +++ b/src/runtime/race/sched_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build race -// +build race package race_test diff --git a/src/runtime/race/syso_test.go b/src/runtime/race/syso_test.go index f5095737a4..2f1a91cab1 100644 --- a/src/runtime/race/syso_test.go +++ b/src/runtime/race/syso_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build race -// +build race package race diff --git a/src/runtime/race/timer_test.go b/src/runtime/race/timer_test.go index f11f8456a0..dd59005564 100644 --- a/src/runtime/race/timer_test.go +++ b/src/runtime/race/timer_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build race -// +build race package race_test diff --git a/src/runtime/race0.go b/src/runtime/race0.go index 0e431b8103..f36d4387c7 100644 --- a/src/runtime/race0.go +++ b/src/runtime/race0.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !race -// +build !race // Dummy race detection API, used when not built with -race. diff --git a/src/runtime/relax_stub.go b/src/runtime/relax_stub.go index 5b92879c20..e507702fc1 100644 --- a/src/runtime/relax_stub.go +++ b/src/runtime/relax_stub.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !windows -// +build !windows package runtime diff --git a/src/runtime/runtime_mmap_test.go b/src/runtime/runtime_mmap_test.go index f71f8afa57..9323c09355 100644 --- a/src/runtime/runtime_mmap_test.go +++ b/src/runtime/runtime_mmap_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package runtime_test diff --git a/src/runtime/runtime_unix_test.go b/src/runtime/runtime_unix_test.go index 0251c676e6..642a946280 100644 --- a/src/runtime/runtime_unix_test.go +++ b/src/runtime/runtime_unix_test.go @@ -7,7 +7,6 @@ // and Close(-1) is nearly universally fast. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || plan9 -// +build aix darwin dragonfly freebsd linux netbsd openbsd plan9 package runtime_test diff --git a/src/runtime/semasleep_test.go b/src/runtime/semasleep_test.go index 905e932b7d..cf4ef18208 100644 --- a/src/runtime/semasleep_test.go +++ b/src/runtime/semasleep_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !plan9 && !windows && !js -// +build !plan9,!windows,!js package runtime_test diff --git a/src/runtime/sigaction.go b/src/runtime/sigaction.go index 30050efcc7..05f44f65db 100644 --- a/src/runtime/sigaction.go +++ b/src/runtime/sigaction.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build (linux && !amd64 && !arm64 && !ppc64le) || (freebsd && !amd64) -// +build linux,!amd64,!arm64,!ppc64le freebsd,!amd64 package runtime diff --git a/src/runtime/signal_386.go b/src/runtime/signal_386.go index 69a59e6dcf..aa66032caa 100644 --- a/src/runtime/signal_386.go +++ b/src/runtime/signal_386.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd || linux || netbsd || openbsd -// +build dragonfly freebsd linux netbsd openbsd package runtime diff --git a/src/runtime/signal_aix_ppc64.go b/src/runtime/signal_aix_ppc64.go index 5999d9dc3d..c6cb91a0a2 100644 --- a/src/runtime/signal_aix_ppc64.go +++ b/src/runtime/signal_aix_ppc64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix -// +build aix package runtime diff --git a/src/runtime/signal_amd64.go b/src/runtime/signal_amd64.go index 20490cffbf..67a21950d7 100644 --- a/src/runtime/signal_amd64.go +++ b/src/runtime/signal_amd64.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 && (darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris) -// +build amd64 -// +build darwin dragonfly freebsd linux netbsd openbsd solaris package runtime diff --git a/src/runtime/signal_arm.go b/src/runtime/signal_arm.go index a0780788f8..fff302f4d4 100644 --- a/src/runtime/signal_arm.go +++ b/src/runtime/signal_arm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd || linux || netbsd || openbsd -// +build dragonfly freebsd linux netbsd openbsd package runtime diff --git a/src/runtime/signal_arm64.go b/src/runtime/signal_arm64.go index 9d4a8b8a99..771585a8f9 100644 --- a/src/runtime/signal_arm64.go +++ b/src/runtime/signal_arm64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || freebsd || linux || netbsd || openbsd -// +build darwin freebsd linux netbsd openbsd package runtime diff --git a/src/runtime/signal_linux_mips64x.go b/src/runtime/signal_linux_mips64x.go index e62d6a93fd..9c2a286001 100644 --- a/src/runtime/signal_linux_mips64x.go +++ b/src/runtime/signal_linux_mips64x.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (mips64 || mips64le) -// +build linux -// +build mips64 mips64le package runtime diff --git a/src/runtime/signal_linux_mipsx.go b/src/runtime/signal_linux_mipsx.go index f3969c5aac..f11bfc9b3a 100644 --- a/src/runtime/signal_linux_mipsx.go +++ b/src/runtime/signal_linux_mipsx.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (mips || mipsle) -// +build linux -// +build mips mipsle package runtime diff --git a/src/runtime/signal_linux_ppc64x.go b/src/runtime/signal_linux_ppc64x.go index d2eeb39ead..31754289ec 100644 --- a/src/runtime/signal_linux_ppc64x.go +++ b/src/runtime/signal_linux_ppc64x.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (ppc64 || ppc64le) -// +build linux -// +build ppc64 ppc64le package runtime diff --git a/src/runtime/signal_mips64x.go b/src/runtime/signal_mips64x.go index 87dfa724c4..cee1bf7a1b 100644 --- a/src/runtime/signal_mips64x.go +++ b/src/runtime/signal_mips64x.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (linux || openbsd) && (mips64 || mips64le) -// +build linux openbsd -// +build mips64 mips64le package runtime diff --git a/src/runtime/signal_mipsx.go b/src/runtime/signal_mipsx.go index 5067799bd6..ba92655152 100644 --- a/src/runtime/signal_mipsx.go +++ b/src/runtime/signal_mipsx.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (mips || mipsle) -// +build linux -// +build mips mipsle package runtime diff --git a/src/runtime/signal_ppc64x.go b/src/runtime/signal_ppc64x.go index 8a39d59957..bdd354026c 100644 --- a/src/runtime/signal_ppc64x.go +++ b/src/runtime/signal_ppc64x.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (aix || linux) && (ppc64 || ppc64le) -// +build aix linux -// +build ppc64 ppc64le package runtime diff --git a/src/runtime/signal_riscv64.go b/src/runtime/signal_riscv64.go index 8a24e4e36a..5eeb227aa0 100644 --- a/src/runtime/signal_riscv64.go +++ b/src/runtime/signal_riscv64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && riscv64 -// +build linux,riscv64 package runtime diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go index 8854629224..7c454437e4 100644 --- a/src/runtime/signal_unix.go +++ b/src/runtime/signal_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package runtime diff --git a/src/runtime/signal_windows_test.go b/src/runtime/signal_windows_test.go index 1b7cb9d4c4..7c88ab573e 100644 --- a/src/runtime/signal_windows_test.go +++ b/src/runtime/signal_windows_test.go @@ -1,5 +1,4 @@ //go:build windows -// +build windows package runtime_test diff --git a/src/runtime/sigqueue.go b/src/runtime/sigqueue.go index 6c91fb3fb3..7b84a0ef65 100644 --- a/src/runtime/sigqueue.go +++ b/src/runtime/sigqueue.go @@ -29,7 +29,6 @@ // nor deadlocks. //go:build !plan9 -// +build !plan9 package runtime diff --git a/src/runtime/sigqueue_note.go b/src/runtime/sigqueue_note.go index e23446bea4..fb1a517fa5 100644 --- a/src/runtime/sigqueue_note.go +++ b/src/runtime/sigqueue_note.go @@ -8,7 +8,6 @@ // those functions. These functions will never be called. //go:build !darwin && !plan9 -// +build !darwin,!plan9 package runtime diff --git a/src/runtime/sigtab_linux_generic.go b/src/runtime/sigtab_linux_generic.go index dc1debddab..fe93bbafb5 100644 --- a/src/runtime/sigtab_linux_generic.go +++ b/src/runtime/sigtab_linux_generic.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !mips && !mipsle && !mips64 && !mips64le && linux -// +build !mips,!mipsle,!mips64,!mips64le,linux package runtime diff --git a/src/runtime/sigtab_linux_mipsx.go b/src/runtime/sigtab_linux_mipsx.go index af9c7e56eb..295ced5bbb 100644 --- a/src/runtime/sigtab_linux_mipsx.go +++ b/src/runtime/sigtab_linux_mipsx.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (mips || mipsle || mips64 || mips64le) && linux -// +build mips mipsle mips64 mips64le -// +build linux package runtime diff --git a/src/runtime/stubs2.go b/src/runtime/stubs2.go index 525b324c81..9aa965454d 100644 --- a/src/runtime/stubs2.go +++ b/src/runtime/stubs2.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !aix && !darwin && !js && !openbsd && !plan9 && !solaris && !windows -// +build !aix,!darwin,!js,!openbsd,!plan9,!solaris,!windows package runtime diff --git a/src/runtime/stubs3.go b/src/runtime/stubs3.go index b895be4c70..891663b110 100644 --- a/src/runtime/stubs3.go +++ b/src/runtime/stubs3.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !aix && !darwin && !freebsd && !openbsd && !plan9 && !solaris -// +build !aix,!darwin,!freebsd,!openbsd,!plan9,!solaris package runtime diff --git a/src/runtime/stubs_linux.go b/src/runtime/stubs_linux.go index ba267009ca..06c14e2160 100644 --- a/src/runtime/stubs_linux.go +++ b/src/runtime/stubs_linux.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux -// +build linux package runtime diff --git a/src/runtime/stubs_mips64x.go b/src/runtime/stubs_mips64x.go index 05a4d0d38d..a9ddfc0256 100644 --- a/src/runtime/stubs_mips64x.go +++ b/src/runtime/stubs_mips64x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips64 || mips64le -// +build mips64 mips64le package runtime diff --git a/src/runtime/stubs_mipsx.go b/src/runtime/stubs_mipsx.go index 9bffb35b67..d48f9b88e8 100644 --- a/src/runtime/stubs_mipsx.go +++ b/src/runtime/stubs_mipsx.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips || mipsle -// +build mips mipsle package runtime diff --git a/src/runtime/stubs_nonlinux.go b/src/runtime/stubs_nonlinux.go index f9b98595fc..1a06d7cc1d 100644 --- a/src/runtime/stubs_nonlinux.go +++ b/src/runtime/stubs_nonlinux.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !linux -// +build !linux package runtime diff --git a/src/runtime/stubs_ppc64.go b/src/runtime/stubs_ppc64.go index 3895973f7c..07127629d1 100644 --- a/src/runtime/stubs_ppc64.go +++ b/src/runtime/stubs_ppc64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux -// +build linux package runtime diff --git a/src/runtime/stubs_ppc64x.go b/src/runtime/stubs_ppc64x.go index 2c647ea672..95e43a5162 100644 --- a/src/runtime/stubs_ppc64x.go +++ b/src/runtime/stubs_ppc64x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64le || ppc64 -// +build ppc64le ppc64 package runtime diff --git a/src/runtime/sys_libc.go b/src/runtime/sys_libc.go index b1a9f8b536..7012b4167e 100644 --- a/src/runtime/sys_libc.go +++ b/src/runtime/sys_libc.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || (openbsd && !mips64) -// +build darwin openbsd,!mips64 package runtime diff --git a/src/runtime/sys_mips64x.go b/src/runtime/sys_mips64x.go index 842a4a7084..b71538409c 100644 --- a/src/runtime/sys_mips64x.go +++ b/src/runtime/sys_mips64x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips64 || mips64le -// +build mips64 mips64le package runtime diff --git a/src/runtime/sys_mipsx.go b/src/runtime/sys_mipsx.go index 2038eb7d79..b60135f964 100644 --- a/src/runtime/sys_mipsx.go +++ b/src/runtime/sys_mipsx.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips || mipsle -// +build mips mipsle package runtime diff --git a/src/runtime/sys_nonppc64x.go b/src/runtime/sys_nonppc64x.go index 66821b1f76..653f1c999f 100644 --- a/src/runtime/sys_nonppc64x.go +++ b/src/runtime/sys_nonppc64x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !ppc64 && !ppc64le -// +build !ppc64,!ppc64le package runtime diff --git a/src/runtime/sys_openbsd.go b/src/runtime/sys_openbsd.go index 15888619b1..9f3a25fcf8 100644 --- a/src/runtime/sys_openbsd.go +++ b/src/runtime/sys_openbsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build openbsd && !mips64 -// +build openbsd,!mips64 package runtime diff --git a/src/runtime/sys_openbsd1.go b/src/runtime/sys_openbsd1.go index b4e9f54538..4b80f60226 100644 --- a/src/runtime/sys_openbsd1.go +++ b/src/runtime/sys_openbsd1.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build openbsd && !mips64 -// +build openbsd,!mips64 package runtime diff --git a/src/runtime/sys_openbsd2.go b/src/runtime/sys_openbsd2.go index 23e0b195fd..7024cfa86d 100644 --- a/src/runtime/sys_openbsd2.go +++ b/src/runtime/sys_openbsd2.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build openbsd && !mips64 -// +build openbsd,!mips64 package runtime diff --git a/src/runtime/sys_openbsd3.go b/src/runtime/sys_openbsd3.go index a917ebde61..269bf86f10 100644 --- a/src/runtime/sys_openbsd3.go +++ b/src/runtime/sys_openbsd3.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build openbsd && !mips64 -// +build openbsd,!mips64 package runtime diff --git a/src/runtime/sys_ppc64x.go b/src/runtime/sys_ppc64x.go index 69bd99fa09..56c5c9575e 100644 --- a/src/runtime/sys_ppc64x.go +++ b/src/runtime/sys_ppc64x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le package runtime diff --git a/src/runtime/sys_x86.go b/src/runtime/sys_x86.go index 856c73a2f6..9fb36c2a66 100644 --- a/src/runtime/sys_x86.go +++ b/src/runtime/sys_x86.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 || 386 -// +build amd64 386 package runtime diff --git a/src/runtime/time_fake.go b/src/runtime/time_fake.go index c790faba3d..107f6be335 100644 --- a/src/runtime/time_fake.go +++ b/src/runtime/time_fake.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build faketime && !windows -// +build faketime,!windows // Faketime isn't currently supported on Windows. This would require // modifying syscall.Write to call syscall.faketimeWrite, diff --git a/src/runtime/time_nofake.go b/src/runtime/time_nofake.go index 5a4ceaf43d..2b85c5aa01 100644 --- a/src/runtime/time_nofake.go +++ b/src/runtime/time_nofake.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !faketime -// +build !faketime package runtime diff --git a/src/runtime/timeasm.go b/src/runtime/timeasm.go index 468ff8a0d3..0421388686 100644 --- a/src/runtime/timeasm.go +++ b/src/runtime/timeasm.go @@ -5,8 +5,6 @@ // Declarations for operating systems implementing time.now directly in assembly. //go:build !faketime && (windows || (linux && amd64)) -// +build !faketime -// +build windows linux,amd64 package runtime diff --git a/src/runtime/timestub.go b/src/runtime/timestub.go index 6f16c70b81..1d2926b43d 100644 --- a/src/runtime/timestub.go +++ b/src/runtime/timestub.go @@ -6,9 +6,6 @@ // indirectly, in terms of walltime and nanotime assembly. //go:build !faketime && !windows && !(linux && amd64) -// +build !faketime -// +build !windows -// +build !linux !amd64 package runtime diff --git a/src/runtime/timestub2.go b/src/runtime/timestub2.go index 800a2a94e0..b9a5cc6345 100644 --- a/src/runtime/timestub2.go +++ b/src/runtime/timestub2.go @@ -3,13 +3,6 @@ // license that can be found in the LICENSE file. //go:build !aix && !darwin && !freebsd && !openbsd && !solaris && !windows && !(linux && amd64) -// +build !aix -// +build !darwin -// +build !freebsd -// +build !openbsd -// +build !solaris -// +build !windows -// +build !linux !amd64 package runtime diff --git a/src/runtime/tls_stub.go b/src/runtime/tls_stub.go index 95dafd007c..7bdfc6b89a 100644 --- a/src/runtime/tls_stub.go +++ b/src/runtime/tls_stub.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build (windows && !amd64) || !windows -// +build windows,!amd64 !windows package runtime diff --git a/src/runtime/vdso_elf32.go b/src/runtime/vdso_elf32.go index 456173b0f5..1b8afbedf4 100644 --- a/src/runtime/vdso_elf32.go +++ b/src/runtime/vdso_elf32.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (386 || arm) -// +build linux -// +build 386 arm package runtime diff --git a/src/runtime/vdso_elf64.go b/src/runtime/vdso_elf64.go index aecc84dcfe..d46d6f8c34 100644 --- a/src/runtime/vdso_elf64.go +++ b/src/runtime/vdso_elf64.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (amd64 || arm64 || mips64 || mips64le || ppc64 || ppc64le || riscv64) -// +build linux -// +build amd64 arm64 mips64 mips64le ppc64 ppc64le riscv64 package runtime diff --git a/src/runtime/vdso_freebsd.go b/src/runtime/vdso_freebsd.go index 7ca7b2810b..0fe21cf647 100644 --- a/src/runtime/vdso_freebsd.go +++ b/src/runtime/vdso_freebsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build freebsd -// +build freebsd package runtime diff --git a/src/runtime/vdso_freebsd_x86.go b/src/runtime/vdso_freebsd_x86.go index 23a5a8c322..5324a3d4cb 100644 --- a/src/runtime/vdso_freebsd_x86.go +++ b/src/runtime/vdso_freebsd_x86.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build freebsd && (386 || amd64) -// +build freebsd -// +build 386 amd64 package runtime diff --git a/src/runtime/vdso_in_none.go b/src/runtime/vdso_in_none.go index 3e98b08b15..618bd39b42 100644 --- a/src/runtime/vdso_in_none.go +++ b/src/runtime/vdso_in_none.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build (linux && !386 && !amd64 && !arm && !arm64 && !mips64 && !mips64le && !ppc64 && !ppc64le && !riscv64) || !linux -// +build linux,!386,!amd64,!arm,!arm64,!mips64,!mips64le,!ppc64,!ppc64le,!riscv64 !linux package runtime diff --git a/src/runtime/vdso_linux.go b/src/runtime/vdso_linux.go index 20c8db78be..cff2000767 100644 --- a/src/runtime/vdso_linux.go +++ b/src/runtime/vdso_linux.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (386 || amd64 || arm || arm64 || mips64 || mips64le || ppc64 || ppc64le || riscv64) -// +build linux -// +build 386 amd64 arm arm64 mips64 mips64le ppc64 ppc64le riscv64 package runtime diff --git a/src/runtime/vdso_linux_mips64x.go b/src/runtime/vdso_linux_mips64x.go index 395ddbba69..1444f8e524 100644 --- a/src/runtime/vdso_linux_mips64x.go +++ b/src/runtime/vdso_linux_mips64x.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (mips64 || mips64le) -// +build linux -// +build mips64 mips64le package runtime diff --git a/src/runtime/vdso_linux_ppc64x.go b/src/runtime/vdso_linux_ppc64x.go index b741dbfcdc..09c8d9d20e 100644 --- a/src/runtime/vdso_linux_ppc64x.go +++ b/src/runtime/vdso_linux_ppc64x.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (ppc64 || ppc64le) -// +build linux -// +build ppc64 ppc64le package runtime diff --git a/src/runtime/vlrt.go b/src/runtime/vlrt.go index 927b585a92..1dcb125aef 100644 --- a/src/runtime/vlrt.go +++ b/src/runtime/vlrt.go @@ -24,7 +24,6 @@ // THE SOFTWARE. //go:build arm || 386 || mips || mipsle -// +build arm 386 mips mipsle package runtime diff --git a/src/runtime/wincallback.go b/src/runtime/wincallback.go index 73f1e567ce..ca9965979f 100644 --- a/src/runtime/wincallback.go +++ b/src/runtime/wincallback.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore // Generate Windows callback assembly file. diff --git a/src/runtime/write_err.go b/src/runtime/write_err.go index a4656fd728..81ae872e9c 100644 --- a/src/runtime/write_err.go +++ b/src/runtime/write_err.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !android -// +build !android package runtime diff --git a/src/sync/pool_test.go b/src/sync/pool_test.go index 65666daab4..f94153c8d7 100644 --- a/src/sync/pool_test.go +++ b/src/sync/pool_test.go @@ -4,7 +4,6 @@ // Pool is no-op under race detector, so all these tests do not work. //go:build !race -// +build !race package sync_test diff --git a/src/sync/runtime2.go b/src/sync/runtime2.go index c4b44893f0..9b7e9922fb 100644 --- a/src/sync/runtime2.go +++ b/src/sync/runtime2.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !goexperiment.staticlockranking -// +build !goexperiment.staticlockranking package sync diff --git a/src/sync/runtime2_lockrank.go b/src/sync/runtime2_lockrank.go index e91fdb6c1f..cdb1af41c6 100644 --- a/src/sync/runtime2_lockrank.go +++ b/src/sync/runtime2_lockrank.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build goexperiment.staticlockranking -// +build goexperiment.staticlockranking package sync diff --git a/src/syscall/bpf_bsd.go b/src/syscall/bpf_bsd.go index 452d4cf14b..735c078895 100644 --- a/src/syscall/bpf_bsd.go +++ b/src/syscall/bpf_bsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd || netbsd || openbsd -// +build dragonfly freebsd netbsd openbsd // Berkeley packet filter for BSD variants diff --git a/src/syscall/creds_test.go b/src/syscall/creds_test.go index c1a8b516e8..1ee56fc340 100644 --- a/src/syscall/creds_test.go +++ b/src/syscall/creds_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux -// +build linux package syscall_test diff --git a/src/syscall/dirent.go b/src/syscall/dirent.go index 9e1222e81c..237ea79ad6 100644 --- a/src/syscall/dirent.go +++ b/src/syscall/dirent.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris package syscall diff --git a/src/syscall/dirent_test.go b/src/syscall/dirent_test.go index 71b445ba9b..6570bf9217 100644 --- a/src/syscall/dirent_test.go +++ b/src/syscall/dirent_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package syscall_test diff --git a/src/syscall/endian_big.go b/src/syscall/endian_big.go index dc0947fa6e..8e3874eb86 100644 --- a/src/syscall/endian_big.go +++ b/src/syscall/endian_big.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. // //go:build ppc64 || s390x || mips || mips64 -// +build ppc64 s390x mips mips64 package syscall diff --git a/src/syscall/endian_little.go b/src/syscall/endian_little.go index a894445f73..edfb6cf164 100644 --- a/src/syscall/endian_little.go +++ b/src/syscall/endian_little.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. // //go:build 386 || amd64 || arm || arm64 || ppc64le || mips64le || mipsle || riscv64 || wasm -// +build 386 amd64 arm arm64 ppc64le mips64le mipsle riscv64 wasm package syscall diff --git a/src/syscall/env_unix.go b/src/syscall/env_unix.go index 022ef6ed73..521967c79f 100644 --- a/src/syscall/env_unix.go +++ b/src/syscall/env_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris || plan9 -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris plan9 // Unix environment variables. diff --git a/src/syscall/exec_aix_test.go b/src/syscall/exec_aix_test.go index 17c7ac0664..f2d54a40bd 100644 --- a/src/syscall/exec_aix_test.go +++ b/src/syscall/exec_aix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix -// +build aix package syscall diff --git a/src/syscall/exec_bsd.go b/src/syscall/exec_bsd.go index d2e50e3dd3..148f5a91aa 100644 --- a/src/syscall/exec_bsd.go +++ b/src/syscall/exec_bsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || netbsd || (openbsd && mips64) -// +build dragonfly netbsd openbsd,mips64 package syscall diff --git a/src/syscall/exec_libc.go b/src/syscall/exec_libc.go index b14abd4e63..c8549c4964 100644 --- a/src/syscall/exec_libc.go +++ b/src/syscall/exec_libc.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || solaris -// +build aix solaris // This file handles forkAndExecInChild function for OS using libc syscall like AIX or Solaris. diff --git a/src/syscall/exec_libc2.go b/src/syscall/exec_libc2.go index bd98109d07..b05f053bbf 100644 --- a/src/syscall/exec_libc2.go +++ b/src/syscall/exec_libc2.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || (openbsd && !mips64) -// +build darwin openbsd,!mips64 package syscall diff --git a/src/syscall/exec_linux.go b/src/syscall/exec_linux.go index e1506e1e2b..0f0dee8ea5 100644 --- a/src/syscall/exec_linux.go +++ b/src/syscall/exec_linux.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux -// +build linux package syscall diff --git a/src/syscall/exec_linux_test.go b/src/syscall/exec_linux_test.go index 79b2633aca..80440ca4d6 100644 --- a/src/syscall/exec_linux_test.go +++ b/src/syscall/exec_linux_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux -// +build linux package syscall_test diff --git a/src/syscall/exec_pdeathsig_test.go b/src/syscall/exec_pdeathsig_test.go index 6533d3a138..96ae27b494 100644 --- a/src/syscall/exec_pdeathsig_test.go +++ b/src/syscall/exec_pdeathsig_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build freebsd || linux -// +build freebsd linux package syscall_test diff --git a/src/syscall/exec_solaris_test.go b/src/syscall/exec_solaris_test.go index f54fc8385d..90e5349bf4 100644 --- a/src/syscall/exec_solaris_test.go +++ b/src/syscall/exec_solaris_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build solaris -// +build solaris package syscall diff --git a/src/syscall/exec_unix.go b/src/syscall/exec_unix.go index 54b18dccd7..64eb5ed9f0 100644 --- a/src/syscall/exec_unix.go +++ b/src/syscall/exec_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris // Fork, exec, wait, etc. diff --git a/src/syscall/exec_unix_test.go b/src/syscall/exec_unix_test.go index 866671ba2a..55f5f7025a 100644 --- a/src/syscall/exec_unix_test.go +++ b/src/syscall/exec_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package syscall_test diff --git a/src/syscall/export_unix_test.go b/src/syscall/export_unix_test.go index 2d2c67673d..2f678d2566 100644 --- a/src/syscall/export_unix_test.go +++ b/src/syscall/export_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd || linux || netbsd || openbsd -// +build dragonfly freebsd linux netbsd openbsd package syscall diff --git a/src/syscall/flock.go b/src/syscall/flock.go index 3b43b6aede..8cb8f16153 100644 --- a/src/syscall/flock.go +++ b/src/syscall/flock.go @@ -1,5 +1,4 @@ //go:build linux || freebsd || openbsd || netbsd || dragonfly -// +build linux freebsd openbsd netbsd dragonfly // Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/src/syscall/flock_linux_32bit.go b/src/syscall/flock_linux_32bit.go index 2f3277497c..76a09fc47e 100644 --- a/src/syscall/flock_linux_32bit.go +++ b/src/syscall/flock_linux_32bit.go @@ -6,7 +6,6 @@ // internal/syscall/unix/fcntl_linux_32bit.go. //go:build (linux && 386) || (linux && arm) || (linux && mips) || (linux && mipsle) -// +build linux,386 linux,arm linux,mips linux,mipsle package syscall diff --git a/src/syscall/forkpipe.go b/src/syscall/forkpipe.go index 79cbdf4150..6f7d29ce67 100644 --- a/src/syscall/forkpipe.go +++ b/src/syscall/forkpipe.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || solaris -// +build aix darwin solaris package syscall diff --git a/src/syscall/forkpipe2.go b/src/syscall/forkpipe2.go index e57240c156..312244c0d8 100644 --- a/src/syscall/forkpipe2.go +++ b/src/syscall/forkpipe2.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd || netbsd || openbsd -// +build dragonfly freebsd netbsd openbsd package syscall diff --git a/src/syscall/fs_js.go b/src/syscall/fs_js.go index 0170516201..84a554e8b9 100644 --- a/src/syscall/fs_js.go +++ b/src/syscall/fs_js.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm package syscall diff --git a/src/syscall/getdirentries_test.go b/src/syscall/getdirentries_test.go index 814e656649..ddd8208c15 100644 --- a/src/syscall/getdirentries_test.go +++ b/src/syscall/getdirentries_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || freebsd || netbsd || openbsd -// +build darwin freebsd netbsd openbsd package syscall_test diff --git a/src/syscall/mkasm.go b/src/syscall/mkasm.go index e0ec46681d..dce61f322c 100644 --- a/src/syscall/mkasm.go +++ b/src/syscall/mkasm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore // mkasm.go generates assembly trampolines to call library routines from Go. // This program must be run after mksyscall.pl. diff --git a/src/syscall/mkpost.go b/src/syscall/mkpost.go index 94e8d92eff..4f81b81b57 100644 --- a/src/syscall/mkpost.go +++ b/src/syscall/mkpost.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore // mkpost processes the output of cgo -godefs to // modify the generated types. It is used to clean up diff --git a/src/syscall/mksyscall_windows.go b/src/syscall/mksyscall_windows.go index d8e8a713c5..39517bc7f1 100644 --- a/src/syscall/mksyscall_windows.go +++ b/src/syscall/mksyscall_windows.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore // mksyscall_windows wraps golang.org/x/sys/windows/mkwinsyscall. package main diff --git a/src/syscall/mmap_unix_test.go b/src/syscall/mmap_unix_test.go index e3909f1afb..3e9c08d67d 100644 --- a/src/syscall/mmap_unix_test.go +++ b/src/syscall/mmap_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd -// +build aix darwin dragonfly freebsd linux netbsd openbsd package syscall_test diff --git a/src/syscall/msan.go b/src/syscall/msan.go index 89fb75f03c..89c580799f 100644 --- a/src/syscall/msan.go +++ b/src/syscall/msan.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build msan -// +build msan package syscall diff --git a/src/syscall/msan0.go b/src/syscall/msan0.go index 85097025a0..fba8a5f716 100644 --- a/src/syscall/msan0.go +++ b/src/syscall/msan0.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !msan -// +build !msan package syscall diff --git a/src/syscall/net_js.go b/src/syscall/net_js.go index 2998c2159c..4f8258ddb3 100644 --- a/src/syscall/net_js.go +++ b/src/syscall/net_js.go @@ -6,7 +6,6 @@ // This file only exists to make the compiler happy. //go:build js && wasm -// +build js,wasm package syscall diff --git a/src/syscall/ptrace_darwin.go b/src/syscall/ptrace_darwin.go index b968c7c7f3..519e451c73 100644 --- a/src/syscall/ptrace_darwin.go +++ b/src/syscall/ptrace_darwin.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !ios -// +build !ios package syscall diff --git a/src/syscall/ptrace_ios.go b/src/syscall/ptrace_ios.go index 5209d1e0dd..fa8d000715 100644 --- a/src/syscall/ptrace_ios.go +++ b/src/syscall/ptrace_ios.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ios -// +build ios package syscall diff --git a/src/syscall/route_bsd.go b/src/syscall/route_bsd.go index e9321a4e64..8e47ff888e 100644 --- a/src/syscall/route_bsd.go +++ b/src/syscall/route_bsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || netbsd || openbsd -// +build darwin dragonfly freebsd netbsd openbsd package syscall diff --git a/src/syscall/route_freebsd_32bit.go b/src/syscall/route_freebsd_32bit.go index 412833a37c..c70f0bb0d3 100644 --- a/src/syscall/route_freebsd_32bit.go +++ b/src/syscall/route_freebsd_32bit.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build (freebsd && 386) || (freebsd && arm) -// +build freebsd,386 freebsd,arm package syscall diff --git a/src/syscall/route_freebsd_64bit.go b/src/syscall/route_freebsd_64bit.go index 5300bed471..9febdfaf35 100644 --- a/src/syscall/route_freebsd_64bit.go +++ b/src/syscall/route_freebsd_64bit.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build (freebsd && amd64) || (freebsd && arm64) -// +build freebsd,amd64 freebsd,arm64 package syscall diff --git a/src/syscall/setuidgid_32_linux.go b/src/syscall/setuidgid_32_linux.go index 64897fe43c..6920f33987 100644 --- a/src/syscall/setuidgid_32_linux.go +++ b/src/syscall/setuidgid_32_linux.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (386 || arm) -// +build linux -// +build 386 arm package syscall diff --git a/src/syscall/setuidgid_linux.go b/src/syscall/setuidgid_linux.go index 3b36f66fa2..c995d258eb 100644 --- a/src/syscall/setuidgid_linux.go +++ b/src/syscall/setuidgid_linux.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && !386 && !arm -// +build linux,!386,!arm package syscall diff --git a/src/syscall/sockcmsg_unix.go b/src/syscall/sockcmsg_unix.go index 99913b9a88..a3dcf818da 100644 --- a/src/syscall/sockcmsg_unix.go +++ b/src/syscall/sockcmsg_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris // Socket control messages diff --git a/src/syscall/sockcmsg_unix_other.go b/src/syscall/sockcmsg_unix_other.go index bd8dcfa34c..845bd9df99 100644 --- a/src/syscall/sockcmsg_unix_other.go +++ b/src/syscall/sockcmsg_unix_other.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin freebsd linux netbsd openbsd solaris package syscall diff --git a/src/syscall/syscall_bsd.go b/src/syscall/syscall_bsd.go index 40b1c07a90..ebe99ff230 100644 --- a/src/syscall/syscall_bsd.go +++ b/src/syscall/syscall_bsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || netbsd || openbsd -// +build darwin dragonfly freebsd netbsd openbsd // BSD system call wrappers shared by *BSD based systems // including OS X (Darwin) and FreeBSD. Like the other diff --git a/src/syscall/syscall_bsd_test.go b/src/syscall/syscall_bsd_test.go index 2d8a8cbfe6..98fab1d396 100644 --- a/src/syscall/syscall_bsd_test.go +++ b/src/syscall/syscall_bsd_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || openbsd -// +build darwin dragonfly freebsd openbsd package syscall_test diff --git a/src/syscall/syscall_freebsd_test.go b/src/syscall/syscall_freebsd_test.go index 72cd133b85..f04b12b6d3 100644 --- a/src/syscall/syscall_freebsd_test.go +++ b/src/syscall/syscall_freebsd_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build freebsd -// +build freebsd package syscall_test diff --git a/src/syscall/syscall_illumos.go b/src/syscall/syscall_illumos.go index ef95fe58f7..de6b160048 100644 --- a/src/syscall/syscall_illumos.go +++ b/src/syscall/syscall_illumos.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build illumos -// +build illumos // Illumos system calls not present on Solaris. diff --git a/src/syscall/syscall_js.go b/src/syscall/syscall_js.go index ed70d62284..cd95499063 100644 --- a/src/syscall/syscall_js.go +++ b/src/syscall/syscall_js.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm package syscall diff --git a/src/syscall/syscall_linux_mips64x.go b/src/syscall/syscall_linux_mips64x.go index fa0d2799ed..7c9dd80614 100644 --- a/src/syscall/syscall_linux_mips64x.go +++ b/src/syscall/syscall_linux_mips64x.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (mips64 || mips64le) -// +build linux -// +build mips64 mips64le package syscall diff --git a/src/syscall/syscall_linux_mipsx.go b/src/syscall/syscall_linux_mipsx.go index 568523eb27..741eeb14bb 100644 --- a/src/syscall/syscall_linux_mipsx.go +++ b/src/syscall/syscall_linux_mipsx.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (mips || mipsle) -// +build linux -// +build mips mipsle package syscall diff --git a/src/syscall/syscall_linux_ppc64x.go b/src/syscall/syscall_linux_ppc64x.go index 3e73f6f2a4..cc1b72e0e7 100644 --- a/src/syscall/syscall_linux_ppc64x.go +++ b/src/syscall/syscall_linux_ppc64x.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (ppc64 || ppc64le) -// +build linux -// +build ppc64 ppc64le package syscall diff --git a/src/syscall/syscall_openbsd1.go b/src/syscall/syscall_openbsd1.go index 15870ce1ee..bddeda637a 100644 --- a/src/syscall/syscall_openbsd1.go +++ b/src/syscall/syscall_openbsd1.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build openbsd && mips64 -// +build openbsd,mips64 package syscall diff --git a/src/syscall/syscall_openbsd_libc.go b/src/syscall/syscall_openbsd_libc.go index e67ee4e571..15b68fd0fc 100644 --- a/src/syscall/syscall_openbsd_libc.go +++ b/src/syscall/syscall_openbsd_libc.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build openbsd && !mips64 -// +build openbsd,!mips64 package syscall diff --git a/src/syscall/syscall_ptrace_test.go b/src/syscall/syscall_ptrace_test.go index 45729d9e8e..5b128de779 100644 --- a/src/syscall/syscall_ptrace_test.go +++ b/src/syscall/syscall_ptrace_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd -// +build darwin dragonfly freebsd linux netbsd openbsd package syscall_test diff --git a/src/syscall/syscall_unix.go b/src/syscall/syscall_unix.go index 101e39c7d0..9413db3832 100644 --- a/src/syscall/syscall_unix.go +++ b/src/syscall/syscall_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package syscall diff --git a/src/syscall/syscall_unix_test.go b/src/syscall/syscall_unix_test.go index af0bc856ee..7cc78c2147 100644 --- a/src/syscall/syscall_unix_test.go +++ b/src/syscall/syscall_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package syscall_test diff --git a/src/syscall/tables_js.go b/src/syscall/tables_js.go index 64d958415d..78a1e71a01 100644 --- a/src/syscall/tables_js.go +++ b/src/syscall/tables_js.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm package syscall diff --git a/src/syscall/time_fake.go b/src/syscall/time_fake.go index cf88aeb921..b60fe60b03 100644 --- a/src/syscall/time_fake.go +++ b/src/syscall/time_fake.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build faketime -// +build faketime package syscall diff --git a/src/syscall/time_nofake.go b/src/syscall/time_nofake.go index 5eaa2daabd..231875d8c3 100644 --- a/src/syscall/time_nofake.go +++ b/src/syscall/time_nofake.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !faketime -// +build !faketime package syscall diff --git a/src/syscall/timestruct.go b/src/syscall/timestruct.go index e4f3d50f56..7cf4be45b1 100644 --- a/src/syscall/timestruct.go +++ b/src/syscall/timestruct.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris package syscall diff --git a/src/syscall/types_aix.go b/src/syscall/types_aix.go index 6588d690ea..9e05af90ee 100644 --- a/src/syscall/types_aix.go +++ b/src/syscall/types_aix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore /* Input to cgo -godefs. See also mkerrors.sh and mkall.sh diff --git a/src/syscall/types_darwin.go b/src/syscall/types_darwin.go index c2a32c0782..c9404aaf1b 100644 --- a/src/syscall/types_darwin.go +++ b/src/syscall/types_darwin.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore /* Input to cgo -godefs. See also mkerrors.sh and mkall.sh diff --git a/src/syscall/types_dragonfly.go b/src/syscall/types_dragonfly.go index 9f8d5bc3dd..33420c4a92 100644 --- a/src/syscall/types_dragonfly.go +++ b/src/syscall/types_dragonfly.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore /* Input to cgo -godefs. See also mkerrors.sh and mkall.sh diff --git a/src/syscall/types_freebsd.go b/src/syscall/types_freebsd.go index d741411703..83bc7dc499 100644 --- a/src/syscall/types_freebsd.go +++ b/src/syscall/types_freebsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore /* Input to cgo -godefs. See also mkerrors.sh and mkall.sh diff --git a/src/syscall/types_illumos_amd64.go b/src/syscall/types_illumos_amd64.go index 254e3e7cfe..22c172f1f7 100644 --- a/src/syscall/types_illumos_amd64.go +++ b/src/syscall/types_illumos_amd64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build illumos -// +build illumos // Illumos consts not present on Solaris. These are added manually rather than // auto-generated by mkerror.sh diff --git a/src/syscall/types_linux.go b/src/syscall/types_linux.go index bf76be978b..23a76edd90 100644 --- a/src/syscall/types_linux.go +++ b/src/syscall/types_linux.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore /* Input to cgo -godefs. See also mkerrors.sh and mkall.sh diff --git a/src/syscall/types_netbsd.go b/src/syscall/types_netbsd.go index 0bd25ea3c9..e53e8c9386 100644 --- a/src/syscall/types_netbsd.go +++ b/src/syscall/types_netbsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore /* Input to cgo -godefs. See also mkerrors.sh and mkall.sh diff --git a/src/syscall/types_openbsd.go b/src/syscall/types_openbsd.go index 8b41cdca23..bfe6e9f592 100644 --- a/src/syscall/types_openbsd.go +++ b/src/syscall/types_openbsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore /* Input to cgo -godefs. See also mkerrors.sh and mkall.sh diff --git a/src/syscall/types_solaris.go b/src/syscall/types_solaris.go index 179f791481..2f56bc0601 100644 --- a/src/syscall/types_solaris.go +++ b/src/syscall/types_solaris.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore /* Input to cgo -godefs. See also mkerrors.sh and mkall.sh diff --git a/src/syscall/zerrors_darwin_amd64.go b/src/syscall/zerrors_darwin_amd64.go index 0b9897284c..ecbe89c547 100644 --- a/src/syscall/zerrors_darwin_amd64.go +++ b/src/syscall/zerrors_darwin_amd64.go @@ -5,7 +5,6 @@ // cgo -godefs -- -m64 _const.go //go:build amd64 && darwin -// +build amd64,darwin package syscall diff --git a/src/syscall/zerrors_darwin_arm64.go b/src/syscall/zerrors_darwin_arm64.go index 5f210fd1c4..fa7cb845c3 100644 --- a/src/syscall/zerrors_darwin_arm64.go +++ b/src/syscall/zerrors_darwin_arm64.go @@ -5,7 +5,6 @@ // cgo -godefs -- -m64 _const.go //go:build arm64 && darwin -// +build arm64,darwin package syscall diff --git a/src/syscall/zerrors_dragonfly_amd64.go b/src/syscall/zerrors_dragonfly_amd64.go index 35e2a52d25..bca2f50c96 100644 --- a/src/syscall/zerrors_dragonfly_amd64.go +++ b/src/syscall/zerrors_dragonfly_amd64.go @@ -5,7 +5,6 @@ // cgo -godefs -- -m64 _const.go //go:build amd64 && dragonfly -// +build amd64,dragonfly package syscall diff --git a/src/syscall/zerrors_freebsd_386.go b/src/syscall/zerrors_freebsd_386.go index aec26ad778..b1441e76a3 100644 --- a/src/syscall/zerrors_freebsd_386.go +++ b/src/syscall/zerrors_freebsd_386.go @@ -5,7 +5,6 @@ // cgo -godefs -- -m32 _const.go //go:build 386 && freebsd -// +build 386,freebsd package syscall diff --git a/src/syscall/zerrors_freebsd_amd64.go b/src/syscall/zerrors_freebsd_amd64.go index d6d13e4155..3aed004986 100644 --- a/src/syscall/zerrors_freebsd_amd64.go +++ b/src/syscall/zerrors_freebsd_amd64.go @@ -5,7 +5,6 @@ // cgo -godefs -- -m64 _const.go //go:build amd64 && freebsd -// +build amd64,freebsd package syscall diff --git a/src/syscall/zerrors_freebsd_arm.go b/src/syscall/zerrors_freebsd_arm.go index 15c714fad8..e1f91ff86c 100644 --- a/src/syscall/zerrors_freebsd_arm.go +++ b/src/syscall/zerrors_freebsd_arm.go @@ -5,7 +5,6 @@ // cgo -godefs -- _const.go //go:build arm && freebsd -// +build arm,freebsd package syscall diff --git a/src/syscall/zerrors_freebsd_arm64.go b/src/syscall/zerrors_freebsd_arm64.go index b20ce7d823..d0cb6c8ac7 100644 --- a/src/syscall/zerrors_freebsd_arm64.go +++ b/src/syscall/zerrors_freebsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build freebsd && arm64 -// +build freebsd,arm64 // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/src/syscall/zerrors_linux_386.go b/src/syscall/zerrors_linux_386.go index fb64932ad6..5e4c867bc9 100644 --- a/src/syscall/zerrors_linux_386.go +++ b/src/syscall/zerrors_linux_386.go @@ -5,7 +5,6 @@ // cgo -godefs -- -m32 _const.go //go:build 386 && linux -// +build 386,linux package syscall diff --git a/src/syscall/zerrors_linux_amd64.go b/src/syscall/zerrors_linux_amd64.go index 3a92bcdbb4..3ff6e498e7 100644 --- a/src/syscall/zerrors_linux_amd64.go +++ b/src/syscall/zerrors_linux_amd64.go @@ -5,7 +5,6 @@ // cgo -godefs -- -m64 _const.go //go:build amd64 && linux -// +build amd64,linux package syscall diff --git a/src/syscall/zerrors_linux_arm.go b/src/syscall/zerrors_linux_arm.go index e013d8e7fd..35825cc9fb 100644 --- a/src/syscall/zerrors_linux_arm.go +++ b/src/syscall/zerrors_linux_arm.go @@ -5,7 +5,6 @@ // cgo -godefs -- _const.go //go:build arm && linux -// +build arm,linux package syscall diff --git a/src/syscall/zerrors_linux_arm64.go b/src/syscall/zerrors_linux_arm64.go index 1a4d33e3fd..444b8816d5 100644 --- a/src/syscall/zerrors_linux_arm64.go +++ b/src/syscall/zerrors_linux_arm64.go @@ -5,7 +5,6 @@ // cgo -godefs -- _const.go //go:build arm64 && linux -// +build arm64,linux package syscall diff --git a/src/syscall/zerrors_linux_ppc64.go b/src/syscall/zerrors_linux_ppc64.go index 1dda43be70..dd439acc58 100644 --- a/src/syscall/zerrors_linux_ppc64.go +++ b/src/syscall/zerrors_linux_ppc64.go @@ -5,7 +5,6 @@ // cgo -godefs -- -m64 _const.go //go:build ppc64 && linux -// +build ppc64,linux package syscall diff --git a/src/syscall/zerrors_linux_ppc64le.go b/src/syscall/zerrors_linux_ppc64le.go index 6d56f1c998..b71cb0b4e7 100644 --- a/src/syscall/zerrors_linux_ppc64le.go +++ b/src/syscall/zerrors_linux_ppc64le.go @@ -5,7 +5,6 @@ // cgo -godefs -- -m64 _const.go //go:build ppc64le && linux -// +build ppc64le,linux package syscall diff --git a/src/syscall/zerrors_netbsd_386.go b/src/syscall/zerrors_netbsd_386.go index 934e9ef073..b2fcb65782 100644 --- a/src/syscall/zerrors_netbsd_386.go +++ b/src/syscall/zerrors_netbsd_386.go @@ -5,7 +5,6 @@ // cgo -godefs -- -m32 _const.go //go:build 386 && netbsd -// +build 386,netbsd package syscall diff --git a/src/syscall/zerrors_netbsd_amd64.go b/src/syscall/zerrors_netbsd_amd64.go index 0f5ad61a9f..dc52c3ca57 100644 --- a/src/syscall/zerrors_netbsd_amd64.go +++ b/src/syscall/zerrors_netbsd_amd64.go @@ -5,7 +5,6 @@ // cgo -godefs -- -m64 _const.go //go:build amd64 && netbsd -// +build amd64,netbsd package syscall diff --git a/src/syscall/zerrors_netbsd_arm.go b/src/syscall/zerrors_netbsd_arm.go index 9d8678750d..3137e18a24 100644 --- a/src/syscall/zerrors_netbsd_arm.go +++ b/src/syscall/zerrors_netbsd_arm.go @@ -5,7 +5,6 @@ // cgo -godefs -- -marm _const.go //go:build arm && netbsd -// +build arm,netbsd package syscall diff --git a/src/syscall/zerrors_netbsd_arm64.go b/src/syscall/zerrors_netbsd_arm64.go index 7adb72f7ed..cc1b0088c9 100644 --- a/src/syscall/zerrors_netbsd_arm64.go +++ b/src/syscall/zerrors_netbsd_arm64.go @@ -5,7 +5,6 @@ // cgo -godefs -- -m64 _const.go //go:build arm64 && netbsd -// +build arm64,netbsd package syscall diff --git a/src/syscall/zerrors_openbsd_386.go b/src/syscall/zerrors_openbsd_386.go index a8457c6edf..d17ecb96e5 100644 --- a/src/syscall/zerrors_openbsd_386.go +++ b/src/syscall/zerrors_openbsd_386.go @@ -5,7 +5,6 @@ // cgo -godefs -- -m32 _const.go //go:build 386 && openbsd -// +build 386,openbsd package syscall diff --git a/src/syscall/zerrors_openbsd_amd64.go b/src/syscall/zerrors_openbsd_amd64.go index eb19537a2a..4904e7614f 100644 --- a/src/syscall/zerrors_openbsd_amd64.go +++ b/src/syscall/zerrors_openbsd_amd64.go @@ -5,7 +5,6 @@ // cgo -godefs -- -m64 _const.go //go:build amd64 && openbsd -// +build amd64,openbsd package syscall diff --git a/src/syscall/zerrors_openbsd_arm.go b/src/syscall/zerrors_openbsd_arm.go index 89a4e6d89a..76ac9173a9 100644 --- a/src/syscall/zerrors_openbsd_arm.go +++ b/src/syscall/zerrors_openbsd_arm.go @@ -5,7 +5,6 @@ // cgo -godefs -- _const.go //go:build arm && openbsd -// +build arm,openbsd package syscall diff --git a/src/syscall/zerrors_solaris_amd64.go b/src/syscall/zerrors_solaris_amd64.go index b7dee69602..fb25dacee4 100644 --- a/src/syscall/zerrors_solaris_amd64.go +++ b/src/syscall/zerrors_solaris_amd64.go @@ -5,7 +5,6 @@ // cgo -godefs -- -m64 _const.go //go:build amd64 && solaris -// +build amd64,solaris package syscall diff --git a/src/syscall/zsyscall_aix_ppc64.go b/src/syscall/zsyscall_aix_ppc64.go index 134ae41165..94f1b4371c 100644 --- a/src/syscall/zsyscall_aix_ppc64.go +++ b/src/syscall/zsyscall_aix_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build aix && ppc64 -// +build aix,ppc64 package syscall diff --git a/src/syscall/zsyscall_darwin_amd64.go b/src/syscall/zsyscall_darwin_amd64.go index ff88fef74e..0ccdaf2d0e 100644 --- a/src/syscall/zsyscall_darwin_amd64.go +++ b/src/syscall/zsyscall_darwin_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build darwin && amd64 -// +build darwin,amd64 package syscall diff --git a/src/syscall/zsyscall_darwin_arm64.go b/src/syscall/zsyscall_darwin_arm64.go index b096b5e662..09bf34bb3c 100644 --- a/src/syscall/zsyscall_darwin_arm64.go +++ b/src/syscall/zsyscall_darwin_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build darwin && arm64 -// +build darwin,arm64 package syscall diff --git a/src/syscall/zsyscall_dragonfly_amd64.go b/src/syscall/zsyscall_dragonfly_amd64.go index aa327c0010..5d5576d76f 100644 --- a/src/syscall/zsyscall_dragonfly_amd64.go +++ b/src/syscall/zsyscall_dragonfly_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build dragonfly && amd64 -// +build dragonfly,amd64 package syscall diff --git a/src/syscall/zsyscall_freebsd_386.go b/src/syscall/zsyscall_freebsd_386.go index 7137d66f0b..ed0eb9fa15 100644 --- a/src/syscall/zsyscall_freebsd_386.go +++ b/src/syscall/zsyscall_freebsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build freebsd && 386 -// +build freebsd,386 package syscall diff --git a/src/syscall/zsyscall_freebsd_amd64.go b/src/syscall/zsyscall_freebsd_amd64.go index d721dafde2..e291a56756 100644 --- a/src/syscall/zsyscall_freebsd_amd64.go +++ b/src/syscall/zsyscall_freebsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build freebsd && amd64 -// +build freebsd,amd64 package syscall diff --git a/src/syscall/zsyscall_freebsd_arm.go b/src/syscall/zsyscall_freebsd_arm.go index d9dbea921a..7dd856fd97 100644 --- a/src/syscall/zsyscall_freebsd_arm.go +++ b/src/syscall/zsyscall_freebsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build freebsd && arm -// +build freebsd,arm package syscall diff --git a/src/syscall/zsyscall_freebsd_arm64.go b/src/syscall/zsyscall_freebsd_arm64.go index a24f0115e2..229a9a2238 100644 --- a/src/syscall/zsyscall_freebsd_arm64.go +++ b/src/syscall/zsyscall_freebsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build freebsd && arm64 -// +build freebsd,arm64 package syscall diff --git a/src/syscall/zsyscall_linux_386.go b/src/syscall/zsyscall_linux_386.go index a1394d32cb..c385dd3ca1 100644 --- a/src/syscall/zsyscall_linux_386.go +++ b/src/syscall/zsyscall_linux_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build linux && 386 -// +build linux,386 package syscall diff --git a/src/syscall/zsyscall_linux_amd64.go b/src/syscall/zsyscall_linux_amd64.go index de6047d11c..2059271324 100644 --- a/src/syscall/zsyscall_linux_amd64.go +++ b/src/syscall/zsyscall_linux_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build linux && amd64 -// +build linux,amd64 package syscall diff --git a/src/syscall/zsyscall_linux_arm.go b/src/syscall/zsyscall_linux_arm.go index 3663b2eead..50498c6eb6 100644 --- a/src/syscall/zsyscall_linux_arm.go +++ b/src/syscall/zsyscall_linux_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build linux && arm -// +build linux,arm package syscall diff --git a/src/syscall/zsyscall_linux_arm64.go b/src/syscall/zsyscall_linux_arm64.go index 19a9c0ca61..6714123f9c 100644 --- a/src/syscall/zsyscall_linux_arm64.go +++ b/src/syscall/zsyscall_linux_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build linux && arm64 -// +build linux,arm64 package syscall diff --git a/src/syscall/zsyscall_linux_mips.go b/src/syscall/zsyscall_linux_mips.go index 966b2e1f2c..c6f4878ff7 100644 --- a/src/syscall/zsyscall_linux_mips.go +++ b/src/syscall/zsyscall_linux_mips.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build linux && mips -// +build linux,mips package syscall diff --git a/src/syscall/zsyscall_linux_mips64.go b/src/syscall/zsyscall_linux_mips64.go index c6812a0515..5187c28ebb 100644 --- a/src/syscall/zsyscall_linux_mips64.go +++ b/src/syscall/zsyscall_linux_mips64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build linux && mips64 -// +build linux,mips64 package syscall diff --git a/src/syscall/zsyscall_linux_mips64le.go b/src/syscall/zsyscall_linux_mips64le.go index eaaf7dfb41..f3dacfeeda 100644 --- a/src/syscall/zsyscall_linux_mips64le.go +++ b/src/syscall/zsyscall_linux_mips64le.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build linux && mips64le -// +build linux,mips64le package syscall diff --git a/src/syscall/zsyscall_linux_mipsle.go b/src/syscall/zsyscall_linux_mipsle.go index bb159f1fe7..fbc543709f 100644 --- a/src/syscall/zsyscall_linux_mipsle.go +++ b/src/syscall/zsyscall_linux_mipsle.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build linux && mipsle -// +build linux,mipsle package syscall diff --git a/src/syscall/zsyscall_linux_ppc64.go b/src/syscall/zsyscall_linux_ppc64.go index 8a4328560a..b71dca2b37 100644 --- a/src/syscall/zsyscall_linux_ppc64.go +++ b/src/syscall/zsyscall_linux_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build linux && ppc64 -// +build linux,ppc64 package syscall diff --git a/src/syscall/zsyscall_linux_ppc64le.go b/src/syscall/zsyscall_linux_ppc64le.go index 274b55ce6b..193fbbc541 100644 --- a/src/syscall/zsyscall_linux_ppc64le.go +++ b/src/syscall/zsyscall_linux_ppc64le.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build linux && ppc64le -// +build linux,ppc64le package syscall diff --git a/src/syscall/zsyscall_linux_riscv64.go b/src/syscall/zsyscall_linux_riscv64.go index e21dc46f32..33b1e9b431 100644 --- a/src/syscall/zsyscall_linux_riscv64.go +++ b/src/syscall/zsyscall_linux_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build linux && riscv64 -// +build linux,riscv64 package syscall diff --git a/src/syscall/zsyscall_linux_s390x.go b/src/syscall/zsyscall_linux_s390x.go index fc667e7c3f..2ab78c71bf 100644 --- a/src/syscall/zsyscall_linux_s390x.go +++ b/src/syscall/zsyscall_linux_s390x.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build linux && s390x -// +build linux,s390x package syscall diff --git a/src/syscall/zsyscall_netbsd_386.go b/src/syscall/zsyscall_netbsd_386.go index 07ff5fba5f..408318181a 100644 --- a/src/syscall/zsyscall_netbsd_386.go +++ b/src/syscall/zsyscall_netbsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build netbsd && 386 -// +build netbsd,386 package syscall diff --git a/src/syscall/zsyscall_netbsd_amd64.go b/src/syscall/zsyscall_netbsd_amd64.go index ffb4e059a4..2039cf6d0e 100644 --- a/src/syscall/zsyscall_netbsd_amd64.go +++ b/src/syscall/zsyscall_netbsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build netbsd && amd64 -// +build netbsd,amd64 package syscall diff --git a/src/syscall/zsyscall_netbsd_arm.go b/src/syscall/zsyscall_netbsd_arm.go index 37df77e5e8..3c287ea223 100644 --- a/src/syscall/zsyscall_netbsd_arm.go +++ b/src/syscall/zsyscall_netbsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build netbsd && arm -// +build netbsd,arm package syscall diff --git a/src/syscall/zsyscall_netbsd_arm64.go b/src/syscall/zsyscall_netbsd_arm64.go index c5eb57a226..1d40db9e6b 100644 --- a/src/syscall/zsyscall_netbsd_arm64.go +++ b/src/syscall/zsyscall_netbsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build netbsd && arm64 -// +build netbsd,arm64 package syscall diff --git a/src/syscall/zsyscall_openbsd_386.go b/src/syscall/zsyscall_openbsd_386.go index 1ff5c95fa1..5f95d7a9c6 100644 --- a/src/syscall/zsyscall_openbsd_386.go +++ b/src/syscall/zsyscall_openbsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build openbsd && 386 -// +build openbsd,386 package syscall diff --git a/src/syscall/zsyscall_openbsd_amd64.go b/src/syscall/zsyscall_openbsd_amd64.go index 85cb195739..189bf887e6 100644 --- a/src/syscall/zsyscall_openbsd_amd64.go +++ b/src/syscall/zsyscall_openbsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build openbsd && amd64 -// +build openbsd,amd64 package syscall diff --git a/src/syscall/zsyscall_openbsd_arm.go b/src/syscall/zsyscall_openbsd_arm.go index 04a2fadccd..c7513a3ac9 100644 --- a/src/syscall/zsyscall_openbsd_arm.go +++ b/src/syscall/zsyscall_openbsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build openbsd && arm -// +build openbsd,arm package syscall diff --git a/src/syscall/zsyscall_openbsd_arm64.go b/src/syscall/zsyscall_openbsd_arm64.go index fa35905d1b..293b703600 100644 --- a/src/syscall/zsyscall_openbsd_arm64.go +++ b/src/syscall/zsyscall_openbsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build openbsd && arm64 -// +build openbsd,arm64 package syscall diff --git a/src/syscall/zsyscall_openbsd_mips64.go b/src/syscall/zsyscall_openbsd_mips64.go index 70fd1474fd..51904b5e29 100644 --- a/src/syscall/zsyscall_openbsd_mips64.go +++ b/src/syscall/zsyscall_openbsd_mips64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build openbsd && mips64 -// +build openbsd,mips64 package syscall diff --git a/src/syscall/zsyscall_plan9_386.go b/src/syscall/zsyscall_plan9_386.go index 8b7727b343..32fa0f0eb6 100644 --- a/src/syscall/zsyscall_plan9_386.go +++ b/src/syscall/zsyscall_plan9_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build plan9 && 386 -// +build plan9,386 package syscall diff --git a/src/syscall/zsyscall_plan9_amd64.go b/src/syscall/zsyscall_plan9_amd64.go index bed9108ea6..b3337ce811 100644 --- a/src/syscall/zsyscall_plan9_amd64.go +++ b/src/syscall/zsyscall_plan9_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build plan9 && amd64 -// +build plan9,amd64 package syscall diff --git a/src/syscall/zsyscall_plan9_arm.go b/src/syscall/zsyscall_plan9_arm.go index 7bbcf9b4b7..3705566fa3 100644 --- a/src/syscall/zsyscall_plan9_arm.go +++ b/src/syscall/zsyscall_plan9_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build plan9 && arm -// +build plan9,arm package syscall diff --git a/src/syscall/zsyscall_solaris_amd64.go b/src/syscall/zsyscall_solaris_amd64.go index 9b37dc0950..2d8cdfd280 100644 --- a/src/syscall/zsyscall_solaris_amd64.go +++ b/src/syscall/zsyscall_solaris_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build solaris && amd64 -// +build solaris,amd64 package syscall diff --git a/src/syscall/zsysnum_darwin_amd64.go b/src/syscall/zsysnum_darwin_amd64.go index f66f7d2715..08e003f292 100644 --- a/src/syscall/zsysnum_darwin_amd64.go +++ b/src/syscall/zsysnum_darwin_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build amd64 && darwin -// +build amd64,darwin package syscall diff --git a/src/syscall/zsysnum_darwin_arm64.go b/src/syscall/zsysnum_darwin_arm64.go index 6fa146368a..71309bb4d6 100644 --- a/src/syscall/zsysnum_darwin_arm64.go +++ b/src/syscall/zsysnum_darwin_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build arm64 && darwin -// +build arm64,darwin package syscall diff --git a/src/syscall/zsysnum_dragonfly_amd64.go b/src/syscall/zsysnum_dragonfly_amd64.go index e8996db0f8..03d4b06a09 100644 --- a/src/syscall/zsysnum_dragonfly_amd64.go +++ b/src/syscall/zsysnum_dragonfly_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build amd64 && dragonfly -// +build amd64,dragonfly package syscall diff --git a/src/syscall/zsysnum_freebsd_386.go b/src/syscall/zsysnum_freebsd_386.go index 1ed7e3ee8d..355b2ec303 100644 --- a/src/syscall/zsysnum_freebsd_386.go +++ b/src/syscall/zsysnum_freebsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build 386 && freebsd -// +build 386,freebsd package syscall diff --git a/src/syscall/zsysnum_freebsd_amd64.go b/src/syscall/zsysnum_freebsd_amd64.go index d72dbc944a..84c821c955 100644 --- a/src/syscall/zsysnum_freebsd_amd64.go +++ b/src/syscall/zsysnum_freebsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build amd64 && freebsd -// +build amd64,freebsd package syscall diff --git a/src/syscall/zsysnum_freebsd_arm.go b/src/syscall/zsysnum_freebsd_arm.go index 4f4dc4db79..785e7875f4 100644 --- a/src/syscall/zsysnum_freebsd_arm.go +++ b/src/syscall/zsysnum_freebsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build arm && freebsd -// +build arm,freebsd package syscall diff --git a/src/syscall/zsysnum_freebsd_arm64.go b/src/syscall/zsysnum_freebsd_arm64.go index ab1a05258e..7144a8abed 100644 --- a/src/syscall/zsysnum_freebsd_arm64.go +++ b/src/syscall/zsysnum_freebsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build arm64 && freebsd -// +build arm64,freebsd package syscall diff --git a/src/syscall/zsysnum_linux_386.go b/src/syscall/zsysnum_linux_386.go index 792f43550e..4966d2a947 100644 --- a/src/syscall/zsysnum_linux_386.go +++ b/src/syscall/zsysnum_linux_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build 386 && linux -// +build 386,linux package syscall diff --git a/src/syscall/zsysnum_linux_amd64.go b/src/syscall/zsysnum_linux_amd64.go index 9ea18d6111..576c7c36a6 100644 --- a/src/syscall/zsysnum_linux_amd64.go +++ b/src/syscall/zsysnum_linux_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build amd64 && linux -// +build amd64,linux package syscall diff --git a/src/syscall/zsysnum_linux_arm.go b/src/syscall/zsysnum_linux_arm.go index ccae9c15e3..b0da97c64b 100644 --- a/src/syscall/zsysnum_linux_arm.go +++ b/src/syscall/zsysnum_linux_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build arm && linux -// +build arm,linux package syscall diff --git a/src/syscall/zsysnum_linux_arm64.go b/src/syscall/zsysnum_linux_arm64.go index 17c54a2c83..0136d9440b 100644 --- a/src/syscall/zsysnum_linux_arm64.go +++ b/src/syscall/zsysnum_linux_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build arm64 && linux -// +build arm64,linux package syscall diff --git a/src/syscall/zsysnum_linux_ppc64.go b/src/syscall/zsysnum_linux_ppc64.go index a0d37ff1f2..cc964c23e2 100644 --- a/src/syscall/zsysnum_linux_ppc64.go +++ b/src/syscall/zsysnum_linux_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build ppc64 && linux -// +build ppc64,linux package syscall diff --git a/src/syscall/zsysnum_linux_ppc64le.go b/src/syscall/zsysnum_linux_ppc64le.go index f8f82d2043..57bfb7795f 100644 --- a/src/syscall/zsysnum_linux_ppc64le.go +++ b/src/syscall/zsysnum_linux_ppc64le.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build ppc64le && linux -// +build ppc64le,linux package syscall diff --git a/src/syscall/zsysnum_netbsd_386.go b/src/syscall/zsysnum_netbsd_386.go index fd0c329951..5696c4befe 100644 --- a/src/syscall/zsysnum_netbsd_386.go +++ b/src/syscall/zsysnum_netbsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build 386 && netbsd -// +build 386,netbsd package syscall diff --git a/src/syscall/zsysnum_netbsd_amd64.go b/src/syscall/zsysnum_netbsd_amd64.go index 03f2cd3bd3..9fb85cddba 100644 --- a/src/syscall/zsysnum_netbsd_amd64.go +++ b/src/syscall/zsysnum_netbsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build amd64 && netbsd -// +build amd64,netbsd package syscall diff --git a/src/syscall/zsysnum_netbsd_arm.go b/src/syscall/zsysnum_netbsd_arm.go index 7b356e7102..e0e8994641 100644 --- a/src/syscall/zsysnum_netbsd_arm.go +++ b/src/syscall/zsysnum_netbsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build arm && netbsd -// +build arm,netbsd package syscall diff --git a/src/syscall/zsysnum_netbsd_arm64.go b/src/syscall/zsysnum_netbsd_arm64.go index 3f57ec4d89..9653364dae 100644 --- a/src/syscall/zsysnum_netbsd_arm64.go +++ b/src/syscall/zsysnum_netbsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build arm64 && netbsd -// +build arm64,netbsd package syscall diff --git a/src/syscall/zsysnum_openbsd_386.go b/src/syscall/zsysnum_openbsd_386.go index b289886d6c..3b12639bd7 100644 --- a/src/syscall/zsysnum_openbsd_386.go +++ b/src/syscall/zsysnum_openbsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build 386 && openbsd -// +build 386,openbsd package syscall diff --git a/src/syscall/zsysnum_openbsd_amd64.go b/src/syscall/zsysnum_openbsd_amd64.go index 8cf2b68dcd..bce309dc5d 100644 --- a/src/syscall/zsysnum_openbsd_amd64.go +++ b/src/syscall/zsysnum_openbsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build amd64 && openbsd -// +build amd64,openbsd package syscall diff --git a/src/syscall/zsysnum_openbsd_arm.go b/src/syscall/zsysnum_openbsd_arm.go index cc33773a05..05aed70762 100644 --- a/src/syscall/zsysnum_openbsd_arm.go +++ b/src/syscall/zsysnum_openbsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build arm && openbsd -// +build arm,openbsd package syscall diff --git a/src/syscall/zsysnum_solaris_amd64.go b/src/syscall/zsysnum_solaris_amd64.go index 23c9c715b5..ea244e535e 100644 --- a/src/syscall/zsysnum_solaris_amd64.go +++ b/src/syscall/zsysnum_solaris_amd64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 && solaris -// +build amd64,solaris package syscall diff --git a/src/syscall/ztypes_darwin_amd64.go b/src/syscall/ztypes_darwin_amd64.go index 8feacc47ab..551edc7025 100644 --- a/src/syscall/ztypes_darwin_amd64.go +++ b/src/syscall/ztypes_darwin_amd64.go @@ -2,7 +2,6 @@ // cgo -godefs types_darwin.go //go:build amd64 && darwin -// +build amd64,darwin package syscall diff --git a/src/syscall/ztypes_darwin_arm64.go b/src/syscall/ztypes_darwin_arm64.go index 8079d22429..46f78a97eb 100644 --- a/src/syscall/ztypes_darwin_arm64.go +++ b/src/syscall/ztypes_darwin_arm64.go @@ -2,7 +2,6 @@ // cgo -godefs types_darwin.go //go:build arm64 && darwin -// +build arm64,darwin package syscall diff --git a/src/syscall/ztypes_dragonfly_amd64.go b/src/syscall/ztypes_dragonfly_amd64.go index a51e0038bb..ec519b72ec 100644 --- a/src/syscall/ztypes_dragonfly_amd64.go +++ b/src/syscall/ztypes_dragonfly_amd64.go @@ -2,7 +2,6 @@ // cgo -godefs types_dragonfly.go //go:build amd64 && dragonfly -// +build amd64,dragonfly package syscall diff --git a/src/syscall/ztypes_freebsd_386.go b/src/syscall/ztypes_freebsd_386.go index 1739726883..e1946dece8 100644 --- a/src/syscall/ztypes_freebsd_386.go +++ b/src/syscall/ztypes_freebsd_386.go @@ -2,7 +2,6 @@ // cgo -godefs types_freebsd.go | go run mkpost.go //go:build 386 && freebsd -// +build 386,freebsd package syscall diff --git a/src/syscall/ztypes_freebsd_amd64.go b/src/syscall/ztypes_freebsd_amd64.go index 0457d8e995..a718345d79 100644 --- a/src/syscall/ztypes_freebsd_amd64.go +++ b/src/syscall/ztypes_freebsd_amd64.go @@ -2,7 +2,6 @@ // cgo -godefs types_freebsd.go | go run mkpost.go //go:build amd64 && freebsd -// +build amd64,freebsd package syscall diff --git a/src/syscall/ztypes_freebsd_arm.go b/src/syscall/ztypes_freebsd_arm.go index 29c8380d89..9c5a066713 100644 --- a/src/syscall/ztypes_freebsd_arm.go +++ b/src/syscall/ztypes_freebsd_arm.go @@ -2,7 +2,6 @@ // cgo -godefs -- -fsigned-char types_freebsd.go //go:build arm && freebsd -// +build arm,freebsd package syscall diff --git a/src/syscall/ztypes_freebsd_arm64.go b/src/syscall/ztypes_freebsd_arm64.go index 6472db0080..3ccd9fc0dd 100644 --- a/src/syscall/ztypes_freebsd_arm64.go +++ b/src/syscall/ztypes_freebsd_arm64.go @@ -2,7 +2,6 @@ // cgo -godefs types_freebsd.go | go run mkpost.go //go:build arm64 && freebsd -// +build arm64,freebsd package syscall diff --git a/src/syscall/ztypes_linux_386.go b/src/syscall/ztypes_linux_386.go index 251a0c0b4a..a45511e847 100644 --- a/src/syscall/ztypes_linux_386.go +++ b/src/syscall/ztypes_linux_386.go @@ -2,7 +2,6 @@ // cgo -godefs types_linux.go //go:build 386 && linux -// +build 386,linux package syscall diff --git a/src/syscall/ztypes_linux_amd64.go b/src/syscall/ztypes_linux_amd64.go index 34c953fc8b..1bab13bf43 100644 --- a/src/syscall/ztypes_linux_amd64.go +++ b/src/syscall/ztypes_linux_amd64.go @@ -2,7 +2,6 @@ // cgo -godefs types_linux.go //go:build amd64 && linux -// +build amd64,linux package syscall diff --git a/src/syscall/ztypes_linux_arm.go b/src/syscall/ztypes_linux_arm.go index 4de656b491..a4d61bd19b 100644 --- a/src/syscall/ztypes_linux_arm.go +++ b/src/syscall/ztypes_linux_arm.go @@ -2,7 +2,6 @@ // cgo -godefs types_linux.go //go:build arm && linux -// +build arm,linux package syscall diff --git a/src/syscall/ztypes_linux_arm64.go b/src/syscall/ztypes_linux_arm64.go index bed9cb0851..1e469c36d2 100644 --- a/src/syscall/ztypes_linux_arm64.go +++ b/src/syscall/ztypes_linux_arm64.go @@ -2,7 +2,6 @@ // cgo -godefs -- -fsigned-char types_linux.go //go:build arm64 && linux -// +build arm64,linux package syscall diff --git a/src/syscall/ztypes_linux_ppc64.go b/src/syscall/ztypes_linux_ppc64.go index 355533fb27..c830cee966 100644 --- a/src/syscall/ztypes_linux_ppc64.go +++ b/src/syscall/ztypes_linux_ppc64.go @@ -2,7 +2,6 @@ // cgo -godefs types_linux.go //go:build ppc64 && linux -// +build ppc64,linux package syscall diff --git a/src/syscall/ztypes_linux_ppc64le.go b/src/syscall/ztypes_linux_ppc64le.go index 94e12c742c..770ddc9fe9 100644 --- a/src/syscall/ztypes_linux_ppc64le.go +++ b/src/syscall/ztypes_linux_ppc64le.go @@ -2,7 +2,6 @@ // cgo -godefs types_linux.go //go:build ppc64le && linux -// +build ppc64le,linux package syscall diff --git a/src/syscall/ztypes_netbsd_386.go b/src/syscall/ztypes_netbsd_386.go index 321460f45a..74eaa4a150 100644 --- a/src/syscall/ztypes_netbsd_386.go +++ b/src/syscall/ztypes_netbsd_386.go @@ -2,7 +2,6 @@ // cgo -godefs types_netbsd.go //go:build 386 && netbsd -// +build 386,netbsd package syscall diff --git a/src/syscall/ztypes_netbsd_amd64.go b/src/syscall/ztypes_netbsd_amd64.go index 370d717263..fc28fc9bb8 100644 --- a/src/syscall/ztypes_netbsd_amd64.go +++ b/src/syscall/ztypes_netbsd_amd64.go @@ -2,7 +2,6 @@ // cgo -godefs types_netbsd.go //go:build amd64 && netbsd -// +build amd64,netbsd package syscall diff --git a/src/syscall/ztypes_netbsd_arm.go b/src/syscall/ztypes_netbsd_arm.go index 557c634533..1f885048dd 100644 --- a/src/syscall/ztypes_netbsd_arm.go +++ b/src/syscall/ztypes_netbsd_arm.go @@ -2,7 +2,6 @@ // cgo -godefs types_netbsd.go //go:build arm && netbsd -// +build arm,netbsd package syscall diff --git a/src/syscall/ztypes_netbsd_arm64.go b/src/syscall/ztypes_netbsd_arm64.go index 19f3690341..cac74693d7 100644 --- a/src/syscall/ztypes_netbsd_arm64.go +++ b/src/syscall/ztypes_netbsd_arm64.go @@ -2,7 +2,6 @@ // cgo -godefs types_netbsd.go //go:build arm64 && netbsd -// +build arm64,netbsd package syscall diff --git a/src/syscall/ztypes_openbsd_386.go b/src/syscall/ztypes_openbsd_386.go index 222c6c7e46..f9ba685e25 100644 --- a/src/syscall/ztypes_openbsd_386.go +++ b/src/syscall/ztypes_openbsd_386.go @@ -2,7 +2,6 @@ // cgo -godefs types_openbsd.go //go:build 386 && openbsd -// +build 386,openbsd package syscall diff --git a/src/syscall/ztypes_openbsd_amd64.go b/src/syscall/ztypes_openbsd_amd64.go index 644ee9b3df..889b9551ae 100644 --- a/src/syscall/ztypes_openbsd_amd64.go +++ b/src/syscall/ztypes_openbsd_amd64.go @@ -2,7 +2,6 @@ // cgo -godefs types_openbsd.go //go:build amd64 && openbsd -// +build amd64,openbsd package syscall diff --git a/src/syscall/ztypes_solaris_amd64.go b/src/syscall/ztypes_solaris_amd64.go index 64e16b4943..d486cd002f 100644 --- a/src/syscall/ztypes_solaris_amd64.go +++ b/src/syscall/ztypes_solaris_amd64.go @@ -2,7 +2,6 @@ // cgo -godefs types_solaris.go //go:build amd64 && solaris -// +build amd64,solaris package syscall diff --git a/src/testing/run_example.go b/src/testing/run_example.go index d9e342d495..e7eab1e50e 100644 --- a/src/testing/run_example.go +++ b/src/testing/run_example.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !js -// +build !js // TODO(@musiol, @odeke-em): re-unify this entire file back into // example.go when js/wasm gets an os.Pipe implementation diff --git a/src/testing/run_example_js.go b/src/testing/run_example_js.go index d914633ba9..adef9511fb 100644 --- a/src/testing/run_example_js.go +++ b/src/testing/run_example_js.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js -// +build js package testing diff --git a/src/time/embed.go b/src/time/embed.go index 34490c859d..2a9821baa9 100644 --- a/src/time/embed.go +++ b/src/time/embed.go @@ -6,7 +6,6 @@ // the binary. //go:build timetzdata -// +build timetzdata package time diff --git a/src/time/genzabbrs.go b/src/time/genzabbrs.go index 9fd2f2b762..a8651bfdb8 100644 --- a/src/time/genzabbrs.go +++ b/src/time/genzabbrs.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore // // usage: diff --git a/src/time/sys_plan9.go b/src/time/sys_plan9.go index 4dc55e44aa..ba37cf5424 100644 --- a/src/time/sys_plan9.go +++ b/src/time/sys_plan9.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build plan9 -// +build plan9 package time diff --git a/src/time/sys_unix.go b/src/time/sys_unix.go index 60fc090dc9..a949a6af22 100644 --- a/src/time/sys_unix.go +++ b/src/time/sys_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris package time diff --git a/src/time/tzdata/generate_zipdata.go b/src/time/tzdata/generate_zipdata.go index 0869c8458c..4f40b51c73 100644 --- a/src/time/tzdata/generate_zipdata.go +++ b/src/time/tzdata/generate_zipdata.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ignore -// +build ignore // This program generates zipdata.go from $GOROOT/lib/time/zoneinfo.zip. package main diff --git a/src/time/zoneinfo_ios.go b/src/time/zoneinfo_ios.go index 044691e130..7eccabf249 100644 --- a/src/time/zoneinfo_ios.go +++ b/src/time/zoneinfo_ios.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ios -// +build ios package time diff --git a/src/time/zoneinfo_js.go b/src/time/zoneinfo_js.go index 8245614d2e..d0aefb9088 100644 --- a/src/time/zoneinfo_js.go +++ b/src/time/zoneinfo_js.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm package time diff --git a/src/time/zoneinfo_unix.go b/src/time/zoneinfo_unix.go index 4ea029dbde..23f8b3cdb4 100644 --- a/src/time/zoneinfo_unix.go +++ b/src/time/zoneinfo_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || (darwin && !ios) || dragonfly || freebsd || (linux && !android) || netbsd || openbsd || solaris -// +build aix darwin,!ios dragonfly freebsd linux,!android netbsd openbsd solaris // Parse "zoneinfo" time zone file. // This is a fairly standard file format used on OS X, Linux, BSD, Sun, and others. diff --git a/src/time/zoneinfo_unix_test.go b/src/time/zoneinfo_unix_test.go index b75b374c3d..de95295cd3 100644 --- a/src/time/zoneinfo_unix_test.go +++ b/src/time/zoneinfo_unix_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || (darwin && !ios) || dragonfly || freebsd || (linux && !android) || netbsd || openbsd || solaris -// +build aix darwin,!ios dragonfly freebsd linux,!android netbsd openbsd solaris package time_test -- GitLab From 5e217284dc9f3b55e8c8b225dc81c1eb1004d423 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 28 Oct 2021 16:06:21 -0400 Subject: [PATCH 1806/2500] cmd/internal/goobj: bump version number There have a few updates to the Go object file in this cycle (e.g. FuncInfo format change, some changes in constant values), and it is not compatible with the old tools. Bump up the version number. Change-Id: Id176979b139c76ded2c50f2678eb313934326d6f Reviewed-on: https://go-review.googlesource.com/c/go/+/359483 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: Than McIntosh TryBot-Result: Go Bot --- src/cmd/internal/goobj/objfile.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/internal/goobj/objfile.go b/src/cmd/internal/goobj/objfile.go index 4dfea84539..9765058392 100644 --- a/src/cmd/internal/goobj/objfile.go +++ b/src/cmd/internal/goobj/objfile.go @@ -31,7 +31,7 @@ import ( // New object file format. // // Header struct { -// Magic [...]byte // "\x00go117ld" +// Magic [...]byte // "\x00go118ld" // Fingerprint [8]byte // Flags uint32 // Offsets [...]uint32 // byte offset of each block below @@ -215,7 +215,7 @@ type Header struct { Offsets [NBlk]uint32 } -const Magic = "\x00go117ld" +const Magic = "\x00go118ld" func (h *Header) Write(w *Writer) { w.RawString(h.Magic) -- GitLab From 834e36ec778c11b068a2d5354343d4668e5a9ceb Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 28 Oct 2021 16:23:51 -0400 Subject: [PATCH 1807/2500] net/http: restore generated // +build comment The upstream cmd/bundle tool does not yet omit it, and the longtest builders test that the generated file is not modified. For #41184. Change-Id: Ib68f532139ed1436cbaf3a756f300fe60f520cab Reviewed-on: https://go-review.googlesource.com/c/go/+/359484 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills Reviewed-by: Dmitri Shuralyov Reviewed-by: David Chase TryBot-Result: Go Bot --- src/net/http/h2_bundle.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go index df98232824..29226d4065 100644 --- a/src/net/http/h2_bundle.go +++ b/src/net/http/h2_bundle.go @@ -1,4 +1,5 @@ //go:build !nethttpomithttp2 +// +build !nethttpomithttp2 // Code generated by golang.org/x/tools/cmd/bundle. DO NOT EDIT. // $ bundle -o=h2_bundle.go -prefix=http2 -tags=!nethttpomithttp2 golang.org/x/net/http2 -- GitLab From e741e2fe0e51840b16bfc84d8daaba7670e7aac9 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 28 Oct 2021 15:00:33 -0400 Subject: [PATCH 1808/2500] cmd/go: consolidate fuzz-support checks We had been repeating conditions for specific platforms and architectures to gate fuzzing tests, but the more of those tests we add the more we will have to update if the set of supported platforms and archictures expands over time. We also ought to provide a friendlier error message when 'go test -fuzz' is used on non-supported platforms. This change adds predicates in cmd/internal/sys, which already contains similar predicates for related functionality (such as the race detector), and uses those predicates in 'go test' and TestScript. For #48495 Change-Id: If24c3997aeb4d201258e21e5b6cf4f7c08fbadd7 Reviewed-on: https://go-review.googlesource.com/c/go/+/359481 Trust: Bryan C. Mills Trust: Katie Hockman Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/cmd/go/go_test.go | 12 ++++++---- src/cmd/go/internal/test/test.go | 12 +++++++--- src/cmd/go/internal/work/init.go | 15 +----------- src/cmd/go/script_test.go | 4 ++++ src/cmd/go/testdata/script/README | 2 ++ src/cmd/go/testdata/script/test_fuzz.txt | 5 ++-- .../go/testdata/script/test_fuzz_cache.txt | 7 +----- .../go/testdata/script/test_fuzz_chatty.txt | 4 +--- .../go/testdata/script/test_fuzz_cleanup.txt | 3 +-- .../go/testdata/script/test_fuzz_deadline.txt | 4 +--- .../go/testdata/script/test_fuzz_fuzztime.txt | 4 +--- .../go/testdata/script/test_fuzz_io_error.txt | 2 +- .../go/testdata/script/test_fuzz_match.txt | 3 +-- .../go/testdata/script/test_fuzz_minimize.txt | 4 +--- .../script/test_fuzz_minimize_interesting.txt | 6 +---- .../go/testdata/script/test_fuzz_multiple.txt | 4 +--- .../script/test_fuzz_mutate_crash.txt | 3 +-- .../testdata/script/test_fuzz_mutate_fail.txt | 3 +-- .../go/testdata/script/test_fuzz_mutator.txt | 3 +-- .../script/test_fuzz_non_crash_signal.txt | 4 ++-- .../go/testdata/script/test_fuzz_parallel.txt | 4 +--- src/cmd/go/testdata/script/test_fuzz_run.txt | 6 ++--- .../testdata/script/test_fuzz_seed_corpus.txt | 10 ++------ .../go/testdata/script/test_fuzz_setenv.txt | 2 +- .../testdata/script/test_fuzz_unsupported.txt | 18 +++++++++++++++ src/cmd/internal/sys/supported.go | 23 +++++++++++++++++++ src/internal/fuzz/counters_unsupported.go | 6 +++++ src/internal/fuzz/sys_unimplemented.go | 3 ++- 28 files changed, 96 insertions(+), 80 deletions(-) create mode 100644 src/cmd/go/testdata/script/test_fuzz_unsupported.txt diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index 339014e94e..c13d77a1af 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -43,10 +43,12 @@ func init() { } var ( - canRace = false // whether we can run the race detector - canCgo = false // whether we can use cgo - canMSan = false // whether we can run the memory sanitizer - canASan = false // whether we can run the address sanitizer + canRace = false // whether we can run the race detector + canCgo = false // whether we can use cgo + canMSan = false // whether we can run the memory sanitizer + canASan = false // whether we can run the address sanitizer + canFuzz = false // whether we can search for new fuzz failures + fuzzInstrumented = false // whether fuzzing uses instrumentation ) var exeSuffix string = func() string { @@ -206,6 +208,8 @@ func TestMain(m *testing.M) { if isAlpineLinux() || runtime.Compiler == "gccgo" { canRace = false } + canFuzz = sys.FuzzSupported(runtime.GOOS, runtime.GOARCH) + fuzzInstrumented = sys.FuzzInstrumented(runtime.GOOS, runtime.GOARCH) } // Don't let these environment variables confuse the test. os.Setenv("GOENV", "off") diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index ea1d4ff20e..0806d29f21 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -31,9 +31,10 @@ import ( "cmd/go/internal/lockedfile" "cmd/go/internal/modload" "cmd/go/internal/search" + "cmd/go/internal/str" "cmd/go/internal/trace" "cmd/go/internal/work" - "cmd/go/internal/str" + "cmd/internal/sys" "cmd/internal/test2json" ) @@ -651,8 +652,13 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { if testO != "" && len(pkgs) != 1 { base.Fatalf("cannot use -o flag with multiple packages") } - if testFuzz != "" && len(pkgs) != 1 { - base.Fatalf("cannot use -fuzz flag with multiple packages") + if testFuzz != "" { + if !sys.FuzzSupported(cfg.Goos, cfg.Goarch) { + base.Fatalf("-fuzz flag is not supported on %s/%s", cfg.Goos, cfg.Goarch) + } + if len(pkgs) != 1 { + base.Fatalf("cannot use -fuzz flag with multiple packages") + } } if testProfile() != "" && len(pkgs) != 1 { base.Fatalf("cannot use %s flag with multiple packages", testProfile()) diff --git a/src/cmd/go/internal/work/init.go b/src/cmd/go/internal/work/init.go index b2ee00d53c..9111150233 100644 --- a/src/cmd/go/internal/work/init.go +++ b/src/cmd/go/internal/work/init.go @@ -67,20 +67,7 @@ func BuildInit() { // instrumentation is added. 'go test -fuzz' still works without coverage, // but it generates random inputs without guidance, so it's much less effective. func fuzzInstrumentFlags() []string { - // TODO: expand the set of supported platforms, with testing. Nothing about - // the instrumentation is OS specific, but only amd64 and arm64 are - // supported in the runtime. See src/runtime/libfuzzer*. - // - // Keep in sync with build constraints in - // internal/fuzz/counters_{un,}supported.go - switch cfg.Goos { - case "darwin", "freebsd", "linux", "windows": - default: - return nil - } - switch cfg.Goarch { - case "amd64", "arm64": - default: + if !sys.FuzzInstrumented(cfg.Goos, cfg.Goarch) { return nil } return []string{"-d=libfuzzer"} diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go index acb1f91b44..98c1b68ed9 100644 --- a/src/cmd/go/script_test.go +++ b/src/cmd/go/script_test.go @@ -357,6 +357,10 @@ Script: ok = canASan case "race": ok = canRace + case "fuzz": + ok = canFuzz + case "fuzz-instrumented": + ok = fuzzInstrumented case "net": ok = testenv.HasExternalNetwork() case "link": diff --git a/src/cmd/go/testdata/script/README b/src/cmd/go/testdata/script/README index 2b88e880c9..2b55fa8977 100644 --- a/src/cmd/go/testdata/script/README +++ b/src/cmd/go/testdata/script/README @@ -80,6 +80,8 @@ should only run when the condition is satisfied. The available conditions are: - Test environment details: - [short] for testing.Short() - [cgo], [msan], [asan], [race] for whether cgo, msan, asan, and the race detector can be used + - [fuzz] for whether 'go test -fuzz' can be used at all + - [fuzz-instrumented] for whether 'go test -fuzz' uses coverage-instrumented binaries - [net] for whether the external network can be used - [link] for testenv.HasLink() - [root] for os.Geteuid() == 0 diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt index 4665202bf0..020012d73e 100644 --- a/src/cmd/go/testdata/script/test_fuzz.txt +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -1,5 +1,4 @@ -# TODO(jayconrod): support shared memory on more platforms. -[!darwin] [!linux] [!windows] skip +[!fuzz] skip # Test that running a fuzz target that returns without failing or calling # f.Fuzz fails and causes a non-zero exit status. @@ -495,4 +494,4 @@ go test fuzz v1 []byte("12345") -- corpustesting/testdata/fuzz/FuzzWrongType/1 -- go test fuzz v1 -int("00000") \ No newline at end of file +int("00000") diff --git a/src/cmd/go/testdata/script/test_fuzz_cache.txt b/src/cmd/go/testdata/script/test_fuzz_cache.txt index fc1c9a1752..552966b06b 100644 --- a/src/cmd/go/testdata/script/test_fuzz_cache.txt +++ b/src/cmd/go/testdata/script/test_fuzz_cache.txt @@ -1,9 +1,4 @@ -# TODO(jayconrod): support shared memory on more platforms. -[!darwin] [!linux] [!windows] skip - -# Instrumentation not supported on other archs. -# See #14565. -[!amd64] [!arm64] skip +[!fuzz-instrumented] skip [short] skip env GOCACHE=$WORK/cache diff --git a/src/cmd/go/testdata/script/test_fuzz_chatty.txt b/src/cmd/go/testdata/script/test_fuzz_chatty.txt index 9ebd480c90..1abcbbd389 100644 --- a/src/cmd/go/testdata/script/test_fuzz_chatty.txt +++ b/src/cmd/go/testdata/script/test_fuzz_chatty.txt @@ -1,6 +1,4 @@ -# TODO(jayconrod): support shared memory on more platforms. -[!darwin] [!linux] [!windows] skip - +[!fuzz] skip [short] skip # Run chatty fuzz targets with an error. diff --git a/src/cmd/go/testdata/script/test_fuzz_cleanup.txt b/src/cmd/go/testdata/script/test_fuzz_cleanup.txt index 88625916ba..b65022bd74 100644 --- a/src/cmd/go/testdata/script/test_fuzz_cleanup.txt +++ b/src/cmd/go/testdata/script/test_fuzz_cleanup.txt @@ -1,5 +1,4 @@ -# TODO(jayconrod): support shared memory on more platforms. -[!darwin] [!linux] [!windows] skip +[!fuzz] skip [short] skip # Cleanup should run after F.Skip. diff --git a/src/cmd/go/testdata/script/test_fuzz_deadline.txt b/src/cmd/go/testdata/script/test_fuzz_deadline.txt index 12f1054f61..5ba76a3d4f 100644 --- a/src/cmd/go/testdata/script/test_fuzz_deadline.txt +++ b/src/cmd/go/testdata/script/test_fuzz_deadline.txt @@ -1,6 +1,4 @@ -# TODO(jayconrod): support shared memory on more platforms. -[!darwin] [!linux] [!windows] skip - +[!fuzz] skip [short] skip # The fuzz function should be able to detect whether -timeout diff --git a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt index c3933bc7e2..56d94a4bcf 100644 --- a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt +++ b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt @@ -1,6 +1,4 @@ -# TODO(jayconrod): support shared memory on more platforms. -[!darwin] [!linux] [!windows] skip - +[!fuzz] skip [short] skip # There are no seed values, so 'go test' should finish quickly. diff --git a/src/cmd/go/testdata/script/test_fuzz_io_error.txt b/src/cmd/go/testdata/script/test_fuzz_io_error.txt index 4c7ab4c152..1a0aa6427e 100644 --- a/src/cmd/go/testdata/script/test_fuzz_io_error.txt +++ b/src/cmd/go/testdata/script/test_fuzz_io_error.txt @@ -6,7 +6,7 @@ # This is unlikely, but possible. It's difficult to simulate interruptions # due to ^C and EOF errors which are more common. We don't report those. [short] skip -[!darwin] [!linux] [!windows] skip +[!fuzz] skip # If the I/O error occurs before F.Fuzz is called, the coordinator should # stop the worker and say that. diff --git a/src/cmd/go/testdata/script/test_fuzz_match.txt b/src/cmd/go/testdata/script/test_fuzz_match.txt index 3a2ca631ad..0c0085f2c2 100644 --- a/src/cmd/go/testdata/script/test_fuzz_match.txt +++ b/src/cmd/go/testdata/script/test_fuzz_match.txt @@ -1,5 +1,4 @@ -# TODO(jayconrod): support shared memory on more platforms. -[!darwin] [!linux] [!windows] skip +[!fuzz] skip # Matches only fuzz targets to test. go test standalone_fuzz_test.go diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize.txt b/src/cmd/go/testdata/script/test_fuzz_minimize.txt index 3293e878bb..462fb9a963 100644 --- a/src/cmd/go/testdata/script/test_fuzz_minimize.txt +++ b/src/cmd/go/testdata/script/test_fuzz_minimize.txt @@ -1,6 +1,4 @@ -# TODO(jayconrod): support shared memory on more platforms. -[!darwin] [!linux] [!windows] skip - +[!fuzz] skip [short] skip # We clean the fuzz cache during this test. Don't clean the user's cache. diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt b/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt index 8ea4cdb8a5..e017a4cad3 100644 --- a/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt +++ b/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt @@ -1,8 +1,4 @@ -# TODO(jayconrod): support shared memory on more platforms. -[!darwin] [!linux] [!windows] skip - -# Instrumentation only supported on 64-bit architectures. -[!amd64] [!arm64] skip +[!fuzz-instrumented] skip # Test that when an interesting value is discovered (one that expands coverage), # the fuzzing engine minimizes it before writing it to the cache. diff --git a/src/cmd/go/testdata/script/test_fuzz_multiple.txt b/src/cmd/go/testdata/script/test_fuzz_multiple.txt index 6a7732f514..d96b2b6206 100644 --- a/src/cmd/go/testdata/script/test_fuzz_multiple.txt +++ b/src/cmd/go/testdata/script/test_fuzz_multiple.txt @@ -2,9 +2,7 @@ # enabled, and multiple package or multiple fuzz targets match. # TODO(#46312): support fuzzing multiple targets in multiple packages. -# TODO(jayconrod): support shared memory on more platforms. -[!darwin] [!linux] [!windows] skip - +[!fuzz] skip [short] skip # With fuzzing disabled, multiple targets can be tested. diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt index 628e003f41..4c4fa8e651 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt @@ -1,5 +1,4 @@ -# TODO(jayconrod): support shared memory on more platforms. -[!darwin] [!linux] [!windows] skip +[!fuzz] skip # Tests that a crash caused by a mutator-discovered input writes the bad input # to testdata, and fails+reports correctly. This tests the end-to-end behavior diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate_fail.txt b/src/cmd/go/testdata/script/test_fuzz_mutate_fail.txt index 935c22a05e..b5eab17349 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutate_fail.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutate_fail.txt @@ -1,5 +1,4 @@ -# TODO(jayconrod): support shared memory on more platforms. -[!darwin] [!linux] [!windows] skip +[!fuzz] skip # Check that if a worker does not call F.Fuzz or calls F.Fail first, # 'go test' exits non-zero and no crasher is recorded. diff --git a/src/cmd/go/testdata/script/test_fuzz_mutator.txt b/src/cmd/go/testdata/script/test_fuzz_mutator.txt index 9d0738e169..76b86488ad 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutator.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutator.txt @@ -1,5 +1,4 @@ -# TODO(jayconrod): support shared memory on more platforms. -[!darwin] [!linux] [!windows] skip +[!fuzz] skip # Test basic fuzzing mutator behavior. # diff --git a/src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt b/src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt index 1568757de7..f1a4c6669f 100644 --- a/src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt +++ b/src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt @@ -1,7 +1,7 @@ # NOTE: this test is skipped on Windows, since there's no concept of signals. # When a process terminates another process, it provides an exit code. -# TODO(jayconrod): support shared memory on more platforms. -[!darwin] [!freebsd] [!linux] skip +[windows] skip +[!fuzz] skip [short] skip # FuzzNonCrash sends itself a signal that does not appear to be a crash. diff --git a/src/cmd/go/testdata/script/test_fuzz_parallel.txt b/src/cmd/go/testdata/script/test_fuzz_parallel.txt index a49f30a27f..1795e0b2a5 100644 --- a/src/cmd/go/testdata/script/test_fuzz_parallel.txt +++ b/src/cmd/go/testdata/script/test_fuzz_parallel.txt @@ -1,6 +1,4 @@ -# TODO(jayconrod): support shared memory on more platforms. -[!darwin] [!linux] [!windows] skip - +[!fuzz] skip [short] skip # When running seed inputs, T.Parallel should let multiple inputs run in diff --git a/src/cmd/go/testdata/script/test_fuzz_run.txt b/src/cmd/go/testdata/script/test_fuzz_run.txt index e546d997cb..99a4413d32 100644 --- a/src/cmd/go/testdata/script/test_fuzz_run.txt +++ b/src/cmd/go/testdata/script/test_fuzz_run.txt @@ -1,6 +1,4 @@ -# TODO(jayconrod): support shared memory on more platforms. -[!darwin] [!linux] [!windows] skip - +[!fuzz] skip [short] skip env GOCACHE=$WORK/cache @@ -142,4 +140,4 @@ go test fuzz v1 string("fails") -- testdata/fuzz/FuzzFoo/thispasses -- go test fuzz v1 -string("passes") \ No newline at end of file +string("passes") diff --git a/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt b/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt index 18f634a3b6..4be9a6e385 100644 --- a/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt +++ b/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt @@ -1,10 +1,4 @@ -# TODO(jayconrod): support shared memory on more platforms. -[!darwin] [!linux] [!windows] skip - -# Instrumentation not supported on other archs. -# See #14565. -[!amd64] [!arm64] skip - +[!fuzz-instrumented] skip [short] skip env GOCACHE=$WORK/cache @@ -206,4 +200,4 @@ go test fuzz v1 int(10) -- cache-file-bytes -- go test fuzz v1 -[]byte("11111111111111111111") \ No newline at end of file +[]byte("11111111111111111111") diff --git a/src/cmd/go/testdata/script/test_fuzz_setenv.txt b/src/cmd/go/testdata/script/test_fuzz_setenv.txt index 9738697a91..2924569de1 100644 --- a/src/cmd/go/testdata/script/test_fuzz_setenv.txt +++ b/src/cmd/go/testdata/script/test_fuzz_setenv.txt @@ -1,5 +1,5 @@ +[!fuzz] skip [short] skip -[!darwin] [!linux] [!windows] skip go test -fuzz=FuzzA -fuzztime=100x fuzz_setenv_test.go diff --git a/src/cmd/go/testdata/script/test_fuzz_unsupported.txt b/src/cmd/go/testdata/script/test_fuzz_unsupported.txt new file mode 100644 index 0000000000..1ed0b8a6f7 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_unsupported.txt @@ -0,0 +1,18 @@ +[fuzz] skip + +! go test -fuzz=. -fuzztime=1x +! stdout . +stderr '^-fuzz flag is not supported on '$GOOS'/'$GOARCH'$' + +-- go.mod -- +module example + +go 1.18 +-- fuzz_test.go -- +package example + +import "testing" + +func FuzzTrivial(f *testing.F) { + f.Fuzz(func(t *testing.T, _ []byte) {}) +} diff --git a/src/cmd/internal/sys/supported.go b/src/cmd/internal/sys/supported.go index 473e390587..18ca50f927 100644 --- a/src/cmd/internal/sys/supported.go +++ b/src/cmd/internal/sys/supported.go @@ -45,6 +45,29 @@ func ASanSupported(goos, goarch string) bool { } } +// FuzzSupported reports whether goos/goarch supports fuzzing +// ('go test -fuzz=.'). +func FuzzSupported(goos, goarch string) bool { + switch goos { + case "darwin", "linux", "windows": + return true + default: + return false + } +} + +// FuzzInstrumented reports whether fuzzing on goos/goarch uses coverage +// instrumentation. (FuzzInstrumented implies FuzzSupported.) +func FuzzInstrumented(goos, goarch string) bool { + switch goarch { + case "amd64", "arm64": + // TODO(#14565): support more architectures. + return FuzzSupported(goos, goarch) + default: + return false + } +} + // MustLinkExternal reports whether goos/goarch requires external linking. // (This is the opposite of internal/testenv.CanInternalLink. Keep them in sync.) func MustLinkExternal(goos, goarch string) bool { diff --git a/src/internal/fuzz/counters_unsupported.go b/src/internal/fuzz/counters_unsupported.go index 9595cb93f7..bf28157068 100644 --- a/src/internal/fuzz/counters_unsupported.go +++ b/src/internal/fuzz/counters_unsupported.go @@ -2,6 +2,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// TODO: expand the set of supported platforms, with testing. Nothing about +// the instrumentation is OS specific, but only amd64 and arm64 are +// supported in the runtime. See src/runtime/libfuzzer*. +// +// If you update this constraint, also update cmd/internal/sys.FuzzInstrumeted. +// //go:build !((darwin || linux || windows || freebsd) && (amd64 || arm64)) package fuzz diff --git a/src/internal/fuzz/sys_unimplemented.go b/src/internal/fuzz/sys_unimplemented.go index 05954bb07f..123a32583c 100644 --- a/src/internal/fuzz/sys_unimplemented.go +++ b/src/internal/fuzz/sys_unimplemented.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// TODO(jayconrod): support more platforms. +// If you update this constraint, also update cmd/internal/sys.FuzzSupported. +// //go:build !darwin && !linux && !windows package fuzz -- GitLab From b9540246ba591e0ec5cd7cc1d6d62ab911ff9328 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Wed, 27 Oct 2021 16:31:18 -0400 Subject: [PATCH 1809/2500] cmd/go: disallow the -fuzz flag for tests outside the main module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Normally, when fuzzing identifies a failure it saves the failing input to the package's testdata directory. However, the testdata directory for packages outside the main module is normally not writable — and when it is, writing to a testdata directory inside the module cache would corrupt the checksum for that module (and permanently alter the behavior of that version of the module globally). In the future we could consider a flag to allow failures to be saved to an alternate location, or perhaps in the build cache; or, we could suppress writes entirely and rely on the user to identify and copy the failing input from the test log. However, it's a bit late in the cycle for that big a design decision right now. For Go 1.18, we will just enforce that the package to be fuzzed resides in the main module, which is typically a writable VCS checkout. Fixes #48495 Change-Id: I8d3d56372394b1aaa94fa920399c659363fa17fa Reviewed-on: https://go-review.googlesource.com/c/go/+/359414 Trust: Bryan C. Mills Trust: Katie Hockman Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/cmd/go/alldocs.go | 11 ++-- src/cmd/go/internal/test/test.go | 45 ++++++++++++-- .../mod/example.com_fuzzfail_v0.1.0.txt | 20 +++++++ .../mod/example.com_fuzzfail_v0.2.0.txt | 23 ++++++++ .../go/testdata/script/test_fuzz_modcache.txt | 58 +++++++++++++++++++ 5 files changed, 147 insertions(+), 10 deletions(-) create mode 100644 src/cmd/go/testdata/mod/example.com_fuzzfail_v0.1.0.txt create mode 100644 src/cmd/go/testdata/mod/example.com_fuzzfail_v0.2.0.txt create mode 100644 src/cmd/go/testdata/script/test_fuzz_modcache.txt diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 537f800944..1b9b22a812 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -2785,11 +2785,12 @@ // // -fuzz regexp // Run the fuzz target matching the regular expression. When specified, -// the command line argument must match exactly one package, and regexp -// must match exactly one fuzz target within that package. After tests, -// benchmarks, seed corpora of other fuzz targets, and examples have -// completed, the matching target will be fuzzed. See the Fuzzing section -// of the testing package documentation for details. +// the command line argument must match exactly one package within the +// main module, and regexp must match exactly one fuzz target within +// that package. After tests, benchmarks, seed corpora of other fuzz +// targets, and examples have completed, the matching target will be +// fuzzed. See the Fuzzing section of the testing package documentation +// for details. // // -fuzztime t // Run enough iterations of the fuzz test to take t, specified as a diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 0806d29f21..c435cc3fb2 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -36,6 +36,8 @@ import ( "cmd/go/internal/work" "cmd/internal/sys" "cmd/internal/test2json" + + "golang.org/x/mod/module" ) // Break init loop. @@ -248,11 +250,12 @@ control the execution of any test: -fuzz regexp Run the fuzz target matching the regular expression. When specified, - the command line argument must match exactly one package, and regexp - must match exactly one fuzz target within that package. After tests, - benchmarks, seed corpora of other fuzz targets, and examples have - completed, the matching target will be fuzzed. See the Fuzzing section - of the testing package documentation for details. + the command line argument must match exactly one package within the + main module, and regexp must match exactly one fuzz target within + that package. After tests, benchmarks, seed corpora of other fuzz + targets, and examples have completed, the matching target will be + fuzzed. See the Fuzzing section of the testing package documentation + for details. -fuzztime t Run enough iterations of the fuzz test to take t, specified as a @@ -659,6 +662,38 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { if len(pkgs) != 1 { base.Fatalf("cannot use -fuzz flag with multiple packages") } + + // Reject the '-fuzz' flag if the package is outside the main module. + // Otherwise, if fuzzing identifies a failure it could corrupt checksums in + // the module cache (or permanently alter the behavior of std tests for all + // users) by writing the failing input to the package's testdata directory. + // (See https://golang.org/issue/48495 and test_fuzz_modcache.txt.) + mainMods := modload.MainModules + if m := pkgs[0].Module; m != nil && m.Path != "" { + if !mainMods.Contains(m.Path) { + base.Fatalf("cannot use -fuzz flag on package outside the main module") + } + } else if pkgs[0].Standard && modload.Enabled() { + // Because packages in 'std' and 'cmd' are part of the standard library, + // they are only treated as part of a module in 'go mod' subcommands and + // 'go get'. However, we still don't want to accidentally corrupt their + // testdata during fuzzing, nor do we want to fail with surprising errors + // if GOROOT isn't writable (as is often the case for Go toolchains + // installed through package managers). + // + // If the user is requesting to fuzz a standard-library package, ensure + // that they are in the same module as that package (just like when + // fuzzing any other package). + if strings.HasPrefix(pkgs[0].ImportPath, "cmd/") { + if !mainMods.Contains("cmd") || !mainMods.InGorootSrc(module.Version{Path: "cmd"}) { + base.Fatalf("cannot use -fuzz flag on package outside the main module") + } + } else { + if !mainMods.Contains("std") || !mainMods.InGorootSrc(module.Version{Path: "std"}) { + base.Fatalf("cannot use -fuzz flag on package outside the main module") + } + } + } } if testProfile() != "" && len(pkgs) != 1 { base.Fatalf("cannot use %s flag with multiple packages", testProfile()) diff --git a/src/cmd/go/testdata/mod/example.com_fuzzfail_v0.1.0.txt b/src/cmd/go/testdata/mod/example.com_fuzzfail_v0.1.0.txt new file mode 100644 index 0000000000..af005ffb41 --- /dev/null +++ b/src/cmd/go/testdata/mod/example.com_fuzzfail_v0.1.0.txt @@ -0,0 +1,20 @@ +-- .mod -- +module example.com/fuzzfail + +go 1.18 +-- .info -- +{"Version":"v0.1.0"} +-- go.mod -- +module example.com/fuzzfail + +go 1.18 +-- fuzzfail_test.go -- +package fuzzfail + +import "testing" + +func FuzzFail(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + t.Fatalf("oops: %q", b) + }) +} diff --git a/src/cmd/go/testdata/mod/example.com_fuzzfail_v0.2.0.txt b/src/cmd/go/testdata/mod/example.com_fuzzfail_v0.2.0.txt new file mode 100644 index 0000000000..ea599aa611 --- /dev/null +++ b/src/cmd/go/testdata/mod/example.com_fuzzfail_v0.2.0.txt @@ -0,0 +1,23 @@ +-- .mod -- +module example.com/fuzzfail + +go 1.18 +-- .info -- +{"Version":"v0.2.0"} +-- go.mod -- +module example.com/fuzzfail + +go 1.18 +-- fuzzfail_test.go -- +package fuzzfail + +import "testing" + +func FuzzFail(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + t.Fatalf("oops: %q", b) + }) +} +-- testdata/fuzz/FuzzFail/bbb0c2d22aa1a24617301566dc7486f8b625d38024603ba62757c1124013b49a -- +go test fuzz v1 +[]byte("\x05") diff --git a/src/cmd/go/testdata/script/test_fuzz_modcache.txt b/src/cmd/go/testdata/script/test_fuzz_modcache.txt new file mode 100644 index 0000000000..c0f18ea3c0 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_modcache.txt @@ -0,0 +1,58 @@ +# This test demonstrates the fuzz corpus behavior for packages outside of the main module. +# (See https://golang.org/issue/48495.) + +[short] skip + +# Set -modcacherw so that the test behaves the same regardless of whether the +# module cache is writable. (For example, on some platforms it can always be +# written if the user is running as root.) At one point, a failing fuzz test +# in a writable module cache would corrupt module checksums in the cache. +env GOFLAGS=-modcacherw + + +# When the upstream module has no test corpus, running 'go test' should succeed, +# but 'go test -fuzz=.' should error out before running the test. +# (It should NOT corrupt the module cache by writing out new fuzz inputs, +# even if the cache is writable.) + +go get -t example.com/fuzzfail@v0.1.0 +go test example.com/fuzzfail + +! go test -fuzz=. example.com/fuzzfail +! stdout . +stderr '^cannot use -fuzz flag on package outside the main module$' + +go mod verify + + +# If the module does include a test corpus, 'go test' (without '-fuzz') should +# load that corpus and run the fuzz tests against it, but 'go test -fuzz=.' +# should continue to be rejected. + +go get -t example.com/fuzzfail@v0.2.0 + +! go test example.com/fuzzfail +stdout '^\s*fuzzfail_test\.go:7: oops:' + +! go test -fuzz=. example.com/fuzzfail +! stdout . +stderr '^cannot use -fuzz flag on package outside the main module$' + +go mod verify + + +# Packages in 'std' cannot be fuzzed when the corresponding GOROOT module is not +# the main module — either the failures would not be recorded or the behavior of +# the 'std' tests would change globally. + +! go test -fuzz . encoding/json +stderr '^cannot use -fuzz flag on package outside the main module$' + +! go test -fuzz . cmd/buildid +stderr '^cannot use -fuzz flag on package outside the main module$' + + +-- go.mod -- +module example.com/m + +go 1.18 -- GitLab From d0751b1ad8d7a68586dc7567cee44e0ce323f26f Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 28 Oct 2021 15:57:45 -0400 Subject: [PATCH 1810/2500] cmd/go: test with SIGTERM in test_fuzz_non_crash_signal The test currently uses only SIGKILL (which cannot be trapped by the worker process) and SIGILL (which is handled by the Go runtime, and does pretty unambiguously indicate a crash). It is missing a third (and perhaps more likely) case: a signal like SIGTERM that is handled by the Go runtime and causes the test to terminate, but nonetheless does not indicate a crash. Change-Id: I0595a0917e977e8eb2c24ae8b706d734ce3b2f4f Reviewed-on: https://go-review.googlesource.com/c/go/+/359482 Trust: Bryan C. Mills Trust: Katie Hockman Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- .../script/test_fuzz_non_crash_signal.txt | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt b/src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt index f1a4c6669f..31d54bcb70 100644 --- a/src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt +++ b/src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt @@ -10,6 +10,15 @@ ! exists testdata ! stdout unreachable ! stderr unreachable +stdout 'fuzzing process terminated by unexpected signal; no crash will be recorded: signal: terminated' + +# FuzzKill sends itself a signal that cannot be caught by the worker process +# and does not appear to be a crash. +# We should not save a crasher. +! go test -fuzz=FuzzKill +! exists testdata +! stdout unreachable +! stderr unreachable stdout 'fuzzing process terminated by unexpected signal; no crash will be recorded: signal: killed' # FuzzCrash sends itself a signal that looks like a crash. @@ -33,6 +42,17 @@ import ( ) func FuzzNonCrash(f *testing.F) { + f.Fuzz(func(*testing.T, bool) { + pid := syscall.Getpid() + if err := syscall.Kill(pid, syscall.SIGTERM); err != nil { + panic(err) + } + // signal may not be received immediately. Wait for it. + select{} + }) +} + +func FuzzKill(f *testing.F) { f.Fuzz(func(*testing.T, bool) { pid := syscall.Getpid() if err := syscall.Kill(pid, syscall.SIGKILL); err != nil { -- GitLab From af05d8be3d9dd566b2ce3ff5344258314f128ff6 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 28 Oct 2021 13:51:39 -0400 Subject: [PATCH 1811/2500] all: manual fixups for //go:build vs // +build Update many generators, also handle files that were not part of the standard build during 'go fix' in CL 344955. Fixes #41184. Change-Id: I1edc684e8101882dcd11f75c6745c266fccfe9e7 Reviewed-on: https://go-review.googlesource.com/c/go/+/359476 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Bryan C. Mills --- src/crypto/elliptic/gen_p256_table.go | 1 - src/internal/goarch/gengoarch.go | 3 +-- src/internal/goos/gengoos.go | 1 - src/internal/syscall/windows/exec_windows_test.go | 1 - src/internal/syscall/windows/mksyscall.go | 1 - src/internal/syscall/windows/registry/export_test.go | 1 - src/internal/syscall/windows/registry/key.go | 1 - src/internal/syscall/windows/registry/mksyscall.go | 1 - src/internal/syscall/windows/registry/registry_test.go | 1 - src/internal/syscall/windows/registry/syscall.go | 1 - src/internal/syscall/windows/registry/value.go | 1 - src/internal/syscall/windows/sysdll/sysdll.go | 1 - src/runtime/asan/asan.go | 3 --- src/runtime/mkduff.go | 2 -- src/runtime/mkpreempt.go | 1 - src/runtime/msan/msan.go | 3 --- src/runtime/wincallback.go | 1 - src/syscall/js/export_test.go | 1 - src/syscall/js/func.go | 1 - src/syscall/js/js.go | 1 - src/syscall/js/js_test.go | 1 - 21 files changed, 1 insertion(+), 27 deletions(-) diff --git a/src/crypto/elliptic/gen_p256_table.go b/src/crypto/elliptic/gen_p256_table.go index 54aafa2c38..367bd4b67d 100644 --- a/src/crypto/elliptic/gen_p256_table.go +++ b/src/crypto/elliptic/gen_p256_table.go @@ -26,7 +26,6 @@ func main() { // Generated by gen_p256_table.go. DO NOT EDIT. //go:build amd64 || arm64 -// +build amd64 arm64 package elliptic diff --git a/src/internal/goarch/gengoarch.go b/src/internal/goarch/gengoarch.go index d146cc5bc9..3c706e04ad 100644 --- a/src/internal/goarch/gengoarch.go +++ b/src/internal/goarch/gengoarch.go @@ -39,8 +39,7 @@ func main() { } var buf bytes.Buffer fmt.Fprintf(&buf, "// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.\n\n") - fmt.Fprintf(&buf, "//go:build %s\n", target) - fmt.Fprintf(&buf, "// +build %s\n\n", target) // must explicitly include target for bootstrapping purposes + fmt.Fprintf(&buf, "//go:build %s\n", target) // must explicitly include target for bootstrapping purposes fmt.Fprintf(&buf, "package goarch\n\n") fmt.Fprintf(&buf, "const GOARCH = `%s`\n\n", target) for _, goarch := range goarches { diff --git a/src/internal/goos/gengoos.go b/src/internal/goos/gengoos.go index f8ddfcc7ff..1b62503fd0 100644 --- a/src/internal/goos/gengoos.go +++ b/src/internal/goos/gengoos.go @@ -51,7 +51,6 @@ func main() { var buf bytes.Buffer fmt.Fprintf(&buf, "// Code generated by gengoos.go using 'go generate'. DO NOT EDIT.\n\n") fmt.Fprintf(&buf, "//go:build %s\n", strings.Join(tags, " && ")) - fmt.Fprintf(&buf, "// +build %s\n\n", strings.Join(tags, ",")) fmt.Fprintf(&buf, "package goos\n\n") fmt.Fprintf(&buf, "const GOOS = `%s`\n\n", target) for _, goos := range gooses { diff --git a/src/internal/syscall/windows/exec_windows_test.go b/src/internal/syscall/windows/exec_windows_test.go index 0db626636e..3311da5474 100644 --- a/src/internal/syscall/windows/exec_windows_test.go +++ b/src/internal/syscall/windows/exec_windows_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows -// +build windows package windows_test diff --git a/src/internal/syscall/windows/mksyscall.go b/src/internal/syscall/windows/mksyscall.go index 39f745db7a..81f08c627e 100644 --- a/src/internal/syscall/windows/mksyscall.go +++ b/src/internal/syscall/windows/mksyscall.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build generate -// +build generate package windows diff --git a/src/internal/syscall/windows/registry/export_test.go b/src/internal/syscall/windows/registry/export_test.go index d02d93f287..7f1ac70e8f 100644 --- a/src/internal/syscall/windows/registry/export_test.go +++ b/src/internal/syscall/windows/registry/export_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows -// +build windows package registry diff --git a/src/internal/syscall/windows/registry/key.go b/src/internal/syscall/windows/registry/key.go index ebe73a2e02..ba5c292c5e 100644 --- a/src/internal/syscall/windows/registry/key.go +++ b/src/internal/syscall/windows/registry/key.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows -// +build windows // Package registry provides access to the Windows registry. // diff --git a/src/internal/syscall/windows/registry/mksyscall.go b/src/internal/syscall/windows/registry/mksyscall.go index 0a007df7cc..0e0b4210d5 100644 --- a/src/internal/syscall/windows/registry/mksyscall.go +++ b/src/internal/syscall/windows/registry/mksyscall.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build generate -// +build generate package registry diff --git a/src/internal/syscall/windows/registry/registry_test.go b/src/internal/syscall/windows/registry/registry_test.go index 69b84e1c4c..134b5450fc 100644 --- a/src/internal/syscall/windows/registry/registry_test.go +++ b/src/internal/syscall/windows/registry/registry_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows -// +build windows package registry_test diff --git a/src/internal/syscall/windows/registry/syscall.go b/src/internal/syscall/windows/registry/syscall.go index bb61279361..cb315adade 100644 --- a/src/internal/syscall/windows/registry/syscall.go +++ b/src/internal/syscall/windows/registry/syscall.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows -// +build windows package registry diff --git a/src/internal/syscall/windows/registry/value.go b/src/internal/syscall/windows/registry/value.go index e1fc99c40d..025574015f 100644 --- a/src/internal/syscall/windows/registry/value.go +++ b/src/internal/syscall/windows/registry/value.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows -// +build windows package registry diff --git a/src/internal/syscall/windows/sysdll/sysdll.go b/src/internal/syscall/windows/sysdll/sysdll.go index 61b998e4cf..e79fd19edc 100644 --- a/src/internal/syscall/windows/sysdll/sysdll.go +++ b/src/internal/syscall/windows/sysdll/sysdll.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows -// +build windows // Package sysdll is an internal leaf package that records and reports // which Windows DLL names are used by Go itself. These DLLs are then diff --git a/src/runtime/asan/asan.go b/src/runtime/asan/asan.go index 40ebf96824..ac71466b71 100644 --- a/src/runtime/asan/asan.go +++ b/src/runtime/asan/asan.go @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build asan && linux && (arm64 || amd64) -// +build asan -// +build linux -// +build arm64 amd64 package asan diff --git a/src/runtime/mkduff.go b/src/runtime/mkduff.go index d05158975f..e8a85702c6 100644 --- a/src/runtime/mkduff.go +++ b/src/runtime/mkduff.go @@ -179,7 +179,6 @@ func copyARM64(w io.Writer) { func tagsPPC64x(w io.Writer) { fmt.Fprintln(w) fmt.Fprintln(w, "//go:build ppc64 || ppc64le") - fmt.Fprintln(w, "// +build ppc64 ppc64le") fmt.Fprintln(w) } @@ -207,7 +206,6 @@ func copyPPC64x(w io.Writer) { func tagsMIPS64x(w io.Writer) { fmt.Fprintln(w) fmt.Fprintln(w, "//go:build mips64 || mips64le") - fmt.Fprintln(w, "// +build mips64 mips64le") fmt.Fprintln(w) } diff --git a/src/runtime/mkpreempt.go b/src/runtime/mkpreempt.go index acfb518d10..d662e73813 100644 --- a/src/runtime/mkpreempt.go +++ b/src/runtime/mkpreempt.go @@ -123,7 +123,6 @@ func header(arch string) { if beLe[arch] { base := arch[:len(arch)-1] fmt.Fprintf(out, "//go:build %s || %sle\n", base, base) - fmt.Fprintf(out, "// +build %s %sle\n\n", base, base) } fmt.Fprintf(out, "#include \"go_asm.h\"\n") fmt.Fprintf(out, "#include \"textflag.h\"\n\n") diff --git a/src/runtime/msan/msan.go b/src/runtime/msan/msan.go index 9908a8ec22..f1bf4e1065 100644 --- a/src/runtime/msan/msan.go +++ b/src/runtime/msan/msan.go @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build msan && linux && (amd64 || arm64) -// +build msan -// +build linux -// +build amd64 arm64 package msan diff --git a/src/runtime/wincallback.go b/src/runtime/wincallback.go index ca9965979f..442a984708 100644 --- a/src/runtime/wincallback.go +++ b/src/runtime/wincallback.go @@ -22,7 +22,6 @@ func genasm386Amd64() { buf.WriteString(`// Code generated by wincallback.go using 'go generate'. DO NOT EDIT. //go:build 386 || amd64 -// +build 386 amd64 // runtime·callbackasm is called by external code to // execute Go implemented callback function. It is not diff --git a/src/syscall/js/export_test.go b/src/syscall/js/export_test.go index 4bd9c5d595..fb61daea7c 100644 --- a/src/syscall/js/export_test.go +++ b/src/syscall/js/export_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm package js diff --git a/src/syscall/js/func.go b/src/syscall/js/func.go index dde1e68100..77fb9e66ca 100644 --- a/src/syscall/js/func.go +++ b/src/syscall/js/func.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm package js diff --git a/src/syscall/js/js.go b/src/syscall/js/js.go index 0da0ddfa0f..d80d5d63de 100644 --- a/src/syscall/js/js.go +++ b/src/syscall/js/js.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm // Package js gives access to the WebAssembly host environment when using the js/wasm architecture. // Its API is based on JavaScript semantics. diff --git a/src/syscall/js/js_test.go b/src/syscall/js/js_test.go index 8088a897f6..fa8c782459 100644 --- a/src/syscall/js/js_test.go +++ b/src/syscall/js/js_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build js && wasm -// +build js,wasm // To run these tests: // -- GitLab From 33c392f72d16163eb0795b3d61b2196ac21e1799 Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Sun, 24 Oct 2021 14:11:07 +1100 Subject: [PATCH 1812/2500] reflect: add FieldByIndexErr This new function, although different in signature from other reflect functions, allows the caller to avoid the panic caused by nil embedded fields in calls to FieldByIndex. Fixes #48218 Change-Id: I447f135bb789148c27ae3f2f23dcf43094f4c1de Reviewed-on: https://go-review.googlesource.com/c/go/+/357962 Trust: Rob Pike Run-TryBot: Rob Pike TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/reflect/value.go | 27 ++++++++++++++++++++++++++- src/reflect/visiblefields_test.go | 19 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/reflect/value.go b/src/reflect/value.go index 618d38893e..90edf8e31d 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -5,6 +5,7 @@ package reflect import ( + "errors" "internal/abi" "internal/goarch" "internal/itoa" @@ -1232,7 +1233,8 @@ func (v Value) Field(i int) Value { } // FieldByIndex returns the nested field corresponding to index. -// It panics if v's Kind is not struct. +// It panics if evaluation requires stepping through a nil +// pointer or a field that is not a struct. func (v Value) FieldByIndex(index []int) Value { if len(index) == 1 { return v.Field(index[0]) @@ -1252,6 +1254,29 @@ func (v Value) FieldByIndex(index []int) Value { return v } +// FieldByIndexErr returns the nested field corresponding to index. +// It returns an error if evaluation requires stepping through a nil +// pointer, but panics if it must step through a field that +// is not a struct. +func (v Value) FieldByIndexErr(index []int) (Value, error) { + if len(index) == 1 { + return v.Field(index[0]), nil + } + v.mustBe(Struct) + for i, x := range index { + if i > 0 { + if v.Kind() == Ptr && v.typ.Elem().Kind() == Struct { + if v.IsNil() { + return Value{}, errors.New("reflect: indirection through nil pointer to embedded struct field " + v.typ.Elem().Name()) + } + v = v.Elem() + } + } + v = v.Field(x) + } + return v, nil +} + // FieldByName returns the struct field with the given name. // It returns the zero Value if no field was found. // It panics if v's Kind is not struct. diff --git a/src/reflect/visiblefields_test.go b/src/reflect/visiblefields_test.go index 915bbee867..5ae322321b 100644 --- a/src/reflect/visiblefields_test.go +++ b/src/reflect/visiblefields_test.go @@ -6,6 +6,7 @@ package reflect_test import ( . "reflect" + "strings" "testing" ) @@ -328,3 +329,21 @@ func TestFields(t *testing.T) { }) } } + +// Must not panic with nil embedded pointer. +func TestFieldByIndexErr(t *testing.T) { + type A struct { + S string + } + type B struct { + *A + } + v := ValueOf(B{}) + _, err := v.FieldByIndexErr([]int{0, 0}) + if err == nil { + t.Fatal("expected error") + } + if !strings.Contains(err.Error(), "embedded struct field A") { + t.Fatal(err) + } +} -- GitLab From d3d8852d8997a6429cbd498138908e537869a6ef Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Sun, 24 Oct 2021 15:44:15 +1100 Subject: [PATCH 1813/2500] text/template: use reflect.Value.FieldByIndexErr to avoid a crash on a nil pointer as an embedded field. Fixes #48215 Change-Id: I214faa6e3cf08cdec1c01035e4bbca0900c6a408 Reviewed-on: https://go-review.googlesource.com/c/go/+/357963 Trust: Rob Pike Run-TryBot: Rob Pike TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/text/template/exec.go | 5 ++++- src/text/template/exec_test.go | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/text/template/exec.go b/src/text/template/exec.go index 7e44497530..c42cbb2ad3 100644 --- a/src/text/template/exec.go +++ b/src/text/template/exec.go @@ -635,10 +635,13 @@ func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node, case reflect.Struct: tField, ok := receiver.Type().FieldByName(fieldName) if ok { - field := receiver.FieldByIndex(tField.Index) + field, err := receiver.FieldByIndexErr(tField.Index) if !tField.IsExported() { s.errorf("%s is an unexported field of struct type %s", fieldName, typ) } + if err != nil { + s.errorf("%v", err) + } // If it's a function, we must call it. if hasArgs { s.errorf("%s has arguments but cannot be invoked as function", fieldName) diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go index 9c0772945e..3c40aa901e 100644 --- a/src/text/template/exec_test.go +++ b/src/text/template/exec_test.go @@ -1787,3 +1787,26 @@ func TestIssue39807(t *testing.T) { wg.Wait() } + +// Issue 48215: embedded nil pointer causes panic. +// Fixed by adding FieldByIndexErr to the reflect package. +func TestIssue48215(t *testing.T) { + type A struct { + S string + } + type B struct { + *A + } + tmpl, err := New("").Parse(`{{ .S }}`) + if err != nil { + t.Fatal(err) + } + err = tmpl.Execute(io.Discard, B{}) + // We expect an error, not a panic. + if err == nil { + t.Fatal("did not get error for nil embedded struct") + } + if !strings.Contains(err.Error(), "reflect: indirection through nil pointer to embedded struct field A") { + t.Fatal(err) + } +} -- GitLab From 2c7cdec2a762108ae9231b7861c3689f4d23b58c Mon Sep 17 00:00:00 2001 From: Meng Zhuo Date: Thu, 28 Oct 2021 10:04:36 +0800 Subject: [PATCH 1814/2500] io: remove UTF8 specified document for RuneReader RuneReader is fine with UTF16 or any other character encoding Fixes #49178 Change-Id: I08a5ac205e095349d451d3b60411eaeebc3aa563 Reviewed-on: https://go-review.googlesource.com/c/go/+/359334 Trust: Meng Zhuo Reviewed-by: Meng Zhuo Reviewed-by: Ian Lance Taylor Reviewed-by: Rob Pike Run-TryBot: Meng Zhuo TryBot-Result: Go Bot --- src/io/io.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/io/io.go b/src/io/io.go index ceac7ba7f8..5635392dfb 100644 --- a/src/io/io.go +++ b/src/io/io.go @@ -279,7 +279,7 @@ type ByteWriter interface { // RuneReader is the interface that wraps the ReadRune method. // -// ReadRune reads a single UTF-8 encoded Unicode character +// ReadRune reads a single encoded Unicode character // and returns the rune and its size in bytes. If no character is // available, err will be set. type RuneReader interface { -- GitLab From f2885263748364a2a7f4e0d47abd5095699cd39f Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 28 Oct 2021 22:25:02 -0400 Subject: [PATCH 1815/2500] cmd/go: test that the reserved paths "example" and "test" are not used Proposal #37641 reserved the paths "example" and "test" for end users, so no path beginning with either of those elements may be added to the standard library. (We are unlikely to add them by accident, but this test codifies the policy accepted in the proposal.) Fixes #37641 Change-Id: I999064180336c923d4918a1176c371b8f5666f8b Reviewed-on: https://go-review.googlesource.com/c/go/+/359576 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Dmitri Shuralyov --- src/cmd/go/testdata/script/list_reserved.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/cmd/go/testdata/script/list_reserved.txt diff --git a/src/cmd/go/testdata/script/list_reserved.txt b/src/cmd/go/testdata/script/list_reserved.txt new file mode 100644 index 0000000000..b9c5361492 --- /dev/null +++ b/src/cmd/go/testdata/script/list_reserved.txt @@ -0,0 +1,7 @@ +# https://golang.org/issue/37641: the paths "example" and "test" are reserved +# for end users, and must never exist in the standard library. + +go list example/... test/... +stderr 'go: warning: "example/..." matched no packages$' +stderr 'go: warning: "test/..." matched no packages$' +! stdout . -- GitLab From 3aecb3a8f7e1435c76003a20068c0208fd73649a Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Thu, 8 Jul 2021 21:42:01 +0000 Subject: [PATCH 1816/2500] runtime: fix sweep termination condition Currently, there is a chance that the sweep termination condition could flap, causing e.g. runtime.GC to return before all sweep work has not only been drained, but also completed. CL 307915 and CL 307916 attempted to fix this problem, but it is still possible that mheap_.sweepDrained is marked before any outstanding sweepers are accounted for in mheap_.sweepers, leaving a window in which a thread could observe isSweepDone as true before it actually was (and after some time it would revert to false, then true again, depending on the number of outstanding sweepers at that point). This change fixes the sweep termination condition by merging mheap_.sweepers and mheap_.sweepDrained into a single atomic value. This value is updated such that a new potential sweeper will increment the oustanding sweeper count iff there are still outstanding spans to be swept without an outstanding sweeper to pick them up. This design simplifies the sweep termination condition into a single atomic load and comparison and ensures the condition never flaps. Updates #46500. Fixes #45315. Change-Id: I6d69aff156b8d48428c4cc8cfdbf28be346dbf04 Reviewed-on: https://go-review.googlesource.com/c/go/+/333389 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Austin Clements --- src/runtime/mcentral.go | 91 +++++++------- src/runtime/mgc.go | 12 +- src/runtime/mgcsweep.go | 214 ++++++++++++++++++++++---------- src/runtime/mheap.go | 11 +- src/runtime/pprof/mprof_test.go | 11 -- 5 files changed, 208 insertions(+), 131 deletions(-) diff --git a/src/runtime/mcentral.go b/src/runtime/mcentral.go index 6013c94c69..0a871a611e 100644 --- a/src/runtime/mcentral.go +++ b/src/runtime/mcentral.go @@ -102,59 +102,62 @@ func (c *mcentral) cacheSpan() *mspan { spanBudget := 100 var s *mspan - sl := newSweepLocker() - sg := sl.sweepGen + var sl sweepLocker // Try partial swept spans first. + sg := mheap_.sweepgen if s = c.partialSwept(sg).pop(); s != nil { goto havespan } - // Now try partial unswept spans. - for ; spanBudget >= 0; spanBudget-- { - s = c.partialUnswept(sg).pop() - if s == nil { - break - } - if s, ok := sl.tryAcquire(s); ok { - // We got ownership of the span, so let's sweep it and use it. - s.sweep(true) - sl.dispose() - goto havespan - } - // We failed to get ownership of the span, which means it's being or - // has been swept by an asynchronous sweeper that just couldn't remove it - // from the unswept list. That sweeper took ownership of the span and - // responsibility for either freeing it to the heap or putting it on the - // right swept list. Either way, we should just ignore it (and it's unsafe - // for us to do anything else). - } - // Now try full unswept spans, sweeping them and putting them into the - // right list if we fail to get a span. - for ; spanBudget >= 0; spanBudget-- { - s = c.fullUnswept(sg).pop() - if s == nil { - break - } - if s, ok := sl.tryAcquire(s); ok { - // We got ownership of the span, so let's sweep it. - s.sweep(true) - // Check if there's any free space. - freeIndex := s.nextFreeIndex() - if freeIndex != s.nelems { - s.freeindex = freeIndex - sl.dispose() + sl = sweep.active.begin() + if sl.valid { + // Now try partial unswept spans. + for ; spanBudget >= 0; spanBudget-- { + s = c.partialUnswept(sg).pop() + if s == nil { + break + } + if s, ok := sl.tryAcquire(s); ok { + // We got ownership of the span, so let's sweep it and use it. + s.sweep(true) + sweep.active.end(sl) goto havespan } - // Add it to the swept list, because sweeping didn't give us any free space. - c.fullSwept(sg).push(s.mspan) + // We failed to get ownership of the span, which means it's being or + // has been swept by an asynchronous sweeper that just couldn't remove it + // from the unswept list. That sweeper took ownership of the span and + // responsibility for either freeing it to the heap or putting it on the + // right swept list. Either way, we should just ignore it (and it's unsafe + // for us to do anything else). + } + // Now try full unswept spans, sweeping them and putting them into the + // right list if we fail to get a span. + for ; spanBudget >= 0; spanBudget-- { + s = c.fullUnswept(sg).pop() + if s == nil { + break + } + if s, ok := sl.tryAcquire(s); ok { + // We got ownership of the span, so let's sweep it. + s.sweep(true) + // Check if there's any free space. + freeIndex := s.nextFreeIndex() + if freeIndex != s.nelems { + s.freeindex = freeIndex + sweep.active.end(sl) + goto havespan + } + // Add it to the swept list, because sweeping didn't give us any free space. + c.fullSwept(sg).push(s.mspan) + } + // See comment for partial unswept spans. + } + sweep.active.end(sl) + if trace.enabled { + traceGCSweepDone() + traceDone = true } - // See comment for partial unswept spans. - } - sl.dispose() - if trace.enabled { - traceGCSweepDone() - traceDone = true } // We failed to get a span from the mcentral so get one from mheap. diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go index 429b907322..e7c023919c 100644 --- a/src/runtime/mgc.go +++ b/src/runtime/mgc.go @@ -154,7 +154,7 @@ func gcinit() { throw("size of Workbuf is suboptimal") } // No sweep on the first cycle. - mheap_.sweepDrained = 1 + sweep.active.state.Store(sweepDrainedMask) // Initialize GC pacer state. // Use the environment variable GOGC for the initial gcPercent value. @@ -1022,8 +1022,10 @@ func gcMarkTermination(nextTriggerRatio float64) { // Those aren't tracked in any sweep lists, so we need to // count them against sweep completion until we ensure all // those spans have been forced out. - sl := newSweepLocker() - sl.blockCompletion() + sl := sweep.active.begin() + if !sl.valid { + throw("failed to set sweep barrier") + } systemstack(func() { startTheWorldWithSema(true) }) @@ -1050,7 +1052,7 @@ func gcMarkTermination(nextTriggerRatio float64) { }) // Now that we've swept stale spans in mcaches, they don't // count against unswept spans. - sl.dispose() + sweep.active.end(sl) // Print gctrace before dropping worldsema. As soon as we drop // worldsema another cycle could start and smash the stats @@ -1457,7 +1459,7 @@ func gcSweep(mode gcMode) { lock(&mheap_.lock) mheap_.sweepgen += 2 - mheap_.sweepDrained = 0 + sweep.active.reset() mheap_.pagesSwept.Store(0) mheap_.sweepArenas = mheap_.allArenas mheap_.reclaimIndex.Store(0) diff --git a/src/runtime/mgcsweep.go b/src/runtime/mgcsweep.go index 9c7f9d340d..a431d8a2af 100644 --- a/src/runtime/mgcsweep.go +++ b/src/runtime/mgcsweep.go @@ -41,6 +41,10 @@ type sweepdata struct { nbgsweep uint32 npausesweep uint32 + // active tracks outstanding sweepers and the sweep + // termination condition. + active activeSweep + // centralIndex is the current unswept span class. // It represents an index into the mcentral span // sets. Accessed and updated via its load and @@ -116,6 +120,108 @@ func (h *mheap) nextSpanForSweep() *mspan { return nil } +const sweepDrainedMask = 1 << 31 + +// activeSweep is a type that captures whether sweeping +// is done, and whether there are any outstanding sweepers. +// +// Every potential sweeper must call begin() before they look +// for work, and end() after they've finished sweeping. +type activeSweep struct { + // state is divided into two parts. + // + // The top bit (masked by sweepDrainedMask) is a boolean + // value indicating whether all the sweep work has been + // drained from the queue. + // + // The rest of the bits are a counter, indicating the + // number of outstanding concurrent sweepers. + state atomic.Uint32 +} + +// begin registers a new sweeper. Returns a sweepLocker +// for acquiring spans for sweeping. Any outstanding sweeper blocks +// sweep termination. +// +// If the sweepLocker is invalid, the caller can be sure that all +// outstanding sweep work has been drained, so there is nothing left +// to sweep. Note that there may be sweepers currently running, so +// this does not indicate that all sweeping has completed. +// +// Even if the sweepLocker is invalid, its sweepGen is always valid. +func (a *activeSweep) begin() sweepLocker { + for { + state := a.state.Load() + if state&sweepDrainedMask != 0 { + return sweepLocker{mheap_.sweepgen, false} + } + if a.state.CompareAndSwap(state, state+1) { + return sweepLocker{mheap_.sweepgen, true} + } + } +} + +// end deregisters a sweeper. Must be called once for each time +// begin is called if the sweepLocker is valid. +func (a *activeSweep) end(sl sweepLocker) { + if sl.sweepGen != mheap_.sweepgen { + throw("sweeper left outstanding across sweep generations") + } + for { + state := a.state.Load() + if (state&^sweepDrainedMask)-1 >= sweepDrainedMask { + throw("mismatched begin/end of activeSweep") + } + if a.state.CompareAndSwap(state, state-1) { + if state != sweepDrainedMask { + return + } + if debug.gcpacertrace > 0 { + print("pacer: sweep done at heap size ", gcController.heapLive>>20, "MB; allocated ", (gcController.heapLive-mheap_.sweepHeapLiveBasis)>>20, "MB during sweep; swept ", mheap_.pagesSwept.Load(), " pages at ", mheap_.sweepPagesPerByte, " pages/byte\n") + } + return + } + } +} + +// markDrained marks the active sweep cycle as having drained +// all remaining work. This is safe to be called concurrently +// with all other methods of activeSweep, though may race. +// +// Returns true if this call was the one that actually performed +// the mark. +func (a *activeSweep) markDrained() bool { + for { + state := a.state.Load() + if state&sweepDrainedMask != 0 { + return false + } + if a.state.CompareAndSwap(state, state|sweepDrainedMask) { + return true + } + } +} + +// sweepers returns the current number of active sweepers. +func (a *activeSweep) sweepers() uint32 { + return a.state.Load() &^ sweepDrainedMask +} + +// isDone returns true if all sweep work has been drained and no more +// outstanding sweepers exist. That is, when the sweep phase is +// completely done. +func (a *activeSweep) isDone() bool { + return a.state.Load() == sweepDrainedMask +} + +// reset sets up the activeSweep for the next sweep cycle. +// +// The world must be stopped. +func (a *activeSweep) reset() { + assertWorldStopped() + a.state.Store(0) +} + // finishsweep_m ensures that all spans are swept. // // The world must be stopped. This ensures there are no sweeps in @@ -134,6 +240,15 @@ func finishsweep_m() { sweep.npausesweep++ } + // Make sure there aren't any outstanding sweepers left. + // At this point, with the world stopped, it means one of two + // things. Either we were able to preempt a sweeper, or that + // a sweeper didn't call sweep.active.end when it should have. + // Both cases indicate a bug, so throw. + if sweep.active.sweepers() != 0 { + throw("active sweepers found at start of mark phase") + } + // Reset all the unswept buffers, which should be empty. // Do this in sweep termination as opposed to mark termination // so that we can catch unswept spans and reclaim blocks as @@ -183,15 +298,11 @@ func bgsweep(c chan int) { } } -// sweepLocker acquires sweep ownership of spans and blocks sweep -// completion. +// sweepLocker acquires sweep ownership of spans. type sweepLocker struct { // sweepGen is the sweep generation of the heap. sweepGen uint32 - // blocking indicates that this tracker is blocking sweep - // completion, usually as a result of acquiring sweep - // ownership of at least one span. - blocking bool + valid bool } // sweepLocked represents sweep ownership of a span. @@ -199,22 +310,16 @@ type sweepLocked struct { *mspan } -func newSweepLocker() sweepLocker { - return sweepLocker{ - sweepGen: mheap_.sweepgen, - } -} - // tryAcquire attempts to acquire sweep ownership of span s. If it // successfully acquires ownership, it blocks sweep completion. func (l *sweepLocker) tryAcquire(s *mspan) (sweepLocked, bool) { + if !l.valid { + throw("use of invalid sweepLocker") + } // Check before attempting to CAS. if atomic.Load(&s.sweepgen) != l.sweepGen-2 { return sweepLocked{}, false } - // Add ourselves to sweepers before potentially taking - // ownership. - l.blockCompletion() // Attempt to acquire sweep ownership of s. if !atomic.Cas(&s.sweepgen, l.sweepGen-2, l.sweepGen-1) { return sweepLocked{}, false @@ -222,48 +327,22 @@ func (l *sweepLocker) tryAcquire(s *mspan) (sweepLocked, bool) { return sweepLocked{s}, true } -// blockCompletion blocks sweep completion without acquiring any -// specific spans. -func (l *sweepLocker) blockCompletion() { - if !l.blocking { - atomic.Xadd(&mheap_.sweepers, +1) - l.blocking = true - } -} - -func (l *sweepLocker) dispose() { - if !l.blocking { - return - } - // Decrement the number of active sweepers and if this is the - // last one, mark sweep as complete. - l.blocking = false - if atomic.Xadd(&mheap_.sweepers, -1) == 0 && atomic.Load(&mheap_.sweepDrained) != 0 { - l.sweepIsDone() - } -} - -func (l *sweepLocker) sweepIsDone() { - if debug.gcpacertrace > 0 { - print("pacer: sweep done at heap size ", gcController.heapLive>>20, "MB; allocated ", (gcController.heapLive-mheap_.sweepHeapLiveBasis)>>20, "MB during sweep; swept ", mheap_.pagesSwept.Load(), " pages at ", mheap_.sweepPagesPerByte, " pages/byte\n") - } -} - // sweepone sweeps some unswept heap span and returns the number of pages returned // to the heap, or ^uintptr(0) if there was nothing to sweep. func sweepone() uintptr { - _g_ := getg() + gp := getg() - // increment locks to ensure that the goroutine is not preempted + // Increment locks to ensure that the goroutine is not preempted // in the middle of sweep thus leaving the span in an inconsistent state for next GC - _g_.m.locks++ - if atomic.Load(&mheap_.sweepDrained) != 0 { - _g_.m.locks-- - return ^uintptr(0) - } + gp.m.locks++ + // TODO(austin): sweepone is almost always called in a loop; // lift the sweepLocker into its callers. - sl := newSweepLocker() + sl := sweep.active.begin() + if !sl.valid { + gp.m.locks-- + return ^uintptr(0) + } // Find a span to sweep. npages := ^uintptr(0) @@ -271,7 +350,7 @@ func sweepone() uintptr { for { s := mheap_.nextSpanForSweep() if s == nil { - noMoreWork = atomic.Cas(&mheap_.sweepDrained, 0, 1) + noMoreWork = sweep.active.markDrained() break } if state := s.state.get(); state != mSpanInUse { @@ -301,8 +380,7 @@ func sweepone() uintptr { break } } - - sl.dispose() + sweep.active.end(sl) if noMoreWork { // The sweep list is empty. There may still be @@ -331,7 +409,7 @@ func sweepone() uintptr { readyForScavenger() } - _g_.m.locks-- + gp.m.locks-- return npages } @@ -342,10 +420,7 @@ func sweepone() uintptr { // GC runs; to prevent that the caller must be non-preemptible or must // somehow block GC progress. func isSweepDone() bool { - // Check that all spans have at least begun sweeping and there - // are no active sweepers. If both are true, then all spans - // have finished sweeping. - return atomic.Load(&mheap_.sweepDrained) != 0 && atomic.Load(&mheap_.sweepers) == 0 + return sweep.active.isDone() } // Returns only when span s has been swept. @@ -359,16 +434,23 @@ func (s *mspan) ensureSwept() { throw("mspan.ensureSwept: m is not locked") } - sl := newSweepLocker() - // The caller must be sure that the span is a mSpanInUse span. - if s, ok := sl.tryAcquire(s); ok { - s.sweep(false) - sl.dispose() - return + // If this operation fails, then that means that there are + // no more spans to be swept. In this case, either s has already + // been swept, or is about to be acquired for sweeping and swept. + sl := sweep.active.begin() + if sl.valid { + // The caller must be sure that the span is a mSpanInUse span. + if s, ok := sl.tryAcquire(s); ok { + s.sweep(false) + sweep.active.end(sl) + return + } + sweep.active.end(sl) } - sl.dispose() - // unfortunate condition, and we don't have efficient means to wait + // Unfortunately we can't sweep the span ourselves. Somebody else + // got to it first. We don't have efficient means to wait, but that's + // OK, it will be swept fairly soon. for { spangen := atomic.Load(&s.sweepgen) if spangen == sl.sweepGen || spangen == sl.sweepGen+3 { diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go index 0e7694aab7..4f32e888b2 100644 --- a/src/runtime/mheap.go +++ b/src/runtime/mheap.go @@ -65,9 +65,7 @@ type mheap struct { lock mutex pages pageAlloc // page allocation data structure - sweepgen uint32 // sweep generation, see comment in mspan; written during STW - sweepDrained uint32 // all spans are swept or are being swept - sweepers uint32 // number of active sweepone calls + sweepgen uint32 // sweep generation, see comment in mspan; written during STW // allspans is a slice of all mspans ever created. Each mspan // appears exactly once. @@ -815,7 +813,10 @@ func (h *mheap) reclaimChunk(arenas []arenaIdx, pageIdx, n uintptr) uintptr { n0 := n var nFreed uintptr - sl := newSweepLocker() + sl := sweep.active.begin() + if !sl.valid { + return 0 + } for n > 0 { ai := arenas[pageIdx/pagesPerArena] ha := h.arenas[ai.l1()][ai.l2()] @@ -861,7 +862,7 @@ func (h *mheap) reclaimChunk(arenas []arenaIdx, pageIdx, n uintptr) uintptr { pageIdx += uintptr(len(inUse) * 8) n -= uintptr(len(inUse) * 8) } - sl.dispose() + sweep.active.end(sl) if trace.enabled { unlock(&h.lock) // Account for pages scanned but not reclaimed. diff --git a/src/runtime/pprof/mprof_test.go b/src/runtime/pprof/mprof_test.go index b44b32aed2..ab8341d32f 100644 --- a/src/runtime/pprof/mprof_test.go +++ b/src/runtime/pprof/mprof_test.go @@ -85,17 +85,6 @@ func TestMemoryProfiler(t *testing.T) { runtime.GC() // materialize stats - // TODO(mknyszek): Fix #45315 and remove this extra call. - // - // Unfortunately, it's possible for the sweep termination condition - // to flap, so with just one runtime.GC call, a freed object could be - // missed, leading this test to fail. A second call reduces the chance - // of this happening to zero, because sweeping actually has to finish - // to move on to the next GC, during which nothing will happen. - // - // See #46500 for more details. - runtime.GC() - memoryProfilerRun++ tests := []struct { -- GitLab From 645d07819b2224ba4d759829443f7c6442162c69 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 13 May 2021 10:44:47 -0400 Subject: [PATCH 1817/2500] sync: add Mutex.TryLock, RWMutex.TryLock, RWMutex.TryRLock Use of these functions is almost (but not) always a bad idea. Very rarely they are necessary, and third-party implementations (using a mutex and an atomic word, say) cannot integrate as well with the race detector as implmentations in package sync itself. Fixes #45435. Change-Id: I0128ca48ef5e0a3b09c913f0f3a7ee5c56388000 Reviewed-on: https://go-review.googlesource.com/c/go/+/319769 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/sync/mutex.go | 15 ++++++++++ src/sync/mutex_test.go | 18 ++++++++++++ src/sync/rwmutex.go | 59 ++++++++++++++++++++++++++++++++++++++++ src/sync/rwmutex_test.go | 28 +++++++++++++++++++ 4 files changed, 120 insertions(+) diff --git a/src/sync/mutex.go b/src/sync/mutex.go index 3028552f74..9dd04d9470 100644 --- a/src/sync/mutex.go +++ b/src/sync/mutex.go @@ -81,6 +81,21 @@ func (m *Mutex) Lock() { m.lockSlow() } +// TryLock tries to lock m and reports whether it succeeded. +// +// Note that while correct uses of TryLock do exist, they are rare, +// and use of TryLock is often a sign of a deeper problem +// in a particular use of mutexes. +func (m *Mutex) TryLock() bool { + if atomic.CompareAndSwapInt32(&m.state, 0, mutexLocked) { + if race.Enabled { + race.Acquire(unsafe.Pointer(m)) + } + return true + } + return false +} + func (m *Mutex) lockSlow() { var waitStartTime int64 starving := false diff --git a/src/sync/mutex_test.go b/src/sync/mutex_test.go index 98c1bf2a5f..cca0986a30 100644 --- a/src/sync/mutex_test.go +++ b/src/sync/mutex_test.go @@ -60,6 +60,12 @@ func BenchmarkContendedSemaphore(b *testing.B) { func HammerMutex(m *Mutex, loops int, cdone chan bool) { for i := 0; i < loops; i++ { + if i%3 == 0 { + if m.TryLock() { + m.Unlock() + } + continue + } m.Lock() m.Unlock() } @@ -71,7 +77,19 @@ func TestMutex(t *testing.T) { t.Logf("got mutexrate %d expected 0", n) } defer runtime.SetMutexProfileFraction(0) + m := new(Mutex) + + m.Lock() + if m.TryLock() { + t.Fatalf("TryLock succeeded with mutex locked") + } + m.Unlock() + if !m.TryLock() { + t.Fatalf("TryLock failed with mutex unlocked") + } + m.Unlock() + c := make(chan bool) for i := 0; i < 10; i++ { go HammerMutex(m, 1000, c) diff --git a/src/sync/rwmutex.go b/src/sync/rwmutex.go index 3012b5548e..f0d4c9771a 100644 --- a/src/sync/rwmutex.go +++ b/src/sync/rwmutex.go @@ -68,6 +68,34 @@ func (rw *RWMutex) RLock() { } } +// TryRLock tries to lock rw for reading and reports whether it succeeded. +// +// Note that while correct uses of TryRLock do exist, they are rare, +// and use of TryRLock is often a sign of a deeper problem +// in a particular use of mutexes. +func (rw *RWMutex) TryRLock() bool { + if race.Enabled { + _ = rw.w.state + race.Disable() + } + for { + c := atomic.LoadInt32(&rw.readerCount) + if c < 0 { + if race.Enabled { + race.Enable() + } + return false + } + if atomic.CompareAndSwapInt32(&rw.readerCount, c, c+1) { + if race.Enabled { + race.Enable() + race.Acquire(unsafe.Pointer(&rw.readerSem)) + } + return true + } + } +} + // RUnlock undoes a single RLock call; // it does not affect other simultaneous readers. // It is a run-time error if rw is not locked for reading @@ -122,6 +150,37 @@ func (rw *RWMutex) Lock() { } } +// TryLock tries to lock rw for writing and reports whether it succeeded. +// +// Note that while correct uses of TryLock do exist, they are rare, +// and use of TryLock is often a sign of a deeper problem +// in a particular use of mutexes. +func (rw *RWMutex) TryLock() bool { + if race.Enabled { + _ = rw.w.state + race.Disable() + } + if !rw.w.TryLock() { + if race.Enabled { + race.Enable() + } + return false + } + if !atomic.CompareAndSwapInt32(&rw.readerCount, 0, -rwmutexMaxReaders) { + rw.w.Unlock() + if race.Enabled { + race.Enable() + } + return false + } + if race.Enabled { + race.Enable() + race.Acquire(unsafe.Pointer(&rw.readerSem)) + race.Acquire(unsafe.Pointer(&rw.writerSem)) + } + return true +} + // Unlock unlocks rw for writing. It is a run-time error if rw is // not locked for writing on entry to Unlock. // diff --git a/src/sync/rwmutex_test.go b/src/sync/rwmutex_test.go index c98e69fd07..dfbdd9bbee 100644 --- a/src/sync/rwmutex_test.go +++ b/src/sync/rwmutex_test.go @@ -108,6 +108,34 @@ func HammerRWMutex(gomaxprocs, numReaders, num_iterations int) { } func TestRWMutex(t *testing.T) { + var m RWMutex + + m.Lock() + if m.TryLock() { + t.Fatalf("TryLock succeeded with mutex locked") + } + if m.TryRLock() { + t.Fatalf("TryRLock succeeded with mutex locked") + } + m.Unlock() + + if !m.TryLock() { + t.Fatalf("TryLock failed with mutex unlocked") + } + m.Unlock() + + if !m.TryRLock() { + t.Fatalf("TryRLock failed with mutex unlocked") + } + if !m.TryRLock() { + t.Fatalf("TryRLock failed with mutex rlocked") + } + if m.TryLock() { + t.Fatalf("TryLock succeeded with mutex rlocked") + } + m.RUnlock() + m.RUnlock() + defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(-1)) n := 1000 if testing.Short() { -- GitLab From a88575d662a7e8e4fbb31bf139bcffc063e2a734 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 29 Oct 2021 01:18:24 +0000 Subject: [PATCH 1818/2500] Revert "cmd/go: remove support for -buildmode=shared" This reverts CL 359096. Updates #47788. Reason for revert: -buildmode=shared may have actually been working in a few very specific cases. We should not remove -buildmode=shared until we have implemented an alternative to support those few cases. Change-Id: Ia962b06abacc11f6f29fc29d092773be175e32f1 Reviewed-on: https://go-review.googlesource.com/c/go/+/359575 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Russ Cox --- doc/go1.18.html | 7 - misc/cgo/testshared/overlaydir_test.go | 78 ++ misc/cgo/testshared/shared_test.go | 1080 +++++++++++++++++ misc/cgo/testshared/testdata/dep2/dep2.go | 15 + misc/cgo/testshared/testdata/dep3/dep3.go | 22 + misc/cgo/testshared/testdata/depBase/asm.s | 10 + misc/cgo/testshared/testdata/depBase/dep.go | 37 + misc/cgo/testshared/testdata/depBase/gccgo.go | 9 + misc/cgo/testshared/testdata/depBase/stubs.go | 9 + .../testshared/testdata/division/division.go | 17 + misc/cgo/testshared/testdata/exe/exe.go | 45 + misc/cgo/testshared/testdata/exe2/exe2.go | 8 + misc/cgo/testshared/testdata/exe3/exe3.go | 7 + misc/cgo/testshared/testdata/execgo/exe.go | 8 + .../testshared/testdata/explicit/explicit.go | 9 + .../testshared/testdata/gcdata/main/main.go | 37 + misc/cgo/testshared/testdata/gcdata/p/p.go | 7 + misc/cgo/testshared/testdata/global/main.go | 71 ++ .../testshared/testdata/globallib/global.go | 17 + misc/cgo/testshared/testdata/iface/main.go | 17 + misc/cgo/testshared/testdata/iface_a/a.go | 17 + misc/cgo/testshared/testdata/iface_b/b.go | 17 + misc/cgo/testshared/testdata/iface_i/i.go | 17 + .../testshared/testdata/implicit/implicit.go | 5 + .../testdata/implicitcmd/implicitcmd.go | 10 + misc/cgo/testshared/testdata/issue25065/a.go | 20 + .../testdata/issue30768/issue30768lib/lib.go | 11 + .../testshared/testdata/issue30768/x_test.go | 22 + .../cgo/testshared/testdata/issue39777/a/a.go | 9 + .../cgo/testshared/testdata/issue39777/b/b.go | 7 + .../cgo/testshared/testdata/issue44031/a/a.go | 9 + .../cgo/testshared/testdata/issue44031/b/b.go | 17 + .../testdata/issue44031/main/main.go | 20 + .../cgo/testshared/testdata/issue47837/a/a.go | 19 + .../testdata/issue47837/main/main.go | 14 + .../testshared/testdata/trivial/trivial.go | 9 + src/cmd/dist/test.go | 9 + src/cmd/go/alldocs.go | 9 + src/cmd/go/internal/help/helpdoc.go | 5 + src/cmd/go/internal/list/list.go | 3 +- src/cmd/go/internal/work/build.go | 3 + src/cmd/go/internal/work/init.go | 31 +- .../go/testdata/script/list_linkshared.txt | 16 + src/cmd/internal/sys/supported.go | 7 + 44 files changed, 1786 insertions(+), 30 deletions(-) create mode 100644 misc/cgo/testshared/overlaydir_test.go create mode 100644 misc/cgo/testshared/shared_test.go create mode 100644 misc/cgo/testshared/testdata/dep2/dep2.go create mode 100644 misc/cgo/testshared/testdata/dep3/dep3.go create mode 100644 misc/cgo/testshared/testdata/depBase/asm.s create mode 100644 misc/cgo/testshared/testdata/depBase/dep.go create mode 100644 misc/cgo/testshared/testdata/depBase/gccgo.go create mode 100644 misc/cgo/testshared/testdata/depBase/stubs.go create mode 100644 misc/cgo/testshared/testdata/division/division.go create mode 100644 misc/cgo/testshared/testdata/exe/exe.go create mode 100644 misc/cgo/testshared/testdata/exe2/exe2.go create mode 100644 misc/cgo/testshared/testdata/exe3/exe3.go create mode 100644 misc/cgo/testshared/testdata/execgo/exe.go create mode 100644 misc/cgo/testshared/testdata/explicit/explicit.go create mode 100644 misc/cgo/testshared/testdata/gcdata/main/main.go create mode 100644 misc/cgo/testshared/testdata/gcdata/p/p.go create mode 100644 misc/cgo/testshared/testdata/global/main.go create mode 100644 misc/cgo/testshared/testdata/globallib/global.go create mode 100644 misc/cgo/testshared/testdata/iface/main.go create mode 100644 misc/cgo/testshared/testdata/iface_a/a.go create mode 100644 misc/cgo/testshared/testdata/iface_b/b.go create mode 100644 misc/cgo/testshared/testdata/iface_i/i.go create mode 100644 misc/cgo/testshared/testdata/implicit/implicit.go create mode 100644 misc/cgo/testshared/testdata/implicitcmd/implicitcmd.go create mode 100644 misc/cgo/testshared/testdata/issue25065/a.go create mode 100644 misc/cgo/testshared/testdata/issue30768/issue30768lib/lib.go create mode 100644 misc/cgo/testshared/testdata/issue30768/x_test.go create mode 100644 misc/cgo/testshared/testdata/issue39777/a/a.go create mode 100644 misc/cgo/testshared/testdata/issue39777/b/b.go create mode 100644 misc/cgo/testshared/testdata/issue44031/a/a.go create mode 100644 misc/cgo/testshared/testdata/issue44031/b/b.go create mode 100644 misc/cgo/testshared/testdata/issue44031/main/main.go create mode 100644 misc/cgo/testshared/testdata/issue47837/a/a.go create mode 100644 misc/cgo/testshared/testdata/issue47837/main/main.go create mode 100644 misc/cgo/testshared/testdata/trivial/trivial.go create mode 100644 src/cmd/go/testdata/script/list_linkshared.txt diff --git a/doc/go1.18.html b/doc/go1.18.html index 875577fd10..6fe993d51b 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -90,13 +90,6 @@ Do not send CLs removing the interior tags from such phrases. package.

-

- The go command no longer supports -linkshared - and -buildmode=shared. - (shared building and linking has never worked in module mode or - when GOROOT is not writable.) -

-

TODO: complete this section, or delete if not needed

diff --git a/misc/cgo/testshared/overlaydir_test.go b/misc/cgo/testshared/overlaydir_test.go new file mode 100644 index 0000000000..eb587a2d44 --- /dev/null +++ b/misc/cgo/testshared/overlaydir_test.go @@ -0,0 +1,78 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package shared_test + +import ( + "io" + "os" + "path/filepath" + "strings" +) + +// overlayDir makes a minimal-overhead copy of srcRoot in which new files may be added. +// +// TODO: Once we no longer need to support the misc module in GOPATH mode, +// factor this function out into a package to reduce duplication. +func overlayDir(dstRoot, srcRoot string) error { + dstRoot = filepath.Clean(dstRoot) + if err := os.MkdirAll(dstRoot, 0777); err != nil { + return err + } + + srcRoot, err := filepath.Abs(srcRoot) + if err != nil { + return err + } + + return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error { + if err != nil || srcPath == srcRoot { + return err + } + + suffix := strings.TrimPrefix(srcPath, srcRoot) + for len(suffix) > 0 && suffix[0] == filepath.Separator { + suffix = suffix[1:] + } + dstPath := filepath.Join(dstRoot, suffix) + + perm := info.Mode() & os.ModePerm + if info.Mode()&os.ModeSymlink != 0 { + info, err = os.Stat(srcPath) + if err != nil { + return err + } + perm = info.Mode() & os.ModePerm + } + + // Always copy directories (don't symlink them). + // If we add a file in the overlay, we don't want to add it in the original. + if info.IsDir() { + return os.MkdirAll(dstPath, perm|0200) + } + + // If the OS supports symlinks, use them instead of copying bytes. + if err := os.Symlink(srcPath, dstPath); err == nil { + return nil + } + + // Otherwise, copy the bytes. + src, err := os.Open(srcPath) + if err != nil { + return err + } + defer src.Close() + + dst, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm) + if err != nil { + return err + } + + _, err = io.Copy(dst, src) + if closeErr := dst.Close(); err == nil { + err = closeErr + } + return err + }) +} diff --git a/misc/cgo/testshared/shared_test.go b/misc/cgo/testshared/shared_test.go new file mode 100644 index 0000000000..672811fe0e --- /dev/null +++ b/misc/cgo/testshared/shared_test.go @@ -0,0 +1,1080 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package shared_test + +import ( + "bufio" + "bytes" + "debug/elf" + "encoding/binary" + "flag" + "fmt" + "go/build" + "io" + "log" + "os" + "os/exec" + "path/filepath" + "regexp" + "runtime" + "sort" + "strings" + "testing" + "time" +) + +var gopathInstallDir, gorootInstallDir string + +// This is the smallest set of packages we can link into a shared +// library (runtime/cgo is built implicitly). +var minpkgs = []string{"runtime", "sync/atomic"} +var soname = "libruntime,sync-atomic.so" + +var testX = flag.Bool("testx", false, "if true, pass -x to 'go' subcommands invoked by the test") +var testWork = flag.Bool("testwork", false, "if true, log and do not delete the temporary working directory") + +// run runs a command and calls t.Errorf if it fails. +func run(t *testing.T, msg string, args ...string) { + runWithEnv(t, msg, nil, args...) +} + +// runWithEnv runs a command under the given environment and calls t.Errorf if it fails. +func runWithEnv(t *testing.T, msg string, env []string, args ...string) { + c := exec.Command(args[0], args[1:]...) + if len(env) != 0 { + c.Env = append(os.Environ(), env...) + } + if output, err := c.CombinedOutput(); err != nil { + t.Errorf("executing %s (%s) failed %s:\n%s", strings.Join(args, " "), msg, err, output) + } +} + +// goCmd invokes the go tool with the installsuffix set up by TestMain. It calls +// t.Fatalf if the command fails. +func goCmd(t *testing.T, args ...string) string { + newargs := []string{args[0]} + if *testX { + newargs = append(newargs, "-x") + } + newargs = append(newargs, args[1:]...) + c := exec.Command("go", newargs...) + stderr := new(strings.Builder) + c.Stderr = stderr + + if testing.Verbose() && t == nil { + fmt.Fprintf(os.Stderr, "+ go %s\n", strings.Join(args, " ")) + c.Stderr = os.Stderr + } + output, err := c.Output() + + if err != nil { + if t != nil { + t.Helper() + t.Fatalf("executing %s failed %v:\n%s", strings.Join(c.Args, " "), err, stderr) + } else { + // Panic instead of using log.Fatalf so that deferred cleanup may run in testMain. + log.Panicf("executing %s failed %v:\n%s", strings.Join(c.Args, " "), err, stderr) + } + } + if testing.Verbose() && t != nil { + t.Logf("go %s", strings.Join(args, " ")) + if stderr.Len() > 0 { + t.Logf("%s", stderr) + } + } + return string(bytes.TrimSpace(output)) +} + +// TestMain calls testMain so that the latter can use defer (TestMain exits with os.Exit). +func testMain(m *testing.M) (int, error) { + workDir, err := os.MkdirTemp("", "shared_test") + if err != nil { + return 0, err + } + if *testWork || testing.Verbose() { + fmt.Printf("+ mkdir -p %s\n", workDir) + } + if !*testWork { + defer os.RemoveAll(workDir) + } + + // Some tests need to edit the source in GOPATH, so copy this directory to a + // temporary directory and chdir to that. + gopath := filepath.Join(workDir, "gopath") + modRoot, err := cloneTestdataModule(gopath) + if err != nil { + return 0, err + } + if testing.Verbose() { + fmt.Printf("+ export GOPATH=%s\n", gopath) + fmt.Printf("+ cd %s\n", modRoot) + } + os.Setenv("GOPATH", gopath) + // Explicitly override GOBIN as well, in case it was set through a GOENV file. + os.Setenv("GOBIN", filepath.Join(gopath, "bin")) + os.Chdir(modRoot) + os.Setenv("PWD", modRoot) + + // The test also needs to install libraries into GOROOT/pkg, so copy the + // subset of GOROOT that we need. + // + // TODO(golang.org/issue/28553): Rework -buildmode=shared so that it does not + // need to write to GOROOT. + goroot := filepath.Join(workDir, "goroot") + if err := cloneGOROOTDeps(goroot); err != nil { + return 0, err + } + if testing.Verbose() { + fmt.Fprintf(os.Stderr, "+ export GOROOT=%s\n", goroot) + } + os.Setenv("GOROOT", goroot) + + myContext := build.Default + myContext.GOROOT = goroot + myContext.GOPATH = gopath + runtimeP, err := myContext.Import("runtime", ".", build.ImportComment) + if err != nil { + return 0, fmt.Errorf("import failed: %v", err) + } + gorootInstallDir = runtimeP.PkgTargetRoot + "_dynlink" + + // All tests depend on runtime being built into a shared library. Because + // that takes a few seconds, do it here and have all tests use the version + // built here. + goCmd(nil, append([]string{"install", "-buildmode=shared"}, minpkgs...)...) + + myContext.InstallSuffix = "_dynlink" + depP, err := myContext.Import("./depBase", ".", build.ImportComment) + if err != nil { + return 0, fmt.Errorf("import failed: %v", err) + } + if depP.PkgTargetRoot == "" { + gopathInstallDir = filepath.Dir(goCmd(nil, "list", "-buildmode=shared", "-f", "{{.Target}}", "./depBase")) + } else { + gopathInstallDir = filepath.Join(depP.PkgTargetRoot, "testshared") + } + return m.Run(), nil +} + +func TestMain(m *testing.M) { + log.SetFlags(log.Lshortfile) + flag.Parse() + + exitCode, err := testMain(m) + if err != nil { + log.Fatal(err) + } + os.Exit(exitCode) +} + +// cloneTestdataModule clones the packages from src/testshared into gopath. +// It returns the directory within gopath at which the module root is located. +func cloneTestdataModule(gopath string) (string, error) { + modRoot := filepath.Join(gopath, "src", "testshared") + if err := overlayDir(modRoot, "testdata"); err != nil { + return "", err + } + if err := os.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module testshared\n"), 0644); err != nil { + return "", err + } + return modRoot, nil +} + +// cloneGOROOTDeps copies (or symlinks) the portions of GOROOT/src and +// GOROOT/pkg relevant to this test into the given directory. +// It must be run from within the testdata module. +func cloneGOROOTDeps(goroot string) error { + oldGOROOT := strings.TrimSpace(goCmd(nil, "env", "GOROOT")) + if oldGOROOT == "" { + return fmt.Errorf("go env GOROOT returned an empty string") + } + + // Before we clone GOROOT, figure out which packages we need to copy over. + listArgs := []string{ + "list", + "-deps", + "-f", "{{if and .Standard (not .ForTest)}}{{.ImportPath}}{{end}}", + } + stdDeps := goCmd(nil, append(listArgs, minpkgs...)...) + testdataDeps := goCmd(nil, append(listArgs, "-test", "./...")...) + + pkgs := append(strings.Split(strings.TrimSpace(stdDeps), "\n"), + strings.Split(strings.TrimSpace(testdataDeps), "\n")...) + sort.Strings(pkgs) + var pkgRoots []string + for _, pkg := range pkgs { + parentFound := false + for _, prev := range pkgRoots { + if strings.HasPrefix(pkg, prev) { + // We will copy in the source for pkg when we copy in prev. + parentFound = true + break + } + } + if !parentFound { + pkgRoots = append(pkgRoots, pkg) + } + } + + gorootDirs := []string{ + "pkg/tool", + "pkg/include", + } + for _, pkg := range pkgRoots { + gorootDirs = append(gorootDirs, filepath.Join("src", pkg)) + } + + for _, dir := range gorootDirs { + if testing.Verbose() { + fmt.Fprintf(os.Stderr, "+ cp -r %s %s\n", filepath.Join(oldGOROOT, dir), filepath.Join(goroot, dir)) + } + if err := overlayDir(filepath.Join(goroot, dir), filepath.Join(oldGOROOT, dir)); err != nil { + return err + } + } + + return nil +} + +// The shared library was built at the expected location. +func TestSOBuilt(t *testing.T) { + _, err := os.Stat(filepath.Join(gorootInstallDir, soname)) + if err != nil { + t.Error(err) + } +} + +func hasDynTag(f *elf.File, tag elf.DynTag) bool { + ds := f.SectionByType(elf.SHT_DYNAMIC) + if ds == nil { + return false + } + d, err := ds.Data() + if err != nil { + return false + } + for len(d) > 0 { + var t elf.DynTag + switch f.Class { + case elf.ELFCLASS32: + t = elf.DynTag(f.ByteOrder.Uint32(d[0:4])) + d = d[8:] + case elf.ELFCLASS64: + t = elf.DynTag(f.ByteOrder.Uint64(d[0:8])) + d = d[16:] + } + if t == tag { + return true + } + } + return false +} + +// The shared library does not have relocations against the text segment. +func TestNoTextrel(t *testing.T) { + sopath := filepath.Join(gorootInstallDir, soname) + f, err := elf.Open(sopath) + if err != nil { + t.Fatal("elf.Open failed: ", err) + } + defer f.Close() + if hasDynTag(f, elf.DT_TEXTREL) { + t.Errorf("%s has DT_TEXTREL set", soname) + } +} + +// The shared library does not contain symbols called ".dup" +// (See golang.org/issue/14841.) +func TestNoDupSymbols(t *testing.T) { + sopath := filepath.Join(gorootInstallDir, soname) + f, err := elf.Open(sopath) + if err != nil { + t.Fatal("elf.Open failed: ", err) + } + defer f.Close() + syms, err := f.Symbols() + if err != nil { + t.Errorf("error reading symbols %v", err) + return + } + for _, s := range syms { + if s.Name == ".dup" { + t.Fatalf("%s contains symbol called .dup", sopath) + } + } +} + +// The install command should have created a "shlibname" file for the +// listed packages (and runtime/cgo, and math on arm) indicating the +// name of the shared library containing it. +func TestShlibnameFiles(t *testing.T) { + pkgs := append([]string{}, minpkgs...) + pkgs = append(pkgs, "runtime/cgo") + if runtime.GOARCH == "arm" { + pkgs = append(pkgs, "math") + } + for _, pkg := range pkgs { + shlibnamefile := filepath.Join(gorootInstallDir, pkg+".shlibname") + contentsb, err := os.ReadFile(shlibnamefile) + if err != nil { + t.Errorf("error reading shlibnamefile for %s: %v", pkg, err) + continue + } + contents := strings.TrimSpace(string(contentsb)) + if contents != soname { + t.Errorf("shlibnamefile for %s has wrong contents: %q", pkg, contents) + } + } +} + +// Is a given offset into the file contained in a loaded segment? +func isOffsetLoaded(f *elf.File, offset uint64) bool { + for _, prog := range f.Progs { + if prog.Type == elf.PT_LOAD { + if prog.Off <= offset && offset < prog.Off+prog.Filesz { + return true + } + } + } + return false +} + +func rnd(v int32, r int32) int32 { + if r <= 0 { + return v + } + v += r - 1 + c := v % r + if c < 0 { + c += r + } + v -= c + return v +} + +func readwithpad(r io.Reader, sz int32) ([]byte, error) { + data := make([]byte, rnd(sz, 4)) + _, err := io.ReadFull(r, data) + if err != nil { + return nil, err + } + data = data[:sz] + return data, nil +} + +type note struct { + name string + tag int32 + desc string + section *elf.Section +} + +// Read all notes from f. As ELF section names are not supposed to be special, one +// looks for a particular note by scanning all SHT_NOTE sections looking for a note +// with a particular "name" and "tag". +func readNotes(f *elf.File) ([]*note, error) { + var notes []*note + for _, sect := range f.Sections { + if sect.Type != elf.SHT_NOTE { + continue + } + r := sect.Open() + for { + var namesize, descsize, tag int32 + err := binary.Read(r, f.ByteOrder, &namesize) + if err != nil { + if err == io.EOF { + break + } + return nil, fmt.Errorf("read namesize failed: %v", err) + } + err = binary.Read(r, f.ByteOrder, &descsize) + if err != nil { + return nil, fmt.Errorf("read descsize failed: %v", err) + } + err = binary.Read(r, f.ByteOrder, &tag) + if err != nil { + return nil, fmt.Errorf("read type failed: %v", err) + } + name, err := readwithpad(r, namesize) + if err != nil { + return nil, fmt.Errorf("read name failed: %v", err) + } + desc, err := readwithpad(r, descsize) + if err != nil { + return nil, fmt.Errorf("read desc failed: %v", err) + } + notes = append(notes, ¬e{name: string(name), tag: tag, desc: string(desc), section: sect}) + } + } + return notes, nil +} + +func dynStrings(t *testing.T, path string, flag elf.DynTag) []string { + t.Helper() + f, err := elf.Open(path) + if err != nil { + t.Fatalf("elf.Open(%q) failed: %v", path, err) + } + defer f.Close() + dynstrings, err := f.DynString(flag) + if err != nil { + t.Fatalf("DynString(%s) failed on %s: %v", flag, path, err) + } + return dynstrings +} + +func AssertIsLinkedToRegexp(t *testing.T, path string, re *regexp.Regexp) { + t.Helper() + for _, dynstring := range dynStrings(t, path, elf.DT_NEEDED) { + if re.MatchString(dynstring) { + return + } + } + t.Errorf("%s is not linked to anything matching %v", path, re) +} + +func AssertIsLinkedTo(t *testing.T, path, lib string) { + t.Helper() + AssertIsLinkedToRegexp(t, path, regexp.MustCompile(regexp.QuoteMeta(lib))) +} + +func AssertHasRPath(t *testing.T, path, dir string) { + t.Helper() + for _, tag := range []elf.DynTag{elf.DT_RPATH, elf.DT_RUNPATH} { + for _, dynstring := range dynStrings(t, path, tag) { + for _, rpath := range strings.Split(dynstring, ":") { + if filepath.Clean(rpath) == filepath.Clean(dir) { + return + } + } + } + } + t.Errorf("%s does not have rpath %s", path, dir) +} + +// Build a trivial program that links against the shared runtime and check it runs. +func TestTrivialExecutable(t *testing.T) { + goCmd(t, "install", "-linkshared", "./trivial") + run(t, "trivial executable", "../../bin/trivial") + AssertIsLinkedTo(t, "../../bin/trivial", soname) + AssertHasRPath(t, "../../bin/trivial", gorootInstallDir) + checkSize(t, "../../bin/trivial", 100000) // it is 19K on linux/amd64, 100K should be enough +} + +// Build a trivial program in PIE mode that links against the shared runtime and check it runs. +func TestTrivialExecutablePIE(t *testing.T) { + goCmd(t, "build", "-buildmode=pie", "-o", "trivial.pie", "-linkshared", "./trivial") + run(t, "trivial executable", "./trivial.pie") + AssertIsLinkedTo(t, "./trivial.pie", soname) + AssertHasRPath(t, "./trivial.pie", gorootInstallDir) + checkSize(t, "./trivial.pie", 100000) // it is 19K on linux/amd64, 100K should be enough +} + +// Check that the file size does not exceed a limit. +func checkSize(t *testing.T, f string, limit int64) { + fi, err := os.Stat(f) + if err != nil { + t.Fatalf("stat failed: %v", err) + } + if sz := fi.Size(); sz > limit { + t.Errorf("file too large: got %d, want <= %d", sz, limit) + } +} + +// Build a division test program and check it runs. +func TestDivisionExecutable(t *testing.T) { + goCmd(t, "install", "-linkshared", "./division") + run(t, "division executable", "../../bin/division") +} + +// Build an executable that uses cgo linked against the shared runtime and check it +// runs. +func TestCgoExecutable(t *testing.T) { + goCmd(t, "install", "-linkshared", "./execgo") + run(t, "cgo executable", "../../bin/execgo") +} + +func checkPIE(t *testing.T, name string) { + f, err := elf.Open(name) + if err != nil { + t.Fatal("elf.Open failed: ", err) + } + defer f.Close() + if f.Type != elf.ET_DYN { + t.Errorf("%s has type %v, want ET_DYN", name, f.Type) + } + if hasDynTag(f, elf.DT_TEXTREL) { + t.Errorf("%s has DT_TEXTREL set", name) + } +} + +func TestTrivialPIE(t *testing.T) { + name := "trivial_pie" + goCmd(t, "build", "-buildmode=pie", "-o="+name, "./trivial") + defer os.Remove(name) + run(t, name, "./"+name) + checkPIE(t, name) +} + +func TestCgoPIE(t *testing.T) { + name := "cgo_pie" + goCmd(t, "build", "-buildmode=pie", "-o="+name, "./execgo") + defer os.Remove(name) + run(t, name, "./"+name) + checkPIE(t, name) +} + +// Build a GOPATH package into a shared library that links against the goroot runtime +// and an executable that links against both. +func TestGopathShlib(t *testing.T) { + goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase") + shlib := goCmd(t, "list", "-f", "{{.Shlib}}", "-buildmode=shared", "-linkshared", "./depBase") + AssertIsLinkedTo(t, shlib, soname) + goCmd(t, "install", "-linkshared", "./exe") + AssertIsLinkedTo(t, "../../bin/exe", soname) + AssertIsLinkedTo(t, "../../bin/exe", filepath.Base(shlib)) + AssertHasRPath(t, "../../bin/exe", gorootInstallDir) + AssertHasRPath(t, "../../bin/exe", filepath.Dir(gopathInstallDir)) + // And check it runs. + run(t, "executable linked to GOPATH library", "../../bin/exe") +} + +// The shared library contains a note listing the packages it contains in a section +// that is not mapped into memory. +func testPkgListNote(t *testing.T, f *elf.File, note *note) { + if note.section.Flags != 0 { + t.Errorf("package list section has flags %v, want 0", note.section.Flags) + } + if isOffsetLoaded(f, note.section.Offset) { + t.Errorf("package list section contained in PT_LOAD segment") + } + if note.desc != "testshared/depBase\n" { + t.Errorf("incorrect package list %q, want %q", note.desc, "testshared/depBase\n") + } +} + +// The shared library contains a note containing the ABI hash that is mapped into +// memory and there is a local symbol called go.link.abihashbytes that points 16 +// bytes into it. +func testABIHashNote(t *testing.T, f *elf.File, note *note) { + if note.section.Flags != elf.SHF_ALLOC { + t.Errorf("abi hash section has flags %v, want SHF_ALLOC", note.section.Flags) + } + if !isOffsetLoaded(f, note.section.Offset) { + t.Errorf("abihash section not contained in PT_LOAD segment") + } + var hashbytes elf.Symbol + symbols, err := f.Symbols() + if err != nil { + t.Errorf("error reading symbols %v", err) + return + } + for _, sym := range symbols { + if sym.Name == "go.link.abihashbytes" { + hashbytes = sym + } + } + if hashbytes.Name == "" { + t.Errorf("no symbol called go.link.abihashbytes") + return + } + if elf.ST_BIND(hashbytes.Info) != elf.STB_LOCAL { + t.Errorf("%s has incorrect binding %v, want STB_LOCAL", hashbytes.Name, elf.ST_BIND(hashbytes.Info)) + } + if f.Sections[hashbytes.Section] != note.section { + t.Errorf("%s has incorrect section %v, want %s", hashbytes.Name, f.Sections[hashbytes.Section].Name, note.section.Name) + } + if hashbytes.Value-note.section.Addr != 16 { + t.Errorf("%s has incorrect offset into section %d, want 16", hashbytes.Name, hashbytes.Value-note.section.Addr) + } +} + +// A Go shared library contains a note indicating which other Go shared libraries it +// was linked against in an unmapped section. +func testDepsNote(t *testing.T, f *elf.File, note *note) { + if note.section.Flags != 0 { + t.Errorf("package list section has flags %v, want 0", note.section.Flags) + } + if isOffsetLoaded(f, note.section.Offset) { + t.Errorf("package list section contained in PT_LOAD segment") + } + // libdepBase.so just links against the lib containing the runtime. + if note.desc != soname { + t.Errorf("incorrect dependency list %q, want %q", note.desc, soname) + } +} + +// The shared library contains notes with defined contents; see above. +func TestNotes(t *testing.T) { + goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase") + shlib := goCmd(t, "list", "-f", "{{.Shlib}}", "-buildmode=shared", "-linkshared", "./depBase") + f, err := elf.Open(shlib) + if err != nil { + t.Fatal(err) + } + defer f.Close() + notes, err := readNotes(f) + if err != nil { + t.Fatal(err) + } + pkgListNoteFound := false + abiHashNoteFound := false + depsNoteFound := false + for _, note := range notes { + if note.name != "Go\x00\x00" { + continue + } + switch note.tag { + case 1: // ELF_NOTE_GOPKGLIST_TAG + if pkgListNoteFound { + t.Error("multiple package list notes") + } + testPkgListNote(t, f, note) + pkgListNoteFound = true + case 2: // ELF_NOTE_GOABIHASH_TAG + if abiHashNoteFound { + t.Error("multiple abi hash notes") + } + testABIHashNote(t, f, note) + abiHashNoteFound = true + case 3: // ELF_NOTE_GODEPS_TAG + if depsNoteFound { + t.Error("multiple dependency list notes") + } + testDepsNote(t, f, note) + depsNoteFound = true + } + } + if !pkgListNoteFound { + t.Error("package list note not found") + } + if !abiHashNoteFound { + t.Error("abi hash note not found") + } + if !depsNoteFound { + t.Error("deps note not found") + } +} + +// Build a GOPATH package (depBase) into a shared library that links against the goroot +// runtime, another package (dep2) that links against the first, and an +// executable that links against dep2. +func TestTwoGopathShlibs(t *testing.T) { + goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase") + goCmd(t, "install", "-buildmode=shared", "-linkshared", "./dep2") + goCmd(t, "install", "-linkshared", "./exe2") + run(t, "executable linked to GOPATH library", "../../bin/exe2") +} + +func TestThreeGopathShlibs(t *testing.T) { + goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase") + goCmd(t, "install", "-buildmode=shared", "-linkshared", "./dep2") + goCmd(t, "install", "-buildmode=shared", "-linkshared", "./dep3") + goCmd(t, "install", "-linkshared", "./exe3") + run(t, "executable linked to GOPATH library", "../../bin/exe3") +} + +// If gccgo is not available or not new enough, call t.Skip. +func requireGccgo(t *testing.T) { + t.Helper() + + gccgoName := os.Getenv("GCCGO") + if gccgoName == "" { + gccgoName = "gccgo" + } + gccgoPath, err := exec.LookPath(gccgoName) + if err != nil { + t.Skip("gccgo not found") + } + cmd := exec.Command(gccgoPath, "-dumpversion") + output, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("%s -dumpversion failed: %v\n%s", gccgoPath, err, output) + } + if string(output) < "5" { + t.Skipf("gccgo too old (%s)", strings.TrimSpace(string(output))) + } + + gomod, err := exec.Command("go", "env", "GOMOD").Output() + if err != nil { + t.Fatalf("go env GOMOD: %v", err) + } + if len(bytes.TrimSpace(gomod)) > 0 { + t.Skipf("gccgo not supported in module mode; see golang.org/issue/30344") + } +} + +// Build a GOPATH package into a shared library with gccgo and an executable that +// links against it. +func TestGoPathShlibGccgo(t *testing.T) { + requireGccgo(t) + + libgoRE := regexp.MustCompile("libgo.so.[0-9]+") + + goCmd(t, "install", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "./depBase") + + // Run 'go list' after 'go install': with gccgo, we apparently don't know the + // shlib location until after we've installed it. + shlib := goCmd(t, "list", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "-f", "{{.Shlib}}", "./depBase") + + AssertIsLinkedToRegexp(t, shlib, libgoRE) + goCmd(t, "install", "-compiler=gccgo", "-linkshared", "./exe") + AssertIsLinkedToRegexp(t, "../../bin/exe", libgoRE) + AssertIsLinkedTo(t, "../../bin/exe", filepath.Base(shlib)) + AssertHasRPath(t, "../../bin/exe", filepath.Dir(shlib)) + // And check it runs. + run(t, "gccgo-built", "../../bin/exe") +} + +// The gccgo version of TestTwoGopathShlibs: build a GOPATH package into a shared +// library with gccgo, another GOPATH package that depends on the first and an +// executable that links the second library. +func TestTwoGopathShlibsGccgo(t *testing.T) { + requireGccgo(t) + + libgoRE := regexp.MustCompile("libgo.so.[0-9]+") + + goCmd(t, "install", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "./depBase") + goCmd(t, "install", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "./dep2") + goCmd(t, "install", "-compiler=gccgo", "-linkshared", "./exe2") + + // Run 'go list' after 'go install': with gccgo, we apparently don't know the + // shlib location until after we've installed it. + dep2 := goCmd(t, "list", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "-f", "{{.Shlib}}", "./dep2") + depBase := goCmd(t, "list", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "-f", "{{.Shlib}}", "./depBase") + + AssertIsLinkedToRegexp(t, depBase, libgoRE) + AssertIsLinkedToRegexp(t, dep2, libgoRE) + AssertIsLinkedTo(t, dep2, filepath.Base(depBase)) + AssertIsLinkedToRegexp(t, "../../bin/exe2", libgoRE) + AssertIsLinkedTo(t, "../../bin/exe2", filepath.Base(dep2)) + AssertIsLinkedTo(t, "../../bin/exe2", filepath.Base(depBase)) + + // And check it runs. + run(t, "gccgo-built", "../../bin/exe2") +} + +// Testing rebuilding of shared libraries when they are stale is a bit more +// complicated that it seems like it should be. First, we make everything "old": but +// only a few seconds old, or it might be older than gc (or the runtime source) and +// everything will get rebuilt. Then define a timestamp slightly newer than this +// time, which is what we set the mtime to of a file to cause it to be seen as new, +// and finally another slightly even newer one that we can compare files against to +// see if they have been rebuilt. +var oldTime = time.Now().Add(-9 * time.Second) +var nearlyNew = time.Now().Add(-6 * time.Second) +var stampTime = time.Now().Add(-3 * time.Second) + +// resetFileStamps makes "everything" (bin, src, pkg from GOPATH and the +// test-specific parts of GOROOT) appear old. +func resetFileStamps() { + chtime := func(path string, info os.FileInfo, err error) error { + return os.Chtimes(path, oldTime, oldTime) + } + reset := func(path string) { + if err := filepath.Walk(path, chtime); err != nil { + log.Panicf("resetFileStamps failed: %v", err) + } + + } + reset("../../bin") + reset("../../pkg") + reset("../../src") + reset(gorootInstallDir) +} + +// touch changes path and returns a function that changes it back. +// It also sets the time of the file, so that we can see if it is rewritten. +func touch(t *testing.T, path string) (cleanup func()) { + t.Helper() + data, err := os.ReadFile(path) + if err != nil { + t.Fatal(err) + } + old := make([]byte, len(data)) + copy(old, data) + if bytes.HasPrefix(data, []byte("!\n")) { + // Change last digit of build ID. + // (Content ID in the new content-based build IDs.) + const marker = `build id "` + i := bytes.Index(data, []byte(marker)) + if i < 0 { + t.Fatal("cannot find build id in archive") + } + j := bytes.IndexByte(data[i+len(marker):], '"') + if j < 0 { + t.Fatal("cannot find build id in archive") + } + i += len(marker) + j - 1 + if data[i] == 'a' { + data[i] = 'b' + } else { + data[i] = 'a' + } + } else { + // assume it's a text file + data = append(data, '\n') + } + + // If the file is still a symlink from an overlay, delete it so that we will + // replace it with a regular file instead of overwriting the symlinked one. + fi, err := os.Lstat(path) + if err == nil && !fi.Mode().IsRegular() { + fi, err = os.Stat(path) + if err := os.Remove(path); err != nil { + t.Fatal(err) + } + } + if err != nil { + t.Fatal(err) + } + + // If we're replacing a symlink to a read-only file, make the new file + // user-writable. + perm := fi.Mode().Perm() | 0200 + + if err := os.WriteFile(path, data, perm); err != nil { + t.Fatal(err) + } + if err := os.Chtimes(path, nearlyNew, nearlyNew); err != nil { + t.Fatal(err) + } + return func() { + if err := os.WriteFile(path, old, perm); err != nil { + t.Fatal(err) + } + } +} + +// isNew returns if the path is newer than the time stamp used by touch. +func isNew(t *testing.T, path string) bool { + t.Helper() + fi, err := os.Stat(path) + if err != nil { + t.Fatal(err) + } + return fi.ModTime().After(stampTime) +} + +// Fail unless path has been rebuilt (i.e. is newer than the time stamp used by +// isNew) +func AssertRebuilt(t *testing.T, msg, path string) { + t.Helper() + if !isNew(t, path) { + t.Errorf("%s was not rebuilt (%s)", msg, path) + } +} + +// Fail if path has been rebuilt (i.e. is newer than the time stamp used by isNew) +func AssertNotRebuilt(t *testing.T, msg, path string) { + t.Helper() + if isNew(t, path) { + t.Errorf("%s was rebuilt (%s)", msg, path) + } +} + +func TestRebuilding(t *testing.T) { + goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase") + goCmd(t, "install", "-linkshared", "./exe") + info := strings.Fields(goCmd(t, "list", "-buildmode=shared", "-linkshared", "-f", "{{.Target}} {{.Shlib}}", "./depBase")) + if len(info) != 2 { + t.Fatalf("go list failed to report Target and/or Shlib") + } + target := info[0] + shlib := info[1] + + // If the source is newer than both the .a file and the .so, both are rebuilt. + t.Run("newsource", func(t *testing.T) { + resetFileStamps() + cleanup := touch(t, "./depBase/dep.go") + defer func() { + cleanup() + goCmd(t, "install", "-linkshared", "./exe") + }() + goCmd(t, "install", "-linkshared", "./exe") + AssertRebuilt(t, "new source", target) + AssertRebuilt(t, "new source", shlib) + }) + + // If the .a file is newer than the .so, the .so is rebuilt (but not the .a) + t.Run("newarchive", func(t *testing.T) { + resetFileStamps() + AssertNotRebuilt(t, "new .a file before build", target) + goCmd(t, "list", "-linkshared", "-f={{.ImportPath}} {{.Stale}} {{.StaleReason}} {{.Target}}", "./depBase") + AssertNotRebuilt(t, "new .a file before build", target) + cleanup := touch(t, target) + defer func() { + cleanup() + goCmd(t, "install", "-v", "-linkshared", "./exe") + }() + goCmd(t, "install", "-v", "-linkshared", "./exe") + AssertNotRebuilt(t, "new .a file", target) + AssertRebuilt(t, "new .a file", shlib) + }) +} + +func appendFile(t *testing.T, path, content string) { + t.Helper() + f, err := os.OpenFile(path, os.O_WRONLY|os.O_APPEND, 0660) + if err != nil { + t.Fatalf("os.OpenFile failed: %v", err) + } + defer func() { + err := f.Close() + if err != nil { + t.Fatalf("f.Close failed: %v", err) + } + }() + _, err = f.WriteString(content) + if err != nil { + t.Fatalf("f.WriteString failed: %v", err) + } +} + +func createFile(t *testing.T, path, content string) { + t.Helper() + f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644) + if err != nil { + t.Fatalf("os.OpenFile failed: %v", err) + } + _, err = f.WriteString(content) + if closeErr := f.Close(); err == nil { + err = closeErr + } + if err != nil { + t.Fatalf("WriteString failed: %v", err) + } +} + +func TestABIChecking(t *testing.T) { + goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase") + goCmd(t, "install", "-linkshared", "./exe") + + // If we make an ABI-breaking change to depBase and rebuild libp.so but not exe, + // exe will abort with a complaint on startup. + // This assumes adding an exported function breaks ABI, which is not true in + // some senses but suffices for the narrow definition of ABI compatibility the + // toolchain uses today. + resetFileStamps() + + createFile(t, "./depBase/break.go", "package depBase\nfunc ABIBreak() {}\n") + defer os.Remove("./depBase/break.go") + + goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase") + c := exec.Command("../../bin/exe") + output, err := c.CombinedOutput() + if err == nil { + t.Fatal("executing exe did not fail after ABI break") + } + scanner := bufio.NewScanner(bytes.NewReader(output)) + foundMsg := false + const wantPrefix = "abi mismatch detected between the executable and lib" + for scanner.Scan() { + if strings.HasPrefix(scanner.Text(), wantPrefix) { + foundMsg = true + break + } + } + if err = scanner.Err(); err != nil { + t.Errorf("scanner encountered error: %v", err) + } + if !foundMsg { + t.Fatalf("exe failed, but without line %q; got output:\n%s", wantPrefix, output) + } + + // Rebuilding exe makes it work again. + goCmd(t, "install", "-linkshared", "./exe") + run(t, "rebuilt exe", "../../bin/exe") + + // If we make a change which does not break ABI (such as adding an unexported + // function) and rebuild libdepBase.so, exe still works, even if new function + // is in a file by itself. + resetFileStamps() + createFile(t, "./depBase/dep2.go", "package depBase\nfunc noABIBreak() {}\n") + goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase") + run(t, "after non-ABI breaking change", "../../bin/exe") +} + +// If a package 'explicit' imports a package 'implicit', building +// 'explicit' into a shared library implicitly includes implicit in +// the shared library. Building an executable that imports both +// explicit and implicit builds the code from implicit into the +// executable rather than fetching it from the shared library. The +// link still succeeds and the executable still runs though. +func TestImplicitInclusion(t *testing.T) { + goCmd(t, "install", "-buildmode=shared", "-linkshared", "./explicit") + goCmd(t, "install", "-linkshared", "./implicitcmd") + run(t, "running executable linked against library that contains same package as it", "../../bin/implicitcmd") +} + +// Tests to make sure that the type fields of empty interfaces and itab +// fields of nonempty interfaces are unique even across modules, +// so that interface equality works correctly. +func TestInterface(t *testing.T) { + goCmd(t, "install", "-buildmode=shared", "-linkshared", "./iface_a") + // Note: iface_i gets installed implicitly as a dependency of iface_a. + goCmd(t, "install", "-buildmode=shared", "-linkshared", "./iface_b") + goCmd(t, "install", "-linkshared", "./iface") + run(t, "running type/itab uniqueness tester", "../../bin/iface") +} + +// Access a global variable from a library. +func TestGlobal(t *testing.T) { + goCmd(t, "install", "-buildmode=shared", "-linkshared", "./globallib") + goCmd(t, "install", "-linkshared", "./global") + run(t, "global executable", "../../bin/global") + AssertIsLinkedTo(t, "../../bin/global", soname) + AssertHasRPath(t, "../../bin/global", gorootInstallDir) +} + +// Run a test using -linkshared of an installed shared package. +// Issue 26400. +func TestTestInstalledShared(t *testing.T) { + goCmd(t, "test", "-linkshared", "-test.short", "sync/atomic") +} + +// Test generated pointer method with -linkshared. +// Issue 25065. +func TestGeneratedMethod(t *testing.T) { + goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue25065") +} + +// Test use of shared library struct with generated hash function. +// Issue 30768. +func TestGeneratedHash(t *testing.T) { + goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue30768/issue30768lib") + goCmd(t, "test", "-linkshared", "./issue30768") +} + +// Test that packages can be added not in dependency order (here a depends on b, and a adds +// before b). This could happen with e.g. go build -buildmode=shared std. See issue 39777. +func TestPackageOrder(t *testing.T) { + goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue39777/a", "./issue39777/b") +} + +// Test that GC data are generated correctly by the linker when it needs a type defined in +// a shared library. See issue 39927. +func TestGCData(t *testing.T) { + goCmd(t, "install", "-buildmode=shared", "-linkshared", "./gcdata/p") + goCmd(t, "build", "-linkshared", "./gcdata/main") + runWithEnv(t, "running gcdata/main", []string{"GODEBUG=clobberfree=1"}, "./main") +} + +// Test that we don't decode type symbols from shared libraries (which has no data, +// causing panic). See issue 44031. +func TestIssue44031(t *testing.T) { + goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue44031/a") + goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue44031/b") + goCmd(t, "run", "-linkshared", "./issue44031/main") +} + +// Test that we use a variable from shared libraries (which implement an +// interface in shared libraries.). A weak reference is used in the itab +// in main process. It can cause unreacheble panic. See issue 47873. +func TestIssue47873(t *testing.T) { + goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue47837/a") + goCmd(t, "run", "-linkshared", "./issue47837/main") +} diff --git a/misc/cgo/testshared/testdata/dep2/dep2.go b/misc/cgo/testshared/testdata/dep2/dep2.go new file mode 100644 index 0000000000..94f38cf507 --- /dev/null +++ b/misc/cgo/testshared/testdata/dep2/dep2.go @@ -0,0 +1,15 @@ +package dep2 + +import "testshared/depBase" + +var W int = 1 + +var hasProg depBase.HasProg + +type Dep2 struct { + depBase.Dep +} + +func G() int { + return depBase.F() + 1 +} diff --git a/misc/cgo/testshared/testdata/dep3/dep3.go b/misc/cgo/testshared/testdata/dep3/dep3.go new file mode 100644 index 0000000000..6b02ad2ee5 --- /dev/null +++ b/misc/cgo/testshared/testdata/dep3/dep3.go @@ -0,0 +1,22 @@ +package dep3 + +// The point of this test file is that it references a type from +// depBase that is also referenced in dep2, but dep2 is loaded by the +// linker before depBase (because it is earlier in the import list). +// There was a bug in the linker where it would not correctly read out +// the type data in this case and later crash. + +import ( + "testshared/dep2" + "testshared/depBase" +) + +type Dep3 struct { + dep depBase.Dep + dep2 dep2.Dep2 +} + +func D3() int { + var x Dep3 + return x.dep.X + x.dep2.X +} diff --git a/misc/cgo/testshared/testdata/depBase/asm.s b/misc/cgo/testshared/testdata/depBase/asm.s new file mode 100644 index 0000000000..0f1111f392 --- /dev/null +++ b/misc/cgo/testshared/testdata/depBase/asm.s @@ -0,0 +1,10 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build gc + +#include "textflag.h" + +TEXT ·ImplementedInAsm(SB),NOSPLIT,$0-0 + RET diff --git a/misc/cgo/testshared/testdata/depBase/dep.go b/misc/cgo/testshared/testdata/depBase/dep.go new file mode 100644 index 0000000000..e7cc7c81eb --- /dev/null +++ b/misc/cgo/testshared/testdata/depBase/dep.go @@ -0,0 +1,37 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package depBase + +import ( + "os" + "reflect" +) + +var SlicePtr interface{} = &[]int{} + +var V int = 1 + +var HasMask []string = []string{"hi"} + +type HasProg struct { + array [1024]*byte +} + +type Dep struct { + X int +} + +func (d *Dep) Method() int { + // This code below causes various go.itab.* symbols to be generated in + // the shared library. Similar code in ../exe/exe.go results in + // exercising https://golang.org/issues/17594 + reflect.TypeOf(os.Stdout).Elem() + return 10 +} + +func F() int { + defer func() {}() + return V +} diff --git a/misc/cgo/testshared/testdata/depBase/gccgo.go b/misc/cgo/testshared/testdata/depBase/gccgo.go new file mode 100644 index 0000000000..2b02a1e83b --- /dev/null +++ b/misc/cgo/testshared/testdata/depBase/gccgo.go @@ -0,0 +1,9 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build gccgo + +package depBase + +func ImplementedInAsm() {} diff --git a/misc/cgo/testshared/testdata/depBase/stubs.go b/misc/cgo/testshared/testdata/depBase/stubs.go new file mode 100644 index 0000000000..c77953803b --- /dev/null +++ b/misc/cgo/testshared/testdata/depBase/stubs.go @@ -0,0 +1,9 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build gc + +package depBase + +func ImplementedInAsm() diff --git a/misc/cgo/testshared/testdata/division/division.go b/misc/cgo/testshared/testdata/division/division.go new file mode 100644 index 0000000000..bb5fc98460 --- /dev/null +++ b/misc/cgo/testshared/testdata/division/division.go @@ -0,0 +1,17 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +//go:noinline +func div(x, y uint32) uint32 { + return x / y +} + +func main() { + a := div(97, 11) + if a != 8 { + panic("FAIL") + } +} diff --git a/misc/cgo/testshared/testdata/exe/exe.go b/misc/cgo/testshared/testdata/exe/exe.go new file mode 100644 index 0000000000..ee95f97bc9 --- /dev/null +++ b/misc/cgo/testshared/testdata/exe/exe.go @@ -0,0 +1,45 @@ +package main + +import ( + "os" + "reflect" + "runtime" + + "testshared/depBase" +) + +// Having a function declared in the main package triggered +// golang.org/issue/18250 +func DeclaredInMain() { +} + +type C struct { +} + +func F() *C { + return nil +} + +var slicePtr interface{} = &[]int{} + +func main() { + defer depBase.ImplementedInAsm() + // This code below causes various go.itab.* symbols to be generated in + // the executable. Similar code in ../depBase/dep.go results in + // exercising https://golang.org/issues/17594 + reflect.TypeOf(os.Stdout).Elem() + runtime.GC() + depBase.V = depBase.F() + 1 + + var c *C + if reflect.TypeOf(F).Out(0) != reflect.TypeOf(c) { + panic("bad reflection results, see golang.org/issue/18252") + } + + sp := reflect.New(reflect.TypeOf(slicePtr).Elem()) + s := sp.Interface() + + if reflect.TypeOf(s) != reflect.TypeOf(slicePtr) { + panic("bad reflection results, see golang.org/issue/18729") + } +} diff --git a/misc/cgo/testshared/testdata/exe2/exe2.go b/misc/cgo/testshared/testdata/exe2/exe2.go new file mode 100644 index 0000000000..433f331e36 --- /dev/null +++ b/misc/cgo/testshared/testdata/exe2/exe2.go @@ -0,0 +1,8 @@ +package main + +import "testshared/dep2" + +func main() { + d := &dep2.Dep2{} + dep2.W = dep2.G() + 1 + d.Method() +} diff --git a/misc/cgo/testshared/testdata/exe3/exe3.go b/misc/cgo/testshared/testdata/exe3/exe3.go new file mode 100644 index 0000000000..533e3a9e3d --- /dev/null +++ b/misc/cgo/testshared/testdata/exe3/exe3.go @@ -0,0 +1,7 @@ +package main + +import "testshared/dep3" + +func main() { + dep3.D3() +} diff --git a/misc/cgo/testshared/testdata/execgo/exe.go b/misc/cgo/testshared/testdata/execgo/exe.go new file mode 100644 index 0000000000..0427be8bdf --- /dev/null +++ b/misc/cgo/testshared/testdata/execgo/exe.go @@ -0,0 +1,8 @@ +package main + +/* + */ +import "C" + +func main() { +} diff --git a/misc/cgo/testshared/testdata/explicit/explicit.go b/misc/cgo/testshared/testdata/explicit/explicit.go new file mode 100644 index 0000000000..af969fcb23 --- /dev/null +++ b/misc/cgo/testshared/testdata/explicit/explicit.go @@ -0,0 +1,9 @@ +package explicit + +import ( + "testshared/implicit" +) + +func E() int { + return implicit.I() +} diff --git a/misc/cgo/testshared/testdata/gcdata/main/main.go b/misc/cgo/testshared/testdata/gcdata/main/main.go new file mode 100644 index 0000000000..394862fd94 --- /dev/null +++ b/misc/cgo/testshared/testdata/gcdata/main/main.go @@ -0,0 +1,37 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test that GC data is generated correctly for global +// variables with types defined in a shared library. +// See issue 39927. + +// This test run under GODEBUG=clobberfree=1. The check +// *x[i] == 12345 depends on this debug mode to clobber +// the value if the object is freed prematurely. + +package main + +import ( + "fmt" + "runtime" + "testshared/gcdata/p" +) + +var x p.T + +func main() { + for i := range x { + x[i] = new(int) + *x[i] = 12345 + } + runtime.GC() + runtime.GC() + runtime.GC() + for i := range x { + if *x[i] != 12345 { + fmt.Printf("x[%d] == %d, want 12345\n", i, *x[i]) + panic("FAIL") + } + } +} diff --git a/misc/cgo/testshared/testdata/gcdata/p/p.go b/misc/cgo/testshared/testdata/gcdata/p/p.go new file mode 100644 index 0000000000..1fee75429e --- /dev/null +++ b/misc/cgo/testshared/testdata/gcdata/p/p.go @@ -0,0 +1,7 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T [10]*int diff --git a/misc/cgo/testshared/testdata/global/main.go b/misc/cgo/testshared/testdata/global/main.go new file mode 100644 index 0000000000..f43e7c3fb3 --- /dev/null +++ b/misc/cgo/testshared/testdata/global/main.go @@ -0,0 +1,71 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "testshared/globallib" +) + +//go:noinline +func testLoop() { + for i, s := range globallib.Data { + if s != int64(i) { + panic("testLoop: mismatch") + } + } +} + +//go:noinline +func ptrData() *[1<<20 + 10]int64 { + return &globallib.Data +} + +//go:noinline +func testMediumOffset() { + for i, s := range globallib.Data[1<<16-2:] { + if s != int64(i)+1<<16-2 { + panic("testMediumOffset: index mismatch") + } + } + + x := globallib.Data[1<<16-1] + if x != 1<<16-1 { + panic("testMediumOffset: direct mismatch") + } + + y := &globallib.Data[1<<16-3] + if y != &ptrData()[1<<16-3] { + panic("testMediumOffset: address mismatch") + } +} + +//go:noinline +func testLargeOffset() { + for i, s := range globallib.Data[1<<20:] { + if s != int64(i)+1<<20 { + panic("testLargeOffset: index mismatch") + } + } + + x := globallib.Data[1<<20+1] + if x != 1<<20+1 { + panic("testLargeOffset: direct mismatch") + } + + y := &globallib.Data[1<<20+2] + if y != &ptrData()[1<<20+2] { + panic("testLargeOffset: address mismatch") + } +} + +func main() { + testLoop() + + // SSA rules commonly merge offsets into addresses. These + // tests access global data in different ways to try + // and exercise different SSA rules. + testMediumOffset() + testLargeOffset() +} diff --git a/misc/cgo/testshared/testdata/globallib/global.go b/misc/cgo/testshared/testdata/globallib/global.go new file mode 100644 index 0000000000..b4372a2e9e --- /dev/null +++ b/misc/cgo/testshared/testdata/globallib/global.go @@ -0,0 +1,17 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package globallib + +// Data is large enough to that offsets into it do not fit into +// 16-bit or 20-bit immediates. Ideally we'd also try and overrun +// 32-bit immediates, but that requires the test machine to have +// too much memory. +var Data [1<<20 + 10]int64 + +func init() { + for i := range Data { + Data[i] = int64(i) + } +} diff --git a/misc/cgo/testshared/testdata/iface/main.go b/misc/cgo/testshared/testdata/iface/main.go new file mode 100644 index 0000000000..d26ebbcc9c --- /dev/null +++ b/misc/cgo/testshared/testdata/iface/main.go @@ -0,0 +1,17 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "testshared/iface_a" +import "testshared/iface_b" + +func main() { + if iface_a.F() != iface_b.F() { + panic("empty interfaces not equal") + } + if iface_a.G() != iface_b.G() { + panic("non-empty interfaces not equal") + } +} diff --git a/misc/cgo/testshared/testdata/iface_a/a.go b/misc/cgo/testshared/testdata/iface_a/a.go new file mode 100644 index 0000000000..e2cef1ecda --- /dev/null +++ b/misc/cgo/testshared/testdata/iface_a/a.go @@ -0,0 +1,17 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package iface_a + +import "testshared/iface_i" + +//go:noinline +func F() interface{} { + return (*iface_i.T)(nil) +} + +//go:noinline +func G() iface_i.I { + return (*iface_i.T)(nil) +} diff --git a/misc/cgo/testshared/testdata/iface_b/b.go b/misc/cgo/testshared/testdata/iface_b/b.go new file mode 100644 index 0000000000..dd3e027b37 --- /dev/null +++ b/misc/cgo/testshared/testdata/iface_b/b.go @@ -0,0 +1,17 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package iface_b + +import "testshared/iface_i" + +//go:noinline +func F() interface{} { + return (*iface_i.T)(nil) +} + +//go:noinline +func G() iface_i.I { + return (*iface_i.T)(nil) +} diff --git a/misc/cgo/testshared/testdata/iface_i/i.go b/misc/cgo/testshared/testdata/iface_i/i.go new file mode 100644 index 0000000000..31c80387c7 --- /dev/null +++ b/misc/cgo/testshared/testdata/iface_i/i.go @@ -0,0 +1,17 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package iface_i + +type I interface { + M() +} + +type T struct { +} + +func (t *T) M() { +} + +// *T implements I diff --git a/misc/cgo/testshared/testdata/implicit/implicit.go b/misc/cgo/testshared/testdata/implicit/implicit.go new file mode 100644 index 0000000000..5360188c56 --- /dev/null +++ b/misc/cgo/testshared/testdata/implicit/implicit.go @@ -0,0 +1,5 @@ +package implicit + +func I() int { + return 42 +} diff --git a/misc/cgo/testshared/testdata/implicitcmd/implicitcmd.go b/misc/cgo/testshared/testdata/implicitcmd/implicitcmd.go new file mode 100644 index 0000000000..4d4296738e --- /dev/null +++ b/misc/cgo/testshared/testdata/implicitcmd/implicitcmd.go @@ -0,0 +1,10 @@ +package main + +import ( + "testshared/explicit" + "testshared/implicit" +) + +func main() { + println(implicit.I() + explicit.E()) +} diff --git a/misc/cgo/testshared/testdata/issue25065/a.go b/misc/cgo/testshared/testdata/issue25065/a.go new file mode 100644 index 0000000000..979350ff24 --- /dev/null +++ b/misc/cgo/testshared/testdata/issue25065/a.go @@ -0,0 +1,20 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package issue25065 has a type with a method that is +// 1) referenced in a method expression +// 2) not called +// 3) not converted to an interface +// 4) is a value method but the reference is to the pointer method +// These cases avoid the call to makefuncsym from typecheckfunc, but we +// still need to call makefuncsym somehow or the symbol will not be defined. +package issue25065 + +type T int + +func (t T) M() {} + +func F() func(*T) { + return (*T).M +} diff --git a/misc/cgo/testshared/testdata/issue30768/issue30768lib/lib.go b/misc/cgo/testshared/testdata/issue30768/issue30768lib/lib.go new file mode 100644 index 0000000000..9e45ebe683 --- /dev/null +++ b/misc/cgo/testshared/testdata/issue30768/issue30768lib/lib.go @@ -0,0 +1,11 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package issue30768lib + +// S is a struct that requires a generated hash function. +type S struct { + A string + B int +} diff --git a/misc/cgo/testshared/testdata/issue30768/x_test.go b/misc/cgo/testshared/testdata/issue30768/x_test.go new file mode 100644 index 0000000000..1bbd139d3e --- /dev/null +++ b/misc/cgo/testshared/testdata/issue30768/x_test.go @@ -0,0 +1,22 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package issue30768_test + +import ( + "testing" + + "testshared/issue30768/issue30768lib" +) + +type s struct { + s issue30768lib.S +} + +func Test30768(t *testing.T) { + // Calling t.Log will convert S to an empty interface, + // which will force a reference to the generated hash function, + // defined in the shared library. + t.Log(s{}) +} diff --git a/misc/cgo/testshared/testdata/issue39777/a/a.go b/misc/cgo/testshared/testdata/issue39777/a/a.go new file mode 100644 index 0000000000..c7bf835951 --- /dev/null +++ b/misc/cgo/testshared/testdata/issue39777/a/a.go @@ -0,0 +1,9 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +import "testshared/issue39777/b" + +func F() { b.F() } diff --git a/misc/cgo/testshared/testdata/issue39777/b/b.go b/misc/cgo/testshared/testdata/issue39777/b/b.go new file mode 100644 index 0000000000..4e681965e6 --- /dev/null +++ b/misc/cgo/testshared/testdata/issue39777/b/b.go @@ -0,0 +1,7 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package b + +func F() {} diff --git a/misc/cgo/testshared/testdata/issue44031/a/a.go b/misc/cgo/testshared/testdata/issue44031/a/a.go new file mode 100644 index 0000000000..48827e682f --- /dev/null +++ b/misc/cgo/testshared/testdata/issue44031/a/a.go @@ -0,0 +1,9 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type ATypeWithALoooooongName interface { // a long name, so the type descriptor symbol name is mangled + M() +} diff --git a/misc/cgo/testshared/testdata/issue44031/b/b.go b/misc/cgo/testshared/testdata/issue44031/b/b.go new file mode 100644 index 0000000000..ad3ebec2b9 --- /dev/null +++ b/misc/cgo/testshared/testdata/issue44031/b/b.go @@ -0,0 +1,17 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package b + +import "testshared/issue44031/a" + +type T int + +func (T) M() {} + +var i = a.ATypeWithALoooooongName(T(0)) + +func F() { + i.M() +} diff --git a/misc/cgo/testshared/testdata/issue44031/main/main.go b/misc/cgo/testshared/testdata/issue44031/main/main.go new file mode 100644 index 0000000000..47f2e3a98e --- /dev/null +++ b/misc/cgo/testshared/testdata/issue44031/main/main.go @@ -0,0 +1,20 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "testshared/issue44031/b" + +type t int + +func (t) m() {} + +type i interface{ m() } // test that unexported method is correctly marked + +var v interface{} = t(0) + +func main() { + b.F() + v.(i).m() +} diff --git a/misc/cgo/testshared/testdata/issue47837/a/a.go b/misc/cgo/testshared/testdata/issue47837/a/a.go new file mode 100644 index 0000000000..68588eda2f --- /dev/null +++ b/misc/cgo/testshared/testdata/issue47837/a/a.go @@ -0,0 +1,19 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type A interface { + M() +} + +//go:noinline +func TheFuncWithArgA(a A) { + a.M() +} + +type ImplA struct{} + +//go:noinline +func (A *ImplA) M() {} diff --git a/misc/cgo/testshared/testdata/issue47837/main/main.go b/misc/cgo/testshared/testdata/issue47837/main/main.go new file mode 100644 index 0000000000..77c6f34379 --- /dev/null +++ b/misc/cgo/testshared/testdata/issue47837/main/main.go @@ -0,0 +1,14 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "testshared/issue47837/a" +) + +func main() { + var vara a.ImplA + a.TheFuncWithArgA(&vara) +} diff --git a/misc/cgo/testshared/testdata/trivial/trivial.go b/misc/cgo/testshared/testdata/trivial/trivial.go new file mode 100644 index 0000000000..6ade47ce36 --- /dev/null +++ b/misc/cgo/testshared/testdata/trivial/trivial.go @@ -0,0 +1,9 @@ +package main + +func main() { + // This is enough to make sure that the executable references + // a type descriptor, which was the cause of + // https://golang.org/issue/25970. + c := make(chan int) + _ = c +} diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index 87238cc74f..5935011e19 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -762,6 +762,9 @@ func (t *tester) registerTests() { if t.supportedBuildmode("c-shared") { t.registerHostTest("testcshared", "../misc/cgo/testcshared", "misc/cgo/testcshared", ".") } + if t.supportedBuildmode("shared") { + t.registerTest("testshared", "../misc/cgo/testshared", t.goTest(), t.timeout(600), ".") + } if t.supportedBuildmode("plugin") { t.registerTest("testplugin", "../misc/cgo/testplugin", t.goTest(), t.timeout(600), ".") } @@ -1044,6 +1047,12 @@ func (t *tester) supportedBuildmode(mode string) bool { return true } return false + case "shared": + switch pair { + case "linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le", "linux-s390x": + return true + } + return false case "plugin": // linux-arm64 is missing because it causes the external linker // to crash, see https://golang.org/issue/17138 diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 1b9b22a812..487a8f580b 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -162,6 +162,9 @@ // flags has a similar effect. // -ldflags '[pattern=]arg list' // arguments to pass on each go tool link invocation. +// -linkshared +// build code that will be linked against shared libraries previously +// created with -buildmode=shared. // -mod mode // module download mode to use: readonly, vendor, or mod. // By default, if a vendor directory is present and the go version in go.mod @@ -779,6 +782,7 @@ // Name string // package name // Doc string // package documentation string // Target string // install path +// Shlib string // the shared library that contains this package (only set when -linkshared) // Goroot bool // is this package in the Go root? // Standard bool // is this package part of the standard Go library? // Stale bool // would 'go install' do anything for this package? @@ -1799,6 +1803,11 @@ // non-main packages are built into .a files (the default // behavior). // +// -buildmode=shared +// Combine all the listed non-main packages into a single shared +// library that will be used when building with the -linkshared +// option. Packages named main are ignored. +// // -buildmode=exe // Build the listed main packages and everything they import into // executables. Packages not named main are ignored. diff --git a/src/cmd/go/internal/help/helpdoc.go b/src/cmd/go/internal/help/helpdoc.go index 2bb3584eba..035235fe1b 100644 --- a/src/cmd/go/internal/help/helpdoc.go +++ b/src/cmd/go/internal/help/helpdoc.go @@ -726,6 +726,11 @@ are: non-main packages are built into .a files (the default behavior). + -buildmode=shared + Combine all the listed non-main packages into a single shared + library that will be used when building with the -linkshared + option. Packages named main are ignored. + -buildmode=exe Build the listed main packages and everything they import into executables. Packages not named main are ignored. diff --git a/src/cmd/go/internal/list/list.go b/src/cmd/go/internal/list/list.go index f23fbe5fea..8c85ddcf21 100644 --- a/src/cmd/go/internal/list/list.go +++ b/src/cmd/go/internal/list/list.go @@ -23,8 +23,8 @@ import ( "cmd/go/internal/load" "cmd/go/internal/modinfo" "cmd/go/internal/modload" - "cmd/go/internal/str" "cmd/go/internal/work" + "cmd/go/internal/str" ) var CmdList = &base.Command{ @@ -56,6 +56,7 @@ to -f '{{.ImportPath}}'. The struct being passed to the template is: Name string // package name Doc string // package documentation string Target string // install path + Shlib string // the shared library that contains this package (only set when -linkshared) Goroot bool // is this package in the Go root? Standard bool // is this package part of the standard Go library? Stale bool // would 'go install' do anything for this package? diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go index e39ffcbd50..9d0ad27f0d 100644 --- a/src/cmd/go/internal/work/build.go +++ b/src/cmd/go/internal/work/build.go @@ -116,6 +116,9 @@ and test commands: flags has a similar effect. -ldflags '[pattern=]arg list' arguments to pass on each go tool link invocation. + -linkshared + build code that will be linked against shared libraries previously + created with -buildmode=shared. -mod mode module download mode to use: readonly, vendor, or mod. By default, if a vendor directory is present and the go version in go.mod diff --git a/src/cmd/go/internal/work/init.go b/src/cmd/go/internal/work/init.go index 9111150233..dc368de1c1 100644 --- a/src/cmd/go/internal/work/init.go +++ b/src/cmd/go/internal/work/init.go @@ -233,20 +233,16 @@ func buildModeInit() { } ldBuildmode = "pie" case "shared": - if cfg.Goos == "linux" { - switch cfg.Goarch { - case "386", "amd64", "arm", "arm64", "ppc64le", "s390x": - // -buildmode=shared was supported on these platforms at one point, but - // never really worked in module mode. - // Support was officially dropped as of Go 1.18. - // (See https://golang.org/issue/47788.) - base.Fatalf("-buildmode=shared no longer supported as of Go 1.18") - - // TODO(#47788): Remove supporting code for -buildmode=shared. - // (For the Go 1.18 release, we will keep most of the code around but - // disabled to avoid merge conflicts in case we need to revert quickly.) - } + pkgsFilter = pkgsNotMain + if gccgo { + codegenArg = "-fPIC" + } else { + codegenArg = "-dynlink" + } + if cfg.BuildO != "" { + base.Fatalf("-buildmode=shared and -o not supported together") } + ldBuildmode = "shared" case "plugin": pkgsFilter = oneMainPkg if gccgo { @@ -265,15 +261,6 @@ func buildModeInit() { } if cfg.BuildLinkshared { - if cfg.Goos == "linux" { - switch cfg.Goarch { - case "386", "amd64", "arm", "arm64", "ppc64le", "s390x": - base.Fatalf("-linkshared no longer supported as of Go 1.18") - // TODO(#47788): Remove supporting code for linkshared. - // (For the Go 1.18 release, we will keep most of the code around but - // disabled to avoid merge conflicts in case we need to revert quickly.) - } - } if !sys.BuildModeSupported(cfg.BuildToolchainName, "shared", cfg.Goos, cfg.Goarch) { base.Fatalf("-linkshared not supported on %s/%s\n", cfg.Goos, cfg.Goarch) } diff --git a/src/cmd/go/testdata/script/list_linkshared.txt b/src/cmd/go/testdata/script/list_linkshared.txt new file mode 100644 index 0000000000..baae1e2be8 --- /dev/null +++ b/src/cmd/go/testdata/script/list_linkshared.txt @@ -0,0 +1,16 @@ +env GO111MODULE=on + +# golang.org/issue/35759: 'go list -linkshared' +# panicked if invoked on a test-only package. + +[!buildmode:shared] skip + +go list -f '{{.ImportPath}}: {{.Target}} {{.Shlib}}' -linkshared . +stdout '^example.com: $' + +-- go.mod -- +module example.com + +go 1.14 +-- x.go -- +package x diff --git a/src/cmd/internal/sys/supported.go b/src/cmd/internal/sys/supported.go index 18ca50f927..4fa5aa495e 100644 --- a/src/cmd/internal/sys/supported.go +++ b/src/cmd/internal/sys/supported.go @@ -132,6 +132,13 @@ func BuildModeSupported(compiler, buildmode, goos, goarch string) bool { } return false + case "shared": + switch platform { + case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x": + return true + } + return false + case "plugin": switch platform { case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/s390x", "linux/ppc64le", -- GitLab From d8fc7f785e84515c0a5beb8baeb3c1ca35bebf68 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Thu, 28 Oct 2021 17:52:22 +0000 Subject: [PATCH 1819/2500] runtime: clean up allocation zeroing Currently, the runtime zeroes allocations in several ways. First, small object spans are always zeroed if they come from mheap, and their slots are zeroed later in mallocgc if needed. Second, large object spans (objects that have their own spans) plumb the need for zeroing down into mheap. Thirdly, large objects that have no pointers have their zeroing delayed until after preemption is reenabled, but before returning in mallocgc. All of this has two consequences: 1. Spans for small objects that come from mheap are sometimes unnecessarily zeroed, even if the mallocgc call that created them doesn't need the object slot to be zeroed. 2. This is all messy and difficult to reason about. This CL simplifies this code, resolving both (1) and (2). First, it recognizes that zeroing in mheap is unnecessary for small object spans; mallocgc and its callees in mcache and mcentral, by design, are *always* able to deal with non-zeroed spans. They must, for they deal with recycled spans all the time. Once this fact is made clear, the only remaining use of zeroing in mheap is for large objects. As a result, this CL lifts mheap zeroing for large objects into mallocgc, to parallel all the other codepaths in mallocgc. This is makes the large object allocation code less surprising. Next, this CL sets the flag for the delayed zeroing explicitly in the one case where it matters, and inverts and renames the flag from isZeroed to delayZeroing. Finally, it adds a check to make sure that only pointer-free allocations take the delayed zeroing codepath, as an extra safety measure. Benchmark results: https://perf.golang.org/search?q=upload:20211028.8 Inspired by tapir.liu@gmail.com's CL 343470. Change-Id: I7e1296adc19ce8a02c8d93a0a5082aefb2673e8f Reviewed-on: https://go-review.googlesource.com/c/go/+/359477 Trust: Michael Knyszek Reviewed-by: David Chase --- src/runtime/malloc.go | 25 ++++++++++++++++++++----- src/runtime/mcache.go | 9 +++------ src/runtime/mcentral.go | 2 +- src/runtime/mheap.go | 21 +++++---------------- 4 files changed, 29 insertions(+), 28 deletions(-) diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index c389cb1e45..8af1d96f1a 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -980,8 +980,8 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { var x unsafe.Pointer noscan := typ == nil || typ.ptrdata == 0 // In some cases block zeroing can profitably (for latency reduction purposes) - // be delayed till preemption is possible; isZeroed tracks that state. - isZeroed := true + // be delayed till preemption is possible; delayedZeroing tracks that state. + delayedZeroing := false if size <= maxSmallSize { if noscan && size < maxTinySize { // Tiny allocator. @@ -1079,11 +1079,23 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { shouldhelpgc = true // For large allocations, keep track of zeroed state so that // bulk zeroing can be happen later in a preemptible context. - span, isZeroed = c.allocLarge(size, needzero && !noscan, noscan) + span = c.allocLarge(size, noscan) span.freeindex = 1 span.allocCount = 1 - x = unsafe.Pointer(span.base()) size = span.elemsize + x = unsafe.Pointer(span.base()) + if needzero && span.needzero != 0 { + if noscan { + delayedZeroing = true + } else { + memclrNoHeapPointers(x, size) + // We've in theory cleared almost the whole span here, + // and could take the extra step of actually clearing + // the whole thing. However, don't. Any GC bits for the + // uncleared parts will be zero, and it's just going to + // be needzero = 1 once freed anyway. + } + } } var scanSize uintptr @@ -1139,7 +1151,10 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { // Pointerfree data can be zeroed late in a context where preemption can occur. // x will keep the memory alive. - if !isZeroed && needzero { + if delayedZeroing { + if !noscan { + throw("delayed zeroing on data that may contain pointers") + } memclrNoHeapPointersChunked(size, x) // This is a possible preemption point: see #47302 } diff --git a/src/runtime/mcache.go b/src/runtime/mcache.go index 21c36ca750..52bb944cdd 100644 --- a/src/runtime/mcache.go +++ b/src/runtime/mcache.go @@ -206,10 +206,7 @@ func (c *mcache) refill(spc spanClass) { } // allocLarge allocates a span for a large object. -// The boolean result indicates whether the span is known-zeroed. -// If it did not need to be zeroed, it may not have been zeroed; -// but if it came directly from the OS, it is already zeroed. -func (c *mcache) allocLarge(size uintptr, needzero bool, noscan bool) (*mspan, bool) { +func (c *mcache) allocLarge(size uintptr, noscan bool) *mspan { if size+_PageSize < size { throw("out of memory") } @@ -224,7 +221,7 @@ func (c *mcache) allocLarge(size uintptr, needzero bool, noscan bool) (*mspan, b deductSweepCredit(npages*_PageSize, npages) spc := makeSpanClass(0, noscan) - s, isZeroed := mheap_.alloc(npages, spc, needzero) + s := mheap_.alloc(npages, spc) if s == nil { throw("out of memory") } @@ -248,7 +245,7 @@ func (c *mcache) allocLarge(size uintptr, needzero bool, noscan bool) (*mspan, b mheap_.central[spc].mcentral.fullSwept(mheap_.sweepgen).push(s) s.limit = s.base() + size heapBitsForAddr(s.base()).initSpan(s) - return s, isZeroed + return s } func (c *mcache) releaseAll() { diff --git a/src/runtime/mcentral.go b/src/runtime/mcentral.go index 0a871a611e..4ae3a883a4 100644 --- a/src/runtime/mcentral.go +++ b/src/runtime/mcentral.go @@ -241,7 +241,7 @@ func (c *mcentral) grow() *mspan { npages := uintptr(class_to_allocnpages[c.spanclass.sizeclass()]) size := uintptr(class_to_size[c.spanclass.sizeclass()]) - s, _ := mheap_.alloc(npages, c.spanclass, true) + s := mheap_.alloc(npages, c.spanclass) if s == nil { return nil } diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go index 4f32e888b2..5fd036c1b3 100644 --- a/src/runtime/mheap.go +++ b/src/runtime/mheap.go @@ -894,10 +894,9 @@ func (s spanAllocType) manual() bool { // // spanclass indicates the span's size class and scannability. // -// If needzero is true, the memory for the returned span will be zeroed. -// The boolean returned indicates whether the returned span contains zeroes, -// either because this was requested, or because it was already zeroed. -func (h *mheap) alloc(npages uintptr, spanclass spanClass, needzero bool) (*mspan, bool) { +// Returns a span that has been fully initialized. span.needzero indicates +// whether the span has been zeroed. Note that it may not be. +func (h *mheap) alloc(npages uintptr, spanclass spanClass) *mspan { // Don't do any operations that lock the heap on the G stack. // It might trigger stack growth, and the stack growth code needs // to be able to allocate heap. @@ -910,17 +909,7 @@ func (h *mheap) alloc(npages uintptr, spanclass spanClass, needzero bool) (*mspa } s = h.allocSpan(npages, spanAllocHeap, spanclass) }) - - if s == nil { - return nil, false - } - isZeroed := s.needzero == 0 - if needzero && !isZeroed { - memclrNoHeapPointers(unsafe.Pointer(s.base()), s.npages<<_PageShift) - isZeroed = true - } - s.needzero = 0 - return s, isZeroed + return s } // allocManual allocates a manually-managed span of npage pages. @@ -1009,7 +998,7 @@ func (h *mheap) allocNeedsZero(base, npage uintptr) (needZero bool) { break } zeroedBase = atomic.Loaduintptr(&ha.zeroedBase) - // Sanity check zeroedBase. + // Double check basic conditions of zeroedBase. if zeroedBase <= arenaLimit && zeroedBase > arenaBase { // The zeroedBase moved into the space we were trying to // claim. That's very bad, and indicates someone allocated -- GitLab From 353d5b6c536c7028eba058ba27014fae0206298a Mon Sep 17 00:00:00 2001 From: Zhi Zheng Date: Mon, 5 Apr 2021 16:00:07 -0700 Subject: [PATCH 1820/2500] runtime: enable crash dump creation on Windows This change provides ability to create dumps on Windows that can be used by "dlv core" command. Currently only full dumps can be correctly read by Delve. Below are the steps to create and use the dumps. 1. Configure Windows OS to collect dumps before running the program. Instructions on how to do the configuration are here: https://docs.microsoft.com/en-us/windows/win32/wer/collecting-user-mode-dumps. In order for Delve to read the dump, set the DumpType to full dump, i.e. DumpType=2. 2. Go program only generates dumps when the environment variable GOTRACEBACK is set to crash. Run command "set GOTRACEBACK=crash" before running the program. 3. Dump files will be generated in %LOCALAPPDATA%\CrashDumps 4. Use Delve command "dlv core" to open the dump, e.g.: "dlv core a.exe a.exe.3840.dmp". Fixes #20498 Change-Id: Ib9aa82e7aea9da19594dc49348876997b24e9600 Reviewed-on: https://go-review.googlesource.com/c/go/+/307372 Run-TryBot: Alessandro Arzilli TryBot-Result: Go Bot Reviewed-by: Patrik Nyblom Trust: Alex Brainman --- src/runtime/os_windows.go | 4 ++ src/runtime/panic.go | 11 ++++++ src/runtime/signal_windows.go | 74 ++++++++++++++++++++++++----------- 3 files changed, 67 insertions(+), 22 deletions(-) diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go index 648239fb36..0e17e75e3e 100644 --- a/src/runtime/os_windows.go +++ b/src/runtime/os_windows.go @@ -40,6 +40,7 @@ const ( //go:cgo_import_dynamic runtime._LoadLibraryW LoadLibraryW%1 "kernel32.dll" //go:cgo_import_dynamic runtime._LoadLibraryA LoadLibraryA%1 "kernel32.dll" //go:cgo_import_dynamic runtime._PostQueuedCompletionStatus PostQueuedCompletionStatus%4 "kernel32.dll" +//go:cgo_import_dynamic runtime._RaiseException RaiseException%4 "kernel32.dll" //go:cgo_import_dynamic runtime._ResumeThread ResumeThread%1 "kernel32.dll" //go:cgo_import_dynamic runtime._SetConsoleCtrlHandler SetConsoleCtrlHandler%2 "kernel32.dll" //go:cgo_import_dynamic runtime._SetErrorMode SetErrorMode%1 "kernel32.dll" @@ -93,6 +94,7 @@ var ( _PostQueuedCompletionStatus, _QueryPerformanceCounter, _QueryPerformanceFrequency, + _RaiseException, _ResumeThread, _SetConsoleCtrlHandler, _SetErrorMode, @@ -120,6 +122,7 @@ var ( _AddVectoredContinueHandler, _LoadLibraryExA, _LoadLibraryExW, + _WerSetFlags, _ stdFunction // Use RtlGenRandom to generate cryptographically random data. @@ -254,6 +257,7 @@ func loadOptionalSyscalls() { _AddVectoredContinueHandler = windowsFindfunc(k32, []byte("AddVectoredContinueHandler\000")) _LoadLibraryExA = windowsFindfunc(k32, []byte("LoadLibraryExA\000")) _LoadLibraryExW = windowsFindfunc(k32, []byte("LoadLibraryExW\000")) + _WerSetFlags = windowsFindfunc(k32, []byte("WerSetFlags\000")) useLoadLibraryEx = (_LoadLibraryExW != nil && _LoadLibraryExA != nil && _AddDllDirectory != nil) var advapi32dll = []byte("advapi32.dll\000") diff --git a/src/runtime/panic.go b/src/runtime/panic.go index c4f3f41ff5..58135cf8ce 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -975,6 +975,11 @@ var runningPanicDefers uint32 // panicking is incremented and decremented atomically. var panicking uint32 +// tracebackprinted is zero before gopanic() prints the traceback. After +// traceback is printed, it sets to 1 so that the subsequent exception handler +// won't print the traceback again. +var tracebackprinted uint32 + // paniclk is held while printing the panic information and stack trace, // so that two concurrent panics don't overlap their output. var paniclk mutex @@ -1018,6 +1023,9 @@ func fatalthrow() { startpanic_m() if dopanic_m(gp, pc, sp) { + // At this point, traceback has already been printed. + // Set tracebackprinted to 1 to avoid printing traceback again + tracebackprinted = 1 // crash uses a decent amount of nosplit stack and we're already // low on stack in throw, so crash on the system stack (unlike // fatalpanic). @@ -1059,6 +1067,9 @@ func fatalpanic(msgs *_panic) { }) if docrash { + // At this point, traceback has already been printed. + // Set tracebackprinted to 1 to avoid printing traceback again + tracebackprinted = 1 // By crashing outside the above systemstack call, debuggers // will not be confused when generating a backtrace. // Function crash is marked nosplit to avoid stack growth. diff --git a/src/runtime/signal_windows.go b/src/runtime/signal_windows.go index 16c36d07f1..ca4a9ea451 100644 --- a/src/runtime/signal_windows.go +++ b/src/runtime/signal_windows.go @@ -22,6 +22,30 @@ func disableWER() { stdcall1(_SetErrorMode, uintptr(errormode)|SEM_FAILCRITICALERRORS|SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX) } +// enableWERNoUI re-enables Windows error reporting without fault reporting UI. +// It returns false on older Windows versions (XP and earlier) where WerSetFlags() is not supported. +// +// This is marked nosplit since it is used during crash. +// +//go:nosplit +func enableWERNoUI() bool { + if _WerSetFlags == nil { + return false + } + + // Disable Fault reporting UI + const ( + WER_FAULT_REPORTING_NO_UI = 0x0020 + ) + if stdcall1(_WerSetFlags, WER_FAULT_REPORTING_NO_UI) != 0 { + return false + } + + // re-enable Windows Error Reporting + stdcall1(_SetErrorMode, 0) + return true +} + // in sys_windows_386.s and sys_windows_amd64.s func exceptiontramp() func firstcontinuetramp() @@ -108,6 +132,7 @@ func exceptionhandler(info *exceptionrecord, r *context, gp *g) int32 { // Don't go through any more of the Windows handler chain. // Crash now. winthrow(info, r, gp) + exit(2) } // After this point, it is safe to grow the stack. @@ -196,6 +221,15 @@ func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 { } winthrow(info, r, gp) + + _, _, docrash := gotraceback() + if docrash { + // trigger crash dump creation + if enableWERNoUI() { + return _EXCEPTION_CONTINUE_SEARCH + } + } + exit(2) return 0 // not reached } @@ -203,11 +237,6 @@ func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 { func winthrow(info *exceptionrecord, r *context, gp *g) { _g_ := getg() - if panicking != 0 { // traceback already printed - exit(2) - } - panicking = 1 - // In case we're handling a g0 stack overflow, blow away the // g0 stack bounds so we have room to print the traceback. If // this somehow overflows the stack, the OS will trap it. @@ -229,18 +258,16 @@ func winthrow(info *exceptionrecord, r *context, gp *g) { _g_.m.throwing = 1 _g_.m.caughtsig.set(gp) - level, _, docrash := gotraceback() + level, _, _ := gotraceback() if level > 0 { - tracebacktrap(r.ip(), r.sp(), r.lr(), gp) - tracebackothers(gp) + // only print traceback when it hasn't been printed + if tracebackprinted == 0 { + tracebacktrap(r.ip(), r.sp(), r.lr(), gp) + tracebackothers(gp) + tracebackprinted = 1 + } dumpregs(r) } - - if docrash { - crash() - } - - exit(2) } func sigpanic() { @@ -312,14 +339,17 @@ func signame(sig uint32) string { //go:nosplit func crash() { - // TODO: This routine should do whatever is needed - // to make the Windows program abort/crash as it - // would if Go was not intercepting signals. - // On Unix the routine would remove the custom signal - // handler and then raise a signal (like SIGABRT). - // Something like that should happen here. - // It's okay to leave this empty for now: if crash returns - // the ordinary exit-after-panic happens. + // When GOTRACEBACK==crash, raise the same exception + // from kernel32.dll, so that Windows gets a chance + // to handle the exception by creating a crash dump. + + // Get the Exception code that caused the crash + gp := getg() + exceptionCode := gp.sig + + // RaiseException() here will not be handled in exceptionhandler() + // because it comes from kernel32.dll + stdcall4(_RaiseException, uintptr(unsafe.Pointer(&exceptionCode)), 0, 0, 0) } // gsignalStack is unused on Windows. -- GitLab From 413672fc84e0ced7531cdc7cf0e5db32061e8194 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Sun, 11 Apr 2021 18:37:52 +0000 Subject: [PATCH 1821/2500] runtime: detangle sweeper pacing from GC pacing The sweeper's pacing state is global, so detangle it from the GC pacer's state updates so that the GC pacer can be tested. For #44167. Change-Id: Ibcea989cd435b73c5891f777d9f95f9604e03bd1 Reviewed-on: https://go-review.googlesource.com/c/go/+/309273 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Michael Pratt --- src/runtime/mgc.go | 1 + src/runtime/mgcpacer.go | 35 +-------------------------------- src/runtime/mgcsweep.go | 43 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 34 deletions(-) diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go index e7c023919c..b2ed18fe6a 100644 --- a/src/runtime/mgc.go +++ b/src/runtime/mgc.go @@ -971,6 +971,7 @@ func gcMarkTermination(nextTriggerRatio float64) { // Update GC trigger and pacing for the next cycle. gcController.commit(nextTriggerRatio) + gcPaceSweeper(gcController.trigger) gcPaceScavenger(gcController.heapGoal, gcController.lastHeapGoal) // Update timing memstats diff --git a/src/runtime/mgcpacer.go b/src/runtime/mgcpacer.go index 73fe6e15e4..980cb2f086 100644 --- a/src/runtime/mgcpacer.go +++ b/src/runtime/mgcpacer.go @@ -735,40 +735,6 @@ func (c *gcControllerState) commit(triggerRatio float64) { if gcphase != _GCoff { c.revise() } - - // Update sweep pacing. - if isSweepDone() { - mheap_.sweepPagesPerByte = 0 - } else { - // Concurrent sweep needs to sweep all of the in-use - // pages by the time the allocated heap reaches the GC - // trigger. Compute the ratio of in-use pages to sweep - // per byte allocated, accounting for the fact that - // some might already be swept. - heapLiveBasis := atomic.Load64(&c.heapLive) - heapDistance := int64(trigger) - int64(heapLiveBasis) - // Add a little margin so rounding errors and - // concurrent sweep are less likely to leave pages - // unswept when GC starts. - heapDistance -= 1024 * 1024 - if heapDistance < _PageSize { - // Avoid setting the sweep ratio extremely high - heapDistance = _PageSize - } - pagesSwept := mheap_.pagesSwept.Load() - pagesInUse := mheap_.pagesInUse.Load() - sweepDistancePages := int64(pagesInUse) - int64(pagesSwept) - if sweepDistancePages <= 0 { - mheap_.sweepPagesPerByte = 0 - } else { - mheap_.sweepPagesPerByte = float64(sweepDistancePages) / float64(heapDistance) - mheap_.sweepHeapLiveBasis = heapLiveBasis - // Write pagesSweptBasis last, since this - // signals concurrent sweeps to recompute - // their debt. - mheap_.pagesSweptBasis.Store(pagesSwept) - } - } } // effectiveGrowthRatio returns the current effective heap growth @@ -819,6 +785,7 @@ func setGCPercent(in int32) (out int32) { systemstack(func() { lock(&mheap_.lock) out = gcController.setGCPercent(in) + gcPaceSweeper(gcController.trigger) gcPaceScavenger(gcController.heapGoal, gcController.lastHeapGoal) unlock(&mheap_.lock) }) diff --git a/src/runtime/mgcsweep.go b/src/runtime/mgcsweep.go index a431d8a2af..b06df32b20 100644 --- a/src/runtime/mgcsweep.go +++ b/src/runtime/mgcsweep.go @@ -830,3 +830,46 @@ func clobberfree(x unsafe.Pointer, size uintptr) { *(*uint32)(add(x, i)) = 0xdeadbeef } } + +// gcPaceSweeper updates the sweeper's pacing parameters. +// +// Must be called whenever the GC's pacing is updated. +// +// The world must be stopped, or mheap_.lock must be held. +func gcPaceSweeper(trigger uint64) { + assertWorldStoppedOrLockHeld(&mheap_.lock) + + // Update sweep pacing. + if isSweepDone() { + mheap_.sweepPagesPerByte = 0 + } else { + // Concurrent sweep needs to sweep all of the in-use + // pages by the time the allocated heap reaches the GC + // trigger. Compute the ratio of in-use pages to sweep + // per byte allocated, accounting for the fact that + // some might already be swept. + heapLiveBasis := atomic.Load64(&gcController.heapLive) + heapDistance := int64(trigger) - int64(heapLiveBasis) + // Add a little margin so rounding errors and + // concurrent sweep are less likely to leave pages + // unswept when GC starts. + heapDistance -= 1024 * 1024 + if heapDistance < _PageSize { + // Avoid setting the sweep ratio extremely high + heapDistance = _PageSize + } + pagesSwept := mheap_.pagesSwept.Load() + pagesInUse := mheap_.pagesInUse.Load() + sweepDistancePages := int64(pagesInUse) - int64(pagesSwept) + if sweepDistancePages <= 0 { + mheap_.sweepPagesPerByte = 0 + } else { + mheap_.sweepPagesPerByte = float64(sweepDistancePages) / float64(heapDistance) + mheap_.sweepHeapLiveBasis = heapLiveBasis + // Write pagesSweptBasis last, since this + // signals concurrent sweeps to recompute + // their debt. + mheap_.pagesSweptBasis.Store(pagesSwept) + } + } +} -- GitLab From 903f313d8b6e85c031fc5918273ff4800fa9f952 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Fri, 29 Oct 2021 17:58:42 +0000 Subject: [PATCH 1822/2500] runtime: fix unclosed GCSweepStart trace event CL 333389 erroneously moved traceGCSweepDone inside the sl.valid block that it introduced in mcentral.cacheSpan, when it should have left it outside that scope, because the trace event is created unconditionally at the top of the method. Fixes #49231. Change-Id: If719c05063d4f4d330a320da6dc00d1e9d8102e4 Reviewed-on: https://go-review.googlesource.com/c/go/+/359775 Trust: Michael Knyszek Run-TryBot: Michael Knyszek Reviewed-by: Michael Pratt TryBot-Result: Go Bot --- src/runtime/mcentral.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/runtime/mcentral.go b/src/runtime/mcentral.go index 4ae3a883a4..e4bdf35071 100644 --- a/src/runtime/mcentral.go +++ b/src/runtime/mcentral.go @@ -154,10 +154,10 @@ func (c *mcentral) cacheSpan() *mspan { // See comment for partial unswept spans. } sweep.active.end(sl) - if trace.enabled { - traceGCSweepDone() - traceDone = true - } + } + if trace.enabled { + traceGCSweepDone() + traceDone = true } // We failed to get a span from the mcentral so get one from mheap. -- GitLab From 4a5d78ff8b7e777d70b18a61698b1ac07bbd623d Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Sun, 11 Apr 2021 18:11:48 +0000 Subject: [PATCH 1823/2500] runtime: move pacer time updates and state resets into methods Currently GC pacer updates are applied somewhat haphazardly via direct field access. To facilitate ease of testing, move these field updates into methods. Further CLs will move more of these updates into methods. For #44167. Change-Id: I25b10d2219ae27b356b5f236d44827546c86578d Reviewed-on: https://go-review.googlesource.com/c/go/+/309274 Trust: Michael Knyszek Run-TryBot: Michael Knyszek Reviewed-by: Michael Pratt --- src/runtime/mgc.go | 39 +++++++++++---------------------------- src/runtime/mgcpacer.go | 41 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 29 deletions(-) diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go index b2ed18fe6a..cf53585dcd 100644 --- a/src/runtime/mgc.go +++ b/src/runtime/mgc.go @@ -661,7 +661,9 @@ func gcStart(trigger gcTrigger) { work.cycles++ - gcController.startCycle() + // Assists and workers can start the moment we start + // the world. + gcController.startCycle(now) work.heapGoal = gcController.heapGoal // In STW mode, disable scheduling of user Gs. This may also @@ -704,10 +706,6 @@ func gcStart(trigger gcTrigger) { // mutators. atomic.Store(&gcBlackenEnabled, 1) - // Assists and workers can start the moment we start - // the world. - gcController.markStartTime = now - // In STW mode, we could block the instant systemstack // returns, so make sure we're not preemptible. mp = acquirem() @@ -965,8 +963,7 @@ func gcMarkTermination(nextTriggerRatio float64) { throw("gc done but gcphase != _GCoff") } - // Record heapGoal and heap_inuse for scavenger. - gcController.lastHeapGoal = gcController.heapGoal + // Record heap_inuse for scavenger. memstats.last_heap_inuse = memstats.heap_inuse // Update GC trigger and pacing for the next cycle. @@ -1291,15 +1288,9 @@ func gcBgMarkWorker() { // Account for time. duration := nanotime() - startTime - switch pp.gcMarkWorkerMode { - case gcMarkWorkerDedicatedMode: - atomic.Xaddint64(&gcController.dedicatedMarkTime, duration) - atomic.Xaddint64(&gcController.dedicatedMarkWorkersNeeded, 1) - case gcMarkWorkerFractionalMode: - atomic.Xaddint64(&gcController.fractionalMarkTime, duration) + gcController.logWorkTime(pp.gcMarkWorkerMode, duration) + if pp.gcMarkWorkerMode == gcMarkWorkerFractionalMode { atomic.Xaddint64(&pp.gcFractionalMarkTime, duration) - case gcMarkWorkerIdleMode: - atomic.Xaddint64(&gcController.idleMarkTime, duration) } // Was this the last worker and did we run out @@ -1419,30 +1410,22 @@ func gcMark(startTime int64) { gcw.dispose() } - // Update the marked heap stat. - gcController.heapMarked = work.bytesMarked - // Flush scanAlloc from each mcache since we're about to modify // heapScan directly. If we were to flush this later, then scanAlloc // might have incorrect information. + // + // Note that it's not important to retain this information; we know + // exactly what heapScan is at this point via scanWork. for _, p := range allp { c := p.mcache if c == nil { continue } - gcController.heapScan += uint64(c.scanAlloc) c.scanAlloc = 0 } - // Update other GC heap size stats. This must happen after - // cachestats (which flushes local statistics to these) and - // flushallmcaches (which modifies gcController.heapLive). - gcController.heapLive = work.bytesMarked - gcController.heapScan = uint64(gcController.scanWork) - - if trace.enabled { - traceHeapAlloc() - } + // Reset controller state. + gcController.resetLive(work.bytesMarked) } // gcSweep must be called on the system stack because it acquires the heap diff --git a/src/runtime/mgcpacer.go b/src/runtime/mgcpacer.go index 980cb2f086..503b8110b3 100644 --- a/src/runtime/mgcpacer.go +++ b/src/runtime/mgcpacer.go @@ -268,13 +268,14 @@ func (c *gcControllerState) init(gcPercent int32) { // startCycle resets the GC controller's state and computes estimates // for a new GC cycle. The caller must hold worldsema and the world // must be stopped. -func (c *gcControllerState) startCycle() { +func (c *gcControllerState) startCycle(markStartTime int64) { c.scanWork = 0 c.bgScanCredit = 0 c.assistTime = 0 c.dedicatedMarkTime = 0 c.fractionalMarkTime = 0 c.idleMarkTime = 0 + c.markStartTime = markStartTime // Ensure that the heap goal is at least a little larger than // the current live heap size. This may not be the case if GC @@ -441,6 +442,10 @@ func (c *gcControllerState) revise() { // userForced indicates whether the current GC cycle was forced // by the application. func (c *gcControllerState) endCycle(userForced bool) float64 { + // Record last heap goal for the scavenger. + // We'll be updating the heap goal soon. + gcController.lastHeapGoal = gcController.heapGoal + if userForced { // Forced GC means this cycle didn't start at the // trigger, so where it finished isn't good @@ -630,6 +635,40 @@ func (c *gcControllerState) findRunnableGCWorker(_p_ *p) *g { return gp } +// resetLive sets up the controller state for the next mark phase after the end +// of the previous one. Must be called after endCycle and before commit, before +// the world is started. +// +// The world must be stopped. +func (c *gcControllerState) resetLive(bytesMarked uint64) { + c.heapMarked = bytesMarked + c.heapLive = bytesMarked + c.heapScan = uint64(c.scanWork) + + // heapLive was updated, so emit a trace event. + if trace.enabled { + traceHeapAlloc() + } +} + +// logWorkTime updates mark work accounting in the controller by a duration of +// work in nanoseconds. +// +// Safe to execute at any time. +func (c *gcControllerState) logWorkTime(mode gcMarkWorkerMode, duration int64) { + switch mode { + case gcMarkWorkerDedicatedMode: + atomic.Xaddint64(&c.dedicatedMarkTime, duration) + atomic.Xaddint64(&c.dedicatedMarkWorkersNeeded, 1) + case gcMarkWorkerFractionalMode: + atomic.Xaddint64(&c.fractionalMarkTime, duration) + case gcMarkWorkerIdleMode: + atomic.Xaddint64(&c.idleMarkTime, duration) + default: + throw("logWorkTime: unknown mark worker mode") + } +} + // commit sets the trigger ratio and updates everything // derived from it: the absolute trigger, the heap goal, mark pacing, // and sweep pacing. -- GitLab From 8e112a7c2a814de9156f68dc8b167e4ef8c98c52 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Sun, 11 Apr 2021 18:29:03 +0000 Subject: [PATCH 1824/2500] runtime: move heapLive and heapScan updates into a method This change moves heapLive and heapScan updates on gcController into a method for better testability. It's also less error-prone because code that updates these fields needs to remember to emit traces and/or call gcController.revise; this method now handles those cases. For #44167. Change-Id: I3d6f2e7abb22def27c93feacff50162b0b074da2 Reviewed-on: https://go-review.googlesource.com/c/go/+/309275 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Michael Pratt --- src/runtime/mcache.go | 39 ++++++++++----------------------------- src/runtime/mgcpacer.go | 17 +++++++++++++++++ 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/src/runtime/mcache.go b/src/runtime/mcache.go index 52bb944cdd..86a8958b9d 100644 --- a/src/runtime/mcache.go +++ b/src/runtime/mcache.go @@ -184,24 +184,13 @@ func (c *mcache) refill(spc spanClass) { } memstats.heapStats.release() - // Update gcController.heapLive with the same assumption. - usedBytes := uintptr(s.allocCount) * s.elemsize - atomic.Xadd64(&gcController.heapLive, int64(s.npages*pageSize)-int64(usedBytes)) - + // Update heapLive with the same assumption. // While we're here, flush scanAlloc, since we have to call // revise anyway. - atomic.Xadd64(&gcController.heapScan, int64(c.scanAlloc)) + usedBytes := uintptr(s.allocCount) * s.elemsize + gcController.update(int64(s.npages*pageSize)-int64(usedBytes), int64(c.scanAlloc)) c.scanAlloc = 0 - if trace.enabled { - // gcController.heapLive changed. - traceHeapAlloc() - } - if gcBlackenEnabled != 0 { - // gcController.heapLive and heapScan changed. - gcController.revise() - } - c.alloc[spc] = s } @@ -230,15 +219,8 @@ func (c *mcache) allocLarge(size uintptr, noscan bool) *mspan { atomic.Xadduintptr(&stats.largeAllocCount, 1) memstats.heapStats.release() - // Update gcController.heapLive and revise pacing if needed. - atomic.Xadd64(&gcController.heapLive, int64(npages*pageSize)) - if trace.enabled { - // Trace that a heap alloc occurred because gcController.heapLive changed. - traceHeapAlloc() - } - if gcBlackenEnabled != 0 { - gcController.revise() - } + // Update heapLive. + gcController.update(int64(s.npages*pageSize), 0) // Put the large span in the mcentral swept list so that it's // visible to the background sweeper. @@ -250,10 +232,11 @@ func (c *mcache) allocLarge(size uintptr, noscan bool) *mspan { func (c *mcache) releaseAll() { // Take this opportunity to flush scanAlloc. - atomic.Xadd64(&gcController.heapScan, int64(c.scanAlloc)) + scanAlloc := int64(c.scanAlloc) c.scanAlloc = 0 sg := mheap_.sweepgen + dHeapLive := int64(0) for i := range c.alloc { s := c.alloc[i] if s != &emptymspan { @@ -270,7 +253,7 @@ func (c *mcache) releaseAll() { // gcController.heapLive was totally recomputed since // caching this span, so we don't do this for // stale spans. - atomic.Xadd64(&gcController.heapLive, -int64(n)*int64(s.elemsize)) + dHeapLive -= int64(n) * int64(s.elemsize) } // Release the span to the mcentral. mheap_.central[i].mcentral.uncacheSpan(s) @@ -287,10 +270,8 @@ func (c *mcache) releaseAll() { c.tinyAllocs = 0 memstats.heapStats.release() - // Updated heapScan and possible gcController.heapLive. - if gcBlackenEnabled != 0 { - gcController.revise() - } + // Updated heapScan and heapLive. + gcController.update(dHeapLive, scanAlloc) } // prepareForSweep flushes c if the system has entered a new sweep phase diff --git a/src/runtime/mgcpacer.go b/src/runtime/mgcpacer.go index 503b8110b3..094dcc701a 100644 --- a/src/runtime/mgcpacer.go +++ b/src/runtime/mgcpacer.go @@ -669,6 +669,23 @@ func (c *gcControllerState) logWorkTime(mode gcMarkWorkerMode, duration int64) { } } +func (c *gcControllerState) update(dHeapLive, dHeapScan int64) { + if dHeapLive != 0 { + atomic.Xadd64(&gcController.heapLive, dHeapLive) + if trace.enabled { + // gcController.heapLive changed. + traceHeapAlloc() + } + } + if dHeapScan != 0 { + atomic.Xadd64(&gcController.heapScan, dHeapScan) + } + if gcBlackenEnabled != 0 { + // gcController.heapLive and heapScan changed. + c.revise() + } +} + // commit sets the trigger ratio and updates everything // derived from it: the absolute trigger, the heap goal, mark pacing, // and sweep pacing. -- GitLab From 9ac1ee2d464eff73077afda83677f155bd69c6b8 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 12 Apr 2021 22:33:54 +0000 Subject: [PATCH 1825/2500] runtime: track the amount of scannable allocated stack for the GC pacer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change adds two fields to gcControllerState: stackScan, used for pacing decisions, and scannableStackSize, which directly tracks the amount of space allocated for inuse stacks that will be scanned. scannableStackSize is not updated directly, but is instead flushed from each P when at an least 8 KiB delta has accumulated. This helps reduce issues with atomics contention for newly created goroutines. Stack growth paths are largely unaffected. StackGrowth-48 51.4ns ± 0% 51.4ns ± 0% ~ (p=0.927 n=10+10) StackGrowthDeep-48 6.14µs ± 3% 6.25µs ± 4% ~ (p=0.090 n=10+9) CreateGoroutines-48 273ns ± 1% 273ns ± 1% ~ (p=0.676 n=9+10) CreateGoroutinesParallel-48 65.5ns ± 5% 66.6ns ± 7% ~ (p=0.340 n=9+9) CreateGoroutinesCapture-48 2.06µs ± 1% 2.07µs ± 4% ~ (p=0.217 n=10+10) CreateGoroutinesSingle-48 550ns ± 3% 563ns ± 4% +2.41% (p=0.034 n=8+10) For #44167. Change-Id: Id1800d41d3a6c211b43aeb5681c57c0dc8880daf Reviewed-on: https://go-review.googlesource.com/c/go/+/309589 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Michael Pratt --- src/runtime/mgcpacer.go | 29 +++++++++++++++++++++++++++++ src/runtime/proc.go | 7 +++++-- src/runtime/runtime2.go | 6 ++++++ src/runtime/stack.go | 5 +++++ 4 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/runtime/mgcpacer.go b/src/runtime/mgcpacer.go index 094dcc701a..9cc7cf99db 100644 --- a/src/runtime/mgcpacer.go +++ b/src/runtime/mgcpacer.go @@ -47,6 +47,10 @@ const ( // defaultHeapMinimum is the value of heapMinimum for GOGC==100. defaultHeapMinimum = 4 << 20 + + // scannableStackSizeSlack is the bytes of stack space allocated or freed + // that can accumulate on a P before updating gcController.stackSize. + scannableStackSizeSlack = 8 << 10 ) func init() { @@ -166,6 +170,18 @@ type gcControllerState struct { // Read and written atomically or with the world stopped. heapScan uint64 + // stackScan is a snapshot of scannableStackSize taken at each GC + // STW pause and is used in pacing decisions. + // + // Updated only while the world is stopped. + stackScan uint64 + + // scannableStackSize is the amount of allocated goroutine stack space in + // use by goroutines. + // + // Read and updated atomically. + scannableStackSize uint64 + // heapMarked is the number of bytes marked by the previous // GC. After mark termination, heapLive == heapMarked, but // unlike heapLive, heapMarked does not change until the @@ -276,6 +292,7 @@ func (c *gcControllerState) startCycle(markStartTime int64) { c.fractionalMarkTime = 0 c.idleMarkTime = 0 c.markStartTime = markStartTime + c.stackScan = atomic.Load64(&c.scannableStackSize) // Ensure that the heap goal is at least a little larger than // the current live heap size. This may not be the case if GC @@ -686,6 +703,18 @@ func (c *gcControllerState) update(dHeapLive, dHeapScan int64) { } } +func (c *gcControllerState) addScannableStack(pp *p, amount int64) { + if pp == nil { + atomic.Xadd64(&c.scannableStackSize, amount) + return + } + pp.scannableStackSizeDelta += amount + if pp.scannableStackSizeDelta >= scannableStackSizeSlack || pp.scannableStackSizeDelta <= -scannableStackSizeSlack { + atomic.Xadd64(&c.scannableStackSize, pp.scannableStackSizeDelta) + pp.scannableStackSizeDelta = 0 + } +} + // commit sets the trigger ratio and updates everything // derived from it: the absolute trigger, the heap goal, mark pacing, // and sweep pacing. diff --git a/src/runtime/proc.go b/src/runtime/proc.go index bd7dacd440..615f53d31f 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -3623,8 +3623,10 @@ func goexit1() { // goexit continuation on g0. func goexit0(gp *g) { _g_ := getg() + _p_ := _g_.m.p.ptr() casgstatus(gp, _Grunning, _Gdead) + gcController.addScannableStack(_p_, -int64(gp.stack.hi-gp.stack.lo)) if isSystemGoroutine(gp, false) { atomic.Xadd(&sched.ngsys, -1) } @@ -3655,7 +3657,7 @@ func goexit0(gp *g) { dropg() if GOARCH == "wasm" { // no threads yet on wasm - gfput(_g_.m.p.ptr(), gp) + gfput(_p_, gp) schedule() // never returns } @@ -3663,7 +3665,7 @@ func goexit0(gp *g) { print("invalid m->lockedInt = ", _g_.m.lockedInt, "\n") throw("internal lockOSThread error") } - gfput(_g_.m.p.ptr(), gp) + gfput(_p_, gp) if locked { // The goroutine may have locked this thread because // it put it in an unusual kernel state. Kill it @@ -4292,6 +4294,7 @@ func newproc1(fn *funcval, callergp *g, callerpc uintptr) *g { newg.tracking = true } casgstatus(newg, _Gdead, _Grunnable) + gcController.addScannableStack(_p_, int64(newg.stack.hi-newg.stack.lo)) if _p_.goidcache == _p_.goidcacheend { // Sched.goidgen is the last allocated id, diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index db1c6e307b..bfd857e8d5 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -734,6 +734,12 @@ type p struct { // Race context used while executing timer functions. timerRaceCtx uintptr + // scannableStackSizeDelta accumulates the amount of stack space held by + // live goroutines (i.e. those eligible for stack scanning). + // Flushed to gcController.scannableStackSize once scannableStackSizeSlack + // or -scannableStackSizeSlack is reached. + scannableStackSizeDelta int64 + // preempt is set to indicate that this P should be enter the // scheduler ASAP (regardless of what G is running on it). preempt bool diff --git a/src/runtime/stack.go b/src/runtime/stack.go index 284c6b3b84..8ae9c1e698 100644 --- a/src/runtime/stack.go +++ b/src/runtime/stack.go @@ -852,6 +852,11 @@ func copystack(gp *g, newsize uintptr) { throw("nil stackbase") } used := old.hi - gp.sched.sp + // Add just the difference to gcController.addScannableStack. + // g0 stacks never move, so this will never account for them. + // It's also fine if we have no P, addScannableStack can deal with + // that case. + gcController.addScannableStack(getg().m.p.ptr(), int64(newsize)-int64(old.hi-old.lo)) // allocate new stack new := stackalloc(uint32(newsize)) -- GitLab From 9da64156a62e4661fb5b0e64a2f196f253ce0dc5 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 12 Apr 2021 22:40:36 +0000 Subject: [PATCH 1826/2500] runtime: track scannable globals space For #44167. Change-Id: I2cd13229d88f630451fabd113b0e5a04841e9e79 Reviewed-on: https://go-review.googlesource.com/c/go/+/309590 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Michael Pratt --- src/runtime/mgcpacer.go | 10 ++++++++++ src/runtime/symtab.go | 7 +++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/runtime/mgcpacer.go b/src/runtime/mgcpacer.go index 9cc7cf99db..ad7c4bb840 100644 --- a/src/runtime/mgcpacer.go +++ b/src/runtime/mgcpacer.go @@ -182,6 +182,12 @@ type gcControllerState struct { // Read and updated atomically. scannableStackSize uint64 + // globalsScan is the total amount of global variable space + // that is scannable. + // + // Read and updated atomically. + globalsScan uint64 + // heapMarked is the number of bytes marked by the previous // GC. After mark termination, heapLive == heapMarked, but // unlike heapLive, heapMarked does not change until the @@ -715,6 +721,10 @@ func (c *gcControllerState) addScannableStack(pp *p, amount int64) { } } +func (c *gcControllerState) addGlobals(amount int64) { + atomic.Xadd64(&c.globalsScan, amount) +} + // commit sets the trigger ratio and updates everything // derived from it: the absolute trigger, the heap goal, mark pacing, // and sweep pacing. diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 41161d6f90..3237a6b708 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -529,8 +529,11 @@ func modulesinit() { } *modules = append(*modules, md) if md.gcdatamask == (bitvector{}) { - md.gcdatamask = progToPointerMask((*byte)(unsafe.Pointer(md.gcdata)), md.edata-md.data) - md.gcbssmask = progToPointerMask((*byte)(unsafe.Pointer(md.gcbss)), md.ebss-md.bss) + scanDataSize := md.edata - md.data + md.gcdatamask = progToPointerMask((*byte)(unsafe.Pointer(md.gcdata)), scanDataSize) + scanBSSSize := md.ebss - md.bss + md.gcbssmask = progToPointerMask((*byte)(unsafe.Pointer(md.gcbss)), scanBSSSize) + gcController.addGlobals(int64(scanDataSize + scanBSSSize)) } } -- GitLab From 5ec2427357f4917d0aad40cffddeea73e580129e Mon Sep 17 00:00:00 2001 From: Michael Knyszek Date: Fri, 1 Oct 2021 15:07:45 -0400 Subject: [PATCH 1827/2500] runtime: pass nanotime and gomaxprocs into startCycle and endCycle explicitly This is to facilitate testing of the pacer, since otherwise this is accessing global state, which is impossible to stub out properly. For #44167. Change-Id: I52c3b51fc0ffff38e3bbe534bd66e5761c0003a8 Reviewed-on: https://go-review.googlesource.com/c/go/+/353353 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Michael Pratt --- src/runtime/mgc.go | 4 ++-- src/runtime/mgcpacer.go | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go index cf53585dcd..03711a9617 100644 --- a/src/runtime/mgc.go +++ b/src/runtime/mgc.go @@ -663,7 +663,7 @@ func gcStart(trigger gcTrigger) { // Assists and workers can start the moment we start // the world. - gcController.startCycle(now) + gcController.startCycle(now, int(gomaxprocs)) work.heapGoal = gcController.heapGoal // In STW mode, disable scheduling of user Gs. This may also @@ -889,7 +889,7 @@ top: // endCycle depends on all gcWork cache stats being flushed. // The termination algorithm above ensured that up to // allocations since the ragged barrier. - nextTriggerRatio := gcController.endCycle(work.userForced) + nextTriggerRatio := gcController.endCycle(now, int(gomaxprocs), work.userForced) // Perform mark termination. This will restart the world. gcMarkTermination(nextTriggerRatio) diff --git a/src/runtime/mgcpacer.go b/src/runtime/mgcpacer.go index ad7c4bb840..160383db43 100644 --- a/src/runtime/mgcpacer.go +++ b/src/runtime/mgcpacer.go @@ -290,7 +290,7 @@ func (c *gcControllerState) init(gcPercent int32) { // startCycle resets the GC controller's state and computes estimates // for a new GC cycle. The caller must hold worldsema and the world // must be stopped. -func (c *gcControllerState) startCycle(markStartTime int64) { +func (c *gcControllerState) startCycle(markStartTime int64, procs int) { c.scanWork = 0 c.bgScanCredit = 0 c.assistTime = 0 @@ -316,7 +316,7 @@ func (c *gcControllerState) startCycle(markStartTime int64) { // dedicated workers so that the utilization is closest to // 25%. For small GOMAXPROCS, this would introduce too much // error, so we add fractional workers in that case. - totalUtilizationGoal := float64(gomaxprocs) * gcBackgroundUtilization + totalUtilizationGoal := float64(procs) * gcBackgroundUtilization c.dedicatedMarkWorkersNeeded = int64(totalUtilizationGoal + 0.5) utilError := float64(c.dedicatedMarkWorkersNeeded)/totalUtilizationGoal - 1 const maxUtilError = 0.3 @@ -329,14 +329,14 @@ func (c *gcControllerState) startCycle(markStartTime int64) { // Too many dedicated workers. c.dedicatedMarkWorkersNeeded-- } - c.fractionalUtilizationGoal = (totalUtilizationGoal - float64(c.dedicatedMarkWorkersNeeded)) / float64(gomaxprocs) + c.fractionalUtilizationGoal = (totalUtilizationGoal - float64(c.dedicatedMarkWorkersNeeded)) / float64(procs) } else { c.fractionalUtilizationGoal = 0 } // In STW mode, we just want dedicated workers. if debug.gcstoptheworld > 0 { - c.dedicatedMarkWorkersNeeded = int64(gomaxprocs) + c.dedicatedMarkWorkersNeeded = int64(procs) c.fractionalUtilizationGoal = 0 } @@ -464,7 +464,7 @@ func (c *gcControllerState) revise() { // endCycle computes the trigger ratio for the next cycle. // userForced indicates whether the current GC cycle was forced // by the application. -func (c *gcControllerState) endCycle(userForced bool) float64 { +func (c *gcControllerState) endCycle(now int64, procs int, userForced bool) float64 { // Record last heap goal for the scavenger. // We'll be updating the heap goal soon. gcController.lastHeapGoal = gcController.heapGoal @@ -495,13 +495,13 @@ func (c *gcControllerState) endCycle(userForced bool) float64 { // heap growth is the error. goalGrowthRatio := c.effectiveGrowthRatio() actualGrowthRatio := float64(c.heapLive)/float64(c.heapMarked) - 1 - assistDuration := nanotime() - c.markStartTime + assistDuration := now - c.markStartTime // Assume background mark hit its utilization goal. utilization := gcBackgroundUtilization // Add assist utilization; avoid divide by zero. if assistDuration > 0 { - utilization += float64(c.assistTime) / float64(assistDuration*int64(gomaxprocs)) + utilization += float64(c.assistTime) / float64(assistDuration*int64(procs)) } triggerError := goalGrowthRatio - c.triggerRatio - utilization/gcGoalUtilization*(actualGrowthRatio-c.triggerRatio) -- GitLab From 6afdf01e5385183bea4ba2661bb4088b32626b3d Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 29 Oct 2021 12:07:55 -0400 Subject: [PATCH 1828/2500] cmd/go: make assertions more precise in TestScript/gcflags_patterns This fixes a rare test flake observed in https://build.golang.org/log/18e531785e7f8b3e6a6d5231787a9d8bdd4a60ea. Change-Id: I0986752f5c1abc626070b9f8ecf34c629a15cd2a Reviewed-on: https://go-review.googlesource.com/c/go/+/359735 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- .../go/testdata/script/gcflags_patterns.txt | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/cmd/go/testdata/script/gcflags_patterns.txt b/src/cmd/go/testdata/script/gcflags_patterns.txt index e9521c2fb2..5b81e9481a 100644 --- a/src/cmd/go/testdata/script/gcflags_patterns.txt +++ b/src/cmd/go/testdata/script/gcflags_patterns.txt @@ -7,24 +7,24 @@ env GOCACHE=$WORK/gocache # Looking for compile commands, so need a clean cache # -gcflags=-e applies to named packages, not dependencies go build -n -v -gcflags=-e z1 z2 -stderr 'compile.* -p z1.* -e' -stderr 'compile.* -p z2.* -e' +stderr 'compile.* -p z1.* -e ' +stderr 'compile.* -p z2.* -e ' stderr 'compile.* -p y' -! stderr 'compile.* -p [^z].* -e' +! stderr 'compile.* -p [^z].* -e ' # -gcflags can specify package=flags, and can be repeated; last match wins go build -n -v -gcflags=-e -gcflags=z1=-N z1 z2 -stderr 'compile.* -p z1.* -N' -! stderr 'compile.* -p z1.* -e' -! stderr 'compile.* -p z2.* -N' -stderr 'compile.* -p z2.* -e' +stderr 'compile.* -p z1.* -N ' +! stderr 'compile.* -p z1.* -e ' +! stderr 'compile.* -p z2.* -N ' +stderr 'compile.* -p z2.* -e ' stderr 'compile.* -p y' -! stderr 'compile.* -p [^z].* -e' -! stderr 'compile.* -p [^z].* -N' +! stderr 'compile.* -p [^z].* -e ' +! stderr 'compile.* -p [^z].* -N ' # -gcflags can have arbitrary spaces around the flags go build -n -v -gcflags=' z1 = -e ' z1 -stderr 'compile.* -p z1.* -e' +stderr 'compile.* -p z1.* -e ' # -gcflags='all=-e' should apply to all packages, even with go test go test -c -n -gcflags='all=-e' z1 -- GitLab From 459293388ceb74d9cf61c930f02325645cd0cb7d Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 28 Oct 2021 20:54:45 -0400 Subject: [PATCH 1829/2500] cmd/go: document that tests must not write to their source modules Fixes #28386 Updates #48495 Change-Id: I76186077c7bbe3f8f608026ee1865de83fe169b4 Reviewed-on: https://go-review.googlesource.com/c/go/+/359574 Trust: Bryan C. Mills Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot --- src/cmd/go/alldocs.go | 6 +++++- src/cmd/go/internal/test/test.go | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 487a8f580b..0dcb317995 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -2951,7 +2951,11 @@ // When 'go test' runs a test binary, it does so from within the // corresponding package's source code directory. Depending on the test, // it may be necessary to do the same when invoking a generated test -// binary directly. +// binary directly. Because that directory may be located within the +// module cache, which may be read-only and is verified by checksums, the +// test must not write to it or any other directory within the module +// unless explicitly requested by the user (such as with the -fuzz flag, +// which writes failures to testdata/fuzz). // // The command-line package list, if present, must appear before any // flag not known to the go test command. Continuing the example above, diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index c435cc3fb2..cfb0a1465f 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -407,7 +407,11 @@ leave the test binary in pkg.test for use when analyzing the profiles. When 'go test' runs a test binary, it does so from within the corresponding package's source code directory. Depending on the test, it may be necessary to do the same when invoking a generated test -binary directly. +binary directly. Because that directory may be located within the +module cache, which may be read-only and is verified by checksums, the +test must not write to it or any other directory within the module +unless explicitly requested by the user (such as with the -fuzz flag, +which writes failures to testdata/fuzz). The command-line package list, if present, must appear before any flag not known to the go test command. Continuing the example above, -- GitLab From 5ec139fa78ac6ba3f0f715b6aa9235d36346a4a4 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 22 Sep 2021 16:49:39 -0400 Subject: [PATCH 1830/2500] runtime: remove unnecessary argument stores for panicIndex etc. on ARM64 If register ABI is used, no need to store the arguments to stack. I forgot them in CL 323937. Change-Id: I888af2b547a8fc97d13716bc8e8f3acd5c5bc127 Reviewed-on: https://go-review.googlesource.com/c/go/+/351609 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: David Chase --- src/runtime/asm_arm64.s | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/runtime/asm_arm64.s b/src/runtime/asm_arm64.s index 8cbd17fa75..9e9d9314ef 100644 --- a/src/runtime/asm_arm64.s +++ b/src/runtime/asm_arm64.s @@ -1383,12 +1383,16 @@ flush: // Defined as ABIInternal since the compiler generates ABIInternal // calls to it directly and it does not use the stack-based Go ABI. TEXT runtime·panicIndex(SB),NOSPLIT,$0-16 +#ifndef GOEXPERIMENT_regabiargs MOVD R0, x+0(FP) MOVD R1, y+8(FP) +#endif JMP runtime·goPanicIndex(SB) TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16 +#ifndef GOEXPERIMENT_regabiargs MOVD R0, x+0(FP) MOVD R1, y+8(FP) +#endif JMP runtime·goPanicIndexU(SB) TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16 #ifdef GOEXPERIMENT_regabiargs @@ -1427,12 +1431,16 @@ TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16 #endif JMP runtime·goPanicSliceAcapU(SB) TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16 +#ifndef GOEXPERIMENT_regabiargs MOVD R0, x+0(FP) MOVD R1, y+8(FP) +#endif JMP runtime·goPanicSliceB(SB) TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16 +#ifndef GOEXPERIMENT_regabiargs MOVD R0, x+0(FP) MOVD R1, y+8(FP) +#endif JMP runtime·goPanicSliceBU(SB) TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16 #ifdef GOEXPERIMENT_regabiargs @@ -1489,12 +1497,16 @@ TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16 #endif JMP runtime·goPanicSlice3BU(SB) TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16 +#ifndef GOEXPERIMENT_regabiargs MOVD R0, x+0(FP) MOVD R1, y+8(FP) +#endif JMP runtime·goPanicSlice3C(SB) TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16 +#ifndef GOEXPERIMENT_regabiargs MOVD R0, x+0(FP) MOVD R1, y+8(FP) +#endif JMP runtime·goPanicSlice3CU(SB) TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-16 #ifdef GOEXPERIMENT_regabiargs -- GitLab From 994049a9ad3d4230d0835ce36616a34a466f6718 Mon Sep 17 00:00:00 2001 From: Michael Knyszek Date: Fri, 1 Oct 2021 15:11:51 -0400 Subject: [PATCH 1831/2500] runtime: add testing framework and basic tests for GC pacer This change creates a formal exported interface for the GC pacer and creates tests for it that simulate some series of GC cycles. The tests are completely driven by the real pacer implementation, except for assists, which are idealized (though revise is called repeatedly). For #44167. Change-Id: I0112242b07e7702595ca71001d781ad6c1fddd2d Reviewed-on: https://go-review.googlesource.com/c/go/+/353354 Trust: Michael Knyszek Run-TryBot: Michael Knyszek Reviewed-by: Michael Pratt TryBot-Result: Go Bot --- src/runtime/export_test.go | 78 +++++ src/runtime/mgcpacer_test.go | 590 +++++++++++++++++++++++++++++++++++ 2 files changed, 668 insertions(+) create mode 100644 src/runtime/mgcpacer_test.go diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index 01f917bded..2cc89e7121 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -1230,3 +1230,81 @@ func GCTestPointerClass(p unsafe.Pointer) string { } const Raceenabled = raceenabled + +const ( + GCBackgroundUtilization = gcBackgroundUtilization + GCGoalUtilization = gcGoalUtilization +) + +type GCController struct { + gcControllerState +} + +func NewGCController(gcPercent int) *GCController { + // Force the controller to escape. We're going to + // do 64-bit atomics on it, and if it gets stack-allocated + // on a 32-bit architecture, it may get allocated unaligned + // space. + g := escape(new(GCController)).(*GCController) + g.init(int32(gcPercent)) + return g +} + +func (c *GCController) StartCycle(stackSize, globalsSize uint64, scannableFrac float64, gomaxprocs int) { + c.scannableStackSize = stackSize + c.globalsScan = globalsSize + c.heapLive = c.trigger + c.heapScan += uint64(float64(c.trigger-c.heapMarked) * scannableFrac) + c.startCycle(0, gomaxprocs) +} + +func (c *GCController) AssistWorkPerByte() float64 { + return c.assistWorkPerByte.Load() +} + +func (c *GCController) HeapGoal() uint64 { + return c.heapGoal +} + +func (c *GCController) HeapLive() uint64 { + return c.heapLive +} + +func (c *GCController) HeapMarked() uint64 { + return c.heapMarked +} + +func (c *GCController) Trigger() uint64 { + return c.trigger +} + +type GCControllerReviseDelta struct { + HeapLive int64 + HeapScan int64 + HeapScanWork int64 + StackScanWork int64 + GlobalsScanWork int64 +} + +func (c *GCController) Revise(d GCControllerReviseDelta) { + c.heapLive += uint64(d.HeapLive) + c.heapScan += uint64(d.HeapScan) + c.scanWork += d.HeapScanWork + d.StackScanWork + d.GlobalsScanWork + c.revise() +} + +func (c *GCController) EndCycle(bytesMarked uint64, assistTime, elapsed int64, gomaxprocs int) { + c.assistTime = assistTime + triggerRatio := c.endCycle(elapsed, gomaxprocs, false) + c.resetLive(bytesMarked) + c.commit(triggerRatio) +} + +var escapeSink interface{} + +//go:noinline +func escape(x interface{}) interface{} { + escapeSink = x + escapeSink = nil + return x +} diff --git a/src/runtime/mgcpacer_test.go b/src/runtime/mgcpacer_test.go new file mode 100644 index 0000000000..5a9f46c6d1 --- /dev/null +++ b/src/runtime/mgcpacer_test.go @@ -0,0 +1,590 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime_test + +import ( + "fmt" + "math" + "math/rand" + . "runtime" + "testing" + "time" +) + +func TestGcPacer(t *testing.T) { + t.Parallel() + + const initialHeapBytes = 256 << 10 + for _, e := range []*gcExecTest{ + { + // The most basic test case: a steady-state heap. + // Growth to an O(MiB) heap, then constant heap size, alloc/scan rates. + name: "Steady", + gcPercent: 100, + globalsBytes: 32 << 10, + nCores: 8, + allocRate: constant(33.0), + scanRate: constant(1024.0), + growthRate: constant(2.0).sum(ramp(-1.0, 12)), + scannableFrac: constant(1.0), + stackBytes: constant(8192), + length: 50, + checker: func(t *testing.T, c []gcCycleResult) { + n := len(c) + if n >= 25 { + // Make sure the pacer settles into a non-degenerate state in at least 25 GC cycles. + assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, c[n-2].gcUtilization, 0.005) + assertInRange(t, "goal ratio", c[n-1].goalRatio(), 0.95, 1.05) + } + }, + }, + { + // This tests the GC pacer's response to a small change in allocation rate. + name: "StepAlloc", + gcPercent: 100, + globalsBytes: 32 << 10, + nCores: 8, + allocRate: constant(33.0).sum(ramp(66.0, 1).delay(50)), + scanRate: constant(1024.0), + growthRate: constant(2.0).sum(ramp(-1.0, 12)), + scannableFrac: constant(1.0), + stackBytes: constant(8192), + length: 100, + checker: func(t *testing.T, c []gcCycleResult) { + n := len(c) + if (n >= 25 && n < 50) || n >= 75 { + // Make sure the pacer settles into a non-degenerate state in at least 25 GC cycles + // and then is able to settle again after a significant jump in allocation rate. + assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, c[n-2].gcUtilization, 0.005) + assertInRange(t, "goal ratio", c[n-1].goalRatio(), 0.95, 1.05) + } + }, + }, + { + // This tests the GC pacer's response to a large change in allocation rate. + name: "HeavyStepAlloc", + gcPercent: 100, + globalsBytes: 32 << 10, + nCores: 8, + allocRate: constant(33).sum(ramp(330, 1).delay(50)), + scanRate: constant(1024.0), + growthRate: constant(2.0).sum(ramp(-1.0, 12)), + scannableFrac: constant(1.0), + stackBytes: constant(8192), + length: 100, + checker: func(t *testing.T, c []gcCycleResult) { + n := len(c) + if (n >= 25 && n < 50) || n >= 75 { + // Make sure the pacer settles into a non-degenerate state in at least 25 GC cycles + // and then is able to settle again after a significant jump in allocation rate. + assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, c[n-2].gcUtilization, 0.005) + assertInRange(t, "goal ratio", c[n-1].goalRatio(), 0.95, 1.05) + } + }, + }, + { + // This tests the GC pacer's response to a change in the fraction of the scannable heap. + name: "StepScannableFrac", + gcPercent: 100, + globalsBytes: 32 << 10, + nCores: 8, + allocRate: constant(128.0), + scanRate: constant(1024.0), + growthRate: constant(2.0).sum(ramp(-1.0, 12)), + scannableFrac: constant(0.2).sum(unit(0.5).delay(50)), + stackBytes: constant(8192), + length: 100, + checker: func(t *testing.T, c []gcCycleResult) { + n := len(c) + if (n >= 25 && n < 50) || n >= 75 { + // Make sure the pacer settles into a non-degenerate state in at least 25 GC cycles + // and then is able to settle again after a significant jump in allocation rate. + assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, c[n-2].gcUtilization, 0.005) + assertInRange(t, "goal ratio", c[n-1].goalRatio(), 0.95, 1.05) + } + }, + }, + { + // This test makes sure that in the face of a varying (in this case, oscillating) allocation + // rate, the pacer does a reasonably good job of staying abreast of the changes. + name: "OscAlloc", + gcPercent: 100, + globalsBytes: 32 << 10, + nCores: 8, + allocRate: oscillate(13, 0, 8).offset(67), + scanRate: constant(1024.0), + growthRate: constant(2.0).sum(ramp(-1.0, 12)), + scannableFrac: constant(1.0), + stackBytes: constant(8192), + length: 50, + checker: func(t *testing.T, c []gcCycleResult) { + n := len(c) + if n > 12 { + // After the 12th GC, the heap will stop growing. Now, just make sure that: + // 1. Utilization isn't varying _too_ much, and + // 2. The pacer is mostly keeping up with the goal. + assertInRange(t, "goal ratio", c[n-1].goalRatio(), 0.95, 1.05) + assertInRange(t, "GC utilization", c[n-1].gcUtilization, 0.25, 0.4) + } + }, + }, + { + // This test is the same as OscAlloc, but instead of oscillating, the allocation rate is jittery. + name: "JitterAlloc", + gcPercent: 100, + globalsBytes: 32 << 10, + nCores: 8, + allocRate: random(13, 0xf).offset(132), + scanRate: constant(1024.0), + growthRate: constant(2.0).sum(ramp(-1.0, 12), random(0.01, 0xe)), + scannableFrac: constant(1.0), + stackBytes: constant(8192), + length: 50, + checker: func(t *testing.T, c []gcCycleResult) { + n := len(c) + if n > 12 { + // After the 12th GC, the heap will stop growing. Now, just make sure that: + // 1. Utilization isn't varying _too_ much, and + // 2. The pacer is mostly keeping up with the goal. + assertInRange(t, "goal ratio", c[n-1].goalRatio(), 0.95, 1.05) + assertInRange(t, "GC utilization", c[n-1].gcUtilization, 0.25, 0.4) + } + }, + }, + { + // This test is the same as JitterAlloc, but with a much higher allocation rate. + // The jitter is proportionally the same. + name: "HeavyJitterAlloc", + gcPercent: 100, + globalsBytes: 32 << 10, + nCores: 8, + allocRate: random(33.0, 0x0).offset(330), + scanRate: constant(1024.0), + growthRate: constant(2.0).sum(ramp(-1.0, 12), random(0.01, 0x152)), + scannableFrac: constant(1.0), + stackBytes: constant(8192), + length: 50, + checker: func(t *testing.T, c []gcCycleResult) { + n := len(c) + if n > 13 { + // After the 12th GC, the heap will stop growing. Now, just make sure that: + // 1. Utilization isn't varying _too_ much, and + // 2. The pacer is mostly keeping up with the goal. + // We start at the 13th here because we want to use the 12th as a reference. + assertInRange(t, "goal ratio", c[n-1].goalRatio(), 0.95, 1.05) + // Unlike the other tests, GC utilization here will vary more and tend higher. + // Just make sure it's not going too crazy. + assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, c[n-2].gcUtilization, 0.05) + assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, c[11].gcUtilization, 0.07) + } + }, + }, + } { + e := e + t.Run(e.name, func(t *testing.T) { + t.Parallel() + + c := NewGCController(e.gcPercent) + var bytesAllocatedBlackLast int64 + results := make([]gcCycleResult, 0, e.length) + for i := 0; i < e.length; i++ { + cycle := e.next() + c.StartCycle(cycle.stackBytes, e.globalsBytes, cycle.scannableFrac, e.nCores) + + // Update pacer incrementally as we complete scan work. + const ( + revisePeriod = 500 * time.Microsecond + rateConv = 1024 * float64(revisePeriod) / float64(time.Millisecond) + ) + var nextHeapMarked int64 + if i == 0 { + nextHeapMarked = initialHeapBytes + } else { + nextHeapMarked = int64(float64(int64(c.HeapMarked())-bytesAllocatedBlackLast) * cycle.growthRate) + } + globalsScanWorkLeft := int64(e.globalsBytes) + stackScanWorkLeft := int64(cycle.stackBytes) + heapScanWorkLeft := int64(float64(nextHeapMarked) * cycle.scannableFrac) + doWork := func(work int64) (int64, int64, int64) { + var deltas [3]int64 + + // Do globals work first, then stacks, then heap. + for i, workLeft := range []*int64{&globalsScanWorkLeft, &stackScanWorkLeft, &heapScanWorkLeft} { + if *workLeft == 0 { + continue + } + if *workLeft > work { + deltas[i] += work + *workLeft -= work + work = 0 + break + } else { + deltas[i] += *workLeft + work -= *workLeft + *workLeft = 0 + } + } + return deltas[0], deltas[1], deltas[2] + } + var ( + gcDuration int64 + assistTime int64 + bytesAllocatedBlack int64 + ) + for heapScanWorkLeft+stackScanWorkLeft+globalsScanWorkLeft > 0 { + // Simulate GC assist pacing. + // + // Note that this is an idealized view of the GC assist pacing + // mechanism. + + // From the assist ratio and the alloc and scan rates, we can idealize what + // the GC CPU utilization looks like. + // + // We start with assistRatio = (bytes of scan work) / (bytes of runway) (by definition). + // + // Over revisePeriod, we can also calculate how many bytes are scanned and + // allocated, given some GC CPU utilization u: + // + // bytesScanned = scanRate * rateConv * nCores * u + // bytesAllocated = allocRate * rateConv * nCores * (1 - u) + // + // During revisePeriod, assistRatio is kept constant, and GC assists kick in to + // maintain it. Specifically, they act to prevent too many bytes being allocated + // compared to how many bytes are scanned. It directly defines the ratio of + // bytesScanned to bytesAllocated over this period, hence: + // + // assistRatio = bytesScanned / bytesAllocated + // + // From this, we can solve for utilization, because everything else has already + // been determined: + // + // assistRatio = (scanRate * rateConv * nCores * u) / (allocRate * rateConv * nCores * (1 - u)) + // assistRatio = (scanRate * u) / (allocRate * (1 - u)) + // assistRatio * allocRate * (1-u) = scanRate * u + // assistRatio * allocRate - assistRatio * allocRate * u = scanRate * u + // assistRatio * allocRate = assistRatio * allocRate * u + scanRate * u + // assistRatio * allocRate = (assistRatio * allocRate + scanRate) * u + // u = (assistRatio * allocRate) / (assistRatio * allocRate + scanRate) + // + // Note that this may give a utilization that is _less_ than GCBackgroundUtilization, + // which isn't possible in practice because of dedicated workers. Thus, this case + // must be interpreted as GC assists not kicking in at all, and just round up. All + // downstream values will then have this accounted for. + assistRatio := c.AssistWorkPerByte() + utilization := assistRatio * cycle.allocRate / (assistRatio*cycle.allocRate + cycle.scanRate) + if utilization < GCBackgroundUtilization { + utilization = GCBackgroundUtilization + } + + // Knowing the utilization, calculate bytesScanned and bytesAllocated. + bytesScanned := int64(cycle.scanRate * rateConv * float64(e.nCores) * utilization) + bytesAllocated := int64(cycle.allocRate * rateConv * float64(e.nCores) * (1 - utilization)) + + // Subtract work from our model. + globalsScanned, stackScanned, heapScanned := doWork(bytesScanned) + + // doWork may not use all of bytesScanned. + // In this case, the GC actually ends sometime in this period. + // Let's figure out when, exactly, and adjust bytesAllocated too. + actualElapsed := revisePeriod + actualAllocated := bytesAllocated + if actualScanned := globalsScanned + stackScanned + heapScanned; actualScanned < bytesScanned { + // actualScanned = scanRate * rateConv * (t / revisePeriod) * nCores * u + // => t = actualScanned * revisePeriod / (scanRate * rateConv * nCores * u) + actualElapsed = time.Duration(float64(actualScanned) * float64(revisePeriod) / (cycle.scanRate * rateConv * float64(e.nCores) * utilization)) + actualAllocated = int64(cycle.allocRate * rateConv * float64(actualElapsed) / float64(revisePeriod) * float64(e.nCores) * (1 - utilization)) + } + + // Ask the pacer to revise. + c.Revise(GCControllerReviseDelta{ + HeapLive: actualAllocated, + HeapScan: int64(float64(actualAllocated) * cycle.scannableFrac), + HeapScanWork: heapScanned, + StackScanWork: stackScanned, + GlobalsScanWork: globalsScanned, + }) + + // Accumulate variables. + assistTime += int64(float64(actualElapsed) * float64(e.nCores) * (utilization - GCBackgroundUtilization)) + gcDuration += int64(actualElapsed) + bytesAllocatedBlack += actualAllocated + } + + // Put together the results, log them, and concatenate them. + result := gcCycleResult{ + cycle: i + 1, + heapLive: c.HeapMarked(), + heapScannable: int64(float64(int64(c.HeapMarked())-bytesAllocatedBlackLast) * cycle.scannableFrac), + heapTrigger: c.Trigger(), + heapPeak: c.HeapLive(), + heapGoal: c.HeapGoal(), + gcUtilization: float64(assistTime)/(float64(gcDuration)*float64(e.nCores)) + GCBackgroundUtilization, + } + t.Log("GC", result.String()) + results = append(results, result) + + // Run the checker for this test. + e.check(t, results) + + c.EndCycle(uint64(nextHeapMarked+bytesAllocatedBlack), assistTime, gcDuration, e.nCores) + + bytesAllocatedBlackLast = bytesAllocatedBlack + } + }) + } +} + +type gcExecTest struct { + name string + + gcPercent int + globalsBytes uint64 + nCores int + + allocRate float64Stream // > 0, KiB / cpu-ms + scanRate float64Stream // > 0, KiB / cpu-ms + growthRate float64Stream // > 0 + scannableFrac float64Stream // Clamped to [0, 1] + stackBytes float64Stream // Multiple of 2048. + length int + + checker func(*testing.T, []gcCycleResult) +} + +// minRate is an arbitrary minimum for allocRate, scanRate, and growthRate. +// These values just cannot be zero. +const minRate = 0.0001 + +func (e *gcExecTest) next() gcCycle { + return gcCycle{ + allocRate: e.allocRate.min(minRate)(), + scanRate: e.scanRate.min(minRate)(), + growthRate: e.growthRate.min(minRate)(), + scannableFrac: e.scannableFrac.limit(0, 1)(), + stackBytes: uint64(e.stackBytes.quantize(2048).min(0)()), + } +} + +func (e *gcExecTest) check(t *testing.T, results []gcCycleResult) { + t.Helper() + + // Do some basic general checks first. + n := len(results) + switch n { + case 0: + t.Fatal("no results passed to check") + return + case 1: + if results[0].cycle != 1 { + t.Error("first cycle has incorrect number") + } + default: + if results[n-1].cycle != results[n-2].cycle+1 { + t.Error("cycle numbers out of order") + } + } + if u := results[n-1].gcUtilization; u < 0 || u > 1 { + t.Fatal("GC utilization not within acceptable bounds") + } + if s := results[n-1].heapScannable; s < 0 { + t.Fatal("heapScannable is negative") + } + if e.checker == nil { + t.Fatal("test-specific checker is missing") + } + + // Run the test-specific checker. + e.checker(t, results) +} + +type gcCycle struct { + allocRate float64 + scanRate float64 + growthRate float64 + scannableFrac float64 + stackBytes uint64 +} + +type gcCycleResult struct { + cycle int + + // These come directly from the pacer, so uint64. + heapLive uint64 + heapTrigger uint64 + heapGoal uint64 + heapPeak uint64 + + // These are produced by the simulation, so int64 and + // float64 are more appropriate, so that we can check for + // bad states in the simulation. + heapScannable int64 + gcUtilization float64 +} + +func (r *gcCycleResult) goalRatio() float64 { + return float64(r.heapPeak) / float64(r.heapGoal) +} + +func (r *gcCycleResult) String() string { + return fmt.Sprintf("%d %2.1f%% %d->%d->%d (goal: %d)", r.cycle, r.gcUtilization*100, r.heapLive, r.heapTrigger, r.heapPeak, r.heapGoal) +} + +func assertInEpsilon(t *testing.T, name string, a, b, epsilon float64) { + t.Helper() + assertInRange(t, name, a, b-epsilon, b+epsilon) +} + +func assertInRange(t *testing.T, name string, a, min, max float64) { + t.Helper() + if a < min || a > max { + t.Errorf("%s not in range (%f, %f): %f", name, min, max, a) + } +} + +// float64Stream is a function that generates an infinite stream of +// float64 values when called repeatedly. +type float64Stream func() float64 + +// constant returns a stream that generates the value c. +func constant(c float64) float64Stream { + return func() float64 { + return c + } +} + +// unit returns a stream that generates a single peak with +// amplitude amp, followed by zeroes. +// +// In another manner of speaking, this is the Kronecker delta. +func unit(amp float64) float64Stream { + dropped := false + return func() float64 { + if dropped { + return 0 + } + dropped = true + return amp + } +} + +// oscillate returns a stream that oscillates sinusoidally +// with the given amplitude, phase, and period. +func oscillate(amp, phase float64, period int) float64Stream { + var cycle int + return func() float64 { + p := float64(cycle)/float64(period)*2*math.Pi + phase + cycle++ + if cycle == period { + cycle = 0 + } + return math.Sin(p) * amp + } +} + +// ramp returns a stream that moves from zero to height +// over the course of length steps. +func ramp(height float64, length int) float64Stream { + var cycle int + return func() float64 { + h := height * float64(cycle) / float64(length) + if cycle < length { + cycle++ + } + return h + } +} + +// random returns a stream that generates random numbers +// between -amp and amp. +func random(amp float64, seed int64) float64Stream { + r := rand.New(rand.NewSource(seed)) + return func() float64 { + return ((r.Float64() - 0.5) * 2) * amp + } +} + +// delay returns a new stream which is a buffered version +// of f: it returns zero for cycles steps, followed by f. +func (f float64Stream) delay(cycles int) float64Stream { + zeroes := 0 + return func() float64 { + if zeroes < cycles { + zeroes++ + return 0 + } + return f() + } +} + +// scale returns a new stream that is f, but attenuated by a +// constant factor. +func (f float64Stream) scale(amt float64) float64Stream { + return func() float64 { + return f() * amt + } +} + +// offset returns a new stream that is f but offset by amt +// at each step. +func (f float64Stream) offset(amt float64) float64Stream { + return func() float64 { + old := f() + return old + amt + } +} + +// sum returns a new stream that is the sum of all input streams +// at each step. +func (f float64Stream) sum(fs ...float64Stream) float64Stream { + return func() float64 { + sum := f() + for _, s := range fs { + sum += s() + } + return sum + } +} + +// quantize returns a new stream that rounds f to a multiple +// of mult at each step. +func (f float64Stream) quantize(mult float64) float64Stream { + return func() float64 { + r := f() / mult + if r < 0 { + return math.Ceil(r) * mult + } + return math.Floor(r) * mult + } +} + +// min returns a new stream that replaces all values produced +// by f lower than min with min. +func (f float64Stream) min(min float64) float64Stream { + return func() float64 { + return math.Max(min, f()) + } +} + +// max returns a new stream that replaces all values produced +// by f higher than max with max. +func (f float64Stream) max(max float64) float64Stream { + return func() float64 { + return math.Min(max, f()) + } +} + +// limit returns a new stream that replaces all values produced +// by f lower than min with min and higher than max with max. +func (f float64Stream) limit(min, max float64) float64Stream { + return func() float64 { + v := f() + if v < min { + v = min + } else if v > max { + v = max + } + return v + } +} -- GitLab From c76893d0da115a63374982196384f78fff224d55 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Fri, 8 Jan 2021 19:09:07 +0100 Subject: [PATCH 1832/2500] crypto/elliptic: refactor P-224 field implementation Improved readability, replaced constant time bit masked operations with named functions, added comments. The behavior of every function should be unchanged. The largest change is the logic that in p224Contract checks if the value is greater than or equal to p. Instead of a lot of error-prone masking, we run a throwaway subtraction chain and look at the final borrow bit. We could also not throw away the subtraction chain output and do a constant time select instead of another masked subtraction, but we'd still have to fix any underflows (because these are unsaturated limbs and they underflow at 2^32 instead of 2^28). That's similar but different from the carry-down chain we do elsewhere in that function (which does undeflow fixing and borrow at the same time). I thought having both variations in the same function would be confusing. Here's how it would look like. var b uint32 var outMinusP p224FieldElement for i := 0; i < len(out); i++ { outMinusP[i], b = bits.Sub32(out[i], p224P[i], b) } for i := 0; i < 3; i++ { mask := maskIfNegative(outMinusP[i]) outMinusP[i] += (1 << 28) & mask // Note we DON'T borrow here, because it happened above. } for i := 0; i < len(out); i++ { out[i] = select32(b, out[i], outMinusP[i]) } Change-Id: I00932e8f171eff7f441b45666dccfd219ecbbc50 Reviewed-on: https://go-review.googlesource.com/c/go/+/326311 Trust: Filippo Valsorda Reviewed-by: Julie Qiu --- src/crypto/elliptic/p224.go | 221 +++++++++++++------------------ src/crypto/elliptic/p224_test.go | 4 +- 2 files changed, 91 insertions(+), 134 deletions(-) diff --git a/src/crypto/elliptic/p224.go b/src/crypto/elliptic/p224.go index 8c76021464..8f3622c89c 100644 --- a/src/crypto/elliptic/p224.go +++ b/src/crypto/elliptic/p224.go @@ -10,7 +10,9 @@ package elliptic // See https://www.imperialviolet.org/2010/12/04/ecc.html ([1]) for background. import ( + "encoding/binary" "math/big" + "math/bits" ) var p224 p224Curve @@ -139,41 +141,22 @@ func (curve p224Curve) ScalarBaseMult(scalar []byte) (x, y *big.Int) { type p224FieldElement [8]uint32 // p224P is the order of the field, represented as a p224FieldElement. -var p224P = [8]uint32{1, 0, 0, 0xffff000, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff} +var p224P = p224FieldElement{1, 0, 0, 0xffff000, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff} // p224IsZero returns 1 if a == 0 mod p and 0 otherwise. // // a[i] < 2**29 func p224IsZero(a *p224FieldElement) uint32 { - // Since a p224FieldElement contains 224 bits there are two possible - // representations of 0: 0 and p. var minimal p224FieldElement p224Contract(&minimal, a) - var isZero, isP uint32 - for i, v := range minimal { - isZero |= v - isP |= v - p224P[i] + var acc uint32 + for _, v := range minimal { + acc |= v } + mask := ^maskIsNotZero(acc) - // If either isZero or isP is 0, then we should return 1. - isZero |= isZero >> 16 - isZero |= isZero >> 8 - isZero |= isZero >> 4 - isZero |= isZero >> 2 - isZero |= isZero >> 1 - - isP |= isP >> 16 - isP |= isP >> 8 - isP |= isP >> 4 - isP |= isP >> 2 - isP |= isP >> 1 - - // For isZero and isP, the LSB is 0 iff all the bits are zero. - result := isZero & isP - result = (^result) & 1 - - return result + return 1 & mask } // p224Add computes *out = a+b @@ -192,6 +175,12 @@ const two31m15m3 = 1<<31 - 1<<15 - 1<<3 // p224ZeroModP31 is 0 mod p where bit 31 is set in all limbs so that we can // subtract smaller amounts without underflow. See the section "Subtraction" in // [1] for reasoning. +// +// To calculate this value, start by adding 2³¹ to the lowest limb and +// subtracting 2³ from the next one to compensate. Repeat for each next limb, +// ending up with 2³¹ - 2³ in each of them, and a carry of -2³. Apply the +// reduction identity, and we need to subtract 2³ * 2⁹⁶ - 2³ = 2¹⁵ * 2⁸⁴ - 2³ so +// we subtract 2¹⁵ from the 4th limb and add 2³ to the first limb. var p224ZeroModP31 = []uint32{two31p3, two31m3, two31m3, two31m15m3, two31m3, two31m3, two31m3, two31m3} // p224Sub computes *out = a-b @@ -225,7 +214,7 @@ const bottom28Bits = 0xfffffff // a[i] < 2**29, b[i] < 2**30 (or vice versa) // out[i] < 2**29 func p224Mul(out, a, b *p224FieldElement, tmp *p224LargeFieldElement) { - for i := 0; i < 15; i++ { + for i := range tmp { tmp[i] = 0 } @@ -243,7 +232,7 @@ func p224Mul(out, a, b *p224FieldElement, tmp *p224LargeFieldElement) { // a[i] < 2**29 // out[i] < 2**29 func p224Square(out, a *p224FieldElement, tmp *p224LargeFieldElement) { - for i := 0; i < 15; i++ { + for i := range tmp { tmp[i] = 0 } @@ -253,7 +242,7 @@ func p224Square(out, a *p224FieldElement, tmp *p224LargeFieldElement) { if i == j { tmp[i+j] += r } else { - tmp[i+j] += r << 1 + tmp[i+j] += r * 2 } } } @@ -264,22 +253,33 @@ func p224Square(out, a *p224FieldElement, tmp *p224LargeFieldElement) { // ReduceLarge converts a p224LargeFieldElement to a p224FieldElement. // // in[i] < 2**62 +// out[i] < 2**29 func p224ReduceLarge(out *p224FieldElement, in *p224LargeFieldElement) { for i := 0; i < 8; i++ { in[i] += p224ZeroModP63[i] } - // Eliminate the coefficients at 2**224 and greater. + // Eliminate the coefficients at 2**224 and greater by applying the + // reduction identity. + // + // a + top * 2²²⁴ = a + top * 2⁹⁶ - top + // + // Since top here is in[8..14], both the subtraction at offset 0 and the + // addition at offset 96 (3 * 28 + 16) span multiple limbs. The subtraction + // can't underflow because of the p224ZeroModP63 addition above, while the + // addition can't overflow because of the 62 bit input bounds. for i := 14; i >= 8; i-- { in[i-8] -= in[i] in[i-5] += (in[i] & 0xffff) << 12 in[i-4] += in[i] >> 16 } in[8] = 0 - // in[0..8] < 2**64 + // in[0..7] < 2**64 + // in[9..14] discarded - // As the values become small enough, we start to store them in |out| - // and use 32-bit operations. + // Run a carry chain and light reduction. Keep [0] large so we can do the + // subtraction safely. As the values become small enough, we start to store + // them in out and use 32-bit operations. for i := 1; i < 8; i++ { in[i+1] += in[i] >> 28 out[i] = uint32(in[i] & bottom28Bits) @@ -292,6 +292,7 @@ func p224ReduceLarge(out *p224FieldElement, in *p224LargeFieldElement) { // out[4] < 2**29 // out[1,2,5..7] < 2**28 + // Carry the overflow of [0] into the short 28 bit limbs. out[0] = uint32(in[0] & bottom28Bits) out[1] += uint32((in[0] >> 28) & bottom28Bits) out[2] += uint32(in[0] >> 56) @@ -312,28 +313,23 @@ func p224Reduce(a *p224FieldElement) { top := a[7] >> 28 a[7] &= bottom28Bits - // top < 2**4 - mask := top - mask |= mask >> 2 - mask |= mask >> 1 - mask <<= 31 - mask = uint32(int32(mask) >> 31) - // Mask is all ones if top != 0, all zero otherwise - a[0] -= top a[3] += top << 12 - // We may have just made a[0] negative but, if we did, then we must - // have added something to a[3], this it's > 2**12. Therefore we can - // carry down to a[0]. + // We may have just made a[0] negative but if we did top must have been not + // zero, so a[3] is not zero, so we can carry down to a[0]. (Note that we + // don't actually check if a[0] went negative, like in p224Contract, nor we + // try to stop the carry at a[1] or a[2], because here we can afford to go + // above 28 bits, so instead we carry all the way down from a[3].) + mask := maskIsNotZero(top) a[3] -= 1 & mask a[2] += mask & (1<<28 - 1) a[1] += mask & (1<<28 - 1) a[0] += mask & (1 << 28) } -// p224Invert calculates *out = in**-1 by computing in**(2**224 - 2**96 - 1), -// i.e. Fermat's little theorem. +// p224Invert calculates *out = in**-1 by using Fermat's little theorem and +// computing in**(p-2) = in**(2**224 - 2**96 - 1). func p224Invert(out, in *p224FieldElement) { var f1, f2, f3, f4 p224FieldElement var c p224LargeFieldElement @@ -408,13 +404,14 @@ func p224Contract(out, in *p224FieldElement) { // out[0] negative then we know that out[3] is sufficiently positive // because we just added to it. for i := 0; i < 3; i++ { - mask := uint32(int32(out[i]) >> 31) + mask := maskIsNegative(out[i]) out[i] += (1 << 28) & mask out[i+1] -= 1 & mask } // We might have pushed out[3] over 2**28 so we perform another, partial, - // carry chain. + // carry chain; carry the overflow according to the reduction identity; and + // carry down in case we made out[0] negative. for i := 3; i < 7; i++ { out[i+1] += out[i] >> 28 out[i] &= bottom28Bits @@ -422,10 +419,15 @@ func p224Contract(out, in *p224FieldElement) { top = out[7] >> 28 out[7] &= bottom28Bits - // Eliminate top while maintaining the same value mod p. out[0] -= top out[3] += top << 12 + for i := 0; i < 3; i++ { + mask := maskIsNegative(out[i]) + out[i] += (1 << 28) & mask + out[i+1] -= 1 & mask + } + // There are two cases to consider for out[3]: // 1) The first time that we eliminated top, we didn't push out[3] over // 2**28. In this case, the partial carry chain didn't change any values @@ -436,60 +438,14 @@ func p224Contract(out, in *p224FieldElement) { // In both cases, out[3] cannot have overflowed when we eliminated top for // the second time. - // Again, we may just have made out[0] negative, so do the same carry down. - // As before, if we made out[0] negative then we know that out[3] is - // sufficiently positive. - for i := 0; i < 3; i++ { - mask := uint32(int32(out[i]) >> 31) - out[i] += (1 << 28) & mask - out[i+1] -= 1 & mask + // Now we need to subtract p if the value is >= p. To check, we subtract p + // with a borrow chain and look at the final borrow bit. + var b uint32 + for i := 0; i < len(out); i++ { + _, b = bits.Sub32(out[i], p224P[i], b) } + mask := ^maskIsNotZero(b) - // Now we see if the value is >= p and, if so, subtract p. - - // First we build a mask from the top four limbs, which must all be - // equal to bottom28Bits if the whole value is >= p. If top4AllOnes - // ends up with any zero bits in the bottom 28 bits, then this wasn't - // true. - top4AllOnes := uint32(0xffffffff) - for i := 4; i < 8; i++ { - top4AllOnes &= out[i] - } - top4AllOnes |= 0xf0000000 - // Now we replicate any zero bits to all the bits in top4AllOnes. - top4AllOnes &= top4AllOnes >> 16 - top4AllOnes &= top4AllOnes >> 8 - top4AllOnes &= top4AllOnes >> 4 - top4AllOnes &= top4AllOnes >> 2 - top4AllOnes &= top4AllOnes >> 1 - top4AllOnes = uint32(int32(top4AllOnes<<31) >> 31) - - // Now we test whether the bottom three limbs are non-zero. - bottom3NonZero := out[0] | out[1] | out[2] - bottom3NonZero |= bottom3NonZero >> 16 - bottom3NonZero |= bottom3NonZero >> 8 - bottom3NonZero |= bottom3NonZero >> 4 - bottom3NonZero |= bottom3NonZero >> 2 - bottom3NonZero |= bottom3NonZero >> 1 - bottom3NonZero = uint32(int32(bottom3NonZero<<31) >> 31) - - // Assuming top4AllOnes != 0, everything depends on the value of out[3]. - // If it's > 0xffff000 then the whole value is > p - // If it's = 0xffff000 and bottom3NonZero != 0, then the whole value is >= p - // If it's < 0xffff000, then the whole value is < p - n := 0xffff000 - out[3] - out3Equal := n - out3Equal |= out3Equal >> 16 - out3Equal |= out3Equal >> 8 - out3Equal |= out3Equal >> 4 - out3Equal |= out3Equal >> 2 - out3Equal |= out3Equal >> 1 - out3Equal = ^uint32(int32(out3Equal<<31) >> 31) - - // If out[3] > 0xffff000 then n's MSB will be one. - out3GT := uint32(int32(n) >> 31) - - mask := top4AllOnes & ((out3Equal & bottom3NonZero) | out3GT) out[0] -= 1 & mask out[3] -= 0xffff000 & mask out[4] -= 0xfffffff & mask @@ -501,12 +457,26 @@ func p224Contract(out, in *p224FieldElement) { // out[0..3] needs to be positive and able to absorb the -1 or the value // would have been < p, and the subtraction wouldn't have happened. for i := 0; i < 3; i++ { - mask := uint32(int32(out[i]) >> 31) + mask := maskIsNegative(out[i]) out[i] += (1 << 28) & mask out[i+1] -= 1 & mask } } +// maskIsNegative returns 0xffffffff if the most significant bit of v is set, +// and 0 otherwise. +func maskIsNegative(v uint32) uint32 { return uint32(int32(v) >> 31) } + +// maskIfNegative returns 0xffffffff if v is not zero, and 0 otherwise. +func maskIsNotZero(v uint32) uint32 { + v |= v >> 16 + v |= v >> 8 + v |= v >> 4 + v |= v >> 2 + v |= v >> 1 + return uint32(int32(v<<31) >> 31) +} + // Group element functions. // // These functions deal with group elements. The group is an elliptic curve @@ -650,14 +620,11 @@ func p224DoubleJacobian(x3, y3, z3, x1, y1, z1 *p224FieldElement) { p224Reduce(y3) } -// p224CopyConditional sets *out = *in iff the least-significant-bit of control -// is true, and it runs in constant time. +// p224CopyConditional sets *out = *in in constant time if control is not zero. func p224CopyConditional(out, in *p224FieldElement, control uint32) { - control <<= 31 - control = uint32(int32(control) >> 31) - + mask := maskIsNotZero(control) for i := 0; i < 8; i++ { - out[i] ^= (out[i] ^ in[i]) & control + out[i] ^= (out[i] ^ in[i]) & mask } } @@ -702,37 +669,27 @@ func p224ToAffine(x, y, z *p224FieldElement) (*big.Int, *big.Int) { } // get28BitsFromEnd returns the least-significant 28 bits from buf>>shift, -// where buf is interpreted as a big-endian number. -func get28BitsFromEnd(buf []byte, shift uint) (uint32, []byte) { - var ret uint32 - - for i := uint(0); i < 4; i++ { - var b byte - if l := len(buf); l > 0 { - b = buf[l-1] - // We don't remove the byte if we're about to return and we're not - // reading all of it. - if i != 3 || shift == 4 { - buf = buf[:l-1] - } - } - ret |= uint32(b) << (8 * i) >> shift +// where buf is interpreted as a big-endian number. shift must be at most +// 4 bits higher than a multiple of 8. +func get28BitsFromEnd(buf []byte, shift int) uint32 { + buf = buf[:len(buf)-shift/8] + shift = shift % 8 + if shift > 4 { + panic("misuse of get28BitsFromEnd") } + + ret := binary.BigEndian.Uint32(buf[len(buf)-4:]) + ret >>= shift ret &= bottom28Bits - return ret, buf + return ret } // p224FromBig sets *out = *in. func p224FromBig(out *p224FieldElement, in *big.Int) { - bytes := in.Bytes() - out[0], bytes = get28BitsFromEnd(bytes, 0) - out[1], bytes = get28BitsFromEnd(bytes, 4) - out[2], bytes = get28BitsFromEnd(bytes, 0) - out[3], bytes = get28BitsFromEnd(bytes, 4) - out[4], bytes = get28BitsFromEnd(bytes, 0) - out[5], bytes = get28BitsFromEnd(bytes, 4) - out[6], bytes = get28BitsFromEnd(bytes, 0) - out[7], bytes = get28BitsFromEnd(bytes, 4) + bytes := in.FillBytes(make([]byte, 224/8)) + for i := range out { + out[i] = get28BitsFromEnd(bytes, 28*i) + } } // p224ToBig returns in as a big.Int. diff --git a/src/crypto/elliptic/p224_test.go b/src/crypto/elliptic/p224_test.go index b213b273d2..3e0c78b0f9 100644 --- a/src/crypto/elliptic/p224_test.go +++ b/src/crypto/elliptic/p224_test.go @@ -261,7 +261,7 @@ func TestP224IsZero(t *testing.T) { if got := p224IsZero(&p224FieldElement{}); got != 1 { t.Errorf("p224IsZero(0) = %d, expected 1", got) } - if got := p224IsZero((*p224FieldElement)(&p224P)); got != 1 { + if got := p224IsZero(&p224P); got != 1 { t.Errorf("p224IsZero(p) = %d, expected 1", got) } if got := p224IsZero(&p224FieldElement{1}); got != 0 { @@ -294,7 +294,7 @@ func TestP224Invert(t *testing.T) { t.Errorf("p224Invert(0) = %x, expected 0", out) } - p224Invert(&out, (*p224FieldElement)(&p224P)) + p224Invert(&out, &p224P) if got := p224IsZero(&out); got != 1 { t.Errorf("p224Invert(p) = %x, expected 0", out) } -- GitLab From 3571ab58b8069fd945427ba49c4d8a702325bdb0 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Fri, 29 Oct 2021 17:47:32 -0400 Subject: [PATCH 1833/2500] go/types: make built-in to accept type sets with single underlying types This is a straightforward port of CL 357776 to go/types. Change-Id: I64220840a01f57cd7955f7d956b9aa8227473b46 Reviewed-on: https://go-review.googlesource.com/c/go/+/359874 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/builtins.go | 6 +++--- src/go/types/testdata/check/builtins.go2 | 22 +++++++++++++--------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 29a8339f3e..de7d7e6b5f 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -469,13 +469,13 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b } var min int // minimum number of arguments - switch optype(T).(type) { + switch singleUnder(T).(type) { case *Slice: min = 2 case *Map, *Chan: min = 1 - case *top: - check.invalidArg(arg0, _InvalidMake, "cannot make %s; type parameter has no structural type", arg0) + case nil: + check.errorf(arg0, _InvalidMake, "cannot make %s; type set has no single underlying type", arg0) return default: check.invalidArg(arg0, _InvalidMake, "cannot make %s; type must be slice, map, or channel", arg0) diff --git a/src/go/types/testdata/check/builtins.go2 b/src/go/types/testdata/check/builtins.go2 index f9b6ec7926..7cca6fd714 100644 --- a/src/go/types/testdata/check/builtins.go2 +++ b/src/go/types/testdata/check/builtins.go2 @@ -127,15 +127,18 @@ func _[T M4[K, V], K comparable, V any](m T) { // make +type myChan chan int + func _[ - S1 interface{ []int }, - S2 interface{ []int | chan int }, + S1 ~[]int, + S2 ~[]int | ~chan int, - M1 interface{ map[string]int }, - M2 interface{ map[string]int | chan int }, + M1 ~map[string]int, + M2 ~map[string]int | ~chan int, - C1 interface{ chan int }, - C2 interface{ chan int | chan string }, + C1 ~chan int, + C2 ~chan int | ~chan string, + C3 chan int | myChan, // single underlying type ]() { type S0 []int _ = make([]int, 10) @@ -145,7 +148,7 @@ func _[ _ = make /* ERROR expects 2 or 3 arguments */ (S1) _ = make(S1, 10, 20) _ = make /* ERROR expects 2 or 3 arguments */ (S1, 10, 20, 30) - _ = make(S2 /* ERROR cannot make .* no structural type */ , 10) + _ = make(S2 /* ERROR cannot make .* no single underlying type */ , 10) type M0 map[string]int _ = make(map[string]int) @@ -153,7 +156,7 @@ func _[ _ = make(M1) _ = make(M1, 10) _ = make/* ERROR expects 1 or 2 arguments */(M1, 10, 20) - _ = make(M2 /* ERROR cannot make .* no structural type */ ) + _ = make(M2 /* ERROR cannot make .* no single underlying type */ ) type C0 chan int _ = make(chan int) @@ -161,7 +164,8 @@ func _[ _ = make(C1) _ = make(C1, 10) _ = make/* ERROR expects 1 or 2 arguments */(C1, 10, 20) - _ = make(C2 /* ERROR cannot make .* no structural type */ ) + _ = make(C2 /* ERROR cannot make .* no single underlying type */ ) + _ = make(C3) } // unsafe.Alignof -- GitLab From 02bd226b8abb713061fcef4e53ffebc57770466b Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Fri, 29 Oct 2021 18:01:09 -0400 Subject: [PATCH 1834/2500] go/types: range clause to accept type sets with single underlying types This is a port of CL 357778 to go/types, adjusted to include error codes and to use the different range statement syntax in go/ast. Change-Id: Id537c195cd33a8b422a366269ca8730c2a5bccf1 Reviewed-on: https://go-review.googlesource.com/c/go/+/359875 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer --- src/go/types/stmt.go | 71 +++++++++------------- src/go/types/testdata/check/typeparams.go2 | 12 ++-- 2 files changed, 35 insertions(+), 48 deletions(-) diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index 92542597c5..7197310bd9 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -832,20 +832,28 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { // determine key/value types var key, val Type if x.mode != invalid { - // Ranging over a type parameter is permitted if it has a structural type. - typ := optype(x.typ) - if _, ok := typ.(*Chan); ok && s.Value != nil { - check.softErrorf(atPos(s.Value.Pos()), _InvalidIterVar, "range over %s permits only one iteration variable", &x) - // ok to continue + // Ranging over a type parameter is permitted if it has a single underlying type. + var cause string + u := singleUnder(x.typ) + switch t := u.(type) { + case nil: + cause = "type set has no single underlying type" + case *Chan: + if s.Value != nil { + check.softErrorf(s.Value, _InvalidIterVar, "range over %s permits only one iteration variable", &x) + // ok to continue + } + if t.dir == SendOnly { + cause = "receive from send-only channel" + } } - var msg string - key, val, msg = rangeKeyVal(typ, isVarName(s.Key), isVarName(s.Value)) - if key == nil || msg != "" { - if msg != "" { - // TODO(rFindley) should this be parenthesized, to be consistent with other qualifiers? - msg = ": " + msg + key, val = rangeKeyVal(u) + if key == nil || cause != "" { + if cause == "" { + check.softErrorf(&x, _InvalidRangeExpr, "cannot range over %s", &x) + } else { + check.softErrorf(&x, _InvalidRangeExpr, "cannot range over %s (%s)", &x, cause) } - check.softErrorf(&x, _InvalidRangeExpr, "cannot range over %s%s", &x, msg) // ok to continue } } @@ -930,44 +938,23 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { } } -// isVarName reports whether x is a non-nil, non-blank (_) expression. -func isVarName(x ast.Expr) bool { - if x == nil { - return false - } - ident, _ := unparen(x).(*ast.Ident) - return ident == nil || ident.Name != "_" -} - // rangeKeyVal returns the key and value type produced by a range clause -// over an expression of type typ, and possibly an error message. If the -// range clause is not permitted the returned key is nil or msg is not -// empty (in that case we still may have a non-nil key type which can be -// used to reduce the chance for follow-on errors). -// The wantKey, wantVal, and hasVal flags indicate which of the iteration -// variables are used or present; this matters if we range over a generic -// type where not all keys or values are of the same type. -func rangeKeyVal(typ Type, wantKey, wantVal bool) (Type, Type, string) { +// over an expression of type typ. If the range clause is not permitted +// the results are nil. +func rangeKeyVal(typ Type) (key, val Type) { switch typ := arrayPtrDeref(typ).(type) { case *Basic: if isString(typ) { - return Typ[Int], universeRune, "" // use 'rune' name + return Typ[Int], universeRune // use 'rune' name } case *Array: - return Typ[Int], typ.elem, "" + return Typ[Int], typ.elem case *Slice: - return Typ[Int], typ.elem, "" + return Typ[Int], typ.elem case *Map: - return typ.key, typ.elem, "" + return typ.key, typ.elem case *Chan: - var msg string - if typ.dir == SendOnly { - msg = "receive from send-only channel" - } - return typ.elem, Typ[Invalid], msg - case *top: - // we have a type parameter with no structural type - return nil, nil, "no structural type" + return typ.elem, Typ[Invalid] } - return nil, nil, "" + return } diff --git a/src/go/types/testdata/check/typeparams.go2 b/src/go/types/testdata/check/typeparams.go2 index 10f84314fd..c4b0c212d2 100644 --- a/src/go/types/testdata/check/typeparams.go2 +++ b/src/go/types/testdata/check/typeparams.go2 @@ -184,7 +184,7 @@ func _[ for _, _ = range b1 {} var b2 B2 - for range b2 /* ERROR cannot range over b2 .* no structural type */ {} + for range b2 {} var c0 chan int for range c0 {} @@ -197,7 +197,7 @@ func _[ for _, _ /* ERROR permits only one iteration variable */ = range c1 {} var c2 C2 - for range c2 /* ERROR cannot range over c2 .* no structural type */ {} + for range c2 /* ERROR cannot range over c2.*no single underlying type */ {} var c3 C3 for range c3 /* ERROR receive from send-only channel */ {} @@ -213,7 +213,7 @@ func _[ for _, _ = range s1 {} var s2 S2 - for range s2 /* ERROR cannot range over s2 .* no structural type */ {} + for range s2 /* ERROR cannot range over s2.*no single underlying type */ {} var a0 []int for range a0 {} @@ -226,7 +226,7 @@ func _[ for _, _ = range a1 {} var a2 A2 - for range a2 /* ERROR cannot range over a2 .* no structural type */ {} + for range a2 /* ERROR cannot range over a2.*no single underlying type */ {} var p0 *[10]int for range p0 {} @@ -239,7 +239,7 @@ func _[ for _, _ = range p1 {} var p2 P2 - for range p2 /* ERROR cannot range over p2 .* no structural type */ {} + for range p2 /* ERROR cannot range over p2.*no single underlying type */ {} var m0 map[string]int for range m0 {} @@ -252,7 +252,7 @@ func _[ for _, _ = range m1 {} var m2 M2 - for range m2 /* ERROR cannot range over m2 .* no structural type */ {} + for range m2 /* ERROR cannot range over m2.*no single underlying type */ {} } // type inference checks -- GitLab From 71e6ab8f958bf346f9e0b46c4a35310615360215 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Fri, 29 Oct 2021 18:06:15 -0400 Subject: [PATCH 1835/2500] go/types: slice exprs to accept type sets with single underlying types This is a port of CL 357779 to go/types. A test error message was repositioned on the sliced operand. Change-Id: Ie775c128f70d9cb08a2eba54b8bc082134ec3200 Reviewed-on: https://go-review.googlesource.com/c/go/+/359876 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/index.go | 21 +++++++++++++-------- src/go/types/testdata/check/typeparams.go2 | 5 +++++ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/go/types/index.go b/src/go/types/index.go index 613f6292e4..24c1812039 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -207,9 +207,14 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { valid := false length := int64(-1) // valid if >= 0 - switch typ := optype(x.typ).(type) { + switch u := singleUnder(x.typ).(type) { + case nil: + check.errorf(x, _NonSliceableOperand, "cannot slice %s: type set has no single underlying type", x) + x.mode = invalid + return + case *Basic: - if isString(typ) { + if isString(u) { if e.Slice3 { check.invalidOp(x, _InvalidSliceExpr, "3-index slice of string") x.mode = invalid @@ -221,26 +226,26 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { } // spec: "For untyped string operands the result // is a non-constant value of type string." - if typ.kind == UntypedString { + if u.kind == UntypedString { x.typ = Typ[String] } } case *Array: valid = true - length = typ.len + length = u.len if x.mode != variable { check.invalidOp(x, _NonSliceableOperand, "cannot slice %s (value not addressable)", x) x.mode = invalid return } - x.typ = &Slice{elem: typ.elem} + x.typ = &Slice{elem: u.elem} case *Pointer: - if typ := asArray(typ.base); typ != nil { + if u := asArray(u.base); u != nil { valid = true - length = typ.len - x.typ = &Slice{elem: typ.elem} + length = u.len + x.typ = &Slice{elem: u.elem} } case *Slice: diff --git a/src/go/types/testdata/check/typeparams.go2 b/src/go/types/testdata/check/typeparams.go2 index c4b0c212d2..3694b0ed00 100644 --- a/src/go/types/testdata/check/typeparams.go2 +++ b/src/go/types/testdata/check/typeparams.go2 @@ -123,6 +123,11 @@ func _[T interface{ ~[]byte }] (x T, i, j, k int) { var _ T = x[i:j:k] } func _[T interface{ ~string }] (x T, i, j, k int) { var _ T = x[i:j] } func _[T interface{ ~string }] (x T, i, j, k int) { var _ T = x /* ERROR 3-index slice of string */ [i:j:k] } +type myByte1 []byte +type myByte2 []byte +func _[T interface{ []byte | myByte1 | myByte2 }] (x T, i, j, k int) { var _ T = x[i:j:k] } +func _[T interface{ []byte | myByte1 | []int }] (x T, i, j, k int) { var _ T = x /* ERROR no single underlying type */ [i:j:k] } + // len/cap built-ins func _[T any](x T) { _ = len(x /* ERROR invalid argument */ ) } -- GitLab From c812b97ec67ae2d674b5bb4e2fd29c7ab7fa08dc Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Fri, 29 Oct 2021 18:08:08 -0400 Subject: [PATCH 1836/2500] go/types: comp literals to accept type sets with single underlying types This is a clean port of CL 357915 to go/types. Change-Id: Idf5850a8bdcf3596c561c97bcd60539945139743 Reviewed-on: https://go-review.googlesource.com/c/go/+/359877 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/expr.go | 2 +- src/go/types/testdata/check/compliterals.go2 | 22 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/go/types/testdata/check/compliterals.go2 diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 3a09dfd85f..8b26e64971 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -1223,7 +1223,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { goto Error } - switch utyp := optype(base).(type) { + switch utyp := singleUnder(base).(type) { case *Struct: if len(e.Elts) == 0 { break diff --git a/src/go/types/testdata/check/compliterals.go2 b/src/go/types/testdata/check/compliterals.go2 new file mode 100644 index 0000000000..60eac97a3f --- /dev/null +++ b/src/go/types/testdata/check/compliterals.go2 @@ -0,0 +1,22 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Composite literals with parameterized types + +package comp_literals + +type myStruct struct { + f int +} + +type slice[E any] []E + +func struct_literals[S struct{f int}|myStruct]() { + _ = S{} + _ = S{0} + _ = S{f: 0} + + _ = slice[int]{1, 2, 3} + _ = slice[S]{{}, {0}, {f:0}} +} -- GitLab From 8dfb4472318e151656f77623e8cabdca290c22fb Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 13 Oct 2021 20:48:45 -0700 Subject: [PATCH 1837/2500] runtime: do not add open defer entry above a started open defer entry Fix two defer bugs related to adding/removing open defer entries. The bugs relate to the way that we add and remove open defer entries from the defer chain. At the point of a panic, when we want to start processing defer entries in order during the panic process, we need to add entries to the defer chain for stack frames with open defers, since the normal fast-defer code does not add these entries. We do this by calling addOneOpenDeferFrame() at the beginning of each time around the defer loop in gopanic(). Those defer entries get sorted with other open and non-open-coded defer frames. However, the tricky part is that we also need to remove defer entries if they end not being needed because of a recover (which means we are back to executing the defer code inline at function exits). But we need to deal with multiple panics and in-process defers on the stack, so we can't just remove all open-coded defers from the the defer chain during a recover. The fix (and new invariant) is that we should not add any open-coded defers to the defer chain that are higher up the stack than an open-coded defer that is in progress. We know that open-coded defer will still be run until completed, and when it is completed, then a more outer frame will be added (if there is one). This fits with existing code in gopanic that only removes open-coded defer entries up to any defer in progress. These bugs were because of the previous inconsistency between adding and removing open defer entries, which meant that stale defer entries could be left on the list, in these unusual cases with both recursive panics plus multiple independent (non-nested) cases of panic & recover. The test for #48898 was difficult to add to defer_test.go (while keeping the failure mode), so I added as a go/test/fixedbug test instead. Fixes #43920 Updates #43941 Fixes #48898 Change-Id: I593b77033e08c33094315abf8089fbc4cab07376 Reviewed-on: https://go-review.googlesource.com/c/go/+/356011 Trust: Dan Scales Trust: Cuong Manh Le Reviewed-by: Austin Clements --- src/runtime/defer_test.go | 79 +++++++++++++++++++++++++++++++++++ src/runtime/panic.go | 55 +++++++++++++++++------- test/fixedbugs/issue48898.go | 40 ++++++++++++++++++ test/fixedbugs/issue48898.out | 1 + 4 files changed, 161 insertions(+), 14 deletions(-) create mode 100644 test/fixedbugs/issue48898.go create mode 100644 test/fixedbugs/issue48898.out diff --git a/src/runtime/defer_test.go b/src/runtime/defer_test.go index fc96144597..1d5745d60b 100644 --- a/src/runtime/defer_test.go +++ b/src/runtime/defer_test.go @@ -438,3 +438,82 @@ func expect(t *testing.T, n int, err interface{}) { t.Fatalf("have %v, want %v", err, n) } } + +func TestIssue43920(t *testing.T) { + var steps int + + defer func() { + expect(t, 1, recover()) + }() + defer func() { + defer func() { + defer func() { + expect(t, 5, recover()) + }() + defer panic(5) + func() { + panic(4) + }() + }() + defer func() { + expect(t, 3, recover()) + }() + defer panic(3) + }() + func() { + defer step(t, &steps, 1) + panic(1) + }() +} + +func step(t *testing.T, steps *int, want int) { + println("step", want) + *steps++ + if *steps != want { + t.Fatalf("have %v, want %v", *steps, want) + } +} + +func TestIssue43941(t *testing.T) { + var steps int = 7 + defer func() { + step(t, &steps, 14) + expect(t, 4, recover()) + }() + func() { + func() { + defer func() { + defer func() { + expect(t, 3, recover()) + }() + defer panic(3) + panic(2) + }() + defer func() { + expect(t, 1, recover()) + }() + defer panic(1) + }() + defer func() {}() + defer func() {}() + defer step(t, &steps, 10) + defer step(t, &steps, 9) + step(t, &steps, 8) + }() + func() { + defer step(t, &steps, 13) + defer step(t, &steps, 12) + func() { + defer step(t, &steps, 11) + panic(4) + }() + + // Code below isn't executed, + // but removing it breaks the test case. + defer func() {}() + defer panic(-1) + defer step(t, &steps, -1) + defer step(t, &steps, -1) + defer func() {}() + }() +} diff --git a/src/runtime/panic.go b/src/runtime/panic.go index 58135cf8ce..eec69dfdc6 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -560,14 +560,28 @@ func printpanics(p *_panic) { print("\n") } -// addOneOpenDeferFrame scans the stack for the first frame (if any) with -// open-coded defers and if it finds one, adds a single record to the defer chain -// for that frame. If sp is non-nil, it starts the stack scan from the frame -// specified by sp. If sp is nil, it uses the sp from the current defer record -// (which has just been finished). Hence, it continues the stack scan from the -// frame of the defer that just finished. It skips any frame that already has an -// open-coded _defer record, which would have been created from a previous -// (unrecovered) panic. +// addOneOpenDeferFrame scans the stack (in gentraceback order, from inner frames to +// outer frames) for the first frame (if any) with open-coded defers. If it finds +// one, it adds a single entry to the defer chain for that frame. The entry added +// represents all the defers in the associated open defer frame, and is sorted in +// order with respect to any non-open-coded defers. +// +// addOneOpenDeferFrame stops (possibly without adding a new entry) if it encounters +// an in-progress open defer entry. An in-progress open defer entry means there has +// been a new panic because of a defer in the associated frame. addOneOpenDeferFrame +// does not add an open defer entry past a started entry, because that started entry +// still needs to finished, and addOneOpenDeferFrame will be called when that started +// entry is completed. The defer removal loop in gopanic() similarly stops at an +// in-progress defer entry. Together, addOneOpenDeferFrame and the defer removal loop +// ensure the invariant that there is no open defer entry further up the stack than +// an in-progress defer, and also that the defer removal loop is guaranteed to remove +// all not-in-progress open defer entries from the defer chain. +// +// If sp is non-nil, addOneOpenDeferFrame starts the stack scan from the frame +// specified by sp. If sp is nil, it uses the sp from the current defer record (which +// has just been finished). Hence, it continues the stack scan from the frame of the +// defer that just finished. It skips any frame that already has a (not-in-progress) +// open-coded _defer record in the defer chain. // // Note: All entries of the defer chain (including this new open-coded entry) have // their pointers (including sp) adjusted properly if the stack moves while @@ -608,6 +622,16 @@ func addOneOpenDeferFrame(gp *g, pc uintptr, sp unsafe.Pointer) { if !d.openDefer { throw("duplicated defer entry") } + // Don't add any record past an + // in-progress defer entry. We don't + // need it, and more importantly, we + // want to keep the invariant that + // there is no open defer entry + // passed an in-progress entry (see + // header comment). + if d.started { + return false + } return true } prev = d @@ -849,12 +873,15 @@ func gopanic(e interface{}) { } atomic.Xadd(&runningPanicDefers, -1) - // Remove any remaining non-started, open-coded - // defer entries after a recover, since the - // corresponding defers will be executed normally - // (inline). Any such entry will become stale once - // we run the corresponding defers inline and exit - // the associated stack frame. + // After a recover, remove any remaining non-started, + // open-coded defer entries, since the corresponding defers + // will be executed normally (inline). Any such entry will + // become stale once we run the corresponding defers inline + // and exit the associated stack frame. We only remove up to + // the first started (in-progress) open defer entry, not + // including the current frame, since any higher entries will + // be from a higher panic in progress, and will still be + // needed. d := gp._defer var prev *_defer if !done { diff --git a/test/fixedbugs/issue48898.go b/test/fixedbugs/issue48898.go new file mode 100644 index 0000000000..c3af16480f --- /dev/null +++ b/test/fixedbugs/issue48898.go @@ -0,0 +1,40 @@ +// run + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func main() { + defer func() { + println(recover().(int)) + }() + func() { + func() (_ [2]int) { type _ int; return }() + func() { + defer func() { + defer func() { + recover() + }() + defer panic(3) + panic(2) + }() + defer func() { + recover() + }() + panic(1) + }() + defer func() {}() + }() + + var x = 123 + func() { + // in the original issue, this defer was not executed (which is incorrect) + defer print(x) + func() { + defer func() {}() + panic(4) + }() + }() +} diff --git a/test/fixedbugs/issue48898.out b/test/fixedbugs/issue48898.out new file mode 100644 index 0000000000..81c545efeb --- /dev/null +++ b/test/fixedbugs/issue48898.out @@ -0,0 +1 @@ +1234 -- GitLab From 5d6d9f5610066584374c2dfe7624fa9f251089a0 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 27 Oct 2021 19:16:27 -0700 Subject: [PATCH 1838/2500] cmd/compile: use Structure() to get single underlying type of typeparam. Use types2.Structure() to get single underlying type of typeparams, to handle some unusual cases where a type param is constrained to a single underlying struct or map type. Fixes #48538 Change-Id: I289fb7b31d489f7586f2b04aeb1df74e15a9f965 Reviewed-on: https://go-review.googlesource.com/c/go/+/359335 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/noder/expr.go | 2 +- test/run.go | 1 + test/typeparam/issue48538.go | 60 ++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 test/typeparam/issue48538.go diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 65568f2307..d19513a1ac 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -344,7 +344,7 @@ func (g *irgen) compLit(typ types2.Type, lit *syntax.CompositeLit) ir.Node { return typed(g.typ(typ), n) } - _, isStruct := typ.Underlying().(*types2.Struct) + _, isStruct := types2.Structure(typ).(*types2.Struct) exprs := make([]ir.Node, len(lit.ElemList)) for i, elem := range lit.ElemList { diff --git a/test/run.go b/test/run.go index 0c5da1af78..942fd032f2 100644 --- a/test/run.go +++ b/test/run.go @@ -2188,6 +2188,7 @@ var unifiedFailures = setOf( "fixedbugs/issue42284.go", // prints "T(0) does not escape", but test expects "a.I(a.T(0)) does not escape" "fixedbugs/issue7921.go", // prints "… escapes to heap", but test expects "string(…) escapes to heap" + "typeparam/issue48538.go", // assertion failure, interprets struct key as closure variable ) func setOf(keys ...string) map[string]bool { diff --git a/test/typeparam/issue48538.go b/test/typeparam/issue48538.go new file mode 100644 index 0000000000..fed9b5e9a6 --- /dev/null +++ b/test/typeparam/issue48538.go @@ -0,0 +1,60 @@ +// compile -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Testing composite literal for a type param constrained to be a struct or a map. + +package p + +type C interface { + ~struct{ b1, b2 string } +} + +func f[T C]() T { + return T{ + b1: "a", + b2: "b", + } +} + +func f2[T ~struct{ b1, b2 string }]() T { + return T{ + b1: "a", + b2: "b", + } +} + +type D interface { + map[string]string | S +} + +type S map[string]string + +func g[T D]() T { + b1 := "foo" + b2 := "bar" + return T{ + b1: "a", + b2: "b", + } +} + +func g2[T map[string]string]() T { + b1 := "foo" + b2 := "bar" + return T{ + b1: "a", + b2: "b", + } +} + +func g3[T S]() T { + b1 := "foo" + b2 := "bar" + return T{ + b1: "a", + b2: "b", + } +} -- GitLab From e39b854a6797a7159602f0d6b351ef35ebfa01d0 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Thu, 13 May 2021 15:33:48 -0400 Subject: [PATCH 1839/2500] crypto/elliptic: use complete addition formulas for P-521 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Complete formulas don't have exceptions for P = Q or P = 0, which makes them significantly simpler and safer to implement. Notice how the constant time IsZero checks are gone. It's not free, but still well within the performance gains of CL 315271. name old time/op new time/op delta pkg:crypto/elliptic goos:darwin goarch:amd64 ScalarBaseMult/P521-16 1.34ms ± 3% 1.63ms ± 4% +21.78% (p=0.000 n=10+10) ScalarMult/P521-16 1.35ms ± 3% 1.65ms ± 4% +22.58% (p=0.000 n=10+10) pkg:crypto/ecdsa goos:darwin goarch:amd64 Sign/P521-16 1.45ms ± 2% 1.67ms ± 1% +15.00% (p=0.000 n=10+8) Verify/P521-16 2.68ms ± 1% 3.10ms ± 2% +16.02% (p=0.000 n=10+9) GenerateKey/P521-16 1.31ms ± 4% 1.53ms ± 1% +16.89% (p=0.000 n=10+9) Change-Id: Ibd9a961e9865df68a1250aba739c190caf9a54de Reviewed-on: https://go-review.googlesource.com/c/go/+/320071 Trust: Filippo Valsorda Run-TryBot: Filippo Valsorda TryBot-Result: Go Bot Reviewed-by: Julie Qiu --- src/crypto/elliptic/p521.go | 261 ++++++++++++++++++------------------ 1 file changed, 131 insertions(+), 130 deletions(-) diff --git a/src/crypto/elliptic/p521.go b/src/crypto/elliptic/p521.go index 3d355943ec..463b9f4e39 100644 --- a/src/crypto/elliptic/p521.go +++ b/src/crypto/elliptic/p521.go @@ -11,6 +11,7 @@ import ( type p521Curve struct { *CurveParams + b *fiat.P521Element } var p521 p521Curve @@ -25,6 +26,7 @@ func initP521() { p521.Gx, _ = new(big.Int).SetString("c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", 16) p521.Gy, _ = new(big.Int).SetString("11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", 16) p521.BitSize = 521 + p521.b = bigIntToFiatP521(p521.B) } func (curve p521Curve) Params() *CurveParams { @@ -34,7 +36,6 @@ func (curve p521Curve) Params() *CurveParams { func (curve p521Curve) IsOnCurve(x, y *big.Int) bool { x1 := bigIntToFiatP521(x) y1 := bigIntToFiatP521(y) - b := bigIntToFiatP521(curve.B) // TODO: precompute this value. // x³ - 3x + b. x3 := new(fiat.P521Element).Square(x1) @@ -44,7 +45,7 @@ func (curve p521Curve) IsOnCurve(x, y *big.Int) bool { threeX.Add(threeX, x1) x3.Sub(x3, threeX) - x3.Add(x3, b) + x3.Add(x3, curve.b) // y² = x³ - 3x + b y2 := new(fiat.P521Element).Square(y1) @@ -52,10 +53,20 @@ func (curve p521Curve) IsOnCurve(x, y *big.Int) bool { return x3.Equal(y2) == 1 } +// p521Point is a P-521 point in projective coordinates, where x = X/Z, y = Y/Z. type p521Point struct { x, y, z *fiat.P521Element } +// newP521Point returns a new p521Point representing the identity point. +func newP521Point() *p521Point { + return &p521Point{ + x: new(fiat.P521Element), + y: new(fiat.P521Element).One(), + z: new(fiat.P521Element), + } +} + func fiatP521ToBigInt(x *fiat.P521Element) *big.Int { xBytes := x.Bytes() for i := range xBytes[:len(xBytes)/2] { @@ -64,20 +75,16 @@ func fiatP521ToBigInt(x *fiat.P521Element) *big.Int { return new(big.Int).SetBytes(xBytes) } -// affineFromJacobian brings a point in Jacobian coordinates back to affine -// coordinates, with (0, 0) representing infinity by convention. It also goes -// back to big.Int values to match the exposed API. -func (curve p521Curve) affineFromJacobian(p *p521Point) (x, y *big.Int) { +// Affine returns p in affine coordinates, with (0, 0) representing infinity by +// convention. It also goes back to big.Int values to match the exposed API. +func (p *p521Point) Affine() (x, y *big.Int) { if p.z.IsZero() == 1 { return new(big.Int), new(big.Int) } zinv := new(fiat.P521Element).Invert(p.z) - zinvsq := new(fiat.P521Element).Mul(zinv, zinv) - - xx := new(fiat.P521Element).Mul(p.x, zinvsq) - zinvsq.Mul(zinvsq, zinv) - yy := new(fiat.P521Element).Mul(p.y, zinvsq) + xx := new(fiat.P521Element).Mul(p.x, zinv) + yy := new(fiat.P521Element).Mul(p.y, zinv) return fiatP521ToBigInt(xx), fiatP521ToBigInt(yy) } @@ -96,18 +103,14 @@ func bigIntToFiatP521(x *big.Int) *fiat.P521Element { return x1 } -// jacobianFromAffine converts (x, y) affine coordinates into (x, y, z) Jacobian +// newP521PointFromAffine converts (x, y) affine coordinates into (X, Y, Z) projective // coordinates. It also converts from big.Int to fiat, which is necessarily a // messy and variable-time operation, which we can't avoid due to the exposed API. -func (curve p521Curve) jacobianFromAffine(x, y *big.Int) *p521Point { +func newP521PointFromAffine(x, y *big.Int) *p521Point { // (0, 0) is by convention the point at infinity, which can't be represented - // in affine coordinates, but is (0, 0, 0) in Jacobian. + // in affine coordinates, but is (0, 0, 0) in projective coordinates. if x.Sign() == 0 && y.Sign() == 0 { - return &p521Point{ - x: new(fiat.P521Element), - y: new(fiat.P521Element), - z: new(fiat.P521Element), - } + return newP521Point() } return &p521Point{ x: bigIntToFiatP521(x), @@ -117,65 +120,59 @@ func (curve p521Curve) jacobianFromAffine(x, y *big.Int) *p521Point { } func (curve p521Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { - p1 := curve.jacobianFromAffine(x1, y1) - p2 := curve.jacobianFromAffine(x2, y2) - return curve.affineFromJacobian(p1.addJacobian(p1, p2)) + p1 := newP521PointFromAffine(x1, y1) + p2 := newP521PointFromAffine(x2, y2) + return p1.Add(p1, p2).Affine() } -// addJacobian sets q = p1 + p2, and returns q. The points may overlap. -func (q *p521Point) addJacobian(p1, p2 *p521Point) *p521Point { - // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl - z1IsZero := p1.z.IsZero() - z2IsZero := p2.z.IsZero() - - z1z1 := new(fiat.P521Element).Square(p1.z) - z2z2 := new(fiat.P521Element).Square(p2.z) - - u1 := new(fiat.P521Element).Mul(p1.x, z2z2) - u2 := new(fiat.P521Element).Mul(p2.x, z1z1) - h := new(fiat.P521Element).Sub(u2, u1) - xEqual := h.IsZero() == 1 - i := new(fiat.P521Element).Add(h, h) - i.Square(i) - j := new(fiat.P521Element).Mul(h, i) - - s1 := new(fiat.P521Element).Mul(p1.y, p2.z) - s1.Mul(s1, z2z2) - s2 := new(fiat.P521Element).Mul(p2.y, p1.z) - s2.Mul(s2, z1z1) - r := new(fiat.P521Element).Sub(s2, s1) - yEqual := r.IsZero() == 1 - if xEqual && yEqual && z1IsZero == 0 && z2IsZero == 0 { - return q.doubleJacobian(p1) - } - r.Add(r, r) - v := new(fiat.P521Element).Mul(u1, i) - - x := new(fiat.P521Element).Set(r) - x.Square(x) - x.Sub(x, j) - x.Sub(x, v) - x.Sub(x, v) - - y := new(fiat.P521Element).Set(r) - v.Sub(v, x) - y.Mul(y, v) - s1.Mul(s1, j) - s1.Add(s1, s1) - y.Sub(y, s1) - - z := new(fiat.P521Element).Add(p1.z, p2.z) - z.Square(z) - z.Sub(z, z1z1) - z.Sub(z, z2z2) - z.Mul(z, h) - - x.Select(p2.x, x, z1IsZero) - x.Select(p1.x, x, z2IsZero) - y.Select(p2.y, y, z1IsZero) - y.Select(p1.y, y, z2IsZero) - z.Select(p2.z, z, z1IsZero) - z.Select(p1.z, z, z2IsZero) +// Add sets q = p1 + p2, and returns q. The points may overlap. +func (q *p521Point) Add(p1, p2 *p521Point) *p521Point { + // Complete addition formula for a = -3 from "Complete addition formulas for + // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §A.2. + + t0 := new(fiat.P521Element).Mul(p1.x, p2.x) // t0 := X1 * X2 + t1 := new(fiat.P521Element).Mul(p1.y, p2.y) // t1 := Y1 * Y2 + t2 := new(fiat.P521Element).Mul(p1.z, p2.z) // t2 := Z1 * Z2 + t3 := new(fiat.P521Element).Add(p1.x, p1.y) // t3 := X1 + Y1 + t4 := new(fiat.P521Element).Add(p2.x, p2.y) // t4 := X2 + Y2 + t3.Mul(t3, t4) // t3 := t3 * t4 + t4.Add(t0, t1) // t4 := t0 + t1 + t3.Sub(t3, t4) // t3 := t3 - t4 + t4.Add(p1.y, p1.z) // t4 := Y1 + Z1 + x := new(fiat.P521Element).Add(p2.y, p2.z) // X3 := Y2 + Z2 + t4.Mul(t4, x) // t4 := t4 * X3 + x.Add(t1, t2) // X3 := t1 + t2 + t4.Sub(t4, x) // t4 := t4 - X3 + x.Add(p1.x, p1.z) // X3 := X1 + Z1 + y := new(fiat.P521Element).Add(p2.x, p2.z) // Y3 := X2 + Z2 + x.Mul(x, y) // X3 := X3 * Y3 + y.Add(t0, t2) // Y3 := t0 + t2 + y.Sub(x, y) // Y3 := X3 - Y3 + z := new(fiat.P521Element).Mul(p521.b, t2) // Z3 := b * t2 + x.Sub(y, z) // X3 := Y3 - Z3 + z.Add(x, x) // Z3 := X3 + X3 + x.Add(x, z) // X3 := X3 + Z3 + z.Sub(t1, x) // Z3 := t1 - X3 + x.Add(t1, x) // X3 := t1 + X3 + y.Mul(p521.b, y) // Y3 := b * Y3 + t1.Add(t2, t2) // t1 := t2 + t2 + t2.Add(t1, t2) // t2 := t1 + t2 + y.Sub(y, t2) // Y3 := Y3 - t2 + y.Sub(y, t0) // Y3 := Y3 - t0 + t1.Add(y, y) // t1 := Y3 + Y3 + y.Add(t1, y) // Y3 := t1 + Y3 + t1.Add(t0, t0) // t1 := t0 + t0 + t0.Add(t1, t0) // t0 := t1 + t0 + t0.Sub(t0, t2) // t0 := t0 - t2 + t1.Mul(t4, y) // t1 := t4 * Y3 + t2.Mul(t0, y) // t2 := t0 * Y3 + y.Mul(x, z) // Y3 := X3 * Z3 + y.Add(y, t2) // Y3 := Y3 + t2 + x.Mul(t3, x) // X3 := t3 * X3 + x.Sub(x, t1) // X3 := X3 - t1 + z.Mul(t4, z) // Z3 := t4 * Z3 + t1.Mul(t3, t0) // t1 := t3 * t0 + z.Add(z, t1) // Z3 := Z3 + t1 q.x.Set(x) q.y.Set(y) @@ -184,74 +181,78 @@ func (q *p521Point) addJacobian(p1, p2 *p521Point) *p521Point { } func (curve p521Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { - p := curve.jacobianFromAffine(x1, y1) - return curve.affineFromJacobian(p.doubleJacobian(p)) + p := newP521PointFromAffine(x1, y1) + return p.Double(p).Affine() } -// doubleJacobian sets q = p + p, and returns q. The points may overlap. -func (q *p521Point) doubleJacobian(p *p521Point) *p521Point { - // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b - delta := new(fiat.P521Element).Square(p.z) - gamma := new(fiat.P521Element).Square(p.y) - alpha := new(fiat.P521Element).Sub(p.x, delta) - alpha2 := new(fiat.P521Element).Add(p.x, delta) - alpha.Mul(alpha, alpha2) - alpha2.Set(alpha) - alpha.Add(alpha, alpha) - alpha.Add(alpha, alpha2) - - beta := alpha2.Mul(p.x, gamma) - - q.x.Square(alpha) - beta8 := new(fiat.P521Element).Add(beta, beta) - beta8.Add(beta8, beta8) - beta8.Add(beta8, beta8) - q.x.Sub(q.x, beta8) - - q.z.Add(p.y, p.z) - q.z.Square(q.z) - q.z.Sub(q.z, gamma) - q.z.Sub(q.z, delta) - - beta.Add(beta, beta) - beta.Add(beta, beta) - beta.Sub(beta, q.x) - q.y.Mul(alpha, beta) - - gamma.Square(gamma) - gamma.Add(gamma, gamma) - gamma.Add(gamma, gamma) - gamma.Add(gamma, gamma) - - q.y.Sub(q.y, gamma) +// Double sets q = p + p, and returns q. The points may overlap. +func (q *p521Point) Double(p *p521Point) *p521Point { + // Complete addition formula for a = -3 from "Complete addition formulas for + // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §A.2. + + t0 := new(fiat.P521Element).Square(p.x) // t0 := X ^ 2 + t1 := new(fiat.P521Element).Square(p.y) // t1 := Y ^ 2 + t2 := new(fiat.P521Element).Square(p.z) // t2 := Z ^ 2 + t3 := new(fiat.P521Element).Mul(p.x, p.y) // t3 := X * Y + t3.Add(t3, t3) // t3 := t3 + t3 + z := new(fiat.P521Element).Mul(p.x, p.z) // Z3 := X * Z + z.Add(z, z) // Z3 := Z3 + Z3 + y := new(fiat.P521Element).Mul(p521.b, t2) // Y3 := b * t2 + y.Sub(y, z) // Y3 := Y3 - Z3 + x := new(fiat.P521Element).Add(y, y) // X3 := Y3 + Y3 + y.Add(x, y) // Y3 := X3 + Y3 + x.Sub(t1, y) // X3 := t1 - Y3 + y.Add(t1, y) // Y3 := t1 + Y3 + y.Mul(x, y) // Y3 := X3 * Y3 + x.Mul(x, t3) // X3 := X3 * t3 + t3.Add(t2, t2) // t3 := t2 + t2 + t2.Add(t2, t3) // t2 := t2 + t3 + z.Mul(p521.b, z) // Z3 := b * Z3 + z.Sub(z, t2) // Z3 := Z3 - t2 + z.Sub(z, t0) // Z3 := Z3 - t0 + t3.Add(z, z) // t3 := Z3 + Z3 + z.Add(z, t3) // Z3 := Z3 + t3 + t3.Add(t0, t0) // t3 := t0 + t0 + t0.Add(t3, t0) // t0 := t3 + t0 + t0.Sub(t0, t2) // t0 := t0 - t2 + t0.Mul(t0, z) // t0 := t0 * Z3 + y.Add(y, t0) // Y3 := Y3 + t0 + t0.Mul(p.y, p.z) // t0 := Y * Z + t0.Add(t0, t0) // t0 := t0 + t0 + z.Mul(t0, z) // Z3 := t0 * Z3 + x.Sub(x, z) // X3 := X3 - Z3 + z.Mul(t0, t1) // Z3 := t0 * t1 + z.Add(z, z) // Z3 := Z3 + Z3 + z.Add(z, z) // Z3 := Z3 + Z3 + + q.x.Set(x) + q.y.Set(y) + q.z.Set(z) + return q +} +// Select sets q to p1 if cond == 1, and to p2 if cond == 0. +func (q *p521Point) Select(p1, p2 *p521Point, cond int) *p521Point { + q.x.Select(p1.x, p2.x, cond) + q.y.Select(p1.y, p2.y, cond) + q.z.Select(p1.z, p2.z, cond) return q } func (curve p521Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) { - B := curve.jacobianFromAffine(Bx, By) - p, t := &p521Point{ - x: new(fiat.P521Element), - y: new(fiat.P521Element), - z: new(fiat.P521Element), - }, &p521Point{ - x: new(fiat.P521Element), - y: new(fiat.P521Element), - z: new(fiat.P521Element), - } + B := newP521PointFromAffine(Bx, By) + p, t := newP521Point(), newP521Point() for _, byte := range scalar { for bitNum := 0; bitNum < 8; bitNum++ { - p.doubleJacobian(p) + p.Double(p) + t.Add(p, B) bit := (byte >> (7 - bitNum)) & 1 - t.addJacobian(p, B) - p.x.Select(t.x, p.x, int(bit)) - p.y.Select(t.y, p.y, int(bit)) - p.z.Select(t.z, p.z, int(bit)) + p.Select(t, p, int(bit)) } } - return curve.affineFromJacobian(p) + return p.Affine() } func (curve p521Curve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) { -- GitLab From d1dceafc290865989be713cd6e235670169b73b3 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Fri, 14 May 2021 13:03:45 -0400 Subject: [PATCH 1840/2500] crypto/elliptic: use a 4-bit sliding window for P-521 ScalarMult MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit name old time/op new time/op delta pkg:crypto/elliptic goos:darwin goarch:amd64 ScalarBaseMult/P521-16 1.63ms ± 4% 1.00ms ± 1% -38.69% (p=0.000 n=10+8) ScalarMult/P521-16 1.65ms ± 4% 0.99ms ± 2% -40.15% (p=0.000 n=10+10) pkg:crypto/ecdsa goos:darwin goarch:amd64 Sign/P521-16 1.67ms ± 1% 1.12ms ± 2% -32.82% (p=0.000 n=8+10) Verify/P521-16 3.10ms ± 2% 2.00ms ± 2% -35.54% (p=0.000 n=9+10) GenerateKey/P521-16 1.53ms ± 1% 0.98ms ± 2% -35.81% (p=0.000 n=9+10) Change-Id: I109e821399d71330a77d105496e227746cc3ea0d Reviewed-on: https://go-review.googlesource.com/c/go/+/320072 Trust: Filippo Valsorda Run-TryBot: Filippo Valsorda TryBot-Result: Go Bot Reviewed-by: Julie Qiu --- src/crypto/elliptic/p521.go | 40 ++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/src/crypto/elliptic/p521.go b/src/crypto/elliptic/p521.go index 463b9f4e39..569a58c6f3 100644 --- a/src/crypto/elliptic/p521.go +++ b/src/crypto/elliptic/p521.go @@ -6,6 +6,7 @@ package elliptic import ( "crypto/elliptic/internal/fiat" + "crypto/subtle" "math/big" ) @@ -243,13 +244,42 @@ func (curve p521Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *bi B := newP521PointFromAffine(Bx, By) p, t := newP521Point(), newP521Point() + // table holds the first 16 multiples of q. The explicit newP521Point calls + // get inlined, letting the allocations live on the stack. + var table = [16]*p521Point{ + newP521Point(), newP521Point(), newP521Point(), newP521Point(), + newP521Point(), newP521Point(), newP521Point(), newP521Point(), + newP521Point(), newP521Point(), newP521Point(), newP521Point(), + newP521Point(), newP521Point(), newP521Point(), newP521Point(), + } + for i := 1; i < 16; i++ { + table[i].Add(table[i-1], B) + } + + // Instead of doing the classic double-and-add chain, we do it with a + // four-bit window: we double four times, and then add [0-15]P. for _, byte := range scalar { - for bitNum := 0; bitNum < 8; bitNum++ { - p.Double(p) - t.Add(p, B) - bit := (byte >> (7 - bitNum)) & 1 - p.Select(t, p, int(bit)) + p.Double(p) + p.Double(p) + p.Double(p) + p.Double(p) + + for i := uint8(0); i < 16; i++ { + cond := subtle.ConstantTimeByteEq(byte>>4, i) + t.Select(table[i], t, cond) + } + p.Add(p, t) + + p.Double(p) + p.Double(p) + p.Double(p) + p.Double(p) + + for i := uint8(0); i < 16; i++ { + cond := subtle.ConstantTimeByteEq(byte&0b1111, i) + t.Select(table[i], t, cond) } + p.Add(p, t) } return p.Affine() -- GitLab From 30b5d6385e91ab557978c0024a9eb90e656623b7 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Sat, 15 May 2021 09:48:31 -0400 Subject: [PATCH 1841/2500] crypto/elliptic: move P-521 group logic to internal/nistec This abstracts the clunky and not constant time math/big elliptic.Curve compatibility layer away from the pure fiat-backed group logic. Change-Id: I3b7a7495034d0c569b21c442ae36958763b8b2d0 Reviewed-on: https://go-review.googlesource.com/c/go/+/320074 Trust: Filippo Valsorda Run-TryBot: Filippo Valsorda TryBot-Result: Go Bot Reviewed-by: Julie Qiu --- src/crypto/elliptic/elliptic.go | 9 +- src/crypto/elliptic/elliptic_test.go | 35 ++ src/crypto/elliptic/internal/fiat/p521.go | 24 +- .../elliptic/internal/fiat/p521_test.go | 2 +- src/crypto/elliptic/internal/nistec/p521.go | 306 ++++++++++++++++ .../elliptic/internal/nistec/p521_test.go | 44 +++ src/crypto/elliptic/p521.go | 346 ++++++------------ src/go/build/deps_test.go | 1 + 8 files changed, 517 insertions(+), 250 deletions(-) create mode 100644 src/crypto/elliptic/internal/nistec/p521.go create mode 100644 src/crypto/elliptic/internal/nistec/p521_test.go diff --git a/src/crypto/elliptic/elliptic.go b/src/crypto/elliptic/elliptic.go index f072960bfe..cdde0c4e60 100644 --- a/src/crypto/elliptic/elliptic.go +++ b/src/crypto/elliptic/elliptic.go @@ -21,9 +21,12 @@ import ( // A Curve represents a short-form Weierstrass curve with a=-3. // -// Note that the point at infinity (0, 0) is not considered on the curve, and -// although it can be returned by Add, Double, ScalarMult, or ScalarBaseMult, it -// can't be marshaled or unmarshaled, and IsOnCurve will return false for it. +// The output of Add, Double, and ScalarMult when the input is not a point on +// the curve is undefined. +// +// Note that the conventional point at infinity (0, 0) is not considered on the +// curve, although it can be returned by Add, Double, ScalarMult, or +// ScalarBaseMult (but not Unmarshal or UnmarshalCompressed). type Curve interface { // Params returns the parameters for the curve. Params() *CurveParams diff --git a/src/crypto/elliptic/elliptic_test.go b/src/crypto/elliptic/elliptic_test.go index 183861a54b..c9744b5a51 100644 --- a/src/crypto/elliptic/elliptic_test.go +++ b/src/crypto/elliptic/elliptic_test.go @@ -109,6 +109,15 @@ func testInfinity(t *testing.T, curve Curve) { if curve.IsOnCurve(x, y) { t.Errorf("IsOnCurve(∞) == true") } + + if xx, yy := Unmarshal(curve, Marshal(curve, x, y)); xx != nil || yy != nil { + t.Errorf("Unmarshal(Marshal(∞)) did not return an error") + } + // We don't test UnmarshalCompressed(MarshalCompressed(∞)) because there are + // two valid points with x = 0. + if xx, yy := Unmarshal(curve, []byte{0x00}); xx != nil || yy != nil { + t.Errorf("Unmarshal(∞) did not return an error") + } } func TestMarshal(t *testing.T) { @@ -274,3 +283,29 @@ func BenchmarkScalarMult(b *testing.B) { } }) } + +func BenchmarkMarshalUnmarshal(b *testing.B) { + benchmarkAllCurves(b, func(b *testing.B, curve Curve) { + _, x, y, _ := GenerateKey(curve, rand.Reader) + b.Run("Uncompressed", func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + buf := Marshal(curve, x, y) + xx, yy := Unmarshal(curve, buf) + if xx.Cmp(x) != 0 || yy.Cmp(y) != 0 { + b.Error("Unmarshal output different from Marshal input") + } + } + }) + b.Run("Compressed", func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + buf := Marshal(curve, x, y) + xx, yy := Unmarshal(curve, buf) + if xx.Cmp(x) != 0 || yy.Cmp(y) != 0 { + b.Error("Unmarshal output different from Marshal input") + } + } + }) + }) +} diff --git a/src/crypto/elliptic/internal/fiat/p521.go b/src/crypto/elliptic/internal/fiat/p521.go index dc677327e6..647c3f914f 100644 --- a/src/crypto/elliptic/internal/fiat/p521.go +++ b/src/crypto/elliptic/internal/fiat/p521.go @@ -53,28 +53,40 @@ func (e *P521Element) Set(t *P521Element) *P521Element { return e } -// Bytes returns the 66-byte little-endian encoding of e. +// Bytes returns the 66-byte big-endian encoding of e. func (e *P521Element) Bytes() []byte { - // This function must be inlined to move the allocation to the parent and - // save it from escaping to the heap. + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. var out [66]byte - p521ToBytes(&out, &e.x) + return e.bytes(&out) +} + +func (e *P521Element) bytes(out *[66]byte) []byte { + p521ToBytes(out, &e.x) + invertEndianness(out[:]) return out[:] } -// SetBytes sets e = v, where v is a little-endian 66-byte encoding, and returns +// SetBytes sets e = v, where v is a big-endian 66-byte encoding, and returns // e. If v is not 66 bytes or it encodes a value higher than 2^521 - 1, SetBytes // returns nil and an error, and e is unchanged. func (e *P521Element) SetBytes(v []byte) (*P521Element, error) { - if len(v) != 66 || v[65] > 1 { + if len(v) != 66 || v[0] > 1 { return nil, errors.New("invalid P-521 field encoding") } var in [66]byte copy(in[:], v) + invertEndianness(in[:]) p521FromBytes(&e.x, &in) return e, nil } +func invertEndianness(v []byte) { + for i := 0; i < len(v)/2; i++ { + v[i], v[len(v)-1-i] = v[len(v)-1-i], v[i] + } +} + // Add sets e = t1 + t2, and returns e. func (e *P521Element) Add(t1, t2 *P521Element) *P521Element { p521Add(&e.x, &t1.x, &t2.x) diff --git a/src/crypto/elliptic/internal/fiat/p521_test.go b/src/crypto/elliptic/internal/fiat/p521_test.go index 661bde397e..2b374faa27 100644 --- a/src/crypto/elliptic/internal/fiat/p521_test.go +++ b/src/crypto/elliptic/internal/fiat/p521_test.go @@ -15,7 +15,7 @@ func p521Random(t *testing.T) *fiat.P521Element { if _, err := rand.Read(buf); err != nil { t.Fatal(err) } - buf[65] &= 1 + buf[0] &= 1 e, err := new(fiat.P521Element).SetBytes(buf) if err != nil { t.Fatal(err) diff --git a/src/crypto/elliptic/internal/nistec/p521.go b/src/crypto/elliptic/internal/nistec/p521.go new file mode 100644 index 0000000000..e5b4e46d4b --- /dev/null +++ b/src/crypto/elliptic/internal/nistec/p521.go @@ -0,0 +1,306 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package nistec implements the NIST P elliptic curves from FIPS 186-4. +// +// This package uses fiat-crypto for its backend field arithmetic (not math/big) +// and exposes constant-time, heap allocation-free, byte slice-based safe APIs. +// Group operations use modern and safe complete addition formulas. The point at +// infinity is handled and encoded according to SEC 1, Version 2.0, and invalid +// curve points can't be represented. +package nistec + +import ( + "crypto/elliptic/internal/fiat" + "crypto/subtle" + "errors" +) + +var p521B, _ = new(fiat.P521Element).SetBytes([]byte{ + 0x00, 0x51, 0x95, 0x3e, 0xb9, 0x61, 0x8e, 0x1c, 0x9a, 0x1f, 0x92, 0x9a, + 0x21, 0xa0, 0xb6, 0x85, 0x40, 0xee, 0xa2, 0xda, 0x72, 0x5b, 0x99, 0xb3, + 0x15, 0xf3, 0xb8, 0xb4, 0x89, 0x91, 0x8e, 0xf1, 0x09, 0xe1, 0x56, 0x19, + 0x39, 0x51, 0xec, 0x7e, 0x93, 0x7b, 0x16, 0x52, 0xc0, 0xbd, 0x3b, 0xb1, + 0xbf, 0x07, 0x35, 0x73, 0xdf, 0x88, 0x3d, 0x2c, 0x34, 0xf1, 0xef, 0x45, + 0x1f, 0xd4, 0x6b, 0x50, 0x3f, 0x00}) + +var p521G, _ = NewP521Point().SetBytes([]byte{0x04, + 0x00, 0xc6, 0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, 0xe9, 0xcd, 0x9e, 0x3e, + 0xcb, 0x66, 0x23, 0x95, 0xb4, 0x42, 0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f, + 0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d, 0x3d, 0xba, 0xa1, 0x4b, + 0x5e, 0x77, 0xef, 0xe7, 0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff, + 0xa8, 0xde, 0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a, 0x42, 0x9b, 0xf9, 0x7e, + 0x7e, 0x31, 0xc2, 0xe5, 0xbd, 0x66, 0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, + 0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, + 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, + 0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, + 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, + 0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50}) + +const p521ElementLength = 66 + +// P521Point is a P-521 point. The zero value is NOT valid. +type P521Point struct { + // The point is represented in projective coordinates (X:Y:Z), + // where x = X/Z and y = Y/Z. + x, y, z *fiat.P521Element +} + +// NewP521Point returns a new P521Point representing the point at infinity point. +func NewP521Point() *P521Point { + return &P521Point{ + x: new(fiat.P521Element), + y: new(fiat.P521Element).One(), + z: new(fiat.P521Element), + } +} + +// NewP521Generator returns a new P521Point set to the canonical generator. +func NewP521Generator() *P521Point { + return NewP521Point().Set(p521G) +} + +// Set sets p = q and returns p. +func (p *P521Point) Set(q *P521Point) *P521Point { + p.x.Set(q.x) + p.y.Set(q.y) + p.z.Set(q.z) + return p +} + +// SetBytes sets p to the compressed, uncompressed, or infinity value encoded in +// b, as specified in SEC 1, Version 2.0, Section 2.3.4. If the point is not on +// the curve, it returns nil and an error, and the receiver is unchanged. +// Otherwise, it returns p. +func (p *P521Point) SetBytes(b []byte) (*P521Point, error) { + switch { + // Point at infinity. + case len(b) == 1 && b[0] == 0: + return p.Set(NewP521Point()), nil + + // Uncompressed form. + case len(b) == 1+2*p521ElementLength && b[0] == 4: + x, err := new(fiat.P521Element).SetBytes(b[1 : 1+p521ElementLength]) + if err != nil { + return nil, err + } + y, err := new(fiat.P521Element).SetBytes(b[1+p521ElementLength:]) + if err != nil { + return nil, err + } + if err := p521CheckOnCurve(x, y); err != nil { + return nil, err + } + p.x.Set(x) + p.y.Set(y) + p.z.One() + return p, nil + + // Compressed form + case len(b) == 1+p521ElementLength && b[0] == 0: + return nil, errors.New("unimplemented") // TODO(filippo) + + default: + return nil, errors.New("invalid P521 point encoding") + } +} + +func p521CheckOnCurve(x, y *fiat.P521Element) error { + // x³ - 3x + b. + x3 := new(fiat.P521Element).Square(x) + x3.Mul(x3, x) + + threeX := new(fiat.P521Element).Add(x, x) + threeX.Add(threeX, x) + + x3.Sub(x3, threeX) + x3.Add(x3, p521B) + + // y² = x³ - 3x + b + y2 := new(fiat.P521Element).Square(y) + + if x3.Equal(y2) != 1 { + return errors.New("P521 point not on curve") + } + return nil +} + +// Bytes returns the uncompressed or infinity encoding of p, as specified in +// SEC 1, Version 2.0, Section 2.3.3. Note that the encoding of the point at +// infinity is shorter than all other encodings. +func (p *P521Point) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var out [133]byte + return p.bytes(&out) +} + +func (p *P521Point) bytes(out *[133]byte) []byte { + if p.z.IsZero() == 1 { + return append(out[:0], 0) + } + + zinv := new(fiat.P521Element).Invert(p.z) + xx := new(fiat.P521Element).Mul(p.x, zinv) + yy := new(fiat.P521Element).Mul(p.y, zinv) + + buf := append(out[:0], 4) + buf = append(buf, xx.Bytes()...) + buf = append(buf, yy.Bytes()...) + return buf +} + +// Add sets q = p1 + p2, and returns q. The points may overlap. +func (q *P521Point) Add(p1, p2 *P521Point) *P521Point { + // Complete addition formula for a = -3 from "Complete addition formulas for + // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §A.2. + + t0 := new(fiat.P521Element).Mul(p1.x, p2.x) // t0 := X1 * X2 + t1 := new(fiat.P521Element).Mul(p1.y, p2.y) // t1 := Y1 * Y2 + t2 := new(fiat.P521Element).Mul(p1.z, p2.z) // t2 := Z1 * Z2 + t3 := new(fiat.P521Element).Add(p1.x, p1.y) // t3 := X1 + Y1 + t4 := new(fiat.P521Element).Add(p2.x, p2.y) // t4 := X2 + Y2 + t3.Mul(t3, t4) // t3 := t3 * t4 + t4.Add(t0, t1) // t4 := t0 + t1 + t3.Sub(t3, t4) // t3 := t3 - t4 + t4.Add(p1.y, p1.z) // t4 := Y1 + Z1 + x3 := new(fiat.P521Element).Add(p2.y, p2.z) // X3 := Y2 + Z2 + t4.Mul(t4, x3) // t4 := t4 * X3 + x3.Add(t1, t2) // X3 := t1 + t2 + t4.Sub(t4, x3) // t4 := t4 - X3 + x3.Add(p1.x, p1.z) // X3 := X1 + Z1 + y3 := new(fiat.P521Element).Add(p2.x, p2.z) // Y3 := X2 + Z2 + x3.Mul(x3, y3) // X3 := X3 * Y3 + y3.Add(t0, t2) // Y3 := t0 + t2 + y3.Sub(x3, y3) // Y3 := X3 - Y3 + z3 := new(fiat.P521Element).Mul(p521B, t2) // Z3 := b * t2 + x3.Sub(y3, z3) // X3 := Y3 - Z3 + z3.Add(x3, x3) // Z3 := X3 + X3 + x3.Add(x3, z3) // X3 := X3 + Z3 + z3.Sub(t1, x3) // Z3 := t1 - X3 + x3.Add(t1, x3) // X3 := t1 + X3 + y3.Mul(p521B, y3) // Y3 := b * Y3 + t1.Add(t2, t2) // t1 := t2 + t2 + t2.Add(t1, t2) // t2 := t1 + t2 + y3.Sub(y3, t2) // Y3 := Y3 - t2 + y3.Sub(y3, t0) // Y3 := Y3 - t0 + t1.Add(y3, y3) // t1 := Y3 + Y3 + y3.Add(t1, y3) // Y3 := t1 + Y3 + t1.Add(t0, t0) // t1 := t0 + t0 + t0.Add(t1, t0) // t0 := t1 + t0 + t0.Sub(t0, t2) // t0 := t0 - t2 + t1.Mul(t4, y3) // t1 := t4 * Y3 + t2.Mul(t0, y3) // t2 := t0 * Y3 + y3.Mul(x3, z3) // Y3 := X3 * Z3 + y3.Add(y3, t2) // Y3 := Y3 + t2 + x3.Mul(t3, x3) // X3 := t3 * X3 + x3.Sub(x3, t1) // X3 := X3 - t1 + z3.Mul(t4, z3) // Z3 := t4 * Z3 + t1.Mul(t3, t0) // t1 := t3 * t0 + z3.Add(z3, t1) // Z3 := Z3 + t1 + + q.x.Set(x3) + q.y.Set(y3) + q.z.Set(z3) + return q +} + +// Double sets q = p + p, and returns q. The points may overlap. +func (q *P521Point) Double(p *P521Point) *P521Point { + // Complete addition formula for a = -3 from "Complete addition formulas for + // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §A.2. + + t0 := new(fiat.P521Element).Square(p.x) // t0 := X ^ 2 + t1 := new(fiat.P521Element).Square(p.y) // t1 := Y ^ 2 + t2 := new(fiat.P521Element).Square(p.z) // t2 := Z ^ 2 + t3 := new(fiat.P521Element).Mul(p.x, p.y) // t3 := X * Y + t3.Add(t3, t3) // t3 := t3 + t3 + z3 := new(fiat.P521Element).Mul(p.x, p.z) // Z3 := X * Z + z3.Add(z3, z3) // Z3 := Z3 + Z3 + y3 := new(fiat.P521Element).Mul(p521B, t2) // Y3 := b * t2 + y3.Sub(y3, z3) // Y3 := Y3 - Z3 + x3 := new(fiat.P521Element).Add(y3, y3) // X3 := Y3 + Y3 + y3.Add(x3, y3) // Y3 := X3 + Y3 + x3.Sub(t1, y3) // X3 := t1 - Y3 + y3.Add(t1, y3) // Y3 := t1 + Y3 + y3.Mul(x3, y3) // Y3 := X3 * Y3 + x3.Mul(x3, t3) // X3 := X3 * t3 + t3.Add(t2, t2) // t3 := t2 + t2 + t2.Add(t2, t3) // t2 := t2 + t3 + z3.Mul(p521B, z3) // Z3 := b * Z3 + z3.Sub(z3, t2) // Z3 := Z3 - t2 + z3.Sub(z3, t0) // Z3 := Z3 - t0 + t3.Add(z3, z3) // t3 := Z3 + Z3 + z3.Add(z3, t3) // Z3 := Z3 + t3 + t3.Add(t0, t0) // t3 := t0 + t0 + t0.Add(t3, t0) // t0 := t3 + t0 + t0.Sub(t0, t2) // t0 := t0 - t2 + t0.Mul(t0, z3) // t0 := t0 * Z3 + y3.Add(y3, t0) // Y3 := Y3 + t0 + t0.Mul(p.y, p.z) // t0 := Y * Z + t0.Add(t0, t0) // t0 := t0 + t0 + z3.Mul(t0, z3) // Z3 := t0 * Z3 + x3.Sub(x3, z3) // X3 := X3 - Z3 + z3.Mul(t0, t1) // Z3 := t0 * t1 + z3.Add(z3, z3) // Z3 := Z3 + Z3 + z3.Add(z3, z3) // Z3 := Z3 + Z3 + + q.x.Set(x3) + q.y.Set(y3) + q.z.Set(z3) + return q +} + +// Select sets q to p1 if cond == 1, and to p2 if cond == 0. +func (q *P521Point) Select(p1, p2 *P521Point, cond int) *P521Point { + q.x.Select(p1.x, p2.x, cond) + q.y.Select(p1.y, p2.y, cond) + q.z.Select(p1.z, p2.z, cond) + return q +} + +// ScalarMult sets p = scalar * q, and returns p. +func (p *P521Point) ScalarMult(q *P521Point, scalar []byte) *P521Point { + // table holds the first 16 multiples of q. The explicit newP521Point calls + // get inlined, letting the allocations live on the stack. + var table = [16]*P521Point{ + NewP521Point(), NewP521Point(), NewP521Point(), NewP521Point(), + NewP521Point(), NewP521Point(), NewP521Point(), NewP521Point(), + NewP521Point(), NewP521Point(), NewP521Point(), NewP521Point(), + NewP521Point(), NewP521Point(), NewP521Point(), NewP521Point(), + } + for i := 1; i < 16; i++ { + table[i].Add(table[i-1], q) + } + + // Instead of doing the classic double-and-add chain, we do it with a + // four-bit window: we double four times, and then add [0-15]P. + t := NewP521Point() + p.Set(NewP521Point()) + for _, byte := range scalar { + p.Double(p) + p.Double(p) + p.Double(p) + p.Double(p) + + for i := uint8(0); i < 16; i++ { + cond := subtle.ConstantTimeByteEq(byte>>4, i) + t.Select(table[i], t, cond) + } + p.Add(p, t) + + p.Double(p) + p.Double(p) + p.Double(p) + p.Double(p) + + for i := uint8(0); i < 16; i++ { + cond := subtle.ConstantTimeByteEq(byte&0b1111, i) + t.Select(table[i], t, cond) + } + p.Add(p, t) + } + + return p +} diff --git a/src/crypto/elliptic/internal/nistec/p521_test.go b/src/crypto/elliptic/internal/nistec/p521_test.go new file mode 100644 index 0000000000..e62c1cbf29 --- /dev/null +++ b/src/crypto/elliptic/internal/nistec/p521_test.go @@ -0,0 +1,44 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package nistec_test + +import ( + "crypto/elliptic/internal/nistec" + "math/rand" + "os" + "strings" + "testing" +) + +func TestP521Allocations(t *testing.T) { + if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-noopt") { + t.Skip("skipping allocations test without relevant optimizations") + } + if allocs := testing.AllocsPerRun(100, func() { + p := nistec.NewP521Generator() + scalar := make([]byte, 66) + rand.Read(scalar) + p.ScalarMult(p, scalar) + out := p.Bytes() + if _, err := p.SetBytes(out); err != nil { + t.Fatal(err) + } + }); allocs > 0 { + t.Errorf("expected zero allocations, got %0.1f", allocs) + } +} + +func BenchmarkScalarMult(b *testing.B) { + b.Run("P521", func(b *testing.B) { + scalar := make([]byte, 66) + rand.Read(scalar) + p := nistec.NewP521Generator() + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + p.ScalarMult(p, scalar) + } + }) +} diff --git a/src/crypto/elliptic/p521.go b/src/crypto/elliptic/p521.go index 569a58c6f3..4cc5f86d6d 100644 --- a/src/crypto/elliptic/p521.go +++ b/src/crypto/elliptic/p521.go @@ -5,286 +5,152 @@ package elliptic import ( - "crypto/elliptic/internal/fiat" - "crypto/subtle" + "crypto/elliptic/internal/nistec" + "crypto/rand" "math/big" ) +// p521Curve is a Curve implementation based on nistec.P521Point. +// +// It's a wrapper that exposes the big.Int-based Curve interface and encodes the +// legacy idiosyncrasies it requires, such as invalid and infinity point +// handling. +// +// To interact with the nistec package, points are encoded into and decoded from +// properly formatted byte slices. All big.Int use is limited to this package. +// Encoding and decoding is 1/1000th of the runtime of a scalar multiplication, +// so the overhead is acceptable. type p521Curve struct { - *CurveParams - b *fiat.P521Element + params *CurveParams } var p521 p521Curve -var p521Params *CurveParams +var _ Curve = p521 func initP521() { - // See FIPS 186-3, section D.2.5 - p521.CurveParams = &CurveParams{Name: "P-521"} - p521.P, _ = new(big.Int).SetString("6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151", 10) - p521.N, _ = new(big.Int).SetString("6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005449", 10) - p521.B, _ = new(big.Int).SetString("051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", 16) - p521.Gx, _ = new(big.Int).SetString("c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", 16) - p521.Gy, _ = new(big.Int).SetString("11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", 16) - p521.BitSize = 521 - p521.b = bigIntToFiatP521(p521.B) + p521.params = &CurveParams{ + Name: "P-521", + BitSize: 521, + // FIPS 186-4, section D.1.2.5 + P: bigFromDecimal("68647976601306097149819007990813932172694353001433" + + "0540939446345918554318339765605212255964066145455497729631139148" + + "0858037121987999716643812574028291115057151"), + N: bigFromDecimal("68647976601306097149819007990813932172694353001433" + + "0540939446345918554318339765539424505774633321719753296399637136" + + "3321113864768612440380340372808892707005449"), + B: bigFromHex("0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8" + + "b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef" + + "451fd46b503f00"), + Gx: bigFromHex("00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f8" + + "28af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf9" + + "7e7e31c2e5bd66"), + Gy: bigFromHex("011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817" + + "afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088" + + "be94769fd16650"), + } } func (curve p521Curve) Params() *CurveParams { - return curve.CurveParams + return curve.params } func (curve p521Curve) IsOnCurve(x, y *big.Int) bool { - x1 := bigIntToFiatP521(x) - y1 := bigIntToFiatP521(y) - - // x³ - 3x + b. - x3 := new(fiat.P521Element).Square(x1) - x3.Mul(x3, x1) - - threeX := new(fiat.P521Element).Add(x1, x1) - threeX.Add(threeX, x1) - - x3.Sub(x3, threeX) - x3.Add(x3, curve.b) - - // y² = x³ - 3x + b - y2 := new(fiat.P521Element).Square(y1) - - return x3.Equal(y2) == 1 + // IsOnCurve is documented to reject (0, 0), so we don't use + // p521PointFromAffine, but let SetBytes reject the invalid Marshal output. + _, err := nistec.NewP521Point().SetBytes(Marshal(curve, x, y)) + return err == nil } -// p521Point is a P-521 point in projective coordinates, where x = X/Z, y = Y/Z. -type p521Point struct { - x, y, z *fiat.P521Element -} - -// newP521Point returns a new p521Point representing the identity point. -func newP521Point() *p521Point { - return &p521Point{ - x: new(fiat.P521Element), - y: new(fiat.P521Element).One(), - z: new(fiat.P521Element), +func p521PointFromAffine(x, y *big.Int) (p *nistec.P521Point, ok bool) { + // (0, 0) is by convention the point at infinity, which can't be represented + // in affine coordinates. Marshal incorrectly encodes it as an uncompressed + // point, which SetBytes correctly rejects. See Issue 37294. + if x.Sign() == 0 && y.Sign() == 0 { + return nistec.NewP521Point(), true } -} - -func fiatP521ToBigInt(x *fiat.P521Element) *big.Int { - xBytes := x.Bytes() - for i := range xBytes[:len(xBytes)/2] { - xBytes[i], xBytes[len(xBytes)-i-1] = xBytes[len(xBytes)-i-1], xBytes[i] + p, err := nistec.NewP521Point().SetBytes(Marshal(P521(), x, y)) + if err != nil { + return nil, false } - return new(big.Int).SetBytes(xBytes) + return p, true } -// Affine returns p in affine coordinates, with (0, 0) representing infinity by -// convention. It also goes back to big.Int values to match the exposed API. -func (p *p521Point) Affine() (x, y *big.Int) { - if p.z.IsZero() == 1 { +func p521PointToAffine(p *nistec.P521Point) (x, y *big.Int) { + out := p.Bytes() + if len(out) == 1 && out[0] == 0 { + // This is the correct encoding of the point at infinity, which + // Unmarshal does not support. See Issue 37294. return new(big.Int), new(big.Int) } - - zinv := new(fiat.P521Element).Invert(p.z) - xx := new(fiat.P521Element).Mul(p.x, zinv) - yy := new(fiat.P521Element).Mul(p.y, zinv) - - return fiatP521ToBigInt(xx), fiatP521ToBigInt(yy) -} - -func bigIntToFiatP521(x *big.Int) *fiat.P521Element { - xBytes := new(big.Int).Mod(x, p521.P).FillBytes(make([]byte, 66)) - for i := range xBytes[:len(xBytes)/2] { - xBytes[i], xBytes[len(xBytes)-i-1] = xBytes[len(xBytes)-i-1], xBytes[i] + x, y = Unmarshal(P521(), out) + if x == nil { + panic("crypto/elliptic: internal error: Unmarshal rejected a valid point encoding") } - x1, err := new(fiat.P521Element).SetBytes(xBytes) + return x, y +} + +// p521RandomPoint returns a random point on the curve. It's used when Add, +// Double, or ScalarMult are fed a point not on the curve, which is undefined +// behavior. Originally, we used to do the math on it anyway (which allows +// invalid curve attacks) and relied on the caller and Unmarshal to avoid this +// happening in the first place. Now, we just can't construct a nistec.P521Point +// for an invalid pair of coordinates, because that API is safer. If we panic, +// we risk introducing a DoS. If we return nil, we risk a panic. If we return +// the input, ecdsa.Verify might fail open. The safest course seems to be to +// return a valid, random point, which hopefully won't help the attacker. +func p521RandomPoint() (x, y *big.Int) { + _, x, y, err := GenerateKey(P521(), rand.Reader) if err != nil { - // The input is reduced modulo P and encoded in a fixed size bytes - // slice, this should be impossible. - panic("internal error: bigIntToFiatP521") + panic("crypto/elliptic: failed to generate random point") } - return x1 + return x, y } -// newP521PointFromAffine converts (x, y) affine coordinates into (X, Y, Z) projective -// coordinates. It also converts from big.Int to fiat, which is necessarily a -// messy and variable-time operation, which we can't avoid due to the exposed API. -func newP521PointFromAffine(x, y *big.Int) *p521Point { - // (0, 0) is by convention the point at infinity, which can't be represented - // in affine coordinates, but is (0, 0, 0) in projective coordinates. - if x.Sign() == 0 && y.Sign() == 0 { - return newP521Point() +func (curve p521Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { + p1, ok := p521PointFromAffine(x1, y1) + if !ok { + return p521RandomPoint() } - return &p521Point{ - x: bigIntToFiatP521(x), - y: bigIntToFiatP521(y), - z: new(fiat.P521Element).One(), + p2, ok := p521PointFromAffine(x2, y2) + if !ok { + return p521RandomPoint() } -} - -func (curve p521Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { - p1 := newP521PointFromAffine(x1, y1) - p2 := newP521PointFromAffine(x2, y2) - return p1.Add(p1, p2).Affine() -} - -// Add sets q = p1 + p2, and returns q. The points may overlap. -func (q *p521Point) Add(p1, p2 *p521Point) *p521Point { - // Complete addition formula for a = -3 from "Complete addition formulas for - // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §A.2. - - t0 := new(fiat.P521Element).Mul(p1.x, p2.x) // t0 := X1 * X2 - t1 := new(fiat.P521Element).Mul(p1.y, p2.y) // t1 := Y1 * Y2 - t2 := new(fiat.P521Element).Mul(p1.z, p2.z) // t2 := Z1 * Z2 - t3 := new(fiat.P521Element).Add(p1.x, p1.y) // t3 := X1 + Y1 - t4 := new(fiat.P521Element).Add(p2.x, p2.y) // t4 := X2 + Y2 - t3.Mul(t3, t4) // t3 := t3 * t4 - t4.Add(t0, t1) // t4 := t0 + t1 - t3.Sub(t3, t4) // t3 := t3 - t4 - t4.Add(p1.y, p1.z) // t4 := Y1 + Z1 - x := new(fiat.P521Element).Add(p2.y, p2.z) // X3 := Y2 + Z2 - t4.Mul(t4, x) // t4 := t4 * X3 - x.Add(t1, t2) // X3 := t1 + t2 - t4.Sub(t4, x) // t4 := t4 - X3 - x.Add(p1.x, p1.z) // X3 := X1 + Z1 - y := new(fiat.P521Element).Add(p2.x, p2.z) // Y3 := X2 + Z2 - x.Mul(x, y) // X3 := X3 * Y3 - y.Add(t0, t2) // Y3 := t0 + t2 - y.Sub(x, y) // Y3 := X3 - Y3 - z := new(fiat.P521Element).Mul(p521.b, t2) // Z3 := b * t2 - x.Sub(y, z) // X3 := Y3 - Z3 - z.Add(x, x) // Z3 := X3 + X3 - x.Add(x, z) // X3 := X3 + Z3 - z.Sub(t1, x) // Z3 := t1 - X3 - x.Add(t1, x) // X3 := t1 + X3 - y.Mul(p521.b, y) // Y3 := b * Y3 - t1.Add(t2, t2) // t1 := t2 + t2 - t2.Add(t1, t2) // t2 := t1 + t2 - y.Sub(y, t2) // Y3 := Y3 - t2 - y.Sub(y, t0) // Y3 := Y3 - t0 - t1.Add(y, y) // t1 := Y3 + Y3 - y.Add(t1, y) // Y3 := t1 + Y3 - t1.Add(t0, t0) // t1 := t0 + t0 - t0.Add(t1, t0) // t0 := t1 + t0 - t0.Sub(t0, t2) // t0 := t0 - t2 - t1.Mul(t4, y) // t1 := t4 * Y3 - t2.Mul(t0, y) // t2 := t0 * Y3 - y.Mul(x, z) // Y3 := X3 * Z3 - y.Add(y, t2) // Y3 := Y3 + t2 - x.Mul(t3, x) // X3 := t3 * X3 - x.Sub(x, t1) // X3 := X3 - t1 - z.Mul(t4, z) // Z3 := t4 * Z3 - t1.Mul(t3, t0) // t1 := t3 * t0 - z.Add(z, t1) // Z3 := Z3 + t1 - - q.x.Set(x) - q.y.Set(y) - q.z.Set(z) - return q + return p521PointToAffine(p1.Add(p1, p2)) } func (curve p521Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { - p := newP521PointFromAffine(x1, y1) - return p.Double(p).Affine() -} - -// Double sets q = p + p, and returns q. The points may overlap. -func (q *p521Point) Double(p *p521Point) *p521Point { - // Complete addition formula for a = -3 from "Complete addition formulas for - // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §A.2. - - t0 := new(fiat.P521Element).Square(p.x) // t0 := X ^ 2 - t1 := new(fiat.P521Element).Square(p.y) // t1 := Y ^ 2 - t2 := new(fiat.P521Element).Square(p.z) // t2 := Z ^ 2 - t3 := new(fiat.P521Element).Mul(p.x, p.y) // t3 := X * Y - t3.Add(t3, t3) // t3 := t3 + t3 - z := new(fiat.P521Element).Mul(p.x, p.z) // Z3 := X * Z - z.Add(z, z) // Z3 := Z3 + Z3 - y := new(fiat.P521Element).Mul(p521.b, t2) // Y3 := b * t2 - y.Sub(y, z) // Y3 := Y3 - Z3 - x := new(fiat.P521Element).Add(y, y) // X3 := Y3 + Y3 - y.Add(x, y) // Y3 := X3 + Y3 - x.Sub(t1, y) // X3 := t1 - Y3 - y.Add(t1, y) // Y3 := t1 + Y3 - y.Mul(x, y) // Y3 := X3 * Y3 - x.Mul(x, t3) // X3 := X3 * t3 - t3.Add(t2, t2) // t3 := t2 + t2 - t2.Add(t2, t3) // t2 := t2 + t3 - z.Mul(p521.b, z) // Z3 := b * Z3 - z.Sub(z, t2) // Z3 := Z3 - t2 - z.Sub(z, t0) // Z3 := Z3 - t0 - t3.Add(z, z) // t3 := Z3 + Z3 - z.Add(z, t3) // Z3 := Z3 + t3 - t3.Add(t0, t0) // t3 := t0 + t0 - t0.Add(t3, t0) // t0 := t3 + t0 - t0.Sub(t0, t2) // t0 := t0 - t2 - t0.Mul(t0, z) // t0 := t0 * Z3 - y.Add(y, t0) // Y3 := Y3 + t0 - t0.Mul(p.y, p.z) // t0 := Y * Z - t0.Add(t0, t0) // t0 := t0 + t0 - z.Mul(t0, z) // Z3 := t0 * Z3 - x.Sub(x, z) // X3 := X3 - Z3 - z.Mul(t0, t1) // Z3 := t0 * t1 - z.Add(z, z) // Z3 := Z3 + Z3 - z.Add(z, z) // Z3 := Z3 + Z3 - - q.x.Set(x) - q.y.Set(y) - q.z.Set(z) - return q -} - -// Select sets q to p1 if cond == 1, and to p2 if cond == 0. -func (q *p521Point) Select(p1, p2 *p521Point, cond int) *p521Point { - q.x.Select(p1.x, p2.x, cond) - q.y.Select(p1.y, p2.y, cond) - q.z.Select(p1.z, p2.z, cond) - return q + p, ok := p521PointFromAffine(x1, y1) + if !ok { + return p521RandomPoint() + } + return p521PointToAffine(p.Double(p)) } func (curve p521Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) { - B := newP521PointFromAffine(Bx, By) - p, t := newP521Point(), newP521Point() - - // table holds the first 16 multiples of q. The explicit newP521Point calls - // get inlined, letting the allocations live on the stack. - var table = [16]*p521Point{ - newP521Point(), newP521Point(), newP521Point(), newP521Point(), - newP521Point(), newP521Point(), newP521Point(), newP521Point(), - newP521Point(), newP521Point(), newP521Point(), newP521Point(), - newP521Point(), newP521Point(), newP521Point(), newP521Point(), + p, ok := p521PointFromAffine(Bx, By) + if !ok { + return p521RandomPoint() } - for i := 1; i < 16; i++ { - table[i].Add(table[i-1], B) - } - - // Instead of doing the classic double-and-add chain, we do it with a - // four-bit window: we double four times, and then add [0-15]P. - for _, byte := range scalar { - p.Double(p) - p.Double(p) - p.Double(p) - p.Double(p) - - for i := uint8(0); i < 16; i++ { - cond := subtle.ConstantTimeByteEq(byte>>4, i) - t.Select(table[i], t, cond) - } - p.Add(p, t) + return p521PointToAffine(p.ScalarMult(p, scalar)) +} - p.Double(p) - p.Double(p) - p.Double(p) - p.Double(p) +func (curve p521Curve) ScalarBaseMult(scalar []byte) (*big.Int, *big.Int) { + p := nistec.NewP521Generator() + return p521PointToAffine(p.ScalarMult(p, scalar)) +} - for i := uint8(0); i < 16; i++ { - cond := subtle.ConstantTimeByteEq(byte&0b1111, i) - t.Select(table[i], t, cond) - } - p.Add(p, t) +func bigFromDecimal(s string) *big.Int { + b, ok := new(big.Int).SetString(s, 10) + if !ok { + panic("invalid encoding") } - - return p.Affine() + return b } -func (curve p521Curve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) { - return curve.ScalarMult(curve.Gx, curve.Gy, k) +func bigFromHex(s string) *big.Int { + b, ok := new(big.Int).SetString(s, 16) + if !ok { + panic("invalid encoding") + } + return b } diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index ab85c99602..f4a92f8be4 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -396,6 +396,7 @@ var depsRules = ` < crypto/subtle < crypto/internal/subtle < crypto/elliptic/internal/fiat + < crypto/elliptic/internal/nistec < crypto/ed25519/internal/edwards25519/field, golang.org/x/crypto/curve25519/internal/field < crypto/ed25519/internal/edwards25519 < crypto/cipher -- GitLab From f582778ee991e8a443e691f9a45c8f0600a748a0 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 6 Aug 2021 17:01:25 -0400 Subject: [PATCH 1842/2500] cmd/compile: emit sensible go_asm.h consts for big ints Currently, the compiler will emit any const that doesn't fit in an int64 to go_asm.h like #define const_stackPreempt constant.intVal{val:(*big.Int)(0xc000c06c40)} This happens because dumpasmhdr formats the constant.Value using the verb "%#v". Since constant.Value doesn't implement the GoString() method, this just prints the Go-syntax representation of the value. This happens to work for small integer constants, which go/constant represents directly as an int64, but not for integer constants that don't fit in an int64, which go/constant represents as a big.Int. Make these constants usable by changing the formatting verb to "%v", which will call the String() method, giving a reasonable result in all cases. Change-Id: I365eeb88c8acfc43ff377cc873432269bde3f541 Reviewed-on: https://go-review.googlesource.com/c/go/+/359954 Trust: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot Reviewed-by: David Chase --- src/cmd/compile/internal/gc/export.go | 2 +- test/asmhdr.dir/main.go | 66 +++++++++++++++++++++++++++ test/asmhdr.dir/main.s | 27 +++++++++++ test/asmhdr.go | 9 ++++ 4 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 test/asmhdr.dir/main.go create mode 100644 test/asmhdr.dir/main.s create mode 100644 test/asmhdr.go diff --git a/src/cmd/compile/internal/gc/export.go b/src/cmd/compile/internal/gc/export.go index 2eac7d03c2..eed438705a 100644 --- a/src/cmd/compile/internal/gc/export.go +++ b/src/cmd/compile/internal/gc/export.go @@ -31,7 +31,7 @@ func dumpasmhdr() { if t == constant.Float || t == constant.Complex { break } - fmt.Fprintf(b, "#define const_%s %#v\n", n.Sym().Name, n.Val()) + fmt.Fprintf(b, "#define const_%s %v\n", n.Sym().Name, n.Val()) case ir.OTYPE: t := n.Type() diff --git a/test/asmhdr.dir/main.go b/test/asmhdr.dir/main.go new file mode 100644 index 0000000000..808b5de7bb --- /dev/null +++ b/test/asmhdr.dir/main.go @@ -0,0 +1,66 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "unsafe" + +const ( + smallInt = 42 + + // For bigInt, we use a value that's too big for an int64, but still + // fits in uint64. go/constant uses a different representation for + // values larger than int64, but the cmd/asm parser can't parse + // anything bigger than a uint64. + bigInt = 0xffffffffffffffff + + stringVal = "test" +) + +var ( + smallIntAsm int64 + bigIntAsm uint64 + stringAsm [len(stringVal)]byte +) + +type typ struct { + a uint64 + b [100]uint8 + c uint8 +} + +var ( + typSize uint64 + + typA, typB, typC uint64 +) + +func main() { + if smallInt != smallIntAsm { + println("smallInt", smallInt, "!=", smallIntAsm) + } + if bigInt != bigIntAsm { + println("bigInt", uint64(bigInt), "!=", bigIntAsm) + } + if stringVal != string(stringAsm[:]) { + println("stringVal", stringVal, "!=", string(stringAsm[:])) + } + + // We also include boolean consts in go_asm.h, but they're + // defined to be "true" or "false", and it's not clear how to + // use that in assembly. + + if want := unsafe.Sizeof(typ{}); want != uintptr(typSize) { + println("typSize", want, "!=", typSize) + } + if want := unsafe.Offsetof(typ{}.a); want != uintptr(typA) { + println("typA", want, "!=", typA) + } + if want := unsafe.Offsetof(typ{}.b); want != uintptr(typB) { + println("typB", want, "!=", typB) + } + if want := unsafe.Offsetof(typ{}.c); want != uintptr(typC) { + println("typC", want, "!=", typC) + } +} diff --git a/test/asmhdr.dir/main.s b/test/asmhdr.dir/main.s new file mode 100644 index 0000000000..7e2d8e7abd --- /dev/null +++ b/test/asmhdr.dir/main.s @@ -0,0 +1,27 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "go_asm.h" +#define RODATA 8 + +DATA ·smallIntAsm(SB)/8, $const_smallInt +GLOBL ·smallIntAsm(SB),RODATA,$8 + +DATA ·bigIntAsm(SB)/8, $const_bigInt +GLOBL ·bigIntAsm(SB),RODATA,$8 + +DATA ·stringAsm(SB)/4, $const_stringVal +GLOBL ·stringAsm(SB),RODATA,$4 + +DATA ·typSize(SB)/8, $typ__size +GLOBL ·typSize(SB),RODATA,$8 + +DATA ·typA(SB)/8, $typ_a +GLOBL ·typA(SB),RODATA,$8 + +DATA ·typB(SB)/8, $typ_b +GLOBL ·typB(SB),RODATA,$8 + +DATA ·typC(SB)/8, $typ_c +GLOBL ·typC(SB),RODATA,$8 diff --git a/test/asmhdr.go b/test/asmhdr.go new file mode 100644 index 0000000000..772f98e2cc --- /dev/null +++ b/test/asmhdr.go @@ -0,0 +1,9 @@ +// buildrundir + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test the -asmhdr output of the compiler. + +package ignored -- GitLab From 6113dacf32db7a996bc53fa7ca0db314cd3e7378 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 17 Sep 2021 09:56:21 -0400 Subject: [PATCH 1843/2500] cmd/compile: make -memprofilerate work There are multiple things preventing the -memprofilerate flag from working right now: - CmdFlags.MemProfileRate has type int64, which is currently not supported by the compiler's reflection-based registerFlags. Unfortunately, rather than letting you know this, registerFlags simply ignores this field. - Nothing consumes CmdFlags.MemProfileRate anyway. startProfile instead uses a package-local memprofilerate variable that is never set to anything. Fix this by making CmdFlags.MemProfileRate an int (that's what runtime.MemProfileRate is anyway) and using it in startProfile. While we're here, prevent similar flag parsing bugs in the future by making registerFlags panic if it encounters a flag field of unsupported type. Change-Id: Ib9a1fcd8f4c5e9d7175a4fabc375f31e79774f9a Reviewed-on: https://go-review.googlesource.com/c/go/+/359955 Trust: Austin Clements Trust: Josh Bleecher Snyder Run-TryBot: Austin Clements TryBot-Result: Go Bot Reviewed-by: Josh Bleecher Snyder Reviewed-by: David Chase --- src/cmd/compile/internal/base/flag.go | 4 +++- src/cmd/compile/internal/gc/util.go | 9 +++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/cmd/compile/internal/base/flag.go b/src/cmd/compile/internal/base/flag.go index 51938e8fd5..9d630ce97a 100644 --- a/src/cmd/compile/internal/base/flag.go +++ b/src/cmd/compile/internal/base/flag.go @@ -109,7 +109,7 @@ type CmdFlags struct { Live CountFlag "help:\"debug liveness analysis\"" MSan bool "help:\"build code compatible with C/C++ memory sanitizer\"" MemProfile string "help:\"write memory profile to `file`\"" - MemProfileRate int64 "help:\"set runtime.MemProfileRate to `rate`\"" + MemProfileRate int "help:\"set runtime.MemProfileRate to `rate`\"" MutexProfile string "help:\"write mutex profile to `file`\"" NoLocalImports bool "help:\"reject local (relative) imports\"" Pack bool "help:\"write to file.a instead of file.o\"" @@ -330,6 +330,8 @@ func registerFlags() { case funcType: f := v.Field(i).Interface().(func(string)) objabi.Flagfn1(name, help, f) + default: + panic(fmt.Sprintf("base.Flag.%s has unexpected type %s", f.Name, f.Type)) } } } diff --git a/src/cmd/compile/internal/gc/util.go b/src/cmd/compile/internal/gc/util.go index 4baddbc029..56fd137de2 100644 --- a/src/cmd/compile/internal/gc/util.go +++ b/src/cmd/compile/internal/gc/util.go @@ -12,10 +12,7 @@ import ( "cmd/compile/internal/base" ) -var ( - memprofilerate int64 - traceHandler func(string) -) +var traceHandler func(string) func startProfile() { if base.Flag.CPUProfile != "" { @@ -29,8 +26,8 @@ func startProfile() { base.AtExit(pprof.StopCPUProfile) } if base.Flag.MemProfile != "" { - if memprofilerate != 0 { - runtime.MemProfileRate = int(memprofilerate) + if base.Flag.MemProfileRate != 0 { + runtime.MemProfileRate = base.Flag.MemProfileRate } f, err := os.Create(base.Flag.MemProfile) if err != nil { -- GitLab From 0bef30d28ac0b9654e5daef0fef731d7a9495214 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sat, 30 Oct 2021 10:50:59 -0700 Subject: [PATCH 1844/2500] cmd/compile/internal/syntax: fix parsing of array or slice constraint types This is a port of the idea used in CL 359134 from go/parser to syntax, with adjustments due to the slightly different structure of the two parsers, and some refactoring to simplify the logic. Fixes #49175. Change-Id: Ib4955bde708f2b08345f35523e6094c03ab3076c Reviewed-on: https://go-review.googlesource.com/c/go/+/360135 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/syntax/parser.go | 82 +++++++++++-------- .../internal/syntax/testdata/typeset.go2 | 10 ++- 2 files changed, 57 insertions(+), 35 deletions(-) diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index af5a505cdb..9f02cb6c2c 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -586,42 +586,54 @@ func (p *parser) typeDecl(group *Group) Decl { d.Pragma = p.takePragma() d.Name = p.name() - if p.tok == _Lbrack { - // array/slice or generic type - // name "[" ... + if p.allowGenerics() && p.tok == _Lbrack { + // d.Name "[" ... + // array/slice or type parameter list pos := p.pos() p.next() switch p.tok { - case _Rbrack: - // name "[" "]" ... - p.next() - d.Type = p.sliceType(pos) case _Name: - // array or generic type - // name "[" name ... - p.xnest++ - // TODO(gri) p.expr may consume an opening "[" when it shouldn't (issue #49175) - x := p.expr() - p.xnest-- - if name0, ok := x.(*Name); p.allowGenerics() && ok && p.tok != _Rbrack { - // generic type - // name "[" name ... - d.TParamList = p.paramList(name0, _Rbrack, true) - pos := p.pos() - if p.gotAssign() { - p.syntaxErrorAt(pos, "generic type cannot be alias") + // d.Name "[" name ... + // array or type parameter list + name := p.name() + // Index or slice expressions are never constant and thus invalid + // array length expressions. Thus, if we see a "[" following name + // we can safely assume that "[" name starts a type parameter list. + var x Expr // x != nil means x is the array length expression + if p.tok != _Lbrack { + // d.Name "[" name ... + // If we reach here, the next token is not a "[", and we need to + // parse the expression starting with name. If that expression is + // just that name, not followed by a "]" (in which case we might + // have the array length "[" name "]"), we can also safely assume + // a type parameter list. + p.xnest++ + // To parse the expression starting with name, expand the call + // sequence we would get by passing in name to parser.expr, and + // pass in name to parser.pexpr. + x = p.binaryExpr(p.pexpr(name, false), 0) + p.xnest-- + if x == name && p.tok != _Rbrack { + x = nil } + } + if x == nil { + // d.Name "[" name ... + // type parameter list + d.TParamList = p.paramList(name, _Rbrack, true) + d.Alias = p.gotAssign() d.Type = p.typeOrNil() } else { + // d.Name "[" x "]" ... // x is the array length expression - // name "[" x ... - if debug && x == nil { - panic("length expression is nil") - } d.Type = p.arrayType(pos, x) } + case _Rbrack: + // d.Name "[" "]" ... + p.next() + d.Type = p.sliceType(pos) default: - // name "[" ... + // d.Name "[" ... d.Type = p.arrayType(pos, nil) } } else { @@ -736,14 +748,16 @@ func (p *parser) expr() Expr { defer p.trace("expr")() } - return p.binaryExpr(0) + return p.binaryExpr(nil, 0) } // Expression = UnaryExpr | Expression binary_op Expression . -func (p *parser) binaryExpr(prec int) Expr { +func (p *parser) binaryExpr(x Expr, prec int) Expr { // don't trace binaryExpr - only leads to overly nested trace output - x := p.unaryExpr() + if x == nil { + x = p.unaryExpr() + } for (p.tok == _Operator || p.tok == _Star) && p.prec > prec { t := new(Operation) t.pos = p.pos() @@ -751,7 +765,7 @@ func (p *parser) binaryExpr(prec int) Expr { tprec := p.prec p.next() t.X = x - t.Y = p.binaryExpr(tprec) + t.Y = p.binaryExpr(nil, tprec) x = t } return x @@ -846,7 +860,7 @@ func (p *parser) unaryExpr() Expr { // TODO(mdempsky): We need parens here so we can report an // error for "(x) := true". It should be possible to detect // and reject that more efficiently though. - return p.pexpr(true) + return p.pexpr(nil, true) } // callStmt parses call-like statements that can be preceded by 'defer' and 'go'. @@ -860,7 +874,7 @@ func (p *parser) callStmt() *CallStmt { s.Tok = p.tok // _Defer or _Go p.next() - x := p.pexpr(p.tok == _Lparen) // keep_parens so we can report error below + x := p.pexpr(nil, p.tok == _Lparen) // keep_parens so we can report error below if t := unparen(x); t != x { p.errorAt(x.Pos(), fmt.Sprintf("expression in %s must not be parenthesized", s.Tok)) // already progressed, no need to advance @@ -976,12 +990,14 @@ func (p *parser) operand(keep_parens bool) Expr { // "]" . // TypeAssertion = "." "(" Type ")" . // Arguments = "(" [ ( ExpressionList | Type [ "," ExpressionList ] ) [ "..." ] [ "," ] ] ")" . -func (p *parser) pexpr(keep_parens bool) Expr { +func (p *parser) pexpr(x Expr, keep_parens bool) Expr { if trace { defer p.trace("pexpr")() } - x := p.operand(keep_parens) + if x == nil { + x = p.operand(keep_parens) + } loop: for { diff --git a/src/cmd/compile/internal/syntax/testdata/typeset.go2 b/src/cmd/compile/internal/syntax/testdata/typeset.go2 index 78d3fe1ae5..19b74f28ea 100644 --- a/src/cmd/compile/internal/syntax/testdata/typeset.go2 +++ b/src/cmd/compile/internal/syntax/testdata/typeset.go2 @@ -44,17 +44,23 @@ type ( _[_ t|~struct{}] t _[_ ~t|~struct{}] t - // TODO(gri) fix this (issue #49175) - // _[_ []t]t + // test cases for issue #49175 + _[_ []t]t + _[_ [1]t]t _[_ ~[]t]t + _[_ ~[1]t]t + t [ /* ERROR type parameters must be named */ t[0]]t ) // test cases for issue #49174 func _[_ t]() {} func _[_ []t]() {} +func _[_ [1]t]() {} func _[_ []t | t]() {} +func _[_ [1]t | t]() {} func _[_ t | []t]() {} func _[_ []t | []t]() {} +func _[_ [1]t | [1]t]() {} func _[_ t[t] | t[t]]() {} // Single-expression type parameter lists and those that don't start -- GitLab From 8e3d5f0bb324eebb92cc93264a63afa7ded9ab9a Mon Sep 17 00:00:00 2001 From: Nigel Tao Date: Wed, 27 Oct 2021 14:24:37 +1100 Subject: [PATCH 1845/2500] image/draw: rename and reorder some benchmarks The intention is for BenchmarkFooBar functions to map 1:1 to drawFooBar functions. Recent draw.go changes have added more drawFooBar functions and have further modified the mapping, as fallback drawFooBar functions aren't invoked as often as they used to. This commit restores the 1:1 mapping and reorganizes the BenchmarkFooBar functions in the same order as the matching drawFooBar functions appear. Also modify a TestDraw test case from vgradGreen(255) = {0, 136, 0, 255} to vgradGreen(90) = {0, 48, 0, 90}. Doing so matches the existing "The source pixel is {0, 48, 0, 90}" comment but also makes for a more interesting test case, as the source pixel is no longer fully opaque. Fully opaque is already covered by the vgradGray() test case on the next line. Also fix a "variable source" comment copy-pasto when the source image is actually uniform, not variable. Also add a func DrawMask type switch comment about interface types. Change-Id: I828e71f2ee8ec617f523c8aafb118fb7ba166876 Reviewed-on: https://go-review.googlesource.com/c/go/+/358974 Trust: Nigel Tao Trust: Brad Fitzpatrick Run-TryBot: Nigel Tao TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/image/draw/bench_test.go | 27 +++++++++++++-------------- src/image/draw/draw.go | 2 ++ src/image/draw/draw_test.go | 13 +++++++++---- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/image/draw/bench_test.go b/src/image/draw/bench_test.go index 2b7c6d6ac4..55d25b8596 100644 --- a/src/image/draw/bench_test.go +++ b/src/image/draw/bench_test.go @@ -190,8 +190,7 @@ func bench(b *testing.B, dcm, scm, mcm color.Model, op Op) { } } -// The BenchmarkFoo and BenchmarkFooN functions exercise a drawFoo fast-path -// function in draw.go. +// The BenchmarkFoo functions exercise a drawFoo fast-path function in draw.go. func BenchmarkFillOver(b *testing.B) { bench(b, color.RGBAModel, nil, nil, Over) @@ -233,12 +232,20 @@ func BenchmarkGlyphOver(b *testing.B) { bench(b, color.RGBAModel, nil, color.AlphaModel, Over) } -func BenchmarkRGBA1(b *testing.B) { - bench(b, color.RGBAModel, color.RGBA64Model, nil, Src) +func BenchmarkRGBAMaskOver(b *testing.B) { + bench(b, color.RGBAModel, color.RGBAModel, color.AlphaModel, Over) } -func BenchmarkRGBA2(b *testing.B) { - bench(b, color.RGBAModel, color.RGBAModel, color.AlphaModel, Over) +func BenchmarkGrayMaskOver(b *testing.B) { + bench(b, color.RGBAModel, color.GrayModel, color.AlphaModel, Over) +} + +func BenchmarkRGBA64ImageMaskOver(b *testing.B) { + bench(b, color.RGBAModel, color.RGBA64Model, color.AlphaModel, Over) +} + +func BenchmarkRGBA(b *testing.B) { + bench(b, color.RGBAModel, color.RGBA64Model, nil, Src) } func BenchmarkPalettedFill(b *testing.B) { @@ -266,11 +273,3 @@ func BenchmarkGenericSrc(b *testing.B) { func BenchmarkGenericMaskSrc(b *testing.B) { bench(b, color.RGBA64Model, color.RGBA64Model, color.AlphaModel, Src) } - -func BenchmarkRGBA64Over(b *testing.B) { - bench(b, color.RGBAModel, color.RGBA64Model, color.AlphaModel, Over) -} - -func BenchmarkGrayOver(b *testing.B) { - bench(b, color.RGBAModel, color.GrayModel, color.AlphaModel, Over) -} diff --git a/src/image/draw/draw.go b/src/image/draw/draw.go index d3c5b29097..7dd18dfdb5 100644 --- a/src/image/draw/draw.go +++ b/src/image/draw/draw.go @@ -166,6 +166,8 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas case *image.Gray: drawGrayMaskOver(dst0, r, src0, sp, mask0, mp) return + // Case order matters. The next case (image.RGBA64Image) is an + // interface type that the concrete types above also implement. case image.RGBA64Image: drawRGBA64ImageMaskOver(dst0, r, src0, sp, mask0, mp) return diff --git a/src/image/draw/draw_test.go b/src/image/draw/draw_test.go index 75a2896631..77f1c5c2c2 100644 --- a/src/image/draw/draw_test.go +++ b/src/image/draw/draw_test.go @@ -380,7 +380,7 @@ var drawTests = []drawTest{ {"cmykAlphaSrc", vgradMagenta(), fillAlpha(192), Src, color.RGBA{145, 67, 145, 192}}, {"cmykNil", vgradMagenta(), nil, Over, color.RGBA{192, 89, 192, 255}}, {"cmykNilSrc", vgradMagenta(), nil, Src, color.RGBA{192, 89, 192, 255}}, - // Variable mask and variable source. + // Variable mask and uniform source. // At (x, y) == (8, 8): // The destination pixel is {136, 0, 0, 255}. // The source pixel is {0, 0, 255, 255}. @@ -397,9 +397,14 @@ var drawTests = []drawTest{ Over, color.RGBA{81, 0, 102, 255}}, {"genericSrcSlowest", fillBlue(255), convertToSlowestRGBA(vgradAlpha(192)), Src, color.RGBA{0, 0, 102, 102}}, - // The source pixel is {0, 48, 0, 90}. - {"rgbaVariableMaskOver", vgradGreen(255), vgradAlpha(192), Over, color.RGBA{81, 54, 0, 255}}, - // The source pixel is {136} in Gray-space, which is {136, 136, 136, 255} in RGBA-space. + // Variable mask and variable source. + // At (x, y) == (8, 8): + // The destination pixel is {136, 0, 0, 255}. + // The source pixel is: + // - {0, 48, 0, 90}. + // - {136} in Gray-space, which is {136, 136, 136, 255} in RGBA-space. + // The mask pixel's alpha is 102, or 40%. + {"rgbaVariableMaskOver", vgradGreen(90), vgradAlpha(192), Over, color.RGBA{117, 19, 0, 255}}, {"grayVariableMaskOver", vgradGray(), vgradAlpha(192), Over, color.RGBA{136, 54, 54, 255}}, } -- GitLab From 243c5ae019bab96caf55dd443a0ecd128f079d9c Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sat, 30 Oct 2021 20:54:39 -0400 Subject: [PATCH 1846/2500] go/parser: simplify parsing of array or slice constraint types Simplify the parsing of array or slice constraint types added in CL 359134, following the port in CL 360135. Change-Id: Ia86d4b0149a222423d3b19623dd39d4aeb23857d Reviewed-on: https://go-review.googlesource.com/c/go/+/360115 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/parser/parser.go | 98 +++++++++++++++++++---------------------- 1 file changed, 46 insertions(+), 52 deletions(-) diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go index 792fe4141c..8952a2bc29 100644 --- a/src/go/parser/parser.go +++ b/src/go/parser/parser.go @@ -455,10 +455,10 @@ func (p *parser) parseExprList() (list []ast.Expr) { defer un(trace(p, "ExpressionList")) } - list = append(list, p.checkExpr(p.parseExpr(nil))) + list = append(list, p.checkExpr(p.parseExpr())) for p.tok == token.COMMA { p.next() - list = append(list, p.checkExpr(p.parseExpr(nil))) + list = append(list, p.checkExpr(p.parseExpr())) } return @@ -525,23 +525,27 @@ func (p *parser) parseTypeName(ident *ast.Ident) ast.Expr { return ident } -func (p *parser) parseArrayLen() ast.Expr { +// "[" has already been consumed, and lbrack is its position. +// If len != nil it is the already consumed array length. +func (p *parser) parseArrayType(lbrack token.Pos, len ast.Expr) *ast.ArrayType { if p.trace { - defer un(trace(p, "ArrayLen")) + defer un(trace(p, "ArrayType")) } - p.exprLev++ - var len ast.Expr - // always permit ellipsis for more fault-tolerant parsing - if p.tok == token.ELLIPSIS { - len = &ast.Ellipsis{Ellipsis: p.pos} - p.next() - } else if p.tok != token.RBRACK { - len = p.parseRhs() + if len == nil { + p.exprLev++ + // always permit ellipsis for more fault-tolerant parsing + if p.tok == token.ELLIPSIS { + len = &ast.Ellipsis{Ellipsis: p.pos} + p.next() + } else if p.tok != token.RBRACK { + len = p.parseRhs() + } + p.exprLev-- } - p.exprLev-- - - return len + p.expect(token.RBRACK) + elt := p.parseType() + return &ast.ArrayType{Lbrack: lbrack, Len: len, Elt: elt} } func (p *parser) parseArrayFieldOrTypeInstance(x *ast.Ident) (*ast.Ident, ast.Expr) { @@ -996,7 +1000,7 @@ func (p *parser) parseMethodSpec() *ast.Field { lbrack := p.pos p.next() p.exprLev++ - x := p.parseExpr(nil) + x := p.parseExpr() p.exprLev-- if name0, _ := x.(*ast.Ident); name0 != nil && p.tok != token.COMMA && p.tok != token.RBRACK { // generic method m[T any] @@ -1238,10 +1242,7 @@ func (p *parser) tryIdentOrType() ast.Expr { return typ case token.LBRACK: lbrack := p.expect(token.LBRACK) - alen := p.parseArrayLen() - p.expect(token.RBRACK) - elt := p.parseType() - return &ast.ArrayType{Lbrack: lbrack, Len: alen, Elt: elt} + return p.parseArrayType(lbrack, nil) case token.STRUCT: return p.parseStructType() case token.MUL: @@ -1526,7 +1527,7 @@ func (p *parser) parseValue() ast.Expr { return p.parseLiteralValue(nil) } - x := p.checkExpr(p.parseExpr(nil)) + x := p.checkExpr(p.parseExpr()) return x } @@ -1802,18 +1803,18 @@ func (p *parser) parseBinaryExpr(x ast.Expr, prec1 int) ast.Expr { // The result may be a type or even a raw type ([...]int). Callers must // check the result (using checkExpr or checkExprOrType), depending on // context. -func (p *parser) parseExpr(lhs ast.Expr) ast.Expr { +func (p *parser) parseExpr() ast.Expr { if p.trace { defer un(trace(p, "Expression")) } - return p.parseBinaryExpr(lhs, token.LowestPrec+1) + return p.parseBinaryExpr(nil, token.LowestPrec+1) } func (p *parser) parseRhs() ast.Expr { old := p.inRhs p.inRhs = true - x := p.checkExpr(p.parseExpr(nil)) + x := p.checkExpr(p.parseExpr()) p.inRhs = old return x } @@ -1821,7 +1822,7 @@ func (p *parser) parseRhs() ast.Expr { func (p *parser) parseRhsOrType() ast.Expr { old := p.inRhs p.inRhs = true - x := p.checkExprOrType(p.parseExpr(nil)) + x := p.checkExprOrType(p.parseExpr()) p.inRhs = old return x } @@ -2554,49 +2555,42 @@ func (p *parser) parseTypeSpec(doc *ast.CommentGroup, _ token.Pos, _ token.Token ident := p.parseIdent() spec := &ast.TypeSpec{Doc: doc, Name: ident} - switch p.tok { - case token.LBRACK: + if p.tok == token.LBRACK && p.allowGenerics() { lbrack := p.pos p.next() if p.tok == token.IDENT { // array type or generic type: [name0... name0 := p.parseIdent() - if p.allowGenerics() && p.tok == token.LBRACK { - // Index or slice expressions are not valid array lengths, so we can - // parse as though we are in a generic type with array or slice - // constraint: [T [... - p.parseGenericType(spec, lbrack, name0) - break - } else { - + // Index or slice expressions are never constant and thus invalid + // array length expressions. Thus, if we see a "[" following name + // we can safely assume that "[" name starts a type parameter list. + var x ast.Expr // x != nil means x is the array length expression + if p.tok != token.LBRACK { // We may still have either an array type or generic type -- check if // name0 is the entire expr. p.exprLev++ lhs := p.parsePrimaryExpr(name0) - x := p.parseExpr(lhs) + x = p.parseBinaryExpr(lhs, token.LowestPrec+1) p.exprLev-- - - if name1, _ := x.(*ast.Ident); p.allowGenerics() && name1 != nil && p.tok != token.RBRACK { - // generic type [T any]; - p.parseGenericType(spec, lbrack, name1) - } else { - // array type - // TODO(rfindley) should resolve all identifiers in x. - p.expect(token.RBRACK) - elt := p.parseType() - spec.Type = &ast.ArrayType{Lbrack: lbrack, Len: x, Elt: elt} + if x == name0 && p.tok != token.RBRACK { + x = nil } } + + if x == nil { + // generic type [T any]; + p.parseGenericType(spec, lbrack, name0) + } else { + // array type + // TODO(rfindley) should resolve all identifiers in x. + spec.Type = p.parseArrayType(lbrack, x) + } } else { // array type - alen := p.parseArrayLen() - p.expect(token.RBRACK) - elt := p.parseType() - spec.Type = &ast.ArrayType{Lbrack: lbrack, Len: alen, Elt: elt} + spec.Type = p.parseArrayType(lbrack, nil) } - - default: + } else { // no type parameters if p.tok == token.ASSIGN { // type alias -- GitLab From 3fa9ee49a077a0bcb7419110da02ca54a019f2cc Mon Sep 17 00:00:00 2001 From: Alexander Melentyev Date: Sun, 31 Oct 2021 17:50:22 +0000 Subject: [PATCH 1847/2500] bytes: remove redundant type conversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Icafb2d9fd11b23d3acaf9df07e7f90d8bcd829fa GitHub-Last-Rev: 2b766460554860510f3fec03a4b9fe2e65fad268 GitHub-Pull-Request: golang/go#49243 Reviewed-on: https://go-review.googlesource.com/c/go/+/360096 Reviewed-by: Brad Fitzpatrick Trust: Brad Fitzpatrick Trust: Martin Möhrmann --- src/bytes/bytes.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bytes/bytes.go b/src/bytes/bytes.go index 926f65cc8f..529d95a888 100644 --- a/src/bytes/bytes.go +++ b/src/bytes/bytes.go @@ -699,7 +699,7 @@ func ToValidUTF8(s, replacement []byte) []byte { if c < utf8.RuneSelf { i++ invalid = false - b = append(b, byte(c)) + b = append(b, c) continue } _, wid := utf8.DecodeRune(s[i:]) -- GitLab From fd09e88722e0af150bf8960e95e8da500ad91001 Mon Sep 17 00:00:00 2001 From: Alexander Melentyev Date: Sun, 31 Oct 2021 17:50:38 +0000 Subject: [PATCH 1848/2500] testing: remove redundant type conversion Change-Id: Ib6415bb09af02e9ebc0099f50bf0fd7b572f2516 GitHub-Last-Rev: ebaa849d66efa45bd8ca50a8306652d823a41678 GitHub-Pull-Request: golang/go#49244 Reviewed-on: https://go-review.googlesource.com/c/go/+/360214 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Emmanuel Odeke --- src/testing/benchmark.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/testing/benchmark.go b/src/testing/benchmark.go index 1ce637e137..d8ec217f66 100644 --- a/src/testing/benchmark.go +++ b/src/testing/benchmark.go @@ -45,7 +45,7 @@ func (f *durationOrCountFlag) String() string { if f.n > 0 { return fmt.Sprintf("%dx", f.n) } - return time.Duration(f.d).String() + return f.d.String() } func (f *durationOrCountFlag) Set(s string) error { -- GitLab From 89c527007f75884a78ffede5d493ec021e7dfcdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6hrmann?= Date: Sun, 31 Oct 2021 17:58:07 +0100 Subject: [PATCH 1849/2500] reflect: avoid stack copies of hiter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use a pointer reciever to avoid copying the hiter struct when checking if it is intialized. Found through profiling that showed reflect map iteration spending a good amount of time in duffcopy. This change will also help other MapIter methods checking hiter struct initialization like Value() and Key(). name old time/op new time/op delta MapIterNext-12 97.9ns ± 4% 83.8ns ± 2% -14.37% (p=0.000 n=10+10) Change-Id: I73ab964fa28061ee7e6d5c663a85048bd2e0274e Reviewed-on: https://go-review.googlesource.com/c/go/+/360254 Reviewed-by: Josh Bleecher Snyder Trust: Josh Bleecher Snyder Trust: Martin Möhrmann --- src/reflect/all_test.go | 10 ++++++++++ src/reflect/value.go | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index 725be28bf0..acc09962a0 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -7568,6 +7568,16 @@ func TestMapIterNext(t *testing.T) { } } +func BenchmarkMapIterNext(b *testing.B) { + m := ValueOf(map[string]int{"a": 0, "b": 1, "c": 2, "d": 3}) + it := m.MapRange() + for i := 0; i < b.N; i++ { + for it.Next() { + } + it.Reset(m) + } +} + func TestMapIterDelete0(t *testing.T) { // Delete all elements before first iteration. m := map[string]int{"one": 1, "two": 2, "three": 3} diff --git a/src/reflect/value.go b/src/reflect/value.go index 90edf8e31d..ecf9dd7bc8 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -1665,7 +1665,7 @@ type hiter struct { checkBucket uintptr } -func (h hiter) initialized() bool { +func (h *hiter) initialized() bool { return h.t != nil } -- GitLab From fde4cc2a3189e2c964a0ce49de3cbe79ebedf985 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Tue, 5 Oct 2021 10:35:31 -0400 Subject: [PATCH 1850/2500] testing: reduce memory used by subtest names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is heavily based on CL 341336 by Joe Tsai and CL 351452 by Jay Conrod. T.Run and T.Name use a map[string]int64 to hold the next suffix to use when duplicate names are passed to T.Run. This map necessarily retains one entry per unique name. However, it's a waste of memory to retain one entry per duplicate name: when we encounter the Nth duplicate, we know that names 00 through N-1 have been used just by looking at N. We do still need to store (and check for collisions againsts) explicit names provided by the caller. For example, if the user passes in "a", then "a#01", then "a" again, we cannot deduplicate the second "a" to "a#01" — we need to instead skip ahead to "a#02". We can do so by checking the count of "a", then generating a proposed deduplicated name, then double-checking that proposed name against only the explicit names so far. This somewhat reduces memory usage for tests that spawn large numbers of duplicate subtests, but doesn't solve the problem of memory growth for fuzzing — we still have to track all of the explicit, user-provided subtest names, and in a long-running fuzz test that set alone may be unbounded. This fixes memory growth for the example described in https://golang.org/issue/44517#issuecomment-897104060, but not the one in https://golang.org/issue/44517#issuecomment-933825661. For #44517 Change-Id: Ia159ecfcf44561ba67508d3af6377c27856df31d Reviewed-on: https://go-review.googlesource.com/c/go/+/354749 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Reviewed-by: Emmanuel Odeke Reviewed-by: Jay Conrod --- src/testing/match.go | 78 +++++++++++++++++++++++------ src/testing/match_test.go | 101 +++++++++++++++++++++++++------------- 2 files changed, 131 insertions(+), 48 deletions(-) diff --git a/src/testing/match.go b/src/testing/match.go index c6ff429fe4..d530f70c26 100644 --- a/src/testing/match.go +++ b/src/testing/match.go @@ -17,8 +17,13 @@ type matcher struct { filter filterMatch matchFunc func(pat, str string) (bool, error) - mu sync.Mutex - subNames map[string]int64 + mu sync.Mutex + + // subNames is used to deduplicate subtest names. + // Each key is the subtest name joined to the deduplicated name of the parent test. + // Each value is the count of the number of occurrences of the given subtest name + // already seen. + subNames map[string]int32 } type filterMatch interface { @@ -54,7 +59,7 @@ func newMatcher(matchString func(pat, str string) (bool, error), patterns, name return &matcher{ filter: impl, matchFunc: matchString, - subNames: map[string]int64{}, + subNames: map[string]int32{}, } } @@ -189,22 +194,65 @@ func splitRegexp(s string) filterMatch { // unique creates a unique name for the given parent and subname by affixing it // with one or more counts, if necessary. func (m *matcher) unique(parent, subname string) string { - name := fmt.Sprintf("%s/%s", parent, subname) - empty := subname == "" + base := parent + "/" + subname + for { - next, exists := m.subNames[name] - if !empty && !exists { - m.subNames[name] = 1 // next count is 1 - return name + n := m.subNames[base] + if n < 0 { + panic("subtest count overflow") } - // Name was already used. We increment with the count and append a - // string with the count. - m.subNames[name] = next + 1 + m.subNames[base] = n + 1 + + if n == 0 && subname != "" { + prefix, nn := parseSubtestNumber(base) + if len(prefix) < len(base) && nn < m.subNames[prefix] { + // This test is explicitly named like "parent/subname#NN", + // and #NN was already used for the NNth occurrence of "parent/subname". + // Loop to add a disambiguating suffix. + continue + } + return base + } + + name := fmt.Sprintf("%s#%02d", base, n) + if m.subNames[name] != 0 { + // This is the nth occurrence of base, but the name "parent/subname#NN" + // collides with the first occurrence of a subtest *explicitly* named + // "parent/subname#NN". Try the next number. + continue + } + + return name + } +} + +// parseSubtestNumber splits a subtest name into a "#%02d"-formatted int32 +// suffix (if present), and a prefix preceding that suffix (always). +func parseSubtestNumber(s string) (prefix string, nn int32) { + i := strings.LastIndex(s, "#") + if i < 0 { + return s, 0 + } + + prefix, suffix := s[:i], s[i+1:] + if len(suffix) < 2 || (len(suffix) > 2 && suffix[0] == '0') { + // Even if suffix is numeric, it is not a possible output of a "%02" format + // string: it has either too few digits or too many leading zeroes. + return s, 0 + } + if suffix == "00" { + if !strings.HasSuffix(prefix, "/") { + // We only use "#00" as a suffix for subtests named with the empty + // string — it isn't a valid suffix if the subtest name is non-empty. + return s, 0 + } + } - // Add a count to guarantee uniqueness. - name = fmt.Sprintf("%s#%02d", name, next) - empty = false + n, err := strconv.ParseInt(suffix, 10, 32) + if err != nil || n < 0 { + return s, 0 } + return prefix, int32(n) } // rewrite rewrites a subname to having only printable characters and no white diff --git a/src/testing/match_test.go b/src/testing/match_test.go index 9ceadbb31d..206ac0b651 100644 --- a/src/testing/match_test.go +++ b/src/testing/match_test.go @@ -149,49 +149,84 @@ func TestMatcher(t *T) { } } +var namingTestCases = []struct{ name, want string }{ + // Uniqueness + {"", "x/#00"}, + {"", "x/#01"}, + {"#0", "x/#0"}, // Doesn't conflict with #00 because the number of digits differs. + {"#00", "x/#00#01"}, // Conflicts with implicit #00 (used above), so add a suffix. + {"#", "x/#"}, + {"#", "x/##01"}, + + {"t", "x/t"}, + {"t", "x/t#01"}, + {"t", "x/t#02"}, + {"t#00", "x/t#00"}, // Explicit "#00" doesn't conflict with the unsuffixed first subtest. + + {"a#01", "x/a#01"}, // user has subtest with this name. + {"a", "x/a"}, // doesn't conflict with this name. + {"a", "x/a#02"}, // This string is claimed now, so resume + {"a", "x/a#03"}, // with counting. + {"a#02", "x/a#02#01"}, // We already used a#02 once, so add a suffix. + + {"b#00", "x/b#00"}, + {"b", "x/b"}, // Implicit 0 doesn't conflict with explicit "#00". + {"b", "x/b#01"}, + {"b#9223372036854775807", "x/b#9223372036854775807"}, // MaxInt64 + {"b", "x/b#02"}, + {"b", "x/b#03"}, + + // Sanitizing + {"A:1 B:2", "x/A:1_B:2"}, + {"s\t\r\u00a0", "x/s___"}, + {"\x01", `x/\x01`}, + {"\U0010ffff", `x/\U0010ffff`}, +} + func TestNaming(t *T) { m := newMatcher(regexp.MatchString, "", "") - parent := &common{name: "x", level: 1} // top-level test. - // Rig the matcher with some preloaded values. - m.subNames["x/b"] = 1000 - - testCases := []struct { - name, want string - }{ - // Uniqueness - {"", "x/#00"}, - {"", "x/#01"}, - - {"t", "x/t"}, - {"t", "x/t#01"}, - {"t", "x/t#02"}, - - {"a#01", "x/a#01"}, // user has subtest with this name. - {"a", "x/a"}, // doesn't conflict with this name. - {"a", "x/a#01#01"}, // conflict, add disambiguating string. - {"a", "x/a#02"}, // This string is claimed now, so resume - {"a", "x/a#03"}, // with counting. - {"a#02", "x/a#02#01"}, - - {"b", "x/b#1000"}, // rigged, see above - {"b", "x/b#1001"}, - - // // Sanitizing - {"A:1 B:2", "x/A:1_B:2"}, - {"s\t\r\u00a0", "x/s___"}, - {"\x01", `x/\x01`}, - {"\U0010ffff", `x/\U0010ffff`}, - } - - for i, tc := range testCases { + for i, tc := range namingTestCases { if got, _, _ := m.fullName(parent, tc.name); got != tc.want { t.Errorf("%d:%s: got %q; want %q", i, tc.name, got, tc.want) } } } +func FuzzNaming(f *F) { + for _, tc := range namingTestCases { + f.Add(tc.name) + } + parent := &common{name: "x", level: 1} + var m *matcher + var seen map[string]string + reset := func() { + m = newMatcher(regexp.MatchString, "", "") + seen = make(map[string]string) + } + reset() + + f.Fuzz(func(t *T, subname string) { + if len(subname) > 10 { + // Long names attract the OOM killer. + t.Skip() + } + name := m.unique(parent.name, subname) + if !strings.Contains(name, "/"+subname) { + t.Errorf("name %q does not contain subname %q", name, subname) + } + if prev, ok := seen[name]; ok { + t.Errorf("name %q generated by both %q and %q", name, prev, subname) + } + if len(seen) > 1e6 { + // Free up memory. + reset() + } + seen[name] = subname + }) +} + // GoString returns a string that is more readable than the default, which makes // it easier to read test errors. func (m alternationMatch) GoString() string { -- GitLab From 732db407d30e9bd49d0907fd820207e6d646df9c Mon Sep 17 00:00:00 2001 From: "Paul E. Murphy" Date: Wed, 20 Oct 2021 13:40:54 -0500 Subject: [PATCH 1851/2500] cmd/link: make ppc64le __glink_PLTresolve position-independent This code is only generated when linking cgo internally with fixed position code. This feature of the internal linker is only supported on ppc64le/linux targets. This moves ppc64le/linux a little closer to supporting PIE when internal linking. This is more similar to the implementation suggested in the power architecture elfv2 supplement, and works with both PIE and static code. Change-Id: I0b64e1c22b9e07b5151378d2ab19ee0e50405fc5 Reviewed-on: https://go-review.googlesource.com/c/go/+/357332 Run-TryBot: Paul Murphy TryBot-Result: Go Bot Reviewed-by: Lynn Boger Reviewed-by: Cherry Mui --- src/cmd/link/internal/ppc64/asm.go | 41 ++++++++++++++++++------------ 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go index 9507010603..62b319d196 100644 --- a/src/cmd/link/internal/ppc64/asm.go +++ b/src/cmd/link/internal/ppc64/asm.go @@ -1067,35 +1067,31 @@ func ensureglinkresolver(ctxt *ld.Link, ldr *loader.Loader) *loader.SymbolBuilde return glink } - // This is essentially the resolver from the ppc64 ELF ABI. + // This is essentially the resolver from the ppc64 ELFv2 ABI. // At entry, r12 holds the address of the symbol resolver stub // for the target routine and the argument registers hold the // arguments for the target routine. // + // PC-rel offsets are computed once the final codesize of the + // resolver is known. + // // This stub is PIC, so first get the PC of label 1 into r11. - // Other things will be relative to this. glink.AddUint32(ctxt.Arch, 0x7c0802a6) // mflr r0 glink.AddUint32(ctxt.Arch, 0x429f0005) // bcl 20,31,1f glink.AddUint32(ctxt.Arch, 0x7d6802a6) // 1: mflr r11 - glink.AddUint32(ctxt.Arch, 0x7c0803a6) // mtlf r0 + glink.AddUint32(ctxt.Arch, 0x7c0803a6) // mtlr r0 - // Compute the .plt array index from the entry point address. - // Because this is PIC, everything is relative to label 1b (in - // r11): - // r0 = ((r12 - r11) - (res_0 - r11)) / 4 = (r12 - res_0) / 4 - glink.AddUint32(ctxt.Arch, 0x3800ffd0) // li r0,-(res_0-1b)=-48 + // Compute the .plt array index from the entry point address + // into r0. This is computed relative to label 1 above. + glink.AddUint32(ctxt.Arch, 0x38000000) // li r0,-(res_0-1b) glink.AddUint32(ctxt.Arch, 0x7c006214) // add r0,r0,r12 glink.AddUint32(ctxt.Arch, 0x7c0b0050) // sub r0,r0,r11 glink.AddUint32(ctxt.Arch, 0x7800f082) // srdi r0,r0,2 - // r11 = address of the first byte of the PLT - r, _ := glink.AddRel(objabi.R_ADDRPOWER) - r.SetSym(ctxt.PLT) - r.SetSiz(8) - r.SetOff(int32(glink.Size())) - r.SetAdd(0) - glink.AddUint32(ctxt.Arch, 0x3d600000) // addis r11,0,.plt@ha - glink.AddUint32(ctxt.Arch, 0x396b0000) // addi r11,r11,.plt@l + // Load the PC-rel offset of ".plt - 1b", and add it to 1b. + // This is stored after this stub and before the resolvers. + glink.AddUint32(ctxt.Arch, 0xe98b0000) // ld r12,res_0-1b-8(r11) + glink.AddUint32(ctxt.Arch, 0x7d6b6214) // add r11,r11,r12 // Load r12 = dynamic resolver address and r11 = DSO // identifier from the first two doublewords of the PLT. @@ -1106,6 +1102,19 @@ func ensureglinkresolver(ctxt *ld.Link, ldr *loader.Loader) *loader.SymbolBuilde glink.AddUint32(ctxt.Arch, 0x7d8903a6) // mtctr r12 glink.AddUint32(ctxt.Arch, 0x4e800420) // bctr + // Store the PC-rel offset to the PLT + r, _ := glink.AddRel(objabi.R_PCREL) + r.SetSym(ctxt.PLT) + r.SetSiz(8) + r.SetOff(int32(glink.Size())) + r.SetAdd(glink.Size()) // Adjust the offset to be relative to label 1 above. + glink.AddUint64(ctxt.Arch, 0) // The offset to the PLT. + + // Resolve PC-rel offsets above now the final size of the stub is known. + res0m1b := glink.Size() - 8 // res_0 - 1b + glink.SetUint32(ctxt.Arch, 16, 0x38000000|uint32(uint16(-res0m1b))) + glink.SetUint32(ctxt.Arch, 32, 0xe98b0000|uint32(uint16(res0m1b-8))) + // The symbol resolvers must immediately follow. // res_0: -- GitLab From 4056934e483c51fa046f9c2d1ee35f0385b84d91 Mon Sep 17 00:00:00 2001 From: Archana R Date: Mon, 25 Oct 2021 23:57:46 -0500 Subject: [PATCH 1852/2500] test/codegen: updated arithmetic tests to verify on ppc64,ppc64le Updated multiple tests in test/codegen/arithmetic.go to verify on ppc64/ppc64le as well Change-Id: I79ca9f87017ea31147a4ba16f5d42ba0fcae64e1 Reviewed-on: https://go-review.googlesource.com/c/go/+/358546 Run-TryBot: Lynn Boger TryBot-Result: Go Bot Reviewed-by: Lynn Boger Reviewed-by: Cherry Mui --- test/codegen/arithmetic.go | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/test/codegen/arithmetic.go b/test/codegen/arithmetic.go index 8b8c8ed64b..00841d52ae 100644 --- a/test/codegen/arithmetic.go +++ b/test/codegen/arithmetic.go @@ -86,24 +86,32 @@ func NegAddFromConstNeg(a int) int { func SubSubNegSimplify(a, b int) int { // amd64:"NEGQ" + // ppc64:"NEG" + // ppc64le:"NEG" r := (a - b) - a return r } func SubAddSimplify(a, b int) int { // amd64:-"SUBQ",-"ADDQ" + // ppc64:-"SUB",-"ADD" + // ppc64le:-"SUB",-"ADD" r := a + (b - a) return r } func SubAddNegSimplify(a, b int) int { // amd64:"NEGQ",-"ADDQ",-"SUBQ" + // ppc64:"NEG",-"ADD",-"SUB" + // ppc64le:"NEG",-"ADD",-"SUB" r := a - (b + a) return r } func AddAddSubSimplify(a, b, c int) int { // amd64:-"SUBQ" + // ppc64:-"SUB" + // ppc64le:-"SUB" r := a + (b + (c - a)) return r } @@ -159,30 +167,40 @@ func MulMemSrc(a []uint32, b []float32) { func MergeMuls1(n int) int { // amd64:"IMUL3Q\t[$]46" // 386:"IMUL3L\t[$]46" + // ppc64le:"MULLD\t[$]46" + // ppc64:"MULLD\t[$]46" return 15*n + 31*n // 46n } func MergeMuls2(n int) int { // amd64:"IMUL3Q\t[$]23","(ADDQ\t[$]29)|(LEAQ\t29)" // 386:"IMUL3L\t[$]23","ADDL\t[$]29" + // ppc64le/power9:"MADDLD",-"MULLD\t[$]23",-"ADD\t[$]29" + // ppc64le/power8:"MULLD\t[$]23","ADD\t[$]29" return 5*n + 7*(n+1) + 11*(n+2) // 23n + 29 } func MergeMuls3(a, n int) int { // amd64:"ADDQ\t[$]19",-"IMULQ\t[$]19" // 386:"ADDL\t[$]19",-"IMULL\t[$]19" + // ppc64:"ADD\t[$]19",-"MULLD\t[$]19" + // ppc64le:"ADD\t[$]19",-"MULLD\t[$]19" return a*n + 19*n // (a+19)n } func MergeMuls4(n int) int { // amd64:"IMUL3Q\t[$]14" // 386:"IMUL3L\t[$]14" + // ppc64:"MULLD\t[$]14" + // ppc64le:"MULLD\t[$]14" return 23*n - 9*n // 14n } func MergeMuls5(a, n int) int { // amd64:"ADDQ\t[$]-19",-"IMULQ\t[$]19" // 386:"ADDL\t[$]-19",-"IMULL\t[$]19" + // ppc64:"ADD\t[$]-19",-"MULLD\t[$]19" + // ppc64le:"ADD\t[$]-19",-"MULLD\t[$]19" return a*n - 19*n // (a-19)n } @@ -507,6 +525,8 @@ func MULA(a, b, c uint32) (uint32, uint32, uint32) { r1 := c*79 + a // arm:`ADD`,-`MULA`,-`MUL\s` // arm64:`ADD`,-`MADD`,-`MULW` + // ppc64:`ADD`,-`MULLD` + // ppc64le:`ADD`,-`MULLD` r2 := b*64 + c return r0, r1, r2 } @@ -522,6 +542,8 @@ func MULS(a, b, c uint32) (uint32, uint32, uint32) { r1 := a - c*79 // arm/7:`SUB`,-`MULS`,-`MUL\s` // arm64:`SUB`,-`MSUBW`,-`MULW` + // ppc64:`SUB`,-`MULLD` + // ppc64le:`SUB`,-`MULLD` r2 := c - b*64 return r0, r1, r2 } @@ -550,12 +572,20 @@ func divInt(v int64) int64 { // "(z + C) -x -> C + (z - x)" can optimize the following cases. func constantFold1(i0, j0, i1, j1, i2, j2, i3, j3 int) (int, int, int, int) { // arm64:"SUB","ADD\t[$]2" + // ppc64:"SUB","ADD\t[$]2" + // ppc64le:"SUB","ADD\t[$]2" r0 := (i0 + 3) - (j0 + 1) // arm64:"SUB","SUB\t[$]4" + // ppc64:"SUB","ADD\t[$]-4" + // ppc64le:"SUB","ADD\t[$]-4" r1 := (i1 - 3) - (j1 + 1) // arm64:"SUB","ADD\t[$]4" + // ppc64:"SUB","ADD\t[$]4" + // ppc64le:"SUB","ADD\t[$]4" r2 := (i2 + 3) - (j2 - 1) // arm64:"SUB","SUB\t[$]2" + // ppc64:"SUB","ADD\t[$]-2" + // ppc64le:"SUB","ADD\t[$]-2" r3 := (i3 - 3) - (j3 - 1) return r0, r1, r2, r3 } @@ -564,14 +594,20 @@ func constantFold1(i0, j0, i1, j1, i2, j2, i3, j3 int) (int, int, int, int) { // "(C - z) - x -> C - (z + x)" can optimize the following cases. func constantFold2(i0, j0, i1, j1 int) (int, int) { // arm64:"ADD","MOVD\t[$]2","SUB" + // ppc64le: `SUBC\tR[0-9]+,\s[$]2,\sR` + // ppc64: `SUBC\tR[0-9]+,\s[$]2,\sR` r0 := (3 - i0) - (j0 + 1) // arm64:"ADD","MOVD\t[$]4","SUB" + // ppc64le: `SUBC\tR[0-9]+,\s[$]4,\sR` + // ppc64: `SUBC\tR[0-9]+,\s[$]4,\sR` r1 := (3 - i1) - (j1 - 1) return r0, r1 } func constantFold3(i, j int) int { // arm64: "MOVD\t[$]30","MUL",-"ADD",-"LSL" + // ppc64:"MULLD\t[$]30","MULLD" + // ppc64le:"MULLD\t[$]30","MULLD" r := (5 * i) * (6 * j) return r } -- GitLab From 82f902ae8e2b7f7eff0cdb087e47e939cc296a62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6hrmann?= Date: Mon, 1 Nov 2021 06:42:01 +0100 Subject: [PATCH 1853/2500] strings: align Clone output with string([]byte("")) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a comment how strings of length 0 are treated and that they always will result in the return of a string equal to the constant string "". The previous implementation would return a string header that uses runtime.zerobase as the backing array pointer while the string constant "" has 0 as pointer value. Using 0 has the backing array pointer is also the behaviour of string([]byte(input)) which makes the new behaviour a better drop in replacement. Change-Id: Ic5460e9494b6708edbdfa4361e878d50db54ba10 Reviewed-on: https://go-review.googlesource.com/c/go/+/360255 Trust: Martin Möhrmann Run-TryBot: Martin Möhrmann TryBot-Result: Go Bot Reviewed-by: Russ Cox --- src/strings/clone.go | 5 +++++ src/strings/clone_test.go | 11 ++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/strings/clone.go b/src/strings/clone.go index 6097c6cc88..edd1497d9e 100644 --- a/src/strings/clone.go +++ b/src/strings/clone.go @@ -16,7 +16,12 @@ import ( // overuse of Clone can make programs use more memory. // Clone should typically be used only rarely, and only when // profiling indicates that it is needed. +// For strings of length zero the string "" will be returned +// and no allocation is made. func Clone(s string) string { + if len(s) == 0 { + return "" + } b := make([]byte, len(s)) copy(b, s) return *(*string)(unsafe.Pointer(&b)) diff --git a/src/strings/clone_test.go b/src/strings/clone_test.go index 5396771047..a9ba8add23 100644 --- a/src/strings/clone_test.go +++ b/src/strings/clone_test.go @@ -11,9 +11,13 @@ import ( "unsafe" ) +var emptyString string + func TestClone(t *testing.T) { var cloneTests = []string{ "", + strings.Clone(""), + strings.Repeat("a", 42)[:0], "short", strings.Repeat("a", 42), } @@ -25,9 +29,14 @@ func TestClone(t *testing.T) { inputHeader := (*reflect.StringHeader)(unsafe.Pointer(&input)) cloneHeader := (*reflect.StringHeader)(unsafe.Pointer(&clone)) - if inputHeader.Data == cloneHeader.Data { + if len(input) != 0 && cloneHeader.Data == inputHeader.Data { t.Errorf("Clone(%q) return value should not reference inputs backing memory.", input) } + + emptyHeader := (*reflect.StringHeader)(unsafe.Pointer(&emptyString)) + if len(input) == 0 && cloneHeader.Data != emptyHeader.Data { + t.Errorf("Clone(%#v) return value should be equal to empty string.", inputHeader) + } } } -- GitLab From d2b512160e4fc9dd69947ad9566c2dab1a135694 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sun, 31 Oct 2021 10:37:15 -0700 Subject: [PATCH 1854/2500] cmd/compile/internal/types2: differently named types are not assignable When checking assignability, a value of a named type (incl. a type parameter) can never be assigned to a variable of a differently named type. Specifically, if the types are two differently named type parameters, then values of one are never assignable to variables of the other. This CL clarifies the assignabiliy rules and simplifies the implementation. Fixes #49242. Change-Id: Id72a2c9bed5cdb726855e7a707137db1009e7953 Reviewed-on: https://go-review.googlesource.com/c/go/+/360274 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/operand.go | 66 +++++++++---------- .../types2/testdata/fixedbugs/issue49242.go2 | 27 ++++++++ .../types2/testdata/spec/assignability.go2 | 46 ++++++++++--- 3 files changed, 94 insertions(+), 45 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue49242.go2 diff --git a/src/cmd/compile/internal/types2/operand.go b/src/cmd/compile/internal/types2/operand.go index e4db0554f3..2f85802701 100644 --- a/src/cmd/compile/internal/types2/operand.go +++ b/src/cmd/compile/internal/types2/operand.go @@ -317,19 +317,11 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er } } - // common case: if we don't have type parameters, we're done + // optimization: if we don't have type parameters, we're done if Vp == nil && Tp == nil { return false, _IncompatibleAssign } - // determine type parameter operands with specific type terms - if Vp != nil && !Vp.hasTerms() { - Vp = nil - } - if Tp != nil && !Tp.hasTerms() { - Tp = nil - } - errorf := func(format string, args ...interface{}) { if check != nil && reason != nil { msg := check.sprintf(format, args...) @@ -340,46 +332,48 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er } } - ok := false - code := _IncompatibleAssign - switch { - case Vp != nil && Tp != nil: - x := *x // don't clobber outer x - ok = Vp.is(func(V *term) bool { - x.typ = V.typ - return Tp.is(func(T *term) bool { - ok, code = x.assignableTo(check, T.typ, reason) - if !ok { - errorf("cannot assign %s (in %s) to %s (in %s)", V.typ, Vp, T.typ, Tp) - return false - } - return true - }) - }) - case Vp != nil: - x := *x // don't clobber outer x - ok = Vp.is(func(V *term) bool { - x.typ = V.typ - ok, code = x.assignableTo(check, T, reason) + // x's type V is not a named type and T is a type parameter, and + // x is assignable to each specific type in T's type set. + if !hasName(V) && Tp != nil { + ok := false + code := _IncompatibleAssign + Tp.is(func(T *term) bool { + if T == nil { + return false // no specific types + } + ok, code = x.assignableTo(check, T.typ, reason) if !ok { - errorf("cannot assign %s (in %s) to %s", V.typ, Vp, T) + errorf("cannot assign %s to %s (in %s)", x.typ, T.typ, Tp) return false } return true }) - case Tp != nil: + return ok, code + } + + // x's type V is a type parameter and T is not a named type, + // and values x' of each specific type in V's type set are + // assignable to T. + if Vp != nil && !hasName(T) { x := *x // don't clobber outer x - ok = Tp.is(func(T *term) bool { - ok, code = x.assignableTo(check, T.typ, reason) + ok := false + code := _IncompatibleAssign + Vp.is(func(V *term) bool { + if V == nil { + return false // no specific types + } + x.typ = V.typ + ok, code = x.assignableTo(check, T, reason) if !ok { - errorf("cannot assign %s to %s (in %s)", x.typ, T.typ, Tp) + errorf("cannot assign %s (in %s) to %s", V.typ, Vp, T) return false } return true }) + return ok, code } - return ok, code + return false, _IncompatibleAssign } // kind2tok translates syntax.LitKinds into token.Tokens. diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49242.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49242.go2 new file mode 100644 index 0000000000..524a0cbae3 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49242.go2 @@ -0,0 +1,27 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func _[P int](x P) int { + return x // ERROR cannot use x .* as int value in return statement +} + +func _[P int]() int { + return P /* ERROR cannot use P\(1\) .* as int value in return statement */ (1) +} + +func _[P int](x int) P { + return x // ERROR cannot use x .* as P value in return statement +} + +func _[P, Q any](x P) Q { + return x // ERROR cannot use x .* as Q value in return statement +} + +// test case from issue +func F[G interface{ uint }]() int { + f := func(uint) int { return 0 } + return f(G /* ERROR cannot use G\(1\) .* as uint value in argument to f */ (1)) +} diff --git a/src/cmd/compile/internal/types2/testdata/spec/assignability.go2 b/src/cmd/compile/internal/types2/testdata/spec/assignability.go2 index ab8f9c08b2..fb28358bbb 100644 --- a/src/cmd/compile/internal/types2/testdata/spec/assignability.go2 +++ b/src/cmd/compile/internal/types2/testdata/spec/assignability.go2 @@ -109,20 +109,48 @@ func _[ ) var ( - _ _CC = C - _ _SC = C - _ _RC = C + _ _CC = C // ERROR cannot use C .* as _CC value + _ _SC = C // ERROR cannot use C .* as _SC value + _ _RC = C // ERROR cannot use C .* as _RC value - _ CC = _CC(nil) - _ SC = _CC(nil) - _ RC = _CC(nil) + _ CC = _CC /* ERROR cannot use _CC\(nil\) .* as CC value */ (nil) + _ SC = _CC /* ERROR cannot use _CC\(nil\) .* as SC value */ (nil) + _ RC = _CC /* ERROR cannot use _CC\(nil\) .* as RC value */ (nil) - _ CC = C - _ SC = C // ERROR cannot use C .* as SC value .* cannot assign Chan to SendChan - _ RC = C // ERROR cannot use C .* as RC value .* cannot assign Chan to RecvChan + _ CC = C // ERROR cannot use C .* as CC value + _ SC = C // ERROR cannot use C .* as SC value + _ RC = C // ERROR cannot use C .* as RC value ) } +// "x's type V is not a named type and T is a type parameter, and x is assignable to each specific type in T's type set." +func _[ + TP0 any, + TP1 ~_Chan, + TP2 ~chan int | ~chan byte, +]() { + var ( + _ TP0 = c // ERROR cannot use c .* as TP0 value + _ TP0 = C // ERROR cannot use C .* as TP0 value + _ TP1 = c + _ TP1 = C // ERROR cannot use C .* as TP1 value + _ TP2 = c // ERROR .* cannot assign chan int to chan byte + ) +} + +// "x's type V is a type parameter and T is not a named type, and values x' of each specific type in V's type set are assignable to T." +func _[ + TP0 Interface, + TP1 ~_Chan, + TP2 ~chan int | ~chan byte, +](X0 TP0, X1 TP1, X2 TP2) { + i = X0 + I = X0 + c = X1 + C = X1 // ERROR cannot use X1 .* as Chan value + c = X2 // ERROR .* cannot assign chan byte \(in TP2\) to chan int +} + // "x is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type" func _[TP Interface](X TP) { b = nil // ERROR cannot use untyped nil -- GitLab From e2e910ef30f5b54018131cd24b198ced6e8215f8 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sun, 31 Oct 2021 12:08:32 -0700 Subject: [PATCH 1855/2500] cmd/compile/internal/types2: remove subscripts from type parameter names This is a port of CL 357814 from go/types to types2 with minor adjustments due to small differences in error handling code. Change-Id: I72ecc4532e8349f569cabb38006f3d8ff517bf30 Reviewed-on: https://go-review.googlesource.com/c/go/+/360276 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/api_test.go | 14 +++++----- .../compile/internal/types2/builtins_test.go | 6 ++--- src/cmd/compile/internal/types2/errors.go | 12 ++++----- .../compile/internal/types2/instantiate.go | 2 +- src/cmd/compile/internal/types2/typestring.go | 26 +++++++++++++------ 5 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index 26652f3e74..5e111d6d87 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -326,25 +326,25 @@ func TestTypesInfo(t *testing.T) { {brokenPkg + `x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string]invalid type`}, // parameterized functions - {genericPkg + `p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[generic_p0.T₁ interface{}](generic_p0.T₁)`}, + {genericPkg + `p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[generic_p0.T interface{}](generic_p0.T)`}, {genericPkg + `p1; func f[T any](T) {}; var _ = f[int]`, `f[int]`, `func(int)`}, {genericPkg + `p2; func f[T any](T) {}; func _() { f(42) }`, `f`, `func(int)`}, {genericPkg + `p3; func f[T any](T) {}; func _() { f[int](42) }`, `f[int]`, `func(int)`}, - {genericPkg + `p4; func f[T any](T) {}; func _() { f[int](42) }`, `f`, `func[generic_p4.T₁ interface{}](generic_p4.T₁)`}, + {genericPkg + `p4; func f[T any](T) {}; func _() { f[int](42) }`, `f`, `func[generic_p4.T interface{}](generic_p4.T)`}, {genericPkg + `p5; func f[T any](T) {}; func _() { f(42) }`, `f(42)`, `()`}, // type parameters {genericPkg + `t0; type t[] int; var _ t`, `t`, `generic_t0.t`}, // t[] is a syntax error that is ignored in this test in favor of t - {genericPkg + `t1; type t[P any] int; var _ t[int]`, `t`, `generic_t1.t[generic_t1.P₁ interface{}]`}, - {genericPkg + `t2; type t[P interface{}] int; var _ t[int]`, `t`, `generic_t2.t[generic_t2.P₁ interface{}]`}, - {genericPkg + `t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `generic_t3.t[generic_t3.P₁, generic_t3.Q₂ interface{}]`}, - {brokenPkg + `t4; type t[P, Q interface{ m() }] int; var _ t[int, int]`, `t`, `broken_t4.t[broken_t4.P₁, broken_t4.Q₂ interface{m()}]`}, + {genericPkg + `t1; type t[P any] int; var _ t[int]`, `t`, `generic_t1.t[generic_t1.P interface{}]`}, + {genericPkg + `t2; type t[P interface{}] int; var _ t[int]`, `t`, `generic_t2.t[generic_t2.P interface{}]`}, + {genericPkg + `t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `generic_t3.t[generic_t3.P, generic_t3.Q interface{}]`}, + {brokenPkg + `t4; type t[P, Q interface{ m() }] int; var _ t[int, int]`, `t`, `broken_t4.t[broken_t4.P, broken_t4.Q interface{m()}]`}, // instantiated types must be sanitized {genericPkg + `g0; type t[P any] int; var x struct{ f t[int] }; var _ = x.f`, `x.f`, `generic_g0.t[int]`}, // issue 45096 - {genericPkg + `issue45096; func _[T interface{ ~int8 | ~int16 | ~int32 }](x T) { _ = x < 0 }`, `0`, `generic_issue45096.T₁`}, + {genericPkg + `issue45096; func _[T interface{ ~int8 | ~int16 | ~int32 }](x T) { _ = x < 0 }`, `0`, `generic_issue45096.T`}, // issue 47895 {`package p; import "unsafe"; type S struct { f int }; var s S; var _ = unsafe.Offsetof(s.f)`, `s.f`, `int`}, diff --git a/src/cmd/compile/internal/types2/builtins_test.go b/src/cmd/compile/internal/types2/builtins_test.go index 52dbba1cb9..dd71715a27 100644 --- a/src/cmd/compile/internal/types2/builtins_test.go +++ b/src/cmd/compile/internal/types2/builtins_test.go @@ -112,15 +112,15 @@ var builtinCalls = []struct { {"Alignof", `_ = unsafe.Alignof(0)`, `invalid type`}, // constant {"Alignof", `var x struct{}; _ = unsafe.Alignof(x)`, `invalid type`}, // constant - {"Alignof", `var x P; _ = unsafe.Alignof(x)`, `func(p.P₁) uintptr`}, + {"Alignof", `var x P; _ = unsafe.Alignof(x)`, `func(p.P) uintptr`}, {"Offsetof", `var x struct{f bool}; _ = unsafe.Offsetof(x.f)`, `invalid type`}, // constant {"Offsetof", `var x struct{_ int; f bool}; _ = unsafe.Offsetof((&x).f)`, `invalid type`}, // constant - {"Offsetof", `var x struct{_ int; f P}; _ = unsafe.Offsetof((&x).f)`, `func(p.P₁) uintptr`}, + {"Offsetof", `var x struct{_ int; f P}; _ = unsafe.Offsetof((&x).f)`, `func(p.P) uintptr`}, {"Sizeof", `_ = unsafe.Sizeof(0)`, `invalid type`}, // constant {"Sizeof", `var x struct{}; _ = unsafe.Sizeof(x)`, `invalid type`}, // constant - {"Sizeof", `var x P; _ = unsafe.Sizeof(x)`, `func(p.P₁) uintptr`}, + {"Sizeof", `var x P; _ = unsafe.Sizeof(x)`, `func(p.P) uintptr`}, {"Slice", `var p *int; _ = unsafe.Slice(p, 1)`, `func(*int, int) []int`}, {"Slice", `var p *byte; var n uintptr; _ = unsafe.Slice(p, n)`, `func(*byte, uintptr) []byte`}, diff --git a/src/cmd/compile/internal/types2/errors.go b/src/cmd/compile/internal/types2/errors.go index 0c8a4a90ff..b56d11a28b 100644 --- a/src/cmd/compile/internal/types2/errors.go +++ b/src/cmd/compile/internal/types2/errors.go @@ -66,7 +66,7 @@ func (err *error_) msg(qf Qualifier) string { fmt.Fprintf(&buf, "%s: ", p.pos) } } - buf.WriteString(sprintf(qf, p.format, p.args...)) + buf.WriteString(sprintf(qf, false, p.format, p.args...)) } return buf.String() } @@ -85,7 +85,7 @@ func (err *error_) errorf(at poser, format string, args ...interface{}) { err.desc = append(err.desc, errorDesc{posFor(at), format, args}) } -func sprintf(qf Qualifier, format string, args ...interface{}) string { +func sprintf(qf Qualifier, debug bool, format string, args ...interface{}) string { for i, arg := range args { switch a := arg.(type) { case nil: @@ -101,7 +101,7 @@ func sprintf(qf Qualifier, format string, args ...interface{}) string { case Object: arg = ObjectString(a, qf) case Type: - arg = TypeString(a, qf) + arg = typeString(a, qf, debug) } args[i] = arg } @@ -146,7 +146,7 @@ func (check *Checker) markImports(pkg *Package) { } func (check *Checker) sprintf(format string, args ...interface{}) string { - return sprintf(check.qualifier, format, args...) + return sprintf(check.qualifier, false, format, args...) } func (check *Checker) report(err *error_) { @@ -160,13 +160,13 @@ func (check *Checker) trace(pos syntax.Pos, format string, args ...interface{}) fmt.Printf("%s:\t%s%s\n", pos, strings.Repeat(". ", check.indent), - check.sprintf(format, args...), + sprintf(check.qualifier, true, format, args...), ) } // dump is only needed for debugging func (check *Checker) dump(format string, args ...interface{}) { - fmt.Println(check.sprintf(format, args...)) + fmt.Println(sprintf(check.qualifier, true, format, args...)) } func (check *Checker) err(at poser, msg string, soft bool) { diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 8228ef2c31..44cf593ffb 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -155,7 +155,7 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap qf = check.qualifier } errorf := func(format string, args ...interface{}) error { - return errors.New(sprintf(qf, format, args...)) + return errors.New(sprintf(qf, false, format, args...)) } // No type argument with non-empty type set satisfies the empty type set. diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 709499792b..56bf4124fd 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -43,8 +43,14 @@ func RelativeTo(pkg *Package) Qualifier { // The Qualifier controls the printing of // package-level objects, and may be nil. func TypeString(typ Type, qf Qualifier) string { + return typeString(typ, qf, false) +} + +func typeString(typ Type, qf Qualifier, debug bool) string { var buf bytes.Buffer - WriteType(&buf, typ, qf) + w := newTypeWriter(&buf, qf) + w.debug = debug + w.typ(typ) return buf.String() } @@ -64,19 +70,20 @@ func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) { } type typeWriter struct { - buf *bytes.Buffer - seen map[Type]bool - qf Qualifier - ctxt *Context // if non-nil, we are type hashing + buf *bytes.Buffer + seen map[Type]bool + qf Qualifier + ctxt *Context // if non-nil, we are type hashing + debug bool // if true, write debug annotations } func newTypeWriter(buf *bytes.Buffer, qf Qualifier) *typeWriter { - return &typeWriter{buf, make(map[Type]bool), qf, nil} + return &typeWriter{buf, make(map[Type]bool), qf, nil, false} } func newTypeHasher(buf *bytes.Buffer, ctxt *Context) *typeWriter { assert(ctxt != nil) - return &typeWriter{buf, make(map[Type]bool), nil, ctxt} + return &typeWriter{buf, make(map[Type]bool), nil, ctxt, false} } func (w *typeWriter) byte(b byte) { @@ -270,7 +277,10 @@ func (w *typeWriter) typ(typ Type) { if t.obj.pkg != nil { writePackage(w.buf, t.obj.pkg, w.qf) } - w.string(t.obj.name + subscript(t.id)) + w.string(t.obj.name) + if w.debug || w.ctxt != nil { + w.string(subscript(t.id)) + } default: // For externally defined implementations of Type. -- GitLab From 0ae4c7ff4a6d24ab33a0deebba74609159291b8c Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sun, 31 Oct 2021 17:27:12 -0700 Subject: [PATCH 1856/2500] cmd/compile/internal/types2: fix TypeName.IsAlias for type parameter names This is a port of CL 359656 from go/types to types2. For #49213. Change-Id: Ib98f9a344c1397af92e061cafd519ea374fd60bc Reviewed-on: https://go-review.googlesource.com/c/go/+/360294 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/object.go | 2 ++ src/cmd/compile/internal/types2/object_test.go | 3 +++ .../compile/internal/types2/testdata/fixedbugs/issue45985.go2 | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/types2/object.go b/src/cmd/compile/internal/types2/object.go index affeaf61f2..c7d6709c26 100644 --- a/src/cmd/compile/internal/types2/object.go +++ b/src/cmd/compile/internal/types2/object.go @@ -315,6 +315,8 @@ func (obj *TypeName) IsAlias() bool { return obj.pkg != nil || t.name != obj.name || t == universeByte || t == universeRune case *Named: return obj != t.obj + case *TypeParam: + return obj != t.obj default: return true } diff --git a/src/cmd/compile/internal/types2/object_test.go b/src/cmd/compile/internal/types2/object_test.go index a86733a5c9..ed3c123023 100644 --- a/src/cmd/compile/internal/types2/object_test.go +++ b/src/cmd/compile/internal/types2/object_test.go @@ -33,6 +33,8 @@ func TestIsAlias(t *testing.T) { pkg := NewPackage("p", "p") t1 := NewTypeName(nopos, pkg, "t1", nil) n1 := NewNamed(t1, new(Struct), nil) + t5 := NewTypeName(nopos, pkg, "t5", nil) + NewTypeParam(t5, nil) for _, test := range []struct { name *TypeName alias bool @@ -46,6 +48,7 @@ func TestIsAlias(t *testing.T) { {NewTypeName(nopos, nil, "int32", Typ[Int32]), false}, // type name refers to basic type with same name {NewTypeName(nopos, pkg, "int32", Typ[Int32]), true}, // type name is declared in user-defined package (outside Universe) {NewTypeName(nopos, nil, "rune", Typ[Rune]), true}, // type name refers to basic type rune which is an alias already + {t5, false}, // type name refers to type parameter and vice versa } { check(test.name, test.alias) } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45985.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45985.go2 index f25b9d2b26..ee5282d6ef 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45985.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45985.go2 @@ -5,7 +5,7 @@ package issue45985 // TODO(gri): this error should be on app[int] below. -func app[S /* ERROR "type S = S does not match" */ interface{ ~[]T }, T any](s S, e T) S { +func app[S /* ERROR "type S S does not match" */ interface{ ~[]T }, T any](s S, e T) S { return append(s, e) } -- GitLab From 80bedb848092c993182f79a946d54776dc251549 Mon Sep 17 00:00:00 2001 From: zhouguangyuan Date: Fri, 29 Oct 2021 15:24:28 +0800 Subject: [PATCH 1857/2500] go/types: fix TypeName.IsAlias for type parameter names Fixes #49213 Change-Id: I2bfc151b74b0d14efbd00e5d28584f4180126c5d Reviewed-on: https://go-review.googlesource.com/c/go/+/359656 Trust: Robert Griesemer Trust: Robert Findley Run-TryBot: Robert Griesemer Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/types/object.go | 2 ++ src/go/types/object_test.go | 3 +++ src/go/types/testdata/fixedbugs/issue45985.go2 | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/go/types/object.go b/src/go/types/object.go index 18015fc967..a8bd62a04e 100644 --- a/src/go/types/object.go +++ b/src/go/types/object.go @@ -269,6 +269,8 @@ func (obj *TypeName) IsAlias() bool { return obj.pkg != nil || t.name != obj.name || t == universeByte || t == universeRune case *Named: return obj != t.obj + case *TypeParam: + return obj != t.obj default: return true } diff --git a/src/go/types/object_test.go b/src/go/types/object_test.go index 0ff8fdd6fa..c12af64df7 100644 --- a/src/go/types/object_test.go +++ b/src/go/types/object_test.go @@ -30,6 +30,8 @@ func TestIsAlias(t *testing.T) { pkg := NewPackage("p", "p") t1 := NewTypeName(0, pkg, "t1", nil) n1 := NewNamed(t1, new(Struct), nil) + t5 := NewTypeName(0, pkg, "t5", nil) + NewTypeParam(t5, nil) for _, test := range []struct { name *TypeName alias bool @@ -43,6 +45,7 @@ func TestIsAlias(t *testing.T) { {NewTypeName(0, nil, "int32", Typ[Int32]), false}, // type name refers to basic type with same name {NewTypeName(0, pkg, "int32", Typ[Int32]), true}, // type name is declared in user-defined package (outside Universe) {NewTypeName(0, nil, "rune", Typ[Rune]), true}, // type name refers to basic type rune which is an alias already + {t5, false}, // type name refers to type parameter and vice versa } { check(test.name, test.alias) } diff --git a/src/go/types/testdata/fixedbugs/issue45985.go2 b/src/go/types/testdata/fixedbugs/issue45985.go2 index 6e42dbb633..07395911cd 100644 --- a/src/go/types/testdata/fixedbugs/issue45985.go2 +++ b/src/go/types/testdata/fixedbugs/issue45985.go2 @@ -5,7 +5,7 @@ package issue45985 // TODO(rFindley): this error should be on app[int] below. -func app[S /* ERROR "type S = S does not match" */ interface{ ~[]T }, T any](s S, e T) S { +func app[S /* ERROR "type S S does not match" */ interface{ ~[]T }, T any](s S, e T) S { return append(s, e) } -- GitLab From 2bcf1c0373195724161a9dc287e1dbc26404e4fa Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Fri, 29 Oct 2021 11:21:45 -0700 Subject: [PATCH 1858/2500] internal/fuzz: don't add duplicate corpus entries If a identical input is already present in the corpus, don't re-add it. This may happen when the same input produces a different coverage map, causing the coordinator to think it has found a new input. This fixes a race between reading/writing cached inputs. Fixes #48721 Change-Id: I4807602f433c2b99396d25ceaa58b827796b3555 Reviewed-on: https://go-review.googlesource.com/c/go/+/359755 Trust: Roland Shoemaker Trust: Katie Hockman Run-TryBot: Roland Shoemaker Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills Reviewed-by: Katie Hockman --- src/internal/fuzz/fuzz.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 5008927f0e..78319a7496 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -316,6 +316,23 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err // Update the coordinator's coverage mask and save the value. inputSize := len(result.entry.Data) if opts.CacheDir != "" { + // It is possible that the input that was discovered is already + // present in the corpus, but the worker produced a coverage map + // that still expanded our total coverage (this may happen due to + // flakiness in the coverage counters). In order to prevent adding + // duplicate entries to the corpus (and re-writing the file on + // disk), skip it if the on disk file already exists. + // TOOD(roland): this check is limited in that it will only be + // applied if we are using the CacheDir. Another option would be + // to iterate through the corpus and check if it is already present, + // which would catch cases where we are not caching entries. + // A slightly faster approach would be to keep some kind of map of + // entry hashes, which would allow us to avoid iterating through + // all entries. + _, err = os.Stat(result.entry.Path) + if err == nil { + continue + } err := writeToCorpus(&result.entry, opts.CacheDir) if err != nil { stop(err) -- GitLab From b5a5b7bfb1ba25abf8cad8b9ad9451fb6e79d941 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Fri, 29 Oct 2021 22:42:50 +0000 Subject: [PATCH 1859/2500] runtime: disable pacer lock held assertions in tests Fixes #49234. Change-Id: I64c1eab0dce2bbe990343b43a32858a6c9f3dcda Reviewed-on: https://go-review.googlesource.com/c/go/+/359878 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Michael Pratt --- src/runtime/export_test.go | 1 + src/runtime/mgcpacer.go | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index 2cc89e7121..533627fa58 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -1246,6 +1246,7 @@ func NewGCController(gcPercent int) *GCController { // on a 32-bit architecture, it may get allocated unaligned // space. g := escape(new(GCController)).(*GCController) + g.gcControllerState.test = true // Mark it as a test copy. g.init(int32(gcPercent)) return g } diff --git a/src/runtime/mgcpacer.go b/src/runtime/mgcpacer.go index 160383db43..af43e6258f 100644 --- a/src/runtime/mgcpacer.go +++ b/src/runtime/mgcpacer.go @@ -269,6 +269,9 @@ type gcControllerState struct { // If this is zero, no fractional workers are needed. fractionalUtilizationGoal float64 + // test indicates that this is a test-only copy of gcControllerState. + test bool + _ cpu.CacheLinePad } @@ -737,7 +740,9 @@ func (c *gcControllerState) addGlobals(amount int64) { // // mheap_.lock must be held or the world must be stopped. func (c *gcControllerState) commit(triggerRatio float64) { - assertWorldStoppedOrLockHeld(&mheap_.lock) + if !c.test { + assertWorldStoppedOrLockHeld(&mheap_.lock) + } // Compute the next GC goal, which is when the allocated heap // has grown by GOGC/100 over the heap marked by the last @@ -842,7 +847,9 @@ func (c *gcControllerState) commit(triggerRatio float64) { // // mheap_.lock must be held or the world must be stopped. func (c *gcControllerState) effectiveGrowthRatio() float64 { - assertWorldStoppedOrLockHeld(&mheap_.lock) + if !c.test { + assertWorldStoppedOrLockHeld(&mheap_.lock) + } egogc := float64(atomic.Load64(&c.heapGoal)-c.heapMarked) / float64(c.heapMarked) if egogc < 0 { @@ -859,7 +866,9 @@ func (c *gcControllerState) effectiveGrowthRatio() float64 { // // The world must be stopped, or mheap_.lock must be held. func (c *gcControllerState) setGCPercent(in int32) int32 { - assertWorldStoppedOrLockHeld(&mheap_.lock) + if !c.test { + assertWorldStoppedOrLockHeld(&mheap_.lock) + } out := c.gcPercent if in < 0 { -- GitLab From 5f1bcd1bc29615b4366f6da8df958bd048ef89a8 Mon Sep 17 00:00:00 2001 From: Ruslan Andreev Date: Mon, 1 Nov 2021 18:17:49 +0000 Subject: [PATCH 1860/2500] sync: add PoolStarvation benchmark This benchmark simulates object starvation in order to force Ps to steal objects from other Ps. Extracted from CL 314229. Change-Id: Iee31df355ba04d80fbd91c4414e397a375e6d6d7 Reviewed-on: https://go-review.googlesource.com/c/go/+/360256 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: David Chase Trust: Cherry Mui --- src/sync/pool_test.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/sync/pool_test.go b/src/sync/pool_test.go index f94153c8d7..d991621624 100644 --- a/src/sync/pool_test.go +++ b/src/sync/pool_test.go @@ -270,6 +270,26 @@ func BenchmarkPoolOverflow(b *testing.B) { }) } +// Simulate object starvation in order to force Ps to steal objects +// from other Ps. +func BenchmarkPoolStarvation(b *testing.B) { + var p Pool + count := 100 + // Reduce number of putted objects by 33 %. It creates objects starvation + // that force P-local storage to steal objects from other Ps. + countStarved := count - int(float32(count)*0.33) + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + for b := 0; b < countStarved; b++ { + p.Put(1) + } + for b := 0; b < count; b++ { + p.Get() + } + } + }) +} + var globalSink interface{} func BenchmarkPoolSTW(b *testing.B) { -- GitLab From 02e5913406b2ac354695471690b79d8d4242ad8d Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 1 Nov 2021 15:00:16 -0700 Subject: [PATCH 1861/2500] go/types, types2: remove confusing debugging output in inference error message When type inference cannot infer type arguments it prints the list of inferred type arguments (often empty) at the end of the error message. This was meant as debugging support only. Removed for now. Eventually we should provide a better error message. Fixes #49272. Change-Id: I68d43a6ace91081009cab0f2fbad7bfbddf5e76b Reviewed-on: https://go-review.googlesource.com/c/go/+/360554 Trust: Robert Griesemer Trust: Dan Scales Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/types2/infer.go | 2 +- src/go/types/infer.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index 156c2290f7..494e896ee9 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -218,7 +218,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, // At least one type argument couldn't be inferred. assert(targs != nil && index >= 0 && targs[index] == nil) tpar := tparams[index] - check.errorf(pos, "cannot infer %s (%s) (%s)", tpar.obj.name, tpar.obj.pos, targs) + check.errorf(pos, "cannot infer %s (%s)", tpar.obj.name, tpar.obj.pos) return nil } diff --git a/src/go/types/infer.go b/src/go/types/infer.go index 3348c29476..43b9af348e 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -214,7 +214,7 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, // At least one type argument couldn't be inferred. assert(index >= 0 && targs[index] == nil) tpar := tparams[index] - check.errorf(posn, _Todo, "cannot infer %s (%v) (%v)", tpar.obj.name, tpar.obj.pos, targs) + check.errorf(posn, _Todo, "cannot infer %s (%v)", tpar.obj.name, tpar.obj.pos) return nil } -- GitLab From 81fea0b4fd3b134d4c1d121abad171e358037ce3 Mon Sep 17 00:00:00 2001 From: Timothy Gu Date: Fri, 7 May 2021 01:03:59 -0700 Subject: [PATCH 1862/2500] net/url: consider ForceQuery in ResolveReference Previously, when resolving references of form (https://golang.org/?hello).ResolveReference(?) we only used URL.RawQuery to determine whether or not a query part is defined. Go 1.7 introduced URL.ForceQuery as a flag for the situation where a query part is provided but empty. But we did not use it in ResolveReference. This leads to the erroneous output https://golang.org/?hello when the correct output should be https://golang.org/? This commit rectifies that error. Fixes #46033 Change-Id: I05bc0b48bf2bbf13b4ddc0dd10599ea613dc2188 Reviewed-on: https://go-review.googlesource.com/c/go/+/317930 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Damien Neil --- src/net/url/url.go | 2 +- src/net/url/url_test.go | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/net/url/url.go b/src/net/url/url.go index d571ab2fc4..f31aa08b59 100644 --- a/src/net/url/url.go +++ b/src/net/url/url.go @@ -1083,7 +1083,7 @@ func (u *URL) ResolveReference(ref *URL) *URL { url.Path = "" return &url } - if ref.Path == "" && ref.RawQuery == "" { + if ref.Path == "" && !ref.ForceQuery && ref.RawQuery == "" { url.RawQuery = u.RawQuery if ref.Fragment == "" { url.Fragment = u.Fragment diff --git a/src/net/url/url_test.go b/src/net/url/url_test.go index 6807d58f1a..7c807d7a38 100644 --- a/src/net/url/url_test.go +++ b/src/net/url/url_test.go @@ -1244,6 +1244,9 @@ var resolveReferenceTests = []struct { {"https://a/b/c/d;p?q", "//g/d/e/f?y#s", "https://g/d/e/f?y#s"}, {"https://a/b/c/d;p#s", "?y", "https://a/b/c/d;p?y"}, {"https://a/b/c/d;p?q#s", "?y", "https://a/b/c/d;p?y"}, + + // Empty path and query but with ForceQuery (issue 46033). + {"https://a/b/c/d;p?q#s", "?", "https://a/b/c/d;p?"}, } func TestResolveReference(t *testing.T) { -- GitLab From a59e33224e42d60a97fa720a45e1b74eb6aaa3d0 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Mon, 2 Aug 2021 14:55:51 -0700 Subject: [PATCH 1863/2500] net/netip: add new IP address package Co-authored-by: Alex Willmer (GitHub @moreati) Co-authored-by: Alexander Yastrebov Co-authored-by: David Anderson (Tailscale CLA) Co-authored-by: David Crawshaw (Tailscale CLA) Co-authored-by: Dmytro Shynkevych (Tailscale CLA) Co-authored-by: Elias Naur Co-authored-by: Joe Tsai (Tailscale CLA) Co-authored-by: Jonathan Yu (GitHub @jawnsy) Co-authored-by: Josh Bleecher Snyder (Tailscale CLA) Co-authored-by: Maisem Ali (Tailscale CLA) Co-authored-by: Manuel Mendez (Go AUTHORS mmendez534@...) Co-authored-by: Matt Layher Co-authored-by: Noah Treuhaft (GitHub @nwt) Co-authored-by: Stefan Majer Co-authored-by: Terin Stock (Cloudflare CLA) Co-authored-by: Tobias Klauser Fixes #46518 Change-Id: I0041f9e1115d61fa6e95fcf32b01d9faee708712 Reviewed-on: https://go-review.googlesource.com/c/go/+/339309 Run-TryBot: Brad Fitzpatrick TryBot-Result: Go Bot Reviewed-by: Russ Cox Trust: Brad Fitzpatrick --- src/bytes/bytes.go | 2 +- src/crypto/x509/root_darwin.go | 4 +- src/go/build/deps_test.go | 16 +- src/internal/fuzz/fuzz.go | 9 +- src/internal/godebug/godebug.go | 34 + src/internal/godebug/godebug_test.go | 34 + src/internal/intern/intern.go | 178 +++ src/internal/intern/intern_test.go | 199 +++ src/net/conf.go | 3 +- src/net/http/server.go | 4 +- src/net/http/transport.go | 4 +- src/net/lookup.go | 23 + src/net/netip/export_test.go | 30 + src/net/netip/inlining_test.go | 110 ++ src/net/netip/leaf_alts.go | 43 + src/net/netip/netip.go | 1414 ++++++++++++++++++++ src/net/netip/netip_pkg_test.go | 359 +++++ src/net/netip/netip_test.go | 1798 ++++++++++++++++++++++++++ src/net/netip/slow_test.go | 190 +++ src/net/netip/uint128.go | 92 ++ src/net/netip/uint128_test.go | 89 ++ src/net/parse.go | 23 - src/net/parse_test.go | 27 - src/net/tcpsock.go | 15 + src/net/udpsock.go | 60 + src/strings/compare.go | 2 +- 26 files changed, 4694 insertions(+), 68 deletions(-) create mode 100644 src/internal/godebug/godebug.go create mode 100644 src/internal/godebug/godebug_test.go create mode 100644 src/internal/intern/intern.go create mode 100644 src/internal/intern/intern_test.go create mode 100644 src/net/netip/export_test.go create mode 100644 src/net/netip/inlining_test.go create mode 100644 src/net/netip/leaf_alts.go create mode 100644 src/net/netip/netip.go create mode 100644 src/net/netip/netip_pkg_test.go create mode 100644 src/net/netip/netip_test.go create mode 100644 src/net/netip/slow_test.go create mode 100644 src/net/netip/uint128.go create mode 100644 src/net/netip/uint128_test.go diff --git a/src/bytes/bytes.go b/src/bytes/bytes.go index 529d95a888..9e6b68eaf4 100644 --- a/src/bytes/bytes.go +++ b/src/bytes/bytes.go @@ -21,7 +21,7 @@ func Equal(a, b []byte) bool { } // Compare returns an integer comparing two byte slices lexicographically. -// The result will be 0 if a==b, -1 if a < b, and +1 if a > b. +// The result will be 0 if a == b, -1 if a < b, and +1 if a > b. // A nil argument is equivalent to an empty slice. func Compare(a, b []byte) int { return bytealg.Compare(a, b) diff --git a/src/crypto/x509/root_darwin.go b/src/crypto/x509/root_darwin.go index 164ad9dc77..ef051efd31 100644 --- a/src/crypto/x509/root_darwin.go +++ b/src/crypto/x509/root_darwin.go @@ -10,11 +10,11 @@ import ( "bytes" macOS "crypto/x509/internal/macos" "fmt" + "internal/godebug" "os" - "strings" ) -var debugDarwinRoots = strings.Contains(os.Getenv("GODEBUG"), "x509roots=1") +var debugDarwinRoots = godebug.Get("x509roots") == "1" func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) { return nil, nil diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index f4a92f8be4..1dd65d60d9 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -173,7 +173,7 @@ var depsRules = ` io/fs < embed; - unicode, fmt !< os, os/signal; + unicode, fmt !< net, os, os/signal; os/signal, STR < path/filepath @@ -187,6 +187,8 @@ var depsRules = ` OS < golang.org/x/sys/cpu; + os < internal/godebug; + # FMT is OS (which includes string routines) plus reflect and fmt. # It does not include package log, which should be avoided in core packages. strconv, unicode @@ -352,6 +354,13 @@ var depsRules = ` golang.org/x/net/lif, golang.org/x/net/route; + os, runtime, strconv, sync, unsafe, + internal/godebug + < internal/intern; + + internal/bytealg, internal/intern, internal/itoa, math/bits, sort, strconv + < net/netip; + # net is unavoidable when doing any networking, # so large dependencies must be kept out. # This is a long-looking list but most of these @@ -360,10 +369,12 @@ var depsRules = ` golang.org/x/net/dns/dnsmessage, golang.org/x/net/lif, golang.org/x/net/route, + internal/godebug, internal/nettrace, internal/poll, internal/singleflight, internal/race, + net/netip, os < net; @@ -515,7 +526,8 @@ var depsRules = ` FMT, DEBUG, flag, runtime/trace, internal/sysinfo, math/rand < testing; - FMT, crypto/sha256, encoding/json, go/ast, go/parser, go/token, math/rand, encoding/hex, crypto/sha256 + FMT, crypto/sha256, encoding/json, go/ast, go/parser, go/token, + internal/godebug, math/rand, encoding/hex, crypto/sha256 < internal/fuzz; internal/fuzz, internal/testlog, runtime/pprof, regexp diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 78319a7496..2ebe2a64db 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -12,6 +12,7 @@ import ( "crypto/sha256" "errors" "fmt" + "internal/godebug" "io" "io/ioutil" "math/bits" @@ -1063,13 +1064,7 @@ var ( func shouldPrintDebugInfo() bool { debugInfoOnce.Do(func() { - debug := strings.Split(os.Getenv("GODEBUG"), ",") - for _, f := range debug { - if f == "fuzzdebug=1" { - debugInfo = true - break - } - } + debugInfo = godebug.Get("fuzzdebug") == "1" }) return debugInfo } diff --git a/src/internal/godebug/godebug.go b/src/internal/godebug/godebug.go new file mode 100644 index 0000000000..ac434e5fd8 --- /dev/null +++ b/src/internal/godebug/godebug.go @@ -0,0 +1,34 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package godebug parses the GODEBUG environment variable. +package godebug + +import "os" + +// Get returns the value for the provided GODEBUG key. +func Get(key string) string { + return get(os.Getenv("GODEBUG"), key) +} + +// get returns the value part of key=value in s (a GODEBUG value). +func get(s, key string) string { + for i := 0; i < len(s)-len(key)-1; i++ { + if i > 0 && s[i-1] != ',' { + continue + } + afterKey := s[i+len(key):] + if afterKey[0] != '=' || s[i:i+len(key)] != key { + continue + } + val := afterKey[1:] + for i, b := range val { + if b == ',' { + return val[:i] + } + } + return val + } + return "" +} diff --git a/src/internal/godebug/godebug_test.go b/src/internal/godebug/godebug_test.go new file mode 100644 index 0000000000..41b9117b73 --- /dev/null +++ b/src/internal/godebug/godebug_test.go @@ -0,0 +1,34 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package godebug + +import "testing" + +func TestGet(t *testing.T) { + tests := []struct { + godebug string + key string + want string + }{ + {"", "", ""}, + {"", "foo", ""}, + {"foo=bar", "foo", "bar"}, + {"foo=bar,after=x", "foo", "bar"}, + {"before=x,foo=bar,after=x", "foo", "bar"}, + {"before=x,foo=bar", "foo", "bar"}, + {",,,foo=bar,,,", "foo", "bar"}, + {"foodecoy=wrong,foo=bar", "foo", "bar"}, + {"foo=", "foo", ""}, + {"foo", "foo", ""}, + {",foo", "foo", ""}, + {"foo=bar,baz", "loooooooong", ""}, + } + for _, tt := range tests { + got := get(tt.godebug, tt.key) + if got != tt.want { + t.Errorf("get(%q, %q) = %q; want %q", tt.godebug, tt.key, got, tt.want) + } + } +} diff --git a/src/internal/intern/intern.go b/src/internal/intern/intern.go new file mode 100644 index 0000000000..666caa6d2f --- /dev/null +++ b/src/internal/intern/intern.go @@ -0,0 +1,178 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package intern lets you make smaller comparable values by boxing +// a larger comparable value (such as a 16 byte string header) down +// into a globally unique 8 byte pointer. +// +// The globally unique pointers are garbage collected with weak +// references and finalizers. This package hides that. +package intern + +import ( + "internal/godebug" + "runtime" + "sync" + "unsafe" +) + +// A Value pointer is the handle to an underlying comparable value. +// See func Get for how Value pointers may be used. +type Value struct { + _ [0]func() // prevent people from accidentally using value type as comparable + cmpVal interface{} + // resurrected is guarded by mu (for all instances of Value). + // It is set true whenever v is synthesized from a uintptr. + resurrected bool +} + +// Get returns the comparable value passed to the Get func +// that returned v. +func (v *Value) Get() interface{} { return v.cmpVal } + +// key is a key in our global value map. +// It contains type-specialized fields to avoid allocations +// when converting common types to empty interfaces. +type key struct { + s string + cmpVal interface{} + // isString reports whether key contains a string. + // Without it, the zero value of key is ambiguous. + isString bool +} + +// keyFor returns a key to use with cmpVal. +func keyFor(cmpVal interface{}) key { + if s, ok := cmpVal.(string); ok { + return key{s: s, isString: true} + } + return key{cmpVal: cmpVal} +} + +// Value returns a *Value built from k. +func (k key) Value() *Value { + if k.isString { + return &Value{cmpVal: k.s} + } + return &Value{cmpVal: k.cmpVal} +} + +var ( + // mu guards valMap, a weakref map of *Value by underlying value. + // It also guards the resurrected field of all *Values. + mu sync.Mutex + valMap = map[key]uintptr{} // to uintptr(*Value) + valSafe = safeMap() // non-nil in safe+leaky mode +) + +// safeMap returns a non-nil map if we're in safe-but-leaky mode, +// as controlled by GODEBUG=intern=leaky +func safeMap() map[key]*Value { + if godebug.Get("intern") == "leaky" { + return map[key]*Value{} + } + return nil +} + +// Get returns a pointer representing the comparable value cmpVal. +// +// The returned pointer will be the same for Get(v) and Get(v2) +// if and only if v == v2, and can be used as a map key. +func Get(cmpVal interface{}) *Value { + return get(keyFor(cmpVal)) +} + +// GetByString is identical to Get, except that it is specialized for strings. +// This avoids an allocation from putting a string into an interface{} +// to pass as an argument to Get. +func GetByString(s string) *Value { + return get(key{s: s, isString: true}) +} + +// We play unsafe games that violate Go's rules (and assume a non-moving +// collector). So we quiet Go here. +// See the comment below Get for more implementation details. +//go:nocheckptr +func get(k key) *Value { + mu.Lock() + defer mu.Unlock() + + var v *Value + if valSafe != nil { + v = valSafe[k] + } else if addr, ok := valMap[k]; ok { + v = (*Value)(unsafe.Pointer(addr)) + v.resurrected = true + } + if v != nil { + return v + } + v = k.Value() + if valSafe != nil { + valSafe[k] = v + } else { + // SetFinalizer before uintptr conversion (theoretical concern; + // see https://github.com/go4org/intern/issues/13) + runtime.SetFinalizer(v, finalize) + valMap[k] = uintptr(unsafe.Pointer(v)) + } + return v +} + +func finalize(v *Value) { + mu.Lock() + defer mu.Unlock() + if v.resurrected { + // We lost the race. Somebody resurrected it while we + // were about to finalize it. Try again next round. + v.resurrected = false + runtime.SetFinalizer(v, finalize) + return + } + delete(valMap, keyFor(v.cmpVal)) +} + +// Interning is simple if you don't require that unused values be +// garbage collectable. But we do require that; we don't want to be +// DOS vector. We do this by using a uintptr to hide the pointer from +// the garbage collector, and using a finalizer to eliminate the +// pointer when no other code is using it. +// +// The obvious implementation of this is to use a +// map[interface{}]uintptr-of-*interface{}, and set up a finalizer to +// delete from the map. Unfortunately, this is racy. Because pointers +// are being created in violation of Go's unsafety rules, it's +// possible to create a pointer to a value concurrently with the GC +// concluding that the value can be collected. There are other races +// that break the equality invariant as well, but the use-after-free +// will cause a runtime crash. +// +// To make this work, the finalizer needs to know that no references +// have been unsafely created since the finalizer was set up. To do +// this, values carry a "resurrected" sentinel, which gets set +// whenever a pointer is unsafely created. If the finalizer encounters +// the sentinel, it clears the sentinel and delays collection for one +// additional GC cycle, by re-installing itself as finalizer. This +// ensures that the unsafely created pointer is visible to the GC, and +// will correctly prevent collection. +// +// This technique does mean that interned values that get reused take +// at least 3 GC cycles to fully collect (1 to clear the sentinel, 1 +// to clean up the unsafe map, 1 to be actually deleted). +// +// @ianlancetaylor commented in +// https://github.com/golang/go/issues/41303#issuecomment-717401656 +// that it is possible to implement weak references in terms of +// finalizers without unsafe. Unfortunately, the approach he outlined +// does not work here, for two reasons. First, there is no way to +// construct a strong pointer out of a weak pointer; our map stores +// weak pointers, but we must return strong pointers to callers. +// Second, and more fundamentally, we must return not just _a_ strong +// pointer to callers, but _the same_ strong pointer to callers. In +// order to return _the same_ strong pointer to callers, we must track +// it, which is exactly what we cannot do with strong pointers. +// +// See https://github.com/inetaf/netaddr/issues/53 for more +// discussion, and https://github.com/go4org/intern/issues/2 for an +// illustration of the subtleties at play. diff --git a/src/internal/intern/intern_test.go b/src/internal/intern/intern_test.go new file mode 100644 index 0000000000..d1e409ef95 --- /dev/null +++ b/src/internal/intern/intern_test.go @@ -0,0 +1,199 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package intern + +import ( + "fmt" + "runtime" + "testing" +) + +func TestBasics(t *testing.T) { + clearMap() + foo := Get("foo") + bar := Get("bar") + empty := Get("") + nilEface := Get(nil) + i := Get(0x7777777) + foo2 := Get("foo") + bar2 := Get("bar") + empty2 := Get("") + nilEface2 := Get(nil) + i2 := Get(0x7777777) + foo3 := GetByString("foo") + empty3 := GetByString("") + + if foo.Get() != foo2.Get() { + t.Error("foo/foo2 values differ") + } + if foo.Get() != foo3.Get() { + t.Error("foo/foo3 values differ") + } + if foo.Get() != "foo" { + t.Error("foo.Get not foo") + } + if foo != foo2 { + t.Error("foo/foo2 pointers differ") + } + if foo != foo3 { + t.Error("foo/foo3 pointers differ") + } + + if bar.Get() != bar2.Get() { + t.Error("bar values differ") + } + if bar.Get() != "bar" { + t.Error("bar.Get not bar") + } + if bar != bar2 { + t.Error("bar pointers differ") + } + + if i.Get() != i.Get() { + t.Error("i values differ") + } + if i.Get() != 0x7777777 { + t.Error("i.Get not 0x7777777") + } + if i != i2 { + t.Error("i pointers differ") + } + + if empty.Get() != empty2.Get() { + t.Error("empty/empty2 values differ") + } + if empty.Get() != empty.Get() { + t.Error("empty/empty3 values differ") + } + if empty.Get() != "" { + t.Error("empty.Get not empty string") + } + if empty != empty2 { + t.Error("empty/empty2 pointers differ") + } + if empty != empty3 { + t.Error("empty/empty3 pointers differ") + } + + if nilEface.Get() != nilEface2.Get() { + t.Error("nilEface values differ") + } + if nilEface.Get() != nil { + t.Error("nilEface.Get not nil") + } + if nilEface != nilEface2 { + t.Error("nilEface pointers differ") + } + + if n := mapLen(); n != 5 { + t.Errorf("map len = %d; want 4", n) + } + + wantEmpty(t) +} + +func wantEmpty(t testing.TB) { + t.Helper() + const gcTries = 5000 + for try := 0; try < gcTries; try++ { + runtime.GC() + n := mapLen() + if n == 0 { + break + } + if try == gcTries-1 { + t.Errorf("map len = %d after (%d GC tries); want 0, contents: %v", n, gcTries, mapKeys()) + } + } +} + +func TestStress(t *testing.T) { + iters := 10000 + if testing.Short() { + iters = 1000 + } + var sink []byte + for i := 0; i < iters; i++ { + _ = Get("foo") + sink = make([]byte, 1<<20) + } + _ = sink +} + +func BenchmarkStress(b *testing.B) { + done := make(chan struct{}) + defer close(done) + go func() { + for { + select { + case <-done: + return + default: + } + runtime.GC() + } + }() + + clearMap() + v1 := Get("foo") + b.ReportAllocs() + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + v2 := Get("foo") + if v1 != v2 { + b.Fatal("wrong value") + } + // And also a key we don't retain: + _ = Get("bar") + } + }) + runtime.GC() + wantEmpty(b) +} + +func mapLen() int { + mu.Lock() + defer mu.Unlock() + return len(valMap) +} + +func mapKeys() (keys []string) { + mu.Lock() + defer mu.Unlock() + for k := range valMap { + keys = append(keys, fmt.Sprint(k)) + } + return keys +} + +func clearMap() { + mu.Lock() + defer mu.Unlock() + for k := range valMap { + delete(valMap, k) + } +} + +var ( + globalString = "not a constant" + sink string +) + +func TestGetByStringAllocs(t *testing.T) { + allocs := int(testing.AllocsPerRun(100, func() { + GetByString(globalString) + })) + if allocs != 0 { + t.Errorf("GetString allocated %d objects, want 0", allocs) + } +} + +func BenchmarkGetByString(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + v := GetByString(globalString) + sink = v.Get().(string) + } +} diff --git a/src/net/conf.go b/src/net/conf.go index 1115699ab0..415caedacc 100644 --- a/src/net/conf.go +++ b/src/net/conf.go @@ -8,6 +8,7 @@ package net import ( "internal/bytealg" + "internal/godebug" "os" "runtime" "sync" @@ -286,7 +287,7 @@ func (c *conf) hostLookupOrder(r *Resolver, hostname string) (ret hostLookupOrde // cgo+2 // same, but debug level 2 // etc. func goDebugNetDNS() (dnsMode string, debugLevel int) { - goDebug := goDebugString("netdns") + goDebug := godebug.Get("netdns") parsePart := func(s string) { if s == "" { return diff --git a/src/net/http/server.go b/src/net/http/server.go index e9b0b4d9bd..91fad68694 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -13,6 +13,7 @@ import ( "crypto/tls" "errors" "fmt" + "internal/godebug" "io" "log" "math/rand" @@ -20,7 +21,6 @@ import ( "net/textproto" "net/url" urlpkg "net/url" - "os" "path" "runtime" "sort" @@ -3296,7 +3296,7 @@ func (srv *Server) onceSetNextProtoDefaults_Serve() { // configured otherwise. (by setting srv.TLSNextProto non-nil) // It must only be called via srv.nextProtoOnce (use srv.setupHTTP2_*). func (srv *Server) onceSetNextProtoDefaults() { - if omitBundledHTTP2 || strings.Contains(os.Getenv("GODEBUG"), "http2server=0") { + if omitBundledHTTP2 || godebug.Get("http2server") == "0" { return } // Enable HTTP/2 by default if the user hasn't otherwise diff --git a/src/net/http/transport.go b/src/net/http/transport.go index 0e60992e6c..05a1659136 100644 --- a/src/net/http/transport.go +++ b/src/net/http/transport.go @@ -17,6 +17,7 @@ import ( "crypto/tls" "errors" "fmt" + "internal/godebug" "io" "log" "net" @@ -24,7 +25,6 @@ import ( "net/http/internal/ascii" "net/textproto" "net/url" - "os" "reflect" "strings" "sync" @@ -360,7 +360,7 @@ func (t *Transport) hasCustomTLSDialer() bool { // It must be called via t.nextProtoOnce.Do. func (t *Transport) onceSetNextProtoDefaults() { t.tlsNextProtoWasNil = (t.TLSNextProto == nil) - if strings.Contains(os.Getenv("GODEBUG"), "http2client=0") { + if godebug.Get("http2client") == "0" { return } diff --git a/src/net/lookup.go b/src/net/lookup.go index fe573b8a27..e10c71ae75 100644 --- a/src/net/lookup.go +++ b/src/net/lookup.go @@ -8,6 +8,7 @@ import ( "context" "internal/nettrace" "internal/singleflight" + "net/netip" "sync" ) @@ -232,6 +233,28 @@ func (r *Resolver) LookupIP(ctx context.Context, network, host string) ([]IP, er return ips, nil } +// LookupNetIP looks up host using the local resolver. +// It returns a slice of that host's IP addresses of the type specified by +// network. +// The network must be one of "ip", "ip4" or "ip6". +func (r *Resolver) LookupNetIP(ctx context.Context, network, host string) ([]netip.Addr, error) { + // TODO(bradfitz): make this efficient, making the internal net package + // type throughout be netip.Addr and only converting to the net.IP slice + // version at the edge. But for now (2021-10-20), this is a wrapper around + // the old way. + ips, err := r.LookupIP(ctx, network, host) + if err != nil { + return nil, err + } + ret := make([]netip.Addr, 0, len(ips)) + for _, ip := range ips { + if a, ok := netip.AddrFromSlice(ip); ok { + ret = append(ret, a) + } + } + return ret, nil +} + // onlyValuesCtx is a context that uses an underlying context // for value lookup if the underlying context hasn't yet expired. type onlyValuesCtx struct { diff --git a/src/net/netip/export_test.go b/src/net/netip/export_test.go new file mode 100644 index 0000000000..59971fa2e4 --- /dev/null +++ b/src/net/netip/export_test.go @@ -0,0 +1,30 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package netip + +import "internal/intern" + +var ( + Z0 = z0 + Z4 = z4 + Z6noz = z6noz +) + +type Uint128 = uint128 + +func Mk128(hi, lo uint64) Uint128 { + return uint128{hi, lo} +} + +func MkAddr(u Uint128, z *intern.Value) Addr { + return Addr{u, z} +} + +func IPv4(a, b, c, d uint8) Addr { return AddrFrom4([4]byte{a, b, c, d}) } + +var TestAppendToMarshal = testAppendToMarshal + +func (a Addr) IsZero() bool { return a.isZero() } +func (p Prefix) IsZero() bool { return p.isZero() } diff --git a/src/net/netip/inlining_test.go b/src/net/netip/inlining_test.go new file mode 100644 index 0000000000..107fe1f083 --- /dev/null +++ b/src/net/netip/inlining_test.go @@ -0,0 +1,110 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package netip + +import ( + "internal/testenv" + "os/exec" + "path/filepath" + "regexp" + "runtime" + "strings" + "testing" +) + +func TestInlining(t *testing.T) { + testenv.MustHaveGoBuild(t) + t.Parallel() + var exe string + if runtime.GOOS == "windows" { + exe = ".exe" + } + out, err := exec.Command( + filepath.Join(runtime.GOROOT(), "bin", "go"+exe), + "build", + "--gcflags=-m", + "net/netip").CombinedOutput() + if err != nil { + t.Fatalf("go build: %v, %s", err, out) + } + got := map[string]bool{} + regexp.MustCompile(` can inline (\S+)`).ReplaceAllFunc(out, func(match []byte) []byte { + got[strings.TrimPrefix(string(match), " can inline ")] = true + return nil + }) + wantInlinable := []string{ + "(*uint128).halves", + "Addr.BitLen", + "Addr.hasZone", + "Addr.Is4", + "Addr.Is4In6", + "Addr.Is6", + "Addr.IsLoopback", + "Addr.IsMulticast", + "Addr.IsInterfaceLocalMulticast", + "Addr.IsValid", + "Addr.IsUnspecified", + "Addr.Less", + "Addr.lessOrEq", + "Addr.Unmap", + "Addr.Zone", + "Addr.v4", + "Addr.v6", + "Addr.v6u16", + "Addr.withoutZone", + "AddrPortFrom", + "AddrPort.Addr", + "AddrPort.Port", + "AddrPort.IsValid", + "Prefix.IsSingleIP", + "Prefix.Masked", + "Prefix.IsValid", + "PrefixFrom", + "Prefix.Addr", + "Prefix.Bits", + "AddrFrom4", + "IPv6LinkLocalAllNodes", + "IPv6Unspecified", + "MustParseAddr", + "MustParseAddrPort", + "MustParsePrefix", + "appendDecimal", + "appendHex", + "uint128.addOne", + "uint128.and", + "uint128.bitsClearedFrom", + "uint128.bitsSetFrom", + "uint128.isZero", + "uint128.not", + "uint128.or", + "uint128.subOne", + "uint128.xor", + } + switch runtime.GOARCH { + case "amd64", "arm64": + // These don't inline on 32-bit. + wantInlinable = append(wantInlinable, + "u64CommonPrefixLen", + "uint128.commonPrefixLen", + "Addr.Next", + "Addr.Prev", + ) + } + + for _, want := range wantInlinable { + if !got[want] { + t.Errorf("%q is no longer inlinable", want) + continue + } + delete(got, want) + } + for sym := range got { + if strings.Contains(sym, ".func") { + continue + } + t.Logf("not in expected set, but also inlinable: %q", sym) + + } +} diff --git a/src/net/netip/leaf_alts.go b/src/net/netip/leaf_alts.go new file mode 100644 index 0000000000..c51f7dfa54 --- /dev/null +++ b/src/net/netip/leaf_alts.go @@ -0,0 +1,43 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Stuff that exists in std, but we can't use due to being a dependency +// of net, for go/build deps_test policy reasons. + +package netip + +func stringsLastIndexByte(s string, b byte) int { + for i := len(s) - 1; i >= 0; i-- { + if s[i] == b { + return i + } + } + return -1 +} + +func beUint64(b []byte) uint64 { + _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 + return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | + uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 +} + +func bePutUint64(b []byte, v uint64) { + _ = b[7] // early bounds check to guarantee safety of writes below + b[0] = byte(v >> 56) + b[1] = byte(v >> 48) + b[2] = byte(v >> 40) + b[3] = byte(v >> 32) + b[4] = byte(v >> 24) + b[5] = byte(v >> 16) + b[6] = byte(v >> 8) + b[7] = byte(v) +} + +func bePutUint32(b []byte, v uint32) { + _ = b[3] // early bounds check to guarantee safety of writes below + b[0] = byte(v >> 24) + b[1] = byte(v >> 16) + b[2] = byte(v >> 8) + b[3] = byte(v) +} diff --git a/src/net/netip/netip.go b/src/net/netip/netip.go new file mode 100644 index 0000000000..4ef3b4bb68 --- /dev/null +++ b/src/net/netip/netip.go @@ -0,0 +1,1414 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package netip defines a IP address type that's a small value type. +// Building on that Addr type, the package also defines AddrPort (an +// IP address and a port), and Prefix (a IP address and a bit length +// prefix). +// +// Compared to the net.IP type, this package's Addr type takes less +// memory, is immutable, and is comparable (supports == and being a +// map key). +package netip + +import ( + "errors" + "math" + "strconv" + + "internal/bytealg" + "internal/intern" + "internal/itoa" +) + +// Sizes: (64-bit) +// net.IP: 24 byte slice header + {4, 16} = 28 to 40 bytes +// net.IPAddr: 40 byte slice header + {4, 16} = 44 to 56 bytes + zone length +// netip.Addr: 24 bytes (zone is per-name singleton, shared across all users) + +// Addr represents an IPv4 or IPv6 address (with or without a scoped +// addressing zone), similar to net.IP or net.IPAddr. +// +// Unlike net.IP or net.IPAddr, Addr is a comparable value +// type (it supports == and can be a map key) and is immutable. +type Addr struct { + // addr is the hi and lo bits of an IPv6 address. If z==z4, + // hi and lo contain the IPv4-mapped IPv6 address. + // + // hi and lo are constructed by interpreting a 16-byte IPv6 + // address as a big-endian 128-bit number. The most significant + // bits of that number go into hi, the rest into lo. + // + // For example, 0011:2233:4455:6677:8899:aabb:ccdd:eeff is stored as: + // addr.hi = 0x0011223344556677 + // addr.lo = 0x8899aabbccddeeff + // + // We store IPs like this, rather than as [16]byte, because it + // turns most operations on IPs into arithmetic and bit-twiddling + // operations on 64-bit registers, which is much faster than + // bytewise processing. + addr uint128 + + // z is a combination of the address family and the IPv6 zone. + // + // nil means invalid IP address (for a zero Addr). + // z4 means an IPv4 address. + // z6noz means an IPv6 address without a zone. + // + // Otherwise it's the interned zone name string. + z *intern.Value +} + +// z0, z4, and z6noz are sentinel IP.z values. +// See the IP type's field docs. +var ( + z0 = (*intern.Value)(nil) + z4 = new(intern.Value) + z6noz = new(intern.Value) +) + +// IPv6LinkLocalAllNodes returns the IPv6 link-local all nodes multicast +// address ff02::1. +func IPv6LinkLocalAllNodes() Addr { return AddrFrom16([16]byte{0: 0xff, 1: 0x02, 15: 0x01}) } + +// IPv6Unspecified returns the IPv6 unspecified address "::". +func IPv6Unspecified() Addr { return Addr{z: z6noz} } + +// AddrFrom4 returns the address of the IPv4 address given by the bytes in addr. +func AddrFrom4(addr [4]byte) Addr { + return Addr{ + addr: uint128{0, 0xffff00000000 | uint64(addr[0])<<24 | uint64(addr[1])<<16 | uint64(addr[2])<<8 | uint64(addr[3])}, + z: z4, + } +} + +// AddrFrom16 returns the IPv6 address given by the bytes in addr. +// An IPv6-mapped IPv4 address is left as an IPv6 address. +// (Use Unmap to convert them if needed.) +func AddrFrom16(addr [16]byte) Addr { + return Addr{ + addr: uint128{ + beUint64(addr[:8]), + beUint64(addr[8:]), + }, + z: z6noz, + } +} + +// ipv6Slice is like IPv6Raw, but operates on a 16-byte slice. Assumes +// slice is 16 bytes, caller must enforce this. +func ipv6Slice(addr []byte) Addr { + return Addr{ + addr: uint128{ + beUint64(addr[:8]), + beUint64(addr[8:]), + }, + z: z6noz, + } +} + +// ParseAddr parses s as an IP address, returning the result. The string +// s can be in dotted decimal ("192.0.2.1"), IPv6 ("2001:db8::68"), +// or IPv6 with a scoped addressing zone ("fe80::1cc0:3e8c:119f:c2e1%ens18"). +func ParseAddr(s string) (Addr, error) { + for i := 0; i < len(s); i++ { + switch s[i] { + case '.': + return parseIPv4(s) + case ':': + return parseIPv6(s) + case '%': + // Assume that this was trying to be an IPv6 address with + // a zone specifier, but the address is missing. + return Addr{}, parseAddrError{in: s, msg: "missing IPv6 address"} + } + } + return Addr{}, parseAddrError{in: s, msg: "unable to parse IP"} +} + +// MustParseAddr calls ParseAddr(s) and panics on error. +// It is intended for use in tests with hard-coded strings. +func MustParseAddr(s string) Addr { + ip, err := ParseAddr(s) + if err != nil { + panic(err) + } + return ip +} + +type parseAddrError struct { + in string // the string given to ParseAddr + msg string // an explanation of the parse failure + at string // optionally, the unparsed portion of in at which the error occurred. +} + +func (err parseAddrError) Error() string { + q := strconv.Quote + if err.at != "" { + return "ParseAddr(" + q(err.in) + "): " + err.msg + " (at " + q(err.at) + ")" + } + return "ParseAddr(" + q(err.in) + "): " + err.msg +} + +// parseIPv4 parses s as an IPv4 address (in form "192.168.0.1"). +func parseIPv4(s string) (ip Addr, err error) { + var fields [4]uint8 + var val, pos int + for i := 0; i < len(s); i++ { + if s[i] >= '0' && s[i] <= '9' { + val = val*10 + int(s[i]) - '0' + if val > 255 { + return Addr{}, parseAddrError{in: s, msg: "IPv4 field has value >255"} + } + } else if s[i] == '.' { + // .1.2.3 + // 1.2.3. + // 1..2.3 + if i == 0 || i == len(s)-1 || s[i-1] == '.' { + return Addr{}, parseAddrError{in: s, msg: "IPv4 field must have at least one digit", at: s[i:]} + } + // 1.2.3.4.5 + if pos == 3 { + return Addr{}, parseAddrError{in: s, msg: "IPv4 address too long"} + } + fields[pos] = uint8(val) + pos++ + val = 0 + } else { + return Addr{}, parseAddrError{in: s, msg: "unexpected character", at: s[i:]} + } + } + if pos < 3 { + return Addr{}, parseAddrError{in: s, msg: "IPv4 address too short"} + } + fields[3] = uint8(val) + return AddrFrom4(fields), nil +} + +// parseIPv6 parses s as an IPv6 address (in form "2001:db8::68"). +func parseIPv6(in string) (Addr, error) { + s := in + + // Split off the zone right from the start. Yes it's a second scan + // of the string, but trying to handle it inline makes a bunch of + // other inner loop conditionals more expensive, and it ends up + // being slower. + zone := "" + i := bytealg.IndexByteString(s, '%') + if i != -1 { + s, zone = s[:i], s[i+1:] + if zone == "" { + // Not allowed to have an empty zone if explicitly specified. + return Addr{}, parseAddrError{in: in, msg: "zone must be a non-empty string"} + } + } + + var ip [16]byte + ellipsis := -1 // position of ellipsis in ip + + // Might have leading ellipsis + if len(s) >= 2 && s[0] == ':' && s[1] == ':' { + ellipsis = 0 + s = s[2:] + // Might be only ellipsis + if len(s) == 0 { + return IPv6Unspecified().WithZone(zone), nil + } + } + + // Loop, parsing hex numbers followed by colon. + i = 0 + for i < 16 { + // Hex number. Similar to parseIPv4, inlining the hex number + // parsing yields a significant performance increase. + off := 0 + acc := uint32(0) + for ; off < len(s); off++ { + c := s[off] + if c >= '0' && c <= '9' { + acc = (acc << 4) + uint32(c-'0') + } else if c >= 'a' && c <= 'f' { + acc = (acc << 4) + uint32(c-'a'+10) + } else if c >= 'A' && c <= 'F' { + acc = (acc << 4) + uint32(c-'A'+10) + } else { + break + } + if acc > math.MaxUint16 { + // Overflow, fail. + return Addr{}, parseAddrError{in: in, msg: "IPv6 field has value >=2^16", at: s} + } + } + if off == 0 { + // No digits found, fail. + return Addr{}, parseAddrError{in: in, msg: "each colon-separated field must have at least one digit", at: s} + } + + // If followed by dot, might be in trailing IPv4. + if off < len(s) && s[off] == '.' { + if ellipsis < 0 && i != 12 { + // Not the right place. + return Addr{}, parseAddrError{in: in, msg: "embedded IPv4 address must replace the final 2 fields of the address", at: s} + } + if i+4 > 16 { + // Not enough room. + return Addr{}, parseAddrError{in: in, msg: "too many hex fields to fit an embedded IPv4 at the end of the address", at: s} + } + // TODO: could make this a bit faster by having a helper + // that parses to a [4]byte, and have both parseIPv4 and + // parseIPv6 use it. + ip4, err := parseIPv4(s) + if err != nil { + return Addr{}, parseAddrError{in: in, msg: err.Error(), at: s} + } + ip[i] = ip4.v4(0) + ip[i+1] = ip4.v4(1) + ip[i+2] = ip4.v4(2) + ip[i+3] = ip4.v4(3) + s = "" + i += 4 + break + } + + // Save this 16-bit chunk. + ip[i] = byte(acc >> 8) + ip[i+1] = byte(acc) + i += 2 + + // Stop at end of string. + s = s[off:] + if len(s) == 0 { + break + } + + // Otherwise must be followed by colon and more. + if s[0] != ':' { + return Addr{}, parseAddrError{in: in, msg: "unexpected character, want colon", at: s} + } else if len(s) == 1 { + return Addr{}, parseAddrError{in: in, msg: "colon must be followed by more characters", at: s} + } + s = s[1:] + + // Look for ellipsis. + if s[0] == ':' { + if ellipsis >= 0 { // already have one + return Addr{}, parseAddrError{in: in, msg: "multiple :: in address", at: s} + } + ellipsis = i + s = s[1:] + if len(s) == 0 { // can be at end + break + } + } + } + + // Must have used entire string. + if len(s) != 0 { + return Addr{}, parseAddrError{in: in, msg: "trailing garbage after address", at: s} + } + + // If didn't parse enough, expand ellipsis. + if i < 16 { + if ellipsis < 0 { + return Addr{}, parseAddrError{in: in, msg: "address string too short"} + } + n := 16 - i + for j := i - 1; j >= ellipsis; j-- { + ip[j+n] = ip[j] + } + for j := ellipsis + n - 1; j >= ellipsis; j-- { + ip[j] = 0 + } + } else if ellipsis >= 0 { + // Ellipsis must represent at least one 0 group. + return Addr{}, parseAddrError{in: in, msg: "the :: must expand to at least one field of zeros"} + } + return AddrFrom16(ip).WithZone(zone), nil +} + +// AddrFromSlice parses the 4- or 16-byte byte slice as an IPv4 or IPv6 address. +// Note that a net.IP can be passed directly as the []byte argument. +// If slice's length is not 4 or 16, AddrFromSlice returns Addr{}, false. +func AddrFromSlice(slice []byte) (ip Addr, ok bool) { + switch len(slice) { + case 4: + return AddrFrom4(*(*[4]byte)(slice)), true + case 16: + return ipv6Slice(slice), true + } + return Addr{}, false +} + +// v4 returns the i'th byte of ip. If ip is not an IPv4, v4 returns +// unspecified garbage. +func (ip Addr) v4(i uint8) uint8 { + return uint8(ip.addr.lo >> ((3 - i) * 8)) +} + +// v6 returns the i'th byte of ip. If ip is an IPv4 address, this +// accesses the IPv4-mapped IPv6 address form of the IP. +func (ip Addr) v6(i uint8) uint8 { + return uint8(*(ip.addr.halves()[(i/8)%2]) >> ((7 - i%8) * 8)) +} + +// v6u16 returns the i'th 16-bit word of ip. If ip is an IPv4 address, +// this accesses the IPv4-mapped IPv6 address form of the IP. +func (ip Addr) v6u16(i uint8) uint16 { + return uint16(*(ip.addr.halves()[(i/4)%2]) >> ((3 - i%4) * 16)) +} + +// isZero reports whether ip is the zero value of the IP type. +// The zero value is not a valid IP address of any type. +// +// Note that "0.0.0.0" and "::" are not the zero value. Use IsUnspecified to +// check for these values instead. +func (ip Addr) isZero() bool { + // Faster than comparing ip == Addr{}, but effectively equivalent, + // as there's no way to make an IP with a nil z from this package. + return ip.z == z0 +} + +// IsValid reports whether the Addr is an initialized address (not the zero Addr). +// +// Note that "0.0.0.0" and "::" are both valid values. +func (ip Addr) IsValid() bool { return ip.z != z0 } + +// BitLen returns the number of bits in the IP address: +// 128 for IPv6, 32 for IPv4, and 0 for the zero Addr. +// +// Note that IPv4-mapped IPv6 addresses are considered IPv6 addresses +// and therefore have bit length 128. +func (ip Addr) BitLen() int { + switch ip.z { + case z0: + return 0 + case z4: + return 32 + } + return 128 +} + +// Zone returns ip's IPv6 scoped addressing zone, if any. +func (ip Addr) Zone() string { + if ip.z == nil { + return "" + } + zone, _ := ip.z.Get().(string) + return zone +} + +// Compare returns an integer comparing two IPs. +// The result will be 0 if ip == ip2, -1 if ip < ip2, and +1 if ip > ip2. +// The definition of "less than" is the same as the Less method. +func (ip Addr) Compare(ip2 Addr) int { + f1, f2 := ip.BitLen(), ip2.BitLen() + if f1 < f2 { + return -1 + } + if f1 > f2 { + return 1 + } + hi1, hi2 := ip.addr.hi, ip2.addr.hi + if hi1 < hi2 { + return -1 + } + if hi1 > hi2 { + return 1 + } + lo1, lo2 := ip.addr.lo, ip2.addr.lo + if lo1 < lo2 { + return -1 + } + if lo1 > lo2 { + return 1 + } + if ip.Is6() { + za, zb := ip.Zone(), ip2.Zone() + if za < zb { + return -1 + } + if za > zb { + return 1 + } + } + return 0 +} + +// Less reports whether ip sorts before ip2. +// IP addresses sort first by length, then their address. +// IPv6 addresses with zones sort just after the same address without a zone. +func (ip Addr) Less(ip2 Addr) bool { return ip.Compare(ip2) == -1 } + +func (ip Addr) lessOrEq(ip2 Addr) bool { return ip.Compare(ip2) <= 0 } + +// ipZone returns the standard library net.IP from ip, as well +// as the zone. +// The optional reuse IP provides memory to reuse. +func (ip Addr) ipZone(reuse []byte) (stdIP []byte, zone string) { + base := reuse[:0] + switch { + case ip.z == z0: + return nil, "" + case ip.Is4(): + a4 := ip.As4() + return append(base, a4[:]...), "" + default: + a16 := ip.As16() + return append(base, a16[:]...), ip.Zone() + } +} + +// IPAddrParts returns the net.IPAddr representation of an Addr. +// +// The slice will be nil if ip is the zero Addr. +// The zone is the empty string if there is no zone. +func (ip Addr) IPAddrParts() (slice []byte, zone string) { + return ip.ipZone(nil) +} + +// Is4 reports whether ip is an IPv4 address. +// +// It returns false for IP4-mapped IPv6 addresses. See IP.Unmap. +func (ip Addr) Is4() bool { + return ip.z == z4 +} + +// Is4In6 reports whether ip is an IPv4-mapped IPv6 address. +func (ip Addr) Is4In6() bool { + return ip.Is6() && ip.addr.hi == 0 && ip.addr.lo>>32 == 0xffff +} + +// Is6 reports whether ip is an IPv6 address, including IPv4-mapped +// IPv6 addresses. +func (ip Addr) Is6() bool { + return ip.z != z0 && ip.z != z4 +} + +// Unmap returns ip with any IPv4-mapped IPv6 address prefix removed. +// +// That is, if ip is an IPv6 address wrapping an IPv4 adddress, it +// returns the wrapped IPv4 address. Otherwise it returns ip unmodified. +func (ip Addr) Unmap() Addr { + if ip.Is4In6() { + ip.z = z4 + } + return ip +} + +// WithZone returns an IP that's the same as ip but with the provided +// zone. If zone is empty, the zone is removed. If ip is an IPv4 +// address, WithZone is a no-op and returns ip unchanged. +func (ip Addr) WithZone(zone string) Addr { + if !ip.Is6() { + return ip + } + if zone == "" { + ip.z = z6noz + return ip + } + ip.z = intern.GetByString(zone) + return ip +} + +// withoutZone unconditionally strips the zone from IP. +// It's similar to WithZone, but small enough to be inlinable. +func (ip Addr) withoutZone() Addr { + if !ip.Is6() { + return ip + } + ip.z = z6noz + return ip +} + +// hasZone reports whether IP has an IPv6 zone. +func (ip Addr) hasZone() bool { + return ip.z != z0 && ip.z != z4 && ip.z != z6noz +} + +// IsLinkLocalUnicast reports whether ip is a link-local unicast address. +func (ip Addr) IsLinkLocalUnicast() bool { + // Dynamic Configuration of IPv4 Link-Local Addresses + // https://datatracker.ietf.org/doc/html/rfc3927#section-2.1 + if ip.Is4() { + return ip.v4(0) == 169 && ip.v4(1) == 254 + } + // IP Version 6 Addressing Architecture (2.4 Address Type Identification) + // https://datatracker.ietf.org/doc/html/rfc4291#section-2.4 + if ip.Is6() { + return ip.v6u16(0)&0xffc0 == 0xfe80 + } + return false // zero value +} + +// IsLoopback reports whether ip is a loopback address. +func (ip Addr) IsLoopback() bool { + // Requirements for Internet Hosts -- Communication Layers (3.2.1.3 Addressing) + // https://datatracker.ietf.org/doc/html/rfc1122#section-3.2.1.3 + if ip.Is4() { + return ip.v4(0) == 127 + } + // IP Version 6 Addressing Architecture (2.4 Address Type Identification) + // https://datatracker.ietf.org/doc/html/rfc4291#section-2.4 + if ip.Is6() { + return ip.addr.hi == 0 && ip.addr.lo == 1 + } + return false // zero value +} + +// IsMulticast reports whether ip is a multicast address. +func (ip Addr) IsMulticast() bool { + // Host Extensions for IP Multicasting (4. HOST GROUP ADDRESSES) + // https://datatracker.ietf.org/doc/html/rfc1112#section-4 + if ip.Is4() { + return ip.v4(0)&0xf0 == 0xe0 + } + // IP Version 6 Addressing Architecture (2.4 Address Type Identification) + // https://datatracker.ietf.org/doc/html/rfc4291#section-2.4 + if ip.Is6() { + return ip.addr.hi>>(64-8) == 0xff // ip.v6(0) == 0xff + } + return false // zero value +} + +// IsInterfaceLocalMulticast reports whether ip is an IPv6 interface-local +// multicast address. +func (ip Addr) IsInterfaceLocalMulticast() bool { + // IPv6 Addressing Architecture (2.7.1. Pre-Defined Multicast Addresses) + // https://datatracker.ietf.org/doc/html/rfc4291#section-2.7.1 + if ip.Is6() { + return ip.v6u16(0)&0xff0f == 0xff01 + } + return false // zero value +} + +// IsLinkLocalMulticast reports whether ip is a link-local multicast address. +func (ip Addr) IsLinkLocalMulticast() bool { + // IPv4 Multicast Guidelines (4. Local Network Control Block (224.0.0/24)) + // https://datatracker.ietf.org/doc/html/rfc5771#section-4 + if ip.Is4() { + return ip.v4(0) == 224 && ip.v4(1) == 0 && ip.v4(2) == 0 + } + // IPv6 Addressing Architecture (2.7.1. Pre-Defined Multicast Addresses) + // https://datatracker.ietf.org/doc/html/rfc4291#section-2.7.1 + if ip.Is6() { + return ip.v6u16(0)&0xff0f == 0xff02 + } + return false // zero value +} + +// IsGlobalUnicast reports whether ip is a global unicast address. +// +// It returns true for IPv6 addresses which fall outside of the current +// IANA-allocated 2000::/3 global unicast space, with the exception of the +// link-local address space. It also returns true even if ip is in the IPv4 +// private address space or IPv6 unique local address space. +// It returns false for the zero Addr. +// +// For reference, see RFC 1122, RFC 4291, and RFC 4632. +func (ip Addr) IsGlobalUnicast() bool { + if ip.z == z0 { + // Invalid or zero-value. + return false + } + + // Match package net's IsGlobalUnicast logic. Notably private IPv4 addresses + // and ULA IPv6 addresses are still considered "global unicast". + if ip.Is4() && (ip == AddrFrom4([4]byte{}) || ip == AddrFrom4([4]byte{255, 255, 255, 255})) { + return false + } + + return ip != IPv6Unspecified() && + !ip.IsLoopback() && + !ip.IsMulticast() && + !ip.IsLinkLocalUnicast() +} + +// IsPrivate reports whether ip is a private address, according to RFC 1918 +// (IPv4 addresses) and RFC 4193 (IPv6 addresses). That is, it reports whether +// ip is in 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, or fc00::/7. This is the +// same as net.IP.IsPrivate. +func (ip Addr) IsPrivate() bool { + // Match the stdlib's IsPrivate logic. + if ip.Is4() { + // RFC 1918 allocates 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16 as + // private IPv4 address subnets. + return ip.v4(0) == 10 || + (ip.v4(0) == 172 && ip.v4(1)&0xf0 == 16) || + (ip.v4(0) == 192 && ip.v4(1) == 168) + } + + if ip.Is6() { + // RFC 4193 allocates fc00::/7 as the unique local unicast IPv6 address + // subnet. + return ip.v6(0)&0xfe == 0xfc + } + + return false // zero value +} + +// IsUnspecified reports whether ip is an unspecified address, either the IPv4 +// address "0.0.0.0" or the IPv6 address "::". +// +// Note that the zero Addr is not an unspecified address. +func (ip Addr) IsUnspecified() bool { + return ip == AddrFrom4([4]byte{}) || ip == IPv6Unspecified() +} + +// Prefix keeps only the top b bits of IP, producing a Prefix +// of the specified length. +// If ip is a zero Addr, Prefix always returns a zero Prefix and a nil error. +// Otherwise, if bits is less than zero or greater than ip.BitLen(), +// Prefix returns an error. +func (ip Addr) Prefix(b int) (Prefix, error) { + if b < 0 { + return Prefix{}, errors.New("negative Prefix bits") + } + effectiveBits := b + switch ip.z { + case z0: + return Prefix{}, nil + case z4: + if b > 32 { + return Prefix{}, errors.New("prefix length " + itoa.Itoa(b) + " too large for IPv4") + } + effectiveBits += 96 + default: + if b > 128 { + return Prefix{}, errors.New("prefix length " + itoa.Itoa(b) + " too large for IPv6") + } + } + ip.addr = ip.addr.and(mask6(effectiveBits)) + return PrefixFrom(ip, b), nil +} + +const ( + netIPv4len = 4 + netIPv6len = 16 +) + +// As16 returns the IP address in its 16-byte representation. +// IPv4 addresses are returned in their v6-mapped form. +// IPv6 addresses with zones are returned without their zone (use the +// Zone method to get it). +// The ip zero value returns all zeroes. +func (ip Addr) As16() [16]byte { + var ret [16]byte + bePutUint64(ret[:8], ip.addr.hi) + bePutUint64(ret[8:], ip.addr.lo) + return ret +} + +// As4 returns an IPv4 or IPv4-in-IPv6 address in its 4-byte representation. +// If ip is the zero Addr or an IPv6 address, As4 panics. +// Note that 0.0.0.0 is not the zero Addr. +func (ip Addr) As4() [4]byte { + if ip.z == z4 || ip.Is4In6() { + var ret [4]byte + bePutUint32(ret[:], uint32(ip.addr.lo)) + return ret + } + if ip.z == z0 { + panic("As4 called on IP zero value") + } + panic("As4 called on IPv6 address") +} + +// Next returns the address following ip. +// If there is none, it returns the zero Addr. +func (ip Addr) Next() Addr { + ip.addr = ip.addr.addOne() + if ip.Is4() { + if uint32(ip.addr.lo) == 0 { + // Overflowed. + return Addr{} + } + } else { + if ip.addr.isZero() { + // Overflowed + return Addr{} + } + } + return ip +} + +// Prev returns the IP before ip. +// If there is none, it returns the IP zero value. +func (ip Addr) Prev() Addr { + if ip.Is4() { + if uint32(ip.addr.lo) == 0 { + return Addr{} + } + } else if ip.addr.isZero() { + return Addr{} + } + ip.addr = ip.addr.subOne() + return ip +} + +// String returns the string form of the IP address ip. +// It returns one of 5 forms: +// +// - "invalid IP", if ip is the zero Addr +// - IPv4 dotted decimal ("192.0.2.1") +// - IPv6 ("2001:db8::1") +// - "::ffff:1.2.3.4" (if Is4In6) +// - IPv6 with zone ("fe80:db8::1%eth0") +// +// Note that unlike package net's IP.String method, +// IP4-mapped IPv6 addresses format with a "::ffff:" +// prefix before the dotted quad. +func (ip Addr) String() string { + switch ip.z { + case z0: + return "invalid IP" + case z4: + return ip.string4() + default: + if ip.Is4In6() { + // TODO(bradfitz): this could alloc less. + return "::ffff:" + ip.Unmap().String() + } + return ip.string6() + } +} + +// AppendTo appends a text encoding of ip, +// as generated by MarshalText, +// to b and returns the extended buffer. +func (ip Addr) AppendTo(b []byte) []byte { + switch ip.z { + case z0: + return b + case z4: + return ip.appendTo4(b) + default: + if ip.Is4In6() { + b = append(b, "::ffff:"...) + return ip.Unmap().appendTo4(b) + } + return ip.appendTo6(b) + } +} + +// digits is a string of the hex digits from 0 to f. It's used in +// appendDecimal and appendHex to format IP addresses. +const digits = "0123456789abcdef" + +// appendDecimal appends the decimal string representation of x to b. +func appendDecimal(b []byte, x uint8) []byte { + // Using this function rather than strconv.AppendUint makes IPv4 + // string building 2x faster. + + if x >= 100 { + b = append(b, digits[x/100]) + } + if x >= 10 { + b = append(b, digits[x/10%10]) + } + return append(b, digits[x%10]) +} + +// appendHex appends the hex string representation of x to b. +func appendHex(b []byte, x uint16) []byte { + // Using this function rather than strconv.AppendUint makes IPv6 + // string building 2x faster. + + if x >= 0x1000 { + b = append(b, digits[x>>12]) + } + if x >= 0x100 { + b = append(b, digits[x>>8&0xf]) + } + if x >= 0x10 { + b = append(b, digits[x>>4&0xf]) + } + return append(b, digits[x&0xf]) +} + +// appendHexPad appends the fully padded hex string representation of x to b. +func appendHexPad(b []byte, x uint16) []byte { + return append(b, digits[x>>12], digits[x>>8&0xf], digits[x>>4&0xf], digits[x&0xf]) +} + +func (ip Addr) string4() string { + const max = len("255.255.255.255") + ret := make([]byte, 0, max) + ret = ip.appendTo4(ret) + return string(ret) +} + +func (ip Addr) appendTo4(ret []byte) []byte { + ret = appendDecimal(ret, ip.v4(0)) + ret = append(ret, '.') + ret = appendDecimal(ret, ip.v4(1)) + ret = append(ret, '.') + ret = appendDecimal(ret, ip.v4(2)) + ret = append(ret, '.') + ret = appendDecimal(ret, ip.v4(3)) + return ret +} + +// string6 formats ip in IPv6 textual representation. It follows the +// guidelines in section 4 of RFC 5952 +// (https://tools.ietf.org/html/rfc5952#section-4): no unnecessary +// zeros, use :: to elide the longest run of zeros, and don't use :: +// to compact a single zero field. +func (ip Addr) string6() string { + // Use a zone with a "plausibly long" name, so that most zone-ful + // IP addresses won't require additional allocation. + // + // The compiler does a cool optimization here, where ret ends up + // stack-allocated and so the only allocation this function does + // is to construct the returned string. As such, it's okay to be a + // bit greedy here, size-wise. + const max = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0") + ret := make([]byte, 0, max) + ret = ip.appendTo6(ret) + return string(ret) +} + +func (ip Addr) appendTo6(ret []byte) []byte { + zeroStart, zeroEnd := uint8(255), uint8(255) + for i := uint8(0); i < 8; i++ { + j := i + for j < 8 && ip.v6u16(j) == 0 { + j++ + } + if l := j - i; l >= 2 && l > zeroEnd-zeroStart { + zeroStart, zeroEnd = i, j + } + } + + for i := uint8(0); i < 8; i++ { + if i == zeroStart { + ret = append(ret, ':', ':') + i = zeroEnd + if i >= 8 { + break + } + } else if i > 0 { + ret = append(ret, ':') + } + + ret = appendHex(ret, ip.v6u16(i)) + } + + if ip.z != z6noz { + ret = append(ret, '%') + ret = append(ret, ip.Zone()...) + } + return ret +} + +// StringExpanded is like String but IPv6 addresses are expanded with leading +// zeroes and no "::" compression. For example, "2001:db8::1" becomes +// "2001:0db8:0000:0000:0000:0000:0000:0001". +func (ip Addr) StringExpanded() string { + switch ip.z { + case z0, z4: + return ip.String() + } + + const size = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff") + ret := make([]byte, 0, size) + for i := uint8(0); i < 8; i++ { + if i > 0 { + ret = append(ret, ':') + } + + ret = appendHexPad(ret, ip.v6u16(i)) + } + + if ip.z != z6noz { + // The addition of a zone will cause a second allocation, but when there + // is no zone the ret slice will be stack allocated. + ret = append(ret, '%') + ret = append(ret, ip.Zone()...) + } + return string(ret) +} + +// MarshalText implements the encoding.TextMarshaler interface, +// The encoding is the same as returned by String, with one exception: +// If ip is the zero Addr, the encoding is the empty string. +func (ip Addr) MarshalText() ([]byte, error) { + switch ip.z { + case z0: + return []byte(""), nil + case z4: + max := len("255.255.255.255") + b := make([]byte, 0, max) + return ip.appendTo4(b), nil + default: + max := len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0") + b := make([]byte, 0, max) + if ip.Is4In6() { + b = append(b, "::ffff:"...) + return ip.Unmap().appendTo4(b), nil + } + return ip.appendTo6(b), nil + } +} + +// UnmarshalText implements the encoding.TextUnmarshaler interface. +// The IP address is expected in a form accepted by ParseAddr. +// +// If text is empty, UnmarshalText sets *ip to the zero Addr and +// returns no error. +func (ip *Addr) UnmarshalText(text []byte) error { + if len(text) == 0 { + *ip = Addr{} + return nil + } + var err error + *ip, err = ParseAddr(string(text)) + return err +} + +// MarshalBinary implements the encoding.BinaryMarshaler interface. +// It returns a zero-length slice for the zero Addr, +// the 4-byte form for an IPv4 address, +// and the 16-byte form with zone appended for an IPv6 address. +func (ip Addr) MarshalBinary() ([]byte, error) { + switch ip.z { + case z0: + return nil, nil + case z4: + b := ip.As4() + return b[:], nil + default: + b16 := ip.As16() + b := b16[:] + if z := ip.Zone(); z != "" { + b = append(b, []byte(z)...) + } + return b, nil + } +} + +// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. +// It expects data in the form generated by MarshalBinary. +func (ip *Addr) UnmarshalBinary(b []byte) error { + n := len(b) + switch { + case n == 0: + *ip = Addr{} + return nil + case n == 4: + *ip = AddrFrom4(*(*[4]byte)(b)) + return nil + case n == 16: + *ip = ipv6Slice(b) + return nil + case n > 16: + *ip = ipv6Slice(b[:16]).WithZone(string(b[16:])) + return nil + } + return errors.New("unexpected slice size") +} + +// AddrPort is an IP and a port number. +type AddrPort struct { + ip Addr + port uint16 +} + +// AddrPortFrom returns an AddrPort with the provided IP and port. +// It does not allocate. +func AddrPortFrom(ip Addr, port uint16) AddrPort { return AddrPort{ip: ip, port: port} } + +// Addr returns p's IP address. +func (p AddrPort) Addr() Addr { return p.ip } + +// Port returns p's port. +func (p AddrPort) Port() uint16 { return p.port } + +// splitAddrPort splits s into an IP address string and a port +// string. It splits strings shaped like "foo:bar" or "[foo]:bar", +// without further validating the substrings. v6 indicates whether the +// ip string should parse as an IPv6 address or an IPv4 address, in +// order for s to be a valid ip:port string. +func splitAddrPort(s string) (ip, port string, v6 bool, err error) { + i := stringsLastIndexByte(s, ':') + if i == -1 { + return "", "", false, errors.New("not an ip:port") + } + + ip, port = s[:i], s[i+1:] + if len(ip) == 0 { + return "", "", false, errors.New("no IP") + } + if len(port) == 0 { + return "", "", false, errors.New("no port") + } + if ip[0] == '[' { + if len(ip) < 2 || ip[len(ip)-1] != ']' { + return "", "", false, errors.New("missing ]") + } + ip = ip[1 : len(ip)-1] + v6 = true + } + + return ip, port, v6, nil +} + +// ParseAddrPort parses s as an AddrPort. +// +// It doesn't do any name resolution: both the address and the port +// must be numeric. +func ParseAddrPort(s string) (AddrPort, error) { + var ipp AddrPort + ip, port, v6, err := splitAddrPort(s) + if err != nil { + return ipp, err + } + port16, err := strconv.ParseUint(port, 10, 16) + if err != nil { + return ipp, errors.New("invalid port " + strconv.Quote(port) + " parsing " + strconv.Quote(s)) + } + ipp.port = uint16(port16) + ipp.ip, err = ParseAddr(ip) + if err != nil { + return AddrPort{}, err + } + if v6 && ipp.ip.Is4() { + return AddrPort{}, errors.New("invalid ip:port " + strconv.Quote(s) + ", square brackets can only be used with IPv6 addresses") + } else if !v6 && ipp.ip.Is6() { + return AddrPort{}, errors.New("invalid ip:port " + strconv.Quote(s) + ", IPv6 addresses must be surrounded by square brackets") + } + return ipp, nil +} + +// MustParseAddrPort calls ParseAddrPort(s) and panics on error. +// It is intended for use in tests with hard-coded strings. +func MustParseAddrPort(s string) AddrPort { + ip, err := ParseAddrPort(s) + if err != nil { + panic(err) + } + return ip +} + +// isZero reports whether p is the zero AddrPort. +func (p AddrPort) isZero() bool { return p == AddrPort{} } + +// IsValid reports whether p.IP() is valid. +// All ports are valid, including zero. +func (p AddrPort) IsValid() bool { return p.ip.IsValid() } + +func (p AddrPort) String() string { + switch p.ip.z { + case z0: + return "invalid AddrPort" + case z4: + a := p.ip.As4() + buf := make([]byte, 0, 21) + for i := range a { + buf = strconv.AppendUint(buf, uint64(a[i]), 10) + buf = append(buf, "...:"[i]) + } + buf = strconv.AppendUint(buf, uint64(p.port), 10) + return string(buf) + default: + // TODO: this could be more efficient allocation-wise: + return joinHostPort(p.ip.String(), itoa.Itoa(int(p.port))) + } +} + +func joinHostPort(host, port string) string { + // We assume that host is a literal IPv6 address if host has + // colons. + if bytealg.IndexByteString(host, ':') >= 0 { + return "[" + host + "]:" + port + } + return host + ":" + port +} + +// AppendTo appends a text encoding of p, +// as generated by MarshalText, +// to b and returns the extended buffer. +func (p AddrPort) AppendTo(b []byte) []byte { + switch p.ip.z { + case z0: + return b + case z4: + b = p.ip.appendTo4(b) + default: + b = append(b, '[') + b = p.ip.appendTo6(b) + b = append(b, ']') + } + b = append(b, ':') + b = strconv.AppendInt(b, int64(p.port), 10) + return b +} + +// MarshalText implements the encoding.TextMarshaler interface. The +// encoding is the same as returned by String, with one exception: if +// p.Addr() is the zero Addr, the encoding is the empty string. +func (p AddrPort) MarshalText() ([]byte, error) { + var max int + switch p.ip.z { + case z0: + case z4: + max = len("255.255.255.255:65535") + default: + max = len("[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0]:65535") + } + b := make([]byte, 0, max) + b = p.AppendTo(b) + return b, nil +} + +// UnmarshalText implements the encoding.TextUnmarshaler +// interface. The AddrPort is expected in a form +// generated by MarshalText or accepted by ParseAddrPort. +func (p *AddrPort) UnmarshalText(text []byte) error { + if len(text) == 0 { + *p = AddrPort{} + return nil + } + var err error + *p, err = ParseAddrPort(string(text)) + return err +} + +// Prefix is an IP address prefix (CIDR) representing an IP network. +// +// The first Bits() of Addr() are specified. The remaining bits match any address. +// The range of Bits() is [0,32] for IPv4 or [0,128] for IPv6. +type Prefix struct { + ip Addr + + // bits is logically a uint8 (storing [0,128]) but also + // encodes an "invalid" bit, currently represented by the + // invalidPrefixBits sentinel value. It could be packed into + // the uint8 more with more comlicated expressions in the + // accessors, but the extra byte (in padding anyway) doesn't + // hurt and simplifies code below. + bits int16 +} + +// invalidPrefixBits is the Prefix.bits value used when PrefixFrom is +// outside the range of a uint8. It's returned as the int -1 in the +// public API. +const invalidPrefixBits = -1 + +// PrefixFrom returns an Prefix with the provided IP address and bit +// prefix length. +// +// It does not allocate. Unlike Addr.Prefix, PrefixFrom does not mask +// off the host bits of ip. +// +// If bits is less than zero or greater than ip.BitLen, Prefix.Bits +// will return an invalid value -1. +func PrefixFrom(ip Addr, bits int) Prefix { + if bits < 0 || bits > ip.BitLen() { + bits = invalidPrefixBits + } + b16 := int16(bits) + return Prefix{ + ip: ip.withoutZone(), + bits: b16, + } +} + +// Addr returns p's IP address. +func (p Prefix) Addr() Addr { return p.ip } + +// Bits returns p's prefix length. +// +// It reports -1 if invalid. +func (p Prefix) Bits() int { return int(p.bits) } + +// IsValid reports whether whether p.Bits() has a valid range for p.IP(). +// If p.Addr() is the zero Addr, IsValid returns false. +// Note that if p is the zero Prefix, then p.IsValid() == false. +func (p Prefix) IsValid() bool { return !p.ip.isZero() && p.bits >= 0 && int(p.bits) <= p.ip.BitLen() } + +func (p Prefix) isZero() bool { return p == Prefix{} } + +// IsSingleIP reports whether p contains exactly one IP. +func (p Prefix) IsSingleIP() bool { return p.bits != 0 && int(p.bits) == p.ip.BitLen() } + +// ParsePrefix parses s as an IP address prefix. +// The string can be in the form "192.168.1.0/24" or "2001::db8::/32", +// the CIDR notation defined in RFC 4632 and RFC 4291. +// +// Note that masked address bits are not zeroed. Use Masked for that. +func ParsePrefix(s string) (Prefix, error) { + i := stringsLastIndexByte(s, '/') + if i < 0 { + return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): no '/'") + } + ip, err := ParseAddr(s[:i]) + if err != nil { + return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): " + err.Error()) + } + bitsStr := s[i+1:] + bits, err := strconv.Atoi(bitsStr) + if err != nil { + return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + ": bad bits after slash: " + strconv.Quote(bitsStr)) + } + maxBits := 32 + if ip.Is6() { + maxBits = 128 + } + if bits < 0 || bits > maxBits { + return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + ": prefix length out of range") + } + return PrefixFrom(ip, bits), nil +} + +// MustParsePrefix calls ParsePrefix(s) and panics on error. +// It is intended for use in tests with hard-coded strings. +func MustParsePrefix(s string) Prefix { + ip, err := ParsePrefix(s) + if err != nil { + panic(err) + } + return ip +} + +// Masked returns p in its canonical form, with all but the high +// p.Bits() bits of p.Addr() masked off. +// +// If p is zero or otherwise invalid, Masked returns the zero Prefix. +func (p Prefix) Masked() Prefix { + if m, err := p.ip.Prefix(int(p.bits)); err == nil { + return m + } + return Prefix{} +} + +// Contains reports whether the network p includes ip. +// +// An IPv4 address will not match an IPv6 prefix. +// A v6-mapped IPv6 address will not match an IPv4 prefix. +// A zero-value IP will not match any prefix. +// If ip has an IPv6 zone, Contains returns false, +// because Prefixes strip zones. +func (p Prefix) Contains(ip Addr) bool { + if !p.IsValid() || ip.hasZone() { + return false + } + if f1, f2 := p.ip.BitLen(), ip.BitLen(); f1 == 0 || f2 == 0 || f1 != f2 { + return false + } + if ip.Is4() { + // xor the IP addresses together; mismatched bits are now ones. + // Shift away the number of bits we don't care about. + // Shifts in Go are more efficient if the compiler can prove + // that the shift amount is smaller than the width of the shifted type (64 here). + // We know that p.bits is in the range 0..32 because p is Valid; + // the compiler doesn't know that, so mask with 63 to help it. + // Now truncate to 32 bits, because this is IPv4. + // If all the bits we care about are equal, the result will be zero. + return uint32((ip.addr.lo^p.ip.addr.lo)>>((32-p.bits)&63)) == 0 + } else { + // xor the IP addresses together. + // Mask away the bits we don't care about. + // If all the bits we care about are equal, the result will be zero. + return ip.addr.xor(p.ip.addr).and(mask6(int(p.bits))).isZero() + } +} + +// Overlaps reports whether p and o contain any IP addresses in common. +// +// If p and o are of different address families or either have a zero +// IP, it reports false. Like the Contains method, a prefix with a +// v6-mapped IPv4 IP is still treated as an IPv6 mask. +func (p Prefix) Overlaps(o Prefix) bool { + if !p.IsValid() || !o.IsValid() { + return false + } + if p == o { + return true + } + if p.ip.Is4() != o.ip.Is4() { + return false + } + var minBits int16 + if p.bits < o.bits { + minBits = p.bits + } else { + minBits = o.bits + } + if minBits == 0 { + return true + } + // One of these Prefix calls might look redundant, but we don't require + // that p and o values are normalized (via Prefix.Masked) first, + // so the Prefix call on the one that's already minBits serves to zero + // out any remaining bits in IP. + var err error + if p, err = p.ip.Prefix(int(minBits)); err != nil { + return false + } + if o, err = o.ip.Prefix(int(minBits)); err != nil { + return false + } + return p.ip == o.ip +} + +// AppendTo appends a text encoding of p, +// as generated by MarshalText, +// to b and returns the extended buffer. +func (p Prefix) AppendTo(b []byte) []byte { + if p.isZero() { + return b + } + if !p.IsValid() { + return append(b, "invalid Prefix"...) + } + + // p.ip is non-nil, because p is valid. + if p.ip.z == z4 { + b = p.ip.appendTo4(b) + } else { + b = p.ip.appendTo6(b) + } + + b = append(b, '/') + b = appendDecimal(b, uint8(p.bits)) + return b +} + +// MarshalText implements the encoding.TextMarshaler interface, +// The encoding is the same as returned by String, with one exception: +// If p is the zero value, the encoding is the empty string. +func (p Prefix) MarshalText() ([]byte, error) { + var max int + switch p.ip.z { + case z0: + case z4: + max = len("255.255.255.255/32") + default: + max = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0/128") + } + b := make([]byte, 0, max) + b = p.AppendTo(b) + return b, nil +} + +// UnmarshalText implements the encoding.TextUnmarshaler interface. +// The IP address is expected in a form accepted by ParsePrefix +// or generated by MarshalText. +func (p *Prefix) UnmarshalText(text []byte) error { + if len(text) == 0 { + *p = Prefix{} + return nil + } + var err error + *p, err = ParsePrefix(string(text)) + return err +} + +// String returns the CIDR notation of p: "/". +func (p Prefix) String() string { + if !p.IsValid() { + return "invalid Prefix" + } + return p.ip.String() + "/" + itoa.Itoa(int(p.bits)) +} diff --git a/src/net/netip/netip_pkg_test.go b/src/net/netip/netip_pkg_test.go new file mode 100644 index 0000000000..f5cd9ee86d --- /dev/null +++ b/src/net/netip/netip_pkg_test.go @@ -0,0 +1,359 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package netip + +import ( + "bytes" + "encoding" + "encoding/json" + "strings" + "testing" +) + +var ( + mustPrefix = MustParsePrefix + mustIP = MustParseAddr +) + +func TestPrefixValid(t *testing.T) { + v4 := MustParseAddr("1.2.3.4") + v6 := MustParseAddr("::1") + tests := []struct { + ipp Prefix + want bool + }{ + {Prefix{v4, -2}, false}, + {Prefix{v4, -1}, false}, + {Prefix{v4, 0}, true}, + {Prefix{v4, 32}, true}, + {Prefix{v4, 33}, false}, + + {Prefix{v6, -2}, false}, + {Prefix{v6, -1}, false}, + {Prefix{v6, 0}, true}, + {Prefix{v6, 32}, true}, + {Prefix{v6, 128}, true}, + {Prefix{v6, 129}, false}, + + {Prefix{Addr{}, -2}, false}, + {Prefix{Addr{}, -1}, false}, + {Prefix{Addr{}, 0}, false}, + {Prefix{Addr{}, 32}, false}, + {Prefix{Addr{}, 128}, false}, + } + for _, tt := range tests { + got := tt.ipp.IsValid() + if got != tt.want { + t.Errorf("(%v).IsValid() = %v want %v", tt.ipp, got, tt.want) + } + } +} + +var nextPrevTests = []struct { + ip Addr + next Addr + prev Addr +}{ + {mustIP("10.0.0.1"), mustIP("10.0.0.2"), mustIP("10.0.0.0")}, + {mustIP("10.0.0.255"), mustIP("10.0.1.0"), mustIP("10.0.0.254")}, + {mustIP("127.0.0.1"), mustIP("127.0.0.2"), mustIP("127.0.0.0")}, + {mustIP("254.255.255.255"), mustIP("255.0.0.0"), mustIP("254.255.255.254")}, + {mustIP("255.255.255.255"), Addr{}, mustIP("255.255.255.254")}, + {mustIP("0.0.0.0"), mustIP("0.0.0.1"), Addr{}}, + {mustIP("::"), mustIP("::1"), Addr{}}, + {mustIP("::%x"), mustIP("::1%x"), Addr{}}, + {mustIP("::1"), mustIP("::2"), mustIP("::")}, + {mustIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"), Addr{}, mustIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe")}, +} + +func TestIPNextPrev(t *testing.T) { + doNextPrev(t) + + for _, ip := range []Addr{ + mustIP("0.0.0.0"), + mustIP("::"), + } { + got := ip.Prev() + if !got.isZero() { + t.Errorf("IP(%v).Prev = %v; want zero", ip, got) + } + } + + var allFF [16]byte + for i := range allFF { + allFF[i] = 0xff + } + + for _, ip := range []Addr{ + mustIP("255.255.255.255"), + AddrFrom16(allFF), + } { + got := ip.Next() + if !got.isZero() { + t.Errorf("IP(%v).Next = %v; want zero", ip, got) + } + } +} + +func BenchmarkIPNextPrev(b *testing.B) { + for i := 0; i < b.N; i++ { + doNextPrev(b) + } +} + +func doNextPrev(t testing.TB) { + for _, tt := range nextPrevTests { + gnext, gprev := tt.ip.Next(), tt.ip.Prev() + if gnext != tt.next { + t.Errorf("IP(%v).Next = %v; want %v", tt.ip, gnext, tt.next) + } + if gprev != tt.prev { + t.Errorf("IP(%v).Prev = %v; want %v", tt.ip, gprev, tt.prev) + } + if !tt.ip.Next().isZero() && tt.ip.Next().Prev() != tt.ip { + t.Errorf("IP(%v).Next.Prev = %v; want %v", tt.ip, tt.ip.Next().Prev(), tt.ip) + } + if !tt.ip.Prev().isZero() && tt.ip.Prev().Next() != tt.ip { + t.Errorf("IP(%v).Prev.Next = %v; want %v", tt.ip, tt.ip.Prev().Next(), tt.ip) + } + } +} + +func TestIPBitLen(t *testing.T) { + tests := []struct { + ip Addr + want int + }{ + {Addr{}, 0}, + {mustIP("0.0.0.0"), 32}, + {mustIP("10.0.0.1"), 32}, + {mustIP("::"), 128}, + {mustIP("fed0::1"), 128}, + {mustIP("::ffff:10.0.0.1"), 128}, + } + for _, tt := range tests { + got := tt.ip.BitLen() + if got != tt.want { + t.Errorf("BitLen(%v) = %d; want %d", tt.ip, got, tt.want) + } + } +} + +func TestPrefixContains(t *testing.T) { + tests := []struct { + ipp Prefix + ip Addr + want bool + }{ + {mustPrefix("9.8.7.6/0"), mustIP("9.8.7.6"), true}, + {mustPrefix("9.8.7.6/16"), mustIP("9.8.7.6"), true}, + {mustPrefix("9.8.7.6/16"), mustIP("9.8.6.4"), true}, + {mustPrefix("9.8.7.6/16"), mustIP("9.9.7.6"), false}, + {mustPrefix("9.8.7.6/32"), mustIP("9.8.7.6"), true}, + {mustPrefix("9.8.7.6/32"), mustIP("9.8.7.7"), false}, + {mustPrefix("9.8.7.6/32"), mustIP("9.8.7.7"), false}, + {mustPrefix("::1/0"), mustIP("::1"), true}, + {mustPrefix("::1/0"), mustIP("::2"), true}, + {mustPrefix("::1/127"), mustIP("::1"), true}, + {mustPrefix("::1/127"), mustIP("::2"), false}, + {mustPrefix("::1/128"), mustIP("::1"), true}, + {mustPrefix("::1/127"), mustIP("::2"), false}, + // zones support + {mustPrefix("::1%a/128"), mustIP("::1"), true}, // prefix zones are stripped... + {mustPrefix("::1%a/128"), mustIP("::1%a"), false}, // but ip zones are not + // invalid IP + {mustPrefix("::1/0"), Addr{}, false}, + {mustPrefix("1.2.3.4/0"), Addr{}, false}, + // invalid Prefix + {Prefix{mustIP("::1"), 129}, mustIP("::1"), false}, + {Prefix{mustIP("1.2.3.4"), 33}, mustIP("1.2.3.4"), false}, + {Prefix{Addr{}, 0}, mustIP("1.2.3.4"), false}, + {Prefix{Addr{}, 32}, mustIP("1.2.3.4"), false}, + {Prefix{Addr{}, 128}, mustIP("::1"), false}, + // wrong IP family + {mustPrefix("::1/0"), mustIP("1.2.3.4"), false}, + {mustPrefix("1.2.3.4/0"), mustIP("::1"), false}, + } + for _, tt := range tests { + got := tt.ipp.Contains(tt.ip) + if got != tt.want { + t.Errorf("(%v).Contains(%v) = %v want %v", tt.ipp, tt.ip, got, tt.want) + } + } +} + +func TestParseIPError(t *testing.T) { + tests := []struct { + ip string + errstr string + }{ + { + ip: "localhost", + }, + { + ip: "500.0.0.1", + errstr: "field has value >255", + }, + { + ip: "::gggg%eth0", + errstr: "must have at least one digit", + }, + { + ip: "fe80::1cc0:3e8c:119f:c2e1%", + errstr: "zone must be a non-empty string", + }, + { + ip: "%eth0", + errstr: "missing IPv6 address", + }, + } + for _, test := range tests { + t.Run(test.ip, func(t *testing.T) { + _, err := ParseAddr(test.ip) + if err == nil { + t.Fatal("no error") + } + if _, ok := err.(parseAddrError); !ok { + t.Errorf("error type is %T, want parseIPError", err) + } + if test.errstr == "" { + test.errstr = "unable to parse IP" + } + if got := err.Error(); !strings.Contains(got, test.errstr) { + t.Errorf("error is missing substring %q: %s", test.errstr, got) + } + }) + } +} + +func TestParseAddrPort(t *testing.T) { + tests := []struct { + in string + want AddrPort + wantErr bool + }{ + {in: "1.2.3.4:1234", want: AddrPort{mustIP("1.2.3.4"), 1234}}, + {in: "1.1.1.1:123456", wantErr: true}, + {in: "1.1.1.1:-123", wantErr: true}, + {in: "[::1]:1234", want: AddrPort{mustIP("::1"), 1234}}, + {in: "[1.2.3.4]:1234", wantErr: true}, + {in: "fe80::1:1234", wantErr: true}, + {in: ":0", wantErr: true}, // if we need to parse this form, there should be a separate function that explicitly allows it + } + for _, test := range tests { + t.Run(test.in, func(t *testing.T) { + got, err := ParseAddrPort(test.in) + if err != nil { + if test.wantErr { + return + } + t.Fatal(err) + } + if got != test.want { + t.Errorf("got %v; want %v", got, test.want) + } + if got.String() != test.in { + t.Errorf("String = %q; want %q", got.String(), test.in) + } + }) + + t.Run(test.in+"/AppendTo", func(t *testing.T) { + got, err := ParseAddrPort(test.in) + if err == nil { + testAppendToMarshal(t, got) + } + }) + + // TextMarshal and TextUnmarshal mostly behave like + // ParseAddrPort and String. Divergent behavior are handled in + // TestAddrPortMarshalUnmarshal. + t.Run(test.in+"/Marshal", func(t *testing.T) { + var got AddrPort + jsin := `"` + test.in + `"` + err := json.Unmarshal([]byte(jsin), &got) + if err != nil { + if test.wantErr { + return + } + t.Fatal(err) + } + if got != test.want { + t.Errorf("got %v; want %v", got, test.want) + } + gotb, err := json.Marshal(got) + if err != nil { + t.Fatal(err) + } + if string(gotb) != jsin { + t.Errorf("Marshal = %q; want %q", string(gotb), jsin) + } + }) + } +} + +func TestAddrPortMarshalUnmarshal(t *testing.T) { + tests := []struct { + in string + want AddrPort + }{ + {"", AddrPort{}}, + } + + for _, test := range tests { + t.Run(test.in, func(t *testing.T) { + orig := `"` + test.in + `"` + + var ipp AddrPort + if err := json.Unmarshal([]byte(orig), &ipp); err != nil { + t.Fatalf("failed to unmarshal: %v", err) + } + + ippb, err := json.Marshal(ipp) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + back := string(ippb) + if orig != back { + t.Errorf("Marshal = %q; want %q", back, orig) + } + + testAppendToMarshal(t, ipp) + }) + } +} + +type appendMarshaler interface { + encoding.TextMarshaler + AppendTo([]byte) []byte +} + +// testAppendToMarshal tests that x's AppendTo and MarshalText methods yield the same results. +// x's MarshalText method must not return an error. +func testAppendToMarshal(t *testing.T, x appendMarshaler) { + t.Helper() + m, err := x.MarshalText() + if err != nil { + t.Fatalf("(%v).MarshalText: %v", x, err) + } + a := make([]byte, 0, len(m)) + a = x.AppendTo(a) + if !bytes.Equal(m, a) { + t.Errorf("(%v).MarshalText = %q, (%v).AppendTo = %q", x, m, x, a) + } +} + +func TestIPv6Accessor(t *testing.T) { + var a [16]byte + for i := range a { + a[i] = uint8(i) + 1 + } + ip := AddrFrom16(a) + for i := range a { + if got, want := ip.v6(uint8(i)), uint8(i)+1; got != want { + t.Errorf("v6(%v) = %v; want %v", i, got, want) + } + } +} diff --git a/src/net/netip/netip_test.go b/src/net/netip/netip_test.go new file mode 100644 index 0000000000..5d935c8fd3 --- /dev/null +++ b/src/net/netip/netip_test.go @@ -0,0 +1,1798 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package netip_test + +import ( + "bytes" + "encoding/json" + "flag" + "fmt" + "internal/intern" + "net" + . "net/netip" + "reflect" + "sort" + "strings" + "testing" +) + +var long = flag.Bool("long", false, "run long tests") + +type uint128 = Uint128 + +var ( + mustPrefix = MustParsePrefix + mustIP = MustParseAddr +) + +func TestParseAddr(t *testing.T) { + var validIPs = []struct { + in string + ip Addr // output of ParseAddr() + str string // output of String(). If "", use in. + }{ + // Basic zero IPv4 address. + { + in: "0.0.0.0", + ip: MkAddr(Mk128(0, 0xffff00000000), Z4), + }, + // Basic non-zero IPv4 address. + { + in: "192.168.140.255", + ip: MkAddr(Mk128(0, 0xffffc0a88cff), Z4), + }, + // IPv4 address in windows-style "print all the digits" form. + { + in: "010.000.015.001", + ip: MkAddr(Mk128(0, 0xffff0a000f01), Z4), + str: "10.0.15.1", + }, + // IPv4 address with a silly amount of leading zeros. + { + in: "000001.00000002.00000003.000000004", + ip: MkAddr(Mk128(0, 0xffff01020304), Z4), + str: "1.2.3.4", + }, + // Basic zero IPv6 address. + { + in: "::", + ip: MkAddr(Mk128(0, 0), Z6noz), + }, + // Localhost IPv6. + { + in: "::1", + ip: MkAddr(Mk128(0, 1), Z6noz), + }, + // Fully expanded IPv6 address. + { + in: "fd7a:115c:a1e0:ab12:4843:cd96:626b:430b", + ip: MkAddr(Mk128(0xfd7a115ca1e0ab12, 0x4843cd96626b430b), Z6noz), + }, + // IPv6 with elided fields in the middle. + { + in: "fd7a:115c::626b:430b", + ip: MkAddr(Mk128(0xfd7a115c00000000, 0x00000000626b430b), Z6noz), + }, + // IPv6 with elided fields at the end. + { + in: "fd7a:115c:a1e0:ab12:4843:cd96::", + ip: MkAddr(Mk128(0xfd7a115ca1e0ab12, 0x4843cd9600000000), Z6noz), + }, + // IPv6 with single elided field at the end. + { + in: "fd7a:115c:a1e0:ab12:4843:cd96:626b::", + ip: MkAddr(Mk128(0xfd7a115ca1e0ab12, 0x4843cd96626b0000), Z6noz), + str: "fd7a:115c:a1e0:ab12:4843:cd96:626b:0", + }, + // IPv6 with single elided field in the middle. + { + in: "fd7a:115c:a1e0::4843:cd96:626b:430b", + ip: MkAddr(Mk128(0xfd7a115ca1e00000, 0x4843cd96626b430b), Z6noz), + str: "fd7a:115c:a1e0:0:4843:cd96:626b:430b", + }, + // IPv6 with the trailing 32 bits written as IPv4 dotted decimal. (4in6) + { + in: "::ffff:192.168.140.255", + ip: MkAddr(Mk128(0, 0x0000ffffc0a88cff), Z6noz), + str: "::ffff:192.168.140.255", + }, + // IPv6 with a zone specifier. + { + in: "fd7a:115c:a1e0:ab12:4843:cd96:626b:430b%eth0", + ip: MkAddr(Mk128(0xfd7a115ca1e0ab12, 0x4843cd96626b430b), intern.Get("eth0")), + }, + // IPv6 with dotted decimal and zone specifier. + { + in: "1:2::ffff:192.168.140.255%eth1", + ip: MkAddr(Mk128(0x0001000200000000, 0x0000ffffc0a88cff), intern.Get("eth1")), + str: "1:2::ffff:c0a8:8cff%eth1", + }, + // IPv6 with capital letters. + { + in: "FD9E:1A04:F01D::1", + ip: MkAddr(Mk128(0xfd9e1a04f01d0000, 0x1), Z6noz), + str: "fd9e:1a04:f01d::1", + }, + } + + for _, test := range validIPs { + t.Run(test.in, func(t *testing.T) { + got, err := ParseAddr(test.in) + if err != nil { + t.Fatal(err) + } + if got != test.ip { + t.Errorf("ParseAddr(%q) got %#v, want %#v", test.in, got, test.ip) + } + + // Check that ParseAddr is a pure function. + got2, err := ParseAddr(test.in) + if err != nil { + t.Fatal(err) + } + if got != got2 { + t.Errorf("ParseAddr(%q) got 2 different results: %#v, %#v", test.in, got, got2) + } + + // Check that ParseAddr(ip.String()) is the identity function. + s := got.String() + got3, err := ParseAddr(s) + if err != nil { + t.Fatal(err) + } + if got != got3 { + t.Errorf("ParseAddr(%q) != ParseAddr(ParseIP(%q).String()). Got %#v, want %#v", test.in, test.in, got3, got) + } + + // Check that the slow-but-readable parser produces the same result. + slow, err := parseIPSlow(test.in) + if err != nil { + t.Fatal(err) + } + if got != slow { + t.Errorf("ParseAddr(%q) = %#v, parseIPSlow(%q) = %#v", test.in, got, test.in, slow) + } + + // Check that the parsed IP formats as expected. + s = got.String() + wants := test.str + if wants == "" { + wants = test.in + } + if s != wants { + t.Errorf("ParseAddr(%q).String() got %q, want %q", test.in, s, wants) + } + + // Check that AppendTo matches MarshalText. + TestAppendToMarshal(t, got) + + // Check that MarshalText/UnmarshalText work similarly to + // ParseAddr/String (see TestIPMarshalUnmarshal for + // marshal-specific behavior that's not common with + // ParseAddr/String). + js := `"` + test.in + `"` + var jsgot Addr + if err := json.Unmarshal([]byte(js), &jsgot); err != nil { + t.Fatal(err) + } + if jsgot != got { + t.Errorf("json.Unmarshal(%q) = %#v, want %#v", test.in, jsgot, got) + } + jsb, err := json.Marshal(jsgot) + if err != nil { + t.Fatal(err) + } + jswant := `"` + wants + `"` + jsback := string(jsb) + if jsback != jswant { + t.Errorf("Marshal(Unmarshal(%q)) = %s, want %s", test.in, jsback, jswant) + } + }) + } + + var invalidIPs = []string{ + // Empty string + "", + // Garbage non-IP + "bad", + // Single number. Some parsers accept this as an IPv4 address in + // big-endian uint32 form, but we don't. + "1234", + // IPv4 with a zone specifier + "1.2.3.4%eth0", + // IPv4 field must have at least one digit + ".1.2.3", + "1.2.3.", + "1..2.3", + // IPv4 address too long + "1.2.3.4.5", + // IPv4 in dotted octal form + "0300.0250.0214.0377", + // IPv4 in dotted hex form + "0xc0.0xa8.0x8c.0xff", + // IPv4 in class B form + "192.168.12345", + // IPv4 in class B form, with a small enough number to be + // parseable as a regular dotted decimal field. + "127.0.1", + // IPv4 in class A form + "192.1234567", + // IPv4 in class A form, with a small enough number to be + // parseable as a regular dotted decimal field. + "127.1", + // IPv4 field has value >255 + "192.168.300.1", + // IPv4 with too many fields + "192.168.0.1.5.6", + // IPv6 with not enough fields + "1:2:3:4:5:6:7", + // IPv6 with too many fields + "1:2:3:4:5:6:7:8:9", + // IPv6 with 8 fields and a :: expander + "1:2:3:4::5:6:7:8", + // IPv6 with a field bigger than 2b + "fe801::1", + // IPv6 with non-hex values in field + "fe80:tail:scal:e::", + // IPv6 with a zone delimiter but no zone. + "fe80::1%", + // IPv6 (without ellipsis) with too many fields for trailing embedded IPv4. + "ffff:ffff:ffff:ffff:ffff:ffff:ffff:192.168.140.255", + // IPv6 (with ellipsis) with too many fields for trailing embedded IPv4. + "ffff::ffff:ffff:ffff:ffff:ffff:ffff:192.168.140.255", + // IPv6 with invalid embedded IPv4. + "::ffff:192.168.140.bad", + // IPv6 with multiple ellipsis ::. + "fe80::1::1", + // IPv6 with invalid non hex/colon character. + "fe80:1?:1", + // IPv6 with truncated bytes after single colon. + "fe80:", + } + + for _, s := range invalidIPs { + t.Run(s, func(t *testing.T) { + got, err := ParseAddr(s) + if err == nil { + t.Errorf("ParseAddr(%q) = %#v, want error", s, got) + } + + slow, err := parseIPSlow(s) + if err == nil { + t.Errorf("parseIPSlow(%q) = %#v, want error", s, slow) + } + + std := net.ParseIP(s) + if std != nil { + t.Errorf("net.ParseIP(%q) = %#v, want error", s, std) + } + + if s == "" { + // Don't test unmarshaling of "" here, do it in + // IPMarshalUnmarshal. + return + } + var jsgot Addr + js := []byte(`"` + s + `"`) + if err := json.Unmarshal(js, &jsgot); err == nil { + t.Errorf("json.Unmarshal(%q) = %#v, want error", s, jsgot) + } + }) + } +} + +func TestIPv4Constructors(t *testing.T) { + if AddrFrom4([4]byte{1, 2, 3, 4}) != MustParseAddr("1.2.3.4") { + t.Errorf("don't match") + } +} + +func TestAddrMarshalUnmarshalBinary(t *testing.T) { + tests := []struct { + ip string + wantSize int + }{ + {"", 0}, // zero IP + {"1.2.3.4", 4}, + {"fd7a:115c:a1e0:ab12:4843:cd96:626b:430b", 16}, + {"::ffff:c000:0280", 16}, + {"::ffff:c000:0280%eth0", 20}, + } + for _, tc := range tests { + var ip Addr + if len(tc.ip) > 0 { + ip = mustIP(tc.ip) + } + b, err := ip.MarshalBinary() + if err != nil { + t.Fatal(err) + } + if len(b) != tc.wantSize { + t.Fatalf("%q encoded to size %d; want %d", tc.ip, len(b), tc.wantSize) + } + var ip2 Addr + if err := ip2.UnmarshalBinary(b); err != nil { + t.Fatal(err) + } + if ip != ip2 { + t.Fatalf("got %v; want %v", ip2, ip) + } + } + + // Cannot unmarshal from unexpected IP length. + for _, l := range []int{3, 5} { + var ip2 Addr + if err := ip2.UnmarshalBinary(bytes.Repeat([]byte{1}, l)); err == nil { + t.Fatalf("unmarshaled from unexpected IP length %d", l) + } + } +} + +func TestAddrMarshalUnmarshal(t *testing.T) { + // This only tests the cases where Marshal/Unmarshal diverges from + // the behavior of ParseAddr/String. For the rest of the test cases, + // see TestParseAddr above. + orig := `""` + var ip Addr + if err := json.Unmarshal([]byte(orig), &ip); err != nil { + t.Fatalf("Unmarshal(%q) got error %v", orig, err) + } + if ip != (Addr{}) { + t.Errorf("Unmarshal(%q) is not the zero Addr", orig) + } + + jsb, err := json.Marshal(ip) + if err != nil { + t.Fatalf("Marshal(%v) got error %v", ip, err) + } + back := string(jsb) + if back != orig { + t.Errorf("Marshal(Unmarshal(%q)) got %q, want %q", orig, back, orig) + } +} + +func TestAddrFrom16(t *testing.T) { + tests := []struct { + name string + in [16]byte + want Addr + }{ + { + name: "v6-raw", + in: [...]byte{15: 1}, + want: MkAddr(Mk128(0, 1), Z6noz), + }, + { + name: "v4-raw", + in: [...]byte{10: 0xff, 11: 0xff, 12: 1, 13: 2, 14: 3, 15: 4}, + want: MkAddr(Mk128(0, 0xffff01020304), Z6noz), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := AddrFrom16(tt.in) + if got != tt.want { + t.Errorf("got %#v; want %#v", got, tt.want) + } + }) + } +} + +func TestIPProperties(t *testing.T) { + var ( + nilIP Addr + + unicast4 = mustIP("192.0.2.1") + unicast6 = mustIP("2001:db8::1") + unicastZone6 = mustIP("2001:db8::1%eth0") + unicast6Unassigned = mustIP("4000::1") // not in 2000::/3. + + multicast4 = mustIP("224.0.0.1") + multicast6 = mustIP("ff02::1") + multicastZone6 = mustIP("ff02::1%eth0") + + llu4 = mustIP("169.254.0.1") + llu6 = mustIP("fe80::1") + llu6Last = mustIP("febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff") + lluZone6 = mustIP("fe80::1%eth0") + + loopback4 = mustIP("127.0.0.1") + loopback6 = mustIP("::1") + + ilm6 = mustIP("ff01::1") + ilmZone6 = mustIP("ff01::1%eth0") + + private4a = mustIP("10.0.0.1") + private4b = mustIP("172.16.0.1") + private4c = mustIP("192.168.1.1") + private6 = mustIP("fd00::1") + + unspecified4 = AddrFrom4([4]byte{}) + unspecified6 = IPv6Unspecified() + ) + + tests := []struct { + name string + ip Addr + globalUnicast bool + interfaceLocalMulticast bool + linkLocalMulticast bool + linkLocalUnicast bool + loopback bool + multicast bool + private bool + unspecified bool + }{ + { + name: "nil", + ip: nilIP, + }, + { + name: "unicast v4Addr", + ip: unicast4, + globalUnicast: true, + }, + { + name: "unicast v6Addr", + ip: unicast6, + globalUnicast: true, + }, + { + name: "unicast v6AddrZone", + ip: unicastZone6, + globalUnicast: true, + }, + { + name: "unicast v6Addr unassigned", + ip: unicast6Unassigned, + globalUnicast: true, + }, + { + name: "multicast v4Addr", + ip: multicast4, + linkLocalMulticast: true, + multicast: true, + }, + { + name: "multicast v6Addr", + ip: multicast6, + linkLocalMulticast: true, + multicast: true, + }, + { + name: "multicast v6AddrZone", + ip: multicastZone6, + linkLocalMulticast: true, + multicast: true, + }, + { + name: "link-local unicast v4Addr", + ip: llu4, + linkLocalUnicast: true, + }, + { + name: "link-local unicast v6Addr", + ip: llu6, + linkLocalUnicast: true, + }, + { + name: "link-local unicast v6Addr upper bound", + ip: llu6Last, + linkLocalUnicast: true, + }, + { + name: "link-local unicast v6AddrZone", + ip: lluZone6, + linkLocalUnicast: true, + }, + { + name: "loopback v4Addr", + ip: loopback4, + loopback: true, + }, + { + name: "loopback v6Addr", + ip: loopback6, + loopback: true, + }, + { + name: "interface-local multicast v6Addr", + ip: ilm6, + interfaceLocalMulticast: true, + multicast: true, + }, + { + name: "interface-local multicast v6AddrZone", + ip: ilmZone6, + interfaceLocalMulticast: true, + multicast: true, + }, + { + name: "private v4Addr 10/8", + ip: private4a, + globalUnicast: true, + private: true, + }, + { + name: "private v4Addr 172.16/12", + ip: private4b, + globalUnicast: true, + private: true, + }, + { + name: "private v4Addr 192.168/16", + ip: private4c, + globalUnicast: true, + private: true, + }, + { + name: "private v6Addr", + ip: private6, + globalUnicast: true, + private: true, + }, + { + name: "unspecified v4Addr", + ip: unspecified4, + unspecified: true, + }, + { + name: "unspecified v6Addr", + ip: unspecified6, + unspecified: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gu := tt.ip.IsGlobalUnicast() + if gu != tt.globalUnicast { + t.Errorf("IsGlobalUnicast(%v) = %v; want %v", tt.ip, gu, tt.globalUnicast) + } + + ilm := tt.ip.IsInterfaceLocalMulticast() + if ilm != tt.interfaceLocalMulticast { + t.Errorf("IsInterfaceLocalMulticast(%v) = %v; want %v", tt.ip, ilm, tt.interfaceLocalMulticast) + } + + llu := tt.ip.IsLinkLocalUnicast() + if llu != tt.linkLocalUnicast { + t.Errorf("IsLinkLocalUnicast(%v) = %v; want %v", tt.ip, llu, tt.linkLocalUnicast) + } + + llm := tt.ip.IsLinkLocalMulticast() + if llm != tt.linkLocalMulticast { + t.Errorf("IsLinkLocalMulticast(%v) = %v; want %v", tt.ip, llm, tt.linkLocalMulticast) + } + + lo := tt.ip.IsLoopback() + if lo != tt.loopback { + t.Errorf("IsLoopback(%v) = %v; want %v", tt.ip, lo, tt.loopback) + } + + multicast := tt.ip.IsMulticast() + if multicast != tt.multicast { + t.Errorf("IsMulticast(%v) = %v; want %v", tt.ip, multicast, tt.multicast) + } + + private := tt.ip.IsPrivate() + if private != tt.private { + t.Errorf("IsPrivate(%v) = %v; want %v", tt.ip, private, tt.private) + } + + unspecified := tt.ip.IsUnspecified() + if unspecified != tt.unspecified { + t.Errorf("IsUnspecified(%v) = %v; want %v", tt.ip, unspecified, tt.unspecified) + } + }) + } +} + +func TestAddrWellKnown(t *testing.T) { + tests := []struct { + name string + ip Addr + std net.IP + }{ + { + name: "IPv6 link-local all nodes", + ip: IPv6LinkLocalAllNodes(), + std: net.IPv6linklocalallnodes, + }, + { + name: "IPv6 unspecified", + ip: IPv6Unspecified(), + std: net.IPv6unspecified, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + want := tt.std.String() + got := tt.ip.String() + + if got != want { + t.Fatalf("got %s, want %s", got, want) + } + }) + } +} + +func TestLessCompare(t *testing.T) { + tests := []struct { + a, b Addr + want bool + }{ + {Addr{}, Addr{}, false}, + {Addr{}, mustIP("1.2.3.4"), true}, + {mustIP("1.2.3.4"), Addr{}, false}, + + {mustIP("1.2.3.4"), mustIP("0102:0304::0"), true}, + {mustIP("0102:0304::0"), mustIP("1.2.3.4"), false}, + {mustIP("1.2.3.4"), mustIP("1.2.3.4"), false}, + + {mustIP("::1"), mustIP("::2"), true}, + {mustIP("::1"), mustIP("::1%foo"), true}, + {mustIP("::1%foo"), mustIP("::2"), true}, + {mustIP("::2"), mustIP("::3"), true}, + + {mustIP("::"), mustIP("0.0.0.0"), false}, + {mustIP("0.0.0.0"), mustIP("::"), true}, + + {mustIP("::1%a"), mustIP("::1%b"), true}, + {mustIP("::1%a"), mustIP("::1%a"), false}, + {mustIP("::1%b"), mustIP("::1%a"), false}, + } + for _, tt := range tests { + got := tt.a.Less(tt.b) + if got != tt.want { + t.Errorf("Less(%q, %q) = %v; want %v", tt.a, tt.b, got, tt.want) + } + cmp := tt.a.Compare(tt.b) + if got && cmp != -1 { + t.Errorf("Less(%q, %q) = true, but Compare = %v (not -1)", tt.a, tt.b, cmp) + } + if cmp < -1 || cmp > 1 { + t.Errorf("bogus Compare return value %v", cmp) + } + if cmp == 0 && tt.a != tt.b { + t.Errorf("Compare(%q, %q) = 0; but not equal", tt.a, tt.b) + } + if cmp == 1 && !tt.b.Less(tt.a) { + t.Errorf("Compare(%q, %q) = 1; but b.Less(a) isn't true", tt.a, tt.b) + } + + // Also check inverse. + if got == tt.want && got { + got2 := tt.b.Less(tt.a) + if got2 { + t.Errorf("Less(%q, %q) was correctly %v, but so was Less(%q, %q)", tt.a, tt.b, got, tt.b, tt.a) + } + } + } + + // And just sort. + values := []Addr{ + mustIP("::1"), + mustIP("::2"), + Addr{}, + mustIP("1.2.3.4"), + mustIP("8.8.8.8"), + mustIP("::1%foo"), + } + sort.Slice(values, func(i, j int) bool { return values[i].Less(values[j]) }) + got := fmt.Sprintf("%s", values) + want := `[invalid IP 1.2.3.4 8.8.8.8 ::1 ::1%foo ::2]` + if got != want { + t.Errorf("unexpected sort\n got: %s\nwant: %s\n", got, want) + } +} + +func TestIPStringExpanded(t *testing.T) { + tests := []struct { + ip Addr + s string + }{ + { + ip: Addr{}, + s: "invalid IP", + }, + { + ip: mustIP("192.0.2.1"), + s: "192.0.2.1", + }, + { + ip: mustIP("::ffff:192.0.2.1"), + s: "0000:0000:0000:0000:0000:ffff:c000:0201", + }, + { + ip: mustIP("2001:db8::1"), + s: "2001:0db8:0000:0000:0000:0000:0000:0001", + }, + { + ip: mustIP("2001:db8::1%eth0"), + s: "2001:0db8:0000:0000:0000:0000:0000:0001%eth0", + }, + } + + for _, tt := range tests { + t.Run(tt.ip.String(), func(t *testing.T) { + want := tt.s + got := tt.ip.StringExpanded() + + if got != want { + t.Fatalf("got %s, want %s", got, want) + } + }) + } +} + +func TestPrefixMasking(t *testing.T) { + type subtest struct { + ip Addr + bits uint8 + p Prefix + ok bool + } + + // makeIPv6 produces a set of IPv6 subtests with an optional zone identifier. + makeIPv6 := func(zone string) []subtest { + if zone != "" { + zone = "%" + zone + } + + return []subtest{ + { + ip: mustIP(fmt.Sprintf("2001:db8::1%s", zone)), + bits: 255, + }, + { + ip: mustIP(fmt.Sprintf("2001:db8::1%s", zone)), + bits: 32, + p: mustPrefix(fmt.Sprintf("2001:db8::%s/32", zone)), + ok: true, + }, + { + ip: mustIP(fmt.Sprintf("fe80::dead:beef:dead:beef%s", zone)), + bits: 96, + p: mustPrefix(fmt.Sprintf("fe80::dead:beef:0:0%s/96", zone)), + ok: true, + }, + { + ip: mustIP(fmt.Sprintf("aaaa::%s", zone)), + bits: 4, + p: mustPrefix(fmt.Sprintf("a000::%s/4", zone)), + ok: true, + }, + { + ip: mustIP(fmt.Sprintf("::%s", zone)), + bits: 63, + p: mustPrefix(fmt.Sprintf("::%s/63", zone)), + ok: true, + }, + } + } + + tests := []struct { + family string + subtests []subtest + }{ + { + family: "nil", + subtests: []subtest{ + { + bits: 255, + ok: true, + }, + { + bits: 16, + ok: true, + }, + }, + }, + { + family: "IPv4", + subtests: []subtest{ + { + ip: mustIP("192.0.2.0"), + bits: 255, + }, + { + ip: mustIP("192.0.2.0"), + bits: 16, + p: mustPrefix("192.0.0.0/16"), + ok: true, + }, + { + ip: mustIP("255.255.255.255"), + bits: 20, + p: mustPrefix("255.255.240.0/20"), + ok: true, + }, + { + // Partially masking one byte that contains both + // 1s and 0s on either side of the mask limit. + ip: mustIP("100.98.156.66"), + bits: 10, + p: mustPrefix("100.64.0.0/10"), + ok: true, + }, + }, + }, + { + family: "IPv6", + subtests: makeIPv6(""), + }, + { + family: "IPv6 zone", + subtests: makeIPv6("eth0"), + }, + } + + for _, tt := range tests { + t.Run(tt.family, func(t *testing.T) { + for _, st := range tt.subtests { + t.Run(st.p.String(), func(t *testing.T) { + // Ensure st.ip is not mutated. + orig := st.ip.String() + + p, err := st.ip.Prefix(int(st.bits)) + if st.ok && err != nil { + t.Fatalf("failed to produce prefix: %v", err) + } + if !st.ok && err == nil { + t.Fatal("expected an error, but none occurred") + } + if err != nil { + t.Logf("err: %v", err) + return + } + + if !reflect.DeepEqual(p, st.p) { + t.Errorf("prefix = %q, want %q", p, st.p) + } + + if got := st.ip.String(); got != orig { + t.Errorf("IP was mutated: %q, want %q", got, orig) + } + }) + } + }) + } +} + +func TestPrefixMarshalUnmarshal(t *testing.T) { + tests := []string{ + "", + "1.2.3.4/32", + "0.0.0.0/0", + "::/0", + "::1/128", + "::ffff:c000:1234/128", + "2001:db8::/32", + } + + for _, s := range tests { + t.Run(s, func(t *testing.T) { + // Ensure that JSON (and by extension, text) marshaling is + // sane by entering quoted input. + orig := `"` + s + `"` + + var p Prefix + if err := json.Unmarshal([]byte(orig), &p); err != nil { + t.Fatalf("failed to unmarshal: %v", err) + } + + pb, err := json.Marshal(p) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + back := string(pb) + if orig != back { + t.Errorf("Marshal = %q; want %q", back, orig) + } + }) + } +} + +func TestPrefixMarshalUnmarshalZone(t *testing.T) { + orig := `"fe80::1cc0:3e8c:119f:c2e1%ens18/128"` + unzoned := `"fe80::1cc0:3e8c:119f:c2e1/128"` + + var p Prefix + if err := json.Unmarshal([]byte(orig), &p); err != nil { + t.Fatalf("failed to unmarshal: %v", err) + } + + pb, err := json.Marshal(p) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + back := string(pb) + if back != unzoned { + t.Errorf("Marshal = %q; want %q", back, unzoned) + } +} + +func TestPrefixUnmarshalTextNonZero(t *testing.T) { + ip := mustPrefix("fe80::/64") + if err := ip.UnmarshalText([]byte("xxx")); err == nil { + t.Fatal("unmarshaled into non-empty Prefix") + } +} + +func TestIs4AndIs6(t *testing.T) { + tests := []struct { + ip Addr + is4 bool + is6 bool + }{ + {Addr{}, false, false}, + {mustIP("1.2.3.4"), true, false}, + {mustIP("127.0.0.2"), true, false}, + {mustIP("::1"), false, true}, + {mustIP("::ffff:192.0.2.128"), false, true}, + {mustIP("::fffe:c000:0280"), false, true}, + {mustIP("::1%eth0"), false, true}, + } + for _, tt := range tests { + got4 := tt.ip.Is4() + if got4 != tt.is4 { + t.Errorf("Is4(%q) = %v; want %v", tt.ip, got4, tt.is4) + } + + got6 := tt.ip.Is6() + if got6 != tt.is6 { + t.Errorf("Is6(%q) = %v; want %v", tt.ip, got6, tt.is6) + } + } +} + +func TestIs4In6(t *testing.T) { + tests := []struct { + ip Addr + want bool + wantUnmap Addr + }{ + {Addr{}, false, Addr{}}, + {mustIP("::ffff:c000:0280"), true, mustIP("192.0.2.128")}, + {mustIP("::ffff:192.0.2.128"), true, mustIP("192.0.2.128")}, + {mustIP("::ffff:192.0.2.128%eth0"), true, mustIP("192.0.2.128")}, + {mustIP("::fffe:c000:0280"), false, mustIP("::fffe:c000:0280")}, + {mustIP("::ffff:127.001.002.003"), true, mustIP("127.1.2.3")}, + {mustIP("::ffff:7f01:0203"), true, mustIP("127.1.2.3")}, + {mustIP("0:0:0:0:0000:ffff:127.1.2.3"), true, mustIP("127.1.2.3")}, + {mustIP("0:0:0:0:000000:ffff:127.1.2.3"), true, mustIP("127.1.2.3")}, + {mustIP("0:0:0:0::ffff:127.1.2.3"), true, mustIP("127.1.2.3")}, + {mustIP("::1"), false, mustIP("::1")}, + {mustIP("1.2.3.4"), false, mustIP("1.2.3.4")}, + } + for _, tt := range tests { + got := tt.ip.Is4In6() + if got != tt.want { + t.Errorf("Is4In6(%q) = %v; want %v", tt.ip, got, tt.want) + } + u := tt.ip.Unmap() + if u != tt.wantUnmap { + t.Errorf("Unmap(%q) = %v; want %v", tt.ip, u, tt.wantUnmap) + } + } +} + +func TestPrefixMasked(t *testing.T) { + tests := []struct { + prefix Prefix + masked Prefix + }{ + { + prefix: mustPrefix("192.168.0.255/24"), + masked: mustPrefix("192.168.0.0/24"), + }, + { + prefix: mustPrefix("2100::/3"), + masked: mustPrefix("2000::/3"), + }, + { + prefix: PrefixFrom(mustIP("2000::"), 129), + masked: Prefix{}, + }, + { + prefix: PrefixFrom(mustIP("1.2.3.4"), 33), + masked: Prefix{}, + }, + } + for _, test := range tests { + t.Run(test.prefix.String(), func(t *testing.T) { + got := test.prefix.Masked() + if got != test.masked { + t.Errorf("Masked=%s, want %s", got, test.masked) + } + }) + } +} + +func TestPrefix(t *testing.T) { + tests := []struct { + prefix string + ip Addr + bits int + str string + contains []Addr + notContains []Addr + }{ + { + prefix: "192.168.0.0/24", + ip: mustIP("192.168.0.0"), + bits: 24, + contains: mustIPs("192.168.0.1", "192.168.0.55"), + notContains: mustIPs("192.168.1.1", "1.1.1.1"), + }, + { + prefix: "192.168.1.1/32", + ip: mustIP("192.168.1.1"), + bits: 32, + contains: mustIPs("192.168.1.1"), + notContains: mustIPs("192.168.1.2"), + }, + { + prefix: "100.64.0.0/10", // CGNAT range; prefix not multiple of 8 + ip: mustIP("100.64.0.0"), + bits: 10, + contains: mustIPs("100.64.0.0", "100.64.0.1", "100.81.251.94", "100.100.100.100", "100.127.255.254", "100.127.255.255"), + notContains: mustIPs("100.63.255.255", "100.128.0.0"), + }, + { + prefix: "2001:db8::/96", + ip: mustIP("2001:db8::"), + bits: 96, + contains: mustIPs("2001:db8::aaaa:bbbb", "2001:db8::1"), + notContains: mustIPs("2001:db8::1:aaaa:bbbb", "2001:db9::"), + }, + { + prefix: "0.0.0.0/0", + ip: mustIP("0.0.0.0"), + bits: 0, + contains: mustIPs("192.168.0.1", "1.1.1.1"), + notContains: append(mustIPs("2001:db8::1"), Addr{}), + }, + { + prefix: "::/0", + ip: mustIP("::"), + bits: 0, + contains: mustIPs("::1", "2001:db8::1"), + notContains: mustIPs("192.0.2.1"), + }, + { + prefix: "2000::/3", + ip: mustIP("2000::"), + bits: 3, + contains: mustIPs("2001:db8::1"), + notContains: mustIPs("fe80::1"), + }, + { + prefix: "::%0/00/80", + ip: mustIP("::"), + bits: 80, + str: "::/80", + contains: mustIPs("::"), + notContains: mustIPs("ff::%0/00", "ff::%1/23", "::%0/00", "::%1/23"), + }, + } + for _, test := range tests { + t.Run(test.prefix, func(t *testing.T) { + prefix, err := ParsePrefix(test.prefix) + if err != nil { + t.Fatal(err) + } + if prefix.Addr() != test.ip { + t.Errorf("IP=%s, want %s", prefix.Addr(), test.ip) + } + if prefix.Bits() != test.bits { + t.Errorf("bits=%d, want %d", prefix.Bits(), test.bits) + } + for _, ip := range test.contains { + if !prefix.Contains(ip) { + t.Errorf("does not contain %s", ip) + } + } + for _, ip := range test.notContains { + if prefix.Contains(ip) { + t.Errorf("contains %s", ip) + } + } + want := test.str + if want == "" { + want = test.prefix + } + if got := prefix.String(); got != want { + t.Errorf("prefix.String()=%q, want %q", got, want) + } + + TestAppendToMarshal(t, prefix) + }) + } +} + +func TestPrefixFromInvalidBits(t *testing.T) { + v4 := MustParseAddr("1.2.3.4") + v6 := MustParseAddr("66::66") + tests := []struct { + ip Addr + in, want int + }{ + {v4, 0, 0}, + {v6, 0, 0}, + {v4, 1, 1}, + {v4, 33, -1}, + {v6, 33, 33}, + {v6, 127, 127}, + {v6, 128, 128}, + {v4, 254, -1}, + {v4, 255, -1}, + {v4, -1, -1}, + {v6, -1, -1}, + {v4, -5, -1}, + {v6, -5, -1}, + } + for _, tt := range tests { + p := PrefixFrom(tt.ip, tt.in) + if got := p.Bits(); got != tt.want { + t.Errorf("for (%v, %v), Bits out = %v; want %v", tt.ip, tt.in, got, tt.want) + } + } +} + +func TestParsePrefixAllocs(t *testing.T) { + tests := []struct { + ip string + slash string + }{ + {"192.168.1.0", "/24"}, + {"aaaa:bbbb:cccc::", "/24"}, + } + for _, test := range tests { + prefix := test.ip + test.slash + t.Run(prefix, func(t *testing.T) { + ipAllocs := int(testing.AllocsPerRun(5, func() { + ParseAddr(test.ip) + })) + prefixAllocs := int(testing.AllocsPerRun(5, func() { + ParsePrefix(prefix) + })) + if got := prefixAllocs - ipAllocs; got != 0 { + t.Errorf("allocs=%d, want 0", got) + } + }) + } +} + +func TestParsePrefixError(t *testing.T) { + tests := []struct { + prefix string + errstr string + }{ + { + prefix: "192.168.0.0", + errstr: "no '/'", + }, + { + prefix: "1.257.1.1/24", + errstr: "value >255", + }, + { + prefix: "1.1.1.0/q", + errstr: "bad bits", + }, + { + prefix: "1.1.1.0/-1", + errstr: "out of range", + }, + { + prefix: "1.1.1.0/33", + errstr: "out of range", + }, + { + prefix: "2001::/129", + errstr: "out of range", + }, + } + for _, test := range tests { + t.Run(test.prefix, func(t *testing.T) { + _, err := ParsePrefix(test.prefix) + if err == nil { + t.Fatal("no error") + } + if got := err.Error(); !strings.Contains(got, test.errstr) { + t.Errorf("error is missing substring %q: %s", test.errstr, got) + } + }) + } +} + +func TestPrefixIsSingleIP(t *testing.T) { + tests := []struct { + ipp Prefix + want bool + }{ + {ipp: mustPrefix("127.0.0.1/32"), want: true}, + {ipp: mustPrefix("127.0.0.1/31"), want: false}, + {ipp: mustPrefix("127.0.0.1/0"), want: false}, + {ipp: mustPrefix("::1/128"), want: true}, + {ipp: mustPrefix("::1/127"), want: false}, + {ipp: mustPrefix("::1/0"), want: false}, + {ipp: Prefix{}, want: false}, + } + for _, tt := range tests { + got := tt.ipp.IsSingleIP() + if got != tt.want { + t.Errorf("IsSingleIP(%v) = %v want %v", tt.ipp, got, tt.want) + } + } +} + +func mustIPs(strs ...string) []Addr { + var res []Addr + for _, s := range strs { + res = append(res, mustIP(s)) + } + return res +} + +func BenchmarkBinaryMarshalRoundTrip(b *testing.B) { + b.ReportAllocs() + tests := []struct { + name string + ip string + }{ + {"ipv4", "1.2.3.4"}, + {"ipv6", "2001:db8::1"}, + {"ipv6+zone", "2001:db8::1%eth0"}, + } + for _, tc := range tests { + b.Run(tc.name, func(b *testing.B) { + ip := mustIP(tc.ip) + for i := 0; i < b.N; i++ { + bt, err := ip.MarshalBinary() + if err != nil { + b.Fatal(err) + } + var ip2 Addr + if err := ip2.UnmarshalBinary(bt); err != nil { + b.Fatal(err) + } + } + }) + } +} + +func BenchmarkStdIPv4(b *testing.B) { + b.ReportAllocs() + ips := []net.IP{} + for i := 0; i < b.N; i++ { + ip := net.IPv4(8, 8, 8, 8) + ips = ips[:0] + for i := 0; i < 100; i++ { + ips = append(ips, ip) + } + } +} + +func BenchmarkIPv4(b *testing.B) { + b.ReportAllocs() + ips := []Addr{} + for i := 0; i < b.N; i++ { + ip := IPv4(8, 8, 8, 8) + ips = ips[:0] + for i := 0; i < 100; i++ { + ips = append(ips, ip) + } + } +} + +// ip4i was one of the possible representations of IP that came up in +// discussions, inlining IPv4 addresses, but having an "overflow" +// interface for IPv6 or IPv6 + zone. This is here for benchmarking. +type ip4i struct { + ip4 [4]byte + flags1 byte + flags2 byte + flags3 byte + flags4 byte + ipv6 interface{} +} + +func newip4i_v4(a, b, c, d byte) ip4i { + return ip4i{ip4: [4]byte{a, b, c, d}} +} + +// BenchmarkIPv4_inline benchmarks the candidate representation, ip4i. +func BenchmarkIPv4_inline(b *testing.B) { + b.ReportAllocs() + ips := []ip4i{} + for i := 0; i < b.N; i++ { + ip := newip4i_v4(8, 8, 8, 8) + ips = ips[:0] + for i := 0; i < 100; i++ { + ips = append(ips, ip) + } + } +} + +func BenchmarkStdIPv6(b *testing.B) { + b.ReportAllocs() + ips := []net.IP{} + for i := 0; i < b.N; i++ { + ip := net.ParseIP("2001:db8::1") + ips = ips[:0] + for i := 0; i < 100; i++ { + ips = append(ips, ip) + } + } +} + +func BenchmarkIPv6(b *testing.B) { + b.ReportAllocs() + ips := []Addr{} + for i := 0; i < b.N; i++ { + ip := mustIP("2001:db8::1") + ips = ips[:0] + for i := 0; i < 100; i++ { + ips = append(ips, ip) + } + } +} + +func BenchmarkIPv4Contains(b *testing.B) { + b.ReportAllocs() + prefix := PrefixFrom(IPv4(192, 168, 1, 0), 24) + ip := IPv4(192, 168, 1, 1) + for i := 0; i < b.N; i++ { + prefix.Contains(ip) + } +} + +func BenchmarkIPv6Contains(b *testing.B) { + b.ReportAllocs() + prefix := MustParsePrefix("::1/128") + ip := MustParseAddr("::1") + for i := 0; i < b.N; i++ { + prefix.Contains(ip) + } +} + +var parseBenchInputs = []struct { + name string + ip string +}{ + {"v4", "192.168.1.1"}, + {"v6", "fd7a:115c:a1e0:ab12:4843:cd96:626b:430b"}, + {"v6_ellipsis", "fd7a:115c::626b:430b"}, + {"v6_v4", "::ffff:192.168.140.255"}, + {"v6_zone", "1:2::ffff:192.168.140.255%eth1"}, +} + +func BenchmarkParseAddr(b *testing.B) { + sinkInternValue = intern.Get("eth1") // Pin to not benchmark the intern package + for _, test := range parseBenchInputs { + b.Run(test.name, func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + sinkIP, _ = ParseAddr(test.ip) + } + }) + } +} + +func BenchmarkStdParseIP(b *testing.B) { + for _, test := range parseBenchInputs { + b.Run(test.name, func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + sinkStdIP = net.ParseIP(test.ip) + } + }) + } +} + +func BenchmarkIPString(b *testing.B) { + for _, test := range parseBenchInputs { + ip := MustParseAddr(test.ip) + b.Run(test.name, func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + sinkString = ip.String() + } + }) + } +} + +func BenchmarkIPStringExpanded(b *testing.B) { + for _, test := range parseBenchInputs { + ip := MustParseAddr(test.ip) + b.Run(test.name, func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + sinkString = ip.StringExpanded() + } + }) + } +} + +func BenchmarkIPMarshalText(b *testing.B) { + b.ReportAllocs() + ip := MustParseAddr("66.55.44.33") + for i := 0; i < b.N; i++ { + sinkBytes, _ = ip.MarshalText() + } +} + +func BenchmarkAddrPortString(b *testing.B) { + for _, test := range parseBenchInputs { + ip := MustParseAddr(test.ip) + ipp := AddrPortFrom(ip, 60000) + b.Run(test.name, func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + sinkString = ipp.String() + } + }) + } +} + +func BenchmarkAddrPortMarshalText(b *testing.B) { + for _, test := range parseBenchInputs { + ip := MustParseAddr(test.ip) + ipp := AddrPortFrom(ip, 60000) + b.Run(test.name, func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + sinkBytes, _ = ipp.MarshalText() + } + }) + } +} + +func BenchmarkPrefixMasking(b *testing.B) { + tests := []struct { + name string + ip Addr + bits int + }{ + { + name: "IPv4 /32", + ip: IPv4(192, 0, 2, 0), + bits: 32, + }, + { + name: "IPv4 /17", + ip: IPv4(192, 0, 2, 0), + bits: 17, + }, + { + name: "IPv4 /0", + ip: IPv4(192, 0, 2, 0), + bits: 0, + }, + { + name: "IPv6 /128", + ip: mustIP("2001:db8::1"), + bits: 128, + }, + { + name: "IPv6 /65", + ip: mustIP("2001:db8::1"), + bits: 65, + }, + { + name: "IPv6 /0", + ip: mustIP("2001:db8::1"), + bits: 0, + }, + { + name: "IPv6 zone /128", + ip: mustIP("2001:db8::1%eth0"), + bits: 128, + }, + { + name: "IPv6 zone /65", + ip: mustIP("2001:db8::1%eth0"), + bits: 65, + }, + { + name: "IPv6 zone /0", + ip: mustIP("2001:db8::1%eth0"), + bits: 0, + }, + } + + for _, tt := range tests { + b.Run(tt.name, func(b *testing.B) { + b.ReportAllocs() + + for i := 0; i < b.N; i++ { + sinkPrefix, _ = tt.ip.Prefix(tt.bits) + } + }) + } +} + +func BenchmarkPrefixMarshalText(b *testing.B) { + b.ReportAllocs() + ipp := MustParsePrefix("66.55.44.33/22") + for i := 0; i < b.N; i++ { + sinkBytes, _ = ipp.MarshalText() + } +} + +func BenchmarkParseAddrPort(b *testing.B) { + for _, test := range parseBenchInputs { + var ipp string + if strings.HasPrefix(test.name, "v6") { + ipp = fmt.Sprintf("[%s]:1234", test.ip) + } else { + ipp = fmt.Sprintf("%s:1234", test.ip) + } + b.Run(test.name, func(b *testing.B) { + b.ReportAllocs() + + for i := 0; i < b.N; i++ { + sinkAddrPort, _ = ParseAddrPort(ipp) + } + }) + } +} + +func TestAs4(t *testing.T) { + tests := []struct { + ip Addr + want [4]byte + wantPanic bool + }{ + { + ip: mustIP("1.2.3.4"), + want: [4]byte{1, 2, 3, 4}, + }, + { + ip: AddrFrom16(mustIP("1.2.3.4").As16()), // IPv4-in-IPv6 + want: [4]byte{1, 2, 3, 4}, + }, + { + ip: mustIP("0.0.0.0"), + want: [4]byte{0, 0, 0, 0}, + }, + { + ip: Addr{}, + wantPanic: true, + }, + { + ip: mustIP("::1"), + wantPanic: true, + }, + } + as4 := func(ip Addr) (v [4]byte, gotPanic bool) { + defer func() { + if recover() != nil { + gotPanic = true + return + } + }() + v = ip.As4() + return + } + for i, tt := range tests { + got, gotPanic := as4(tt.ip) + if gotPanic != tt.wantPanic { + t.Errorf("%d. panic on %v = %v; want %v", i, tt.ip, gotPanic, tt.wantPanic) + continue + } + if got != tt.want { + t.Errorf("%d. %v = %v; want %v", i, tt.ip, got, tt.want) + } + } +} + +func TestPrefixOverlaps(t *testing.T) { + pfx := mustPrefix + tests := []struct { + a, b Prefix + want bool + }{ + {Prefix{}, pfx("1.2.0.0/16"), false}, // first zero + {pfx("1.2.0.0/16"), Prefix{}, false}, // second zero + {pfx("::0/3"), pfx("0.0.0.0/3"), false}, // different families + + {pfx("1.2.0.0/16"), pfx("1.2.0.0/16"), true}, // equal + + {pfx("1.2.0.0/16"), pfx("1.2.3.0/24"), true}, + {pfx("1.2.3.0/24"), pfx("1.2.0.0/16"), true}, + + {pfx("1.2.0.0/16"), pfx("1.2.3.0/32"), true}, + {pfx("1.2.3.0/32"), pfx("1.2.0.0/16"), true}, + + // Match /0 either order + {pfx("1.2.3.0/32"), pfx("0.0.0.0/0"), true}, + {pfx("0.0.0.0/0"), pfx("1.2.3.0/32"), true}, + + {pfx("1.2.3.0/32"), pfx("5.5.5.5/0"), true}, // normalization not required; /0 means true + + // IPv6 overlapping + {pfx("5::1/128"), pfx("5::0/8"), true}, + {pfx("5::0/8"), pfx("5::1/128"), true}, + + // IPv6 not overlapping + {pfx("1::1/128"), pfx("2::2/128"), false}, + {pfx("0100::0/8"), pfx("::1/128"), false}, + + // v6-mapped v4 should not overlap with IPv4. + {PrefixFrom(AddrFrom16(mustIP("1.2.0.0").As16()), 16), pfx("1.2.3.0/24"), false}, + + // Invalid prefixes + {PrefixFrom(mustIP("1.2.3.4"), 33), pfx("1.2.3.0/24"), false}, + {PrefixFrom(mustIP("2000::"), 129), pfx("2000::/64"), false}, + } + for i, tt := range tests { + if got := tt.a.Overlaps(tt.b); got != tt.want { + t.Errorf("%d. (%v).Overlaps(%v) = %v; want %v", i, tt.a, tt.b, got, tt.want) + } + // Overlaps is commutative + if got := tt.b.Overlaps(tt.a); got != tt.want { + t.Errorf("%d. (%v).Overlaps(%v) = %v; want %v", i, tt.b, tt.a, got, tt.want) + } + } +} + +// Sink variables are here to force the compiler to not elide +// seemingly useless work in benchmarks and allocation tests. If you +// were to just `_ = foo()` within a test function, the compiler could +// correctly deduce that foo() does nothing and doesn't need to be +// called. By writing results to a global variable, we hide that fact +// from the compiler and force it to keep the code under test. +var ( + sinkIP Addr + sinkStdIP net.IP + sinkAddrPort AddrPort + sinkPrefix Prefix + sinkPrefixSlice []Prefix + sinkInternValue *intern.Value + sinkIP16 [16]byte + sinkIP4 [4]byte + sinkBool bool + sinkString string + sinkBytes []byte + sinkUDPAddr = &net.UDPAddr{IP: make(net.IP, 0, 16)} +) + +func TestNoAllocs(t *testing.T) { + // Wrappers that panic on error, to prove that our alloc-free + // methods are returning successfully. + panicIP := func(ip Addr, err error) Addr { + if err != nil { + panic(err) + } + return ip + } + panicPfx := func(pfx Prefix, err error) Prefix { + if err != nil { + panic(err) + } + return pfx + } + panicIPP := func(ipp AddrPort, err error) AddrPort { + if err != nil { + panic(err) + } + return ipp + } + test := func(name string, f func()) { + t.Run(name, func(t *testing.T) { + n := testing.AllocsPerRun(1000, f) + if n != 0 { + t.Fatalf("allocs = %d; want 0", int(n)) + } + }) + } + + // IP constructors + test("IPv4", func() { sinkIP = IPv4(1, 2, 3, 4) }) + test("AddrFrom4", func() { sinkIP = AddrFrom4([4]byte{1, 2, 3, 4}) }) + test("AddrFrom16", func() { sinkIP = AddrFrom16([16]byte{}) }) + test("ParseAddr/4", func() { sinkIP = panicIP(ParseAddr("1.2.3.4")) }) + test("ParseAddr/6", func() { sinkIP = panicIP(ParseAddr("::1")) }) + test("MustParseAddr", func() { sinkIP = MustParseAddr("1.2.3.4") }) + test("IPv6LinkLocalAllNodes", func() { sinkIP = IPv6LinkLocalAllNodes() }) + test("IPv6Unspecified", func() { sinkIP = IPv6Unspecified() }) + + // IP methods + test("IP.IsZero", func() { sinkBool = MustParseAddr("1.2.3.4").IsZero() }) + test("IP.BitLen", func() { sinkBool = MustParseAddr("1.2.3.4").BitLen() == 8 }) + test("IP.Zone/4", func() { sinkBool = MustParseAddr("1.2.3.4").Zone() == "" }) + test("IP.Zone/6", func() { sinkBool = MustParseAddr("fe80::1").Zone() == "" }) + test("IP.Zone/6zone", func() { sinkBool = MustParseAddr("fe80::1%zone").Zone() == "" }) + test("IP.Compare", func() { + a := MustParseAddr("1.2.3.4") + b := MustParseAddr("2.3.4.5") + sinkBool = a.Compare(b) == 0 + }) + test("IP.Less", func() { + a := MustParseAddr("1.2.3.4") + b := MustParseAddr("2.3.4.5") + sinkBool = a.Less(b) + }) + test("IP.Is4", func() { sinkBool = MustParseAddr("1.2.3.4").Is4() }) + test("IP.Is6", func() { sinkBool = MustParseAddr("fe80::1").Is6() }) + test("IP.Is4In6", func() { sinkBool = MustParseAddr("fe80::1").Is4In6() }) + test("IP.Unmap", func() { sinkIP = MustParseAddr("ffff::2.3.4.5").Unmap() }) + test("IP.WithZone", func() { sinkIP = MustParseAddr("fe80::1").WithZone("") }) + test("IP.IsGlobalUnicast", func() { sinkBool = MustParseAddr("2001:db8::1").IsGlobalUnicast() }) + test("IP.IsInterfaceLocalMulticast", func() { sinkBool = MustParseAddr("fe80::1").IsInterfaceLocalMulticast() }) + test("IP.IsLinkLocalMulticast", func() { sinkBool = MustParseAddr("fe80::1").IsLinkLocalMulticast() }) + test("IP.IsLinkLocalUnicast", func() { sinkBool = MustParseAddr("fe80::1").IsLinkLocalUnicast() }) + test("IP.IsLoopback", func() { sinkBool = MustParseAddr("fe80::1").IsLoopback() }) + test("IP.IsMulticast", func() { sinkBool = MustParseAddr("fe80::1").IsMulticast() }) + test("IP.IsPrivate", func() { sinkBool = MustParseAddr("fd00::1").IsPrivate() }) + test("IP.IsUnspecified", func() { sinkBool = IPv6Unspecified().IsUnspecified() }) + test("IP.Prefix/4", func() { sinkPrefix = panicPfx(MustParseAddr("1.2.3.4").Prefix(20)) }) + test("IP.Prefix/6", func() { sinkPrefix = panicPfx(MustParseAddr("fe80::1").Prefix(64)) }) + test("IP.As16", func() { sinkIP16 = MustParseAddr("1.2.3.4").As16() }) + test("IP.As4", func() { sinkIP4 = MustParseAddr("1.2.3.4").As4() }) + test("IP.Next", func() { sinkIP = MustParseAddr("1.2.3.4").Next() }) + test("IP.Prev", func() { sinkIP = MustParseAddr("1.2.3.4").Prev() }) + + // AddrPort constructors + test("AddrPortFrom", func() { sinkAddrPort = AddrPortFrom(IPv4(1, 2, 3, 4), 22) }) + test("ParseAddrPort", func() { sinkAddrPort = panicIPP(ParseAddrPort("[::1]:1234")) }) + test("MustParseAddrPort", func() { sinkAddrPort = MustParseAddrPort("[::1]:1234") }) + + // Prefix constructors + test("PrefixFrom", func() { sinkPrefix = PrefixFrom(IPv4(1, 2, 3, 4), 32) }) + test("ParsePrefix/4", func() { sinkPrefix = panicPfx(ParsePrefix("1.2.3.4/20")) }) + test("ParsePrefix/6", func() { sinkPrefix = panicPfx(ParsePrefix("fe80::1/64")) }) + test("MustParsePrefix", func() { sinkPrefix = MustParsePrefix("1.2.3.4/20") }) + + // Prefix methods + test("Prefix.Contains", func() { sinkBool = MustParsePrefix("1.2.3.0/24").Contains(MustParseAddr("1.2.3.4")) }) + test("Prefix.Overlaps", func() { + a, b := MustParsePrefix("1.2.3.0/24"), MustParsePrefix("1.2.0.0/16") + sinkBool = a.Overlaps(b) + }) + test("Prefix.IsZero", func() { sinkBool = MustParsePrefix("1.2.0.0/16").IsZero() }) + test("Prefix.IsSingleIP", func() { sinkBool = MustParsePrefix("1.2.3.4/32").IsSingleIP() }) + test("IPPRefix.Masked", func() { sinkPrefix = MustParsePrefix("1.2.3.4/16").Masked() }) +} + +func TestPrefixString(t *testing.T) { + tests := []struct { + ipp Prefix + want string + }{ + {Prefix{}, "invalid Prefix"}, + {PrefixFrom(Addr{}, 8), "invalid Prefix"}, + {PrefixFrom(MustParseAddr("1.2.3.4"), 88), "invalid Prefix"}, + } + + for _, tt := range tests { + if got := tt.ipp.String(); got != tt.want { + t.Errorf("(%#v).String() = %q want %q", tt.ipp, got, tt.want) + } + } +} + +func TestInvalidAddrPortString(t *testing.T) { + tests := []struct { + ipp AddrPort + want string + }{ + {AddrPort{}, "invalid AddrPort"}, + {AddrPortFrom(Addr{}, 80), "invalid AddrPort"}, + } + + for _, tt := range tests { + if got := tt.ipp.String(); got != tt.want { + t.Errorf("(%#v).String() = %q want %q", tt.ipp, got, tt.want) + } + } +} diff --git a/src/net/netip/slow_test.go b/src/net/netip/slow_test.go new file mode 100644 index 0000000000..5b46a39a83 --- /dev/null +++ b/src/net/netip/slow_test.go @@ -0,0 +1,190 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package netip_test + +import ( + "fmt" + . "net/netip" + "strconv" + "strings" +) + +// zeros is a slice of eight stringified zeros. It's used in +// parseIPSlow to construct slices of specific amounts of zero fields, +// from 1 to 8. +var zeros = []string{"0", "0", "0", "0", "0", "0", "0", "0"} + +// parseIPSlow is like ParseIP, but aims for readability above +// speed. It's the reference implementation for correctness checking +// and against which we measure optimized parsers. +// +// parseIPSlow understands the following forms of IP addresses: +// - Regular IPv4: 1.2.3.4 +// - IPv4 with many leading zeros: 0000001.0000002.0000003.0000004 +// - Regular IPv6: 1111:2222:3333:4444:5555:6666:7777:8888 +// - IPv6 with many leading zeros: 00000001:0000002:0000003:0000004:0000005:0000006:0000007:0000008 +// - IPv6 with zero blocks elided: 1111:2222::7777:8888 +// - IPv6 with trailing 32 bits expressed as IPv4: 1111:2222:3333:4444:5555:6666:77.77.88.88 +// +// It does not process the following IP address forms, which have been +// varyingly accepted by some programs due to an under-specification +// of the shapes of IPv4 addresses: +// +// - IPv4 as a single 32-bit uint: 4660 (same as "1.2.3.4") +// - IPv4 with octal numbers: 0300.0250.0.01 (same as "192.168.0.1") +// - IPv4 with hex numbers: 0xc0.0xa8.0x0.0x1 (same as "192.168.0.1") +// - IPv4 in "class-B style": 1.2.52 (same as "1.2.3.4") +// - IPv4 in "class-A style": 1.564 (same as "1.2.3.4") +func parseIPSlow(s string) (Addr, error) { + // Identify and strip out the zone, if any. There should be 0 or 1 + // '%' in the string. + var zone string + fs := strings.Split(s, "%") + switch len(fs) { + case 1: + // No zone, that's fine. + case 2: + s, zone = fs[0], fs[1] + if zone == "" { + return Addr{}, fmt.Errorf("netaddr.ParseIP(%q): no zone after zone specifier", s) + } + default: + return Addr{}, fmt.Errorf("netaddr.ParseIP(%q): too many zone specifiers", s) // TODO: less specific? + } + + // IPv4 by itself is easy to do in a helper. + if strings.Count(s, ":") == 0 { + if zone != "" { + return Addr{}, fmt.Errorf("netaddr.ParseIP(%q): IPv4 addresses cannot have a zone", s) + } + return parseIPv4Slow(s) + } + + normal, err := normalizeIPv6Slow(s) + if err != nil { + return Addr{}, err + } + + // At this point, we've normalized the address back into 8 hex + // fields of 16 bits each. Parse that. + fs = strings.Split(normal, ":") + if len(fs) != 8 { + return Addr{}, fmt.Errorf("netaddr.ParseIP(%q): wrong size address", s) + } + var ret [16]byte + for i, f := range fs { + a, b, err := parseWord(f) + if err != nil { + return Addr{}, err + } + ret[i*2] = a + ret[i*2+1] = b + } + + return AddrFrom16(ret).WithZone(zone), nil +} + +// normalizeIPv6Slow expands s, which is assumed to be an IPv6 +// address, to its canonical text form. +// +// The canonical form of an IPv6 address is 8 colon-separated fields, +// where each field should be a hex value from 0 to ffff. This +// function does not verify the contents of each field. +// +// This function performs two transformations: +// - The last 32 bits of an IPv6 address may be represented in +// IPv4-style dotted quad form, as in 1:2:3:4:5:6:7.8.9.10. That +// address is transformed to its hex equivalent, +// e.g. 1:2:3:4:5:6:708:90a. +// - An address may contain one "::", which expands into as many +// 16-bit blocks of zeros as needed to make the address its correct +// full size. For example, fe80::1:2 expands to fe80:0:0:0:0:0:1:2. +// +// Both short forms may be present in a single address, +// e.g. fe80::1.2.3.4. +func normalizeIPv6Slow(orig string) (string, error) { + s := orig + + // Find and convert an IPv4 address in the final field, if any. + i := strings.LastIndex(s, ":") + if i == -1 { + return "", fmt.Errorf("netaddr.ParseIP(%q): invalid IP address", orig) + } + if strings.Contains(s[i+1:], ".") { + ip, err := parseIPv4Slow(s[i+1:]) + if err != nil { + return "", err + } + a4 := ip.As4() + s = fmt.Sprintf("%s:%02x%02x:%02x%02x", s[:i], a4[0], a4[1], a4[2], a4[3]) + } + + // Find and expand a ::, if any. + fs := strings.Split(s, "::") + switch len(fs) { + case 1: + // No ::, nothing to do. + case 2: + lhs, rhs := fs[0], fs[1] + // Found a ::, figure out how many zero blocks need to be + // inserted. + nblocks := strings.Count(lhs, ":") + strings.Count(rhs, ":") + if lhs != "" { + nblocks++ + } + if rhs != "" { + nblocks++ + } + if nblocks > 7 { + return "", fmt.Errorf("netaddr.ParseIP(%q): address too long", orig) + } + fs = nil + // Either side of the :: can be empty. We don't want empty + // fields to feature in the final normalized address. + if lhs != "" { + fs = append(fs, lhs) + } + fs = append(fs, zeros[:8-nblocks]...) + if rhs != "" { + fs = append(fs, rhs) + } + s = strings.Join(fs, ":") + default: + // Too many :: + return "", fmt.Errorf("netaddr.ParseIP(%q): invalid IP address", orig) + } + + return s, nil +} + +// parseIPv4Slow parses and returns an IPv4 address in dotted quad +// form, e.g. "192.168.0.1". It is slow but easy to read, and the +// reference implementation against which we compare faster +// implementations for correctness. +func parseIPv4Slow(s string) (Addr, error) { + fs := strings.Split(s, ".") + if len(fs) != 4 { + return Addr{}, fmt.Errorf("netaddr.ParseIP(%q): invalid IP address", s) + } + var ret [4]byte + for i := range ret { + val, err := strconv.ParseUint(fs[i], 10, 8) + if err != nil { + return Addr{}, err + } + ret[i] = uint8(val) + } + return AddrFrom4([4]byte{ret[0], ret[1], ret[2], ret[3]}), nil +} + +// parseWord converts a 16-bit hex string into its corresponding +// two-byte value. +func parseWord(s string) (byte, byte, error) { + ret, err := strconv.ParseUint(s, 16, 16) + if err != nil { + return 0, 0, err + } + return uint8(ret >> 8), uint8(ret), nil +} diff --git a/src/net/netip/uint128.go b/src/net/netip/uint128.go new file mode 100644 index 0000000000..738939d7de --- /dev/null +++ b/src/net/netip/uint128.go @@ -0,0 +1,92 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package netip + +import "math/bits" + +// uint128 represents a uint128 using two uint64s. +// +// When the methods below mention a bit number, bit 0 is the most +// significant bit (in hi) and bit 127 is the lowest (lo&1). +type uint128 struct { + hi uint64 + lo uint64 +} + +// mask6 returns a uint128 bitmask with the topmost n bits of a +// 128-bit number. +func mask6(n int) uint128 { + return uint128{^(^uint64(0) >> n), ^uint64(0) << (128 - n)} +} + +// isZero reports whether u == 0. +// +// It's faster than u == (uint128{}) because the compiler (as of Go +// 1.15/1.16b1) doesn't do this trick and instead inserts a branch in +// its eq alg's generated code. +func (u uint128) isZero() bool { return u.hi|u.lo == 0 } + +// and returns the bitwise AND of u and m (u&m). +func (u uint128) and(m uint128) uint128 { + return uint128{u.hi & m.hi, u.lo & m.lo} +} + +// xor returns the bitwise XOR of u and m (u^m). +func (u uint128) xor(m uint128) uint128 { + return uint128{u.hi ^ m.hi, u.lo ^ m.lo} +} + +// or returns the bitwise OR of u and m (u|m). +func (u uint128) or(m uint128) uint128 { + return uint128{u.hi | m.hi, u.lo | m.lo} +} + +// not returns the bitwise NOT of u. +func (u uint128) not() uint128 { + return uint128{^u.hi, ^u.lo} +} + +// subOne returns u - 1. +func (u uint128) subOne() uint128 { + lo, borrow := bits.Sub64(u.lo, 1, 0) + return uint128{u.hi - borrow, lo} +} + +// addOne returns u + 1. +func (u uint128) addOne() uint128 { + lo, carry := bits.Add64(u.lo, 1, 0) + return uint128{u.hi + carry, lo} +} + +func u64CommonPrefixLen(a, b uint64) uint8 { + return uint8(bits.LeadingZeros64(a ^ b)) +} + +func (u uint128) commonPrefixLen(v uint128) (n uint8) { + if n = u64CommonPrefixLen(u.hi, v.hi); n == 64 { + n += u64CommonPrefixLen(u.lo, v.lo) + } + return +} + +// halves returns the two uint64 halves of the uint128. +// +// Logically, think of it as returning two uint64s. +// It only returns pointers for inlining reasons on 32-bit platforms. +func (u *uint128) halves() [2]*uint64 { + return [2]*uint64{&u.hi, &u.lo} +} + +// bitsSetFrom returns a copy of u with the given bit +// and all subsequent ones set. +func (u uint128) bitsSetFrom(bit uint8) uint128 { + return u.or(mask6(int(bit)).not()) +} + +// bitsClearedFrom returns a copy of u with the given bit +// and all subsequent ones cleared. +func (u uint128) bitsClearedFrom(bit uint8) uint128 { + return u.and(mask6(int(bit))) +} diff --git a/src/net/netip/uint128_test.go b/src/net/netip/uint128_test.go new file mode 100644 index 0000000000..dd1ae0ec79 --- /dev/null +++ b/src/net/netip/uint128_test.go @@ -0,0 +1,89 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package netip + +import ( + "testing" +) + +func TestUint128AddSub(t *testing.T) { + const add1 = 1 + const sub1 = -1 + tests := []struct { + in uint128 + op int // +1 or -1 to add vs subtract + want uint128 + }{ + {uint128{0, 0}, add1, uint128{0, 1}}, + {uint128{0, 1}, add1, uint128{0, 2}}, + {uint128{1, 0}, add1, uint128{1, 1}}, + {uint128{0, ^uint64(0)}, add1, uint128{1, 0}}, + {uint128{^uint64(0), ^uint64(0)}, add1, uint128{0, 0}}, + + {uint128{0, 0}, sub1, uint128{^uint64(0), ^uint64(0)}}, + {uint128{0, 1}, sub1, uint128{0, 0}}, + {uint128{0, 2}, sub1, uint128{0, 1}}, + {uint128{1, 0}, sub1, uint128{0, ^uint64(0)}}, + {uint128{1, 1}, sub1, uint128{1, 0}}, + } + for _, tt := range tests { + var got uint128 + switch tt.op { + case add1: + got = tt.in.addOne() + case sub1: + got = tt.in.subOne() + default: + panic("bogus op") + } + if got != tt.want { + t.Errorf("%v add %d = %v; want %v", tt.in, tt.op, got, tt.want) + } + } +} + +func TestBitsSetFrom(t *testing.T) { + tests := []struct { + bit uint8 + want uint128 + }{ + {0, uint128{^uint64(0), ^uint64(0)}}, + {1, uint128{^uint64(0) >> 1, ^uint64(0)}}, + {63, uint128{1, ^uint64(0)}}, + {64, uint128{0, ^uint64(0)}}, + {65, uint128{0, ^uint64(0) >> 1}}, + {127, uint128{0, 1}}, + {128, uint128{0, 0}}, + } + for _, tt := range tests { + var zero uint128 + got := zero.bitsSetFrom(tt.bit) + if got != tt.want { + t.Errorf("0.bitsSetFrom(%d) = %064b want %064b", tt.bit, got, tt.want) + } + } +} + +func TestBitsClearedFrom(t *testing.T) { + tests := []struct { + bit uint8 + want uint128 + }{ + {0, uint128{0, 0}}, + {1, uint128{1 << 63, 0}}, + {63, uint128{^uint64(0) &^ 1, 0}}, + {64, uint128{^uint64(0), 0}}, + {65, uint128{^uint64(0), 1 << 63}}, + {127, uint128{^uint64(0), ^uint64(0) &^ 1}}, + {128, uint128{^uint64(0), ^uint64(0)}}, + } + for _, tt := range tests { + ones := uint128{^uint64(0), ^uint64(0)} + got := ones.bitsClearedFrom(tt.bit) + if got != tt.want { + t.Errorf("ones.bitsClearedFrom(%d) = %064b want %064b", tt.bit, got, tt.want) + } + } +} diff --git a/src/net/parse.go b/src/net/parse.go index 0d7cce12e6..ee2890fe2c 100644 --- a/src/net/parse.go +++ b/src/net/parse.go @@ -341,26 +341,3 @@ func readFull(r io.Reader) (all []byte, err error) { } } } - -// goDebugString returns the value of the named GODEBUG key. -// GODEBUG is of the form "key=val,key2=val2" -func goDebugString(key string) string { - s := os.Getenv("GODEBUG") - for i := 0; i < len(s)-len(key)-1; i++ { - if i > 0 && s[i-1] != ',' { - continue - } - afterKey := s[i+len(key):] - if afterKey[0] != '=' || s[i:i+len(key)] != key { - continue - } - val := afterKey[1:] - for i, b := range val { - if b == ',' { - return val[:i] - } - } - return val - } - return "" -} diff --git a/src/net/parse_test.go b/src/net/parse_test.go index c5f8bfd198..97716d769a 100644 --- a/src/net/parse_test.go +++ b/src/net/parse_test.go @@ -51,33 +51,6 @@ func TestReadLine(t *testing.T) { } } -func TestGoDebugString(t *testing.T) { - defer os.Setenv("GODEBUG", os.Getenv("GODEBUG")) - tests := []struct { - godebug string - key string - want string - }{ - {"", "foo", ""}, - {"foo=", "foo", ""}, - {"foo=bar", "foo", "bar"}, - {"foo=bar,", "foo", "bar"}, - {"foo,foo=bar,", "foo", "bar"}, - {"foo1=bar,foo=bar,", "foo", "bar"}, - {"foo=bar,foo=bar,", "foo", "bar"}, - {"foo=", "foo", ""}, - {"foo", "foo", ""}, - {",foo", "foo", ""}, - {"foo=bar,baz", "loooooooong", ""}, - } - for _, tt := range tests { - os.Setenv("GODEBUG", tt.godebug) - if got := goDebugString(tt.key); got != tt.want { - t.Errorf("for %q, goDebugString(%q) = %q; want %q", tt.godebug, tt.key, got, tt.want) - } - } -} - func TestDtoi(t *testing.T) { for _, tt := range []struct { in string diff --git a/src/net/tcpsock.go b/src/net/tcpsock.go index 19a90143f3..fddb018aab 100644 --- a/src/net/tcpsock.go +++ b/src/net/tcpsock.go @@ -8,6 +8,7 @@ import ( "context" "internal/itoa" "io" + "net/netip" "os" "syscall" "time" @@ -23,6 +24,20 @@ type TCPAddr struct { Zone string // IPv6 scoped addressing zone } +// AddrPort returns the TCPAddr a as a netip.AddrPort. +// +// If a.Port does not fit in a uint16, it's silently truncated. +// +// If a is nil, a zero value is returned. +func (a *TCPAddr) AddrPort() netip.AddrPort { + if a == nil { + return netip.AddrPort{} + } + na, _ := netip.AddrFromSlice(a.IP) + na = na.WithZone(a.Zone) + return netip.AddrPortFrom(na, uint16(a.Port)) +} + // Network returns the address's network name, "tcp". func (a *TCPAddr) Network() string { return "tcp" } diff --git a/src/net/udpsock.go b/src/net/udpsock.go index 70f2ce226a..95ffa85939 100644 --- a/src/net/udpsock.go +++ b/src/net/udpsock.go @@ -7,6 +7,7 @@ package net import ( "context" "internal/itoa" + "net/netip" "syscall" ) @@ -26,6 +27,20 @@ type UDPAddr struct { Zone string // IPv6 scoped addressing zone } +// AddrPort returns the UDPAddr a as a netip.AddrPort. +// +// If a.Port does not fit in a uint16, it's silently truncated. +// +// If a is nil, a zero value is returned. +func (a *UDPAddr) AddrPort() netip.AddrPort { + if a == nil { + return netip.AddrPort{} + } + na, _ := netip.AddrFromSlice(a.IP) + na = na.WithZone(a.Zone) + return netip.AddrPortFrom(na, uint16(a.Port)) +} + // Network returns the address's network name, "udp". func (a *UDPAddr) Network() string { return "udp" } @@ -84,6 +99,21 @@ func ResolveUDPAddr(network, address string) (*UDPAddr, error) { return addrs.forResolve(network, address).(*UDPAddr), nil } +// UDPAddrFromAddrPort returns addr as a UDPAddr. +// +// If addr is not valid, it returns nil. +func UDPAddrFromAddrPort(addr netip.AddrPort) *UDPAddr { + if !addr.IsValid() { + return nil + } + ip16 := addr.Addr().As16() + return &UDPAddr{ + IP: IP(ip16[:]), + Zone: addr.Addr().Zone(), + Port: int(addr.Port()), + } +} + // UDPConn is the implementation of the Conn and PacketConn interfaces // for UDP network connections. type UDPConn struct { @@ -148,6 +178,18 @@ func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, return } +// ReadMsgUDPAddrPort is like ReadMsgUDP but returns an netip.AddrPort instead of a UDPAddr. +func (c *UDPConn) ReadMsgUDPAddrPort(b, oob []byte) (n, oobn, flags int, addr netip.AddrPort, err error) { + // TODO(bradfitz): make this efficient, making the internal net package + // type throughout be netip.Addr and only converting to the net.IP slice + // version at the edge. But for now (2021-10-20), this is a wrapper around + // the old way. + var ua *UDPAddr + n, oobn, flags, ua, err = c.ReadMsgUDP(b, oob) + addr = ua.AddrPort() + return +} + // WriteToUDP acts like WriteTo but takes a UDPAddr. func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) { if !c.ok() { @@ -160,6 +202,15 @@ func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) { return n, err } +// WriteToUDPAddrPort acts like WriteTo but takes a netip.AddrPort. +func (c *UDPConn) WriteToUDPAddrPort(b []byte, addr netip.AddrPort) (int, error) { + // TODO(bradfitz): make this efficient, making the internal net package + // type throughout be netip.Addr and only converting to the net.IP slice + // version at the edge. But for now (2021-10-20), this is a wrapper around + // the old way. + return c.WriteToUDP(b, UDPAddrFromAddrPort(addr)) +} + // WriteTo implements the PacketConn WriteTo method. func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) { if !c.ok() { @@ -195,6 +246,15 @@ func (c *UDPConn) WriteMsgUDP(b, oob []byte, addr *UDPAddr) (n, oobn int, err er return } +// WriteMsgUDPAddrPort is like WriteMsgUDP but takes a netip.AddrPort instead of a UDPAddr. +func (c *UDPConn) WriteMsgUDPAddrPort(b, oob []byte, addr netip.AddrPort) (n, oobn int, err error) { + // TODO(bradfitz): make this efficient, making the internal net package + // type throughout be netip.Addr and only converting to the net.IP slice + // version at the edge. But for now (2021-10-20), this is a wrapper around + // the old way. + return c.WriteMsgUDP(b, oob, UDPAddrFromAddrPort(addr)) +} + func newUDPConn(fd *netFD) *UDPConn { return &UDPConn{conn{fd}} } // DialUDP acts like Dial for UDP networks. diff --git a/src/strings/compare.go b/src/strings/compare.go index 1fe6b8d89a..2bd4a243db 100644 --- a/src/strings/compare.go +++ b/src/strings/compare.go @@ -5,7 +5,7 @@ package strings // Compare returns an integer comparing two strings lexicographically. -// The result will be 0 if a==b, -1 if a < b, and +1 if a > b. +// The result will be 0 if a == b, -1 if a < b, and +1 if a > b. // // Compare is included only for symmetry with package bytes. // It is usually clearer and always faster to use the built-in -- GitLab From a45457df82263c292e2c66c152a12b5df0f27f15 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Mon, 1 Nov 2021 02:04:13 +0700 Subject: [PATCH 1864/2500] cmd/compile: fix panic when refer to method of imported instantiated type In case of reference to method call of an imported fully-instantiated type, nameNode.Func will be nil causes checkFetchBody panic. To fix this, make sure checkFetchBody is only called when Func is not nil. Fixes #49246 Change-Id: I32e9208385a86d4600d8ebf6f5efd8fca571ea16 Reviewed-on: https://go-review.googlesource.com/c/go/+/360056 Trust: Cuong Manh Le Trust: Dan Scales Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 15 +++++++++++++-- test/typeparam/issue49246.dir/a.go | 20 ++++++++++++++++++++ test/typeparam/issue49246.dir/b.go | 9 +++++++++ test/typeparam/issue49246.go | 7 +++++++ 4 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 test/typeparam/issue49246.dir/a.go create mode 100644 test/typeparam/issue49246.dir/b.go create mode 100644 test/typeparam/issue49246.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 56010a356e..74281bc479 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -624,7 +624,7 @@ func (g *genInst) getDictOrSubdict(declInfo *instInfo, n ir.Node, nameNode *ir.N // yet. If so, it imports the body. func checkFetchBody(nameNode *ir.Name) { if nameNode.Func.Body == nil && nameNode.Func.Inl != nil { - // If there is no body yet but Func.Inl exists, then we can can + // If there is no body yet but Func.Inl exists, then we can // import the whole generic body. assert(nameNode.Func.Inl.Cost == 1 && nameNode.Sym().Pkg != types.LocalPkg) typecheck.ImportBody(nameNode.Func) @@ -638,7 +638,18 @@ func checkFetchBody(nameNode *ir.Name) { // with the type arguments shapes. If the instantiated function is not already // cached, then it calls genericSubst to create the new instantiation. func (g *genInst) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMeth bool) *instInfo { - checkFetchBody(nameNode) + if nameNode.Func == nil { + // If nameNode.Func is nil, this must be a reference to a method of + // an imported instantiated type. We will have already called + // g.instantiateMethods() on the fully-instantiated type, so + // g.instInfoMap[sym] will be non-nil below. + rcvr := nameNode.Type().Recv() + if rcvr == nil || !deref(rcvr.Type).IsFullyInstantiated() { + base.FatalfAt(nameNode.Pos(), "Unexpected function instantiation %v with no body", nameNode) + } + } else { + checkFetchBody(nameNode) + } // Convert any non-shape type arguments to their shape, so we can reduce the // number of instantiations we have to generate. You can actually have a mix diff --git a/test/typeparam/issue49246.dir/a.go b/test/typeparam/issue49246.dir/a.go new file mode 100644 index 0000000000..97459ee748 --- /dev/null +++ b/test/typeparam/issue49246.dir/a.go @@ -0,0 +1,20 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type R[T any] struct{ v T } + +func (r R[T]) Self() R[T] { return R[T]{} } + +type Fn[T any] func() R[T] + +func X() (r R[int]) { return r.Self() } + +func Y[T any](a Fn[T]) Fn[int] { + return func() (r R[int]) { + // No crash: return R[int]{} + return r.Self() + } +} diff --git a/test/typeparam/issue49246.dir/b.go b/test/typeparam/issue49246.dir/b.go new file mode 100644 index 0000000000..5141b72fd4 --- /dev/null +++ b/test/typeparam/issue49246.dir/b.go @@ -0,0 +1,9 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package b + +import "./a" + +func Crash() { a.Y(a.X)() } diff --git a/test/typeparam/issue49246.go b/test/typeparam/issue49246.go new file mode 100644 index 0000000000..87b4ff46c1 --- /dev/null +++ b/test/typeparam/issue49246.go @@ -0,0 +1,7 @@ +// compiledir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From 926856542fd01ae2f8c05466338a139f2fdfee85 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 1 Nov 2021 17:28:19 -0700 Subject: [PATCH 1865/2500] syscall,internal/poll: copy arrays by assignment instead of looping golang.org/x/sys contains similar code and also needs updating. Change-Id: Id00177397639075d4792eb253829d8042941b70c Reviewed-on: https://go-review.googlesource.com/c/go/+/360602 Trust: Josh Bleecher Snyder Trust: Brad Fitzpatrick Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/internal/poll/fd_windows.go | 8 ++------ src/syscall/syscall_aix.go | 16 ++++------------ src/syscall/syscall_bsd.go | 24 ++++++------------------ src/syscall/syscall_linux.go | 24 ++++++------------------ src/syscall/syscall_solaris.go | 16 ++++------------ src/syscall/syscall_windows.go | 16 ++++------------ 6 files changed, 26 insertions(+), 78 deletions(-) diff --git a/src/internal/poll/fd_windows.go b/src/internal/poll/fd_windows.go index 48fcdf306c..d883cd1ecc 100644 --- a/src/internal/poll/fd_windows.go +++ b/src/internal/poll/fd_windows.go @@ -1102,9 +1102,7 @@ func sockaddrToRaw(sa syscall.Sockaddr) (unsafe.Pointer, int32, error) { p := (*[2]byte)(unsafe.Pointer(&raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) - for i := 0; i < len(sa.Addr); i++ { - raw.Addr[i] = sa.Addr[i] - } + raw.Addr = sa.Addr return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw)), nil case *syscall.SockaddrInet6: var raw syscall.RawSockaddrInet6 @@ -1113,9 +1111,7 @@ func sockaddrToRaw(sa syscall.Sockaddr) (unsafe.Pointer, int32, error) { p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) raw.Scope_id = sa.ZoneId - for i := 0; i < len(sa.Addr); i++ { - raw.Addr[i] = sa.Addr[i] - } + raw.Addr = sa.Addr return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw)), nil default: return nil, 0, syscall.EWINDOWS diff --git a/src/syscall/syscall_aix.go b/src/syscall/syscall_aix.go index 20e77ac875..f3b160cae4 100644 --- a/src/syscall/syscall_aix.go +++ b/src/syscall/syscall_aix.go @@ -255,9 +255,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil } @@ -270,9 +268,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) sa.raw.Scope_id = sa.ZoneId - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil } @@ -443,9 +439,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { sa := new(SockaddrInet4) p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil case AF_INET6: @@ -453,9 +447,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { sa := new(SockaddrInet6) p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil } return nil, EAFNOSUPPORT diff --git a/src/syscall/syscall_bsd.go b/src/syscall/syscall_bsd.go index ebe99ff230..8945661300 100644 --- a/src/syscall/syscall_bsd.go +++ b/src/syscall/syscall_bsd.go @@ -167,9 +167,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil } @@ -183,9 +181,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) sa.raw.Scope_id = sa.ZoneId - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil } @@ -214,9 +210,7 @@ func (sa *SockaddrDatalink) sockaddr() (unsafe.Pointer, _Socklen, error) { sa.raw.Nlen = sa.Nlen sa.raw.Alen = sa.Alen sa.raw.Slen = sa.Slen - for i := 0; i < len(sa.raw.Data); i++ { - sa.raw.Data[i] = sa.Data[i] - } + sa.raw.Data = sa.Data return unsafe.Pointer(&sa.raw), SizeofSockaddrDatalink, nil } @@ -232,9 +226,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { sa.Nlen = pp.Nlen sa.Alen = pp.Alen sa.Slen = pp.Slen - for i := 0; i < len(sa.Data); i++ { - sa.Data[i] = pp.Data[i] - } + sa.Data = pp.Data return sa, nil case AF_UNIX: @@ -266,9 +258,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { sa := new(SockaddrInet4) p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil case AF_INET6: @@ -277,9 +267,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) sa.ZoneId = pp.Scope_id - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil } return nil, EAFNOSUPPORT diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go index f02fa45a89..1c6033bbab 100644 --- a/src/syscall/syscall_linux.go +++ b/src/syscall/syscall_linux.go @@ -393,9 +393,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil } @@ -408,9 +406,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) sa.raw.Scope_id = sa.ZoneId - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil } @@ -461,9 +457,7 @@ func (sa *SockaddrLinklayer) sockaddr() (unsafe.Pointer, _Socklen, error) { sa.raw.Hatype = sa.Hatype sa.raw.Pkttype = sa.Pkttype sa.raw.Halen = sa.Halen - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrLinklayer, nil } @@ -502,9 +496,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { sa.Hatype = pp.Hatype sa.Pkttype = pp.Pkttype sa.Halen = pp.Halen - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil case AF_UNIX: @@ -537,9 +529,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { sa := new(SockaddrInet4) p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil case AF_INET6: @@ -548,9 +538,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) sa.ZoneId = pp.Scope_id - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil } return nil, EAFNOSUPPORT diff --git a/src/syscall/syscall_solaris.go b/src/syscall/syscall_solaris.go index dedfbd03c0..13616fca9d 100644 --- a/src/syscall/syscall_solaris.go +++ b/src/syscall/syscall_solaris.go @@ -69,9 +69,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil } @@ -84,9 +82,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) sa.raw.Scope_id = sa.ZoneId - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil } @@ -304,9 +300,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { sa := new(SockaddrInet4) p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil case AF_INET6: @@ -315,9 +309,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) sa.ZoneId = pp.Scope_id - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil } return nil, EAFNOSUPPORT diff --git a/src/syscall/syscall_windows.go b/src/syscall/syscall_windows.go index d4e51e541d..a8a78b9ef8 100644 --- a/src/syscall/syscall_windows.go +++ b/src/syscall/syscall_windows.go @@ -738,9 +738,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, int32, error) { p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil } @@ -760,9 +758,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, int32, error) { p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) sa.raw.Scope_id = sa.ZoneId - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil } @@ -835,9 +831,7 @@ func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) { sa := new(SockaddrInet4) p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil case AF_INET6: @@ -846,9 +840,7 @@ func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) { p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) sa.ZoneId = pp.Scope_id - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil } return nil, EAFNOSUPPORT -- GitLab From 65f34786336201d99291e45d1631339b20c09e06 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 1 Nov 2021 17:27:09 -0700 Subject: [PATCH 1866/2500] encoding: simplify some code Change-Id: I63aac663da4ce7bdd198d385f87929c74f6a5cf8 Reviewed-on: https://go-review.googlesource.com/c/go/+/360601 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/encoding/ascii85/ascii85.go | 4 +--- src/encoding/base32/base32.go | 4 +--- src/encoding/base64/base64.go | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/encoding/ascii85/ascii85.go b/src/encoding/ascii85/ascii85.go index d42eb0ab00..f1f7af863c 100644 --- a/src/encoding/ascii85/ascii85.go +++ b/src/encoding/ascii85/ascii85.go @@ -142,9 +142,7 @@ func (e *encoder) Write(p []byte) (n int, err error) { } // Trailing fringe. - for i := 0; i < len(p); i++ { - e.buf[i] = p[i] - } + copy(e.buf[:], p) e.nbuf = len(p) n += len(p) return diff --git a/src/encoding/base32/base32.go b/src/encoding/base32/base32.go index 2f7d3637e5..3feea9ba47 100644 --- a/src/encoding/base32/base32.go +++ b/src/encoding/base32/base32.go @@ -221,9 +221,7 @@ func (e *encoder) Write(p []byte) (n int, err error) { } // Trailing fringe. - for i := 0; i < len(p); i++ { - e.buf[i] = p[i] - } + copy(e.buf[:], p) e.nbuf = len(p) n += len(p) return diff --git a/src/encoding/base64/base64.go b/src/encoding/base64/base64.go index 0c33f8e5f8..4a3e590649 100644 --- a/src/encoding/base64/base64.go +++ b/src/encoding/base64/base64.go @@ -229,9 +229,7 @@ func (e *encoder) Write(p []byte) (n int, err error) { } // Trailing fringe. - for i := 0; i < len(p); i++ { - e.buf[i] = p[i] - } + copy(e.buf[:], p) e.nbuf = len(p) n += len(p) return -- GitLab From b0472aa990dfa9fb4ffe49b5af6f3d744d81ba6e Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 1 Nov 2021 14:05:14 -0700 Subject: [PATCH 1867/2500] net: add BenchmarkReadWriteMsgUDPAddrPort The main item of interest here is the allocs. BenchmarkReadWriteMsgUDPAddrPort-8 195920 6450 ns/op 176 B/op 5 allocs/op Change-Id: I358bd18888ce254b6c6d5d5c920e6d22ce5a2ef4 Reviewed-on: https://go-review.googlesource.com/c/go/+/360595 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/net/udpsock_test.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/net/udpsock_test.go b/src/net/udpsock_test.go index 0f8f463100..74e449c888 100644 --- a/src/net/udpsock_test.go +++ b/src/net/udpsock_test.go @@ -474,6 +474,27 @@ func TestUDPReadTimeout(t *testing.T) { } } +func BenchmarkReadWriteMsgUDPAddrPort(b *testing.B) { + conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) + if err != nil { + b.Fatal(err) + } + addr := conn.LocalAddr().(*UDPAddr).AddrPort() + buf := make([]byte, 8) + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _, _, err := conn.WriteMsgUDPAddrPort(buf, nil, addr) + if err != nil { + b.Fatal(err) + } + _, _, _, _, err = conn.ReadMsgUDPAddrPort(buf, nil) + if err != nil { + b.Fatal(err) + } + } +} + func BenchmarkWriteToReadFromUDP(b *testing.B) { conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) if err != nil { -- GitLab From 3c61cb3dcd888fdef1c7456be144a1c4a44272a7 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 1 Nov 2021 12:44:43 -0700 Subject: [PATCH 1868/2500] net: optimize ReadMsgUDPAddrPort MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of implementing ReadMsgUDPAddrPort in terms of ReadMsgUDP, do it the other way around. This keeps the code minimal while still avoiding allocs. We could also rearrange ReadMsgUDP to be mid-stack inlined to avoid allocating the *UDPAddr, but anyone who's trying to eliminate allocs should use ReadMsgUDPAddrPort instead anyway, because ReadMsgUDP will always allocate at least once (the IP slice). name old time/op new time/op delta ReadWriteMsgUDPAddrPort-8 5.26µs ± 3% 5.29µs ± 6% ~ (p=0.429 n=12+13) name old alloc/op new alloc/op delta ReadWriteMsgUDPAddrPort-8 176B ± 0% 128B ± 0% -27.27% (p=0.000 n=15+15) name old allocs/op new allocs/op delta ReadWriteMsgUDPAddrPort-8 5.00 ± 0% 4.00 ± 0% -20.00% (p=0.000 n=15+15) Change-Id: I15228cb4ec4f13f2f390407b6c62c44c228e7201 Reviewed-on: https://go-review.googlesource.com/c/go/+/360596 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/net/udpsock.go | 22 +++++++++------------- src/net/udpsock_plan9.go | 5 +++-- src/net/udpsock_posix.go | 9 ++++++--- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/net/udpsock.go b/src/net/udpsock.go index 95ffa85939..8c97ca7537 100644 --- a/src/net/udpsock.go +++ b/src/net/udpsock.go @@ -168,8 +168,16 @@ func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) { // The packages golang.org/x/net/ipv4 and golang.org/x/net/ipv6 can be // used to manipulate IP-level socket options in oob. func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) { + var ap netip.AddrPort + n, oobn, flags, ap, err = c.ReadMsgUDPAddrPort(b, oob) + addr = UDPAddrFromAddrPort(ap) + return +} + +// ReadMsgUDPAddrPort is like ReadMsgUDP but returns an netip.AddrPort instead of a UDPAddr. +func (c *UDPConn) ReadMsgUDPAddrPort(b, oob []byte) (n, oobn, flags int, addr netip.AddrPort, err error) { if !c.ok() { - return 0, 0, 0, nil, syscall.EINVAL + return 0, 0, 0, netip.AddrPort{}, syscall.EINVAL } n, oobn, flags, addr, err = c.readMsg(b, oob) if err != nil { @@ -178,18 +186,6 @@ func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, return } -// ReadMsgUDPAddrPort is like ReadMsgUDP but returns an netip.AddrPort instead of a UDPAddr. -func (c *UDPConn) ReadMsgUDPAddrPort(b, oob []byte) (n, oobn, flags int, addr netip.AddrPort, err error) { - // TODO(bradfitz): make this efficient, making the internal net package - // type throughout be netip.Addr and only converting to the net.IP slice - // version at the edge. But for now (2021-10-20), this is a wrapper around - // the old way. - var ua *UDPAddr - n, oobn, flags, ua, err = c.ReadMsgUDP(b, oob) - addr = ua.AddrPort() - return -} - // WriteToUDP acts like WriteTo but takes a UDPAddr. func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) { if !c.ok() { diff --git a/src/net/udpsock_plan9.go b/src/net/udpsock_plan9.go index 1df293d1db..c18af2356d 100644 --- a/src/net/udpsock_plan9.go +++ b/src/net/udpsock_plan9.go @@ -7,6 +7,7 @@ package net import ( "context" "errors" + "net/netip" "os" "syscall" ) @@ -28,8 +29,8 @@ func (c *UDPConn) readFrom(b []byte, addr *UDPAddr) (int, *UDPAddr, error) { return n, addr, nil } -func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) { - return 0, 0, 0, nil, syscall.EPLAN9 +func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr netip.AddrPort, err error) { + return 0, 0, 0, netip.AddrPort{}, syscall.EPLAN9 } func (c *UDPConn) writeTo(b []byte, addr *UDPAddr) (int, error) { diff --git a/src/net/udpsock_posix.go b/src/net/udpsock_posix.go index c3f7ddb77e..b20025140f 100644 --- a/src/net/udpsock_posix.go +++ b/src/net/udpsock_posix.go @@ -8,6 +8,7 @@ package net import ( "context" + "net/netip" "syscall" ) @@ -68,14 +69,16 @@ func (c *UDPConn) readFrom(b []byte, addr *UDPAddr) (int, *UDPAddr, error) { return n, addr, err } -func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) { +func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr netip.AddrPort, err error) { var sa syscall.Sockaddr n, oobn, flags, sa, err = c.fd.readMsg(b, oob, 0) switch sa := sa.(type) { case *syscall.SockaddrInet4: - addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port} + ip := netip.AddrFrom4(sa.Addr) + addr = netip.AddrPortFrom(ip, uint16(sa.Port)) case *syscall.SockaddrInet6: - addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneCache.name(int(sa.ZoneId))} + ip := netip.AddrFrom16(sa.Addr).WithZone(zoneCache.name(int(sa.ZoneId))) + addr = netip.AddrPortFrom(ip, uint16(sa.Port)) } return } -- GitLab From 6f1e9a9c21aec8531db40dbf61ad10fe77d7bee5 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 1 Nov 2021 13:34:08 -0700 Subject: [PATCH 1869/2500] net: optimize WriteMsgUDPAddrPort MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is one step towards optimizing WriteMsgUDPAddrPort. Further steps remain, namely to avoid the syscall.Sockaddr interface, as we do for UDPConn.WriteToUDP and UDPConn.ReadFromUDP. A previous change optimized ReadMsgUDPAddrPort by having ReadMsgUDP call ReadMsgUDPAddrPort rather than the other way around. This change does not implement WriteMsgUDP in terms of WriteMsgUDPAddrPort, because a few layers deep, on posix platforms only (in ipToSockaddrInet4 and ipToSockaddrInet6), is special handling of zero-length IP addresses and IPv4zero. It treats IP(nil) as equivalent to 0.0.0.0 or ::, and 0.0.0.0 as equivalent to :: in an IPv6 context. Based on the comments, I suspect that this treatment was intended for the Listen* API, not the Write* API, but it affects both, and I am nervous about changing the behavior for Write*. The netip package doesn't have a way to represent a "zero-length IP address" as distinct from an invalid IP address (which is a good thing), so to implement WriteMsgUDP using WriteMsgUDPAddrPort, we would have to duplicate this special handling at the start of WriteMsgUDP. But this handling depends on whether the UDPConn is an IPv4 or an IPv6 conn, which is also platform-specific information. As a result, every attempt I made to implement WriteMsgUDP using WriteMsgUDPAddrPort while preserving behavior ended up being considerably worse than copy/paste/modify. This does mean that WriteMsgUDP and WriteMsgUDPAddrPort will have different behavior in these cases. name old time/op new time/op delta ReadWriteMsgUDPAddrPort-8 5.29µs ± 6% 5.02µs ± 7% -5.14% (p=0.000 n=13+15) name old alloc/op new alloc/op delta ReadWriteMsgUDPAddrPort-8 128B ± 0% 64B ± 0% -50.00% (p=0.000 n=15+15) name old allocs/op new allocs/op delta ReadWriteMsgUDPAddrPort-8 4.00 ± 0% 2.00 ± 0% -50.00% (p=0.000 n=15+15) Change-Id: Ia78eb49734f4301d7772dfdbb5a87e4d303a9f7a Reviewed-on: https://go-review.googlesource.com/c/go/+/360597 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/net/ipsock_posix.go | 30 ++++++++++++++++++++++++++++++ src/net/udpsock.go | 20 +++++++++++++++----- src/net/udpsock_plan9.go | 4 ++++ src/net/udpsock_posix.go | 28 ++++++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 5 deletions(-) diff --git a/src/net/ipsock_posix.go b/src/net/ipsock_posix.go index 0910f63d48..e433e8a91c 100644 --- a/src/net/ipsock_posix.go +++ b/src/net/ipsock_posix.go @@ -9,6 +9,7 @@ package net import ( "context" "internal/poll" + "net/netip" "runtime" "syscall" ) @@ -196,3 +197,32 @@ func ipToSockaddr(family int, ip IP, port int, zone string) (syscall.Sockaddr, e } return nil, &AddrError{Err: "invalid address family", Addr: ip.String()} } + +func addrPortToSockaddrInet4(ap netip.AddrPort) (syscall.SockaddrInet4, error) { + // ipToSockaddrInet4 has special handling here for zero length slices. + // We do not, because netip has no concept of a generic zero IP address. + addr := ap.Addr() + if !addr.Is4() { + return syscall.SockaddrInet4{}, &AddrError{Err: "non-IPv4 address", Addr: addr.String()} + } + sa := syscall.SockaddrInet4{ + Addr: addr.As4(), + Port: int(ap.Port()), + } + return sa, nil +} + +func addrPortToSockaddrInet6(ap netip.AddrPort) (syscall.SockaddrInet6, error) { + // ipToSockaddrInet6 has special handling here for zero length slices. + // We do not, because netip has no concept of a generic zero IP address. + addr := ap.Addr() + if !addr.Is6() { + return syscall.SockaddrInet6{}, &AddrError{Err: "non-IPv6 address", Addr: addr.String()} + } + sa := syscall.SockaddrInet6{ + Addr: addr.As16(), + Port: int(ap.Port()), + ZoneId: uint32(zoneCache.index(addr.Zone())), + } + return sa, nil +} diff --git a/src/net/udpsock.go b/src/net/udpsock.go index 8c97ca7537..0d563fd4f5 100644 --- a/src/net/udpsock.go +++ b/src/net/udpsock.go @@ -114,6 +114,13 @@ func UDPAddrFromAddrPort(addr netip.AddrPort) *UDPAddr { } } +// An addrPortUDPAddr is a netip.AddrPort-based UDP address that satisfies the Addr interface. +type addrPortUDPAddr struct { + netip.AddrPort +} + +func (addrPortUDPAddr) Network() string { return "udp" } + // UDPConn is the implementation of the Conn and PacketConn interfaces // for UDP network connections. type UDPConn struct { @@ -244,11 +251,14 @@ func (c *UDPConn) WriteMsgUDP(b, oob []byte, addr *UDPAddr) (n, oobn int, err er // WriteMsgUDPAddrPort is like WriteMsgUDP but takes a netip.AddrPort instead of a UDPAddr. func (c *UDPConn) WriteMsgUDPAddrPort(b, oob []byte, addr netip.AddrPort) (n, oobn int, err error) { - // TODO(bradfitz): make this efficient, making the internal net package - // type throughout be netip.Addr and only converting to the net.IP slice - // version at the edge. But for now (2021-10-20), this is a wrapper around - // the old way. - return c.WriteMsgUDP(b, oob, UDPAddrFromAddrPort(addr)) + if !c.ok() { + return 0, 0, syscall.EINVAL + } + n, oobn, err = c.writeMsgAddrPort(b, oob, addr) + if err != nil { + err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addrPortUDPAddr{addr}, Err: err} + } + return } func newUDPConn(fd *netFD) *UDPConn { return &UDPConn{conn{fd}} } diff --git a/src/net/udpsock_plan9.go b/src/net/udpsock_plan9.go index c18af2356d..ac5afa2281 100644 --- a/src/net/udpsock_plan9.go +++ b/src/net/udpsock_plan9.go @@ -57,6 +57,10 @@ func (c *UDPConn) writeMsg(b, oob []byte, addr *UDPAddr) (n, oobn int, err error return 0, 0, syscall.EPLAN9 } +func (c *UDPConn) writeMsgAddrPort(b, oob []byte, addr netip.AddrPort) (n, oobn int, err error) { + return 0, 0, syscall.EPLAN9 +} + func (sd *sysDialer) dialUDP(ctx context.Context, laddr, raddr *UDPAddr) (*UDPConn, error) { fd, err := dialPlan9(ctx, sd.network, laddr, raddr) if err != nil { diff --git a/src/net/udpsock_posix.go b/src/net/udpsock_posix.go index b20025140f..646687d148 100644 --- a/src/net/udpsock_posix.go +++ b/src/net/udpsock_posix.go @@ -123,6 +123,34 @@ func (c *UDPConn) writeMsg(b, oob []byte, addr *UDPAddr) (n, oobn int, err error return c.fd.writeMsg(b, oob, sa) } +func (c *UDPConn) writeMsgAddrPort(b, oob []byte, addr netip.AddrPort) (n, oobn int, err error) { + if c.fd.isConnected && addr.IsValid() { + return 0, 0, ErrWriteToConnected + } + if !c.fd.isConnected && !addr.IsValid() { + return 0, 0, errMissingAddress + } + + switch c.fd.family { + case syscall.AF_INET: + sa, err := addrPortToSockaddrInet4(addr) + if err != nil { + return 0, 0, err + } + // TODO: Implement writeMsgInet4 to avoid allocation converting sa to an interface. + return c.fd.writeMsg(b, oob, &sa) + case syscall.AF_INET6: + sa, err := addrPortToSockaddrInet6(addr) + if err != nil { + return 0, 0, err + } + // TODO: Implement writeMsgInet6 to avoid allocation converting sa to an interface. + return c.fd.writeMsg(b, oob, &sa) + default: + return 0, 0, &AddrError{Err: "invalid address family", Addr: addr.Addr().String()} + } +} + func (sd *sysDialer) dialUDP(ctx context.Context, laddr, raddr *UDPAddr) (*UDPConn, error) { fd, err := internetSocket(ctx, sd.network, laddr, raddr, syscall.SOCK_DGRAM, 0, "dial", sd.Dialer.Control) if err != nil { -- GitLab From 6f327f7b889b81549d551ce6963067267578bd70 Mon Sep 17 00:00:00 2001 From: fanzha02 Date: Tue, 5 Jan 2021 17:52:43 +0800 Subject: [PATCH 1870/2500] runtime, syscall: add calls to asan functions Add explicit address sanitizer instrumentation to the runtime and syscall packages. The compiler does not instrument the runtime package. It does instrument the syscall package, but we need to add a couple of cases that it can't see. Refer to the implementation of the asan malloc runtime library, this patch also allocates extra memory as the redzone, around the returned memory region, and marks the redzone as unaddressable to detect the overflows or underflows. Updates #44853. Change-Id: I2753d1cc1296935a66bf521e31ce91e35fcdf798 Reviewed-on: https://go-review.googlesource.com/c/go/+/298614 Run-TryBot: Ian Lance Taylor Reviewed-by: Ian Lance Taylor Trust: fannie zhang --- src/runtime/cgo_sigaction.go | 7 +++++- src/runtime/iface.go | 7 ++++++ src/runtime/malloc.go | 44 +++++++++++++++++++++++++++++++++- src/runtime/map.go | 12 ++++++++++ src/runtime/mbarrier.go | 8 +++++++ src/runtime/mgcsweep.go | 5 +++- src/runtime/mheap.go | 6 +++++ src/runtime/mprof.go | 6 +++++ src/runtime/proc.go | 6 +++++ src/runtime/select.go | 16 +++++++++++++ src/runtime/slice.go | 10 ++++++++ src/runtime/stack.go | 6 +++++ src/runtime/string.go | 9 +++++++ src/runtime/traceback.go | 6 +++++ src/syscall/asan.go | 23 ++++++++++++++++++ src/syscall/asan0.go | 20 ++++++++++++++++ src/syscall/syscall_unix.go | 6 +++++ src/syscall/syscall_windows.go | 6 +++++ 18 files changed, 200 insertions(+), 3 deletions(-) create mode 100644 src/syscall/asan.go create mode 100644 src/syscall/asan0.go diff --git a/src/runtime/cgo_sigaction.go b/src/runtime/cgo_sigaction.go index 7e8ae28275..a2e12f0f0e 100644 --- a/src/runtime/cgo_sigaction.go +++ b/src/runtime/cgo_sigaction.go @@ -27,7 +27,9 @@ func sigaction(sig uint32, new, old *sigactiont) { if msanenabled && new != nil { msanwrite(unsafe.Pointer(new), unsafe.Sizeof(*new)) } - + if asanenabled && new != nil { + asanwrite(unsafe.Pointer(new), unsafe.Sizeof(*new)) + } if _cgo_sigaction == nil || inForkedChild { sysSigaction(sig, new, old) } else { @@ -79,6 +81,9 @@ func sigaction(sig uint32, new, old *sigactiont) { if msanenabled && old != nil { msanread(unsafe.Pointer(old), unsafe.Sizeof(*old)) } + if asanenabled && old != nil { + asanread(unsafe.Pointer(old), unsafe.Sizeof(*old)) + } } // callCgoSigaction calls the sigaction function in the runtime/cgo package diff --git a/src/runtime/iface.go b/src/runtime/iface.go index 3d1d9d6ba1..e2bec10948 100644 --- a/src/runtime/iface.go +++ b/src/runtime/iface.go @@ -325,6 +325,9 @@ func convT(t *_type, v unsafe.Pointer) unsafe.Pointer { if msanenabled { msanread(v, t.size) } + if asanenabled { + asanread(v, t.size) + } x := mallocgc(t.size, t, true) typedmemmove(t, x, v) return x @@ -337,6 +340,10 @@ func convTnoptr(t *_type, v unsafe.Pointer) unsafe.Pointer { if msanenabled { msanread(v, t.size) } + if asanenabled { + asanread(v, t.size) + } + x := mallocgc(t.size, t, false) memmove(x, v, t.size) return x diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index 8af1d96f1a..e267e2df23 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -908,6 +908,14 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { if size == 0 { return unsafe.Pointer(&zerobase) } + userSize := size + if asanenabled { + // Refer to ASAN runtime library, the malloc() function allocates extra memory, + // the redzone, around the user requested memory region. And the redzones are marked + // as unaddressable. We perform the same operations in Go to detect the overflows or + // underflows. + size += computeRZlog(size) + } if debug.malloc { if debug.sbrk != 0 { @@ -971,7 +979,7 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { mp.mallocing = 1 shouldhelpgc := false - dataSize := size + dataSize := userSize c := getMCache(mp) if c == nil { throw("mallocgc called without a P or outside bootstrapping") @@ -1138,6 +1146,17 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { msanmalloc(x, size) } + if asanenabled { + // We should only read/write the memory with the size asked by the user. + // The rest of the allocated memory should be poisoned, so that we can report + // errors when accessing poisoned memory. + // The allocated memory is larger than required userSize, it will also include + // redzone and some other padding bytes. + rzBeg := unsafe.Add(x, userSize) + asanpoison(rzBeg, size-userSize) + asanunpoison(x, userSize) + } + if rate := MemProfileRate; rate > 0 { // Note cache c only valid while m acquired; see #47302 if rate != 1 && size < c.nextSample { @@ -1514,3 +1533,26 @@ type notInHeap struct{} func (p *notInHeap) add(bytes uintptr) *notInHeap { return (*notInHeap)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + bytes)) } + +// computeRZlog computes the size of the redzone. +// Refer to the implementation of the compiler-rt. +func computeRZlog(userSize uintptr) uintptr { + switch { + case userSize <= (64 - 16): + return 16 << 0 + case userSize <= (128 - 32): + return 16 << 1 + case userSize <= (512 - 64): + return 16 << 2 + case userSize <= (4096 - 128): + return 16 << 3 + case userSize <= (1<<14)-256: + return 16 << 4 + case userSize <= (1<<15)-512: + return 16 << 5 + case userSize <= (1<<16)-1024: + return 16 << 6 + default: + return 16 << 7 + } +} diff --git a/src/runtime/map.go b/src/runtime/map.go index 985c297cd4..e91b25eaec 100644 --- a/src/runtime/map.go +++ b/src/runtime/map.go @@ -402,6 +402,9 @@ func mapaccess1(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer { if msanenabled && h != nil { msanread(key, t.key.size) } + if asanenabled && h != nil { + asanread(key, t.key.size) + } if h == nil || h.count == 0 { if t.hashMightPanic() { t.hasher(key, 0) // see issue 23734 @@ -460,6 +463,9 @@ func mapaccess2(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, bool) if msanenabled && h != nil { msanread(key, t.key.size) } + if asanenabled && h != nil { + asanread(key, t.key.size) + } if h == nil || h.count == 0 { if t.hashMightPanic() { t.hasher(key, 0) // see issue 23734 @@ -582,6 +588,9 @@ func mapassign(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer { if msanenabled { msanread(key, t.key.size) } + if asanenabled { + asanread(key, t.key.size) + } if h.flags&hashWriting != 0 { throw("concurrent map writes") } @@ -693,6 +702,9 @@ func mapdelete(t *maptype, h *hmap, key unsafe.Pointer) { if msanenabled && h != nil { msanread(key, t.key.size) } + if asanenabled && h != nil { + asanread(key, t.key.size) + } if h == nil || h.count == 0 { if t.hashMightPanic() { t.hasher(key, 0) // see issue 23734 diff --git a/src/runtime/mbarrier.go b/src/runtime/mbarrier.go index 3fd1cca42c..0f8b2af5fa 100644 --- a/src/runtime/mbarrier.go +++ b/src/runtime/mbarrier.go @@ -184,6 +184,10 @@ func reflect_typedmemmove(typ *_type, dst, src unsafe.Pointer) { msanwrite(dst, typ.size) msanread(src, typ.size) } + if asanenabled { + asanwrite(dst, typ.size) + asanread(src, typ.size) + } typedmemmove(typ, dst, src) } @@ -262,6 +266,10 @@ func typedslicecopy(typ *_type, dstPtr unsafe.Pointer, dstLen int, srcPtr unsafe msanwrite(dstPtr, uintptr(n)*typ.size) msanread(srcPtr, uintptr(n)*typ.size) } + if asanenabled { + asanwrite(dstPtr, uintptr(n)*typ.size) + asanread(srcPtr, uintptr(n)*typ.size) + } if writeBarrier.cgo { cgoCheckSliceCopy(typ, dstPtr, srcPtr, n) diff --git a/src/runtime/mgcsweep.go b/src/runtime/mgcsweep.go index b06df32b20..fdbec30cf1 100644 --- a/src/runtime/mgcsweep.go +++ b/src/runtime/mgcsweep.go @@ -563,7 +563,7 @@ func (sl *sweepLocked) sweep(preserve bool) bool { spanHasNoSpecials(s) } - if debug.allocfreetrace != 0 || debug.clobberfree != 0 || raceenabled || msanenabled { + if debug.allocfreetrace != 0 || debug.clobberfree != 0 || raceenabled || msanenabled || asanenabled { // Find all newly freed objects. This doesn't have to // efficient; allocfreetrace has massive overhead. mbits := s.markBitsForBase() @@ -583,6 +583,9 @@ func (sl *sweepLocked) sweep(preserve bool) bool { if msanenabled { msanfree(unsafe.Pointer(x), size) } + if asanenabled { + asanpoison(unsafe.Pointer(x), size) + } } mbits.advance() abits.advance() diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go index 5fd036c1b3..057ab06b1d 100644 --- a/src/runtime/mheap.go +++ b/src/runtime/mheap.go @@ -1419,6 +1419,12 @@ func (h *mheap) freeSpan(s *mspan) { bytes := s.npages << _PageShift msanfree(base, bytes) } + if asanenabled { + // Tell asan that this entire span is no longer in use. + base := unsafe.Pointer(s.base()) + bytes := s.npages << _PageShift + asanpoison(base, bytes) + } h.freeSpanLocked(s, spanAllocHeap) unlock(&h.lock) }) diff --git a/src/runtime/mprof.go b/src/runtime/mprof.go index 0e6043cf2a..b4de8f53a9 100644 --- a/src/runtime/mprof.go +++ b/src/runtime/mprof.go @@ -627,6 +627,9 @@ func record(r *MemProfileRecord, b *bucket) { if msanenabled { msanwrite(unsafe.Pointer(&r.Stack0[0]), unsafe.Sizeof(r.Stack0)) } + if asanenabled { + asanwrite(unsafe.Pointer(&r.Stack0[0]), unsafe.Sizeof(r.Stack0)) + } copy(r.Stack0[:], b.stk()) for i := int(b.nstk); i < len(r.Stack0); i++ { r.Stack0[i] = 0 @@ -680,6 +683,9 @@ func BlockProfile(p []BlockProfileRecord) (n int, ok bool) { if msanenabled { msanwrite(unsafe.Pointer(&r.Stack0[0]), unsafe.Sizeof(r.Stack0)) } + if asanenabled { + asanwrite(unsafe.Pointer(&r.Stack0[0]), unsafe.Sizeof(r.Stack0)) + } i := copy(r.Stack0[:], b.stk()) for ; i < len(r.Stack0); i++ { r.Stack0[i] = 0 diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 615f53d31f..bf5fa8e4fc 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -2233,6 +2233,9 @@ func newm1(mp *m) { if msanenabled { msanwrite(unsafe.Pointer(&ts), unsafe.Sizeof(ts)) } + if asanenabled { + asanwrite(unsafe.Pointer(&ts), unsafe.Sizeof(ts)) + } execLock.rlock() // Prevent process clone. asmcgocall(_cgo_thread_start, unsafe.Pointer(&ts)) execLock.runlock() @@ -4435,6 +4438,9 @@ retry: if msanenabled { msanmalloc(unsafe.Pointer(gp.stack.lo), gp.stack.hi-gp.stack.lo) } + if asanenabled { + asanunpoison(unsafe.Pointer(gp.stack.lo), gp.stack.hi-gp.stack.lo) + } } return gp } diff --git a/src/runtime/select.go b/src/runtime/select.go index ee1f95ffa9..e18b2f14c0 100644 --- a/src/runtime/select.go +++ b/src/runtime/select.go @@ -406,6 +406,13 @@ func selectgo(cas0 *scase, order0 *uint16, pc0 *uintptr, nsends, nrecvs int, blo msanwrite(cas.elem, c.elemtype.size) } } + if asanenabled { + if casi < nsends { + asanread(cas.elem, c.elemtype.size) + } else if cas.elem != nil { + asanwrite(cas.elem, c.elemtype.size) + } + } selunlock(scases, lockorder) goto retc @@ -421,6 +428,9 @@ bufrecv: if msanenabled && cas.elem != nil { msanwrite(cas.elem, c.elemtype.size) } + if asanenabled && cas.elem != nil { + asanwrite(cas.elem, c.elemtype.size) + } recvOK = true qp = chanbuf(c, c.recvx) if cas.elem != nil { @@ -444,6 +454,9 @@ bufsend: if msanenabled { msanread(cas.elem, c.elemtype.size) } + if asanenabled { + asanread(cas.elem, c.elemtype.size) + } typedmemmove(c.elemtype, chanbuf(c, c.sendx), cas.elem) c.sendx++ if c.sendx == c.dataqsiz { @@ -482,6 +495,9 @@ send: if msanenabled { msanread(cas.elem, c.elemtype.size) } + if asanenabled { + asanread(cas.elem, c.elemtype.size) + } send(c, sg, cas.elem, func() { selunlock(scases, lockorder) }, 2) if debugSelect { print("syncsend: cas0=", cas0, " c=", c, "\n") diff --git a/src/runtime/slice.go b/src/runtime/slice.go index aab8a598c5..ac0b7d5fef 100644 --- a/src/runtime/slice.go +++ b/src/runtime/slice.go @@ -76,6 +76,9 @@ func makeslicecopy(et *_type, tolen int, fromlen int, from unsafe.Pointer) unsaf if msanenabled { msanread(from, copymem) } + if asanenabled { + asanread(from, copymem) + } memmove(to, from, copymem) @@ -168,6 +171,9 @@ func growslice(et *_type, old slice, cap int) slice { if msanenabled { msanread(old.array, uintptr(old.len*int(et.size))) } + if asanenabled { + asanread(old.array, uintptr(old.len*int(et.size))) + } if cap < old.cap { panic(errorString("growslice: cap out of range")) @@ -311,6 +317,10 @@ func slicecopy(toPtr unsafe.Pointer, toLen int, fromPtr unsafe.Pointer, fromLen msanread(fromPtr, size) msanwrite(toPtr, size) } + if asanenabled { + asanread(fromPtr, size) + asanwrite(toPtr, size) + } if size == 1 { // common case worth about 2x to do here // TODO: is this still worth it with new memmove impl? diff --git a/src/runtime/stack.go b/src/runtime/stack.go index 8ae9c1e698..52d21e4ee4 100644 --- a/src/runtime/stack.go +++ b/src/runtime/stack.go @@ -424,6 +424,9 @@ func stackalloc(n uint32) stack { if msanenabled { msanmalloc(v, uintptr(n)) } + if asanenabled { + asanunpoison(v, uintptr(n)) + } if stackDebug >= 1 { print(" allocated ", v, "\n") } @@ -461,6 +464,9 @@ func stackfree(stk stack) { if msanenabled { msanfree(v, n) } + if asanenabled { + asanpoison(v, n) + } if n < _FixedStack<<_NumStackOrders && n < _StackCacheSize { order := uint8(0) n2 := n diff --git a/src/runtime/string.go b/src/runtime/string.go index d6990dab9a..980a9866e6 100644 --- a/src/runtime/string.go +++ b/src/runtime/string.go @@ -94,6 +94,9 @@ func slicebytetostring(buf *tmpBuf, ptr *byte, n int) (str string) { if msanenabled { msanread(unsafe.Pointer(ptr), uintptr(n)) } + if asanenabled { + asanread(unsafe.Pointer(ptr), uintptr(n)) + } if n == 1 { p := unsafe.Pointer(&staticuint64s[*ptr]) if goarch.BigEndian { @@ -158,6 +161,9 @@ func slicebytetostringtmp(ptr *byte, n int) (str string) { if msanenabled && n > 0 { msanread(unsafe.Pointer(ptr), uintptr(n)) } + if asanenabled && n > 0 { + asanread(unsafe.Pointer(ptr), uintptr(n)) + } stringStructOf(&str).str = unsafe.Pointer(ptr) stringStructOf(&str).len = n return @@ -209,6 +215,9 @@ func slicerunetostring(buf *tmpBuf, a []rune) string { if msanenabled && len(a) > 0 { msanread(unsafe.Pointer(&a[0]), uintptr(len(a))*unsafe.Sizeof(a[0])) } + if asanenabled && len(a) > 0 { + asanread(unsafe.Pointer(&a[0]), uintptr(len(a))*unsafe.Sizeof(a[0])) + } var dum [4]byte size1 := 0 for _, r := range a { diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go index 5de1abce9a..36627a6735 100644 --- a/src/runtime/traceback.go +++ b/src/runtime/traceback.go @@ -1390,6 +1390,9 @@ func callCgoSymbolizer(arg *cgoSymbolizerArg) { if msanenabled { msanwrite(unsafe.Pointer(arg), unsafe.Sizeof(cgoSymbolizerArg{})) } + if asanenabled { + asanwrite(unsafe.Pointer(arg), unsafe.Sizeof(cgoSymbolizerArg{})) + } call(cgoSymbolizer, noescape(unsafe.Pointer(arg))) } @@ -1412,5 +1415,8 @@ func cgoContextPCs(ctxt uintptr, buf []uintptr) { if msanenabled { msanwrite(unsafe.Pointer(&arg), unsafe.Sizeof(arg)) } + if asanenabled { + asanwrite(unsafe.Pointer(&arg), unsafe.Sizeof(arg)) + } call(cgoTraceback, noescape(unsafe.Pointer(&arg))) } diff --git a/src/syscall/asan.go b/src/syscall/asan.go new file mode 100644 index 0000000000..3199130211 --- /dev/null +++ b/src/syscall/asan.go @@ -0,0 +1,23 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build asan +// +build asan + +package syscall + +import ( + "runtime" + "unsafe" +) + +const asanenabled = true + +func asanRead(addr unsafe.Pointer, len int) { + runtime.ASanRead(addr, len) +} + +func asanWrite(addr unsafe.Pointer, len int) { + runtime.ASanWrite(addr, len) +} diff --git a/src/syscall/asan0.go b/src/syscall/asan0.go new file mode 100644 index 0000000000..7b69f4a64b --- /dev/null +++ b/src/syscall/asan0.go @@ -0,0 +1,20 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !asan +// +build !asan + +package syscall + +import ( + "unsafe" +) + +const asanenabled = false + +func asanRead(addr unsafe.Pointer, len int) { +} + +func asanWrite(addr unsafe.Pointer, len int) { +} diff --git a/src/syscall/syscall_unix.go b/src/syscall/syscall_unix.go index 9413db3832..5a91a023e1 100644 --- a/src/syscall/syscall_unix.go +++ b/src/syscall/syscall_unix.go @@ -197,6 +197,9 @@ func Read(fd int, p []byte) (n int, err error) { if msanenabled && n > 0 { msanWrite(unsafe.Pointer(&p[0]), n) } + if asanenabled && n > 0 { + asanWrite(unsafe.Pointer(&p[0]), n) + } return } @@ -218,6 +221,9 @@ func Write(fd int, p []byte) (n int, err error) { if msanenabled && n > 0 { msanRead(unsafe.Pointer(&p[0]), n) } + if asanenabled && n > 0 { + asanRead(unsafe.Pointer(&p[0]), n) + } return } diff --git a/src/syscall/syscall_windows.go b/src/syscall/syscall_windows.go index a8a78b9ef8..0456074d47 100644 --- a/src/syscall/syscall_windows.go +++ b/src/syscall/syscall_windows.go @@ -394,6 +394,9 @@ func Read(fd Handle, p []byte) (n int, err error) { if msanenabled && done > 0 { msanWrite(unsafe.Pointer(&p[0]), int(done)) } + if asanenabled && done > 0 { + asanWrite(unsafe.Pointer(&p[0]), int(done)) + } return int(done), nil } @@ -412,6 +415,9 @@ func Write(fd Handle, p []byte) (n int, err error) { if msanenabled && done > 0 { msanRead(unsafe.Pointer(&p[0]), int(done)) } + if asanenabled && done > 0 { + asanRead(unsafe.Pointer(&p[0]), int(done)) + } return int(done), nil } -- GitLab From a97c527ac491cc13f6778010a2a81c84642ea1ca Mon Sep 17 00:00:00 2001 From: Rhys Hiltner Date: Wed, 29 Sep 2021 17:35:27 -0700 Subject: [PATCH 1871/2500] runtime: add padding to Linux kernel structures Go exchanges siginfo and sigevent structures with the kernel. They contain unions, but Go's use is limited to the first few fields. Pad out the rest so the size Go sees is the same as what the Linux kernel sees. This is a follow-up to CL 342052 which added the sigevent struct without padding, and to CL 353136 which added the padding but with an assertion that confused several type-checkers. It updates the siginfo struct as well so there are no bad examples in the defs_linux_*.go files. Reviewed-on: https://go-review.googlesource.com/c/go/+/353136 Change-Id: I9610632ff0ec43eba91f560536f5441fa907b36f Reviewed-on: https://go-review.googlesource.com/c/go/+/360094 Run-TryBot: Ian Lance Taylor Reviewed-by: Ian Lance Taylor Reviewed-by: Michael Pratt --- src/runtime/defs_linux_386.go | 20 ++++++++++++++++++-- src/runtime/defs_linux_amd64.go | 20 ++++++++++++++++++-- src/runtime/defs_linux_arm.go | 20 ++++++++++++++++++-- src/runtime/defs_linux_arm64.go | 20 ++++++++++++++++++-- src/runtime/defs_linux_mips64x.go | 20 ++++++++++++++++++-- src/runtime/defs_linux_mipsx.go | 20 ++++++++++++++++++-- src/runtime/defs_linux_ppc64.go | 20 ++++++++++++++++++-- src/runtime/defs_linux_ppc64le.go | 20 ++++++++++++++++++-- src/runtime/defs_linux_riscv64.go | 20 ++++++++++++++++++-- src/runtime/defs_linux_s390x.go | 20 ++++++++++++++++++-- src/runtime/export_linux_test.go | 5 +++++ src/runtime/os_linux.go | 16 ++++++++++------ src/runtime/runtime_linux_test.go | 11 +++++++++++ 13 files changed, 206 insertions(+), 26 deletions(-) diff --git a/src/runtime/defs_linux_386.go b/src/runtime/defs_linux_386.go index d8b546cb4c..24fb58bbf8 100644 --- a/src/runtime/defs_linux_386.go +++ b/src/runtime/defs_linux_386.go @@ -3,6 +3,8 @@ package runtime +import "unsafe" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -166,7 +168,7 @@ type sigactiont struct { sa_mask uint64 } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_errno int32 si_code int32 @@ -174,6 +176,13 @@ type siginfo struct { si_addr uint32 } +type siginfo struct { + siginfoFields + + // Pad struct to the max size in the kernel. + _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte +} + type stackt struct { ss_sp *byte ss_flags int32 @@ -229,7 +238,7 @@ type itimerval struct { it_value timeval } -type sigevent struct { +type sigeventFields struct { value uintptr signo int32 notify int32 @@ -237,6 +246,13 @@ type sigevent struct { sigev_notify_thread_id int32 } +type sigevent struct { + sigeventFields + + // Pad struct to the max size in the kernel. + _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte +} + type epollevent struct { events uint32 data [8]byte // to match amd64 diff --git a/src/runtime/defs_linux_amd64.go b/src/runtime/defs_linux_amd64.go index 6afb67f77f..36da22f8ce 100644 --- a/src/runtime/defs_linux_amd64.go +++ b/src/runtime/defs_linux_amd64.go @@ -3,6 +3,8 @@ package runtime +import "unsafe" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -128,7 +130,7 @@ type sigactiont struct { sa_mask uint64 } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_errno int32 si_code int32 @@ -136,6 +138,13 @@ type siginfo struct { si_addr uint64 } +type siginfo struct { + siginfoFields + + // Pad struct to the max size in the kernel. + _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte +} + type itimerspec struct { it_interval timespec it_value timespec @@ -146,7 +155,7 @@ type itimerval struct { it_value timeval } -type sigevent struct { +type sigeventFields struct { value uintptr signo int32 notify int32 @@ -154,6 +163,13 @@ type sigevent struct { sigev_notify_thread_id int32 } +type sigevent struct { + sigeventFields + + // Pad struct to the max size in the kernel. + _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte +} + type epollevent struct { events uint32 data [8]byte // unaligned uintptr diff --git a/src/runtime/defs_linux_arm.go b/src/runtime/defs_linux_arm.go index ec24d76326..13d06969e3 100644 --- a/src/runtime/defs_linux_arm.go +++ b/src/runtime/defs_linux_arm.go @@ -4,6 +4,8 @@ package runtime +import "unsafe" + // Constants const ( _EINTR = 0x4 @@ -169,7 +171,7 @@ type itimerval struct { it_value timeval } -type sigevent struct { +type sigeventFields struct { value uintptr signo int32 notify int32 @@ -177,7 +179,14 @@ type sigevent struct { sigev_notify_thread_id int32 } -type siginfo struct { +type sigevent struct { + sigeventFields + + // Pad struct to the max size in the kernel. + _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte +} + +type siginfoFields struct { si_signo int32 si_errno int32 si_code int32 @@ -185,6 +194,13 @@ type siginfo struct { si_addr uint32 } +type siginfo struct { + siginfoFields + + // Pad struct to the max size in the kernel. + _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte +} + type sigactiont struct { sa_handler uintptr sa_flags uint32 diff --git a/src/runtime/defs_linux_arm64.go b/src/runtime/defs_linux_arm64.go index f9f175004b..f9ee9cbc35 100644 --- a/src/runtime/defs_linux_arm64.go +++ b/src/runtime/defs_linux_arm64.go @@ -3,6 +3,8 @@ package runtime +import "unsafe" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -128,7 +130,7 @@ type sigactiont struct { sa_mask uint64 } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_errno int32 si_code int32 @@ -136,6 +138,13 @@ type siginfo struct { si_addr uint64 } +type siginfo struct { + siginfoFields + + // Pad struct to the max size in the kernel. + _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte +} + type itimerspec struct { it_interval timespec it_value timespec @@ -146,7 +155,7 @@ type itimerval struct { it_value timeval } -type sigevent struct { +type sigeventFields struct { value uintptr signo int32 notify int32 @@ -154,6 +163,13 @@ type sigevent struct { sigev_notify_thread_id int32 } +type sigevent struct { + sigeventFields + + // Pad struct to the max size in the kernel. + _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte +} + type epollevent struct { events uint32 _pad uint32 diff --git a/src/runtime/defs_linux_mips64x.go b/src/runtime/defs_linux_mips64x.go index 63433cb9be..2601082ee1 100644 --- a/src/runtime/defs_linux_mips64x.go +++ b/src/runtime/defs_linux_mips64x.go @@ -6,6 +6,8 @@ package runtime +import "unsafe" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -134,7 +136,7 @@ type sigactiont struct { sa_restorer uintptr } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_code int32 si_errno int32 @@ -143,6 +145,13 @@ type siginfo struct { si_addr uint64 } +type siginfo struct { + siginfoFields + + // Pad struct to the max size in the kernel. + _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte +} + type itimerspec struct { it_interval timespec it_value timespec @@ -153,7 +162,7 @@ type itimerval struct { it_value timeval } -type sigevent struct { +type sigeventFields struct { value uintptr signo int32 notify int32 @@ -161,6 +170,13 @@ type sigevent struct { sigev_notify_thread_id int32 } +type sigevent struct { + sigeventFields + + // Pad struct to the max size in the kernel. + _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte +} + type epollevent struct { events uint32 pad_cgo_0 [4]byte diff --git a/src/runtime/defs_linux_mipsx.go b/src/runtime/defs_linux_mipsx.go index ffbf5051eb..37651ef7e4 100644 --- a/src/runtime/defs_linux_mipsx.go +++ b/src/runtime/defs_linux_mipsx.go @@ -6,6 +6,8 @@ package runtime +import "unsafe" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -129,7 +131,7 @@ type sigactiont struct { sa_restorer uintptr } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_code int32 si_errno int32 @@ -137,6 +139,13 @@ type siginfo struct { si_addr uint32 } +type siginfo struct { + siginfoFields + + // Pad struct to the max size in the kernel. + _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte +} + type itimerspec struct { it_interval timespec it_value timespec @@ -147,7 +156,7 @@ type itimerval struct { it_value timeval } -type sigevent struct { +type sigeventFields struct { value uintptr signo int32 notify int32 @@ -155,6 +164,13 @@ type sigevent struct { sigev_notify_thread_id int32 } +type sigevent struct { + sigeventFields + + // Pad struct to the max size in the kernel. + _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte +} + type epollevent struct { events uint32 pad_cgo_0 [4]byte diff --git a/src/runtime/defs_linux_ppc64.go b/src/runtime/defs_linux_ppc64.go index e0775e2974..c7aa7234c1 100644 --- a/src/runtime/defs_linux_ppc64.go +++ b/src/runtime/defs_linux_ppc64.go @@ -3,6 +3,8 @@ package runtime +import "unsafe" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -129,7 +131,7 @@ type sigactiont struct { sa_mask uint64 } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_errno int32 si_code int32 @@ -137,6 +139,13 @@ type siginfo struct { si_addr uint64 } +type siginfo struct { + siginfoFields + + // Pad struct to the max size in the kernel. + _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte +} + type itimerspec struct { it_interval timespec it_value timespec @@ -147,7 +156,7 @@ type itimerval struct { it_value timeval } -type sigevent struct { +type sigeventFields struct { value uintptr signo int32 notify int32 @@ -155,6 +164,13 @@ type sigevent struct { sigev_notify_thread_id int32 } +type sigevent struct { + sigeventFields + + // Pad struct to the max size in the kernel. + _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte +} + type epollevent struct { events uint32 pad_cgo_0 [4]byte diff --git a/src/runtime/defs_linux_ppc64le.go b/src/runtime/defs_linux_ppc64le.go index e0775e2974..c7aa7234c1 100644 --- a/src/runtime/defs_linux_ppc64le.go +++ b/src/runtime/defs_linux_ppc64le.go @@ -3,6 +3,8 @@ package runtime +import "unsafe" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -129,7 +131,7 @@ type sigactiont struct { sa_mask uint64 } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_errno int32 si_code int32 @@ -137,6 +139,13 @@ type siginfo struct { si_addr uint64 } +type siginfo struct { + siginfoFields + + // Pad struct to the max size in the kernel. + _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte +} + type itimerspec struct { it_interval timespec it_value timespec @@ -147,7 +156,7 @@ type itimerval struct { it_value timeval } -type sigevent struct { +type sigeventFields struct { value uintptr signo int32 notify int32 @@ -155,6 +164,13 @@ type sigevent struct { sigev_notify_thread_id int32 } +type sigevent struct { + sigeventFields + + // Pad struct to the max size in the kernel. + _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte +} + type epollevent struct { events uint32 pad_cgo_0 [4]byte diff --git a/src/runtime/defs_linux_riscv64.go b/src/runtime/defs_linux_riscv64.go index 1052213a4c..332720a8c8 100644 --- a/src/runtime/defs_linux_riscv64.go +++ b/src/runtime/defs_linux_riscv64.go @@ -4,6 +4,8 @@ package runtime +import "unsafe" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -126,7 +128,7 @@ type sigactiont struct { sa_mask uint64 } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_errno int32 si_code int32 @@ -134,6 +136,13 @@ type siginfo struct { si_addr uint64 } +type siginfo struct { + siginfoFields + + // Pad struct to the max size in the kernel. + _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte +} + type itimerspec struct { it_interval timespec it_value timespec @@ -144,7 +153,7 @@ type itimerval struct { it_value timeval } -type sigevent struct { +type sigeventFields struct { value uintptr signo int32 notify int32 @@ -152,6 +161,13 @@ type sigevent struct { sigev_notify_thread_id int32 } +type sigevent struct { + sigeventFields + + // Pad struct to the max size in the kernel. + _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte +} + type epollevent struct { events uint32 pad_cgo_0 [4]byte diff --git a/src/runtime/defs_linux_s390x.go b/src/runtime/defs_linux_s390x.go index b072955d4a..740d8100c5 100644 --- a/src/runtime/defs_linux_s390x.go +++ b/src/runtime/defs_linux_s390x.go @@ -4,6 +4,8 @@ package runtime +import "unsafe" + const ( _EINTR = 0x4 _EAGAIN = 0xb @@ -125,7 +127,7 @@ type sigactiont struct { sa_mask uint64 } -type siginfo struct { +type siginfoFields struct { si_signo int32 si_errno int32 si_code int32 @@ -133,6 +135,13 @@ type siginfo struct { si_addr uint64 } +type siginfo struct { + siginfoFields + + // Pad struct to the max size in the kernel. + _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte +} + type itimerspec struct { it_interval timespec it_value timespec @@ -143,7 +152,7 @@ type itimerval struct { it_value timeval } -type sigevent struct { +type sigeventFields struct { value uintptr signo int32 notify int32 @@ -151,6 +160,13 @@ type sigevent struct { sigev_notify_thread_id int32 } +type sigevent struct { + sigeventFields + + // Pad struct to the max size in the kernel. + _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte +} + type epollevent struct { events uint32 pad_cgo_0 [4]byte diff --git a/src/runtime/export_linux_test.go b/src/runtime/export_linux_test.go index b7c901f238..dea94a934c 100644 --- a/src/runtime/export_linux_test.go +++ b/src/runtime/export_linux_test.go @@ -8,11 +8,16 @@ package runtime import "unsafe" +const SiginfoMaxSize = _si_max_size +const SigeventMaxSize = _sigev_max_size + var NewOSProc0 = newosproc0 var Mincore = mincore var Add = add type EpollEvent epollevent +type Siginfo siginfo +type Sigevent sigevent func Epollctl(epfd, op, fd int32, ev unsafe.Pointer) int32 { return epollctl(epfd, op, fd, (*epollevent)(ev)) diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go index 06773c2193..32a1e1b4f7 100644 --- a/src/runtime/os_linux.go +++ b/src/runtime/os_linux.go @@ -440,6 +440,11 @@ func pipe() (r, w int32, errno int32) func pipe2(flags int32) (r, w int32, errno int32) func setNonblock(fd int32) +const ( + _si_max_size = 128 + _sigev_max_size = 64 +) + //go:nosplit //go:nowritebarrierrec func setsig(i uint32, fn uintptr) { @@ -636,12 +641,11 @@ func setThreadCPUProfiler(hz int32) { spec.it_interval.setNsec(1e9 / int64(hz)) var timerid int32 - sevp := &sigevent{ - notify: _SIGEV_THREAD_ID, - signo: _SIGPROF, - sigev_notify_thread_id: int32(mp.procid), - } - ret := timer_create(_CLOCK_THREAD_CPUTIME_ID, sevp, &timerid) + var sevp sigevent + sevp.notify = _SIGEV_THREAD_ID + sevp.signo = _SIGPROF + sevp.sigev_notify_thread_id = int32(mp.procid) + ret := timer_create(_CLOCK_THREAD_CPUTIME_ID, &sevp, &timerid) if ret != 0 { // If we cannot create a timer for this M, leave profileTimerValid false // to fall back to the process-wide setitimer profiler. diff --git a/src/runtime/runtime_linux_test.go b/src/runtime/runtime_linux_test.go index cd59368cb2..a753aeea58 100644 --- a/src/runtime/runtime_linux_test.go +++ b/src/runtime/runtime_linux_test.go @@ -61,3 +61,14 @@ func TestEpollctlErrorSign(t *testing.T) { t.Errorf("epollctl = %v, want %v", v, -EBADF) } } + +func TestKernelStructSize(t *testing.T) { + // Check that the Go definitions of structures exchanged with the kernel are + // the same size as what the kernel defines. + if have, want := unsafe.Sizeof(Siginfo{}), uintptr(SiginfoMaxSize); have != want { + t.Errorf("Go's siginfo struct is %d bytes long; kernel expects %d", have, want) + } + if have, want := unsafe.Sizeof(Sigevent{}), uintptr(SigeventMaxSize); have != want { + t.Errorf("Go's sigevent struct is %d bytes long; kernel expects %d", have, want) + } +} -- GitLab From 4633b2db4bec605d7920295322d19f895ae89964 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Mon, 1 Nov 2021 20:25:48 -0700 Subject: [PATCH 1872/2500] cmd/go, internal/cpu: use internal/godebug in tests Change-Id: Ifdf67e778e88ee70780428aa5479d2e091752a3a Reviewed-on: https://go-review.googlesource.com/c/go/+/360605 Run-TryBot: Brad Fitzpatrick Trust: Brad Fitzpatrick TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/cmd/go/go_test.go | 11 ++++++----- src/internal/cpu/cpu_test.go | 3 ++- src/internal/cpu/cpu_x86_test.go | 4 ++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index c13d77a1af..d8bed1dac0 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -13,6 +13,7 @@ import ( "flag" "fmt" "go/format" + "internal/godebug" "internal/race" "internal/testenv" "io" @@ -2281,7 +2282,7 @@ func TestUpxCompression(t *testing.T) { func TestCacheListStale(t *testing.T) { tooSlow(t) - if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") { + if godebug.Get("gocacheverify") == "1" { t.Skip("GODEBUG gocacheverify") } tg := testgo(t) @@ -2304,7 +2305,7 @@ func TestCacheListStale(t *testing.T) { func TestCacheCoverage(t *testing.T) { tooSlow(t) - if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") { + if godebug.Get("gocacheverify") == "1" { t.Skip("GODEBUG gocacheverify") } @@ -2336,7 +2337,7 @@ func TestIssue22588(t *testing.T) { func TestIssue22531(t *testing.T) { tooSlow(t) - if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") { + if godebug.Get("gocacheverify") == "1" { t.Skip("GODEBUG gocacheverify") } tg := testgo(t) @@ -2365,7 +2366,7 @@ func TestIssue22531(t *testing.T) { func TestIssue22596(t *testing.T) { tooSlow(t) - if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") { + if godebug.Get("gocacheverify") == "1" { t.Skip("GODEBUG gocacheverify") } tg := testgo(t) @@ -2395,7 +2396,7 @@ func TestIssue22596(t *testing.T) { func TestTestCache(t *testing.T) { tooSlow(t) - if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") { + if godebug.Get("gocacheverify") == "1" { t.Skip("GODEBUG gocacheverify") } tg := testgo(t) diff --git a/src/internal/cpu/cpu_test.go b/src/internal/cpu/cpu_test.go index 06ad20800f..8c21256b34 100644 --- a/src/internal/cpu/cpu_test.go +++ b/src/internal/cpu/cpu_test.go @@ -6,6 +6,7 @@ package cpu_test import ( . "internal/cpu" + "internal/godebug" "internal/testenv" "os" "os/exec" @@ -52,7 +53,7 @@ func TestDisableAllCapabilities(t *testing.T) { func TestAllCapabilitiesDisabled(t *testing.T) { MustHaveDebugOptionsSupport(t) - if os.Getenv("GODEBUG") != "cpu.all=off" { + if godebug.Get("cpu.all") != "off" { t.Skipf("skipping test: GODEBUG=cpu.all=off not set") } diff --git a/src/internal/cpu/cpu_x86_test.go b/src/internal/cpu/cpu_x86_test.go index 0fef065f20..c8be210055 100644 --- a/src/internal/cpu/cpu_x86_test.go +++ b/src/internal/cpu/cpu_x86_test.go @@ -8,7 +8,7 @@ package cpu_test import ( . "internal/cpu" - "os" + "internal/godebug" "testing" ) @@ -25,7 +25,7 @@ func TestDisableSSE3(t *testing.T) { func TestSSE3DebugOption(t *testing.T) { MustHaveDebugOptionsSupport(t) - if os.Getenv("GODEBUG") != "cpu.sse3=off" { + if godebug.Get("cpu.sse3") != "off" { t.Skipf("skipping test: GODEBUG=cpu.sse3=off not set") } -- GitLab From c1ea3395a6fdb2b66e6f445358ca40b78882adce Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Mon, 1 Nov 2021 22:25:55 -0700 Subject: [PATCH 1873/2500] doc/go1.18: add net/netip Updates #46518 Change-Id: Iefc2fec93becc7b36ba2b933ae79f7c9424317fc Reviewed-on: https://go-review.googlesource.com/c/go/+/360634 Reviewed-by: Ian Lance Taylor Trust: Brad Fitzpatrick --- doc/go1.18.html | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/doc/go1.18.html b/doc/go1.18.html index 6fe993d51b..82fe6f4520 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -123,10 +123,33 @@ Do not send CLs removing the interior tags from such phrases.

Core library

+

TODO

TODO: complete this section

+

New net/netip package

+

+ The new net/netip + package defines a new IP address type, Addr + that's a small, comparable, value type. Compared to the existing + net.IP type, the netip.Addr type takes less + memory, is immutable, and is comparable so it supports == + and can be used as a map key. +

+

+ In addition to Addr, the package defines + AddrPort, representing + an IP and port, and + Prefix, representing + a network CIDR prefix. +

+

+ The net package now has methods to send and receive UDP packets + using netip.Addr values instead of the relatively heavy + *net.UDPAddr values. +

+

Minor changes to the library

-- GitLab From 3ee426aefa519b0b2f814a834f5026481c187946 Mon Sep 17 00:00:00 2001 From: fanzha02 Date: Tue, 5 Jan 2021 17:52:43 +0800 Subject: [PATCH 1874/2500] cmd/dist: add asan tests in misc/cgo/testsanitizers package Add asan tests to check the use of Go with -asan option. Currenly, the address sanitizer in Go only checks for error memory access to heap objects. TODO: Enable check for error memory access to global objects. Updates #44853. Change-Id: I83579f229f117b5684a369fc8f365f4dea140648 Reviewed-on: https://go-review.googlesource.com/c/go/+/298615 Trust: fannie zhang Run-TryBot: fannie zhang Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- misc/cgo/testsanitizers/asan_test.go | 66 +++++++++++++++++++ misc/cgo/testsanitizers/cc_test.go | 14 ++++ .../cgo/testsanitizers/testdata/asan1_fail.go | 28 ++++++++ .../cgo/testsanitizers/testdata/asan2_fail.go | 34 ++++++++++ .../cgo/testsanitizers/testdata/asan3_fail.go | 23 +++++++ .../cgo/testsanitizers/testdata/asan4_fail.go | 22 +++++++ .../testdata/asan_useAfterReturn.go | 26 ++++++++ src/cmd/internal/sys/supported.go | 1 + 8 files changed, 214 insertions(+) create mode 100644 misc/cgo/testsanitizers/asan_test.go create mode 100644 misc/cgo/testsanitizers/testdata/asan1_fail.go create mode 100644 misc/cgo/testsanitizers/testdata/asan2_fail.go create mode 100644 misc/cgo/testsanitizers/testdata/asan3_fail.go create mode 100644 misc/cgo/testsanitizers/testdata/asan4_fail.go create mode 100644 misc/cgo/testsanitizers/testdata/asan_useAfterReturn.go diff --git a/misc/cgo/testsanitizers/asan_test.go b/misc/cgo/testsanitizers/asan_test.go new file mode 100644 index 0000000000..dbcce2fe28 --- /dev/null +++ b/misc/cgo/testsanitizers/asan_test.go @@ -0,0 +1,66 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sanitizers_test + +import ( + "strings" + "testing" +) + +func TestASAN(t *testing.T) { + goos, err := goEnv("GOOS") + if err != nil { + t.Fatal(err) + } + goarch, err := goEnv("GOARCH") + if err != nil { + t.Fatal(err) + } + // The asan tests require support for the -asan option. + if !aSanSupported(goos, goarch) { + t.Skipf("skipping on %s/%s; -asan option is not supported.", goos, goarch) + } + + t.Parallel() + requireOvercommit(t) + config := configure("address") + config.skipIfCSanitizerBroken(t) + + mustRun(t, config.goCmd("build", "std")) + + cases := []struct { + src string + memoryAccessError string + }{ + {src: "asan1_fail.go", memoryAccessError: "heap-use-after-free"}, + {src: "asan2_fail.go", memoryAccessError: "heap-buffer-overflow"}, + {src: "asan3_fail.go", memoryAccessError: "use-after-poison"}, + {src: "asan4_fail.go", memoryAccessError: "use-after-poison"}, + {src: "asan_useAfterReturn.go"}, + } + for _, tc := range cases { + tc := tc + name := strings.TrimSuffix(tc.src, ".go") + t.Run(name, func(t *testing.T) { + t.Parallel() + + dir := newTempDir(t) + defer dir.RemoveAll(t) + + outPath := dir.Join(name) + mustRun(t, config.goCmd("build", "-o", outPath, srcPath(tc.src))) + + cmd := hangProneCmd(outPath) + if tc.memoryAccessError != "" { + out, err := cmd.CombinedOutput() + if err != nil && strings.Contains(string(out), tc.memoryAccessError) { + return + } + t.Fatalf("%#q exited without expected memory access error\n%s; got failure\n%s", strings.Join(cmd.Args, " "), tc.memoryAccessError, out) + } + mustRun(t, cmd) + }) + } +} diff --git a/misc/cgo/testsanitizers/cc_test.go b/misc/cgo/testsanitizers/cc_test.go index 7af30ab557..b776afa3e6 100644 --- a/misc/cgo/testsanitizers/cc_test.go +++ b/misc/cgo/testsanitizers/cc_test.go @@ -267,6 +267,9 @@ func configure(sanitizer string) *config { c.ldFlags = append(c.ldFlags, "-fPIC", "-static-libtsan") } + case "address": + c.goFlags = append(c.goFlags, "-asan") + default: panic(fmt.Sprintf("unrecognized sanitizer: %q", sanitizer)) } @@ -450,3 +453,14 @@ func mSanSupported(goos, goarch string) bool { return false } } + +// aSanSupported is a copy of the function cmd/internal/sys.ASanSupported, +// because the internal pacakage can't be used here. +func aSanSupported(goos, goarch string) bool { + switch goos { + case "linux": + return goarch == "amd64" || goarch == "arm64" + default: + return false + } +} diff --git a/misc/cgo/testsanitizers/testdata/asan1_fail.go b/misc/cgo/testsanitizers/testdata/asan1_fail.go new file mode 100644 index 0000000000..e60db76981 --- /dev/null +++ b/misc/cgo/testsanitizers/testdata/asan1_fail.go @@ -0,0 +1,28 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +/* +#include +#include + +int *p; +int* test() { + p = (int *)malloc(2 * sizeof(int)); + free(p); + return p; +} +*/ +import "C" +import "fmt" + +func main() { + // C passes Go an invalid pointer. + a := C.test() + // Use after free + *a = 2 + // We shouldn't get here; asan should stop us first. + fmt.Println(*a) +} diff --git a/misc/cgo/testsanitizers/testdata/asan2_fail.go b/misc/cgo/testsanitizers/testdata/asan2_fail.go new file mode 100644 index 0000000000..e35670c440 --- /dev/null +++ b/misc/cgo/testsanitizers/testdata/asan2_fail.go @@ -0,0 +1,34 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +/* +#include +#include + +int *p; +int* f() { + int i; + p = (int *)malloc(5*sizeof(int)); + for (i = 0; i < 5; i++) { + p[i] = i+10; + } + return p; +} +*/ +import "C" +import ( + "fmt" + "unsafe" +) + +func main() { + a := C.f() + q5 := (*C.int)(unsafe.Add(unsafe.Pointer(a), 4*5)) + // Access to C pointer out of bounds. + *q5 = 100 + // We shouldn't get here; asan should stop us first. + fmt.Printf("q5: %d, %x\n", *q5, q5) +} diff --git a/misc/cgo/testsanitizers/testdata/asan3_fail.go b/misc/cgo/testsanitizers/testdata/asan3_fail.go new file mode 100644 index 0000000000..9f6d26dd89 --- /dev/null +++ b/misc/cgo/testsanitizers/testdata/asan3_fail.go @@ -0,0 +1,23 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +/* +#include +#include + +void test(int *a) { + // Access Go pointer out of bounds. + int c = a[5]; // BOOM + // We shouldn't get here; asan should stop us first. + printf("a[5]=%d\n", c); +} +*/ +import "C" + +func main() { + cIntSlice := []C.int{200, 201, 203, 203, 204} + C.test(&cIntSlice[0]) +} diff --git a/misc/cgo/testsanitizers/testdata/asan4_fail.go b/misc/cgo/testsanitizers/testdata/asan4_fail.go new file mode 100644 index 0000000000..12098458ae --- /dev/null +++ b/misc/cgo/testsanitizers/testdata/asan4_fail.go @@ -0,0 +1,22 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +/* +#include +#include + +void test(int* a) { + // Access Go pointer out of bounds. + a[3] = 300; // BOOM + // We shouldn't get here; asan should stop us first. + printf("a[3]=%d\n", a[3]); +}*/ +import "C" + +func main() { + var cIntArray [2]C.int + C.test(&cIntArray[0]) // cIntArray is moved to heap. +} diff --git a/misc/cgo/testsanitizers/testdata/asan_useAfterReturn.go b/misc/cgo/testsanitizers/testdata/asan_useAfterReturn.go new file mode 100644 index 0000000000..3d3d5a6ab1 --- /dev/null +++ b/misc/cgo/testsanitizers/testdata/asan_useAfterReturn.go @@ -0,0 +1,26 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +// The -fsanitize=address option of C compier can detect stack-use-after-return bugs. +// In the following program, the local variable 'local' was moved to heap by the Go +// compiler because foo() is returning the reference to 'local', and return stack of +// foo() will be invalid. Thus for main() to use the reference to 'local', the 'local' +// must be available even after foo() has finished. Therefore, Go has no such issue. + +import "fmt" + +var ptr *int + +func main() { + foo() + fmt.Printf("ptr=%x, %v", *ptr, ptr) +} + +func foo() { + var local int + local = 1 + ptr = &local // local is moved to heap. +} diff --git a/src/cmd/internal/sys/supported.go b/src/cmd/internal/sys/supported.go index 4fa5aa495e..de2a3fd140 100644 --- a/src/cmd/internal/sys/supported.go +++ b/src/cmd/internal/sys/supported.go @@ -36,6 +36,7 @@ func MSanSupported(goos, goarch string) bool { // ASanSupported reports whether goos/goarch supports the address // sanitizer option. +// There is a copy of this function in misc/cgo/testsanitizers/cc_test.go. func ASanSupported(goos, goarch string) bool { switch goos { case "linux": -- GitLab From 088bb4bf4ad851a7f9a0d409e2f64c483cb7121a Mon Sep 17 00:00:00 2001 From: Leonard Wang Date: Sat, 30 Oct 2021 22:26:56 +0800 Subject: [PATCH 1875/2500] A+C: add Leonard Wang (individual CLA) Change-Id: I9fa687804c7f0f1d5a987b95ab1c3110468d1b65 Reviewed-on: https://go-review.googlesource.com/c/go/+/360054 Reviewed-by: Meng Zhuo Reviewed-by: Ian Lance Taylor Trust: Meng Zhuo Run-TryBot: Meng Zhuo TryBot-Result: Go Bot --- AUTHORS | 1 + CONTRIBUTORS | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index ad907967b4..8d7e196732 100644 --- a/AUTHORS +++ b/AUTHORS @@ -817,6 +817,7 @@ Lehner Florian Leigh McCulloch Leo Antunes Leon Klingele +Leonard Wang Leonel Quinteros Lev Shamardin Lewin Bormann diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 706d630193..a548cb0e2f 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -1569,7 +1569,7 @@ Leigh McCulloch Leo Antunes Leo Rudberg Leon Klingele -Leonard Wang +Leonard Wang Leonardo Comelli Leonel Quinteros Lev Shamardin -- GitLab From 4d7bf41bebc7ad4f71150b8b57fca12aff6da144 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 1 Nov 2021 19:39:18 +0000 Subject: [PATCH 1876/2500] syscall: remove GOMAXPROCS change in TestExecHelper TestExec and TestExecHelper check for a workaround of a particular OS bug on darwin that's triggered more often via asynchronous preemption. As part of this, the test sets up 100 CPU-bound goroutines, and sets GOMAXPROCS to 50, sleeping for a little bit before calling Exec. Thus far, this is fine because the scheduler runs the Execing goroutine in a timely manner. However, CL 309869 will reduce the minimum heap size, causing a GC to happen during the test. On a 16 CPU machine, with GOMAXPROCS at 50, and 100 CPU-bound goroutines, both the OS scheduler and the Go scheduler are severly oversaturated. As a result, the test often (not always, but often) runs out for the full lifetime of those 100 goroutines, which run for about 1 second. The minimum heap size reduction is not necessary to trigger this; an additional call to runtime.GC in the helper is also sufficient to trigger this delay. The delay on its own isn't great, since it adds a whole second to all.bash on its own. However, it also seems correlated with other subprocess tests in the syscall package, namely TestPassFD and TestFcntlFlock. These tests fail in a fairly superficial way: the file descriptor for the temporary directories they make gets clobbered, is closed, or becomes stale. Change-Id: I213dd5e38967d19a8b317e6d4c5024b57f9e3fed Reviewed-on: https://go-review.googlesource.com/c/go/+/360574 Trust: Michael Knyszek Run-TryBot: Michael Knyszek Reviewed-by: Ian Lance Taylor --- src/syscall/exec_unix_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/syscall/exec_unix_test.go b/src/syscall/exec_unix_test.go index 55f5f7025a..b7ae77552b 100644 --- a/src/syscall/exec_unix_test.go +++ b/src/syscall/exec_unix_test.go @@ -13,7 +13,6 @@ import ( "os" "os/exec" "os/signal" - "runtime" "syscall" "testing" "time" @@ -327,7 +326,6 @@ func TestExecHelper(t *testing.T) { // We don't have to worry about restoring these values. // We are in a child process that only runs this test, // and we are going to call syscall.Exec anyhow. - runtime.GOMAXPROCS(50) os.Setenv("GO_WANT_HELPER_PROCESS", "3") stop := time.Now().Add(time.Second) -- GitLab From da7173a2ed637c803b8ff59d0c948e7c7d056c50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Geisend=C3=B6rfer?= Date: Mon, 20 Sep 2021 16:09:47 +0200 Subject: [PATCH 1877/2500] runtime: fix missing pprof labels Use gp.m.curg instead of the gp when recording cpu profiler stack traces. This ensures profiler labels are captured when systemstack or similar is executing on behalf of the current goroutine. After this there are still rare cases of samples containing the labelHog function, so more work might be needed. This patch should fix ~99% of the problem. Fixes #48577. Change-Id: I27132110e3d09721ec3b3ef417122bc70d8f3279 Reviewed-on: https://go-review.googlesource.com/c/go/+/351751 Reviewed-by: Michael Pratt Run-TryBot: Michael Pratt TryBot-Result: Go Bot Trust: Michael Knyszek --- src/runtime/cpuprof.go | 11 +----- src/runtime/pprof/pprof_test.go | 67 +++++++++++++++++++++++++++++++++ src/runtime/proc.go | 9 ++++- 3 files changed, 76 insertions(+), 11 deletions(-) diff --git a/src/runtime/cpuprof.go b/src/runtime/cpuprof.go index c81ab710c2..6076564716 100644 --- a/src/runtime/cpuprof.go +++ b/src/runtime/cpuprof.go @@ -89,7 +89,7 @@ func SetCPUProfileRate(hz int) { // held at the time of the signal, nor can it use substantial amounts // of stack. //go:nowritebarrierrec -func (p *cpuProfile) add(gp *g, stk []uintptr) { +func (p *cpuProfile) add(tagPtr *unsafe.Pointer, stk []uintptr) { // Simple cas-lock to coordinate with setcpuprofilerate. for !atomic.Cas(&prof.signalLock, 0, 1) { osyield() @@ -104,15 +104,6 @@ func (p *cpuProfile) add(gp *g, stk []uintptr) { // because otherwise its write barrier behavior may not // be correct. See the long comment there before // changing the argument here. - // - // Note: it can happen on Windows, where we are calling - // p.add with a gp that is not the current g, that gp is nil, - // meaning we interrupted a system thread with no g. - // Avoid faulting in that case. - var tagPtr *unsafe.Pointer - if gp != nil { - tagPtr = &gp.labels - } cpuprof.log.write(tagPtr, nanotime(), hdr[:], stk) } diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go index 06e0274e9a..da006cbe45 100644 --- a/src/runtime/pprof/pprof_test.go +++ b/src/runtime/pprof/pprof_test.go @@ -1361,6 +1361,73 @@ func TestLabelRace(t *testing.T) { }) } +func TestLabelSystemstack(t *testing.T) { + // See http://golang.org/cl/351751. + prof := testCPUProfile(t, stackContainsLabeled, []string{"runtime.systemstack;key=value"}, avoidFunctions(), func(dur time.Duration) { + Do(context.Background(), Labels("key", "value"), func(context.Context) { + var wg sync.WaitGroup + stop := make(chan struct{}) + for i := 0; i < runtime.GOMAXPROCS(0); i++ { + wg.Add(1) + go func() { + defer wg.Done() + labelHog(stop) + }() + } + + time.Sleep(dur) + close(stop) + wg.Wait() + }) + }) + + var withLabel, withoutLabel int64 + for _, s := range prof.Sample { + var systemstack, labelHog bool + for _, loc := range s.Location { + for _, l := range loc.Line { + switch l.Function.Name { + case "runtime.systemstack": + systemstack = true + case "runtime/pprof.labelHog": + labelHog = true + } + } + } + + if systemstack && labelHog { + if s.Label != nil && contains(s.Label["key"], "value") { + withLabel += s.Value[0] + } else { + withoutLabel += s.Value[0] + } + } + } + + // ratio on 2019 Intel MBP before/after CL 351751 for n=30 runs: + // before: mean=0.013 stddev=0.013 min=0.000 max=0.039 + // after : mean=0.996 stddev=0.007 min=0.967 max=1.000 + // + // TODO: Figure out why some samples still contain labelHog without labels. + // Once fixed this test case can be simplified to just check that all samples + // containing labelHog() have the label, and no other samples do. + ratio := float64(withLabel) / float64((withLabel + withoutLabel)) + if ratio < 0.9 { + t.Fatalf("only %.1f%% of labelHog(systemstack()) samples have label", ratio*100) + } +} + +func labelHog(stop chan struct{}) { + for i := 0; ; i++ { + select { + case <-stop: + return + default: + fmt.Fprintf(io.Discard, "%d", i) + } + } +} + // Check that there is no deadlock when the program receives SIGPROF while in // 64bit atomics' critical section. Used to happen on mips{,le}. See #20146. func TestAtomicLoadStore64(t *testing.T) { diff --git a/src/runtime/proc.go b/src/runtime/proc.go index bf5fa8e4fc..268d5ff398 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -4711,7 +4711,14 @@ func sigprof(pc, sp, lr uintptr, gp *g, mp *m) { } if prof.hz != 0 { - cpuprof.add(gp, stk[:n]) + // Note: it can happen on Windows that we interrupted a system thread + // with no g, so gp could nil. The other nil checks are done out of + // caution, but not expected to be nil in practice. + var tagPtr *unsafe.Pointer + if gp != nil && gp.m != nil && gp.m.curg != nil { + tagPtr = &gp.m.curg.labels + } + cpuprof.add(tagPtr, stk[:n]) } getg().m.mallocing-- } -- GitLab From c3cb1ecc36512a00492f27fa3ba19e5dad6194f1 Mon Sep 17 00:00:00 2001 From: Amelia Downs Date: Mon, 27 Sep 2021 16:54:39 -0400 Subject: [PATCH 1878/2500] internal/fuzz: minimize bytes to be human readable Try to replace every byte with one of the following printable characters: "012789ABCXYZabcxyz !\"#$%&'()*+,.". Fixes #48129 Change-Id: Ie58f6bbc3431d50d9f0a3f608ba63e854ac6ce79 Reviewed-on: https://go-review.googlesource.com/c/go/+/352614 Reviewed-by: Katie Hockman Reviewed-by: Amelia Downs Trust: Katie Hockman Trust: Julie Qiu Run-TryBot: Katie Hockman TryBot-Result: Go Bot --- src/internal/fuzz/minimize.go | 19 ++++++++++++++ src/internal/fuzz/minimize_test.go | 41 +++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/internal/fuzz/minimize.go b/src/internal/fuzz/minimize.go index 974df369ee..c6e4559665 100644 --- a/src/internal/fuzz/minimize.go +++ b/src/internal/fuzz/minimize.go @@ -79,6 +79,25 @@ func minimizeBytes(v []byte, try func(interface{}) bool, shouldStop func() bool) j = len(v) } } + + // Then, try to make it more simplified and human-readable by trying to replace each + // byte with a printable character. + printableChars := []byte("012789ABCXYZabcxyz !\"#$%&'()*+,.") + for i, b := range v { + if shouldStop() { + return + } + + for _, pc := range printableChars { + v[i] = pc + if try(v) { + // Successful. Move on to the next byte in v. + break + } + // Unsuccessful. Revert v[i] back to original value. + v[i] = b + } + } } func minimizeInteger(v uint, try func(interface{}) bool, shouldStop func() bool) { diff --git a/src/internal/fuzz/minimize_test.go b/src/internal/fuzz/minimize_test.go index 13385e14d6..dc153d0de4 100644 --- a/src/internal/fuzz/minimize_test.go +++ b/src/internal/fuzz/minimize_test.go @@ -13,6 +13,8 @@ import ( "fmt" "reflect" "testing" + "unicode" + "unicode/utf8" ) func TestMinimizeInput(t *testing.T) { @@ -54,7 +56,7 @@ func TestMinimizeInput(t *testing.T) { return fmt.Errorf("bad %v", e.Values[0]) }, input: []interface{}{[]byte{1, 2, 3, 4, 5}}, - expected: []interface{}{[]byte{2, 3}}, + expected: []interface{}{[]byte("00")}, }, { name: "set_of_bytes", @@ -71,6 +73,18 @@ func TestMinimizeInput(t *testing.T) { input: []interface{}{[]byte{0, 1, 2, 3, 4, 5}}, expected: []interface{}{[]byte{0, 4, 5}}, }, + { + name: "non_ascii_bytes", + fn: func(e CorpusEntry) error { + b := e.Values[0].([]byte) + if len(b) == 3 { + return fmt.Errorf("bad %v", e.Values[0]) + } + return nil + }, + input: []interface{}{[]byte("ท")}, // ท is 3 bytes + expected: []interface{}{[]byte("000")}, + }, { name: "ones_string", fn: func(e CorpusEntry) error { @@ -89,6 +103,31 @@ func TestMinimizeInput(t *testing.T) { input: []interface{}{"001010001000000000000000000"}, expected: []interface{}{"111"}, }, + { + name: "string_length", + fn: func(e CorpusEntry) error { + b := e.Values[0].(string) + if len(b) == 5 { + return fmt.Errorf("bad %v", e.Values[0]) + } + return nil + }, + input: []interface{}{"zzzzz"}, + expected: []interface{}{"00000"}, + }, + { + name: "string_with_letter", + fn: func(e CorpusEntry) error { + b := e.Values[0].(string) + r, _ := utf8.DecodeRune([]byte(b)) + if unicode.IsLetter(r) { + return fmt.Errorf("bad %v", e.Values[0]) + } + return nil + }, + input: []interface{}{"ZZZZZ"}, + expected: []interface{}{"A"}, + }, { name: "int", fn: func(e CorpusEntry) error { -- GitLab From d39c8739662835b2f92894a8550bbcd59f83557f Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 1 Nov 2021 12:14:25 -0700 Subject: [PATCH 1879/2500] cmd/compile/internal/types2: fix conversions of constants to type parameter When converting a constant to a type parameter, the result is never constant (type parameters are not constant types), but we still need to verfy that the constant is representable by each specific type in the type set of the type parameter. Fixes #49247. Change-Id: I460983c7070b33baadce25dd23210e10930cfb2c Reviewed-on: https://go-review.googlesource.com/c/go/+/360396 Trust: Robert Griesemer Reviewed-by: Robert Findley --- .../compile/internal/types2/conversions.go | 39 ++++++++++++++----- src/cmd/compile/internal/types2/expr.go | 1 + src/cmd/compile/internal/types2/predicates.go | 6 +++ .../types2/testdata/fixedbugs/issue49247.go2 | 20 ++++++++++ .../types2/testdata/spec/conversions.go2 | 21 ++++++++++ 5 files changed, 77 insertions(+), 10 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue49247.go2 diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go index bc33b3a44b..0e26a73cf8 100644 --- a/src/cmd/compile/internal/types2/conversions.go +++ b/src/cmd/compile/internal/types2/conversions.go @@ -16,26 +16,45 @@ import ( func (check *Checker) conversion(x *operand, T Type) { constArg := x.mode == constant_ - var ok bool - var cause string - switch { - case constArg && isConstType(T): - // constant conversion (T cannot be a type parameter) + constConvertibleTo := func(T Type, val *constant.Value) bool { switch t := asBasic(T); { - case representableConst(x.val, check, t, &x.val): - ok = true + case representableConst(x.val, check, t, val): + return true case isInteger(x.typ) && isString(t): codepoint := unicode.ReplacementChar if i, ok := constant.Uint64Val(x.val); ok && i <= unicode.MaxRune { codepoint = rune(i) } - x.val = constant.MakeString(string(codepoint)) - ok = true + if val != nil { + *val = constant.MakeString(string(codepoint)) + } + return true } + return false + } + + var ok bool + var cause string + switch { + case constArg && isConstType(T): + // constant conversion + ok = constConvertibleTo(T, &x.val) + case constArg && isTypeParam(T): + // x is convertible to T if it is convertible + // to each specific type in the type set of T. + // If T's type set is empty, or if it doesn't + // have specific types, constant x cannot be + // converted. + ok = under(T).(*TypeParam).underIs(func(u Type) bool { + // t is nil if there are no specific type terms + // TODO(gri) add a cause in case of failure + return u != nil && constConvertibleTo(u, nil) + }) + x.mode = value // type parameters are not constants case x.convertibleTo(check, T, &cause): // non-constant conversion - x.mode = value ok = true + x.mode = value } if !ok { diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index ae7b205e53..eb5ec9f3fb 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -743,6 +743,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const return nil, nil, _InvalidUntypedConversion } case *TypeParam: + // TODO(gri) review this code - doesn't look quite right ok := t.underIs(func(t Type) bool { target, _, _ := check.implicitTypeAndValue(x, t) return target != nil diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 380fb6489c..6d93a8a227 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -80,6 +80,12 @@ func IsInterface(typ Type) bool { return asInterface(typ) != nil } +// isTypeParam reports whether typ is a type parameter. +func isTypeParam(typ Type) bool { + _, ok := under(typ).(*TypeParam) + return ok +} + // Comparable reports whether values of type T are comparable. func Comparable(T Type) bool { return comparable(T, nil) diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49247.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49247.go2 new file mode 100644 index 0000000000..3f25e0ee35 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49247.go2 @@ -0,0 +1,20 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type integer interface { + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr +} + +func Add1024[T integer](s []T) { + for i, v := range s { + s[i] = v + 1024 // ERROR cannot convert 1024 \(untyped int constant\) to T + } +} + +func f[T interface{ int8 }]() { + println(T(1024 /* ERROR cannot convert 1024 \(untyped int value\) to T */)) +} diff --git a/src/cmd/compile/internal/types2/testdata/spec/conversions.go2 b/src/cmd/compile/internal/types2/testdata/spec/conversions.go2 index 0acd2762a1..942d9c0f6f 100644 --- a/src/cmd/compile/internal/types2/testdata/spec/conversions.go2 +++ b/src/cmd/compile/internal/types2/testdata/spec/conversions.go2 @@ -6,6 +6,27 @@ package conversions import "unsafe" +// constant conversions + +func _[T ~byte]() T { return 255 } +func _[T ~byte]() T { return 256 /* ERROR cannot use 256 .* as T value */ } + +func _[T ~byte]() { + const _ = T /* ERROR T\(0\) .* is not constant */ (0) + var _ T = 255 + var _ T = 256 // ERROR cannot use 256 .* as T value +} + +func _[T ~string]() T { return T('a') } +func _[T ~int | ~string]() T { return T('a') } +func _[T ~byte | ~int | ~string]() T { return T(256 /* ERROR cannot convert 256 .* to T */ ) } + +// implicit conversions never convert to string +func _[T ~string]() { + var _ string = 0 // ERROR cannot use .* as string value + var _ T = 0 // ERROR cannot use .* as T value +} + // "x is assignable to T" // - tested via assignability tests -- GitLab From 599de4b2c348738a5d6d2f5d475c74ac835e091a Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 1 Nov 2021 13:41:32 -0700 Subject: [PATCH 1880/2500] cmd/compile/internal/types2: adjust printing of type parameter in error For constraint type inference failures where the type parameter doesn't match the constraint, print the type parameter rather than its type name object. This provides more flexibility for improving the error message down the road. Change-Id: I188871d6f26a16cd96e59770966a1ec65607b128 Reviewed-on: https://go-review.googlesource.com/c/go/+/360514 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/infer.go | 7 ++++--- .../internal/types2/testdata/fixedbugs/issue45985.go2 | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index 494e896ee9..24c461f1c3 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -378,7 +378,6 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type, // If a constraint has a structural type, unify the corresponding type parameter with it. for _, tpar := range tparams { - typ := tpar sbound := structure(tpar) if sbound != nil { // If the structural type is the underlying type of a single @@ -386,8 +385,10 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type, if named, _ := tpar.singleType().(*Named); named != nil { sbound = named } - if !u.unify(typ, sbound) { - check.errorf(tpar.obj, "%s does not match %s", tpar.obj, sbound) + if !u.unify(tpar, sbound) { + // TODO(gri) improve error message by providing the type arguments + // which we know already + check.errorf(tpar.obj, "%s does not match %s", tpar, sbound) return nil, 0 } } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45985.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45985.go2 index ee5282d6ef..9963d2ee00 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45985.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45985.go2 @@ -5,7 +5,7 @@ package issue45985 // TODO(gri): this error should be on app[int] below. -func app[S /* ERROR "type S S does not match" */ interface{ ~[]T }, T any](s S, e T) S { +func app[S /* ERROR "S does not match" */ interface{ ~[]T }, T any](s S, e T) S { return append(s, e) } -- GitLab From f801da7855d3a82cc415279262e6b1ca7df39e5f Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 1 Nov 2021 16:05:14 -0700 Subject: [PATCH 1881/2500] cmd/compile/internal/types2: fix indexing of generic types Correctly track if the index expression is addressable. Rewrote code slightly. Fixes #49275. Change-Id: Ic54edd0213a091173ff5403ab0e3e1f1fca0e361 Reviewed-on: https://go-review.googlesource.com/c/go/+/360603 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/index.go | 87 ++++++++++--------- .../types2/testdata/check/typeparams.go2 | 8 ++ 2 files changed, 53 insertions(+), 42 deletions(-) diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index 23e433ac6a..bb7033e957 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -101,77 +101,80 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo case *TypeParam: // TODO(gri) report detailed failure cause for better error messages - var tkey, telem Type // tkey != nil if we have maps + var key, elem Type // key != nil: we must have all maps + mode := variable // non-maps result mode + // TODO(gri) factor out closure and use it for non-typeparam cases as well if typ.underIs(func(u Type) bool { - var key, elem Type - alen := int64(-1) // valid if >= 0 + l := int64(-1) // valid if >= 0 + var k, e Type // k is only set for maps switch t := u.(type) { case *Basic: - if !isString(t) { - return false + if isString(t) { + e = universeByte + mode = value } - elem = universeByte case *Array: - elem = t.elem - alen = t.len + l = t.len + e = t.elem + if x.mode != variable { + mode = value + } case *Pointer: - a, _ := under(t.base).(*Array) - if a == nil { - return false + if t := asArray(t.base); t != nil { + l = t.len + e = t.elem } - elem = a.elem - alen = a.len case *Slice: - elem = t.elem + e = t.elem case *Map: - key = t.key - elem = t.elem - default: + k = t.key + e = t.elem + } + if e == nil { return false } - assert(elem != nil) - if telem == nil { + if elem == nil { // first type - tkey, telem = key, elem - length = alen - } else { - // all map keys must be identical (incl. all nil) - if !Identical(key, tkey) { - return false - } - // all element types must be identical - if !Identical(elem, telem) { - return false - } - tkey, telem = key, elem - // track the minimal length for arrays - if alen >= 0 && alen < length { - length = alen - } + length = l + key, elem = k, e + return true + } + // all map keys must be identical (incl. all nil) + // (that is, we cannot mix maps with other types) + if !Identical(key, k) { + return false + } + // all element types must be identical + if !Identical(elem, e) { + return false + } + // track the minimal length for arrays, if any + if l >= 0 && l < length { + length = l } return true }) { // For maps, the index expression must be assignable to the map key type. - if tkey != nil { + if key != nil { index := check.singleIndex(e) if index == nil { x.mode = invalid return false } - var key operand - check.expr(&key, index) - check.assignment(&key, tkey, "map index") + var k operand + check.expr(&k, index) + check.assignment(&k, key, "map index") // ok to continue even if indexing failed - map element type is known x.mode = mapindex - x.typ = telem + x.typ = elem x.expr = e return false } // no maps valid = true - x.mode = variable - x.typ = telem + x.mode = mode + x.typ = elem } } diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 index 11adb21d95..a1bf6c262f 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 @@ -114,6 +114,14 @@ func _[T interface{ [10]int }](x T, i int) { _ = x[i]; _ = x[9]; _ = x[10 /* ERR func _[T interface{ [10]byte | string }](x T, i int) { _ = x[i]; _ = x[9]; _ = x[10 /* ERROR out of bounds */ ] } func _[T interface{ [10]int | *[20]int | []int }](x T, i int) { _ = x[i]; _ = x[9]; _ = x[10 /* ERROR out of bounds */ ] } +// indexing with strings and non-variable arrays (assignment not permitted) +func _[T string](x T) { _ = x[0]; x /* ERROR cannot assign */ [0] = 0 } +func _[T []byte | string](x T) { x /* ERROR cannot assign */ [0] = 0 } +func _[T [10]byte]() { f := func() (x T) { return }; f /* ERROR cannot assign */ ()[0] = 0 } +func _[T [10]byte]() { f := func() (x *T) { return }; f /* ERROR cannot index */ ()[0] = 0 } +func _[T [10]byte]() { f := func() (x *T) { return }; (*f())[0] = 0 } +func _[T *[10]byte]() { f := func() (x T) { return }; f()[0] = 0 } + // slicing func _[T interface{ ~[10]E }, E any] (x T, i, j, k int) { var _ []E = x[i:j] } -- GitLab From c6a0b6f2de9a778b03a29c656531617a606761f0 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Tue, 2 Nov 2021 15:38:47 +0000 Subject: [PATCH 1882/2500] Revert "runtime: fix missing pprof labels" This reverts CL 351751. Reason for revert: new test is failing on many builders. Change-Id: I066211c9f25607ca9eb5299aedea2ecc5069e34f Reviewed-on: https://go-review.googlesource.com/c/go/+/360757 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Michael Pratt --- src/runtime/cpuprof.go | 11 +++++- src/runtime/pprof/pprof_test.go | 67 --------------------------------- src/runtime/proc.go | 9 +---- 3 files changed, 11 insertions(+), 76 deletions(-) diff --git a/src/runtime/cpuprof.go b/src/runtime/cpuprof.go index 6076564716..c81ab710c2 100644 --- a/src/runtime/cpuprof.go +++ b/src/runtime/cpuprof.go @@ -89,7 +89,7 @@ func SetCPUProfileRate(hz int) { // held at the time of the signal, nor can it use substantial amounts // of stack. //go:nowritebarrierrec -func (p *cpuProfile) add(tagPtr *unsafe.Pointer, stk []uintptr) { +func (p *cpuProfile) add(gp *g, stk []uintptr) { // Simple cas-lock to coordinate with setcpuprofilerate. for !atomic.Cas(&prof.signalLock, 0, 1) { osyield() @@ -104,6 +104,15 @@ func (p *cpuProfile) add(tagPtr *unsafe.Pointer, stk []uintptr) { // because otherwise its write barrier behavior may not // be correct. See the long comment there before // changing the argument here. + // + // Note: it can happen on Windows, where we are calling + // p.add with a gp that is not the current g, that gp is nil, + // meaning we interrupted a system thread with no g. + // Avoid faulting in that case. + var tagPtr *unsafe.Pointer + if gp != nil { + tagPtr = &gp.labels + } cpuprof.log.write(tagPtr, nanotime(), hdr[:], stk) } diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go index da006cbe45..06e0274e9a 100644 --- a/src/runtime/pprof/pprof_test.go +++ b/src/runtime/pprof/pprof_test.go @@ -1361,73 +1361,6 @@ func TestLabelRace(t *testing.T) { }) } -func TestLabelSystemstack(t *testing.T) { - // See http://golang.org/cl/351751. - prof := testCPUProfile(t, stackContainsLabeled, []string{"runtime.systemstack;key=value"}, avoidFunctions(), func(dur time.Duration) { - Do(context.Background(), Labels("key", "value"), func(context.Context) { - var wg sync.WaitGroup - stop := make(chan struct{}) - for i := 0; i < runtime.GOMAXPROCS(0); i++ { - wg.Add(1) - go func() { - defer wg.Done() - labelHog(stop) - }() - } - - time.Sleep(dur) - close(stop) - wg.Wait() - }) - }) - - var withLabel, withoutLabel int64 - for _, s := range prof.Sample { - var systemstack, labelHog bool - for _, loc := range s.Location { - for _, l := range loc.Line { - switch l.Function.Name { - case "runtime.systemstack": - systemstack = true - case "runtime/pprof.labelHog": - labelHog = true - } - } - } - - if systemstack && labelHog { - if s.Label != nil && contains(s.Label["key"], "value") { - withLabel += s.Value[0] - } else { - withoutLabel += s.Value[0] - } - } - } - - // ratio on 2019 Intel MBP before/after CL 351751 for n=30 runs: - // before: mean=0.013 stddev=0.013 min=0.000 max=0.039 - // after : mean=0.996 stddev=0.007 min=0.967 max=1.000 - // - // TODO: Figure out why some samples still contain labelHog without labels. - // Once fixed this test case can be simplified to just check that all samples - // containing labelHog() have the label, and no other samples do. - ratio := float64(withLabel) / float64((withLabel + withoutLabel)) - if ratio < 0.9 { - t.Fatalf("only %.1f%% of labelHog(systemstack()) samples have label", ratio*100) - } -} - -func labelHog(stop chan struct{}) { - for i := 0; ; i++ { - select { - case <-stop: - return - default: - fmt.Fprintf(io.Discard, "%d", i) - } - } -} - // Check that there is no deadlock when the program receives SIGPROF while in // 64bit atomics' critical section. Used to happen on mips{,le}. See #20146. func TestAtomicLoadStore64(t *testing.T) { diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 268d5ff398..bf5fa8e4fc 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -4711,14 +4711,7 @@ func sigprof(pc, sp, lr uintptr, gp *g, mp *m) { } if prof.hz != 0 { - // Note: it can happen on Windows that we interrupted a system thread - // with no g, so gp could nil. The other nil checks are done out of - // caution, but not expected to be nil in practice. - var tagPtr *unsafe.Pointer - if gp != nil && gp.m != nil && gp.m.curg != nil { - tagPtr = &gp.m.curg.labels - } - cpuprof.add(tagPtr, stk[:n]) + cpuprof.add(gp, stk[:n]) } getg().m.mallocing-- } -- GitLab From f2ff1c6074b1591c231f8f6b3394f9700cac7fad Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sun, 31 Oct 2021 00:20:13 +0700 Subject: [PATCH 1883/2500] cmd/compile: fix rewriting slice literal call argument When seeing Key:Value expression in slice literal, the compiler only needs to emit tmp var for the Value, not the whole expression. Fixes #49240 Change-Id: I7bda3c796a93c0fa1974f7c5930f38025dfa665c Reviewed-on: https://go-review.googlesource.com/c/go/+/360055 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Cherry Mui Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/escape/call.go | 6 +++++- test/fixedbugs/issue49240.go | 11 +++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 test/fixedbugs/issue49240.go diff --git a/src/cmd/compile/internal/escape/call.go b/src/cmd/compile/internal/escape/call.go index 9e5abed591..63e790a786 100644 --- a/src/cmd/compile/internal/escape/call.go +++ b/src/cmd/compile/internal/escape/call.go @@ -337,7 +337,11 @@ func (e *escape) rewriteArgument(argp *ir.Node, init *ir.Nodes, call ir.Node, fn if arg := *argp; arg.Op() == ir.OSLICELIT { list := arg.(*ir.CompLitExpr).List for i := range list { - visit(arg.Pos(), &list[i]) + el := &list[i] + if list[i].Op() == ir.OKEY { + el = &list[i].(*ir.KeyExpr).Value + } + visit(arg.Pos(), el) } } else { visit(call.Pos(), argp) diff --git a/test/fixedbugs/issue49240.go b/test/fixedbugs/issue49240.go new file mode 100644 index 0000000000..26929fe1a2 --- /dev/null +++ b/test/fixedbugs/issue49240.go @@ -0,0 +1,11 @@ +// compile + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func f() { + go copy([]int{1: 0}, []int{}) +} -- GitLab From 58fb05a24a756a9a4386faff977e6495cdccb12f Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Tue, 2 Nov 2021 10:19:24 +0700 Subject: [PATCH 1884/2500] cmd/compile: explain special treatment when rewrite slice literal args Followup discussion in CL 360055. Change-Id: I36212c2a497b152d01ed86d244d5f57bd34a64a6 Reviewed-on: https://go-review.googlesource.com/c/go/+/360614 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le Reviewed-by: Cherry Mui TryBot-Result: Go Bot --- src/cmd/compile/internal/escape/call.go | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/escape/call.go b/src/cmd/compile/internal/escape/call.go index 63e790a786..d1215afca8 100644 --- a/src/cmd/compile/internal/escape/call.go +++ b/src/cmd/compile/internal/escape/call.go @@ -333,7 +333,24 @@ func (e *escape) rewriteArgument(argp *ir.Node, init *ir.Nodes, call ir.Node, fn } } - // Peel away any slice lits. + // Peel away any slice literals for better escape analyze + // them. For example: + // + // go F([]int{a, b}) + // + // If F doesn't escape its arguments, then the slice can + // be allocated on the new goroutine's stack. + // + // For variadic functions, the compiler has already rewritten: + // + // f(a, b, c) + // + // to: + // + // f([]T{a, b, c}...) + // + // So we need to look into slice elements to handle uintptr(ptr) + // arguments to syscall-like functions correctly. if arg := *argp; arg.Op() == ir.OSLICELIT { list := arg.(*ir.CompLitExpr).List for i := range list { -- GitLab From 8c8baad927b2fd0bca589bacab658fe0f7eb5dac Mon Sep 17 00:00:00 2001 From: vpachkov Date: Sun, 31 Oct 2021 11:06:27 +0000 Subject: [PATCH 1885/2500] runtime: check amd64 microarchitecture level at startup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make Go runtime throw if it's been compiled to assume instruction set extensions that aren't available on the CPU. Updates #48506 Change-Id: Ic4d6696e1cd6b28d389a86fe64e8175ea3ca135a GitHub-Last-Rev: ba338377f549344b416fbd519576e95ce5d523be GitHub-Pull-Request: golang/go#48514 Reviewed-on: https://go-review.googlesource.com/c/go/+/351191 Run-TryBot: Martin Möhrmann TryBot-Result: Go Bot Reviewed-by: Martin Möhrmann Reviewed-by: Keith Randall Trust: Martin Möhrmann --- src/runtime/asm_amd64.s | 137 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 135 insertions(+), 2 deletions(-) diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index 3ab6060ec0..0f0e5be21a 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -78,6 +78,87 @@ GLOBL _rt0_amd64_lib_argc<>(SB),NOPTR, $8 DATA _rt0_amd64_lib_argv<>(SB)/8, $0 GLOBL _rt0_amd64_lib_argv<>(SB),NOPTR, $8 +#ifdef GOAMD64_v2 +DATA bad_cpu_msg<>+0x00(SB)/84, $"This program can only be run on AMD64 processors with v2 microarchitecture support.\n" +#endif + +#ifdef GOAMD64_v3 +DATA bad_cpu_msg<>+0x00(SB)/84, $"This program can only be run on AMD64 processors with v3 microarchitecture support.\n" +#endif + +#ifdef GOAMD64_v4 +DATA bad_cpu_msg<>+0x00(SB)/84, $"This program can only be run on AMD64 processors with v4 microarchitecture support.\n" +#endif + +GLOBL bad_cpu_msg<>(SB), RODATA, $84 + +// Define a list of AMD64 microarchitecture level features +// https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels + + // SSE3 SSSE3 CMPXCHNG16 SSE4.1 SSE4.2 POPCNT +#define V2_FEATURES_CX (1 << 0 | 1 << 9 | 1 << 13 | 1 << 19 | 1 << 20 | 1 << 23) + // LAHF/SAHF +#define V2_EXT_FEATURES_CX (1 << 0) + // FMA MOVBE OSXSAVE AVX F16C +#define V3_FEATURES_CX (V2_FEATURES_CX | 1 << 12 | 1 << 22 | 1 << 27 | 1 << 28 | 1 << 29) + // ABM (FOR LZNCT) +#define V3_EXT_FEATURES_CX (V2_EXT_FEATURES_CX | 1 << 5) + // BMI1 AVX2 BMI2 +#define V3_EXT_FEATURES_BX (1 << 3 | 1 << 5 | 1 << 8) + // XMM YMM +#define V3_OS_SUPPORT_AX (1 << 1 | 1 << 2) + +#define V4_FEATURES_CX V3_FEATURES_CX + +#define V4_EXT_FEATURES_CX V3_EXT_FEATURES_CX + // AVX512F AVX512DQ AVX512CD AVX512BW AVX512VL +#define V4_EXT_FEATURES_BX (V3_EXT_FEATURES_BX | 1 << 16 | 1 << 17 | 1 << 28 | 1 << 30 | 1 << 31) + // OPMASK ZMM +#define V4_OS_SUPPORT_AX (V3_OS_SUPPORT_AX | 1 << 5 | (1 << 6 | 1 << 7)) + +#ifdef GOAMD64_v2 +#define NEED_MAX_CPUID 0x80000001 +#define NEED_FEATURES_CX V2_FEATURES_CX +#define NEED_EXT_FEATURES_CX V2_EXT_FEATURES_CX +#endif + +#ifdef GOAMD64_v3 +#define NEED_MAX_CPUID 0x80000001 +#define NEED_FEATURES_CX V3_FEATURES_CX +#define NEED_EXT_FEATURES_CX V3_EXT_FEATURES_CX +#define NEED_EXT_FEATURES_BX V3_EXT_FEATURES_BX +#define NEED_OS_SUPPORT_AX V3_OS_SUPPORT_AX +#endif + +#ifdef GOAMD64_v4 +#define NEED_MAX_CPUID 0x80000001 +#define NEED_FEATURES_CX V4_FEATURES_CX +#define NEED_EXT_FEATURES_CX V4_EXT_FEATURES_CX +#define NEED_EXT_FEATURES_BX V4_EXT_FEATURES_BX + +// Downgrading v4 OS checks on Darwin for now, see CL 285572. +#ifdef GOOS_darwin +#define NEED_OS_SUPPORT_AX V3_OS_SUPPORT_AX +#else +#define NEED_OS_SUPPORT_AX V4_OS_SUPPORT_AX +#endif + +#endif + +#ifdef GOAMD64_v1 +#define SKIP_GOAMD64_CHECK +#endif + +#ifndef GOAMD64_v1 +#ifndef GOAMD64_v2 +#ifndef GOAMD64_v3 +#ifndef GOAMD64_v4 +#define SKIP_GOAMD64_CHECK +#endif +#endif +#endif +#endif + TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0 // copy arguments forward on an even stack MOVQ DI, AX // argc @@ -99,10 +180,24 @@ TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0 // find out information about the processor we're on MOVL $0, AX CPUID - MOVL AX, SI CMPL AX, $0 +#ifdef SKIP_GOAMD64_CHECK JE nocpuinfo +#else + JNE has_cpuinfo +bad_cpu: // show that the program requires a certain microarchitecture level. + MOVQ $2, 0(SP) + MOVQ $bad_cpu_msg<>(SB), AX + MOVQ AX, 8(SP) + MOVQ $84, 16(SP) + CALL runtime·write(SB) + MOVQ $1, 0(SP) + CALL runtime·exit(SB) + CALL runtime·abort(SB) +#endif + +has_cpuinfo: CMPL BX, $0x756E6547 // "Genu" JNE notintel CMPL DX, $0x49656E69 // "ineI" @@ -110,13 +205,51 @@ TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0 CMPL CX, $0x6C65746E // "ntel" JNE notintel MOVB $1, runtime·isIntel(SB) -notintel: +notintel: // Load EAX=1 cpuid flags MOVL $1, AX CPUID MOVL AX, runtime·processorVersionInfo(SB) +#ifdef NEED_FEATURES_CX + ANDL $NEED_FEATURES_CX, CX + CMPL CX, $NEED_FEATURES_CX + JNE bad_cpu +#endif + +#ifdef NEED_MAX_CPUID + MOVL $0x80000000, AX + CPUID + CMPL AX, $NEED_MAX_CPUID + JL bad_cpu +#endif + +#ifdef NEED_EXT_FEATURES_BX + MOVL $7, AX + MOVL $0, CX + CPUID + ANDL $NEED_EXT_FEATURES_BX, BX + CMPL BX, $NEED_EXT_FEATURES_BX + JNE bad_cpu +#endif + +#ifdef NEED_EXT_FEATURES_CX + MOVL $0x80000001, AX + CPUID + ANDL $NEED_EXT_FEATURES_CX, CX + CMPL CX, $NEED_EXT_FEATURES_CX + JNE bad_cpu +#endif + +#ifdef NEED_OS_SUPPORT_AX + XORL CX, CX + XGETBV + ANDL $NEED_OS_SUPPORT_AX, AX + CMPL AX, $NEED_OS_SUPPORT_AX + JNE bad_cpu +#endif + nocpuinfo: // if there is an _cgo_init, call it. MOVQ _cgo_init(SB), AX -- GitLab From c406380fa984d14a1f104fd2502d832565b45eb2 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 1 Nov 2021 14:46:35 -0400 Subject: [PATCH 1886/2500] go/types: better error messages for empty type sets This is a clean port of CL 358175 to go/types. Change-Id: If1b4e51d1579fd168e651d79d031335ff09ca128 Reviewed-on: https://go-review.googlesource.com/c/go/+/360474 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer --- src/go/types/instantiate.go | 32 +++++++++++++------ src/go/types/testdata/check/typeinst2.go2 | 28 +++++++++++++--- .../types/testdata/fixedbugs/issue47411.go2 | 2 +- src/go/types/typeset.go | 2 +- 4 files changed, 48 insertions(+), 16 deletions(-) diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 3720cb725a..8d8d281842 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -134,8 +134,16 @@ func (check *Checker) verify(pos token.Pos, tparams []*TypeParam, targs []Type) // TODO(gri) This should be a method of interfaces or type sets. func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap substMap) error { iface := tpar.iface() + + // Every type argument satisfies interface{}. if iface.Empty() { - return nil // no type bound + return nil + } + + // A type argument that is a type parameter with an empty type set satisfies any constraint. + // (The empty set is a subset of any set.) + if targ := asTypeParam(targ); targ != nil && targ.iface().typeSet().IsEmpty() { + return nil } // TODO(rfindley): it would be great if users could pass in a qualifier here, @@ -149,6 +157,11 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap return errors.New(sprintf(nil, qf, false, format, args...)) } + // No type argument with non-empty type set satisfies the empty type set. + if iface.typeSet().IsEmpty() { + return errorf("%s does not satisfy %s (constraint type set is empty)", targ, tpar.bound) + } + // The type parameter bound is parameterized with the same type parameters // as the instantiated type; before we can use it for bounds checking we // need to instantiate it with the type arguments with which we instantiate @@ -190,28 +203,27 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap } } - // targ's underlying type must also be one of the interface types listed, if any + // targ must also be in the set of types of iface, if any. + // Constraints with empty type sets were already excluded above. if !iface.typeSet().hasTerms() { return nil // nothing to do } - // If targ is itself a type parameter, each of its possible types, but at least one, must be in the - // list of iface types (i.e., the targ type list must be a non-empty subset of the iface types). + // If targ is itself a type parameter, each of its possible types must be in the set + // of iface types (i.e., the targ type set must be a subset of the iface type set). + // Type arguments with empty type sets were already excluded above. if targ := asTypeParam(targ); targ != nil { targBound := targ.iface() - if !targBound.typeSet().hasTerms() { - return errorf("%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ) - } if !targBound.typeSet().subsetOf(iface.typeSet()) { - // TODO(gri) need better error message + // TODO(gri) report which type is missing return errorf("%s does not satisfy %s", targ, tpar.bound) } return nil } - // Otherwise, targ's type or underlying type must also be one of the interface types listed, if any. + // Otherwise, targ's type must be included in the iface type set. if !iface.typeSet().includes(targ) { - // TODO(gri) better error message + // TODO(gri) report which type is missing return errorf("%s does not satisfy %s", targ, tpar.bound) } diff --git a/src/go/types/testdata/check/typeinst2.go2 b/src/go/types/testdata/check/typeinst2.go2 index 37d32263d4..ebcc300675 100644 --- a/src/go/types/testdata/check/typeinst2.go2 +++ b/src/go/types/testdata/check/typeinst2.go2 @@ -226,10 +226,10 @@ type I012 interface { } func f012[T I012]() {} -var _ = f012[int /* ERROR does not satisfy I012 */ ] -var _ = f012[bool /* ERROR does not satisfy I012 */ ] -var _ = f012[string /* ERROR does not satisfy I012 */ ] -var _ = f012[float64 /* ERROR does not satisfy I012 */ ] +var _ = f012[int /* ERROR does not satisfy I012.*type set is empty */ ] +var _ = f012[bool /* ERROR does not satisfy I012.*type set is empty */ ] +var _ = f012[string /* ERROR does not satisfy I012.*type set is empty */ ] +var _ = f012[float64 /* ERROR does not satisfy I012.*type set is empty */ ] type I12 interface { E1 @@ -256,3 +256,23 @@ var _ = f0_[float64 /* ERROR does not satisfy I0_ */ ] // Using a function instance as a type is an error. var _ f0 // ERROR not a type var _ f0 /* ERROR not a type */ [int] + +// Empty type sets can only be satisfied by empty type sets. +type none interface { + // force an empty type set + int + string +} + +func ff[T none]() {} +func gg[T any]() {} +func hh[T ~int]() {} + +func _[T none]() { + _ = ff[int /* ERROR int does not satisfy none \(constraint type set is empty\) */ ] + _ = ff[T] // pathological but ok because T's type set is empty, too + _ = gg[int] + _ = gg[T] + _ = hh[int] + _ = hh[T] +} diff --git a/src/go/types/testdata/fixedbugs/issue47411.go2 b/src/go/types/testdata/fixedbugs/issue47411.go2 index 2fc26d9e85..fde704bb41 100644 --- a/src/go/types/testdata/fixedbugs/issue47411.go2 +++ b/src/go/types/testdata/fixedbugs/issue47411.go2 @@ -19,7 +19,7 @@ func _[P comparable, _ = f[R /* ERROR R has no constraints */ ] _ = g[int] - _ = g[P /* ERROR P has no type constraints */ ] + _ = g[P /* ERROR P does not satisfy interface{interface{comparable; ~int\|~string} */ ] _ = g[Q] _ = g[func /* ERROR does not satisfy comparable */()] _ = g[R /* ERROR R has no constraints */ ] diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index a1893d0588..d6c4e5cd8c 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -99,7 +99,7 @@ func (s *_TypeSet) String() string { // ---------------------------------------------------------------------------- // Implementation -func (s *_TypeSet) hasTerms() bool { return !s.terms.isAll() } +func (s *_TypeSet) hasTerms() bool { return !s.terms.isEmpty() && !s.terms.isAll() } func (s *_TypeSet) structuralType() Type { return s.terms.structuralType() } func (s *_TypeSet) includes(t Type) bool { return s.terms.includes(t) } func (s1 *_TypeSet) subsetOf(s2 *_TypeSet) bool { return s1.terms.subsetOf(s2.terms) } -- GitLab From af8aafd570bca4f78b434e7633bf33b6e186931c Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 1 Nov 2021 15:03:53 -0400 Subject: [PATCH 1887/2500] go/types: clarify is/underIs semantics and implementation This is a port of CL 358594 to go/types. Some code in conversions.go had to be trivially reorganized to align with types2 -- I'm not sure how go/types diverged from the base. Change-Id: I40ce247bbb3b9d0e87ce88c50e440c12774c0745 Reviewed-on: https://go-review.googlesource.com/c/go/+/360475 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer --- src/go/types/builtins.go | 5 +++- src/go/types/conversions.go | 18 ++++++++++----- src/go/types/expr.go | 2 ++ src/go/types/infer.go | 2 +- src/go/types/operand.go | 3 +++ src/go/types/typeparam.go | 11 +++++++++ src/go/types/typeset.go | 46 +++++++++++++++++++------------------ 7 files changed, 57 insertions(+), 30 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index de7d7e6b5f..87c26775a6 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -843,7 +843,10 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { // Test if t satisfies the requirements for the argument // type and collect possible result types at the same time. var terms []*Term - if !tp.iface().typeSet().is(func(t *term) bool { + if !tp.is(func(t *term) bool { + if t == nil { + return false + } if r := f(t.typ); r != nil { terms = append(terms, NewTerm(t.tilde, r)) return true diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go index fe62adbf10..8c8b63e23a 100644 --- a/src/go/types/conversions.go +++ b/src/go/types/conversions.go @@ -20,7 +20,7 @@ func (check *Checker) conversion(x *operand, T Type) { var cause string switch { case constArg && isConstType(T): - // constant conversion + // constant conversion (T cannot be a type parameter) switch t := asBasic(T); { case representableConst(x.val, check, t, &x.val): ok = true @@ -92,6 +92,16 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { return true } + // determine type parameter operands with specific type terms + Vp, _ := under(x.typ).(*TypeParam) + Tp, _ := under(T).(*TypeParam) + if Vp != nil && !Vp.hasTerms() { + Vp = nil + } + if Tp != nil && !Tp.hasTerms() { + Tp = nil + } + errorf := func(format string, args ...interface{}) { if check != nil && cause != nil { msg := check.sprintf(format, args...) @@ -102,11 +112,7 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { } } - // TODO(gri) consider passing under(x.typ), under(T) into convertibleToImpl (optimization) - Vp, _ := under(x.typ).(*TypeParam) - Tp, _ := under(T).(*TypeParam) - - // generic cases + // generic cases with specific type terms // (generic operands cannot be constants, so we can ignore x.val) switch { case Vp != nil && Tp != nil: diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 8b26e64971..ef5958ba3f 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -142,6 +142,8 @@ var op2str2 = [...]string{ token.SHL: "shift", } +// If typ is a type parameter, underIs returns the result of typ.underIs(f). +// Otherwise, underIs returns the result of f(under(typ)). func underIs(typ Type, f func(Type) bool) bool { u := under(typ) if tpar, _ := u.(*TypeParam); tpar != nil { diff --git a/src/go/types/infer.go b/src/go/types/infer.go index 43b9af348e..9302bd7f57 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -315,7 +315,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { } } return tset.is(func(t *term) bool { - return w.isParameterized(t.typ) + return t != nil && w.isParameterized(t.typ) }) case *Map: diff --git a/src/go/types/operand.go b/src/go/types/operand.go index 855dac66aa..ef7d764201 100644 --- a/src/go/types/operand.go +++ b/src/go/types/operand.go @@ -258,6 +258,9 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er if t, _ := under(T).(*TypeParam); t != nil { return t.is(func(t *term) bool { // TODO(gri) this could probably be more efficient + if t == nil { + return false + } if t.tilde { // TODO(gri) We need to check assignability // for the underlying type of x. diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index af36266f11..791e9db8f8 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -123,10 +123,21 @@ func (t *TypeParam) structuralType() Type { return t.iface().typeSet().structuralType() } +// hasTerms reports whether the type parameter constraint has specific type terms. +func (t *TypeParam) hasTerms() bool { + return t.iface().typeSet().hasTerms() +} + +// is calls f with the specific type terms of t's constraint and reports whether +// all calls to f returned true. If there are no specific terms, is +// returns the result of f(nil). func (t *TypeParam) is(f func(*term) bool) bool { return t.iface().typeSet().is(f) } +// underIs calls f with the underlying types of the specific type terms +// of t's constraint and reports whether all calls to f returned true. +// If there are no specific terms, underIs returns the result of f(nil). func (t *TypeParam) underIs(f func(Type) bool) bool { return t.iface().typeSet().underIs(f) } diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index d6c4e5cd8c..215b48488f 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -37,7 +37,7 @@ func (s *_TypeSet) IsComparable() bool { return s.comparable } return s.is(func(t *term) bool { - return Comparable(t.typ) + return t != nil && Comparable(t.typ) }) } @@ -99,27 +99,29 @@ func (s *_TypeSet) String() string { // ---------------------------------------------------------------------------- // Implementation -func (s *_TypeSet) hasTerms() bool { return !s.terms.isEmpty() && !s.terms.isAll() } -func (s *_TypeSet) structuralType() Type { return s.terms.structuralType() } -func (s *_TypeSet) includes(t Type) bool { return s.terms.includes(t) } +// hasTerms reports whether the type set has specific type terms. +func (s *_TypeSet) hasTerms() bool { return !s.terms.isEmpty() && !s.terms.isAll() } + +// structuralType returns the single type in s if there is exactly one; otherwise the result is nil. +func (s *_TypeSet) structuralType() Type { return s.terms.structuralType() } + +// includes reports whether t ∈ s. +func (s *_TypeSet) includes(t Type) bool { return s.terms.includes(t) } + +// subsetOf reports whether s1 ⊆ s2. func (s1 *_TypeSet) subsetOf(s2 *_TypeSet) bool { return s1.terms.subsetOf(s2.terms) } // TODO(gri) TypeSet.is and TypeSet.underIs should probably also go into termlist.go -var topTerm = term{false, theTop} - +// is calls f with the specific type terms of s and reports whether +// all calls to f returned true. If there are no specific terms, is +// returns the result of f(nil). func (s *_TypeSet) is(f func(*term) bool) bool { - if len(s.terms) == 0 { - return false + if !s.hasTerms() { + return f(nil) } for _, t := range s.terms { - // Terms represent the top term with a nil type. - // The rest of the type checker uses the top type - // instead. Convert. - // TODO(gri) investigate if we can do without this - if t.typ == nil { - t = &topTerm - } + assert(t.typ != nil) if !f(t) { return false } @@ -127,17 +129,17 @@ func (s *_TypeSet) is(f func(*term) bool) bool { return true } +// underIs calls f with the underlying types of the specific type terms +// of s and reports whether all calls to f returned true. If there are +// no specific terms, is returns the result of f(nil). func (s *_TypeSet) underIs(f func(Type) bool) bool { - if len(s.terms) == 0 { - return false + if !s.hasTerms() { + return f(nil) } for _, t := range s.terms { - // see corresponding comment in TypeSet.is + assert(t.typ != nil) + // x == under(x) for ~x terms u := t.typ - if u == nil { - u = theTop - } - // t == under(t) for ~t terms if !t.tilde { u = under(u) } -- GitLab From 62b29b035948c08041e4218d0b176d057c8a6f6f Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 1 Nov 2021 15:11:31 -0400 Subject: [PATCH 1888/2500] go/types: generalize assignability to generic types This is a port of CL 357917 to go/types. Some error messages in assignability.go2 had to be adjusted. I left a TODO to investigate whether we should align error messages. Change-Id: Ia323ffe18bc08e82de62044f35b8b0f3edd7dc08 Reviewed-on: https://go-review.googlesource.com/c/go/+/360476 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer --- src/go/types/check_test.go | 1 + src/go/types/operand.go | 107 ++++++-- src/go/types/testdata/spec/assignability.go2 | 236 ++++++++++++++++++ .../{examples => spec}/conversions.go2 | 0 4 files changed, 318 insertions(+), 26 deletions(-) create mode 100644 src/go/types/testdata/spec/assignability.go2 rename src/go/types/testdata/{examples => spec}/conversions.go2 (100%) diff --git a/src/go/types/check_test.go b/src/go/types/check_test.go index e6176738d1..75b26e34bd 100644 --- a/src/go/types/check_test.go +++ b/src/go/types/check_test.go @@ -359,6 +359,7 @@ func TestIssue47243_TypedRHS(t *testing.T) { } func TestCheck(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/check", false) } +func TestSpec(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/spec", false) } func TestExamples(t *testing.T) { testDirFiles(t, "testdata/examples", false) } func TestFixedbugs(t *testing.T) { testDirFiles(t, "testdata/fixedbugs", false) } diff --git a/src/go/types/operand.go b/src/go/types/operand.go index ef7d764201..0ba3c4bafc 100644 --- a/src/go/types/operand.go +++ b/src/go/types/operand.go @@ -234,53 +234,46 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er V := x.typ - const debugAssignableTo = false - if debugAssignableTo && check != nil { - check.dump("V = %s", V) - check.dump("T = %s", T) - } - // x's type is identical to T if Identical(V, T) { return true, 0 } - Vu := optype(V) - Tu := optype(T) - - if debugAssignableTo && check != nil { - check.dump("Vu = %s", Vu) - check.dump("Tu = %s", Tu) - } + Vu := under(V) + Tu := under(T) + Vp, _ := Vu.(*TypeParam) + Tp, _ := Tu.(*TypeParam) // x is an untyped value representable by a value of type T. if isUntyped(Vu) { - if t, _ := under(T).(*TypeParam); t != nil { - return t.is(func(t *term) bool { - // TODO(gri) this could probably be more efficient + assert(Vp == nil) + if Tp != nil { + // T is a type parameter: x is assignable to T if it is + // representable by each specific type in the type set of T. + return Tp.is(func(t *term) bool { if t == nil { return false } - if t.tilde { - // TODO(gri) We need to check assignability - // for the underlying type of x. - } - ok, _ := x.assignableTo(check, t.typ, reason) - return ok + // A term may be a tilde term but the underlying + // type of an untyped value doesn't change so we + // don't need to do anything special. + newType, _, _ := check.implicitTypeAndValue(x, t.typ) + return newType != nil }), _IncompatibleAssign } - newType, _, _ := check.implicitTypeAndValue(x, Tu) + newType, _, _ := check.implicitTypeAndValue(x, T) return newType != nil, _IncompatibleAssign } // Vu is typed // x's type V and T have identical underlying types // and at least one of V or T is not a named type - if Identical(Vu, Tu) && (!isNamed(V) || !isNamed(T)) { + // and neither is a type parameter. + if Identical(Vu, Tu) && (!isNamed(V) || !isNamed(T)) && Vp == nil && Tp == nil { return true, 0 } - // T is an interface type and x implements T + // T is an interface type and x implements T and T is not a type parameter if Ti, ok := Tu.(*Interface); ok { if m, wrongType := check.missingMethod(V, Ti, true); m != nil /* Implements(V, Ti) */ { if reason != nil { @@ -310,5 +303,67 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er } } - return false, _IncompatibleAssign + // common case: if we don't have type parameters, we're done + if Vp == nil && Tp == nil { + return false, _IncompatibleAssign + } + + // determine type parameter operands with specific type terms + if Vp != nil && !Vp.hasTerms() { + Vp = nil + } + if Tp != nil && !Tp.hasTerms() { + Tp = nil + } + + errorf := func(format string, args ...interface{}) { + if check != nil && reason != nil { + msg := check.sprintf(format, args...) + if *reason != "" { + msg += "\n\t" + *reason + } + *reason = msg + } + } + + ok := false + code := _IncompatibleAssign + switch { + case Vp != nil && Tp != nil: + x := *x // don't clobber outer x + ok = Vp.is(func(V *term) bool { + x.typ = V.typ + return Tp.is(func(T *term) bool { + ok, code = x.assignableTo(check, T.typ, reason) + if !ok { + errorf("cannot assign %s (in %s) to %s (in %s)", V.typ, Vp, T.typ, Tp) + return false + } + return true + }) + }) + case Vp != nil: + x := *x // don't clobber outer x + ok = Vp.is(func(V *term) bool { + x.typ = V.typ + ok, code = x.assignableTo(check, T, reason) + if !ok { + errorf("cannot assign %s (in %s) to %s", V.typ, Vp, T) + return false + } + return true + }) + case Tp != nil: + x := *x // don't clobber outer x + ok = Tp.is(func(T *term) bool { + ok, code = x.assignableTo(check, T.typ, reason) + if !ok { + errorf("cannot assign %s to %s (in %s)", x.typ, T.typ, Tp) + return false + } + return true + }) + } + + return ok, code } diff --git a/src/go/types/testdata/spec/assignability.go2 b/src/go/types/testdata/spec/assignability.go2 new file mode 100644 index 0000000000..4c6774b811 --- /dev/null +++ b/src/go/types/testdata/spec/assignability.go2 @@ -0,0 +1,236 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package assignability + +// See the end of this package for the declarations +// of the types and variables used in these tests. + +// "x's type is identical to T" +func _[TP any](X TP) { + b = b + a = a + l = l + s = s + p = p + f = f + i = i + m = m + c = c + d = d + + B = B + A = A + L = L + S = S + P = P + F = F + I = I + M = M + C = C + D = D + X = X +} + +// "x's type V and T have identical underlying types and at least one +// of V or T is not a defined type and neither is a type parameter" +func _[TP1, TP2 Interface](X1 TP1, X2 TP2) { + b = B // ERROR cannot use B .* as int value + a = A + l = L + s = S + p = P + f = F + i = I + m = M + c = C + d = D + + B = b // ERROR cannot use b .* as Basic value + A = a + L = l + S = s + P = p + F = f + I = i + M = m + C = c + D = d + X1 = i // ERROR cannot use i .* as TP1 value + X1 = X2 // ERROR cannot use X2 .* as TP1 value +} + +// "T is an interface type and x implements T and T is not a type parameter" +func _[TP Interface](X TP) { + i = d // ERROR missing method m + i = D + i = X + X = i // ERROR cannot use i .* as TP value +} + +// "x is a bidirectional channel value, T is a channel type, x's type V and T have identical element types, and at least one of V or T is not a defined type" +type ( + _SendChan = chan<- int + _RecvChan = <-chan int + + SendChan _SendChan + RecvChan _RecvChan +) + +func _[ + _CC ~_Chan, + _SC ~_SendChan, + _RC ~_RecvChan, + + CC Chan, + SC SendChan, + RC RecvChan, +]() { + var ( + _ _SendChan = c + _ _RecvChan = c + _ _Chan = c + + _ _SendChan = C + _ _RecvChan = C + _ _Chan = C + + _ SendChan = c + _ RecvChan = c + _ Chan = c + + _ SendChan = C // ERROR cannot use C .* as SendChan value + _ RecvChan = C // ERROR cannot use C .* as RecvChan value + _ Chan = C + _ Chan = make /* ERROR cannot use make\(chan Basic\) .* as Chan value */ (chan Basic) + ) + + var ( + _ _CC = C + _ _SC = C + _ _RC = C + + _ CC = _CC(nil) + _ SC = _CC(nil) + _ RC = _CC(nil) + + _ CC = C + _ SC = C // ERROR cannot use C .* as SC value .* cannot assign Chan to SendChan + _ RC = C // ERROR cannot use C .* as RC value .* cannot assign Chan to RecvChan + ) +} + +// "x is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type" +// TODO(rfindley) error messages about untyped nil diverge from types2 here. +// Consider aligning them. +func _[TP Interface](X TP) { + b = nil // ERROR cannot use.*untyped nil + a = nil // ERROR cannot use.*untyped nil + l = nil + s = nil // ERROR cannot use.*untyped nil + p = nil + f = nil + i = nil + m = nil + c = nil + d = nil // ERROR cannot use.*untyped nil + + B = nil // ERROR cannot use.*untyped nil + A = nil // ERROR cannot use.*untyped nil + L = nil + S = nil // ERROR cannot use.*untyped nil + P = nil + F = nil + I = nil + M = nil + C = nil + D = nil // ERROR cannot use.*untyped nil + X = nil // ERROR cannot use.*untyped nil +} + +// "x is an untyped constant representable by a value of type T" +func _[ + Int8 ~int8, + Int16 ~int16, + Int32 ~int32, + Int64 ~int64, + Int8_16 ~int8 | ~int16, +]( + i8 Int8, + i16 Int16, + i32 Int32, + i64 Int64, + i8_16 Int8_16, +) { + b = 42 + b = 42.0 + // etc. + + i8 = -1 << 7 + i8 = 1<<7 - 1 + i16 = -1 << 15 + i16 = 1<<15 - 1 + i32 = -1 << 31 + i32 = 1<<31 - 1 + i64 = -1 << 63 + i64 = 1<<63 - 1 + + i8_16 = -1 << 7 + i8_16 = 1<<7 - 1 + i8_16 = - /* ERROR cannot use .* as Int8_16 */ 1 << 15 + i8_16 = 1 /* ERROR cannot use .* as Int8_16 */ <<15 - 1 +} + +// proto-types for tests + +type ( + _Basic = int + _Array = [10]int + _Slice = []int + _Struct = struct{ f int } + _Pointer = *int + _Func = func(x int) string + _Interface = interface{ m() int } + _Map = map[string]int + _Chan = chan int + + Basic _Basic + Array _Array + Slice _Slice + Struct _Struct + Pointer _Pointer + Func _Func + Interface _Interface + Map _Map + Chan _Chan + Defined _Struct +) + +func (Defined) m() int + +// proto-variables for tests + +var ( + b _Basic + a _Array + l _Slice + s _Struct + p _Pointer + f _Func + i _Interface + m _Map + c _Chan + d _Struct + + B Basic + A Array + L Slice + S Struct + P Pointer + F Func + I Interface + M Map + C Chan + D Defined +) diff --git a/src/go/types/testdata/examples/conversions.go2 b/src/go/types/testdata/spec/conversions.go2 similarity index 100% rename from src/go/types/testdata/examples/conversions.go2 rename to src/go/types/testdata/spec/conversions.go2 -- GitLab From 4e7dd9fc08fb5aa86773b65d865719d96f67f49d Mon Sep 17 00:00:00 2001 From: "Paul E. Murphy" Date: Tue, 19 Oct 2021 11:17:53 -0500 Subject: [PATCH 1889/2500] bytes: test for page boundary crosses on sep of Index Improve TestIndexNearPageBoundary to verify needles ending on a page boundary don't cause a segfault. Change-Id: I2edb13db63a71dc9955e266f6b97026ee13bf76e Reviewed-on: https://go-review.googlesource.com/c/go/+/356889 Reviewed-by: Cherry Mui Trust: Lynn Boger --- src/bytes/boundary_test.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/bytes/boundary_test.go b/src/bytes/boundary_test.go index 8dac751866..f9855fcb05 100644 --- a/src/bytes/boundary_test.go +++ b/src/bytes/boundary_test.go @@ -65,7 +65,11 @@ func TestIndexByteNearPageBoundary(t *testing.T) { func TestIndexNearPageBoundary(t *testing.T) { t.Parallel() - var q [64]byte + q := dangerousSlice(t) + if len(q) > 64 { + // Only worry about when we're near the end of a page. + q = q[len(q)-64:] + } b := dangerousSlice(t) if len(b) > 256 { // Only worry about when we're near the end of a page. @@ -81,4 +85,16 @@ func TestIndexNearPageBoundary(t *testing.T) { } q[j-1] = 0 } + + // Test differing alignments and sizes of q which always end on a page boundary. + q[len(q)-1] = 1 // difference is only found on the last byte + for j := 0; j < len(q); j++ { + for i := range b { + idx := Index(b[i:], q[j:]) + if idx != -1 { + t.Fatalf("Index(b[%d:], q[%d:])=%d, want -1\n", i, j, idx) + } + } + } + q[len(q)-1] = 0 } -- GitLab From 7548327374844719bf90cce199e7fa4b43b94e2b Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 2 Nov 2021 10:14:29 -0700 Subject: [PATCH 1890/2500] comd/compile/internal/types2: add missing nil check in const conversion Follow-up on CL 360396. Fixes #49296. Change-Id: Ie08f86ae884da4cfd5db557cbf4f721a237dc39f Reviewed-on: https://go-review.googlesource.com/c/go/+/360796 Trust: Robert Griesemer Reviewed-by: Robert Findley --- .../compile/internal/types2/conversions.go | 2 ++ .../types2/testdata/fixedbugs/issue49296.go2 | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue49296.go2 diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go index 0e26a73cf8..4d0ed79c38 100644 --- a/src/cmd/compile/internal/types2/conversions.go +++ b/src/cmd/compile/internal/types2/conversions.go @@ -18,6 +18,8 @@ func (check *Checker) conversion(x *operand, T Type) { constConvertibleTo := func(T Type, val *constant.Value) bool { switch t := asBasic(T); { + case t == nil: + // nothing to do case representableConst(x.val, check, t, val): return true case isInteger(x.typ) && isString(t): diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49296.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49296.go2 new file mode 100644 index 0000000000..8f52acc8a4 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49296.go2 @@ -0,0 +1,20 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func _[ + T0 any, + T1 []int, + T2 ~float64 | ~complex128 | chan int, +]() { + _ = T0(nil /* ERROR cannot convert untyped nil to T0 */ ) + _ = T1(1 /* ERROR cannot convert 1 .* to T1 */ ) + _ = T2(2 /* ERROR cannot convert 2 .* to T2 */ ) +} + +// test case from issue +func f[T interface{[]int}]() { + _ = T(1 /* ERROR cannot convert */ ) +} -- GitLab From 4ec52e363e93baa859cbdec23f997a489cfeca11 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 20 Oct 2021 13:17:07 -0700 Subject: [PATCH 1891/2500] go/types: add check that code is monomorphizable This CL adds a check to ensure that generic Go code doesn't involve any unbounded recursive instantiation, which are incompatible with an implementation that uses static instantiation (i.e., monomorphization or compile-time dictionary construction). Updates #48098. Change-Id: I9d051f0f9369ab881592a361a5d0e2a716788a6b Reviewed-on: https://go-review.googlesource.com/c/go/+/357449 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer Trust: Matthew Dempsky --- src/go/types/call.go | 2 + src/go/types/check.go | 6 + src/go/types/errorcodes.go | 7 + src/go/types/mono.go | 331 ++++++++++++++++++ src/go/types/mono_test.go | 92 +++++ src/go/types/signature.go | 1 + .../types/testdata/fixedbugs/issue48974.go2 | 2 +- src/go/types/typexpr.go | 2 + 8 files changed, 442 insertions(+), 1 deletion(-) create mode 100644 src/go/types/mono.go create mode 100644 src/go/types/mono_test.go diff --git a/src/go/types/call.go b/src/go/types/call.go index 6894f1c182..36086891b5 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -91,6 +91,8 @@ func (check *Checker) instantiateSignature(pos token.Pos, typ *Signature, targs pos = posList[i] } check.softErrorf(atPos(pos), _Todo, err.Error()) + } else { + check.mono.recordInstance(check.pkg, pos, tparams, targs, posList) } return inst diff --git a/src/go/types/check.go b/src/go/types/check.go index 2b8ef9f061..3a0e4a6a23 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -129,6 +129,7 @@ type Checker struct { imports []*PkgName // list of imported packages dotImportMap map[dotImportKey]*PkgName // maps dot-imported objects to the package they were dot-imported through recvTParamMap map[*ast.Ident]*TypeParam // maps blank receiver type parameters to their type + mono monoGraph // graph for detecting non-monomorphizable instantiation loops firstErr error // first error encountered methods map[*TypeName][]*Func // maps package scope type names to associated non-blank (non-interface) methods @@ -306,6 +307,11 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) { check.recordUntyped() + if check.firstErr == nil { + // TODO(mdempsky): Ensure monomorph is safe when errors exist. + check.monomorph() + } + check.pkg.complete = true // no longer needed - release memory diff --git a/src/go/types/errorcodes.go b/src/go/types/errorcodes.go index 49c6a74c20..88dd0fda2f 100644 --- a/src/go/types/errorcodes.go +++ b/src/go/types/errorcodes.go @@ -1301,6 +1301,13 @@ const ( // var _ = unsafe.Slice(&x, uint64(1) << 63) _InvalidUnsafeSlice + // _InvalidInstanceCycle occurs when an invalid cycle is detected + // within the instantiation graph. + // + // Example: + // func f[T any]() { f[*T]() } + _InvalidInstanceCycle + // _Todo is a placeholder for error codes that have not been decided. // TODO(rFindley) remove this error code after deciding on errors for generics code. _Todo diff --git a/src/go/types/mono.go b/src/go/types/mono.go new file mode 100644 index 0000000000..fb1127e959 --- /dev/null +++ b/src/go/types/mono.go @@ -0,0 +1,331 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +import ( + "go/token" +) + +// This file implements a check to validate that a Go package doesn't +// have unbounded recursive instantiation, which is not compatible +// with compilers using static instantiation (such as +// monomorphization). +// +// It implements a sort of "type flow" analysis by detecting which +// type parameters are instantiated with other type parameters (or +// types derived thereof). A package cannot be statically instantiated +// if the graph has any cycles involving at least one derived type. +// +// Concretely, we construct a directed, weighted graph. Vertices are +// used to represent type parameters as well as some defined +// types. Edges are used to represent how types depend on each other: +// +// * Everywhere a type-parameterized function or type is instantiated, +// we add edges to each type parameter from the vertices (if any) +// representing each type parameter or defined type referenced by +// the type argument. If the type argument is just the referenced +// type itself, then the edge has weight 0, otherwise 1. +// +// * For every defined type declared within a type-parameterized +// function or method, we add an edge of weight 1 to the defined +// type from each ambient type parameter. +// +// For example, given: +// +// func f[A, B any]() { +// type T int +// f[T, map[A]B]() +// } +// +// we construct vertices representing types A, B, and T. Because of +// declaration "type T int", we construct edges T<-A and T<-B with +// weight 1; and because of instantiation "f[T, map[A]B]" we construct +// edges A<-T with weight 0, and B<-A and B<-B with weight 1. +// +// Finally, we look for any positive-weight cycles. Zero-weight cycles +// are allowed because static instantiation will reach a fixed point. + +type monoGraph struct { + vertices []monoVertex + edges []monoEdge + + // canon maps method receiver type parameters to their respective + // receiver type's type parameters. + canon map[*TypeParam]*TypeParam + + // nameIdx maps a defined type or (canonical) type parameter to its + // vertex index. + nameIdx map[*TypeName]int +} + +type monoVertex struct { + weight int // weight of heaviest known path to this vertex + pre int // previous edge (if any) in the above path + len int // length of the above path + + // obj is the defined type or type parameter represented by this + // vertex. + obj *TypeName +} + +type monoEdge struct { + dst int + src int + weight int + + // report emits an error describing why this edge exists. + // + // TODO(mdempsky): Avoid requiring a function closure for each edge. + report func(check *Checker) +} + +func (check *Checker) monomorph() { + // We detect unbounded instantiation cycles using a variant of + // Bellman-Ford's algorithm. Namely, instead of always running |V| + // iterations, we run until we either reach a fixed point or we've + // found a path of length |V|. This allows us to terminate earlier + // when there are no cycles, which should be the common case. + + again := true + for again { + again = false + + for i, edge := range check.mono.edges { + src := &check.mono.vertices[edge.src] + dst := &check.mono.vertices[edge.dst] + + // N.B., we're looking for the greatest weight paths, unlike + // typical Bellman-Ford. + w := src.weight + edge.weight + if w <= dst.weight { + continue + } + + dst.pre = i + dst.len = src.len + 1 + if dst.len == len(check.mono.vertices) { + check.reportInstanceLoop(edge.dst) + return + } + + dst.weight = w + again = true + } + } +} + +func (check *Checker) reportInstanceLoop(v int) { + var stack []int + seen := make([]bool, len(check.mono.vertices)) + + // We have a path that contains a cycle and ends at v, but v may + // only be reachable from the cycle, not on the cycle itself. We + // start by walking backwards along the path until we find a vertex + // that appears twice. + for !seen[v] { + stack = append(stack, v) + seen[v] = true + v = check.mono.edges[check.mono.vertices[v].pre].src + } + + // Trim any vertices we visited before visiting v the first + // time. Since v is the first vertex we found within the cycle, any + // vertices we visited earlier cannot be part of the cycle. + for stack[0] != v { + stack = stack[1:] + } + + // TODO(mdempsky): Pivot stack so we report the cycle from the top? + + obj := check.mono.vertices[v].obj + check.errorf(obj, _InvalidInstanceCycle, "instantiation cycle:") + + for _, v := range stack { + edge := check.mono.edges[check.mono.vertices[v].pre] + edge.report(check) + } +} + +// recordCanon records that tpar is the canonical type parameter +// corresponding to method type parameter mpar. +func (w *monoGraph) recordCanon(mpar, tpar *TypeParam) { + if w.canon == nil { + w.canon = make(map[*TypeParam]*TypeParam) + } + w.canon[mpar] = tpar +} + +// recordInstance records that the given type parameters were +// instantiated with the corresponding type arguments. +func (w *monoGraph) recordInstance(pkg *Package, pos token.Pos, tparams []*TypeParam, targs []Type, posList []token.Pos) { + for i, tpar := range tparams { + pos := pos + if i < len(posList) { + pos = posList[i] + } + w.assign(pkg, pos, tpar, targs[i]) + } +} + +// assign records that tpar was instantiated as targ at pos. +func (w *monoGraph) assign(pkg *Package, pos token.Pos, tpar *TypeParam, targ Type) { + // Go generics do not have an analog to C++`s template-templates, + // where a template parameter can itself be an instantiable + // template. So any instantiation cycles must occur within a single + // package. Accordingly, we can ignore instantiations of imported + // type parameters. + // + // TODO(mdempsky): Push this check up into recordInstance? All type + // parameters in a list will appear in the same package. + if tpar.Obj().Pkg() != pkg { + return + } + + // flow adds an edge from vertex src representing that typ flows to tpar. + flow := func(src int, typ Type) { + weight := 1 + if typ == targ { + weight = 0 + } + + w.addEdge(w.typeParamVertex(tpar), src, weight, func(check *Checker) { + qf := RelativeTo(check.pkg) + check.errorf(atPos(pos), _InvalidInstanceCycle, "\t%s instantiated as %s", tpar.Obj().Name(), TypeString(targ, qf)) // secondary error, \t indented + }) + } + + // Recursively walk the type argument to find any defined types or + // type parameters. + var do func(typ Type) + do = func(typ Type) { + switch typ := typ.(type) { + default: + panic("unexpected type") + + case *TypeParam: + assert(typ.Obj().Pkg() == pkg) + flow(w.typeParamVertex(typ), typ) + + case *Named: + if src := w.localNamedVertex(pkg, typ.Origin()); src >= 0 { + flow(src, typ) + } + + targs := typ.TypeArgs() + for i := 0; i < targs.Len(); i++ { + do(targs.At(i)) + } + + case *Array: + do(typ.Elem()) + case *Basic: + // ok + case *Chan: + do(typ.Elem()) + case *Map: + do(typ.Key()) + do(typ.Elem()) + case *Pointer: + do(typ.Elem()) + case *Slice: + do(typ.Elem()) + + case *Interface: + for i := 0; i < typ.NumMethods(); i++ { + do(typ.Method(i).Type()) + } + case *Signature: + tuple := func(tup *Tuple) { + for i := 0; i < tup.Len(); i++ { + do(tup.At(i).Type()) + } + } + tuple(typ.Params()) + tuple(typ.Results()) + case *Struct: + for i := 0; i < typ.NumFields(); i++ { + do(typ.Field(i).Type()) + } + } + } + do(targ) +} + +// localNamedVertex returns the index of the vertex representing +// named, or -1 if named doesn't need representation. +func (w *monoGraph) localNamedVertex(pkg *Package, named *Named) int { + obj := named.Obj() + if obj.Pkg() != pkg { + return -1 // imported type + } + + root := pkg.Scope() + if obj.Parent() == root { + return -1 // package scope, no ambient type parameters + } + + if idx, ok := w.nameIdx[obj]; ok { + return idx + } + + idx := -1 + + // Walk the type definition's scope to find any ambient type + // parameters that it's implicitly parameterized by. + for scope := obj.Parent(); scope != root; scope = scope.Parent() { + for _, elem := range scope.elems { + if elem, ok := elem.(*TypeName); ok && !elem.IsAlias() && elem.Pos() < obj.Pos() { + if tpar, ok := elem.Type().(*TypeParam); ok { + if idx < 0 { + idx = len(w.vertices) + w.vertices = append(w.vertices, monoVertex{obj: obj}) + } + + w.addEdge(idx, w.typeParamVertex(tpar), 1, func(check *Checker) { + check.errorf(obj, _InvalidInstanceCycle, "\t%s implicitly parameterized by %s", obj.Name(), elem.Name()) + }) + } + } + } + } + + if w.nameIdx == nil { + w.nameIdx = make(map[*TypeName]int) + } + w.nameIdx[obj] = idx + return idx +} + +// typeParamVertex returns the index of the vertex representing tpar. +func (w *monoGraph) typeParamVertex(tpar *TypeParam) int { + if x, ok := w.canon[tpar]; ok { + tpar = x + } + + obj := tpar.Obj() + + if idx, ok := w.nameIdx[obj]; ok { + return idx + } + + if w.nameIdx == nil { + w.nameIdx = make(map[*TypeName]int) + } + + idx := len(w.vertices) + w.vertices = append(w.vertices, monoVertex{obj: obj}) + w.nameIdx[obj] = idx + return idx +} + +func (w *monoGraph) addEdge(dst, src, weight int, report func(check *Checker)) { + // TODO(mdempsky): Deduplicate redundant edges? + w.edges = append(w.edges, monoEdge{ + dst: dst, + src: src, + weight: weight, + report: report, + }) +} diff --git a/src/go/types/mono_test.go b/src/go/types/mono_test.go new file mode 100644 index 0000000000..c4c5282427 --- /dev/null +++ b/src/go/types/mono_test.go @@ -0,0 +1,92 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types_test + +import ( + "bytes" + "errors" + "fmt" + "go/ast" + "go/importer" + "go/parser" + "go/token" + "go/types" + "strings" + "testing" +) + +func checkMono(t *testing.T, body string) error { + fset := token.NewFileSet() + file, err := parser.ParseFile(fset, "x.go", "package x; import `unsafe`; var _ unsafe.Pointer;\n"+body, 0) + if err != nil { + t.Fatal(err) + } + files := []*ast.File{file} + + var buf bytes.Buffer + conf := types.Config{ + Error: func(err error) { fmt.Fprintln(&buf, err) }, + Importer: importer.Default(), + } + conf.Check("x", fset, files, nil) + if buf.Len() == 0 { + return nil + } + return errors.New(strings.TrimRight(buf.String(), "\n")) +} + +func TestMonoGood(t *testing.T) { + for i, good := range goods { + if err := checkMono(t, good); err != nil { + t.Errorf("%d: unexpected failure: %v", i, err) + } + } +} + +func TestMonoBad(t *testing.T) { + for i, bad := range bads { + if err := checkMono(t, bad); err == nil { + t.Errorf("%d: unexpected success", i) + } else { + t.Log(err) + } + } +} + +var goods = []string{ + "func F[T any](x T) { F(x) }", + "func F[T, U, V any]() { F[U, V, T](); F[V, T, U]() }", + "type Ring[A, B, C any] struct { L *Ring[B, C, A]; R *Ring[C, A, B] }", + "func F[T any]() { type U[T any] [unsafe.Sizeof(F[*T])]byte }", + "func F[T any]() { type U[T any] [unsafe.Sizeof(F[*T])]byte; var _ U[int] }", + "type U[T any] [unsafe.Sizeof(F[*T])]byte; func F[T any]() { var _ U[U[int]] }", + "func F[T any]() { type A = int; F[A]() }", +} + +// TODO(mdempsky): Validate specific error messages and positioning. + +var bads = []string{ + "func F[T any](x T) { F(&x) }", + "func F[T any]() { F[*T]() }", + "func F[T any]() { F[[]T]() }", + "func F[T any]() { F[[1]T]() }", + "func F[T any]() { F[chan T]() }", + "func F[T any]() { F[map[*T]int]() }", + "func F[T any]() { F[map[error]T]() }", + "func F[T any]() { F[func(T)]() }", + "func F[T any]() { F[func() T]() }", + "func F[T any]() { F[struct{ t T }]() }", + "func F[T any]() { F[interface{ t() T }]() }", + "type U[_ any] int; func F[T any]() { F[U[T]]() }", + "func F[T any]() { type U int; F[U]() }", + "func F[T any]() { type U int; F[*U]() }", + "type U[T any] int; func (U[T]) m() { var _ U[*T] }", + "type U[T any] int; func (*U[T]) m() { var _ U[*T] }", + "type U[T any] [unsafe.Sizeof(F[*T])]byte; func F[T any]() { var _ U[T] }", + "func F[A, B, C, D, E any]() { F[B, C, D, E, *A]() }", + "type U[_ any] int; const X = unsafe.Sizeof(func() { type A[T any] U[A[*T]] })", + "func F[T any]() { type A = *T; F[A]() }", + "type A[T any] struct { _ A[*T] }", +} diff --git a/src/go/types/signature.go b/src/go/types/signature.go index c83bf09032..ad69c95d12 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -148,6 +148,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast list := make([]Type, sig.RecvTypeParams().Len()) for i, t := range sig.RecvTypeParams().list() { list[i] = t + check.mono.recordCanon(t, recvTParams[i]) } smap := makeSubstMap(recvTParams, list) for i, tpar := range sig.RecvTypeParams().list() { diff --git a/src/go/types/testdata/fixedbugs/issue48974.go2 b/src/go/types/testdata/fixedbugs/issue48974.go2 index ca4b6d9321..d8ff7c8cf4 100644 --- a/src/go/types/testdata/fixedbugs/issue48974.go2 +++ b/src/go/types/testdata/fixedbugs/issue48974.go2 @@ -8,7 +8,7 @@ type Fooer interface { Foo() } -type Fooable[F Fooer] struct { +type Fooable[F /* ERROR instantiation cycle */ Fooer] struct { ptr F } diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 092e355b38..3636c8556a 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -457,6 +457,8 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named pos = posList[i] } check.softErrorf(atPos(pos), _Todo, err.Error()) + } else { + check.mono.recordInstance(check.pkg, x.Pos(), inst.tparams.list(), inst.targs.list(), posList) } } -- GitLab From 629ffebd451613b32e6b9578ff4c807791197b38 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Mon, 1 Nov 2021 10:28:52 -0700 Subject: [PATCH 1892/2500] cmd/go: disallow profile flags when using -fuzz Disallow the usage of coverprofile, blockprofile, cpuprofile, memprofile, mutexprofile, and trace when fuzzing, since these currently do not work as the user would expect. Fixes #48178 Change-Id: Ibe6dfaef9b28a91c60c26fcad38c33a2a959d869 Reviewed-on: https://go-review.googlesource.com/c/go/+/360395 Trust: Roland Shoemaker Trust: Katie Hockman Run-TryBot: Bryan C. Mills Reviewed-by: Bryan C. Mills Reviewed-by: Katie Hockman TryBot-Result: Go Bot --- src/cmd/go/internal/test/test.go | 6 +++ .../script/test_fuzz_profile_flags.txt | 38 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 src/cmd/go/testdata/script/test_fuzz_profile_flags.txt diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index cfb0a1465f..7dca6b531c 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -666,6 +666,12 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { if len(pkgs) != 1 { base.Fatalf("cannot use -fuzz flag with multiple packages") } + if testCoverProfile != "" { + base.Fatalf("cannot use -coverprofile flag with -fuzz flag") + } + if profileFlag := testProfile(); profileFlag != "" { + base.Fatalf("cannot use %s flag with -fuzz flag", profileFlag) + } // Reject the '-fuzz' flag if the package is outside the main module. // Otherwise, if fuzzing identifies a failure it could corrupt checksums in diff --git a/src/cmd/go/testdata/script/test_fuzz_profile_flags.txt b/src/cmd/go/testdata/script/test_fuzz_profile_flags.txt new file mode 100644 index 0000000000..5434c723ad --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_profile_flags.txt @@ -0,0 +1,38 @@ +[!fuzz] skip + +! go test -fuzz=FuzzTrivial -coverprofile=prof +! stdout . +stderr '^cannot use -coverprofile flag with -fuzz flag$' + +! go test -fuzz=FuzzTrivial -blockprofile=prof +! stdout . +stderr '^cannot use -blockprofile flag with -fuzz flag$' + +! go test -fuzz=FuzzTrivial -cpuprofile=prof +! stdout . +stderr '^cannot use -cpuprofile flag with -fuzz flag$' + +! go test -fuzz=FuzzTrivial -memprofile=prof +! stdout . +stderr '^cannot use -memprofile flag with -fuzz flag$' + +! go test -fuzz=FuzzTrivial -mutexprofile=prof +! stdout . +stderr '^cannot use -mutexprofile flag with -fuzz flag$' + +! go test -fuzz=FuzzTrivial -trace=prof +! stdout . +stderr '^cannot use -trace flag with -fuzz flag$' + +-- go.mod -- +module example + +go 1.18 +-- fuzz_test.go -- +package example + +import "testing" + +func FuzzTrivial(f *testing.F) { + f.Fuzz(func(t *testing.T, _ []byte) {}) +} -- GitLab From f7a95d2c17c2b2506034d519b68a267c944f6450 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Wed, 6 Oct 2021 12:40:35 -0700 Subject: [PATCH 1893/2500] debug/gosym: bulk allocate Syms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit name old time/op new time/op delta 115/NewLineTable-8 80.7ns ± 1% 81.7ns ± 3% ~ (p=0.408 n=10+8) 115/NewTable-8 76.3µs ± 2% 63.3µs ± 3% -17.03% (p=0.000 n=9+9) 115/LineToPC-8 56.8µs ± 2% 56.8µs ± 3% ~ (p=0.905 n=10+9) 115/PCToLine-8 252ns ± 1% 256ns ± 5% ~ (p=0.183 n=10+10) name old alloc/op new alloc/op delta 115/NewLineTable-8 384B ± 0% 384B ± 0% ~ (all equal) 115/NewTable-8 164kB ± 0% 172kB ± 0% +4.97% (p=0.000 n=10+10) 115/LineToPC-8 0.00B 0.00B ~ (all equal) 115/PCToLine-8 0.00B 0.00B ~ (all equal) name old allocs/op new allocs/op delta 115/NewLineTable-8 3.00 ± 0% 3.00 ± 0% ~ (all equal) 115/NewTable-8 1.04k ± 0% 0.01k ± 0% -98.75% (p=0.000 n=10+10) 115/LineToPC-8 0.00 0.00 ~ (all equal) 115/PCToLine-8 0.00 0.00 ~ (all equal) Change-Id: Ibfe6c0cb86737dee8209cb1f58f5b796aa7b30aa Reviewed-on: https://go-review.googlesource.com/c/go/+/353134 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/debug/gosym/pclntab.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/debug/gosym/pclntab.go b/src/debug/gosym/pclntab.go index 134cb3d194..a687c406b2 100644 --- a/src/debug/gosym/pclntab.go +++ b/src/debug/gosym/pclntab.go @@ -297,6 +297,7 @@ func (t *LineTable) go12Funcs() []Func { ft := t.funcTab() funcs := make([]Func, ft.Count()) + syms := make([]Sym, len(funcs)) for i := range funcs { f := &funcs[i] f.Entry = ft.pc(i) @@ -304,13 +305,14 @@ func (t *LineTable) go12Funcs() []Func { info := t.funcData(uint32(i)) f.LineTable = t f.FrameSize = int(info.deferreturn()) - f.Sym = &Sym{ + syms[i] = Sym{ Value: f.Entry, Type: 'T', Name: t.funcName(info.nameoff()), GoType: 0, Func: f, } + f.Sym = &syms[i] } return funcs } -- GitLab From 79c5240799e02feeacfdde3472f22b4b0401f3c7 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Sat, 30 Oct 2021 14:39:29 -0700 Subject: [PATCH 1894/2500] cmd/compile: mark type descriptors as always dupok The types of the two interfaces should be equal, but they aren't. We end up with multiple descriptors for a type when we need type descriptors to be unique. Fixes #49241 Change-Id: I8a6c70da541c6088a92a01392bc83b61cc130eba Reviewed-on: https://go-review.googlesource.com/c/go/+/360134 Trust: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- .../compile/internal/reflectdata/reflect.go | 9 +++----- test/typeparam/issue49241.dir/a.go | 13 ++++++++++++ test/typeparam/issue49241.dir/b.go | 17 +++++++++++++++ test/typeparam/issue49241.dir/c.go | 17 +++++++++++++++ test/typeparam/issue49241.dir/main.go | 21 +++++++++++++++++++ test/typeparam/issue49241.go | 7 +++++++ 6 files changed, 78 insertions(+), 6 deletions(-) create mode 100644 test/typeparam/issue49241.dir/a.go create mode 100644 test/typeparam/issue49241.dir/b.go create mode 100644 test/typeparam/issue49241.dir/c.go create mode 100644 test/typeparam/issue49241.dir/main.go create mode 100644 test/typeparam/issue49241.go diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index ce41b8c934..d396c249e4 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -959,11 +959,6 @@ func writeType(t *types.Type) *obj.LSym { base.Fatalf("unresolved defined type: %v", tbase) } - dupok := 0 - if tbase.Sym() == nil || tbase.HasShape() { // TODO(mdempsky): Probably need DUPOK for instantiated types too. - dupok = obj.DUPOK - } - if !NeedEmit(tbase) { if i := typecheck.BaseTypeIndex(t); i >= 0 { lsym.Pkg = tbase.Sym().Pkg.Prefix @@ -1196,7 +1191,9 @@ func writeType(t *types.Type) *obj.LSym { } ot = dextratypeData(lsym, ot, t) - objw.Global(lsym, int32(ot), int16(dupok|obj.RODATA)) + objw.Global(lsym, int32(ot), int16(obj.DUPOK|obj.RODATA)) + // Note: DUPOK is required to ensure that we don't end up with more + // than one type descriptor for a given type. // The linker will leave a table of all the typelinks for // types in the binary, so the runtime can find them. diff --git a/test/typeparam/issue49241.dir/a.go b/test/typeparam/issue49241.dir/a.go new file mode 100644 index 0000000000..34c99657d4 --- /dev/null +++ b/test/typeparam/issue49241.dir/a.go @@ -0,0 +1,13 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type T[P any] struct { + x P +} + +type U struct { + a,b int +} diff --git a/test/typeparam/issue49241.dir/b.go b/test/typeparam/issue49241.dir/b.go new file mode 100644 index 0000000000..45c1afbaf1 --- /dev/null +++ b/test/typeparam/issue49241.dir/b.go @@ -0,0 +1,17 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package b + +import "a" + +//go:noinline +func F() interface {} { + return a.T[int]{} +} + +//go:noinline +func G() interface{} { + return struct{X,Y a.U}{} +} diff --git a/test/typeparam/issue49241.dir/c.go b/test/typeparam/issue49241.dir/c.go new file mode 100644 index 0000000000..ea3bab2954 --- /dev/null +++ b/test/typeparam/issue49241.dir/c.go @@ -0,0 +1,17 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package c + +import "a" + +//go:noinline +func F() interface {} { + return a.T[int]{} +} + +//go:noinline +func G() interface{} { + return struct{X,Y a.U}{} +} diff --git a/test/typeparam/issue49241.dir/main.go b/test/typeparam/issue49241.dir/main.go new file mode 100644 index 0000000000..7c8a8b1acd --- /dev/null +++ b/test/typeparam/issue49241.dir/main.go @@ -0,0 +1,21 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "b" + "c" +) + +func main() { + if b.G() != c.G() { + println(b.G(), c.G()) + panic("bad") + } + if b.F() != c.F() { + println(b.F(), c.F()) + panic("bad") + } +} diff --git a/test/typeparam/issue49241.go b/test/typeparam/issue49241.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/issue49241.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From 0b37bd9b3f7556d31061c6007afca59ffe2642d3 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 1 Nov 2021 14:07:30 -0700 Subject: [PATCH 1895/2500] net: add BenchmarkWriteToReadFromUDPAddrPort The main item of interest is the allocs. BenchmarkWriteToReadFromUDPAddrPort-8 237735 5152 ns/op 68 B/op 3 allocs/op Change-Id: I5cb3f2e1ebbb02acc51039c2266e99b90d388a99 Reviewed-on: https://go-review.googlesource.com/c/go/+/360598 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/net/udpsock_test.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/net/udpsock_test.go b/src/net/udpsock_test.go index 74e449c888..371d9af511 100644 --- a/src/net/udpsock_test.go +++ b/src/net/udpsock_test.go @@ -479,6 +479,7 @@ func BenchmarkReadWriteMsgUDPAddrPort(b *testing.B) { if err != nil { b.Fatal(err) } + defer conn.Close() addr := conn.LocalAddr().(*UDPAddr).AddrPort() buf := make([]byte, 8) b.ResetTimer() @@ -500,6 +501,7 @@ func BenchmarkWriteToReadFromUDP(b *testing.B) { if err != nil { b.Fatal(err) } + defer conn.Close() addr := conn.LocalAddr() buf := make([]byte, 8) b.ResetTimer() @@ -515,3 +517,25 @@ func BenchmarkWriteToReadFromUDP(b *testing.B) { } } } + +func BenchmarkWriteToReadFromUDPAddrPort(b *testing.B) { + conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) + if err != nil { + b.Fatal(err) + } + defer conn.Close() + addr := conn.LocalAddr().(*UDPAddr).AddrPort() + buf := make([]byte, 8) + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _, err := conn.WriteToUDPAddrPort(buf, addr) + if err != nil { + b.Fatal(err) + } + _, _, err = conn.ReadFromUDP(buf) // TODO: create and use ReadFromUDPAddrPort + if err != nil { + b.Fatal(err) + } + } +} -- GitLab From 433ba582f7c72636066ec92679a325b7ee15297c Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 1 Nov 2021 13:23:39 -0700 Subject: [PATCH 1896/2500] net: optimize WriteToUDPAddrPort MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See the recent change optimizing WriteMsgUDPAddrPort for an explanation of why this change includes copy/paste/modify instead of implementing WriteToUDP using WriteToUDPAddrPort. name old time/op new time/op delta WriteToReadFromUDPAddrPort-8 5.02µs ± 3% 4.71µs ± 2% -6.31% (p=0.000 n=15+14) name old alloc/op new alloc/op delta WriteToReadFromUDPAddrPort-8 68.0B ± 0% 4.0B ± 0% -94.12% (p=0.000 n=15+15) name old allocs/op new allocs/op delta WriteToReadFromUDPAddrPort-8 3.00 ± 0% 1.00 ± 0% -66.67% (p=0.000 n=15+15) Change-Id: I301715e774de07eb6ccb4e329ccf2e554609abc1 Reviewed-on: https://go-review.googlesource.com/c/go/+/360599 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/net/udpsock.go | 13 ++++++++----- src/net/udpsock_plan9.go | 4 ++++ src/net/udpsock_posix.go | 26 ++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/net/udpsock.go b/src/net/udpsock.go index 0d563fd4f5..a829789a1b 100644 --- a/src/net/udpsock.go +++ b/src/net/udpsock.go @@ -207,11 +207,14 @@ func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) { // WriteToUDPAddrPort acts like WriteTo but takes a netip.AddrPort. func (c *UDPConn) WriteToUDPAddrPort(b []byte, addr netip.AddrPort) (int, error) { - // TODO(bradfitz): make this efficient, making the internal net package - // type throughout be netip.Addr and only converting to the net.IP slice - // version at the edge. But for now (2021-10-20), this is a wrapper around - // the old way. - return c.WriteToUDP(b, UDPAddrFromAddrPort(addr)) + if !c.ok() { + return 0, syscall.EINVAL + } + n, err := c.writeToAddrPort(b, addr) + if err != nil { + err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addrPortUDPAddr{addr}, Err: err} + } + return n, err } // WriteTo implements the PacketConn WriteTo method. diff --git a/src/net/udpsock_plan9.go b/src/net/udpsock_plan9.go index ac5afa2281..dfb81a8d0c 100644 --- a/src/net/udpsock_plan9.go +++ b/src/net/udpsock_plan9.go @@ -53,6 +53,10 @@ func (c *UDPConn) writeTo(b []byte, addr *UDPAddr) (int, error) { return len(b), nil } +func (c *UDPConn) writeToAddrPort(b []byte, addr netip.AddrPort) (int, error) { + return c.writeTo(b, UDPAddrFromAddrPort(addr)) // TODO: optimize instead of allocating +} + func (c *UDPConn) writeMsg(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) { return 0, 0, syscall.EPLAN9 } diff --git a/src/net/udpsock_posix.go b/src/net/udpsock_posix.go index 646687d148..718d11e60f 100644 --- a/src/net/udpsock_posix.go +++ b/src/net/udpsock_posix.go @@ -109,6 +109,32 @@ func (c *UDPConn) writeTo(b []byte, addr *UDPAddr) (int, error) { } } +func (c *UDPConn) writeToAddrPort(b []byte, addr netip.AddrPort) (int, error) { + if c.fd.isConnected { + return 0, ErrWriteToConnected + } + if !addr.IsValid() { + return 0, errMissingAddress + } + + switch c.fd.family { + case syscall.AF_INET: + sa, err := addrPortToSockaddrInet4(addr) + if err != nil { + return 0, err + } + return c.fd.writeToInet4(b, sa) + case syscall.AF_INET6: + sa, err := addrPortToSockaddrInet6(addr) + if err != nil { + return 0, err + } + return c.fd.writeToInet6(b, sa) + default: + return 0, &AddrError{Err: "invalid address family", Addr: addr.Addr().String()} + } +} + func (c *UDPConn) writeMsg(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) { if c.fd.isConnected && addr != nil { return 0, 0, ErrWriteToConnected -- GitLab From c702f91b38f98c98a12b9933dce42dbd500e21fd Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 1 Nov 2021 13:45:21 -0700 Subject: [PATCH 1897/2500] net: add ReadFromUDPAddrPort MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is now possible to do completely allocation-free UDP. This is implemented completely separately from ReadFromUDP because ReadFromUDP exists in a delicate balance to allow mid-stack inlining. After performance-sensitive callers have migrated to ReadFromUDPAddrPort, we may be able to simplify ReadFromUDP to call ReadFromUDPAddrPort. name old time/op new time/op delta WriteToReadFromUDPAddrPort-8 4.71µs ± 2% 4.81µs ± 5% +2.18% (p=0.000 n=14+14) name old alloc/op new alloc/op delta WriteToReadFromUDPAddrPort-8 4.00B ± 0% 0.00B -100.00% (p=0.000 n=15+15) name old allocs/op new allocs/op delta WriteToReadFromUDPAddrPort-8 1.00 ± 0% 0.00 -100.00% (p=0.000 n=15+15) Change-Id: I37f5ad9416a1d4333ed48d83474b2cf933b2a1be Reviewed-on: https://go-review.googlesource.com/c/go/+/360600 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/net/udpsock.go | 12 ++++++++++++ src/net/udpsock_plan9.go | 19 +++++++++++++++++++ src/net/udpsock_posix.go | 25 +++++++++++++++++++++++++ src/net/udpsock_test.go | 2 +- 4 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/net/udpsock.go b/src/net/udpsock.go index a829789a1b..622b1f83fb 100644 --- a/src/net/udpsock.go +++ b/src/net/udpsock.go @@ -167,6 +167,18 @@ func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) { return n, addr, err } +// ReadFromUDPAddrPort acts like ReadFrom but returns a netip.AddrPort. +func (c *UDPConn) ReadFromUDPAddrPort(b []byte) (n int, addr netip.AddrPort, err error) { + if !c.ok() { + return 0, netip.AddrPort{}, syscall.EINVAL + } + n, addr, err = c.readFromAddrPort(b) + if err != nil { + err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err} + } + return n, addr, err +} + // ReadMsgUDP reads a message from c, copying the payload into b and // the associated out-of-band data into oob. It returns the number of // bytes copied into b, the number of bytes copied into oob, the flags diff --git a/src/net/udpsock_plan9.go b/src/net/udpsock_plan9.go index dfb81a8d0c..732a3b07ee 100644 --- a/src/net/udpsock_plan9.go +++ b/src/net/udpsock_plan9.go @@ -29,6 +29,25 @@ func (c *UDPConn) readFrom(b []byte, addr *UDPAddr) (int, *UDPAddr, error) { return n, addr, nil } +func (c *UDPConn) readFromAddrPort(b []byte) (int, netip.AddrPort, error) { + // TODO: optimize. The equivalent code on posix is alloc-free. + buf := make([]byte, udpHeaderSize+len(b)) + m, err := c.fd.Read(buf) + if err != nil { + return 0, netip.AddrPort{}, err + } + if m < udpHeaderSize { + return 0, netip.AddrPort{}, errors.New("short read reading UDP header") + } + buf = buf[:m] + + h, buf := unmarshalUDPHeader(buf) + n := copy(b, buf) + ip, _ := netip.AddrFromSlice(h.raddr) + addr := netip.AddrPortFrom(ip, h.rport) + return n, addr, nil +} + func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr netip.AddrPort, err error) { return 0, 0, 0, netip.AddrPort{}, syscall.EPLAN9 } diff --git a/src/net/udpsock_posix.go b/src/net/udpsock_posix.go index 718d11e60f..c93994f836 100644 --- a/src/net/udpsock_posix.go +++ b/src/net/udpsock_posix.go @@ -69,6 +69,31 @@ func (c *UDPConn) readFrom(b []byte, addr *UDPAddr) (int, *UDPAddr, error) { return n, addr, err } +func (c *UDPConn) readFromAddrPort(b []byte) (n int, addr netip.AddrPort, err error) { + var ip netip.Addr + var port int + switch c.fd.family { + case syscall.AF_INET: + var from syscall.SockaddrInet4 + n, err = c.fd.readFromInet4(b, &from) + if err == nil { + ip = netip.AddrFrom4(from.Addr) + port = from.Port + } + case syscall.AF_INET6: + var from syscall.SockaddrInet6 + n, err = c.fd.readFromInet6(b, &from) + if err == nil { + ip = netip.AddrFrom16(from.Addr).WithZone(zoneCache.name(int(from.ZoneId))) + port = from.Port + } + } + if err == nil { + addr = netip.AddrPortFrom(ip, uint16(port)) + } + return n, addr, err +} + func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr netip.AddrPort, err error) { var sa syscall.Sockaddr n, oobn, flags, sa, err = c.fd.readMsg(b, oob, 0) diff --git a/src/net/udpsock_test.go b/src/net/udpsock_test.go index 371d9af511..7eef6f64af 100644 --- a/src/net/udpsock_test.go +++ b/src/net/udpsock_test.go @@ -533,7 +533,7 @@ func BenchmarkWriteToReadFromUDPAddrPort(b *testing.B) { if err != nil { b.Fatal(err) } - _, _, err = conn.ReadFromUDP(buf) // TODO: create and use ReadFromUDPAddrPort + _, _, err = conn.ReadFromUDPAddrPort(buf) if err != nil { b.Fatal(err) } -- GitLab From 80a7968842895a5c05efa6464ce49b62413436c1 Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Tue, 2 Nov 2021 13:44:05 -0400 Subject: [PATCH 1898/2500] cmd/compile/internal/abi: fix some typos in comments Fix a few types in the header comment for 'ComputePadding'. Change-Id: If38911e6dcbec571845ae44eef30fd6c33f589cb Reviewed-on: https://go-review.googlesource.com/c/go/+/360814 Trust: Than McIntosh Run-TryBot: Than McIntosh TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Reviewed-by: Cherry Mui --- src/cmd/compile/internal/abi/abiutils.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/abi/abiutils.go b/src/cmd/compile/internal/abi/abiutils.go index 4da4e9ca3a..74c8707b29 100644 --- a/src/cmd/compile/internal/abi/abiutils.go +++ b/src/cmd/compile/internal/abi/abiutils.go @@ -780,11 +780,11 @@ func (state *assignState) assignParamOrReturn(pt *types.Type, n types.Object, is } // ComputePadding returns a list of "post element" padding values in -// the case where we have a structure being passed in registers. Give -// a param assignment corresponding to a struct, it returns a list of -// contaning padding values for each field, e.g. the Kth element in +// the case where we have a structure being passed in registers. Given +// a param assignment corresponding to a struct, it returns a list +// containing padding values for each field, e.g. the Kth element in // the list is the amount of padding between field K and the following -// field. For things that are not struct (or structs without padding) +// field. For things that are not structs (or structs without padding) // it returns a list of zeros. Example: // // type small struct { @@ -796,8 +796,8 @@ func (state *assignState) assignParamOrReturn(pt *types.Type, n types.Object, is // // For this struct we would return a list [0, 1, 0, 0], meaning that // we have one byte of padding after the second field, and no bytes of -// padding after any of the other fields. Input parameter "storage" -// is with enough capacity to accommodate padding elements for +// padding after any of the other fields. Input parameter "storage" is +// a slice with enough capacity to accommodate padding elements for // the architected register set in question. func (pa *ABIParamAssignment) ComputePadding(storage []uint64) []uint64 { nr := len(pa.Registers) -- GitLab From 1011e26b9cec8b5e7b0b827805b2fe079904521a Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Tue, 2 Nov 2021 11:52:36 -0700 Subject: [PATCH 1899/2500] net/http: deflake TestServerKeepAlivesEnabled_h{1,2} This test assumes that two successive TCP connections will use different source ports. This does not appear to be a universally safe assumption. Rewrite the test to use httptrace to detect connection reuse instead. Fixes #46707 Change-Id: Iebfbdfdeb77a1e6663a0c654dc847cc270c5d54d Reviewed-on: https://go-review.googlesource.com/c/go/+/360854 Trust: Damien Neil Run-TryBot: Damien Neil TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/net/http/serve_test.go | 42 ++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index 6394da3bb7..a98d6c313f 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -23,6 +23,7 @@ import ( "net" . "net/http" "net/http/httptest" + "net/http/httptrace" "net/http/httputil" "net/http/internal" "net/http/internal/testcert" @@ -5689,22 +5690,37 @@ func testServerKeepAlivesEnabled(t *testing.T, h2 bool) { } // Not parallel: messes with global variable. (http2goAwayTimeout) defer afterTest(t) - cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { - fmt.Fprintf(w, "%v", r.RemoteAddr) - })) + cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {})) defer cst.close() srv := cst.ts.Config srv.SetKeepAlivesEnabled(false) - a := cst.getURL(cst.ts.URL) - if !waitCondition(2*time.Second, 10*time.Millisecond, srv.ExportAllConnsIdle) { - t.Fatalf("test server has active conns") - } - b := cst.getURL(cst.ts.URL) - if a == b { - t.Errorf("got same connection between first and second requests") - } - if !waitCondition(2*time.Second, 10*time.Millisecond, srv.ExportAllConnsIdle) { - t.Fatalf("test server has active conns") + for try := 0; try < 2; try++ { + if !waitCondition(2*time.Second, 10*time.Millisecond, srv.ExportAllConnsIdle) { + t.Fatalf("request %v: test server has active conns", try) + } + conns := 0 + var info httptrace.GotConnInfo + ctx := httptrace.WithClientTrace(context.Background(), &httptrace.ClientTrace{ + GotConn: func(v httptrace.GotConnInfo) { + conns++ + info = v + }, + }) + req, err := NewRequestWithContext(ctx, "GET", cst.ts.URL, nil) + if err != nil { + t.Fatal(err) + } + res, err := cst.c.Do(req) + if err != nil { + t.Fatal(err) + } + res.Body.Close() + if conns != 1 { + t.Fatalf("request %v: got %v conns, want 1", try, conns) + } + if info.Reused || info.WasIdle { + t.Fatalf("request %v: Reused=%v (want false), WasIdle=%v (want false)", try, info.Reused, info.WasIdle) + } } } -- GitLab From c45c32b1cd6ba635fda3add12f48766fd6aef5d8 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 2 Nov 2021 11:23:34 -0700 Subject: [PATCH 1900/2500] go/types: avoid closure allocations in mono check This CL replaces monoEdge's "report" field with fields "pos" and "typ", and pushes the logic for formatting them into the report loop. This avoids needing to allocate a function closure for each edge. Also tweak a test case so the two type parameters involved in the cycle aren't both "T" so they're easier to understand. Change-Id: I9d392ad1d99a4c5e89da4613084e885149ebad07 Reviewed-on: https://go-review.googlesource.com/c/go/+/360815 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/mono.go | 42 +++++++++++++++++++++------------------ src/go/types/mono_test.go | 2 +- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/go/types/mono.go b/src/go/types/mono.go index fb1127e959..d4d884393b 100644 --- a/src/go/types/mono.go +++ b/src/go/types/mono.go @@ -71,14 +71,11 @@ type monoVertex struct { } type monoEdge struct { - dst int - src int - weight int + dst, src int + weight int - // report emits an error describing why this edge exists. - // - // TODO(mdempsky): Avoid requiring a function closure for each edge. - report func(check *Checker) + pos token.Pos + typ Type } func (check *Checker) monomorph() { @@ -139,12 +136,22 @@ func (check *Checker) reportInstanceLoop(v int) { // TODO(mdempsky): Pivot stack so we report the cycle from the top? - obj := check.mono.vertices[v].obj - check.errorf(obj, _InvalidInstanceCycle, "instantiation cycle:") + obj0 := check.mono.vertices[v].obj + check.errorf(obj0, _InvalidInstanceCycle, "instantiation cycle:") + qf := RelativeTo(check.pkg) for _, v := range stack { edge := check.mono.edges[check.mono.vertices[v].pre] - edge.report(check) + obj := check.mono.vertices[edge.dst].obj + + switch obj.Type().(type) { + default: + panic("unexpected type") + case *Named: + check.errorf(atPos(edge.pos), _InvalidInstanceCycle, "\t%s implicitly parameterized by %s", obj.Name(), TypeString(edge.typ, qf)) // secondary error, \t indented + case *TypeParam: + check.errorf(atPos(edge.pos), _InvalidInstanceCycle, "\t%s instantiated as %s", obj.Name(), TypeString(edge.typ, qf)) // secondary error, \t indented + } } } @@ -190,10 +197,7 @@ func (w *monoGraph) assign(pkg *Package, pos token.Pos, tpar *TypeParam, targ Ty weight = 0 } - w.addEdge(w.typeParamVertex(tpar), src, weight, func(check *Checker) { - qf := RelativeTo(check.pkg) - check.errorf(atPos(pos), _InvalidInstanceCycle, "\t%s instantiated as %s", tpar.Obj().Name(), TypeString(targ, qf)) // secondary error, \t indented - }) + w.addEdge(w.typeParamVertex(tpar), src, weight, pos, targ) } // Recursively walk the type argument to find any defined types or @@ -283,9 +287,7 @@ func (w *monoGraph) localNamedVertex(pkg *Package, named *Named) int { w.vertices = append(w.vertices, monoVertex{obj: obj}) } - w.addEdge(idx, w.typeParamVertex(tpar), 1, func(check *Checker) { - check.errorf(obj, _InvalidInstanceCycle, "\t%s implicitly parameterized by %s", obj.Name(), elem.Name()) - }) + w.addEdge(idx, w.typeParamVertex(tpar), 1, obj.Pos(), tpar) } } } @@ -320,12 +322,14 @@ func (w *monoGraph) typeParamVertex(tpar *TypeParam) int { return idx } -func (w *monoGraph) addEdge(dst, src, weight int, report func(check *Checker)) { +func (w *monoGraph) addEdge(dst, src, weight int, pos token.Pos, typ Type) { // TODO(mdempsky): Deduplicate redundant edges? w.edges = append(w.edges, monoEdge{ dst: dst, src: src, weight: weight, - report: report, + + pos: pos, + typ: typ, }) } diff --git a/src/go/types/mono_test.go b/src/go/types/mono_test.go index c4c5282427..5df3d493f8 100644 --- a/src/go/types/mono_test.go +++ b/src/go/types/mono_test.go @@ -84,7 +84,7 @@ var bads = []string{ "func F[T any]() { type U int; F[*U]() }", "type U[T any] int; func (U[T]) m() { var _ U[*T] }", "type U[T any] int; func (*U[T]) m() { var _ U[*T] }", - "type U[T any] [unsafe.Sizeof(F[*T])]byte; func F[T any]() { var _ U[T] }", + "type U[T1 any] [unsafe.Sizeof(F[*T1])]byte; func F[T2 any]() { var _ U[T2] }", "func F[A, B, C, D, E any]() { F[B, C, D, E, *A]() }", "type U[_ any] int; const X = unsafe.Sizeof(func() { type A[T any] U[A[*T]] })", "func F[T any]() { type A = *T; F[A]() }", -- GitLab From 7c9510ef3ec4b1008b599c9c8a0ec9adaba4b663 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 1 Nov 2021 22:35:29 +0000 Subject: [PATCH 1901/2500] syscall: fix finalizer fd close bugs in TestFcntlFlock and TestPassFD Currently, the syscall test suite takes very little time to run. It stands to reason that pretty much every time, zero GCs execute. With CL 309869, this changes because the minimum heap size is lowered, triggering two bugs in the test suite. One bug is in TestFcntlFlock, where a raw FD is wrapped in an os.File whose last reference is passed into a Cmd. That FD is then closed by a defer syscall.Close, instead of the os.File's Close, so the finalizer may fire *after* that FD has already been reused by another test. The second bug is in the child helper process of TestPassFD, where there's a small window in which a temp file's FD is encoded for an out-of-band unix domain socket message to the parent, but not yet sent. The point of encoding is also the last reference that FD's os.File, so a finalizer may run at any time. While it's safe for the finalizer to run after the FD is sent, if it runs before, the send will fail, since unix domain sockets require that any sent FDs are valid. Change-Id: I2d1bd7e6db6efcc6763273217fd85cb5b9764274 Reviewed-on: https://go-review.googlesource.com/c/go/+/360575 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/syscall/syscall_unix_test.go | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/syscall/syscall_unix_test.go b/src/syscall/syscall_unix_test.go index 7cc78c2147..e4af0ba4a5 100644 --- a/src/syscall/syscall_unix_test.go +++ b/src/syscall/syscall_unix_test.go @@ -84,16 +84,24 @@ func TestFcntlFlock(t *testing.T) { if err != nil { t.Fatalf("Open failed: %v", err) } - defer syscall.Close(fd) - if err := syscall.Ftruncate(fd, 1<<20); err != nil { + // f takes ownership of fd, and will close it. + // + // N.B. This defer is also necessary to keep f alive + // while we use its fd, preventing its finalizer from + // executing. + f := os.NewFile(uintptr(fd), name) + defer f.Close() + + if err := syscall.Ftruncate(int(f.Fd()), 1<<20); err != nil { t.Fatalf("Ftruncate(1<<20) failed: %v", err) } - if err := syscall.FcntlFlock(uintptr(fd), syscall.F_SETLK, &flock); err != nil { + if err := syscall.FcntlFlock(f.Fd(), syscall.F_SETLK, &flock); err != nil { t.Fatalf("FcntlFlock(F_SETLK) failed: %v", err) } + cmd := exec.Command(os.Args[0], "-test.run=^TestFcntlFlock$") cmd.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=1") - cmd.ExtraFiles = []*os.File{os.NewFile(uintptr(fd), name)} + cmd.ExtraFiles = []*os.File{f} out, err := cmd.CombinedOutput() if len(out) > 0 || err != nil { t.Fatalf("child process: %q, %v", out, err) @@ -251,6 +259,10 @@ func passFDChild() { fmt.Printf("TempFile: %v", err) return } + // N.B. This defer is also necessary to keep f alive + // while we use its fd, preventing its finalizer from + // executing. + defer f.Close() f.Write([]byte("Hello from child process!\n")) f.Seek(0, io.SeekStart) -- GitLab From b29182b54ac343bbc58a30357d9df908f1c3b727 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 1 Nov 2021 15:27:13 -0400 Subject: [PATCH 1902/2500] go/types: clean up asT converters (step 1 of 2) This is a port of CL 358597 to go/types. A comment was missing in the base of applyTypeFunc, which had been there since the initial check-in of types2; somehow it was not in go/types. Change-Id: If08efd92d782dd3099b26254ae6e311c6cea8c3b Reviewed-on: https://go-review.googlesource.com/c/go/+/360477 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/assignments.go | 2 +- src/go/types/builtins.go | 24 ++++---- src/go/types/call.go | 8 +-- src/go/types/conversions.go | 24 ++++---- src/go/types/expr.go | 8 ++- src/go/types/index.go | 6 +- src/go/types/infer.go | 4 +- src/go/types/lookup.go | 8 +-- src/go/types/predicates.go | 10 +--- src/go/types/sizeof_test.go | 1 - src/go/types/sizes.go | 2 +- src/go/types/subst.go | 2 +- src/go/types/testdata/check/issues.go2 | 7 +++ src/go/types/type.go | 83 +++++++------------------- src/go/types/typestring.go | 5 +- src/go/types/typexpr.go | 4 +- 16 files changed, 82 insertions(+), 116 deletions(-) diff --git a/src/go/types/assignments.go b/src/go/types/assignments.go index 2810133a1f..cfdb0eb14a 100644 --- a/src/go/types/assignments.go +++ b/src/go/types/assignments.go @@ -71,7 +71,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { } // A generic (non-instantiated) function value cannot be assigned to a variable. - if sig := asSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { + if sig := toSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { check.errorf(x, _Todo, "cannot use generic function %s without instantiation in %s", x, context) } diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 87c26775a6..e6fb6ef4ff 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -83,7 +83,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // of S and the respective parameter passing rules apply." S := x.typ var T Type - if s := asSlice(S); s != nil { + if s, _ := singleUnder(S).(*Slice); s != nil { T = s.elem } else { check.invalidArg(x, _InvalidAppend, "%s is not a slice", x) @@ -296,8 +296,10 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b } // the argument types must be of floating-point type - f := func(x Type) Type { - if t := asBasic(x); t != nil { + // (applyTypeFunc never calls f with a type parameter) + f := func(typ Type) Type { + assert(asTypeParam(typ) == nil) + if t := toBasic(typ); t != nil { switch t.kind { case Float32: return Typ[Complex64] @@ -418,8 +420,10 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b } // the argument must be of complex type - f := func(x Type) Type { - if t := asBasic(x); t != nil { + // (applyTypeFunc never calls f with a type parameter) + f := func(typ Type) Type { + assert(asTypeParam(typ) == nil) + if t := toBasic(typ); t != nil { switch t.kind { case Complex64: return Typ[Float32] @@ -709,7 +713,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b return } - typ := asPointer(x.typ) + typ := toPointer(x.typ) if typ == nil { check.invalidArg(x, _InvalidUnsafeSlice, "%s is not a pointer", x) return @@ -825,7 +829,7 @@ func hasVarSize(t Type) bool { } case *TypeParam: return true - case *Named, *Union, *top: + case *Named, *Union: unreachable() } return false @@ -856,8 +860,8 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { return nil } - // Construct a suitable new type parameter for the sum type. The - // type param is placed in the current package so export/import + // Construct a suitable new type parameter for the result type. + // The type parameter is placed in the current package so export/import // works as expected. tpar := NewTypeName(token.NoPos, check.pkg, "", nil) ptyp := check.newTypeParam(tpar, NewInterfaceType(nil, []Type{NewUnion(terms)})) // assigns type to tpar as a side-effect @@ -889,7 +893,7 @@ func makeSig(res Type, args ...Type) *Signature { // otherwise it returns typ. func arrayPtrDeref(typ Type) Type { if p, ok := typ.(*Pointer); ok { - if a := asArray(p.base); a != nil { + if a := toArray(p.base); a != nil { return a } } diff --git a/src/go/types/call.go b/src/go/types/call.go index 36086891b5..a4e834271f 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -141,10 +141,9 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { check.errorf(call.Args[0], _BadDotDotDotSyntax, "invalid use of ... in conversion to %s", T) break } - if t := asInterface(T); t != nil { + if t := toInterface(T); t != nil { if !t.IsMethodSet() { - // TODO(rfindley): remove the phrase "type list" from this error. - check.errorf(call, _Todo, "cannot use interface %s in conversion (contains type list or is comparable)", T) + check.errorf(call, _Todo, "cannot use interface %s in conversion (contains specific type constraints or is comparable)", T) break } } @@ -175,7 +174,8 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { // signature may be generic cgocall := x.mode == cgofunc - sig := asSignature(x.typ) + // a type parameter may be "called" if all types have the same signature + sig, _ := singleUnder(x.typ).(*Signature) if sig == nil { check.invalidOp(x, _InvalidCall, "cannot call non-function %s", x) x.mode = invalid diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go index 8c8b63e23a..c3fc04e406 100644 --- a/src/go/types/conversions.go +++ b/src/go/types/conversions.go @@ -21,7 +21,7 @@ func (check *Checker) conversion(x *operand, T Type) { switch { case constArg && isConstType(T): // constant conversion (T cannot be a type parameter) - switch t := asBasic(T); { + switch t := toBasic(T); { case representableConst(x.val, check, t, &x.val): ok = true case isInteger(x.typ) && isString(t): @@ -198,9 +198,9 @@ func convertibleToImpl(check *Checker, V, T Type, cause *string) bool { // "V is a slice, T is a pointer-to-array type, // and the slice and array types have identical element types." - if s := asSlice(V); s != nil { - if p := asPointer(T); p != nil { - if a := asArray(p.Elem()); a != nil { + if s := toSlice(V); s != nil { + if p := toPointer(T); p != nil { + if a := toArray(p.Elem()); a != nil { if Identical(s.Elem(), a.Elem()) { if check == nil || check.allowVersion(check.pkg, 1, 17) { return true @@ -216,27 +216,31 @@ func convertibleToImpl(check *Checker, V, T Type, cause *string) bool { return false } +// Helper predicates for convertibleToImpl. The types provided to convertibleToImpl +// may be type parameters but they won't have specific type terms. Thus it is ok to +// use the toT convenience converters in the predicates below. + func isUintptr(typ Type) bool { - t := asBasic(typ) + t := toBasic(typ) return t != nil && t.kind == Uintptr } func isUnsafePointer(typ Type) bool { - // TODO(gri): Is this asBasic(typ) instead of typ.(*Basic) correct? + // TODO(gri): Is this toBasic(typ) instead of typ.(*Basic) correct? // (The former calls under(), while the latter doesn't.) // The spec does not say so, but gc claims it is. See also // issue 6326. - t := asBasic(typ) + t := toBasic(typ) return t != nil && t.kind == UnsafePointer } func isPointer(typ Type) bool { - return asPointer(typ) != nil + return toPointer(typ) != nil } func isBytesOrRunes(typ Type) bool { - if s := asSlice(typ); s != nil { - t := asBasic(s.elem) + if s := toSlice(typ); s != nil { + t := toBasic(s.elem) return t != nil && (t.kind == Byte || t.kind == Rune) } return false diff --git a/src/go/types/expr.go b/src/go/types/expr.go index ef5958ba3f..266f896f6e 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -100,8 +100,10 @@ func (check *Checker) overflow(x *operand, op token.Token, opPos token.Pos) { // Typed constants must be representable in // their type after each constant operation. + // x.typ cannot be a type parameter (type + // parameters cannot be constant types). if isTyped(x.typ) { - check.representable(x, asBasic(x.typ)) + check.representable(x, toBasic(x.typ)) return } @@ -554,7 +556,7 @@ func (check *Checker) updateExprType(x ast.Expr, typ Type, final bool) { // If the new type is not final and still untyped, just // update the recorded type. if !final && isUntyped(typ) { - old.typ = asBasic(typ) + old.typ = toBasic(typ) check.untyped[x] = old return } @@ -1353,7 +1355,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { duplicate := false // if the key is of interface type, the type is also significant when checking for duplicates xkey := keyVal(x.val) - if asInterface(utyp.key) != nil { + if toInterface(utyp.key) != nil { for _, vtyp := range visited[xkey] { if Identical(vtyp, x.typ) { duplicate = true diff --git a/src/go/types/index.go b/src/go/types/index.go index 24c1812039..9f723bcf67 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -35,7 +35,7 @@ func (check *Checker) indexExpr(x *operand, e *typeparams.IndexExpr) (isFuncInst return false case value: - if sig := asSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { + if sig := toSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { // function instantiation return true } @@ -72,7 +72,7 @@ func (check *Checker) indexExpr(x *operand, e *typeparams.IndexExpr) (isFuncInst x.typ = typ.elem case *Pointer: - if typ := asArray(typ.base); typ != nil { + if typ := toArray(typ.base); typ != nil { valid = true length = typ.len x.mode = variable @@ -242,7 +242,7 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { x.typ = &Slice{elem: u.elem} case *Pointer: - if u := asArray(u.base); u != nil { + if u := toArray(u.base); u != nil { valid = true length = u.len x.typ = &Slice{elem: u.elem} diff --git a/src/go/types/infer.go b/src/go/types/infer.go index 9302bd7f57..cea0780721 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -270,7 +270,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { }() switch t := typ.(type) { - case nil, *top, *Basic: // TODO(gri) should nil be handled here? + case nil, *Basic: // TODO(gri) should nil be handled here? break case *Array: @@ -499,7 +499,7 @@ func (w *cycleFinder) typ(typ Type) { defer delete(w.seen, typ) switch t := typ.(type) { - case *Basic, *top: + case *Basic: // nothing to do case *Array: diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index afb1215af2..506cc69384 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -302,7 +302,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, return } - if ityp := asInterface(V); ityp != nil { + if ityp := toInterface(V); ityp != nil { // TODO(gri) the methods are sorted - could do this more efficiently for _, m := range T.typeSet().methods { _, f := ityp.typeSet().LookupMethod(m.pkg, m.name) @@ -400,7 +400,7 @@ func (check *Checker) assertableTo(V *Interface, T Type) (method, wrongType *Fun // no static check is required if T is an interface // spec: "If T is an interface type, x.(T) asserts that the // dynamic type of x implements the interface T." - if asInterface(T) != nil && !forceStrict { + if toInterface(T) != nil && !forceStrict { return } return check.missingMethod(T, V, false) @@ -418,8 +418,8 @@ func deref(typ Type) (Type, bool) { // derefStructPtr dereferences typ if it is a (named or unnamed) pointer to a // (named or unnamed) struct and returns its base. Otherwise it returns typ. func derefStructPtr(typ Type) Type { - if p := asPointer(typ); p != nil { - if asStruct(p.base) != nil { + if p := toPointer(typ); p != nil { + if toStruct(p.base) != nil { return p.base } } diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index b687c151c7..d4ce97a16b 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -58,7 +58,7 @@ func isNumericOrString(typ Type) bool { return is(typ, IsNumeric|IsString) } // are not fully set up. func isTyped(typ Type) bool { // isTyped is called with types that are not fully - // set up. Must not call asBasic()! + // set up. Must not call toBasic()! t, _ := typ.(*Basic) return t == nil || t.info&IsUntyped == 0 } @@ -72,13 +72,13 @@ func isOrdered(typ Type) bool { return is(typ, IsOrdered) } func isConstType(typ Type) bool { // Type parameters are never const types. - t, _ := under(typ).(*Basic) + t := toBasic(typ) return t != nil && t.info&IsConstType != 0 } // IsInterface reports whether typ is an interface type. func IsInterface(typ Type) bool { - return asInterface(typ) != nil + return toInterface(typ) != nil } // Comparable reports whether values of type T are comparable. @@ -341,10 +341,6 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { case *TypeParam: // nothing to do (x and y being equal is caught in the very beginning of this function) - case *top: - // Either both types are theTop in which case the initial x == y check - // will have caught them. Otherwise they are not identical. - case nil: // avoid a crash in case of nil type diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index 0e3c0064a0..5b7ee8bb78 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -33,7 +33,6 @@ func TestSizeof(t *testing.T) { {Named{}, 68, 128}, {TypeParam{}, 28, 48}, {term{}, 12, 24}, - {top{}, 0, 0}, // Objects {PkgName{}, 48, 88}, diff --git a/src/go/types/sizes.go b/src/go/types/sizes.go index 4c85bfe057..0f65c5830c 100644 --- a/src/go/types/sizes.go +++ b/src/go/types/sizes.go @@ -243,7 +243,7 @@ func (conf *Config) offsetsof(T *Struct) []int64 { func (conf *Config) offsetof(typ Type, index []int) int64 { var o int64 for _, i := range index { - s := asStruct(typ) + s := toStruct(typ) o += conf.offsetsof(s)[i] typ = s.fields[i].typ } diff --git a/src/go/types/subst.go b/src/go/types/subst.go index e539ab54e6..f0b79f60c6 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -74,7 +74,7 @@ func (subst *subster) typ(typ Type) Type { // Call typOrNil if it's possible that typ is nil. panic("nil typ") - case *Basic, *top: + case *Basic: // nothing to do case *Array: diff --git a/src/go/types/testdata/check/issues.go2 b/src/go/types/testdata/check/issues.go2 index 6a93bcc9ac..b7bba5d3b1 100644 --- a/src/go/types/testdata/check/issues.go2 +++ b/src/go/types/testdata/check/issues.go2 @@ -224,6 +224,13 @@ func _[T interface{ ~func() }](f T) { go f() } +type F1 func() +type F2 func() +func _[T interface{ func()|F1|F2 }](f T) { + f() + go f() +} + // We must compare against the underlying type of term list entries // when checking if a constraint is satisfied by a type. The under- // lying type of each term list entry must be computed after the diff --git a/src/go/types/type.go b/src/go/types/type.go index 502c9b2d52..011babdcb9 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -9,26 +9,13 @@ package types type Type interface { // Underlying returns the underlying type of a type // w/o following forwarding chains. Only used by - // client packages (here for backward-compatibility). + // client packages. Underlying() Type // String returns a string representation of a type. String() string } -// top represents the top of the type lattice. -// It is the underlying type of a type parameter that -// can be satisfied by any type (ignoring methods), -// because its type constraint contains no restrictions -// besides methods. -type top struct{} - -// theTop is the singleton top type. -var theTop = &top{} - -func (t *top) Underlying() Type { return t } -func (t *top) String() string { return TypeString(t, nil) } - // under returns the true expanded underlying type. // If it doesn't exist, the result is Typ[Invalid]. // under must only be called when a type is known @@ -40,77 +27,47 @@ func under(t Type) Type { return t } -// optype returns a type's operational type. Except for -// type parameters, the operational type is the same -// as the underlying type (as returned by under). For -// Type parameters, the operational type is the structural -// type, if any; otherwise it's the top type. -// The result is never the incoming type parameter. -func optype(typ Type) Type { - if t := asTypeParam(typ); t != nil { - // TODO(gri) review accuracy of this comment - // If the optype is typ, return the top type as we have - // no information. It also prevents infinite recursion - // via the asTypeParam converter function. This can happen - // for a type parameter list of the form: - // (type T interface { type T }). - // See also issue #39680. - if u := t.structuralType(); u != nil { - assert(u != typ) // "naked" type parameters cannot be embedded - return under(u) // optype should always return an underlying type - } - return theTop - } - return under(typ) -} - -// Converters -// -// A converter must only be called when a type is -// known to be fully set up. A converter returns -// a type's operational type (see comment for optype) -// or nil if the type argument is not of the -// respective type. +// Convenience converters -func asBasic(t Type) *Basic { - op, _ := optype(t).(*Basic) +func toBasic(t Type) *Basic { + op, _ := under(t).(*Basic) return op } -func asArray(t Type) *Array { - op, _ := optype(t).(*Array) +func toArray(t Type) *Array { + op, _ := under(t).(*Array) return op } -func asSlice(t Type) *Slice { - op, _ := optype(t).(*Slice) +func toSlice(t Type) *Slice { + op, _ := under(t).(*Slice) return op } -func asStruct(t Type) *Struct { - op, _ := optype(t).(*Struct) +func toStruct(t Type) *Struct { + op, _ := under(t).(*Struct) return op } -func asPointer(t Type) *Pointer { - op, _ := optype(t).(*Pointer) +func toPointer(t Type) *Pointer { + op, _ := under(t).(*Pointer) return op } -func asSignature(t Type) *Signature { - op, _ := optype(t).(*Signature) +func toSignature(t Type) *Signature { + op, _ := under(t).(*Signature) return op } -// If the argument to asInterface, asNamed, or asTypeParam is of the respective type -// (possibly after expanding an instance type), these methods return that type. -// Otherwise the result is nil. - -func asInterface(t Type) *Interface { - op, _ := optype(t).(*Interface) +func toInterface(t Type) *Interface { + op, _ := under(t).(*Interface) return op } +// If the argument to asNamed, or asTypeParam is of the respective type +// (possibly after expanding resolving a *Named type), these methods return that type. +// Otherwise the result is nil. + func asNamed(t Type) *Named { e, _ := t.(*Named) if e != nil { diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 9154ebc406..1e36db82ea 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -283,9 +283,6 @@ func (w *typeWriter) typ(typ Type) { w.string(subscript(t.id)) } - case *top: - w.error("⊤") - default: // For externally defined implementations of Type. // Note: In this case cycles won't be caught. @@ -369,7 +366,7 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) { } else { // special case: // append(s, "foo"...) leads to signature func([]byte, string...) - if t := asBasic(typ); t == nil || t.kind != String { + if t := toBasic(typ); t == nil || t.kind != String { w.error("expected string type") continue } diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 3636c8556a..ad6eab9c79 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -141,11 +141,11 @@ func (check *Checker) typ(e ast.Expr) Type { // constraint interface. func (check *Checker) varType(e ast.Expr) Type { typ := check.definedType(e, nil) - // We don't want to call under() (via asInterface) or complete interfaces while we + // We don't want to call under() (via toInterface) or complete interfaces while we // are in the middle of type-checking parameter declarations that might belong to // interface methods. Delay this check to the end of type-checking. check.later(func() { - if t := asInterface(typ); t != nil { + if t := toInterface(typ); t != nil { tset := computeInterfaceTypeSet(check, e.Pos(), t) // TODO(gri) is this the correct position? if !tset.IsMethodSet() { if tset.comparable { -- GitLab From b24687394b55a93449e2be4e6892ead58ea9a10f Mon Sep 17 00:00:00 2001 From: Jason7602 Date: Tue, 14 Sep 2021 21:38:19 +0800 Subject: [PATCH 1903/2500] archive/zip: don't panic on (*Reader).Open Previously, opening a zip with (*Reader).Open could result in a panic if the zip contained a file whose name was exclusively made up of slash characters or ".." path elements. Open could also panic if passed the empty string directly as an argument. Now, any files in the zip whose name could not be made valid for fs.FS.Open will be skipped, and no longer added to the fs.FS file list, although they are still accessible through (*Reader).File. Note that it was already the case that a file could be accessible from (*Reader).Open with a name different from the one in (*Reader).File, as the former is the cleaned name, while the latter is the original one. Finally, made the actual panic site robust as a defense-in-depth measure. Fixes CVE-2021-41772 Fixes #48085 Co-authored-by: Filippo Valsorda Change-Id: I6271a3f2892e7746f52e213b8eba9a1bba974678 Reviewed-on: https://go-review.googlesource.com/c/go/+/349770 Run-TryBot: Filippo Valsorda Reviewed-by: Katie Hockman Reviewed-by: Filippo Valsorda Trust: Katie Hockman Trust: Julie Qiu --- src/archive/zip/reader.go | 10 ++- src/archive/zip/reader_test.go | 128 +++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 2 deletions(-) diff --git a/src/archive/zip/reader.go b/src/archive/zip/reader.go index c91a8d00e6..e40a2c656b 100644 --- a/src/archive/zip/reader.go +++ b/src/archive/zip/reader.go @@ -741,6 +741,9 @@ func (r *Reader) initFileList() { for _, file := range r.File { isDir := len(file.Name) > 0 && file.Name[len(file.Name)-1] == '/' name := toValidName(file.Name) + if name == "" { + continue + } for dir := path.Dir(name); dir != "."; dir = path.Dir(dir) { dirs[dir] = true } @@ -782,8 +785,11 @@ func fileEntryLess(x, y string) bool { func (r *Reader) Open(name string) (fs.File, error) { r.initFileList() + if !fs.ValidPath(name) { + return nil, &fs.PathError{Op: "open", Path: name, Err: fs.ErrInvalid} + } e := r.openLookup(name) - if e == nil || !fs.ValidPath(name) { + if e == nil { return nil, &fs.PathError{Op: "open", Path: name, Err: fs.ErrNotExist} } if e.isDir { @@ -797,7 +803,7 @@ func (r *Reader) Open(name string) (fs.File, error) { } func split(name string) (dir, elem string, isDir bool) { - if name[len(name)-1] == '/' { + if len(name) > 0 && name[len(name)-1] == '/' { isDir = true name = name[:len(name)-1] } diff --git a/src/archive/zip/reader_test.go b/src/archive/zip/reader_test.go index afb03ace24..a54915316c 100644 --- a/src/archive/zip/reader_test.go +++ b/src/archive/zip/reader_test.go @@ -13,6 +13,7 @@ import ( "io/fs" "os" "path/filepath" + "reflect" "regexp" "strings" "testing" @@ -1202,6 +1203,15 @@ func TestCVE202127919(t *testing.T) { if err != nil { t.Errorf("Error reading file: %v", err) } + if len(r.File) != 1 { + t.Fatalf("No entries in the file list") + } + if r.File[0].Name != "../test.txt" { + t.Errorf("Unexpected entry name: %s", r.File[0].Name) + } + if _, err := r.File[0].Open(); err != nil { + t.Errorf("Error opening file: %v", err) + } } func TestReadDataDescriptor(t *testing.T) { @@ -1402,3 +1412,121 @@ func TestCVE202139293(t *testing.T) { t.Fatalf("unexpected error, got: %v, want: %v", err, ErrFormat) } } + +func TestCVE202141772(t *testing.T) { + // Archive contains a file whose name is exclusively made up of '/', '\' + // characters, or "../", "..\" paths, which would previously cause a panic. + // + // Length Method Size Cmpr Date Time CRC-32 Name + // -------- ------ ------- ---- ---------- ----- -------- ---- + // 0 Stored 0 0% 08-05-2021 18:32 00000000 / + // 0 Stored 0 0% 09-14-2021 12:59 00000000 // + // 0 Stored 0 0% 09-14-2021 12:59 00000000 \ + // 11 Stored 11 0% 09-14-2021 13:04 0d4a1185 /test.txt + // -------- ------- --- ------- + // 11 11 0% 4 files + data := []byte{ + 0x50, 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x06, 0x94, 0x05, 0x53, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x50, + 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x78, 0x67, 0x2e, 0x53, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x2f, 0x2f, 0x50, + 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x78, 0x67, 0x2e, 0x53, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x5c, 0x50, 0x4b, + 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x91, 0x68, 0x2e, 0x53, 0x85, 0x11, 0x4a, 0x0d, + 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x2f, 0x74, 0x65, 0x73, + 0x74, 0x2e, 0x74, 0x78, 0x74, 0x68, 0x65, 0x6c, + 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, + 0x50, 0x4b, 0x01, 0x02, 0x14, 0x03, 0x0a, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x06, 0x94, 0x05, 0x53, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0xed, 0x41, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x50, + 0x4b, 0x01, 0x02, 0x3f, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x78, 0x67, 0x2e, 0x53, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x24, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x1f, 0x00, 0x00, 0x00, 0x2f, 0x2f, 0x0a, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x18, 0x00, 0x93, 0x98, 0x25, 0x57, 0x25, + 0xa9, 0xd7, 0x01, 0x93, 0x98, 0x25, 0x57, 0x25, + 0xa9, 0xd7, 0x01, 0x93, 0x98, 0x25, 0x57, 0x25, + 0xa9, 0xd7, 0x01, 0x50, 0x4b, 0x01, 0x02, 0x3f, + 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, + 0x67, 0x2e, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, + 0x00, 0x5c, 0x0a, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x93, 0x98, + 0x25, 0x57, 0x25, 0xa9, 0xd7, 0x01, 0x93, 0x98, + 0x25, 0x57, 0x25, 0xa9, 0xd7, 0x01, 0x93, 0x98, + 0x25, 0x57, 0x25, 0xa9, 0xd7, 0x01, 0x50, 0x4b, + 0x01, 0x02, 0x3f, 0x00, 0x0a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x91, 0x68, 0x2e, 0x53, 0x85, 0x11, + 0x4a, 0x0d, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, + 0x00, 0x00, 0x09, 0x00, 0x24, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x5e, 0x00, 0x00, 0x00, 0x2f, 0x74, 0x65, 0x73, + 0x74, 0x2e, 0x74, 0x78, 0x74, 0x0a, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, + 0x00, 0xa9, 0x80, 0x51, 0x01, 0x26, 0xa9, 0xd7, + 0x01, 0x31, 0xd1, 0x57, 0x01, 0x26, 0xa9, 0xd7, + 0x01, 0xdf, 0x48, 0x85, 0xf9, 0x25, 0xa9, 0xd7, + 0x01, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x04, 0x00, 0x31, 0x01, 0x00, + 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, + } + r, err := NewReader(bytes.NewReader([]byte(data)), int64(len(data))) + if err != nil { + t.Fatalf("Error reading the archive: %v", err) + } + entryNames := []string{`/`, `//`, `\`, `/test.txt`} + var names []string + for _, f := range r.File { + names = append(names, f.Name) + if _, err := f.Open(); err != nil { + t.Errorf("Error opening %q: %v", f.Name, err) + } + if _, err := r.Open(f.Name); err == nil { + t.Errorf("Opening %q with fs.FS API succeeded", f.Name) + } + } + if !reflect.DeepEqual(names, entryNames) { + t.Errorf("Unexpected file entries: %q", names) + } + if _, err := r.Open(""); err == nil { + t.Errorf("Opening %q with fs.FS API succeeded", "") + } + if _, err := r.Open("test.txt"); err != nil { + t.Errorf("Error opening %q with fs.FS API: %v", "test.txt", err) + } + dirEntries, err := fs.ReadDir(r, ".") + if err != nil { + t.Fatalf("Error reading the root directory: %v", err) + } + if len(dirEntries) != 1 || dirEntries[0].Name() != "test.txt" { + t.Errorf("Unexpected directory entries") + for _, dirEntry := range dirEntries { + _, err := r.Open(dirEntry.Name()) + t.Logf("%q (Open error: %v)", dirEntry.Name(), err) + } + t.FailNow() + } + info, err := dirEntries[0].Info() + if err != nil { + t.Fatalf("Error reading info entry: %v", err) + } + if name := info.Name(); name != "test.txt" { + t.Errorf("Inconsistent name in info entry: %v", name) + } +} -- GitLab From 79024cf33d0cea53a0c75f428d79a9f971f12b5b Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 2 Nov 2021 11:05:03 -0700 Subject: [PATCH 1904/2500] errors: improve wording in As doc comment "so" didn't have an antecedent. Change-Id: I27f7b334decea7bc34bfa3f3f2d3a79874c6fe90 Reviewed-on: https://go-review.googlesource.com/c/go/+/360797 Trust: Josh Bleecher Snyder Reviewed-by: Ian Lance Taylor --- src/errors/wrap.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/errors/wrap.go b/src/errors/wrap.go index b73d5a8ce2..ab3cdb86d3 100644 --- a/src/errors/wrap.go +++ b/src/errors/wrap.go @@ -59,7 +59,7 @@ func Is(err, target error) bool { } } -// As finds the first error in err's chain that matches target, and if so, sets +// As finds the first error in err's chain that matches target, and if one is found, sets // target to that error value and returns true. Otherwise, it returns false. // // The chain consists of err itself followed by the sequence of errors obtained by -- GitLab From 1012bc810fcd3076015edf947785e54ec6b1d766 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 2 Nov 2021 11:20:10 -0400 Subject: [PATCH 1905/2500] go/types: clean up asT converters (step 2 of 2) This is a clean port of CL 358774 to go/types. Change-Id: Icba54336de2b8de7c2002d2a44cac856907178c9 Reviewed-on: https://go-review.googlesource.com/c/go/+/360754 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/assignments.go | 2 +- src/go/types/builtins.go | 8 ++++---- src/go/types/call.go | 2 +- src/go/types/conversions.go | 20 ++++++++++---------- src/go/types/expr.go | 6 +++--- src/go/types/index.go | 6 +++--- src/go/types/lookup.go | 8 ++++---- src/go/types/predicates.go | 6 +++--- src/go/types/sizes.go | 2 +- src/go/types/type.go | 14 +++++++------- src/go/types/typestring.go | 2 +- src/go/types/typexpr.go | 2 +- 12 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/go/types/assignments.go b/src/go/types/assignments.go index cfdb0eb14a..2810133a1f 100644 --- a/src/go/types/assignments.go +++ b/src/go/types/assignments.go @@ -71,7 +71,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { } // A generic (non-instantiated) function value cannot be assigned to a variable. - if sig := toSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { + if sig := asSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { check.errorf(x, _Todo, "cannot use generic function %s without instantiation in %s", x, context) } diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index e6fb6ef4ff..ceb2adcaae 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -299,7 +299,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // (applyTypeFunc never calls f with a type parameter) f := func(typ Type) Type { assert(asTypeParam(typ) == nil) - if t := toBasic(typ); t != nil { + if t := asBasic(typ); t != nil { switch t.kind { case Float32: return Typ[Complex64] @@ -423,7 +423,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // (applyTypeFunc never calls f with a type parameter) f := func(typ Type) Type { assert(asTypeParam(typ) == nil) - if t := toBasic(typ); t != nil { + if t := asBasic(typ); t != nil { switch t.kind { case Complex64: return Typ[Float32] @@ -713,7 +713,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b return } - typ := toPointer(x.typ) + typ := asPointer(x.typ) if typ == nil { check.invalidArg(x, _InvalidUnsafeSlice, "%s is not a pointer", x) return @@ -893,7 +893,7 @@ func makeSig(res Type, args ...Type) *Signature { // otherwise it returns typ. func arrayPtrDeref(typ Type) Type { if p, ok := typ.(*Pointer); ok { - if a := toArray(p.base); a != nil { + if a := asArray(p.base); a != nil { return a } } diff --git a/src/go/types/call.go b/src/go/types/call.go index a4e834271f..64c7658a60 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -141,7 +141,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { check.errorf(call.Args[0], _BadDotDotDotSyntax, "invalid use of ... in conversion to %s", T) break } - if t := toInterface(T); t != nil { + if t := asInterface(T); t != nil { if !t.IsMethodSet() { check.errorf(call, _Todo, "cannot use interface %s in conversion (contains specific type constraints or is comparable)", T) break diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go index c3fc04e406..f8af12b68f 100644 --- a/src/go/types/conversions.go +++ b/src/go/types/conversions.go @@ -21,7 +21,7 @@ func (check *Checker) conversion(x *operand, T Type) { switch { case constArg && isConstType(T): // constant conversion (T cannot be a type parameter) - switch t := toBasic(T); { + switch t := asBasic(T); { case representableConst(x.val, check, t, &x.val): ok = true case isInteger(x.typ) && isString(t): @@ -198,9 +198,9 @@ func convertibleToImpl(check *Checker, V, T Type, cause *string) bool { // "V is a slice, T is a pointer-to-array type, // and the slice and array types have identical element types." - if s := toSlice(V); s != nil { - if p := toPointer(T); p != nil { - if a := toArray(p.Elem()); a != nil { + if s := asSlice(V); s != nil { + if p := asPointer(T); p != nil { + if a := asArray(p.Elem()); a != nil { if Identical(s.Elem(), a.Elem()) { if check == nil || check.allowVersion(check.pkg, 1, 17) { return true @@ -221,26 +221,26 @@ func convertibleToImpl(check *Checker, V, T Type, cause *string) bool { // use the toT convenience converters in the predicates below. func isUintptr(typ Type) bool { - t := toBasic(typ) + t := asBasic(typ) return t != nil && t.kind == Uintptr } func isUnsafePointer(typ Type) bool { - // TODO(gri): Is this toBasic(typ) instead of typ.(*Basic) correct? + // TODO(gri): Is this asBasic(typ) instead of typ.(*Basic) correct? // (The former calls under(), while the latter doesn't.) // The spec does not say so, but gc claims it is. See also // issue 6326. - t := toBasic(typ) + t := asBasic(typ) return t != nil && t.kind == UnsafePointer } func isPointer(typ Type) bool { - return toPointer(typ) != nil + return asPointer(typ) != nil } func isBytesOrRunes(typ Type) bool { - if s := toSlice(typ); s != nil { - t := toBasic(s.elem) + if s := asSlice(typ); s != nil { + t := asBasic(s.elem) return t != nil && (t.kind == Byte || t.kind == Rune) } return false diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 266f896f6e..103053e6b7 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -103,7 +103,7 @@ func (check *Checker) overflow(x *operand, op token.Token, opPos token.Pos) { // x.typ cannot be a type parameter (type // parameters cannot be constant types). if isTyped(x.typ) { - check.representable(x, toBasic(x.typ)) + check.representable(x, asBasic(x.typ)) return } @@ -556,7 +556,7 @@ func (check *Checker) updateExprType(x ast.Expr, typ Type, final bool) { // If the new type is not final and still untyped, just // update the recorded type. if !final && isUntyped(typ) { - old.typ = toBasic(typ) + old.typ = asBasic(typ) check.untyped[x] = old return } @@ -1355,7 +1355,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { duplicate := false // if the key is of interface type, the type is also significant when checking for duplicates xkey := keyVal(x.val) - if toInterface(utyp.key) != nil { + if asInterface(utyp.key) != nil { for _, vtyp := range visited[xkey] { if Identical(vtyp, x.typ) { duplicate = true diff --git a/src/go/types/index.go b/src/go/types/index.go index 9f723bcf67..24c1812039 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -35,7 +35,7 @@ func (check *Checker) indexExpr(x *operand, e *typeparams.IndexExpr) (isFuncInst return false case value: - if sig := toSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { + if sig := asSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { // function instantiation return true } @@ -72,7 +72,7 @@ func (check *Checker) indexExpr(x *operand, e *typeparams.IndexExpr) (isFuncInst x.typ = typ.elem case *Pointer: - if typ := toArray(typ.base); typ != nil { + if typ := asArray(typ.base); typ != nil { valid = true length = typ.len x.mode = variable @@ -242,7 +242,7 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { x.typ = &Slice{elem: u.elem} case *Pointer: - if u := toArray(u.base); u != nil { + if u := asArray(u.base); u != nil { valid = true length = u.len x.typ = &Slice{elem: u.elem} diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index 506cc69384..afb1215af2 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -302,7 +302,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, return } - if ityp := toInterface(V); ityp != nil { + if ityp := asInterface(V); ityp != nil { // TODO(gri) the methods are sorted - could do this more efficiently for _, m := range T.typeSet().methods { _, f := ityp.typeSet().LookupMethod(m.pkg, m.name) @@ -400,7 +400,7 @@ func (check *Checker) assertableTo(V *Interface, T Type) (method, wrongType *Fun // no static check is required if T is an interface // spec: "If T is an interface type, x.(T) asserts that the // dynamic type of x implements the interface T." - if toInterface(T) != nil && !forceStrict { + if asInterface(T) != nil && !forceStrict { return } return check.missingMethod(T, V, false) @@ -418,8 +418,8 @@ func deref(typ Type) (Type, bool) { // derefStructPtr dereferences typ if it is a (named or unnamed) pointer to a // (named or unnamed) struct and returns its base. Otherwise it returns typ. func derefStructPtr(typ Type) Type { - if p := toPointer(typ); p != nil { - if toStruct(p.base) != nil { + if p := asPointer(typ); p != nil { + if asStruct(p.base) != nil { return p.base } } diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index d4ce97a16b..b802682e8f 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -58,7 +58,7 @@ func isNumericOrString(typ Type) bool { return is(typ, IsNumeric|IsString) } // are not fully set up. func isTyped(typ Type) bool { // isTyped is called with types that are not fully - // set up. Must not call toBasic()! + // set up. Must not call asBasic()! t, _ := typ.(*Basic) return t == nil || t.info&IsUntyped == 0 } @@ -72,13 +72,13 @@ func isOrdered(typ Type) bool { return is(typ, IsOrdered) } func isConstType(typ Type) bool { // Type parameters are never const types. - t := toBasic(typ) + t := asBasic(typ) return t != nil && t.info&IsConstType != 0 } // IsInterface reports whether typ is an interface type. func IsInterface(typ Type) bool { - return toInterface(typ) != nil + return asInterface(typ) != nil } // Comparable reports whether values of type T are comparable. diff --git a/src/go/types/sizes.go b/src/go/types/sizes.go index 0f65c5830c..4c85bfe057 100644 --- a/src/go/types/sizes.go +++ b/src/go/types/sizes.go @@ -243,7 +243,7 @@ func (conf *Config) offsetsof(T *Struct) []int64 { func (conf *Config) offsetof(typ Type, index []int) int64 { var o int64 for _, i := range index { - s := toStruct(typ) + s := asStruct(typ) o += conf.offsetsof(s)[i] typ = s.fields[i].typ } diff --git a/src/go/types/type.go b/src/go/types/type.go index 011babdcb9..4247f52c31 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -29,37 +29,37 @@ func under(t Type) Type { // Convenience converters -func toBasic(t Type) *Basic { +func asBasic(t Type) *Basic { op, _ := under(t).(*Basic) return op } -func toArray(t Type) *Array { +func asArray(t Type) *Array { op, _ := under(t).(*Array) return op } -func toSlice(t Type) *Slice { +func asSlice(t Type) *Slice { op, _ := under(t).(*Slice) return op } -func toStruct(t Type) *Struct { +func asStruct(t Type) *Struct { op, _ := under(t).(*Struct) return op } -func toPointer(t Type) *Pointer { +func asPointer(t Type) *Pointer { op, _ := under(t).(*Pointer) return op } -func toSignature(t Type) *Signature { +func asSignature(t Type) *Signature { op, _ := under(t).(*Signature) return op } -func toInterface(t Type) *Interface { +func asInterface(t Type) *Interface { op, _ := under(t).(*Interface) return op } diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 1e36db82ea..40a8ff475d 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -366,7 +366,7 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) { } else { // special case: // append(s, "foo"...) leads to signature func([]byte, string...) - if t := toBasic(typ); t == nil || t.kind != String { + if t := asBasic(typ); t == nil || t.kind != String { w.error("expected string type") continue } diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index ad6eab9c79..e1d942a5c6 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -145,7 +145,7 @@ func (check *Checker) varType(e ast.Expr) Type { // are in the middle of type-checking parameter declarations that might belong to // interface methods. Delay this check to the end of type-checking. check.later(func() { - if t := toInterface(typ); t != nil { + if t := asInterface(typ); t != nil { tset := computeInterfaceTypeSet(check, e.Pos(), t) // TODO(gri) is this the correct position? if !tset.IsMethodSet() { if tset.comparable { -- GitLab From 60fd3ed2b167e4bb823600ea6862758a222a48c2 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 2 Nov 2021 11:23:19 -0400 Subject: [PATCH 1906/2500] go/types: rename isNamed predicate to hasName This is a clean port of CL 358621 to go/types. Change-Id: I4e858b1b70cff69b6e0e76bb8a58a70ff54990c9 Reviewed-on: https://go-review.googlesource.com/c/go/+/360755 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/operand.go | 9 ++++----- src/go/types/predicates.go | 7 ++++--- src/go/types/testdata/spec/assignability.go2 | 8 +++++--- src/go/types/unify.go | 8 ++++---- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/go/types/operand.go b/src/go/types/operand.go index 0ba3c4bafc..a71449083f 100644 --- a/src/go/types/operand.go +++ b/src/go/types/operand.go @@ -267,9 +267,8 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er // Vu is typed // x's type V and T have identical underlying types - // and at least one of V or T is not a named type - // and neither is a type parameter. - if Identical(Vu, Tu) && (!isNamed(V) || !isNamed(T)) && Vp == nil && Tp == nil { + // and at least one of V or T is not a named type. + if Identical(Vu, Tu) && (!hasName(V) || !hasName(T)) { return true, 0 } @@ -296,10 +295,10 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er // x is a bidirectional channel value, T is a channel // type, x's type V and T have identical element types, - // and at least one of V or T is not a named type + // and at least one of V or T is not a named type. if Vc, ok := Vu.(*Chan); ok && Vc.dir == SendRecv { if Tc, ok := Tu.(*Chan); ok && Identical(Vc.elem, Tc.elem) { - return !isNamed(V) || !isNamed(T), _InvalidChanAssign + return !hasName(V) || !hasName(T), _InvalidChanAssign } } diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index b802682e8f..2f74397d41 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -8,9 +8,10 @@ package types import "go/token" -// isNamed reports whether typ has a name. -// isNamed may be called with types that are not fully set up. -func isNamed(typ Type) bool { +// hasName reports whether typ has a name. This includes +// predeclared types, defined types, and type parameters. +// hasName may be called with types that are not fully set up. +func hasName(typ Type) bool { switch typ.(type) { case *Basic, *Named, *TypeParam: return true diff --git a/src/go/types/testdata/spec/assignability.go2 b/src/go/types/testdata/spec/assignability.go2 index 4c6774b811..8ec878bf39 100644 --- a/src/go/types/testdata/spec/assignability.go2 +++ b/src/go/types/testdata/spec/assignability.go2 @@ -33,8 +33,9 @@ func _[TP any](X TP) { X = X } -// "x's type V and T have identical underlying types and at least one -// of V or T is not a defined type and neither is a type parameter" +// "x's type V and T have identical underlying types +// and at least one of V or T is not a named type." +// (here a named type is a type with a name) func _[TP1, TP2 Interface](X1 TP1, X2 TP2) { b = B // ERROR cannot use B .* as int value a = A @@ -69,7 +70,8 @@ func _[TP Interface](X TP) { X = i // ERROR cannot use i .* as TP value } -// "x is a bidirectional channel value, T is a channel type, x's type V and T have identical element types, and at least one of V or T is not a defined type" +// "x is a bidirectional channel value, T is a channel type, x's type V and T have identical element types, and at least one of V or T is not a named type" +// (here a named type is a type with a name) type ( _SendChan = chan<- int _RecvChan = <-chan int diff --git a/src/go/types/unify.go b/src/go/types/unify.go index 99c9c9e614..d3b86008ef 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -235,13 +235,13 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { // If exact unification is known to fail because we attempt to // match a type name against an unnamed type literal, consider // the underlying type of the named type. - // (Subtle: We use isNamed to include any type with a name (incl. - // basic types and type parameters. We use asNamed() because we only + // (Subtle: We use hasName to include any type with a name (incl. + // basic types and type parameters. We use asNamed because we only // want *Named types.) switch { - case !isNamed(x) && y != nil && asNamed(y) != nil: + case !hasName(x) && y != nil && asNamed(y) != nil: return u.nify(x, under(y), p) - case x != nil && asNamed(x) != nil && !isNamed(y): + case x != nil && asNamed(x) != nil && !hasName(y): return u.nify(under(x), y, p) } } -- GitLab From 80065cf2f6cdf56616c87036af91afa7f2fb2913 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 2 Nov 2021 11:34:11 -0400 Subject: [PATCH 1907/2500] go/types: implement singleType and structure (type) This is a clean port of CL 359015 to go/types. Change-Id: Iea4e3bfe0a4ae0e5a9052cb6e66c01405bd57c3d Reviewed-on: https://go-review.googlesource.com/c/go/+/360756 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/builtins.go | 26 ++++++++++---------- src/go/types/call.go | 2 +- src/go/types/expr.go | 2 +- src/go/types/index.go | 2 +- src/go/types/infer.go | 13 +++++++--- src/go/types/stmt.go | 2 +- src/go/types/termlist.go | 4 +-- src/go/types/termlist_test.go | 6 ++--- src/go/types/testdata/examples/inference.go2 | 23 +++++++++++++++++ src/go/types/typeparam.go | 6 ++--- src/go/types/typeset.go | 4 +-- 11 files changed, 59 insertions(+), 31 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index ceb2adcaae..aefac786ca 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -83,7 +83,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // of S and the respective parameter passing rules apply." S := x.typ var T Type - if s, _ := singleUnder(S).(*Slice); s != nil { + if s, _ := structure(S).(*Slice); s != nil { T = s.elem } else { check.invalidArg(x, _InvalidAppend, "%s is not a slice", x) @@ -332,14 +332,14 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b case _Copy: // copy(x, y []T) int - dst, _ := singleUnder(x.typ).(*Slice) + dst, _ := structure(x.typ).(*Slice) var y operand arg(&y, 1) if y.mode == invalid { return } - src, _ := singleUnderString(y.typ).(*Slice) + src, _ := structureString(y.typ).(*Slice) if dst == nil || src == nil { check.invalidArg(x, _InvalidCopy, "copy expects slice arguments; found %s and %s", x, &y) @@ -473,7 +473,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b } var min int // minimum number of arguments - switch singleUnder(T).(type) { + switch structure(T).(type) { case *Slice: min = 2 case *Map, *Chan: @@ -776,11 +776,11 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b return true } -// If typ is a type parameter, single under returns the single underlying -// type of all types in the corresponding type constraint if it exists, or -// nil if it doesn't exist. If typ is not a type parameter, singleUnder -// just returns the underlying type. -func singleUnder(typ Type) Type { +// If typ is a type parameter, structure returns the single underlying +// type of all types in the corresponding type constraint if it exists, +// or nil otherwise. If typ is not a type parameter, structure returns +// the underlying type. +func structure(typ Type) Type { var su Type if underIs(typ, func(u Type) bool { if su != nil && !Identical(su, u) { @@ -795,10 +795,10 @@ func singleUnder(typ Type) Type { return nil } -// singleUnderString is like singleUnder but also considers []byte and -// string as "identical". In this case, if successful, the result is always -// []byte. -func singleUnderString(typ Type) Type { +// structureString is like structure but also considers []byte and +// string as "identical". In this case, if successful, the result +// is always []byte. +func structureString(typ Type) Type { var su Type if underIs(typ, func(u Type) bool { if isString(u) { diff --git a/src/go/types/call.go b/src/go/types/call.go index 64c7658a60..a7024f5f9c 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -175,7 +175,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { cgocall := x.mode == cgofunc // a type parameter may be "called" if all types have the same signature - sig, _ := singleUnder(x.typ).(*Signature) + sig, _ := structure(x.typ).(*Signature) if sig == nil { check.invalidOp(x, _InvalidCall, "cannot call non-function %s", x) x.mode = invalid diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 103053e6b7..612f0da210 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -1227,7 +1227,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { goto Error } - switch utyp := singleUnder(base).(type) { + switch utyp := structure(base).(type) { case *Struct: if len(e.Elts) == 0 { break diff --git a/src/go/types/index.go b/src/go/types/index.go index 24c1812039..807cf58980 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -207,7 +207,7 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { valid := false length := int64(-1) // valid if >= 0 - switch u := singleUnder(x.typ).(type) { + switch u := structure(x.typ).(type) { case nil: check.errorf(x, _NonSliceableOperand, "cannot slice %s: type set has no single underlying type", x) x.mode = invalid diff --git a/src/go/types/infer.go b/src/go/types/infer.go index cea0780721..61f7eaf91e 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -358,7 +358,7 @@ func (w *tpWalker) isParameterizedTypeList(list []Type) bool { func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type, index int) { assert(len(tparams) >= len(targs) && len(targs) > 0) - // Setup bidirectional unification between those structural bounds + // Setup bidirectional unification between constraints // and the corresponding type arguments (which may be nil!). u := newUnifier(false) u.x.init(tparams) @@ -371,11 +371,16 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type, } } - // Unify type parameters with their structural constraints, if any. + // If a constraint has a structural type, unify the corresponding type parameter with it. for _, tpar := range tparams { typ := tpar - sbound := typ.structuralType() + sbound := structure(tpar) if sbound != nil { + // If the structural type is the underlying type of a single + // defined type in the constraint, use that defined type instead. + if named, _ := tpar.singleType().(*Named); named != nil { + sbound = named + } if !u.unify(typ, sbound) { check.errorf(tpar.obj, _Todo, "%s does not match %s", tpar.obj, sbound) return nil, 0 @@ -384,7 +389,7 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type, } // u.x.types() now contains the incoming type arguments plus any additional type - // arguments for which there were structural constraints. The newly inferred non- + // arguments which were inferred from structural types. The newly inferred non- // nil entries may still contain references to other type parameters. // For instance, for [A any, B interface{ []C }, C interface{ *A }], if A == int // was given, unification produced the type list [int, []C, *A]. We eliminate the diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index 7197310bd9..cc4eceae5d 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -834,7 +834,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { if x.mode != invalid { // Ranging over a type parameter is permitted if it has a single underlying type. var cause string - u := singleUnder(x.typ) + u := structure(x.typ) switch t := u.(type) { case nil: cause = "type set has no single underlying type" diff --git a/src/go/types/termlist.go b/src/go/types/termlist.go index 99114cbf4c..c4ab0e037e 100644 --- a/src/go/types/termlist.go +++ b/src/go/types/termlist.go @@ -93,8 +93,8 @@ func (xl termlist) norm() termlist { } // If the type set represented by xl is specified by a single (non-𝓤) term, -// structuralType returns that type. Otherwise it returns nil. -func (xl termlist) structuralType() Type { +// singleType returns that type. Otherwise it returns nil. +func (xl termlist) singleType() Type { if nl := xl.norm(); len(nl) == 1 { return nl[0].typ // if nl.isAll() then typ is nil, which is ok } diff --git a/src/go/types/termlist_test.go b/src/go/types/termlist_test.go index d1fe28f728..dddca7a682 100644 --- a/src/go/types/termlist_test.go +++ b/src/go/types/termlist_test.go @@ -106,7 +106,7 @@ func TestTermlistNorm(t *testing.T) { } } -func TestTermlistStructuralType(t *testing.T) { +func TestTermlistSingleType(t *testing.T) { // helper to deal with nil types tstring := func(typ Type) string { if typ == nil { @@ -128,9 +128,9 @@ func TestTermlistStructuralType(t *testing.T) { "∅ ∪ ~int ∪ string": "nil", } { xl := maketl(test) - got := tstring(xl.structuralType()) + got := tstring(xl.singleType()) if got != want { - t.Errorf("(%v).structuralType() == %v; want %v", test, got, want) + t.Errorf("(%v).singleType() == %v; want %v", test, got, want) } } } diff --git a/src/go/types/testdata/examples/inference.go2 b/src/go/types/testdata/examples/inference.go2 index 9a2dcc47f2..73246b0137 100644 --- a/src/go/types/testdata/examples/inference.go2 +++ b/src/go/types/testdata/examples/inference.go2 @@ -99,3 +99,26 @@ func _() { related2(1.0, []int{}) related2 /* ERROR does not satisfy */ (float64(1.0), []int{}) } + +type List[P any] []P + +func related3[Elem any, Slice []Elem | List[Elem]]() Slice { return nil } + +func _() { + // related3 can be instantiated explicitly + related3[int, []int]() + related3[byte, List[byte]]() + + // Alternatively, the 2nd type argument can be inferred + // from the first one through constraint type inference. + related3[int]() + + // The inferred type is the structural type of the Slice + // type parameter. + var _ []int = related3[int]() + + // It is not the defined parameterized type List. + type anotherList []float32 + var _ anotherList = related3[float32]() // valid + var _ anotherList = related3 /* ERROR cannot use .* \(value of type List\[float32\]\) as anotherList */ [float32, List[float32]]() +} diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index 791e9db8f8..731b746d05 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -118,9 +118,9 @@ func (t *TypeParam) iface() *Interface { return ityp } -// structuralType returns the structural type of the type parameter's constraint; or nil. -func (t *TypeParam) structuralType() Type { - return t.iface().typeSet().structuralType() +// singleType returns the single type of the type parameter constraint; or nil. +func (t *TypeParam) singleType() Type { + return t.iface().typeSet().singleType() } // hasTerms reports whether the type parameter constraint has specific type terms. diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index 215b48488f..f8e76ed400 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -102,8 +102,8 @@ func (s *_TypeSet) String() string { // hasTerms reports whether the type set has specific type terms. func (s *_TypeSet) hasTerms() bool { return !s.terms.isEmpty() && !s.terms.isAll() } -// structuralType returns the single type in s if there is exactly one; otherwise the result is nil. -func (s *_TypeSet) structuralType() Type { return s.terms.structuralType() } +// singleType returns the single type in s if there is exactly one; otherwise the result is nil. +func (s *_TypeSet) singleType() Type { return s.terms.singleType() } // includes reports whether t ∈ s. func (s *_TypeSet) includes(t Type) bool { return s.terms.includes(t) } -- GitLab From ea403bc237657e160e628e2670bbbb62016bf2b2 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 2 Nov 2021 11:42:54 -0400 Subject: [PATCH 1908/2500] go/types: disallow lone type parameter on RHS of type declaration This is a clean port of CL 359177 to go/types. Change-Id: I6c1574e3a1c23ea326eb8d4aacea0e78415703ab Reviewed-on: https://go-review.googlesource.com/c/go/+/360758 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/api_test.go | 14 ---- src/go/types/decl.go | 9 ++- src/go/types/testdata/check/linalg.go2 | 61 +++++++++-------- src/go/types/testdata/check/typeinst.go2 | 5 +- src/go/types/testdata/check/typeinst2.go2 | 30 +++++---- src/go/types/testdata/check/typeparams.go2 | 19 +++--- src/go/types/testdata/examples/methods.go2 | 31 +++++---- src/go/types/testdata/examples/types.go2 | 13 ++-- .../types/testdata/fixedbugs/issue39634.go2 | 7 +- .../types/testdata/fixedbugs/issue39768.go2 | 17 ++--- .../types/testdata/fixedbugs/issue39938.go2 | 2 +- .../types/testdata/fixedbugs/issue45639.go2 | 13 ++-- .../types/testdata/fixedbugs/issue47747.go2 | 67 ++++++++++--------- 13 files changed, 143 insertions(+), 145 deletions(-) diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index 7407426979..34cc61fc2c 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -604,13 +604,6 @@ func TestDefsInfo(t *testing.T) { {`package p3; type x int`, `x`, `type p3.x int`}, {`package p4; func f()`, `f`, `func p4.f()`}, {`package p5; func f() int { x, _ := 1, 2; return x }`, `_`, `var _ int`}, - - // generic types must be sanitized - // (need to use sufficiently nested types to provoke unexpanded types) - {genericPkg + `g0; type t[P any] P; const x = t[int](42)`, `x`, `const generic_g0.x generic_g0.t[int]`}, - {genericPkg + `g1; type t[P any] P; var x = t[int](42)`, `x`, `var generic_g1.x generic_g1.t[int]`}, - {genericPkg + `g2; type t[P any] P; type x struct{ f t[int] }`, `x`, `type generic_g2.x struct{f generic_g2.t[int]}`}, - {genericPkg + `g3; type t[P any] P; func f(x struct{ f t[string] }); var g = f`, `g`, `var generic_g3.g func(x struct{f generic_g3.t[string]})`}, } for _, test := range tests { @@ -649,13 +642,6 @@ func TestUsesInfo(t *testing.T) { {`package p2; func _() { _ = x }; var x int`, `x`, `var p2.x int`}, {`package p3; func _() { type _ x }; type x int`, `x`, `type p3.x int`}, {`package p4; func _() { _ = f }; func f()`, `f`, `func p4.f()`}, - - // generic types must be sanitized - // (need to use sufficiently nested types to provoke unexpanded types) - {genericPkg + `g0; func _() { _ = x }; type t[P any] P; const x = t[int](42)`, `x`, `const generic_g0.x generic_g0.t[int]`}, - {genericPkg + `g1; func _() { _ = x }; type t[P any] P; var x = t[int](42)`, `x`, `var generic_g1.x generic_g1.t[int]`}, - {genericPkg + `g2; func _() { type _ x }; type t[P any] P; type x struct{ f t[int] }`, `x`, `type generic_g2.x struct{f generic_g2.t[int]}`}, - {genericPkg + `g3; func _() { _ = f }; type t[P any] P; func f(x struct{ f t[string] })`, `f`, `func generic_g3.f(x struct{f generic_g3.t[string]})`}, } for _, test := range tests { diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 6982fed0b8..8d255dcf3d 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -653,9 +653,12 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { named.underlying = Typ[Invalid] } - // If the RHS is a type parameter, it must be from this type declaration. - if tpar, _ := named.underlying.(*TypeParam); tpar != nil && tparamIndex(named.TypeParams().list(), tpar) < 0 { - check.errorf(tdecl.Type, _Todo, "cannot use function type parameter %s as RHS in type declaration", tpar) + // Disallow a lone type parameter as the RHS of a type declaration (issue #45639). + // We can look directly at named.underlying because even if it is still a *Named + // type (underlying not fully resolved yet) it cannot become a type parameter due + // to this very restriction. + if tpar, _ := named.underlying.(*TypeParam); tpar != nil { + check.error(tdecl.Type, _Todo, "cannot use a type parameter as RHS in type declaration") named.underlying = Typ[Invalid] } } diff --git a/src/go/types/testdata/check/linalg.go2 b/src/go/types/testdata/check/linalg.go2 index efc090a1d1..f02e773dbe 100644 --- a/src/go/types/testdata/check/linalg.go2 +++ b/src/go/types/testdata/check/linalg.go2 @@ -4,8 +4,6 @@ package linalg -import "math" - // Numeric is type bound that matches any numeric type. // It would likely be in a constraints package in the standard library. type Numeric interface { @@ -52,32 +50,33 @@ type Complex interface { ~complex64 | ~complex128 } -// OrderedAbs is a helper type that defines an Abs method for -// ordered numeric types. -type OrderedAbs[T OrderedNumeric] T - -func (a OrderedAbs[T]) Abs() OrderedAbs[T] { - if a < 0 { - return -a - } - return a -} - -// ComplexAbs is a helper type that defines an Abs method for -// complex types. -type ComplexAbs[T Complex] T - -func (a ComplexAbs[T]) Abs() ComplexAbs[T] { - r := float64(real(a)) - i := float64(imag(a)) - d := math.Sqrt(r * r + i * i) - return ComplexAbs[T](complex(d, 0)) -} - -func OrderedAbsDifference[T OrderedNumeric](a, b T) T { - return T(AbsDifference(OrderedAbs[T](a), OrderedAbs[T](b))) -} - -func ComplexAbsDifference[T Complex](a, b T) T { - return T(AbsDifference(ComplexAbs[T](a), ComplexAbs[T](b))) -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// // OrderedAbs is a helper type that defines an Abs method for +// // ordered numeric types. +// type OrderedAbs[T OrderedNumeric] T +// +// func (a OrderedAbs[T]) Abs() OrderedAbs[T] { +// if a < 0 { +// return -a +// } +// return a +// } +// +// // ComplexAbs is a helper type that defines an Abs method for +// // complex types. +// type ComplexAbs[T Complex] T +// +// func (a ComplexAbs[T]) Abs() ComplexAbs[T] { +// r := float64(real(a)) +// i := float64(imag(a)) +// d := math.Sqrt(r * r + i * i) +// return ComplexAbs[T](complex(d, 0)) +// } +// +// func OrderedAbsDifference[T OrderedNumeric](a, b T) T { +// return T(AbsDifference(OrderedAbs[T](a), OrderedAbs[T](b))) +// } +// +// func ComplexAbsDifference[T Complex](a, b T) T { +// return T(AbsDifference(ComplexAbs[T](a), ComplexAbs[T](b))) +// } diff --git a/src/go/types/testdata/check/typeinst.go2 b/src/go/types/testdata/check/typeinst.go2 index f4f6c0264b..65481202e4 100644 --- a/src/go/types/testdata/check/typeinst.go2 +++ b/src/go/types/testdata/check/typeinst.go2 @@ -8,7 +8,8 @@ type myInt int // Parameterized type declarations -type T1[P any] P +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +type T1[P any] P // ERROR cannot use a type parameter as RHS in type declaration type T2[P any] struct { f P @@ -19,7 +20,7 @@ type List[P any] []P // Alias type declarations cannot have type parameters. // Issue #46477 proposses to change that. -type A1[P any] = /* ERROR cannot be alias */ P +type A1[P any] = /* ERROR cannot be alias */ struct{} // Pending clarification of #46477 we disallow aliases // of generic types. diff --git a/src/go/types/testdata/check/typeinst2.go2 b/src/go/types/testdata/check/typeinst2.go2 index ebcc300675..f07c42a1da 100644 --- a/src/go/types/testdata/check/typeinst2.go2 +++ b/src/go/types/testdata/check/typeinst2.go2 @@ -87,25 +87,27 @@ type NumericAbs[T any] interface { func AbsDifference[T NumericAbs[T]](x T) { panic(0) } -type OrderedAbs[T any] T - -func (a OrderedAbs[T]) Abs() OrderedAbs[T] - -func OrderedAbsDifference[T any](x T) { - AbsDifference(OrderedAbs[T](x)) -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// type OrderedAbs[T any] T +// +// func (a OrderedAbs[T]) Abs() OrderedAbs[T] +// +// func OrderedAbsDifference[T any](x T) { +// AbsDifference(OrderedAbs[T](x)) +// } // same code, reduced to essence func g[P interface{ m() P }](x P) { panic(0) } -type T4[P any] P - -func (_ T4[P]) m() T4[P] - -func _[Q any](x Q) { - g(T4[Q](x)) -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// type T4[P any] P +// +// func (_ T4[P]) m() T4[P] +// +// func _[Q any](x Q) { +// g(T4[Q](x)) +// } // Another test case that caused problems in the past diff --git a/src/go/types/testdata/check/typeparams.go2 b/src/go/types/testdata/check/typeparams.go2 index 3694b0ed00..446667cd66 100644 --- a/src/go/types/testdata/check/typeparams.go2 +++ b/src/go/types/testdata/check/typeparams.go2 @@ -352,15 +352,16 @@ func _() { // the previous example was extracted from -func f12[T interface{m() T}]() {} - -type A[T any] T - -func (a A[T]) m() A[T] - -func _[T any]() { - f12[A[T]]() -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// func f12[T interface{m() T}]() {} +// +// type A[T any] T +// +// func (a A[T]) m() A[T] +// +// func _[T any]() { +// f12[A[T]]() +// } // method expressions diff --git a/src/go/types/testdata/examples/methods.go2 b/src/go/types/testdata/examples/methods.go2 index 4e87041e54..1d76d553dc 100644 --- a/src/go/types/testdata/examples/methods.go2 +++ b/src/go/types/testdata/examples/methods.go2 @@ -6,8 +6,6 @@ package p -import "unsafe" - // Parameterized types may have methods. type T1[A any] struct{ a A } @@ -97,17 +95,18 @@ type T0 struct{} func (T0) _() {} func (T1[A]) _() {} -// A generic receiver type may constrain its type parameter such -// that it must be a pointer type. Such receiver types are not -// permitted. -type T3a[P interface{ ~int | ~string | ~float64 }] P - -func (T3a[_]) m() {} // this is ok - -type T3b[P interface{ ~unsafe.Pointer }] P - -func (T3b /* ERROR invalid receiver */ [_]) m() {} - -type T3c[P interface{ *int | *string }] P - -func (T3c /* ERROR invalid receiver */ [_]) m() {} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// // A generic receiver type may constrain its type parameter such +// // that it must be a pointer type. Such receiver types are not +// // permitted. +// type T3a[P interface{ ~int | ~string | ~float64 }] P +// +// func (T3a[_]) m() {} // this is ok +// +// type T3b[P interface{ ~unsafe.Pointer }] P +// +// func (T3b /* ERROR invalid receiver */ [_]) m() {} +// +// type T3c[P interface{ *int | *string }] P +// +// func (T3c /* ERROR invalid receiver */ [_]) m() {} diff --git a/src/go/types/testdata/examples/types.go2 b/src/go/types/testdata/examples/types.go2 index 367b73120c..33642fa42f 100644 --- a/src/go/types/testdata/examples/types.go2 +++ b/src/go/types/testdata/examples/types.go2 @@ -191,12 +191,13 @@ type _ struct { // _ = y < 0 //} -// It is not permitted to declare a local type whose underlying -// type is a type parameter not declared by that type declaration. -func _[T any]() { - type _ T // ERROR cannot use function type parameter T as RHS in type declaration - type _ [_ any] T // ERROR cannot use function type parameter T as RHS in type declaration -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// // It is not permitted to declare a local type whose underlying +// // type is a type parameter not declared by that type declaration. +// func _[T any]() { +// type _ T // ERROR cannot use function type parameter T as RHS in type declaration +// type _ [_ any] T // ERROR cannot use function type parameter T as RHS in type declaration +// } // As a special case, an explicit type argument may be omitted // from a type parameter bound if the type bound expects exactly diff --git a/src/go/types/testdata/fixedbugs/issue39634.go2 b/src/go/types/testdata/fixedbugs/issue39634.go2 index 5cff6e7555..2de2f4378a 100644 --- a/src/go/types/testdata/fixedbugs/issue39634.go2 +++ b/src/go/types/testdata/fixedbugs/issue39634.go2 @@ -74,9 +74,10 @@ func F20[t Z20]() { F20(t /* ERROR invalid composite literal type */ {}) } type Z21 /* ERROR illegal cycle */ interface{ Z21 } func F21[T Z21]() { ( /* ERROR not used */ F21[Z21]) } -// crash 24 -type T24[P any] P -func (r T24[P]) m() { T24 /* ERROR without instantiation */ .m() } +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// // crash 24 +// type T24[P any] P +// func (r T24[P]) m() { T24 /* ERROR without instantiation */ .m() } // crash 25 type T25[A any] int diff --git a/src/go/types/testdata/fixedbugs/issue39768.go2 b/src/go/types/testdata/fixedbugs/issue39768.go2 index fb522733e0..696d9d9bee 100644 --- a/src/go/types/testdata/fixedbugs/issue39768.go2 +++ b/src/go/types/testdata/fixedbugs/issue39768.go2 @@ -4,14 +4,15 @@ package p -type T[P any] P -type A = T // ERROR cannot use generic type -var x A[int] -var _ A - -type B = T[int] -var y B = x -var _ B /* ERROR not a generic type */ [int] +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// type T[P any] P +// type A = T // ERROR cannot use generic type +// var x A[int] +// var _ A +// +// type B = T[int] +// var y B = x +// var _ B /* ERROR not a generic type */ [int] // test case from issue diff --git a/src/go/types/testdata/fixedbugs/issue39938.go2 b/src/go/types/testdata/fixedbugs/issue39938.go2 index 31bec5fb01..114646786d 100644 --- a/src/go/types/testdata/fixedbugs/issue39938.go2 +++ b/src/go/types/testdata/fixedbugs/issue39938.go2 @@ -8,7 +8,7 @@ package p -type E0[P any] P +type E0[P any] []P type E1[P any] *P type E2[P any] struct{ _ P } type E3[P any] struct{ _ *P } diff --git a/src/go/types/testdata/fixedbugs/issue45639.go2 b/src/go/types/testdata/fixedbugs/issue45639.go2 index 441fb4cb34..80148fe481 100644 --- a/src/go/types/testdata/fixedbugs/issue45639.go2 +++ b/src/go/types/testdata/fixedbugs/issue45639.go2 @@ -4,9 +4,10 @@ package P -// It is not permitted to declare a local type whose underlying -// type is a type parameters not declared by that type declaration. -func _[T any]() { - type _ T // ERROR cannot use function type parameter T as RHS in type declaration - type _ [_ any] T // ERROR cannot use function type parameter T as RHS in type declaration -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// // It is not permitted to declare a local type whose underlying +// // type is a type parameters not declared by that type declaration. +// func _[T any]() { +// type _ T // ERROR cannot use function type parameter T as RHS in type declaration +// type _ [_ any] T // ERROR cannot use function type parameter T as RHS in type declaration +// } diff --git a/src/go/types/testdata/fixedbugs/issue47747.go2 b/src/go/types/testdata/fixedbugs/issue47747.go2 index af52056bef..6a2e787bf9 100644 --- a/src/go/types/testdata/fixedbugs/issue47747.go2 +++ b/src/go/types/testdata/fixedbugs/issue47747.go2 @@ -4,15 +4,16 @@ package p -type T1[P any] P - -func (T1[_]) m() {} - -func _[P any](x *T1[P]) { - // x.m exists because x is of type *T1 where T1 is a defined type - // (even though under(T1) is a type parameter) - x.m() -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// type T1[P any] P +// +// func (T1[_]) m() {} +// +// func _[P any](x *T1[P]) { +// // x.m exists because x is of type *T1 where T1 is a defined type +// // (even though under(T1) is a type parameter) +// x.m() +// } func _[P interface{ m() }](x P) { @@ -40,29 +41,31 @@ type Barer[t any] interface { Bar(t) } -type Foo1[t any] t -type Bar[t any] t - -func (l Foo1[t]) Foo(v Barer[t]) { v.Bar(t(l)) } -func (b *Bar[t]) Bar(l t) { *b = Bar[t](l) } - -func _[t any](f Fooer1[t]) t { - var b Bar[t] - f.Foo(&b) - return t(b) -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// type Foo1[t any] t +// type Bar[t any] t +// +// func (l Foo1[t]) Foo(v Barer[t]) { v.Bar(t(l)) } +// func (b *Bar[t]) Bar(l t) { *b = Bar[t](l) } +// +// func _[t any](f Fooer1[t]) t { +// var b Bar[t] +// f.Foo(&b) +// return t(b) +// } // Test case 2 from issue -type Fooer2[t any] interface { - Foo() -} - -type Foo2[t any] t - -func (f *Foo2[t]) Foo() {} - -func _[t any](v t) { - var f = Foo2[t](v) - _ = Fooer2[t](&f) -} +// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). +// type Fooer2[t any] interface { +// Foo() +// } +// +// type Foo2[t any] t +// +// func (f *Foo2[t]) Foo() {} +// +// func _[t any](v t) { +// var f = Foo2[t](v) +// _ = Fooer2[t](&f) +// } -- GitLab From 42e6b5bce2d027d4fcc4a7358b97a468494855d8 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 2 Nov 2021 11:46:25 -0400 Subject: [PATCH 1909/2500] go/types: differently named types are not assignable This is a clean port of CL 360274 to go/types. Change-Id: Idfa584fab95f7226e10b1a7c5b06d56a0bf9d757 Reviewed-on: https://go-review.googlesource.com/c/go/+/360759 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/operand.go | 66 +++++++++---------- .../types/testdata/fixedbugs/issue49242.go2 | 27 ++++++++ src/go/types/testdata/spec/assignability.go2 | 46 ++++++++++--- 3 files changed, 94 insertions(+), 45 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue49242.go2 diff --git a/src/go/types/operand.go b/src/go/types/operand.go index a71449083f..8b76e939b6 100644 --- a/src/go/types/operand.go +++ b/src/go/types/operand.go @@ -302,19 +302,11 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er } } - // common case: if we don't have type parameters, we're done + // optimization: if we don't have type parameters, we're done if Vp == nil && Tp == nil { return false, _IncompatibleAssign } - // determine type parameter operands with specific type terms - if Vp != nil && !Vp.hasTerms() { - Vp = nil - } - if Tp != nil && !Tp.hasTerms() { - Tp = nil - } - errorf := func(format string, args ...interface{}) { if check != nil && reason != nil { msg := check.sprintf(format, args...) @@ -325,44 +317,46 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er } } - ok := false - code := _IncompatibleAssign - switch { - case Vp != nil && Tp != nil: - x := *x // don't clobber outer x - ok = Vp.is(func(V *term) bool { - x.typ = V.typ - return Tp.is(func(T *term) bool { - ok, code = x.assignableTo(check, T.typ, reason) - if !ok { - errorf("cannot assign %s (in %s) to %s (in %s)", V.typ, Vp, T.typ, Tp) - return false - } - return true - }) - }) - case Vp != nil: - x := *x // don't clobber outer x - ok = Vp.is(func(V *term) bool { - x.typ = V.typ - ok, code = x.assignableTo(check, T, reason) + // x's type V is not a named type and T is a type parameter, and + // x is assignable to each specific type in T's type set. + if !hasName(V) && Tp != nil { + ok := false + code := _IncompatibleAssign + Tp.is(func(T *term) bool { + if T == nil { + return false // no specific types + } + ok, code = x.assignableTo(check, T.typ, reason) if !ok { - errorf("cannot assign %s (in %s) to %s", V.typ, Vp, T) + errorf("cannot assign %s to %s (in %s)", x.typ, T.typ, Tp) return false } return true }) - case Tp != nil: + return ok, code + } + + // x's type V is a type parameter and T is not a named type, + // and values x' of each specific type in V's type set are + // assignable to T. + if Vp != nil && !hasName(T) { x := *x // don't clobber outer x - ok = Tp.is(func(T *term) bool { - ok, code = x.assignableTo(check, T.typ, reason) + ok := false + code := _IncompatibleAssign + Vp.is(func(V *term) bool { + if V == nil { + return false // no specific types + } + x.typ = V.typ + ok, code = x.assignableTo(check, T, reason) if !ok { - errorf("cannot assign %s to %s (in %s)", x.typ, T.typ, Tp) + errorf("cannot assign %s (in %s) to %s", V.typ, Vp, T) return false } return true }) + return ok, code } - return ok, code + return false, _IncompatibleAssign } diff --git a/src/go/types/testdata/fixedbugs/issue49242.go2 b/src/go/types/testdata/fixedbugs/issue49242.go2 new file mode 100644 index 0000000000..524a0cbae3 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue49242.go2 @@ -0,0 +1,27 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func _[P int](x P) int { + return x // ERROR cannot use x .* as int value in return statement +} + +func _[P int]() int { + return P /* ERROR cannot use P\(1\) .* as int value in return statement */ (1) +} + +func _[P int](x int) P { + return x // ERROR cannot use x .* as P value in return statement +} + +func _[P, Q any](x P) Q { + return x // ERROR cannot use x .* as Q value in return statement +} + +// test case from issue +func F[G interface{ uint }]() int { + f := func(uint) int { return 0 } + return f(G /* ERROR cannot use G\(1\) .* as uint value in argument to f */ (1)) +} diff --git a/src/go/types/testdata/spec/assignability.go2 b/src/go/types/testdata/spec/assignability.go2 index 8ec878bf39..a6e71aac81 100644 --- a/src/go/types/testdata/spec/assignability.go2 +++ b/src/go/types/testdata/spec/assignability.go2 @@ -109,20 +109,48 @@ func _[ ) var ( - _ _CC = C - _ _SC = C - _ _RC = C + _ _CC = C // ERROR cannot use C .* as _CC value + _ _SC = C // ERROR cannot use C .* as _SC value + _ _RC = C // ERROR cannot use C .* as _RC value - _ CC = _CC(nil) - _ SC = _CC(nil) - _ RC = _CC(nil) + _ CC = _CC /* ERROR cannot use _CC\(nil\) .* as CC value */ (nil) + _ SC = _CC /* ERROR cannot use _CC\(nil\) .* as SC value */ (nil) + _ RC = _CC /* ERROR cannot use _CC\(nil\) .* as RC value */ (nil) - _ CC = C - _ SC = C // ERROR cannot use C .* as SC value .* cannot assign Chan to SendChan - _ RC = C // ERROR cannot use C .* as RC value .* cannot assign Chan to RecvChan + _ CC = C // ERROR cannot use C .* as CC value + _ SC = C // ERROR cannot use C .* as SC value + _ RC = C // ERROR cannot use C .* as RC value ) } +// "x's type V is not a named type and T is a type parameter, and x is assignable to each specific type in T's type set." +func _[ + TP0 any, + TP1 ~_Chan, + TP2 ~chan int | ~chan byte, +]() { + var ( + _ TP0 = c // ERROR cannot use c .* as TP0 value + _ TP0 = C // ERROR cannot use C .* as TP0 value + _ TP1 = c + _ TP1 = C // ERROR cannot use C .* as TP1 value + _ TP2 = c // ERROR .* cannot assign chan int to chan byte + ) +} + +// "x's type V is a type parameter and T is not a named type, and values x' of each specific type in V's type set are assignable to T." +func _[ + TP0 Interface, + TP1 ~_Chan, + TP2 ~chan int | ~chan byte, +](X0 TP0, X1 TP1, X2 TP2) { + i = X0 + I = X0 + c = X1 + C = X1 // ERROR cannot use X1 .* as Chan value + c = X2 // ERROR .* cannot assign chan byte \(in TP2\) to chan int +} + // "x is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type" // TODO(rfindley) error messages about untyped nil diverge from types2 here. // Consider aligning them. -- GitLab From 2157498dfee125e43cc37cad622fb7d2115dd3a8 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Tue, 2 Nov 2021 07:59:16 -0700 Subject: [PATCH 1910/2500] doc/go1.18: remove some redundancy from netip docs Change-Id: I593862331add3366f6b337844588568301746b80 Reviewed-on: https://go-review.googlesource.com/c/go/+/360608 Reviewed-by: Josh Bleecher Snyder Trust: Josh Bleecher Snyder Trust: Brad Fitzpatrick --- doc/go1.18.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 82fe6f4520..171cc3cb22 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -131,8 +131,8 @@ Do not send CLs removing the interior tags from such phrases.

New net/netip package

The new net/netip - package defines a new IP address type, Addr - that's a small, comparable, value type. Compared to the existing + package defines a new IP address type, Addr. + Compared to the existing net.IP type, the netip.Addr type takes less memory, is immutable, and is comparable so it supports == and can be used as a map key. -- GitLab From eb63cbd2950e703ff2a6bd04330e97dc76c7923d Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 2 Nov 2021 12:30:37 -0700 Subject: [PATCH 1911/2500] cmd/compile: remove TODO that is no longer relevant types2 methods are now sorted in the same way as types1, so this TODO is no longer needed. (Comment change only). Change-Id: Ic975ce001a5d54f15381a9cb7b6969dff795e3b4 Reviewed-on: https://go-review.googlesource.com/c/go/+/360856 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/noder/expr.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index d19513a1ac..24e6dbefe7 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -235,12 +235,6 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto return DotField(pos, x, last) } - // TODO(danscales,mdempsky): Interface method sets are not sorted the - // same between types and types2. In particular, using "last" here - // without conversion will likely fail if an interface contains - // unexported methods from two different packages (due to cross-package - // interface embedding). - var n ir.Node method2 := selinfo.Obj().(*types2.Func) -- GitLab From a0f373ca08b05eb97e4bff7e8710c023d94231c3 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 2 Nov 2021 13:56:22 -0700 Subject: [PATCH 1912/2500] runtime/asan: declare asan reporting functions in C Fixes #49287 Change-Id: I3f970d6db0b1dee886df2f7bb6cbeb56a37c42c2 Reviewed-on: https://go-review.googlesource.com/c/go/+/360860 Trust: Ian Lance Taylor Reviewed-by: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot --- src/runtime/asan/asan.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/runtime/asan/asan.go b/src/runtime/asan/asan.go index ac71466b71..eb66b3aab5 100644 --- a/src/runtime/asan/asan.go +++ b/src/runtime/asan/asan.go @@ -10,9 +10,21 @@ package asan #cgo CFLAGS: -fsanitize=address #cgo LDFLAGS: -fsanitize=address +#include #include #include +extern void __asan_report_load1(void*); +extern void __asan_report_load2(void*); +extern void __asan_report_load4(void*); +extern void __asan_report_load8(void*); +extern void __asan_report_load_n(void*, uintptr_t); +extern void __asan_report_store1(void*); +extern void __asan_report_store2(void*); +extern void __asan_report_store4(void*); +extern void __asan_report_store8(void*); +extern void __asan_report_store_n(void*, uintptr_t); + void __asan_read_go(void *addr, uintptr_t sz) { if (__asan_region_is_poisoned(addr, sz)) { switch (sz) { -- GitLab From 32d27527a6dfb45a98d47a4a9ac5341028d79aa1 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 2 Nov 2021 18:25:21 -0400 Subject: [PATCH 1913/2500] go/types: fix conversions of constants to type parameter This is a port of both CL 360396 and CL 360796 to go/types. The latter is added to avoid introducing an intermediate bug. An error message was adjusted in issue49296.go2, with a TODO to switch to the types2 error. Change-Id: Iede294b69b4e097e53876498f039ee18667568c4 Reviewed-on: https://go-review.googlesource.com/c/go/+/360934 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/conversions.go | 41 ++++++++++++++----- src/go/types/expr.go | 1 + src/go/types/predicates.go | 6 +++ .../types/testdata/fixedbugs/issue49247.go2 | 20 +++++++++ .../types/testdata/fixedbugs/issue49296.go2 | 21 ++++++++++ src/go/types/testdata/spec/conversions.go2 | 21 ++++++++++ 6 files changed, 100 insertions(+), 10 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue49247.go2 create mode 100644 src/go/types/testdata/fixedbugs/issue49296.go2 diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go index f8af12b68f..9baad98e09 100644 --- a/src/go/types/conversions.go +++ b/src/go/types/conversions.go @@ -16,26 +16,47 @@ import ( func (check *Checker) conversion(x *operand, T Type) { constArg := x.mode == constant_ - var ok bool - var cause string - switch { - case constArg && isConstType(T): - // constant conversion (T cannot be a type parameter) + constConvertibleTo := func(T Type, val *constant.Value) bool { switch t := asBasic(T); { - case representableConst(x.val, check, t, &x.val): - ok = true + case t == nil: + // nothing to do + case representableConst(x.val, check, t, val): + return true case isInteger(x.typ) && isString(t): codepoint := unicode.ReplacementChar if i, ok := constant.Uint64Val(x.val); ok && i <= unicode.MaxRune { codepoint = rune(i) } - x.val = constant.MakeString(string(codepoint)) - ok = true + if val != nil { + *val = constant.MakeString(string(codepoint)) + } + return true } + return false + } + + var ok bool + var cause string + switch { + case constArg && isConstType(T): + // constant conversion + ok = constConvertibleTo(T, &x.val) + case constArg && isTypeParam(T): + // x is convertible to T if it is convertible + // to each specific type in the type set of T. + // If T's type set is empty, or if it doesn't + // have specific types, constant x cannot be + // converted. + ok = under(T).(*TypeParam).underIs(func(u Type) bool { + // t is nil if there are no specific type terms + // TODO(gri) add a cause in case of failure + return u != nil && constConvertibleTo(u, nil) + }) + x.mode = value // type parameters are not constants case x.convertibleTo(check, T, &cause): // non-constant conversion - x.mode = value ok = true + x.mode = value } if !ok { diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 612f0da210..d4de212e06 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -681,6 +681,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const return nil, nil, _InvalidUntypedConversion } case *TypeParam: + // TODO(gri) review this code - doesn't look quite right ok := t.underIs(func(t Type) bool { target, _, _ := check.implicitTypeAndValue(x, t) return target != nil diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 2f74397d41..3c76d15c79 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -82,6 +82,12 @@ func IsInterface(typ Type) bool { return asInterface(typ) != nil } +// isTypeParam reports whether typ is a type parameter. +func isTypeParam(typ Type) bool { + _, ok := under(typ).(*TypeParam) + return ok +} + // Comparable reports whether values of type T are comparable. func Comparable(T Type) bool { return comparable(T, nil) diff --git a/src/go/types/testdata/fixedbugs/issue49247.go2 b/src/go/types/testdata/fixedbugs/issue49247.go2 new file mode 100644 index 0000000000..3f25e0ee35 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue49247.go2 @@ -0,0 +1,20 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type integer interface { + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr +} + +func Add1024[T integer](s []T) { + for i, v := range s { + s[i] = v + 1024 // ERROR cannot convert 1024 \(untyped int constant\) to T + } +} + +func f[T interface{ int8 }]() { + println(T(1024 /* ERROR cannot convert 1024 \(untyped int value\) to T */)) +} diff --git a/src/go/types/testdata/fixedbugs/issue49296.go2 b/src/go/types/testdata/fixedbugs/issue49296.go2 new file mode 100644 index 0000000000..8c6d0b678d --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue49296.go2 @@ -0,0 +1,21 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func _[ + T0 any, + T1 []int, + T2 ~float64 | ~complex128 | chan int, +]() { + // TODO(rfindley): the types2 error here is clearer. + _ = T0(nil /* ERROR cannot convert nil \(untyped nil value\) to T0 */ ) + _ = T1(1 /* ERROR cannot convert 1 .* to T1 */ ) + _ = T2(2 /* ERROR cannot convert 2 .* to T2 */ ) +} + +// test case from issue +func f[T interface{[]int}]() { + _ = T(1 /* ERROR cannot convert */ ) +} diff --git a/src/go/types/testdata/spec/conversions.go2 b/src/go/types/testdata/spec/conversions.go2 index eb988ffed1..47b1f07d87 100644 --- a/src/go/types/testdata/spec/conversions.go2 +++ b/src/go/types/testdata/spec/conversions.go2 @@ -6,6 +6,27 @@ package conversions import "unsafe" +// constant conversions + +func _[T ~byte]() T { return 255 } +func _[T ~byte]() T { return 256 /* ERROR cannot use 256 .* as T value */ } + +func _[T ~byte]() { + const _ = T /* ERROR T\(0\) .* is not constant */ (0) + var _ T = 255 + var _ T = 256 // ERROR cannot use 256 .* as T value +} + +func _[T ~string]() T { return T('a') } +func _[T ~int | ~string]() T { return T('a') } +func _[T ~byte | ~int | ~string]() T { return T(256 /* ERROR cannot convert 256 .* to T */ ) } + +// implicit conversions never convert to string +func _[T ~string]() { + var _ string = 0 // ERROR cannot use .* as string value + var _ T = 0 // ERROR cannot use .* as T value +} + // "x is assignable to T" // - tested via assignability tests -- GitLab From d6f7203a3c63276680457b9794191a366a1a4401 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 2 Nov 2021 18:29:27 -0400 Subject: [PATCH 1914/2500] go/types: adjust printing of type parameter in error This is a clean port of CL 360514 to go/types. Change-Id: Ia13638b3758b3b8017867934d09136ac5f9a62ca Reviewed-on: https://go-review.googlesource.com/c/go/+/360935 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/infer.go | 7 ++++--- src/go/types/testdata/fixedbugs/issue45985.go2 | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/go/types/infer.go b/src/go/types/infer.go index 61f7eaf91e..41326a1be8 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -373,7 +373,6 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type, // If a constraint has a structural type, unify the corresponding type parameter with it. for _, tpar := range tparams { - typ := tpar sbound := structure(tpar) if sbound != nil { // If the structural type is the underlying type of a single @@ -381,8 +380,10 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type, if named, _ := tpar.singleType().(*Named); named != nil { sbound = named } - if !u.unify(typ, sbound) { - check.errorf(tpar.obj, _Todo, "%s does not match %s", tpar.obj, sbound) + if !u.unify(tpar, sbound) { + // TODO(gri) improve error message by providing the type arguments + // which we know already + check.errorf(tpar.obj, _Todo, "%s does not match %s", tpar, sbound) return nil, 0 } } diff --git a/src/go/types/testdata/fixedbugs/issue45985.go2 b/src/go/types/testdata/fixedbugs/issue45985.go2 index 07395911cd..637e2cad5e 100644 --- a/src/go/types/testdata/fixedbugs/issue45985.go2 +++ b/src/go/types/testdata/fixedbugs/issue45985.go2 @@ -5,7 +5,7 @@ package issue45985 // TODO(rFindley): this error should be on app[int] below. -func app[S /* ERROR "type S S does not match" */ interface{ ~[]T }, T any](s S, e T) S { +func app[S /* ERROR "S does not match" */ interface{ ~[]T }, T any](s S, e T) S { return append(s, e) } -- GitLab From 2b81b863a258decaaca26ab4c01bfd070cc01ebe Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 2 Nov 2021 18:36:36 -0400 Subject: [PATCH 1915/2500] go/types: fix indexing of generic types This is a clean port of CL 360603 to go/types. Change-Id: Iadb312f07e509ff83339d5525765b7b7987bf233 Reviewed-on: https://go-review.googlesource.com/c/go/+/360936 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/index.go | 87 +++++++++++----------- src/go/types/testdata/check/typeparams.go2 | 8 ++ 2 files changed, 53 insertions(+), 42 deletions(-) diff --git a/src/go/types/index.go b/src/go/types/index.go index 807cf58980..a85d314efa 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -101,77 +101,80 @@ func (check *Checker) indexExpr(x *operand, e *typeparams.IndexExpr) (isFuncInst case *TypeParam: // TODO(gri) report detailed failure cause for better error messages - var tkey, telem Type // tkey != nil if we have maps + var key, elem Type // key != nil: we must have all maps + mode := variable // non-maps result mode + // TODO(gri) factor out closure and use it for non-typeparam cases as well if typ.underIs(func(u Type) bool { - var key, elem Type - alen := int64(-1) // valid if >= 0 + l := int64(-1) // valid if >= 0 + var k, e Type // k is only set for maps switch t := u.(type) { case *Basic: - if !isString(t) { - return false + if isString(t) { + e = universeByte + mode = value } - elem = universeByte case *Array: - elem = t.elem - alen = t.len + l = t.len + e = t.elem + if x.mode != variable { + mode = value + } case *Pointer: - a, _ := under(t.base).(*Array) - if a == nil { - return false + if t := asArray(t.base); t != nil { + l = t.len + e = t.elem } - elem = a.elem - alen = a.len case *Slice: - elem = t.elem + e = t.elem case *Map: - key = t.key - elem = t.elem - default: + k = t.key + e = t.elem + } + if e == nil { return false } - assert(elem != nil) - if telem == nil { + if elem == nil { // first type - tkey, telem = key, elem - length = alen - } else { - // all map keys must be identical (incl. all nil) - if !Identical(key, tkey) { - return false - } - // all element types must be identical - if !Identical(elem, telem) { - return false - } - tkey, telem = key, elem - // track the minimal length for arrays - if alen >= 0 && alen < length { - length = alen - } + length = l + key, elem = k, e + return true + } + // all map keys must be identical (incl. all nil) + // (that is, we cannot mix maps with other types) + if !Identical(key, k) { + return false + } + // all element types must be identical + if !Identical(elem, e) { + return false + } + // track the minimal length for arrays, if any + if l >= 0 && l < length { + length = l } return true }) { // For maps, the index expression must be assignable to the map key type. - if tkey != nil { + if key != nil { index := check.singleIndex(e) if index == nil { x.mode = invalid return false } - var key operand - check.expr(&key, index) - check.assignment(&key, tkey, "map index") + var k operand + check.expr(&k, index) + check.assignment(&k, key, "map index") // ok to continue even if indexing failed - map element type is known x.mode = mapindex - x.typ = telem + x.typ = elem x.expr = e return false } // no maps valid = true - x.mode = variable - x.typ = telem + x.mode = mode + x.typ = elem } } diff --git a/src/go/types/testdata/check/typeparams.go2 b/src/go/types/testdata/check/typeparams.go2 index 446667cd66..09d478c4d7 100644 --- a/src/go/types/testdata/check/typeparams.go2 +++ b/src/go/types/testdata/check/typeparams.go2 @@ -114,6 +114,14 @@ func _[T interface{ [10]int }](x T, i int) { _ = x[i]; _ = x[9]; _ = x[10 /* ERR func _[T interface{ [10]byte | string }](x T, i int) { _ = x[i]; _ = x[9]; _ = x[10 /* ERROR out of bounds */ ] } func _[T interface{ [10]int | *[20]int | []int }](x T, i int) { _ = x[i]; _ = x[9]; _ = x[10 /* ERROR out of bounds */ ] } +// indexing with strings and non-variable arrays (assignment not permitted) +func _[T string](x T) { _ = x[0]; x /* ERROR cannot assign */ [0] = 0 } +func _[T []byte | string](x T) { x /* ERROR cannot assign */ [0] = 0 } +func _[T [10]byte]() { f := func() (x T) { return }; f /* ERROR cannot assign */ ()[0] = 0 } +func _[T [10]byte]() { f := func() (x *T) { return }; f /* ERROR cannot index */ ()[0] = 0 } +func _[T [10]byte]() { f := func() (x *T) { return }; (*f())[0] = 0 } +func _[T *[10]byte]() { f := func() (x T) { return }; f()[0] = 0 } + // slicing func _[T interface{ ~[10]E }, E any] (x T, i, j, k int) { var _ []E = x[i:j] } -- GitLab From 49a00631b118834010e4d0124ccc04eeaf2cd7ac Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 2 Nov 2021 18:42:51 -0400 Subject: [PATCH 1916/2500] go/types: report cause for failing const conversions This is a port of CL 360795 to go/types. Error messages were adjusted accordingly, with a TODO to fix the discrepancy. Change-Id: Ifd7d8248fa11a31fde391021f3c5f1840877892f Reviewed-on: https://go-review.googlesource.com/c/go/+/360937 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/conversions.go | 11 +++++++++-- src/go/types/testdata/spec/conversions.go2 | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go index 9baad98e09..a6f0714ba0 100644 --- a/src/go/types/conversions.go +++ b/src/go/types/conversions.go @@ -49,8 +49,15 @@ func (check *Checker) conversion(x *operand, T Type) { // converted. ok = under(T).(*TypeParam).underIs(func(u Type) bool { // t is nil if there are no specific type terms - // TODO(gri) add a cause in case of failure - return u != nil && constConvertibleTo(u, nil) + if u == nil { + cause = check.sprintf("%s does not contain specific types", T) + return false + } + if !constConvertibleTo(u, nil) { + cause = check.sprintf("cannot convert %s to %s (in %s)", x, u, T) + return false + } + return true }) x.mode = value // type parameters are not constants case x.convertibleTo(check, T, &cause): diff --git a/src/go/types/testdata/spec/conversions.go2 b/src/go/types/testdata/spec/conversions.go2 index 47b1f07d87..e54403cea9 100644 --- a/src/go/types/testdata/spec/conversions.go2 +++ b/src/go/types/testdata/spec/conversions.go2 @@ -27,6 +27,20 @@ func _[T ~string]() { var _ T = 0 // ERROR cannot use .* as T value } +// failing const conversions of constants to type parameters report a cause +func _[ + T1 any, + T2 interface{ m() }, + T3 ~int | ~float64 | ~bool, + T4 ~int | ~string, +]() { + // TODO(rfindley): align the error formatting here with types2. + _ = T1(0 /* ERROR cannot convert 0 .* to T1.*T1 does not contain specific types */ ) + _ = T2(1 /* ERROR cannot convert 1 .* to T2.*T2 does not contain specific types */ ) + _ = T3(2 /* ERROR cannot convert 2 .* to T3.*cannot convert 2 .* to bool \(in T3\) */ ) + _ = T4(3.14 /* ERROR cannot convert 3.14 .* to T4.*cannot convert 3.14 .* to int \(in T4\) */ ) +} + // "x is assignable to T" // - tested via assignability tests -- GitLab From 8f0ca7dc720b7197c91e02c8cef6e19ad95978d0 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 2 Nov 2021 09:58:12 -0700 Subject: [PATCH 1917/2500] cmd/compile/internal/types2: report cause for failing const conversions Follow-up on CL 360396. Change-Id: Icd802baffb1fef91f8fef0070b6167a438ceda1a Reviewed-on: https://go-review.googlesource.com/c/go/+/360795 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/conversions.go | 11 +++++++++-- .../internal/types2/testdata/spec/conversions.go2 | 13 +++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go index 4d0ed79c38..5798bacca7 100644 --- a/src/cmd/compile/internal/types2/conversions.go +++ b/src/cmd/compile/internal/types2/conversions.go @@ -49,8 +49,15 @@ func (check *Checker) conversion(x *operand, T Type) { // converted. ok = under(T).(*TypeParam).underIs(func(u Type) bool { // t is nil if there are no specific type terms - // TODO(gri) add a cause in case of failure - return u != nil && constConvertibleTo(u, nil) + if u == nil { + cause = check.sprintf("%s does not contain specific types", T) + return false + } + if !constConvertibleTo(u, nil) { + cause = check.sprintf("cannot convert %s to %s (in %s)", x, u, T) + return false + } + return true }) x.mode = value // type parameters are not constants case x.convertibleTo(check, T, &cause): diff --git a/src/cmd/compile/internal/types2/testdata/spec/conversions.go2 b/src/cmd/compile/internal/types2/testdata/spec/conversions.go2 index 942d9c0f6f..fde332f34b 100644 --- a/src/cmd/compile/internal/types2/testdata/spec/conversions.go2 +++ b/src/cmd/compile/internal/types2/testdata/spec/conversions.go2 @@ -27,6 +27,19 @@ func _[T ~string]() { var _ T = 0 // ERROR cannot use .* as T value } +// failing const conversions of constants to type parameters report a cause +func _[ + T1 any, + T2 interface{ m() }, + T3 ~int | ~float64 | ~bool, + T4 ~int | ~string, +]() { + _ = T1(0 /* ERROR cannot convert 0 .* to T1\n\tT1 does not contain specific types */ ) + _ = T2(1 /* ERROR cannot convert 1 .* to T2\n\tT2 does not contain specific types */ ) + _ = T3(2 /* ERROR cannot convert 2 .* to T3\n\tcannot convert 2 .* to bool \(in T3\) */ ) + _ = T4(3.14 /* ERROR cannot convert 3.14 .* to T4\n\tcannot convert 3.14 .* to int \(in T4\) */ ) +} + // "x is assignable to T" // - tested via assignability tests -- GitLab From a4b2c579e92c001287fd7b549bc9f67bcf2bfe7b Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 2 Nov 2021 14:12:05 -0700 Subject: [PATCH 1918/2500] runtime: install sigPreempt signal handler for c-archive/c-shared Fixes #49288 Change-Id: I7bfcbecbefa68871a3e556935a73f241fff44c0e Reviewed-on: https://go-review.googlesource.com/c/go/+/360861 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- misc/cgo/testcarchive/carchive_test.go | 52 ++++++++++++++++++++++ misc/cgo/testcarchive/testdata/libgo8/a.go | 36 +++++++++++++++ misc/cgo/testcarchive/testdata/main8.c | 16 +++++++ src/runtime/signal_unix.go | 4 +- 4 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 misc/cgo/testcarchive/testdata/libgo8/a.go create mode 100644 misc/cgo/testcarchive/testdata/main8.c diff --git a/misc/cgo/testcarchive/carchive_test.go b/misc/cgo/testcarchive/carchive_test.go index 55be3c5f70..a2b43bb72d 100644 --- a/misc/cgo/testcarchive/carchive_test.go +++ b/misc/cgo/testcarchive/carchive_test.go @@ -931,3 +931,55 @@ func TestManyCalls(t *testing.T) { t.Error(err) } } + +// Issue 49288. +func TestPreemption(t *testing.T) { + if runtime.Compiler == "gccgo" { + t.Skip("skipping asynchronous preemption test with gccgo") + } + + t.Parallel() + + if !testWork { + defer func() { + os.Remove("testp8" + exeSuffix) + os.Remove("libgo8.a") + os.Remove("libgo8.h") + }() + } + + cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo8.a", "./libgo8") + if out, err := cmd.CombinedOutput(); err != nil { + t.Logf("%s", out) + t.Fatal(err) + } + checkLineComments(t, "libgo8.h") + + ccArgs := append(cc, "-o", "testp8"+exeSuffix, "main8.c", "libgo8.a") + if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil { + t.Logf("%s", out) + t.Fatal(err) + } + + argv := cmdToRun("./testp8") + cmd = exec.Command(argv[0], argv[1:]...) + var sb strings.Builder + cmd.Stdout = &sb + cmd.Stderr = &sb + if err := cmd.Start(); err != nil { + t.Fatal(err) + } + + timer := time.AfterFunc(time.Minute, + func() { + t.Error("test program timed out") + cmd.Process.Kill() + }, + ) + defer timer.Stop() + + if err := cmd.Wait(); err != nil { + t.Log(sb.String()) + t.Error(err) + } +} diff --git a/misc/cgo/testcarchive/testdata/libgo8/a.go b/misc/cgo/testcarchive/testdata/libgo8/a.go new file mode 100644 index 0000000000..718418ecb8 --- /dev/null +++ b/misc/cgo/testcarchive/testdata/libgo8/a.go @@ -0,0 +1,36 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "C" + +import ( + "os" + "runtime" + "sync/atomic" +) + +var started int32 + +// Start a goroutine that loops forever. +func init() { + runtime.GOMAXPROCS(1) + go func() { + for { + atomic.StoreInt32(&started, 1) + } + }() +} + +//export GoFunction8 +func GoFunction8() { + for atomic.LoadInt32(&started) == 0 { + runtime.Gosched() + } + os.Exit(0) +} + +func main() { +} diff --git a/misc/cgo/testcarchive/testdata/main8.c b/misc/cgo/testcarchive/testdata/main8.c new file mode 100644 index 0000000000..95fb7a349e --- /dev/null +++ b/misc/cgo/testcarchive/testdata/main8.c @@ -0,0 +1,16 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test preemption. + +#include + +#include "libgo8.h" + +int main() { + GoFunction8(); + + // That should have exited the program. + abort(); +} diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go index 7c454437e4..dbcbfc67bc 100644 --- a/src/runtime/signal_unix.go +++ b/src/runtime/signal_unix.go @@ -167,8 +167,8 @@ func sigInstallGoHandler(sig uint32) bool { } // When built using c-archive or c-shared, only install signal - // handlers for synchronous signals and SIGPIPE. - if (isarchive || islibrary) && t.flags&_SigPanic == 0 && sig != _SIGPIPE { + // handlers for synchronous signals and SIGPIPE and sigPreempt. + if (isarchive || islibrary) && t.flags&_SigPanic == 0 && sig != _SIGPIPE && sig != sigPreempt { return false } -- GitLab From 519c0a2323700934cbec97b75df92917108548be Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 2 Nov 2021 12:50:05 -0700 Subject: [PATCH 1919/2500] cmd/compile/internal/types2: port nomono check from go/types Same logic as CL 357449 (including CL 360815), just ported to types2. Updates #48098. Change-Id: I4578f7329bb4ffc42410025bb6cb97e24697ebfd Reviewed-on: https://go-review.googlesource.com/c/go/+/360857 Trust: Matthew Dempsky Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/call.go | 2 + src/cmd/compile/internal/types2/check.go | 6 + src/cmd/compile/internal/types2/mono.go | 337 ++++++++++++++++++ src/cmd/compile/internal/types2/mono_test.go | 89 +++++ src/cmd/compile/internal/types2/signature.go | 1 + .../types2/testdata/fixedbugs/issue48974.go2 | 2 +- src/cmd/compile/internal/types2/typexpr.go | 2 + 7 files changed, 438 insertions(+), 1 deletion(-) create mode 100644 src/cmd/compile/internal/types2/mono.go create mode 100644 src/cmd/compile/internal/types2/mono_test.go diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 220ba940b3..49cae5a930 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -88,6 +88,8 @@ func (check *Checker) instantiateSignature(pos syntax.Pos, typ *Signature, targs pos = posList[i] } check.softErrorf(pos, err.Error()) + } else { + check.mono.recordInstance(check.pkg, pos, tparams, targs, posList) } return inst diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go index 6e8883e5de..ffc59f7011 100644 --- a/src/cmd/compile/internal/types2/check.go +++ b/src/cmd/compile/internal/types2/check.go @@ -126,6 +126,7 @@ type Checker struct { imports []*PkgName // list of imported packages dotImportMap map[dotImportKey]*PkgName // maps dot-imported objects to the package they were dot-imported through recvTParamMap map[*syntax.Name]*TypeParam // maps blank receiver type parameters to their type + mono monoGraph // graph for detecting non-monomorphizable instantiation loops firstErr error // first error encountered methods map[*TypeName][]*Func // maps package scope type names to associated non-blank (non-interface) methods @@ -317,6 +318,11 @@ func (check *Checker) checkFiles(files []*syntax.File) (err error) { print("== recordUntyped ==") check.recordUntyped() + if check.firstErr == nil { + // TODO(mdempsky): Ensure monomorph is safe when errors exist. + check.monomorph() + } + check.pkg.complete = true // no longer needed - release memory diff --git a/src/cmd/compile/internal/types2/mono.go b/src/cmd/compile/internal/types2/mono.go new file mode 100644 index 0000000000..39c4d4fbef --- /dev/null +++ b/src/cmd/compile/internal/types2/mono.go @@ -0,0 +1,337 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types2 + +import ( + "cmd/compile/internal/syntax" +) + +// This file implements a check to validate that a Go package doesn't +// have unbounded recursive instantiation, which is not compatible +// with compilers using static instantiation (such as +// monomorphization). +// +// It implements a sort of "type flow" analysis by detecting which +// type parameters are instantiated with other type parameters (or +// types derived thereof). A package cannot be statically instantiated +// if the graph has any cycles involving at least one derived type. +// +// Concretely, we construct a directed, weighted graph. Vertices are +// used to represent type parameters as well as some defined +// types. Edges are used to represent how types depend on each other: +// +// * Everywhere a type-parameterized function or type is instantiated, +// we add edges to each type parameter from the vertices (if any) +// representing each type parameter or defined type referenced by +// the type argument. If the type argument is just the referenced +// type itself, then the edge has weight 0, otherwise 1. +// +// * For every defined type declared within a type-parameterized +// function or method, we add an edge of weight 1 to the defined +// type from each ambient type parameter. +// +// For example, given: +// +// func f[A, B any]() { +// type T int +// f[T, map[A]B]() +// } +// +// we construct vertices representing types A, B, and T. Because of +// declaration "type T int", we construct edges T<-A and T<-B with +// weight 1; and because of instantiation "f[T, map[A]B]" we construct +// edges A<-T with weight 0, and B<-A and B<-B with weight 1. +// +// Finally, we look for any positive-weight cycles. Zero-weight cycles +// are allowed because static instantiation will reach a fixed point. + +type monoGraph struct { + vertices []monoVertex + edges []monoEdge + + // canon maps method receiver type parameters to their respective + // receiver type's type parameters. + canon map[*TypeParam]*TypeParam + + // nameIdx maps a defined type or (canonical) type parameter to its + // vertex index. + nameIdx map[*TypeName]int +} + +type monoVertex struct { + weight int // weight of heaviest known path to this vertex + pre int // previous edge (if any) in the above path + len int // length of the above path + + // obj is the defined type or type parameter represented by this + // vertex. + obj *TypeName +} + +type monoEdge struct { + dst, src int + weight int + + pos syntax.Pos + typ Type +} + +func (check *Checker) monomorph() { + // We detect unbounded instantiation cycles using a variant of + // Bellman-Ford's algorithm. Namely, instead of always running |V| + // iterations, we run until we either reach a fixed point or we've + // found a path of length |V|. This allows us to terminate earlier + // when there are no cycles, which should be the common case. + + again := true + for again { + again = false + + for i, edge := range check.mono.edges { + src := &check.mono.vertices[edge.src] + dst := &check.mono.vertices[edge.dst] + + // N.B., we're looking for the greatest weight paths, unlike + // typical Bellman-Ford. + w := src.weight + edge.weight + if w <= dst.weight { + continue + } + + dst.pre = i + dst.len = src.len + 1 + if dst.len == len(check.mono.vertices) { + check.reportInstanceLoop(edge.dst) + return + } + + dst.weight = w + again = true + } + } +} + +func (check *Checker) reportInstanceLoop(v int) { + var stack []int + seen := make([]bool, len(check.mono.vertices)) + + // We have a path that contains a cycle and ends at v, but v may + // only be reachable from the cycle, not on the cycle itself. We + // start by walking backwards along the path until we find a vertex + // that appears twice. + for !seen[v] { + stack = append(stack, v) + seen[v] = true + v = check.mono.edges[check.mono.vertices[v].pre].src + } + + // Trim any vertices we visited before visiting v the first + // time. Since v is the first vertex we found within the cycle, any + // vertices we visited earlier cannot be part of the cycle. + for stack[0] != v { + stack = stack[1:] + } + + // TODO(mdempsky): Pivot stack so we report the cycle from the top? + + var err error_ + obj0 := check.mono.vertices[v].obj + err.errorf(obj0, "instantiation cycle:") + + qf := RelativeTo(check.pkg) + for _, v := range stack { + edge := check.mono.edges[check.mono.vertices[v].pre] + obj := check.mono.vertices[edge.dst].obj + + switch obj.Type().(type) { + default: + panic("unexpected type") + case *Named: + err.errorf(edge.pos, "%s implicitly parameterized by %s", obj.Name(), TypeString(edge.typ, qf)) // secondary error, \t indented + case *TypeParam: + err.errorf(edge.pos, "%s instantiated as %s", obj.Name(), TypeString(edge.typ, qf)) // secondary error, \t indented + } + } + check.report(&err) +} + +// recordCanon records that tpar is the canonical type parameter +// corresponding to method type parameter mpar. +func (w *monoGraph) recordCanon(mpar, tpar *TypeParam) { + if w.canon == nil { + w.canon = make(map[*TypeParam]*TypeParam) + } + w.canon[mpar] = tpar +} + +// recordInstance records that the given type parameters were +// instantiated with the corresponding type arguments. +func (w *monoGraph) recordInstance(pkg *Package, pos syntax.Pos, tparams []*TypeParam, targs []Type, posList []syntax.Pos) { + for i, tpar := range tparams { + pos := pos + if i < len(posList) { + pos = posList[i] + } + w.assign(pkg, pos, tpar, targs[i]) + } +} + +// assign records that tpar was instantiated as targ at pos. +func (w *monoGraph) assign(pkg *Package, pos syntax.Pos, tpar *TypeParam, targ Type) { + // Go generics do not have an analog to C++`s template-templates, + // where a template parameter can itself be an instantiable + // template. So any instantiation cycles must occur within a single + // package. Accordingly, we can ignore instantiations of imported + // type parameters. + // + // TODO(mdempsky): Push this check up into recordInstance? All type + // parameters in a list will appear in the same package. + if tpar.Obj().Pkg() != pkg { + return + } + + // flow adds an edge from vertex src representing that typ flows to tpar. + flow := func(src int, typ Type) { + weight := 1 + if typ == targ { + weight = 0 + } + + w.addEdge(w.typeParamVertex(tpar), src, weight, pos, targ) + } + + // Recursively walk the type argument to find any defined types or + // type parameters. + var do func(typ Type) + do = func(typ Type) { + switch typ := typ.(type) { + default: + panic("unexpected type") + + case *TypeParam: + assert(typ.Obj().Pkg() == pkg) + flow(w.typeParamVertex(typ), typ) + + case *Named: + if src := w.localNamedVertex(pkg, typ.Origin()); src >= 0 { + flow(src, typ) + } + + targs := typ.TypeArgs() + for i := 0; i < targs.Len(); i++ { + do(targs.At(i)) + } + + case *Array: + do(typ.Elem()) + case *Basic: + // ok + case *Chan: + do(typ.Elem()) + case *Map: + do(typ.Key()) + do(typ.Elem()) + case *Pointer: + do(typ.Elem()) + case *Slice: + do(typ.Elem()) + + case *Interface: + for i := 0; i < typ.NumMethods(); i++ { + do(typ.Method(i).Type()) + } + case *Signature: + tuple := func(tup *Tuple) { + for i := 0; i < tup.Len(); i++ { + do(tup.At(i).Type()) + } + } + tuple(typ.Params()) + tuple(typ.Results()) + case *Struct: + for i := 0; i < typ.NumFields(); i++ { + do(typ.Field(i).Type()) + } + } + } + do(targ) +} + +// localNamedVertex returns the index of the vertex representing +// named, or -1 if named doesn't need representation. +func (w *monoGraph) localNamedVertex(pkg *Package, named *Named) int { + obj := named.Obj() + if obj.Pkg() != pkg { + return -1 // imported type + } + + root := pkg.Scope() + if obj.Parent() == root { + return -1 // package scope, no ambient type parameters + } + + if idx, ok := w.nameIdx[obj]; ok { + return idx + } + + idx := -1 + + // Walk the type definition's scope to find any ambient type + // parameters that it's implicitly parameterized by. + for scope := obj.Parent(); scope != root; scope = scope.Parent() { + for _, elem := range scope.elems { + if elem, ok := elem.(*TypeName); ok && !elem.IsAlias() && elem.Pos().Cmp(obj.Pos()) < 0 { + if tpar, ok := elem.Type().(*TypeParam); ok { + if idx < 0 { + idx = len(w.vertices) + w.vertices = append(w.vertices, monoVertex{obj: obj}) + } + + w.addEdge(idx, w.typeParamVertex(tpar), 1, obj.Pos(), tpar) + } + } + } + } + + if w.nameIdx == nil { + w.nameIdx = make(map[*TypeName]int) + } + w.nameIdx[obj] = idx + return idx +} + +// typeParamVertex returns the index of the vertex representing tpar. +func (w *monoGraph) typeParamVertex(tpar *TypeParam) int { + if x, ok := w.canon[tpar]; ok { + tpar = x + } + + obj := tpar.Obj() + + if idx, ok := w.nameIdx[obj]; ok { + return idx + } + + if w.nameIdx == nil { + w.nameIdx = make(map[*TypeName]int) + } + + idx := len(w.vertices) + w.vertices = append(w.vertices, monoVertex{obj: obj}) + w.nameIdx[obj] = idx + return idx +} + +func (w *monoGraph) addEdge(dst, src, weight int, pos syntax.Pos, typ Type) { + // TODO(mdempsky): Deduplicate redundant edges? + w.edges = append(w.edges, monoEdge{ + dst: dst, + src: src, + weight: weight, + + pos: pos, + typ: typ, + }) +} diff --git a/src/cmd/compile/internal/types2/mono_test.go b/src/cmd/compile/internal/types2/mono_test.go new file mode 100644 index 0000000000..19d0e95637 --- /dev/null +++ b/src/cmd/compile/internal/types2/mono_test.go @@ -0,0 +1,89 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types2_test + +import ( + "bytes" + "cmd/compile/internal/syntax" + "cmd/compile/internal/types2" + "errors" + "fmt" + "strings" + "testing" +) + +func checkMono(t *testing.T, body string) error { + src := "package x; import `unsafe`; var _ unsafe.Pointer;\n" + body + file, err := syntax.Parse(syntax.NewFileBase("x.go"), strings.NewReader(src), nil, nil, syntax.AllowGenerics) + if err != nil { + t.Fatal(err) + } + files := []*syntax.File{file} + + var buf bytes.Buffer + conf := types2.Config{ + Error: func(err error) { fmt.Fprintln(&buf, err) }, + Importer: defaultImporter(), + } + conf.Check("x", files, nil) + if buf.Len() == 0 { + return nil + } + return errors.New(strings.TrimRight(buf.String(), "\n")) +} + +func TestMonoGood(t *testing.T) { + for i, good := range goods { + if err := checkMono(t, good); err != nil { + t.Errorf("%d: unexpected failure: %v", i, err) + } + } +} + +func TestMonoBad(t *testing.T) { + for i, bad := range bads { + if err := checkMono(t, bad); err == nil { + t.Errorf("%d: unexpected success", i) + } else { + t.Log(err) + } + } +} + +var goods = []string{ + "func F[T any](x T) { F(x) }", + "func F[T, U, V any]() { F[U, V, T](); F[V, T, U]() }", + "type Ring[A, B, C any] struct { L *Ring[B, C, A]; R *Ring[C, A, B] }", + "func F[T any]() { type U[T any] [unsafe.Sizeof(F[*T])]byte }", + "func F[T any]() { type U[T any] [unsafe.Sizeof(F[*T])]byte; var _ U[int] }", + "type U[T any] [unsafe.Sizeof(F[*T])]byte; func F[T any]() { var _ U[U[int]] }", + "func F[T any]() { type A = int; F[A]() }", +} + +// TODO(mdempsky): Validate specific error messages and positioning. + +var bads = []string{ + "func F[T any](x T) { F(&x) }", + "func F[T any]() { F[*T]() }", + "func F[T any]() { F[[]T]() }", + "func F[T any]() { F[[1]T]() }", + "func F[T any]() { F[chan T]() }", + "func F[T any]() { F[map[*T]int]() }", + "func F[T any]() { F[map[error]T]() }", + "func F[T any]() { F[func(T)]() }", + "func F[T any]() { F[func() T]() }", + "func F[T any]() { F[struct{ t T }]() }", + "func F[T any]() { F[interface{ t() T }]() }", + "type U[_ any] int; func F[T any]() { F[U[T]]() }", + "func F[T any]() { type U int; F[U]() }", + "func F[T any]() { type U int; F[*U]() }", + "type U[T any] int; func (U[T]) m() { var _ U[*T] }", + "type U[T any] int; func (*U[T]) m() { var _ U[*T] }", + "type U[T1 any] [unsafe.Sizeof(F[*T1])]byte; func F[T2 any]() { var _ U[T2] }", + "func F[A, B, C, D, E any]() { F[B, C, D, E, *A]() }", + "type U[_ any] int; const X = unsafe.Sizeof(func() { type A[T any] U[A[*T]] })", + "func F[T any]() { type A = *T; F[A]() }", + "type A[T any] struct { _ A[*T] }", +} diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index 604d0c9dbd..4541435587 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -148,6 +148,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] list := make([]Type, sig.RecvTypeParams().Len()) for i, t := range sig.RecvTypeParams().list() { list[i] = t + check.mono.recordCanon(t, recvTParams[i]) } smap := makeSubstMap(recvTParams, list) for i, tpar := range sig.RecvTypeParams().list() { diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48974.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48974.go2 index ca4b6d9321..d8ff7c8cf4 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48974.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48974.go2 @@ -8,7 +8,7 @@ type Fooer interface { Foo() } -type Fooable[F Fooer] struct { +type Fooable[F /* ERROR instantiation cycle */ Fooer] struct { ptr F } diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index d8183bfd9c..95893fd1e1 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -481,6 +481,8 @@ func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def pos = posList[i] } check.softErrorf(pos, err.Error()) + } else { + check.mono.recordInstance(check.pkg, x.Pos(), inst.tparams.list(), inst.targs.list(), posList) } } -- GitLab From 5b213178e72b6031c9ec790bf9fe784c66b397e3 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Sun, 26 Sep 2021 19:21:29 +1000 Subject: [PATCH 1920/2500] cmd/asm,cmd/compile,runtime: stop using X3 (aka GP) on riscv64 The X3 (aka GP) register will potentially be loaded with the __global_pointer$ symbol during program start up (usually by the dynamic linker). As such, non-Go code may depend on the contents of GP and calculate offsets based on it, including code called via cgo and signal handlers installed by non-Go code. As such, stop using the X3 register so that there are fewer issues interacting between Go and non-Go code. While here remove the X4 (TP) name from the assembler such that any references must use the 'TP' name. This should reduce the likelihood of accidental use (like we do for the 'g' register). The same applies for X3 (GP) when the -shared flag is given. Updates #47100 Change-Id: I72e82b5ca3f80c46a781781345ca0432a4111b74 Reviewed-on: https://go-review.googlesource.com/c/go/+/351859 Trust: Joel Sing Run-TryBot: Joel Sing Reviewed-by: Cherry Mui TryBot-Result: Go Bot --- src/cmd/asm/internal/arch/arch.go | 14 +- src/cmd/asm/internal/asm/operand_test.go | 2 +- src/cmd/asm/main.go | 6 +- .../compile/internal/ssa/gen/RISCV64Ops.go | 5 +- src/cmd/compile/internal/ssa/opGen.go | 500 +++++++++--------- src/runtime/asm_riscv64.s | 97 ++-- src/runtime/cgo/asm_riscv64.s | 60 +-- src/runtime/cgo/gcc_riscv64.S | 108 ++-- src/runtime/mkpreempt.go | 8 +- src/runtime/preempt_riscv64.s | 238 +++++---- src/runtime/tls_riscv64.s | 4 +- 11 files changed, 519 insertions(+), 523 deletions(-) diff --git a/src/cmd/asm/internal/arch/arch.go b/src/cmd/asm/internal/arch/arch.go index 8c71b79965..4d374cb828 100644 --- a/src/cmd/asm/internal/arch/arch.go +++ b/src/cmd/asm/internal/arch/arch.go @@ -50,7 +50,7 @@ func nilRegisterNumber(name string, n int16) (int16, bool) { // Set configures the architecture specified by GOARCH and returns its representation. // It returns nil if GOARCH is not recognized. -func Set(GOARCH string) *Arch { +func Set(GOARCH string, shared bool) *Arch { switch GOARCH { case "386": return archX86(&x86.Link386) @@ -73,7 +73,7 @@ func Set(GOARCH string) *Arch { case "ppc64le": return archPPC64(&ppc64.Linkppc64le) case "riscv64": - return archRISCV64() + return archRISCV64(shared) case "s390x": return archS390x() case "wasm": @@ -541,12 +541,18 @@ func archMips64(linkArch *obj.LinkArch) *Arch { } } -func archRISCV64() *Arch { +func archRISCV64(shared bool) *Arch { register := make(map[string]int16) // Standard register names. for i := riscv.REG_X0; i <= riscv.REG_X31; i++ { - if i == riscv.REG_G { + // Disallow X3 in shared mode, as this will likely be used as the + // GP register, which could result in problems in non-Go code, + // including signal handlers. + if shared && i == riscv.REG_GP { + continue + } + if i == riscv.REG_TP || i == riscv.REG_G { continue } name := fmt.Sprintf("X%d", i-riscv.REG_X0) diff --git a/src/cmd/asm/internal/asm/operand_test.go b/src/cmd/asm/internal/asm/operand_test.go index 8ef02b1a0e..c1295a0c42 100644 --- a/src/cmd/asm/internal/asm/operand_test.go +++ b/src/cmd/asm/internal/asm/operand_test.go @@ -19,7 +19,7 @@ import ( func setArch(goarch string) (*arch.Arch, *obj.Link) { buildcfg.GOOS = "linux" // obj can handle this OS for all architectures. buildcfg.GOARCH = goarch - architecture := arch.Set(goarch) + architecture := arch.Set(goarch, false) if architecture == nil { panic("asm: unrecognized architecture " + goarch) } diff --git a/src/cmd/asm/main.go b/src/cmd/asm/main.go index 043bc696e5..3e32aa3d7d 100644 --- a/src/cmd/asm/main.go +++ b/src/cmd/asm/main.go @@ -29,13 +29,13 @@ func main() { buildcfg.Check() GOARCH := buildcfg.GOARCH - architecture := arch.Set(GOARCH) + flags.Parse() + + architecture := arch.Set(GOARCH, *flags.Shared || *flags.Dynlink) if architecture == nil { log.Fatalf("unrecognized architecture %s", GOARCH) } - flags.Parse() - ctxt := obj.Linknew(architecture.LinkArch) ctxt.Debugasm = flags.PrintOut ctxt.Debugvlog = flags.DebugV diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go index 880fad1c49..076919773b 100644 --- a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go @@ -29,6 +29,7 @@ const ( riscv64REG_CTXT = 20 riscv64REG_LR = 1 riscv64REG_SP = 2 + riscv64REG_GP = 3 riscv64REG_TP = 4 riscv64REG_TMP = 31 riscv64REG_ZERO = 0 @@ -80,8 +81,8 @@ func init() { // Add general purpose registers to gpMask. switch r { - // ZERO, TP and TMP are not in any gp mask. - case riscv64REG_ZERO, riscv64REG_TP, riscv64REG_TMP: + // ZERO, GP, TP and TMP are not in any gp mask. + case riscv64REG_ZERO, riscv64REG_GP, riscv64REG_TP, riscv64REG_TMP: case riscv64REG_G: gpgMask |= mask gpspsbgMask |= mask diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index ed10f35fb9..2038575b0c 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -27949,11 +27949,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AADD, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27964,10 +27964,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AADDI, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27978,10 +27978,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AADDIW, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27991,10 +27991,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ANEG, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28004,10 +28004,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ANEGW, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28017,11 +28017,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASUB, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28031,11 +28031,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASUBW, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28046,11 +28046,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMUL, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28061,11 +28061,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMULW, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28076,11 +28076,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMULH, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28091,11 +28091,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMULHU, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28105,12 +28105,12 @@ var opcodeTable = [...]opInfo{ resultNotInArgs: true, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28120,12 +28120,12 @@ var opcodeTable = [...]opInfo{ resultNotInArgs: true, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28135,11 +28135,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ADIV, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28149,11 +28149,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ADIVU, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28163,11 +28163,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ADIVW, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28177,11 +28177,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ADIVUW, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28191,11 +28191,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AREM, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28205,11 +28205,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AREMU, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28219,11 +28219,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AREMW, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28233,11 +28233,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AREMUW, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28250,10 +28250,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOV, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28265,7 +28265,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOV, reg: regInfo{ outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28278,10 +28278,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVB, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28294,10 +28294,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVH, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28310,10 +28310,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVW, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28326,10 +28326,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOV, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28342,10 +28342,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVBU, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28358,10 +28358,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVHU, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28374,10 +28374,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVWU, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28390,8 +28390,8 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVB, reg: regInfo{ inputs: []inputInfo{ - {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {1, 1006632946}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -28404,8 +28404,8 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVH, reg: regInfo{ inputs: []inputInfo{ - {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {1, 1006632946}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -28418,8 +28418,8 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVW, reg: regInfo{ inputs: []inputInfo{ - {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {1, 1006632946}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -28432,8 +28432,8 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOV, reg: regInfo{ inputs: []inputInfo{ - {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {1, 1006632946}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -28446,7 +28446,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVB, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -28459,7 +28459,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVH, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -28472,7 +28472,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVW, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -28485,7 +28485,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOV, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -28495,10 +28495,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVB, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28508,10 +28508,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVH, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28521,10 +28521,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVW, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28534,10 +28534,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOV, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28547,10 +28547,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVBU, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28560,10 +28560,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVHU, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28573,10 +28573,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVWU, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28586,10 +28586,10 @@ var opcodeTable = [...]opInfo{ resultInArg0: true, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28599,11 +28599,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASLL, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28613,11 +28613,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASRA, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28627,11 +28627,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASRL, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28642,10 +28642,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASLLI, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28656,10 +28656,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASRAI, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28670,10 +28670,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASRLI, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28684,11 +28684,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AXOR, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28699,10 +28699,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AXORI, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28713,11 +28713,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AOR, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28728,10 +28728,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AORI, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28742,11 +28742,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AAND, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28757,10 +28757,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AANDI, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28770,10 +28770,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ANOT, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28783,10 +28783,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASEQZ, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28796,10 +28796,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASNEZ, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28809,11 +28809,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASLT, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28824,10 +28824,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASLTI, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28837,11 +28837,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASLTU, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28852,10 +28852,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASLTIU, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28865,10 +28865,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOV, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28878,7 +28878,7 @@ var opcodeTable = [...]opInfo{ argLen: 1, call: true, reg: regInfo{ - clobbers: 9223372035781033972, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + clobbers: 9223372035781033968, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, }, { @@ -28888,7 +28888,7 @@ var opcodeTable = [...]opInfo{ call: true, tailCall: true, reg: regInfo{ - clobbers: 9223372035781033972, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + clobbers: 9223372035781033968, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, }, { @@ -28899,9 +28899,9 @@ var opcodeTable = [...]opInfo{ reg: regInfo{ inputs: []inputInfo{ {1, 524288}, // X20 - {0, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632946}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, - clobbers: 9223372035781033972, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + clobbers: 9223372035781033968, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, }, { @@ -28911,9 +28911,9 @@ var opcodeTable = [...]opInfo{ call: true, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, - clobbers: 9223372035781033972, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + clobbers: 9223372035781033968, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, }, { @@ -28950,7 +28950,7 @@ var opcodeTable = [...]opInfo{ reg: regInfo{ inputs: []inputInfo{ {0, 16}, // X5 - {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, clobbers: 16, // X5 }, @@ -28965,7 +28965,7 @@ var opcodeTable = [...]opInfo{ inputs: []inputInfo{ {0, 16}, // X5 {1, 32}, // X6 - {2, 1006632884}, // X3 X5 X6 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {2, 1006632880}, // X5 X6 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, clobbers: 112, // X5 X6 X7 }, @@ -28976,10 +28976,10 @@ var opcodeTable = [...]opInfo{ faultOnNilArg0: true, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28989,10 +28989,10 @@ var opcodeTable = [...]opInfo{ faultOnNilArg0: true, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29002,10 +29002,10 @@ var opcodeTable = [...]opInfo{ faultOnNilArg0: true, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29016,8 +29016,8 @@ var opcodeTable = [...]opInfo{ hasSideEffects: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {1, 1006632946}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -29028,8 +29028,8 @@ var opcodeTable = [...]opInfo{ hasSideEffects: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {1, 1006632946}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -29040,8 +29040,8 @@ var opcodeTable = [...]opInfo{ hasSideEffects: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {1, 1006632946}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -29053,11 +29053,11 @@ var opcodeTable = [...]opInfo{ hasSideEffects: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB + {1, 1073741808}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, 9223372037928517618}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29069,11 +29069,11 @@ var opcodeTable = [...]opInfo{ hasSideEffects: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB + {1, 1073741808}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, 9223372037928517618}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29086,11 +29086,11 @@ var opcodeTable = [...]opInfo{ unsafePoint: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB + {1, 1073741808}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, 9223372037928517618}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29103,11 +29103,11 @@ var opcodeTable = [...]opInfo{ unsafePoint: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB + {1, 1073741808}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, 9223372037928517618}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29120,12 +29120,12 @@ var opcodeTable = [...]opInfo{ unsafePoint: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 - {2, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB + {1, 1073741808}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {2, 1073741808}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, 9223372037928517618}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29138,12 +29138,12 @@ var opcodeTable = [...]opInfo{ unsafePoint: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 - {2, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB + {1, 1073741808}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {2, 1073741808}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, 9223372037928517618}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29155,8 +29155,8 @@ var opcodeTable = [...]opInfo{ asm: riscv.AAMOANDW, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB + {1, 1073741808}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, 9223372037928517618}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB }, }, }, @@ -29168,8 +29168,8 @@ var opcodeTable = [...]opInfo{ asm: riscv.AAMOORW, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB + {1, 1073741808}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, 9223372037928517618}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB }, }, }, @@ -29180,7 +29180,7 @@ var opcodeTable = [...]opInfo{ faultOnNilArg0: true, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632946}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29199,7 +29199,7 @@ var opcodeTable = [...]opInfo{ rematerializeable: true, reg: regInfo{ outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29209,7 +29209,7 @@ var opcodeTable = [...]opInfo{ rematerializeable: true, reg: regInfo{ outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29353,7 +29353,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AFMVSX, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 @@ -29366,7 +29366,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AFCVTSW, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 @@ -29379,7 +29379,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AFCVTSL, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 @@ -29395,7 +29395,7 @@ var opcodeTable = [...]opInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29408,7 +29408,7 @@ var opcodeTable = [...]opInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29421,7 +29421,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVF, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 @@ -29437,7 +29437,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVF, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, }, @@ -29453,7 +29453,7 @@ var opcodeTable = [...]opInfo{ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29468,7 +29468,7 @@ var opcodeTable = [...]opInfo{ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29482,7 +29482,7 @@ var opcodeTable = [...]opInfo{ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29496,7 +29496,7 @@ var opcodeTable = [...]opInfo{ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29681,7 +29681,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AFMVDX, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 @@ -29694,7 +29694,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AFCVTDW, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 @@ -29707,7 +29707,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AFCVTDL, reg: regInfo{ inputs: []inputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 @@ -29723,7 +29723,7 @@ var opcodeTable = [...]opInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29736,7 +29736,7 @@ var opcodeTable = [...]opInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29775,7 +29775,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVD, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 @@ -29791,7 +29791,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVD, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB + {0, 9223372037861408754}, // SP X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, }, @@ -29807,7 +29807,7 @@ var opcodeTable = [...]opInfo{ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29822,7 +29822,7 @@ var opcodeTable = [...]opInfo{ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29836,7 +29836,7 @@ var opcodeTable = [...]opInfo{ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -29850,7 +29850,7 @@ var opcodeTable = [...]opInfo{ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -37293,34 +37293,34 @@ var linkRegPPC64 = int8(-1) var registersRISCV64 = [...]Register{ {0, riscv.REG_X0, -1, "X0"}, {1, riscv.REGSP, -1, "SP"}, - {2, riscv.REG_X3, 0, "X3"}, + {2, riscv.REG_X3, -1, "X3"}, {3, riscv.REG_X4, -1, "X4"}, - {4, riscv.REG_X5, 1, "X5"}, - {5, riscv.REG_X6, 2, "X6"}, - {6, riscv.REG_X7, 3, "X7"}, - {7, riscv.REG_X8, 4, "X8"}, - {8, riscv.REG_X9, 5, "X9"}, - {9, riscv.REG_X10, 6, "X10"}, - {10, riscv.REG_X11, 7, "X11"}, - {11, riscv.REG_X12, 8, "X12"}, - {12, riscv.REG_X13, 9, "X13"}, - {13, riscv.REG_X14, 10, "X14"}, - {14, riscv.REG_X15, 11, "X15"}, - {15, riscv.REG_X16, 12, "X16"}, - {16, riscv.REG_X17, 13, "X17"}, - {17, riscv.REG_X18, 14, "X18"}, - {18, riscv.REG_X19, 15, "X19"}, - {19, riscv.REG_X20, 16, "X20"}, - {20, riscv.REG_X21, 17, "X21"}, - {21, riscv.REG_X22, 18, "X22"}, - {22, riscv.REG_X23, 19, "X23"}, - {23, riscv.REG_X24, 20, "X24"}, - {24, riscv.REG_X25, 21, "X25"}, - {25, riscv.REG_X26, 22, "X26"}, + {4, riscv.REG_X5, 0, "X5"}, + {5, riscv.REG_X6, 1, "X6"}, + {6, riscv.REG_X7, 2, "X7"}, + {7, riscv.REG_X8, 3, "X8"}, + {8, riscv.REG_X9, 4, "X9"}, + {9, riscv.REG_X10, 5, "X10"}, + {10, riscv.REG_X11, 6, "X11"}, + {11, riscv.REG_X12, 7, "X12"}, + {12, riscv.REG_X13, 8, "X13"}, + {13, riscv.REG_X14, 9, "X14"}, + {14, riscv.REG_X15, 10, "X15"}, + {15, riscv.REG_X16, 11, "X16"}, + {16, riscv.REG_X17, 12, "X17"}, + {17, riscv.REG_X18, 13, "X18"}, + {18, riscv.REG_X19, 14, "X19"}, + {19, riscv.REG_X20, 15, "X20"}, + {20, riscv.REG_X21, 16, "X21"}, + {21, riscv.REG_X22, 17, "X22"}, + {22, riscv.REG_X23, 18, "X23"}, + {23, riscv.REG_X24, 19, "X24"}, + {24, riscv.REG_X25, 20, "X25"}, + {25, riscv.REG_X26, 21, "X26"}, {26, riscv.REGG, -1, "g"}, - {27, riscv.REG_X28, 23, "X28"}, - {28, riscv.REG_X29, 24, "X29"}, - {29, riscv.REG_X30, 25, "X30"}, + {27, riscv.REG_X28, 22, "X28"}, + {28, riscv.REG_X29, 23, "X29"}, + {29, riscv.REG_X30, 24, "X30"}, {30, riscv.REG_X31, -1, "X31"}, {31, riscv.REG_F0, -1, "F0"}, {32, riscv.REG_F1, -1, "F1"}, @@ -37358,7 +37358,7 @@ var registersRISCV64 = [...]Register{ } var paramIntRegRISCV64 = []int8(nil) var paramFloatRegRISCV64 = []int8(nil) -var gpRegMaskRISCV64 = regMask(1006632948) +var gpRegMaskRISCV64 = regMask(1006632944) var fpRegMaskRISCV64 = regMask(9223372034707292160) var specialRegMaskRISCV64 = regMask(0) var framepointerRegRISCV64 = int8(-1) diff --git a/src/runtime/asm_riscv64.s b/src/runtime/asm_riscv64.s index 531b46927c..0e813189d4 100644 --- a/src/runtime/asm_riscv64.s +++ b/src/runtime/asm_riscv64.s @@ -631,10 +631,10 @@ TEXT ·checkASM(SB),NOSPLIT,$0-1 // The act of CALLing gcWriteBarrier will clobber RA (LR). // It does not clobber any other general-purpose registers, // but may clobber others (e.g., floating point registers). -TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$216 +TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$208 // Save the registers clobbered by the fast path. - MOV A0, 25*8(X2) - MOV A1, 26*8(X2) + MOV A0, 24*8(X2) + MOV A1, 25*8(X2) MOV g_m(g), A0 MOV m_p(A0), A0 MOV (p_wbBuf+wbBuf_next)(A0), A1 @@ -650,8 +650,8 @@ TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$216 // Is the buffer full? BEQ A1, T6, flush ret: - MOV 25*8(X2), A0 - MOV 26*8(X2), A1 + MOV 24*8(X2), A0 + MOV 25*8(X2), A1 // Do the write. MOV T1, (T0) RET @@ -664,34 +664,34 @@ flush: // X0 is zero register // X1 is LR, saved by prologue // X2 is SP - MOV X3, 3*8(X2) + // X3 is GP // X4 is TP // X5 is first arg to wbBufFlush (T0) // X6 is second arg to wbBufFlush (T1) - MOV X7, 4*8(X2) - MOV X8, 5*8(X2) - MOV X9, 6*8(X2) + MOV X7, 3*8(X2) + MOV X8, 4*8(X2) + MOV X9, 5*8(X2) // X10 already saved (A0) // X11 already saved (A1) - MOV X12, 7*8(X2) - MOV X13, 8*8(X2) - MOV X14, 9*8(X2) - MOV X15, 10*8(X2) - MOV X16, 11*8(X2) - MOV X17, 12*8(X2) - MOV X18, 13*8(X2) - MOV X19, 14*8(X2) - MOV X20, 15*8(X2) - MOV X21, 16*8(X2) - MOV X22, 17*8(X2) - MOV X23, 18*8(X2) - MOV X24, 19*8(X2) - MOV X25, 20*8(X2) - MOV X26, 21*8(X2) + MOV X12, 6*8(X2) + MOV X13, 7*8(X2) + MOV X14, 8*8(X2) + MOV X15, 9*8(X2) + MOV X16, 10*8(X2) + MOV X17, 11*8(X2) + MOV X18, 12*8(X2) + MOV X19, 13*8(X2) + MOV X20, 14*8(X2) + MOV X21, 15*8(X2) + MOV X22, 16*8(X2) + MOV X23, 17*8(X2) + MOV X24, 18*8(X2) + MOV X25, 19*8(X2) + MOV X26, 20*8(X2) // X27 is g. - MOV X28, 22*8(X2) - MOV X29, 23*8(X2) - MOV X30, 24*8(X2) + MOV X28, 21*8(X2) + MOV X29, 22*8(X2) + MOV X30, 23*8(X2) // X31 is tmp register. // This takes arguments T0 and T1. @@ -699,28 +699,27 @@ flush: MOV 1*8(X2), T0 MOV 2*8(X2), T1 - MOV 3*8(X2), X3 - MOV 4*8(X2), X7 - MOV 5*8(X2), X8 - MOV 6*8(X2), X9 - MOV 7*8(X2), X12 - MOV 8*8(X2), X13 - MOV 9*8(X2), X14 - MOV 10*8(X2), X15 - MOV 11*8(X2), X16 - MOV 12*8(X2), X17 - MOV 13*8(X2), X18 - MOV 14*8(X2), X19 - MOV 15*8(X2), X20 - MOV 16*8(X2), X21 - MOV 17*8(X2), X22 - MOV 18*8(X2), X23 - MOV 19*8(X2), X24 - MOV 20*8(X2), X25 - MOV 21*8(X2), X26 - MOV 22*8(X2), X28 - MOV 23*8(X2), X29 - MOV 24*8(X2), X30 + MOV 3*8(X2), X7 + MOV 4*8(X2), X8 + MOV 5*8(X2), X9 + MOV 6*8(X2), X12 + MOV 7*8(X2), X13 + MOV 8*8(X2), X14 + MOV 9*8(X2), X15 + MOV 10*8(X2), X16 + MOV 11*8(X2), X17 + MOV 12*8(X2), X18 + MOV 13*8(X2), X19 + MOV 14*8(X2), X20 + MOV 15*8(X2), X21 + MOV 16*8(X2), X22 + MOV 17*8(X2), X23 + MOV 18*8(X2), X24 + MOV 19*8(X2), X25 + MOV 20*8(X2), X26 + MOV 21*8(X2), X28 + MOV 22*8(X2), X29 + MOV 23*8(X2), X30 JMP ret diff --git a/src/runtime/cgo/asm_riscv64.s b/src/runtime/cgo/asm_riscv64.s index fcd1d36ca8..45151bf02b 100644 --- a/src/runtime/cgo/asm_riscv64.s +++ b/src/runtime/cgo/asm_riscv64.s @@ -14,7 +14,7 @@ TEXT crosscall2(SB),NOSPLIT|NOFRAME,$0 * registers. Note that at procedure entry the first argument is at * 8(X2). */ - ADD $(-8*31), X2 + ADD $(-8*29), X2 MOV X10, (8*1)(X2) // fn unsafe.Pointer MOV X11, (8*2)(X2) // a unsafe.Pointer MOV X13, (8*3)(X2) // ctxt uintptr @@ -30,21 +30,19 @@ TEXT crosscall2(SB),NOSPLIT|NOFRAME,$0 MOV X25, (8*13)(X2) MOV X26, (8*14)(X2) MOV g, (8*15)(X2) - MOV X3, (8*16)(X2) - MOV X4, (8*17)(X2) - MOV X1, (8*18)(X2) - MOVD F8, (8*19)(X2) - MOVD F9, (8*20)(X2) - MOVD F18, (8*21)(X2) - MOVD F19, (8*22)(X2) - MOVD F20, (8*23)(X2) - MOVD F21, (8*24)(X2) - MOVD F22, (8*25)(X2) - MOVD F23, (8*26)(X2) - MOVD F24, (8*27)(X2) - MOVD F25, (8*28)(X2) - MOVD F26, (8*29)(X2) - MOVD F27, (8*30)(X2) + MOV X1, (8*16)(X2) + MOVD F8, (8*17)(X2) + MOVD F9, (8*18)(X2) + MOVD F18, (8*19)(X2) + MOVD F19, (8*20)(X2) + MOVD F20, (8*21)(X2) + MOVD F21, (8*22)(X2) + MOVD F22, (8*23)(X2) + MOVD F23, (8*24)(X2) + MOVD F24, (8*25)(X2) + MOVD F25, (8*26)(X2) + MOVD F26, (8*27)(X2) + MOVD F27, (8*28)(X2) // Initialize Go ABI environment CALL runtime·load_g(SB) @@ -62,21 +60,19 @@ TEXT crosscall2(SB),NOSPLIT|NOFRAME,$0 MOV (8*13)(X2), X25 MOV (8*14)(X2), X26 MOV (8*15)(X2), g - MOV (8*16)(X2), X3 - MOV (8*17)(X2), X4 - MOV (8*18)(X2), X1 - MOVD (8*19)(X2), F8 - MOVD (8*20)(X2), F9 - MOVD (8*21)(X2), F18 - MOVD (8*22)(X2), F19 - MOVD (8*23)(X2), F20 - MOVD (8*24)(X2), F21 - MOVD (8*25)(X2), F22 - MOVD (8*26)(X2), F23 - MOVD (8*27)(X2), F24 - MOVD (8*28)(X2), F25 - MOVD (8*29)(X2), F26 - MOVD (8*30)(X2), F27 - ADD $(8*31), X2 + MOV (8*16)(X2), X1 + MOVD (8*17)(X2), F8 + MOVD (8*18)(X2), F9 + MOVD (8*19)(X2), F18 + MOVD (8*20)(X2), F19 + MOVD (8*21)(X2), F20 + MOVD (8*22)(X2), F21 + MOVD (8*23)(X2), F22 + MOVD (8*24)(X2), F23 + MOVD (8*25)(X2), F24 + MOVD (8*26)(X2), F25 + MOVD (8*27)(X2), F26 + MOVD (8*28)(X2), F27 + ADD $(8*29), X2 RET diff --git a/src/runtime/cgo/gcc_riscv64.S b/src/runtime/cgo/gcc_riscv64.S index fdc77496d9..f429dc64ee 100644 --- a/src/runtime/cgo/gcc_riscv64.S +++ b/src/runtime/cgo/gcc_riscv64.S @@ -8,38 +8,36 @@ * Calling into the gc tool chain, where all registers are caller save. * Called from standard RISCV ELF psABI, where x8-x9, x18-x27, f8-f9 and * f18-f27 are callee-save, so they must be saved explicitly, along with - * x1 (LR), x3 (GP) and x4 (TP). + * x1 (LR). */ .globl crosscall1 crosscall1: - sd x1, -216(sp) - addi sp, sp, -216 - sd x3, 8(sp) - sd x4, 16(sp) - sd x8, 24(sp) - sd x9, 32(sp) - sd x18, 40(sp) - sd x19, 48(sp) - sd x20, 56(sp) - sd x21, 64(sp) - sd x22, 72(sp) - sd x23, 80(sp) - sd x24, 88(sp) - sd x25, 96(sp) - sd x26, 104(sp) - sd x27, 112(sp) - fsd f8, 120(sp) - fsd f9, 128(sp) - fsd f18, 136(sp) - fsd f19, 144(sp) - fsd f20, 152(sp) - fsd f21, 160(sp) - fsd f22, 168(sp) - fsd f23, 176(sp) - fsd f24, 184(sp) - fsd f25, 192(sp) - fsd f26, 200(sp) - fsd f27, 208(sp) + sd x1, -200(sp) + addi sp, sp, -200 + sd x8, 8(sp) + sd x9, 16(sp) + sd x18, 24(sp) + sd x19, 32(sp) + sd x20, 40(sp) + sd x21, 48(sp) + sd x22, 56(sp) + sd x23, 64(sp) + sd x24, 72(sp) + sd x25, 80(sp) + sd x26, 88(sp) + sd x27, 96(sp) + fsd f8, 104(sp) + fsd f9, 112(sp) + fsd f18, 120(sp) + fsd f19, 128(sp) + fsd f20, 136(sp) + fsd f21, 144(sp) + fsd f22, 152(sp) + fsd f23, 160(sp) + fsd f24, 168(sp) + fsd f25, 176(sp) + fsd f26, 184(sp) + fsd f27, 192(sp) // a0 = *fn, a1 = *setg_gcc, a2 = *g mv s1, a0 @@ -49,33 +47,31 @@ crosscall1: jalr ra, s1 // call fn ld x1, 0(sp) - ld x3, 8(sp) - ld x4, 16(sp) - ld x8, 24(sp) - ld x9, 32(sp) - ld x18, 40(sp) - ld x19, 48(sp) - ld x20, 56(sp) - ld x21, 64(sp) - ld x22, 72(sp) - ld x23, 80(sp) - ld x24, 88(sp) - ld x25, 96(sp) - ld x26, 104(sp) - ld x27, 112(sp) - fld f8, 120(sp) - fld f9, 128(sp) - fld f18, 136(sp) - fld f19, 144(sp) - fld f20, 152(sp) - fld f21, 160(sp) - fld f22, 168(sp) - fld f23, 176(sp) - fld f24, 184(sp) - fld f25, 192(sp) - fld f26, 200(sp) - fld f27, 208(sp) - addi sp, sp, 216 + ld x8, 8(sp) + ld x9, 16(sp) + ld x18, 24(sp) + ld x19, 32(sp) + ld x20, 40(sp) + ld x21, 48(sp) + ld x22, 56(sp) + ld x23, 64(sp) + ld x24, 72(sp) + ld x25, 80(sp) + ld x26, 88(sp) + ld x27, 96(sp) + fld f8, 104(sp) + fld f9, 112(sp) + fld f18, 120(sp) + fld f19, 128(sp) + fld f20, 136(sp) + fld f21, 144(sp) + fld f22, 152(sp) + fld f23, 160(sp) + fld f24, 168(sp) + fld f25, 176(sp) + fld f26, 184(sp) + fld f27, 192(sp) + addi sp, sp, 200 jr ra diff --git a/src/runtime/mkpreempt.go b/src/runtime/mkpreempt.go index d662e73813..e8c23d485a 100644 --- a/src/runtime/mkpreempt.go +++ b/src/runtime/mkpreempt.go @@ -504,12 +504,12 @@ func genPPC64() { } func genRISCV64() { - // X0 (zero), X1 (LR), X2 (SP), X4 (TP), X27 (g), X31 (TMP) are special. + // X0 (zero), X1 (LR), X2 (SP), X3 (GP), X4 (TP), X27 (g), X31 (TMP) are special. var l = layout{sp: "X2", stack: 8} - // Add integer registers (X3, X5-X26, X28-30). - for i := 3; i < 31; i++ { - if i == 4 || i == 27 { + // Add integer registers (X5-X26, X28-30). + for i := 5; i < 31; i++ { + if i == 27 { continue } reg := fmt.Sprintf("X%d", i) diff --git a/src/runtime/preempt_riscv64.s b/src/runtime/preempt_riscv64.s index eb68dcba2b..56df6c30e0 100644 --- a/src/runtime/preempt_riscv64.s +++ b/src/runtime/preempt_riscv64.s @@ -4,126 +4,124 @@ #include "textflag.h" TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 - MOV X1, -472(X2) - ADD $-472, X2 - MOV X3, 8(X2) - MOV X5, 16(X2) - MOV X6, 24(X2) - MOV X7, 32(X2) - MOV X8, 40(X2) - MOV X9, 48(X2) - MOV X10, 56(X2) - MOV X11, 64(X2) - MOV X12, 72(X2) - MOV X13, 80(X2) - MOV X14, 88(X2) - MOV X15, 96(X2) - MOV X16, 104(X2) - MOV X17, 112(X2) - MOV X18, 120(X2) - MOV X19, 128(X2) - MOV X20, 136(X2) - MOV X21, 144(X2) - MOV X22, 152(X2) - MOV X23, 160(X2) - MOV X24, 168(X2) - MOV X25, 176(X2) - MOV X26, 184(X2) - MOV X28, 192(X2) - MOV X29, 200(X2) - MOV X30, 208(X2) - MOVD F0, 216(X2) - MOVD F1, 224(X2) - MOVD F2, 232(X2) - MOVD F3, 240(X2) - MOVD F4, 248(X2) - MOVD F5, 256(X2) - MOVD F6, 264(X2) - MOVD F7, 272(X2) - MOVD F8, 280(X2) - MOVD F9, 288(X2) - MOVD F10, 296(X2) - MOVD F11, 304(X2) - MOVD F12, 312(X2) - MOVD F13, 320(X2) - MOVD F14, 328(X2) - MOVD F15, 336(X2) - MOVD F16, 344(X2) - MOVD F17, 352(X2) - MOVD F18, 360(X2) - MOVD F19, 368(X2) - MOVD F20, 376(X2) - MOVD F21, 384(X2) - MOVD F22, 392(X2) - MOVD F23, 400(X2) - MOVD F24, 408(X2) - MOVD F25, 416(X2) - MOVD F26, 424(X2) - MOVD F27, 432(X2) - MOVD F28, 440(X2) - MOVD F29, 448(X2) - MOVD F30, 456(X2) - MOVD F31, 464(X2) + MOV X1, -464(X2) + ADD $-464, X2 + MOV X5, 8(X2) + MOV X6, 16(X2) + MOV X7, 24(X2) + MOV X8, 32(X2) + MOV X9, 40(X2) + MOV X10, 48(X2) + MOV X11, 56(X2) + MOV X12, 64(X2) + MOV X13, 72(X2) + MOV X14, 80(X2) + MOV X15, 88(X2) + MOV X16, 96(X2) + MOV X17, 104(X2) + MOV X18, 112(X2) + MOV X19, 120(X2) + MOV X20, 128(X2) + MOV X21, 136(X2) + MOV X22, 144(X2) + MOV X23, 152(X2) + MOV X24, 160(X2) + MOV X25, 168(X2) + MOV X26, 176(X2) + MOV X28, 184(X2) + MOV X29, 192(X2) + MOV X30, 200(X2) + MOVD F0, 208(X2) + MOVD F1, 216(X2) + MOVD F2, 224(X2) + MOVD F3, 232(X2) + MOVD F4, 240(X2) + MOVD F5, 248(X2) + MOVD F6, 256(X2) + MOVD F7, 264(X2) + MOVD F8, 272(X2) + MOVD F9, 280(X2) + MOVD F10, 288(X2) + MOVD F11, 296(X2) + MOVD F12, 304(X2) + MOVD F13, 312(X2) + MOVD F14, 320(X2) + MOVD F15, 328(X2) + MOVD F16, 336(X2) + MOVD F17, 344(X2) + MOVD F18, 352(X2) + MOVD F19, 360(X2) + MOVD F20, 368(X2) + MOVD F21, 376(X2) + MOVD F22, 384(X2) + MOVD F23, 392(X2) + MOVD F24, 400(X2) + MOVD F25, 408(X2) + MOVD F26, 416(X2) + MOVD F27, 424(X2) + MOVD F28, 432(X2) + MOVD F29, 440(X2) + MOVD F30, 448(X2) + MOVD F31, 456(X2) CALL ·asyncPreempt2(SB) - MOVD 464(X2), F31 - MOVD 456(X2), F30 - MOVD 448(X2), F29 - MOVD 440(X2), F28 - MOVD 432(X2), F27 - MOVD 424(X2), F26 - MOVD 416(X2), F25 - MOVD 408(X2), F24 - MOVD 400(X2), F23 - MOVD 392(X2), F22 - MOVD 384(X2), F21 - MOVD 376(X2), F20 - MOVD 368(X2), F19 - MOVD 360(X2), F18 - MOVD 352(X2), F17 - MOVD 344(X2), F16 - MOVD 336(X2), F15 - MOVD 328(X2), F14 - MOVD 320(X2), F13 - MOVD 312(X2), F12 - MOVD 304(X2), F11 - MOVD 296(X2), F10 - MOVD 288(X2), F9 - MOVD 280(X2), F8 - MOVD 272(X2), F7 - MOVD 264(X2), F6 - MOVD 256(X2), F5 - MOVD 248(X2), F4 - MOVD 240(X2), F3 - MOVD 232(X2), F2 - MOVD 224(X2), F1 - MOVD 216(X2), F0 - MOV 208(X2), X30 - MOV 200(X2), X29 - MOV 192(X2), X28 - MOV 184(X2), X26 - MOV 176(X2), X25 - MOV 168(X2), X24 - MOV 160(X2), X23 - MOV 152(X2), X22 - MOV 144(X2), X21 - MOV 136(X2), X20 - MOV 128(X2), X19 - MOV 120(X2), X18 - MOV 112(X2), X17 - MOV 104(X2), X16 - MOV 96(X2), X15 - MOV 88(X2), X14 - MOV 80(X2), X13 - MOV 72(X2), X12 - MOV 64(X2), X11 - MOV 56(X2), X10 - MOV 48(X2), X9 - MOV 40(X2), X8 - MOV 32(X2), X7 - MOV 24(X2), X6 - MOV 16(X2), X5 - MOV 8(X2), X3 - MOV 472(X2), X1 + MOVD 456(X2), F31 + MOVD 448(X2), F30 + MOVD 440(X2), F29 + MOVD 432(X2), F28 + MOVD 424(X2), F27 + MOVD 416(X2), F26 + MOVD 408(X2), F25 + MOVD 400(X2), F24 + MOVD 392(X2), F23 + MOVD 384(X2), F22 + MOVD 376(X2), F21 + MOVD 368(X2), F20 + MOVD 360(X2), F19 + MOVD 352(X2), F18 + MOVD 344(X2), F17 + MOVD 336(X2), F16 + MOVD 328(X2), F15 + MOVD 320(X2), F14 + MOVD 312(X2), F13 + MOVD 304(X2), F12 + MOVD 296(X2), F11 + MOVD 288(X2), F10 + MOVD 280(X2), F9 + MOVD 272(X2), F8 + MOVD 264(X2), F7 + MOVD 256(X2), F6 + MOVD 248(X2), F5 + MOVD 240(X2), F4 + MOVD 232(X2), F3 + MOVD 224(X2), F2 + MOVD 216(X2), F1 + MOVD 208(X2), F0 + MOV 200(X2), X30 + MOV 192(X2), X29 + MOV 184(X2), X28 + MOV 176(X2), X26 + MOV 168(X2), X25 + MOV 160(X2), X24 + MOV 152(X2), X23 + MOV 144(X2), X22 + MOV 136(X2), X21 + MOV 128(X2), X20 + MOV 120(X2), X19 + MOV 112(X2), X18 + MOV 104(X2), X17 + MOV 96(X2), X16 + MOV 88(X2), X15 + MOV 80(X2), X14 + MOV 72(X2), X13 + MOV 64(X2), X12 + MOV 56(X2), X11 + MOV 48(X2), X10 + MOV 40(X2), X9 + MOV 32(X2), X8 + MOV 24(X2), X7 + MOV 16(X2), X6 + MOV 8(X2), X5 + MOV 464(X2), X1 MOV (X2), X31 - ADD $480, X2 + ADD $472, X2 JMP (X31) diff --git a/src/runtime/tls_riscv64.s b/src/runtime/tls_riscv64.s index 22b550b761..397919aeba 100644 --- a/src/runtime/tls_riscv64.s +++ b/src/runtime/tls_riscv64.s @@ -15,7 +15,7 @@ TEXT runtime·save_g(SB),NOSPLIT|NOFRAME,$0-0 BEQ X0, X31, nocgo MOV runtime·tls_g(SB), X31 - ADD X4, X31 // add offset to thread pointer (X4) + ADD TP, X31 // add offset to thread pointer (X4) MOV g, (X31) nocgo: @@ -23,7 +23,7 @@ nocgo: TEXT runtime·load_g(SB),NOSPLIT|NOFRAME,$0-0 MOV runtime·tls_g(SB), X31 - ADD X4, X31 // add offset to thread pointer (X4) + ADD TP, X31 // add offset to thread pointer (X4) MOV (X31), g RET -- GitLab From 6458b2e8db7c4529248934f7e491df02d1e89318 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Fri, 16 Jul 2021 03:06:18 +1000 Subject: [PATCH 1921/2500] all: add support for c-archive and c-shared on linux/riscv64 This provides the runtime glue (_rt0_riscv64_linux_lib) for c-archive and c-shared support, along with enabling both of these buildmodes on linux/riscv64. Both misc/cgo/testcarchive and misc/cgo/testcshared now pass on this platform. Fixes #47100 Change-Id: I7ad75b23ae1d592dbac60d15bba557668287711f Reviewed-on: https://go-review.googlesource.com/c/go/+/334872 Trust: Joel Sing Run-TryBot: Joel Sing Reviewed-by: Cherry Mui --- misc/cgo/testcshared/testdata/libgo2/dup2.go | 2 +- misc/cgo/testcshared/testdata/libgo2/dup3.go | 2 +- src/cmd/compile/internal/ssa/regalloc.go | 2 + src/cmd/dist/test.go | 4 +- src/cmd/internal/sys/supported.go | 2 +- src/cmd/link/internal/ld/config.go | 2 +- src/runtime/rt0_linux_riscv64.s | 98 ++++++++++++++++++++ 7 files changed, 106 insertions(+), 6 deletions(-) diff --git a/misc/cgo/testcshared/testdata/libgo2/dup2.go b/misc/cgo/testcshared/testdata/libgo2/dup2.go index d18f0b130d..d343aa54d9 100644 --- a/misc/cgo/testcshared/testdata/libgo2/dup2.go +++ b/misc/cgo/testcshared/testdata/libgo2/dup2.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build darwin dragonfly freebsd linux,!arm64 netbsd openbsd +// +build darwin dragonfly freebsd linux,!arm64,!riscv64 netbsd openbsd package main diff --git a/misc/cgo/testcshared/testdata/libgo2/dup3.go b/misc/cgo/testcshared/testdata/libgo2/dup3.go index c9c65a6e3c..459f0dc196 100644 --- a/misc/cgo/testcshared/testdata/libgo2/dup3.go +++ b/misc/cgo/testcshared/testdata/libgo2/dup3.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux,arm64 +// +build linux,arm64 linux,riscv64 package main diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index 91b04e99f4..64792d0c80 100644 --- a/src/cmd/compile/internal/ssa/regalloc.go +++ b/src/cmd/compile/internal/ssa/regalloc.go @@ -635,6 +635,8 @@ func (s *regAllocState) init(f *Func) { // nothing to do case "ppc64le": // R2 already reserved. // nothing to do + case "riscv64": // X3 (aka GP) and X4 (aka TP) already reserved. + // nothing to do case "s390x": s.allocatable &^= 1 << 11 // R11 default: diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index 5935011e19..14b48351db 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -1031,7 +1031,7 @@ func (t *tester) supportedBuildmode(mode string) bool { switch pair { case "aix-ppc64", "darwin-amd64", "darwin-arm64", "ios-arm64", - "linux-amd64", "linux-386", "linux-ppc64le", "linux-s390x", + "linux-amd64", "linux-386", "linux-ppc64le", "linux-riscv64", "linux-s390x", "freebsd-amd64", "windows-amd64", "windows-386": return true @@ -1039,7 +1039,7 @@ func (t *tester) supportedBuildmode(mode string) bool { return false case "c-shared": switch pair { - case "linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le", "linux-s390x", + case "linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le", "linux-riscv64", "linux-s390x", "darwin-amd64", "darwin-arm64", "freebsd-amd64", "android-arm", "android-arm64", "android-386", diff --git a/src/cmd/internal/sys/supported.go b/src/cmd/internal/sys/supported.go index de2a3fd140..c6a78a51eb 100644 --- a/src/cmd/internal/sys/supported.go +++ b/src/cmd/internal/sys/supported.go @@ -105,7 +105,7 @@ func BuildModeSupported(compiler, buildmode, goos, goarch string) bool { case "c-shared": switch platform { - case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/ppc64le", "linux/s390x", + case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/ppc64le", "linux/riscv64", "linux/s390x", "android/amd64", "android/arm", "android/arm64", "android/386", "freebsd/amd64", "darwin/amd64", "darwin/arm64", diff --git a/src/cmd/link/internal/ld/config.go b/src/cmd/link/internal/ld/config.go index 72616ff62f..2d7e1bff68 100644 --- a/src/cmd/link/internal/ld/config.go +++ b/src/cmd/link/internal/ld/config.go @@ -74,7 +74,7 @@ func (mode *BuildMode) Set(s string) error { *mode = BuildModeCArchive case "c-shared": switch buildcfg.GOARCH { - case "386", "amd64", "arm", "arm64", "ppc64le", "s390x": + case "386", "amd64", "arm", "arm64", "ppc64le", "riscv64", "s390x": default: return badmode() } diff --git a/src/runtime/rt0_linux_riscv64.s b/src/runtime/rt0_linux_riscv64.s index f31f7f75e5..d6b8ac85dc 100644 --- a/src/runtime/rt0_linux_riscv64.s +++ b/src/runtime/rt0_linux_riscv64.s @@ -9,6 +9,104 @@ TEXT _rt0_riscv64_linux(SB),NOSPLIT|NOFRAME,$0 ADD $8, X2, A1 // argv JMP main(SB) +// When building with -buildmode=c-shared, this symbol is called when the shared +// library is loaded. +TEXT _rt0_riscv64_linux_lib(SB),NOSPLIT,$224 + // Preserve callee-save registers, along with X1 (LR). + MOV X1, (8*3)(X2) + MOV X8, (8*4)(X2) + MOV X9, (8*5)(X2) + MOV X18, (8*6)(X2) + MOV X19, (8*7)(X2) + MOV X20, (8*8)(X2) + MOV X21, (8*9)(X2) + MOV X22, (8*10)(X2) + MOV X23, (8*11)(X2) + MOV X24, (8*12)(X2) + MOV X25, (8*13)(X2) + MOV X26, (8*14)(X2) + MOV g, (8*15)(X2) + MOVD F8, (8*16)(X2) + MOVD F9, (8*17)(X2) + MOVD F18, (8*18)(X2) + MOVD F19, (8*19)(X2) + MOVD F20, (8*20)(X2) + MOVD F21, (8*21)(X2) + MOVD F22, (8*22)(X2) + MOVD F23, (8*23)(X2) + MOVD F24, (8*24)(X2) + MOVD F25, (8*25)(X2) + MOVD F26, (8*26)(X2) + MOVD F27, (8*27)(X2) + + // Initialize g as nil in case of using g later e.g. sigaction in cgo_sigaction.go + MOV X0, g + + MOV A0, _rt0_riscv64_linux_lib_argc<>(SB) + MOV A1, _rt0_riscv64_linux_lib_argv<>(SB) + + // Synchronous initialization. + MOV $runtime·libpreinit(SB), T0 + JALR RA, T0 + + // Create a new thread to do the runtime initialization and return. + MOV _cgo_sys_thread_create(SB), T0 + BEQZ T0, nocgo + MOV $_rt0_riscv64_linux_lib_go(SB), A0 + MOV $0, A1 + JALR RA, T0 + JMP restore + +nocgo: + MOV $0x800000, A0 // stacksize = 8192KB + MOV $_rt0_riscv64_linux_lib_go(SB), A1 + MOV A0, 8(X2) + MOV A1, 16(X2) + MOV $runtime·newosproc0(SB), T0 + JALR RA, T0 + +restore: + // Restore callee-save registers, along with X1 (LR). + MOV (8*3)(X2), X1 + MOV (8*4)(X2), X8 + MOV (8*5)(X2), X9 + MOV (8*6)(X2), X18 + MOV (8*7)(X2), X19 + MOV (8*8)(X2), X20 + MOV (8*9)(X2), X21 + MOV (8*10)(X2), X22 + MOV (8*11)(X2), X23 + MOV (8*12)(X2), X24 + MOV (8*13)(X2), X25 + MOV (8*14)(X2), X26 + MOV (8*15)(X2), g + MOVD (8*16)(X2), F8 + MOVD (8*17)(X2), F9 + MOVD (8*18)(X2), F18 + MOVD (8*19)(X2), F19 + MOVD (8*20)(X2), F20 + MOVD (8*21)(X2), F21 + MOVD (8*22)(X2), F22 + MOVD (8*23)(X2), F23 + MOVD (8*24)(X2), F24 + MOVD (8*25)(X2), F25 + MOVD (8*26)(X2), F26 + MOVD (8*27)(X2), F27 + + RET + +TEXT _rt0_riscv64_linux_lib_go(SB),NOSPLIT,$0 + MOV _rt0_riscv64_linux_lib_argc<>(SB), A0 + MOV _rt0_riscv64_linux_lib_argv<>(SB), A1 + MOV $runtime·rt0_go(SB), T0 + JALR ZERO, T0 + +DATA _rt0_riscv64_linux_lib_argc<>(SB)/8, $0 +GLOBL _rt0_riscv64_linux_lib_argc<>(SB),NOPTR, $8 +DATA _rt0_riscv64_linux_lib_argv<>(SB)/8, $0 +GLOBL _rt0_riscv64_linux_lib_argv<>(SB),NOPTR, $8 + + TEXT main(SB),NOSPLIT|NOFRAME,$0 MOV $runtime·rt0_go(SB), T0 JALR ZERO, T0 -- GitLab From c143661568dc23badd4ba04f4193658fc1fd9c33 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 2 Nov 2021 20:42:21 -0700 Subject: [PATCH 1922/2500] test/typeparam: add test for indexing on typeparams with various constraints Add test for indexing on variables whose types are constrained to various kinds of types. Change-Id: I991eecfe39dba5d817c0fbe259ba558d4881ea84 Reviewed-on: https://go-review.googlesource.com/c/go/+/360867 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- test/typeparam/index2.go | 67 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 test/typeparam/index2.go diff --git a/test/typeparam/index2.go b/test/typeparam/index2.go new file mode 100644 index 0000000000..683b76f76d --- /dev/null +++ b/test/typeparam/index2.go @@ -0,0 +1,67 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Testing various generic uses of indexing, both for reads and writes. + +package main + +import "fmt" + +// Can index an argument (read/write) constrained to be a slice or an array. +func Index1[T interface{ []int64 | [5]int64 }](x T) int64 { + x[2] = 5 + return x[3] +} + +// Can index an argument (read) constrained to be a byte array or a string. +func Index2[T interface{ []byte | string }](x T) byte { + return x[3] +} + +// Can index an argument (write) constrained to be a byte array, but not a string. +func Index2a[T interface{ []byte }](x T) byte { + x[2] = 'b' + return x[3] +} + +// Can index an argument (read/write) constrained to be a map. Maps can't +// be combined with any other type for indexing purposes. +func Index3[T interface{ map[int]int64 }](x T) int64 { + x[2] = 43 + return x[3] +} + +// But the type of the map keys or values can be parameterized. +func Index4[T any](x map[int]T) T { + var zero T + x[2] = zero + return x[3] +} + +func test[T comparable](got, want T) { + if got != want { + panic(fmt.Sprintf("got %v, want %v", got, want)) + } +} + +func main() { + x := make([]int64, 4) + x[3] = 2 + y := [5]int64{1, 2, 3, 4, 5} + z := "abcd" + w := make([]byte, 4) + w[3] = 5 + v := make(map[int]int64) + v[3] = 18 + + test(Index1(x), int64(2)) + test(Index1(y), int64(4)) + test(Index2(z), byte(100)) + test(Index2(w), byte(5)) + test(Index2a(w), byte(5)) + test(Index3(v), int64(18)) + test(Index4(v), int64(18)) +} -- GitLab From 5f0e5d21bb1f2c1baf15bfd90ad5b090b88e6292 Mon Sep 17 00:00:00 2001 From: Rhys Hiltner Date: Fri, 29 Oct 2021 17:35:30 -0700 Subject: [PATCH 1923/2500] runtime/pprof: disable GC during calibration test TestCPUProfileMultithreadMagnitude compares Go's CPU profile against the OS's accounting of the process's execution time, expecting them to be near equal. Background work from the runtime (especially in the garbage collector) can add significant noise to that measurement and flakiness to the test. Disable automatic GC cycles during the test. Updates #49065 Change-Id: Ie88895bfea17374278c5187f3a83e9f486bd37fb Reviewed-on: https://go-review.googlesource.com/c/go/+/359934 Reviewed-by: Michael Pratt Trust: Michael Pratt Trust: Michael Knyszek --- src/runtime/pprof/pprof_test.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go index 06e0274e9a..417d5034a6 100644 --- a/src/runtime/pprof/pprof_test.go +++ b/src/runtime/pprof/pprof_test.go @@ -20,6 +20,7 @@ import ( "os/exec" "regexp" "runtime" + "runtime/debug" "strings" "sync" "sync/atomic" @@ -133,6 +134,14 @@ func TestCPUProfileMultithreadMagnitude(t *testing.T) { parallelism := runtime.GOMAXPROCS(0) + // This test compares the process's total CPU time against the CPU + // profiler's view of time spent in direct execution of user code. + // Background work, especially from the garbage collector, adds noise to + // that measurement. Disable automatic triggering of the GC, and then + // request a complete GC cycle (up through sweep termination). + defer debug.SetGCPercent(debug.SetGCPercent(-1)) + runtime.GC() + var cpuTime1, cpuTimeN time.Duration p := testCPUProfile(t, stackContains, []string{"runtime/pprof.cpuHog1", "runtime/pprof.cpuHog3"}, avoidFunctions(), func(dur time.Duration) { cpuTime1 = diffCPUTime(t, func() { -- GitLab From e0e6e4d23fe840c2c9b4caed30930cad6788b797 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Wed, 3 Nov 2021 10:58:59 -0400 Subject: [PATCH 1924/2500] internal/fuzz: improve error for mismatched types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #48635 Change-Id: Ia3cde119d5eb31bc771fe3a39acb2372dbd988ff Reviewed-on: https://go-review.googlesource.com/c/go/+/361114 Trust: Katie Hockman Trust: Daniel Martí Run-TryBot: Katie Hockman Reviewed-by: Daniel Martí Reviewed-by: Bryan C. Mills --- src/cmd/go/testdata/script/test_fuzz.txt | 5 +++-- src/internal/fuzz/fuzz.go | 10 +++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt index 020012d73e..150491be04 100644 --- a/src/cmd/go/testdata/script/test_fuzz.txt +++ b/src/cmd/go/testdata/script/test_fuzz.txt @@ -152,6 +152,7 @@ stdout FAIL # Test that the wrong type given with f.Add will fail. ! go test -run FuzzWrongType fuzz_add_test.go ! stdout ^ok +stdout '\[string int\], want \[\[\]uint8 int8\]' stdout FAIL # Test fatal with testdata seed corpus @@ -435,8 +436,8 @@ func FuzzAddDifferentType(f *testing.F) { } func FuzzWrongType(f *testing.F) { - f.Add("hello") - f.Fuzz(func(*testing.T, []byte) {}) + f.Add("hello", 50) + f.Fuzz(func(*testing.T, []byte, int8) {}) } -- corpustesting/fuzz_testdata_corpus_test.go -- diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 2ebe2a64db..aef1dee978 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -997,11 +997,15 @@ func readCorpusData(data []byte, types []reflect.Type) ([]interface{}, error) { // provided. func CheckCorpus(vals []interface{}, types []reflect.Type) error { if len(vals) != len(types) { - return fmt.Errorf("wrong number of values in corpus entry %v: want %v", vals, types) + return fmt.Errorf("wrong number of values in corpus entry: %d, want %d", len(vals), len(types)) + } + valsT := make([]reflect.Type, len(vals)) + for valsI, v := range vals { + valsT[valsI] = reflect.TypeOf(v) } for i := range types { - if reflect.TypeOf(vals[i]) != types[i] { - return fmt.Errorf("mismatched types in corpus entry: %v, want %v", vals, types) + if valsT[i] != types[i] { + return fmt.Errorf("mismatched types in corpus entry: %v, want %v", valsT, types) } } return nil -- GitLab From d4e0e8e4a41e5e1e7d0359287a1015791ce778ed Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Wed, 3 Nov 2021 09:40:32 -0700 Subject: [PATCH 1925/2500] cmd/compile: make pointers to arrays their own shape Pointers to arrays can be used to cast from a slice. We need the shape of such type params to be different so we can compile those casts correctly. This is kind of a big hammer to fix #49295. It would be nice to only do this when we know there's a []T->*[N]T conversion. Fixes #49295 Change-Id: Ibda33057fab2dd28162537aab0f1244211d68e3f Reviewed-on: https://go-review.googlesource.com/c/go/+/361135 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/typecheck/subr.go | 4 ++- test/typeparam/issue49295.go | 30 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 test/typeparam/issue49295.go diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 96e120fe03..1986845f64 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1421,7 +1421,9 @@ func Shapify(t *types.Type, index int) *types.Type { // All pointers have the same shape. // TODO: Make unsafe.Pointer the same shape as normal pointers. - if u.Kind() == types.TPTR { + // Note: pointers to arrays are special because of slice-to-array-pointer + // conversions. See issue 49295. + if u.Kind() == types.TPTR && u.Elem().Kind() != types.TARRAY { u = types.Types[types.TUINT8].PtrTo() } diff --git a/test/typeparam/issue49295.go b/test/typeparam/issue49295.go new file mode 100644 index 0000000000..435b44d10c --- /dev/null +++ b/test/typeparam/issue49295.go @@ -0,0 +1,30 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "io" + +type Reader struct { + buf []byte +} +type Token *[16]byte + +func Read[T interface{ ~*[16]byte }](r *Reader) (t T, err error) { + if n := len(t); len(r.buf) >= n { + t = T(r.buf[:n]) + r.buf = r.buf[n:] + return + } + err = io.EOF + return +} + +func main() { + r := &Reader{buf: []byte("0123456789abcdef")} + token, err := Read[Token](r) + _, _ = token, err +} -- GitLab From cfd016df1fba2a2a104f4cca705aa4357777986b Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Wed, 3 Nov 2021 18:19:04 +0100 Subject: [PATCH 1926/2500] runtime: on windows, read nanotime with one instruction or issue barrier On 64-bit, this is more efficient, and on ARM64, this prevents the time from moving backwards due to the weaker memory model. On ARM32 due to the weaker memory model, we issue a memory barrier. Updates #48072. Change-Id: If4695716c3039d8af14e14808af217f5c99fc93a Reviewed-on: https://go-review.googlesource.com/c/go/+/361057 Trust: Jason A. Donenfeld Run-TryBot: Jason A. Donenfeld TryBot-Result: Go Bot Reviewed-by: Austin Clements --- src/runtime/sys_windows_amd64.s | 13 +++---------- src/runtime/sys_windows_arm.s | 2 ++ src/runtime/sys_windows_arm64.s | 10 +--------- src/runtime/time_windows.h | 1 + src/runtime/time_windows_amd64.s | 19 +++---------------- src/runtime/time_windows_arm.s | 4 ++++ src/runtime/time_windows_arm64.s | 22 +++------------------- 7 files changed, 17 insertions(+), 54 deletions(-) diff --git a/src/runtime/sys_windows_amd64.s b/src/runtime/sys_windows_amd64.s index 1e4c1d2b61..1467b4d57b 100644 --- a/src/runtime/sys_windows_amd64.s +++ b/src/runtime/sys_windows_amd64.s @@ -344,16 +344,9 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$0-8 CMPB runtime·useQPCTime(SB), $0 JNE useQPC MOVQ $_INTERRUPT_TIME, DI -loop: - MOVL time_hi1(DI), AX - MOVL time_lo(DI), BX - MOVL time_hi2(DI), CX - CMPL AX, CX - JNE loop - SHLQ $32, CX - ORQ BX, CX - IMULQ $100, CX - MOVQ CX, ret+0(FP) + MOVQ time_lo(DI), AX + IMULQ $100, AX + MOVQ AX, ret+0(FP) RET useQPC: JMP runtime·nanotimeQPC(SB) diff --git a/src/runtime/sys_windows_arm.s b/src/runtime/sys_windows_arm.s index c9e96cb652..e5b1b7e9f3 100644 --- a/src/runtime/sys_windows_arm.s +++ b/src/runtime/sys_windows_arm.s @@ -350,7 +350,9 @@ TEXT runtime·nanotime1(SB),NOSPLIT|NOFRAME,$0-8 MOVW $_INTERRUPT_TIME, R3 loop: MOVW time_hi1(R3), R1 + DMB MB_ISH MOVW time_lo(R3), R0 + DMB MB_ISH MOVW time_hi2(R3), R2 CMP R1, R2 BNE loop diff --git a/src/runtime/sys_windows_arm64.s b/src/runtime/sys_windows_arm64.s index 44145c53fb..87f8f0d218 100644 --- a/src/runtime/sys_windows_arm64.s +++ b/src/runtime/sys_windows_arm64.s @@ -415,15 +415,7 @@ TEXT runtime·nanotime1(SB),NOSPLIT|NOFRAME,$0-8 CMP $0, R0 BNE useQPC MOVD $_INTERRUPT_TIME, R3 -loop: - MOVWU time_hi1(R3), R1 - MOVWU time_lo(R3), R0 - MOVWU time_hi2(R3), R2 - CMP R1, R2 - BNE loop - - // wintime = R1:R0, multiply by 100 - ORR R1<<32, R0 + MOVD time_lo(R3), R0 MOVD $100, R1 MUL R1, R0 MOVD R0, ret+0(FP) diff --git a/src/runtime/time_windows.h b/src/runtime/time_windows.h index cd16fd163b..7c2e65c328 100644 --- a/src/runtime/time_windows.h +++ b/src/runtime/time_windows.h @@ -9,6 +9,7 @@ // http://web.archive.org/web/20210411000829/https://wrkhpi.wordpress.com/2007/08/09/getting-os-information-the-kuser_shared_data-structure/ // Must read hi1, then lo, then hi2. The snapshot is valid if hi1 == hi2. +// Or, on 64-bit, just read lo:hi1 all at once atomically. #define _INTERRUPT_TIME 0x7ffe0008 #define _SYSTEM_TIME 0x7ffe0014 #define time_lo 0 diff --git a/src/runtime/time_windows_amd64.s b/src/runtime/time_windows_amd64.s index 93ab960b06..045f64eb46 100644 --- a/src/runtime/time_windows_amd64.s +++ b/src/runtime/time_windows_amd64.s @@ -12,27 +12,14 @@ TEXT time·now(SB),NOSPLIT,$0-24 CMPB runtime·useQPCTime(SB), $0 JNE useQPC + MOVQ $_INTERRUPT_TIME, DI -loop: - MOVL time_hi1(DI), AX - MOVL time_lo(DI), BX - MOVL time_hi2(DI), CX - CMPL AX, CX - JNE loop - SHLQ $32, AX - ORQ BX, AX + MOVQ time_lo(DI), AX IMULQ $100, AX MOVQ AX, mono+16(FP) MOVQ $_SYSTEM_TIME, DI -wall: - MOVL time_hi1(DI), AX - MOVL time_lo(DI), BX - MOVL time_hi2(DI), CX - CMPL AX, CX - JNE wall - SHLQ $32, AX - ORQ BX, AX + MOVQ time_lo(DI), AX MOVQ $116444736000000000, DI SUBQ DI, AX IMULQ $100, AX diff --git a/src/runtime/time_windows_arm.s b/src/runtime/time_windows_arm.s index 7c763b66ed..6552d75ff1 100644 --- a/src/runtime/time_windows_arm.s +++ b/src/runtime/time_windows_arm.s @@ -17,7 +17,9 @@ TEXT time·now(SB),NOSPLIT|NOFRAME,$0-20 MOVW $_INTERRUPT_TIME, R3 loop: MOVW time_hi1(R3), R1 + DMB MB_ISH MOVW time_lo(R3), R0 + DMB MB_ISH MOVW time_hi2(R3), R2 CMP R1, R2 BNE loop @@ -34,7 +36,9 @@ loop: MOVW $_SYSTEM_TIME, R3 wall: MOVW time_hi1(R3), R1 + DMB MB_ISH MOVW time_lo(R3), R0 + DMB MB_ISH MOVW time_hi2(R3), R2 CMP R1, R2 BNE wall diff --git a/src/runtime/time_windows_arm64.s b/src/runtime/time_windows_arm64.s index ef52ce4c99..e8a0eb2f93 100644 --- a/src/runtime/time_windows_arm64.s +++ b/src/runtime/time_windows_arm64.s @@ -13,34 +13,18 @@ TEXT time·now(SB),NOSPLIT|NOFRAME,$0-24 MOVB runtime·useQPCTime(SB), R0 CMP $0, R0 BNE useQPC - MOVD $_INTERRUPT_TIME, R3 -loop: - MOVWU time_hi1(R3), R1 - MOVWU time_lo(R3), R0 - MOVWU time_hi2(R3), R2 - CMP R1, R2 - BNE loop - // wintime = R1:R0, multiply by 100 - ORR R1<<32, R0 + MOVD $_INTERRUPT_TIME, R3 + MOVD time_lo(R3), R0 MOVD $100, R1 MUL R1, R0 MOVD R0, mono+16(FP) MOVD $_SYSTEM_TIME, R3 -wall: - MOVWU time_hi1(R3), R1 - MOVWU time_lo(R3), R0 - MOVWU time_hi2(R3), R2 - CMP R1, R2 - BNE wall - - // w = R1:R0 in 100ns units + MOVD time_lo(R3), R0 // convert to Unix epoch (but still 100ns units) #define delta 116444736000000000 - ORR R1<<32, R0 SUB $delta, R0 - // Convert to nSec MOVD $100, R1 MUL R1, R0 -- GitLab From 74f99d0933d5c201fc17d90ab612cd1a9c7d425f Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Tue, 9 Jun 2020 08:58:08 +0100 Subject: [PATCH 1927/2500] database/sql: Fix idle connection reuse MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix idle connection reuse so that ConnMaxIdleTime clears down excessive idle connections. This now ensures that db.freeConn is ordered by returnedAt and that connections that have been idle for the shortest period are reused first. In addition connectionCleanerRunLocked updates the next check deadline based on idle and maximum life time information so that we avoid waiting up to double MaxIdleTime to close connections. Corrected the calling timer of connectionCleaner. Fixes #39471 Change-Id: I6d26b3542179ef35aa13e5265a89bc0f08ba7fa1 Reviewed-on: https://go-review.googlesource.com/c/go/+/237337 Reviewed-by: Tamás Gulácsi Reviewed-by: Daniel Theophanes Trust: Ian Lance Taylor --- src/database/sql/sql.go | 86 +++++++++++++++++++++++------------ src/database/sql/sql_test.go | 87 +++++++++++++++++++++++++++++------- 2 files changed, 130 insertions(+), 43 deletions(-) diff --git a/src/database/sql/sql.go b/src/database/sql/sql.go index b40b5c8fe4..e4a5a225b0 100644 --- a/src/database/sql/sql.go +++ b/src/database/sql/sql.go @@ -464,8 +464,8 @@ type DB struct { // connections in Stmt.css. numClosed uint64 - mu sync.Mutex // protects following fields - freeConn []*driverConn + mu sync.Mutex // protects following fields + freeConn []*driverConn // free connections ordered by returnedAt oldest to newest connRequests map[uint64]chan connRequest nextRequest uint64 // Next key to use in connRequests. numOpen int // number of opened and pending open connections @@ -1079,7 +1079,7 @@ func (db *DB) connectionCleaner(d time.Duration) { return } - closing := db.connectionCleanerRunLocked() + d, closing := db.connectionCleanerRunLocked(d) db.mu.Unlock() for _, c := range closing { c.Close() @@ -1088,45 +1088,74 @@ func (db *DB) connectionCleaner(d time.Duration) { if d < minInterval { d = minInterval } + + if !t.Stop() { + select { + case <-t.C: + default: + } + } t.Reset(d) } } -func (db *DB) connectionCleanerRunLocked() (closing []*driverConn) { - if db.maxLifetime > 0 { - expiredSince := nowFunc().Add(-db.maxLifetime) - for i := 0; i < len(db.freeConn); i++ { +// connectionCleanerRunLocked removes connections that should be closed from +// freeConn and returns them along side an updated duration to the next check +// if a quicker check is required to ensure connections are checked appropriately. +func (db *DB) connectionCleanerRunLocked(d time.Duration) (time.Duration, []*driverConn) { + var idleClosing int64 + var closing []*driverConn + if db.maxIdleTime > 0 { + // As freeConn is ordered by returnedAt process + // in reverse order to minimise the work needed. + idleSince := nowFunc().Add(-db.maxIdleTime) + last := len(db.freeConn) - 1 + for i := last; i >= 0; i-- { c := db.freeConn[i] - if c.createdAt.Before(expiredSince) { - closing = append(closing, c) - last := len(db.freeConn) - 1 - db.freeConn[i] = db.freeConn[last] - db.freeConn[last] = nil - db.freeConn = db.freeConn[:last] - i-- + if c.returnedAt.Before(idleSince) { + i++ + closing = db.freeConn[:i] + db.freeConn = db.freeConn[i:] + idleClosing = int64(len(closing)) + db.maxIdleTimeClosed += idleClosing + break + } + } + + if len(db.freeConn) > 0 { + c := db.freeConn[0] + if d2 := c.returnedAt.Sub(idleSince); d2 < d { + // Ensure idle connections are cleaned up as soon as + // possible. + d = d2 } } - db.maxLifetimeClosed += int64(len(closing)) } - if db.maxIdleTime > 0 { - expiredSince := nowFunc().Add(-db.maxIdleTime) - var expiredCount int64 + if db.maxLifetime > 0 { + expiredSince := nowFunc().Add(-db.maxLifetime) for i := 0; i < len(db.freeConn); i++ { c := db.freeConn[i] - if db.maxIdleTime > 0 && c.returnedAt.Before(expiredSince) { + if c.createdAt.Before(expiredSince) { closing = append(closing, c) - expiredCount++ + last := len(db.freeConn) - 1 - db.freeConn[i] = db.freeConn[last] + // Use slow delete as order is required to ensure + // connections are reused least idle time first. + copy(db.freeConn[i:], db.freeConn[i+1:]) db.freeConn[last] = nil db.freeConn = db.freeConn[:last] i-- + } else if d2 := c.createdAt.Sub(expiredSince); d2 < d { + // Prevent connections sitting the freeConn when they + // have expired by updating our next deadline d. + d = d2 } } - db.maxIdleTimeClosed += expiredCount + db.maxLifetimeClosed += int64(len(closing)) - idleClosing } - return + + return d, closing } // DBStats contains database statistics. @@ -1272,11 +1301,12 @@ func (db *DB) conn(ctx context.Context, strategy connReuseStrategy) (*driverConn lifetime := db.maxLifetime // Prefer a free connection, if possible. - numFree := len(db.freeConn) - if strategy == cachedOrNewConn && numFree > 0 { - conn := db.freeConn[0] - copy(db.freeConn, db.freeConn[1:]) - db.freeConn = db.freeConn[:numFree-1] + last := len(db.freeConn) - 1 + if strategy == cachedOrNewConn && last >= 0 { + // Reuse the lowest idle time connection so we can close + // connections which remain idle as soon as possible. + conn := db.freeConn[last] + db.freeConn = db.freeConn[:last] conn.inUse = true if conn.expired(lifetime) { db.maxLifetimeClosed++ diff --git a/src/database/sql/sql_test.go b/src/database/sql/sql_test.go index f771dee4a9..15c30e0d00 100644 --- a/src/database/sql/sql_test.go +++ b/src/database/sql/sql_test.go @@ -2399,10 +2399,14 @@ func TestConnMaxLifetime(t *testing.T) { tx.Commit() tx2.Commit() - driver.mu.Lock() - opens = driver.openCount - opens0 - closes = driver.closeCount - closes0 - driver.mu.Unlock() + // Give connectionCleaner chance to run. + for i := 0; i < 100 && closes != 1; i++ { + time.Sleep(time.Millisecond) + driver.mu.Lock() + opens = driver.openCount - opens0 + closes = driver.closeCount - closes0 + driver.mu.Unlock() + } if opens != 3 { t.Errorf("opens = %d; want 3", opens) @@ -2410,6 +2414,10 @@ func TestConnMaxLifetime(t *testing.T) { if closes != 1 { t.Errorf("closes = %d; want 1", closes) } + + if s := db.Stats(); s.MaxLifetimeClosed != 1 { + t.Errorf("MaxLifetimeClosed = %d; want 1 %#v", s.MaxLifetimeClosed, s) + } } // golang.org/issue/5323 @@ -3896,14 +3904,48 @@ func TestStatsMaxIdleClosedTen(t *testing.T) { } } +// testUseConns uses count concurrent connections with 1 nanosecond apart. +// Returns the returnedAt time of the final connection. +func testUseConns(t *testing.T, count int, tm time.Time, db *DB) time.Time { + conns := make([]*Conn, count) + ctx := context.Background() + for i := range conns { + c, err := db.Conn(ctx) + if err != nil { + t.Error(err) + } + conns[i] = c + } + + for _, c := range conns { + tm = tm.Add(time.Nanosecond) + nowFunc = func() time.Time { + return tm + } + if err := c.Close(); err != nil { + t.Error(err) + } + } + + return tm +} + func TestMaxIdleTime(t *testing.T) { + usedConns := 5 + reusedConns := 2 list := []struct { wantMaxIdleTime time.Duration + wantNextCheck time.Duration wantIdleClosed int64 timeOffset time.Duration }{ - {time.Nanosecond, 1, 10 * time.Millisecond}, - {time.Hour, 0, 10 * time.Millisecond}, + { + time.Millisecond, + time.Millisecond - time.Nanosecond, + int64(usedConns - reusedConns), + 10 * time.Millisecond, + }, + {time.Hour, time.Second, 0, 10 * time.Millisecond}, } baseTime := time.Unix(0, 0) defer func() { @@ -3917,23 +3959,38 @@ func TestMaxIdleTime(t *testing.T) { db := newTestDB(t, "people") defer closeDB(t, db) - db.SetMaxOpenConns(1) - db.SetMaxIdleConns(1) + db.SetMaxOpenConns(usedConns) + db.SetMaxIdleConns(usedConns) db.SetConnMaxIdleTime(item.wantMaxIdleTime) db.SetConnMaxLifetime(0) preMaxIdleClosed := db.Stats().MaxIdleTimeClosed - if err := db.Ping(); err != nil { - t.Fatal(err) + // Busy usedConns. + tm := testUseConns(t, usedConns, baseTime, db) + + tm = baseTime.Add(item.timeOffset) + + // Reuse connections which should never be considered idle + // and exercises the sorting for issue 39471. + testUseConns(t, reusedConns, tm, db) + + db.mu.Lock() + nc, closing := db.connectionCleanerRunLocked(time.Second) + if nc != item.wantNextCheck { + t.Errorf("got %v; want %v next check duration", nc, item.wantNextCheck) } - nowFunc = func() time.Time { - return baseTime.Add(item.timeOffset) + // Validate freeConn order. + var last time.Time + for _, c := range db.freeConn { + if last.After(c.returnedAt) { + t.Error("freeConn is not ordered by returnedAt") + break + } + last = c.returnedAt } - db.mu.Lock() - closing := db.connectionCleanerRunLocked() db.mu.Unlock() for _, c := range closing { c.Close() @@ -3945,7 +4002,7 @@ func TestMaxIdleTime(t *testing.T) { st := db.Stats() maxIdleClosed := st.MaxIdleTimeClosed - preMaxIdleClosed if g, w := maxIdleClosed, item.wantIdleClosed; g != w { - t.Errorf(" got: %d; want %d max idle closed conns", g, w) + t.Errorf("got: %d; want %d max idle closed conns", g, w) } }) } -- GitLab From 7f2463cc363fe8dbcbb89d521d1ede650de86c9b Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Wed, 3 Nov 2021 11:26:37 -0700 Subject: [PATCH 1928/2500] cmd/compile: fix up shape type package Use go.shape instead of .shape as the package the compiler uses to store shape types. Prevent path escaping for compiler-internal types, so we don't need to see %2e everywhere. Change-Id: I98e39c3b6472560113bdea7e0ba6eb7b81cb35e0 Reviewed-on: https://go-review.googlesource.com/c/go/+/361174 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/types/pkg.go | 9 ++++++++- src/cmd/compile/internal/types/type.go | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/types/pkg.go b/src/cmd/compile/internal/types/pkg.go index f63a357f0d..fe42049cee 100644 --- a/src/cmd/compile/internal/types/pkg.go +++ b/src/cmd/compile/internal/types/pkg.go @@ -9,6 +9,7 @@ import ( "cmd/internal/objabi" "fmt" "sort" + "strings" "sync" ) @@ -48,7 +49,13 @@ func NewPkg(path, name string) *Pkg { p := new(Pkg) p.Path = path p.Name = name - p.Prefix = objabi.PathToPrefix(path) + if strings.HasPrefix(path, "go.") { + // Special compiler-internal packages don't need to be escaped. + // This particularly helps with the go.shape package. + p.Prefix = path + } else { + p.Prefix = objabi.PathToPrefix(path) + } p.Syms = make(map[string]*Sym) pkgMap[path] = p diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index c3efbc9f07..6288df30d6 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -2202,4 +2202,4 @@ var ( var SimType [NTYPE]Kind -var ShapePkg = NewPkg(".shape", ".shape") +var ShapePkg = NewPkg("go.shape", "go.shape") -- GitLab From d3f5dd57811ca6c55654e67c58cf594fc2e5091e Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Wed, 3 Nov 2021 13:43:12 -0700 Subject: [PATCH 1929/2500] syscall: migrate new UDP send/recv API to internal/syscall/unix CL 331490 and friends added new API to package syscall. This was a mistake that we need to fix before Go 1.18 is released. Change-Id: I697c9a4fa649d564822f585dc163df5ab9e5ae08 Reviewed-on: https://go-review.googlesource.com/c/go/+/361216 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- api/next.txt | 108 -------------------- src/internal/poll/fd_unix.go | 9 +- src/internal/poll/fd_windows.go | 4 +- src/internal/syscall/unix/net.go | 28 +++++ src/internal/syscall/unix/net_js.go | 28 +++++ src/internal/syscall/windows/net_windows.go | 18 ++++ src/syscall/net_js.go | 16 --- src/syscall/syscall_unix.go | 8 +- src/syscall/syscall_windows.go | 4 +- 9 files changed, 87 insertions(+), 136 deletions(-) create mode 100644 src/internal/syscall/unix/net.go create mode 100644 src/internal/syscall/unix/net_js.go create mode 100644 src/internal/syscall/windows/net_windows.go diff --git a/api/next.txt b/api/next.txt index 9e4bb83cb7..cc4120b7ab 100644 --- a/api/next.txt +++ b/api/next.txt @@ -8,114 +8,6 @@ pkg runtime/debug, type BuildInfo struct, Settings []BuildSetting pkg runtime/debug, type BuildSetting struct pkg runtime/debug, type BuildSetting struct, Key string pkg runtime/debug, type BuildSetting struct, Value string -pkg syscall (darwin-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (darwin-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (darwin-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (darwin-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (darwin-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (darwin-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (darwin-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (darwin-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (freebsd-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (freebsd-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (freebsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (freebsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (freebsd-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (freebsd-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (freebsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (freebsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (freebsd-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (freebsd-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (freebsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (freebsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (freebsd-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (freebsd-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (freebsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (freebsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (freebsd-arm), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (freebsd-arm), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (freebsd-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (freebsd-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (freebsd-arm-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (freebsd-arm-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (freebsd-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (freebsd-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (linux-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (linux-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (linux-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (linux-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (linux-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (linux-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (linux-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (linux-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (linux-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (linux-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (linux-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (linux-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (linux-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (linux-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (linux-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (linux-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (linux-arm), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (linux-arm), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (linux-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (linux-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (linux-arm-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (linux-arm-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (linux-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (linux-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (netbsd-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (netbsd-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (netbsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (netbsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (netbsd-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (netbsd-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (netbsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (netbsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (netbsd-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (netbsd-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (netbsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (netbsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (netbsd-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (netbsd-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (netbsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (netbsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (netbsd-arm), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (netbsd-arm), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (netbsd-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (netbsd-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (netbsd-arm-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (netbsd-arm-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (netbsd-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (netbsd-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (netbsd-arm64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (netbsd-arm64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (netbsd-arm64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (netbsd-arm64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (netbsd-arm64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (netbsd-arm64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (netbsd-arm64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (netbsd-arm64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (openbsd-386), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (openbsd-386), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (openbsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (openbsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (openbsd-386-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (openbsd-386-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (openbsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (openbsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (openbsd-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (openbsd-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (openbsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (openbsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (openbsd-amd64-cgo), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error) -pkg syscall (openbsd-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error) -pkg syscall (openbsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error -pkg syscall (openbsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error -pkg syscall (windows-386), func WSASendtoInet4(Handle, *WSABuf, uint32, *uint32, uint32, SockaddrInet4, *Overlapped, *uint8) error -pkg syscall (windows-386), func WSASendtoInet6(Handle, *WSABuf, uint32, *uint32, uint32, SockaddrInet6, *Overlapped, *uint8) error -pkg syscall (windows-amd64), func WSASendtoInet4(Handle, *WSABuf, uint32, *uint32, uint32, SockaddrInet4, *Overlapped, *uint8) error -pkg syscall (windows-amd64), func WSASendtoInet6(Handle, *WSABuf, uint32, *uint32, uint32, SockaddrInet6, *Overlapped, *uint8) error pkg testing, func Fuzz(func(*F)) FuzzResult pkg testing, func MainStart(testDeps, []InternalTest, []InternalBenchmark, []InternalFuzzTarget, []InternalExample) *M pkg testing, func RunFuzzTargets(func(string, string) (bool, error), []InternalFuzzTarget) bool diff --git a/src/internal/poll/fd_unix.go b/src/internal/poll/fd_unix.go index d4c32e4d41..fd5ac85850 100644 --- a/src/internal/poll/fd_unix.go +++ b/src/internal/poll/fd_unix.go @@ -7,6 +7,7 @@ package poll import ( + "internal/syscall/unix" "io" "sync/atomic" "syscall" @@ -239,7 +240,7 @@ func (fd *FD) ReadFromInet4(p []byte, from *syscall.SockaddrInet4) (int, error) return 0, err } for { - n, err := syscall.RecvfromInet4(fd.Sysfd, p, 0, from) + n, err := unix.RecvfromInet4(fd.Sysfd, p, 0, from) if err != nil { if err == syscall.EINTR { continue @@ -266,7 +267,7 @@ func (fd *FD) ReadFromInet6(p []byte, from *syscall.SockaddrInet6) (int, error) return 0, err } for { - n, err := syscall.RecvfromInet6(fd.Sysfd, p, 0, from) + n, err := unix.RecvfromInet6(fd.Sysfd, p, 0, from) if err != nil { if err == syscall.EINTR { continue @@ -390,7 +391,7 @@ func (fd *FD) WriteToInet4(p []byte, sa syscall.SockaddrInet4) (int, error) { return 0, err } for { - err := syscall.SendtoInet4(fd.Sysfd, p, 0, sa) + err := unix.SendtoInet4(fd.Sysfd, p, 0, sa) if err == syscall.EINTR { continue } @@ -416,7 +417,7 @@ func (fd *FD) WriteToInet6(p []byte, sa syscall.SockaddrInet6) (int, error) { return 0, err } for { - err := syscall.SendtoInet6(fd.Sysfd, p, 0, sa) + err := unix.SendtoInet6(fd.Sysfd, p, 0, sa) if err == syscall.EINTR { continue } diff --git a/src/internal/poll/fd_windows.go b/src/internal/poll/fd_windows.go index d883cd1ecc..0f5ae8e0d4 100644 --- a/src/internal/poll/fd_windows.go +++ b/src/internal/poll/fd_windows.go @@ -870,7 +870,7 @@ func (fd *FD) WriteToInet4(buf []byte, sa4 syscall.SockaddrInet4) (int, error) { o.InitBuf(buf) o.sa4 = sa4 n, err := execIO(o, func(o *operation) error { - return syscall.WSASendtoInet4(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa4, &o.o, nil) + return windows.WSASendtoInet4(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa4, &o.o, nil) }) return n, err } @@ -885,7 +885,7 @@ func (fd *FD) WriteToInet4(buf []byte, sa4 syscall.SockaddrInet4) (int, error) { o.InitBuf(b) o.sa4 = sa4 n, err := execIO(o, func(o *operation) error { - return syscall.WSASendtoInet4(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa4, &o.o, nil) + return windows.WSASendtoInet4(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa4, &o.o, nil) }) ntotal += int(n) if err != nil { diff --git a/src/internal/syscall/unix/net.go b/src/internal/syscall/unix/net.go new file mode 100644 index 0000000000..773cf34d96 --- /dev/null +++ b/src/internal/syscall/unix/net.go @@ -0,0 +1,28 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris + +package unix + +import ( + "syscall" + _ "unsafe" +) + +//go:linkname RecvfromInet4 syscall.recvfromInet4 +//go:noescape +func RecvfromInet4(fd int, p []byte, flags int, from *syscall.SockaddrInet4) (int, error) + +//go:linkname RecvfromInet6 syscall.recvfromInet6 +//go:noescape +func RecvfromInet6(fd int, p []byte, flags int, from *syscall.SockaddrInet6) (n int, err error) + +//go:linkname SendtoInet4 syscall.sendtoInet4 +//go:noescape +func SendtoInet4(fd int, p []byte, flags int, to syscall.SockaddrInet4) (err error) + +//go:linkname SendtoInet6 syscall.sendtoInet6 +//go:noescape +func SendtoInet6(fd int, p []byte, flags int, to syscall.SockaddrInet6) (err error) diff --git a/src/internal/syscall/unix/net_js.go b/src/internal/syscall/unix/net_js.go new file mode 100644 index 0000000000..3fc5a66470 --- /dev/null +++ b/src/internal/syscall/unix/net_js.go @@ -0,0 +1,28 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build js + +package unix + +import ( + "syscall" + _ "unsafe" +) + +func RecvfromInet4(fd int, p []byte, flags int, from *syscall.SockaddrInet4) (int, error) { + return 0, syscall.ENOSYS +} + +func RecvfromInet6(fd int, p []byte, flags int, from *syscall.SockaddrInet6) (n int, err error) { + return 0, syscall.ENOSYS +} + +func SendtoInet4(fd int, p []byte, flags int, to syscall.SockaddrInet4) (err error) { + return syscall.ENOSYS +} + +func SendtoInet6(fd int, p []byte, flags int, to syscall.SockaddrInet6) (err error) { + return syscall.ENOSYS +} diff --git a/src/internal/syscall/windows/net_windows.go b/src/internal/syscall/windows/net_windows.go new file mode 100644 index 0000000000..1fccd55e4b --- /dev/null +++ b/src/internal/syscall/windows/net_windows.go @@ -0,0 +1,18 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package windows + +import ( + "syscall" + _ "unsafe" +) + +//go:linkname WSASendtoInet4 syscall.wsaSendtoInet4 +//go:noescape +func WSASendtoInet4(s syscall.Handle, bufs *syscall.WSABuf, bufcnt uint32, sent *uint32, flags uint32, to syscall.SockaddrInet4, overlapped *syscall.Overlapped, croutine *byte) (err error) + +//go:linkname WSASendtoInet6 syscall.wsaSendtoInet6 +//go:noescape +func WSASendtoInet6(s syscall.Handle, bufs *syscall.WSABuf, bufcnt uint32, sent *uint32, flags uint32, to syscall.SockaddrInet6, overlapped *syscall.Overlapped, croutine *byte) (err error) diff --git a/src/syscall/net_js.go b/src/syscall/net_js.go index 4f8258ddb3..253ab22dd9 100644 --- a/src/syscall/net_js.go +++ b/src/syscall/net_js.go @@ -91,26 +91,10 @@ func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) { return 0, nil, ENOSYS } -func RecvfromInet4(fd int, p []byte, flags int, from *SockaddrInet4) (n int, err error) { - return 0, ENOSYS -} - -func RecvfromInet6(fd int, p []byte, flags int, from *SockaddrInet6) (n int, err error) { - return 0, ENOSYS -} - func Sendto(fd int, p []byte, flags int, to Sockaddr) error { return ENOSYS } -func SendtoInet4(fd int, p []byte, flags int, to SockaddrInet4) error { - return ENOSYS -} - -func SendtoInet6(fd int, p []byte, flags int, to SockaddrInet6) error { - return ENOSYS -} - func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn, recvflags int, from Sockaddr, err error) { return 0, 0, 0, nil, ENOSYS } diff --git a/src/syscall/syscall_unix.go b/src/syscall/syscall_unix.go index 5a91a023e1..adc1e5dbfb 100644 --- a/src/syscall/syscall_unix.go +++ b/src/syscall/syscall_unix.go @@ -297,7 +297,7 @@ func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) { return } -func RecvfromInet4(fd int, p []byte, flags int, from *SockaddrInet4) (n int, err error) { +func recvfromInet4(fd int, p []byte, flags int, from *SockaddrInet4) (n int, err error) { var rsa RawSockaddrAny var socklen _Socklen = SizeofSockaddrAny if n, err = recvfrom(fd, p, flags, &rsa, &socklen); err != nil { @@ -310,7 +310,7 @@ func RecvfromInet4(fd int, p []byte, flags int, from *SockaddrInet4) (n int, err return } -func RecvfromInet6(fd int, p []byte, flags int, from *SockaddrInet6) (n int, err error) { +func recvfromInet6(fd int, p []byte, flags int, from *SockaddrInet6) (n int, err error) { var rsa RawSockaddrAny var socklen _Socklen = SizeofSockaddrAny if n, err = recvfrom(fd, p, flags, &rsa, &socklen); err != nil { @@ -324,7 +324,7 @@ func RecvfromInet6(fd int, p []byte, flags int, from *SockaddrInet6) (n int, err return } -func SendtoInet4(fd int, p []byte, flags int, to SockaddrInet4) (err error) { +func sendtoInet4(fd int, p []byte, flags int, to SockaddrInet4) (err error) { ptr, n, err := to.sockaddr() if err != nil { return err @@ -332,7 +332,7 @@ func SendtoInet4(fd int, p []byte, flags int, to SockaddrInet4) (err error) { return sendto(fd, p, flags, ptr, n) } -func SendtoInet6(fd int, p []byte, flags int, to SockaddrInet6) (err error) { +func sendtoInet6(fd int, p []byte, flags int, to SockaddrInet6) (err error) { ptr, n, err := to.sockaddr() if err != nil { return err diff --git a/src/syscall/syscall_windows.go b/src/syscall/syscall_windows.go index 0456074d47..48fedb33d7 100644 --- a/src/syscall/syscall_windows.go +++ b/src/syscall/syscall_windows.go @@ -922,7 +922,7 @@ func WSASendto(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32 return err } -func WSASendtoInet4(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to SockaddrInet4, overlapped *Overlapped, croutine *byte) (err error) { +func wsaSendtoInet4(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to SockaddrInet4, overlapped *Overlapped, croutine *byte) (err error) { rsa, len, err := to.sockaddr() if err != nil { return err @@ -938,7 +938,7 @@ func WSASendtoInet4(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags u return err } -func WSASendtoInet6(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to SockaddrInet6, overlapped *Overlapped, croutine *byte) (err error) { +func wsaSendtoInet6(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to SockaddrInet6, overlapped *Overlapped, croutine *byte) (err error) { rsa, len, err := to.sockaddr() if err != nil { return err -- GitLab From 1f368d5b860b178bcbd55dfeb64474295263516b Mon Sep 17 00:00:00 2001 From: Daniel Theophanes Date: Mon, 12 Jul 2021 09:25:04 -0500 Subject: [PATCH 1930/2500] database/sql: use errors.Is when checking ErrBadConn When drivers return driver.ErrBadConn, no meaningful information about what the cause of the problem is returned. Ideally the driver.ErrBadConn would be always caught with the retry loop, but this is not always the case. Drivers today must choose between returning a useful error and use the rety logic. This allows supporting both. Fixes #47142 Change-Id: I454573028f041dfdf874eed6c254fb194ccf6d96 Reviewed-on: https://go-review.googlesource.com/c/go/+/333949 Run-TryBot: Ian Lance Taylor Trust: Ian Lance Taylor Trust: Daniel Theophanes TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/database/sql/driver/driver.go | 3 ++ src/database/sql/fakedb_test.go | 27 ++++++++---- src/database/sql/sql.go | 69 ++++++++++++++++++------------- src/database/sql/sql_test.go | 2 +- 4 files changed, 64 insertions(+), 37 deletions(-) diff --git a/src/database/sql/driver/driver.go b/src/database/sql/driver/driver.go index f09396175a..ea1de5a8fb 100644 --- a/src/database/sql/driver/driver.go +++ b/src/database/sql/driver/driver.go @@ -156,6 +156,9 @@ var ErrSkip = errors.New("driver: skip fast-path; continue as if unimplemented") // if there's a possibility that the database server might have // performed the operation. Even if the server sends back an error, // you shouldn't return ErrBadConn. +// +// Errors will be checked using errors.Is. An error may +// wrap ErrBadConn or implement the Is(error) bool method. var ErrBadConn = errors.New("driver: bad connection") // Pinger is an optional interface that may be implemented by a Conn. diff --git a/src/database/sql/fakedb_test.go b/src/database/sql/fakedb_test.go index 4b68f1cba9..34e97e012b 100644 --- a/src/database/sql/fakedb_test.go +++ b/src/database/sql/fakedb_test.go @@ -96,6 +96,19 @@ type fakeDB struct { allowAny bool } +type fakeError struct { + Message string + Wrapped error +} + +func (err fakeError) Error() string { + return err.Message +} + +func (err fakeError) Unwrap() error { + return err.Wrapped +} + type table struct { mu sync.Mutex colname []string @@ -368,7 +381,7 @@ func (c *fakeConn) isDirtyAndMark() bool { func (c *fakeConn) Begin() (driver.Tx, error) { if c.isBad() { - return nil, driver.ErrBadConn + return nil, fakeError{Wrapped: driver.ErrBadConn} } if c.currTx != nil { return nil, errors.New("fakedb: already in a transaction") @@ -401,7 +414,7 @@ func (c *fakeConn) ResetSession(ctx context.Context) error { c.dirtySession = false c.currTx = nil if c.isBad() { - return driver.ErrBadConn + return fakeError{Message: "Reset Session: bad conn", Wrapped: driver.ErrBadConn} } return nil } @@ -629,7 +642,7 @@ func (c *fakeConn) PrepareContext(ctx context.Context, query string) (driver.Stm } if c.stickyBad || (hookPrepareBadConn != nil && hookPrepareBadConn()) { - return nil, driver.ErrBadConn + return nil, fakeError{Message: "Preapre: Sticky Bad", Wrapped: driver.ErrBadConn} } c.touchMem() @@ -756,7 +769,7 @@ func (s *fakeStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (d } if s.c.stickyBad || (hookExecBadConn != nil && hookExecBadConn()) { - return nil, driver.ErrBadConn + return nil, fakeError{Message: "Exec: Sticky Bad", Wrapped: driver.ErrBadConn} } if s.c.isDirtyAndMark() { return nil, errFakeConnSessionDirty @@ -870,7 +883,7 @@ func (s *fakeStmt) QueryContext(ctx context.Context, args []driver.NamedValue) ( } if s.c.stickyBad || (hookQueryBadConn != nil && hookQueryBadConn()) { - return nil, driver.ErrBadConn + return nil, fakeError{Message: "Query: Sticky Bad", Wrapped: driver.ErrBadConn} } if s.c.isDirtyAndMark() { return nil, errFakeConnSessionDirty @@ -1031,7 +1044,7 @@ var hookCommitBadConn func() bool func (tx *fakeTx) Commit() error { tx.c.currTx = nil if hookCommitBadConn != nil && hookCommitBadConn() { - return driver.ErrBadConn + return fakeError{Message: "Commit: Hook Bad Conn", Wrapped: driver.ErrBadConn} } tx.c.touchMem() return nil @@ -1043,7 +1056,7 @@ var hookRollbackBadConn func() bool func (tx *fakeTx) Rollback() error { tx.c.currTx = nil if hookRollbackBadConn != nil && hookRollbackBadConn() { - return driver.ErrBadConn + return fakeError{Message: "Rollback: Hook Bad Conn", Wrapped: driver.ErrBadConn} } tx.c.touchMem() return nil diff --git a/src/database/sql/sql.go b/src/database/sql/sql.go index e4a5a225b0..897bca059b 100644 --- a/src/database/sql/sql.go +++ b/src/database/sql/sql.go @@ -848,14 +848,15 @@ func (db *DB) pingDC(ctx context.Context, dc *driverConn, release func(error)) e func (db *DB) PingContext(ctx context.Context) error { var dc *driverConn var err error - + var isBadConn bool for i := 0; i < maxBadConnRetries; i++ { dc, err = db.conn(ctx, cachedOrNewConn) - if err != driver.ErrBadConn { + isBadConn = errors.Is(err, driver.ErrBadConn) + if !isBadConn { break } } - if err == driver.ErrBadConn { + if isBadConn { dc, err = db.conn(ctx, alwaysNewConn) } if err != nil { @@ -1317,9 +1318,9 @@ func (db *DB) conn(ctx context.Context, strategy connReuseStrategy) (*driverConn db.mu.Unlock() // Reset the session if required. - if err := conn.resetSession(ctx); err == driver.ErrBadConn { + if err := conn.resetSession(ctx); errors.Is(err, driver.ErrBadConn) { conn.Close() - return nil, driver.ErrBadConn + return nil, err } return conn, nil @@ -1381,9 +1382,9 @@ func (db *DB) conn(ctx context.Context, strategy connReuseStrategy) (*driverConn } // Reset the session if required. - if err := ret.conn.resetSession(ctx); err == driver.ErrBadConn { + if err := ret.conn.resetSession(ctx); errors.Is(err, driver.ErrBadConn) { ret.conn.Close() - return nil, driver.ErrBadConn + return nil, err } return ret.conn, ret.err } @@ -1442,7 +1443,7 @@ const debugGetPut = false // putConn adds a connection to the db's free pool. // err is optionally the last error that occurred on this connection. func (db *DB) putConn(dc *driverConn, err error, resetSession bool) { - if err != driver.ErrBadConn { + if !errors.Is(err, driver.ErrBadConn) { if !dc.validateConnection(resetSession) { err = driver.ErrBadConn } @@ -1456,7 +1457,7 @@ func (db *DB) putConn(dc *driverConn, err error, resetSession bool) { panic("sql: connection returned that was never out") } - if err != driver.ErrBadConn && dc.expired(db.maxLifetime) { + if !errors.Is(err, driver.ErrBadConn) && dc.expired(db.maxLifetime) { db.maxLifetimeClosed++ err = driver.ErrBadConn } @@ -1471,7 +1472,7 @@ func (db *DB) putConn(dc *driverConn, err error, resetSession bool) { } dc.onPut = nil - if err == driver.ErrBadConn { + if errors.Is(err, driver.ErrBadConn) { // Don't reuse bad connections. // Since the conn is considered bad and is being discarded, treat it // as closed. Don't decrement the open count here, finalClose will @@ -1551,13 +1552,15 @@ const maxBadConnRetries = 2 func (db *DB) PrepareContext(ctx context.Context, query string) (*Stmt, error) { var stmt *Stmt var err error + var isBadConn bool for i := 0; i < maxBadConnRetries; i++ { stmt, err = db.prepare(ctx, query, cachedOrNewConn) - if err != driver.ErrBadConn { + isBadConn = errors.Is(err, driver.ErrBadConn) + if !isBadConn { break } } - if err == driver.ErrBadConn { + if isBadConn { return db.prepare(ctx, query, alwaysNewConn) } return stmt, err @@ -1627,13 +1630,15 @@ func (db *DB) prepareDC(ctx context.Context, dc *driverConn, release func(error) func (db *DB) ExecContext(ctx context.Context, query string, args ...interface{}) (Result, error) { var res Result var err error + var isBadConn bool for i := 0; i < maxBadConnRetries; i++ { res, err = db.exec(ctx, query, args, cachedOrNewConn) - if err != driver.ErrBadConn { + isBadConn = errors.Is(err, driver.ErrBadConn) + if !isBadConn { break } } - if err == driver.ErrBadConn { + if isBadConn { return db.exec(ctx, query, args, alwaysNewConn) } return res, err @@ -1700,13 +1705,15 @@ func (db *DB) execDC(ctx context.Context, dc *driverConn, release func(error), q func (db *DB) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error) { var rows *Rows var err error + var isBadConn bool for i := 0; i < maxBadConnRetries; i++ { rows, err = db.query(ctx, query, args, cachedOrNewConn) - if err != driver.ErrBadConn { + isBadConn = errors.Is(err, driver.ErrBadConn) + if !isBadConn { break } } - if err == driver.ErrBadConn { + if isBadConn { return db.query(ctx, query, args, alwaysNewConn) } return rows, err @@ -1835,13 +1842,15 @@ func (db *DB) QueryRow(query string, args ...interface{}) *Row { func (db *DB) BeginTx(ctx context.Context, opts *TxOptions) (*Tx, error) { var tx *Tx var err error + var isBadConn bool for i := 0; i < maxBadConnRetries; i++ { tx, err = db.begin(ctx, opts, cachedOrNewConn) - if err != driver.ErrBadConn { + isBadConn = errors.Is(err, driver.ErrBadConn) + if !isBadConn { break } } - if err == driver.ErrBadConn { + if isBadConn { return db.begin(ctx, opts, alwaysNewConn) } return tx, err @@ -1914,13 +1923,15 @@ var ErrConnDone = errors.New("sql: connection is already closed") func (db *DB) Conn(ctx context.Context) (*Conn, error) { var dc *driverConn var err error + var isBadConn bool for i := 0; i < maxBadConnRetries; i++ { dc, err = db.conn(ctx, cachedOrNewConn) - if err != driver.ErrBadConn { + isBadConn = errors.Is(err, driver.ErrBadConn) + if !isBadConn { break } } - if err == driver.ErrBadConn { + if isBadConn { dc, err = db.conn(ctx, alwaysNewConn) } if err != nil { @@ -2032,8 +2043,8 @@ func (c *Conn) PrepareContext(ctx context.Context, query string) (*Stmt, error) // Raw executes f exposing the underlying driver connection for the // duration of f. The driverConn must not be used outside of f. // -// Once f returns and err is not equal to driver.ErrBadConn, the Conn will -// continue to be usable until Conn.Close is called. +// Once f returns and err is not driver.ErrBadConn, the Conn will continue to be usable +// until Conn.Close is called. func (c *Conn) Raw(f func(driverConn interface{}) error) (err error) { var dc *driverConn var release releaseConn @@ -2084,7 +2095,7 @@ func (c *Conn) BeginTx(ctx context.Context, opts *TxOptions) (*Tx, error) { // as the sql operation is done with the dc. func (c *Conn) closemuRUnlockCondReleaseConn(err error) { c.closemu.RUnlock() - if err == driver.ErrBadConn { + if errors.Is(err, driver.ErrBadConn) { c.close(err) } } @@ -2278,7 +2289,7 @@ func (tx *Tx) Commit() error { withLock(tx.dc, func() { err = tx.txi.Commit() }) - if err != driver.ErrBadConn { + if !errors.Is(err, driver.ErrBadConn) { tx.closePrepared() } tx.close(err) @@ -2310,7 +2321,7 @@ func (tx *Tx) rollback(discardConn bool) error { withLock(tx.dc, func() { err = tx.txi.Rollback() }) - if err != driver.ErrBadConn { + if !errors.Is(err, driver.ErrBadConn) { tx.closePrepared() } if discardConn { @@ -2616,7 +2627,7 @@ func (s *Stmt) ExecContext(ctx context.Context, args ...interface{}) (Result, er } dc, releaseConn, ds, err := s.connStmt(ctx, strategy) if err != nil { - if err == driver.ErrBadConn { + if errors.Is(err, driver.ErrBadConn) { continue } return nil, err @@ -2624,7 +2635,7 @@ func (s *Stmt) ExecContext(ctx context.Context, args ...interface{}) (Result, er res, err = resultFromStatement(ctx, dc.ci, ds, args...) releaseConn(err) - if err != driver.ErrBadConn { + if !errors.Is(err, driver.ErrBadConn) { return res, err } } @@ -2764,7 +2775,7 @@ func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, er } dc, releaseConn, ds, err := s.connStmt(ctx, strategy) if err != nil { - if err == driver.ErrBadConn { + if errors.Is(err, driver.ErrBadConn) { continue } return nil, err @@ -2798,7 +2809,7 @@ func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, er } releaseConn(err) - if err != driver.ErrBadConn { + if !errors.Is(err, driver.ErrBadConn) { return nil, err } } diff --git a/src/database/sql/sql_test.go b/src/database/sql/sql_test.go index 15c30e0d00..889adc3164 100644 --- a/src/database/sql/sql_test.go +++ b/src/database/sql/sql_test.go @@ -3159,7 +3159,7 @@ func TestTxEndBadConn(t *testing.T) { return broken } - if err := op(); err != driver.ErrBadConn { + if err := op(); !errors.Is(err, driver.ErrBadConn) { t.Errorf(name+": %v", err) return } -- GitLab From 283373d124b39be62fb4dc0349ddf0cb1c99aeb7 Mon Sep 17 00:00:00 2001 From: Mostafa Solati Date: Tue, 3 Aug 2021 21:39:29 +0430 Subject: [PATCH 1931/2500] database/sql: fix tx.Prepare documentation Fixes: #45978 Change-Id: I3d5ccd621d670f97bb1a642b4e84b6629347a315 Reviewed-on: https://go-review.googlesource.com/c/go/+/339291 Reviewed-by: Daniel Theophanes Trust: Cherry Mui --- src/database/sql/sql.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/database/sql/sql.go b/src/database/sql/sql.go index 897bca059b..5131c08b51 100644 --- a/src/database/sql/sql.go +++ b/src/database/sql/sql.go @@ -2364,8 +2364,8 @@ func (tx *Tx) PrepareContext(ctx context.Context, query string) (*Stmt, error) { // Prepare creates a prepared statement for use within a transaction. // -// The returned statement operates within the transaction and can no longer -// be used once the transaction has been committed or rolled back. +// The returned statement operates within the transaction and will be closed +// when the transaction has been committed or rolled back. // // To use an existing prepared statement on this transaction, see Tx.Stmt. // -- GitLab From fa19146038e0e94480c93d43e2a8306c419d5119 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Wed, 3 Nov 2021 16:18:36 +0100 Subject: [PATCH 1932/2500] net/netip: fix various typos in comments Change-Id: I67998f70969ac6e6ff1b52a56e49a61ef167ed50 Reviewed-on: https://go-review.googlesource.com/c/go/+/361055 Trust: Jason A. Donenfeld Run-TryBot: Jason A. Donenfeld TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/net/netip/netip.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/net/netip/netip.go b/src/net/netip/netip.go index 4ef3b4bb68..d15a4947ac 100644 --- a/src/net/netip/netip.go +++ b/src/net/netip/netip.go @@ -4,7 +4,7 @@ // Package netip defines a IP address type that's a small value type. // Building on that Addr type, the package also defines AddrPort (an -// IP address and a port), and Prefix (a IP address and a bit length +// IP address and a port), and Prefix (an IP address and a bit length // prefix). // // Compared to the net.IP type, this package's Addr type takes less @@ -1184,7 +1184,7 @@ type Prefix struct { // bits is logically a uint8 (storing [0,128]) but also // encodes an "invalid" bit, currently represented by the // invalidPrefixBits sentinel value. It could be packed into - // the uint8 more with more comlicated expressions in the + // the uint8 more with more complicated expressions in the // accessors, but the extra byte (in padding anyway) doesn't // hurt and simplifies code below. bits int16 @@ -1195,7 +1195,7 @@ type Prefix struct { // public API. const invalidPrefixBits = -1 -// PrefixFrom returns an Prefix with the provided IP address and bit +// PrefixFrom returns a Prefix with the provided IP address and bit // prefix length. // // It does not allocate. Unlike Addr.Prefix, PrefixFrom does not mask @@ -1222,7 +1222,7 @@ func (p Prefix) Addr() Addr { return p.ip } // It reports -1 if invalid. func (p Prefix) Bits() int { return int(p.bits) } -// IsValid reports whether whether p.Bits() has a valid range for p.IP(). +// IsValid reports whether p.Bits() has a valid range for p.IP(). // If p.Addr() is the zero Addr, IsValid returns false. // Note that if p is the zero Prefix, then p.IsValid() == false. func (p Prefix) IsValid() bool { return !p.ip.isZero() && p.bits >= 0 && int(p.bits) <= p.ip.BitLen() } -- GitLab From 604963052072d7895138c78751c477cf25625e7d Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Wed, 3 Nov 2021 13:54:08 -0700 Subject: [PATCH 1933/2500] internal/poll: remove alloc sending IPv6 UDP on Windows This was an oversight in CL 331511. Change-Id: Ibc20bf6ea80a8675d43d9691ed551dffab1d9215 Reviewed-on: https://go-review.googlesource.com/c/go/+/361254 Trust: Josh Bleecher Snyder Trust: Brad Fitzpatrick Run-TryBot: Josh Bleecher Snyder Reviewed-by: Brad Fitzpatrick TryBot-Result: Go Bot --- src/internal/poll/fd_windows.go | 42 +++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/src/internal/poll/fd_windows.go b/src/internal/poll/fd_windows.go index 0f5ae8e0d4..139f78a7c1 100644 --- a/src/internal/poll/fd_windows.go +++ b/src/internal/poll/fd_windows.go @@ -857,7 +857,7 @@ func (fd *FD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) { return ntotal, nil } -// WriteTo wraps the sendto network call for IPv4. +// WriteToInet4 is WriteTo, specialized for syscall.SockaddrInet4. func (fd *FD) WriteToInet4(buf []byte, sa4 syscall.SockaddrInet4) (int, error) { if err := fd.writeLock(); err != nil { return 0, err @@ -896,9 +896,43 @@ func (fd *FD) WriteToInet4(buf []byte, sa4 syscall.SockaddrInet4) (int, error) { return ntotal, nil } -// WriteTo wraps the sendto network call for IPv6. -func (fd *FD) WriteToInet6(buf []byte, sa syscall.SockaddrInet6) (int, error) { - return fd.WriteTo(buf, &sa) +// WriteToInet6 is WriteTo, specialized for syscall.SockaddrInet6. +func (fd *FD) WriteToInet6(buf []byte, sa6 syscall.SockaddrInet6) (int, error) { + if err := fd.writeLock(); err != nil { + return 0, err + } + defer fd.writeUnlock() + + if len(buf) == 0 { + // handle zero-byte payload + o := &fd.wop + o.InitBuf(buf) + o.sa6 = sa6 + n, err := execIO(o, func(o *operation) error { + return windows.WSASendtoInet6(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa6, &o.o, nil) + }) + return n, err + } + + ntotal := 0 + for len(buf) > 0 { + b := buf + if len(b) > maxRW { + b = b[:maxRW] + } + o := &fd.wop + o.InitBuf(b) + o.sa6 = sa6 + n, err := execIO(o, func(o *operation) error { + return windows.WSASendtoInet6(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa6, &o.o, nil) + }) + ntotal += int(n) + if err != nil { + return ntotal, err + } + buf = buf[n:] + } + return ntotal, nil } // Call ConnectEx. This doesn't need any locking, since it is only -- GitLab From be0cd9e5ec01141def07412b0ef3fa0d3f8cba9d Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 2 Nov 2021 11:59:56 -0700 Subject: [PATCH 1934/2500] syscall: unify unix Sendmsg prologues These were identical. This is a preliminary step towards remove allocs per UDP send. Change-Id: I21e1264c7d4747baa626ddb93afff4c1cf225d13 Reviewed-on: https://go-review.googlesource.com/c/go/+/361256 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/syscall/syscall_aix.go | 15 +-------------- src/syscall/syscall_bsd.go | 15 +-------------- src/syscall/syscall_linux.go | 16 +--------------- src/syscall/syscall_solaris.go | 15 +-------------- src/syscall/syscall_unix.go | 17 +++++++++++++++++ 5 files changed, 21 insertions(+), 57 deletions(-) diff --git a/src/syscall/syscall_aix.go b/src/syscall/syscall_aix.go index f3b160cae4..36172cc678 100644 --- a/src/syscall/syscall_aix.go +++ b/src/syscall/syscall_aix.go @@ -360,20 +360,7 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from return } -func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { - _, err = SendmsgN(fd, p, oob, to, flags) - return -} - -func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { - var ptr unsafe.Pointer - var salen _Socklen - if to != nil { - ptr, salen, err = to.sockaddr() - if err != nil { - return 0, err - } - } +func sendmsgN(fd int, p, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) { var msg Msghdr msg.Name = (*byte)(unsafe.Pointer(ptr)) msg.Namelen = uint32(salen) diff --git a/src/syscall/syscall_bsd.go b/src/syscall/syscall_bsd.go index 8945661300..71a331d6c0 100644 --- a/src/syscall/syscall_bsd.go +++ b/src/syscall/syscall_bsd.go @@ -394,20 +394,7 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from //sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) -func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { - _, err = SendmsgN(fd, p, oob, to, flags) - return -} - -func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { - var ptr unsafe.Pointer - var salen _Socklen - if to != nil { - ptr, salen, err = to.sockaddr() - if err != nil { - return 0, err - } - } +func sendmsgN(fd int, p, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) { var msg Msghdr msg.Name = (*byte)(unsafe.Pointer(ptr)) msg.Namelen = uint32(salen) diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go index 1c6033bbab..695ce2b198 100644 --- a/src/syscall/syscall_linux.go +++ b/src/syscall/syscall_linux.go @@ -679,21 +679,7 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from return } -func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { - _, err = SendmsgN(fd, p, oob, to, flags) - return -} - -func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { - var ptr unsafe.Pointer - var salen _Socklen - if to != nil { - var err error - ptr, salen, err = to.sockaddr() - if err != nil { - return 0, err - } - } +func sendmsgN(fd int, p, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) { var msg Msghdr msg.Name = (*byte)(ptr) msg.Namelen = uint32(salen) diff --git a/src/syscall/syscall_solaris.go b/src/syscall/syscall_solaris.go index 13616fca9d..15b3c2bb40 100644 --- a/src/syscall/syscall_solaris.go +++ b/src/syscall/syscall_solaris.go @@ -365,22 +365,9 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from return } -func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { - _, err = SendmsgN(fd, p, oob, to, flags) - return -} - //sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_sendmsg -func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { - var ptr unsafe.Pointer - var salen _Socklen - if to != nil { - ptr, salen, err = to.sockaddr() - if err != nil { - return 0, err - } - } +func sendmsgN(fd int, p, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) { var msg Msghdr msg.Name = (*byte)(unsafe.Pointer(ptr)) msg.Namelen = uint32(salen) diff --git a/src/syscall/syscall_unix.go b/src/syscall/syscall_unix.go index adc1e5dbfb..2837c976e3 100644 --- a/src/syscall/syscall_unix.go +++ b/src/syscall/syscall_unix.go @@ -324,6 +324,23 @@ func recvfromInet6(fd int, p []byte, flags int, from *SockaddrInet6) (n int, err return } +func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { + _, err = SendmsgN(fd, p, oob, to, flags) + return +} + +func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { + var ptr unsafe.Pointer + var salen _Socklen + if to != nil { + ptr, salen, err = to.sockaddr() + if err != nil { + return 0, err + } + } + return sendmsgN(fd, p, oob, ptr, salen, flags) +} + func sendtoInet4(fd int, p []byte, flags int, to SockaddrInet4) (err error) { ptr, n, err := to.sockaddr() if err != nil { -- GitLab From 91962dfde1a754a0ccdc514c9a2acfae25fc1f5e Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 2 Nov 2021 12:25:23 -0700 Subject: [PATCH 1935/2500] syscall: unify unix Recvmsg epilogues These were identical. This is a preliminary step towards remove allocs per UDP receive. Change-Id: I83106cd3f1fe4bc5bae2d1b0ebd23eedd820abed Reviewed-on: https://go-review.googlesource.com/c/go/+/361258 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/syscall/syscall_aix.go | 9 ++------- src/syscall/syscall_bsd.go | 9 ++------- src/syscall/syscall_linux.go | 9 ++------- src/syscall/syscall_solaris.go | 9 ++------- src/syscall/syscall_unix.go | 10 ++++++++++ 5 files changed, 18 insertions(+), 28 deletions(-) diff --git a/src/syscall/syscall_aix.go b/src/syscall/syscall_aix.go index 36172cc678..0f5101999f 100644 --- a/src/syscall/syscall_aix.go +++ b/src/syscall/syscall_aix.go @@ -321,10 +321,9 @@ func Accept(fd int) (nfd int, sa Sockaddr, err error) { return } -func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { +func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) { var msg Msghdr - var rsa RawSockaddrAny - msg.Name = (*byte)(unsafe.Pointer(&rsa)) + msg.Name = (*byte)(unsafe.Pointer(rsa)) msg.Namelen = uint32(SizeofSockaddrAny) var iov Iovec if len(p) > 0 { @@ -353,10 +352,6 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from } oobn = int(msg.Controllen) recvflags = int(msg.Flags) - // source address is only specified if the socket is unconnected - if rsa.Addr.Family != AF_UNSPEC { - from, err = anyToSockaddr(&rsa) - } return } diff --git a/src/syscall/syscall_bsd.go b/src/syscall/syscall_bsd.go index 71a331d6c0..5e636d5258 100644 --- a/src/syscall/syscall_bsd.go +++ b/src/syscall/syscall_bsd.go @@ -358,10 +358,9 @@ func GetsockoptICMPv6Filter(fd, level, opt int) (*ICMPv6Filter, error) { //sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) //sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) -func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { +func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) { var msg Msghdr - var rsa RawSockaddrAny - msg.Name = (*byte)(unsafe.Pointer(&rsa)) + msg.Name = (*byte)(unsafe.Pointer(rsa)) msg.Namelen = uint32(SizeofSockaddrAny) var iov Iovec if len(p) > 0 { @@ -385,10 +384,6 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from } oobn = int(msg.Controllen) recvflags = int(msg.Flags) - // source address is only specified if the socket is unconnected - if rsa.Addr.Family != AF_UNSPEC { - from, err = anyToSockaddr(&rsa) - } return } diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go index 695ce2b198..c002299641 100644 --- a/src/syscall/syscall_linux.go +++ b/src/syscall/syscall_linux.go @@ -638,10 +638,9 @@ func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) { return setsockopt(fd, level, opt, unsafe.Pointer(mreq), unsafe.Sizeof(*mreq)) } -func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { +func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) { var msg Msghdr - var rsa RawSockaddrAny - msg.Name = (*byte)(unsafe.Pointer(&rsa)) + msg.Name = (*byte)(unsafe.Pointer(rsa)) msg.Namelen = uint32(SizeofSockaddrAny) var iov Iovec if len(p) > 0 { @@ -672,10 +671,6 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from } oobn = int(msg.Controllen) recvflags = int(msg.Flags) - // source address is only specified if the socket is unconnected - if rsa.Addr.Family != AF_UNSPEC { - from, err = anyToSockaddr(&rsa) - } return } diff --git a/src/syscall/syscall_solaris.go b/src/syscall/syscall_solaris.go index 15b3c2bb40..5f12f229c4 100644 --- a/src/syscall/syscall_solaris.go +++ b/src/syscall/syscall_solaris.go @@ -332,10 +332,9 @@ func Accept(fd int) (nfd int, sa Sockaddr, err error) { return } -func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { +func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) { var msg Msghdr - var rsa RawSockaddrAny - msg.Name = (*byte)(unsafe.Pointer(&rsa)) + msg.Name = (*byte)(unsafe.Pointer(rsa)) msg.Namelen = uint32(SizeofSockaddrAny) var iov Iovec if len(p) > 0 { @@ -358,10 +357,6 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from return } oobn = int(msg.Accrightslen) - // source address is only specified if the socket is unconnected - if rsa.Addr.Family != AF_UNSPEC { - from, err = anyToSockaddr(&rsa) - } return } diff --git a/src/syscall/syscall_unix.go b/src/syscall/syscall_unix.go index 2837c976e3..d1ecc361c6 100644 --- a/src/syscall/syscall_unix.go +++ b/src/syscall/syscall_unix.go @@ -324,6 +324,16 @@ func recvfromInet6(fd int, p []byte, flags int, from *SockaddrInet6) (n int, err return } +func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { + var rsa RawSockaddrAny + n, oobn, recvflags, err = recvmsgRaw(fd, p, oob, flags, &rsa) + // source address is only specified if the socket is unconnected + if rsa.Addr.Family != AF_UNSPEC { + from, err = anyToSockaddr(&rsa) + } + return +} + func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { _, err = SendmsgN(fd, p, oob, to, flags) return -- GitLab From 9cf671106721451af4a556dc0bf56c133836d008 Mon Sep 17 00:00:00 2001 From: Zvonimir Pavlinovic Date: Wed, 3 Nov 2021 16:31:11 -0700 Subject: [PATCH 1936/2500] cmd/cover: use fmt.Print for newline-ending fixed string This redundancy is now caught by the improved printf vet checker (golang/go#30436). Updates #49322 Change-Id: Id450247adc6fa28a9244c019be3c1b52c2d17f49 Reviewed-on: https://go-review.googlesource.com/c/go/+/361263 Run-TryBot: Zvonimir Pavlinovic TryBot-Result: Go Bot Trust: Zvonimir Pavlinovic Reviewed-by: Dmitri Shuralyov --- src/cmd/cover/cover.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/cover/cover.go b/src/cmd/cover/cover.go index 7ee000861b..9c8529f7eb 100644 --- a/src/cmd/cover/cover.go +++ b/src/cmd/cover/cover.go @@ -40,8 +40,8 @@ Finally, to generate modified source code with coverage annotations ` func usage() { - fmt.Fprintln(os.Stderr, usageMessage) - fmt.Fprintln(os.Stderr, "Flags:") + fmt.Fprint(os.Stderr, usageMessage) + fmt.Fprintln(os.Stderr, "\nFlags:") flag.PrintDefaults() fmt.Fprintln(os.Stderr, "\n Only one of -html, -func, or -mode may be set.") os.Exit(2) -- GitLab From a419f2f5c364031e2f65a9f031e8bb52e9c22fc9 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 3 Nov 2021 14:58:59 -0700 Subject: [PATCH 1937/2500] cmd/compile/internal/syntax: better error message when type parameters are not permitted Fixes #48382. Change-Id: I215896a4429839c41c9136b6922b1b748ed47734 Reviewed-on: https://go-review.googlesource.com/c/go/+/361259 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/syntax/parser.go | 45 ++++++++++++------- .../internal/syntax/testdata/issue48382.go2 | 15 +++++++ 2 files changed, 43 insertions(+), 17 deletions(-) create mode 100644 src/cmd/compile/internal/syntax/testdata/issue48382.go2 diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index 9f02cb6c2c..770175fe54 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -708,15 +708,7 @@ func (p *parser) funcDeclOrNil() *FuncDecl { } f.Name = p.name() - if p.allowGenerics() && p.got(_Lbrack) { - if p.tok == _Rbrack { - p.syntaxError("empty type parameter list") - p.next() - } else { - f.TParamList = p.paramList(nil, _Rbrack, true) - } - } - f.Type = p.funcType() + f.TParamList, f.Type = p.funcType("") if p.tok == _Lbrace { f.Body = p.funcBody() } @@ -944,7 +936,7 @@ func (p *parser) operand(keep_parens bool) Expr { case _Func: pos := p.pos() p.next() - ftyp := p.funcType() + _, ftyp := p.funcType("function literal") if p.tok == _Lbrace { p.xnest++ @@ -1284,7 +1276,8 @@ func (p *parser) typeOrNil() Expr { case _Func: // fntype p.next() - return p.funcType() + _, t := p.funcType("function type") + return t case _Lbrack: // '[' oexpr ']' ntype @@ -1357,18 +1350,34 @@ func (p *parser) typeInstance(typ Expr) Expr { return x } -func (p *parser) funcType() *FuncType { +// If context != "", type parameters are not permitted. +func (p *parser) funcType(context string) ([]*Field, *FuncType) { if trace { defer p.trace("funcType")() } typ := new(FuncType) typ.pos = p.pos() + + var tparamList []*Field + if p.allowGenerics() && p.got(_Lbrack) { + if context != "" { + // accept but complain + p.syntaxErrorAt(typ.pos, context+" cannot have type parameters") + } + if p.tok == _Rbrack { + p.syntaxError("empty type parameter list") + p.next() + } else { + tparamList = p.paramList(nil, _Rbrack, true) + } + } + p.want(_Lparen) typ.ParamList = p.paramList(nil, _Rparen, false) typ.ResultList = p.funcResult() - return typ + return tparamList, typ } // "[" has already been consumed, and pos is its position. @@ -1697,11 +1706,13 @@ func (p *parser) methodDecl() *Field { // already progressed, no need to advance } + const context = "interface method" + switch p.tok { case _Lparen: // method f.Name = name - f.Type = p.funcType() + _, f.Type = p.funcType(context) case _Lbrack: if p.allowGenerics() { @@ -1721,7 +1732,7 @@ func (p *parser) methodDecl() *Field { // name[]( p.errorAt(pos, "empty type parameter list") f.Name = name - f.Type = p.funcType() + _, f.Type = p.funcType(context) } else { p.errorAt(pos, "empty type argument list") f.Type = name @@ -1738,7 +1749,7 @@ func (p *parser) methodDecl() *Field { // as if [] were absent. if p.tok == _Lparen { f.Name = name - f.Type = p.funcType() + _, f.Type = p.funcType(context) } else { f.Type = name } @@ -1749,7 +1760,7 @@ func (p *parser) methodDecl() *Field { if list[0].Name != nil { // generic method f.Name = name - f.Type = p.funcType() + _, f.Type = p.funcType(context) // TODO(gri) Record list as type parameter list with f.Type // if we want to type-check the generic method. // For now, report an error so this is not a silent event. diff --git a/src/cmd/compile/internal/syntax/testdata/issue48382.go2 b/src/cmd/compile/internal/syntax/testdata/issue48382.go2 new file mode 100644 index 0000000000..1e8f4b0ec6 --- /dev/null +++ b/src/cmd/compile/internal/syntax/testdata/issue48382.go2 @@ -0,0 +1,15 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type _ func /* ERROR function type cannot have type parameters */ [ /* ERROR empty type parameter list */ ]() +type _ func /* ERROR function type cannot have type parameters */ [ x /* ERROR missing type constraint */ ]() +type _ func /* ERROR function type cannot have type parameters */ [P any]() + +var _ = func /* ERROR function literal cannot have type parameters */ [P any]() {} + +type _ interface{ + m /* ERROR interface method cannot have type parameters */ [P any]() +} -- GitLab From 1292e212416f5bca1f32d3ec0679b7dae97f6f1b Mon Sep 17 00:00:00 2001 From: Zvonimir Pavlinovic Date: Wed, 3 Nov 2021 16:44:44 -0700 Subject: [PATCH 1938/2500] cmd/trace: use fmt.Print for newline-ending fixed string This redundancy is now caught by the improved printf vet checker. Updates #49322 Change-Id: Ic7a931b8d4838be02ebb855b69624b95093bd114 Reviewed-on: https://go-review.googlesource.com/c/go/+/361265 Run-TryBot: Zvonimir Pavlinovic TryBot-Result: Go Bot Trust: Zvonimir Pavlinovic Reviewed-by: Ian Lance Taylor --- src/cmd/trace/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/trace/main.go b/src/cmd/trace/main.go index f94586abf3..3aeba223ee 100644 --- a/src/cmd/trace/main.go +++ b/src/cmd/trace/main.go @@ -66,7 +66,7 @@ var ( func main() { flag.Usage = func() { - fmt.Fprintln(os.Stderr, usageMessage) + fmt.Fprint(os.Stderr, usageMessage) os.Exit(2) } flag.Parse() -- GitLab From e72d7150cb7f62edf6768ac5f33194d7f96443a1 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 2 Nov 2021 19:49:15 -0400 Subject: [PATCH 1939/2500] go/types: remove qualification from type parameter strings Type parameters only exist within the scope of a type or function declaration, so there is really no reason to package-qualify them. It is also confusing to do so, as it makes their type string look like a defined type. Fixes #49215 Change-Id: I986c527e78d45f3cadd75bc3b244e23dabe707ee Reviewed-on: https://go-review.googlesource.com/c/go/+/360938 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/api_test.go | 12 ++++++------ src/go/types/builtins_test.go | 6 +++--- src/go/types/typestring.go | 4 ---- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index 34cc61fc2c..807bffbff6 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -345,18 +345,18 @@ func TestTypesInfo(t *testing.T) { {broken + `x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string][-1]int`}, // parameterized functions - {genericPkg + `p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[generic_p0.T interface{}](generic_p0.T)`}, + {genericPkg + `p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[T interface{}](T)`}, {genericPkg + `p1; func f[T any](T) {}; var _ = f[int]`, `f[int]`, `func(int)`}, {genericPkg + `p2; func f[T any](T) {}; func _() { f(42) }`, `f`, `func(int)`}, {genericPkg + `p3; func f[T any](T) {}; func _() { f[int](42) }`, `f[int]`, `func(int)`}, - {genericPkg + `p4; func f[T any](T) {}; func _() { f[int](42) }`, `f`, `func[generic_p4.T interface{}](generic_p4.T)`}, + {genericPkg + `p4; func f[T any](T) {}; func _() { f[int](42) }`, `f`, `func[T interface{}](T)`}, {genericPkg + `p5; func f[T any](T) {}; func _() { f(42) }`, `f(42)`, `()`}, // type parameters {genericPkg + `t0; type t[] int; var _ t`, `t`, `generic_t0.t`}, // t[] is a syntax error that is ignored in this test in favor of t - {genericPkg + `t1; type t[P any] int; var _ t[int]`, `t`, `generic_t1.t[generic_t1.P interface{}]`}, - {genericPkg + `t2; type t[P interface{}] int; var _ t[int]`, `t`, `generic_t2.t[generic_t2.P interface{}]`}, - {genericPkg + `t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `generic_t3.t[generic_t3.P, generic_t3.Q interface{}]`}, + {genericPkg + `t1; type t[P any] int; var _ t[int]`, `t`, `generic_t1.t[P interface{}]`}, + {genericPkg + `t2; type t[P interface{}] int; var _ t[int]`, `t`, `generic_t2.t[P interface{}]`}, + {genericPkg + `t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `generic_t3.t[P, Q interface{}]`}, // TODO (rFindley): compare with types2, which resolves the type broken_t4.t[P₁, Q₂ interface{m()}] here {broken + `t4; type t[P, Q interface{ m() }] int; var _ t[int, int]`, `t`, `broken_t4.t`}, @@ -365,7 +365,7 @@ func TestTypesInfo(t *testing.T) { {genericPkg + `g0; type t[P any] int; var x struct{ f t[int] }; var _ = x.f`, `x.f`, `generic_g0.t[int]`}, // issue 45096 - {genericPkg + `issue45096; func _[T interface{ ~int8 | ~int16 | ~int32 }](x T) { _ = x < 0 }`, `0`, `generic_issue45096.T`}, + {genericPkg + `issue45096; func _[T interface{ ~int8 | ~int16 | ~int32 }](x T) { _ = x < 0 }`, `0`, `T`}, // issue 47895 {`package p; import "unsafe"; type S struct { f int }; var s S; var _ = unsafe.Offsetof(s.f)`, `s.f`, `int`}, diff --git a/src/go/types/builtins_test.go b/src/go/types/builtins_test.go index db56aea3fe..edcd7e7724 100644 --- a/src/go/types/builtins_test.go +++ b/src/go/types/builtins_test.go @@ -113,15 +113,15 @@ var builtinCalls = []struct { {"Alignof", `_ = unsafe.Alignof(0)`, `invalid type`}, // constant {"Alignof", `var x struct{}; _ = unsafe.Alignof(x)`, `invalid type`}, // constant - {"Alignof", `var x P; _ = unsafe.Alignof(x)`, `func(p.P) uintptr`}, + {"Alignof", `var x P; _ = unsafe.Alignof(x)`, `func(P) uintptr`}, {"Offsetof", `var x struct{f bool}; _ = unsafe.Offsetof(x.f)`, `invalid type`}, // constant {"Offsetof", `var x struct{_ int; f bool}; _ = unsafe.Offsetof((&x).f)`, `invalid type`}, // constant - {"Offsetof", `var x struct{_ int; f P}; _ = unsafe.Offsetof((&x).f)`, `func(p.P) uintptr`}, + {"Offsetof", `var x struct{_ int; f P}; _ = unsafe.Offsetof((&x).f)`, `func(P) uintptr`}, {"Sizeof", `_ = unsafe.Sizeof(0)`, `invalid type`}, // constant {"Sizeof", `var x struct{}; _ = unsafe.Sizeof(x)`, `invalid type`}, // constant - {"Sizeof", `var x P; _ = unsafe.Sizeof(x)`, `func(p.P) uintptr`}, + {"Sizeof", `var x P; _ = unsafe.Sizeof(x)`, `func(P) uintptr`}, {"Slice", `var p *int; _ = unsafe.Slice(p, 1)`, `func(*int, int) []int`}, {"Slice", `var p *byte; var n uintptr; _ = unsafe.Slice(p, n)`, `func(*byte, uintptr) []byte`}, diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 40a8ff475d..e138af6488 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -274,10 +274,6 @@ func (w *typeWriter) typ(typ Type) { w.error("unnamed type parameter") break } - // Optionally write out package for typeparams (like Named). - if t.obj.pkg != nil { - writePackage(w.buf, t.obj.pkg, w.qf) - } w.string(t.obj.name) if w.debug || w.ctxt != nil { w.string(subscript(t.id)) -- GitLab From 240df188d67edc3df498a77bf99d3152244c14ab Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 3 Nov 2021 15:29:43 -0700 Subject: [PATCH 1940/2500] cmd/compile: add extra test for the non-mono pass Just add a test for another function that is not monomorphisable, which comes from the Featherweight Go paper. Updates #48018 Change-Id: I664e3f48412b02678e32b50204dc4befae90374c Reviewed-on: https://go-review.googlesource.com/c/go/+/361262 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- .../types2/testdata/fixedbugs/issue48018.go2 | 20 +++++++++++++++++++ .../types/testdata/fixedbugs/issue48018.go2 | 20 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue48018.go2 create mode 100644 src/go/types/testdata/fixedbugs/issue48018.go2 diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48018.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48018.go2 new file mode 100644 index 0000000000..e6ccc6b9be --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48018.go2 @@ -0,0 +1,20 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type Box[A any] struct { + value A +} + +func Nest[A /* ERROR instantiation cycle */ any](b Box[A], n int) interface{} { + if n == 0 { + return b + } + return Nest(Box[Box[A]]{b}, n-1) +} + +func main() { + Nest(Box[int]{0}, 10) +} diff --git a/src/go/types/testdata/fixedbugs/issue48018.go2 b/src/go/types/testdata/fixedbugs/issue48018.go2 new file mode 100644 index 0000000000..e6ccc6b9be --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue48018.go2 @@ -0,0 +1,20 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type Box[A any] struct { + value A +} + +func Nest[A /* ERROR instantiation cycle */ any](b Box[A], n int) interface{} { + if n == 0 { + return b + } + return Nest(Box[Box[A]]{b}, n-1) +} + +func main() { + Nest(Box[int]{0}, 10) +} -- GitLab From d9bb5f6f109a4342c52958f30acfc3f3d633ee4f Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Wed, 3 Nov 2021 18:18:18 +0000 Subject: [PATCH 1941/2500] syscall: fix and document uses of RegEnumKeyEx RegEnumKeyEx has an undocumented requirement that subsequent calls need to be made from the same thread. This change documents that requirement and fixes uses of it in std. Fixes #49320. Change-Id: I6d182227e22dd437996a878b3a978943f01b2d61 Reviewed-on: https://go-review.googlesource.com/c/go/+/361154 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/internal/syscall/windows/registry/key.go | 11 ++++++- src/syscall/syscall_windows.go | 30 +++++++++++++++++++- src/syscall/zsyscall_windows.go | 2 +- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/internal/syscall/windows/registry/key.go b/src/internal/syscall/windows/registry/key.go index ba5c292c5e..ec38cf9288 100644 --- a/src/internal/syscall/windows/registry/key.go +++ b/src/internal/syscall/windows/registry/key.go @@ -25,7 +25,10 @@ // package registry -import "syscall" +import ( + "runtime" + "syscall" +) const ( // Registry key security and access rights. @@ -88,6 +91,12 @@ func OpenKey(k Key, path string, access uint32) (Key, error) { // ReadSubKeyNames returns the names of subkeys of key k. func (k Key) ReadSubKeyNames() ([]string, error) { + // RegEnumKeyEx must be called repeatedly and to completion. + // During this time, this goroutine cannot migrate away from + // its current thread. See #49320. + runtime.LockOSThread() + defer runtime.UnlockOSThread() + names := make([]string, 0) // Registry key size limit is 255 bytes and described there: // https://msdn.microsoft.com/library/windows/desktop/ms724872.aspx diff --git a/src/syscall/syscall_windows.go b/src/syscall/syscall_windows.go index 48fedb33d7..69e163e00f 100644 --- a/src/syscall/syscall_windows.go +++ b/src/syscall/syscall_windows.go @@ -279,7 +279,7 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) = advapi32.RegOpenKeyExW //sys RegCloseKey(key Handle) (regerrno error) = advapi32.RegCloseKey //sys RegQueryInfoKey(key Handle, class *uint16, classLen *uint32, reserved *uint32, subkeysLen *uint32, maxSubkeyLen *uint32, maxClassLen *uint32, valuesLen *uint32, maxValueNameLen *uint32, maxValueLen *uint32, saLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegQueryInfoKeyW -//sys RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegEnumKeyExW +//sys regEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegEnumKeyExW //sys RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) = advapi32.RegQueryValueExW //sys getCurrentProcessId() (pid uint32) = kernel32.GetCurrentProcessId //sys GetConsoleMode(console Handle, mode *uint32) (err error) = kernel32.GetConsoleMode @@ -1301,3 +1301,31 @@ func newProcThreadAttributeList(maxAttrCount uint32) (*_PROC_THREAD_ATTRIBUTE_LI } return al, nil } + +// RegEnumKeyEx enumerates the subkeys of an open registry key. +// Each call retrieves information about one subkey. name is +// a buffer that should be large enough to hold the name of the +// subkey plus a null terminating character. nameLen is its +// length. On return, nameLen will contain the actual length of the +// subkey. +// +// Should name not be large enough to hold the subkey, this function +// will return ERROR_MORE_DATA, and must be called again with an +// appropriately sized buffer. +// +// reserved must be nil. class and classLen behave like name and nameLen +// but for the class of the subkey, except that they are optional. +// lastWriteTime, if not nil, will be populated with the time the subkey +// was last written. +// +// The caller must enumerate all subkeys in order. That is +// RegEnumKeyEx must be called with index starting at 0, incrementing +// the index until the function returns ERROR_NO_MORE_ITEMS, or with +// the index of the last subkey (obtainable from RegQueryInfoKey), +// decrementing until index 0 is enumerated. +// +// Successive calls to this API must happen on the same OS thread, +// so call runtime.LockOSThread before calling this function. +func RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) { + return regEnumKeyEx(key, index, name, nameLen, reserved, class, classLen, lastWriteTime) +} diff --git a/src/syscall/zsyscall_windows.go b/src/syscall/zsyscall_windows.go index 7bfff16be6..2d6f34e059 100644 --- a/src/syscall/zsyscall_windows.go +++ b/src/syscall/zsyscall_windows.go @@ -305,7 +305,7 @@ func RegCloseKey(key Handle) (regerrno error) { return } -func RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) { +func regEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) { r0, _, _ := Syscall9(procRegEnumKeyExW.Addr(), 8, uintptr(key), uintptr(index), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(class)), uintptr(unsafe.Pointer(classLen)), uintptr(unsafe.Pointer(lastWriteTime)), 0) if r0 != 0 { regerrno = Errno(r0) -- GitLab From bd49a998bf68609259c155cd7b9f4ed76d948a0d Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Mon, 1 Nov 2021 14:32:39 +0700 Subject: [PATCH 1942/2500] cmd/compile: fix missing update source type in storeArgOrLoad After removing trivial wrapper types, the source needs to be updated with new type, otherwise, it leads to mismatch between field offset and the source type for selecting struct/array. Fixes #49249 Change-Id: I26f9440bcb2e78bcf0617afc21d9d40cdbe4aca6 Reviewed-on: https://go-review.googlesource.com/c/go/+/360057 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: David Chase --- src/cmd/compile/internal/ssa/expand_calls.go | 2 + test/fixedbugs/issue49249.go | 55 ++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 test/fixedbugs/issue49249.go diff --git a/src/cmd/compile/internal/ssa/expand_calls.go b/src/cmd/compile/internal/ssa/expand_calls.go index 18c9ab696d..91ff9f87f9 100644 --- a/src/cmd/compile/internal/ssa/expand_calls.go +++ b/src/cmd/compile/internal/ssa/expand_calls.go @@ -954,6 +954,7 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, source, mem *Value, elt := t.Elem() if source.Type != t && t.NumElem() == 1 && elt.Size() == t.Size() && t.Size() == x.regSize { t = removeTrivialWrapperTypes(t) + source.Type = t // it could be a leaf type, but the "leaf" could be complex64 (for example) return x.storeArgOrLoad(pos, b, source, mem, t, storeOffset, loadRegOffset, storeRc) } @@ -987,6 +988,7 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, source, mem *Value, // v139 is later stored as an intVal == struct{val *big.Int} which naively requires the fields of // of a *uint8, which does not succeed. t = removeTrivialWrapperTypes(t) + source.Type = t // it could be a leaf type, but the "leaf" could be complex64 (for example) return x.storeArgOrLoad(pos, b, source, mem, t, storeOffset, loadRegOffset, storeRc) } diff --git a/test/fixedbugs/issue49249.go b/test/fixedbugs/issue49249.go new file mode 100644 index 0000000000..f152a5a701 --- /dev/null +++ b/test/fixedbugs/issue49249.go @@ -0,0 +1,55 @@ +// compile -l + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func f() int { + var a, b struct { + s struct { + s struct { + byte + float32 + } + } + } + _ = a + + return func() int { + return func() int { + a = struct { + s struct { + s struct { + byte + float32 + } + } + }{b.s} + return 0 + }() + }() +} + +func g() int { + var a, b struct { + s [1][1]struct { + byte + float32 + } + } + _ = a + + return func() int { + return func() int { + a = struct { + s [1][1]struct { + byte + float32 + } + }{b.s} + return 0 + }() + }() +} -- GitLab From 747e4afe0756cefd4281ba77855c6666e07beabf Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 3 Nov 2021 18:06:42 -0700 Subject: [PATCH 1943/2500] cmd/compile/internal/types2: remove qualification from type parameter strings This is a clean port of CL 360938 from go/types to types2. For #49215. Change-Id: If20779c862b71641cb6afe4c281fbad5488a8abe Reviewed-on: https://go-review.googlesource.com/c/go/+/361266 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/api_test.go | 14 +++++++------- src/cmd/compile/internal/types2/builtins_test.go | 6 +++--- src/cmd/compile/internal/types2/typestring.go | 4 ---- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index 5e111d6d87..30cfbe0ee4 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -326,25 +326,25 @@ func TestTypesInfo(t *testing.T) { {brokenPkg + `x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string]invalid type`}, // parameterized functions - {genericPkg + `p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[generic_p0.T interface{}](generic_p0.T)`}, + {genericPkg + `p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[T interface{}](T)`}, {genericPkg + `p1; func f[T any](T) {}; var _ = f[int]`, `f[int]`, `func(int)`}, {genericPkg + `p2; func f[T any](T) {}; func _() { f(42) }`, `f`, `func(int)`}, {genericPkg + `p3; func f[T any](T) {}; func _() { f[int](42) }`, `f[int]`, `func(int)`}, - {genericPkg + `p4; func f[T any](T) {}; func _() { f[int](42) }`, `f`, `func[generic_p4.T interface{}](generic_p4.T)`}, + {genericPkg + `p4; func f[T any](T) {}; func _() { f[int](42) }`, `f`, `func[T interface{}](T)`}, {genericPkg + `p5; func f[T any](T) {}; func _() { f(42) }`, `f(42)`, `()`}, // type parameters {genericPkg + `t0; type t[] int; var _ t`, `t`, `generic_t0.t`}, // t[] is a syntax error that is ignored in this test in favor of t - {genericPkg + `t1; type t[P any] int; var _ t[int]`, `t`, `generic_t1.t[generic_t1.P interface{}]`}, - {genericPkg + `t2; type t[P interface{}] int; var _ t[int]`, `t`, `generic_t2.t[generic_t2.P interface{}]`}, - {genericPkg + `t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `generic_t3.t[generic_t3.P, generic_t3.Q interface{}]`}, - {brokenPkg + `t4; type t[P, Q interface{ m() }] int; var _ t[int, int]`, `t`, `broken_t4.t[broken_t4.P, broken_t4.Q interface{m()}]`}, + {genericPkg + `t1; type t[P any] int; var _ t[int]`, `t`, `generic_t1.t[P interface{}]`}, + {genericPkg + `t2; type t[P interface{}] int; var _ t[int]`, `t`, `generic_t2.t[P interface{}]`}, + {genericPkg + `t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `generic_t3.t[P, Q interface{}]`}, + {brokenPkg + `t4; type t[P, Q interface{ m() }] int; var _ t[int, int]`, `t`, `broken_t4.t[P, Q interface{m()}]`}, // instantiated types must be sanitized {genericPkg + `g0; type t[P any] int; var x struct{ f t[int] }; var _ = x.f`, `x.f`, `generic_g0.t[int]`}, // issue 45096 - {genericPkg + `issue45096; func _[T interface{ ~int8 | ~int16 | ~int32 }](x T) { _ = x < 0 }`, `0`, `generic_issue45096.T`}, + {genericPkg + `issue45096; func _[T interface{ ~int8 | ~int16 | ~int32 }](x T) { _ = x < 0 }`, `0`, `T`}, // issue 47895 {`package p; import "unsafe"; type S struct { f int }; var s S; var _ = unsafe.Offsetof(s.f)`, `s.f`, `int`}, diff --git a/src/cmd/compile/internal/types2/builtins_test.go b/src/cmd/compile/internal/types2/builtins_test.go index dd71715a27..be5707cdfe 100644 --- a/src/cmd/compile/internal/types2/builtins_test.go +++ b/src/cmd/compile/internal/types2/builtins_test.go @@ -112,15 +112,15 @@ var builtinCalls = []struct { {"Alignof", `_ = unsafe.Alignof(0)`, `invalid type`}, // constant {"Alignof", `var x struct{}; _ = unsafe.Alignof(x)`, `invalid type`}, // constant - {"Alignof", `var x P; _ = unsafe.Alignof(x)`, `func(p.P) uintptr`}, + {"Alignof", `var x P; _ = unsafe.Alignof(x)`, `func(P) uintptr`}, {"Offsetof", `var x struct{f bool}; _ = unsafe.Offsetof(x.f)`, `invalid type`}, // constant {"Offsetof", `var x struct{_ int; f bool}; _ = unsafe.Offsetof((&x).f)`, `invalid type`}, // constant - {"Offsetof", `var x struct{_ int; f P}; _ = unsafe.Offsetof((&x).f)`, `func(p.P) uintptr`}, + {"Offsetof", `var x struct{_ int; f P}; _ = unsafe.Offsetof((&x).f)`, `func(P) uintptr`}, {"Sizeof", `_ = unsafe.Sizeof(0)`, `invalid type`}, // constant {"Sizeof", `var x struct{}; _ = unsafe.Sizeof(x)`, `invalid type`}, // constant - {"Sizeof", `var x P; _ = unsafe.Sizeof(x)`, `func(p.P) uintptr`}, + {"Sizeof", `var x P; _ = unsafe.Sizeof(x)`, `func(P) uintptr`}, {"Slice", `var p *int; _ = unsafe.Slice(p, 1)`, `func(*int, int) []int`}, {"Slice", `var p *byte; var n uintptr; _ = unsafe.Slice(p, n)`, `func(*byte, uintptr) []byte`}, diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 56bf4124fd..f18a32016f 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -273,10 +273,6 @@ func (w *typeWriter) typ(typ Type) { w.error("unnamed type parameter") break } - // Optionally write out package for typeparams (like Named). - if t.obj.pkg != nil { - writePackage(w.buf, t.obj.pkg, w.qf) - } w.string(t.obj.name) if w.debug || w.ctxt != nil { w.string(subscript(t.id)) -- GitLab From 9e4e23c724bc2145c5aee6edf3ec60cc322047cc Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 2 Nov 2021 17:31:51 -0700 Subject: [PATCH 1944/2500] cmd/compile/internal/types2: rename isX predicates to allX, add simple is_X (step 1 of 2) Rename the isX predicates to allX to clearly identify that these predicates are looking inside type parameters. Introduce is_X as predicates that do not look inside type parameters so we can see all call sites. The next CL will rename them all back to isX. Review all call sites and use correct predicate. Replace the single helper function is with isBasic and allBasic. Change-Id: I3430ccfc466fdedf4b58a6158f95d47b9020f7a5 Change-Id: I81116b87cf8f2e17526723c7440676d133057aca Reviewed-on: https://go-review.googlesource.com/c/go/+/360955 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/builtins.go | 14 +-- src/cmd/compile/internal/types2/check.go | 6 +- .../compile/internal/types2/conversions.go | 12 +-- src/cmd/compile/internal/types2/expr.go | 90 +++++++++---------- src/cmd/compile/internal/types2/index.go | 8 +- src/cmd/compile/internal/types2/predicates.go | 66 +++++++++----- src/cmd/compile/internal/types2/sizes.go | 2 +- src/cmd/compile/internal/types2/stmt.go | 8 +- src/cmd/compile/internal/types2/typexpr.go | 2 +- 9 files changed, 114 insertions(+), 94 deletions(-) diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index c5c6bdf0a5..c92eccf765 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -101,7 +101,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( if x.mode == invalid { return } - if isString(x.typ) { + if allString(x.typ) { if check.Types != nil { sig := makeSig(S, S, x.typ) sig.variadic = true @@ -146,7 +146,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( var val constant.Value switch typ = arrayPtrDeref(under(x.typ)); t := typ.(type) { case *Basic: - if isString(t) && id == _Len { + if is_String(t) && id == _Len { if x.mode == constant_ { mode = constant_ val = constant.MakeInt64(int64(len(constant.StringVal(x.val)))) @@ -182,7 +182,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( if t.underIs(func(t Type) bool { switch t := arrayPtrDeref(t).(type) { case *Basic: - if isString(t) && id == _Len { + if is_String(t) && id == _Len { return true } case *Array, *Slice, *Chan: @@ -267,7 +267,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( // because shifts of floats are not permitted) if x.mode == constant_ && y.mode == constant_ { toFloat := func(x *operand) { - if isNumeric(x.typ) && constant.Sign(constant.Imag(x.val)) == 0 { + if is_Numeric(x.typ) && constant.Sign(constant.Imag(x.val)) == 0 { x.typ = Typ[UntypedFloat] } } @@ -398,7 +398,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( if x.mode == constant_ { // an untyped constant number can always be considered // as a complex constant - if isNumeric(x.typ) { + if is_Numeric(x.typ) { x.typ = Typ[UntypedComplex] } } else { @@ -726,7 +726,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( // assert(pred) causes a typechecker error if pred is false. // The result of assert is the value of pred if there is no error. // Note: assert is only available in self-test mode. - if x.mode != constant_ || !isBoolean(x.typ) { + if x.mode != constant_ || !is_Boolean(x.typ) { check.errorf(x, invalidArg+"%s is not a boolean constant", x) return } @@ -802,7 +802,7 @@ func structure(typ Type) Type { func structureString(typ Type) Type { var su Type if underIs(typ, func(u Type) bool { - if isString(u) { + if is_String(u) { u = NewSlice(universeByte) } if su != nil && !Identical(su, u) { diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go index ffc59f7011..f69514e38a 100644 --- a/src/cmd/compile/internal/types2/check.go +++ b/src/cmd/compile/internal/types2/check.go @@ -430,9 +430,9 @@ func (check *Checker) recordTypeAndValue(x syntax.Expr, mode operandMode, typ Ty } if mode == constant_ { assert(val != nil) - // We check is(typ, IsConstType) here as constant expressions may be + // We check allBasic(typ, IsConstType) here as constant expressions may be // recorded as type parameters. - assert(typ == Typ[Invalid] || is(typ, IsConstType)) + assert(typ == Typ[Invalid] || allBasic(typ, IsConstType)) } if m := check.Types; m != nil { m[x] = TypeAndValue{mode, typ, val} @@ -462,7 +462,7 @@ func (check *Checker) recordCommaOkTypes(x syntax.Expr, a [2]Type) { if a[0] == nil || a[1] == nil { return } - assert(isTyped(a[0]) && isTyped(a[1]) && (isBoolean(a[1]) || a[1] == universeError)) + assert(isTyped(a[0]) && isTyped(a[1]) && (is_Boolean(a[1]) || a[1] == universeError)) if m := check.Types; m != nil { for { tv := m[x] diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go index 5798bacca7..c029f1147d 100644 --- a/src/cmd/compile/internal/types2/conversions.go +++ b/src/cmd/compile/internal/types2/conversions.go @@ -22,7 +22,7 @@ func (check *Checker) conversion(x *operand, T Type) { // nothing to do case representableConst(x.val, check, t, val): return true - case isInteger(x.typ) && isString(t): + case is_Integer(x.typ) && is_String(t): codepoint := unicode.ReplacementChar if i, ok := constant.Uint64Val(x.val); ok && i <= unicode.MaxRune { codepoint = rune(i) @@ -93,7 +93,7 @@ func (check *Checker) conversion(x *operand, T Type) { // ok } else if IsInterface(T) || constArg && !isConstType(T) { final = Default(x.typ) - } else if isInteger(x.typ) && isString(T) { + } else if is_Integer(x.typ) && allString(T) { final = x.typ } check.updateExprType(x.expr, final, true) @@ -197,22 +197,22 @@ func convertibleToImpl(check *Checker, V, T Type, cause *string) bool { } // "V and T are both integer or floating point types" - if isIntegerOrFloat(V) && isIntegerOrFloat(T) { + if is_IntegerOrFloat(V) && is_IntegerOrFloat(T) { return true } // "V and T are both complex types" - if isComplex(V) && isComplex(T) { + if is_Complex(V) && is_Complex(T) { return true } // "V is an integer or a slice of bytes or runes and T is a string type" - if (isInteger(V) || isBytesOrRunes(Vu)) && isString(T) { + if (is_Integer(V) || isBytesOrRunes(Vu)) && is_String(T) { return true } // "V is a string and T is a slice of bytes or runes" - if isString(V) && isBytesOrRunes(Tu) { + if is_String(V) && isBytesOrRunes(Tu) { return true } diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index eb5ec9f3fb..1db5af00da 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -63,10 +63,10 @@ var unaryOpPredicates opPredicates func init() { // Setting unaryOpPredicates in init avoids declaration cycles. unaryOpPredicates = opPredicates{ - syntax.Add: isNumeric, - syntax.Sub: isNumeric, - syntax.Xor: isInteger, - syntax.Not: isBoolean, + syntax.Add: allNumeric, + syntax.Sub: allNumeric, + syntax.Xor: allInteger, + syntax.Not: allBoolean, } } @@ -225,7 +225,7 @@ func (check *Checker) unary(x *operand, e *syntax.Operation) { return } var prec uint - if isUnsigned(x.typ) { + if is_Unsigned(x.typ) { prec = uint(check.conf.sizeof(x.typ) * 8) } x.val = constant.UnaryOp(op2tok[e.Op], x.val, prec) @@ -302,7 +302,7 @@ func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *c } switch { - case isInteger(typ): + case is_Integer(typ): x := constant.ToInt(x) if x.Kind() != constant.Int { return false @@ -357,7 +357,7 @@ func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *c return true } - case isFloat(typ): + case is_Float(typ): x := constant.ToFloat(x) if x.Kind() != constant.Float { return false @@ -387,7 +387,7 @@ func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *c unreachable() } - case isComplex(typ): + case is_Complex(typ): x := constant.ToComplex(x) if x.Kind() != constant.Complex { return false @@ -419,10 +419,10 @@ func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *c unreachable() } - case isString(typ): + case is_String(typ): return x.Kind() == constant.String - case isBoolean(typ): + case is_Boolean(typ): return x.Kind() == constant.Bool } @@ -474,7 +474,7 @@ func (check *Checker) representation(x *operand, typ *Basic) (constant.Value, er assert(x.mode == constant_) v := x.val if !representableConst(x.val, check, typ, &v) { - if isNumeric(x.typ) && isNumeric(typ) { + if is_Numeric(x.typ) && is_Numeric(typ) { // numeric conversion : error msg // // integer -> integer : overflows @@ -482,7 +482,7 @@ func (check *Checker) representation(x *operand, typ *Basic) (constant.Value, er // float -> integer : truncated // float -> float : overflows // - if !isInteger(x.typ) && isInteger(typ) { + if !is_Integer(x.typ) && is_Integer(typ) { return nil, _TruncatedFloat } else { return nil, _NumericOverflow @@ -630,7 +630,7 @@ func (check *Checker) updateExprType(x syntax.Expr, typ Type, final bool) { // If x is the lhs of a shift, its final type must be integer. // We already know from the shift check that it is representable // as an integer if it is a constant. - if !isInteger(typ) { + if !is_Integer(typ) { check.errorf(x, invalidOp+"shifted operand %s (type %s) must be integer", x, typ) return } @@ -692,7 +692,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const // both x and target are untyped xkind := x.typ.(*Basic).kind tkind := target.(*Basic).kind - if isNumeric(x.typ) && isNumeric(target) { + if is_Numeric(x.typ) && is_Numeric(target) { if xkind < tkind { return target, nil, 0 } @@ -710,10 +710,10 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const return nil, nil, _InvalidUntypedConversion } - switch t := under(target).(type) { + switch u := under(target).(type) { case *Basic: if x.mode == constant_ { - v, code := check.representation(x, t) + v, code := check.representation(x, u) if code != 0 { return nil, nil, code } @@ -725,18 +725,18 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const // the value nil. switch x.typ.(*Basic).kind { case UntypedBool: - if !isBoolean(target) { + if !is_Boolean(target) { return nil, nil, _InvalidUntypedConversion } case UntypedInt, UntypedRune, UntypedFloat, UntypedComplex: - if !isNumeric(target) { + if !is_Numeric(target) { return nil, nil, _InvalidUntypedConversion } case UntypedString: // Non-constant untyped string values are not permitted by the spec and // should not occur during normal typechecking passes, but this path is // reachable via the AssignableTo API. - if !isString(target) { + if !is_String(target) { return nil, nil, _InvalidUntypedConversion } default: @@ -744,7 +744,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const } case *TypeParam: // TODO(gri) review this code - doesn't look quite right - ok := t.underIs(func(t Type) bool { + ok := u.underIs(func(t Type) bool { target, _, _ := check.implicitTypeAndValue(x, t) return target != nil }) @@ -755,7 +755,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const // Update operand types to the default type rather than the target // (interface) type: values must have concrete dynamic types. // Untyped nil was handled upfront. - if !t.Empty() { + if !u.Empty() { return nil, nil, _InvalidUntypedConversion // cannot assign untyped values to non-empty interfaces } return Default(x.typ), nil, 0 // default type for nil is nil @@ -779,7 +779,7 @@ func (check *Checker) comparison(x, y *operand, op syntax.Operator) { defined = Comparable(x.typ) && Comparable(y.typ) || x.isNil() && hasNil(y.typ) || y.isNil() && hasNil(x.typ) case syntax.Lss, syntax.Leq, syntax.Gtr, syntax.Geq: // spec: The ordering operators <, <=, >, and >= apply to operands that are ordered." - defined = isOrdered(x.typ) && isOrdered(y.typ) + defined = allOrdered(x.typ) && allOrdered(y.typ) default: unreachable() } @@ -833,7 +833,7 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) { xval = constant.ToInt(x.val) } - if isInteger(x.typ) || isUntyped(x.typ) && xval != nil && xval.Kind() == constant.Int { + if allInteger(x.typ) || isUntyped(x.typ) && xval != nil && xval.Kind() == constant.Int { // The lhs is of integer type or an untyped constant representable // as an integer. Nothing to do. } else { @@ -856,7 +856,7 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) { } } - // Caution: Check for isUntyped first because isInteger includes untyped + // Caution: Check for isUntyped first because is_Integer includes untyped // integers (was bug #43697). if isUntyped(y.typ) { check.convertUntyped(y, Typ[Uint]) @@ -864,11 +864,11 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) { x.mode = invalid return } - } else if !isInteger(y.typ) { + } else if !allInteger(y.typ) { check.errorf(y, invalidOp+"shift count %s must be integer", y) x.mode = invalid return - } else if !isUnsigned(y.typ) && !check.allowVersion(check.pkg, 1, 13) { + } else if !allUnsigned(y.typ) && !check.allowVersion(check.pkg, 1, 13) { check.errorf(y, invalidOp+"signed shift count %s requires go1.13 or later", y) x.mode = invalid return @@ -880,7 +880,7 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) { if x.val.Kind() == constant.Unknown || y.val.Kind() == constant.Unknown { x.val = constant.MakeUnknown() // ensure the correct type - see comment below - if !isInteger(x.typ) { + if !is_Integer(x.typ) { x.typ = Typ[UntypedInt] } return @@ -897,7 +897,7 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) { // (e.g., 2.0, an untyped float) - this can only happen for untyped // non-integer numeric constants. Correct the type so that the shift // result is of integer type. - if !isInteger(x.typ) { + if !is_Integer(x.typ) { x.typ = Typ[UntypedInt] } // x is a constant so xval != nil and it must be of Int kind. @@ -939,7 +939,7 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) { } // non-constant shift - lhs must be an integer - if !isInteger(x.typ) { + if !allInteger(x.typ) { check.errorf(x, invalidOp+"shifted operand %s must be integer", x) x.mode = invalid return @@ -953,19 +953,19 @@ var binaryOpPredicates opPredicates func init() { // Setting binaryOpPredicates in init avoids declaration cycles. binaryOpPredicates = opPredicates{ - syntax.Add: isNumericOrString, - syntax.Sub: isNumeric, - syntax.Mul: isNumeric, - syntax.Div: isNumeric, - syntax.Rem: isInteger, + syntax.Add: allNumericOrString, + syntax.Sub: allNumeric, + syntax.Mul: allNumeric, + syntax.Div: allNumeric, + syntax.Rem: allInteger, - syntax.And: isInteger, - syntax.Or: isInteger, - syntax.Xor: isInteger, - syntax.AndNot: isInteger, + syntax.And: allInteger, + syntax.Or: allInteger, + syntax.Xor: allInteger, + syntax.AndNot: allInteger, - syntax.AndAnd: isBoolean, - syntax.OrOr: isBoolean, + syntax.AndAnd: allBoolean, + syntax.OrOr: allBoolean, } } @@ -995,10 +995,10 @@ func (check *Checker) binary(x *operand, e syntax.Expr, lhs, rhs syntax.Expr, op if IsInterface(x.typ) || IsInterface(y.typ) { return true } - if isBoolean(x.typ) != isBoolean(y.typ) { + if allBoolean(x.typ) != allBoolean(y.typ) { return false } - if isString(x.typ) != isString(y.typ) { + if allString(x.typ) != allString(y.typ) { return false } if x.isNil() && !hasNil(y.typ) { @@ -1047,14 +1047,14 @@ func (check *Checker) binary(x *operand, e syntax.Expr, lhs, rhs syntax.Expr, op if op == syntax.Div || op == syntax.Rem { // check for zero divisor - if (x.mode == constant_ || isInteger(x.typ)) && y.mode == constant_ && constant.Sign(y.val) == 0 { + if (x.mode == constant_ || allInteger(x.typ)) && y.mode == constant_ && constant.Sign(y.val) == 0 { check.error(&y, invalidOp+"division by zero") x.mode = invalid return } // check for divisor underflow in complex division (see issue 20227) - if x.mode == constant_ && y.mode == constant_ && isComplex(x.typ) { + if x.mode == constant_ && y.mode == constant_ && is_Complex(x.typ) { re, im := constant.Real(y.val), constant.Imag(y.val) re2, im2 := constant.BinaryOp(re, token.MUL, re), constant.BinaryOp(im, token.MUL, im) if constant.Sign(re2) == 0 && constant.Sign(im2) == 0 { @@ -1074,7 +1074,7 @@ func (check *Checker) binary(x *operand, e syntax.Expr, lhs, rhs syntax.Expr, op } // force integer division for integer operands tok := op2tok[op] - if op == syntax.Div && isInteger(x.typ) { + if op == syntax.Div && is_Integer(x.typ) { tok = token.QUO_ASSIGN } x.val = constant.BinaryOp(x.val, tok, y.val) diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index bb7033e957..1b080139f3 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -51,7 +51,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo length := int64(-1) // valid if >= 0 switch typ := under(x.typ).(type) { case *Basic: - if isString(typ) { + if is_String(typ) { valid = true if x.mode == constant_ { length = int64(len(constant.StringVal(x.val))) @@ -109,7 +109,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo var k, e Type // k is only set for maps switch t := u.(type) { case *Basic: - if isString(t) { + if is_String(t) { e = universeByte mode = value } @@ -217,7 +217,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { return case *Basic: - if isString(u) { + if is_String(u) { if e.Full { check.error(x, invalidOp+"3-index slice of string") x.mode = invalid @@ -386,7 +386,7 @@ func (check *Checker) isValidIndex(x *operand, what string, allowNegative bool) } // spec: "the index x must be of integer type or an untyped constant" - if !isInteger(x.typ) { + if !allInteger(x.typ) { check.errorf(x, invalidArg+"%s %s must be integer", what, x) return false } diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 6d93a8a227..980d254084 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -25,33 +25,55 @@ func isGeneric(typ Type) bool { return named != nil && named.obj != nil && named.targs == nil && named.TypeParams() != nil } -func is(typ Type, what BasicInfo) bool { - switch t := under(typ).(type) { +// The is_X predicates below report whether t is an X. +// If t is a type parameter the result is false; i.e., +// these predicates don't look inside a type parameter. + +func is_Boolean(t Type) bool { return isBasic(t, IsBoolean) } +func is_Integer(t Type) bool { return isBasic(t, IsInteger) } +func is_Unsigned(t Type) bool { return isBasic(t, IsUnsigned) } +func is_Float(t Type) bool { return isBasic(t, IsFloat) } +func is_Complex(t Type) bool { return isBasic(t, IsComplex) } +func is_Numeric(t Type) bool { return isBasic(t, IsNumeric) } +func is_String(t Type) bool { return isBasic(t, IsString) } +func is_IntegerOrFloat(t Type) bool { return isBasic(t, IsInteger|IsFloat) } + +// isBasic reports whether under(t) is a basic type with the specified info. +// If t is a type parameter the result is false; i.e., +// isBasic does not look inside a type parameter. +func isBasic(t Type, info BasicInfo) bool { + u, _ := under(t).(*Basic) + return u != nil && u.info&info != 0 +} + +// The allX predicates below report whether t is an X. +// If t is a type parameter the result is true if is_X is true +// for all specified types of the type parameter's type set. +// allX is an optimized version of is_X(structure(t)) (which +// is the same as underIs(t, is_X)). + +func allBoolean(t Type) bool { return allBasic(t, IsBoolean) } +func allInteger(t Type) bool { return allBasic(t, IsInteger) } +func allUnsigned(t Type) bool { return allBasic(t, IsUnsigned) } +func allNumeric(t Type) bool { return allBasic(t, IsNumeric) } +func allString(t Type) bool { return allBasic(t, IsString) } +func allOrdered(t Type) bool { return allBasic(t, IsOrdered) } +func allNumericOrString(t Type) bool { return allBasic(t, IsNumeric|IsString) } + +// allBasic reports whether under(t) is a basic type with the specified info. +// If t is a type parameter, the result is true if isBasic(t, info) is true +// for all specific types of the type parameter's type set. +// allBasic(t, info) is an optimized version of isBasic(structure(t), info). +func allBasic(t Type, info BasicInfo) bool { + switch u := under(t).(type) { case *Basic: - return t.info&what != 0 + return u.info&info != 0 case *TypeParam: - return t.underIs(func(t Type) bool { return is(t, what) }) + return u.is(func(t *term) bool { return t != nil && isBasic(t.typ, info) }) } return false } -func isBoolean(typ Type) bool { return is(typ, IsBoolean) } -func isInteger(typ Type) bool { return is(typ, IsInteger) } -func isUnsigned(typ Type) bool { return is(typ, IsUnsigned) } -func isFloat(typ Type) bool { return is(typ, IsFloat) } -func isComplex(typ Type) bool { return is(typ, IsComplex) } -func isNumeric(typ Type) bool { return is(typ, IsNumeric) } -func isString(typ Type) bool { return is(typ, IsString) } - -// Note that if typ is a type parameter, isInteger(typ) || isFloat(typ) does not -// produce the expected result because a type set that contains both an integer -// and a floating-point type is neither (all) integers, nor (all) floats. -// Use isIntegerOrFloat instead. -func isIntegerOrFloat(typ Type) bool { return is(typ, IsInteger|IsFloat) } - -// isNumericOrString is the equivalent of isIntegerOrFloat for isNumeric(typ) || isString(typ). -func isNumericOrString(typ Type) bool { return is(typ, IsNumeric|IsString) } - // isTyped reports whether typ is typed; i.e., not an untyped // constant or boolean. isTyped may be called with types that // are not fully set up. @@ -67,8 +89,6 @@ func isUntyped(typ Type) bool { return !isTyped(typ) } -func isOrdered(typ Type) bool { return is(typ, IsOrdered) } - func isConstType(typ Type) bool { // Type parameters are never const types. t := asBasic(typ) diff --git a/src/cmd/compile/internal/types2/sizes.go b/src/cmd/compile/internal/types2/sizes.go index 6a3d19d8ea..8f93ca6b87 100644 --- a/src/cmd/compile/internal/types2/sizes.go +++ b/src/cmd/compile/internal/types2/sizes.go @@ -82,7 +82,7 @@ func (s *StdSizes) Alignof(T Type) int64 { return 1 } // complex{64,128} are aligned like [2]float{32,64}. - if isComplex(T) { + if is_Complex(T) { a /= 2 } if a > s.MaxAlign { diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index dd2100f711..b8b53a868e 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -443,7 +443,7 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) { if x.mode == invalid { return } - if !isNumeric(x.typ) { + if !allNumeric(x.typ) { check.errorf(lhs[0], invalidOp+"%s%s%s (non-numeric type %s)", lhs[0], s.Op, s.Op, x.typ) return } @@ -556,7 +556,7 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) { check.simpleStmt(s.Init) var x operand check.expr(&x, s.Cond) - if x.mode != invalid && !isBoolean(x.typ) { + if x.mode != invalid && !allBoolean(x.typ) { check.error(s.Cond, "non-boolean condition in if statement") } check.stmt(inner, s.Then) @@ -645,7 +645,7 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) { if s.Cond != nil { var x operand check.expr(&x, s.Cond) - if x.mode != invalid && !isBoolean(x.typ) { + if x.mode != invalid && !allBoolean(x.typ) { check.error(s.Cond, "non-boolean condition in for statement") } } @@ -942,7 +942,7 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s func rangeKeyVal(typ Type) (key, val Type) { switch typ := arrayPtrDeref(typ).(type) { case *Basic: - if isString(typ) { + if is_String(typ) { return Typ[Int], universeRune // use 'rune' name } case *Array: diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 95893fd1e1..7007176980 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -513,7 +513,7 @@ func (check *Checker) arrayLength(e syntax.Expr) int64 { return -1 } - if isUntyped(x.typ) || isInteger(x.typ) { + if isUntyped(x.typ) || is_Integer(x.typ) { if val := constant.ToInt(x.val); val.Kind() == constant.Int { if representableConst(val, check, Typ[Int], nil) { if n, ok := constant.Int64Val(val); ok && n >= 0 { -- GitLab From ad2044a498cbbb211fe14fd4eeb0a63709363cfc Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 3 Nov 2021 08:39:41 -0700 Subject: [PATCH 1945/2500] cmd/compile/internal/types2: rename is_X predicates back to isX (step 2 of 2) This is s/is_/is/ throughout. No other changes. Change-Id: I1be77a209133edc68a6dec0677a4991a7683f116 Reviewed-on: https://go-review.googlesource.com/c/go/+/361134 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/builtins.go | 12 +++---- src/cmd/compile/internal/types2/check.go | 2 +- .../compile/internal/types2/conversions.go | 12 +++---- src/cmd/compile/internal/types2/expr.go | 36 +++++++++---------- src/cmd/compile/internal/types2/index.go | 6 ++-- src/cmd/compile/internal/types2/predicates.go | 24 ++++++------- src/cmd/compile/internal/types2/sizes.go | 2 +- src/cmd/compile/internal/types2/stmt.go | 2 +- src/cmd/compile/internal/types2/typexpr.go | 2 +- 9 files changed, 49 insertions(+), 49 deletions(-) diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index c92eccf765..548d55e10c 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -146,7 +146,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( var val constant.Value switch typ = arrayPtrDeref(under(x.typ)); t := typ.(type) { case *Basic: - if is_String(t) && id == _Len { + if isString(t) && id == _Len { if x.mode == constant_ { mode = constant_ val = constant.MakeInt64(int64(len(constant.StringVal(x.val)))) @@ -182,7 +182,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( if t.underIs(func(t Type) bool { switch t := arrayPtrDeref(t).(type) { case *Basic: - if is_String(t) && id == _Len { + if isString(t) && id == _Len { return true } case *Array, *Slice, *Chan: @@ -267,7 +267,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( // because shifts of floats are not permitted) if x.mode == constant_ && y.mode == constant_ { toFloat := func(x *operand) { - if is_Numeric(x.typ) && constant.Sign(constant.Imag(x.val)) == 0 { + if isNumeric(x.typ) && constant.Sign(constant.Imag(x.val)) == 0 { x.typ = Typ[UntypedFloat] } } @@ -398,7 +398,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( if x.mode == constant_ { // an untyped constant number can always be considered // as a complex constant - if is_Numeric(x.typ) { + if isNumeric(x.typ) { x.typ = Typ[UntypedComplex] } } else { @@ -726,7 +726,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( // assert(pred) causes a typechecker error if pred is false. // The result of assert is the value of pred if there is no error. // Note: assert is only available in self-test mode. - if x.mode != constant_ || !is_Boolean(x.typ) { + if x.mode != constant_ || !isBoolean(x.typ) { check.errorf(x, invalidArg+"%s is not a boolean constant", x) return } @@ -802,7 +802,7 @@ func structure(typ Type) Type { func structureString(typ Type) Type { var su Type if underIs(typ, func(u Type) bool { - if is_String(u) { + if isString(u) { u = NewSlice(universeByte) } if su != nil && !Identical(su, u) { diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go index f69514e38a..b9a76a8990 100644 --- a/src/cmd/compile/internal/types2/check.go +++ b/src/cmd/compile/internal/types2/check.go @@ -462,7 +462,7 @@ func (check *Checker) recordCommaOkTypes(x syntax.Expr, a [2]Type) { if a[0] == nil || a[1] == nil { return } - assert(isTyped(a[0]) && isTyped(a[1]) && (is_Boolean(a[1]) || a[1] == universeError)) + assert(isTyped(a[0]) && isTyped(a[1]) && (isBoolean(a[1]) || a[1] == universeError)) if m := check.Types; m != nil { for { tv := m[x] diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go index c029f1147d..bd7b82fabf 100644 --- a/src/cmd/compile/internal/types2/conversions.go +++ b/src/cmd/compile/internal/types2/conversions.go @@ -22,7 +22,7 @@ func (check *Checker) conversion(x *operand, T Type) { // nothing to do case representableConst(x.val, check, t, val): return true - case is_Integer(x.typ) && is_String(t): + case isInteger(x.typ) && isString(t): codepoint := unicode.ReplacementChar if i, ok := constant.Uint64Val(x.val); ok && i <= unicode.MaxRune { codepoint = rune(i) @@ -93,7 +93,7 @@ func (check *Checker) conversion(x *operand, T Type) { // ok } else if IsInterface(T) || constArg && !isConstType(T) { final = Default(x.typ) - } else if is_Integer(x.typ) && allString(T) { + } else if isInteger(x.typ) && allString(T) { final = x.typ } check.updateExprType(x.expr, final, true) @@ -197,22 +197,22 @@ func convertibleToImpl(check *Checker, V, T Type, cause *string) bool { } // "V and T are both integer or floating point types" - if is_IntegerOrFloat(V) && is_IntegerOrFloat(T) { + if isIntegerOrFloat(V) && isIntegerOrFloat(T) { return true } // "V and T are both complex types" - if is_Complex(V) && is_Complex(T) { + if isComplex(V) && isComplex(T) { return true } // "V is an integer or a slice of bytes or runes and T is a string type" - if (is_Integer(V) || isBytesOrRunes(Vu)) && is_String(T) { + if (isInteger(V) || isBytesOrRunes(Vu)) && isString(T) { return true } // "V is a string and T is a slice of bytes or runes" - if is_String(V) && isBytesOrRunes(Tu) { + if isString(V) && isBytesOrRunes(Tu) { return true } diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 1db5af00da..95b96f2334 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -225,7 +225,7 @@ func (check *Checker) unary(x *operand, e *syntax.Operation) { return } var prec uint - if is_Unsigned(x.typ) { + if isUnsigned(x.typ) { prec = uint(check.conf.sizeof(x.typ) * 8) } x.val = constant.UnaryOp(op2tok[e.Op], x.val, prec) @@ -302,7 +302,7 @@ func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *c } switch { - case is_Integer(typ): + case isInteger(typ): x := constant.ToInt(x) if x.Kind() != constant.Int { return false @@ -357,7 +357,7 @@ func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *c return true } - case is_Float(typ): + case isFloat(typ): x := constant.ToFloat(x) if x.Kind() != constant.Float { return false @@ -387,7 +387,7 @@ func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *c unreachable() } - case is_Complex(typ): + case isComplex(typ): x := constant.ToComplex(x) if x.Kind() != constant.Complex { return false @@ -419,10 +419,10 @@ func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *c unreachable() } - case is_String(typ): + case isString(typ): return x.Kind() == constant.String - case is_Boolean(typ): + case isBoolean(typ): return x.Kind() == constant.Bool } @@ -474,7 +474,7 @@ func (check *Checker) representation(x *operand, typ *Basic) (constant.Value, er assert(x.mode == constant_) v := x.val if !representableConst(x.val, check, typ, &v) { - if is_Numeric(x.typ) && is_Numeric(typ) { + if isNumeric(x.typ) && isNumeric(typ) { // numeric conversion : error msg // // integer -> integer : overflows @@ -482,7 +482,7 @@ func (check *Checker) representation(x *operand, typ *Basic) (constant.Value, er // float -> integer : truncated // float -> float : overflows // - if !is_Integer(x.typ) && is_Integer(typ) { + if !isInteger(x.typ) && isInteger(typ) { return nil, _TruncatedFloat } else { return nil, _NumericOverflow @@ -630,7 +630,7 @@ func (check *Checker) updateExprType(x syntax.Expr, typ Type, final bool) { // If x is the lhs of a shift, its final type must be integer. // We already know from the shift check that it is representable // as an integer if it is a constant. - if !is_Integer(typ) { + if !isInteger(typ) { check.errorf(x, invalidOp+"shifted operand %s (type %s) must be integer", x, typ) return } @@ -692,7 +692,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const // both x and target are untyped xkind := x.typ.(*Basic).kind tkind := target.(*Basic).kind - if is_Numeric(x.typ) && is_Numeric(target) { + if isNumeric(x.typ) && isNumeric(target) { if xkind < tkind { return target, nil, 0 } @@ -725,18 +725,18 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const // the value nil. switch x.typ.(*Basic).kind { case UntypedBool: - if !is_Boolean(target) { + if !isBoolean(target) { return nil, nil, _InvalidUntypedConversion } case UntypedInt, UntypedRune, UntypedFloat, UntypedComplex: - if !is_Numeric(target) { + if !isNumeric(target) { return nil, nil, _InvalidUntypedConversion } case UntypedString: // Non-constant untyped string values are not permitted by the spec and // should not occur during normal typechecking passes, but this path is // reachable via the AssignableTo API. - if !is_String(target) { + if !isString(target) { return nil, nil, _InvalidUntypedConversion } default: @@ -856,7 +856,7 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) { } } - // Caution: Check for isUntyped first because is_Integer includes untyped + // Caution: Check for isUntyped first because isInteger includes untyped // integers (was bug #43697). if isUntyped(y.typ) { check.convertUntyped(y, Typ[Uint]) @@ -880,7 +880,7 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) { if x.val.Kind() == constant.Unknown || y.val.Kind() == constant.Unknown { x.val = constant.MakeUnknown() // ensure the correct type - see comment below - if !is_Integer(x.typ) { + if !isInteger(x.typ) { x.typ = Typ[UntypedInt] } return @@ -897,7 +897,7 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) { // (e.g., 2.0, an untyped float) - this can only happen for untyped // non-integer numeric constants. Correct the type so that the shift // result is of integer type. - if !is_Integer(x.typ) { + if !isInteger(x.typ) { x.typ = Typ[UntypedInt] } // x is a constant so xval != nil and it must be of Int kind. @@ -1054,7 +1054,7 @@ func (check *Checker) binary(x *operand, e syntax.Expr, lhs, rhs syntax.Expr, op } // check for divisor underflow in complex division (see issue 20227) - if x.mode == constant_ && y.mode == constant_ && is_Complex(x.typ) { + if x.mode == constant_ && y.mode == constant_ && isComplex(x.typ) { re, im := constant.Real(y.val), constant.Imag(y.val) re2, im2 := constant.BinaryOp(re, token.MUL, re), constant.BinaryOp(im, token.MUL, im) if constant.Sign(re2) == 0 && constant.Sign(im2) == 0 { @@ -1074,7 +1074,7 @@ func (check *Checker) binary(x *operand, e syntax.Expr, lhs, rhs syntax.Expr, op } // force integer division for integer operands tok := op2tok[op] - if op == syntax.Div && is_Integer(x.typ) { + if op == syntax.Div && isInteger(x.typ) { tok = token.QUO_ASSIGN } x.val = constant.BinaryOp(x.val, tok, y.val) diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index 1b080139f3..67110704e9 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -51,7 +51,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo length := int64(-1) // valid if >= 0 switch typ := under(x.typ).(type) { case *Basic: - if is_String(typ) { + if isString(typ) { valid = true if x.mode == constant_ { length = int64(len(constant.StringVal(x.val))) @@ -109,7 +109,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo var k, e Type // k is only set for maps switch t := u.(type) { case *Basic: - if is_String(t) { + if isString(t) { e = universeByte mode = value } @@ -217,7 +217,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { return case *Basic: - if is_String(u) { + if isString(u) { if e.Full { check.error(x, invalidOp+"3-index slice of string") x.mode = invalid diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 980d254084..5a82608671 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -25,18 +25,18 @@ func isGeneric(typ Type) bool { return named != nil && named.obj != nil && named.targs == nil && named.TypeParams() != nil } -// The is_X predicates below report whether t is an X. +// The isX predicates below report whether t is an X. // If t is a type parameter the result is false; i.e., // these predicates don't look inside a type parameter. -func is_Boolean(t Type) bool { return isBasic(t, IsBoolean) } -func is_Integer(t Type) bool { return isBasic(t, IsInteger) } -func is_Unsigned(t Type) bool { return isBasic(t, IsUnsigned) } -func is_Float(t Type) bool { return isBasic(t, IsFloat) } -func is_Complex(t Type) bool { return isBasic(t, IsComplex) } -func is_Numeric(t Type) bool { return isBasic(t, IsNumeric) } -func is_String(t Type) bool { return isBasic(t, IsString) } -func is_IntegerOrFloat(t Type) bool { return isBasic(t, IsInteger|IsFloat) } +func isBoolean(t Type) bool { return isBasic(t, IsBoolean) } +func isInteger(t Type) bool { return isBasic(t, IsInteger) } +func isUnsigned(t Type) bool { return isBasic(t, IsUnsigned) } +func isFloat(t Type) bool { return isBasic(t, IsFloat) } +func isComplex(t Type) bool { return isBasic(t, IsComplex) } +func isNumeric(t Type) bool { return isBasic(t, IsNumeric) } +func isString(t Type) bool { return isBasic(t, IsString) } +func isIntegerOrFloat(t Type) bool { return isBasic(t, IsInteger|IsFloat) } // isBasic reports whether under(t) is a basic type with the specified info. // If t is a type parameter the result is false; i.e., @@ -47,10 +47,10 @@ func isBasic(t Type, info BasicInfo) bool { } // The allX predicates below report whether t is an X. -// If t is a type parameter the result is true if is_X is true +// If t is a type parameter the result is true if isX is true // for all specified types of the type parameter's type set. -// allX is an optimized version of is_X(structure(t)) (which -// is the same as underIs(t, is_X)). +// allX is an optimized version of isX(structure(t)) (which +// is the same as underIs(t, isX)). func allBoolean(t Type) bool { return allBasic(t, IsBoolean) } func allInteger(t Type) bool { return allBasic(t, IsInteger) } diff --git a/src/cmd/compile/internal/types2/sizes.go b/src/cmd/compile/internal/types2/sizes.go index 8f93ca6b87..6a3d19d8ea 100644 --- a/src/cmd/compile/internal/types2/sizes.go +++ b/src/cmd/compile/internal/types2/sizes.go @@ -82,7 +82,7 @@ func (s *StdSizes) Alignof(T Type) int64 { return 1 } // complex{64,128} are aligned like [2]float{32,64}. - if is_Complex(T) { + if isComplex(T) { a /= 2 } if a > s.MaxAlign { diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index b8b53a868e..eaf420aca7 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -942,7 +942,7 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s func rangeKeyVal(typ Type) (key, val Type) { switch typ := arrayPtrDeref(typ).(type) { case *Basic: - if is_String(typ) { + if isString(typ) { return Typ[Int], universeRune // use 'rune' name } case *Array: diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 7007176980..95893fd1e1 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -513,7 +513,7 @@ func (check *Checker) arrayLength(e syntax.Expr) int64 { return -1 } - if isUntyped(x.typ) || is_Integer(x.typ) { + if isUntyped(x.typ) || isInteger(x.typ) { if val := constant.ToInt(x.val); val.Kind() == constant.Int { if representableConst(val, check, Typ[Int], nil) { if n, ok := constant.Int64Val(val); ok && n >= 0 { -- GitLab From 5fd0c49a4d8cd3bfff3c06e17a0fd9c41bc2f64a Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 2 Nov 2021 21:31:50 -0700 Subject: [PATCH 1946/2500] cmd/compile/internal/types2: minor cleanups in predicates.go - reordered some functions for better organization - renamed single arguments typ to t for consistency - updated some comments No functional changes. Change-Id: I4362ac48044595cdf5c3d9eb7b2f7b94e776d65b Reviewed-on: https://go-review.googlesource.com/c/go/+/360956 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/predicates.go | 87 +++++++++---------- 1 file changed, 41 insertions(+), 46 deletions(-) diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 5a82608671..7fbb91eb61 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -6,25 +6,6 @@ package types2 -// hasName reports whether typ has a name. This includes -// predeclared types, defined types, and type parameters. -// hasName may be called with types that are not fully set up. -func hasName(typ Type) bool { - switch typ.(type) { - case *Basic, *Named, *TypeParam: - return true - } - return false -} - -// isGeneric reports whether a type is a generic, uninstantiated type (generic -// signatures are not included). -func isGeneric(typ Type) bool { - // A parameterized type is only instantiated if it doesn't have an instantiation already. - named, _ := typ.(*Named) - return named != nil && named.obj != nil && named.targs == nil && named.TypeParams() != nil -} - // The isX predicates below report whether t is an X. // If t is a type parameter the result is false; i.e., // these predicates don't look inside a type parameter. @@ -37,6 +18,7 @@ func isComplex(t Type) bool { return isBasic(t, IsComplex) } func isNumeric(t Type) bool { return isBasic(t, IsNumeric) } func isString(t Type) bool { return isBasic(t, IsString) } func isIntegerOrFloat(t Type) bool { return isBasic(t, IsInteger|IsFloat) } +func isConstType(t Type) bool { return isBasic(t, IsConstType) } // isBasic reports whether under(t) is a basic type with the specified info. // If t is a type parameter the result is false; i.e., @@ -74,36 +56,50 @@ func allBasic(t Type, info BasicInfo) bool { return false } -// isTyped reports whether typ is typed; i.e., not an untyped +// hasName reports whether t has a name. This includes +// predeclared types, defined types, and type parameters. +// hasName may be called with types that are not fully set up. +func hasName(t Type) bool { + switch t.(type) { + case *Basic, *Named, *TypeParam: + return true + } + return false +} + +// isTyped reports whether t is typed; i.e., not an untyped // constant or boolean. isTyped may be called with types that // are not fully set up. -func isTyped(typ Type) bool { +func isTyped(t Type) bool { // isTyped is called with types that are not fully // set up. Must not call asBasic()! - t, _ := typ.(*Basic) - return t == nil || t.info&IsUntyped == 0 + b, _ := t.(*Basic) + return b == nil || b.info&IsUntyped == 0 } -// isUntyped(typ) is the same as !isTyped(typ). -func isUntyped(typ Type) bool { - return !isTyped(typ) +// isUntyped(t) is the same as !isTyped(t). +func isUntyped(t Type) bool { + return !isTyped(t) } -func isConstType(typ Type) bool { - // Type parameters are never const types. - t := asBasic(typ) - return t != nil && t.info&IsConstType != 0 +// IsInterface reports whether t is an interface type. +func IsInterface(t Type) bool { + return asInterface(t) != nil } -// IsInterface reports whether typ is an interface type. -func IsInterface(typ Type) bool { - return asInterface(typ) != nil +// isTypeParam reports whether t is a type parameter. +func isTypeParam(t Type) bool { + _, ok := under(t).(*TypeParam) + return ok } -// isTypeParam reports whether typ is a type parameter. -func isTypeParam(typ Type) bool { - _, ok := under(typ).(*TypeParam) - return ok +// isGeneric reports whether a type is a generic, uninstantiated type +// (generic signatures are not included). +// TODO(gri) should we include signatures or assert that they are not present? +func isGeneric(t Type) bool { + // A parameterized type is only generic if it doesn't have an instantiation already. + named, _ := t.(*Named) + return named != nil && named.obj != nil && named.targs == nil && named.TypeParams() != nil } // Comparable reports whether values of type T are comparable. @@ -142,15 +138,15 @@ func comparable(T Type, seen map[Type]bool) bool { return false } -// hasNil reports whether a type includes the nil value. -func hasNil(typ Type) bool { - switch t := under(typ).(type) { +// hasNil reports whether type t includes the nil value. +func hasNil(t Type) bool { + switch u := under(t).(type) { case *Basic: - return t.kind == UnsafePointer + return u.kind == UnsafePointer case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan: return true case *TypeParam: - return t.underIs(hasNil) + return u.underIs(hasNil) } return false } @@ -392,9 +388,8 @@ func identicalTParams(x, y []*TypeParam, cmpTags bool, p *ifacePair) bool { // Default returns the default "typed" type for an "untyped" type; // it returns the incoming type for all other types. The default type // for untyped nil is untyped nil. -// -func Default(typ Type) Type { - if t, ok := typ.(*Basic); ok { +func Default(t Type) Type { + if t, ok := t.(*Basic); ok { switch t.kind { case UntypedBool: return Typ[Bool] @@ -410,5 +405,5 @@ func Default(typ Type) Type { return Typ[String] } } - return typ + return t } -- GitLab From 2cf85b1fb8b3b6629b834016735ddeaaf7b96fda Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 3 Nov 2021 12:39:43 -0700 Subject: [PATCH 1947/2500] cmd/compile/internal/types2: implement compiler helper functions without using under These functions are exported for the compiler and are used after type checking is finished. There is no need to call under() in their implementations; they can rely entirely on the public API. This opens the door to moving them into the compiler eventually. They may also be slightly more efficient. Change-Id: Ib4f83d2dcf82e3c319c3147e01ecaea684553ea5 Reviewed-on: https://go-review.googlesource.com/c/go/+/361214 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/type.go | 34 ++++++++++++++++++++----- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 33d3d3642c..300c81f5fa 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -81,10 +81,32 @@ func asTypeParam(t Type) *TypeParam { return u } -// Exported for the compiler. +// Helper functions exported for the compiler. +// These functions assume type checking has completed +// and Type.Underlying() is returning the fully set up +// underlying type. Do not use internally. -func AsPointer(t Type) *Pointer { return asPointer(t) } -func AsNamed(t Type) *Named { return asNamed(t) } -func AsSignature(t Type) *Signature { return asSignature(t) } -func AsInterface(t Type) *Interface { return asInterface(t) } -func AsTypeParam(t Type) *TypeParam { return asTypeParam(t) } +func AsPointer(t Type) *Pointer { + u, _ := t.Underlying().(*Pointer) + return u +} + +func AsNamed(t Type) *Named { + u, _ := t.(*Named) + return u +} + +func AsSignature(t Type) *Signature { + u, _ := t.Underlying().(*Signature) + return u +} + +func AsInterface(t Type) *Interface { + u, _ := t.Underlying().(*Interface) + return u +} + +func AsTypeParam(t Type) *TypeParam { + u, _ := t.Underlying().(*TypeParam) + return u +} -- GitLab From 2622235a99800d1d7add47c5c138f5efbe51361c Mon Sep 17 00:00:00 2001 From: Alex Brainman Date: Sun, 31 Oct 2021 17:58:34 +1100 Subject: [PATCH 1948/2500] runtime: do not generate crash dump on Windows 7 It appears Windows 7 ignores WER_FAULT_REPORTING_NO_UI WerSetFlags API flag. And now after CL 307372, runtime will display WER GUI dialogue. We don't want to introduce random GUI dialogues during Go program execution. So disable dump crash creation on Windows 7 altogether. Updates #20498 Change-Id: Ie268a7d4609f8a0eba4fe9ecf250856b0a61b331 Reviewed-on: https://go-review.googlesource.com/c/go/+/360617 Trust: Alex Brainman Run-TryBot: Alex Brainman TryBot-Result: Go Bot Reviewed-by: Patrik Nyblom --- src/runtime/signal_windows.go | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/runtime/signal_windows.go b/src/runtime/signal_windows.go index ca4a9ea451..b036f3c965 100644 --- a/src/runtime/signal_windows.go +++ b/src/runtime/signal_windows.go @@ -22,8 +22,16 @@ func disableWER() { stdcall1(_SetErrorMode, uintptr(errormode)|SEM_FAILCRITICALERRORS|SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX) } +// isWin7 returns true on Windows 7. Otherwise it returns false. +// +//go:nosplit +func isWin7() bool { + var maj, min, build uint32 + stdcall3(_RtlGetNtVersionNumbers, uintptr(unsafe.Pointer(&maj)), uintptr(unsafe.Pointer(&min)), uintptr(unsafe.Pointer(&build))) + return maj < 6 || (maj == 6 && min <= 1) +} + // enableWERNoUI re-enables Windows error reporting without fault reporting UI. -// It returns false on older Windows versions (XP and earlier) where WerSetFlags() is not supported. // // This is marked nosplit since it is used during crash. // @@ -224,9 +232,14 @@ func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 { _, _, docrash := gotraceback() if docrash { - // trigger crash dump creation - if enableWERNoUI() { - return _EXCEPTION_CONTINUE_SEARCH + // Windows 7 apears to ignore WER_FAULT_REPORTING_NO_UI + // WerSetFlags API flag. So do not call enableWERNoUI + // on Windows 7. + if !isWin7() { + // trigger crash dump creation + if enableWERNoUI() { + return _EXCEPTION_CONTINUE_SEARCH + } } } exit(2) -- GitLab From a3f7be9b8cee00aa281a0bedeae22b4cd4bc64dd Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Wed, 3 Nov 2021 22:15:17 -0400 Subject: [PATCH 1949/2500] net/http: reduce TestClientTimeout_h{1,2} latency The test had been setting an arbitrary 200ms timeout to allow the server's handler to set up before timing out. That is not only potentially flaky on slow machines, but also typically much longer than necessary. Replace the hard-coded timeout with a much shorter initial timeout, and use exponential backoff to lengthen it if needed. This allows the test to be run about 20x faster in the typical case, which may make it easier to reproduce rare failure modes by running with a higher -count flag. For #43120 Change-Id: I1e0d0ec99d5a107fff56e3bcc7174d686ec582d1 Reviewed-on: https://go-review.googlesource.com/c/go/+/361275 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Damien Neil --- src/net/http/client_test.go | 100 +++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 42 deletions(-) diff --git a/src/net/http/client_test.go b/src/net/http/client_test.go index e741c3746f..fb6fbe7197 100644 --- a/src/net/http/client_test.go +++ b/src/net/http/client_test.go @@ -1205,64 +1205,80 @@ func TestClientTimeout_h2(t *testing.T) { testClientTimeout(t, h2Mode) } func testClientTimeout(t *testing.T, h2 bool) { setParallel(t) defer afterTest(t) - testDone := make(chan struct{}) // closed in defer below - sawRoot := make(chan bool, 1) - sawSlow := make(chan bool, 1) + var ( + mu sync.Mutex + nonce string // a unique per-request string + sawSlowNonce bool // true if the handler saw /slow?nonce= + ) cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { + _ = r.ParseForm() if r.URL.Path == "/" { - sawRoot <- true - Redirect(w, r, "/slow", StatusFound) + Redirect(w, r, "/slow?nonce="+r.Form.Get("nonce"), StatusFound) return } if r.URL.Path == "/slow" { - sawSlow <- true + mu.Lock() + if r.Form.Get("nonce") == nonce { + sawSlowNonce = true + } else { + t.Logf("mismatched nonce: received %s, want %s", r.Form.Get("nonce"), nonce) + } + mu.Unlock() + w.Write([]byte("Hello")) w.(Flusher).Flush() - <-testDone + <-r.Context().Done() return } })) defer cst.close() - defer close(testDone) // before cst.close, to unblock /slow handler - // 200ms should be long enough to get a normal request (the / - // handler), but not so long that it makes the test slow. - const timeout = 200 * time.Millisecond - cst.c.Timeout = timeout - - res, err := cst.c.Get(cst.ts.URL) - if err != nil { - if strings.Contains(err.Error(), "Client.Timeout") { - t.Skipf("host too slow to get fast resource in %v", timeout) + // Try to trigger a timeout after reading part of the response body. + // The initial timeout is emprically usually long enough on a decently fast + // machine, but if we undershoot we'll retry with exponentially longer + // timeouts until the test either passes or times out completely. + // This keeps the test reasonably fast in the typical case but allows it to + // also eventually succeed on arbitrarily slow machines. + timeout := 10 * time.Millisecond + nextNonce := 0 + for ; ; timeout *= 2 { + if timeout <= 0 { + // The only way we can feasibly hit this while the test is running is if + // the request fails without actually waiting for the timeout to occur. + t.Fatalf("timeout overflow") + } + if deadline, ok := t.Deadline(); ok && !time.Now().Add(timeout).Before(deadline) { + t.Fatalf("failed to produce expected timeout before test deadline") + } + t.Logf("attempting test with timeout %v", timeout) + cst.c.Timeout = timeout + + mu.Lock() + nonce = fmt.Sprint(nextNonce) + nextNonce++ + sawSlowNonce = false + mu.Unlock() + res, err := cst.c.Get(cst.ts.URL + "/?nonce=" + nonce) + if err != nil { + if strings.Contains(err.Error(), "Client.Timeout") { + // Timed out before handler could respond. + t.Logf("timeout before response received") + continue + } + t.Fatal(err) } - t.Fatal(err) - } - select { - case <-sawRoot: - // good. - default: - t.Fatal("handler never got / request") - } - - select { - case <-sawSlow: - // good. - default: - t.Fatal("handler never got /slow request") - } + mu.Lock() + ok := sawSlowNonce + mu.Unlock() + if !ok { + t.Fatal("handler never got /slow request, but client returned response") + } - errc := make(chan error, 1) - go func() { - _, err := io.ReadAll(res.Body) - errc <- err + _, err = io.ReadAll(res.Body) res.Body.Close() - }() - const failTime = 5 * time.Second - select { - case err := <-errc: if err == nil { t.Fatal("expected error from ReadAll") } @@ -1275,8 +1291,8 @@ func testClientTimeout(t *testing.T, h2 bool) { if got := ne.Error(); !strings.Contains(got, "(Client.Timeout") { t.Errorf("error string = %q; missing timeout substring", got) } - case <-time.After(failTime): - t.Errorf("timeout after %v waiting for timeout of %v", failTime, timeout) + + break } } -- GitLab From 901bf291bc90819cb6dad76064475cf9ecbc9651 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Thu, 3 Dec 2020 13:29:58 +0100 Subject: [PATCH 1950/2500] runtime: allow builtin write function to be redirected with function pointer The x/sys/windows package currently uses go:linkname for other facilities inside of runtime that are not suitable to be exposed as a public API due to their dangers but are still necessary for manipulating any low-level plumbing that the runtime controls. Logging, via the built-in println and panic handler, is one such low-level plumbing feature. In this case, x/sys/windows/svc needs to be able to redirect panics to the Windows event log. Because the event log is a complicated interface, this requires a bit more fiddling than the simple solution used on Android (baking it into runtime itself), and because Windows services are very diverse, the event log might not even always be a desirable destination. This commit accomplishes this by exposing a function pointer called "overrideWrite" that low-level runtime packages like x/sys/windows/svc can use to redirect output logs toward the event log or otherwise. It is not safe or acceptable to use as a generic mechanism, and for that reason, we wouldn't want to expose this as a real stable API, similar to the other instances of go:linkname in x/sys/windows. But for packages that must interoperate with low-level Go runtime fundamentals, this is a safety hatch for packages that are developed in tandem with the runtime. x/sys/windows is one such package. Updates #42888. Change-Id: I77a32ff7e1494324e8cc38e792e007f86d32672d Reviewed-on: https://go-review.googlesource.com/c/go/+/278792 Trust: Jason A. Donenfeld Run-TryBot: Jason A. Donenfeld TryBot-Result: Go Bot Reviewed-by: Russ Cox --- src/runtime/time_nofake.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/runtime/time_nofake.go b/src/runtime/time_nofake.go index 2b85c5aa01..70a2102b22 100644 --- a/src/runtime/time_nofake.go +++ b/src/runtime/time_nofake.go @@ -19,9 +19,14 @@ func nanotime() int64 { return nanotime1() } +var overrideWrite func(fd uintptr, p unsafe.Pointer, n int32) int32 + // write must be nosplit on Windows (see write1) // //go:nosplit func write(fd uintptr, p unsafe.Pointer, n int32) int32 { + if overrideWrite != nil { + return overrideWrite(fd, noescape(p), n) + } return write1(fd, p, n) } -- GitLab From 00d6d2037ee1bf4b6959219120b79b7c01244b02 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Fri, 29 Oct 2021 17:41:41 -0400 Subject: [PATCH 1951/2500] cmd/doc, go/doc: add basic support for generic code Update cmd/doc and go/doc for the generics, by adding handling for type parameters and the new embedded interface elements. Specifically: - Format type parameters when summarizing type and function nodes. - Find the origin type name for instantiation expressions, so that methods are associated with generic type declarations. - Generalize the handling of embedding 'error' in interfaces to arbitrary predeclared types. - Keep embedded type literals. - Update filtering to descend into embedded type literals. Also add "any" to the list of predeclared types. Updates #49210 Change-Id: I6ea82869f19c3cdbc3c842f01581c8fc7e1c2ee7 Reviewed-on: https://go-review.googlesource.com/c/go/+/359778 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/doc/pkg.go | 21 ++++++-- src/go/doc/exports.go | 58 +++++++++++++++------- src/go/doc/filter.go | 2 + src/go/doc/reader.go | 29 +++++++---- src/go/doc/testdata/generics.0.golden | 70 +++++++++++++++++++++++++++ src/go/doc/testdata/generics.1.golden | 60 +++++++++++++++++++++++ src/go/doc/testdata/generics.2.golden | 70 +++++++++++++++++++++++++++ src/go/doc/testdata/generics.go | 61 +++++++++++++++++++++++ 8 files changed, 339 insertions(+), 32 deletions(-) create mode 100644 src/go/doc/testdata/generics.0.golden create mode 100644 src/go/doc/testdata/generics.1.golden create mode 100644 src/go/doc/testdata/generics.2.golden create mode 100644 src/go/doc/testdata/generics.go diff --git a/src/cmd/doc/pkg.go b/src/cmd/doc/pkg.go index 822c9e16f8..2257c5c0eb 100644 --- a/src/cmd/doc/pkg.go +++ b/src/cmd/doc/pkg.go @@ -323,7 +323,8 @@ func (pkg *Package) oneLineNodeDepth(node ast.Node, depth int) string { if n.Assign.IsValid() { sep = " = " } - return fmt.Sprintf("type %s%s%s", n.Name.Name, sep, pkg.oneLineNodeDepth(n.Type, depth)) + tparams := pkg.formatTypeParams(n.TypeParams, depth) + return fmt.Sprintf("type %s%s%s%s", n.Name.Name, tparams, sep, pkg.oneLineNodeDepth(n.Type, depth)) case *ast.FuncType: var params []string @@ -342,15 +343,16 @@ func (pkg *Package) oneLineNodeDepth(node ast.Node, depth int) string { } } + tparam := pkg.formatTypeParams(n.TypeParams, depth) param := joinStrings(params) if len(results) == 0 { - return fmt.Sprintf("func(%s)", param) + return fmt.Sprintf("func%s(%s)", tparam, param) } result := joinStrings(results) if !needParens { - return fmt.Sprintf("func(%s) %s", param, result) + return fmt.Sprintf("func%s(%s) %s", tparam, param, result) } - return fmt.Sprintf("func(%s) (%s)", param, result) + return fmt.Sprintf("func%s(%s) (%s)", tparam, param, result) case *ast.StructType: if n.Fields == nil || len(n.Fields.List) == 0 { @@ -419,6 +421,17 @@ func (pkg *Package) oneLineNodeDepth(node ast.Node, depth int) string { } } +func (pkg *Package) formatTypeParams(list *ast.FieldList, depth int) string { + if list.NumFields() == 0 { + return "" + } + var tparams []string + for _, field := range list.List { + tparams = append(tparams, pkg.oneLineField(field, depth)) + } + return "[" + joinStrings(tparams) + "]" +} + // oneLineField returns a one-line summary of the field. func (pkg *Package) oneLineField(field *ast.Field, depth int) string { var names []string diff --git a/src/go/doc/exports.go b/src/go/doc/exports.go index 819c030c9b..671c622205 100644 --- a/src/go/doc/exports.go +++ b/src/go/doc/exports.go @@ -79,18 +79,15 @@ func hasExportedName(list []*ast.Ident) bool { return false } -// removeErrorField removes anonymous fields named "error" from an interface. -// This is called when "error" has been determined to be a local name, -// not the predeclared type. -// -func removeErrorField(ityp *ast.InterfaceType) { +// removeAnonymousField removes anonymous fields named name from an interface. +func removeAnonymousField(name string, ityp *ast.InterfaceType) { list := ityp.Methods.List // we know that ityp.Methods != nil j := 0 for _, field := range list { keepField := true if n := len(field.Names); n == 0 { // anonymous field - if fname, _ := baseTypeName(field.Type); fname == "error" { + if fname, _ := baseTypeName(field.Type); fname == name { keepField = false } } @@ -119,16 +116,25 @@ func (r *reader) filterFieldList(parent *namedType, fields *ast.FieldList, ityp for _, field := range list { keepField := false if n := len(field.Names); n == 0 { - // anonymous field + // anonymous field or embedded type or union element fname := r.recordAnonymousField(parent, field.Type) - if token.IsExported(fname) { - keepField = true - } else if ityp != nil && fname == "error" { - // possibly the predeclared error interface; keep - // it for now but remember this interface so that - // it can be fixed if error is also defined locally - keepField = true - r.remember(ityp) + if fname != "" { + if token.IsExported(fname) { + keepField = true + } else if ityp != nil && predeclaredTypes[fname] { + // possibly an embedded predeclared type; keep it for now but + // remember this interface so that it can be fixed if name is also + // defined locally + keepField = true + r.remember(fname, ityp) + } + } else { + // If we're operating on an interface, assume that this is an embedded + // type or union element. + // + // TODO(rfindley): consider traversing into approximation/unions + // elements to see if they are entirely unexported. + keepField = ityp != nil } } else { field.Names = filterIdentList(field.Names) @@ -172,6 +178,17 @@ func (r *reader) filterType(parent *namedType, typ ast.Expr) { // nothing to do case *ast.ParenExpr: r.filterType(nil, t.X) + case *ast.StarExpr: // possibly an embedded type literal + r.filterType(nil, t.X) + case *ast.UnaryExpr: + if t.Op == token.TILDE { // approximation element + r.filterType(nil, t.X) + } + case *ast.BinaryExpr: + if t.Op == token.OR { // union + r.filterType(nil, t.X) + r.filterType(nil, t.Y) + } case *ast.ArrayType: r.filterType(nil, t.Elt) case *ast.StructType: @@ -179,6 +196,7 @@ func (r *reader) filterType(parent *namedType, typ ast.Expr) { t.Incomplete = true } case *ast.FuncType: + r.filterParamList(t.TypeParams) r.filterParamList(t.Params) r.filterParamList(t.Results) case *ast.InterfaceType: @@ -219,12 +237,16 @@ func (r *reader) filterSpec(spec ast.Spec) bool { } } case *ast.TypeSpec: + // Don't filter type parameters here, by analogy with function parameters + // which are not filtered for top-level function declarations. if name := s.Name.Name; token.IsExported(name) { r.filterType(r.lookupType(s.Name.Name), s.Type) return true - } else if name == "error" { - // special case: remember that error is declared locally - r.errorDecl = true + } else if IsPredeclared(name) { + if r.shadowedPredecl == nil { + r.shadowedPredecl = make(map[string]bool) + } + r.shadowedPredecl[name] = true } } return false diff --git a/src/go/doc/filter.go b/src/go/doc/filter.go index a6f243f33e..9904da150e 100644 --- a/src/go/doc/filter.go +++ b/src/go/doc/filter.go @@ -34,6 +34,8 @@ func matchDecl(d *ast.GenDecl, f Filter) bool { if f(v.Name.Name) { return true } + // We don't match ordinary parameters in filterFuncs, so by analogy don't + // match type parameters here. switch t := v.Type.(type) { case *ast.StructType: if matchFields(t.Fields, f) { diff --git a/src/go/doc/reader.go b/src/go/doc/reader.go index c277b35e89..348b9b59a0 100644 --- a/src/go/doc/reader.go +++ b/src/go/doc/reader.go @@ -101,6 +101,10 @@ func baseTypeName(x ast.Expr) (name string, imported bool) { switch t := x.(type) { case *ast.Ident: return t.Name, false + case *ast.IndexExpr: + return baseTypeName(t.X) + case *ast.IndexListExpr: + return baseTypeName(t.X) case *ast.SelectorExpr: if _, ok := t.X.(*ast.Ident); ok { // only possible for qualified type names; @@ -112,7 +116,7 @@ func baseTypeName(x ast.Expr) (name string, imported bool) { case *ast.StarExpr: return baseTypeName(t.X) } - return + return "", false } // An embeddedSet describes a set of embedded types. @@ -163,9 +167,9 @@ type reader struct { types map[string]*namedType funcs methodSet - // support for package-local error type declarations - errorDecl bool // if set, type "error" was declared locally - fixlist []*ast.InterfaceType // list of interfaces containing anonymous field "error" + // support for package-local shadowing of predeclared types + shadowedPredecl map[string]bool + fixmap map[string][]*ast.InterfaceType } func (r *reader) isVisible(name string) bool { @@ -224,8 +228,11 @@ func (r *reader) readDoc(comment *ast.CommentGroup) { r.doc += "\n" + text } -func (r *reader) remember(typ *ast.InterfaceType) { - r.fixlist = append(r.fixlist, typ) +func (r *reader) remember(predecl string, typ *ast.InterfaceType) { + if r.fixmap == nil { + r.fixmap = make(map[string][]*ast.InterfaceType) + } + r.fixmap[predecl] = append(r.fixmap[predecl], typ) } func specNames(specs []ast.Spec) []string { @@ -679,10 +686,11 @@ func (r *reader) computeMethodSets() { } } - // if error was declared locally, don't treat it as exported field anymore - if r.errorDecl { - for _, ityp := range r.fixlist { - removeErrorField(ityp) + // For any predeclared names that are declared locally, don't treat them as + // exported fields anymore. + for predecl := range r.shadowedPredecl { + for _, ityp := range r.fixmap[predecl] { + removeAnonymousField(predecl, ityp) } } } @@ -869,6 +877,7 @@ func IsPredeclared(s string) bool { } var predeclaredTypes = map[string]bool{ + "any": true, "bool": true, "byte": true, "complex64": true, diff --git a/src/go/doc/testdata/generics.0.golden b/src/go/doc/testdata/generics.0.golden new file mode 100644 index 0000000000..a6dbcf673c --- /dev/null +++ b/src/go/doc/testdata/generics.0.golden @@ -0,0 +1,70 @@ +// Package generics contains the new syntax supporting generic ... +PACKAGE generics + +IMPORTPATH + testdata/generics + +FILENAMES + testdata/generics.go + +FUNCTIONS + // AnotherFunc has an implicit constraint interface. Neither type ... + func AnotherFunc[T ~struct{ f int }](_ struct{ f int }) + + // Func has an instantiated constraint. + func Func[T Constraint[string, Type[int]]]() + + +TYPES + // AFuncType demonstrates filtering of parameters and type ... + type AFuncType[T ~struct{ f int }] func(_ struct { + // contains filtered or unexported fields + }) + + // Constraint is a constraint interface with two type parameters. + type Constraint[P, Q interface{ string | ~int | Type[int] }] interface { + ~int | ~byte | Type[string] + M() P + } + + // NewEmbeddings demonstrates how we filter the new embedded ... + type NewEmbeddings interface { + string // should not be filtered + + struct { + // contains filtered or unexported fields + } + ~struct { + // contains filtered or unexported fields + } + *struct { + // contains filtered or unexported fields + } + struct { + // contains filtered or unexported fields + } | ~struct { + // contains filtered or unexported fields + } + // contains filtered or unexported methods + } + + // Parameterized types should be shown. + type Type[P any] struct { + Field P + } + + // Variables with an instantiated type should be shown. + var X Type[int] + + // Constructors for parameterized types should be shown. + func Constructor[lowerCase any]() Type[lowerCase] + + // MethodA uses a different name for its receiver type parameter. + func (t Type[A]) MethodA(p A) + + // MethodB has a blank receiver type parameter. + func (t Type[_]) MethodB() + + // MethodC has a lower-case receiver type parameter. + func (t Type[c]) MethodC() + diff --git a/src/go/doc/testdata/generics.1.golden b/src/go/doc/testdata/generics.1.golden new file mode 100644 index 0000000000..c0548b5e96 --- /dev/null +++ b/src/go/doc/testdata/generics.1.golden @@ -0,0 +1,60 @@ +// Package generics contains the new syntax supporting generic ... +PACKAGE generics + +IMPORTPATH + testdata/generics + +FILENAMES + testdata/generics.go + +FUNCTIONS + // AnotherFunc has an implicit constraint interface. Neither type ... + func AnotherFunc[T ~struct{ f int }](_ struct{ f int }) + + // Func has an instantiated constraint. + func Func[T Constraint[string, Type[int]]]() + + +TYPES + // AFuncType demonstrates filtering of parameters and type ... + type AFuncType[T ~struct{ f int }] func(_ struct{ f int }) + + // Constraint is a constraint interface with two type parameters. + type Constraint[P, Q interface{ string | ~int | Type[int] }] interface { + ~int | ~byte | Type[string] + M() P + } + + // NewEmbeddings demonstrates how we filter the new embedded ... + type NewEmbeddings interface { + string // should not be filtered + int16 + struct{ f int } + ~struct{ f int } + *struct{ f int } + struct{ f int } | ~struct{ f int } + } + + // Parameterized types should be shown. + type Type[P any] struct { + Field P + } + + // Variables with an instantiated type should be shown. + var X Type[int] + + // Constructors for parameterized types should be shown. + func Constructor[lowerCase any]() Type[lowerCase] + + // MethodA uses a different name for its receiver type parameter. + func (t Type[A]) MethodA(p A) + + // MethodB has a blank receiver type parameter. + func (t Type[_]) MethodB() + + // MethodC has a lower-case receiver type parameter. + func (t Type[c]) MethodC() + + // int16 shadows the predeclared type int16. + type int16 int + diff --git a/src/go/doc/testdata/generics.2.golden b/src/go/doc/testdata/generics.2.golden new file mode 100644 index 0000000000..a6dbcf673c --- /dev/null +++ b/src/go/doc/testdata/generics.2.golden @@ -0,0 +1,70 @@ +// Package generics contains the new syntax supporting generic ... +PACKAGE generics + +IMPORTPATH + testdata/generics + +FILENAMES + testdata/generics.go + +FUNCTIONS + // AnotherFunc has an implicit constraint interface. Neither type ... + func AnotherFunc[T ~struct{ f int }](_ struct{ f int }) + + // Func has an instantiated constraint. + func Func[T Constraint[string, Type[int]]]() + + +TYPES + // AFuncType demonstrates filtering of parameters and type ... + type AFuncType[T ~struct{ f int }] func(_ struct { + // contains filtered or unexported fields + }) + + // Constraint is a constraint interface with two type parameters. + type Constraint[P, Q interface{ string | ~int | Type[int] }] interface { + ~int | ~byte | Type[string] + M() P + } + + // NewEmbeddings demonstrates how we filter the new embedded ... + type NewEmbeddings interface { + string // should not be filtered + + struct { + // contains filtered or unexported fields + } + ~struct { + // contains filtered or unexported fields + } + *struct { + // contains filtered or unexported fields + } + struct { + // contains filtered or unexported fields + } | ~struct { + // contains filtered or unexported fields + } + // contains filtered or unexported methods + } + + // Parameterized types should be shown. + type Type[P any] struct { + Field P + } + + // Variables with an instantiated type should be shown. + var X Type[int] + + // Constructors for parameterized types should be shown. + func Constructor[lowerCase any]() Type[lowerCase] + + // MethodA uses a different name for its receiver type parameter. + func (t Type[A]) MethodA(p A) + + // MethodB has a blank receiver type parameter. + func (t Type[_]) MethodB() + + // MethodC has a lower-case receiver type parameter. + func (t Type[c]) MethodC() + diff --git a/src/go/doc/testdata/generics.go b/src/go/doc/testdata/generics.go new file mode 100644 index 0000000000..b5debba437 --- /dev/null +++ b/src/go/doc/testdata/generics.go @@ -0,0 +1,61 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package generics contains the new syntax supporting generic programming in +// Go. +package generics + +// Variables with an instantiated type should be shown. +var X Type[int] + +// Parameterized types should be shown. +type Type[P any] struct { + Field P +} + +// Constructors for parameterized types should be shown. +func Constructor[lowerCase any]() Type[lowerCase] { + return Type[lowerCase]{} +} + +// MethodA uses a different name for its receiver type parameter. +func (t Type[A]) MethodA(p A) {} + +// MethodB has a blank receiver type parameter. +func (t Type[_]) MethodB() {} + +// MethodC has a lower-case receiver type parameter. +func (t Type[c]) MethodC() {} + +// Constraint is a constraint interface with two type parameters. +type Constraint[P, Q interface{ string | ~int | Type[int] }] interface { + ~int | ~byte | Type[string] + M() P +} + +// int16 shadows the predeclared type int16. +type int16 int + +// NewEmbeddings demonstrates how we filter the new embedded elements. +type NewEmbeddings interface { + string // should not be filtered + int16 + struct{ f int } + ~struct{ f int } + *struct{ f int } + struct{ f int } | ~struct{ f int } +} + +// Func has an instantiated constraint. +func Func[T Constraint[string, Type[int]]]() {} + +// AnotherFunc has an implicit constraint interface. +// +// Neither type parameters nor regular parameters should be filtered. +func AnotherFunc[T ~struct{ f int }](_ struct{ f int }) {} + +// AFuncType demonstrates filtering of parameters and type parameters. Here we +// don't filter type parameters (to be consistent with function declarations), +// but DO filter the RHS. +type AFuncType[T ~struct{ f int }] func(_ struct{ f int }) -- GitLab From 6ba68a0581d537edfd6eb2e5675c408f18eb4eed Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 3 Nov 2021 14:47:04 -0700 Subject: [PATCH 1952/2500] cmd/compile: don't inline fn with no shape params, but passed a shape arg Don't inline a function fn that has no shape parameters, but is passed at least one shape arg. This means we must be inlining a non-generic function fn that was passed into a generic function, and can be called with a shape arg because it matches an appropriate type parameter. But fn may include an interface conversion (that may be applied to a shape arg) that was not apparent when we first created the instantiation of the generic function. We can't handle this if we actually do the inlining, since we want to know all interface conversions immediately after stenciling. So, we avoid inlining in this case. Fixes #49309. Change-Id: I7b8ab7b13e58fdb0111db91bc92a91d313f7c2c3 Reviewed-on: https://go-review.googlesource.com/c/go/+/361260 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/inline/inl.go | 21 +++++++++++++++++++++ test/typeparam/issue49309.go | 25 +++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 test/typeparam/issue49309.go diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index da905bd627..b764aed534 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -685,6 +685,27 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b return n } + // Don't inline a function fn that has no shape parameters, but is passed at + // least one shape arg. This means we must be inlining a non-generic function + // fn that was passed into a generic function, and can be called with a shape + // arg because it matches an appropriate type parameters. But fn may include + // an interface conversion (that may be applied to a shape arg) that was not + // apparent when we first created the instantiation of the generic function. + // We can't handle this if we actually do the inlining, since we want to know + // all interface conversions immediately after stenciling. So, we avoid + // inlining in this case. See #49309. + if !fn.Type().HasShape() { + for _, arg := range n.Args { + if arg.Type().HasShape() { + if logopt.Enabled() { + logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", ir.FuncName(ir.CurFunc), + fmt.Sprintf("inlining non-shape function %v with shape args", ir.FuncName(fn))) + } + return n + } + } + } + if base.Flag.Cfg.Instrumenting && types.IsRuntimePkg(fn.Sym().Pkg) { // Runtime package must not be instrumented. // Instrument skips runtime package. However, some runtime code can be diff --git a/test/typeparam/issue49309.go b/test/typeparam/issue49309.go new file mode 100644 index 0000000000..36da86a9c3 --- /dev/null +++ b/test/typeparam/issue49309.go @@ -0,0 +1,25 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func genfunc[T any](f func(c T)) { + var r T + + f(r) +} + +func myfunc(c string) { + test2(c) +} + +//go:noinline +func test2(a interface{}) { +} + +func main() { + genfunc(myfunc) +} -- GitLab From f934b8326f18c4be2cb26ed1e87621d926ba209b Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 3 Nov 2021 20:42:44 -0700 Subject: [PATCH 1953/2500] cmd/compile/internal/types2: check non-generic conversions first This enables the elimination of convertibleToImpl again, with the code structure close to the original non-generic version, and closely matching the structure of assignableTo. We also don't need the hasTerm tests; instead we can rely directly on the mechanism of TypeParam.is which is feeding a nil term if there are no specific types. Change-Id: I0385acca779d75c3c961d06afb464714fe51705d Reviewed-on: https://go-review.googlesource.com/c/go/+/361269 Trust: Robert Griesemer Reviewed-by: Robert Findley --- .../compile/internal/types2/conversions.go | 119 +++++++++--------- 1 file changed, 62 insertions(+), 57 deletions(-) diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go index bd7b82fabf..44e8aad84f 100644 --- a/src/cmd/compile/internal/types2/conversions.go +++ b/src/cmd/compile/internal/types2/conversions.go @@ -122,64 +122,8 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { return true } - // determine type parameter operands with specific type terms - Vp, _ := under(x.typ).(*TypeParam) - Tp, _ := under(T).(*TypeParam) - if Vp != nil && !Vp.hasTerms() { - Vp = nil - } - if Tp != nil && !Tp.hasTerms() { - Tp = nil - } - - errorf := func(format string, args ...interface{}) { - if check != nil && cause != nil { - msg := check.sprintf(format, args...) - if *cause != "" { - msg += "\n\t" + *cause - } - *cause = msg - } - } - - // generic cases with specific type terms - // (generic operands cannot be constants, so we can ignore x.val) - switch { - case Vp != nil && Tp != nil: - return Vp.is(func(V *term) bool { - return Tp.is(func(T *term) bool { - if !convertibleToImpl(check, V.typ, T.typ, cause) { - errorf("cannot convert %s (in %s) to %s (in %s)", V.typ, Vp, T.typ, Tp) - return false - } - return true - }) - }) - case Vp != nil: - return Vp.is(func(V *term) bool { - if !convertibleToImpl(check, V.typ, T, cause) { - errorf("cannot convert %s (in %s) to %s", V.typ, Vp, T) - return false - } - return true - }) - case Tp != nil: - return Tp.is(func(T *term) bool { - if !convertibleToImpl(check, x.typ, T.typ, cause) { - errorf("cannot convert %s to %s (in %s)", x.typ, T.typ, Tp) - return false - } - return true - }) - } - - // non-generic case - return convertibleToImpl(check, x.typ, T, cause) -} - -// convertibleToImpl should only be called by convertibleTo -func convertibleToImpl(check *Checker, V, T Type, cause *string) bool { // "V and T have identical underlying types if tags are ignored" + V := x.typ Vu := under(V) Tu := under(T) if IdenticalIgnoreTags(Vu, Tu) { @@ -250,6 +194,67 @@ func convertibleToImpl(check *Checker, V, T Type, cause *string) bool { } } + // optimization: if we don't have type parameters, we're done + Vp, _ := Vu.(*TypeParam) + Tp, _ := Tu.(*TypeParam) + if Vp == nil && Tp == nil { + return false + } + + errorf := func(format string, args ...interface{}) { + if check != nil && cause != nil { + msg := check.sprintf(format, args...) + if *cause != "" { + msg += "\n\t" + *cause + } + *cause = msg + } + } + + // generic cases with specific type terms + // (generic operands cannot be constants, so we can ignore x.val) + switch { + case Vp != nil && Tp != nil: + x := *x // don't clobber outer x + return Vp.is(func(V *term) bool { + if V == nil { + return false // no specific types + } + x.typ = V.typ + return Tp.is(func(T *term) bool { + if !x.convertibleTo(check, T.typ, cause) { + errorf("cannot convert %s (in %s) to %s (in %s)", V.typ, Vp, T.typ, Tp) + return false + } + return true + }) + }) + case Vp != nil: + x := *x // don't clobber outer x + return Vp.is(func(V *term) bool { + if V == nil { + return false // no specific types + } + x.typ = V.typ + if !x.convertibleTo(check, T, cause) { + errorf("cannot convert %s (in %s) to %s", V.typ, Vp, T) + return false + } + return true + }) + case Tp != nil: + return Tp.is(func(T *term) bool { + if T == nil { + return false // no specific types + } + if !x.convertibleTo(check, T.typ, cause) { + errorf("cannot convert %s to %s (in %s)", x.typ, T.typ, Tp) + return false + } + return true + }) + } + return false } -- GitLab From 6e7b82a4bbd08e5724a29e204faf97342a0b6a15 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Thu, 4 Nov 2021 08:46:07 -0400 Subject: [PATCH 1954/2500] cmd/pprof: update vendored github.com/google/pprof Pull in the latest published version of github.com/google/pprof as part of #36905. This adds the fmt.Println redundant newline fix from google/pprof@f987b9c94b318d4bd026dcc7892f7f1fab6eadab. Done with: go get -d github.com/google/pprof@latest go mod tidy go mod vendor For #36905. Fixes #49322. Change-Id: Ia832766bba65a30c68407b73b33fefbe81438e65 Reviewed-on: https://go-review.googlesource.com/c/go/+/361294 Trust: Dmitri Shuralyov Trust: Zvonimir Pavlinovic Run-TryBot: Dmitri Shuralyov Run-TryBot: Zvonimir Pavlinovic TryBot-Result: Go Bot Reviewed-by: Zvonimir Pavlinovic --- src/cmd/go.mod | 6 +- src/cmd/go.sum | 13 +- .../google/pprof/internal/elfexec/elfexec.go | 105 +- .../pprof/internal/report/source_html.go | 3 +- .../ianlancetaylor/demangle/README.md | 2 +- .../github.com/ianlancetaylor/demangle/ast.go | 982 +++++- .../ianlancetaylor/demangle/demangle.go | 574 ++- .../ianlancetaylor/demangle/rust.go | 1069 ++++++ .../vendor/golang.org/x/sys/unix/mkerrors.sh | 9 +- .../golang.org/x/sys/unix/syscall_darwin.go | 40 +- .../golang.org/x/sys/unix/syscall_illumos.go | 8 + .../golang.org/x/sys/unix/syscall_linux.go | 82 +- .../x/sys/unix/syscall_linux_386.go | 38 - .../x/sys/unix/syscall_linux_amd64.go | 48 - .../x/sys/unix/syscall_linux_arm.go | 42 - .../x/sys/unix/syscall_linux_arm64.go | 51 - .../x/sys/unix/syscall_linux_mips64x.go | 39 - .../x/sys/unix/syscall_linux_mipsx.go | 35 - .../x/sys/unix/syscall_linux_ppc.go | 38 - .../x/sys/unix/syscall_linux_ppc64x.go | 38 - .../x/sys/unix/syscall_linux_riscv64.go | 51 - .../x/sys/unix/syscall_linux_s390x.go | 36 - .../x/sys/unix/syscall_linux_sparc64.go | 37 - .../golang.org/x/sys/unix/sysvshm_linux.go | 21 + .../golang.org/x/sys/unix/sysvshm_unix.go | 61 + .../x/sys/unix/sysvshm_unix_other.go | 14 + .../x/sys/unix/zerrors_darwin_amd64.go | 3126 +++++++++-------- .../x/sys/unix/zerrors_darwin_arm64.go | 3126 +++++++++-------- .../golang.org/x/sys/unix/zerrors_linux.go | 16 + .../x/sys/unix/zsyscall_darwin_amd64.go | 59 + .../x/sys/unix/zsyscall_darwin_amd64.s | 24 + .../x/sys/unix/zsyscall_darwin_arm64.go | 59 + .../x/sys/unix/zsyscall_darwin_arm64.s | 24 + .../golang.org/x/sys/unix/zsyscall_linux.go | 69 +- .../x/sys/unix/zsyscall_linux_386.go | 53 - .../x/sys/unix/zsyscall_linux_amd64.go | 53 - .../x/sys/unix/zsyscall_linux_arm.go | 53 - .../x/sys/unix/zsyscall_linux_mips.go | 55 - .../x/sys/unix/zsyscall_linux_mips64.go | 32 - .../x/sys/unix/zsyscall_linux_mips64le.go | 32 - .../x/sys/unix/zsyscall_linux_mipsle.go | 55 - .../x/sys/unix/zsyscall_linux_ppc.go | 53 - .../x/sys/unix/zsyscall_linux_ppc64.go | 53 - .../x/sys/unix/zsyscall_linux_ppc64le.go | 53 - .../x/sys/unix/zsyscall_linux_s390x.go | 43 - .../x/sys/unix/zsyscall_linux_sparc64.go | 42 - .../x/sys/unix/ztypes_darwin_amd64.go | 127 + .../x/sys/unix/ztypes_darwin_arm64.go | 127 + .../x/sys/unix/ztypes_freebsd_386.go | 2 + .../x/sys/unix/ztypes_freebsd_amd64.go | 2 + .../x/sys/unix/ztypes_freebsd_arm.go | 2 + .../x/sys/unix/ztypes_freebsd_arm64.go | 2 + .../x/sys/unix/ztypes_illumos_amd64.go | 2 + .../golang.org/x/sys/unix/ztypes_linux.go | 33 + .../golang.org/x/sys/unix/ztypes_linux_386.go | 33 + .../x/sys/unix/ztypes_linux_amd64.go | 30 + .../golang.org/x/sys/unix/ztypes_linux_arm.go | 33 + .../x/sys/unix/ztypes_linux_arm64.go | 30 + .../x/sys/unix/ztypes_linux_mips.go | 32 + .../x/sys/unix/ztypes_linux_mips64.go | 30 + .../x/sys/unix/ztypes_linux_mips64le.go | 30 + .../x/sys/unix/ztypes_linux_mipsle.go | 32 + .../golang.org/x/sys/unix/ztypes_linux_ppc.go | 34 + .../x/sys/unix/ztypes_linux_ppc64.go | 29 + .../x/sys/unix/ztypes_linux_ppc64le.go | 29 + .../x/sys/unix/ztypes_linux_riscv64.go | 30 + .../x/sys/unix/ztypes_linux_s390x.go | 29 + .../x/sys/unix/ztypes_linux_sparc64.go | 29 + .../x/sys/windows/memory_windows.go | 11 + .../x/sys/windows/syscall_windows.go | 10 + .../golang.org/x/sys/windows/types_windows.go | 14 + .../x/sys/windows/zsyscall_windows.go | 90 + src/cmd/vendor/modules.txt | 8 +- src/go.mod | 2 +- src/go.sum | 4 +- src/vendor/modules.txt | 2 +- 76 files changed, 7006 insertions(+), 4384 deletions(-) create mode 100644 src/cmd/vendor/github.com/ianlancetaylor/demangle/rust.go create mode 100644 src/cmd/vendor/golang.org/x/sys/unix/sysvshm_linux.go create mode 100644 src/cmd/vendor/golang.org/x/sys/unix/sysvshm_unix.go create mode 100644 src/cmd/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go diff --git a/src/cmd/go.mod b/src/cmd/go.mod index e6fdc902dd..f7802a1675 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -3,7 +3,7 @@ module cmd go 1.18 require ( - github.com/google/pprof v0.0.0-20211001005136-7fe48b4c820b + github.com/google/pprof v0.0.0-20211104044539-f987b9c94b31 golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1 golang.org/x/mod v0.5.1-0.20210913215816-37dd6891021a golang.org/x/sync v0.0.0-20210220032951-036812b2e83c @@ -12,8 +12,8 @@ require ( ) require ( - github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 // indirect + github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d // indirect golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect - golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e // indirect + golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 4993128d1a..25c25d81bd 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -1,10 +1,10 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/google/pprof v0.0.0-20211001005136-7fe48b4c820b h1:GX4+fGLMW5XTmDXB3R6UhTwZIYqgAOdA19+Ea0+3CU4= -github.com/google/pprof v0.0.0-20211001005136-7fe48b4c820b/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 h1:mV02weKRL81bEnm8A0HT1/CAelMQDBuQIfLw8n+d6xI= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/google/pprof v0.0.0-20211104044539-f987b9c94b31 h1:YvpxjnjGhf/vDEeYOysNbsrtB///PKS8lqkFNSDm1p8= +github.com/google/pprof v0.0.0-20211104044539-f987b9c94b31/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= +github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d h1:uGg2frlt3IcT7kbV6LEp5ONv4vmoO2FW4qSO+my/aoM= +github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1 h1:MwxAfiDvuwX8Nnnc6iRDhzyMyyc2tz5tYyCP/pZcPCg= golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= @@ -13,9 +13,8 @@ golang.org/x/mod v0.5.1-0.20210913215816-37dd6891021a h1:55PVa91KndtPGH2lus5l2gD golang.org/x/mod v0.5.1-0.20210913215816-37dd6891021a/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e h1:XMgFehsDnnLGtjvjOfqWSUzt0alpTR1RSEuznObga2c= -golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac h1:oN6lz7iLW/YC7un8pq+9bOLyXrprv2+DKfkJY+2LJJw= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/tools v0.1.8-0.20211025211149-f916b54a1784 h1:+xP+QoP2SEPgbn+07I/yJTzP+gavj0XKGS6+JU5tlck= diff --git a/src/cmd/vendor/github.com/google/pprof/internal/elfexec/elfexec.go b/src/cmd/vendor/github.com/google/pprof/internal/elfexec/elfexec.go index 4f11645185..6447092d3d 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/elfexec/elfexec.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/elfexec/elfexec.go @@ -165,19 +165,61 @@ func GetBuildID(binary io.ReaderAt) ([]byte, error) { return nil, nil } -// GetBase determines the base address to subtract from virtual -// address to get symbol table address. For an executable, the base -// is 0. Otherwise, it's a shared library, and the base is the -// address where the mapping starts. The kernel is special, and may -// use the address of the _stext symbol as the mmap start. _stext -// offset can be obtained with `nm vmlinux | grep _stext` -func GetBase(fh *elf.FileHeader, loadSegment *elf.ProgHeader, stextOffset *uint64, start, limit, offset uint64) (uint64, error) { +// kernelBase caluclates the base for kernel mappings, which usually require +// special handling. For kernel mappings, tools (like perf) use the address of +// the kernel relocation symbol (_text or _stext) as the mmap start. Additionaly, +// for obfuscation, ChromeOS profiles have the kernel image remapped to the 0-th page. +func kernelBase(loadSegment *elf.ProgHeader, stextOffset *uint64, start, limit, offset uint64) (uint64, bool) { const ( - pageSize = 4096 // PAGE_OFFSET for PowerPC64, see arch/powerpc/Kconfig in the kernel sources. pageOffsetPpc64 = 0xc000000000000000 + pageSize = 4096 ) + if loadSegment.Vaddr == start-offset { + return offset, true + } + if start == 0 && limit != 0 && stextOffset != nil { + // ChromeOS remaps its kernel to 0. Nothing else should come + // down this path. Empirical values: + // VADDR=0xffffffff80200000 + // stextOffset=0xffffffff80200198 + return start - *stextOffset, true + } + if start >= loadSegment.Vaddr && limit > start && (offset == 0 || offset == pageOffsetPpc64 || offset == start) { + // Some kernels look like: + // VADDR=0xffffffff80200000 + // stextOffset=0xffffffff80200198 + // Start=0xffffffff83200000 + // Limit=0xffffffff84200000 + // Offset=0 (0xc000000000000000 for PowerPC64) (== Start for ASLR kernel) + // So the base should be: + if stextOffset != nil && (start%pageSize) == (*stextOffset%pageSize) { + // perf uses the address of _stext as start. Some tools may + // adjust for this before calling GetBase, in which case the page + // alignment should be different from that of stextOffset. + return start - *stextOffset, true + } + + return start - loadSegment.Vaddr, true + } + if start%pageSize != 0 && stextOffset != nil && *stextOffset%pageSize == start%pageSize { + // ChromeOS remaps its kernel to 0 + start%pageSize. Nothing + // else should come down this path. Empirical values: + // start=0x198 limit=0x2f9fffff offset=0 + // VADDR=0xffffffff81000000 + // stextOffset=0xffffffff81000198 + return start - *stextOffset, true + } + return 0, false +} + +// GetBase determines the base address to subtract from virtual +// address to get symbol table address. For an executable, the base +// is 0. Otherwise, it's a shared library, and the base is the +// address where the mapping starts. The kernel needs special hanldling. +func GetBase(fh *elf.FileHeader, loadSegment *elf.ProgHeader, stextOffset *uint64, start, limit, offset uint64) (uint64, error) { + if start == 0 && offset == 0 && (limit == ^uint64(0) || limit == 0) { // Some tools may introduce a fake mapping that spans the entire // address space. Assume that the address has already been @@ -202,43 +244,15 @@ func GetBase(fh *elf.FileHeader, loadSegment *elf.ProgHeader, stextOffset *uint6 // the 64-bit address space. return start - offset + loadSegment.Off - loadSegment.Vaddr, nil } - // Various kernel heuristics and cases follow. - if loadSegment.Vaddr == start-offset { - return offset, nil + // Various kernel heuristics and cases are handled separately. + if base, match := kernelBase(loadSegment, stextOffset, start, limit, offset); match { + return base, nil } - if start == 0 && limit != 0 { - // ChromeOS remaps its kernel to 0. Nothing else should come - // down this path. Empirical values: - // VADDR=0xffffffff80200000 - // stextOffset=0xffffffff80200198 - if stextOffset != nil { - return -*stextOffset, nil - } - return -loadSegment.Vaddr, nil - } - if start >= loadSegment.Vaddr && limit > start && (offset == 0 || offset == pageOffsetPpc64 || offset == start) { - // Some kernels look like: - // VADDR=0xffffffff80200000 - // stextOffset=0xffffffff80200198 - // Start=0xffffffff83200000 - // Limit=0xffffffff84200000 - // Offset=0 (0xc000000000000000 for PowerPC64) (== Start for ASLR kernel) - // So the base should be: - if stextOffset != nil && (start%pageSize) == (*stextOffset%pageSize) { - // perf uses the address of _stext as start. Some tools may - // adjust for this before calling GetBase, in which case the page - // alignment should be different from that of stextOffset. - return start - *stextOffset, nil - } - + // ChromeOS can remap its kernel to 0, and the caller might have not found + // the _stext symbol. Split this case from kernelBase() above, since we don't + // want to apply it to an ET_DYN user-mode executable. + if start == 0 && limit != 0 && stextOffset == nil { return start - loadSegment.Vaddr, nil - } else if start%pageSize != 0 && stextOffset != nil && *stextOffset%pageSize == start%pageSize { - // ChromeOS remaps its kernel to 0 + start%pageSize. Nothing - // else should come down this path. Empirical values: - // start=0x198 limit=0x2f9fffff offset=0 - // VADDR=0xffffffff81000000 - // stextOffset=0xffffffff81000198 - return start - *stextOffset, nil } return 0, fmt.Errorf("don't know how to handle EXEC segment: %v start=0x%x limit=0x%x offset=0x%x", *loadSegment, start, limit, offset) @@ -255,6 +269,11 @@ func GetBase(fh *elf.FileHeader, loadSegment *elf.ProgHeader, stextOffset *uint6 if loadSegment == nil { return start - offset, nil } + // Kernels compiled as PIE can be ET_DYN as well. Use heuristic, similar to + // the ET_EXEC case above. + if base, match := kernelBase(loadSegment, stextOffset, start, limit, offset); match { + return base, nil + } // The program header, if not nil, indicates the offset in the file where // the executable segment is located (loadSegment.Off), and the base virtual // address where the first byte of the segment is loaded diff --git a/src/cmd/vendor/github.com/google/pprof/internal/report/source_html.go b/src/cmd/vendor/github.com/google/pprof/internal/report/source_html.go index 17c9f6eb94..851693f1d0 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/report/source_html.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/report/source_html.go @@ -72,5 +72,4 @@ function pprof_toggle_asm(e) { const weblistPageClosing = ` - -` +` diff --git a/src/cmd/vendor/github.com/ianlancetaylor/demangle/README.md b/src/cmd/vendor/github.com/ianlancetaylor/demangle/README.md index ef3f94a63d..2c01cae088 100644 --- a/src/cmd/vendor/github.com/ianlancetaylor/demangle/README.md +++ b/src/cmd/vendor/github.com/ianlancetaylor/demangle/README.md @@ -1,3 +1,3 @@ # github.com/ianlancetaylor/demangle -A Go package that can be used to demangle C++ symbol names. +A Go package that can be used to demangle C++ and Rust symbol names. diff --git a/src/cmd/vendor/github.com/ianlancetaylor/demangle/ast.go b/src/cmd/vendor/github.com/ianlancetaylor/demangle/ast.go index ccbe5b3559..7b9178f1bb 100644 --- a/src/cmd/vendor/github.com/ianlancetaylor/demangle/ast.go +++ b/src/cmd/vendor/github.com/ianlancetaylor/demangle/ast.go @@ -11,6 +11,7 @@ import ( // AST is an abstract syntax tree representing a C++ declaration. // This is sufficient for the demangler but is by no means a general C++ AST. +// This abstract syntax tree is only used for C++ symbols, not Rust symbols. type AST interface { // Internal method to convert to demangled string. print(*printState) @@ -37,21 +38,25 @@ type AST interface { // ASTToString returns the demangled name of the AST. func ASTToString(a AST, options ...Option) string { tparams := true + llvmStyle := false for _, o := range options { switch o { case NoTemplateParams: tparams = false + case LLVMStyle: + llvmStyle = true } } - ps := printState{tparams: tparams} + ps := printState{tparams: tparams, llvmStyle: llvmStyle} a.print(&ps) return ps.buf.String() } // The printState type holds information needed to print an AST. type printState struct { - tparams bool // whether to print template parameters + tparams bool // whether to print template parameters + llvmStyle bool buf strings.Builder last byte // Last byte written to buffer. @@ -408,7 +413,11 @@ type LambdaAuto struct { func (la *LambdaAuto) print(ps *printState) { // We print the index plus 1 because that is what the standard // demangler does. - fmt.Fprintf(&ps.buf, "auto:%d", la.Index+1) + if ps.llvmStyle { + ps.writeString("auto") + } else { + fmt.Fprintf(&ps.buf, "auto:%d", la.Index+1) + } } func (la *LambdaAuto) Traverse(fn func(AST) bool) { @@ -504,6 +513,9 @@ func (q *Qualifier) print(ps *printState) { ps.writeByte('(') first := true for _, e := range q.Exprs { + if el, ok := e.(*ExprList); ok && len(el.Exprs) == 0 { + continue + } if !first { ps.writeString(", ") } @@ -715,7 +727,11 @@ type BuiltinType struct { } func (bt *BuiltinType) print(ps *printState) { - ps.writeString(bt.Name) + name := bt.Name + if ps.llvmStyle && name == "decltype(nullptr)" { + name = "std::nullptr_t" + } + ps.writeString(name) } func (bt *BuiltinType) Traverse(fn func(AST) bool) { @@ -970,10 +986,15 @@ type VendorQualifier struct { } func (vq *VendorQualifier) print(ps *printState) { - ps.inner = append(ps.inner, vq) - ps.print(vq.Type) - if len(ps.inner) > 0 { - ps.printOneInner(nil) + if ps.llvmStyle { + ps.print(vq.Type) + vq.printInner(ps) + } else { + ps.inner = append(ps.inner, vq) + ps.print(vq.Type) + if len(ps.inner) > 0 { + ps.printOneInner(nil) + } } } @@ -1110,19 +1131,27 @@ func (at *ArrayType) goString(indent int, field string) string { at.Element.goString(indent+2, "Element: ")) } -// FunctionType is a function type. The Return field may be nil for -// cases where the return type is not part of the mangled name. +// FunctionType is a function type. type FunctionType struct { Return AST Args []AST + + // The forLocalName field reports whether this FunctionType + // was created for a local name. With the default GNU demangling + // output we don't print the return type in that case. + ForLocalName bool } func (ft *FunctionType) print(ps *printState) { - if ft.Return != nil { + retType := ft.Return + if ft.ForLocalName && !ps.llvmStyle { + retType = nil + } + if retType != nil { // Pass the return type as an inner type in order to // print the arguments in the right location. ps.inner = append(ps.inner, ft) - ps.print(ft.Return) + ps.print(retType) if len(ps.inner) == 0 { // Everything was printed. return @@ -1227,7 +1256,11 @@ func (ft *FunctionType) Copy(fn func(AST) AST, skip func(AST) bool) AST { if !changed { return fn(ft) } - ft = &FunctionType{Return: ret, Args: args} + ft = &FunctionType{ + Return: ret, + Args: args, + ForLocalName: ft.ForLocalName, + } if r := fn(ft); r != nil { return r } @@ -1239,6 +1272,10 @@ func (ft *FunctionType) GoString() string { } func (ft *FunctionType) goString(indent int, field string) string { + var forLocalName string + if ft.ForLocalName { + forLocalName = " ForLocalName: true" + } var r string if ft.Return == nil { r = fmt.Sprintf("%*sReturn: nil", indent+2, "") @@ -1255,7 +1292,8 @@ func (ft *FunctionType) goString(indent int, field string) string { args += a.goString(indent+4, fmt.Sprintf("%d: ", i)) } } - return fmt.Sprintf("%*s%sFunctionType:\n%s\n%s", indent, "", field, r, args) + return fmt.Sprintf("%*s%sFunctionType:%s\n%s\n%s", indent, "", field, + forLocalName, r, args) } // FunctionParam is a parameter of a function, used for last-specified @@ -1267,6 +1305,12 @@ type FunctionParam struct { func (fp *FunctionParam) print(ps *printState) { if fp.Index == 0 { ps.writeString("this") + } else if ps.llvmStyle { + if fp.Index == 1 { + ps.writeString("fp") + } else { + fmt.Fprintf(&ps.buf, "fp%d", fp.Index-2) + } } else { fmt.Fprintf(&ps.buf, "{parm#%d}", fp.Index) } @@ -1422,9 +1466,15 @@ func (vt *VectorType) print(ps *printState) { } func (vt *VectorType) printInner(ps *printState) { - ps.writeString(" __vector(") + end := byte(')') + if ps.llvmStyle { + ps.writeString(" vector[") + end = ']' + } else { + ps.writeString(" __vector(") + } ps.print(vt.Dimension) - ps.writeByte(')') + ps.writeByte(end) } func (vt *VectorType) Traverse(fn func(AST) bool) { @@ -1466,13 +1516,59 @@ func (vt *VectorType) goString(indent int, field string) string { vt.Base.goString(indent+2, "Base: ")) } +// ElaboratedType is an elaborated struct/union/enum type. +type ElaboratedType struct { + Kind string + Type AST +} + +func (et *ElaboratedType) print(ps *printState) { + ps.writeString(et.Kind) + ps.writeString(" ") + et.Type.print(ps) +} + +func (et *ElaboratedType) Traverse(fn func(AST) bool) { + if fn(et) { + et.Type.Traverse(fn) + } +} + +func (et *ElaboratedType) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(et) { + return nil + } + typ := et.Type.Copy(fn, skip) + if typ == nil { + return fn(et) + } + et = &ElaboratedType{Kind: et.Kind, Type: typ} + if r := fn(et); r != nil { + return r + } + return et +} + +func (et *ElaboratedType) GoString() string { + return et.goString(0, "") +} + +func (et *ElaboratedType) goString(indent int, field string) string { + return fmt.Sprintf("%*s%sElaboratedtype: Kind: %s\n%s", indent, "", field, + et.Kind, et.Type.goString(indent+2, "Expr: ")) +} + // Decltype is the decltype operator. type Decltype struct { Expr AST } func (dt *Decltype) print(ps *printState) { - ps.writeString("decltype (") + ps.writeString("decltype") + if !ps.llvmStyle { + ps.writeString(" ") + } + ps.writeString("(") ps.print(dt.Expr) ps.writeByte(')') } @@ -1544,15 +1640,20 @@ func (op *Operator) goString(indent int, field string) string { // Constructor is a constructor. type Constructor struct { Name AST + Base AST // base class of inheriting constructor } func (c *Constructor) print(ps *printState) { ps.print(c.Name) + // We don't include the base class in the demangled string. } func (c *Constructor) Traverse(fn func(AST) bool) { if fn(c) { c.Name.Traverse(fn) + if c.Base != nil { + c.Base.Traverse(fn) + } } } @@ -1561,10 +1662,20 @@ func (c *Constructor) Copy(fn func(AST) AST, skip func(AST) bool) AST { return nil } name := c.Name.Copy(fn, skip) - if name == nil { + var base AST + if c.Base != nil { + base = c.Base.Copy(fn, skip) + } + if name == nil && base == nil { return fn(c) } - c = &Constructor{Name: name} + if name == nil { + name = c.Name + } + if base == nil { + base = c.Base + } + c = &Constructor{Name: name, Base: base} if r := fn(c); r != nil { return r } @@ -1576,7 +1687,13 @@ func (c *Constructor) GoString() string { } func (c *Constructor) goString(indent int, field string) string { - return fmt.Sprintf("%*s%sConstructor:\n%s", indent, "", field, c.Name.goString(indent+2, "Name: ")) + var sb strings.Builder + fmt.Fprintf(&sb, "%*s%sConstructor:\n", indent, "", field) + if c.Base != nil { + fmt.Fprintf(&sb, "%s\n", c.Base.goString(indent+2, "Base: ")) + } + fmt.Fprintf(&sb, "%s", c.Name.goString(indent+2, "Name: ")) + return sb.String() } // Destructor is a destructor. @@ -1727,8 +1844,12 @@ func (pe *PackExpansion) print(ps *printState) { // We normally only get here if the simplify function was // unable to locate and expand the pack. if pe.Pack == nil { - parenthesize(ps, pe.Base) - ps.writeString("...") + if ps.llvmStyle { + ps.print(pe.Base) + } else { + parenthesize(ps, pe.Base) + ps.writeString("...") + } } else { ps.print(pe.Base) } @@ -1834,7 +1955,13 @@ type SizeofPack struct { } func (sp *SizeofPack) print(ps *printState) { - ps.writeString(fmt.Sprintf("%d", len(sp.Pack.Args))) + if ps.llvmStyle { + ps.writeString("sizeof...(") + ps.print(sp.Pack) + ps.writeByte(')') + } else { + ps.writeString(fmt.Sprintf("%d", len(sp.Pack.Args))) + } } func (sp *SizeofPack) Traverse(fn func(AST) bool) { @@ -1932,6 +2059,287 @@ func (sa *SizeofArgs) goString(indent int, field string) string { return fmt.Sprintf("%*s%sSizeofArgs:\n%s", indent, "", field, args) } +// TemplateParamName is the name of a template parameter that the +// demangler introduced for a lambda that has explicit template +// parameters. This is a prefix with an index. +type TemplateParamName struct { + Prefix string + Index int +} + +func (tpn *TemplateParamName) print(ps *printState) { + ps.writeString(tpn.Prefix) + if tpn.Index > 0 { + ps.writeString(fmt.Sprintf("%d", tpn.Index-1)) + } +} + +func (tpn *TemplateParamName) Traverse(fn func(AST) bool) { + fn(tpn) +} + +func (tpn *TemplateParamName) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(tpn) { + return nil + } + return fn(tpn) +} + +func (tpn *TemplateParamName) GoString() string { + return tpn.goString(0, "") +} + +func (tpn *TemplateParamName) goString(indent int, field string) string { + name := tpn.Prefix + if tpn.Index > 0 { + name += fmt.Sprintf("%d", tpn.Index-1) + } + return fmt.Sprintf("%*s%sTemplateParamName: %s", indent, "", field, name) +} + +// TypeTemplateParam is a type template parameter that appears in a +// lambda with explicit template parameters. +type TypeTemplateParam struct { + Name AST +} + +func (ttp *TypeTemplateParam) print(ps *printState) { + ps.writeString("typename ") + ps.printInner(false) + ps.print(ttp.Name) +} + +func (ttp *TypeTemplateParam) Traverse(fn func(AST) bool) { + if fn(ttp) { + ttp.Name.Traverse(fn) + } +} + +func (ttp *TypeTemplateParam) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(ttp) { + return nil + } + name := ttp.Name.Copy(fn, skip) + if name == nil { + return fn(ttp) + } + ttp = &TypeTemplateParam{Name: name} + if r := fn(ttp); r != nil { + return r + } + return ttp +} + +func (ttp *TypeTemplateParam) GoString() string { + return ttp.goString(0, "") +} + +func (ttp *TypeTemplateParam) goString(indent int, field string) string { + return fmt.Sprintf("%*s%sTypeTemplateParam:\n%s", indent, "", field, + ttp.Name.goString(indent+2, "Name")) +} + +// NonTypeTemplateParam is a non-type template parameter that appears +// in a lambda with explicit template parameters. +type NonTypeTemplateParam struct { + Name AST + Type AST +} + +func (nttp *NonTypeTemplateParam) print(ps *printState) { + ps.inner = append(ps.inner, nttp) + ps.print(nttp.Type) + if len(ps.inner) > 0 { + ps.writeByte(' ') + ps.print(nttp.Name) + ps.inner = ps.inner[:len(ps.inner)-1] + } +} + +func (nttp *NonTypeTemplateParam) printInner(ps *printState) { + ps.print(nttp.Name) +} + +func (nttp *NonTypeTemplateParam) Traverse(fn func(AST) bool) { + if fn(nttp) { + nttp.Name.Traverse(fn) + nttp.Type.Traverse(fn) + } +} + +func (nttp *NonTypeTemplateParam) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(nttp) { + return nil + } + name := nttp.Name.Copy(fn, skip) + typ := nttp.Type.Copy(fn, skip) + if name == nil && typ == nil { + return fn(nttp) + } + if name == nil { + name = nttp.Name + } + if typ == nil { + typ = nttp.Type + } + nttp = &NonTypeTemplateParam{Name: name, Type: typ} + if r := fn(nttp); r != nil { + return r + } + return nttp +} + +func (nttp *NonTypeTemplateParam) GoString() string { + return nttp.goString(0, "") +} + +func (nttp *NonTypeTemplateParam) goString(indent int, field string) string { + return fmt.Sprintf("%*s%sNonTypeTemplateParam:\n%s\n%s", indent, "", field, + nttp.Name.goString(indent+2, "Name: "), + nttp.Type.goString(indent+2, "Type: ")) +} + +// TemplateTemplateParam is a template template parameter that appears +// in a lambda with explicit template parameters. +type TemplateTemplateParam struct { + Name AST + Params []AST +} + +func (ttp *TemplateTemplateParam) print(ps *printState) { + ps.writeString("template<") + for i, param := range ttp.Params { + if i > 0 { + ps.writeString(", ") + } + ps.print(param) + } + ps.writeString("> typename ") + ps.print(ttp.Name) +} + +func (ttp *TemplateTemplateParam) Traverse(fn func(AST) bool) { + if fn(ttp) { + ttp.Name.Traverse(fn) + for _, param := range ttp.Params { + param.Traverse(fn) + } + } +} + +func (ttp *TemplateTemplateParam) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(ttp) { + return nil + } + + changed := false + + name := ttp.Name.Copy(fn, skip) + if name == nil { + name = ttp.Name + } else { + changed = true + } + + params := make([]AST, len(ttp.Params)) + for i, p := range ttp.Params { + pc := p.Copy(fn, skip) + if pc == nil { + params[i] = p + } else { + params[i] = pc + changed = true + } + } + + if !changed { + return fn(ttp) + } + + ttp = &TemplateTemplateParam{ + Name: name, + Params: params, + } + if r := fn(ttp); r != nil { + return r + } + return ttp +} + +func (ttp *TemplateTemplateParam) GoString() string { + return ttp.goString(0, "") +} + +func (ttp *TemplateTemplateParam) goString(indent int, field string) string { + var params strings.Builder + fmt.Fprintf(¶ms, "%*sParams:", indent+2, "") + for i, p := range ttp.Params { + params.WriteByte('\n') + params.WriteString(p.goString(indent+4, fmt.Sprintf("%d: ", i))) + } + return fmt.Sprintf("%*s%sTemplateTemplateParam:\n%s\n%s", indent, "", field, + ttp.Name.goString(indent+2, "Name: "), + params.String()) +} + +// TemplateParamPack is a template parameter pack that appears in a +// lambda with explicit template parameters. +type TemplateParamPack struct { + Param AST +} + +func (tpp *TemplateParamPack) print(ps *printState) { + holdInner := ps.inner + defer func() { ps.inner = holdInner }() + + ps.inner = []AST{tpp} + if nttp, ok := tpp.Param.(*NonTypeTemplateParam); ok { + ps.print(nttp.Type) + } else { + ps.print(tpp.Param) + } + if len(ps.inner) > 0 { + ps.writeString("...") + } +} + +func (tpp *TemplateParamPack) printInner(ps *printState) { + ps.writeString("...") + if nttp, ok := tpp.Param.(*NonTypeTemplateParam); ok { + ps.print(nttp.Name) + } +} + +func (tpp *TemplateParamPack) Traverse(fn func(AST) bool) { + if fn(tpp) { + tpp.Param.Traverse(fn) + } +} + +func (tpp *TemplateParamPack) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(tpp) { + return nil + } + param := tpp.Param.Copy(fn, skip) + if param == nil { + return fn(tpp) + } + tpp = &TemplateParamPack{Param: param} + if r := fn(tpp); r != nil { + return r + } + return tpp +} + +func (tpp *TemplateParamPack) GoString() string { + return tpp.goString(0, "") +} + +func (tpp *TemplateParamPack) goString(indent int, field string) string { + return fmt.Sprintf("%*s%sTemplateParamPack:\n%s", indent, "", field, + tpp.Param.goString(indent+2, "Param: ")) +} + // Cast is a type cast. type Cast struct { To AST @@ -1977,7 +2385,11 @@ func (c *Cast) goString(indent int, field string) string { func parenthesize(ps *printState, val AST) { paren := false switch v := val.(type) { - case *Name, *InitializerList, *FunctionParam: + case *Name, *InitializerList: + case *FunctionParam: + if ps.llvmStyle { + paren = true + } case *Qualified: if v.LocalName { paren = true @@ -2047,14 +2459,17 @@ type Unary struct { } func (u *Unary) print(ps *printState) { + op, _ := u.Op.(*Operator) expr := u.Expr // Don't print the argument list when taking the address of a // function. - if op, ok := u.Op.(*Operator); ok && op.Name == "&" { - if t, ok := expr.(*Typed); ok { - if _, ok := t.Type.(*FunctionType); ok { - expr = t.Name + if !ps.llvmStyle { + if op != nil && op.Name == "&" { + if t, ok := expr.(*Typed); ok { + if _, ok := t.Type.(*FunctionType); ok { + expr = t.Name + } } } } @@ -2063,8 +2478,11 @@ func (u *Unary) print(ps *printState) { parenthesize(ps, expr) } - if op, ok := u.Op.(*Operator); ok { + if op != nil { ps.writeString(op.Name) + if ps.llvmStyle && op.Name == "noexcept" { + ps.writeByte(' ') + } } else if c, ok := u.Op.(*Cast); ok { ps.writeByte('(') ps.print(c.To) @@ -2074,7 +2492,7 @@ func (u *Unary) print(ps *printState) { } if !u.Suffix { - if op, ok := u.Op.(*Operator); ok && op.Name == "::" { + if op != nil && op.Name == "::" { // Don't use parentheses after ::. ps.print(expr) } else if u.SizeofType { @@ -2082,6 +2500,19 @@ func (u *Unary) print(ps *printState) { ps.writeByte('(') ps.print(expr) ps.writeByte(')') + } else if op != nil && op.Name == "__alignof__" { + // Always use parentheses for __alignof__ argument. + ps.writeByte('(') + ps.print(expr) + ps.writeByte(')') + } else if ps.llvmStyle { + if op == nil || op.Name != `operator"" ` { + ps.writeByte('(') + } + ps.print(expr) + if op == nil || op.Name != `operator"" ` { + ps.writeByte(')') + } } else { parenthesize(ps, expr) } @@ -2140,7 +2571,16 @@ func isDesignatedInitializer(x AST) bool { switch x := x.(type) { case *Binary: if op, ok := x.Op.(*Operator); ok { - return op.Name == "=" || op.Name == "]=" + if op.Name == "]=" { + return true + } + if op.Name != "=" { + return false + } + if _, ok := x.Left.(*Literal); ok { + return false + } + return true } case *Trinary: if op, ok := x.Op.(*Operator); ok { @@ -2185,8 +2625,13 @@ func (b *Binary) print(ps *printState) { // initializer chains. ps.print(b.Right) } else { - ps.writeByte('=') - parenthesize(ps, b.Right) + if ps.llvmStyle { + ps.writeString(" = ") + ps.print(b.Right) + } else { + ps.writeByte('=') + parenthesize(ps, b.Right) + } } return } @@ -2200,9 +2645,19 @@ func (b *Binary) print(ps *printState) { left := b.Left + skipParens := false + skipBothParens := false + addSpaces := ps.llvmStyle + if ps.llvmStyle && op != nil { + switch op.Name { + case ".", "->": + skipBothParens = true + addSpaces = false + } + } + // For a function call in an expression, don't print the types // of the arguments unless there is a return type. - skipParens := false if op != nil && op.Name == "()" { if ty, ok := b.Left.(*Typed); ok { if ft, ok := ty.Type.(*FunctionType); ok { @@ -2215,10 +2670,17 @@ func (b *Binary) print(ps *printState) { left = ty.Name } } + if ps.llvmStyle { + skipParens = true + } } - if skipParens { + if skipParens || skipBothParens { ps.print(left) + } else if ps.llvmStyle { + ps.writeByte('(') + ps.print(left) + ps.writeByte(')') } else { parenthesize(ps, left) } @@ -2232,13 +2694,27 @@ func (b *Binary) print(ps *printState) { if op != nil { if op.Name != "()" { + if addSpaces { + ps.writeByte(' ') + } ps.writeString(op.Name) + if addSpaces { + ps.writeByte(' ') + } } } else { ps.print(b.Op) } - parenthesize(ps, b.Right) + if skipBothParens { + ps.print(b.Right) + } else if ps.llvmStyle { + ps.writeByte('(') + ps.print(b.Right) + ps.writeByte(')') + } else { + parenthesize(ps, b.Right) + } if op != nil && op.Name == ">" { ps.writeByte(')') @@ -2310,14 +2786,23 @@ func (t *Trinary) print(ps *printState) { // initializer chains. ps.print(t.Third) } else { - ps.writeByte('=') - parenthesize(ps, t.Third) + if ps.llvmStyle { + ps.writeString(" = ") + ps.print(t.Third) + } else { + ps.writeByte('=') + parenthesize(ps, t.Third) + } } return } parenthesize(ps, t.First) - ps.writeByte('?') + if ps.llvmStyle { + ps.writeString(" ? ") + } else { + ps.writeByte('?') + } parenthesize(ps, t.Second) ps.writeString(" : ") parenthesize(ps, t.Third) @@ -2386,31 +2871,44 @@ func (f *Fold) print(ps *printState) { op, _ := f.Op.(*Operator) printOp := func() { if op != nil { + if ps.llvmStyle { + ps.writeByte(' ') + } ps.writeString(op.Name) + if ps.llvmStyle { + ps.writeByte(' ') + } } else { ps.print(f.Op) } } + foldParenthesize := func(a AST) { + if _, ok := a.(*ArgumentPack); ok || !ps.llvmStyle { + parenthesize(ps, a) + } else { + ps.print(a) + } + } if f.Arg2 == nil { if f.Left { ps.writeString("(...") printOp() - parenthesize(ps, f.Arg1) + foldParenthesize(f.Arg1) ps.writeString(")") } else { ps.writeString("(") - parenthesize(ps, f.Arg1) + foldParenthesize(f.Arg1) printOp() ps.writeString("...)") } } else { ps.writeString("(") - parenthesize(ps, f.Arg1) + foldParenthesize(f.Arg1) printOp() ps.writeString("...") printOp() - parenthesize(ps, f.Arg2) + foldParenthesize(f.Arg2) ps.writeString(")") } } @@ -2471,6 +2969,143 @@ func (f *Fold) goString(indent int, field string) string { } } +// Subobject is a a reference to an offset in an expression. This is +// used for C++20 manglings of class types used as the type of +// non-type template arguments. +// +// See https://github.com/itanium-cxx-abi/cxx-abi/issues/47. +type Subobject struct { + Type AST + SubExpr AST + Offset int + Selectors []int + PastEnd bool +} + +func (so *Subobject) print(ps *printState) { + ps.print(so.SubExpr) + ps.writeString(".<") + ps.print(so.Type) + ps.writeString(fmt.Sprintf(" at offset %d>", so.Offset)) +} + +func (so *Subobject) Traverse(fn func(AST) bool) { + if fn(so) { + so.Type.Traverse(fn) + so.SubExpr.Traverse(fn) + } +} + +func (so *Subobject) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(so) { + return nil + } + typ := so.Type.Copy(fn, skip) + subExpr := so.SubExpr.Copy(fn, skip) + if typ == nil && subExpr == nil { + return nil + } + if typ == nil { + typ = so.Type + } + if subExpr == nil { + subExpr = so.SubExpr + } + so = &Subobject{ + Type: typ, + SubExpr: subExpr, + Offset: so.Offset, + Selectors: so.Selectors, + PastEnd: so.PastEnd, + } + if r := fn(so); r != nil { + return r + } + return so +} + +func (so *Subobject) GoString() string { + return so.goString(0, "") +} + +func (so *Subobject) goString(indent int, field string) string { + var selectors string + for _, s := range so.Selectors { + selectors += fmt.Sprintf(" %d", s) + } + return fmt.Sprintf("%*s%sSubobject:\n%s\n%s\n%*sOffset: %d\n%*sSelectors:%s\n%*sPastEnd: %t", + indent, "", field, + so.Type.goString(indent+2, "Type: "), + so.SubExpr.goString(indent+2, "SubExpr: "), + indent+2, "", so.Offset, + indent+2, "", selectors, + indent+2, "", so.PastEnd) +} + +// PtrMemCast is a conversion of an expression to a pointer-to-member +// type. This is used for C++20 manglings of class types used as the +// type of non-type template arguments. +// +// See https://github.com/itanium-cxx-abi/cxx-abi/issues/47. +type PtrMemCast struct { + Type AST + Expr AST + Offset int +} + +func (pmc *PtrMemCast) print(ps *printState) { + ps.writeString("(") + ps.print(pmc.Type) + ps.writeString(")(") + ps.print(pmc.Expr) + ps.writeString(")") +} + +func (pmc *PtrMemCast) Traverse(fn func(AST) bool) { + if fn(pmc) { + pmc.Type.Traverse(fn) + pmc.Expr.Traverse(fn) + } +} + +func (pmc *PtrMemCast) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(pmc) { + return nil + } + typ := pmc.Type.Copy(fn, skip) + expr := pmc.Expr.Copy(fn, skip) + if typ == nil && expr == nil { + return nil + } + if typ == nil { + typ = pmc.Type + } + if expr == nil { + expr = pmc.Expr + } + pmc = &PtrMemCast{ + Type: typ, + Expr: expr, + Offset: pmc.Offset, + } + if r := fn(pmc); r != nil { + return r + } + return pmc +} + +func (pmc *PtrMemCast) GoString() string { + return pmc.goString(0, "") +} + +func (pmc *PtrMemCast) goString(indent int, field string) string { + return fmt.Sprintf("%*s%sPtrMemCast:\n%s\n%s\n%*sOffset: %d", + indent, "", field, + pmc.Type.goString(indent+2, "Type: "), + pmc.Expr.goString(indent+2, "Expr: "), + indent+2, "", pmc.Offset) +} + // New is a use of operator new in an expression. type New struct { Op AST @@ -2609,7 +3244,11 @@ func (l *Literal) print(ps *printState) { return } } else if b.Name == "decltype(nullptr)" && l.Val == "" { - ps.print(l.Type) + if ps.llvmStyle { + ps.writeString("nullptr") + } else { + ps.print(l.Type) + } return } else { isFloat = builtinTypeFloat[b.Name] @@ -2667,6 +3306,90 @@ func (l *Literal) goString(indent int, field string) string { indent+2, "", l.Val) } +// StringLiteral is a string literal. +type StringLiteral struct { + Type AST +} + +func (sl *StringLiteral) print(ps *printState) { + ps.writeString(`"<`) + sl.Type.print(ps) + ps.writeString(`>"`) +} + +func (sl *StringLiteral) Traverse(fn func(AST) bool) { + if fn(sl) { + sl.Type.Traverse(fn) + } +} + +func (sl *StringLiteral) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(sl) { + return nil + } + typ := sl.Type.Copy(fn, skip) + if typ == nil { + return fn(sl) + } + sl = &StringLiteral{Type: typ} + if r := fn(sl); r != nil { + return r + } + return sl +} + +func (sl *StringLiteral) GoString() string { + return sl.goString(0, "") +} + +func (sl *StringLiteral) goString(indent int, field string) string { + return fmt.Sprintf("%*s%sStringLiteral:\n%s", indent, "", field, + sl.Type.goString(indent+2, "")) +} + +// LambdaExpr is a literal that is a lambda expression. +type LambdaExpr struct { + Type AST +} + +func (le *LambdaExpr) print(ps *printState) { + ps.writeString("[]") + if cl, ok := le.Type.(*Closure); ok { + cl.printTypes(ps) + } + ps.writeString("{...}") +} + +func (le *LambdaExpr) Traverse(fn func(AST) bool) { + if fn(le) { + le.Type.Traverse(fn) + } +} + +func (le *LambdaExpr) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(le) { + return nil + } + typ := le.Type.Copy(fn, skip) + if typ == nil { + return fn(le) + } + le = &LambdaExpr{Type: typ} + if r := fn(le); r != nil { + return r + } + return le +} + +func (le *LambdaExpr) GoString() string { + return le.goString(0, "") +} + +func (le *LambdaExpr) goString(indent int, field string) string { + return fmt.Sprintf("%*s%sLambdaExpr:\n%s", indent, "", field, + le.Type.goString(indent+2, "")) +} + // ExprList is a list of expressions, typically arguments to a // function call in an expression. type ExprList struct { @@ -2803,7 +3526,9 @@ type DefaultArg struct { } func (da *DefaultArg) print(ps *printState) { - fmt.Fprintf(&ps.buf, "{default arg#%d}::", da.Num+1) + if !ps.llvmStyle { + fmt.Fprintf(&ps.buf, "{default arg#%d}::", da.Num+1) + } ps.print(da.Arg) } @@ -2839,23 +3564,53 @@ func (da *DefaultArg) goString(indent int, field string) string { // Closure is a closure, or lambda expression. type Closure struct { - Types []AST - Num int + TemplateArgs []AST + Types []AST + Num int } func (cl *Closure) print(ps *printState) { - ps.writeString("{lambda(") + if ps.llvmStyle { + if cl.Num == 0 { + ps.writeString("'lambda'") + } else { + ps.writeString(fmt.Sprintf("'lambda%d'", cl.Num-1)) + } + } else { + ps.writeString("{lambda") + } + cl.printTypes(ps) + if !ps.llvmStyle { + ps.writeString(fmt.Sprintf("#%d}", cl.Num+1)) + } +} + +func (cl *Closure) printTypes(ps *printState) { + if len(cl.TemplateArgs) > 0 { + ps.writeString("<") + for i, a := range cl.TemplateArgs { + if i > 0 { + ps.writeString(", ") + } + ps.print(a) + } + ps.writeString(">") + } + ps.writeString("(") for i, t := range cl.Types { if i > 0 { ps.writeString(", ") } ps.print(t) } - ps.writeString(fmt.Sprintf(")#%d}", cl.Num+1)) + ps.writeString(")") } func (cl *Closure) Traverse(fn func(AST) bool) { if fn(cl) { + for _, a := range cl.TemplateArgs { + a.Traverse(fn) + } for _, t := range cl.Types { t.Traverse(fn) } @@ -2866,8 +3621,20 @@ func (cl *Closure) Copy(fn func(AST) AST, skip func(AST) bool) AST { if skip(cl) { return nil } - types := make([]AST, len(cl.Types)) changed := false + + args := make([]AST, len(cl.TemplateArgs)) + for i, a := range cl.TemplateArgs { + ac := a.Copy(fn, skip) + if ac == nil { + args[i] = a + } else { + args[i] = ac + changed = true + } + } + + types := make([]AST, len(cl.Types)) for i, t := range cl.Types { tc := t.Copy(fn, skip) if tc == nil { @@ -2877,10 +3644,11 @@ func (cl *Closure) Copy(fn func(AST) AST, skip func(AST) bool) AST { changed = true } } + if !changed { return fn(cl) } - cl = &Closure{Types: types, Num: cl.Num} + cl = &Closure{TemplateArgs: args, Types: types, Num: cl.Num} if r := fn(cl); r != nil { return r } @@ -2892,6 +3660,16 @@ func (cl *Closure) GoString() string { } func (cl *Closure) goString(indent int, field string) string { + var args string + if len(cl.TemplateArgs) == 0 { + args = fmt.Sprintf("%*sTemplateArgs: nil", indent+2, "") + } else { + args = fmt.Sprintf("%*sTemplateArgs:", indent+2, "") + for i, a := range cl.TemplateArgs { + args += "\n" + args += a.goString(indent+4, fmt.Sprintf("%d: ", i)) + } + } var types string if len(cl.Types) == 0 { types = fmt.Sprintf("%*sTypes: nil", indent+2, "") @@ -2902,7 +3680,71 @@ func (cl *Closure) goString(indent int, field string) string { types += t.goString(indent+4, fmt.Sprintf("%d: ", i)) } } - return fmt.Sprintf("%*s%sClosure: Num: %d\n%s", indent, "", field, cl.Num, types) + return fmt.Sprintf("%*s%sClosure: Num: %d\n%s\n%s", indent, "", field, + cl.Num, args, types) +} + +// StructuredBindings is a structured binding declaration. +type StructuredBindings struct { + Bindings []AST +} + +func (sb *StructuredBindings) print(ps *printState) { + ps.writeString("[") + for i, b := range sb.Bindings { + if i > 0 { + ps.writeString(", ") + } + b.print(ps) + } + ps.writeString("]") +} + +func (sb *StructuredBindings) Traverse(fn func(AST) bool) { + if fn(sb) { + for _, b := range sb.Bindings { + b.Traverse(fn) + } + } +} + +func (sb *StructuredBindings) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(sb) { + return nil + } + changed := false + bindings := make([]AST, len(sb.Bindings)) + for i, b := range sb.Bindings { + bc := b.Copy(fn, skip) + if bc == nil { + bindings[i] = b + } else { + bindings[i] = bc + changed = true + } + } + if !changed { + return fn(sb) + } + sb = &StructuredBindings{Bindings: bindings} + if r := fn(sb); r != nil { + return r + } + return sb +} + +func (sb *StructuredBindings) GoString() string { + return sb.goString(0, "") +} + +func (sb *StructuredBindings) goString(indent int, field string) string { + var strb strings.Builder + fmt.Fprintf(&strb, "%*s%sStructuredBinding:", indent, "", field) + for _, b := range sb.Bindings { + strb.WriteByte('\n') + strb.WriteString(b.goString(indent+2, "")) + } + return strb.String() } // UnnamedType is an unnamed type, that just has an index. @@ -2911,7 +3753,15 @@ type UnnamedType struct { } func (ut *UnnamedType) print(ps *printState) { - ps.writeString(fmt.Sprintf("{unnamed type#%d}", ut.Num+1)) + if ps.llvmStyle { + if ut.Num == 0 { + ps.writeString("'unnamed'") + } else { + ps.writeString(fmt.Sprintf("'unnamed%d'", ut.Num-1)) + } + } else { + ps.writeString(fmt.Sprintf("{unnamed type#%d}", ut.Num+1)) + } } func (ut *UnnamedType) Traverse(fn func(AST) bool) { @@ -2941,7 +3791,13 @@ type Clone struct { func (c *Clone) print(ps *printState) { ps.print(c.Base) - ps.writeString(fmt.Sprintf(" [clone %s]", c.Suffix)) + if ps.llvmStyle { + ps.writeString(" (") + ps.writeString(c.Suffix) + ps.writeByte(')') + } else { + ps.writeString(fmt.Sprintf(" [clone %s]", c.Suffix)) + } } func (c *Clone) Traverse(fn func(AST) bool) { @@ -2982,7 +3838,16 @@ type Special struct { } func (s *Special) print(ps *printState) { - ps.writeString(s.Prefix) + prefix := s.Prefix + if ps.llvmStyle { + switch prefix { + case "TLS wrapper function for ": + prefix = "thread-local wrapper routine for " + case "TLS init function for ": + prefix = "thread-local initialization routine for " + } + } + ps.writeString(prefix) ps.print(s.Val) } @@ -3194,7 +4059,12 @@ func (ps *printState) printOneInner(save *[]AST) { func (ps *printState) isEmpty(a AST) bool { switch a := a.(type) { case *ArgumentPack: - return len(a.Args) == 0 + for _, a := range a.Args { + if !ps.isEmpty(a) { + return false + } + } + return true case *ExprList: return len(a.Exprs) == 0 case *PackExpansion: diff --git a/src/cmd/vendor/github.com/ianlancetaylor/demangle/demangle.go b/src/cmd/vendor/github.com/ianlancetaylor/demangle/demangle.go index c2667446df..9eec0aa3c8 100644 --- a/src/cmd/vendor/github.com/ianlancetaylor/demangle/demangle.go +++ b/src/cmd/vendor/github.com/ianlancetaylor/demangle/demangle.go @@ -2,9 +2,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package demangle defines functions that demangle GCC/LLVM C++ symbol names. +// Package demangle defines functions that demangle GCC/LLVM +// C++ and Rust symbol names. // This package recognizes names that were mangled according to the C++ ABI -// defined at http://codesourcery.com/cxx-abi/. +// defined at http://codesourcery.com/cxx-abi/ and the Rust ABI +// defined at +// https://rust-lang.github.io/rfcs/2603-rust-symbol-name-mangling-v0.html // // Most programs will want to call Filter or ToString. package demangle @@ -17,7 +20,7 @@ import ( // ErrNotMangledName is returned by CheckedDemangle if the string does // not appear to be a C++ symbol name. -var ErrNotMangledName = errors.New("not a C++ mangled name") +var ErrNotMangledName = errors.New("not a C++ or Rust mangled name") // Option is the type of demangler options. type Option int @@ -33,11 +36,23 @@ const ( // NoParams implies NoClones. NoClones + // The NoRust option disables demangling of old-style Rust + // mangled names, which can be confused with C++ style mangled + // names. New style Rust mangled names are still recognized. + NoRust + // The Verbose option turns on more verbose demangling. Verbose + + // LLVMStyle tries to translate an AST to a string in the + // style of the LLVM demangler. This does not affect + // the parsing of the AST, only the conversion of the AST + // to a string. + LLVMStyle ) -// Filter demangles a C++ symbol name, returning the human-readable C++ name. +// Filter demangles a C++ or Rust symbol name, +// returning the human-readable C++ or Rust name. // If any error occurs during demangling, the input string is returned. func Filter(name string, options ...Option) string { ret, err := ToString(name, options...) @@ -47,11 +62,34 @@ func Filter(name string, options ...Option) string { return ret } -// ToString demangles a C++ symbol name, returning a human-readable C++ -// name or an error. -// If the name does not appear to be a C++ symbol name at all, the -// error will be ErrNotMangledName. +// ToString demangles a C++ or Rust symbol name, +// returning a human-readable C++ or Rust name or an error. +// If the name does not appear to be a C++ or Rust symbol name at all, +// the error will be ErrNotMangledName. func ToString(name string, options ...Option) (string, error) { + if strings.HasPrefix(name, "_R") { + return rustToString(name, options) + } + + // Check for an old-style Rust mangled name. + // It starts with _ZN and ends with "17h" followed by 16 hex digits + // followed by "E". + if strings.HasPrefix(name, "_ZN") && strings.HasSuffix(name, "E") && len(name) > 23 && name[len(name)-20:len(name)-17] == "17h" { + noRust := false + for _, o := range options { + if o == NoRust { + noRust = true + break + } + } + if !noRust { + s, ok := oldRustToString(name, options) + if ok { + return s, nil + } + } + } + a, err := ToAST(name, options...) if err != nil { return "", err @@ -65,12 +103,37 @@ func ToString(name string, options ...Option) (string, error) { // the parameter types are not demangled. // If the name does not appear to be a C++ symbol name at all, the // error will be ErrNotMangledName. +// This function does not currently support Rust symbol names. func ToAST(name string, options ...Option) (AST, error) { if strings.HasPrefix(name, "_Z") { a, err := doDemangle(name[2:], options...) return a, adjustErr(err, 2) } + if strings.HasPrefix(name, "___Z") { + // clang extensions + block := strings.LastIndex(name, "_block_invoke") + if block == -1 { + return nil, ErrNotMangledName + } + a, err := doDemangle(name[4:block], options...) + if err != nil { + return a, adjustErr(err, 4) + } + name = strings.TrimPrefix(name[block:], "_block_invoke") + if len(name) > 0 && name[0] == '_' { + name = name[1:] + } + for len(name) > 0 && isDigit(name[0]) { + name = name[1:] + } + if len(name) > 0 && name[0] != '.' { + return nil, errors.New("unparsed characters at end of mangled name") + } + a = &Special{Prefix: "invocation function for block in ", Val: a} + return a, nil + } + const prefix = "_GLOBAL_" if strings.HasPrefix(name, prefix) { // The standard demangler ignores NoParams for global @@ -150,12 +213,13 @@ func doDemangle(name string, options ...Option) (ret AST, err error) { case NoParams: params = false clones = false - case NoTemplateParams: - // This is a valid option but only affect printing of the AST. case NoClones: clones = false case Verbose: verbose = true + case NoTemplateParams, LLVMStyle: + // These are valid options but only affect + // printing of the AST. default: return nil, fmt.Errorf("unrecognized demangler option %v", o) } @@ -185,7 +249,16 @@ type state struct { off int // offset of str within original string subs substitutions // substitutions templates []*Template // templates being processed - inLambda int // number of lambdas being parsed + + // The number of entries in templates when we started parsing + // a lambda, plus 1 so that 0 means not parsing a lambda. + lambdaTemplateLevel int + + // Counts of template parameters without template arguments, + // for lambdas. + typeTemplateParamCount int + nonTypeTemplateParamCount int + templateTemplateParamCount int } // copy returns a copy of the current state. @@ -308,35 +381,40 @@ func (st *state) encoding(params bool, local forLocalNameType) AST { return a } - check := a - mwq, _ := check.(*MethodWithQualifiers) - if mwq != nil { - check = mwq.Method - } + mwq, _ := a.(*MethodWithQualifiers) - var template *Template - switch check := check.(type) { - case *Template: - template = check - case *Qualified: - if check.LocalName { - n := check.Name - if nmwq, ok := n.(*MethodWithQualifiers); ok { - n = nmwq.Method + var findTemplate func(AST) *Template + findTemplate = func(check AST) *Template { + switch check := check.(type) { + case *Template: + return check + case *Qualified: + if check.LocalName { + return findTemplate(check.Name) + } else if _, ok := check.Name.(*Constructor); ok { + return findTemplate(check.Name) + } + case *MethodWithQualifiers: + return findTemplate(check.Method) + case *Constructor: + if check.Base != nil { + return findTemplate(check.Base) } - template, _ = n.(*Template) } + return nil } - var oldInLambda int + + template := findTemplate(a) + var oldLambdaTemplateLevel int if template != nil { st.templates = append(st.templates, template) - oldInLambda = st.inLambda - st.inLambda = 0 + oldLambdaTemplateLevel = st.lambdaTemplateLevel + st.lambdaTemplateLevel = 0 } // Checking for the enable_if attribute here is what the LLVM // demangler does. This is not very general but perhaps it is - // sufficent. + // sufficient. const enableIfPrefix = "Ua9enable_ifI" var enableIfArgs []AST if strings.HasPrefix(st.str, enableIfPrefix) { @@ -348,7 +426,7 @@ func (st *state) encoding(params bool, local forLocalNameType) AST { if template != nil { st.templates = st.templates[:len(st.templates)-1] - st.inLambda = oldInLambda + st.lambdaTemplateLevel = oldLambdaTemplateLevel } ft = simplify(ft) @@ -357,7 +435,7 @@ func (st *state) encoding(params bool, local forLocalNameType) AST { // doesn't get confused with the top level return type. if local == forLocalName { if functype, ok := ft.(*FunctionType); ok { - functype.Return = nil + functype.ForLocalName = true } } @@ -573,7 +651,7 @@ func (st *state) prefix() AST { var next AST c := st.str[0] - if isDigit(c) || isLower(c) || c == 'U' || c == 'L' { + if isDigit(c) || isLower(c) || c == 'U' || c == 'L' || (c == 'D' && len(st.str) > 1 && st.str[1] == 'C') { un, isUnCast := st.unqualifiedName() next = un if isUnCast { @@ -595,10 +673,17 @@ func (st *state) prefix() AST { st.fail("constructor before name is seen") } st.advance(1) + var base AST if inheriting { - last = st.demangleType(false) + base = st.demangleType(false) + } + next = &Constructor{ + Name: getLast(last), + Base: base, + } + if len(st.str) > 0 && st.str[0] == 'B' { + next = st.taggedName(next) } - next = &Constructor{Name: getLast(last)} case 'D': if len(st.str) > 1 && (st.str[1] == 'T' || st.str[1] == 't') { next = st.demangleType(false) @@ -611,6 +696,9 @@ func (st *state) prefix() AST { } st.advance(2) next = &Destructor{Name: getLast(last)} + if len(st.str) > 0 && st.str[0] == 'B' { + next = st.taggedName(next) + } } case 'S': next = st.substitution(true) @@ -713,6 +801,18 @@ func (st *state) unqualifiedName() (r AST, isCast bool) { n := st.sourceName() a = &Unary{Op: op, Expr: n, Suffix: false, SizeofType: false} } + } else if c == 'D' && len(st.str) > 1 && st.str[1] == 'C' { + var bindings []AST + st.advance(2) + for { + binding := st.sourceName() + bindings = append(bindings, binding) + if len(st.str) > 0 && st.str[0] == 'E' { + st.advance(1) + break + } + } + a = &StructuredBindings{Bindings: bindings} } else { switch c { case 'C', 'D': @@ -728,6 +828,10 @@ func (st *state) unqualifiedName() (r AST, isCast bool) { } c := st.str[1] switch c { + case 'b': + st.advance(2) + st.compactNumber() + a = &Name{Name: "'block-literal'"} case 'l': a = st.closureTypeName() case 't': @@ -802,6 +906,42 @@ func (st *state) number() int { return val } +// ::= <0-9A-Z>+ +// +// We expect this to be followed by an underscore. +func (st *state) seqID(eofOK bool) int { + if len(st.str) > 0 && st.str[0] == '_' { + st.advance(1) + return 0 + } + id := 0 + for { + if len(st.str) == 0 { + if eofOK { + return id + 1 + } + st.fail("missing end to sequence ID") + } + // Don't overflow a 32-bit int. + if id >= 0x80000000/36-36 { + st.fail("sequence ID overflow") + } + c := st.str[0] + if c == '_' { + st.advance(1) + return id + 1 + } + if isDigit(c) { + id = id*36 + int(c-'0') + } else if isUpper(c) { + id = id*36 + int(c-'A') + 10 + } else { + st.fail("invalid character in sequence ID") + } + st.advance(1) + } +} + // An operator is the demangled name, and the number of arguments it // takes in an expression. type operator struct { @@ -864,6 +1004,7 @@ var operators = map[string]operator{ "ng": {"-", 1}, "nt": {"!", 1}, "nw": {"new", 3}, + "nx": {"noexcept", 1}, "oR": {"|=", 2}, "oo": {"||", 2}, "or": {"|", 2}, @@ -1094,8 +1235,8 @@ func (st *state) specialName() AST { return &Special{Prefix: "guard variable for ", Val: n} case 'R': n := st.name() - i := st.number() - return &Special{Prefix: fmt.Sprintf("reference temporary #%d for ", i), Val: n} + st.seqID(true) + return &Special{Prefix: "reference temporary for ", Val: n} case 'A': v := st.encoding(true, notForLocalName) return &Special{Prefix: "hidden alias for ", Val: v} @@ -1257,6 +1398,23 @@ func (st *state) demangleType(isCast bool) AST { case 'M': ret = st.pointerToMemberType(isCast) case 'T': + if len(st.str) > 1 && (st.str[1] == 's' || st.str[1] == 'u' || st.str[1] == 'e') { + c = st.str[1] + st.advance(2) + ret = st.name() + var kind string + switch c { + case 's': + kind = "struct" + case 'u': + kind = "union" + case 'e': + kind = "enum" + } + ret = &ElaboratedType{Kind: kind, Type: ret} + break + } + ret = st.templateParam() if len(st.str) > 0 && st.str[0] == 'I' { // See the function comment to explain this. @@ -1681,7 +1839,11 @@ func (st *state) bareFunctionType(hasReturnType bool) AST { returnType = st.demangleType(false) } types := st.parmlist() - return &FunctionType{Return: returnType, Args: types} + return &FunctionType{ + Return: returnType, + Args: types, + ForLocalName: false, // may be set later in encoding + } } // ::= A <(positive dimension) number> _ <(element) type> @@ -1798,6 +1960,8 @@ func (st *state) compactNumber() int { // ::= T_ // ::= T <(parameter-2 non-negative) number> _ +// ::= TL __ +// ::= TL _ _ // // When a template parameter is a substitution candidate, any // reference to that substitution refers to the template parameter @@ -1805,22 +1969,27 @@ func (st *state) compactNumber() int { // whatever the template parameter would be expanded to here. We sort // this out in substitution and simplify. func (st *state) templateParam() AST { - if len(st.templates) == 0 && st.inLambda == 0 { - st.fail("template parameter not in scope of template") - } off := st.off - st.checkChar('T') + + level := 0 + if len(st.str) > 0 && st.str[0] == 'L' { + st.advance(1) + level = st.compactNumber() + } + n := st.compactNumber() - if st.inLambda > 0 { - // g++ mangles lambda auto params as template params. - // Apparently we can't encounter a template within a lambda. - // See https://gcc.gnu.org/PR78252. - return &LambdaAuto{Index: n} + if level >= len(st.templates) { + if st.lambdaTemplateLevel > 0 && level == st.lambdaTemplateLevel-1 { + // Lambda auto params are mangled as template params. + // See https://gcc.gnu.org/PR78252. + return &LambdaAuto{Index: n} + } + st.failEarlier(fmt.Sprintf("template parameter is not in scope of template (level %d >= %d)", level, len(st.templates)), st.off-off) } - template := st.templates[len(st.templates)-1] + template := st.templates[level] if template == nil { // We are parsing a cast operator. If the cast is @@ -1830,6 +1999,11 @@ func (st *state) templateParam() AST { } if n >= len(template.Args) { + if st.lambdaTemplateLevel > 0 && level == st.lambdaTemplateLevel-1 { + // Lambda auto params are mangled as template params. + // See https://gcc.gnu.org/PR78252. + return &LambdaAuto{Index: n} + } st.failEarlier(fmt.Sprintf("template index out of range (%d >= %d)", n, len(template.Args)), st.off-off) } @@ -1968,9 +2142,11 @@ func (st *state) exprList(stop byte) AST { // ::= dc // ::= sc // ::= cc +// ::= mc [] E // ::= rc // ::= ti // ::= te +// ::= so [] * [p] E // ::= st // ::= sz // ::= at @@ -1991,6 +2167,7 @@ func (st *state) exprList(stop byte) AST { // ::= fR // ::= tw // ::= tr +// ::= u * E // ::= // ::= // @@ -2013,6 +2190,9 @@ func (st *state) expression() AST { return st.exprPrimary() } else if st.str[0] == 'T' { return st.templateParam() + } else if st.str[0] == 's' && len(st.str) > 1 && st.str[1] == 'o' { + st.advance(2) + return st.subobject() } else if st.str[0] == 's' && len(st.str) > 1 && st.str[1] == 'r' { return st.unresolvedName() } else if st.str[0] == 's' && len(st.str) > 1 && st.str[1] == 'p' { @@ -2063,6 +2243,23 @@ func (st *state) expression() AST { st.cvQualifiers() index := st.compactNumber() return &FunctionParam{Index: index + 1} + } else if st.str[0] == 'm' && len(st.str) > 1 && st.str[1] == 'c' { + st.advance(2) + typ := st.demangleType(false) + expr := st.expression() + offset := 0 + if len(st.str) > 0 && (st.str[0] == 'n' || isDigit(st.str[0])) { + offset = st.number() + } + if len(st.str) == 0 || st.str[0] != 'E' { + st.fail("expected E after pointer-to-member conversion") + } + st.advance(1) + return &PtrMemCast{ + Type: typ, + Expr: expr, + Offset: offset, + } } else if isDigit(st.str[0]) || (st.str[0] == 'o' && len(st.str) > 1 && st.str[1] == 'n') { if st.str[0] == 'o' { // Skip operator function ID. @@ -2088,6 +2285,50 @@ func (st *state) expression() AST { o, _ := st.operatorName(true) t := st.demangleType(false) return &Unary{Op: o, Expr: t, Suffix: false, SizeofType: true} + } else if st.str[0] == 'u' { + st.advance(1) + name := st.sourceName() + // Special case __uuidof followed by type or + // expression, as used by LLVM. + if n, ok := name.(*Name); ok && n.Name == "__uuidof" { + if len(st.str) < 2 { + st.fail("missing uuidof argument") + } + var operand AST + if st.str[0] == 't' { + st.advance(1) + operand = st.demangleType(false) + } else if st.str[0] == 'z' { + st.advance(1) + operand = st.expression() + } + if operand != nil { + return &Binary{ + Op: &Operator{Name: "()"}, + Left: name, + Right: &ExprList{ + Exprs: []AST{operand}, + }, + } + } + } + var args []AST + for { + if len(st.str) == 0 { + st.fail("missing argument in vendor extended expressoin") + } + if st.str[0] == 'E' { + st.advance(1) + break + } + arg := st.templateArg() + args = append(args, arg) + } + return &Binary{ + Op: &Operator{Name: "()"}, + Left: name, + Right: &ExprList{Exprs: args}, + } } else { if len(st.str) < 2 { st.fail("missing operator code") @@ -2185,6 +2426,42 @@ func (st *state) expression() AST { } } +// ::= so [] * [p] E +// ::= _ [] +func (st *state) subobject() AST { + typ := st.demangleType(false) + expr := st.expression() + offset := 0 + if len(st.str) > 0 && (st.str[0] == 'n' || isDigit(st.str[0])) { + offset = st.number() + } + var selectors []int + for len(st.str) > 0 && st.str[0] == '_' { + st.advance(1) + selector := 0 + if len(st.str) > 0 && (st.str[0] == 'n' || isDigit(st.str[0])) { + selector = st.number() + } + selectors = append(selectors, selector) + } + pastEnd := false + if len(st.str) > 0 && st.str[0] == 'p' { + st.advance(1) + pastEnd = true + } + if len(st.str) == 0 || st.str[0] != 'E' { + st.fail("expected E after subobject") + } + st.advance(1) + return &Subobject{ + Type: typ, + SubExpr: expr, + Offset: offset, + Selectors: selectors, + PastEnd: pastEnd, + } +} + // ::= [gs] // ::= sr // ::= srN + E @@ -2320,6 +2597,14 @@ func (st *state) exprPrimary() AST { } else { t := st.demangleType(false) + isArrayType := func(typ AST) bool { + if twq, ok := typ.(*TypeWithQualifiers); ok { + typ = twq.Base + } + _, ok := typ.(*ArrayType) + return ok + } + neg := false if len(st.str) > 0 && st.str[0] == 'n' { neg = true @@ -2331,6 +2616,13 @@ func (st *state) exprPrimary() AST { // We accept one if present because GCC // used to generate one. // https://gcc.gnu.org/PR91979. + } else if cl, ok := t.(*Closure); ok { + // A closure doesn't have a value. + st.advance(1) + return &LambdaExpr{Type: cl} + } else if isArrayType(t) { + st.advance(1) + return &StringLiteral{Type: t} } else { st.fail("missing literal value") } @@ -2354,6 +2646,15 @@ func (st *state) exprPrimary() AST { // __ <(non-negative) number> _ (when number >= 10) func (st *state) discriminator(a AST) AST { if len(st.str) == 0 || st.str[0] != '_' { + // clang can generate a discriminator at the end of + // the string with no underscore. + for i := 0; i < len(st.str); i++ { + if !isDigit(st.str[i]) { + return a + } + } + // Skip the trailing digits. + st.advance(len(st.str)) return a } off := st.off @@ -2379,18 +2680,131 @@ func (st *state) discriminator(a AST) AST { } // ::= Ul E [ ] _ +// ::= + func (st *state) closureTypeName() AST { st.checkChar('U') st.checkChar('l') - st.inLambda++ + + oldLambdaTemplateLevel := st.lambdaTemplateLevel + st.lambdaTemplateLevel = len(st.templates) + 1 + + var templateArgs []AST + var template *Template + for len(st.str) > 1 && st.str[0] == 'T' { + arg, templateVal := st.templateParamDecl() + if arg == nil { + break + } + templateArgs = append(templateArgs, arg) + if template == nil { + template = &Template{ + Name: &Name{Name: "lambda"}, + } + st.templates = append(st.templates, template) + } + template.Args = append(template.Args, templateVal) + } + types := st.parmlist() - st.inLambda-- + + st.lambdaTemplateLevel = oldLambdaTemplateLevel + + if template != nil { + st.templates = st.templates[:len(st.templates)-1] + } + if len(st.str) == 0 || st.str[0] != 'E' { st.fail("expected E after closure type name") } st.advance(1) num := st.compactNumber() - return &Closure{Types: types, Num: num} + return &Closure{TemplateArgs: templateArgs, Types: types, Num: num} +} + +// ::= Ty # type parameter +// ::= Tn # non-type parameter +// ::= Tt * E # template parameter +// ::= Tp # parameter pack +// +// Returns the new AST to include in the AST we are building and the +// new AST to add to the list of template parameters. +// +// Returns nil, nil if not looking at a template-param-decl. +func (st *state) templateParamDecl() (AST, AST) { + if len(st.str) < 2 || st.str[0] != 'T' { + return nil, nil + } + mk := func(prefix string, p *int) AST { + idx := *p + (*p)++ + return &TemplateParamName{ + Prefix: prefix, + Index: idx, + } + } + switch st.str[1] { + case 'y': + st.advance(2) + name := mk("$T", &st.typeTemplateParamCount) + tp := &TypeTemplateParam{ + Name: name, + } + return tp, name + case 'n': + st.advance(2) + name := mk("$N", &st.nonTypeTemplateParamCount) + typ := st.demangleType(false) + tp := &NonTypeTemplateParam{ + Name: name, + Type: typ, + } + return tp, name + case 't': + st.advance(2) + name := mk("$TT", &st.templateTemplateParamCount) + var params []AST + var template *Template + for { + if len(st.str) == 0 { + st.fail("expected closure template parameter") + } + if st.str[0] == 'E' { + st.advance(1) + break + } + off := st.off + param, templateVal := st.templateParamDecl() + if param == nil { + st.failEarlier("expected closure template parameter", st.off-off) + } + params = append(params, param) + if template == nil { + template = &Template{ + Name: &Name{Name: "template_template"}, + } + st.templates = append(st.templates, template) + } + template.Args = append(template.Args, templateVal) + } + if template != nil { + st.templates = st.templates[:len(st.templates)-1] + } + tp := &TemplateTemplateParam{ + Name: name, + Params: params, + } + return tp, name + case 'p': + st.advance(2) + off := st.off + param, templateVal := st.templateParamDecl() + if param == nil { + st.failEarlier("expected lambda template parameter", st.off-off) + } + return &TemplateParamPack{Param: param}, templateVal + default: + return nil, nil + } } // ::= Ut [ ] _ @@ -2504,36 +2918,11 @@ func (st *state) substitution(forPrefix bool) AST { st.fail("missing substitution index") } c := st.str[0] - st.advance(1) - dec := 1 + off := st.off if c == '_' || isDigit(c) || isUpper(c) { - id := 0 - if c != '_' { - for c != '_' { - // Don't overflow a 32-bit int. - if id >= 0x80000000/36-36 { - st.fail("substitution index overflow") - } - if isDigit(c) { - id = id*36 + int(c-'0') - } else if isUpper(c) { - id = id*36 + int(c-'A') + 10 - } else { - st.fail("invalid character in substitution index") - } - - if len(st.str) == 0 { - st.fail("missing end to substitution index") - } - c = st.str[0] - st.advance(1) - dec++ - } - id++ - } - + id := st.seqID(false) if id >= len(st.subs) { - st.failEarlier(fmt.Sprintf("substitution index out of range (%d >= %d)", id, len(st.subs)), dec) + st.failEarlier(fmt.Sprintf("substitution index out of range (%d >= %d)", id, len(st.subs)), st.off-off) } ret := st.subs[id] @@ -2545,18 +2934,18 @@ func (st *state) substitution(forPrefix bool) AST { // When copying a Typed we may need to adjust // the templates. copyTemplates := st.templates - var oldInLambda []int + var oldLambdaTemplateLevel []int // pushTemplate is called from skip, popTemplate from copy. pushTemplate := func(template *Template) { copyTemplates = append(copyTemplates, template) - oldInLambda = append(oldInLambda, st.inLambda) - st.inLambda = 0 + oldLambdaTemplateLevel = append(oldLambdaTemplateLevel, st.lambdaTemplateLevel) + st.lambdaTemplateLevel = 0 } popTemplate := func() { copyTemplates = copyTemplates[:len(copyTemplates)-1] - st.inLambda = oldInLambda[len(oldInLambda)-1] - oldInLambda = oldInLambda[:len(oldInLambda)-1] + st.lambdaTemplateLevel = oldLambdaTemplateLevel[len(oldLambdaTemplateLevel)-1] + oldLambdaTemplateLevel = oldLambdaTemplateLevel[:len(oldLambdaTemplateLevel)-1] } copy := func(a AST) AST { @@ -2569,8 +2958,9 @@ func (st *state) substitution(forPrefix bool) AST { } return nil case *Closure: - // Undo the decrement in skip. - st.inLambda-- + // Undo the save in skip. + st.lambdaTemplateLevel = oldLambdaTemplateLevel[len(oldLambdaTemplateLevel)-1] + oldLambdaTemplateLevel = oldLambdaTemplateLevel[:len(oldLambdaTemplateLevel)-1] return nil case *TemplateParam: index = a.Index @@ -2582,7 +2972,7 @@ func (st *state) substitution(forPrefix bool) AST { default: return nil } - if st.inLambda > 0 { + if st.lambdaTemplateLevel > 0 { if _, ok := a.(*LambdaAuto); ok { return nil } @@ -2598,7 +2988,7 @@ func (st *state) substitution(forPrefix bool) AST { // here. template = rt } else { - st.failEarlier("substituted template parameter not in scope of template", dec) + st.failEarlier("substituted template parameter not in scope of template", st.off-off) } if template == nil { // This template parameter is within @@ -2607,7 +2997,7 @@ func (st *state) substitution(forPrefix bool) AST { } if index >= len(template.Args) { - st.failEarlier(fmt.Sprintf("substituted template index out of range (%d >= %d)", index, len(template.Args)), dec) + st.failEarlier(fmt.Sprintf("substituted template index out of range (%d >= %d)", index, len(template.Args)), st.off-off) } return &TemplateParam{Index: index, Template: template} @@ -2622,8 +3012,9 @@ func (st *state) substitution(forPrefix bool) AST { } return false case *Closure: - // This is decremented in copy. - st.inLambda++ + // This is undone in copy. + oldLambdaTemplateLevel = append(oldLambdaTemplateLevel, st.lambdaTemplateLevel) + st.lambdaTemplateLevel = len(copyTemplates) + 1 return false case *TemplateParam, *LambdaAuto: return false @@ -2643,6 +3034,7 @@ func (st *state) substitution(forPrefix bool) AST { return ret } else { + st.advance(1) m := subAST if st.verbose { m = verboseAST diff --git a/src/cmd/vendor/github.com/ianlancetaylor/demangle/rust.go b/src/cmd/vendor/github.com/ianlancetaylor/demangle/rust.go new file mode 100644 index 0000000000..140b631644 --- /dev/null +++ b/src/cmd/vendor/github.com/ianlancetaylor/demangle/rust.go @@ -0,0 +1,1069 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package demangle + +import ( + "fmt" + "math" + "math/bits" + "strings" + "unicode/utf8" +) + +// rustToString demangles a Rust symbol. +func rustToString(name string, options []Option) (ret string, err error) { + if !strings.HasPrefix(name, "_R") { + return "", ErrNotMangledName + } + + // When the demangling routines encounter an error, they panic + // with a value of type demangleErr. + defer func() { + if r := recover(); r != nil { + if de, ok := r.(demangleErr); ok { + ret = "" + err = de + return + } + panic(r) + } + }() + + suffix := "" + dot := strings.Index(name, ".") + if dot >= 0 { + suffix = name[dot:] + name = name[:dot] + } + + name = name[2:] + rst := &rustState{orig: name, str: name} + rst.symbolName() + + if len(rst.str) > 0 { + rst.fail("unparsed characters at end of mangled name") + } + + if suffix != "" { + rst.skip = false + rst.writeString(" (") + rst.writeString(suffix) + rst.writeByte(')') + } + + return rst.buf.String(), nil +} + +// A rustState holds the current state of demangling a Rust string. +type rustState struct { + orig string // the original string being demangled + str string // remainder of string to demangle + off int // offset of str within original string + buf strings.Builder // demangled string being built + skip bool // don't print, just skip + lifetimes int64 // number of bound lifetimes + last byte // last byte written to buffer +} + +// fail panics with demangleErr, to be caught in rustToString. +func (rst *rustState) fail(err string) { + panic(demangleErr{err: err, off: rst.off}) +} + +// advance advances the current string offset. +func (rst *rustState) advance(add int) { + if len(rst.str) < add { + panic("internal error") + } + rst.str = rst.str[add:] + rst.off += add +} + +// checkChar requires that the next character in the string be c, +// and advances past it. +func (rst *rustState) checkChar(c byte) { + if len(rst.str) == 0 || rst.str[0] != c { + rst.fail("expected " + string(c)) + } + rst.advance(1) +} + +// writeByte writes a byte to the buffer. +func (rst *rustState) writeByte(c byte) { + if rst.skip { + return + } + rst.last = c + rst.buf.WriteByte(c) +} + +// writeString writes a string to the buffer. +func (rst *rustState) writeString(s string) { + if rst.skip { + return + } + if len(s) > 0 { + rst.last = s[len(s)-1] + rst.buf.WriteString(s) + } +} + +// = "_R" [] [] +// = +// +// We've already skipped the "_R". +func (rst *rustState) symbolName() { + if len(rst.str) < 1 { + rst.fail("expected symbol-name") + } + + if isDigit(rst.str[0]) { + rst.fail("unsupported Rust encoding version") + } + + rst.path(true) + + if len(rst.str) > 0 { + rst.skip = true + rst.path(false) + } +} + +// = "C" // crate root +// | "M" // (inherent impl) +// | "X" // (trait impl) +// | "Y" // (trait definition) +// | "N" // ...::ident (nested path) +// | "I" {} "E" // ... (generic args) +// | +// = "C" // closure +// | "S" // shim +// | // other special namespaces +// | // internal namespaces +// +// needsSeparator is true if we need to write out :: for a generic; +// it is passed as false if we are in the middle of a type. +func (rst *rustState) path(needsSeparator bool) { + if len(rst.str) < 1 { + rst.fail("expected path") + } + switch c := rst.str[0]; c { + case 'C': + rst.advance(1) + _, ident := rst.identifier() + rst.writeString(ident) + case 'M', 'X': + rst.advance(1) + rst.implPath() + rst.writeByte('<') + rst.demangleType() + if c == 'X' { + rst.writeString(" as ") + rst.path(false) + } + rst.writeByte('>') + case 'Y': + rst.advance(1) + rst.writeByte('<') + rst.demangleType() + rst.writeString(" as ") + rst.path(false) + rst.writeByte('>') + case 'N': + rst.advance(1) + + if len(rst.str) < 1 { + rst.fail("expected namespace") + } + ns := rst.str[0] + switch { + case ns >= 'a' && ns <= 'z': + case ns >= 'A' && ns <= 'Z': + default: + rst.fail("invalid namespace character") + } + rst.advance(1) + + rst.path(needsSeparator) + + dis, ident := rst.identifier() + + if ns >= 'A' && ns <= 'Z' { + rst.writeString("::{") + switch ns { + case 'C': + rst.writeString("closure") + case 'S': + rst.writeString("shim") + default: + rst.writeByte(ns) + } + if len(ident) > 0 { + rst.writeByte(':') + rst.writeString(ident) + } + if !rst.skip { + fmt.Fprintf(&rst.buf, "#%d}", dis) + rst.last = '}' + } + } else { + rst.writeString("::") + rst.writeString(ident) + } + case 'I': + rst.advance(1) + rst.path(needsSeparator) + if needsSeparator { + rst.writeString("::") + } + rst.writeByte('<') + first := true + for len(rst.str) > 0 && rst.str[0] != 'E' { + if first { + first = false + } else { + rst.writeString(", ") + } + rst.genericArg() + } + rst.writeByte('>') + rst.checkChar('E') + case 'B': + rst.backref(func() { rst.path(needsSeparator) }) + default: + rst.fail("unrecognized letter in path") + } +} + +// = [] +func (rst *rustState) implPath() { + // This path is not part of the demangled string. + hold := rst.skip + rst.skip = true + defer func() { + rst.skip = hold + }() + + rst.disambiguator() + rst.path(false) +} + +// = [] +// Returns the disambiguator and the identifier. +func (rst *rustState) identifier() (int64, string) { + dis := rst.disambiguator() + ident := rst.undisambiguatedIdentifier() + return dis, ident +} + +// = "s" +// This is optional. +func (rst *rustState) disambiguator() int64 { + if len(rst.str) == 0 || rst.str[0] != 's' { + return 0 + } + rst.advance(1) + return rst.base62Number() + 1 +} + +// = ["u"] ["_"] +func (rst *rustState) undisambiguatedIdentifier() string { + punycode := false + if len(rst.str) > 0 && rst.str[0] == 'u' { + rst.advance(1) + punycode = true + } + + val := rst.decimalNumber() + + if len(rst.str) > 0 && rst.str[0] == '_' { + rst.advance(1) + } + + if len(rst.str) < val { + rst.fail("not enough characters for identifier") + } + id := rst.str[:val] + rst.advance(val) + + for i := 0; i < len(id); i++ { + c := id[i] + switch { + case c >= '0' && c <= '9': + case c >= 'A' && c <= 'Z': + case c >= 'a' && c <= 'z': + case c == '_': + default: + rst.fail("invalid character in identifier") + } + } + + if punycode { + id = rst.expandPunycode(id) + } + + return id +} + +// expandPunycode decodes the Rust version of punycode. +// This algorithm is taken from RFC 3492 section 6.2. +func (rst *rustState) expandPunycode(s string) string { + const ( + base = 36 + tmin = 1 + tmax = 26 + skew = 38 + damp = 700 + initialBias = 72 + initialN = 128 + ) + + idx := strings.LastIndex(s, "_") + if idx < 0 { + rst.fail("missing underscore in punycode string") + } + + output := []rune(s[:idx]) + encoding := s[idx+1:] + + i := 0 + n := initialN + bias := initialBias + + pos := 0 + for pos < len(encoding) { + oldI := i + w := 1 + for k := base; ; k += base { + if pos == len(encoding) { + rst.fail("unterminated punycode") + } + + var digit byte + d := encoding[pos] + pos++ + switch { + case '0' <= d && d <= '9': + digit = d - '0' + 26 + case 'A' <= d && d <= 'Z': + digit = d - 'A' + case 'a' <= d && d <= 'z': + digit = d - 'a' + default: + rst.fail("invalid punycode digit") + } + + i += int(digit) * w + if i < 0 { + rst.fail("punycode number overflow") + } + + var t int + if k <= bias { + t = tmin + } else if k > bias+tmax { + t = tmax + } else { + t = k - bias + } + + if int(digit) < t { + break + } + + if w >= math.MaxInt32/base { + rst.fail("punycode number overflow") + } + w *= base - t + } + + delta := i - oldI + numPoints := len(output) + 1 + firstTime := oldI == 0 + if firstTime { + delta /= damp + } else { + delta /= 2 + } + delta += delta / numPoints + k := 0 + for delta > ((base-tmin)*tmax)/2 { + delta /= base - tmin + k += base + } + bias = k + ((base-tmin+1)*delta)/(delta+skew) + + n += i / (len(output) + 1) + if n > utf8.MaxRune { + rst.fail("punycode rune overflow") + } + i %= len(output) + 1 + output = append(output, 0) + copy(output[i+1:], output[i:]) + output[i] = rune(n) + i++ + } + + return string(output) +} + +// = +// | +// | "K" // forward-compat for const generics +// = "L" +func (rst *rustState) genericArg() { + if len(rst.str) < 1 { + rst.fail("expected generic-arg") + } + if rst.str[0] == 'L' { + rst.advance(1) + rst.writeLifetime(rst.base62Number()) + } else if rst.str[0] == 'K' { + rst.advance(1) + rst.demangleConst() + } else { + rst.demangleType() + } +} + +// = "G" +// This is optional. +func (rst *rustState) binder() { + if len(rst.str) < 1 || rst.str[0] != 'G' { + return + } + rst.advance(1) + + binderLifetimes := rst.base62Number() + 1 + + // Every bound lifetime should be referenced later. + if binderLifetimes >= int64(len(rst.str))-rst.lifetimes { + rst.fail("binder lifetimes overflow") + } + + rst.writeString("for<") + for i := int64(0); i < binderLifetimes; i++ { + if i > 0 { + rst.writeString(", ") + } + rst.lifetimes++ + rst.writeLifetime(1) + } + rst.writeString("> ") +} + +// = +// | // named type +// | "A" // [T; N] +// | "S" // [T] +// | "T" {} "E" // (T1, T2, T3, ...) +// | "R" [] // &T +// | "Q" [] // &mut T +// | "P" // *const T +// | "O" // *mut T +// | "F" // fn(...) -> ... +// | "D" // dyn Trait + Send + 'a +// | +func (rst *rustState) demangleType() { + if len(rst.str) < 1 { + rst.fail("expected type") + } + c := rst.str[0] + if c >= 'a' && c <= 'z' { + rst.basicType() + return + } + switch c { + case 'C', 'M', 'X', 'Y', 'N', 'I': + rst.path(false) + case 'A', 'S': + rst.advance(1) + rst.writeByte('[') + rst.demangleType() + if c == 'A' { + rst.writeString("; ") + rst.demangleConst() + } + rst.writeByte(']') + case 'T': + rst.advance(1) + rst.writeByte('(') + c := 0 + for len(rst.str) > 0 && rst.str[0] != 'E' { + if c > 0 { + rst.writeString(", ") + } + c++ + rst.demangleType() + } + if c == 1 { + rst.writeByte(',') + } + rst.writeByte(')') + rst.checkChar('E') + case 'R', 'Q': + rst.advance(1) + rst.writeByte('&') + if len(rst.str) > 0 && rst.str[0] == 'L' { + rst.advance(1) + if lifetime := rst.base62Number(); lifetime > 0 { + rst.writeLifetime(lifetime) + rst.writeByte(' ') + } + } + if c == 'Q' { + rst.writeString("mut ") + } + rst.demangleType() + case 'P': + rst.advance(1) + rst.writeString("*const ") + rst.demangleType() + case 'O': + rst.advance(1) + rst.writeString("*mut ") + rst.demangleType() + case 'F': + rst.advance(1) + hold := rst.lifetimes + rst.fnSig() + rst.lifetimes = hold + case 'D': + rst.advance(1) + hold := rst.lifetimes + rst.dynBounds() + rst.lifetimes = hold + if len(rst.str) == 0 || rst.str[0] != 'L' { + rst.fail("expected L") + } + rst.advance(1) + if lifetime := rst.base62Number(); lifetime > 0 { + if rst.last != ' ' { + rst.writeByte(' ') + } + rst.writeString("+ ") + rst.writeLifetime(lifetime) + } + case 'B': + rst.backref(rst.demangleType) + default: + rst.fail("unrecognized character in type") + } +} + +var rustBasicTypes = map[byte]string{ + 'a': "i8", + 'b': "bool", + 'c': "char", + 'd': "f64", + 'e': "str", + 'f': "f32", + 'h': "u8", + 'i': "isize", + 'j': "usize", + 'l': "i32", + 'm': "u32", + 'n': "i128", + 'o': "u128", + 'p': "_", + 's': "i16", + 't': "u16", + 'u': "()", + 'v': "...", + 'x': "i64", + 'y': "u64", + 'z': "!", +} + +// +func (rst *rustState) basicType() { + if len(rst.str) < 1 { + rst.fail("expected basic type") + } + str, ok := rustBasicTypes[rst.str[0]] + if !ok { + rst.fail("unrecognized basic type character") + } + rst.advance(1) + rst.writeString(str) +} + +// = [] ["U"] ["K" ] {} "E" +// = "C" +// | +func (rst *rustState) fnSig() { + rst.binder() + if len(rst.str) > 0 && rst.str[0] == 'U' { + rst.advance(1) + rst.writeString("unsafe ") + } + if len(rst.str) > 0 && rst.str[0] == 'K' { + rst.advance(1) + if len(rst.str) > 0 && rst.str[0] == 'C' { + rst.advance(1) + rst.writeString(`extern "C" `) + } else { + rst.writeString(`extern "`) + id := rst.undisambiguatedIdentifier() + id = strings.ReplaceAll(id, "_", "-") + rst.writeString(id) + rst.writeString(`" `) + } + } + rst.writeString("fn(") + first := true + for len(rst.str) > 0 && rst.str[0] != 'E' { + if first { + first = false + } else { + rst.writeString(", ") + } + rst.demangleType() + } + rst.checkChar('E') + rst.writeByte(')') + if len(rst.str) > 0 && rst.str[0] == 'u' { + rst.advance(1) + } else { + rst.writeString(" -> ") + rst.demangleType() + } +} + +// = [] {} "E" +func (rst *rustState) dynBounds() { + rst.writeString("dyn ") + rst.binder() + first := true + for len(rst.str) > 0 && rst.str[0] != 'E' { + if first { + first = false + } else { + rst.writeString(" + ") + } + rst.dynTrait() + } + rst.checkChar('E') +} + +// = {} +// = "p" +func (rst *rustState) dynTrait() { + started := rst.pathStartGenerics() + for len(rst.str) > 0 && rst.str[0] == 'p' { + rst.advance(1) + if started { + rst.writeString(", ") + } else { + rst.writeByte('<') + started = true + } + rst.writeString(rst.undisambiguatedIdentifier()) + rst.writeString(" = ") + rst.demangleType() + } + if started { + rst.writeByte('>') + } +} + +// pathStartGenerics is like path but if it sees an I to start generic +// arguments it won't close them. It reports whether it started generics. +func (rst *rustState) pathStartGenerics() bool { + if len(rst.str) < 1 { + rst.fail("expected path") + } + switch rst.str[0] { + case 'I': + rst.advance(1) + rst.path(false) + rst.writeByte('<') + first := true + for len(rst.str) > 0 && rst.str[0] != 'E' { + if first { + first = false + } else { + rst.writeString(", ") + } + rst.genericArg() + } + rst.checkChar('E') + return true + case 'B': + var started bool + rst.backref(func() { started = rst.pathStartGenerics() }) + return started + default: + rst.path(false) + return false + } +} + +// writeLifetime writes out a lifetime binding. +func (rst *rustState) writeLifetime(lifetime int64) { + rst.writeByte('\'') + if lifetime == 0 { + rst.writeByte('_') + return + } + depth := rst.lifetimes - lifetime + if depth < 0 { + rst.fail("invalid lifetime") + } else if depth < 26 { + rst.writeByte('a' + byte(depth)) + } else { + rst.writeByte('z') + if !rst.skip { + fmt.Fprintf(&rst.buf, "%d", depth-26+1) + rst.last = '0' + } + } +} + +// = +// | "p" // placeholder, shown as _ +// | +// = ["n"] {} "_" +func (rst *rustState) demangleConst() { + if len(rst.str) < 1 { + rst.fail("expected constant") + } + + if rst.str[0] == 'B' { + rst.backref(rst.demangleConst) + return + } + + if rst.str[0] == 'p' { + rst.advance(1) + rst.writeByte('_') + return + } + + typ := rst.str[0] + + const ( + invalid = iota + signedInt + unsignedInt + boolean + character + ) + + var kind int + switch typ { + case 'a', 's', 'l', 'x', 'n', 'i': + kind = signedInt + case 'h', 't', 'm', 'y', 'o', 'j': + kind = unsignedInt + case 'b': + kind = boolean + case 'c': + kind = character + default: + rst.fail("unrecognized constant type") + } + + rst.advance(1) + + if kind == signedInt && len(rst.str) > 0 && rst.str[0] == 'n' { + rst.advance(1) + rst.writeByte('-') + } + + start := rst.str + digits := 0 + val := uint64(0) +digitLoop: + for len(rst.str) > 0 { + c := rst.str[0] + var digit uint64 + switch { + case c >= '0' && c <= '9': + digit = uint64(c - '0') + case c >= 'a' && c <= 'f': + digit = uint64(c - 'a' + 10) + case c == '_': + rst.advance(1) + break digitLoop + default: + rst.fail("expected hex digit or _") + } + rst.advance(1) + if val == 0 && digit == 0 && (len(rst.str) == 0 || rst.str[0] != '_') { + rst.fail("invalid leading 0 in constant") + } + val *= 16 + val += digit + digits++ + } + + if digits == 0 { + rst.fail("expected constant") + } + + switch kind { + case signedInt, unsignedInt: + if digits > 16 { + // Value too big, just write out the string. + rst.writeString("0x") + rst.writeString(start[:digits]) + } else { + if !rst.skip { + fmt.Fprintf(&rst.buf, "%d", val) + rst.last = '0' + } + } + case boolean: + if digits > 1 { + rst.fail("boolean value too large") + } else if val == 0 { + rst.writeString("false") + } else if val == 1 { + rst.writeString("true") + } else { + rst.fail("invalid boolean value") + } + case character: + if digits > 6 { + rst.fail("character value too large") + } + rst.writeByte('\'') + if val == '\t' { + rst.writeString(`\t`) + } else if val == '\r' { + rst.writeString(`\r`) + } else if val == '\n' { + rst.writeString(`\n`) + } else if val == '\\' { + rst.writeString(`\\`) + } else if val == '\'' { + rst.writeString(`\'`) + } else if val >= ' ' && val <= '~' { + // printable ASCII character + rst.writeByte(byte(val)) + } else { + if !rst.skip { + fmt.Fprintf(&rst.buf, `\u{%x}`, val) + rst.last = '}' + } + } + rst.writeByte('\'') + default: + panic("internal error") + } +} + +// = {<0-9a-zA-Z>} "_" +func (rst *rustState) base62Number() int64 { + if len(rst.str) > 0 && rst.str[0] == '_' { + rst.advance(1) + return 0 + } + val := int64(0) + for len(rst.str) > 0 { + c := rst.str[0] + rst.advance(1) + if c == '_' { + return val + 1 + } + val *= 62 + if c >= '0' && c <= '9' { + val += int64(c - '0') + } else if c >= 'a' && c <= 'z' { + val += int64(c - 'a' + 10) + } else if c >= 'A' && c <= 'Z' { + val += int64(c - 'A' + 36) + } else { + rst.fail("invalid digit in base 62 number") + } + } + rst.fail("expected _ after base 62 number") + return 0 +} + +// = "B" +func (rst *rustState) backref(demangle func()) { + backoff := rst.off + + rst.checkChar('B') + idx64 := rst.base62Number() + + if rst.skip { + return + } + + idx := int(idx64) + if int64(idx) != idx64 { + rst.fail("backref index overflow") + } + if idx < 0 || idx >= backoff { + rst.fail("invalid backref index") + } + + holdStr := rst.str + holdOff := rst.off + rst.str = rst.orig[idx:backoff] + rst.off = idx + defer func() { + rst.str = holdStr + rst.off = holdOff + }() + + demangle() +} + +func (rst *rustState) decimalNumber() int { + if len(rst.str) == 0 { + rst.fail("expected number") + } + + val := 0 + for len(rst.str) > 0 && isDigit(rst.str[0]) { + add := int(rst.str[0] - '0') + if val >= math.MaxInt32/10-add { + rst.fail("decimal number overflow") + } + val *= 10 + val += add + rst.advance(1) + } + return val +} + +// oldRustToString demangles a Rust symbol using the old demangling. +// The second result reports whether this is a valid Rust mangled name. +func oldRustToString(name string, options []Option) (string, bool) { + // We know that the string starts with _ZN. + name = name[3:] + + hexDigit := func(c byte) (byte, bool) { + switch { + case c >= '0' && c <= '9': + return c - '0', true + case c >= 'a' && c <= 'f': + return c - 'a' + 10, true + default: + return 0, false + } + } + + // We know that the strings end with "17h" followed by 16 characters + // followed by "E". We check that the 16 characters are all hex digits. + // Also the hex digits must contain at least 5 distinct digits. + seen := uint16(0) + for i := len(name) - 17; i < len(name) - 1; i++ { + digit, ok := hexDigit(name[i]) + if !ok { + return "", false + } + seen |= 1 << digit + } + if bits.OnesCount16(seen) < 5 { + return "", false + } + name = name[:len(name)-20] + + // The name is a sequence of length-preceded identifiers. + var sb strings.Builder + for len(name) > 0 { + if !isDigit(name[0]) { + return "", false + } + + val := 0 + for len(name) > 0 && isDigit(name[0]) { + add := int(name[0] - '0') + if val >= math.MaxInt32/10-add { + return "", false + } + val *= 10 + val += add + name = name[1:] + } + + // An optional trailing underscore can separate the + // length from the identifier. + if len(name) > 0 && name[0] == '_' { + name = name[1:] + val-- + } + + if len(name) < val { + return "", false + } + + id := name[:val] + name = name[val:] + + if sb.Len() > 0 { + sb.WriteString("::") + } + + // Ignore leading underscores preceding escape sequences. + if strings.HasPrefix(id, "_$") { + id = id[1:] + } + + // The identifier can have escape sequences. + escape: + for len(id) > 0 { + switch c := id[0]; c { + case '$': + codes := map[string]byte { + "SP": '@', + "BP": '*', + "RF": '&', + "LT": '<', + "GT": '>', + "LP": '(', + "RP": ')', + } + + valid := true + if len(id) > 2 && id[1] == 'C' && id[2] == '$' { + sb.WriteByte(',') + id = id[3:] + } else if len(id) > 4 && id[1] == 'u' && id[4] == '$' { + dig1, ok1 := hexDigit(id[2]) + dig2, ok2 := hexDigit(id[3]) + val := (dig1 << 4) | dig2 + if !ok1 || !ok2 || dig1 > 7 || val < ' ' { + valid = false + } else { + sb.WriteByte(val) + id = id[5:] + } + } else if len(id) > 3 && id[3] == '$' { + if code, ok := codes[id[1:3]]; !ok { + valid = false + } else { + sb.WriteByte(code) + id = id[4:] + } + } else { + valid = false + } + if !valid { + sb.WriteString(id) + break escape + } + case '.': + if strings.HasPrefix(id, "..") { + sb.WriteString("::") + id = id[2:] + } else { + sb.WriteByte(c) + id = id[1:] + } + default: + sb.WriteByte(c) + id = id[1:] + } + } + } + + return sb.String(), true +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh b/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh index 0bcb8c3226..a74ef58f8c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -54,7 +54,7 @@ includes_AIX=' includes_Darwin=' #define _DARWIN_C_SOURCE -#define KERNEL +#define KERNEL 1 #define _DARWIN_USE_64_BIT_INODE #define __APPLE_USE_RFC_3542 #include @@ -75,6 +75,7 @@ includes_Darwin=' #include #include #include +#include #include #include #include @@ -82,6 +83,9 @@ includes_Darwin=' #include #include #include + +// for backwards compatibility because moved TIOCREMOTE to Kernel.framework after MacOSX12.0.sdk. +#define TIOCREMOTE 0x80047469 ' includes_DragonFly=' @@ -229,6 +233,7 @@ struct ltchars { #include #include #include +#include #include #include #include @@ -465,7 +470,6 @@ ccflags="$@" $2 !~ /^EQUIV_/ && $2 !~ /^EXPR_/ && $2 !~ /^EVIOC/ && - $2 !~ /^EV_/ && $2 ~ /^E[A-Z0-9_]+$/ || $2 ~ /^B[0-9_]+$/ || $2 ~ /^(OLD|NEW)DEV$/ || @@ -497,6 +501,7 @@ ccflags="$@" $2 ~ /^O?XTABS$/ || $2 ~ /^TC[IO](ON|OFF)$/ || $2 ~ /^IN_/ || + $2 ~ /^LANDLOCK_/ || $2 ~ /^LOCK_(SH|EX|NB|UN)$/ || $2 ~ /^LO_(KEY|NAME)_SIZE$/ || $2 ~ /^LOOP_(CLR|CTL|GET|SET)_/ || diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go index 23f6b57606..a8c13317d7 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go @@ -48,6 +48,30 @@ func (sa *SockaddrCtl) sockaddr() (unsafe.Pointer, _Socklen, error) { return unsafe.Pointer(&sa.raw), SizeofSockaddrCtl, nil } +// SockaddrVM implements the Sockaddr interface for AF_VSOCK type sockets. +// SockaddrVM provides access to Darwin VM sockets: a mechanism that enables +// bidirectional communication between a hypervisor and its guest virtual +// machines. +type SockaddrVM struct { + // CID and Port specify a context ID and port address for a VM socket. + // Guests have a unique CID, and hosts may have a well-known CID of: + // - VMADDR_CID_HYPERVISOR: refers to the hypervisor process. + // - VMADDR_CID_LOCAL: refers to local communication (loopback). + // - VMADDR_CID_HOST: refers to other processes on the host. + CID uint32 + Port uint32 + raw RawSockaddrVM +} + +func (sa *SockaddrVM) sockaddr() (unsafe.Pointer, _Socklen, error) { + sa.raw.Len = SizeofSockaddrVM + sa.raw.Family = AF_VSOCK + sa.raw.Port = sa.Port + sa.raw.Cid = sa.CID + + return unsafe.Pointer(&sa.raw), SizeofSockaddrVM, nil +} + func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { switch rsa.Addr.Family { case AF_SYSTEM: @@ -58,6 +82,13 @@ func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { sa.Unit = pp.Sc_unit return sa, nil } + case AF_VSOCK: + pp := (*RawSockaddrVM)(unsafe.Pointer(rsa)) + sa := &SockaddrVM{ + CID: pp.Cid, + Port: pp.Port, + } + return sa, nil } return nil, EAFNOSUPPORT } @@ -433,6 +464,11 @@ func SysctlKinfoProcSlice(name string) ([]KinfoProc, error) { //sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) +//sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error) +//sys shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) +//sys shmdt(addr uintptr) (err error) +//sys shmget(key int, size int, flag int) (id int, err error) + /* * Exposed directly */ @@ -590,10 +626,6 @@ func SysctlKinfoProcSlice(name string) ([]KinfoProc, error) { // Msgget // Msgsnd // Msgrcv -// Shmat -// Shmctl -// Shmdt -// Shmget // Shm_open // Shm_unlink // Sem_open diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_illumos.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_illumos.go index 8c53576835..8d5f294c42 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_illumos.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_illumos.go @@ -162,6 +162,14 @@ func (l *Lifreq) GetLifruInt() int { return *(*int)(unsafe.Pointer(&l.Lifru[0])) } +func (l *Lifreq) SetLifruUint(d uint) { + *(*uint)(unsafe.Pointer(&l.Lifru[0])) = d +} + +func (l *Lifreq) GetLifruUint() uint { + return *(*uint)(unsafe.Pointer(&l.Lifru[0])) +} + func IoctlLifreq(fd int, req uint, l *Lifreq) error { return ioctl(fd, req, uintptr(unsafe.Pointer(l))) } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go index 2839435e3d..fff38a84c9 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -13,7 +13,6 @@ package unix import ( "encoding/binary" - "runtime" "syscall" "unsafe" ) @@ -38,6 +37,13 @@ func Creat(path string, mode uint32) (fd int, err error) { return Open(path, O_CREAT|O_WRONLY|O_TRUNC, mode) } +func EpollCreate(size int) (fd int, err error) { + if size <= 0 { + return -1, EINVAL + } + return EpollCreate1(0) +} + //sys FanotifyInit(flags uint, event_f_flags uint) (fd int, err error) //sys fanotifyMark(fd int, flags uint, mask uint64, dirFd int, pathname *byte) (err error) @@ -66,6 +72,10 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { return fchmodat(dirfd, path, mode) } +func InotifyInit() (fd int, err error) { + return InotifyInit1(0) +} + //sys ioctl(fd int, req uint, arg uintptr) (err error) = SYS_IOCTL //sys ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) = SYS_IOCTL @@ -109,6 +119,23 @@ func Openat2(dirfd int, path string, how *OpenHow) (fd int, err error) { return openat2(dirfd, path, how, SizeofOpenHow) } +func Pipe(p []int) error { + return Pipe2(p, 0) +} + +//sysnb pipe2(p *[2]_C_int, flags int) (err error) + +func Pipe2(p []int, flags int) error { + if len(p) != 2 { + return EINVAL + } + var pp [2]_C_int + err := pipe2(&pp, flags) + p[0] = int(pp[0]) + p[1] = int(pp[1]) + return err +} + //sys ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) func Ppoll(fds []PollFd, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { @@ -118,6 +145,15 @@ func Ppoll(fds []PollFd, timeout *Timespec, sigmask *Sigset_t) (n int, err error return ppoll(&fds[0], len(fds), timeout, sigmask) } +func Poll(fds []PollFd, timeout int) (n int, err error) { + var ts *Timespec + if timeout >= 0 { + ts = new(Timespec) + *ts = NsecToTimespec(int64(timeout) * 1e6) + } + return Ppoll(fds, ts, nil) +} + //sys Readlinkat(dirfd int, path string, buf []byte) (n int, err error) func Readlink(path string, buf []byte) (n int, err error) { @@ -168,27 +204,7 @@ func Utimes(path string, tv []Timeval) error { //sys utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) func UtimesNano(path string, ts []Timespec) error { - if ts == nil { - err := utimensat(AT_FDCWD, path, nil, 0) - if err != ENOSYS { - return err - } - return utimes(path, nil) - } - if len(ts) != 2 { - return EINVAL - } - err := utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) - if err != ENOSYS { - return err - } - // If the utimensat syscall isn't available (utimensat was added to Linux - // in 2.6.22, Released, 8 July 2007) then fall back to utimes - var tv [2]Timeval - for i := 0; i < 2; i++ { - tv[i] = NsecToTimeval(TimespecToNsec(ts[i])) - } - return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) + return UtimesNanoAt(AT_FDCWD, path, ts, 0) } func UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) error { @@ -1229,11 +1245,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { func Accept(fd int) (nfd int, sa Sockaddr, err error) { var rsa RawSockaddrAny var len _Socklen = SizeofSockaddrAny - // Try accept4 first for Android, then try accept for kernel older than 2.6.28 nfd, err = accept4(fd, &rsa, &len, 0) - if err == ENOSYS { - nfd, err = accept(fd, &rsa, &len) - } if err != nil { return } @@ -1816,11 +1828,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Dup(oldfd int) (fd int, err error) func Dup2(oldfd, newfd int) error { - // Android O and newer blocks dup2; riscv and arm64 don't implement dup2. - if runtime.GOOS == "android" || runtime.GOARCH == "riscv64" || runtime.GOARCH == "arm64" { - return Dup3(oldfd, newfd, 0) - } - return dup2(oldfd, newfd) + return Dup3(oldfd, newfd, 0) } //sys Dup3(oldfd int, newfd int, flags int) (err error) @@ -2308,6 +2316,14 @@ type RemoteIovec struct { //sys ProcessVMReadv(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) = SYS_PROCESS_VM_READV //sys ProcessVMWritev(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) = SYS_PROCESS_VM_WRITEV +//sys PidfdOpen(pid int, flags int) (fd int, err error) = SYS_PIDFD_OPEN +//sys PidfdGetfd(pidfd int, targetfd int, flags int) (fd int, err error) = SYS_PIDFD_GETFD + +//sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error) +//sys shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) +//sys shmdt(addr uintptr) (err error) +//sys shmget(key int, size int, flag int) (id int, err error) + /* * Unimplemented */ @@ -2389,10 +2405,6 @@ type RemoteIovec struct { // SetRobustList // SetThreadArea // SetTidAddress -// Shmat -// Shmctl -// Shmdt -// Shmget // Sigaltstack // Swapoff // Swapon diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_386.go index 91317d749a..5f757e8aa7 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_386.go @@ -19,36 +19,8 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: int32(sec), Usec: int32(usec)} } -//sysnb pipe(p *[2]_C_int) (err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe(&pp) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - // 64-bit file system and 32-bit uid calls // (386 default is 32-bit file system and 16-bit uid). -//sys dup2(oldfd int, newfd int) (err error) -//sysnb EpollCreate(size int) (fd int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64_64 //sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32 @@ -59,7 +31,6 @@ func Pipe2(p []int, flags int) (err error) { //sysnb Geteuid() (euid int) = SYS_GETEUID32 //sysnb Getgid() (gid int) = SYS_GETGID32 //sysnb Getuid() (uid int) = SYS_GETUID32 -//sysnb InotifyInit() (fd int, err error) //sys Ioperm(from int, num int, on int) (err error) //sys Iopl(level int) (err error) //sys Lchown(path string, uid int, gid int) (err error) = SYS_LCHOWN32 @@ -381,12 +352,3 @@ func (cmsg *Cmsghdr) SetLen(length int) { func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { rsa.Service_name_len = uint32(length) } - -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) -} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go index 85cd97da09..4299125aa7 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go @@ -7,8 +7,6 @@ package unix -//sys dup2(oldfd int, newfd int) (err error) -//sysnb EpollCreate(size int) (fd int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fchown(fd int, uid int, gid int) (err error) @@ -21,17 +19,6 @@ package unix //sysnb Getgid() (gid int) //sysnb Getrlimit(resource int, rlim *Rlimit) (err error) //sysnb Getuid() (uid int) -//sysnb inotifyInit() (fd int, err error) - -func InotifyInit() (fd int, err error) { - // First try inotify_init1, because Android's seccomp policy blocks the latter. - fd, err = InotifyInit1(0) - if err == ENOSYS { - fd, err = inotifyInit() - } - return -} - //sys Ioperm(from int, num int, on int) (err error) //sys Iopl(level int) (err error) //sys Lchown(path string, uid int, gid int) (err error) @@ -126,32 +113,6 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: sec, Usec: usec} } -//sysnb pipe(p *[2]_C_int) (err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe(&pp) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - func (r *PtraceRegs) PC() uint64 { return r.Rip } func (r *PtraceRegs) SetPC(pc uint64) { r.Rip = pc } @@ -176,15 +137,6 @@ func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { rsa.Service_name_len = uint64(length) } -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) -} - //sys kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error) func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm.go index b961a620e9..79edeb9cb1 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm.go @@ -19,36 +19,6 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: int32(sec), Usec: int32(usec)} } -//sysnb pipe(p *[2]_C_int) (err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - // Try pipe2 first for Android O, then try pipe for kernel 2.6.23. - err = pipe2(&pp, 0) - if err == ENOSYS { - err = pipe(&pp) - } - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { newoffset, errno := seek(fd, offset, whence) if errno != 0 { @@ -76,8 +46,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { // 64-bit file system and 32-bit uid calls // (16-bit uid calls are not always supported in newer kernels) -//sys dup2(oldfd int, newfd int) (err error) -//sysnb EpollCreate(size int) (fd int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32 //sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64 @@ -86,7 +54,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { //sysnb Geteuid() (euid int) = SYS_GETEUID32 //sysnb Getgid() (gid int) = SYS_GETGID32 //sysnb Getuid() (uid int) = SYS_GETUID32 -//sysnb InotifyInit() (fd int, err error) //sys Lchown(path string, uid int, gid int) (err error) = SYS_LCHOWN32 //sys Listen(s int, n int) (err error) //sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64 @@ -260,15 +227,6 @@ func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { rsa.Service_name_len = uint32(length) } -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) -} - //sys armSyncFileRange(fd int, flags int, off int64, n int64) (err error) = SYS_ARM_SYNC_FILE_RANGE func SyncFileRange(fd int, off int64, n int64, flags int) error { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go index 4b977ba44b..862890de29 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go @@ -9,13 +9,6 @@ package unix import "unsafe" -func EpollCreate(size int) (fd int, err error) { - if size <= 0 { - return -1, EINVAL - } - return EpollCreate1(0) -} - //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fchown(fd int, uid int, gid int) (err error) @@ -145,30 +138,6 @@ func utimes(path string, tv *[2]Timeval) (err error) { return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) } -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, 0) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - // Getrlimit prefers the prlimit64 system call. See issue 38604. func Getrlimit(resource int, rlim *Rlimit) error { err := Prlimit(0, resource, nil, rlim) @@ -211,31 +180,11 @@ func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { rsa.Service_name_len = uint64(length) } -func InotifyInit() (fd int, err error) { - return InotifyInit1(0) -} - -// dup2 exists because func Dup3 in syscall_linux.go references -// it in an unreachable path. dup2 isn't available on arm64. -func dup2(oldfd int, newfd int) error - func Pause() error { _, err := ppoll(nil, 0, nil, nil) return err } -func Poll(fds []PollFd, timeout int) (n int, err error) { - var ts *Timespec - if timeout >= 0 { - ts = new(Timespec) - *ts = NsecToTimespec(int64(timeout) * 1e6) - } - if len(fds) == 0 { - return ppoll(nil, 0, ts, nil) - } - return ppoll(&fds[0], len(fds), ts, nil) -} - //sys kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error) func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go index 27aee81d97..8932e34ad2 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go @@ -8,8 +8,6 @@ package unix -//sys dup2(oldfd int, newfd int) (err error) -//sysnb EpollCreate(size int) (fd int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fchown(fd int, uid int, gid int) (err error) @@ -94,30 +92,6 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: sec, Usec: usec} } -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, 0) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - func Ioperm(from int, num int, on int) (err error) { return ENOSYS } @@ -220,16 +194,3 @@ func (cmsg *Cmsghdr) SetLen(length int) { func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { rsa.Service_name_len = uint64(length) } - -func InotifyInit() (fd int, err error) { - return InotifyInit1(0) -} - -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) -} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go index 21d74e2fbe..7821c25d9f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go @@ -15,8 +15,6 @@ import ( func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) -//sys dup2(oldfd int, newfd int) (err error) -//sysnb EpollCreate(size int) (fd int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fchown(fd int, uid int, gid int) (err error) @@ -60,7 +58,6 @@ func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, //sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) //sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) -//sysnb InotifyInit() (fd int, err error) //sys Ioperm(from int, num int, on int) (err error) //sys Iopl(level int) (err error) @@ -113,29 +110,6 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: int32(sec), Usec: int32(usec)} } -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe() (p1 int, p2 int, err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - p[0], p[1], err = pipe() - return -} - //sys mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error) func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) { @@ -232,12 +206,3 @@ func (cmsg *Cmsghdr) SetLen(length int) { func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { rsa.Service_name_len = uint32(length) } - -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) -} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go index 6f1fc581ed..c5053a0f03 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go @@ -12,8 +12,6 @@ import ( "unsafe" ) -//sys dup2(oldfd int, newfd int) (err error) -//sysnb EpollCreate(size int) (fd int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fchown(fd int, uid int, gid int) (err error) //sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64 @@ -23,7 +21,6 @@ import ( //sysnb Geteuid() (euid int) //sysnb Getgid() (gid int) //sysnb Getuid() (uid int) -//sysnb InotifyInit() (fd int, err error) //sys Ioperm(from int, num int, on int) (err error) //sys Iopl(level int) (err error) //sys Lchown(path string, uid int, gid int) (err error) @@ -218,41 +215,6 @@ func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { rsa.Service_name_len = uint32(length) } -//sysnb pipe(p *[2]_C_int) (err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe(&pp) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) -} - //sys syncFileRange2(fd int, flags int, off int64, n int64) (err error) = SYS_SYNC_FILE_RANGE2 func SyncFileRange(fd int, off int64, n int64, flags int) error { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go index 5259a5feaf..25786c4216 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go @@ -8,8 +8,6 @@ package unix -//sys dup2(oldfd int, newfd int) (err error) -//sysnb EpollCreate(size int) (fd int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fchown(fd int, uid int, gid int) (err error) @@ -22,7 +20,6 @@ package unix //sysnb Getgid() (gid int) //sysnb Getrlimit(resource int, rlim *Rlimit) (err error) = SYS_UGETRLIMIT //sysnb Getuid() (uid int) -//sysnb InotifyInit() (fd int, err error) //sys Ioperm(from int, num int, on int) (err error) //sys Iopl(level int) (err error) //sys Lchown(path string, uid int, gid int) (err error) @@ -104,41 +101,6 @@ func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { rsa.Service_name_len = uint64(length) } -//sysnb pipe(p *[2]_C_int) (err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe(&pp) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) -} - //sys syncFileRange2(fd int, flags int, off int64, n int64) (err error) = SYS_SYNC_FILE_RANGE2 func SyncFileRange(fd int, off int64, n int64, flags int) error { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go index 8ef821e5da..6f9f710414 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go @@ -9,13 +9,6 @@ package unix import "unsafe" -func EpollCreate(size int) (fd int, err error) { - if size <= 0 { - return -1, EINVAL - } - return EpollCreate1(0) -} - //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fchown(fd int, uid int, gid int) (err error) @@ -144,30 +137,6 @@ func utimes(path string, tv *[2]Timeval) (err error) { return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) } -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, 0) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - func (r *PtraceRegs) PC() uint64 { return r.Pc } func (r *PtraceRegs) SetPC(pc uint64) { r.Pc = pc } @@ -192,27 +161,11 @@ func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { rsa.Service_name_len = uint64(length) } -func InotifyInit() (fd int, err error) { - return InotifyInit1(0) -} - func Pause() error { _, err := ppoll(nil, 0, nil, nil) return err } -func Poll(fds []PollFd, timeout int) (n int, err error) { - var ts *Timespec - if timeout >= 0 { - ts = new(Timespec) - *ts = NsecToTimespec(int64(timeout) * 1e6) - } - if len(fds) == 0 { - return ppoll(nil, 0, ts, nil) - } - return ppoll(&fds[0], len(fds), ts, nil) -} - func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) { return Renameat2(olddirfd, oldpath, newdirfd, newpath, 0) } @@ -229,7 +182,3 @@ func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error } return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags) } - -// dup2 exists because func Dup3 in syscall_linux.go references -// it in an unreachable path. dup2 isn't available on arm64. -func dup2(oldfd int, newfd int) error diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go index a1c0574b58..6aa59cb270 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go @@ -11,8 +11,6 @@ import ( "unsafe" ) -//sys dup2(oldfd int, newfd int) (err error) -//sysnb EpollCreate(size int) (fd int, err error) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fchown(fd int, uid int, gid int) (err error) @@ -25,7 +23,6 @@ import ( //sysnb Getgid() (gid int) //sysnb Getrlimit(resource int, rlim *Rlimit) (err error) //sysnb Getuid() (uid int) -//sysnb InotifyInit() (fd int, err error) //sys Lchown(path string, uid int, gid int) (err error) //sys Lstat(path string, stat *Stat_t) (err error) //sys Pause() (err error) @@ -77,30 +74,6 @@ func setTimeval(sec, usec int64) Timeval { return Timeval{Sec: sec, Usec: usec} } -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, 0) // pipe2 is the same as pipe when flags are set to 0. - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - func Ioperm(from int, num int, on int) (err error) { return ENOSYS } @@ -324,15 +297,6 @@ func Shutdown(s, how int) error { return nil } -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) -} - //sys kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error) func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go index de14b88983..bbe8d174f8 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go @@ -9,7 +9,6 @@ package unix //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 -//sys dup2(oldfd int, newfd int) (err error) //sys Fchown(fd int, uid int, gid int) (err error) //sys Fstat(fd int, stat *Stat_t) (err error) //sys Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64 @@ -20,7 +19,6 @@ package unix //sysnb Getgid() (gid int) //sysnb Getrlimit(resource int, rlim *Rlimit) (err error) //sysnb Getuid() (uid int) -//sysnb InotifyInit() (fd int, err error) //sys Lchown(path string, uid int, gid int) (err error) //sys Listen(s int, n int) (err error) //sys Lstat(path string, stat *Stat_t) (err error) @@ -119,38 +117,3 @@ func (cmsg *Cmsghdr) SetLen(length int) { func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { rsa.Service_name_len = uint64(length) } - -//sysnb pipe(p *[2]_C_int) (err error) - -func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe(&pp) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sysnb pipe2(p *[2]_C_int, flags int) (err error) - -func Pipe2(p []int, flags int) (err error) { - if len(p) != 2 { - return EINVAL - } - var pp [2]_C_int - err = pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) - return -} - -//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) - -func Poll(fds []PollFd, timeout int) (n int, err error) { - if len(fds) == 0 { - return poll(nil, 0, timeout) - } - return poll(&fds[0], len(fds), timeout) -} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/sysvshm_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/sysvshm_linux.go new file mode 100644 index 0000000000..2c3a4437f0 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/sys/unix/sysvshm_linux.go @@ -0,0 +1,21 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux +// +build linux + +package unix + +import "runtime" + +// SysvShmCtl performs control operations on the shared memory segment +// specified by id. +func SysvShmCtl(id, cmd int, desc *SysvShmDesc) (result int, err error) { + if runtime.GOARCH == "arm" || + runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le" { + cmd |= ipc_64 + } + + return shmctl(id, cmd, desc) +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/sysvshm_unix.go b/src/cmd/vendor/golang.org/x/sys/unix/sysvshm_unix.go new file mode 100644 index 0000000000..0bb4c8de55 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/sys/unix/sysvshm_unix.go @@ -0,0 +1,61 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (darwin && !ios) || linux +// +build darwin,!ios linux + +package unix + +import ( + "unsafe" + + "golang.org/x/sys/internal/unsafeheader" +) + +// SysvShmAttach attaches the Sysv shared memory segment associated with the +// shared memory identifier id. +func SysvShmAttach(id int, addr uintptr, flag int) ([]byte, error) { + addr, errno := shmat(id, addr, flag) + if errno != nil { + return nil, errno + } + + // Retrieve the size of the shared memory to enable slice creation + var info SysvShmDesc + + _, err := SysvShmCtl(id, IPC_STAT, &info) + if err != nil { + // release the shared memory if we can't find the size + + // ignoring error from shmdt as there's nothing sensible to return here + shmdt(addr) + return nil, err + } + + // Use unsafe to convert addr into a []byte. + // TODO: convert to unsafe.Slice once we can assume Go 1.17 + var b []byte + hdr := (*unsafeheader.Slice)(unsafe.Pointer(&b)) + hdr.Data = unsafe.Pointer(addr) + hdr.Cap = int(info.Segsz) + hdr.Len = int(info.Segsz) + return b, nil +} + +// SysvShmDetach unmaps the shared memory slice returned from SysvShmAttach. +// +// It is not safe to use the slice after calling this function. +func SysvShmDetach(data []byte) error { + if len(data) == 0 { + return EINVAL + } + + return shmdt(uintptr(unsafe.Pointer(&data[0]))) +} + +// SysvShmGet returns the Sysv shared memory identifier associated with key. +// If the IPC_CREAT flag is specified a new segment is created. +func SysvShmGet(key, size, flag int) (id int, err error) { + return shmget(key, size, flag) +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go b/src/cmd/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go new file mode 100644 index 0000000000..71bddefdb8 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go @@ -0,0 +1,14 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin && !ios +// +build darwin,!ios + +package unix + +// SysvShmCtl performs control operations on the shared memory segment +// specified by id. +func SysvShmCtl(id, cmd int, desc *SysvShmDesc) (result int, err error) { + return shmctl(id, cmd, desc) +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go index a3a45fec59..476a1c7e77 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go @@ -12,1556 +12,1582 @@ package unix import "syscall" const ( - AF_APPLETALK = 0x10 - AF_CCITT = 0xa - AF_CHAOS = 0x5 - AF_CNT = 0x15 - AF_COIP = 0x14 - AF_DATAKIT = 0x9 - AF_DECnet = 0xc - AF_DLI = 0xd - AF_E164 = 0x1c - AF_ECMA = 0x8 - AF_HYLINK = 0xf - AF_IEEE80211 = 0x25 - AF_IMPLINK = 0x3 - AF_INET = 0x2 - AF_INET6 = 0x1e - AF_IPX = 0x17 - AF_ISDN = 0x1c - AF_ISO = 0x7 - AF_LAT = 0xe - AF_LINK = 0x12 - AF_LOCAL = 0x1 - AF_MAX = 0x29 - AF_NATM = 0x1f - AF_NDRV = 0x1b - AF_NETBIOS = 0x21 - AF_NS = 0x6 - AF_OSI = 0x7 - AF_PPP = 0x22 - AF_PUP = 0x4 - AF_RESERVED_36 = 0x24 - AF_ROUTE = 0x11 - AF_SIP = 0x18 - AF_SNA = 0xb - AF_SYSTEM = 0x20 - AF_SYS_CONTROL = 0x2 - AF_UNIX = 0x1 - AF_UNSPEC = 0x0 - AF_UTUN = 0x26 - AF_VSOCK = 0x28 - ALTWERASE = 0x200 - ATTR_BIT_MAP_COUNT = 0x5 - ATTR_CMN_ACCESSMASK = 0x20000 - ATTR_CMN_ACCTIME = 0x1000 - ATTR_CMN_ADDEDTIME = 0x10000000 - ATTR_CMN_BKUPTIME = 0x2000 - ATTR_CMN_CHGTIME = 0x800 - ATTR_CMN_CRTIME = 0x200 - ATTR_CMN_DATA_PROTECT_FLAGS = 0x40000000 - ATTR_CMN_DEVID = 0x2 - ATTR_CMN_DOCUMENT_ID = 0x100000 - ATTR_CMN_ERROR = 0x20000000 - ATTR_CMN_EXTENDED_SECURITY = 0x400000 - ATTR_CMN_FILEID = 0x2000000 - ATTR_CMN_FLAGS = 0x40000 - ATTR_CMN_FNDRINFO = 0x4000 - ATTR_CMN_FSID = 0x4 - ATTR_CMN_FULLPATH = 0x8000000 - ATTR_CMN_GEN_COUNT = 0x80000 - ATTR_CMN_GRPID = 0x10000 - ATTR_CMN_GRPUUID = 0x1000000 - ATTR_CMN_MODTIME = 0x400 - ATTR_CMN_NAME = 0x1 - ATTR_CMN_NAMEDATTRCOUNT = 0x80000 - ATTR_CMN_NAMEDATTRLIST = 0x100000 - ATTR_CMN_OBJID = 0x20 - ATTR_CMN_OBJPERMANENTID = 0x40 - ATTR_CMN_OBJTAG = 0x10 - ATTR_CMN_OBJTYPE = 0x8 - ATTR_CMN_OWNERID = 0x8000 - ATTR_CMN_PARENTID = 0x4000000 - ATTR_CMN_PAROBJID = 0x80 - ATTR_CMN_RETURNED_ATTRS = 0x80000000 - ATTR_CMN_SCRIPT = 0x100 - ATTR_CMN_SETMASK = 0x51c7ff00 - ATTR_CMN_USERACCESS = 0x200000 - ATTR_CMN_UUID = 0x800000 - ATTR_CMN_VALIDMASK = 0xffffffff - ATTR_CMN_VOLSETMASK = 0x6700 - ATTR_FILE_ALLOCSIZE = 0x4 - ATTR_FILE_CLUMPSIZE = 0x10 - ATTR_FILE_DATAALLOCSIZE = 0x400 - ATTR_FILE_DATAEXTENTS = 0x800 - ATTR_FILE_DATALENGTH = 0x200 - ATTR_FILE_DEVTYPE = 0x20 - ATTR_FILE_FILETYPE = 0x40 - ATTR_FILE_FORKCOUNT = 0x80 - ATTR_FILE_FORKLIST = 0x100 - ATTR_FILE_IOBLOCKSIZE = 0x8 - ATTR_FILE_LINKCOUNT = 0x1 - ATTR_FILE_RSRCALLOCSIZE = 0x2000 - ATTR_FILE_RSRCEXTENTS = 0x4000 - ATTR_FILE_RSRCLENGTH = 0x1000 - ATTR_FILE_SETMASK = 0x20 - ATTR_FILE_TOTALSIZE = 0x2 - ATTR_FILE_VALIDMASK = 0x37ff - ATTR_VOL_ALLOCATIONCLUMP = 0x40 - ATTR_VOL_ATTRIBUTES = 0x40000000 - ATTR_VOL_CAPABILITIES = 0x20000 - ATTR_VOL_DIRCOUNT = 0x400 - ATTR_VOL_ENCODINGSUSED = 0x10000 - ATTR_VOL_FILECOUNT = 0x200 - ATTR_VOL_FSTYPE = 0x1 - ATTR_VOL_INFO = 0x80000000 - ATTR_VOL_IOBLOCKSIZE = 0x80 - ATTR_VOL_MAXOBJCOUNT = 0x800 - ATTR_VOL_MINALLOCATION = 0x20 - ATTR_VOL_MOUNTEDDEVICE = 0x8000 - ATTR_VOL_MOUNTFLAGS = 0x4000 - ATTR_VOL_MOUNTPOINT = 0x1000 - ATTR_VOL_NAME = 0x2000 - ATTR_VOL_OBJCOUNT = 0x100 - ATTR_VOL_QUOTA_SIZE = 0x10000000 - ATTR_VOL_RESERVED_SIZE = 0x20000000 - ATTR_VOL_SETMASK = 0x80002000 - ATTR_VOL_SIGNATURE = 0x2 - ATTR_VOL_SIZE = 0x4 - ATTR_VOL_SPACEAVAIL = 0x10 - ATTR_VOL_SPACEFREE = 0x8 - ATTR_VOL_UUID = 0x40000 - ATTR_VOL_VALIDMASK = 0xf007ffff - B0 = 0x0 - B110 = 0x6e - B115200 = 0x1c200 - B1200 = 0x4b0 - B134 = 0x86 - B14400 = 0x3840 - B150 = 0x96 - B1800 = 0x708 - B19200 = 0x4b00 - B200 = 0xc8 - B230400 = 0x38400 - B2400 = 0x960 - B28800 = 0x7080 - B300 = 0x12c - B38400 = 0x9600 - B4800 = 0x12c0 - B50 = 0x32 - B57600 = 0xe100 - B600 = 0x258 - B7200 = 0x1c20 - B75 = 0x4b - B76800 = 0x12c00 - B9600 = 0x2580 - BIOCFLUSH = 0x20004268 - BIOCGBLEN = 0x40044266 - BIOCGDLT = 0x4004426a - BIOCGDLTLIST = 0xc00c4279 - BIOCGETIF = 0x4020426b - BIOCGHDRCMPLT = 0x40044274 - BIOCGRSIG = 0x40044272 - BIOCGRTIMEOUT = 0x4010426e - BIOCGSEESENT = 0x40044276 - BIOCGSTATS = 0x4008426f - BIOCIMMEDIATE = 0x80044270 - BIOCPROMISC = 0x20004269 - BIOCSBLEN = 0xc0044266 - BIOCSDLT = 0x80044278 - BIOCSETF = 0x80104267 - BIOCSETFNR = 0x8010427e - BIOCSETIF = 0x8020426c - BIOCSHDRCMPLT = 0x80044275 - BIOCSRSIG = 0x80044273 - BIOCSRTIMEOUT = 0x8010426d - BIOCSSEESENT = 0x80044277 - BIOCVERSION = 0x40044271 - BPF_A = 0x10 - BPF_ABS = 0x20 - BPF_ADD = 0x0 - BPF_ALIGNMENT = 0x4 - BPF_ALU = 0x4 - BPF_AND = 0x50 - BPF_B = 0x10 - BPF_DIV = 0x30 - BPF_H = 0x8 - BPF_IMM = 0x0 - BPF_IND = 0x40 - BPF_JA = 0x0 - BPF_JEQ = 0x10 - BPF_JGE = 0x30 - BPF_JGT = 0x20 - BPF_JMP = 0x5 - BPF_JSET = 0x40 - BPF_K = 0x0 - BPF_LD = 0x0 - BPF_LDX = 0x1 - BPF_LEN = 0x80 - BPF_LSH = 0x60 - BPF_MAJOR_VERSION = 0x1 - BPF_MAXBUFSIZE = 0x80000 - BPF_MAXINSNS = 0x200 - BPF_MEM = 0x60 - BPF_MEMWORDS = 0x10 - BPF_MINBUFSIZE = 0x20 - BPF_MINOR_VERSION = 0x1 - BPF_MISC = 0x7 - BPF_MSH = 0xa0 - BPF_MUL = 0x20 - BPF_NEG = 0x80 - BPF_OR = 0x40 - BPF_RELEASE = 0x30bb6 - BPF_RET = 0x6 - BPF_RSH = 0x70 - BPF_ST = 0x2 - BPF_STX = 0x3 - BPF_SUB = 0x10 - BPF_TAX = 0x0 - BPF_TXA = 0x80 - BPF_W = 0x0 - BPF_X = 0x8 - BRKINT = 0x2 - BS0 = 0x0 - BS1 = 0x8000 - BSDLY = 0x8000 - CFLUSH = 0xf - CLOCAL = 0x8000 - CLOCK_MONOTONIC = 0x6 - CLOCK_MONOTONIC_RAW = 0x4 - CLOCK_MONOTONIC_RAW_APPROX = 0x5 - CLOCK_PROCESS_CPUTIME_ID = 0xc - CLOCK_REALTIME = 0x0 - CLOCK_THREAD_CPUTIME_ID = 0x10 - CLOCK_UPTIME_RAW = 0x8 - CLOCK_UPTIME_RAW_APPROX = 0x9 - CLONE_NOFOLLOW = 0x1 - CLONE_NOOWNERCOPY = 0x2 - CR0 = 0x0 - CR1 = 0x1000 - CR2 = 0x2000 - CR3 = 0x3000 - CRDLY = 0x3000 - CREAD = 0x800 - CRTSCTS = 0x30000 - CS5 = 0x0 - CS6 = 0x100 - CS7 = 0x200 - CS8 = 0x300 - CSIZE = 0x300 - CSTART = 0x11 - CSTATUS = 0x14 - CSTOP = 0x13 - CSTOPB = 0x400 - CSUSP = 0x1a - CTLIOCGINFO = 0xc0644e03 - CTL_HW = 0x6 - CTL_KERN = 0x1 - CTL_MAXNAME = 0xc - CTL_NET = 0x4 - DLT_A429 = 0xb8 - DLT_A653_ICM = 0xb9 - DLT_AIRONET_HEADER = 0x78 - DLT_AOS = 0xde - DLT_APPLE_IP_OVER_IEEE1394 = 0x8a - DLT_ARCNET = 0x7 - DLT_ARCNET_LINUX = 0x81 - DLT_ATM_CLIP = 0x13 - DLT_ATM_RFC1483 = 0xb - DLT_AURORA = 0x7e - DLT_AX25 = 0x3 - DLT_AX25_KISS = 0xca - DLT_BACNET_MS_TP = 0xa5 - DLT_BLUETOOTH_HCI_H4 = 0xbb - DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 0xc9 - DLT_CAN20B = 0xbe - DLT_CAN_SOCKETCAN = 0xe3 - DLT_CHAOS = 0x5 - DLT_CHDLC = 0x68 - DLT_CISCO_IOS = 0x76 - DLT_C_HDLC = 0x68 - DLT_C_HDLC_WITH_DIR = 0xcd - DLT_DBUS = 0xe7 - DLT_DECT = 0xdd - DLT_DOCSIS = 0x8f - DLT_DVB_CI = 0xeb - DLT_ECONET = 0x73 - DLT_EN10MB = 0x1 - DLT_EN3MB = 0x2 - DLT_ENC = 0x6d - DLT_ERF = 0xc5 - DLT_ERF_ETH = 0xaf - DLT_ERF_POS = 0xb0 - DLT_FC_2 = 0xe0 - DLT_FC_2_WITH_FRAME_DELIMS = 0xe1 - DLT_FDDI = 0xa - DLT_FLEXRAY = 0xd2 - DLT_FRELAY = 0x6b - DLT_FRELAY_WITH_DIR = 0xce - DLT_GCOM_SERIAL = 0xad - DLT_GCOM_T1E1 = 0xac - DLT_GPF_F = 0xab - DLT_GPF_T = 0xaa - DLT_GPRS_LLC = 0xa9 - DLT_GSMTAP_ABIS = 0xda - DLT_GSMTAP_UM = 0xd9 - DLT_HHDLC = 0x79 - DLT_IBM_SN = 0x92 - DLT_IBM_SP = 0x91 - DLT_IEEE802 = 0x6 - DLT_IEEE802_11 = 0x69 - DLT_IEEE802_11_RADIO = 0x7f - DLT_IEEE802_11_RADIO_AVS = 0xa3 - DLT_IEEE802_15_4 = 0xc3 - DLT_IEEE802_15_4_LINUX = 0xbf - DLT_IEEE802_15_4_NOFCS = 0xe6 - DLT_IEEE802_15_4_NONASK_PHY = 0xd7 - DLT_IEEE802_16_MAC_CPS = 0xbc - DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1 - DLT_IPFILTER = 0x74 - DLT_IPMB = 0xc7 - DLT_IPMB_LINUX = 0xd1 - DLT_IPNET = 0xe2 - DLT_IPOIB = 0xf2 - DLT_IPV4 = 0xe4 - DLT_IPV6 = 0xe5 - DLT_IP_OVER_FC = 0x7a - DLT_JUNIPER_ATM1 = 0x89 - DLT_JUNIPER_ATM2 = 0x87 - DLT_JUNIPER_ATM_CEMIC = 0xee - DLT_JUNIPER_CHDLC = 0xb5 - DLT_JUNIPER_ES = 0x84 - DLT_JUNIPER_ETHER = 0xb2 - DLT_JUNIPER_FIBRECHANNEL = 0xea - DLT_JUNIPER_FRELAY = 0xb4 - DLT_JUNIPER_GGSN = 0x85 - DLT_JUNIPER_ISM = 0xc2 - DLT_JUNIPER_MFR = 0x86 - DLT_JUNIPER_MLFR = 0x83 - DLT_JUNIPER_MLPPP = 0x82 - DLT_JUNIPER_MONITOR = 0xa4 - DLT_JUNIPER_PIC_PEER = 0xae - DLT_JUNIPER_PPP = 0xb3 - DLT_JUNIPER_PPPOE = 0xa7 - DLT_JUNIPER_PPPOE_ATM = 0xa8 - DLT_JUNIPER_SERVICES = 0x88 - DLT_JUNIPER_SRX_E2E = 0xe9 - DLT_JUNIPER_ST = 0xc8 - DLT_JUNIPER_VP = 0xb7 - DLT_JUNIPER_VS = 0xe8 - DLT_LAPB_WITH_DIR = 0xcf - DLT_LAPD = 0xcb - DLT_LIN = 0xd4 - DLT_LINUX_EVDEV = 0xd8 - DLT_LINUX_IRDA = 0x90 - DLT_LINUX_LAPD = 0xb1 - DLT_LINUX_PPP_WITHDIRECTION = 0xa6 - DLT_LINUX_SLL = 0x71 - DLT_LOOP = 0x6c - DLT_LTALK = 0x72 - DLT_MATCHING_MAX = 0x10a - DLT_MATCHING_MIN = 0x68 - DLT_MFR = 0xb6 - DLT_MOST = 0xd3 - DLT_MPEG_2_TS = 0xf3 - DLT_MPLS = 0xdb - DLT_MTP2 = 0x8c - DLT_MTP2_WITH_PHDR = 0x8b - DLT_MTP3 = 0x8d - DLT_MUX27010 = 0xec - DLT_NETANALYZER = 0xf0 - DLT_NETANALYZER_TRANSPARENT = 0xf1 - DLT_NFC_LLCP = 0xf5 - DLT_NFLOG = 0xef - DLT_NG40 = 0xf4 - DLT_NULL = 0x0 - DLT_PCI_EXP = 0x7d - DLT_PFLOG = 0x75 - DLT_PFSYNC = 0x12 - DLT_PPI = 0xc0 - DLT_PPP = 0x9 - DLT_PPP_BSDOS = 0x10 - DLT_PPP_ETHER = 0x33 - DLT_PPP_PPPD = 0xa6 - DLT_PPP_SERIAL = 0x32 - DLT_PPP_WITH_DIR = 0xcc - DLT_PPP_WITH_DIRECTION = 0xa6 - DLT_PRISM_HEADER = 0x77 - DLT_PRONET = 0x4 - DLT_RAIF1 = 0xc6 - DLT_RAW = 0xc - DLT_RIO = 0x7c - DLT_SCCP = 0x8e - DLT_SITA = 0xc4 - DLT_SLIP = 0x8 - DLT_SLIP_BSDOS = 0xf - DLT_STANAG_5066_D_PDU = 0xed - DLT_SUNATM = 0x7b - DLT_SYMANTEC_FIREWALL = 0x63 - DLT_TZSP = 0x80 - DLT_USB = 0xba - DLT_USB_DARWIN = 0x10a - DLT_USB_LINUX = 0xbd - DLT_USB_LINUX_MMAPPED = 0xdc - DLT_USER0 = 0x93 - DLT_USER1 = 0x94 - DLT_USER10 = 0x9d - DLT_USER11 = 0x9e - DLT_USER12 = 0x9f - DLT_USER13 = 0xa0 - DLT_USER14 = 0xa1 - DLT_USER15 = 0xa2 - DLT_USER2 = 0x95 - DLT_USER3 = 0x96 - DLT_USER4 = 0x97 - DLT_USER5 = 0x98 - DLT_USER6 = 0x99 - DLT_USER7 = 0x9a - DLT_USER8 = 0x9b - DLT_USER9 = 0x9c - DLT_WIHART = 0xdf - DLT_X2E_SERIAL = 0xd5 - DLT_X2E_XORAYA = 0xd6 - DT_BLK = 0x6 - DT_CHR = 0x2 - DT_DIR = 0x4 - DT_FIFO = 0x1 - DT_LNK = 0xa - DT_REG = 0x8 - DT_SOCK = 0xc - DT_UNKNOWN = 0x0 - DT_WHT = 0xe - ECHO = 0x8 - ECHOCTL = 0x40 - ECHOE = 0x2 - ECHOK = 0x4 - ECHOKE = 0x1 - ECHONL = 0x10 - ECHOPRT = 0x20 - EVFILT_AIO = -0x3 - EVFILT_EXCEPT = -0xf - EVFILT_FS = -0x9 - EVFILT_MACHPORT = -0x8 - EVFILT_PROC = -0x5 - EVFILT_READ = -0x1 - EVFILT_SIGNAL = -0x6 - EVFILT_SYSCOUNT = 0x11 - EVFILT_THREADMARKER = 0x11 - EVFILT_TIMER = -0x7 - EVFILT_USER = -0xa - EVFILT_VM = -0xc - EVFILT_VNODE = -0x4 - EVFILT_WRITE = -0x2 - EV_ADD = 0x1 - EV_CLEAR = 0x20 - EV_DELETE = 0x2 - EV_DISABLE = 0x8 - EV_DISPATCH = 0x80 - EV_DISPATCH2 = 0x180 - EV_ENABLE = 0x4 - EV_EOF = 0x8000 - EV_ERROR = 0x4000 - EV_FLAG0 = 0x1000 - EV_FLAG1 = 0x2000 - EV_ONESHOT = 0x10 - EV_OOBAND = 0x2000 - EV_POLL = 0x1000 - EV_RECEIPT = 0x40 - EV_SYSFLAGS = 0xf000 - EV_UDATA_SPECIFIC = 0x100 - EV_VANISHED = 0x200 - EXTA = 0x4b00 - EXTB = 0x9600 - EXTPROC = 0x800 - FD_CLOEXEC = 0x1 - FD_SETSIZE = 0x400 - FF0 = 0x0 - FF1 = 0x4000 - FFDLY = 0x4000 - FLUSHO = 0x800000 - FSOPT_ATTR_CMN_EXTENDED = 0x20 - FSOPT_NOFOLLOW = 0x1 - FSOPT_NOINMEMUPDATE = 0x2 - FSOPT_PACK_INVAL_ATTRS = 0x8 - FSOPT_REPORT_FULLSIZE = 0x4 - FSOPT_RETURN_REALDEV = 0x200 - F_ADDFILESIGS = 0x3d - F_ADDFILESIGS_FOR_DYLD_SIM = 0x53 - F_ADDFILESIGS_INFO = 0x67 - F_ADDFILESIGS_RETURN = 0x61 - F_ADDFILESUPPL = 0x68 - F_ADDSIGS = 0x3b - F_ALLOCATEALL = 0x4 - F_ALLOCATECONTIG = 0x2 - F_BARRIERFSYNC = 0x55 - F_CHECK_LV = 0x62 - F_CHKCLEAN = 0x29 - F_DUPFD = 0x0 - F_DUPFD_CLOEXEC = 0x43 - F_FINDSIGS = 0x4e - F_FLUSH_DATA = 0x28 - F_FREEZE_FS = 0x35 - F_FULLFSYNC = 0x33 - F_GETCODEDIR = 0x48 - F_GETFD = 0x1 - F_GETFL = 0x3 - F_GETLK = 0x7 - F_GETLKPID = 0x42 - F_GETNOSIGPIPE = 0x4a - F_GETOWN = 0x5 - F_GETPATH = 0x32 - F_GETPATH_MTMINFO = 0x47 - F_GETPATH_NOFIRMLINK = 0x66 - F_GETPROTECTIONCLASS = 0x3f - F_GETPROTECTIONLEVEL = 0x4d - F_GETSIGSINFO = 0x69 - F_GLOBAL_NOCACHE = 0x37 - F_LOG2PHYS = 0x31 - F_LOG2PHYS_EXT = 0x41 - F_NOCACHE = 0x30 - F_NODIRECT = 0x3e - F_OK = 0x0 - F_PATHPKG_CHECK = 0x34 - F_PEOFPOSMODE = 0x3 - F_PREALLOCATE = 0x2a - F_PUNCHHOLE = 0x63 - F_RDADVISE = 0x2c - F_RDAHEAD = 0x2d - F_RDLCK = 0x1 - F_SETBACKINGSTORE = 0x46 - F_SETFD = 0x2 - F_SETFL = 0x4 - F_SETLK = 0x8 - F_SETLKW = 0x9 - F_SETLKWTIMEOUT = 0xa - F_SETNOSIGPIPE = 0x49 - F_SETOWN = 0x6 - F_SETPROTECTIONCLASS = 0x40 - F_SETSIZE = 0x2b - F_SINGLE_WRITER = 0x4c - F_SPECULATIVE_READ = 0x65 - F_THAW_FS = 0x36 - F_TRANSCODEKEY = 0x4b - F_TRIM_ACTIVE_FILE = 0x64 - F_UNLCK = 0x2 - F_VOLPOSMODE = 0x4 - F_WRLCK = 0x3 - HUPCL = 0x4000 - HW_MACHINE = 0x1 - ICANON = 0x100 - ICMP6_FILTER = 0x12 - ICRNL = 0x100 - IEXTEN = 0x400 - IFF_ALLMULTI = 0x200 - IFF_ALTPHYS = 0x4000 - IFF_BROADCAST = 0x2 - IFF_DEBUG = 0x4 - IFF_LINK0 = 0x1000 - IFF_LINK1 = 0x2000 - IFF_LINK2 = 0x4000 - IFF_LOOPBACK = 0x8 - IFF_MULTICAST = 0x8000 - IFF_NOARP = 0x80 - IFF_NOTRAILERS = 0x20 - IFF_OACTIVE = 0x400 - IFF_POINTOPOINT = 0x10 - IFF_PROMISC = 0x100 - IFF_RUNNING = 0x40 - IFF_SIMPLEX = 0x800 - IFF_UP = 0x1 - IFNAMSIZ = 0x10 - IFT_1822 = 0x2 - IFT_6LOWPAN = 0x40 - IFT_AAL5 = 0x31 - IFT_ARCNET = 0x23 - IFT_ARCNETPLUS = 0x24 - IFT_ATM = 0x25 - IFT_BRIDGE = 0xd1 - IFT_CARP = 0xf8 - IFT_CELLULAR = 0xff - IFT_CEPT = 0x13 - IFT_DS3 = 0x1e - IFT_ENC = 0xf4 - IFT_EON = 0x19 - IFT_ETHER = 0x6 - IFT_FAITH = 0x38 - IFT_FDDI = 0xf - IFT_FRELAY = 0x20 - IFT_FRELAYDCE = 0x2c - IFT_GIF = 0x37 - IFT_HDH1822 = 0x3 - IFT_HIPPI = 0x2f - IFT_HSSI = 0x2e - IFT_HY = 0xe - IFT_IEEE1394 = 0x90 - IFT_IEEE8023ADLAG = 0x88 - IFT_ISDNBASIC = 0x14 - IFT_ISDNPRIMARY = 0x15 - IFT_ISO88022LLC = 0x29 - IFT_ISO88023 = 0x7 - IFT_ISO88024 = 0x8 - IFT_ISO88025 = 0x9 - IFT_ISO88026 = 0xa - IFT_L2VLAN = 0x87 - IFT_LAPB = 0x10 - IFT_LOCALTALK = 0x2a - IFT_LOOP = 0x18 - IFT_MIOX25 = 0x26 - IFT_MODEM = 0x30 - IFT_NSIP = 0x1b - IFT_OTHER = 0x1 - IFT_P10 = 0xc - IFT_P80 = 0xd - IFT_PARA = 0x22 - IFT_PDP = 0xff - IFT_PFLOG = 0xf5 - IFT_PFSYNC = 0xf6 - IFT_PKTAP = 0xfe - IFT_PPP = 0x17 - IFT_PROPMUX = 0x36 - IFT_PROPVIRTUAL = 0x35 - IFT_PTPSERIAL = 0x16 - IFT_RS232 = 0x21 - IFT_SDLC = 0x11 - IFT_SIP = 0x1f - IFT_SLIP = 0x1c - IFT_SMDSDXI = 0x2b - IFT_SMDSICIP = 0x34 - IFT_SONET = 0x27 - IFT_SONETPATH = 0x32 - IFT_SONETVT = 0x33 - IFT_STARLAN = 0xb - IFT_STF = 0x39 - IFT_T1 = 0x12 - IFT_ULTRA = 0x1d - IFT_V35 = 0x2d - IFT_X25 = 0x5 - IFT_X25DDN = 0x4 - IFT_X25PLE = 0x28 - IFT_XETHER = 0x1a - IGNBRK = 0x1 - IGNCR = 0x80 - IGNPAR = 0x4 - IMAXBEL = 0x2000 - INLCR = 0x40 - INPCK = 0x10 - IN_CLASSA_HOST = 0xffffff - IN_CLASSA_MAX = 0x80 - IN_CLASSA_NET = 0xff000000 - IN_CLASSA_NSHIFT = 0x18 - IN_CLASSB_HOST = 0xffff - IN_CLASSB_MAX = 0x10000 - IN_CLASSB_NET = 0xffff0000 - IN_CLASSB_NSHIFT = 0x10 - IN_CLASSC_HOST = 0xff - IN_CLASSC_NET = 0xffffff00 - IN_CLASSC_NSHIFT = 0x8 - IN_CLASSD_HOST = 0xfffffff - IN_CLASSD_NET = 0xf0000000 - IN_CLASSD_NSHIFT = 0x1c - IN_LINKLOCALNETNUM = 0xa9fe0000 - IN_LOOPBACKNET = 0x7f - IPPROTO_3PC = 0x22 - IPPROTO_ADFS = 0x44 - IPPROTO_AH = 0x33 - IPPROTO_AHIP = 0x3d - IPPROTO_APES = 0x63 - IPPROTO_ARGUS = 0xd - IPPROTO_AX25 = 0x5d - IPPROTO_BHA = 0x31 - IPPROTO_BLT = 0x1e - IPPROTO_BRSATMON = 0x4c - IPPROTO_CFTP = 0x3e - IPPROTO_CHAOS = 0x10 - IPPROTO_CMTP = 0x26 - IPPROTO_CPHB = 0x49 - IPPROTO_CPNX = 0x48 - IPPROTO_DDP = 0x25 - IPPROTO_DGP = 0x56 - IPPROTO_DIVERT = 0xfe - IPPROTO_DONE = 0x101 - IPPROTO_DSTOPTS = 0x3c - IPPROTO_EGP = 0x8 - IPPROTO_EMCON = 0xe - IPPROTO_ENCAP = 0x62 - IPPROTO_EON = 0x50 - IPPROTO_ESP = 0x32 - IPPROTO_ETHERIP = 0x61 - IPPROTO_FRAGMENT = 0x2c - IPPROTO_GGP = 0x3 - IPPROTO_GMTP = 0x64 - IPPROTO_GRE = 0x2f - IPPROTO_HELLO = 0x3f - IPPROTO_HMP = 0x14 - IPPROTO_HOPOPTS = 0x0 - IPPROTO_ICMP = 0x1 - IPPROTO_ICMPV6 = 0x3a - IPPROTO_IDP = 0x16 - IPPROTO_IDPR = 0x23 - IPPROTO_IDRP = 0x2d - IPPROTO_IGMP = 0x2 - IPPROTO_IGP = 0x55 - IPPROTO_IGRP = 0x58 - IPPROTO_IL = 0x28 - IPPROTO_INLSP = 0x34 - IPPROTO_INP = 0x20 - IPPROTO_IP = 0x0 - IPPROTO_IPCOMP = 0x6c - IPPROTO_IPCV = 0x47 - IPPROTO_IPEIP = 0x5e - IPPROTO_IPIP = 0x4 - IPPROTO_IPPC = 0x43 - IPPROTO_IPV4 = 0x4 - IPPROTO_IPV6 = 0x29 - IPPROTO_IRTP = 0x1c - IPPROTO_KRYPTOLAN = 0x41 - IPPROTO_LARP = 0x5b - IPPROTO_LEAF1 = 0x19 - IPPROTO_LEAF2 = 0x1a - IPPROTO_MAX = 0x100 - IPPROTO_MAXID = 0x34 - IPPROTO_MEAS = 0x13 - IPPROTO_MHRP = 0x30 - IPPROTO_MICP = 0x5f - IPPROTO_MTP = 0x5c - IPPROTO_MUX = 0x12 - IPPROTO_ND = 0x4d - IPPROTO_NHRP = 0x36 - IPPROTO_NONE = 0x3b - IPPROTO_NSP = 0x1f - IPPROTO_NVPII = 0xb - IPPROTO_OSPFIGP = 0x59 - IPPROTO_PGM = 0x71 - IPPROTO_PIGP = 0x9 - IPPROTO_PIM = 0x67 - IPPROTO_PRM = 0x15 - IPPROTO_PUP = 0xc - IPPROTO_PVP = 0x4b - IPPROTO_RAW = 0xff - IPPROTO_RCCMON = 0xa - IPPROTO_RDP = 0x1b - IPPROTO_ROUTING = 0x2b - IPPROTO_RSVP = 0x2e - IPPROTO_RVD = 0x42 - IPPROTO_SATEXPAK = 0x40 - IPPROTO_SATMON = 0x45 - IPPROTO_SCCSP = 0x60 - IPPROTO_SCTP = 0x84 - IPPROTO_SDRP = 0x2a - IPPROTO_SEP = 0x21 - IPPROTO_SRPC = 0x5a - IPPROTO_ST = 0x7 - IPPROTO_SVMTP = 0x52 - IPPROTO_SWIPE = 0x35 - IPPROTO_TCF = 0x57 - IPPROTO_TCP = 0x6 - IPPROTO_TP = 0x1d - IPPROTO_TPXX = 0x27 - IPPROTO_TRUNK1 = 0x17 - IPPROTO_TRUNK2 = 0x18 - IPPROTO_TTP = 0x54 - IPPROTO_UDP = 0x11 - IPPROTO_VINES = 0x53 - IPPROTO_VISA = 0x46 - IPPROTO_VMTP = 0x51 - IPPROTO_WBEXPAK = 0x4f - IPPROTO_WBMON = 0x4e - IPPROTO_WSN = 0x4a - IPPROTO_XNET = 0xf - IPPROTO_XTP = 0x24 - IPV6_2292DSTOPTS = 0x17 - IPV6_2292HOPLIMIT = 0x14 - IPV6_2292HOPOPTS = 0x16 - IPV6_2292NEXTHOP = 0x15 - IPV6_2292PKTINFO = 0x13 - IPV6_2292PKTOPTIONS = 0x19 - IPV6_2292RTHDR = 0x18 - IPV6_3542DSTOPTS = 0x32 - IPV6_3542HOPLIMIT = 0x2f - IPV6_3542HOPOPTS = 0x31 - IPV6_3542NEXTHOP = 0x30 - IPV6_3542PKTINFO = 0x2e - IPV6_3542RTHDR = 0x33 - IPV6_ADDR_MC_FLAGS_PREFIX = 0x20 - IPV6_ADDR_MC_FLAGS_TRANSIENT = 0x10 - IPV6_ADDR_MC_FLAGS_UNICAST_BASED = 0x30 - IPV6_AUTOFLOWLABEL = 0x3b - IPV6_BINDV6ONLY = 0x1b - IPV6_BOUND_IF = 0x7d - IPV6_CHECKSUM = 0x1a - IPV6_DEFAULT_MULTICAST_HOPS = 0x1 - IPV6_DEFAULT_MULTICAST_LOOP = 0x1 - IPV6_DEFHLIM = 0x40 - IPV6_DONTFRAG = 0x3e - IPV6_DSTOPTS = 0x32 - IPV6_FAITH = 0x1d - IPV6_FLOWINFO_MASK = 0xffffff0f - IPV6_FLOWLABEL_MASK = 0xffff0f00 - IPV6_FLOW_ECN_MASK = 0x3000 - IPV6_FRAGTTL = 0x3c - IPV6_FW_ADD = 0x1e - IPV6_FW_DEL = 0x1f - IPV6_FW_FLUSH = 0x20 - IPV6_FW_GET = 0x22 - IPV6_FW_ZERO = 0x21 - IPV6_HLIMDEC = 0x1 - IPV6_HOPLIMIT = 0x2f - IPV6_HOPOPTS = 0x31 - IPV6_IPSEC_POLICY = 0x1c - IPV6_JOIN_GROUP = 0xc - IPV6_LEAVE_GROUP = 0xd - IPV6_MAXHLIM = 0xff - IPV6_MAXOPTHDR = 0x800 - IPV6_MAXPACKET = 0xffff - IPV6_MAX_GROUP_SRC_FILTER = 0x200 - IPV6_MAX_MEMBERSHIPS = 0xfff - IPV6_MAX_SOCK_SRC_FILTER = 0x80 - IPV6_MIN_MEMBERSHIPS = 0x1f - IPV6_MMTU = 0x500 - IPV6_MSFILTER = 0x4a - IPV6_MULTICAST_HOPS = 0xa - IPV6_MULTICAST_IF = 0x9 - IPV6_MULTICAST_LOOP = 0xb - IPV6_NEXTHOP = 0x30 - IPV6_PATHMTU = 0x2c - IPV6_PKTINFO = 0x2e - IPV6_PORTRANGE = 0xe - IPV6_PORTRANGE_DEFAULT = 0x0 - IPV6_PORTRANGE_HIGH = 0x1 - IPV6_PORTRANGE_LOW = 0x2 - IPV6_PREFER_TEMPADDR = 0x3f - IPV6_RECVDSTOPTS = 0x28 - IPV6_RECVHOPLIMIT = 0x25 - IPV6_RECVHOPOPTS = 0x27 - IPV6_RECVPATHMTU = 0x2b - IPV6_RECVPKTINFO = 0x3d - IPV6_RECVRTHDR = 0x26 - IPV6_RECVTCLASS = 0x23 - IPV6_RTHDR = 0x33 - IPV6_RTHDRDSTOPTS = 0x39 - IPV6_RTHDR_LOOSE = 0x0 - IPV6_RTHDR_STRICT = 0x1 - IPV6_RTHDR_TYPE_0 = 0x0 - IPV6_SOCKOPT_RESERVED1 = 0x3 - IPV6_TCLASS = 0x24 - IPV6_UNICAST_HOPS = 0x4 - IPV6_USE_MIN_MTU = 0x2a - IPV6_V6ONLY = 0x1b - IPV6_VERSION = 0x60 - IPV6_VERSION_MASK = 0xf0 - IP_ADD_MEMBERSHIP = 0xc - IP_ADD_SOURCE_MEMBERSHIP = 0x46 - IP_BLOCK_SOURCE = 0x48 - IP_BOUND_IF = 0x19 - IP_DEFAULT_MULTICAST_LOOP = 0x1 - IP_DEFAULT_MULTICAST_TTL = 0x1 - IP_DF = 0x4000 - IP_DONTFRAG = 0x1c - IP_DROP_MEMBERSHIP = 0xd - IP_DROP_SOURCE_MEMBERSHIP = 0x47 - IP_DUMMYNET_CONFIGURE = 0x3c - IP_DUMMYNET_DEL = 0x3d - IP_DUMMYNET_FLUSH = 0x3e - IP_DUMMYNET_GET = 0x40 - IP_FAITH = 0x16 - IP_FW_ADD = 0x28 - IP_FW_DEL = 0x29 - IP_FW_FLUSH = 0x2a - IP_FW_GET = 0x2c - IP_FW_RESETLOG = 0x2d - IP_FW_ZERO = 0x2b - IP_HDRINCL = 0x2 - IP_IPSEC_POLICY = 0x15 - IP_MAXPACKET = 0xffff - IP_MAX_GROUP_SRC_FILTER = 0x200 - IP_MAX_MEMBERSHIPS = 0xfff - IP_MAX_SOCK_MUTE_FILTER = 0x80 - IP_MAX_SOCK_SRC_FILTER = 0x80 - IP_MF = 0x2000 - IP_MIN_MEMBERSHIPS = 0x1f - IP_MSFILTER = 0x4a - IP_MSS = 0x240 - IP_MULTICAST_IF = 0x9 - IP_MULTICAST_IFINDEX = 0x42 - IP_MULTICAST_LOOP = 0xb - IP_MULTICAST_TTL = 0xa - IP_MULTICAST_VIF = 0xe - IP_NAT__XXX = 0x37 - IP_OFFMASK = 0x1fff - IP_OLD_FW_ADD = 0x32 - IP_OLD_FW_DEL = 0x33 - IP_OLD_FW_FLUSH = 0x34 - IP_OLD_FW_GET = 0x36 - IP_OLD_FW_RESETLOG = 0x38 - IP_OLD_FW_ZERO = 0x35 - IP_OPTIONS = 0x1 - IP_PKTINFO = 0x1a - IP_PORTRANGE = 0x13 - IP_PORTRANGE_DEFAULT = 0x0 - IP_PORTRANGE_HIGH = 0x1 - IP_PORTRANGE_LOW = 0x2 - IP_RECVDSTADDR = 0x7 - IP_RECVIF = 0x14 - IP_RECVOPTS = 0x5 - IP_RECVPKTINFO = 0x1a - IP_RECVRETOPTS = 0x6 - IP_RECVTOS = 0x1b - IP_RECVTTL = 0x18 - IP_RETOPTS = 0x8 - IP_RF = 0x8000 - IP_RSVP_OFF = 0x10 - IP_RSVP_ON = 0xf - IP_RSVP_VIF_OFF = 0x12 - IP_RSVP_VIF_ON = 0x11 - IP_STRIPHDR = 0x17 - IP_TOS = 0x3 - IP_TRAFFIC_MGT_BACKGROUND = 0x41 - IP_TTL = 0x4 - IP_UNBLOCK_SOURCE = 0x49 - ISIG = 0x80 - ISTRIP = 0x20 - IUTF8 = 0x4000 - IXANY = 0x800 - IXOFF = 0x400 - IXON = 0x200 - KERN_HOSTNAME = 0xa - KERN_OSRELEASE = 0x2 - KERN_OSTYPE = 0x1 - KERN_VERSION = 0x4 - LOCAL_PEERCRED = 0x1 - LOCAL_PEEREPID = 0x3 - LOCAL_PEEREUUID = 0x5 - LOCAL_PEERPID = 0x2 - LOCAL_PEERTOKEN = 0x6 - LOCAL_PEERUUID = 0x4 - LOCK_EX = 0x2 - LOCK_NB = 0x4 - LOCK_SH = 0x1 - LOCK_UN = 0x8 - MADV_CAN_REUSE = 0x9 - MADV_DONTNEED = 0x4 - MADV_FREE = 0x5 - MADV_FREE_REUSABLE = 0x7 - MADV_FREE_REUSE = 0x8 - MADV_NORMAL = 0x0 - MADV_PAGEOUT = 0xa - MADV_RANDOM = 0x1 - MADV_SEQUENTIAL = 0x2 - MADV_WILLNEED = 0x3 - MADV_ZERO_WIRED_PAGES = 0x6 - MAP_32BIT = 0x8000 - MAP_ANON = 0x1000 - MAP_ANONYMOUS = 0x1000 - MAP_COPY = 0x2 - MAP_FILE = 0x0 - MAP_FIXED = 0x10 - MAP_HASSEMAPHORE = 0x200 - MAP_JIT = 0x800 - MAP_NOCACHE = 0x400 - MAP_NOEXTEND = 0x100 - MAP_NORESERVE = 0x40 - MAP_PRIVATE = 0x2 - MAP_RENAME = 0x20 - MAP_RESERVED0080 = 0x80 - MAP_RESILIENT_CODESIGN = 0x2000 - MAP_RESILIENT_MEDIA = 0x4000 - MAP_SHARED = 0x1 - MAP_TRANSLATED_ALLOW_EXECUTE = 0x20000 - MAP_UNIX03 = 0x40000 - MCAST_BLOCK_SOURCE = 0x54 - MCAST_EXCLUDE = 0x2 - MCAST_INCLUDE = 0x1 - MCAST_JOIN_GROUP = 0x50 - MCAST_JOIN_SOURCE_GROUP = 0x52 - MCAST_LEAVE_GROUP = 0x51 - MCAST_LEAVE_SOURCE_GROUP = 0x53 - MCAST_UNBLOCK_SOURCE = 0x55 - MCAST_UNDEFINED = 0x0 - MCL_CURRENT = 0x1 - MCL_FUTURE = 0x2 - MNT_ASYNC = 0x40 - MNT_AUTOMOUNTED = 0x400000 - MNT_CMDFLAGS = 0xf0000 - MNT_CPROTECT = 0x80 - MNT_DEFWRITE = 0x2000000 - MNT_DONTBROWSE = 0x100000 - MNT_DOVOLFS = 0x8000 - MNT_DWAIT = 0x4 - MNT_EXPORTED = 0x100 - MNT_EXT_ROOT_DATA_VOL = 0x1 - MNT_FORCE = 0x80000 - MNT_IGNORE_OWNERSHIP = 0x200000 - MNT_JOURNALED = 0x800000 - MNT_LOCAL = 0x1000 - MNT_MULTILABEL = 0x4000000 - MNT_NOATIME = 0x10000000 - MNT_NOBLOCK = 0x20000 - MNT_NODEV = 0x10 - MNT_NOEXEC = 0x4 - MNT_NOSUID = 0x8 - MNT_NOUSERXATTR = 0x1000000 - MNT_NOWAIT = 0x2 - MNT_QUARANTINE = 0x400 - MNT_QUOTA = 0x2000 - MNT_RDONLY = 0x1 - MNT_RELOAD = 0x40000 - MNT_REMOVABLE = 0x200 - MNT_ROOTFS = 0x4000 - MNT_SNAPSHOT = 0x40000000 - MNT_STRICTATIME = 0x80000000 - MNT_SYNCHRONOUS = 0x2 - MNT_UNION = 0x20 - MNT_UNKNOWNPERMISSIONS = 0x200000 - MNT_UPDATE = 0x10000 - MNT_VISFLAGMASK = 0xd7f0f7ff - MNT_WAIT = 0x1 - MSG_CTRUNC = 0x20 - MSG_DONTROUTE = 0x4 - MSG_DONTWAIT = 0x80 - MSG_EOF = 0x100 - MSG_EOR = 0x8 - MSG_FLUSH = 0x400 - MSG_HAVEMORE = 0x2000 - MSG_HOLD = 0x800 - MSG_NEEDSA = 0x10000 - MSG_NOSIGNAL = 0x80000 - MSG_OOB = 0x1 - MSG_PEEK = 0x2 - MSG_RCVMORE = 0x4000 - MSG_SEND = 0x1000 - MSG_TRUNC = 0x10 - MSG_WAITALL = 0x40 - MSG_WAITSTREAM = 0x200 - MS_ASYNC = 0x1 - MS_DEACTIVATE = 0x8 - MS_INVALIDATE = 0x2 - MS_KILLPAGES = 0x4 - MS_SYNC = 0x10 - NAME_MAX = 0xff - NET_RT_DUMP = 0x1 - NET_RT_DUMP2 = 0x7 - NET_RT_FLAGS = 0x2 - NET_RT_FLAGS_PRIV = 0xa - NET_RT_IFLIST = 0x3 - NET_RT_IFLIST2 = 0x6 - NET_RT_MAXID = 0xb - NET_RT_STAT = 0x4 - NET_RT_TRASH = 0x5 - NFDBITS = 0x20 - NL0 = 0x0 - NL1 = 0x100 - NL2 = 0x200 - NL3 = 0x300 - NLDLY = 0x300 - NOFLSH = 0x80000000 - NOKERNINFO = 0x2000000 - NOTE_ABSOLUTE = 0x8 - NOTE_ATTRIB = 0x8 - NOTE_BACKGROUND = 0x40 - NOTE_CHILD = 0x4 - NOTE_CRITICAL = 0x20 - NOTE_DELETE = 0x1 - NOTE_EXEC = 0x20000000 - NOTE_EXIT = 0x80000000 - NOTE_EXITSTATUS = 0x4000000 - NOTE_EXIT_CSERROR = 0x40000 - NOTE_EXIT_DECRYPTFAIL = 0x10000 - NOTE_EXIT_DETAIL = 0x2000000 - NOTE_EXIT_DETAIL_MASK = 0x70000 - NOTE_EXIT_MEMORY = 0x20000 - NOTE_EXIT_REPARENTED = 0x80000 - NOTE_EXTEND = 0x4 - NOTE_FFAND = 0x40000000 - NOTE_FFCOPY = 0xc0000000 - NOTE_FFCTRLMASK = 0xc0000000 - NOTE_FFLAGSMASK = 0xffffff - NOTE_FFNOP = 0x0 - NOTE_FFOR = 0x80000000 - NOTE_FORK = 0x40000000 - NOTE_FUNLOCK = 0x100 - NOTE_LEEWAY = 0x10 - NOTE_LINK = 0x10 - NOTE_LOWAT = 0x1 - NOTE_MACHTIME = 0x100 - NOTE_MACH_CONTINUOUS_TIME = 0x80 - NOTE_NONE = 0x80 - NOTE_NSECONDS = 0x4 - NOTE_OOB = 0x2 - NOTE_PCTRLMASK = -0x100000 - NOTE_PDATAMASK = 0xfffff - NOTE_REAP = 0x10000000 - NOTE_RENAME = 0x20 - NOTE_REVOKE = 0x40 - NOTE_SECONDS = 0x1 - NOTE_SIGNAL = 0x8000000 - NOTE_TRACK = 0x1 - NOTE_TRACKERR = 0x2 - NOTE_TRIGGER = 0x1000000 - NOTE_USECONDS = 0x2 - NOTE_VM_ERROR = 0x10000000 - NOTE_VM_PRESSURE = 0x80000000 - NOTE_VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000 - NOTE_VM_PRESSURE_TERMINATE = 0x40000000 - NOTE_WRITE = 0x2 - OCRNL = 0x10 - OFDEL = 0x20000 - OFILL = 0x80 - ONLCR = 0x2 - ONLRET = 0x40 - ONOCR = 0x20 - ONOEOT = 0x8 - OPOST = 0x1 - OXTABS = 0x4 - O_ACCMODE = 0x3 - O_ALERT = 0x20000000 - O_APPEND = 0x8 - O_ASYNC = 0x40 - O_CLOEXEC = 0x1000000 - O_CREAT = 0x200 - O_DIRECTORY = 0x100000 - O_DP_GETRAWENCRYPTED = 0x1 - O_DP_GETRAWUNENCRYPTED = 0x2 - O_DSYNC = 0x400000 - O_EVTONLY = 0x8000 - O_EXCL = 0x800 - O_EXLOCK = 0x20 - O_FSYNC = 0x80 - O_NDELAY = 0x4 - O_NOCTTY = 0x20000 - O_NOFOLLOW = 0x100 - O_NOFOLLOW_ANY = 0x20000000 - O_NONBLOCK = 0x4 - O_POPUP = 0x80000000 - O_RDONLY = 0x0 - O_RDWR = 0x2 - O_SHLOCK = 0x10 - O_SYMLINK = 0x200000 - O_SYNC = 0x80 - O_TRUNC = 0x400 - O_WRONLY = 0x1 - PARENB = 0x1000 - PARMRK = 0x8 - PARODD = 0x2000 - PENDIN = 0x20000000 - PRIO_PGRP = 0x1 - PRIO_PROCESS = 0x0 - PRIO_USER = 0x2 - PROT_EXEC = 0x4 - PROT_NONE = 0x0 - PROT_READ = 0x1 - PROT_WRITE = 0x2 - PT_ATTACH = 0xa - PT_ATTACHEXC = 0xe - PT_CONTINUE = 0x7 - PT_DENY_ATTACH = 0x1f - PT_DETACH = 0xb - PT_FIRSTMACH = 0x20 - PT_FORCEQUOTA = 0x1e - PT_KILL = 0x8 - PT_READ_D = 0x2 - PT_READ_I = 0x1 - PT_READ_U = 0x3 - PT_SIGEXC = 0xc - PT_STEP = 0x9 - PT_THUPDATE = 0xd - PT_TRACE_ME = 0x0 - PT_WRITE_D = 0x5 - PT_WRITE_I = 0x4 - PT_WRITE_U = 0x6 - RLIMIT_AS = 0x5 - RLIMIT_CORE = 0x4 - RLIMIT_CPU = 0x0 - RLIMIT_CPU_USAGE_MONITOR = 0x2 - RLIMIT_DATA = 0x2 - RLIMIT_FSIZE = 0x1 - RLIMIT_MEMLOCK = 0x6 - RLIMIT_NOFILE = 0x8 - RLIMIT_NPROC = 0x7 - RLIMIT_RSS = 0x5 - RLIMIT_STACK = 0x3 - RLIM_INFINITY = 0x7fffffffffffffff - RTAX_AUTHOR = 0x6 - RTAX_BRD = 0x7 - RTAX_DST = 0x0 - RTAX_GATEWAY = 0x1 - RTAX_GENMASK = 0x3 - RTAX_IFA = 0x5 - RTAX_IFP = 0x4 - RTAX_MAX = 0x8 - RTAX_NETMASK = 0x2 - RTA_AUTHOR = 0x40 - RTA_BRD = 0x80 - RTA_DST = 0x1 - RTA_GATEWAY = 0x2 - RTA_GENMASK = 0x8 - RTA_IFA = 0x20 - RTA_IFP = 0x10 - RTA_NETMASK = 0x4 - RTF_BLACKHOLE = 0x1000 - RTF_BROADCAST = 0x400000 - RTF_CLONING = 0x100 - RTF_CONDEMNED = 0x2000000 - RTF_DEAD = 0x20000000 - RTF_DELCLONE = 0x80 - RTF_DONE = 0x40 - RTF_DYNAMIC = 0x10 - RTF_GATEWAY = 0x2 - RTF_GLOBAL = 0x40000000 - RTF_HOST = 0x4 - RTF_IFREF = 0x4000000 - RTF_IFSCOPE = 0x1000000 - RTF_LLDATA = 0x400 - RTF_LLINFO = 0x400 - RTF_LOCAL = 0x200000 - RTF_MODIFIED = 0x20 - RTF_MULTICAST = 0x800000 - RTF_NOIFREF = 0x2000 - RTF_PINNED = 0x100000 - RTF_PRCLONING = 0x10000 - RTF_PROTO1 = 0x8000 - RTF_PROTO2 = 0x4000 - RTF_PROTO3 = 0x40000 - RTF_PROXY = 0x8000000 - RTF_REJECT = 0x8 - RTF_ROUTER = 0x10000000 - RTF_STATIC = 0x800 - RTF_UP = 0x1 - RTF_WASCLONED = 0x20000 - RTF_XRESOLVE = 0x200 - RTM_ADD = 0x1 - RTM_CHANGE = 0x3 - RTM_DELADDR = 0xd - RTM_DELETE = 0x2 - RTM_DELMADDR = 0x10 - RTM_GET = 0x4 - RTM_GET2 = 0x14 - RTM_IFINFO = 0xe - RTM_IFINFO2 = 0x12 - RTM_LOCK = 0x8 - RTM_LOSING = 0x5 - RTM_MISS = 0x7 - RTM_NEWADDR = 0xc - RTM_NEWMADDR = 0xf - RTM_NEWMADDR2 = 0x13 - RTM_OLDADD = 0x9 - RTM_OLDDEL = 0xa - RTM_REDIRECT = 0x6 - RTM_RESOLVE = 0xb - RTM_RTTUNIT = 0xf4240 - RTM_VERSION = 0x5 - RTV_EXPIRE = 0x4 - RTV_HOPCOUNT = 0x2 - RTV_MTU = 0x1 - RTV_RPIPE = 0x8 - RTV_RTT = 0x40 - RTV_RTTVAR = 0x80 - RTV_SPIPE = 0x10 - RTV_SSTHRESH = 0x20 - RUSAGE_CHILDREN = -0x1 - RUSAGE_SELF = 0x0 - SCM_CREDS = 0x3 - SCM_RIGHTS = 0x1 - SCM_TIMESTAMP = 0x2 - SCM_TIMESTAMP_MONOTONIC = 0x4 - SEEK_CUR = 0x1 - SEEK_DATA = 0x4 - SEEK_END = 0x2 - SEEK_HOLE = 0x3 - SEEK_SET = 0x0 - SHUT_RD = 0x0 - SHUT_RDWR = 0x2 - SHUT_WR = 0x1 - SIOCADDMULTI = 0x80206931 - SIOCAIFADDR = 0x8040691a - SIOCARPIPLL = 0xc0206928 - SIOCATMARK = 0x40047307 - SIOCAUTOADDR = 0xc0206926 - SIOCAUTONETMASK = 0x80206927 - SIOCDELMULTI = 0x80206932 - SIOCDIFADDR = 0x80206919 - SIOCDIFPHYADDR = 0x80206941 - SIOCGDRVSPEC = 0xc028697b - SIOCGETVLAN = 0xc020697f - SIOCGHIWAT = 0x40047301 - SIOCGIF6LOWPAN = 0xc02069c5 - SIOCGIFADDR = 0xc0206921 - SIOCGIFALTMTU = 0xc0206948 - SIOCGIFASYNCMAP = 0xc020697c - SIOCGIFBOND = 0xc0206947 - SIOCGIFBRDADDR = 0xc0206923 - SIOCGIFCAP = 0xc020695b - SIOCGIFCONF = 0xc00c6924 - SIOCGIFDEVMTU = 0xc0206944 - SIOCGIFDSTADDR = 0xc0206922 - SIOCGIFFLAGS = 0xc0206911 - SIOCGIFFUNCTIONALTYPE = 0xc02069ad - SIOCGIFGENERIC = 0xc020693a - SIOCGIFKPI = 0xc0206987 - SIOCGIFMAC = 0xc0206982 - SIOCGIFMEDIA = 0xc02c6938 - SIOCGIFMETRIC = 0xc0206917 - SIOCGIFMTU = 0xc0206933 - SIOCGIFNETMASK = 0xc0206925 - SIOCGIFPDSTADDR = 0xc0206940 - SIOCGIFPHYS = 0xc0206935 - SIOCGIFPSRCADDR = 0xc020693f - SIOCGIFSTATUS = 0xc331693d - SIOCGIFVLAN = 0xc020697f - SIOCGIFWAKEFLAGS = 0xc0206988 - SIOCGIFXMEDIA = 0xc02c6948 - SIOCGLOWAT = 0x40047303 - SIOCGPGRP = 0x40047309 - SIOCIFCREATE = 0xc0206978 - SIOCIFCREATE2 = 0xc020697a - SIOCIFDESTROY = 0x80206979 - SIOCIFGCLONERS = 0xc0106981 - SIOCRSLVMULTI = 0xc010693b - SIOCSDRVSPEC = 0x8028697b - SIOCSETVLAN = 0x8020697e - SIOCSHIWAT = 0x80047300 - SIOCSIF6LOWPAN = 0x802069c4 - SIOCSIFADDR = 0x8020690c - SIOCSIFALTMTU = 0x80206945 - SIOCSIFASYNCMAP = 0x8020697d - SIOCSIFBOND = 0x80206946 - SIOCSIFBRDADDR = 0x80206913 - SIOCSIFCAP = 0x8020695a - SIOCSIFDSTADDR = 0x8020690e - SIOCSIFFLAGS = 0x80206910 - SIOCSIFGENERIC = 0x80206939 - SIOCSIFKPI = 0x80206986 - SIOCSIFLLADDR = 0x8020693c - SIOCSIFMAC = 0x80206983 - SIOCSIFMEDIA = 0xc0206937 - SIOCSIFMETRIC = 0x80206918 - SIOCSIFMTU = 0x80206934 - SIOCSIFNETMASK = 0x80206916 - SIOCSIFPHYADDR = 0x8040693e - SIOCSIFPHYS = 0x80206936 - SIOCSIFVLAN = 0x8020697e - SIOCSLOWAT = 0x80047302 - SIOCSPGRP = 0x80047308 - SOCK_DGRAM = 0x2 - SOCK_MAXADDRLEN = 0xff - SOCK_RAW = 0x3 - SOCK_RDM = 0x4 - SOCK_SEQPACKET = 0x5 - SOCK_STREAM = 0x1 - SOL_LOCAL = 0x0 - SOL_SOCKET = 0xffff - SOMAXCONN = 0x80 - SO_ACCEPTCONN = 0x2 - SO_BROADCAST = 0x20 - SO_DEBUG = 0x1 - SO_DONTROUTE = 0x10 - SO_DONTTRUNC = 0x2000 - SO_ERROR = 0x1007 - SO_KEEPALIVE = 0x8 - SO_LABEL = 0x1010 - SO_LINGER = 0x80 - SO_LINGER_SEC = 0x1080 - SO_NETSVC_MARKING_LEVEL = 0x1119 - SO_NET_SERVICE_TYPE = 0x1116 - SO_NKE = 0x1021 - SO_NOADDRERR = 0x1023 - SO_NOSIGPIPE = 0x1022 - SO_NOTIFYCONFLICT = 0x1026 - SO_NP_EXTENSIONS = 0x1083 - SO_NREAD = 0x1020 - SO_NUMRCVPKT = 0x1112 - SO_NWRITE = 0x1024 - SO_OOBINLINE = 0x100 - SO_PEERLABEL = 0x1011 - SO_RANDOMPORT = 0x1082 - SO_RCVBUF = 0x1002 - SO_RCVLOWAT = 0x1004 - SO_RCVTIMEO = 0x1006 - SO_REUSEADDR = 0x4 - SO_REUSEPORT = 0x200 - SO_REUSESHAREUID = 0x1025 - SO_SNDBUF = 0x1001 - SO_SNDLOWAT = 0x1003 - SO_SNDTIMEO = 0x1005 - SO_TIMESTAMP = 0x400 - SO_TIMESTAMP_MONOTONIC = 0x800 - SO_TYPE = 0x1008 - SO_UPCALLCLOSEWAIT = 0x1027 - SO_USELOOPBACK = 0x40 - SO_WANTMORE = 0x4000 - SO_WANTOOBFLAG = 0x8000 - S_IEXEC = 0x40 - S_IFBLK = 0x6000 - S_IFCHR = 0x2000 - S_IFDIR = 0x4000 - S_IFIFO = 0x1000 - S_IFLNK = 0xa000 - S_IFMT = 0xf000 - S_IFREG = 0x8000 - S_IFSOCK = 0xc000 - S_IFWHT = 0xe000 - S_IREAD = 0x100 - S_IRGRP = 0x20 - S_IROTH = 0x4 - S_IRUSR = 0x100 - S_IRWXG = 0x38 - S_IRWXO = 0x7 - S_IRWXU = 0x1c0 - S_ISGID = 0x400 - S_ISTXT = 0x200 - S_ISUID = 0x800 - S_ISVTX = 0x200 - S_IWGRP = 0x10 - S_IWOTH = 0x2 - S_IWRITE = 0x80 - S_IWUSR = 0x80 - S_IXGRP = 0x8 - S_IXOTH = 0x1 - S_IXUSR = 0x40 - TAB0 = 0x0 - TAB1 = 0x400 - TAB2 = 0x800 - TAB3 = 0x4 - TABDLY = 0xc04 - TCIFLUSH = 0x1 - TCIOFF = 0x3 - TCIOFLUSH = 0x3 - TCION = 0x4 - TCOFLUSH = 0x2 - TCOOFF = 0x1 - TCOON = 0x2 - TCP_CONNECTIONTIMEOUT = 0x20 - TCP_CONNECTION_INFO = 0x106 - TCP_ENABLE_ECN = 0x104 - TCP_FASTOPEN = 0x105 - TCP_KEEPALIVE = 0x10 - TCP_KEEPCNT = 0x102 - TCP_KEEPINTVL = 0x101 - TCP_MAXHLEN = 0x3c - TCP_MAXOLEN = 0x28 - TCP_MAXSEG = 0x2 - TCP_MAXWIN = 0xffff - TCP_MAX_SACK = 0x4 - TCP_MAX_WINSHIFT = 0xe - TCP_MINMSS = 0xd8 - TCP_MSS = 0x200 - TCP_NODELAY = 0x1 - TCP_NOOPT = 0x8 - TCP_NOPUSH = 0x4 - TCP_NOTSENT_LOWAT = 0x201 - TCP_RXT_CONNDROPTIME = 0x80 - TCP_RXT_FINDROP = 0x100 - TCP_SENDMOREACKS = 0x103 - TCSAFLUSH = 0x2 - TIOCCBRK = 0x2000747a - TIOCCDTR = 0x20007478 - TIOCCONS = 0x80047462 - TIOCDCDTIMESTAMP = 0x40107458 - TIOCDRAIN = 0x2000745e - TIOCDSIMICROCODE = 0x20007455 - TIOCEXCL = 0x2000740d - TIOCEXT = 0x80047460 - TIOCFLUSH = 0x80047410 - TIOCGDRAINWAIT = 0x40047456 - TIOCGETA = 0x40487413 - TIOCGETD = 0x4004741a - TIOCGPGRP = 0x40047477 - TIOCGWINSZ = 0x40087468 - TIOCIXOFF = 0x20007480 - TIOCIXON = 0x20007481 - TIOCMBIC = 0x8004746b - TIOCMBIS = 0x8004746c - TIOCMGDTRWAIT = 0x4004745a - TIOCMGET = 0x4004746a - TIOCMODG = 0x40047403 - TIOCMODS = 0x80047404 - TIOCMSDTRWAIT = 0x8004745b - TIOCMSET = 0x8004746d - TIOCM_CAR = 0x40 - TIOCM_CD = 0x40 - TIOCM_CTS = 0x20 - TIOCM_DSR = 0x100 - TIOCM_DTR = 0x2 - TIOCM_LE = 0x1 - TIOCM_RI = 0x80 - TIOCM_RNG = 0x80 - TIOCM_RTS = 0x4 - TIOCM_SR = 0x10 - TIOCM_ST = 0x8 - TIOCNOTTY = 0x20007471 - TIOCNXCL = 0x2000740e - TIOCOUTQ = 0x40047473 - TIOCPKT = 0x80047470 - TIOCPKT_DATA = 0x0 - TIOCPKT_DOSTOP = 0x20 - TIOCPKT_FLUSHREAD = 0x1 - TIOCPKT_FLUSHWRITE = 0x2 - TIOCPKT_IOCTL = 0x40 - TIOCPKT_NOSTOP = 0x10 - TIOCPKT_START = 0x8 - TIOCPKT_STOP = 0x4 - TIOCPTYGNAME = 0x40807453 - TIOCPTYGRANT = 0x20007454 - TIOCPTYUNLK = 0x20007452 - TIOCREMOTE = 0x80047469 - TIOCSBRK = 0x2000747b - TIOCSCONS = 0x20007463 - TIOCSCTTY = 0x20007461 - TIOCSDRAINWAIT = 0x80047457 - TIOCSDTR = 0x20007479 - TIOCSETA = 0x80487414 - TIOCSETAF = 0x80487416 - TIOCSETAW = 0x80487415 - TIOCSETD = 0x8004741b - TIOCSIG = 0x2000745f - TIOCSPGRP = 0x80047476 - TIOCSTART = 0x2000746e - TIOCSTAT = 0x20007465 - TIOCSTI = 0x80017472 - TIOCSTOP = 0x2000746f - TIOCSWINSZ = 0x80087467 - TIOCTIMESTAMP = 0x40107459 - TIOCUCNTL = 0x80047466 - TOSTOP = 0x400000 - VDISCARD = 0xf - VDSUSP = 0xb - VEOF = 0x0 - VEOL = 0x1 - VEOL2 = 0x2 - VERASE = 0x3 - VINTR = 0x8 - VKILL = 0x5 - VLNEXT = 0xe - VMIN = 0x10 - VM_LOADAVG = 0x2 - VM_MACHFACTOR = 0x4 - VM_MAXID = 0x6 - VM_METER = 0x1 - VM_SWAPUSAGE = 0x5 - VQUIT = 0x9 - VREPRINT = 0x6 - VSTART = 0xc - VSTATUS = 0x12 - VSTOP = 0xd - VSUSP = 0xa - VT0 = 0x0 - VT1 = 0x10000 - VTDLY = 0x10000 - VTIME = 0x11 - VWERASE = 0x4 - WCONTINUED = 0x10 - WCOREFLAG = 0x80 - WEXITED = 0x4 - WNOHANG = 0x1 - WNOWAIT = 0x20 - WORDSIZE = 0x40 - WSTOPPED = 0x8 - WUNTRACED = 0x2 - XATTR_CREATE = 0x2 - XATTR_NODEFAULT = 0x10 - XATTR_NOFOLLOW = 0x1 - XATTR_NOSECURITY = 0x8 - XATTR_REPLACE = 0x4 - XATTR_SHOWCOMPRESSION = 0x20 + AF_APPLETALK = 0x10 + AF_CCITT = 0xa + AF_CHAOS = 0x5 + AF_CNT = 0x15 + AF_COIP = 0x14 + AF_DATAKIT = 0x9 + AF_DECnet = 0xc + AF_DLI = 0xd + AF_E164 = 0x1c + AF_ECMA = 0x8 + AF_HYLINK = 0xf + AF_IEEE80211 = 0x25 + AF_IMPLINK = 0x3 + AF_INET = 0x2 + AF_INET6 = 0x1e + AF_IPX = 0x17 + AF_ISDN = 0x1c + AF_ISO = 0x7 + AF_LAT = 0xe + AF_LINK = 0x12 + AF_LOCAL = 0x1 + AF_MAX = 0x29 + AF_NATM = 0x1f + AF_NDRV = 0x1b + AF_NETBIOS = 0x21 + AF_NS = 0x6 + AF_OSI = 0x7 + AF_PPP = 0x22 + AF_PUP = 0x4 + AF_RESERVED_36 = 0x24 + AF_ROUTE = 0x11 + AF_SIP = 0x18 + AF_SNA = 0xb + AF_SYSTEM = 0x20 + AF_SYS_CONTROL = 0x2 + AF_UNIX = 0x1 + AF_UNSPEC = 0x0 + AF_UTUN = 0x26 + AF_VSOCK = 0x28 + ALTWERASE = 0x200 + ATTR_BIT_MAP_COUNT = 0x5 + ATTR_CMN_ACCESSMASK = 0x20000 + ATTR_CMN_ACCTIME = 0x1000 + ATTR_CMN_ADDEDTIME = 0x10000000 + ATTR_CMN_BKUPTIME = 0x2000 + ATTR_CMN_CHGTIME = 0x800 + ATTR_CMN_CRTIME = 0x200 + ATTR_CMN_DATA_PROTECT_FLAGS = 0x40000000 + ATTR_CMN_DEVID = 0x2 + ATTR_CMN_DOCUMENT_ID = 0x100000 + ATTR_CMN_ERROR = 0x20000000 + ATTR_CMN_EXTENDED_SECURITY = 0x400000 + ATTR_CMN_FILEID = 0x2000000 + ATTR_CMN_FLAGS = 0x40000 + ATTR_CMN_FNDRINFO = 0x4000 + ATTR_CMN_FSID = 0x4 + ATTR_CMN_FULLPATH = 0x8000000 + ATTR_CMN_GEN_COUNT = 0x80000 + ATTR_CMN_GRPID = 0x10000 + ATTR_CMN_GRPUUID = 0x1000000 + ATTR_CMN_MODTIME = 0x400 + ATTR_CMN_NAME = 0x1 + ATTR_CMN_NAMEDATTRCOUNT = 0x80000 + ATTR_CMN_NAMEDATTRLIST = 0x100000 + ATTR_CMN_OBJID = 0x20 + ATTR_CMN_OBJPERMANENTID = 0x40 + ATTR_CMN_OBJTAG = 0x10 + ATTR_CMN_OBJTYPE = 0x8 + ATTR_CMN_OWNERID = 0x8000 + ATTR_CMN_PARENTID = 0x4000000 + ATTR_CMN_PAROBJID = 0x80 + ATTR_CMN_RETURNED_ATTRS = 0x80000000 + ATTR_CMN_SCRIPT = 0x100 + ATTR_CMN_SETMASK = 0x51c7ff00 + ATTR_CMN_USERACCESS = 0x200000 + ATTR_CMN_UUID = 0x800000 + ATTR_CMN_VALIDMASK = 0xffffffff + ATTR_CMN_VOLSETMASK = 0x6700 + ATTR_FILE_ALLOCSIZE = 0x4 + ATTR_FILE_CLUMPSIZE = 0x10 + ATTR_FILE_DATAALLOCSIZE = 0x400 + ATTR_FILE_DATAEXTENTS = 0x800 + ATTR_FILE_DATALENGTH = 0x200 + ATTR_FILE_DEVTYPE = 0x20 + ATTR_FILE_FILETYPE = 0x40 + ATTR_FILE_FORKCOUNT = 0x80 + ATTR_FILE_FORKLIST = 0x100 + ATTR_FILE_IOBLOCKSIZE = 0x8 + ATTR_FILE_LINKCOUNT = 0x1 + ATTR_FILE_RSRCALLOCSIZE = 0x2000 + ATTR_FILE_RSRCEXTENTS = 0x4000 + ATTR_FILE_RSRCLENGTH = 0x1000 + ATTR_FILE_SETMASK = 0x20 + ATTR_FILE_TOTALSIZE = 0x2 + ATTR_FILE_VALIDMASK = 0x37ff + ATTR_VOL_ALLOCATIONCLUMP = 0x40 + ATTR_VOL_ATTRIBUTES = 0x40000000 + ATTR_VOL_CAPABILITIES = 0x20000 + ATTR_VOL_DIRCOUNT = 0x400 + ATTR_VOL_ENCODINGSUSED = 0x10000 + ATTR_VOL_FILECOUNT = 0x200 + ATTR_VOL_FSTYPE = 0x1 + ATTR_VOL_INFO = 0x80000000 + ATTR_VOL_IOBLOCKSIZE = 0x80 + ATTR_VOL_MAXOBJCOUNT = 0x800 + ATTR_VOL_MINALLOCATION = 0x20 + ATTR_VOL_MOUNTEDDEVICE = 0x8000 + ATTR_VOL_MOUNTFLAGS = 0x4000 + ATTR_VOL_MOUNTPOINT = 0x1000 + ATTR_VOL_NAME = 0x2000 + ATTR_VOL_OBJCOUNT = 0x100 + ATTR_VOL_QUOTA_SIZE = 0x10000000 + ATTR_VOL_RESERVED_SIZE = 0x20000000 + ATTR_VOL_SETMASK = 0x80002000 + ATTR_VOL_SIGNATURE = 0x2 + ATTR_VOL_SIZE = 0x4 + ATTR_VOL_SPACEAVAIL = 0x10 + ATTR_VOL_SPACEFREE = 0x8 + ATTR_VOL_SPACEUSED = 0x800000 + ATTR_VOL_UUID = 0x40000 + ATTR_VOL_VALIDMASK = 0xf087ffff + B0 = 0x0 + B110 = 0x6e + B115200 = 0x1c200 + B1200 = 0x4b0 + B134 = 0x86 + B14400 = 0x3840 + B150 = 0x96 + B1800 = 0x708 + B19200 = 0x4b00 + B200 = 0xc8 + B230400 = 0x38400 + B2400 = 0x960 + B28800 = 0x7080 + B300 = 0x12c + B38400 = 0x9600 + B4800 = 0x12c0 + B50 = 0x32 + B57600 = 0xe100 + B600 = 0x258 + B7200 = 0x1c20 + B75 = 0x4b + B76800 = 0x12c00 + B9600 = 0x2580 + BIOCFLUSH = 0x20004268 + BIOCGBLEN = 0x40044266 + BIOCGDLT = 0x4004426a + BIOCGDLTLIST = 0xc00c4279 + BIOCGETIF = 0x4020426b + BIOCGHDRCMPLT = 0x40044274 + BIOCGRSIG = 0x40044272 + BIOCGRTIMEOUT = 0x4010426e + BIOCGSEESENT = 0x40044276 + BIOCGSTATS = 0x4008426f + BIOCIMMEDIATE = 0x80044270 + BIOCPROMISC = 0x20004269 + BIOCSBLEN = 0xc0044266 + BIOCSDLT = 0x80044278 + BIOCSETF = 0x80104267 + BIOCSETFNR = 0x8010427e + BIOCSETIF = 0x8020426c + BIOCSHDRCMPLT = 0x80044275 + BIOCSRSIG = 0x80044273 + BIOCSRTIMEOUT = 0x8010426d + BIOCSSEESENT = 0x80044277 + BIOCVERSION = 0x40044271 + BPF_A = 0x10 + BPF_ABS = 0x20 + BPF_ADD = 0x0 + BPF_ALIGNMENT = 0x4 + BPF_ALU = 0x4 + BPF_AND = 0x50 + BPF_B = 0x10 + BPF_DIV = 0x30 + BPF_H = 0x8 + BPF_IMM = 0x0 + BPF_IND = 0x40 + BPF_JA = 0x0 + BPF_JEQ = 0x10 + BPF_JGE = 0x30 + BPF_JGT = 0x20 + BPF_JMP = 0x5 + BPF_JSET = 0x40 + BPF_K = 0x0 + BPF_LD = 0x0 + BPF_LDX = 0x1 + BPF_LEN = 0x80 + BPF_LSH = 0x60 + BPF_MAJOR_VERSION = 0x1 + BPF_MAXBUFSIZE = 0x80000 + BPF_MAXINSNS = 0x200 + BPF_MEM = 0x60 + BPF_MEMWORDS = 0x10 + BPF_MINBUFSIZE = 0x20 + BPF_MINOR_VERSION = 0x1 + BPF_MISC = 0x7 + BPF_MSH = 0xa0 + BPF_MUL = 0x20 + BPF_NEG = 0x80 + BPF_OR = 0x40 + BPF_RELEASE = 0x30bb6 + BPF_RET = 0x6 + BPF_RSH = 0x70 + BPF_ST = 0x2 + BPF_STX = 0x3 + BPF_SUB = 0x10 + BPF_TAX = 0x0 + BPF_TXA = 0x80 + BPF_W = 0x0 + BPF_X = 0x8 + BRKINT = 0x2 + BS0 = 0x0 + BS1 = 0x8000 + BSDLY = 0x8000 + CFLUSH = 0xf + CLOCAL = 0x8000 + CLOCK_MONOTONIC = 0x6 + CLOCK_MONOTONIC_RAW = 0x4 + CLOCK_MONOTONIC_RAW_APPROX = 0x5 + CLOCK_PROCESS_CPUTIME_ID = 0xc + CLOCK_REALTIME = 0x0 + CLOCK_THREAD_CPUTIME_ID = 0x10 + CLOCK_UPTIME_RAW = 0x8 + CLOCK_UPTIME_RAW_APPROX = 0x9 + CLONE_NOFOLLOW = 0x1 + CLONE_NOOWNERCOPY = 0x2 + CR0 = 0x0 + CR1 = 0x1000 + CR2 = 0x2000 + CR3 = 0x3000 + CRDLY = 0x3000 + CREAD = 0x800 + CRTSCTS = 0x30000 + CS5 = 0x0 + CS6 = 0x100 + CS7 = 0x200 + CS8 = 0x300 + CSIZE = 0x300 + CSTART = 0x11 + CSTATUS = 0x14 + CSTOP = 0x13 + CSTOPB = 0x400 + CSUSP = 0x1a + CTLIOCGINFO = 0xc0644e03 + CTL_HW = 0x6 + CTL_KERN = 0x1 + CTL_MAXNAME = 0xc + CTL_NET = 0x4 + DLT_A429 = 0xb8 + DLT_A653_ICM = 0xb9 + DLT_AIRONET_HEADER = 0x78 + DLT_AOS = 0xde + DLT_APPLE_IP_OVER_IEEE1394 = 0x8a + DLT_ARCNET = 0x7 + DLT_ARCNET_LINUX = 0x81 + DLT_ATM_CLIP = 0x13 + DLT_ATM_RFC1483 = 0xb + DLT_AURORA = 0x7e + DLT_AX25 = 0x3 + DLT_AX25_KISS = 0xca + DLT_BACNET_MS_TP = 0xa5 + DLT_BLUETOOTH_HCI_H4 = 0xbb + DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 0xc9 + DLT_CAN20B = 0xbe + DLT_CAN_SOCKETCAN = 0xe3 + DLT_CHAOS = 0x5 + DLT_CHDLC = 0x68 + DLT_CISCO_IOS = 0x76 + DLT_C_HDLC = 0x68 + DLT_C_HDLC_WITH_DIR = 0xcd + DLT_DBUS = 0xe7 + DLT_DECT = 0xdd + DLT_DOCSIS = 0x8f + DLT_DVB_CI = 0xeb + DLT_ECONET = 0x73 + DLT_EN10MB = 0x1 + DLT_EN3MB = 0x2 + DLT_ENC = 0x6d + DLT_ERF = 0xc5 + DLT_ERF_ETH = 0xaf + DLT_ERF_POS = 0xb0 + DLT_FC_2 = 0xe0 + DLT_FC_2_WITH_FRAME_DELIMS = 0xe1 + DLT_FDDI = 0xa + DLT_FLEXRAY = 0xd2 + DLT_FRELAY = 0x6b + DLT_FRELAY_WITH_DIR = 0xce + DLT_GCOM_SERIAL = 0xad + DLT_GCOM_T1E1 = 0xac + DLT_GPF_F = 0xab + DLT_GPF_T = 0xaa + DLT_GPRS_LLC = 0xa9 + DLT_GSMTAP_ABIS = 0xda + DLT_GSMTAP_UM = 0xd9 + DLT_HHDLC = 0x79 + DLT_IBM_SN = 0x92 + DLT_IBM_SP = 0x91 + DLT_IEEE802 = 0x6 + DLT_IEEE802_11 = 0x69 + DLT_IEEE802_11_RADIO = 0x7f + DLT_IEEE802_11_RADIO_AVS = 0xa3 + DLT_IEEE802_15_4 = 0xc3 + DLT_IEEE802_15_4_LINUX = 0xbf + DLT_IEEE802_15_4_NOFCS = 0xe6 + DLT_IEEE802_15_4_NONASK_PHY = 0xd7 + DLT_IEEE802_16_MAC_CPS = 0xbc + DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1 + DLT_IPFILTER = 0x74 + DLT_IPMB = 0xc7 + DLT_IPMB_LINUX = 0xd1 + DLT_IPNET = 0xe2 + DLT_IPOIB = 0xf2 + DLT_IPV4 = 0xe4 + DLT_IPV6 = 0xe5 + DLT_IP_OVER_FC = 0x7a + DLT_JUNIPER_ATM1 = 0x89 + DLT_JUNIPER_ATM2 = 0x87 + DLT_JUNIPER_ATM_CEMIC = 0xee + DLT_JUNIPER_CHDLC = 0xb5 + DLT_JUNIPER_ES = 0x84 + DLT_JUNIPER_ETHER = 0xb2 + DLT_JUNIPER_FIBRECHANNEL = 0xea + DLT_JUNIPER_FRELAY = 0xb4 + DLT_JUNIPER_GGSN = 0x85 + DLT_JUNIPER_ISM = 0xc2 + DLT_JUNIPER_MFR = 0x86 + DLT_JUNIPER_MLFR = 0x83 + DLT_JUNIPER_MLPPP = 0x82 + DLT_JUNIPER_MONITOR = 0xa4 + DLT_JUNIPER_PIC_PEER = 0xae + DLT_JUNIPER_PPP = 0xb3 + DLT_JUNIPER_PPPOE = 0xa7 + DLT_JUNIPER_PPPOE_ATM = 0xa8 + DLT_JUNIPER_SERVICES = 0x88 + DLT_JUNIPER_SRX_E2E = 0xe9 + DLT_JUNIPER_ST = 0xc8 + DLT_JUNIPER_VP = 0xb7 + DLT_JUNIPER_VS = 0xe8 + DLT_LAPB_WITH_DIR = 0xcf + DLT_LAPD = 0xcb + DLT_LIN = 0xd4 + DLT_LINUX_EVDEV = 0xd8 + DLT_LINUX_IRDA = 0x90 + DLT_LINUX_LAPD = 0xb1 + DLT_LINUX_PPP_WITHDIRECTION = 0xa6 + DLT_LINUX_SLL = 0x71 + DLT_LOOP = 0x6c + DLT_LTALK = 0x72 + DLT_MATCHING_MAX = 0x10a + DLT_MATCHING_MIN = 0x68 + DLT_MFR = 0xb6 + DLT_MOST = 0xd3 + DLT_MPEG_2_TS = 0xf3 + DLT_MPLS = 0xdb + DLT_MTP2 = 0x8c + DLT_MTP2_WITH_PHDR = 0x8b + DLT_MTP3 = 0x8d + DLT_MUX27010 = 0xec + DLT_NETANALYZER = 0xf0 + DLT_NETANALYZER_TRANSPARENT = 0xf1 + DLT_NFC_LLCP = 0xf5 + DLT_NFLOG = 0xef + DLT_NG40 = 0xf4 + DLT_NULL = 0x0 + DLT_PCI_EXP = 0x7d + DLT_PFLOG = 0x75 + DLT_PFSYNC = 0x12 + DLT_PPI = 0xc0 + DLT_PPP = 0x9 + DLT_PPP_BSDOS = 0x10 + DLT_PPP_ETHER = 0x33 + DLT_PPP_PPPD = 0xa6 + DLT_PPP_SERIAL = 0x32 + DLT_PPP_WITH_DIR = 0xcc + DLT_PPP_WITH_DIRECTION = 0xa6 + DLT_PRISM_HEADER = 0x77 + DLT_PRONET = 0x4 + DLT_RAIF1 = 0xc6 + DLT_RAW = 0xc + DLT_RIO = 0x7c + DLT_SCCP = 0x8e + DLT_SITA = 0xc4 + DLT_SLIP = 0x8 + DLT_SLIP_BSDOS = 0xf + DLT_STANAG_5066_D_PDU = 0xed + DLT_SUNATM = 0x7b + DLT_SYMANTEC_FIREWALL = 0x63 + DLT_TZSP = 0x80 + DLT_USB = 0xba + DLT_USB_DARWIN = 0x10a + DLT_USB_LINUX = 0xbd + DLT_USB_LINUX_MMAPPED = 0xdc + DLT_USER0 = 0x93 + DLT_USER1 = 0x94 + DLT_USER10 = 0x9d + DLT_USER11 = 0x9e + DLT_USER12 = 0x9f + DLT_USER13 = 0xa0 + DLT_USER14 = 0xa1 + DLT_USER15 = 0xa2 + DLT_USER2 = 0x95 + DLT_USER3 = 0x96 + DLT_USER4 = 0x97 + DLT_USER5 = 0x98 + DLT_USER6 = 0x99 + DLT_USER7 = 0x9a + DLT_USER8 = 0x9b + DLT_USER9 = 0x9c + DLT_WIHART = 0xdf + DLT_X2E_SERIAL = 0xd5 + DLT_X2E_XORAYA = 0xd6 + DT_BLK = 0x6 + DT_CHR = 0x2 + DT_DIR = 0x4 + DT_FIFO = 0x1 + DT_LNK = 0xa + DT_REG = 0x8 + DT_SOCK = 0xc + DT_UNKNOWN = 0x0 + DT_WHT = 0xe + ECHO = 0x8 + ECHOCTL = 0x40 + ECHOE = 0x2 + ECHOK = 0x4 + ECHOKE = 0x1 + ECHONL = 0x10 + ECHOPRT = 0x20 + EVFILT_AIO = -0x3 + EVFILT_EXCEPT = -0xf + EVFILT_FS = -0x9 + EVFILT_MACHPORT = -0x8 + EVFILT_PROC = -0x5 + EVFILT_READ = -0x1 + EVFILT_SIGNAL = -0x6 + EVFILT_SYSCOUNT = 0x11 + EVFILT_THREADMARKER = 0x11 + EVFILT_TIMER = -0x7 + EVFILT_USER = -0xa + EVFILT_VM = -0xc + EVFILT_VNODE = -0x4 + EVFILT_WRITE = -0x2 + EV_ADD = 0x1 + EV_CLEAR = 0x20 + EV_DELETE = 0x2 + EV_DISABLE = 0x8 + EV_DISPATCH = 0x80 + EV_DISPATCH2 = 0x180 + EV_ENABLE = 0x4 + EV_EOF = 0x8000 + EV_ERROR = 0x4000 + EV_FLAG0 = 0x1000 + EV_FLAG1 = 0x2000 + EV_ONESHOT = 0x10 + EV_OOBAND = 0x2000 + EV_POLL = 0x1000 + EV_RECEIPT = 0x40 + EV_SYSFLAGS = 0xf000 + EV_UDATA_SPECIFIC = 0x100 + EV_VANISHED = 0x200 + EXTA = 0x4b00 + EXTB = 0x9600 + EXTPROC = 0x800 + FD_CLOEXEC = 0x1 + FD_SETSIZE = 0x400 + FF0 = 0x0 + FF1 = 0x4000 + FFDLY = 0x4000 + FLUSHO = 0x800000 + FSOPT_ATTR_CMN_EXTENDED = 0x20 + FSOPT_NOFOLLOW = 0x1 + FSOPT_NOINMEMUPDATE = 0x2 + FSOPT_PACK_INVAL_ATTRS = 0x8 + FSOPT_REPORT_FULLSIZE = 0x4 + FSOPT_RETURN_REALDEV = 0x200 + F_ADDFILESIGS = 0x3d + F_ADDFILESIGS_FOR_DYLD_SIM = 0x53 + F_ADDFILESIGS_INFO = 0x67 + F_ADDFILESIGS_RETURN = 0x61 + F_ADDFILESUPPL = 0x68 + F_ADDSIGS = 0x3b + F_ALLOCATEALL = 0x4 + F_ALLOCATECONTIG = 0x2 + F_BARRIERFSYNC = 0x55 + F_CHECK_LV = 0x62 + F_CHKCLEAN = 0x29 + F_DUPFD = 0x0 + F_DUPFD_CLOEXEC = 0x43 + F_FINDSIGS = 0x4e + F_FLUSH_DATA = 0x28 + F_FREEZE_FS = 0x35 + F_FULLFSYNC = 0x33 + F_GETCODEDIR = 0x48 + F_GETFD = 0x1 + F_GETFL = 0x3 + F_GETLK = 0x7 + F_GETLKPID = 0x42 + F_GETNOSIGPIPE = 0x4a + F_GETOWN = 0x5 + F_GETPATH = 0x32 + F_GETPATH_MTMINFO = 0x47 + F_GETPATH_NOFIRMLINK = 0x66 + F_GETPROTECTIONCLASS = 0x3f + F_GETPROTECTIONLEVEL = 0x4d + F_GETSIGSINFO = 0x69 + F_GLOBAL_NOCACHE = 0x37 + F_LOG2PHYS = 0x31 + F_LOG2PHYS_EXT = 0x41 + F_NOCACHE = 0x30 + F_NODIRECT = 0x3e + F_OK = 0x0 + F_PATHPKG_CHECK = 0x34 + F_PEOFPOSMODE = 0x3 + F_PREALLOCATE = 0x2a + F_PUNCHHOLE = 0x63 + F_RDADVISE = 0x2c + F_RDAHEAD = 0x2d + F_RDLCK = 0x1 + F_SETBACKINGSTORE = 0x46 + F_SETFD = 0x2 + F_SETFL = 0x4 + F_SETLK = 0x8 + F_SETLKW = 0x9 + F_SETLKWTIMEOUT = 0xa + F_SETNOSIGPIPE = 0x49 + F_SETOWN = 0x6 + F_SETPROTECTIONCLASS = 0x40 + F_SETSIZE = 0x2b + F_SINGLE_WRITER = 0x4c + F_SPECULATIVE_READ = 0x65 + F_THAW_FS = 0x36 + F_TRANSCODEKEY = 0x4b + F_TRIM_ACTIVE_FILE = 0x64 + F_UNLCK = 0x2 + F_VOLPOSMODE = 0x4 + F_WRLCK = 0x3 + HUPCL = 0x4000 + HW_MACHINE = 0x1 + ICANON = 0x100 + ICMP6_FILTER = 0x12 + ICRNL = 0x100 + IEXTEN = 0x400 + IFF_ALLMULTI = 0x200 + IFF_ALTPHYS = 0x4000 + IFF_BROADCAST = 0x2 + IFF_DEBUG = 0x4 + IFF_LINK0 = 0x1000 + IFF_LINK1 = 0x2000 + IFF_LINK2 = 0x4000 + IFF_LOOPBACK = 0x8 + IFF_MULTICAST = 0x8000 + IFF_NOARP = 0x80 + IFF_NOTRAILERS = 0x20 + IFF_OACTIVE = 0x400 + IFF_POINTOPOINT = 0x10 + IFF_PROMISC = 0x100 + IFF_RUNNING = 0x40 + IFF_SIMPLEX = 0x800 + IFF_UP = 0x1 + IFNAMSIZ = 0x10 + IFT_1822 = 0x2 + IFT_6LOWPAN = 0x40 + IFT_AAL5 = 0x31 + IFT_ARCNET = 0x23 + IFT_ARCNETPLUS = 0x24 + IFT_ATM = 0x25 + IFT_BRIDGE = 0xd1 + IFT_CARP = 0xf8 + IFT_CELLULAR = 0xff + IFT_CEPT = 0x13 + IFT_DS3 = 0x1e + IFT_ENC = 0xf4 + IFT_EON = 0x19 + IFT_ETHER = 0x6 + IFT_FAITH = 0x38 + IFT_FDDI = 0xf + IFT_FRELAY = 0x20 + IFT_FRELAYDCE = 0x2c + IFT_GIF = 0x37 + IFT_HDH1822 = 0x3 + IFT_HIPPI = 0x2f + IFT_HSSI = 0x2e + IFT_HY = 0xe + IFT_IEEE1394 = 0x90 + IFT_IEEE8023ADLAG = 0x88 + IFT_ISDNBASIC = 0x14 + IFT_ISDNPRIMARY = 0x15 + IFT_ISO88022LLC = 0x29 + IFT_ISO88023 = 0x7 + IFT_ISO88024 = 0x8 + IFT_ISO88025 = 0x9 + IFT_ISO88026 = 0xa + IFT_L2VLAN = 0x87 + IFT_LAPB = 0x10 + IFT_LOCALTALK = 0x2a + IFT_LOOP = 0x18 + IFT_MIOX25 = 0x26 + IFT_MODEM = 0x30 + IFT_NSIP = 0x1b + IFT_OTHER = 0x1 + IFT_P10 = 0xc + IFT_P80 = 0xd + IFT_PARA = 0x22 + IFT_PDP = 0xff + IFT_PFLOG = 0xf5 + IFT_PFSYNC = 0xf6 + IFT_PKTAP = 0xfe + IFT_PPP = 0x17 + IFT_PROPMUX = 0x36 + IFT_PROPVIRTUAL = 0x35 + IFT_PTPSERIAL = 0x16 + IFT_RS232 = 0x21 + IFT_SDLC = 0x11 + IFT_SIP = 0x1f + IFT_SLIP = 0x1c + IFT_SMDSDXI = 0x2b + IFT_SMDSICIP = 0x34 + IFT_SONET = 0x27 + IFT_SONETPATH = 0x32 + IFT_SONETVT = 0x33 + IFT_STARLAN = 0xb + IFT_STF = 0x39 + IFT_T1 = 0x12 + IFT_ULTRA = 0x1d + IFT_V35 = 0x2d + IFT_X25 = 0x5 + IFT_X25DDN = 0x4 + IFT_X25PLE = 0x28 + IFT_XETHER = 0x1a + IGNBRK = 0x1 + IGNCR = 0x80 + IGNPAR = 0x4 + IMAXBEL = 0x2000 + INLCR = 0x40 + INPCK = 0x10 + IN_CLASSA_HOST = 0xffffff + IN_CLASSA_MAX = 0x80 + IN_CLASSA_NET = 0xff000000 + IN_CLASSA_NSHIFT = 0x18 + IN_CLASSB_HOST = 0xffff + IN_CLASSB_MAX = 0x10000 + IN_CLASSB_NET = 0xffff0000 + IN_CLASSB_NSHIFT = 0x10 + IN_CLASSC_HOST = 0xff + IN_CLASSC_NET = 0xffffff00 + IN_CLASSC_NSHIFT = 0x8 + IN_CLASSD_HOST = 0xfffffff + IN_CLASSD_NET = 0xf0000000 + IN_CLASSD_NSHIFT = 0x1c + IN_LINKLOCALNETNUM = 0xa9fe0000 + IN_LOOPBACKNET = 0x7f + IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x400473d1 + IPPROTO_3PC = 0x22 + IPPROTO_ADFS = 0x44 + IPPROTO_AH = 0x33 + IPPROTO_AHIP = 0x3d + IPPROTO_APES = 0x63 + IPPROTO_ARGUS = 0xd + IPPROTO_AX25 = 0x5d + IPPROTO_BHA = 0x31 + IPPROTO_BLT = 0x1e + IPPROTO_BRSATMON = 0x4c + IPPROTO_CFTP = 0x3e + IPPROTO_CHAOS = 0x10 + IPPROTO_CMTP = 0x26 + IPPROTO_CPHB = 0x49 + IPPROTO_CPNX = 0x48 + IPPROTO_DDP = 0x25 + IPPROTO_DGP = 0x56 + IPPROTO_DIVERT = 0xfe + IPPROTO_DONE = 0x101 + IPPROTO_DSTOPTS = 0x3c + IPPROTO_EGP = 0x8 + IPPROTO_EMCON = 0xe + IPPROTO_ENCAP = 0x62 + IPPROTO_EON = 0x50 + IPPROTO_ESP = 0x32 + IPPROTO_ETHERIP = 0x61 + IPPROTO_FRAGMENT = 0x2c + IPPROTO_GGP = 0x3 + IPPROTO_GMTP = 0x64 + IPPROTO_GRE = 0x2f + IPPROTO_HELLO = 0x3f + IPPROTO_HMP = 0x14 + IPPROTO_HOPOPTS = 0x0 + IPPROTO_ICMP = 0x1 + IPPROTO_ICMPV6 = 0x3a + IPPROTO_IDP = 0x16 + IPPROTO_IDPR = 0x23 + IPPROTO_IDRP = 0x2d + IPPROTO_IGMP = 0x2 + IPPROTO_IGP = 0x55 + IPPROTO_IGRP = 0x58 + IPPROTO_IL = 0x28 + IPPROTO_INLSP = 0x34 + IPPROTO_INP = 0x20 + IPPROTO_IP = 0x0 + IPPROTO_IPCOMP = 0x6c + IPPROTO_IPCV = 0x47 + IPPROTO_IPEIP = 0x5e + IPPROTO_IPIP = 0x4 + IPPROTO_IPPC = 0x43 + IPPROTO_IPV4 = 0x4 + IPPROTO_IPV6 = 0x29 + IPPROTO_IRTP = 0x1c + IPPROTO_KRYPTOLAN = 0x41 + IPPROTO_LARP = 0x5b + IPPROTO_LEAF1 = 0x19 + IPPROTO_LEAF2 = 0x1a + IPPROTO_MAX = 0x100 + IPPROTO_MAXID = 0x34 + IPPROTO_MEAS = 0x13 + IPPROTO_MHRP = 0x30 + IPPROTO_MICP = 0x5f + IPPROTO_MTP = 0x5c + IPPROTO_MUX = 0x12 + IPPROTO_ND = 0x4d + IPPROTO_NHRP = 0x36 + IPPROTO_NONE = 0x3b + IPPROTO_NSP = 0x1f + IPPROTO_NVPII = 0xb + IPPROTO_OSPFIGP = 0x59 + IPPROTO_PGM = 0x71 + IPPROTO_PIGP = 0x9 + IPPROTO_PIM = 0x67 + IPPROTO_PRM = 0x15 + IPPROTO_PUP = 0xc + IPPROTO_PVP = 0x4b + IPPROTO_RAW = 0xff + IPPROTO_RCCMON = 0xa + IPPROTO_RDP = 0x1b + IPPROTO_ROUTING = 0x2b + IPPROTO_RSVP = 0x2e + IPPROTO_RVD = 0x42 + IPPROTO_SATEXPAK = 0x40 + IPPROTO_SATMON = 0x45 + IPPROTO_SCCSP = 0x60 + IPPROTO_SCTP = 0x84 + IPPROTO_SDRP = 0x2a + IPPROTO_SEP = 0x21 + IPPROTO_SRPC = 0x5a + IPPROTO_ST = 0x7 + IPPROTO_SVMTP = 0x52 + IPPROTO_SWIPE = 0x35 + IPPROTO_TCF = 0x57 + IPPROTO_TCP = 0x6 + IPPROTO_TP = 0x1d + IPPROTO_TPXX = 0x27 + IPPROTO_TRUNK1 = 0x17 + IPPROTO_TRUNK2 = 0x18 + IPPROTO_TTP = 0x54 + IPPROTO_UDP = 0x11 + IPPROTO_VINES = 0x53 + IPPROTO_VISA = 0x46 + IPPROTO_VMTP = 0x51 + IPPROTO_WBEXPAK = 0x4f + IPPROTO_WBMON = 0x4e + IPPROTO_WSN = 0x4a + IPPROTO_XNET = 0xf + IPPROTO_XTP = 0x24 + IPV6_2292DSTOPTS = 0x17 + IPV6_2292HOPLIMIT = 0x14 + IPV6_2292HOPOPTS = 0x16 + IPV6_2292NEXTHOP = 0x15 + IPV6_2292PKTINFO = 0x13 + IPV6_2292PKTOPTIONS = 0x19 + IPV6_2292RTHDR = 0x18 + IPV6_3542DSTOPTS = 0x32 + IPV6_3542HOPLIMIT = 0x2f + IPV6_3542HOPOPTS = 0x31 + IPV6_3542NEXTHOP = 0x30 + IPV6_3542PKTINFO = 0x2e + IPV6_3542RTHDR = 0x33 + IPV6_ADDR_MC_FLAGS_PREFIX = 0x20 + IPV6_ADDR_MC_FLAGS_TRANSIENT = 0x10 + IPV6_ADDR_MC_FLAGS_UNICAST_BASED = 0x30 + IPV6_AUTOFLOWLABEL = 0x3b + IPV6_BINDV6ONLY = 0x1b + IPV6_BOUND_IF = 0x7d + IPV6_CHECKSUM = 0x1a + IPV6_DEFAULT_MULTICAST_HOPS = 0x1 + IPV6_DEFAULT_MULTICAST_LOOP = 0x1 + IPV6_DEFHLIM = 0x40 + IPV6_DONTFRAG = 0x3e + IPV6_DSTOPTS = 0x32 + IPV6_FAITH = 0x1d + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 + IPV6_FLOW_ECN_MASK = 0x3000 + IPV6_FRAGTTL = 0x3c + IPV6_FW_ADD = 0x1e + IPV6_FW_DEL = 0x1f + IPV6_FW_FLUSH = 0x20 + IPV6_FW_GET = 0x22 + IPV6_FW_ZERO = 0x21 + IPV6_HLIMDEC = 0x1 + IPV6_HOPLIMIT = 0x2f + IPV6_HOPOPTS = 0x31 + IPV6_IPSEC_POLICY = 0x1c + IPV6_JOIN_GROUP = 0xc + IPV6_LEAVE_GROUP = 0xd + IPV6_MAXHLIM = 0xff + IPV6_MAXOPTHDR = 0x800 + IPV6_MAXPACKET = 0xffff + IPV6_MAX_GROUP_SRC_FILTER = 0x200 + IPV6_MAX_MEMBERSHIPS = 0xfff + IPV6_MAX_SOCK_SRC_FILTER = 0x80 + IPV6_MIN_MEMBERSHIPS = 0x1f + IPV6_MMTU = 0x500 + IPV6_MSFILTER = 0x4a + IPV6_MULTICAST_HOPS = 0xa + IPV6_MULTICAST_IF = 0x9 + IPV6_MULTICAST_LOOP = 0xb + IPV6_NEXTHOP = 0x30 + IPV6_PATHMTU = 0x2c + IPV6_PKTINFO = 0x2e + IPV6_PORTRANGE = 0xe + IPV6_PORTRANGE_DEFAULT = 0x0 + IPV6_PORTRANGE_HIGH = 0x1 + IPV6_PORTRANGE_LOW = 0x2 + IPV6_PREFER_TEMPADDR = 0x3f + IPV6_RECVDSTOPTS = 0x28 + IPV6_RECVHOPLIMIT = 0x25 + IPV6_RECVHOPOPTS = 0x27 + IPV6_RECVPATHMTU = 0x2b + IPV6_RECVPKTINFO = 0x3d + IPV6_RECVRTHDR = 0x26 + IPV6_RECVTCLASS = 0x23 + IPV6_RTHDR = 0x33 + IPV6_RTHDRDSTOPTS = 0x39 + IPV6_RTHDR_LOOSE = 0x0 + IPV6_RTHDR_STRICT = 0x1 + IPV6_RTHDR_TYPE_0 = 0x0 + IPV6_SOCKOPT_RESERVED1 = 0x3 + IPV6_TCLASS = 0x24 + IPV6_UNICAST_HOPS = 0x4 + IPV6_USE_MIN_MTU = 0x2a + IPV6_V6ONLY = 0x1b + IPV6_VERSION = 0x60 + IPV6_VERSION_MASK = 0xf0 + IP_ADD_MEMBERSHIP = 0xc + IP_ADD_SOURCE_MEMBERSHIP = 0x46 + IP_BLOCK_SOURCE = 0x48 + IP_BOUND_IF = 0x19 + IP_DEFAULT_MULTICAST_LOOP = 0x1 + IP_DEFAULT_MULTICAST_TTL = 0x1 + IP_DF = 0x4000 + IP_DONTFRAG = 0x1c + IP_DROP_MEMBERSHIP = 0xd + IP_DROP_SOURCE_MEMBERSHIP = 0x47 + IP_DUMMYNET_CONFIGURE = 0x3c + IP_DUMMYNET_DEL = 0x3d + IP_DUMMYNET_FLUSH = 0x3e + IP_DUMMYNET_GET = 0x40 + IP_FAITH = 0x16 + IP_FW_ADD = 0x28 + IP_FW_DEL = 0x29 + IP_FW_FLUSH = 0x2a + IP_FW_GET = 0x2c + IP_FW_RESETLOG = 0x2d + IP_FW_ZERO = 0x2b + IP_HDRINCL = 0x2 + IP_IPSEC_POLICY = 0x15 + IP_MAXPACKET = 0xffff + IP_MAX_GROUP_SRC_FILTER = 0x200 + IP_MAX_MEMBERSHIPS = 0xfff + IP_MAX_SOCK_MUTE_FILTER = 0x80 + IP_MAX_SOCK_SRC_FILTER = 0x80 + IP_MF = 0x2000 + IP_MIN_MEMBERSHIPS = 0x1f + IP_MSFILTER = 0x4a + IP_MSS = 0x240 + IP_MULTICAST_IF = 0x9 + IP_MULTICAST_IFINDEX = 0x42 + IP_MULTICAST_LOOP = 0xb + IP_MULTICAST_TTL = 0xa + IP_MULTICAST_VIF = 0xe + IP_NAT__XXX = 0x37 + IP_OFFMASK = 0x1fff + IP_OLD_FW_ADD = 0x32 + IP_OLD_FW_DEL = 0x33 + IP_OLD_FW_FLUSH = 0x34 + IP_OLD_FW_GET = 0x36 + IP_OLD_FW_RESETLOG = 0x38 + IP_OLD_FW_ZERO = 0x35 + IP_OPTIONS = 0x1 + IP_PKTINFO = 0x1a + IP_PORTRANGE = 0x13 + IP_PORTRANGE_DEFAULT = 0x0 + IP_PORTRANGE_HIGH = 0x1 + IP_PORTRANGE_LOW = 0x2 + IP_RECVDSTADDR = 0x7 + IP_RECVIF = 0x14 + IP_RECVOPTS = 0x5 + IP_RECVPKTINFO = 0x1a + IP_RECVRETOPTS = 0x6 + IP_RECVTOS = 0x1b + IP_RECVTTL = 0x18 + IP_RETOPTS = 0x8 + IP_RF = 0x8000 + IP_RSVP_OFF = 0x10 + IP_RSVP_ON = 0xf + IP_RSVP_VIF_OFF = 0x12 + IP_RSVP_VIF_ON = 0x11 + IP_STRIPHDR = 0x17 + IP_TOS = 0x3 + IP_TRAFFIC_MGT_BACKGROUND = 0x41 + IP_TTL = 0x4 + IP_UNBLOCK_SOURCE = 0x49 + ISIG = 0x80 + ISTRIP = 0x20 + IUTF8 = 0x4000 + IXANY = 0x800 + IXOFF = 0x400 + IXON = 0x200 + KERN_HOSTNAME = 0xa + KERN_OSRELEASE = 0x2 + KERN_OSTYPE = 0x1 + KERN_VERSION = 0x4 + LOCAL_PEERCRED = 0x1 + LOCAL_PEEREPID = 0x3 + LOCAL_PEEREUUID = 0x5 + LOCAL_PEERPID = 0x2 + LOCAL_PEERTOKEN = 0x6 + LOCAL_PEERUUID = 0x4 + LOCK_EX = 0x2 + LOCK_NB = 0x4 + LOCK_SH = 0x1 + LOCK_UN = 0x8 + MADV_CAN_REUSE = 0x9 + MADV_DONTNEED = 0x4 + MADV_FREE = 0x5 + MADV_FREE_REUSABLE = 0x7 + MADV_FREE_REUSE = 0x8 + MADV_NORMAL = 0x0 + MADV_PAGEOUT = 0xa + MADV_RANDOM = 0x1 + MADV_SEQUENTIAL = 0x2 + MADV_WILLNEED = 0x3 + MADV_ZERO_WIRED_PAGES = 0x6 + MAP_32BIT = 0x8000 + MAP_ANON = 0x1000 + MAP_ANONYMOUS = 0x1000 + MAP_COPY = 0x2 + MAP_FILE = 0x0 + MAP_FIXED = 0x10 + MAP_HASSEMAPHORE = 0x200 + MAP_JIT = 0x800 + MAP_NOCACHE = 0x400 + MAP_NOEXTEND = 0x100 + MAP_NORESERVE = 0x40 + MAP_PRIVATE = 0x2 + MAP_RENAME = 0x20 + MAP_RESERVED0080 = 0x80 + MAP_RESILIENT_CODESIGN = 0x2000 + MAP_RESILIENT_MEDIA = 0x4000 + MAP_SHARED = 0x1 + MAP_TRANSLATED_ALLOW_EXECUTE = 0x20000 + MAP_UNIX03 = 0x40000 + MCAST_BLOCK_SOURCE = 0x54 + MCAST_EXCLUDE = 0x2 + MCAST_INCLUDE = 0x1 + MCAST_JOIN_GROUP = 0x50 + MCAST_JOIN_SOURCE_GROUP = 0x52 + MCAST_LEAVE_GROUP = 0x51 + MCAST_LEAVE_SOURCE_GROUP = 0x53 + MCAST_UNBLOCK_SOURCE = 0x55 + MCAST_UNDEFINED = 0x0 + MCL_CURRENT = 0x1 + MCL_FUTURE = 0x2 + MNT_ASYNC = 0x40 + MNT_AUTOMOUNTED = 0x400000 + MNT_CMDFLAGS = 0xf0000 + MNT_CPROTECT = 0x80 + MNT_DEFWRITE = 0x2000000 + MNT_DONTBROWSE = 0x100000 + MNT_DOVOLFS = 0x8000 + MNT_DWAIT = 0x4 + MNT_EXPORTED = 0x100 + MNT_EXT_ROOT_DATA_VOL = 0x1 + MNT_FORCE = 0x80000 + MNT_IGNORE_OWNERSHIP = 0x200000 + MNT_JOURNALED = 0x800000 + MNT_LOCAL = 0x1000 + MNT_MULTILABEL = 0x4000000 + MNT_NOATIME = 0x10000000 + MNT_NOBLOCK = 0x20000 + MNT_NODEV = 0x10 + MNT_NOEXEC = 0x4 + MNT_NOSUID = 0x8 + MNT_NOUSERXATTR = 0x1000000 + MNT_NOWAIT = 0x2 + MNT_QUARANTINE = 0x400 + MNT_QUOTA = 0x2000 + MNT_RDONLY = 0x1 + MNT_RELOAD = 0x40000 + MNT_REMOVABLE = 0x200 + MNT_ROOTFS = 0x4000 + MNT_SNAPSHOT = 0x40000000 + MNT_STRICTATIME = 0x80000000 + MNT_SYNCHRONOUS = 0x2 + MNT_UNION = 0x20 + MNT_UNKNOWNPERMISSIONS = 0x200000 + MNT_UPDATE = 0x10000 + MNT_VISFLAGMASK = 0xd7f0f7ff + MNT_WAIT = 0x1 + MSG_CTRUNC = 0x20 + MSG_DONTROUTE = 0x4 + MSG_DONTWAIT = 0x80 + MSG_EOF = 0x100 + MSG_EOR = 0x8 + MSG_FLUSH = 0x400 + MSG_HAVEMORE = 0x2000 + MSG_HOLD = 0x800 + MSG_NEEDSA = 0x10000 + MSG_NOSIGNAL = 0x80000 + MSG_OOB = 0x1 + MSG_PEEK = 0x2 + MSG_RCVMORE = 0x4000 + MSG_SEND = 0x1000 + MSG_TRUNC = 0x10 + MSG_WAITALL = 0x40 + MSG_WAITSTREAM = 0x200 + MS_ASYNC = 0x1 + MS_DEACTIVATE = 0x8 + MS_INVALIDATE = 0x2 + MS_KILLPAGES = 0x4 + MS_SYNC = 0x10 + NAME_MAX = 0xff + NET_RT_DUMP = 0x1 + NET_RT_DUMP2 = 0x7 + NET_RT_FLAGS = 0x2 + NET_RT_FLAGS_PRIV = 0xa + NET_RT_IFLIST = 0x3 + NET_RT_IFLIST2 = 0x6 + NET_RT_MAXID = 0xb + NET_RT_STAT = 0x4 + NET_RT_TRASH = 0x5 + NFDBITS = 0x20 + NL0 = 0x0 + NL1 = 0x100 + NL2 = 0x200 + NL3 = 0x300 + NLDLY = 0x300 + NOFLSH = 0x80000000 + NOKERNINFO = 0x2000000 + NOTE_ABSOLUTE = 0x8 + NOTE_ATTRIB = 0x8 + NOTE_BACKGROUND = 0x40 + NOTE_CHILD = 0x4 + NOTE_CRITICAL = 0x20 + NOTE_DELETE = 0x1 + NOTE_EXEC = 0x20000000 + NOTE_EXIT = 0x80000000 + NOTE_EXITSTATUS = 0x4000000 + NOTE_EXIT_CSERROR = 0x40000 + NOTE_EXIT_DECRYPTFAIL = 0x10000 + NOTE_EXIT_DETAIL = 0x2000000 + NOTE_EXIT_DETAIL_MASK = 0x70000 + NOTE_EXIT_MEMORY = 0x20000 + NOTE_EXIT_REPARENTED = 0x80000 + NOTE_EXTEND = 0x4 + NOTE_FFAND = 0x40000000 + NOTE_FFCOPY = 0xc0000000 + NOTE_FFCTRLMASK = 0xc0000000 + NOTE_FFLAGSMASK = 0xffffff + NOTE_FFNOP = 0x0 + NOTE_FFOR = 0x80000000 + NOTE_FORK = 0x40000000 + NOTE_FUNLOCK = 0x100 + NOTE_LEEWAY = 0x10 + NOTE_LINK = 0x10 + NOTE_LOWAT = 0x1 + NOTE_MACHTIME = 0x100 + NOTE_MACH_CONTINUOUS_TIME = 0x80 + NOTE_NONE = 0x80 + NOTE_NSECONDS = 0x4 + NOTE_OOB = 0x2 + NOTE_PCTRLMASK = -0x100000 + NOTE_PDATAMASK = 0xfffff + NOTE_REAP = 0x10000000 + NOTE_RENAME = 0x20 + NOTE_REVOKE = 0x40 + NOTE_SECONDS = 0x1 + NOTE_SIGNAL = 0x8000000 + NOTE_TRACK = 0x1 + NOTE_TRACKERR = 0x2 + NOTE_TRIGGER = 0x1000000 + NOTE_USECONDS = 0x2 + NOTE_VM_ERROR = 0x10000000 + NOTE_VM_PRESSURE = 0x80000000 + NOTE_VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000 + NOTE_VM_PRESSURE_TERMINATE = 0x40000000 + NOTE_WRITE = 0x2 + OCRNL = 0x10 + OFDEL = 0x20000 + OFILL = 0x80 + ONLCR = 0x2 + ONLRET = 0x40 + ONOCR = 0x20 + ONOEOT = 0x8 + OPOST = 0x1 + OXTABS = 0x4 + O_ACCMODE = 0x3 + O_ALERT = 0x20000000 + O_APPEND = 0x8 + O_ASYNC = 0x40 + O_CLOEXEC = 0x1000000 + O_CREAT = 0x200 + O_DIRECTORY = 0x100000 + O_DP_GETRAWENCRYPTED = 0x1 + O_DP_GETRAWUNENCRYPTED = 0x2 + O_DSYNC = 0x400000 + O_EVTONLY = 0x8000 + O_EXCL = 0x800 + O_EXLOCK = 0x20 + O_FSYNC = 0x80 + O_NDELAY = 0x4 + O_NOCTTY = 0x20000 + O_NOFOLLOW = 0x100 + O_NOFOLLOW_ANY = 0x20000000 + O_NONBLOCK = 0x4 + O_POPUP = 0x80000000 + O_RDONLY = 0x0 + O_RDWR = 0x2 + O_SHLOCK = 0x10 + O_SYMLINK = 0x200000 + O_SYNC = 0x80 + O_TRUNC = 0x400 + O_WRONLY = 0x1 + PARENB = 0x1000 + PARMRK = 0x8 + PARODD = 0x2000 + PENDIN = 0x20000000 + PRIO_PGRP = 0x1 + PRIO_PROCESS = 0x0 + PRIO_USER = 0x2 + PROT_EXEC = 0x4 + PROT_NONE = 0x0 + PROT_READ = 0x1 + PROT_WRITE = 0x2 + PT_ATTACH = 0xa + PT_ATTACHEXC = 0xe + PT_CONTINUE = 0x7 + PT_DENY_ATTACH = 0x1f + PT_DETACH = 0xb + PT_FIRSTMACH = 0x20 + PT_FORCEQUOTA = 0x1e + PT_KILL = 0x8 + PT_READ_D = 0x2 + PT_READ_I = 0x1 + PT_READ_U = 0x3 + PT_SIGEXC = 0xc + PT_STEP = 0x9 + PT_THUPDATE = 0xd + PT_TRACE_ME = 0x0 + PT_WRITE_D = 0x5 + PT_WRITE_I = 0x4 + PT_WRITE_U = 0x6 + RLIMIT_AS = 0x5 + RLIMIT_CORE = 0x4 + RLIMIT_CPU = 0x0 + RLIMIT_CPU_USAGE_MONITOR = 0x2 + RLIMIT_DATA = 0x2 + RLIMIT_FSIZE = 0x1 + RLIMIT_MEMLOCK = 0x6 + RLIMIT_NOFILE = 0x8 + RLIMIT_NPROC = 0x7 + RLIMIT_RSS = 0x5 + RLIMIT_STACK = 0x3 + RLIM_INFINITY = 0x7fffffffffffffff + RTAX_AUTHOR = 0x6 + RTAX_BRD = 0x7 + RTAX_DST = 0x0 + RTAX_GATEWAY = 0x1 + RTAX_GENMASK = 0x3 + RTAX_IFA = 0x5 + RTAX_IFP = 0x4 + RTAX_MAX = 0x8 + RTAX_NETMASK = 0x2 + RTA_AUTHOR = 0x40 + RTA_BRD = 0x80 + RTA_DST = 0x1 + RTA_GATEWAY = 0x2 + RTA_GENMASK = 0x8 + RTA_IFA = 0x20 + RTA_IFP = 0x10 + RTA_NETMASK = 0x4 + RTF_BLACKHOLE = 0x1000 + RTF_BROADCAST = 0x400000 + RTF_CLONING = 0x100 + RTF_CONDEMNED = 0x2000000 + RTF_DEAD = 0x20000000 + RTF_DELCLONE = 0x80 + RTF_DONE = 0x40 + RTF_DYNAMIC = 0x10 + RTF_GATEWAY = 0x2 + RTF_GLOBAL = 0x40000000 + RTF_HOST = 0x4 + RTF_IFREF = 0x4000000 + RTF_IFSCOPE = 0x1000000 + RTF_LLDATA = 0x400 + RTF_LLINFO = 0x400 + RTF_LOCAL = 0x200000 + RTF_MODIFIED = 0x20 + RTF_MULTICAST = 0x800000 + RTF_NOIFREF = 0x2000 + RTF_PINNED = 0x100000 + RTF_PRCLONING = 0x10000 + RTF_PROTO1 = 0x8000 + RTF_PROTO2 = 0x4000 + RTF_PROTO3 = 0x40000 + RTF_PROXY = 0x8000000 + RTF_REJECT = 0x8 + RTF_ROUTER = 0x10000000 + RTF_STATIC = 0x800 + RTF_UP = 0x1 + RTF_WASCLONED = 0x20000 + RTF_XRESOLVE = 0x200 + RTM_ADD = 0x1 + RTM_CHANGE = 0x3 + RTM_DELADDR = 0xd + RTM_DELETE = 0x2 + RTM_DELMADDR = 0x10 + RTM_GET = 0x4 + RTM_GET2 = 0x14 + RTM_IFINFO = 0xe + RTM_IFINFO2 = 0x12 + RTM_LOCK = 0x8 + RTM_LOSING = 0x5 + RTM_MISS = 0x7 + RTM_NEWADDR = 0xc + RTM_NEWMADDR = 0xf + RTM_NEWMADDR2 = 0x13 + RTM_OLDADD = 0x9 + RTM_OLDDEL = 0xa + RTM_REDIRECT = 0x6 + RTM_RESOLVE = 0xb + RTM_RTTUNIT = 0xf4240 + RTM_VERSION = 0x5 + RTV_EXPIRE = 0x4 + RTV_HOPCOUNT = 0x2 + RTV_MTU = 0x1 + RTV_RPIPE = 0x8 + RTV_RTT = 0x40 + RTV_RTTVAR = 0x80 + RTV_SPIPE = 0x10 + RTV_SSTHRESH = 0x20 + RUSAGE_CHILDREN = -0x1 + RUSAGE_SELF = 0x0 + SCM_CREDS = 0x3 + SCM_RIGHTS = 0x1 + SCM_TIMESTAMP = 0x2 + SCM_TIMESTAMP_MONOTONIC = 0x4 + SEEK_CUR = 0x1 + SEEK_DATA = 0x4 + SEEK_END = 0x2 + SEEK_HOLE = 0x3 + SEEK_SET = 0x0 + SHUT_RD = 0x0 + SHUT_RDWR = 0x2 + SHUT_WR = 0x1 + SIOCADDMULTI = 0x80206931 + SIOCAIFADDR = 0x8040691a + SIOCARPIPLL = 0xc0206928 + SIOCATMARK = 0x40047307 + SIOCAUTOADDR = 0xc0206926 + SIOCAUTONETMASK = 0x80206927 + SIOCDELMULTI = 0x80206932 + SIOCDIFADDR = 0x80206919 + SIOCDIFPHYADDR = 0x80206941 + SIOCGDRVSPEC = 0xc028697b + SIOCGETVLAN = 0xc020697f + SIOCGHIWAT = 0x40047301 + SIOCGIF6LOWPAN = 0xc02069c5 + SIOCGIFADDR = 0xc0206921 + SIOCGIFALTMTU = 0xc0206948 + SIOCGIFASYNCMAP = 0xc020697c + SIOCGIFBOND = 0xc0206947 + SIOCGIFBRDADDR = 0xc0206923 + SIOCGIFCAP = 0xc020695b + SIOCGIFCONF = 0xc00c6924 + SIOCGIFDEVMTU = 0xc0206944 + SIOCGIFDSTADDR = 0xc0206922 + SIOCGIFFLAGS = 0xc0206911 + SIOCGIFFUNCTIONALTYPE = 0xc02069ad + SIOCGIFGENERIC = 0xc020693a + SIOCGIFKPI = 0xc0206987 + SIOCGIFMAC = 0xc0206982 + SIOCGIFMEDIA = 0xc02c6938 + SIOCGIFMETRIC = 0xc0206917 + SIOCGIFMTU = 0xc0206933 + SIOCGIFNETMASK = 0xc0206925 + SIOCGIFPDSTADDR = 0xc0206940 + SIOCGIFPHYS = 0xc0206935 + SIOCGIFPSRCADDR = 0xc020693f + SIOCGIFSTATUS = 0xc331693d + SIOCGIFVLAN = 0xc020697f + SIOCGIFWAKEFLAGS = 0xc0206988 + SIOCGIFXMEDIA = 0xc02c6948 + SIOCGLOWAT = 0x40047303 + SIOCGPGRP = 0x40047309 + SIOCIFCREATE = 0xc0206978 + SIOCIFCREATE2 = 0xc020697a + SIOCIFDESTROY = 0x80206979 + SIOCIFGCLONERS = 0xc0106981 + SIOCRSLVMULTI = 0xc010693b + SIOCSDRVSPEC = 0x8028697b + SIOCSETVLAN = 0x8020697e + SIOCSHIWAT = 0x80047300 + SIOCSIF6LOWPAN = 0x802069c4 + SIOCSIFADDR = 0x8020690c + SIOCSIFALTMTU = 0x80206945 + SIOCSIFASYNCMAP = 0x8020697d + SIOCSIFBOND = 0x80206946 + SIOCSIFBRDADDR = 0x80206913 + SIOCSIFCAP = 0x8020695a + SIOCSIFDSTADDR = 0x8020690e + SIOCSIFFLAGS = 0x80206910 + SIOCSIFGENERIC = 0x80206939 + SIOCSIFKPI = 0x80206986 + SIOCSIFLLADDR = 0x8020693c + SIOCSIFMAC = 0x80206983 + SIOCSIFMEDIA = 0xc0206937 + SIOCSIFMETRIC = 0x80206918 + SIOCSIFMTU = 0x80206934 + SIOCSIFNETMASK = 0x80206916 + SIOCSIFPHYADDR = 0x8040693e + SIOCSIFPHYS = 0x80206936 + SIOCSIFVLAN = 0x8020697e + SIOCSLOWAT = 0x80047302 + SIOCSPGRP = 0x80047308 + SOCK_DGRAM = 0x2 + SOCK_MAXADDRLEN = 0xff + SOCK_RAW = 0x3 + SOCK_RDM = 0x4 + SOCK_SEQPACKET = 0x5 + SOCK_STREAM = 0x1 + SOL_LOCAL = 0x0 + SOL_SOCKET = 0xffff + SOMAXCONN = 0x80 + SO_ACCEPTCONN = 0x2 + SO_BROADCAST = 0x20 + SO_DEBUG = 0x1 + SO_DONTROUTE = 0x10 + SO_DONTTRUNC = 0x2000 + SO_ERROR = 0x1007 + SO_KEEPALIVE = 0x8 + SO_LABEL = 0x1010 + SO_LINGER = 0x80 + SO_LINGER_SEC = 0x1080 + SO_NETSVC_MARKING_LEVEL = 0x1119 + SO_NET_SERVICE_TYPE = 0x1116 + SO_NKE = 0x1021 + SO_NOADDRERR = 0x1023 + SO_NOSIGPIPE = 0x1022 + SO_NOTIFYCONFLICT = 0x1026 + SO_NP_EXTENSIONS = 0x1083 + SO_NREAD = 0x1020 + SO_NUMRCVPKT = 0x1112 + SO_NWRITE = 0x1024 + SO_OOBINLINE = 0x100 + SO_PEERLABEL = 0x1011 + SO_RANDOMPORT = 0x1082 + SO_RCVBUF = 0x1002 + SO_RCVLOWAT = 0x1004 + SO_RCVTIMEO = 0x1006 + SO_REUSEADDR = 0x4 + SO_REUSEPORT = 0x200 + SO_REUSESHAREUID = 0x1025 + SO_SNDBUF = 0x1001 + SO_SNDLOWAT = 0x1003 + SO_SNDTIMEO = 0x1005 + SO_TIMESTAMP = 0x400 + SO_TIMESTAMP_MONOTONIC = 0x800 + SO_TRACKER_ATTRIBUTE_FLAGS_APP_APPROVED = 0x1 + SO_TRACKER_ATTRIBUTE_FLAGS_DOMAIN_SHORT = 0x4 + SO_TRACKER_ATTRIBUTE_FLAGS_TRACKER = 0x2 + SO_TRACKER_TRANSPARENCY_VERSION = 0x3 + SO_TYPE = 0x1008 + SO_UPCALLCLOSEWAIT = 0x1027 + SO_USELOOPBACK = 0x40 + SO_WANTMORE = 0x4000 + SO_WANTOOBFLAG = 0x8000 + S_IEXEC = 0x40 + S_IFBLK = 0x6000 + S_IFCHR = 0x2000 + S_IFDIR = 0x4000 + S_IFIFO = 0x1000 + S_IFLNK = 0xa000 + S_IFMT = 0xf000 + S_IFREG = 0x8000 + S_IFSOCK = 0xc000 + S_IFWHT = 0xe000 + S_IREAD = 0x100 + S_IRGRP = 0x20 + S_IROTH = 0x4 + S_IRUSR = 0x100 + S_IRWXG = 0x38 + S_IRWXO = 0x7 + S_IRWXU = 0x1c0 + S_ISGID = 0x400 + S_ISTXT = 0x200 + S_ISUID = 0x800 + S_ISVTX = 0x200 + S_IWGRP = 0x10 + S_IWOTH = 0x2 + S_IWRITE = 0x80 + S_IWUSR = 0x80 + S_IXGRP = 0x8 + S_IXOTH = 0x1 + S_IXUSR = 0x40 + TAB0 = 0x0 + TAB1 = 0x400 + TAB2 = 0x800 + TAB3 = 0x4 + TABDLY = 0xc04 + TCIFLUSH = 0x1 + TCIOFF = 0x3 + TCIOFLUSH = 0x3 + TCION = 0x4 + TCOFLUSH = 0x2 + TCOOFF = 0x1 + TCOON = 0x2 + TCPOPT_CC = 0xb + TCPOPT_CCECHO = 0xd + TCPOPT_CCNEW = 0xc + TCPOPT_EOL = 0x0 + TCPOPT_FASTOPEN = 0x22 + TCPOPT_MAXSEG = 0x2 + TCPOPT_NOP = 0x1 + TCPOPT_SACK = 0x5 + TCPOPT_SACK_HDR = 0x1010500 + TCPOPT_SACK_PERMITTED = 0x4 + TCPOPT_SACK_PERMIT_HDR = 0x1010402 + TCPOPT_SIGNATURE = 0x13 + TCPOPT_TIMESTAMP = 0x8 + TCPOPT_TSTAMP_HDR = 0x101080a + TCPOPT_WINDOW = 0x3 + TCP_CONNECTIONTIMEOUT = 0x20 + TCP_CONNECTION_INFO = 0x106 + TCP_ENABLE_ECN = 0x104 + TCP_FASTOPEN = 0x105 + TCP_KEEPALIVE = 0x10 + TCP_KEEPCNT = 0x102 + TCP_KEEPINTVL = 0x101 + TCP_MAXHLEN = 0x3c + TCP_MAXOLEN = 0x28 + TCP_MAXSEG = 0x2 + TCP_MAXWIN = 0xffff + TCP_MAX_SACK = 0x4 + TCP_MAX_WINSHIFT = 0xe + TCP_MINMSS = 0xd8 + TCP_MSS = 0x200 + TCP_NODELAY = 0x1 + TCP_NOOPT = 0x8 + TCP_NOPUSH = 0x4 + TCP_NOTSENT_LOWAT = 0x201 + TCP_RXT_CONNDROPTIME = 0x80 + TCP_RXT_FINDROP = 0x100 + TCP_SENDMOREACKS = 0x103 + TCSAFLUSH = 0x2 + TIOCCBRK = 0x2000747a + TIOCCDTR = 0x20007478 + TIOCCONS = 0x80047462 + TIOCDCDTIMESTAMP = 0x40107458 + TIOCDRAIN = 0x2000745e + TIOCDSIMICROCODE = 0x20007455 + TIOCEXCL = 0x2000740d + TIOCEXT = 0x80047460 + TIOCFLUSH = 0x80047410 + TIOCGDRAINWAIT = 0x40047456 + TIOCGETA = 0x40487413 + TIOCGETD = 0x4004741a + TIOCGPGRP = 0x40047477 + TIOCGWINSZ = 0x40087468 + TIOCIXOFF = 0x20007480 + TIOCIXON = 0x20007481 + TIOCMBIC = 0x8004746b + TIOCMBIS = 0x8004746c + TIOCMGDTRWAIT = 0x4004745a + TIOCMGET = 0x4004746a + TIOCMODG = 0x40047403 + TIOCMODS = 0x80047404 + TIOCMSDTRWAIT = 0x8004745b + TIOCMSET = 0x8004746d + TIOCM_CAR = 0x40 + TIOCM_CD = 0x40 + TIOCM_CTS = 0x20 + TIOCM_DSR = 0x100 + TIOCM_DTR = 0x2 + TIOCM_LE = 0x1 + TIOCM_RI = 0x80 + TIOCM_RNG = 0x80 + TIOCM_RTS = 0x4 + TIOCM_SR = 0x10 + TIOCM_ST = 0x8 + TIOCNOTTY = 0x20007471 + TIOCNXCL = 0x2000740e + TIOCOUTQ = 0x40047473 + TIOCPKT = 0x80047470 + TIOCPKT_DATA = 0x0 + TIOCPKT_DOSTOP = 0x20 + TIOCPKT_FLUSHREAD = 0x1 + TIOCPKT_FLUSHWRITE = 0x2 + TIOCPKT_IOCTL = 0x40 + TIOCPKT_NOSTOP = 0x10 + TIOCPKT_START = 0x8 + TIOCPKT_STOP = 0x4 + TIOCPTYGNAME = 0x40807453 + TIOCPTYGRANT = 0x20007454 + TIOCPTYUNLK = 0x20007452 + TIOCREMOTE = 0x80047469 + TIOCSBRK = 0x2000747b + TIOCSCONS = 0x20007463 + TIOCSCTTY = 0x20007461 + TIOCSDRAINWAIT = 0x80047457 + TIOCSDTR = 0x20007479 + TIOCSETA = 0x80487414 + TIOCSETAF = 0x80487416 + TIOCSETAW = 0x80487415 + TIOCSETD = 0x8004741b + TIOCSIG = 0x2000745f + TIOCSPGRP = 0x80047476 + TIOCSTART = 0x2000746e + TIOCSTAT = 0x20007465 + TIOCSTI = 0x80017472 + TIOCSTOP = 0x2000746f + TIOCSWINSZ = 0x80087467 + TIOCTIMESTAMP = 0x40107459 + TIOCUCNTL = 0x80047466 + TOSTOP = 0x400000 + VDISCARD = 0xf + VDSUSP = 0xb + VEOF = 0x0 + VEOL = 0x1 + VEOL2 = 0x2 + VERASE = 0x3 + VINTR = 0x8 + VKILL = 0x5 + VLNEXT = 0xe + VMADDR_CID_ANY = 0xffffffff + VMADDR_CID_HOST = 0x2 + VMADDR_CID_HYPERVISOR = 0x0 + VMADDR_CID_RESERVED = 0x1 + VMADDR_PORT_ANY = 0xffffffff + VMIN = 0x10 + VM_LOADAVG = 0x2 + VM_MACHFACTOR = 0x4 + VM_MAXID = 0x6 + VM_METER = 0x1 + VM_SWAPUSAGE = 0x5 + VQUIT = 0x9 + VREPRINT = 0x6 + VSTART = 0xc + VSTATUS = 0x12 + VSTOP = 0xd + VSUSP = 0xa + VT0 = 0x0 + VT1 = 0x10000 + VTDLY = 0x10000 + VTIME = 0x11 + VWERASE = 0x4 + WCONTINUED = 0x10 + WCOREFLAG = 0x80 + WEXITED = 0x4 + WNOHANG = 0x1 + WNOWAIT = 0x20 + WORDSIZE = 0x40 + WSTOPPED = 0x8 + WUNTRACED = 0x2 + XATTR_CREATE = 0x2 + XATTR_NODEFAULT = 0x10 + XATTR_NOFOLLOW = 0x1 + XATTR_NOSECURITY = 0x8 + XATTR_REPLACE = 0x4 + XATTR_SHOWCOMPRESSION = 0x20 ) // Errors diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go index 31009d7f05..e36f5178d6 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go @@ -12,1556 +12,1582 @@ package unix import "syscall" const ( - AF_APPLETALK = 0x10 - AF_CCITT = 0xa - AF_CHAOS = 0x5 - AF_CNT = 0x15 - AF_COIP = 0x14 - AF_DATAKIT = 0x9 - AF_DECnet = 0xc - AF_DLI = 0xd - AF_E164 = 0x1c - AF_ECMA = 0x8 - AF_HYLINK = 0xf - AF_IEEE80211 = 0x25 - AF_IMPLINK = 0x3 - AF_INET = 0x2 - AF_INET6 = 0x1e - AF_IPX = 0x17 - AF_ISDN = 0x1c - AF_ISO = 0x7 - AF_LAT = 0xe - AF_LINK = 0x12 - AF_LOCAL = 0x1 - AF_MAX = 0x29 - AF_NATM = 0x1f - AF_NDRV = 0x1b - AF_NETBIOS = 0x21 - AF_NS = 0x6 - AF_OSI = 0x7 - AF_PPP = 0x22 - AF_PUP = 0x4 - AF_RESERVED_36 = 0x24 - AF_ROUTE = 0x11 - AF_SIP = 0x18 - AF_SNA = 0xb - AF_SYSTEM = 0x20 - AF_SYS_CONTROL = 0x2 - AF_UNIX = 0x1 - AF_UNSPEC = 0x0 - AF_UTUN = 0x26 - AF_VSOCK = 0x28 - ALTWERASE = 0x200 - ATTR_BIT_MAP_COUNT = 0x5 - ATTR_CMN_ACCESSMASK = 0x20000 - ATTR_CMN_ACCTIME = 0x1000 - ATTR_CMN_ADDEDTIME = 0x10000000 - ATTR_CMN_BKUPTIME = 0x2000 - ATTR_CMN_CHGTIME = 0x800 - ATTR_CMN_CRTIME = 0x200 - ATTR_CMN_DATA_PROTECT_FLAGS = 0x40000000 - ATTR_CMN_DEVID = 0x2 - ATTR_CMN_DOCUMENT_ID = 0x100000 - ATTR_CMN_ERROR = 0x20000000 - ATTR_CMN_EXTENDED_SECURITY = 0x400000 - ATTR_CMN_FILEID = 0x2000000 - ATTR_CMN_FLAGS = 0x40000 - ATTR_CMN_FNDRINFO = 0x4000 - ATTR_CMN_FSID = 0x4 - ATTR_CMN_FULLPATH = 0x8000000 - ATTR_CMN_GEN_COUNT = 0x80000 - ATTR_CMN_GRPID = 0x10000 - ATTR_CMN_GRPUUID = 0x1000000 - ATTR_CMN_MODTIME = 0x400 - ATTR_CMN_NAME = 0x1 - ATTR_CMN_NAMEDATTRCOUNT = 0x80000 - ATTR_CMN_NAMEDATTRLIST = 0x100000 - ATTR_CMN_OBJID = 0x20 - ATTR_CMN_OBJPERMANENTID = 0x40 - ATTR_CMN_OBJTAG = 0x10 - ATTR_CMN_OBJTYPE = 0x8 - ATTR_CMN_OWNERID = 0x8000 - ATTR_CMN_PARENTID = 0x4000000 - ATTR_CMN_PAROBJID = 0x80 - ATTR_CMN_RETURNED_ATTRS = 0x80000000 - ATTR_CMN_SCRIPT = 0x100 - ATTR_CMN_SETMASK = 0x51c7ff00 - ATTR_CMN_USERACCESS = 0x200000 - ATTR_CMN_UUID = 0x800000 - ATTR_CMN_VALIDMASK = 0xffffffff - ATTR_CMN_VOLSETMASK = 0x6700 - ATTR_FILE_ALLOCSIZE = 0x4 - ATTR_FILE_CLUMPSIZE = 0x10 - ATTR_FILE_DATAALLOCSIZE = 0x400 - ATTR_FILE_DATAEXTENTS = 0x800 - ATTR_FILE_DATALENGTH = 0x200 - ATTR_FILE_DEVTYPE = 0x20 - ATTR_FILE_FILETYPE = 0x40 - ATTR_FILE_FORKCOUNT = 0x80 - ATTR_FILE_FORKLIST = 0x100 - ATTR_FILE_IOBLOCKSIZE = 0x8 - ATTR_FILE_LINKCOUNT = 0x1 - ATTR_FILE_RSRCALLOCSIZE = 0x2000 - ATTR_FILE_RSRCEXTENTS = 0x4000 - ATTR_FILE_RSRCLENGTH = 0x1000 - ATTR_FILE_SETMASK = 0x20 - ATTR_FILE_TOTALSIZE = 0x2 - ATTR_FILE_VALIDMASK = 0x37ff - ATTR_VOL_ALLOCATIONCLUMP = 0x40 - ATTR_VOL_ATTRIBUTES = 0x40000000 - ATTR_VOL_CAPABILITIES = 0x20000 - ATTR_VOL_DIRCOUNT = 0x400 - ATTR_VOL_ENCODINGSUSED = 0x10000 - ATTR_VOL_FILECOUNT = 0x200 - ATTR_VOL_FSTYPE = 0x1 - ATTR_VOL_INFO = 0x80000000 - ATTR_VOL_IOBLOCKSIZE = 0x80 - ATTR_VOL_MAXOBJCOUNT = 0x800 - ATTR_VOL_MINALLOCATION = 0x20 - ATTR_VOL_MOUNTEDDEVICE = 0x8000 - ATTR_VOL_MOUNTFLAGS = 0x4000 - ATTR_VOL_MOUNTPOINT = 0x1000 - ATTR_VOL_NAME = 0x2000 - ATTR_VOL_OBJCOUNT = 0x100 - ATTR_VOL_QUOTA_SIZE = 0x10000000 - ATTR_VOL_RESERVED_SIZE = 0x20000000 - ATTR_VOL_SETMASK = 0x80002000 - ATTR_VOL_SIGNATURE = 0x2 - ATTR_VOL_SIZE = 0x4 - ATTR_VOL_SPACEAVAIL = 0x10 - ATTR_VOL_SPACEFREE = 0x8 - ATTR_VOL_UUID = 0x40000 - ATTR_VOL_VALIDMASK = 0xf007ffff - B0 = 0x0 - B110 = 0x6e - B115200 = 0x1c200 - B1200 = 0x4b0 - B134 = 0x86 - B14400 = 0x3840 - B150 = 0x96 - B1800 = 0x708 - B19200 = 0x4b00 - B200 = 0xc8 - B230400 = 0x38400 - B2400 = 0x960 - B28800 = 0x7080 - B300 = 0x12c - B38400 = 0x9600 - B4800 = 0x12c0 - B50 = 0x32 - B57600 = 0xe100 - B600 = 0x258 - B7200 = 0x1c20 - B75 = 0x4b - B76800 = 0x12c00 - B9600 = 0x2580 - BIOCFLUSH = 0x20004268 - BIOCGBLEN = 0x40044266 - BIOCGDLT = 0x4004426a - BIOCGDLTLIST = 0xc00c4279 - BIOCGETIF = 0x4020426b - BIOCGHDRCMPLT = 0x40044274 - BIOCGRSIG = 0x40044272 - BIOCGRTIMEOUT = 0x4010426e - BIOCGSEESENT = 0x40044276 - BIOCGSTATS = 0x4008426f - BIOCIMMEDIATE = 0x80044270 - BIOCPROMISC = 0x20004269 - BIOCSBLEN = 0xc0044266 - BIOCSDLT = 0x80044278 - BIOCSETF = 0x80104267 - BIOCSETFNR = 0x8010427e - BIOCSETIF = 0x8020426c - BIOCSHDRCMPLT = 0x80044275 - BIOCSRSIG = 0x80044273 - BIOCSRTIMEOUT = 0x8010426d - BIOCSSEESENT = 0x80044277 - BIOCVERSION = 0x40044271 - BPF_A = 0x10 - BPF_ABS = 0x20 - BPF_ADD = 0x0 - BPF_ALIGNMENT = 0x4 - BPF_ALU = 0x4 - BPF_AND = 0x50 - BPF_B = 0x10 - BPF_DIV = 0x30 - BPF_H = 0x8 - BPF_IMM = 0x0 - BPF_IND = 0x40 - BPF_JA = 0x0 - BPF_JEQ = 0x10 - BPF_JGE = 0x30 - BPF_JGT = 0x20 - BPF_JMP = 0x5 - BPF_JSET = 0x40 - BPF_K = 0x0 - BPF_LD = 0x0 - BPF_LDX = 0x1 - BPF_LEN = 0x80 - BPF_LSH = 0x60 - BPF_MAJOR_VERSION = 0x1 - BPF_MAXBUFSIZE = 0x80000 - BPF_MAXINSNS = 0x200 - BPF_MEM = 0x60 - BPF_MEMWORDS = 0x10 - BPF_MINBUFSIZE = 0x20 - BPF_MINOR_VERSION = 0x1 - BPF_MISC = 0x7 - BPF_MSH = 0xa0 - BPF_MUL = 0x20 - BPF_NEG = 0x80 - BPF_OR = 0x40 - BPF_RELEASE = 0x30bb6 - BPF_RET = 0x6 - BPF_RSH = 0x70 - BPF_ST = 0x2 - BPF_STX = 0x3 - BPF_SUB = 0x10 - BPF_TAX = 0x0 - BPF_TXA = 0x80 - BPF_W = 0x0 - BPF_X = 0x8 - BRKINT = 0x2 - BS0 = 0x0 - BS1 = 0x8000 - BSDLY = 0x8000 - CFLUSH = 0xf - CLOCAL = 0x8000 - CLOCK_MONOTONIC = 0x6 - CLOCK_MONOTONIC_RAW = 0x4 - CLOCK_MONOTONIC_RAW_APPROX = 0x5 - CLOCK_PROCESS_CPUTIME_ID = 0xc - CLOCK_REALTIME = 0x0 - CLOCK_THREAD_CPUTIME_ID = 0x10 - CLOCK_UPTIME_RAW = 0x8 - CLOCK_UPTIME_RAW_APPROX = 0x9 - CLONE_NOFOLLOW = 0x1 - CLONE_NOOWNERCOPY = 0x2 - CR0 = 0x0 - CR1 = 0x1000 - CR2 = 0x2000 - CR3 = 0x3000 - CRDLY = 0x3000 - CREAD = 0x800 - CRTSCTS = 0x30000 - CS5 = 0x0 - CS6 = 0x100 - CS7 = 0x200 - CS8 = 0x300 - CSIZE = 0x300 - CSTART = 0x11 - CSTATUS = 0x14 - CSTOP = 0x13 - CSTOPB = 0x400 - CSUSP = 0x1a - CTLIOCGINFO = 0xc0644e03 - CTL_HW = 0x6 - CTL_KERN = 0x1 - CTL_MAXNAME = 0xc - CTL_NET = 0x4 - DLT_A429 = 0xb8 - DLT_A653_ICM = 0xb9 - DLT_AIRONET_HEADER = 0x78 - DLT_AOS = 0xde - DLT_APPLE_IP_OVER_IEEE1394 = 0x8a - DLT_ARCNET = 0x7 - DLT_ARCNET_LINUX = 0x81 - DLT_ATM_CLIP = 0x13 - DLT_ATM_RFC1483 = 0xb - DLT_AURORA = 0x7e - DLT_AX25 = 0x3 - DLT_AX25_KISS = 0xca - DLT_BACNET_MS_TP = 0xa5 - DLT_BLUETOOTH_HCI_H4 = 0xbb - DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 0xc9 - DLT_CAN20B = 0xbe - DLT_CAN_SOCKETCAN = 0xe3 - DLT_CHAOS = 0x5 - DLT_CHDLC = 0x68 - DLT_CISCO_IOS = 0x76 - DLT_C_HDLC = 0x68 - DLT_C_HDLC_WITH_DIR = 0xcd - DLT_DBUS = 0xe7 - DLT_DECT = 0xdd - DLT_DOCSIS = 0x8f - DLT_DVB_CI = 0xeb - DLT_ECONET = 0x73 - DLT_EN10MB = 0x1 - DLT_EN3MB = 0x2 - DLT_ENC = 0x6d - DLT_ERF = 0xc5 - DLT_ERF_ETH = 0xaf - DLT_ERF_POS = 0xb0 - DLT_FC_2 = 0xe0 - DLT_FC_2_WITH_FRAME_DELIMS = 0xe1 - DLT_FDDI = 0xa - DLT_FLEXRAY = 0xd2 - DLT_FRELAY = 0x6b - DLT_FRELAY_WITH_DIR = 0xce - DLT_GCOM_SERIAL = 0xad - DLT_GCOM_T1E1 = 0xac - DLT_GPF_F = 0xab - DLT_GPF_T = 0xaa - DLT_GPRS_LLC = 0xa9 - DLT_GSMTAP_ABIS = 0xda - DLT_GSMTAP_UM = 0xd9 - DLT_HHDLC = 0x79 - DLT_IBM_SN = 0x92 - DLT_IBM_SP = 0x91 - DLT_IEEE802 = 0x6 - DLT_IEEE802_11 = 0x69 - DLT_IEEE802_11_RADIO = 0x7f - DLT_IEEE802_11_RADIO_AVS = 0xa3 - DLT_IEEE802_15_4 = 0xc3 - DLT_IEEE802_15_4_LINUX = 0xbf - DLT_IEEE802_15_4_NOFCS = 0xe6 - DLT_IEEE802_15_4_NONASK_PHY = 0xd7 - DLT_IEEE802_16_MAC_CPS = 0xbc - DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1 - DLT_IPFILTER = 0x74 - DLT_IPMB = 0xc7 - DLT_IPMB_LINUX = 0xd1 - DLT_IPNET = 0xe2 - DLT_IPOIB = 0xf2 - DLT_IPV4 = 0xe4 - DLT_IPV6 = 0xe5 - DLT_IP_OVER_FC = 0x7a - DLT_JUNIPER_ATM1 = 0x89 - DLT_JUNIPER_ATM2 = 0x87 - DLT_JUNIPER_ATM_CEMIC = 0xee - DLT_JUNIPER_CHDLC = 0xb5 - DLT_JUNIPER_ES = 0x84 - DLT_JUNIPER_ETHER = 0xb2 - DLT_JUNIPER_FIBRECHANNEL = 0xea - DLT_JUNIPER_FRELAY = 0xb4 - DLT_JUNIPER_GGSN = 0x85 - DLT_JUNIPER_ISM = 0xc2 - DLT_JUNIPER_MFR = 0x86 - DLT_JUNIPER_MLFR = 0x83 - DLT_JUNIPER_MLPPP = 0x82 - DLT_JUNIPER_MONITOR = 0xa4 - DLT_JUNIPER_PIC_PEER = 0xae - DLT_JUNIPER_PPP = 0xb3 - DLT_JUNIPER_PPPOE = 0xa7 - DLT_JUNIPER_PPPOE_ATM = 0xa8 - DLT_JUNIPER_SERVICES = 0x88 - DLT_JUNIPER_SRX_E2E = 0xe9 - DLT_JUNIPER_ST = 0xc8 - DLT_JUNIPER_VP = 0xb7 - DLT_JUNIPER_VS = 0xe8 - DLT_LAPB_WITH_DIR = 0xcf - DLT_LAPD = 0xcb - DLT_LIN = 0xd4 - DLT_LINUX_EVDEV = 0xd8 - DLT_LINUX_IRDA = 0x90 - DLT_LINUX_LAPD = 0xb1 - DLT_LINUX_PPP_WITHDIRECTION = 0xa6 - DLT_LINUX_SLL = 0x71 - DLT_LOOP = 0x6c - DLT_LTALK = 0x72 - DLT_MATCHING_MAX = 0x10a - DLT_MATCHING_MIN = 0x68 - DLT_MFR = 0xb6 - DLT_MOST = 0xd3 - DLT_MPEG_2_TS = 0xf3 - DLT_MPLS = 0xdb - DLT_MTP2 = 0x8c - DLT_MTP2_WITH_PHDR = 0x8b - DLT_MTP3 = 0x8d - DLT_MUX27010 = 0xec - DLT_NETANALYZER = 0xf0 - DLT_NETANALYZER_TRANSPARENT = 0xf1 - DLT_NFC_LLCP = 0xf5 - DLT_NFLOG = 0xef - DLT_NG40 = 0xf4 - DLT_NULL = 0x0 - DLT_PCI_EXP = 0x7d - DLT_PFLOG = 0x75 - DLT_PFSYNC = 0x12 - DLT_PPI = 0xc0 - DLT_PPP = 0x9 - DLT_PPP_BSDOS = 0x10 - DLT_PPP_ETHER = 0x33 - DLT_PPP_PPPD = 0xa6 - DLT_PPP_SERIAL = 0x32 - DLT_PPP_WITH_DIR = 0xcc - DLT_PPP_WITH_DIRECTION = 0xa6 - DLT_PRISM_HEADER = 0x77 - DLT_PRONET = 0x4 - DLT_RAIF1 = 0xc6 - DLT_RAW = 0xc - DLT_RIO = 0x7c - DLT_SCCP = 0x8e - DLT_SITA = 0xc4 - DLT_SLIP = 0x8 - DLT_SLIP_BSDOS = 0xf - DLT_STANAG_5066_D_PDU = 0xed - DLT_SUNATM = 0x7b - DLT_SYMANTEC_FIREWALL = 0x63 - DLT_TZSP = 0x80 - DLT_USB = 0xba - DLT_USB_DARWIN = 0x10a - DLT_USB_LINUX = 0xbd - DLT_USB_LINUX_MMAPPED = 0xdc - DLT_USER0 = 0x93 - DLT_USER1 = 0x94 - DLT_USER10 = 0x9d - DLT_USER11 = 0x9e - DLT_USER12 = 0x9f - DLT_USER13 = 0xa0 - DLT_USER14 = 0xa1 - DLT_USER15 = 0xa2 - DLT_USER2 = 0x95 - DLT_USER3 = 0x96 - DLT_USER4 = 0x97 - DLT_USER5 = 0x98 - DLT_USER6 = 0x99 - DLT_USER7 = 0x9a - DLT_USER8 = 0x9b - DLT_USER9 = 0x9c - DLT_WIHART = 0xdf - DLT_X2E_SERIAL = 0xd5 - DLT_X2E_XORAYA = 0xd6 - DT_BLK = 0x6 - DT_CHR = 0x2 - DT_DIR = 0x4 - DT_FIFO = 0x1 - DT_LNK = 0xa - DT_REG = 0x8 - DT_SOCK = 0xc - DT_UNKNOWN = 0x0 - DT_WHT = 0xe - ECHO = 0x8 - ECHOCTL = 0x40 - ECHOE = 0x2 - ECHOK = 0x4 - ECHOKE = 0x1 - ECHONL = 0x10 - ECHOPRT = 0x20 - EVFILT_AIO = -0x3 - EVFILT_EXCEPT = -0xf - EVFILT_FS = -0x9 - EVFILT_MACHPORT = -0x8 - EVFILT_PROC = -0x5 - EVFILT_READ = -0x1 - EVFILT_SIGNAL = -0x6 - EVFILT_SYSCOUNT = 0x11 - EVFILT_THREADMARKER = 0x11 - EVFILT_TIMER = -0x7 - EVFILT_USER = -0xa - EVFILT_VM = -0xc - EVFILT_VNODE = -0x4 - EVFILT_WRITE = -0x2 - EV_ADD = 0x1 - EV_CLEAR = 0x20 - EV_DELETE = 0x2 - EV_DISABLE = 0x8 - EV_DISPATCH = 0x80 - EV_DISPATCH2 = 0x180 - EV_ENABLE = 0x4 - EV_EOF = 0x8000 - EV_ERROR = 0x4000 - EV_FLAG0 = 0x1000 - EV_FLAG1 = 0x2000 - EV_ONESHOT = 0x10 - EV_OOBAND = 0x2000 - EV_POLL = 0x1000 - EV_RECEIPT = 0x40 - EV_SYSFLAGS = 0xf000 - EV_UDATA_SPECIFIC = 0x100 - EV_VANISHED = 0x200 - EXTA = 0x4b00 - EXTB = 0x9600 - EXTPROC = 0x800 - FD_CLOEXEC = 0x1 - FD_SETSIZE = 0x400 - FF0 = 0x0 - FF1 = 0x4000 - FFDLY = 0x4000 - FLUSHO = 0x800000 - FSOPT_ATTR_CMN_EXTENDED = 0x20 - FSOPT_NOFOLLOW = 0x1 - FSOPT_NOINMEMUPDATE = 0x2 - FSOPT_PACK_INVAL_ATTRS = 0x8 - FSOPT_REPORT_FULLSIZE = 0x4 - FSOPT_RETURN_REALDEV = 0x200 - F_ADDFILESIGS = 0x3d - F_ADDFILESIGS_FOR_DYLD_SIM = 0x53 - F_ADDFILESIGS_INFO = 0x67 - F_ADDFILESIGS_RETURN = 0x61 - F_ADDFILESUPPL = 0x68 - F_ADDSIGS = 0x3b - F_ALLOCATEALL = 0x4 - F_ALLOCATECONTIG = 0x2 - F_BARRIERFSYNC = 0x55 - F_CHECK_LV = 0x62 - F_CHKCLEAN = 0x29 - F_DUPFD = 0x0 - F_DUPFD_CLOEXEC = 0x43 - F_FINDSIGS = 0x4e - F_FLUSH_DATA = 0x28 - F_FREEZE_FS = 0x35 - F_FULLFSYNC = 0x33 - F_GETCODEDIR = 0x48 - F_GETFD = 0x1 - F_GETFL = 0x3 - F_GETLK = 0x7 - F_GETLKPID = 0x42 - F_GETNOSIGPIPE = 0x4a - F_GETOWN = 0x5 - F_GETPATH = 0x32 - F_GETPATH_MTMINFO = 0x47 - F_GETPATH_NOFIRMLINK = 0x66 - F_GETPROTECTIONCLASS = 0x3f - F_GETPROTECTIONLEVEL = 0x4d - F_GETSIGSINFO = 0x69 - F_GLOBAL_NOCACHE = 0x37 - F_LOG2PHYS = 0x31 - F_LOG2PHYS_EXT = 0x41 - F_NOCACHE = 0x30 - F_NODIRECT = 0x3e - F_OK = 0x0 - F_PATHPKG_CHECK = 0x34 - F_PEOFPOSMODE = 0x3 - F_PREALLOCATE = 0x2a - F_PUNCHHOLE = 0x63 - F_RDADVISE = 0x2c - F_RDAHEAD = 0x2d - F_RDLCK = 0x1 - F_SETBACKINGSTORE = 0x46 - F_SETFD = 0x2 - F_SETFL = 0x4 - F_SETLK = 0x8 - F_SETLKW = 0x9 - F_SETLKWTIMEOUT = 0xa - F_SETNOSIGPIPE = 0x49 - F_SETOWN = 0x6 - F_SETPROTECTIONCLASS = 0x40 - F_SETSIZE = 0x2b - F_SINGLE_WRITER = 0x4c - F_SPECULATIVE_READ = 0x65 - F_THAW_FS = 0x36 - F_TRANSCODEKEY = 0x4b - F_TRIM_ACTIVE_FILE = 0x64 - F_UNLCK = 0x2 - F_VOLPOSMODE = 0x4 - F_WRLCK = 0x3 - HUPCL = 0x4000 - HW_MACHINE = 0x1 - ICANON = 0x100 - ICMP6_FILTER = 0x12 - ICRNL = 0x100 - IEXTEN = 0x400 - IFF_ALLMULTI = 0x200 - IFF_ALTPHYS = 0x4000 - IFF_BROADCAST = 0x2 - IFF_DEBUG = 0x4 - IFF_LINK0 = 0x1000 - IFF_LINK1 = 0x2000 - IFF_LINK2 = 0x4000 - IFF_LOOPBACK = 0x8 - IFF_MULTICAST = 0x8000 - IFF_NOARP = 0x80 - IFF_NOTRAILERS = 0x20 - IFF_OACTIVE = 0x400 - IFF_POINTOPOINT = 0x10 - IFF_PROMISC = 0x100 - IFF_RUNNING = 0x40 - IFF_SIMPLEX = 0x800 - IFF_UP = 0x1 - IFNAMSIZ = 0x10 - IFT_1822 = 0x2 - IFT_6LOWPAN = 0x40 - IFT_AAL5 = 0x31 - IFT_ARCNET = 0x23 - IFT_ARCNETPLUS = 0x24 - IFT_ATM = 0x25 - IFT_BRIDGE = 0xd1 - IFT_CARP = 0xf8 - IFT_CELLULAR = 0xff - IFT_CEPT = 0x13 - IFT_DS3 = 0x1e - IFT_ENC = 0xf4 - IFT_EON = 0x19 - IFT_ETHER = 0x6 - IFT_FAITH = 0x38 - IFT_FDDI = 0xf - IFT_FRELAY = 0x20 - IFT_FRELAYDCE = 0x2c - IFT_GIF = 0x37 - IFT_HDH1822 = 0x3 - IFT_HIPPI = 0x2f - IFT_HSSI = 0x2e - IFT_HY = 0xe - IFT_IEEE1394 = 0x90 - IFT_IEEE8023ADLAG = 0x88 - IFT_ISDNBASIC = 0x14 - IFT_ISDNPRIMARY = 0x15 - IFT_ISO88022LLC = 0x29 - IFT_ISO88023 = 0x7 - IFT_ISO88024 = 0x8 - IFT_ISO88025 = 0x9 - IFT_ISO88026 = 0xa - IFT_L2VLAN = 0x87 - IFT_LAPB = 0x10 - IFT_LOCALTALK = 0x2a - IFT_LOOP = 0x18 - IFT_MIOX25 = 0x26 - IFT_MODEM = 0x30 - IFT_NSIP = 0x1b - IFT_OTHER = 0x1 - IFT_P10 = 0xc - IFT_P80 = 0xd - IFT_PARA = 0x22 - IFT_PDP = 0xff - IFT_PFLOG = 0xf5 - IFT_PFSYNC = 0xf6 - IFT_PKTAP = 0xfe - IFT_PPP = 0x17 - IFT_PROPMUX = 0x36 - IFT_PROPVIRTUAL = 0x35 - IFT_PTPSERIAL = 0x16 - IFT_RS232 = 0x21 - IFT_SDLC = 0x11 - IFT_SIP = 0x1f - IFT_SLIP = 0x1c - IFT_SMDSDXI = 0x2b - IFT_SMDSICIP = 0x34 - IFT_SONET = 0x27 - IFT_SONETPATH = 0x32 - IFT_SONETVT = 0x33 - IFT_STARLAN = 0xb - IFT_STF = 0x39 - IFT_T1 = 0x12 - IFT_ULTRA = 0x1d - IFT_V35 = 0x2d - IFT_X25 = 0x5 - IFT_X25DDN = 0x4 - IFT_X25PLE = 0x28 - IFT_XETHER = 0x1a - IGNBRK = 0x1 - IGNCR = 0x80 - IGNPAR = 0x4 - IMAXBEL = 0x2000 - INLCR = 0x40 - INPCK = 0x10 - IN_CLASSA_HOST = 0xffffff - IN_CLASSA_MAX = 0x80 - IN_CLASSA_NET = 0xff000000 - IN_CLASSA_NSHIFT = 0x18 - IN_CLASSB_HOST = 0xffff - IN_CLASSB_MAX = 0x10000 - IN_CLASSB_NET = 0xffff0000 - IN_CLASSB_NSHIFT = 0x10 - IN_CLASSC_HOST = 0xff - IN_CLASSC_NET = 0xffffff00 - IN_CLASSC_NSHIFT = 0x8 - IN_CLASSD_HOST = 0xfffffff - IN_CLASSD_NET = 0xf0000000 - IN_CLASSD_NSHIFT = 0x1c - IN_LINKLOCALNETNUM = 0xa9fe0000 - IN_LOOPBACKNET = 0x7f - IPPROTO_3PC = 0x22 - IPPROTO_ADFS = 0x44 - IPPROTO_AH = 0x33 - IPPROTO_AHIP = 0x3d - IPPROTO_APES = 0x63 - IPPROTO_ARGUS = 0xd - IPPROTO_AX25 = 0x5d - IPPROTO_BHA = 0x31 - IPPROTO_BLT = 0x1e - IPPROTO_BRSATMON = 0x4c - IPPROTO_CFTP = 0x3e - IPPROTO_CHAOS = 0x10 - IPPROTO_CMTP = 0x26 - IPPROTO_CPHB = 0x49 - IPPROTO_CPNX = 0x48 - IPPROTO_DDP = 0x25 - IPPROTO_DGP = 0x56 - IPPROTO_DIVERT = 0xfe - IPPROTO_DONE = 0x101 - IPPROTO_DSTOPTS = 0x3c - IPPROTO_EGP = 0x8 - IPPROTO_EMCON = 0xe - IPPROTO_ENCAP = 0x62 - IPPROTO_EON = 0x50 - IPPROTO_ESP = 0x32 - IPPROTO_ETHERIP = 0x61 - IPPROTO_FRAGMENT = 0x2c - IPPROTO_GGP = 0x3 - IPPROTO_GMTP = 0x64 - IPPROTO_GRE = 0x2f - IPPROTO_HELLO = 0x3f - IPPROTO_HMP = 0x14 - IPPROTO_HOPOPTS = 0x0 - IPPROTO_ICMP = 0x1 - IPPROTO_ICMPV6 = 0x3a - IPPROTO_IDP = 0x16 - IPPROTO_IDPR = 0x23 - IPPROTO_IDRP = 0x2d - IPPROTO_IGMP = 0x2 - IPPROTO_IGP = 0x55 - IPPROTO_IGRP = 0x58 - IPPROTO_IL = 0x28 - IPPROTO_INLSP = 0x34 - IPPROTO_INP = 0x20 - IPPROTO_IP = 0x0 - IPPROTO_IPCOMP = 0x6c - IPPROTO_IPCV = 0x47 - IPPROTO_IPEIP = 0x5e - IPPROTO_IPIP = 0x4 - IPPROTO_IPPC = 0x43 - IPPROTO_IPV4 = 0x4 - IPPROTO_IPV6 = 0x29 - IPPROTO_IRTP = 0x1c - IPPROTO_KRYPTOLAN = 0x41 - IPPROTO_LARP = 0x5b - IPPROTO_LEAF1 = 0x19 - IPPROTO_LEAF2 = 0x1a - IPPROTO_MAX = 0x100 - IPPROTO_MAXID = 0x34 - IPPROTO_MEAS = 0x13 - IPPROTO_MHRP = 0x30 - IPPROTO_MICP = 0x5f - IPPROTO_MTP = 0x5c - IPPROTO_MUX = 0x12 - IPPROTO_ND = 0x4d - IPPROTO_NHRP = 0x36 - IPPROTO_NONE = 0x3b - IPPROTO_NSP = 0x1f - IPPROTO_NVPII = 0xb - IPPROTO_OSPFIGP = 0x59 - IPPROTO_PGM = 0x71 - IPPROTO_PIGP = 0x9 - IPPROTO_PIM = 0x67 - IPPROTO_PRM = 0x15 - IPPROTO_PUP = 0xc - IPPROTO_PVP = 0x4b - IPPROTO_RAW = 0xff - IPPROTO_RCCMON = 0xa - IPPROTO_RDP = 0x1b - IPPROTO_ROUTING = 0x2b - IPPROTO_RSVP = 0x2e - IPPROTO_RVD = 0x42 - IPPROTO_SATEXPAK = 0x40 - IPPROTO_SATMON = 0x45 - IPPROTO_SCCSP = 0x60 - IPPROTO_SCTP = 0x84 - IPPROTO_SDRP = 0x2a - IPPROTO_SEP = 0x21 - IPPROTO_SRPC = 0x5a - IPPROTO_ST = 0x7 - IPPROTO_SVMTP = 0x52 - IPPROTO_SWIPE = 0x35 - IPPROTO_TCF = 0x57 - IPPROTO_TCP = 0x6 - IPPROTO_TP = 0x1d - IPPROTO_TPXX = 0x27 - IPPROTO_TRUNK1 = 0x17 - IPPROTO_TRUNK2 = 0x18 - IPPROTO_TTP = 0x54 - IPPROTO_UDP = 0x11 - IPPROTO_VINES = 0x53 - IPPROTO_VISA = 0x46 - IPPROTO_VMTP = 0x51 - IPPROTO_WBEXPAK = 0x4f - IPPROTO_WBMON = 0x4e - IPPROTO_WSN = 0x4a - IPPROTO_XNET = 0xf - IPPROTO_XTP = 0x24 - IPV6_2292DSTOPTS = 0x17 - IPV6_2292HOPLIMIT = 0x14 - IPV6_2292HOPOPTS = 0x16 - IPV6_2292NEXTHOP = 0x15 - IPV6_2292PKTINFO = 0x13 - IPV6_2292PKTOPTIONS = 0x19 - IPV6_2292RTHDR = 0x18 - IPV6_3542DSTOPTS = 0x32 - IPV6_3542HOPLIMIT = 0x2f - IPV6_3542HOPOPTS = 0x31 - IPV6_3542NEXTHOP = 0x30 - IPV6_3542PKTINFO = 0x2e - IPV6_3542RTHDR = 0x33 - IPV6_ADDR_MC_FLAGS_PREFIX = 0x20 - IPV6_ADDR_MC_FLAGS_TRANSIENT = 0x10 - IPV6_ADDR_MC_FLAGS_UNICAST_BASED = 0x30 - IPV6_AUTOFLOWLABEL = 0x3b - IPV6_BINDV6ONLY = 0x1b - IPV6_BOUND_IF = 0x7d - IPV6_CHECKSUM = 0x1a - IPV6_DEFAULT_MULTICAST_HOPS = 0x1 - IPV6_DEFAULT_MULTICAST_LOOP = 0x1 - IPV6_DEFHLIM = 0x40 - IPV6_DONTFRAG = 0x3e - IPV6_DSTOPTS = 0x32 - IPV6_FAITH = 0x1d - IPV6_FLOWINFO_MASK = 0xffffff0f - IPV6_FLOWLABEL_MASK = 0xffff0f00 - IPV6_FLOW_ECN_MASK = 0x3000 - IPV6_FRAGTTL = 0x3c - IPV6_FW_ADD = 0x1e - IPV6_FW_DEL = 0x1f - IPV6_FW_FLUSH = 0x20 - IPV6_FW_GET = 0x22 - IPV6_FW_ZERO = 0x21 - IPV6_HLIMDEC = 0x1 - IPV6_HOPLIMIT = 0x2f - IPV6_HOPOPTS = 0x31 - IPV6_IPSEC_POLICY = 0x1c - IPV6_JOIN_GROUP = 0xc - IPV6_LEAVE_GROUP = 0xd - IPV6_MAXHLIM = 0xff - IPV6_MAXOPTHDR = 0x800 - IPV6_MAXPACKET = 0xffff - IPV6_MAX_GROUP_SRC_FILTER = 0x200 - IPV6_MAX_MEMBERSHIPS = 0xfff - IPV6_MAX_SOCK_SRC_FILTER = 0x80 - IPV6_MIN_MEMBERSHIPS = 0x1f - IPV6_MMTU = 0x500 - IPV6_MSFILTER = 0x4a - IPV6_MULTICAST_HOPS = 0xa - IPV6_MULTICAST_IF = 0x9 - IPV6_MULTICAST_LOOP = 0xb - IPV6_NEXTHOP = 0x30 - IPV6_PATHMTU = 0x2c - IPV6_PKTINFO = 0x2e - IPV6_PORTRANGE = 0xe - IPV6_PORTRANGE_DEFAULT = 0x0 - IPV6_PORTRANGE_HIGH = 0x1 - IPV6_PORTRANGE_LOW = 0x2 - IPV6_PREFER_TEMPADDR = 0x3f - IPV6_RECVDSTOPTS = 0x28 - IPV6_RECVHOPLIMIT = 0x25 - IPV6_RECVHOPOPTS = 0x27 - IPV6_RECVPATHMTU = 0x2b - IPV6_RECVPKTINFO = 0x3d - IPV6_RECVRTHDR = 0x26 - IPV6_RECVTCLASS = 0x23 - IPV6_RTHDR = 0x33 - IPV6_RTHDRDSTOPTS = 0x39 - IPV6_RTHDR_LOOSE = 0x0 - IPV6_RTHDR_STRICT = 0x1 - IPV6_RTHDR_TYPE_0 = 0x0 - IPV6_SOCKOPT_RESERVED1 = 0x3 - IPV6_TCLASS = 0x24 - IPV6_UNICAST_HOPS = 0x4 - IPV6_USE_MIN_MTU = 0x2a - IPV6_V6ONLY = 0x1b - IPV6_VERSION = 0x60 - IPV6_VERSION_MASK = 0xf0 - IP_ADD_MEMBERSHIP = 0xc - IP_ADD_SOURCE_MEMBERSHIP = 0x46 - IP_BLOCK_SOURCE = 0x48 - IP_BOUND_IF = 0x19 - IP_DEFAULT_MULTICAST_LOOP = 0x1 - IP_DEFAULT_MULTICAST_TTL = 0x1 - IP_DF = 0x4000 - IP_DONTFRAG = 0x1c - IP_DROP_MEMBERSHIP = 0xd - IP_DROP_SOURCE_MEMBERSHIP = 0x47 - IP_DUMMYNET_CONFIGURE = 0x3c - IP_DUMMYNET_DEL = 0x3d - IP_DUMMYNET_FLUSH = 0x3e - IP_DUMMYNET_GET = 0x40 - IP_FAITH = 0x16 - IP_FW_ADD = 0x28 - IP_FW_DEL = 0x29 - IP_FW_FLUSH = 0x2a - IP_FW_GET = 0x2c - IP_FW_RESETLOG = 0x2d - IP_FW_ZERO = 0x2b - IP_HDRINCL = 0x2 - IP_IPSEC_POLICY = 0x15 - IP_MAXPACKET = 0xffff - IP_MAX_GROUP_SRC_FILTER = 0x200 - IP_MAX_MEMBERSHIPS = 0xfff - IP_MAX_SOCK_MUTE_FILTER = 0x80 - IP_MAX_SOCK_SRC_FILTER = 0x80 - IP_MF = 0x2000 - IP_MIN_MEMBERSHIPS = 0x1f - IP_MSFILTER = 0x4a - IP_MSS = 0x240 - IP_MULTICAST_IF = 0x9 - IP_MULTICAST_IFINDEX = 0x42 - IP_MULTICAST_LOOP = 0xb - IP_MULTICAST_TTL = 0xa - IP_MULTICAST_VIF = 0xe - IP_NAT__XXX = 0x37 - IP_OFFMASK = 0x1fff - IP_OLD_FW_ADD = 0x32 - IP_OLD_FW_DEL = 0x33 - IP_OLD_FW_FLUSH = 0x34 - IP_OLD_FW_GET = 0x36 - IP_OLD_FW_RESETLOG = 0x38 - IP_OLD_FW_ZERO = 0x35 - IP_OPTIONS = 0x1 - IP_PKTINFO = 0x1a - IP_PORTRANGE = 0x13 - IP_PORTRANGE_DEFAULT = 0x0 - IP_PORTRANGE_HIGH = 0x1 - IP_PORTRANGE_LOW = 0x2 - IP_RECVDSTADDR = 0x7 - IP_RECVIF = 0x14 - IP_RECVOPTS = 0x5 - IP_RECVPKTINFO = 0x1a - IP_RECVRETOPTS = 0x6 - IP_RECVTOS = 0x1b - IP_RECVTTL = 0x18 - IP_RETOPTS = 0x8 - IP_RF = 0x8000 - IP_RSVP_OFF = 0x10 - IP_RSVP_ON = 0xf - IP_RSVP_VIF_OFF = 0x12 - IP_RSVP_VIF_ON = 0x11 - IP_STRIPHDR = 0x17 - IP_TOS = 0x3 - IP_TRAFFIC_MGT_BACKGROUND = 0x41 - IP_TTL = 0x4 - IP_UNBLOCK_SOURCE = 0x49 - ISIG = 0x80 - ISTRIP = 0x20 - IUTF8 = 0x4000 - IXANY = 0x800 - IXOFF = 0x400 - IXON = 0x200 - KERN_HOSTNAME = 0xa - KERN_OSRELEASE = 0x2 - KERN_OSTYPE = 0x1 - KERN_VERSION = 0x4 - LOCAL_PEERCRED = 0x1 - LOCAL_PEEREPID = 0x3 - LOCAL_PEEREUUID = 0x5 - LOCAL_PEERPID = 0x2 - LOCAL_PEERTOKEN = 0x6 - LOCAL_PEERUUID = 0x4 - LOCK_EX = 0x2 - LOCK_NB = 0x4 - LOCK_SH = 0x1 - LOCK_UN = 0x8 - MADV_CAN_REUSE = 0x9 - MADV_DONTNEED = 0x4 - MADV_FREE = 0x5 - MADV_FREE_REUSABLE = 0x7 - MADV_FREE_REUSE = 0x8 - MADV_NORMAL = 0x0 - MADV_PAGEOUT = 0xa - MADV_RANDOM = 0x1 - MADV_SEQUENTIAL = 0x2 - MADV_WILLNEED = 0x3 - MADV_ZERO_WIRED_PAGES = 0x6 - MAP_32BIT = 0x8000 - MAP_ANON = 0x1000 - MAP_ANONYMOUS = 0x1000 - MAP_COPY = 0x2 - MAP_FILE = 0x0 - MAP_FIXED = 0x10 - MAP_HASSEMAPHORE = 0x200 - MAP_JIT = 0x800 - MAP_NOCACHE = 0x400 - MAP_NOEXTEND = 0x100 - MAP_NORESERVE = 0x40 - MAP_PRIVATE = 0x2 - MAP_RENAME = 0x20 - MAP_RESERVED0080 = 0x80 - MAP_RESILIENT_CODESIGN = 0x2000 - MAP_RESILIENT_MEDIA = 0x4000 - MAP_SHARED = 0x1 - MAP_TRANSLATED_ALLOW_EXECUTE = 0x20000 - MAP_UNIX03 = 0x40000 - MCAST_BLOCK_SOURCE = 0x54 - MCAST_EXCLUDE = 0x2 - MCAST_INCLUDE = 0x1 - MCAST_JOIN_GROUP = 0x50 - MCAST_JOIN_SOURCE_GROUP = 0x52 - MCAST_LEAVE_GROUP = 0x51 - MCAST_LEAVE_SOURCE_GROUP = 0x53 - MCAST_UNBLOCK_SOURCE = 0x55 - MCAST_UNDEFINED = 0x0 - MCL_CURRENT = 0x1 - MCL_FUTURE = 0x2 - MNT_ASYNC = 0x40 - MNT_AUTOMOUNTED = 0x400000 - MNT_CMDFLAGS = 0xf0000 - MNT_CPROTECT = 0x80 - MNT_DEFWRITE = 0x2000000 - MNT_DONTBROWSE = 0x100000 - MNT_DOVOLFS = 0x8000 - MNT_DWAIT = 0x4 - MNT_EXPORTED = 0x100 - MNT_EXT_ROOT_DATA_VOL = 0x1 - MNT_FORCE = 0x80000 - MNT_IGNORE_OWNERSHIP = 0x200000 - MNT_JOURNALED = 0x800000 - MNT_LOCAL = 0x1000 - MNT_MULTILABEL = 0x4000000 - MNT_NOATIME = 0x10000000 - MNT_NOBLOCK = 0x20000 - MNT_NODEV = 0x10 - MNT_NOEXEC = 0x4 - MNT_NOSUID = 0x8 - MNT_NOUSERXATTR = 0x1000000 - MNT_NOWAIT = 0x2 - MNT_QUARANTINE = 0x400 - MNT_QUOTA = 0x2000 - MNT_RDONLY = 0x1 - MNT_RELOAD = 0x40000 - MNT_REMOVABLE = 0x200 - MNT_ROOTFS = 0x4000 - MNT_SNAPSHOT = 0x40000000 - MNT_STRICTATIME = 0x80000000 - MNT_SYNCHRONOUS = 0x2 - MNT_UNION = 0x20 - MNT_UNKNOWNPERMISSIONS = 0x200000 - MNT_UPDATE = 0x10000 - MNT_VISFLAGMASK = 0xd7f0f7ff - MNT_WAIT = 0x1 - MSG_CTRUNC = 0x20 - MSG_DONTROUTE = 0x4 - MSG_DONTWAIT = 0x80 - MSG_EOF = 0x100 - MSG_EOR = 0x8 - MSG_FLUSH = 0x400 - MSG_HAVEMORE = 0x2000 - MSG_HOLD = 0x800 - MSG_NEEDSA = 0x10000 - MSG_NOSIGNAL = 0x80000 - MSG_OOB = 0x1 - MSG_PEEK = 0x2 - MSG_RCVMORE = 0x4000 - MSG_SEND = 0x1000 - MSG_TRUNC = 0x10 - MSG_WAITALL = 0x40 - MSG_WAITSTREAM = 0x200 - MS_ASYNC = 0x1 - MS_DEACTIVATE = 0x8 - MS_INVALIDATE = 0x2 - MS_KILLPAGES = 0x4 - MS_SYNC = 0x10 - NAME_MAX = 0xff - NET_RT_DUMP = 0x1 - NET_RT_DUMP2 = 0x7 - NET_RT_FLAGS = 0x2 - NET_RT_FLAGS_PRIV = 0xa - NET_RT_IFLIST = 0x3 - NET_RT_IFLIST2 = 0x6 - NET_RT_MAXID = 0xb - NET_RT_STAT = 0x4 - NET_RT_TRASH = 0x5 - NFDBITS = 0x20 - NL0 = 0x0 - NL1 = 0x100 - NL2 = 0x200 - NL3 = 0x300 - NLDLY = 0x300 - NOFLSH = 0x80000000 - NOKERNINFO = 0x2000000 - NOTE_ABSOLUTE = 0x8 - NOTE_ATTRIB = 0x8 - NOTE_BACKGROUND = 0x40 - NOTE_CHILD = 0x4 - NOTE_CRITICAL = 0x20 - NOTE_DELETE = 0x1 - NOTE_EXEC = 0x20000000 - NOTE_EXIT = 0x80000000 - NOTE_EXITSTATUS = 0x4000000 - NOTE_EXIT_CSERROR = 0x40000 - NOTE_EXIT_DECRYPTFAIL = 0x10000 - NOTE_EXIT_DETAIL = 0x2000000 - NOTE_EXIT_DETAIL_MASK = 0x70000 - NOTE_EXIT_MEMORY = 0x20000 - NOTE_EXIT_REPARENTED = 0x80000 - NOTE_EXTEND = 0x4 - NOTE_FFAND = 0x40000000 - NOTE_FFCOPY = 0xc0000000 - NOTE_FFCTRLMASK = 0xc0000000 - NOTE_FFLAGSMASK = 0xffffff - NOTE_FFNOP = 0x0 - NOTE_FFOR = 0x80000000 - NOTE_FORK = 0x40000000 - NOTE_FUNLOCK = 0x100 - NOTE_LEEWAY = 0x10 - NOTE_LINK = 0x10 - NOTE_LOWAT = 0x1 - NOTE_MACHTIME = 0x100 - NOTE_MACH_CONTINUOUS_TIME = 0x80 - NOTE_NONE = 0x80 - NOTE_NSECONDS = 0x4 - NOTE_OOB = 0x2 - NOTE_PCTRLMASK = -0x100000 - NOTE_PDATAMASK = 0xfffff - NOTE_REAP = 0x10000000 - NOTE_RENAME = 0x20 - NOTE_REVOKE = 0x40 - NOTE_SECONDS = 0x1 - NOTE_SIGNAL = 0x8000000 - NOTE_TRACK = 0x1 - NOTE_TRACKERR = 0x2 - NOTE_TRIGGER = 0x1000000 - NOTE_USECONDS = 0x2 - NOTE_VM_ERROR = 0x10000000 - NOTE_VM_PRESSURE = 0x80000000 - NOTE_VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000 - NOTE_VM_PRESSURE_TERMINATE = 0x40000000 - NOTE_WRITE = 0x2 - OCRNL = 0x10 - OFDEL = 0x20000 - OFILL = 0x80 - ONLCR = 0x2 - ONLRET = 0x40 - ONOCR = 0x20 - ONOEOT = 0x8 - OPOST = 0x1 - OXTABS = 0x4 - O_ACCMODE = 0x3 - O_ALERT = 0x20000000 - O_APPEND = 0x8 - O_ASYNC = 0x40 - O_CLOEXEC = 0x1000000 - O_CREAT = 0x200 - O_DIRECTORY = 0x100000 - O_DP_GETRAWENCRYPTED = 0x1 - O_DP_GETRAWUNENCRYPTED = 0x2 - O_DSYNC = 0x400000 - O_EVTONLY = 0x8000 - O_EXCL = 0x800 - O_EXLOCK = 0x20 - O_FSYNC = 0x80 - O_NDELAY = 0x4 - O_NOCTTY = 0x20000 - O_NOFOLLOW = 0x100 - O_NOFOLLOW_ANY = 0x20000000 - O_NONBLOCK = 0x4 - O_POPUP = 0x80000000 - O_RDONLY = 0x0 - O_RDWR = 0x2 - O_SHLOCK = 0x10 - O_SYMLINK = 0x200000 - O_SYNC = 0x80 - O_TRUNC = 0x400 - O_WRONLY = 0x1 - PARENB = 0x1000 - PARMRK = 0x8 - PARODD = 0x2000 - PENDIN = 0x20000000 - PRIO_PGRP = 0x1 - PRIO_PROCESS = 0x0 - PRIO_USER = 0x2 - PROT_EXEC = 0x4 - PROT_NONE = 0x0 - PROT_READ = 0x1 - PROT_WRITE = 0x2 - PT_ATTACH = 0xa - PT_ATTACHEXC = 0xe - PT_CONTINUE = 0x7 - PT_DENY_ATTACH = 0x1f - PT_DETACH = 0xb - PT_FIRSTMACH = 0x20 - PT_FORCEQUOTA = 0x1e - PT_KILL = 0x8 - PT_READ_D = 0x2 - PT_READ_I = 0x1 - PT_READ_U = 0x3 - PT_SIGEXC = 0xc - PT_STEP = 0x9 - PT_THUPDATE = 0xd - PT_TRACE_ME = 0x0 - PT_WRITE_D = 0x5 - PT_WRITE_I = 0x4 - PT_WRITE_U = 0x6 - RLIMIT_AS = 0x5 - RLIMIT_CORE = 0x4 - RLIMIT_CPU = 0x0 - RLIMIT_CPU_USAGE_MONITOR = 0x2 - RLIMIT_DATA = 0x2 - RLIMIT_FSIZE = 0x1 - RLIMIT_MEMLOCK = 0x6 - RLIMIT_NOFILE = 0x8 - RLIMIT_NPROC = 0x7 - RLIMIT_RSS = 0x5 - RLIMIT_STACK = 0x3 - RLIM_INFINITY = 0x7fffffffffffffff - RTAX_AUTHOR = 0x6 - RTAX_BRD = 0x7 - RTAX_DST = 0x0 - RTAX_GATEWAY = 0x1 - RTAX_GENMASK = 0x3 - RTAX_IFA = 0x5 - RTAX_IFP = 0x4 - RTAX_MAX = 0x8 - RTAX_NETMASK = 0x2 - RTA_AUTHOR = 0x40 - RTA_BRD = 0x80 - RTA_DST = 0x1 - RTA_GATEWAY = 0x2 - RTA_GENMASK = 0x8 - RTA_IFA = 0x20 - RTA_IFP = 0x10 - RTA_NETMASK = 0x4 - RTF_BLACKHOLE = 0x1000 - RTF_BROADCAST = 0x400000 - RTF_CLONING = 0x100 - RTF_CONDEMNED = 0x2000000 - RTF_DEAD = 0x20000000 - RTF_DELCLONE = 0x80 - RTF_DONE = 0x40 - RTF_DYNAMIC = 0x10 - RTF_GATEWAY = 0x2 - RTF_GLOBAL = 0x40000000 - RTF_HOST = 0x4 - RTF_IFREF = 0x4000000 - RTF_IFSCOPE = 0x1000000 - RTF_LLDATA = 0x400 - RTF_LLINFO = 0x400 - RTF_LOCAL = 0x200000 - RTF_MODIFIED = 0x20 - RTF_MULTICAST = 0x800000 - RTF_NOIFREF = 0x2000 - RTF_PINNED = 0x100000 - RTF_PRCLONING = 0x10000 - RTF_PROTO1 = 0x8000 - RTF_PROTO2 = 0x4000 - RTF_PROTO3 = 0x40000 - RTF_PROXY = 0x8000000 - RTF_REJECT = 0x8 - RTF_ROUTER = 0x10000000 - RTF_STATIC = 0x800 - RTF_UP = 0x1 - RTF_WASCLONED = 0x20000 - RTF_XRESOLVE = 0x200 - RTM_ADD = 0x1 - RTM_CHANGE = 0x3 - RTM_DELADDR = 0xd - RTM_DELETE = 0x2 - RTM_DELMADDR = 0x10 - RTM_GET = 0x4 - RTM_GET2 = 0x14 - RTM_IFINFO = 0xe - RTM_IFINFO2 = 0x12 - RTM_LOCK = 0x8 - RTM_LOSING = 0x5 - RTM_MISS = 0x7 - RTM_NEWADDR = 0xc - RTM_NEWMADDR = 0xf - RTM_NEWMADDR2 = 0x13 - RTM_OLDADD = 0x9 - RTM_OLDDEL = 0xa - RTM_REDIRECT = 0x6 - RTM_RESOLVE = 0xb - RTM_RTTUNIT = 0xf4240 - RTM_VERSION = 0x5 - RTV_EXPIRE = 0x4 - RTV_HOPCOUNT = 0x2 - RTV_MTU = 0x1 - RTV_RPIPE = 0x8 - RTV_RTT = 0x40 - RTV_RTTVAR = 0x80 - RTV_SPIPE = 0x10 - RTV_SSTHRESH = 0x20 - RUSAGE_CHILDREN = -0x1 - RUSAGE_SELF = 0x0 - SCM_CREDS = 0x3 - SCM_RIGHTS = 0x1 - SCM_TIMESTAMP = 0x2 - SCM_TIMESTAMP_MONOTONIC = 0x4 - SEEK_CUR = 0x1 - SEEK_DATA = 0x4 - SEEK_END = 0x2 - SEEK_HOLE = 0x3 - SEEK_SET = 0x0 - SHUT_RD = 0x0 - SHUT_RDWR = 0x2 - SHUT_WR = 0x1 - SIOCADDMULTI = 0x80206931 - SIOCAIFADDR = 0x8040691a - SIOCARPIPLL = 0xc0206928 - SIOCATMARK = 0x40047307 - SIOCAUTOADDR = 0xc0206926 - SIOCAUTONETMASK = 0x80206927 - SIOCDELMULTI = 0x80206932 - SIOCDIFADDR = 0x80206919 - SIOCDIFPHYADDR = 0x80206941 - SIOCGDRVSPEC = 0xc028697b - SIOCGETVLAN = 0xc020697f - SIOCGHIWAT = 0x40047301 - SIOCGIF6LOWPAN = 0xc02069c5 - SIOCGIFADDR = 0xc0206921 - SIOCGIFALTMTU = 0xc0206948 - SIOCGIFASYNCMAP = 0xc020697c - SIOCGIFBOND = 0xc0206947 - SIOCGIFBRDADDR = 0xc0206923 - SIOCGIFCAP = 0xc020695b - SIOCGIFCONF = 0xc00c6924 - SIOCGIFDEVMTU = 0xc0206944 - SIOCGIFDSTADDR = 0xc0206922 - SIOCGIFFLAGS = 0xc0206911 - SIOCGIFFUNCTIONALTYPE = 0xc02069ad - SIOCGIFGENERIC = 0xc020693a - SIOCGIFKPI = 0xc0206987 - SIOCGIFMAC = 0xc0206982 - SIOCGIFMEDIA = 0xc02c6938 - SIOCGIFMETRIC = 0xc0206917 - SIOCGIFMTU = 0xc0206933 - SIOCGIFNETMASK = 0xc0206925 - SIOCGIFPDSTADDR = 0xc0206940 - SIOCGIFPHYS = 0xc0206935 - SIOCGIFPSRCADDR = 0xc020693f - SIOCGIFSTATUS = 0xc331693d - SIOCGIFVLAN = 0xc020697f - SIOCGIFWAKEFLAGS = 0xc0206988 - SIOCGIFXMEDIA = 0xc02c6948 - SIOCGLOWAT = 0x40047303 - SIOCGPGRP = 0x40047309 - SIOCIFCREATE = 0xc0206978 - SIOCIFCREATE2 = 0xc020697a - SIOCIFDESTROY = 0x80206979 - SIOCIFGCLONERS = 0xc0106981 - SIOCRSLVMULTI = 0xc010693b - SIOCSDRVSPEC = 0x8028697b - SIOCSETVLAN = 0x8020697e - SIOCSHIWAT = 0x80047300 - SIOCSIF6LOWPAN = 0x802069c4 - SIOCSIFADDR = 0x8020690c - SIOCSIFALTMTU = 0x80206945 - SIOCSIFASYNCMAP = 0x8020697d - SIOCSIFBOND = 0x80206946 - SIOCSIFBRDADDR = 0x80206913 - SIOCSIFCAP = 0x8020695a - SIOCSIFDSTADDR = 0x8020690e - SIOCSIFFLAGS = 0x80206910 - SIOCSIFGENERIC = 0x80206939 - SIOCSIFKPI = 0x80206986 - SIOCSIFLLADDR = 0x8020693c - SIOCSIFMAC = 0x80206983 - SIOCSIFMEDIA = 0xc0206937 - SIOCSIFMETRIC = 0x80206918 - SIOCSIFMTU = 0x80206934 - SIOCSIFNETMASK = 0x80206916 - SIOCSIFPHYADDR = 0x8040693e - SIOCSIFPHYS = 0x80206936 - SIOCSIFVLAN = 0x8020697e - SIOCSLOWAT = 0x80047302 - SIOCSPGRP = 0x80047308 - SOCK_DGRAM = 0x2 - SOCK_MAXADDRLEN = 0xff - SOCK_RAW = 0x3 - SOCK_RDM = 0x4 - SOCK_SEQPACKET = 0x5 - SOCK_STREAM = 0x1 - SOL_LOCAL = 0x0 - SOL_SOCKET = 0xffff - SOMAXCONN = 0x80 - SO_ACCEPTCONN = 0x2 - SO_BROADCAST = 0x20 - SO_DEBUG = 0x1 - SO_DONTROUTE = 0x10 - SO_DONTTRUNC = 0x2000 - SO_ERROR = 0x1007 - SO_KEEPALIVE = 0x8 - SO_LABEL = 0x1010 - SO_LINGER = 0x80 - SO_LINGER_SEC = 0x1080 - SO_NETSVC_MARKING_LEVEL = 0x1119 - SO_NET_SERVICE_TYPE = 0x1116 - SO_NKE = 0x1021 - SO_NOADDRERR = 0x1023 - SO_NOSIGPIPE = 0x1022 - SO_NOTIFYCONFLICT = 0x1026 - SO_NP_EXTENSIONS = 0x1083 - SO_NREAD = 0x1020 - SO_NUMRCVPKT = 0x1112 - SO_NWRITE = 0x1024 - SO_OOBINLINE = 0x100 - SO_PEERLABEL = 0x1011 - SO_RANDOMPORT = 0x1082 - SO_RCVBUF = 0x1002 - SO_RCVLOWAT = 0x1004 - SO_RCVTIMEO = 0x1006 - SO_REUSEADDR = 0x4 - SO_REUSEPORT = 0x200 - SO_REUSESHAREUID = 0x1025 - SO_SNDBUF = 0x1001 - SO_SNDLOWAT = 0x1003 - SO_SNDTIMEO = 0x1005 - SO_TIMESTAMP = 0x400 - SO_TIMESTAMP_MONOTONIC = 0x800 - SO_TYPE = 0x1008 - SO_UPCALLCLOSEWAIT = 0x1027 - SO_USELOOPBACK = 0x40 - SO_WANTMORE = 0x4000 - SO_WANTOOBFLAG = 0x8000 - S_IEXEC = 0x40 - S_IFBLK = 0x6000 - S_IFCHR = 0x2000 - S_IFDIR = 0x4000 - S_IFIFO = 0x1000 - S_IFLNK = 0xa000 - S_IFMT = 0xf000 - S_IFREG = 0x8000 - S_IFSOCK = 0xc000 - S_IFWHT = 0xe000 - S_IREAD = 0x100 - S_IRGRP = 0x20 - S_IROTH = 0x4 - S_IRUSR = 0x100 - S_IRWXG = 0x38 - S_IRWXO = 0x7 - S_IRWXU = 0x1c0 - S_ISGID = 0x400 - S_ISTXT = 0x200 - S_ISUID = 0x800 - S_ISVTX = 0x200 - S_IWGRP = 0x10 - S_IWOTH = 0x2 - S_IWRITE = 0x80 - S_IWUSR = 0x80 - S_IXGRP = 0x8 - S_IXOTH = 0x1 - S_IXUSR = 0x40 - TAB0 = 0x0 - TAB1 = 0x400 - TAB2 = 0x800 - TAB3 = 0x4 - TABDLY = 0xc04 - TCIFLUSH = 0x1 - TCIOFF = 0x3 - TCIOFLUSH = 0x3 - TCION = 0x4 - TCOFLUSH = 0x2 - TCOOFF = 0x1 - TCOON = 0x2 - TCP_CONNECTIONTIMEOUT = 0x20 - TCP_CONNECTION_INFO = 0x106 - TCP_ENABLE_ECN = 0x104 - TCP_FASTOPEN = 0x105 - TCP_KEEPALIVE = 0x10 - TCP_KEEPCNT = 0x102 - TCP_KEEPINTVL = 0x101 - TCP_MAXHLEN = 0x3c - TCP_MAXOLEN = 0x28 - TCP_MAXSEG = 0x2 - TCP_MAXWIN = 0xffff - TCP_MAX_SACK = 0x4 - TCP_MAX_WINSHIFT = 0xe - TCP_MINMSS = 0xd8 - TCP_MSS = 0x200 - TCP_NODELAY = 0x1 - TCP_NOOPT = 0x8 - TCP_NOPUSH = 0x4 - TCP_NOTSENT_LOWAT = 0x201 - TCP_RXT_CONNDROPTIME = 0x80 - TCP_RXT_FINDROP = 0x100 - TCP_SENDMOREACKS = 0x103 - TCSAFLUSH = 0x2 - TIOCCBRK = 0x2000747a - TIOCCDTR = 0x20007478 - TIOCCONS = 0x80047462 - TIOCDCDTIMESTAMP = 0x40107458 - TIOCDRAIN = 0x2000745e - TIOCDSIMICROCODE = 0x20007455 - TIOCEXCL = 0x2000740d - TIOCEXT = 0x80047460 - TIOCFLUSH = 0x80047410 - TIOCGDRAINWAIT = 0x40047456 - TIOCGETA = 0x40487413 - TIOCGETD = 0x4004741a - TIOCGPGRP = 0x40047477 - TIOCGWINSZ = 0x40087468 - TIOCIXOFF = 0x20007480 - TIOCIXON = 0x20007481 - TIOCMBIC = 0x8004746b - TIOCMBIS = 0x8004746c - TIOCMGDTRWAIT = 0x4004745a - TIOCMGET = 0x4004746a - TIOCMODG = 0x40047403 - TIOCMODS = 0x80047404 - TIOCMSDTRWAIT = 0x8004745b - TIOCMSET = 0x8004746d - TIOCM_CAR = 0x40 - TIOCM_CD = 0x40 - TIOCM_CTS = 0x20 - TIOCM_DSR = 0x100 - TIOCM_DTR = 0x2 - TIOCM_LE = 0x1 - TIOCM_RI = 0x80 - TIOCM_RNG = 0x80 - TIOCM_RTS = 0x4 - TIOCM_SR = 0x10 - TIOCM_ST = 0x8 - TIOCNOTTY = 0x20007471 - TIOCNXCL = 0x2000740e - TIOCOUTQ = 0x40047473 - TIOCPKT = 0x80047470 - TIOCPKT_DATA = 0x0 - TIOCPKT_DOSTOP = 0x20 - TIOCPKT_FLUSHREAD = 0x1 - TIOCPKT_FLUSHWRITE = 0x2 - TIOCPKT_IOCTL = 0x40 - TIOCPKT_NOSTOP = 0x10 - TIOCPKT_START = 0x8 - TIOCPKT_STOP = 0x4 - TIOCPTYGNAME = 0x40807453 - TIOCPTYGRANT = 0x20007454 - TIOCPTYUNLK = 0x20007452 - TIOCREMOTE = 0x80047469 - TIOCSBRK = 0x2000747b - TIOCSCONS = 0x20007463 - TIOCSCTTY = 0x20007461 - TIOCSDRAINWAIT = 0x80047457 - TIOCSDTR = 0x20007479 - TIOCSETA = 0x80487414 - TIOCSETAF = 0x80487416 - TIOCSETAW = 0x80487415 - TIOCSETD = 0x8004741b - TIOCSIG = 0x2000745f - TIOCSPGRP = 0x80047476 - TIOCSTART = 0x2000746e - TIOCSTAT = 0x20007465 - TIOCSTI = 0x80017472 - TIOCSTOP = 0x2000746f - TIOCSWINSZ = 0x80087467 - TIOCTIMESTAMP = 0x40107459 - TIOCUCNTL = 0x80047466 - TOSTOP = 0x400000 - VDISCARD = 0xf - VDSUSP = 0xb - VEOF = 0x0 - VEOL = 0x1 - VEOL2 = 0x2 - VERASE = 0x3 - VINTR = 0x8 - VKILL = 0x5 - VLNEXT = 0xe - VMIN = 0x10 - VM_LOADAVG = 0x2 - VM_MACHFACTOR = 0x4 - VM_MAXID = 0x6 - VM_METER = 0x1 - VM_SWAPUSAGE = 0x5 - VQUIT = 0x9 - VREPRINT = 0x6 - VSTART = 0xc - VSTATUS = 0x12 - VSTOP = 0xd - VSUSP = 0xa - VT0 = 0x0 - VT1 = 0x10000 - VTDLY = 0x10000 - VTIME = 0x11 - VWERASE = 0x4 - WCONTINUED = 0x10 - WCOREFLAG = 0x80 - WEXITED = 0x4 - WNOHANG = 0x1 - WNOWAIT = 0x20 - WORDSIZE = 0x40 - WSTOPPED = 0x8 - WUNTRACED = 0x2 - XATTR_CREATE = 0x2 - XATTR_NODEFAULT = 0x10 - XATTR_NOFOLLOW = 0x1 - XATTR_NOSECURITY = 0x8 - XATTR_REPLACE = 0x4 - XATTR_SHOWCOMPRESSION = 0x20 + AF_APPLETALK = 0x10 + AF_CCITT = 0xa + AF_CHAOS = 0x5 + AF_CNT = 0x15 + AF_COIP = 0x14 + AF_DATAKIT = 0x9 + AF_DECnet = 0xc + AF_DLI = 0xd + AF_E164 = 0x1c + AF_ECMA = 0x8 + AF_HYLINK = 0xf + AF_IEEE80211 = 0x25 + AF_IMPLINK = 0x3 + AF_INET = 0x2 + AF_INET6 = 0x1e + AF_IPX = 0x17 + AF_ISDN = 0x1c + AF_ISO = 0x7 + AF_LAT = 0xe + AF_LINK = 0x12 + AF_LOCAL = 0x1 + AF_MAX = 0x29 + AF_NATM = 0x1f + AF_NDRV = 0x1b + AF_NETBIOS = 0x21 + AF_NS = 0x6 + AF_OSI = 0x7 + AF_PPP = 0x22 + AF_PUP = 0x4 + AF_RESERVED_36 = 0x24 + AF_ROUTE = 0x11 + AF_SIP = 0x18 + AF_SNA = 0xb + AF_SYSTEM = 0x20 + AF_SYS_CONTROL = 0x2 + AF_UNIX = 0x1 + AF_UNSPEC = 0x0 + AF_UTUN = 0x26 + AF_VSOCK = 0x28 + ALTWERASE = 0x200 + ATTR_BIT_MAP_COUNT = 0x5 + ATTR_CMN_ACCESSMASK = 0x20000 + ATTR_CMN_ACCTIME = 0x1000 + ATTR_CMN_ADDEDTIME = 0x10000000 + ATTR_CMN_BKUPTIME = 0x2000 + ATTR_CMN_CHGTIME = 0x800 + ATTR_CMN_CRTIME = 0x200 + ATTR_CMN_DATA_PROTECT_FLAGS = 0x40000000 + ATTR_CMN_DEVID = 0x2 + ATTR_CMN_DOCUMENT_ID = 0x100000 + ATTR_CMN_ERROR = 0x20000000 + ATTR_CMN_EXTENDED_SECURITY = 0x400000 + ATTR_CMN_FILEID = 0x2000000 + ATTR_CMN_FLAGS = 0x40000 + ATTR_CMN_FNDRINFO = 0x4000 + ATTR_CMN_FSID = 0x4 + ATTR_CMN_FULLPATH = 0x8000000 + ATTR_CMN_GEN_COUNT = 0x80000 + ATTR_CMN_GRPID = 0x10000 + ATTR_CMN_GRPUUID = 0x1000000 + ATTR_CMN_MODTIME = 0x400 + ATTR_CMN_NAME = 0x1 + ATTR_CMN_NAMEDATTRCOUNT = 0x80000 + ATTR_CMN_NAMEDATTRLIST = 0x100000 + ATTR_CMN_OBJID = 0x20 + ATTR_CMN_OBJPERMANENTID = 0x40 + ATTR_CMN_OBJTAG = 0x10 + ATTR_CMN_OBJTYPE = 0x8 + ATTR_CMN_OWNERID = 0x8000 + ATTR_CMN_PARENTID = 0x4000000 + ATTR_CMN_PAROBJID = 0x80 + ATTR_CMN_RETURNED_ATTRS = 0x80000000 + ATTR_CMN_SCRIPT = 0x100 + ATTR_CMN_SETMASK = 0x51c7ff00 + ATTR_CMN_USERACCESS = 0x200000 + ATTR_CMN_UUID = 0x800000 + ATTR_CMN_VALIDMASK = 0xffffffff + ATTR_CMN_VOLSETMASK = 0x6700 + ATTR_FILE_ALLOCSIZE = 0x4 + ATTR_FILE_CLUMPSIZE = 0x10 + ATTR_FILE_DATAALLOCSIZE = 0x400 + ATTR_FILE_DATAEXTENTS = 0x800 + ATTR_FILE_DATALENGTH = 0x200 + ATTR_FILE_DEVTYPE = 0x20 + ATTR_FILE_FILETYPE = 0x40 + ATTR_FILE_FORKCOUNT = 0x80 + ATTR_FILE_FORKLIST = 0x100 + ATTR_FILE_IOBLOCKSIZE = 0x8 + ATTR_FILE_LINKCOUNT = 0x1 + ATTR_FILE_RSRCALLOCSIZE = 0x2000 + ATTR_FILE_RSRCEXTENTS = 0x4000 + ATTR_FILE_RSRCLENGTH = 0x1000 + ATTR_FILE_SETMASK = 0x20 + ATTR_FILE_TOTALSIZE = 0x2 + ATTR_FILE_VALIDMASK = 0x37ff + ATTR_VOL_ALLOCATIONCLUMP = 0x40 + ATTR_VOL_ATTRIBUTES = 0x40000000 + ATTR_VOL_CAPABILITIES = 0x20000 + ATTR_VOL_DIRCOUNT = 0x400 + ATTR_VOL_ENCODINGSUSED = 0x10000 + ATTR_VOL_FILECOUNT = 0x200 + ATTR_VOL_FSTYPE = 0x1 + ATTR_VOL_INFO = 0x80000000 + ATTR_VOL_IOBLOCKSIZE = 0x80 + ATTR_VOL_MAXOBJCOUNT = 0x800 + ATTR_VOL_MINALLOCATION = 0x20 + ATTR_VOL_MOUNTEDDEVICE = 0x8000 + ATTR_VOL_MOUNTFLAGS = 0x4000 + ATTR_VOL_MOUNTPOINT = 0x1000 + ATTR_VOL_NAME = 0x2000 + ATTR_VOL_OBJCOUNT = 0x100 + ATTR_VOL_QUOTA_SIZE = 0x10000000 + ATTR_VOL_RESERVED_SIZE = 0x20000000 + ATTR_VOL_SETMASK = 0x80002000 + ATTR_VOL_SIGNATURE = 0x2 + ATTR_VOL_SIZE = 0x4 + ATTR_VOL_SPACEAVAIL = 0x10 + ATTR_VOL_SPACEFREE = 0x8 + ATTR_VOL_SPACEUSED = 0x800000 + ATTR_VOL_UUID = 0x40000 + ATTR_VOL_VALIDMASK = 0xf087ffff + B0 = 0x0 + B110 = 0x6e + B115200 = 0x1c200 + B1200 = 0x4b0 + B134 = 0x86 + B14400 = 0x3840 + B150 = 0x96 + B1800 = 0x708 + B19200 = 0x4b00 + B200 = 0xc8 + B230400 = 0x38400 + B2400 = 0x960 + B28800 = 0x7080 + B300 = 0x12c + B38400 = 0x9600 + B4800 = 0x12c0 + B50 = 0x32 + B57600 = 0xe100 + B600 = 0x258 + B7200 = 0x1c20 + B75 = 0x4b + B76800 = 0x12c00 + B9600 = 0x2580 + BIOCFLUSH = 0x20004268 + BIOCGBLEN = 0x40044266 + BIOCGDLT = 0x4004426a + BIOCGDLTLIST = 0xc00c4279 + BIOCGETIF = 0x4020426b + BIOCGHDRCMPLT = 0x40044274 + BIOCGRSIG = 0x40044272 + BIOCGRTIMEOUT = 0x4010426e + BIOCGSEESENT = 0x40044276 + BIOCGSTATS = 0x4008426f + BIOCIMMEDIATE = 0x80044270 + BIOCPROMISC = 0x20004269 + BIOCSBLEN = 0xc0044266 + BIOCSDLT = 0x80044278 + BIOCSETF = 0x80104267 + BIOCSETFNR = 0x8010427e + BIOCSETIF = 0x8020426c + BIOCSHDRCMPLT = 0x80044275 + BIOCSRSIG = 0x80044273 + BIOCSRTIMEOUT = 0x8010426d + BIOCSSEESENT = 0x80044277 + BIOCVERSION = 0x40044271 + BPF_A = 0x10 + BPF_ABS = 0x20 + BPF_ADD = 0x0 + BPF_ALIGNMENT = 0x4 + BPF_ALU = 0x4 + BPF_AND = 0x50 + BPF_B = 0x10 + BPF_DIV = 0x30 + BPF_H = 0x8 + BPF_IMM = 0x0 + BPF_IND = 0x40 + BPF_JA = 0x0 + BPF_JEQ = 0x10 + BPF_JGE = 0x30 + BPF_JGT = 0x20 + BPF_JMP = 0x5 + BPF_JSET = 0x40 + BPF_K = 0x0 + BPF_LD = 0x0 + BPF_LDX = 0x1 + BPF_LEN = 0x80 + BPF_LSH = 0x60 + BPF_MAJOR_VERSION = 0x1 + BPF_MAXBUFSIZE = 0x80000 + BPF_MAXINSNS = 0x200 + BPF_MEM = 0x60 + BPF_MEMWORDS = 0x10 + BPF_MINBUFSIZE = 0x20 + BPF_MINOR_VERSION = 0x1 + BPF_MISC = 0x7 + BPF_MSH = 0xa0 + BPF_MUL = 0x20 + BPF_NEG = 0x80 + BPF_OR = 0x40 + BPF_RELEASE = 0x30bb6 + BPF_RET = 0x6 + BPF_RSH = 0x70 + BPF_ST = 0x2 + BPF_STX = 0x3 + BPF_SUB = 0x10 + BPF_TAX = 0x0 + BPF_TXA = 0x80 + BPF_W = 0x0 + BPF_X = 0x8 + BRKINT = 0x2 + BS0 = 0x0 + BS1 = 0x8000 + BSDLY = 0x8000 + CFLUSH = 0xf + CLOCAL = 0x8000 + CLOCK_MONOTONIC = 0x6 + CLOCK_MONOTONIC_RAW = 0x4 + CLOCK_MONOTONIC_RAW_APPROX = 0x5 + CLOCK_PROCESS_CPUTIME_ID = 0xc + CLOCK_REALTIME = 0x0 + CLOCK_THREAD_CPUTIME_ID = 0x10 + CLOCK_UPTIME_RAW = 0x8 + CLOCK_UPTIME_RAW_APPROX = 0x9 + CLONE_NOFOLLOW = 0x1 + CLONE_NOOWNERCOPY = 0x2 + CR0 = 0x0 + CR1 = 0x1000 + CR2 = 0x2000 + CR3 = 0x3000 + CRDLY = 0x3000 + CREAD = 0x800 + CRTSCTS = 0x30000 + CS5 = 0x0 + CS6 = 0x100 + CS7 = 0x200 + CS8 = 0x300 + CSIZE = 0x300 + CSTART = 0x11 + CSTATUS = 0x14 + CSTOP = 0x13 + CSTOPB = 0x400 + CSUSP = 0x1a + CTLIOCGINFO = 0xc0644e03 + CTL_HW = 0x6 + CTL_KERN = 0x1 + CTL_MAXNAME = 0xc + CTL_NET = 0x4 + DLT_A429 = 0xb8 + DLT_A653_ICM = 0xb9 + DLT_AIRONET_HEADER = 0x78 + DLT_AOS = 0xde + DLT_APPLE_IP_OVER_IEEE1394 = 0x8a + DLT_ARCNET = 0x7 + DLT_ARCNET_LINUX = 0x81 + DLT_ATM_CLIP = 0x13 + DLT_ATM_RFC1483 = 0xb + DLT_AURORA = 0x7e + DLT_AX25 = 0x3 + DLT_AX25_KISS = 0xca + DLT_BACNET_MS_TP = 0xa5 + DLT_BLUETOOTH_HCI_H4 = 0xbb + DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 0xc9 + DLT_CAN20B = 0xbe + DLT_CAN_SOCKETCAN = 0xe3 + DLT_CHAOS = 0x5 + DLT_CHDLC = 0x68 + DLT_CISCO_IOS = 0x76 + DLT_C_HDLC = 0x68 + DLT_C_HDLC_WITH_DIR = 0xcd + DLT_DBUS = 0xe7 + DLT_DECT = 0xdd + DLT_DOCSIS = 0x8f + DLT_DVB_CI = 0xeb + DLT_ECONET = 0x73 + DLT_EN10MB = 0x1 + DLT_EN3MB = 0x2 + DLT_ENC = 0x6d + DLT_ERF = 0xc5 + DLT_ERF_ETH = 0xaf + DLT_ERF_POS = 0xb0 + DLT_FC_2 = 0xe0 + DLT_FC_2_WITH_FRAME_DELIMS = 0xe1 + DLT_FDDI = 0xa + DLT_FLEXRAY = 0xd2 + DLT_FRELAY = 0x6b + DLT_FRELAY_WITH_DIR = 0xce + DLT_GCOM_SERIAL = 0xad + DLT_GCOM_T1E1 = 0xac + DLT_GPF_F = 0xab + DLT_GPF_T = 0xaa + DLT_GPRS_LLC = 0xa9 + DLT_GSMTAP_ABIS = 0xda + DLT_GSMTAP_UM = 0xd9 + DLT_HHDLC = 0x79 + DLT_IBM_SN = 0x92 + DLT_IBM_SP = 0x91 + DLT_IEEE802 = 0x6 + DLT_IEEE802_11 = 0x69 + DLT_IEEE802_11_RADIO = 0x7f + DLT_IEEE802_11_RADIO_AVS = 0xa3 + DLT_IEEE802_15_4 = 0xc3 + DLT_IEEE802_15_4_LINUX = 0xbf + DLT_IEEE802_15_4_NOFCS = 0xe6 + DLT_IEEE802_15_4_NONASK_PHY = 0xd7 + DLT_IEEE802_16_MAC_CPS = 0xbc + DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1 + DLT_IPFILTER = 0x74 + DLT_IPMB = 0xc7 + DLT_IPMB_LINUX = 0xd1 + DLT_IPNET = 0xe2 + DLT_IPOIB = 0xf2 + DLT_IPV4 = 0xe4 + DLT_IPV6 = 0xe5 + DLT_IP_OVER_FC = 0x7a + DLT_JUNIPER_ATM1 = 0x89 + DLT_JUNIPER_ATM2 = 0x87 + DLT_JUNIPER_ATM_CEMIC = 0xee + DLT_JUNIPER_CHDLC = 0xb5 + DLT_JUNIPER_ES = 0x84 + DLT_JUNIPER_ETHER = 0xb2 + DLT_JUNIPER_FIBRECHANNEL = 0xea + DLT_JUNIPER_FRELAY = 0xb4 + DLT_JUNIPER_GGSN = 0x85 + DLT_JUNIPER_ISM = 0xc2 + DLT_JUNIPER_MFR = 0x86 + DLT_JUNIPER_MLFR = 0x83 + DLT_JUNIPER_MLPPP = 0x82 + DLT_JUNIPER_MONITOR = 0xa4 + DLT_JUNIPER_PIC_PEER = 0xae + DLT_JUNIPER_PPP = 0xb3 + DLT_JUNIPER_PPPOE = 0xa7 + DLT_JUNIPER_PPPOE_ATM = 0xa8 + DLT_JUNIPER_SERVICES = 0x88 + DLT_JUNIPER_SRX_E2E = 0xe9 + DLT_JUNIPER_ST = 0xc8 + DLT_JUNIPER_VP = 0xb7 + DLT_JUNIPER_VS = 0xe8 + DLT_LAPB_WITH_DIR = 0xcf + DLT_LAPD = 0xcb + DLT_LIN = 0xd4 + DLT_LINUX_EVDEV = 0xd8 + DLT_LINUX_IRDA = 0x90 + DLT_LINUX_LAPD = 0xb1 + DLT_LINUX_PPP_WITHDIRECTION = 0xa6 + DLT_LINUX_SLL = 0x71 + DLT_LOOP = 0x6c + DLT_LTALK = 0x72 + DLT_MATCHING_MAX = 0x10a + DLT_MATCHING_MIN = 0x68 + DLT_MFR = 0xb6 + DLT_MOST = 0xd3 + DLT_MPEG_2_TS = 0xf3 + DLT_MPLS = 0xdb + DLT_MTP2 = 0x8c + DLT_MTP2_WITH_PHDR = 0x8b + DLT_MTP3 = 0x8d + DLT_MUX27010 = 0xec + DLT_NETANALYZER = 0xf0 + DLT_NETANALYZER_TRANSPARENT = 0xf1 + DLT_NFC_LLCP = 0xf5 + DLT_NFLOG = 0xef + DLT_NG40 = 0xf4 + DLT_NULL = 0x0 + DLT_PCI_EXP = 0x7d + DLT_PFLOG = 0x75 + DLT_PFSYNC = 0x12 + DLT_PPI = 0xc0 + DLT_PPP = 0x9 + DLT_PPP_BSDOS = 0x10 + DLT_PPP_ETHER = 0x33 + DLT_PPP_PPPD = 0xa6 + DLT_PPP_SERIAL = 0x32 + DLT_PPP_WITH_DIR = 0xcc + DLT_PPP_WITH_DIRECTION = 0xa6 + DLT_PRISM_HEADER = 0x77 + DLT_PRONET = 0x4 + DLT_RAIF1 = 0xc6 + DLT_RAW = 0xc + DLT_RIO = 0x7c + DLT_SCCP = 0x8e + DLT_SITA = 0xc4 + DLT_SLIP = 0x8 + DLT_SLIP_BSDOS = 0xf + DLT_STANAG_5066_D_PDU = 0xed + DLT_SUNATM = 0x7b + DLT_SYMANTEC_FIREWALL = 0x63 + DLT_TZSP = 0x80 + DLT_USB = 0xba + DLT_USB_DARWIN = 0x10a + DLT_USB_LINUX = 0xbd + DLT_USB_LINUX_MMAPPED = 0xdc + DLT_USER0 = 0x93 + DLT_USER1 = 0x94 + DLT_USER10 = 0x9d + DLT_USER11 = 0x9e + DLT_USER12 = 0x9f + DLT_USER13 = 0xa0 + DLT_USER14 = 0xa1 + DLT_USER15 = 0xa2 + DLT_USER2 = 0x95 + DLT_USER3 = 0x96 + DLT_USER4 = 0x97 + DLT_USER5 = 0x98 + DLT_USER6 = 0x99 + DLT_USER7 = 0x9a + DLT_USER8 = 0x9b + DLT_USER9 = 0x9c + DLT_WIHART = 0xdf + DLT_X2E_SERIAL = 0xd5 + DLT_X2E_XORAYA = 0xd6 + DT_BLK = 0x6 + DT_CHR = 0x2 + DT_DIR = 0x4 + DT_FIFO = 0x1 + DT_LNK = 0xa + DT_REG = 0x8 + DT_SOCK = 0xc + DT_UNKNOWN = 0x0 + DT_WHT = 0xe + ECHO = 0x8 + ECHOCTL = 0x40 + ECHOE = 0x2 + ECHOK = 0x4 + ECHOKE = 0x1 + ECHONL = 0x10 + ECHOPRT = 0x20 + EVFILT_AIO = -0x3 + EVFILT_EXCEPT = -0xf + EVFILT_FS = -0x9 + EVFILT_MACHPORT = -0x8 + EVFILT_PROC = -0x5 + EVFILT_READ = -0x1 + EVFILT_SIGNAL = -0x6 + EVFILT_SYSCOUNT = 0x11 + EVFILT_THREADMARKER = 0x11 + EVFILT_TIMER = -0x7 + EVFILT_USER = -0xa + EVFILT_VM = -0xc + EVFILT_VNODE = -0x4 + EVFILT_WRITE = -0x2 + EV_ADD = 0x1 + EV_CLEAR = 0x20 + EV_DELETE = 0x2 + EV_DISABLE = 0x8 + EV_DISPATCH = 0x80 + EV_DISPATCH2 = 0x180 + EV_ENABLE = 0x4 + EV_EOF = 0x8000 + EV_ERROR = 0x4000 + EV_FLAG0 = 0x1000 + EV_FLAG1 = 0x2000 + EV_ONESHOT = 0x10 + EV_OOBAND = 0x2000 + EV_POLL = 0x1000 + EV_RECEIPT = 0x40 + EV_SYSFLAGS = 0xf000 + EV_UDATA_SPECIFIC = 0x100 + EV_VANISHED = 0x200 + EXTA = 0x4b00 + EXTB = 0x9600 + EXTPROC = 0x800 + FD_CLOEXEC = 0x1 + FD_SETSIZE = 0x400 + FF0 = 0x0 + FF1 = 0x4000 + FFDLY = 0x4000 + FLUSHO = 0x800000 + FSOPT_ATTR_CMN_EXTENDED = 0x20 + FSOPT_NOFOLLOW = 0x1 + FSOPT_NOINMEMUPDATE = 0x2 + FSOPT_PACK_INVAL_ATTRS = 0x8 + FSOPT_REPORT_FULLSIZE = 0x4 + FSOPT_RETURN_REALDEV = 0x200 + F_ADDFILESIGS = 0x3d + F_ADDFILESIGS_FOR_DYLD_SIM = 0x53 + F_ADDFILESIGS_INFO = 0x67 + F_ADDFILESIGS_RETURN = 0x61 + F_ADDFILESUPPL = 0x68 + F_ADDSIGS = 0x3b + F_ALLOCATEALL = 0x4 + F_ALLOCATECONTIG = 0x2 + F_BARRIERFSYNC = 0x55 + F_CHECK_LV = 0x62 + F_CHKCLEAN = 0x29 + F_DUPFD = 0x0 + F_DUPFD_CLOEXEC = 0x43 + F_FINDSIGS = 0x4e + F_FLUSH_DATA = 0x28 + F_FREEZE_FS = 0x35 + F_FULLFSYNC = 0x33 + F_GETCODEDIR = 0x48 + F_GETFD = 0x1 + F_GETFL = 0x3 + F_GETLK = 0x7 + F_GETLKPID = 0x42 + F_GETNOSIGPIPE = 0x4a + F_GETOWN = 0x5 + F_GETPATH = 0x32 + F_GETPATH_MTMINFO = 0x47 + F_GETPATH_NOFIRMLINK = 0x66 + F_GETPROTECTIONCLASS = 0x3f + F_GETPROTECTIONLEVEL = 0x4d + F_GETSIGSINFO = 0x69 + F_GLOBAL_NOCACHE = 0x37 + F_LOG2PHYS = 0x31 + F_LOG2PHYS_EXT = 0x41 + F_NOCACHE = 0x30 + F_NODIRECT = 0x3e + F_OK = 0x0 + F_PATHPKG_CHECK = 0x34 + F_PEOFPOSMODE = 0x3 + F_PREALLOCATE = 0x2a + F_PUNCHHOLE = 0x63 + F_RDADVISE = 0x2c + F_RDAHEAD = 0x2d + F_RDLCK = 0x1 + F_SETBACKINGSTORE = 0x46 + F_SETFD = 0x2 + F_SETFL = 0x4 + F_SETLK = 0x8 + F_SETLKW = 0x9 + F_SETLKWTIMEOUT = 0xa + F_SETNOSIGPIPE = 0x49 + F_SETOWN = 0x6 + F_SETPROTECTIONCLASS = 0x40 + F_SETSIZE = 0x2b + F_SINGLE_WRITER = 0x4c + F_SPECULATIVE_READ = 0x65 + F_THAW_FS = 0x36 + F_TRANSCODEKEY = 0x4b + F_TRIM_ACTIVE_FILE = 0x64 + F_UNLCK = 0x2 + F_VOLPOSMODE = 0x4 + F_WRLCK = 0x3 + HUPCL = 0x4000 + HW_MACHINE = 0x1 + ICANON = 0x100 + ICMP6_FILTER = 0x12 + ICRNL = 0x100 + IEXTEN = 0x400 + IFF_ALLMULTI = 0x200 + IFF_ALTPHYS = 0x4000 + IFF_BROADCAST = 0x2 + IFF_DEBUG = 0x4 + IFF_LINK0 = 0x1000 + IFF_LINK1 = 0x2000 + IFF_LINK2 = 0x4000 + IFF_LOOPBACK = 0x8 + IFF_MULTICAST = 0x8000 + IFF_NOARP = 0x80 + IFF_NOTRAILERS = 0x20 + IFF_OACTIVE = 0x400 + IFF_POINTOPOINT = 0x10 + IFF_PROMISC = 0x100 + IFF_RUNNING = 0x40 + IFF_SIMPLEX = 0x800 + IFF_UP = 0x1 + IFNAMSIZ = 0x10 + IFT_1822 = 0x2 + IFT_6LOWPAN = 0x40 + IFT_AAL5 = 0x31 + IFT_ARCNET = 0x23 + IFT_ARCNETPLUS = 0x24 + IFT_ATM = 0x25 + IFT_BRIDGE = 0xd1 + IFT_CARP = 0xf8 + IFT_CELLULAR = 0xff + IFT_CEPT = 0x13 + IFT_DS3 = 0x1e + IFT_ENC = 0xf4 + IFT_EON = 0x19 + IFT_ETHER = 0x6 + IFT_FAITH = 0x38 + IFT_FDDI = 0xf + IFT_FRELAY = 0x20 + IFT_FRELAYDCE = 0x2c + IFT_GIF = 0x37 + IFT_HDH1822 = 0x3 + IFT_HIPPI = 0x2f + IFT_HSSI = 0x2e + IFT_HY = 0xe + IFT_IEEE1394 = 0x90 + IFT_IEEE8023ADLAG = 0x88 + IFT_ISDNBASIC = 0x14 + IFT_ISDNPRIMARY = 0x15 + IFT_ISO88022LLC = 0x29 + IFT_ISO88023 = 0x7 + IFT_ISO88024 = 0x8 + IFT_ISO88025 = 0x9 + IFT_ISO88026 = 0xa + IFT_L2VLAN = 0x87 + IFT_LAPB = 0x10 + IFT_LOCALTALK = 0x2a + IFT_LOOP = 0x18 + IFT_MIOX25 = 0x26 + IFT_MODEM = 0x30 + IFT_NSIP = 0x1b + IFT_OTHER = 0x1 + IFT_P10 = 0xc + IFT_P80 = 0xd + IFT_PARA = 0x22 + IFT_PDP = 0xff + IFT_PFLOG = 0xf5 + IFT_PFSYNC = 0xf6 + IFT_PKTAP = 0xfe + IFT_PPP = 0x17 + IFT_PROPMUX = 0x36 + IFT_PROPVIRTUAL = 0x35 + IFT_PTPSERIAL = 0x16 + IFT_RS232 = 0x21 + IFT_SDLC = 0x11 + IFT_SIP = 0x1f + IFT_SLIP = 0x1c + IFT_SMDSDXI = 0x2b + IFT_SMDSICIP = 0x34 + IFT_SONET = 0x27 + IFT_SONETPATH = 0x32 + IFT_SONETVT = 0x33 + IFT_STARLAN = 0xb + IFT_STF = 0x39 + IFT_T1 = 0x12 + IFT_ULTRA = 0x1d + IFT_V35 = 0x2d + IFT_X25 = 0x5 + IFT_X25DDN = 0x4 + IFT_X25PLE = 0x28 + IFT_XETHER = 0x1a + IGNBRK = 0x1 + IGNCR = 0x80 + IGNPAR = 0x4 + IMAXBEL = 0x2000 + INLCR = 0x40 + INPCK = 0x10 + IN_CLASSA_HOST = 0xffffff + IN_CLASSA_MAX = 0x80 + IN_CLASSA_NET = 0xff000000 + IN_CLASSA_NSHIFT = 0x18 + IN_CLASSB_HOST = 0xffff + IN_CLASSB_MAX = 0x10000 + IN_CLASSB_NET = 0xffff0000 + IN_CLASSB_NSHIFT = 0x10 + IN_CLASSC_HOST = 0xff + IN_CLASSC_NET = 0xffffff00 + IN_CLASSC_NSHIFT = 0x8 + IN_CLASSD_HOST = 0xfffffff + IN_CLASSD_NET = 0xf0000000 + IN_CLASSD_NSHIFT = 0x1c + IN_LINKLOCALNETNUM = 0xa9fe0000 + IN_LOOPBACKNET = 0x7f + IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x400473d1 + IPPROTO_3PC = 0x22 + IPPROTO_ADFS = 0x44 + IPPROTO_AH = 0x33 + IPPROTO_AHIP = 0x3d + IPPROTO_APES = 0x63 + IPPROTO_ARGUS = 0xd + IPPROTO_AX25 = 0x5d + IPPROTO_BHA = 0x31 + IPPROTO_BLT = 0x1e + IPPROTO_BRSATMON = 0x4c + IPPROTO_CFTP = 0x3e + IPPROTO_CHAOS = 0x10 + IPPROTO_CMTP = 0x26 + IPPROTO_CPHB = 0x49 + IPPROTO_CPNX = 0x48 + IPPROTO_DDP = 0x25 + IPPROTO_DGP = 0x56 + IPPROTO_DIVERT = 0xfe + IPPROTO_DONE = 0x101 + IPPROTO_DSTOPTS = 0x3c + IPPROTO_EGP = 0x8 + IPPROTO_EMCON = 0xe + IPPROTO_ENCAP = 0x62 + IPPROTO_EON = 0x50 + IPPROTO_ESP = 0x32 + IPPROTO_ETHERIP = 0x61 + IPPROTO_FRAGMENT = 0x2c + IPPROTO_GGP = 0x3 + IPPROTO_GMTP = 0x64 + IPPROTO_GRE = 0x2f + IPPROTO_HELLO = 0x3f + IPPROTO_HMP = 0x14 + IPPROTO_HOPOPTS = 0x0 + IPPROTO_ICMP = 0x1 + IPPROTO_ICMPV6 = 0x3a + IPPROTO_IDP = 0x16 + IPPROTO_IDPR = 0x23 + IPPROTO_IDRP = 0x2d + IPPROTO_IGMP = 0x2 + IPPROTO_IGP = 0x55 + IPPROTO_IGRP = 0x58 + IPPROTO_IL = 0x28 + IPPROTO_INLSP = 0x34 + IPPROTO_INP = 0x20 + IPPROTO_IP = 0x0 + IPPROTO_IPCOMP = 0x6c + IPPROTO_IPCV = 0x47 + IPPROTO_IPEIP = 0x5e + IPPROTO_IPIP = 0x4 + IPPROTO_IPPC = 0x43 + IPPROTO_IPV4 = 0x4 + IPPROTO_IPV6 = 0x29 + IPPROTO_IRTP = 0x1c + IPPROTO_KRYPTOLAN = 0x41 + IPPROTO_LARP = 0x5b + IPPROTO_LEAF1 = 0x19 + IPPROTO_LEAF2 = 0x1a + IPPROTO_MAX = 0x100 + IPPROTO_MAXID = 0x34 + IPPROTO_MEAS = 0x13 + IPPROTO_MHRP = 0x30 + IPPROTO_MICP = 0x5f + IPPROTO_MTP = 0x5c + IPPROTO_MUX = 0x12 + IPPROTO_ND = 0x4d + IPPROTO_NHRP = 0x36 + IPPROTO_NONE = 0x3b + IPPROTO_NSP = 0x1f + IPPROTO_NVPII = 0xb + IPPROTO_OSPFIGP = 0x59 + IPPROTO_PGM = 0x71 + IPPROTO_PIGP = 0x9 + IPPROTO_PIM = 0x67 + IPPROTO_PRM = 0x15 + IPPROTO_PUP = 0xc + IPPROTO_PVP = 0x4b + IPPROTO_RAW = 0xff + IPPROTO_RCCMON = 0xa + IPPROTO_RDP = 0x1b + IPPROTO_ROUTING = 0x2b + IPPROTO_RSVP = 0x2e + IPPROTO_RVD = 0x42 + IPPROTO_SATEXPAK = 0x40 + IPPROTO_SATMON = 0x45 + IPPROTO_SCCSP = 0x60 + IPPROTO_SCTP = 0x84 + IPPROTO_SDRP = 0x2a + IPPROTO_SEP = 0x21 + IPPROTO_SRPC = 0x5a + IPPROTO_ST = 0x7 + IPPROTO_SVMTP = 0x52 + IPPROTO_SWIPE = 0x35 + IPPROTO_TCF = 0x57 + IPPROTO_TCP = 0x6 + IPPROTO_TP = 0x1d + IPPROTO_TPXX = 0x27 + IPPROTO_TRUNK1 = 0x17 + IPPROTO_TRUNK2 = 0x18 + IPPROTO_TTP = 0x54 + IPPROTO_UDP = 0x11 + IPPROTO_VINES = 0x53 + IPPROTO_VISA = 0x46 + IPPROTO_VMTP = 0x51 + IPPROTO_WBEXPAK = 0x4f + IPPROTO_WBMON = 0x4e + IPPROTO_WSN = 0x4a + IPPROTO_XNET = 0xf + IPPROTO_XTP = 0x24 + IPV6_2292DSTOPTS = 0x17 + IPV6_2292HOPLIMIT = 0x14 + IPV6_2292HOPOPTS = 0x16 + IPV6_2292NEXTHOP = 0x15 + IPV6_2292PKTINFO = 0x13 + IPV6_2292PKTOPTIONS = 0x19 + IPV6_2292RTHDR = 0x18 + IPV6_3542DSTOPTS = 0x32 + IPV6_3542HOPLIMIT = 0x2f + IPV6_3542HOPOPTS = 0x31 + IPV6_3542NEXTHOP = 0x30 + IPV6_3542PKTINFO = 0x2e + IPV6_3542RTHDR = 0x33 + IPV6_ADDR_MC_FLAGS_PREFIX = 0x20 + IPV6_ADDR_MC_FLAGS_TRANSIENT = 0x10 + IPV6_ADDR_MC_FLAGS_UNICAST_BASED = 0x30 + IPV6_AUTOFLOWLABEL = 0x3b + IPV6_BINDV6ONLY = 0x1b + IPV6_BOUND_IF = 0x7d + IPV6_CHECKSUM = 0x1a + IPV6_DEFAULT_MULTICAST_HOPS = 0x1 + IPV6_DEFAULT_MULTICAST_LOOP = 0x1 + IPV6_DEFHLIM = 0x40 + IPV6_DONTFRAG = 0x3e + IPV6_DSTOPTS = 0x32 + IPV6_FAITH = 0x1d + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 + IPV6_FLOW_ECN_MASK = 0x3000 + IPV6_FRAGTTL = 0x3c + IPV6_FW_ADD = 0x1e + IPV6_FW_DEL = 0x1f + IPV6_FW_FLUSH = 0x20 + IPV6_FW_GET = 0x22 + IPV6_FW_ZERO = 0x21 + IPV6_HLIMDEC = 0x1 + IPV6_HOPLIMIT = 0x2f + IPV6_HOPOPTS = 0x31 + IPV6_IPSEC_POLICY = 0x1c + IPV6_JOIN_GROUP = 0xc + IPV6_LEAVE_GROUP = 0xd + IPV6_MAXHLIM = 0xff + IPV6_MAXOPTHDR = 0x800 + IPV6_MAXPACKET = 0xffff + IPV6_MAX_GROUP_SRC_FILTER = 0x200 + IPV6_MAX_MEMBERSHIPS = 0xfff + IPV6_MAX_SOCK_SRC_FILTER = 0x80 + IPV6_MIN_MEMBERSHIPS = 0x1f + IPV6_MMTU = 0x500 + IPV6_MSFILTER = 0x4a + IPV6_MULTICAST_HOPS = 0xa + IPV6_MULTICAST_IF = 0x9 + IPV6_MULTICAST_LOOP = 0xb + IPV6_NEXTHOP = 0x30 + IPV6_PATHMTU = 0x2c + IPV6_PKTINFO = 0x2e + IPV6_PORTRANGE = 0xe + IPV6_PORTRANGE_DEFAULT = 0x0 + IPV6_PORTRANGE_HIGH = 0x1 + IPV6_PORTRANGE_LOW = 0x2 + IPV6_PREFER_TEMPADDR = 0x3f + IPV6_RECVDSTOPTS = 0x28 + IPV6_RECVHOPLIMIT = 0x25 + IPV6_RECVHOPOPTS = 0x27 + IPV6_RECVPATHMTU = 0x2b + IPV6_RECVPKTINFO = 0x3d + IPV6_RECVRTHDR = 0x26 + IPV6_RECVTCLASS = 0x23 + IPV6_RTHDR = 0x33 + IPV6_RTHDRDSTOPTS = 0x39 + IPV6_RTHDR_LOOSE = 0x0 + IPV6_RTHDR_STRICT = 0x1 + IPV6_RTHDR_TYPE_0 = 0x0 + IPV6_SOCKOPT_RESERVED1 = 0x3 + IPV6_TCLASS = 0x24 + IPV6_UNICAST_HOPS = 0x4 + IPV6_USE_MIN_MTU = 0x2a + IPV6_V6ONLY = 0x1b + IPV6_VERSION = 0x60 + IPV6_VERSION_MASK = 0xf0 + IP_ADD_MEMBERSHIP = 0xc + IP_ADD_SOURCE_MEMBERSHIP = 0x46 + IP_BLOCK_SOURCE = 0x48 + IP_BOUND_IF = 0x19 + IP_DEFAULT_MULTICAST_LOOP = 0x1 + IP_DEFAULT_MULTICAST_TTL = 0x1 + IP_DF = 0x4000 + IP_DONTFRAG = 0x1c + IP_DROP_MEMBERSHIP = 0xd + IP_DROP_SOURCE_MEMBERSHIP = 0x47 + IP_DUMMYNET_CONFIGURE = 0x3c + IP_DUMMYNET_DEL = 0x3d + IP_DUMMYNET_FLUSH = 0x3e + IP_DUMMYNET_GET = 0x40 + IP_FAITH = 0x16 + IP_FW_ADD = 0x28 + IP_FW_DEL = 0x29 + IP_FW_FLUSH = 0x2a + IP_FW_GET = 0x2c + IP_FW_RESETLOG = 0x2d + IP_FW_ZERO = 0x2b + IP_HDRINCL = 0x2 + IP_IPSEC_POLICY = 0x15 + IP_MAXPACKET = 0xffff + IP_MAX_GROUP_SRC_FILTER = 0x200 + IP_MAX_MEMBERSHIPS = 0xfff + IP_MAX_SOCK_MUTE_FILTER = 0x80 + IP_MAX_SOCK_SRC_FILTER = 0x80 + IP_MF = 0x2000 + IP_MIN_MEMBERSHIPS = 0x1f + IP_MSFILTER = 0x4a + IP_MSS = 0x240 + IP_MULTICAST_IF = 0x9 + IP_MULTICAST_IFINDEX = 0x42 + IP_MULTICAST_LOOP = 0xb + IP_MULTICAST_TTL = 0xa + IP_MULTICAST_VIF = 0xe + IP_NAT__XXX = 0x37 + IP_OFFMASK = 0x1fff + IP_OLD_FW_ADD = 0x32 + IP_OLD_FW_DEL = 0x33 + IP_OLD_FW_FLUSH = 0x34 + IP_OLD_FW_GET = 0x36 + IP_OLD_FW_RESETLOG = 0x38 + IP_OLD_FW_ZERO = 0x35 + IP_OPTIONS = 0x1 + IP_PKTINFO = 0x1a + IP_PORTRANGE = 0x13 + IP_PORTRANGE_DEFAULT = 0x0 + IP_PORTRANGE_HIGH = 0x1 + IP_PORTRANGE_LOW = 0x2 + IP_RECVDSTADDR = 0x7 + IP_RECVIF = 0x14 + IP_RECVOPTS = 0x5 + IP_RECVPKTINFO = 0x1a + IP_RECVRETOPTS = 0x6 + IP_RECVTOS = 0x1b + IP_RECVTTL = 0x18 + IP_RETOPTS = 0x8 + IP_RF = 0x8000 + IP_RSVP_OFF = 0x10 + IP_RSVP_ON = 0xf + IP_RSVP_VIF_OFF = 0x12 + IP_RSVP_VIF_ON = 0x11 + IP_STRIPHDR = 0x17 + IP_TOS = 0x3 + IP_TRAFFIC_MGT_BACKGROUND = 0x41 + IP_TTL = 0x4 + IP_UNBLOCK_SOURCE = 0x49 + ISIG = 0x80 + ISTRIP = 0x20 + IUTF8 = 0x4000 + IXANY = 0x800 + IXOFF = 0x400 + IXON = 0x200 + KERN_HOSTNAME = 0xa + KERN_OSRELEASE = 0x2 + KERN_OSTYPE = 0x1 + KERN_VERSION = 0x4 + LOCAL_PEERCRED = 0x1 + LOCAL_PEEREPID = 0x3 + LOCAL_PEEREUUID = 0x5 + LOCAL_PEERPID = 0x2 + LOCAL_PEERTOKEN = 0x6 + LOCAL_PEERUUID = 0x4 + LOCK_EX = 0x2 + LOCK_NB = 0x4 + LOCK_SH = 0x1 + LOCK_UN = 0x8 + MADV_CAN_REUSE = 0x9 + MADV_DONTNEED = 0x4 + MADV_FREE = 0x5 + MADV_FREE_REUSABLE = 0x7 + MADV_FREE_REUSE = 0x8 + MADV_NORMAL = 0x0 + MADV_PAGEOUT = 0xa + MADV_RANDOM = 0x1 + MADV_SEQUENTIAL = 0x2 + MADV_WILLNEED = 0x3 + MADV_ZERO_WIRED_PAGES = 0x6 + MAP_32BIT = 0x8000 + MAP_ANON = 0x1000 + MAP_ANONYMOUS = 0x1000 + MAP_COPY = 0x2 + MAP_FILE = 0x0 + MAP_FIXED = 0x10 + MAP_HASSEMAPHORE = 0x200 + MAP_JIT = 0x800 + MAP_NOCACHE = 0x400 + MAP_NOEXTEND = 0x100 + MAP_NORESERVE = 0x40 + MAP_PRIVATE = 0x2 + MAP_RENAME = 0x20 + MAP_RESERVED0080 = 0x80 + MAP_RESILIENT_CODESIGN = 0x2000 + MAP_RESILIENT_MEDIA = 0x4000 + MAP_SHARED = 0x1 + MAP_TRANSLATED_ALLOW_EXECUTE = 0x20000 + MAP_UNIX03 = 0x40000 + MCAST_BLOCK_SOURCE = 0x54 + MCAST_EXCLUDE = 0x2 + MCAST_INCLUDE = 0x1 + MCAST_JOIN_GROUP = 0x50 + MCAST_JOIN_SOURCE_GROUP = 0x52 + MCAST_LEAVE_GROUP = 0x51 + MCAST_LEAVE_SOURCE_GROUP = 0x53 + MCAST_UNBLOCK_SOURCE = 0x55 + MCAST_UNDEFINED = 0x0 + MCL_CURRENT = 0x1 + MCL_FUTURE = 0x2 + MNT_ASYNC = 0x40 + MNT_AUTOMOUNTED = 0x400000 + MNT_CMDFLAGS = 0xf0000 + MNT_CPROTECT = 0x80 + MNT_DEFWRITE = 0x2000000 + MNT_DONTBROWSE = 0x100000 + MNT_DOVOLFS = 0x8000 + MNT_DWAIT = 0x4 + MNT_EXPORTED = 0x100 + MNT_EXT_ROOT_DATA_VOL = 0x1 + MNT_FORCE = 0x80000 + MNT_IGNORE_OWNERSHIP = 0x200000 + MNT_JOURNALED = 0x800000 + MNT_LOCAL = 0x1000 + MNT_MULTILABEL = 0x4000000 + MNT_NOATIME = 0x10000000 + MNT_NOBLOCK = 0x20000 + MNT_NODEV = 0x10 + MNT_NOEXEC = 0x4 + MNT_NOSUID = 0x8 + MNT_NOUSERXATTR = 0x1000000 + MNT_NOWAIT = 0x2 + MNT_QUARANTINE = 0x400 + MNT_QUOTA = 0x2000 + MNT_RDONLY = 0x1 + MNT_RELOAD = 0x40000 + MNT_REMOVABLE = 0x200 + MNT_ROOTFS = 0x4000 + MNT_SNAPSHOT = 0x40000000 + MNT_STRICTATIME = 0x80000000 + MNT_SYNCHRONOUS = 0x2 + MNT_UNION = 0x20 + MNT_UNKNOWNPERMISSIONS = 0x200000 + MNT_UPDATE = 0x10000 + MNT_VISFLAGMASK = 0xd7f0f7ff + MNT_WAIT = 0x1 + MSG_CTRUNC = 0x20 + MSG_DONTROUTE = 0x4 + MSG_DONTWAIT = 0x80 + MSG_EOF = 0x100 + MSG_EOR = 0x8 + MSG_FLUSH = 0x400 + MSG_HAVEMORE = 0x2000 + MSG_HOLD = 0x800 + MSG_NEEDSA = 0x10000 + MSG_NOSIGNAL = 0x80000 + MSG_OOB = 0x1 + MSG_PEEK = 0x2 + MSG_RCVMORE = 0x4000 + MSG_SEND = 0x1000 + MSG_TRUNC = 0x10 + MSG_WAITALL = 0x40 + MSG_WAITSTREAM = 0x200 + MS_ASYNC = 0x1 + MS_DEACTIVATE = 0x8 + MS_INVALIDATE = 0x2 + MS_KILLPAGES = 0x4 + MS_SYNC = 0x10 + NAME_MAX = 0xff + NET_RT_DUMP = 0x1 + NET_RT_DUMP2 = 0x7 + NET_RT_FLAGS = 0x2 + NET_RT_FLAGS_PRIV = 0xa + NET_RT_IFLIST = 0x3 + NET_RT_IFLIST2 = 0x6 + NET_RT_MAXID = 0xb + NET_RT_STAT = 0x4 + NET_RT_TRASH = 0x5 + NFDBITS = 0x20 + NL0 = 0x0 + NL1 = 0x100 + NL2 = 0x200 + NL3 = 0x300 + NLDLY = 0x300 + NOFLSH = 0x80000000 + NOKERNINFO = 0x2000000 + NOTE_ABSOLUTE = 0x8 + NOTE_ATTRIB = 0x8 + NOTE_BACKGROUND = 0x40 + NOTE_CHILD = 0x4 + NOTE_CRITICAL = 0x20 + NOTE_DELETE = 0x1 + NOTE_EXEC = 0x20000000 + NOTE_EXIT = 0x80000000 + NOTE_EXITSTATUS = 0x4000000 + NOTE_EXIT_CSERROR = 0x40000 + NOTE_EXIT_DECRYPTFAIL = 0x10000 + NOTE_EXIT_DETAIL = 0x2000000 + NOTE_EXIT_DETAIL_MASK = 0x70000 + NOTE_EXIT_MEMORY = 0x20000 + NOTE_EXIT_REPARENTED = 0x80000 + NOTE_EXTEND = 0x4 + NOTE_FFAND = 0x40000000 + NOTE_FFCOPY = 0xc0000000 + NOTE_FFCTRLMASK = 0xc0000000 + NOTE_FFLAGSMASK = 0xffffff + NOTE_FFNOP = 0x0 + NOTE_FFOR = 0x80000000 + NOTE_FORK = 0x40000000 + NOTE_FUNLOCK = 0x100 + NOTE_LEEWAY = 0x10 + NOTE_LINK = 0x10 + NOTE_LOWAT = 0x1 + NOTE_MACHTIME = 0x100 + NOTE_MACH_CONTINUOUS_TIME = 0x80 + NOTE_NONE = 0x80 + NOTE_NSECONDS = 0x4 + NOTE_OOB = 0x2 + NOTE_PCTRLMASK = -0x100000 + NOTE_PDATAMASK = 0xfffff + NOTE_REAP = 0x10000000 + NOTE_RENAME = 0x20 + NOTE_REVOKE = 0x40 + NOTE_SECONDS = 0x1 + NOTE_SIGNAL = 0x8000000 + NOTE_TRACK = 0x1 + NOTE_TRACKERR = 0x2 + NOTE_TRIGGER = 0x1000000 + NOTE_USECONDS = 0x2 + NOTE_VM_ERROR = 0x10000000 + NOTE_VM_PRESSURE = 0x80000000 + NOTE_VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000 + NOTE_VM_PRESSURE_TERMINATE = 0x40000000 + NOTE_WRITE = 0x2 + OCRNL = 0x10 + OFDEL = 0x20000 + OFILL = 0x80 + ONLCR = 0x2 + ONLRET = 0x40 + ONOCR = 0x20 + ONOEOT = 0x8 + OPOST = 0x1 + OXTABS = 0x4 + O_ACCMODE = 0x3 + O_ALERT = 0x20000000 + O_APPEND = 0x8 + O_ASYNC = 0x40 + O_CLOEXEC = 0x1000000 + O_CREAT = 0x200 + O_DIRECTORY = 0x100000 + O_DP_GETRAWENCRYPTED = 0x1 + O_DP_GETRAWUNENCRYPTED = 0x2 + O_DSYNC = 0x400000 + O_EVTONLY = 0x8000 + O_EXCL = 0x800 + O_EXLOCK = 0x20 + O_FSYNC = 0x80 + O_NDELAY = 0x4 + O_NOCTTY = 0x20000 + O_NOFOLLOW = 0x100 + O_NOFOLLOW_ANY = 0x20000000 + O_NONBLOCK = 0x4 + O_POPUP = 0x80000000 + O_RDONLY = 0x0 + O_RDWR = 0x2 + O_SHLOCK = 0x10 + O_SYMLINK = 0x200000 + O_SYNC = 0x80 + O_TRUNC = 0x400 + O_WRONLY = 0x1 + PARENB = 0x1000 + PARMRK = 0x8 + PARODD = 0x2000 + PENDIN = 0x20000000 + PRIO_PGRP = 0x1 + PRIO_PROCESS = 0x0 + PRIO_USER = 0x2 + PROT_EXEC = 0x4 + PROT_NONE = 0x0 + PROT_READ = 0x1 + PROT_WRITE = 0x2 + PT_ATTACH = 0xa + PT_ATTACHEXC = 0xe + PT_CONTINUE = 0x7 + PT_DENY_ATTACH = 0x1f + PT_DETACH = 0xb + PT_FIRSTMACH = 0x20 + PT_FORCEQUOTA = 0x1e + PT_KILL = 0x8 + PT_READ_D = 0x2 + PT_READ_I = 0x1 + PT_READ_U = 0x3 + PT_SIGEXC = 0xc + PT_STEP = 0x9 + PT_THUPDATE = 0xd + PT_TRACE_ME = 0x0 + PT_WRITE_D = 0x5 + PT_WRITE_I = 0x4 + PT_WRITE_U = 0x6 + RLIMIT_AS = 0x5 + RLIMIT_CORE = 0x4 + RLIMIT_CPU = 0x0 + RLIMIT_CPU_USAGE_MONITOR = 0x2 + RLIMIT_DATA = 0x2 + RLIMIT_FSIZE = 0x1 + RLIMIT_MEMLOCK = 0x6 + RLIMIT_NOFILE = 0x8 + RLIMIT_NPROC = 0x7 + RLIMIT_RSS = 0x5 + RLIMIT_STACK = 0x3 + RLIM_INFINITY = 0x7fffffffffffffff + RTAX_AUTHOR = 0x6 + RTAX_BRD = 0x7 + RTAX_DST = 0x0 + RTAX_GATEWAY = 0x1 + RTAX_GENMASK = 0x3 + RTAX_IFA = 0x5 + RTAX_IFP = 0x4 + RTAX_MAX = 0x8 + RTAX_NETMASK = 0x2 + RTA_AUTHOR = 0x40 + RTA_BRD = 0x80 + RTA_DST = 0x1 + RTA_GATEWAY = 0x2 + RTA_GENMASK = 0x8 + RTA_IFA = 0x20 + RTA_IFP = 0x10 + RTA_NETMASK = 0x4 + RTF_BLACKHOLE = 0x1000 + RTF_BROADCAST = 0x400000 + RTF_CLONING = 0x100 + RTF_CONDEMNED = 0x2000000 + RTF_DEAD = 0x20000000 + RTF_DELCLONE = 0x80 + RTF_DONE = 0x40 + RTF_DYNAMIC = 0x10 + RTF_GATEWAY = 0x2 + RTF_GLOBAL = 0x40000000 + RTF_HOST = 0x4 + RTF_IFREF = 0x4000000 + RTF_IFSCOPE = 0x1000000 + RTF_LLDATA = 0x400 + RTF_LLINFO = 0x400 + RTF_LOCAL = 0x200000 + RTF_MODIFIED = 0x20 + RTF_MULTICAST = 0x800000 + RTF_NOIFREF = 0x2000 + RTF_PINNED = 0x100000 + RTF_PRCLONING = 0x10000 + RTF_PROTO1 = 0x8000 + RTF_PROTO2 = 0x4000 + RTF_PROTO3 = 0x40000 + RTF_PROXY = 0x8000000 + RTF_REJECT = 0x8 + RTF_ROUTER = 0x10000000 + RTF_STATIC = 0x800 + RTF_UP = 0x1 + RTF_WASCLONED = 0x20000 + RTF_XRESOLVE = 0x200 + RTM_ADD = 0x1 + RTM_CHANGE = 0x3 + RTM_DELADDR = 0xd + RTM_DELETE = 0x2 + RTM_DELMADDR = 0x10 + RTM_GET = 0x4 + RTM_GET2 = 0x14 + RTM_IFINFO = 0xe + RTM_IFINFO2 = 0x12 + RTM_LOCK = 0x8 + RTM_LOSING = 0x5 + RTM_MISS = 0x7 + RTM_NEWADDR = 0xc + RTM_NEWMADDR = 0xf + RTM_NEWMADDR2 = 0x13 + RTM_OLDADD = 0x9 + RTM_OLDDEL = 0xa + RTM_REDIRECT = 0x6 + RTM_RESOLVE = 0xb + RTM_RTTUNIT = 0xf4240 + RTM_VERSION = 0x5 + RTV_EXPIRE = 0x4 + RTV_HOPCOUNT = 0x2 + RTV_MTU = 0x1 + RTV_RPIPE = 0x8 + RTV_RTT = 0x40 + RTV_RTTVAR = 0x80 + RTV_SPIPE = 0x10 + RTV_SSTHRESH = 0x20 + RUSAGE_CHILDREN = -0x1 + RUSAGE_SELF = 0x0 + SCM_CREDS = 0x3 + SCM_RIGHTS = 0x1 + SCM_TIMESTAMP = 0x2 + SCM_TIMESTAMP_MONOTONIC = 0x4 + SEEK_CUR = 0x1 + SEEK_DATA = 0x4 + SEEK_END = 0x2 + SEEK_HOLE = 0x3 + SEEK_SET = 0x0 + SHUT_RD = 0x0 + SHUT_RDWR = 0x2 + SHUT_WR = 0x1 + SIOCADDMULTI = 0x80206931 + SIOCAIFADDR = 0x8040691a + SIOCARPIPLL = 0xc0206928 + SIOCATMARK = 0x40047307 + SIOCAUTOADDR = 0xc0206926 + SIOCAUTONETMASK = 0x80206927 + SIOCDELMULTI = 0x80206932 + SIOCDIFADDR = 0x80206919 + SIOCDIFPHYADDR = 0x80206941 + SIOCGDRVSPEC = 0xc028697b + SIOCGETVLAN = 0xc020697f + SIOCGHIWAT = 0x40047301 + SIOCGIF6LOWPAN = 0xc02069c5 + SIOCGIFADDR = 0xc0206921 + SIOCGIFALTMTU = 0xc0206948 + SIOCGIFASYNCMAP = 0xc020697c + SIOCGIFBOND = 0xc0206947 + SIOCGIFBRDADDR = 0xc0206923 + SIOCGIFCAP = 0xc020695b + SIOCGIFCONF = 0xc00c6924 + SIOCGIFDEVMTU = 0xc0206944 + SIOCGIFDSTADDR = 0xc0206922 + SIOCGIFFLAGS = 0xc0206911 + SIOCGIFFUNCTIONALTYPE = 0xc02069ad + SIOCGIFGENERIC = 0xc020693a + SIOCGIFKPI = 0xc0206987 + SIOCGIFMAC = 0xc0206982 + SIOCGIFMEDIA = 0xc02c6938 + SIOCGIFMETRIC = 0xc0206917 + SIOCGIFMTU = 0xc0206933 + SIOCGIFNETMASK = 0xc0206925 + SIOCGIFPDSTADDR = 0xc0206940 + SIOCGIFPHYS = 0xc0206935 + SIOCGIFPSRCADDR = 0xc020693f + SIOCGIFSTATUS = 0xc331693d + SIOCGIFVLAN = 0xc020697f + SIOCGIFWAKEFLAGS = 0xc0206988 + SIOCGIFXMEDIA = 0xc02c6948 + SIOCGLOWAT = 0x40047303 + SIOCGPGRP = 0x40047309 + SIOCIFCREATE = 0xc0206978 + SIOCIFCREATE2 = 0xc020697a + SIOCIFDESTROY = 0x80206979 + SIOCIFGCLONERS = 0xc0106981 + SIOCRSLVMULTI = 0xc010693b + SIOCSDRVSPEC = 0x8028697b + SIOCSETVLAN = 0x8020697e + SIOCSHIWAT = 0x80047300 + SIOCSIF6LOWPAN = 0x802069c4 + SIOCSIFADDR = 0x8020690c + SIOCSIFALTMTU = 0x80206945 + SIOCSIFASYNCMAP = 0x8020697d + SIOCSIFBOND = 0x80206946 + SIOCSIFBRDADDR = 0x80206913 + SIOCSIFCAP = 0x8020695a + SIOCSIFDSTADDR = 0x8020690e + SIOCSIFFLAGS = 0x80206910 + SIOCSIFGENERIC = 0x80206939 + SIOCSIFKPI = 0x80206986 + SIOCSIFLLADDR = 0x8020693c + SIOCSIFMAC = 0x80206983 + SIOCSIFMEDIA = 0xc0206937 + SIOCSIFMETRIC = 0x80206918 + SIOCSIFMTU = 0x80206934 + SIOCSIFNETMASK = 0x80206916 + SIOCSIFPHYADDR = 0x8040693e + SIOCSIFPHYS = 0x80206936 + SIOCSIFVLAN = 0x8020697e + SIOCSLOWAT = 0x80047302 + SIOCSPGRP = 0x80047308 + SOCK_DGRAM = 0x2 + SOCK_MAXADDRLEN = 0xff + SOCK_RAW = 0x3 + SOCK_RDM = 0x4 + SOCK_SEQPACKET = 0x5 + SOCK_STREAM = 0x1 + SOL_LOCAL = 0x0 + SOL_SOCKET = 0xffff + SOMAXCONN = 0x80 + SO_ACCEPTCONN = 0x2 + SO_BROADCAST = 0x20 + SO_DEBUG = 0x1 + SO_DONTROUTE = 0x10 + SO_DONTTRUNC = 0x2000 + SO_ERROR = 0x1007 + SO_KEEPALIVE = 0x8 + SO_LABEL = 0x1010 + SO_LINGER = 0x80 + SO_LINGER_SEC = 0x1080 + SO_NETSVC_MARKING_LEVEL = 0x1119 + SO_NET_SERVICE_TYPE = 0x1116 + SO_NKE = 0x1021 + SO_NOADDRERR = 0x1023 + SO_NOSIGPIPE = 0x1022 + SO_NOTIFYCONFLICT = 0x1026 + SO_NP_EXTENSIONS = 0x1083 + SO_NREAD = 0x1020 + SO_NUMRCVPKT = 0x1112 + SO_NWRITE = 0x1024 + SO_OOBINLINE = 0x100 + SO_PEERLABEL = 0x1011 + SO_RANDOMPORT = 0x1082 + SO_RCVBUF = 0x1002 + SO_RCVLOWAT = 0x1004 + SO_RCVTIMEO = 0x1006 + SO_REUSEADDR = 0x4 + SO_REUSEPORT = 0x200 + SO_REUSESHAREUID = 0x1025 + SO_SNDBUF = 0x1001 + SO_SNDLOWAT = 0x1003 + SO_SNDTIMEO = 0x1005 + SO_TIMESTAMP = 0x400 + SO_TIMESTAMP_MONOTONIC = 0x800 + SO_TRACKER_ATTRIBUTE_FLAGS_APP_APPROVED = 0x1 + SO_TRACKER_ATTRIBUTE_FLAGS_DOMAIN_SHORT = 0x4 + SO_TRACKER_ATTRIBUTE_FLAGS_TRACKER = 0x2 + SO_TRACKER_TRANSPARENCY_VERSION = 0x3 + SO_TYPE = 0x1008 + SO_UPCALLCLOSEWAIT = 0x1027 + SO_USELOOPBACK = 0x40 + SO_WANTMORE = 0x4000 + SO_WANTOOBFLAG = 0x8000 + S_IEXEC = 0x40 + S_IFBLK = 0x6000 + S_IFCHR = 0x2000 + S_IFDIR = 0x4000 + S_IFIFO = 0x1000 + S_IFLNK = 0xa000 + S_IFMT = 0xf000 + S_IFREG = 0x8000 + S_IFSOCK = 0xc000 + S_IFWHT = 0xe000 + S_IREAD = 0x100 + S_IRGRP = 0x20 + S_IROTH = 0x4 + S_IRUSR = 0x100 + S_IRWXG = 0x38 + S_IRWXO = 0x7 + S_IRWXU = 0x1c0 + S_ISGID = 0x400 + S_ISTXT = 0x200 + S_ISUID = 0x800 + S_ISVTX = 0x200 + S_IWGRP = 0x10 + S_IWOTH = 0x2 + S_IWRITE = 0x80 + S_IWUSR = 0x80 + S_IXGRP = 0x8 + S_IXOTH = 0x1 + S_IXUSR = 0x40 + TAB0 = 0x0 + TAB1 = 0x400 + TAB2 = 0x800 + TAB3 = 0x4 + TABDLY = 0xc04 + TCIFLUSH = 0x1 + TCIOFF = 0x3 + TCIOFLUSH = 0x3 + TCION = 0x4 + TCOFLUSH = 0x2 + TCOOFF = 0x1 + TCOON = 0x2 + TCPOPT_CC = 0xb + TCPOPT_CCECHO = 0xd + TCPOPT_CCNEW = 0xc + TCPOPT_EOL = 0x0 + TCPOPT_FASTOPEN = 0x22 + TCPOPT_MAXSEG = 0x2 + TCPOPT_NOP = 0x1 + TCPOPT_SACK = 0x5 + TCPOPT_SACK_HDR = 0x1010500 + TCPOPT_SACK_PERMITTED = 0x4 + TCPOPT_SACK_PERMIT_HDR = 0x1010402 + TCPOPT_SIGNATURE = 0x13 + TCPOPT_TIMESTAMP = 0x8 + TCPOPT_TSTAMP_HDR = 0x101080a + TCPOPT_WINDOW = 0x3 + TCP_CONNECTIONTIMEOUT = 0x20 + TCP_CONNECTION_INFO = 0x106 + TCP_ENABLE_ECN = 0x104 + TCP_FASTOPEN = 0x105 + TCP_KEEPALIVE = 0x10 + TCP_KEEPCNT = 0x102 + TCP_KEEPINTVL = 0x101 + TCP_MAXHLEN = 0x3c + TCP_MAXOLEN = 0x28 + TCP_MAXSEG = 0x2 + TCP_MAXWIN = 0xffff + TCP_MAX_SACK = 0x4 + TCP_MAX_WINSHIFT = 0xe + TCP_MINMSS = 0xd8 + TCP_MSS = 0x200 + TCP_NODELAY = 0x1 + TCP_NOOPT = 0x8 + TCP_NOPUSH = 0x4 + TCP_NOTSENT_LOWAT = 0x201 + TCP_RXT_CONNDROPTIME = 0x80 + TCP_RXT_FINDROP = 0x100 + TCP_SENDMOREACKS = 0x103 + TCSAFLUSH = 0x2 + TIOCCBRK = 0x2000747a + TIOCCDTR = 0x20007478 + TIOCCONS = 0x80047462 + TIOCDCDTIMESTAMP = 0x40107458 + TIOCDRAIN = 0x2000745e + TIOCDSIMICROCODE = 0x20007455 + TIOCEXCL = 0x2000740d + TIOCEXT = 0x80047460 + TIOCFLUSH = 0x80047410 + TIOCGDRAINWAIT = 0x40047456 + TIOCGETA = 0x40487413 + TIOCGETD = 0x4004741a + TIOCGPGRP = 0x40047477 + TIOCGWINSZ = 0x40087468 + TIOCIXOFF = 0x20007480 + TIOCIXON = 0x20007481 + TIOCMBIC = 0x8004746b + TIOCMBIS = 0x8004746c + TIOCMGDTRWAIT = 0x4004745a + TIOCMGET = 0x4004746a + TIOCMODG = 0x40047403 + TIOCMODS = 0x80047404 + TIOCMSDTRWAIT = 0x8004745b + TIOCMSET = 0x8004746d + TIOCM_CAR = 0x40 + TIOCM_CD = 0x40 + TIOCM_CTS = 0x20 + TIOCM_DSR = 0x100 + TIOCM_DTR = 0x2 + TIOCM_LE = 0x1 + TIOCM_RI = 0x80 + TIOCM_RNG = 0x80 + TIOCM_RTS = 0x4 + TIOCM_SR = 0x10 + TIOCM_ST = 0x8 + TIOCNOTTY = 0x20007471 + TIOCNXCL = 0x2000740e + TIOCOUTQ = 0x40047473 + TIOCPKT = 0x80047470 + TIOCPKT_DATA = 0x0 + TIOCPKT_DOSTOP = 0x20 + TIOCPKT_FLUSHREAD = 0x1 + TIOCPKT_FLUSHWRITE = 0x2 + TIOCPKT_IOCTL = 0x40 + TIOCPKT_NOSTOP = 0x10 + TIOCPKT_START = 0x8 + TIOCPKT_STOP = 0x4 + TIOCPTYGNAME = 0x40807453 + TIOCPTYGRANT = 0x20007454 + TIOCPTYUNLK = 0x20007452 + TIOCREMOTE = 0x80047469 + TIOCSBRK = 0x2000747b + TIOCSCONS = 0x20007463 + TIOCSCTTY = 0x20007461 + TIOCSDRAINWAIT = 0x80047457 + TIOCSDTR = 0x20007479 + TIOCSETA = 0x80487414 + TIOCSETAF = 0x80487416 + TIOCSETAW = 0x80487415 + TIOCSETD = 0x8004741b + TIOCSIG = 0x2000745f + TIOCSPGRP = 0x80047476 + TIOCSTART = 0x2000746e + TIOCSTAT = 0x20007465 + TIOCSTI = 0x80017472 + TIOCSTOP = 0x2000746f + TIOCSWINSZ = 0x80087467 + TIOCTIMESTAMP = 0x40107459 + TIOCUCNTL = 0x80047466 + TOSTOP = 0x400000 + VDISCARD = 0xf + VDSUSP = 0xb + VEOF = 0x0 + VEOL = 0x1 + VEOL2 = 0x2 + VERASE = 0x3 + VINTR = 0x8 + VKILL = 0x5 + VLNEXT = 0xe + VMADDR_CID_ANY = 0xffffffff + VMADDR_CID_HOST = 0x2 + VMADDR_CID_HYPERVISOR = 0x0 + VMADDR_CID_RESERVED = 0x1 + VMADDR_PORT_ANY = 0xffffffff + VMIN = 0x10 + VM_LOADAVG = 0x2 + VM_MACHFACTOR = 0x4 + VM_MAXID = 0x6 + VM_METER = 0x1 + VM_SWAPUSAGE = 0x5 + VQUIT = 0x9 + VREPRINT = 0x6 + VSTART = 0xc + VSTATUS = 0x12 + VSTOP = 0xd + VSUSP = 0xa + VT0 = 0x0 + VT1 = 0x10000 + VTDLY = 0x10000 + VTIME = 0x11 + VWERASE = 0x4 + WCONTINUED = 0x10 + WCOREFLAG = 0x80 + WEXITED = 0x4 + WNOHANG = 0x1 + WNOWAIT = 0x20 + WORDSIZE = 0x40 + WSTOPPED = 0x8 + WUNTRACED = 0x2 + XATTR_CREATE = 0x2 + XATTR_NODEFAULT = 0x10 + XATTR_NOFOLLOW = 0x1 + XATTR_NOSECURITY = 0x8 + XATTR_REPLACE = 0x4 + XATTR_SHOWCOMPRESSION = 0x20 ) // Errors diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go index 8894c4af44..78d4b85ece 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -1333,6 +1333,20 @@ const ( KEY_SPEC_THREAD_KEYRING = -0x1 KEY_SPEC_USER_KEYRING = -0x4 KEY_SPEC_USER_SESSION_KEYRING = -0x5 + LANDLOCK_ACCESS_FS_EXECUTE = 0x1 + LANDLOCK_ACCESS_FS_MAKE_BLOCK = 0x800 + LANDLOCK_ACCESS_FS_MAKE_CHAR = 0x40 + LANDLOCK_ACCESS_FS_MAKE_DIR = 0x80 + LANDLOCK_ACCESS_FS_MAKE_FIFO = 0x400 + LANDLOCK_ACCESS_FS_MAKE_REG = 0x100 + LANDLOCK_ACCESS_FS_MAKE_SOCK = 0x200 + LANDLOCK_ACCESS_FS_MAKE_SYM = 0x1000 + LANDLOCK_ACCESS_FS_READ_DIR = 0x8 + LANDLOCK_ACCESS_FS_READ_FILE = 0x4 + LANDLOCK_ACCESS_FS_REMOVE_DIR = 0x10 + LANDLOCK_ACCESS_FS_REMOVE_FILE = 0x20 + LANDLOCK_ACCESS_FS_WRITE_FILE = 0x2 + LANDLOCK_CREATE_RULESET_VERSION = 0x1 LINUX_REBOOT_CMD_CAD_OFF = 0x0 LINUX_REBOOT_CMD_CAD_ON = 0x89abcdef LINUX_REBOOT_CMD_HALT = 0xcdef0123 @@ -1383,6 +1397,8 @@ const ( MADV_NOHUGEPAGE = 0xf MADV_NORMAL = 0x0 MADV_PAGEOUT = 0x15 + MADV_POPULATE_READ = 0x16 + MADV_POPULATE_WRITE = 0x17 MADV_RANDOM = 0x1 MADV_REMOVE = 0x9 MADV_SEQUENTIAL = 0x2 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go index d4efe8d457..0ae0ed4cb8 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go @@ -734,6 +734,65 @@ var libc_sendfile_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func shmat(id int, addr uintptr, flag int) (ret uintptr, err error) { + r0, _, e1 := syscall_syscall(libc_shmat_trampoline_addr, uintptr(id), uintptr(addr), uintptr(flag)) + ret = uintptr(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shmat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shmat shmat "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) { + r0, _, e1 := syscall_syscall(libc_shmctl_trampoline_addr, uintptr(id), uintptr(cmd), uintptr(unsafe.Pointer(buf))) + result = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shmctl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shmctl shmctl "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmdt(addr uintptr) (err error) { + _, _, e1 := syscall_syscall(libc_shmdt_trampoline_addr, uintptr(addr), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shmdt_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shmdt shmdt "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmget(key int, size int, flag int) (id int, err error) { + r0, _, e1 := syscall_syscall(libc_shmget_trampoline_addr, uintptr(key), uintptr(size), uintptr(flag)) + id = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shmget_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shmget shmget "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Access(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s index bc169c2ab9..eac6ca806f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s @@ -264,6 +264,30 @@ TEXT libc_sendfile_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_sendfile_trampoline_addr(SB), RODATA, $8 DATA ·libc_sendfile_trampoline_addr(SB)/8, $libc_sendfile_trampoline<>(SB) +TEXT libc_shmat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shmat(SB) + +GLOBL ·libc_shmat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shmat_trampoline_addr(SB)/8, $libc_shmat_trampoline<>(SB) + +TEXT libc_shmctl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shmctl(SB) + +GLOBL ·libc_shmctl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shmctl_trampoline_addr(SB)/8, $libc_shmctl_trampoline<>(SB) + +TEXT libc_shmdt_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shmdt(SB) + +GLOBL ·libc_shmdt_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shmdt_trampoline_addr(SB)/8, $libc_shmdt_trampoline<>(SB) + +TEXT libc_shmget_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shmget(SB) + +GLOBL ·libc_shmget_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shmget_trampoline_addr(SB)/8, $libc_shmget_trampoline<>(SB) + TEXT libc_access_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_access(SB) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go index f2ee2bd33b..cf71be3edb 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go @@ -734,6 +734,65 @@ var libc_sendfile_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func shmat(id int, addr uintptr, flag int) (ret uintptr, err error) { + r0, _, e1 := syscall_syscall(libc_shmat_trampoline_addr, uintptr(id), uintptr(addr), uintptr(flag)) + ret = uintptr(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shmat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shmat shmat "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) { + r0, _, e1 := syscall_syscall(libc_shmctl_trampoline_addr, uintptr(id), uintptr(cmd), uintptr(unsafe.Pointer(buf))) + result = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shmctl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shmctl shmctl "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmdt(addr uintptr) (err error) { + _, _, e1 := syscall_syscall(libc_shmdt_trampoline_addr, uintptr(addr), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shmdt_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shmdt shmdt "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmget(key int, size int, flag int) (id int, err error) { + r0, _, e1 := syscall_syscall(libc_shmget_trampoline_addr, uintptr(key), uintptr(size), uintptr(flag)) + id = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_shmget_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_shmget shmget "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Access(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s index 33e19776db..4ebcf21758 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s @@ -264,6 +264,30 @@ TEXT libc_sendfile_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_sendfile_trampoline_addr(SB), RODATA, $8 DATA ·libc_sendfile_trampoline_addr(SB)/8, $libc_sendfile_trampoline<>(SB) +TEXT libc_shmat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shmat(SB) + +GLOBL ·libc_shmat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shmat_trampoline_addr(SB)/8, $libc_shmat_trampoline<>(SB) + +TEXT libc_shmctl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shmctl(SB) + +GLOBL ·libc_shmctl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shmctl_trampoline_addr(SB)/8, $libc_shmctl_trampoline<>(SB) + +TEXT libc_shmdt_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shmdt(SB) + +GLOBL ·libc_shmdt_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shmdt_trampoline_addr(SB)/8, $libc_shmdt_trampoline<>(SB) + +TEXT libc_shmget_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_shmget(SB) + +GLOBL ·libc_shmget_trampoline_addr(SB), RODATA, $8 +DATA ·libc_shmget_trampoline_addr(SB)/8, $libc_shmget_trampoline<>(SB) + TEXT libc_access_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_access(SB) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go index 2dbe3da7a0..4f5da1f54f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go @@ -110,6 +110,16 @@ func openat2(dirfd int, path string, open_how *OpenHow, size int) (fd int, err e // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func pipe2(p *[2]_C_int, flags int) (err error) { + _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) n = int(r0) @@ -1945,8 +1955,63 @@ func ProcessVMWritev(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags u // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe2(p *[2]_C_int, flags int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) +func PidfdOpen(pid int, flags int) (fd int, err error) { + r0, _, e1 := Syscall(SYS_PIDFD_OPEN, uintptr(pid), uintptr(flags), 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func PidfdGetfd(pidfd int, targetfd int, flags int) (fd int, err error) { + r0, _, e1 := Syscall(SYS_PIDFD_GETFD, uintptr(pidfd), uintptr(targetfd), uintptr(flags)) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmat(id int, addr uintptr, flag int) (ret uintptr, err error) { + r0, _, e1 := Syscall(SYS_SHMAT, uintptr(id), uintptr(addr), uintptr(flag)) + ret = uintptr(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) { + r0, _, e1 := Syscall(SYS_SHMCTL, uintptr(id), uintptr(cmd), uintptr(unsafe.Pointer(buf))) + result = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmdt(addr uintptr) (err error) { + _, _, e1 := Syscall(SYS_SHMDT, uintptr(addr), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmget(key int, size int, flag int) (id int, err error) { + r0, _, e1 := Syscall(SYS_SHMGET, uintptr(key), uintptr(size), uintptr(flag)) + id = int(r0) if e1 != 0 { err = errnoErr(e1) } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go index e37096e4de..ff90c81e73 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go @@ -46,37 +46,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe(p *[2]_C_int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -181,17 +150,6 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Ioperm(from int, num int, on int) (err error) { _, _, e1 := Syscall(SYS_IOPERM, uintptr(from), uintptr(num), uintptr(on)) if e1 != 0 { @@ -566,14 +524,3 @@ func utimes(path string, times *[2]Timeval) (err error) { } return } - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go index 9919d8486d..fa7d3dbe4e 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go @@ -46,27 +46,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -191,17 +170,6 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func inotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Ioperm(from int, num int, on int) (err error) { _, _, e1 := Syscall(SYS_IOPERM, uintptr(from), uintptr(num), uintptr(on)) if e1 != 0 { @@ -711,27 +679,6 @@ func utimes(path string, times *[2]Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe(p *[2]_C_int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(cmdline) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go index 076754d48d..654f91530f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go @@ -46,16 +46,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe(p *[2]_C_int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) fd = int(r0) @@ -235,27 +225,6 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -340,17 +309,6 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Lchown(path string, uid int, gid int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -681,17 +639,6 @@ func setrlimit(resource int, rlim *rlimit32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func armSyncFileRange(fd int, flags int, off int64, n int64) (err error) { _, _, e1 := Syscall6(SYS_ARM_SYNC_FILE_RANGE, uintptr(fd), uintptr(flags), uintptr(off), uintptr(off>>32), uintptr(n), uintptr(n>>32)) if e1 != 0 { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go index 4703cf3c33..6d15528853 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go @@ -46,27 +46,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -544,17 +523,6 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Ioperm(from int, num int, on int) (err error) { _, _, e1 := Syscall(SYS_IOPERM, uintptr(from), uintptr(num), uintptr(on)) if e1 != 0 { @@ -706,18 +674,6 @@ func Pause() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe() (p1 int, p2 int, err error) { - r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) - p1 = int(r0) - p2 = int(r1) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error) { r0, _, e1 := Syscall6(SYS_MMAP2, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(pageOffset)) xaddr = uintptr(r0) @@ -746,14 +702,3 @@ func setrlimit(resource int, rlim *rlimit32) (err error) { } return } - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go index a134f9a4d2..1e20d72df2 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go @@ -46,27 +46,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -717,14 +696,3 @@ func stat(path string, st *stat_t) (err error) { } return } - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go index b1fff2d946..82b5e2d9ed 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go @@ -46,27 +46,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -717,14 +696,3 @@ func stat(path string, st *stat_t) (err error) { } return } - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go index d13d6da01e..a0440c1d43 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go @@ -46,27 +46,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -544,17 +523,6 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Ioperm(from int, num int, on int) (err error) { _, _, e1 := Syscall(SYS_IOPERM, uintptr(from), uintptr(num), uintptr(on)) if e1 != 0 { @@ -706,18 +674,6 @@ func Pause() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe() (p1 int, p2 int, err error) { - r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) - p1 = int(r0) - p2 = int(r1) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error) { r0, _, e1 := Syscall6(SYS_MMAP2, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(pageOffset)) xaddr = uintptr(r0) @@ -746,14 +702,3 @@ func setrlimit(resource int, rlim *rlimit32) (err error) { } return } - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go index 927cf1a00f..5864b9ca64 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go @@ -46,27 +46,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -161,17 +140,6 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Ioperm(from int, num int, on int) (err error) { _, _, e1 := Syscall(SYS_IOPERM, uintptr(from), uintptr(num), uintptr(on)) if e1 != 0 { @@ -717,27 +685,6 @@ func setrlimit(resource int, rlim *rlimit32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe(p *[2]_C_int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func syncFileRange2(fd int, flags int, off int64, n int64) (err error) { _, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE2, uintptr(fd), uintptr(flags), uintptr(off>>32), uintptr(off), uintptr(n>>32), uintptr(n)) if e1 != 0 { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go index da8ec03966..beeb49e342 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go @@ -46,27 +46,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -191,17 +170,6 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Ioperm(from int, num int, on int) (err error) { _, _, e1 := Syscall(SYS_IOPERM, uintptr(from), uintptr(num), uintptr(on)) if e1 != 0 { @@ -763,27 +731,6 @@ func utimes(path string, times *[2]Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe(p *[2]_C_int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func syncFileRange2(fd int, flags int, off int64, n int64) (err error) { _, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE2, uintptr(fd), uintptr(flags), uintptr(off), uintptr(n), 0, 0) if e1 != 0 { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go index 083f493bb6..53139b82c7 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go @@ -46,27 +46,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -191,17 +170,6 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Ioperm(from int, num int, on int) (err error) { _, _, e1 := Syscall(SYS_IOPERM, uintptr(from), uintptr(num), uintptr(on)) if e1 != 0 { @@ -763,27 +731,6 @@ func utimes(path string, times *[2]Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe(p *[2]_C_int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func syncFileRange2(fd int, flags int, off int64, n int64) (err error) { _, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE2, uintptr(fd), uintptr(flags), uintptr(off), uintptr(n), 0, 0) if e1 != 0 { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go index bb347407d3..202add37d1 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go @@ -46,27 +46,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func EpollCreate(size int) (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer if len(events) > 0 { @@ -191,17 +170,6 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Lchown(path string, uid int, gid int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -553,17 +521,6 @@ func utimes(path string, times *[2]Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(cmdline) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go index 8edc517e1e..2ab268c343 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go @@ -73,16 +73,6 @@ func Fadvise(fd int, offset int64, length int64, advice int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func dup2(oldfd int, newfd int) (err error) { - _, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Fchown(fd int, uid int, gid int) (err error) { _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) if e1 != 0 { @@ -180,17 +170,6 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func InotifyInit() (fd int, err error) { - r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Lchown(path string, uid int, gid int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -718,24 +697,3 @@ func utimes(path string, times *[2]Timeval) (err error) { } return } - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func pipe(p *[2]_C_int) (err error) { - _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { - r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go index 4c8dc0ba2e..7efe5ccba3 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go @@ -209,6 +209,92 @@ type RawSockaddrCtl struct { Sc_reserved [5]uint32 } +type RawSockaddrVM struct { + Len uint8 + Family uint8 + Reserved1 uint16 + Port uint32 + Cid uint32 +} + +type XVSockPCB struct { + Xv_len uint32 + Xv_vsockpp uint64 + Xvp_local_cid uint32 + Xvp_local_port uint32 + Xvp_remote_cid uint32 + Xvp_remote_port uint32 + Xvp_rxcnt uint32 + Xvp_txcnt uint32 + Xvp_peer_rxhiwat uint32 + Xvp_peer_rxcnt uint32 + Xvp_last_pid int32 + Xvp_gencnt uint64 + Xv_socket XSocket + _ [4]byte +} + +type XSocket struct { + Xso_len uint32 + Xso_so uint32 + So_type int16 + So_options int16 + So_linger int16 + So_state int16 + So_pcb uint32 + Xso_protocol int32 + Xso_family int32 + So_qlen int16 + So_incqlen int16 + So_qlimit int16 + So_timeo int16 + So_error uint16 + So_pgid int32 + So_oobmark uint32 + So_rcv XSockbuf + So_snd XSockbuf + So_uid uint32 +} + +type XSocket64 struct { + Xso_len uint32 + _ [8]byte + So_type int16 + So_options int16 + So_linger int16 + So_state int16 + _ [8]byte + Xso_protocol int32 + Xso_family int32 + So_qlen int16 + So_incqlen int16 + So_qlimit int16 + So_timeo int16 + So_error uint16 + So_pgid int32 + So_oobmark uint32 + So_rcv XSockbuf + So_snd XSockbuf + So_uid uint32 +} + +type XSockbuf struct { + Cc uint32 + Hiwat uint32 + Mbcnt uint32 + Mbmax uint32 + Lowat int32 + Flags int16 + Timeo int16 +} + +type XVSockPgen struct { + Len uint32 + Count uint64 + Gen uint64 + Sogen uint64 +} + type _Socklen uint32 type Xucred struct { @@ -287,6 +373,11 @@ const ( SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x14 SizeofSockaddrCtl = 0x20 + SizeofSockaddrVM = 0xc + SizeofXvsockpcb = 0xa8 + SizeofXSocket = 0x64 + SizeofXSockbuf = 0x18 + SizeofXVSockPgen = 0x20 SizeofXucred = 0x4c SizeofLinger = 0x8 SizeofIovec = 0x10 @@ -639,3 +730,39 @@ type Ucred struct { Ngroups int16 Groups [16]uint32 } + +type SysvIpcPerm struct { + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint16 + _ uint16 + _ int32 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint64 + Lpid int32 + Cpid int32 + Nattch uint16 + _ [34]byte +} + +const ( + IPC_CREAT = 0x200 + IPC_EXCL = 0x400 + IPC_NOWAIT = 0x800 + IPC_PRIVATE = 0x0 +) + +const ( + IPC_RMID = 0x0 + IPC_SET = 0x1 + IPC_STAT = 0x2 +) + +const ( + SHM_RDONLY = 0x1000 + SHM_RND = 0x2000 +) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go index 96f0e6ae2a..b23a2efe81 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go @@ -209,6 +209,92 @@ type RawSockaddrCtl struct { Sc_reserved [5]uint32 } +type RawSockaddrVM struct { + Len uint8 + Family uint8 + Reserved1 uint16 + Port uint32 + Cid uint32 +} + +type XVSockPCB struct { + Xv_len uint32 + Xv_vsockpp uint64 + Xvp_local_cid uint32 + Xvp_local_port uint32 + Xvp_remote_cid uint32 + Xvp_remote_port uint32 + Xvp_rxcnt uint32 + Xvp_txcnt uint32 + Xvp_peer_rxhiwat uint32 + Xvp_peer_rxcnt uint32 + Xvp_last_pid int32 + Xvp_gencnt uint64 + Xv_socket XSocket + _ [4]byte +} + +type XSocket struct { + Xso_len uint32 + Xso_so uint32 + So_type int16 + So_options int16 + So_linger int16 + So_state int16 + So_pcb uint32 + Xso_protocol int32 + Xso_family int32 + So_qlen int16 + So_incqlen int16 + So_qlimit int16 + So_timeo int16 + So_error uint16 + So_pgid int32 + So_oobmark uint32 + So_rcv XSockbuf + So_snd XSockbuf + So_uid uint32 +} + +type XSocket64 struct { + Xso_len uint32 + _ [8]byte + So_type int16 + So_options int16 + So_linger int16 + So_state int16 + _ [8]byte + Xso_protocol int32 + Xso_family int32 + So_qlen int16 + So_incqlen int16 + So_qlimit int16 + So_timeo int16 + So_error uint16 + So_pgid int32 + So_oobmark uint32 + So_rcv XSockbuf + So_snd XSockbuf + So_uid uint32 +} + +type XSockbuf struct { + Cc uint32 + Hiwat uint32 + Mbcnt uint32 + Mbmax uint32 + Lowat int32 + Flags int16 + Timeo int16 +} + +type XVSockPgen struct { + Len uint32 + Count uint64 + Gen uint64 + Sogen uint64 +} + type _Socklen uint32 type Xucred struct { @@ -287,6 +373,11 @@ const ( SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x14 SizeofSockaddrCtl = 0x20 + SizeofSockaddrVM = 0xc + SizeofXvsockpcb = 0xa8 + SizeofXSocket = 0x64 + SizeofXSockbuf = 0x18 + SizeofXVSockPgen = 0x20 SizeofXucred = 0x4c SizeofLinger = 0x8 SizeofIovec = 0x10 @@ -639,3 +730,39 @@ type Ucred struct { Ngroups int16 Groups [16]uint32 } + +type SysvIpcPerm struct { + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint16 + _ uint16 + _ int32 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint64 + Lpid int32 + Cpid int32 + Nattch uint16 + _ [34]byte +} + +const ( + IPC_CREAT = 0x200 + IPC_EXCL = 0x400 + IPC_NOWAIT = 0x800 + IPC_PRIVATE = 0x0 +) + +const ( + IPC_RMID = 0x0 + IPC_SET = 0x1 + IPC_STAT = 0x2 +) + +const ( + SHM_RDONLY = 0x1000 + SHM_RND = 0x2000 +) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go index 1f99c024af..4eec078e52 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go @@ -31,6 +31,8 @@ type Timeval struct { Usec int32 } +type Time_t int32 + type Rusage struct { Utime Timeval Stime Timeval diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go index ddf0305a5d..7622904a53 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go @@ -31,6 +31,8 @@ type Timeval struct { Usec int64 } +type Time_t int64 + type Rusage struct { Utime Timeval Stime Timeval diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go index dce0a5c80c..19223ce8ec 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go @@ -33,6 +33,8 @@ type Timeval struct { _ [4]byte } +type Time_t int32 + type Rusage struct { Utime Timeval Stime Timeval diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go index e232447025..8e3e33f679 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go @@ -31,6 +31,8 @@ type Timeval struct { Usec int64 } +type Time_t int64 + type Rusage struct { Utime Timeval Stime Timeval diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_illumos_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_illumos_amd64.go index 236f37ef6f..4c485261d6 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_illumos_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_illumos_amd64.go @@ -13,6 +13,8 @@ const ( I_STR = 0x5308 I_POP = 0x5303 I_PUSH = 0x5302 + I_LINK = 0x530c + I_UNLINK = 0x530d I_PLINK = 0x5316 I_PUNLINK = 0x5317 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go index 4b73bb3b63..249ecfcd4c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -3923,3 +3923,36 @@ const ( NFC_SDP_ATTR_URI = 0x1 NFC_SDP_ATTR_SAP = 0x2 ) + +type LandlockRulesetAttr struct { + Access_fs uint64 +} + +type LandlockPathBeneathAttr struct { + Allowed_access uint64 + Parent_fd int32 +} + +const ( + LANDLOCK_RULE_PATH_BENEATH = 0x1 +) + +const ( + IPC_CREAT = 0x200 + IPC_EXCL = 0x400 + IPC_NOWAIT = 0x800 + IPC_PRIVATE = 0x0 + + ipc_64 = 0x100 +) + +const ( + IPC_RMID = 0x0 + IPC_SET = 0x1 + IPC_STAT = 0x2 +) + +const ( + SHM_RDONLY = 0x1000 + SHM_RND = 0x2000 +) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index 72f2e96f32..eeeb9aa39a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -635,3 +635,36 @@ const ( PPS_GETCAP = 0x800470a3 PPS_FETCH = 0xc00470a4 ) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint16 + _ [2]uint8 + Seq uint16 + _ uint16 + _ uint32 + _ uint32 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint32 + Atime uint32 + Atime_high uint32 + Dtime uint32 + Dtime_high uint32 + Ctime uint32 + Ctime_high uint32 + Cpid int32 + Lpid int32 + Nattch uint32 + _ uint32 + _ uint32 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index d5f018d13d..d30e1155cc 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -653,3 +653,33 @@ const ( PPS_GETCAP = 0x800870a3 PPS_FETCH = 0xc00870a4 ) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ [0]uint8 + Seq uint16 + _ uint16 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint64 + Atime int64 + Dtime int64 + Ctime int64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index 675446d936..69d0297520 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -630,3 +630,36 @@ const ( PPS_GETCAP = 0x800470a3 PPS_FETCH = 0xc00470a4 ) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint16 + _ [2]uint8 + Seq uint16 + _ uint16 + _ uint32 + _ uint32 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint32 + Atime uint32 + Atime_high uint32 + Dtime uint32 + Dtime_high uint32 + Ctime uint32 + Ctime_high uint32 + Cpid int32 + Lpid int32 + Nattch uint32 + _ uint32 + _ uint32 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index 711d0711cd..28a0455bc9 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -632,3 +632,33 @@ const ( PPS_GETCAP = 0x800870a3 PPS_FETCH = 0xc00870a4 ) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ [0]uint8 + Seq uint16 + _ uint16 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint64 + Atime int64 + Dtime int64 + Ctime int64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index c1131c7411..64a845483d 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -636,3 +636,35 @@ const ( PPS_GETCAP = 0x400470a3 PPS_FETCH = 0xc00470a4 ) + +const ( + PIDFD_NONBLOCK = 0x80 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ [0]uint8 + Seq uint16 + _ uint16 + _ uint32 + _ uint32 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint32 + Atime uint32 + Dtime uint32 + Ctime uint32 + Cpid int32 + Lpid int32 + Nattch uint32 + Atime_high uint16 + Dtime_high uint16 + Ctime_high uint16 + _ uint16 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index 91d5574ff9..a1b7dee412 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -635,3 +635,33 @@ const ( PPS_GETCAP = 0x400870a3 PPS_FETCH = 0xc00870a4 ) + +const ( + PIDFD_NONBLOCK = 0x80 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ [0]uint8 + Seq uint16 + _ uint16 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint64 + Atime int64 + Dtime int64 + Ctime int64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index 5d721497b7..936fa6a266 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -635,3 +635,33 @@ const ( PPS_GETCAP = 0x400870a3 PPS_FETCH = 0xc00870a4 ) + +const ( + PIDFD_NONBLOCK = 0x80 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ [0]uint8 + Seq uint16 + _ uint16 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint64 + Atime int64 + Dtime int64 + Ctime int64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index a5addd06aa..5dd546fbf0 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -636,3 +636,35 @@ const ( PPS_GETCAP = 0x400470a3 PPS_FETCH = 0xc00470a4 ) + +const ( + PIDFD_NONBLOCK = 0x80 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ [0]uint8 + Seq uint16 + _ uint16 + _ uint32 + _ uint32 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint32 + Atime uint32 + Dtime uint32 + Ctime uint32 + Cpid int32 + Lpid int32 + Nattch uint32 + Atime_high uint16 + Dtime_high uint16 + Ctime_high uint16 + _ uint16 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go index bb6b03dfcb..947b32e434 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go @@ -642,3 +642,37 @@ const ( PPS_GETCAP = 0x400470a3 PPS_FETCH = 0xc00470a4 ) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + Seq uint32 + _ uint32 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Atime_high uint32 + Atime uint32 + Dtime_high uint32 + Dtime uint32 + Ctime_high uint32 + Ctime uint32 + _ uint32 + Segsz uint32 + Cpid int32 + Lpid int32 + Nattch uint32 + _ uint32 + _ uint32 + _ [4]byte +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index 7637243b7b..2a606151b0 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -642,3 +642,32 @@ const ( PPS_GETCAP = 0x400870a3 PPS_FETCH = 0xc00870a4 ) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + Seq uint32 + _ uint32 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Atime int64 + Dtime int64 + Ctime int64 + Segsz uint64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index a1a28e525f..d0d735d02c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -642,3 +642,32 @@ const ( PPS_GETCAP = 0x400870a3 PPS_FETCH = 0xc00870a4 ) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + Seq uint32 + _ uint32 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Atime int64 + Dtime int64 + Ctime int64 + Segsz uint64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go index e0a8a13622..95e3d6d06f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -660,3 +660,33 @@ const ( PPS_GETCAP = 0x800870a3 PPS_FETCH = 0xc00870a4 ) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ [0]uint8 + Seq uint16 + _ uint16 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint64 + Atime int64 + Dtime int64 + Ctime int64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index 21d6e56c70..cccf1ef26a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -656,3 +656,32 @@ const ( PPS_GETCAP = 0x800870a3 PPS_FETCH = 0xc00870a4 ) + +const ( + PIDFD_NONBLOCK = 0x800 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ uint16 + Seq uint16 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Segsz uint64 + Atime int64 + Dtime int64 + Ctime int64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go index 0531e98f64..44fcbe4e9a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -637,3 +637,32 @@ const ( PPS_GETCAP = 0x400870a3 PPS_FETCH = 0xc00870a4 ) + +const ( + PIDFD_NONBLOCK = 0x4000 +) + +type SysvIpcPerm struct { + Key int32 + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode uint32 + _ uint16 + Seq uint16 + _ uint64 + _ uint64 +} +type SysvShmDesc struct { + Perm SysvIpcPerm + Atime int64 + Dtime int64 + Ctime int64 + Segsz uint64 + Cpid int32 + Lpid int32 + Nattch uint64 + _ uint64 + _ uint64 +} diff --git a/src/cmd/vendor/golang.org/x/sys/windows/memory_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/memory_windows.go index 1adb60739a..6dc0920a84 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/memory_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/memory_windows.go @@ -35,3 +35,14 @@ const ( QUOTA_LIMITS_HARDWS_MAX_DISABLE = 0x00000008 QUOTA_LIMITS_HARDWS_MAX_ENABLE = 0x00000004 ) + +type MemoryBasicInformation struct { + BaseAddress uintptr + AllocationBase uintptr + AllocationProtect uint32 + PartitionId uint16 + RegionSize uintptr + State uint32 + Protect uint32 + Type uint32 +} diff --git a/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go index 1215b2ae20..d3b59ae69c 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go @@ -274,6 +274,11 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys VirtualAlloc(address uintptr, size uintptr, alloctype uint32, protect uint32) (value uintptr, err error) = kernel32.VirtualAlloc //sys VirtualFree(address uintptr, size uintptr, freetype uint32) (err error) = kernel32.VirtualFree //sys VirtualProtect(address uintptr, size uintptr, newprotect uint32, oldprotect *uint32) (err error) = kernel32.VirtualProtect +//sys VirtualProtectEx(process Handle, address uintptr, size uintptr, newProtect uint32, oldProtect *uint32) (err error) = kernel32.VirtualProtectEx +//sys VirtualQuery(address uintptr, buffer *MemoryBasicInformation, length uintptr) (err error) = kernel32.VirtualQuery +//sys VirtualQueryEx(process Handle, address uintptr, buffer *MemoryBasicInformation, length uintptr) (err error) = kernel32.VirtualQueryEx +//sys ReadProcessMemory(process Handle, baseAddress uintptr, buffer *byte, size uintptr, numberOfBytesRead *uintptr) (err error) = kernel32.ReadProcessMemory +//sys WriteProcessMemory(process Handle, baseAddress uintptr, buffer *byte, size uintptr, numberOfBytesWritten *uintptr) (err error) = kernel32.WriteProcessMemory //sys TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) = mswsock.TransmitFile //sys ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree bool, mask uint32, retlen *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) = kernel32.ReadDirectoryChangesW //sys FindFirstChangeNotification(path string, watchSubtree bool, notifyFilter uint32) (handle Handle, err error) [failretval==InvalidHandle] = kernel32.FindFirstChangeNotificationW @@ -398,6 +403,11 @@ func NewCallbackCDecl(fn interface{}) uintptr { // Process Status API (PSAPI) //sys EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) = psapi.EnumProcesses +//sys EnumProcessModules(process Handle, module *Handle, cb uint32, cbNeeded *uint32) (err error) = psapi.EnumProcessModules +//sys EnumProcessModulesEx(process Handle, module *Handle, cb uint32, cbNeeded *uint32, filterFlag uint32) (err error) = psapi.EnumProcessModulesEx +//sys GetModuleInformation(process Handle, module Handle, modinfo *ModuleInfo, cb uint32) (err error) = psapi.GetModuleInformation +//sys GetModuleFileNameEx(process Handle, module Handle, filename *uint16, size uint32) (err error) = psapi.GetModuleFileNameExW +//sys GetModuleBaseName(process Handle, module Handle, baseName *uint16, size uint32) (err error) = psapi.GetModuleBaseNameW // NT Native APIs //sys rtlNtStatusToDosErrorNoTeb(ntstatus NTStatus) (ret syscall.Errno) = ntdll.RtlNtStatusToDosErrorNoTeb diff --git a/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go index 17f03312df..88e0ce5d0d 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go @@ -242,6 +242,14 @@ const ( TH32CS_INHERIT = 0x80000000 ) +const ( + // flags for EnumProcessModulesEx + LIST_MODULES_32BIT = 0x01 + LIST_MODULES_64BIT = 0x02 + LIST_MODULES_ALL = 0x03 + LIST_MODULES_DEFAULT = 0x00 +) + const ( // filters for ReadDirectoryChangesW and FindFirstChangeNotificationW FILE_NOTIFY_CHANGE_FILE_NAME = 0x001 @@ -2773,3 +2781,9 @@ const ( // Flag for QueryFullProcessImageName. const PROCESS_NAME_NATIVE = 1 + +type ModuleInfo struct { + BaseOfDll uintptr + SizeOfImage uint32 + EntryPoint uintptr +} diff --git a/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go index 2083ec376e..4ea788e4c4 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go @@ -303,6 +303,7 @@ var ( procReadConsoleW = modkernel32.NewProc("ReadConsoleW") procReadDirectoryChangesW = modkernel32.NewProc("ReadDirectoryChangesW") procReadFile = modkernel32.NewProc("ReadFile") + procReadProcessMemory = modkernel32.NewProc("ReadProcessMemory") procReleaseMutex = modkernel32.NewProc("ReleaseMutex") procRemoveDirectoryW = modkernel32.NewProc("RemoveDirectoryW") procResetEvent = modkernel32.NewProc("ResetEvent") @@ -345,12 +346,16 @@ var ( procVirtualFree = modkernel32.NewProc("VirtualFree") procVirtualLock = modkernel32.NewProc("VirtualLock") procVirtualProtect = modkernel32.NewProc("VirtualProtect") + procVirtualProtectEx = modkernel32.NewProc("VirtualProtectEx") + procVirtualQuery = modkernel32.NewProc("VirtualQuery") + procVirtualQueryEx = modkernel32.NewProc("VirtualQueryEx") procVirtualUnlock = modkernel32.NewProc("VirtualUnlock") procWTSGetActiveConsoleSessionId = modkernel32.NewProc("WTSGetActiveConsoleSessionId") procWaitForMultipleObjects = modkernel32.NewProc("WaitForMultipleObjects") procWaitForSingleObject = modkernel32.NewProc("WaitForSingleObject") procWriteConsoleW = modkernel32.NewProc("WriteConsoleW") procWriteFile = modkernel32.NewProc("WriteFile") + procWriteProcessMemory = modkernel32.NewProc("WriteProcessMemory") procAcceptEx = modmswsock.NewProc("AcceptEx") procGetAcceptExSockaddrs = modmswsock.NewProc("GetAcceptExSockaddrs") procTransmitFile = modmswsock.NewProc("TransmitFile") @@ -377,7 +382,12 @@ var ( procCoTaskMemFree = modole32.NewProc("CoTaskMemFree") procCoUninitialize = modole32.NewProc("CoUninitialize") procStringFromGUID2 = modole32.NewProc("StringFromGUID2") + procEnumProcessModules = modpsapi.NewProc("EnumProcessModules") + procEnumProcessModulesEx = modpsapi.NewProc("EnumProcessModulesEx") procEnumProcesses = modpsapi.NewProc("EnumProcesses") + procGetModuleBaseNameW = modpsapi.NewProc("GetModuleBaseNameW") + procGetModuleFileNameExW = modpsapi.NewProc("GetModuleFileNameExW") + procGetModuleInformation = modpsapi.NewProc("GetModuleInformation") procSubscribeServiceChangeNotifications = modsechost.NewProc("SubscribeServiceChangeNotifications") procUnsubscribeServiceChangeNotifications = modsechost.NewProc("UnsubscribeServiceChangeNotifications") procGetUserNameExW = modsecur32.NewProc("GetUserNameExW") @@ -2631,6 +2641,14 @@ func ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) ( return } +func ReadProcessMemory(process Handle, baseAddress uintptr, buffer *byte, size uintptr, numberOfBytesRead *uintptr) (err error) { + r1, _, e1 := syscall.Syscall6(procReadProcessMemory.Addr(), 5, uintptr(process), uintptr(baseAddress), uintptr(unsafe.Pointer(buffer)), uintptr(size), uintptr(unsafe.Pointer(numberOfBytesRead)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func ReleaseMutex(mutex Handle) (err error) { r1, _, e1 := syscall.Syscall(procReleaseMutex.Addr(), 1, uintptr(mutex), 0, 0) if r1 == 0 { @@ -2985,6 +3003,30 @@ func VirtualProtect(address uintptr, size uintptr, newprotect uint32, oldprotect return } +func VirtualProtectEx(process Handle, address uintptr, size uintptr, newProtect uint32, oldProtect *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procVirtualProtectEx.Addr(), 5, uintptr(process), uintptr(address), uintptr(size), uintptr(newProtect), uintptr(unsafe.Pointer(oldProtect)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func VirtualQuery(address uintptr, buffer *MemoryBasicInformation, length uintptr) (err error) { + r1, _, e1 := syscall.Syscall(procVirtualQuery.Addr(), 3, uintptr(address), uintptr(unsafe.Pointer(buffer)), uintptr(length)) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func VirtualQueryEx(process Handle, address uintptr, buffer *MemoryBasicInformation, length uintptr) (err error) { + r1, _, e1 := syscall.Syscall6(procVirtualQueryEx.Addr(), 4, uintptr(process), uintptr(address), uintptr(unsafe.Pointer(buffer)), uintptr(length), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func VirtualUnlock(addr uintptr, length uintptr) (err error) { r1, _, e1 := syscall.Syscall(procVirtualUnlock.Addr(), 2, uintptr(addr), uintptr(length), 0) if r1 == 0 { @@ -3041,6 +3083,14 @@ func WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) return } +func WriteProcessMemory(process Handle, baseAddress uintptr, buffer *byte, size uintptr, numberOfBytesWritten *uintptr) (err error) { + r1, _, e1 := syscall.Syscall6(procWriteProcessMemory.Addr(), 5, uintptr(process), uintptr(baseAddress), uintptr(unsafe.Pointer(buffer)), uintptr(size), uintptr(unsafe.Pointer(numberOfBytesWritten)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (err error) { r1, _, e1 := syscall.Syscall9(procAcceptEx.Addr(), 8, uintptr(ls), uintptr(as), uintptr(unsafe.Pointer(buf)), uintptr(rxdatalen), uintptr(laddrlen), uintptr(raddrlen), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(overlapped)), 0) if r1 == 0 { @@ -3225,6 +3275,22 @@ func stringFromGUID2(rguid *GUID, lpsz *uint16, cchMax int32) (chars int32) { return } +func EnumProcessModules(process Handle, module *Handle, cb uint32, cbNeeded *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procEnumProcessModules.Addr(), 4, uintptr(process), uintptr(unsafe.Pointer(module)), uintptr(cb), uintptr(unsafe.Pointer(cbNeeded)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func EnumProcessModulesEx(process Handle, module *Handle, cb uint32, cbNeeded *uint32, filterFlag uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procEnumProcessModulesEx.Addr(), 5, uintptr(process), uintptr(unsafe.Pointer(module)), uintptr(cb), uintptr(unsafe.Pointer(cbNeeded)), uintptr(filterFlag), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) { var _p0 *uint32 if len(processIds) > 0 { @@ -3237,6 +3303,30 @@ func EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) { return } +func GetModuleBaseName(process Handle, module Handle, baseName *uint16, size uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetModuleBaseNameW.Addr(), 4, uintptr(process), uintptr(module), uintptr(unsafe.Pointer(baseName)), uintptr(size), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetModuleFileNameEx(process Handle, module Handle, filename *uint16, size uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetModuleFileNameExW.Addr(), 4, uintptr(process), uintptr(module), uintptr(unsafe.Pointer(filename)), uintptr(size), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetModuleInformation(process Handle, module Handle, modinfo *ModuleInfo, cb uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetModuleInformation.Addr(), 4, uintptr(process), uintptr(module), uintptr(unsafe.Pointer(modinfo)), uintptr(cb), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func SubscribeServiceChangeNotifications(service Handle, eventType uint32, callback uintptr, callbackCtx uintptr, subscription *uintptr) (ret error) { ret = procSubscribeServiceChangeNotifications.Find() if ret != nil { diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index ecb170d290..ad08e583fb 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -1,4 +1,4 @@ -# github.com/google/pprof v0.0.0-20211001005136-7fe48b4c820b +# github.com/google/pprof v0.0.0-20211104044539-f987b9c94b31 ## explicit; go 1.14 github.com/google/pprof/driver github.com/google/pprof/internal/binutils @@ -15,8 +15,8 @@ github.com/google/pprof/profile github.com/google/pprof/third_party/d3 github.com/google/pprof/third_party/d3flamegraph github.com/google/pprof/third_party/svgpan -# github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 -## explicit +# github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d +## explicit; go 1.12 github.com/ianlancetaylor/demangle # golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1 ## explicit; go 1.17 @@ -42,7 +42,7 @@ golang.org/x/mod/zip # golang.org/x/sync v0.0.0-20210220032951-036812b2e83c ## explicit golang.org/x/sync/semaphore -# golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e +# golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac ## explicit; go 1.17 golang.org/x/sys/internal/unsafeheader golang.org/x/sys/plan9 diff --git a/src/go.mod b/src/go.mod index 35231cf911..7d982c75aa 100644 --- a/src/go.mod +++ b/src/go.mod @@ -8,6 +8,6 @@ require ( ) require ( - golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e // indirect + golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect golang.org/x/text v0.3.7 // indirect ) diff --git a/src/go.sum b/src/go.sum index 621d61384a..ff1279697d 100644 --- a/src/go.sum +++ b/src/go.sum @@ -2,7 +2,7 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s3 golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/net v0.0.0-20211005215030-d2e5035098b3 h1:G64nFNerDErBd2KdvHvIn3Ee6ccUQBTfhDZEO0DccfU= golang.org/x/net v0.0.0-20211005215030-d2e5035098b3/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e h1:XMgFehsDnnLGtjvjOfqWSUzt0alpTR1RSEuznObga2c= -golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac h1:oN6lz7iLW/YC7un8pq+9bOLyXrprv2+DKfkJY+2LJJw= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index 683040db9b..770a08e1fb 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -19,7 +19,7 @@ golang.org/x/net/idna golang.org/x/net/lif golang.org/x/net/nettest golang.org/x/net/route -# golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e +# golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac ## explicit; go 1.17 golang.org/x/sys/cpu # golang.org/x/text v0.3.7 -- GitLab From 577287728a8e8abbcbc6c96fdd49feb5a99ced0c Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Wed, 3 Nov 2021 16:28:51 -0400 Subject: [PATCH 1955/2500] runtime: clear upper half of sec in ARM walltime https://golang.org/cl/246763 accidentally changed this to assign the old value of vdsoPC to the upper half of sec as that is the last value in R1. The old value of vdsoPC is usually zero, so this typically works. However, the reentrant case will have a non-zero value, resulting in a bogus returned time. I am unsure if walltime is reachable from a signal handler, so this may never occur. Change-Id: I8562d6ec2a845fcffee9618d994b8ea57fbd199e Reviewed-on: https://go-review.googlesource.com/c/go/+/361159 Trust: Michael Pratt Run-TryBot: Michael Pratt TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/sys_linux_arm.s | 1 + 1 file changed, 1 insertion(+) diff --git a/src/runtime/sys_linux_arm.s b/src/runtime/sys_linux_arm.s index 3f30da7b54..65935de99f 100644 --- a/src/runtime/sys_linux_arm.s +++ b/src/runtime/sys_linux_arm.s @@ -360,6 +360,7 @@ finish: MOVW R1, m_vdsoPC(R5) MOVW R0, sec_lo+0(FP) + MOVW $0, R1 MOVW R1, sec_hi+4(FP) MOVW R2, nsec+8(FP) RET -- GitLab From b2149ac336987940b3f14c50c064a43bf9a761de Mon Sep 17 00:00:00 2001 From: jiahua wang Date: Thu, 4 Nov 2021 10:13:11 +0800 Subject: [PATCH 1956/2500] net/netip: fix various typos in comment Change-Id: I02724dadacd9b3f23ca7e6bda581cba62ceff828 Reviewed-on: https://go-review.googlesource.com/c/go/+/361274 Reviewed-by: Ian Lance Taylor Reviewed-by: Damien Neil Trust: Damien Neil Run-TryBot: Damien Neil TryBot-Result: Go Bot --- src/net/netip/netip.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/netip/netip.go b/src/net/netip/netip.go index d15a4947ac..02a4aa0452 100644 --- a/src/net/netip/netip.go +++ b/src/net/netip/netip.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package netip defines a IP address type that's a small value type. +// Package netip defines an IP address type that's a small value type. // Building on that Addr type, the package also defines AddrPort (an // IP address and a port), and Prefix (an IP address and a bit length // prefix). -- GitLab From 5af93a2d1556226656f003f65ac1de034b8fb55f Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Thu, 4 Nov 2021 13:55:31 -0400 Subject: [PATCH 1957/2500] internal/fuzz: improve minimizing message In order to know the actual number of bytes of the entire corpus entry, the coordinator would likely need to unmarshal the bytes and tally up the length. That's more work than it is worth, so this change just clarifies that the printed # of bytes is the length of the entire file, not just the entry itself. Fixes #48989 Change-Id: I6fa0c0206a249cefdf6335040c560ec0c5a55b4a Reviewed-on: https://go-review.googlesource.com/c/go/+/361414 Trust: Katie Hockman Run-TryBot: Katie Hockman Reviewed-by: Roland Shoemaker TryBot-Result: Go Bot --- src/internal/fuzz/fuzz.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index aef1dee978..8bd40fe8bf 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -246,7 +246,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err // Send it back to a worker for minimization. Disable inputC so // other workers don't continue fuzzing. c.crashMinimizing = &result - fmt.Fprintf(c.opts.Log, "fuzz: minimizing %d-byte crash input...\n", len(result.entry.Data)) + fmt.Fprintf(c.opts.Log, "fuzz: minimizing %d-byte crash file\n", len(result.entry.Data)) c.queueForMinimization(result, nil) } else if !crashWritten { // Found a crasher that's either minimized or not minimizable. -- GitLab From 988efd58197205060ace508d29984fbab6eb3840 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 2 Nov 2021 18:30:08 -0400 Subject: [PATCH 1958/2500] cmd/link: don't use label symbol for absolute address relocations on ARM64 PE On ARM64 PE, when external linking, the PE relocation does not have an explicit addend, and instead has the addend encoded in the instruction or data. An instruction (e.g. ADRP, ADD) has limited width for the addend, so when the addend is large we use a label symbol, which points to the middle of the original target symbol, and a smaller addend. But for an absolute address relocation in the data section, we have the full width to encode the addend and we should not use the label symbol. Also, since we do not adjust the addend in the data, using the label symbol will actually make it point to the wrong address. E.g for an R_ADDR relocation targeting x+0x123456, we should emit 0x123456 in the data with an IMAGE_REL_ARM64_ADDR64 relocation pointing to x, whereas the current code emits 0x123456 in the data with an IMAGE_REL_ARM64_ADDR64 relocation pointing to the label symbol x+1MB, so it will actually be resolved to x+0x223456. This CL fixes this. Fixes #47557. Change-Id: I64e02b56f1d792f8c20ca61b78623ef5c3e34d7e Reviewed-on: https://go-review.googlesource.com/c/go/+/360895 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/link/internal/arm64/asm.go | 2 +- src/cmd/link/link_test.go | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/cmd/link/internal/arm64/asm.go b/src/cmd/link/internal/arm64/asm.go index f56c9c1222..abae0f87bc 100644 --- a/src/cmd/link/internal/arm64/asm.go +++ b/src/cmd/link/internal/arm64/asm.go @@ -602,7 +602,7 @@ func pereloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, rs := r.Xsym rt := r.Type - if r.Xadd != signext21(r.Xadd) { + if rt == objabi.R_ADDRARM64 && r.Xadd != signext21(r.Xadd) { // If the relocation target would overflow the addend, then target // a linker-manufactured label symbol with a smaller addend instead. label := ldr.Lookup(offsetLabelName(ldr, rs, r.Xadd/peRelocLimit*peRelocLimit), ldr.SymVersion(rs)) diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go index 2b0b2dc4a1..ad7658bb25 100644 --- a/src/cmd/link/link_test.go +++ b/src/cmd/link/link_test.go @@ -997,13 +997,31 @@ package main var x = [1<<25]byte{1<<23: 23, 1<<24: 24} +var addr = [...]*byte{ + &x[1<<23-1], + &x[1<<23], + &x[1<<23+1], + &x[1<<24-1], + &x[1<<24], + &x[1<<24+1], +} + func main() { + // check relocations in instructions check(x[1<<23-1], 0) check(x[1<<23], 23) check(x[1<<23+1], 0) check(x[1<<24-1], 0) check(x[1<<24], 24) check(x[1<<24+1], 0) + + // check absolute address relocations in data + check(*addr[0], 0) + check(*addr[1], 23) + check(*addr[2], 0) + check(*addr[3], 0) + check(*addr[4], 24) + check(*addr[5], 0) } func check(x, y byte) { -- GitLab From a108b280bc724779ebaa6656d35f0fb307fb2a9b Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Tue, 13 Apr 2021 03:07:27 +0000 Subject: [PATCH 1959/2500] runtime: implement GC pacer redesign This change implements the GC pacer redesign outlined in #44167 and the accompanying design document, behind a GOEXPERIMENT flag that is on by default. In addition to adding the new pacer, this CL also includes code to track and account for stack and globals scan work in the pacer and in the assist credit system. The new pacer also deviates slightly from the document in that it increases the bound on the minimum trigger ratio from 0.6 (scaled by GOGC) to 0.7. The logic behind this change is that the new pacer much more consistently hits the goal (good!) leading to slightly less frequent GC cycles, but _longer_ ones (in this case, bad!). It turns out that the cost of having the GC on hurts throughput significantly (per byte of memory used), though tail latencies can improve by up to 10%! To be conservative, this change moves the value to 0.7 where there is a small improvement to both throughput and latency, given the memory use. Because the new pacer accounts for the two most significant sources of scan work after heap objects, it is now also safer to reduce the minimum heap size without leading to very poor amortization. This change thus decreases the minimum heap size to 512 KiB, which corresponds to the fact that the runtime has around 200 KiB of scannable globals always there, up-front, providing a baseline. Benchmark results: https://perf.golang.org/search?q=upload:20211001.6 tile38's KNearest benchmark shows a memory increase, but throughput (and latency) per byte of memory used is better. gopher-lua showed an increase in both CPU time and memory usage, but subsequent attempts to reproduce this behavior are inconsistent. Sometimes the overall performance is better, sometimes it's worse. This suggests that the benchmark is fairly noisy in a way not captured by the benchmarking framework itself. biogo-igor is the only benchmark to show a significant performance loss. This benchmark exhibits a very high GC rate, with relatively little work to do in each cycle. The idle mark workers are quite active. In the new pacer, mark phases are longer, mark assists are fewer, and some of that time in mark assists has shifted to idle workers. Linux perf indicates that the difference in CPU time can be mostly attributed to write-barrier slow path related calls, which in turn indicates that the write barrier being on for longer is the primary culprit. This also explains the memory increase, as a longer mark phase leads to more memory allocated black, surviving an extra cycle and contributing to the heap goal. For #44167. Change-Id: I8ac7cfef7d593e4a642c9b2be43fb3591a8ec9c4 Reviewed-on: https://go-review.googlesource.com/c/go/+/309869 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Austin Clements Reviewed-by: Michael Pratt --- .../goexperiment/exp_pacerredesign_off.go | 9 + .../goexperiment/exp_pacerredesign_on.go | 9 + src/internal/goexperiment/flags.go | 6 + src/runtime/export_test.go | 4 +- src/runtime/mgc.go | 2 + src/runtime/mgcmark.go | 117 ++-- src/runtime/mgcpacer.go | 498 +++++++++++++++--- src/runtime/mgcpacer_test.go | 127 ++++- src/runtime/mgcwork.go | 11 +- 9 files changed, 680 insertions(+), 103 deletions(-) create mode 100644 src/internal/goexperiment/exp_pacerredesign_off.go create mode 100644 src/internal/goexperiment/exp_pacerredesign_on.go diff --git a/src/internal/goexperiment/exp_pacerredesign_off.go b/src/internal/goexperiment/exp_pacerredesign_off.go new file mode 100644 index 0000000000..62e1831437 --- /dev/null +++ b/src/internal/goexperiment/exp_pacerredesign_off.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.pacerredesign +// +build !goexperiment.pacerredesign + +package goexperiment + +const PacerRedesign = false +const PacerRedesignInt = 0 diff --git a/src/internal/goexperiment/exp_pacerredesign_on.go b/src/internal/goexperiment/exp_pacerredesign_on.go new file mode 100644 index 0000000000..b22b031009 --- /dev/null +++ b/src/internal/goexperiment/exp_pacerredesign_on.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.pacerredesign +// +build goexperiment.pacerredesign + +package goexperiment + +const PacerRedesign = true +const PacerRedesignInt = 1 diff --git a/src/internal/goexperiment/flags.go b/src/internal/goexperiment/flags.go index 0a61a0e5fc..3bf19222e1 100644 --- a/src/internal/goexperiment/flags.go +++ b/src/internal/goexperiment/flags.go @@ -83,4 +83,10 @@ type Flags struct { // Requires wrappers (to do ABI translation), and reflect (so // reflection calls use registers). RegabiArgs bool + + // PacerRedesign enables the new GC pacer in the runtime. + // + // Details regarding the new pacer may be found at + // https://golang.org/design/44167-gc-pacer-redesign + PacerRedesign bool } diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index 533627fa58..5149252c83 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -1290,7 +1290,9 @@ type GCControllerReviseDelta struct { func (c *GCController) Revise(d GCControllerReviseDelta) { c.heapLive += uint64(d.HeapLive) c.heapScan += uint64(d.HeapScan) - c.scanWork += d.HeapScanWork + d.StackScanWork + d.GlobalsScanWork + c.heapScanWork.Add(d.HeapScanWork) + c.stackScanWork.Add(d.StackScanWork) + c.globalsScanWork.Add(d.GlobalsScanWork) c.revise() } diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go index 03711a9617..96f4157b59 100644 --- a/src/runtime/mgc.go +++ b/src/runtime/mgc.go @@ -1084,6 +1084,8 @@ func gcMarkTermination(nextTriggerRatio float64) { print(" ms cpu, ", work.heap0>>20, "->", work.heap1>>20, "->", work.heap2>>20, " MB, ", work.heapGoal>>20, " MB goal, ", + gcController.stackScan>>20, " MB stacks, ", + gcController.globalsScan>>20, " MB globals, ", work.maxprocs, " P") if work.userForced { print(" (forced)") diff --git a/src/runtime/mgcmark.go b/src/runtime/mgcmark.go index efda65fe1e..a5129bd1ee 100644 --- a/src/runtime/mgcmark.go +++ b/src/runtime/mgcmark.go @@ -8,6 +8,7 @@ package runtime import ( "internal/goarch" + "internal/goexperiment" "runtime/internal/atomic" "runtime/internal/sys" "unsafe" @@ -151,20 +152,28 @@ var oneptrmask = [...]uint8{1} // // Preemption must be disabled (because this uses a gcWork). // +// Returns the amount of GC work credit produced by the operation. +// If flushBgCredit is true, then that credit is also flushed +// to the background credit pool. +// // nowritebarrier is only advisory here. // //go:nowritebarrier -func markroot(gcw *gcWork, i uint32) { +func markroot(gcw *gcWork, i uint32, flushBgCredit bool) int64 { // Note: if you add a case here, please also update heapdump.go:dumproots. + var workDone int64 + var workCounter *atomic.Int64 switch { case work.baseData <= i && i < work.baseBSS: + workCounter = &gcController.globalsScanWork for _, datap := range activeModules() { - markrootBlock(datap.data, datap.edata-datap.data, datap.gcdatamask.bytedata, gcw, int(i-work.baseData)) + workDone += markrootBlock(datap.data, datap.edata-datap.data, datap.gcdatamask.bytedata, gcw, int(i-work.baseData)) } case work.baseBSS <= i && i < work.baseSpans: + workCounter = &gcController.globalsScanWork for _, datap := range activeModules() { - markrootBlock(datap.bss, datap.ebss-datap.bss, datap.gcbssmask.bytedata, gcw, int(i-work.baseBSS)) + workDone += markrootBlock(datap.bss, datap.ebss-datap.bss, datap.gcbssmask.bytedata, gcw, int(i-work.baseBSS)) } case i == fixedRootFinalizers: @@ -184,6 +193,7 @@ func markroot(gcw *gcWork, i uint32) { default: // the rest is scanning goroutine stacks + workCounter = &gcController.stackScanWork var gp *g if work.baseStacks <= i && i < work.baseEnd { // N.B. Atomic read of allglen in gcMarkRootPrepare @@ -230,7 +240,7 @@ func markroot(gcw *gcWork, i uint32) { if gp.gcscandone { throw("g already scanned") } - scanstack(gp, gcw) + workDone += scanstack(gp, gcw) gp.gcscandone = true resumeG(stopped) @@ -239,13 +249,24 @@ func markroot(gcw *gcWork, i uint32) { } }) } + if goexperiment.PacerRedesign { + if workCounter != nil && workDone != 0 { + workCounter.Add(workDone) + if flushBgCredit { + gcFlushBgCredit(workDone) + } + } + } + return workDone } // markrootBlock scans the shard'th shard of the block of memory [b0, // b0+n0), with the given pointer mask. // +// Returns the amount of work done. +// //go:nowritebarrier -func markrootBlock(b0, n0 uintptr, ptrmask0 *uint8, gcw *gcWork, shard int) { +func markrootBlock(b0, n0 uintptr, ptrmask0 *uint8, gcw *gcWork, shard int) int64 { if rootBlockBytes%(8*goarch.PtrSize) != 0 { // This is necessary to pick byte offsets in ptrmask0. throw("rootBlockBytes must be a multiple of 8*ptrSize") @@ -256,7 +277,7 @@ func markrootBlock(b0, n0 uintptr, ptrmask0 *uint8, gcw *gcWork, shard int) { // These tests are written to avoid any possible overflow. off := uintptr(shard) * rootBlockBytes if off >= n0 { - return + return 0 } b := b0 + off ptrmask := (*uint8)(add(unsafe.Pointer(ptrmask0), uintptr(shard)*(rootBlockBytes/(8*goarch.PtrSize)))) @@ -267,6 +288,7 @@ func markrootBlock(b0, n0 uintptr, ptrmask0 *uint8, gcw *gcWork, shard int) { // Scan this shard. scanblock(b, n, ptrmask, gcw, nil) + return int64(n) } // markrootFreeGStacks frees stacks of dead Gs. @@ -681,6 +703,13 @@ func gcFlushBgCredit(scanWork int64) { // scanstack scans gp's stack, greying all pointers found on the stack. // +// For goexperiment.PacerRedesign: +// Returns the amount of scan work performed, but doesn't update +// gcController.stackScanWork or flush any credit. Any background credit produced +// by this function should be flushed by its caller. scanstack itself can't +// safely flush because it may result in trying to wake up a goroutine that +// was just scanned, resulting in a self-deadlock. +// // scanstack will also shrink the stack if it is safe to do so. If it // is not, it schedules a stack shrink for the next synchronous safe // point. @@ -690,7 +719,7 @@ func gcFlushBgCredit(scanWork int64) { // //go:nowritebarrier //go:systemstack -func scanstack(gp *g, gcw *gcWork) { +func scanstack(gp *g, gcw *gcWork) int64 { if readgstatus(gp)&_Gscan == 0 { print("runtime:scanstack: gp=", gp, ", goid=", gp.goid, ", gp->atomicstatus=", hex(readgstatus(gp)), "\n") throw("scanstack - bad status") @@ -701,7 +730,7 @@ func scanstack(gp *g, gcw *gcWork) { print("runtime: gp=", gp, ", goid=", gp.goid, ", gp->atomicstatus=", readgstatus(gp), "\n") throw("mark - bad status") case _Gdead: - return + return 0 case _Grunning: print("runtime: gp=", gp, ", goid=", gp.goid, ", gp->atomicstatus=", readgstatus(gp), "\n") throw("scanstack: goroutine not stopped") @@ -713,6 +742,15 @@ func scanstack(gp *g, gcw *gcWork) { throw("can't scan our own stack") } + // stackSize is the amount of work we'll be reporting. + // + // We report the total stack size, more than we scan, + // because this number needs to line up with gcControllerState's + // stackScan and scannableStackSize fields. + // + // See the documentation on those fields for more information. + stackSize := gp.stack.hi - gp.stack.lo + if isShrinkStackSafe(gp) { // Shrink the stack if not much of it is being used. shrinkstack(gp) @@ -852,6 +890,7 @@ func scanstack(gp *g, gcw *gcWork) { if state.buf != nil || state.cbuf != nil || state.freeBuf != nil { throw("remaining pointer buffers") } + return int64(stackSize) } // Scan a stack frame: local variables and function arguments/results. @@ -984,7 +1023,7 @@ func gcDrain(gcw *gcWork, flags gcDrainFlags) { flushBgCredit := flags&gcDrainFlushBgCredit != 0 idle := flags&gcDrainIdle != 0 - initScanWork := gcw.scanWork + initScanWork := gcw.heapScanWork // checkWork is the scan work before performing the next // self-preempt check. @@ -1007,7 +1046,7 @@ func gcDrain(gcw *gcWork, flags gcDrainFlags) { if job >= work.markrootJobs { break } - markroot(gcw, job) + markroot(gcw, job, flushBgCredit) if check != nil && check() { goto done } @@ -1046,14 +1085,14 @@ func gcDrain(gcw *gcWork, flags gcDrainFlags) { // Flush background scan work credit to the global // account if we've accumulated enough locally so // mutator assists can draw on it. - if gcw.scanWork >= gcCreditSlack { - atomic.Xaddint64(&gcController.scanWork, gcw.scanWork) + if gcw.heapScanWork >= gcCreditSlack { + gcController.heapScanWork.Add(gcw.heapScanWork) if flushBgCredit { - gcFlushBgCredit(gcw.scanWork - initScanWork) + gcFlushBgCredit(gcw.heapScanWork - initScanWork) initScanWork = 0 } - checkWork -= gcw.scanWork - gcw.scanWork = 0 + checkWork -= gcw.heapScanWork + gcw.heapScanWork = 0 if checkWork <= 0 { checkWork += drainCheckThreshold @@ -1066,12 +1105,12 @@ func gcDrain(gcw *gcWork, flags gcDrainFlags) { done: // Flush remaining scan work credit. - if gcw.scanWork > 0 { - atomic.Xaddint64(&gcController.scanWork, gcw.scanWork) + if gcw.heapScanWork > 0 { + gcController.heapScanWork.Add(gcw.heapScanWork) if flushBgCredit { - gcFlushBgCredit(gcw.scanWork - initScanWork) + gcFlushBgCredit(gcw.heapScanWork - initScanWork) } - gcw.scanWork = 0 + gcw.heapScanWork = 0 } } @@ -1095,10 +1134,10 @@ func gcDrainN(gcw *gcWork, scanWork int64) int64 { // There may already be scan work on the gcw, which we don't // want to claim was done by this call. - workFlushed := -gcw.scanWork + workFlushed := -gcw.heapScanWork gp := getg().m.curg - for !gp.preempt && workFlushed+gcw.scanWork < scanWork { + for !gp.preempt && workFlushed+gcw.heapScanWork < scanWork { // See gcDrain comment. if work.full == 0 { gcw.balance() @@ -1117,13 +1156,13 @@ func gcDrainN(gcw *gcWork, scanWork int64) int64 { if b == 0 { // Try to do a root job. - // - // TODO: Assists should get credit for this - // work. if work.markrootNext < work.markrootJobs { job := atomic.Xadd(&work.markrootNext, +1) - 1 if job < work.markrootJobs { - markroot(gcw, job) + work := markroot(gcw, job, false) + if goexperiment.PacerRedesign { + workFlushed += work + } continue } } @@ -1134,10 +1173,10 @@ func gcDrainN(gcw *gcWork, scanWork int64) int64 { scanobject(b, gcw) // Flush background scan work credit. - if gcw.scanWork >= gcCreditSlack { - atomic.Xaddint64(&gcController.scanWork, gcw.scanWork) - workFlushed += gcw.scanWork - gcw.scanWork = 0 + if gcw.heapScanWork >= gcCreditSlack { + gcController.heapScanWork.Add(gcw.heapScanWork) + workFlushed += gcw.heapScanWork + gcw.heapScanWork = 0 } } @@ -1145,14 +1184,14 @@ func gcDrainN(gcw *gcWork, scanWork int64) int64 { // here because this never flushes to bgScanCredit and // gcw.dispose will flush any remaining work to scanWork. - return workFlushed + gcw.scanWork + return workFlushed + gcw.heapScanWork } // scanblock scans b as scanobject would, but using an explicit // pointer bitmap instead of the heap bitmap. // // This is used to scan non-heap roots, so it does not update -// gcw.bytesMarked or gcw.scanWork. +// gcw.bytesMarked or gcw.heapScanWork. // // If stk != nil, possible stack pointers are also reported to stk.putPtr. //go:nowritebarrier @@ -1282,7 +1321,7 @@ func scanobject(b uintptr, gcw *gcWork) { } } gcw.bytesMarked += uint64(n) - gcw.scanWork += int64(i) + gcw.heapScanWork += int64(i) } // scanConservative scans block [b, b+n) conservatively, treating any @@ -1521,7 +1560,19 @@ func gcmarknewobject(span *mspan, obj, size, scanSize uintptr) { gcw := &getg().m.p.ptr().gcw gcw.bytesMarked += uint64(size) - gcw.scanWork += int64(scanSize) + if !goexperiment.PacerRedesign { + // The old pacer counts newly allocated memory toward + // heapScanWork because heapScan is continuously updated + // throughout the GC cyle with newly allocated memory. However, + // these objects are never actually scanned, so we need + // to account for them in heapScanWork here, "faking" their work. + // Otherwise the pacer will think it's always behind, potentially + // by a large margin. + // + // The new pacer doesn't care about this because it ceases to updated + // heapScan once a GC cycle starts, effectively snapshotting it. + gcw.heapScanWork += int64(scanSize) + } } // gcMarkTinyAllocs greys all active tiny alloc blocks. diff --git a/src/runtime/mgcpacer.go b/src/runtime/mgcpacer.go index af43e6258f..f886a07da1 100644 --- a/src/runtime/mgcpacer.go +++ b/src/runtime/mgcpacer.go @@ -6,6 +6,7 @@ package runtime import ( "internal/cpu" + "internal/goexperiment" "runtime/internal/atomic" "unsafe" ) @@ -13,7 +14,8 @@ import ( const ( // gcGoalUtilization is the goal CPU utilization for // marking as a fraction of GOMAXPROCS. - gcGoalUtilization = 0.30 + gcGoalUtilization = goexperiment.PacerRedesignInt*gcBackgroundUtilization + + (1-goexperiment.PacerRedesignInt)*(gcBackgroundUtilization+0.05) // gcBackgroundUtilization is the fixed CPU utilization for background // marking. It must be <= gcGoalUtilization. The difference between @@ -26,10 +28,15 @@ const ( // better control CPU and heap growth. However, the larger the gap, // the more mutator assists are expected to happen, which impact // mutator latency. + // + // If goexperiment.PacerRedesign, the trigger feedback controller + // is replaced with an estimate of the mark/cons ratio that doesn't + // have the same saturation issues, so this is set equal to + // gcGoalUtilization. gcBackgroundUtilization = 0.25 // gcCreditSlack is the amount of scan work credit that can - // accumulate locally before updating gcController.scanWork and, + // accumulate locally before updating gcController.heapScanWork and, // optionally, gcController.bgScanCredit. Lower values give a more // accurate assist ratio and make it more likely that assists will // successfully steal background credit. Higher values reduce memory @@ -46,7 +53,8 @@ const ( gcOverAssistWork = 64 << 10 // defaultHeapMinimum is the value of heapMinimum for GOGC==100. - defaultHeapMinimum = 4 << 20 + defaultHeapMinimum = goexperiment.PacerRedesignInt*(512<<10) + + (1-goexperiment.PacerRedesignInt)*(4<<20) // scannableStackSizeSlack is the bytes of stack space allocated or freed // that can accumulate on a P before updating gcController.stackSize. @@ -108,6 +116,8 @@ type gcControllerState struct { // during mark termination for the next cycle's trigger. // // Protected by mheap_.lock or a STW. + // + // Used if !goexperiment.PacerRedesign. triggerRatio float64 // trigger is the heap size that triggers marking. @@ -122,6 +132,31 @@ type gcControllerState struct { // Protected by mheap_.lock or a STW. trigger uint64 + // consMark is the estimated per-CPU consMark ratio for the application. + // + // It represents the ratio between the application's allocation + // rate, as bytes allocated per CPU-time, and the GC's scan rate, + // as bytes scanned per CPU-time. + // The units of this ratio are (B / cpu-ns) / (B / cpu-ns). + // + // At a high level, this value is computed as the bytes of memory + // allocated (cons) per unit of scan work completed (mark) in a GC + // cycle, divided by the CPU time spent on each activity. + // + // Updated at the end of each GC cycle, in endCycle. + // + // For goexperiment.PacerRedesign. + consMark float64 + + // consMarkController holds the state for the mark-cons ratio + // estimation over time. + // + // Its purpose is to smooth out noisiness in the computation of + // consMark; see consMark for details. + // + // For goexperiment.PacerRedesign. + consMarkController piController + // heapGoal is the goal heapLive for when next GC ends. // Set to ^uint64(0) if disabled. // @@ -164,12 +199,23 @@ type gcControllerState struct { // is the live heap (as counted by heapLive), but omitting // no-scan objects and no-scan tails of objects. // - // Whenever this is updated, call this gcControllerState's - // revise() method. + // For !goexperiment.PacerRedesign: Whenever this is updated, + // call this gcControllerState's revise() method. It is read + // and written atomically or with the world stopped. // - // Read and written atomically or with the world stopped. + // For goexperiment.PacerRedesign: This value is fixed at the + // start of a GC cycle, so during a GC cycle it is safe to + // read without atomics, and it represents the maximum scannable + // heap. heapScan uint64 + // lastHeapScan is the number of bytes of heap that were scanned + // last GC cycle. It is the same as heapMarked, but only + // includes the "scannable" parts of objects. + // + // Updated when the world is stopped. + lastHeapScan uint64 + // stackScan is a snapshot of scannableStackSize taken at each GC // STW pause and is used in pacing decisions. // @@ -179,6 +225,12 @@ type gcControllerState struct { // scannableStackSize is the amount of allocated goroutine stack space in // use by goroutines. // + // This number tracks allocated goroutine stack space rather than used + // goroutine stack space (i.e. what is actually scanned) because used + // goroutine stack space is much harder to measure cheaply. By using + // allocated space, we make an overestimate; this is OK, it's better + // to conservatively overcount than undercount. + // // Read and updated atomically. scannableStackSize uint64 @@ -194,16 +246,26 @@ type gcControllerState struct { // next mark termination. heapMarked uint64 - // scanWork is the total scan work performed this cycle. This - // is updated atomically during the cycle. Updates occur in - // bounded batches, since it is both written and read - // throughout the cycle. At the end of the cycle, this is how + // heapScanWork is the total heap scan work performed this cycle. + // stackScanWork is the total stack scan work performed this cycle. + // globalsScanWork is the total globals scan work performed this cycle. + // + // These are updated atomically during the cycle. Updates occur in + // bounded batches, since they are both written and read + // throughout the cycle. At the end of the cycle, heapScanWork is how // much of the retained heap is scannable. // - // Currently this is the bytes of heap scanned. For most uses, - // this is an opaque unit of work, but for estimation the - // definition is important. - scanWork int64 + // Currently these are measured in bytes. For most uses, this is an + // opaque unit of work, but for estimation the definition is important. + // + // Note that stackScanWork includes all allocated space, not just the + // size of the stack itself, mirroring stackSize. + // + // For !goexperiment.PacerRedesign, stackScanWork and globalsScanWork + // are always zero. + heapScanWork atomic.Int64 + stackScanWork atomic.Int64 + globalsScanWork atomic.Int64 // bgScanCredit is the scan work credit accumulated by the // concurrent background scan. This credit is accumulated by @@ -278,13 +340,39 @@ type gcControllerState struct { func (c *gcControllerState) init(gcPercent int32) { c.heapMinimum = defaultHeapMinimum - // Set a reasonable initial GC trigger. - c.triggerRatio = 7 / 8.0 + if goexperiment.PacerRedesign { + c.consMarkController = piController{ + // Tuned first via the Ziegler-Nichols process in simulation, + // then the integral time was manually tuned against real-world + // applications to deal with noisiness in the measured cons/mark + // ratio. + kp: 0.9, + ti: 4.0, + + // An update is done once per GC cycle. + period: 1, + + // Set a high reset time in GC cycles. + // This is inversely proportional to the rate at which we + // accumulate error from clipping. By making this very high + // we make the accumulation slow. In general, clipping is + // OK in our situation, hence the choice. + // + // Tune this if we get unintended effects from clipping for + // a long time. + tt: 1000, + min: -1000, + max: 1000, + } + } else { + // Set a reasonable initial GC trigger. + c.triggerRatio = 7 / 8.0 - // Fake a heapMarked value so it looks like a trigger at - // heapMinimum is the appropriate growth from heapMarked. - // This will go into computing the initial GC goal. - c.heapMarked = uint64(float64(c.heapMinimum) / (1 + c.triggerRatio)) + // Fake a heapMarked value so it looks like a trigger at + // heapMinimum is the appropriate growth from heapMarked. + // This will go into computing the initial GC goal. + c.heapMarked = uint64(float64(c.heapMinimum) / (1 + c.triggerRatio)) + } // This will also compute and set the GC trigger and goal. c.setGCPercent(gcPercent) @@ -294,7 +382,9 @@ func (c *gcControllerState) init(gcPercent int32) { // for a new GC cycle. The caller must hold worldsema and the world // must be stopped. func (c *gcControllerState) startCycle(markStartTime int64, procs int) { - c.scanWork = 0 + c.heapScanWork.Store(0) + c.stackScanWork.Store(0) + c.globalsScanWork.Store(0) c.bgScanCredit = 0 c.assistTime = 0 c.dedicatedMarkTime = 0 @@ -310,8 +400,14 @@ func (c *gcControllerState) startCycle(markStartTime int64, procs int) { // GOGC. Assist is proportional to this distance, so enforce a // minimum distance, even if it means going over the GOGC goal // by a tiny bit. - if c.heapGoal < c.heapLive+1024*1024 { - c.heapGoal = c.heapLive + 1024*1024 + if goexperiment.PacerRedesign { + if c.heapGoal < c.heapLive+64<<10 { + c.heapGoal = c.heapLive + 64<<10 + } + } else { + if c.heapGoal < c.heapLive+1<<20 { + c.heapGoal = c.heapLive + 1<<20 + } } // Compute the background mark utilization goal. In general, @@ -394,32 +490,79 @@ func (c *gcControllerState) revise() { } live := atomic.Load64(&c.heapLive) scan := atomic.Load64(&c.heapScan) - work := atomic.Loadint64(&c.scanWork) + work := c.heapScanWork.Load() + c.stackScanWork.Load() + c.globalsScanWork.Load() // Assume we're under the soft goal. Pace GC to complete at // heapGoal assuming the heap is in steady-state. heapGoal := int64(atomic.Load64(&c.heapGoal)) - // Compute the expected scan work remaining. - // - // This is estimated based on the expected - // steady-state scannable heap. For example, with - // GOGC=100, only half of the scannable heap is - // expected to be live, so that's what we target. - // - // (This is a float calculation to avoid overflowing on - // 100*heapScan.) - scanWorkExpected := int64(float64(scan) * 100 / float64(100+gcPercent)) - - if int64(live) > heapGoal || work > scanWorkExpected { - // We're past the soft goal, or we've already done more scan - // work than we expected. Pace GC so that in the worst case it - // will complete by the hard goal. - const maxOvershoot = 1.1 - heapGoal = int64(float64(heapGoal) * maxOvershoot) - - // Compute the upper bound on the scan work remaining. - scanWorkExpected = int64(scan) + var scanWorkExpected int64 + if goexperiment.PacerRedesign { + // The expected scan work is computed as the amount of bytes scanned last + // GC cycle, plus our estimate of stacks and globals work for this cycle. + scanWorkExpected = int64(c.lastHeapScan + c.stackScan + c.globalsScan) + + // maxScanWork is a worst-case estimate of the amount of scan work that + // needs to be performed in this GC cycle. Specifically, it represents + // the case where *all* scannable memory turns out to be live. + maxScanWork := int64(scan + c.stackScan + c.globalsScan) + if work > scanWorkExpected { + // We've already done more scan work than expected. Because our expectation + // is based on a steady-state scannable heap size, we assume this means our + // heap is growing. Compute a new heap goal that takes our existing runway + // computed for scanWorkExpected and extrapolates it to maxScanWork, the worst-case + // scan work. This keeps our assist ratio stable if the heap continues to grow. + // + // The effect of this mechanism is that assists stay flat in the face of heap + // growths. It's OK to use more memory this cycle to scan all the live heap, + // because the next GC cycle is inevitably going to use *at least* that much + // memory anyway. + heapGoal = int64(float64(heapGoal-int64(c.trigger))/float64(scanWorkExpected)*float64(maxScanWork)) + int64(c.trigger) + scanWorkExpected = maxScanWork + + // hardGoal is a hard limit on the amount that we're willing to push back the + // heap goal, and that's twice the heap goal (i.e. if GOGC=100 and the heap and/or + // stacks and/or globals grow to twice their size, this limits the current GC cycle's + // growth to 4x the original live heap's size). + // + // This maintains the invariant that we use no more memory than the next GC cycle + // will anyway. + hardGoal := int64((1.0 + float64(gcPercent)/100.0) * float64(heapGoal)) + if heapGoal > hardGoal { + heapGoal = hardGoal + } + } + if int64(live) > heapGoal { + // We're already past our heap goal, even the extrapolated one. + // Leave ourselves some extra runway, so in the worst case we + // finish by that point. + const maxOvershoot = 1.1 + heapGoal = int64(float64(heapGoal) * maxOvershoot) + + // Compute the upper bound on the scan work remaining. + scanWorkExpected = maxScanWork + } + } else { + // Compute the expected scan work remaining. + // + // This is estimated based on the expected + // steady-state scannable heap. For example, with + // GOGC=100, only half of the scannable heap is + // expected to be live, so that's what we target. + // + // (This is a float calculation to avoid overflowing on + // 100*heapScan.) + scanWorkExpected = int64(float64(scan) * 100 / float64(100+gcPercent)) + if int64(live) > heapGoal || work > scanWorkExpected { + // We're past the soft goal, or we've already done more scan + // work than we expected. Pace GC so that in the worst case it + // will complete by the hard goal. + const maxOvershoot = 1.1 + heapGoal = int64(float64(heapGoal) * maxOvershoot) + + // Compute the upper bound on the scan work remaining. + scanWorkExpected = int64(scan) + } } // Compute the remaining scan work estimate. @@ -464,7 +607,9 @@ func (c *gcControllerState) revise() { c.assistBytesPerWork.Store(assistBytesPerWork) } -// endCycle computes the trigger ratio for the next cycle. +// endCycle computes the trigger ratio (!goexperiment.PacerRedesign) +// or the consMark estimate (goexperiment.PacerRedesign) for the next cycle. +// Returns the trigger ratio if application, or 0 (goexperiment.PacerRedesign). // userForced indicates whether the current GC cycle was forced // by the application. func (c *gcControllerState) endCycle(now int64, procs int, userForced bool) float64 { @@ -472,6 +617,81 @@ func (c *gcControllerState) endCycle(now int64, procs int, userForced bool) floa // We'll be updating the heap goal soon. gcController.lastHeapGoal = gcController.heapGoal + // Compute the duration of time for which assists were turned on. + assistDuration := now - c.markStartTime + + // Assume background mark hit its utilization goal. + utilization := gcBackgroundUtilization + // Add assist utilization; avoid divide by zero. + if assistDuration > 0 { + utilization += float64(c.assistTime) / float64(assistDuration*int64(procs)) + } + + if goexperiment.PacerRedesign { + if c.heapLive <= c.trigger { + // Shouldn't happen, but let's be very safe about this in case the + // GC is somehow extremely short. + // + // In this case though, the only reasonable value for c.heapLive-c.trigger + // would be 0, which isn't really all that useful, i.e. the GC was so short + // that it didn't matter. + // + // Ignore this case and don't update anything. + return 0 + } + idleUtilization := 0.0 + if assistDuration > 0 { + idleUtilization = float64(c.idleMarkTime) / float64(assistDuration*int64(procs)) + } + // Determine the cons/mark ratio. + // + // The units we want for the numerator and denominator are both B / cpu-ns. + // We get this by taking the bytes allocated or scanned, and divide by the amount of + // CPU time it took for those operations. For allocations, that CPU time is + // + // assistDuration * procs * (1 - utilization) + // + // Where utilization includes just background GC workers and assists. It does *not* + // include idle GC work time, because in theory the mutator is free to take that at + // any point. + // + // For scanning, that CPU time is + // + // assistDuration * procs * (utilization + idleUtilization) + // + // In this case, we *include* idle utilization, because that is additional CPU time that the + // the GC had available to it. + // + // In effect, idle GC time is sort of double-counted here, but it's very weird compared + // to other kinds of GC work, because of how fluid it is. Namely, because the mutator is + // *always* free to take it. + // + // So this calculation is really: + // (heapLive-trigger) / (assistDuration * procs * (1-utilization)) / + // (scanWork) / (assistDuration * procs * (utilization+idleUtilization) + // + // Note that because we only care about the ratio, assistDuration and procs cancel out. + scanWork := c.heapScanWork.Load() + c.stackScanWork.Load() + c.globalsScanWork.Load() + currentConsMark := (float64(c.heapLive-c.trigger) * (utilization + idleUtilization)) / + (float64(scanWork) * (1 - utilization)) + + // Update cons/mark controller. + oldConsMark := c.consMark + c.consMark = c.consMarkController.next(c.consMark, currentConsMark) + + if debug.gcpacertrace > 0 { + printlock() + print("pacer: ", int(utilization*100), "% CPU (", int(gcGoalUtilization*100), " exp.) for ") + print(c.heapScanWork.Load(), "+", c.stackScanWork.Load(), "+", c.globalsScanWork.Load(), " B work (", c.lastHeapScan+c.stackScan+c.globalsScan, " B exp.) ") + print("in ", c.trigger, " B -> ", c.heapLive, " B (∆goal ", int64(c.heapLive)-int64(c.heapGoal), ", cons/mark ", oldConsMark, ")") + println() + printunlock() + } + return 0 + } + + // !goexperiment.PacerRedesign below. + if userForced { // Forced GC means this cycle didn't start at the // trigger, so where it finished isn't good @@ -498,15 +718,6 @@ func (c *gcControllerState) endCycle(now int64, procs int, userForced bool) floa // heap growth is the error. goalGrowthRatio := c.effectiveGrowthRatio() actualGrowthRatio := float64(c.heapLive)/float64(c.heapMarked) - 1 - assistDuration := now - c.markStartTime - - // Assume background mark hit its utilization goal. - utilization := gcBackgroundUtilization - // Add assist utilization; avoid divide by zero. - if assistDuration > 0 { - utilization += float64(c.assistTime) / float64(assistDuration*int64(procs)) - } - triggerError := goalGrowthRatio - c.triggerRatio - utilization/gcGoalUtilization*(actualGrowthRatio-c.triggerRatio) // Finally, we adjust the trigger for next time by this error, @@ -525,7 +736,7 @@ func (c *gcControllerState) endCycle(now int64, procs int, userForced bool) floa H_g := int64(float64(H_m_prev) * (1 + h_g)) u_a := utilization u_g := gcGoalUtilization - W_a := c.scanWork + W_a := c.heapScanWork.Load() print("pacer: H_m_prev=", H_m_prev, " h_t=", h_t, " H_T=", H_T, " h_a=", h_a, " H_a=", H_a, @@ -669,7 +880,8 @@ func (c *gcControllerState) findRunnableGCWorker(_p_ *p) *g { func (c *gcControllerState) resetLive(bytesMarked uint64) { c.heapMarked = bytesMarked c.heapLive = bytesMarked - c.heapScan = uint64(c.scanWork) + c.heapScan = uint64(c.heapScanWork.Load()) + c.lastHeapScan = uint64(c.heapScanWork.Load()) // heapLive was updated, so emit a trace event. if trace.enabled { @@ -703,8 +915,12 @@ func (c *gcControllerState) update(dHeapLive, dHeapScan int64) { traceHeapAlloc() } } - if dHeapScan != 0 { - atomic.Xadd64(&gcController.heapScan, dHeapScan) + // Only update heapScan in the new pacer redesign if we're not + // currently in a GC. + if !goexperiment.PacerRedesign || gcBlackenEnabled == 0 { + if dHeapScan != 0 { + atomic.Xadd64(&gcController.heapScan, dHeapScan) + } } if gcBlackenEnabled != 0 { // gcController.heapLive and heapScan changed. @@ -728,9 +944,10 @@ func (c *gcControllerState) addGlobals(amount int64) { atomic.Xadd64(&c.globalsScan, amount) } -// commit sets the trigger ratio and updates everything -// derived from it: the absolute trigger, the heap goal, mark pacing, -// and sweep pacing. +// commit recomputes all pacing parameters from scratch, namely +// absolute trigger, the heap goal, mark pacing, and sweep pacing. +// +// If goexperiment.PacerRedesign is true, triggerRatio is ignored. // // This can be called any time. If GC is the in the middle of a // concurrent phase, it will adjust the pacing of that phase. @@ -744,6 +961,130 @@ func (c *gcControllerState) commit(triggerRatio float64) { assertWorldStoppedOrLockHeld(&mheap_.lock) } + if !goexperiment.PacerRedesign { + c.oldCommit(triggerRatio) + return + } + + // Compute the next GC goal, which is when the allocated heap + // has grown by GOGC/100 over where it started the last cycle, + // plus additional runway for non-heap sources of GC work. + goal := ^uint64(0) + if c.gcPercent >= 0 { + goal = c.heapMarked + (c.heapMarked+atomic.Load64(&c.stackScan)+atomic.Load64(&c.globalsScan))*uint64(c.gcPercent)/100 + } + + // Don't trigger below the minimum heap size. + minTrigger := c.heapMinimum + if !isSweepDone() { + // Concurrent sweep happens in the heap growth + // from gcController.heapLive to trigger, so ensure + // that concurrent sweep has some heap growth + // in which to perform sweeping before we + // start the next GC cycle. + sweepMin := atomic.Load64(&c.heapLive) + sweepMinHeapDistance + if sweepMin > minTrigger { + minTrigger = sweepMin + } + } + + // If we let the trigger go too low, then if the application + // is allocating very rapidly we might end up in a situation + // where we're allocating black during a nearly always-on GC. + // The result of this is a growing heap and ultimately an + // increase in RSS. By capping us at a point >0, we're essentially + // saying that we're OK using more CPU during the GC to prevent + // this growth in RSS. + // + // The current constant was chosen empirically: given a sufficiently + // fast/scalable allocator with 48 Ps that could drive the trigger ratio + // to <0.05, this constant causes applications to retain the same peak + // RSS compared to not having this allocator. + if triggerBound := uint64(0.7*float64(goal-c.heapMarked)) + c.heapMarked; minTrigger < triggerBound { + minTrigger = triggerBound + } + + // For small heaps, set the max trigger point at 95% of the heap goal. + // This ensures we always have *some* headroom when the GC actually starts. + // For larger heaps, set the max trigger point at the goal, minus the + // minimum heap size. + // This choice follows from the fact that the minimum heap size is chosen + // to reflect the costs of a GC with no work to do. With a large heap but + // very little scan work to perform, this gives us exactly as much runway + // as we would need, in the worst case. + maxRunway := uint64(0.95 * float64(goal-c.heapMarked)) + if largeHeapMaxRunway := goal - c.heapMinimum; goal > c.heapMinimum && maxRunway < largeHeapMaxRunway { + maxRunway = largeHeapMaxRunway + } + maxTrigger := maxRunway + c.heapMarked + if maxTrigger < minTrigger { + maxTrigger = minTrigger + } + + // Compute the trigger by using our estimate of the cons/mark ratio. + // + // The idea is to take our expected scan work, and multiply it by + // the cons/mark ratio to determine how long it'll take to complete + // that scan work in terms of bytes allocated. This gives us our GC's + // runway. + // + // However, the cons/mark ratio is a ratio of rates per CPU-second, but + // here we care about the relative rates for some division of CPU + // resources among the mutator and the GC. + // + // To summarize, we have B / cpu-ns, and we want B / ns. We get that + // by multiplying by our desired division of CPU resources. We choose + // to express CPU resources as GOMAPROCS*fraction. Note that because + // we're working with a ratio here, we can omit the number of CPU cores, + // because they'll appear in the numerator and denominator and cancel out. + // As a result, this is basically just "weighing" the cons/mark ratio by + // our desired division of resources. + // + // Furthermore, by setting the trigger so that CPU resources are divided + // this way, assuming that the cons/mark ratio is correct, we make that + // division a reality. + var trigger uint64 + runway := uint64((c.consMark * (1 - gcGoalUtilization) / (gcGoalUtilization)) * float64(c.lastHeapScan+c.stackScan+c.globalsScan)) + if runway > goal { + trigger = minTrigger + } else { + trigger = goal - runway + } + if trigger < minTrigger { + trigger = minTrigger + } + if trigger > maxTrigger { + trigger = maxTrigger + } + if trigger > goal { + goal = trigger + } + + // Commit to the trigger and goal. + c.trigger = trigger + atomic.Store64(&c.heapGoal, goal) + if trace.enabled { + traceHeapGoal() + } + + // Update mark pacing. + if gcphase != _GCoff { + c.revise() + } +} + +// oldCommit sets the trigger ratio and updates everything +// derived from it: the absolute trigger, the heap goal, mark pacing, +// and sweep pacing. +// +// This can be called any time. If GC is the in the middle of a +// concurrent phase, it will adjust the pacing of that phase. +// +// This depends on gcPercent, gcController.heapMarked, and +// gcController.heapLive. These must be up to date. +// +// For !goexperiment.PacerRedesign. +func (c *gcControllerState) oldCommit(triggerRatio float64) { // Compute the next GC goal, which is when the allocated heap // has grown by GOGC/100 over the heap marked by the last // cycle. @@ -913,3 +1254,38 @@ func readGOGC() int32 { } return 100 } + +type piController struct { + kp float64 // Proportional constant. + ti float64 // Integral time constant. + tt float64 // Reset time in GC cyles. + + // Period in GC cycles between updates. + period float64 + + min, max float64 // Output boundaries. + + // PI controller state. + + errIntegral float64 // Integral of the error from t=0 to now. +} + +func (c *piController) next(input, setpoint float64) float64 { + // Compute the raw output value. + prop := c.kp * (setpoint - input) + rawOutput := prop + c.errIntegral + + // Clamp rawOutput into output. + output := rawOutput + if output < c.min { + output = c.min + } else if output > c.max { + output = c.max + } + + // Update the controller's state. + if c.ti != 0 && c.tt != 0 { + c.errIntegral += (c.kp*c.period/c.ti)*(setpoint-input) + (c.period/c.tt)*(output-rawOutput) + } + return output +} diff --git a/src/runtime/mgcpacer_test.go b/src/runtime/mgcpacer_test.go index 5a9f46c6d1..d2707ca5a1 100644 --- a/src/runtime/mgcpacer_test.go +++ b/src/runtime/mgcpacer_test.go @@ -6,6 +6,7 @@ package runtime_test import ( "fmt" + "internal/goexperiment" "math" "math/rand" . "runtime" @@ -34,12 +35,76 @@ func TestGcPacer(t *testing.T) { checker: func(t *testing.T, c []gcCycleResult) { n := len(c) if n >= 25 { + if goexperiment.PacerRedesign { + // For the pacer redesign, assert something even stronger: at this alloc/scan rate, + // it should be extremely close to the goal utilization. + assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, GCGoalUtilization, 0.005) + } + // Make sure the pacer settles into a non-degenerate state in at least 25 GC cycles. assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, c[n-2].gcUtilization, 0.005) assertInRange(t, "goal ratio", c[n-1].goalRatio(), 0.95, 1.05) } }, }, + { + // Same as the steady-state case, but lots of stacks to scan relative to the heap size. + name: "SteadyBigStacks", + gcPercent: 100, + globalsBytes: 32 << 10, + nCores: 8, + allocRate: constant(132.0), + scanRate: constant(1024.0), + growthRate: constant(2.0).sum(ramp(-1.0, 12)), + scannableFrac: constant(1.0), + stackBytes: constant(2048).sum(ramp(128<<20, 8)), + length: 50, + checker: func(t *testing.T, c []gcCycleResult) { + // Check the same conditions as the steady-state case, except the old pacer can't + // really handle this well, so don't check the goal ratio for it. + n := len(c) + if n >= 25 { + if goexperiment.PacerRedesign { + // For the pacer redesign, assert something even stronger: at this alloc/scan rate, + // it should be extremely close to the goal utilization. + assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, GCGoalUtilization, 0.005) + assertInRange(t, "goal ratio", c[n-1].goalRatio(), 0.95, 1.05) + } + + // Make sure the pacer settles into a non-degenerate state in at least 25 GC cycles. + assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, c[n-2].gcUtilization, 0.005) + } + }, + }, + { + // Same as the steady-state case, but lots of globals to scan relative to the heap size. + name: "SteadyBigGlobals", + gcPercent: 100, + globalsBytes: 128 << 20, + nCores: 8, + allocRate: constant(132.0), + scanRate: constant(1024.0), + growthRate: constant(2.0).sum(ramp(-1.0, 12)), + scannableFrac: constant(1.0), + stackBytes: constant(8192), + length: 50, + checker: func(t *testing.T, c []gcCycleResult) { + // Check the same conditions as the steady-state case, except the old pacer can't + // really handle this well, so don't check the goal ratio for it. + n := len(c) + if n >= 25 { + if goexperiment.PacerRedesign { + // For the pacer redesign, assert something even stronger: at this alloc/scan rate, + // it should be extremely close to the goal utilization. + assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, GCGoalUtilization, 0.005) + assertInRange(t, "goal ratio", c[n-1].goalRatio(), 0.95, 1.05) + } + + // Make sure the pacer settles into a non-degenerate state in at least 25 GC cycles. + assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, c[n-2].gcUtilization, 0.005) + } + }, + }, { // This tests the GC pacer's response to a small change in allocation rate. name: "StepAlloc", @@ -106,6 +171,47 @@ func TestGcPacer(t *testing.T) { } }, }, + { + // Tests the pacer for a high GOGC value with a large heap growth happening + // in the middle. The purpose of the large heap growth is to check if GC + // utilization ends up sensitive + name: "HighGOGC", + gcPercent: 1500, + globalsBytes: 32 << 10, + nCores: 8, + allocRate: random(7, 0x53).offset(165), + scanRate: constant(1024.0), + growthRate: constant(2.0).sum(ramp(-1.0, 12), random(0.01, 0x1), unit(14).delay(25)), + scannableFrac: constant(1.0), + stackBytes: constant(8192), + length: 50, + checker: func(t *testing.T, c []gcCycleResult) { + n := len(c) + if goexperiment.PacerRedesign && n > 12 { + if n == 26 { + // In the 26th cycle there's a heap growth. Overshoot is expected to maintain + // a stable utilization, but we should *never* overshoot more than GOGC of + // the next cycle. + assertInRange(t, "goal ratio", c[n-1].goalRatio(), 0.90, 15) + } else { + // Give a wider goal range here. With such a high GOGC value we're going to be + // forced to undershoot. + // + // TODO(mknyszek): Instead of placing a 0.95 limit on the trigger, make the limit + // based on absolute bytes, that's based somewhat in how the minimum heap size + // is determined. + assertInRange(t, "goal ratio", c[n-1].goalRatio(), 0.90, 1.05) + } + + // Ensure utilization remains stable despite a growth in live heap size + // at GC #25. This test fails prior to the GC pacer redesign. + // + // Because GOGC is so large, we should also be really close to the goal utilization. + assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, GCGoalUtilization, GCGoalUtilization+0.03) + assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, c[n-2].gcUtilization, 0.03) + } + }, + }, { // This test makes sure that in the face of a varying (in this case, oscillating) allocation // rate, the pacer does a reasonably good job of staying abreast of the changes. @@ -126,7 +232,12 @@ func TestGcPacer(t *testing.T) { // 1. Utilization isn't varying _too_ much, and // 2. The pacer is mostly keeping up with the goal. assertInRange(t, "goal ratio", c[n-1].goalRatio(), 0.95, 1.05) - assertInRange(t, "GC utilization", c[n-1].gcUtilization, 0.25, 0.4) + if goexperiment.PacerRedesign { + assertInRange(t, "GC utilization", c[n-1].gcUtilization, 0.25, 0.3) + } else { + // The old pacer is messier here, and needs a lot more tolerance. + assertInRange(t, "GC utilization", c[n-1].gcUtilization, 0.25, 0.4) + } } }, }, @@ -149,7 +260,12 @@ func TestGcPacer(t *testing.T) { // 1. Utilization isn't varying _too_ much, and // 2. The pacer is mostly keeping up with the goal. assertInRange(t, "goal ratio", c[n-1].goalRatio(), 0.95, 1.05) - assertInRange(t, "GC utilization", c[n-1].gcUtilization, 0.25, 0.4) + if goexperiment.PacerRedesign { + assertInRange(t, "GC utilization", c[n-1].gcUtilization, 0.25, 0.3) + } else { + // The old pacer is messier here, and needs a lot more tolerance. + assertInRange(t, "GC utilization", c[n-1].gcUtilization, 0.25, 0.4) + } } }, }, @@ -177,7 +293,12 @@ func TestGcPacer(t *testing.T) { // Unlike the other tests, GC utilization here will vary more and tend higher. // Just make sure it's not going too crazy. assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, c[n-2].gcUtilization, 0.05) - assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, c[11].gcUtilization, 0.07) + if goexperiment.PacerRedesign { + assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, c[11].gcUtilization, 0.05) + } else { + // The old pacer is messier here, and needs a little more tolerance. + assertInEpsilon(t, "GC utilization", c[n-1].gcUtilization, c[11].gcUtilization, 0.07) + } } }, }, diff --git a/src/runtime/mgcwork.go b/src/runtime/mgcwork.go index 8787d93d87..9c3f7fd223 100644 --- a/src/runtime/mgcwork.go +++ b/src/runtime/mgcwork.go @@ -77,9 +77,10 @@ type gcWork struct { // into work.bytesMarked by dispose. bytesMarked uint64 - // Scan work performed on this gcWork. This is aggregated into + // Heap scan work performed on this gcWork. This is aggregated into // gcController by dispose and may also be flushed by callers. - scanWork int64 + // Other types of scan work are flushed immediately. + heapScanWork int64 // flushedWork indicates that a non-empty work buffer was // flushed to the global work list since the last gcMarkDone @@ -274,9 +275,9 @@ func (w *gcWork) dispose() { atomic.Xadd64(&work.bytesMarked, int64(w.bytesMarked)) w.bytesMarked = 0 } - if w.scanWork != 0 { - atomic.Xaddint64(&gcController.scanWork, w.scanWork) - w.scanWork = 0 + if w.heapScanWork != 0 { + gcController.heapScanWork.Add(w.heapScanWork) + w.heapScanWork = 0 } } -- GitLab From 961aab26bffece299f1528b44d260ea0a921ac56 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 25 Oct 2021 21:43:27 +0000 Subject: [PATCH 1960/2500] internal/buildcfg: enable the pacer redesign by default Change-Id: Ifb90d5482cb0cedee6cb4d6297853ac7913d14ee Reviewed-on: https://go-review.googlesource.com/c/go/+/358674 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Michael Pratt --- src/internal/buildcfg/exp.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go index 043d079cf6..a9b29d6718 100644 --- a/src/internal/buildcfg/exp.go +++ b/src/internal/buildcfg/exp.go @@ -56,6 +56,7 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (flags, baseline goexperiment RegabiWrappers: regabiSupported, RegabiReflect: regabiSupported, RegabiArgs: regabiSupported, + PacerRedesign: true, } // Start with the statically enabled set of experiments. -- GitLab From 9b2dd1f7714b38f1bfe25676357b62c1bb4cad64 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Wed, 3 Nov 2021 14:44:16 -0400 Subject: [PATCH 1961/2500] internal/fuzz: fix internal error handling This doesn't handle every possible scenario, but improves the one we can control. For example, if the worker panics for some reason, we have no way of knowing whether the panic occurred in an expected way (while executing the fuzz target) or due to an internal error in the worker. So any panic will still be treated as a crash. However, if it fails due to some internal bug that we know how to catch, then the error should be reported to the user without a new crasher being written to testdata. This is very difficult to test. The reasons an internal error would occur is because something went very wrong, and we have a bug in our code (which is why they were previously panics). So simulating a problem like this in a test is not really feasible. Fixes #48804 Change-Id: I334618f84eb4a994a8d17419551a510b1fdef071 Reviewed-on: https://go-review.googlesource.com/c/go/+/361115 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills Reviewed-by: Roland Shoemaker --- src/internal/fuzz/worker.go | 47 ++++++++++++++++++-------------- src/internal/fuzz/worker_test.go | 2 +- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 388675f713..02efa7f84a 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -153,7 +153,7 @@ func (w *worker) coordinate(ctx context.Context) error { Warmup: input.warmup, CoverageData: input.coverageData, } - entry, resp, err := w.client.fuzz(ctx, input.entry, args) + entry, resp, isInternalError, err := w.client.fuzz(ctx, input.entry, args) canMinimize := true if err != nil { // Error communicating with worker. @@ -167,14 +167,6 @@ func (w *worker) coordinate(ctx context.Context) error { // Report an error, but don't record a crasher. return fmt.Errorf("communicating with fuzzing process: %v", err) } - if w.waitErr == nil || isInterruptError(w.waitErr) { - // Worker stopped, either by exiting with status 0 or after being - // interrupted with a signal (not sent by coordinator). See comment in - // termC case above. - // - // Since we expect I/O errors around interrupts, ignore this error. - return nil - } if sig, ok := terminationSignal(w.waitErr); ok && !isCrashSignal(sig) { // Worker terminated by a signal that probably wasn't caused by a // specific input to the fuzz function. For example, on Linux, @@ -183,6 +175,11 @@ func (w *worker) coordinate(ctx context.Context) error { // is closed. Don't record a crasher. return fmt.Errorf("fuzzing process terminated by unexpected signal; no crash will be recorded: %v", w.waitErr) } + if isInternalError { + // An internal error occurred which shouldn't be considered + // a crash. + return err + } // Unexpected termination. Set error message and fall through. // We'll restart the worker on the next iteration. // Don't attempt to minimize this since it crashed the worker. @@ -567,6 +564,10 @@ type fuzzResponse struct { // Err is the error string caused by the value in shared memory, which is // non-empty if the value in shared memory caused a crash. Err string + + // InternalErr is the error string caused by an internal error in the + // worker. This shouldn't be considered a crasher. + InternalErr string } // pingArgs contains arguments to workerServer.ping. @@ -663,7 +664,8 @@ func (ws *workerServer) serve(ctx context.Context) error { func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzResponse) { if args.CoverageData != nil { if ws.coverageMask != nil && len(args.CoverageData) != len(ws.coverageMask) { - panic(fmt.Sprintf("unexpected size for CoverageData: got %d, expected %d", len(args.CoverageData), len(ws.coverageMask))) + resp.InternalErr = fmt.Sprintf("unexpected size for CoverageData: got %d, expected %d", len(args.CoverageData), len(ws.coverageMask)) + return resp } ws.coverageMask = args.CoverageData } @@ -682,12 +684,14 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo ws.memMu <- mem }() if args.Limit > 0 && mem.header().count >= args.Limit { - panic(fmt.Sprintf("mem.header().count %d already exceeds args.Limit %d", mem.header().count, args.Limit)) + resp.InternalErr = fmt.Sprintf("mem.header().count %d already exceeds args.Limit %d", mem.header().count, args.Limit) + return resp } vals, err := unmarshalCorpusFile(mem.valueCopy()) if err != nil { - panic(err) + resp.InternalErr = err.Error() + return resp } shouldStop := func() bool { @@ -1027,7 +1031,7 @@ func (wc *workerClient) minimize(ctx context.Context, entryIn CorpusEntry, args entryOut.Parent = entryIn.Parent entryOut.Generation = entryIn.Generation if err != nil { - panic(fmt.Sprintf("workerClient.minimize unmarshaling minimized value: %v", err)) + return CorpusEntry{}, minimizeResponse{}, fmt.Errorf("workerClient.minimize unmarshaling minimized value: %v", err) } } else { // Did not minimize, but the original input may still be interesting, @@ -1039,40 +1043,43 @@ func (wc *workerClient) minimize(ctx context.Context, entryIn CorpusEntry, args } // fuzz tells the worker to call the fuzz method. See workerServer.fuzz. -func (wc *workerClient) fuzz(ctx context.Context, entryIn CorpusEntry, args fuzzArgs) (entryOut CorpusEntry, resp fuzzResponse, err error) { +func (wc *workerClient) fuzz(ctx context.Context, entryIn CorpusEntry, args fuzzArgs) (entryOut CorpusEntry, resp fuzzResponse, isInternalError bool, err error) { wc.mu.Lock() defer wc.mu.Unlock() mem, ok := <-wc.memMu if !ok { - return CorpusEntry{}, fuzzResponse{}, errSharedMemClosed + return CorpusEntry{}, fuzzResponse{}, true, errSharedMemClosed } mem.header().count = 0 inp, err := CorpusEntryData(entryIn) if err != nil { - return CorpusEntry{}, fuzzResponse{}, err + return CorpusEntry{}, fuzzResponse{}, true, err } mem.setValue(inp) wc.memMu <- mem c := call{Fuzz: &args} callErr := wc.callLocked(ctx, c, &resp) + if resp.InternalErr != "" { + return CorpusEntry{}, fuzzResponse{}, true, errors.New(resp.InternalErr) + } mem, ok = <-wc.memMu if !ok { - return CorpusEntry{}, fuzzResponse{}, errSharedMemClosed + return CorpusEntry{}, fuzzResponse{}, true, errSharedMemClosed } defer func() { wc.memMu <- mem }() resp.Count = mem.header().count if !bytes.Equal(inp, mem.valueRef()) { - panic("workerServer.fuzz modified input") + return CorpusEntry{}, fuzzResponse{}, true, errors.New("workerServer.fuzz modified input") } needEntryOut := callErr != nil || resp.Err != "" || (!args.Warmup && resp.CoverageData != nil) if needEntryOut { valuesOut, err := unmarshalCorpusFile(inp) if err != nil { - panic(fmt.Sprintf("unmarshaling fuzz input value after call: %v", err)) + return CorpusEntry{}, fuzzResponse{}, true, fmt.Errorf("unmarshaling fuzz input value after call: %v", err) } wc.m.r.restore(mem.header().randState, mem.header().randInc) if !args.Warmup { @@ -1098,7 +1105,7 @@ func (wc *workerClient) fuzz(ctx context.Context, entryIn CorpusEntry, args fuzz } } - return entryOut, resp, callErr + return entryOut, resp, false, callErr } // ping tells the worker to call the ping method. See workerServer.ping. diff --git a/src/internal/fuzz/worker_test.go b/src/internal/fuzz/worker_test.go index e32770b02b..c6f83fd08d 100644 --- a/src/internal/fuzz/worker_test.go +++ b/src/internal/fuzz/worker_test.go @@ -96,7 +96,7 @@ func BenchmarkWorkerFuzz(b *testing.B) { Limit: int64(b.N) - i, Timeout: workerFuzzDuration, } - _, resp, err := w.client.fuzz(context.Background(), entry, args) + _, resp, _, err := w.client.fuzz(context.Background(), entry, args) if err != nil { b.Fatal(err) } -- GitLab From fc5e8cd6c9de00f8d7da645343934c548e62223e Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 4 Oct 2021 19:52:48 +0000 Subject: [PATCH 1962/2500] runtime: update and access scavengeGoal atomically The first step toward acquiring the heap lock less frequently in the scavenger. Change-Id: Idc69fd8602be2c83268c155951230d60e20b42fe Reviewed-on: https://go-review.googlesource.com/c/go/+/353973 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Michael Pratt --- src/runtime/mgcscavenge.go | 8 ++++---- src/runtime/mheap.go | 7 +++++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/runtime/mgcscavenge.go b/src/runtime/mgcscavenge.go index fb9b5c8694..4edeb8739e 100644 --- a/src/runtime/mgcscavenge.go +++ b/src/runtime/mgcscavenge.go @@ -125,7 +125,7 @@ func gcPaceScavenger(heapGoal, lastHeapGoal uint64) { // information about the heap yet) so this is fine, and avoids a fault // or garbage data later. if lastHeapGoal == 0 { - mheap_.scavengeGoal = ^uint64(0) + atomic.Store64(&mheap_.scavengeGoal, ^uint64(0)) return } // Compute our scavenging goal. @@ -157,10 +157,10 @@ func gcPaceScavenger(heapGoal, lastHeapGoal uint64) { // the background scavenger. We disable the background scavenger if there's // less than one physical page of work to do because it's not worth it. if retainedNow <= retainedGoal || retainedNow-retainedGoal < uint64(physPageSize) { - mheap_.scavengeGoal = ^uint64(0) + atomic.Store64(&mheap_.scavengeGoal, ^uint64(0)) return } - mheap_.scavengeGoal = retainedGoal + atomic.Store64(&mheap_.scavengeGoal, retainedGoal) } // Sleep/wait state of the background scavenger. @@ -299,7 +299,7 @@ func bgscavenge(c chan int) { lock(&mheap_.lock) // If background scavenging is disabled or if there's no work to do just park. - retained, goal := heapRetained(), mheap_.scavengeGoal + retained, goal := heapRetained(), atomic.Load64(&mheap_.scavengeGoal) if retained <= goal { unlock(&mheap_.lock) return diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go index 057ab06b1d..f2f6e7f4cf 100644 --- a/src/runtime/mheap.go +++ b/src/runtime/mheap.go @@ -111,6 +111,8 @@ type mheap struct { // scavengeGoal is the amount of total retained heap memory (measured by // heapRetained) that the runtime will try to maintain by returning memory // to the OS. + // + // Accessed atomically. scavengeGoal uint64 // Page reclaimer state @@ -1399,9 +1401,10 @@ func (h *mheap) grow(npage uintptr) bool { // By scavenging inline we deal with the failure to allocate out of // memory fragments by scavenging the memory fragments that are least // likely to be re-used. - if retained := heapRetained(); retained+uint64(totalGrowth) > h.scavengeGoal { + scavengeGoal := atomic.Load64(&h.scavengeGoal) + if retained := heapRetained(); retained+uint64(totalGrowth) > scavengeGoal { todo := totalGrowth - if overage := uintptr(retained + uint64(totalGrowth) - h.scavengeGoal); todo > overage { + if overage := uintptr(retained + uint64(totalGrowth) - scavengeGoal); todo > overage { todo = overage } h.pages.scavenge(todo, false) -- GitLab From 6d1fffac6388d965616520eb23f36885760d5b66 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 18 Oct 2021 18:22:02 +0000 Subject: [PATCH 1963/2500] runtime: set and clear only the relevant bits in allocToCache Currently allocToCache ham-handedly calls pageAlloc.allocRange on the full size of the cache. This is fine as long as scavenged bits are never set when alloc bits are set. This is true right now, but won't be true as of the next CL. This change makes allocToCache more carefully set the bits. Note that in the allocToCache path, we were also calling update *twice*, erroneously. The first time, with contig=true! Luckily today there's no correctness error there because the page cache is small enough that the contig=true logic doesn't matter, but this should at least improve allocation performance a little bit. Change-Id: I3ff9590ac86d251e4c5063cfd633570238b0cdbf Reviewed-on: https://go-review.googlesource.com/c/go/+/356609 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Michael Pratt --- src/runtime/mpagecache.go | 12 ++++-- src/runtime/mpagecache_test.go | 68 ++++++++++++++++++++++------------ src/runtime/mpallocbits.go | 18 +++++++++ 3 files changed, 71 insertions(+), 27 deletions(-) diff --git a/src/runtime/mpagecache.go b/src/runtime/mpagecache.go index 4b5c66d8d6..7206e2dbdb 100644 --- a/src/runtime/mpagecache.go +++ b/src/runtime/mpagecache.go @@ -123,9 +123,10 @@ func (p *pageAlloc) allocToCache() pageCache { } c := pageCache{} ci := chunkIndex(p.searchAddr.addr()) // chunk index + var chunk *pallocData if p.summary[len(p.summary)-1][ci] != 0 { // Fast path: there's free pages at or near the searchAddr address. - chunk := p.chunkOf(ci) + chunk = p.chunkOf(ci) j, _ := chunk.find(1, chunkPageIndex(p.searchAddr.addr())) if j == ^uint(0) { throw("bad summary data") @@ -146,7 +147,7 @@ func (p *pageAlloc) allocToCache() pageCache { return pageCache{} } ci := chunkIndex(addr) - chunk := p.chunkOf(ci) + chunk = p.chunkOf(ci) c = pageCache{ base: alignDown(addr, 64*pageSize), cache: ^chunk.pages64(chunkPageIndex(addr)), @@ -154,8 +155,11 @@ func (p *pageAlloc) allocToCache() pageCache { } } - // Set the bits as allocated and clear the scavenged bits. - p.allocRange(c.base, pageCachePages) + // Set the page bits as allocated and clear the scavenged bits, but + // be careful to only set and clear the relevant bits. + cpi := chunkPageIndex(c.base) + chunk.allocPages64(cpi, c.cache) + chunk.scavenged.clearBlock64(cpi, c.cache&c.scav /* free and scavenged */) // Update as an allocation, but note that it's not contiguous. p.update(c.base, pageCachePages, false, true) diff --git a/src/runtime/mpagecache_test.go b/src/runtime/mpagecache_test.go index 2ed0c0aa6a..69084f9a84 100644 --- a/src/runtime/mpagecache_test.go +++ b/src/runtime/mpagecache_test.go @@ -261,17 +261,18 @@ func TestPageAllocAllocToCache(t *testing.T) { t.Skip("skipping because virtual memory is limited; see #36210") } type test struct { - before map[ChunkIdx][]BitRange - scav map[ChunkIdx][]BitRange - hits []PageCache // expected base addresses and patterns - after map[ChunkIdx][]BitRange + beforeAlloc map[ChunkIdx][]BitRange + beforeScav map[ChunkIdx][]BitRange + hits []PageCache // expected base addresses and patterns + afterAlloc map[ChunkIdx][]BitRange + afterScav map[ChunkIdx][]BitRange } tests := map[string]test{ "AllFree": { - before: map[ChunkIdx][]BitRange{ + beforeAlloc: map[ChunkIdx][]BitRange{ BaseChunkIdx: {}, }, - scav: map[ChunkIdx][]BitRange{ + beforeScav: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{1, 1}, {64, 64}}, }, hits: []PageCache{ @@ -280,17 +281,17 @@ func TestPageAllocAllocToCache(t *testing.T) { NewPageCache(PageBase(BaseChunkIdx, 128), ^uint64(0), 0), NewPageCache(PageBase(BaseChunkIdx, 192), ^uint64(0), 0), }, - after: map[ChunkIdx][]BitRange{ + afterAlloc: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{0, 256}}, }, }, "ManyArena": { - before: map[ChunkIdx][]BitRange{ + beforeAlloc: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{0, PallocChunkPages}}, BaseChunkIdx + 1: {{0, PallocChunkPages}}, BaseChunkIdx + 2: {{0, PallocChunkPages - 64}}, }, - scav: map[ChunkIdx][]BitRange{ + beforeScav: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{0, PallocChunkPages}}, BaseChunkIdx + 1: {{0, PallocChunkPages}}, BaseChunkIdx + 2: {}, @@ -298,46 +299,50 @@ func TestPageAllocAllocToCache(t *testing.T) { hits: []PageCache{ NewPageCache(PageBase(BaseChunkIdx+2, PallocChunkPages-64), ^uint64(0), 0), }, - after: map[ChunkIdx][]BitRange{ + afterAlloc: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{0, PallocChunkPages}}, BaseChunkIdx + 1: {{0, PallocChunkPages}}, BaseChunkIdx + 2: {{0, PallocChunkPages}}, }, }, "NotContiguous": { - before: map[ChunkIdx][]BitRange{ + beforeAlloc: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{0, PallocChunkPages}}, BaseChunkIdx + 0xff: {{0, 0}}, }, - scav: map[ChunkIdx][]BitRange{ + beforeScav: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{0, PallocChunkPages}}, BaseChunkIdx + 0xff: {{31, 67}}, }, hits: []PageCache{ NewPageCache(PageBase(BaseChunkIdx+0xff, 0), ^uint64(0), ((uint64(1)<<33)-1)<<31), }, - after: map[ChunkIdx][]BitRange{ + afterAlloc: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{0, PallocChunkPages}}, BaseChunkIdx + 0xff: {{0, 64}}, }, + afterScav: map[ChunkIdx][]BitRange{ + BaseChunkIdx: {{0, PallocChunkPages}}, + BaseChunkIdx + 0xff: {{64, 34}}, + }, }, "First": { - before: map[ChunkIdx][]BitRange{ + beforeAlloc: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{0, 32}, {33, 31}, {96, 32}}, }, - scav: map[ChunkIdx][]BitRange{ + beforeScav: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{1, 4}, {31, 5}, {66, 2}}, }, hits: []PageCache{ NewPageCache(PageBase(BaseChunkIdx, 0), 1<<32, 1<<32), NewPageCache(PageBase(BaseChunkIdx, 64), (uint64(1)<<32)-1, 0x3<<2), }, - after: map[ChunkIdx][]BitRange{ + afterAlloc: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{0, 128}}, }, }, "Fail": { - before: map[ChunkIdx][]BitRange{ + beforeAlloc: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{0, PallocChunkPages}}, }, hits: []PageCache{ @@ -345,10 +350,27 @@ func TestPageAllocAllocToCache(t *testing.T) { NewPageCache(0, 0, 0), NewPageCache(0, 0, 0), }, - after: map[ChunkIdx][]BitRange{ + afterAlloc: map[ChunkIdx][]BitRange{ BaseChunkIdx: {{0, PallocChunkPages}}, }, }, + "RetainScavBits": { + beforeAlloc: map[ChunkIdx][]BitRange{ + BaseChunkIdx: {{0, 1}, {10, 2}}, + }, + beforeScav: map[ChunkIdx][]BitRange{ + BaseChunkIdx: {{0, 4}, {11, 1}}, + }, + hits: []PageCache{ + NewPageCache(PageBase(BaseChunkIdx, 0), ^uint64(0x1|(0x3<<10)), 0x7<<1), + }, + afterAlloc: map[ChunkIdx][]BitRange{ + BaseChunkIdx: {{0, 64}}, + }, + afterScav: map[ChunkIdx][]BitRange{ + BaseChunkIdx: {{0, 1}, {11, 1}}, + }, + }, } if PageAlloc64Bit != 0 { const chunkIdxBigJump = 0x100000 // chunk index offset which translates to O(TiB) @@ -359,11 +381,11 @@ func TestPageAllocAllocToCache(t *testing.T) { sumsPerPhysPage := ChunkIdx(PhysPageSize / PallocSumBytes) baseChunkIdx := BaseChunkIdx &^ (sumsPerPhysPage - 1) tests["DiscontiguousMappedSumBoundary"] = test{ - before: map[ChunkIdx][]BitRange{ + beforeAlloc: map[ChunkIdx][]BitRange{ baseChunkIdx + sumsPerPhysPage - 1: {{0, PallocChunkPages - 1}}, baseChunkIdx + chunkIdxBigJump: {{1, PallocChunkPages - 1}}, }, - scav: map[ChunkIdx][]BitRange{ + beforeScav: map[ChunkIdx][]BitRange{ baseChunkIdx + sumsPerPhysPage - 1: {}, baseChunkIdx + chunkIdxBigJump: {}, }, @@ -372,7 +394,7 @@ func TestPageAllocAllocToCache(t *testing.T) { NewPageCache(PageBase(baseChunkIdx+chunkIdxBigJump, 0), 1, 0), NewPageCache(0, 0, 0), }, - after: map[ChunkIdx][]BitRange{ + afterAlloc: map[ChunkIdx][]BitRange{ baseChunkIdx + sumsPerPhysPage - 1: {{0, PallocChunkPages}}, baseChunkIdx + chunkIdxBigJump: {{0, PallocChunkPages}}, }, @@ -381,7 +403,7 @@ func TestPageAllocAllocToCache(t *testing.T) { for name, v := range tests { v := v t.Run(name, func(t *testing.T) { - b := NewPageAlloc(v.before, v.scav) + b := NewPageAlloc(v.beforeAlloc, v.beforeScav) defer FreePageAlloc(b) for _, expect := range v.hits { @@ -390,7 +412,7 @@ func TestPageAllocAllocToCache(t *testing.T) { return } } - want := NewPageAlloc(v.after, v.scav) + want := NewPageAlloc(v.afterAlloc, v.afterScav) defer FreePageAlloc(want) checkPageAlloc(t, want, b) diff --git a/src/runtime/mpallocbits.go b/src/runtime/mpallocbits.go index ff112300c3..f63164becd 100644 --- a/src/runtime/mpallocbits.go +++ b/src/runtime/mpallocbits.go @@ -57,6 +57,12 @@ func (b *pageBits) setAll() { } } +// setBlock64 sets the 64-bit aligned block of bits containing the i'th bit that +// are set in v. +func (b *pageBits) setBlock64(i uint, v uint64) { + b[i/64] |= v +} + // clear clears bit i of pageBits. func (b *pageBits) clear(i uint) { b[i/64] &^= 1 << (i % 64) @@ -93,6 +99,12 @@ func (b *pageBits) clearAll() { } } +// clearBlock64 clears the 64-bit aligned block of bits containing the i'th bit that +// are set in v. +func (b *pageBits) clearBlock64(i uint, v uint64) { + b[i/64] &^= v +} + // popcntRange counts the number of set bits in the // range [i, i+n). func (b *pageBits) popcntRange(i, n uint) (s uint) { @@ -367,6 +379,12 @@ func (b *pallocBits) pages64(i uint) uint64 { return (*pageBits)(b).block64(i) } +// allocPages64 allocates a 64-bit block of 64 pages aligned to 64 pages according +// to the bits set in alloc. The block set is the one containing the i'th page. +func (b *pallocBits) allocPages64(i uint, alloc uint64) { + (*pageBits)(b).setBlock64(i, alloc) +} + // findBitRange64 returns the bit index of the first set of // n consecutive 1 bits. If no consecutive set of 1 bits of // size n may be found in c, then it returns an integer >= 64. -- GitLab From 99699d14fe538f6886948ee6d3cc57f7f2a9bff7 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Thu, 4 Nov 2021 11:59:17 -0700 Subject: [PATCH 1964/2500] cmd/compile: fix TypeDefn to deal with node with no Ntype set Adjust TypeDefn(), which is used by reportTypeLoop(), to work for nodes with no Ntype set (which are all nodes in -G=3 mode). Normally, reportTypeLoop() would not be called, because the types2 typechecker would have already caught it. This is a possible way to report an unusual type loop involving type params, which is not being caught by the types2 type checker. Updates #48962 Change-Id: I55edee46026eece2e8647c5b5b4d8dfb39eeb5f8 Reviewed-on: https://go-review.googlesource.com/c/go/+/361398 Trust: Dan Scales Reviewed-by: Matthew Dempsky Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/ir/name.go | 5 ++++- test/typeparam/issue48962.go | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 test/typeparam/issue48962.go diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go index dcfff7deba..1d4110c73c 100644 --- a/src/cmd/compile/internal/ir/name.go +++ b/src/cmd/compile/internal/ir/name.go @@ -146,7 +146,10 @@ func (n *Name) editChildren(edit func(Node) Node) {} // That is, given "type T Defn", it returns Defn. // It is used by package types. func (n *Name) TypeDefn() *types.Type { - return n.Ntype.Type() + if n.Ntype != nil { + return n.Ntype.Type() + } + return n.Type() } // RecordFrameOffset records the frame offset for the name. diff --git a/test/typeparam/issue48962.go b/test/typeparam/issue48962.go new file mode 100644 index 0000000000..de9a23cdd2 --- /dev/null +++ b/test/typeparam/issue48962.go @@ -0,0 +1,15 @@ +// errorcheck -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T0[P any] struct { // ERROR "invalid recursive type" + f P +} + +type T1 struct { + _ T0[T1] +} -- GitLab From 978e39e9e647d7359a41ac32992ef6ff5380be08 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Thu, 4 Nov 2021 16:08:08 -0400 Subject: [PATCH 1965/2500] crypto/elliptic: tolerate large inputs to IsOnCurve methods The behavior of all Curve methods and package functions when provided an off-curve point is undefined, except for IsOnCurve which should really always return false, not panic. Change-Id: I52f65df25c5af0314fef2c63d0778db72c0f1313 Reviewed-on: https://go-review.googlesource.com/c/go/+/361402 Trust: Filippo Valsorda Run-TryBot: Filippo Valsorda Reviewed-by: Roland Shoemaker TryBot-Result: Go Bot --- src/crypto/elliptic/elliptic_test.go | 10 ++++++++++ src/crypto/elliptic/p224.go | 4 ++++ src/crypto/elliptic/p521.go | 16 +++++++++++----- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/crypto/elliptic/elliptic_test.go b/src/crypto/elliptic/elliptic_test.go index c9744b5a51..d30a6939a4 100644 --- a/src/crypto/elliptic/elliptic_test.go +++ b/src/crypto/elliptic/elliptic_test.go @@ -241,6 +241,16 @@ func testMarshalCompressed(t *testing.T, curve Curve, x, y *big.Int, want []byte } } +func TestLargeIsOnCurve(t *testing.T) { + testAllCurves(t, func(t *testing.T, curve Curve) { + large := big.NewInt(1) + large.Lsh(large, 1000) + if curve.IsOnCurve(large, large) { + t.Errorf("(2^1000, 2^1000) is reported on the curve") + } + }) +} + func benchmarkAllCurves(t *testing.B, f func(*testing.B, Curve)) { tests := []struct { name string diff --git a/src/crypto/elliptic/p224.go b/src/crypto/elliptic/p224.go index 8f3622c89c..34079d14b1 100644 --- a/src/crypto/elliptic/p224.go +++ b/src/crypto/elliptic/p224.go @@ -50,6 +50,10 @@ func (curve p224Curve) Params() *CurveParams { } func (curve p224Curve) IsOnCurve(bigX, bigY *big.Int) bool { + if bigX.BitLen() > 224 || bigY.BitLen() > 224 { + return false + } + var x, y p224FieldElement p224FromBig(&x, bigX) p224FromBig(&y, bigY) diff --git a/src/crypto/elliptic/p521.go b/src/crypto/elliptic/p521.go index 4cc5f86d6d..e64007dfe3 100644 --- a/src/crypto/elliptic/p521.go +++ b/src/crypto/elliptic/p521.go @@ -55,19 +55,25 @@ func (curve p521Curve) Params() *CurveParams { } func (curve p521Curve) IsOnCurve(x, y *big.Int) bool { - // IsOnCurve is documented to reject (0, 0), so we don't use - // p521PointFromAffine, but let SetBytes reject the invalid Marshal output. - _, err := nistec.NewP521Point().SetBytes(Marshal(curve, x, y)) - return err == nil + // IsOnCurve is documented to reject (0, 0), the conventional point at + // infinity, which however is accepted by p521PointFromAffine. + if x.Sign() == 0 && y.Sign() == 0 { + return false + } + _, ok := p521PointFromAffine(x, y) + return ok } func p521PointFromAffine(x, y *big.Int) (p *nistec.P521Point, ok bool) { // (0, 0) is by convention the point at infinity, which can't be represented // in affine coordinates. Marshal incorrectly encodes it as an uncompressed - // point, which SetBytes correctly rejects. See Issue 37294. + // point, which SetBytes would correctly reject. See Issue 37294. if x.Sign() == 0 && y.Sign() == 0 { return nistec.NewP521Point(), true } + if x.BitLen() > 521 || y.BitLen() > 521 { + return nil, false + } p, err := nistec.NewP521Point().SetBytes(Marshal(P521(), x, y)) if err != nil { return nil, false -- GitLab From 1f9dce749db804a8cce767adde3701378db1461c Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Wed, 20 Oct 2021 14:02:24 -0400 Subject: [PATCH 1966/2500] cmd/go: download fewer dependencies in 'go mod download' In modules that specify 'go 1.17' or higher, the go.mod file explicitly requires modules for all packages transitively imported by the main module. Users tend to use 'go mod download' to prepare for testing the main module itself, so we should only download those relevant modules. In 'go 1.16' and earlier modules, we continue to download all modules in the module graph (because we cannot in general tell which ones are relevant without loading the full package import graph). 'go mod download all' continues to download every module in 'go list all', as it did before. Fixes #44435 Change-Id: I3f286c0e2549d6688b3832ff116e6cd77a19401c Reviewed-on: https://go-review.googlesource.com/c/go/+/357310 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Michael Matloob --- doc/go1.18.html | 13 +++++ src/cmd/go/alldocs.go | 7 ++- src/cmd/go/internal/modcmd/download.go | 61 ++++++++++++++++----- src/cmd/go/internal/modload/buildlist.go | 2 +- src/cmd/go/internal/modload/modfile.go | 6 +- src/cmd/go/testdata/script/mod_download.txt | 44 +++++++++++++++ 6 files changed, 113 insertions(+), 20 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 171cc3cb22..385a1ae804 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -90,6 +90,19 @@ Do not send CLs removing the interior tags from such phrases. package.

+

+ If the main module's go.mod file + specifies go 1.17 + or higher, go mod download without + arguments now downloads source code for only the modules + explicitly required in the main + module's go.mod file. (In a go 1.17 or + higher module, that set already includes all dependencies needed to build the + packages and tests in the main module.) + To also download source code for transitive dependencies, use + go mod download all. +

+

TODO: complete this section, or delete if not needed

diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 0dcb317995..4420073e52 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -1074,8 +1074,11 @@ // // Download downloads the named modules, which can be module patterns selecting // dependencies of the main module or module queries of the form path@version. -// With no arguments, download applies to all dependencies of the main module -// (equivalent to 'go mod download all'). +// +// With no arguments, download applies to the modules needed to build and test +// the packages in the main module: the modules explicitly required by the main +// module if it is at 'go 1.17' or higher, or all transitively-required modules +// if at 'go 1.16' or lower. // // The go command will automatically download modules as needed during ordinary // execution. The "go mod download" command is useful mainly for pre-filling diff --git a/src/cmd/go/internal/modcmd/download.go b/src/cmd/go/internal/modcmd/download.go index 5ea56c34bd..f252133762 100644 --- a/src/cmd/go/internal/modcmd/download.go +++ b/src/cmd/go/internal/modcmd/download.go @@ -16,6 +16,7 @@ import ( "cmd/go/internal/modload" "golang.org/x/mod/module" + "golang.org/x/mod/semver" ) var cmdDownload = &base.Command{ @@ -24,8 +25,11 @@ var cmdDownload = &base.Command{ Long: ` Download downloads the named modules, which can be module patterns selecting dependencies of the main module or module queries of the form path@version. -With no arguments, download applies to all dependencies of the main module -(equivalent to 'go mod download all'). + +With no arguments, download applies to the modules needed to build and test +the packages in the main module: the modules explicitly required by the main +module if it is at 'go 1.17' or higher, or all transitively-required modules +if at 'go 1.16' or lower. The go command will automatically download modules as needed during ordinary execution. The "go mod download" command is useful mainly for pre-filling @@ -87,13 +91,8 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { // Check whether modules are enabled and whether we're in a module. modload.ForceUseModules = true modload.ExplicitWriteGoMod = true - if !modload.HasModRoot() && len(args) == 0 { - base.Fatalf("go: no modules specified (see 'go help mod download')") - } haveExplicitArgs := len(args) > 0 - if !haveExplicitArgs { - args = []string{"all"} - } + if modload.HasModRoot() { modload.LoadModFile(ctx) // to fill MainModules @@ -102,14 +101,48 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { } mainModule := modload.MainModules.Versions()[0] - targetAtUpgrade := mainModule.Path + "@upgrade" - targetAtPatch := mainModule.Path + "@patch" - for _, arg := range args { - switch arg { - case mainModule.Path, targetAtUpgrade, targetAtPatch: - os.Stderr.WriteString("go: skipping download of " + arg + " that resolves to the main module\n") + if haveExplicitArgs { + targetAtUpgrade := mainModule.Path + "@upgrade" + targetAtPatch := mainModule.Path + "@patch" + for _, arg := range args { + switch arg { + case mainModule.Path, targetAtUpgrade, targetAtPatch: + os.Stderr.WriteString("go: skipping download of " + arg + " that resolves to the main module\n") + } } + } else { + modFile := modload.MainModules.ModFile(mainModule) + if modFile.Go == nil || semver.Compare("v"+modFile.Go.Version, modload.ExplicitIndirectVersionV) < 0 { + if len(modFile.Require) > 0 { + args = []string{"all"} + } + } else { + // As of Go 1.17, the go.mod file explicitly requires every module + // that provides any package imported by the main module. + // 'go mod download' is typically run before testing packages in the + // main module, so by default we shouldn't download the others + // (which are presumed irrelevant to the packages in the main module). + // See https://golang.org/issue/44435. + // + // However, we also need to load the full module graph, to ensure that + // we have downloaded enough of the module graph to run 'go list all', + // 'go mod graph', and similar commands. + _ = modload.LoadModGraph(ctx, "") + + for _, m := range modFile.Require { + args = append(args, m.Mod.Path) + } + } + } + } + + if len(args) == 0 { + if modload.HasModRoot() { + os.Stderr.WriteString("go: no module dependencies to download\n") + } else { + base.Errorf("go: no modules specified (see 'go help mod download')") } + base.Exit() } downloadModule := func(m *moduleJSON) { diff --git a/src/cmd/go/internal/modload/buildlist.go b/src/cmd/go/internal/modload/buildlist.go index 4634ad009d..27cab0b9c8 100644 --- a/src/cmd/go/internal/modload/buildlist.go +++ b/src/cmd/go/internal/modload/buildlist.go @@ -236,7 +236,7 @@ func (rs *Requirements) IsDirect(path string) bool { // A ModuleGraph represents the complete graph of module dependencies // of a main module. // -// If the main module is lazily loaded, the graph does not include +// If the main module supports module graph pruning, the graph does not include // transitive dependencies of non-root (implicit) dependencies. type ModuleGraph struct { g *mvs.Graph diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index 87e8a5e83d..1672d563b7 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -33,13 +33,13 @@ const ( // tests outside of the main module. narrowAllVersionV = "v1.16" - // explicitIndirectVersionV is the Go version (plus leading "v") at which a + // ExplicitIndirectVersionV is the Go version (plus leading "v") at which a // module's go.mod file is expected to list explicit requirements on every // module that provides any package transitively imported by that module. // // Other indirect dependencies of such a module can be safely pruned out of // the module graph; see https://golang.org/ref/mod#graph-pruning. - explicitIndirectVersionV = "v1.17" + ExplicitIndirectVersionV = "v1.17" // separateIndirectVersionV is the Go version (plus leading "v") at which // "// indirect" dependencies are added in a block separate from the direct @@ -123,7 +123,7 @@ const ( ) func pruningForGoVersion(goVersion string) modPruning { - if semver.Compare("v"+goVersion, explicitIndirectVersionV) < 0 { + if semver.Compare("v"+goVersion, ExplicitIndirectVersionV) < 0 { // The go.mod file does not duplicate relevant information about transitive // dependencies, so they cannot be pruned out. return unpruned diff --git a/src/cmd/go/testdata/script/mod_download.txt b/src/cmd/go/testdata/script/mod_download.txt index 89e58a2cfd..154e68338b 100644 --- a/src/cmd/go/testdata/script/mod_download.txt +++ b/src/cmd/go/testdata/script/mod_download.txt @@ -128,6 +128,50 @@ rm go.sum go mod download all cmp go.mod.update go.mod grep '^rsc.io/sampler v1.3.0 ' go.sum + +# https://golang.org/issue/44435: At go 1.17 or higher, 'go mod download' +# (without arguments) should only download the modules explicitly required in +# the go.mod file, not (presumed-irrelevant) transitive dependencies. +# +# (If the go.mod file is inconsistent, the version downloaded should be the +# selected version from the broader graph, but the go.mod file will also be +# updated to list the correct versions. If at some point we change 'go mod +# download' to stop updating for consistency, then it should fail if the +# requirements are inconsistent.) + +rm go.sum +cp go.mod.orig go.mod +go mod edit -go=1.17 +cp go.mod.update go.mod.go117 +go mod edit -go=1.17 go.mod.go117 + +go clean -modcache +go mod download +cmp go.mod go.mod.go117 + +go list -e -m all +stdout '^rsc.io/quote v1.5.2$' +exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip +stdout '^rsc.io/sampler v1.3.0$' +! exists $GOPATH/pkg/mod/cache/download/rsc.io/sampler/@v/v1.2.1.zip +exists $GOPATH/pkg/mod/cache/download/rsc.io/sampler/@v/v1.3.0.zip +stdout '^golang\.org/x/text v0.0.0-20170915032832-14c0d48ead0c$' +! exists $GOPATH/pkg/mod/cache/download/golang.org/x/text/@v/v0.0.0-20170915032832-14c0d48ead0c.zip +cmp go.mod go.mod.go117 + +# However, 'go mod download all' continues to download the selected version +# of every module reported by 'go list -m all'. + +cp go.mod.orig go.mod +go mod edit -go=1.17 +go clean -modcache +go mod download all +exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip +! exists $GOPATH/pkg/mod/cache/download/rsc.io/sampler/@v/v1.2.1.zip +exists $GOPATH/pkg/mod/cache/download/rsc.io/sampler/@v/v1.3.0.zip +exists $GOPATH/pkg/mod/cache/download/golang.org/x/text/@v/v0.0.0-20170915032832-14c0d48ead0c.zip +cmp go.mod go.mod.go117 + cd .. # allow go mod download without go.mod -- GitLab From 82481525280e4d0c74cb3f6341ce2f4653a165b8 Mon Sep 17 00:00:00 2001 From: Simon Law Date: Thu, 4 Nov 2021 11:14:59 -0700 Subject: [PATCH 1967/2500] test: fix indentation for -shuffle help text The help text for the go test -shuffle flag is not indented like the other flags. This patch brings it into alignment. Fixes #49357 Change-Id: I3f18dc7cd84d5f23099262acf6e2fedccb11379c Reviewed-on: https://go-review.googlesource.com/c/go/+/361395 Reviewed-by: Bryan C. Mills Trust: Bryan C. Mills Trust: Michael Matloob Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot --- src/cmd/go/alldocs.go | 10 +++++----- src/cmd/go/internal/test/test.go | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 4420073e52..c9426801c5 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -2854,11 +2854,11 @@ // exhaustive tests. // // -shuffle off,on,N -// Randomize the execution order of tests and benchmarks. -// It is off by default. If -shuffle is set to on, then it will seed -// the randomizer using the system clock. If -shuffle is set to an -// integer N, then N will be used as the seed value. In both cases, -// the seed will be reported for reproducibility. +// Randomize the execution order of tests and benchmarks. +// It is off by default. If -shuffle is set to on, then it will seed +// the randomizer using the system clock. If -shuffle is set to an +// integer N, then N will be used as the seed value. In both cases, +// the seed will be reported for reproducibility. // // -timeout d // If a test binary runs longer than duration d, panic. diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 7dca6b531c..de6525d541 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -307,11 +307,11 @@ control the execution of any test: exhaustive tests. -shuffle off,on,N - Randomize the execution order of tests and benchmarks. - It is off by default. If -shuffle is set to on, then it will seed - the randomizer using the system clock. If -shuffle is set to an - integer N, then N will be used as the seed value. In both cases, - the seed will be reported for reproducibility. + Randomize the execution order of tests and benchmarks. + It is off by default. If -shuffle is set to on, then it will seed + the randomizer using the system clock. If -shuffle is set to an + integer N, then N will be used as the seed value. In both cases, + the seed will be reported for reproducibility. -timeout d If a test binary runs longer than duration d, panic. -- GitLab From 71fc881cff79d0f3b352c20b947f4911892864fa Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Wed, 3 Nov 2021 10:39:54 -0400 Subject: [PATCH 1968/2500] cmd/go: ensure that 'go test' prints the FAIL line for a package on a new line Fixes #49317 Change-Id: I4038fd4c1d845d54ecbbf82bf73060db1b44c9bc Reviewed-on: https://go-review.googlesource.com/c/go/+/361095 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/cmd/go/internal/test/test.go | 14 +++- .../go/testdata/script/test_fail_newline.txt | 65 +++++++++++++++++++ 2 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 src/cmd/go/testdata/script/test_fail_newline.txt diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index de6525d541..7361c11786 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -1405,15 +1405,25 @@ func (c *runCache) builderRunTest(b *work.Builder, ctx context.Context, a *work. if bytes.HasPrefix(out, tooManyTargetsToFuzz[1:]) || bytes.Contains(out, tooManyTargetsToFuzz) { norun = " [will not fuzz, -fuzz matches more than one target]" } + if len(out) > 0 && !bytes.HasSuffix(out, []byte("\n")) { + // Ensure that the output ends with a newline before the "ok" + // line we're about to print (https://golang.org/issue/49317). + cmd.Stdout.Write([]byte("\n")) + } fmt.Fprintf(cmd.Stdout, "ok \t%s\t%s%s%s\n", a.Package.ImportPath, t, coveragePercentage(out), norun) c.saveOutput(a) } else { base.SetExitStatus(1) - // If there was test output, assume we don't need to print the exit status. - // Buf there's no test output, do print the exit status. if len(out) == 0 { + // If there was no test output, print the exit status so that the reason + // for failure is clear. fmt.Fprintf(cmd.Stdout, "%s\n", err) + } else if !bytes.HasSuffix(out, []byte("\n")) { + // Otherwise, ensure that the output ends with a newline before the FAIL + // line we're about to print (https://golang.org/issue/49317). + cmd.Stdout.Write([]byte("\n")) } + // NOTE(golang.org/issue/37555): test2json reports that a test passes // unless "FAIL" is printed at the beginning of a line. The test may not // actually print that if it panics, exits, or terminates abnormally, diff --git a/src/cmd/go/testdata/script/test_fail_newline.txt b/src/cmd/go/testdata/script/test_fail_newline.txt new file mode 100644 index 0000000000..43cee565a1 --- /dev/null +++ b/src/cmd/go/testdata/script/test_fail_newline.txt @@ -0,0 +1,65 @@ +[short] skip + +# In package list mode, output is buffered. +# Check that a newline is printed after the buffer's contents. +cd fail +! go test . +! stderr . +stdout '^exitcode=1\n' +stdout '^FAIL\s+example/fail' + +# In local directory mode output is streamed, so we don't know +# whether the test printed anything at all, so we print the exit code +# (just in case it failed without emitting any output at all), +# and that happens to add the needed newline as well. +! go test +! stderr . +stdout '^exitcode=1exit status 1\n' +stdout '^FAIL\s+example/fail' + +# In package list mode, if the test passes the 'ok' message appears +# on its own line. +cd ../skip +go test -v . +! stderr . +stdout '^skipping\n' +stdout '^ok\s+example/skip' + +# If the output is streamed and the test passes, we can't tell whether it ended +# in a partial line, and don't want to emit any extra output in the +# overwhelmingly common case that it did not. +# (In theory we could hook the 'os' package to report whether output +# was emitted and whether it ended in a newline, but that seems too invasive.) +go test +! stderr . +stdout '^skippingok\s+example/skip' + + +-- go.mod -- +module example + +go 1.18 +-- fail/fail_test.go -- +package fail + +import ( + "os" + "testing" +) + +func TestMain(m *testing.M) { + os.Stderr.WriteString("exitcode=1") + os.Exit(1) +} +-- skip/skip_test.go -- +package skip + +import ( + "os" + "testing" +) + +func TestMain(m *testing.M) { + os.Stderr.WriteString("skipping") + os.Exit(0) +} -- GitLab From 2c32f29f2f88e56f329547467090e7315cd3c1e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20D=C3=B6tsch?= Date: Fri, 29 Oct 2021 03:23:15 +0000 Subject: [PATCH 1969/2500] cmd/go: clarify errors for pseudo-version commit length These error messages contain the expected shortened revision in braces, but don't explicitly tell the user that this is the expected one. Just unified it with the "does not match version-control timestamp" error which does the same... Change-Id: I8e07df7bd776fd1b39c4c90c4788cb3d626ea00b GitHub-Last-Rev: d14681ad086790f4e43c312c8a328d588acc6ec4 GitHub-Pull-Request: golang/go#42578 Reviewed-on: https://go-review.googlesource.com/c/go/+/269877 Trust: Bryan C. Mills Trust: Jay Conrod Reviewed-by: Jay Conrod --- src/cmd/go/internal/modfetch/coderepo.go | 6 +++--- src/cmd/go/testdata/script/mod_invalid_version.txt | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cmd/go/internal/modfetch/coderepo.go b/src/cmd/go/internal/modfetch/coderepo.go index dfef9f73c2..df835c3d7e 100644 --- a/src/cmd/go/internal/modfetch/coderepo.go +++ b/src/cmd/go/internal/modfetch/coderepo.go @@ -567,11 +567,11 @@ func (r *codeRepo) validatePseudoVersion(info *codehost.RevInfo, version string) if rev != info.Short { switch { case strings.HasPrefix(rev, info.Short): - return fmt.Errorf("revision is longer than canonical (%s)", info.Short) + return fmt.Errorf("revision is longer than canonical (expected %s)", info.Short) case strings.HasPrefix(info.Short, rev): - return fmt.Errorf("revision is shorter than canonical (%s)", info.Short) + return fmt.Errorf("revision is shorter than canonical (expected %s)", info.Short) default: - return fmt.Errorf("does not match short name of revision (%s)", info.Short) + return fmt.Errorf("does not match short name of revision (expected %s)", info.Short) } } diff --git a/src/cmd/go/testdata/script/mod_invalid_version.txt b/src/cmd/go/testdata/script/mod_invalid_version.txt index f9317b676d..428b8aa60e 100644 --- a/src/cmd/go/testdata/script/mod_invalid_version.txt +++ b/src/cmd/go/testdata/script/mod_invalid_version.txt @@ -57,20 +57,20 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0 cd outside ! go list -m golang.org/x/text -stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0: invalid pseudo-version: revision is shorter than canonical \(14c0d48ead0c\)' +stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0: invalid pseudo-version: revision is shorter than canonical \(expected 14c0d48ead0c\)' cd .. ! go list -m golang.org/x/text -stderr 'golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0: invalid pseudo-version: revision is shorter than canonical \(14c0d48ead0c\)' +stderr 'golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0: invalid pseudo-version: revision is shorter than canonical \(expected 14c0d48ead0c\)' # A pseudo-version with more than 12 digits of SHA-1 prefix is invalid. cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0cd47e3104ada247d91be04afc7a5a cd outside ! go list -m golang.org/x/text -stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0cd47e3104ada247d91be04afc7a5a: invalid pseudo-version: revision is longer than canonical \(14c0d48ead0c\)' +stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0cd47e3104ada247d91be04afc7a5a: invalid pseudo-version: revision is longer than canonical \(expected 14c0d48ead0c\)' cd .. ! go list -m golang.org/x/text -stderr 'golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0cd47e3104ada247d91be04afc7a5a: invalid pseudo-version: revision is longer than canonical \(14c0d48ead0c\)' +stderr 'golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0cd47e3104ada247d91be04afc7a5a: invalid pseudo-version: revision is longer than canonical \(expected 14c0d48ead0c\)' # A pseudo-version that does not match the commit timestamp is invalid. cp go.mod.orig go.mod -- GitLab From 156abe51221c5723c3ff524ea0fcbe65d8272bfa Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Thu, 4 Nov 2021 21:09:34 +0000 Subject: [PATCH 1970/2500] runtime: fix hard goal calculation The new GC pacer has a bug where the hard goal isn't set in relation to the original heap goal, but rather to the one already extrapolated for overshoot. In practice, I have never once seen this case arise because the extrapolated goal used for overshoot is conservative. No test because writing a test for this case is impossible in the idealized model the pacer tests create. It is possible to simulate but will take more work. For now, just leave a TODO. Change-Id: I24ff710016cd8100fad54f71b2c8cdea0f7dfa79 Reviewed-on: https://go-review.googlesource.com/c/go/+/361435 Reviewed-by: Michael Pratt Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot --- src/runtime/mgcpacer.go | 7 ++++--- src/runtime/mgcpacer_test.go | 6 ++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/runtime/mgcpacer.go b/src/runtime/mgcpacer.go index f886a07da1..230e78b000 100644 --- a/src/runtime/mgcpacer.go +++ b/src/runtime/mgcpacer.go @@ -517,7 +517,7 @@ func (c *gcControllerState) revise() { // growths. It's OK to use more memory this cycle to scan all the live heap, // because the next GC cycle is inevitably going to use *at least* that much // memory anyway. - heapGoal = int64(float64(heapGoal-int64(c.trigger))/float64(scanWorkExpected)*float64(maxScanWork)) + int64(c.trigger) + extHeapGoal := int64(float64(heapGoal-int64(c.trigger))/float64(scanWorkExpected)*float64(maxScanWork)) + int64(c.trigger) scanWorkExpected = maxScanWork // hardGoal is a hard limit on the amount that we're willing to push back the @@ -528,9 +528,10 @@ func (c *gcControllerState) revise() { // This maintains the invariant that we use no more memory than the next GC cycle // will anyway. hardGoal := int64((1.0 + float64(gcPercent)/100.0) * float64(heapGoal)) - if heapGoal > hardGoal { - heapGoal = hardGoal + if extHeapGoal > hardGoal { + extHeapGoal = hardGoal } + heapGoal = extHeapGoal } if int64(live) > heapGoal { // We're already past our heap goal, even the extrapolated one. diff --git a/src/runtime/mgcpacer_test.go b/src/runtime/mgcpacer_test.go index d2707ca5a1..9ec0e5172b 100644 --- a/src/runtime/mgcpacer_test.go +++ b/src/runtime/mgcpacer_test.go @@ -302,6 +302,12 @@ func TestGcPacer(t *testing.T) { } }, }, + // TODO(mknyszek): Write a test that exercises the pacer's hard goal. + // This is difficult in the idealized model this testing framework places + // the pacer in, because the calculated overshoot is directly proportional + // to the runway for the case of the expected work. + // However, it is still possible to trigger this case if something exceptional + // happens between calls to revise; the framework just doesn't support this yet. } { e := e t.Run(e.name, func(t *testing.T) { -- GitLab From bfd74fd4228009bb9243c1836f9886ba1ad56e15 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Wed, 3 Nov 2021 14:08:43 -0700 Subject: [PATCH 1971/2500] net: remove the alloc from WriteMsgUDPAddrPort MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit name old time/op new time/op delta ReadWriteMsgUDPAddrPort-8 5.12µs ± 8% 4.59µs ± 3% -10.19% (p=0.000 n=10+9) name old alloc/op new alloc/op delta ReadWriteMsgUDPAddrPort-8 64.0B ± 0% 32.0B ± 0% -50.00% (p=0.000 n=10+10) name old allocs/op new allocs/op delta ReadWriteMsgUDPAddrPort-8 2.00 ± 0% 1.00 ± 0% -50.00% (p=0.000 n=10+10) Change-Id: Idf540b2f9f8035660305a0ab1cfc3e162569db63 Reviewed-on: https://go-review.googlesource.com/c/go/+/361257 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/internal/poll/fd_unix.go | 52 ++++++++++++++++++ src/internal/poll/fd_windows.go | 84 +++++++++++++++++++++++------ src/internal/syscall/unix/net.go | 8 +++ src/internal/syscall/unix/net_js.go | 8 +++ src/net/fd_posix.go | 12 +++++ src/net/net_fake.go | 8 +++ src/net/udpsock_posix.go | 6 +-- src/syscall/syscall_unix.go | 16 ++++++ 8 files changed, 175 insertions(+), 19 deletions(-) diff --git a/src/internal/poll/fd_unix.go b/src/internal/poll/fd_unix.go index fd5ac85850..b090e5b6bd 100644 --- a/src/internal/poll/fd_unix.go +++ b/src/internal/poll/fd_unix.go @@ -485,6 +485,58 @@ func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, err } } +// WriteMsgInet4 is WriteMsg specialized for syscall.SockaddrInet4. +func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa syscall.SockaddrInet4) (int, int, error) { + if err := fd.writeLock(); err != nil { + return 0, 0, err + } + defer fd.writeUnlock() + if err := fd.pd.prepareWrite(fd.isFile); err != nil { + return 0, 0, err + } + for { + n, err := unix.SendmsgNInet4(fd.Sysfd, p, oob, sa, 0) + if err == syscall.EINTR { + continue + } + if err == syscall.EAGAIN && fd.pd.pollable() { + if err = fd.pd.waitWrite(fd.isFile); err == nil { + continue + } + } + if err != nil { + return n, 0, err + } + return n, len(oob), err + } +} + +// WriteMsgInet6 is WriteMsg specialized for syscall.SockaddrInet6. +func (fd *FD) WriteMsgInet6(p []byte, oob []byte, sa syscall.SockaddrInet6) (int, int, error) { + if err := fd.writeLock(); err != nil { + return 0, 0, err + } + defer fd.writeUnlock() + if err := fd.pd.prepareWrite(fd.isFile); err != nil { + return 0, 0, err + } + for { + n, err := unix.SendmsgNInet6(fd.Sysfd, p, oob, sa, 0) + if err == syscall.EINTR { + continue + } + if err == syscall.EAGAIN && fd.pd.pollable() { + if err = fd.pd.waitWrite(fd.isFile); err == nil { + continue + } + } + if err != nil { + return n, 0, err + } + return n, len(oob), err + } +} + // Accept wraps the accept network call. func (fd *FD) Accept() (int, syscall.Sockaddr, string, error) { if err := fd.readLock(); err != nil { diff --git a/src/internal/poll/fd_windows.go b/src/internal/poll/fd_windows.go index 139f78a7c1..f8fc4de75d 100644 --- a/src/internal/poll/fd_windows.go +++ b/src/internal/poll/fd_windows.go @@ -1128,25 +1128,35 @@ func (fd *FD) RawWrite(f func(uintptr) bool) error { return syscall.EWINDOWS } +func sockaddrInet4ToRaw(sa syscall.SockaddrInet4) (unsafe.Pointer, int32) { + var raw syscall.RawSockaddrInet4 + raw.Family = syscall.AF_INET + p := (*[2]byte)(unsafe.Pointer(&raw.Port)) + p[0] = byte(sa.Port >> 8) + p[1] = byte(sa.Port) + raw.Addr = sa.Addr + return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw)) +} + +func sockaddrInet6ToRaw(sa syscall.SockaddrInet6) (unsafe.Pointer, int32) { + var raw syscall.RawSockaddrInet6 + raw.Family = syscall.AF_INET6 + p := (*[2]byte)(unsafe.Pointer(&raw.Port)) + p[0] = byte(sa.Port >> 8) + p[1] = byte(sa.Port) + raw.Scope_id = sa.ZoneId + raw.Addr = sa.Addr + return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw)) +} + func sockaddrToRaw(sa syscall.Sockaddr) (unsafe.Pointer, int32, error) { switch sa := sa.(type) { case *syscall.SockaddrInet4: - var raw syscall.RawSockaddrInet4 - raw.Family = syscall.AF_INET - p := (*[2]byte)(unsafe.Pointer(&raw.Port)) - p[0] = byte(sa.Port >> 8) - p[1] = byte(sa.Port) - raw.Addr = sa.Addr - return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw)), nil + ptr, sz := sockaddrInet4ToRaw(*sa) + return ptr, sz, nil case *syscall.SockaddrInet6: - var raw syscall.RawSockaddrInet6 - raw.Family = syscall.AF_INET6 - p := (*[2]byte)(unsafe.Pointer(&raw.Port)) - p[0] = byte(sa.Port >> 8) - p[1] = byte(sa.Port) - raw.Scope_id = sa.ZoneId - raw.Addr = sa.Addr - return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw)), nil + ptr, sz := sockaddrInet6ToRaw(*sa) + return ptr, sz, nil default: return nil, 0, syscall.EWINDOWS } @@ -1206,3 +1216,47 @@ func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, err }) return n, int(o.msg.Control.Len), err } + +// WriteMsgInet4 is WriteMsg specialized for syscall.SockaddrInet4. +func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa syscall.SockaddrInet4) (int, int, error) { + if len(p) > maxRW { + return 0, 0, errors.New("packet is too large (only 1GB is allowed)") + } + + if err := fd.writeLock(); err != nil { + return 0, 0, err + } + defer fd.writeUnlock() + + o := &fd.wop + o.InitMsg(p, oob) + rsa, len := sockaddrInet4ToRaw(sa) + o.msg.Name = (syscall.Pointer)(rsa) + o.msg.Namelen = len + n, err := execIO(o, func(o *operation) error { + return windows.WSASendMsg(o.fd.Sysfd, &o.msg, 0, &o.qty, &o.o, nil) + }) + return n, int(o.msg.Control.Len), err +} + +// WriteMsgInet6 is WriteMsg specialized for syscall.SockaddrInet6. +func (fd *FD) WriteMsgInet6(p []byte, oob []byte, sa syscall.SockaddrInet6) (int, int, error) { + if len(p) > maxRW { + return 0, 0, errors.New("packet is too large (only 1GB is allowed)") + } + + if err := fd.writeLock(); err != nil { + return 0, 0, err + } + defer fd.writeUnlock() + + o := &fd.wop + o.InitMsg(p, oob) + rsa, len := sockaddrInet6ToRaw(sa) + o.msg.Name = (syscall.Pointer)(rsa) + o.msg.Namelen = len + n, err := execIO(o, func(o *operation) error { + return windows.WSASendMsg(o.fd.Sysfd, &o.msg, 0, &o.qty, &o.o, nil) + }) + return n, int(o.msg.Control.Len), err +} diff --git a/src/internal/syscall/unix/net.go b/src/internal/syscall/unix/net.go index 773cf34d96..71e50f54c3 100644 --- a/src/internal/syscall/unix/net.go +++ b/src/internal/syscall/unix/net.go @@ -26,3 +26,11 @@ func SendtoInet4(fd int, p []byte, flags int, to syscall.SockaddrInet4) (err err //go:linkname SendtoInet6 syscall.sendtoInet6 //go:noescape func SendtoInet6(fd int, p []byte, flags int, to syscall.SockaddrInet6) (err error) + +//go:linkname SendmsgNInet4 syscall.sendmsgNInet4 +//go:noescape +func SendmsgNInet4(fd int, p, oob []byte, to syscall.SockaddrInet4, flags int) (n int, err error) + +//go:linkname SendmsgNInet6 syscall.sendmsgNInet6 +//go:noescape +func SendmsgNInet6(fd int, p, oob []byte, to syscall.SockaddrInet6, flags int) (n int, err error) diff --git a/src/internal/syscall/unix/net_js.go b/src/internal/syscall/unix/net_js.go index 3fc5a66470..35bc687b58 100644 --- a/src/internal/syscall/unix/net_js.go +++ b/src/internal/syscall/unix/net_js.go @@ -26,3 +26,11 @@ func SendtoInet4(fd int, p []byte, flags int, to syscall.SockaddrInet4) (err err func SendtoInet6(fd int, p []byte, flags int, to syscall.SockaddrInet6) (err error) { return syscall.ENOSYS } + +func SendmsgNInet4(fd int, p, oob []byte, to syscall.SockaddrInet4, flags int) (n int, err error) { + return 0, syscall.ENOSYS +} + +func SendmsgNInet6(fd int, p, oob []byte, to syscall.SockaddrInet6, flags int) (n int, err error) { + return 0, syscall.ENOSYS +} diff --git a/src/net/fd_posix.go b/src/net/fd_posix.go index 1887a45186..edcef1f2e1 100644 --- a/src/net/fd_posix.go +++ b/src/net/fd_posix.go @@ -110,6 +110,18 @@ func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oob return n, oobn, wrapSyscallError(writeMsgSyscallName, err) } +func (fd *netFD) writeMsgInet4(p []byte, oob []byte, sa syscall.SockaddrInet4) (n int, oobn int, err error) { + n, oobn, err = fd.pfd.WriteMsgInet4(p, oob, sa) + runtime.KeepAlive(fd) + return n, oobn, wrapSyscallError(writeMsgSyscallName, err) +} + +func (fd *netFD) writeMsgInet6(p []byte, oob []byte, sa syscall.SockaddrInet6) (n int, oobn int, err error) { + n, oobn, err = fd.pfd.WriteMsgInet6(p, oob, sa) + runtime.KeepAlive(fd) + return n, oobn, wrapSyscallError(writeMsgSyscallName, err) +} + func (fd *netFD) SetDeadline(t time.Time) error { return fd.pfd.SetDeadline(t) } diff --git a/src/net/net_fake.go b/src/net/net_fake.go index d58bd82029..2ade9f7774 100644 --- a/src/net/net_fake.go +++ b/src/net/net_fake.go @@ -279,6 +279,14 @@ func (fd *netFD) readMsg(p []byte, oob []byte, flags int) (n, oobn, retflags int return 0, 0, 0, nil, syscall.ENOSYS } +func (fd *netFD) writeMsgInet4(p []byte, oob []byte, sa syscall.SockaddrInet4) (n int, oobn int, err error) { + return 0, 0, syscall.ENOSYS +} + +func (fd *netFD) writeMsgInet6(p []byte, oob []byte, sa syscall.SockaddrInet6) (n int, oobn int, err error) { + return 0, 0, syscall.ENOSYS +} + func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) { return 0, syscall.ENOSYS } diff --git a/src/net/udpsock_posix.go b/src/net/udpsock_posix.go index c93994f836..468afbc4dc 100644 --- a/src/net/udpsock_posix.go +++ b/src/net/udpsock_posix.go @@ -188,15 +188,13 @@ func (c *UDPConn) writeMsgAddrPort(b, oob []byte, addr netip.AddrPort) (n, oobn if err != nil { return 0, 0, err } - // TODO: Implement writeMsgInet4 to avoid allocation converting sa to an interface. - return c.fd.writeMsg(b, oob, &sa) + return c.fd.writeMsgInet4(b, oob, sa) case syscall.AF_INET6: sa, err := addrPortToSockaddrInet6(addr) if err != nil { return 0, 0, err } - // TODO: Implement writeMsgInet6 to avoid allocation converting sa to an interface. - return c.fd.writeMsg(b, oob, &sa) + return c.fd.writeMsgInet6(b, oob, sa) default: return 0, 0, &AddrError{Err: "invalid address family", Addr: addr.Addr().String()} } diff --git a/src/syscall/syscall_unix.go b/src/syscall/syscall_unix.go index d1ecc361c6..8692a65794 100644 --- a/src/syscall/syscall_unix.go +++ b/src/syscall/syscall_unix.go @@ -351,6 +351,22 @@ func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) return sendmsgN(fd, p, oob, ptr, salen, flags) } +func sendmsgNInet4(fd int, p, oob []byte, to SockaddrInet4, flags int) (n int, err error) { + ptr, salen, err := to.sockaddr() + if err != nil { + return 0, err + } + return sendmsgN(fd, p, oob, ptr, salen, flags) +} + +func sendmsgNInet6(fd int, p, oob []byte, to SockaddrInet6, flags int) (n int, err error) { + ptr, salen, err := to.sockaddr() + if err != nil { + return 0, err + } + return sendmsgN(fd, p, oob, ptr, salen, flags) +} + func sendtoInet4(fd int, p []byte, flags int, to SockaddrInet4) (err error) { ptr, n, err := to.sockaddr() if err != nil { -- GitLab From 37634eeff9b7510d2eb224397c2bc8c806da83e1 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Wed, 3 Nov 2021 14:42:52 -0700 Subject: [PATCH 1972/2500] net: remove the alloc from ReadMsgUDPAddrPort MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit name old time/op new time/op delta ReadWriteMsgUDPAddrPort-8 4.95µs ± 5% 4.55µs ± 1% -7.96% (p=0.016 n=5+4) name old alloc/op new alloc/op delta ReadWriteMsgUDPAddrPort-8 32.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) name old allocs/op new allocs/op delta ReadWriteMsgUDPAddrPort-8 1.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) Change-Id: Ib968c6f2968926ec9a364dd52063cd0d7c29b10c Reviewed-on: https://go-review.googlesource.com/c/go/+/360862 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/internal/poll/fd_unix.go | 54 ++++++++++++++++++++ src/internal/poll/fd_windows.go | 79 ++++++++++++++++++++++++++--- src/internal/syscall/unix/net.go | 8 +++ src/internal/syscall/unix/net_js.go | 8 +++ src/net/fd_posix.go | 12 +++++ src/net/net_fake.go | 8 +++ src/net/udpsock_posix.go | 12 +++-- src/syscall/syscall_unix.go | 27 ++++++++++ 8 files changed, 195 insertions(+), 13 deletions(-) diff --git a/src/internal/poll/fd_unix.go b/src/internal/poll/fd_unix.go index b090e5b6bd..45d4ce07b2 100644 --- a/src/internal/poll/fd_unix.go +++ b/src/internal/poll/fd_unix.go @@ -311,6 +311,60 @@ func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.S } } +// ReadMsgInet4 is ReadMsg, but specialized for syscall.SockaddrInet4. +func (fd *FD) ReadMsgInet4(p []byte, oob []byte, flags int, sa4 *syscall.SockaddrInet4) (int, int, int, error) { + if err := fd.readLock(); err != nil { + return 0, 0, 0, err + } + defer fd.readUnlock() + if err := fd.pd.prepareRead(fd.isFile); err != nil { + return 0, 0, 0, err + } + for { + n, oobn, sysflags, err := unix.RecvmsgInet4(fd.Sysfd, p, oob, flags, sa4) + if err != nil { + if err == syscall.EINTR { + continue + } + // TODO(dfc) should n and oobn be set to 0 + if err == syscall.EAGAIN && fd.pd.pollable() { + if err = fd.pd.waitRead(fd.isFile); err == nil { + continue + } + } + } + err = fd.eofError(n, err) + return n, oobn, sysflags, err + } +} + +// ReadMsgInet6 is ReadMsg, but specialized for syscall.SockaddrInet6. +func (fd *FD) ReadMsgInet6(p []byte, oob []byte, flags int, sa6 *syscall.SockaddrInet6) (int, int, int, error) { + if err := fd.readLock(); err != nil { + return 0, 0, 0, err + } + defer fd.readUnlock() + if err := fd.pd.prepareRead(fd.isFile); err != nil { + return 0, 0, 0, err + } + for { + n, oobn, sysflags, err := unix.RecvmsgInet6(fd.Sysfd, p, oob, flags, sa6) + if err != nil { + if err == syscall.EINTR { + continue + } + // TODO(dfc) should n and oobn be set to 0 + if err == syscall.EAGAIN && fd.pd.pollable() { + if err = fd.pd.waitRead(fd.isFile); err == nil { + continue + } + } + } + err = fd.eofError(n, err) + return n, oobn, sysflags, err + } +} + // Write implements io.Writer. func (fd *FD) Write(p []byte) (int, error) { if err := fd.writeLock(); err != nil { diff --git a/src/internal/poll/fd_windows.go b/src/internal/poll/fd_windows.go index f8fc4de75d..4dd5986efd 100644 --- a/src/internal/poll/fd_windows.go +++ b/src/internal/poll/fd_windows.go @@ -620,10 +620,7 @@ func (fd *FD) ReadFromInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) if err != nil { return n, err } - sa, _ := o.rsa.Sockaddr() - if sa != nil { - *sa4 = *(sa.(*syscall.SockaddrInet4)) - } + rawToSockaddrInet4(o.rsa, sa4) return n, err } @@ -652,10 +649,7 @@ func (fd *FD) ReadFromInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) if err != nil { return n, err } - sa, _ := o.rsa.Sockaddr() - if sa != nil { - *sa6 = *(sa.(*syscall.SockaddrInet6)) - } + rawToSockaddrInet6(o.rsa, sa6) return n, err } @@ -1149,6 +1143,21 @@ func sockaddrInet6ToRaw(sa syscall.SockaddrInet6) (unsafe.Pointer, int32) { return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw)) } +func rawToSockaddrInet4(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet4) { + pp := (*syscall.RawSockaddrInet4)(unsafe.Pointer(rsa)) + p := (*[2]byte)(unsafe.Pointer(&pp.Port)) + sa.Port = int(p[0])<<8 + int(p[1]) + sa.Addr = pp.Addr +} + +func rawToSockaddrInet6(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet6) { + pp := (*syscall.RawSockaddrInet6)(unsafe.Pointer(rsa)) + p := (*[2]byte)(unsafe.Pointer(&pp.Port)) + sa.Port = int(p[0])<<8 + int(p[1]) + sa.ZoneId = pp.Scope_id + sa.Addr = pp.Addr +} + func sockaddrToRaw(sa syscall.Sockaddr) (unsafe.Pointer, int32, error) { switch sa := sa.(type) { case *syscall.SockaddrInet4: @@ -1190,6 +1199,60 @@ func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.S return n, int(o.msg.Control.Len), int(o.msg.Flags), sa, err } +// ReadMsgInet4 is ReadMsg, but specialized to return a syscall.SockaddrInet4. +func (fd *FD) ReadMsgInet4(p []byte, oob []byte, flags int, sa4 *syscall.SockaddrInet4) (int, int, int, error) { + if err := fd.readLock(); err != nil { + return 0, 0, 0, err + } + defer fd.readUnlock() + + if len(p) > maxRW { + p = p[:maxRW] + } + + o := &fd.rop + o.InitMsg(p, oob) + o.rsa = new(syscall.RawSockaddrAny) + o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa)) + o.msg.Namelen = int32(unsafe.Sizeof(*o.rsa)) + o.msg.Flags = uint32(flags) + n, err := execIO(o, func(o *operation) error { + return windows.WSARecvMsg(o.fd.Sysfd, &o.msg, &o.qty, &o.o, nil) + }) + err = fd.eofError(n, err) + if err == nil { + rawToSockaddrInet4(o.rsa, sa4) + } + return n, int(o.msg.Control.Len), int(o.msg.Flags), err +} + +// ReadMsgInet6 is ReadMsg, but specialized to return a syscall.SockaddrInet6. +func (fd *FD) ReadMsgInet6(p []byte, oob []byte, flags int, sa6 *syscall.SockaddrInet6) (int, int, int, error) { + if err := fd.readLock(); err != nil { + return 0, 0, 0, err + } + defer fd.readUnlock() + + if len(p) > maxRW { + p = p[:maxRW] + } + + o := &fd.rop + o.InitMsg(p, oob) + o.rsa = new(syscall.RawSockaddrAny) + o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa)) + o.msg.Namelen = int32(unsafe.Sizeof(*o.rsa)) + o.msg.Flags = uint32(flags) + n, err := execIO(o, func(o *operation) error { + return windows.WSARecvMsg(o.fd.Sysfd, &o.msg, &o.qty, &o.o, nil) + }) + err = fd.eofError(n, err) + if err == nil { + rawToSockaddrInet6(o.rsa, sa6) + } + return n, int(o.msg.Control.Len), int(o.msg.Flags), err +} + // WriteMsg wraps the WSASendMsg network call. func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, error) { if len(p) > maxRW { diff --git a/src/internal/syscall/unix/net.go b/src/internal/syscall/unix/net.go index 71e50f54c3..87ce89b57f 100644 --- a/src/internal/syscall/unix/net.go +++ b/src/internal/syscall/unix/net.go @@ -34,3 +34,11 @@ func SendmsgNInet4(fd int, p, oob []byte, to syscall.SockaddrInet4, flags int) ( //go:linkname SendmsgNInet6 syscall.sendmsgNInet6 //go:noescape func SendmsgNInet6(fd int, p, oob []byte, to syscall.SockaddrInet6, flags int) (n int, err error) + +//go:linkname RecvmsgInet4 syscall.recvmsgInet4 +//go:noescape +func RecvmsgInet4(fd int, p, oob []byte, flags int, from *syscall.SockaddrInet4) (n, oobn int, recvflags int, err error) + +//go:linkname RecvmsgInet6 syscall.recvmsgInet6 +//go:noescape +func RecvmsgInet6(fd int, p, oob []byte, flags int, from *syscall.SockaddrInet6) (n, oobn int, recvflags int, err error) diff --git a/src/internal/syscall/unix/net_js.go b/src/internal/syscall/unix/net_js.go index 35bc687b58..defc3f6fb2 100644 --- a/src/internal/syscall/unix/net_js.go +++ b/src/internal/syscall/unix/net_js.go @@ -34,3 +34,11 @@ func SendmsgNInet4(fd int, p, oob []byte, to syscall.SockaddrInet4, flags int) ( func SendmsgNInet6(fd int, p, oob []byte, to syscall.SockaddrInet6, flags int) (n int, err error) { return 0, syscall.ENOSYS } + +func RecvmsgInet4(fd int, p, oob []byte, flags int, from *syscall.SockaddrInet4) (n, oobn int, recvflags int, err error) { + return 0, 0, 0, syscall.ENOSYS +} + +func RecvmsgInet6(fd int, p, oob []byte, flags int, from *syscall.SockaddrInet6) (n, oobn int, recvflags int, err error) { + return 0, 0, 0, syscall.ENOSYS +} diff --git a/src/net/fd_posix.go b/src/net/fd_posix.go index edcef1f2e1..d12dbeebd2 100644 --- a/src/net/fd_posix.go +++ b/src/net/fd_posix.go @@ -80,6 +80,18 @@ func (fd *netFD) readMsg(p []byte, oob []byte, flags int) (n, oobn, retflags int return n, oobn, retflags, sa, wrapSyscallError(readMsgSyscallName, err) } +func (fd *netFD) readMsgInet4(p []byte, oob []byte, flags int, sa *syscall.SockaddrInet4) (n, oobn, retflags int, err error) { + n, oobn, retflags, err = fd.pfd.ReadMsgInet4(p, oob, flags, sa) + runtime.KeepAlive(fd) + return n, oobn, retflags, wrapSyscallError(readMsgSyscallName, err) +} + +func (fd *netFD) readMsgInet6(p []byte, oob []byte, flags int, sa *syscall.SockaddrInet6) (n, oobn, retflags int, err error) { + n, oobn, retflags, err = fd.pfd.ReadMsgInet6(p, oob, flags, sa) + runtime.KeepAlive(fd) + return n, oobn, retflags, wrapSyscallError(readMsgSyscallName, err) +} + func (fd *netFD) Write(p []byte) (nn int, err error) { nn, err = fd.pfd.Write(p) runtime.KeepAlive(fd) diff --git a/src/net/net_fake.go b/src/net/net_fake.go index 2ade9f7774..8da9d15bb2 100644 --- a/src/net/net_fake.go +++ b/src/net/net_fake.go @@ -279,6 +279,14 @@ func (fd *netFD) readMsg(p []byte, oob []byte, flags int) (n, oobn, retflags int return 0, 0, 0, nil, syscall.ENOSYS } +func (fd *netFD) readMsgInet4(p []byte, oob []byte, flags int, sa *syscall.SockaddrInet4) (n, oobn, retflags int, err error) { + return 0, 0, 0, syscall.ENOSYS +} + +func (fd *netFD) readMsgInet6(p []byte, oob []byte, flags int, sa *syscall.SockaddrInet6) (n, oobn, retflags int, err error) { + return 0, 0, 0, syscall.ENOSYS +} + func (fd *netFD) writeMsgInet4(p []byte, oob []byte, sa syscall.SockaddrInet4) (n int, oobn int, err error) { return 0, 0, syscall.ENOSYS } diff --git a/src/net/udpsock_posix.go b/src/net/udpsock_posix.go index 468afbc4dc..2bf6568a95 100644 --- a/src/net/udpsock_posix.go +++ b/src/net/udpsock_posix.go @@ -95,13 +95,15 @@ func (c *UDPConn) readFromAddrPort(b []byte) (n int, addr netip.AddrPort, err er } func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr netip.AddrPort, err error) { - var sa syscall.Sockaddr - n, oobn, flags, sa, err = c.fd.readMsg(b, oob, 0) - switch sa := sa.(type) { - case *syscall.SockaddrInet4: + switch c.fd.family { + case syscall.AF_INET: + var sa syscall.SockaddrInet4 + n, oobn, flags, err = c.fd.readMsgInet4(b, oob, 0, &sa) ip := netip.AddrFrom4(sa.Addr) addr = netip.AddrPortFrom(ip, uint16(sa.Port)) - case *syscall.SockaddrInet6: + case syscall.AF_INET6: + var sa syscall.SockaddrInet6 + n, oobn, flags, err = c.fd.readMsgInet6(b, oob, 0, &sa) ip := netip.AddrFrom16(sa.Addr).WithZone(zoneCache.name(int(sa.ZoneId))) addr = netip.AddrPortFrom(ip, uint16(sa.Port)) } diff --git a/src/syscall/syscall_unix.go b/src/syscall/syscall_unix.go index 8692a65794..56d3cad1d0 100644 --- a/src/syscall/syscall_unix.go +++ b/src/syscall/syscall_unix.go @@ -324,6 +324,33 @@ func recvfromInet6(fd int, p []byte, flags int, from *SockaddrInet6) (n int, err return } +func recvmsgInet4(fd int, p, oob []byte, flags int, from *SockaddrInet4) (n, oobn int, recvflags int, err error) { + var rsa RawSockaddrAny + n, oobn, recvflags, err = recvmsgRaw(fd, p, oob, flags, &rsa) + if err != nil { + return + } + pp := (*RawSockaddrInet4)(unsafe.Pointer(&rsa)) + port := (*[2]byte)(unsafe.Pointer(&pp.Port)) + from.Port = int(port[0])<<8 + int(port[1]) + from.Addr = pp.Addr + return +} + +func recvmsgInet6(fd int, p, oob []byte, flags int, from *SockaddrInet6) (n, oobn int, recvflags int, err error) { + var rsa RawSockaddrAny + n, oobn, recvflags, err = recvmsgRaw(fd, p, oob, flags, &rsa) + if err != nil { + return + } + pp := (*RawSockaddrInet6)(unsafe.Pointer(&rsa)) + port := (*[2]byte)(unsafe.Pointer(&pp.Port)) + from.Port = int(port[0])<<8 + int(port[1]) + from.ZoneId = pp.Scope_id + from.Addr = pp.Addr + return +} + func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { var rsa RawSockaddrAny n, oobn, recvflags, err = recvmsgRaw(fd, p, oob, flags, &rsa) -- GitLab From 8ad0a7e7853ffea6140e942ea5f553061d3423c2 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Wed, 3 Nov 2021 16:28:47 -0700 Subject: [PATCH 1973/2500] net: pass around pointers to SockaddrInetN ...instead of the structs themselves. Escape analysis can handle this, and it'll avoid a bunch of large struct copies. Change-Id: Ia9c6064ed32a4c26d5a96dae2ed7d7ece6d38704 Reviewed-on: https://go-review.googlesource.com/c/go/+/361264 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/internal/poll/fd_unix.go | 8 +++--- src/internal/poll/fd_windows.go | 30 +++++++++------------ src/internal/syscall/unix/net.go | 8 +++--- src/internal/syscall/unix/net_js.go | 8 +++--- src/internal/syscall/windows/net_windows.go | 4 +-- src/net/fd_posix.go | 8 +++--- src/net/net_fake.go | 8 +++--- src/net/udpsock_posix.go | 12 ++++----- src/syscall/syscall_unix.go | 8 +++--- src/syscall/syscall_windows.go | 4 +-- 10 files changed, 46 insertions(+), 52 deletions(-) diff --git a/src/internal/poll/fd_unix.go b/src/internal/poll/fd_unix.go index 45d4ce07b2..85971a16cd 100644 --- a/src/internal/poll/fd_unix.go +++ b/src/internal/poll/fd_unix.go @@ -436,7 +436,7 @@ func (fd *FD) Pwrite(p []byte, off int64) (int, error) { } // WriteToInet4 wraps the sendto network call for IPv4 addresses. -func (fd *FD) WriteToInet4(p []byte, sa syscall.SockaddrInet4) (int, error) { +func (fd *FD) WriteToInet4(p []byte, sa *syscall.SockaddrInet4) (int, error) { if err := fd.writeLock(); err != nil { return 0, err } @@ -462,7 +462,7 @@ func (fd *FD) WriteToInet4(p []byte, sa syscall.SockaddrInet4) (int, error) { } // WriteToInet6 wraps the sendto network call for IPv6 addresses. -func (fd *FD) WriteToInet6(p []byte, sa syscall.SockaddrInet6) (int, error) { +func (fd *FD) WriteToInet6(p []byte, sa *syscall.SockaddrInet6) (int, error) { if err := fd.writeLock(); err != nil { return 0, err } @@ -540,7 +540,7 @@ func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, err } // WriteMsgInet4 is WriteMsg specialized for syscall.SockaddrInet4. -func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa syscall.SockaddrInet4) (int, int, error) { +func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa *syscall.SockaddrInet4) (int, int, error) { if err := fd.writeLock(); err != nil { return 0, 0, err } @@ -566,7 +566,7 @@ func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa syscall.SockaddrInet4) (int } // WriteMsgInet6 is WriteMsg specialized for syscall.SockaddrInet6. -func (fd *FD) WriteMsgInet6(p []byte, oob []byte, sa syscall.SockaddrInet6) (int, int, error) { +func (fd *FD) WriteMsgInet6(p []byte, oob []byte, sa *syscall.SockaddrInet6) (int, int, error) { if err := fd.writeLock(); err != nil { return 0, 0, err } diff --git a/src/internal/poll/fd_windows.go b/src/internal/poll/fd_windows.go index 4dd5986efd..94cdfca601 100644 --- a/src/internal/poll/fd_windows.go +++ b/src/internal/poll/fd_windows.go @@ -79,8 +79,6 @@ type operation struct { buf syscall.WSABuf msg windows.WSAMsg sa syscall.Sockaddr - sa4 syscall.SockaddrInet4 - sa6 syscall.SockaddrInet6 rsa *syscall.RawSockaddrAny rsan int32 handle syscall.Handle @@ -852,7 +850,7 @@ func (fd *FD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) { } // WriteToInet4 is WriteTo, specialized for syscall.SockaddrInet4. -func (fd *FD) WriteToInet4(buf []byte, sa4 syscall.SockaddrInet4) (int, error) { +func (fd *FD) WriteToInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) { if err := fd.writeLock(); err != nil { return 0, err } @@ -862,9 +860,8 @@ func (fd *FD) WriteToInet4(buf []byte, sa4 syscall.SockaddrInet4) (int, error) { // handle zero-byte payload o := &fd.wop o.InitBuf(buf) - o.sa4 = sa4 n, err := execIO(o, func(o *operation) error { - return windows.WSASendtoInet4(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa4, &o.o, nil) + return windows.WSASendtoInet4(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, sa4, &o.o, nil) }) return n, err } @@ -877,9 +874,8 @@ func (fd *FD) WriteToInet4(buf []byte, sa4 syscall.SockaddrInet4) (int, error) { } o := &fd.wop o.InitBuf(b) - o.sa4 = sa4 n, err := execIO(o, func(o *operation) error { - return windows.WSASendtoInet4(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa4, &o.o, nil) + return windows.WSASendtoInet4(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, sa4, &o.o, nil) }) ntotal += int(n) if err != nil { @@ -891,7 +887,7 @@ func (fd *FD) WriteToInet4(buf []byte, sa4 syscall.SockaddrInet4) (int, error) { } // WriteToInet6 is WriteTo, specialized for syscall.SockaddrInet6. -func (fd *FD) WriteToInet6(buf []byte, sa6 syscall.SockaddrInet6) (int, error) { +func (fd *FD) WriteToInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) { if err := fd.writeLock(); err != nil { return 0, err } @@ -901,9 +897,8 @@ func (fd *FD) WriteToInet6(buf []byte, sa6 syscall.SockaddrInet6) (int, error) { // handle zero-byte payload o := &fd.wop o.InitBuf(buf) - o.sa6 = sa6 n, err := execIO(o, func(o *operation) error { - return windows.WSASendtoInet6(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa6, &o.o, nil) + return windows.WSASendtoInet6(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, sa6, &o.o, nil) }) return n, err } @@ -916,9 +911,8 @@ func (fd *FD) WriteToInet6(buf []byte, sa6 syscall.SockaddrInet6) (int, error) { } o := &fd.wop o.InitBuf(b) - o.sa6 = sa6 n, err := execIO(o, func(o *operation) error { - return windows.WSASendtoInet6(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa6, &o.o, nil) + return windows.WSASendtoInet6(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, sa6, &o.o, nil) }) ntotal += int(n) if err != nil { @@ -1122,7 +1116,7 @@ func (fd *FD) RawWrite(f func(uintptr) bool) error { return syscall.EWINDOWS } -func sockaddrInet4ToRaw(sa syscall.SockaddrInet4) (unsafe.Pointer, int32) { +func sockaddrInet4ToRaw(sa *syscall.SockaddrInet4) (unsafe.Pointer, int32) { var raw syscall.RawSockaddrInet4 raw.Family = syscall.AF_INET p := (*[2]byte)(unsafe.Pointer(&raw.Port)) @@ -1132,7 +1126,7 @@ func sockaddrInet4ToRaw(sa syscall.SockaddrInet4) (unsafe.Pointer, int32) { return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw)) } -func sockaddrInet6ToRaw(sa syscall.SockaddrInet6) (unsafe.Pointer, int32) { +func sockaddrInet6ToRaw(sa *syscall.SockaddrInet6) (unsafe.Pointer, int32) { var raw syscall.RawSockaddrInet6 raw.Family = syscall.AF_INET6 p := (*[2]byte)(unsafe.Pointer(&raw.Port)) @@ -1161,10 +1155,10 @@ func rawToSockaddrInet6(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet6) func sockaddrToRaw(sa syscall.Sockaddr) (unsafe.Pointer, int32, error) { switch sa := sa.(type) { case *syscall.SockaddrInet4: - ptr, sz := sockaddrInet4ToRaw(*sa) + ptr, sz := sockaddrInet4ToRaw(sa) return ptr, sz, nil case *syscall.SockaddrInet6: - ptr, sz := sockaddrInet6ToRaw(*sa) + ptr, sz := sockaddrInet6ToRaw(sa) return ptr, sz, nil default: return nil, 0, syscall.EWINDOWS @@ -1281,7 +1275,7 @@ func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, err } // WriteMsgInet4 is WriteMsg specialized for syscall.SockaddrInet4. -func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa syscall.SockaddrInet4) (int, int, error) { +func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa *syscall.SockaddrInet4) (int, int, error) { if len(p) > maxRW { return 0, 0, errors.New("packet is too large (only 1GB is allowed)") } @@ -1303,7 +1297,7 @@ func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa syscall.SockaddrInet4) (int } // WriteMsgInet6 is WriteMsg specialized for syscall.SockaddrInet6. -func (fd *FD) WriteMsgInet6(p []byte, oob []byte, sa syscall.SockaddrInet6) (int, int, error) { +func (fd *FD) WriteMsgInet6(p []byte, oob []byte, sa *syscall.SockaddrInet6) (int, int, error) { if len(p) > maxRW { return 0, 0, errors.New("packet is too large (only 1GB is allowed)") } diff --git a/src/internal/syscall/unix/net.go b/src/internal/syscall/unix/net.go index 87ce89b57f..85632e1c03 100644 --- a/src/internal/syscall/unix/net.go +++ b/src/internal/syscall/unix/net.go @@ -21,19 +21,19 @@ func RecvfromInet6(fd int, p []byte, flags int, from *syscall.SockaddrInet6) (n //go:linkname SendtoInet4 syscall.sendtoInet4 //go:noescape -func SendtoInet4(fd int, p []byte, flags int, to syscall.SockaddrInet4) (err error) +func SendtoInet4(fd int, p []byte, flags int, to *syscall.SockaddrInet4) (err error) //go:linkname SendtoInet6 syscall.sendtoInet6 //go:noescape -func SendtoInet6(fd int, p []byte, flags int, to syscall.SockaddrInet6) (err error) +func SendtoInet6(fd int, p []byte, flags int, to *syscall.SockaddrInet6) (err error) //go:linkname SendmsgNInet4 syscall.sendmsgNInet4 //go:noescape -func SendmsgNInet4(fd int, p, oob []byte, to syscall.SockaddrInet4, flags int) (n int, err error) +func SendmsgNInet4(fd int, p, oob []byte, to *syscall.SockaddrInet4, flags int) (n int, err error) //go:linkname SendmsgNInet6 syscall.sendmsgNInet6 //go:noescape -func SendmsgNInet6(fd int, p, oob []byte, to syscall.SockaddrInet6, flags int) (n int, err error) +func SendmsgNInet6(fd int, p, oob []byte, to *syscall.SockaddrInet6, flags int) (n int, err error) //go:linkname RecvmsgInet4 syscall.recvmsgInet4 //go:noescape diff --git a/src/internal/syscall/unix/net_js.go b/src/internal/syscall/unix/net_js.go index defc3f6fb2..622fc8eb14 100644 --- a/src/internal/syscall/unix/net_js.go +++ b/src/internal/syscall/unix/net_js.go @@ -19,19 +19,19 @@ func RecvfromInet6(fd int, p []byte, flags int, from *syscall.SockaddrInet6) (n return 0, syscall.ENOSYS } -func SendtoInet4(fd int, p []byte, flags int, to syscall.SockaddrInet4) (err error) { +func SendtoInet4(fd int, p []byte, flags int, to *syscall.SockaddrInet4) (err error) { return syscall.ENOSYS } -func SendtoInet6(fd int, p []byte, flags int, to syscall.SockaddrInet6) (err error) { +func SendtoInet6(fd int, p []byte, flags int, to *syscall.SockaddrInet6) (err error) { return syscall.ENOSYS } -func SendmsgNInet4(fd int, p, oob []byte, to syscall.SockaddrInet4, flags int) (n int, err error) { +func SendmsgNInet4(fd int, p, oob []byte, to *syscall.SockaddrInet4, flags int) (n int, err error) { return 0, syscall.ENOSYS } -func SendmsgNInet6(fd int, p, oob []byte, to syscall.SockaddrInet6, flags int) (n int, err error) { +func SendmsgNInet6(fd int, p, oob []byte, to *syscall.SockaddrInet6, flags int) (n int, err error) { return 0, syscall.ENOSYS } diff --git a/src/internal/syscall/windows/net_windows.go b/src/internal/syscall/windows/net_windows.go index 1fccd55e4b..3d3df7161c 100644 --- a/src/internal/syscall/windows/net_windows.go +++ b/src/internal/syscall/windows/net_windows.go @@ -11,8 +11,8 @@ import ( //go:linkname WSASendtoInet4 syscall.wsaSendtoInet4 //go:noescape -func WSASendtoInet4(s syscall.Handle, bufs *syscall.WSABuf, bufcnt uint32, sent *uint32, flags uint32, to syscall.SockaddrInet4, overlapped *syscall.Overlapped, croutine *byte) (err error) +func WSASendtoInet4(s syscall.Handle, bufs *syscall.WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *syscall.SockaddrInet4, overlapped *syscall.Overlapped, croutine *byte) (err error) //go:linkname WSASendtoInet6 syscall.wsaSendtoInet6 //go:noescape -func WSASendtoInet6(s syscall.Handle, bufs *syscall.WSABuf, bufcnt uint32, sent *uint32, flags uint32, to syscall.SockaddrInet6, overlapped *syscall.Overlapped, croutine *byte) (err error) +func WSASendtoInet6(s syscall.Handle, bufs *syscall.WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *syscall.SockaddrInet6, overlapped *syscall.Overlapped, croutine *byte) (err error) diff --git a/src/net/fd_posix.go b/src/net/fd_posix.go index d12dbeebd2..1845c173bb 100644 --- a/src/net/fd_posix.go +++ b/src/net/fd_posix.go @@ -104,13 +104,13 @@ func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) { return n, wrapSyscallError(writeToSyscallName, err) } -func (fd *netFD) writeToInet4(p []byte, sa syscall.SockaddrInet4) (n int, err error) { +func (fd *netFD) writeToInet4(p []byte, sa *syscall.SockaddrInet4) (n int, err error) { n, err = fd.pfd.WriteToInet4(p, sa) runtime.KeepAlive(fd) return n, wrapSyscallError(writeToSyscallName, err) } -func (fd *netFD) writeToInet6(p []byte, sa syscall.SockaddrInet6) (n int, err error) { +func (fd *netFD) writeToInet6(p []byte, sa *syscall.SockaddrInet6) (n int, err error) { n, err = fd.pfd.WriteToInet6(p, sa) runtime.KeepAlive(fd) return n, wrapSyscallError(writeToSyscallName, err) @@ -122,13 +122,13 @@ func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oob return n, oobn, wrapSyscallError(writeMsgSyscallName, err) } -func (fd *netFD) writeMsgInet4(p []byte, oob []byte, sa syscall.SockaddrInet4) (n int, oobn int, err error) { +func (fd *netFD) writeMsgInet4(p []byte, oob []byte, sa *syscall.SockaddrInet4) (n int, oobn int, err error) { n, oobn, err = fd.pfd.WriteMsgInet4(p, oob, sa) runtime.KeepAlive(fd) return n, oobn, wrapSyscallError(writeMsgSyscallName, err) } -func (fd *netFD) writeMsgInet6(p []byte, oob []byte, sa syscall.SockaddrInet6) (n int, oobn int, err error) { +func (fd *netFD) writeMsgInet6(p []byte, oob []byte, sa *syscall.SockaddrInet6) (n int, oobn int, err error) { n, oobn, err = fd.pfd.WriteMsgInet6(p, oob, sa) runtime.KeepAlive(fd) return n, oobn, wrapSyscallError(writeMsgSyscallName, err) diff --git a/src/net/net_fake.go b/src/net/net_fake.go index 8da9d15bb2..ee5644c67f 100644 --- a/src/net/net_fake.go +++ b/src/net/net_fake.go @@ -287,11 +287,11 @@ func (fd *netFD) readMsgInet6(p []byte, oob []byte, flags int, sa *syscall.Socka return 0, 0, 0, syscall.ENOSYS } -func (fd *netFD) writeMsgInet4(p []byte, oob []byte, sa syscall.SockaddrInet4) (n int, oobn int, err error) { +func (fd *netFD) writeMsgInet4(p []byte, oob []byte, sa *syscall.SockaddrInet4) (n int, oobn int, err error) { return 0, 0, syscall.ENOSYS } -func (fd *netFD) writeMsgInet6(p []byte, oob []byte, sa syscall.SockaddrInet6) (n int, oobn int, err error) { +func (fd *netFD) writeMsgInet6(p []byte, oob []byte, sa *syscall.SockaddrInet6) (n int, oobn int, err error) { return 0, 0, syscall.ENOSYS } @@ -299,11 +299,11 @@ func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) { return 0, syscall.ENOSYS } -func (fd *netFD) writeToInet4(p []byte, sa syscall.SockaddrInet4) (n int, err error) { +func (fd *netFD) writeToInet4(p []byte, sa *syscall.SockaddrInet4) (n int, err error) { return 0, syscall.ENOSYS } -func (fd *netFD) writeToInet6(p []byte, sa syscall.SockaddrInet6) (n int, err error) { +func (fd *netFD) writeToInet6(p []byte, sa *syscall.SockaddrInet6) (n int, err error) { return 0, syscall.ENOSYS } diff --git a/src/net/udpsock_posix.go b/src/net/udpsock_posix.go index 2bf6568a95..6544397673 100644 --- a/src/net/udpsock_posix.go +++ b/src/net/udpsock_posix.go @@ -124,13 +124,13 @@ func (c *UDPConn) writeTo(b []byte, addr *UDPAddr) (int, error) { if err != nil { return 0, err } - return c.fd.writeToInet4(b, sa) + return c.fd.writeToInet4(b, &sa) case syscall.AF_INET6: sa, err := ipToSockaddrInet6(addr.IP, addr.Port, addr.Zone) if err != nil { return 0, err } - return c.fd.writeToInet6(b, sa) + return c.fd.writeToInet6(b, &sa) default: return 0, &AddrError{Err: "invalid address family", Addr: addr.IP.String()} } @@ -150,13 +150,13 @@ func (c *UDPConn) writeToAddrPort(b []byte, addr netip.AddrPort) (int, error) { if err != nil { return 0, err } - return c.fd.writeToInet4(b, sa) + return c.fd.writeToInet4(b, &sa) case syscall.AF_INET6: sa, err := addrPortToSockaddrInet6(addr) if err != nil { return 0, err } - return c.fd.writeToInet6(b, sa) + return c.fd.writeToInet6(b, &sa) default: return 0, &AddrError{Err: "invalid address family", Addr: addr.Addr().String()} } @@ -190,13 +190,13 @@ func (c *UDPConn) writeMsgAddrPort(b, oob []byte, addr netip.AddrPort) (n, oobn if err != nil { return 0, 0, err } - return c.fd.writeMsgInet4(b, oob, sa) + return c.fd.writeMsgInet4(b, oob, &sa) case syscall.AF_INET6: sa, err := addrPortToSockaddrInet6(addr) if err != nil { return 0, 0, err } - return c.fd.writeMsgInet6(b, oob, sa) + return c.fd.writeMsgInet6(b, oob, &sa) default: return 0, 0, &AddrError{Err: "invalid address family", Addr: addr.Addr().String()} } diff --git a/src/syscall/syscall_unix.go b/src/syscall/syscall_unix.go index 56d3cad1d0..5ee938115d 100644 --- a/src/syscall/syscall_unix.go +++ b/src/syscall/syscall_unix.go @@ -378,7 +378,7 @@ func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) return sendmsgN(fd, p, oob, ptr, salen, flags) } -func sendmsgNInet4(fd int, p, oob []byte, to SockaddrInet4, flags int) (n int, err error) { +func sendmsgNInet4(fd int, p, oob []byte, to *SockaddrInet4, flags int) (n int, err error) { ptr, salen, err := to.sockaddr() if err != nil { return 0, err @@ -386,7 +386,7 @@ func sendmsgNInet4(fd int, p, oob []byte, to SockaddrInet4, flags int) (n int, e return sendmsgN(fd, p, oob, ptr, salen, flags) } -func sendmsgNInet6(fd int, p, oob []byte, to SockaddrInet6, flags int) (n int, err error) { +func sendmsgNInet6(fd int, p, oob []byte, to *SockaddrInet6, flags int) (n int, err error) { ptr, salen, err := to.sockaddr() if err != nil { return 0, err @@ -394,7 +394,7 @@ func sendmsgNInet6(fd int, p, oob []byte, to SockaddrInet6, flags int) (n int, e return sendmsgN(fd, p, oob, ptr, salen, flags) } -func sendtoInet4(fd int, p []byte, flags int, to SockaddrInet4) (err error) { +func sendtoInet4(fd int, p []byte, flags int, to *SockaddrInet4) (err error) { ptr, n, err := to.sockaddr() if err != nil { return err @@ -402,7 +402,7 @@ func sendtoInet4(fd int, p []byte, flags int, to SockaddrInet4) (err error) { return sendto(fd, p, flags, ptr, n) } -func sendtoInet6(fd int, p []byte, flags int, to SockaddrInet6) (err error) { +func sendtoInet6(fd int, p []byte, flags int, to *SockaddrInet6) (err error) { ptr, n, err := to.sockaddr() if err != nil { return err diff --git a/src/syscall/syscall_windows.go b/src/syscall/syscall_windows.go index 69e163e00f..ecb1eeecf6 100644 --- a/src/syscall/syscall_windows.go +++ b/src/syscall/syscall_windows.go @@ -922,7 +922,7 @@ func WSASendto(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32 return err } -func wsaSendtoInet4(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to SockaddrInet4, overlapped *Overlapped, croutine *byte) (err error) { +func wsaSendtoInet4(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *SockaddrInet4, overlapped *Overlapped, croutine *byte) (err error) { rsa, len, err := to.sockaddr() if err != nil { return err @@ -938,7 +938,7 @@ func wsaSendtoInet4(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags u return err } -func wsaSendtoInet6(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to SockaddrInet6, overlapped *Overlapped, croutine *byte) (err error) { +func wsaSendtoInet6(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *SockaddrInet6, overlapped *Overlapped, croutine *byte) (err error) { rsa, len, err := to.sockaddr() if err != nil { return err -- GitLab From 1e0c3b28777420e5af73f40d4cad691ad8c43513 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Thu, 4 Nov 2021 12:19:04 -0700 Subject: [PATCH 1974/2500] internal/poll: re-use RawSockaddrAny buffers across requests on windows We were re-allocating a new RawSockaddrAny on every UDP read/write. We can re-use them instead. This reduces the number of allocs for UDP read/write on windows to zero. Co-authored-by: David Crawshaw Change-Id: I2f05c974e2e7b4f67937ae4e1c99583e81d140af Reviewed-on: https://go-review.googlesource.com/c/go/+/361404 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/internal/poll/fd_windows.go | 59 +++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 21 deletions(-) diff --git a/src/internal/poll/fd_windows.go b/src/internal/poll/fd_windows.go index 94cdfca601..0d8bf87992 100644 --- a/src/internal/poll/fd_windows.go +++ b/src/internal/poll/fd_windows.go @@ -1116,25 +1116,27 @@ func (fd *FD) RawWrite(f func(uintptr) bool) error { return syscall.EWINDOWS } -func sockaddrInet4ToRaw(sa *syscall.SockaddrInet4) (unsafe.Pointer, int32) { - var raw syscall.RawSockaddrInet4 +func sockaddrInet4ToRaw(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet4) int32 { + *rsa = syscall.RawSockaddrAny{} + raw := (*syscall.RawSockaddrInet4)(unsafe.Pointer(rsa)) raw.Family = syscall.AF_INET p := (*[2]byte)(unsafe.Pointer(&raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) raw.Addr = sa.Addr - return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw)) + return int32(unsafe.Sizeof(*raw)) } -func sockaddrInet6ToRaw(sa *syscall.SockaddrInet6) (unsafe.Pointer, int32) { - var raw syscall.RawSockaddrInet6 +func sockaddrInet6ToRaw(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet6) int32 { + *rsa = syscall.RawSockaddrAny{} + raw := (*syscall.RawSockaddrInet6)(unsafe.Pointer(rsa)) raw.Family = syscall.AF_INET6 p := (*[2]byte)(unsafe.Pointer(&raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) raw.Scope_id = sa.ZoneId raw.Addr = sa.Addr - return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw)) + return int32(unsafe.Sizeof(*raw)) } func rawToSockaddrInet4(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet4) { @@ -1152,16 +1154,16 @@ func rawToSockaddrInet6(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet6) sa.Addr = pp.Addr } -func sockaddrToRaw(sa syscall.Sockaddr) (unsafe.Pointer, int32, error) { +func sockaddrToRaw(rsa *syscall.RawSockaddrAny, sa syscall.Sockaddr) (int32, error) { switch sa := sa.(type) { case *syscall.SockaddrInet4: - ptr, sz := sockaddrInet4ToRaw(sa) - return ptr, sz, nil + sz := sockaddrInet4ToRaw(rsa, sa) + return sz, nil case *syscall.SockaddrInet6: - ptr, sz := sockaddrInet6ToRaw(sa) - return ptr, sz, nil + sz := sockaddrInet6ToRaw(rsa, sa) + return sz, nil default: - return nil, 0, syscall.EWINDOWS + return 0, syscall.EWINDOWS } } @@ -1178,7 +1180,9 @@ func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.S o := &fd.rop o.InitMsg(p, oob) - o.rsa = new(syscall.RawSockaddrAny) + if o.rsa == nil { + o.rsa = new(syscall.RawSockaddrAny) + } o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa)) o.msg.Namelen = int32(unsafe.Sizeof(*o.rsa)) o.msg.Flags = uint32(flags) @@ -1206,7 +1210,9 @@ func (fd *FD) ReadMsgInet4(p []byte, oob []byte, flags int, sa4 *syscall.Sockadd o := &fd.rop o.InitMsg(p, oob) - o.rsa = new(syscall.RawSockaddrAny) + if o.rsa == nil { + o.rsa = new(syscall.RawSockaddrAny) + } o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa)) o.msg.Namelen = int32(unsafe.Sizeof(*o.rsa)) o.msg.Flags = uint32(flags) @@ -1233,7 +1239,9 @@ func (fd *FD) ReadMsgInet6(p []byte, oob []byte, flags int, sa6 *syscall.Sockadd o := &fd.rop o.InitMsg(p, oob) - o.rsa = new(syscall.RawSockaddrAny) + if o.rsa == nil { + o.rsa = new(syscall.RawSockaddrAny) + } o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa)) o.msg.Namelen = int32(unsafe.Sizeof(*o.rsa)) o.msg.Flags = uint32(flags) @@ -1261,11 +1269,14 @@ func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, err o := &fd.wop o.InitMsg(p, oob) if sa != nil { - rsa, len, err := sockaddrToRaw(sa) + if o.rsa == nil { + o.rsa = new(syscall.RawSockaddrAny) + } + len, err := sockaddrToRaw(o.rsa, sa) if err != nil { return 0, 0, err } - o.msg.Name = (syscall.Pointer)(rsa) + o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa)) o.msg.Namelen = len } n, err := execIO(o, func(o *operation) error { @@ -1287,8 +1298,11 @@ func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa *syscall.SockaddrInet4) (in o := &fd.wop o.InitMsg(p, oob) - rsa, len := sockaddrInet4ToRaw(sa) - o.msg.Name = (syscall.Pointer)(rsa) + if o.rsa == nil { + o.rsa = new(syscall.RawSockaddrAny) + } + len := sockaddrInet4ToRaw(o.rsa, sa) + o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa)) o.msg.Namelen = len n, err := execIO(o, func(o *operation) error { return windows.WSASendMsg(o.fd.Sysfd, &o.msg, 0, &o.qty, &o.o, nil) @@ -1309,8 +1323,11 @@ func (fd *FD) WriteMsgInet6(p []byte, oob []byte, sa *syscall.SockaddrInet6) (in o := &fd.wop o.InitMsg(p, oob) - rsa, len := sockaddrInet6ToRaw(sa) - o.msg.Name = (syscall.Pointer)(rsa) + if o.rsa == nil { + o.rsa = new(syscall.RawSockaddrAny) + } + len := sockaddrInet6ToRaw(o.rsa, sa) + o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa)) o.msg.Namelen = len n, err := execIO(o, func(o *operation) error { return windows.WSASendMsg(o.fd.Sysfd, &o.msg, 0, &o.qty, &o.o, nil) -- GitLab From 76c48e9346bba98689e059aaee5952c17d45a48c Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Thu, 4 Nov 2021 11:33:39 -0700 Subject: [PATCH 1975/2500] net: add UDP allocs test Change-Id: Ibefd1ca0236d17d57fc5aa5938a56ae92272ca60 Reviewed-on: https://go-review.googlesource.com/c/go/+/361396 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/net/udpsock_test.go | 53 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/net/udpsock_test.go b/src/net/udpsock_test.go index 7eef6f64af..518c66c331 100644 --- a/src/net/udpsock_test.go +++ b/src/net/udpsock_test.go @@ -474,6 +474,59 @@ func TestUDPReadTimeout(t *testing.T) { } } +func TestAllocs(t *testing.T) { + conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) + if err != nil { + t.Fatal(err) + } + defer conn.Close() + addr := conn.LocalAddr() + addrPort := addr.(*UDPAddr).AddrPort() + buf := make([]byte, 8) + + allocs := testing.AllocsPerRun(1000, func() { + _, _, err := conn.WriteMsgUDPAddrPort(buf, nil, addrPort) + if err != nil { + t.Fatal(err) + } + _, _, _, _, err = conn.ReadMsgUDPAddrPort(buf, nil) + if err != nil { + t.Fatal(err) + } + }) + if got := int(allocs); got != 0 { + t.Errorf("WriteMsgUDPAddrPort/ReadMsgUDPAddrPort allocated %d objects", got) + } + + allocs = testing.AllocsPerRun(1000, func() { + _, err := conn.WriteToUDPAddrPort(buf, addrPort) + if err != nil { + t.Fatal(err) + } + _, _, err = conn.ReadFromUDPAddrPort(buf) + if err != nil { + t.Fatal(err) + } + }) + if got := int(allocs); got != 0 { + t.Errorf("WriteToUDPAddrPort/ReadFromUDPAddrPort allocated %d objects", got) + } + + allocs = testing.AllocsPerRun(1000, func() { + _, err := conn.WriteTo(buf, addr) + if err != nil { + t.Fatal(err) + } + _, _, err = conn.ReadFromUDP(buf) + if err != nil { + t.Fatal(err) + } + }) + if got := int(allocs); got != 1 { + t.Errorf("WriteTo/ReadFromUDP allocated %d objects", got) + } +} + func BenchmarkReadWriteMsgUDPAddrPort(b *testing.B) { conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) if err != nil { -- GitLab From 256a8fc6ef297f2a2cec0cb7c918f61706b6f9a3 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Thu, 4 Nov 2021 23:13:12 +0000 Subject: [PATCH 1976/2500] sync/atomic: disable GC during TestHammerStoreLoad TestHammerStoreLoad involves a stress test of StorePointer, which has a write barrier. The "pointer" that is being written is not a real value, which is generally fine (though not *really* safe) on 64-bit systems because they never point to an actual object. On 32-bit systems, however, this is much more likely. Because I can't figure out how to rewrite the test such that it still is testing the same conditions but is also using real pointers, just disable the GC during the test, and make sure there isn't one currently in progress. Fixes #49362. Change-Id: If81883fedf06568132e6484f40c820aa69027a9c Reviewed-on: https://go-review.googlesource.com/c/go/+/361455 Trust: Michael Knyszek Run-TryBot: Michael Knyszek Reviewed-by: Ian Lance Taylor TryBot-Result: Go Bot --- src/sync/atomic/atomic_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/sync/atomic/atomic_test.go b/src/sync/atomic/atomic_test.go index eadc962f70..4b8c2a58f3 100644 --- a/src/sync/atomic/atomic_test.go +++ b/src/sync/atomic/atomic_test.go @@ -7,6 +7,7 @@ package atomic_test import ( "fmt" "runtime" + "runtime/debug" "strings" . "sync/atomic" "testing" @@ -1196,6 +1197,11 @@ func TestHammerStoreLoad(t *testing.T) { } const procs = 8 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(procs)) + // Disable the GC because hammerStoreLoadPointer invokes + // write barriers on values that aren't real pointers. + defer debug.SetGCPercent(debug.SetGCPercent(-1)) + // Ensure any in-progress GC is finished. + runtime.GC() for _, tt := range tests { c := make(chan int) var val uint64 -- GitLab From 0e5f287fde7b2cf11c8cffb7839f970a8f3e2f9b Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Fri, 5 Nov 2021 00:10:31 +0100 Subject: [PATCH 1977/2500] runtime: use correct constant when computing nsec remainder A code comment on amd64 for windows and plan9 contained a snippet for splitting apart the sec and nsec components of a unix timestamp, with produced assembly below, which was then cleaned up by hand. When arm64 was ported, that code snippet in the comment went through the compiler to produce some code that was then pasted and cleaned up. Unfortunately, the comment had a typo in it, containing 8 zeros instead of 9. This resulted in the constant used in the assembly being wrong, spotted by @bufflig's eagle eyes. So, this commit fixes the comment on all three platforms, and the assembly on windows/arm64. Fixes #48072. Change-Id: I786fe89147328b0d25544f52c927ddfdb9f6f1cf Reviewed-on: https://go-review.googlesource.com/c/go/+/361474 Trust: Jason A. Donenfeld Run-TryBot: Jason A. Donenfeld Reviewed-by: Patrik Nyblom TryBot-Result: Go Bot --- src/runtime/sys_plan9_amd64.s | 2 +- src/runtime/time_windows_amd64.s | 2 +- src/runtime/time_windows_arm64.s | 9 +++------ 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/runtime/sys_plan9_amd64.s b/src/runtime/sys_plan9_amd64.s index 39fc4c68e4..638300dfb9 100644 --- a/src/runtime/sys_plan9_amd64.s +++ b/src/runtime/sys_plan9_amd64.s @@ -94,7 +94,7 @@ TEXT runtime·walltime(SB),NOSPLIT,$8-12 MOVQ 0(SP), AX // generated code for - // func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 } + // func f(x uint64) (uint64, uint64) { return x/1000000000, x%1000000000 } // adapted to reduce duplication MOVQ AX, CX MOVQ $1360296554856532783, AX diff --git a/src/runtime/time_windows_amd64.s b/src/runtime/time_windows_amd64.s index 045f64eb46..70f6a008cd 100644 --- a/src/runtime/time_windows_amd64.s +++ b/src/runtime/time_windows_amd64.s @@ -25,7 +25,7 @@ TEXT time·now(SB),NOSPLIT,$0-24 IMULQ $100, AX // generated code for - // func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 } + // func f(x uint64) (uint64, uint64) { return x/1000000000, x%1000000000 } // adapted to reduce duplication MOVQ AX, CX MOVQ $1360296554856532783, AX diff --git a/src/runtime/time_windows_arm64.s b/src/runtime/time_windows_arm64.s index e8a0eb2f93..ef5b848473 100644 --- a/src/runtime/time_windows_arm64.s +++ b/src/runtime/time_windows_arm64.s @@ -32,17 +32,14 @@ TEXT time·now(SB),NOSPLIT|NOFRAME,$0-24 // Code stolen from compiler output for: // // var x uint64 - // func f() (sec uint64, nsec uint32) { return x / 1000000000, uint32(x % 100000000) } + // func f() (sec uint64, nsec uint32) { return x / 1000000000, uint32(x % 1000000000) } // LSR $1, R0, R1 MOVD $-8543223759426509416, R2 - UMULH R2, R1, R1 + UMULH R1, R2, R1 LSR $28, R1, R1 MOVD R1, sec+0(FP) - MOVD $-6067343680855748867, R1 - UMULH R0, R1, R1 - LSR $26, R1, R1 - MOVD $100000000, R2 + MOVD $1000000000, R2 MSUB R1, R0, R2, R0 MOVW R0, nsec+8(FP) RET -- GitLab From 1c4cfd80109da81a2c6cf49b4d3ff49c45af8e03 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 17 Sep 2021 10:07:41 -0400 Subject: [PATCH 1978/2500] cmd/compile,cmd/internal/objabi: move -d flag parser to objabi This moves and slightly generalizes the -d debug flag parser from cmd/compile/internal/base to cmd/internal/objabi so that we can use the same debug flag syntax in other tools. This makes a few minor tweaks to implementation details. The flag itself is now just a flag.Value that gets constructed explicitly, rather than at init time, and we've cleaned up the implementation a little (e.g., using a map instead of a linear search of a slice). The help text is now automatically alphabetized. Rather than describing the values of some flags in the help text footer, we simply include it in the flags' help text and make sure multi-line help text renders sensibly. For #48297. Change-Id: Id373ee3b767e456be483fb28c110d025149be532 Reviewed-on: https://go-review.googlesource.com/c/go/+/359956 Trust: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot Reviewed-by: David Chase Reviewed-by: Cherry Mui --- src/cmd/compile/internal/base/debug.go | 146 +--------------------- src/cmd/compile/internal/base/flag.go | 36 +++--- src/cmd/internal/objabi/flag.go | 164 +++++++++++++++++++++++++ 3 files changed, 187 insertions(+), 159 deletions(-) diff --git a/src/cmd/compile/internal/base/debug.go b/src/cmd/compile/internal/base/debug.go index e2245e1c26..37e345bd7f 100644 --- a/src/cmd/compile/internal/base/debug.go +++ b/src/cmd/compile/internal/base/debug.go @@ -6,15 +6,6 @@ package base -import ( - "fmt" - "log" - "os" - "reflect" - "strconv" - "strings" -) - // Debug holds the parsed debugging configuration values. var Debug DebugFlags @@ -26,7 +17,7 @@ var Debug DebugFlags // Each setting is name=value; for ints, name is short for name=1. type DebugFlags struct { Append int `help:"print information about append compilation"` - Checkptr int `help:"instrument unsafe pointer conversions"` + Checkptr int `help:"instrument unsafe pointer conversions\n0: instrumentation disabled\n1: conversions involving unsafe.Pointer are instrumented\n2: conversions to unsafe.Pointer force heap allocation"` Closure int `help:"print information about closure compilation"` DclStack int `help:"run internal dclstack check"` Defer int `help:"print information about defer compilation"` @@ -40,7 +31,7 @@ type DebugFlags struct { LocationLists int `help:"print information about DWARF location list creation"` Nil int `help:"print information about nil checks"` NoOpenDefer int `help:"disable open-coded defers"` - PCTab string `help:"print named pc-value table"` + PCTab string `help:"print named pc-value table\nOne of: pctospadj, pctofile, pctoline, pctoinline, pctopcdata"` Panic int `help:"show all compiler panics"` Slice int `help:"print information about slice compilation"` SoftFloat int `help:"force compiler to emit soft-float code"` @@ -52,141 +43,10 @@ type DebugFlags struct { WB int `help:"print information about write barriers"` ABIWrap int `help:"print information about ABI wrapper generation"` - any bool // set when any of the values have been set -} - -// Any reports whether any of the debug flags have been set. -func (d *DebugFlags) Any() bool { return d.any } - -type debugField struct { - name string - help string - val interface{} // *int or *string -} - -var debugTab []debugField - -func init() { - v := reflect.ValueOf(&Debug).Elem() - t := v.Type() - for i := 0; i < t.NumField(); i++ { - f := t.Field(i) - if f.Name == "any" { - continue - } - name := strings.ToLower(f.Name) - help := f.Tag.Get("help") - if help == "" { - panic(fmt.Sprintf("base.Debug.%s is missing help text", f.Name)) - } - ptr := v.Field(i).Addr().Interface() - switch ptr.(type) { - default: - panic(fmt.Sprintf("base.Debug.%s has invalid type %v (must be int or string)", f.Name, f.Type)) - case *int, *string: - // ok - } - debugTab = append(debugTab, debugField{name, help, ptr}) - } + Any bool // set when any of the debug flags have been set } // DebugSSA is called to set a -d ssa/... option. // If nil, those options are reported as invalid options. // If DebugSSA returns a non-empty string, that text is reported as a compiler error. var DebugSSA func(phase, flag string, val int, valString string) string - -// parseDebug parses the -d debug string argument. -func parseDebug(debugstr string) { - // parse -d argument - if debugstr == "" { - return - } - Debug.any = true -Split: - for _, name := range strings.Split(debugstr, ",") { - if name == "" { - continue - } - // display help about the -d option itself and quit - if name == "help" { - fmt.Print(debugHelpHeader) - maxLen := len("ssa/help") - for _, t := range debugTab { - if len(t.name) > maxLen { - maxLen = len(t.name) - } - } - for _, t := range debugTab { - fmt.Printf("\t%-*s\t%s\n", maxLen, t.name, t.help) - } - // ssa options have their own help - fmt.Printf("\t%-*s\t%s\n", maxLen, "ssa/help", "print help about SSA debugging") - fmt.Print(debugHelpFooter) - os.Exit(0) - } - val, valstring, haveInt := 1, "", true - if i := strings.IndexAny(name, "=:"); i >= 0 { - var err error - name, valstring = name[:i], name[i+1:] - val, err = strconv.Atoi(valstring) - if err != nil { - val, haveInt = 1, false - } - } - for _, t := range debugTab { - if t.name != name { - continue - } - switch vp := t.val.(type) { - case nil: - // Ignore - case *string: - *vp = valstring - case *int: - if !haveInt { - log.Fatalf("invalid debug value %v", name) - } - *vp = val - default: - panic("bad debugtab type") - } - continue Split - } - // special case for ssa for now - if DebugSSA != nil && strings.HasPrefix(name, "ssa/") { - // expect form ssa/phase/flag - // e.g. -d=ssa/generic_cse/time - // _ in phase name also matches space - phase := name[4:] - flag := "debug" // default flag is debug - if i := strings.Index(phase, "/"); i >= 0 { - flag = phase[i+1:] - phase = phase[:i] - } - err := DebugSSA(phase, flag, val, valstring) - if err != "" { - log.Fatalf(err) - } - continue Split - } - log.Fatalf("unknown debug key -d %s\n", name) - } -} - -const debugHelpHeader = `usage: -d arg[,arg]* and arg is [=] - - is one of: - -` - -const debugHelpFooter = ` - is key-specific. - -Key "checkptr" supports values: - "0": instrumentation disabled - "1": conversions involving unsafe.Pointer are instrumented - "2": conversions to unsafe.Pointer force heap allocation - -Key "pctab" supports values: - "pctospadj", "pctofile", "pctoline", "pctoinline", "pctopcdata" -` diff --git a/src/cmd/compile/internal/base/flag.go b/src/cmd/compile/internal/base/flag.go index 9d630ce97a..f38eaa91c0 100644 --- a/src/cmd/compile/internal/base/flag.go +++ b/src/cmd/compile/internal/base/flag.go @@ -64,19 +64,19 @@ type CmdFlags struct { // V is added by objabi.AddVersionFlag W CountFlag "help:\"debug parse tree after type checking\"" - LowerC int "help:\"concurrency during compilation (1 means no concurrency)\"" - LowerD func(string) "help:\"enable debugging settings; try -d help\"" - LowerE CountFlag "help:\"no limit on number of errors reported\"" - LowerH CountFlag "help:\"halt on error\"" - LowerJ CountFlag "help:\"debug runtime-initialized variables\"" - LowerL CountFlag "help:\"disable inlining\"" - LowerM CountFlag "help:\"print optimization decisions\"" - LowerO string "help:\"write output to `file`\"" - LowerP *string "help:\"set expected package import `path`\"" // &Ctxt.Pkgpath, set below - LowerR CountFlag "help:\"debug generated wrappers\"" - LowerT bool "help:\"enable tracing for debugging the compiler\"" - LowerW CountFlag "help:\"debug type checking\"" - LowerV *bool "help:\"increase debug verbosity\"" + LowerC int "help:\"concurrency during compilation (1 means no concurrency)\"" + LowerD flag.Value "help:\"enable debugging settings; try -d help\"" + LowerE CountFlag "help:\"no limit on number of errors reported\"" + LowerH CountFlag "help:\"halt on error\"" + LowerJ CountFlag "help:\"debug runtime-initialized variables\"" + LowerL CountFlag "help:\"disable inlining\"" + LowerM CountFlag "help:\"print optimization decisions\"" + LowerO string "help:\"write output to `file`\"" + LowerP *string "help:\"set expected package import `path`\"" // &Ctxt.Pkgpath, set below + LowerR CountFlag "help:\"debug generated wrappers\"" + LowerT bool "help:\"enable tracing for debugging the compiler\"" + LowerW CountFlag "help:\"debug type checking\"" + LowerV *bool "help:\"increase debug verbosity\"" // Special characters Percent int "flag:\"%\" help:\"debug non-static initializers\"" @@ -145,7 +145,7 @@ func ParseFlags() { Flag.I = addImportDir Flag.LowerC = 1 - Flag.LowerD = parseDebug + Flag.LowerD = objabi.NewDebugFlag(&Debug, DebugSSA) Flag.LowerP = &Ctxt.Pkgpath Flag.LowerV = &Ctxt.Debugvlog @@ -331,7 +331,11 @@ func registerFlags() { f := v.Field(i).Interface().(func(string)) objabi.Flagfn1(name, help, f) default: - panic(fmt.Sprintf("base.Flag.%s has unexpected type %s", f.Name, f.Type)) + if val, ok := v.Field(i).Interface().(flag.Value); ok { + flag.Var(val, name, help) + } else { + panic(fmt.Sprintf("base.Flag.%s has unexpected type %s", f.Name, f.Type)) + } } } } @@ -359,7 +363,7 @@ func concurrentBackendAllowed() bool { // while writing the object file, and that is non-concurrent. // Adding Debug_vlog, however, causes Debug.S to also print // while flushing the plist, which happens concurrently. - if Ctxt.Debugvlog || Debug.Any() || Flag.Live > 0 { + if Ctxt.Debugvlog || Debug.Any || Flag.Live > 0 { return false } // TODO: Test and delete this condition. diff --git a/src/cmd/internal/objabi/flag.go b/src/cmd/internal/objabi/flag.go index e41fc570b0..f75c054fcb 100644 --- a/src/cmd/internal/objabi/flag.go +++ b/src/cmd/internal/objabi/flag.go @@ -13,6 +13,8 @@ import ( "io/ioutil" "log" "os" + "reflect" + "sort" "strconv" "strings" ) @@ -202,3 +204,165 @@ func DecodeArg(arg string) string { } return b.String() } + +type debugField struct { + name string + help string + val interface{} // *int or *string +} + +type DebugFlag struct { + tab map[string]debugField + any *bool + + debugSSA DebugSSA +} + +// A DebugSSA function is called to set a -d ssa/... option. +// If nil, those options are reported as invalid options. +// If DebugSSA returns a non-empty string, that text is reported as a compiler error. +// If phase is "help", it should print usage information and terminate the process. +type DebugSSA func(phase, flag string, val int, valString string) string + +// NewDebugFlag constructs a DebugFlag for the fields of debug, which +// must be a pointer to a struct. +// +// Each field of *debug is a different value, named for the lower-case of the field name. +// Each field must be an int or string and must have a `help` struct tag. +// There may be an "Any bool" field, which will be set if any debug flags are set. +// +// The returned flag takes a comma-separated list of settings. +// Each setting is name=value; for ints, name is short for name=1. +// +// If debugSSA is non-nil, any debug flags of the form ssa/... will be +// passed to debugSSA for processing. +func NewDebugFlag(debug interface{}, debugSSA DebugSSA) *DebugFlag { + flag := &DebugFlag{ + tab: make(map[string]debugField), + debugSSA: debugSSA, + } + + v := reflect.ValueOf(debug).Elem() + t := v.Type() + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + ptr := v.Field(i).Addr().Interface() + if f.Name == "Any" { + switch ptr := ptr.(type) { + default: + panic("debug.Any must have type bool") + case *bool: + flag.any = ptr + } + continue + } + name := strings.ToLower(f.Name) + help := f.Tag.Get("help") + if help == "" { + panic(fmt.Sprintf("debug.%s is missing help text", f.Name)) + } + switch ptr.(type) { + default: + panic(fmt.Sprintf("debug.%s has invalid type %v (must be int or string)", f.Name, f.Type)) + case *int, *string: + // ok + } + flag.tab[name] = debugField{name, help, ptr} + } + + return flag +} + +func (f *DebugFlag) Set(debugstr string) error { + if debugstr == "" { + return nil + } + if f.any != nil { + *f.any = true + } + for _, name := range strings.Split(debugstr, ",") { + if name == "" { + continue + } + // display help about the debug option itself and quit + if name == "help" { + fmt.Print(debugHelpHeader) + maxLen, names := 0, []string{} + if f.debugSSA != nil { + maxLen = len("ssa/help") + } + for name := range f.tab { + if len(name) > maxLen { + maxLen = len(name) + } + names = append(names, name) + } + sort.Strings(names) + // Indent multi-line help messages. + nl := fmt.Sprintf("\n\t%-*s\t", maxLen, "") + for _, name := range names { + help := f.tab[name].help + fmt.Printf("\t%-*s\t%s\n", maxLen, name, strings.Replace(help, "\n", nl, -1)) + } + if f.debugSSA != nil { + // ssa options have their own help + fmt.Printf("\t%-*s\t%s\n", maxLen, "ssa/help", "print help about SSA debugging") + } + os.Exit(0) + } + + val, valstring, haveInt := 1, "", true + if i := strings.IndexAny(name, "=:"); i >= 0 { + var err error + name, valstring = name[:i], name[i+1:] + val, err = strconv.Atoi(valstring) + if err != nil { + val, haveInt = 1, false + } + } + + if t, ok := f.tab[name]; ok { + switch vp := t.val.(type) { + case nil: + // Ignore + case *string: + *vp = valstring + case *int: + if !haveInt { + log.Fatalf("invalid debug value %v", name) + } + *vp = val + default: + panic("bad debugtab type") + } + } else if f.debugSSA != nil && strings.HasPrefix(name, "ssa/") { + // expect form ssa/phase/flag + // e.g. -d=ssa/generic_cse/time + // _ in phase name also matches space + phase := name[4:] + flag := "debug" // default flag is debug + if i := strings.Index(phase, "/"); i >= 0 { + flag = phase[i+1:] + phase = phase[:i] + } + err := f.debugSSA(phase, flag, val, valstring) + if err != "" { + log.Fatalf(err) + } + } else { + return fmt.Errorf("unknown debug key %s\n", name) + } + } + + return nil +} + +const debugHelpHeader = `usage: -d arg[,arg]* and arg is [=] + + is one of: + +` + +func (f *DebugFlag) String() string { + return "" +} -- GitLab From 3839b6001470f7bc73c9a80f6458f7111ae3d9cc Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 20 Aug 2019 17:39:09 -0400 Subject: [PATCH 1979/2500] cmd/{asm,compile,internal/obj}: add "maymorestack" support This adds a debugging hook for optionally calling a "maymorestack" function in the prologue of any function that might call morestack (whether it does at run time or not). The maymorestack function will let us improve lock checking and add debugging modes that stress function preemption and stack growth. Passes toolstash-check -all (except on js/wasm, where toolstash appears to be broken) Fixes #48297. Change-Id: I27197947482b329af75dafb9971fc0d3a52eaf31 Reviewed-on: https://go-review.googlesource.com/c/go/+/359795 Trust: Austin Clements Run-TryBot: Austin Clements Reviewed-by: Cherry Mui --- src/cmd/asm/internal/flags/flags.go | 5 ++ src/cmd/asm/main.go | 1 + src/cmd/compile/internal/base/debug.go | 1 + src/cmd/compile/internal/base/flag.go | 1 + src/cmd/internal/obj/arm/obj5.go | 57 ++++++++++++++- src/cmd/internal/obj/arm64/obj7.go | 87 ++++++++++++++++++++++- src/cmd/internal/obj/link.go | 3 +- src/cmd/internal/obj/mips/obj0.go | 79 ++++++++++++++++++++- src/cmd/internal/obj/ppc64/obj9.go | 93 +++++++++++++++++++++++- src/cmd/internal/obj/riscv/obj.go | 58 ++++++++++++++- src/cmd/internal/obj/s390x/objz.go | 81 ++++++++++++++++++--- src/cmd/internal/obj/wasm/wasmobj.go | 56 ++++++++++++++- src/cmd/internal/obj/x86/obj6.go | 97 +++++++++++++++++++------- test/maymorestack.go | 47 +++++++++++++ 14 files changed, 620 insertions(+), 46 deletions(-) create mode 100644 test/maymorestack.go diff --git a/src/cmd/asm/internal/flags/flags.go b/src/cmd/asm/internal/flags/flags.go index dd947c7b5b..607166e664 100644 --- a/src/cmd/asm/internal/flags/flags.go +++ b/src/cmd/asm/internal/flags/flags.go @@ -28,6 +28,10 @@ var ( CompilingRuntime = flag.Bool("compiling-runtime", false, "source to be compiled is part of the Go runtime") ) +var DebugFlags struct { + MayMoreStack string `help:"call named function before all stack growth checks"` +} + var ( D MultiFlag I MultiFlag @@ -39,6 +43,7 @@ func init() { flag.Var(&D, "D", "predefined symbol with optional simple value -D=identifier=value; can be set multiple times") flag.Var(&I, "I", "include directory; can be set multiple times") flag.BoolVar(&DebugV, "v", false, "print debug output") + flag.Var(objabi.NewDebugFlag(&DebugFlags, nil), "d", "enable debugging settings; try -d help") objabi.AddVersionFlag() // -V objabi.Flagcount("S", "print assembly and machine code", &PrintOut) } diff --git a/src/cmd/asm/main.go b/src/cmd/asm/main.go index 3e32aa3d7d..3683527f5b 100644 --- a/src/cmd/asm/main.go +++ b/src/cmd/asm/main.go @@ -42,6 +42,7 @@ func main() { ctxt.Flag_dynlink = *flags.Dynlink ctxt.Flag_linkshared = *flags.Linkshared ctxt.Flag_shared = *flags.Shared || *flags.Dynlink + ctxt.Flag_maymorestack = flags.DebugFlags.MayMoreStack ctxt.IsAsm = true ctxt.Pkgpath = *flags.Importpath switch *flags.Spectre { diff --git a/src/cmd/compile/internal/base/debug.go b/src/cmd/compile/internal/base/debug.go index 37e345bd7f..b105e46e35 100644 --- a/src/cmd/compile/internal/base/debug.go +++ b/src/cmd/compile/internal/base/debug.go @@ -42,6 +42,7 @@ type DebugFlags struct { UnifiedQuirks int `help:"enable unified IR construction's quirks mode"` WB int `help:"print information about write barriers"` ABIWrap int `help:"print information about ABI wrapper generation"` + MayMoreStack string `help:"call named function before all stack growth checks"` Any bool // set when any of the debug flags have been set } diff --git a/src/cmd/compile/internal/base/flag.go b/src/cmd/compile/internal/base/flag.go index f38eaa91c0..d78f93b343 100644 --- a/src/cmd/compile/internal/base/flag.go +++ b/src/cmd/compile/internal/base/flag.go @@ -192,6 +192,7 @@ func ParseFlags() { Ctxt.Flag_shared = Ctxt.Flag_dynlink || Ctxt.Flag_shared Ctxt.Flag_optimize = Flag.N == 0 Ctxt.Debugasm = int(Flag.S) + Ctxt.Flag_maymorestack = Debug.MayMoreStack if flag.NArg() < 1 { usage() diff --git a/src/cmd/internal/obj/arm/obj5.go b/src/cmd/internal/obj/arm/obj5.go index 1454d8a7c9..38aa11cde9 100644 --- a/src/cmd/internal/obj/arm/obj5.go +++ b/src/cmd/internal/obj/arm/obj5.go @@ -634,6 +634,61 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { } func (c *ctxt5) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { + if c.ctxt.Flag_maymorestack != "" { + // Save LR and make room for REGCTXT. + const frameSize = 8 + // MOVW.W R14,$-8(SP) + p = obj.Appendp(p, c.newprog) + p.As = AMOVW + p.Scond |= C_WBIT + p.From.Type = obj.TYPE_REG + p.From.Reg = REGLINK + p.To.Type = obj.TYPE_MEM + p.To.Offset = -frameSize + p.To.Reg = REGSP + p.Spadj = frameSize + + // MOVW REGCTXT, 4(SP) + p = obj.Appendp(p, c.newprog) + p.As = AMOVW + p.From.Type = obj.TYPE_REG + p.From.Reg = REGCTXT + p.To.Type = obj.TYPE_MEM + p.To.Offset = 4 + p.To.Reg = REGSP + + // CALL maymorestack + p = obj.Appendp(p, c.newprog) + p.As = obj.ACALL + p.To.Type = obj.TYPE_BRANCH + // See ../x86/obj6.go + p.To.Sym = c.ctxt.LookupABI(c.ctxt.Flag_maymorestack, c.cursym.ABI()) + + // Restore REGCTXT and LR. + + // MOVW 4(SP), REGCTXT + p = obj.Appendp(p, c.newprog) + p.As = AMOVW + p.From.Type = obj.TYPE_MEM + p.From.Offset = 4 + p.From.Reg = REGSP + p.To.Type = obj.TYPE_REG + p.To.Reg = REGCTXT + + // MOVW.P 8(SP), R14 + p.As = AMOVW + p.Scond |= C_PBIT + p.From.Type = obj.TYPE_MEM + p.From.Offset = frameSize + p.From.Reg = REGSP + p.To.Type = obj.TYPE_REG + p.To.Reg = REGLINK + p.Spadj = -frameSize + } + + // Jump back to here after morestack returns. + startPred := p + // MOVW g_stackguard(g), R1 p = obj.Appendp(p, c.newprog) @@ -761,7 +816,7 @@ func (c *ctxt5) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { b := obj.Appendp(pcdata, c.newprog) b.As = obj.AJMP b.To.Type = obj.TYPE_BRANCH - b.To.SetTarget(c.cursym.Func().Text.Link) + b.To.SetTarget(startPred.Link) b.Spadj = +framesize return end diff --git a/src/cmd/internal/obj/arm64/obj7.go b/src/cmd/internal/obj/arm64/obj7.go index ae8deede3a..e9eb786cb2 100644 --- a/src/cmd/internal/obj/arm64/obj7.go +++ b/src/cmd/internal/obj/arm64/obj7.go @@ -58,6 +58,91 @@ var noZRreplace = map[obj.As]bool{ } func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { + if c.ctxt.Flag_maymorestack != "" { + p = c.cursym.Func().SpillRegisterArgs(p, c.newprog) + + // Save LR and make room for FP, REGCTXT. Leave room + // for caller's saved FP. + const frameSize = 32 + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From.Type = obj.TYPE_REG + p.From.Reg = REGLINK + p.To.Type = obj.TYPE_MEM + p.Scond = C_XPRE + p.To.Offset = -frameSize + p.To.Reg = REGSP + p.Spadj = frameSize + + // Save FP. + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From.Type = obj.TYPE_REG + p.From.Reg = REGFP + p.To.Type = obj.TYPE_MEM + p.To.Reg = REGSP + p.To.Offset = -8 + + p = obj.Appendp(p, c.newprog) + p.As = ASUB + p.From.Type = obj.TYPE_CONST + p.From.Offset = 8 + p.Reg = REGSP + p.To.Type = obj.TYPE_REG + p.To.Reg = REGFP + + // Save REGCTXT (for simplicity we do this whether or + // not we need it.) + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From.Type = obj.TYPE_REG + p.From.Reg = REGCTXT + p.To.Type = obj.TYPE_MEM + p.To.Reg = REGSP + p.To.Offset = 8 + + // BL maymorestack + p = obj.Appendp(p, c.newprog) + p.As = ABL + p.To.Type = obj.TYPE_BRANCH + // See ../x86/obj6.go + p.To.Sym = c.ctxt.LookupABI(c.ctxt.Flag_maymorestack, c.cursym.ABI()) + + // Restore REGCTXT. + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From.Type = obj.TYPE_MEM + p.From.Reg = REGSP + p.From.Offset = 8 + p.To.Type = obj.TYPE_REG + p.To.Reg = REGCTXT + + // Restore FP. + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From.Type = obj.TYPE_MEM + p.From.Reg = REGSP + p.From.Offset = -8 + p.To.Type = obj.TYPE_REG + p.To.Reg = REGFP + + // Restore LR and SP. + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From.Type = obj.TYPE_MEM + p.Scond = C_XPOST + p.From.Offset = frameSize + p.From.Reg = REGSP + p.To.Type = obj.TYPE_REG + p.To.Reg = REGLINK + p.Spadj = -frameSize + + p = c.cursym.Func().UnspillRegisterArgs(p, c.newprog) + } + + // Jump back to here after morestack returns. + startPred := p + // MOV g_stackguard(g), RT1 p = obj.Appendp(p, c.newprog) @@ -212,7 +297,7 @@ func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { jmp := obj.Appendp(pcdata, c.newprog) jmp.As = AB jmp.To.Type = obj.TYPE_BRANCH - jmp.To.SetTarget(c.cursym.Func().Text.Link) + jmp.To.SetTarget(startPred.Link) jmp.Spadj = +framesize return end diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index 4bcfb05a5e..11af143f22 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -880,7 +880,8 @@ type Link struct { Flag_linkshared bool Flag_optimize bool Flag_locationlists bool - Retpoline bool // emit use of retpoline stubs for indirect jmp/call + Retpoline bool // emit use of retpoline stubs for indirect jmp/call + Flag_maymorestack string // If not "", call this function before stack checks Bso *bufio.Writer Pathname string Pkgpath string // the current package's import path, "" if unknown diff --git a/src/cmd/internal/obj/mips/obj0.go b/src/cmd/internal/obj/mips/obj0.go index 1f31d0c4cd..9e2ccc1929 100644 --- a/src/cmd/internal/obj/mips/obj0.go +++ b/src/cmd/internal/obj/mips/obj0.go @@ -658,6 +658,82 @@ func (c *ctxt0) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { mov = AMOVW } + if c.ctxt.Flag_maymorestack != "" { + // Save LR and REGCTXT. + frameSize := 2 * c.ctxt.Arch.PtrSize + + p = c.ctxt.StartUnsafePoint(p, c.newprog) + + // MOV REGLINK, -8/-16(SP) + p = obj.Appendp(p, c.newprog) + p.As = mov + p.From.Type = obj.TYPE_REG + p.From.Reg = REGLINK + p.To.Type = obj.TYPE_MEM + p.To.Offset = int64(-frameSize) + p.To.Reg = REGSP + + // MOV REGCTXT, -4/-8(SP) + p = obj.Appendp(p, c.newprog) + p.As = mov + p.From.Type = obj.TYPE_REG + p.From.Reg = REGCTXT + p.To.Type = obj.TYPE_MEM + p.To.Offset = -int64(c.ctxt.Arch.PtrSize) + p.To.Reg = REGSP + + // ADD $-8/$-16, SP + p = obj.Appendp(p, c.newprog) + p.As = add + p.From.Type = obj.TYPE_CONST + p.From.Offset = int64(-frameSize) + p.To.Type = obj.TYPE_REG + p.To.Reg = REGSP + p.Spadj = int32(frameSize) + + // JAL maymorestack + p = obj.Appendp(p, c.newprog) + p.As = AJAL + p.To.Type = obj.TYPE_BRANCH + // See ../x86/obj6.go + p.To.Sym = c.ctxt.LookupABI(c.ctxt.Flag_maymorestack, c.cursym.ABI()) + p.Mark |= BRANCH + + // Restore LR and REGCTXT. + + // MOV 0(SP), REGLINK + p = obj.Appendp(p, c.newprog) + p.As = mov + p.From.Type = obj.TYPE_MEM + p.From.Offset = 0 + p.From.Reg = REGSP + p.To.Type = obj.TYPE_REG + p.To.Reg = REGLINK + + // MOV 4/8(SP), REGCTXT + p = obj.Appendp(p, c.newprog) + p.As = mov + p.From.Type = obj.TYPE_MEM + p.From.Offset = int64(c.ctxt.Arch.PtrSize) + p.From.Reg = REGSP + p.To.Type = obj.TYPE_REG + p.To.Reg = REGCTXT + + // ADD $8/$16, SP + p = obj.Appendp(p, c.newprog) + p.As = add + p.From.Type = obj.TYPE_CONST + p.From.Offset = int64(frameSize) + p.To.Type = obj.TYPE_REG + p.To.Reg = REGSP + p.Spadj = int32(-frameSize) + + p = c.ctxt.EndUnsafePoint(p, c.newprog, -1) + } + + // Jump back to here after morestack returns. + startPred := p + // MOV g_stackguard(g), R1 p = obj.Appendp(p, c.newprog) @@ -787,7 +863,8 @@ func (c *ctxt0) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { p.As = AJMP p.To.Type = obj.TYPE_BRANCH - p.To.SetTarget(c.cursym.Func().Text.Link) + p.To.SetTarget(startPred.Link) + startPred.Link.Mark |= LABEL p.Mark |= BRANCH // placeholder for q1's jump target diff --git a/src/cmd/internal/obj/ppc64/obj9.go b/src/cmd/internal/obj/ppc64/obj9.go index ee93fe048b..7ac6465a72 100644 --- a/src/cmd/internal/obj/ppc64/obj9.go +++ b/src/cmd/internal/obj/ppc64/obj9.go @@ -1048,7 +1048,96 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { } */ func (c *ctxt9) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { - p0 := p // save entry point, but skipping the two instructions setting R2 in shared mode + if c.ctxt.Flag_maymorestack != "" { + if c.ctxt.Flag_shared || c.ctxt.Flag_dynlink { + // See the call to morestack for why these are + // complicated to support. + c.ctxt.Diag("maymorestack with -shared or -dynlink is not supported") + } + + // Spill arguments. This has to happen before we open + // any more frame space. + p = c.cursym.Func().SpillRegisterArgs(p, c.newprog) + + // Save LR and REGCTXT + frameSize := 8 + c.ctxt.FixedFrameSize() + + // MOVD LR, REGTMP + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From.Type = obj.TYPE_REG + p.From.Reg = REG_LR + p.To.Type = obj.TYPE_REG + p.To.Reg = REGTMP + // MOVDU REGTMP, -16(SP) + p = obj.Appendp(p, c.newprog) + p.As = AMOVDU + p.From.Type = obj.TYPE_REG + p.From.Reg = REGTMP + p.To.Type = obj.TYPE_MEM + p.To.Offset = -frameSize + p.To.Reg = REGSP + p.Spadj = int32(frameSize) + + // MOVD REGCTXT, 8(SP) + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From.Type = obj.TYPE_REG + p.From.Reg = REGCTXT + p.To.Type = obj.TYPE_MEM + p.To.Offset = 8 + p.To.Reg = REGSP + + // BL maymorestack + p = obj.Appendp(p, c.newprog) + p.As = ABL + p.To.Type = obj.TYPE_BRANCH + // See ../x86/obj6.go + p.To.Sym = c.ctxt.LookupABI(c.ctxt.Flag_maymorestack, c.cursym.ABI()) + + // Restore LR and REGCTXT + + // MOVD 8(SP), REGCTXT + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From.Type = obj.TYPE_MEM + p.From.Offset = 8 + p.From.Reg = REGSP + p.To.Type = obj.TYPE_REG + p.To.Reg = REGCTXT + + // MOVD 0(SP), REGTMP + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From.Type = obj.TYPE_MEM + p.From.Offset = 0 + p.From.Reg = REGSP + p.To.Type = obj.TYPE_REG + p.To.Reg = REGTMP + + // MOVD REGTMP, LR + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From.Type = obj.TYPE_REG + p.From.Reg = REGTMP + p.To.Type = obj.TYPE_REG + p.To.Reg = REG_LR + + // ADD $16, SP + p = obj.Appendp(p, c.newprog) + p.As = AADD + p.From.Type = obj.TYPE_CONST + p.From.Offset = frameSize + p.To.Type = obj.TYPE_REG + p.To.Reg = REGSP + p.Spadj = -int32(frameSize) + + // Unspill arguments. + p = c.cursym.Func().UnspillRegisterArgs(p, c.newprog) + } + + // save entry point, but skipping the two instructions setting R2 in shared mode and maymorestack + startPred := p // MOVD g_stackguard(g), R22 p = obj.Appendp(p, c.newprog) @@ -1262,7 +1351,7 @@ func (c *ctxt9) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { p = obj.Appendp(p, c.newprog) p.As = ABR p.To.Type = obj.TYPE_BRANCH - p.To.SetTarget(p0.Link) + p.To.SetTarget(startPred.Link) // placeholder for q1's jump target p = obj.Appendp(p, c.newprog) diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index c27ad99b2d..5755b118db 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -722,6 +722,62 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, cursym *obj.LSym, newprog obj.ProgA return p } + if ctxt.Flag_maymorestack != "" { + // Save LR and REGCTXT + const frameSize = 16 + p = ctxt.StartUnsafePoint(p, newprog) + // MOV LR, -16(SP) + p = obj.Appendp(p, newprog) + p.As = AMOV + p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR} + p.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: -frameSize} + // ADDI $-16, SP + p = obj.Appendp(p, newprog) + p.As = AADDI + p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: -frameSize} + p.Reg = REG_SP + p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP} + p.Spadj = frameSize + // MOV REGCTXT, 8(SP) + p = obj.Appendp(p, newprog) + p.As = AMOV + p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_CTXT} + p.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 8} + + // CALL maymorestack + p = obj.Appendp(p, newprog) + p.As = obj.ACALL + p.To.Type = obj.TYPE_BRANCH + // See ../x86/obj6.go + p.To.Sym = ctxt.LookupABI(ctxt.Flag_maymorestack, cursym.ABI()) + jalToSym(ctxt, p, REG_X5) + + // Restore LR and REGCTXT + + // MOV 8(SP), REGCTXT + p = obj.Appendp(p, newprog) + p.As = AMOV + p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 8} + p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_CTXT} + // MOV (SP), LR + p = obj.Appendp(p, newprog) + p.As = AMOV + p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 0} + p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR} + // ADDI $16, SP + p = obj.Appendp(p, newprog) + p.As = AADDI + p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: frameSize} + p.Reg = REG_SP + p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP} + p.Spadj = -frameSize + + p = ctxt.EndUnsafePoint(p, newprog, -1) + } + + // Jump back to here after morestack returns. + startPred := p + // MOV g_stackguard(g), X10 p = obj.Appendp(p, newprog) p.As = AMOV @@ -821,7 +877,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, cursym *obj.LSym, newprog obj.ProgA p.As = AJAL p.To = obj.Addr{Type: obj.TYPE_BRANCH} p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO} - p.To.SetTarget(cursym.Func().Text.Link) + p.To.SetTarget(startPred.Link) // placeholder for to_done's jump target p = obj.Appendp(p, newprog) diff --git a/src/cmd/internal/obj/s390x/objz.go b/src/cmd/internal/obj/s390x/objz.go index 201163b015..de40ff05af 100644 --- a/src/cmd/internal/obj/s390x/objz.go +++ b/src/cmd/internal/obj/s390x/objz.go @@ -294,6 +294,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { var pLast *obj.Prog var pPre *obj.Prog var pPreempt *obj.Prog + var pCheck *obj.Prog wasSplit := false for p := c.cursym.Func().Text; p != nil; p = p.Link { pLast = p @@ -323,7 +324,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { q := p if !p.From.Sym.NoSplit() { - p, pPreempt = c.stacksplitPre(p, autosize) // emit pre part of split check + p, pPreempt, pCheck = c.stacksplitPre(p, autosize) // emit pre part of split check pPre = p p = c.ctxt.EndUnsafePoint(p, c.newprog, -1) wasSplit = true //need post part of split @@ -563,14 +564,69 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { } } if wasSplit { - c.stacksplitPost(pLast, pPre, pPreempt, autosize) // emit post part of split check + c.stacksplitPost(pLast, pPre, pPreempt, pCheck, autosize) // emit post part of split check } } -func (c *ctxtz) stacksplitPre(p *obj.Prog, framesize int32) (*obj.Prog, *obj.Prog) { +// stacksplitPre generates the function stack check prologue following +// Prog p (which should be the TEXT Prog). It returns one or two +// branch Progs that must be patched to jump to the morestack epilogue, +// and the Prog that starts the morestack check. +func (c *ctxtz) stacksplitPre(p *obj.Prog, framesize int32) (pPre, pPreempt, pCheck *obj.Prog) { + if c.ctxt.Flag_maymorestack != "" { + // Save LR and REGCTXT + const frameSize = 16 + p = c.ctxt.StartUnsafePoint(p, c.newprog) + // MOVD LR, -16(SP) + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR} + p.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REGSP, Offset: -frameSize} + // MOVD $-16(SP), SP + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From = obj.Addr{Type: obj.TYPE_ADDR, Offset: -frameSize, Reg: REGSP} + p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REGSP} + p.Spadj = frameSize + // MOVD REGCTXT, 8(SP) + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REGCTXT} + p.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REGSP, Offset: 8} + + // BL maymorestack + p = obj.Appendp(p, c.newprog) + p.As = ABL + // See ../x86/obj6.go + sym := c.ctxt.LookupABI(c.ctxt.Flag_maymorestack, c.cursym.ABI()) + p.To = obj.Addr{Type: obj.TYPE_BRANCH, Sym: sym} + + // Restore LR and REGCTXT + + // MOVD REGCTXT, 8(SP) + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REGSP, Offset: 8} + p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REGCTXT} + // MOVD (SP), LR + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REGSP, Offset: 0} + p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR} + // MOVD $16(SP), SP + p = obj.Appendp(p, c.newprog) + p.As = AMOVD + p.From = obj.Addr{Type: obj.TYPE_CONST, Reg: REGSP, Offset: frameSize} + p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REGSP} + p.Spadj = -frameSize + + p = c.ctxt.EndUnsafePoint(p, c.newprog, -1) + } // MOVD g_stackguard(g), R3 p = obj.Appendp(p, c.newprog) + // Jump back to here after morestack returns. + pCheck = p p.As = AMOVD p.From.Type = obj.TYPE_MEM @@ -599,12 +655,11 @@ func (c *ctxtz) stacksplitPre(p *obj.Prog, framesize int32) (*obj.Prog, *obj.Pro p.As = ACMPUBGE p.To.Type = obj.TYPE_BRANCH - return p, nil + return p, nil, pCheck } // large stack: SP-framesize < stackguard-StackSmall - var q *obj.Prog offset := int64(framesize) - objabi.StackSmall if framesize > objabi.StackBig { // Such a large stack we need to protect against underflow. @@ -625,7 +680,7 @@ func (c *ctxtz) stacksplitPre(p *obj.Prog, framesize int32) (*obj.Prog, *obj.Pro p.To.Reg = REG_R4 p = obj.Appendp(p, c.newprog) - q = p + pPreempt = p p.As = ACMPUBLT p.From.Type = obj.TYPE_REG p.From.Reg = REGSP @@ -651,10 +706,16 @@ func (c *ctxtz) stacksplitPre(p *obj.Prog, framesize int32) (*obj.Prog, *obj.Pro p.As = ACMPUBGE p.To.Type = obj.TYPE_BRANCH - return p, q + return p, pPreempt, pCheck } -func (c *ctxtz) stacksplitPost(p *obj.Prog, pPre *obj.Prog, pPreempt *obj.Prog, framesize int32) *obj.Prog { +// stacksplitPost generates the function epilogue that calls morestack +// and returns the new last instruction in the function. +// +// p is the last Prog in the function. pPre and pPreempt, if non-nil, +// are the instructions that branch to the epilogue. This will fill in +// their branch targets. pCheck is the Prog that begins the stack check. +func (c *ctxtz) stacksplitPost(p *obj.Prog, pPre, pPreempt, pCheck *obj.Prog, framesize int32) *obj.Prog { // Now we are at the end of the function, but logically // we are still in function prologue. We need to fix the // SP data and PCDATA. @@ -692,12 +753,12 @@ func (c *ctxtz) stacksplitPost(p *obj.Prog, pPre *obj.Prog, pPreempt *obj.Prog, p = c.ctxt.EndUnsafePoint(p, c.newprog, -1) - // BR start + // BR pCheck p = obj.Appendp(p, c.newprog) p.As = ABR p.To.Type = obj.TYPE_BRANCH - p.To.SetTarget(c.cursym.Func().Text.Link) + p.To.SetTarget(pCheck) return p } diff --git a/src/cmd/internal/obj/wasm/wasmobj.go b/src/cmd/internal/obj/wasm/wasmobj.go index 4d276db678..1c726f77d3 100644 --- a/src/cmd/internal/obj/wasm/wasmobj.go +++ b/src/cmd/internal/obj/wasm/wasmobj.go @@ -243,6 +243,51 @@ func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { p.Spadj = int32(framesize) } + needMoreStack := !s.Func().Text.From.Sym.NoSplit() + + // If the maymorestack debug option is enabled, insert the + // call to maymorestack *before* processing resume points so + // we can construct a resume point after maymorestack for + // morestack to resume at. + var pMorestack = s.Func().Text + if needMoreStack && ctxt.Flag_maymorestack != "" { + p := pMorestack + + // Save REGCTXT on the stack. + const tempFrame = 8 + p = appendp(p, AGet, regAddr(REG_SP)) + p = appendp(p, AI32Const, constAddr(tempFrame)) + p = appendp(p, AI32Sub) + p = appendp(p, ASet, regAddr(REG_SP)) + p.Spadj = tempFrame + ctxtp := obj.Addr{ + Type: obj.TYPE_MEM, + Reg: REG_SP, + Offset: 0, + } + p = appendp(p, AMOVD, regAddr(REGCTXT), ctxtp) + + // maymorestack must not itself preempt because we + // don't have full stack information, so this can be + // ACALLNORESUME. + p = appendp(p, ACALLNORESUME, constAddr(0)) + // See ../x86/obj6.go + sym := ctxt.LookupABI(ctxt.Flag_maymorestack, s.ABI()) + p.To = obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_EXTERN, Sym: sym} + + // Restore REGCTXT. + p = appendp(p, AMOVD, ctxtp, regAddr(REGCTXT)) + p = appendp(p, AGet, regAddr(REG_SP)) + p = appendp(p, AI32Const, constAddr(tempFrame)) + p = appendp(p, AI32Add) + p = appendp(p, ASet, regAddr(REG_SP)) + p.Spadj = -tempFrame + + // Add an explicit ARESUMEPOINT after maymorestack for + // morestack to resume at. + pMorestack = appendp(p, ARESUMEPOINT) + } + // Introduce resume points for CALL instructions // and collect other explicit resume points. numResumePoints := 0 @@ -303,8 +348,8 @@ func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { tableIdxs = append(tableIdxs, uint64(numResumePoints)) s.Size = pc + 1 - if !s.Func().Text.From.Sym.NoSplit() { - p := s.Func().Text + if needMoreStack { + p := pMorestack if framesize <= objabi.StackSmall { // small stack: SP <= stackguard @@ -341,6 +386,13 @@ func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { // TODO(neelance): handle wraparound case p = appendp(p, AIf) + // This CALL does *not* have a resume point after it + // (we already inserted all of the resume points). As + // a result, morestack will resume at the *previous* + // resume point (typically, the beginning of the + // function) and perform the morestack check again. + // This is why we don't need an explicit loop like + // other architectures. p = appendp(p, obj.ACALL, constAddr(0)) if s.Func().Text.From.Sym.NeedCtxt() { p.To = obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_EXTERN, Sym: morestack} diff --git a/src/cmd/internal/obj/x86/obj6.go b/src/cmd/internal/obj/x86/obj6.go index 183ca2ebe9..a82285a0d3 100644 --- a/src/cmd/internal/obj/x86/obj6.go +++ b/src/cmd/internal/obj/x86/obj6.go @@ -644,19 +644,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { } } - var regg int16 - if !p.From.Sym.NoSplit() || p.From.Sym.Wrapper() { - if ctxt.Arch.Family == sys.AMD64 && cursym.ABI() == obj.ABIInternal { - regg = REGG // use the g register directly in ABIInternal - } else { - p = obj.Appendp(p, newprog) - regg = REG_CX - if ctxt.Arch.Family == sys.AMD64 { - regg = REGG // == REG_R14 - } - p = load_g(ctxt, p, newprog, regg) // load g into regg - } - } var regEntryTmp0, regEntryTmp1 int16 if ctxt.Arch.Family == sys.AMD64 { regEntryTmp0, regEntryTmp1 = REGENTRYTMP0, REGENTRYTMP1 @@ -664,8 +651,13 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { regEntryTmp0, regEntryTmp1 = REG_BX, REG_DI } - if !cursym.Func().Text.From.Sym.NoSplit() { - p = stacksplit(ctxt, cursym, p, newprog, autoffset, int32(textarg), regg) // emit split check + var regg int16 + if !p.From.Sym.NoSplit() { + // Emit split check and load G register + p, regg = stacksplit(ctxt, cursym, p, newprog, autoffset, int32(textarg)) + } else if p.From.Sym.Wrapper() { + // Load G register for the wrapper code + p, regg = loadG(ctxt, cursym, p, newprog) } // Delve debugger would like the next instruction to be noted as the end of the function prologue. @@ -973,12 +965,21 @@ func indir_cx(ctxt *obj.Link, a *obj.Addr) { a.Reg = REG_CX } -// Append code to p to load g into cx. -// Overwrites p with the first instruction (no first appendp). -// Overwriting p is unusual but it lets use this in both the -// prologue (caller must call appendp first) and in the epilogue. -// Returns last new instruction. -func load_g(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, rg int16) *obj.Prog { +// loadG ensures the G is loaded into a register (either CX or REGG), +// appending instructions to p if necessary. It returns the new last +// instruction and the G register. +func loadG(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgAlloc) (*obj.Prog, int16) { + if ctxt.Arch.Family == sys.AMD64 && cursym.ABI() == obj.ABIInternal { + // Use the G register directly in ABIInternal + return p, REGG + } + + var regg int16 = REG_CX + if ctxt.Arch.Family == sys.AMD64 { + regg = REGG // == REG_R14 + } + + p = obj.Appendp(p, newprog) p.As = AMOVQ if ctxt.Arch.PtrSize == 4 { p.As = AMOVL @@ -987,8 +988,9 @@ func load_g(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, rg int16) *obj.P p.From.Reg = REG_TLS p.From.Offset = 0 p.To.Type = obj.TYPE_REG - p.To.Reg = rg + p.To.Reg = regg + // Rewrite TLS instruction if necessary. next := p.Link progedit(ctxt, p, newprog) for p.Link != next { @@ -1000,24 +1002,26 @@ func load_g(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, rg int16) *obj.P p.From.Scale = 2 } - return p + return p, regg } // Append code to p to check for stack split. // Appends to (does not overwrite) p. // Assumes g is in rg. -// Returns last new instruction. -func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgAlloc, framesize int32, textarg int32, rg int16) *obj.Prog { +// Returns last new instruction and G register. +func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgAlloc, framesize int32, textarg int32) (*obj.Prog, int16) { cmp := ACMPQ lea := ALEAQ mov := AMOVQ sub := ASUBQ + push, pop := APUSHQ, APOPQ if ctxt.Arch.Family == sys.I386 { cmp = ACMPL lea = ALEAL mov = AMOVL sub = ASUBL + push, pop = APUSHL, APOPL } tmp := int16(REG_AX) // use AX for 32-bit @@ -1026,6 +1030,45 @@ func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgA tmp = int16(REGENTRYTMP0) } + if ctxt.Flag_maymorestack != "" { + p = cursym.Func().SpillRegisterArgs(p, newprog) + + if cursym.Func().Text.From.Sym.NeedCtxt() { + p = obj.Appendp(p, newprog) + p.As = push + p.From.Type = obj.TYPE_REG + p.From.Reg = REGCTXT + } + + // We call maymorestack with an ABI matching the + // caller's ABI. Since this is the first thing that + // happens in the function, we have to be consistent + // with the caller about CPU state (notably, + // fixed-meaning registers). + + p = obj.Appendp(p, newprog) + p.As = obj.ACALL + p.To.Type = obj.TYPE_BRANCH + p.To.Name = obj.NAME_EXTERN + p.To.Sym = ctxt.LookupABI(ctxt.Flag_maymorestack, cursym.ABI()) + + if cursym.Func().Text.From.Sym.NeedCtxt() { + p = obj.Appendp(p, newprog) + p.As = pop + p.To.Type = obj.TYPE_REG + p.To.Reg = REGCTXT + } + + p = cursym.Func().UnspillRegisterArgs(p, newprog) + } + + // Jump back to here after morestack returns. + startPred := p + + // Load G register + var rg int16 + p, rg = loadG(ctxt, cursym, p, newprog) + var q1 *obj.Prog if framesize <= objabi.StackSmall { // small stack: SP <= stackguard @@ -1171,7 +1214,7 @@ func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgA jmp := obj.Appendp(pcdata, newprog) jmp.As = obj.AJMP jmp.To.Type = obj.TYPE_BRANCH - jmp.To.SetTarget(cursym.Func().Text.Link) + jmp.To.SetTarget(startPred.Link) jmp.Spadj = +framesize jls.To.SetTarget(spill) @@ -1179,7 +1222,7 @@ func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgA q1.To.SetTarget(spill) } - return end + return end, rg } func isR15(r int16) bool { diff --git a/test/maymorestack.go b/test/maymorestack.go new file mode 100644 index 0000000000..ec84ad44bc --- /dev/null +++ b/test/maymorestack.go @@ -0,0 +1,47 @@ +// run -gcflags=-d=maymorestack=main.mayMoreStack + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test the maymorestack testing hook by injecting a hook that counts +// how many times it is called and checking that count. + +package main + +import "runtime" + +var count uint32 + +//go:nosplit +func mayMoreStack() { + count++ +} + +func main() { + const wantCount = 128 + + anotherFunc(wantCount - 1) // -1 because the call to main already counted + + if count == 0 { + panic("mayMoreStack not called") + } else if count != wantCount { + println(count, "!=", wantCount) + panic("wrong number of calls to mayMoreStack") + } +} + +//go:noinline +func anotherFunc(n int) { + // Trigger a stack growth on at least some calls to + // anotherFunc to test that mayMoreStack is called outside the + // morestack loop. It's also important that it is called + // before (not after) morestack, but that's hard to test. + var x [1 << 10]byte + + if n > 1 { + anotherFunc(n - 1) + } + + runtime.KeepAlive(x) +} -- GitLab From 35c7234601c409a1d1595e4eb9fe72e8ba4e6464 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Wed, 15 Sep 2021 17:14:21 -0400 Subject: [PATCH 1980/2500] runtime: add always-preempt maymorestack hook This adds a maymorestack hook that forces a preemption at every possible cooperative preemption point. This would have helped us catch several recent preemption-related bugs earlier, including #47302, #47304, and #47441. For #48297. Change-Id: Ib82c973589c8a7223900e1842913b8591938fb9f Reviewed-on: https://go-review.googlesource.com/c/go/+/359796 Trust: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot Reviewed-by: Cherry Mui Reviewed-by: Michael Pratt Reviewed-by: David Chase --- src/runtime/debug.go | 34 ++++++++++++++++++++++++++++++++++ src/runtime/stack.go | 3 +++ 2 files changed, 37 insertions(+) diff --git a/src/runtime/debug.go b/src/runtime/debug.go index 82deefa200..c343f430cc 100644 --- a/src/runtime/debug.go +++ b/src/runtime/debug.go @@ -61,3 +61,37 @@ func NumGoroutine() int { func debug_modinfo() string { return modinfo } + +// mayMoreStackPreempt is a maymorestack hook that forces a preemption +// at every possible cooperative preemption point. +// +// This is valuable to apply to the runtime, which can be sensitive to +// preemption points. To apply this to all preemption points in the +// runtime and runtime-like code, use the following in bash or zsh: +// +// X=(-{gc,asm}flags={runtime/...,reflect,sync}=-d=maymorestack=runtime.mayMoreStackPreempt) GOFLAGS=${X[@]} +// +// This must be deeply nosplit because it is called from a function +// prologue before the stack is set up and because the compiler will +// call it from any splittable prologue (leading to infinite +// recursion). +// +// Ideally it should also use very little stack because the linker +// doesn't currently account for this in nosplit stack depth checking. +// +//go:nosplit +// +// Ensure mayMoreStackPreempt can be called for all ABIs. +// +//go:linkname mayMoreStackPreempt +func mayMoreStackPreempt() { + // Don't do anything on the g0 or gsignal stack. + g := getg() + if g == g.m.g0 || g == g.m.gsignal { + return + } + // Force a preemption, unless the stack is already poisoned. + if g.stackguard0 < stackPoisonMin { + g.stackguard0 = stackPreempt + } +} diff --git a/src/runtime/stack.go b/src/runtime/stack.go index 52d21e4ee4..7d9ae1e9d2 100644 --- a/src/runtime/stack.go +++ b/src/runtime/stack.go @@ -144,6 +144,9 @@ const ( // Force a stack movement. Used for debugging. // 0xfffffeed in hex. stackForceMove = uintptrMask & -275 + + // stackPoisonMin is the lowest allowed stack poison value. + stackPoisonMin = uintptrMask & -4096 ) // Global pool of spans that have free stacks. -- GitLab From bd580a0d10729553a7905481d17eed0436198866 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 27 Sep 2021 10:05:13 -0400 Subject: [PATCH 1981/2500] runtime: add a maymorestack hook that moves the stack This adds a maymorestack hook that moves the stack at every cooperative preemption point. For #48297. Change-Id: Ic15f9bcbc163345e6422586302d57fda4744caec Reviewed-on: https://go-review.googlesource.com/c/go/+/359797 Trust: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot Reviewed-by: Cherry Mui Reviewed-by: Michael Pratt Reviewed-by: David Chase --- src/runtime/debug.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/runtime/debug.go b/src/runtime/debug.go index c343f430cc..2703a0ce01 100644 --- a/src/runtime/debug.go +++ b/src/runtime/debug.go @@ -95,3 +95,22 @@ func mayMoreStackPreempt() { g.stackguard0 = stackPreempt } } + +// mayMoreStackMove is a maymorestack hook that forces stack movement +// at every possible point. +// +// See mayMoreStackPreempt. +// +//go:nosplit +//go:linkname mayMoreStackMove +func mayMoreStackMove() { + // Don't do anything on the g0 or gsignal stack. + g := getg() + if g == g.m.g0 || g == g.m.gsignal { + return + } + // Force stack movement, unless the stack is already poisoned. + if g.stackguard0 < stackPoisonMin { + g.stackguard0 = stackForceMove + } +} -- GitLab From 0a5ca2422f14f9c17a017207feb9f83f94ce0e89 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Mon, 27 Sep 2021 14:40:06 -0400 Subject: [PATCH 1982/2500] crypto/ecdsa: draw a fixed amount of entropy while signing The current code, introduced in CL 2422, mixes K bits of entropy with the private key and message digest to generate the signature nonce, where K is half the bit size of the curve. While the ECDLP complexity (and hence security level) of a curve is half its bit size, the birthday bound on K bits is only K/2. For P-224, this means we should expect a collision after 2^56 signatures over the same message with the same key. A collision, which is unlikely, would still not be a major practical concern, because the scheme would fall back to a secure deterministic signature scheme, and simply leak the fact that the two signed messages are the same (which is presumably already public). Still, we can simplify the code and remove the eventuality by always drawing 256 bits of entropy. Change-Id: I58097bd3cfc9283503e38751c924c53d271af92b Reviewed-on: https://go-review.googlesource.com/c/go/+/352530 Trust: Filippo Valsorda Run-TryBot: Filippo Valsorda TryBot-Result: Go Bot Reviewed-by: Roland Shoemaker --- src/crypto/ecdsa/ecdsa.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/crypto/ecdsa/ecdsa.go b/src/crypto/ecdsa/ecdsa.go index 219436935f..282596d2d2 100644 --- a/src/crypto/ecdsa/ecdsa.go +++ b/src/crypto/ecdsa/ecdsa.go @@ -200,12 +200,8 @@ var errZeroParam = errors.New("zero parameter") func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) { randutil.MaybeReadByte(rand) - // Get min(log2(q) / 2, 256) bits of entropy from rand. - entropylen := (priv.Curve.Params().BitSize + 7) / 16 - if entropylen > 32 { - entropylen = 32 - } - entropy := make([]byte, entropylen) + // Get 256 bits of entropy from rand. + entropy := make([]byte, 32) _, err = io.ReadFull(rand, entropy) if err != nil { return -- GitLab From 3b5add5d683572a81ed57007612bc2c712aa7789 Mon Sep 17 00:00:00 2001 From: lgbgbl Date: Fri, 5 Nov 2021 04:57:59 +0000 Subject: [PATCH 1983/2500] bufio: fix typo in comment Change-Id: I6074334bc73ee1773fc83d049142ad764e39e5a9 GitHub-Last-Rev: 6a8789318ab132a169a89be807394af55c855ce9 GitHub-Pull-Request: golang/go#49373 Reviewed-on: https://go-review.googlesource.com/c/go/+/361413 Reviewed-by: Brad Fitzpatrick Reviewed-by: Ian Lance Taylor --- src/bufio/bufio_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bufio/bufio_test.go b/src/bufio/bufio_test.go index 66b3e70053..4dddfa9085 100644 --- a/src/bufio/bufio_test.go +++ b/src/bufio/bufio_test.go @@ -1520,7 +1520,7 @@ func TestReaderDiscard(t *testing.T) { wantBuffered: 0, }, // Any error from filling shouldn't show up until we - // get past the valid bytes. Here we return we return 5 valid bytes at the same time + // get past the valid bytes. Here we return 5 valid bytes at the same time // as an error, but test that we don't see the error from Discard. { name: "fill error, discard less", -- GitLab From b68c02e2919aec347438a7ec6512b0d2accd163f Mon Sep 17 00:00:00 2001 From: Andy Pan Date: Fri, 5 Nov 2021 10:40:31 +0800 Subject: [PATCH 1984/2500] internal/poll: fix the wrong function names in comments Change-Id: Ib17df2751209129ad6d1c148829625b347b702a9 Reviewed-on: https://go-review.googlesource.com/c/go/+/361514 Reviewed-by: Brad Fitzpatrick Reviewed-by: Ian Lance Taylor Trust: Brad Fitzpatrick --- src/internal/poll/fd_windows.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/internal/poll/fd_windows.go b/src/internal/poll/fd_windows.go index 0d8bf87992..1ca281b2a4 100644 --- a/src/internal/poll/fd_windows.go +++ b/src/internal/poll/fd_windows.go @@ -593,7 +593,7 @@ func (fd *FD) ReadFrom(buf []byte) (int, syscall.Sockaddr, error) { return n, sa, nil } -// ReadFrom wraps the recvfrom network call for IPv4. +// ReadFromInet4 wraps the recvfrom network call for IPv4. func (fd *FD) ReadFromInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) { if len(buf) == 0 { return 0, nil @@ -622,7 +622,7 @@ func (fd *FD) ReadFromInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) return n, err } -// ReadFrom wraps the recvfrom network call for IPv6. +// ReadFromInet6 wraps the recvfrom network call for IPv6. func (fd *FD) ReadFromInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) { if len(buf) == 0 { return 0, nil -- GitLab From 6fefb7f9f3b632bdd0c3997ecc5b1096a5077cdf Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 4 Nov 2021 13:28:25 -0700 Subject: [PATCH 1985/2500] cmd/compile: gracefully fallback when inline bodies are missing Currently, we rely on a "crawling" step during export to identify function and method bodies that need to be exported or re-exported so we can trim out unnecessary ones and reduce build artifact sizes. To catch cases where we expect a function to be inlinable but we failed to export its body, we made this condition a fatal compiler error. However, with generics, it's much harder to perfectly identify all function bodies that need to be exported; and several attempts at tweaking the algorithm have resulted in still having failure cases. So for now, this CL changes a missing inline body into a graceful failure instead. Change-Id: I04b0872d0dcaae9c3de473e92ce584e4ec6fd782 Reviewed-on: https://go-review.googlesource.com/c/go/+/361403 Trust: Matthew Dempsky Trust: Dan Scales Run-TryBot: Matthew Dempsky Reviewed-by: Dan Scales --- src/cmd/compile/internal/inline/inl.go | 4 ++-- src/cmd/compile/internal/typecheck/crawler.go | 2 +- src/cmd/compile/internal/typecheck/iimport.go | 21 +++++++++++++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index b764aed534..47b895f7e3 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -309,7 +309,7 @@ func (v *hairyVisitor) doNode(n ir.Node) bool { break } - if fn := inlCallee(n.X); fn != nil && fn.Inl != nil { + if fn := inlCallee(n.X); fn != nil && typecheck.HaveInlineBody(fn) { v.budget -= fn.Inl.Cost break } @@ -585,7 +585,7 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool, edit func(ir.No if ir.IsIntrinsicCall(call) { break } - if fn := inlCallee(call.X); fn != nil && fn.Inl != nil { + if fn := inlCallee(call.X); fn != nil && typecheck.HaveInlineBody(fn) { n = mkinlcall(call, fn, maxCost, inlMap, edit) } } diff --git a/src/cmd/compile/internal/typecheck/crawler.go b/src/cmd/compile/internal/typecheck/crawler.go index ae2b3b1df4..ae6542d071 100644 --- a/src/cmd/compile/internal/typecheck/crawler.go +++ b/src/cmd/compile/internal/typecheck/crawler.go @@ -207,7 +207,7 @@ func (p *crawler) markInlBody(n *ir.Name) { if fn == nil { base.Fatalf("markInlBody: missing Func on %v", n) } - if fn.Inl == nil { + if !HaveInlineBody(fn) { return } diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 7c6c23e737..26bc838ed9 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -81,6 +81,27 @@ func ImportBody(fn *ir.Func) { inimport = false } +// HaveInlineBody reports whether we have fn's inline body available +// for inlining. +func HaveInlineBody(fn *ir.Func) bool { + if fn.Inl == nil { + return false + } + + // Unified IR is much more conservative about pruning unreachable + // methods (at the cost of increased build artifact size). + if base.Debug.Unified != 0 { + return true + } + + if fn.Inl.Body != nil { + return true + } + + _, ok := inlineImporter[fn.Nname.Sym()] + return ok +} + func importReaderFor(sym *types.Sym, importers map[*types.Sym]iimporterAndOffset) *importReader { x, ok := importers[sym] if !ok { -- GitLab From a0d661ab0ff896abe45d6d4e79cb71df233c5319 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Fri, 5 Nov 2021 08:18:57 -0700 Subject: [PATCH 1986/2500] net: skip new alloc test on some builders Change-Id: Ib785212eb9e035a10d327696c180caf730d2e5e7 Reviewed-on: https://go-review.googlesource.com/c/go/+/361634 Run-TryBot: Brad Fitzpatrick TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills Trust: Brad Fitzpatrick --- src/net/udpsock_test.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/net/udpsock_test.go b/src/net/udpsock_test.go index 518c66c331..9fe74f47a2 100644 --- a/src/net/udpsock_test.go +++ b/src/net/udpsock_test.go @@ -475,6 +475,17 @@ func TestUDPReadTimeout(t *testing.T) { } func TestAllocs(t *testing.T) { + switch runtime.GOOS { + case "plan9": + // Plan9 wasn't optimized. + t.Skipf("skipping on %v", runtime.GOOS) + } + builder := os.Getenv("GO_BUILDER_NAME") + switch builder { + case "linux-amd64-noopt": + // Optimizations are required to remove the allocs. + t.Skipf("skipping on %v", builder) + } conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) if err != nil { t.Fatal(err) -- GitLab From f249fa27a9117dd5986f35463fc6a1467ecc72bb Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Fri, 5 Nov 2021 20:30:38 +0700 Subject: [PATCH 1987/2500] cmd/compile: only update source type when processing struct/array CL 360057 fixed missing update source type in storeArgOrLoad. However, we should only update the type when processing struct/array. If we update the type right before calling storeArgOrLoad, we may generate a value with invalid type, e.g, OpStructSelect with non-struct type. Fixes #49378 Change-Id: Ib7e10f72f818880f550aae5c9f653db463ce29b0 Reviewed-on: https://go-review.googlesource.com/c/go/+/361594 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: David Chase --- src/cmd/compile/internal/ssa/expand_calls.go | 4 ++-- test/fixedbugs/issue49378.go | 25 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 test/fixedbugs/issue49378.go diff --git a/src/cmd/compile/internal/ssa/expand_calls.go b/src/cmd/compile/internal/ssa/expand_calls.go index 91ff9f87f9..a3cea855f2 100644 --- a/src/cmd/compile/internal/ssa/expand_calls.go +++ b/src/cmd/compile/internal/ssa/expand_calls.go @@ -954,11 +954,11 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, source, mem *Value, elt := t.Elem() if source.Type != t && t.NumElem() == 1 && elt.Size() == t.Size() && t.Size() == x.regSize { t = removeTrivialWrapperTypes(t) - source.Type = t // it could be a leaf type, but the "leaf" could be complex64 (for example) return x.storeArgOrLoad(pos, b, source, mem, t, storeOffset, loadRegOffset, storeRc) } eltRO := x.regWidth(elt) + source.Type = t for i := int64(0); i < t.NumElem(); i++ { sel := source.Block.NewValue1I(pos, OpArraySelect, elt, i, source) mem = x.storeArgOrLoad(pos, b, sel, mem, elt, storeOffset+i*elt.Size(), loadRegOffset, storeRc.at(t, 0)) @@ -988,11 +988,11 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, source, mem *Value, // v139 is later stored as an intVal == struct{val *big.Int} which naively requires the fields of // of a *uint8, which does not succeed. t = removeTrivialWrapperTypes(t) - source.Type = t // it could be a leaf type, but the "leaf" could be complex64 (for example) return x.storeArgOrLoad(pos, b, source, mem, t, storeOffset, loadRegOffset, storeRc) } + source.Type = t for i := 0; i < t.NumFields(); i++ { fld := t.Field(i) sel := source.Block.NewValue1I(pos, OpStructSelect, fld.Type, int64(i), source) diff --git a/test/fixedbugs/issue49378.go b/test/fixedbugs/issue49378.go new file mode 100644 index 0000000000..70f466c929 --- /dev/null +++ b/test/fixedbugs/issue49378.go @@ -0,0 +1,25 @@ +// compile + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func f(i int) { + var s1 struct { + s struct{ s struct{ i int } } + } + var s2, s3 struct { + a struct{ i int } + b int + } + func() { + i = 1 + 2*i + s3.a.i + func() int { + s2.a, s2.b = s3.a, s3.b + return 0 + }() + func(*int) int { + return s1.s.s.i + }(new(int)) + }() +} -- GitLab From c58417b97f2b8d16176ddd294ae4471f834ab4d6 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 4 Nov 2021 16:53:30 -0400 Subject: [PATCH 1988/2500] runtime: mark TestTracebackArgs test functions nosplit The argument liveness tests expect outputs where a dead stack slot has a poisoned value. If the test function is preempted at the prologue, it will go with the morestack code path which will spill all the argument registers. Mark them nosplit to avoid that. Should fix #49354. Change-Id: I3b13e72e925748687a53c494bfaa70f07d9496fa Reviewed-on: https://go-review.googlesource.com/c/go/+/361211 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Austin Clements --- src/runtime/traceback_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/runtime/traceback_test.go b/src/runtime/traceback_test.go index 0333b85c56..7d8b04e14b 100644 --- a/src/runtime/traceback_test.go +++ b/src/runtime/traceback_test.go @@ -353,6 +353,9 @@ func testTracebackArgs8d(a testArgsType8d) int { return n } +// nosplit to avoid preemption or morestack spilling registers. +// +//go:nosplit //go:noinline func testTracebackArgs9(a int64, b int32, c int16, d int8, x [2]int, y int) int { if a < 0 { @@ -366,6 +369,9 @@ func testTracebackArgs9(a int64, b int32, c int16, d int8, x [2]int, y int) int return n } +// nosplit to avoid preemption or morestack spilling registers. +// +//go:nosplit //go:noinline func testTracebackArgs10(a, b, c, d, e int32) int { // no use of any args @@ -373,8 +379,10 @@ func testTracebackArgs10(a, b, c, d, e int32) int { } // norace to avoid race instrumentation changing spill locations. +// nosplit to avoid preemption or morestack spilling registers. // //go:norace +//go:nosplit //go:noinline func testTracebackArgs11a(a, b, c int32) int { if a < 0 { @@ -387,8 +395,10 @@ func testTracebackArgs11a(a, b, c int32) int { } // norace to avoid race instrumentation changing spill locations. +// nosplit to avoid preemption or morestack spilling registers. // //go:norace +//go:nosplit //go:noinline func testTracebackArgs11b(a, b, c, d int32) int { var x int32 -- GitLab From 3796df1b13c6be62ca28244dcd6121544770e371 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Thu, 4 Nov 2021 21:35:55 -0700 Subject: [PATCH 1989/2500] net/netip: don't accept ParseAddr with leading zeros Fixes #49365 Updates #30999 Change-Id: Ic92bce01b435baf70574c65524bde82f9cee3d8d Reviewed-on: https://go-review.googlesource.com/c/go/+/361534 Run-TryBot: Brad Fitzpatrick TryBot-Result: Go Bot Reviewed-by: Josh Bleecher Snyder Trust: Josh Bleecher Snyder Trust: Brad Fitzpatrick --- src/net/netip/netip.go | 6 ++++++ src/net/netip/netip_test.go | 32 +++++++++++++++++++++----------- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/net/netip/netip.go b/src/net/netip/netip.go index 02a4aa0452..b0c13b81fc 100644 --- a/src/net/netip/netip.go +++ b/src/net/netip/netip.go @@ -155,9 +155,14 @@ func (err parseAddrError) Error() string { func parseIPv4(s string) (ip Addr, err error) { var fields [4]uint8 var val, pos int + var digLen int // number of digits in current octet for i := 0; i < len(s); i++ { if s[i] >= '0' && s[i] <= '9' { + if digLen == 1 && val == 0 { + return Addr{}, parseAddrError{in: s, msg: "IPv4 field has octet with leading zero"} + } val = val*10 + int(s[i]) - '0' + digLen++ if val > 255 { return Addr{}, parseAddrError{in: s, msg: "IPv4 field has value >255"} } @@ -175,6 +180,7 @@ func parseIPv4(s string) (ip Addr, err error) { fields[pos] = uint8(val) pos++ val = 0 + digLen = 0 } else { return Addr{}, parseAddrError{in: s, msg: "unexpected character", at: s[i:]} } diff --git a/src/net/netip/netip_test.go b/src/net/netip/netip_test.go index 5d935c8fd3..241a71bb83 100644 --- a/src/net/netip/netip_test.go +++ b/src/net/netip/netip_test.go @@ -29,9 +29,10 @@ var ( func TestParseAddr(t *testing.T) { var validIPs = []struct { - in string - ip Addr // output of ParseAddr() - str string // output of String(). If "", use in. + in string + ip Addr // output of ParseAddr() + str string // output of String(). If "", use in. + wantErr string }{ // Basic zero IPv4 address. { @@ -45,15 +46,18 @@ func TestParseAddr(t *testing.T) { }, // IPv4 address in windows-style "print all the digits" form. { - in: "010.000.015.001", - ip: MkAddr(Mk128(0, 0xffff0a000f01), Z4), - str: "10.0.15.1", + in: "010.000.015.001", + wantErr: `ParseAddr("010.000.015.001"): IPv4 field has octet with leading zero`, }, // IPv4 address with a silly amount of leading zeros. { - in: "000001.00000002.00000003.000000004", - ip: MkAddr(Mk128(0, 0xffff01020304), Z4), - str: "1.2.3.4", + in: "000001.00000002.00000003.000000004", + wantErr: `ParseAddr("000001.00000002.00000003.000000004"): IPv4 field has octet with leading zero`, + }, + // 4-in-6 with octet with leading zero + { + in: "::ffff:1.2.03.4", + wantErr: `ParseAddr("::ffff:1.2.03.4"): ParseAddr("1.2.03.4"): IPv4 field has octet with leading zero (at "1.2.03.4")`, }, // Basic zero IPv6 address. { @@ -121,10 +125,16 @@ func TestParseAddr(t *testing.T) { t.Run(test.in, func(t *testing.T) { got, err := ParseAddr(test.in) if err != nil { + if err.Error() == test.wantErr { + return + } t.Fatal(err) } + if test.wantErr != "" { + t.Fatalf("wanted error %q; got none", test.wantErr) + } if got != test.ip { - t.Errorf("ParseAddr(%q) got %#v, want %#v", test.in, got, test.ip) + t.Errorf("got %#v, want %#v", got, test.ip) } // Check that ParseAddr is a pure function. @@ -963,7 +973,7 @@ func TestIs4In6(t *testing.T) { {mustIP("::ffff:192.0.2.128"), true, mustIP("192.0.2.128")}, {mustIP("::ffff:192.0.2.128%eth0"), true, mustIP("192.0.2.128")}, {mustIP("::fffe:c000:0280"), false, mustIP("::fffe:c000:0280")}, - {mustIP("::ffff:127.001.002.003"), true, mustIP("127.1.2.3")}, + {mustIP("::ffff:127.1.2.3"), true, mustIP("127.1.2.3")}, {mustIP("::ffff:7f01:0203"), true, mustIP("127.1.2.3")}, {mustIP("0:0:0:0:0000:ffff:127.1.2.3"), true, mustIP("127.1.2.3")}, {mustIP("0:0:0:0:000000:ffff:127.1.2.3"), true, mustIP("127.1.2.3")}, -- GitLab From 62c6ff4296fa5919a208552c57b44e4710b4e5e1 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Thu, 4 Nov 2021 16:03:49 -0700 Subject: [PATCH 1990/2500] runtime: fix a lock rank ordering and some edges. The first stack-trace in #49361 shows that traceBuf must precede fin in lockrank ordering, since traceBuf is acquired in StartTrace(), which eventually leads to getting fin in queueFinalizer(). It is fine to move traceBuf above fin, since there are no other conflicting dependencies. The second stack trace shows that there is an edge bewtween reflectOffs and fin, since reflectOffs is acquired in addReflectOff, and map operations can lead to an allocation that eventually causes fin to be acquired in queueFinalizer(). Fixes #49361 Change-Id: I8e857ef9ecdff37fdd229e4dba22e15bc71d4ba5 Reviewed-on: https://go-review.googlesource.com/c/go/+/361407 Trust: Dan Scales Reviewed-by: Michael Pratt --- src/runtime/lockrank.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/runtime/lockrank.go b/src/runtime/lockrank.go index dde9f7c21a..54b0f4ce9c 100644 --- a/src/runtime/lockrank.go +++ b/src/runtime/lockrank.go @@ -51,9 +51,9 @@ const ( lockRankItab lockRankReflectOffs lockRankHchan // Multiple hchans acquired in lock order in syncadjustsudogs() + lockRankTraceBuf lockRankFin lockRankNotifyList - lockRankTraceBuf lockRankTraceStrings lockRankMspanSpecial lockRankProf @@ -131,9 +131,9 @@ var lockNames = []string{ lockRankReflectOffs: "reflectOffs", lockRankHchan: "hchan", + lockRankTraceBuf: "traceBuf", lockRankFin: "fin", lockRankNotifyList: "notifyList", - lockRankTraceBuf: "traceBuf", lockRankTraceStrings: "traceStrings", lockRankMspanSpecial: "mspanSpecial", lockRankProf: "prof", @@ -208,30 +208,30 @@ var lockPartialOrder [][]lockRank = [][]lockRank{ lockRankItab: {}, lockRankReflectOffs: {lockRankItab}, lockRankHchan: {lockRankScavenge, lockRankSweep, lockRankHchan}, - lockRankFin: {lockRankSysmon, lockRankScavenge, lockRankSched, lockRankAllg, lockRankTimers, lockRankHchan}, - lockRankNotifyList: {}, lockRankTraceBuf: {lockRankSysmon, lockRankScavenge}, + lockRankFin: {lockRankSysmon, lockRankScavenge, lockRankSched, lockRankAllg, lockRankTimers, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf}, + lockRankNotifyList: {}, lockRankTraceStrings: {lockRankTraceBuf}, - lockRankMspanSpecial: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings}, - lockRankProf: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings}, - lockRankGcBitsArenas: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings}, + lockRankMspanSpecial: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings}, + lockRankProf: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings}, + lockRankGcBitsArenas: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings}, lockRankRoot: {}, lockRankTrace: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankHchan, lockRankTraceBuf, lockRankTraceStrings, lockRankRoot}, - lockRankTraceStackTab: {lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankAllg, lockRankTimers, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankRoot, lockRankTrace}, + lockRankTraceStackTab: {lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankAllg, lockRankTimers, lockRankHchan, lockRankTraceBuf, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankRoot, lockRankTrace}, lockRankNetpollInit: {lockRankTimers}, lockRankRwmutexW: {}, lockRankRwmutexR: {lockRankSysmon, lockRankRwmutexW}, - lockRankSpanSetSpine: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings}, - lockRankGscan: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankSpanSetSpine}, - lockRankStackpool: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankRwmutexR, lockRankSpanSetSpine, lockRankGscan}, + lockRankSpanSetSpine: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings}, + lockRankGscan: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankSpanSetSpine}, + lockRankStackpool: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankRwmutexR, lockRankSpanSetSpine, lockRankGscan}, lockRankStackLarge: {lockRankSysmon, lockRankAssistQueue, lockRankSched, lockRankItab, lockRankHchan, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankSpanSetSpine, lockRankGscan}, lockRankDefer: {}, lockRankSudog: {lockRankHchan, lockRankNotifyList}, lockRankWbufSpans: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankRoot, lockRankGscan, lockRankDefer, lockRankSudog}, - lockRankMheap: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankSpanSetSpine, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankDefer, lockRankSudog, lockRankWbufSpans}, - lockRankMheapSpecial: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings}, + lockRankMheap: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankSpanSetSpine, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankDefer, lockRankSudog, lockRankWbufSpans}, + lockRankMheapSpecial: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings}, lockRankGlobalAlloc: {lockRankProf, lockRankSpanSetSpine, lockRankMheap, lockRankMheapSpecial}, lockRankGFree: {lockRankSched}, -- GitLab From 37951d888152c6f3a2e4c11c609bfb0fbad6b15d Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Fri, 5 Nov 2021 10:07:11 -0700 Subject: [PATCH 1991/2500] net/netip: optimize As4 and As16 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit name old time/op new time/op delta As16-8 2.88ns ± 3% 2.16ns ± 3% -25.19% (p=0.000 n=15+15) Fixes #49379 Updates #20859 Change-Id: If4cf58d19ed0e2ac0f179da5c132ed37061e4cb7 Reviewed-on: https://go-review.googlesource.com/c/go/+/361674 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder Reviewed-by: Brad Fitzpatrick --- src/net/netip/netip.go | 16 +++++++--------- src/net/netip/netip_test.go | 9 +++++++++ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/net/netip/netip.go b/src/net/netip/netip.go index b0c13b81fc..8cde6ef3d2 100644 --- a/src/net/netip/netip.go +++ b/src/net/netip/netip.go @@ -698,21 +698,19 @@ const ( // IPv6 addresses with zones are returned without their zone (use the // Zone method to get it). // The ip zero value returns all zeroes. -func (ip Addr) As16() [16]byte { - var ret [16]byte - bePutUint64(ret[:8], ip.addr.hi) - bePutUint64(ret[8:], ip.addr.lo) - return ret +func (ip Addr) As16() (a16 [16]byte) { + bePutUint64(a16[:8], ip.addr.hi) + bePutUint64(a16[8:], ip.addr.lo) + return a16 } // As4 returns an IPv4 or IPv4-in-IPv6 address in its 4-byte representation. // If ip is the zero Addr or an IPv6 address, As4 panics. // Note that 0.0.0.0 is not the zero Addr. -func (ip Addr) As4() [4]byte { +func (ip Addr) As4() (a4 [4]byte) { if ip.z == z4 || ip.Is4In6() { - var ret [4]byte - bePutUint32(ret[:], uint32(ip.addr.lo)) - return ret + bePutUint32(a4[:], uint32(ip.addr.lo)) + return a4 } if ip.z == z0 { panic("As4 called on IP zero value") diff --git a/src/net/netip/netip_test.go b/src/net/netip/netip_test.go index 241a71bb83..c39b1ec201 100644 --- a/src/net/netip/netip_test.go +++ b/src/net/netip/netip_test.go @@ -1806,3 +1806,12 @@ func TestInvalidAddrPortString(t *testing.T) { } } } + +var sink16 [16]byte + +func BenchmarkAs16(b *testing.B) { + addr := MustParseAddr("1::10") + for i := 0; i < b.N; i++ { + sink16 = addr.As16() + } +} -- GitLab From 0bc98b3e9b3b6b55489bb9ffed54377e678eba28 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Fri, 5 Nov 2021 17:09:22 +0100 Subject: [PATCH 1992/2500] syscall: fix mkall.sh for openbsd/386 CL 287654 converted the syscall package on openbsd/386 to use libc. However, the mksyscall.pl invocation wasn't adjusted. Do so now to use syscall_openbsd_libc.go like the other libc-based openbsd ports. Change-Id: I48a7bd6ce4c25eca5222f560ed584e412b466111 Reviewed-on: https://go-review.googlesource.com/c/go/+/361481 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick Reviewed-by: Cherry Mui --- src/syscall/mkall.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/syscall/mkall.sh b/src/syscall/mkall.sh index dffb52864b..5fc91d3815 100755 --- a/src/syscall/mkall.sh +++ b/src/syscall/mkall.sh @@ -283,7 +283,7 @@ netbsd_arm64) mktypes="GOARCH=$GOARCH go tool cgo -godefs" ;; openbsd_386) - GOOSARCH_in="syscall_openbsd1.go syscall_openbsd_$GOARCH.go" + GOOSARCH_in="syscall_openbsd_libc.go syscall_openbsd_$GOARCH.go" mkerrors="$mkerrors -m32" mksyscall="./mksyscall.pl -l32 -openbsd -libc" mksysctl="./mksysctl_openbsd.pl" -- GitLab From 4f543b59c5618abccf0e78a17a2aeb173c085a91 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 4 Oct 2021 20:36:49 +0000 Subject: [PATCH 1993/2500] runtime: don't hold the heap lock while scavenging This change modifies the scavenger to no longer hold the heap lock while actively scavenging pages. To achieve this, the change also: * Reverses the locking behavior of the (*pageAlloc).scavenge API, to only acquire the heap lock when necessary. * Introduces a new lock on the scavenger-related fields in a pageAlloc so that access to those fields doesn't require the heap lock. There are a few places in the scavenge path, notably reservation, that requires synchronization. The heap lock is far too heavy handed for this case. * Changes the scavenger to marks pages that are actively being scavenged as allocated, and "frees" them back to the page allocator the usual way. * Lifts the heap-growth scavenging code out of mheap.grow, where the heap lock is held, and into allocSpan, just after the lock is released. Releasing the lock during mheap.grow is not feasible if we want to ensure that allocation always makes progress (post-growth, another allocator could come in and take all that space, forcing the goroutine that just grew the heap to do so again). This change means that the scavenger now must do more work for each scavenge, but it is also now much more scalable. Although in theory it's not great by always taking the locked paths in the page allocator, it takes advantage of some properties of the allocator: * Most of the time, the scavenger will be working with one page at a time. The page allocator's locked path is optimized for this case. * On the allocation path, it doesn't need to do the find operation at all; it can go straight to setting bits for the range and updating the summary structure. Change-Id: Ie941d5e7c05dcc96476795c63fef74bcafc2a0f1 Reviewed-on: https://go-review.googlesource.com/c/go/+/353974 Trust: Michael Knyszek Reviewed-by: Michael Pratt --- src/runtime/export_test.go | 10 +- src/runtime/lockrank.go | 25 ++-- src/runtime/mgcscavenge.go | 228 +++++++++++++++----------------- src/runtime/mgcscavenge_test.go | 10 +- src/runtime/mheap.go | 63 +++++---- src/runtime/mpagealloc.go | 28 +++- 6 files changed, 187 insertions(+), 177 deletions(-) diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index 5149252c83..b2e64f14ad 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -796,21 +796,17 @@ func (p *PageAlloc) Free(base, npages uintptr) { // None of the tests need any higher-level locking, so we just // take the lock internally. lock(pp.mheapLock) - pp.free(base, npages) + pp.free(base, npages, true) unlock(pp.mheapLock) }) } func (p *PageAlloc) Bounds() (ChunkIdx, ChunkIdx) { return ChunkIdx((*pageAlloc)(p).start), ChunkIdx((*pageAlloc)(p).end) } -func (p *PageAlloc) Scavenge(nbytes uintptr, mayUnlock bool) (r uintptr) { +func (p *PageAlloc) Scavenge(nbytes uintptr) (r uintptr) { pp := (*pageAlloc)(p) systemstack(func() { - // None of the tests need any higher-level locking, so we just - // take the lock internally. - lock(pp.mheapLock) - r = pp.scavenge(nbytes, mayUnlock) - unlock(pp.mheapLock) + r = pp.scavenge(nbytes) }) return } diff --git a/src/runtime/lockrank.go b/src/runtime/lockrank.go index 54b0f4ce9c..4a16bc0ddb 100644 --- a/src/runtime/lockrank.go +++ b/src/runtime/lockrank.go @@ -80,6 +80,7 @@ const ( // Memory-related leaf locks lockRankGlobalAlloc + lockRankPageAllocScav // Other leaf locks lockRankGFree @@ -157,7 +158,8 @@ var lockNames = []string{ lockRankMheap: "mheap", lockRankMheapSpecial: "mheapSpecial", - lockRankGlobalAlloc: "globalAlloc.mutex", + lockRankGlobalAlloc: "globalAlloc.mutex", + lockRankPageAllocScav: "pageAlloc.scav.lock", lockRankGFree: "gFree", lockRankHchanLeaf: "hchanLeaf", @@ -223,16 +225,17 @@ var lockPartialOrder [][]lockRank = [][]lockRank{ lockRankRwmutexW: {}, lockRankRwmutexR: {lockRankSysmon, lockRankRwmutexW}, - lockRankSpanSetSpine: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings}, - lockRankGscan: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankSpanSetSpine}, - lockRankStackpool: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankRwmutexR, lockRankSpanSetSpine, lockRankGscan}, - lockRankStackLarge: {lockRankSysmon, lockRankAssistQueue, lockRankSched, lockRankItab, lockRankHchan, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankSpanSetSpine, lockRankGscan}, - lockRankDefer: {}, - lockRankSudog: {lockRankHchan, lockRankNotifyList}, - lockRankWbufSpans: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankRoot, lockRankGscan, lockRankDefer, lockRankSudog}, - lockRankMheap: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankSpanSetSpine, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankDefer, lockRankSudog, lockRankWbufSpans}, - lockRankMheapSpecial: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings}, - lockRankGlobalAlloc: {lockRankProf, lockRankSpanSetSpine, lockRankMheap, lockRankMheapSpecial}, + lockRankSpanSetSpine: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings}, + lockRankGscan: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankSpanSetSpine}, + lockRankStackpool: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankRwmutexR, lockRankSpanSetSpine, lockRankGscan}, + lockRankStackLarge: {lockRankSysmon, lockRankAssistQueue, lockRankSched, lockRankItab, lockRankHchan, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankSpanSetSpine, lockRankGscan}, + lockRankDefer: {}, + lockRankSudog: {lockRankHchan, lockRankNotifyList}, + lockRankWbufSpans: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankRoot, lockRankGscan, lockRankDefer, lockRankSudog}, + lockRankMheap: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankSpanSetSpine, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankDefer, lockRankSudog, lockRankWbufSpans}, + lockRankMheapSpecial: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings}, + lockRankGlobalAlloc: {lockRankProf, lockRankSpanSetSpine, lockRankMheap, lockRankMheapSpecial}, + lockRankPageAllocScav: {lockRankMheap}, lockRankGFree: {lockRankSched}, lockRankHchanLeaf: {lockRankGscan, lockRankHchanLeaf}, diff --git a/src/runtime/mgcscavenge.go b/src/runtime/mgcscavenge.go index 4edeb8739e..72ec81e5e3 100644 --- a/src/runtime/mgcscavenge.go +++ b/src/runtime/mgcscavenge.go @@ -289,30 +289,17 @@ func bgscavenge(c chan int) { for { released := uintptr(0) - - // Time in scavenging critical section. crit := float64(0) - // Run on the system stack since we grab the heap lock, - // and a stack growth with the heap lock means a deadlock. - systemstack(func() { - lock(&mheap_.lock) - - // If background scavenging is disabled or if there's no work to do just park. - retained, goal := heapRetained(), atomic.Load64(&mheap_.scavengeGoal) - if retained <= goal { - unlock(&mheap_.lock) - return - } - + // If background scavenging is disabled or if there's no work to do just park. + retained, goal := heapRetained(), atomic.Load64(&mheap_.scavengeGoal) + if retained > goal { // Scavenge one page, and measure the amount of time spent scavenging. start := nanotime() - released = mheap_.pages.scavenge(physPageSize, true) - mheap_.pages.scav.released += released + released = mheap_.pages.scavenge(physPageSize) + atomic.Xadduintptr(&mheap_.pages.scav.released, released) crit = float64(nanotime() - start) - - unlock(&mheap_.lock) - }) + } if released == 0 { lock(&scavenge.lock) @@ -395,16 +382,7 @@ func bgscavenge(c chan int) { // back to the top of the heap. // // Returns the amount of memory scavenged in bytes. -// -// p.mheapLock must be held, but may be temporarily released if -// mayUnlock == true. -// -// Must run on the system stack because p.mheapLock must be held. -// -//go:systemstack -func (p *pageAlloc) scavenge(nbytes uintptr, mayUnlock bool) uintptr { - assertLockHeld(p.mheapLock) - +func (p *pageAlloc) scavenge(nbytes uintptr) uintptr { var ( addrs addrRange gen uint32 @@ -416,9 +394,11 @@ func (p *pageAlloc) scavenge(nbytes uintptr, mayUnlock bool) uintptr { break } } - r, a := p.scavengeOne(addrs, nbytes-released, mayUnlock) - released += r - addrs = a + systemstack(func() { + r, a := p.scavengeOne(addrs, nbytes-released) + released += r + addrs = a + }) } // Only unreserve the space which hasn't been scavenged or searched // to ensure we always make progress. @@ -456,8 +436,9 @@ func printScavTrace(gen uint32, released uintptr, forced bool) { func (p *pageAlloc) scavengeStartGen() { assertLockHeld(p.mheapLock) + lock(&p.scav.lock) if debug.scavtrace > 0 { - printScavTrace(p.scav.gen, p.scav.released, false) + printScavTrace(p.scav.gen, atomic.Loaduintptr(&p.scav.released), false) } p.inUse.cloneInto(&p.scav.inUse) @@ -487,9 +468,10 @@ func (p *pageAlloc) scavengeStartGen() { // arena in size, so virtually every heap has the scavenger on. p.scav.reservationBytes = alignUp(p.inUse.totalBytes, pallocChunkBytes) / scavengeReservationShards p.scav.gen++ - p.scav.released = 0 + atomic.Storeuintptr(&p.scav.released, 0) p.scav.freeHWM = minOffAddr p.scav.scavLWM = maxOffAddr + unlock(&p.scav.lock) } // scavengeReserve reserves a contiguous range of the address space @@ -498,14 +480,9 @@ func (p *pageAlloc) scavengeStartGen() { // first. // // Returns the reserved range and the scavenge generation number for it. -// -// p.mheapLock must be held. -// -// Must run on the system stack because p.mheapLock must be held. -// -//go:systemstack func (p *pageAlloc) scavengeReserve() (addrRange, uint32) { - assertLockHeld(p.mheapLock) + lock(&p.scav.lock) + gen := p.scav.gen // Start by reserving the minimum. r := p.scav.inUse.removeLast(p.scav.reservationBytes) @@ -513,7 +490,8 @@ func (p *pageAlloc) scavengeReserve() (addrRange, uint32) { // Return early if the size is zero; we don't want to use // the bogus address below. if r.size() == 0 { - return r, p.scav.gen + unlock(&p.scav.lock) + return r, gen } // The scavenger requires that base be aligned to a @@ -524,28 +502,26 @@ func (p *pageAlloc) scavengeReserve() (addrRange, uint32) { // Remove from inUse however much extra we just pulled out. p.scav.inUse.removeGreaterEqual(newBase) + unlock(&p.scav.lock) + r.base = offAddr{newBase} - return r, p.scav.gen + return r, gen } // scavengeUnreserve returns an unscavenged portion of a range that was // previously reserved with scavengeReserve. -// -// p.mheapLock must be held. -// -// Must run on the system stack because p.mheapLock must be held. -// -//go:systemstack func (p *pageAlloc) scavengeUnreserve(r addrRange, gen uint32) { - assertLockHeld(p.mheapLock) - - if r.size() == 0 || gen != p.scav.gen { + if r.size() == 0 { return } if r.base.addr()%pallocChunkBytes != 0 { throw("unreserving unaligned region") } - p.scav.inUse.add(r) + lock(&p.scav.lock) + if gen == p.scav.gen { + p.scav.inUse.add(r) + } + unlock(&p.scav.lock) } // scavengeOne walks over address range work until it finds @@ -559,15 +535,10 @@ func (p *pageAlloc) scavengeUnreserve(r addrRange, gen uint32) { // // work's base address must be aligned to pallocChunkBytes. // -// p.mheapLock must be held, but may be temporarily released if -// mayUnlock == true. -// -// Must run on the system stack because p.mheapLock must be held. +// Must run on the systemstack because it acquires p.mheapLock. // //go:systemstack -func (p *pageAlloc) scavengeOne(work addrRange, max uintptr, mayUnlock bool) (uintptr, addrRange) { - assertLockHeld(p.mheapLock) - +func (p *pageAlloc) scavengeOne(work addrRange, max uintptr) (uintptr, addrRange) { // Defensively check if we've received an empty address range. // If so, just return. if work.size() == 0 { @@ -599,40 +570,12 @@ func (p *pageAlloc) scavengeOne(work addrRange, max uintptr, mayUnlock bool) (ui minPages = 1 } - // Helpers for locking and unlocking only if mayUnlock == true. - lockHeap := func() { - if mayUnlock { - lock(p.mheapLock) - } - } - unlockHeap := func() { - if mayUnlock { - unlock(p.mheapLock) - } - } - - // Fast path: check the chunk containing the top-most address in work, - // starting at that address's page index in the chunk. - // - // Note that work.end() is exclusive, so get the chunk we care about - // by subtracting 1. - maxAddr := work.limit.addr() - 1 - maxChunk := chunkIndex(maxAddr) - if p.summary[len(p.summary)-1][maxChunk].max() >= uint(minPages) { - // We only bother looking for a candidate if there at least - // minPages free pages at all. - base, npages := p.chunkOf(maxChunk).findScavengeCandidate(chunkPageIndex(maxAddr), minPages, maxPages) - - // If we found something, scavenge it and return! - if npages != 0 { - work.limit = offAddr{p.scavengeRangeLocked(maxChunk, base, npages)} - - assertLockHeld(p.mheapLock) // Must be locked on return. - return uintptr(npages) * pageSize, work - } + // Fast path: check the chunk containing the top-most address in work. + if r, w := p.scavengeOneFast(work, minPages, maxPages); r != 0 { + return r, w + } else { + work = w } - // Update the limit to reflect the fact that we checked maxChunk already. - work.limit = offAddr{chunkBase(maxChunk)} // findCandidate finds the next scavenge candidate in work optimistically. // @@ -671,37 +614,61 @@ func (p *pageAlloc) scavengeOne(work addrRange, max uintptr, mayUnlock bool) (ui // looking for any free and unscavenged page. If we think we see something, // lock and verify it! for work.size() != 0 { - unlockHeap() // Search for the candidate. candidateChunkIdx, ok := findCandidate(work) - - // Lock the heap. We need to do this now if we found a candidate or not. - // If we did, we'll verify it. If not, we need to lock before returning - // anyway. - lockHeap() - if !ok { // We didn't find a candidate, so we're done. work.limit = work.base break } + // Lock, so we can verify what we found. + lock(p.mheapLock) + // Find, verify, and scavenge if we can. chunk := p.chunkOf(candidateChunkIdx) base, npages := chunk.findScavengeCandidate(pallocChunkPages-1, minPages, maxPages) if npages > 0 { work.limit = offAddr{p.scavengeRangeLocked(candidateChunkIdx, base, npages)} - - assertLockHeld(p.mheapLock) // Must be locked on return. + unlock(p.mheapLock) return uintptr(npages) * pageSize, work } + unlock(p.mheapLock) // We were fooled, so let's continue from where we left off. work.limit = offAddr{chunkBase(candidateChunkIdx)} } + return 0, work +} - assertLockHeld(p.mheapLock) // Must be locked on return. +// scavengeOneFast is the fast path for scavengeOne, which just checks the top +// chunk of work for some pages to scavenge. +// +// Must run on the system stack because it acquires the heap lock. +// +//go:systemstack +func (p *pageAlloc) scavengeOneFast(work addrRange, minPages, maxPages uintptr) (uintptr, addrRange) { + maxAddr := work.limit.addr() - 1 + maxChunk := chunkIndex(maxAddr) + + lock(p.mheapLock) + if p.summary[len(p.summary)-1][maxChunk].max() >= uint(minPages) { + // We only bother looking for a candidate if there at least + // minPages free pages at all. + base, npages := p.chunkOf(maxChunk).findScavengeCandidate(chunkPageIndex(maxAddr), minPages, maxPages) + + // If we found something, scavenge it and return! + if npages != 0 { + work.limit = offAddr{p.scavengeRangeLocked(maxChunk, base, npages)} + unlock(p.mheapLock) + return uintptr(npages) * pageSize, work + } + } + unlock(p.mheapLock) + + // Update the limit to reflect the fact that we checked maxChunk already. + work.limit = offAddr{chunkBase(maxChunk)} return 0, work } @@ -712,38 +679,57 @@ func (p *pageAlloc) scavengeOne(work addrRange, max uintptr, mayUnlock bool) (ui // // Returns the base address of the scavenged region. // -// p.mheapLock must be held. +// p.mheapLock must be held. Unlocks p.mheapLock but reacquires +// it before returning. Must be run on the systemstack as a result. +// +//go:systemstack func (p *pageAlloc) scavengeRangeLocked(ci chunkIdx, base, npages uint) uintptr { assertLockHeld(p.mheapLock) - p.chunkOf(ci).scavenged.setRange(base, npages) - // Compute the full address for the start of the range. addr := chunkBase(ci) + uintptr(base)*pageSize + // Mark the range we're about to scavenge as allocated, because + // we don't want any allocating goroutines to grab it while + // the scavenging is in progress. + if scav := p.allocRange(addr, uintptr(npages)); scav != 0 { + throw("double scavenge") + } + + // With that done, it's safe to unlock. + unlock(p.mheapLock) + // Update the scavenge low watermark. + lock(&p.scav.lock) if oAddr := (offAddr{addr}); oAddr.lessThan(p.scav.scavLWM) { p.scav.scavLWM = oAddr } + unlock(&p.scav.lock) - // Only perform the actual scavenging if we're not in a test. - // It's dangerous to do so otherwise. - if p.test { - return addr - } - sysUnused(unsafe.Pointer(addr), uintptr(npages)*pageSize) + if !p.test { + // Only perform the actual scavenging if we're not in a test. + // It's dangerous to do so otherwise. + sysUnused(unsafe.Pointer(addr), uintptr(npages)*pageSize) - // Update global accounting only when not in test, otherwise - // the runtime's accounting will be wrong. - nbytes := int64(npages) * pageSize - atomic.Xadd64(&memstats.heap_released, nbytes) + // Update global accounting only when not in test, otherwise + // the runtime's accounting will be wrong. + nbytes := int64(npages) * pageSize + atomic.Xadd64(&memstats.heap_released, nbytes) - // Update consistent accounting too. - stats := memstats.heapStats.acquire() - atomic.Xaddint64(&stats.committed, -nbytes) - atomic.Xaddint64(&stats.released, nbytes) - memstats.heapStats.release() + // Update consistent accounting too. + stats := memstats.heapStats.acquire() + atomic.Xaddint64(&stats.committed, -nbytes) + atomic.Xaddint64(&stats.released, nbytes) + memstats.heapStats.release() + } + + // Relock the heap, because now we need to make these pages + // available allocation. Free them back to the page allocator. + lock(p.mheapLock) + p.free(addr, uintptr(npages), true) + // Mark the range as scavenged. + p.chunkOf(ci).scavenged.setRange(base, npages) return addr } diff --git a/src/runtime/mgcscavenge_test.go b/src/runtime/mgcscavenge_test.go index 3b12a2e1e6..b186cad2f4 100644 --- a/src/runtime/mgcscavenge_test.go +++ b/src/runtime/mgcscavenge_test.go @@ -430,12 +430,12 @@ func TestPageAllocScavenge(t *testing.T) { } for name, v := range tests { v := v - runTest := func(t *testing.T, mayUnlock bool) { + t.Run(name, func(t *testing.T) { b := NewPageAlloc(v.beforeAlloc, v.beforeScav) defer FreePageAlloc(b) for iter, h := range v.expect { - if got := b.Scavenge(h.request, mayUnlock); got != h.expect { + if got := b.Scavenge(h.request); got != h.expect { t.Fatalf("bad scavenge #%d: want %d, got %d", iter+1, h.expect, got) } } @@ -443,12 +443,6 @@ func TestPageAllocScavenge(t *testing.T) { defer FreePageAlloc(want) checkPageAlloc(t, want, b) - } - t.Run(name, func(t *testing.T) { - runTest(t, false) - }) - t.Run(name+"MayUnlock", func(t *testing.T) { - runTest(t, true) }) } } diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go index f2f6e7f4cf..ecbd0a3a49 100644 --- a/src/runtime/mheap.go +++ b/src/runtime/mheap.go @@ -80,7 +80,7 @@ type mheap struct { // access (since that may free the backing store). allspans []*mspan // all spans out there - _ uint32 // align uint64 fields on 32-bit for atomics + // _ uint32 // align uint64 fields on 32-bit for atomics // Proportional sweep // @@ -1120,6 +1120,7 @@ func (h *mheap) allocSpan(npages uintptr, typ spanAllocType, spanclass spanClass // Function-global state. gp := getg() base, scav := uintptr(0), uintptr(0) + growth := uintptr(0) // On some platforms we need to provide physical page aligned stack // allocations. Where the page size is less than the physical page @@ -1165,7 +1166,9 @@ func (h *mheap) allocSpan(npages uintptr, typ spanAllocType, spanclass spanClass // Try to acquire a base address. base, scav = h.pages.alloc(npages) if base == 0 { - if !h.grow(npages) { + var ok bool + growth, ok = h.grow(npages) + if !ok { unlock(&h.lock) return nil } @@ -1189,16 +1192,35 @@ func (h *mheap) allocSpan(npages uintptr, typ spanAllocType, spanclass spanClass // Return memory around the aligned allocation. spaceBefore := base - allocBase if spaceBefore > 0 { - h.pages.free(allocBase, spaceBefore/pageSize) + h.pages.free(allocBase, spaceBefore/pageSize, false) } spaceAfter := (allocPages-npages)*pageSize - spaceBefore if spaceAfter > 0 { - h.pages.free(base+npages*pageSize, spaceAfter/pageSize) + h.pages.free(base+npages*pageSize, spaceAfter/pageSize, false) } } unlock(&h.lock) + if growth > 0 { + // We just caused a heap growth, so scavenge down what will soon be used. + // By scavenging inline we deal with the failure to allocate out of + // memory fragments by scavenging the memory fragments that are least + // likely to be re-used. + scavengeGoal := atomic.Load64(&h.scavengeGoal) + if retained := heapRetained(); retained+uint64(growth) > scavengeGoal { + // The scavenging algorithm requires the heap lock to be dropped so it + // can acquire it only sparingly. This is a potentially expensive operation + // so it frees up other goroutines to allocate in the meanwhile. In fact, + // they can make use of the growth we just created. + todo := growth + if overage := uintptr(retained + uint64(growth) - scavengeGoal); todo > overage { + todo = overage + } + h.pages.scavenge(todo) + } + } + HaveSpan: // At this point, both s != nil and base != 0, and the heap // lock is no longer held. Initialize the span. @@ -1311,10 +1333,10 @@ HaveSpan: } // Try to add at least npage pages of memory to the heap, -// returning whether it worked. +// returning how much the heap grew by and whether it worked. // // h.lock must be held. -func (h *mheap) grow(npage uintptr) bool { +func (h *mheap) grow(npage uintptr) (uintptr, bool) { assertLockHeld(&h.lock) // We must grow the heap in whole palloc chunks. @@ -1336,7 +1358,7 @@ func (h *mheap) grow(npage uintptr) bool { av, asize := h.sysAlloc(ask) if av == nil { print("runtime: out of memory: cannot allocate ", ask, "-byte block (", memstats.heap_sys, " in use)\n") - return false + return 0, false } if uintptr(av) == h.curArena.end { @@ -1396,20 +1418,7 @@ func (h *mheap) grow(npage uintptr) bool { // space ready for allocation. h.pages.grow(v, nBase-v) totalGrowth += nBase - v - - // We just caused a heap growth, so scavenge down what will soon be used. - // By scavenging inline we deal with the failure to allocate out of - // memory fragments by scavenging the memory fragments that are least - // likely to be re-used. - scavengeGoal := atomic.Load64(&h.scavengeGoal) - if retained := heapRetained(); retained+uint64(totalGrowth) > scavengeGoal { - todo := totalGrowth - if overage := uintptr(retained + uint64(totalGrowth) - scavengeGoal); todo > overage { - todo = overage - } - h.pages.scavenge(todo, false) - } - return true + return totalGrowth, true } // Free the span back into the heap. @@ -1499,7 +1508,7 @@ func (h *mheap) freeSpanLocked(s *mspan, typ spanAllocType) { memstats.heapStats.release() // Mark the space as free. - h.pages.free(s.base(), s.npages) + h.pages.free(s.base(), s.npages, false) // Free the span structure. We no longer have a use for it. s.state.set(mSpanDead) @@ -1515,13 +1524,19 @@ func (h *mheap) scavengeAll() { // the mheap API. gp := getg() gp.m.mallocing++ + lock(&h.lock) // Start a new scavenge generation so we have a chance to walk // over the whole heap. h.pages.scavengeStartGen() - released := h.pages.scavenge(^uintptr(0), false) - gen := h.pages.scav.gen unlock(&h.lock) + + released := h.pages.scavenge(^uintptr(0)) + + lock(&h.pages.scav.lock) + gen := h.pages.scav.gen + unlock(&h.pages.scav.lock) + gp.m.mallocing-- if debug.scavtrace > 0 { diff --git a/src/runtime/mpagealloc.go b/src/runtime/mpagealloc.go index 862882cd82..2725e3b7c7 100644 --- a/src/runtime/mpagealloc.go +++ b/src/runtime/mpagealloc.go @@ -226,6 +226,8 @@ type pageAlloc struct { // are currently available. Otherwise one might iterate over unused // ranges. // + // Protected by mheapLock. + // // TODO(mknyszek): Consider changing the definition of the bitmap // such that 1 means free and 0 means in-use so that summaries and // the bitmaps align better on zero-values. @@ -261,29 +263,41 @@ type pageAlloc struct { inUse addrRanges // scav stores the scavenger state. - // - // All fields are protected by mheapLock. scav struct { + lock mutex + // inUse is a slice of ranges of address space which have not // yet been looked at by the scavenger. + // + // Protected by lock. inUse addrRanges // gen is the scavenge generation number. + // + // Protected by lock. gen uint32 // reservationBytes is how large of a reservation should be made // in bytes of address space for each scavenge iteration. + // + // Protected by lock. reservationBytes uintptr // released is the amount of memory released this generation. + // + // Updated atomically. released uintptr // scavLWM is the lowest (offset) address that the scavenger reached this // scavenge generation. + // + // Protected by lock. scavLWM offAddr // freeHWM is the highest (offset) address of a page that was freed to // the page allocator this scavenge generation. + // + // Protected by mheapLock. freeHWM offAddr } @@ -864,17 +878,19 @@ Found: // Must run on the system stack because p.mheapLock must be held. // //go:systemstack -func (p *pageAlloc) free(base, npages uintptr) { +func (p *pageAlloc) free(base, npages uintptr, scavenged bool) { assertLockHeld(p.mheapLock) // If we're freeing pages below the p.searchAddr, update searchAddr. if b := (offAddr{base}); b.lessThan(p.searchAddr) { p.searchAddr = b } - // Update the free high watermark for the scavenger. limit := base + npages*pageSize - 1 - if offLimit := (offAddr{limit}); p.scav.freeHWM.lessThan(offLimit) { - p.scav.freeHWM = offLimit + if !scavenged { + // Update the free high watermark for the scavenger. + if offLimit := (offAddr{limit}); p.scav.freeHWM.lessThan(offLimit) { + p.scav.freeHWM = offLimit + } } if npages == 1 { // Fast path: we're clearing a single bit, and we know exactly -- GitLab From f063e0da28d441065d36f7d676f86d478f67db1f Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 18 Oct 2021 19:01:33 +0000 Subject: [PATCH 1994/2500] runtime: add harddecommit GODEBUG flag This change adds a new debug flag that makes the runtime map pages PROT_NONE in sysUnused on Linux, in addition to the usual madvise calls. This behavior mimics the behavior of decommit on Windows, and is helpful in debugging the scavenger. sysUsed is also updated to re-map the pages as PROT_READ|PROT_WRITE, mimicing Windows' explicit commit behavior. Change-Id: Iaac5fcd0e6920bd1d0e753dd4e7f0c0b128fe842 Reviewed-on: https://go-review.googlesource.com/c/go/+/356612 Trust: Michael Knyszek Reviewed-by: Michael Pratt --- src/runtime/extern.go | 5 +++++ src/runtime/mem_linux.go | 20 ++++++++++++++++++++ src/runtime/runtime1.go | 2 ++ 3 files changed, 27 insertions(+) diff --git a/src/runtime/extern.go b/src/runtime/extern.go index b2003ba543..f1f6ea5123 100644 --- a/src/runtime/extern.go +++ b/src/runtime/extern.go @@ -78,6 +78,11 @@ It is a comma-separated list of name=val pairs setting these named variables: If the line ends with "(forced)", this GC was forced by a runtime.GC() call. + harddecommit: setting harddecommit=1 causes memory that is returned to the OS to + also have protections removed on it. This is the only mode of operation on Windows, + but is helpful in debugging scavenger-related issues on other platforms. Currently, + only supported on Linux. + inittrace: setting inittrace=1 causes the runtime to emit a single line to standard error for each package with init work, summarizing the execution time and memory allocation. No information is printed for inits executed as part of plugin loading diff --git a/src/runtime/mem_linux.go b/src/runtime/mem_linux.go index 3436851091..f8f9c53170 100644 --- a/src/runtime/mem_linux.go +++ b/src/runtime/mem_linux.go @@ -114,9 +114,29 @@ func sysUnused(v unsafe.Pointer, n uintptr) { atomic.Store(&adviseUnused, _MADV_DONTNEED) madvise(v, n, _MADV_DONTNEED) } + + if debug.harddecommit > 0 { + p, err := mmap(v, n, _PROT_NONE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, -1, 0) + if p != v || err != 0 { + throw("runtime: cannot disable permissions in address space") + } + } } func sysUsed(v unsafe.Pointer, n uintptr) { + if debug.harddecommit > 0 { + p, err := mmap(v, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, -1, 0) + if err == _ENOMEM { + throw("runtime: out of memory") + } + if p != v || err != 0 { + throw("runtime: cannot remap pages in address space") + } + return + + // Don't do the sysHugePage optimization in hard decommit mode. + // We're breaking up pages everywhere, there's no point. + } // Partially undo the NOHUGEPAGE marks from sysUnused // for whole huge pages between v and v+n. This may // leave huge pages off at the end points v and v+n diff --git a/src/runtime/runtime1.go b/src/runtime/runtime1.go index b6c3cbfff4..65e1e0eebc 100644 --- a/src/runtime/runtime1.go +++ b/src/runtime/runtime1.go @@ -315,6 +315,7 @@ var debug struct { schedtrace int32 tracebackancestors int32 asyncpreemptoff int32 + harddecommit int32 // debug.malloc is used as a combined debug check // in the malloc function and should be set @@ -344,6 +345,7 @@ var dbgvars = []dbgVar{ {"tracebackancestors", &debug.tracebackancestors}, {"asyncpreemptoff", &debug.asyncpreemptoff}, {"inittrace", &debug.inittrace}, + {"harddecommit", &debug.harddecommit}, } func parsedebugvars() { -- GitLab From e48e4b4cbbe270bc43e4209dce10c9225254aa64 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 4 Oct 2021 21:44:06 +0000 Subject: [PATCH 1995/2500] runtime: use a controller to control the scavenge rate Currently the scavenge rate is determined by a bunch of ad-hoc mechanisms. Just use a controller instead, now that we have one. To facilitate this, the scavenger now attempts to scavenge for at least 1 ms at a time, because any less and the timer system is too imprecise to give useful feedback to the controller. Also increase the amount that we scavenge at once, to try to reduce the overheads involved (at the expense of a little bit of latency). This change also modifies the controller to accept an update period, because it's useful to allow that to be variable. Change-Id: I8a15b2355d0a7c6cbac68c957082d5819618f7d7 Reviewed-on: https://go-review.googlesource.com/c/go/+/353975 Trust: Michael Knyszek Reviewed-by: Michael Pratt --- src/runtime/mgcpacer.go | 15 ++-- src/runtime/mgcscavenge.go | 159 +++++++++++++++++++++---------------- 2 files changed, 96 insertions(+), 78 deletions(-) diff --git a/src/runtime/mgcpacer.go b/src/runtime/mgcpacer.go index 230e78b000..5b699cb298 100644 --- a/src/runtime/mgcpacer.go +++ b/src/runtime/mgcpacer.go @@ -349,9 +349,6 @@ func (c *gcControllerState) init(gcPercent int32) { kp: 0.9, ti: 4.0, - // An update is done once per GC cycle. - period: 1, - // Set a high reset time in GC cycles. // This is inversely proportional to the rate at which we // accumulate error from clipping. By making this very high @@ -677,8 +674,9 @@ func (c *gcControllerState) endCycle(now int64, procs int, userForced bool) floa (float64(scanWork) * (1 - utilization)) // Update cons/mark controller. + // Period for this is 1 GC cycle. oldConsMark := c.consMark - c.consMark = c.consMarkController.next(c.consMark, currentConsMark) + c.consMark = c.consMarkController.next(c.consMark, currentConsMark, 1.0) if debug.gcpacertrace > 0 { printlock() @@ -1259,10 +1257,7 @@ func readGOGC() int32 { type piController struct { kp float64 // Proportional constant. ti float64 // Integral time constant. - tt float64 // Reset time in GC cyles. - - // Period in GC cycles between updates. - period float64 + tt float64 // Reset time. min, max float64 // Output boundaries. @@ -1271,7 +1266,7 @@ type piController struct { errIntegral float64 // Integral of the error from t=0 to now. } -func (c *piController) next(input, setpoint float64) float64 { +func (c *piController) next(input, setpoint, period float64) float64 { // Compute the raw output value. prop := c.kp * (setpoint - input) rawOutput := prop + c.errIntegral @@ -1286,7 +1281,7 @@ func (c *piController) next(input, setpoint float64) float64 { // Update the controller's state. if c.ti != 0 && c.tt != 0 { - c.errIntegral += (c.kp*c.period/c.ti)*(setpoint-input) + (c.period/c.tt)*(output-rawOutput) + c.errIntegral += (c.kp*period/c.ti)*(setpoint-input) + (period/c.tt)*(output-rawOutput) } return output } diff --git a/src/runtime/mgcscavenge.go b/src/runtime/mgcscavenge.go index 72ec81e5e3..a2a88e94d2 100644 --- a/src/runtime/mgcscavenge.go +++ b/src/runtime/mgcscavenge.go @@ -270,35 +270,85 @@ func bgscavenge(c chan int) { c <- 1 goparkunlock(&scavenge.lock, waitReasonGCScavengeWait, traceEvGoBlock, 1) - // Exponentially-weighted moving average of the fraction of time this - // goroutine spends scavenging (that is, percent of a single CPU). - // It represents a measure of scheduling overheads which might extend - // the sleep or the critical time beyond what's expected. Assume no - // overhead to begin with. + // idealFraction is the ideal % of overall application CPU time that we + // spend scavenging. // - // TODO(mknyszek): Consider making this based on total CPU time of the - // application (i.e. scavengePercent * GOMAXPROCS). This isn't really - // feasible now because the scavenger acquires the heap lock over the - // scavenging operation, which means scavenging effectively blocks - // allocators and isn't scalable. However, given a scalable allocator, - // it makes sense to also make the scavenger scale with it; if you're - // allocating more frequently, then presumably you're also generating - // more work for the scavenger. - const idealFraction = scavengePercent / 100.0 - scavengeEWMA := float64(idealFraction) - + // TODO(mknyszek): Currently this is percent of one CPU (hence the division + // by gomaxprocs), but ideally this should be 1% of overall CPU time. + // Given a scalable memory allocator, it makes sense that the scavenger + // should scale with it; if you're allocating more frequently, then presumably + // you're also generating more work from the scavenger. + idealFraction := float64(scavengePercent) / 100.0 / float64(gomaxprocs) + + // Input: fraction of CPU time used. + // Setpoint: idealFraction. + // Output: ratio of critical time to sleep time (determines sleep time). + // + // The output of this controller is somewhat indirect to what we actually + // want to achieve: how much time to sleep for. The reason for this definition + // is to ensure that the controller's outputs have a direct relationship with + // its inputs (as opposed to an inverse relationship), making it somewhat + // easier to reason about for tuning purposes. + critSleepController := piController{ + // Tuned loosely via Ziegler-Nichols process. + kp: 0.3375, + ti: 3.2e6, + tt: 1e9, // 1 second reset time. + + // These ranges seem wide, but we want to give the controller plenty of + // room to hunt for the optimal value. + min: 0.001, // 1:1000 + max: 1000.0, // 1000:1 + } + // It doesn't really matter what value we start at, but we can't be zero, because + // that'll cause divide-by-zero issues. + critSleepRatio := 0.001 for { released := uintptr(0) crit := float64(0) - // If background scavenging is disabled or if there's no work to do just park. - retained, goal := heapRetained(), atomic.Load64(&mheap_.scavengeGoal) - if retained > goal { - // Scavenge one page, and measure the amount of time spent scavenging. + // Spend at least 1 ms scavenging, otherwise the corresponding + // sleep time to maintain our desired utilization is too low to + // be reliable. + const minCritTime = 1e6 + for crit < minCritTime { + // If background scavenging is disabled or if there's no work to do just park. + retained, goal := heapRetained(), atomic.Load64(&mheap_.scavengeGoal) + if retained <= goal { + break + } + + // scavengeQuantum is the amount of memory we try to scavenge + // in one go. A smaller value means the scavenger is more responsive + // to the scheduler in case of e.g. preemption. A larger value means + // that the overheads of scavenging are better amortized, so better + // scavenging throughput. + // + // The current value is chosen assuming a cost of ~10µs/physical page + // (this is somewhat pessimistic), which implies a worst-case latency of + // about 160µs for 4 KiB physical pages. The current value is biased + // toward latency over throughput. + const scavengeQuantum = 64 << 10 + + // Accumulate the amount of time spent scavenging. start := nanotime() - released = mheap_.pages.scavenge(physPageSize) + released = mheap_.pages.scavenge(scavengeQuantum) atomic.Xadduintptr(&mheap_.pages.scav.released, released) - crit = float64(nanotime() - start) + end := nanotime() + + // On some platforms we may see end >= start if the time it takes to scavenge + // memory is less than the minimum granularity of its clock (e.g. Windows) or + // due to clock bugs. + // + // In this case, just assume scavenging takes 10 µs per regular physical page + // (determined empirically), and conservatively ignore the impact of huge pages + // on timing. + const approxCritNSPerPhysicalPage = 10e3 + if end <= start { + crit += approxCritNSPerPhysicalPage * float64(released/physPageSize) + } else { + crit += float64(end - start) + } } if released == 0 { @@ -316,18 +366,13 @@ func bgscavenge(c chan int) { throw("released less than one physical page of memory") } - // On some platforms we may see crit as zero if the time it takes to scavenge - // memory is less than the minimum granularity of its clock (e.g. Windows). - // In this case, just assume scavenging takes 10 µs per regular physical page - // (determined empirically), and conservatively ignore the impact of huge pages - // on timing. - // - // We shouldn't ever see a crit value less than zero unless there's a bug of - // some kind, either on our side or in the platform we're running on, but be - // defensive in that case as well. - const approxCritNSPerPhysicalPage = 10e3 - if crit <= 0 { - crit = approxCritNSPerPhysicalPage * float64(released/physPageSize) + if crit < minCritTime { + // This means there wasn't enough work to actually fill up minCritTime. + // That's fine; we shouldn't try to do anything with this information + // because it's going result in a short enough sleep request that things + // will get messy. Just assume we did at least this much work. + // All this means is that we'll sleep longer than we otherwise would have. + crit = minCritTime } // Multiply the critical time by 1 + the ratio of the costs of using @@ -338,41 +383,19 @@ func bgscavenge(c chan int) { // because of the additional overheads of using scavenged memory. crit *= 1 + scavengeCostRatio - // If we spent more than 10 ms (for example, if the OS scheduled us away, or someone - // put their machine to sleep) in the critical section, bound the time we use to - // calculate at 10 ms to avoid letting the sleep time get arbitrarily high. - const maxCrit = 10e6 - if crit > maxCrit { - crit = maxCrit - } + // Go to sleep for our current sleepNS. + slept := scavengeSleep(int64(crit / critSleepRatio)) - // Compute the amount of time to sleep, assuming we want to use at most - // scavengePercent of CPU time. Take into account scheduling overheads - // that may extend the length of our sleep by multiplying by how far - // off we are from the ideal ratio. For example, if we're sleeping too - // much, then scavengeEMWA < idealFraction, so we'll adjust the sleep time - // down. - adjust := scavengeEWMA / idealFraction - sleepTime := int64(adjust * crit / (scavengePercent / 100.0)) - - // Go to sleep. - slept := scavengeSleep(sleepTime) - - // Compute the new ratio. - fraction := crit / (crit + float64(slept)) - - // Set a lower bound on the fraction. - // Due to OS-related anomalies we may "sleep" for an inordinate amount - // of time. Let's avoid letting the ratio get out of hand by bounding - // the sleep time we use in our EWMA. - const minFraction = 1.0 / 1000.0 - if fraction < minFraction { - fraction = minFraction - } - - // Update scavengeEWMA by merging in the new crit/slept ratio. - const alpha = 0.5 - scavengeEWMA = alpha*fraction + (1-alpha)*scavengeEWMA + // Calculate the CPU time spent. + // + // This may be slightly inaccurate with respect to GOMAXPROCS, but we're + // recomputing this often enough relative to GOMAXPROCS changes in general + // (it only changes when the world is stopped, and not during a GC) that + // that small inaccuracy is in the noise. + cpuFraction := float64(crit) / ((float64(slept) + crit) * float64(gomaxprocs)) + + // Update the critSleepRatio, adjusting until we reach our ideal fraction. + critSleepRatio = critSleepController.next(cpuFraction, idealFraction, float64(slept)+crit) } } -- GitLab From 6f32d2050d7f0a9d0c529a1a7a21aa8c1d63fa20 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 25 Oct 2021 21:49:05 +0000 Subject: [PATCH 1996/2500] runtime: pace the scavenger according to 1% of overall CPU time Currently the scavenger is paced to 1% of 1 CPU because it had scalability problems. As of the last few CLs, that should be largely resolved. This change resolves the TODO and paces the scavenger according to 1% of overall CPU time. This change is made separately to allow it to be more easily rolled back. Change-Id: I1ab4de24ba41c564960701634a128a813c55ece9 Reviewed-on: https://go-review.googlesource.com/c/go/+/358675 Trust: Michael Knyszek Reviewed-by: Michael Pratt --- src/runtime/mgcscavenge.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/runtime/mgcscavenge.go b/src/runtime/mgcscavenge.go index a2a88e94d2..4a7f2465fd 100644 --- a/src/runtime/mgcscavenge.go +++ b/src/runtime/mgcscavenge.go @@ -272,13 +272,7 @@ func bgscavenge(c chan int) { // idealFraction is the ideal % of overall application CPU time that we // spend scavenging. - // - // TODO(mknyszek): Currently this is percent of one CPU (hence the division - // by gomaxprocs), but ideally this should be 1% of overall CPU time. - // Given a scalable memory allocator, it makes sense that the scavenger - // should scale with it; if you're allocating more frequently, then presumably - // you're also generating more work from the scavenger. - idealFraction := float64(scavengePercent) / 100.0 / float64(gomaxprocs) + idealFraction := float64(scavengePercent) / 100.0 // Input: fraction of CPU time used. // Setpoint: idealFraction. -- GitLab From df1837799d418eed6b4921cd1252dd8eae76cd98 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Wed, 3 Nov 2021 18:49:51 +0000 Subject: [PATCH 1997/2500] runtime: make consistentHeapStats acquire/release nosplit consistentHeapStats is updated during a stack allocation, so a stack growth during an acquire or release could cause another acquire to happen before the operation completes fully. This may lead to an invalid sequence number. Fixes #49395. Change-Id: I41ce3393dff80201793e053d4d6394d7b211a5b7 Reviewed-on: https://go-review.googlesource.com/c/go/+/361158 Trust: Michael Knyszek Reviewed-by: Michael Pratt Reviewed-by: Austin Clements --- src/runtime/mstats.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/runtime/mstats.go b/src/runtime/mstats.go index 341ba9a936..c2303e5b8e 100644 --- a/src/runtime/mstats.go +++ b/src/runtime/mstats.go @@ -790,7 +790,15 @@ type consistentHeapStats struct { // // The caller's P must not change between acquire and // release. This also means that the caller should not -// acquire a P or release its P in between. +// acquire a P or release its P in between. A P also must +// not acquire a given consistentHeapStats if it hasn't +// yet released it. +// +// nosplit because a stack growth in this function could +// lead to a stack allocation that could reenter the +// function. +// +//go:nosplit func (m *consistentHeapStats) acquire() *heapStatsDelta { if pp := getg().m.p.ptr(); pp != nil { seq := atomic.Xadd(&pp.statsSeq, 1) @@ -814,6 +822,12 @@ func (m *consistentHeapStats) acquire() *heapStatsDelta { // The caller's P must not change between acquire and // release. This also means that the caller should not // acquire a P or release its P in between. +// +// nosplit because a stack growth in this function could +// lead to a stack allocation that causes another acquire +// before this operation has completed. +// +//go:nosplit func (m *consistentHeapStats) release() { if pp := getg().m.p.ptr(); pp != nil { seq := atomic.Xadd(&pp.statsSeq, 1) -- GitLab From 53bab198d93153f0123cb806ebb2b5c9ebbe8dc7 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 5 Nov 2021 10:11:11 -0400 Subject: [PATCH 1998/2500] runtime: skip TestNoShrinkStackWhileParking on netbsd/arm64 This test appears to deadlock frequently on the only netbsd-arm64 builder we have (netbsd-arm64-bsiegert). Skip the test to provide more useful test coverage for other failures. For #49382 Change-Id: I3be32f58ce1e396f7c69163e70cf58f779f57ac6 Reviewed-on: https://go-review.googlesource.com/c/go/+/361615 Trust: Bryan C. Mills Trust: Benny Siegert Run-TryBot: Bryan C. Mills Reviewed-by: Benny Siegert --- src/runtime/chan_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/runtime/chan_test.go b/src/runtime/chan_test.go index c9ce3ac643..355267c5e3 100644 --- a/src/runtime/chan_test.go +++ b/src/runtime/chan_test.go @@ -624,6 +624,10 @@ func TestShrinkStackDuringBlockedSend(t *testing.T) { } func TestNoShrinkStackWhileParking(t *testing.T) { + if runtime.GOOS == "netbsd" && runtime.GOARCH == "arm64" { + testenv.SkipFlaky(t, 49382) + } + // The goal of this test is to trigger a "racy sudog adjustment" // throw. Basically, there's a window between when a goroutine // becomes available for preemption for stack scanning (and thus, -- GitLab From 93bab8a2f918afa8417f7b46da69c21d643de880 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Sat, 30 Oct 2021 00:27:51 -0400 Subject: [PATCH 1999/2500] crypto/elliptic: port P-224 and P-384 to fiat-crypto MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also, adopt addchain code generation for field inversion, and switch P-521 to Montgomery multiplication, which is significantly slower but allows us to reuse the P-224/P-256/P-384 wrapper code. No one uses P-521 anyway, and it's still faster than it was in Go 1.16. Removed a portion of tests that ran the P-224 vectors against P-256, for some reason. Sadly, fiat-crypto is not fast enough to replace the generic 32-bit P-256 implementation (just yet?). A change in visible behavior is that we literally can't internally operate on invalid curve points anymore (yay!) but the crypto/elliptic API locked us into accepting any pair of integers for Add/Double/ScalarMult and return no error (sigh), although of course that's undefined behavior. Panics are always regretted. Returning nil leads to panics. A fixed point might be exploited. The most reasonable solution felt to return a made up random point, which is not that different from an off-curve point but leaks less. name old time/op new time/op delta pkg:crypto/elliptic goos:darwin goarch:arm64 ScalarBaseMult/P224-8 573µs ± 0% 146µs ± 0% -74.56% (p=0.000 n=7+9) ScalarMult/P224-8 574µs ± 0% 152µs ± 5% -73.58% (p=0.000 n=7+10) MarshalUnmarshal/P224/Uncompressed-8 664ns ± 0% 481ns ± 1% -27.64% (p=0.000 n=8+10) MarshalUnmarshal/P224/Compressed-8 666ns ± 1% 480ns ± 0% -27.92% (p=0.000 n=10+10) pkg:crypto/ecdsa goos:darwin goarch:arm64 Sign/P224-8 597µs ± 0% 169µs ± 2% -71.71% (p=0.000 n=10+9) Verify/P224-8 1.18ms ± 1% 0.32ms ± 5% -72.81% (p=0.000 n=10+10) GenerateKey/P224-8 577µs ± 0% 147µs ± 0% -74.51% (p=0.000 n=8+8) name old time/op new time/op delta pkg:crypto/elliptic goos:darwin goarch:arm64 ScalarBaseMult/P384-8 2.01ms ± 2% 0.50ms ± 0% -75.00% (p=0.000 n=10+8) ScalarMult/P384-8 2.02ms ± 3% 0.51ms ± 3% -74.64% (p=0.000 n=10+10) MarshalUnmarshal/P384/Uncompressed-8 1.09µs ± 1% 0.76µs ± 0% -30.27% (p=0.000 n=10+9) MarshalUnmarshal/P384/Compressed-8 1.08µs ± 0% 0.76µs ± 1% -29.86% (p=0.000 n=8+10) pkg:crypto/ecdsa goos:darwin goarch:arm64 Sign/P384-8 2.06ms ± 1% 0.56ms ± 2% -72.76% (p=0.000 n=10+10) Verify/P384-8 4.06ms ± 2% 1.08ms ± 0% -73.49% (p=0.000 n=10+8) GenerateKey/P384-8 2.01ms ± 1% 0.51ms ± 3% -74.65% (p=0.000 n=10+10) name old time/op new time/op delta pkg:crypto/elliptic goos:darwin goarch:arm64 ScalarBaseMult/P521-8 715µs ± 6% 1525µs ± 4% +113.39% (p=0.000 n=10+10) ScalarMult/P521-8 698µs ± 1% 1543µs ± 1% +120.99% (p=0.000 n=9+9) MarshalUnmarshal/P521/Uncompressed-8 797ns ± 0% 1296ns ± 0% +62.65% (p=0.000 n=10+9) MarshalUnmarshal/P521/Compressed-8 798ns ± 0% 1299ns ± 1% +62.82% (p=0.000 n=8+10) pkg:crypto/ecdsa goos:darwin goarch:arm64 Sign/P521-8 810µs ± 3% 1645µs ± 0% +103.03% (p=0.000 n=10+10) Verify/P521-8 1.42ms ± 1% 3.19ms ± 1% +125.28% (p=0.000 n=10+8) GenerateKey/P521-8 698µs ± 1% 1549µs ± 0% +121.87% (p=0.000 n=10+7) Updates #40171 Change-Id: I34edf5002b5e9fad0ebb6c1e2119fb123ea6d18f Reviewed-on: https://go-review.googlesource.com/c/go/+/360014 Run-TryBot: Filippo Valsorda Trust: Filippo Valsorda Reviewed-by: David Chase Reviewed-by: Julie Qiu TryBot-Result: Go Bot --- .../compile/internal/ssa/stmtlines_test.go | 3 + src/crypto/elliptic/elliptic.go | 32 +- src/crypto/elliptic/elliptic_test.go | 5 +- src/crypto/elliptic/internal/fiat/Dockerfile | 8 +- src/crypto/elliptic/internal/fiat/README | 21 +- .../elliptic/internal/fiat/fiat_test.go | 64 + src/crypto/elliptic/internal/fiat/generate.go | 330 + src/crypto/elliptic/internal/fiat/p224.go | 135 + .../elliptic/internal/fiat/p224_fiat64.go | 1429 ++++ .../elliptic/internal/fiat/p224_invert.go | 87 + src/crypto/elliptic/internal/fiat/p384.go | 135 + .../elliptic/internal/fiat/p384_fiat64.go | 3004 ++++++++ .../elliptic/internal/fiat/p384_invert.go | 102 + src/crypto/elliptic/internal/fiat/p521.go | 170 +- .../elliptic/internal/fiat/p521_fiat64.go | 6141 +++++++++++++---- .../elliptic/internal/fiat/p521_invert.go | 89 + .../elliptic/internal/fiat/p521_test.go | 37 - .../elliptic/internal/nistec/nistec_test.go | 94 + src/crypto/elliptic/internal/nistec/p224.go | 293 + src/crypto/elliptic/internal/nistec/p384.go | 298 + src/crypto/elliptic/internal/nistec/p521.go | 6 +- .../elliptic/internal/nistec/p521_test.go | 44 - src/crypto/elliptic/p224.go | 785 +-- src/crypto/elliptic/p224_test.go | 306 +- src/crypto/elliptic/p256.go | 3 + src/crypto/elliptic/p256_test.go | 19 +- src/crypto/elliptic/p384.go | 141 + src/crypto/elliptic/p521.go | 8 +- 28 files changed, 11284 insertions(+), 2505 deletions(-) create mode 100644 src/crypto/elliptic/internal/fiat/fiat_test.go create mode 100644 src/crypto/elliptic/internal/fiat/generate.go create mode 100644 src/crypto/elliptic/internal/fiat/p224.go create mode 100644 src/crypto/elliptic/internal/fiat/p224_fiat64.go create mode 100644 src/crypto/elliptic/internal/fiat/p224_invert.go create mode 100644 src/crypto/elliptic/internal/fiat/p384.go create mode 100644 src/crypto/elliptic/internal/fiat/p384_fiat64.go create mode 100644 src/crypto/elliptic/internal/fiat/p384_invert.go create mode 100644 src/crypto/elliptic/internal/fiat/p521_invert.go delete mode 100644 src/crypto/elliptic/internal/fiat/p521_test.go create mode 100644 src/crypto/elliptic/internal/nistec/nistec_test.go create mode 100644 src/crypto/elliptic/internal/nistec/p224.go create mode 100644 src/crypto/elliptic/internal/nistec/p384.go delete mode 100644 src/crypto/elliptic/internal/nistec/p521_test.go create mode 100644 src/crypto/elliptic/p384.go diff --git a/src/cmd/compile/internal/ssa/stmtlines_test.go b/src/cmd/compile/internal/ssa/stmtlines_test.go index 90dd261c55..088f9802e6 100644 --- a/src/cmd/compile/internal/ssa/stmtlines_test.go +++ b/src/cmd/compile/internal/ssa/stmtlines_test.go @@ -89,6 +89,9 @@ func TestStmtLines(t *testing.T) { if pkgname == "runtime" { continue } + if pkgname == "crypto/elliptic/internal/fiat" { + continue // golang.org/issue/49372 + } if e.Val(dwarf.AttrStmtList) == nil { continue } diff --git a/src/crypto/elliptic/elliptic.go b/src/crypto/elliptic/elliptic.go index cdde0c4e60..d06a284154 100644 --- a/src/crypto/elliptic/elliptic.go +++ b/src/crypto/elliptic/elliptic.go @@ -85,7 +85,7 @@ func (curve *CurveParams) polynomial(x *big.Int) *big.Int { func (curve *CurveParams) IsOnCurve(x, y *big.Int) bool { // If there is a dedicated constant-time implementation for this curve operation, // use that instead of the generic one. - if specific, ok := matchesSpecificCurve(curve, p224, p521); ok { + if specific, ok := matchesSpecificCurve(curve, p224, p384, p521); ok { return specific.IsOnCurve(x, y) } @@ -128,7 +128,7 @@ func (curve *CurveParams) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big. func (curve *CurveParams) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { // If there is a dedicated constant-time implementation for this curve operation, // use that instead of the generic one. - if specific, ok := matchesSpecificCurve(curve, p224, p521); ok { + if specific, ok := matchesSpecificCurve(curve, p224, p384, p521); ok { return specific.Add(x1, y1, x2, y2) } @@ -218,7 +218,7 @@ func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int func (curve *CurveParams) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { // If there is a dedicated constant-time implementation for this curve operation, // use that instead of the generic one. - if specific, ok := matchesSpecificCurve(curve, p224, p521); ok { + if specific, ok := matchesSpecificCurve(curve, p224, p384, p521); ok { return specific.Double(x1, y1) } @@ -290,7 +290,7 @@ func (curve *CurveParams) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) { // If there is a dedicated constant-time implementation for this curve operation, // use that instead of the generic one. - if specific, ok := matchesSpecificCurve(curve, p224, p256, p521); ok { + if specific, ok := matchesSpecificCurve(curve, p224, p256, p384, p521); ok { return specific.ScalarMult(Bx, By, k) } @@ -313,7 +313,7 @@ func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big. func (curve *CurveParams) ScalarBaseMult(k []byte) (*big.Int, *big.Int) { // If there is a dedicated constant-time implementation for this curve operation, // use that instead of the generic one. - if specific, ok := matchesSpecificCurve(curve, p224, p256, p521); ok { + if specific, ok := matchesSpecificCurve(curve, p224, p256, p384, p521); ok { return specific.ScalarBaseMult(k) } @@ -431,7 +431,6 @@ func UnmarshalCompressed(curve Curve, data []byte) (x, y *big.Int) { } var initonce sync.Once -var p384 *CurveParams func initAll() { initP224() @@ -440,15 +439,16 @@ func initAll() { initP521() } -func initP384() { - // See FIPS 186-3, section D.2.4 - p384 = &CurveParams{Name: "P-384"} - p384.P, _ = new(big.Int).SetString("39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319", 10) - p384.N, _ = new(big.Int).SetString("39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942643", 10) - p384.B, _ = new(big.Int).SetString("b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef", 16) - p384.Gx, _ = new(big.Int).SetString("aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7", 16) - p384.Gy, _ = new(big.Int).SetString("3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f", 16) - p384.BitSize = 384 +// P224 returns a Curve which implements NIST P-224 (FIPS 186-3, section D.2.2), +// also known as secp224r1. The CurveParams.Name of this Curve is "P-224". +// +// Multiple invocations of this function will return the same value, so it can +// be used for equality checks and switch statements. +// +// The cryptographic operations are implemented using constant-time algorithms. +func P224() Curve { + initonce.Do(initAll) + return p224 } // P256 returns a Curve which implements NIST P-256 (FIPS 186-3, section D.2.3), @@ -470,7 +470,7 @@ func P256() Curve { // Multiple invocations of this function will return the same value, so it can // be used for equality checks and switch statements. // -// The cryptographic operations do not use constant-time algorithms. +// The cryptographic operations are implemented using constant-time algorithms. func P384() Curve { initonce.Do(initAll) return p384 diff --git a/src/crypto/elliptic/elliptic_test.go b/src/crypto/elliptic/elliptic_test.go index d30a6939a4..f5b36f75ca 100644 --- a/src/crypto/elliptic/elliptic_test.go +++ b/src/crypto/elliptic/elliptic_test.go @@ -14,9 +14,8 @@ import ( // genericParamsForCurve returns the dereferenced CurveParams for // the specified curve. This is used to avoid the logic for -// upgrading a curve to it's specific implementation, forcing -// usage of the generic implementation. This is only relevant -// for the P224, P256, and P521 curves. +// upgrading a curve to its specific implementation, forcing +// usage of the generic implementation. func genericParamsForCurve(c Curve) *CurveParams { d := *(c.Params()) return &d diff --git a/src/crypto/elliptic/internal/fiat/Dockerfile b/src/crypto/elliptic/internal/fiat/Dockerfile index 7b5ece0e30..2877e0b2c1 100644 --- a/src/crypto/elliptic/internal/fiat/Dockerfile +++ b/src/crypto/elliptic/internal/fiat/Dockerfile @@ -4,9 +4,9 @@ FROM coqorg/coq:8.13.2 -RUN git clone https://github.com/mit-plv/fiat-crypto -RUN cd fiat-crypto && git checkout c076f3550bea2bb7f4cb5766a32594b9e67694f2 -RUN cd fiat-crypto && git submodule update --init --recursive +RUN git clone https://github.com/mit-plv/fiat-crypto && cd fiat-crypto && \ + git checkout 23d2dbc4ab897d14bde4404f70cd6991635f9c01 && \ + git submodule update --init --recursive RUN cd fiat-crypto && eval $(opam env) && make -j4 standalone-ocaml SKIP_BEDROCK2=1 -ENTRYPOINT ["fiat-crypto/src/ExtractionOCaml/unsaturated_solinas"] +ENV PATH /home/coq/fiat-crypto/src/ExtractionOCaml:$PATH diff --git a/src/crypto/elliptic/internal/fiat/README b/src/crypto/elliptic/internal/fiat/README index 171f57a327..916ebc14ce 100644 --- a/src/crypto/elliptic/internal/fiat/README +++ b/src/crypto/elliptic/internal/fiat/README @@ -1,17 +1,12 @@ The code in this package was autogenerated by the fiat-crypto project -at commit c076f3550 from a formally verified model. - - docker build -t fiat-crypto:c076f3550 . - docker run fiat-crypto:c076f3550 --lang Go --no-wide-int --cmovznz-by-mul \ - --internal-static --public-function-case camelCase --public-type-case camelCase \ - --private-function-case camelCase --private-type-case camelCase \ - --no-prefix-fiat --package-name fiat --doc-text-before-function-name '' \ - --doc-prepend-header 'Code generated by Fiat Cryptography. DO NOT EDIT.' \ - --doc-newline-before-package-declaration p521 64 9 '2^521 - 1' \ - carry_mul carry_square carry add sub to_bytes from_bytes selectznz \ - > p521_fiat64.go - -It comes under the following license. +at version v0.0.9 from a formally verified model, and by the addchain +project at a recent tip version. + + docker build -t fiat-crypto:v0.0.9 . + go install github.com/mmcloughlin/addchain/cmd/addchain@v0.3.1-0.20211027081849-6a7d3decbe08 + ../../../../../bin/go run generate.go + +fiat-crypto code comes under the following license. Copyright (c) 2015-2020 The fiat-crypto Authors. All rights reserved. diff --git a/src/crypto/elliptic/internal/fiat/fiat_test.go b/src/crypto/elliptic/internal/fiat/fiat_test.go new file mode 100644 index 0000000000..9ecd863788 --- /dev/null +++ b/src/crypto/elliptic/internal/fiat/fiat_test.go @@ -0,0 +1,64 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fiat_test + +import ( + "crypto/elliptic/internal/fiat" + "testing" +) + +func BenchmarkMul(b *testing.B) { + b.Run("P224", func(b *testing.B) { + v := new(fiat.P224Element).One() + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + v.Mul(v, v) + } + }) + b.Run("P384", func(b *testing.B) { + v := new(fiat.P384Element).One() + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + v.Mul(v, v) + } + }) + b.Run("P521", func(b *testing.B) { + v := new(fiat.P521Element).One() + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + v.Mul(v, v) + } + }) +} + +func BenchmarkSquare(b *testing.B) { + b.Run("P224", func(b *testing.B) { + v := new(fiat.P224Element).One() + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + v.Square(v) + } + }) + b.Run("P384", func(b *testing.B) { + v := new(fiat.P384Element).One() + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + v.Square(v) + } + }) + b.Run("P521", func(b *testing.B) { + v := new(fiat.P521Element).One() + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + v.Square(v) + } + }) +} diff --git a/src/crypto/elliptic/internal/fiat/generate.go b/src/crypto/elliptic/internal/fiat/generate.go new file mode 100644 index 0000000000..fd8509de45 --- /dev/null +++ b/src/crypto/elliptic/internal/fiat/generate.go @@ -0,0 +1,330 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ignore + +package main + +import ( + "bytes" + "go/format" + "io" + "log" + "os" + "os/exec" + "text/template" +) + +var curves = []struct { + Element string + Prime string + Prefix string + FiatType string + BytesLen int +}{ + { + Element: "P224Element", + Prime: "2^224 - 2^96 + 1", + Prefix: "p224", + FiatType: "[4]uint64", + BytesLen: 28, + }, + // The 32-bit pure Go P-256 in crypto/elliptic is still faster than the + // autogenerated code here, regrettably. + // { + // Element: "P256Element", + // Prime: "2^256 - 2^224 + 2^192 + 2^96 - 1", + // Prefix: "p256", + // FiatType: "[4]uint64", + // BytesLen: 32, + // }, + { + Element: "P384Element", + Prime: "2^384 - 2^128 - 2^96 + 2^32 - 1", + Prefix: "p384", + FiatType: "[6]uint64", + BytesLen: 48, + }, + // Note that unsaturated_solinas would be about 2x faster than + // word_by_word_montgomery for P-521, but this curve is used rarely enough + // that it's not worth carrying unsaturated_solinas support for it. + { + Element: "P521Element", + Prime: "2^521 - 1", + Prefix: "p521", + FiatType: "[9]uint64", + BytesLen: 66, + }, +} + +func main() { + t := template.Must(template.New("montgomery").Parse(tmplWrapper)) + + tmplAddchainFile, err := os.CreateTemp("", "addchain-template") + if err != nil { + log.Fatal(err) + } + defer os.Remove(tmplAddchainFile.Name()) + if _, err := io.WriteString(tmplAddchainFile, tmplAddchain); err != nil { + log.Fatal(err) + } + if err := tmplAddchainFile.Close(); err != nil { + log.Fatal(err) + } + + for _, c := range curves { + log.Printf("Generating %s.go...", c.Prefix) + f, err := os.Create(c.Prefix + ".go") + if err != nil { + log.Fatal(err) + } + if err := t.Execute(f, c); err != nil { + log.Fatal(err) + } + if err := f.Close(); err != nil { + log.Fatal(err) + } + + log.Printf("Generating %s_fiat64.go...", c.Prefix) + cmd := exec.Command("docker", "run", "--rm", "--entrypoint", "word_by_word_montgomery", + "fiat-crypto:v0.0.9", "--lang", "Go", "--no-wide-int", "--cmovznz-by-mul", + "--relax-primitive-carry-to-bitwidth", "32,64", "--internal-static", + "--public-function-case", "camelCase", "--public-type-case", "camelCase", + "--private-function-case", "camelCase", "--private-type-case", "camelCase", + "--doc-text-before-function-name", "", "--doc-newline-before-package-declaration", + "--doc-prepend-header", "Code generated by Fiat Cryptography. DO NOT EDIT.", + "--package-name", "fiat", "--no-prefix-fiat", c.Prefix, "64", c.Prime, + "mul", "square", "add", "sub", "one", "from_montgomery", "to_montgomery", + "selectznz", "to_bytes", "from_bytes") + cmd.Stderr = os.Stderr + out, err := cmd.Output() + if err != nil { + log.Fatal(err) + } + out, err = format.Source(out) + if err != nil { + log.Fatal(err) + } + if err := os.WriteFile(c.Prefix+"_fiat64.go", out, 0644); err != nil { + log.Fatal(err) + } + + log.Printf("Generating %s_invert.go...", c.Prefix) + f, err = os.CreateTemp("", "addchain-"+c.Prefix) + if err != nil { + log.Fatal(err) + } + defer os.Remove(f.Name()) + cmd = exec.Command("addchain", "search", c.Prime+" - 2") + cmd.Stderr = os.Stderr + cmd.Stdout = f + if err := cmd.Run(); err != nil { + log.Fatal(err) + } + if err := f.Close(); err != nil { + log.Fatal(err) + } + cmd = exec.Command("addchain", "gen", "-tmpl", tmplAddchainFile.Name(), f.Name()) + cmd.Stderr = os.Stderr + out, err = cmd.Output() + if err != nil { + log.Fatal(err) + } + out = bytes.Replace(out, []byte("Element"), []byte(c.Element), -1) + out, err = format.Source(out) + if err != nil { + log.Fatal(err) + } + if err := os.WriteFile(c.Prefix+"_invert.go", out, 0644); err != nil { + log.Fatal(err) + } + } +} + +const tmplWrapper = `// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by generate.go. DO NOT EDIT. + +package fiat + +import ( + "crypto/subtle" + "errors" +) + +// {{ .Element }} is an integer modulo {{ .Prime }}. +// +// The zero value is a valid zero element. +type {{ .Element }} struct { + // Values are represented internally always in the Montgomery domain, and + // converted in Bytes and SetBytes. + x {{ .Prefix }}MontgomeryDomainFieldElement +} + +const {{ .Prefix }}ElementLen = {{ .BytesLen }} + +type {{ .Prefix }}UntypedFieldElement = {{ .FiatType }} + +// One sets e = 1, and returns e. +func (e *{{ .Element }}) One() *{{ .Element }} { + {{ .Prefix }}SetOne(&e.x) + return e +} + +// Equal returns 1 if e == t, and zero otherwise. +func (e *{{ .Element }}) Equal(t *{{ .Element }}) int { + eBytes := e.Bytes() + tBytes := t.Bytes() + return subtle.ConstantTimeCompare(eBytes, tBytes) +} + +var {{ .Prefix }}ZeroEncoding = new({{ .Element }}).Bytes() + +// IsZero returns 1 if e == 0, and zero otherwise. +func (e *{{ .Element }}) IsZero() int { + eBytes := e.Bytes() + return subtle.ConstantTimeCompare(eBytes, {{ .Prefix }}ZeroEncoding) +} + +// Set sets e = t, and returns e. +func (e *{{ .Element }}) Set(t *{{ .Element }}) *{{ .Element }} { + e.x = t.x + return e +} + +// Bytes returns the {{ .BytesLen }}-byte big-endian encoding of e. +func (e *{{ .Element }}) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var out [{{ .Prefix }}ElementLen]byte + return e.bytes(&out) +} + +func (e *{{ .Element }}) bytes(out *[{{ .Prefix }}ElementLen]byte) []byte { + var tmp {{ .Prefix }}NonMontgomeryDomainFieldElement + {{ .Prefix }}FromMontgomery(&tmp, &e.x) + {{ .Prefix }}ToBytes(out, (*{{ .Prefix }}UntypedFieldElement)(&tmp)) + {{ .Prefix }}InvertEndianness(out[:]) + return out[:] +} + +// {{ .Prefix }}MinusOneEncoding is the encoding of -1 mod p, so p - 1, the +// highest canonical encoding. It is used by SetBytes to check for non-canonical +// encodings such as p + k, 2p + k, etc. +var {{ .Prefix }}MinusOneEncoding = new({{ .Element }}).Sub( + new({{ .Element }}), new({{ .Element }}).One()).Bytes() + +// SetBytes sets e = v, where v is a big-endian {{ .BytesLen }}-byte encoding, and returns e. +// If v is not {{ .BytesLen }} bytes or it encodes a value higher than {{ .Prime }}, +// SetBytes returns nil and an error, and e is unchanged. +func (e *{{ .Element }}) SetBytes(v []byte) (*{{ .Element }}, error) { + if len(v) != {{ .Prefix }}ElementLen { + return nil, errors.New("invalid {{ .Element }} encoding") + } + for i := range v { + if v[i] < {{ .Prefix }}MinusOneEncoding[i] { + break + } + if v[i] > {{ .Prefix }}MinusOneEncoding[i] { + return nil, errors.New("invalid {{ .Element }} encoding") + } + } + var in [{{ .Prefix }}ElementLen]byte + copy(in[:], v) + {{ .Prefix }}InvertEndianness(in[:]) + var tmp {{ .Prefix }}NonMontgomeryDomainFieldElement + {{ .Prefix }}FromBytes((*{{ .Prefix }}UntypedFieldElement)(&tmp), &in) + {{ .Prefix }}ToMontgomery(&e.x, &tmp) + return e, nil +} + +// Add sets e = t1 + t2, and returns e. +func (e *{{ .Element }}) Add(t1, t2 *{{ .Element }}) *{{ .Element }} { + {{ .Prefix }}Add(&e.x, &t1.x, &t2.x) + return e +} + +// Sub sets e = t1 - t2, and returns e. +func (e *{{ .Element }}) Sub(t1, t2 *{{ .Element }}) *{{ .Element }} { + {{ .Prefix }}Sub(&e.x, &t1.x, &t2.x) + return e +} + +// Mul sets e = t1 * t2, and returns e. +func (e *{{ .Element }}) Mul(t1, t2 *{{ .Element }}) *{{ .Element }} { + {{ .Prefix }}Mul(&e.x, &t1.x, &t2.x) + return e +} + +// Square sets e = t * t, and returns e. +func (e *{{ .Element }}) Square(t *{{ .Element }}) *{{ .Element }} { + {{ .Prefix }}Square(&e.x, &t.x) + return e +} + +// Select sets v to a if cond == 1, and to b if cond == 0. +func (v *{{ .Element }}) Select(a, b *{{ .Element }}, cond int) *{{ .Element }} { + {{ .Prefix }}Selectznz((*{{ .Prefix }}UntypedFieldElement)(&v.x), {{ .Prefix }}Uint1(cond), + (*{{ .Prefix }}UntypedFieldElement)(&b.x), (*{{ .Prefix }}UntypedFieldElement)(&a.x)) + return v +} + +func {{ .Prefix }}InvertEndianness(v []byte) { + for i := 0; i < len(v)/2; i++ { + v[i], v[len(v)-1-i] = v[len(v)-1-i], v[i] + } +} +` + +const tmplAddchain = `// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by {{ .Meta.Name }}. DO NOT EDIT. + +package fiat + +// Invert sets e = 1/x, and returns e. +// +// If x == 0, Invert returns e = 0. +func (e *Element) Invert(x *Element) *Element { + // Inversion is implemented as exponentiation with exponent p − 2. + // The sequence of {{ .Ops.Adds }} multiplications and {{ .Ops.Doubles }} squarings is derived from the + // following addition chain generated with {{ .Meta.Module }} {{ .Meta.ReleaseTag }}. + // + {{- range lines (format .Script) }} + // {{ . }} + {{- end }} + // + + var z = new(Element).Set(e) + {{- range .Program.Temporaries }} + var {{ . }} = new(Element) + {{- end }} + {{ range $i := .Program.Instructions -}} + {{- with add $i.Op }} + {{ $i.Output }}.Mul({{ .X }}, {{ .Y }}) + {{- end -}} + + {{- with double $i.Op }} + {{ $i.Output }}.Square({{ .X }}) + {{- end -}} + + {{- with shift $i.Op -}} + {{- $first := 0 -}} + {{- if ne $i.Output.Identifier .X.Identifier }} + {{ $i.Output }}.Square({{ .X }}) + {{- $first = 1 -}} + {{- end }} + for s := {{ $first }}; s < {{ .S }}; s++ { + {{ $i.Output }}.Square({{ $i.Output }}) + } + {{- end -}} + {{- end }} + + return e.Set(z) +} +` diff --git a/src/crypto/elliptic/internal/fiat/p224.go b/src/crypto/elliptic/internal/fiat/p224.go new file mode 100644 index 0000000000..4dddeb07a4 --- /dev/null +++ b/src/crypto/elliptic/internal/fiat/p224.go @@ -0,0 +1,135 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by generate.go. DO NOT EDIT. + +package fiat + +import ( + "crypto/subtle" + "errors" +) + +// P224Element is an integer modulo 2^224 - 2^96 + 1. +// +// The zero value is a valid zero element. +type P224Element struct { + // Values are represented internally always in the Montgomery domain, and + // converted in Bytes and SetBytes. + x p224MontgomeryDomainFieldElement +} + +const p224ElementLen = 28 + +type p224UntypedFieldElement = [4]uint64 + +// One sets e = 1, and returns e. +func (e *P224Element) One() *P224Element { + p224SetOne(&e.x) + return e +} + +// Equal returns 1 if e == t, and zero otherwise. +func (e *P224Element) Equal(t *P224Element) int { + eBytes := e.Bytes() + tBytes := t.Bytes() + return subtle.ConstantTimeCompare(eBytes, tBytes) +} + +var p224ZeroEncoding = new(P224Element).Bytes() + +// IsZero returns 1 if e == 0, and zero otherwise. +func (e *P224Element) IsZero() int { + eBytes := e.Bytes() + return subtle.ConstantTimeCompare(eBytes, p224ZeroEncoding) +} + +// Set sets e = t, and returns e. +func (e *P224Element) Set(t *P224Element) *P224Element { + e.x = t.x + return e +} + +// Bytes returns the 28-byte big-endian encoding of e. +func (e *P224Element) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var out [p224ElementLen]byte + return e.bytes(&out) +} + +func (e *P224Element) bytes(out *[p224ElementLen]byte) []byte { + var tmp p224NonMontgomeryDomainFieldElement + p224FromMontgomery(&tmp, &e.x) + p224ToBytes(out, (*p224UntypedFieldElement)(&tmp)) + p224InvertEndianness(out[:]) + return out[:] +} + +// p224MinusOneEncoding is the encoding of -1 mod p, so p - 1, the +// highest canonical encoding. It is used by SetBytes to check for non-canonical +// encodings such as p + k, 2p + k, etc. +var p224MinusOneEncoding = new(P224Element).Sub( + new(P224Element), new(P224Element).One()).Bytes() + +// SetBytes sets e = v, where v is a big-endian 28-byte encoding, and returns e. +// If v is not 28 bytes or it encodes a value higher than 2^224 - 2^96 + 1, +// SetBytes returns nil and an error, and e is unchanged. +func (e *P224Element) SetBytes(v []byte) (*P224Element, error) { + if len(v) != p224ElementLen { + return nil, errors.New("invalid P224Element encoding") + } + for i := range v { + if v[i] < p224MinusOneEncoding[i] { + break + } + if v[i] > p224MinusOneEncoding[i] { + return nil, errors.New("invalid P224Element encoding") + } + } + var in [p224ElementLen]byte + copy(in[:], v) + p224InvertEndianness(in[:]) + var tmp p224NonMontgomeryDomainFieldElement + p224FromBytes((*p224UntypedFieldElement)(&tmp), &in) + p224ToMontgomery(&e.x, &tmp) + return e, nil +} + +// Add sets e = t1 + t2, and returns e. +func (e *P224Element) Add(t1, t2 *P224Element) *P224Element { + p224Add(&e.x, &t1.x, &t2.x) + return e +} + +// Sub sets e = t1 - t2, and returns e. +func (e *P224Element) Sub(t1, t2 *P224Element) *P224Element { + p224Sub(&e.x, &t1.x, &t2.x) + return e +} + +// Mul sets e = t1 * t2, and returns e. +func (e *P224Element) Mul(t1, t2 *P224Element) *P224Element { + p224Mul(&e.x, &t1.x, &t2.x) + return e +} + +// Square sets e = t * t, and returns e. +func (e *P224Element) Square(t *P224Element) *P224Element { + p224Square(&e.x, &t.x) + return e +} + +// Select sets v to a if cond == 1, and to b if cond == 0. +func (v *P224Element) Select(a, b *P224Element, cond int) *P224Element { + p224Selectznz((*p224UntypedFieldElement)(&v.x), p224Uint1(cond), + (*p224UntypedFieldElement)(&b.x), (*p224UntypedFieldElement)(&a.x)) + return v +} + +func p224InvertEndianness(v []byte) { + for i := 0; i < len(v)/2; i++ { + v[i], v[len(v)-1-i] = v[len(v)-1-i], v[i] + } +} diff --git a/src/crypto/elliptic/internal/fiat/p224_fiat64.go b/src/crypto/elliptic/internal/fiat/p224_fiat64.go new file mode 100644 index 0000000000..4ece3e9220 --- /dev/null +++ b/src/crypto/elliptic/internal/fiat/p224_fiat64.go @@ -0,0 +1,1429 @@ +// Code generated by Fiat Cryptography. DO NOT EDIT. +// +// Autogenerated: word_by_word_montgomery --lang Go --no-wide-int --cmovznz-by-mul --relax-primitive-carry-to-bitwidth 32,64 --internal-static --public-function-case camelCase --public-type-case camelCase --private-function-case camelCase --private-type-case camelCase --doc-text-before-function-name '' --doc-newline-before-package-declaration --doc-prepend-header 'Code generated by Fiat Cryptography. DO NOT EDIT.' --package-name fiat --no-prefix-fiat p224 64 '2^224 - 2^96 + 1' mul square add sub one from_montgomery to_montgomery selectznz to_bytes from_bytes +// +// curve description: p224 +// +// machine_wordsize = 64 (from "64") +// +// requested operations: mul, square, add, sub, one, from_montgomery, to_montgomery, selectznz, to_bytes, from_bytes +// +// m = 0xffffffffffffffffffffffffffffffff000000000000000000000001 (from "2^224 - 2^96 + 1") +// +// +// +// NOTE: In addition to the bounds specified above each function, all +// +// functions synthesized for this Montgomery arithmetic require the +// +// input to be strictly less than the prime modulus (m), and also +// +// require the input to be in the unique saturated representation. +// +// All functions also ensure that these two properties are true of +// +// return values. +// +// +// +// Computed values: +// +// eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) +// +// bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) +// +// twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) in +// +// if x1 & (2^256-1) < 2^255 then x1 & (2^256-1) else (x1 & (2^256-1)) - 2^256 + +package fiat + +import "math/bits" + +type p224Uint1 uint64 // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927 +type p224Int1 int64 // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927 + +// The type p224MontgomeryDomainFieldElement is a field element in the Montgomery domain. +// +// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +type p224MontgomeryDomainFieldElement [4]uint64 + +// The type p224NonMontgomeryDomainFieldElement is a field element NOT in the Montgomery domain. +// +// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +type p224NonMontgomeryDomainFieldElement [4]uint64 + +// p224CmovznzU64 is a single-word conditional move. +// +// Postconditions: +// out1 = (if arg1 = 0 then arg2 else arg3) +// +// Input Bounds: +// arg1: [0x0 ~> 0x1] +// arg2: [0x0 ~> 0xffffffffffffffff] +// arg3: [0x0 ~> 0xffffffffffffffff] +// Output Bounds: +// out1: [0x0 ~> 0xffffffffffffffff] +func p224CmovznzU64(out1 *uint64, arg1 p224Uint1, arg2 uint64, arg3 uint64) { + x1 := (uint64(arg1) * 0xffffffffffffffff) + x2 := ((x1 & arg3) | ((^x1) & arg2)) + *out1 = x2 +} + +// p224Mul multiplies two field elements in the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// 0 ≤ eval arg2 < m +// Postconditions: +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m +// 0 ≤ eval out1 < m +// +func p224Mul(out1 *p224MontgomeryDomainFieldElement, arg1 *p224MontgomeryDomainFieldElement, arg2 *p224MontgomeryDomainFieldElement) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[0] + var x5 uint64 + var x6 uint64 + x6, x5 = bits.Mul64(x4, arg2[3]) + var x7 uint64 + var x8 uint64 + x8, x7 = bits.Mul64(x4, arg2[2]) + var x9 uint64 + var x10 uint64 + x10, x9 = bits.Mul64(x4, arg2[1]) + var x11 uint64 + var x12 uint64 + x12, x11 = bits.Mul64(x4, arg2[0]) + var x13 uint64 + var x14 uint64 + x13, x14 = bits.Add64(x12, x9, uint64(0x0)) + var x15 uint64 + var x16 uint64 + x15, x16 = bits.Add64(x10, x7, uint64(p224Uint1(x14))) + var x17 uint64 + var x18 uint64 + x17, x18 = bits.Add64(x8, x5, uint64(p224Uint1(x16))) + x19 := (uint64(p224Uint1(x18)) + x6) + var x20 uint64 + _, x20 = bits.Mul64(x11, 0xffffffffffffffff) + var x22 uint64 + var x23 uint64 + x23, x22 = bits.Mul64(x20, 0xffffffff) + var x24 uint64 + var x25 uint64 + x25, x24 = bits.Mul64(x20, 0xffffffffffffffff) + var x26 uint64 + var x27 uint64 + x27, x26 = bits.Mul64(x20, 0xffffffff00000000) + var x28 uint64 + var x29 uint64 + x28, x29 = bits.Add64(x27, x24, uint64(0x0)) + var x30 uint64 + var x31 uint64 + x30, x31 = bits.Add64(x25, x22, uint64(p224Uint1(x29))) + x32 := (uint64(p224Uint1(x31)) + x23) + var x34 uint64 + _, x34 = bits.Add64(x11, x20, uint64(0x0)) + var x35 uint64 + var x36 uint64 + x35, x36 = bits.Add64(x13, x26, uint64(p224Uint1(x34))) + var x37 uint64 + var x38 uint64 + x37, x38 = bits.Add64(x15, x28, uint64(p224Uint1(x36))) + var x39 uint64 + var x40 uint64 + x39, x40 = bits.Add64(x17, x30, uint64(p224Uint1(x38))) + var x41 uint64 + var x42 uint64 + x41, x42 = bits.Add64(x19, x32, uint64(p224Uint1(x40))) + var x43 uint64 + var x44 uint64 + x44, x43 = bits.Mul64(x1, arg2[3]) + var x45 uint64 + var x46 uint64 + x46, x45 = bits.Mul64(x1, arg2[2]) + var x47 uint64 + var x48 uint64 + x48, x47 = bits.Mul64(x1, arg2[1]) + var x49 uint64 + var x50 uint64 + x50, x49 = bits.Mul64(x1, arg2[0]) + var x51 uint64 + var x52 uint64 + x51, x52 = bits.Add64(x50, x47, uint64(0x0)) + var x53 uint64 + var x54 uint64 + x53, x54 = bits.Add64(x48, x45, uint64(p224Uint1(x52))) + var x55 uint64 + var x56 uint64 + x55, x56 = bits.Add64(x46, x43, uint64(p224Uint1(x54))) + x57 := (uint64(p224Uint1(x56)) + x44) + var x58 uint64 + var x59 uint64 + x58, x59 = bits.Add64(x35, x49, uint64(0x0)) + var x60 uint64 + var x61 uint64 + x60, x61 = bits.Add64(x37, x51, uint64(p224Uint1(x59))) + var x62 uint64 + var x63 uint64 + x62, x63 = bits.Add64(x39, x53, uint64(p224Uint1(x61))) + var x64 uint64 + var x65 uint64 + x64, x65 = bits.Add64(x41, x55, uint64(p224Uint1(x63))) + var x66 uint64 + var x67 uint64 + x66, x67 = bits.Add64(uint64(p224Uint1(x42)), x57, uint64(p224Uint1(x65))) + var x68 uint64 + _, x68 = bits.Mul64(x58, 0xffffffffffffffff) + var x70 uint64 + var x71 uint64 + x71, x70 = bits.Mul64(x68, 0xffffffff) + var x72 uint64 + var x73 uint64 + x73, x72 = bits.Mul64(x68, 0xffffffffffffffff) + var x74 uint64 + var x75 uint64 + x75, x74 = bits.Mul64(x68, 0xffffffff00000000) + var x76 uint64 + var x77 uint64 + x76, x77 = bits.Add64(x75, x72, uint64(0x0)) + var x78 uint64 + var x79 uint64 + x78, x79 = bits.Add64(x73, x70, uint64(p224Uint1(x77))) + x80 := (uint64(p224Uint1(x79)) + x71) + var x82 uint64 + _, x82 = bits.Add64(x58, x68, uint64(0x0)) + var x83 uint64 + var x84 uint64 + x83, x84 = bits.Add64(x60, x74, uint64(p224Uint1(x82))) + var x85 uint64 + var x86 uint64 + x85, x86 = bits.Add64(x62, x76, uint64(p224Uint1(x84))) + var x87 uint64 + var x88 uint64 + x87, x88 = bits.Add64(x64, x78, uint64(p224Uint1(x86))) + var x89 uint64 + var x90 uint64 + x89, x90 = bits.Add64(x66, x80, uint64(p224Uint1(x88))) + x91 := (uint64(p224Uint1(x90)) + uint64(p224Uint1(x67))) + var x92 uint64 + var x93 uint64 + x93, x92 = bits.Mul64(x2, arg2[3]) + var x94 uint64 + var x95 uint64 + x95, x94 = bits.Mul64(x2, arg2[2]) + var x96 uint64 + var x97 uint64 + x97, x96 = bits.Mul64(x2, arg2[1]) + var x98 uint64 + var x99 uint64 + x99, x98 = bits.Mul64(x2, arg2[0]) + var x100 uint64 + var x101 uint64 + x100, x101 = bits.Add64(x99, x96, uint64(0x0)) + var x102 uint64 + var x103 uint64 + x102, x103 = bits.Add64(x97, x94, uint64(p224Uint1(x101))) + var x104 uint64 + var x105 uint64 + x104, x105 = bits.Add64(x95, x92, uint64(p224Uint1(x103))) + x106 := (uint64(p224Uint1(x105)) + x93) + var x107 uint64 + var x108 uint64 + x107, x108 = bits.Add64(x83, x98, uint64(0x0)) + var x109 uint64 + var x110 uint64 + x109, x110 = bits.Add64(x85, x100, uint64(p224Uint1(x108))) + var x111 uint64 + var x112 uint64 + x111, x112 = bits.Add64(x87, x102, uint64(p224Uint1(x110))) + var x113 uint64 + var x114 uint64 + x113, x114 = bits.Add64(x89, x104, uint64(p224Uint1(x112))) + var x115 uint64 + var x116 uint64 + x115, x116 = bits.Add64(x91, x106, uint64(p224Uint1(x114))) + var x117 uint64 + _, x117 = bits.Mul64(x107, 0xffffffffffffffff) + var x119 uint64 + var x120 uint64 + x120, x119 = bits.Mul64(x117, 0xffffffff) + var x121 uint64 + var x122 uint64 + x122, x121 = bits.Mul64(x117, 0xffffffffffffffff) + var x123 uint64 + var x124 uint64 + x124, x123 = bits.Mul64(x117, 0xffffffff00000000) + var x125 uint64 + var x126 uint64 + x125, x126 = bits.Add64(x124, x121, uint64(0x0)) + var x127 uint64 + var x128 uint64 + x127, x128 = bits.Add64(x122, x119, uint64(p224Uint1(x126))) + x129 := (uint64(p224Uint1(x128)) + x120) + var x131 uint64 + _, x131 = bits.Add64(x107, x117, uint64(0x0)) + var x132 uint64 + var x133 uint64 + x132, x133 = bits.Add64(x109, x123, uint64(p224Uint1(x131))) + var x134 uint64 + var x135 uint64 + x134, x135 = bits.Add64(x111, x125, uint64(p224Uint1(x133))) + var x136 uint64 + var x137 uint64 + x136, x137 = bits.Add64(x113, x127, uint64(p224Uint1(x135))) + var x138 uint64 + var x139 uint64 + x138, x139 = bits.Add64(x115, x129, uint64(p224Uint1(x137))) + x140 := (uint64(p224Uint1(x139)) + uint64(p224Uint1(x116))) + var x141 uint64 + var x142 uint64 + x142, x141 = bits.Mul64(x3, arg2[3]) + var x143 uint64 + var x144 uint64 + x144, x143 = bits.Mul64(x3, arg2[2]) + var x145 uint64 + var x146 uint64 + x146, x145 = bits.Mul64(x3, arg2[1]) + var x147 uint64 + var x148 uint64 + x148, x147 = bits.Mul64(x3, arg2[0]) + var x149 uint64 + var x150 uint64 + x149, x150 = bits.Add64(x148, x145, uint64(0x0)) + var x151 uint64 + var x152 uint64 + x151, x152 = bits.Add64(x146, x143, uint64(p224Uint1(x150))) + var x153 uint64 + var x154 uint64 + x153, x154 = bits.Add64(x144, x141, uint64(p224Uint1(x152))) + x155 := (uint64(p224Uint1(x154)) + x142) + var x156 uint64 + var x157 uint64 + x156, x157 = bits.Add64(x132, x147, uint64(0x0)) + var x158 uint64 + var x159 uint64 + x158, x159 = bits.Add64(x134, x149, uint64(p224Uint1(x157))) + var x160 uint64 + var x161 uint64 + x160, x161 = bits.Add64(x136, x151, uint64(p224Uint1(x159))) + var x162 uint64 + var x163 uint64 + x162, x163 = bits.Add64(x138, x153, uint64(p224Uint1(x161))) + var x164 uint64 + var x165 uint64 + x164, x165 = bits.Add64(x140, x155, uint64(p224Uint1(x163))) + var x166 uint64 + _, x166 = bits.Mul64(x156, 0xffffffffffffffff) + var x168 uint64 + var x169 uint64 + x169, x168 = bits.Mul64(x166, 0xffffffff) + var x170 uint64 + var x171 uint64 + x171, x170 = bits.Mul64(x166, 0xffffffffffffffff) + var x172 uint64 + var x173 uint64 + x173, x172 = bits.Mul64(x166, 0xffffffff00000000) + var x174 uint64 + var x175 uint64 + x174, x175 = bits.Add64(x173, x170, uint64(0x0)) + var x176 uint64 + var x177 uint64 + x176, x177 = bits.Add64(x171, x168, uint64(p224Uint1(x175))) + x178 := (uint64(p224Uint1(x177)) + x169) + var x180 uint64 + _, x180 = bits.Add64(x156, x166, uint64(0x0)) + var x181 uint64 + var x182 uint64 + x181, x182 = bits.Add64(x158, x172, uint64(p224Uint1(x180))) + var x183 uint64 + var x184 uint64 + x183, x184 = bits.Add64(x160, x174, uint64(p224Uint1(x182))) + var x185 uint64 + var x186 uint64 + x185, x186 = bits.Add64(x162, x176, uint64(p224Uint1(x184))) + var x187 uint64 + var x188 uint64 + x187, x188 = bits.Add64(x164, x178, uint64(p224Uint1(x186))) + x189 := (uint64(p224Uint1(x188)) + uint64(p224Uint1(x165))) + var x190 uint64 + var x191 uint64 + x190, x191 = bits.Sub64(x181, uint64(0x1), uint64(0x0)) + var x192 uint64 + var x193 uint64 + x192, x193 = bits.Sub64(x183, 0xffffffff00000000, uint64(p224Uint1(x191))) + var x194 uint64 + var x195 uint64 + x194, x195 = bits.Sub64(x185, 0xffffffffffffffff, uint64(p224Uint1(x193))) + var x196 uint64 + var x197 uint64 + x196, x197 = bits.Sub64(x187, 0xffffffff, uint64(p224Uint1(x195))) + var x199 uint64 + _, x199 = bits.Sub64(x189, uint64(0x0), uint64(p224Uint1(x197))) + var x200 uint64 + p224CmovznzU64(&x200, p224Uint1(x199), x190, x181) + var x201 uint64 + p224CmovznzU64(&x201, p224Uint1(x199), x192, x183) + var x202 uint64 + p224CmovznzU64(&x202, p224Uint1(x199), x194, x185) + var x203 uint64 + p224CmovznzU64(&x203, p224Uint1(x199), x196, x187) + out1[0] = x200 + out1[1] = x201 + out1[2] = x202 + out1[3] = x203 +} + +// p224Square squares a field element in the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// Postconditions: +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg1)) mod m +// 0 ≤ eval out1 < m +// +func p224Square(out1 *p224MontgomeryDomainFieldElement, arg1 *p224MontgomeryDomainFieldElement) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[0] + var x5 uint64 + var x6 uint64 + x6, x5 = bits.Mul64(x4, arg1[3]) + var x7 uint64 + var x8 uint64 + x8, x7 = bits.Mul64(x4, arg1[2]) + var x9 uint64 + var x10 uint64 + x10, x9 = bits.Mul64(x4, arg1[1]) + var x11 uint64 + var x12 uint64 + x12, x11 = bits.Mul64(x4, arg1[0]) + var x13 uint64 + var x14 uint64 + x13, x14 = bits.Add64(x12, x9, uint64(0x0)) + var x15 uint64 + var x16 uint64 + x15, x16 = bits.Add64(x10, x7, uint64(p224Uint1(x14))) + var x17 uint64 + var x18 uint64 + x17, x18 = bits.Add64(x8, x5, uint64(p224Uint1(x16))) + x19 := (uint64(p224Uint1(x18)) + x6) + var x20 uint64 + _, x20 = bits.Mul64(x11, 0xffffffffffffffff) + var x22 uint64 + var x23 uint64 + x23, x22 = bits.Mul64(x20, 0xffffffff) + var x24 uint64 + var x25 uint64 + x25, x24 = bits.Mul64(x20, 0xffffffffffffffff) + var x26 uint64 + var x27 uint64 + x27, x26 = bits.Mul64(x20, 0xffffffff00000000) + var x28 uint64 + var x29 uint64 + x28, x29 = bits.Add64(x27, x24, uint64(0x0)) + var x30 uint64 + var x31 uint64 + x30, x31 = bits.Add64(x25, x22, uint64(p224Uint1(x29))) + x32 := (uint64(p224Uint1(x31)) + x23) + var x34 uint64 + _, x34 = bits.Add64(x11, x20, uint64(0x0)) + var x35 uint64 + var x36 uint64 + x35, x36 = bits.Add64(x13, x26, uint64(p224Uint1(x34))) + var x37 uint64 + var x38 uint64 + x37, x38 = bits.Add64(x15, x28, uint64(p224Uint1(x36))) + var x39 uint64 + var x40 uint64 + x39, x40 = bits.Add64(x17, x30, uint64(p224Uint1(x38))) + var x41 uint64 + var x42 uint64 + x41, x42 = bits.Add64(x19, x32, uint64(p224Uint1(x40))) + var x43 uint64 + var x44 uint64 + x44, x43 = bits.Mul64(x1, arg1[3]) + var x45 uint64 + var x46 uint64 + x46, x45 = bits.Mul64(x1, arg1[2]) + var x47 uint64 + var x48 uint64 + x48, x47 = bits.Mul64(x1, arg1[1]) + var x49 uint64 + var x50 uint64 + x50, x49 = bits.Mul64(x1, arg1[0]) + var x51 uint64 + var x52 uint64 + x51, x52 = bits.Add64(x50, x47, uint64(0x0)) + var x53 uint64 + var x54 uint64 + x53, x54 = bits.Add64(x48, x45, uint64(p224Uint1(x52))) + var x55 uint64 + var x56 uint64 + x55, x56 = bits.Add64(x46, x43, uint64(p224Uint1(x54))) + x57 := (uint64(p224Uint1(x56)) + x44) + var x58 uint64 + var x59 uint64 + x58, x59 = bits.Add64(x35, x49, uint64(0x0)) + var x60 uint64 + var x61 uint64 + x60, x61 = bits.Add64(x37, x51, uint64(p224Uint1(x59))) + var x62 uint64 + var x63 uint64 + x62, x63 = bits.Add64(x39, x53, uint64(p224Uint1(x61))) + var x64 uint64 + var x65 uint64 + x64, x65 = bits.Add64(x41, x55, uint64(p224Uint1(x63))) + var x66 uint64 + var x67 uint64 + x66, x67 = bits.Add64(uint64(p224Uint1(x42)), x57, uint64(p224Uint1(x65))) + var x68 uint64 + _, x68 = bits.Mul64(x58, 0xffffffffffffffff) + var x70 uint64 + var x71 uint64 + x71, x70 = bits.Mul64(x68, 0xffffffff) + var x72 uint64 + var x73 uint64 + x73, x72 = bits.Mul64(x68, 0xffffffffffffffff) + var x74 uint64 + var x75 uint64 + x75, x74 = bits.Mul64(x68, 0xffffffff00000000) + var x76 uint64 + var x77 uint64 + x76, x77 = bits.Add64(x75, x72, uint64(0x0)) + var x78 uint64 + var x79 uint64 + x78, x79 = bits.Add64(x73, x70, uint64(p224Uint1(x77))) + x80 := (uint64(p224Uint1(x79)) + x71) + var x82 uint64 + _, x82 = bits.Add64(x58, x68, uint64(0x0)) + var x83 uint64 + var x84 uint64 + x83, x84 = bits.Add64(x60, x74, uint64(p224Uint1(x82))) + var x85 uint64 + var x86 uint64 + x85, x86 = bits.Add64(x62, x76, uint64(p224Uint1(x84))) + var x87 uint64 + var x88 uint64 + x87, x88 = bits.Add64(x64, x78, uint64(p224Uint1(x86))) + var x89 uint64 + var x90 uint64 + x89, x90 = bits.Add64(x66, x80, uint64(p224Uint1(x88))) + x91 := (uint64(p224Uint1(x90)) + uint64(p224Uint1(x67))) + var x92 uint64 + var x93 uint64 + x93, x92 = bits.Mul64(x2, arg1[3]) + var x94 uint64 + var x95 uint64 + x95, x94 = bits.Mul64(x2, arg1[2]) + var x96 uint64 + var x97 uint64 + x97, x96 = bits.Mul64(x2, arg1[1]) + var x98 uint64 + var x99 uint64 + x99, x98 = bits.Mul64(x2, arg1[0]) + var x100 uint64 + var x101 uint64 + x100, x101 = bits.Add64(x99, x96, uint64(0x0)) + var x102 uint64 + var x103 uint64 + x102, x103 = bits.Add64(x97, x94, uint64(p224Uint1(x101))) + var x104 uint64 + var x105 uint64 + x104, x105 = bits.Add64(x95, x92, uint64(p224Uint1(x103))) + x106 := (uint64(p224Uint1(x105)) + x93) + var x107 uint64 + var x108 uint64 + x107, x108 = bits.Add64(x83, x98, uint64(0x0)) + var x109 uint64 + var x110 uint64 + x109, x110 = bits.Add64(x85, x100, uint64(p224Uint1(x108))) + var x111 uint64 + var x112 uint64 + x111, x112 = bits.Add64(x87, x102, uint64(p224Uint1(x110))) + var x113 uint64 + var x114 uint64 + x113, x114 = bits.Add64(x89, x104, uint64(p224Uint1(x112))) + var x115 uint64 + var x116 uint64 + x115, x116 = bits.Add64(x91, x106, uint64(p224Uint1(x114))) + var x117 uint64 + _, x117 = bits.Mul64(x107, 0xffffffffffffffff) + var x119 uint64 + var x120 uint64 + x120, x119 = bits.Mul64(x117, 0xffffffff) + var x121 uint64 + var x122 uint64 + x122, x121 = bits.Mul64(x117, 0xffffffffffffffff) + var x123 uint64 + var x124 uint64 + x124, x123 = bits.Mul64(x117, 0xffffffff00000000) + var x125 uint64 + var x126 uint64 + x125, x126 = bits.Add64(x124, x121, uint64(0x0)) + var x127 uint64 + var x128 uint64 + x127, x128 = bits.Add64(x122, x119, uint64(p224Uint1(x126))) + x129 := (uint64(p224Uint1(x128)) + x120) + var x131 uint64 + _, x131 = bits.Add64(x107, x117, uint64(0x0)) + var x132 uint64 + var x133 uint64 + x132, x133 = bits.Add64(x109, x123, uint64(p224Uint1(x131))) + var x134 uint64 + var x135 uint64 + x134, x135 = bits.Add64(x111, x125, uint64(p224Uint1(x133))) + var x136 uint64 + var x137 uint64 + x136, x137 = bits.Add64(x113, x127, uint64(p224Uint1(x135))) + var x138 uint64 + var x139 uint64 + x138, x139 = bits.Add64(x115, x129, uint64(p224Uint1(x137))) + x140 := (uint64(p224Uint1(x139)) + uint64(p224Uint1(x116))) + var x141 uint64 + var x142 uint64 + x142, x141 = bits.Mul64(x3, arg1[3]) + var x143 uint64 + var x144 uint64 + x144, x143 = bits.Mul64(x3, arg1[2]) + var x145 uint64 + var x146 uint64 + x146, x145 = bits.Mul64(x3, arg1[1]) + var x147 uint64 + var x148 uint64 + x148, x147 = bits.Mul64(x3, arg1[0]) + var x149 uint64 + var x150 uint64 + x149, x150 = bits.Add64(x148, x145, uint64(0x0)) + var x151 uint64 + var x152 uint64 + x151, x152 = bits.Add64(x146, x143, uint64(p224Uint1(x150))) + var x153 uint64 + var x154 uint64 + x153, x154 = bits.Add64(x144, x141, uint64(p224Uint1(x152))) + x155 := (uint64(p224Uint1(x154)) + x142) + var x156 uint64 + var x157 uint64 + x156, x157 = bits.Add64(x132, x147, uint64(0x0)) + var x158 uint64 + var x159 uint64 + x158, x159 = bits.Add64(x134, x149, uint64(p224Uint1(x157))) + var x160 uint64 + var x161 uint64 + x160, x161 = bits.Add64(x136, x151, uint64(p224Uint1(x159))) + var x162 uint64 + var x163 uint64 + x162, x163 = bits.Add64(x138, x153, uint64(p224Uint1(x161))) + var x164 uint64 + var x165 uint64 + x164, x165 = bits.Add64(x140, x155, uint64(p224Uint1(x163))) + var x166 uint64 + _, x166 = bits.Mul64(x156, 0xffffffffffffffff) + var x168 uint64 + var x169 uint64 + x169, x168 = bits.Mul64(x166, 0xffffffff) + var x170 uint64 + var x171 uint64 + x171, x170 = bits.Mul64(x166, 0xffffffffffffffff) + var x172 uint64 + var x173 uint64 + x173, x172 = bits.Mul64(x166, 0xffffffff00000000) + var x174 uint64 + var x175 uint64 + x174, x175 = bits.Add64(x173, x170, uint64(0x0)) + var x176 uint64 + var x177 uint64 + x176, x177 = bits.Add64(x171, x168, uint64(p224Uint1(x175))) + x178 := (uint64(p224Uint1(x177)) + x169) + var x180 uint64 + _, x180 = bits.Add64(x156, x166, uint64(0x0)) + var x181 uint64 + var x182 uint64 + x181, x182 = bits.Add64(x158, x172, uint64(p224Uint1(x180))) + var x183 uint64 + var x184 uint64 + x183, x184 = bits.Add64(x160, x174, uint64(p224Uint1(x182))) + var x185 uint64 + var x186 uint64 + x185, x186 = bits.Add64(x162, x176, uint64(p224Uint1(x184))) + var x187 uint64 + var x188 uint64 + x187, x188 = bits.Add64(x164, x178, uint64(p224Uint1(x186))) + x189 := (uint64(p224Uint1(x188)) + uint64(p224Uint1(x165))) + var x190 uint64 + var x191 uint64 + x190, x191 = bits.Sub64(x181, uint64(0x1), uint64(0x0)) + var x192 uint64 + var x193 uint64 + x192, x193 = bits.Sub64(x183, 0xffffffff00000000, uint64(p224Uint1(x191))) + var x194 uint64 + var x195 uint64 + x194, x195 = bits.Sub64(x185, 0xffffffffffffffff, uint64(p224Uint1(x193))) + var x196 uint64 + var x197 uint64 + x196, x197 = bits.Sub64(x187, 0xffffffff, uint64(p224Uint1(x195))) + var x199 uint64 + _, x199 = bits.Sub64(x189, uint64(0x0), uint64(p224Uint1(x197))) + var x200 uint64 + p224CmovznzU64(&x200, p224Uint1(x199), x190, x181) + var x201 uint64 + p224CmovznzU64(&x201, p224Uint1(x199), x192, x183) + var x202 uint64 + p224CmovznzU64(&x202, p224Uint1(x199), x194, x185) + var x203 uint64 + p224CmovznzU64(&x203, p224Uint1(x199), x196, x187) + out1[0] = x200 + out1[1] = x201 + out1[2] = x202 + out1[3] = x203 +} + +// p224Add adds two field elements in the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// 0 ≤ eval arg2 < m +// Postconditions: +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m +// 0 ≤ eval out1 < m +// +func p224Add(out1 *p224MontgomeryDomainFieldElement, arg1 *p224MontgomeryDomainFieldElement, arg2 *p224MontgomeryDomainFieldElement) { + var x1 uint64 + var x2 uint64 + x1, x2 = bits.Add64(arg1[0], arg2[0], uint64(0x0)) + var x3 uint64 + var x4 uint64 + x3, x4 = bits.Add64(arg1[1], arg2[1], uint64(p224Uint1(x2))) + var x5 uint64 + var x6 uint64 + x5, x6 = bits.Add64(arg1[2], arg2[2], uint64(p224Uint1(x4))) + var x7 uint64 + var x8 uint64 + x7, x8 = bits.Add64(arg1[3], arg2[3], uint64(p224Uint1(x6))) + var x9 uint64 + var x10 uint64 + x9, x10 = bits.Sub64(x1, uint64(0x1), uint64(0x0)) + var x11 uint64 + var x12 uint64 + x11, x12 = bits.Sub64(x3, 0xffffffff00000000, uint64(p224Uint1(x10))) + var x13 uint64 + var x14 uint64 + x13, x14 = bits.Sub64(x5, 0xffffffffffffffff, uint64(p224Uint1(x12))) + var x15 uint64 + var x16 uint64 + x15, x16 = bits.Sub64(x7, 0xffffffff, uint64(p224Uint1(x14))) + var x18 uint64 + _, x18 = bits.Sub64(uint64(p224Uint1(x8)), uint64(0x0), uint64(p224Uint1(x16))) + var x19 uint64 + p224CmovznzU64(&x19, p224Uint1(x18), x9, x1) + var x20 uint64 + p224CmovznzU64(&x20, p224Uint1(x18), x11, x3) + var x21 uint64 + p224CmovznzU64(&x21, p224Uint1(x18), x13, x5) + var x22 uint64 + p224CmovznzU64(&x22, p224Uint1(x18), x15, x7) + out1[0] = x19 + out1[1] = x20 + out1[2] = x21 + out1[3] = x22 +} + +// p224Sub subtracts two field elements in the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// 0 ≤ eval arg2 < m +// Postconditions: +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m +// 0 ≤ eval out1 < m +// +func p224Sub(out1 *p224MontgomeryDomainFieldElement, arg1 *p224MontgomeryDomainFieldElement, arg2 *p224MontgomeryDomainFieldElement) { + var x1 uint64 + var x2 uint64 + x1, x2 = bits.Sub64(arg1[0], arg2[0], uint64(0x0)) + var x3 uint64 + var x4 uint64 + x3, x4 = bits.Sub64(arg1[1], arg2[1], uint64(p224Uint1(x2))) + var x5 uint64 + var x6 uint64 + x5, x6 = bits.Sub64(arg1[2], arg2[2], uint64(p224Uint1(x4))) + var x7 uint64 + var x8 uint64 + x7, x8 = bits.Sub64(arg1[3], arg2[3], uint64(p224Uint1(x6))) + var x9 uint64 + p224CmovznzU64(&x9, p224Uint1(x8), uint64(0x0), 0xffffffffffffffff) + var x10 uint64 + var x11 uint64 + x10, x11 = bits.Add64(x1, uint64((p224Uint1(x9) & 0x1)), uint64(0x0)) + var x12 uint64 + var x13 uint64 + x12, x13 = bits.Add64(x3, (x9 & 0xffffffff00000000), uint64(p224Uint1(x11))) + var x14 uint64 + var x15 uint64 + x14, x15 = bits.Add64(x5, x9, uint64(p224Uint1(x13))) + var x16 uint64 + x16, _ = bits.Add64(x7, (x9 & 0xffffffff), uint64(p224Uint1(x15))) + out1[0] = x10 + out1[1] = x12 + out1[2] = x14 + out1[3] = x16 +} + +// p224SetOne returns the field element one in the Montgomery domain. +// +// Postconditions: +// eval (from_montgomery out1) mod m = 1 mod m +// 0 ≤ eval out1 < m +// +func p224SetOne(out1 *p224MontgomeryDomainFieldElement) { + out1[0] = 0xffffffff00000000 + out1[1] = 0xffffffffffffffff + out1[2] = uint64(0x0) + out1[3] = uint64(0x0) +} + +// p224FromMontgomery translates a field element out of the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// Postconditions: +// eval out1 mod m = (eval arg1 * ((2^64)⁻¹ mod m)^4) mod m +// 0 ≤ eval out1 < m +// +func p224FromMontgomery(out1 *p224NonMontgomeryDomainFieldElement, arg1 *p224MontgomeryDomainFieldElement) { + x1 := arg1[0] + var x2 uint64 + _, x2 = bits.Mul64(x1, 0xffffffffffffffff) + var x4 uint64 + var x5 uint64 + x5, x4 = bits.Mul64(x2, 0xffffffff) + var x6 uint64 + var x7 uint64 + x7, x6 = bits.Mul64(x2, 0xffffffffffffffff) + var x8 uint64 + var x9 uint64 + x9, x8 = bits.Mul64(x2, 0xffffffff00000000) + var x10 uint64 + var x11 uint64 + x10, x11 = bits.Add64(x9, x6, uint64(0x0)) + var x12 uint64 + var x13 uint64 + x12, x13 = bits.Add64(x7, x4, uint64(p224Uint1(x11))) + var x15 uint64 + _, x15 = bits.Add64(x1, x2, uint64(0x0)) + var x16 uint64 + var x17 uint64 + x16, x17 = bits.Add64(uint64(0x0), x8, uint64(p224Uint1(x15))) + var x18 uint64 + var x19 uint64 + x18, x19 = bits.Add64(uint64(0x0), x10, uint64(p224Uint1(x17))) + var x20 uint64 + var x21 uint64 + x20, x21 = bits.Add64(uint64(0x0), x12, uint64(p224Uint1(x19))) + var x22 uint64 + var x23 uint64 + x22, x23 = bits.Add64(x16, arg1[1], uint64(0x0)) + var x24 uint64 + var x25 uint64 + x24, x25 = bits.Add64(x18, uint64(0x0), uint64(p224Uint1(x23))) + var x26 uint64 + var x27 uint64 + x26, x27 = bits.Add64(x20, uint64(0x0), uint64(p224Uint1(x25))) + var x28 uint64 + _, x28 = bits.Mul64(x22, 0xffffffffffffffff) + var x30 uint64 + var x31 uint64 + x31, x30 = bits.Mul64(x28, 0xffffffff) + var x32 uint64 + var x33 uint64 + x33, x32 = bits.Mul64(x28, 0xffffffffffffffff) + var x34 uint64 + var x35 uint64 + x35, x34 = bits.Mul64(x28, 0xffffffff00000000) + var x36 uint64 + var x37 uint64 + x36, x37 = bits.Add64(x35, x32, uint64(0x0)) + var x38 uint64 + var x39 uint64 + x38, x39 = bits.Add64(x33, x30, uint64(p224Uint1(x37))) + var x41 uint64 + _, x41 = bits.Add64(x22, x28, uint64(0x0)) + var x42 uint64 + var x43 uint64 + x42, x43 = bits.Add64(x24, x34, uint64(p224Uint1(x41))) + var x44 uint64 + var x45 uint64 + x44, x45 = bits.Add64(x26, x36, uint64(p224Uint1(x43))) + var x46 uint64 + var x47 uint64 + x46, x47 = bits.Add64((uint64(p224Uint1(x27)) + (uint64(p224Uint1(x21)) + (uint64(p224Uint1(x13)) + x5))), x38, uint64(p224Uint1(x45))) + var x48 uint64 + var x49 uint64 + x48, x49 = bits.Add64(x42, arg1[2], uint64(0x0)) + var x50 uint64 + var x51 uint64 + x50, x51 = bits.Add64(x44, uint64(0x0), uint64(p224Uint1(x49))) + var x52 uint64 + var x53 uint64 + x52, x53 = bits.Add64(x46, uint64(0x0), uint64(p224Uint1(x51))) + var x54 uint64 + _, x54 = bits.Mul64(x48, 0xffffffffffffffff) + var x56 uint64 + var x57 uint64 + x57, x56 = bits.Mul64(x54, 0xffffffff) + var x58 uint64 + var x59 uint64 + x59, x58 = bits.Mul64(x54, 0xffffffffffffffff) + var x60 uint64 + var x61 uint64 + x61, x60 = bits.Mul64(x54, 0xffffffff00000000) + var x62 uint64 + var x63 uint64 + x62, x63 = bits.Add64(x61, x58, uint64(0x0)) + var x64 uint64 + var x65 uint64 + x64, x65 = bits.Add64(x59, x56, uint64(p224Uint1(x63))) + var x67 uint64 + _, x67 = bits.Add64(x48, x54, uint64(0x0)) + var x68 uint64 + var x69 uint64 + x68, x69 = bits.Add64(x50, x60, uint64(p224Uint1(x67))) + var x70 uint64 + var x71 uint64 + x70, x71 = bits.Add64(x52, x62, uint64(p224Uint1(x69))) + var x72 uint64 + var x73 uint64 + x72, x73 = bits.Add64((uint64(p224Uint1(x53)) + (uint64(p224Uint1(x47)) + (uint64(p224Uint1(x39)) + x31))), x64, uint64(p224Uint1(x71))) + var x74 uint64 + var x75 uint64 + x74, x75 = bits.Add64(x68, arg1[3], uint64(0x0)) + var x76 uint64 + var x77 uint64 + x76, x77 = bits.Add64(x70, uint64(0x0), uint64(p224Uint1(x75))) + var x78 uint64 + var x79 uint64 + x78, x79 = bits.Add64(x72, uint64(0x0), uint64(p224Uint1(x77))) + var x80 uint64 + _, x80 = bits.Mul64(x74, 0xffffffffffffffff) + var x82 uint64 + var x83 uint64 + x83, x82 = bits.Mul64(x80, 0xffffffff) + var x84 uint64 + var x85 uint64 + x85, x84 = bits.Mul64(x80, 0xffffffffffffffff) + var x86 uint64 + var x87 uint64 + x87, x86 = bits.Mul64(x80, 0xffffffff00000000) + var x88 uint64 + var x89 uint64 + x88, x89 = bits.Add64(x87, x84, uint64(0x0)) + var x90 uint64 + var x91 uint64 + x90, x91 = bits.Add64(x85, x82, uint64(p224Uint1(x89))) + var x93 uint64 + _, x93 = bits.Add64(x74, x80, uint64(0x0)) + var x94 uint64 + var x95 uint64 + x94, x95 = bits.Add64(x76, x86, uint64(p224Uint1(x93))) + var x96 uint64 + var x97 uint64 + x96, x97 = bits.Add64(x78, x88, uint64(p224Uint1(x95))) + var x98 uint64 + var x99 uint64 + x98, x99 = bits.Add64((uint64(p224Uint1(x79)) + (uint64(p224Uint1(x73)) + (uint64(p224Uint1(x65)) + x57))), x90, uint64(p224Uint1(x97))) + x100 := (uint64(p224Uint1(x99)) + (uint64(p224Uint1(x91)) + x83)) + var x101 uint64 + var x102 uint64 + x101, x102 = bits.Sub64(x94, uint64(0x1), uint64(0x0)) + var x103 uint64 + var x104 uint64 + x103, x104 = bits.Sub64(x96, 0xffffffff00000000, uint64(p224Uint1(x102))) + var x105 uint64 + var x106 uint64 + x105, x106 = bits.Sub64(x98, 0xffffffffffffffff, uint64(p224Uint1(x104))) + var x107 uint64 + var x108 uint64 + x107, x108 = bits.Sub64(x100, 0xffffffff, uint64(p224Uint1(x106))) + var x110 uint64 + _, x110 = bits.Sub64(uint64(0x0), uint64(0x0), uint64(p224Uint1(x108))) + var x111 uint64 + p224CmovznzU64(&x111, p224Uint1(x110), x101, x94) + var x112 uint64 + p224CmovznzU64(&x112, p224Uint1(x110), x103, x96) + var x113 uint64 + p224CmovznzU64(&x113, p224Uint1(x110), x105, x98) + var x114 uint64 + p224CmovznzU64(&x114, p224Uint1(x110), x107, x100) + out1[0] = x111 + out1[1] = x112 + out1[2] = x113 + out1[3] = x114 +} + +// p224ToMontgomery translates a field element into the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// Postconditions: +// eval (from_montgomery out1) mod m = eval arg1 mod m +// 0 ≤ eval out1 < m +// +func p224ToMontgomery(out1 *p224MontgomeryDomainFieldElement, arg1 *p224NonMontgomeryDomainFieldElement) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[0] + var x5 uint64 + var x6 uint64 + x6, x5 = bits.Mul64(x4, 0xffffffff) + var x7 uint64 + var x8 uint64 + x8, x7 = bits.Mul64(x4, 0xfffffffe00000000) + var x9 uint64 + var x10 uint64 + x10, x9 = bits.Mul64(x4, 0xffffffff00000000) + var x11 uint64 + var x12 uint64 + x12, x11 = bits.Mul64(x4, 0xffffffff00000001) + var x13 uint64 + var x14 uint64 + x13, x14 = bits.Add64(x12, x9, uint64(0x0)) + var x15 uint64 + var x16 uint64 + x15, x16 = bits.Add64(x10, x7, uint64(p224Uint1(x14))) + var x17 uint64 + var x18 uint64 + x17, x18 = bits.Add64(x8, x5, uint64(p224Uint1(x16))) + var x19 uint64 + _, x19 = bits.Mul64(x11, 0xffffffffffffffff) + var x21 uint64 + var x22 uint64 + x22, x21 = bits.Mul64(x19, 0xffffffff) + var x23 uint64 + var x24 uint64 + x24, x23 = bits.Mul64(x19, 0xffffffffffffffff) + var x25 uint64 + var x26 uint64 + x26, x25 = bits.Mul64(x19, 0xffffffff00000000) + var x27 uint64 + var x28 uint64 + x27, x28 = bits.Add64(x26, x23, uint64(0x0)) + var x29 uint64 + var x30 uint64 + x29, x30 = bits.Add64(x24, x21, uint64(p224Uint1(x28))) + var x32 uint64 + _, x32 = bits.Add64(x11, x19, uint64(0x0)) + var x33 uint64 + var x34 uint64 + x33, x34 = bits.Add64(x13, x25, uint64(p224Uint1(x32))) + var x35 uint64 + var x36 uint64 + x35, x36 = bits.Add64(x15, x27, uint64(p224Uint1(x34))) + var x37 uint64 + var x38 uint64 + x37, x38 = bits.Add64(x17, x29, uint64(p224Uint1(x36))) + var x39 uint64 + var x40 uint64 + x40, x39 = bits.Mul64(x1, 0xffffffff) + var x41 uint64 + var x42 uint64 + x42, x41 = bits.Mul64(x1, 0xfffffffe00000000) + var x43 uint64 + var x44 uint64 + x44, x43 = bits.Mul64(x1, 0xffffffff00000000) + var x45 uint64 + var x46 uint64 + x46, x45 = bits.Mul64(x1, 0xffffffff00000001) + var x47 uint64 + var x48 uint64 + x47, x48 = bits.Add64(x46, x43, uint64(0x0)) + var x49 uint64 + var x50 uint64 + x49, x50 = bits.Add64(x44, x41, uint64(p224Uint1(x48))) + var x51 uint64 + var x52 uint64 + x51, x52 = bits.Add64(x42, x39, uint64(p224Uint1(x50))) + var x53 uint64 + var x54 uint64 + x53, x54 = bits.Add64(x33, x45, uint64(0x0)) + var x55 uint64 + var x56 uint64 + x55, x56 = bits.Add64(x35, x47, uint64(p224Uint1(x54))) + var x57 uint64 + var x58 uint64 + x57, x58 = bits.Add64(x37, x49, uint64(p224Uint1(x56))) + var x59 uint64 + var x60 uint64 + x59, x60 = bits.Add64(((uint64(p224Uint1(x38)) + (uint64(p224Uint1(x18)) + x6)) + (uint64(p224Uint1(x30)) + x22)), x51, uint64(p224Uint1(x58))) + var x61 uint64 + _, x61 = bits.Mul64(x53, 0xffffffffffffffff) + var x63 uint64 + var x64 uint64 + x64, x63 = bits.Mul64(x61, 0xffffffff) + var x65 uint64 + var x66 uint64 + x66, x65 = bits.Mul64(x61, 0xffffffffffffffff) + var x67 uint64 + var x68 uint64 + x68, x67 = bits.Mul64(x61, 0xffffffff00000000) + var x69 uint64 + var x70 uint64 + x69, x70 = bits.Add64(x68, x65, uint64(0x0)) + var x71 uint64 + var x72 uint64 + x71, x72 = bits.Add64(x66, x63, uint64(p224Uint1(x70))) + var x74 uint64 + _, x74 = bits.Add64(x53, x61, uint64(0x0)) + var x75 uint64 + var x76 uint64 + x75, x76 = bits.Add64(x55, x67, uint64(p224Uint1(x74))) + var x77 uint64 + var x78 uint64 + x77, x78 = bits.Add64(x57, x69, uint64(p224Uint1(x76))) + var x79 uint64 + var x80 uint64 + x79, x80 = bits.Add64(x59, x71, uint64(p224Uint1(x78))) + var x81 uint64 + var x82 uint64 + x82, x81 = bits.Mul64(x2, 0xffffffff) + var x83 uint64 + var x84 uint64 + x84, x83 = bits.Mul64(x2, 0xfffffffe00000000) + var x85 uint64 + var x86 uint64 + x86, x85 = bits.Mul64(x2, 0xffffffff00000000) + var x87 uint64 + var x88 uint64 + x88, x87 = bits.Mul64(x2, 0xffffffff00000001) + var x89 uint64 + var x90 uint64 + x89, x90 = bits.Add64(x88, x85, uint64(0x0)) + var x91 uint64 + var x92 uint64 + x91, x92 = bits.Add64(x86, x83, uint64(p224Uint1(x90))) + var x93 uint64 + var x94 uint64 + x93, x94 = bits.Add64(x84, x81, uint64(p224Uint1(x92))) + var x95 uint64 + var x96 uint64 + x95, x96 = bits.Add64(x75, x87, uint64(0x0)) + var x97 uint64 + var x98 uint64 + x97, x98 = bits.Add64(x77, x89, uint64(p224Uint1(x96))) + var x99 uint64 + var x100 uint64 + x99, x100 = bits.Add64(x79, x91, uint64(p224Uint1(x98))) + var x101 uint64 + var x102 uint64 + x101, x102 = bits.Add64(((uint64(p224Uint1(x80)) + (uint64(p224Uint1(x60)) + (uint64(p224Uint1(x52)) + x40))) + (uint64(p224Uint1(x72)) + x64)), x93, uint64(p224Uint1(x100))) + var x103 uint64 + _, x103 = bits.Mul64(x95, 0xffffffffffffffff) + var x105 uint64 + var x106 uint64 + x106, x105 = bits.Mul64(x103, 0xffffffff) + var x107 uint64 + var x108 uint64 + x108, x107 = bits.Mul64(x103, 0xffffffffffffffff) + var x109 uint64 + var x110 uint64 + x110, x109 = bits.Mul64(x103, 0xffffffff00000000) + var x111 uint64 + var x112 uint64 + x111, x112 = bits.Add64(x110, x107, uint64(0x0)) + var x113 uint64 + var x114 uint64 + x113, x114 = bits.Add64(x108, x105, uint64(p224Uint1(x112))) + var x116 uint64 + _, x116 = bits.Add64(x95, x103, uint64(0x0)) + var x117 uint64 + var x118 uint64 + x117, x118 = bits.Add64(x97, x109, uint64(p224Uint1(x116))) + var x119 uint64 + var x120 uint64 + x119, x120 = bits.Add64(x99, x111, uint64(p224Uint1(x118))) + var x121 uint64 + var x122 uint64 + x121, x122 = bits.Add64(x101, x113, uint64(p224Uint1(x120))) + var x123 uint64 + var x124 uint64 + x124, x123 = bits.Mul64(x3, 0xffffffff) + var x125 uint64 + var x126 uint64 + x126, x125 = bits.Mul64(x3, 0xfffffffe00000000) + var x127 uint64 + var x128 uint64 + x128, x127 = bits.Mul64(x3, 0xffffffff00000000) + var x129 uint64 + var x130 uint64 + x130, x129 = bits.Mul64(x3, 0xffffffff00000001) + var x131 uint64 + var x132 uint64 + x131, x132 = bits.Add64(x130, x127, uint64(0x0)) + var x133 uint64 + var x134 uint64 + x133, x134 = bits.Add64(x128, x125, uint64(p224Uint1(x132))) + var x135 uint64 + var x136 uint64 + x135, x136 = bits.Add64(x126, x123, uint64(p224Uint1(x134))) + var x137 uint64 + var x138 uint64 + x137, x138 = bits.Add64(x117, x129, uint64(0x0)) + var x139 uint64 + var x140 uint64 + x139, x140 = bits.Add64(x119, x131, uint64(p224Uint1(x138))) + var x141 uint64 + var x142 uint64 + x141, x142 = bits.Add64(x121, x133, uint64(p224Uint1(x140))) + var x143 uint64 + var x144 uint64 + x143, x144 = bits.Add64(((uint64(p224Uint1(x122)) + (uint64(p224Uint1(x102)) + (uint64(p224Uint1(x94)) + x82))) + (uint64(p224Uint1(x114)) + x106)), x135, uint64(p224Uint1(x142))) + var x145 uint64 + _, x145 = bits.Mul64(x137, 0xffffffffffffffff) + var x147 uint64 + var x148 uint64 + x148, x147 = bits.Mul64(x145, 0xffffffff) + var x149 uint64 + var x150 uint64 + x150, x149 = bits.Mul64(x145, 0xffffffffffffffff) + var x151 uint64 + var x152 uint64 + x152, x151 = bits.Mul64(x145, 0xffffffff00000000) + var x153 uint64 + var x154 uint64 + x153, x154 = bits.Add64(x152, x149, uint64(0x0)) + var x155 uint64 + var x156 uint64 + x155, x156 = bits.Add64(x150, x147, uint64(p224Uint1(x154))) + var x158 uint64 + _, x158 = bits.Add64(x137, x145, uint64(0x0)) + var x159 uint64 + var x160 uint64 + x159, x160 = bits.Add64(x139, x151, uint64(p224Uint1(x158))) + var x161 uint64 + var x162 uint64 + x161, x162 = bits.Add64(x141, x153, uint64(p224Uint1(x160))) + var x163 uint64 + var x164 uint64 + x163, x164 = bits.Add64(x143, x155, uint64(p224Uint1(x162))) + x165 := ((uint64(p224Uint1(x164)) + (uint64(p224Uint1(x144)) + (uint64(p224Uint1(x136)) + x124))) + (uint64(p224Uint1(x156)) + x148)) + var x166 uint64 + var x167 uint64 + x166, x167 = bits.Sub64(x159, uint64(0x1), uint64(0x0)) + var x168 uint64 + var x169 uint64 + x168, x169 = bits.Sub64(x161, 0xffffffff00000000, uint64(p224Uint1(x167))) + var x170 uint64 + var x171 uint64 + x170, x171 = bits.Sub64(x163, 0xffffffffffffffff, uint64(p224Uint1(x169))) + var x172 uint64 + var x173 uint64 + x172, x173 = bits.Sub64(x165, 0xffffffff, uint64(p224Uint1(x171))) + var x175 uint64 + _, x175 = bits.Sub64(uint64(0x0), uint64(0x0), uint64(p224Uint1(x173))) + var x176 uint64 + p224CmovznzU64(&x176, p224Uint1(x175), x166, x159) + var x177 uint64 + p224CmovznzU64(&x177, p224Uint1(x175), x168, x161) + var x178 uint64 + p224CmovznzU64(&x178, p224Uint1(x175), x170, x163) + var x179 uint64 + p224CmovznzU64(&x179, p224Uint1(x175), x172, x165) + out1[0] = x176 + out1[1] = x177 + out1[2] = x178 + out1[3] = x179 +} + +// p224Selectznz is a multi-limb conditional select. +// +// Postconditions: +// eval out1 = (if arg1 = 0 then eval arg2 else eval arg3) +// +// Input Bounds: +// arg1: [0x0 ~> 0x1] +// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +// arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +// Output Bounds: +// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +func p224Selectznz(out1 *[4]uint64, arg1 p224Uint1, arg2 *[4]uint64, arg3 *[4]uint64) { + var x1 uint64 + p224CmovznzU64(&x1, arg1, arg2[0], arg3[0]) + var x2 uint64 + p224CmovznzU64(&x2, arg1, arg2[1], arg3[1]) + var x3 uint64 + p224CmovznzU64(&x3, arg1, arg2[2], arg3[2]) + var x4 uint64 + p224CmovznzU64(&x4, arg1, arg2[3], arg3[3]) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 +} + +// p224ToBytes serializes a field element NOT in the Montgomery domain to bytes in little-endian order. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// Postconditions: +// out1 = map (λ x, ⌊((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)⌋) [0..27] +// +// Input Bounds: +// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffff]] +// Output Bounds: +// out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]] +func p224ToBytes(out1 *[28]uint8, arg1 *[4]uint64) { + x1 := arg1[3] + x2 := arg1[2] + x3 := arg1[1] + x4 := arg1[0] + x5 := (uint8(x4) & 0xff) + x6 := (x4 >> 8) + x7 := (uint8(x6) & 0xff) + x8 := (x6 >> 8) + x9 := (uint8(x8) & 0xff) + x10 := (x8 >> 8) + x11 := (uint8(x10) & 0xff) + x12 := (x10 >> 8) + x13 := (uint8(x12) & 0xff) + x14 := (x12 >> 8) + x15 := (uint8(x14) & 0xff) + x16 := (x14 >> 8) + x17 := (uint8(x16) & 0xff) + x18 := uint8((x16 >> 8)) + x19 := (uint8(x3) & 0xff) + x20 := (x3 >> 8) + x21 := (uint8(x20) & 0xff) + x22 := (x20 >> 8) + x23 := (uint8(x22) & 0xff) + x24 := (x22 >> 8) + x25 := (uint8(x24) & 0xff) + x26 := (x24 >> 8) + x27 := (uint8(x26) & 0xff) + x28 := (x26 >> 8) + x29 := (uint8(x28) & 0xff) + x30 := (x28 >> 8) + x31 := (uint8(x30) & 0xff) + x32 := uint8((x30 >> 8)) + x33 := (uint8(x2) & 0xff) + x34 := (x2 >> 8) + x35 := (uint8(x34) & 0xff) + x36 := (x34 >> 8) + x37 := (uint8(x36) & 0xff) + x38 := (x36 >> 8) + x39 := (uint8(x38) & 0xff) + x40 := (x38 >> 8) + x41 := (uint8(x40) & 0xff) + x42 := (x40 >> 8) + x43 := (uint8(x42) & 0xff) + x44 := (x42 >> 8) + x45 := (uint8(x44) & 0xff) + x46 := uint8((x44 >> 8)) + x47 := (uint8(x1) & 0xff) + x48 := (x1 >> 8) + x49 := (uint8(x48) & 0xff) + x50 := (x48 >> 8) + x51 := (uint8(x50) & 0xff) + x52 := uint8((x50 >> 8)) + out1[0] = x5 + out1[1] = x7 + out1[2] = x9 + out1[3] = x11 + out1[4] = x13 + out1[5] = x15 + out1[6] = x17 + out1[7] = x18 + out1[8] = x19 + out1[9] = x21 + out1[10] = x23 + out1[11] = x25 + out1[12] = x27 + out1[13] = x29 + out1[14] = x31 + out1[15] = x32 + out1[16] = x33 + out1[17] = x35 + out1[18] = x37 + out1[19] = x39 + out1[20] = x41 + out1[21] = x43 + out1[22] = x45 + out1[23] = x46 + out1[24] = x47 + out1[25] = x49 + out1[26] = x51 + out1[27] = x52 +} + +// p224FromBytes deserializes a field element NOT in the Montgomery domain from bytes in little-endian order. +// +// Preconditions: +// 0 ≤ bytes_eval arg1 < m +// Postconditions: +// eval out1 mod m = bytes_eval arg1 mod m +// 0 ≤ eval out1 < m +// +// Input Bounds: +// arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]] +// Output Bounds: +// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffff]] +func p224FromBytes(out1 *[4]uint64, arg1 *[28]uint8) { + x1 := (uint64(arg1[27]) << 24) + x2 := (uint64(arg1[26]) << 16) + x3 := (uint64(arg1[25]) << 8) + x4 := arg1[24] + x5 := (uint64(arg1[23]) << 56) + x6 := (uint64(arg1[22]) << 48) + x7 := (uint64(arg1[21]) << 40) + x8 := (uint64(arg1[20]) << 32) + x9 := (uint64(arg1[19]) << 24) + x10 := (uint64(arg1[18]) << 16) + x11 := (uint64(arg1[17]) << 8) + x12 := arg1[16] + x13 := (uint64(arg1[15]) << 56) + x14 := (uint64(arg1[14]) << 48) + x15 := (uint64(arg1[13]) << 40) + x16 := (uint64(arg1[12]) << 32) + x17 := (uint64(arg1[11]) << 24) + x18 := (uint64(arg1[10]) << 16) + x19 := (uint64(arg1[9]) << 8) + x20 := arg1[8] + x21 := (uint64(arg1[7]) << 56) + x22 := (uint64(arg1[6]) << 48) + x23 := (uint64(arg1[5]) << 40) + x24 := (uint64(arg1[4]) << 32) + x25 := (uint64(arg1[3]) << 24) + x26 := (uint64(arg1[2]) << 16) + x27 := (uint64(arg1[1]) << 8) + x28 := arg1[0] + x29 := (x27 + uint64(x28)) + x30 := (x26 + x29) + x31 := (x25 + x30) + x32 := (x24 + x31) + x33 := (x23 + x32) + x34 := (x22 + x33) + x35 := (x21 + x34) + x36 := (x19 + uint64(x20)) + x37 := (x18 + x36) + x38 := (x17 + x37) + x39 := (x16 + x38) + x40 := (x15 + x39) + x41 := (x14 + x40) + x42 := (x13 + x41) + x43 := (x11 + uint64(x12)) + x44 := (x10 + x43) + x45 := (x9 + x44) + x46 := (x8 + x45) + x47 := (x7 + x46) + x48 := (x6 + x47) + x49 := (x5 + x48) + x50 := (x3 + uint64(x4)) + x51 := (x2 + x50) + x52 := (x1 + x51) + out1[0] = x35 + out1[1] = x42 + out1[2] = x49 + out1[3] = x52 +} diff --git a/src/crypto/elliptic/internal/fiat/p224_invert.go b/src/crypto/elliptic/internal/fiat/p224_invert.go new file mode 100644 index 0000000000..4163ed0c67 --- /dev/null +++ b/src/crypto/elliptic/internal/fiat/p224_invert.go @@ -0,0 +1,87 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by addchain. DO NOT EDIT. + +package fiat + +// Invert sets e = 1/x, and returns e. +// +// If x == 0, Invert returns e = 0. +func (e *P224Element) Invert(x *P224Element) *P224Element { + // Inversion is implemented as exponentiation with exponent p − 2. + // The sequence of 11 multiplications and 223 squarings is derived from the + // following addition chain generated with github.com/mmcloughlin/addchain v0.3.0. + // + // _10 = 2*1 + // _11 = 1 + _10 + // _110 = 2*_11 + // _111 = 1 + _110 + // _111000 = _111 << 3 + // _111111 = _111 + _111000 + // x12 = _111111 << 6 + _111111 + // x14 = x12 << 2 + _11 + // x17 = x14 << 3 + _111 + // x31 = x17 << 14 + x14 + // x48 = x31 << 17 + x17 + // x96 = x48 << 48 + x48 + // x127 = x96 << 31 + x31 + // return x127 << 97 + x96 + // + + var z = new(P224Element).Set(e) + var t0 = new(P224Element) + var t1 = new(P224Element) + var t2 = new(P224Element) + + z.Square(x) + t0.Mul(x, z) + z.Square(t0) + z.Mul(x, z) + t1.Square(z) + for s := 1; s < 3; s++ { + t1.Square(t1) + } + t1.Mul(z, t1) + t2.Square(t1) + for s := 1; s < 6; s++ { + t2.Square(t2) + } + t1.Mul(t1, t2) + for s := 0; s < 2; s++ { + t1.Square(t1) + } + t0.Mul(t0, t1) + t1.Square(t0) + for s := 1; s < 3; s++ { + t1.Square(t1) + } + z.Mul(z, t1) + t1.Square(z) + for s := 1; s < 14; s++ { + t1.Square(t1) + } + t0.Mul(t0, t1) + t1.Square(t0) + for s := 1; s < 17; s++ { + t1.Square(t1) + } + z.Mul(z, t1) + t1.Square(z) + for s := 1; s < 48; s++ { + t1.Square(t1) + } + z.Mul(z, t1) + t1.Square(z) + for s := 1; s < 31; s++ { + t1.Square(t1) + } + t0.Mul(t0, t1) + for s := 0; s < 97; s++ { + t0.Square(t0) + } + z.Mul(z, t0) + + return e.Set(z) +} diff --git a/src/crypto/elliptic/internal/fiat/p384.go b/src/crypto/elliptic/internal/fiat/p384.go new file mode 100644 index 0000000000..5474d77d48 --- /dev/null +++ b/src/crypto/elliptic/internal/fiat/p384.go @@ -0,0 +1,135 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by generate.go. DO NOT EDIT. + +package fiat + +import ( + "crypto/subtle" + "errors" +) + +// P384Element is an integer modulo 2^384 - 2^128 - 2^96 + 2^32 - 1. +// +// The zero value is a valid zero element. +type P384Element struct { + // Values are represented internally always in the Montgomery domain, and + // converted in Bytes and SetBytes. + x p384MontgomeryDomainFieldElement +} + +const p384ElementLen = 48 + +type p384UntypedFieldElement = [6]uint64 + +// One sets e = 1, and returns e. +func (e *P384Element) One() *P384Element { + p384SetOne(&e.x) + return e +} + +// Equal returns 1 if e == t, and zero otherwise. +func (e *P384Element) Equal(t *P384Element) int { + eBytes := e.Bytes() + tBytes := t.Bytes() + return subtle.ConstantTimeCompare(eBytes, tBytes) +} + +var p384ZeroEncoding = new(P384Element).Bytes() + +// IsZero returns 1 if e == 0, and zero otherwise. +func (e *P384Element) IsZero() int { + eBytes := e.Bytes() + return subtle.ConstantTimeCompare(eBytes, p384ZeroEncoding) +} + +// Set sets e = t, and returns e. +func (e *P384Element) Set(t *P384Element) *P384Element { + e.x = t.x + return e +} + +// Bytes returns the 48-byte big-endian encoding of e. +func (e *P384Element) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var out [p384ElementLen]byte + return e.bytes(&out) +} + +func (e *P384Element) bytes(out *[p384ElementLen]byte) []byte { + var tmp p384NonMontgomeryDomainFieldElement + p384FromMontgomery(&tmp, &e.x) + p384ToBytes(out, (*p384UntypedFieldElement)(&tmp)) + p384InvertEndianness(out[:]) + return out[:] +} + +// p384MinusOneEncoding is the encoding of -1 mod p, so p - 1, the +// highest canonical encoding. It is used by SetBytes to check for non-canonical +// encodings such as p + k, 2p + k, etc. +var p384MinusOneEncoding = new(P384Element).Sub( + new(P384Element), new(P384Element).One()).Bytes() + +// SetBytes sets e = v, where v is a big-endian 48-byte encoding, and returns e. +// If v is not 48 bytes or it encodes a value higher than 2^384 - 2^128 - 2^96 + 2^32 - 1, +// SetBytes returns nil and an error, and e is unchanged. +func (e *P384Element) SetBytes(v []byte) (*P384Element, error) { + if len(v) != p384ElementLen { + return nil, errors.New("invalid P384Element encoding") + } + for i := range v { + if v[i] < p384MinusOneEncoding[i] { + break + } + if v[i] > p384MinusOneEncoding[i] { + return nil, errors.New("invalid P384Element encoding") + } + } + var in [p384ElementLen]byte + copy(in[:], v) + p384InvertEndianness(in[:]) + var tmp p384NonMontgomeryDomainFieldElement + p384FromBytes((*p384UntypedFieldElement)(&tmp), &in) + p384ToMontgomery(&e.x, &tmp) + return e, nil +} + +// Add sets e = t1 + t2, and returns e. +func (e *P384Element) Add(t1, t2 *P384Element) *P384Element { + p384Add(&e.x, &t1.x, &t2.x) + return e +} + +// Sub sets e = t1 - t2, and returns e. +func (e *P384Element) Sub(t1, t2 *P384Element) *P384Element { + p384Sub(&e.x, &t1.x, &t2.x) + return e +} + +// Mul sets e = t1 * t2, and returns e. +func (e *P384Element) Mul(t1, t2 *P384Element) *P384Element { + p384Mul(&e.x, &t1.x, &t2.x) + return e +} + +// Square sets e = t * t, and returns e. +func (e *P384Element) Square(t *P384Element) *P384Element { + p384Square(&e.x, &t.x) + return e +} + +// Select sets v to a if cond == 1, and to b if cond == 0. +func (v *P384Element) Select(a, b *P384Element, cond int) *P384Element { + p384Selectznz((*p384UntypedFieldElement)(&v.x), p384Uint1(cond), + (*p384UntypedFieldElement)(&b.x), (*p384UntypedFieldElement)(&a.x)) + return v +} + +func p384InvertEndianness(v []byte) { + for i := 0; i < len(v)/2; i++ { + v[i], v[len(v)-1-i] = v[len(v)-1-i], v[i] + } +} diff --git a/src/crypto/elliptic/internal/fiat/p384_fiat64.go b/src/crypto/elliptic/internal/fiat/p384_fiat64.go new file mode 100644 index 0000000000..493bed47e1 --- /dev/null +++ b/src/crypto/elliptic/internal/fiat/p384_fiat64.go @@ -0,0 +1,3004 @@ +// Code generated by Fiat Cryptography. DO NOT EDIT. +// +// Autogenerated: word_by_word_montgomery --lang Go --no-wide-int --cmovznz-by-mul --relax-primitive-carry-to-bitwidth 32,64 --internal-static --public-function-case camelCase --public-type-case camelCase --private-function-case camelCase --private-type-case camelCase --doc-text-before-function-name '' --doc-newline-before-package-declaration --doc-prepend-header 'Code generated by Fiat Cryptography. DO NOT EDIT.' --package-name fiat --no-prefix-fiat p384 64 '2^384 - 2^128 - 2^96 + 2^32 - 1' mul square add sub one from_montgomery to_montgomery selectznz to_bytes from_bytes +// +// curve description: p384 +// +// machine_wordsize = 64 (from "64") +// +// requested operations: mul, square, add, sub, one, from_montgomery, to_montgomery, selectznz, to_bytes, from_bytes +// +// m = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff (from "2^384 - 2^128 - 2^96 + 2^32 - 1") +// +// +// +// NOTE: In addition to the bounds specified above each function, all +// +// functions synthesized for this Montgomery arithmetic require the +// +// input to be strictly less than the prime modulus (m), and also +// +// require the input to be in the unique saturated representation. +// +// All functions also ensure that these two properties are true of +// +// return values. +// +// +// +// Computed values: +// +// eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) + (z[4] << 256) + (z[5] << 0x140) +// +// bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) + (z[28] << 224) + (z[29] << 232) + (z[30] << 240) + (z[31] << 248) + (z[32] << 256) + (z[33] << 0x108) + (z[34] << 0x110) + (z[35] << 0x118) + (z[36] << 0x120) + (z[37] << 0x128) + (z[38] << 0x130) + (z[39] << 0x138) + (z[40] << 0x140) + (z[41] << 0x148) + (z[42] << 0x150) + (z[43] << 0x158) + (z[44] << 0x160) + (z[45] << 0x168) + (z[46] << 0x170) + (z[47] << 0x178) +// +// twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) + (z[4] << 256) + (z[5] << 0x140) in +// +// if x1 & (2^384-1) < 2^383 then x1 & (2^384-1) else (x1 & (2^384-1)) - 2^384 + +package fiat + +import "math/bits" + +type p384Uint1 uint64 // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927 +type p384Int1 int64 // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927 + +// The type p384MontgomeryDomainFieldElement is a field element in the Montgomery domain. +// +// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +type p384MontgomeryDomainFieldElement [6]uint64 + +// The type p384NonMontgomeryDomainFieldElement is a field element NOT in the Montgomery domain. +// +// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +type p384NonMontgomeryDomainFieldElement [6]uint64 + +// p384CmovznzU64 is a single-word conditional move. +// +// Postconditions: +// out1 = (if arg1 = 0 then arg2 else arg3) +// +// Input Bounds: +// arg1: [0x0 ~> 0x1] +// arg2: [0x0 ~> 0xffffffffffffffff] +// arg3: [0x0 ~> 0xffffffffffffffff] +// Output Bounds: +// out1: [0x0 ~> 0xffffffffffffffff] +func p384CmovznzU64(out1 *uint64, arg1 p384Uint1, arg2 uint64, arg3 uint64) { + x1 := (uint64(arg1) * 0xffffffffffffffff) + x2 := ((x1 & arg3) | ((^x1) & arg2)) + *out1 = x2 +} + +// p384Mul multiplies two field elements in the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// 0 ≤ eval arg2 < m +// Postconditions: +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m +// 0 ≤ eval out1 < m +// +func p384Mul(out1 *p384MontgomeryDomainFieldElement, arg1 *p384MontgomeryDomainFieldElement, arg2 *p384MontgomeryDomainFieldElement) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[4] + x5 := arg1[5] + x6 := arg1[0] + var x7 uint64 + var x8 uint64 + x8, x7 = bits.Mul64(x6, arg2[5]) + var x9 uint64 + var x10 uint64 + x10, x9 = bits.Mul64(x6, arg2[4]) + var x11 uint64 + var x12 uint64 + x12, x11 = bits.Mul64(x6, arg2[3]) + var x13 uint64 + var x14 uint64 + x14, x13 = bits.Mul64(x6, arg2[2]) + var x15 uint64 + var x16 uint64 + x16, x15 = bits.Mul64(x6, arg2[1]) + var x17 uint64 + var x18 uint64 + x18, x17 = bits.Mul64(x6, arg2[0]) + var x19 uint64 + var x20 uint64 + x19, x20 = bits.Add64(x18, x15, uint64(0x0)) + var x21 uint64 + var x22 uint64 + x21, x22 = bits.Add64(x16, x13, uint64(p384Uint1(x20))) + var x23 uint64 + var x24 uint64 + x23, x24 = bits.Add64(x14, x11, uint64(p384Uint1(x22))) + var x25 uint64 + var x26 uint64 + x25, x26 = bits.Add64(x12, x9, uint64(p384Uint1(x24))) + var x27 uint64 + var x28 uint64 + x27, x28 = bits.Add64(x10, x7, uint64(p384Uint1(x26))) + x29 := (uint64(p384Uint1(x28)) + x8) + var x30 uint64 + _, x30 = bits.Mul64(x17, 0x100000001) + var x32 uint64 + var x33 uint64 + x33, x32 = bits.Mul64(x30, 0xffffffffffffffff) + var x34 uint64 + var x35 uint64 + x35, x34 = bits.Mul64(x30, 0xffffffffffffffff) + var x36 uint64 + var x37 uint64 + x37, x36 = bits.Mul64(x30, 0xffffffffffffffff) + var x38 uint64 + var x39 uint64 + x39, x38 = bits.Mul64(x30, 0xfffffffffffffffe) + var x40 uint64 + var x41 uint64 + x41, x40 = bits.Mul64(x30, 0xffffffff00000000) + var x42 uint64 + var x43 uint64 + x43, x42 = bits.Mul64(x30, 0xffffffff) + var x44 uint64 + var x45 uint64 + x44, x45 = bits.Add64(x43, x40, uint64(0x0)) + var x46 uint64 + var x47 uint64 + x46, x47 = bits.Add64(x41, x38, uint64(p384Uint1(x45))) + var x48 uint64 + var x49 uint64 + x48, x49 = bits.Add64(x39, x36, uint64(p384Uint1(x47))) + var x50 uint64 + var x51 uint64 + x50, x51 = bits.Add64(x37, x34, uint64(p384Uint1(x49))) + var x52 uint64 + var x53 uint64 + x52, x53 = bits.Add64(x35, x32, uint64(p384Uint1(x51))) + x54 := (uint64(p384Uint1(x53)) + x33) + var x56 uint64 + _, x56 = bits.Add64(x17, x42, uint64(0x0)) + var x57 uint64 + var x58 uint64 + x57, x58 = bits.Add64(x19, x44, uint64(p384Uint1(x56))) + var x59 uint64 + var x60 uint64 + x59, x60 = bits.Add64(x21, x46, uint64(p384Uint1(x58))) + var x61 uint64 + var x62 uint64 + x61, x62 = bits.Add64(x23, x48, uint64(p384Uint1(x60))) + var x63 uint64 + var x64 uint64 + x63, x64 = bits.Add64(x25, x50, uint64(p384Uint1(x62))) + var x65 uint64 + var x66 uint64 + x65, x66 = bits.Add64(x27, x52, uint64(p384Uint1(x64))) + var x67 uint64 + var x68 uint64 + x67, x68 = bits.Add64(x29, x54, uint64(p384Uint1(x66))) + var x69 uint64 + var x70 uint64 + x70, x69 = bits.Mul64(x1, arg2[5]) + var x71 uint64 + var x72 uint64 + x72, x71 = bits.Mul64(x1, arg2[4]) + var x73 uint64 + var x74 uint64 + x74, x73 = bits.Mul64(x1, arg2[3]) + var x75 uint64 + var x76 uint64 + x76, x75 = bits.Mul64(x1, arg2[2]) + var x77 uint64 + var x78 uint64 + x78, x77 = bits.Mul64(x1, arg2[1]) + var x79 uint64 + var x80 uint64 + x80, x79 = bits.Mul64(x1, arg2[0]) + var x81 uint64 + var x82 uint64 + x81, x82 = bits.Add64(x80, x77, uint64(0x0)) + var x83 uint64 + var x84 uint64 + x83, x84 = bits.Add64(x78, x75, uint64(p384Uint1(x82))) + var x85 uint64 + var x86 uint64 + x85, x86 = bits.Add64(x76, x73, uint64(p384Uint1(x84))) + var x87 uint64 + var x88 uint64 + x87, x88 = bits.Add64(x74, x71, uint64(p384Uint1(x86))) + var x89 uint64 + var x90 uint64 + x89, x90 = bits.Add64(x72, x69, uint64(p384Uint1(x88))) + x91 := (uint64(p384Uint1(x90)) + x70) + var x92 uint64 + var x93 uint64 + x92, x93 = bits.Add64(x57, x79, uint64(0x0)) + var x94 uint64 + var x95 uint64 + x94, x95 = bits.Add64(x59, x81, uint64(p384Uint1(x93))) + var x96 uint64 + var x97 uint64 + x96, x97 = bits.Add64(x61, x83, uint64(p384Uint1(x95))) + var x98 uint64 + var x99 uint64 + x98, x99 = bits.Add64(x63, x85, uint64(p384Uint1(x97))) + var x100 uint64 + var x101 uint64 + x100, x101 = bits.Add64(x65, x87, uint64(p384Uint1(x99))) + var x102 uint64 + var x103 uint64 + x102, x103 = bits.Add64(x67, x89, uint64(p384Uint1(x101))) + var x104 uint64 + var x105 uint64 + x104, x105 = bits.Add64(uint64(p384Uint1(x68)), x91, uint64(p384Uint1(x103))) + var x106 uint64 + _, x106 = bits.Mul64(x92, 0x100000001) + var x108 uint64 + var x109 uint64 + x109, x108 = bits.Mul64(x106, 0xffffffffffffffff) + var x110 uint64 + var x111 uint64 + x111, x110 = bits.Mul64(x106, 0xffffffffffffffff) + var x112 uint64 + var x113 uint64 + x113, x112 = bits.Mul64(x106, 0xffffffffffffffff) + var x114 uint64 + var x115 uint64 + x115, x114 = bits.Mul64(x106, 0xfffffffffffffffe) + var x116 uint64 + var x117 uint64 + x117, x116 = bits.Mul64(x106, 0xffffffff00000000) + var x118 uint64 + var x119 uint64 + x119, x118 = bits.Mul64(x106, 0xffffffff) + var x120 uint64 + var x121 uint64 + x120, x121 = bits.Add64(x119, x116, uint64(0x0)) + var x122 uint64 + var x123 uint64 + x122, x123 = bits.Add64(x117, x114, uint64(p384Uint1(x121))) + var x124 uint64 + var x125 uint64 + x124, x125 = bits.Add64(x115, x112, uint64(p384Uint1(x123))) + var x126 uint64 + var x127 uint64 + x126, x127 = bits.Add64(x113, x110, uint64(p384Uint1(x125))) + var x128 uint64 + var x129 uint64 + x128, x129 = bits.Add64(x111, x108, uint64(p384Uint1(x127))) + x130 := (uint64(p384Uint1(x129)) + x109) + var x132 uint64 + _, x132 = bits.Add64(x92, x118, uint64(0x0)) + var x133 uint64 + var x134 uint64 + x133, x134 = bits.Add64(x94, x120, uint64(p384Uint1(x132))) + var x135 uint64 + var x136 uint64 + x135, x136 = bits.Add64(x96, x122, uint64(p384Uint1(x134))) + var x137 uint64 + var x138 uint64 + x137, x138 = bits.Add64(x98, x124, uint64(p384Uint1(x136))) + var x139 uint64 + var x140 uint64 + x139, x140 = bits.Add64(x100, x126, uint64(p384Uint1(x138))) + var x141 uint64 + var x142 uint64 + x141, x142 = bits.Add64(x102, x128, uint64(p384Uint1(x140))) + var x143 uint64 + var x144 uint64 + x143, x144 = bits.Add64(x104, x130, uint64(p384Uint1(x142))) + x145 := (uint64(p384Uint1(x144)) + uint64(p384Uint1(x105))) + var x146 uint64 + var x147 uint64 + x147, x146 = bits.Mul64(x2, arg2[5]) + var x148 uint64 + var x149 uint64 + x149, x148 = bits.Mul64(x2, arg2[4]) + var x150 uint64 + var x151 uint64 + x151, x150 = bits.Mul64(x2, arg2[3]) + var x152 uint64 + var x153 uint64 + x153, x152 = bits.Mul64(x2, arg2[2]) + var x154 uint64 + var x155 uint64 + x155, x154 = bits.Mul64(x2, arg2[1]) + var x156 uint64 + var x157 uint64 + x157, x156 = bits.Mul64(x2, arg2[0]) + var x158 uint64 + var x159 uint64 + x158, x159 = bits.Add64(x157, x154, uint64(0x0)) + var x160 uint64 + var x161 uint64 + x160, x161 = bits.Add64(x155, x152, uint64(p384Uint1(x159))) + var x162 uint64 + var x163 uint64 + x162, x163 = bits.Add64(x153, x150, uint64(p384Uint1(x161))) + var x164 uint64 + var x165 uint64 + x164, x165 = bits.Add64(x151, x148, uint64(p384Uint1(x163))) + var x166 uint64 + var x167 uint64 + x166, x167 = bits.Add64(x149, x146, uint64(p384Uint1(x165))) + x168 := (uint64(p384Uint1(x167)) + x147) + var x169 uint64 + var x170 uint64 + x169, x170 = bits.Add64(x133, x156, uint64(0x0)) + var x171 uint64 + var x172 uint64 + x171, x172 = bits.Add64(x135, x158, uint64(p384Uint1(x170))) + var x173 uint64 + var x174 uint64 + x173, x174 = bits.Add64(x137, x160, uint64(p384Uint1(x172))) + var x175 uint64 + var x176 uint64 + x175, x176 = bits.Add64(x139, x162, uint64(p384Uint1(x174))) + var x177 uint64 + var x178 uint64 + x177, x178 = bits.Add64(x141, x164, uint64(p384Uint1(x176))) + var x179 uint64 + var x180 uint64 + x179, x180 = bits.Add64(x143, x166, uint64(p384Uint1(x178))) + var x181 uint64 + var x182 uint64 + x181, x182 = bits.Add64(x145, x168, uint64(p384Uint1(x180))) + var x183 uint64 + _, x183 = bits.Mul64(x169, 0x100000001) + var x185 uint64 + var x186 uint64 + x186, x185 = bits.Mul64(x183, 0xffffffffffffffff) + var x187 uint64 + var x188 uint64 + x188, x187 = bits.Mul64(x183, 0xffffffffffffffff) + var x189 uint64 + var x190 uint64 + x190, x189 = bits.Mul64(x183, 0xffffffffffffffff) + var x191 uint64 + var x192 uint64 + x192, x191 = bits.Mul64(x183, 0xfffffffffffffffe) + var x193 uint64 + var x194 uint64 + x194, x193 = bits.Mul64(x183, 0xffffffff00000000) + var x195 uint64 + var x196 uint64 + x196, x195 = bits.Mul64(x183, 0xffffffff) + var x197 uint64 + var x198 uint64 + x197, x198 = bits.Add64(x196, x193, uint64(0x0)) + var x199 uint64 + var x200 uint64 + x199, x200 = bits.Add64(x194, x191, uint64(p384Uint1(x198))) + var x201 uint64 + var x202 uint64 + x201, x202 = bits.Add64(x192, x189, uint64(p384Uint1(x200))) + var x203 uint64 + var x204 uint64 + x203, x204 = bits.Add64(x190, x187, uint64(p384Uint1(x202))) + var x205 uint64 + var x206 uint64 + x205, x206 = bits.Add64(x188, x185, uint64(p384Uint1(x204))) + x207 := (uint64(p384Uint1(x206)) + x186) + var x209 uint64 + _, x209 = bits.Add64(x169, x195, uint64(0x0)) + var x210 uint64 + var x211 uint64 + x210, x211 = bits.Add64(x171, x197, uint64(p384Uint1(x209))) + var x212 uint64 + var x213 uint64 + x212, x213 = bits.Add64(x173, x199, uint64(p384Uint1(x211))) + var x214 uint64 + var x215 uint64 + x214, x215 = bits.Add64(x175, x201, uint64(p384Uint1(x213))) + var x216 uint64 + var x217 uint64 + x216, x217 = bits.Add64(x177, x203, uint64(p384Uint1(x215))) + var x218 uint64 + var x219 uint64 + x218, x219 = bits.Add64(x179, x205, uint64(p384Uint1(x217))) + var x220 uint64 + var x221 uint64 + x220, x221 = bits.Add64(x181, x207, uint64(p384Uint1(x219))) + x222 := (uint64(p384Uint1(x221)) + uint64(p384Uint1(x182))) + var x223 uint64 + var x224 uint64 + x224, x223 = bits.Mul64(x3, arg2[5]) + var x225 uint64 + var x226 uint64 + x226, x225 = bits.Mul64(x3, arg2[4]) + var x227 uint64 + var x228 uint64 + x228, x227 = bits.Mul64(x3, arg2[3]) + var x229 uint64 + var x230 uint64 + x230, x229 = bits.Mul64(x3, arg2[2]) + var x231 uint64 + var x232 uint64 + x232, x231 = bits.Mul64(x3, arg2[1]) + var x233 uint64 + var x234 uint64 + x234, x233 = bits.Mul64(x3, arg2[0]) + var x235 uint64 + var x236 uint64 + x235, x236 = bits.Add64(x234, x231, uint64(0x0)) + var x237 uint64 + var x238 uint64 + x237, x238 = bits.Add64(x232, x229, uint64(p384Uint1(x236))) + var x239 uint64 + var x240 uint64 + x239, x240 = bits.Add64(x230, x227, uint64(p384Uint1(x238))) + var x241 uint64 + var x242 uint64 + x241, x242 = bits.Add64(x228, x225, uint64(p384Uint1(x240))) + var x243 uint64 + var x244 uint64 + x243, x244 = bits.Add64(x226, x223, uint64(p384Uint1(x242))) + x245 := (uint64(p384Uint1(x244)) + x224) + var x246 uint64 + var x247 uint64 + x246, x247 = bits.Add64(x210, x233, uint64(0x0)) + var x248 uint64 + var x249 uint64 + x248, x249 = bits.Add64(x212, x235, uint64(p384Uint1(x247))) + var x250 uint64 + var x251 uint64 + x250, x251 = bits.Add64(x214, x237, uint64(p384Uint1(x249))) + var x252 uint64 + var x253 uint64 + x252, x253 = bits.Add64(x216, x239, uint64(p384Uint1(x251))) + var x254 uint64 + var x255 uint64 + x254, x255 = bits.Add64(x218, x241, uint64(p384Uint1(x253))) + var x256 uint64 + var x257 uint64 + x256, x257 = bits.Add64(x220, x243, uint64(p384Uint1(x255))) + var x258 uint64 + var x259 uint64 + x258, x259 = bits.Add64(x222, x245, uint64(p384Uint1(x257))) + var x260 uint64 + _, x260 = bits.Mul64(x246, 0x100000001) + var x262 uint64 + var x263 uint64 + x263, x262 = bits.Mul64(x260, 0xffffffffffffffff) + var x264 uint64 + var x265 uint64 + x265, x264 = bits.Mul64(x260, 0xffffffffffffffff) + var x266 uint64 + var x267 uint64 + x267, x266 = bits.Mul64(x260, 0xffffffffffffffff) + var x268 uint64 + var x269 uint64 + x269, x268 = bits.Mul64(x260, 0xfffffffffffffffe) + var x270 uint64 + var x271 uint64 + x271, x270 = bits.Mul64(x260, 0xffffffff00000000) + var x272 uint64 + var x273 uint64 + x273, x272 = bits.Mul64(x260, 0xffffffff) + var x274 uint64 + var x275 uint64 + x274, x275 = bits.Add64(x273, x270, uint64(0x0)) + var x276 uint64 + var x277 uint64 + x276, x277 = bits.Add64(x271, x268, uint64(p384Uint1(x275))) + var x278 uint64 + var x279 uint64 + x278, x279 = bits.Add64(x269, x266, uint64(p384Uint1(x277))) + var x280 uint64 + var x281 uint64 + x280, x281 = bits.Add64(x267, x264, uint64(p384Uint1(x279))) + var x282 uint64 + var x283 uint64 + x282, x283 = bits.Add64(x265, x262, uint64(p384Uint1(x281))) + x284 := (uint64(p384Uint1(x283)) + x263) + var x286 uint64 + _, x286 = bits.Add64(x246, x272, uint64(0x0)) + var x287 uint64 + var x288 uint64 + x287, x288 = bits.Add64(x248, x274, uint64(p384Uint1(x286))) + var x289 uint64 + var x290 uint64 + x289, x290 = bits.Add64(x250, x276, uint64(p384Uint1(x288))) + var x291 uint64 + var x292 uint64 + x291, x292 = bits.Add64(x252, x278, uint64(p384Uint1(x290))) + var x293 uint64 + var x294 uint64 + x293, x294 = bits.Add64(x254, x280, uint64(p384Uint1(x292))) + var x295 uint64 + var x296 uint64 + x295, x296 = bits.Add64(x256, x282, uint64(p384Uint1(x294))) + var x297 uint64 + var x298 uint64 + x297, x298 = bits.Add64(x258, x284, uint64(p384Uint1(x296))) + x299 := (uint64(p384Uint1(x298)) + uint64(p384Uint1(x259))) + var x300 uint64 + var x301 uint64 + x301, x300 = bits.Mul64(x4, arg2[5]) + var x302 uint64 + var x303 uint64 + x303, x302 = bits.Mul64(x4, arg2[4]) + var x304 uint64 + var x305 uint64 + x305, x304 = bits.Mul64(x4, arg2[3]) + var x306 uint64 + var x307 uint64 + x307, x306 = bits.Mul64(x4, arg2[2]) + var x308 uint64 + var x309 uint64 + x309, x308 = bits.Mul64(x4, arg2[1]) + var x310 uint64 + var x311 uint64 + x311, x310 = bits.Mul64(x4, arg2[0]) + var x312 uint64 + var x313 uint64 + x312, x313 = bits.Add64(x311, x308, uint64(0x0)) + var x314 uint64 + var x315 uint64 + x314, x315 = bits.Add64(x309, x306, uint64(p384Uint1(x313))) + var x316 uint64 + var x317 uint64 + x316, x317 = bits.Add64(x307, x304, uint64(p384Uint1(x315))) + var x318 uint64 + var x319 uint64 + x318, x319 = bits.Add64(x305, x302, uint64(p384Uint1(x317))) + var x320 uint64 + var x321 uint64 + x320, x321 = bits.Add64(x303, x300, uint64(p384Uint1(x319))) + x322 := (uint64(p384Uint1(x321)) + x301) + var x323 uint64 + var x324 uint64 + x323, x324 = bits.Add64(x287, x310, uint64(0x0)) + var x325 uint64 + var x326 uint64 + x325, x326 = bits.Add64(x289, x312, uint64(p384Uint1(x324))) + var x327 uint64 + var x328 uint64 + x327, x328 = bits.Add64(x291, x314, uint64(p384Uint1(x326))) + var x329 uint64 + var x330 uint64 + x329, x330 = bits.Add64(x293, x316, uint64(p384Uint1(x328))) + var x331 uint64 + var x332 uint64 + x331, x332 = bits.Add64(x295, x318, uint64(p384Uint1(x330))) + var x333 uint64 + var x334 uint64 + x333, x334 = bits.Add64(x297, x320, uint64(p384Uint1(x332))) + var x335 uint64 + var x336 uint64 + x335, x336 = bits.Add64(x299, x322, uint64(p384Uint1(x334))) + var x337 uint64 + _, x337 = bits.Mul64(x323, 0x100000001) + var x339 uint64 + var x340 uint64 + x340, x339 = bits.Mul64(x337, 0xffffffffffffffff) + var x341 uint64 + var x342 uint64 + x342, x341 = bits.Mul64(x337, 0xffffffffffffffff) + var x343 uint64 + var x344 uint64 + x344, x343 = bits.Mul64(x337, 0xffffffffffffffff) + var x345 uint64 + var x346 uint64 + x346, x345 = bits.Mul64(x337, 0xfffffffffffffffe) + var x347 uint64 + var x348 uint64 + x348, x347 = bits.Mul64(x337, 0xffffffff00000000) + var x349 uint64 + var x350 uint64 + x350, x349 = bits.Mul64(x337, 0xffffffff) + var x351 uint64 + var x352 uint64 + x351, x352 = bits.Add64(x350, x347, uint64(0x0)) + var x353 uint64 + var x354 uint64 + x353, x354 = bits.Add64(x348, x345, uint64(p384Uint1(x352))) + var x355 uint64 + var x356 uint64 + x355, x356 = bits.Add64(x346, x343, uint64(p384Uint1(x354))) + var x357 uint64 + var x358 uint64 + x357, x358 = bits.Add64(x344, x341, uint64(p384Uint1(x356))) + var x359 uint64 + var x360 uint64 + x359, x360 = bits.Add64(x342, x339, uint64(p384Uint1(x358))) + x361 := (uint64(p384Uint1(x360)) + x340) + var x363 uint64 + _, x363 = bits.Add64(x323, x349, uint64(0x0)) + var x364 uint64 + var x365 uint64 + x364, x365 = bits.Add64(x325, x351, uint64(p384Uint1(x363))) + var x366 uint64 + var x367 uint64 + x366, x367 = bits.Add64(x327, x353, uint64(p384Uint1(x365))) + var x368 uint64 + var x369 uint64 + x368, x369 = bits.Add64(x329, x355, uint64(p384Uint1(x367))) + var x370 uint64 + var x371 uint64 + x370, x371 = bits.Add64(x331, x357, uint64(p384Uint1(x369))) + var x372 uint64 + var x373 uint64 + x372, x373 = bits.Add64(x333, x359, uint64(p384Uint1(x371))) + var x374 uint64 + var x375 uint64 + x374, x375 = bits.Add64(x335, x361, uint64(p384Uint1(x373))) + x376 := (uint64(p384Uint1(x375)) + uint64(p384Uint1(x336))) + var x377 uint64 + var x378 uint64 + x378, x377 = bits.Mul64(x5, arg2[5]) + var x379 uint64 + var x380 uint64 + x380, x379 = bits.Mul64(x5, arg2[4]) + var x381 uint64 + var x382 uint64 + x382, x381 = bits.Mul64(x5, arg2[3]) + var x383 uint64 + var x384 uint64 + x384, x383 = bits.Mul64(x5, arg2[2]) + var x385 uint64 + var x386 uint64 + x386, x385 = bits.Mul64(x5, arg2[1]) + var x387 uint64 + var x388 uint64 + x388, x387 = bits.Mul64(x5, arg2[0]) + var x389 uint64 + var x390 uint64 + x389, x390 = bits.Add64(x388, x385, uint64(0x0)) + var x391 uint64 + var x392 uint64 + x391, x392 = bits.Add64(x386, x383, uint64(p384Uint1(x390))) + var x393 uint64 + var x394 uint64 + x393, x394 = bits.Add64(x384, x381, uint64(p384Uint1(x392))) + var x395 uint64 + var x396 uint64 + x395, x396 = bits.Add64(x382, x379, uint64(p384Uint1(x394))) + var x397 uint64 + var x398 uint64 + x397, x398 = bits.Add64(x380, x377, uint64(p384Uint1(x396))) + x399 := (uint64(p384Uint1(x398)) + x378) + var x400 uint64 + var x401 uint64 + x400, x401 = bits.Add64(x364, x387, uint64(0x0)) + var x402 uint64 + var x403 uint64 + x402, x403 = bits.Add64(x366, x389, uint64(p384Uint1(x401))) + var x404 uint64 + var x405 uint64 + x404, x405 = bits.Add64(x368, x391, uint64(p384Uint1(x403))) + var x406 uint64 + var x407 uint64 + x406, x407 = bits.Add64(x370, x393, uint64(p384Uint1(x405))) + var x408 uint64 + var x409 uint64 + x408, x409 = bits.Add64(x372, x395, uint64(p384Uint1(x407))) + var x410 uint64 + var x411 uint64 + x410, x411 = bits.Add64(x374, x397, uint64(p384Uint1(x409))) + var x412 uint64 + var x413 uint64 + x412, x413 = bits.Add64(x376, x399, uint64(p384Uint1(x411))) + var x414 uint64 + _, x414 = bits.Mul64(x400, 0x100000001) + var x416 uint64 + var x417 uint64 + x417, x416 = bits.Mul64(x414, 0xffffffffffffffff) + var x418 uint64 + var x419 uint64 + x419, x418 = bits.Mul64(x414, 0xffffffffffffffff) + var x420 uint64 + var x421 uint64 + x421, x420 = bits.Mul64(x414, 0xffffffffffffffff) + var x422 uint64 + var x423 uint64 + x423, x422 = bits.Mul64(x414, 0xfffffffffffffffe) + var x424 uint64 + var x425 uint64 + x425, x424 = bits.Mul64(x414, 0xffffffff00000000) + var x426 uint64 + var x427 uint64 + x427, x426 = bits.Mul64(x414, 0xffffffff) + var x428 uint64 + var x429 uint64 + x428, x429 = bits.Add64(x427, x424, uint64(0x0)) + var x430 uint64 + var x431 uint64 + x430, x431 = bits.Add64(x425, x422, uint64(p384Uint1(x429))) + var x432 uint64 + var x433 uint64 + x432, x433 = bits.Add64(x423, x420, uint64(p384Uint1(x431))) + var x434 uint64 + var x435 uint64 + x434, x435 = bits.Add64(x421, x418, uint64(p384Uint1(x433))) + var x436 uint64 + var x437 uint64 + x436, x437 = bits.Add64(x419, x416, uint64(p384Uint1(x435))) + x438 := (uint64(p384Uint1(x437)) + x417) + var x440 uint64 + _, x440 = bits.Add64(x400, x426, uint64(0x0)) + var x441 uint64 + var x442 uint64 + x441, x442 = bits.Add64(x402, x428, uint64(p384Uint1(x440))) + var x443 uint64 + var x444 uint64 + x443, x444 = bits.Add64(x404, x430, uint64(p384Uint1(x442))) + var x445 uint64 + var x446 uint64 + x445, x446 = bits.Add64(x406, x432, uint64(p384Uint1(x444))) + var x447 uint64 + var x448 uint64 + x447, x448 = bits.Add64(x408, x434, uint64(p384Uint1(x446))) + var x449 uint64 + var x450 uint64 + x449, x450 = bits.Add64(x410, x436, uint64(p384Uint1(x448))) + var x451 uint64 + var x452 uint64 + x451, x452 = bits.Add64(x412, x438, uint64(p384Uint1(x450))) + x453 := (uint64(p384Uint1(x452)) + uint64(p384Uint1(x413))) + var x454 uint64 + var x455 uint64 + x454, x455 = bits.Sub64(x441, 0xffffffff, uint64(0x0)) + var x456 uint64 + var x457 uint64 + x456, x457 = bits.Sub64(x443, 0xffffffff00000000, uint64(p384Uint1(x455))) + var x458 uint64 + var x459 uint64 + x458, x459 = bits.Sub64(x445, 0xfffffffffffffffe, uint64(p384Uint1(x457))) + var x460 uint64 + var x461 uint64 + x460, x461 = bits.Sub64(x447, 0xffffffffffffffff, uint64(p384Uint1(x459))) + var x462 uint64 + var x463 uint64 + x462, x463 = bits.Sub64(x449, 0xffffffffffffffff, uint64(p384Uint1(x461))) + var x464 uint64 + var x465 uint64 + x464, x465 = bits.Sub64(x451, 0xffffffffffffffff, uint64(p384Uint1(x463))) + var x467 uint64 + _, x467 = bits.Sub64(x453, uint64(0x0), uint64(p384Uint1(x465))) + var x468 uint64 + p384CmovznzU64(&x468, p384Uint1(x467), x454, x441) + var x469 uint64 + p384CmovznzU64(&x469, p384Uint1(x467), x456, x443) + var x470 uint64 + p384CmovznzU64(&x470, p384Uint1(x467), x458, x445) + var x471 uint64 + p384CmovznzU64(&x471, p384Uint1(x467), x460, x447) + var x472 uint64 + p384CmovznzU64(&x472, p384Uint1(x467), x462, x449) + var x473 uint64 + p384CmovznzU64(&x473, p384Uint1(x467), x464, x451) + out1[0] = x468 + out1[1] = x469 + out1[2] = x470 + out1[3] = x471 + out1[4] = x472 + out1[5] = x473 +} + +// p384Square squares a field element in the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// Postconditions: +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg1)) mod m +// 0 ≤ eval out1 < m +// +func p384Square(out1 *p384MontgomeryDomainFieldElement, arg1 *p384MontgomeryDomainFieldElement) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[4] + x5 := arg1[5] + x6 := arg1[0] + var x7 uint64 + var x8 uint64 + x8, x7 = bits.Mul64(x6, arg1[5]) + var x9 uint64 + var x10 uint64 + x10, x9 = bits.Mul64(x6, arg1[4]) + var x11 uint64 + var x12 uint64 + x12, x11 = bits.Mul64(x6, arg1[3]) + var x13 uint64 + var x14 uint64 + x14, x13 = bits.Mul64(x6, arg1[2]) + var x15 uint64 + var x16 uint64 + x16, x15 = bits.Mul64(x6, arg1[1]) + var x17 uint64 + var x18 uint64 + x18, x17 = bits.Mul64(x6, arg1[0]) + var x19 uint64 + var x20 uint64 + x19, x20 = bits.Add64(x18, x15, uint64(0x0)) + var x21 uint64 + var x22 uint64 + x21, x22 = bits.Add64(x16, x13, uint64(p384Uint1(x20))) + var x23 uint64 + var x24 uint64 + x23, x24 = bits.Add64(x14, x11, uint64(p384Uint1(x22))) + var x25 uint64 + var x26 uint64 + x25, x26 = bits.Add64(x12, x9, uint64(p384Uint1(x24))) + var x27 uint64 + var x28 uint64 + x27, x28 = bits.Add64(x10, x7, uint64(p384Uint1(x26))) + x29 := (uint64(p384Uint1(x28)) + x8) + var x30 uint64 + _, x30 = bits.Mul64(x17, 0x100000001) + var x32 uint64 + var x33 uint64 + x33, x32 = bits.Mul64(x30, 0xffffffffffffffff) + var x34 uint64 + var x35 uint64 + x35, x34 = bits.Mul64(x30, 0xffffffffffffffff) + var x36 uint64 + var x37 uint64 + x37, x36 = bits.Mul64(x30, 0xffffffffffffffff) + var x38 uint64 + var x39 uint64 + x39, x38 = bits.Mul64(x30, 0xfffffffffffffffe) + var x40 uint64 + var x41 uint64 + x41, x40 = bits.Mul64(x30, 0xffffffff00000000) + var x42 uint64 + var x43 uint64 + x43, x42 = bits.Mul64(x30, 0xffffffff) + var x44 uint64 + var x45 uint64 + x44, x45 = bits.Add64(x43, x40, uint64(0x0)) + var x46 uint64 + var x47 uint64 + x46, x47 = bits.Add64(x41, x38, uint64(p384Uint1(x45))) + var x48 uint64 + var x49 uint64 + x48, x49 = bits.Add64(x39, x36, uint64(p384Uint1(x47))) + var x50 uint64 + var x51 uint64 + x50, x51 = bits.Add64(x37, x34, uint64(p384Uint1(x49))) + var x52 uint64 + var x53 uint64 + x52, x53 = bits.Add64(x35, x32, uint64(p384Uint1(x51))) + x54 := (uint64(p384Uint1(x53)) + x33) + var x56 uint64 + _, x56 = bits.Add64(x17, x42, uint64(0x0)) + var x57 uint64 + var x58 uint64 + x57, x58 = bits.Add64(x19, x44, uint64(p384Uint1(x56))) + var x59 uint64 + var x60 uint64 + x59, x60 = bits.Add64(x21, x46, uint64(p384Uint1(x58))) + var x61 uint64 + var x62 uint64 + x61, x62 = bits.Add64(x23, x48, uint64(p384Uint1(x60))) + var x63 uint64 + var x64 uint64 + x63, x64 = bits.Add64(x25, x50, uint64(p384Uint1(x62))) + var x65 uint64 + var x66 uint64 + x65, x66 = bits.Add64(x27, x52, uint64(p384Uint1(x64))) + var x67 uint64 + var x68 uint64 + x67, x68 = bits.Add64(x29, x54, uint64(p384Uint1(x66))) + var x69 uint64 + var x70 uint64 + x70, x69 = bits.Mul64(x1, arg1[5]) + var x71 uint64 + var x72 uint64 + x72, x71 = bits.Mul64(x1, arg1[4]) + var x73 uint64 + var x74 uint64 + x74, x73 = bits.Mul64(x1, arg1[3]) + var x75 uint64 + var x76 uint64 + x76, x75 = bits.Mul64(x1, arg1[2]) + var x77 uint64 + var x78 uint64 + x78, x77 = bits.Mul64(x1, arg1[1]) + var x79 uint64 + var x80 uint64 + x80, x79 = bits.Mul64(x1, arg1[0]) + var x81 uint64 + var x82 uint64 + x81, x82 = bits.Add64(x80, x77, uint64(0x0)) + var x83 uint64 + var x84 uint64 + x83, x84 = bits.Add64(x78, x75, uint64(p384Uint1(x82))) + var x85 uint64 + var x86 uint64 + x85, x86 = bits.Add64(x76, x73, uint64(p384Uint1(x84))) + var x87 uint64 + var x88 uint64 + x87, x88 = bits.Add64(x74, x71, uint64(p384Uint1(x86))) + var x89 uint64 + var x90 uint64 + x89, x90 = bits.Add64(x72, x69, uint64(p384Uint1(x88))) + x91 := (uint64(p384Uint1(x90)) + x70) + var x92 uint64 + var x93 uint64 + x92, x93 = bits.Add64(x57, x79, uint64(0x0)) + var x94 uint64 + var x95 uint64 + x94, x95 = bits.Add64(x59, x81, uint64(p384Uint1(x93))) + var x96 uint64 + var x97 uint64 + x96, x97 = bits.Add64(x61, x83, uint64(p384Uint1(x95))) + var x98 uint64 + var x99 uint64 + x98, x99 = bits.Add64(x63, x85, uint64(p384Uint1(x97))) + var x100 uint64 + var x101 uint64 + x100, x101 = bits.Add64(x65, x87, uint64(p384Uint1(x99))) + var x102 uint64 + var x103 uint64 + x102, x103 = bits.Add64(x67, x89, uint64(p384Uint1(x101))) + var x104 uint64 + var x105 uint64 + x104, x105 = bits.Add64(uint64(p384Uint1(x68)), x91, uint64(p384Uint1(x103))) + var x106 uint64 + _, x106 = bits.Mul64(x92, 0x100000001) + var x108 uint64 + var x109 uint64 + x109, x108 = bits.Mul64(x106, 0xffffffffffffffff) + var x110 uint64 + var x111 uint64 + x111, x110 = bits.Mul64(x106, 0xffffffffffffffff) + var x112 uint64 + var x113 uint64 + x113, x112 = bits.Mul64(x106, 0xffffffffffffffff) + var x114 uint64 + var x115 uint64 + x115, x114 = bits.Mul64(x106, 0xfffffffffffffffe) + var x116 uint64 + var x117 uint64 + x117, x116 = bits.Mul64(x106, 0xffffffff00000000) + var x118 uint64 + var x119 uint64 + x119, x118 = bits.Mul64(x106, 0xffffffff) + var x120 uint64 + var x121 uint64 + x120, x121 = bits.Add64(x119, x116, uint64(0x0)) + var x122 uint64 + var x123 uint64 + x122, x123 = bits.Add64(x117, x114, uint64(p384Uint1(x121))) + var x124 uint64 + var x125 uint64 + x124, x125 = bits.Add64(x115, x112, uint64(p384Uint1(x123))) + var x126 uint64 + var x127 uint64 + x126, x127 = bits.Add64(x113, x110, uint64(p384Uint1(x125))) + var x128 uint64 + var x129 uint64 + x128, x129 = bits.Add64(x111, x108, uint64(p384Uint1(x127))) + x130 := (uint64(p384Uint1(x129)) + x109) + var x132 uint64 + _, x132 = bits.Add64(x92, x118, uint64(0x0)) + var x133 uint64 + var x134 uint64 + x133, x134 = bits.Add64(x94, x120, uint64(p384Uint1(x132))) + var x135 uint64 + var x136 uint64 + x135, x136 = bits.Add64(x96, x122, uint64(p384Uint1(x134))) + var x137 uint64 + var x138 uint64 + x137, x138 = bits.Add64(x98, x124, uint64(p384Uint1(x136))) + var x139 uint64 + var x140 uint64 + x139, x140 = bits.Add64(x100, x126, uint64(p384Uint1(x138))) + var x141 uint64 + var x142 uint64 + x141, x142 = bits.Add64(x102, x128, uint64(p384Uint1(x140))) + var x143 uint64 + var x144 uint64 + x143, x144 = bits.Add64(x104, x130, uint64(p384Uint1(x142))) + x145 := (uint64(p384Uint1(x144)) + uint64(p384Uint1(x105))) + var x146 uint64 + var x147 uint64 + x147, x146 = bits.Mul64(x2, arg1[5]) + var x148 uint64 + var x149 uint64 + x149, x148 = bits.Mul64(x2, arg1[4]) + var x150 uint64 + var x151 uint64 + x151, x150 = bits.Mul64(x2, arg1[3]) + var x152 uint64 + var x153 uint64 + x153, x152 = bits.Mul64(x2, arg1[2]) + var x154 uint64 + var x155 uint64 + x155, x154 = bits.Mul64(x2, arg1[1]) + var x156 uint64 + var x157 uint64 + x157, x156 = bits.Mul64(x2, arg1[0]) + var x158 uint64 + var x159 uint64 + x158, x159 = bits.Add64(x157, x154, uint64(0x0)) + var x160 uint64 + var x161 uint64 + x160, x161 = bits.Add64(x155, x152, uint64(p384Uint1(x159))) + var x162 uint64 + var x163 uint64 + x162, x163 = bits.Add64(x153, x150, uint64(p384Uint1(x161))) + var x164 uint64 + var x165 uint64 + x164, x165 = bits.Add64(x151, x148, uint64(p384Uint1(x163))) + var x166 uint64 + var x167 uint64 + x166, x167 = bits.Add64(x149, x146, uint64(p384Uint1(x165))) + x168 := (uint64(p384Uint1(x167)) + x147) + var x169 uint64 + var x170 uint64 + x169, x170 = bits.Add64(x133, x156, uint64(0x0)) + var x171 uint64 + var x172 uint64 + x171, x172 = bits.Add64(x135, x158, uint64(p384Uint1(x170))) + var x173 uint64 + var x174 uint64 + x173, x174 = bits.Add64(x137, x160, uint64(p384Uint1(x172))) + var x175 uint64 + var x176 uint64 + x175, x176 = bits.Add64(x139, x162, uint64(p384Uint1(x174))) + var x177 uint64 + var x178 uint64 + x177, x178 = bits.Add64(x141, x164, uint64(p384Uint1(x176))) + var x179 uint64 + var x180 uint64 + x179, x180 = bits.Add64(x143, x166, uint64(p384Uint1(x178))) + var x181 uint64 + var x182 uint64 + x181, x182 = bits.Add64(x145, x168, uint64(p384Uint1(x180))) + var x183 uint64 + _, x183 = bits.Mul64(x169, 0x100000001) + var x185 uint64 + var x186 uint64 + x186, x185 = bits.Mul64(x183, 0xffffffffffffffff) + var x187 uint64 + var x188 uint64 + x188, x187 = bits.Mul64(x183, 0xffffffffffffffff) + var x189 uint64 + var x190 uint64 + x190, x189 = bits.Mul64(x183, 0xffffffffffffffff) + var x191 uint64 + var x192 uint64 + x192, x191 = bits.Mul64(x183, 0xfffffffffffffffe) + var x193 uint64 + var x194 uint64 + x194, x193 = bits.Mul64(x183, 0xffffffff00000000) + var x195 uint64 + var x196 uint64 + x196, x195 = bits.Mul64(x183, 0xffffffff) + var x197 uint64 + var x198 uint64 + x197, x198 = bits.Add64(x196, x193, uint64(0x0)) + var x199 uint64 + var x200 uint64 + x199, x200 = bits.Add64(x194, x191, uint64(p384Uint1(x198))) + var x201 uint64 + var x202 uint64 + x201, x202 = bits.Add64(x192, x189, uint64(p384Uint1(x200))) + var x203 uint64 + var x204 uint64 + x203, x204 = bits.Add64(x190, x187, uint64(p384Uint1(x202))) + var x205 uint64 + var x206 uint64 + x205, x206 = bits.Add64(x188, x185, uint64(p384Uint1(x204))) + x207 := (uint64(p384Uint1(x206)) + x186) + var x209 uint64 + _, x209 = bits.Add64(x169, x195, uint64(0x0)) + var x210 uint64 + var x211 uint64 + x210, x211 = bits.Add64(x171, x197, uint64(p384Uint1(x209))) + var x212 uint64 + var x213 uint64 + x212, x213 = bits.Add64(x173, x199, uint64(p384Uint1(x211))) + var x214 uint64 + var x215 uint64 + x214, x215 = bits.Add64(x175, x201, uint64(p384Uint1(x213))) + var x216 uint64 + var x217 uint64 + x216, x217 = bits.Add64(x177, x203, uint64(p384Uint1(x215))) + var x218 uint64 + var x219 uint64 + x218, x219 = bits.Add64(x179, x205, uint64(p384Uint1(x217))) + var x220 uint64 + var x221 uint64 + x220, x221 = bits.Add64(x181, x207, uint64(p384Uint1(x219))) + x222 := (uint64(p384Uint1(x221)) + uint64(p384Uint1(x182))) + var x223 uint64 + var x224 uint64 + x224, x223 = bits.Mul64(x3, arg1[5]) + var x225 uint64 + var x226 uint64 + x226, x225 = bits.Mul64(x3, arg1[4]) + var x227 uint64 + var x228 uint64 + x228, x227 = bits.Mul64(x3, arg1[3]) + var x229 uint64 + var x230 uint64 + x230, x229 = bits.Mul64(x3, arg1[2]) + var x231 uint64 + var x232 uint64 + x232, x231 = bits.Mul64(x3, arg1[1]) + var x233 uint64 + var x234 uint64 + x234, x233 = bits.Mul64(x3, arg1[0]) + var x235 uint64 + var x236 uint64 + x235, x236 = bits.Add64(x234, x231, uint64(0x0)) + var x237 uint64 + var x238 uint64 + x237, x238 = bits.Add64(x232, x229, uint64(p384Uint1(x236))) + var x239 uint64 + var x240 uint64 + x239, x240 = bits.Add64(x230, x227, uint64(p384Uint1(x238))) + var x241 uint64 + var x242 uint64 + x241, x242 = bits.Add64(x228, x225, uint64(p384Uint1(x240))) + var x243 uint64 + var x244 uint64 + x243, x244 = bits.Add64(x226, x223, uint64(p384Uint1(x242))) + x245 := (uint64(p384Uint1(x244)) + x224) + var x246 uint64 + var x247 uint64 + x246, x247 = bits.Add64(x210, x233, uint64(0x0)) + var x248 uint64 + var x249 uint64 + x248, x249 = bits.Add64(x212, x235, uint64(p384Uint1(x247))) + var x250 uint64 + var x251 uint64 + x250, x251 = bits.Add64(x214, x237, uint64(p384Uint1(x249))) + var x252 uint64 + var x253 uint64 + x252, x253 = bits.Add64(x216, x239, uint64(p384Uint1(x251))) + var x254 uint64 + var x255 uint64 + x254, x255 = bits.Add64(x218, x241, uint64(p384Uint1(x253))) + var x256 uint64 + var x257 uint64 + x256, x257 = bits.Add64(x220, x243, uint64(p384Uint1(x255))) + var x258 uint64 + var x259 uint64 + x258, x259 = bits.Add64(x222, x245, uint64(p384Uint1(x257))) + var x260 uint64 + _, x260 = bits.Mul64(x246, 0x100000001) + var x262 uint64 + var x263 uint64 + x263, x262 = bits.Mul64(x260, 0xffffffffffffffff) + var x264 uint64 + var x265 uint64 + x265, x264 = bits.Mul64(x260, 0xffffffffffffffff) + var x266 uint64 + var x267 uint64 + x267, x266 = bits.Mul64(x260, 0xffffffffffffffff) + var x268 uint64 + var x269 uint64 + x269, x268 = bits.Mul64(x260, 0xfffffffffffffffe) + var x270 uint64 + var x271 uint64 + x271, x270 = bits.Mul64(x260, 0xffffffff00000000) + var x272 uint64 + var x273 uint64 + x273, x272 = bits.Mul64(x260, 0xffffffff) + var x274 uint64 + var x275 uint64 + x274, x275 = bits.Add64(x273, x270, uint64(0x0)) + var x276 uint64 + var x277 uint64 + x276, x277 = bits.Add64(x271, x268, uint64(p384Uint1(x275))) + var x278 uint64 + var x279 uint64 + x278, x279 = bits.Add64(x269, x266, uint64(p384Uint1(x277))) + var x280 uint64 + var x281 uint64 + x280, x281 = bits.Add64(x267, x264, uint64(p384Uint1(x279))) + var x282 uint64 + var x283 uint64 + x282, x283 = bits.Add64(x265, x262, uint64(p384Uint1(x281))) + x284 := (uint64(p384Uint1(x283)) + x263) + var x286 uint64 + _, x286 = bits.Add64(x246, x272, uint64(0x0)) + var x287 uint64 + var x288 uint64 + x287, x288 = bits.Add64(x248, x274, uint64(p384Uint1(x286))) + var x289 uint64 + var x290 uint64 + x289, x290 = bits.Add64(x250, x276, uint64(p384Uint1(x288))) + var x291 uint64 + var x292 uint64 + x291, x292 = bits.Add64(x252, x278, uint64(p384Uint1(x290))) + var x293 uint64 + var x294 uint64 + x293, x294 = bits.Add64(x254, x280, uint64(p384Uint1(x292))) + var x295 uint64 + var x296 uint64 + x295, x296 = bits.Add64(x256, x282, uint64(p384Uint1(x294))) + var x297 uint64 + var x298 uint64 + x297, x298 = bits.Add64(x258, x284, uint64(p384Uint1(x296))) + x299 := (uint64(p384Uint1(x298)) + uint64(p384Uint1(x259))) + var x300 uint64 + var x301 uint64 + x301, x300 = bits.Mul64(x4, arg1[5]) + var x302 uint64 + var x303 uint64 + x303, x302 = bits.Mul64(x4, arg1[4]) + var x304 uint64 + var x305 uint64 + x305, x304 = bits.Mul64(x4, arg1[3]) + var x306 uint64 + var x307 uint64 + x307, x306 = bits.Mul64(x4, arg1[2]) + var x308 uint64 + var x309 uint64 + x309, x308 = bits.Mul64(x4, arg1[1]) + var x310 uint64 + var x311 uint64 + x311, x310 = bits.Mul64(x4, arg1[0]) + var x312 uint64 + var x313 uint64 + x312, x313 = bits.Add64(x311, x308, uint64(0x0)) + var x314 uint64 + var x315 uint64 + x314, x315 = bits.Add64(x309, x306, uint64(p384Uint1(x313))) + var x316 uint64 + var x317 uint64 + x316, x317 = bits.Add64(x307, x304, uint64(p384Uint1(x315))) + var x318 uint64 + var x319 uint64 + x318, x319 = bits.Add64(x305, x302, uint64(p384Uint1(x317))) + var x320 uint64 + var x321 uint64 + x320, x321 = bits.Add64(x303, x300, uint64(p384Uint1(x319))) + x322 := (uint64(p384Uint1(x321)) + x301) + var x323 uint64 + var x324 uint64 + x323, x324 = bits.Add64(x287, x310, uint64(0x0)) + var x325 uint64 + var x326 uint64 + x325, x326 = bits.Add64(x289, x312, uint64(p384Uint1(x324))) + var x327 uint64 + var x328 uint64 + x327, x328 = bits.Add64(x291, x314, uint64(p384Uint1(x326))) + var x329 uint64 + var x330 uint64 + x329, x330 = bits.Add64(x293, x316, uint64(p384Uint1(x328))) + var x331 uint64 + var x332 uint64 + x331, x332 = bits.Add64(x295, x318, uint64(p384Uint1(x330))) + var x333 uint64 + var x334 uint64 + x333, x334 = bits.Add64(x297, x320, uint64(p384Uint1(x332))) + var x335 uint64 + var x336 uint64 + x335, x336 = bits.Add64(x299, x322, uint64(p384Uint1(x334))) + var x337 uint64 + _, x337 = bits.Mul64(x323, 0x100000001) + var x339 uint64 + var x340 uint64 + x340, x339 = bits.Mul64(x337, 0xffffffffffffffff) + var x341 uint64 + var x342 uint64 + x342, x341 = bits.Mul64(x337, 0xffffffffffffffff) + var x343 uint64 + var x344 uint64 + x344, x343 = bits.Mul64(x337, 0xffffffffffffffff) + var x345 uint64 + var x346 uint64 + x346, x345 = bits.Mul64(x337, 0xfffffffffffffffe) + var x347 uint64 + var x348 uint64 + x348, x347 = bits.Mul64(x337, 0xffffffff00000000) + var x349 uint64 + var x350 uint64 + x350, x349 = bits.Mul64(x337, 0xffffffff) + var x351 uint64 + var x352 uint64 + x351, x352 = bits.Add64(x350, x347, uint64(0x0)) + var x353 uint64 + var x354 uint64 + x353, x354 = bits.Add64(x348, x345, uint64(p384Uint1(x352))) + var x355 uint64 + var x356 uint64 + x355, x356 = bits.Add64(x346, x343, uint64(p384Uint1(x354))) + var x357 uint64 + var x358 uint64 + x357, x358 = bits.Add64(x344, x341, uint64(p384Uint1(x356))) + var x359 uint64 + var x360 uint64 + x359, x360 = bits.Add64(x342, x339, uint64(p384Uint1(x358))) + x361 := (uint64(p384Uint1(x360)) + x340) + var x363 uint64 + _, x363 = bits.Add64(x323, x349, uint64(0x0)) + var x364 uint64 + var x365 uint64 + x364, x365 = bits.Add64(x325, x351, uint64(p384Uint1(x363))) + var x366 uint64 + var x367 uint64 + x366, x367 = bits.Add64(x327, x353, uint64(p384Uint1(x365))) + var x368 uint64 + var x369 uint64 + x368, x369 = bits.Add64(x329, x355, uint64(p384Uint1(x367))) + var x370 uint64 + var x371 uint64 + x370, x371 = bits.Add64(x331, x357, uint64(p384Uint1(x369))) + var x372 uint64 + var x373 uint64 + x372, x373 = bits.Add64(x333, x359, uint64(p384Uint1(x371))) + var x374 uint64 + var x375 uint64 + x374, x375 = bits.Add64(x335, x361, uint64(p384Uint1(x373))) + x376 := (uint64(p384Uint1(x375)) + uint64(p384Uint1(x336))) + var x377 uint64 + var x378 uint64 + x378, x377 = bits.Mul64(x5, arg1[5]) + var x379 uint64 + var x380 uint64 + x380, x379 = bits.Mul64(x5, arg1[4]) + var x381 uint64 + var x382 uint64 + x382, x381 = bits.Mul64(x5, arg1[3]) + var x383 uint64 + var x384 uint64 + x384, x383 = bits.Mul64(x5, arg1[2]) + var x385 uint64 + var x386 uint64 + x386, x385 = bits.Mul64(x5, arg1[1]) + var x387 uint64 + var x388 uint64 + x388, x387 = bits.Mul64(x5, arg1[0]) + var x389 uint64 + var x390 uint64 + x389, x390 = bits.Add64(x388, x385, uint64(0x0)) + var x391 uint64 + var x392 uint64 + x391, x392 = bits.Add64(x386, x383, uint64(p384Uint1(x390))) + var x393 uint64 + var x394 uint64 + x393, x394 = bits.Add64(x384, x381, uint64(p384Uint1(x392))) + var x395 uint64 + var x396 uint64 + x395, x396 = bits.Add64(x382, x379, uint64(p384Uint1(x394))) + var x397 uint64 + var x398 uint64 + x397, x398 = bits.Add64(x380, x377, uint64(p384Uint1(x396))) + x399 := (uint64(p384Uint1(x398)) + x378) + var x400 uint64 + var x401 uint64 + x400, x401 = bits.Add64(x364, x387, uint64(0x0)) + var x402 uint64 + var x403 uint64 + x402, x403 = bits.Add64(x366, x389, uint64(p384Uint1(x401))) + var x404 uint64 + var x405 uint64 + x404, x405 = bits.Add64(x368, x391, uint64(p384Uint1(x403))) + var x406 uint64 + var x407 uint64 + x406, x407 = bits.Add64(x370, x393, uint64(p384Uint1(x405))) + var x408 uint64 + var x409 uint64 + x408, x409 = bits.Add64(x372, x395, uint64(p384Uint1(x407))) + var x410 uint64 + var x411 uint64 + x410, x411 = bits.Add64(x374, x397, uint64(p384Uint1(x409))) + var x412 uint64 + var x413 uint64 + x412, x413 = bits.Add64(x376, x399, uint64(p384Uint1(x411))) + var x414 uint64 + _, x414 = bits.Mul64(x400, 0x100000001) + var x416 uint64 + var x417 uint64 + x417, x416 = bits.Mul64(x414, 0xffffffffffffffff) + var x418 uint64 + var x419 uint64 + x419, x418 = bits.Mul64(x414, 0xffffffffffffffff) + var x420 uint64 + var x421 uint64 + x421, x420 = bits.Mul64(x414, 0xffffffffffffffff) + var x422 uint64 + var x423 uint64 + x423, x422 = bits.Mul64(x414, 0xfffffffffffffffe) + var x424 uint64 + var x425 uint64 + x425, x424 = bits.Mul64(x414, 0xffffffff00000000) + var x426 uint64 + var x427 uint64 + x427, x426 = bits.Mul64(x414, 0xffffffff) + var x428 uint64 + var x429 uint64 + x428, x429 = bits.Add64(x427, x424, uint64(0x0)) + var x430 uint64 + var x431 uint64 + x430, x431 = bits.Add64(x425, x422, uint64(p384Uint1(x429))) + var x432 uint64 + var x433 uint64 + x432, x433 = bits.Add64(x423, x420, uint64(p384Uint1(x431))) + var x434 uint64 + var x435 uint64 + x434, x435 = bits.Add64(x421, x418, uint64(p384Uint1(x433))) + var x436 uint64 + var x437 uint64 + x436, x437 = bits.Add64(x419, x416, uint64(p384Uint1(x435))) + x438 := (uint64(p384Uint1(x437)) + x417) + var x440 uint64 + _, x440 = bits.Add64(x400, x426, uint64(0x0)) + var x441 uint64 + var x442 uint64 + x441, x442 = bits.Add64(x402, x428, uint64(p384Uint1(x440))) + var x443 uint64 + var x444 uint64 + x443, x444 = bits.Add64(x404, x430, uint64(p384Uint1(x442))) + var x445 uint64 + var x446 uint64 + x445, x446 = bits.Add64(x406, x432, uint64(p384Uint1(x444))) + var x447 uint64 + var x448 uint64 + x447, x448 = bits.Add64(x408, x434, uint64(p384Uint1(x446))) + var x449 uint64 + var x450 uint64 + x449, x450 = bits.Add64(x410, x436, uint64(p384Uint1(x448))) + var x451 uint64 + var x452 uint64 + x451, x452 = bits.Add64(x412, x438, uint64(p384Uint1(x450))) + x453 := (uint64(p384Uint1(x452)) + uint64(p384Uint1(x413))) + var x454 uint64 + var x455 uint64 + x454, x455 = bits.Sub64(x441, 0xffffffff, uint64(0x0)) + var x456 uint64 + var x457 uint64 + x456, x457 = bits.Sub64(x443, 0xffffffff00000000, uint64(p384Uint1(x455))) + var x458 uint64 + var x459 uint64 + x458, x459 = bits.Sub64(x445, 0xfffffffffffffffe, uint64(p384Uint1(x457))) + var x460 uint64 + var x461 uint64 + x460, x461 = bits.Sub64(x447, 0xffffffffffffffff, uint64(p384Uint1(x459))) + var x462 uint64 + var x463 uint64 + x462, x463 = bits.Sub64(x449, 0xffffffffffffffff, uint64(p384Uint1(x461))) + var x464 uint64 + var x465 uint64 + x464, x465 = bits.Sub64(x451, 0xffffffffffffffff, uint64(p384Uint1(x463))) + var x467 uint64 + _, x467 = bits.Sub64(x453, uint64(0x0), uint64(p384Uint1(x465))) + var x468 uint64 + p384CmovznzU64(&x468, p384Uint1(x467), x454, x441) + var x469 uint64 + p384CmovznzU64(&x469, p384Uint1(x467), x456, x443) + var x470 uint64 + p384CmovznzU64(&x470, p384Uint1(x467), x458, x445) + var x471 uint64 + p384CmovznzU64(&x471, p384Uint1(x467), x460, x447) + var x472 uint64 + p384CmovznzU64(&x472, p384Uint1(x467), x462, x449) + var x473 uint64 + p384CmovznzU64(&x473, p384Uint1(x467), x464, x451) + out1[0] = x468 + out1[1] = x469 + out1[2] = x470 + out1[3] = x471 + out1[4] = x472 + out1[5] = x473 +} + +// p384Add adds two field elements in the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// 0 ≤ eval arg2 < m +// Postconditions: +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m +// 0 ≤ eval out1 < m +// +func p384Add(out1 *p384MontgomeryDomainFieldElement, arg1 *p384MontgomeryDomainFieldElement, arg2 *p384MontgomeryDomainFieldElement) { + var x1 uint64 + var x2 uint64 + x1, x2 = bits.Add64(arg1[0], arg2[0], uint64(0x0)) + var x3 uint64 + var x4 uint64 + x3, x4 = bits.Add64(arg1[1], arg2[1], uint64(p384Uint1(x2))) + var x5 uint64 + var x6 uint64 + x5, x6 = bits.Add64(arg1[2], arg2[2], uint64(p384Uint1(x4))) + var x7 uint64 + var x8 uint64 + x7, x8 = bits.Add64(arg1[3], arg2[3], uint64(p384Uint1(x6))) + var x9 uint64 + var x10 uint64 + x9, x10 = bits.Add64(arg1[4], arg2[4], uint64(p384Uint1(x8))) + var x11 uint64 + var x12 uint64 + x11, x12 = bits.Add64(arg1[5], arg2[5], uint64(p384Uint1(x10))) + var x13 uint64 + var x14 uint64 + x13, x14 = bits.Sub64(x1, 0xffffffff, uint64(0x0)) + var x15 uint64 + var x16 uint64 + x15, x16 = bits.Sub64(x3, 0xffffffff00000000, uint64(p384Uint1(x14))) + var x17 uint64 + var x18 uint64 + x17, x18 = bits.Sub64(x5, 0xfffffffffffffffe, uint64(p384Uint1(x16))) + var x19 uint64 + var x20 uint64 + x19, x20 = bits.Sub64(x7, 0xffffffffffffffff, uint64(p384Uint1(x18))) + var x21 uint64 + var x22 uint64 + x21, x22 = bits.Sub64(x9, 0xffffffffffffffff, uint64(p384Uint1(x20))) + var x23 uint64 + var x24 uint64 + x23, x24 = bits.Sub64(x11, 0xffffffffffffffff, uint64(p384Uint1(x22))) + var x26 uint64 + _, x26 = bits.Sub64(uint64(p384Uint1(x12)), uint64(0x0), uint64(p384Uint1(x24))) + var x27 uint64 + p384CmovznzU64(&x27, p384Uint1(x26), x13, x1) + var x28 uint64 + p384CmovznzU64(&x28, p384Uint1(x26), x15, x3) + var x29 uint64 + p384CmovznzU64(&x29, p384Uint1(x26), x17, x5) + var x30 uint64 + p384CmovznzU64(&x30, p384Uint1(x26), x19, x7) + var x31 uint64 + p384CmovznzU64(&x31, p384Uint1(x26), x21, x9) + var x32 uint64 + p384CmovznzU64(&x32, p384Uint1(x26), x23, x11) + out1[0] = x27 + out1[1] = x28 + out1[2] = x29 + out1[3] = x30 + out1[4] = x31 + out1[5] = x32 +} + +// p384Sub subtracts two field elements in the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// 0 ≤ eval arg2 < m +// Postconditions: +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m +// 0 ≤ eval out1 < m +// +func p384Sub(out1 *p384MontgomeryDomainFieldElement, arg1 *p384MontgomeryDomainFieldElement, arg2 *p384MontgomeryDomainFieldElement) { + var x1 uint64 + var x2 uint64 + x1, x2 = bits.Sub64(arg1[0], arg2[0], uint64(0x0)) + var x3 uint64 + var x4 uint64 + x3, x4 = bits.Sub64(arg1[1], arg2[1], uint64(p384Uint1(x2))) + var x5 uint64 + var x6 uint64 + x5, x6 = bits.Sub64(arg1[2], arg2[2], uint64(p384Uint1(x4))) + var x7 uint64 + var x8 uint64 + x7, x8 = bits.Sub64(arg1[3], arg2[3], uint64(p384Uint1(x6))) + var x9 uint64 + var x10 uint64 + x9, x10 = bits.Sub64(arg1[4], arg2[4], uint64(p384Uint1(x8))) + var x11 uint64 + var x12 uint64 + x11, x12 = bits.Sub64(arg1[5], arg2[5], uint64(p384Uint1(x10))) + var x13 uint64 + p384CmovznzU64(&x13, p384Uint1(x12), uint64(0x0), 0xffffffffffffffff) + var x14 uint64 + var x15 uint64 + x14, x15 = bits.Add64(x1, (x13 & 0xffffffff), uint64(0x0)) + var x16 uint64 + var x17 uint64 + x16, x17 = bits.Add64(x3, (x13 & 0xffffffff00000000), uint64(p384Uint1(x15))) + var x18 uint64 + var x19 uint64 + x18, x19 = bits.Add64(x5, (x13 & 0xfffffffffffffffe), uint64(p384Uint1(x17))) + var x20 uint64 + var x21 uint64 + x20, x21 = bits.Add64(x7, x13, uint64(p384Uint1(x19))) + var x22 uint64 + var x23 uint64 + x22, x23 = bits.Add64(x9, x13, uint64(p384Uint1(x21))) + var x24 uint64 + x24, _ = bits.Add64(x11, x13, uint64(p384Uint1(x23))) + out1[0] = x14 + out1[1] = x16 + out1[2] = x18 + out1[3] = x20 + out1[4] = x22 + out1[5] = x24 +} + +// p384SetOne returns the field element one in the Montgomery domain. +// +// Postconditions: +// eval (from_montgomery out1) mod m = 1 mod m +// 0 ≤ eval out1 < m +// +func p384SetOne(out1 *p384MontgomeryDomainFieldElement) { + out1[0] = 0xffffffff00000001 + out1[1] = 0xffffffff + out1[2] = uint64(0x1) + out1[3] = uint64(0x0) + out1[4] = uint64(0x0) + out1[5] = uint64(0x0) +} + +// p384FromMontgomery translates a field element out of the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// Postconditions: +// eval out1 mod m = (eval arg1 * ((2^64)⁻¹ mod m)^6) mod m +// 0 ≤ eval out1 < m +// +func p384FromMontgomery(out1 *p384NonMontgomeryDomainFieldElement, arg1 *p384MontgomeryDomainFieldElement) { + x1 := arg1[0] + var x2 uint64 + _, x2 = bits.Mul64(x1, 0x100000001) + var x4 uint64 + var x5 uint64 + x5, x4 = bits.Mul64(x2, 0xffffffffffffffff) + var x6 uint64 + var x7 uint64 + x7, x6 = bits.Mul64(x2, 0xffffffffffffffff) + var x8 uint64 + var x9 uint64 + x9, x8 = bits.Mul64(x2, 0xffffffffffffffff) + var x10 uint64 + var x11 uint64 + x11, x10 = bits.Mul64(x2, 0xfffffffffffffffe) + var x12 uint64 + var x13 uint64 + x13, x12 = bits.Mul64(x2, 0xffffffff00000000) + var x14 uint64 + var x15 uint64 + x15, x14 = bits.Mul64(x2, 0xffffffff) + var x16 uint64 + var x17 uint64 + x16, x17 = bits.Add64(x15, x12, uint64(0x0)) + var x18 uint64 + var x19 uint64 + x18, x19 = bits.Add64(x13, x10, uint64(p384Uint1(x17))) + var x20 uint64 + var x21 uint64 + x20, x21 = bits.Add64(x11, x8, uint64(p384Uint1(x19))) + var x22 uint64 + var x23 uint64 + x22, x23 = bits.Add64(x9, x6, uint64(p384Uint1(x21))) + var x24 uint64 + var x25 uint64 + x24, x25 = bits.Add64(x7, x4, uint64(p384Uint1(x23))) + var x27 uint64 + _, x27 = bits.Add64(x1, x14, uint64(0x0)) + var x28 uint64 + var x29 uint64 + x28, x29 = bits.Add64(uint64(0x0), x16, uint64(p384Uint1(x27))) + var x30 uint64 + var x31 uint64 + x30, x31 = bits.Add64(uint64(0x0), x18, uint64(p384Uint1(x29))) + var x32 uint64 + var x33 uint64 + x32, x33 = bits.Add64(uint64(0x0), x20, uint64(p384Uint1(x31))) + var x34 uint64 + var x35 uint64 + x34, x35 = bits.Add64(uint64(0x0), x22, uint64(p384Uint1(x33))) + var x36 uint64 + var x37 uint64 + x36, x37 = bits.Add64(uint64(0x0), x24, uint64(p384Uint1(x35))) + var x38 uint64 + var x39 uint64 + x38, x39 = bits.Add64(uint64(0x0), (uint64(p384Uint1(x25)) + x5), uint64(p384Uint1(x37))) + var x40 uint64 + var x41 uint64 + x40, x41 = bits.Add64(x28, arg1[1], uint64(0x0)) + var x42 uint64 + var x43 uint64 + x42, x43 = bits.Add64(x30, uint64(0x0), uint64(p384Uint1(x41))) + var x44 uint64 + var x45 uint64 + x44, x45 = bits.Add64(x32, uint64(0x0), uint64(p384Uint1(x43))) + var x46 uint64 + var x47 uint64 + x46, x47 = bits.Add64(x34, uint64(0x0), uint64(p384Uint1(x45))) + var x48 uint64 + var x49 uint64 + x48, x49 = bits.Add64(x36, uint64(0x0), uint64(p384Uint1(x47))) + var x50 uint64 + var x51 uint64 + x50, x51 = bits.Add64(x38, uint64(0x0), uint64(p384Uint1(x49))) + var x52 uint64 + _, x52 = bits.Mul64(x40, 0x100000001) + var x54 uint64 + var x55 uint64 + x55, x54 = bits.Mul64(x52, 0xffffffffffffffff) + var x56 uint64 + var x57 uint64 + x57, x56 = bits.Mul64(x52, 0xffffffffffffffff) + var x58 uint64 + var x59 uint64 + x59, x58 = bits.Mul64(x52, 0xffffffffffffffff) + var x60 uint64 + var x61 uint64 + x61, x60 = bits.Mul64(x52, 0xfffffffffffffffe) + var x62 uint64 + var x63 uint64 + x63, x62 = bits.Mul64(x52, 0xffffffff00000000) + var x64 uint64 + var x65 uint64 + x65, x64 = bits.Mul64(x52, 0xffffffff) + var x66 uint64 + var x67 uint64 + x66, x67 = bits.Add64(x65, x62, uint64(0x0)) + var x68 uint64 + var x69 uint64 + x68, x69 = bits.Add64(x63, x60, uint64(p384Uint1(x67))) + var x70 uint64 + var x71 uint64 + x70, x71 = bits.Add64(x61, x58, uint64(p384Uint1(x69))) + var x72 uint64 + var x73 uint64 + x72, x73 = bits.Add64(x59, x56, uint64(p384Uint1(x71))) + var x74 uint64 + var x75 uint64 + x74, x75 = bits.Add64(x57, x54, uint64(p384Uint1(x73))) + var x77 uint64 + _, x77 = bits.Add64(x40, x64, uint64(0x0)) + var x78 uint64 + var x79 uint64 + x78, x79 = bits.Add64(x42, x66, uint64(p384Uint1(x77))) + var x80 uint64 + var x81 uint64 + x80, x81 = bits.Add64(x44, x68, uint64(p384Uint1(x79))) + var x82 uint64 + var x83 uint64 + x82, x83 = bits.Add64(x46, x70, uint64(p384Uint1(x81))) + var x84 uint64 + var x85 uint64 + x84, x85 = bits.Add64(x48, x72, uint64(p384Uint1(x83))) + var x86 uint64 + var x87 uint64 + x86, x87 = bits.Add64(x50, x74, uint64(p384Uint1(x85))) + var x88 uint64 + var x89 uint64 + x88, x89 = bits.Add64((uint64(p384Uint1(x51)) + uint64(p384Uint1(x39))), (uint64(p384Uint1(x75)) + x55), uint64(p384Uint1(x87))) + var x90 uint64 + var x91 uint64 + x90, x91 = bits.Add64(x78, arg1[2], uint64(0x0)) + var x92 uint64 + var x93 uint64 + x92, x93 = bits.Add64(x80, uint64(0x0), uint64(p384Uint1(x91))) + var x94 uint64 + var x95 uint64 + x94, x95 = bits.Add64(x82, uint64(0x0), uint64(p384Uint1(x93))) + var x96 uint64 + var x97 uint64 + x96, x97 = bits.Add64(x84, uint64(0x0), uint64(p384Uint1(x95))) + var x98 uint64 + var x99 uint64 + x98, x99 = bits.Add64(x86, uint64(0x0), uint64(p384Uint1(x97))) + var x100 uint64 + var x101 uint64 + x100, x101 = bits.Add64(x88, uint64(0x0), uint64(p384Uint1(x99))) + var x102 uint64 + _, x102 = bits.Mul64(x90, 0x100000001) + var x104 uint64 + var x105 uint64 + x105, x104 = bits.Mul64(x102, 0xffffffffffffffff) + var x106 uint64 + var x107 uint64 + x107, x106 = bits.Mul64(x102, 0xffffffffffffffff) + var x108 uint64 + var x109 uint64 + x109, x108 = bits.Mul64(x102, 0xffffffffffffffff) + var x110 uint64 + var x111 uint64 + x111, x110 = bits.Mul64(x102, 0xfffffffffffffffe) + var x112 uint64 + var x113 uint64 + x113, x112 = bits.Mul64(x102, 0xffffffff00000000) + var x114 uint64 + var x115 uint64 + x115, x114 = bits.Mul64(x102, 0xffffffff) + var x116 uint64 + var x117 uint64 + x116, x117 = bits.Add64(x115, x112, uint64(0x0)) + var x118 uint64 + var x119 uint64 + x118, x119 = bits.Add64(x113, x110, uint64(p384Uint1(x117))) + var x120 uint64 + var x121 uint64 + x120, x121 = bits.Add64(x111, x108, uint64(p384Uint1(x119))) + var x122 uint64 + var x123 uint64 + x122, x123 = bits.Add64(x109, x106, uint64(p384Uint1(x121))) + var x124 uint64 + var x125 uint64 + x124, x125 = bits.Add64(x107, x104, uint64(p384Uint1(x123))) + var x127 uint64 + _, x127 = bits.Add64(x90, x114, uint64(0x0)) + var x128 uint64 + var x129 uint64 + x128, x129 = bits.Add64(x92, x116, uint64(p384Uint1(x127))) + var x130 uint64 + var x131 uint64 + x130, x131 = bits.Add64(x94, x118, uint64(p384Uint1(x129))) + var x132 uint64 + var x133 uint64 + x132, x133 = bits.Add64(x96, x120, uint64(p384Uint1(x131))) + var x134 uint64 + var x135 uint64 + x134, x135 = bits.Add64(x98, x122, uint64(p384Uint1(x133))) + var x136 uint64 + var x137 uint64 + x136, x137 = bits.Add64(x100, x124, uint64(p384Uint1(x135))) + var x138 uint64 + var x139 uint64 + x138, x139 = bits.Add64((uint64(p384Uint1(x101)) + uint64(p384Uint1(x89))), (uint64(p384Uint1(x125)) + x105), uint64(p384Uint1(x137))) + var x140 uint64 + var x141 uint64 + x140, x141 = bits.Add64(x128, arg1[3], uint64(0x0)) + var x142 uint64 + var x143 uint64 + x142, x143 = bits.Add64(x130, uint64(0x0), uint64(p384Uint1(x141))) + var x144 uint64 + var x145 uint64 + x144, x145 = bits.Add64(x132, uint64(0x0), uint64(p384Uint1(x143))) + var x146 uint64 + var x147 uint64 + x146, x147 = bits.Add64(x134, uint64(0x0), uint64(p384Uint1(x145))) + var x148 uint64 + var x149 uint64 + x148, x149 = bits.Add64(x136, uint64(0x0), uint64(p384Uint1(x147))) + var x150 uint64 + var x151 uint64 + x150, x151 = bits.Add64(x138, uint64(0x0), uint64(p384Uint1(x149))) + var x152 uint64 + _, x152 = bits.Mul64(x140, 0x100000001) + var x154 uint64 + var x155 uint64 + x155, x154 = bits.Mul64(x152, 0xffffffffffffffff) + var x156 uint64 + var x157 uint64 + x157, x156 = bits.Mul64(x152, 0xffffffffffffffff) + var x158 uint64 + var x159 uint64 + x159, x158 = bits.Mul64(x152, 0xffffffffffffffff) + var x160 uint64 + var x161 uint64 + x161, x160 = bits.Mul64(x152, 0xfffffffffffffffe) + var x162 uint64 + var x163 uint64 + x163, x162 = bits.Mul64(x152, 0xffffffff00000000) + var x164 uint64 + var x165 uint64 + x165, x164 = bits.Mul64(x152, 0xffffffff) + var x166 uint64 + var x167 uint64 + x166, x167 = bits.Add64(x165, x162, uint64(0x0)) + var x168 uint64 + var x169 uint64 + x168, x169 = bits.Add64(x163, x160, uint64(p384Uint1(x167))) + var x170 uint64 + var x171 uint64 + x170, x171 = bits.Add64(x161, x158, uint64(p384Uint1(x169))) + var x172 uint64 + var x173 uint64 + x172, x173 = bits.Add64(x159, x156, uint64(p384Uint1(x171))) + var x174 uint64 + var x175 uint64 + x174, x175 = bits.Add64(x157, x154, uint64(p384Uint1(x173))) + var x177 uint64 + _, x177 = bits.Add64(x140, x164, uint64(0x0)) + var x178 uint64 + var x179 uint64 + x178, x179 = bits.Add64(x142, x166, uint64(p384Uint1(x177))) + var x180 uint64 + var x181 uint64 + x180, x181 = bits.Add64(x144, x168, uint64(p384Uint1(x179))) + var x182 uint64 + var x183 uint64 + x182, x183 = bits.Add64(x146, x170, uint64(p384Uint1(x181))) + var x184 uint64 + var x185 uint64 + x184, x185 = bits.Add64(x148, x172, uint64(p384Uint1(x183))) + var x186 uint64 + var x187 uint64 + x186, x187 = bits.Add64(x150, x174, uint64(p384Uint1(x185))) + var x188 uint64 + var x189 uint64 + x188, x189 = bits.Add64((uint64(p384Uint1(x151)) + uint64(p384Uint1(x139))), (uint64(p384Uint1(x175)) + x155), uint64(p384Uint1(x187))) + var x190 uint64 + var x191 uint64 + x190, x191 = bits.Add64(x178, arg1[4], uint64(0x0)) + var x192 uint64 + var x193 uint64 + x192, x193 = bits.Add64(x180, uint64(0x0), uint64(p384Uint1(x191))) + var x194 uint64 + var x195 uint64 + x194, x195 = bits.Add64(x182, uint64(0x0), uint64(p384Uint1(x193))) + var x196 uint64 + var x197 uint64 + x196, x197 = bits.Add64(x184, uint64(0x0), uint64(p384Uint1(x195))) + var x198 uint64 + var x199 uint64 + x198, x199 = bits.Add64(x186, uint64(0x0), uint64(p384Uint1(x197))) + var x200 uint64 + var x201 uint64 + x200, x201 = bits.Add64(x188, uint64(0x0), uint64(p384Uint1(x199))) + var x202 uint64 + _, x202 = bits.Mul64(x190, 0x100000001) + var x204 uint64 + var x205 uint64 + x205, x204 = bits.Mul64(x202, 0xffffffffffffffff) + var x206 uint64 + var x207 uint64 + x207, x206 = bits.Mul64(x202, 0xffffffffffffffff) + var x208 uint64 + var x209 uint64 + x209, x208 = bits.Mul64(x202, 0xffffffffffffffff) + var x210 uint64 + var x211 uint64 + x211, x210 = bits.Mul64(x202, 0xfffffffffffffffe) + var x212 uint64 + var x213 uint64 + x213, x212 = bits.Mul64(x202, 0xffffffff00000000) + var x214 uint64 + var x215 uint64 + x215, x214 = bits.Mul64(x202, 0xffffffff) + var x216 uint64 + var x217 uint64 + x216, x217 = bits.Add64(x215, x212, uint64(0x0)) + var x218 uint64 + var x219 uint64 + x218, x219 = bits.Add64(x213, x210, uint64(p384Uint1(x217))) + var x220 uint64 + var x221 uint64 + x220, x221 = bits.Add64(x211, x208, uint64(p384Uint1(x219))) + var x222 uint64 + var x223 uint64 + x222, x223 = bits.Add64(x209, x206, uint64(p384Uint1(x221))) + var x224 uint64 + var x225 uint64 + x224, x225 = bits.Add64(x207, x204, uint64(p384Uint1(x223))) + var x227 uint64 + _, x227 = bits.Add64(x190, x214, uint64(0x0)) + var x228 uint64 + var x229 uint64 + x228, x229 = bits.Add64(x192, x216, uint64(p384Uint1(x227))) + var x230 uint64 + var x231 uint64 + x230, x231 = bits.Add64(x194, x218, uint64(p384Uint1(x229))) + var x232 uint64 + var x233 uint64 + x232, x233 = bits.Add64(x196, x220, uint64(p384Uint1(x231))) + var x234 uint64 + var x235 uint64 + x234, x235 = bits.Add64(x198, x222, uint64(p384Uint1(x233))) + var x236 uint64 + var x237 uint64 + x236, x237 = bits.Add64(x200, x224, uint64(p384Uint1(x235))) + var x238 uint64 + var x239 uint64 + x238, x239 = bits.Add64((uint64(p384Uint1(x201)) + uint64(p384Uint1(x189))), (uint64(p384Uint1(x225)) + x205), uint64(p384Uint1(x237))) + var x240 uint64 + var x241 uint64 + x240, x241 = bits.Add64(x228, arg1[5], uint64(0x0)) + var x242 uint64 + var x243 uint64 + x242, x243 = bits.Add64(x230, uint64(0x0), uint64(p384Uint1(x241))) + var x244 uint64 + var x245 uint64 + x244, x245 = bits.Add64(x232, uint64(0x0), uint64(p384Uint1(x243))) + var x246 uint64 + var x247 uint64 + x246, x247 = bits.Add64(x234, uint64(0x0), uint64(p384Uint1(x245))) + var x248 uint64 + var x249 uint64 + x248, x249 = bits.Add64(x236, uint64(0x0), uint64(p384Uint1(x247))) + var x250 uint64 + var x251 uint64 + x250, x251 = bits.Add64(x238, uint64(0x0), uint64(p384Uint1(x249))) + var x252 uint64 + _, x252 = bits.Mul64(x240, 0x100000001) + var x254 uint64 + var x255 uint64 + x255, x254 = bits.Mul64(x252, 0xffffffffffffffff) + var x256 uint64 + var x257 uint64 + x257, x256 = bits.Mul64(x252, 0xffffffffffffffff) + var x258 uint64 + var x259 uint64 + x259, x258 = bits.Mul64(x252, 0xffffffffffffffff) + var x260 uint64 + var x261 uint64 + x261, x260 = bits.Mul64(x252, 0xfffffffffffffffe) + var x262 uint64 + var x263 uint64 + x263, x262 = bits.Mul64(x252, 0xffffffff00000000) + var x264 uint64 + var x265 uint64 + x265, x264 = bits.Mul64(x252, 0xffffffff) + var x266 uint64 + var x267 uint64 + x266, x267 = bits.Add64(x265, x262, uint64(0x0)) + var x268 uint64 + var x269 uint64 + x268, x269 = bits.Add64(x263, x260, uint64(p384Uint1(x267))) + var x270 uint64 + var x271 uint64 + x270, x271 = bits.Add64(x261, x258, uint64(p384Uint1(x269))) + var x272 uint64 + var x273 uint64 + x272, x273 = bits.Add64(x259, x256, uint64(p384Uint1(x271))) + var x274 uint64 + var x275 uint64 + x274, x275 = bits.Add64(x257, x254, uint64(p384Uint1(x273))) + var x277 uint64 + _, x277 = bits.Add64(x240, x264, uint64(0x0)) + var x278 uint64 + var x279 uint64 + x278, x279 = bits.Add64(x242, x266, uint64(p384Uint1(x277))) + var x280 uint64 + var x281 uint64 + x280, x281 = bits.Add64(x244, x268, uint64(p384Uint1(x279))) + var x282 uint64 + var x283 uint64 + x282, x283 = bits.Add64(x246, x270, uint64(p384Uint1(x281))) + var x284 uint64 + var x285 uint64 + x284, x285 = bits.Add64(x248, x272, uint64(p384Uint1(x283))) + var x286 uint64 + var x287 uint64 + x286, x287 = bits.Add64(x250, x274, uint64(p384Uint1(x285))) + var x288 uint64 + var x289 uint64 + x288, x289 = bits.Add64((uint64(p384Uint1(x251)) + uint64(p384Uint1(x239))), (uint64(p384Uint1(x275)) + x255), uint64(p384Uint1(x287))) + var x290 uint64 + var x291 uint64 + x290, x291 = bits.Sub64(x278, 0xffffffff, uint64(0x0)) + var x292 uint64 + var x293 uint64 + x292, x293 = bits.Sub64(x280, 0xffffffff00000000, uint64(p384Uint1(x291))) + var x294 uint64 + var x295 uint64 + x294, x295 = bits.Sub64(x282, 0xfffffffffffffffe, uint64(p384Uint1(x293))) + var x296 uint64 + var x297 uint64 + x296, x297 = bits.Sub64(x284, 0xffffffffffffffff, uint64(p384Uint1(x295))) + var x298 uint64 + var x299 uint64 + x298, x299 = bits.Sub64(x286, 0xffffffffffffffff, uint64(p384Uint1(x297))) + var x300 uint64 + var x301 uint64 + x300, x301 = bits.Sub64(x288, 0xffffffffffffffff, uint64(p384Uint1(x299))) + var x303 uint64 + _, x303 = bits.Sub64(uint64(p384Uint1(x289)), uint64(0x0), uint64(p384Uint1(x301))) + var x304 uint64 + p384CmovznzU64(&x304, p384Uint1(x303), x290, x278) + var x305 uint64 + p384CmovznzU64(&x305, p384Uint1(x303), x292, x280) + var x306 uint64 + p384CmovznzU64(&x306, p384Uint1(x303), x294, x282) + var x307 uint64 + p384CmovznzU64(&x307, p384Uint1(x303), x296, x284) + var x308 uint64 + p384CmovznzU64(&x308, p384Uint1(x303), x298, x286) + var x309 uint64 + p384CmovznzU64(&x309, p384Uint1(x303), x300, x288) + out1[0] = x304 + out1[1] = x305 + out1[2] = x306 + out1[3] = x307 + out1[4] = x308 + out1[5] = x309 +} + +// p384ToMontgomery translates a field element into the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// Postconditions: +// eval (from_montgomery out1) mod m = eval arg1 mod m +// 0 ≤ eval out1 < m +// +func p384ToMontgomery(out1 *p384MontgomeryDomainFieldElement, arg1 *p384NonMontgomeryDomainFieldElement) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[4] + x5 := arg1[5] + x6 := arg1[0] + var x7 uint64 + var x8 uint64 + x8, x7 = bits.Mul64(x6, 0x200000000) + var x9 uint64 + var x10 uint64 + x10, x9 = bits.Mul64(x6, 0xfffffffe00000000) + var x11 uint64 + var x12 uint64 + x12, x11 = bits.Mul64(x6, 0x200000000) + var x13 uint64 + var x14 uint64 + x14, x13 = bits.Mul64(x6, 0xfffffffe00000001) + var x15 uint64 + var x16 uint64 + x15, x16 = bits.Add64(x14, x11, uint64(0x0)) + var x17 uint64 + var x18 uint64 + x17, x18 = bits.Add64(x12, x9, uint64(p384Uint1(x16))) + var x19 uint64 + var x20 uint64 + x19, x20 = bits.Add64(x10, x7, uint64(p384Uint1(x18))) + var x21 uint64 + var x22 uint64 + x21, x22 = bits.Add64(x8, x6, uint64(p384Uint1(x20))) + var x23 uint64 + _, x23 = bits.Mul64(x13, 0x100000001) + var x25 uint64 + var x26 uint64 + x26, x25 = bits.Mul64(x23, 0xffffffffffffffff) + var x27 uint64 + var x28 uint64 + x28, x27 = bits.Mul64(x23, 0xffffffffffffffff) + var x29 uint64 + var x30 uint64 + x30, x29 = bits.Mul64(x23, 0xffffffffffffffff) + var x31 uint64 + var x32 uint64 + x32, x31 = bits.Mul64(x23, 0xfffffffffffffffe) + var x33 uint64 + var x34 uint64 + x34, x33 = bits.Mul64(x23, 0xffffffff00000000) + var x35 uint64 + var x36 uint64 + x36, x35 = bits.Mul64(x23, 0xffffffff) + var x37 uint64 + var x38 uint64 + x37, x38 = bits.Add64(x36, x33, uint64(0x0)) + var x39 uint64 + var x40 uint64 + x39, x40 = bits.Add64(x34, x31, uint64(p384Uint1(x38))) + var x41 uint64 + var x42 uint64 + x41, x42 = bits.Add64(x32, x29, uint64(p384Uint1(x40))) + var x43 uint64 + var x44 uint64 + x43, x44 = bits.Add64(x30, x27, uint64(p384Uint1(x42))) + var x45 uint64 + var x46 uint64 + x45, x46 = bits.Add64(x28, x25, uint64(p384Uint1(x44))) + var x48 uint64 + _, x48 = bits.Add64(x13, x35, uint64(0x0)) + var x49 uint64 + var x50 uint64 + x49, x50 = bits.Add64(x15, x37, uint64(p384Uint1(x48))) + var x51 uint64 + var x52 uint64 + x51, x52 = bits.Add64(x17, x39, uint64(p384Uint1(x50))) + var x53 uint64 + var x54 uint64 + x53, x54 = bits.Add64(x19, x41, uint64(p384Uint1(x52))) + var x55 uint64 + var x56 uint64 + x55, x56 = bits.Add64(x21, x43, uint64(p384Uint1(x54))) + var x57 uint64 + var x58 uint64 + x57, x58 = bits.Add64(uint64(p384Uint1(x22)), x45, uint64(p384Uint1(x56))) + var x59 uint64 + var x60 uint64 + x59, x60 = bits.Add64(uint64(0x0), (uint64(p384Uint1(x46)) + x26), uint64(p384Uint1(x58))) + var x61 uint64 + var x62 uint64 + x62, x61 = bits.Mul64(x1, 0x200000000) + var x63 uint64 + var x64 uint64 + x64, x63 = bits.Mul64(x1, 0xfffffffe00000000) + var x65 uint64 + var x66 uint64 + x66, x65 = bits.Mul64(x1, 0x200000000) + var x67 uint64 + var x68 uint64 + x68, x67 = bits.Mul64(x1, 0xfffffffe00000001) + var x69 uint64 + var x70 uint64 + x69, x70 = bits.Add64(x68, x65, uint64(0x0)) + var x71 uint64 + var x72 uint64 + x71, x72 = bits.Add64(x66, x63, uint64(p384Uint1(x70))) + var x73 uint64 + var x74 uint64 + x73, x74 = bits.Add64(x64, x61, uint64(p384Uint1(x72))) + var x75 uint64 + var x76 uint64 + x75, x76 = bits.Add64(x62, x1, uint64(p384Uint1(x74))) + var x77 uint64 + var x78 uint64 + x77, x78 = bits.Add64(x49, x67, uint64(0x0)) + var x79 uint64 + var x80 uint64 + x79, x80 = bits.Add64(x51, x69, uint64(p384Uint1(x78))) + var x81 uint64 + var x82 uint64 + x81, x82 = bits.Add64(x53, x71, uint64(p384Uint1(x80))) + var x83 uint64 + var x84 uint64 + x83, x84 = bits.Add64(x55, x73, uint64(p384Uint1(x82))) + var x85 uint64 + var x86 uint64 + x85, x86 = bits.Add64(x57, x75, uint64(p384Uint1(x84))) + var x87 uint64 + var x88 uint64 + x87, x88 = bits.Add64(x59, uint64(p384Uint1(x76)), uint64(p384Uint1(x86))) + var x89 uint64 + _, x89 = bits.Mul64(x77, 0x100000001) + var x91 uint64 + var x92 uint64 + x92, x91 = bits.Mul64(x89, 0xffffffffffffffff) + var x93 uint64 + var x94 uint64 + x94, x93 = bits.Mul64(x89, 0xffffffffffffffff) + var x95 uint64 + var x96 uint64 + x96, x95 = bits.Mul64(x89, 0xffffffffffffffff) + var x97 uint64 + var x98 uint64 + x98, x97 = bits.Mul64(x89, 0xfffffffffffffffe) + var x99 uint64 + var x100 uint64 + x100, x99 = bits.Mul64(x89, 0xffffffff00000000) + var x101 uint64 + var x102 uint64 + x102, x101 = bits.Mul64(x89, 0xffffffff) + var x103 uint64 + var x104 uint64 + x103, x104 = bits.Add64(x102, x99, uint64(0x0)) + var x105 uint64 + var x106 uint64 + x105, x106 = bits.Add64(x100, x97, uint64(p384Uint1(x104))) + var x107 uint64 + var x108 uint64 + x107, x108 = bits.Add64(x98, x95, uint64(p384Uint1(x106))) + var x109 uint64 + var x110 uint64 + x109, x110 = bits.Add64(x96, x93, uint64(p384Uint1(x108))) + var x111 uint64 + var x112 uint64 + x111, x112 = bits.Add64(x94, x91, uint64(p384Uint1(x110))) + var x114 uint64 + _, x114 = bits.Add64(x77, x101, uint64(0x0)) + var x115 uint64 + var x116 uint64 + x115, x116 = bits.Add64(x79, x103, uint64(p384Uint1(x114))) + var x117 uint64 + var x118 uint64 + x117, x118 = bits.Add64(x81, x105, uint64(p384Uint1(x116))) + var x119 uint64 + var x120 uint64 + x119, x120 = bits.Add64(x83, x107, uint64(p384Uint1(x118))) + var x121 uint64 + var x122 uint64 + x121, x122 = bits.Add64(x85, x109, uint64(p384Uint1(x120))) + var x123 uint64 + var x124 uint64 + x123, x124 = bits.Add64(x87, x111, uint64(p384Uint1(x122))) + var x125 uint64 + var x126 uint64 + x125, x126 = bits.Add64((uint64(p384Uint1(x88)) + uint64(p384Uint1(x60))), (uint64(p384Uint1(x112)) + x92), uint64(p384Uint1(x124))) + var x127 uint64 + var x128 uint64 + x128, x127 = bits.Mul64(x2, 0x200000000) + var x129 uint64 + var x130 uint64 + x130, x129 = bits.Mul64(x2, 0xfffffffe00000000) + var x131 uint64 + var x132 uint64 + x132, x131 = bits.Mul64(x2, 0x200000000) + var x133 uint64 + var x134 uint64 + x134, x133 = bits.Mul64(x2, 0xfffffffe00000001) + var x135 uint64 + var x136 uint64 + x135, x136 = bits.Add64(x134, x131, uint64(0x0)) + var x137 uint64 + var x138 uint64 + x137, x138 = bits.Add64(x132, x129, uint64(p384Uint1(x136))) + var x139 uint64 + var x140 uint64 + x139, x140 = bits.Add64(x130, x127, uint64(p384Uint1(x138))) + var x141 uint64 + var x142 uint64 + x141, x142 = bits.Add64(x128, x2, uint64(p384Uint1(x140))) + var x143 uint64 + var x144 uint64 + x143, x144 = bits.Add64(x115, x133, uint64(0x0)) + var x145 uint64 + var x146 uint64 + x145, x146 = bits.Add64(x117, x135, uint64(p384Uint1(x144))) + var x147 uint64 + var x148 uint64 + x147, x148 = bits.Add64(x119, x137, uint64(p384Uint1(x146))) + var x149 uint64 + var x150 uint64 + x149, x150 = bits.Add64(x121, x139, uint64(p384Uint1(x148))) + var x151 uint64 + var x152 uint64 + x151, x152 = bits.Add64(x123, x141, uint64(p384Uint1(x150))) + var x153 uint64 + var x154 uint64 + x153, x154 = bits.Add64(x125, uint64(p384Uint1(x142)), uint64(p384Uint1(x152))) + var x155 uint64 + _, x155 = bits.Mul64(x143, 0x100000001) + var x157 uint64 + var x158 uint64 + x158, x157 = bits.Mul64(x155, 0xffffffffffffffff) + var x159 uint64 + var x160 uint64 + x160, x159 = bits.Mul64(x155, 0xffffffffffffffff) + var x161 uint64 + var x162 uint64 + x162, x161 = bits.Mul64(x155, 0xffffffffffffffff) + var x163 uint64 + var x164 uint64 + x164, x163 = bits.Mul64(x155, 0xfffffffffffffffe) + var x165 uint64 + var x166 uint64 + x166, x165 = bits.Mul64(x155, 0xffffffff00000000) + var x167 uint64 + var x168 uint64 + x168, x167 = bits.Mul64(x155, 0xffffffff) + var x169 uint64 + var x170 uint64 + x169, x170 = bits.Add64(x168, x165, uint64(0x0)) + var x171 uint64 + var x172 uint64 + x171, x172 = bits.Add64(x166, x163, uint64(p384Uint1(x170))) + var x173 uint64 + var x174 uint64 + x173, x174 = bits.Add64(x164, x161, uint64(p384Uint1(x172))) + var x175 uint64 + var x176 uint64 + x175, x176 = bits.Add64(x162, x159, uint64(p384Uint1(x174))) + var x177 uint64 + var x178 uint64 + x177, x178 = bits.Add64(x160, x157, uint64(p384Uint1(x176))) + var x180 uint64 + _, x180 = bits.Add64(x143, x167, uint64(0x0)) + var x181 uint64 + var x182 uint64 + x181, x182 = bits.Add64(x145, x169, uint64(p384Uint1(x180))) + var x183 uint64 + var x184 uint64 + x183, x184 = bits.Add64(x147, x171, uint64(p384Uint1(x182))) + var x185 uint64 + var x186 uint64 + x185, x186 = bits.Add64(x149, x173, uint64(p384Uint1(x184))) + var x187 uint64 + var x188 uint64 + x187, x188 = bits.Add64(x151, x175, uint64(p384Uint1(x186))) + var x189 uint64 + var x190 uint64 + x189, x190 = bits.Add64(x153, x177, uint64(p384Uint1(x188))) + var x191 uint64 + var x192 uint64 + x191, x192 = bits.Add64((uint64(p384Uint1(x154)) + uint64(p384Uint1(x126))), (uint64(p384Uint1(x178)) + x158), uint64(p384Uint1(x190))) + var x193 uint64 + var x194 uint64 + x194, x193 = bits.Mul64(x3, 0x200000000) + var x195 uint64 + var x196 uint64 + x196, x195 = bits.Mul64(x3, 0xfffffffe00000000) + var x197 uint64 + var x198 uint64 + x198, x197 = bits.Mul64(x3, 0x200000000) + var x199 uint64 + var x200 uint64 + x200, x199 = bits.Mul64(x3, 0xfffffffe00000001) + var x201 uint64 + var x202 uint64 + x201, x202 = bits.Add64(x200, x197, uint64(0x0)) + var x203 uint64 + var x204 uint64 + x203, x204 = bits.Add64(x198, x195, uint64(p384Uint1(x202))) + var x205 uint64 + var x206 uint64 + x205, x206 = bits.Add64(x196, x193, uint64(p384Uint1(x204))) + var x207 uint64 + var x208 uint64 + x207, x208 = bits.Add64(x194, x3, uint64(p384Uint1(x206))) + var x209 uint64 + var x210 uint64 + x209, x210 = bits.Add64(x181, x199, uint64(0x0)) + var x211 uint64 + var x212 uint64 + x211, x212 = bits.Add64(x183, x201, uint64(p384Uint1(x210))) + var x213 uint64 + var x214 uint64 + x213, x214 = bits.Add64(x185, x203, uint64(p384Uint1(x212))) + var x215 uint64 + var x216 uint64 + x215, x216 = bits.Add64(x187, x205, uint64(p384Uint1(x214))) + var x217 uint64 + var x218 uint64 + x217, x218 = bits.Add64(x189, x207, uint64(p384Uint1(x216))) + var x219 uint64 + var x220 uint64 + x219, x220 = bits.Add64(x191, uint64(p384Uint1(x208)), uint64(p384Uint1(x218))) + var x221 uint64 + _, x221 = bits.Mul64(x209, 0x100000001) + var x223 uint64 + var x224 uint64 + x224, x223 = bits.Mul64(x221, 0xffffffffffffffff) + var x225 uint64 + var x226 uint64 + x226, x225 = bits.Mul64(x221, 0xffffffffffffffff) + var x227 uint64 + var x228 uint64 + x228, x227 = bits.Mul64(x221, 0xffffffffffffffff) + var x229 uint64 + var x230 uint64 + x230, x229 = bits.Mul64(x221, 0xfffffffffffffffe) + var x231 uint64 + var x232 uint64 + x232, x231 = bits.Mul64(x221, 0xffffffff00000000) + var x233 uint64 + var x234 uint64 + x234, x233 = bits.Mul64(x221, 0xffffffff) + var x235 uint64 + var x236 uint64 + x235, x236 = bits.Add64(x234, x231, uint64(0x0)) + var x237 uint64 + var x238 uint64 + x237, x238 = bits.Add64(x232, x229, uint64(p384Uint1(x236))) + var x239 uint64 + var x240 uint64 + x239, x240 = bits.Add64(x230, x227, uint64(p384Uint1(x238))) + var x241 uint64 + var x242 uint64 + x241, x242 = bits.Add64(x228, x225, uint64(p384Uint1(x240))) + var x243 uint64 + var x244 uint64 + x243, x244 = bits.Add64(x226, x223, uint64(p384Uint1(x242))) + var x246 uint64 + _, x246 = bits.Add64(x209, x233, uint64(0x0)) + var x247 uint64 + var x248 uint64 + x247, x248 = bits.Add64(x211, x235, uint64(p384Uint1(x246))) + var x249 uint64 + var x250 uint64 + x249, x250 = bits.Add64(x213, x237, uint64(p384Uint1(x248))) + var x251 uint64 + var x252 uint64 + x251, x252 = bits.Add64(x215, x239, uint64(p384Uint1(x250))) + var x253 uint64 + var x254 uint64 + x253, x254 = bits.Add64(x217, x241, uint64(p384Uint1(x252))) + var x255 uint64 + var x256 uint64 + x255, x256 = bits.Add64(x219, x243, uint64(p384Uint1(x254))) + var x257 uint64 + var x258 uint64 + x257, x258 = bits.Add64((uint64(p384Uint1(x220)) + uint64(p384Uint1(x192))), (uint64(p384Uint1(x244)) + x224), uint64(p384Uint1(x256))) + var x259 uint64 + var x260 uint64 + x260, x259 = bits.Mul64(x4, 0x200000000) + var x261 uint64 + var x262 uint64 + x262, x261 = bits.Mul64(x4, 0xfffffffe00000000) + var x263 uint64 + var x264 uint64 + x264, x263 = bits.Mul64(x4, 0x200000000) + var x265 uint64 + var x266 uint64 + x266, x265 = bits.Mul64(x4, 0xfffffffe00000001) + var x267 uint64 + var x268 uint64 + x267, x268 = bits.Add64(x266, x263, uint64(0x0)) + var x269 uint64 + var x270 uint64 + x269, x270 = bits.Add64(x264, x261, uint64(p384Uint1(x268))) + var x271 uint64 + var x272 uint64 + x271, x272 = bits.Add64(x262, x259, uint64(p384Uint1(x270))) + var x273 uint64 + var x274 uint64 + x273, x274 = bits.Add64(x260, x4, uint64(p384Uint1(x272))) + var x275 uint64 + var x276 uint64 + x275, x276 = bits.Add64(x247, x265, uint64(0x0)) + var x277 uint64 + var x278 uint64 + x277, x278 = bits.Add64(x249, x267, uint64(p384Uint1(x276))) + var x279 uint64 + var x280 uint64 + x279, x280 = bits.Add64(x251, x269, uint64(p384Uint1(x278))) + var x281 uint64 + var x282 uint64 + x281, x282 = bits.Add64(x253, x271, uint64(p384Uint1(x280))) + var x283 uint64 + var x284 uint64 + x283, x284 = bits.Add64(x255, x273, uint64(p384Uint1(x282))) + var x285 uint64 + var x286 uint64 + x285, x286 = bits.Add64(x257, uint64(p384Uint1(x274)), uint64(p384Uint1(x284))) + var x287 uint64 + _, x287 = bits.Mul64(x275, 0x100000001) + var x289 uint64 + var x290 uint64 + x290, x289 = bits.Mul64(x287, 0xffffffffffffffff) + var x291 uint64 + var x292 uint64 + x292, x291 = bits.Mul64(x287, 0xffffffffffffffff) + var x293 uint64 + var x294 uint64 + x294, x293 = bits.Mul64(x287, 0xffffffffffffffff) + var x295 uint64 + var x296 uint64 + x296, x295 = bits.Mul64(x287, 0xfffffffffffffffe) + var x297 uint64 + var x298 uint64 + x298, x297 = bits.Mul64(x287, 0xffffffff00000000) + var x299 uint64 + var x300 uint64 + x300, x299 = bits.Mul64(x287, 0xffffffff) + var x301 uint64 + var x302 uint64 + x301, x302 = bits.Add64(x300, x297, uint64(0x0)) + var x303 uint64 + var x304 uint64 + x303, x304 = bits.Add64(x298, x295, uint64(p384Uint1(x302))) + var x305 uint64 + var x306 uint64 + x305, x306 = bits.Add64(x296, x293, uint64(p384Uint1(x304))) + var x307 uint64 + var x308 uint64 + x307, x308 = bits.Add64(x294, x291, uint64(p384Uint1(x306))) + var x309 uint64 + var x310 uint64 + x309, x310 = bits.Add64(x292, x289, uint64(p384Uint1(x308))) + var x312 uint64 + _, x312 = bits.Add64(x275, x299, uint64(0x0)) + var x313 uint64 + var x314 uint64 + x313, x314 = bits.Add64(x277, x301, uint64(p384Uint1(x312))) + var x315 uint64 + var x316 uint64 + x315, x316 = bits.Add64(x279, x303, uint64(p384Uint1(x314))) + var x317 uint64 + var x318 uint64 + x317, x318 = bits.Add64(x281, x305, uint64(p384Uint1(x316))) + var x319 uint64 + var x320 uint64 + x319, x320 = bits.Add64(x283, x307, uint64(p384Uint1(x318))) + var x321 uint64 + var x322 uint64 + x321, x322 = bits.Add64(x285, x309, uint64(p384Uint1(x320))) + var x323 uint64 + var x324 uint64 + x323, x324 = bits.Add64((uint64(p384Uint1(x286)) + uint64(p384Uint1(x258))), (uint64(p384Uint1(x310)) + x290), uint64(p384Uint1(x322))) + var x325 uint64 + var x326 uint64 + x326, x325 = bits.Mul64(x5, 0x200000000) + var x327 uint64 + var x328 uint64 + x328, x327 = bits.Mul64(x5, 0xfffffffe00000000) + var x329 uint64 + var x330 uint64 + x330, x329 = bits.Mul64(x5, 0x200000000) + var x331 uint64 + var x332 uint64 + x332, x331 = bits.Mul64(x5, 0xfffffffe00000001) + var x333 uint64 + var x334 uint64 + x333, x334 = bits.Add64(x332, x329, uint64(0x0)) + var x335 uint64 + var x336 uint64 + x335, x336 = bits.Add64(x330, x327, uint64(p384Uint1(x334))) + var x337 uint64 + var x338 uint64 + x337, x338 = bits.Add64(x328, x325, uint64(p384Uint1(x336))) + var x339 uint64 + var x340 uint64 + x339, x340 = bits.Add64(x326, x5, uint64(p384Uint1(x338))) + var x341 uint64 + var x342 uint64 + x341, x342 = bits.Add64(x313, x331, uint64(0x0)) + var x343 uint64 + var x344 uint64 + x343, x344 = bits.Add64(x315, x333, uint64(p384Uint1(x342))) + var x345 uint64 + var x346 uint64 + x345, x346 = bits.Add64(x317, x335, uint64(p384Uint1(x344))) + var x347 uint64 + var x348 uint64 + x347, x348 = bits.Add64(x319, x337, uint64(p384Uint1(x346))) + var x349 uint64 + var x350 uint64 + x349, x350 = bits.Add64(x321, x339, uint64(p384Uint1(x348))) + var x351 uint64 + var x352 uint64 + x351, x352 = bits.Add64(x323, uint64(p384Uint1(x340)), uint64(p384Uint1(x350))) + var x353 uint64 + _, x353 = bits.Mul64(x341, 0x100000001) + var x355 uint64 + var x356 uint64 + x356, x355 = bits.Mul64(x353, 0xffffffffffffffff) + var x357 uint64 + var x358 uint64 + x358, x357 = bits.Mul64(x353, 0xffffffffffffffff) + var x359 uint64 + var x360 uint64 + x360, x359 = bits.Mul64(x353, 0xffffffffffffffff) + var x361 uint64 + var x362 uint64 + x362, x361 = bits.Mul64(x353, 0xfffffffffffffffe) + var x363 uint64 + var x364 uint64 + x364, x363 = bits.Mul64(x353, 0xffffffff00000000) + var x365 uint64 + var x366 uint64 + x366, x365 = bits.Mul64(x353, 0xffffffff) + var x367 uint64 + var x368 uint64 + x367, x368 = bits.Add64(x366, x363, uint64(0x0)) + var x369 uint64 + var x370 uint64 + x369, x370 = bits.Add64(x364, x361, uint64(p384Uint1(x368))) + var x371 uint64 + var x372 uint64 + x371, x372 = bits.Add64(x362, x359, uint64(p384Uint1(x370))) + var x373 uint64 + var x374 uint64 + x373, x374 = bits.Add64(x360, x357, uint64(p384Uint1(x372))) + var x375 uint64 + var x376 uint64 + x375, x376 = bits.Add64(x358, x355, uint64(p384Uint1(x374))) + var x378 uint64 + _, x378 = bits.Add64(x341, x365, uint64(0x0)) + var x379 uint64 + var x380 uint64 + x379, x380 = bits.Add64(x343, x367, uint64(p384Uint1(x378))) + var x381 uint64 + var x382 uint64 + x381, x382 = bits.Add64(x345, x369, uint64(p384Uint1(x380))) + var x383 uint64 + var x384 uint64 + x383, x384 = bits.Add64(x347, x371, uint64(p384Uint1(x382))) + var x385 uint64 + var x386 uint64 + x385, x386 = bits.Add64(x349, x373, uint64(p384Uint1(x384))) + var x387 uint64 + var x388 uint64 + x387, x388 = bits.Add64(x351, x375, uint64(p384Uint1(x386))) + var x389 uint64 + var x390 uint64 + x389, x390 = bits.Add64((uint64(p384Uint1(x352)) + uint64(p384Uint1(x324))), (uint64(p384Uint1(x376)) + x356), uint64(p384Uint1(x388))) + var x391 uint64 + var x392 uint64 + x391, x392 = bits.Sub64(x379, 0xffffffff, uint64(0x0)) + var x393 uint64 + var x394 uint64 + x393, x394 = bits.Sub64(x381, 0xffffffff00000000, uint64(p384Uint1(x392))) + var x395 uint64 + var x396 uint64 + x395, x396 = bits.Sub64(x383, 0xfffffffffffffffe, uint64(p384Uint1(x394))) + var x397 uint64 + var x398 uint64 + x397, x398 = bits.Sub64(x385, 0xffffffffffffffff, uint64(p384Uint1(x396))) + var x399 uint64 + var x400 uint64 + x399, x400 = bits.Sub64(x387, 0xffffffffffffffff, uint64(p384Uint1(x398))) + var x401 uint64 + var x402 uint64 + x401, x402 = bits.Sub64(x389, 0xffffffffffffffff, uint64(p384Uint1(x400))) + var x404 uint64 + _, x404 = bits.Sub64(uint64(p384Uint1(x390)), uint64(0x0), uint64(p384Uint1(x402))) + var x405 uint64 + p384CmovznzU64(&x405, p384Uint1(x404), x391, x379) + var x406 uint64 + p384CmovznzU64(&x406, p384Uint1(x404), x393, x381) + var x407 uint64 + p384CmovznzU64(&x407, p384Uint1(x404), x395, x383) + var x408 uint64 + p384CmovznzU64(&x408, p384Uint1(x404), x397, x385) + var x409 uint64 + p384CmovznzU64(&x409, p384Uint1(x404), x399, x387) + var x410 uint64 + p384CmovznzU64(&x410, p384Uint1(x404), x401, x389) + out1[0] = x405 + out1[1] = x406 + out1[2] = x407 + out1[3] = x408 + out1[4] = x409 + out1[5] = x410 +} + +// p384Selectznz is a multi-limb conditional select. +// +// Postconditions: +// eval out1 = (if arg1 = 0 then eval arg2 else eval arg3) +// +// Input Bounds: +// arg1: [0x0 ~> 0x1] +// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +// arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +// Output Bounds: +// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +func p384Selectznz(out1 *[6]uint64, arg1 p384Uint1, arg2 *[6]uint64, arg3 *[6]uint64) { + var x1 uint64 + p384CmovznzU64(&x1, arg1, arg2[0], arg3[0]) + var x2 uint64 + p384CmovznzU64(&x2, arg1, arg2[1], arg3[1]) + var x3 uint64 + p384CmovznzU64(&x3, arg1, arg2[2], arg3[2]) + var x4 uint64 + p384CmovznzU64(&x4, arg1, arg2[3], arg3[3]) + var x5 uint64 + p384CmovznzU64(&x5, arg1, arg2[4], arg3[4]) + var x6 uint64 + p384CmovznzU64(&x6, arg1, arg2[5], arg3[5]) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 + out1[4] = x5 + out1[5] = x6 +} + +// p384ToBytes serializes a field element NOT in the Montgomery domain to bytes in little-endian order. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// Postconditions: +// out1 = map (λ x, ⌊((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)⌋) [0..47] +// +// Input Bounds: +// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +// Output Bounds: +// out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]] +func p384ToBytes(out1 *[48]uint8, arg1 *[6]uint64) { + x1 := arg1[5] + x2 := arg1[4] + x3 := arg1[3] + x4 := arg1[2] + x5 := arg1[1] + x6 := arg1[0] + x7 := (uint8(x6) & 0xff) + x8 := (x6 >> 8) + x9 := (uint8(x8) & 0xff) + x10 := (x8 >> 8) + x11 := (uint8(x10) & 0xff) + x12 := (x10 >> 8) + x13 := (uint8(x12) & 0xff) + x14 := (x12 >> 8) + x15 := (uint8(x14) & 0xff) + x16 := (x14 >> 8) + x17 := (uint8(x16) & 0xff) + x18 := (x16 >> 8) + x19 := (uint8(x18) & 0xff) + x20 := uint8((x18 >> 8)) + x21 := (uint8(x5) & 0xff) + x22 := (x5 >> 8) + x23 := (uint8(x22) & 0xff) + x24 := (x22 >> 8) + x25 := (uint8(x24) & 0xff) + x26 := (x24 >> 8) + x27 := (uint8(x26) & 0xff) + x28 := (x26 >> 8) + x29 := (uint8(x28) & 0xff) + x30 := (x28 >> 8) + x31 := (uint8(x30) & 0xff) + x32 := (x30 >> 8) + x33 := (uint8(x32) & 0xff) + x34 := uint8((x32 >> 8)) + x35 := (uint8(x4) & 0xff) + x36 := (x4 >> 8) + x37 := (uint8(x36) & 0xff) + x38 := (x36 >> 8) + x39 := (uint8(x38) & 0xff) + x40 := (x38 >> 8) + x41 := (uint8(x40) & 0xff) + x42 := (x40 >> 8) + x43 := (uint8(x42) & 0xff) + x44 := (x42 >> 8) + x45 := (uint8(x44) & 0xff) + x46 := (x44 >> 8) + x47 := (uint8(x46) & 0xff) + x48 := uint8((x46 >> 8)) + x49 := (uint8(x3) & 0xff) + x50 := (x3 >> 8) + x51 := (uint8(x50) & 0xff) + x52 := (x50 >> 8) + x53 := (uint8(x52) & 0xff) + x54 := (x52 >> 8) + x55 := (uint8(x54) & 0xff) + x56 := (x54 >> 8) + x57 := (uint8(x56) & 0xff) + x58 := (x56 >> 8) + x59 := (uint8(x58) & 0xff) + x60 := (x58 >> 8) + x61 := (uint8(x60) & 0xff) + x62 := uint8((x60 >> 8)) + x63 := (uint8(x2) & 0xff) + x64 := (x2 >> 8) + x65 := (uint8(x64) & 0xff) + x66 := (x64 >> 8) + x67 := (uint8(x66) & 0xff) + x68 := (x66 >> 8) + x69 := (uint8(x68) & 0xff) + x70 := (x68 >> 8) + x71 := (uint8(x70) & 0xff) + x72 := (x70 >> 8) + x73 := (uint8(x72) & 0xff) + x74 := (x72 >> 8) + x75 := (uint8(x74) & 0xff) + x76 := uint8((x74 >> 8)) + x77 := (uint8(x1) & 0xff) + x78 := (x1 >> 8) + x79 := (uint8(x78) & 0xff) + x80 := (x78 >> 8) + x81 := (uint8(x80) & 0xff) + x82 := (x80 >> 8) + x83 := (uint8(x82) & 0xff) + x84 := (x82 >> 8) + x85 := (uint8(x84) & 0xff) + x86 := (x84 >> 8) + x87 := (uint8(x86) & 0xff) + x88 := (x86 >> 8) + x89 := (uint8(x88) & 0xff) + x90 := uint8((x88 >> 8)) + out1[0] = x7 + out1[1] = x9 + out1[2] = x11 + out1[3] = x13 + out1[4] = x15 + out1[5] = x17 + out1[6] = x19 + out1[7] = x20 + out1[8] = x21 + out1[9] = x23 + out1[10] = x25 + out1[11] = x27 + out1[12] = x29 + out1[13] = x31 + out1[14] = x33 + out1[15] = x34 + out1[16] = x35 + out1[17] = x37 + out1[18] = x39 + out1[19] = x41 + out1[20] = x43 + out1[21] = x45 + out1[22] = x47 + out1[23] = x48 + out1[24] = x49 + out1[25] = x51 + out1[26] = x53 + out1[27] = x55 + out1[28] = x57 + out1[29] = x59 + out1[30] = x61 + out1[31] = x62 + out1[32] = x63 + out1[33] = x65 + out1[34] = x67 + out1[35] = x69 + out1[36] = x71 + out1[37] = x73 + out1[38] = x75 + out1[39] = x76 + out1[40] = x77 + out1[41] = x79 + out1[42] = x81 + out1[43] = x83 + out1[44] = x85 + out1[45] = x87 + out1[46] = x89 + out1[47] = x90 +} + +// p384FromBytes deserializes a field element NOT in the Montgomery domain from bytes in little-endian order. +// +// Preconditions: +// 0 ≤ bytes_eval arg1 < m +// Postconditions: +// eval out1 mod m = bytes_eval arg1 mod m +// 0 ≤ eval out1 < m +// +// Input Bounds: +// arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]] +// Output Bounds: +// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +func p384FromBytes(out1 *[6]uint64, arg1 *[48]uint8) { + x1 := (uint64(arg1[47]) << 56) + x2 := (uint64(arg1[46]) << 48) + x3 := (uint64(arg1[45]) << 40) + x4 := (uint64(arg1[44]) << 32) + x5 := (uint64(arg1[43]) << 24) + x6 := (uint64(arg1[42]) << 16) + x7 := (uint64(arg1[41]) << 8) + x8 := arg1[40] + x9 := (uint64(arg1[39]) << 56) + x10 := (uint64(arg1[38]) << 48) + x11 := (uint64(arg1[37]) << 40) + x12 := (uint64(arg1[36]) << 32) + x13 := (uint64(arg1[35]) << 24) + x14 := (uint64(arg1[34]) << 16) + x15 := (uint64(arg1[33]) << 8) + x16 := arg1[32] + x17 := (uint64(arg1[31]) << 56) + x18 := (uint64(arg1[30]) << 48) + x19 := (uint64(arg1[29]) << 40) + x20 := (uint64(arg1[28]) << 32) + x21 := (uint64(arg1[27]) << 24) + x22 := (uint64(arg1[26]) << 16) + x23 := (uint64(arg1[25]) << 8) + x24 := arg1[24] + x25 := (uint64(arg1[23]) << 56) + x26 := (uint64(arg1[22]) << 48) + x27 := (uint64(arg1[21]) << 40) + x28 := (uint64(arg1[20]) << 32) + x29 := (uint64(arg1[19]) << 24) + x30 := (uint64(arg1[18]) << 16) + x31 := (uint64(arg1[17]) << 8) + x32 := arg1[16] + x33 := (uint64(arg1[15]) << 56) + x34 := (uint64(arg1[14]) << 48) + x35 := (uint64(arg1[13]) << 40) + x36 := (uint64(arg1[12]) << 32) + x37 := (uint64(arg1[11]) << 24) + x38 := (uint64(arg1[10]) << 16) + x39 := (uint64(arg1[9]) << 8) + x40 := arg1[8] + x41 := (uint64(arg1[7]) << 56) + x42 := (uint64(arg1[6]) << 48) + x43 := (uint64(arg1[5]) << 40) + x44 := (uint64(arg1[4]) << 32) + x45 := (uint64(arg1[3]) << 24) + x46 := (uint64(arg1[2]) << 16) + x47 := (uint64(arg1[1]) << 8) + x48 := arg1[0] + x49 := (x47 + uint64(x48)) + x50 := (x46 + x49) + x51 := (x45 + x50) + x52 := (x44 + x51) + x53 := (x43 + x52) + x54 := (x42 + x53) + x55 := (x41 + x54) + x56 := (x39 + uint64(x40)) + x57 := (x38 + x56) + x58 := (x37 + x57) + x59 := (x36 + x58) + x60 := (x35 + x59) + x61 := (x34 + x60) + x62 := (x33 + x61) + x63 := (x31 + uint64(x32)) + x64 := (x30 + x63) + x65 := (x29 + x64) + x66 := (x28 + x65) + x67 := (x27 + x66) + x68 := (x26 + x67) + x69 := (x25 + x68) + x70 := (x23 + uint64(x24)) + x71 := (x22 + x70) + x72 := (x21 + x71) + x73 := (x20 + x72) + x74 := (x19 + x73) + x75 := (x18 + x74) + x76 := (x17 + x75) + x77 := (x15 + uint64(x16)) + x78 := (x14 + x77) + x79 := (x13 + x78) + x80 := (x12 + x79) + x81 := (x11 + x80) + x82 := (x10 + x81) + x83 := (x9 + x82) + x84 := (x7 + uint64(x8)) + x85 := (x6 + x84) + x86 := (x5 + x85) + x87 := (x4 + x86) + x88 := (x3 + x87) + x89 := (x2 + x88) + x90 := (x1 + x89) + out1[0] = x55 + out1[1] = x62 + out1[2] = x69 + out1[3] = x76 + out1[4] = x83 + out1[5] = x90 +} diff --git a/src/crypto/elliptic/internal/fiat/p384_invert.go b/src/crypto/elliptic/internal/fiat/p384_invert.go new file mode 100644 index 0000000000..24169e98d9 --- /dev/null +++ b/src/crypto/elliptic/internal/fiat/p384_invert.go @@ -0,0 +1,102 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by addchain. DO NOT EDIT. + +package fiat + +// Invert sets e = 1/x, and returns e. +// +// If x == 0, Invert returns e = 0. +func (e *P384Element) Invert(x *P384Element) *P384Element { + // Inversion is implemented as exponentiation with exponent p − 2. + // The sequence of 15 multiplications and 383 squarings is derived from the + // following addition chain generated with github.com/mmcloughlin/addchain v0.3.0. + // + // _10 = 2*1 + // _11 = 1 + _10 + // _110 = 2*_11 + // _111 = 1 + _110 + // _111000 = _111 << 3 + // _111111 = _111 + _111000 + // x12 = _111111 << 6 + _111111 + // x24 = x12 << 12 + x12 + // x30 = x24 << 6 + _111111 + // x31 = 2*x30 + 1 + // x32 = 2*x31 + 1 + // x63 = x32 << 31 + x31 + // x126 = x63 << 63 + x63 + // x252 = x126 << 126 + x126 + // x255 = x252 << 3 + _111 + // i397 = ((x255 << 33 + x32) << 94 + x30) << 2 + // return 1 + i397 + // + + var z = new(P384Element).Set(e) + var t0 = new(P384Element) + var t1 = new(P384Element) + var t2 = new(P384Element) + var t3 = new(P384Element) + + z.Square(x) + z.Mul(x, z) + z.Square(z) + t1.Mul(x, z) + z.Square(t1) + for s := 1; s < 3; s++ { + z.Square(z) + } + z.Mul(t1, z) + t0.Square(z) + for s := 1; s < 6; s++ { + t0.Square(t0) + } + t0.Mul(z, t0) + t2.Square(t0) + for s := 1; s < 12; s++ { + t2.Square(t2) + } + t0.Mul(t0, t2) + for s := 0; s < 6; s++ { + t0.Square(t0) + } + z.Mul(z, t0) + t0.Square(z) + t2.Mul(x, t0) + t0.Square(t2) + t0.Mul(x, t0) + t3.Square(t0) + for s := 1; s < 31; s++ { + t3.Square(t3) + } + t2.Mul(t2, t3) + t3.Square(t2) + for s := 1; s < 63; s++ { + t3.Square(t3) + } + t2.Mul(t2, t3) + t3.Square(t2) + for s := 1; s < 126; s++ { + t3.Square(t3) + } + t2.Mul(t2, t3) + for s := 0; s < 3; s++ { + t2.Square(t2) + } + t1.Mul(t1, t2) + for s := 0; s < 33; s++ { + t1.Square(t1) + } + t0.Mul(t0, t1) + for s := 0; s < 94; s++ { + t0.Square(t0) + } + z.Mul(z, t0) + for s := 0; s < 2; s++ { + z.Square(z) + } + z.Mul(x, z) + + return e.Set(z) +} diff --git a/src/crypto/elliptic/internal/fiat/p521.go b/src/crypto/elliptic/internal/fiat/p521.go index 647c3f914f..3d12117e49 100644 --- a/src/crypto/elliptic/internal/fiat/p521.go +++ b/src/crypto/elliptic/internal/fiat/p521.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package fiat implements prime order fields using formally verified algorithms -// from the Fiat Cryptography project. +// Code generated by generate.go. DO NOT EDIT. + package fiat import ( @@ -15,20 +15,18 @@ import ( // // The zero value is a valid zero element. type P521Element struct { - // This element has the following bounds, which are tighter than - // the output bounds of some operations. Those operations must be - // followed by a carry. - // - // [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], - // [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], - // [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000] - x [9]uint64 + // Values are represented internally always in the Montgomery domain, and + // converted in Bytes and SetBytes. + x p521MontgomeryDomainFieldElement } +const p521ElementLen = 66 + +type p521UntypedFieldElement = [9]uint64 + // One sets e = 1, and returns e. func (e *P521Element) One() *P521Element { - *e = P521Element{} - e.x[0] = 1 + p521SetOne(&e.x) return e } @@ -57,153 +55,81 @@ func (e *P521Element) Set(t *P521Element) *P521Element { func (e *P521Element) Bytes() []byte { // This function is outlined to make the allocations inline in the caller // rather than happen on the heap. - var out [66]byte + var out [p521ElementLen]byte return e.bytes(&out) } -func (e *P521Element) bytes(out *[66]byte) []byte { - p521ToBytes(out, &e.x) - invertEndianness(out[:]) +func (e *P521Element) bytes(out *[p521ElementLen]byte) []byte { + var tmp p521NonMontgomeryDomainFieldElement + p521FromMontgomery(&tmp, &e.x) + p521ToBytes(out, (*p521UntypedFieldElement)(&tmp)) + p521InvertEndianness(out[:]) return out[:] } -// SetBytes sets e = v, where v is a big-endian 66-byte encoding, and returns -// e. If v is not 66 bytes or it encodes a value higher than 2^521 - 1, SetBytes -// returns nil and an error, and e is unchanged. +// p521MinusOneEncoding is the encoding of -1 mod p, so p - 1, the +// highest canonical encoding. It is used by SetBytes to check for non-canonical +// encodings such as p + k, 2p + k, etc. +var p521MinusOneEncoding = new(P521Element).Sub( + new(P521Element), new(P521Element).One()).Bytes() + +// SetBytes sets e = v, where v is a big-endian 66-byte encoding, and returns e. +// If v is not 66 bytes or it encodes a value higher than 2^521 - 1, +// SetBytes returns nil and an error, and e is unchanged. func (e *P521Element) SetBytes(v []byte) (*P521Element, error) { - if len(v) != 66 || v[0] > 1 { - return nil, errors.New("invalid P-521 field encoding") + if len(v) != p521ElementLen { + return nil, errors.New("invalid P521Element encoding") + } + for i := range v { + if v[i] < p521MinusOneEncoding[i] { + break + } + if v[i] > p521MinusOneEncoding[i] { + return nil, errors.New("invalid P521Element encoding") + } } - var in [66]byte + var in [p521ElementLen]byte copy(in[:], v) - invertEndianness(in[:]) - p521FromBytes(&e.x, &in) + p521InvertEndianness(in[:]) + var tmp p521NonMontgomeryDomainFieldElement + p521FromBytes((*p521UntypedFieldElement)(&tmp), &in) + p521ToMontgomery(&e.x, &tmp) return e, nil } -func invertEndianness(v []byte) { - for i := 0; i < len(v)/2; i++ { - v[i], v[len(v)-1-i] = v[len(v)-1-i], v[i] - } -} - // Add sets e = t1 + t2, and returns e. func (e *P521Element) Add(t1, t2 *P521Element) *P521Element { p521Add(&e.x, &t1.x, &t2.x) - p521Carry(&e.x, &e.x) return e } // Sub sets e = t1 - t2, and returns e. func (e *P521Element) Sub(t1, t2 *P521Element) *P521Element { p521Sub(&e.x, &t1.x, &t2.x) - p521Carry(&e.x, &e.x) return e } // Mul sets e = t1 * t2, and returns e. func (e *P521Element) Mul(t1, t2 *P521Element) *P521Element { - p521CarryMul(&e.x, &t1.x, &t2.x) + p521Mul(&e.x, &t1.x, &t2.x) return e } // Square sets e = t * t, and returns e. func (e *P521Element) Square(t *P521Element) *P521Element { - p521CarrySquare(&e.x, &t.x) + p521Square(&e.x, &t.x) return e } -// Select sets e to a if cond == 1, and to b if cond == 0. +// Select sets v to a if cond == 1, and to b if cond == 0. func (v *P521Element) Select(a, b *P521Element, cond int) *P521Element { - p521Selectznz(&v.x, p521Uint1(cond), &b.x, &a.x) + p521Selectznz((*p521UntypedFieldElement)(&v.x), p521Uint1(cond), + (*p521UntypedFieldElement)(&b.x), (*p521UntypedFieldElement)(&a.x)) return v } -// Invert sets e = 1/t, and returns e. -// -// If t == 0, Invert returns e = 0. -func (e *P521Element) Invert(t *P521Element) *P521Element { - // Inversion is implemented as exponentiation with exponent p − 2. - // The sequence of multiplications and squarings was generated with - // github.com/mmcloughlin/addchain v0.2.0. - - var t1, t2 = new(P521Element), new(P521Element) - - // _10 = 2 * 1 - t1.Square(t) - - // _11 = 1 + _10 - t1.Mul(t, t1) - - // _1100 = _11 << 2 - t2.Square(t1) - t2.Square(t2) - - // _1111 = _11 + _1100 - t1.Mul(t1, t2) - - // _11110000 = _1111 << 4 - t2.Square(t1) - for i := 0; i < 3; i++ { - t2.Square(t2) - } - - // _11111111 = _1111 + _11110000 - t1.Mul(t1, t2) - - // x16 = _11111111<<8 + _11111111 - t2.Square(t1) - for i := 0; i < 7; i++ { - t2.Square(t2) - } - t1.Mul(t1, t2) - - // x32 = x16<<16 + x16 - t2.Square(t1) - for i := 0; i < 15; i++ { - t2.Square(t2) - } - t1.Mul(t1, t2) - - // x64 = x32<<32 + x32 - t2.Square(t1) - for i := 0; i < 31; i++ { - t2.Square(t2) - } - t1.Mul(t1, t2) - - // x65 = 2*x64 + 1 - t2.Square(t1) - t2.Mul(t2, t) - - // x129 = x65<<64 + x64 - for i := 0; i < 64; i++ { - t2.Square(t2) - } - t1.Mul(t1, t2) - - // x130 = 2*x129 + 1 - t2.Square(t1) - t2.Mul(t2, t) - - // x259 = x130<<129 + x129 - for i := 0; i < 129; i++ { - t2.Square(t2) - } - t1.Mul(t1, t2) - - // x260 = 2*x259 + 1 - t2.Square(t1) - t2.Mul(t2, t) - - // x519 = x260<<259 + x259 - for i := 0; i < 259; i++ { - t2.Square(t2) +func p521InvertEndianness(v []byte) { + for i := 0; i < len(v)/2; i++ { + v[i], v[len(v)-1-i] = v[len(v)-1-i], v[i] } - t1.Mul(t1, t2) - - // return x519<<2 + 1 - t1.Square(t1) - t1.Square(t1) - return e.Mul(t1, t) } diff --git a/src/crypto/elliptic/internal/fiat/p521_fiat64.go b/src/crypto/elliptic/internal/fiat/p521_fiat64.go index f86283b587..9f4f290f4c 100644 --- a/src/crypto/elliptic/internal/fiat/p521_fiat64.go +++ b/src/crypto/elliptic/internal/fiat/p521_fiat64.go @@ -1,133 +1,57 @@ // Code generated by Fiat Cryptography. DO NOT EDIT. // -// Autogenerated: 'fiat-crypto/src/ExtractionOCaml/unsaturated_solinas' --lang Go --no-wide-int --cmovznz-by-mul --internal-static --public-function-case camelCase --public-type-case camelCase --private-function-case camelCase --private-type-case camelCase --no-prefix-fiat --package-name fiat --doc-text-before-function-name '' --doc-prepend-header 'Code generated by Fiat Cryptography. DO NOT EDIT.' --doc-newline-before-package-declaration p521 64 9 '2^521 - 1' carry_mul carry_square carry add sub to_bytes from_bytes selectznz +// Autogenerated: word_by_word_montgomery --lang Go --no-wide-int --cmovznz-by-mul --relax-primitive-carry-to-bitwidth 32,64 --internal-static --public-function-case camelCase --public-type-case camelCase --private-function-case camelCase --private-type-case camelCase --doc-text-before-function-name '' --doc-newline-before-package-declaration --doc-prepend-header 'Code generated by Fiat Cryptography. DO NOT EDIT.' --package-name fiat --no-prefix-fiat p521 64 '2^521 - 1' mul square add sub one from_montgomery to_montgomery selectznz to_bytes from_bytes // // curve description: p521 // // machine_wordsize = 64 (from "64") // -// requested operations: carry_mul, carry_square, carry, add, sub, to_bytes, from_bytes, selectznz +// requested operations: mul, square, add, sub, one, from_montgomery, to_montgomery, selectznz, to_bytes, from_bytes // -// n = 9 (from "9") +// m = 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff (from "2^521 - 1") // -// s-c = 2^521 - [(1, 1)] (from "2^521 - 1") // -// tight_bounds_multiplier = 1 (from "") // +// NOTE: In addition to the bounds specified above each function, all // +// functions synthesized for this Montgomery arithmetic require the // -// Computed values: +// input to be strictly less than the prime modulus (m), and also +// +// require the input to be in the unique saturated representation. +// +// All functions also ensure that these two properties are true of +// +// return values. // -// carry_chain = [0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1] // -// eval z = z[0] + (z[1] << 58) + (z[2] << 116) + (z[3] << 174) + (z[4] << 232) + (z[5] << 0x122) + (z[6] << 0x15c) + (z[7] << 0x196) + (z[8] << 0x1d0) +// +// Computed values: +// +// eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) + (z[4] << 256) + (z[5] << 0x140) + (z[6] << 0x180) + (z[7] << 0x1c0) + (z[8] << 2^9) // // bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) + (z[28] << 224) + (z[29] << 232) + (z[30] << 240) + (z[31] << 248) + (z[32] << 256) + (z[33] << 0x108) + (z[34] << 0x110) + (z[35] << 0x118) + (z[36] << 0x120) + (z[37] << 0x128) + (z[38] << 0x130) + (z[39] << 0x138) + (z[40] << 0x140) + (z[41] << 0x148) + (z[42] << 0x150) + (z[43] << 0x158) + (z[44] << 0x160) + (z[45] << 0x168) + (z[46] << 0x170) + (z[47] << 0x178) + (z[48] << 0x180) + (z[49] << 0x188) + (z[50] << 0x190) + (z[51] << 0x198) + (z[52] << 0x1a0) + (z[53] << 0x1a8) + (z[54] << 0x1b0) + (z[55] << 0x1b8) + (z[56] << 0x1c0) + (z[57] << 0x1c8) + (z[58] << 0x1d0) + (z[59] << 0x1d8) + (z[60] << 0x1e0) + (z[61] << 0x1e8) + (z[62] << 0x1f0) + (z[63] << 0x1f8) + (z[64] << 2^9) + (z[65] << 0x208) // -// balance = [0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x3fffffffffffffe] +// twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) + (z[4] << 256) + (z[5] << 0x140) + (z[6] << 0x180) + (z[7] << 0x1c0) + (z[8] << 2^9) in +// +// if x1 & (2^576-1) < 2^575 then x1 & (2^576-1) else (x1 & (2^576-1)) - 2^576 package fiat import "math/bits" -type p521Uint1 uint8 -type p521Int1 int8 - -// p521AddcarryxU64 is a thin wrapper around bits.Add64 that uses p521Uint1 rather than uint64 -func p521AddcarryxU64(x uint64, y uint64, carry p521Uint1) (uint64, p521Uint1) { - sum, carryOut := bits.Add64(x, y, uint64(carry)) - return sum, p521Uint1(carryOut) -} - -// p521SubborrowxU64 is a thin wrapper around bits.Sub64 that uses p521Uint1 rather than uint64 -func p521SubborrowxU64(x uint64, y uint64, carry p521Uint1) (uint64, p521Uint1) { - sum, carryOut := bits.Sub64(x, y, uint64(carry)) - return sum, p521Uint1(carryOut) -} - -// p521AddcarryxU58 is an addition with carry. -// -// Postconditions: -// out1 = (arg1 + arg2 + arg3) mod 2^58 -// out2 = ⌊(arg1 + arg2 + arg3) / 2^58⌋ -// -// Input Bounds: -// arg1: [0x0 ~> 0x1] -// arg2: [0x0 ~> 0x3ffffffffffffff] -// arg3: [0x0 ~> 0x3ffffffffffffff] -// Output Bounds: -// out1: [0x0 ~> 0x3ffffffffffffff] -// out2: [0x0 ~> 0x1] -func p521AddcarryxU58(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) { - x1 := ((uint64(arg1) + arg2) + arg3) - x2 := (x1 & 0x3ffffffffffffff) - x3 := p521Uint1((x1 >> 58)) - *out1 = x2 - *out2 = x3 -} - -// p521SubborrowxU58 is a subtraction with borrow. -// -// Postconditions: -// out1 = (-arg1 + arg2 + -arg3) mod 2^58 -// out2 = -⌊(-arg1 + arg2 + -arg3) / 2^58⌋ -// -// Input Bounds: -// arg1: [0x0 ~> 0x1] -// arg2: [0x0 ~> 0x3ffffffffffffff] -// arg3: [0x0 ~> 0x3ffffffffffffff] -// Output Bounds: -// out1: [0x0 ~> 0x3ffffffffffffff] -// out2: [0x0 ~> 0x1] -func p521SubborrowxU58(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) { - x1 := ((int64(arg2) - int64(arg1)) - int64(arg3)) - x2 := p521Int1((x1 >> 58)) - x3 := (uint64(x1) & 0x3ffffffffffffff) - *out1 = x3 - *out2 = (0x0 - p521Uint1(x2)) -} +type p521Uint1 uint64 // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927 +type p521Int1 int64 // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927 -// p521AddcarryxU57 is an addition with carry. -// -// Postconditions: -// out1 = (arg1 + arg2 + arg3) mod 2^57 -// out2 = ⌊(arg1 + arg2 + arg3) / 2^57⌋ +// The type p521MontgomeryDomainFieldElement is a field element in the Montgomery domain. // -// Input Bounds: -// arg1: [0x0 ~> 0x1] -// arg2: [0x0 ~> 0x1ffffffffffffff] -// arg3: [0x0 ~> 0x1ffffffffffffff] -// Output Bounds: -// out1: [0x0 ~> 0x1ffffffffffffff] -// out2: [0x0 ~> 0x1] -func p521AddcarryxU57(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) { - x1 := ((uint64(arg1) + arg2) + arg3) - x2 := (x1 & 0x1ffffffffffffff) - x3 := p521Uint1((x1 >> 57)) - *out1 = x2 - *out2 = x3 -} +// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +type p521MontgomeryDomainFieldElement [9]uint64 -// p521SubborrowxU57 is a subtraction with borrow. +// The type p521NonMontgomeryDomainFieldElement is a field element NOT in the Montgomery domain. // -// Postconditions: -// out1 = (-arg1 + arg2 + -arg3) mod 2^57 -// out2 = -⌊(-arg1 + arg2 + -arg3) / 2^57⌋ -// -// Input Bounds: -// arg1: [0x0 ~> 0x1] -// arg2: [0x0 ~> 0x1ffffffffffffff] -// arg3: [0x0 ~> 0x1ffffffffffffff] -// Output Bounds: -// out1: [0x0 ~> 0x1ffffffffffffff] -// out2: [0x0 ~> 0x1] -func p521SubborrowxU57(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) { - x1 := ((int64(arg2) - int64(arg1)) - int64(arg3)) - x2 := p521Int1((x1 >> 57)) - x3 := (uint64(x1) & 0x1ffffffffffffff) - *out1 = x3 - *out2 = (0x0 - p521Uint1(x2)) -} +// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +type p521NonMontgomeryDomainFieldElement [9]uint64 // p521CmovznzU64 is a single-word conditional move. // @@ -146,1229 +70,5083 @@ func p521CmovznzU64(out1 *uint64, arg1 p521Uint1, arg2 uint64, arg3 uint64) { *out1 = x2 } -// p521CarryMul multiplies two field elements and reduces the result. +// p521Mul multiplies two field elements in the Montgomery domain. // +// Preconditions: +// 0 ≤ eval arg1 < m +// 0 ≤ eval arg2 < m // Postconditions: -// eval out1 mod m = (eval arg1 * eval arg2) mod m +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m +// 0 ≤ eval out1 < m // -// Input Bounds: -// arg1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]] -// arg2: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]] -// Output Bounds: -// out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] -func p521CarryMul(out1 *[9]uint64, arg1 *[9]uint64, arg2 *[9]uint64) { - var x1 uint64 - var x2 uint64 - x2, x1 = bits.Mul64(arg1[8], (arg2[8] * 0x2)) - var x3 uint64 - var x4 uint64 - x4, x3 = bits.Mul64(arg1[8], (arg2[7] * 0x2)) - var x5 uint64 - var x6 uint64 - x6, x5 = bits.Mul64(arg1[8], (arg2[6] * 0x2)) - var x7 uint64 - var x8 uint64 - x8, x7 = bits.Mul64(arg1[8], (arg2[5] * 0x2)) - var x9 uint64 +func p521Mul(out1 *p521MontgomeryDomainFieldElement, arg1 *p521MontgomeryDomainFieldElement, arg2 *p521MontgomeryDomainFieldElement) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[4] + x5 := arg1[5] + x6 := arg1[6] + x7 := arg1[7] + x8 := arg1[8] + x9 := arg1[0] var x10 uint64 - x10, x9 = bits.Mul64(arg1[8], (arg2[4] * 0x2)) var x11 uint64 + x11, x10 = bits.Mul64(x9, arg2[8]) var x12 uint64 - x12, x11 = bits.Mul64(arg1[8], (arg2[3] * 0x2)) var x13 uint64 + x13, x12 = bits.Mul64(x9, arg2[7]) var x14 uint64 - x14, x13 = bits.Mul64(arg1[8], (arg2[2] * 0x2)) var x15 uint64 + x15, x14 = bits.Mul64(x9, arg2[6]) var x16 uint64 - x16, x15 = bits.Mul64(arg1[8], (arg2[1] * 0x2)) var x17 uint64 + x17, x16 = bits.Mul64(x9, arg2[5]) var x18 uint64 - x18, x17 = bits.Mul64(arg1[7], (arg2[8] * 0x2)) var x19 uint64 + x19, x18 = bits.Mul64(x9, arg2[4]) var x20 uint64 - x20, x19 = bits.Mul64(arg1[7], (arg2[7] * 0x2)) var x21 uint64 + x21, x20 = bits.Mul64(x9, arg2[3]) var x22 uint64 - x22, x21 = bits.Mul64(arg1[7], (arg2[6] * 0x2)) var x23 uint64 + x23, x22 = bits.Mul64(x9, arg2[2]) var x24 uint64 - x24, x23 = bits.Mul64(arg1[7], (arg2[5] * 0x2)) var x25 uint64 + x25, x24 = bits.Mul64(x9, arg2[1]) var x26 uint64 - x26, x25 = bits.Mul64(arg1[7], (arg2[4] * 0x2)) var x27 uint64 + x27, x26 = bits.Mul64(x9, arg2[0]) var x28 uint64 - x28, x27 = bits.Mul64(arg1[7], (arg2[3] * 0x2)) var x29 uint64 + x28, x29 = bits.Add64(x27, x24, uint64(0x0)) var x30 uint64 - x30, x29 = bits.Mul64(arg1[7], (arg2[2] * 0x2)) var x31 uint64 + x30, x31 = bits.Add64(x25, x22, uint64(p521Uint1(x29))) var x32 uint64 - x32, x31 = bits.Mul64(arg1[6], (arg2[8] * 0x2)) var x33 uint64 + x32, x33 = bits.Add64(x23, x20, uint64(p521Uint1(x31))) var x34 uint64 - x34, x33 = bits.Mul64(arg1[6], (arg2[7] * 0x2)) var x35 uint64 + x34, x35 = bits.Add64(x21, x18, uint64(p521Uint1(x33))) var x36 uint64 - x36, x35 = bits.Mul64(arg1[6], (arg2[6] * 0x2)) var x37 uint64 + x36, x37 = bits.Add64(x19, x16, uint64(p521Uint1(x35))) var x38 uint64 - x38, x37 = bits.Mul64(arg1[6], (arg2[5] * 0x2)) var x39 uint64 + x38, x39 = bits.Add64(x17, x14, uint64(p521Uint1(x37))) var x40 uint64 - x40, x39 = bits.Mul64(arg1[6], (arg2[4] * 0x2)) var x41 uint64 + x40, x41 = bits.Add64(x15, x12, uint64(p521Uint1(x39))) var x42 uint64 - x42, x41 = bits.Mul64(arg1[6], (arg2[3] * 0x2)) var x43 uint64 - var x44 uint64 - x44, x43 = bits.Mul64(arg1[5], (arg2[8] * 0x2)) + x42, x43 = bits.Add64(x13, x10, uint64(p521Uint1(x41))) + x44 := (uint64(p521Uint1(x43)) + x11) var x45 uint64 var x46 uint64 - x46, x45 = bits.Mul64(arg1[5], (arg2[7] * 0x2)) + x46, x45 = bits.Mul64(x26, 0x1ff) var x47 uint64 var x48 uint64 - x48, x47 = bits.Mul64(arg1[5], (arg2[6] * 0x2)) + x48, x47 = bits.Mul64(x26, 0xffffffffffffffff) var x49 uint64 var x50 uint64 - x50, x49 = bits.Mul64(arg1[5], (arg2[5] * 0x2)) + x50, x49 = bits.Mul64(x26, 0xffffffffffffffff) var x51 uint64 var x52 uint64 - x52, x51 = bits.Mul64(arg1[5], (arg2[4] * 0x2)) + x52, x51 = bits.Mul64(x26, 0xffffffffffffffff) var x53 uint64 var x54 uint64 - x54, x53 = bits.Mul64(arg1[4], (arg2[8] * 0x2)) + x54, x53 = bits.Mul64(x26, 0xffffffffffffffff) var x55 uint64 var x56 uint64 - x56, x55 = bits.Mul64(arg1[4], (arg2[7] * 0x2)) + x56, x55 = bits.Mul64(x26, 0xffffffffffffffff) var x57 uint64 var x58 uint64 - x58, x57 = bits.Mul64(arg1[4], (arg2[6] * 0x2)) + x58, x57 = bits.Mul64(x26, 0xffffffffffffffff) var x59 uint64 var x60 uint64 - x60, x59 = bits.Mul64(arg1[4], (arg2[5] * 0x2)) + x60, x59 = bits.Mul64(x26, 0xffffffffffffffff) var x61 uint64 var x62 uint64 - x62, x61 = bits.Mul64(arg1[3], (arg2[8] * 0x2)) + x62, x61 = bits.Mul64(x26, 0xffffffffffffffff) var x63 uint64 var x64 uint64 - x64, x63 = bits.Mul64(arg1[3], (arg2[7] * 0x2)) + x63, x64 = bits.Add64(x62, x59, uint64(0x0)) var x65 uint64 var x66 uint64 - x66, x65 = bits.Mul64(arg1[3], (arg2[6] * 0x2)) + x65, x66 = bits.Add64(x60, x57, uint64(p521Uint1(x64))) var x67 uint64 var x68 uint64 - x68, x67 = bits.Mul64(arg1[2], (arg2[8] * 0x2)) + x67, x68 = bits.Add64(x58, x55, uint64(p521Uint1(x66))) var x69 uint64 var x70 uint64 - x70, x69 = bits.Mul64(arg1[2], (arg2[7] * 0x2)) + x69, x70 = bits.Add64(x56, x53, uint64(p521Uint1(x68))) var x71 uint64 var x72 uint64 - x72, x71 = bits.Mul64(arg1[1], (arg2[8] * 0x2)) + x71, x72 = bits.Add64(x54, x51, uint64(p521Uint1(x70))) var x73 uint64 var x74 uint64 - x74, x73 = bits.Mul64(arg1[8], arg2[0]) + x73, x74 = bits.Add64(x52, x49, uint64(p521Uint1(x72))) var x75 uint64 var x76 uint64 - x76, x75 = bits.Mul64(arg1[7], arg2[1]) + x75, x76 = bits.Add64(x50, x47, uint64(p521Uint1(x74))) var x77 uint64 var x78 uint64 - x78, x77 = bits.Mul64(arg1[7], arg2[0]) - var x79 uint64 - var x80 uint64 - x80, x79 = bits.Mul64(arg1[6], arg2[2]) + x77, x78 = bits.Add64(x48, x45, uint64(p521Uint1(x76))) + x79 := (uint64(p521Uint1(x78)) + x46) var x81 uint64 + _, x81 = bits.Add64(x26, x61, uint64(0x0)) var x82 uint64 - x82, x81 = bits.Mul64(arg1[6], arg2[1]) var x83 uint64 + x82, x83 = bits.Add64(x28, x63, uint64(p521Uint1(x81))) var x84 uint64 - x84, x83 = bits.Mul64(arg1[6], arg2[0]) var x85 uint64 + x84, x85 = bits.Add64(x30, x65, uint64(p521Uint1(x83))) var x86 uint64 - x86, x85 = bits.Mul64(arg1[5], arg2[3]) var x87 uint64 + x86, x87 = bits.Add64(x32, x67, uint64(p521Uint1(x85))) var x88 uint64 - x88, x87 = bits.Mul64(arg1[5], arg2[2]) var x89 uint64 + x88, x89 = bits.Add64(x34, x69, uint64(p521Uint1(x87))) var x90 uint64 - x90, x89 = bits.Mul64(arg1[5], arg2[1]) var x91 uint64 + x90, x91 = bits.Add64(x36, x71, uint64(p521Uint1(x89))) var x92 uint64 - x92, x91 = bits.Mul64(arg1[5], arg2[0]) var x93 uint64 + x92, x93 = bits.Add64(x38, x73, uint64(p521Uint1(x91))) var x94 uint64 - x94, x93 = bits.Mul64(arg1[4], arg2[4]) var x95 uint64 + x94, x95 = bits.Add64(x40, x75, uint64(p521Uint1(x93))) var x96 uint64 - x96, x95 = bits.Mul64(arg1[4], arg2[3]) var x97 uint64 + x96, x97 = bits.Add64(x42, x77, uint64(p521Uint1(x95))) var x98 uint64 - x98, x97 = bits.Mul64(arg1[4], arg2[2]) var x99 uint64 + x98, x99 = bits.Add64(x44, x79, uint64(p521Uint1(x97))) var x100 uint64 - x100, x99 = bits.Mul64(arg1[4], arg2[1]) var x101 uint64 + x101, x100 = bits.Mul64(x1, arg2[8]) var x102 uint64 - x102, x101 = bits.Mul64(arg1[4], arg2[0]) var x103 uint64 + x103, x102 = bits.Mul64(x1, arg2[7]) var x104 uint64 - x104, x103 = bits.Mul64(arg1[3], arg2[5]) var x105 uint64 + x105, x104 = bits.Mul64(x1, arg2[6]) var x106 uint64 - x106, x105 = bits.Mul64(arg1[3], arg2[4]) var x107 uint64 + x107, x106 = bits.Mul64(x1, arg2[5]) var x108 uint64 - x108, x107 = bits.Mul64(arg1[3], arg2[3]) var x109 uint64 + x109, x108 = bits.Mul64(x1, arg2[4]) var x110 uint64 - x110, x109 = bits.Mul64(arg1[3], arg2[2]) var x111 uint64 + x111, x110 = bits.Mul64(x1, arg2[3]) var x112 uint64 - x112, x111 = bits.Mul64(arg1[3], arg2[1]) var x113 uint64 + x113, x112 = bits.Mul64(x1, arg2[2]) var x114 uint64 - x114, x113 = bits.Mul64(arg1[3], arg2[0]) var x115 uint64 + x115, x114 = bits.Mul64(x1, arg2[1]) var x116 uint64 - x116, x115 = bits.Mul64(arg1[2], arg2[6]) var x117 uint64 + x117, x116 = bits.Mul64(x1, arg2[0]) var x118 uint64 - x118, x117 = bits.Mul64(arg1[2], arg2[5]) var x119 uint64 + x118, x119 = bits.Add64(x117, x114, uint64(0x0)) var x120 uint64 - x120, x119 = bits.Mul64(arg1[2], arg2[4]) var x121 uint64 + x120, x121 = bits.Add64(x115, x112, uint64(p521Uint1(x119))) var x122 uint64 - x122, x121 = bits.Mul64(arg1[2], arg2[3]) var x123 uint64 + x122, x123 = bits.Add64(x113, x110, uint64(p521Uint1(x121))) var x124 uint64 - x124, x123 = bits.Mul64(arg1[2], arg2[2]) var x125 uint64 + x124, x125 = bits.Add64(x111, x108, uint64(p521Uint1(x123))) var x126 uint64 - x126, x125 = bits.Mul64(arg1[2], arg2[1]) var x127 uint64 + x126, x127 = bits.Add64(x109, x106, uint64(p521Uint1(x125))) var x128 uint64 - x128, x127 = bits.Mul64(arg1[2], arg2[0]) var x129 uint64 + x128, x129 = bits.Add64(x107, x104, uint64(p521Uint1(x127))) var x130 uint64 - x130, x129 = bits.Mul64(arg1[1], arg2[7]) var x131 uint64 + x130, x131 = bits.Add64(x105, x102, uint64(p521Uint1(x129))) var x132 uint64 - x132, x131 = bits.Mul64(arg1[1], arg2[6]) var x133 uint64 - var x134 uint64 - x134, x133 = bits.Mul64(arg1[1], arg2[5]) + x132, x133 = bits.Add64(x103, x100, uint64(p521Uint1(x131))) + x134 := (uint64(p521Uint1(x133)) + x101) var x135 uint64 var x136 uint64 - x136, x135 = bits.Mul64(arg1[1], arg2[4]) + x135, x136 = bits.Add64(x82, x116, uint64(0x0)) var x137 uint64 var x138 uint64 - x138, x137 = bits.Mul64(arg1[1], arg2[3]) + x137, x138 = bits.Add64(x84, x118, uint64(p521Uint1(x136))) var x139 uint64 var x140 uint64 - x140, x139 = bits.Mul64(arg1[1], arg2[2]) + x139, x140 = bits.Add64(x86, x120, uint64(p521Uint1(x138))) var x141 uint64 var x142 uint64 - x142, x141 = bits.Mul64(arg1[1], arg2[1]) + x141, x142 = bits.Add64(x88, x122, uint64(p521Uint1(x140))) var x143 uint64 var x144 uint64 - x144, x143 = bits.Mul64(arg1[1], arg2[0]) + x143, x144 = bits.Add64(x90, x124, uint64(p521Uint1(x142))) var x145 uint64 var x146 uint64 - x146, x145 = bits.Mul64(arg1[0], arg2[8]) + x145, x146 = bits.Add64(x92, x126, uint64(p521Uint1(x144))) var x147 uint64 var x148 uint64 - x148, x147 = bits.Mul64(arg1[0], arg2[7]) + x147, x148 = bits.Add64(x94, x128, uint64(p521Uint1(x146))) var x149 uint64 var x150 uint64 - x150, x149 = bits.Mul64(arg1[0], arg2[6]) + x149, x150 = bits.Add64(x96, x130, uint64(p521Uint1(x148))) var x151 uint64 var x152 uint64 - x152, x151 = bits.Mul64(arg1[0], arg2[5]) + x151, x152 = bits.Add64(x98, x132, uint64(p521Uint1(x150))) var x153 uint64 var x154 uint64 - x154, x153 = bits.Mul64(arg1[0], arg2[4]) + x153, x154 = bits.Add64(uint64(p521Uint1(x99)), x134, uint64(p521Uint1(x152))) var x155 uint64 var x156 uint64 - x156, x155 = bits.Mul64(arg1[0], arg2[3]) + x156, x155 = bits.Mul64(x135, 0x1ff) var x157 uint64 var x158 uint64 - x158, x157 = bits.Mul64(arg1[0], arg2[2]) + x158, x157 = bits.Mul64(x135, 0xffffffffffffffff) var x159 uint64 var x160 uint64 - x160, x159 = bits.Mul64(arg1[0], arg2[1]) + x160, x159 = bits.Mul64(x135, 0xffffffffffffffff) var x161 uint64 var x162 uint64 - x162, x161 = bits.Mul64(arg1[0], arg2[0]) + x162, x161 = bits.Mul64(x135, 0xffffffffffffffff) var x163 uint64 - var x164 p521Uint1 - x163, x164 = p521AddcarryxU64(x29, x15, 0x0) + var x164 uint64 + x164, x163 = bits.Mul64(x135, 0xffffffffffffffff) var x165 uint64 - x165, _ = p521AddcarryxU64(x30, x16, x164) + var x166 uint64 + x166, x165 = bits.Mul64(x135, 0xffffffffffffffff) var x167 uint64 - var x168 p521Uint1 - x167, x168 = p521AddcarryxU64(x41, x163, 0x0) + var x168 uint64 + x168, x167 = bits.Mul64(x135, 0xffffffffffffffff) var x169 uint64 - x169, _ = p521AddcarryxU64(x42, x165, x168) + var x170 uint64 + x170, x169 = bits.Mul64(x135, 0xffffffffffffffff) var x171 uint64 - var x172 p521Uint1 - x171, x172 = p521AddcarryxU64(x51, x167, 0x0) + var x172 uint64 + x172, x171 = bits.Mul64(x135, 0xffffffffffffffff) var x173 uint64 - x173, _ = p521AddcarryxU64(x52, x169, x172) + var x174 uint64 + x173, x174 = bits.Add64(x172, x169, uint64(0x0)) var x175 uint64 - var x176 p521Uint1 - x175, x176 = p521AddcarryxU64(x59, x171, 0x0) + var x176 uint64 + x175, x176 = bits.Add64(x170, x167, uint64(p521Uint1(x174))) var x177 uint64 - x177, _ = p521AddcarryxU64(x60, x173, x176) + var x178 uint64 + x177, x178 = bits.Add64(x168, x165, uint64(p521Uint1(x176))) var x179 uint64 - var x180 p521Uint1 - x179, x180 = p521AddcarryxU64(x65, x175, 0x0) + var x180 uint64 + x179, x180 = bits.Add64(x166, x163, uint64(p521Uint1(x178))) var x181 uint64 - x181, _ = p521AddcarryxU64(x66, x177, x180) + var x182 uint64 + x181, x182 = bits.Add64(x164, x161, uint64(p521Uint1(x180))) var x183 uint64 - var x184 p521Uint1 - x183, x184 = p521AddcarryxU64(x69, x179, 0x0) + var x184 uint64 + x183, x184 = bits.Add64(x162, x159, uint64(p521Uint1(x182))) var x185 uint64 - x185, _ = p521AddcarryxU64(x70, x181, x184) + var x186 uint64 + x185, x186 = bits.Add64(x160, x157, uint64(p521Uint1(x184))) var x187 uint64 - var x188 p521Uint1 - x187, x188 = p521AddcarryxU64(x71, x183, 0x0) - var x189 uint64 - x189, _ = p521AddcarryxU64(x72, x185, x188) + var x188 uint64 + x187, x188 = bits.Add64(x158, x155, uint64(p521Uint1(x186))) + x189 := (uint64(p521Uint1(x188)) + x156) var x191 uint64 - var x192 p521Uint1 - x191, x192 = p521AddcarryxU64(x161, x187, 0x0) + _, x191 = bits.Add64(x135, x171, uint64(0x0)) + var x192 uint64 var x193 uint64 - x193, _ = p521AddcarryxU64(x162, x189, x192) - x195 := ((x191 >> 58) | ((x193 << 6) & 0xffffffffffffffff)) - x196 := (x193 >> 58) - x197 := (x191 & 0x3ffffffffffffff) + x192, x193 = bits.Add64(x137, x173, uint64(p521Uint1(x191))) + var x194 uint64 + var x195 uint64 + x194, x195 = bits.Add64(x139, x175, uint64(p521Uint1(x193))) + var x196 uint64 + var x197 uint64 + x196, x197 = bits.Add64(x141, x177, uint64(p521Uint1(x195))) var x198 uint64 - var x199 p521Uint1 - x198, x199 = p521AddcarryxU64(x75, x73, 0x0) + var x199 uint64 + x198, x199 = bits.Add64(x143, x179, uint64(p521Uint1(x197))) var x200 uint64 - x200, _ = p521AddcarryxU64(x76, x74, x199) + var x201 uint64 + x200, x201 = bits.Add64(x145, x181, uint64(p521Uint1(x199))) var x202 uint64 - var x203 p521Uint1 - x202, x203 = p521AddcarryxU64(x79, x198, 0x0) + var x203 uint64 + x202, x203 = bits.Add64(x147, x183, uint64(p521Uint1(x201))) var x204 uint64 - x204, _ = p521AddcarryxU64(x80, x200, x203) + var x205 uint64 + x204, x205 = bits.Add64(x149, x185, uint64(p521Uint1(x203))) var x206 uint64 - var x207 p521Uint1 - x206, x207 = p521AddcarryxU64(x85, x202, 0x0) + var x207 uint64 + x206, x207 = bits.Add64(x151, x187, uint64(p521Uint1(x205))) var x208 uint64 - x208, _ = p521AddcarryxU64(x86, x204, x207) - var x210 uint64 - var x211 p521Uint1 - x210, x211 = p521AddcarryxU64(x93, x206, 0x0) + var x209 uint64 + x208, x209 = bits.Add64(x153, x189, uint64(p521Uint1(x207))) + x210 := (uint64(p521Uint1(x209)) + uint64(p521Uint1(x154))) + var x211 uint64 var x212 uint64 - x212, _ = p521AddcarryxU64(x94, x208, x211) + x212, x211 = bits.Mul64(x2, arg2[8]) + var x213 uint64 var x214 uint64 - var x215 p521Uint1 - x214, x215 = p521AddcarryxU64(x103, x210, 0x0) + x214, x213 = bits.Mul64(x2, arg2[7]) + var x215 uint64 var x216 uint64 - x216, _ = p521AddcarryxU64(x104, x212, x215) + x216, x215 = bits.Mul64(x2, arg2[6]) + var x217 uint64 var x218 uint64 - var x219 p521Uint1 - x218, x219 = p521AddcarryxU64(x115, x214, 0x0) + x218, x217 = bits.Mul64(x2, arg2[5]) + var x219 uint64 var x220 uint64 - x220, _ = p521AddcarryxU64(x116, x216, x219) + x220, x219 = bits.Mul64(x2, arg2[4]) + var x221 uint64 var x222 uint64 - var x223 p521Uint1 - x222, x223 = p521AddcarryxU64(x129, x218, 0x0) + x222, x221 = bits.Mul64(x2, arg2[3]) + var x223 uint64 var x224 uint64 - x224, _ = p521AddcarryxU64(x130, x220, x223) + x224, x223 = bits.Mul64(x2, arg2[2]) + var x225 uint64 var x226 uint64 - var x227 p521Uint1 - x226, x227 = p521AddcarryxU64(x145, x222, 0x0) + x226, x225 = bits.Mul64(x2, arg2[1]) + var x227 uint64 var x228 uint64 - x228, _ = p521AddcarryxU64(x146, x224, x227) + x228, x227 = bits.Mul64(x2, arg2[0]) + var x229 uint64 var x230 uint64 - var x231 p521Uint1 - x230, x231 = p521AddcarryxU64(x77, x1, 0x0) + x229, x230 = bits.Add64(x228, x225, uint64(0x0)) + var x231 uint64 var x232 uint64 - x232, _ = p521AddcarryxU64(x78, x2, x231) + x231, x232 = bits.Add64(x226, x223, uint64(p521Uint1(x230))) + var x233 uint64 var x234 uint64 - var x235 p521Uint1 - x234, x235 = p521AddcarryxU64(x81, x230, 0x0) + x233, x234 = bits.Add64(x224, x221, uint64(p521Uint1(x232))) + var x235 uint64 var x236 uint64 - x236, _ = p521AddcarryxU64(x82, x232, x235) + x235, x236 = bits.Add64(x222, x219, uint64(p521Uint1(x234))) + var x237 uint64 var x238 uint64 - var x239 p521Uint1 - x238, x239 = p521AddcarryxU64(x87, x234, 0x0) + x237, x238 = bits.Add64(x220, x217, uint64(p521Uint1(x236))) + var x239 uint64 var x240 uint64 - x240, _ = p521AddcarryxU64(x88, x236, x239) + x239, x240 = bits.Add64(x218, x215, uint64(p521Uint1(x238))) + var x241 uint64 var x242 uint64 - var x243 p521Uint1 - x242, x243 = p521AddcarryxU64(x95, x238, 0x0) + x241, x242 = bits.Add64(x216, x213, uint64(p521Uint1(x240))) + var x243 uint64 var x244 uint64 - x244, _ = p521AddcarryxU64(x96, x240, x243) + x243, x244 = bits.Add64(x214, x211, uint64(p521Uint1(x242))) + x245 := (uint64(p521Uint1(x244)) + x212) var x246 uint64 - var x247 p521Uint1 - x246, x247 = p521AddcarryxU64(x105, x242, 0x0) + var x247 uint64 + x246, x247 = bits.Add64(x192, x227, uint64(0x0)) var x248 uint64 - x248, _ = p521AddcarryxU64(x106, x244, x247) + var x249 uint64 + x248, x249 = bits.Add64(x194, x229, uint64(p521Uint1(x247))) var x250 uint64 - var x251 p521Uint1 - x250, x251 = p521AddcarryxU64(x117, x246, 0x0) + var x251 uint64 + x250, x251 = bits.Add64(x196, x231, uint64(p521Uint1(x249))) var x252 uint64 - x252, _ = p521AddcarryxU64(x118, x248, x251) + var x253 uint64 + x252, x253 = bits.Add64(x198, x233, uint64(p521Uint1(x251))) var x254 uint64 - var x255 p521Uint1 - x254, x255 = p521AddcarryxU64(x131, x250, 0x0) + var x255 uint64 + x254, x255 = bits.Add64(x200, x235, uint64(p521Uint1(x253))) var x256 uint64 - x256, _ = p521AddcarryxU64(x132, x252, x255) + var x257 uint64 + x256, x257 = bits.Add64(x202, x237, uint64(p521Uint1(x255))) var x258 uint64 - var x259 p521Uint1 - x258, x259 = p521AddcarryxU64(x147, x254, 0x0) + var x259 uint64 + x258, x259 = bits.Add64(x204, x239, uint64(p521Uint1(x257))) var x260 uint64 - x260, _ = p521AddcarryxU64(x148, x256, x259) + var x261 uint64 + x260, x261 = bits.Add64(x206, x241, uint64(p521Uint1(x259))) var x262 uint64 - var x263 p521Uint1 - x262, x263 = p521AddcarryxU64(x17, x3, 0x0) + var x263 uint64 + x262, x263 = bits.Add64(x208, x243, uint64(p521Uint1(x261))) var x264 uint64 - x264, _ = p521AddcarryxU64(x18, x4, x263) + var x265 uint64 + x264, x265 = bits.Add64(x210, x245, uint64(p521Uint1(x263))) var x266 uint64 - var x267 p521Uint1 - x266, x267 = p521AddcarryxU64(x83, x262, 0x0) + var x267 uint64 + x267, x266 = bits.Mul64(x246, 0x1ff) var x268 uint64 - x268, _ = p521AddcarryxU64(x84, x264, x267) + var x269 uint64 + x269, x268 = bits.Mul64(x246, 0xffffffffffffffff) var x270 uint64 - var x271 p521Uint1 - x270, x271 = p521AddcarryxU64(x89, x266, 0x0) + var x271 uint64 + x271, x270 = bits.Mul64(x246, 0xffffffffffffffff) var x272 uint64 - x272, _ = p521AddcarryxU64(x90, x268, x271) + var x273 uint64 + x273, x272 = bits.Mul64(x246, 0xffffffffffffffff) var x274 uint64 - var x275 p521Uint1 - x274, x275 = p521AddcarryxU64(x97, x270, 0x0) + var x275 uint64 + x275, x274 = bits.Mul64(x246, 0xffffffffffffffff) var x276 uint64 - x276, _ = p521AddcarryxU64(x98, x272, x275) + var x277 uint64 + x277, x276 = bits.Mul64(x246, 0xffffffffffffffff) var x278 uint64 - var x279 p521Uint1 - x278, x279 = p521AddcarryxU64(x107, x274, 0x0) + var x279 uint64 + x279, x278 = bits.Mul64(x246, 0xffffffffffffffff) var x280 uint64 - x280, _ = p521AddcarryxU64(x108, x276, x279) + var x281 uint64 + x281, x280 = bits.Mul64(x246, 0xffffffffffffffff) var x282 uint64 - var x283 p521Uint1 - x282, x283 = p521AddcarryxU64(x119, x278, 0x0) + var x283 uint64 + x283, x282 = bits.Mul64(x246, 0xffffffffffffffff) var x284 uint64 - x284, _ = p521AddcarryxU64(x120, x280, x283) + var x285 uint64 + x284, x285 = bits.Add64(x283, x280, uint64(0x0)) var x286 uint64 - var x287 p521Uint1 - x286, x287 = p521AddcarryxU64(x133, x282, 0x0) + var x287 uint64 + x286, x287 = bits.Add64(x281, x278, uint64(p521Uint1(x285))) var x288 uint64 - x288, _ = p521AddcarryxU64(x134, x284, x287) + var x289 uint64 + x288, x289 = bits.Add64(x279, x276, uint64(p521Uint1(x287))) var x290 uint64 - var x291 p521Uint1 - x290, x291 = p521AddcarryxU64(x149, x286, 0x0) + var x291 uint64 + x290, x291 = bits.Add64(x277, x274, uint64(p521Uint1(x289))) var x292 uint64 - x292, _ = p521AddcarryxU64(x150, x288, x291) + var x293 uint64 + x292, x293 = bits.Add64(x275, x272, uint64(p521Uint1(x291))) var x294 uint64 - var x295 p521Uint1 - x294, x295 = p521AddcarryxU64(x19, x5, 0x0) + var x295 uint64 + x294, x295 = bits.Add64(x273, x270, uint64(p521Uint1(x293))) var x296 uint64 - x296, _ = p521AddcarryxU64(x20, x6, x295) + var x297 uint64 + x296, x297 = bits.Add64(x271, x268, uint64(p521Uint1(x295))) var x298 uint64 - var x299 p521Uint1 - x298, x299 = p521AddcarryxU64(x31, x294, 0x0) - var x300 uint64 - x300, _ = p521AddcarryxU64(x32, x296, x299) + var x299 uint64 + x298, x299 = bits.Add64(x269, x266, uint64(p521Uint1(x297))) + x300 := (uint64(p521Uint1(x299)) + x267) var x302 uint64 - var x303 p521Uint1 - x302, x303 = p521AddcarryxU64(x91, x298, 0x0) + _, x302 = bits.Add64(x246, x282, uint64(0x0)) + var x303 uint64 var x304 uint64 - x304, _ = p521AddcarryxU64(x92, x300, x303) + x303, x304 = bits.Add64(x248, x284, uint64(p521Uint1(x302))) + var x305 uint64 var x306 uint64 - var x307 p521Uint1 - x306, x307 = p521AddcarryxU64(x99, x302, 0x0) + x305, x306 = bits.Add64(x250, x286, uint64(p521Uint1(x304))) + var x307 uint64 var x308 uint64 - x308, _ = p521AddcarryxU64(x100, x304, x307) + x307, x308 = bits.Add64(x252, x288, uint64(p521Uint1(x306))) + var x309 uint64 var x310 uint64 - var x311 p521Uint1 - x310, x311 = p521AddcarryxU64(x109, x306, 0x0) + x309, x310 = bits.Add64(x254, x290, uint64(p521Uint1(x308))) + var x311 uint64 var x312 uint64 - x312, _ = p521AddcarryxU64(x110, x308, x311) + x311, x312 = bits.Add64(x256, x292, uint64(p521Uint1(x310))) + var x313 uint64 var x314 uint64 - var x315 p521Uint1 - x314, x315 = p521AddcarryxU64(x121, x310, 0x0) + x313, x314 = bits.Add64(x258, x294, uint64(p521Uint1(x312))) + var x315 uint64 var x316 uint64 - x316, _ = p521AddcarryxU64(x122, x312, x315) + x315, x316 = bits.Add64(x260, x296, uint64(p521Uint1(x314))) + var x317 uint64 var x318 uint64 - var x319 p521Uint1 - x318, x319 = p521AddcarryxU64(x135, x314, 0x0) + x317, x318 = bits.Add64(x262, x298, uint64(p521Uint1(x316))) + var x319 uint64 var x320 uint64 - x320, _ = p521AddcarryxU64(x136, x316, x319) + x319, x320 = bits.Add64(x264, x300, uint64(p521Uint1(x318))) + x321 := (uint64(p521Uint1(x320)) + uint64(p521Uint1(x265))) var x322 uint64 - var x323 p521Uint1 - x322, x323 = p521AddcarryxU64(x151, x318, 0x0) + var x323 uint64 + x323, x322 = bits.Mul64(x3, arg2[8]) var x324 uint64 - x324, _ = p521AddcarryxU64(x152, x320, x323) + var x325 uint64 + x325, x324 = bits.Mul64(x3, arg2[7]) var x326 uint64 - var x327 p521Uint1 - x326, x327 = p521AddcarryxU64(x21, x7, 0x0) + var x327 uint64 + x327, x326 = bits.Mul64(x3, arg2[6]) var x328 uint64 - x328, _ = p521AddcarryxU64(x22, x8, x327) + var x329 uint64 + x329, x328 = bits.Mul64(x3, arg2[5]) var x330 uint64 - var x331 p521Uint1 - x330, x331 = p521AddcarryxU64(x33, x326, 0x0) + var x331 uint64 + x331, x330 = bits.Mul64(x3, arg2[4]) var x332 uint64 - x332, _ = p521AddcarryxU64(x34, x328, x331) + var x333 uint64 + x333, x332 = bits.Mul64(x3, arg2[3]) var x334 uint64 - var x335 p521Uint1 - x334, x335 = p521AddcarryxU64(x43, x330, 0x0) + var x335 uint64 + x335, x334 = bits.Mul64(x3, arg2[2]) var x336 uint64 - x336, _ = p521AddcarryxU64(x44, x332, x335) + var x337 uint64 + x337, x336 = bits.Mul64(x3, arg2[1]) var x338 uint64 - var x339 p521Uint1 - x338, x339 = p521AddcarryxU64(x101, x334, 0x0) + var x339 uint64 + x339, x338 = bits.Mul64(x3, arg2[0]) var x340 uint64 - x340, _ = p521AddcarryxU64(x102, x336, x339) + var x341 uint64 + x340, x341 = bits.Add64(x339, x336, uint64(0x0)) var x342 uint64 - var x343 p521Uint1 - x342, x343 = p521AddcarryxU64(x111, x338, 0x0) + var x343 uint64 + x342, x343 = bits.Add64(x337, x334, uint64(p521Uint1(x341))) var x344 uint64 - x344, _ = p521AddcarryxU64(x112, x340, x343) + var x345 uint64 + x344, x345 = bits.Add64(x335, x332, uint64(p521Uint1(x343))) var x346 uint64 - var x347 p521Uint1 - x346, x347 = p521AddcarryxU64(x123, x342, 0x0) + var x347 uint64 + x346, x347 = bits.Add64(x333, x330, uint64(p521Uint1(x345))) var x348 uint64 - x348, _ = p521AddcarryxU64(x124, x344, x347) + var x349 uint64 + x348, x349 = bits.Add64(x331, x328, uint64(p521Uint1(x347))) var x350 uint64 - var x351 p521Uint1 - x350, x351 = p521AddcarryxU64(x137, x346, 0x0) + var x351 uint64 + x350, x351 = bits.Add64(x329, x326, uint64(p521Uint1(x349))) var x352 uint64 - x352, _ = p521AddcarryxU64(x138, x348, x351) + var x353 uint64 + x352, x353 = bits.Add64(x327, x324, uint64(p521Uint1(x351))) var x354 uint64 - var x355 p521Uint1 - x354, x355 = p521AddcarryxU64(x153, x350, 0x0) - var x356 uint64 - x356, _ = p521AddcarryxU64(x154, x352, x355) + var x355 uint64 + x354, x355 = bits.Add64(x325, x322, uint64(p521Uint1(x353))) + x356 := (uint64(p521Uint1(x355)) + x323) + var x357 uint64 var x358 uint64 - var x359 p521Uint1 - x358, x359 = p521AddcarryxU64(x23, x9, 0x0) + x357, x358 = bits.Add64(x303, x338, uint64(0x0)) + var x359 uint64 var x360 uint64 - x360, _ = p521AddcarryxU64(x24, x10, x359) + x359, x360 = bits.Add64(x305, x340, uint64(p521Uint1(x358))) + var x361 uint64 var x362 uint64 - var x363 p521Uint1 - x362, x363 = p521AddcarryxU64(x35, x358, 0x0) + x361, x362 = bits.Add64(x307, x342, uint64(p521Uint1(x360))) + var x363 uint64 var x364 uint64 - x364, _ = p521AddcarryxU64(x36, x360, x363) + x363, x364 = bits.Add64(x309, x344, uint64(p521Uint1(x362))) + var x365 uint64 var x366 uint64 - var x367 p521Uint1 - x366, x367 = p521AddcarryxU64(x45, x362, 0x0) + x365, x366 = bits.Add64(x311, x346, uint64(p521Uint1(x364))) + var x367 uint64 var x368 uint64 - x368, _ = p521AddcarryxU64(x46, x364, x367) + x367, x368 = bits.Add64(x313, x348, uint64(p521Uint1(x366))) + var x369 uint64 var x370 uint64 - var x371 p521Uint1 - x370, x371 = p521AddcarryxU64(x53, x366, 0x0) + x369, x370 = bits.Add64(x315, x350, uint64(p521Uint1(x368))) + var x371 uint64 var x372 uint64 - x372, _ = p521AddcarryxU64(x54, x368, x371) + x371, x372 = bits.Add64(x317, x352, uint64(p521Uint1(x370))) + var x373 uint64 var x374 uint64 - var x375 p521Uint1 - x374, x375 = p521AddcarryxU64(x113, x370, 0x0) + x373, x374 = bits.Add64(x319, x354, uint64(p521Uint1(x372))) + var x375 uint64 var x376 uint64 - x376, _ = p521AddcarryxU64(x114, x372, x375) + x375, x376 = bits.Add64(x321, x356, uint64(p521Uint1(x374))) + var x377 uint64 var x378 uint64 - var x379 p521Uint1 - x378, x379 = p521AddcarryxU64(x125, x374, 0x0) + x378, x377 = bits.Mul64(x357, 0x1ff) + var x379 uint64 var x380 uint64 - x380, _ = p521AddcarryxU64(x126, x376, x379) + x380, x379 = bits.Mul64(x357, 0xffffffffffffffff) + var x381 uint64 var x382 uint64 - var x383 p521Uint1 - x382, x383 = p521AddcarryxU64(x139, x378, 0x0) + x382, x381 = bits.Mul64(x357, 0xffffffffffffffff) + var x383 uint64 var x384 uint64 - x384, _ = p521AddcarryxU64(x140, x380, x383) + x384, x383 = bits.Mul64(x357, 0xffffffffffffffff) + var x385 uint64 var x386 uint64 - var x387 p521Uint1 - x386, x387 = p521AddcarryxU64(x155, x382, 0x0) + x386, x385 = bits.Mul64(x357, 0xffffffffffffffff) + var x387 uint64 var x388 uint64 - x388, _ = p521AddcarryxU64(x156, x384, x387) + x388, x387 = bits.Mul64(x357, 0xffffffffffffffff) + var x389 uint64 var x390 uint64 - var x391 p521Uint1 - x390, x391 = p521AddcarryxU64(x25, x11, 0x0) + x390, x389 = bits.Mul64(x357, 0xffffffffffffffff) + var x391 uint64 var x392 uint64 - x392, _ = p521AddcarryxU64(x26, x12, x391) + x392, x391 = bits.Mul64(x357, 0xffffffffffffffff) + var x393 uint64 var x394 uint64 - var x395 p521Uint1 - x394, x395 = p521AddcarryxU64(x37, x390, 0x0) + x394, x393 = bits.Mul64(x357, 0xffffffffffffffff) + var x395 uint64 var x396 uint64 - x396, _ = p521AddcarryxU64(x38, x392, x395) + x395, x396 = bits.Add64(x394, x391, uint64(0x0)) + var x397 uint64 var x398 uint64 - var x399 p521Uint1 - x398, x399 = p521AddcarryxU64(x47, x394, 0x0) + x397, x398 = bits.Add64(x392, x389, uint64(p521Uint1(x396))) + var x399 uint64 var x400 uint64 - x400, _ = p521AddcarryxU64(x48, x396, x399) + x399, x400 = bits.Add64(x390, x387, uint64(p521Uint1(x398))) + var x401 uint64 var x402 uint64 - var x403 p521Uint1 - x402, x403 = p521AddcarryxU64(x55, x398, 0x0) + x401, x402 = bits.Add64(x388, x385, uint64(p521Uint1(x400))) + var x403 uint64 var x404 uint64 - x404, _ = p521AddcarryxU64(x56, x400, x403) + x403, x404 = bits.Add64(x386, x383, uint64(p521Uint1(x402))) + var x405 uint64 var x406 uint64 - var x407 p521Uint1 - x406, x407 = p521AddcarryxU64(x61, x402, 0x0) + x405, x406 = bits.Add64(x384, x381, uint64(p521Uint1(x404))) + var x407 uint64 var x408 uint64 - x408, _ = p521AddcarryxU64(x62, x404, x407) + x407, x408 = bits.Add64(x382, x379, uint64(p521Uint1(x406))) + var x409 uint64 var x410 uint64 - var x411 p521Uint1 - x410, x411 = p521AddcarryxU64(x127, x406, 0x0) - var x412 uint64 - x412, _ = p521AddcarryxU64(x128, x408, x411) + x409, x410 = bits.Add64(x380, x377, uint64(p521Uint1(x408))) + x411 := (uint64(p521Uint1(x410)) + x378) + var x413 uint64 + _, x413 = bits.Add64(x357, x393, uint64(0x0)) var x414 uint64 - var x415 p521Uint1 - x414, x415 = p521AddcarryxU64(x141, x410, 0x0) + var x415 uint64 + x414, x415 = bits.Add64(x359, x395, uint64(p521Uint1(x413))) var x416 uint64 - x416, _ = p521AddcarryxU64(x142, x412, x415) + var x417 uint64 + x416, x417 = bits.Add64(x361, x397, uint64(p521Uint1(x415))) var x418 uint64 - var x419 p521Uint1 - x418, x419 = p521AddcarryxU64(x157, x414, 0x0) + var x419 uint64 + x418, x419 = bits.Add64(x363, x399, uint64(p521Uint1(x417))) var x420 uint64 - x420, _ = p521AddcarryxU64(x158, x416, x419) + var x421 uint64 + x420, x421 = bits.Add64(x365, x401, uint64(p521Uint1(x419))) var x422 uint64 - var x423 p521Uint1 - x422, x423 = p521AddcarryxU64(x27, x13, 0x0) + var x423 uint64 + x422, x423 = bits.Add64(x367, x403, uint64(p521Uint1(x421))) var x424 uint64 - x424, _ = p521AddcarryxU64(x28, x14, x423) + var x425 uint64 + x424, x425 = bits.Add64(x369, x405, uint64(p521Uint1(x423))) var x426 uint64 - var x427 p521Uint1 - x426, x427 = p521AddcarryxU64(x39, x422, 0x0) + var x427 uint64 + x426, x427 = bits.Add64(x371, x407, uint64(p521Uint1(x425))) var x428 uint64 - x428, _ = p521AddcarryxU64(x40, x424, x427) + var x429 uint64 + x428, x429 = bits.Add64(x373, x409, uint64(p521Uint1(x427))) var x430 uint64 - var x431 p521Uint1 - x430, x431 = p521AddcarryxU64(x49, x426, 0x0) - var x432 uint64 - x432, _ = p521AddcarryxU64(x50, x428, x431) + var x431 uint64 + x430, x431 = bits.Add64(x375, x411, uint64(p521Uint1(x429))) + x432 := (uint64(p521Uint1(x431)) + uint64(p521Uint1(x376))) + var x433 uint64 var x434 uint64 - var x435 p521Uint1 - x434, x435 = p521AddcarryxU64(x57, x430, 0x0) + x434, x433 = bits.Mul64(x4, arg2[8]) + var x435 uint64 var x436 uint64 - x436, _ = p521AddcarryxU64(x58, x432, x435) + x436, x435 = bits.Mul64(x4, arg2[7]) + var x437 uint64 var x438 uint64 - var x439 p521Uint1 - x438, x439 = p521AddcarryxU64(x63, x434, 0x0) + x438, x437 = bits.Mul64(x4, arg2[6]) + var x439 uint64 var x440 uint64 - x440, _ = p521AddcarryxU64(x64, x436, x439) + x440, x439 = bits.Mul64(x4, arg2[5]) + var x441 uint64 var x442 uint64 - var x443 p521Uint1 - x442, x443 = p521AddcarryxU64(x67, x438, 0x0) + x442, x441 = bits.Mul64(x4, arg2[4]) + var x443 uint64 var x444 uint64 - x444, _ = p521AddcarryxU64(x68, x440, x443) + x444, x443 = bits.Mul64(x4, arg2[3]) + var x445 uint64 var x446 uint64 - var x447 p521Uint1 - x446, x447 = p521AddcarryxU64(x143, x442, 0x0) + x446, x445 = bits.Mul64(x4, arg2[2]) + var x447 uint64 var x448 uint64 - x448, _ = p521AddcarryxU64(x144, x444, x447) + x448, x447 = bits.Mul64(x4, arg2[1]) + var x449 uint64 var x450 uint64 - var x451 p521Uint1 - x450, x451 = p521AddcarryxU64(x159, x446, 0x0) + x450, x449 = bits.Mul64(x4, arg2[0]) + var x451 uint64 var x452 uint64 - x452, _ = p521AddcarryxU64(x160, x448, x451) + x451, x452 = bits.Add64(x450, x447, uint64(0x0)) + var x453 uint64 var x454 uint64 - var x455 p521Uint1 - x454, x455 = p521AddcarryxU64(x195, x450, 0x0) + x453, x454 = bits.Add64(x448, x445, uint64(p521Uint1(x452))) + var x455 uint64 var x456 uint64 - x456, _ = p521AddcarryxU64(x196, x452, x455) - x458 := ((x454 >> 58) | ((x456 << 6) & 0xffffffffffffffff)) - x459 := (x456 >> 58) - x460 := (x454 & 0x3ffffffffffffff) + x455, x456 = bits.Add64(x446, x443, uint64(p521Uint1(x454))) + var x457 uint64 + var x458 uint64 + x457, x458 = bits.Add64(x444, x441, uint64(p521Uint1(x456))) + var x459 uint64 + var x460 uint64 + x459, x460 = bits.Add64(x442, x439, uint64(p521Uint1(x458))) var x461 uint64 - var x462 p521Uint1 - x461, x462 = p521AddcarryxU64(x458, x418, 0x0) + var x462 uint64 + x461, x462 = bits.Add64(x440, x437, uint64(p521Uint1(x460))) var x463 uint64 - x463, _ = p521AddcarryxU64(x459, x420, x462) - x465 := ((x461 >> 58) | ((x463 << 6) & 0xffffffffffffffff)) - x466 := (x463 >> 58) - x467 := (x461 & 0x3ffffffffffffff) + var x464 uint64 + x463, x464 = bits.Add64(x438, x435, uint64(p521Uint1(x462))) + var x465 uint64 + var x466 uint64 + x465, x466 = bits.Add64(x436, x433, uint64(p521Uint1(x464))) + x467 := (uint64(p521Uint1(x466)) + x434) var x468 uint64 - var x469 p521Uint1 - x468, x469 = p521AddcarryxU64(x465, x386, 0x0) + var x469 uint64 + x468, x469 = bits.Add64(x414, x449, uint64(0x0)) var x470 uint64 - x470, _ = p521AddcarryxU64(x466, x388, x469) - x472 := ((x468 >> 58) | ((x470 << 6) & 0xffffffffffffffff)) - x473 := (x470 >> 58) - x474 := (x468 & 0x3ffffffffffffff) + var x471 uint64 + x470, x471 = bits.Add64(x416, x451, uint64(p521Uint1(x469))) + var x472 uint64 + var x473 uint64 + x472, x473 = bits.Add64(x418, x453, uint64(p521Uint1(x471))) + var x474 uint64 var x475 uint64 - var x476 p521Uint1 - x475, x476 = p521AddcarryxU64(x472, x354, 0x0) + x474, x475 = bits.Add64(x420, x455, uint64(p521Uint1(x473))) + var x476 uint64 var x477 uint64 - x477, _ = p521AddcarryxU64(x473, x356, x476) - x479 := ((x475 >> 58) | ((x477 << 6) & 0xffffffffffffffff)) - x480 := (x477 >> 58) - x481 := (x475 & 0x3ffffffffffffff) + x476, x477 = bits.Add64(x422, x457, uint64(p521Uint1(x475))) + var x478 uint64 + var x479 uint64 + x478, x479 = bits.Add64(x424, x459, uint64(p521Uint1(x477))) + var x480 uint64 + var x481 uint64 + x480, x481 = bits.Add64(x426, x461, uint64(p521Uint1(x479))) var x482 uint64 - var x483 p521Uint1 - x482, x483 = p521AddcarryxU64(x479, x322, 0x0) + var x483 uint64 + x482, x483 = bits.Add64(x428, x463, uint64(p521Uint1(x481))) var x484 uint64 - x484, _ = p521AddcarryxU64(x480, x324, x483) - x486 := ((x482 >> 58) | ((x484 << 6) & 0xffffffffffffffff)) - x487 := (x484 >> 58) - x488 := (x482 & 0x3ffffffffffffff) + var x485 uint64 + x484, x485 = bits.Add64(x430, x465, uint64(p521Uint1(x483))) + var x486 uint64 + var x487 uint64 + x486, x487 = bits.Add64(x432, x467, uint64(p521Uint1(x485))) + var x488 uint64 var x489 uint64 - var x490 p521Uint1 - x489, x490 = p521AddcarryxU64(x486, x290, 0x0) + x489, x488 = bits.Mul64(x468, 0x1ff) + var x490 uint64 var x491 uint64 - x491, _ = p521AddcarryxU64(x487, x292, x490) - x493 := ((x489 >> 58) | ((x491 << 6) & 0xffffffffffffffff)) - x494 := (x491 >> 58) - x495 := (x489 & 0x3ffffffffffffff) + x491, x490 = bits.Mul64(x468, 0xffffffffffffffff) + var x492 uint64 + var x493 uint64 + x493, x492 = bits.Mul64(x468, 0xffffffffffffffff) + var x494 uint64 + var x495 uint64 + x495, x494 = bits.Mul64(x468, 0xffffffffffffffff) var x496 uint64 - var x497 p521Uint1 - x496, x497 = p521AddcarryxU64(x493, x258, 0x0) + var x497 uint64 + x497, x496 = bits.Mul64(x468, 0xffffffffffffffff) var x498 uint64 - x498, _ = p521AddcarryxU64(x494, x260, x497) - x500 := ((x496 >> 58) | ((x498 << 6) & 0xffffffffffffffff)) - x501 := (x498 >> 58) - x502 := (x496 & 0x3ffffffffffffff) + var x499 uint64 + x499, x498 = bits.Mul64(x468, 0xffffffffffffffff) + var x500 uint64 + var x501 uint64 + x501, x500 = bits.Mul64(x468, 0xffffffffffffffff) + var x502 uint64 var x503 uint64 - var x504 p521Uint1 - x503, x504 = p521AddcarryxU64(x500, x226, 0x0) + x503, x502 = bits.Mul64(x468, 0xffffffffffffffff) + var x504 uint64 var x505 uint64 - x505, _ = p521AddcarryxU64(x501, x228, x504) - x507 := ((x503 >> 57) | ((x505 << 7) & 0xffffffffffffffff)) - x508 := (x505 >> 57) - x509 := (x503 & 0x1ffffffffffffff) + x505, x504 = bits.Mul64(x468, 0xffffffffffffffff) + var x506 uint64 + var x507 uint64 + x506, x507 = bits.Add64(x505, x502, uint64(0x0)) + var x508 uint64 + var x509 uint64 + x508, x509 = bits.Add64(x503, x500, uint64(p521Uint1(x507))) var x510 uint64 - var x511 p521Uint1 - x510, x511 = p521AddcarryxU64(x197, x507, 0x0) - x512 := (uint64(x511) + x508) - x513 := ((x510 >> 58) | ((x512 << 6) & 0xffffffffffffffff)) - x514 := (x510 & 0x3ffffffffffffff) - x515 := (x513 + x460) - x516 := p521Uint1((x515 >> 58)) - x517 := (x515 & 0x3ffffffffffffff) - x518 := (uint64(x516) + x467) - out1[0] = x514 - out1[1] = x517 - out1[2] = x518 - out1[3] = x474 - out1[4] = x481 - out1[5] = x488 - out1[6] = x495 - out1[7] = x502 - out1[8] = x509 + var x511 uint64 + x510, x511 = bits.Add64(x501, x498, uint64(p521Uint1(x509))) + var x512 uint64 + var x513 uint64 + x512, x513 = bits.Add64(x499, x496, uint64(p521Uint1(x511))) + var x514 uint64 + var x515 uint64 + x514, x515 = bits.Add64(x497, x494, uint64(p521Uint1(x513))) + var x516 uint64 + var x517 uint64 + x516, x517 = bits.Add64(x495, x492, uint64(p521Uint1(x515))) + var x518 uint64 + var x519 uint64 + x518, x519 = bits.Add64(x493, x490, uint64(p521Uint1(x517))) + var x520 uint64 + var x521 uint64 + x520, x521 = bits.Add64(x491, x488, uint64(p521Uint1(x519))) + x522 := (uint64(p521Uint1(x521)) + x489) + var x524 uint64 + _, x524 = bits.Add64(x468, x504, uint64(0x0)) + var x525 uint64 + var x526 uint64 + x525, x526 = bits.Add64(x470, x506, uint64(p521Uint1(x524))) + var x527 uint64 + var x528 uint64 + x527, x528 = bits.Add64(x472, x508, uint64(p521Uint1(x526))) + var x529 uint64 + var x530 uint64 + x529, x530 = bits.Add64(x474, x510, uint64(p521Uint1(x528))) + var x531 uint64 + var x532 uint64 + x531, x532 = bits.Add64(x476, x512, uint64(p521Uint1(x530))) + var x533 uint64 + var x534 uint64 + x533, x534 = bits.Add64(x478, x514, uint64(p521Uint1(x532))) + var x535 uint64 + var x536 uint64 + x535, x536 = bits.Add64(x480, x516, uint64(p521Uint1(x534))) + var x537 uint64 + var x538 uint64 + x537, x538 = bits.Add64(x482, x518, uint64(p521Uint1(x536))) + var x539 uint64 + var x540 uint64 + x539, x540 = bits.Add64(x484, x520, uint64(p521Uint1(x538))) + var x541 uint64 + var x542 uint64 + x541, x542 = bits.Add64(x486, x522, uint64(p521Uint1(x540))) + x543 := (uint64(p521Uint1(x542)) + uint64(p521Uint1(x487))) + var x544 uint64 + var x545 uint64 + x545, x544 = bits.Mul64(x5, arg2[8]) + var x546 uint64 + var x547 uint64 + x547, x546 = bits.Mul64(x5, arg2[7]) + var x548 uint64 + var x549 uint64 + x549, x548 = bits.Mul64(x5, arg2[6]) + var x550 uint64 + var x551 uint64 + x551, x550 = bits.Mul64(x5, arg2[5]) + var x552 uint64 + var x553 uint64 + x553, x552 = bits.Mul64(x5, arg2[4]) + var x554 uint64 + var x555 uint64 + x555, x554 = bits.Mul64(x5, arg2[3]) + var x556 uint64 + var x557 uint64 + x557, x556 = bits.Mul64(x5, arg2[2]) + var x558 uint64 + var x559 uint64 + x559, x558 = bits.Mul64(x5, arg2[1]) + var x560 uint64 + var x561 uint64 + x561, x560 = bits.Mul64(x5, arg2[0]) + var x562 uint64 + var x563 uint64 + x562, x563 = bits.Add64(x561, x558, uint64(0x0)) + var x564 uint64 + var x565 uint64 + x564, x565 = bits.Add64(x559, x556, uint64(p521Uint1(x563))) + var x566 uint64 + var x567 uint64 + x566, x567 = bits.Add64(x557, x554, uint64(p521Uint1(x565))) + var x568 uint64 + var x569 uint64 + x568, x569 = bits.Add64(x555, x552, uint64(p521Uint1(x567))) + var x570 uint64 + var x571 uint64 + x570, x571 = bits.Add64(x553, x550, uint64(p521Uint1(x569))) + var x572 uint64 + var x573 uint64 + x572, x573 = bits.Add64(x551, x548, uint64(p521Uint1(x571))) + var x574 uint64 + var x575 uint64 + x574, x575 = bits.Add64(x549, x546, uint64(p521Uint1(x573))) + var x576 uint64 + var x577 uint64 + x576, x577 = bits.Add64(x547, x544, uint64(p521Uint1(x575))) + x578 := (uint64(p521Uint1(x577)) + x545) + var x579 uint64 + var x580 uint64 + x579, x580 = bits.Add64(x525, x560, uint64(0x0)) + var x581 uint64 + var x582 uint64 + x581, x582 = bits.Add64(x527, x562, uint64(p521Uint1(x580))) + var x583 uint64 + var x584 uint64 + x583, x584 = bits.Add64(x529, x564, uint64(p521Uint1(x582))) + var x585 uint64 + var x586 uint64 + x585, x586 = bits.Add64(x531, x566, uint64(p521Uint1(x584))) + var x587 uint64 + var x588 uint64 + x587, x588 = bits.Add64(x533, x568, uint64(p521Uint1(x586))) + var x589 uint64 + var x590 uint64 + x589, x590 = bits.Add64(x535, x570, uint64(p521Uint1(x588))) + var x591 uint64 + var x592 uint64 + x591, x592 = bits.Add64(x537, x572, uint64(p521Uint1(x590))) + var x593 uint64 + var x594 uint64 + x593, x594 = bits.Add64(x539, x574, uint64(p521Uint1(x592))) + var x595 uint64 + var x596 uint64 + x595, x596 = bits.Add64(x541, x576, uint64(p521Uint1(x594))) + var x597 uint64 + var x598 uint64 + x597, x598 = bits.Add64(x543, x578, uint64(p521Uint1(x596))) + var x599 uint64 + var x600 uint64 + x600, x599 = bits.Mul64(x579, 0x1ff) + var x601 uint64 + var x602 uint64 + x602, x601 = bits.Mul64(x579, 0xffffffffffffffff) + var x603 uint64 + var x604 uint64 + x604, x603 = bits.Mul64(x579, 0xffffffffffffffff) + var x605 uint64 + var x606 uint64 + x606, x605 = bits.Mul64(x579, 0xffffffffffffffff) + var x607 uint64 + var x608 uint64 + x608, x607 = bits.Mul64(x579, 0xffffffffffffffff) + var x609 uint64 + var x610 uint64 + x610, x609 = bits.Mul64(x579, 0xffffffffffffffff) + var x611 uint64 + var x612 uint64 + x612, x611 = bits.Mul64(x579, 0xffffffffffffffff) + var x613 uint64 + var x614 uint64 + x614, x613 = bits.Mul64(x579, 0xffffffffffffffff) + var x615 uint64 + var x616 uint64 + x616, x615 = bits.Mul64(x579, 0xffffffffffffffff) + var x617 uint64 + var x618 uint64 + x617, x618 = bits.Add64(x616, x613, uint64(0x0)) + var x619 uint64 + var x620 uint64 + x619, x620 = bits.Add64(x614, x611, uint64(p521Uint1(x618))) + var x621 uint64 + var x622 uint64 + x621, x622 = bits.Add64(x612, x609, uint64(p521Uint1(x620))) + var x623 uint64 + var x624 uint64 + x623, x624 = bits.Add64(x610, x607, uint64(p521Uint1(x622))) + var x625 uint64 + var x626 uint64 + x625, x626 = bits.Add64(x608, x605, uint64(p521Uint1(x624))) + var x627 uint64 + var x628 uint64 + x627, x628 = bits.Add64(x606, x603, uint64(p521Uint1(x626))) + var x629 uint64 + var x630 uint64 + x629, x630 = bits.Add64(x604, x601, uint64(p521Uint1(x628))) + var x631 uint64 + var x632 uint64 + x631, x632 = bits.Add64(x602, x599, uint64(p521Uint1(x630))) + x633 := (uint64(p521Uint1(x632)) + x600) + var x635 uint64 + _, x635 = bits.Add64(x579, x615, uint64(0x0)) + var x636 uint64 + var x637 uint64 + x636, x637 = bits.Add64(x581, x617, uint64(p521Uint1(x635))) + var x638 uint64 + var x639 uint64 + x638, x639 = bits.Add64(x583, x619, uint64(p521Uint1(x637))) + var x640 uint64 + var x641 uint64 + x640, x641 = bits.Add64(x585, x621, uint64(p521Uint1(x639))) + var x642 uint64 + var x643 uint64 + x642, x643 = bits.Add64(x587, x623, uint64(p521Uint1(x641))) + var x644 uint64 + var x645 uint64 + x644, x645 = bits.Add64(x589, x625, uint64(p521Uint1(x643))) + var x646 uint64 + var x647 uint64 + x646, x647 = bits.Add64(x591, x627, uint64(p521Uint1(x645))) + var x648 uint64 + var x649 uint64 + x648, x649 = bits.Add64(x593, x629, uint64(p521Uint1(x647))) + var x650 uint64 + var x651 uint64 + x650, x651 = bits.Add64(x595, x631, uint64(p521Uint1(x649))) + var x652 uint64 + var x653 uint64 + x652, x653 = bits.Add64(x597, x633, uint64(p521Uint1(x651))) + x654 := (uint64(p521Uint1(x653)) + uint64(p521Uint1(x598))) + var x655 uint64 + var x656 uint64 + x656, x655 = bits.Mul64(x6, arg2[8]) + var x657 uint64 + var x658 uint64 + x658, x657 = bits.Mul64(x6, arg2[7]) + var x659 uint64 + var x660 uint64 + x660, x659 = bits.Mul64(x6, arg2[6]) + var x661 uint64 + var x662 uint64 + x662, x661 = bits.Mul64(x6, arg2[5]) + var x663 uint64 + var x664 uint64 + x664, x663 = bits.Mul64(x6, arg2[4]) + var x665 uint64 + var x666 uint64 + x666, x665 = bits.Mul64(x6, arg2[3]) + var x667 uint64 + var x668 uint64 + x668, x667 = bits.Mul64(x6, arg2[2]) + var x669 uint64 + var x670 uint64 + x670, x669 = bits.Mul64(x6, arg2[1]) + var x671 uint64 + var x672 uint64 + x672, x671 = bits.Mul64(x6, arg2[0]) + var x673 uint64 + var x674 uint64 + x673, x674 = bits.Add64(x672, x669, uint64(0x0)) + var x675 uint64 + var x676 uint64 + x675, x676 = bits.Add64(x670, x667, uint64(p521Uint1(x674))) + var x677 uint64 + var x678 uint64 + x677, x678 = bits.Add64(x668, x665, uint64(p521Uint1(x676))) + var x679 uint64 + var x680 uint64 + x679, x680 = bits.Add64(x666, x663, uint64(p521Uint1(x678))) + var x681 uint64 + var x682 uint64 + x681, x682 = bits.Add64(x664, x661, uint64(p521Uint1(x680))) + var x683 uint64 + var x684 uint64 + x683, x684 = bits.Add64(x662, x659, uint64(p521Uint1(x682))) + var x685 uint64 + var x686 uint64 + x685, x686 = bits.Add64(x660, x657, uint64(p521Uint1(x684))) + var x687 uint64 + var x688 uint64 + x687, x688 = bits.Add64(x658, x655, uint64(p521Uint1(x686))) + x689 := (uint64(p521Uint1(x688)) + x656) + var x690 uint64 + var x691 uint64 + x690, x691 = bits.Add64(x636, x671, uint64(0x0)) + var x692 uint64 + var x693 uint64 + x692, x693 = bits.Add64(x638, x673, uint64(p521Uint1(x691))) + var x694 uint64 + var x695 uint64 + x694, x695 = bits.Add64(x640, x675, uint64(p521Uint1(x693))) + var x696 uint64 + var x697 uint64 + x696, x697 = bits.Add64(x642, x677, uint64(p521Uint1(x695))) + var x698 uint64 + var x699 uint64 + x698, x699 = bits.Add64(x644, x679, uint64(p521Uint1(x697))) + var x700 uint64 + var x701 uint64 + x700, x701 = bits.Add64(x646, x681, uint64(p521Uint1(x699))) + var x702 uint64 + var x703 uint64 + x702, x703 = bits.Add64(x648, x683, uint64(p521Uint1(x701))) + var x704 uint64 + var x705 uint64 + x704, x705 = bits.Add64(x650, x685, uint64(p521Uint1(x703))) + var x706 uint64 + var x707 uint64 + x706, x707 = bits.Add64(x652, x687, uint64(p521Uint1(x705))) + var x708 uint64 + var x709 uint64 + x708, x709 = bits.Add64(x654, x689, uint64(p521Uint1(x707))) + var x710 uint64 + var x711 uint64 + x711, x710 = bits.Mul64(x690, 0x1ff) + var x712 uint64 + var x713 uint64 + x713, x712 = bits.Mul64(x690, 0xffffffffffffffff) + var x714 uint64 + var x715 uint64 + x715, x714 = bits.Mul64(x690, 0xffffffffffffffff) + var x716 uint64 + var x717 uint64 + x717, x716 = bits.Mul64(x690, 0xffffffffffffffff) + var x718 uint64 + var x719 uint64 + x719, x718 = bits.Mul64(x690, 0xffffffffffffffff) + var x720 uint64 + var x721 uint64 + x721, x720 = bits.Mul64(x690, 0xffffffffffffffff) + var x722 uint64 + var x723 uint64 + x723, x722 = bits.Mul64(x690, 0xffffffffffffffff) + var x724 uint64 + var x725 uint64 + x725, x724 = bits.Mul64(x690, 0xffffffffffffffff) + var x726 uint64 + var x727 uint64 + x727, x726 = bits.Mul64(x690, 0xffffffffffffffff) + var x728 uint64 + var x729 uint64 + x728, x729 = bits.Add64(x727, x724, uint64(0x0)) + var x730 uint64 + var x731 uint64 + x730, x731 = bits.Add64(x725, x722, uint64(p521Uint1(x729))) + var x732 uint64 + var x733 uint64 + x732, x733 = bits.Add64(x723, x720, uint64(p521Uint1(x731))) + var x734 uint64 + var x735 uint64 + x734, x735 = bits.Add64(x721, x718, uint64(p521Uint1(x733))) + var x736 uint64 + var x737 uint64 + x736, x737 = bits.Add64(x719, x716, uint64(p521Uint1(x735))) + var x738 uint64 + var x739 uint64 + x738, x739 = bits.Add64(x717, x714, uint64(p521Uint1(x737))) + var x740 uint64 + var x741 uint64 + x740, x741 = bits.Add64(x715, x712, uint64(p521Uint1(x739))) + var x742 uint64 + var x743 uint64 + x742, x743 = bits.Add64(x713, x710, uint64(p521Uint1(x741))) + x744 := (uint64(p521Uint1(x743)) + x711) + var x746 uint64 + _, x746 = bits.Add64(x690, x726, uint64(0x0)) + var x747 uint64 + var x748 uint64 + x747, x748 = bits.Add64(x692, x728, uint64(p521Uint1(x746))) + var x749 uint64 + var x750 uint64 + x749, x750 = bits.Add64(x694, x730, uint64(p521Uint1(x748))) + var x751 uint64 + var x752 uint64 + x751, x752 = bits.Add64(x696, x732, uint64(p521Uint1(x750))) + var x753 uint64 + var x754 uint64 + x753, x754 = bits.Add64(x698, x734, uint64(p521Uint1(x752))) + var x755 uint64 + var x756 uint64 + x755, x756 = bits.Add64(x700, x736, uint64(p521Uint1(x754))) + var x757 uint64 + var x758 uint64 + x757, x758 = bits.Add64(x702, x738, uint64(p521Uint1(x756))) + var x759 uint64 + var x760 uint64 + x759, x760 = bits.Add64(x704, x740, uint64(p521Uint1(x758))) + var x761 uint64 + var x762 uint64 + x761, x762 = bits.Add64(x706, x742, uint64(p521Uint1(x760))) + var x763 uint64 + var x764 uint64 + x763, x764 = bits.Add64(x708, x744, uint64(p521Uint1(x762))) + x765 := (uint64(p521Uint1(x764)) + uint64(p521Uint1(x709))) + var x766 uint64 + var x767 uint64 + x767, x766 = bits.Mul64(x7, arg2[8]) + var x768 uint64 + var x769 uint64 + x769, x768 = bits.Mul64(x7, arg2[7]) + var x770 uint64 + var x771 uint64 + x771, x770 = bits.Mul64(x7, arg2[6]) + var x772 uint64 + var x773 uint64 + x773, x772 = bits.Mul64(x7, arg2[5]) + var x774 uint64 + var x775 uint64 + x775, x774 = bits.Mul64(x7, arg2[4]) + var x776 uint64 + var x777 uint64 + x777, x776 = bits.Mul64(x7, arg2[3]) + var x778 uint64 + var x779 uint64 + x779, x778 = bits.Mul64(x7, arg2[2]) + var x780 uint64 + var x781 uint64 + x781, x780 = bits.Mul64(x7, arg2[1]) + var x782 uint64 + var x783 uint64 + x783, x782 = bits.Mul64(x7, arg2[0]) + var x784 uint64 + var x785 uint64 + x784, x785 = bits.Add64(x783, x780, uint64(0x0)) + var x786 uint64 + var x787 uint64 + x786, x787 = bits.Add64(x781, x778, uint64(p521Uint1(x785))) + var x788 uint64 + var x789 uint64 + x788, x789 = bits.Add64(x779, x776, uint64(p521Uint1(x787))) + var x790 uint64 + var x791 uint64 + x790, x791 = bits.Add64(x777, x774, uint64(p521Uint1(x789))) + var x792 uint64 + var x793 uint64 + x792, x793 = bits.Add64(x775, x772, uint64(p521Uint1(x791))) + var x794 uint64 + var x795 uint64 + x794, x795 = bits.Add64(x773, x770, uint64(p521Uint1(x793))) + var x796 uint64 + var x797 uint64 + x796, x797 = bits.Add64(x771, x768, uint64(p521Uint1(x795))) + var x798 uint64 + var x799 uint64 + x798, x799 = bits.Add64(x769, x766, uint64(p521Uint1(x797))) + x800 := (uint64(p521Uint1(x799)) + x767) + var x801 uint64 + var x802 uint64 + x801, x802 = bits.Add64(x747, x782, uint64(0x0)) + var x803 uint64 + var x804 uint64 + x803, x804 = bits.Add64(x749, x784, uint64(p521Uint1(x802))) + var x805 uint64 + var x806 uint64 + x805, x806 = bits.Add64(x751, x786, uint64(p521Uint1(x804))) + var x807 uint64 + var x808 uint64 + x807, x808 = bits.Add64(x753, x788, uint64(p521Uint1(x806))) + var x809 uint64 + var x810 uint64 + x809, x810 = bits.Add64(x755, x790, uint64(p521Uint1(x808))) + var x811 uint64 + var x812 uint64 + x811, x812 = bits.Add64(x757, x792, uint64(p521Uint1(x810))) + var x813 uint64 + var x814 uint64 + x813, x814 = bits.Add64(x759, x794, uint64(p521Uint1(x812))) + var x815 uint64 + var x816 uint64 + x815, x816 = bits.Add64(x761, x796, uint64(p521Uint1(x814))) + var x817 uint64 + var x818 uint64 + x817, x818 = bits.Add64(x763, x798, uint64(p521Uint1(x816))) + var x819 uint64 + var x820 uint64 + x819, x820 = bits.Add64(x765, x800, uint64(p521Uint1(x818))) + var x821 uint64 + var x822 uint64 + x822, x821 = bits.Mul64(x801, 0x1ff) + var x823 uint64 + var x824 uint64 + x824, x823 = bits.Mul64(x801, 0xffffffffffffffff) + var x825 uint64 + var x826 uint64 + x826, x825 = bits.Mul64(x801, 0xffffffffffffffff) + var x827 uint64 + var x828 uint64 + x828, x827 = bits.Mul64(x801, 0xffffffffffffffff) + var x829 uint64 + var x830 uint64 + x830, x829 = bits.Mul64(x801, 0xffffffffffffffff) + var x831 uint64 + var x832 uint64 + x832, x831 = bits.Mul64(x801, 0xffffffffffffffff) + var x833 uint64 + var x834 uint64 + x834, x833 = bits.Mul64(x801, 0xffffffffffffffff) + var x835 uint64 + var x836 uint64 + x836, x835 = bits.Mul64(x801, 0xffffffffffffffff) + var x837 uint64 + var x838 uint64 + x838, x837 = bits.Mul64(x801, 0xffffffffffffffff) + var x839 uint64 + var x840 uint64 + x839, x840 = bits.Add64(x838, x835, uint64(0x0)) + var x841 uint64 + var x842 uint64 + x841, x842 = bits.Add64(x836, x833, uint64(p521Uint1(x840))) + var x843 uint64 + var x844 uint64 + x843, x844 = bits.Add64(x834, x831, uint64(p521Uint1(x842))) + var x845 uint64 + var x846 uint64 + x845, x846 = bits.Add64(x832, x829, uint64(p521Uint1(x844))) + var x847 uint64 + var x848 uint64 + x847, x848 = bits.Add64(x830, x827, uint64(p521Uint1(x846))) + var x849 uint64 + var x850 uint64 + x849, x850 = bits.Add64(x828, x825, uint64(p521Uint1(x848))) + var x851 uint64 + var x852 uint64 + x851, x852 = bits.Add64(x826, x823, uint64(p521Uint1(x850))) + var x853 uint64 + var x854 uint64 + x853, x854 = bits.Add64(x824, x821, uint64(p521Uint1(x852))) + x855 := (uint64(p521Uint1(x854)) + x822) + var x857 uint64 + _, x857 = bits.Add64(x801, x837, uint64(0x0)) + var x858 uint64 + var x859 uint64 + x858, x859 = bits.Add64(x803, x839, uint64(p521Uint1(x857))) + var x860 uint64 + var x861 uint64 + x860, x861 = bits.Add64(x805, x841, uint64(p521Uint1(x859))) + var x862 uint64 + var x863 uint64 + x862, x863 = bits.Add64(x807, x843, uint64(p521Uint1(x861))) + var x864 uint64 + var x865 uint64 + x864, x865 = bits.Add64(x809, x845, uint64(p521Uint1(x863))) + var x866 uint64 + var x867 uint64 + x866, x867 = bits.Add64(x811, x847, uint64(p521Uint1(x865))) + var x868 uint64 + var x869 uint64 + x868, x869 = bits.Add64(x813, x849, uint64(p521Uint1(x867))) + var x870 uint64 + var x871 uint64 + x870, x871 = bits.Add64(x815, x851, uint64(p521Uint1(x869))) + var x872 uint64 + var x873 uint64 + x872, x873 = bits.Add64(x817, x853, uint64(p521Uint1(x871))) + var x874 uint64 + var x875 uint64 + x874, x875 = bits.Add64(x819, x855, uint64(p521Uint1(x873))) + x876 := (uint64(p521Uint1(x875)) + uint64(p521Uint1(x820))) + var x877 uint64 + var x878 uint64 + x878, x877 = bits.Mul64(x8, arg2[8]) + var x879 uint64 + var x880 uint64 + x880, x879 = bits.Mul64(x8, arg2[7]) + var x881 uint64 + var x882 uint64 + x882, x881 = bits.Mul64(x8, arg2[6]) + var x883 uint64 + var x884 uint64 + x884, x883 = bits.Mul64(x8, arg2[5]) + var x885 uint64 + var x886 uint64 + x886, x885 = bits.Mul64(x8, arg2[4]) + var x887 uint64 + var x888 uint64 + x888, x887 = bits.Mul64(x8, arg2[3]) + var x889 uint64 + var x890 uint64 + x890, x889 = bits.Mul64(x8, arg2[2]) + var x891 uint64 + var x892 uint64 + x892, x891 = bits.Mul64(x8, arg2[1]) + var x893 uint64 + var x894 uint64 + x894, x893 = bits.Mul64(x8, arg2[0]) + var x895 uint64 + var x896 uint64 + x895, x896 = bits.Add64(x894, x891, uint64(0x0)) + var x897 uint64 + var x898 uint64 + x897, x898 = bits.Add64(x892, x889, uint64(p521Uint1(x896))) + var x899 uint64 + var x900 uint64 + x899, x900 = bits.Add64(x890, x887, uint64(p521Uint1(x898))) + var x901 uint64 + var x902 uint64 + x901, x902 = bits.Add64(x888, x885, uint64(p521Uint1(x900))) + var x903 uint64 + var x904 uint64 + x903, x904 = bits.Add64(x886, x883, uint64(p521Uint1(x902))) + var x905 uint64 + var x906 uint64 + x905, x906 = bits.Add64(x884, x881, uint64(p521Uint1(x904))) + var x907 uint64 + var x908 uint64 + x907, x908 = bits.Add64(x882, x879, uint64(p521Uint1(x906))) + var x909 uint64 + var x910 uint64 + x909, x910 = bits.Add64(x880, x877, uint64(p521Uint1(x908))) + x911 := (uint64(p521Uint1(x910)) + x878) + var x912 uint64 + var x913 uint64 + x912, x913 = bits.Add64(x858, x893, uint64(0x0)) + var x914 uint64 + var x915 uint64 + x914, x915 = bits.Add64(x860, x895, uint64(p521Uint1(x913))) + var x916 uint64 + var x917 uint64 + x916, x917 = bits.Add64(x862, x897, uint64(p521Uint1(x915))) + var x918 uint64 + var x919 uint64 + x918, x919 = bits.Add64(x864, x899, uint64(p521Uint1(x917))) + var x920 uint64 + var x921 uint64 + x920, x921 = bits.Add64(x866, x901, uint64(p521Uint1(x919))) + var x922 uint64 + var x923 uint64 + x922, x923 = bits.Add64(x868, x903, uint64(p521Uint1(x921))) + var x924 uint64 + var x925 uint64 + x924, x925 = bits.Add64(x870, x905, uint64(p521Uint1(x923))) + var x926 uint64 + var x927 uint64 + x926, x927 = bits.Add64(x872, x907, uint64(p521Uint1(x925))) + var x928 uint64 + var x929 uint64 + x928, x929 = bits.Add64(x874, x909, uint64(p521Uint1(x927))) + var x930 uint64 + var x931 uint64 + x930, x931 = bits.Add64(x876, x911, uint64(p521Uint1(x929))) + var x932 uint64 + var x933 uint64 + x933, x932 = bits.Mul64(x912, 0x1ff) + var x934 uint64 + var x935 uint64 + x935, x934 = bits.Mul64(x912, 0xffffffffffffffff) + var x936 uint64 + var x937 uint64 + x937, x936 = bits.Mul64(x912, 0xffffffffffffffff) + var x938 uint64 + var x939 uint64 + x939, x938 = bits.Mul64(x912, 0xffffffffffffffff) + var x940 uint64 + var x941 uint64 + x941, x940 = bits.Mul64(x912, 0xffffffffffffffff) + var x942 uint64 + var x943 uint64 + x943, x942 = bits.Mul64(x912, 0xffffffffffffffff) + var x944 uint64 + var x945 uint64 + x945, x944 = bits.Mul64(x912, 0xffffffffffffffff) + var x946 uint64 + var x947 uint64 + x947, x946 = bits.Mul64(x912, 0xffffffffffffffff) + var x948 uint64 + var x949 uint64 + x949, x948 = bits.Mul64(x912, 0xffffffffffffffff) + var x950 uint64 + var x951 uint64 + x950, x951 = bits.Add64(x949, x946, uint64(0x0)) + var x952 uint64 + var x953 uint64 + x952, x953 = bits.Add64(x947, x944, uint64(p521Uint1(x951))) + var x954 uint64 + var x955 uint64 + x954, x955 = bits.Add64(x945, x942, uint64(p521Uint1(x953))) + var x956 uint64 + var x957 uint64 + x956, x957 = bits.Add64(x943, x940, uint64(p521Uint1(x955))) + var x958 uint64 + var x959 uint64 + x958, x959 = bits.Add64(x941, x938, uint64(p521Uint1(x957))) + var x960 uint64 + var x961 uint64 + x960, x961 = bits.Add64(x939, x936, uint64(p521Uint1(x959))) + var x962 uint64 + var x963 uint64 + x962, x963 = bits.Add64(x937, x934, uint64(p521Uint1(x961))) + var x964 uint64 + var x965 uint64 + x964, x965 = bits.Add64(x935, x932, uint64(p521Uint1(x963))) + x966 := (uint64(p521Uint1(x965)) + x933) + var x968 uint64 + _, x968 = bits.Add64(x912, x948, uint64(0x0)) + var x969 uint64 + var x970 uint64 + x969, x970 = bits.Add64(x914, x950, uint64(p521Uint1(x968))) + var x971 uint64 + var x972 uint64 + x971, x972 = bits.Add64(x916, x952, uint64(p521Uint1(x970))) + var x973 uint64 + var x974 uint64 + x973, x974 = bits.Add64(x918, x954, uint64(p521Uint1(x972))) + var x975 uint64 + var x976 uint64 + x975, x976 = bits.Add64(x920, x956, uint64(p521Uint1(x974))) + var x977 uint64 + var x978 uint64 + x977, x978 = bits.Add64(x922, x958, uint64(p521Uint1(x976))) + var x979 uint64 + var x980 uint64 + x979, x980 = bits.Add64(x924, x960, uint64(p521Uint1(x978))) + var x981 uint64 + var x982 uint64 + x981, x982 = bits.Add64(x926, x962, uint64(p521Uint1(x980))) + var x983 uint64 + var x984 uint64 + x983, x984 = bits.Add64(x928, x964, uint64(p521Uint1(x982))) + var x985 uint64 + var x986 uint64 + x985, x986 = bits.Add64(x930, x966, uint64(p521Uint1(x984))) + x987 := (uint64(p521Uint1(x986)) + uint64(p521Uint1(x931))) + var x988 uint64 + var x989 uint64 + x988, x989 = bits.Sub64(x969, 0xffffffffffffffff, uint64(0x0)) + var x990 uint64 + var x991 uint64 + x990, x991 = bits.Sub64(x971, 0xffffffffffffffff, uint64(p521Uint1(x989))) + var x992 uint64 + var x993 uint64 + x992, x993 = bits.Sub64(x973, 0xffffffffffffffff, uint64(p521Uint1(x991))) + var x994 uint64 + var x995 uint64 + x994, x995 = bits.Sub64(x975, 0xffffffffffffffff, uint64(p521Uint1(x993))) + var x996 uint64 + var x997 uint64 + x996, x997 = bits.Sub64(x977, 0xffffffffffffffff, uint64(p521Uint1(x995))) + var x998 uint64 + var x999 uint64 + x998, x999 = bits.Sub64(x979, 0xffffffffffffffff, uint64(p521Uint1(x997))) + var x1000 uint64 + var x1001 uint64 + x1000, x1001 = bits.Sub64(x981, 0xffffffffffffffff, uint64(p521Uint1(x999))) + var x1002 uint64 + var x1003 uint64 + x1002, x1003 = bits.Sub64(x983, 0xffffffffffffffff, uint64(p521Uint1(x1001))) + var x1004 uint64 + var x1005 uint64 + x1004, x1005 = bits.Sub64(x985, 0x1ff, uint64(p521Uint1(x1003))) + var x1007 uint64 + _, x1007 = bits.Sub64(x987, uint64(0x0), uint64(p521Uint1(x1005))) + var x1008 uint64 + p521CmovznzU64(&x1008, p521Uint1(x1007), x988, x969) + var x1009 uint64 + p521CmovznzU64(&x1009, p521Uint1(x1007), x990, x971) + var x1010 uint64 + p521CmovznzU64(&x1010, p521Uint1(x1007), x992, x973) + var x1011 uint64 + p521CmovznzU64(&x1011, p521Uint1(x1007), x994, x975) + var x1012 uint64 + p521CmovznzU64(&x1012, p521Uint1(x1007), x996, x977) + var x1013 uint64 + p521CmovznzU64(&x1013, p521Uint1(x1007), x998, x979) + var x1014 uint64 + p521CmovznzU64(&x1014, p521Uint1(x1007), x1000, x981) + var x1015 uint64 + p521CmovznzU64(&x1015, p521Uint1(x1007), x1002, x983) + var x1016 uint64 + p521CmovznzU64(&x1016, p521Uint1(x1007), x1004, x985) + out1[0] = x1008 + out1[1] = x1009 + out1[2] = x1010 + out1[3] = x1011 + out1[4] = x1012 + out1[5] = x1013 + out1[6] = x1014 + out1[7] = x1015 + out1[8] = x1016 } -// p521CarrySquare squares a field element and reduces the result. +// p521Square squares a field element in the Montgomery domain. // +// Preconditions: +// 0 ≤ eval arg1 < m // Postconditions: -// eval out1 mod m = (eval arg1 * eval arg1) mod m +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg1)) mod m +// 0 ≤ eval out1 < m // -// Input Bounds: -// arg1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]] -// Output Bounds: -// out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] -func p521CarrySquare(out1 *[9]uint64, arg1 *[9]uint64) { - x1 := arg1[8] - x2 := (x1 * 0x2) - x3 := (arg1[8] * 0x2) - x4 := arg1[7] - x5 := (x4 * 0x2) - x6 := (arg1[7] * 0x2) - x7 := arg1[6] - x8 := (x7 * 0x2) - x9 := (arg1[6] * 0x2) - x10 := arg1[5] - x11 := (x10 * 0x2) - x12 := (arg1[5] * 0x2) - x13 := (arg1[4] * 0x2) - x14 := (arg1[3] * 0x2) - x15 := (arg1[2] * 0x2) - x16 := (arg1[1] * 0x2) +func p521Square(out1 *p521MontgomeryDomainFieldElement, arg1 *p521MontgomeryDomainFieldElement) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[4] + x5 := arg1[5] + x6 := arg1[6] + x7 := arg1[7] + x8 := arg1[8] + x9 := arg1[0] + var x10 uint64 + var x11 uint64 + x11, x10 = bits.Mul64(x9, arg1[8]) + var x12 uint64 + var x13 uint64 + x13, x12 = bits.Mul64(x9, arg1[7]) + var x14 uint64 + var x15 uint64 + x15, x14 = bits.Mul64(x9, arg1[6]) + var x16 uint64 var x17 uint64 + x17, x16 = bits.Mul64(x9, arg1[5]) var x18 uint64 - x18, x17 = bits.Mul64(arg1[8], (x1 * 0x2)) var x19 uint64 + x19, x18 = bits.Mul64(x9, arg1[4]) var x20 uint64 - x20, x19 = bits.Mul64(arg1[7], (x2 * 0x2)) var x21 uint64 + x21, x20 = bits.Mul64(x9, arg1[3]) var x22 uint64 - x22, x21 = bits.Mul64(arg1[7], (x4 * 0x2)) var x23 uint64 + x23, x22 = bits.Mul64(x9, arg1[2]) var x24 uint64 - x24, x23 = bits.Mul64(arg1[6], (x2 * 0x2)) var x25 uint64 + x25, x24 = bits.Mul64(x9, arg1[1]) var x26 uint64 - x26, x25 = bits.Mul64(arg1[6], (x5 * 0x2)) var x27 uint64 + x27, x26 = bits.Mul64(x9, arg1[0]) var x28 uint64 - x28, x27 = bits.Mul64(arg1[6], (x7 * 0x2)) var x29 uint64 + x28, x29 = bits.Add64(x27, x24, uint64(0x0)) var x30 uint64 - x30, x29 = bits.Mul64(arg1[5], (x2 * 0x2)) var x31 uint64 + x30, x31 = bits.Add64(x25, x22, uint64(p521Uint1(x29))) var x32 uint64 - x32, x31 = bits.Mul64(arg1[5], (x5 * 0x2)) var x33 uint64 + x32, x33 = bits.Add64(x23, x20, uint64(p521Uint1(x31))) var x34 uint64 - x34, x33 = bits.Mul64(arg1[5], (x8 * 0x2)) var x35 uint64 + x34, x35 = bits.Add64(x21, x18, uint64(p521Uint1(x33))) var x36 uint64 - x36, x35 = bits.Mul64(arg1[5], (x10 * 0x2)) var x37 uint64 + x36, x37 = bits.Add64(x19, x16, uint64(p521Uint1(x35))) var x38 uint64 - x38, x37 = bits.Mul64(arg1[4], (x2 * 0x2)) var x39 uint64 + x38, x39 = bits.Add64(x17, x14, uint64(p521Uint1(x37))) var x40 uint64 - x40, x39 = bits.Mul64(arg1[4], (x5 * 0x2)) var x41 uint64 + x40, x41 = bits.Add64(x15, x12, uint64(p521Uint1(x39))) var x42 uint64 - x42, x41 = bits.Mul64(arg1[4], (x8 * 0x2)) var x43 uint64 - var x44 uint64 - x44, x43 = bits.Mul64(arg1[4], (x11 * 0x2)) + x42, x43 = bits.Add64(x13, x10, uint64(p521Uint1(x41))) + x44 := (uint64(p521Uint1(x43)) + x11) var x45 uint64 var x46 uint64 - x46, x45 = bits.Mul64(arg1[4], arg1[4]) + x46, x45 = bits.Mul64(x26, 0x1ff) var x47 uint64 var x48 uint64 - x48, x47 = bits.Mul64(arg1[3], (x2 * 0x2)) + x48, x47 = bits.Mul64(x26, 0xffffffffffffffff) var x49 uint64 var x50 uint64 - x50, x49 = bits.Mul64(arg1[3], (x5 * 0x2)) + x50, x49 = bits.Mul64(x26, 0xffffffffffffffff) var x51 uint64 var x52 uint64 - x52, x51 = bits.Mul64(arg1[3], (x8 * 0x2)) + x52, x51 = bits.Mul64(x26, 0xffffffffffffffff) var x53 uint64 var x54 uint64 - x54, x53 = bits.Mul64(arg1[3], x12) + x54, x53 = bits.Mul64(x26, 0xffffffffffffffff) var x55 uint64 var x56 uint64 - x56, x55 = bits.Mul64(arg1[3], x13) + x56, x55 = bits.Mul64(x26, 0xffffffffffffffff) var x57 uint64 var x58 uint64 - x58, x57 = bits.Mul64(arg1[3], arg1[3]) + x58, x57 = bits.Mul64(x26, 0xffffffffffffffff) var x59 uint64 var x60 uint64 - x60, x59 = bits.Mul64(arg1[2], (x2 * 0x2)) + x60, x59 = bits.Mul64(x26, 0xffffffffffffffff) var x61 uint64 var x62 uint64 - x62, x61 = bits.Mul64(arg1[2], (x5 * 0x2)) + x62, x61 = bits.Mul64(x26, 0xffffffffffffffff) var x63 uint64 var x64 uint64 - x64, x63 = bits.Mul64(arg1[2], x9) + x63, x64 = bits.Add64(x62, x59, uint64(0x0)) var x65 uint64 var x66 uint64 - x66, x65 = bits.Mul64(arg1[2], x12) + x65, x66 = bits.Add64(x60, x57, uint64(p521Uint1(x64))) var x67 uint64 var x68 uint64 - x68, x67 = bits.Mul64(arg1[2], x13) + x67, x68 = bits.Add64(x58, x55, uint64(p521Uint1(x66))) var x69 uint64 var x70 uint64 - x70, x69 = bits.Mul64(arg1[2], x14) + x69, x70 = bits.Add64(x56, x53, uint64(p521Uint1(x68))) var x71 uint64 var x72 uint64 - x72, x71 = bits.Mul64(arg1[2], arg1[2]) + x71, x72 = bits.Add64(x54, x51, uint64(p521Uint1(x70))) var x73 uint64 var x74 uint64 - x74, x73 = bits.Mul64(arg1[1], (x2 * 0x2)) + x73, x74 = bits.Add64(x52, x49, uint64(p521Uint1(x72))) var x75 uint64 var x76 uint64 - x76, x75 = bits.Mul64(arg1[1], x6) + x75, x76 = bits.Add64(x50, x47, uint64(p521Uint1(x74))) var x77 uint64 var x78 uint64 - x78, x77 = bits.Mul64(arg1[1], x9) - var x79 uint64 - var x80 uint64 - x80, x79 = bits.Mul64(arg1[1], x12) + x77, x78 = bits.Add64(x48, x45, uint64(p521Uint1(x76))) + x79 := (uint64(p521Uint1(x78)) + x46) var x81 uint64 + _, x81 = bits.Add64(x26, x61, uint64(0x0)) var x82 uint64 - x82, x81 = bits.Mul64(arg1[1], x13) var x83 uint64 + x82, x83 = bits.Add64(x28, x63, uint64(p521Uint1(x81))) var x84 uint64 - x84, x83 = bits.Mul64(arg1[1], x14) var x85 uint64 + x84, x85 = bits.Add64(x30, x65, uint64(p521Uint1(x83))) var x86 uint64 - x86, x85 = bits.Mul64(arg1[1], x15) var x87 uint64 + x86, x87 = bits.Add64(x32, x67, uint64(p521Uint1(x85))) var x88 uint64 - x88, x87 = bits.Mul64(arg1[1], arg1[1]) var x89 uint64 + x88, x89 = bits.Add64(x34, x69, uint64(p521Uint1(x87))) var x90 uint64 - x90, x89 = bits.Mul64(arg1[0], x3) var x91 uint64 + x90, x91 = bits.Add64(x36, x71, uint64(p521Uint1(x89))) var x92 uint64 - x92, x91 = bits.Mul64(arg1[0], x6) var x93 uint64 + x92, x93 = bits.Add64(x38, x73, uint64(p521Uint1(x91))) var x94 uint64 - x94, x93 = bits.Mul64(arg1[0], x9) var x95 uint64 + x94, x95 = bits.Add64(x40, x75, uint64(p521Uint1(x93))) var x96 uint64 - x96, x95 = bits.Mul64(arg1[0], x12) var x97 uint64 + x96, x97 = bits.Add64(x42, x77, uint64(p521Uint1(x95))) var x98 uint64 - x98, x97 = bits.Mul64(arg1[0], x13) var x99 uint64 + x98, x99 = bits.Add64(x44, x79, uint64(p521Uint1(x97))) var x100 uint64 - x100, x99 = bits.Mul64(arg1[0], x14) var x101 uint64 + x101, x100 = bits.Mul64(x1, arg1[8]) var x102 uint64 - x102, x101 = bits.Mul64(arg1[0], x15) var x103 uint64 + x103, x102 = bits.Mul64(x1, arg1[7]) var x104 uint64 - x104, x103 = bits.Mul64(arg1[0], x16) var x105 uint64 + x105, x104 = bits.Mul64(x1, arg1[6]) var x106 uint64 - x106, x105 = bits.Mul64(arg1[0], arg1[0]) var x107 uint64 - var x108 p521Uint1 - x107, x108 = p521AddcarryxU64(x51, x43, 0x0) + x107, x106 = bits.Mul64(x1, arg1[5]) + var x108 uint64 var x109 uint64 - x109, _ = p521AddcarryxU64(x52, x44, x108) + x109, x108 = bits.Mul64(x1, arg1[4]) + var x110 uint64 var x111 uint64 - var x112 p521Uint1 - x111, x112 = p521AddcarryxU64(x61, x107, 0x0) + x111, x110 = bits.Mul64(x1, arg1[3]) + var x112 uint64 var x113 uint64 - x113, _ = p521AddcarryxU64(x62, x109, x112) + x113, x112 = bits.Mul64(x1, arg1[2]) + var x114 uint64 var x115 uint64 - var x116 p521Uint1 - x115, x116 = p521AddcarryxU64(x73, x111, 0x0) + x115, x114 = bits.Mul64(x1, arg1[1]) + var x116 uint64 var x117 uint64 - x117, _ = p521AddcarryxU64(x74, x113, x116) + x117, x116 = bits.Mul64(x1, arg1[0]) + var x118 uint64 var x119 uint64 - var x120 p521Uint1 - x119, x120 = p521AddcarryxU64(x105, x115, 0x0) + x118, x119 = bits.Add64(x117, x114, uint64(0x0)) + var x120 uint64 var x121 uint64 - x121, _ = p521AddcarryxU64(x106, x117, x120) - x123 := ((x119 >> 58) | ((x121 << 6) & 0xffffffffffffffff)) - x124 := (x121 >> 58) - x125 := (x119 & 0x3ffffffffffffff) + x120, x121 = bits.Add64(x115, x112, uint64(p521Uint1(x119))) + var x122 uint64 + var x123 uint64 + x122, x123 = bits.Add64(x113, x110, uint64(p521Uint1(x121))) + var x124 uint64 + var x125 uint64 + x124, x125 = bits.Add64(x111, x108, uint64(p521Uint1(x123))) var x126 uint64 - var x127 p521Uint1 - x126, x127 = p521AddcarryxU64(x53, x45, 0x0) + var x127 uint64 + x126, x127 = bits.Add64(x109, x106, uint64(p521Uint1(x125))) var x128 uint64 - x128, _ = p521AddcarryxU64(x54, x46, x127) + var x129 uint64 + x128, x129 = bits.Add64(x107, x104, uint64(p521Uint1(x127))) var x130 uint64 - var x131 p521Uint1 - x130, x131 = p521AddcarryxU64(x63, x126, 0x0) + var x131 uint64 + x130, x131 = bits.Add64(x105, x102, uint64(p521Uint1(x129))) var x132 uint64 - x132, _ = p521AddcarryxU64(x64, x128, x131) - var x134 uint64 - var x135 p521Uint1 - x134, x135 = p521AddcarryxU64(x75, x130, 0x0) + var x133 uint64 + x132, x133 = bits.Add64(x103, x100, uint64(p521Uint1(x131))) + x134 := (uint64(p521Uint1(x133)) + x101) + var x135 uint64 var x136 uint64 - x136, _ = p521AddcarryxU64(x76, x132, x135) + x135, x136 = bits.Add64(x82, x116, uint64(0x0)) + var x137 uint64 var x138 uint64 - var x139 p521Uint1 - x138, x139 = p521AddcarryxU64(x89, x134, 0x0) + x137, x138 = bits.Add64(x84, x118, uint64(p521Uint1(x136))) + var x139 uint64 var x140 uint64 - x140, _ = p521AddcarryxU64(x90, x136, x139) + x139, x140 = bits.Add64(x86, x120, uint64(p521Uint1(x138))) + var x141 uint64 var x142 uint64 - var x143 p521Uint1 - x142, x143 = p521AddcarryxU64(x55, x17, 0x0) + x141, x142 = bits.Add64(x88, x122, uint64(p521Uint1(x140))) + var x143 uint64 var x144 uint64 - x144, _ = p521AddcarryxU64(x56, x18, x143) + x143, x144 = bits.Add64(x90, x124, uint64(p521Uint1(x142))) + var x145 uint64 var x146 uint64 - var x147 p521Uint1 - x146, x147 = p521AddcarryxU64(x65, x142, 0x0) + x145, x146 = bits.Add64(x92, x126, uint64(p521Uint1(x144))) + var x147 uint64 var x148 uint64 - x148, _ = p521AddcarryxU64(x66, x144, x147) + x147, x148 = bits.Add64(x94, x128, uint64(p521Uint1(x146))) + var x149 uint64 var x150 uint64 - var x151 p521Uint1 - x150, x151 = p521AddcarryxU64(x77, x146, 0x0) + x149, x150 = bits.Add64(x96, x130, uint64(p521Uint1(x148))) + var x151 uint64 var x152 uint64 - x152, _ = p521AddcarryxU64(x78, x148, x151) + x151, x152 = bits.Add64(x98, x132, uint64(p521Uint1(x150))) + var x153 uint64 var x154 uint64 - var x155 p521Uint1 - x154, x155 = p521AddcarryxU64(x91, x150, 0x0) + x153, x154 = bits.Add64(uint64(p521Uint1(x99)), x134, uint64(p521Uint1(x152))) + var x155 uint64 var x156 uint64 - x156, _ = p521AddcarryxU64(x92, x152, x155) + x156, x155 = bits.Mul64(x135, 0x1ff) + var x157 uint64 var x158 uint64 - var x159 p521Uint1 - x158, x159 = p521AddcarryxU64(x57, x19, 0x0) + x158, x157 = bits.Mul64(x135, 0xffffffffffffffff) + var x159 uint64 var x160 uint64 - x160, _ = p521AddcarryxU64(x58, x20, x159) + x160, x159 = bits.Mul64(x135, 0xffffffffffffffff) + var x161 uint64 var x162 uint64 - var x163 p521Uint1 - x162, x163 = p521AddcarryxU64(x67, x158, 0x0) + x162, x161 = bits.Mul64(x135, 0xffffffffffffffff) + var x163 uint64 var x164 uint64 - x164, _ = p521AddcarryxU64(x68, x160, x163) + x164, x163 = bits.Mul64(x135, 0xffffffffffffffff) + var x165 uint64 var x166 uint64 - var x167 p521Uint1 - x166, x167 = p521AddcarryxU64(x79, x162, 0x0) + x166, x165 = bits.Mul64(x135, 0xffffffffffffffff) + var x167 uint64 var x168 uint64 - x168, _ = p521AddcarryxU64(x80, x164, x167) + x168, x167 = bits.Mul64(x135, 0xffffffffffffffff) + var x169 uint64 var x170 uint64 - var x171 p521Uint1 - x170, x171 = p521AddcarryxU64(x93, x166, 0x0) + x170, x169 = bits.Mul64(x135, 0xffffffffffffffff) + var x171 uint64 var x172 uint64 - x172, _ = p521AddcarryxU64(x94, x168, x171) + x172, x171 = bits.Mul64(x135, 0xffffffffffffffff) + var x173 uint64 var x174 uint64 - var x175 p521Uint1 - x174, x175 = p521AddcarryxU64(x23, x21, 0x0) + x173, x174 = bits.Add64(x172, x169, uint64(0x0)) + var x175 uint64 var x176 uint64 - x176, _ = p521AddcarryxU64(x24, x22, x175) + x175, x176 = bits.Add64(x170, x167, uint64(p521Uint1(x174))) + var x177 uint64 var x178 uint64 - var x179 p521Uint1 - x178, x179 = p521AddcarryxU64(x69, x174, 0x0) + x177, x178 = bits.Add64(x168, x165, uint64(p521Uint1(x176))) + var x179 uint64 var x180 uint64 - x180, _ = p521AddcarryxU64(x70, x176, x179) + x179, x180 = bits.Add64(x166, x163, uint64(p521Uint1(x178))) + var x181 uint64 var x182 uint64 - var x183 p521Uint1 - x182, x183 = p521AddcarryxU64(x81, x178, 0x0) + x181, x182 = bits.Add64(x164, x161, uint64(p521Uint1(x180))) + var x183 uint64 var x184 uint64 - x184, _ = p521AddcarryxU64(x82, x180, x183) + x183, x184 = bits.Add64(x162, x159, uint64(p521Uint1(x182))) + var x185 uint64 var x186 uint64 - var x187 p521Uint1 - x186, x187 = p521AddcarryxU64(x95, x182, 0x0) + x185, x186 = bits.Add64(x160, x157, uint64(p521Uint1(x184))) + var x187 uint64 var x188 uint64 - x188, _ = p521AddcarryxU64(x96, x184, x187) - var x190 uint64 - var x191 p521Uint1 - x190, x191 = p521AddcarryxU64(x29, x25, 0x0) + x187, x188 = bits.Add64(x158, x155, uint64(p521Uint1(x186))) + x189 := (uint64(p521Uint1(x188)) + x156) + var x191 uint64 + _, x191 = bits.Add64(x135, x171, uint64(0x0)) var x192 uint64 - x192, _ = p521AddcarryxU64(x30, x26, x191) + var x193 uint64 + x192, x193 = bits.Add64(x137, x173, uint64(p521Uint1(x191))) var x194 uint64 - var x195 p521Uint1 - x194, x195 = p521AddcarryxU64(x71, x190, 0x0) + var x195 uint64 + x194, x195 = bits.Add64(x139, x175, uint64(p521Uint1(x193))) var x196 uint64 - x196, _ = p521AddcarryxU64(x72, x192, x195) + var x197 uint64 + x196, x197 = bits.Add64(x141, x177, uint64(p521Uint1(x195))) var x198 uint64 - var x199 p521Uint1 - x198, x199 = p521AddcarryxU64(x83, x194, 0x0) + var x199 uint64 + x198, x199 = bits.Add64(x143, x179, uint64(p521Uint1(x197))) var x200 uint64 - x200, _ = p521AddcarryxU64(x84, x196, x199) + var x201 uint64 + x200, x201 = bits.Add64(x145, x181, uint64(p521Uint1(x199))) var x202 uint64 - var x203 p521Uint1 - x202, x203 = p521AddcarryxU64(x97, x198, 0x0) + var x203 uint64 + x202, x203 = bits.Add64(x147, x183, uint64(p521Uint1(x201))) var x204 uint64 - x204, _ = p521AddcarryxU64(x98, x200, x203) + var x205 uint64 + x204, x205 = bits.Add64(x149, x185, uint64(p521Uint1(x203))) var x206 uint64 - var x207 p521Uint1 - x206, x207 = p521AddcarryxU64(x31, x27, 0x0) + var x207 uint64 + x206, x207 = bits.Add64(x151, x187, uint64(p521Uint1(x205))) var x208 uint64 - x208, _ = p521AddcarryxU64(x32, x28, x207) - var x210 uint64 - var x211 p521Uint1 - x210, x211 = p521AddcarryxU64(x37, x206, 0x0) + var x209 uint64 + x208, x209 = bits.Add64(x153, x189, uint64(p521Uint1(x207))) + x210 := (uint64(p521Uint1(x209)) + uint64(p521Uint1(x154))) + var x211 uint64 var x212 uint64 - x212, _ = p521AddcarryxU64(x38, x208, x211) + x212, x211 = bits.Mul64(x2, arg1[8]) + var x213 uint64 var x214 uint64 - var x215 p521Uint1 - x214, x215 = p521AddcarryxU64(x85, x210, 0x0) + x214, x213 = bits.Mul64(x2, arg1[7]) + var x215 uint64 var x216 uint64 - x216, _ = p521AddcarryxU64(x86, x212, x215) + x216, x215 = bits.Mul64(x2, arg1[6]) + var x217 uint64 var x218 uint64 - var x219 p521Uint1 - x218, x219 = p521AddcarryxU64(x99, x214, 0x0) + x218, x217 = bits.Mul64(x2, arg1[5]) + var x219 uint64 var x220 uint64 - x220, _ = p521AddcarryxU64(x100, x216, x219) + x220, x219 = bits.Mul64(x2, arg1[4]) + var x221 uint64 var x222 uint64 - var x223 p521Uint1 - x222, x223 = p521AddcarryxU64(x39, x33, 0x0) + x222, x221 = bits.Mul64(x2, arg1[3]) + var x223 uint64 var x224 uint64 - x224, _ = p521AddcarryxU64(x40, x34, x223) + x224, x223 = bits.Mul64(x2, arg1[2]) + var x225 uint64 var x226 uint64 - var x227 p521Uint1 - x226, x227 = p521AddcarryxU64(x47, x222, 0x0) + x226, x225 = bits.Mul64(x2, arg1[1]) + var x227 uint64 var x228 uint64 - x228, _ = p521AddcarryxU64(x48, x224, x227) + x228, x227 = bits.Mul64(x2, arg1[0]) + var x229 uint64 var x230 uint64 - var x231 p521Uint1 - x230, x231 = p521AddcarryxU64(x87, x226, 0x0) + x229, x230 = bits.Add64(x228, x225, uint64(0x0)) + var x231 uint64 var x232 uint64 - x232, _ = p521AddcarryxU64(x88, x228, x231) + x231, x232 = bits.Add64(x226, x223, uint64(p521Uint1(x230))) + var x233 uint64 var x234 uint64 - var x235 p521Uint1 - x234, x235 = p521AddcarryxU64(x101, x230, 0x0) + x233, x234 = bits.Add64(x224, x221, uint64(p521Uint1(x232))) + var x235 uint64 var x236 uint64 - x236, _ = p521AddcarryxU64(x102, x232, x235) + x235, x236 = bits.Add64(x222, x219, uint64(p521Uint1(x234))) + var x237 uint64 var x238 uint64 - var x239 p521Uint1 - x238, x239 = p521AddcarryxU64(x41, x35, 0x0) + x237, x238 = bits.Add64(x220, x217, uint64(p521Uint1(x236))) + var x239 uint64 var x240 uint64 - x240, _ = p521AddcarryxU64(x42, x36, x239) + x239, x240 = bits.Add64(x218, x215, uint64(p521Uint1(x238))) + var x241 uint64 var x242 uint64 - var x243 p521Uint1 - x242, x243 = p521AddcarryxU64(x49, x238, 0x0) + x241, x242 = bits.Add64(x216, x213, uint64(p521Uint1(x240))) + var x243 uint64 var x244 uint64 - x244, _ = p521AddcarryxU64(x50, x240, x243) + x243, x244 = bits.Add64(x214, x211, uint64(p521Uint1(x242))) + x245 := (uint64(p521Uint1(x244)) + x212) var x246 uint64 - var x247 p521Uint1 - x246, x247 = p521AddcarryxU64(x59, x242, 0x0) + var x247 uint64 + x246, x247 = bits.Add64(x192, x227, uint64(0x0)) var x248 uint64 - x248, _ = p521AddcarryxU64(x60, x244, x247) + var x249 uint64 + x248, x249 = bits.Add64(x194, x229, uint64(p521Uint1(x247))) var x250 uint64 - var x251 p521Uint1 - x250, x251 = p521AddcarryxU64(x103, x246, 0x0) + var x251 uint64 + x250, x251 = bits.Add64(x196, x231, uint64(p521Uint1(x249))) var x252 uint64 - x252, _ = p521AddcarryxU64(x104, x248, x251) + var x253 uint64 + x252, x253 = bits.Add64(x198, x233, uint64(p521Uint1(x251))) var x254 uint64 - var x255 p521Uint1 - x254, x255 = p521AddcarryxU64(x123, x250, 0x0) + var x255 uint64 + x254, x255 = bits.Add64(x200, x235, uint64(p521Uint1(x253))) var x256 uint64 - x256, _ = p521AddcarryxU64(x124, x252, x255) - x258 := ((x254 >> 58) | ((x256 << 6) & 0xffffffffffffffff)) - x259 := (x256 >> 58) - x260 := (x254 & 0x3ffffffffffffff) + var x257 uint64 + x256, x257 = bits.Add64(x202, x237, uint64(p521Uint1(x255))) + var x258 uint64 + var x259 uint64 + x258, x259 = bits.Add64(x204, x239, uint64(p521Uint1(x257))) + var x260 uint64 var x261 uint64 - var x262 p521Uint1 - x261, x262 = p521AddcarryxU64(x258, x234, 0x0) + x260, x261 = bits.Add64(x206, x241, uint64(p521Uint1(x259))) + var x262 uint64 var x263 uint64 - x263, _ = p521AddcarryxU64(x259, x236, x262) - x265 := ((x261 >> 58) | ((x263 << 6) & 0xffffffffffffffff)) - x266 := (x263 >> 58) - x267 := (x261 & 0x3ffffffffffffff) + x262, x263 = bits.Add64(x208, x243, uint64(p521Uint1(x261))) + var x264 uint64 + var x265 uint64 + x264, x265 = bits.Add64(x210, x245, uint64(p521Uint1(x263))) + var x266 uint64 + var x267 uint64 + x267, x266 = bits.Mul64(x246, 0x1ff) var x268 uint64 - var x269 p521Uint1 - x268, x269 = p521AddcarryxU64(x265, x218, 0x0) + var x269 uint64 + x269, x268 = bits.Mul64(x246, 0xffffffffffffffff) var x270 uint64 - x270, _ = p521AddcarryxU64(x266, x220, x269) - x272 := ((x268 >> 58) | ((x270 << 6) & 0xffffffffffffffff)) - x273 := (x270 >> 58) - x274 := (x268 & 0x3ffffffffffffff) + var x271 uint64 + x271, x270 = bits.Mul64(x246, 0xffffffffffffffff) + var x272 uint64 + var x273 uint64 + x273, x272 = bits.Mul64(x246, 0xffffffffffffffff) + var x274 uint64 var x275 uint64 - var x276 p521Uint1 - x275, x276 = p521AddcarryxU64(x272, x202, 0x0) + x275, x274 = bits.Mul64(x246, 0xffffffffffffffff) + var x276 uint64 var x277 uint64 - x277, _ = p521AddcarryxU64(x273, x204, x276) - x279 := ((x275 >> 58) | ((x277 << 6) & 0xffffffffffffffff)) - x280 := (x277 >> 58) - x281 := (x275 & 0x3ffffffffffffff) + x277, x276 = bits.Mul64(x246, 0xffffffffffffffff) + var x278 uint64 + var x279 uint64 + x279, x278 = bits.Mul64(x246, 0xffffffffffffffff) + var x280 uint64 + var x281 uint64 + x281, x280 = bits.Mul64(x246, 0xffffffffffffffff) var x282 uint64 - var x283 p521Uint1 - x282, x283 = p521AddcarryxU64(x279, x186, 0x0) + var x283 uint64 + x283, x282 = bits.Mul64(x246, 0xffffffffffffffff) var x284 uint64 - x284, _ = p521AddcarryxU64(x280, x188, x283) - x286 := ((x282 >> 58) | ((x284 << 6) & 0xffffffffffffffff)) - x287 := (x284 >> 58) - x288 := (x282 & 0x3ffffffffffffff) + var x285 uint64 + x284, x285 = bits.Add64(x283, x280, uint64(0x0)) + var x286 uint64 + var x287 uint64 + x286, x287 = bits.Add64(x281, x278, uint64(p521Uint1(x285))) + var x288 uint64 var x289 uint64 - var x290 p521Uint1 - x289, x290 = p521AddcarryxU64(x286, x170, 0x0) + x288, x289 = bits.Add64(x279, x276, uint64(p521Uint1(x287))) + var x290 uint64 var x291 uint64 - x291, _ = p521AddcarryxU64(x287, x172, x290) - x293 := ((x289 >> 58) | ((x291 << 6) & 0xffffffffffffffff)) - x294 := (x291 >> 58) - x295 := (x289 & 0x3ffffffffffffff) + x290, x291 = bits.Add64(x277, x274, uint64(p521Uint1(x289))) + var x292 uint64 + var x293 uint64 + x292, x293 = bits.Add64(x275, x272, uint64(p521Uint1(x291))) + var x294 uint64 + var x295 uint64 + x294, x295 = bits.Add64(x273, x270, uint64(p521Uint1(x293))) var x296 uint64 - var x297 p521Uint1 - x296, x297 = p521AddcarryxU64(x293, x154, 0x0) + var x297 uint64 + x296, x297 = bits.Add64(x271, x268, uint64(p521Uint1(x295))) var x298 uint64 - x298, _ = p521AddcarryxU64(x294, x156, x297) - x300 := ((x296 >> 58) | ((x298 << 6) & 0xffffffffffffffff)) - x301 := (x298 >> 58) - x302 := (x296 & 0x3ffffffffffffff) + var x299 uint64 + x298, x299 = bits.Add64(x269, x266, uint64(p521Uint1(x297))) + x300 := (uint64(p521Uint1(x299)) + x267) + var x302 uint64 + _, x302 = bits.Add64(x246, x282, uint64(0x0)) var x303 uint64 - var x304 p521Uint1 - x303, x304 = p521AddcarryxU64(x300, x138, 0x0) + var x304 uint64 + x303, x304 = bits.Add64(x248, x284, uint64(p521Uint1(x302))) var x305 uint64 - x305, _ = p521AddcarryxU64(x301, x140, x304) - x307 := ((x303 >> 57) | ((x305 << 7) & 0xffffffffffffffff)) - x308 := (x305 >> 57) - x309 := (x303 & 0x1ffffffffffffff) + var x306 uint64 + x305, x306 = bits.Add64(x250, x286, uint64(p521Uint1(x304))) + var x307 uint64 + var x308 uint64 + x307, x308 = bits.Add64(x252, x288, uint64(p521Uint1(x306))) + var x309 uint64 var x310 uint64 - var x311 p521Uint1 - x310, x311 = p521AddcarryxU64(x125, x307, 0x0) - x312 := (uint64(x311) + x308) - x313 := ((x310 >> 58) | ((x312 << 6) & 0xffffffffffffffff)) - x314 := (x310 & 0x3ffffffffffffff) - x315 := (x313 + x260) - x316 := p521Uint1((x315 >> 58)) - x317 := (x315 & 0x3ffffffffffffff) - x318 := (uint64(x316) + x267) - out1[0] = x314 - out1[1] = x317 - out1[2] = x318 - out1[3] = x274 - out1[4] = x281 - out1[5] = x288 - out1[6] = x295 - out1[7] = x302 - out1[8] = x309 + x309, x310 = bits.Add64(x254, x290, uint64(p521Uint1(x308))) + var x311 uint64 + var x312 uint64 + x311, x312 = bits.Add64(x256, x292, uint64(p521Uint1(x310))) + var x313 uint64 + var x314 uint64 + x313, x314 = bits.Add64(x258, x294, uint64(p521Uint1(x312))) + var x315 uint64 + var x316 uint64 + x315, x316 = bits.Add64(x260, x296, uint64(p521Uint1(x314))) + var x317 uint64 + var x318 uint64 + x317, x318 = bits.Add64(x262, x298, uint64(p521Uint1(x316))) + var x319 uint64 + var x320 uint64 + x319, x320 = bits.Add64(x264, x300, uint64(p521Uint1(x318))) + x321 := (uint64(p521Uint1(x320)) + uint64(p521Uint1(x265))) + var x322 uint64 + var x323 uint64 + x323, x322 = bits.Mul64(x3, arg1[8]) + var x324 uint64 + var x325 uint64 + x325, x324 = bits.Mul64(x3, arg1[7]) + var x326 uint64 + var x327 uint64 + x327, x326 = bits.Mul64(x3, arg1[6]) + var x328 uint64 + var x329 uint64 + x329, x328 = bits.Mul64(x3, arg1[5]) + var x330 uint64 + var x331 uint64 + x331, x330 = bits.Mul64(x3, arg1[4]) + var x332 uint64 + var x333 uint64 + x333, x332 = bits.Mul64(x3, arg1[3]) + var x334 uint64 + var x335 uint64 + x335, x334 = bits.Mul64(x3, arg1[2]) + var x336 uint64 + var x337 uint64 + x337, x336 = bits.Mul64(x3, arg1[1]) + var x338 uint64 + var x339 uint64 + x339, x338 = bits.Mul64(x3, arg1[0]) + var x340 uint64 + var x341 uint64 + x340, x341 = bits.Add64(x339, x336, uint64(0x0)) + var x342 uint64 + var x343 uint64 + x342, x343 = bits.Add64(x337, x334, uint64(p521Uint1(x341))) + var x344 uint64 + var x345 uint64 + x344, x345 = bits.Add64(x335, x332, uint64(p521Uint1(x343))) + var x346 uint64 + var x347 uint64 + x346, x347 = bits.Add64(x333, x330, uint64(p521Uint1(x345))) + var x348 uint64 + var x349 uint64 + x348, x349 = bits.Add64(x331, x328, uint64(p521Uint1(x347))) + var x350 uint64 + var x351 uint64 + x350, x351 = bits.Add64(x329, x326, uint64(p521Uint1(x349))) + var x352 uint64 + var x353 uint64 + x352, x353 = bits.Add64(x327, x324, uint64(p521Uint1(x351))) + var x354 uint64 + var x355 uint64 + x354, x355 = bits.Add64(x325, x322, uint64(p521Uint1(x353))) + x356 := (uint64(p521Uint1(x355)) + x323) + var x357 uint64 + var x358 uint64 + x357, x358 = bits.Add64(x303, x338, uint64(0x0)) + var x359 uint64 + var x360 uint64 + x359, x360 = bits.Add64(x305, x340, uint64(p521Uint1(x358))) + var x361 uint64 + var x362 uint64 + x361, x362 = bits.Add64(x307, x342, uint64(p521Uint1(x360))) + var x363 uint64 + var x364 uint64 + x363, x364 = bits.Add64(x309, x344, uint64(p521Uint1(x362))) + var x365 uint64 + var x366 uint64 + x365, x366 = bits.Add64(x311, x346, uint64(p521Uint1(x364))) + var x367 uint64 + var x368 uint64 + x367, x368 = bits.Add64(x313, x348, uint64(p521Uint1(x366))) + var x369 uint64 + var x370 uint64 + x369, x370 = bits.Add64(x315, x350, uint64(p521Uint1(x368))) + var x371 uint64 + var x372 uint64 + x371, x372 = bits.Add64(x317, x352, uint64(p521Uint1(x370))) + var x373 uint64 + var x374 uint64 + x373, x374 = bits.Add64(x319, x354, uint64(p521Uint1(x372))) + var x375 uint64 + var x376 uint64 + x375, x376 = bits.Add64(x321, x356, uint64(p521Uint1(x374))) + var x377 uint64 + var x378 uint64 + x378, x377 = bits.Mul64(x357, 0x1ff) + var x379 uint64 + var x380 uint64 + x380, x379 = bits.Mul64(x357, 0xffffffffffffffff) + var x381 uint64 + var x382 uint64 + x382, x381 = bits.Mul64(x357, 0xffffffffffffffff) + var x383 uint64 + var x384 uint64 + x384, x383 = bits.Mul64(x357, 0xffffffffffffffff) + var x385 uint64 + var x386 uint64 + x386, x385 = bits.Mul64(x357, 0xffffffffffffffff) + var x387 uint64 + var x388 uint64 + x388, x387 = bits.Mul64(x357, 0xffffffffffffffff) + var x389 uint64 + var x390 uint64 + x390, x389 = bits.Mul64(x357, 0xffffffffffffffff) + var x391 uint64 + var x392 uint64 + x392, x391 = bits.Mul64(x357, 0xffffffffffffffff) + var x393 uint64 + var x394 uint64 + x394, x393 = bits.Mul64(x357, 0xffffffffffffffff) + var x395 uint64 + var x396 uint64 + x395, x396 = bits.Add64(x394, x391, uint64(0x0)) + var x397 uint64 + var x398 uint64 + x397, x398 = bits.Add64(x392, x389, uint64(p521Uint1(x396))) + var x399 uint64 + var x400 uint64 + x399, x400 = bits.Add64(x390, x387, uint64(p521Uint1(x398))) + var x401 uint64 + var x402 uint64 + x401, x402 = bits.Add64(x388, x385, uint64(p521Uint1(x400))) + var x403 uint64 + var x404 uint64 + x403, x404 = bits.Add64(x386, x383, uint64(p521Uint1(x402))) + var x405 uint64 + var x406 uint64 + x405, x406 = bits.Add64(x384, x381, uint64(p521Uint1(x404))) + var x407 uint64 + var x408 uint64 + x407, x408 = bits.Add64(x382, x379, uint64(p521Uint1(x406))) + var x409 uint64 + var x410 uint64 + x409, x410 = bits.Add64(x380, x377, uint64(p521Uint1(x408))) + x411 := (uint64(p521Uint1(x410)) + x378) + var x413 uint64 + _, x413 = bits.Add64(x357, x393, uint64(0x0)) + var x414 uint64 + var x415 uint64 + x414, x415 = bits.Add64(x359, x395, uint64(p521Uint1(x413))) + var x416 uint64 + var x417 uint64 + x416, x417 = bits.Add64(x361, x397, uint64(p521Uint1(x415))) + var x418 uint64 + var x419 uint64 + x418, x419 = bits.Add64(x363, x399, uint64(p521Uint1(x417))) + var x420 uint64 + var x421 uint64 + x420, x421 = bits.Add64(x365, x401, uint64(p521Uint1(x419))) + var x422 uint64 + var x423 uint64 + x422, x423 = bits.Add64(x367, x403, uint64(p521Uint1(x421))) + var x424 uint64 + var x425 uint64 + x424, x425 = bits.Add64(x369, x405, uint64(p521Uint1(x423))) + var x426 uint64 + var x427 uint64 + x426, x427 = bits.Add64(x371, x407, uint64(p521Uint1(x425))) + var x428 uint64 + var x429 uint64 + x428, x429 = bits.Add64(x373, x409, uint64(p521Uint1(x427))) + var x430 uint64 + var x431 uint64 + x430, x431 = bits.Add64(x375, x411, uint64(p521Uint1(x429))) + x432 := (uint64(p521Uint1(x431)) + uint64(p521Uint1(x376))) + var x433 uint64 + var x434 uint64 + x434, x433 = bits.Mul64(x4, arg1[8]) + var x435 uint64 + var x436 uint64 + x436, x435 = bits.Mul64(x4, arg1[7]) + var x437 uint64 + var x438 uint64 + x438, x437 = bits.Mul64(x4, arg1[6]) + var x439 uint64 + var x440 uint64 + x440, x439 = bits.Mul64(x4, arg1[5]) + var x441 uint64 + var x442 uint64 + x442, x441 = bits.Mul64(x4, arg1[4]) + var x443 uint64 + var x444 uint64 + x444, x443 = bits.Mul64(x4, arg1[3]) + var x445 uint64 + var x446 uint64 + x446, x445 = bits.Mul64(x4, arg1[2]) + var x447 uint64 + var x448 uint64 + x448, x447 = bits.Mul64(x4, arg1[1]) + var x449 uint64 + var x450 uint64 + x450, x449 = bits.Mul64(x4, arg1[0]) + var x451 uint64 + var x452 uint64 + x451, x452 = bits.Add64(x450, x447, uint64(0x0)) + var x453 uint64 + var x454 uint64 + x453, x454 = bits.Add64(x448, x445, uint64(p521Uint1(x452))) + var x455 uint64 + var x456 uint64 + x455, x456 = bits.Add64(x446, x443, uint64(p521Uint1(x454))) + var x457 uint64 + var x458 uint64 + x457, x458 = bits.Add64(x444, x441, uint64(p521Uint1(x456))) + var x459 uint64 + var x460 uint64 + x459, x460 = bits.Add64(x442, x439, uint64(p521Uint1(x458))) + var x461 uint64 + var x462 uint64 + x461, x462 = bits.Add64(x440, x437, uint64(p521Uint1(x460))) + var x463 uint64 + var x464 uint64 + x463, x464 = bits.Add64(x438, x435, uint64(p521Uint1(x462))) + var x465 uint64 + var x466 uint64 + x465, x466 = bits.Add64(x436, x433, uint64(p521Uint1(x464))) + x467 := (uint64(p521Uint1(x466)) + x434) + var x468 uint64 + var x469 uint64 + x468, x469 = bits.Add64(x414, x449, uint64(0x0)) + var x470 uint64 + var x471 uint64 + x470, x471 = bits.Add64(x416, x451, uint64(p521Uint1(x469))) + var x472 uint64 + var x473 uint64 + x472, x473 = bits.Add64(x418, x453, uint64(p521Uint1(x471))) + var x474 uint64 + var x475 uint64 + x474, x475 = bits.Add64(x420, x455, uint64(p521Uint1(x473))) + var x476 uint64 + var x477 uint64 + x476, x477 = bits.Add64(x422, x457, uint64(p521Uint1(x475))) + var x478 uint64 + var x479 uint64 + x478, x479 = bits.Add64(x424, x459, uint64(p521Uint1(x477))) + var x480 uint64 + var x481 uint64 + x480, x481 = bits.Add64(x426, x461, uint64(p521Uint1(x479))) + var x482 uint64 + var x483 uint64 + x482, x483 = bits.Add64(x428, x463, uint64(p521Uint1(x481))) + var x484 uint64 + var x485 uint64 + x484, x485 = bits.Add64(x430, x465, uint64(p521Uint1(x483))) + var x486 uint64 + var x487 uint64 + x486, x487 = bits.Add64(x432, x467, uint64(p521Uint1(x485))) + var x488 uint64 + var x489 uint64 + x489, x488 = bits.Mul64(x468, 0x1ff) + var x490 uint64 + var x491 uint64 + x491, x490 = bits.Mul64(x468, 0xffffffffffffffff) + var x492 uint64 + var x493 uint64 + x493, x492 = bits.Mul64(x468, 0xffffffffffffffff) + var x494 uint64 + var x495 uint64 + x495, x494 = bits.Mul64(x468, 0xffffffffffffffff) + var x496 uint64 + var x497 uint64 + x497, x496 = bits.Mul64(x468, 0xffffffffffffffff) + var x498 uint64 + var x499 uint64 + x499, x498 = bits.Mul64(x468, 0xffffffffffffffff) + var x500 uint64 + var x501 uint64 + x501, x500 = bits.Mul64(x468, 0xffffffffffffffff) + var x502 uint64 + var x503 uint64 + x503, x502 = bits.Mul64(x468, 0xffffffffffffffff) + var x504 uint64 + var x505 uint64 + x505, x504 = bits.Mul64(x468, 0xffffffffffffffff) + var x506 uint64 + var x507 uint64 + x506, x507 = bits.Add64(x505, x502, uint64(0x0)) + var x508 uint64 + var x509 uint64 + x508, x509 = bits.Add64(x503, x500, uint64(p521Uint1(x507))) + var x510 uint64 + var x511 uint64 + x510, x511 = bits.Add64(x501, x498, uint64(p521Uint1(x509))) + var x512 uint64 + var x513 uint64 + x512, x513 = bits.Add64(x499, x496, uint64(p521Uint1(x511))) + var x514 uint64 + var x515 uint64 + x514, x515 = bits.Add64(x497, x494, uint64(p521Uint1(x513))) + var x516 uint64 + var x517 uint64 + x516, x517 = bits.Add64(x495, x492, uint64(p521Uint1(x515))) + var x518 uint64 + var x519 uint64 + x518, x519 = bits.Add64(x493, x490, uint64(p521Uint1(x517))) + var x520 uint64 + var x521 uint64 + x520, x521 = bits.Add64(x491, x488, uint64(p521Uint1(x519))) + x522 := (uint64(p521Uint1(x521)) + x489) + var x524 uint64 + _, x524 = bits.Add64(x468, x504, uint64(0x0)) + var x525 uint64 + var x526 uint64 + x525, x526 = bits.Add64(x470, x506, uint64(p521Uint1(x524))) + var x527 uint64 + var x528 uint64 + x527, x528 = bits.Add64(x472, x508, uint64(p521Uint1(x526))) + var x529 uint64 + var x530 uint64 + x529, x530 = bits.Add64(x474, x510, uint64(p521Uint1(x528))) + var x531 uint64 + var x532 uint64 + x531, x532 = bits.Add64(x476, x512, uint64(p521Uint1(x530))) + var x533 uint64 + var x534 uint64 + x533, x534 = bits.Add64(x478, x514, uint64(p521Uint1(x532))) + var x535 uint64 + var x536 uint64 + x535, x536 = bits.Add64(x480, x516, uint64(p521Uint1(x534))) + var x537 uint64 + var x538 uint64 + x537, x538 = bits.Add64(x482, x518, uint64(p521Uint1(x536))) + var x539 uint64 + var x540 uint64 + x539, x540 = bits.Add64(x484, x520, uint64(p521Uint1(x538))) + var x541 uint64 + var x542 uint64 + x541, x542 = bits.Add64(x486, x522, uint64(p521Uint1(x540))) + x543 := (uint64(p521Uint1(x542)) + uint64(p521Uint1(x487))) + var x544 uint64 + var x545 uint64 + x545, x544 = bits.Mul64(x5, arg1[8]) + var x546 uint64 + var x547 uint64 + x547, x546 = bits.Mul64(x5, arg1[7]) + var x548 uint64 + var x549 uint64 + x549, x548 = bits.Mul64(x5, arg1[6]) + var x550 uint64 + var x551 uint64 + x551, x550 = bits.Mul64(x5, arg1[5]) + var x552 uint64 + var x553 uint64 + x553, x552 = bits.Mul64(x5, arg1[4]) + var x554 uint64 + var x555 uint64 + x555, x554 = bits.Mul64(x5, arg1[3]) + var x556 uint64 + var x557 uint64 + x557, x556 = bits.Mul64(x5, arg1[2]) + var x558 uint64 + var x559 uint64 + x559, x558 = bits.Mul64(x5, arg1[1]) + var x560 uint64 + var x561 uint64 + x561, x560 = bits.Mul64(x5, arg1[0]) + var x562 uint64 + var x563 uint64 + x562, x563 = bits.Add64(x561, x558, uint64(0x0)) + var x564 uint64 + var x565 uint64 + x564, x565 = bits.Add64(x559, x556, uint64(p521Uint1(x563))) + var x566 uint64 + var x567 uint64 + x566, x567 = bits.Add64(x557, x554, uint64(p521Uint1(x565))) + var x568 uint64 + var x569 uint64 + x568, x569 = bits.Add64(x555, x552, uint64(p521Uint1(x567))) + var x570 uint64 + var x571 uint64 + x570, x571 = bits.Add64(x553, x550, uint64(p521Uint1(x569))) + var x572 uint64 + var x573 uint64 + x572, x573 = bits.Add64(x551, x548, uint64(p521Uint1(x571))) + var x574 uint64 + var x575 uint64 + x574, x575 = bits.Add64(x549, x546, uint64(p521Uint1(x573))) + var x576 uint64 + var x577 uint64 + x576, x577 = bits.Add64(x547, x544, uint64(p521Uint1(x575))) + x578 := (uint64(p521Uint1(x577)) + x545) + var x579 uint64 + var x580 uint64 + x579, x580 = bits.Add64(x525, x560, uint64(0x0)) + var x581 uint64 + var x582 uint64 + x581, x582 = bits.Add64(x527, x562, uint64(p521Uint1(x580))) + var x583 uint64 + var x584 uint64 + x583, x584 = bits.Add64(x529, x564, uint64(p521Uint1(x582))) + var x585 uint64 + var x586 uint64 + x585, x586 = bits.Add64(x531, x566, uint64(p521Uint1(x584))) + var x587 uint64 + var x588 uint64 + x587, x588 = bits.Add64(x533, x568, uint64(p521Uint1(x586))) + var x589 uint64 + var x590 uint64 + x589, x590 = bits.Add64(x535, x570, uint64(p521Uint1(x588))) + var x591 uint64 + var x592 uint64 + x591, x592 = bits.Add64(x537, x572, uint64(p521Uint1(x590))) + var x593 uint64 + var x594 uint64 + x593, x594 = bits.Add64(x539, x574, uint64(p521Uint1(x592))) + var x595 uint64 + var x596 uint64 + x595, x596 = bits.Add64(x541, x576, uint64(p521Uint1(x594))) + var x597 uint64 + var x598 uint64 + x597, x598 = bits.Add64(x543, x578, uint64(p521Uint1(x596))) + var x599 uint64 + var x600 uint64 + x600, x599 = bits.Mul64(x579, 0x1ff) + var x601 uint64 + var x602 uint64 + x602, x601 = bits.Mul64(x579, 0xffffffffffffffff) + var x603 uint64 + var x604 uint64 + x604, x603 = bits.Mul64(x579, 0xffffffffffffffff) + var x605 uint64 + var x606 uint64 + x606, x605 = bits.Mul64(x579, 0xffffffffffffffff) + var x607 uint64 + var x608 uint64 + x608, x607 = bits.Mul64(x579, 0xffffffffffffffff) + var x609 uint64 + var x610 uint64 + x610, x609 = bits.Mul64(x579, 0xffffffffffffffff) + var x611 uint64 + var x612 uint64 + x612, x611 = bits.Mul64(x579, 0xffffffffffffffff) + var x613 uint64 + var x614 uint64 + x614, x613 = bits.Mul64(x579, 0xffffffffffffffff) + var x615 uint64 + var x616 uint64 + x616, x615 = bits.Mul64(x579, 0xffffffffffffffff) + var x617 uint64 + var x618 uint64 + x617, x618 = bits.Add64(x616, x613, uint64(0x0)) + var x619 uint64 + var x620 uint64 + x619, x620 = bits.Add64(x614, x611, uint64(p521Uint1(x618))) + var x621 uint64 + var x622 uint64 + x621, x622 = bits.Add64(x612, x609, uint64(p521Uint1(x620))) + var x623 uint64 + var x624 uint64 + x623, x624 = bits.Add64(x610, x607, uint64(p521Uint1(x622))) + var x625 uint64 + var x626 uint64 + x625, x626 = bits.Add64(x608, x605, uint64(p521Uint1(x624))) + var x627 uint64 + var x628 uint64 + x627, x628 = bits.Add64(x606, x603, uint64(p521Uint1(x626))) + var x629 uint64 + var x630 uint64 + x629, x630 = bits.Add64(x604, x601, uint64(p521Uint1(x628))) + var x631 uint64 + var x632 uint64 + x631, x632 = bits.Add64(x602, x599, uint64(p521Uint1(x630))) + x633 := (uint64(p521Uint1(x632)) + x600) + var x635 uint64 + _, x635 = bits.Add64(x579, x615, uint64(0x0)) + var x636 uint64 + var x637 uint64 + x636, x637 = bits.Add64(x581, x617, uint64(p521Uint1(x635))) + var x638 uint64 + var x639 uint64 + x638, x639 = bits.Add64(x583, x619, uint64(p521Uint1(x637))) + var x640 uint64 + var x641 uint64 + x640, x641 = bits.Add64(x585, x621, uint64(p521Uint1(x639))) + var x642 uint64 + var x643 uint64 + x642, x643 = bits.Add64(x587, x623, uint64(p521Uint1(x641))) + var x644 uint64 + var x645 uint64 + x644, x645 = bits.Add64(x589, x625, uint64(p521Uint1(x643))) + var x646 uint64 + var x647 uint64 + x646, x647 = bits.Add64(x591, x627, uint64(p521Uint1(x645))) + var x648 uint64 + var x649 uint64 + x648, x649 = bits.Add64(x593, x629, uint64(p521Uint1(x647))) + var x650 uint64 + var x651 uint64 + x650, x651 = bits.Add64(x595, x631, uint64(p521Uint1(x649))) + var x652 uint64 + var x653 uint64 + x652, x653 = bits.Add64(x597, x633, uint64(p521Uint1(x651))) + x654 := (uint64(p521Uint1(x653)) + uint64(p521Uint1(x598))) + var x655 uint64 + var x656 uint64 + x656, x655 = bits.Mul64(x6, arg1[8]) + var x657 uint64 + var x658 uint64 + x658, x657 = bits.Mul64(x6, arg1[7]) + var x659 uint64 + var x660 uint64 + x660, x659 = bits.Mul64(x6, arg1[6]) + var x661 uint64 + var x662 uint64 + x662, x661 = bits.Mul64(x6, arg1[5]) + var x663 uint64 + var x664 uint64 + x664, x663 = bits.Mul64(x6, arg1[4]) + var x665 uint64 + var x666 uint64 + x666, x665 = bits.Mul64(x6, arg1[3]) + var x667 uint64 + var x668 uint64 + x668, x667 = bits.Mul64(x6, arg1[2]) + var x669 uint64 + var x670 uint64 + x670, x669 = bits.Mul64(x6, arg1[1]) + var x671 uint64 + var x672 uint64 + x672, x671 = bits.Mul64(x6, arg1[0]) + var x673 uint64 + var x674 uint64 + x673, x674 = bits.Add64(x672, x669, uint64(0x0)) + var x675 uint64 + var x676 uint64 + x675, x676 = bits.Add64(x670, x667, uint64(p521Uint1(x674))) + var x677 uint64 + var x678 uint64 + x677, x678 = bits.Add64(x668, x665, uint64(p521Uint1(x676))) + var x679 uint64 + var x680 uint64 + x679, x680 = bits.Add64(x666, x663, uint64(p521Uint1(x678))) + var x681 uint64 + var x682 uint64 + x681, x682 = bits.Add64(x664, x661, uint64(p521Uint1(x680))) + var x683 uint64 + var x684 uint64 + x683, x684 = bits.Add64(x662, x659, uint64(p521Uint1(x682))) + var x685 uint64 + var x686 uint64 + x685, x686 = bits.Add64(x660, x657, uint64(p521Uint1(x684))) + var x687 uint64 + var x688 uint64 + x687, x688 = bits.Add64(x658, x655, uint64(p521Uint1(x686))) + x689 := (uint64(p521Uint1(x688)) + x656) + var x690 uint64 + var x691 uint64 + x690, x691 = bits.Add64(x636, x671, uint64(0x0)) + var x692 uint64 + var x693 uint64 + x692, x693 = bits.Add64(x638, x673, uint64(p521Uint1(x691))) + var x694 uint64 + var x695 uint64 + x694, x695 = bits.Add64(x640, x675, uint64(p521Uint1(x693))) + var x696 uint64 + var x697 uint64 + x696, x697 = bits.Add64(x642, x677, uint64(p521Uint1(x695))) + var x698 uint64 + var x699 uint64 + x698, x699 = bits.Add64(x644, x679, uint64(p521Uint1(x697))) + var x700 uint64 + var x701 uint64 + x700, x701 = bits.Add64(x646, x681, uint64(p521Uint1(x699))) + var x702 uint64 + var x703 uint64 + x702, x703 = bits.Add64(x648, x683, uint64(p521Uint1(x701))) + var x704 uint64 + var x705 uint64 + x704, x705 = bits.Add64(x650, x685, uint64(p521Uint1(x703))) + var x706 uint64 + var x707 uint64 + x706, x707 = bits.Add64(x652, x687, uint64(p521Uint1(x705))) + var x708 uint64 + var x709 uint64 + x708, x709 = bits.Add64(x654, x689, uint64(p521Uint1(x707))) + var x710 uint64 + var x711 uint64 + x711, x710 = bits.Mul64(x690, 0x1ff) + var x712 uint64 + var x713 uint64 + x713, x712 = bits.Mul64(x690, 0xffffffffffffffff) + var x714 uint64 + var x715 uint64 + x715, x714 = bits.Mul64(x690, 0xffffffffffffffff) + var x716 uint64 + var x717 uint64 + x717, x716 = bits.Mul64(x690, 0xffffffffffffffff) + var x718 uint64 + var x719 uint64 + x719, x718 = bits.Mul64(x690, 0xffffffffffffffff) + var x720 uint64 + var x721 uint64 + x721, x720 = bits.Mul64(x690, 0xffffffffffffffff) + var x722 uint64 + var x723 uint64 + x723, x722 = bits.Mul64(x690, 0xffffffffffffffff) + var x724 uint64 + var x725 uint64 + x725, x724 = bits.Mul64(x690, 0xffffffffffffffff) + var x726 uint64 + var x727 uint64 + x727, x726 = bits.Mul64(x690, 0xffffffffffffffff) + var x728 uint64 + var x729 uint64 + x728, x729 = bits.Add64(x727, x724, uint64(0x0)) + var x730 uint64 + var x731 uint64 + x730, x731 = bits.Add64(x725, x722, uint64(p521Uint1(x729))) + var x732 uint64 + var x733 uint64 + x732, x733 = bits.Add64(x723, x720, uint64(p521Uint1(x731))) + var x734 uint64 + var x735 uint64 + x734, x735 = bits.Add64(x721, x718, uint64(p521Uint1(x733))) + var x736 uint64 + var x737 uint64 + x736, x737 = bits.Add64(x719, x716, uint64(p521Uint1(x735))) + var x738 uint64 + var x739 uint64 + x738, x739 = bits.Add64(x717, x714, uint64(p521Uint1(x737))) + var x740 uint64 + var x741 uint64 + x740, x741 = bits.Add64(x715, x712, uint64(p521Uint1(x739))) + var x742 uint64 + var x743 uint64 + x742, x743 = bits.Add64(x713, x710, uint64(p521Uint1(x741))) + x744 := (uint64(p521Uint1(x743)) + x711) + var x746 uint64 + _, x746 = bits.Add64(x690, x726, uint64(0x0)) + var x747 uint64 + var x748 uint64 + x747, x748 = bits.Add64(x692, x728, uint64(p521Uint1(x746))) + var x749 uint64 + var x750 uint64 + x749, x750 = bits.Add64(x694, x730, uint64(p521Uint1(x748))) + var x751 uint64 + var x752 uint64 + x751, x752 = bits.Add64(x696, x732, uint64(p521Uint1(x750))) + var x753 uint64 + var x754 uint64 + x753, x754 = bits.Add64(x698, x734, uint64(p521Uint1(x752))) + var x755 uint64 + var x756 uint64 + x755, x756 = bits.Add64(x700, x736, uint64(p521Uint1(x754))) + var x757 uint64 + var x758 uint64 + x757, x758 = bits.Add64(x702, x738, uint64(p521Uint1(x756))) + var x759 uint64 + var x760 uint64 + x759, x760 = bits.Add64(x704, x740, uint64(p521Uint1(x758))) + var x761 uint64 + var x762 uint64 + x761, x762 = bits.Add64(x706, x742, uint64(p521Uint1(x760))) + var x763 uint64 + var x764 uint64 + x763, x764 = bits.Add64(x708, x744, uint64(p521Uint1(x762))) + x765 := (uint64(p521Uint1(x764)) + uint64(p521Uint1(x709))) + var x766 uint64 + var x767 uint64 + x767, x766 = bits.Mul64(x7, arg1[8]) + var x768 uint64 + var x769 uint64 + x769, x768 = bits.Mul64(x7, arg1[7]) + var x770 uint64 + var x771 uint64 + x771, x770 = bits.Mul64(x7, arg1[6]) + var x772 uint64 + var x773 uint64 + x773, x772 = bits.Mul64(x7, arg1[5]) + var x774 uint64 + var x775 uint64 + x775, x774 = bits.Mul64(x7, arg1[4]) + var x776 uint64 + var x777 uint64 + x777, x776 = bits.Mul64(x7, arg1[3]) + var x778 uint64 + var x779 uint64 + x779, x778 = bits.Mul64(x7, arg1[2]) + var x780 uint64 + var x781 uint64 + x781, x780 = bits.Mul64(x7, arg1[1]) + var x782 uint64 + var x783 uint64 + x783, x782 = bits.Mul64(x7, arg1[0]) + var x784 uint64 + var x785 uint64 + x784, x785 = bits.Add64(x783, x780, uint64(0x0)) + var x786 uint64 + var x787 uint64 + x786, x787 = bits.Add64(x781, x778, uint64(p521Uint1(x785))) + var x788 uint64 + var x789 uint64 + x788, x789 = bits.Add64(x779, x776, uint64(p521Uint1(x787))) + var x790 uint64 + var x791 uint64 + x790, x791 = bits.Add64(x777, x774, uint64(p521Uint1(x789))) + var x792 uint64 + var x793 uint64 + x792, x793 = bits.Add64(x775, x772, uint64(p521Uint1(x791))) + var x794 uint64 + var x795 uint64 + x794, x795 = bits.Add64(x773, x770, uint64(p521Uint1(x793))) + var x796 uint64 + var x797 uint64 + x796, x797 = bits.Add64(x771, x768, uint64(p521Uint1(x795))) + var x798 uint64 + var x799 uint64 + x798, x799 = bits.Add64(x769, x766, uint64(p521Uint1(x797))) + x800 := (uint64(p521Uint1(x799)) + x767) + var x801 uint64 + var x802 uint64 + x801, x802 = bits.Add64(x747, x782, uint64(0x0)) + var x803 uint64 + var x804 uint64 + x803, x804 = bits.Add64(x749, x784, uint64(p521Uint1(x802))) + var x805 uint64 + var x806 uint64 + x805, x806 = bits.Add64(x751, x786, uint64(p521Uint1(x804))) + var x807 uint64 + var x808 uint64 + x807, x808 = bits.Add64(x753, x788, uint64(p521Uint1(x806))) + var x809 uint64 + var x810 uint64 + x809, x810 = bits.Add64(x755, x790, uint64(p521Uint1(x808))) + var x811 uint64 + var x812 uint64 + x811, x812 = bits.Add64(x757, x792, uint64(p521Uint1(x810))) + var x813 uint64 + var x814 uint64 + x813, x814 = bits.Add64(x759, x794, uint64(p521Uint1(x812))) + var x815 uint64 + var x816 uint64 + x815, x816 = bits.Add64(x761, x796, uint64(p521Uint1(x814))) + var x817 uint64 + var x818 uint64 + x817, x818 = bits.Add64(x763, x798, uint64(p521Uint1(x816))) + var x819 uint64 + var x820 uint64 + x819, x820 = bits.Add64(x765, x800, uint64(p521Uint1(x818))) + var x821 uint64 + var x822 uint64 + x822, x821 = bits.Mul64(x801, 0x1ff) + var x823 uint64 + var x824 uint64 + x824, x823 = bits.Mul64(x801, 0xffffffffffffffff) + var x825 uint64 + var x826 uint64 + x826, x825 = bits.Mul64(x801, 0xffffffffffffffff) + var x827 uint64 + var x828 uint64 + x828, x827 = bits.Mul64(x801, 0xffffffffffffffff) + var x829 uint64 + var x830 uint64 + x830, x829 = bits.Mul64(x801, 0xffffffffffffffff) + var x831 uint64 + var x832 uint64 + x832, x831 = bits.Mul64(x801, 0xffffffffffffffff) + var x833 uint64 + var x834 uint64 + x834, x833 = bits.Mul64(x801, 0xffffffffffffffff) + var x835 uint64 + var x836 uint64 + x836, x835 = bits.Mul64(x801, 0xffffffffffffffff) + var x837 uint64 + var x838 uint64 + x838, x837 = bits.Mul64(x801, 0xffffffffffffffff) + var x839 uint64 + var x840 uint64 + x839, x840 = bits.Add64(x838, x835, uint64(0x0)) + var x841 uint64 + var x842 uint64 + x841, x842 = bits.Add64(x836, x833, uint64(p521Uint1(x840))) + var x843 uint64 + var x844 uint64 + x843, x844 = bits.Add64(x834, x831, uint64(p521Uint1(x842))) + var x845 uint64 + var x846 uint64 + x845, x846 = bits.Add64(x832, x829, uint64(p521Uint1(x844))) + var x847 uint64 + var x848 uint64 + x847, x848 = bits.Add64(x830, x827, uint64(p521Uint1(x846))) + var x849 uint64 + var x850 uint64 + x849, x850 = bits.Add64(x828, x825, uint64(p521Uint1(x848))) + var x851 uint64 + var x852 uint64 + x851, x852 = bits.Add64(x826, x823, uint64(p521Uint1(x850))) + var x853 uint64 + var x854 uint64 + x853, x854 = bits.Add64(x824, x821, uint64(p521Uint1(x852))) + x855 := (uint64(p521Uint1(x854)) + x822) + var x857 uint64 + _, x857 = bits.Add64(x801, x837, uint64(0x0)) + var x858 uint64 + var x859 uint64 + x858, x859 = bits.Add64(x803, x839, uint64(p521Uint1(x857))) + var x860 uint64 + var x861 uint64 + x860, x861 = bits.Add64(x805, x841, uint64(p521Uint1(x859))) + var x862 uint64 + var x863 uint64 + x862, x863 = bits.Add64(x807, x843, uint64(p521Uint1(x861))) + var x864 uint64 + var x865 uint64 + x864, x865 = bits.Add64(x809, x845, uint64(p521Uint1(x863))) + var x866 uint64 + var x867 uint64 + x866, x867 = bits.Add64(x811, x847, uint64(p521Uint1(x865))) + var x868 uint64 + var x869 uint64 + x868, x869 = bits.Add64(x813, x849, uint64(p521Uint1(x867))) + var x870 uint64 + var x871 uint64 + x870, x871 = bits.Add64(x815, x851, uint64(p521Uint1(x869))) + var x872 uint64 + var x873 uint64 + x872, x873 = bits.Add64(x817, x853, uint64(p521Uint1(x871))) + var x874 uint64 + var x875 uint64 + x874, x875 = bits.Add64(x819, x855, uint64(p521Uint1(x873))) + x876 := (uint64(p521Uint1(x875)) + uint64(p521Uint1(x820))) + var x877 uint64 + var x878 uint64 + x878, x877 = bits.Mul64(x8, arg1[8]) + var x879 uint64 + var x880 uint64 + x880, x879 = bits.Mul64(x8, arg1[7]) + var x881 uint64 + var x882 uint64 + x882, x881 = bits.Mul64(x8, arg1[6]) + var x883 uint64 + var x884 uint64 + x884, x883 = bits.Mul64(x8, arg1[5]) + var x885 uint64 + var x886 uint64 + x886, x885 = bits.Mul64(x8, arg1[4]) + var x887 uint64 + var x888 uint64 + x888, x887 = bits.Mul64(x8, arg1[3]) + var x889 uint64 + var x890 uint64 + x890, x889 = bits.Mul64(x8, arg1[2]) + var x891 uint64 + var x892 uint64 + x892, x891 = bits.Mul64(x8, arg1[1]) + var x893 uint64 + var x894 uint64 + x894, x893 = bits.Mul64(x8, arg1[0]) + var x895 uint64 + var x896 uint64 + x895, x896 = bits.Add64(x894, x891, uint64(0x0)) + var x897 uint64 + var x898 uint64 + x897, x898 = bits.Add64(x892, x889, uint64(p521Uint1(x896))) + var x899 uint64 + var x900 uint64 + x899, x900 = bits.Add64(x890, x887, uint64(p521Uint1(x898))) + var x901 uint64 + var x902 uint64 + x901, x902 = bits.Add64(x888, x885, uint64(p521Uint1(x900))) + var x903 uint64 + var x904 uint64 + x903, x904 = bits.Add64(x886, x883, uint64(p521Uint1(x902))) + var x905 uint64 + var x906 uint64 + x905, x906 = bits.Add64(x884, x881, uint64(p521Uint1(x904))) + var x907 uint64 + var x908 uint64 + x907, x908 = bits.Add64(x882, x879, uint64(p521Uint1(x906))) + var x909 uint64 + var x910 uint64 + x909, x910 = bits.Add64(x880, x877, uint64(p521Uint1(x908))) + x911 := (uint64(p521Uint1(x910)) + x878) + var x912 uint64 + var x913 uint64 + x912, x913 = bits.Add64(x858, x893, uint64(0x0)) + var x914 uint64 + var x915 uint64 + x914, x915 = bits.Add64(x860, x895, uint64(p521Uint1(x913))) + var x916 uint64 + var x917 uint64 + x916, x917 = bits.Add64(x862, x897, uint64(p521Uint1(x915))) + var x918 uint64 + var x919 uint64 + x918, x919 = bits.Add64(x864, x899, uint64(p521Uint1(x917))) + var x920 uint64 + var x921 uint64 + x920, x921 = bits.Add64(x866, x901, uint64(p521Uint1(x919))) + var x922 uint64 + var x923 uint64 + x922, x923 = bits.Add64(x868, x903, uint64(p521Uint1(x921))) + var x924 uint64 + var x925 uint64 + x924, x925 = bits.Add64(x870, x905, uint64(p521Uint1(x923))) + var x926 uint64 + var x927 uint64 + x926, x927 = bits.Add64(x872, x907, uint64(p521Uint1(x925))) + var x928 uint64 + var x929 uint64 + x928, x929 = bits.Add64(x874, x909, uint64(p521Uint1(x927))) + var x930 uint64 + var x931 uint64 + x930, x931 = bits.Add64(x876, x911, uint64(p521Uint1(x929))) + var x932 uint64 + var x933 uint64 + x933, x932 = bits.Mul64(x912, 0x1ff) + var x934 uint64 + var x935 uint64 + x935, x934 = bits.Mul64(x912, 0xffffffffffffffff) + var x936 uint64 + var x937 uint64 + x937, x936 = bits.Mul64(x912, 0xffffffffffffffff) + var x938 uint64 + var x939 uint64 + x939, x938 = bits.Mul64(x912, 0xffffffffffffffff) + var x940 uint64 + var x941 uint64 + x941, x940 = bits.Mul64(x912, 0xffffffffffffffff) + var x942 uint64 + var x943 uint64 + x943, x942 = bits.Mul64(x912, 0xffffffffffffffff) + var x944 uint64 + var x945 uint64 + x945, x944 = bits.Mul64(x912, 0xffffffffffffffff) + var x946 uint64 + var x947 uint64 + x947, x946 = bits.Mul64(x912, 0xffffffffffffffff) + var x948 uint64 + var x949 uint64 + x949, x948 = bits.Mul64(x912, 0xffffffffffffffff) + var x950 uint64 + var x951 uint64 + x950, x951 = bits.Add64(x949, x946, uint64(0x0)) + var x952 uint64 + var x953 uint64 + x952, x953 = bits.Add64(x947, x944, uint64(p521Uint1(x951))) + var x954 uint64 + var x955 uint64 + x954, x955 = bits.Add64(x945, x942, uint64(p521Uint1(x953))) + var x956 uint64 + var x957 uint64 + x956, x957 = bits.Add64(x943, x940, uint64(p521Uint1(x955))) + var x958 uint64 + var x959 uint64 + x958, x959 = bits.Add64(x941, x938, uint64(p521Uint1(x957))) + var x960 uint64 + var x961 uint64 + x960, x961 = bits.Add64(x939, x936, uint64(p521Uint1(x959))) + var x962 uint64 + var x963 uint64 + x962, x963 = bits.Add64(x937, x934, uint64(p521Uint1(x961))) + var x964 uint64 + var x965 uint64 + x964, x965 = bits.Add64(x935, x932, uint64(p521Uint1(x963))) + x966 := (uint64(p521Uint1(x965)) + x933) + var x968 uint64 + _, x968 = bits.Add64(x912, x948, uint64(0x0)) + var x969 uint64 + var x970 uint64 + x969, x970 = bits.Add64(x914, x950, uint64(p521Uint1(x968))) + var x971 uint64 + var x972 uint64 + x971, x972 = bits.Add64(x916, x952, uint64(p521Uint1(x970))) + var x973 uint64 + var x974 uint64 + x973, x974 = bits.Add64(x918, x954, uint64(p521Uint1(x972))) + var x975 uint64 + var x976 uint64 + x975, x976 = bits.Add64(x920, x956, uint64(p521Uint1(x974))) + var x977 uint64 + var x978 uint64 + x977, x978 = bits.Add64(x922, x958, uint64(p521Uint1(x976))) + var x979 uint64 + var x980 uint64 + x979, x980 = bits.Add64(x924, x960, uint64(p521Uint1(x978))) + var x981 uint64 + var x982 uint64 + x981, x982 = bits.Add64(x926, x962, uint64(p521Uint1(x980))) + var x983 uint64 + var x984 uint64 + x983, x984 = bits.Add64(x928, x964, uint64(p521Uint1(x982))) + var x985 uint64 + var x986 uint64 + x985, x986 = bits.Add64(x930, x966, uint64(p521Uint1(x984))) + x987 := (uint64(p521Uint1(x986)) + uint64(p521Uint1(x931))) + var x988 uint64 + var x989 uint64 + x988, x989 = bits.Sub64(x969, 0xffffffffffffffff, uint64(0x0)) + var x990 uint64 + var x991 uint64 + x990, x991 = bits.Sub64(x971, 0xffffffffffffffff, uint64(p521Uint1(x989))) + var x992 uint64 + var x993 uint64 + x992, x993 = bits.Sub64(x973, 0xffffffffffffffff, uint64(p521Uint1(x991))) + var x994 uint64 + var x995 uint64 + x994, x995 = bits.Sub64(x975, 0xffffffffffffffff, uint64(p521Uint1(x993))) + var x996 uint64 + var x997 uint64 + x996, x997 = bits.Sub64(x977, 0xffffffffffffffff, uint64(p521Uint1(x995))) + var x998 uint64 + var x999 uint64 + x998, x999 = bits.Sub64(x979, 0xffffffffffffffff, uint64(p521Uint1(x997))) + var x1000 uint64 + var x1001 uint64 + x1000, x1001 = bits.Sub64(x981, 0xffffffffffffffff, uint64(p521Uint1(x999))) + var x1002 uint64 + var x1003 uint64 + x1002, x1003 = bits.Sub64(x983, 0xffffffffffffffff, uint64(p521Uint1(x1001))) + var x1004 uint64 + var x1005 uint64 + x1004, x1005 = bits.Sub64(x985, 0x1ff, uint64(p521Uint1(x1003))) + var x1007 uint64 + _, x1007 = bits.Sub64(x987, uint64(0x0), uint64(p521Uint1(x1005))) + var x1008 uint64 + p521CmovznzU64(&x1008, p521Uint1(x1007), x988, x969) + var x1009 uint64 + p521CmovznzU64(&x1009, p521Uint1(x1007), x990, x971) + var x1010 uint64 + p521CmovznzU64(&x1010, p521Uint1(x1007), x992, x973) + var x1011 uint64 + p521CmovznzU64(&x1011, p521Uint1(x1007), x994, x975) + var x1012 uint64 + p521CmovznzU64(&x1012, p521Uint1(x1007), x996, x977) + var x1013 uint64 + p521CmovznzU64(&x1013, p521Uint1(x1007), x998, x979) + var x1014 uint64 + p521CmovznzU64(&x1014, p521Uint1(x1007), x1000, x981) + var x1015 uint64 + p521CmovznzU64(&x1015, p521Uint1(x1007), x1002, x983) + var x1016 uint64 + p521CmovznzU64(&x1016, p521Uint1(x1007), x1004, x985) + out1[0] = x1008 + out1[1] = x1009 + out1[2] = x1010 + out1[3] = x1011 + out1[4] = x1012 + out1[5] = x1013 + out1[6] = x1014 + out1[7] = x1015 + out1[8] = x1016 } -// p521Carry reduces a field element. +// p521Add adds two field elements in the Montgomery domain. // +// Preconditions: +// 0 ≤ eval arg1 < m +// 0 ≤ eval arg2 < m // Postconditions: -// eval out1 mod m = eval arg1 mod m +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m +// 0 ≤ eval out1 < m // -// Input Bounds: -// arg1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]] -// Output Bounds: -// out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] -func p521Carry(out1 *[9]uint64, arg1 *[9]uint64) { - x1 := arg1[0] - x2 := ((x1 >> 58) + arg1[1]) - x3 := ((x2 >> 58) + arg1[2]) - x4 := ((x3 >> 58) + arg1[3]) - x5 := ((x4 >> 58) + arg1[4]) - x6 := ((x5 >> 58) + arg1[5]) - x7 := ((x6 >> 58) + arg1[6]) - x8 := ((x7 >> 58) + arg1[7]) - x9 := ((x8 >> 58) + arg1[8]) - x10 := ((x1 & 0x3ffffffffffffff) + (x9 >> 57)) - x11 := (uint64(p521Uint1((x10 >> 58))) + (x2 & 0x3ffffffffffffff)) - x12 := (x10 & 0x3ffffffffffffff) - x13 := (x11 & 0x3ffffffffffffff) - x14 := (uint64(p521Uint1((x11 >> 58))) + (x3 & 0x3ffffffffffffff)) - x15 := (x4 & 0x3ffffffffffffff) - x16 := (x5 & 0x3ffffffffffffff) - x17 := (x6 & 0x3ffffffffffffff) - x18 := (x7 & 0x3ffffffffffffff) - x19 := (x8 & 0x3ffffffffffffff) - x20 := (x9 & 0x1ffffffffffffff) - out1[0] = x12 - out1[1] = x13 - out1[2] = x14 - out1[3] = x15 - out1[4] = x16 - out1[5] = x17 - out1[6] = x18 - out1[7] = x19 - out1[8] = x20 -} +func p521Add(out1 *p521MontgomeryDomainFieldElement, arg1 *p521MontgomeryDomainFieldElement, arg2 *p521MontgomeryDomainFieldElement) { + var x1 uint64 + var x2 uint64 + x1, x2 = bits.Add64(arg1[0], arg2[0], uint64(0x0)) + var x3 uint64 + var x4 uint64 + x3, x4 = bits.Add64(arg1[1], arg2[1], uint64(p521Uint1(x2))) + var x5 uint64 + var x6 uint64 + x5, x6 = bits.Add64(arg1[2], arg2[2], uint64(p521Uint1(x4))) + var x7 uint64 + var x8 uint64 + x7, x8 = bits.Add64(arg1[3], arg2[3], uint64(p521Uint1(x6))) + var x9 uint64 + var x10 uint64 + x9, x10 = bits.Add64(arg1[4], arg2[4], uint64(p521Uint1(x8))) + var x11 uint64 + var x12 uint64 + x11, x12 = bits.Add64(arg1[5], arg2[5], uint64(p521Uint1(x10))) + var x13 uint64 + var x14 uint64 + x13, x14 = bits.Add64(arg1[6], arg2[6], uint64(p521Uint1(x12))) + var x15 uint64 + var x16 uint64 + x15, x16 = bits.Add64(arg1[7], arg2[7], uint64(p521Uint1(x14))) + var x17 uint64 + var x18 uint64 + x17, x18 = bits.Add64(arg1[8], arg2[8], uint64(p521Uint1(x16))) + var x19 uint64 + var x20 uint64 + x19, x20 = bits.Sub64(x1, 0xffffffffffffffff, uint64(0x0)) + var x21 uint64 + var x22 uint64 + x21, x22 = bits.Sub64(x3, 0xffffffffffffffff, uint64(p521Uint1(x20))) + var x23 uint64 + var x24 uint64 + x23, x24 = bits.Sub64(x5, 0xffffffffffffffff, uint64(p521Uint1(x22))) + var x25 uint64 + var x26 uint64 + x25, x26 = bits.Sub64(x7, 0xffffffffffffffff, uint64(p521Uint1(x24))) + var x27 uint64 + var x28 uint64 + x27, x28 = bits.Sub64(x9, 0xffffffffffffffff, uint64(p521Uint1(x26))) + var x29 uint64 + var x30 uint64 + x29, x30 = bits.Sub64(x11, 0xffffffffffffffff, uint64(p521Uint1(x28))) + var x31 uint64 + var x32 uint64 + x31, x32 = bits.Sub64(x13, 0xffffffffffffffff, uint64(p521Uint1(x30))) + var x33 uint64 + var x34 uint64 + x33, x34 = bits.Sub64(x15, 0xffffffffffffffff, uint64(p521Uint1(x32))) + var x35 uint64 + var x36 uint64 + x35, x36 = bits.Sub64(x17, 0x1ff, uint64(p521Uint1(x34))) + var x38 uint64 + _, x38 = bits.Sub64(uint64(p521Uint1(x18)), uint64(0x0), uint64(p521Uint1(x36))) + var x39 uint64 + p521CmovznzU64(&x39, p521Uint1(x38), x19, x1) + var x40 uint64 + p521CmovznzU64(&x40, p521Uint1(x38), x21, x3) + var x41 uint64 + p521CmovznzU64(&x41, p521Uint1(x38), x23, x5) + var x42 uint64 + p521CmovznzU64(&x42, p521Uint1(x38), x25, x7) + var x43 uint64 + p521CmovznzU64(&x43, p521Uint1(x38), x27, x9) + var x44 uint64 + p521CmovznzU64(&x44, p521Uint1(x38), x29, x11) + var x45 uint64 + p521CmovznzU64(&x45, p521Uint1(x38), x31, x13) + var x46 uint64 + p521CmovznzU64(&x46, p521Uint1(x38), x33, x15) + var x47 uint64 + p521CmovznzU64(&x47, p521Uint1(x38), x35, x17) + out1[0] = x39 + out1[1] = x40 + out1[2] = x41 + out1[3] = x42 + out1[4] = x43 + out1[5] = x44 + out1[6] = x45 + out1[7] = x46 + out1[8] = x47 +} + +// p521Sub subtracts two field elements in the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// 0 ≤ eval arg2 < m +// Postconditions: +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m +// 0 ≤ eval out1 < m +// +func p521Sub(out1 *p521MontgomeryDomainFieldElement, arg1 *p521MontgomeryDomainFieldElement, arg2 *p521MontgomeryDomainFieldElement) { + var x1 uint64 + var x2 uint64 + x1, x2 = bits.Sub64(arg1[0], arg2[0], uint64(0x0)) + var x3 uint64 + var x4 uint64 + x3, x4 = bits.Sub64(arg1[1], arg2[1], uint64(p521Uint1(x2))) + var x5 uint64 + var x6 uint64 + x5, x6 = bits.Sub64(arg1[2], arg2[2], uint64(p521Uint1(x4))) + var x7 uint64 + var x8 uint64 + x7, x8 = bits.Sub64(arg1[3], arg2[3], uint64(p521Uint1(x6))) + var x9 uint64 + var x10 uint64 + x9, x10 = bits.Sub64(arg1[4], arg2[4], uint64(p521Uint1(x8))) + var x11 uint64 + var x12 uint64 + x11, x12 = bits.Sub64(arg1[5], arg2[5], uint64(p521Uint1(x10))) + var x13 uint64 + var x14 uint64 + x13, x14 = bits.Sub64(arg1[6], arg2[6], uint64(p521Uint1(x12))) + var x15 uint64 + var x16 uint64 + x15, x16 = bits.Sub64(arg1[7], arg2[7], uint64(p521Uint1(x14))) + var x17 uint64 + var x18 uint64 + x17, x18 = bits.Sub64(arg1[8], arg2[8], uint64(p521Uint1(x16))) + var x19 uint64 + p521CmovznzU64(&x19, p521Uint1(x18), uint64(0x0), 0xffffffffffffffff) + var x20 uint64 + var x21 uint64 + x20, x21 = bits.Add64(x1, x19, uint64(0x0)) + var x22 uint64 + var x23 uint64 + x22, x23 = bits.Add64(x3, x19, uint64(p521Uint1(x21))) + var x24 uint64 + var x25 uint64 + x24, x25 = bits.Add64(x5, x19, uint64(p521Uint1(x23))) + var x26 uint64 + var x27 uint64 + x26, x27 = bits.Add64(x7, x19, uint64(p521Uint1(x25))) + var x28 uint64 + var x29 uint64 + x28, x29 = bits.Add64(x9, x19, uint64(p521Uint1(x27))) + var x30 uint64 + var x31 uint64 + x30, x31 = bits.Add64(x11, x19, uint64(p521Uint1(x29))) + var x32 uint64 + var x33 uint64 + x32, x33 = bits.Add64(x13, x19, uint64(p521Uint1(x31))) + var x34 uint64 + var x35 uint64 + x34, x35 = bits.Add64(x15, x19, uint64(p521Uint1(x33))) + var x36 uint64 + x36, _ = bits.Add64(x17, (x19 & 0x1ff), uint64(p521Uint1(x35))) + out1[0] = x20 + out1[1] = x22 + out1[2] = x24 + out1[3] = x26 + out1[4] = x28 + out1[5] = x30 + out1[6] = x32 + out1[7] = x34 + out1[8] = x36 +} + +// p521SetOne returns the field element one in the Montgomery domain. +// +// Postconditions: +// eval (from_montgomery out1) mod m = 1 mod m +// 0 ≤ eval out1 < m +// +func p521SetOne(out1 *p521MontgomeryDomainFieldElement) { + out1[0] = 0x80000000000000 + out1[1] = uint64(0x0) + out1[2] = uint64(0x0) + out1[3] = uint64(0x0) + out1[4] = uint64(0x0) + out1[5] = uint64(0x0) + out1[6] = uint64(0x0) + out1[7] = uint64(0x0) + out1[8] = uint64(0x0) +} + +// p521FromMontgomery translates a field element out of the Montgomery domain. +// +// Preconditions: +// 0 ≤ eval arg1 < m +// Postconditions: +// eval out1 mod m = (eval arg1 * ((2^64)⁻¹ mod m)^9) mod m +// 0 ≤ eval out1 < m +// +func p521FromMontgomery(out1 *p521NonMontgomeryDomainFieldElement, arg1 *p521MontgomeryDomainFieldElement) { + x1 := arg1[0] + var x2 uint64 + var x3 uint64 + x3, x2 = bits.Mul64(x1, 0x1ff) + var x4 uint64 + var x5 uint64 + x5, x4 = bits.Mul64(x1, 0xffffffffffffffff) + var x6 uint64 + var x7 uint64 + x7, x6 = bits.Mul64(x1, 0xffffffffffffffff) + var x8 uint64 + var x9 uint64 + x9, x8 = bits.Mul64(x1, 0xffffffffffffffff) + var x10 uint64 + var x11 uint64 + x11, x10 = bits.Mul64(x1, 0xffffffffffffffff) + var x12 uint64 + var x13 uint64 + x13, x12 = bits.Mul64(x1, 0xffffffffffffffff) + var x14 uint64 + var x15 uint64 + x15, x14 = bits.Mul64(x1, 0xffffffffffffffff) + var x16 uint64 + var x17 uint64 + x17, x16 = bits.Mul64(x1, 0xffffffffffffffff) + var x18 uint64 + var x19 uint64 + x19, x18 = bits.Mul64(x1, 0xffffffffffffffff) + var x20 uint64 + var x21 uint64 + x20, x21 = bits.Add64(x19, x16, uint64(0x0)) + var x22 uint64 + var x23 uint64 + x22, x23 = bits.Add64(x17, x14, uint64(p521Uint1(x21))) + var x24 uint64 + var x25 uint64 + x24, x25 = bits.Add64(x15, x12, uint64(p521Uint1(x23))) + var x26 uint64 + var x27 uint64 + x26, x27 = bits.Add64(x13, x10, uint64(p521Uint1(x25))) + var x28 uint64 + var x29 uint64 + x28, x29 = bits.Add64(x11, x8, uint64(p521Uint1(x27))) + var x30 uint64 + var x31 uint64 + x30, x31 = bits.Add64(x9, x6, uint64(p521Uint1(x29))) + var x32 uint64 + var x33 uint64 + x32, x33 = bits.Add64(x7, x4, uint64(p521Uint1(x31))) + var x34 uint64 + var x35 uint64 + x34, x35 = bits.Add64(x5, x2, uint64(p521Uint1(x33))) + var x37 uint64 + _, x37 = bits.Add64(x1, x18, uint64(0x0)) + var x38 uint64 + var x39 uint64 + x38, x39 = bits.Add64(uint64(0x0), x20, uint64(p521Uint1(x37))) + var x40 uint64 + var x41 uint64 + x40, x41 = bits.Add64(uint64(0x0), x22, uint64(p521Uint1(x39))) + var x42 uint64 + var x43 uint64 + x42, x43 = bits.Add64(uint64(0x0), x24, uint64(p521Uint1(x41))) + var x44 uint64 + var x45 uint64 + x44, x45 = bits.Add64(uint64(0x0), x26, uint64(p521Uint1(x43))) + var x46 uint64 + var x47 uint64 + x46, x47 = bits.Add64(uint64(0x0), x28, uint64(p521Uint1(x45))) + var x48 uint64 + var x49 uint64 + x48, x49 = bits.Add64(uint64(0x0), x30, uint64(p521Uint1(x47))) + var x50 uint64 + var x51 uint64 + x50, x51 = bits.Add64(uint64(0x0), x32, uint64(p521Uint1(x49))) + var x52 uint64 + var x53 uint64 + x52, x53 = bits.Add64(uint64(0x0), x34, uint64(p521Uint1(x51))) + var x54 uint64 + var x55 uint64 + x54, x55 = bits.Add64(x38, arg1[1], uint64(0x0)) + var x56 uint64 + var x57 uint64 + x56, x57 = bits.Add64(x40, uint64(0x0), uint64(p521Uint1(x55))) + var x58 uint64 + var x59 uint64 + x58, x59 = bits.Add64(x42, uint64(0x0), uint64(p521Uint1(x57))) + var x60 uint64 + var x61 uint64 + x60, x61 = bits.Add64(x44, uint64(0x0), uint64(p521Uint1(x59))) + var x62 uint64 + var x63 uint64 + x62, x63 = bits.Add64(x46, uint64(0x0), uint64(p521Uint1(x61))) + var x64 uint64 + var x65 uint64 + x64, x65 = bits.Add64(x48, uint64(0x0), uint64(p521Uint1(x63))) + var x66 uint64 + var x67 uint64 + x66, x67 = bits.Add64(x50, uint64(0x0), uint64(p521Uint1(x65))) + var x68 uint64 + var x69 uint64 + x68, x69 = bits.Add64(x52, uint64(0x0), uint64(p521Uint1(x67))) + var x70 uint64 + var x71 uint64 + x71, x70 = bits.Mul64(x54, 0x1ff) + var x72 uint64 + var x73 uint64 + x73, x72 = bits.Mul64(x54, 0xffffffffffffffff) + var x74 uint64 + var x75 uint64 + x75, x74 = bits.Mul64(x54, 0xffffffffffffffff) + var x76 uint64 + var x77 uint64 + x77, x76 = bits.Mul64(x54, 0xffffffffffffffff) + var x78 uint64 + var x79 uint64 + x79, x78 = bits.Mul64(x54, 0xffffffffffffffff) + var x80 uint64 + var x81 uint64 + x81, x80 = bits.Mul64(x54, 0xffffffffffffffff) + var x82 uint64 + var x83 uint64 + x83, x82 = bits.Mul64(x54, 0xffffffffffffffff) + var x84 uint64 + var x85 uint64 + x85, x84 = bits.Mul64(x54, 0xffffffffffffffff) + var x86 uint64 + var x87 uint64 + x87, x86 = bits.Mul64(x54, 0xffffffffffffffff) + var x88 uint64 + var x89 uint64 + x88, x89 = bits.Add64(x87, x84, uint64(0x0)) + var x90 uint64 + var x91 uint64 + x90, x91 = bits.Add64(x85, x82, uint64(p521Uint1(x89))) + var x92 uint64 + var x93 uint64 + x92, x93 = bits.Add64(x83, x80, uint64(p521Uint1(x91))) + var x94 uint64 + var x95 uint64 + x94, x95 = bits.Add64(x81, x78, uint64(p521Uint1(x93))) + var x96 uint64 + var x97 uint64 + x96, x97 = bits.Add64(x79, x76, uint64(p521Uint1(x95))) + var x98 uint64 + var x99 uint64 + x98, x99 = bits.Add64(x77, x74, uint64(p521Uint1(x97))) + var x100 uint64 + var x101 uint64 + x100, x101 = bits.Add64(x75, x72, uint64(p521Uint1(x99))) + var x102 uint64 + var x103 uint64 + x102, x103 = bits.Add64(x73, x70, uint64(p521Uint1(x101))) + var x105 uint64 + _, x105 = bits.Add64(x54, x86, uint64(0x0)) + var x106 uint64 + var x107 uint64 + x106, x107 = bits.Add64(x56, x88, uint64(p521Uint1(x105))) + var x108 uint64 + var x109 uint64 + x108, x109 = bits.Add64(x58, x90, uint64(p521Uint1(x107))) + var x110 uint64 + var x111 uint64 + x110, x111 = bits.Add64(x60, x92, uint64(p521Uint1(x109))) + var x112 uint64 + var x113 uint64 + x112, x113 = bits.Add64(x62, x94, uint64(p521Uint1(x111))) + var x114 uint64 + var x115 uint64 + x114, x115 = bits.Add64(x64, x96, uint64(p521Uint1(x113))) + var x116 uint64 + var x117 uint64 + x116, x117 = bits.Add64(x66, x98, uint64(p521Uint1(x115))) + var x118 uint64 + var x119 uint64 + x118, x119 = bits.Add64(x68, x100, uint64(p521Uint1(x117))) + var x120 uint64 + var x121 uint64 + x120, x121 = bits.Add64((uint64(p521Uint1(x69)) + (uint64(p521Uint1(x53)) + (uint64(p521Uint1(x35)) + x3))), x102, uint64(p521Uint1(x119))) + var x122 uint64 + var x123 uint64 + x122, x123 = bits.Add64(x106, arg1[2], uint64(0x0)) + var x124 uint64 + var x125 uint64 + x124, x125 = bits.Add64(x108, uint64(0x0), uint64(p521Uint1(x123))) + var x126 uint64 + var x127 uint64 + x126, x127 = bits.Add64(x110, uint64(0x0), uint64(p521Uint1(x125))) + var x128 uint64 + var x129 uint64 + x128, x129 = bits.Add64(x112, uint64(0x0), uint64(p521Uint1(x127))) + var x130 uint64 + var x131 uint64 + x130, x131 = bits.Add64(x114, uint64(0x0), uint64(p521Uint1(x129))) + var x132 uint64 + var x133 uint64 + x132, x133 = bits.Add64(x116, uint64(0x0), uint64(p521Uint1(x131))) + var x134 uint64 + var x135 uint64 + x134, x135 = bits.Add64(x118, uint64(0x0), uint64(p521Uint1(x133))) + var x136 uint64 + var x137 uint64 + x136, x137 = bits.Add64(x120, uint64(0x0), uint64(p521Uint1(x135))) + var x138 uint64 + var x139 uint64 + x139, x138 = bits.Mul64(x122, 0x1ff) + var x140 uint64 + var x141 uint64 + x141, x140 = bits.Mul64(x122, 0xffffffffffffffff) + var x142 uint64 + var x143 uint64 + x143, x142 = bits.Mul64(x122, 0xffffffffffffffff) + var x144 uint64 + var x145 uint64 + x145, x144 = bits.Mul64(x122, 0xffffffffffffffff) + var x146 uint64 + var x147 uint64 + x147, x146 = bits.Mul64(x122, 0xffffffffffffffff) + var x148 uint64 + var x149 uint64 + x149, x148 = bits.Mul64(x122, 0xffffffffffffffff) + var x150 uint64 + var x151 uint64 + x151, x150 = bits.Mul64(x122, 0xffffffffffffffff) + var x152 uint64 + var x153 uint64 + x153, x152 = bits.Mul64(x122, 0xffffffffffffffff) + var x154 uint64 + var x155 uint64 + x155, x154 = bits.Mul64(x122, 0xffffffffffffffff) + var x156 uint64 + var x157 uint64 + x156, x157 = bits.Add64(x155, x152, uint64(0x0)) + var x158 uint64 + var x159 uint64 + x158, x159 = bits.Add64(x153, x150, uint64(p521Uint1(x157))) + var x160 uint64 + var x161 uint64 + x160, x161 = bits.Add64(x151, x148, uint64(p521Uint1(x159))) + var x162 uint64 + var x163 uint64 + x162, x163 = bits.Add64(x149, x146, uint64(p521Uint1(x161))) + var x164 uint64 + var x165 uint64 + x164, x165 = bits.Add64(x147, x144, uint64(p521Uint1(x163))) + var x166 uint64 + var x167 uint64 + x166, x167 = bits.Add64(x145, x142, uint64(p521Uint1(x165))) + var x168 uint64 + var x169 uint64 + x168, x169 = bits.Add64(x143, x140, uint64(p521Uint1(x167))) + var x170 uint64 + var x171 uint64 + x170, x171 = bits.Add64(x141, x138, uint64(p521Uint1(x169))) + var x173 uint64 + _, x173 = bits.Add64(x122, x154, uint64(0x0)) + var x174 uint64 + var x175 uint64 + x174, x175 = bits.Add64(x124, x156, uint64(p521Uint1(x173))) + var x176 uint64 + var x177 uint64 + x176, x177 = bits.Add64(x126, x158, uint64(p521Uint1(x175))) + var x178 uint64 + var x179 uint64 + x178, x179 = bits.Add64(x128, x160, uint64(p521Uint1(x177))) + var x180 uint64 + var x181 uint64 + x180, x181 = bits.Add64(x130, x162, uint64(p521Uint1(x179))) + var x182 uint64 + var x183 uint64 + x182, x183 = bits.Add64(x132, x164, uint64(p521Uint1(x181))) + var x184 uint64 + var x185 uint64 + x184, x185 = bits.Add64(x134, x166, uint64(p521Uint1(x183))) + var x186 uint64 + var x187 uint64 + x186, x187 = bits.Add64(x136, x168, uint64(p521Uint1(x185))) + var x188 uint64 + var x189 uint64 + x188, x189 = bits.Add64((uint64(p521Uint1(x137)) + (uint64(p521Uint1(x121)) + (uint64(p521Uint1(x103)) + x71))), x170, uint64(p521Uint1(x187))) + var x190 uint64 + var x191 uint64 + x190, x191 = bits.Add64(x174, arg1[3], uint64(0x0)) + var x192 uint64 + var x193 uint64 + x192, x193 = bits.Add64(x176, uint64(0x0), uint64(p521Uint1(x191))) + var x194 uint64 + var x195 uint64 + x194, x195 = bits.Add64(x178, uint64(0x0), uint64(p521Uint1(x193))) + var x196 uint64 + var x197 uint64 + x196, x197 = bits.Add64(x180, uint64(0x0), uint64(p521Uint1(x195))) + var x198 uint64 + var x199 uint64 + x198, x199 = bits.Add64(x182, uint64(0x0), uint64(p521Uint1(x197))) + var x200 uint64 + var x201 uint64 + x200, x201 = bits.Add64(x184, uint64(0x0), uint64(p521Uint1(x199))) + var x202 uint64 + var x203 uint64 + x202, x203 = bits.Add64(x186, uint64(0x0), uint64(p521Uint1(x201))) + var x204 uint64 + var x205 uint64 + x204, x205 = bits.Add64(x188, uint64(0x0), uint64(p521Uint1(x203))) + var x206 uint64 + var x207 uint64 + x207, x206 = bits.Mul64(x190, 0x1ff) + var x208 uint64 + var x209 uint64 + x209, x208 = bits.Mul64(x190, 0xffffffffffffffff) + var x210 uint64 + var x211 uint64 + x211, x210 = bits.Mul64(x190, 0xffffffffffffffff) + var x212 uint64 + var x213 uint64 + x213, x212 = bits.Mul64(x190, 0xffffffffffffffff) + var x214 uint64 + var x215 uint64 + x215, x214 = bits.Mul64(x190, 0xffffffffffffffff) + var x216 uint64 + var x217 uint64 + x217, x216 = bits.Mul64(x190, 0xffffffffffffffff) + var x218 uint64 + var x219 uint64 + x219, x218 = bits.Mul64(x190, 0xffffffffffffffff) + var x220 uint64 + var x221 uint64 + x221, x220 = bits.Mul64(x190, 0xffffffffffffffff) + var x222 uint64 + var x223 uint64 + x223, x222 = bits.Mul64(x190, 0xffffffffffffffff) + var x224 uint64 + var x225 uint64 + x224, x225 = bits.Add64(x223, x220, uint64(0x0)) + var x226 uint64 + var x227 uint64 + x226, x227 = bits.Add64(x221, x218, uint64(p521Uint1(x225))) + var x228 uint64 + var x229 uint64 + x228, x229 = bits.Add64(x219, x216, uint64(p521Uint1(x227))) + var x230 uint64 + var x231 uint64 + x230, x231 = bits.Add64(x217, x214, uint64(p521Uint1(x229))) + var x232 uint64 + var x233 uint64 + x232, x233 = bits.Add64(x215, x212, uint64(p521Uint1(x231))) + var x234 uint64 + var x235 uint64 + x234, x235 = bits.Add64(x213, x210, uint64(p521Uint1(x233))) + var x236 uint64 + var x237 uint64 + x236, x237 = bits.Add64(x211, x208, uint64(p521Uint1(x235))) + var x238 uint64 + var x239 uint64 + x238, x239 = bits.Add64(x209, x206, uint64(p521Uint1(x237))) + var x241 uint64 + _, x241 = bits.Add64(x190, x222, uint64(0x0)) + var x242 uint64 + var x243 uint64 + x242, x243 = bits.Add64(x192, x224, uint64(p521Uint1(x241))) + var x244 uint64 + var x245 uint64 + x244, x245 = bits.Add64(x194, x226, uint64(p521Uint1(x243))) + var x246 uint64 + var x247 uint64 + x246, x247 = bits.Add64(x196, x228, uint64(p521Uint1(x245))) + var x248 uint64 + var x249 uint64 + x248, x249 = bits.Add64(x198, x230, uint64(p521Uint1(x247))) + var x250 uint64 + var x251 uint64 + x250, x251 = bits.Add64(x200, x232, uint64(p521Uint1(x249))) + var x252 uint64 + var x253 uint64 + x252, x253 = bits.Add64(x202, x234, uint64(p521Uint1(x251))) + var x254 uint64 + var x255 uint64 + x254, x255 = bits.Add64(x204, x236, uint64(p521Uint1(x253))) + var x256 uint64 + var x257 uint64 + x256, x257 = bits.Add64((uint64(p521Uint1(x205)) + (uint64(p521Uint1(x189)) + (uint64(p521Uint1(x171)) + x139))), x238, uint64(p521Uint1(x255))) + var x258 uint64 + var x259 uint64 + x258, x259 = bits.Add64(x242, arg1[4], uint64(0x0)) + var x260 uint64 + var x261 uint64 + x260, x261 = bits.Add64(x244, uint64(0x0), uint64(p521Uint1(x259))) + var x262 uint64 + var x263 uint64 + x262, x263 = bits.Add64(x246, uint64(0x0), uint64(p521Uint1(x261))) + var x264 uint64 + var x265 uint64 + x264, x265 = bits.Add64(x248, uint64(0x0), uint64(p521Uint1(x263))) + var x266 uint64 + var x267 uint64 + x266, x267 = bits.Add64(x250, uint64(0x0), uint64(p521Uint1(x265))) + var x268 uint64 + var x269 uint64 + x268, x269 = bits.Add64(x252, uint64(0x0), uint64(p521Uint1(x267))) + var x270 uint64 + var x271 uint64 + x270, x271 = bits.Add64(x254, uint64(0x0), uint64(p521Uint1(x269))) + var x272 uint64 + var x273 uint64 + x272, x273 = bits.Add64(x256, uint64(0x0), uint64(p521Uint1(x271))) + var x274 uint64 + var x275 uint64 + x275, x274 = bits.Mul64(x258, 0x1ff) + var x276 uint64 + var x277 uint64 + x277, x276 = bits.Mul64(x258, 0xffffffffffffffff) + var x278 uint64 + var x279 uint64 + x279, x278 = bits.Mul64(x258, 0xffffffffffffffff) + var x280 uint64 + var x281 uint64 + x281, x280 = bits.Mul64(x258, 0xffffffffffffffff) + var x282 uint64 + var x283 uint64 + x283, x282 = bits.Mul64(x258, 0xffffffffffffffff) + var x284 uint64 + var x285 uint64 + x285, x284 = bits.Mul64(x258, 0xffffffffffffffff) + var x286 uint64 + var x287 uint64 + x287, x286 = bits.Mul64(x258, 0xffffffffffffffff) + var x288 uint64 + var x289 uint64 + x289, x288 = bits.Mul64(x258, 0xffffffffffffffff) + var x290 uint64 + var x291 uint64 + x291, x290 = bits.Mul64(x258, 0xffffffffffffffff) + var x292 uint64 + var x293 uint64 + x292, x293 = bits.Add64(x291, x288, uint64(0x0)) + var x294 uint64 + var x295 uint64 + x294, x295 = bits.Add64(x289, x286, uint64(p521Uint1(x293))) + var x296 uint64 + var x297 uint64 + x296, x297 = bits.Add64(x287, x284, uint64(p521Uint1(x295))) + var x298 uint64 + var x299 uint64 + x298, x299 = bits.Add64(x285, x282, uint64(p521Uint1(x297))) + var x300 uint64 + var x301 uint64 + x300, x301 = bits.Add64(x283, x280, uint64(p521Uint1(x299))) + var x302 uint64 + var x303 uint64 + x302, x303 = bits.Add64(x281, x278, uint64(p521Uint1(x301))) + var x304 uint64 + var x305 uint64 + x304, x305 = bits.Add64(x279, x276, uint64(p521Uint1(x303))) + var x306 uint64 + var x307 uint64 + x306, x307 = bits.Add64(x277, x274, uint64(p521Uint1(x305))) + var x309 uint64 + _, x309 = bits.Add64(x258, x290, uint64(0x0)) + var x310 uint64 + var x311 uint64 + x310, x311 = bits.Add64(x260, x292, uint64(p521Uint1(x309))) + var x312 uint64 + var x313 uint64 + x312, x313 = bits.Add64(x262, x294, uint64(p521Uint1(x311))) + var x314 uint64 + var x315 uint64 + x314, x315 = bits.Add64(x264, x296, uint64(p521Uint1(x313))) + var x316 uint64 + var x317 uint64 + x316, x317 = bits.Add64(x266, x298, uint64(p521Uint1(x315))) + var x318 uint64 + var x319 uint64 + x318, x319 = bits.Add64(x268, x300, uint64(p521Uint1(x317))) + var x320 uint64 + var x321 uint64 + x320, x321 = bits.Add64(x270, x302, uint64(p521Uint1(x319))) + var x322 uint64 + var x323 uint64 + x322, x323 = bits.Add64(x272, x304, uint64(p521Uint1(x321))) + var x324 uint64 + var x325 uint64 + x324, x325 = bits.Add64((uint64(p521Uint1(x273)) + (uint64(p521Uint1(x257)) + (uint64(p521Uint1(x239)) + x207))), x306, uint64(p521Uint1(x323))) + var x326 uint64 + var x327 uint64 + x326, x327 = bits.Add64(x310, arg1[5], uint64(0x0)) + var x328 uint64 + var x329 uint64 + x328, x329 = bits.Add64(x312, uint64(0x0), uint64(p521Uint1(x327))) + var x330 uint64 + var x331 uint64 + x330, x331 = bits.Add64(x314, uint64(0x0), uint64(p521Uint1(x329))) + var x332 uint64 + var x333 uint64 + x332, x333 = bits.Add64(x316, uint64(0x0), uint64(p521Uint1(x331))) + var x334 uint64 + var x335 uint64 + x334, x335 = bits.Add64(x318, uint64(0x0), uint64(p521Uint1(x333))) + var x336 uint64 + var x337 uint64 + x336, x337 = bits.Add64(x320, uint64(0x0), uint64(p521Uint1(x335))) + var x338 uint64 + var x339 uint64 + x338, x339 = bits.Add64(x322, uint64(0x0), uint64(p521Uint1(x337))) + var x340 uint64 + var x341 uint64 + x340, x341 = bits.Add64(x324, uint64(0x0), uint64(p521Uint1(x339))) + var x342 uint64 + var x343 uint64 + x343, x342 = bits.Mul64(x326, 0x1ff) + var x344 uint64 + var x345 uint64 + x345, x344 = bits.Mul64(x326, 0xffffffffffffffff) + var x346 uint64 + var x347 uint64 + x347, x346 = bits.Mul64(x326, 0xffffffffffffffff) + var x348 uint64 + var x349 uint64 + x349, x348 = bits.Mul64(x326, 0xffffffffffffffff) + var x350 uint64 + var x351 uint64 + x351, x350 = bits.Mul64(x326, 0xffffffffffffffff) + var x352 uint64 + var x353 uint64 + x353, x352 = bits.Mul64(x326, 0xffffffffffffffff) + var x354 uint64 + var x355 uint64 + x355, x354 = bits.Mul64(x326, 0xffffffffffffffff) + var x356 uint64 + var x357 uint64 + x357, x356 = bits.Mul64(x326, 0xffffffffffffffff) + var x358 uint64 + var x359 uint64 + x359, x358 = bits.Mul64(x326, 0xffffffffffffffff) + var x360 uint64 + var x361 uint64 + x360, x361 = bits.Add64(x359, x356, uint64(0x0)) + var x362 uint64 + var x363 uint64 + x362, x363 = bits.Add64(x357, x354, uint64(p521Uint1(x361))) + var x364 uint64 + var x365 uint64 + x364, x365 = bits.Add64(x355, x352, uint64(p521Uint1(x363))) + var x366 uint64 + var x367 uint64 + x366, x367 = bits.Add64(x353, x350, uint64(p521Uint1(x365))) + var x368 uint64 + var x369 uint64 + x368, x369 = bits.Add64(x351, x348, uint64(p521Uint1(x367))) + var x370 uint64 + var x371 uint64 + x370, x371 = bits.Add64(x349, x346, uint64(p521Uint1(x369))) + var x372 uint64 + var x373 uint64 + x372, x373 = bits.Add64(x347, x344, uint64(p521Uint1(x371))) + var x374 uint64 + var x375 uint64 + x374, x375 = bits.Add64(x345, x342, uint64(p521Uint1(x373))) + var x377 uint64 + _, x377 = bits.Add64(x326, x358, uint64(0x0)) + var x378 uint64 + var x379 uint64 + x378, x379 = bits.Add64(x328, x360, uint64(p521Uint1(x377))) + var x380 uint64 + var x381 uint64 + x380, x381 = bits.Add64(x330, x362, uint64(p521Uint1(x379))) + var x382 uint64 + var x383 uint64 + x382, x383 = bits.Add64(x332, x364, uint64(p521Uint1(x381))) + var x384 uint64 + var x385 uint64 + x384, x385 = bits.Add64(x334, x366, uint64(p521Uint1(x383))) + var x386 uint64 + var x387 uint64 + x386, x387 = bits.Add64(x336, x368, uint64(p521Uint1(x385))) + var x388 uint64 + var x389 uint64 + x388, x389 = bits.Add64(x338, x370, uint64(p521Uint1(x387))) + var x390 uint64 + var x391 uint64 + x390, x391 = bits.Add64(x340, x372, uint64(p521Uint1(x389))) + var x392 uint64 + var x393 uint64 + x392, x393 = bits.Add64((uint64(p521Uint1(x341)) + (uint64(p521Uint1(x325)) + (uint64(p521Uint1(x307)) + x275))), x374, uint64(p521Uint1(x391))) + var x394 uint64 + var x395 uint64 + x394, x395 = bits.Add64(x378, arg1[6], uint64(0x0)) + var x396 uint64 + var x397 uint64 + x396, x397 = bits.Add64(x380, uint64(0x0), uint64(p521Uint1(x395))) + var x398 uint64 + var x399 uint64 + x398, x399 = bits.Add64(x382, uint64(0x0), uint64(p521Uint1(x397))) + var x400 uint64 + var x401 uint64 + x400, x401 = bits.Add64(x384, uint64(0x0), uint64(p521Uint1(x399))) + var x402 uint64 + var x403 uint64 + x402, x403 = bits.Add64(x386, uint64(0x0), uint64(p521Uint1(x401))) + var x404 uint64 + var x405 uint64 + x404, x405 = bits.Add64(x388, uint64(0x0), uint64(p521Uint1(x403))) + var x406 uint64 + var x407 uint64 + x406, x407 = bits.Add64(x390, uint64(0x0), uint64(p521Uint1(x405))) + var x408 uint64 + var x409 uint64 + x408, x409 = bits.Add64(x392, uint64(0x0), uint64(p521Uint1(x407))) + var x410 uint64 + var x411 uint64 + x411, x410 = bits.Mul64(x394, 0x1ff) + var x412 uint64 + var x413 uint64 + x413, x412 = bits.Mul64(x394, 0xffffffffffffffff) + var x414 uint64 + var x415 uint64 + x415, x414 = bits.Mul64(x394, 0xffffffffffffffff) + var x416 uint64 + var x417 uint64 + x417, x416 = bits.Mul64(x394, 0xffffffffffffffff) + var x418 uint64 + var x419 uint64 + x419, x418 = bits.Mul64(x394, 0xffffffffffffffff) + var x420 uint64 + var x421 uint64 + x421, x420 = bits.Mul64(x394, 0xffffffffffffffff) + var x422 uint64 + var x423 uint64 + x423, x422 = bits.Mul64(x394, 0xffffffffffffffff) + var x424 uint64 + var x425 uint64 + x425, x424 = bits.Mul64(x394, 0xffffffffffffffff) + var x426 uint64 + var x427 uint64 + x427, x426 = bits.Mul64(x394, 0xffffffffffffffff) + var x428 uint64 + var x429 uint64 + x428, x429 = bits.Add64(x427, x424, uint64(0x0)) + var x430 uint64 + var x431 uint64 + x430, x431 = bits.Add64(x425, x422, uint64(p521Uint1(x429))) + var x432 uint64 + var x433 uint64 + x432, x433 = bits.Add64(x423, x420, uint64(p521Uint1(x431))) + var x434 uint64 + var x435 uint64 + x434, x435 = bits.Add64(x421, x418, uint64(p521Uint1(x433))) + var x436 uint64 + var x437 uint64 + x436, x437 = bits.Add64(x419, x416, uint64(p521Uint1(x435))) + var x438 uint64 + var x439 uint64 + x438, x439 = bits.Add64(x417, x414, uint64(p521Uint1(x437))) + var x440 uint64 + var x441 uint64 + x440, x441 = bits.Add64(x415, x412, uint64(p521Uint1(x439))) + var x442 uint64 + var x443 uint64 + x442, x443 = bits.Add64(x413, x410, uint64(p521Uint1(x441))) + var x445 uint64 + _, x445 = bits.Add64(x394, x426, uint64(0x0)) + var x446 uint64 + var x447 uint64 + x446, x447 = bits.Add64(x396, x428, uint64(p521Uint1(x445))) + var x448 uint64 + var x449 uint64 + x448, x449 = bits.Add64(x398, x430, uint64(p521Uint1(x447))) + var x450 uint64 + var x451 uint64 + x450, x451 = bits.Add64(x400, x432, uint64(p521Uint1(x449))) + var x452 uint64 + var x453 uint64 + x452, x453 = bits.Add64(x402, x434, uint64(p521Uint1(x451))) + var x454 uint64 + var x455 uint64 + x454, x455 = bits.Add64(x404, x436, uint64(p521Uint1(x453))) + var x456 uint64 + var x457 uint64 + x456, x457 = bits.Add64(x406, x438, uint64(p521Uint1(x455))) + var x458 uint64 + var x459 uint64 + x458, x459 = bits.Add64(x408, x440, uint64(p521Uint1(x457))) + var x460 uint64 + var x461 uint64 + x460, x461 = bits.Add64((uint64(p521Uint1(x409)) + (uint64(p521Uint1(x393)) + (uint64(p521Uint1(x375)) + x343))), x442, uint64(p521Uint1(x459))) + var x462 uint64 + var x463 uint64 + x462, x463 = bits.Add64(x446, arg1[7], uint64(0x0)) + var x464 uint64 + var x465 uint64 + x464, x465 = bits.Add64(x448, uint64(0x0), uint64(p521Uint1(x463))) + var x466 uint64 + var x467 uint64 + x466, x467 = bits.Add64(x450, uint64(0x0), uint64(p521Uint1(x465))) + var x468 uint64 + var x469 uint64 + x468, x469 = bits.Add64(x452, uint64(0x0), uint64(p521Uint1(x467))) + var x470 uint64 + var x471 uint64 + x470, x471 = bits.Add64(x454, uint64(0x0), uint64(p521Uint1(x469))) + var x472 uint64 + var x473 uint64 + x472, x473 = bits.Add64(x456, uint64(0x0), uint64(p521Uint1(x471))) + var x474 uint64 + var x475 uint64 + x474, x475 = bits.Add64(x458, uint64(0x0), uint64(p521Uint1(x473))) + var x476 uint64 + var x477 uint64 + x476, x477 = bits.Add64(x460, uint64(0x0), uint64(p521Uint1(x475))) + var x478 uint64 + var x479 uint64 + x479, x478 = bits.Mul64(x462, 0x1ff) + var x480 uint64 + var x481 uint64 + x481, x480 = bits.Mul64(x462, 0xffffffffffffffff) + var x482 uint64 + var x483 uint64 + x483, x482 = bits.Mul64(x462, 0xffffffffffffffff) + var x484 uint64 + var x485 uint64 + x485, x484 = bits.Mul64(x462, 0xffffffffffffffff) + var x486 uint64 + var x487 uint64 + x487, x486 = bits.Mul64(x462, 0xffffffffffffffff) + var x488 uint64 + var x489 uint64 + x489, x488 = bits.Mul64(x462, 0xffffffffffffffff) + var x490 uint64 + var x491 uint64 + x491, x490 = bits.Mul64(x462, 0xffffffffffffffff) + var x492 uint64 + var x493 uint64 + x493, x492 = bits.Mul64(x462, 0xffffffffffffffff) + var x494 uint64 + var x495 uint64 + x495, x494 = bits.Mul64(x462, 0xffffffffffffffff) + var x496 uint64 + var x497 uint64 + x496, x497 = bits.Add64(x495, x492, uint64(0x0)) + var x498 uint64 + var x499 uint64 + x498, x499 = bits.Add64(x493, x490, uint64(p521Uint1(x497))) + var x500 uint64 + var x501 uint64 + x500, x501 = bits.Add64(x491, x488, uint64(p521Uint1(x499))) + var x502 uint64 + var x503 uint64 + x502, x503 = bits.Add64(x489, x486, uint64(p521Uint1(x501))) + var x504 uint64 + var x505 uint64 + x504, x505 = bits.Add64(x487, x484, uint64(p521Uint1(x503))) + var x506 uint64 + var x507 uint64 + x506, x507 = bits.Add64(x485, x482, uint64(p521Uint1(x505))) + var x508 uint64 + var x509 uint64 + x508, x509 = bits.Add64(x483, x480, uint64(p521Uint1(x507))) + var x510 uint64 + var x511 uint64 + x510, x511 = bits.Add64(x481, x478, uint64(p521Uint1(x509))) + var x513 uint64 + _, x513 = bits.Add64(x462, x494, uint64(0x0)) + var x514 uint64 + var x515 uint64 + x514, x515 = bits.Add64(x464, x496, uint64(p521Uint1(x513))) + var x516 uint64 + var x517 uint64 + x516, x517 = bits.Add64(x466, x498, uint64(p521Uint1(x515))) + var x518 uint64 + var x519 uint64 + x518, x519 = bits.Add64(x468, x500, uint64(p521Uint1(x517))) + var x520 uint64 + var x521 uint64 + x520, x521 = bits.Add64(x470, x502, uint64(p521Uint1(x519))) + var x522 uint64 + var x523 uint64 + x522, x523 = bits.Add64(x472, x504, uint64(p521Uint1(x521))) + var x524 uint64 + var x525 uint64 + x524, x525 = bits.Add64(x474, x506, uint64(p521Uint1(x523))) + var x526 uint64 + var x527 uint64 + x526, x527 = bits.Add64(x476, x508, uint64(p521Uint1(x525))) + var x528 uint64 + var x529 uint64 + x528, x529 = bits.Add64((uint64(p521Uint1(x477)) + (uint64(p521Uint1(x461)) + (uint64(p521Uint1(x443)) + x411))), x510, uint64(p521Uint1(x527))) + var x530 uint64 + var x531 uint64 + x530, x531 = bits.Add64(x514, arg1[8], uint64(0x0)) + var x532 uint64 + var x533 uint64 + x532, x533 = bits.Add64(x516, uint64(0x0), uint64(p521Uint1(x531))) + var x534 uint64 + var x535 uint64 + x534, x535 = bits.Add64(x518, uint64(0x0), uint64(p521Uint1(x533))) + var x536 uint64 + var x537 uint64 + x536, x537 = bits.Add64(x520, uint64(0x0), uint64(p521Uint1(x535))) + var x538 uint64 + var x539 uint64 + x538, x539 = bits.Add64(x522, uint64(0x0), uint64(p521Uint1(x537))) + var x540 uint64 + var x541 uint64 + x540, x541 = bits.Add64(x524, uint64(0x0), uint64(p521Uint1(x539))) + var x542 uint64 + var x543 uint64 + x542, x543 = bits.Add64(x526, uint64(0x0), uint64(p521Uint1(x541))) + var x544 uint64 + var x545 uint64 + x544, x545 = bits.Add64(x528, uint64(0x0), uint64(p521Uint1(x543))) + var x546 uint64 + var x547 uint64 + x547, x546 = bits.Mul64(x530, 0x1ff) + var x548 uint64 + var x549 uint64 + x549, x548 = bits.Mul64(x530, 0xffffffffffffffff) + var x550 uint64 + var x551 uint64 + x551, x550 = bits.Mul64(x530, 0xffffffffffffffff) + var x552 uint64 + var x553 uint64 + x553, x552 = bits.Mul64(x530, 0xffffffffffffffff) + var x554 uint64 + var x555 uint64 + x555, x554 = bits.Mul64(x530, 0xffffffffffffffff) + var x556 uint64 + var x557 uint64 + x557, x556 = bits.Mul64(x530, 0xffffffffffffffff) + var x558 uint64 + var x559 uint64 + x559, x558 = bits.Mul64(x530, 0xffffffffffffffff) + var x560 uint64 + var x561 uint64 + x561, x560 = bits.Mul64(x530, 0xffffffffffffffff) + var x562 uint64 + var x563 uint64 + x563, x562 = bits.Mul64(x530, 0xffffffffffffffff) + var x564 uint64 + var x565 uint64 + x564, x565 = bits.Add64(x563, x560, uint64(0x0)) + var x566 uint64 + var x567 uint64 + x566, x567 = bits.Add64(x561, x558, uint64(p521Uint1(x565))) + var x568 uint64 + var x569 uint64 + x568, x569 = bits.Add64(x559, x556, uint64(p521Uint1(x567))) + var x570 uint64 + var x571 uint64 + x570, x571 = bits.Add64(x557, x554, uint64(p521Uint1(x569))) + var x572 uint64 + var x573 uint64 + x572, x573 = bits.Add64(x555, x552, uint64(p521Uint1(x571))) + var x574 uint64 + var x575 uint64 + x574, x575 = bits.Add64(x553, x550, uint64(p521Uint1(x573))) + var x576 uint64 + var x577 uint64 + x576, x577 = bits.Add64(x551, x548, uint64(p521Uint1(x575))) + var x578 uint64 + var x579 uint64 + x578, x579 = bits.Add64(x549, x546, uint64(p521Uint1(x577))) + var x581 uint64 + _, x581 = bits.Add64(x530, x562, uint64(0x0)) + var x582 uint64 + var x583 uint64 + x582, x583 = bits.Add64(x532, x564, uint64(p521Uint1(x581))) + var x584 uint64 + var x585 uint64 + x584, x585 = bits.Add64(x534, x566, uint64(p521Uint1(x583))) + var x586 uint64 + var x587 uint64 + x586, x587 = bits.Add64(x536, x568, uint64(p521Uint1(x585))) + var x588 uint64 + var x589 uint64 + x588, x589 = bits.Add64(x538, x570, uint64(p521Uint1(x587))) + var x590 uint64 + var x591 uint64 + x590, x591 = bits.Add64(x540, x572, uint64(p521Uint1(x589))) + var x592 uint64 + var x593 uint64 + x592, x593 = bits.Add64(x542, x574, uint64(p521Uint1(x591))) + var x594 uint64 + var x595 uint64 + x594, x595 = bits.Add64(x544, x576, uint64(p521Uint1(x593))) + var x596 uint64 + var x597 uint64 + x596, x597 = bits.Add64((uint64(p521Uint1(x545)) + (uint64(p521Uint1(x529)) + (uint64(p521Uint1(x511)) + x479))), x578, uint64(p521Uint1(x595))) + x598 := (uint64(p521Uint1(x597)) + (uint64(p521Uint1(x579)) + x547)) + var x599 uint64 + var x600 uint64 + x599, x600 = bits.Sub64(x582, 0xffffffffffffffff, uint64(0x0)) + var x601 uint64 + var x602 uint64 + x601, x602 = bits.Sub64(x584, 0xffffffffffffffff, uint64(p521Uint1(x600))) + var x603 uint64 + var x604 uint64 + x603, x604 = bits.Sub64(x586, 0xffffffffffffffff, uint64(p521Uint1(x602))) + var x605 uint64 + var x606 uint64 + x605, x606 = bits.Sub64(x588, 0xffffffffffffffff, uint64(p521Uint1(x604))) + var x607 uint64 + var x608 uint64 + x607, x608 = bits.Sub64(x590, 0xffffffffffffffff, uint64(p521Uint1(x606))) + var x609 uint64 + var x610 uint64 + x609, x610 = bits.Sub64(x592, 0xffffffffffffffff, uint64(p521Uint1(x608))) + var x611 uint64 + var x612 uint64 + x611, x612 = bits.Sub64(x594, 0xffffffffffffffff, uint64(p521Uint1(x610))) + var x613 uint64 + var x614 uint64 + x613, x614 = bits.Sub64(x596, 0xffffffffffffffff, uint64(p521Uint1(x612))) + var x615 uint64 + var x616 uint64 + x615, x616 = bits.Sub64(x598, 0x1ff, uint64(p521Uint1(x614))) + var x618 uint64 + _, x618 = bits.Sub64(uint64(0x0), uint64(0x0), uint64(p521Uint1(x616))) + var x619 uint64 + p521CmovznzU64(&x619, p521Uint1(x618), x599, x582) + var x620 uint64 + p521CmovznzU64(&x620, p521Uint1(x618), x601, x584) + var x621 uint64 + p521CmovznzU64(&x621, p521Uint1(x618), x603, x586) + var x622 uint64 + p521CmovznzU64(&x622, p521Uint1(x618), x605, x588) + var x623 uint64 + p521CmovznzU64(&x623, p521Uint1(x618), x607, x590) + var x624 uint64 + p521CmovznzU64(&x624, p521Uint1(x618), x609, x592) + var x625 uint64 + p521CmovznzU64(&x625, p521Uint1(x618), x611, x594) + var x626 uint64 + p521CmovznzU64(&x626, p521Uint1(x618), x613, x596) + var x627 uint64 + p521CmovznzU64(&x627, p521Uint1(x618), x615, x598) + out1[0] = x619 + out1[1] = x620 + out1[2] = x621 + out1[3] = x622 + out1[4] = x623 + out1[5] = x624 + out1[6] = x625 + out1[7] = x626 + out1[8] = x627 +} -// p521Add adds two field elements. +// p521ToMontgomery translates a field element into the Montgomery domain. // +// Preconditions: +// 0 ≤ eval arg1 < m // Postconditions: -// eval out1 mod m = (eval arg1 + eval arg2) mod m +// eval (from_montgomery out1) mod m = eval arg1 mod m +// 0 ≤ eval out1 < m // -// Input Bounds: -// arg1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] -// arg2: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] -// Output Bounds: -// out1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]] -func p521Add(out1 *[9]uint64, arg1 *[9]uint64, arg2 *[9]uint64) { - x1 := (arg1[0] + arg2[0]) - x2 := (arg1[1] + arg2[1]) - x3 := (arg1[2] + arg2[2]) - x4 := (arg1[3] + arg2[3]) - x5 := (arg1[4] + arg2[4]) - x6 := (arg1[5] + arg2[5]) - x7 := (arg1[6] + arg2[6]) - x8 := (arg1[7] + arg2[7]) - x9 := (arg1[8] + arg2[8]) - out1[0] = x1 - out1[1] = x2 - out1[2] = x3 - out1[3] = x4 - out1[4] = x5 - out1[5] = x6 - out1[6] = x7 - out1[7] = x8 - out1[8] = x9 +func p521ToMontgomery(out1 *p521MontgomeryDomainFieldElement, arg1 *p521NonMontgomeryDomainFieldElement) { + var x1 uint64 + var x2 uint64 + x2, x1 = bits.Mul64(arg1[0], 0x400000000000) + var x3 uint64 + var x4 uint64 + x4, x3 = bits.Mul64(arg1[1], 0x400000000000) + var x5 uint64 + var x6 uint64 + x5, x6 = bits.Add64(x2, x3, uint64(0x0)) + var x7 uint64 + var x8 uint64 + x8, x7 = bits.Mul64(x1, 0x1ff) + var x9 uint64 + var x10 uint64 + x10, x9 = bits.Mul64(x1, 0xffffffffffffffff) + var x11 uint64 + var x12 uint64 + x12, x11 = bits.Mul64(x1, 0xffffffffffffffff) + var x13 uint64 + var x14 uint64 + x14, x13 = bits.Mul64(x1, 0xffffffffffffffff) + var x15 uint64 + var x16 uint64 + x16, x15 = bits.Mul64(x1, 0xffffffffffffffff) + var x17 uint64 + var x18 uint64 + x18, x17 = bits.Mul64(x1, 0xffffffffffffffff) + var x19 uint64 + var x20 uint64 + x20, x19 = bits.Mul64(x1, 0xffffffffffffffff) + var x21 uint64 + var x22 uint64 + x22, x21 = bits.Mul64(x1, 0xffffffffffffffff) + var x23 uint64 + var x24 uint64 + x24, x23 = bits.Mul64(x1, 0xffffffffffffffff) + var x25 uint64 + var x26 uint64 + x25, x26 = bits.Add64(x24, x21, uint64(0x0)) + var x27 uint64 + var x28 uint64 + x27, x28 = bits.Add64(x22, x19, uint64(p521Uint1(x26))) + var x29 uint64 + var x30 uint64 + x29, x30 = bits.Add64(x20, x17, uint64(p521Uint1(x28))) + var x31 uint64 + var x32 uint64 + x31, x32 = bits.Add64(x18, x15, uint64(p521Uint1(x30))) + var x33 uint64 + var x34 uint64 + x33, x34 = bits.Add64(x16, x13, uint64(p521Uint1(x32))) + var x35 uint64 + var x36 uint64 + x35, x36 = bits.Add64(x14, x11, uint64(p521Uint1(x34))) + var x37 uint64 + var x38 uint64 + x37, x38 = bits.Add64(x12, x9, uint64(p521Uint1(x36))) + var x39 uint64 + var x40 uint64 + x39, x40 = bits.Add64(x10, x7, uint64(p521Uint1(x38))) + var x42 uint64 + _, x42 = bits.Add64(x1, x23, uint64(0x0)) + var x43 uint64 + var x44 uint64 + x43, x44 = bits.Add64(x5, x25, uint64(p521Uint1(x42))) + var x45 uint64 + var x46 uint64 + x45, x46 = bits.Add64((uint64(p521Uint1(x6)) + x4), x27, uint64(p521Uint1(x44))) + var x47 uint64 + var x48 uint64 + x47, x48 = bits.Add64(uint64(0x0), x29, uint64(p521Uint1(x46))) + var x49 uint64 + var x50 uint64 + x49, x50 = bits.Add64(uint64(0x0), x31, uint64(p521Uint1(x48))) + var x51 uint64 + var x52 uint64 + x51, x52 = bits.Add64(uint64(0x0), x33, uint64(p521Uint1(x50))) + var x53 uint64 + var x54 uint64 + x53, x54 = bits.Add64(uint64(0x0), x35, uint64(p521Uint1(x52))) + var x55 uint64 + var x56 uint64 + x55, x56 = bits.Add64(uint64(0x0), x37, uint64(p521Uint1(x54))) + var x57 uint64 + var x58 uint64 + x57, x58 = bits.Add64(uint64(0x0), x39, uint64(p521Uint1(x56))) + var x59 uint64 + var x60 uint64 + x60, x59 = bits.Mul64(arg1[2], 0x400000000000) + var x61 uint64 + var x62 uint64 + x61, x62 = bits.Add64(x45, x59, uint64(0x0)) + var x63 uint64 + var x64 uint64 + x63, x64 = bits.Add64(x47, x60, uint64(p521Uint1(x62))) + var x65 uint64 + var x66 uint64 + x65, x66 = bits.Add64(x49, uint64(0x0), uint64(p521Uint1(x64))) + var x67 uint64 + var x68 uint64 + x67, x68 = bits.Add64(x51, uint64(0x0), uint64(p521Uint1(x66))) + var x69 uint64 + var x70 uint64 + x69, x70 = bits.Add64(x53, uint64(0x0), uint64(p521Uint1(x68))) + var x71 uint64 + var x72 uint64 + x71, x72 = bits.Add64(x55, uint64(0x0), uint64(p521Uint1(x70))) + var x73 uint64 + var x74 uint64 + x73, x74 = bits.Add64(x57, uint64(0x0), uint64(p521Uint1(x72))) + var x75 uint64 + var x76 uint64 + x76, x75 = bits.Mul64(x43, 0x1ff) + var x77 uint64 + var x78 uint64 + x78, x77 = bits.Mul64(x43, 0xffffffffffffffff) + var x79 uint64 + var x80 uint64 + x80, x79 = bits.Mul64(x43, 0xffffffffffffffff) + var x81 uint64 + var x82 uint64 + x82, x81 = bits.Mul64(x43, 0xffffffffffffffff) + var x83 uint64 + var x84 uint64 + x84, x83 = bits.Mul64(x43, 0xffffffffffffffff) + var x85 uint64 + var x86 uint64 + x86, x85 = bits.Mul64(x43, 0xffffffffffffffff) + var x87 uint64 + var x88 uint64 + x88, x87 = bits.Mul64(x43, 0xffffffffffffffff) + var x89 uint64 + var x90 uint64 + x90, x89 = bits.Mul64(x43, 0xffffffffffffffff) + var x91 uint64 + var x92 uint64 + x92, x91 = bits.Mul64(x43, 0xffffffffffffffff) + var x93 uint64 + var x94 uint64 + x93, x94 = bits.Add64(x92, x89, uint64(0x0)) + var x95 uint64 + var x96 uint64 + x95, x96 = bits.Add64(x90, x87, uint64(p521Uint1(x94))) + var x97 uint64 + var x98 uint64 + x97, x98 = bits.Add64(x88, x85, uint64(p521Uint1(x96))) + var x99 uint64 + var x100 uint64 + x99, x100 = bits.Add64(x86, x83, uint64(p521Uint1(x98))) + var x101 uint64 + var x102 uint64 + x101, x102 = bits.Add64(x84, x81, uint64(p521Uint1(x100))) + var x103 uint64 + var x104 uint64 + x103, x104 = bits.Add64(x82, x79, uint64(p521Uint1(x102))) + var x105 uint64 + var x106 uint64 + x105, x106 = bits.Add64(x80, x77, uint64(p521Uint1(x104))) + var x107 uint64 + var x108 uint64 + x107, x108 = bits.Add64(x78, x75, uint64(p521Uint1(x106))) + var x110 uint64 + _, x110 = bits.Add64(x43, x91, uint64(0x0)) + var x111 uint64 + var x112 uint64 + x111, x112 = bits.Add64(x61, x93, uint64(p521Uint1(x110))) + var x113 uint64 + var x114 uint64 + x113, x114 = bits.Add64(x63, x95, uint64(p521Uint1(x112))) + var x115 uint64 + var x116 uint64 + x115, x116 = bits.Add64(x65, x97, uint64(p521Uint1(x114))) + var x117 uint64 + var x118 uint64 + x117, x118 = bits.Add64(x67, x99, uint64(p521Uint1(x116))) + var x119 uint64 + var x120 uint64 + x119, x120 = bits.Add64(x69, x101, uint64(p521Uint1(x118))) + var x121 uint64 + var x122 uint64 + x121, x122 = bits.Add64(x71, x103, uint64(p521Uint1(x120))) + var x123 uint64 + var x124 uint64 + x123, x124 = bits.Add64(x73, x105, uint64(p521Uint1(x122))) + var x125 uint64 + var x126 uint64 + x125, x126 = bits.Add64((uint64(p521Uint1(x74)) + (uint64(p521Uint1(x58)) + (uint64(p521Uint1(x40)) + x8))), x107, uint64(p521Uint1(x124))) + var x127 uint64 + var x128 uint64 + x128, x127 = bits.Mul64(arg1[3], 0x400000000000) + var x129 uint64 + var x130 uint64 + x129, x130 = bits.Add64(x113, x127, uint64(0x0)) + var x131 uint64 + var x132 uint64 + x131, x132 = bits.Add64(x115, x128, uint64(p521Uint1(x130))) + var x133 uint64 + var x134 uint64 + x133, x134 = bits.Add64(x117, uint64(0x0), uint64(p521Uint1(x132))) + var x135 uint64 + var x136 uint64 + x135, x136 = bits.Add64(x119, uint64(0x0), uint64(p521Uint1(x134))) + var x137 uint64 + var x138 uint64 + x137, x138 = bits.Add64(x121, uint64(0x0), uint64(p521Uint1(x136))) + var x139 uint64 + var x140 uint64 + x139, x140 = bits.Add64(x123, uint64(0x0), uint64(p521Uint1(x138))) + var x141 uint64 + var x142 uint64 + x141, x142 = bits.Add64(x125, uint64(0x0), uint64(p521Uint1(x140))) + var x143 uint64 + var x144 uint64 + x144, x143 = bits.Mul64(x111, 0x1ff) + var x145 uint64 + var x146 uint64 + x146, x145 = bits.Mul64(x111, 0xffffffffffffffff) + var x147 uint64 + var x148 uint64 + x148, x147 = bits.Mul64(x111, 0xffffffffffffffff) + var x149 uint64 + var x150 uint64 + x150, x149 = bits.Mul64(x111, 0xffffffffffffffff) + var x151 uint64 + var x152 uint64 + x152, x151 = bits.Mul64(x111, 0xffffffffffffffff) + var x153 uint64 + var x154 uint64 + x154, x153 = bits.Mul64(x111, 0xffffffffffffffff) + var x155 uint64 + var x156 uint64 + x156, x155 = bits.Mul64(x111, 0xffffffffffffffff) + var x157 uint64 + var x158 uint64 + x158, x157 = bits.Mul64(x111, 0xffffffffffffffff) + var x159 uint64 + var x160 uint64 + x160, x159 = bits.Mul64(x111, 0xffffffffffffffff) + var x161 uint64 + var x162 uint64 + x161, x162 = bits.Add64(x160, x157, uint64(0x0)) + var x163 uint64 + var x164 uint64 + x163, x164 = bits.Add64(x158, x155, uint64(p521Uint1(x162))) + var x165 uint64 + var x166 uint64 + x165, x166 = bits.Add64(x156, x153, uint64(p521Uint1(x164))) + var x167 uint64 + var x168 uint64 + x167, x168 = bits.Add64(x154, x151, uint64(p521Uint1(x166))) + var x169 uint64 + var x170 uint64 + x169, x170 = bits.Add64(x152, x149, uint64(p521Uint1(x168))) + var x171 uint64 + var x172 uint64 + x171, x172 = bits.Add64(x150, x147, uint64(p521Uint1(x170))) + var x173 uint64 + var x174 uint64 + x173, x174 = bits.Add64(x148, x145, uint64(p521Uint1(x172))) + var x175 uint64 + var x176 uint64 + x175, x176 = bits.Add64(x146, x143, uint64(p521Uint1(x174))) + var x178 uint64 + _, x178 = bits.Add64(x111, x159, uint64(0x0)) + var x179 uint64 + var x180 uint64 + x179, x180 = bits.Add64(x129, x161, uint64(p521Uint1(x178))) + var x181 uint64 + var x182 uint64 + x181, x182 = bits.Add64(x131, x163, uint64(p521Uint1(x180))) + var x183 uint64 + var x184 uint64 + x183, x184 = bits.Add64(x133, x165, uint64(p521Uint1(x182))) + var x185 uint64 + var x186 uint64 + x185, x186 = bits.Add64(x135, x167, uint64(p521Uint1(x184))) + var x187 uint64 + var x188 uint64 + x187, x188 = bits.Add64(x137, x169, uint64(p521Uint1(x186))) + var x189 uint64 + var x190 uint64 + x189, x190 = bits.Add64(x139, x171, uint64(p521Uint1(x188))) + var x191 uint64 + var x192 uint64 + x191, x192 = bits.Add64(x141, x173, uint64(p521Uint1(x190))) + var x193 uint64 + var x194 uint64 + x193, x194 = bits.Add64((uint64(p521Uint1(x142)) + (uint64(p521Uint1(x126)) + (uint64(p521Uint1(x108)) + x76))), x175, uint64(p521Uint1(x192))) + var x195 uint64 + var x196 uint64 + x196, x195 = bits.Mul64(arg1[4], 0x400000000000) + var x197 uint64 + var x198 uint64 + x197, x198 = bits.Add64(x181, x195, uint64(0x0)) + var x199 uint64 + var x200 uint64 + x199, x200 = bits.Add64(x183, x196, uint64(p521Uint1(x198))) + var x201 uint64 + var x202 uint64 + x201, x202 = bits.Add64(x185, uint64(0x0), uint64(p521Uint1(x200))) + var x203 uint64 + var x204 uint64 + x203, x204 = bits.Add64(x187, uint64(0x0), uint64(p521Uint1(x202))) + var x205 uint64 + var x206 uint64 + x205, x206 = bits.Add64(x189, uint64(0x0), uint64(p521Uint1(x204))) + var x207 uint64 + var x208 uint64 + x207, x208 = bits.Add64(x191, uint64(0x0), uint64(p521Uint1(x206))) + var x209 uint64 + var x210 uint64 + x209, x210 = bits.Add64(x193, uint64(0x0), uint64(p521Uint1(x208))) + var x211 uint64 + var x212 uint64 + x212, x211 = bits.Mul64(x179, 0x1ff) + var x213 uint64 + var x214 uint64 + x214, x213 = bits.Mul64(x179, 0xffffffffffffffff) + var x215 uint64 + var x216 uint64 + x216, x215 = bits.Mul64(x179, 0xffffffffffffffff) + var x217 uint64 + var x218 uint64 + x218, x217 = bits.Mul64(x179, 0xffffffffffffffff) + var x219 uint64 + var x220 uint64 + x220, x219 = bits.Mul64(x179, 0xffffffffffffffff) + var x221 uint64 + var x222 uint64 + x222, x221 = bits.Mul64(x179, 0xffffffffffffffff) + var x223 uint64 + var x224 uint64 + x224, x223 = bits.Mul64(x179, 0xffffffffffffffff) + var x225 uint64 + var x226 uint64 + x226, x225 = bits.Mul64(x179, 0xffffffffffffffff) + var x227 uint64 + var x228 uint64 + x228, x227 = bits.Mul64(x179, 0xffffffffffffffff) + var x229 uint64 + var x230 uint64 + x229, x230 = bits.Add64(x228, x225, uint64(0x0)) + var x231 uint64 + var x232 uint64 + x231, x232 = bits.Add64(x226, x223, uint64(p521Uint1(x230))) + var x233 uint64 + var x234 uint64 + x233, x234 = bits.Add64(x224, x221, uint64(p521Uint1(x232))) + var x235 uint64 + var x236 uint64 + x235, x236 = bits.Add64(x222, x219, uint64(p521Uint1(x234))) + var x237 uint64 + var x238 uint64 + x237, x238 = bits.Add64(x220, x217, uint64(p521Uint1(x236))) + var x239 uint64 + var x240 uint64 + x239, x240 = bits.Add64(x218, x215, uint64(p521Uint1(x238))) + var x241 uint64 + var x242 uint64 + x241, x242 = bits.Add64(x216, x213, uint64(p521Uint1(x240))) + var x243 uint64 + var x244 uint64 + x243, x244 = bits.Add64(x214, x211, uint64(p521Uint1(x242))) + var x246 uint64 + _, x246 = bits.Add64(x179, x227, uint64(0x0)) + var x247 uint64 + var x248 uint64 + x247, x248 = bits.Add64(x197, x229, uint64(p521Uint1(x246))) + var x249 uint64 + var x250 uint64 + x249, x250 = bits.Add64(x199, x231, uint64(p521Uint1(x248))) + var x251 uint64 + var x252 uint64 + x251, x252 = bits.Add64(x201, x233, uint64(p521Uint1(x250))) + var x253 uint64 + var x254 uint64 + x253, x254 = bits.Add64(x203, x235, uint64(p521Uint1(x252))) + var x255 uint64 + var x256 uint64 + x255, x256 = bits.Add64(x205, x237, uint64(p521Uint1(x254))) + var x257 uint64 + var x258 uint64 + x257, x258 = bits.Add64(x207, x239, uint64(p521Uint1(x256))) + var x259 uint64 + var x260 uint64 + x259, x260 = bits.Add64(x209, x241, uint64(p521Uint1(x258))) + var x261 uint64 + var x262 uint64 + x261, x262 = bits.Add64((uint64(p521Uint1(x210)) + (uint64(p521Uint1(x194)) + (uint64(p521Uint1(x176)) + x144))), x243, uint64(p521Uint1(x260))) + var x263 uint64 + var x264 uint64 + x264, x263 = bits.Mul64(arg1[5], 0x400000000000) + var x265 uint64 + var x266 uint64 + x265, x266 = bits.Add64(x249, x263, uint64(0x0)) + var x267 uint64 + var x268 uint64 + x267, x268 = bits.Add64(x251, x264, uint64(p521Uint1(x266))) + var x269 uint64 + var x270 uint64 + x269, x270 = bits.Add64(x253, uint64(0x0), uint64(p521Uint1(x268))) + var x271 uint64 + var x272 uint64 + x271, x272 = bits.Add64(x255, uint64(0x0), uint64(p521Uint1(x270))) + var x273 uint64 + var x274 uint64 + x273, x274 = bits.Add64(x257, uint64(0x0), uint64(p521Uint1(x272))) + var x275 uint64 + var x276 uint64 + x275, x276 = bits.Add64(x259, uint64(0x0), uint64(p521Uint1(x274))) + var x277 uint64 + var x278 uint64 + x277, x278 = bits.Add64(x261, uint64(0x0), uint64(p521Uint1(x276))) + var x279 uint64 + var x280 uint64 + x280, x279 = bits.Mul64(x247, 0x1ff) + var x281 uint64 + var x282 uint64 + x282, x281 = bits.Mul64(x247, 0xffffffffffffffff) + var x283 uint64 + var x284 uint64 + x284, x283 = bits.Mul64(x247, 0xffffffffffffffff) + var x285 uint64 + var x286 uint64 + x286, x285 = bits.Mul64(x247, 0xffffffffffffffff) + var x287 uint64 + var x288 uint64 + x288, x287 = bits.Mul64(x247, 0xffffffffffffffff) + var x289 uint64 + var x290 uint64 + x290, x289 = bits.Mul64(x247, 0xffffffffffffffff) + var x291 uint64 + var x292 uint64 + x292, x291 = bits.Mul64(x247, 0xffffffffffffffff) + var x293 uint64 + var x294 uint64 + x294, x293 = bits.Mul64(x247, 0xffffffffffffffff) + var x295 uint64 + var x296 uint64 + x296, x295 = bits.Mul64(x247, 0xffffffffffffffff) + var x297 uint64 + var x298 uint64 + x297, x298 = bits.Add64(x296, x293, uint64(0x0)) + var x299 uint64 + var x300 uint64 + x299, x300 = bits.Add64(x294, x291, uint64(p521Uint1(x298))) + var x301 uint64 + var x302 uint64 + x301, x302 = bits.Add64(x292, x289, uint64(p521Uint1(x300))) + var x303 uint64 + var x304 uint64 + x303, x304 = bits.Add64(x290, x287, uint64(p521Uint1(x302))) + var x305 uint64 + var x306 uint64 + x305, x306 = bits.Add64(x288, x285, uint64(p521Uint1(x304))) + var x307 uint64 + var x308 uint64 + x307, x308 = bits.Add64(x286, x283, uint64(p521Uint1(x306))) + var x309 uint64 + var x310 uint64 + x309, x310 = bits.Add64(x284, x281, uint64(p521Uint1(x308))) + var x311 uint64 + var x312 uint64 + x311, x312 = bits.Add64(x282, x279, uint64(p521Uint1(x310))) + var x314 uint64 + _, x314 = bits.Add64(x247, x295, uint64(0x0)) + var x315 uint64 + var x316 uint64 + x315, x316 = bits.Add64(x265, x297, uint64(p521Uint1(x314))) + var x317 uint64 + var x318 uint64 + x317, x318 = bits.Add64(x267, x299, uint64(p521Uint1(x316))) + var x319 uint64 + var x320 uint64 + x319, x320 = bits.Add64(x269, x301, uint64(p521Uint1(x318))) + var x321 uint64 + var x322 uint64 + x321, x322 = bits.Add64(x271, x303, uint64(p521Uint1(x320))) + var x323 uint64 + var x324 uint64 + x323, x324 = bits.Add64(x273, x305, uint64(p521Uint1(x322))) + var x325 uint64 + var x326 uint64 + x325, x326 = bits.Add64(x275, x307, uint64(p521Uint1(x324))) + var x327 uint64 + var x328 uint64 + x327, x328 = bits.Add64(x277, x309, uint64(p521Uint1(x326))) + var x329 uint64 + var x330 uint64 + x329, x330 = bits.Add64((uint64(p521Uint1(x278)) + (uint64(p521Uint1(x262)) + (uint64(p521Uint1(x244)) + x212))), x311, uint64(p521Uint1(x328))) + var x331 uint64 + var x332 uint64 + x332, x331 = bits.Mul64(arg1[6], 0x400000000000) + var x333 uint64 + var x334 uint64 + x333, x334 = bits.Add64(x317, x331, uint64(0x0)) + var x335 uint64 + var x336 uint64 + x335, x336 = bits.Add64(x319, x332, uint64(p521Uint1(x334))) + var x337 uint64 + var x338 uint64 + x337, x338 = bits.Add64(x321, uint64(0x0), uint64(p521Uint1(x336))) + var x339 uint64 + var x340 uint64 + x339, x340 = bits.Add64(x323, uint64(0x0), uint64(p521Uint1(x338))) + var x341 uint64 + var x342 uint64 + x341, x342 = bits.Add64(x325, uint64(0x0), uint64(p521Uint1(x340))) + var x343 uint64 + var x344 uint64 + x343, x344 = bits.Add64(x327, uint64(0x0), uint64(p521Uint1(x342))) + var x345 uint64 + var x346 uint64 + x345, x346 = bits.Add64(x329, uint64(0x0), uint64(p521Uint1(x344))) + var x347 uint64 + var x348 uint64 + x348, x347 = bits.Mul64(x315, 0x1ff) + var x349 uint64 + var x350 uint64 + x350, x349 = bits.Mul64(x315, 0xffffffffffffffff) + var x351 uint64 + var x352 uint64 + x352, x351 = bits.Mul64(x315, 0xffffffffffffffff) + var x353 uint64 + var x354 uint64 + x354, x353 = bits.Mul64(x315, 0xffffffffffffffff) + var x355 uint64 + var x356 uint64 + x356, x355 = bits.Mul64(x315, 0xffffffffffffffff) + var x357 uint64 + var x358 uint64 + x358, x357 = bits.Mul64(x315, 0xffffffffffffffff) + var x359 uint64 + var x360 uint64 + x360, x359 = bits.Mul64(x315, 0xffffffffffffffff) + var x361 uint64 + var x362 uint64 + x362, x361 = bits.Mul64(x315, 0xffffffffffffffff) + var x363 uint64 + var x364 uint64 + x364, x363 = bits.Mul64(x315, 0xffffffffffffffff) + var x365 uint64 + var x366 uint64 + x365, x366 = bits.Add64(x364, x361, uint64(0x0)) + var x367 uint64 + var x368 uint64 + x367, x368 = bits.Add64(x362, x359, uint64(p521Uint1(x366))) + var x369 uint64 + var x370 uint64 + x369, x370 = bits.Add64(x360, x357, uint64(p521Uint1(x368))) + var x371 uint64 + var x372 uint64 + x371, x372 = bits.Add64(x358, x355, uint64(p521Uint1(x370))) + var x373 uint64 + var x374 uint64 + x373, x374 = bits.Add64(x356, x353, uint64(p521Uint1(x372))) + var x375 uint64 + var x376 uint64 + x375, x376 = bits.Add64(x354, x351, uint64(p521Uint1(x374))) + var x377 uint64 + var x378 uint64 + x377, x378 = bits.Add64(x352, x349, uint64(p521Uint1(x376))) + var x379 uint64 + var x380 uint64 + x379, x380 = bits.Add64(x350, x347, uint64(p521Uint1(x378))) + var x382 uint64 + _, x382 = bits.Add64(x315, x363, uint64(0x0)) + var x383 uint64 + var x384 uint64 + x383, x384 = bits.Add64(x333, x365, uint64(p521Uint1(x382))) + var x385 uint64 + var x386 uint64 + x385, x386 = bits.Add64(x335, x367, uint64(p521Uint1(x384))) + var x387 uint64 + var x388 uint64 + x387, x388 = bits.Add64(x337, x369, uint64(p521Uint1(x386))) + var x389 uint64 + var x390 uint64 + x389, x390 = bits.Add64(x339, x371, uint64(p521Uint1(x388))) + var x391 uint64 + var x392 uint64 + x391, x392 = bits.Add64(x341, x373, uint64(p521Uint1(x390))) + var x393 uint64 + var x394 uint64 + x393, x394 = bits.Add64(x343, x375, uint64(p521Uint1(x392))) + var x395 uint64 + var x396 uint64 + x395, x396 = bits.Add64(x345, x377, uint64(p521Uint1(x394))) + var x397 uint64 + var x398 uint64 + x397, x398 = bits.Add64((uint64(p521Uint1(x346)) + (uint64(p521Uint1(x330)) + (uint64(p521Uint1(x312)) + x280))), x379, uint64(p521Uint1(x396))) + var x399 uint64 + var x400 uint64 + x400, x399 = bits.Mul64(arg1[7], 0x400000000000) + var x401 uint64 + var x402 uint64 + x401, x402 = bits.Add64(x385, x399, uint64(0x0)) + var x403 uint64 + var x404 uint64 + x403, x404 = bits.Add64(x387, x400, uint64(p521Uint1(x402))) + var x405 uint64 + var x406 uint64 + x405, x406 = bits.Add64(x389, uint64(0x0), uint64(p521Uint1(x404))) + var x407 uint64 + var x408 uint64 + x407, x408 = bits.Add64(x391, uint64(0x0), uint64(p521Uint1(x406))) + var x409 uint64 + var x410 uint64 + x409, x410 = bits.Add64(x393, uint64(0x0), uint64(p521Uint1(x408))) + var x411 uint64 + var x412 uint64 + x411, x412 = bits.Add64(x395, uint64(0x0), uint64(p521Uint1(x410))) + var x413 uint64 + var x414 uint64 + x413, x414 = bits.Add64(x397, uint64(0x0), uint64(p521Uint1(x412))) + var x415 uint64 + var x416 uint64 + x416, x415 = bits.Mul64(x383, 0x1ff) + var x417 uint64 + var x418 uint64 + x418, x417 = bits.Mul64(x383, 0xffffffffffffffff) + var x419 uint64 + var x420 uint64 + x420, x419 = bits.Mul64(x383, 0xffffffffffffffff) + var x421 uint64 + var x422 uint64 + x422, x421 = bits.Mul64(x383, 0xffffffffffffffff) + var x423 uint64 + var x424 uint64 + x424, x423 = bits.Mul64(x383, 0xffffffffffffffff) + var x425 uint64 + var x426 uint64 + x426, x425 = bits.Mul64(x383, 0xffffffffffffffff) + var x427 uint64 + var x428 uint64 + x428, x427 = bits.Mul64(x383, 0xffffffffffffffff) + var x429 uint64 + var x430 uint64 + x430, x429 = bits.Mul64(x383, 0xffffffffffffffff) + var x431 uint64 + var x432 uint64 + x432, x431 = bits.Mul64(x383, 0xffffffffffffffff) + var x433 uint64 + var x434 uint64 + x433, x434 = bits.Add64(x432, x429, uint64(0x0)) + var x435 uint64 + var x436 uint64 + x435, x436 = bits.Add64(x430, x427, uint64(p521Uint1(x434))) + var x437 uint64 + var x438 uint64 + x437, x438 = bits.Add64(x428, x425, uint64(p521Uint1(x436))) + var x439 uint64 + var x440 uint64 + x439, x440 = bits.Add64(x426, x423, uint64(p521Uint1(x438))) + var x441 uint64 + var x442 uint64 + x441, x442 = bits.Add64(x424, x421, uint64(p521Uint1(x440))) + var x443 uint64 + var x444 uint64 + x443, x444 = bits.Add64(x422, x419, uint64(p521Uint1(x442))) + var x445 uint64 + var x446 uint64 + x445, x446 = bits.Add64(x420, x417, uint64(p521Uint1(x444))) + var x447 uint64 + var x448 uint64 + x447, x448 = bits.Add64(x418, x415, uint64(p521Uint1(x446))) + var x450 uint64 + _, x450 = bits.Add64(x383, x431, uint64(0x0)) + var x451 uint64 + var x452 uint64 + x451, x452 = bits.Add64(x401, x433, uint64(p521Uint1(x450))) + var x453 uint64 + var x454 uint64 + x453, x454 = bits.Add64(x403, x435, uint64(p521Uint1(x452))) + var x455 uint64 + var x456 uint64 + x455, x456 = bits.Add64(x405, x437, uint64(p521Uint1(x454))) + var x457 uint64 + var x458 uint64 + x457, x458 = bits.Add64(x407, x439, uint64(p521Uint1(x456))) + var x459 uint64 + var x460 uint64 + x459, x460 = bits.Add64(x409, x441, uint64(p521Uint1(x458))) + var x461 uint64 + var x462 uint64 + x461, x462 = bits.Add64(x411, x443, uint64(p521Uint1(x460))) + var x463 uint64 + var x464 uint64 + x463, x464 = bits.Add64(x413, x445, uint64(p521Uint1(x462))) + var x465 uint64 + var x466 uint64 + x465, x466 = bits.Add64((uint64(p521Uint1(x414)) + (uint64(p521Uint1(x398)) + (uint64(p521Uint1(x380)) + x348))), x447, uint64(p521Uint1(x464))) + var x467 uint64 + var x468 uint64 + x468, x467 = bits.Mul64(arg1[8], 0x400000000000) + var x469 uint64 + var x470 uint64 + x469, x470 = bits.Add64(x453, x467, uint64(0x0)) + var x471 uint64 + var x472 uint64 + x471, x472 = bits.Add64(x455, x468, uint64(p521Uint1(x470))) + var x473 uint64 + var x474 uint64 + x473, x474 = bits.Add64(x457, uint64(0x0), uint64(p521Uint1(x472))) + var x475 uint64 + var x476 uint64 + x475, x476 = bits.Add64(x459, uint64(0x0), uint64(p521Uint1(x474))) + var x477 uint64 + var x478 uint64 + x477, x478 = bits.Add64(x461, uint64(0x0), uint64(p521Uint1(x476))) + var x479 uint64 + var x480 uint64 + x479, x480 = bits.Add64(x463, uint64(0x0), uint64(p521Uint1(x478))) + var x481 uint64 + var x482 uint64 + x481, x482 = bits.Add64(x465, uint64(0x0), uint64(p521Uint1(x480))) + var x483 uint64 + var x484 uint64 + x484, x483 = bits.Mul64(x451, 0x1ff) + var x485 uint64 + var x486 uint64 + x486, x485 = bits.Mul64(x451, 0xffffffffffffffff) + var x487 uint64 + var x488 uint64 + x488, x487 = bits.Mul64(x451, 0xffffffffffffffff) + var x489 uint64 + var x490 uint64 + x490, x489 = bits.Mul64(x451, 0xffffffffffffffff) + var x491 uint64 + var x492 uint64 + x492, x491 = bits.Mul64(x451, 0xffffffffffffffff) + var x493 uint64 + var x494 uint64 + x494, x493 = bits.Mul64(x451, 0xffffffffffffffff) + var x495 uint64 + var x496 uint64 + x496, x495 = bits.Mul64(x451, 0xffffffffffffffff) + var x497 uint64 + var x498 uint64 + x498, x497 = bits.Mul64(x451, 0xffffffffffffffff) + var x499 uint64 + var x500 uint64 + x500, x499 = bits.Mul64(x451, 0xffffffffffffffff) + var x501 uint64 + var x502 uint64 + x501, x502 = bits.Add64(x500, x497, uint64(0x0)) + var x503 uint64 + var x504 uint64 + x503, x504 = bits.Add64(x498, x495, uint64(p521Uint1(x502))) + var x505 uint64 + var x506 uint64 + x505, x506 = bits.Add64(x496, x493, uint64(p521Uint1(x504))) + var x507 uint64 + var x508 uint64 + x507, x508 = bits.Add64(x494, x491, uint64(p521Uint1(x506))) + var x509 uint64 + var x510 uint64 + x509, x510 = bits.Add64(x492, x489, uint64(p521Uint1(x508))) + var x511 uint64 + var x512 uint64 + x511, x512 = bits.Add64(x490, x487, uint64(p521Uint1(x510))) + var x513 uint64 + var x514 uint64 + x513, x514 = bits.Add64(x488, x485, uint64(p521Uint1(x512))) + var x515 uint64 + var x516 uint64 + x515, x516 = bits.Add64(x486, x483, uint64(p521Uint1(x514))) + var x518 uint64 + _, x518 = bits.Add64(x451, x499, uint64(0x0)) + var x519 uint64 + var x520 uint64 + x519, x520 = bits.Add64(x469, x501, uint64(p521Uint1(x518))) + var x521 uint64 + var x522 uint64 + x521, x522 = bits.Add64(x471, x503, uint64(p521Uint1(x520))) + var x523 uint64 + var x524 uint64 + x523, x524 = bits.Add64(x473, x505, uint64(p521Uint1(x522))) + var x525 uint64 + var x526 uint64 + x525, x526 = bits.Add64(x475, x507, uint64(p521Uint1(x524))) + var x527 uint64 + var x528 uint64 + x527, x528 = bits.Add64(x477, x509, uint64(p521Uint1(x526))) + var x529 uint64 + var x530 uint64 + x529, x530 = bits.Add64(x479, x511, uint64(p521Uint1(x528))) + var x531 uint64 + var x532 uint64 + x531, x532 = bits.Add64(x481, x513, uint64(p521Uint1(x530))) + var x533 uint64 + var x534 uint64 + x533, x534 = bits.Add64((uint64(p521Uint1(x482)) + (uint64(p521Uint1(x466)) + (uint64(p521Uint1(x448)) + x416))), x515, uint64(p521Uint1(x532))) + x535 := (uint64(p521Uint1(x534)) + (uint64(p521Uint1(x516)) + x484)) + var x536 uint64 + var x537 uint64 + x536, x537 = bits.Sub64(x519, 0xffffffffffffffff, uint64(0x0)) + var x538 uint64 + var x539 uint64 + x538, x539 = bits.Sub64(x521, 0xffffffffffffffff, uint64(p521Uint1(x537))) + var x540 uint64 + var x541 uint64 + x540, x541 = bits.Sub64(x523, 0xffffffffffffffff, uint64(p521Uint1(x539))) + var x542 uint64 + var x543 uint64 + x542, x543 = bits.Sub64(x525, 0xffffffffffffffff, uint64(p521Uint1(x541))) + var x544 uint64 + var x545 uint64 + x544, x545 = bits.Sub64(x527, 0xffffffffffffffff, uint64(p521Uint1(x543))) + var x546 uint64 + var x547 uint64 + x546, x547 = bits.Sub64(x529, 0xffffffffffffffff, uint64(p521Uint1(x545))) + var x548 uint64 + var x549 uint64 + x548, x549 = bits.Sub64(x531, 0xffffffffffffffff, uint64(p521Uint1(x547))) + var x550 uint64 + var x551 uint64 + x550, x551 = bits.Sub64(x533, 0xffffffffffffffff, uint64(p521Uint1(x549))) + var x552 uint64 + var x553 uint64 + x552, x553 = bits.Sub64(x535, 0x1ff, uint64(p521Uint1(x551))) + var x555 uint64 + _, x555 = bits.Sub64(uint64(0x0), uint64(0x0), uint64(p521Uint1(x553))) + var x556 uint64 + p521CmovznzU64(&x556, p521Uint1(x555), x536, x519) + var x557 uint64 + p521CmovznzU64(&x557, p521Uint1(x555), x538, x521) + var x558 uint64 + p521CmovznzU64(&x558, p521Uint1(x555), x540, x523) + var x559 uint64 + p521CmovznzU64(&x559, p521Uint1(x555), x542, x525) + var x560 uint64 + p521CmovznzU64(&x560, p521Uint1(x555), x544, x527) + var x561 uint64 + p521CmovznzU64(&x561, p521Uint1(x555), x546, x529) + var x562 uint64 + p521CmovznzU64(&x562, p521Uint1(x555), x548, x531) + var x563 uint64 + p521CmovznzU64(&x563, p521Uint1(x555), x550, x533) + var x564 uint64 + p521CmovznzU64(&x564, p521Uint1(x555), x552, x535) + out1[0] = x556 + out1[1] = x557 + out1[2] = x558 + out1[3] = x559 + out1[4] = x560 + out1[5] = x561 + out1[6] = x562 + out1[7] = x563 + out1[8] = x564 } -// p521Sub subtracts two field elements. +// p521Selectznz is a multi-limb conditional select. // // Postconditions: -// eval out1 mod m = (eval arg1 - eval arg2) mod m +// eval out1 = (if arg1 = 0 then eval arg2 else eval arg3) // // Input Bounds: -// arg1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] -// arg2: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] +// arg1: [0x0 ~> 0x1] +// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +// arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] // Output Bounds: -// out1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]] -func p521Sub(out1 *[9]uint64, arg1 *[9]uint64, arg2 *[9]uint64) { - x1 := ((0x7fffffffffffffe + arg1[0]) - arg2[0]) - x2 := ((0x7fffffffffffffe + arg1[1]) - arg2[1]) - x3 := ((0x7fffffffffffffe + arg1[2]) - arg2[2]) - x4 := ((0x7fffffffffffffe + arg1[3]) - arg2[3]) - x5 := ((0x7fffffffffffffe + arg1[4]) - arg2[4]) - x6 := ((0x7fffffffffffffe + arg1[5]) - arg2[5]) - x7 := ((0x7fffffffffffffe + arg1[6]) - arg2[6]) - x8 := ((0x7fffffffffffffe + arg1[7]) - arg2[7]) - x9 := ((0x3fffffffffffffe + arg1[8]) - arg2[8]) +// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +func p521Selectznz(out1 *[9]uint64, arg1 p521Uint1, arg2 *[9]uint64, arg3 *[9]uint64) { + var x1 uint64 + p521CmovznzU64(&x1, arg1, arg2[0], arg3[0]) + var x2 uint64 + p521CmovznzU64(&x2, arg1, arg2[1], arg3[1]) + var x3 uint64 + p521CmovznzU64(&x3, arg1, arg2[2], arg3[2]) + var x4 uint64 + p521CmovznzU64(&x4, arg1, arg2[3], arg3[3]) + var x5 uint64 + p521CmovznzU64(&x5, arg1, arg2[4], arg3[4]) + var x6 uint64 + p521CmovznzU64(&x6, arg1, arg2[5], arg3[5]) + var x7 uint64 + p521CmovznzU64(&x7, arg1, arg2[6], arg3[6]) + var x8 uint64 + p521CmovznzU64(&x8, arg1, arg2[7], arg3[7]) + var x9 uint64 + p521CmovznzU64(&x9, arg1, arg2[8], arg3[8]) out1[0] = x1 out1[1] = x2 out1[2] = x3 @@ -1380,346 +5158,280 @@ func p521Sub(out1 *[9]uint64, arg1 *[9]uint64, arg2 *[9]uint64) { out1[8] = x9 } -// p521ToBytes serializes a field element to bytes in little-endian order. +// p521ToBytes serializes a field element NOT in the Montgomery domain to bytes in little-endian order. // +// Preconditions: +// 0 ≤ eval arg1 < m // Postconditions: // out1 = map (λ x, ⌊((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)⌋) [0..65] // // Input Bounds: -// arg1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] +// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0x1ff]] // Output Bounds: // out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x1]] func p521ToBytes(out1 *[66]uint8, arg1 *[9]uint64) { - var x1 uint64 - var x2 p521Uint1 - p521SubborrowxU58(&x1, &x2, 0x0, arg1[0], 0x3ffffffffffffff) - var x3 uint64 - var x4 p521Uint1 - p521SubborrowxU58(&x3, &x4, x2, arg1[1], 0x3ffffffffffffff) - var x5 uint64 - var x6 p521Uint1 - p521SubborrowxU58(&x5, &x6, x4, arg1[2], 0x3ffffffffffffff) - var x7 uint64 - var x8 p521Uint1 - p521SubborrowxU58(&x7, &x8, x6, arg1[3], 0x3ffffffffffffff) - var x9 uint64 - var x10 p521Uint1 - p521SubborrowxU58(&x9, &x10, x8, arg1[4], 0x3ffffffffffffff) - var x11 uint64 - var x12 p521Uint1 - p521SubborrowxU58(&x11, &x12, x10, arg1[5], 0x3ffffffffffffff) - var x13 uint64 - var x14 p521Uint1 - p521SubborrowxU58(&x13, &x14, x12, arg1[6], 0x3ffffffffffffff) - var x15 uint64 - var x16 p521Uint1 - p521SubborrowxU58(&x15, &x16, x14, arg1[7], 0x3ffffffffffffff) - var x17 uint64 - var x18 p521Uint1 - p521SubborrowxU57(&x17, &x18, x16, arg1[8], 0x1ffffffffffffff) - var x19 uint64 - p521CmovznzU64(&x19, x18, uint64(0x0), 0xffffffffffffffff) - var x20 uint64 - var x21 p521Uint1 - p521AddcarryxU58(&x20, &x21, 0x0, x1, (x19 & 0x3ffffffffffffff)) - var x22 uint64 - var x23 p521Uint1 - p521AddcarryxU58(&x22, &x23, x21, x3, (x19 & 0x3ffffffffffffff)) - var x24 uint64 - var x25 p521Uint1 - p521AddcarryxU58(&x24, &x25, x23, x5, (x19 & 0x3ffffffffffffff)) - var x26 uint64 - var x27 p521Uint1 - p521AddcarryxU58(&x26, &x27, x25, x7, (x19 & 0x3ffffffffffffff)) - var x28 uint64 - var x29 p521Uint1 - p521AddcarryxU58(&x28, &x29, x27, x9, (x19 & 0x3ffffffffffffff)) - var x30 uint64 - var x31 p521Uint1 - p521AddcarryxU58(&x30, &x31, x29, x11, (x19 & 0x3ffffffffffffff)) - var x32 uint64 - var x33 p521Uint1 - p521AddcarryxU58(&x32, &x33, x31, x13, (x19 & 0x3ffffffffffffff)) - var x34 uint64 - var x35 p521Uint1 - p521AddcarryxU58(&x34, &x35, x33, x15, (x19 & 0x3ffffffffffffff)) - var x36 uint64 - var x37 p521Uint1 - p521AddcarryxU57(&x36, &x37, x35, x17, (x19 & 0x1ffffffffffffff)) - x38 := (x34 << 6) - x39 := (x32 << 4) - x40 := (x30 << 2) - x41 := (x26 << 6) - x42 := (x24 << 4) - x43 := (x22 << 2) - x44 := (uint8(x20) & 0xff) - x45 := (x20 >> 8) + x1 := arg1[8] + x2 := arg1[7] + x3 := arg1[6] + x4 := arg1[5] + x5 := arg1[4] + x6 := arg1[3] + x7 := arg1[2] + x8 := arg1[1] + x9 := arg1[0] + x10 := (uint8(x9) & 0xff) + x11 := (x9 >> 8) + x12 := (uint8(x11) & 0xff) + x13 := (x11 >> 8) + x14 := (uint8(x13) & 0xff) + x15 := (x13 >> 8) + x16 := (uint8(x15) & 0xff) + x17 := (x15 >> 8) + x18 := (uint8(x17) & 0xff) + x19 := (x17 >> 8) + x20 := (uint8(x19) & 0xff) + x21 := (x19 >> 8) + x22 := (uint8(x21) & 0xff) + x23 := uint8((x21 >> 8)) + x24 := (uint8(x8) & 0xff) + x25 := (x8 >> 8) + x26 := (uint8(x25) & 0xff) + x27 := (x25 >> 8) + x28 := (uint8(x27) & 0xff) + x29 := (x27 >> 8) + x30 := (uint8(x29) & 0xff) + x31 := (x29 >> 8) + x32 := (uint8(x31) & 0xff) + x33 := (x31 >> 8) + x34 := (uint8(x33) & 0xff) + x35 := (x33 >> 8) + x36 := (uint8(x35) & 0xff) + x37 := uint8((x35 >> 8)) + x38 := (uint8(x7) & 0xff) + x39 := (x7 >> 8) + x40 := (uint8(x39) & 0xff) + x41 := (x39 >> 8) + x42 := (uint8(x41) & 0xff) + x43 := (x41 >> 8) + x44 := (uint8(x43) & 0xff) + x45 := (x43 >> 8) x46 := (uint8(x45) & 0xff) x47 := (x45 >> 8) x48 := (uint8(x47) & 0xff) x49 := (x47 >> 8) x50 := (uint8(x49) & 0xff) - x51 := (x49 >> 8) - x52 := (uint8(x51) & 0xff) - x53 := (x51 >> 8) + x51 := uint8((x49 >> 8)) + x52 := (uint8(x6) & 0xff) + x53 := (x6 >> 8) x54 := (uint8(x53) & 0xff) x55 := (x53 >> 8) x56 := (uint8(x55) & 0xff) - x57 := uint8((x55 >> 8)) - x58 := (x43 + uint64(x57)) - x59 := (uint8(x58) & 0xff) - x60 := (x58 >> 8) - x61 := (uint8(x60) & 0xff) - x62 := (x60 >> 8) - x63 := (uint8(x62) & 0xff) - x64 := (x62 >> 8) - x65 := (uint8(x64) & 0xff) - x66 := (x64 >> 8) - x67 := (uint8(x66) & 0xff) - x68 := (x66 >> 8) - x69 := (uint8(x68) & 0xff) - x70 := (x68 >> 8) - x71 := (uint8(x70) & 0xff) - x72 := uint8((x70 >> 8)) - x73 := (x42 + uint64(x72)) + x57 := (x55 >> 8) + x58 := (uint8(x57) & 0xff) + x59 := (x57 >> 8) + x60 := (uint8(x59) & 0xff) + x61 := (x59 >> 8) + x62 := (uint8(x61) & 0xff) + x63 := (x61 >> 8) + x64 := (uint8(x63) & 0xff) + x65 := uint8((x63 >> 8)) + x66 := (uint8(x5) & 0xff) + x67 := (x5 >> 8) + x68 := (uint8(x67) & 0xff) + x69 := (x67 >> 8) + x70 := (uint8(x69) & 0xff) + x71 := (x69 >> 8) + x72 := (uint8(x71) & 0xff) + x73 := (x71 >> 8) x74 := (uint8(x73) & 0xff) x75 := (x73 >> 8) x76 := (uint8(x75) & 0xff) x77 := (x75 >> 8) x78 := (uint8(x77) & 0xff) - x79 := (x77 >> 8) - x80 := (uint8(x79) & 0xff) - x81 := (x79 >> 8) + x79 := uint8((x77 >> 8)) + x80 := (uint8(x4) & 0xff) + x81 := (x4 >> 8) x82 := (uint8(x81) & 0xff) x83 := (x81 >> 8) x84 := (uint8(x83) & 0xff) x85 := (x83 >> 8) x86 := (uint8(x85) & 0xff) - x87 := uint8((x85 >> 8)) - x88 := (x41 + uint64(x87)) - x89 := (uint8(x88) & 0xff) - x90 := (x88 >> 8) - x91 := (uint8(x90) & 0xff) - x92 := (x90 >> 8) - x93 := (uint8(x92) & 0xff) - x94 := (x92 >> 8) - x95 := (uint8(x94) & 0xff) - x96 := (x94 >> 8) - x97 := (uint8(x96) & 0xff) - x98 := (x96 >> 8) - x99 := (uint8(x98) & 0xff) - x100 := (x98 >> 8) - x101 := (uint8(x100) & 0xff) - x102 := uint8((x100 >> 8)) - x103 := (uint8(x28) & 0xff) - x104 := (x28 >> 8) - x105 := (uint8(x104) & 0xff) - x106 := (x104 >> 8) - x107 := (uint8(x106) & 0xff) - x108 := (x106 >> 8) - x109 := (uint8(x108) & 0xff) - x110 := (x108 >> 8) - x111 := (uint8(x110) & 0xff) - x112 := (x110 >> 8) - x113 := (uint8(x112) & 0xff) - x114 := (x112 >> 8) - x115 := (uint8(x114) & 0xff) - x116 := uint8((x114 >> 8)) - x117 := (x40 + uint64(x116)) + x87 := (x85 >> 8) + x88 := (uint8(x87) & 0xff) + x89 := (x87 >> 8) + x90 := (uint8(x89) & 0xff) + x91 := (x89 >> 8) + x92 := (uint8(x91) & 0xff) + x93 := uint8((x91 >> 8)) + x94 := (uint8(x3) & 0xff) + x95 := (x3 >> 8) + x96 := (uint8(x95) & 0xff) + x97 := (x95 >> 8) + x98 := (uint8(x97) & 0xff) + x99 := (x97 >> 8) + x100 := (uint8(x99) & 0xff) + x101 := (x99 >> 8) + x102 := (uint8(x101) & 0xff) + x103 := (x101 >> 8) + x104 := (uint8(x103) & 0xff) + x105 := (x103 >> 8) + x106 := (uint8(x105) & 0xff) + x107 := uint8((x105 >> 8)) + x108 := (uint8(x2) & 0xff) + x109 := (x2 >> 8) + x110 := (uint8(x109) & 0xff) + x111 := (x109 >> 8) + x112 := (uint8(x111) & 0xff) + x113 := (x111 >> 8) + x114 := (uint8(x113) & 0xff) + x115 := (x113 >> 8) + x116 := (uint8(x115) & 0xff) + x117 := (x115 >> 8) x118 := (uint8(x117) & 0xff) x119 := (x117 >> 8) x120 := (uint8(x119) & 0xff) - x121 := (x119 >> 8) - x122 := (uint8(x121) & 0xff) - x123 := (x121 >> 8) - x124 := (uint8(x123) & 0xff) - x125 := (x123 >> 8) - x126 := (uint8(x125) & 0xff) - x127 := (x125 >> 8) - x128 := (uint8(x127) & 0xff) - x129 := (x127 >> 8) - x130 := (uint8(x129) & 0xff) - x131 := uint8((x129 >> 8)) - x132 := (x39 + uint64(x131)) - x133 := (uint8(x132) & 0xff) - x134 := (x132 >> 8) - x135 := (uint8(x134) & 0xff) - x136 := (x134 >> 8) - x137 := (uint8(x136) & 0xff) - x138 := (x136 >> 8) - x139 := (uint8(x138) & 0xff) - x140 := (x138 >> 8) - x141 := (uint8(x140) & 0xff) - x142 := (x140 >> 8) - x143 := (uint8(x142) & 0xff) - x144 := (x142 >> 8) - x145 := (uint8(x144) & 0xff) - x146 := uint8((x144 >> 8)) - x147 := (x38 + uint64(x146)) - x148 := (uint8(x147) & 0xff) - x149 := (x147 >> 8) - x150 := (uint8(x149) & 0xff) - x151 := (x149 >> 8) - x152 := (uint8(x151) & 0xff) - x153 := (x151 >> 8) - x154 := (uint8(x153) & 0xff) - x155 := (x153 >> 8) - x156 := (uint8(x155) & 0xff) - x157 := (x155 >> 8) - x158 := (uint8(x157) & 0xff) - x159 := (x157 >> 8) - x160 := (uint8(x159) & 0xff) - x161 := uint8((x159 >> 8)) - x162 := (uint8(x36) & 0xff) - x163 := (x36 >> 8) - x164 := (uint8(x163) & 0xff) - x165 := (x163 >> 8) - x166 := (uint8(x165) & 0xff) - x167 := (x165 >> 8) - x168 := (uint8(x167) & 0xff) - x169 := (x167 >> 8) - x170 := (uint8(x169) & 0xff) - x171 := (x169 >> 8) - x172 := (uint8(x171) & 0xff) - x173 := (x171 >> 8) - x174 := (uint8(x173) & 0xff) - x175 := p521Uint1((x173 >> 8)) - out1[0] = x44 - out1[1] = x46 - out1[2] = x48 - out1[3] = x50 - out1[4] = x52 - out1[5] = x54 - out1[6] = x56 - out1[7] = x59 - out1[8] = x61 - out1[9] = x63 - out1[10] = x65 - out1[11] = x67 - out1[12] = x69 - out1[13] = x71 - out1[14] = x74 - out1[15] = x76 - out1[16] = x78 - out1[17] = x80 - out1[18] = x82 - out1[19] = x84 - out1[20] = x86 - out1[21] = x89 - out1[22] = x91 - out1[23] = x93 - out1[24] = x95 - out1[25] = x97 - out1[26] = x99 - out1[27] = x101 - out1[28] = x102 - out1[29] = x103 - out1[30] = x105 - out1[31] = x107 - out1[32] = x109 - out1[33] = x111 - out1[34] = x113 - out1[35] = x115 - out1[36] = x118 - out1[37] = x120 - out1[38] = x122 - out1[39] = x124 - out1[40] = x126 - out1[41] = x128 - out1[42] = x130 - out1[43] = x133 - out1[44] = x135 - out1[45] = x137 - out1[46] = x139 - out1[47] = x141 - out1[48] = x143 - out1[49] = x145 - out1[50] = x148 - out1[51] = x150 - out1[52] = x152 - out1[53] = x154 - out1[54] = x156 - out1[55] = x158 - out1[56] = x160 - out1[57] = x161 - out1[58] = x162 - out1[59] = x164 - out1[60] = x166 - out1[61] = x168 - out1[62] = x170 - out1[63] = x172 - out1[64] = x174 - out1[65] = uint8(x175) + x121 := uint8((x119 >> 8)) + x122 := (uint8(x1) & 0xff) + x123 := p521Uint1((x1 >> 8)) + out1[0] = x10 + out1[1] = x12 + out1[2] = x14 + out1[3] = x16 + out1[4] = x18 + out1[5] = x20 + out1[6] = x22 + out1[7] = x23 + out1[8] = x24 + out1[9] = x26 + out1[10] = x28 + out1[11] = x30 + out1[12] = x32 + out1[13] = x34 + out1[14] = x36 + out1[15] = x37 + out1[16] = x38 + out1[17] = x40 + out1[18] = x42 + out1[19] = x44 + out1[20] = x46 + out1[21] = x48 + out1[22] = x50 + out1[23] = x51 + out1[24] = x52 + out1[25] = x54 + out1[26] = x56 + out1[27] = x58 + out1[28] = x60 + out1[29] = x62 + out1[30] = x64 + out1[31] = x65 + out1[32] = x66 + out1[33] = x68 + out1[34] = x70 + out1[35] = x72 + out1[36] = x74 + out1[37] = x76 + out1[38] = x78 + out1[39] = x79 + out1[40] = x80 + out1[41] = x82 + out1[42] = x84 + out1[43] = x86 + out1[44] = x88 + out1[45] = x90 + out1[46] = x92 + out1[47] = x93 + out1[48] = x94 + out1[49] = x96 + out1[50] = x98 + out1[51] = x100 + out1[52] = x102 + out1[53] = x104 + out1[54] = x106 + out1[55] = x107 + out1[56] = x108 + out1[57] = x110 + out1[58] = x112 + out1[59] = x114 + out1[60] = x116 + out1[61] = x118 + out1[62] = x120 + out1[63] = x121 + out1[64] = x122 + out1[65] = uint8(x123) } -// p521FromBytes deserializes a field element from bytes in little-endian order. +// p521FromBytes deserializes a field element NOT in the Montgomery domain from bytes in little-endian order. // +// Preconditions: +// 0 ≤ bytes_eval arg1 < m // Postconditions: // eval out1 mod m = bytes_eval arg1 mod m +// 0 ≤ eval out1 < m // // Input Bounds: // arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x1]] // Output Bounds: -// out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] +// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0x1ff]] func p521FromBytes(out1 *[9]uint64, arg1 *[66]uint8) { - x1 := (uint64(p521Uint1(arg1[65])) << 56) - x2 := (uint64(arg1[64]) << 48) - x3 := (uint64(arg1[63]) << 40) - x4 := (uint64(arg1[62]) << 32) - x5 := (uint64(arg1[61]) << 24) - x6 := (uint64(arg1[60]) << 16) - x7 := (uint64(arg1[59]) << 8) - x8 := arg1[58] - x9 := (uint64(arg1[57]) << 50) - x10 := (uint64(arg1[56]) << 42) - x11 := (uint64(arg1[55]) << 34) - x12 := (uint64(arg1[54]) << 26) - x13 := (uint64(arg1[53]) << 18) - x14 := (uint64(arg1[52]) << 10) - x15 := (uint64(arg1[51]) << 2) - x16 := (uint64(arg1[50]) << 52) - x17 := (uint64(arg1[49]) << 44) - x18 := (uint64(arg1[48]) << 36) - x19 := (uint64(arg1[47]) << 28) - x20 := (uint64(arg1[46]) << 20) - x21 := (uint64(arg1[45]) << 12) - x22 := (uint64(arg1[44]) << 4) - x23 := (uint64(arg1[43]) << 54) - x24 := (uint64(arg1[42]) << 46) - x25 := (uint64(arg1[41]) << 38) - x26 := (uint64(arg1[40]) << 30) - x27 := (uint64(arg1[39]) << 22) - x28 := (uint64(arg1[38]) << 14) - x29 := (uint64(arg1[37]) << 6) - x30 := (uint64(arg1[36]) << 56) - x31 := (uint64(arg1[35]) << 48) - x32 := (uint64(arg1[34]) << 40) - x33 := (uint64(arg1[33]) << 32) - x34 := (uint64(arg1[32]) << 24) - x35 := (uint64(arg1[31]) << 16) - x36 := (uint64(arg1[30]) << 8) - x37 := arg1[29] - x38 := (uint64(arg1[28]) << 50) - x39 := (uint64(arg1[27]) << 42) - x40 := (uint64(arg1[26]) << 34) - x41 := (uint64(arg1[25]) << 26) - x42 := (uint64(arg1[24]) << 18) - x43 := (uint64(arg1[23]) << 10) - x44 := (uint64(arg1[22]) << 2) - x45 := (uint64(arg1[21]) << 52) - x46 := (uint64(arg1[20]) << 44) - x47 := (uint64(arg1[19]) << 36) - x48 := (uint64(arg1[18]) << 28) - x49 := (uint64(arg1[17]) << 20) - x50 := (uint64(arg1[16]) << 12) - x51 := (uint64(arg1[15]) << 4) - x52 := (uint64(arg1[14]) << 54) - x53 := (uint64(arg1[13]) << 46) - x54 := (uint64(arg1[12]) << 38) - x55 := (uint64(arg1[11]) << 30) - x56 := (uint64(arg1[10]) << 22) - x57 := (uint64(arg1[9]) << 14) - x58 := (uint64(arg1[8]) << 6) + x1 := (uint64(p521Uint1(arg1[65])) << 8) + x2 := arg1[64] + x3 := (uint64(arg1[63]) << 56) + x4 := (uint64(arg1[62]) << 48) + x5 := (uint64(arg1[61]) << 40) + x6 := (uint64(arg1[60]) << 32) + x7 := (uint64(arg1[59]) << 24) + x8 := (uint64(arg1[58]) << 16) + x9 := (uint64(arg1[57]) << 8) + x10 := arg1[56] + x11 := (uint64(arg1[55]) << 56) + x12 := (uint64(arg1[54]) << 48) + x13 := (uint64(arg1[53]) << 40) + x14 := (uint64(arg1[52]) << 32) + x15 := (uint64(arg1[51]) << 24) + x16 := (uint64(arg1[50]) << 16) + x17 := (uint64(arg1[49]) << 8) + x18 := arg1[48] + x19 := (uint64(arg1[47]) << 56) + x20 := (uint64(arg1[46]) << 48) + x21 := (uint64(arg1[45]) << 40) + x22 := (uint64(arg1[44]) << 32) + x23 := (uint64(arg1[43]) << 24) + x24 := (uint64(arg1[42]) << 16) + x25 := (uint64(arg1[41]) << 8) + x26 := arg1[40] + x27 := (uint64(arg1[39]) << 56) + x28 := (uint64(arg1[38]) << 48) + x29 := (uint64(arg1[37]) << 40) + x30 := (uint64(arg1[36]) << 32) + x31 := (uint64(arg1[35]) << 24) + x32 := (uint64(arg1[34]) << 16) + x33 := (uint64(arg1[33]) << 8) + x34 := arg1[32] + x35 := (uint64(arg1[31]) << 56) + x36 := (uint64(arg1[30]) << 48) + x37 := (uint64(arg1[29]) << 40) + x38 := (uint64(arg1[28]) << 32) + x39 := (uint64(arg1[27]) << 24) + x40 := (uint64(arg1[26]) << 16) + x41 := (uint64(arg1[25]) << 8) + x42 := arg1[24] + x43 := (uint64(arg1[23]) << 56) + x44 := (uint64(arg1[22]) << 48) + x45 := (uint64(arg1[21]) << 40) + x46 := (uint64(arg1[20]) << 32) + x47 := (uint64(arg1[19]) << 24) + x48 := (uint64(arg1[18]) << 16) + x49 := (uint64(arg1[17]) << 8) + x50 := arg1[16] + x51 := (uint64(arg1[15]) << 56) + x52 := (uint64(arg1[14]) << 48) + x53 := (uint64(arg1[13]) << 40) + x54 := (uint64(arg1[12]) << 32) + x55 := (uint64(arg1[11]) << 24) + x56 := (uint64(arg1[10]) << 16) + x57 := (uint64(arg1[9]) << 8) + x58 := arg1[8] x59 := (uint64(arg1[7]) << 56) x60 := (uint64(arg1[6]) << 48) x61 := (uint64(arg1[5]) << 40) @@ -1735,122 +5447,63 @@ func p521FromBytes(out1 *[9]uint64, arg1 *[66]uint8) { x71 := (x61 + x70) x72 := (x60 + x71) x73 := (x59 + x72) - x74 := (x73 & 0x3ffffffffffffff) - x75 := uint8((x73 >> 58)) - x76 := (x58 + uint64(x75)) - x77 := (x57 + x76) - x78 := (x56 + x77) - x79 := (x55 + x78) - x80 := (x54 + x79) - x81 := (x53 + x80) - x82 := (x52 + x81) - x83 := (x82 & 0x3ffffffffffffff) - x84 := uint8((x82 >> 58)) - x85 := (x51 + uint64(x84)) - x86 := (x50 + x85) - x87 := (x49 + x86) - x88 := (x48 + x87) - x89 := (x47 + x88) - x90 := (x46 + x89) - x91 := (x45 + x90) - x92 := (x91 & 0x3ffffffffffffff) - x93 := uint8((x91 >> 58)) - x94 := (x44 + uint64(x93)) - x95 := (x43 + x94) - x96 := (x42 + x95) - x97 := (x41 + x96) - x98 := (x40 + x97) - x99 := (x39 + x98) - x100 := (x38 + x99) - x101 := (x36 + uint64(x37)) - x102 := (x35 + x101) - x103 := (x34 + x102) - x104 := (x33 + x103) - x105 := (x32 + x104) - x106 := (x31 + x105) - x107 := (x30 + x106) - x108 := (x107 & 0x3ffffffffffffff) - x109 := uint8((x107 >> 58)) - x110 := (x29 + uint64(x109)) - x111 := (x28 + x110) - x112 := (x27 + x111) - x113 := (x26 + x112) - x114 := (x25 + x113) - x115 := (x24 + x114) - x116 := (x23 + x115) - x117 := (x116 & 0x3ffffffffffffff) - x118 := uint8((x116 >> 58)) - x119 := (x22 + uint64(x118)) - x120 := (x21 + x119) - x121 := (x20 + x120) - x122 := (x19 + x121) - x123 := (x18 + x122) - x124 := (x17 + x123) - x125 := (x16 + x124) - x126 := (x125 & 0x3ffffffffffffff) - x127 := uint8((x125 >> 58)) - x128 := (x15 + uint64(x127)) - x129 := (x14 + x128) - x130 := (x13 + x129) - x131 := (x12 + x130) - x132 := (x11 + x131) - x133 := (x10 + x132) - x134 := (x9 + x133) - x135 := (x7 + uint64(x8)) - x136 := (x6 + x135) - x137 := (x5 + x136) - x138 := (x4 + x137) - x139 := (x3 + x138) - x140 := (x2 + x139) - x141 := (x1 + x140) - out1[0] = x74 - out1[1] = x83 - out1[2] = x92 - out1[3] = x100 - out1[4] = x108 - out1[5] = x117 - out1[6] = x126 - out1[7] = x134 - out1[8] = x141 -} - -// p521Selectznz is a multi-limb conditional select. -// -// Postconditions: -// eval out1 = (if arg1 = 0 then eval arg2 else eval arg3) -// -// Input Bounds: -// arg1: [0x0 ~> 0x1] -// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] -// arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] -// Output Bounds: -// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] -func p521Selectznz(out1 *[9]uint64, arg1 p521Uint1, arg2 *[9]uint64, arg3 *[9]uint64) { - var x1 uint64 - p521CmovznzU64(&x1, arg1, arg2[0], arg3[0]) - var x2 uint64 - p521CmovznzU64(&x2, arg1, arg2[1], arg3[1]) - var x3 uint64 - p521CmovznzU64(&x3, arg1, arg2[2], arg3[2]) - var x4 uint64 - p521CmovznzU64(&x4, arg1, arg2[3], arg3[3]) - var x5 uint64 - p521CmovznzU64(&x5, arg1, arg2[4], arg3[4]) - var x6 uint64 - p521CmovznzU64(&x6, arg1, arg2[5], arg3[5]) - var x7 uint64 - p521CmovznzU64(&x7, arg1, arg2[6], arg3[6]) - var x8 uint64 - p521CmovznzU64(&x8, arg1, arg2[7], arg3[7]) - var x9 uint64 - p521CmovznzU64(&x9, arg1, arg2[8], arg3[8]) - out1[0] = x1 - out1[1] = x2 - out1[2] = x3 - out1[3] = x4 - out1[4] = x5 - out1[5] = x6 - out1[6] = x7 - out1[7] = x8 - out1[8] = x9 + x74 := (x57 + uint64(x58)) + x75 := (x56 + x74) + x76 := (x55 + x75) + x77 := (x54 + x76) + x78 := (x53 + x77) + x79 := (x52 + x78) + x80 := (x51 + x79) + x81 := (x49 + uint64(x50)) + x82 := (x48 + x81) + x83 := (x47 + x82) + x84 := (x46 + x83) + x85 := (x45 + x84) + x86 := (x44 + x85) + x87 := (x43 + x86) + x88 := (x41 + uint64(x42)) + x89 := (x40 + x88) + x90 := (x39 + x89) + x91 := (x38 + x90) + x92 := (x37 + x91) + x93 := (x36 + x92) + x94 := (x35 + x93) + x95 := (x33 + uint64(x34)) + x96 := (x32 + x95) + x97 := (x31 + x96) + x98 := (x30 + x97) + x99 := (x29 + x98) + x100 := (x28 + x99) + x101 := (x27 + x100) + x102 := (x25 + uint64(x26)) + x103 := (x24 + x102) + x104 := (x23 + x103) + x105 := (x22 + x104) + x106 := (x21 + x105) + x107 := (x20 + x106) + x108 := (x19 + x107) + x109 := (x17 + uint64(x18)) + x110 := (x16 + x109) + x111 := (x15 + x110) + x112 := (x14 + x111) + x113 := (x13 + x112) + x114 := (x12 + x113) + x115 := (x11 + x114) + x116 := (x9 + uint64(x10)) + x117 := (x8 + x116) + x118 := (x7 + x117) + x119 := (x6 + x118) + x120 := (x5 + x119) + x121 := (x4 + x120) + x122 := (x3 + x121) + x123 := (x1 + uint64(x2)) + out1[0] = x73 + out1[1] = x80 + out1[2] = x87 + out1[3] = x94 + out1[4] = x101 + out1[5] = x108 + out1[6] = x115 + out1[7] = x122 + out1[8] = x123 } diff --git a/src/crypto/elliptic/internal/fiat/p521_invert.go b/src/crypto/elliptic/internal/fiat/p521_invert.go new file mode 100644 index 0000000000..407711af36 --- /dev/null +++ b/src/crypto/elliptic/internal/fiat/p521_invert.go @@ -0,0 +1,89 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by addchain. DO NOT EDIT. + +package fiat + +// Invert sets e = 1/x, and returns e. +// +// If x == 0, Invert returns e = 0. +func (e *P521Element) Invert(x *P521Element) *P521Element { + // Inversion is implemented as exponentiation with exponent p − 2. + // The sequence of 13 multiplications and 520 squarings is derived from the + // following addition chain generated with github.com/mmcloughlin/addchain v0.3.0. + // + // _10 = 2*1 + // _11 = 1 + _10 + // _1100 = _11 << 2 + // _1111 = _11 + _1100 + // _11110000 = _1111 << 4 + // _11111111 = _1111 + _11110000 + // x16 = _11111111 << 8 + _11111111 + // x32 = x16 << 16 + x16 + // x64 = x32 << 32 + x32 + // x65 = 2*x64 + 1 + // x129 = x65 << 64 + x64 + // x130 = 2*x129 + 1 + // x259 = x130 << 129 + x129 + // x260 = 2*x259 + 1 + // x519 = x260 << 259 + x259 + // return x519 << 2 + 1 + // + + var z = new(P521Element).Set(e) + var t0 = new(P521Element) + + z.Square(x) + z.Mul(x, z) + t0.Square(z) + for s := 1; s < 2; s++ { + t0.Square(t0) + } + z.Mul(z, t0) + t0.Square(z) + for s := 1; s < 4; s++ { + t0.Square(t0) + } + z.Mul(z, t0) + t0.Square(z) + for s := 1; s < 8; s++ { + t0.Square(t0) + } + z.Mul(z, t0) + t0.Square(z) + for s := 1; s < 16; s++ { + t0.Square(t0) + } + z.Mul(z, t0) + t0.Square(z) + for s := 1; s < 32; s++ { + t0.Square(t0) + } + z.Mul(z, t0) + t0.Square(z) + t0.Mul(x, t0) + for s := 0; s < 64; s++ { + t0.Square(t0) + } + z.Mul(z, t0) + t0.Square(z) + t0.Mul(x, t0) + for s := 0; s < 129; s++ { + t0.Square(t0) + } + z.Mul(z, t0) + t0.Square(z) + t0.Mul(x, t0) + for s := 0; s < 259; s++ { + t0.Square(t0) + } + z.Mul(z, t0) + for s := 0; s < 2; s++ { + z.Square(z) + } + z.Mul(x, z) + + return e.Set(z) +} diff --git a/src/crypto/elliptic/internal/fiat/p521_test.go b/src/crypto/elliptic/internal/fiat/p521_test.go deleted file mode 100644 index 2b374faa27..0000000000 --- a/src/crypto/elliptic/internal/fiat/p521_test.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package fiat_test - -import ( - "crypto/elliptic/internal/fiat" - "crypto/rand" - "testing" -) - -func p521Random(t *testing.T) *fiat.P521Element { - buf := make([]byte, 66) - if _, err := rand.Read(buf); err != nil { - t.Fatal(err) - } - buf[0] &= 1 - e, err := new(fiat.P521Element).SetBytes(buf) - if err != nil { - t.Fatal(err) - } - return e -} - -func TestP521Invert(t *testing.T) { - a := p521Random(t) - inv := new(fiat.P521Element).Invert(a) - one := new(fiat.P521Element).Mul(a, inv) - if new(fiat.P521Element).One().Equal(one) != 1 { - t.Errorf("a * 1/a != 1; got %x for %x", one.Bytes(), a.Bytes()) - } - inv.Invert(new(fiat.P521Element)) - if new(fiat.P521Element).Equal(inv) != 1 { - t.Errorf("1/0 != 0; got %x", inv.Bytes()) - } -} diff --git a/src/crypto/elliptic/internal/nistec/nistec_test.go b/src/crypto/elliptic/internal/nistec/nistec_test.go new file mode 100644 index 0000000000..4eae998c5d --- /dev/null +++ b/src/crypto/elliptic/internal/nistec/nistec_test.go @@ -0,0 +1,94 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package nistec_test + +import ( + "crypto/elliptic/internal/nistec" + "math/rand" + "os" + "strings" + "testing" +) + +func TestAllocations(t *testing.T) { + if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-noopt") { + t.Skip("skipping allocations test without relevant optimizations") + } + t.Run("P224", func(t *testing.T) { + if allocs := testing.AllocsPerRun(100, func() { + p := nistec.NewP224Generator() + scalar := make([]byte, 66) + rand.Read(scalar) + p.ScalarMult(p, scalar) + out := p.Bytes() + if _, err := p.SetBytes(out); err != nil { + t.Fatal(err) + } + }); allocs > 0 { + t.Errorf("expected zero allocations, got %0.1f", allocs) + } + }) + t.Run("P384", func(t *testing.T) { + if allocs := testing.AllocsPerRun(100, func() { + p := nistec.NewP384Generator() + scalar := make([]byte, 66) + rand.Read(scalar) + p.ScalarMult(p, scalar) + out := p.Bytes() + if _, err := p.SetBytes(out); err != nil { + t.Fatal(err) + } + }); allocs > 0 { + t.Errorf("expected zero allocations, got %0.1f", allocs) + } + }) + t.Run("P521", func(t *testing.T) { + if allocs := testing.AllocsPerRun(100, func() { + p := nistec.NewP521Generator() + scalar := make([]byte, 66) + rand.Read(scalar) + p.ScalarMult(p, scalar) + out := p.Bytes() + if _, err := p.SetBytes(out); err != nil { + t.Fatal(err) + } + }); allocs > 0 { + t.Errorf("expected zero allocations, got %0.1f", allocs) + } + }) +} + +func BenchmarkScalarMult(b *testing.B) { + b.Run("P224", func(b *testing.B) { + scalar := make([]byte, 66) + rand.Read(scalar) + p := nistec.NewP224Generator() + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + p.ScalarMult(p, scalar) + } + }) + b.Run("P384", func(b *testing.B) { + scalar := make([]byte, 66) + rand.Read(scalar) + p := nistec.NewP384Generator() + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + p.ScalarMult(p, scalar) + } + }) + b.Run("P521", func(b *testing.B) { + scalar := make([]byte, 66) + rand.Read(scalar) + p := nistec.NewP521Generator() + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + p.ScalarMult(p, scalar) + } + }) +} diff --git a/src/crypto/elliptic/internal/nistec/p224.go b/src/crypto/elliptic/internal/nistec/p224.go new file mode 100644 index 0000000000..74dbc184dd --- /dev/null +++ b/src/crypto/elliptic/internal/nistec/p224.go @@ -0,0 +1,293 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package nistec + +import ( + "crypto/elliptic/internal/fiat" + "crypto/subtle" + "errors" +) + +var p224B, _ = new(fiat.P224Element).SetBytes([]byte{0xb4, 0x05, 0x0a, 0x85, + 0x0c, 0x04, 0xb3, 0xab, 0xf5, 0x41, 0x32, 0x56, 0x50, 0x44, 0xb0, 0xb7, + 0xd7, 0xbf, 0xd8, 0xba, 0x27, 0x0b, 0x39, 0x43, 0x23, 0x55, 0xff, 0xb4}) + +var p224G, _ = NewP224Point().SetBytes([]byte{0x04, + 0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f, 0x32, 0x13, 0x90, 0xb9, + 0x4a, 0x03, 0xc1, 0xd3, 0x56, 0xc2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xd6, + 0x11, 0x5c, 0x1d, 0x21, 0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, + 0x4c, 0x22, 0xdf, 0xe6, 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, + 0x44, 0xd5, 0x81, 0x99, 0x85, 0x0, 0x7e, 0x34}) + +const p224ElementLength = 28 + +// P224Point is a P-224 point. The zero value is NOT valid. +type P224Point struct { + // The point is represented in projective coordinates (X:Y:Z), + // where x = X/Z and y = Y/Z. + x, y, z *fiat.P224Element +} + +// NewP224Point returns a new P224Point representing the point at infinity point. +func NewP224Point() *P224Point { + return &P224Point{ + x: new(fiat.P224Element), + y: new(fiat.P224Element).One(), + z: new(fiat.P224Element), + } +} + +// NewP224Generator returns a new P224Point set to the canonical generator. +func NewP224Generator() *P224Point { + return (&P224Point{ + x: new(fiat.P224Element), + y: new(fiat.P224Element), + z: new(fiat.P224Element), + }).Set(p224G) +} + +// Set sets p = q and returns p. +func (p *P224Point) Set(q *P224Point) *P224Point { + p.x.Set(q.x) + p.y.Set(q.y) + p.z.Set(q.z) + return p +} + +// SetBytes sets p to the compressed, uncompressed, or infinity value encoded in +// b, as specified in SEC 1, Version 2.0, Section 2.3.4. If the point is not on +// the curve, it returns nil and an error, and the receiver is unchanged. +// Otherwise, it returns p. +func (p *P224Point) SetBytes(b []byte) (*P224Point, error) { + switch { + // Point at infinity. + case len(b) == 1 && b[0] == 0: + return p.Set(NewP224Point()), nil + + // Uncompressed form. + case len(b) == 1+2*p224ElementLength && b[0] == 4: + x, err := new(fiat.P224Element).SetBytes(b[1 : 1+p224ElementLength]) + if err != nil { + return nil, err + } + y, err := new(fiat.P224Element).SetBytes(b[1+p224ElementLength:]) + if err != nil { + return nil, err + } + if err := p224CheckOnCurve(x, y); err != nil { + return nil, err + } + p.x.Set(x) + p.y.Set(y) + p.z.One() + return p, nil + + // Compressed form + case len(b) == 1+p224ElementLength && b[0] == 0: + return nil, errors.New("unimplemented") // TODO(filippo) + + default: + return nil, errors.New("invalid P224 point encoding") + } +} + +func p224CheckOnCurve(x, y *fiat.P224Element) error { + // x³ - 3x + b. + x3 := new(fiat.P224Element).Square(x) + x3.Mul(x3, x) + + threeX := new(fiat.P224Element).Add(x, x) + threeX.Add(threeX, x) + + x3.Sub(x3, threeX) + x3.Add(x3, p224B) + + // y² = x³ - 3x + b + y2 := new(fiat.P224Element).Square(y) + + if x3.Equal(y2) != 1 { + return errors.New("P224 point not on curve") + } + return nil +} + +// Bytes returns the uncompressed or infinity encoding of p, as specified in +// SEC 1, Version 2.0, Section 2.3.3. Note that the encoding of the point at +// infinity is shorter than all other encodings. +func (p *P224Point) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var out [133]byte + return p.bytes(&out) +} + +func (p *P224Point) bytes(out *[133]byte) []byte { + if p.z.IsZero() == 1 { + return append(out[:0], 0) + } + + zinv := new(fiat.P224Element).Invert(p.z) + xx := new(fiat.P224Element).Mul(p.x, zinv) + yy := new(fiat.P224Element).Mul(p.y, zinv) + + buf := append(out[:0], 4) + buf = append(buf, xx.Bytes()...) + buf = append(buf, yy.Bytes()...) + return buf +} + +// Add sets q = p1 + p2, and returns q. The points may overlap. +func (q *P224Point) Add(p1, p2 *P224Point) *P224Point { + // Complete addition formula for a = -3 from "Complete addition formulas for + // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §A.2. + + t0 := new(fiat.P224Element).Mul(p1.x, p2.x) // t0 := X1 * X2 + t1 := new(fiat.P224Element).Mul(p1.y, p2.y) // t1 := Y1 * Y2 + t2 := new(fiat.P224Element).Mul(p1.z, p2.z) // t2 := Z1 * Z2 + t3 := new(fiat.P224Element).Add(p1.x, p1.y) // t3 := X1 + Y1 + t4 := new(fiat.P224Element).Add(p2.x, p2.y) // t4 := X2 + Y2 + t3.Mul(t3, t4) // t3 := t3 * t4 + t4.Add(t0, t1) // t4 := t0 + t1 + t3.Sub(t3, t4) // t3 := t3 - t4 + t4.Add(p1.y, p1.z) // t4 := Y1 + Z1 + x3 := new(fiat.P224Element).Add(p2.y, p2.z) // X3 := Y2 + Z2 + t4.Mul(t4, x3) // t4 := t4 * X3 + x3.Add(t1, t2) // X3 := t1 + t2 + t4.Sub(t4, x3) // t4 := t4 - X3 + x3.Add(p1.x, p1.z) // X3 := X1 + Z1 + y3 := new(fiat.P224Element).Add(p2.x, p2.z) // Y3 := X2 + Z2 + x3.Mul(x3, y3) // X3 := X3 * Y3 + y3.Add(t0, t2) // Y3 := t0 + t2 + y3.Sub(x3, y3) // Y3 := X3 - Y3 + z3 := new(fiat.P224Element).Mul(p224B, t2) // Z3 := b * t2 + x3.Sub(y3, z3) // X3 := Y3 - Z3 + z3.Add(x3, x3) // Z3 := X3 + X3 + x3.Add(x3, z3) // X3 := X3 + Z3 + z3.Sub(t1, x3) // Z3 := t1 - X3 + x3.Add(t1, x3) // X3 := t1 + X3 + y3.Mul(p224B, y3) // Y3 := b * Y3 + t1.Add(t2, t2) // t1 := t2 + t2 + t2.Add(t1, t2) // t2 := t1 + t2 + y3.Sub(y3, t2) // Y3 := Y3 - t2 + y3.Sub(y3, t0) // Y3 := Y3 - t0 + t1.Add(y3, y3) // t1 := Y3 + Y3 + y3.Add(t1, y3) // Y3 := t1 + Y3 + t1.Add(t0, t0) // t1 := t0 + t0 + t0.Add(t1, t0) // t0 := t1 + t0 + t0.Sub(t0, t2) // t0 := t0 - t2 + t1.Mul(t4, y3) // t1 := t4 * Y3 + t2.Mul(t0, y3) // t2 := t0 * Y3 + y3.Mul(x3, z3) // Y3 := X3 * Z3 + y3.Add(y3, t2) // Y3 := Y3 + t2 + x3.Mul(t3, x3) // X3 := t3 * X3 + x3.Sub(x3, t1) // X3 := X3 - t1 + z3.Mul(t4, z3) // Z3 := t4 * Z3 + t1.Mul(t3, t0) // t1 := t3 * t0 + z3.Add(z3, t1) // Z3 := Z3 + t1 + + q.x.Set(x3) + q.y.Set(y3) + q.z.Set(z3) + return q +} + +// Double sets q = p + p, and returns q. The points may overlap. +func (q *P224Point) Double(p *P224Point) *P224Point { + // Complete addition formula for a = -3 from "Complete addition formulas for + // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §A.2. + + t0 := new(fiat.P224Element).Square(p.x) // t0 := X ^ 2 + t1 := new(fiat.P224Element).Square(p.y) // t1 := Y ^ 2 + t2 := new(fiat.P224Element).Square(p.z) // t2 := Z ^ 2 + t3 := new(fiat.P224Element).Mul(p.x, p.y) // t3 := X * Y + t3.Add(t3, t3) // t3 := t3 + t3 + z3 := new(fiat.P224Element).Mul(p.x, p.z) // Z3 := X * Z + z3.Add(z3, z3) // Z3 := Z3 + Z3 + y3 := new(fiat.P224Element).Mul(p224B, t2) // Y3 := b * t2 + y3.Sub(y3, z3) // Y3 := Y3 - Z3 + x3 := new(fiat.P224Element).Add(y3, y3) // X3 := Y3 + Y3 + y3.Add(x3, y3) // Y3 := X3 + Y3 + x3.Sub(t1, y3) // X3 := t1 - Y3 + y3.Add(t1, y3) // Y3 := t1 + Y3 + y3.Mul(x3, y3) // Y3 := X3 * Y3 + x3.Mul(x3, t3) // X3 := X3 * t3 + t3.Add(t2, t2) // t3 := t2 + t2 + t2.Add(t2, t3) // t2 := t2 + t3 + z3.Mul(p224B, z3) // Z3 := b * Z3 + z3.Sub(z3, t2) // Z3 := Z3 - t2 + z3.Sub(z3, t0) // Z3 := Z3 - t0 + t3.Add(z3, z3) // t3 := Z3 + Z3 + z3.Add(z3, t3) // Z3 := Z3 + t3 + t3.Add(t0, t0) // t3 := t0 + t0 + t0.Add(t3, t0) // t0 := t3 + t0 + t0.Sub(t0, t2) // t0 := t0 - t2 + t0.Mul(t0, z3) // t0 := t0 * Z3 + y3.Add(y3, t0) // Y3 := Y3 + t0 + t0.Mul(p.y, p.z) // t0 := Y * Z + t0.Add(t0, t0) // t0 := t0 + t0 + z3.Mul(t0, z3) // Z3 := t0 * Z3 + x3.Sub(x3, z3) // X3 := X3 - Z3 + z3.Mul(t0, t1) // Z3 := t0 * t1 + z3.Add(z3, z3) // Z3 := Z3 + Z3 + z3.Add(z3, z3) // Z3 := Z3 + Z3 + + q.x.Set(x3) + q.y.Set(y3) + q.z.Set(z3) + return q +} + +// Select sets q to p1 if cond == 1, and to p2 if cond == 0. +func (q *P224Point) Select(p1, p2 *P224Point, cond int) *P224Point { + q.x.Select(p1.x, p2.x, cond) + q.y.Select(p1.y, p2.y, cond) + q.z.Select(p1.z, p2.z, cond) + return q +} + +// ScalarMult sets p = scalar * q, and returns p. +func (p *P224Point) ScalarMult(q *P224Point, scalar []byte) *P224Point { + // table holds the first 16 multiples of q. The explicit newP224Point calls + // get inlined, letting the allocations live on the stack. + var table = [16]*P224Point{ + NewP224Point(), NewP224Point(), NewP224Point(), NewP224Point(), + NewP224Point(), NewP224Point(), NewP224Point(), NewP224Point(), + NewP224Point(), NewP224Point(), NewP224Point(), NewP224Point(), + NewP224Point(), NewP224Point(), NewP224Point(), NewP224Point(), + } + for i := 1; i < 16; i++ { + table[i].Add(table[i-1], q) + } + + // Instead of doing the classic double-and-add chain, we do it with a + // four-bit window: we double four times, and then add [0-15]P. + t := NewP224Point() + p.Set(NewP224Point()) + for _, byte := range scalar { + p.Double(p) + p.Double(p) + p.Double(p) + p.Double(p) + + for i := uint8(0); i < 16; i++ { + cond := subtle.ConstantTimeByteEq(byte>>4, i) + t.Select(table[i], t, cond) + } + p.Add(p, t) + + p.Double(p) + p.Double(p) + p.Double(p) + p.Double(p) + + for i := uint8(0); i < 16; i++ { + cond := subtle.ConstantTimeByteEq(byte&0b1111, i) + t.Select(table[i], t, cond) + } + p.Add(p, t) + } + + return p +} diff --git a/src/crypto/elliptic/internal/nistec/p384.go b/src/crypto/elliptic/internal/nistec/p384.go new file mode 100644 index 0000000000..24a166de0a --- /dev/null +++ b/src/crypto/elliptic/internal/nistec/p384.go @@ -0,0 +1,298 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package nistec + +import ( + "crypto/elliptic/internal/fiat" + "crypto/subtle" + "errors" +) + +var p384B, _ = new(fiat.P384Element).SetBytes([]byte{ + 0xb3, 0x31, 0x2f, 0xa7, 0xe2, 0x3e, 0xe7, 0xe4, 0x98, 0x8e, 0x05, 0x6b, + 0xe3, 0xf8, 0x2d, 0x19, 0x18, 0x1d, 0x9c, 0x6e, 0xfe, 0x81, 0x41, 0x12, + 0x03, 0x14, 0x08, 0x8f, 0x50, 0x13, 0x87, 0x5a, 0xc6, 0x56, 0x39, 0x8d, + 0x8a, 0x2e, 0xd1, 0x9d, 0x2a, 0x85, 0xc8, 0xed, 0xd3, 0xec, 0x2a, 0xef}) + +var p384G, _ = NewP384Point().SetBytes([]byte{0x4, + 0xaa, 0x87, 0xca, 0x22, 0xbe, 0x8b, 0x05, 0x37, 0x8e, 0xb1, 0xc7, 0x1e, + 0xf3, 0x20, 0xad, 0x74, 0x6e, 0x1d, 0x3b, 0x62, 0x8b, 0xa7, 0x9b, 0x98, + 0x59, 0xf7, 0x41, 0xe0, 0x82, 0x54, 0x2a, 0x38, 0x55, 0x02, 0xf2, 0x5d, + 0xbf, 0x55, 0x29, 0x6c, 0x3a, 0x54, 0x5e, 0x38, 0x72, 0x76, 0x0a, 0xb7, + 0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e, 0x98, 0xbf, + 0x92, 0x92, 0xdc, 0x29, 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c, + 0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, 0x0a, 0x60, 0xb1, 0xce, + 0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f}) + +const p384ElementLength = 48 + +// P384Point is a P-384 point. The zero value is NOT valid. +type P384Point struct { + // The point is represented in projective coordinates (X:Y:Z), + // where x = X/Z and y = Y/Z. + x, y, z *fiat.P384Element +} + +// NewP384Point returns a new P384Point representing the point at infinity point. +func NewP384Point() *P384Point { + return &P384Point{ + x: new(fiat.P384Element), + y: new(fiat.P384Element).One(), + z: new(fiat.P384Element), + } +} + +// NewP384Generator returns a new P384Point set to the canonical generator. +func NewP384Generator() *P384Point { + return (&P384Point{ + x: new(fiat.P384Element), + y: new(fiat.P384Element), + z: new(fiat.P384Element), + }).Set(p384G) +} + +// Set sets p = q and returns p. +func (p *P384Point) Set(q *P384Point) *P384Point { + p.x.Set(q.x) + p.y.Set(q.y) + p.z.Set(q.z) + return p +} + +// SetBytes sets p to the compressed, uncompressed, or infinity value encoded in +// b, as specified in SEC 1, Version 2.0, Section 2.3.4. If the point is not on +// the curve, it returns nil and an error, and the receiver is unchanged. +// Otherwise, it returns p. +func (p *P384Point) SetBytes(b []byte) (*P384Point, error) { + switch { + // Point at infinity. + case len(b) == 1 && b[0] == 0: + return p.Set(NewP384Point()), nil + + // Uncompressed form. + case len(b) == 1+2*p384ElementLength && b[0] == 4: + x, err := new(fiat.P384Element).SetBytes(b[1 : 1+p384ElementLength]) + if err != nil { + return nil, err + } + y, err := new(fiat.P384Element).SetBytes(b[1+p384ElementLength:]) + if err != nil { + return nil, err + } + if err := p384CheckOnCurve(x, y); err != nil { + return nil, err + } + p.x.Set(x) + p.y.Set(y) + p.z.One() + return p, nil + + // Compressed form + case len(b) == 1+p384ElementLength && b[0] == 0: + return nil, errors.New("unimplemented") // TODO(filippo) + + default: + return nil, errors.New("invalid P384 point encoding") + } +} + +func p384CheckOnCurve(x, y *fiat.P384Element) error { + // x³ - 3x + b. + x3 := new(fiat.P384Element).Square(x) + x3.Mul(x3, x) + + threeX := new(fiat.P384Element).Add(x, x) + threeX.Add(threeX, x) + + x3.Sub(x3, threeX) + x3.Add(x3, p384B) + + // y² = x³ - 3x + b + y2 := new(fiat.P384Element).Square(y) + + if x3.Equal(y2) != 1 { + return errors.New("P384 point not on curve") + } + return nil +} + +// Bytes returns the uncompressed or infinity encoding of p, as specified in +// SEC 1, Version 2.0, Section 2.3.3. Note that the encoding of the point at +// infinity is shorter than all other encodings. +func (p *P384Point) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var out [133]byte + return p.bytes(&out) +} + +func (p *P384Point) bytes(out *[133]byte) []byte { + if p.z.IsZero() == 1 { + return append(out[:0], 0) + } + + zinv := new(fiat.P384Element).Invert(p.z) + xx := new(fiat.P384Element).Mul(p.x, zinv) + yy := new(fiat.P384Element).Mul(p.y, zinv) + + buf := append(out[:0], 4) + buf = append(buf, xx.Bytes()...) + buf = append(buf, yy.Bytes()...) + return buf +} + +// Add sets q = p1 + p2, and returns q. The points may overlap. +func (q *P384Point) Add(p1, p2 *P384Point) *P384Point { + // Complete addition formula for a = -3 from "Complete addition formulas for + // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §A.2. + + t0 := new(fiat.P384Element).Mul(p1.x, p2.x) // t0 := X1 * X2 + t1 := new(fiat.P384Element).Mul(p1.y, p2.y) // t1 := Y1 * Y2 + t2 := new(fiat.P384Element).Mul(p1.z, p2.z) // t2 := Z1 * Z2 + t3 := new(fiat.P384Element).Add(p1.x, p1.y) // t3 := X1 + Y1 + t4 := new(fiat.P384Element).Add(p2.x, p2.y) // t4 := X2 + Y2 + t3.Mul(t3, t4) // t3 := t3 * t4 + t4.Add(t0, t1) // t4 := t0 + t1 + t3.Sub(t3, t4) // t3 := t3 - t4 + t4.Add(p1.y, p1.z) // t4 := Y1 + Z1 + x3 := new(fiat.P384Element).Add(p2.y, p2.z) // X3 := Y2 + Z2 + t4.Mul(t4, x3) // t4 := t4 * X3 + x3.Add(t1, t2) // X3 := t1 + t2 + t4.Sub(t4, x3) // t4 := t4 - X3 + x3.Add(p1.x, p1.z) // X3 := X1 + Z1 + y3 := new(fiat.P384Element).Add(p2.x, p2.z) // Y3 := X2 + Z2 + x3.Mul(x3, y3) // X3 := X3 * Y3 + y3.Add(t0, t2) // Y3 := t0 + t2 + y3.Sub(x3, y3) // Y3 := X3 - Y3 + z3 := new(fiat.P384Element).Mul(p384B, t2) // Z3 := b * t2 + x3.Sub(y3, z3) // X3 := Y3 - Z3 + z3.Add(x3, x3) // Z3 := X3 + X3 + x3.Add(x3, z3) // X3 := X3 + Z3 + z3.Sub(t1, x3) // Z3 := t1 - X3 + x3.Add(t1, x3) // X3 := t1 + X3 + y3.Mul(p384B, y3) // Y3 := b * Y3 + t1.Add(t2, t2) // t1 := t2 + t2 + t2.Add(t1, t2) // t2 := t1 + t2 + y3.Sub(y3, t2) // Y3 := Y3 - t2 + y3.Sub(y3, t0) // Y3 := Y3 - t0 + t1.Add(y3, y3) // t1 := Y3 + Y3 + y3.Add(t1, y3) // Y3 := t1 + Y3 + t1.Add(t0, t0) // t1 := t0 + t0 + t0.Add(t1, t0) // t0 := t1 + t0 + t0.Sub(t0, t2) // t0 := t0 - t2 + t1.Mul(t4, y3) // t1 := t4 * Y3 + t2.Mul(t0, y3) // t2 := t0 * Y3 + y3.Mul(x3, z3) // Y3 := X3 * Z3 + y3.Add(y3, t2) // Y3 := Y3 + t2 + x3.Mul(t3, x3) // X3 := t3 * X3 + x3.Sub(x3, t1) // X3 := X3 - t1 + z3.Mul(t4, z3) // Z3 := t4 * Z3 + t1.Mul(t3, t0) // t1 := t3 * t0 + z3.Add(z3, t1) // Z3 := Z3 + t1 + + q.x.Set(x3) + q.y.Set(y3) + q.z.Set(z3) + return q +} + +// Double sets q = p + p, and returns q. The points may overlap. +func (q *P384Point) Double(p *P384Point) *P384Point { + // Complete addition formula for a = -3 from "Complete addition formulas for + // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §A.2. + + t0 := new(fiat.P384Element).Square(p.x) // t0 := X ^ 2 + t1 := new(fiat.P384Element).Square(p.y) // t1 := Y ^ 2 + t2 := new(fiat.P384Element).Square(p.z) // t2 := Z ^ 2 + t3 := new(fiat.P384Element).Mul(p.x, p.y) // t3 := X * Y + t3.Add(t3, t3) // t3 := t3 + t3 + z3 := new(fiat.P384Element).Mul(p.x, p.z) // Z3 := X * Z + z3.Add(z3, z3) // Z3 := Z3 + Z3 + y3 := new(fiat.P384Element).Mul(p384B, t2) // Y3 := b * t2 + y3.Sub(y3, z3) // Y3 := Y3 - Z3 + x3 := new(fiat.P384Element).Add(y3, y3) // X3 := Y3 + Y3 + y3.Add(x3, y3) // Y3 := X3 + Y3 + x3.Sub(t1, y3) // X3 := t1 - Y3 + y3.Add(t1, y3) // Y3 := t1 + Y3 + y3.Mul(x3, y3) // Y3 := X3 * Y3 + x3.Mul(x3, t3) // X3 := X3 * t3 + t3.Add(t2, t2) // t3 := t2 + t2 + t2.Add(t2, t3) // t2 := t2 + t3 + z3.Mul(p384B, z3) // Z3 := b * Z3 + z3.Sub(z3, t2) // Z3 := Z3 - t2 + z3.Sub(z3, t0) // Z3 := Z3 - t0 + t3.Add(z3, z3) // t3 := Z3 + Z3 + z3.Add(z3, t3) // Z3 := Z3 + t3 + t3.Add(t0, t0) // t3 := t0 + t0 + t0.Add(t3, t0) // t0 := t3 + t0 + t0.Sub(t0, t2) // t0 := t0 - t2 + t0.Mul(t0, z3) // t0 := t0 * Z3 + y3.Add(y3, t0) // Y3 := Y3 + t0 + t0.Mul(p.y, p.z) // t0 := Y * Z + t0.Add(t0, t0) // t0 := t0 + t0 + z3.Mul(t0, z3) // Z3 := t0 * Z3 + x3.Sub(x3, z3) // X3 := X3 - Z3 + z3.Mul(t0, t1) // Z3 := t0 * t1 + z3.Add(z3, z3) // Z3 := Z3 + Z3 + z3.Add(z3, z3) // Z3 := Z3 + Z3 + + q.x.Set(x3) + q.y.Set(y3) + q.z.Set(z3) + return q +} + +// Select sets q to p1 if cond == 1, and to p2 if cond == 0. +func (q *P384Point) Select(p1, p2 *P384Point, cond int) *P384Point { + q.x.Select(p1.x, p2.x, cond) + q.y.Select(p1.y, p2.y, cond) + q.z.Select(p1.z, p2.z, cond) + return q +} + +// ScalarMult sets p = scalar * q, and returns p. +func (p *P384Point) ScalarMult(q *P384Point, scalar []byte) *P384Point { + // table holds the first 16 multiples of q. The explicit newP384Point calls + // get inlined, letting the allocations live on the stack. + var table = [16]*P384Point{ + NewP384Point(), NewP384Point(), NewP384Point(), NewP384Point(), + NewP384Point(), NewP384Point(), NewP384Point(), NewP384Point(), + NewP384Point(), NewP384Point(), NewP384Point(), NewP384Point(), + NewP384Point(), NewP384Point(), NewP384Point(), NewP384Point(), + } + for i := 1; i < 16; i++ { + table[i].Add(table[i-1], q) + } + + // Instead of doing the classic double-and-add chain, we do it with a + // four-bit window: we double four times, and then add [0-15]P. + t := NewP384Point() + p.Set(NewP384Point()) + for _, byte := range scalar { + p.Double(p) + p.Double(p) + p.Double(p) + p.Double(p) + + for i := uint8(0); i < 16; i++ { + cond := subtle.ConstantTimeByteEq(byte>>4, i) + t.Select(table[i], t, cond) + } + p.Add(p, t) + + p.Double(p) + p.Double(p) + p.Double(p) + p.Double(p) + + for i := uint8(0); i < 16; i++ { + cond := subtle.ConstantTimeByteEq(byte&0b1111, i) + t.Select(table[i], t, cond) + } + p.Add(p, t) + } + + return p +} diff --git a/src/crypto/elliptic/internal/nistec/p521.go b/src/crypto/elliptic/internal/nistec/p521.go index e5b4e46d4b..cdbd195cf4 100644 --- a/src/crypto/elliptic/internal/nistec/p521.go +++ b/src/crypto/elliptic/internal/nistec/p521.go @@ -58,7 +58,11 @@ func NewP521Point() *P521Point { // NewP521Generator returns a new P521Point set to the canonical generator. func NewP521Generator() *P521Point { - return NewP521Point().Set(p521G) + return (&P521Point{ + x: new(fiat.P521Element), + y: new(fiat.P521Element), + z: new(fiat.P521Element), + }).Set(p521G) } // Set sets p = q and returns p. diff --git a/src/crypto/elliptic/internal/nistec/p521_test.go b/src/crypto/elliptic/internal/nistec/p521_test.go deleted file mode 100644 index e62c1cbf29..0000000000 --- a/src/crypto/elliptic/internal/nistec/p521_test.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package nistec_test - -import ( - "crypto/elliptic/internal/nistec" - "math/rand" - "os" - "strings" - "testing" -) - -func TestP521Allocations(t *testing.T) { - if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-noopt") { - t.Skip("skipping allocations test without relevant optimizations") - } - if allocs := testing.AllocsPerRun(100, func() { - p := nistec.NewP521Generator() - scalar := make([]byte, 66) - rand.Read(scalar) - p.ScalarMult(p, scalar) - out := p.Bytes() - if _, err := p.SetBytes(out); err != nil { - t.Fatal(err) - } - }); allocs > 0 { - t.Errorf("expected zero allocations, got %0.1f", allocs) - } -} - -func BenchmarkScalarMult(b *testing.B) { - b.Run("P521", func(b *testing.B) { - scalar := make([]byte, 66) - rand.Read(scalar) - p := nistec.NewP521Generator() - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - p.ScalarMult(p, scalar) - } - }) -} diff --git a/src/crypto/elliptic/p224.go b/src/crypto/elliptic/p224.go index 34079d14b1..a8533b85ff 100644 --- a/src/crypto/elliptic/p224.go +++ b/src/crypto/elliptic/p224.go @@ -1,739 +1,136 @@ -// Copyright 2012 The Go Authors. All rights reserved. +// Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package elliptic -// This is a constant-time, 32-bit implementation of P224. See FIPS 186-3, -// section D.2.2. -// -// See https://www.imperialviolet.org/2010/12/04/ecc.html ([1]) for background. - import ( - "encoding/binary" + "crypto/elliptic/internal/nistec" + "crypto/rand" "math/big" - "math/bits" ) -var p224 p224Curve - -type p224Curve struct { - *CurveParams - gx, gy, b p224FieldElement -} - -func initP224() { - // See FIPS 186-3, section D.2.2 - p224.CurveParams = &CurveParams{Name: "P-224"} - p224.P, _ = new(big.Int).SetString("26959946667150639794667015087019630673557916260026308143510066298881", 10) - p224.N, _ = new(big.Int).SetString("26959946667150639794667015087019625940457807714424391721682722368061", 10) - p224.B, _ = new(big.Int).SetString("b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", 16) - p224.Gx, _ = new(big.Int).SetString("b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 16) - p224.Gy, _ = new(big.Int).SetString("bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34", 16) - p224.BitSize = 224 - - p224FromBig(&p224.gx, p224.Gx) - p224FromBig(&p224.gy, p224.Gy) - p224FromBig(&p224.b, p224.B) -} - -// P224 returns a Curve which implements P-224 (see FIPS 186-3, section D.2.2). -// -// The cryptographic operations are implemented using constant-time algorithms. -func P224() Curve { - initonce.Do(initAll) - return p224 -} - -func (curve p224Curve) Params() *CurveParams { - return curve.CurveParams -} - -func (curve p224Curve) IsOnCurve(bigX, bigY *big.Int) bool { - if bigX.BitLen() > 224 || bigY.BitLen() > 224 { - return false - } - - var x, y p224FieldElement - p224FromBig(&x, bigX) - p224FromBig(&y, bigY) - - // y² = x³ - 3x + b - var tmp p224LargeFieldElement - var x3 p224FieldElement - p224Square(&x3, &x, &tmp) - p224Mul(&x3, &x3, &x, &tmp) - - for i := 0; i < 8; i++ { - x[i] *= 3 - } - p224Sub(&x3, &x3, &x) - p224Reduce(&x3) - p224Add(&x3, &x3, &curve.b) - p224Contract(&x3, &x3) - - p224Square(&y, &y, &tmp) - p224Contract(&y, &y) - - for i := 0; i < 8; i++ { - if y[i] != x3[i] { - return false - } - } - return true -} - -func (p224Curve) Add(bigX1, bigY1, bigX2, bigY2 *big.Int) (x, y *big.Int) { - var x1, y1, z1, x2, y2, z2, x3, y3, z3 p224FieldElement - - p224FromBig(&x1, bigX1) - p224FromBig(&y1, bigY1) - if bigX1.Sign() != 0 || bigY1.Sign() != 0 { - z1[0] = 1 - } - p224FromBig(&x2, bigX2) - p224FromBig(&y2, bigY2) - if bigX2.Sign() != 0 || bigY2.Sign() != 0 { - z2[0] = 1 - } - - p224AddJacobian(&x3, &y3, &z3, &x1, &y1, &z1, &x2, &y2, &z2) - return p224ToAffine(&x3, &y3, &z3) -} - -func (p224Curve) Double(bigX1, bigY1 *big.Int) (x, y *big.Int) { - var x1, y1, z1, x2, y2, z2 p224FieldElement - - p224FromBig(&x1, bigX1) - p224FromBig(&y1, bigY1) - z1[0] = 1 - - p224DoubleJacobian(&x2, &y2, &z2, &x1, &y1, &z1) - return p224ToAffine(&x2, &y2, &z2) -} - -func (p224Curve) ScalarMult(bigX1, bigY1 *big.Int, scalar []byte) (x, y *big.Int) { - var x1, y1, z1, x2, y2, z2 p224FieldElement - - p224FromBig(&x1, bigX1) - p224FromBig(&y1, bigY1) - z1[0] = 1 - - p224ScalarMult(&x2, &y2, &z2, &x1, &y1, &z1, scalar) - return p224ToAffine(&x2, &y2, &z2) -} - -func (curve p224Curve) ScalarBaseMult(scalar []byte) (x, y *big.Int) { - var z1, x2, y2, z2 p224FieldElement - - z1[0] = 1 - p224ScalarMult(&x2, &y2, &z2, &curve.gx, &curve.gy, &z1, scalar) - return p224ToAffine(&x2, &y2, &z2) -} - -// Field element functions. -// -// The field that we're dealing with is ℤ/pℤ where p = 2**224 - 2**96 + 1. -// -// Field elements are represented by a FieldElement, which is a typedef to an -// array of 8 uint32's. The value of a FieldElement, a, is: -// a[0] + 2**28·a[1] + 2**56·a[1] + ... + 2**196·a[7] -// -// Using 28-bit limbs means that there's only 4 bits of headroom, which is less -// than we would really like. But it has the useful feature that we hit 2**224 -// exactly, making the reflections during a reduce much nicer. -type p224FieldElement [8]uint32 - -// p224P is the order of the field, represented as a p224FieldElement. -var p224P = p224FieldElement{1, 0, 0, 0xffff000, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff} - -// p224IsZero returns 1 if a == 0 mod p and 0 otherwise. +// p224Curve is a Curve implementation based on nistec.P224Point. // -// a[i] < 2**29 -func p224IsZero(a *p224FieldElement) uint32 { - var minimal p224FieldElement - p224Contract(&minimal, a) - - var acc uint32 - for _, v := range minimal { - acc |= v - } - mask := ^maskIsNotZero(acc) - - return 1 & mask -} - -// p224Add computes *out = a+b +// It's a wrapper that exposes the big.Int-based Curve interface and encodes the +// legacy idiosyncrasies it requires, such as invalid and infinity point +// handling. // -// a[i] + b[i] < 2**32 -func p224Add(out, a, b *p224FieldElement) { - for i := 0; i < 8; i++ { - out[i] = a[i] + b[i] - } -} - -const two31p3 = 1<<31 + 1<<3 -const two31m3 = 1<<31 - 1<<3 -const two31m15m3 = 1<<31 - 1<<15 - 1<<3 - -// p224ZeroModP31 is 0 mod p where bit 31 is set in all limbs so that we can -// subtract smaller amounts without underflow. See the section "Subtraction" in -// [1] for reasoning. -// -// To calculate this value, start by adding 2³¹ to the lowest limb and -// subtracting 2³ from the next one to compensate. Repeat for each next limb, -// ending up with 2³¹ - 2³ in each of them, and a carry of -2³. Apply the -// reduction identity, and we need to subtract 2³ * 2⁹⁶ - 2³ = 2¹⁵ * 2⁸⁴ - 2³ so -// we subtract 2¹⁵ from the 4th limb and add 2³ to the first limb. -var p224ZeroModP31 = []uint32{two31p3, two31m3, two31m3, two31m15m3, two31m3, two31m3, two31m3, two31m3} - -// p224Sub computes *out = a-b -// -// a[i], b[i] < 2**30 -// out[i] < 2**32 -func p224Sub(out, a, b *p224FieldElement) { - for i := 0; i < 8; i++ { - out[i] = a[i] + p224ZeroModP31[i] - b[i] - } -} - -// LargeFieldElement also represents an element of the field. The limbs are -// still spaced 28-bits apart and in little-endian order. So the limbs are at -// 0, 28, 56, ..., 392 bits, each 64-bits wide. -type p224LargeFieldElement [15]uint64 - -const two63p35 = 1<<63 + 1<<35 -const two63m35 = 1<<63 - 1<<35 -const two63m35m19 = 1<<63 - 1<<35 - 1<<19 - -// p224ZeroModP63 is 0 mod p where bit 63 is set in all limbs. See the section -// "Subtraction" in [1] for why. -var p224ZeroModP63 = [8]uint64{two63p35, two63m35, two63m35, two63m35, two63m35m19, two63m35, two63m35, two63m35} - -const bottom12Bits = 0xfff -const bottom28Bits = 0xfffffff - -// p224Mul computes *out = a*b -// -// a[i] < 2**29, b[i] < 2**30 (or vice versa) -// out[i] < 2**29 -func p224Mul(out, a, b *p224FieldElement, tmp *p224LargeFieldElement) { - for i := range tmp { - tmp[i] = 0 - } - - for i := 0; i < 8; i++ { - for j := 0; j < 8; j++ { - tmp[i+j] += uint64(a[i]) * uint64(b[j]) - } - } - - p224ReduceLarge(out, tmp) -} - -// Square computes *out = a*a -// -// a[i] < 2**29 -// out[i] < 2**29 -func p224Square(out, a *p224FieldElement, tmp *p224LargeFieldElement) { - for i := range tmp { - tmp[i] = 0 - } - - for i := 0; i < 8; i++ { - for j := 0; j <= i; j++ { - r := uint64(a[i]) * uint64(a[j]) - if i == j { - tmp[i+j] += r - } else { - tmp[i+j] += r * 2 - } - } - } - - p224ReduceLarge(out, tmp) +// To interact with the nistec package, points are encoded into and decoded from +// properly formatted byte slices. All big.Int use is limited to this package. +// Encoding and decoding is 1/1000th of the runtime of a scalar multiplication, +// so the overhead is acceptable. +type p224Curve struct { + params *CurveParams } -// ReduceLarge converts a p224LargeFieldElement to a p224FieldElement. -// -// in[i] < 2**62 -// out[i] < 2**29 -func p224ReduceLarge(out *p224FieldElement, in *p224LargeFieldElement) { - for i := 0; i < 8; i++ { - in[i] += p224ZeroModP63[i] - } - - // Eliminate the coefficients at 2**224 and greater by applying the - // reduction identity. - // - // a + top * 2²²⁴ = a + top * 2⁹⁶ - top - // - // Since top here is in[8..14], both the subtraction at offset 0 and the - // addition at offset 96 (3 * 28 + 16) span multiple limbs. The subtraction - // can't underflow because of the p224ZeroModP63 addition above, while the - // addition can't overflow because of the 62 bit input bounds. - for i := 14; i >= 8; i-- { - in[i-8] -= in[i] - in[i-5] += (in[i] & 0xffff) << 12 - in[i-4] += in[i] >> 16 - } - in[8] = 0 - // in[0..7] < 2**64 - // in[9..14] discarded - - // Run a carry chain and light reduction. Keep [0] large so we can do the - // subtraction safely. As the values become small enough, we start to store - // them in out and use 32-bit operations. - for i := 1; i < 8; i++ { - in[i+1] += in[i] >> 28 - out[i] = uint32(in[i] & bottom28Bits) - } - in[0] -= in[8] - out[3] += uint32(in[8]&0xffff) << 12 - out[4] += uint32(in[8] >> 16) - // in[0] < 2**64 - // out[3] < 2**29 - // out[4] < 2**29 - // out[1,2,5..7] < 2**28 - - // Carry the overflow of [0] into the short 28 bit limbs. - out[0] = uint32(in[0] & bottom28Bits) - out[1] += uint32((in[0] >> 28) & bottom28Bits) - out[2] += uint32(in[0] >> 56) - // out[0] < 2**28 - // out[1..4] < 2**29 - // out[5..7] < 2**28 -} +var p224 p224Curve +var _ Curve = p224 -// Reduce reduces the coefficients of a to smaller bounds. -// -// On entry: a[i] < 2**31 + 2**30 -// On exit: a[i] < 2**29 -func p224Reduce(a *p224FieldElement) { - for i := 0; i < 7; i++ { - a[i+1] += a[i] >> 28 - a[i] &= bottom28Bits +func initP224() { + p224.params = &CurveParams{ + Name: "P-224", + BitSize: 224, + // FIPS 186-4, section D.1.2.2 + P: bigFromDecimal("26959946667150639794667015087019630673557916260026308143510066298881"), + N: bigFromDecimal("26959946667150639794667015087019625940457807714424391721682722368061"), + B: bigFromHex("b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4"), + Gx: bigFromHex("b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21"), + Gy: bigFromHex("bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"), } - top := a[7] >> 28 - a[7] &= bottom28Bits - - a[0] -= top - a[3] += top << 12 - - // We may have just made a[0] negative but if we did top must have been not - // zero, so a[3] is not zero, so we can carry down to a[0]. (Note that we - // don't actually check if a[0] went negative, like in p224Contract, nor we - // try to stop the carry at a[1] or a[2], because here we can afford to go - // above 28 bits, so instead we carry all the way down from a[3].) - mask := maskIsNotZero(top) - a[3] -= 1 & mask - a[2] += mask & (1<<28 - 1) - a[1] += mask & (1<<28 - 1) - a[0] += mask & (1 << 28) } -// p224Invert calculates *out = in**-1 by using Fermat's little theorem and -// computing in**(p-2) = in**(2**224 - 2**96 - 1). -func p224Invert(out, in *p224FieldElement) { - var f1, f2, f3, f4 p224FieldElement - var c p224LargeFieldElement - - p224Square(&f1, in, &c) // 2 - p224Mul(&f1, &f1, in, &c) // 2**2 - 1 - p224Square(&f1, &f1, &c) // 2**3 - 2 - p224Mul(&f1, &f1, in, &c) // 2**3 - 1 - p224Square(&f2, &f1, &c) // 2**4 - 2 - p224Square(&f2, &f2, &c) // 2**5 - 4 - p224Square(&f2, &f2, &c) // 2**6 - 8 - p224Mul(&f1, &f1, &f2, &c) // 2**6 - 1 - p224Square(&f2, &f1, &c) // 2**7 - 2 - for i := 0; i < 5; i++ { // 2**12 - 2**6 - p224Square(&f2, &f2, &c) - } - p224Mul(&f2, &f2, &f1, &c) // 2**12 - 1 - p224Square(&f3, &f2, &c) // 2**13 - 2 - for i := 0; i < 11; i++ { // 2**24 - 2**12 - p224Square(&f3, &f3, &c) - } - p224Mul(&f2, &f3, &f2, &c) // 2**24 - 1 - p224Square(&f3, &f2, &c) // 2**25 - 2 - for i := 0; i < 23; i++ { // 2**48 - 2**24 - p224Square(&f3, &f3, &c) - } - p224Mul(&f3, &f3, &f2, &c) // 2**48 - 1 - p224Square(&f4, &f3, &c) // 2**49 - 2 - for i := 0; i < 47; i++ { // 2**96 - 2**48 - p224Square(&f4, &f4, &c) - } - p224Mul(&f3, &f3, &f4, &c) // 2**96 - 1 - p224Square(&f4, &f3, &c) // 2**97 - 2 - for i := 0; i < 23; i++ { // 2**120 - 2**24 - p224Square(&f4, &f4, &c) - } - p224Mul(&f2, &f4, &f2, &c) // 2**120 - 1 - for i := 0; i < 6; i++ { // 2**126 - 2**6 - p224Square(&f2, &f2, &c) - } - p224Mul(&f1, &f1, &f2, &c) // 2**126 - 1 - p224Square(&f1, &f1, &c) // 2**127 - 2 - p224Mul(&f1, &f1, in, &c) // 2**127 - 1 - for i := 0; i < 97; i++ { // 2**224 - 2**97 - p224Square(&f1, &f1, &c) - } - p224Mul(out, &f1, &f3, &c) // 2**224 - 2**96 - 1 +func (curve p224Curve) Params() *CurveParams { + return curve.params } -// p224Contract converts a FieldElement to its unique, minimal form. -// -// On entry, in[i] < 2**29 -// On exit, out[i] < 2**28 and out < p -func p224Contract(out, in *p224FieldElement) { - copy(out[:], in[:]) - - // First, carry the bits above 28 to the higher limb. - for i := 0; i < 7; i++ { - out[i+1] += out[i] >> 28 - out[i] &= bottom28Bits - } - top := out[7] >> 28 - out[7] &= bottom28Bits - - // Use the reduction identity to carry the overflow. - // - // a + top * 2²²⁴ = a + top * 2⁹⁶ - top - out[0] -= top - out[3] += top << 12 - - // We may just have made out[0] negative. So we carry down. If we made - // out[0] negative then we know that out[3] is sufficiently positive - // because we just added to it. - for i := 0; i < 3; i++ { - mask := maskIsNegative(out[i]) - out[i] += (1 << 28) & mask - out[i+1] -= 1 & mask - } - - // We might have pushed out[3] over 2**28 so we perform another, partial, - // carry chain; carry the overflow according to the reduction identity; and - // carry down in case we made out[0] negative. - for i := 3; i < 7; i++ { - out[i+1] += out[i] >> 28 - out[i] &= bottom28Bits - } - top = out[7] >> 28 - out[7] &= bottom28Bits - - out[0] -= top - out[3] += top << 12 - - for i := 0; i < 3; i++ { - mask := maskIsNegative(out[i]) - out[i] += (1 << 28) & mask - out[i+1] -= 1 & mask - } - - // There are two cases to consider for out[3]: - // 1) The first time that we eliminated top, we didn't push out[3] over - // 2**28. In this case, the partial carry chain didn't change any values - // and top is now zero. - // 2) We did push out[3] over 2**28 the first time that we eliminated top. - // The first value of top was in [0..2], therefore, after overflowing - // and being reduced by the second carry chain, out[3] <= 2<<12 - 1. - // In both cases, out[3] cannot have overflowed when we eliminated top for - // the second time. - - // Now we need to subtract p if the value is >= p. To check, we subtract p - // with a borrow chain and look at the final borrow bit. - var b uint32 - for i := 0; i < len(out); i++ { - _, b = bits.Sub32(out[i], p224P[i], b) - } - mask := ^maskIsNotZero(b) - - out[0] -= 1 & mask - out[3] -= 0xffff000 & mask - out[4] -= 0xfffffff & mask - out[5] -= 0xfffffff & mask - out[6] -= 0xfffffff & mask - out[7] -= 0xfffffff & mask - - // Do one final carry down, in case we made out[0] negative. One of - // out[0..3] needs to be positive and able to absorb the -1 or the value - // would have been < p, and the subtraction wouldn't have happened. - for i := 0; i < 3; i++ { - mask := maskIsNegative(out[i]) - out[i] += (1 << 28) & mask - out[i+1] -= 1 & mask +func (curve p224Curve) IsOnCurve(x, y *big.Int) bool { + // IsOnCurve is documented to reject (0, 0), the conventional point at + // infinity, which however is accepted by p224PointFromAffine. + if x.Sign() == 0 && y.Sign() == 0 { + return false } + _, ok := p224PointFromAffine(x, y) + return ok } -// maskIsNegative returns 0xffffffff if the most significant bit of v is set, -// and 0 otherwise. -func maskIsNegative(v uint32) uint32 { return uint32(int32(v) >> 31) } - -// maskIfNegative returns 0xffffffff if v is not zero, and 0 otherwise. -func maskIsNotZero(v uint32) uint32 { - v |= v >> 16 - v |= v >> 8 - v |= v >> 4 - v |= v >> 2 - v |= v >> 1 - return uint32(int32(v<<31) >> 31) -} - -// Group element functions. -// -// These functions deal with group elements. The group is an elliptic curve -// group with a = -3 defined in FIPS 186-3, section D.2.2. - -// p224AddJacobian computes *out = a+b where a != b. -func p224AddJacobian(x3, y3, z3, x1, y1, z1, x2, y2, z2 *p224FieldElement) { - // See https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-p224Add-2007-bl - var z1z1, z2z2, u1, u2, s1, s2, h, i, j, r, v p224FieldElement - var c p224LargeFieldElement - - z1IsZero := p224IsZero(z1) - z2IsZero := p224IsZero(z2) - - // Z1Z1 = Z1² - p224Square(&z1z1, z1, &c) - // Z2Z2 = Z2² - p224Square(&z2z2, z2, &c) - // U1 = X1*Z2Z2 - p224Mul(&u1, x1, &z2z2, &c) - // U2 = X2*Z1Z1 - p224Mul(&u2, x2, &z1z1, &c) - // S1 = Y1*Z2*Z2Z2 - p224Mul(&s1, z2, &z2z2, &c) - p224Mul(&s1, y1, &s1, &c) - // S2 = Y2*Z1*Z1Z1 - p224Mul(&s2, z1, &z1z1, &c) - p224Mul(&s2, y2, &s2, &c) - // H = U2-U1 - p224Sub(&h, &u2, &u1) - p224Reduce(&h) - xEqual := p224IsZero(&h) - // I = (2*H)² - for j := 0; j < 8; j++ { - i[j] = h[j] << 1 - } - p224Reduce(&i) - p224Square(&i, &i, &c) - // J = H*I - p224Mul(&j, &h, &i, &c) - // r = 2*(S2-S1) - p224Sub(&r, &s2, &s1) - p224Reduce(&r) - yEqual := p224IsZero(&r) - if xEqual == 1 && yEqual == 1 && z1IsZero == 0 && z2IsZero == 0 { - p224DoubleJacobian(x3, y3, z3, x1, y1, z1) - return - } - for i := 0; i < 8; i++ { - r[i] <<= 1 +func p224PointFromAffine(x, y *big.Int) (p *nistec.P224Point, ok bool) { + // (0, 0) is by convention the point at infinity, which can't be represented + // in affine coordinates. Marshal incorrectly encodes it as an uncompressed + // point, which SetBytes would correctly reject. See Issue 37294. + if x.Sign() == 0 && y.Sign() == 0 { + return nistec.NewP224Point(), true } - p224Reduce(&r) - // V = U1*I - p224Mul(&v, &u1, &i, &c) - // Z3 = ((Z1+Z2)²-Z1Z1-Z2Z2)*H - p224Add(&z1z1, &z1z1, &z2z2) - p224Add(&z2z2, z1, z2) - p224Reduce(&z2z2) - p224Square(&z2z2, &z2z2, &c) - p224Sub(z3, &z2z2, &z1z1) - p224Reduce(z3) - p224Mul(z3, z3, &h, &c) - // X3 = r²-J-2*V - for i := 0; i < 8; i++ { - z1z1[i] = v[i] << 1 + if x.BitLen() > 224 || y.BitLen() > 224 { + return nil, false } - p224Add(&z1z1, &j, &z1z1) - p224Reduce(&z1z1) - p224Square(x3, &r, &c) - p224Sub(x3, x3, &z1z1) - p224Reduce(x3) - // Y3 = r*(V-X3)-2*S1*J - for i := 0; i < 8; i++ { - s1[i] <<= 1 + p, err := nistec.NewP224Point().SetBytes(Marshal(P224(), x, y)) + if err != nil { + return nil, false } - p224Mul(&s1, &s1, &j, &c) - p224Sub(&z1z1, &v, x3) - p224Reduce(&z1z1) - p224Mul(&z1z1, &z1z1, &r, &c) - p224Sub(y3, &z1z1, &s1) - p224Reduce(y3) - - p224CopyConditional(x3, x2, z1IsZero) - p224CopyConditional(x3, x1, z2IsZero) - p224CopyConditional(y3, y2, z1IsZero) - p224CopyConditional(y3, y1, z2IsZero) - p224CopyConditional(z3, z2, z1IsZero) - p224CopyConditional(z3, z1, z2IsZero) + return p, true } -// p224DoubleJacobian computes *out = a+a. -func p224DoubleJacobian(x3, y3, z3, x1, y1, z1 *p224FieldElement) { - var delta, gamma, beta, alpha, t p224FieldElement - var c p224LargeFieldElement - - p224Square(&delta, z1, &c) - p224Square(&gamma, y1, &c) - p224Mul(&beta, x1, &gamma, &c) - - // alpha = 3*(X1-delta)*(X1+delta) - p224Add(&t, x1, &delta) - for i := 0; i < 8; i++ { - t[i] += t[i] << 1 - } - p224Reduce(&t) - p224Sub(&alpha, x1, &delta) - p224Reduce(&alpha) - p224Mul(&alpha, &alpha, &t, &c) - - // Z3 = (Y1+Z1)²-gamma-delta - p224Add(z3, y1, z1) - p224Reduce(z3) - p224Square(z3, z3, &c) - p224Sub(z3, z3, &gamma) - p224Reduce(z3) - p224Sub(z3, z3, &delta) - p224Reduce(z3) - - // X3 = alpha²-8*beta - for i := 0; i < 8; i++ { - delta[i] = beta[i] << 3 - } - p224Reduce(&delta) - p224Square(x3, &alpha, &c) - p224Sub(x3, x3, &delta) - p224Reduce(x3) - - // Y3 = alpha*(4*beta-X3)-8*gamma² - for i := 0; i < 8; i++ { - beta[i] <<= 2 +func p224PointToAffine(p *nistec.P224Point) (x, y *big.Int) { + out := p.Bytes() + if len(out) == 1 && out[0] == 0 { + // This is the correct encoding of the point at infinity, which + // Unmarshal does not support. See Issue 37294. + return new(big.Int), new(big.Int) } - p224Sub(&beta, &beta, x3) - p224Reduce(&beta) - p224Square(&gamma, &gamma, &c) - for i := 0; i < 8; i++ { - gamma[i] <<= 3 + x, y = Unmarshal(P224(), out) + if x == nil { + panic("crypto/elliptic: internal error: Unmarshal rejected a valid point encoding") } - p224Reduce(&gamma) - p224Mul(y3, &alpha, &beta, &c) - p224Sub(y3, y3, &gamma) - p224Reduce(y3) + return x, y } -// p224CopyConditional sets *out = *in in constant time if control is not zero. -func p224CopyConditional(out, in *p224FieldElement, control uint32) { - mask := maskIsNotZero(control) - for i := 0; i < 8; i++ { - out[i] ^= (out[i] ^ in[i]) & mask +// p224RandomPoint returns a random point on the curve. It's used when Add, +// Double, or ScalarMult are fed a point not on the curve, which is undefined +// behavior. Originally, we used to do the math on it anyway (which allows +// invalid curve attacks) and relied on the caller and Unmarshal to avoid this +// happening in the first place. Now, we just can't construct a nistec.P224Point +// for an invalid pair of coordinates, because that API is safer. If we panic, +// we risk introducing a DoS. If we return nil, we risk a panic. If we return +// the input, ecdsa.Verify might fail open. The safest course seems to be to +// return a valid, random point, which hopefully won't help the attacker. +func p224RandomPoint() (x, y *big.Int) { + _, x, y, err := GenerateKey(P224(), rand.Reader) + if err != nil { + panic("crypto/elliptic: failed to generate random point") } + return x, y } -func p224ScalarMult(outX, outY, outZ, inX, inY, inZ *p224FieldElement, scalar []byte) { - var xx, yy, zz p224FieldElement - for i := 0; i < 8; i++ { - outX[i] = 0 - outY[i] = 0 - outZ[i] = 0 +func (p224Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { + p1, ok := p224PointFromAffine(x1, y1) + if !ok { + return p224RandomPoint() } - - for _, byte := range scalar { - for bitNum := uint(0); bitNum < 8; bitNum++ { - p224DoubleJacobian(outX, outY, outZ, outX, outY, outZ) - bit := uint32((byte >> (7 - bitNum)) & 1) - p224AddJacobian(&xx, &yy, &zz, inX, inY, inZ, outX, outY, outZ) - p224CopyConditional(outX, &xx, bit) - p224CopyConditional(outY, &yy, bit) - p224CopyConditional(outZ, &zz, bit) - } + p2, ok := p224PointFromAffine(x2, y2) + if !ok { + return p224RandomPoint() } + return p224PointToAffine(p1.Add(p1, p2)) } -// p224ToAffine converts from Jacobian to affine form. -func p224ToAffine(x, y, z *p224FieldElement) (*big.Int, *big.Int) { - var zinv, zinvsq, outx, outy p224FieldElement - var tmp p224LargeFieldElement - - if isPointAtInfinity := p224IsZero(z); isPointAtInfinity == 1 { - return new(big.Int), new(big.Int) +func (p224Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { + p, ok := p224PointFromAffine(x1, y1) + if !ok { + return p224RandomPoint() } - - p224Invert(&zinv, z) - p224Square(&zinvsq, &zinv, &tmp) - p224Mul(x, x, &zinvsq, &tmp) - p224Mul(&zinvsq, &zinvsq, &zinv, &tmp) - p224Mul(y, y, &zinvsq, &tmp) - - p224Contract(&outx, x) - p224Contract(&outy, y) - return p224ToBig(&outx), p224ToBig(&outy) + return p224PointToAffine(p.Double(p)) } -// get28BitsFromEnd returns the least-significant 28 bits from buf>>shift, -// where buf is interpreted as a big-endian number. shift must be at most -// 4 bits higher than a multiple of 8. -func get28BitsFromEnd(buf []byte, shift int) uint32 { - buf = buf[:len(buf)-shift/8] - shift = shift % 8 - if shift > 4 { - panic("misuse of get28BitsFromEnd") +func (p224Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) { + p, ok := p224PointFromAffine(Bx, By) + if !ok { + return p224RandomPoint() } - - ret := binary.BigEndian.Uint32(buf[len(buf)-4:]) - ret >>= shift - ret &= bottom28Bits - return ret + return p224PointToAffine(p.ScalarMult(p, scalar)) } -// p224FromBig sets *out = *in. -func p224FromBig(out *p224FieldElement, in *big.Int) { - bytes := in.FillBytes(make([]byte, 224/8)) - for i := range out { - out[i] = get28BitsFromEnd(bytes, 28*i) - } -} - -// p224ToBig returns in as a big.Int. -func p224ToBig(in *p224FieldElement) *big.Int { - var buf [28]byte - buf[27] = byte(in[0]) - buf[26] = byte(in[0] >> 8) - buf[25] = byte(in[0] >> 16) - buf[24] = byte(((in[0] >> 24) & 0x0f) | (in[1]<<4)&0xf0) - - buf[23] = byte(in[1] >> 4) - buf[22] = byte(in[1] >> 12) - buf[21] = byte(in[1] >> 20) - - buf[20] = byte(in[2]) - buf[19] = byte(in[2] >> 8) - buf[18] = byte(in[2] >> 16) - buf[17] = byte(((in[2] >> 24) & 0x0f) | (in[3]<<4)&0xf0) - - buf[16] = byte(in[3] >> 4) - buf[15] = byte(in[3] >> 12) - buf[14] = byte(in[3] >> 20) - - buf[13] = byte(in[4]) - buf[12] = byte(in[4] >> 8) - buf[11] = byte(in[4] >> 16) - buf[10] = byte(((in[4] >> 24) & 0x0f) | (in[5]<<4)&0xf0) - - buf[9] = byte(in[5] >> 4) - buf[8] = byte(in[5] >> 12) - buf[7] = byte(in[5] >> 20) - - buf[6] = byte(in[6]) - buf[5] = byte(in[6] >> 8) - buf[4] = byte(in[6] >> 16) - buf[3] = byte(((in[6] >> 24) & 0x0f) | (in[7]<<4)&0xf0) - - buf[2] = byte(in[7] >> 4) - buf[1] = byte(in[7] >> 12) - buf[0] = byte(in[7] >> 20) - - return new(big.Int).SetBytes(buf[:]) +func (p224Curve) ScalarBaseMult(scalar []byte) (*big.Int, *big.Int) { + p := nistec.NewP224Generator() + return p224PointToAffine(p.ScalarMult(p, scalar)) } diff --git a/src/crypto/elliptic/p224_test.go b/src/crypto/elliptic/p224_test.go index 3e0c78b0f9..7971f631bf 100644 --- a/src/crypto/elliptic/p224_test.go +++ b/src/crypto/elliptic/p224_test.go @@ -8,313 +8,9 @@ import ( "encoding/hex" "fmt" "math/big" - "math/bits" - "math/rand" - "reflect" "testing" - "testing/quick" ) -var toFromBigTests = []string{ - "0", - "1", - "23", - "b70e0cb46bb4bf7f321390b94a03c1d356c01122343280d6105c1d21", - "706a46d476dcb76798e6046d89474788d164c18032d268fd10704fa6", -} - -func p224AlternativeToBig(in *p224FieldElement) *big.Int { - ret := new(big.Int) - tmp := new(big.Int) - - for i := len(in) - 1; i >= 0; i-- { - ret.Lsh(ret, 28) - tmp.SetInt64(int64(in[i])) - ret.Add(ret, tmp) - } - ret.Mod(ret, P224().Params().P) - return ret -} - -func TestP224ToFromBig(t *testing.T) { - for i, test := range toFromBigTests { - n, _ := new(big.Int).SetString(test, 16) - var x p224FieldElement - p224FromBig(&x, n) - m := p224ToBig(&x) - if n.Cmp(m) != 0 { - t.Errorf("#%d: %x != %x", i, n, m) - } - q := p224AlternativeToBig(&x) - if n.Cmp(q) != 0 { - t.Errorf("#%d: %x != %x (alternative)", i, n, q) - } - } -} - -// quickCheckConfig32 will make each quickcheck test run (32 * -quickchecks) -// times. The default value of -quickchecks is 100. -var quickCheckConfig32 = &quick.Config{MaxCountScale: 32} - -// weirdLimbs can be combined to generate a range of edge-case field elements. -var weirdLimbs = [...]uint32{ - 0, 1, (1 << 29) - 1, - (1 << 12), (1 << 12) - 1, - (1 << 28), (1 << 28) - 1, -} - -func generateLimb(rand *rand.Rand) uint32 { - const bottom29Bits = 0x1fffffff - n := rand.Intn(len(weirdLimbs) + 3) - switch n { - case len(weirdLimbs): - // Random value. - return uint32(rand.Int31n(1 << 29)) - case len(weirdLimbs) + 1: - // Sum of two values. - k := generateLimb(rand) + generateLimb(rand) - return k & bottom29Bits - case len(weirdLimbs) + 2: - // Difference of two values. - k := generateLimb(rand) - generateLimb(rand) - return k & bottom29Bits - default: - return weirdLimbs[n] - } -} - -func (p224FieldElement) Generate(rand *rand.Rand, size int) reflect.Value { - return reflect.ValueOf(p224FieldElement{ - generateLimb(rand), - generateLimb(rand), - generateLimb(rand), - generateLimb(rand), - generateLimb(rand), - generateLimb(rand), - generateLimb(rand), - generateLimb(rand), - }) -} - -func isInBounds(x *p224FieldElement) bool { - return bits.Len32(x[0]) <= 29 && - bits.Len32(x[1]) <= 29 && - bits.Len32(x[2]) <= 29 && - bits.Len32(x[3]) <= 29 && - bits.Len32(x[4]) <= 29 && - bits.Len32(x[5]) <= 29 && - bits.Len32(x[6]) <= 29 && - bits.Len32(x[7]) <= 29 -} - -func TestP224Mul(t *testing.T) { - mulMatchesBigInt := func(a, b, out p224FieldElement) bool { - var tmp p224LargeFieldElement - p224Mul(&out, &a, &b, &tmp) - - exp := new(big.Int).Mul(p224AlternativeToBig(&a), p224AlternativeToBig(&b)) - exp.Mod(exp, P224().Params().P) - got := p224AlternativeToBig(&out) - if exp.Cmp(got) != 0 || !isInBounds(&out) { - t.Logf("a = %x", a) - t.Logf("b = %x", b) - t.Logf("p224Mul(a, b) = %x = %v", out, got) - t.Logf("a * b = %v", exp) - return false - } - - return true - } - - a := p224FieldElement{0xfffffff, 0xfffffff, 0xf00ffff, 0x20f, 0x0, 0x0, 0x0, 0x0} - b := p224FieldElement{1, 0, 0, 0, 0, 0, 0, 0} - if !mulMatchesBigInt(a, b, p224FieldElement{}) { - t.Fail() - } - - if err := quick.Check(mulMatchesBigInt, quickCheckConfig32); err != nil { - t.Error(err) - } -} - -func TestP224Square(t *testing.T) { - squareMatchesBigInt := func(a, out p224FieldElement) bool { - var tmp p224LargeFieldElement - p224Square(&out, &a, &tmp) - - exp := p224AlternativeToBig(&a) - exp.Mul(exp, exp) - exp.Mod(exp, P224().Params().P) - got := p224AlternativeToBig(&out) - if exp.Cmp(got) != 0 || !isInBounds(&out) { - t.Logf("a = %x", a) - t.Logf("p224Square(a, b) = %x = %v", out, got) - t.Logf("a * a = %v", exp) - return false - } - - return true - } - - if err := quick.Check(squareMatchesBigInt, quickCheckConfig32); err != nil { - t.Error(err) - } -} - -func TestP224Add(t *testing.T) { - addMatchesBigInt := func(a, b, out p224FieldElement) bool { - p224Add(&out, &a, &b) - - exp := new(big.Int).Add(p224AlternativeToBig(&a), p224AlternativeToBig(&b)) - exp.Mod(exp, P224().Params().P) - got := p224AlternativeToBig(&out) - if exp.Cmp(got) != 0 { - t.Logf("a = %x", a) - t.Logf("b = %x", b) - t.Logf("p224Add(a, b) = %x = %v", out, got) - t.Logf("a + b = %v", exp) - return false - } - - return true - } - - if err := quick.Check(addMatchesBigInt, quickCheckConfig32); err != nil { - t.Error(err) - } -} - -func TestP224Reduce(t *testing.T) { - reduceMatchesBigInt := func(a p224FieldElement) bool { - out := a - // TODO: generate higher values for functions like p224Reduce that are - // expected to work with higher input bounds. - p224Reduce(&out) - - exp := p224AlternativeToBig(&a) - got := p224AlternativeToBig(&out) - if exp.Cmp(got) != 0 || !isInBounds(&out) { - t.Logf("a = %x = %v", a, exp) - t.Logf("p224Reduce(a) = %x = %v", out, got) - return false - } - - return true - } - - if err := quick.Check(reduceMatchesBigInt, quickCheckConfig32); err != nil { - t.Error(err) - } -} - -func TestP224Contract(t *testing.T) { - contractMatchesBigInt := func(a, out p224FieldElement) bool { - p224Contract(&out, &a) - - exp := p224AlternativeToBig(&a) - got := p224AlternativeToBig(&out) - if exp.Cmp(got) != 0 { - t.Logf("a = %x = %v", a, exp) - t.Logf("p224Contract(a) = %x = %v", out, got) - return false - } - - // Check that out < P. - for i := range p224P { - k := 8 - i - 1 - if out[k] > p224P[k] { - t.Logf("p224Contract(a) = %x", out) - return false - } - if out[k] < p224P[k] { - return true - } - } - t.Logf("p224Contract(a) = %x", out) - return false - } - - if !contractMatchesBigInt(p224P, p224FieldElement{}) { - t.Error("p224Contract(p) is broken") - } - pMinus1 := p224FieldElement{0, 0, 0, 0xffff000, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff} - if !contractMatchesBigInt(pMinus1, p224FieldElement{}) { - t.Error("p224Contract(p - 1) is broken") - } - // Check that we can handle input above p, but lowest limb zero. - a := p224FieldElement{0, 1, 0, 0xffff000, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff} - if !contractMatchesBigInt(a, p224FieldElement{}) { - t.Error("p224Contract(p + 2²⁸) is broken") - } - // Check that we can handle input above p, but lowest three limbs zero. - b := p224FieldElement{0, 0, 0, 0xffff001, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff} - if !contractMatchesBigInt(b, p224FieldElement{}) { - t.Error("p224Contract(p + 2⁸⁴) is broken") - } - - if err := quick.Check(contractMatchesBigInt, quickCheckConfig32); err != nil { - t.Error(err) - } -} - -func TestP224IsZero(t *testing.T) { - if got := p224IsZero(&p224FieldElement{}); got != 1 { - t.Errorf("p224IsZero(0) = %d, expected 1", got) - } - if got := p224IsZero(&p224P); got != 1 { - t.Errorf("p224IsZero(p) = %d, expected 1", got) - } - if got := p224IsZero(&p224FieldElement{1}); got != 0 { - t.Errorf("p224IsZero(1) = %d, expected 0", got) - } - - isZeroMatchesBigInt := func(a p224FieldElement) bool { - isZero := p224IsZero(&a) - - big := p224AlternativeToBig(&a) - if big.Sign() == 0 && isZero != 1 { - return false - } - if big.Sign() != 0 && isZero != 0 { - return false - } - return true - } - - if err := quick.Check(isZeroMatchesBigInt, quickCheckConfig32); err != nil { - t.Error(err) - } -} - -func TestP224Invert(t *testing.T) { - var out p224FieldElement - - p224Invert(&out, &p224FieldElement{}) - if got := p224IsZero(&out); got != 1 { - t.Errorf("p224Invert(0) = %x, expected 0", out) - } - - p224Invert(&out, &p224P) - if got := p224IsZero(&out); got != 1 { - t.Errorf("p224Invert(p) = %x, expected 0", out) - } - - p224Invert(&out, &p224FieldElement{1}) - p224Contract(&out, &out) - if out != (p224FieldElement{1}) { - t.Errorf("p224Invert(1) = %x, expected 1", out) - } - - var tmp p224LargeFieldElement - a := p224FieldElement{1, 2, 3, 4, 5, 6, 7, 8} - p224Invert(&out, &a) - p224Mul(&out, &out, &a, &tmp) - p224Contract(&out, &out) - if out != (p224FieldElement{1}) { - t.Errorf("p224Invert(a) * a = %x, expected 1", out) - } -} - type baseMultTest struct { k string x, y string @@ -602,7 +298,7 @@ func TestP224BaseMult(t *testing.T) { func TestP224GenericBaseMult(t *testing.T) { // We use the P224 CurveParams directly in order to test the generic implementation. - p224 := P224().Params() + p224 := genericParamsForCurve(P224()) for i, e := range p224BaseMultTests { k, ok := new(big.Int).SetString(e.k, 10) if !ok { diff --git a/src/crypto/elliptic/p256.go b/src/crypto/elliptic/p256.go index 7747de7a50..7ff7e33548 100644 --- a/src/crypto/elliptic/p256.go +++ b/src/crypto/elliptic/p256.go @@ -209,6 +209,8 @@ var p256Precomputed = [p256Limbs * 2 * 15 * 2]uint32{ // Field element operations: +const bottom28Bits = 0xfffffff + // nonZeroToAllOnes returns: // 0xffffffff for 0 < x <= 2**31 // 0 for x == 0 or x > 2**31. @@ -269,6 +271,7 @@ const ( two30m2 = 1<<30 - 1<<2 two30p13m2 = 1<<30 + 1<<13 - 1<<2 two31m2 = 1<<31 - 1<<2 + two31m3 = 1<<31 - 1<<3 two31p24m2 = 1<<31 + 1<<24 - 1<<2 two30m27m2 = 1<<30 - 1<<27 - 1<<2 ) diff --git a/src/crypto/elliptic/p256_test.go b/src/crypto/elliptic/p256_test.go index 1435f5e1a5..c6862d9547 100644 --- a/src/crypto/elliptic/p256_test.go +++ b/src/crypto/elliptic/p256_test.go @@ -34,7 +34,7 @@ var p256MultTests = []scalarMultTest{ func TestP256BaseMult(t *testing.T) { p256 := P256() - p256Generic := p256.Params() + p256Generic := genericParamsForCurve(p256) scalars := make([]*big.Int, 0, len(p224BaseMultTests)+1) for _, e := range p224BaseMultTests { @@ -60,23 +60,6 @@ func TestP256BaseMult(t *testing.T) { func TestP256Mult(t *testing.T) { p256 := P256() - p256Generic := p256.Params() - - for i, e := range p224BaseMultTests { - x, _ := new(big.Int).SetString(e.x, 16) - y, _ := new(big.Int).SetString(e.y, 16) - k, _ := new(big.Int).SetString(e.k, 10) - - xx, yy := p256.ScalarMult(x, y, k.Bytes()) - xx2, yy2 := p256Generic.ScalarMult(x, y, k.Bytes()) - if xx.Cmp(xx2) != 0 || yy.Cmp(yy2) != 0 { - t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, xx, yy, xx2, yy2) - } - if testing.Short() && i > 5 { - break - } - } - for i, e := range p256MultTests { x, _ := new(big.Int).SetString(e.xIn, 16) y, _ := new(big.Int).SetString(e.yIn, 16) diff --git a/src/crypto/elliptic/p384.go b/src/crypto/elliptic/p384.go new file mode 100644 index 0000000000..0fb7471850 --- /dev/null +++ b/src/crypto/elliptic/p384.go @@ -0,0 +1,141 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package elliptic + +import ( + "crypto/elliptic/internal/nistec" + "crypto/rand" + "math/big" +) + +// p384Curve is a Curve implementation based on nistec.P384Point. +// +// It's a wrapper that exposes the big.Int-based Curve interface and encodes the +// legacy idiosyncrasies it requires, such as invalid and infinity point +// handling. +// +// To interact with the nistec package, points are encoded into and decoded from +// properly formatted byte slices. All big.Int use is limited to this package. +// Encoding and decoding is 1/1000th of the runtime of a scalar multiplication, +// so the overhead is acceptable. +type p384Curve struct { + params *CurveParams +} + +var p384 p384Curve +var _ Curve = p384 + +func initP384() { + p384.params = &CurveParams{ + Name: "P-384", + BitSize: 384, + // FIPS 186-4, section D.1.2.4 + P: bigFromDecimal("394020061963944792122790401001436138050797392704654" + + "46667948293404245721771496870329047266088258938001861606973112319"), + N: bigFromDecimal("394020061963944792122790401001436138050797392704654" + + "46667946905279627659399113263569398956308152294913554433653942643"), + B: bigFromHex("b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088" + + "f5013875ac656398d8a2ed19d2a85c8edd3ec2aef"), + Gx: bigFromHex("aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741" + + "e082542a385502f25dbf55296c3a545e3872760ab7"), + Gy: bigFromHex("3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da31" + + "13b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f"), + } +} + +func (curve p384Curve) Params() *CurveParams { + return curve.params +} + +func (curve p384Curve) IsOnCurve(x, y *big.Int) bool { + // IsOnCurve is documented to reject (0, 0), the conventional point at + // infinity, which however is accepted by p384PointFromAffine. + if x.Sign() == 0 && y.Sign() == 0 { + return false + } + _, ok := p384PointFromAffine(x, y) + return ok +} + +func p384PointFromAffine(x, y *big.Int) (p *nistec.P384Point, ok bool) { + // (0, 0) is by convention the point at infinity, which can't be represented + // in affine coordinates. Marshal incorrectly encodes it as an uncompressed + // point, which SetBytes would correctly reject. See Issue 37294. + if x.Sign() == 0 && y.Sign() == 0 { + return nistec.NewP384Point(), true + } + if x.BitLen() > 384 || y.BitLen() > 384 { + return nil, false + } + p, err := nistec.NewP384Point().SetBytes(Marshal(P384(), x, y)) + if err != nil { + return nil, false + } + return p, true +} + +func p384PointToAffine(p *nistec.P384Point) (x, y *big.Int) { + out := p.Bytes() + if len(out) == 1 && out[0] == 0 { + // This is the correct encoding of the point at infinity, which + // Unmarshal does not support. See Issue 37294. + return new(big.Int), new(big.Int) + } + x, y = Unmarshal(P384(), out) + if x == nil { + panic("crypto/elliptic: internal error: Unmarshal rejected a valid point encoding") + } + return x, y +} + +// p384RandomPoint returns a random point on the curve. It's used when Add, +// Double, or ScalarMult are fed a point not on the curve, which is undefined +// behavior. Originally, we used to do the math on it anyway (which allows +// invalid curve attacks) and relied on the caller and Unmarshal to avoid this +// happening in the first place. Now, we just can't construct a nistec.P384Point +// for an invalid pair of coordinates, because that API is safer. If we panic, +// we risk introducing a DoS. If we return nil, we risk a panic. If we return +// the input, ecdsa.Verify might fail open. The safest course seems to be to +// return a valid, random point, which hopefully won't help the attacker. +func p384RandomPoint() (x, y *big.Int) { + _, x, y, err := GenerateKey(P384(), rand.Reader) + if err != nil { + panic("crypto/elliptic: failed to generate random point") + } + return x, y +} + +func (p384Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { + p1, ok := p384PointFromAffine(x1, y1) + if !ok { + return p384RandomPoint() + } + p2, ok := p384PointFromAffine(x2, y2) + if !ok { + return p384RandomPoint() + } + return p384PointToAffine(p1.Add(p1, p2)) +} + +func (p384Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { + p, ok := p384PointFromAffine(x1, y1) + if !ok { + return p384RandomPoint() + } + return p384PointToAffine(p.Double(p)) +} + +func (p384Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) { + p, ok := p384PointFromAffine(Bx, By) + if !ok { + return p384RandomPoint() + } + return p384PointToAffine(p.ScalarMult(p, scalar)) +} + +func (p384Curve) ScalarBaseMult(scalar []byte) (*big.Int, *big.Int) { + p := nistec.NewP384Generator() + return p384PointToAffine(p.ScalarMult(p, scalar)) +} diff --git a/src/crypto/elliptic/p521.go b/src/crypto/elliptic/p521.go index e64007dfe3..6c9eed30e5 100644 --- a/src/crypto/elliptic/p521.go +++ b/src/crypto/elliptic/p521.go @@ -112,7 +112,7 @@ func p521RandomPoint() (x, y *big.Int) { return x, y } -func (curve p521Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { +func (p521Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { p1, ok := p521PointFromAffine(x1, y1) if !ok { return p521RandomPoint() @@ -124,7 +124,7 @@ func (curve p521Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { return p521PointToAffine(p1.Add(p1, p2)) } -func (curve p521Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { +func (p521Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { p, ok := p521PointFromAffine(x1, y1) if !ok { return p521RandomPoint() @@ -132,7 +132,7 @@ func (curve p521Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { return p521PointToAffine(p.Double(p)) } -func (curve p521Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) { +func (p521Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) { p, ok := p521PointFromAffine(Bx, By) if !ok { return p521RandomPoint() @@ -140,7 +140,7 @@ func (curve p521Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *bi return p521PointToAffine(p.ScalarMult(p, scalar)) } -func (curve p521Curve) ScalarBaseMult(scalar []byte) (*big.Int, *big.Int) { +func (p521Curve) ScalarBaseMult(scalar []byte) (*big.Int, *big.Int) { p := nistec.NewP521Generator() return p521PointToAffine(p.ScalarMult(p, scalar)) } -- GitLab From fa16efb8358e0cb23e285803075764abbdcffe5e Mon Sep 17 00:00:00 2001 From: "Paul E. Murphy" Date: Wed, 14 Jul 2021 14:09:27 -0500 Subject: [PATCH 2000/2500] cmd/link: enable internal linking of PIE binaries on ppc64le The amd64/arm64 relocation processing is used as a template and updated for ppc64le. This requires updating the TOC relocation handling code to support linux type TOC relocations too (note, AIX uses TOC-indirect accesses). Noteably, the shared flag of go functions is used as a proxy for the local entry point offset encoded in elf objects. Functions in go ppc64le shared objects always[1] insert 2 instructions to regenerate the TOC pointer. [1] excepting a couple special runtime functions, see preprocess in obj9.go for specific details of this behavior. Change-Id: I3646e6dc8a0a0ffe712771a976983315eae5c418 Reviewed-on: https://go-review.googlesource.com/c/go/+/352829 Run-TryBot: Paul Murphy Reviewed-by: Cherry Mui TryBot-Result: Go Bot Trust: Lynn Boger --- src/cmd/dist/test.go | 2 +- src/cmd/internal/sys/supported.go | 2 +- src/cmd/link/internal/ld/config.go | 3 +- src/cmd/link/internal/ld/data.go | 2 + src/cmd/link/internal/ppc64/asm.go | 221 +++++++++++++++++++++++++---- src/debug/elf/elf.go | 2 + 6 files changed, 201 insertions(+), 31 deletions(-) diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index 14b48351db..98e30a158f 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -1013,7 +1013,7 @@ func (t *tester) internalLink() bool { func (t *tester) internalLinkPIE() bool { switch goos + "-" + goarch { case "darwin-amd64", "darwin-arm64", - "linux-amd64", "linux-arm64", + "linux-amd64", "linux-arm64", "linux-ppc64le", "android-arm64", "windows-amd64", "windows-386", "windows-arm": return true diff --git a/src/cmd/internal/sys/supported.go b/src/cmd/internal/sys/supported.go index c6a78a51eb..f25aaabddd 100644 --- a/src/cmd/internal/sys/supported.go +++ b/src/cmd/internal/sys/supported.go @@ -158,7 +158,7 @@ func BuildModeSupported(compiler, buildmode, goos, goarch string) bool { func InternalLinkPIESupported(goos, goarch string) bool { switch goos + "/" + goarch { case "darwin/amd64", "darwin/arm64", - "linux/amd64", "linux/arm64", + "linux/amd64", "linux/arm64", "linux/ppc64le", "android/arm64", "windows-amd64", "windows-386", "windows-arm": return true diff --git a/src/cmd/link/internal/ld/config.go b/src/cmd/link/internal/ld/config.go index 2d7e1bff68..33ab7c3df3 100644 --- a/src/cmd/link/internal/ld/config.go +++ b/src/cmd/link/internal/ld/config.go @@ -225,7 +225,8 @@ func mustLinkExternal(ctxt *Link) (res bool, reason string) { return true, "buildmode=c-shared" case BuildModePIE: switch buildcfg.GOOS + "/" + buildcfg.GOARCH { - case "linux/amd64", "linux/arm64", "android/arm64": + case "android/arm64": + case "linux/amd64", "linux/arm64", "linux/ppc64le": case "windows/386", "windows/amd64", "windows/arm", "windows/arm64": case "darwin/amd64", "darwin/arm64": default: diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 0513a0d10b..4d85977d43 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -227,6 +227,8 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) { // DWARF info between the compiler and linker. continue } + } else if target.IsPPC64() && target.IsPIE() && ldr.SymName(rs) == ".TOC." { + // This is a TOC relative relocation generated from a go object. It is safe to resolve. } else { st.err.errorUnresolved(ldr, s, rs) continue diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go index 62b319d196..d2b140b45d 100644 --- a/src/cmd/link/internal/ppc64/asm.go +++ b/src/cmd/link/internal/ppc64/asm.go @@ -321,6 +321,11 @@ func addelfdynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s lo rela.AddUint64(target.Arch, elf.R_INFO(uint32(ldr.SymDynid(targ)), uint32(elf.R_PPC64_ADDR64))) rela.AddUint64(target.Arch, uint64(r.Add())) su.SetRelocType(rIdx, objabi.ElfRelocOffset) // ignore during relocsym + } else if target.IsPIE() && target.IsInternal() { + // For internal linking PIE, this R_ADDR relocation cannot + // be resolved statically. We need to generate a dynamic + // relocation. Let the code below handle it. + break } return true @@ -383,12 +388,94 @@ func addelfdynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s lo } // Handle references to ELF symbols from our own object files. - if targType != sym.SDYNIMPORT { + relocs := ldr.Relocs(s) + r = relocs.At(rIdx) + + switch r.Type() { + case objabi.R_ADDR: + if ldr.SymType(s) == sym.STEXT { + log.Fatalf("R_ADDR relocation in text symbol %s is unsupported\n", ldr.SymName(s)) + } + if target.IsPIE() && target.IsInternal() { + // When internally linking, generate dynamic relocations + // for all typical R_ADDR relocations. The exception + // are those R_ADDR that are created as part of generating + // the dynamic relocations and must be resolved statically. + // + // There are three phases relevant to understanding this: + // + // dodata() // we are here + // address() // symbol address assignment + // reloc() // resolution of static R_ADDR relocs + // + // At this point symbol addresses have not been + // assigned yet (as the final size of the .rela section + // will affect the addresses), and so we cannot write + // the Elf64_Rela.r_offset now. Instead we delay it + // until after the 'address' phase of the linker is + // complete. We do this via Addaddrplus, which creates + // a new R_ADDR relocation which will be resolved in + // the 'reloc' phase. + // + // These synthetic static R_ADDR relocs must be skipped + // now, or else we will be caught in an infinite loop + // of generating synthetic relocs for our synthetic + // relocs. + // + // Furthermore, the rela sections contain dynamic + // relocations with R_ADDR relocations on + // Elf64_Rela.r_offset. This field should contain the + // symbol offset as determined by reloc(), not the + // final dynamically linked address as a dynamic + // relocation would provide. + switch ldr.SymName(s) { + case ".dynsym", ".rela", ".rela.plt", ".got.plt", ".dynamic": + return false + } + } else { + // Either internally linking a static executable, + // in which case we can resolve these relocations + // statically in the 'reloc' phase, or externally + // linking, in which case the relocation will be + // prepared in the 'reloc' phase and passed to the + // external linker in the 'asmb' phase. + if ldr.SymType(s) != sym.SDATA && ldr.SymType(s) != sym.SRODATA { + break + } + } + // Generate R_PPC64_RELATIVE relocations for best + // efficiency in the dynamic linker. + // + // As noted above, symbol addresses have not been + // assigned yet, so we can't generate the final reloc + // entry yet. We ultimately want: + // + // r_offset = s + r.Off + // r_info = R_PPC64_RELATIVE + // r_addend = targ + r.Add + // + // The dynamic linker will set *offset = base address + + // addend. + // + // AddAddrPlus is used for r_offset and r_addend to + // generate new R_ADDR relocations that will update + // these fields in the 'reloc' phase. + rela := ldr.MakeSymbolUpdater(syms.Rela) + rela.AddAddrPlus(target.Arch, s, int64(r.Off())) + if r.Siz() == 8 { + rela.AddUint64(target.Arch, elf.R_INFO(0, uint32(elf.R_PPC64_RELATIVE))) + } else { + ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ)) + } + rela.AddAddrPlus(target.Arch, targ, int64(r.Add())) + + // Not mark r done here. So we still apply it statically, + // so in the file content we'll also have the right offset + // to the relocation target. So it can be examined statically + // (e.g. go version). return true } - // TODO(austin): Translate our relocations to ELF - return false } @@ -542,35 +629,40 @@ func symtoc(ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) int64 { } // archreloctoc relocates a TOC relative symbol. -// If the symbol pointed by this TOC relative symbol is in .data or .bss, the -// default load instruction can be changed to an addi instruction and the -// symbol address can be used directly. -// This code is for AIX only. func archreloctoc(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) int64 { rs := r.Sym() - if target.IsLinux() { - ldr.Errorf(s, "archrelocaddr called for %s relocation\n", ldr.SymName(rs)) - } var o1, o2 uint32 - - o1 = uint32(val >> 32) - o2 = uint32(val) - - if !strings.HasPrefix(ldr.SymName(rs), "TOC.") { - ldr.Errorf(s, "archreloctoc called for a symbol without TOC anchor") - } var t int64 useAddi := false - relocs := ldr.Relocs(rs) - tarSym := relocs.At(0).Sym() - - if target.IsInternal() && tarSym != 0 && ldr.AttrReachable(tarSym) && ldr.SymSect(tarSym).Seg == &ld.Segdata { - t = ldr.SymValue(tarSym) + r.Add() - ldr.SymValue(syms.TOC) - // change ld to addi in the second instruction - o2 = (o2 & 0x03FF0000) | 0xE<<26 - useAddi = true + + if target.IsBigEndian() { + o1 = uint32(val >> 32) + o2 = uint32(val) + } else { + o1 = uint32(val) + o2 = uint32(val >> 32) + } + + // On AIX, TOC data accesses are always made indirectly against R2 (a sequence of addis+ld+load/store). If the + // The target of the load is known, the sequence can be written into addis+addi+load/store. On Linux, + // TOC data accesses are always made directly against R2 (e.g addis+load/store). + if target.IsAIX() { + if !strings.HasPrefix(ldr.SymName(rs), "TOC.") { + ldr.Errorf(s, "archreloctoc called for a symbol without TOC anchor") + } + relocs := ldr.Relocs(rs) + tarSym := relocs.At(0).Sym() + + if target.IsInternal() && tarSym != 0 && ldr.AttrReachable(tarSym) && ldr.SymSect(tarSym).Seg == &ld.Segdata { + t = ldr.SymValue(tarSym) + r.Add() - ldr.SymValue(syms.TOC) + // change ld to addi in the second instruction + o2 = (o2 & 0x03FF0000) | 0xE<<26 + useAddi = true + } else { + t = ldr.SymValue(rs) + r.Add() - ldr.SymValue(syms.TOC) + } } else { - t = ldr.SymValue(rs) + r.Add() - ldr.SymValue(syms.TOC) + t = ldr.SymValue(rs) + r.Add() - symtoc(ldr, syms, s) } if t != int64(int32(t)) { @@ -593,15 +685,20 @@ func archreloctoc(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r lo } o2 |= uint32(t) & 0xFFFC } + case objabi.R_ADDRPOWER_TOCREL: + o2 |= uint32(t) & 0xffff default: return -1 } - return int64(o1)<<32 | int64(o2) + if target.IsBigEndian() { + return int64(o1)<<32 | int64(o2) + } + return int64(o2)<<32 | int64(o1) } // archrelocaddr relocates a symbol address. -// This code is for AIX only. +// This code is for linux only. func archrelocaddr(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) int64 { rs := r.Sym() if target.IsAIX() { @@ -860,6 +957,18 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off())) + tgtName := ldr.SymName(rs) + + // If we are linking PIE or shared code, all golang generated object files have an extra 2 instruction prologue + // to regenerate the TOC pointer from R12. The exception are two special case functions tested below. Note, + // local call offsets for externally generated objects are accounted for when converting into golang relocs. + if !ldr.IsExternal(rs) && ldr.AttrShared(rs) && tgtName != "runtime.duffzero" && tgtName != "runtime.duffcopy" { + // Furthermore, only apply the offset if the target looks like the start of a function call. + if r.Add() == 0 && ldr.SymType(rs) == sym.STEXT { + t += 8 + } + } + if t&3 != 0 { ldr.Errorf(s, "relocation for %s+%d is not aligned: %d", ldr.SymName(rs), r.Off(), t) } @@ -872,6 +981,62 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade case objabi.R_POWER_TOC: // S + A - .TOC. return ldr.SymValue(rs) + r.Add() - symtoc(ldr, syms, s), nExtReloc, true + case objabi.R_ADDRPOWER_PCREL: // S + A - P + t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off())) + ha := uint16(((t + 0x8000) >> 16) & 0xFFFF) + l := uint16(t) + if target.IsBigEndian() { + val |= int64(l) + val |= int64(ha) << 32 + } else { + val |= int64(ha) + val |= int64(l) << 32 + } + return val, nExtReloc, true + + case objabi.R_POWER_TLS: + const OP_ADD = 31<<26 | 266<<1 + const MASK_OP_ADD = 0x3F<<26 | 0x1FF<<1 + if val&MASK_OP_ADD != OP_ADD { + ldr.Errorf(s, "R_POWER_TLS reloc only supports XO form ADD, not %08X", val) + } + // Verify RB is R13 in ADD RA,RB,RT. + if (val>>11)&0x1F != 13 { + // If external linking is made to support this, it may expect the linker to rewrite RB. + ldr.Errorf(s, "R_POWER_TLS reloc requires R13 in RB (%08X).", uint32(val)) + } + return val, nExtReloc, true + + case objabi.R_POWER_TLS_IE: + // Convert TLS_IE relocation to TLS_LE if supported. + if !(target.IsPIE() && target.IsElf()) { + log.Fatalf("cannot handle R_POWER_TLS_IE (sym %s) when linking non-PIE, non-ELF binaries internally", ldr.SymName(s)) + } + + // We are an ELF binary, we can safely convert to TLS_LE from: + // addis to, r2, x@got@tprel@ha + // ld to, to, x@got@tprel@l(to) + // + // to TLS_LE by converting to: + // addis to, r0, x@tprel@ha + // addi to, to, x@tprel@l(to) + + const OP_ADDI = 14 << 26 + const OP_MASK = 0x3F << 26 + const OP_RA_MASK = 0x1F << 16 + uval := uint64(val) + // convert r2 to r0, and ld to addi + if target.IsBigEndian() { + uval = uval &^ (OP_RA_MASK << 32) + uval = (uval &^ OP_MASK) | OP_ADDI + } else { + uval = uval &^ (OP_RA_MASK) + uval = (uval &^ (OP_MASK << 32)) | (OP_ADDI << 32) + } + val = int64(uval) + // Treat this like an R_POWER_TLS_LE relocation now. + fallthrough + case objabi.R_POWER_TLS_LE: // The thread pointer points 0x7000 bytes after the start of the // thread local storage area as documented in section "3.7.2 TLS diff --git a/src/debug/elf/elf.go b/src/debug/elf/elf.go index 9f8399d4d3..4c51bc4de2 100644 --- a/src/debug/elf/elf.go +++ b/src/debug/elf/elf.go @@ -2349,6 +2349,7 @@ const ( R_PPC64_GOT16_HI R_PPC64 = 16 // R_POWERPC_GOT16_HI R_PPC64_GOT16_HA R_PPC64 = 17 // R_POWERPC_GOT16_HA R_PPC64_JMP_SLOT R_PPC64 = 21 // R_POWERPC_JMP_SLOT + R_PPC64_RELATIVE R_PPC64 = 22 // R_POWERPC_RELATIVE R_PPC64_REL32 R_PPC64 = 26 // R_POWERPC_REL32 R_PPC64_ADDR64 R_PPC64 = 38 R_PPC64_ADDR16_HIGHER R_PPC64 = 39 @@ -2457,6 +2458,7 @@ var rppc64Strings = []intName{ {16, "R_PPC64_GOT16_HI"}, {17, "R_PPC64_GOT16_HA"}, {21, "R_PPC64_JMP_SLOT"}, + {22, "R_PPC64_RELATIVE"}, {26, "R_PPC64_REL32"}, {38, "R_PPC64_ADDR64"}, {39, "R_PPC64_ADDR16_HIGHER"}, -- GitLab From c353f1b41dc869210fda0cc0bd29d8587f1a5edf Mon Sep 17 00:00:00 2001 From: Lynn Boger Date: Fri, 5 Nov 2021 12:22:50 -0500 Subject: [PATCH 2001/2500] crypt/aes: update formatting of ppc64le asm comments This does not change any code, just reformats the comments in the asm code. Change-Id: I70fbfa77db164898d25b59b589d3e85b8399b0fc Reviewed-on: https://go-review.googlesource.com/c/go/+/361694 Reviewed-by: Cherry Mui Trust: Lynn Boger --- src/crypto/aes/asm_ppc64le.s | 795 +++++++++++++++++------------------ 1 file changed, 397 insertions(+), 398 deletions(-) diff --git a/src/crypto/aes/asm_ppc64le.s b/src/crypto/aes/asm_ppc64le.s index a69cb78c8b..f3a96a3a17 100644 --- a/src/crypto/aes/asm_ppc64le.s +++ b/src/crypto/aes/asm_ppc64le.s @@ -13,8 +13,8 @@ // Original code can be found at the link below: // https://github.com/dot-asm/cryptogams/blob/master/ppc/aesp8-ppc.pl -// I changed some function names in order to be more likely to go standards. -// For instance, function aes_p8_set_{en,de}crypt_key become +// Some function names were changed to be consistent with Go function +// names. For instance, function aes_p8_set_{en,de}crypt_key become // set{En,De}cryptKeyAsm. I also split setEncryptKeyAsm in two parts // and a new session was created (doEncryptKeyAsm). This was necessary to // avoid arguments overwriting when setDecryptKeyAsm calls setEncryptKeyAsm. @@ -50,452 +50,451 @@ #define BLK_ROUNDS R6 #define BLK_IDX R7 -DATA ·rcon+0x00(SB)/8, $0x0100000001000000 // RCON -DATA ·rcon+0x08(SB)/8, $0x0100000001000000 // RCON -DATA ·rcon+0x10(SB)/8, $0x1b0000001b000000 -DATA ·rcon+0x18(SB)/8, $0x1b0000001b000000 -DATA ·rcon+0x20(SB)/8, $0x0d0e0f0c0d0e0f0c // MASK -DATA ·rcon+0x28(SB)/8, $0x0d0e0f0c0d0e0f0c // MASK -DATA ·rcon+0x30(SB)/8, $0x0000000000000000 -DATA ·rcon+0x38(SB)/8, $0x0000000000000000 +DATA ·rcon+0x00(SB)/8, $0x0100000001000000 // RCON +DATA ·rcon+0x08(SB)/8, $0x0100000001000000 // RCON +DATA ·rcon+0x10(SB)/8, $0x1b0000001b000000 +DATA ·rcon+0x18(SB)/8, $0x1b0000001b000000 +DATA ·rcon+0x20(SB)/8, $0x0d0e0f0c0d0e0f0c // MASK +DATA ·rcon+0x28(SB)/8, $0x0d0e0f0c0d0e0f0c // MASK +DATA ·rcon+0x30(SB)/8, $0x0000000000000000 +DATA ·rcon+0x38(SB)/8, $0x0000000000000000 GLOBL ·rcon(SB), RODATA, $64 // func setEncryptKeyAsm(key *byte, keylen int, enc *uint32) int -TEXT ·setEncryptKeyAsm(SB),NOSPLIT|NOFRAME,$0 +TEXT ·setEncryptKeyAsm(SB), NOSPLIT|NOFRAME, $0 // Load the arguments inside the registers - MOVD key+0(FP), INP - MOVD keylen+8(FP), BITS - MOVD enc+16(FP), OUT - JMP ·doEncryptKeyAsm(SB) + MOVD key+0(FP), INP + MOVD keylen+8(FP), BITS + MOVD enc+16(FP), OUT + JMP ·doEncryptKeyAsm(SB) // This text is used both setEncryptKeyAsm and setDecryptKeyAsm -TEXT ·doEncryptKeyAsm(SB),NOSPLIT|NOFRAME,$0 +TEXT ·doEncryptKeyAsm(SB), NOSPLIT|NOFRAME, $0 // Do not change R10 since it's storing the LR value in setDecryptKeyAsm // Check arguments - MOVD $-1, PTR // li 6,-1 exit code to -1 (255) - CMPU INP, $0 // cmpldi r3,0 input key pointer set? - BC 0x0E, 2, enc_key_abort // beq- .Lenc_key_abort - CMPU OUT, $0 // cmpldi r5,0 output key pointer set? - BC 0x0E, 2, enc_key_abort // beq- .Lenc_key_abort - MOVD $-2, PTR // li 6,-2 exit code to -2 (254) - CMPW BITS, $128 // cmpwi 4,128 greater or equal to 128 - BC 0x0E, 0, enc_key_abort // blt- .Lenc_key_abort - CMPW BITS, $256 // cmpwi 4,256 lesser or equal to 256 - BC 0x0E, 1, enc_key_abort // bgt- .Lenc_key_abort - ANDCC $0x3f, BITS, TEMP // andi. 0,4,0x3f multiple of 64 - BC 0x06, 2, enc_key_abort // bne- .Lenc_key_abort - - MOVD $·rcon(SB), PTR // PTR point to rcon addr + MOVD $-1, PTR // li 6,-1 exit code to -1 (255) + CMPU INP, $0 // cmpldi r3,0 input key pointer set? + BC 0x0E, 2, enc_key_abort // beq- .Lenc_key_abort + CMPU OUT, $0 // cmpldi r5,0 output key pointer set? + BC 0x0E, 2, enc_key_abort // beq- .Lenc_key_abort + MOVD $-2, PTR // li 6,-2 exit code to -2 (254) + CMPW BITS, $128 // cmpwi 4,128 greater or equal to 128 + BC 0x0E, 0, enc_key_abort // blt- .Lenc_key_abort + CMPW BITS, $256 // cmpwi 4,256 lesser or equal to 256 + BC 0x0E, 1, enc_key_abort // bgt- .Lenc_key_abort + ANDCC $0x3f, BITS, TEMP // andi. 0,4,0x3f multiple of 64 + BC 0x06, 2, enc_key_abort // bne- .Lenc_key_abort + + MOVD $·rcon(SB), PTR // PTR point to rcon addr // Get key from memory and write aligned into VR - NEG INP, R9 // neg 9,3 R9 is ~INP + 1 - LVX (INP)(R0), IN0 // lvx 1,0,3 Load key inside IN0 - ADD $15, INP, INP // addi 3,3,15 Add 15B to INP addr - LVSR (R9)(R0), KEY // lvsr 3,0,9 - MOVD $0x20, R8 // li 8,0x20 R8 = 32 - CMPW BITS, $192 // cmpwi 4,192 Key size == 192? - LVX (INP)(R0), IN1 // lvx 2,0,3 - VSPLTISB $0x0f, MASK // vspltisb 5,0x0f 0x0f0f0f0f... mask - LVX (PTR)(R0), RCON // lvx 4,0,6 Load first 16 bytes into RCON - VXOR KEY, MASK, KEY // vxor 3,3,5 Adjust for byte swap - LVX (PTR)(R8), MASK // lvx 5,8,6 - ADD $0x10, PTR, PTR // addi 6,6,0x10 PTR to next 16 bytes of RCON - VPERM IN0, IN1, KEY, IN0 // vperm 1,1,2,3 Align - MOVD $8, CNT // li 7,8 CNT = 8 - VXOR ZERO, ZERO, ZERO // vxor 0,0,0 Zero to be zero :) - MOVD CNT, CTR // mtctr 7 Set the counter to 8 (rounds) - - LVSL (OUT)(R0), OUTPERM // lvsl 8,0,5 - VSPLTISB $-1, OUTMASK // vspltisb 9,-1 - LVX (OUT)(R0), OUTHEAD // lvx 10,0,5 - VPERM OUTMASK, ZERO, OUTPERM, OUTMASK // vperm 9,9,0,8 - - BLT loop128 // blt .Loop128 - ADD $8, INP, INP // addi 3,3,8 - BEQ l192 // beq .L192 - ADD $8, INP, INP // addi 3,3,8 - JMP l256 // b .L256 + NEG INP, R9 // neg 9,3 R9 is ~INP + 1 + LVX (INP)(R0), IN0 // lvx 1,0,3 Load key inside IN0 + ADD $15, INP, INP // addi 3,3,15 Add 15B to INP addr + LVSR (R9)(R0), KEY // lvsr 3,0,9 + MOVD $0x20, R8 // li 8,0x20 R8 = 32 + CMPW BITS, $192 // cmpwi 4,192 Key size == 192? + LVX (INP)(R0), IN1 // lvx 2,0,3 + VSPLTISB $0x0f, MASK// vspltisb 5,0x0f 0x0f0f0f0f... mask + LVX (PTR)(R0), RCON // lvx 4,0,6 Load first 16 bytes into RCON + VXOR KEY, MASK, KEY // vxor 3,3,5 Adjust for byte swap + LVX (PTR)(R8), MASK // lvx 5,8,6 + ADD $0x10, PTR, PTR // addi 6,6,0x10 PTR to next 16 bytes of RCON + VPERM IN0, IN1, KEY, IN0 // vperm 1,1,2,3 Align + MOVD $8, CNT // li 7,8 CNT = 8 + VXOR ZERO, ZERO, ZERO // vxor 0,0,0 Zero to be zero :) + MOVD CNT, CTR // mtctr 7 Set the counter to 8 (rounds) + + LVSL (OUT)(R0), OUTPERM // lvsl 8,0,5 + VSPLTISB $-1, OUTMASK // vspltisb 9,-1 + LVX (OUT)(R0), OUTHEAD // lvx 10,0,5 + VPERM OUTMASK, ZERO, OUTPERM, OUTMASK // vperm 9,9,0,8 + + BLT loop128 // blt .Loop128 + ADD $8, INP, INP // addi 3,3,8 + BEQ l192 // beq .L192 + ADD $8, INP, INP // addi 3,3,8 + JMP l256 // b .L256 loop128: // Key schedule (Round 1 to 8) - VPERM IN0, IN0, MASK, KEY // vperm 3,1,1,5 Rotate-n-splat - VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 - VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 Rotate - VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 - VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 - VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 - STVX STAGE, (OUT+R0) // stvx 7,0,5 Write to output - ADD $16, OUT, OUT // addi 5,5,16 Point to the next round - - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VADDUWM RCON, RCON, RCON // vadduwm 4,4,4 - VXOR IN0, KEY, IN0 // vxor 1,1,3 - BC 0x10, 0, loop128 // bdnz .Loop128 - - LVX (PTR)(R0), RCON // lvx 4,0,6 Last two round keys + VPERM IN0, IN0, MASK, KEY // vperm 3,1,1,5 Rotate-n-splat + VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 + VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 Rotate + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 + STVX STAGE, (OUT+R0) // stvx 7,0,5 Write to output + ADD $16, OUT, OUT // addi 5,5,16 Point to the next round + + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VADDUWM RCON, RCON, RCON // vadduwm 4,4,4 + VXOR IN0, KEY, IN0 // vxor 1,1,3 + BC 0x10, 0, loop128 // bdnz .Loop128 + + LVX (PTR)(R0), RCON // lvx 4,0,6 Last two round keys // Key schedule (Round 9) - VPERM IN0, IN0, MASK, KEY // vperm 3,1,1,5 Rotate-n-spat - VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 - VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 Rotate - VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 - VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 - VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 - STVX STAGE, (OUT+R0) // stvx 7,0,5 Round 9 - ADD $16, OUT, OUT // addi 5,5,16 + VPERM IN0, IN0, MASK, KEY // vperm 3,1,1,5 Rotate-n-spat + VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 + VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 Rotate + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 + STVX STAGE, (OUT+R0) // stvx 7,0,5 Round 9 + ADD $16, OUT, OUT // addi 5,5,16 // Key schedule (Round 10) - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VADDUWM RCON, RCON, RCON // vadduwm 4,4,4 - VXOR IN0, KEY, IN0 // vxor 1,1,3 - - VPERM IN0, IN0, MASK, KEY // vperm 3,1,1,5 Rotate-n-splat - VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 - VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 Rotate - VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 - VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 - VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 - STVX STAGE, (OUT+R0) // stvx 7,0,5 Round 10 - ADD $16, OUT, OUT // addi 5,5,16 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VADDUWM RCON, RCON, RCON // vadduwm 4,4,4 + VXOR IN0, KEY, IN0 // vxor 1,1,3 + + VPERM IN0, IN0, MASK, KEY // vperm 3,1,1,5 Rotate-n-splat + VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 + VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 Rotate + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 + STVX STAGE, (OUT+R0) // stvx 7,0,5 Round 10 + ADD $16, OUT, OUT // addi 5,5,16 // Key schedule (Round 11) - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VXOR IN0, KEY, IN0 // vxor 1,1,3 - VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 - VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 - VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 - STVX STAGE, (OUT+R0) // stvx 7,0,5 Round 11 - - ADD $15, OUT, INP // addi 3,5,15 - ADD $0x50, OUT, OUT // addi 5,5,0x50 - - MOVD $10, ROUNDS // li 8,10 - JMP done // b .Ldone + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VXOR IN0, KEY, IN0 // vxor 1,1,3 + VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + STVX STAGE, (OUT+R0) // stvx 7,0,5 Round 11 + + ADD $15, OUT, INP // addi 3,5,15 + ADD $0x50, OUT, OUT // addi 5,5,0x50 + + MOVD $10, ROUNDS // li 8,10 + JMP done // b .Ldone l192: - LVX (INP)(R0), TMP // lvx 6,0,3 - MOVD $4, CNT // li 7,4 - VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 - VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 - VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 - STVX STAGE, (OUT+R0) // stvx 7,0,5 - ADD $16, OUT, OUT // addi 5,5,16 - VPERM IN1, TMP, KEY, IN1 // vperm 2,2,6,3 - VSPLTISB $8, KEY // vspltisb 3,8 - MOVD CNT, CTR // mtctr 7 - VSUBUBM MASK, KEY, MASK // vsububm 5,5,3 + LVX (INP)(R0), TMP // lvx 6,0,3 + MOVD $4, CNT // li 7,4 + VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + STVX STAGE, (OUT+R0) // stvx 7,0,5 + ADD $16, OUT, OUT // addi 5,5,16 + VPERM IN1, TMP, KEY, IN1 // vperm 2,2,6,3 + VSPLTISB $8, KEY // vspltisb 3,8 + MOVD CNT, CTR // mtctr 7 + VSUBUBM MASK, KEY, MASK // vsububm 5,5,3 loop192: - VPERM IN1, IN1, MASK, KEY // vperm 3,2,2,5 - VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 - VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 - - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - - VSLDOI $8, ZERO, IN1, STAGE // vsldoi 7,0,2,8 - VSPLTW $3, IN0, TMP // vspltw 6,1,3 - VXOR TMP, IN1, TMP // vxor 6,6,2 - VSLDOI $12, ZERO, IN1, IN1 // vsldoi 2,0,2,12 - VADDUWM RCON, RCON, RCON // vadduwm 4,4,4 - VXOR IN1, TMP, IN1 // vxor 2,2,6 - VXOR IN0, KEY, IN0 // vxor 1,1,3 - VXOR IN1, KEY, IN1 // vxor 2,2,3 - VSLDOI $8, STAGE, IN0, STAGE // vsldoi 7,7,1,8 - - VPERM IN1, IN1, MASK, KEY // vperm 3,2,2,5 - VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 - VPERM STAGE, STAGE, OUTPERM, OUTTAIL // vperm 11,7,7,8 - VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 - VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 - VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 - STVX STAGE, (OUT+R0) // stvx 7,0,5 - ADD $16, OUT, OUT // addi 5,5,16 - - VSLDOI $8, IN0, IN1, STAGE // vsldoi 7,1,2,8 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VPERM STAGE, STAGE, OUTPERM, OUTTAIL // vperm 11,7,7,8 - VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 - VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - STVX STAGE, (OUT+R0) // stvx 7,0,5 - ADD $16, OUT, OUT // addi 5,5,16 - - VSPLTW $3, IN0, TMP // vspltw 6,1,3 - VXOR TMP, IN1, TMP // vxor 6,6,2 - VSLDOI $12, ZERO, IN1, IN1 // vsldoi 2,0,2,12 - VADDUWM RCON, RCON, RCON // vadduwm 4,4,4 - VXOR IN1, TMP, IN1 // vxor 2,2,6 - VXOR IN0, KEY, IN0 // vxor 1,1,3 - VXOR IN1, KEY, IN1 // vxor 2,2,3 - VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 - VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 - VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 - STVX STAGE, (OUT+R0) // stvx 7,0,5 - ADD $15, OUT, INP // addi 3,5,15 - ADD $16, OUT, OUT // addi 5,5,16 - BC 0x10, 0, loop192 // bdnz .Loop192 - - MOVD $12, ROUNDS // li 8,12 - ADD $0x20, OUT, OUT // addi 5,5,0x20 - JMP done // b .Ldone + VPERM IN1, IN1, MASK, KEY // vperm 3,2,2,5 + VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 + VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 + + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + + VSLDOI $8, ZERO, IN1, STAGE // vsldoi 7,0,2,8 + VSPLTW $3, IN0, TMP // vspltw 6,1,3 + VXOR TMP, IN1, TMP // vxor 6,6,2 + VSLDOI $12, ZERO, IN1, IN1 // vsldoi 2,0,2,12 + VADDUWM RCON, RCON, RCON // vadduwm 4,4,4 + VXOR IN1, TMP, IN1 // vxor 2,2,6 + VXOR IN0, KEY, IN0 // vxor 1,1,3 + VXOR IN1, KEY, IN1 // vxor 2,2,3 + VSLDOI $8, STAGE, IN0, STAGE // vsldoi 7,7,1,8 + + VPERM IN1, IN1, MASK, KEY // vperm 3,2,2,5 + VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 + VPERM STAGE, STAGE, OUTPERM, OUTTAIL // vperm 11,7,7,8 + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 + STVX STAGE, (OUT+R0) // stvx 7,0,5 + ADD $16, OUT, OUT // addi 5,5,16 + + VSLDOI $8, IN0, IN1, STAGE // vsldoi 7,1,2,8 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VPERM STAGE, STAGE, OUTPERM, OUTTAIL // vperm 11,7,7,8 + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + STVX STAGE, (OUT+R0) // stvx 7,0,5 + ADD $16, OUT, OUT // addi 5,5,16 + + VSPLTW $3, IN0, TMP // vspltw 6,1,3 + VXOR TMP, IN1, TMP // vxor 6,6,2 + VSLDOI $12, ZERO, IN1, IN1 // vsldoi 2,0,2,12 + VADDUWM RCON, RCON, RCON // vadduwm 4,4,4 + VXOR IN1, TMP, IN1 // vxor 2,2,6 + VXOR IN0, KEY, IN0 // vxor 1,1,3 + VXOR IN1, KEY, IN1 // vxor 2,2,3 + VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + STVX STAGE, (OUT+R0) // stvx 7,0,5 + ADD $15, OUT, INP // addi 3,5,15 + ADD $16, OUT, OUT // addi 5,5,16 + BC 0x10, 0, loop192 // bdnz .Loop192 + + MOVD $12, ROUNDS // li 8,12 + ADD $0x20, OUT, OUT // addi 5,5,0x20 + BR done // b .Ldone l256: - LVX (INP)(R0), TMP // lvx 6,0,3 - MOVD $7, CNT // li 7,7 - MOVD $14, ROUNDS // li 8,14 - VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 - VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 - VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 - STVX STAGE, (OUT+R0) // stvx 7,0,5 - ADD $16, OUT, OUT // addi 5,5,16 - VPERM IN1, TMP, KEY, IN1 // vperm 2,2,6,3 - MOVD CNT, CTR // mtctr 7 + LVX (INP)(R0), TMP // lvx 6,0,3 + MOVD $7, CNT // li 7,7 + MOVD $14, ROUNDS // li 8,14 + VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + STVX STAGE, (OUT+R0) // stvx 7,0,5 + ADD $16, OUT, OUT // addi 5,5,16 + VPERM IN1, TMP, KEY, IN1 // vperm 2,2,6,3 + MOVD CNT, CTR // mtctr 7 loop256: - VPERM IN1, IN1, MASK, KEY // vperm 3,2,2,5 - VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 - VPERM IN1, IN1, OUTPERM, OUTTAIL // vperm 11,2,2,8 - VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 - VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 - VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 - STVX STAGE, (OUT+R0) // stvx 7,0,5 - ADD $16, OUT, OUT // addi 5,5,16 - - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN0, TMP, IN0 // vxor 1,1,6 - VADDUWM RCON, RCON, RCON // vadduwm 4,4,4 - VXOR IN0, KEY, IN0 // vxor 1,1,3 - VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 - VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 - VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 - STVX STAGE, (OUT+R0) // stvx 7,0,5 - ADD $15, OUT, INP // addi 3,5,15 - ADD $16, OUT, OUT // addi 5,5,16 - BC 0x12, 0, done // bdz .Ldone - - VSPLTW $3, IN0, KEY // vspltw 3,1,3 - VSLDOI $12, ZERO, IN1, TMP // vsldoi 6,0,2,12 - VSBOX KEY, KEY // vsbox 3,3 - - VXOR IN1, TMP, IN1 // vxor 2,2,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN1, TMP, IN1 // vxor 2,2,6 - VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 - VXOR IN1, TMP, IN1 // vxor 2,2,6 - - VXOR IN1, KEY, IN1 // vxor 2,2,3 - JMP loop256 // b .Loop256 + VPERM IN1, IN1, MASK, KEY // vperm 3,2,2,5 + VSLDOI $12, ZERO, IN0, TMP // vsldoi 6,0,1,12 + VPERM IN1, IN1, OUTPERM, OUTTAIL // vperm 11,2,2,8 + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + VCIPHERLAST KEY, RCON, KEY // vcipherlast 3,3,4 + STVX STAGE, (OUT+R0) // stvx 7,0,5 + ADD $16, OUT, OUT // addi 5,5,16 + + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN0, TMP, IN0 // vxor 1,1,6 + VADDUWM RCON, RCON, RCON // vadduwm 4,4,4 + VXOR IN0, KEY, IN0 // vxor 1,1,3 + VPERM IN0, IN0, OUTPERM, OUTTAIL // vperm 11,1,1,8 + VSEL OUTHEAD, OUTTAIL, OUTMASK, STAGE // vsel 7,10,11,9 + VOR OUTTAIL, OUTTAIL, OUTHEAD // vor 10,11,11 + STVX STAGE, (OUT+R0) // stvx 7,0,5 + ADD $15, OUT, INP // addi 3,5,15 + ADD $16, OUT, OUT // addi 5,5,16 + BC 0x12, 0, done // bdz .Ldone + + VSPLTW $3, IN0, KEY // vspltw 3,1,3 + VSLDOI $12, ZERO, IN1, TMP // vsldoi 6,0,2,12 + VSBOX KEY, KEY // vsbox 3,3 + + VXOR IN1, TMP, IN1 // vxor 2,2,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN1, TMP, IN1 // vxor 2,2,6 + VSLDOI $12, ZERO, TMP, TMP // vsldoi 6,0,6,12 + VXOR IN1, TMP, IN1 // vxor 2,2,6 + + VXOR IN1, KEY, IN1 // vxor 2,2,3 + JMP loop256 // b .Loop256 done: - LVX (INP)(R0), IN1 // lvx 2,0,3 - VSEL OUTHEAD, IN1, OUTMASK, IN1 // vsel 2,10,2,9 - STVX IN1, (INP+R0) // stvx 2,0,3 - MOVD $0, PTR // li 6,0 set PTR to 0 (exit code 0) - MOVW ROUNDS, 0(OUT) // stw 8,0(5) + LVX (INP)(R0), IN1 // lvx 2,0,3 + VSEL OUTHEAD, IN1, OUTMASK, IN1 // vsel 2,10,2,9 + STVX IN1, (INP+R0) // stvx 2,0,3 + MOVD $0, PTR // li 6,0 set PTR to 0 (exit code 0) + MOVW ROUNDS, 0(OUT) // stw 8,0(5) enc_key_abort: - MOVD PTR, INP // mr 3,6 set exit code with PTR value - MOVD INP, ret+24(FP) // Put return value into the FP - RET // blr + MOVD PTR, INP // mr 3,6 set exit code with PTR value + MOVD INP, ret+24(FP) // Put return value into the FP + RET // blr // func setDecryptKeyAsm(key *byte, keylen int, dec *uint32) int -TEXT ·setDecryptKeyAsm(SB),NOSPLIT|NOFRAME,$0 +TEXT ·setDecryptKeyAsm(SB), NOSPLIT|NOFRAME, $0 // Load the arguments inside the registers - MOVD key+0(FP), INP - MOVD keylen+8(FP), BITS - MOVD dec+16(FP), OUT + MOVD key+0(FP), INP + MOVD keylen+8(FP), BITS + MOVD dec+16(FP), OUT - MOVD LR, R10 // mflr 10 - CALL ·doEncryptKeyAsm(SB) - MOVD R10, LR // mtlr 10 + MOVD LR, R10 // mflr 10 + CALL ·doEncryptKeyAsm(SB) + MOVD R10, LR // mtlr 10 - CMPW INP, $0 // cmpwi 3,0 exit 0 = ok - BC 0x06, 2, dec_key_abort // bne- .Ldec_key_abort + CMPW INP, $0 // cmpwi 3,0 exit 0 = ok + BC 0x06, 2, dec_key_abort // bne- .Ldec_key_abort // doEncryptKeyAsm set ROUNDS (R8) with the proper value for each mode - SLW $4, ROUNDS, CNT // slwi 7,8,4 - SUB $240, OUT, INP // subi 3,5,240 - SRW $1, ROUNDS, ROUNDS // srwi 8,8,1 - ADD R7, INP, OUT // add 5,3,7 - MOVD ROUNDS, CTR // mtctr 8 + SLW $4, ROUNDS, CNT // slwi 7,8,4 + SUB $240, OUT, INP // subi 3,5,240 + SRW $1, ROUNDS, ROUNDS // srwi 8,8,1 + ADD R7, INP, OUT // add 5,3,7 + MOVD ROUNDS, CTR // mtctr 8 -// dec_key will invert the key sequence in order to be used for decrypt + // dec_key will invert the key sequence in order to be used for decrypt dec_key: - MOVWZ 0(INP), TEMP // lwz 0, 0(3) - MOVWZ 4(INP), R6 // lwz 6, 4(3) - MOVWZ 8(INP), R7 // lwz 7, 8(3) - MOVWZ 12(INP), R8 // lwz 8, 12(3) - ADD $16, INP, INP // addi 3,3,16 - MOVWZ 0(OUT), R9 // lwz 9, 0(5) - MOVWZ 4(OUT), R10 // lwz 10,4(5) - MOVWZ 8(OUT), R11 // lwz 11,8(5) - MOVWZ 12(OUT), R12 // lwz 12,12(5) - MOVW TEMP, 0(OUT) // stw 0, 0(5) - MOVW R6, 4(OUT) // stw 6, 4(5) - MOVW R7, 8(OUT) // stw 7, 8(5) - MOVW R8, 12(OUT) // stw 8, 12(5) - SUB $16, OUT, OUT // subi 5,5,16 - MOVW R9, -16(INP) // stw 9, -16(3) - MOVW R10, -12(INP) // stw 10,-12(3) - MOVW R11, -8(INP) // stw 11,-8(3) - MOVW R12, -4(INP) // stw 12,-4(3) - BC 0x10, 0, dec_key // bdnz .Ldeckey - - XOR R3, R3, R3 // xor 3,3,3 Clean R3 + MOVWZ 0(INP), TEMP // lwz 0, 0(3) + MOVWZ 4(INP), R6 // lwz 6, 4(3) + MOVWZ 8(INP), R7 // lwz 7, 8(3) + MOVWZ 12(INP), R8 // lwz 8, 12(3) + ADD $16, INP, INP // addi 3,3,16 + MOVWZ 0(OUT), R9 // lwz 9, 0(5) + MOVWZ 4(OUT), R10 // lwz 10,4(5) + MOVWZ 8(OUT), R11 // lwz 11,8(5) + MOVWZ 12(OUT), R12 // lwz 12,12(5) + MOVW TEMP, 0(OUT) // stw 0, 0(5) + MOVW R6, 4(OUT) // stw 6, 4(5) + MOVW R7, 8(OUT) // stw 7, 8(5) + MOVW R8, 12(OUT) // stw 8, 12(5) + SUB $16, OUT, OUT // subi 5,5,16 + MOVW R9, -16(INP) // stw 9, -16(3) + MOVW R10, -12(INP) // stw 10,-12(3) + MOVW R11, -8(INP) // stw 11,-8(3) + MOVW R12, -4(INP) // stw 12,-4(3) + BC 0x10, 0, dec_key // bdnz .Ldeckey + + XOR R3, R3, R3 // xor 3,3,3 Clean R3 dec_key_abort: - MOVD R3, ret+24(FP) // Put return value into the FP - RET // blr - + MOVD R3, ret+24(FP) // Put return value into the FP + RET // blr // func encryptBlockAsm(dst, src *byte, enc *uint32) -TEXT ·encryptBlockAsm(SB),NOSPLIT|NOFRAME,$0 +TEXT ·encryptBlockAsm(SB), NOSPLIT|NOFRAME, $0 // Load the arguments inside the registers - MOVD dst+0(FP), BLK_OUT - MOVD src+8(FP), BLK_INP - MOVD enc+16(FP), BLK_KEY - - MOVWZ 240(BLK_KEY), BLK_ROUNDS // lwz 6,240(5) - MOVD $15, BLK_IDX // li 7,15 - - LVX (BLK_INP)(R0), ZERO // lvx 0,0,3 - NEG BLK_OUT, R11 // neg 11,4 - LVX (BLK_INP)(BLK_IDX), IN0 // lvx 1,7,3 - LVSL (BLK_INP)(R0), IN1 // lvsl 2,0,3 - VSPLTISB $0x0f, RCON // vspltisb 4,0x0f - LVSR (R11)(R0), KEY // lvsr 3,0,11 - VXOR IN1, RCON, IN1 // vxor 2,2,4 - MOVD $16, BLK_IDX // li 7,16 - VPERM ZERO, IN0, IN1, ZERO // vperm 0,0,1,2 - LVX (BLK_KEY)(R0), IN0 // lvx 1,0,5 - LVSR (BLK_KEY)(R0), MASK // lvsr 5,0,5 - SRW $1, BLK_ROUNDS, BLK_ROUNDS // srwi 6,6,1 - LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 - ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 - SUB $1, BLK_ROUNDS, BLK_ROUNDS // subi 6,6,1 - VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 - - VXOR ZERO, IN0, ZERO // vxor 0,0,1 - LVX (BLK_KEY)(BLK_IDX), IN0 // lvx 1,7,5 - ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 - MOVD BLK_ROUNDS, CTR // mtctr 6 + MOVD dst+0(FP), BLK_OUT + MOVD src+8(FP), BLK_INP + MOVD enc+16(FP), BLK_KEY + + MOVWZ 240(BLK_KEY), BLK_ROUNDS // lwz 6,240(5) + MOVD $15, BLK_IDX // li 7,15 + + LVX (BLK_INP)(R0), ZERO // lvx 0,0,3 + NEG BLK_OUT, R11 // neg 11,4 + LVX (BLK_INP)(BLK_IDX), IN0 // lvx 1,7,3 + LVSL (BLK_INP)(R0), IN1 // lvsl 2,0,3 + VSPLTISB $0x0f, RCON // vspltisb 4,0x0f + LVSR (R11)(R0), KEY // lvsr 3,0,11 + VXOR IN1, RCON, IN1 // vxor 2,2,4 + MOVD $16, BLK_IDX // li 7,16 + VPERM ZERO, IN0, IN1, ZERO // vperm 0,0,1,2 + LVX (BLK_KEY)(R0), IN0 // lvx 1,0,5 + LVSR (BLK_KEY)(R0), MASK // lvsr 5,0,5 + SRW $1, BLK_ROUNDS, BLK_ROUNDS // srwi 6,6,1 + LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 + ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 + SUB $1, BLK_ROUNDS, BLK_ROUNDS // subi 6,6,1 + VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 + + VXOR ZERO, IN0, ZERO // vxor 0,0,1 + LVX (BLK_KEY)(BLK_IDX), IN0 // lvx 1,7,5 + ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 + MOVD BLK_ROUNDS, CTR // mtctr 6 loop_enc: - VPERM IN0, IN1, MASK, IN1 // vperm 2,1,2,5 - VCIPHER ZERO, IN1, ZERO // vcipher 0,0,2 - LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 - ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 - VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 - VCIPHER ZERO, IN0, ZERO // vcipher 0,0,1 - LVX (BLK_KEY)(BLK_IDX), IN0 // lvx 1,7,5 - ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 - BC 0x10, 0, loop_enc // bdnz .Loop_enc - - VPERM IN0, IN1, MASK, IN1 // vperm 2,1,2,5 - VCIPHER ZERO, IN1, ZERO // vcipher 0,0,2 - LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 - VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 - VCIPHERLAST ZERO, IN0, ZERO // vcipherlast 0,0,1 - - VSPLTISB $-1, IN1 // vspltisb 2,-1 - VXOR IN0, IN0, IN0 // vxor 1,1,1 - MOVD $15, BLK_IDX // li 7,15 - VPERM IN1, IN0, KEY, IN1 // vperm 2,2,1,3 - VXOR KEY, RCON, KEY // vxor 3,3,4 - LVX (BLK_OUT)(R0), IN0 // lvx 1,0,4 - VPERM ZERO, ZERO, KEY, ZERO // vperm 0,0,0,3 - VSEL IN0, ZERO, IN1, IN0 // vsel 1,1,0,2 - LVX (BLK_OUT)(BLK_IDX), RCON // lvx 4,7,4 - STVX IN0, (BLK_OUT+R0) // stvx 1,0,4 - VSEL ZERO, RCON, IN1, ZERO // vsel 0,0,4,2 - STVX ZERO, (BLK_OUT+BLK_IDX) // stvx 0,7,4 - - RET // blr - + VPERM IN0, IN1, MASK, IN1 // vperm 2,1,2,5 + VCIPHER ZERO, IN1, ZERO // vcipher 0,0,2 + LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 + ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 + VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 + VCIPHER ZERO, IN0, ZERO // vcipher 0,0,1 + LVX (BLK_KEY)(BLK_IDX), IN0 // lvx 1,7,5 + ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 + BC 0x10, 0, loop_enc // bdnz .Loop_enc + + VPERM IN0, IN1, MASK, IN1 // vperm 2,1,2,5 + VCIPHER ZERO, IN1, ZERO // vcipher 0,0,2 + LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 + VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 + VCIPHERLAST ZERO, IN0, ZERO // vcipherlast 0,0,1 + + VSPLTISB $-1, IN1 // vspltisb 2,-1 + VXOR IN0, IN0, IN0 // vxor 1,1,1 + MOVD $15, BLK_IDX // li 7,15 + VPERM IN1, IN0, KEY, IN1 // vperm 2,2,1,3 + VXOR KEY, RCON, KEY // vxor 3,3,4 + LVX (BLK_OUT)(R0), IN0 // lvx 1,0,4 + VPERM ZERO, ZERO, KEY, ZERO // vperm 0,0,0,3 + VSEL IN0, ZERO, IN1, IN0 // vsel 1,1,0,2 + LVX (BLK_OUT)(BLK_IDX), RCON // lvx 4,7,4 + STVX IN0, (BLK_OUT+R0) // stvx 1,0,4 + VSEL ZERO, RCON, IN1, ZERO // vsel 0,0,4,2 + STVX ZERO, (BLK_OUT+BLK_IDX) // stvx 0,7,4 + + RET // blr // func decryptBlockAsm(dst, src *byte, dec *uint32) -TEXT ·decryptBlockAsm(SB),NOSPLIT|NOFRAME,$0 +TEXT ·decryptBlockAsm(SB), NOSPLIT|NOFRAME, $0 // Load the arguments inside the registers - MOVD dst+0(FP), BLK_OUT - MOVD src+8(FP), BLK_INP - MOVD dec+16(FP), BLK_KEY - - MOVWZ 240(BLK_KEY), BLK_ROUNDS // lwz 6,240(5) - MOVD $15, BLK_IDX // li 7,15 - - LVX (BLK_INP)(R0), ZERO // lvx 0,0,3 - NEG BLK_OUT, R11 // neg 11,4 - LVX (BLK_INP)(BLK_IDX), IN0 // lvx 1,7,3 - LVSL (BLK_INP)(R0), IN1 // lvsl 2,0,3 - VSPLTISB $0x0f, RCON // vspltisb 4,0x0f - LVSR (R11)(R0), KEY // lvsr 3,0,11 - VXOR IN1, RCON, IN1 // vxor 2,2,4 - MOVD $16, BLK_IDX // li 7,16 - VPERM ZERO, IN0, IN1, ZERO // vperm 0,0,1,2 - LVX (BLK_KEY)(R0), IN0 // lvx 1,0,5 - LVSR (BLK_KEY)(R0), MASK // lvsr 5,0,5 - SRW $1, BLK_ROUNDS, BLK_ROUNDS // srwi 6,6,1 - LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 - ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 - SUB $1, BLK_ROUNDS, BLK_ROUNDS // subi 6,6,1 - VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 - - VXOR ZERO, IN0, ZERO // vxor 0,0,1 - LVX (BLK_KEY)(BLK_IDX), IN0 // lvx 1,7,5 - ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 - MOVD BLK_ROUNDS, CTR // mtctr 6 + MOVD dst+0(FP), BLK_OUT + MOVD src+8(FP), BLK_INP + MOVD dec+16(FP), BLK_KEY + + MOVWZ 240(BLK_KEY), BLK_ROUNDS // lwz 6,240(5) + MOVD $15, BLK_IDX // li 7,15 + + LVX (BLK_INP)(R0), ZERO // lvx 0,0,3 + NEG BLK_OUT, R11 // neg 11,4 + LVX (BLK_INP)(BLK_IDX), IN0 // lvx 1,7,3 + LVSL (BLK_INP)(R0), IN1 // lvsl 2,0,3 + VSPLTISB $0x0f, RCON // vspltisb 4,0x0f + LVSR (R11)(R0), KEY // lvsr 3,0,11 + VXOR IN1, RCON, IN1 // vxor 2,2,4 + MOVD $16, BLK_IDX // li 7,16 + VPERM ZERO, IN0, IN1, ZERO // vperm 0,0,1,2 + LVX (BLK_KEY)(R0), IN0 // lvx 1,0,5 + LVSR (BLK_KEY)(R0), MASK // lvsr 5,0,5 + SRW $1, BLK_ROUNDS, BLK_ROUNDS // srwi 6,6,1 + LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 + ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 + SUB $1, BLK_ROUNDS, BLK_ROUNDS // subi 6,6,1 + VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 + + VXOR ZERO, IN0, ZERO // vxor 0,0,1 + LVX (BLK_KEY)(BLK_IDX), IN0 // lvx 1,7,5 + ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 + MOVD BLK_ROUNDS, CTR // mtctr 6 loop_dec: - VPERM IN0, IN1, MASK, IN1 // vperm 2,1,2,5 - VNCIPHER ZERO, IN1, ZERO // vncipher 0,0,2 - LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 - ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 - VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 - VNCIPHER ZERO, IN0, ZERO // vncipher 0,0,1 - LVX (BLK_KEY)(BLK_IDX), IN0 // lvx 1,7,5 - ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 - BC 0x10, 0, loop_dec // bdnz .Loop_dec - - VPERM IN0, IN1, MASK, IN1 // vperm 2,1,2,5 - VNCIPHER ZERO, IN1, ZERO // vncipher 0,0,2 - LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 - VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 - VNCIPHERLAST ZERO, IN0, ZERO // vncipherlast 0,0,1 - - VSPLTISB $-1, IN1 // vspltisb 2,-1 - VXOR IN0, IN0, IN0 // vxor 1,1,1 - MOVD $15, BLK_IDX // li 7,15 - VPERM IN1, IN0, KEY, IN1 // vperm 2,2,1,3 - VXOR KEY, RCON, KEY // vxor 3,3,4 - LVX (BLK_OUT)(R0), IN0 // lvx 1,0,4 - VPERM ZERO, ZERO, KEY, ZERO // vperm 0,0,0,3 - VSEL IN0, ZERO, IN1, IN0 // vsel 1,1,0,2 - LVX (BLK_OUT)(BLK_IDX), RCON // lvx 4,7,4 - STVX IN0, (BLK_OUT+R0) // stvx 1,0,4 - VSEL ZERO, RCON, IN1, ZERO // vsel 0,0,4,2 - STVX ZERO, (BLK_OUT+BLK_IDX) // stvx 0,7,4 - - RET // blr + VPERM IN0, IN1, MASK, IN1 // vperm 2,1,2,5 + VNCIPHER ZERO, IN1, ZERO // vncipher 0,0,2 + LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 + ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 + VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 + VNCIPHER ZERO, IN0, ZERO // vncipher 0,0,1 + LVX (BLK_KEY)(BLK_IDX), IN0 // lvx 1,7,5 + ADD $16, BLK_IDX, BLK_IDX // addi 7,7,16 + BC 0x10, 0, loop_dec // bdnz .Loop_dec + + VPERM IN0, IN1, MASK, IN1 // vperm 2,1,2,5 + VNCIPHER ZERO, IN1, ZERO // vncipher 0,0,2 + LVX (BLK_KEY)(BLK_IDX), IN1 // lvx 2,7,5 + VPERM IN1, IN0, MASK, IN0 // vperm 1,2,1,5 + VNCIPHERLAST ZERO, IN0, ZERO // vncipherlast 0,0,1 + + VSPLTISB $-1, IN1 // vspltisb 2,-1 + VXOR IN0, IN0, IN0 // vxor 1,1,1 + MOVD $15, BLK_IDX // li 7,15 + VPERM IN1, IN0, KEY, IN1 // vperm 2,2,1,3 + VXOR KEY, RCON, KEY // vxor 3,3,4 + LVX (BLK_OUT)(R0), IN0 // lvx 1,0,4 + VPERM ZERO, ZERO, KEY, ZERO // vperm 0,0,0,3 + VSEL IN0, ZERO, IN1, IN0 // vsel 1,1,0,2 + LVX (BLK_OUT)(BLK_IDX), RCON // lvx 4,7,4 + STVX IN0, (BLK_OUT+R0) // stvx 1,0,4 + VSEL ZERO, RCON, IN1, ZERO // vsel 0,0,4,2 + STVX ZERO, (BLK_OUT+BLK_IDX) // stvx 0,7,4 + + RET // blr + -- GitLab From 7be227ccd0213dd10d831f87c133bc8ac2cbdc73 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 5 Nov 2021 15:38:57 -0400 Subject: [PATCH 2002/2500] cmd/go: don't assume case-insensitivity in TestScript/gcflags_patterns For #30432 Change-Id: I84f208705483018559b425b3669e724e7d5627ee Reviewed-on: https://go-review.googlesource.com/c/go/+/361814 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/cmd/go/testdata/script/gcflags_patterns.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cmd/go/testdata/script/gcflags_patterns.txt b/src/cmd/go/testdata/script/gcflags_patterns.txt index 5b81e9481a..24ec5aa11b 100644 --- a/src/cmd/go/testdata/script/gcflags_patterns.txt +++ b/src/cmd/go/testdata/script/gcflags_patterns.txt @@ -58,8 +58,7 @@ go build -n -ldflags=-X=math.pi=3 stderr 'link.* -X=math.pi=3' # -ldflags applies to current directory even if GOPATH is funny -[windows] cd $WORK/GoPath/src/my/cmd/prog -[darwin] cd $WORK/GoPath/src/my/cmd/prog +[!case-sensitive] cd $WORK/GoPath/src/my/cmd/prog go build -n -ldflags=-X=math.pi=3 stderr 'link.* -X=math.pi=3' -- GitLab From 71559a6ffd26031fe562b461d6472fdddbe617eb Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 5 Nov 2021 15:58:34 -0400 Subject: [PATCH 2003/2500] runtime: fix racy stackForceMove check Currently, newstack loads gp.stackguard0 twice to check for different poison values. The race window between these two checks can lead to unintentional stack doubling, and ultimately to stack overflows. Specifically, newstack checks if stackguard0 is stackPreempt first, then it checks if it's stackForceMove. If stackguard0 is set to stackForceMove on entry, but changes to stackPreempt between the two checks, newstack will incorrectly double the stack allocation. Fix this by loading stackguard0 exactly once and then checking it against different poison values. The effect of this is relatively minor because stackForceMove is only used by a small number of runtime tests. I found this because mayMorestackMove uses stackForceMove aggressively, which makes this failure mode much more likely. Change-Id: I1f8b6a6744e45533580a3f45d7030ec2ec65a5fb Reviewed-on: https://go-review.googlesource.com/c/go/+/361775 Trust: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot Reviewed-by: Cherry Mui Reviewed-by: Michael Pratt --- src/runtime/stack.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/runtime/stack.go b/src/runtime/stack.go index 7d9ae1e9d2..25a6f5bbb4 100644 --- a/src/runtime/stack.go +++ b/src/runtime/stack.go @@ -1002,7 +1002,7 @@ func newstack() { // NOTE: stackguard0 may change underfoot, if another thread // is about to try to preempt gp. Read it just once and use that same // value now and below. - preempt := atomic.Loaduintptr(&gp.stackguard0) == stackPreempt + stackguard0 := atomic.Loaduintptr(&gp.stackguard0) // Be conservative about where we preempt. // We are interested in preempting user Go code, not runtime code. @@ -1016,6 +1016,7 @@ func newstack() { // If the GC is in some way dependent on this goroutine (for example, // it needs a lock held by the goroutine), that small preemption turns // into a real deadlock. + preempt := stackguard0 == stackPreempt if preempt { if !canPreemptM(thisg.m) { // Let the goroutine keep running for now. @@ -1083,7 +1084,7 @@ func newstack() { } } - if gp.stackguard0 == stackForceMove { + if stackguard0 == stackForceMove { // Forced stack movement used for debugging. // Don't double the stack (or we may quickly run out // if this is done repeatedly). -- GitLab From dbd3cf884986c88f5b3350709c0f51fa02330805 Mon Sep 17 00:00:00 2001 From: Keiichi Hirobe Date: Sun, 29 Aug 2021 02:38:38 +0900 Subject: [PATCH 2004/2500] net/http: fix comment of writeRequest Change-Id: I5ebfc6a89323cc086ea0e0b619370dc45da1f3a3 Reviewed-on: https://go-review.googlesource.com/c/go/+/345437 Reviewed-by: Damien Neil Trust: Damien Neil Trust: Ian Lance Taylor Run-TryBot: Damien Neil TryBot-Result: Go Bot --- src/net/http/transport.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/http/transport.go b/src/net/http/transport.go index 05a1659136..f2d2f79280 100644 --- a/src/net/http/transport.go +++ b/src/net/http/transport.go @@ -2481,7 +2481,7 @@ type requestAndChan struct { callerGone <-chan struct{} // closed when roundTrip caller has returned } -// A writeRequest is sent by the readLoop's goroutine to the +// A writeRequest is sent by the caller's goroutine to the // writeLoop's goroutine to write a request while the read loop // concurrently waits on both the write response and the server's // reply. -- GitLab From 091948a55fb198be4202c21a5809ec68d77f70c4 Mon Sep 17 00:00:00 2001 From: zhouguangyuan Date: Wed, 3 Nov 2021 22:23:29 +0800 Subject: [PATCH 2005/2500] time: make Ticker.Reset(0) panic Fixes #49315 Change-Id: I0887bad1059b25ae0749bfa1ed6ddccbecca7951 Reviewed-on: https://go-review.googlesource.com/c/go/+/361074 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Reviewed-by: Emmanuel Odeke --- src/time/tick.go | 6 +++++- src/time/tick_test.go | 11 +++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/time/tick.go b/src/time/tick.go index f9522b0b75..babf865aeb 100644 --- a/src/time/tick.go +++ b/src/time/tick.go @@ -48,8 +48,12 @@ func (t *Ticker) Stop() { } // Reset stops a ticker and resets its period to the specified duration. -// The next tick will arrive after the new period elapses. +// The next tick will arrive after the new period elapses. The duration d +// must be greater than zero; if not, Reset will panic. func (t *Ticker) Reset(d Duration) { + if d <= 0 { + panic("non-positive interval for Ticker.Reset") + } if t.r.f == nil { panic("time: Reset called on uninitialized Ticker") } diff --git a/src/time/tick_test.go b/src/time/tick_test.go index d8cd59228f..f539091869 100644 --- a/src/time/tick_test.go +++ b/src/time/tick_test.go @@ -134,6 +134,17 @@ func TestNewTickerLtZeroDuration(t *testing.T) { NewTicker(-1) } +// Test that Ticker.Reset panics when given a duration less than zero. +func TestTickerResetLtZeroDuration(t *testing.T) { + defer func() { + if err := recover(); err == nil { + t.Errorf("Ticker.Reset(0) should have panicked") + } + }() + tk := NewTicker(Second) + tk.Reset(0) +} + func BenchmarkTicker(b *testing.B) { benchmark(b, func(n int) { ticker := NewTicker(Nanosecond) -- GitLab From 4c7cafdd03426bc2b9fb1275d13d0abc755dde16 Mon Sep 17 00:00:00 2001 From: Charlie Getzen Date: Fri, 5 Nov 2021 17:27:35 +0000 Subject: [PATCH 2006/2500] net/http: distinguish between timeouts and client hangups in TimeoutHandler Fixes #48948 Change-Id: I411e3be99c7979ae289fd937388aae63d81adb59 GitHub-Last-Rev: 14abd7e4d774ed5ef63aa0a69e80fbc8b5a5af26 GitHub-Pull-Request: golang/go#48993 Reviewed-on: https://go-review.googlesource.com/c/go/+/356009 Reviewed-by: Damien Neil Trust: Damien Neil Trust: Ian Lance Taylor Run-TryBot: Damien Neil TryBot-Result: Go Bot --- src/net/http/export_test.go | 7 +---- src/net/http/serve_test.go | 63 +++++++++++++++++++++++++++++++++---- src/net/http/server.go | 20 +++++++----- 3 files changed, 71 insertions(+), 19 deletions(-) diff --git a/src/net/http/export_test.go b/src/net/http/export_test.go index 096a6d382a..a849327f45 100644 --- a/src/net/http/export_test.go +++ b/src/net/http/export_test.go @@ -88,12 +88,7 @@ func SetPendingDialHooks(before, after func()) { func SetTestHookServerServe(fn func(*Server, net.Listener)) { testHookServerServe = fn } -func NewTestTimeoutHandler(handler Handler, ch <-chan time.Time) Handler { - ctx, cancel := context.WithCancel(context.Background()) - go func() { - <-ch - cancel() - }() +func NewTestTimeoutHandler(handler Handler, ctx context.Context) Handler { return &timeoutHandler{ handler: handler, testContext: ctx, diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index a98d6c313f..e8fb77446c 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -2274,6 +2274,18 @@ func TestRequestBodyTimeoutClosesConnection(t *testing.T) { } } +// cancelableTimeoutContext overwrites the error message to DeadlineExceeded +type cancelableTimeoutContext struct { + context.Context +} + +func (c cancelableTimeoutContext) Err() error { + if c.Context.Err() != nil { + return context.DeadlineExceeded + } + return nil +} + func TestTimeoutHandler_h1(t *testing.T) { testTimeoutHandler(t, h1Mode) } func TestTimeoutHandler_h2(t *testing.T) { testTimeoutHandler(t, h2Mode) } func testTimeoutHandler(t *testing.T, h2 bool) { @@ -2286,8 +2298,9 @@ func testTimeoutHandler(t *testing.T, h2 bool) { _, werr := w.Write([]byte("hi")) writeErrors <- werr }) - timeout := make(chan time.Time, 1) // write to this to force timeouts - cst := newClientServerTest(t, h2, NewTestTimeoutHandler(sayHi, timeout)) + ctx, cancel := context.WithCancel(context.Background()) + h := NewTestTimeoutHandler(sayHi, cancelableTimeoutContext{ctx}) + cst := newClientServerTest(t, h2, h) defer cst.close() // Succeed without timing out: @@ -2308,7 +2321,8 @@ func testTimeoutHandler(t *testing.T, h2 bool) { } // Times out: - timeout <- time.Time{} + cancel() + res, err = cst.c.Get(cst.ts.URL) if err != nil { t.Error(err) @@ -2429,8 +2443,9 @@ func TestTimeoutHandlerRaceHeaderTimeout(t *testing.T) { _, werr := w.Write([]byte("hi")) writeErrors <- werr }) - timeout := make(chan time.Time, 1) // write to this to force timeouts - cst := newClientServerTest(t, h1Mode, NewTestTimeoutHandler(sayHi, timeout)) + ctx, cancel := context.WithCancel(context.Background()) + h := NewTestTimeoutHandler(sayHi, cancelableTimeoutContext{ctx}) + cst := newClientServerTest(t, h1Mode, h) defer cst.close() // Succeed without timing out: @@ -2451,7 +2466,8 @@ func TestTimeoutHandlerRaceHeaderTimeout(t *testing.T) { } // Times out: - timeout <- time.Time{} + cancel() + res, err = cst.c.Get(cst.ts.URL) if err != nil { t.Error(err) @@ -2501,6 +2517,41 @@ func TestTimeoutHandlerStartTimerWhenServing(t *testing.T) { } } +func TestTimeoutHandlerContextCanceled(t *testing.T) { + setParallel(t) + defer afterTest(t) + sendHi := make(chan bool, 1) + writeErrors := make(chan error, 1) + sayHi := HandlerFunc(func(w ResponseWriter, r *Request) { + w.Header().Set("Content-Type", "text/plain") + <-sendHi + _, werr := w.Write([]byte("hi")) + writeErrors <- werr + }) + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Hour) + h := NewTestTimeoutHandler(sayHi, ctx) + cancel() + cst := newClientServerTest(t, h1Mode, h) + defer cst.close() + + // Succeed without timing out: + sendHi <- true + res, err := cst.c.Get(cst.ts.URL) + if err != nil { + t.Error(err) + } + if g, e := res.StatusCode, StatusServiceUnavailable; g != e { + t.Errorf("got res.StatusCode %d; expected %d", g, e) + } + body, _ := io.ReadAll(res.Body) + if g, e := string(body), ""; g != e { + t.Errorf("got body %q; expected %q", g, e) + } + if g, e := <-writeErrors, context.Canceled; g != e { + t.Errorf("got unexpected Write error on first request: %v", g) + } +} + // https://golang.org/issue/15948 func TestTimeoutHandlerEmptyResponse(t *testing.T) { setParallel(t) diff --git a/src/net/http/server.go b/src/net/http/server.go index 91fad68694..08fd478ed9 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -3391,9 +3391,15 @@ func (h *timeoutHandler) ServeHTTP(w ResponseWriter, r *Request) { case <-ctx.Done(): tw.mu.Lock() defer tw.mu.Unlock() - w.WriteHeader(StatusServiceUnavailable) - io.WriteString(w, h.errorBody()) - tw.timedOut = true + switch err := ctx.Err(); err { + case context.DeadlineExceeded: + w.WriteHeader(StatusServiceUnavailable) + io.WriteString(w, h.errorBody()) + tw.err = ErrHandlerTimeout + default: + w.WriteHeader(StatusServiceUnavailable) + tw.err = err + } } } @@ -3404,7 +3410,7 @@ type timeoutWriter struct { req *Request mu sync.Mutex - timedOut bool + err error wroteHeader bool code int } @@ -3424,8 +3430,8 @@ func (tw *timeoutWriter) Header() Header { return tw.h } func (tw *timeoutWriter) Write(p []byte) (int, error) { tw.mu.Lock() defer tw.mu.Unlock() - if tw.timedOut { - return 0, ErrHandlerTimeout + if tw.err != nil { + return 0, tw.err } if !tw.wroteHeader { tw.writeHeaderLocked(StatusOK) @@ -3437,7 +3443,7 @@ func (tw *timeoutWriter) writeHeaderLocked(code int) { checkWriteHeaderCode(code) switch { - case tw.timedOut: + case tw.err != nil: return case tw.wroteHeader: if tw.req != nil { -- GitLab From 3e9e02412e7770e46c7e725e17dee09a7d79f32c Mon Sep 17 00:00:00 2001 From: jiahua wang Date: Tue, 12 Oct 2021 14:27:02 +0800 Subject: [PATCH 2007/2500] bytes: add example with (*Buffer).Cap, (*Buffer).Read, (*Buffer).ReadByte Change-Id: Ieb107fdfccde9f054491f667a384b16f7af71dea Reviewed-on: https://go-review.googlesource.com/c/go/+/355289 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Cherry Mui --- src/bytes/example_test.go | 43 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/bytes/example_test.go b/src/bytes/example_test.go index d04b088fab..54a7aa6ae6 100644 --- a/src/bytes/example_test.go +++ b/src/bytes/example_test.go @@ -37,6 +37,16 @@ func ExampleBuffer_Bytes() { // Output: hello world } +func ExampleBuffer_Cap() { + buf1 := bytes.NewBuffer(make([]byte, 10)) + buf2 := bytes.NewBuffer(make([]byte, 0, 10)) + fmt.Println(buf1.Cap()) + fmt.Println(buf2.Cap()) + // Output: + // 10 + // 10 +} + func ExampleBuffer_Grow() { var b bytes.Buffer b.Grow(64) @@ -67,6 +77,39 @@ func ExampleBuffer_Next() { // e } +func ExampleBuffer_Read() { + var b bytes.Buffer + b.Grow(64) + b.Write([]byte("abcde")) + rdbuf := make([]byte, 1) + n, err := b.Read(rdbuf) + if err != nil { + panic(err) + } + fmt.Println(n) + fmt.Println(b.String()) + fmt.Println(string(rdbuf)) + // Output + // 1 + // bcde + // a +} + +func ExampleBuffer_ReadByte() { + var b bytes.Buffer + b.Grow(64) + b.Write([]byte("abcde")) + c, err := b.ReadByte() + if err != nil { + panic(err) + } + fmt.Println(c) + fmt.Println(b.String()) + // Output + // 97 + // bcde +} + func ExampleCompare() { // Interpret Compare's result by comparing it to zero. var a, b []byte -- GitLab From 58ec92527041f88d427390a92619cd9a927b6aba Mon Sep 17 00:00:00 2001 From: Dan Kortschak Date: Sun, 29 Aug 2021 14:01:03 +0930 Subject: [PATCH 2008/2500] debug/plan9obj: export ErrNoSymbols This allows callers of *File.Symbols to distinguish absence of symbols from other errors as can already by done in debug/elf. Fixes #48052 Change-Id: I5ba15d8473911e516c016a69c1f1c710f7fc4cd5 Reviewed-on: https://go-review.googlesource.com/c/go/+/350229 Run-TryBot: Ian Lance Taylor Reviewed-by: Ian Lance Taylor Reviewed-by: Cherry Mui --- src/debug/plan9obj/file.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/debug/plan9obj/file.go b/src/debug/plan9obj/file.go index 314608da61..c054635148 100644 --- a/src/debug/plan9obj/file.go +++ b/src/debug/plan9obj/file.go @@ -301,11 +301,15 @@ func newTable(symtab []byte, ptrsz int) ([]Sym, error) { return syms, nil } +// ErrNoSymbols is returned by File.Symbols if there is no such section +// in the File. +var ErrNoSymbols = errors.New("no symbol section") + // Symbols returns the symbol table for f. func (f *File) Symbols() ([]Sym, error) { symtabSection := f.Section("syms") if symtabSection == nil { - return nil, errors.New("no symbol section") + return nil, ErrNoSymbols } symtab, err := symtabSection.Data() -- GitLab From 7aed6dd7e18e2ad3ac0f4eb692188ed7a90b778b Mon Sep 17 00:00:00 2001 From: smasher164 Date: Thu, 28 Oct 2021 17:08:22 -0400 Subject: [PATCH 2009/2500] strings, bytes: deprecate Title Title doesn't handle Unicode punctuation and language-specific capitalization rules. Replace the BUG comment with a Deprecated one, suggesting a more robust alternative, and allowing Title to be exposed to tooling. Fixes #48367. Change-Id: I952f1f37cd35b587a95893fb022827bdd9ec7de9 Reviewed-on: https://go-review.googlesource.com/c/go/+/359485 Reviewed-by: Ian Lance Taylor Trust: Cherry Mui --- src/bytes/bytes.go | 3 ++- src/strings/strings.go | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/bytes/bytes.go b/src/bytes/bytes.go index 9e6b68eaf4..6fdaa49c73 100644 --- a/src/bytes/bytes.go +++ b/src/bytes/bytes.go @@ -746,7 +746,8 @@ func isSeparator(r rune) bool { // Title treats s as UTF-8-encoded bytes and returns a copy with all Unicode letters that begin // words mapped to their title case. // -// BUG(rsc): The rule Title uses for word boundaries does not handle Unicode punctuation properly. +// Deprecated: The rule Title uses for word boundaries does not handle Unicode +// punctuation properly. Use golang.org/x/text/cases instead. func Title(s []byte) []byte { // Use a closure here to remember state. // Hackish but effective. Depends on Map scanning in order and calling diff --git a/src/strings/strings.go b/src/strings/strings.go index bc734048c3..c5a29e95f6 100644 --- a/src/strings/strings.go +++ b/src/strings/strings.go @@ -706,7 +706,8 @@ func isSeparator(r rune) bool { // Title returns a copy of the string s with all Unicode letters that begin words // mapped to their Unicode title case. // -// BUG(rsc): The rule Title uses for word boundaries does not handle Unicode punctuation properly. +// Deprecated: The rule Title uses for word boundaries does not handle Unicode +// punctuation properly. Use golang.org/x/text/cases instead. func Title(s string) string { // Use a closure here to remember state. // Hackish but effective. Depends on Map scanning in order and calling -- GitLab From ad6ce55a55ec445ac946e825532bde5784f8d72b Mon Sep 17 00:00:00 2001 From: jiahua wang Date: Wed, 20 Oct 2021 15:21:46 +0800 Subject: [PATCH 2010/2500] time: add some examples Change-Id: I2668cdea64f75bee87d424730d404834d69362a8 Reviewed-on: https://go-review.googlesource.com/c/go/+/357270 Reviewed-by: Ian Lance Taylor Trust: Cherry Mui --- src/time/example_test.go | 50 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/time/example_test.go b/src/time/example_test.go index 0afb18aba6..ec2259b1ba 100644 --- a/src/time/example_test.go +++ b/src/time/example_test.go @@ -344,6 +344,23 @@ func ExampleTime_Format_pad() { } +func ExampleTime_GoString() { + t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) + fmt.Println(t.GoString()) + t = t.Add(1 * time.Minute) + fmt.Println(t.GoString()) + t = t.AddDate(0, 1, 0) + fmt.Println(t.GoString()) + t, _ = time.Parse("Jan 2, 2006 at 3:04pm (MST)", "Feb 3, 2013 at 7:54pm (UTC)") + fmt.Println(t.GoString()) + + // Output: + // time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) + // time.Date(2009, time.November, 10, 23, 1, 0, 0, time.UTC) + // time.Date(2009, time.December, 10, 23, 1, 0, 0, time.UTC) + // time.Date(2013, time.February, 3, 19, 54, 0, 0, time.UTC) +} + func ExampleParse() { // See the example for Time.Format for a thorough description of how // to define the layout string to parse a time.Time value; Parse and @@ -401,6 +418,39 @@ func ExampleParseInLocation() { // 2012-07-09 00:00:00 +0200 CEST } +func ExampleUnix() { + unixTime := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) + fmt.Println(unixTime.Unix()) + t := time.Unix(unixTime.Unix(), 0).UTC() + fmt.Println(t) + + // Output: + // 1257894000 + // 2009-11-10 23:00:00 +0000 UTC +} + +func ExampleUnixMicro() { + umt := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) + fmt.Println(umt.UnixMicro()) + t := time.UnixMicro(umt.UnixMicro()).UTC() + fmt.Println(t) + + // Output: + // 1257894000000000 + // 2009-11-10 23:00:00 +0000 UTC +} + +func ExampleUnixMilli() { + umt := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) + fmt.Println(umt.UnixMilli()) + t := time.UnixMilli(umt.UnixMilli()).UTC() + fmt.Println(t) + + // Output: + // 1257894000000 + // 2009-11-10 23:00:00 +0000 UTC +} + func ExampleTime_Unix() { // 1 billion seconds of Unix, three ways. fmt.Println(time.Unix(1e9, 0).UTC()) // 1e9 seconds -- GitLab From 90462dfc3aa99649de90bb587af56a9cb0214665 Mon Sep 17 00:00:00 2001 From: zhouguangyuan Date: Tue, 2 Nov 2021 23:17:21 +0800 Subject: [PATCH 2011/2500] time: fix looking for zone offset when date is close to a zone transition The old implement passed start - 1 or end in func lookup to adjust the offset.But if the time is close to the last zoneTrans, like the issue, testcase and comment, the "start" from lookup will be omega. It can't be adjusted correctly. Fixes #49284 Change-Id: Ibaf82dc4db6d5dd3279796f003d2b19c38a26341 Reviewed-on: https://go-review.googlesource.com/c/go/+/360616 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Robert Findley --- src/time/time.go | 14 +++++++------- src/time/time_test.go | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/time/time.go b/src/time/time.go index edf0c62610..8046ff508b 100644 --- a/src/time/time.go +++ b/src/time/time.go @@ -1433,17 +1433,17 @@ func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) T unix := int64(abs) + (absoluteToInternal + internalToUnix) - // Look for zone offset for t, so we can adjust to UTC. - // The lookup function expects UTC, so we pass t in the + // Look for zone offset for expected time, so we can adjust to UTC. + // The lookup function expects UTC, so first we pass unix in the // hope that it will not be too close to a zone transition, // and then adjust if it is. _, offset, start, end, _ := loc.lookup(unix) if offset != 0 { - switch utc := unix - int64(offset); { - case utc < start: - _, offset, _, _, _ = loc.lookup(start - 1) - case utc >= end: - _, offset, _, _, _ = loc.lookup(end) + utc := unix - int64(offset) + // If utc is valid for the time zone we found, then we have the right offset. + // If not, we get the correct offset by looking up utc in the location. + if utc < start || utc >= end { + _, offset, _, _, _ = loc.lookup(utc) } unix -= int64(offset) } diff --git a/src/time/time_test.go b/src/time/time_test.go index 5007b6e723..6a4049617c 100644 --- a/src/time/time_test.go +++ b/src/time/time_test.go @@ -1616,3 +1616,45 @@ func TestTimeAddSecOverflow(t *testing.T) { } } } + +// Issue 49284: time: ParseInLocation incorrectly because of Daylight Saving Time +func TestTimeWithZoneTransition(t *testing.T) { + ForceZipFileForTesting(true) + defer ForceZipFileForTesting(false) + + loc, err := LoadLocation("Asia/Shanghai") + if err != nil { + t.Fatal(err) + } + + tests := [...]struct { + give Time + want Time + }{ + // 14 Apr 1991 - Daylight Saving Time Started + // When time of "Asia/Shanghai" was about to reach + // Sunday, 14 April 1991, 02:00:00 clocks were turned forward 1 hour to + // Sunday, 14 April 1991, 03:00:00 local daylight time instead. + // The UTC time was 13 April 1991, 18:00:00 + 0: {Date(1991, April, 13, 17, 50, 0, 0, loc), Date(1991, April, 13, 9, 50, 0, 0, UTC)}, + 1: {Date(1991, April, 13, 18, 0, 0, 0, loc), Date(1991, April, 13, 10, 0, 0, 0, UTC)}, + 2: {Date(1991, April, 14, 1, 50, 0, 0, loc), Date(1991, April, 13, 17, 50, 0, 0, UTC)}, + 3: {Date(1991, April, 14, 3, 0, 0, 0, loc), Date(1991, April, 13, 18, 0, 0, 0, UTC)}, + + // 15 Sep 1991 - Daylight Saving Time Ended + // When local daylight time of "Asia/Shanghai" was about to reach + // Sunday, 15 September 1991, 02:00:00 clocks were turned backward 1 hour to + // Sunday, 15 September 1991, 01:00:00 local standard time instead. + // The UTC time was 14 September 1991, 17:00:00 + 4: {Date(1991, September, 14, 16, 50, 0, 0, loc), Date(1991, September, 14, 7, 50, 0, 0, UTC)}, + 5: {Date(1991, September, 14, 17, 0, 0, 0, loc), Date(1991, September, 14, 8, 0, 0, 0, UTC)}, + 6: {Date(1991, September, 15, 0, 50, 0, 0, loc), Date(1991, September, 14, 15, 50, 0, 0, UTC)}, + 7: {Date(1991, September, 15, 2, 00, 0, 0, loc), Date(1991, September, 14, 18, 00, 0, 0, UTC)}, + } + + for i, tt := range tests { + if !tt.give.Equal(tt.want) { + t.Errorf("#%d:: %#v is not equal to %#v", i, tt.give.Format(RFC3339), tt.want.Format(RFC3339)) + } + } +} -- GitLab From fb8b1764d8e8afdaf5d8fd00af3720e42d96ad9c Mon Sep 17 00:00:00 2001 From: jiahua wang Date: Wed, 13 Oct 2021 22:16:37 +0800 Subject: [PATCH 2012/2500] errors: add errors.Unwrap example Change-Id: Id2336a6059f7a8d627e6c0661a4d4c05485b65f3 Reviewed-on: https://go-review.googlesource.com/c/go/+/355589 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Trust: Cherry Mui Trust: Robert Findley --- src/errors/wrap_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/errors/wrap_test.go b/src/errors/wrap_test.go index 6f66e99c4a..a22fee2f04 100644 --- a/src/errors/wrap_test.go +++ b/src/errors/wrap_test.go @@ -265,3 +265,13 @@ func ExampleAs() { // Output: // Failed at path: non-existing } + +func ExampleUnwrap() { + err1 := errors.New("error1") + err2 := fmt.Errorf("error2: [%w]", err1) + fmt.Println(err2) + fmt.Println(errors.Unwrap(err2)) + // Output + // error2: [error1] + // error1 +} -- GitLab From 75952abc6a8a8ad09e6bb1966c66b9a68b5d6c4e Mon Sep 17 00:00:00 2001 From: jiahua wang Date: Thu, 7 Oct 2021 15:30:03 +0800 Subject: [PATCH 2013/2500] unicode/utf8: add AppendRune Example Also, correct TestAppendRune error message. Change-Id: I3ca3ac7051af1ae6d449381b78efa86c2f6be8ac Reviewed-on: https://go-review.googlesource.com/c/go/+/354529 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Trust: Robert Findley Trust: Cherry Mui TryBot-Result: Go Bot --- src/unicode/utf8/example_test.go | 10 ++++++++++ src/unicode/utf8/utf8_test.go | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/unicode/utf8/example_test.go b/src/unicode/utf8/example_test.go index 5cd931d242..fe434c9476 100644 --- a/src/unicode/utf8/example_test.go +++ b/src/unicode/utf8/example_test.go @@ -214,3 +214,13 @@ func ExampleValidString() { // true // false } + +func ExampleAppendRune() { + buf1 := utf8.AppendRune(nil, 0x10000) + buf2 := utf8.AppendRune([]byte("init"), 0x10000) + fmt.Println(string(buf1)) + fmt.Println(string(buf2)) + // Output: + // 𐀀 + // init𐀀 +} diff --git a/src/unicode/utf8/utf8_test.go b/src/unicode/utf8/utf8_test.go index a60040ecfd..e9be4d2d63 100644 --- a/src/unicode/utf8/utf8_test.go +++ b/src/unicode/utf8/utf8_test.go @@ -133,7 +133,7 @@ func TestAppendRune(t *testing.T) { t.Errorf("AppendRune(nil, %#04x) = %s, want %s", m.r, buf, m.str) } if buf := AppendRune([]byte("init"), m.r); string(buf) != "init"+m.str { - t.Errorf("AppendRune(nil, %#04x) = %s, want %s", m.r, buf, "init"+m.str) + t.Errorf("AppendRune(init, %#04x) = %s, want %s", m.r, buf, "init"+m.str) } } } -- GitLab From bb53fd740c599dd72c2abdab045ca34a9395ea13 Mon Sep 17 00:00:00 2001 From: Nevkontakte Date: Sat, 23 Oct 2021 14:02:25 +0000 Subject: [PATCH 2014/2500] net/http: adjust a substring which matches "uninteresting" goroutine This change allows the check to pass unmodified under GopherJS, which stack traces are formatted differently (due to being generated by NodeJS). There are no other functions named `interestingGoroutines` in the standard library, so it's very unlikely to create false negatives, and will allow reduce the number of overlays GopherJS needs to maintain. Change-Id: I925594c6c313ca35805811f240c8528241950547 GitHub-Last-Rev: 26b32efb225c1ee85de0a51968c31b1a58d56f92 GitHub-Pull-Request: golang/go#49128 Reviewed-on: https://go-review.googlesource.com/c/go/+/358154 Reviewed-by: Damien Neil Reviewed-by: Emmanuel Odeke Trust: Damien Neil Trust: Ian Lance Taylor Run-TryBot: Damien Neil TryBot-Result: Go Bot --- src/net/http/main_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/http/main_test.go b/src/net/http/main_test.go index 632a308a5c..27872b4e7a 100644 --- a/src/net/http/main_test.go +++ b/src/net/http/main_test.go @@ -43,7 +43,7 @@ func interestingGoroutines() (gs []string) { // These only show up with GOTRACEBACK=2; Issue 5005 (comment 28) strings.Contains(stack, "runtime.goexit") || strings.Contains(stack, "created by runtime.gc") || - strings.Contains(stack, "net/http_test.interestingGoroutines") || + strings.Contains(stack, "interestingGoroutines") || strings.Contains(stack, "runtime.MHeap_Scavenger") { continue } -- GitLab From 6b223e872a255b2722ea921c9d42adcbb5d1d4d5 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Sun, 31 Oct 2021 19:23:14 -0400 Subject: [PATCH 2015/2500] crypto/x509: disable SHA-1 signature verification Updates #41682 Change-Id: Ib766d2587d54dd3aeff8ecab389741df5e8af7cc Reviewed-on: https://go-review.googlesource.com/c/go/+/359777 Run-TryBot: Filippo Valsorda TryBot-Result: Go Bot Trust: Filippo Valsorda Reviewed-by: Roland Shoemaker --- src/crypto/x509/verify_test.go | 4 ++ src/crypto/x509/x509.go | 39 ++++++++++++++---- src/crypto/x509/x509_test.go | 75 +++++++++++++++++++++++++--------- 3 files changed, 90 insertions(+), 28 deletions(-) diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go index df78abd77e..b9b71f4c1e 100644 --- a/src/crypto/x509/verify_test.go +++ b/src/crypto/x509/verify_test.go @@ -534,6 +534,10 @@ func testVerify(t *testing.T, test verifyTest, useSystemRoots bool) { } func TestGoVerify(t *testing.T) { + // Temporarily enable SHA-1 verification since a number of test chains + // require it. TODO(filippo): regenerate test chains. + defer func(old bool) { debugAllowSHA1 = old }(debugAllowSHA1) + debugAllowSHA1 = true for _, test := range verifyTests { t.Run(test.name, func(t *testing.T) { testVerify(t, test, false) diff --git a/src/crypto/x509/x509.go b/src/crypto/x509/x509.go index 4304ab54e1..b5c2b22cd7 100644 --- a/src/crypto/x509/x509.go +++ b/src/crypto/x509/x509.go @@ -18,6 +18,7 @@ import ( "encoding/pem" "errors" "fmt" + "internal/godebug" "io" "math/big" "net" @@ -181,15 +182,15 @@ type SignatureAlgorithm int const ( UnknownSignatureAlgorithm SignatureAlgorithm = iota - MD2WithRSA // Unsupported. - MD5WithRSA // Only supported for signing, not verification. - SHA1WithRSA + MD2WithRSA // Unsupported. + MD5WithRSA // Only supported for signing, not verification. + SHA1WithRSA // Only supported for signing, not verification. SHA256WithRSA SHA384WithRSA SHA512WithRSA DSAWithSHA1 // Unsupported. DSAWithSHA256 // Unsupported. - ECDSAWithSHA1 + ECDSAWithSHA1 // Only supported for signing, not verification. ECDSAWithSHA256 ECDSAWithSHA384 ECDSAWithSHA512 @@ -729,11 +730,23 @@ type Certificate struct { // involves algorithms that are not currently implemented. var ErrUnsupportedAlgorithm = errors.New("x509: cannot verify signature: algorithm unimplemented") -// An InsecureAlgorithmError +// debugAllowSHA1 allows SHA-1 signatures. See issue 41682. +var debugAllowSHA1 = godebug.Get("x509sha1") == "1" + +// An InsecureAlgorithmError indicates that the SignatureAlgorithm used to +// generate the signature is not secure, and the signature has been rejected. +// +// To temporarily restore support for SHA-1 signatures, include the value +// "x509sha1=1" in the GODEBUG environment variable. Note that this option will +// be removed in Go 1.19. type InsecureAlgorithmError SignatureAlgorithm func (e InsecureAlgorithmError) Error() string { - return fmt.Sprintf("x509: cannot verify signature: insecure algorithm %v", SignatureAlgorithm(e)) + var override string + if SignatureAlgorithm(e) == SHA1WithRSA || SignatureAlgorithm(e) == ECDSAWithSHA1 { + override = " (temporarily override with GODEBUG=x509sha1=1)" + } + return fmt.Sprintf("x509: cannot verify signature: insecure algorithm %v", SignatureAlgorithm(e)) + override } // ConstraintViolationError results when a requested usage is not permitted by @@ -825,6 +838,11 @@ func checkSignature(algo SignatureAlgorithm, signed, signature []byte, publicKey } case crypto.MD5: return InsecureAlgorithmError(algo) + case crypto.SHA1: + if !debugAllowSHA1 { + return InsecureAlgorithmError(algo) + } + fallthrough default: if !hashType.Available() { return ErrUnsupportedAlgorithm @@ -1579,9 +1597,12 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv } // Check the signature to ensure the crypto.Signer behaved correctly. - // We skip this check if the signature algorithm is MD5WithRSA as we - // only support this algorithm for signing, and not verification. - if sigAlg := getSignatureAlgorithmFromAI(signatureAlgorithm); sigAlg != MD5WithRSA { + sigAlg := getSignatureAlgorithmFromAI(signatureAlgorithm) + switch sigAlg { + case MD5WithRSA, SHA1WithRSA, ECDSAWithSHA1: + // We skip the check if the signature algorithm is only supported for + // signing, not verification. + default: if err := checkSignature(sigAlg, c.Raw, signature, key.Public()); err != nil { return nil, fmt.Errorf("x509: signature over certificate returned by signer is invalid: %w", err) } diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go index a4053abf41..affab3789d 100644 --- a/src/crypto/x509/x509_test.go +++ b/src/crypto/x509/x509_test.go @@ -585,10 +585,10 @@ func TestCreateSelfSignedCertificate(t *testing.T) { checkSig bool sigAlgo SignatureAlgorithm }{ - {"RSA/RSA", &testPrivateKey.PublicKey, testPrivateKey, true, SHA1WithRSA}, + {"RSA/RSA", &testPrivateKey.PublicKey, testPrivateKey, true, SHA384WithRSA}, {"RSA/ECDSA", &testPrivateKey.PublicKey, ecdsaPriv, false, ECDSAWithSHA384}, {"ECDSA/RSA", &ecdsaPriv.PublicKey, testPrivateKey, false, SHA256WithRSA}, - {"ECDSA/ECDSA", &ecdsaPriv.PublicKey, ecdsaPriv, true, ECDSAWithSHA1}, + {"ECDSA/ECDSA", &ecdsaPriv.PublicKey, ecdsaPriv, true, ECDSAWithSHA256}, {"RSAPSS/RSAPSS", &testPrivateKey.PublicKey, testPrivateKey, true, SHA256WithRSAPSS}, {"ECDSA/RSAPSS", &ecdsaPriv.PublicKey, testPrivateKey, false, SHA256WithRSAPSS}, {"RSAPSS/ECDSA", &testPrivateKey.PublicKey, ecdsaPriv, false, ECDSAWithSHA384}, @@ -886,7 +886,6 @@ var ecdsaTests = []struct { sigAlgo SignatureAlgorithm pemCert string }{ - {ECDSAWithSHA1, ecdsaSHA1CertPem}, {ECDSAWithSHA256, ecdsaSHA256p256CertPem}, {ECDSAWithSHA256, ecdsaSHA256p384CertPem}, {ECDSAWithSHA384, ecdsaSHA384p521CertPem}, @@ -1389,10 +1388,10 @@ func TestCreateCertificateRequest(t *testing.T) { priv interface{} sigAlgo SignatureAlgorithm }{ - {"RSA", testPrivateKey, SHA1WithRSA}, - {"ECDSA-256", ecdsa256Priv, ECDSAWithSHA1}, - {"ECDSA-384", ecdsa384Priv, ECDSAWithSHA1}, - {"ECDSA-521", ecdsa521Priv, ECDSAWithSHA1}, + {"RSA", testPrivateKey, SHA256WithRSA}, + {"ECDSA-256", ecdsa256Priv, ECDSAWithSHA256}, + {"ECDSA-384", ecdsa384Priv, ECDSAWithSHA256}, + {"ECDSA-521", ecdsa521Priv, ECDSAWithSHA256}, {"Ed25519", ed25519Priv, PureEd25519}, } @@ -1783,6 +1782,9 @@ func TestInsecureAlgorithmErrorString(t *testing.T) { sa SignatureAlgorithm want string }{ + {MD5WithRSA, "x509: cannot verify signature: insecure algorithm MD5-RSA"}, + {SHA1WithRSA, "x509: cannot verify signature: insecure algorithm SHA1-RSA (temporarily override with GODEBUG=x509sha1=1)"}, + {ECDSAWithSHA1, "x509: cannot verify signature: insecure algorithm ECDSA-SHA1 (temporarily override with GODEBUG=x509sha1=1)"}, {MD2WithRSA, "x509: cannot verify signature: insecure algorithm MD2-RSA"}, {-1, "x509: cannot verify signature: insecure algorithm -1"}, {0, "x509: cannot verify signature: insecure algorithm 0"}, @@ -1846,6 +1848,30 @@ func TestMD5(t *testing.T) { } } +func TestSHA1(t *testing.T) { + pemBlock, _ := pem.Decode([]byte(ecdsaSHA1CertPem)) + cert, err := ParseCertificate(pemBlock.Bytes) + if err != nil { + t.Fatalf("failed to parse certificate: %s", err) + } + if sa := cert.SignatureAlgorithm; sa != ECDSAWithSHA1 { + t.Errorf("signature algorithm is %v, want %v", sa, ECDSAWithSHA1) + } + if err = cert.CheckSignatureFrom(cert); err == nil { + t.Fatalf("certificate verification succeeded incorrectly") + } + if _, ok := err.(InsecureAlgorithmError); !ok { + t.Fatalf("certificate verification returned %v (%T), wanted InsecureAlgorithmError", err, err) + } + + defer func(old bool) { debugAllowSHA1 = old }(debugAllowSHA1) + debugAllowSHA1 = true + + if err = cert.CheckSignatureFrom(cert); err != nil { + t.Fatalf("SHA-1 certificate did not verify with GODEBUG=x509sha1=1: %v", err) + } +} + // certMissingRSANULL contains an RSA public key where the AlgorithmIdentifier // parameters are omitted rather than being an ASN.1 NULL. const certMissingRSANULL = ` @@ -2897,19 +2923,31 @@ func TestCreateCertificateBrokenSigner(t *testing.T) { } } -func TestCreateCertificateMD5(t *testing.T) { - template := &Certificate{ - SerialNumber: big.NewInt(10), - DNSNames: []string{"example.com"}, - SignatureAlgorithm: MD5WithRSA, - } - k, err := rsa.GenerateKey(rand.Reader, 1024) +func TestCreateCertificateLegacy(t *testing.T) { + ecdsaPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { - t.Fatalf("failed to generate test key: %s", err) + t.Fatalf("Failed to generate ECDSA key: %s", err) } - _, err = CreateCertificate(rand.Reader, template, template, k.Public(), &brokenSigner{k.Public()}) - if err != nil { - t.Fatalf("CreateCertificate failed when SignatureAlgorithm = MD5WithRSA: %s", err) + + for _, sigAlg := range []SignatureAlgorithm{ + MD5WithRSA, SHA1WithRSA, ECDSAWithSHA1, + } { + template := &Certificate{ + SerialNumber: big.NewInt(10), + DNSNames: []string{"example.com"}, + SignatureAlgorithm: sigAlg, + } + var k crypto.Signer + switch sigAlg { + case MD5WithRSA, SHA1WithRSA: + k = testPrivateKey + case ECDSAWithSHA1: + k = ecdsaPriv + } + _, err := CreateCertificate(rand.Reader, template, template, k.Public(), &brokenSigner{k.Public()}) + if err != nil { + t.Fatalf("CreateCertificate failed when SignatureAlgorithm = %v: %s", sigAlg, err) + } } } @@ -3131,7 +3169,6 @@ func TestParseCertificateRawEquals(t *testing.T) { if !bytes.Equal(p.Bytes, cert.Raw) { t.Fatalf("unexpected Certificate.Raw\ngot: %x\nwant: %x\n", cert.Raw, p.Bytes) } - fmt.Printf("in: %x\nout: %x\n", p.Bytes, cert.Raw) } // mismatchingSigAlgIDPEM contains a certificate where the Certificate -- GitLab From 755ede0c5b6a9398170e1da0dae94df1b98352aa Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Tue, 19 Oct 2021 14:05:29 -0400 Subject: [PATCH 2016/2500] cmd/go: fix bugs in replacement path handling These are tested in golang.org/cl/357169 and golang.org/cl/358540. Change-Id: I5add3f202db71731487f2688234c547abe1fd287 Reviewed-on: https://go-review.googlesource.com/c/go/+/361416 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/modload/init.go | 2 +- src/cmd/go/internal/modload/modfile.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 0602aee0cc..9aef5a7c33 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -968,7 +968,7 @@ func makeMainModules(ms []module.Version, rootDirs []string, modFiles []*modfile for _, r := range modFiles[i].Replace { if replacedByWorkFile[r.Old.Path] { continue - } else if prev, ok := replacements[r.Old]; ok && !curModuleReplaces[r.Old] { + } else if prev, ok := replacements[r.Old]; ok && !curModuleReplaces[r.Old] && prev != r.New { base.Fatalf("go: conflicting replacements for %v:\n\t%v\n\t%v\nuse \"go mod editwork -replace %v=[override]\" to resolve", r.Old, prev, r.New, r.Old) } curModuleReplaces[r.Old] = true diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index 1672d563b7..a7e92222a1 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -378,7 +378,7 @@ func canonicalizeReplacePath(r module.Version, modRoot string) module.Version { return r } abs := filepath.Join(modRoot, r.Path) - if rel, err := filepath.Rel(workFilePath, abs); err == nil { + if rel, err := filepath.Rel(filepath.Dir(workFilePath), abs); err == nil { return module.Version{Path: rel, Version: r.Version} } // We couldn't make the version's path relative to the workspace's path, -- GitLab From f00b43f28c9c671637a67b412770acd8af133170 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Fri, 5 Nov 2021 17:29:58 -0400 Subject: [PATCH 2017/2500] doc/go1.18: fill in Go 1.18 release note TODOs using relnote For #47694. Change-Id: Ia80a1859bd0fc6f08d27293f519c22fd9a804fd2 Reviewed-on: https://go-review.googlesource.com/c/go/+/361894 Trust: Dmitri Shuralyov Trust: Carlos Amedee Reviewed-by: Carlos Amedee --- doc/go1.18.html | 199 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 182 insertions(+), 17 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 385a1ae804..55a1de3bd8 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -31,19 +31,30 @@ Do not send CLs removing the interior tags from such phrases.

Ports

-

+

FreeBSD

+ +

Go 1.18 is the last release that is supported on FreeBSD 11.x, which has already reached end-of-life. Go 1.19 will require FreeBSD 12.2+ or FreeBSD 13.0+. FreeBSD 13.0+ will require a kernel with the COMPAT_FREEBSD12 option set (this is the default).

-

Tools

+

PPC64

-

- TODO: complete this section, or delete if not needed +

+ TODO: https://golang.org/cl/353969: internal/buildcfg: enable register ABI for PPC64 +

+ +

RISC-V

+ +

+ The 64-bit RISC-V architecture on Linux (the linux/riscv64 port) + now supports the c-archive and c-shared build modes.

+

Tools

+

Go command

@@ -103,8 +114,8 @@ Do not send CLs removing the interior tags from such phrases. go mod download all.

-

- TODO: complete this section, or delete if not needed +

+ TODO: https://golang.org/cl/349595: https://golang.org/cl/349595: cmd/go: add GOAMD64 environment variable

gofmt

@@ -115,7 +126,6 @@ Do not send CLs removing the interior tags from such phrases. multiple CPUs, gofmt should now be significantly faster.

-

Runtime

@@ -124,24 +134,30 @@ Do not send CLs removing the interior tags from such phrases.

Compiler

-

- TODO: complete this section, or delete if not needed +

+ TODO: https://golang.org/cl/298611: https://golang.org/cl/298611: cmd/compile: add -asan option +

+ +

+ TODO: https://golang.org/cl/352057: https://golang.org/cl/352057: cmd/compile, runtime: track argument stack slot liveness

Linker

-

- TODO: complete this section, or delete if not needed +

+ TODO: https://golang.org/cl/298610: https://golang.org/cl/298610: cmd/link: add -asan option

Core library

-

TODO

-

- TODO: complete this section +

New constraints package

+ +

+ TODO: https://golang.org/cl/349709: constraints: new package

New net/netip package

+

The new net/netip package defines a new IP address type, Addr. @@ -163,6 +179,12 @@ Do not send CLs removing the interior tags from such phrases. *net.UDPAddr values.

+

TODO

+ +

+ TODO: complete this section +

+

Minor changes to the library

@@ -175,6 +197,26 @@ Do not send CLs removing the interior tags from such phrases. TODO: complete this section

+
bufio
+
+

+ TODO: https://golang.org/cl/345569: add Writer.AvailableBuffer +

+ +

+ TODO: https://golang.org/cl/345570: make Reader.Reset and Writer.Reset work on the zero value +

+
+
+ +
crypto/tls
+
+

+ TODO: https://golang.org/cl/325250: add Conn.NetConn method +

+
+
+
debug/buildinfo

@@ -201,9 +243,33 @@ Do not send CLs removing the interior tags from such phrases.

+
net
+
+

+ TODO: https://golang.org/cl/340261: deprecate (net.Error).Temporary +

+
+
+ +
net/http
+
+

+ TODO: https://golang.org/cl/338590: add Cookie.Valid method +

+
+
+ +
os/user
+
+

+ TODO: https://golang.org/cl/330753: implement go native GroupIds +

+
+
+
reflect
-

+

The new Value.SetIterKey and Value.SetIterValue @@ -211,8 +277,7 @@ Do not send CLs removing the interior tags from such phrases. Value.Set(iter.Key()) and Value.Set(iter.Value()) but do fewer allocations.

-
-
+

The new Value.UnsafePointer @@ -221,9 +286,69 @@ Do not send CLs removing the interior tags from such phrases. and Value.Pointer to eliminate the need to perform uintptr to unsafe.Pointer conversions at the callsite (as unsafe.Pointer rules require).

+ +

+ TODO: https://golang.org/cl/321889: allocate hiter as part of MapIter +

+ +

+ TODO: https://golang.org/cl/321891: add MapIter.Reset +

+ +

+ TODO: https://golang.org/cl/345486: optimize for maps with string keys +

+ +

+ TODO: https://golang.org/cl/352131: add Value.{CanInt, CanUint, CanFloat, CanComplex} +

+ +

+ TODO: https://golang.org/cl/357962: add FieldByIndexErr +

+
regexp
+
+

+ TODO: https://golang.org/cl/354569: document and implement that invalid UTF-8 bytes are the same as U+FFFD +

+
+
+ +
strconv
+
+

+ TODO: https://golang.org/cl/343877: reject surrogate halves in Unquote +

+
+
+ +
strings
+
+

+ TODO: https://golang.org/cl/345849: add Clone function +

+
+
+ +
strings,bytes
+
+

+ TODO: https://golang.org/cl/332771: avoid allocations in Trim/TrimLeft/TrimRight +

+
+
+ +
sync
+
+

+ TODO: https://golang.org/cl/319769: add Mutex.TryLock, RWMutex.TryLock, RWMutex.TryRLock +

+
+
+
syscall

@@ -238,5 +363,45 @@ Do not send CLs removing the interior tags from such phrases. Syscall18 are deprecated in favor of SyscallN.

+ +

+ TODO: https://golang.org/cl/355570: add support for SysProcAttr.Pdeathsig on FreeBSD +

+ +
syscall/js
+
+

+ TODO: https://golang.org/cl/356430: remove Wrapper interface +

+
+
+ +
testing
+
+

+ TODO: https://golang.org/cl/343883: increase alternation precedence +

+ +

+ TODO: https://golang.org/cl/356669: skip extra -count iterations if there are no tests +

+
+
+ +
text/template
+
+

+ TODO: https://golang.org/cl/321490: implement short-circuit and, or +

+
+
+ +
unicode/utf8
+
+

+ TODO: https://golang.org/cl/345571: add AppendRune +

+
+
-- GitLab From 035963c7f5d82b5bf1501f407919031f815bd038 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Sun, 31 Oct 2021 23:13:18 -0400 Subject: [PATCH 2018/2500] crypto/tls: set default minimum client version to TLS 1.2 Updates #45428 Change-Id: I5d70066d4091196ec6f8bfc2edf3d78fdc0520c1 Reviewed-on: https://go-review.googlesource.com/c/go/+/359779 Run-TryBot: Filippo Valsorda TryBot-Result: Go Bot Trust: Filippo Valsorda Reviewed-by: Roland Shoemaker --- src/crypto/tls/common.go | 38 +++++++++++++++++++----- src/crypto/tls/handshake_client.go | 8 ++--- src/crypto/tls/handshake_server.go | 6 ++-- src/crypto/tls/handshake_server_test.go | 20 ++++++++++++- src/crypto/tls/handshake_server_tls13.go | 2 +- src/crypto/tls/handshake_test.go | 2 ++ 6 files changed, 59 insertions(+), 17 deletions(-) diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go index 610a5162dd..bb5bec3c4d 100644 --- a/src/crypto/tls/common.go +++ b/src/crypto/tls/common.go @@ -18,6 +18,7 @@ import ( "crypto/x509" "errors" "fmt" + "internal/godebug" "io" "net" "strings" @@ -682,11 +683,20 @@ type Config struct { ClientSessionCache ClientSessionCache // MinVersion contains the minimum TLS version that is acceptable. - // If zero, TLS 1.0 is currently taken as the minimum. + // + // By default, TLS 1.2 is currently used as the minimum when acting as a + // client, and TLS 1.0 when acting as a server. TLS 1.0 is the minimum + // supported by this package, both as a client and as a server. + // + // The client-side default can temporarily be reverted to TLS 1.0 by + // including the value "x509sha1=1" in the GODEBUG environment variable. + // Note that this option will be removed in Go 1.19 (but it will still be + // possible to set this field to VersionTLS10 explicitly). MinVersion uint16 // MaxVersion contains the maximum TLS version that is acceptable. - // If zero, the maximum version supported by this package is used, + // + // By default, the maximum version supported by this package is used, // which is currently TLS 1.3. MaxVersion uint16 @@ -964,9 +974,21 @@ var supportedVersions = []uint16{ VersionTLS10, } -func (c *Config) supportedVersions() []uint16 { +// debugEnableTLS10 enables TLS 1.0. See issue 45428. +var debugEnableTLS10 = godebug.Get("tls10default") == "1" + +// roleClient and roleServer are meant to call supportedVersions and parents +// with more readability at the callsite. +const roleClient = true +const roleServer = false + +func (c *Config) supportedVersions(isClient bool) []uint16 { versions := make([]uint16, 0, len(supportedVersions)) for _, v := range supportedVersions { + if (c == nil || c.MinVersion == 0) && !debugEnableTLS10 && + isClient && v < VersionTLS12 { + continue + } if c != nil && c.MinVersion != 0 && v < c.MinVersion { continue } @@ -978,8 +1000,8 @@ func (c *Config) supportedVersions() []uint16 { return versions } -func (c *Config) maxSupportedVersion() uint16 { - supportedVersions := c.supportedVersions() +func (c *Config) maxSupportedVersion(isClient bool) uint16 { + supportedVersions := c.supportedVersions(isClient) if len(supportedVersions) == 0 { return 0 } @@ -1020,8 +1042,8 @@ func (c *Config) supportsCurve(curve CurveID) bool { // mutualVersion returns the protocol version to use given the advertised // versions of the peer. Priority is given to the peer preference order. -func (c *Config) mutualVersion(peerVersions []uint16) (uint16, bool) { - supportedVersions := c.supportedVersions() +func (c *Config) mutualVersion(isClient bool, peerVersions []uint16) (uint16, bool) { + supportedVersions := c.supportedVersions(isClient) for _, peerVersion := range peerVersions { for _, v := range supportedVersions { if v == peerVersion { @@ -1100,7 +1122,7 @@ func (chi *ClientHelloInfo) SupportsCertificate(c *Certificate) error { if config == nil { config = &Config{} } - vers, ok := config.mutualVersion(chi.SupportedVersions) + vers, ok := config.mutualVersion(roleServer, chi.SupportedVersions) if !ok { return errors.New("no mutually supported protocol versions") } diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go index 4af3d998a3..2ae6f3f534 100644 --- a/src/crypto/tls/handshake_client.go +++ b/src/crypto/tls/handshake_client.go @@ -52,12 +52,12 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, ecdheParameters, error) { return nil, nil, errors.New("tls: NextProtos values too large") } - supportedVersions := config.supportedVersions() + supportedVersions := config.supportedVersions(roleClient) if len(supportedVersions) == 0 { return nil, nil, errors.New("tls: no supported versions satisfy MinVersion and MaxVersion") } - clientHelloVersion := config.maxSupportedVersion() + clientHelloVersion := config.maxSupportedVersion(roleClient) // The version at the beginning of the ClientHello was capped at TLS 1.2 // for compatibility reasons. The supported_versions extension is used // to negotiate versions now. See RFC 8446, Section 4.2.1. @@ -194,7 +194,7 @@ func (c *Conn) clientHandshake(ctx context.Context) (err error) { // If we are negotiating a protocol version that's lower than what we // support, check for the server downgrade canaries. // See RFC 8446, Section 4.1.3. - maxVers := c.config.maxSupportedVersion() + maxVers := c.config.maxSupportedVersion(roleClient) tls12Downgrade := string(serverHello.random[24:]) == downgradeCanaryTLS12 tls11Downgrade := string(serverHello.random[24:]) == downgradeCanaryTLS11 if maxVers == VersionTLS13 && c.vers <= VersionTLS12 && (tls12Downgrade || tls11Downgrade) || @@ -362,7 +362,7 @@ func (c *Conn) pickTLSVersion(serverHello *serverHelloMsg) error { peerVersion = serverHello.supportedVersion } - vers, ok := c.config.mutualVersion([]uint16{peerVersion}) + vers, ok := c.config.mutualVersion(roleClient, []uint16{peerVersion}) if !ok { c.sendAlert(alertProtocolVersion) return fmt.Errorf("tls: server selected unsupported protocol version %x", peerVersion) diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go index 43f30e2fef..5cb152755b 100644 --- a/src/crypto/tls/handshake_server.go +++ b/src/crypto/tls/handshake_server.go @@ -156,7 +156,7 @@ func (c *Conn) readClientHello(ctx context.Context) (*clientHelloMsg, error) { if len(clientHello.supportedVersions) == 0 { clientVersions = supportedVersionsFromMax(clientHello.vers) } - c.vers, ok = c.config.mutualVersion(clientVersions) + c.vers, ok = c.config.mutualVersion(roleServer, clientVersions) if !ok { c.sendAlert(alertProtocolVersion) return nil, fmt.Errorf("tls: client offered only unsupported versions: %x", clientVersions) @@ -191,7 +191,7 @@ func (hs *serverHandshakeState) processClientHello() error { hs.hello.random = make([]byte, 32) serverRandom := hs.hello.random // Downgrade protection canaries. See RFC 8446, Section 4.1.3. - maxVers := c.config.maxSupportedVersion() + maxVers := c.config.maxSupportedVersion(roleServer) if maxVers >= VersionTLS12 && c.vers < maxVers || testingOnlyForceDowngradeCanary { if c.vers == VersionTLS12 { copy(serverRandom[24:], downgradeCanaryTLS12) @@ -354,7 +354,7 @@ func (hs *serverHandshakeState) pickCipherSuite() error { for _, id := range hs.clientHello.cipherSuites { if id == TLS_FALLBACK_SCSV { // The client is doing a fallback connection. See RFC 7507. - if hs.clientHello.vers < c.config.maxSupportedVersion() { + if hs.clientHello.vers < c.config.maxSupportedVersion(roleServer) { c.sendAlert(alertInappropriateFallback) return errors.New("tls: client using inappropriate protocol fallback") } diff --git a/src/crypto/tls/handshake_server_test.go b/src/crypto/tls/handshake_server_test.go index f61b4c88ef..5fb2ebbbb3 100644 --- a/src/crypto/tls/handshake_server_test.go +++ b/src/crypto/tls/handshake_server_test.go @@ -385,13 +385,30 @@ func TestVersion(t *testing.T) { } clientConfig := &Config{ InsecureSkipVerify: true, + MinVersion: VersionTLS10, } state, _, err := testHandshake(t, clientConfig, serverConfig) if err != nil { t.Fatalf("handshake failed: %s", err) } if state.Version != VersionTLS11 { - t.Fatalf("Incorrect version %x, should be %x", state.Version, VersionTLS11) + t.Fatalf("incorrect version %x, should be %x", state.Version, VersionTLS11) + } + + clientConfig.MinVersion = 0 + _, _, err = testHandshake(t, clientConfig, serverConfig) + if err == nil { + t.Fatalf("expected failure to connect with TLS 1.0/1.1") + } + + defer func(old bool) { debugEnableTLS10 = old }(debugEnableTLS10) + debugEnableTLS10 = true + _, _, err = testHandshake(t, clientConfig, serverConfig) + if err != nil { + t.Fatalf("handshake failed: %s", err) + } + if state.Version != VersionTLS11 { + t.Fatalf("incorrect version %x, should be %x", state.Version, VersionTLS11) } } @@ -472,6 +489,7 @@ func testCrossVersionResume(t *testing.T, version uint16) { InsecureSkipVerify: true, ClientSessionCache: NewLRUClientSessionCache(1), ServerName: "servername", + MinVersion: VersionTLS10, } // Establish a session at TLS 1.1. diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go index 08251b84de..0b19502762 100644 --- a/src/crypto/tls/handshake_server_tls13.go +++ b/src/crypto/tls/handshake_server_tls13.go @@ -110,7 +110,7 @@ func (hs *serverHandshakeStateTLS13) processClientHello() error { if id == TLS_FALLBACK_SCSV { // Use c.vers instead of max(supported_versions) because an attacker // could defeat this by adding an arbitrary high version otherwise. - if c.vers < c.config.maxSupportedVersion() { + if c.vers < c.config.maxSupportedVersion(roleServer) { c.sendAlert(alertInappropriateFallback) return errors.New("tls: client using inappropriate protocol fallback") } diff --git a/src/crypto/tls/handshake_test.go b/src/crypto/tls/handshake_test.go index 90ac9bd11e..bacc8b7d4f 100644 --- a/src/crypto/tls/handshake_test.go +++ b/src/crypto/tls/handshake_test.go @@ -363,6 +363,8 @@ func runMain(m *testing.M) int { Certificates: make([]Certificate, 2), InsecureSkipVerify: true, CipherSuites: allCipherSuites(), + MinVersion: VersionTLS10, + MaxVersion: VersionTLS13, } testConfig.Certificates[0].Certificate = [][]byte{testRSACertificate} testConfig.Certificates[0].PrivateKey = testRSAPrivateKey -- GitLab From 35a588109b2a6d8b610be08d32aaf99ef1549085 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Sun, 31 Oct 2021 23:22:38 -0400 Subject: [PATCH 2019/2500] net: accept "." as a valid domain name Fixes #45715 Change-Id: Ibdaa91c97d34473061b377325ebe9a3bf5696c8e Reviewed-on: https://go-review.googlesource.com/c/go/+/360314 Trust: Filippo Valsorda Run-TryBot: Filippo Valsorda TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/net/dnsclient.go | 5 +++++ src/net/dnsclient_unix_test.go | 41 ++++++++++++++++++++++++++++++++++ src/net/lookup.go | 4 +--- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/net/dnsclient.go b/src/net/dnsclient.go index 3c1a12995a..a779c37e53 100644 --- a/src/net/dnsclient.go +++ b/src/net/dnsclient.go @@ -76,6 +76,11 @@ func equalASCIIName(x, y dnsmessage.Name) bool { // (currently restricted to hostname-compatible "preferred name" LDH labels and // SRV-like "underscore labels"; see golang.org/issue/12421). func isDomainName(s string) bool { + // The root domain name is valid. See golang.org/issue/45715. + if s == "." { + return true + } + // See RFC 1035, RFC 3696. // Presentation format has dots before every label except the first, and the // terminal empty label is optional here because we assume fully-qualified diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go index 1d704d021e..14366eca8c 100644 --- a/src/net/dnsclient_unix_test.go +++ b/src/net/dnsclient_unix_test.go @@ -2120,3 +2120,44 @@ func TestNullMX(t *testing.T) { t.Errorf("records = [%v]; want [%v]", strings.Join(records, " "), want[0]) } } + +func TestRootNS(t *testing.T) { + // See https://golang.org/issue/45715. + fake := fakeDNSServer{ + rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) { + r := dnsmessage.Message{ + Header: dnsmessage.Header{ + ID: q.Header.ID, + Response: true, + RCode: dnsmessage.RCodeSuccess, + }, + Questions: q.Questions, + Answers: []dnsmessage.Resource{ + { + Header: dnsmessage.ResourceHeader{ + Name: q.Questions[0].Name, + Type: dnsmessage.TypeNS, + Class: dnsmessage.ClassINET, + }, + Body: &dnsmessage.NSResource{ + NS: dnsmessage.MustNewName("i.root-servers.net."), + }, + }, + }, + } + return r, nil + }, + } + r := Resolver{PreferGo: true, Dial: fake.DialContext} + rrset, err := r.LookupNS(context.Background(), ".") + if err != nil { + t.Fatalf("LookupNS: %v", err) + } + if want := []*NS{&NS{Host: "i.root-servers.net."}}; !reflect.DeepEqual(rrset, want) { + records := []string{} + for _, rr := range rrset { + records = append(records, fmt.Sprintf("%v", rr)) + } + t.Errorf("records = [%v]; want [%v]", strings.Join(records, " "), want[0]) + } +} diff --git a/src/net/lookup.go b/src/net/lookup.go index e10c71ae75..ff4ddbeb82 100644 --- a/src/net/lookup.go +++ b/src/net/lookup.go @@ -558,9 +558,7 @@ func (r *Resolver) LookupMX(ctx context.Context, name string) ([]*MX, error) { if mx == nil { continue } - // Bypass the hostname validity check for targets which contain only a dot, - // as this is used to represent a 'Null' MX record. - if mx.Host != "." && !isDomainName(mx.Host) { + if !isDomainName(mx.Host) { continue } filteredMX = append(filteredMX, mx) -- GitLab From d3a80c795e9368e9dfac4efb49e3ee041513d24a Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Tue, 2 Nov 2021 20:44:32 +0100 Subject: [PATCH 2020/2500] net/netip: add Addr.AsSlice() method We have AddrFrom4, AddrFrom6, AddrFromSlice and As4, As6, but we are missing AsSlice, so this commit adds the missing function. It also gets rid of the less ergonomic and inconsistently named IPAddrParts. Updates #49298. Change-Id: I1c6a2c32fc6c69b244ab49765412ffe3bbe7e5c2 Reviewed-on: https://go-review.googlesource.com/c/go/+/360874 Trust: Jason A. Donenfeld Trust: Josh Bleecher Snyder Run-TryBot: Jason A. Donenfeld TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/net/netip/netip.go | 42 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/src/net/netip/netip.go b/src/net/netip/netip.go index 8cde6ef3d2..9e08be94fc 100644 --- a/src/net/netip/netip.go +++ b/src/net/netip/netip.go @@ -448,31 +448,6 @@ func (ip Addr) Less(ip2 Addr) bool { return ip.Compare(ip2) == -1 } func (ip Addr) lessOrEq(ip2 Addr) bool { return ip.Compare(ip2) <= 0 } -// ipZone returns the standard library net.IP from ip, as well -// as the zone. -// The optional reuse IP provides memory to reuse. -func (ip Addr) ipZone(reuse []byte) (stdIP []byte, zone string) { - base := reuse[:0] - switch { - case ip.z == z0: - return nil, "" - case ip.Is4(): - a4 := ip.As4() - return append(base, a4[:]...), "" - default: - a16 := ip.As16() - return append(base, a16[:]...), ip.Zone() - } -} - -// IPAddrParts returns the net.IPAddr representation of an Addr. -// -// The slice will be nil if ip is the zero Addr. -// The zone is the empty string if there is no zone. -func (ip Addr) IPAddrParts() (slice []byte, zone string) { - return ip.ipZone(nil) -} - // Is4 reports whether ip is an IPv4 address. // // It returns false for IP4-mapped IPv6 addresses. See IP.Unmap. @@ -718,6 +693,23 @@ func (ip Addr) As4() (a4 [4]byte) { panic("As4 called on IPv6 address") } +// AsSlice returns an IPv4 or IPv6 address in its respective 4-byte or 16-byte representation. +func (ip Addr) AsSlice() []byte { + switch ip.z { + case z0: + return nil + case z4: + var ret [4]byte + bePutUint32(ret[:], uint32(ip.addr.lo)) + return ret[:] + default: + var ret [16]byte + bePutUint64(ret[:8], ip.addr.hi) + bePutUint64(ret[8:], ip.addr.lo) + return ret[:] + } +} + // Next returns the address following ip. // If there is none, it returns the zero Addr. func (ip Addr) Next() Addr { -- GitLab From 8f923a4e3c03829874b43291f2bdfd12e2d8189b Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Tue, 2 Nov 2021 21:33:23 +0100 Subject: [PATCH 2021/2500] net/netip: add missing encoding.BinaryUnmarshaler to AddrPort and Prefix The Addr type got an encoding.BinaryUnmarshaler implementation, but not AddrPort and Prefix. This commit adds the missing implementation of that interface to these types. It also adds two round trip tests that follow the template of the existing one for Addr. Updates #49298. Change-Id: Iac633aed8aac579960815bb64d06ff3181214841 Reviewed-on: https://go-review.googlesource.com/c/go/+/360875 Trust: Jason A. Donenfeld Run-TryBot: Jason A. Donenfeld TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/net/netip/leaf_alts.go | 11 +++++ src/net/netip/netip.go | 54 +++++++++++++++++++++++ src/net/netip/netip_test.go | 88 +++++++++++++++++++++++++++++++++++-- 3 files changed, 150 insertions(+), 3 deletions(-) diff --git a/src/net/netip/leaf_alts.go b/src/net/netip/leaf_alts.go index c51f7dfa54..70513abfd9 100644 --- a/src/net/netip/leaf_alts.go +++ b/src/net/netip/leaf_alts.go @@ -41,3 +41,14 @@ func bePutUint32(b []byte, v uint32) { b[2] = byte(v >> 8) b[3] = byte(v) } + +func leUint16(b []byte) uint16 { + _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808 + return uint16(b[0]) | uint16(b[1])<<8 +} + +func lePutUint16(b []byte, v uint16) { + _ = b[1] // early bounds check to guarantee safety of writes below + b[0] = byte(v) + b[1] = byte(v >> 8) +} diff --git a/src/net/netip/netip.go b/src/net/netip/netip.go index 9e08be94fc..90672e045d 100644 --- a/src/net/netip/netip.go +++ b/src/net/netip/netip.go @@ -1170,6 +1170,34 @@ func (p *AddrPort) UnmarshalText(text []byte) error { return err } +// MarshalBinary implements the encoding.BinaryMarshaler interface. +// It returns Addr.MarshalBinary with an additional two bytes appended +// containing the port in little-endian. +func (p AddrPort) MarshalBinary() ([]byte, error) { + b, err := p.Addr().MarshalBinary() + if err != nil { + return nil, err + } + b = append(b, 0, 0) + lePutUint16(b[len(b)-2:], p.Port()) + return b, nil +} + +// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. +// It expects data in the form generated by MarshalBinary. +func (p *AddrPort) UnmarshalBinary(b []byte) error { + if len(b) < 2 { + return errors.New("unexpected slice size") + } + var addr Addr + err := addr.UnmarshalBinary(b[:len(b)-2]) + if err != nil { + return err + } + *p = AddrPortFrom(addr, leUint16(b[len(b)-2:])) + return nil +} + // Prefix is an IP address prefix (CIDR) representing an IP network. // // The first Bits() of Addr() are specified. The remaining bits match any address. @@ -1401,6 +1429,32 @@ func (p *Prefix) UnmarshalText(text []byte) error { return err } +// MarshalBinary implements the encoding.BinaryMarshaler interface. +// It returns Addr.MarshalBinary with an additional byte appended +// containing the prefix bits. +func (p Prefix) MarshalBinary() ([]byte, error) { + b, err := p.Addr().MarshalBinary() + if err != nil { + return nil, err + } + return append(b, uint8(p.Bits())), nil +} + +// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. +// It expects data in the form generated by MarshalBinary. +func (p *Prefix) UnmarshalBinary(b []byte) error { + if len(b) < 1 { + return errors.New("unexpected slice size") + } + var addr Addr + err := addr.UnmarshalBinary(b[:len(b)-1]) + if err != nil { + return err + } + *p = PrefixFrom(addr, int(b[len(b)-1])) + return nil +} + // String returns the CIDR notation of p: "/". func (p Prefix) String() string { if !p.IsValid() { diff --git a/src/net/netip/netip_test.go b/src/net/netip/netip_test.go index c39b1ec201..63af853cb3 100644 --- a/src/net/netip/netip_test.go +++ b/src/net/netip/netip_test.go @@ -25,6 +25,7 @@ type uint128 = Uint128 var ( mustPrefix = MustParsePrefix mustIP = MustParseAddr + mustIPPort = MustParseAddrPort ) func TestParseAddr(t *testing.T) { @@ -332,10 +333,91 @@ func TestAddrMarshalUnmarshalBinary(t *testing.T) { } // Cannot unmarshal from unexpected IP length. - for _, l := range []int{3, 5} { + for _, n := range []int{3, 5} { var ip2 Addr - if err := ip2.UnmarshalBinary(bytes.Repeat([]byte{1}, l)); err == nil { - t.Fatalf("unmarshaled from unexpected IP length %d", l) + if err := ip2.UnmarshalBinary(bytes.Repeat([]byte{1}, n)); err == nil { + t.Fatalf("unmarshaled from unexpected IP length %d", n) + } + } +} + +func TestAddrPortMarshalUnmarshalBinary(t *testing.T) { + tests := []struct { + ipport string + wantSize int + }{ + {"1.2.3.4:51820", 4 + 2}, + {"[fd7a:115c:a1e0:ab12:4843:cd96:626b:430b]:80", 16 + 2}, + {"[::ffff:c000:0280]:65535", 16 + 2}, + {"[::ffff:c000:0280%eth0]:1", 20 + 2}, + } + for _, tc := range tests { + var ipport AddrPort + if len(tc.ipport) > 0 { + ipport = mustIPPort(tc.ipport) + } + b, err := ipport.MarshalBinary() + if err != nil { + t.Fatal(err) + } + if len(b) != tc.wantSize { + t.Fatalf("%q encoded to size %d; want %d", tc.ipport, len(b), tc.wantSize) + } + var ipport2 AddrPort + if err := ipport2.UnmarshalBinary(b); err != nil { + t.Fatal(err) + } + if ipport != ipport2 { + t.Fatalf("got %v; want %v", ipport2, ipport) + } + } + + // Cannot unmarshal from unexpected lengths. + for _, n := range []int{3, 7} { + var ipport2 AddrPort + if err := ipport2.UnmarshalBinary(bytes.Repeat([]byte{1}, n)); err == nil { + t.Fatalf("unmarshaled from unexpected length %d", n) + } + } +} + +func TestPrefixMarshalUnmarshalBinary(t *testing.T) { + type testCase struct { + prefix Prefix + wantSize int + } + tests := []testCase{ + {mustPrefix("1.2.3.4/24"), 4 + 1}, + {mustPrefix("fd7a:115c:a1e0:ab12:4843:cd96:626b:430b/118"), 16 + 1}, + {mustPrefix("::ffff:c000:0280/96"), 16 + 1}, + {mustPrefix("::ffff:c000:0280%eth0/37"), 16 + 1}, // Zone should be stripped + } + tests = append(tests, + testCase{PrefixFrom(tests[0].prefix.Addr(), 33), tests[0].wantSize}, + testCase{PrefixFrom(tests[1].prefix.Addr(), 129), tests[1].wantSize}) + for _, tc := range tests { + prefix := tc.prefix + b, err := prefix.MarshalBinary() + if err != nil { + t.Fatal(err) + } + if len(b) != tc.wantSize { + t.Fatalf("%q encoded to size %d; want %d", tc.prefix, len(b), tc.wantSize) + } + var prefix2 Prefix + if err := prefix2.UnmarshalBinary(b); err != nil { + t.Fatal(err) + } + if prefix != prefix2 { + t.Fatalf("got %v; want %v", prefix2, prefix) + } + } + + // Cannot unmarshal from unexpected lengths. + for _, n := range []int{3, 6} { + var prefix2 Prefix + if err := prefix2.UnmarshalBinary(bytes.Repeat([]byte{1}, n)); err == nil { + t.Fatalf("unmarshaled from unexpected length %d", n) } } } -- GitLab From feb024f4153395e5bbb2a51bb3d1ddc4f5b0d2dc Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Wed, 29 Sep 2021 11:31:01 -0700 Subject: [PATCH 2022/2500] crypto/x509: use platform verifier on darwin When VerifyOptions.Roots is nil, default to using the platform X.509 certificate verification APIs on darwin, rather than using the Go verifier. Since our oldest supported version of macOS is 10.12, we are able to use the modern verification APIs, and don't need to resort to the complex chain building trickery employed by chromium et al. Unfortunately there is not a clean way to programmatically add test roots to the system trust store that the builders would tolerate. The most obvious solution, using 'security add-trusted-cert' requires human interaction for authorization. We could also manually add anchors to the constructed SecTrustRef, but that would require adding a whole bunch of plumbing for test functionality, and would mean we weren't really testing the actual non-test path. The path I've chosen here is to just utilize existing valid, and purposefully invalid, trusted chains, from google.com and the badssl.com test suite. This requires external network access, but most accurately reflects real world contexts. This change removes the x509.SystemCertPool() functionality, which will be ammended in a follow-up change which supports the suggested hybrid pool approach described in #46287. Updates #46287 Fixes #42414 Fixes #38888 Fixes #35631 Fixes #19561 Change-Id: I17f0d6c5cb3ef8a1f2731ce3296478b28d30df46 Reviewed-on: https://go-review.googlesource.com/c/go/+/353132 Trust: Roland Shoemaker Run-TryBot: Roland Shoemaker Reviewed-by: Filippo Valsorda TryBot-Result: Go Bot --- src/crypto/x509/cert_pool.go | 2 + .../x509/internal/macos/corefoundation.go | 77 +++++ .../x509/internal/macos/corefoundation.s | 12 + src/crypto/x509/internal/macos/security.go | 118 ++++++++ src/crypto/x509/internal/macos/security.s | 18 ++ src/crypto/x509/root_darwin.go | 268 +++++------------- src/crypto/x509/root_darwin_test.go | 127 +++++++-- src/crypto/x509/verify.go | 4 +- src/crypto/x509/verify_test.go | 4 +- src/crypto/x509/x509_test.go | 4 +- 10 files changed, 409 insertions(+), 225 deletions(-) diff --git a/src/crypto/x509/cert_pool.go b/src/crypto/x509/cert_pool.go index bcc5db3b70..1886825b17 100644 --- a/src/crypto/x509/cert_pool.go +++ b/src/crypto/x509/cert_pool.go @@ -106,6 +106,8 @@ func SystemCertPool() (*CertPool, error) { if runtime.GOOS == "windows" { // Issue 16736, 18609: return nil, errors.New("crypto/x509: system root pool is not available on Windows") + } else if runtime.GOOS == "darwin" { + return nil, errors.New("crypto/x509: system root pool is not available on macOS") } if sysRoots := systemRootsPool(); sysRoots != nil { diff --git a/src/crypto/x509/internal/macos/corefoundation.go b/src/crypto/x509/internal/macos/corefoundation.go index a91131ac98..07db5c7527 100644 --- a/src/crypto/x509/internal/macos/corefoundation.go +++ b/src/crypto/x509/internal/macos/corefoundation.go @@ -14,6 +14,7 @@ import ( "internal/abi" "reflect" "runtime" + "time" "unsafe" ) @@ -35,11 +36,37 @@ func CFDataToSlice(data CFRef) []byte { return out } +// CFStringToString returns a Go string representation of the passed +// in CFString. +func CFStringToString(ref CFRef) string { + data := CFStringCreateExternalRepresentation(ref) + b := CFDataToSlice(data) + CFRelease(data) + return string(b) +} + +// TimeToCFDateRef converts a time.Time into an apple CFDateRef +func TimeToCFDateRef(t time.Time) CFRef { + secs := t.Sub(time.Date(2001, 1, 1, 0, 0, 0, 0, time.UTC)).Seconds() + ref := CFDateCreate(int(secs)) + return ref +} + type CFString CFRef const kCFAllocatorDefault = 0 const kCFStringEncodingUTF8 = 0x08000100 +//go:cgo_import_dynamic x509_CFDataCreate CFDataCreate "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" + +func BytesToCFData(b []byte) CFRef { + p := unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&b)).Data) + ret := syscall(abi.FuncPCABI0(x509_CFDataCreate_trampoline), kCFAllocatorDefault, uintptr(p), uintptr(len(b)), 0, 0, 0) + runtime.KeepAlive(p) + return CFRef(ret) +} +func x509_CFDataCreate_trampoline() + //go:cgo_import_dynamic x509_CFStringCreateWithBytes CFStringCreateWithBytes "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" // StringToCFString returns a copy of the UTF-8 contents of s as a new CFString. @@ -126,5 +153,55 @@ func CFRelease(ref CFRef) { } func x509_CFRelease_trampoline() +//go:cgo_import_dynamic x509_CFArrayCreateMutable CFArrayCreateMutable "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" + +func CFArrayCreateMutable() CFRef { + ret := syscall(abi.FuncPCABI0(x509_CFArrayCreateMutable_trampoline), kCFAllocatorDefault, 0, 0 /* kCFTypeArrayCallBacks */, 0, 0, 0) + return CFRef(ret) +} +func x509_CFArrayCreateMutable_trampoline() + +//go:cgo_import_dynamic x509_CFArrayAppendValue CFArrayAppendValue "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" + +func CFArrayAppendValue(array CFRef, val CFRef) { + syscall(abi.FuncPCABI0(x509_CFArrayAppendValue_trampoline), uintptr(array), uintptr(val), 0, 0, 0, 0) +} +func x509_CFArrayAppendValue_trampoline() + +//go:cgo_import_dynamic x509_CFDateCreate CFDateCreate "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" + +func CFDateCreate(seconds int) CFRef { + ret := syscall(abi.FuncPCABI0(x509_CFDateCreate_trampoline), kCFAllocatorDefault, uintptr(seconds), 0, 0, 0, 0) + return CFRef(ret) +} +func x509_CFDateCreate_trampoline() + +//go:cgo_import_dynamic x509_CFErrorCopyDescription CFErrorCopyDescription "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" + +func CFErrorCopyDescription(errRef CFRef) CFRef { + ret := syscall(abi.FuncPCABI0(x509_CFErrorCopyDescription_trampoline), uintptr(errRef), 0, 0, 0, 0, 0) + return CFRef(ret) +} +func x509_CFErrorCopyDescription_trampoline() + +//go:cgo_import_dynamic x509_CFStringCreateExternalRepresentation CFStringCreateExternalRepresentation "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" + +func CFStringCreateExternalRepresentation(strRef CFRef) CFRef { + ret := syscall(abi.FuncPCABI0(x509_CFStringCreateExternalRepresentation_trampoline), kCFAllocatorDefault, uintptr(strRef), kCFStringEncodingUTF8, 0, 0, 0) + return CFRef(ret) +} +func x509_CFStringCreateExternalRepresentation_trampoline() + // syscall is implemented in the runtime package (runtime/sys_darwin.go) func syscall(fn, a1, a2, a3, a4, a5, a6 uintptr) uintptr + +// ReleaseCFArray iterates through an array, releasing its contents, and then +// releases the array itself. This is necessary because we cannot, easily, set the +// CFArrayCallBacks argument when creating CFArrays. +func ReleaseCFArray(array CFRef) { + for i := 0; i < CFArrayGetCount(array); i++ { + ref := CFArrayGetValueAtIndex(array, i) + CFRelease(ref) + } + CFRelease(array) +} diff --git a/src/crypto/x509/internal/macos/corefoundation.s b/src/crypto/x509/internal/macos/corefoundation.s index cda2336c9d..376099caa3 100644 --- a/src/crypto/x509/internal/macos/corefoundation.s +++ b/src/crypto/x509/internal/macos/corefoundation.s @@ -28,3 +28,15 @@ TEXT ·x509_CFNumberGetValue_trampoline(SB),NOSPLIT,$0-0 JMP x509_CFNumberGetValue(SB) TEXT ·x509_CFEqual_trampoline(SB),NOSPLIT,$0-0 JMP x509_CFEqual(SB) +TEXT ·x509_CFArrayCreateMutable_trampoline(SB),NOSPLIT,$0-0 + JMP x509_CFArrayCreateMutable(SB) +TEXT ·x509_CFArrayAppendValue_trampoline(SB),NOSPLIT,$0-0 + JMP x509_CFArrayAppendValue(SB) +TEXT ·x509_CFDateCreate_trampoline(SB),NOSPLIT,$0-0 + JMP x509_CFDateCreate(SB) +TEXT ·x509_CFDataCreate_trampoline(SB),NOSPLIT,$0-0 + JMP x509_CFDataCreate(SB) +TEXT ·x509_CFErrorCopyDescription_trampoline(SB),NOSPLIT,$0-0 + JMP x509_CFErrorCopyDescription(SB) +TEXT ·x509_CFStringCreateExternalRepresentation_trampoline(SB),NOSPLIT,$0-0 + JMP x509_CFStringCreateExternalRepresentation(SB) diff --git a/src/crypto/x509/internal/macos/security.go b/src/crypto/x509/internal/macos/security.go index a560248e8b..2805076ccd 100644 --- a/src/crypto/x509/internal/macos/security.go +++ b/src/crypto/x509/internal/macos/security.go @@ -8,6 +8,7 @@ package macOS import ( "errors" + "fmt" "internal/abi" "strconv" "unsafe" @@ -29,6 +30,19 @@ const ( SecTrustSettingsResultUnspecified ) +type SecTrustResultType int32 + +const ( + SecTrustResultInvalid SecTrustResultType = iota + SecTrustResultProceed + SecTrustResultConfirm // deprecated + SecTrustResultDeny + SecTrustResultUnspecified + SecTrustResultRecoverableTrustFailure + SecTrustResultFatalTrustFailure + SecTrustResultOtherError +) + type SecTrustSettingsDomain int32 const ( @@ -115,3 +129,107 @@ func SecPolicyCopyProperties(policy CFRef) CFRef { return CFRef(ret) } func x509_SecPolicyCopyProperties_trampoline() + +//go:cgo_import_dynamic x509_SecTrustCreateWithCertificates SecTrustCreateWithCertificates "/System/Library/Frameworks/Security.framework/Versions/A/Security" + +func SecTrustCreateWithCertificates(certs CFRef, policies CFRef) (CFRef, error) { + var trustObj CFRef + ret := syscall(abi.FuncPCABI0(x509_SecTrustCreateWithCertificates_trampoline), uintptr(certs), uintptr(policies), + uintptr(unsafe.Pointer(&trustObj)), 0, 0, 0) + if int32(ret) != 0 { + return 0, OSStatus{"SecTrustCreateWithCertificates", int32(ret)} + } + return trustObj, nil +} +func x509_SecTrustCreateWithCertificates_trampoline() + +//go:cgo_import_dynamic x509_SecCertificateCreateWithData SecCertificateCreateWithData "/System/Library/Frameworks/Security.framework/Versions/A/Security" + +func SecCertificateCreateWithData(b []byte) CFRef { + data := BytesToCFData(b) + ret := syscall(abi.FuncPCABI0(x509_SecCertificateCreateWithData_trampoline), kCFAllocatorDefault, uintptr(data), 0, 0, 0, 0) + CFRelease(data) + return CFRef(ret) +} +func x509_SecCertificateCreateWithData_trampoline() + +//go:cgo_import_dynamic x509_SecPolicyCreateSSL SecPolicyCreateSSL "/System/Library/Frameworks/Security.framework/Versions/A/Security" + +func SecPolicyCreateSSL(name string) CFRef { + var hostname CFString + if name != "" { + hostname = StringToCFString(name) + defer CFRelease(CFRef(hostname)) + } + ret := syscall(abi.FuncPCABI0(x509_SecPolicyCreateSSL_trampoline), 1 /* true */, uintptr(hostname), 0, 0, 0, 0) + return CFRef(ret) +} +func x509_SecPolicyCreateSSL_trampoline() + +//go:cgo_import_dynamic x509_SecTrustSetVerifyDate SecTrustSetVerifyDate "/System/Library/Frameworks/Security.framework/Versions/A/Security" + +func SecTrustSetVerifyDate(trustObj CFRef, dateRef CFRef) error { + ret := syscall(abi.FuncPCABI0(x509_SecTrustSetVerifyDate_trampoline), uintptr(trustObj), uintptr(dateRef), 0, 0, 0, 0) + if int32(ret) != 0 { + return OSStatus{"SecTrustSetVerifyDate", int32(ret)} + } + return nil +} +func x509_SecTrustSetVerifyDate_trampoline() + +//go:cgo_import_dynamic x509_SecTrustEvaluate SecTrustEvaluate "/System/Library/Frameworks/Security.framework/Versions/A/Security" + +func SecTrustEvaluate(trustObj CFRef) (CFRef, error) { + var result CFRef + ret := syscall(abi.FuncPCABI0(x509_SecTrustEvaluate_trampoline), uintptr(trustObj), uintptr(unsafe.Pointer(&result)), 0, 0, 0, 0) + if int32(ret) != 0 { + return 0, OSStatus{"SecTrustEvaluate", int32(ret)} + } + return CFRef(result), nil +} +func x509_SecTrustEvaluate_trampoline() + +//go:cgo_import_dynamic x509_SecTrustGetResult SecTrustGetResult "/System/Library/Frameworks/Security.framework/Versions/A/Security" + +func SecTrustGetResult(trustObj CFRef, result CFRef) (CFRef, CFRef, error) { + var chain, info CFRef + ret := syscall(abi.FuncPCABI0(x509_SecTrustGetResult_trampoline), uintptr(trustObj), uintptr(unsafe.Pointer(&result)), + uintptr(unsafe.Pointer(&chain)), uintptr(unsafe.Pointer(&info)), 0, 0) + if int32(ret) != 0 { + return 0, 0, OSStatus{"SecTrustGetResult", int32(ret)} + } + return chain, info, nil +} +func x509_SecTrustGetResult_trampoline() + +//go:cgo_import_dynamic x509_SecTrustEvaluateWithError SecTrustEvaluateWithError "/System/Library/Frameworks/Security.framework/Versions/A/Security" + +func SecTrustEvaluateWithError(trustObj CFRef) error { + var errRef CFRef + ret := syscall(abi.FuncPCABI0(x509_SecTrustEvaluateWithError_trampoline), uintptr(trustObj), uintptr(unsafe.Pointer(&errRef)), 0, 0, 0, 0) + if int32(ret) != 1 { + errStr := CFErrorCopyDescription(errRef) + err := fmt.Errorf("x509: %s", CFStringToString(errStr)) + CFRelease(errRef) + CFRelease(errStr) + return err + } + return nil +} +func x509_SecTrustEvaluateWithError_trampoline() + +//go:cgo_import_dynamic x509_SecTrustGetCertificateCount SecTrustGetCertificateCount "/System/Library/Frameworks/Security.framework/Versions/A/Security" + +func SecTrustGetCertificateCount(trustObj CFRef) int { + ret := syscall(abi.FuncPCABI0(x509_SecTrustGetCertificateCount_trampoline), uintptr(trustObj), 0, 0, 0, 0, 0) + return int(ret) +} +func x509_SecTrustGetCertificateCount_trampoline() + +//go:cgo_import_dynamic x509_SecTrustGetCertificateAtIndex SecTrustGetCertificateAtIndex "/System/Library/Frameworks/Security.framework/Versions/A/Security" + +func SecTrustGetCertificateAtIndex(trustObj CFRef, i int) CFRef { + ret := syscall(abi.FuncPCABI0(x509_SecTrustGetCertificateAtIndex_trampoline), uintptr(trustObj), uintptr(i), 0, 0, 0, 0) + return CFRef(ret) +} +func x509_SecTrustGetCertificateAtIndex_trampoline() diff --git a/src/crypto/x509/internal/macos/security.s b/src/crypto/x509/internal/macos/security.s index 0038f25b27..9c1c133489 100644 --- a/src/crypto/x509/internal/macos/security.s +++ b/src/crypto/x509/internal/macos/security.s @@ -18,3 +18,21 @@ TEXT ·x509_SecTrustSettingsCopyTrustSettings_trampoline(SB),NOSPLIT,$0-0 JMP x509_SecTrustSettingsCopyTrustSettings(SB) TEXT ·x509_SecPolicyCopyProperties_trampoline(SB),NOSPLIT,$0-0 JMP x509_SecPolicyCopyProperties(SB) +TEXT ·x509_SecTrustCreateWithCertificates_trampoline(SB),NOSPLIT,$0-0 + JMP x509_SecTrustCreateWithCertificates(SB) +TEXT ·x509_SecCertificateCreateWithData_trampoline(SB),NOSPLIT,$0-0 + JMP x509_SecCertificateCreateWithData(SB) +TEXT ·x509_SecPolicyCreateSSL_trampoline(SB),NOSPLIT,$0-0 + JMP x509_SecPolicyCreateSSL(SB) +TEXT ·x509_SecTrustSetVerifyDate_trampoline(SB),NOSPLIT,$0-0 + JMP x509_SecTrustSetVerifyDate(SB) +TEXT ·x509_SecTrustEvaluate_trampoline(SB),NOSPLIT,$0-0 + JMP x509_SecTrustEvaluate(SB) +TEXT ·x509_SecTrustGetResult_trampoline(SB),NOSPLIT,$0-0 + JMP x509_SecTrustGetResult(SB) +TEXT ·x509_SecTrustEvaluateWithError_trampoline(SB),NOSPLIT,$0-0 + JMP x509_SecTrustEvaluateWithError(SB) +TEXT ·x509_SecTrustGetCertificateCount_trampoline(SB),NOSPLIT,$0-0 + JMP x509_SecTrustGetCertificateCount(SB) +TEXT ·x509_SecTrustGetCertificateAtIndex_trampoline(SB),NOSPLIT,$0-0 + JMP x509_SecTrustGetCertificateAtIndex(SB) diff --git a/src/crypto/x509/root_darwin.go b/src/crypto/x509/root_darwin.go index ef051efd31..eab046120f 100644 --- a/src/crypto/x509/root_darwin.go +++ b/src/crypto/x509/root_darwin.go @@ -7,233 +7,107 @@ package x509 import ( - "bytes" macOS "crypto/x509/internal/macos" - "fmt" - "internal/godebug" - "os" + "errors" ) -var debugDarwinRoots = godebug.Get("x509roots") == "1" - func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) { - return nil, nil -} - -func loadSystemRoots() (*CertPool, error) { - var trustedRoots []*Certificate - untrustedRoots := make(map[string]bool) - - // macOS has three trust domains: one for CAs added by users to their - // "login" keychain, one for CAs added by Admins to the "System" keychain, - // and one for the CAs that ship with the OS. - for _, domain := range []macOS.SecTrustSettingsDomain{ - macOS.SecTrustSettingsDomainUser, - macOS.SecTrustSettingsDomainAdmin, - macOS.SecTrustSettingsDomainSystem, - } { - certs, err := macOS.SecTrustSettingsCopyCertificates(domain) - if err == macOS.ErrNoTrustSettings { - continue - } else if err != nil { - return nil, err - } - defer macOS.CFRelease(certs) - - for i := 0; i < macOS.CFArrayGetCount(certs); i++ { - c := macOS.CFArrayGetValueAtIndex(certs, i) - cert, err := exportCertificate(c) + certs := macOS.CFArrayCreateMutable() + defer macOS.ReleaseCFArray(certs) + leaf := macOS.SecCertificateCreateWithData(c.Raw) + macOS.CFArrayAppendValue(certs, leaf) + if opts.Intermediates != nil { + for _, lc := range opts.Intermediates.lazyCerts { + c, err := lc.getCert() if err != nil { - if debugDarwinRoots { - fmt.Fprintf(os.Stderr, "crypto/x509: domain %d, certificate #%d: %v\n", domain, i, err) - } - continue - } - - var result macOS.SecTrustSettingsResult - if domain == macOS.SecTrustSettingsDomainSystem { - // Certs found in the system domain are always trusted. If the user - // configures "Never Trust" on such a cert, it will also be found in the - // admin or user domain, causing it to be added to untrustedRoots. - result = macOS.SecTrustSettingsResultTrustRoot - } else { - result, err = sslTrustSettingsResult(c) - if err != nil { - if debugDarwinRoots { - fmt.Fprintf(os.Stderr, "crypto/x509: trust settings for %v: %v\n", cert.Subject, err) - } - continue - } - if debugDarwinRoots { - fmt.Fprintf(os.Stderr, "crypto/x509: trust settings for %v: %d\n", cert.Subject, result) - } - } - - switch result { - // "Note the distinction between the results kSecTrustSettingsResultTrustRoot - // and kSecTrustSettingsResultTrustAsRoot: The former can only be applied to - // root (self-signed) certificates; the latter can only be applied to - // non-root certificates." - case macOS.SecTrustSettingsResultTrustRoot: - if isRootCertificate(cert) { - trustedRoots = append(trustedRoots, cert) - } - case macOS.SecTrustSettingsResultTrustAsRoot: - if !isRootCertificate(cert) { - trustedRoots = append(trustedRoots, cert) - } - - case macOS.SecTrustSettingsResultDeny: - // Add this certificate to untrustedRoots, which are subtracted - // from trustedRoots, so that we don't have to evaluate policies - // for every root in the system domain, but still apply user and - // admin policies that override system roots. - untrustedRoots[string(cert.Raw)] = true - - case macOS.SecTrustSettingsResultUnspecified: - // Certificates with unspecified trust should be added to a pool - // of intermediates for chain building, but we don't support it - // at the moment. This is Issue 35631. - - default: - if debugDarwinRoots { - fmt.Fprintf(os.Stderr, "crypto/x509: unknown trust setting for %v: %d\n", cert.Subject, result) - } + return nil, err } + sc := macOS.SecCertificateCreateWithData(c.Raw) + macOS.CFArrayAppendValue(certs, sc) } } - pool := NewCertPool() - for _, cert := range trustedRoots { - if !untrustedRoots[string(cert.Raw)] { - pool.AddCert(cert) - } - } - return pool, nil -} + policies := macOS.CFArrayCreateMutable() + defer macOS.ReleaseCFArray(policies) + sslPolicy := macOS.SecPolicyCreateSSL(opts.DNSName) + macOS.CFArrayAppendValue(policies, sslPolicy) -// exportCertificate returns a *Certificate for a SecCertificateRef. -func exportCertificate(cert macOS.CFRef) (*Certificate, error) { - data, err := macOS.SecItemExport(cert) + trustObj, err := macOS.SecTrustCreateWithCertificates(certs, policies) if err != nil { return nil, err } - defer macOS.CFRelease(data) - der := macOS.CFDataToSlice(data) + defer macOS.CFRelease(trustObj) - return ParseCertificate(der) -} + if !opts.CurrentTime.IsZero() { + dateRef := macOS.TimeToCFDateRef(opts.CurrentTime) + defer macOS.CFRelease(dateRef) + if err := macOS.SecTrustSetVerifyDate(trustObj, dateRef); err != nil { + return nil, err + } + } -// isRootCertificate reports whether Subject and Issuer match. -func isRootCertificate(cert *Certificate) bool { - return bytes.Equal(cert.RawSubject, cert.RawIssuer) -} + // TODO(roland): we may want to allow passing in SCTs via VerifyOptions and + // set them via SecTrustSetSignedCertificateTimestamps, since Apple will + // always enforce its SCT requirements, and there are still _some_ people + // using TLS or OCSP for that. -// sslTrustSettingsResult obtains the final kSecTrustSettingsResult value for a -// certificate in the user or admin domain, combining usage constraints for the -// SSL SecTrustSettingsPolicy, -// -// It ignores SecTrustSettingsKeyUsage and kSecTrustSettingsAllowedError, and -// doesn't support kSecTrustSettingsDefaultRootCertSetting. -// -// https://developer.apple.com/documentation/security/1400261-sectrustsettingscopytrustsetting -func sslTrustSettingsResult(cert macOS.CFRef) (macOS.SecTrustSettingsResult, error) { - // In Apple's implementation user trust settings override admin trust settings - // (which themselves override system trust settings). If SecTrustSettingsCopyTrustSettings - // fails, or returns a NULL trust settings, when looking for the user trust - // settings then fallback to checking the admin trust settings. - // - // See Security-59306.41.2/trust/headers/SecTrustSettings.h for a description of - // the trust settings overrides, and SecLegacyAnchorSourceCopyUsageConstraints in - // Security-59306.41.2/trust/trustd/SecCertificateSource.c for a concrete example - // of how Apple applies the override in the case of NULL trust settings, or non - // success errors. - trustSettings, err := macOS.SecTrustSettingsCopyTrustSettings(cert, macOS.SecTrustSettingsDomainUser) - if err != nil || trustSettings == 0 { - if debugDarwinRoots && err != macOS.ErrNoTrustSettings { - fmt.Fprintf(os.Stderr, "crypto/x509: SecTrustSettingsCopyTrustSettings for SecTrustSettingsDomainUser failed: %s\n", err) - } - trustSettings, err = macOS.SecTrustSettingsCopyTrustSettings(cert, macOS.SecTrustSettingsDomainAdmin) + if err := macOS.SecTrustEvaluateWithError(trustObj); err != nil { + return nil, err } - if err != nil || trustSettings == 0 { - // If there are neither user nor admin trust settings for a certificate returned - // from SecTrustSettingsCopyCertificates Apple returns kSecTrustSettingsResultInvalid, - // as this method is intended to return certificates _which have trust settings_. - // The most likely case for this being triggered is that the existing trust settings - // are invalid and cannot be properly parsed. In this case SecTrustSettingsCopyTrustSettings - // returns errSecInvalidTrustSettings. The existing cgo implementation returns - // kSecTrustSettingsResultUnspecified in this case, which mostly matches the Apple - // implementation because we don't do anything with certificates marked with this - // result. - // - // See SecPVCGetTrustSettingsResult in Security-59306.41.2/trust/trustd/SecPolicyServer.c - if debugDarwinRoots && err != macOS.ErrNoTrustSettings { - fmt.Fprintf(os.Stderr, "crypto/x509: SecTrustSettingsCopyTrustSettings for SecTrustSettingsDomainAdmin failed: %s\n", err) + + chain := [][]*Certificate{{}} + numCerts := macOS.SecTrustGetCertificateCount(trustObj) + for i := 0; i < numCerts; i++ { + certRef := macOS.SecTrustGetCertificateAtIndex(trustObj, i) + cert, err := exportCertificate(certRef) + if err != nil { + return nil, err } - return macOS.SecTrustSettingsResultUnspecified, nil + chain[0] = append(chain[0], cert) } - defer macOS.CFRelease(trustSettings) - - // "An empty trust settings array means 'always trust this certificate' with an - // overall trust setting for the certificate of kSecTrustSettingsResultTrustRoot." - if macOS.CFArrayGetCount(trustSettings) == 0 { - return macOS.SecTrustSettingsResultTrustRoot, nil + if len(chain[0]) == 0 { + // This should _never_ happen, but to be safe + return nil, errors.New("x509: macOS certificate verification internal error") } - isSSLPolicy := func(policyRef macOS.CFRef) bool { - properties := macOS.SecPolicyCopyProperties(policyRef) - defer macOS.CFRelease(properties) - if v, ok := macOS.CFDictionaryGetValueIfPresent(properties, macOS.SecPolicyOid); ok { - return macOS.CFEqual(v, macOS.CFRef(macOS.SecPolicyAppleSSL)) + if opts.DNSName != "" { + // If we have a DNS name, apply our own name verification + if err := chain[0][0].VerifyHostname(opts.DNSName); err != nil { + return nil, err } - return false } - for i := 0; i < macOS.CFArrayGetCount(trustSettings); i++ { - tSetting := macOS.CFArrayGetValueAtIndex(trustSettings, i) + keyUsages := opts.KeyUsages + if len(keyUsages) == 0 { + keyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth} + } - // First, check if this trust setting is constrained to a non-SSL policy. - if policyRef, ok := macOS.CFDictionaryGetValueIfPresent(tSetting, macOS.SecTrustSettingsPolicy); ok { - if !isSSLPolicy(policyRef) { - continue - } + // If any key usage is acceptable then we're done. + for _, usage := range keyUsages { + if usage == ExtKeyUsageAny { + return chain, nil } + } - // Then check if it is restricted to a hostname, so not a root. - if _, ok := macOS.CFDictionaryGetValueIfPresent(tSetting, macOS.SecTrustSettingsPolicyString); ok { - continue - } + if !checkChainForKeyUsage(chain[0], keyUsages) { + return nil, CertificateInvalidError{c, IncompatibleUsage, ""} + } - cfNum, ok := macOS.CFDictionaryGetValueIfPresent(tSetting, macOS.SecTrustSettingsResultKey) - // "If this key is not present, a default value of kSecTrustSettingsResultTrustRoot is assumed." - if !ok { - return macOS.SecTrustSettingsResultTrustRoot, nil - } - result, err := macOS.CFNumberGetValue(cfNum) - if err != nil { - return 0, err - } + return chain, nil +} - // If multiple dictionaries match, we are supposed to "OR" them, - // the semantics of which are not clear. Since TrustRoot and TrustAsRoot - // are mutually exclusive, Deny should probably override, and Invalid and - // Unspecified be overridden, approximate this by stopping at the first - // TrustRoot, TrustAsRoot or Deny. - switch r := macOS.SecTrustSettingsResult(result); r { - case macOS.SecTrustSettingsResultTrustRoot, - macOS.SecTrustSettingsResultTrustAsRoot, - macOS.SecTrustSettingsResultDeny: - return r, nil - } +// exportCertificate returns a *Certificate for a SecCertificateRef. +func exportCertificate(cert macOS.CFRef) (*Certificate, error) { + data, err := macOS.SecItemExport(cert) + if err != nil { + return nil, err } + defer macOS.CFRelease(data) + der := macOS.CFDataToSlice(data) - // If trust settings are present, but none of them match the policy... - // the docs don't tell us what to do. - // - // "Trust settings for a given use apply if any of the dictionaries in the - // certificate’s trust settings array satisfies the specified use." suggests - // that it's as if there were no trust settings at all, so we should maybe - // fallback to the admin trust settings? TODO(golang.org/issue/38888). + return ParseCertificate(der) +} - return macOS.SecTrustSettingsResultUnspecified, nil +func loadSystemRoots() (*CertPool, error) { + return nil, nil } diff --git a/src/crypto/x509/root_darwin_test.go b/src/crypto/x509/root_darwin_test.go index ae2bd02bf8..90a464f624 100644 --- a/src/crypto/x509/root_darwin_test.go +++ b/src/crypto/x509/root_darwin_test.go @@ -2,38 +2,121 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package x509 +package x509_test import ( - "os" - "os/exec" + "crypto/tls" + "crypto/x509" + "internal/testenv" "testing" "time" ) -func TestSystemRoots(t *testing.T) { - t0 := time.Now() - sysRoots, err := loadSystemRoots() // actual system roots - sysRootsDuration := time.Since(t0) - - if err != nil { - t.Fatalf("failed to read system roots: %v", err) +func TestPlatformVerifier(t *testing.T) { + if !testenv.HasExternalNetwork() { + t.Skip() } - t.Logf("loadSystemRoots: %v", sysRootsDuration) + getChain := func(host string) []*x509.Certificate { + t.Helper() + c, err := tls.Dial("tcp", host+":443", &tls.Config{InsecureSkipVerify: true}) + if err != nil { + t.Fatalf("tls connection failed: %s", err) + } + return c.ConnectionState().PeerCertificates + } - // There are 174 system roots on Catalina, and 163 on iOS right now, require - // at least 100 to make sure this is not completely broken. - if want, have := 100, sysRoots.len(); have < want { - t.Errorf("want at least %d system roots, have %d", want, have) + tests := []struct { + name string + host string + verifyName string + verifyTime time.Time + verifyEKU []x509.ExtKeyUsage + expectedErr string + }{ + { + // whatever google.com serves should, hopefully, be trusted + name: "valid chain", + host: "google.com", + }, + { + name: "expired leaf", + host: "expired.badssl.com", + expectedErr: "x509: “*.badssl.com” certificate is expired", + }, + { + name: "wrong host for leaf", + host: "wrong.host.badssl.com", + verifyName: "wrong.host.badssl.com", + expectedErr: "x509: “*.badssl.com” certificate name does not match input", + }, + { + name: "self-signed leaf", + host: "self-signed.badssl.com", + expectedErr: "x509: “*.badssl.com” certificate is not trusted", + }, + { + name: "untrusted root", + host: "untrusted-root.badssl.com", + expectedErr: "x509: “BadSSL Untrusted Root Certificate Authority” certificate is not trusted", + }, + { + name: "revoked leaf", + host: "revoked.badssl.com", + expectedErr: "x509: “revoked.badssl.com” certificate is revoked", + }, + { + name: "leaf missing SCTs", + host: "no-sct.badssl.com", + expectedErr: "x509: “no-sct.badssl.com” certificate is not standards compliant", + }, + { + name: "expired leaf (custom time)", + host: "google.com", + verifyTime: time.Time{}.Add(time.Hour), + expectedErr: "x509: “*.google.com” certificate is expired", + }, + { + name: "valid chain (custom time)", + host: "google.com", + verifyTime: time.Now(), + }, + { + name: "leaf doesn't have acceptable ExtKeyUsage", + host: "google.com", + expectedErr: "x509: certificate specifies an incompatible key usage", + verifyEKU: []x509.ExtKeyUsage{x509.ExtKeyUsageEmailProtection}, + }, } - if t.Failed() { - cmd := exec.Command("security", "dump-trust-settings") - cmd.Stdout, cmd.Stderr = os.Stderr, os.Stderr - cmd.Run() - cmd = exec.Command("security", "dump-trust-settings", "-d") - cmd.Stdout, cmd.Stderr = os.Stderr, os.Stderr - cmd.Run() + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + chain := getChain(tc.host) + var opts x509.VerifyOptions + if len(chain) > 1 { + opts.Intermediates = x509.NewCertPool() + for _, c := range chain[1:] { + opts.Intermediates.AddCert(c) + } + } + if tc.verifyName != "" { + opts.DNSName = tc.verifyName + } + if !tc.verifyTime.IsZero() { + opts.CurrentTime = tc.verifyTime + } + if len(tc.verifyEKU) > 0 { + opts.KeyUsages = tc.verifyEKU + } + + _, err := chain[0].Verify(opts) + if err != nil && tc.expectedErr == "" { + t.Errorf("unexpected verification error: %s", err) + } else if err != nil && err.Error() != tc.expectedErr { + t.Errorf("unexpected verification error: got %q, want %q", err.Error(), tc.expectedErr) + } else if err == nil && tc.expectedErr != "" { + t.Errorf("unexpected verification success: want %q", tc.expectedErr) + } + }) } } diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go index 8aff53afa1..1822a609da 100644 --- a/src/crypto/x509/verify.go +++ b/src/crypto/x509/verify.go @@ -741,8 +741,8 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e } } - // Use Windows's own verification and chain building. - if opts.Roots == nil && runtime.GOOS == "windows" { + // Use platform verifiers, where available + if opts.Roots == nil && (runtime.GOOS == "windows" || runtime.GOOS == "darwin") { return c.systemVerify(&opts) } diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go index b9b71f4c1e..5b3bf9340a 100644 --- a/src/crypto/x509/verify_test.go +++ b/src/crypto/x509/verify_test.go @@ -1836,8 +1836,8 @@ func TestLongChain(t *testing.T) { } func TestSystemRootsError(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("Windows does not use (or support) systemRoots") + if runtime.GOOS == "windows" || runtime.GOOS == "darwin" { + t.Skip("Windows and darwin do not use (or support) systemRoots") } defer func(oldSystemRoots *CertPool) { systemRoots = oldSystemRoots }(systemRootsPool()) diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go index affab3789d..949bd7f08b 100644 --- a/src/crypto/x509/x509_test.go +++ b/src/crypto/x509/x509_test.go @@ -1975,8 +1975,8 @@ func TestMultipleRDN(t *testing.T) { } func TestSystemCertPool(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("not implemented on Windows; Issue 16736, 18609") + if runtime.GOOS == "windows" || runtime.GOOS == "darwin" { + t.Skip("not implemented on Windows (Issue 16736, 18609) or darwin (Issue 46287)") } a, err := SystemCertPool() if err != nil { -- GitLab From 87a3fc518a462a6bef4c395ec5af26f2cdc41207 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Wed, 3 Nov 2021 15:16:01 +0100 Subject: [PATCH 2023/2500] net/netip: reduce allocations in MarshalBinary Addr's MarshalBinary required two allocations in the case of a zone existing, and AddrPort and Prefix both required three. This refactors things slightly so that each marshal function only needs a single allocation. Change-Id: I9bde9969fedc1cad64bebb607188c4287f6a0d01 Reviewed-on: https://go-review.googlesource.com/c/go/+/361054 Trust: Jason A. Donenfeld Run-TryBot: Jason A. Donenfeld TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/net/netip/netip.go | 47 +++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/src/net/netip/netip.go b/src/net/netip/netip.go index 90672e045d..e6e90f11db 100644 --- a/src/net/netip/netip.go +++ b/src/net/netip/netip.go @@ -962,25 +962,30 @@ func (ip *Addr) UnmarshalText(text []byte) error { return err } -// MarshalBinary implements the encoding.BinaryMarshaler interface. -// It returns a zero-length slice for the zero Addr, -// the 4-byte form for an IPv4 address, -// and the 16-byte form with zone appended for an IPv6 address. -func (ip Addr) MarshalBinary() ([]byte, error) { +func (ip Addr) marshalBinaryWithTrailingBytes(trailingBytes int) []byte { + var b []byte switch ip.z { case z0: - return nil, nil + b = make([]byte, trailingBytes) case z4: - b := ip.As4() - return b[:], nil + b = make([]byte, 4+trailingBytes) + bePutUint32(b, uint32(ip.addr.lo)) default: - b16 := ip.As16() - b := b16[:] - if z := ip.Zone(); z != "" { - b = append(b, []byte(z)...) - } - return b, nil + z := ip.Zone() + b = make([]byte, 16+len(z)+trailingBytes) + bePutUint64(b[:8], ip.addr.hi) + bePutUint64(b[8:], ip.addr.lo) + copy(b[16:], z) } + return b +} + +// MarshalBinary implements the encoding.BinaryMarshaler interface. +// It returns a zero-length slice for the zero Addr, +// the 4-byte form for an IPv4 address, +// and the 16-byte form with zone appended for an IPv6 address. +func (ip Addr) MarshalBinary() ([]byte, error) { + return ip.marshalBinaryWithTrailingBytes(0), nil } // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. @@ -1174,11 +1179,7 @@ func (p *AddrPort) UnmarshalText(text []byte) error { // It returns Addr.MarshalBinary with an additional two bytes appended // containing the port in little-endian. func (p AddrPort) MarshalBinary() ([]byte, error) { - b, err := p.Addr().MarshalBinary() - if err != nil { - return nil, err - } - b = append(b, 0, 0) + b := p.Addr().marshalBinaryWithTrailingBytes(2) lePutUint16(b[len(b)-2:], p.Port()) return b, nil } @@ -1433,11 +1434,9 @@ func (p *Prefix) UnmarshalText(text []byte) error { // It returns Addr.MarshalBinary with an additional byte appended // containing the prefix bits. func (p Prefix) MarshalBinary() ([]byte, error) { - b, err := p.Addr().MarshalBinary() - if err != nil { - return nil, err - } - return append(b, uint8(p.Bits())), nil + b := p.Addr().withoutZone().marshalBinaryWithTrailingBytes(1) + b[len(b)-1] = uint8(p.Bits()) + return b, nil } // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. -- GitLab From b07c41d2c1c8d5729250a13b7c560c150c1d9011 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Wed, 3 Nov 2021 16:46:44 +0100 Subject: [PATCH 2024/2500] net/netip: add IPv4Unspecified There is IPv6Unspecified but there is not IPv4Unspecified, making for inconsistent code. This commit adds the missing function. Updates #49298. Change-Id: Id2519b646323642f59fb1cc6ea8e335fdde16290 Reviewed-on: https://go-review.googlesource.com/c/go/+/361056 Trust: Jason A. Donenfeld Trust: Brad Fitzpatrick Run-TryBot: Jason A. Donenfeld TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/net/netip/netip.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/net/netip/netip.go b/src/net/netip/netip.go index e6e90f11db..1596acbb8e 100644 --- a/src/net/netip/netip.go +++ b/src/net/netip/netip.go @@ -75,6 +75,9 @@ func IPv6LinkLocalAllNodes() Addr { return AddrFrom16([16]byte{0: 0xff, 1: 0x02, // IPv6Unspecified returns the IPv6 unspecified address "::". func IPv6Unspecified() Addr { return Addr{z: z6noz} } +// IPv4Unspecified returns the IPv4 unspecified address "0.0.0.0". +func IPv4Unspecified() Addr { return AddrFrom4([4]byte{}) } + // AddrFrom4 returns the address of the IPv4 address given by the bytes in addr. func AddrFrom4(addr [4]byte) Addr { return Addr{ @@ -595,7 +598,7 @@ func (ip Addr) IsGlobalUnicast() bool { // Match package net's IsGlobalUnicast logic. Notably private IPv4 addresses // and ULA IPv6 addresses are still considered "global unicast". - if ip.Is4() && (ip == AddrFrom4([4]byte{}) || ip == AddrFrom4([4]byte{255, 255, 255, 255})) { + if ip.Is4() && (ip == IPv4Unspecified() || ip == AddrFrom4([4]byte{255, 255, 255, 255})) { return false } @@ -633,7 +636,7 @@ func (ip Addr) IsPrivate() bool { // // Note that the zero Addr is not an unspecified address. func (ip Addr) IsUnspecified() bool { - return ip == AddrFrom4([4]byte{}) || ip == IPv6Unspecified() + return ip == IPv4Unspecified() || ip == IPv6Unspecified() } // Prefix keeps only the top b bits of IP, producing a Prefix -- GitLab From 3b7e376df87fa5255c7aa58d5719593b314338fd Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Fri, 5 Nov 2021 15:34:20 -0700 Subject: [PATCH 2025/2500] net/netip: add tests for Addr.AsSlice Change-Id: Ib88dd101b3bbdf4d2bfd79838994cfadef1b604d Reviewed-on: https://go-review.googlesource.com/c/go/+/361915 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder Reviewed-by: Brad Fitzpatrick TryBot-Result: Go Bot --- src/net/netip/netip_test.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/net/netip/netip_test.go b/src/net/netip/netip_test.go index 63af853cb3..a6327f0dea 100644 --- a/src/net/netip/netip_test.go +++ b/src/net/netip/netip_test.go @@ -1889,6 +1889,24 @@ func TestInvalidAddrPortString(t *testing.T) { } } +func TestAsSlice(t *testing.T) { + tests := []struct { + in Addr + want []byte + }{ + {in: Addr{}, want: nil}, + {in: mustIP("1.2.3.4"), want: []byte{1, 2, 3, 4}}, + {in: mustIP("ffff::1"), want: []byte{0xff, 0xff, 15: 1}}, + } + + for _, test := range tests { + got := test.in.AsSlice() + if !bytes.Equal(got, test.want) { + t.Errorf("%v.AsSlice() = %v want %v", test.in, got, test.want) + } + } +} + var sink16 [16]byte func BenchmarkAs16(b *testing.B) { -- GitLab From ba79c1e24198c2222e3bfe350326a8962fee0441 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Fri, 5 Nov 2021 18:40:03 -0400 Subject: [PATCH 2026/2500] doc/go1.18: split bytes and strings packages A small touchup after CL 361894. For #47694. Change-Id: Ifc161516f897f727195d21351a3c8eda7b6e327e Reviewed-on: https://go-review.googlesource.com/c/go/+/361895 Trust: Dmitri Shuralyov Reviewed-by: Carlos Amedee Reviewed-by: Michael Knyszek Run-TryBot: Carlos Amedee --- doc/go1.18.html | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 55a1de3bd8..b86e907874 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -115,7 +115,7 @@ Do not send CLs removing the interior tags from such phrases.

- TODO: https://golang.org/cl/349595: https://golang.org/cl/349595: cmd/go: add GOAMD64 environment variable + TODO: https://golang.org/cl/349595: cmd/go: add GOAMD64 environment variable

gofmt

@@ -135,17 +135,17 @@ Do not send CLs removing the interior tags from such phrases.

Compiler

- TODO: https://golang.org/cl/298611: https://golang.org/cl/298611: cmd/compile: add -asan option + TODO: https://golang.org/cl/298611: cmd/compile: add -asan option

- TODO: https://golang.org/cl/352057: https://golang.org/cl/352057: cmd/compile, runtime: track argument stack slot liveness + TODO: https://golang.org/cl/352057: cmd/compile, runtime: track argument stack slot liveness

Linker

- TODO: https://golang.org/cl/298610: https://golang.org/cl/298610: cmd/link: add -asan option + TODO: https://golang.org/cl/298610: cmd/link: add -asan option

Core library

@@ -209,6 +209,14 @@ Do not send CLs removing the interior tags from such phrases.
+
bytes
+
+

+ TODO: https://golang.org/cl/332771: avoid allocations in Trim/TrimLeft/TrimRight +

+
+
+
crypto/tls

@@ -330,16 +338,12 @@ Do not send CLs removing the interior tags from such phrases.

TODO: https://golang.org/cl/345849: add Clone function

-
-
-
strings,bytes
-

TODO: https://golang.org/cl/332771: avoid allocations in Trim/TrimLeft/TrimRight

-
+
sync
-- GitLab From e83a2047e0332e45c20fb1bcdb984e9cc74ffb1f Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Fri, 5 Nov 2021 14:55:52 -0700 Subject: [PATCH 2027/2500] net/netip: document the zero Addr Fixes #49364 Change-Id: I3372f80723a4deae48ef106f88b0ad880cdd0e45 Reviewed-on: https://go-review.googlesource.com/c/go/+/361914 Trust: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder Reviewed-by: Brad Fitzpatrick --- src/net/netip/netip.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/net/netip/netip.go b/src/net/netip/netip.go index 1596acbb8e..01f6fe5efa 100644 --- a/src/net/netip/netip.go +++ b/src/net/netip/netip.go @@ -32,6 +32,9 @@ import ( // // Unlike net.IP or net.IPAddr, Addr is a comparable value // type (it supports == and can be a map key) and is immutable. +// +// The zero Addr is not a valid IP address. +// Addr{} is distinct from both 0.0.0.0 and ::. type Addr struct { // addr is the hi and lo bits of an IPv6 address. If z==z4, // hi and lo contain the IPv4-mapped IPv6 address. -- GitLab From 2f71c86370a2c3bf2827e8d9f9080d9bf92a5317 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Thu, 21 Oct 2021 21:19:23 +0000 Subject: [PATCH 2028/2500] runtime: retype gcControllerState.gcPercent as atomic.Int32 [git-generate] cd src/runtime mv export_test.go export.go GOROOT=$(dirname $(dirname $PWD)) rf ' add gcControllerState.gcPercent \ // Initialized from GOGC. GOGC=off means no GC. \ gcPercent_ atomic.Int32 ex { import "runtime/internal/atomic" var t gcControllerState var v, w int32 var d int32 t.gcPercent -> t.gcPercent_.Load() t.gcPercent = v -> t.gcPercent_.Store(v) atomic.Loadint32(&t.gcPercent) -> t.gcPercent_.Load() atomic.Storeint32(&t.gcPercent, v) -> t.gcPercent_.Store(v) atomic.Xaddint32(&t.gcPercent, d) -> t.gcPercent_.Add(d) atomic.Casint32(&t.gcPercent, v, w) -> t.gcPercent_.CompareAndSwap(v, w) atomic.Xchgint32(&t.gcPercent, v) -> t.gcPercent_.Swap(v) } rm gcControllerState.gcPercent mv gcControllerState.gcPercent_ gcControllerState.gcPercent ' mv export.go export_test.go Change-Id: I1aae34a3f782d096c6b6233bbf7986e67ce9c5f9 Reviewed-on: https://go-review.googlesource.com/c/go/+/357794 Trust: Michael Knyszek Reviewed-by: Michael Pratt --- src/runtime/mgc.go | 2 +- src/runtime/mgcpacer.go | 31 ++++++++++++++----------------- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go index 96f4157b59..d75893dc43 100644 --- a/src/runtime/mgc.go +++ b/src/runtime/mgc.go @@ -545,7 +545,7 @@ func (t gcTrigger) test() bool { // own write. return gcController.heapLive >= gcController.trigger case gcTriggerTime: - if atomic.Loadint32(&gcController.gcPercent) < 0 { + if gcController.gcPercent.Load() < 0 { return false } lastgc := int64(atomic.Load64(&memstats.last_gc_nanotime)) diff --git a/src/runtime/mgcpacer.go b/src/runtime/mgcpacer.go index 5b699cb298..525f33a0cd 100644 --- a/src/runtime/mgcpacer.go +++ b/src/runtime/mgcpacer.go @@ -84,12 +84,9 @@ func init() { var gcController gcControllerState type gcControllerState struct { - // Initialized from $GOGC. GOGC=off means no GC. - // - // Updated atomically with mheap_.lock held or during a STW. - // Safe to read atomically at any time, or non-atomically with - // mheap_.lock or STW. - gcPercent int32 + + // Initialized from GOGC. GOGC=off means no GC. + gcPercent atomic.Int32 _ uint32 // padding so following 64-bit values are 8-byte aligned @@ -479,7 +476,7 @@ func (c *gcControllerState) startCycle(markStartTime int64, procs int) { // is when assists are enabled and the necessary statistics are // available). func (c *gcControllerState) revise() { - gcPercent := atomic.Loadint32(&c.gcPercent) + gcPercent := c.gcPercent.Load() if gcPercent < 0 { // If GC is disabled but we're running a forced GC, // act like GOGC is huge for the below calculations. @@ -969,8 +966,8 @@ func (c *gcControllerState) commit(triggerRatio float64) { // has grown by GOGC/100 over where it started the last cycle, // plus additional runway for non-heap sources of GC work. goal := ^uint64(0) - if c.gcPercent >= 0 { - goal = c.heapMarked + (c.heapMarked+atomic.Load64(&c.stackScan)+atomic.Load64(&c.globalsScan))*uint64(c.gcPercent)/100 + if c.gcPercent.Load() >= 0 { + goal = c.heapMarked + (c.heapMarked+atomic.Load64(&c.stackScan)+atomic.Load64(&c.globalsScan))*uint64(c.gcPercent.Load())/100 } // Don't trigger below the minimum heap size. @@ -1088,13 +1085,13 @@ func (c *gcControllerState) oldCommit(triggerRatio float64) { // has grown by GOGC/100 over the heap marked by the last // cycle. goal := ^uint64(0) - if c.gcPercent >= 0 { - goal = c.heapMarked + c.heapMarked*uint64(c.gcPercent)/100 + if c.gcPercent.Load() >= 0 { + goal = c.heapMarked + c.heapMarked*uint64(c.gcPercent.Load())/100 } // Set the trigger ratio, capped to reasonable bounds. - if c.gcPercent >= 0 { - scalingFactor := float64(c.gcPercent) / 100 + if c.gcPercent.Load() >= 0 { + scalingFactor := float64(c.gcPercent.Load()) / 100 // Ensure there's always a little margin so that the // mutator assist ratio isn't infinity. maxTriggerRatio := 0.95 * scalingFactor @@ -1134,7 +1131,7 @@ func (c *gcControllerState) oldCommit(triggerRatio float64) { // We trigger the next GC cycle when the allocated heap has // grown by the trigger ratio over the marked heap size. trigger := ^uint64(0) - if c.gcPercent >= 0 { + if c.gcPercent.Load() >= 0 { trigger = uint64(float64(c.heapMarked) * (1 + triggerRatio)) // Don't trigger below the minimum heap size. minTrigger := c.heapMinimum @@ -1210,13 +1207,13 @@ func (c *gcControllerState) setGCPercent(in int32) int32 { assertWorldStoppedOrLockHeld(&mheap_.lock) } - out := c.gcPercent + out := c.gcPercent.Load() if in < 0 { in = -1 } // Write it atomically so readers like revise() can read it safely. - atomic.Storeint32(&c.gcPercent, in) - c.heapMinimum = defaultHeapMinimum * uint64(c.gcPercent) / 100 + c.gcPercent.Store(in) + c.heapMinimum = defaultHeapMinimum * uint64(c.gcPercent.Load()) / 100 // Update pacing in response to gcPercent change. c.commit(c.triggerRatio) -- GitLab From 09e8de70c2ee36d99ba02389da0fe2e203879022 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Thu, 21 Oct 2021 21:26:50 +0000 Subject: [PATCH 2029/2500] runtime: eliminate rendundant loads gcPercent The previous change was an automated change that made gcPercent a type-safe atomic variable. However, that introduced a lot of redundant formal atomic loads of the variable. Remove them by only loading once in each case, and reusing the value. Change-Id: I49647135f423574f94506d456d1cc390150fad02 Reviewed-on: https://go-review.googlesource.com/c/go/+/357795 Trust: Michael Knyszek Reviewed-by: Michael Pratt --- src/runtime/mgcpacer.go | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/runtime/mgcpacer.go b/src/runtime/mgcpacer.go index 525f33a0cd..868666036c 100644 --- a/src/runtime/mgcpacer.go +++ b/src/runtime/mgcpacer.go @@ -966,8 +966,8 @@ func (c *gcControllerState) commit(triggerRatio float64) { // has grown by GOGC/100 over where it started the last cycle, // plus additional runway for non-heap sources of GC work. goal := ^uint64(0) - if c.gcPercent.Load() >= 0 { - goal = c.heapMarked + (c.heapMarked+atomic.Load64(&c.stackScan)+atomic.Load64(&c.globalsScan))*uint64(c.gcPercent.Load())/100 + if gcPercent := c.gcPercent.Load(); gcPercent >= 0 { + goal = c.heapMarked + (c.heapMarked+atomic.Load64(&c.stackScan)+atomic.Load64(&c.globalsScan))*uint64(gcPercent)/100 } // Don't trigger below the minimum heap size. @@ -1081,17 +1081,19 @@ func (c *gcControllerState) commit(triggerRatio float64) { // // For !goexperiment.PacerRedesign. func (c *gcControllerState) oldCommit(triggerRatio float64) { + gcPercent := c.gcPercent.Load() + // Compute the next GC goal, which is when the allocated heap // has grown by GOGC/100 over the heap marked by the last // cycle. goal := ^uint64(0) - if c.gcPercent.Load() >= 0 { - goal = c.heapMarked + c.heapMarked*uint64(c.gcPercent.Load())/100 + if gcPercent >= 0 { + goal = c.heapMarked + c.heapMarked*uint64(gcPercent)/100 } // Set the trigger ratio, capped to reasonable bounds. - if c.gcPercent.Load() >= 0 { - scalingFactor := float64(c.gcPercent.Load()) / 100 + if gcPercent >= 0 { + scalingFactor := float64(gcPercent) / 100 // Ensure there's always a little margin so that the // mutator assist ratio isn't infinity. maxTriggerRatio := 0.95 * scalingFactor @@ -1131,7 +1133,7 @@ func (c *gcControllerState) oldCommit(triggerRatio float64) { // We trigger the next GC cycle when the allocated heap has // grown by the trigger ratio over the marked heap size. trigger := ^uint64(0) - if c.gcPercent.Load() >= 0 { + if gcPercent >= 0 { trigger = uint64(float64(c.heapMarked) * (1 + triggerRatio)) // Don't trigger below the minimum heap size. minTrigger := c.heapMinimum @@ -1211,9 +1213,8 @@ func (c *gcControllerState) setGCPercent(in int32) int32 { if in < 0 { in = -1 } - // Write it atomically so readers like revise() can read it safely. + c.heapMinimum = defaultHeapMinimum * uint64(in) / 100 c.gcPercent.Store(in) - c.heapMinimum = defaultHeapMinimum * uint64(c.gcPercent.Load()) / 100 // Update pacing in response to gcPercent change. c.commit(c.triggerRatio) -- GitLab From b74f2efc47bbfcc4aa301ebda1033948d8b6b63e Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Fri, 1 Oct 2021 09:14:10 -0700 Subject: [PATCH 2030/2500] crypto/x509: use the platform verifier on iOS Use the same certificate verification APIs on iOS as on macOS (they share the same APIs, so we should be able to transparently use them on both.) Updates #46287 Fixes #38843 Change-Id: If70f99b0823dd5fa747c42ff4f20c3b625605327 Reviewed-on: https://go-review.googlesource.com/c/go/+/353403 Trust: Roland Shoemaker Reviewed-by: Filippo Valsorda Run-TryBot: Roland Shoemaker --- src/cmd/dist/test.go | 11 - src/crypto/x509/cert_pool.go | 2 + src/crypto/x509/root_darwin.go | 2 - src/crypto/x509/root_ios.go | 4872 ----------------------------- src/crypto/x509/root_ios_gen.go | 180 -- src/crypto/x509/root_omit.go | 25 - src/crypto/x509/root_omit_test.go | 22 - src/crypto/x509/verify.go | 2 +- src/crypto/x509/verify_test.go | 2 +- src/crypto/x509/x509_test.go | 2 +- 10 files changed, 5 insertions(+), 5115 deletions(-) delete mode 100644 src/crypto/x509/root_ios.go delete mode 100644 src/crypto/x509/root_ios_gen.go delete mode 100644 src/crypto/x509/root_omit.go delete mode 100644 src/crypto/x509/root_omit_test.go diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index 98e30a158f..aea1ee6f25 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -499,17 +499,6 @@ func (t *tester) registerTests() { }) } - if t.iOS() && !t.compileOnly { - t.tests = append(t.tests, distTest{ - name: "x509omitbundledroots", - heading: "crypto/x509 without bundled roots", - fn: func(dt *distTest) error { - t.addCmd(dt, "src", t.goTest(), t.timeout(300), "-tags=x509omitbundledroots", "-run=OmitBundledRoots", "crypto/x509") - return nil - }, - }) - } - // Test ios/amd64 for the iOS simulator. if goos == "darwin" && goarch == "amd64" && t.cgoEnabled { t.tests = append(t.tests, distTest{ diff --git a/src/crypto/x509/cert_pool.go b/src/crypto/x509/cert_pool.go index 1886825b17..d760dc11c6 100644 --- a/src/crypto/x509/cert_pool.go +++ b/src/crypto/x509/cert_pool.go @@ -108,6 +108,8 @@ func SystemCertPool() (*CertPool, error) { return nil, errors.New("crypto/x509: system root pool is not available on Windows") } else if runtime.GOOS == "darwin" { return nil, errors.New("crypto/x509: system root pool is not available on macOS") + } else if runtime.GOOS == "ios" { + return nil, errors.New("crypto/x509: system root pool is not available on iOS") } if sysRoots := systemRootsPool(); sysRoots != nil { diff --git a/src/crypto/x509/root_darwin.go b/src/crypto/x509/root_darwin.go index eab046120f..7bc6ce09fa 100644 --- a/src/crypto/x509/root_darwin.go +++ b/src/crypto/x509/root_darwin.go @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build !ios - package x509 import ( diff --git a/src/crypto/x509/root_ios.go b/src/crypto/x509/root_ios.go deleted file mode 100644 index c5e3fc0b72..0000000000 --- a/src/crypto/x509/root_ios.go +++ /dev/null @@ -1,4872 +0,0 @@ -// Code generated by root_ios_gen.go -version 55188.120.1.0.1; DO NOT EDIT. -// Update the version in root.go and regenerate with "go generate". - -//go:build ios && !x509omitbundledroots - -package x509 - -func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) { - return nil, nil -} - -func loadSystemRoots() (*CertPool, error) { - p := NewCertPool() - p.AppendCertsFromPEM([]byte(systemRootsPEM)) - return p, nil -} - -const systemRootsPEM = ` -# "AAA Certificate Services" -# D7 A7 A0 FB 5D 7E 27 31 D7 71 E9 48 4E BC DE F7 -# 1D 5F 0C 3E 0A 29 48 78 2B C8 3E E0 EA 69 9E F4 ------BEGIN CERTIFICATE----- -MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb -MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow -GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj -YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL -MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE -BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM -GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua -BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe -3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 -YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR -rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm -ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU -oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF -MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v -QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t -b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF -AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q -GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz -Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 -G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi -l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 -smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== ------END CERTIFICATE----- -# "AC RAIZ FNMT-RCM" -# EB C5 57 0C 29 01 8C 4D 67 B1 AA 12 7B AF 12 F7 -# 03 B4 61 1E BC 17 B7 DA B5 57 38 94 17 9B 93 FA ------BEGIN CERTIFICATE----- -MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsx -CzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJ -WiBGTk1ULVJDTTAeFw0wODEwMjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJ -BgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBG -Tk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALpxgHpMhm5/ -yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcfqQgf -BBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAz -WHFctPVrbtQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxF -tBDXaEAUwED653cXeuYLj2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z -374jNUUeAlz+taibmSXaXvMiwzn15Cou08YfxGyqxRxqAQVKL9LFwag0Jl1mpdIC -IfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mwWsXmo8RZZUc1g16p6DUL -mbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnTtOmlcYF7 -wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peS -MKGJ47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2 -ZSysV4999AeU14ECll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMet -UqIJ5G+GR4of6ygnXYMgrwTJbFaai0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUw -AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFPd9xf3E6Jobd2Sn9R2gzL+H -YJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwOi8vd3d3 -LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD -nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1 -RXxlDPiyN8+sD8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYM -LVN0V2Ue1bLdI4E7pWYjJ2cJj+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf -77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrTQfv6MooqtyuGC2mDOL7Nii4LcK2N -JpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW+YJF1DngoABd15jm -fZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7Ixjp -6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp -1txyM/1d8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B -9kiABdcPUXmsEKvU7ANm5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wok -RqEIr9baRRmW1FMdW4R58MD3R++Lj8UGrp1MYp3/RgT408m2ECVAdf4WqslKYIYv -uu8wd+RU4riEmViAqhOLUTpPSPaLtrM= ------END CERTIFICATE----- -# "Actalis Authentication Root CA" -# 55 92 60 84 EC 96 3A 64 B9 6E 2A BE 01 CE 0B A8 -# 6A 64 FB FE BC C7 AA B5 AF C1 55 B3 7F D7 60 66 ------BEGIN CERTIFICATE----- -MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE -BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w -MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 -IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC -SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1 -ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB -MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv -UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX -4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9 -KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/ -gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb -rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ -51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F -be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe -KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F -v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn -fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7 -jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz -ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt -ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL -e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70 -jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz -WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V -SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j -pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX -X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok -fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R -K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU -ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU -LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT -LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== ------END CERTIFICATE----- -# "Admin-Root-CA" -# A3 1F 09 30 53 BD 12 C1 F5 C3 C6 EF D4 98 02 3F -# D2 91 4D 77 58 D0 5D 69 8C E0 84 B5 06 26 E0 E5 ------BEGIN CERTIFICATE----- -MIIFVTCCBD2gAwIBAgIEO/OB0DANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQGEwJj -aDEOMAwGA1UEChMFYWRtaW4xETAPBgNVBAsTCFNlcnZpY2VzMSIwIAYDVQQLExlD -ZXJ0aWZpY2F0aW9uIEF1dGhvcml0aWVzMRYwFAYDVQQDEw1BZG1pbi1Sb290LUNB -MB4XDTAxMTExNTA4NTEwN1oXDTIxMTExMDA3NTEwN1owbDELMAkGA1UEBhMCY2gx -DjAMBgNVBAoTBWFkbWluMREwDwYDVQQLEwhTZXJ2aWNlczEiMCAGA1UECxMZQ2Vy -dGlmaWNhdGlvbiBBdXRob3JpdGllczEWMBQGA1UEAxMNQWRtaW4tUm9vdC1DQTCC -ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMvgr0QUIv5qF0nyXZ3PXAJi -C4C5Wr+oVTN7oxIkXkxvO0GJToM9n7OVJjSmzBL0zJ2HXj0MDRcvhSY+KiZZc6Go -vDvr5Ua481l7ILFeQAFtumeza+vvxeL5Nd0Maga2miiacLNAKXbAcUYRa0Ov5VZB -++YcOYNNt/aisWbJqA2y8He+NsEgJzK5zNdayvYXQTZN+7tVgWOck16Da3+4FXdy -fH1NCWtZlebtMKtERtkVAaVbiWW24CjZKAiVfggjsiLo3yVMPGj3budLx5D9hEEm -vlyDOtcjebca+AcZglppWMX/iHIrx7740y0zd6cWEqiLIcZCrnpkr/KzwO135GkC -AwEAAaOCAf0wggH5MA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIASBkTCBjjCBiwYI -YIV0AREDAQAwfzArBggrBgEFBQcCAjAfGh1UaGlzIGlzIHRoZSBBZG1pbi1Sb290 -LUNBIENQUzBQBggrBgEFBQcCARZEaHR0cDovL3d3dy5pbmZvcm1hdGlrLmFkbWlu -LmNoL1BLSS9saW5rcy9DUFNfMl8xNl83NTZfMV8xN18zXzFfMC5wZGYwfwYDVR0f -BHgwdjB0oHKgcKRuMGwxFjAUBgNVBAMTDUFkbWluLVJvb3QtQ0ExIjAgBgNVBAsT -GUNlcnRpZmljYXRpb24gQXV0aG9yaXRpZXMxETAPBgNVBAsTCFNlcnZpY2VzMQ4w -DAYDVQQKEwVhZG1pbjELMAkGA1UEBhMCY2gwHQYDVR0OBBYEFIKf+iNzIPGXi7JM -Tb5CxX9mzWToMIGZBgNVHSMEgZEwgY6AFIKf+iNzIPGXi7JMTb5CxX9mzWTooXCk -bjBsMQswCQYDVQQGEwJjaDEOMAwGA1UEChMFYWRtaW4xETAPBgNVBAsTCFNlcnZp -Y2VzMSIwIAYDVQQLExlDZXJ0aWZpY2F0aW9uIEF1dGhvcml0aWVzMRYwFAYDVQQD -Ew1BZG1pbi1Sb290LUNBggQ784HQMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0B -AQUFAAOCAQEAeE96XCYRpy6umkPKXDWCRn7INo96ZrWpMggcDORuofHIwdTkgOeM -vWOxDN/yuT7CC3FAaUajbPRbDw0hRMcqKz0aC8CgwcyIyhw/rFK29mfNTG3EviP9 -QSsEbnelFnjpm1wjz4EaBiFjatwpUbI6+Zv3XbEt9QQXBn+c6DeFLe4xvC4B+MTr -a440xTk59pSYux8OHhEvqIwHCkiijGqZhTS3KmGFeBopaR+dJVBRBMoXwzk4B3Hn -0Zib1dEYFZa84vPJZyvxCbLOnPRDJgH6V2uQqbG+6DXVaf/wORVOvF/wzzv0viM/ -RWbEtJZdvo8N3sdtCULzifnxP/V0T9+4ZQ== ------END CERTIFICATE----- -# "AffirmTrust Commercial" -# 03 76 AB 1D 54 C5 F9 80 3C E4 B2 E2 01 A0 EE 7E -# EF 7B 57 B6 36 E8 A9 3C 9B 8D 48 60 C9 6F 5F A7 ------BEGIN CERTIFICATE----- -MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz -dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL -MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp -cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP -Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr -ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL -MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1 -yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr -VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/ -nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ -KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG -XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj -vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt -Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g -N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC -nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= ------END CERTIFICATE----- -# "AffirmTrust Networking" -# 0A 81 EC 5A 92 97 77 F1 45 90 4A F3 8D 5D 50 9F -# 66 B5 E2 C5 8F CD B5 31 05 8B 0E 17 F3 F0 B4 1B ------BEGIN CERTIFICATE----- -MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz -dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL -MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp -cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y -YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua -kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL -QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp -6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG -yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i -QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ -KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO -tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu -QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ -Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u -olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48 -x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= ------END CERTIFICATE----- -# "AffirmTrust Premium" -# 70 A7 3F 7F 37 6B 60 07 42 48 90 45 34 B1 14 82 -# D5 BF 0E 69 8E CC 49 8D F5 25 77 EB F2 E9 3B 9A ------BEGIN CERTIFICATE----- -MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz -dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG -A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U -cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf -qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ -JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ -+jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS -s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5 -HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7 -70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG -V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S -qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S -5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia -C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX -OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE -FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ -BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2 -KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg -Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B -8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ -MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc -0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ -u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF -u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH -YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8 -GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO -RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e -KeC2uAloGRwYQw== ------END CERTIFICATE----- -# "AffirmTrust Premium ECC" -# BD 71 FD F6 DA 97 E4 CF 62 D1 64 7A DD 25 81 B0 -# 7D 79 AD F8 39 7E B4 EC BA 9C 5E 84 88 82 14 23 ------BEGIN CERTIFICATE----- -MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC -VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ -cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ -BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt -VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D -0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9 -ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G -A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs -aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I -flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ== ------END CERTIFICATE----- -# "Amazon Root CA 1" -# 8E CD E6 88 4F 3D 87 B1 12 5B A3 1A C3 FC B1 3D -# 70 16 DE 7F 57 CC 90 4F E1 CB 97 C6 AE 98 19 6E ------BEGIN CERTIFICATE----- -MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF -ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 -b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL -MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv -b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj -ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM -9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw -IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 -VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L -93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm -jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA -A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI -U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs -N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv -o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU -5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy -rqXRfboQnoZsG4q5WTP468SQvvG5 ------END CERTIFICATE----- -# "Amazon Root CA 2" -# 1B A5 B2 AA 8C 65 40 1A 82 96 01 18 F8 0B EC 4F -# 62 30 4D 83 CE C4 71 3A 19 C3 9C 01 1E A4 6D B4 ------BEGIN CERTIFICATE----- -MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF -ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 -b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL -MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv -b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK -gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ -W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg -1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K -8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r -2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me -z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR -8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj -mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz -7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6 -+XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI -0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB -Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm -UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2 -LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY -+gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS -k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl -7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm -btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl -urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+ -fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63 -n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE -76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H -9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT -4PsJYGw= ------END CERTIFICATE----- -# "Amazon Root CA 3" -# 18 CE 6C FE 7B F1 4E 60 B2 E3 47 B8 DF E8 68 CB -# 31 D0 2E BB 3A DA 27 15 69 F5 03 43 B4 6D B3 A4 ------BEGIN CERTIFICATE----- -MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5 -MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g -Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG -A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg -Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl -ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j -QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr -ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr -BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM -YyRIHN8wfdVoOw== ------END CERTIFICATE----- -# "Amazon Root CA 4" -# E3 5D 28 41 9E D0 20 25 CF A6 90 38 CD 62 39 62 -# 45 8D A5 C6 95 FB DE A3 C2 2B 0B FB 25 89 70 92 ------BEGIN CERTIFICATE----- -MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5 -MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g -Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG -A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg -Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi -9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk -M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB -/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB -MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw -CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW -1KyLa2tJElMzrdfkviT8tQp21KW8EA== ------END CERTIFICATE----- -# "ANF Global Root CA" -# E3 26 8F 61 06 BA 8B 66 5A 1A 96 2D DE A1 45 9D -# 2A 46 97 2F 1F 24 40 32 9B 39 0B 89 57 49 AD 45 ------BEGIN CERTIFICATE----- -MIIIGDCCBgCgAwIBAgIGAT8vMXfmMA0GCSqGSIb3DQEBCwUAMIIBCjELMAkGA1UE -BhMCRVMxEjAQBgNVBAgMCUJhcmNlbG9uYTFYMFYGA1UEBwxPQmFyY2Vsb25hIChz -ZWUgY3VycmVudCBhZGRyZXNzIGF0IGh0dHA6Ly93d3cuYW5mLmVzL2VzL2FkZHJl -c3MtZGlyZWNjaW9uLmh0bWwgKTEnMCUGA1UECgweQU5GIEF1dG9yaWRhZCBkZSBD -ZXJ0aWZpY2FjaW9uMRcwFQYDVQQLDA5BTkYgQ2xhc2UgMSBDQTEaMBgGCSqGSIb3 -DQEJARYLaW5mb0BhbmYuZXMxEjAQBgNVBAUTCUc2MzI4NzUxMDEbMBkGA1UEAwwS -QU5GIEdsb2JhbCBSb290IENBMB4XDTEzMDYxMDE3NDUzOFoXDTMzMDYwNTE3NDUz -OFowggEKMQswCQYDVQQGEwJFUzESMBAGA1UECAwJQmFyY2Vsb25hMVgwVgYDVQQH -DE9CYXJjZWxvbmEgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgaHR0cDovL3d3dy5h -bmYuZXMvZXMvYWRkcmVzcy1kaXJlY2Npb24uaHRtbCApMScwJQYDVQQKDB5BTkYg -QXV0b3JpZGFkIGRlIENlcnRpZmljYWNpb24xFzAVBgNVBAsMDkFORiBDbGFzZSAx -IENBMRowGAYJKoZIhvcNAQkBFgtpbmZvQGFuZi5lczESMBAGA1UEBRMJRzYzMjg3 -NTEwMRswGQYDVQQDDBJBTkYgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEB -AQUAA4ICDwAwggIKAoICAQDHPi9xy4wynbcUbWjorVUgQKeUAVh937J7P37XmsfH -ZLOBZKIIlhhCtRwnDlg7x+BUvtJOTkIbEGMujDygUQ2s3HDYr5I41hTyM2Pl0cq2 -EuSGEbPIHb3dEX8NAguFexM0jqNjrreN3hM2/+TOkAxSdDJP2aMurlySC5zwl47K -ZLHtcVrkZnkDa0o5iN24hJT4vBDT4t2q9khQ+qb1D8KgCOb02r1PxWXu3vfd6Ha2 -mkdB97iGuEh5gO2n4yOmFS5goFlVA2UdPbbhJsb8oKVKDd+YdCKGQDCkQyG4AjmC -YiNm3UPG/qtftTH5cWri67DlLtm6fyUFOMmO6NSh0RtR745pL8GyWJUanyq/Q4bF -HQB21E+WtTsCaqjGaoFcrBunMypmCd+jUZXl27TYENRFbrwNdAh7m2UztcIyb+Sg -VJFyfvVsBQNvnp7GPimVxXZNc4VpxEXObRuPWQN1oZN/90PcZVqTia/SHzEyTryL -ckhiLG3jZiaFZ7pTZ5I9wti9Pn+4kOHvE3Y/4nEnUo4mTxPX9pOlinF+VCiybtV2 -u1KSlc+YaIM7VmuyndDZCJRXm3v0/qTE7t5A5fArZl9lvibigMbWB8fpD+c1GpGH -Eo8NRY0lkaM+DkIqQoaziIsz3IKJrfdKaq9bQMSlIfameKBZ8fNYTBZrH9KZAIhz -YwIDAQABo4IBfjCCAXowHQYDVR0OBBYEFIf6nt9SdnXsSUogb1twlo+d77sXMB8G -A1UdIwQYMBaAFIf6nt9SdnXsSUogb1twlo+d77sXMA8GA1UdEwEB/wQFMAMBAf8w -DgYDVR0PAQH/BAQDAgEGMIIBFQYDVR0RBIIBDDCCAQiCEWh0dHA6Ly93d3cuYW5m -LmVzgQtpbmZvQGFuZi5lc6SB5TCB4jE0MDIGA1UECQwrR3JhbiBWaWEgZGUgbGVz -IENvcnRzIENhdGFsYW5lcy4gOTk2LiAwODAxODESMBAGA1UEBwwJQmFyY2Vsb25h -MScwJQYDVQQKDB5BTkYgQXV0b3JpZGFkIGRlIENlcnRpZmljYWNpb24xEjAQBgNV -BAUTCUc2MzI4NzUxMDFZMFcGA1UECwxQSW5zY3JpdGEgZW4gZWwgTWluaXN0ZXJp -byBkZWwgSW50ZXJpb3IgZGUgRXNwYcOxYSBjb24gZWwgbnVtZXJvIG5hY2lvbmFs -IDE3MS40NDMwDQYJKoZIhvcNAQELBQADggIBAIgR9tFTZ9BCYg+HViMxOfF0MHN2 -Pe/eC128ARdS+GH8A4thtbqiH/SOYbWofO/0zssHhNKa5iQEj45lCAb8BANpWJMD -nWkPr6jq2+50a6d0MMgSS2l1rvjSF+3nIrEuicshHXSTi3q/vBLKr7uGKMVFaM68 -XAropIwk6ndlA0JseARSPsbetv7ALESMIZAxlHV1TcctYHd0bB3c/Jz+PLszJQqs -Cg/kBPo2D111OXZkIY8W/fJuG9veR783khAK2gUnC0zLLCNsYzEbdGt8zUmBsAsM -cGxqGm6B6vDXd65OxWqw13xdq/24+5R8Ng1PF9tvfjZkUFBF30CxjWur7P90WiKI -G7IGfr6BE1NgXlhEQQu4F+HizB1ypEPzGWltecXQ4yOzO+H0WfFTjLTYX6VSveyW -DQV18ixF8M4tHP/SwNE+yyv2b2JJ3/3RpxjtFlLk+opJ574x0gD/dMJuWTH0JqVY -3PbRfE1jIxFpk164Qz/Xp7H7w7f6xh+tQCkBs3PUYmnGIZcPwq44Q6JHlCNsKx4K -hxfggTvRCk4w79cUID45c2qDsRCqTPoOo/cbOpcfVhbH9LdMORpmuLwNogRZEUSE -fWpqR9q+0kcQf4zGSWIURIyDrogdpDgoHDxktqgMgc+qA4ZE2WQl1D8hmev53A46 -lUSrWUiWfDXtK3ux ------END CERTIFICATE----- -# "Apple Root CA" -# B0 B1 73 0E CB C7 FF 45 05 14 2C 49 F1 29 5E 6E -# DA 6B CA ED 7E 2C 68 C5 BE 91 B5 A1 10 01 F0 24 ------BEGIN CERTIFICATE----- -MIIEuzCCA6OgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQGEwJVUzET -MBEGA1UEChMKQXBwbGUgSW5jLjEmMCQGA1UECxMdQXBwbGUgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkxFjAUBgNVBAMTDUFwcGxlIFJvb3QgQ0EwHhcNMDYwNDI1MjE0 -MDM2WhcNMzUwMjA5MjE0MDM2WjBiMQswCQYDVQQGEwJVUzETMBEGA1UEChMKQXBw -bGUgSW5jLjEmMCQGA1UECxMdQXBwbGUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx -FjAUBgNVBAMTDUFwcGxlIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw -ggEKAoIBAQDkkakJH5HbHkdQ6wXtXnmELes2oldMVeyLGYne+Uts9QerIjAC6Bg+ -+FAJ039BqJj50cpmnCRrEdCju+QbKsMflZ56DKRHi1vUFjczy8QPTc4UadHJGXL1 -XQ7Vf1+b8iUDulWPTV0N8WQ1IxVLFVkds5T39pyez1C6wVhQZ48ItCD3y6wsIG9w -tj8BMIy3Q88PnT3zK0koGsj+zrW5DtleHNbLPbU6rfQPDgCSC7EhFi501TwN22IW -q6NxkkdTVcGvL0Gz+PvjcM3mo0xFfh9Ma1CWQYnEdGILEINBhzOKgbEwWOxaBDKM -aLOPHd5lc/9nXmW8Sdh2nzMUZaF3lMktAgMBAAGjggF6MIIBdjAOBgNVHQ8BAf8E -BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUK9BpR5R2Cf70a40uQKb3 -R01/CF4wHwYDVR0jBBgwFoAUK9BpR5R2Cf70a40uQKb3R01/CF4wggERBgNVHSAE -ggEIMIIBBDCCAQAGCSqGSIb3Y2QFATCB8jAqBggrBgEFBQcCARYeaHR0cHM6Ly93 -d3cuYXBwbGUuY29tL2FwcGxlY2EvMIHDBggrBgEFBQcCAjCBthqBs1JlbGlhbmNl -IG9uIHRoaXMgY2VydGlmaWNhdGUgYnkgYW55IHBhcnR5IGFzc3VtZXMgYWNjZXB0 -YW5jZSBvZiB0aGUgdGhlbiBhcHBsaWNhYmxlIHN0YW5kYXJkIHRlcm1zIGFuZCBj -b25kaXRpb25zIG9mIHVzZSwgY2VydGlmaWNhdGUgcG9saWN5IGFuZCBjZXJ0aWZp -Y2F0aW9uIHByYWN0aWNlIHN0YXRlbWVudHMuMA0GCSqGSIb3DQEBBQUAA4IBAQBc -NplMLXi37Yyb3PN3m/J20ncwT8EfhYOFG5k9RzfyqZtAjizUsZAS2L70c5vu0mQP -y3lPNNiiPvl4/2vIB+x9OYOLUyDTOMSxv5pPCmv/K/xZpwUJfBdAVhEedNO3iyM7 -R6PVbyTi69G3cN8PReEnyvFteO3ntRcXqNx+IjXKJdXZD9Zr1KIkIxH3oayPc4Fg -xhtbCS+SsvhESPBgOJ4V9T0mZyCKM2r3DYLP3uujL/lTaltkwGMzd/c6ByxW69oP -IQ7aunMZT7XZNn/Bh1XZp5m5MkL72NVxnn6hUrcbvZNCJBIqxw8dtk2cXmPIS4AX -UKqK1drk/NAJBzewdXUh ------END CERTIFICATE----- -# "Apple Root CA - G2" -# C2 B9 B0 42 DD 57 83 0E 7D 11 7D AC 55 AC 8A E1 -# 94 07 D3 8E 41 D8 8F 32 15 BC 3A 89 04 44 A0 50 ------BEGIN CERTIFICATE----- -MIIFkjCCA3qgAwIBAgIIAeDltYNno+AwDQYJKoZIhvcNAQEMBQAwZzEbMBkGA1UE -AwwSQXBwbGUgUm9vdCBDQSAtIEcyMSYwJAYDVQQLDB1BcHBsZSBDZXJ0aWZpY2F0 -aW9uIEF1dGhvcml0eTETMBEGA1UECgwKQXBwbGUgSW5jLjELMAkGA1UEBhMCVVMw -HhcNMTQwNDMwMTgxMDA5WhcNMzkwNDMwMTgxMDA5WjBnMRswGQYDVQQDDBJBcHBs -ZSBSb290IENBIC0gRzIxJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5MRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzCCAiIwDQYJ -KoZIhvcNAQEBBQADggIPADCCAgoCggIBANgREkhI2imKScUcx+xuM23+TfvgHN6s -XuI2pyT5f1BrTM65MFQn5bPW7SXmMLYFN14UIhHF6Kob0vuy0gmVOKTvKkmMXT5x -ZgM4+xb1hYjkWpIMBDLyyED7Ul+f9sDx47pFoFDVEovy3d6RhiPw9bZyLgHaC/Yu -OQhfGaFjQQscp5TBhsRTL3b2CtcM0YM/GlMZ81fVJ3/8E7j4ko380yhDPLVoACVd -J2LT3VXdRCCQgzWTxb+4Gftr49wIQuavbfqeQMpOhYV4SbHXw8EwOTKrfl+q04tv -ny0aIWhwZ7Oj8ZhBbZF8+NfbqOdfIRqMM78xdLe40fTgIvS/cjTf94FNcX1RoeKz -8NMoFnNvzcytN31O661A4T+B/fc9Cj6i8b0xlilZ3MIZgIxbdMYs0xBTJh0UT8TU -gWY8h2czJxQI6bR3hDRSj4n4aJgXv8O7qhOTH11UL6jHfPsNFL4VPSQ08prcdUFm -IrQB1guvkJ4M6mL4m1k8COKWNORj3rw31OsMiANDC1CvoDTdUE0V+1ok2Az6DGOe -HwOx4e7hqkP0ZmUoNwIx7wHHHtHMn23KVDpA287PT0aLSmWaasZobNfMmRtHsHLD -d4/E92GcdB/O/WuhwpyUgquUoue9G7q5cDmVF8Up8zlYNPXEpMZ7YLlmQ1A/bmH8 -DvmGqmAMQ0uVAgMBAAGjQjBAMB0GA1UdDgQWBBTEmRNsGAPCe8CjoA1/coB6HHcm -jTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQwF -AAOCAgEAUabz4vS4PZO/Lc4Pu1vhVRROTtHlznldgX/+tvCHM/jvlOV+3Gp5pxy+ -8JS3ptEwnMgNCnWefZKVfhidfsJxaXwU6s+DDuQUQp50DhDNqxq6EWGBeNjxtUVA -eKuowM77fWM3aPbn+6/Gw0vsHzYmE1SGlHKy6gLti23kDKaQwFd1z4xCfVzmMX3z -ybKSaUYOiPjjLUKyOKimGY3xn83uamW8GrAlvacp/fQ+onVJv57byfenHmOZ4VxG -/5IFjPoeIPmGlFYl5bRXOJ3riGQUIUkhOb9iZqmxospvPyFgxYnURTbImHy99v6Z -SYA7LNKmp4gDBDEZt7Y6YUX6yfIjyGNzv1aJMbDZfGKnexWoiIqrOEDCzBL/FePw -N983csvMmOa/orz6JopxVtfnJBtIRD6e/J/JzBrsQzwBvDR4yGn1xuZW7AYJNpDr -FEobXsmII9oDMJELuDY++ee1KG++P+w8j2Ud5cAeh6Squpj9kuNsJnfdBrRkBof0 -Tta6SqoWqPQFZ2aWuuJVecMsXUmPgEkrihLHdoBR37q9ZV0+N0djMenl9MU/S60E -inpxLK8JQzcPqOMyT/RFtm2XNuyE9QoB6he7hY1Ck3DDUOUUi78/w0EP3SIEIwiK -um1xRKtzCTrJ+VKACd+66eYWyi4uTLLT3OUEVLLUNIAytbwPF+E= ------END CERTIFICATE----- -# "Apple Root CA - G3" -# 63 34 3A BF B8 9A 6A 03 EB B5 7E 9B 3F 5F A7 BE -# 7C 4F 5C 75 6F 30 17 B3 A8 C4 88 C3 65 3E 91 79 ------BEGIN CERTIFICATE----- -MIICQzCCAcmgAwIBAgIILcX8iNLFS5UwCgYIKoZIzj0EAwMwZzEbMBkGA1UEAwwS -QXBwbGUgUm9vdCBDQSAtIEczMSYwJAYDVQQLDB1BcHBsZSBDZXJ0aWZpY2F0aW9u -IEF1dGhvcml0eTETMBEGA1UECgwKQXBwbGUgSW5jLjELMAkGA1UEBhMCVVMwHhcN -MTQwNDMwMTgxOTA2WhcNMzkwNDMwMTgxOTA2WjBnMRswGQYDVQQDDBJBcHBsZSBS -b290IENBIC0gRzMxJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9y -aXR5MRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzB2MBAGByqGSM49 -AgEGBSuBBAAiA2IABJjpLz1AcqTtkyJygRMc3RCV8cWjTnHcFBbZDuWmBSp3ZHtf -TjjTuxxEtX/1H7YyYl3J6YRbTzBPEVoA/VhYDKX1DyxNB0cTddqXl5dvMVztK517 -IDvYuVTZXpmkOlEKMaNCMEAwHQYDVR0OBBYEFLuw3qFYM4iapIqZ3r6966/ayySr -MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2gA -MGUCMQCD6cHEFl4aXTQY2e3v9GwOAEZLuN+yRhHFD/3meoyhpmvOwgPUnPWTxnS4 -at+qIxUCMG1mihDK1A3UT82NQz60imOlM27jbdoXt2QfyFMm+YhidDkLF1vLUagM -6BgD56KyKA== ------END CERTIFICATE----- -# "Apple Root Certificate Authority" -# 0D 83 B6 11 B6 48 A1 A7 5E B8 55 84 00 79 53 75 -# CA D9 2E 26 4E D8 E9 D7 A7 57 C1 F5 EE 2B B2 2D ------BEGIN CERTIFICATE----- -MIIFujCCBKKgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhjELMAkGA1UEBhMCVVMx -HTAbBgNVBAoTFEFwcGxlIENvbXB1dGVyLCBJbmMuMS0wKwYDVQQLEyRBcHBsZSBD -b21wdXRlciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxKTAnBgNVBAMTIEFwcGxlIFJv -b3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTA1MDIxMDAwMTgxNFoXDTI1MDIx -MDAwMTgxNFowgYYxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRBcHBsZSBDb21wdXRl -ciwgSW5jLjEtMCsGA1UECxMkQXBwbGUgQ29tcHV0ZXIgQ2VydGlmaWNhdGUgQXV0 -aG9yaXR5MSkwJwYDVQQDEyBBcHBsZSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0 -eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOSRqQkfkdseR1DrBe1e -eYQt6zaiV0xV7IsZid75S2z1B6siMALoGD74UAnTf0GomPnRymacJGsR0KO75Bsq -wx+VnnoMpEeLW9QWNzPLxA9NzhRp0ckZcvVdDtV/X5vyJQO6VY9NXQ3xZDUjFUsV -WR2zlPf2nJ7PULrBWFBnjwi0IPfLrCwgb3C2PwEwjLdDzw+dPfMrSSgayP7OtbkO -2V4c1ss9tTqt9A8OAJILsSEWLnTVPA3bYharo3GSR1NVwa8vQbP4++NwzeajTEV+ -H0xrUJZBicR0YgsQg0GHM4qBsTBY7FoEMoxos48d3mVz/2deZbxJ2HafMxRloXeU -yS0CAwEAAaOCAi8wggIrMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/ -MB0GA1UdDgQWBBQr0GlHlHYJ/vRrjS5ApvdHTX8IXjAfBgNVHSMEGDAWgBQr0GlH -lHYJ/vRrjS5ApvdHTX8IXjCCASkGA1UdIASCASAwggEcMIIBGAYJKoZIhvdjZAUB -MIIBCTBBBggrBgEFBQcCARY1aHR0cHM6Ly93d3cuYXBwbGUuY29tL2NlcnRpZmlj -YXRlYXV0aG9yaXR5L3Rlcm1zLmh0bWwwgcMGCCsGAQUFBwICMIG2GoGzUmVsaWFu -Y2Ugb24gdGhpcyBjZXJ0aWZpY2F0ZSBieSBhbnkgcGFydHkgYXNzdW1lcyBhY2Nl -cHRhbmNlIG9mIHRoZSB0aGVuIGFwcGxpY2FibGUgc3RhbmRhcmQgdGVybXMgYW5k -IGNvbmRpdGlvbnMgb2YgdXNlLCBjZXJ0aWZpY2F0ZSBwb2xpY3kgYW5kIGNlcnRp -ZmljYXRpb24gcHJhY3RpY2Ugc3RhdGVtZW50cy4wRAYDVR0fBD0wOzA5oDegNYYz -aHR0cHM6Ly93d3cuYXBwbGUuY29tL2NlcnRpZmljYXRlYXV0aG9yaXR5L3Jvb3Qu -Y3JsMFUGCCsGAQUFBwEBBEkwRzBFBggrBgEFBQcwAoY5aHR0cHM6Ly93d3cuYXBw -bGUuY29tL2NlcnRpZmljYXRlYXV0aG9yaXR5L2Nhc2lnbmVycy5odG1sMA0GCSqG -SIb3DQEBBQUAA4IBAQCd2i0oWC99dgS5BNM+zrdmY06PL9T+S61yvaM5xlJNBZhS -9YlRASR5vhoy9+VEi0tEBzmC1lrKtCBe2a4VXR2MHTK/ODFiSF3H4ZCx+CRA+F9Y -m1FdV53B5f88zHIhbsTp6aF31ywXJsM/65roCwO66bNKcuszCVut5mIxauivL9Wv -Hld2j383LS4CXN1jyfJxuCZA3xWNdUQ/eb3mHZnhQyw+rW++uaT+DjUZUWOxw961 -kj5ReAFziqQjyqSI8R5cH0EWLX6VCqrpiUGYGxrdyyC/R14MJsVVNU3GMIuZZxTH -CR+6R8faAQmHJEKVvRNgGQrv6n8Obs3BREM6StXj ------END CERTIFICATE----- -# "Atos TrustedRoot 2011" -# F3 56 BE A2 44 B7 A9 1E B3 5D 53 CA 9A D7 86 4A -# CE 01 8E 2D 35 D5 F8 F9 6D DF 68 A6 F4 1A A4 74 ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE -AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG -EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM -FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC -REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp -Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM -VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+ -SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ -4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L -cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi -eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV -HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG -A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3 -DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j -vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP -DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc -maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D -lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv -KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed ------END CERTIFICATE----- -# "Autoridad de Certificacion Firmaprofesional CIF A62634068" -# 04 04 80 28 BF 1F 28 64 D4 8F 9A D4 D8 32 94 36 -# 6A 82 88 56 55 3F 3B 14 30 3F 90 14 7F 5D 40 EF ------BEGIN CERTIFICATE----- -MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UE -BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h -cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEy -MzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg -Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi -MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9 -thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM -cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG -L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i -NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h -X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b -m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy -Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja -EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T -KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF -6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh -OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYD -VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNHDhpkLzCBpgYD -VR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp -cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBv -ACAAZABlACAAbABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBl -AGwAbwBuAGEAIAAwADgAMAAxADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF -661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx51tkljYyGOylMnfX40S2wBEqgLk9 -am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qkR71kMrv2JYSiJ0L1 -ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaPT481 -PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS -3a/DTg4fJl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5k -SeTy36LssUzAKh3ntLFlosS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF -3dvd6qJ2gHN99ZwExEWN57kci57q13XRcrHedUTnQn3iV2t93Jm8PYMo6oCTjcVM -ZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoRsaS8I8nkvof/uZS2+F0g -StRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTDKCOM/icz -Q0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQB -jLMi6Et8Vcad+qMUu2WFbm5PEn4KPJ2V ------END CERTIFICATE----- -# "Autoridad de Certificacion Raiz del Estado Venezolano" -# 0E D3 FF AB 6C 14 9C 8B 4E 71 05 8E 86 68 D4 29 -# AB FD A6 81 C2 FF F5 08 20 76 41 F0 D7 51 A3 E5 ------BEGIN CERTIFICATE----- -MIIJmzCCB4OgAwIBAgIBATANBgkqhkiG9w0BAQwFADCCAR4xPjA8BgNVBAMTNUF1 -dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIFJhaXogZGVsIEVzdGFkbyBWZW5lem9s -YW5vMQswCQYDVQQGEwJWRTEQMA4GA1UEBxMHQ2FyYWNhczEZMBcGA1UECBMQRGlz -dHJpdG8gQ2FwaXRhbDE2MDQGA1UEChMtU2lzdGVtYSBOYWNpb25hbCBkZSBDZXJ0 -aWZpY2FjaW9uIEVsZWN0cm9uaWNhMUMwQQYDVQQLEzpTdXBlcmludGVuZGVuY2lh -IGRlIFNlcnZpY2lvcyBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMSUwIwYJ -KoZIhvcNAQkBFhZhY3JhaXpAc3VzY2VydGUuZ29iLnZlMB4XDTEwMTIyMjE4MDgy -MVoXDTMwMTIxNzIzNTk1OVowggEeMT4wPAYDVQQDEzVBdXRvcmlkYWQgZGUgQ2Vy -dGlmaWNhY2lvbiBSYWl6IGRlbCBFc3RhZG8gVmVuZXpvbGFubzELMAkGA1UEBhMC -VkUxEDAOBgNVBAcTB0NhcmFjYXMxGTAXBgNVBAgTEERpc3RyaXRvIENhcGl0YWwx -NjA0BgNVBAoTLVNpc3RlbWEgTmFjaW9uYWwgZGUgQ2VydGlmaWNhY2lvbiBFbGVj -dHJvbmljYTFDMEEGA1UECxM6U3VwZXJpbnRlbmRlbmNpYSBkZSBTZXJ2aWNpb3Mg -ZGUgQ2VydGlmaWNhY2lvbiBFbGVjdHJvbmljYTElMCMGCSqGSIb3DQEJARYWYWNy -YWl6QHN1c2NlcnRlLmdvYi52ZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC -ggIBAME77xNS8ZlW47RsBeEaaRZhJoZ4rw785UAFCuPZOAVMqNS1wMYqzy95q6Gk -UO81ER/ugiQX/KMcq/4HBn83fwdYWxPZfwBfK7BP2p/JsFgzYeFP0BXOLmvoJIzl -Jb6FW+1MPwGBjuaZGFImWZsSmGUclb51mRYMZETh9/J5CLThR1exStxHQptwSzra -zNFpkQY/zmj7+YZNA9yDoroVFv6sybYOZ7OxNDo7zkSLo45I7gMwtxqWZ8VkJZkC -8+p0dX6mkhUT0QAV64Zc9HsZiH/oLhEkXjhrgZ28cF73MXIqLx1fyM4kPH1yOJi/ -R72nMwL7D+Sd6mZgI035TxuHXc2/uOwXfKrrTjaJDz8Jp6DdessOkxIgkKXRjP+F -K3ze3n4NUIRGhGRtyvEjK95/2g02t6PeYiYVGur6ruS49n0RAaSS0/LJb6XzaAAe -0mmO2evnEqxIKwy2mZRNPfAVW1l3wCnWiUwryBU6OsbFcFFrQm+00wOicXvOTHBM -aiCVAVZTb9RSLyi+LJ1llzJZO3pq3IRiiBj38Nooo+2ZNbMEciSgmig7YXaUcmud -SVQvLSL+Yw+SqawyezwZuASbp7d/0rutQ59d81zlbMt3J7yB567rT2IqIydQ8qBW -k+fmXzghX+/FidYsh/aK+zZ7Wy68kKHuzEw1Vqkat5DGs+VzAgMBAAGjggLeMIIC -2jASBgNVHRMBAf8ECDAGAQH/AgECMDcGA1UdEgQwMC6CD3N1c2NlcnRlLmdvYi52 -ZaAbBgVghl4CAqASDBBSSUYtRy0yMDAwNDAzNi0wMB0GA1UdDgQWBBStuyIdxuDS -Aaj9dlBSk+2YwU2u0zCCAVAGA1UdIwSCAUcwggFDgBStuyIdxuDSAaj9dlBSk+2Y -wU2u06GCASakggEiMIIBHjE+MDwGA1UEAxM1QXV0b3JpZGFkIGRlIENlcnRpZmlj -YWNpb24gUmFpeiBkZWwgRXN0YWRvIFZlbmV6b2xhbm8xCzAJBgNVBAYTAlZFMRAw -DgYDVQQHEwdDYXJhY2FzMRkwFwYDVQQIExBEaXN0cml0byBDYXBpdGFsMTYwNAYD -VQQKEy1TaXN0ZW1hIE5hY2lvbmFsIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25p -Y2ExQzBBBgNVBAsTOlN1cGVyaW50ZW5kZW5jaWEgZGUgU2VydmljaW9zIGRlIENl -cnRpZmljYWNpb24gRWxlY3Ryb25pY2ExJTAjBgkqhkiG9w0BCQEWFmFjcmFpekBz -dXNjZXJ0ZS5nb2IudmWCAQEwDgYDVR0PAQH/BAQDAgEGMDcGA1UdEQQwMC6CD3N1 -c2NlcnRlLmdvYi52ZaAbBgVghl4CAqASDBBSSUYtRy0yMDAwNDAzNi0wMFQGA1Ud -HwRNMEswJKAioCCGHmhodHA6Ly93d3cuc3VzY2VydGUuZ29iLnZlL2xjcjAjoCGg -H4YdbGRhcDovL2FjcmFpei5zdXNjZXJ0ZS5nb2IudmUwNwYIKwYBBQUHAQEEKzAp -MCcGCCsGAQUFBzABhhtoaHRwOi8vb2NzcC5zdXNjZXJ0ZS5nb2IudmUwQAYDVR0g -BDkwNzA1BgVghl4BAjAsMCoGCCsGAQUFBwIBFh5odHRwOi8vd3d3LnN1c2NlcnRl -LmdvYi52ZS9kcGMwDQYJKoZIhvcNAQEMBQADggIBAK4qy/zmZ9zBwfW3yOYtLcBT -Oy4szJyPz7/RhNH3bPVH7HbDTGpi6JZ4YXdXMBeJE5qBF4a590Kgj8Rlnltt+Rbo -OFQOU1UDqKuTdBsA//Zry5899fmn8jBUkg4nh09jhHHbLlaUScdz704Zz2+UVg7i -s/r3Legxap60KzmdrmTAE9VKte1TQRgavQwVX5/2mO/J+SCas//UngI+h8SyOucq -mjudYEgBrZaodUsagUfn/+AzFNrGLy+al+5nZeHb8JnCfLHWS0M9ZyhgoeO/czyn -99+5G93VWNv4zfc4KiavHZKrkn8F9pg0ycIZh+OwPT/RE2zq4gTazBMlP3ACIe/p -olkNaOEa8KvgzW96sjBZpMW49zFmyINYkcj+uaNCJrVGsXgdBmkuRGJNWFZ9r0cG -woIaxViFBypsz045r1ESfYPlfDOavBhZ/giR/Xocm9CHkPRY2BApMMR0DUCyGETg -Ql+L3kfdTKzuDjUp2DM9FqysQmaM81YDZufWkMhlZPfHwC7KbNougoLroa5Umeos -bqAXWmk46SwIdWRPLLqbUpDTKooynZKpSYIkkotdgJoVZUUCY+RCO8jsVPEU6ece -SxztNUm5UOta1OJPMwSAKRHOo3ilVb9c6lAixDdvV8MeNbqe6asM1mpCHWbJ/0rg -5Ls9Cxx8hracyp0ev7b0 ------END CERTIFICATE----- -# "Baltimore CyberTrust Root" -# 16 AF 57 A9 F6 76 B0 AB 12 60 95 AA 5E BA DE F2 -# 2A B3 11 19 D6 44 AC 95 CD 4B 93 DB F3 F2 6A EB ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ -RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD -VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX -DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y -ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy -VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr -mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr -IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK -mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu -XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy -dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye -jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 -BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 -DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 -9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx -jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 -Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz -ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS -R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp ------END CERTIFICATE----- -# "Belgium Root CA2" -# 9F 97 44 46 3B E1 37 14 75 4E 1A 3B EC F9 8C 08 -# CC 20 5E 4A B3 20 28 F4 E2 83 0C 4A 1B 27 75 B8 ------BEGIN CERTIFICATE----- -MIIDjjCCAnagAwIBAgIIKv++n6Lw6YcwDQYJKoZIhvcNAQEFBQAwKDELMAkGA1UE -BhMCQkUxGTAXBgNVBAMTEEJlbGdpdW0gUm9vdCBDQTIwHhcNMDcxMDA0MTAwMDAw -WhcNMjExMjE1MDgwMDAwWjAoMQswCQYDVQQGEwJCRTEZMBcGA1UEAxMQQmVsZ2l1 -bSBSb290IENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMZzQh6S -/3UPi790hqc/7bIYLS2X+an7mEoj39WN4IzGMhwWLQdC1i22bi+n9fzGhYJdld61 -IgDMqFNAn68KNaJ6x+HK92AQZw6nUHMXU5WfIp8MXW+2QbyM69odRr2nlL/zGsvU -+40OHjPIltfsjFPekx40HopQcSZYtF3CiInaYNKJIT/e1wEYNm7hLHADBGXvmAYr -XR5i3FVr/mZkIV/4L+HXmymvb82fqgxG0YjFnaKVn6w/Fa7yYd/vw2uaItgscf1Y -HewApDgglVrH1Tdjuk+bqv5WRi5j2Qsj1Yr6tSPwiRuhFA0m2kHwOI8w7QUmecFL -TqG4flVSOmlGhHUCAwEAAaOBuzCBuDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ -BAUwAwEB/zBCBgNVHSAEOzA5MDcGBWA4CQEBMC4wLAYIKwYBBQUHAgEWIGh0dHA6 -Ly9yZXBvc2l0b3J5LmVpZC5iZWxnaXVtLmJlMB0GA1UdDgQWBBSFiuv0xbu+DlkD -lN7WgAEV4xCcOTARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0jBBgwFoAUhYrr9MW7 -vg5ZA5Te1oABFeMQnDkwDQYJKoZIhvcNAQEFBQADggEBAFHYhd27V2/MoGy1oyCc -UwnzSgEMdL8rs5qauhjyC4isHLMzr87lEwEnkoRYmhC598wUkmt0FoqW6FHvv/pK -JaeJtmMrXZRY0c8RcrYeuTlBFk0pvDVTC9rejg7NqZV3JcqUWumyaa7YwBO+mPyW -nIR/VRPmPIfjvCCkpDZoa01gZhz5v6yAlGYuuUGK02XThIAC71AdXkbc98m6tTR8 -KvPG2F9fVJ3bTc0R5/0UAoNmXsimABKgX77OFP67H6dh96tK8QYUn8pJQsKpvO2F -sauBQeYNxUJpU4c5nUwfAA4+Bw11V0SoU7Q2dmSZ3G7rPUZuFF1eR1ONeE3gJ7uO -hXY= ------END CERTIFICATE----- -# "Buypass Class 2 Root CA" -# 9A 11 40 25 19 7C 5B B9 5D 94 E6 3D 55 CD 43 79 -# 08 47 B6 46 B2 3C DF 11 AD A4 A0 0E FF 15 FB 48 ------BEGIN CERTIFICATE----- -MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd -MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg -Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow -TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw -HgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB -BQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1g1Lr -6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPV -L4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC91 -1K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx -MlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZ -QmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkB -arcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clr -Us3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLi -FRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRS -P/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN -9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxP -AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+BikoL1Rpzz -uvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h -9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s -A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3t -OluwlN5E40EIosHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo -+fsicdl9sz1Gv7SEr5AcD48Saq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7 -KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYdDnkM/crqJIByw5c/8nerQyIKx+u2 -DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWDLfJ6v9r9jv6ly0Us -H8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0oyLQ -I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7 -5t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h -3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz -Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA= ------END CERTIFICATE----- -# "Buypass Class 3 Root CA" -# ED F7 EB BC A2 7A 2A 38 4D 38 7B 7D 40 10 C6 66 -# E2 ED B4 84 3E 4C 29 B4 AE 1D 5B 93 32 E6 B2 4D ------BEGIN CERTIFICATE----- -MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd -MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg -Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow -TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw -HgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB -BQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRHsJ8Y -ZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3E -N3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9 -tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX -0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c -/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8X -KhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTY -zIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvS -O1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D -34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgP -K9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3 -AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/lb+74suwv -Tg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj -QTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV -cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXS -IGrs/CIBKM+GuIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2 -HJLw5QY33KbmkJs4j1xrG0aGQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsa -O5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8ZORK15FTAaggiG6cX0S5y2CBNOxv -033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2KSb12tjE8nVhz36u -dmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz6MkE -kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41 -3OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD -u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq -4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc= ------END CERTIFICATE----- -# "CA Disig Root R1" -# F9 6F 23 F4 C3 E7 9C 07 7A 46 98 8D 5A F5 90 06 -# 76 A0 F0 39 CB 64 5D D1 75 49 B2 16 C8 24 40 CE ------BEGIN CERTIFICATE----- -MIIFaTCCA1GgAwIBAgIJAMMDmu5QkG4oMA0GCSqGSIb3DQEBBQUAMFIxCzAJBgNV -BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu -MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIxMB4XDTEyMDcxOTA5MDY1NloXDTQy -MDcxOTA5MDY1NlowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx -EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjEw -ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCqw3j33Jijp1pedxiy3QRk -D2P9m5YJgNXoqqXinCaUOuiZc4yd39ffg/N4T0Dhf9Kn0uXKE5Pn7cZ3Xza1lK/o -OI7bm+V8u8yN63Vz4STN5qctGS7Y1oprFOsIYgrY3LMATcMjfF9DCCMyEtztDK3A -fQ+lekLZWnDZv6fXARz2m6uOt0qGeKAeVjGu74IKgEH3G8muqzIm1Cxr7X1r5OJe -IgpFy4QxTaz+29FHuvlglzmxZcfe+5nkCiKxLU3lSCZpq+Kq8/v8kiky6bM+TR8n -oc2OuRf7JT7JbvN32g0S9l3HuzYQ1VTW8+DiR0jm3hTaYVKvJrT1cU/J19IG32PK -/yHoWQbgCNWEFVP3Q+V8xaCJmGtzxmjOZd69fwX3se72V6FglcXM6pM6vpmumwKj -rckWtc7dXpl4fho5frLABaTAgqWjR56M6ly2vGfb5ipN0gTco65F97yLnByn1tUD -3AjLLhbKXEAz6GfDLuemROoRRRw1ZS0eRWEkG4IupZ0zXWX4Qfkuy5Q/H6MMMSRE -7cderVC6xkGbrPAXZcD4XW9boAo0PO7X6oifmPmvTiT6l7Jkdtqr9O3jw2Dv1fkC -yC2fg69naQanMVXVz0tv/wQFx1isXxYb5dKj6zHbHzMVTdDypVP1y+E9Tmgt2BLd -qvLmTZtJ5cUoobqwWsagtQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud -DwEB/wQEAwIBBjAdBgNVHQ4EFgQUiQq0OJMa5qvum5EY+fU8PjXQ04IwDQYJKoZI -hvcNAQEFBQADggIBADKL9p1Kyb4U5YysOMo6CdQbzoaz3evUuii+Eq5FLAR0rBNR -xVgYZk2C2tXck8An4b58n1KeElb21Zyp9HWc+jcSjxyT7Ff+Bw+r1RL3D65hXlaA -SfX8MPWbTx9BLxyE04nH4toCdu0Jz2zBuByDHBb6lM19oMgY0sidbvW9adRtPTXo -HqJPYNcHKfyyo6SdbhWSVhlMCrDpfNIZTUJG7L399ldb3Zh+pE3McgODWF3vkzpB -emOqfDqo9ayk0d2iLbYq/J8BjuIQscTK5GfbVSUZP/3oNn6z4eGBrxEWi1CXYBmC -AMBrTXO40RMHPuq2MU/wQppt4hF05ZSsjYSVPCGvxdpHyN85YmLLW1AL14FABZyb -7bq2ix4Eb5YgOe2kfSnbSM6C3NQCjR0EMVrHS/BsYVLXtFHCgWzN4funodKSds+x -DzdYpPJScWc/DIh4gInByLUfkmO+p3qKViwaqKactV2zY9ATIKHrkWzQjX2v3wvk -F7mGnjixlAxYjOBVqjtjbZqJYLhkKpLGN/R+Q0O3c+gB53+XD9fyexn9GtePyfqF -a3qdnom2piiZk4hA9z7NUaPK6u95RyG1/jLix8NRb76AdPCkwzryT+lf3xkK8jsT -Q6wxpLPn6/wY1gGp8yqPNg7rtLG8t0zJa7+h89n07eLw4+1knj0vllJPgFOL ------END CERTIFICATE----- -# "CA Disig Root R2" -# E2 3D 4A 03 6D 7B 70 E9 F5 95 B1 42 20 79 D2 B9 -# 1E DF BB 1F B6 51 A0 63 3E AA 8A 9D C5 F8 07 03 ------BEGIN CERTIFICATE----- -MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV -BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu -MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy -MDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx -EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjIw -ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbCw3Oe -NcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNH -PWSb6WiaxswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3I -x2ymrdMxp7zo5eFm1tL7A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbe -QTg06ov80egEFGEtQX6sx3dOy1FU+16SGBsEWmjGycT6txOgmLcRK7fWV8x8nhfR -yyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqVg8NTEQxzHQuyRpDRQjrO -QG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa5Beny912 -H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJ -QfYEkoopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUD -i/ZnWejBBhG93c+AAk9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORs -nLMOPReisjQS1n6yqEm70XooQL6iFh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1 -rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud -DwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5uQu0wDQYJKoZI -hvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM -tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqf -GopTpti72TVVsRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkb -lvdhuDvEK7Z4bLQjb/D907JedR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka -+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W81k/BfDxujRNt+3vrMNDcTa/F1bal -TFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjxmHHEt38OFdAlab0i -nSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01utI3 -gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18Dr -G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os -zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x -L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL ------END CERTIFICATE----- -# "Certigna" -# E3 B6 A2 DB 2E D7 CE 48 84 2F 7A C5 32 41 C7 B7 -# 1D 54 14 4B FB 40 C1 1F 3F 1D 0B 42 F5 EE A1 2D ------BEGIN CERTIFICATE----- -MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV -BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X -DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ -BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4 -QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny -gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw -zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q -130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2 -JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw -DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw -ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT -AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj -AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG -9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h -bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc -fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu -HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w -t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw -WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== ------END CERTIFICATE----- -# "Certinomis - Autorité Racine" -# FC BF E2 88 62 06 F7 2B 27 59 3C 8B 07 02 97 E1 -# 2D 76 9E D1 0E D7 93 07 05 A8 09 8E FF C1 4D 17 ------BEGIN CERTIFICATE----- -MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjET -MBEGA1UEChMKQ2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAk -BgNVBAMMHUNlcnRpbm9taXMgLSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4 -Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkGA1UEBhMCRlIxEzARBgNVBAoTCkNl -cnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYwJAYDVQQDDB1DZXJ0 -aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQADggIP -ADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jY -F1AMnmHawE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N -8y4oH3DfVS9O7cdxbwlyLu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWe -rP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K -/OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92NjMD2AR5vpTESOH2VwnHu -7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9qc1pkIuVC -28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6 -lSTClrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1E -nn1So2+WLhl+HPNbxxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB -0iSVL1N6aaLwD4ZFjliCK0wi1F6g530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql09 -5gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna4NH4+ej9Uji29YnfAgMBAAGj -WzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBQN -jLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ -KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9s -ov3/4gbIOZ/xWqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZM -OH8oMDX/nyNTt7buFHAAQCvaR6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q -619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40nJ+U8/aGH88bc62UeYdocMMzpXDn -2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1BCxMjidPJC+iKunqj -o3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjvJL1v -nxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG -5ERQL1TEqkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWq -pdEdnV1j6CTmNhTih60bWfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZb -dsLLO7XSAPCjDuGtbkD326C00EauFddEwk01+dIL8hf2rGbVJLJP0RyZwG71fet0 -BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/vgt2Fl43N+bYdJeimUV5 ------END CERTIFICATE----- -# "Certinomis - Root CA" -# 2A 99 F5 BC 11 74 B7 3C BB 1D 62 08 84 E0 1C 34 -# E5 1C CB 39 78 DA 12 5F 0E 33 26 88 83 BF 41 58 ------BEGIN CERTIFICATE----- -MIIFkjCCA3qgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJGUjET -MBEGA1UEChMKQ2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxHTAb -BgNVBAMTFENlcnRpbm9taXMgLSBSb290IENBMB4XDTEzMTAyMTA5MTcxOFoXDTMz -MTAyMTA5MTcxOFowWjELMAkGA1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMx -FzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMR0wGwYDVQQDExRDZXJ0aW5vbWlzIC0g -Um9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTMCQosP5L2 -fxSeC5yaah1AMGT9qt8OHgZbn1CF6s2Nq0Nn3rD6foCWnoR4kkjW4znuzuRZWJfl -LieY6pOod5tK8O90gC3rMB+12ceAnGInkYjwSond3IjmFPnVAy//ldu9n+ws+hQV -WZUKxkd8aRi5pwP5ynapz8dvtF4F/u7BUrJ1Mofs7SlmO/NKFoL21prbcpjp3vDF -TKWrteoB4owuZH9kb/2jJZOLyKIOSY008B/sWEUuNKqEUL3nskoTuLAPrjhdsKkb -5nPJWqHZZkCqqU2mNAKthH6yI8H7KsZn9DS2sJVqM09xRLWtwHkziOC/7aOgFLSc -CbAK42C++PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK/eVNfaoqoynHWmgE6OXWk6Ri -wsXm9E/G+Z8ajYJJGYrKWUM66A0ywfRMEwNvbqY/kXPLynNvEiCL7sCCeN5LLsJJ -wx3tFvYk9CcbXFcx3FXuqB5vbKziRcxXV4p1VxngtViZSTYxPDMBbRZKzbgqg4SG -m/lg0h9tkQPTYKbVPZrdd5A9NaSfD171UkRpucC63M9933zZxKyGIjK8e2uR73r4 -F2iw4lNVYC2vPsKD2NkJK/DAZNuHi5HMkesE/Xa0lZrmFAYb1TQdvtj/dBxThZng -WVJKYe2InmtJiUZ+IFrZ50rlau7SZRFDAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIB -BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTvkUz1pcMw6C8I6tNxIqSSaHh0 -2TAfBgNVHSMEGDAWgBTvkUz1pcMw6C8I6tNxIqSSaHh02TANBgkqhkiG9w0BAQsF -AAOCAgEAfj1U2iJdGlg+O1QnurrMyOMaauo++RLrVl89UM7g6kgmJs95Vn6RHJk/ -0KGRHCwPT5iVWVO90CLYiF2cN/z7ZMF4jIuaYAnq1fohX9B0ZedQxb8uuQsLrbWw -F6YSjNRieOpWauwK0kDDPAUwPk2Ut59KA9N9J0u2/kTO+hkzGm2kQtHdzMjI1xZS -g081lLMSVX3l4kLr5JyTCcBMWwerx20RoFAXlCOotQqSD7J6wWAsOMwaplv/8gzj -qh8c3LigkyfeY+N/IZ865Z764BNqdeuWXGKRlI5nU7aJ+BIJy29SWwNyhlCVCNSN -h4YVH5Uk2KRvms6knZtt0rJ2BobGVgjF6wnaNsIbW0G+YSrjcOa4pvi2WsS9Iff/ -ql+hbHY5ZtbqTFXhADObE5hjyW/QASAJN1LnDE8+zbz1X5YnpyACleAu6AdBBR8V -btaw5BngDwKTACdyxYvRVB9dSsNAl35VpnzBMwQUAR1JIGkLGZOdblgi90AMRgwj -Y/M50n92Uaf0yKHxDHYiI0ZSKS3io0EHVmmY0gUJvGnHWmHNj4FgFU2A3ZDifcRQ -8ow7bkrHxuaAKzyBvBGAFhAn1/DNP3nMcyrDflOR1m749fPH0FFNjkulW+YZFzvW -gQncItzujrnEj1PhZ7szuIgVRs/taTX/dQ1G885x4cVrhkIGuUE= ------END CERTIFICATE----- -# "Certplus Root CA G1" -# 15 2A 40 2B FC DF 2C D5 48 05 4D 22 75 B3 9C 7F -# CA 3E C0 97 80 78 B0 F0 EA 76 E5 61 A6 C7 43 3E ------BEGIN CERTIFICATE----- -MIIFazCCA1OgAwIBAgISESBVg+QtPlRWhS2DN7cs3EYRMA0GCSqGSIb3DQEBDQUA -MD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2Vy -dHBsdXMgUm9vdCBDQSBHMTAeFw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBa -MD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2Vy -dHBsdXMgUm9vdCBDQSBHMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB -ANpQh7bauKk+nWT6VjOaVj0W5QOVsjQcmm1iBdTYj+eJZJ+622SLZOZ5KmHNr49a -iZFluVj8tANfkT8tEBXgfs+8/H9DZ6itXjYj2JizTfNDnjl8KvzsiNWI7nC9hRYt -6kuJPKNxQv4c/dMcLRC4hlTqQ7jbxofaqK6AJc96Jh2qkbBIb6613p7Y1/oA/caP -0FG7Yn2ksYyy/yARujVjBYZHYEMzkPZHogNPlk2dT8Hq6pyi/jQu3rfKG3akt62f -6ajUeD94/vI4CTYd0hYCyOwqaK/1jpTvLRN6HkJKHRUxrgwEV/xhc/MxVoYxgKDE -EW4wduOU8F8ExKyHcomYxZ3MVwia9Az8fXoFOvpHgDm2z4QTd28n6v+WZxcIbekN -1iNQMLAVdBM+5S//Ds3EC0pd8NgAM0lm66EYfFkuPSi5YXHLtaW6uOrc4nBvCGrc -h2c0798wct3zyT8j/zXhviEpIDCB5BmlIOklynMxdCm+4kLV87ImZsdo/Rmz5yCT -mehd4F6H50boJZwKKSTUzViGUkAksnsPmBIgJPaQbEfIDbsYIC7Z/fyL8inqh3SV -4EJQeIQEQWGw9CEjjy3LKCHyamz0GqbFFLQ3ZU+V/YDI+HLlJWvEYLF7bY5KinPO -WftwenMGE9nTdDckQQoRb5fc5+R+ob0V8rqHDz1oihYHAgMBAAGjYzBhMA4GA1Ud -DwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSowcCbkahDFXxd -Bie0KlHYlwuBsTAfBgNVHSMEGDAWgBSowcCbkahDFXxdBie0KlHYlwuBsTANBgkq -hkiG9w0BAQ0FAAOCAgEAnFZvAX7RvUz1isbwJh/k4DgYzDLDKTudQSk0YcbX8ACh -66Ryj5QXvBMsdbRX7gp8CXrc1cqh0DQT+Hern+X+2B50ioUHj3/MeXrKls3N/U/7 -/SMNkPX0XtPGYX2eEeAC7gkE2Qfdpoq3DIMku4NQkv5gdRE+2J2winq14J2by5BS -S7CTKtQ+FjPlnsZlFT5kOwQ/2wyPX1wdaR+v8+khjPPvl/aatxm2hHSco1S1cE5j -2FddUyGbQJJD+tZ3VTNPZNX70Cxqjm0lpu+F6ALEUz65noe8zDUa3qHpimOHZR4R -Kttjd5cUvpoUmRGywO6wT/gUITJDT5+rosuoD6o7BlXGEilXCNQ314cnrUlZp5Gr -RHpejXDbl85IULFzk/bwg2D5zfHhMf1bfHEhYxQUqq/F3pN+aLHsIqKqkHWetUNy -6mSjhEv9DKgma3GX7lZjZuhCVPnHHd/Qj1vfyDBviP4NxDMcU6ij/UgQ8uQKTuEV -V/xuZDDCVRHc6qnNSlSsKWNEz0pAoNZoWRsz+e86i9sgktxChL8Bq4fA1SCC28a5 -g4VCXA9DO2pJNdWY9BW/+mGBDAkgGNLQFwzLSABQ6XaCjGTXOqAHVcweMcDvOrRl -++O/QmueD6i9a5jc2NvLi6Td11n0bt3+qsOR0C5CB8AMTVPNJLFMWx5R9N/pkvo= ------END CERTIFICATE----- -# "Certplus Root CA G2" -# 6C C0 50 41 E6 44 5E 74 69 6C 4C FB C9 F8 0F 54 -# 3B 7E AB BB 44 B4 CE 6F 78 7C 6A 99 71 C4 2F 17 ------BEGIN CERTIFICATE----- -MIICHDCCAaKgAwIBAgISESDZkc6uo+jF5//pAq/Pc7xVMAoGCCqGSM49BAMDMD4x -CzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBs -dXMgUm9vdCBDQSBHMjAeFw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4x -CzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBs -dXMgUm9vdCBDQSBHMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABM0PW1aC3/BFGtat -93nwHcmsltaeTpwftEIRyoa/bfuFo8XlGVzX7qY/aWfYeOKmycTbLXku54uNAm8x -Ik0G42ByRZ0OQneezs/lf4WbGOT8zC5y0xaTTsqZY1yhBSpsBqNjMGEwDgYDVR0P -AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNqDYwJ5jtpMxjwj -FNiPwyCrKGBZMB8GA1UdIwQYMBaAFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMAoGCCqG -SM49BAMDA2gAMGUCMHD+sAvZ94OX7PNVHdTcswYO/jOYnYs5kGuUIe22113WTNch -p+e/IQ8rzfcq3IUHnQIxAIYUFuXcsGXCwI4Un78kFmjlvPl5adytRSv3tjFzzAal -U5ORGpOucGpnutee5WEaXw== ------END CERTIFICATE----- -# "certSIGN ROOT CA" -# EA A9 62 C4 FA 4A 6B AF EB E4 15 19 6D 35 1C CD -# 88 8D 4F 53 F3 FA 8A E6 D7 C4 66 A9 4E 60 42 BB ------BEGIN CERTIFICATE----- -MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT -AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD -QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP -MREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCC -ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7IJUqOtdu0KBuqV5Do -0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHHrfAQ -UySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5d -RdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQ -OA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv -JoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08C -AwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0O -BBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJ -LjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecY -MnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ -44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6I -Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw -i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN -9u6wWk5JRFRYX0KD ------END CERTIFICATE----- -# "Certum CA" -# D8 E0 FE BC 1D B2 E3 8D 00 94 0F 37 D2 7D 41 34 -# 4D 99 3E 73 4B 99 D5 65 6D 97 78 D4 D8 14 36 24 ------BEGIN CERTIFICATE----- -MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBM -MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD -QTAeFw0wMjA2MTExMDQ2MzlaFw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBM -MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD -QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6xwS7TT3zNJc4YPk/E -jG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdLkKWo -ePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GI -ULdtlkIJ89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapu -Ob7kky/ZR6By6/qmW6/KUz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUg -AKpoC6EahQGcxEZjgoi2IrHu/qpGWX7PNSzVttpd90gzFFS269lvzs2I1qsb2pY7 -HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEA -uI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+GXYkHAQa -TOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTg -xSvgGrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1q -CjqTE5s7FCMTY5w/0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5x -O/fIR/RpbxXyEV6DHpx8Uq79AtoSqFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs -6GAqm4VKQPNriiTsBhYscw== ------END CERTIFICATE----- -# "Certum Trusted Network CA" -# 5C 58 46 8D 55 F5 8E 49 7E 74 39 82 D2 B5 00 10 -# B6 D1 65 37 4A CF 83 A7 D4 A3 2D B7 68 C4 40 8E ------BEGIN CERTIFICATE----- -MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM -MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D -ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU -cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3 -WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg -Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw -IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B -AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH -UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM -TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU -BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM -kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x -AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV -HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y -sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL -I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8 -J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY -VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI -03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= ------END CERTIFICATE----- -# "Certum Trusted Network CA 2" -# B6 76 F2 ED DA E8 77 5C D3 6C B0 F6 3C D1 D4 60 -# 39 61 F4 9E 62 65 BA 01 3A 2F 03 07 B6 D0 B8 04 ------BEGIN CERTIFICATE----- -MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCB -gDELMAkGA1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMu -QS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIG -A1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAyMCIYDzIwMTExMDA2MDgz -OTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQTDEiMCAGA1UEChMZ -VW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3 -b3JrIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWA -DGSdhhuWZGc/IjoedQF97/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn -0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+oCgCXhVqqndwpyeI1B+twTUrWwbNWuKFB -OJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40bRr5HMNUuctHFY9rnY3lE -fktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2puTRZCr+E -Sv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1m -o130GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02i -sx7QBlrd9pPPV3WZ9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOW -OZV7bIBaTxNyxtd9KXpEulKkKtVBRgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgez -Tv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pyehizKV/Ma5ciSixqClnrDvFAS -adgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vMBhBgu4M1t15n -3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD -AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMC -AQYwDQYJKoZIhvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQ -F/xlhMcQSZDe28cmk4gmb3DWAl45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTf -CVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuAL55MYIR4PSFk1vtBHxgP58l1cb29 -XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMoclm2q8KMZiYcdywm -djWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tMpkT/ -WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jb -AoJnwTnbw3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksq -P/ujmv5zMnHCnsZy4YpoJ/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Ko -b7a6bINDd82Kkhehnlt4Fj1F4jNy3eFmypnTycUm/Q1oBEauttmbjL4ZvrHG8hnj -XALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLXis7VmFxWlgPF7ncGNf/P -5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7zAYspsbi -DrW5viSP ------END CERTIFICATE----- -# "CFCA EV ROOT" -# 5C C3 D7 8E 4E 1D 5E 45 54 7A 04 E6 87 3E 64 F9 -# 0C F9 53 6D 1C CC 2E F8 00 F3 55 C4 C5 FD 70 FD ------BEGIN CERTIFICATE----- -MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD -TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y -aXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkx -MjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5j -aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJP -T1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnVBU03 -sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpL -TIpTUnrD7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5 -/ZOkVIBMUtRSqy5J35DNuF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp -7hZZLDRJGqgG16iI0gNyejLi6mhNbiyWZXvKWfry4t3uMCz7zEasxGPrb382KzRz -EpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7xzbh72fROdOXW3NiGUgt -hxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9fpy25IGvP -a931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqot -aK8KgWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNg -TnYGmE69g60dWIolhdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfV -PKPtl8MeNPo4+QgO48BdK4PRVmrJtqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hv -cWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAfBgNVHSMEGDAWgBTj/i39KNAL -tbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd -BgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB -ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObT -ej/tUxPQ4i9qecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdL -jOztUmCypAbqTuv0axn96/Ua4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBS -ESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sGE5uPhnEFtC+NiWYzKXZUmhH4J/qy -P5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfXBDrDMlI1Dlb4pd19 -xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjnaH9d -Ci77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN -5mydLIhyPDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe -/v5WOaHIz16eGWRGENoXkbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+Z -AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ -5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su ------END CERTIFICATE----- -# "Chambers of Commerce Root" -# 0C 25 8A 12 A5 67 4A EF 25 F2 8B A7 DC FA EC EE -# A3 48 E5 41 E6 F5 CC 4E E6 3B 71 B3 61 60 6A C3 ------BEGIN CERTIFICATE----- -MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEn -MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL -ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMg -b2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAxNjEzNDNaFw0zNzA5MzAxNjEzNDRa -MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBB -ODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIw -IAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0B -AQEFAAOCAQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtb -unXF/KGIJPov7coISjlUxFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0d -BmpAPrMMhe5cG3nCYsS4No41XQEMIwRHNaqbYE6gZj3LJgqcQKH0XZi/caulAGgq -7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jWDA+wWFjbw2Y3npuRVDM3 -0pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFVd9oKDMyX -roDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIG -A1UdEwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5j -aGFtYmVyc2lnbi5vcmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p -26EpW1eLTXYGduHRooowDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIA -BzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hhbWJlcnNpZ24ub3JnMCcGA1Ud -EgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYDVR0gBFEwTzBN -BgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz -aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEB -AAxBl8IahsAifJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZd -p0AJPaxJRUXcLo0waLIJuvvDL8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi -1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wNUPf6s+xCX6ndbcj0dc97wXImsQEc -XCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/nADydb47kMgkdTXg0 -eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1erfu -tGWaIZDgqtCYvDi1czyL+Nw= ------END CERTIFICATE----- -# "Chambers of Commerce Root - 2008" -# 06 3E 4A FA C4 91 DF D3 32 F3 08 9B 85 42 E9 46 -# 17 D8 93 D7 FE 94 4E 10 A7 93 7E E2 9D 96 93 C0 ------BEGIN CERTIFICATE----- -MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYD -VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 -IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 -MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJz -IG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEyMjk1MFoXDTM4MDcz -MTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBj -dXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIw -EAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEp -MCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0G -CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW9 -28sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKAXuFixrYp4YFs8r/lfTJq -VKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorjh40G072Q -DuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR -5gN/ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfL -ZEFHcpOrUMPrCXZkNNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05a -Sd+pZgvMPMZ4fKecHePOjlO+Bd5gD2vlGts/4+EhySnB8esHnFIbAURRPHsl18Tl -UlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331lubKgdaX8ZSD6e2wsWsSaR6s -+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ0wlf2eOKNcx5 -Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj -ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAx -hduub+84Mxh2EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNV -HQ4EFgQU+SSsD7K1+HnA+mCIG8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1 -+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpN -YWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29t -L2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVy -ZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAt -IDIwMDiCCQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRV -HSAAMCowKAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20w -DQYJKoZIhvcNAQEFBQADggIBAJASryI1wqM58C7e6bXpeHxIvj99RZJe6dqxGfwW -PJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH3qLPaYRgM+gQDROpI9CF -5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbURWpGqOt1 -glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaH -FoI6M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2 -pSB7+R5KBWIBpih1YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MD -xvbxrN8y8NmBGuScvfaAFPDRLLmF9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QG -tjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcKzBIKinmwPQN/aUv0NCB9szTq -jktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvGnrDQWzilm1De -fhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg -OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZ -d0jQ ------END CERTIFICATE----- -# "Cisco Root CA 2048" -# 83 27 BC 8C 9D 69 94 7B 3D E3 C2 75 11 53 72 67 -# F5 9C 21 B9 FA 7B 61 3F AF BC CD 53 B7 02 40 00 ------BEGIN CERTIFICATE----- -MIIDQzCCAiugAwIBAgIQX/h7KCtU3I1CoxW1aMmt/zANBgkqhkiG9w0BAQUFADA1 -MRYwFAYDVQQKEw1DaXNjbyBTeXN0ZW1zMRswGQYDVQQDExJDaXNjbyBSb290IENB -IDIwNDgwHhcNMDQwNTE0MjAxNzEyWhcNMjkwNTE0MjAyNTQyWjA1MRYwFAYDVQQK -Ew1DaXNjbyBTeXN0ZW1zMRswGQYDVQQDExJDaXNjbyBSb290IENBIDIwNDgwggEg -MA0GCSqGSIb3DQEBAQUAA4IBDQAwggEIAoIBAQCwmrmrp68Kd6ficba0ZmKUeIhH -xmJVhEAyv8CrLqUccda8bnuoqrpu0hWISEWdovyD0My5jOAmaHBKeN8hF570YQXJ -FcjPFto1YYmUQ6iEqDGYeJu5Tm8sUxJszR2tKyS7McQr/4NEb7Y9JHcJ6r8qqB9q -VvYgDxFUl4F1pyXOWWqCZe+36ufijXWLbvLdT6ZeYpzPEApk0E5tzivMW/VgpSdH -jWn0f84bcN5wGyDWbs2mAag8EtKpP6BrXruOIIt6keO1aO6g58QBdKhTCytKmg9l -Eg6CTY5j/e/rmxrbU6YTYK/CfdfHbBcl1HP7R2RQgYCUTOG/rksc35LtLgXfAgED -o1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUJ/PI -FR5umgIJFq0roIlgX9p7L6owEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEF -BQADggEBAJ2dhISjQal8dwy3U8pORFBi71R803UXHOjgxkhLtv5MOhmBVrBW7hmW -Yqpao2TB9k5UM8Z3/sUcuuVdJcr18JOagxEu5sv4dEX+5wW4q+ffy0vhN4TauYuX -cB7w4ovXsNgOnbFp1iqRe6lJT37mjpXYgyc81WhJDtSd9i7rp77rMKSsH0T8lasz -Bvt9YAretIpjsJyp8qS5UwGH0GikJ3+r/+n6yUA4iGe0OcaEb1fJU9u6ju7AQ7L4 -CYNu/2bPPu8Xs1gYJQk0XuPL1hS27PKSb3TkL4Eq1ZKR4OCXPDJoBYVL0fdX4lId -kxpUnwVwwEpxYB5DC2Ae/qPOgRnhCzU= ------END CERTIFICATE----- -# "COMODO Certification Authority" -# 0C 2C D6 3D F7 80 6F A3 99 ED E8 09 11 6B 57 5B -# F8 79 89 F0 65 18 F9 80 8C 86 05 03 17 8B AF 66 ------BEGIN CERTIFICATE----- -MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB -gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G -A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV -BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw -MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl -YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P -RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 -UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI -2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 -Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp -+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ -DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O -nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW -/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g -PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u -QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY -SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv -IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ -RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 -zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd -BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB -ZQ== ------END CERTIFICATE----- -# "COMODO ECC Certification Authority" -# 17 93 92 7A 06 14 54 97 89 AD CE 2F 8F 34 F7 F0 -# B6 6D 0F 3A E3 A3 B8 4D 21 EC 15 DB BA 4F AD C7 ------BEGIN CERTIFICATE----- -MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL -MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE -BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT -IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw -MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy -ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N -T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR -FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J -cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW -BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ -BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm -fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv -GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= ------END CERTIFICATE----- -# "COMODO RSA Certification Authority" -# 52 F0 E1 C4 E5 8E C6 29 29 1B 60 31 7F 07 46 71 -# B8 5D 7E A8 0D 5B 07 27 34 63 53 4B 32 B4 02 34 ------BEGIN CERTIFICATE----- -MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB -hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G -A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV -BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5 -MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT -EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR -Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR -6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X -pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC -9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV -/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf -Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z -+pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w -qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah -SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC -u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf -Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq -crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E -FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB -/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl -wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM -4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV -2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna -FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ -CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK -boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke -jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL -S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb -QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl -0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB -NVOFBkpdn627G190 ------END CERTIFICATE----- -# "ComSign CA" -# AE 44 57 B4 0D 9E DA 96 67 7B 0D 3C 92 D5 7B 51 -# 77 AB D7 AC 10 37 95 83 56 D1 E0 94 51 8B E5 F2 ------BEGIN CERTIFICATE----- -MIIDkzCCAnugAwIBAgIQFBOWgxRVjOp7Y+X8NId3RDANBgkqhkiG9w0BAQUFADA0 -MRMwEQYDVQQDEwpDb21TaWduIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQG -EwJJTDAeFw0wNDAzMjQxMTMyMThaFw0yOTAzMTkxNTAyMThaMDQxEzARBgNVBAMT -CkNvbVNpZ24gQ0ExEDAOBgNVBAoTB0NvbVNpZ24xCzAJBgNVBAYTAklMMIIBIjAN -BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8ORUaSvTx49qROR+WCf4C9DklBKK -8Rs4OC8fMZwG1Cyn3gsqrhqg455qv588x26i+YtkbDqthVVRVKU4VbirgwTyP2Q2 -98CNQ0NqZtH3FyrV7zb6MBBC11PN+fozc0yz6YQgitZBJzXkOPqUm7h65HkfM/sb -2CEJKHxNGGleZIp6GZPKfuzzcuc3B1hZKKxC+cX/zT/npfo4sdAMx9lSGlPWgcxC -ejVb7Us6eva1jsz/D3zkYDaHL63woSV9/9JLEYhwVKZBqGdTUkJe5DSe5L6j7Kpi -Xd3DTKaCQeQzC6zJMw9kglcq/QytNuEMrkvF7zuZ2SOzW120V+x0cAwqTwIDAQAB -o4GgMIGdMAwGA1UdEwQFMAMBAf8wPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDovL2Zl -ZGlyLmNvbXNpZ24uY28uaWwvY3JsL0NvbVNpZ25DQS5jcmwwDgYDVR0PAQH/BAQD -AgGGMB8GA1UdIwQYMBaAFEsBmz5WGmU2dst7l6qSBe4y5ygxMB0GA1UdDgQWBBRL -AZs+VhplNnbLe5eqkgXuMucoMTANBgkqhkiG9w0BAQUFAAOCAQEA0Nmlfv4pYEWd -foPPbrxHbvUanlR2QnG0PFg/LUAlQvaBnPGJEMgOqnhPOAlXsDzACPw1jvFIUY0M -cXS6hMTXcpuEfDhOZAYnKuGntewImbQKDdSFc8gS4TXt8QUxHXOZDOuWyt3T5oWq -8Ir7dcHyCTxlZWTzTNity4hp8+SDtwy9F1qWF8pb/627HOkthIDYIb6FUtnUdLlp -hbpN7Sgy6/lhSuTENh4Z3G+EER+V9YMoGKgzkkMn3V0TBEVPh9VGzT2ouvDzuFYk -Res3x+F2T3I5GN9+dHLHcy056mDmrRGiVod7w2ia/viMcKjfZTL0pECMocJEAw6U -AGegcQCCSA== ------END CERTIFICATE----- -# "ComSign Global Root CA" -# 26 05 87 5A FC C1 76 B2 D6 6D D6 6A 99 5D 7F 8D -# 5E BB 86 CE 12 0D 0E 7E 9E 7C 6E F2 94 A2 7D 4C ------BEGIN CERTIFICATE----- -MIIGATCCA+mgAwIBAgIRAI9hcRW6eVgXjH0ROqzW264wDQYJKoZIhvcNAQELBQAw -RTEfMB0GA1UEAxMWQ29tU2lnbiBHbG9iYWwgUm9vdCBDQTEVMBMGA1UEChMMQ29t -U2lnbiBMdGQuMQswCQYDVQQGEwJJTDAeFw0xMTA3MTgxMDI0NTRaFw0zNjA3MTYx -MDI0NTVaMEUxHzAdBgNVBAMTFkNvbVNpZ24gR2xvYmFsIFJvb3QgQ0ExFTATBgNV -BAoTDENvbVNpZ24gTHRkLjELMAkGA1UEBhMCSUwwggIiMA0GCSqGSIb3DQEBAQUA -A4ICDwAwggIKAoICAQCyKClzKh3rm6n1nvigmV/VU1D4hSwYW2ro3VqpzpPo0Ph3 -3LguqjXd5juDwN4mpxTpD99d7Xu5X6KGTlMVtfN+bTbA4t3x7DU0Zqn0BE5XuOgs -3GLH41Vmr5wox1bShVpM+IsjcN4E/hMnDtt/Bkb5s33xCG+ohz5dlq0gA9qfr/g4 -O9lkHZXTCeYrmVzd/il4x79CqNvGkdL3um+OKYl8rg1dPtD8UsytMaDgBAopKR+W -igc16QJzCbvcinlETlrzP/Ny76BWPnAQgaYBULax/Q5thVU+N3sEOKp6uviTdD+X -O6i96gARU4H0xxPFI75PK/YdHrHjfjQevXl4J37FJfPMSHAbgPBhHC+qn/014DOx -46fEGXcdw2BFeIIIwbj2GH70VyJWmuk/xLMCHHpJ/nIF8w25BQtkPpkwESL6esaU -b1CyB4Vgjyf16/0nRiCAKAyC/DY/Yh+rDWtXK8c6QkXD2XamrVJo43DVNFqGZzbf -5bsUXqiVDOz71AxqqK+p4ek9374xPNMJ2rB5MLPAPycwI0bUuLHhLy6nAIFHLhut -TNI+6Y/soYpi5JSaEjcY7pxI8WIkUAzr2r+6UoT0vAdyOt7nt1y8844a7szo/aKf -woziHl2O1w6ZXUC30K+ptXVaOiW79pBDcbLZ9ZdbONhS7Ea3iH4HJNwktrBJLQID -AQABo4HrMIHoMA8GA1UdEwEB/wQFMAMBAf8wgYQGA1UdHwR9MHswPKA6oDiGNmh0 -dHA6Ly9mZWRpci5jb21zaWduLmNvLmlsL2NybC9jb21zaWduZ2xvYmFscm9vdGNh -LmNybDA7oDmgN4Y1aHR0cDovL2NybDEuY29tc2lnbi5jby5pbC9jcmwvY29tc2ln -bmdsb2JhbHJvb3RjYS5jcmwwDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBQCRZPY -DUhirGm6rgZbPvuqJpFQsTAfBgNVHSMEGDAWgBQCRZPYDUhirGm6rgZbPvuqJpFQ -sTANBgkqhkiG9w0BAQsFAAOCAgEAk1V5V9701xsfy4mfX+tP9Ln5e9h3N+QMwUfj -kr+k3e8iXOqADjTpUHeBkEee5tJq09ZLp/43F5tZ2eHdYq2ZEX7iWHCnOQet6Yw9 -SU1TahsrGDA6JJD9sdPFnNZooGsU1520e0zNB0dNWwxrWAmu4RsBxvEpWCJbvzQL -dOfyX85RWwli81OiVMBc5XvJ1mxsIIqli45oRynKtsWP7E+b0ISJ1n+XFLdQo/Nm -WA/5sDfT0F5YPzWdZymudMbXitimxC+n4oQE4mbQ4Zm718Iwg3pP9gMMcSc7Qc1J -kJHPH9O7gVubkKHuSYj9T3Ym6c6egL1pb4pz/uT7cT26Fiopc/jdqbe2EAfoJZkv -hlp/zdzOoXTWjiKNA5zmgWnZn943FuE9KMRyKtyi/ezJXCh8ypnqLIKxeFfZl69C -BwJsPXUTuqj8Fic0s3aZmmr7C4jXycP+Q8V+akMEIoHAxcd960b4wVWKqOcI/kZS -Q0cYqWOY1LNjznRt9lweWEfwDBL3FhrHOmD4++1N3FkkM4W+Q1b2WOL24clDMj+i -2n9Iw0lc1llHMSMvA5D0vpsXZpOgcCVahfXczQKi9wQ3oZyonJeWx4/rXdMtagAB -VBYGFuMEUEQtybI+eIbnp5peO2WAAblQI4eTy/jMVowe5tfMEXovV3sz9ULgmGb3 -DscLP1I= ------END CERTIFICATE----- -# "ComSign Secured CA" -# 50 79 41 C7 44 60 A0 B4 70 86 22 0D 4E 99 32 57 -# 2A B5 D1 B5 BB CB 89 80 AB 1C B1 76 51 A8 44 D2 ------BEGIN CERTIFICATE----- -MIIDqzCCApOgAwIBAgIRAMcoRwmzuGxFjB36JPU2TukwDQYJKoZIhvcNAQEFBQAw -PDEbMBkGA1UEAxMSQ29tU2lnbiBTZWN1cmVkIENBMRAwDgYDVQQKEwdDb21TaWdu -MQswCQYDVQQGEwJJTDAeFw0wNDAzMjQxMTM3MjBaFw0yOTAzMTYxNTA0NTZaMDwx -GzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBDQTEQMA4GA1UEChMHQ29tU2lnbjEL -MAkGA1UEBhMCSUwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGtWhf -HZQVw6QIVS3joFd67+l0Kru5fFdJGhFeTymHDEjWaueP1H5XJLkGieQcPOqs49oh -gHMhCu95mGwfCP+hUH3ymBvJVG8+pSjsIQQPRbsHPaHA+iqYHU4Gk/v1iDurX8sW -v+bznkqH7Rnqwp9D5PGBpX8QTz7RSmKtUxvLg/8HZaWSLWapW7ha9B20IZFKF3ue -Mv5WJDmyVIRD9YTC2LxBkMyd1mja6YJQqTtoz7VdApRgFrFD2UNd3V2Hbuq7s8lr -9gOUCXDeFhF6K+h2j0kQmHe5Y1yLM5d19guMsqtb3nQgJT/j8xH5h2iGNXHDHYwt -6+UarA9z1YJZQIDTAgMBAAGjgacwgaQwDAYDVR0TBAUwAwEB/zBEBgNVHR8EPTA7 -MDmgN6A1hjNodHRwOi8vZmVkaXIuY29tc2lnbi5jby5pbC9jcmwvQ29tU2lnblNl -Y3VyZWRDQS5jcmwwDgYDVR0PAQH/BAQDAgGGMB8GA1UdIwQYMBaAFMFL7XC29z58 -ADsAj8c+DkWfHl3sMB0GA1UdDgQWBBTBS+1wtvc+fAA7AI/HPg5Fnx5d7DANBgkq -hkiG9w0BAQUFAAOCAQEAFs/ukhNQq3sUnjO2QiBq1BW9Cav8cujvR3qQrFHBZE7p -iL1DRYHjZiM/EoZNGeQFsOY3wo3aBijJD4mkU6l1P7CW+6tMM1X5eCZGbxs2mPtC -dsGCuY7e+0X5YxtiOzkGynd6qDwJz2w2PQ8KRUtpFhpFfTMDZflScZAmlaxMDPWL -kz/MdXSFmLr/YnpNH4n+rr2UAJm/EaXc4HnFFgt9AmEd6oX5AhVP51qJThRv4zdL -hfXBPGHg/QVBspJ/wx2g0K5SZGBrGMYmnNj1ZOQ2GmKfig8+/21OGVZOIJFsnzQz -OjRXUDpvgV4GxvU+fE6OK85lBi5d0ipTdF7Tbieejw== ------END CERTIFICATE----- -# "D-TRUST Root CA 3 2013" -# A1 A8 6D 04 12 1E B8 7F 02 7C 66 F5 33 03 C2 8E -# 57 39 F9 43 FC 84 B3 8A D6 AF 00 90 35 DD 94 57 ------BEGIN CERTIFICATE----- -MIIEDjCCAvagAwIBAgIDD92sMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNVBAYTAkRF -MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxHzAdBgNVBAMMFkQtVFJVU1QgUm9vdCBD -QSAzIDIwMTMwHhcNMTMwOTIwMDgyNTUxWhcNMjgwOTIwMDgyNTUxWjBFMQswCQYD -VQQGEwJERTEVMBMGA1UECgwMRC1UcnVzdCBHbWJIMR8wHQYDVQQDDBZELVRSVVNU -IFJvb3QgQ0EgMyAyMDEzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA -xHtCkoIf7O1UmI4SwMoJ35NuOpNcG+QQd55OaYhs9uFp8vabomGxvQcgdJhl8Ywm -CM2oNcqANtFjbehEeoLDbF7eu+g20sRoNoyfMr2EIuDcwu4QRjltr5M5rofmw7wJ -ySxrZ1vZm3Z1TAvgu8XXvD558l++0ZBX+a72Zl8xv9Ntj6e6SvMjZbu376Ml1wrq -WLbviPr6ebJSWNXwrIyhUXQplapRO5AyA58ccnSQ3j3tYdLl4/1kR+W5t0qp9x+u -loYErC/jpIF3t1oW/9gPP/a3eMykr/pbPBJbqFKJcu+I89VEgYaVI5973bzZNO98 -lDyqwEHC451QGsDkGSL8swIDAQABo4IBBTCCAQEwDwYDVR0TAQH/BAUwAwEB/zAd -BgNVHQ4EFgQUP5DIfccVb/Mkj6nDL0uiDyGyL+cwDgYDVR0PAQH/BAQDAgEGMIG+ -BgNVHR8EgbYwgbMwdKByoHCGbmxkYXA6Ly9kaXJlY3RvcnkuZC10cnVzdC5uZXQv -Q049RC1UUlVTVCUyMFJvb3QlMjBDQSUyMDMlMjAyMDEzLE89RC1UcnVzdCUyMEdt -YkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MDugOaA3hjVodHRwOi8v -Y3JsLmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2FfM18yMDEzLmNybDAN -BgkqhkiG9w0BAQsFAAOCAQEADlkOWOR0SCNEzzQhtZwUGq2aS7eziG1cqRdw8Cqf -jXv5e4X6xznoEAiwNStfzwLS05zICx7uBVSuN5MECX1sj8J0vPgclL4xAUAt8yQg -t4RVLFzI9XRKEBmLo8ftNdYJSNMOwLo5qLBGArDbxohZwr78e7Erz35ih1WWzAFv -m2chlTWL+BD8cRu3SzdppjvW7IvuwbDzJcmPkn2h6sPKRL8mpXSSnON065102ctN -h9j8tGlsi6BDB2B4l+nZk3zCRrybN1Kj7Yo8E6l7U0tJmhEFLAtuVqwfLoJs4Gln -tQ5tLdnkwBXxP/oYcuEVbSdbLTAoK59ImmQrme/ydUlfXA== ------END CERTIFICATE----- -# "D-TRUST Root Class 3 CA 2 2009" -# 49 E7 A4 42 AC F0 EA 62 87 05 00 54 B5 25 64 B6 -# 50 E4 F4 9E 42 E3 48 D6 AA 38 E0 39 E9 57 B1 C1 ------BEGIN CERTIFICATE----- -MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF -MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD -bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha -ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM -HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB -BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03 -UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42 -tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R -ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM -lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp -/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G -A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G -A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj -dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy -MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl -cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js -L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL -BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni -acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 -o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K -zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8 -PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y -Johw1+qRzT65ysCQblrGXnRl11z+o+I= ------END CERTIFICATE----- -# "D-TRUST Root Class 3 CA 2 EV 2009" -# EE C5 49 6B 98 8C E9 86 25 B9 34 09 2E EC 29 08 -# BE D0 B0 F3 16 C2 D4 73 0C 84 EA F1 F3 D3 48 81 ------BEGIN CERTIFICATE----- -MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF -MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD -bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUw -NDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNV -BAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfSegpn -ljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM0 -3TP1YtHhzRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6Z -qQTMFexgaDbtCHu39b+T7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lR -p75mpoo6Kr3HGrHhFPC+Oh25z1uxav60sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8 -HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure3511H3a6UCAwEAAaOCASQw -ggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyvcop9Ntea -HNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFw -Oi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xh -c3MlMjAzJTIwQ0ElMjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1E -RT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MEagRKBChkBodHRwOi8vd3d3LmQt -dHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xhc3NfM19jYV8yX2V2XzIwMDku -Y3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+PPoeUSbrh/Yp -3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 -nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNF -CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na -xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX -KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1 ------END CERTIFICATE----- -# "Developer ID Certification Authority" -# 7A FC 9D 01 A6 2F 03 A2 DE 96 37 93 6D 4A FE 68 -# 09 0D 2D E1 8D 03 F2 9C 88 CF B0 B1 BA 63 58 7F ------BEGIN CERTIFICATE----- -MIIEBDCCAuygAwIBAgIIGHqpqMKWIQwwDQYJKoZIhvcNAQELBQAwYjELMAkGA1UE -BhMCVVMxEzARBgNVBAoTCkFwcGxlIEluYy4xJjAkBgNVBAsTHUFwcGxlIENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5MRYwFAYDVQQDEw1BcHBsZSBSb290IENBMB4XDTEy -MDIwMTIyMTIxNVoXDTI3MDIwMTIyMTIxNVoweTEtMCsGA1UEAwwkRGV2ZWxvcGVy -IElEIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSYwJAYDVQQLDB1BcHBsZSBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eTETMBEGA1UECgwKQXBwbGUgSW5jLjELMAkGA1UE -BhMCVVMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCJdk8GW5pB7qUj -KwKjX9dzP8A1sIuECj8GJH+nlT/rTw6Tr7QO0Mg+5W0Ysx/oiUe/1wkI5P9WmCkV -55SduTWjCs20wOHiYPTK7Cl4RWlpYGtfipL8niPmOsIiszFPHLrytjRZQu6wqQID -GJEEtrN4LjMfgEUNRW+7Dlpbfzrn2AjXCw4ybfuGNuRsq8QRinCEJqqfRNHxuMZ7 -lBebSPcLWBa6I8WfFTl+yl3DMl8P4FJ/QOq+rAhklVvJGpzlgMofakQcbD7EsCYf -Hex7r16gaj1HqVgSMT8gdihtHRywwk4RaSaLy9bQEYLJTg/xVnTQ2QhLZniiq6yn -4tJMh1nJAgMBAAGjgaYwgaMwHQYDVR0OBBYEFFcX7aLP3HyYoRDg/L6HLSzy4xdU -MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUK9BpR5R2Cf70a40uQKb3R01/ -CF4wLgYDVR0fBCcwJTAjoCGgH4YdaHR0cDovL2NybC5hcHBsZS5jb20vcm9vdC5j -cmwwDgYDVR0PAQH/BAQDAgGGMBAGCiqGSIb3Y2QGAgYEAgUAMA0GCSqGSIb3DQEB -CwUAA4IBAQBCOXRrodzGpI83KoyzHQpEvJUsf7xZuKxh+weQkjK51L87wVA5akR0 -ouxbH3Dlqt1LbBwjcS1f0cWTvu6binBlgp0W4xoQF4ktqM39DHhYSQwofzPuAHob -tHastrW7T9+oG53IGZdKC1ZnL8I+trPEgzrwd210xC4jUe6apQNvYPSlSKcGwrta -4h8fRkV+5Jf1JxC3ICJyb3LaxlB1xT0lj12jAOmfNoxIOY+zO+qQgC6VmmD0eM70 -DgpTPqL6T9geroSVjTK8Vk2J6XgY4KyaQrp6RhuEoonOFOiI0ViL9q5WxCwFKkWv -C9lLqQIPNKyIx2FViUTJJ3MH7oLlTvVw ------END CERTIFICATE----- -# "DigiCert Assured ID Root CA" -# 3E 90 99 B5 01 5E 8F 48 6C 00 BC EA 9D 11 1E E7 -# 21 FA BA 35 5A 89 BC F1 DF 69 56 1E 3D C6 32 5C ------BEGIN CERTIFICATE----- -MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv -b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl -cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c -JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP -mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ -wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 -VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ -AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB -AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW -BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun -pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC -dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf -fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm -NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx -H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe -+o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== ------END CERTIFICATE----- -# "DigiCert Assured ID Root G2" -# 7D 05 EB B6 82 33 9F 8C 94 51 EE 09 4E EB FE FA -# 79 53 A1 14 ED B2 F4 49 49 45 2F AB 7D 2F C1 85 ------BEGIN CERTIFICATE----- -MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv -b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl -cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA -n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc -biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp -EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA -bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu -YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB -AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW -BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI -QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I -0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni -lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9 -B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv -ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo -IhNzbM8m9Yop5w== ------END CERTIFICATE----- -# "DigiCert Assured ID Root G3" -# 7E 37 CB 8B 4C 47 09 0C AB 36 55 1B A6 F4 5D B8 -# 40 68 0F BA 16 6A 95 2D B1 00 71 7F 43 05 3F C2 ------BEGIN CERTIFICATE----- -MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw -CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu -ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg -RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV -UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu -Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq -hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf -Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q -RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ -BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD -AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY -JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv -6pZjamVFkpUBtA== ------END CERTIFICATE----- -# "DigiCert Global Root CA" -# 43 48 A0 E9 44 4C 78 CB 26 5E 05 8D 5E 89 44 B4 -# D8 4F 96 62 BD 26 DB 25 7F 89 34 A4 43 C7 01 61 ------BEGIN CERTIFICATE----- -MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD -QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT -MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j -b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB -CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 -nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt -43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P -T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 -gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO -BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR -TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw -DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr -hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg -06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF -PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls -YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk -CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= ------END CERTIFICATE----- -# "DigiCert Global Root G2" -# CB 3C CB B7 60 31 E5 E0 13 8F 8D D3 9A 23 F9 DE -# 47 FF C3 5E 43 C1 14 4C EA 27 D4 6A 5A B1 CB 5F ------BEGIN CERTIFICATE----- -MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH -MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT -MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j -b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI -2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx -1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ -q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz -tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ -vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP -BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV -5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY -1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4 -NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG -Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91 -8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe -pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl -MrY= ------END CERTIFICATE----- -# "DigiCert Global Root G3" -# 31 AD 66 48 F8 10 41 38 C7 38 F3 9E A4 32 01 33 -# 39 3E 3A 18 CC 02 29 6E F9 7C 2A C9 EF 67 31 D0 ------BEGIN CERTIFICATE----- -MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw -CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu -ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe -Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw -EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x -IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF -K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG -fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO -Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd -BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx -AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/ -oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8 -sycX ------END CERTIFICATE----- -# "DigiCert High Assurance EV Root CA" -# 74 31 E5 F4 C3 C1 CE 46 90 77 4F 0B 61 E0 54 40 -# 88 3B A9 A0 1E D0 0B A6 AB D7 80 6E D3 B1 18 CF ------BEGIN CERTIFICATE----- -MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j -ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL -MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 -LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug -RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm -+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW -PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM -xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB -Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 -hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg -EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF -MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA -FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec -nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z -eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF -hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 -Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe -vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep -+OkuE6N36B9K ------END CERTIFICATE----- -# "DigiCert Trusted Root G4" -# 55 2F 7B DC F1 A7 AF 9E 6C E6 72 01 7F 4F 12 AB -# F7 72 40 C7 8E 76 1A C2 03 D1 D9 D2 0A C8 99 88 ------BEGIN CERTIFICATE----- -MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg -RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV -UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu -Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y -ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If -xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV -ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO -DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ -jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/ -CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi -EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM -fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY -uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK -chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t -9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB -hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD -ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2 -SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd -+SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc -fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa -sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N -cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N -0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie -4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI -r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1 -/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm -gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+ ------END CERTIFICATE----- -# "DST Root CA X3" -# 06 87 26 03 31 A7 24 03 D9 09 F1 05 E6 9B CF 0D -# 32 E1 BD 24 93 FF C6 D9 20 6D 11 BC D6 77 07 39 ------BEGIN CERTIFICATE----- -MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ -MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT -DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow -PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD -Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O -rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq -OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b -xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw -7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD -aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV -HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG -SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 -ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr -AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz -R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 -JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo -Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ ------END CERTIFICATE----- -# "E-Tugra Certification Authority" -# B0 BF D5 2B B0 D7 D9 BD 92 BF 5D 4D C1 3D A2 55 -# C0 2C 54 2F 37 83 65 EA 89 39 11 F5 5E 55 F2 3C ------BEGIN CERTIFICATE----- -MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNV -BAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBC -aWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNV -BAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQDDB9FLVR1 -Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMwNTEyMDk0OFoXDTIz -MDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+ -BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhp -em1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN -ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 -MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4vU/kwVRHoViVF56C/UY -B4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vdhQd2h8y/L5VMzH2nPbxH -D5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5KCKpbknSF -Q9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEo -q1+gElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3D -k14opz8n8Y4e0ypQBaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcH -fC425lAcP9tDJMW/hkd5s3kc91r0E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsut -dEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gzrt48Ue7LE3wBf4QOXVGUnhMM -ti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAqjqFGOjGY5RH8 -zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn -rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUX -U8u3Zg5mTPj5dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6 -Jyr+zE7S6E5UMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5 -XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAF -Nzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAKkEh47U6YA5n+KGCR -HTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jOXKqY -GwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c -77NCR807VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3 -+GbHeJAAFS6LrVE1Uweoa2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WK -vJUawSg5TB9D0pH0clmKuVb8P7Sd2nCcdlqMQ1DujjByTd//SffGqWfZbawCEeI6 -FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEVKV0jq9BgoRJP3vQXzTLl -yb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gTDx4JnW2P -AJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpD -y4Q08ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8d -NL/+I5c30jn6PQ0GC7TbO6Orb1wdtn7os4I07QZcJA== ------END CERTIFICATE----- -# "Echoworx Root CA2" -# 66 39 D1 3C AB 85 DF 1A D9 A2 3C 44 3B 3A 60 90 -# 1E 2B 13 8D 45 6F A7 11 83 57 81 08 88 4E C6 BF ------BEGIN CERTIFICATE----- -MIIE5zCCA8+gAwIBAgIBADANBgkqhkiG9w0BAQUFADCBjTELMAkGA1UEBhMCQ0Ex -EDAOBgNVBAgTB09udGFyaW8xEDAOBgNVBAcTB1Rvcm9udG8xHTAbBgNVBAoTFEVj -aG93b3J4IENvcnBvcmF0aW9uMR8wHQYDVQQLExZDZXJ0aWZpY2F0aW9uIFNlcnZp -Y2VzMRowGAYDVQQDExFFY2hvd29yeCBSb290IENBMjAeFw0wNTEwMDYxMDQ5MTNa -Fw0zMDEwMDcxMDQ5MTNaMIGNMQswCQYDVQQGEwJDQTEQMA4GA1UECBMHT250YXJp -bzEQMA4GA1UEBxMHVG9yb250bzEdMBsGA1UEChMURWNob3dvcnggQ29ycG9yYXRp -b24xHzAdBgNVBAsTFkNlcnRpZmljYXRpb24gU2VydmljZXMxGjAYBgNVBAMTEUVj -aG93b3J4IFJvb3QgQ0EyMIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEA -utU/5BkV15UBf+s+JQruKQxr77s3rjp/RpOtmhHILIiO5gsEWP8MMrfrVEiidjI6 -Qh6ans0KAWc2Dw0/j4qKAQzOSyAZgjcdypNTBZ7muv212DA2Pu41rXqwMrlBrVi/ -KTghfdLlNRu6JrC5y8HarrnRFSKF1Thbzz921kLDRoCi+FVs5eVuK5LvIfkhNAqA -byrTgO3T9zfZgk8upmEkANPDL1+8y7dGPB/d6lk0I5mv8PESKX02TlvwgRSIiTHR -k8++iOPLBWlGp7ZfqTEXkPUZhgrQQvxcrwCUo6mk8TqgxCDP5FgPoHFiPLef5szP -ZLBJDWp7GLyE1PmkQI6WiwIBA6OCAVAwggFMMA8GA1UdEwEB/wQFMAMBAf8wCwYD -VR0PBAQDAgEGMB0GA1UdDgQWBBQ74YEboKs/OyGC1eISrq5QqxSlEzCBugYDVR0j -BIGyMIGvgBQ74YEboKs/OyGC1eISrq5QqxSlE6GBk6SBkDCBjTELMAkGA1UEBhMC -Q0ExEDAOBgNVBAgTB09udGFyaW8xEDAOBgNVBAcTB1Rvcm9udG8xHTAbBgNVBAoT -FEVjaG93b3J4IENvcnBvcmF0aW9uMR8wHQYDVQQLExZDZXJ0aWZpY2F0aW9uIFNl -cnZpY2VzMRowGAYDVQQDExFFY2hvd29yeCBSb290IENBMoIBADBQBgNVHSAESTBH -MEUGCysGAQQB+REKAQMBMDYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuZWNob3dv -cnguY29tL2NhL3Jvb3QyL2Nwcy5wZGYwDQYJKoZIhvcNAQEFBQADggEBAG+nrPi/ -0RpfEzrj02C6JGPUar4nbjIhcY6N7DWNeqBoUulBSIH/PYGNHYx7/lnJefiixPGE -7TQ5xPgElxb9bK8zoAApO7U33OubqZ7M7DlHnFeCoOoIAZnG1kuwKwD5CXKB2a74 -HzcqNnFW0IsBFCYqrVh/rQgJOzDA8POGbH0DeD0xjwBBooAolkKT+7ZItJF1Pb56 -QpDL9G+16F7GkmnKlAIYT3QTS3yFGYChnJcd+6txUPhKi9sSOOmAIaKHnkH9Scz+ -A2cSi4A3wUYXVatuVNHpRb2lygfH3SuCX9MU8Ure3zBlSU1LALtMqI4JmcQmQpIq -zIzvO2jHyu9PQqo= ------END CERTIFICATE----- -# "EE Certification Centre Root CA" -# 3E 84 BA 43 42 90 85 16 E7 75 73 C0 99 2F 09 79 -# CA 08 4E 46 85 68 1F F1 95 CC BA 8A 22 9B 8A 76 ------BEGIN CERTIFICATE----- -MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1 -MQswCQYDVQQGEwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1 -czEoMCYGA1UEAwwfRUUgQ2VydGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYG -CSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIwMTAxMDMwMTAxMDMwWhgPMjAzMDEy -MTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNl -ZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBS -b290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEB -AQUAA4IBDwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUy -euuOF0+W2Ap7kaJjbMeMTC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvO -bntl8jixwKIy72KyaOBhU8E2lf/slLo2rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIw -WFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw93X2PaRka9ZP585ArQ/d -MtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtNP2MbRMNE -1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYD -VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/ -zQas8fElyalL1BSZMEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYB -BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEF -BQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+RjxY6hUFaTlrg4wCQiZrxTFGGV -v9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqMlIpPnTX/dqQG -E5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u -uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIW -iAYLtqZLICjU3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/v -GVCJYMzpJJUPwssd8m92kMfMdcGWxZ0= ------END CERTIFICATE----- -# "Entrust Root Certification Authority" -# 73 C1 76 43 4F 1B C6 D5 AD F4 5B 0E 76 E7 27 28 -# 7C 8D E5 76 16 C1 E6 E6 14 1A 2B 2C BC 7D 8E 4C ------BEGIN CERTIFICATE----- -MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC -VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 -Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW -KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl -cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw -NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw -NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy -ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV -BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo -Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 -4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 -KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI -rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi -94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB -sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi -gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo -kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE -vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA -A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t -O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua -AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP -9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ -eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m -0vdXcDazv/wor3ElhVsT/h5/WrQ8 ------END CERTIFICATE----- -# "Entrust Root Certification Authority - EC1" -# 02 ED 0E B2 8C 14 DA 45 16 5C 56 67 91 70 0D 64 -# 51 D7 FB 56 F0 B2 AB 1D 3B 8E B0 70 E5 6E DF F5 ------BEGIN CERTIFICATE----- -MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG -A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3 -d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu -dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq -RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy -MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD -VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0 -L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g -Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD -ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi -A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt -ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH -Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O -BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC -R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX -hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G ------END CERTIFICATE----- -# "Entrust Root Certification Authority - G2" -# 43 DF 57 74 B0 3E 7F EF 5F E4 0D 93 1A 7B ED F1 -# BB 2E 6B 42 73 8C 4E 6D 38 41 10 3D 3A A7 F3 39 ------BEGIN CERTIFICATE----- -MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC -VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50 -cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs -IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz -dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy -NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu -dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt -dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0 -aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T -RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN -cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW -wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1 -U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0 -jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP -BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN -BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/ -jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ -Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v -1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R -nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH -VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g== ------END CERTIFICATE----- -# "Entrust.net Certification Authority (2048)" -# 6D C4 71 72 E0 1C BC B0 BF 62 58 0D 89 5F E2 B8 -# AC 9A D4 F8 73 80 1E 0C 10 B9 C8 37 D2 1E B1 77 ------BEGIN CERTIFICATE----- -MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML -RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp -bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 -IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3 -MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 -LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp -YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG -A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq -K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe -sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX -MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT -XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ -HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH -4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV -HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub -j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo -U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf -zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b -u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+ -bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er -fF6adulZkMV8gzURZVE= ------END CERTIFICATE----- -# "ePKI Root Certification Authority" -# C0 A6 F4 DC 63 A2 4B FD CF 54 EF 2A 6A 08 2A 0A -# 72 DE 35 80 3E 2F F5 FF 52 7A E5 D8 72 06 DF D5 ------BEGIN CERTIFICATE----- -MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe -MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 -ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe -Fw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMw -IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBL -SSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF -AAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAH -SyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAh -ijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X -DZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1 -TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJ -fzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffA -sgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uU -WH1+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLS -nT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pH -dmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJip -NiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDEC -AwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF -MAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH -ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGB -uvl2ICO1J2B01GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6Yl -PwZpVnPDimZI+ymBV3QGypzqKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkP -JXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/ -gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2 -j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+rGNm6 -5ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUB -o2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS -/jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2z -Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE -W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D -hNQ+IIX3Sj0rnP0qCglN6oH4EZw= ------END CERTIFICATE----- -# "GDCA TrustAUTH R5 ROOT" -# BF FF 8F D0 44 33 48 7D 6A 8A A6 0C 1A 29 76 7A -# 9F C2 BB B0 5E 42 0F 71 3A 13 B9 92 89 1D 38 93 ------BEGIN CERTIFICATE----- -MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UE -BhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ -IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0 -MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVowYjELMAkGA1UEBhMCQ04xMjAwBgNV -BAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8w -HQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0BAQEF -AAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJj -Dp6L3TQsAlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBj -TnnEt1u9ol2x8kECK62pOqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+u -KU49tm7srsHwJ5uu4/Ts765/94Y9cnrrpftZTqfrlYwiOXnhLQiPzLyRuEH3FMEj -qcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ9Cy5WmYqsBebnh52nUpm -MUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQxXABZG12 -ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloP -zgsMR6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3Gk -L30SgLdTMEZeS1SZD2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeC -jGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4oR24qoAATILnsn8JuLwwoC8N9VKejveSswoA -HQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx9hoh49pwBiFYFIeFd3mqgnkC -AwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlRMA8GA1UdEwEB -/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg -p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZm -DRd9FBUb1Ov9H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5 -COmSdI31R9KrO9b7eGZONn356ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ry -L3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd+PwyvzeG5LuOmCd+uh8W4XAR8gPf -JWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQHtZa37dG/OaG+svg -IHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBDF8Io -2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV -09tL7ECQ8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQ -XR4EzzffHqhmsYzmIGrv/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrq -T8p+ck0LcIymSLumoRT2+1hEmRSuqguTaaApJUqlyyvdimYHFngVV3Eb7PVHhPOe -MTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== ------END CERTIFICATE----- -# "GeoTrust Global CA" -# FF 85 6A 2D 25 1D CD 88 D3 66 56 F4 50 12 67 98 -# CF AB AA DE 40 79 9C 72 2D E4 D2 B5 DB 36 A7 3A ------BEGIN CERTIFICATE----- -MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT -MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i -YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG -EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg -R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 -9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq -fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv -iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU -1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ -bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW -MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA -ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l -uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn -Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS -tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF -PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un -hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV -5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== ------END CERTIFICATE----- -# "GeoTrust Primary Certification Authority" -# 37 D5 10 06 C5 12 EA AB 62 64 21 F1 EC 8C 92 01 -# 3F C5 F8 2A E9 8E E5 33 EB 46 19 B8 DE B4 D0 6C ------BEGIN CERTIFICATE----- -MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY -MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo -R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx -MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK -Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9 -AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA -ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0 -7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W -kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI -mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ -KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1 -6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl -4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K -oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj -UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU -AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= ------END CERTIFICATE----- -# "GeoTrust Primary Certification Authority - G2" -# 5E DB 7A C4 3B 82 A0 6A 87 61 E8 D7 BE 49 79 EB -# F2 61 1F 7D D7 9B F9 1C 1C 6B 56 6A 21 9E D7 66 ------BEGIN CERTIFICATE----- -MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDEL -MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChj -KSAyMDA3IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2 -MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 -eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1OVowgZgxCzAJBgNV -BAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykgMjAw -NyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNV -BAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH -MjB2MBAGByqGSM49AgEGBSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcL -So17VDs6bl8VAsBQps8lL33KSLjHUGMcKiEIfJo22Av+0SbFWDEwKCXzXV2juLal -tJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO -BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+EVXVMAoG -CCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGT -qQ7mndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBucz -rD6ogRLQy7rQkgu2npaqBA+K ------END CERTIFICATE----- -# "GeoTrust Primary Certification Authority - G3" -# B4 78 B8 12 25 0D F8 78 63 5C 2A A7 EC 7D 15 5E -# AA 62 5E E8 29 16 E2 CD 29 43 61 88 6C D1 FB D4 ------BEGIN CERTIFICATE----- -MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCB -mDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsT -MChjKSAyMDA4IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s -eTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv -cml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIzNTk1OVowgZgxCzAJ -BgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg -MjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0 -BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz -+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5jK/BGvESyiaHAKAxJcCGVn2TAppMSAmUm -hsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdEc5IiaacDiGydY8hS2pgn -5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3CIShwiP/W -JmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exAL -DmKudlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZC -huOl1UcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw -HQYDVR0OBBYEFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IB -AQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9cr5HqQ6XErhK8WTTOd8lNNTB -zU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbEAp7aDHdlDkQN -kv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD -AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH -SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G -spki4cErx5z481+oghLrGREt ------END CERTIFICATE----- -# "Global Chambersign Root" -# EF 3C B4 17 FC 8E BF 6F 97 87 6C 9E 4E CE 39 DE -# 1E A5 FE 64 91 41 D1 02 8B 7D 11 C0 B2 29 8C ED ------BEGIN CERTIFICATE----- -MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEn -MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL -ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENo -YW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYxNDE4WhcNMzcwOTMwMTYxNDE4WjB9 -MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgy -NzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4G -A1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUA -A4IBDQAwggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0 -Mi+ITaFgCPS3CU6gSS9J1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/s -QJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8Oby4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpV -eAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl6DJWk0aJqCWKZQbua795 -B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c8lCrEqWh -z0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0T -AQH/BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1i -ZXJzaWduLm9yZy9jaGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4w -TcbOX60Qq+UDpfqpFDAOBgNVHQ8BAf8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAH -MCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBjaGFtYmVyc2lnbi5vcmcwKgYD -VR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9yZzBbBgNVHSAE -VDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh -bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0B -AQUFAAOCAQEAPDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUM -bKGKfKX0j//U2K0X1S0E0T9YgOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXi -ryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJPJ7oKXqJ1/6v/2j1pReQvayZzKWG -VwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4IBHNfTIzSJRUTN3c -ecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREest2d/ -AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== ------END CERTIFICATE----- -# "Global Chambersign Root - 2008" -# 13 63 35 43 93 34 A7 69 80 16 A0 D3 24 DE 72 28 -# 4E 07 9D 7B 52 20 BB 8F BD 74 78 16 EE BE BA CA ------BEGIN CERTIFICATE----- -MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYD -VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 -IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 -MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD -aGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMxNDBaFw0zODA3MzEx -MjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3Vy -cmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAG -A1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAl -BgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZI -hvcNAQEBBQADggIPADCCAgoCggIBAMDfVtPkOpt2RbQT2//BthmLN0EYlVJH6xed -KYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXfXjaOcNFccUMd2drvXNL7 -G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0ZJJ0YPP2 -zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4 -ddPB/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyG -HoiMvvKRhI9lNNgATH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2 -Id3UwD2ln58fQ1DJu7xsepeY7s2MH/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3V -yJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfeOx2YItaswTXbo6Al/3K1dh3e -beksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSFHTynyQbehP9r -6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh -wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsog -zCtLkykPAgMBAAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQW -BBS5CcqcHtvTbDprru1U8VuTBjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDpr -ru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UEBhMCRVUxQzBBBgNVBAcTOk1hZHJp -ZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJmaXJtYS5jb20vYWRk -cmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJmaXJt -YSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiC -CQDJzdPp1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCow -KAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZI -hvcNAQEFBQADggIBAICIf3DekijZBZRG/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZ -UohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6ReAJ3spED8IXDneRRXoz -X1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/sdZ7LoR/x -fxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVz -a2Mg9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yyd -Yhz2rXzdpjEetrHHfoUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMd -SqlapskD7+3056huirRXhOukP9DuqqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9O -AP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETrP3iZ8ntxPjzxmKfFGBI/5rso -M0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVqc5iJWzouE4ge -v8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z -09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B ------END CERTIFICATE----- -# "GlobalSign" -# CA 42 DD 41 74 5F D0 B8 1E B9 02 36 2C F9 D8 BF -# 71 9D A1 BD 1B 1E FC 94 6F 5B 4C 99 F4 2C 1B 9E ------BEGIN CERTIFICATE----- -MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G -A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp -Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 -MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG -A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL -v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 -eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq -tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd -C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa -zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB -mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH -V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n -bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG -3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs -J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO -291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS -ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd -AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 -TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== ------END CERTIFICATE----- -# "GlobalSign" -# CB B5 22 D7 B7 F1 27 AD 6A 01 13 86 5B DF 1C D4 -# 10 2E 7D 07 59 AF 63 5A 7C F4 72 0D C9 63 C5 3B ------BEGIN CERTIFICATE----- -MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G -A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp -Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 -MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG -A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 -RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT -gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm -KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd -QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ -XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw -DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o -LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU -RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp -jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK -6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX -mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs -Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH -WD9f ------END CERTIFICATE----- -# "GlobalSign" -# 17 9F BC 14 8A 3D D0 0F D2 4E A1 34 58 CC 43 BF -# A7 F5 9C 81 82 D7 83 A5 13 F6 EB EC 10 0C 89 24 ------BEGIN CERTIFICATE----- -MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk -MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH -bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX -DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD -QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu -MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc -8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke -hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD -VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI -KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg -515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO -xwy8p2Fp8fc74SrL+SvzZpA3 ------END CERTIFICATE----- -# "GlobalSign" -# BE C9 49 11 C2 95 56 76 DB 6C 0A 55 09 86 D7 6E -# 3B A0 05 66 7C 44 2C 97 62 B4 FB B7 73 DE 22 8C ------BEGIN CERTIFICATE----- -MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk -MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH -bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX -DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD -QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ -FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw -DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F -uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX -kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs -ewv4n4Q= ------END CERTIFICATE----- -# "GlobalSign" -# 2C AB EA FE 37 D0 6C A2 2A BA 73 91 C0 03 3D 25 -# 98 29 52 C4 53 64 73 49 76 3A 3A B5 AD 6C CF 69 ------BEGIN CERTIFICATE----- -MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg -MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh -bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx -MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET -MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ -KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI -xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k -ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD -aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw -LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw -1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX -k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2 -SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h -bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n -WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY -rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce -MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD -AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu -bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN -nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt -Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61 -55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj -vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf -cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz -oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp -nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs -pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v -JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R -8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4 -5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= ------END CERTIFICATE----- -# "GlobalSign Root CA" -# EB D4 10 40 E4 BB 3E C7 42 C9 E3 81 D3 1E F2 A4 -# 1A 48 B6 68 5C 96 E7 CE F3 C1 DF 6C D4 33 1C 99 ------BEGIN CERTIFICATE----- -MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG -A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv -b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw -MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i -YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT -aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ -jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp -xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp -1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG -snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ -U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 -9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E -BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B -AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz -yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE -38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP -AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad -DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME -HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== ------END CERTIFICATE----- -# "Go Daddy Class 2 Certification Authority" -# C3 84 6B F2 4B 9E 93 CA 64 27 4C 0E C6 7C 1E CC -# 5E 02 4F FC AC D2 D7 40 19 35 0E 81 FE 54 6A E4 ------BEGIN CERTIFICATE----- -MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh -MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE -YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 -MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo -ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg -MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN -ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA -PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w -wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi -EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY -avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ -YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE -sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h -/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 -IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD -ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy -OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P -TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ -HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER -dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf -ReYNnyicsbkqWletNw+vHX/bvZ8= ------END CERTIFICATE----- -# "Go Daddy Root Certificate Authority - G2" -# 45 14 0B 32 47 EB 9C C8 C5 B4 F0 D7 B5 30 91 F7 -# 32 92 08 9E 6E 5A 63 E2 74 9D D3 AC A9 19 8E DA ------BEGIN CERTIFICATE----- -MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx -EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT -EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp -ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz -NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH -EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE -AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw -DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD -E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH -/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy -DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh -GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR -tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA -AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE -FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX -WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu -9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr -gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo -2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO -LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI -4uJEvlz36hz1 ------END CERTIFICATE----- -# "Government Root Certification Authority" -# 70 B9 22 BF DA 0E 3F 4A 34 2E 4E E2 2D 57 9A E5 -# 98 D0 71 CC 5E C9 C3 0F 12 36 80 34 03 88 AE A5 ------BEGIN CERTIFICATE----- -MIIFSzCCAzOgAwIBAgIRALZLiAfiI+7IXBKtpg4GofIwDQYJKoZIhvcNAQELBQAw -PzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dvdmVybm1lbnQgUm9vdCBDZXJ0aWZp -Y2F0aW9uIEF1dGhvcml0eTAeFw0xMjA5MjgwODU4NTFaFw0zNzEyMzExNTU5NTla -MD8xCzAJBgNVBAYTAlRXMTAwLgYDVQQKDCdHb3Zlcm5tZW50IFJvb3QgQ2VydGlm -aWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC -AQC2/5c8gb4BWCQnr44BK9ZykjAyG1+bfNTUf+ihYHMwVxAA+lCWJP5Q5ow6ldFX -eYTVZ1MMKoI+GFy4MCYa1l7GLbIEUQ7v3wxjR+vEEghRK5lxXtVpe+FdyXcdIOxW -juVhYC386RyA3/pqg7sFtR4jEpyCygrzFB0g5AaPQySZn7YKk1pzGxY5vgW28Yyl -ZJKPBeRcdvc5w88tvQ7Yy6gOMZvJRg9nU0MEj8iyyIOAX7ryD6uBNaIgIZfOD4k0 -eA/PH07p+4woPN405+2f0mb1xcoxeNLOUNFggmOd4Ez3B66DNJ1JSUPUfr0t4urH -cWWACOQ2nnlwCjyHKenkkpTqBpIpJ3jmrdc96QoLXvTg1oadLXLLi2RW5vSueKWg -OTNYPNyoj420ai39iHPplVBzBN8RiD5C1gJ0+yzEb7xs1uCAb9GGpTJXA9ZN9E4K -mSJ2fkpAgvjJ5E7LUy3Hsbbi08J1J265DnGyNPy/HE7CPfg26QrMWJqhGIZO4uGq -s3NZbl6dtMIIr69c/aQCb/+4DbvVq9dunxpPkUDwH0ZVbaCSw4nNt7H/HLPLo5wK -4/7NqrwB7N1UypHdTxOHpPaY7/1J1lcqPKZc9mA3v9g+fk5oKiMyOr5u5CI9ByTP -isubXVGzMNJxbc5Gim18SjNE2hIvNkvy6fFRCW3bapcOFwIDAQABo0IwQDAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBTVZx3gnHosnMvFmOcdByYqhux0zTAOBgNV -HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIBAJA75cJTQijq9TFOjj2Rnk0J -89ixUuZPrAwxIbvx6pnMg/y2KOTshAcOD06Xu29oRo8OURWV+Do7H1+CDgxxDryR -T64zLiNB9CZrTxOH+nj2LsIPkQWXqmrBap+8hJ4IKifd2ocXhuGzyl3tOKkpboTe -Rmv8JxlQpRJ6jH1i/NrnzLyfSa8GuCcn8on3Fj0Y5r3e9YwSkZ/jBI3+BxQaWqw5 -ghvxOBnhY+OvbLamURfr+kvriyL2l/4QOl+UoEtTcT9a4RD4co+WgN2NApgAYT2N -vC2xR8zaXeEgp4wxXPHj2rkKhkfIoT0Hozymc26Uke1uJDr5yTDRB6iBfSZ9fYTf -hsmL5a4NHr6JSFEVg5iWL0rrczTXdM3Jb9DCuiv2mv6Z3WAUjhv5nDk8f0OJU+jl -wqu+Iq0nOJt3KLejY2OngeepaUXrjnhWzAWEx/uttjB8YwWfLYwkf0uLkvw4Hp+g -pVezbp3YZLhwmmBScMip0P/GnO0QYV7Ngw5u6E0CQUridgR51lQ/ipgyFKDdLZzn -uoJxo4ZVKZnSKdt1OvfbQ/+2W/u3fjWAjg1srnm3Ni2XUqGwB5wH5Ss2zQOXlL0t -DjQG/MAWifw3VOTWzz0TBPKR2ck2Lj7FWtClTILD/y58Jnb38/1FoqVuVa4uzM8s -iTTa9g3nkagQ6hed8vbs ------END CERTIFICATE----- -# "GTS Root R1" -# 2A 57 54 71 E3 13 40 BC 21 58 1C BD 2C F1 3E 15 -# 84 63 20 3E CE 94 BC F9 D3 CC 19 6B F0 9A 54 72 ------BEGIN CERTIFICATE----- -MIIFWjCCA0KgAwIBAgIQbkepxUtHDA3sM9CJuRz04TANBgkqhkiG9w0BAQwFADBH -MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM -QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIy -MDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNl -cnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEB -AQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaM -f/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vX -mX7wCl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7 -zUjwTcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0P -fyblqAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtc -vfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4 -Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUsp -zBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOO -Rc92wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYW -k70paDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+ -DVrNVjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgF -lQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV -HQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBADiW -Cu49tJYeX++dnAsznyvgyv3SjgofQXSlfKqE1OXyHuY3UjKcC9FhHb8owbZEKTV1 -d5iyfNm9dKyKaOOpMQkpAWBz40d8U6iQSifvS9efk+eCNs6aaAyC58/UEBZvXw6Z -XPYfcX3v73svfuo21pdwCxXu11xWajOl40k4DLh9+42FpLFZXvRq4d2h9mREruZR -gyFmxhE+885H7pwoHyXa/6xmld01D1zvICxi/ZG6qcz8WpyTgYMpl0p8WnK0OdC3 -d8t5/Wk6kjftbjhlRn7pYL15iJdfOBL07q9bgsiG1eGZbYwE8na6SfZu6W0eX6Dv -J4J2QPim01hcDyxC2kLGe4g0x8HYRZvBPsVhHdljUEn2NIVq4BjFbkerQUIpm/Zg -DdIx02OYI5NaAIFItO/Nis3Jz5nu2Z6qNuFoS3FJFDYoOj0dzpqPJeaAcWErtXvM -+SUWgeExX6GjfhaknBZqlxi9dnKlC54dNuYvoS++cJEPqOba+MSSQGwlfnuzCdyy -F62ARPBopY+Udf90WuioAnwMCeKpSwughQtiue+hMZL77/ZRBIls6Kl0obsXs7X9 -SQ98POyDGCBDTtWTurQ0sR8WNh8M5mQ5Fkzc4P4dyKliPUDqysU0ArSuiYgzNdws -E3PYJ/HQcu51OyLemGhmW/HGY0dVHLqlCFF1pkgl ------END CERTIFICATE----- -# "GTS Root R2" -# C4 5D 7B B0 8E 6D 67 E6 2E 42 35 11 0B 56 4E 5F -# 78 FD 92 EF 05 8C 84 0A EA 4E 64 55 D7 58 5C 60 ------BEGIN CERTIFICATE----- -MIIFWjCCA0KgAwIBAgIQbkepxlqz5yDFMJo/aFLybzANBgkqhkiG9w0BAQwFADBH -MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM -QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIy -MDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNl -cnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEB -AQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3Lv -CvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3Kg -GjSY6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9Bu -XvAuMC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOd -re7kRXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXu -PuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1 -mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K -8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqj -x5RWIr9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsR -nTKaG73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0 -kzCqgc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9Ok -twIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV -HQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBALZp -8KZ3/p7uC4Gt4cCpx/k1HUCCq+YEtN/L9x0Pg/B+E02NjO7jMyLDOfxA325BS0JT -vhaI8dI4XsRomRyYUpOM52jtG2pzegVATX9lO9ZY8c6DR2Dj/5epnGB3GFW1fgiT -z9D2PGcDFWEJ+YF59exTpJ/JjwGLc8R3dtyDovUMSRqodt6Sm2T4syzFJ9MHwAiA -pJiS4wGWAqoC7o87xdFtCjMwc3i5T1QWvwsHoaRc5svJXISPD+AVdyx+Jn7axEvb -pxZ3B7DNdehyQtaVhJ2Gg/LkkM0JR9SLA3DaWsYDQvTtN6LwG1BUSw7YhN4ZKJmB -R64JGz9I0cNv4rBgF/XuIwKl2gBbbZCr7qLpGzvpx0QnRY5rn/WkhLx3+WuXrD5R -RaIRpsyF7gpo8j5QOHokYh4XIDdtak23CZvJ/KRY9bb7nE4Yu5UC56GtmwfuNmsk -0jmGwZODUNKBRqhfYlcsu2xkiAhu7xNUX90txGdj08+JN7+dIPT7eoOboB6BAFDC -5AwiWVIQ7UNWhwD4FFKnHYuTjKJNRn8nxnGbJN7k2oaLDX5rIMHAnuFl2GqjpuiF -izoHCBy69Y9Vmhh1fuXsgWbRIXOhNUQLgD1bnF5vKheW0YMjiGZt5obicDIvUiLn -yOd/xCxgXS/Dr55FBcOEArf9LAhST4Ldo/DUhgkC ------END CERTIFICATE----- -# "GTS Root R3" -# 15 D5 B8 77 46 19 EA 7D 54 CE 1C A6 D0 B0 C4 03 -# E0 37 A9 17 F1 31 E8 A0 4E 1E 6B 7A 71 BA BC E5 ------BEGIN CERTIFICATE----- -MIICDDCCAZGgAwIBAgIQbkepx2ypcyRAiQ8DVd2NHTAKBggqhkjOPQQDAzBHMQsw -CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU -MBIGA1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw -MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp -Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQA -IgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout -736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2A -DDL24CejQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud -DgQWBBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEAgFuk -fCPAlaUs3L6JbyO5o91lAFJekazInXJ0glMLfalAvWhgxeG4VDvBNhcl2MG9AjEA -njWSdIUlUfUk7GRSJFClH9voy8l27OyCbvWFGFPouOOaKaqW04MjyaR7YbPMAuhd ------END CERTIFICATE----- -# "GTS Root R4" -# 71 CC A5 39 1F 9E 79 4B 04 80 25 30 B3 63 E1 21 -# DA 8A 30 43 BB 26 66 2F EA 4D CA 7F C9 51 A4 BD ------BEGIN CERTIFICATE----- -MIICCjCCAZGgAwIBAgIQbkepyIuUtui7OyrYorLBmTAKBggqhkjOPQQDAzBHMQsw -CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU -MBIGA1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw -MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp -Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQA -IgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzu -hXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/l -xKvRHYqjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud -DgQWBBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNnADBkAjBqUFJ0 -CMRw3J5QdCHojXohw0+WbhXRIjVhLfoIN+4Zba3bssx9BzT1YBkstTTZbyACMANx -sbqjYAuG7ZoIapVon+Kz4ZNkfF6Tpt95LY2F45TPI11xzPKwTdb+mciUqXWi4w== ------END CERTIFICATE----- -# "Hellenic Academic and Research Institutions ECC RootCA 2015" -# 44 B5 45 AA 8A 25 E6 5A 73 CA 15 DC 27 FC 36 D2 -# 4C 1C B9 95 3A 06 65 39 B1 15 82 DC 48 7B 48 33 ------BEGIN CERTIFICATE----- -MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzAN -BgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl -c2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hl -bGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgRUNDIFJv -b3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEwMzcxMlowgaoxCzAJ -BgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmljIEFj -YWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5 -MUQwQgYDVQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0 -dXRpb25zIEVDQyBSb290Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKg -QehLgoRc4vgxEZmGZE4JJS+dQS8KrjVPdJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJa -jq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoKVlp8aQuqgAkkbH7BRqNC -MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFLQi -C4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaep -lSTAGiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7Sof -TUwJCA3sS61kFyjndc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR ------END CERTIFICATE----- -# "Hellenic Academic and Research Institutions RootCA 2011" -# BC 10 4F 15 A4 8B E7 09 DC A5 42 A7 E1 D4 B9 DF -# 6F 05 45 27 E8 02 EA A9 2D 59 54 44 25 8A FE 71 ------BEGIN CERTIFICATE----- -MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1Ix -RDBCBgNVBAoTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 -dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1p -YyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIFJvb3RDQSAyMDExMB4XDTExMTIw -NjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYTAkdSMUQwQgYDVQQK -EztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENl -cnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl -c2VhcmNoIEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEB -BQADggEPADCCAQoCggEBAKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPz -dYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJ -fel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa71HFK9+WXesyHgLacEns -bgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u8yBRQlqD -75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSP -FEDH3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNV -HRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp -5dgTBCPuQSUwRwYDVR0eBEAwPqA8MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQu -b3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQub3JnMA0GCSqGSIb3DQEBBQUA -A4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVtXdMiKahsog2p -6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 -TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7 -dIsXRSZMFpGD/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8Acys -Nnq/onN694/BtZqhFLKPM58N7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXI -l7WdmplNsDz4SgCbZN2fOUvRJ9e4 ------END CERTIFICATE----- -# "Hellenic Academic and Research Institutions RootCA 2015" -# A0 40 92 9A 02 CE 53 B4 AC F4 F2 FF C6 98 1C E4 -# 49 6F 75 5E 6D 45 FE 0B 2A 69 2B CD 52 52 3F 36 ------BEGIN CERTIFICATE----- -MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1Ix -DzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5k -IFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMT -N0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9v -dENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAxMTIxWjCBpjELMAkG -A1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNh -ZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkx -QDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 -dGlvbnMgUm9vdENBIDIwMTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC -AQDC+Kk/G4n8PDwEXT2QNrCROnk8ZlrvbTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA -4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+ehiGsxr/CL0BgzuNtFajT0 -AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+6PAQZe10 -4S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06C -ojXdFPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV -9Cz82XBST3i4vTwri5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrD -gfgXy5I2XdGj2HUb4Ysn6npIQf1FGQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6 -Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2fu/Z8VFRfS0myGlZYeCsargq -NhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9muiNX6hME6wGko -LfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc -Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNV -HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVd -ctA4GGqd83EkVAswDQYJKoZIhvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0I -XtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+D1hYc2Ryx+hFjtyp8iY/xnmMsVMI -M4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrMd/K4kPFox/la/vot -9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+yd+2V -Z5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/ea -j8GsGsVn82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnh -X9izjFk0WaSrT2y7HxjbdavYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQ -l033DlZdwJVqwjbDG2jJ9SrcR5q+ss7FJej6A7na+RZukYT1HCjI/CbM1xyQVqdf -bzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVtJ94Cj8rDtSvK6evIIVM4 -pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGaJI7ZjnHK -e7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0 -vm9qp/UsQu0yrbYhnr68 ------END CERTIFICATE----- -# "Hongkong Post Root CA 1" -# F9 E6 7D 33 6C 51 00 2A C0 54 C6 32 02 2D 66 DD -# A2 E7 E3 FF F1 0A D0 61 ED 31 D8 BB B4 10 CF B2 ------BEGIN CERTIFICATE----- -MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsx -FjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3Qg -Um9vdCBDQSAxMB4XDTAzMDUxNTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkG -A1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdr -b25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1ApzQ -jVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEn -PzlTCeqrauh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjh -ZY4bXSNmO7ilMlHIhqqhqZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9 -nnV0ttgCXjqQesBCNnLsak3c78QA3xMYV18meMjWCnl3v/evt3a5pQuEF10Q6m/h -q5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNVHRMBAf8ECDAGAQH/AgED -MA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7ih9legYsC -mEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI3 -7piol7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clB -oiMBdDhViw+5LmeiIAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJs -EhTkYY2sEJCehFC78JZvRZ+K88psT/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpO -fMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilTc4afU9hDDl3WY4JxHYB0yvbi -AmvZWg== ------END CERTIFICATE----- -# "IdenTrust Commercial Root CA 1" -# 5D 56 49 9B E4 D2 E0 8B CF CA D0 8A 3E 38 72 3D -# 50 50 3B DE 70 69 48 E4 2F 55 60 30 19 E5 28 AE ------BEGIN CERTIFICATE----- -MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBK -MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVu -VHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQw -MTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScw -JQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ldhNlT -3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU -+ehcCuz/mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gp -S0l4PJNgiCL8mdo2yMKi1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1 -bVoE/c40yiTcdCMbXTMTEl3EASX2MN0CXZ/g1Ue9tOsbobtJSdifWwLziuQkkORi -T0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl3ZBWzvurpWCdxJ35UrCL -vYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzyNeVJSQjK -Vsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZK -dHzVWYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHT -c+XvvqDtMwt0viAgxGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hv -l7yTmvmcEpB4eoCHFddydJxVdHixuuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5N -iGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB -/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZIhvcNAQELBQAD -ggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH -6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwt -LRvM7Kqas6pgghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93 -nAbowacYXVKV7cndJZ5t+qntozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3 -+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmVYjzlVYA211QC//G5Xc7UI2/YRYRK -W2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUXfeu+h1sXIFRRk0pT -AwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/rokTLq -l1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG -4iZZRHUe2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZ -mUlO+KWA2yUPHGNiiskzZ2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A -7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7RcGzM7vRX+Bi6hG6H ------END CERTIFICATE----- -# "IdenTrust Public Sector Root CA 1" -# 30 D0 89 5A 9A 44 8A 26 20 91 63 55 22 D1 F5 20 -# 10 B5 86 7A CA E1 2C 78 EF 95 8F D4 F4 38 9F 2F ------BEGIN CERTIFICATE----- -MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBN -MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVu -VHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcN -MzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0 -MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwggIi -MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTyP4o7 -ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGy -RBb06tD6Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlS -bdsHyo+1W/CD80/HLaXIrcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF -/YTLNiCBWS2ab21ISGHKTN9T0a9SvESfqy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R -3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoSmJxZZoY+rfGwyj4GD3vw -EUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFnol57plzy -9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9V -GxyhLrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ -2fjXctscvG29ZV/viDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsV -WaFHVCkugyhfHMKiq3IXAAaOReyL4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gD -W/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ -BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMwDQYJKoZIhvcN -AQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj -t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHV -DRDtfULAj+7AmgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9 -TaDKQGXSc3z1i9kKlT/YPyNtGtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8G -lwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFtm6/n6J91eEyrRjuazr8FGF1NFTwW -mhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMxNRF4eKLg6TCMf4Df -WN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4Mhn5 -+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJ -tshquDDIajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhA -GaQdp/lLQzfcaFpPz+vCZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv -8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ3Wl9af0AVqW3rLatt8o+Ae+c ------END CERTIFICATE----- -# "ISRG Root X1" -# 96 BC EC 06 26 49 76 F3 74 60 77 9A CF 28 C5 A7 -# CF E8 A3 C0 AA E1 1A 8F FC EE 05 C0 BD DF 08 C6 ------BEGIN CERTIFICATE----- -MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw -TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh -cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 -WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu -ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY -MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc -h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ -0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U -A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW -T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH -B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC -B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv -KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn -OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn -jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw -qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI -rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq -hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL -ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ -3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK -NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 -ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur -TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC -jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc -oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq -4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA -mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d -emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= ------END CERTIFICATE----- -# "Izenpe.com" -# 23 80 42 03 CA 45 D8 CD E7 16 B8 C1 3B F3 B4 48 -# 45 7F A0 6C C1 02 50 99 7F A0 14 58 31 7C 41 E5 ------BEGIN CERTIFICATE----- -MIIF8DCCA9igAwIBAgIPBuhGJy8fCo/RhFzjafbVMA0GCSqGSIb3DQEBBQUAMDgx -CzAJBgNVBAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjETMBEGA1UEAwwKSXpl -bnBlLmNvbTAeFw0wNzEyMTMxMzA4MjdaFw0zNzEyMTMwODI3MjVaMDgxCzAJBgNV -BAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjETMBEGA1UEAwwKSXplbnBlLmNv -bTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMnTesoPHqynhugWZWqx -whtFMnGV2f4QW8yv56V5AY+Jw8ryVXH3d753lPNypCxE2J6SmxQ6oeckkAoKVo7F -2CaU4dlI4S0+2gpy3aOZFdqBoof0e24md4lYrdbrDLJBenNubdt6eEHpCIgSfocu -ZhFjbFT7PJ1ywLwu/8K33Q124zrX97RovqL144FuwUZvXY3gTcZUVYkaMzEKsVe5 -o4qYw+w7NMWVQWl+dcI8IMVhulFHoCCQk6GQS/NOfIVFVJrRBSZBsLVNHTO+xAPI -JXzBcNs79AktVCdIrC/hxKw+yMuSTFM5NyPs0wH54AlETU1kwOENWocivK0bo/4m -tRXzp/yEGensoYi0RGmEg/OJ0XQGqcwL1sLeJ4VQJsoXuMl6h1YsGgEebL4TrRCs -tST1OJGh1kva8bvS3ke18byB9llrzxlT6Y0Vy0rLqW9E5RtBz+GGp8rQap+8TI0G -M1qiheWQNaBiXBZO8OOi+gMatCxxs1gs3nsL2xoP694hHwZ3BgOwye+Z/MC5TwuG -KP7Suerj2qXDR2kS4Nvw9hmL7Xtw1wLW7YcYKCwEJEx35EiKGsY7mtQPyvp10gFA -Wo15v4vPS8+qFsGV5K1Mij4XkdSxYuWC5YAEpAN+jb/af6IPl08M0w3719Hlcn4c -yHf/W5oPt64FRuXxqBbsR6QXAgMBAAGjgfYwgfMwgbAGA1UdEQSBqDCBpYEPaW5m -b0BpemVucGUuY29tpIGRMIGOMUcwRQYDVQQKDD5JWkVOUEUgUy5BLiAtIENJRiBB -MDEzMzcyNjAtUk1lcmMuVml0b3JpYS1HYXN0ZWl6IFQxMDU1IEY2MiBTODFDMEEG -A1UECQw6QXZkYSBkZWwgTWVkaXRlcnJhbmVvIEV0b3JiaWRlYSAxNCAtIDAxMDEw -IFZpdG9yaWEtR2FzdGVpejAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB -BjAdBgNVHQ4EFgQUHRxlDqjyJXu0kc/ksbHmvVV0bAUwDQYJKoZIhvcNAQEFBQAD -ggIBAMeBRm8hGE+gBe/n1bqXUKJg7aWSFBpSm/nxiEqg3Hh10dUflU7F57dp5iL0 -+CmoKom+z892j+Mxc50m0xwbRxYpB2iEitL7sRskPtKYGCwkjq/2e+pEFhsqxPqg -l+nqbFik73WrAGLRne0TNtsiC7bw0fRue0aHwp28vb5CO7dz0JoqPLRbEhYArxk5 -ja2DUBzIgU+9Ag89njWW7u/kwgN8KRwCfr00J16vU9adF79XbOnQgxCvv11N75B7 -XSus7Op9ACYXzAJcY9cZGKfsK8eKPlgOiofmg59OsjQerFQJTx0CCzl+gQgVuaBp -E8gyK+OtbBPWg50jLbJtooiGfqgNASYJQNntKE6MkyQP2/EeTXp6WuKlWPHcj1+Z -ggwuz7LdmMySlD/5CbOlliVbN/UShUHiGUzGigjB3Bh6Dx4/glmimj4/+eAJn/3B -kUtdyXvWton83x18hqrNA/ILUpLxYm9/h+qrdslsUMIZgq+qHfUgKGgu1fxkN0/P -pUTEvnK0jHS0bKf68r10OEMr3q/53NjgnZ/cPcqlY0S/kqJPTIAcuxrDmkoEVU3K -7iYLHL8CxWTTnn7S05EcS6L1HOUXHA0MUqORH5zwIe0ClG+poEnK6EOMxPQ02nwi -o8ZmPrgbBYhdurz3vOXcFD2nhqi2WVIhA16L4wTtSyoeo09Q ------END CERTIFICATE----- -# "Izenpe.com" -# 25 30 CC 8E 98 32 15 02 BA D9 6F 9B 1F BA 1B 09 -# 9E 2D 29 9E 0F 45 48 BB 91 4F 36 3B C0 D4 53 1F ------BEGIN CERTIFICATE----- -MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4 -MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6 -ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD -VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j -b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq -scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO -xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H -LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX -uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD -yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+ -JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q -rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN -BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L -hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB -QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+ -HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu -Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg -QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB -BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx -MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA -A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb -laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56 -awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo -JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw -LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT -VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk -LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb -UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/ -QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+ -naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls -QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== ------END CERTIFICATE----- -# "KISA RootCA 1" -# 6F DB 3F 76 C8 B8 01 A7 53 38 D8 A5 0A 7C 02 87 -# 9F 61 98 B5 7E 59 4D 31 8D 38 32 90 0F ED CD 79 ------BEGIN CERTIFICATE----- -MIIDczCCAlugAwIBAgIBBDANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJLUjEN -MAsGA1UECgwES0lTQTEuMCwGA1UECwwlS29yZWEgQ2VydGlmaWNhdGlvbiBBdXRo -b3JpdHkgQ2VudHJhbDEWMBQGA1UEAwwNS0lTQSBSb290Q0EgMTAeFw0wNTA4MjQw -ODA1NDZaFw0yNTA4MjQwODA1NDZaMGQxCzAJBgNVBAYTAktSMQ0wCwYDVQQKDARL -SVNBMS4wLAYDVQQLDCVLb3JlYSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBDZW50 -cmFsMRYwFAYDVQQDDA1LSVNBIFJvb3RDQSAxMIIBIDANBgkqhkiG9w0BAQEFAAOC -AQ0AMIIBCAKCAQEAvATk+hM58DSWIGtsaLv623f/J/es7C/n/fB/bW+MKs0lCVsk -9KFo/CjsySXirO3eyDOE9bClCTqnsUdIxcxPjHmc+QZXfd3uOPbPFLKc6tPAXXdi -8EcNuRpAU1xkcK8IWsD3z3X5bI1kKB4g/rcbGdNaZoNy4rCbvdMlFQ0yb2Q3lIVG -yHK+d9VuHygvx2nt54OJM1jT3qC/QOhDUO7cTWu8peqmyGGO9cNkrwYV3CmLP3WM -vHFE2/yttRcdbYmDz8Yzvb9Fov4Kn6MRXw+5H5wawkbMnChmn3AmPC7fqoD+jMUE -CSVPzZNHPDfqAmeS/vwiJFys0izgXAEzisEZ2wIBA6MyMDAwHQYDVR0OBBYEFL+2 -J9gDWnZlTGEBQVYx5Yt7OtnMMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEF -BQADggEBABOvUQveimpb5poKyLGQSk6hAp3MiNKrZr097LuxQpVqslxa/6FjZJap -aBV/JV6K+KRzwYCKhQoOUugy50X4TmWAkZl0Q+VFnUkq8JSV3enhMNITbslOsXfl -BM+tWh6UCVrXPAgcrnrpFDLBRa3SJkhyrKhB2vAhhzle3/xk/2F0KpzZm4tfwjeT -2KM3LzuTa7IbB6d/CVDv0zq+IWuKkDsnSlFOa56ch534eJAx7REnxqhZvvwYC/uO -fi5C4e3nCSG9uRPFVmf0JqZCQ5BEVLRxm3bkGhKsGigA35vB1fjbXKP4krG9tNT5 -UNkAAk/bg9ART6RCVmE6fhMy04Qfybo= ------END CERTIFICATE----- -# "Microsec e-Szigno Root CA 2009" -# 3C 5F 81 FE A5 FA B8 2C 64 BF A2 EA EC AF CD E8 -# E0 77 FC 86 20 A7 CA E5 37 16 3D F3 6E DB F3 78 ------BEGIN CERTIFICATE----- -MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD -VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0 -ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G -CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y -OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx -FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp -Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o -dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP -kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc -cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U -fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7 -N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC -xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1 -+rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G -A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM -Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG -SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h -mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk -ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 -tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c -2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t -HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW ------END CERTIFICATE----- -# "NetLock Arany (Class Gold) Főtanúsítvány" -# 6C 61 DA C3 A2 DE F0 31 50 6B E0 36 D2 A6 FE 40 -# 19 94 FB D1 3D F9 C8 D4 66 59 92 74 C4 46 EC 98 ------BEGIN CERTIFICATE----- -MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG -EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3 -MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl -cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR -dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB -pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM -b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm -aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz -IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT -lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz -AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5 -VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG -ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2 -BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG -AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M -U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh -bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C -+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC -bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F -uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2 -XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= ------END CERTIFICATE----- -# "Network Solutions Certificate Authority" -# 15 F0 BA 00 A3 AC 7A F3 AC 88 4C 07 2B 10 11 A0 -# 77 BD 77 C0 97 F4 01 64 B2 F8 59 8A BD 83 86 0C ------BEGIN CERTIFICATE----- -MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi -MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu -MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp -dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV -UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO -ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz -c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP -OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl -mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF -BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4 -qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw -gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB -BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu -bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp -dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8 -6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/ -h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH -/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv -wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN -pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey ------END CERTIFICATE----- -# "OISTE WISeKey Global Root GA CA" -# 41 C9 23 86 6A B4 CA D6 B7 AD 57 80 81 58 2E 02 -# 07 97 A6 CB DF 4F FF 78 CE 83 96 B3 89 37 D7 F5 ------BEGIN CERTIFICATE----- -MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCB -ijELMAkGA1UEBhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHly -aWdodCAoYykgMjAwNTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl -ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQSBDQTAeFw0w -NTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYDVQQGEwJDSDEQMA4G -A1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIwIAYD -VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBX -SVNlS2V5IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAy0+zAJs9Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxR -VVuuk+g3/ytr6dTqvirdqFEr12bDYVxgAsj1znJ7O7jyTmUIms2kahnBAbtzptf2 -w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbDd50kc3vkDIzh2TbhmYsF -mQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ/yxViJGg -4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t9 -4B3RLoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYw -DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQw -EAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOx -SPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vImMMkQyh2I+3QZH4VFvbBsUfk2 -ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4+vg1YFkCExh8 -vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa -hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZi -Fj4A4xylNoEYokxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ -/L7fCg0= ------END CERTIFICATE----- -# "OISTE WISeKey Global Root GB CA" -# 6B 9C 08 E8 6E B0 F7 67 CF AD 65 CD 98 B6 21 49 -# E5 49 4A 67 F5 84 5E 7B D1 ED 01 9F 27 B8 6B D6 ------BEGIN CERTIFICATE----- -MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBt -MQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUg -Rm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9i -YWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAwMzJaFw0zOTEyMDExNTEwMzFaMG0x -CzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBG -b3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh -bCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3 -HEokKtaXscriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGx -WuR51jIjK+FTzJlFXHtPrby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX -1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNk -u7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4oQnc/nSMbsrY9gBQHTC5P -99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvgGUpuuy9r -M2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw -AwEB/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUB -BAMCAQAwDQYJKoZIhvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrgh -cViXfa43FK8+5/ea4n32cZiZBKpDdHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5 -gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0VQreUGdNZtGn//3ZwLWoo4rO -ZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEuiHZeeevJuQHHf -aPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic -Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= ------END CERTIFICATE----- -# "OISTE WISeKey Global Root GC CA" -# 85 60 F9 1C 36 24 DA BA 95 70 B5 FE A0 DB E3 6F -# F1 1A 83 23 BE 94 86 85 4F B3 F3 4A 55 71 19 8D ------BEGIN CERTIFICATE----- -MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQsw -CQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91 -bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwg -Um9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRaFw00MjA1MDkwOTU4MzNaMG0xCzAJ -BgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBGb3Vu -ZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBS -b290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4ni -eUqjFqdrVCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4W -p2OQ0jnUsYd4XxiWD1AbNTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8E -BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7T -rYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0EAwMDaAAwZQIwJsdpW9zV -57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtkAjEA2zQg -Mgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 ------END CERTIFICATE----- -# "OpenTrust Root CA G1" -# 56 C7 71 28 D9 8C 18 D9 1B 4C FD FF BC 25 EE 91 -# 03 D4 75 8E A2 AB AD 82 6A 90 F3 45 7D 46 0E B4 ------BEGIN CERTIFICATE----- -MIIFbzCCA1egAwIBAgISESCzkFU5fX82bWTCp59rY45nMA0GCSqGSIb3DQEBCwUA -MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9w -ZW5UcnVzdCBSb290IENBIEcxMB4XDTE0MDUyNjA4NDU1MFoXDTM4MDExNTAwMDAw -MFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwU -T3BlblRydXN0IFJvb3QgQ0EgRzEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK -AoICAQD4eUbalsUwXopxAy1wpLuwxQjczeY1wICkES3d5oeuXT2R0odsN7faYp6b -wiTXj/HbpqbfRm9RpnHLPhsxZ2L3EVs0J9V5ToybWL0iEA1cJwzdMOWo010hOHQX -/uMftk87ay3bfWAfjH1MBcLrARYVmBSO0ZB3Ij/swjm4eTrwSSTilZHcYTSSjFR0 -77F9jAHiOH3BX2pfJLKOYheteSCtqx234LSWSE9mQxAGFiQD4eCcjsZGT44ameGP -uY4zbGneWK2gDqdkVBFpRGZPTBKnjix9xNRbxQA0MMHZmf4yzgeEtE7NCv82TWLx -p2NX5Ntqp66/K7nJ5rInieV+mhxNaMbBGN4zK1FGSxyO9z0M+Yo0FMT7MzUj8czx -Kselu7Cizv5Ta01BG2Yospb6p64KTrk5M0ScdMGTHPjgniQlQ/GbI4Kq3ywgsNw2 -TgOzfALU5nsaqocTvz6hdLubDuHAk5/XpGbKuxs74zD0M1mKB3IDVedzagMxbm+W -G+Oin6+Sx+31QrclTDsTBM8clq8cIqPQqwWyTBIjUtz9GVsnnB47ev1CI9sjgBPw -vFEVVJSmdz7QdFG9URQIOTfLHzSpMJ1ShC5VkLG631UAC9hWLbFJSXKAqWLXwPYY -EQRVzXR7z2FwefR7LFxckvzluFqrTJOVoSfupb7PcSNCupt2LQIDAQABo2MwYTAO -BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUl0YhVyE1 -2jZVx/PxN3DlCPaTKbYwHwYDVR0jBBgwFoAUl0YhVyE12jZVx/PxN3DlCPaTKbYw -DQYJKoZIhvcNAQELBQADggIBAB3dAmB84DWn5ph76kTOZ0BP8pNuZtQ5iSas000E -PLuHIT839HEl2ku6q5aCgZG27dmxpGWX4m9kWaSW7mDKHyP7Rbr/jyTwyqkxf3kf -gLMtMrpkZ2CvuVnN35pJ06iCsfmYlIrM4LvgBBuZYLFGZdwIorJGnkSI6pN+VxbS -FXJfLkur1J1juONI5f6ELlgKn0Md/rcYkoZDSw6cMoYsYPXpSOqV7XAp8dUv/TW0 -V8/bhUiZucJvbI/NeJWsZCj9VrDDb8O+WVLhX4SPgPL0DTatdrOjteFkdjpY3H1P -XlZs5VVZV6Xf8YpmMIzUUmI4d7S+KNfKNsSbBfD4Fdvb8e80nR14SohWZ25g/4/I -i+GOvUKpMwpZQhISKvqxnUOOBZuZ2mKtVzazHbYNeS2WuOvyDEsMpZTGMKcmGS3t -TAZQMPH9WD25SxdfGbRqhFS0OE85og2WaMMolP3tLR9Ka0OWLpABEPs4poEL0L91 -09S5zvE/bw4cHjdx5RiHdRk/ULlepEU0rbDK5uUTdg8xFKmOLZTW1YVNcxVPS/Ky -Pu1svf0OnWZzsD2097+o4BGkxK51CUpjAEggpsadCwmKtODmzj7HPiY46SvepghJ -AwSQiumPv+i2tCqjI40cHLI5kqiPAlxAOXXUc0ECd97N4EOH1uS6SsNsEn/+KuYj -1oxx ------END CERTIFICATE----- -# "OpenTrust Root CA G2" -# 27 99 58 29 FE 6A 75 15 C1 BF E8 48 F9 C4 76 1D -# B1 6C 22 59 29 25 7B F4 0D 08 94 F2 9E A8 BA F2 ------BEGIN CERTIFICATE----- -MIIFbzCCA1egAwIBAgISESChaRu/vbm9UpaPI+hIvyYRMA0GCSqGSIb3DQEBDQUA -MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9w -ZW5UcnVzdCBSb290IENBIEcyMB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAw -MFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwU -T3BlblRydXN0IFJvb3QgQ0EgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK -AoICAQDMtlelM5QQgTJT32F+D3Y5z1zCU3UdSXqWON2ic2rxb95eolq5cSG+Ntmh -/LzubKh8NBpxGuga2F8ORAbtp+Dz0mEL4DKiltE48MLaARf85KxP6O6JHnSrT78e -CbY2albz4e6WiWYkBuTNQjpK3eCasMSCRbP+yatcfD7J6xcvDH1urqWPyKwlCm/6 -1UWY0jUJ9gNDlP7ZvyCVeYCYitmJNbtRG6Q3ffyZO6v/v6wNj0OxmXsWEH4db0fE -FY8ElggGQgT4hNYdvJGmQr5J1WqIP7wtUdGejeBSzFfdNTVY27SPJIjki9/ca1TS -gSuyzpJLHB9G+h3Ykst2Z7UJmQnlrBcUVXDGPKBWCgOz3GIZ38i1MH/1PCZ1Eb3X -G7OHngevZXHloM8apwkQHZOJZlvoPGIytbU6bumFAYueQ4xncyhZW+vj3CzMpSZy -YhK05pyDRPZRpOLAeiRXyg6lPzq1O4vldu5w5pLeFlwoW5cZJ5L+epJUzpM5ChaH -vGOz9bGTXOBut9Dq+WIyiET7vycotjCVXRIouZW+j1MY5aIYFuJWpLIsEPUdN6b4 -t/bQWVyJ98LVtZR00dX+G7bw5tYee9I8y6jj9RjzIR9u701oBnstXW5DiabA+aC/ -gh7PU3+06yzbXfZqfUAkBXKJOAGTy3HCOV0GEfZvePg3DTmEJwIDAQABo2MwYTAO -BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUajn6QiL3 -5okATV59M4PLuG53hq8wHwYDVR0jBBgwFoAUajn6QiL35okATV59M4PLuG53hq8w -DQYJKoZIhvcNAQENBQADggIBAJjLq0A85TMCl38th6aP1F5Kr7ge57tx+4BkJamz -Gj5oXScmp7oq4fBXgwpkTx4idBvpkF/wrM//T2h6OKQQbA2xx6R3gBi2oihEdqc0 -nXGEL8pZ0keImUEiyTCYYW49qKgFbdEfwFFEVn8nNQLdXpgKQuswv42hm1GqO+qT -RmTFAHneIWv2V6CG1wZy7HBGS4tz3aAhdT7cHcCP009zHIXZ/n9iyJVvttN7jLpT -wm+bREx50B1ws9efAvSyB7DH5fitIw6mVskpEndI2S9G/Tvw/HRwkqWOOAgfZDC2 -t0v7NqwQjqBSM2OdAzVWxWm9xiNaJ5T2pBL4LTM8oValX9YZ6e18CL13zSdkzJTa -TkZQh+D5wVOAHrut+0dSixv9ovneDiK3PTNZbNTe9ZUGMg1RGUFcPk8G97krgCf2 -o6p6fAbhQ8MTOWIaNr3gKC6UAuQpLmBVrkA9sHSSXvAgZJY/X0VdiLWK2gKgW0VU -3jg9CcCoSmVGFvyqv1ROTVu+OEO3KMqLM6oaJbolXCkvW0pujOotnCr2BXbgd5eA -iN1nE28daCSLT7d0geX0YJ96Vdc+N9oWaz53rK4YcJUIeSkDiv7BO7M/Gg+kO14f -WKGVyasvc0rQLW6aWQ9VGHgtPFGml4vmu7JwqkwR3v98KzfUetF3NI/n+UL3PIEM -S1IK ------END CERTIFICATE----- -# "OpenTrust Root CA G3" -# B7 C3 62 31 70 6E 81 07 8C 36 7C B8 96 19 8F 1E -# 32 08 DD 92 69 49 DD 8F 57 09 A4 10 F7 5B 62 92 ------BEGIN CERTIFICATE----- -MIICITCCAaagAwIBAgISESDm+Ez8JLC+BUCs2oMbNGA/MAoGCCqGSM49BAMDMEAx -CzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5U -cnVzdCBSb290IENBIEczMB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFow -QDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwUT3Bl -blRydXN0IFJvb3QgQ0EgRzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARK7liuTcpm -3gY6oxH84Bjwbhy6LTAMidnW7ptzg6kjFYwvWYpa3RTqnVkrQ7cG7DK2uu5Bta1d -oYXM6h0UZqNnfkbilPPntlahFVmhTzeXuSIevRHr9LIfXsMUmuXZl5mjYzBhMA4G -A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRHd8MUi2I5 -DMlv4VBN0BBY3JWIbTAfBgNVHSMEGDAWgBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAK -BggqhkjOPQQDAwNpADBmAjEAj6jcnboMBBf6Fek9LykBl7+BFjNAk2z8+e2AcG+q -j9uEwov1NcoG3GRvaBbhj5G5AjEA2Euly8LQCGzpGPta3U1fJAuwACEl74+nBCZx -4nxp5V2a+EEfOzmTk51V6s2N8fvB ------END CERTIFICATE----- -# "QuoVadis Root CA 1 G3" -# 8A 86 6F D1 B2 76 B5 7E 57 8E 92 1C 65 82 8A 2B -# ED 58 E9 F2 F2 88 05 41 34 B7 F1 F4 BF C9 CC 74 ------BEGIN CERTIFICATE----- -MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQEL -BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc -BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00 -MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM -aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzMwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakEPBtV -wedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWe -rNrwU8lmPNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF341 -68Xfuw6cwI2H44g4hWf6Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh -4Pw5qlPafX7PGglTvF0FBM+hSo+LdoINofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXp -UhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/lg6AnhF4EwfWQvTA9xO+o -abw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV7qJZjqlc -3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/G -KubX9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSt -hfbZxbGL0eUQMk1fiyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KO -Tk0k+17kBL5yG6YnLUlamXrXXAkgt3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOt -zCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB -BjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZIhvcNAQELBQAD -ggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC -MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2 -cDMT/uFPpiN3GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUN -qXsCHKnQO18LwIE6PWThv6ctTr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5 -YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP+V04ikkwj+3x6xn0dxoxGE1nVGwv -b2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh3jRJjehZrJ3ydlo2 -8hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fawx/k -NSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNj -ZgKAvQU6O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhp -q1467HxpvMc7hU6eFbm0FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFt -nh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOVhMJKzRwuJIczYOXD ------END CERTIFICATE----- -# "QuoVadis Root CA 2" -# 85 A0 DD 7D D7 20 AD B7 FF 05 F8 3D 54 2B 20 9D -# C7 FF 45 28 F7 D6 77 B1 83 89 FE A5 E5 C4 9E 86 ------BEGIN CERTIFICATE----- -MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x -GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv -b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV -BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W -YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa -GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg -Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J -WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB -rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp -+ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1 -ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i -Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz -PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og -/zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH -oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI -yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud -EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2 -A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL -MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT -ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f -BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn -g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl -fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K -WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha -B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc -hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR -TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD -mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z -ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y -4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza -8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u ------END CERTIFICATE----- -# "QuoVadis Root CA 2 G3" -# 8F E4 FB 0A F9 3A 4D 0D 67 DB 0B EB B2 3E 37 C7 -# 1B F3 25 DC BC DD 24 0E A0 4D AF 58 B4 7E 18 40 ------BEGIN CERTIFICATE----- -MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL -BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc -BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00 -MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM -aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzMwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFhZiFf -qq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMW -n4rjyduYNM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ym -c5GQYaYDFCDy54ejiK2toIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+ -O7q414AB+6XrW7PFXmAqMaCvN+ggOp+oMiwMzAkd056OXbxMmO7FGmh77FOm6RQ1 -o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+lV0POKa2Mq1W/xPtbAd0j -IaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZoL1NesNKq -IcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz -8eQQsSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43eh -vNURG3YBZwjgQQvD6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l -7ZizlWNof/k19N+IxWA1ksB8aRxhlRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALG -cC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB -BjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZIhvcNAQELBQAD -ggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 -AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RC -roijQ1h5fq7KpVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0Ga -W/ZZGYjeVYg3UQt4XAoeo0L9x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4n -lv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgzdWqTHBLmYF5vHX/JHyPLhGGfHoJE -+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6XU/IyAgkwo1jwDQHV -csaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+NwmNtd -dbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNg -KCLjsZWDzYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeM -HVOyToV7BjjHLPj4sHKNJeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4 -WSr2Rz0ZiC3oheGe7IUIarFsNMkd7EgrO3jtZsSOeWmD3n+M ------END CERTIFICATE----- -# "QuoVadis Root CA 3" -# 18 F1 FC 7F 20 5D F8 AD DD EB 7F E0 07 DD 57 E3 -# AF 37 5A 9C 4D 8D 73 54 6B F4 F1 FE D1 E1 8D 35 ------BEGIN CERTIFICATE----- -MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x -GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv -b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV -BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W -YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM -V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB -4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr -H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd -8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv -vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT -mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe -btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc -T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt -WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ -c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A -4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD -VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG -CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0 -aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 -aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu -dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw -czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G -A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC -TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg -Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0 -7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem -d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd -+LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B -4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN -t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x -DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57 -k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s -zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j -Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT -mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK -4SVhM7JZG+Ju1zdXtg2pEto= ------END CERTIFICATE----- -# "QuoVadis Root CA 3 G3" -# 88 EF 81 DE 20 2E B0 18 45 2E 43 F8 64 72 5C EA -# 5F BD 1F C2 D9 D2 05 73 07 09 C5 D8 B8 69 0F 46 ------BEGIN CERTIFICATE----- -MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQEL -BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc -BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00 -MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM -aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzMwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286IxSR -/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNu -FoM7pmRLMon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXR -U7Ox7sWTaYI+FrUoRqHe6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+c -ra1AdHkrAj80//ogaX3T7mH1urPnMNA3I4ZyYUUpSFlob3emLoG+B01vr87ERROR -FHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3UVDmrJqMz6nWB2i3ND0/k -A9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f75li59wzw -eyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634Ryl -sSqiMd5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBp -VzgeAVuNVejH38DMdyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0Q -A4XN8f+MFrXBsj6IbGB/kE+V9/YtrQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ -ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB -BjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZIhvcNAQELBQAD -ggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px -KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnI -FUBhynLWcKzSt/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5Wvv -oxXqA/4Ti2Tk08HS6IT7SdEQTXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFg -u/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9DuDcpmvJRPpq3t/O5jrFc/ZSXPsoaP -0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGibIh6BJpsQBJFxwAYf -3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmDhPbl -8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+ -DhcI00iX0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HN -PlopNLk9hM6xZdRZkZFWdSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ -ywaZWWDYWGWVjUTR939+J399roD1B0y2PpxxVJkES/1Y+Zj0 ------END CERTIFICATE----- -# "QuoVadis Root Certification Authority" -# A4 5E DE 3B BB F0 9C 8A E1 5C 72 EF C0 72 68 D6 -# 93 A2 1C 99 6F D5 1E 67 CA 07 94 60 FD 6D 88 73 ------BEGIN CERTIFICATE----- -MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC -TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz -MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw -IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR -dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp -li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D -rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ -WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug -F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU -xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC -Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv -dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw -ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl -IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh -c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy -ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh -Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI -KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T -KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq -y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p -dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD -VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL -MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk -fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8 -7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R -cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y -mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW -xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK -SnQ2+Q== ------END CERTIFICATE----- -# "Secure Global CA" -# 42 00 F5 04 3A C8 59 0E BB 52 7D 20 9E D1 50 30 -# 29 FB CB D4 1C A1 B5 06 EC 27 F1 5A DE 7D AC 69 ------BEGIN CERTIFICATE----- -MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK -MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x -GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx -MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg -Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ -iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa -/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ -jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI -HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7 -sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w -gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF -MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw -KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG -AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L -URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO -H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm -I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY -iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc -f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW ------END CERTIFICATE----- -# "SecureTrust CA" -# F1 C1 B5 0A E5 A2 0D D8 03 0E C9 F6 BC 24 82 3D -# D3 67 B5 25 57 59 B4 E7 1B 61 FC E9 F7 37 5D 73 ------BEGIN CERTIFICATE----- -MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI -MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x -FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz -MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv -cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN -AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz -Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO -0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao -wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj -7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS -8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT -BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB -/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg -JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC -NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3 -6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/ -3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm -D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS -CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR -3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= ------END CERTIFICATE----- -# "Security Communication EV RootCA1" -# A2 2D BA 68 1E 97 37 6E 2D 39 7D 72 8A AE 3A 9B -# 62 96 B9 FD BA 60 BC 2E 11 F6 47 F2 C6 75 FB 37 ------BEGIN CERTIFICATE----- -MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDEl -MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMh -U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIz -MloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09N -IFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNlY3VyaXR5IENvbW11 -bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSE -RMqm4miO/VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gO -zXppFodEtZDkBp2uoQSXWHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5 -bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4zZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDF -MxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4bepJz11sS6/vmsJWXMY1 -VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK9U2vP9eC -OKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0G -CSqGSIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HW -tWS3irO4G8za+6xmiEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZ -q51ihPZRwSzJIxXYKLerJRO1RuGGAv8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDb -EJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnWmHyojf6GPgcWkuF75x3sM3Z+ -Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEWT1MKZPlO9L9O -VL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490 ------END CERTIFICATE----- -# "Security Communication RootCA1" -# E7 5E 72 ED 9F 56 0E EC 6E B4 80 00 73 A4 3F C3 -# AD 19 19 5A 39 22 82 01 78 95 97 4A 99 02 6B 6C ------BEGIN CERTIFICATE----- -MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY -MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t -dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5 -WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD -VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8 -9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ -DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9 -Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N -QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ -xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G -A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T -AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG -kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr -Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5 -Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU -JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot -RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw== ------END CERTIFICATE----- -# "Security Communication RootCA2" -# 51 3B 2C EC B8 10 D4 CD E5 DD 85 39 1A DF C6 C2 -# DD 60 D8 7B B7 36 D2 B5 21 48 4A A4 7A 0E BE F6 ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl -MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe -U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX -DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy -dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj -YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV -OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr -zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM -VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ -hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO -ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw -awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs -OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 -DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF -coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc -okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8 -t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy -1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/ -SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 ------END CERTIFICATE----- -# "Sonera Class2 CA" -# 79 08 B4 03 14 C1 38 10 0B 51 8D 07 35 80 7F FB -# FC F8 51 8A 00 95 33 71 05 BA 38 6B 15 3D D9 27 ------BEGIN CERTIFICATE----- -MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP -MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx -MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV -BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o -Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt -5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s -3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej -vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu -8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw -DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG -MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil -zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/ -3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD -FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6 -Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2 -ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M ------END CERTIFICATE----- -# "SSL.com EV Root Certification Authority ECC" -# 22 A2 C1 F7 BD ED 70 4C C1 E7 01 B5 F4 08 C3 10 -# 88 0F E9 56 B5 DE 2A 4A 44 F9 9C 87 3A 25 A7 C8 ------BEGIN CERTIFICATE----- -MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMC -VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T -U0wgQ29ycG9yYXRpb24xNDAyBgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZp -Y2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNTIzWhcNNDEwMjEyMTgx -NTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv -dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NMLmNv -bSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49 -AgEGBSuBBAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMA -VIbc/R/fALhBYlzccBYy3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1Kthku -WnBaBu2+8KGwytAJKaNjMGEwHQYDVR0OBBYEFFvKXuXe0oGqzagtZFG22XKbl+ZP -MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe5d7SgarNqC1kUbbZcpuX -5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJN+vp1RPZ -ytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZg -h5Mmm7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== ------END CERTIFICATE----- -# "SSL.com EV Root Certification Authority RSA R2" -# 2E 7B F1 6C C2 24 85 A7 BB E2 AA 86 96 75 07 61 -# B0 AE 39 BE 3B 2F E9 D0 CC 6D 4E F7 34 91 42 5C ------BEGIN CERTIFICATE----- -MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNV -BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UE -CgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2Vy -dGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMB4XDTE3MDUzMTE4MTQzN1oXDTQy -MDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4G -A1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQD -DC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy -MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvq -M0fNTPl9fb69LT3w23jhhqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssuf -OePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7wcXHswxzpY6IXFJ3vG2fThVUCAtZJycxa -4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTOZw+oz12WGQvE43LrrdF9 -HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+B6KjBSYR -aZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcA -b9ZhCBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQ -Gp8hLH94t2S42Oim9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQV -PWKchjgGAGYS5Fl2WlPAApiiECtoRHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMO -pgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+SlmJuwgUHfbSguPvuUCYHBBXtSu -UDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48+qvWBkofZ6aY -MBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV -HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa4 -9QaAJadz20ZpqJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBW -s47LCp1Jjr+kxJG7ZhcFUZh1++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5 -Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nxY/hoLVUE0fKNsKTPvDxeH3jnpaAg -cLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2GguDKBAdRUNf/ktUM -79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDzOFSz -/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXt -ll9ldDz7CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEm -Kf7GUmG6sXP/wwyc5WxqlD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKK -QbNmC1r7fSOl8hqw/96bg5Qu0T/fkreRrwU7ZcegbLHNYhLDkBvjJc40vG93drEQ -w/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1hlMYegouCRw2n5H9gooi -S9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX9hwJ1C07 -mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w== ------END CERTIFICATE----- -# "SSL.com Root Certification Authority ECC" -# 34 17 BB 06 CC 60 07 DA 1B 96 1C 92 0B 8A B4 CE -# 3F AD 82 0E 4A A3 0B 9A CB C4 A7 4E BD CE BC 65 ------BEGIN CERTIFICATE----- -MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMC -VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T -U0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0 -aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNDAzWhcNNDEwMjEyMTgxNDAz -WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0 -b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNvbSBS -b290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB -BAAiA2IABEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI -7Z4INcgn64mMU1jrYor+8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPg -CemB+vNH06NjMGEwHQYDVR0OBBYEFILRhXMw5zUE044CkvvlpNHEIejNMA8GA1Ud -EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTTjgKS++Wk0cQh6M0wDgYD -VR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCWe+0F+S8T -kdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+ -gA0z5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl ------END CERTIFICATE----- -# "SSL.com Root Certification Authority RSA" -# 85 66 6A 56 2E E0 BE 5C E9 25 C1 D8 89 0A 6F 76 -# A8 7E C1 6D 4D 7D 5F 29 EA 74 19 CF 20 12 3B 69 ------BEGIN CERTIFICATE----- -MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UE -BhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQK -DA9TU0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZp -Y2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYwMjEyMTczOTM5WhcNNDEwMjEyMTcz -OTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv -dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv -bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcN -AQEBBQADggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2R -xFdHaxh3a3by/ZPkPQ/CFp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aX -qhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcC -C52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/geoeOy3ZExqysdBP+lSgQ3 -6YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkpk8zruFvh -/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrF -YD3ZfBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93E -JNyAKoFBbZQ+yODJgUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVc -US4cK38acijnALXRdMbX5J+tB5O2UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8 -ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi81xtZPCvM8hnIk2snYxnP/Okm -+Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4sbE6x/c+cCbqi -M+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV -HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4G -A1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGV -cpNxJK1ok1iOMq8bs3AD/CUrdIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBc -Hadm47GUBwwyOabqG7B52B2ccETjit3E+ZUfijhDPwGFpUenPUayvOUiaPd7nNgs -PgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAslu1OJD7OAUN5F7kR/ -q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjqerQ0 -cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jr -a6x+3uxjMxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90I -H37hVZkLId6Tngr75qNJvTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/Y -K9f1JmzJBjSWFupwWRoyeXkLtoh/D1JIPb9s2KJELtFOt3JY04kTlf5Eq/jXixtu -nLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406ywKBjYZC6VWg3dGq2ktuf -oYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NIWuuA8ShY -Ic2wBlX7Jz9TkHCpBB5XJ7k= ------END CERTIFICATE----- -# "Staat der Nederlanden EV Root CA" -# 4D 24 91 41 4C FE 95 67 46 EC 4C EF A6 CF 6F 72 -# E2 8A 13 29 43 2F 9D 8A 90 7A C4 CB 5D AD C1 5A ------BEGIN CERTIFICATE----- -MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJO -TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFh -dCBkZXIgTmVkZXJsYW5kZW4gRVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0y -MjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIg -TmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRlcmxhbmRlbiBFViBS -b290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkkSzrS -M4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nC -UiY4iKTWO0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3d -Z//BYY1jTw+bbRcwJu+r0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46p -rfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13l -pJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gVXJrm0w912fxBmJc+qiXb -j5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr08C+eKxC -KFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS -/ZbV0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0X -cgOPvZuM5l5Tnrmd74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH -1vI4gnPah1vlPNOePqc7nvQDs/nxfRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrP -px9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB -/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwaivsnuL8wbqg7 -MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI -eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u -2dfOWBfoqSmuc0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHS -v4ilf0X8rLiltTMMgsT7B/Zq5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTC -wPTxGfARKbalGAKb12NMcIxHowNDXLldRqANb/9Zjr7dn3LDWyvfjFvO5QxGbJKy -CqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tNf1zuacpzEPuKqf2e -vTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi5Dp6 -Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIa -Gl6I6lD4WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeL -eG9QgkRQP2YGiqtDhFZKDyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8 -FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGyeUN51q1veieQA6TqJIc/2b3Z6fJfUEkc -7uzXLg== ------END CERTIFICATE----- -# "Staat der Nederlanden Root CA - G2" -# 66 8C 83 94 7D A6 3B 72 4B EC E1 74 3C 31 A0 E6 -# AE D0 DB 8E C5 B3 1B E3 77 BB 78 4F 91 B6 71 6F ------BEGIN CERTIFICATE----- -MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO -TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh -dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oX -DTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl -ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv -b3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ5291 -qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8Sp -uOUfiUtnvWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPU -Z5uW6M7XxgpT0GtJlvOjCwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvE -pMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiile7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp -5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCROME4HYYEhLoaJXhena/M -UGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpICT0ugpTN -GmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy -5V6548r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv -6q012iDTiIJh8BIitrzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEK -eN5KzlW/HdXZt1bv8Hb/C3m1r737qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6 -B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMBAAGjgZcwgZQwDwYDVR0TAQH/ -BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcCARYxaHR0cDov -L3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV -HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqG -SIb3DQEBCwUAA4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLyS -CZa59sCrI2AGeYwRTlHSeYAz+51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen -5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwjf/ST7ZwaUb7dRUG/kSS0H4zpX897 -IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaNkqbG9AclVMwWVxJK -gnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfkCpYL -+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxL -vJxxcypFURmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkm -bEgeqmiSBeGCc1qb3AdbCG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvk -N1trSt8sV4pAWja63XVECDdCcAz+3F4hoKOKwJCcaNpQ5kUQR3i2TtJlycM33+FC -Y7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoVIPVVYpbtbZNQvOSqeK3Z -ywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm66+KAQ== ------END CERTIFICATE----- -# "Staat der Nederlanden Root CA - G3" -# 3C 4F B0 B9 5A B8 B3 00 32 F4 32 B8 6F 53 5F E1 -# 72 C1 85 D0 FD 39 86 58 37 CF 36 18 7F A6 F4 28 ------BEGIN CERTIFICATE----- -MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO -TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh -dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloX -DTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl -ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv -b3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4yolQP -cPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WW -IkYFsO2tx1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqX -xz8ecAgwoNzFs21v0IJyEavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFy -KJLZWyNtZrVtB0LrpjPOktvA9mxjeM3KTj215VKb8b475lRgsGYeCasH/lSJEULR -9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUurmkVLoR9BvUhTFXFkC4az -5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU51nus6+N8 -6U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7 -Ngzp07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHP -bMk7ccHViLVlvMDoFxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXt -BznaqB16nzaeErAMZRKQFWDZJkBE41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTt -XUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMBAAGjQjBAMA8GA1UdEwEB/wQF -MAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleuyjWcLhL75Lpd -INyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD -U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwp -LiniyMMB8jPqKqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8 -Ipf3YF3qKS9Ysr1YvY2WTxB1v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixp -gZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA8KCWAg8zxXHzniN9lLf9OtMJgwYh -/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b8KKaa8MFSu1BYBQw -0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0rmj1A -fsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq -4BZ+Extq1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR -1VmiiXTTn74eS9fGbbeIJG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/ -QFH1T/U67cjF68IeHRaVesd+QnGTbksVtzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM -94B7IWcnMFk= ------END CERTIFICATE----- -# "Starfield Class 2 Certification Authority" -# 14 65 FA 20 53 97 B8 76 FA A6 F0 A9 95 8E 55 90 -# E4 0F CC 7F AA 4F B7 C2 C8 67 75 21 FB 5F B6 58 ------BEGIN CERTIFICATE----- -MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl -MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp -U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw -NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE -ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp -ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 -DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf -8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN -+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 -X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa -K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA -1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G -A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR -zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 -YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD -bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w -DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 -L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D -eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl -xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp -VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY -WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= ------END CERTIFICATE----- -# "Starfield Root Certificate Authority - G2" -# 2C E1 CB 0B F9 D2 F9 E1 02 99 3F BE 21 51 52 C3 -# B2 DD 0C AB DE 1C 68 E5 31 9B 83 91 54 DB B7 F5 ------BEGIN CERTIFICATE----- -MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx -EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT -HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs -ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw -MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 -b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj -aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp -Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg -nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1 -HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N -Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN -dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0 -HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO -BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G -CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU -sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3 -4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg -8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K -pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1 -mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 ------END CERTIFICATE----- -# "Starfield Services Root Certificate Authority - G2" -# 56 8D 69 05 A2 C8 87 08 A4 B3 02 51 90 ED CF ED -# B1 97 4A 60 6A 13 C6 E5 29 0F CB 2A E6 3E DA B5 ------BEGIN CERTIFICATE----- -MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx -EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT -HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs -ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 -MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD -VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy -ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy -dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p -OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2 -8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K -Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe -hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk -6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw -DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q -AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI -bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB -ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z -qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd -iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn -0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN -sSi6 ------END CERTIFICATE----- -# "StartCom Certification Authority" -# C7 66 A9 BE F2 D4 07 1C 86 3A 31 AA 49 20 E8 13 -# B2 D1 98 60 8C B7 B7 CF E2 11 43 B8 36 DF 09 EA ------BEGIN CERTIFICATE----- -MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW -MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg -Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9 -MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi -U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh -cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA -A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk -pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf -OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C -Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT -Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi -HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM -Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w -+2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ -Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 -Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B -26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID -AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE -FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j -ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js -LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM -BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0 -Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy -dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh -cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh -YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg -dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp -bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ -YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT -TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ -9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8 -jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW -FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz -ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1 -ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L -EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu -L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq -yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC -O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V -um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh -NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14= ------END CERTIFICATE----- -# "StartCom Certification Authority" -# E1 78 90 EE 09 A3 FB F4 F4 8B 9C 41 4A 17 D6 37 -# B7 A5 06 47 E9 BC 75 23 22 72 7F CC 17 42 A9 11 ------BEGIN CERTIFICATE----- -MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEW -MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg -Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM3WhcNMzYwOTE3MTk0NjM2WjB9 -MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi -U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh -cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA -A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk -pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf -OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C -Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT -Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi -HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM -Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w -+2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ -Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 -Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B -26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID -AQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD -VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFul -F2mHMMo0aEPQQa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCC -ATgwLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5w -ZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2ludGVybWVk -aWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENvbW1lcmNpYWwgKFN0 -YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0aGUg -c2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93 -d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgG -CWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1 -dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5fPGFf59Jb2vKXfuM/gTF -wWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWmN3PH/UvS -Ta0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst -0OcNOrg+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNc -pRJvkrKTlMeIFw6Ttn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKl -CcWw0bdT82AUuoVpaiF8H3VhFyAXe2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVF -P0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA2MFrLH9ZXF2RsXAiV+uKa0hK -1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBsHvUwyKMQ5bLm -KhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE -JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ -8dCAWZvLMdibD4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnm -fyWl8kgAwKQB2j8= ------END CERTIFICATE----- -# "StartCom Certification Authority G2" -# C7 BA 65 67 DE 93 A7 98 AE 1F AA 79 1E 71 2D 37 -# 8F AE 1F 93 C4 39 7F EA 44 1B B7 CB E6 FD 59 95 ------BEGIN CERTIFICATE----- -MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEW -MBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlm -aWNhdGlvbiBBdXRob3JpdHkgRzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1 -OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoG -A1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRzIwggIiMA0G -CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8Oo1XJ -JZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsD -vfOpL9HG4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnoo -D/Uefyf3lLE3PbfHkffiAez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/ -Q0kGi4xDuFby2X8hQxfqp0iVAXV16iulQ5XqFYSdCI0mblWbq9zSOdIxHWDirMxW -RST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbsO+wmETRIjfaAKxojAuuK -HDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8HvKTlXcxN -nw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM -0D4LnMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/i -UUjXuG+v+E5+M5iSFGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9 -Ha90OrInwMEePnWjFqmveiJdnxMaz6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHg -TuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE -AwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJKoZIhvcNAQEL -BQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K -2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfX -UfEpY9Z1zRbkJ4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl -6/2o1PXWT6RbdejF0mCy2wl+JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK -9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG/+gyRr61M3Z3qAFdlsHB1b6uJcDJ -HgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTcnIhT76IxW1hPkWLI -wpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/XldblhY -XzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5l -IxKVCCIcl85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoo -hdVddLHRDiBYmxOlsGOm7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulr -so8uBtjRkcfGEvRM/TAXw8HaOFvjqermobp573PYtlNXLfbQ4ddI ------END CERTIFICATE----- -# "Swisscom Root CA 1" -# 21 DB 20 12 36 60 BB 2E D4 18 20 5D A1 1E E7 A8 -# 5A 65 E2 BC 6E 55 B5 AF 7E 78 99 C8 A2 66 D9 2E ------BEGIN CERTIFICATE----- -MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBk -MQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0 -YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3Qg -Q0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4MTgyMjA2MjBaMGQxCzAJBgNVBAYT -AmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZp -Y2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIICIjAN -BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9 -m2BtRsiMMW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdih -FvkcxC7mlSpnzNApbjyFNDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/ -TilftKaNXXsLmREDA/7n29uj/x2lzZAeAR81sH8A25Bvxn570e56eqeqDFdvpG3F -EzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkCb6dJtDZd0KTeByy2dbco -kdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn7uHbHaBu -HYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNF -vJbNcA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo -19AOeCMgkckkKmUpWyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjC -L3UcPX7ape8eYIVpQtPM+GP+HkM5haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJW -bjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNYMUJDLXT5xp6mig/p/r+D5kNX -JLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0hBBYw -FDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j -BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzc -K6FptWfUjNP9MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzf -ky9NfEBWMXrrpA9gzXrzvsMnjgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7Ik -Vh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQMbFamIp1TpBcahQq4FJHgmDmHtqB -sfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4HVtA4oJVwIHaM190e -3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtlvrsR -ls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ip -mXeascClOS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HH -b6D0jqTsNFFbjCYDcKF31QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksf -rK/7DZBaZmBwXarNeNQk7shBoJMBkpxqnvy5JMWzFYJ+vq6VK+uxwNrjAWALXmms -hFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCyx/yP2FS1k2Kdzs9Z+z0Y -zirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMWNY6E0F/6 -MBr1mmz0DlP5OlvRHA== ------END CERTIFICATE----- -# "Swisscom Root CA 2" -# F0 9B 12 2C 71 14 F4 A0 9B D4 EA 4F 4A 99 D5 58 -# B4 6E 4C 25 CD 81 14 0D 29 C0 56 13 91 4C 38 41 ------BEGIN CERTIFICATE----- -MIIF2TCCA8GgAwIBAgIQHp4o6Ejy5e/DfEoeWhhntjANBgkqhkiG9w0BAQsFADBk -MQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0 -YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3Qg -Q0EgMjAeFw0xMTA2MjQwODM4MTRaFw0zMTA2MjUwNzM4MTRaMGQxCzAJBgNVBAYT -AmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZp -Y2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAyMIICIjAN -BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAlUJOhJ1R5tMJ6HJaI2nbeHCOFvEr -jw0DzpPMLgAIe6szjPTpQOYXTKueuEcUMncy3SgM3hhLX3af+Dk7/E6J2HzFZ++r -0rk0X2s682Q2zsKwzxNoysjL67XiPS4h3+os1OD5cJZM/2pYmLcX5BtS5X4HAB1f -2uY+lQS3aYg5oUFgJWFLlTloYhyxCwWJwDaCFCE/rtuh/bxvHGCGtlOUSbkrRsVP -ACu/obvLP+DHVxxX6NZp+MEkUp2IVd3Chy50I9AU/SpHWrumnf2U5NGKpV+GY3aF -y6//SSj8gO1MedK75MDvAe5QQQg1I3ArqRa0jG6F6bYRzzHdUyYb3y1aSgJA/MTA -tukxGggo5WDDH8SQjhBiYEQN7Aq+VRhxLKX0srwVYv8c474d2h5Xszx+zYIdkeNL -6yxSNLCK/RJOlrDrcH+eOfdmQrGrrFLadkBXeyq96G4DsguAhYidDMfCd7Camlf0 -uPoTXGiTOmekl9AbmbeGMktg2M7v0Ax/lZ9vh0+Hio5fCHyqW/xavqGRn1V9TrAL -acywlKinh/LTSlDcX3KwFnUey7QYYpqwpzmqm59m2I2mbJYV4+by+PGDYmy7Velh -k6M99bFXi08jsJvllGov34zflVEpYKELKeRcVVi3qPyZ7iVNTA6z00yPhOgpD/0Q -VAKFyPnlw4vP5w8CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0hBBYw -FDASBgdghXQBUwIBBgdghXQBUwIBMBIGA1UdEwEB/wQIMAYBAf8CAQcwHQYDVR0O -BBYEFE0mICKJS9PVpAqhb97iEoHF8TwuMB8GA1UdIwQYMBaAFE0mICKJS9PVpAqh -b97iEoHF8TwuMA0GCSqGSIb3DQEBCwUAA4ICAQAyCrKkG8t9voJXiblqf/P0wS4R -fbgZPnm3qKhyN2abGu2sEzsOv2LwnN+ee6FTSA5BesogpxcbtnjsQJHzQq0Qw1zv -/2BZf82Fo4s9SBwlAjxnffUy6S8w5X2lejjQ82YqZh6NM4OKb3xuqFp1mrjX2lhI -REeoTPpMSQpKwhI3qEAMw8jh0FcNlzKVxzqfl9NX+Ave5XLzo9v/tdhZsnPdTSpx -srpJ9csc1fV5yJmz/MFMdOO0vSk3FQQoHt5FRnDsr7p4DooqzgB53MBfGWcsa0vv -aGgLQ+OswWIJ76bdZWGgr4RVSJFSHMYlkSrQwSIjYVmvRRGFHQEkNI/Ps/8XciAT -woCqISxxOQ7Qj1zB09GOInJGTB2Wrk9xseEFKZZZ9LuedT3PDTcNYtsmjGOpI99n -Bjx8Oto0QuFmtEYE3saWmA9LSHokMnWRn6z3aOkquVVlzl1h0ydw2Df+n7mvoC5W -t6NlUe07qxS/TFED6F+KBZvuim6c779o+sjaC+NCydAXFJy3SuCvkychVSa1ZC+N -8f+mQAWFBVzKBxlcCxMoTFh/wqXvRdpg065lYZ1Tg3TCrvJcwhbtkj6EPnNgiLx2 -9CzP0H1907he0ZESEOnN3col49XtmS++dYFLJPlFRpTJKSFTnCZFqhMX5OfNeOI5 -wSsSnqaeG8XmDtkx2Q== ------END CERTIFICATE----- -# "Swisscom Root EV CA 2" -# D9 5F EA 3C A4 EE DC E7 4C D7 6E 75 FC 6D 1F F6 -# 2C 44 1F 0F A8 BC 77 F0 34 B1 9E 5D B2 58 01 5D ------BEGIN CERTIFICATE----- -MIIF4DCCA8igAwIBAgIRAPL6ZOJ0Y9ON/RAdBB92ylgwDQYJKoZIhvcNAQELBQAw -ZzELMAkGA1UEBhMCY2gxETAPBgNVBAoTCFN3aXNzY29tMSUwIwYDVQQLExxEaWdp -dGFsIENlcnRpZmljYXRlIFNlcnZpY2VzMR4wHAYDVQQDExVTd2lzc2NvbSBSb290 -IEVWIENBIDIwHhcNMTEwNjI0MDk0NTA4WhcNMzEwNjI1MDg0NTA4WjBnMQswCQYD -VQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2Vy -dGlmaWNhdGUgU2VydmljZXMxHjAcBgNVBAMTFVN3aXNzY29tIFJvb3QgRVYgQ0Eg -MjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMT3HS9X6lds93BdY7Bx -UglgRCgzo3pOCvrY6myLURYaVa5UJsTMRQdBTxB5f3HSek4/OE6zAMaVylvNwSqD -1ycfMQ4jFrclyxy0uYAyXhqdk/HoPGAsp15XGVhRXrwsVgu42O+LgrQ8uMIkqBPH -oCE2G3pXKSinLr9xJZDzRINpUKTk4RtiGZQJo/PDvO/0vezbE53PnUgJUmfANykR -HvvSEaeFGHR55E+FFOtSN+KxRdjMDUN/rhPSays/p8LiqG12W0OfvrSdsyaGOx9/ -5fLoZigWJdBLlzin5M8J0TbDC77aO0RYjb7xnglrPvMyxyuHxuxenPaHZa0zKcQv -idm5y8kDnftslFGXEBuGCxobP/YCfnvUxVFkKJ3106yDgYjTdLRZncHrYTNaRdHL -OdAGalNgHa/2+2m8atwBz735j9m9W8E6X47aD0upm50qKGsaCnw8qyIL5XctcfaC -NYGu+HuB5ur+rPQam3Rc6I8k9l2dRsQs0h4rIWqDJ2dVSqTjyDKXZpBy2uPUZC5f -46Fq9mDU5zXNysRojddxyNMkM3OxbPlq4SjbX8Y96L5V5jcb7STZDxmPX2MYWFCB -UWVv8p9+agTnNCRxunZLWB4ZvRVgRaoMEkABnRDixzgHcgplwLa7JSnaFp6LNYth -7eVxV4O1PHGf40+/fh6Bn0GXAgMBAAGjgYYwgYMwDgYDVR0PAQH/BAQDAgGGMB0G -A1UdIQQWMBQwEgYHYIV0AVMCAgYHYIV0AVMCAjASBgNVHRMBAf8ECDAGAQH/AgED -MB0GA1UdDgQWBBRF2aWBbj2ITY1x0kbBbkUe88SAnTAfBgNVHSMEGDAWgBRF2aWB -bj2ITY1x0kbBbkUe88SAnTANBgkqhkiG9w0BAQsFAAOCAgEAlDpzBp9SSzBc1P6x -XCX5145v9Ydkn+0UjrgEjihLj6p7jjm02Vj2e6E1CqGdivdj5eu9OYLU43otb98T -PLr+flaYC/NUn81ETm484T4VvwYmneTwkLbUwp4wLh/vx3rEUMfqe9pQy3omywC0 -Wqu1kx+AiYQElY2NfwmTv9SoqORjbdlk5LgpWgi/UOGED1V7XwgiG/W9mR4U9s70 -WBCCswo9GcG/W6uqmdjyMb3lOGbcWAXH7WMaLgqXfIeTK7KK4/HsGOV1timH59yL -Gn602MnTihdsfSlEvoqq9X46Lmgxk7lq2prg2+kupYTNHAq4Sgj5nPFhJpiTt3tm -7JFe3VE/23MPrQRYCd0EApUKPtN236YQHoA96M2kZNEzx5LH4k5E4wnJTsJdhw4S -nr8PyQUQ3nqjsTzyP6WqJ3mtMX0f/fwZacXduT98zca0wjAefm6S139hdlqP65VN -vBFuIXxZN5nQBrz5Bm0yFqXZaajh3DyAHmBR3NdUIR7KYndP+tiPsys6DXhyyWhB -WkdKwqPrGtcKqzwyVcgKEZzfdNbwQBUdyLmPtTbFr/giuMod89a2GQ+fYWVq6nTI -fI/DT11lgh/ZDYnadXL77/FHZxOzyNEZiCcmmpl5fx7kLD977vHeTYuWl8PVP3wb -I+2ksx0WckNLIOFZfsLorSa/ovc= ------END CERTIFICATE----- -# "SwissSign Gold CA - G2" -# 62 DD 0B E9 B9 F5 0A 16 3E A0 F8 E7 5C 05 3B 1E -# CA 57 EA 55 C8 68 8F 64 7C 68 81 F2 C8 35 7B 95 ------BEGIN CERTIFICATE----- -MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV -BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2ln -biBHb2xkIENBIC0gRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBF -MQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMR8wHQYDVQQDExZT -d2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC -CgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUqt2/8 -76LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+ -bbqBHH5CjCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c -6bM8K8vzARO/Ws/BtQpgvd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqE -emA8atufK+ze3gE/bk3lUIbLtK/tREDFylqM2tIrfKjuvqblCqoOpd8FUrdVxyJd -MmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvRAiTysybUa9oEVeXBCsdt -MDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuendjIj3o02y -MszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69y -FGkOpeUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPi -aG59je883WX0XaxR7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxM -gI93e2CaHt+28kgeDrpOVG2Y4OGiGqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCB -qTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWyV7 -lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64OfPAeGZe6Drn -8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov -L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe6 -45R88a7A3hfm5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczO -UYrHUDFu4Up+GC9pWbY9ZIEr44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5 -O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOfMke6UiI0HTJ6CVanfCU2qT1L2sCC -bwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6mGu6uLftIdxf+u+yv -GPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxpmo/a -77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCC -hdiDyyJkvC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid3 -92qgQmwLOM7XdVAyksLfKzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEpp -Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w -ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt -Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ ------END CERTIFICATE----- -# "SwissSign Platinum CA - G2" -# 3B 22 2E 56 67 11 E9 92 30 0D C0 B1 5A B9 47 3D -# AF DE F8 C8 4D 0C EF 7D 33 17 B4 C1 82 1D 14 36 ------BEGIN CERTIFICATE----- -MIIFwTCCA6mgAwIBAgIITrIAZwwDXU8wDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE -BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEjMCEGA1UEAxMaU3dpc3NTaWdu -IFBsYXRpbnVtIENBIC0gRzIwHhcNMDYxMDI1MDgzNjAwWhcNMzYxMDI1MDgzNjAw -WjBJMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMSMwIQYDVQQD -ExpTd2lzc1NpZ24gUGxhdGludW0gQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQAD -ggIPADCCAgoCggIBAMrfogLi2vj8Bxax3mCq3pZcZB/HL37PZ/pEQtZ2Y5Wu669y -IIpFR4ZieIbWIDkm9K6j/SPnpZy1IiEZtzeTIsBQnIJ71NUERFzLtMKfkr4k2Htn -IuJpX+UFeNSH2XFwMyVTtIc7KZAoNppVRDBopIOXfw0enHb/FZ1glwCNioUD7IC+ -6ixuEFGSzH7VozPY1kneWCqv9hbrS3uQMpe5up1Y8fhXSQQeol0GcN1x2/ndi5ob -jM89o03Oy3z2u5yg+gnOI2Ky6Q0f4nIoj5+saCB9bzuohTEJfwvH6GXp43gOCWcw -izSC+13gzJ2BbWLuCB4ELE6b7P6pT1/9aXjvCR+htL/68++QHkwFix7qepF6w9fl -+zC8bBsQWJj3Gl/QKTIDE0ZNYWqFTFJ0LwYfexHihJfGmfNtf9dng34TaNhxKFrY -zt3oEBSa/m0jh26OWnA81Y0JAKeqvLAxN23IhBQeW71FYyBrS3SMvds6DsHPWhaP -pZjydomyExI7C3d3rLvlPClKknLKYRorXkzig3R3+jVIeoVNjZpTxN94ypeRSCtF -KwH3HBqi7Ri6Cr2D+m+8jVeTO9TUps4e8aCxzqv9KyiaTxvXw3LbpMS/XUz13XuW -ae5ogObnmLo2t/5u7Su9IPhlGdpVCX4l3P5hYnL5fhgC72O00Puv5TtjjGePAgMB -AAGjgawwgakwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O -BBYEFFCvzAeHFUdvOMW0ZdHelarp35zMMB8GA1UdIwQYMBaAFFCvzAeHFUdvOMW0 -ZdHelarp35zMMEYGA1UdIAQ/MD0wOwYJYIV0AVkBAQEBMC4wLAYIKwYBBQUHAgEW -IGh0dHA6Ly9yZXBvc2l0b3J5LnN3aXNzc2lnbi5jb20vMA0GCSqGSIb3DQEBBQUA -A4ICAQAIhab1Fgz8RBrBY+D5VUYI/HAcQiiWjrfFwUF1TglxeeVtlspLpYhg0DB0 -uMoI3LQwnkAHFmtllXcBrqS3NQuB2nEVqXQXOHtYyvkv+8Bldo1bAbl93oI9ZLi+ -FHSjClTTLJUYFzX1UWs/j6KWYTl4a0vlpqD4U99REJNi54Av4tHgvI42Rncz7Lj7 -jposiU0xEQ8mngS7twSNC/K5/FqdOxa3L8iYq/6KUFkuozv8KV2LwUvJ4ooTHbG/ -u0IdUt1O2BReEMYxB+9xJ/cbOQncguqLs5WGXv312l0xpuAxtpTmREl0xRbl9x8D -YSjFyMsSoEJL+WuICI20MhjzdZ/EfwBPBZWcoxcCw7NTm6ogOSkrZvqdr16zktK1 -puEa+S1BaYEUtLS17Yk9zvupnTVCRLEcFHOBzyoBNZox1S2PbYTfgE1X4z/FhHXa -icYwu+uPyyIIoK6q8QNsOktNCaUOcsZWayFCTiMlFGiudgp8DAdwZPmaL/YFOSbG -DI8Zf0NebvRbFS/bYV3mZy8/CJT5YLSYMdp08YSTcU1f+2BY0fvEwW2JorsgH51x -kcsymxM9Pn2SUjWskpSi0xjCfMfqr3YFFt1nJ8J+HAciIfNAChs0B0QTwoRqjt8Z -Wr9/6x3iGjjRXK9HkmuAtTClyY3YqzGBH9/CZjfTk6mFhnll0g== ------END CERTIFICATE----- -# "SwissSign Silver CA - G2" -# BE 6C 4D A2 BB B9 BA 59 B6 F3 93 97 68 37 42 46 -# C3 C0 05 99 3F A9 8F 02 0D 1D ED BE D4 8A 81 D5 ------BEGIN CERTIFICATE----- -MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UE -BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWdu -IFNpbHZlciBDQSAtIEcyMB4XDTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0Nlow -RzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMY -U3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A -MIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644N0Mv -Fz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7br -YT7QbNHm+/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieF -nbAVlDLaYQ1HTWBCrpJH6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH -6ATK72oxh9TAtvmUcXtnZLi2kUpCe2UuMGoM9ZDulebyzYLs2aFK7PayS+VFheZt -eJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5hqAaEuSh6XzjZG6k4sIN/ -c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5FZGkECwJ -MoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRH -HTBsROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTf -jNFusB3hB48IHpmccelM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb6 -5i/4z3GcRm25xBWNOHkDRUjvxF3XCO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOB -rDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU -F6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRBtjpbO8tFnb0c -wpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 -cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIB -AHPGgeAn0i0P4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShp -WJHckRE1qTodvBqlYJ7YH39FkWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9 -xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L3XWgwF15kIwb4FDm3jH+mHtwX6WQ -2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx/uNncqCxv1yL5PqZ -IseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFaDGi8 -aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2X -em1ZqSqPe97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQR -dAtq/gsD/KNVV4n+SsuuWxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/ -OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJDIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+ -hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ubDgEj8Z+7fNzcbBGXJbLy -tGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u ------END CERTIFICATE----- -# "Symantec Class 1 Public Primary Certification Authority - G6" -# 9D 19 0B 2E 31 45 66 68 5B E8 A8 89 E2 7A A8 C7 -# D7 AE 1D 8A AD DB A3 C1 EC F9 D2 48 63 CD 34 B9 ------BEGIN CERTIFICATE----- -MIID9jCCAt6gAwIBAgIQJDJ18h0v0gkz97RqytDzmDANBgkqhkiG9w0BAQsFADCB -lDELMAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMR8w -HQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMUUwQwYDVQQDEzxTeW1hbnRl -YyBDbGFzcyAxIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 -IC0gRzYwHhcNMTExMDE4MDAwMDAwWhcNMzcxMjAxMjM1OTU5WjCBlDELMAkGA1UE -BhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMR8wHQYDVQQLExZT -eW1hbnRlYyBUcnVzdCBOZXR3b3JrMUUwQwYDVQQDEzxTeW1hbnRlYyBDbGFzcyAx -IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzYwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHOddJZKmZgiJM6kXZBxbje/SD -6Jlz+muxNuCad6BAwoGNAcfMjL2Pffd543pMA03Z+/2HOCgs3ZqLVAjbZ/sbjP4o -ki++t7JIp4Gh2F6Iw8w5QEFa0dzl2hCfL9oBTf0uRnz5LicKaTfukaMbasxEvxvH -w9QRslBglwm9LiL1QYRmn81ApqkAgMEflZKf3vNI79sdd2H8f9/ulqRy0LY+/3gn -r8uSFWkI22MQ4uaXrG7crPaizh5HmbmJtxLmodTNWRFnw2+F2EJOKL5ZVVkElauP -N4C/DfD8HzpkMViBeNfiNfYgPym4jxZuPkjctUwH4fIa6n4KedaovetdhitNAgMB -AAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW -BBQzQejIORIVk0jyljIuWvXalF9TYDANBgkqhkiG9w0BAQsFAAOCAQEAFeNzV7EX -tl9JaUSm9l56Z6zS3nVJq/4lVcc6yUQVEG6/MWvL2QeTfxyFYwDjMhLgzMv7OWyP -4lPiPEAz2aSMR+atWPuJr+PehilWNCxFuBL6RIluLRQlKCQBZdbqUqwFblYSCT3Q -dPTXvQbKqDqNVkL6jXI+dPEDct+HG14OelWWLDi3mIXNTTNEyZSPWjEwN0ujOhKz -5zbRIWhLLTjmU64cJVYIVgNnhJ3Gw84kYsdMNs+wBkS39V8C3dlU6S+QTnrIToNA -DJqXPDe/v+z28LSFdyjBC8hnghAXOKK3Buqbvzr46SMHv3TgmDgVVXjucgBcGaP0 -0jPg/73RVDkpDw== ------END CERTIFICATE----- -# "Symantec Class 2 Public Primary Certification Authority - G6" -# CB 62 7D 18 B5 8A D5 6D DE 33 1A 30 45 6B C6 5C -# 60 1A 4E 9B 18 DE DC EA 08 E7 DA AA 07 81 5F F0 ------BEGIN CERTIFICATE----- -MIID9jCCAt6gAwIBAgIQZIKe/DcedF38l/+XyLH/QTANBgkqhkiG9w0BAQsFADCB -lDELMAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMR8w -HQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMUUwQwYDVQQDEzxTeW1hbnRl -YyBDbGFzcyAyIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 -IC0gRzYwHhcNMTExMDE4MDAwMDAwWhcNMzcxMjAxMjM1OTU5WjCBlDELMAkGA1UE -BhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMR8wHQYDVQQLExZT -eW1hbnRlYyBUcnVzdCBOZXR3b3JrMUUwQwYDVQQDEzxTeW1hbnRlYyBDbGFzcyAy -IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzYwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNzOkFyGOFyz9AYxe9GPo15gRn -V2WYKaRPyVyPDzTS+NqoE2KquB5QZ3iwFkygOakVeq7t0qLA8JA3KRgmXOgNPLZs -ST/B4NzZS7YUGQum05bh1gnjGSYc+R9lS/kaQxwAg9bQqkmi1NvmYji6UBRDbfkx -+FYW2TgCkc/rbN27OU6Z4TBnRfHU8I3D3/7yOAchfQBeVkSz5GC9kSucq1sEcg+y -KNlyqwUgQiWpWwNqIBDMMfAr2jUs0Pual07wgksr2F82owstr2MNHSV/oW5cYqGN -KD6h/Bwg+AEvulWaEbAZ0shQeWsOagXXqgQ2sqPy4V93p3ec5R7c6d9qwWVdAgMB -AAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW -BBSHjCCVyJhK0daABkqQNETfHE2/sDANBgkqhkiG9w0BAQsFAAOCAQEAgY6ypWaW -tyGltu9vI1pf24HFQqV4wWn99DzX+VxrcHIa/FqXTQCAiIiCisNxDY7FiZss7Y0L -0nJU9X3UXENX6fOupQIR9nYrgVfdfdp0MP1UR/bgFm6mtApI5ud1Bw8pGTnOefS2 -bMVfmdUfS/rfbSw8DVSAcPCIC4DPxmiiuB1w2XaM/O6lyc+tHc+ZJVdaYkXLFmu9 -Sc2lo4xpeSWuuExsi0BmSxY/zwIa3eFsawdhanYVKZl/G92IgMG/tY9zxaaWI4Sm -KIYkM2oBLldzJbZev4/mHWGoQClnHYebHX+bn5nNMdZUvmK7OaxoEkiRIKXLsd3+ -b/xa5IJVWa8xqQ== ------END CERTIFICATE----- -# "SZAFIR ROOT CA" -# FA BC F5 19 7C DD 7F 45 8A C3 38 32 D3 28 40 21 -# DB 24 25 FD 6B EA 7A 2E 69 B7 48 6E 8F 51 F9 CC ------BEGIN CERTIFICATE----- -MIIDcTCCAlmgAwIBAgIVAOYJ/nrqAGiM4CS07SAbH+9StETRMA0GCSqGSIb3DQEB -BQUAMFAxCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGlj -emVuaW93YSBTLkEuMRcwFQYDVQQDDA5TWkFGSVIgUk9PVCBDQTAeFw0xMTEyMDYx -MTEwNTdaFw0zMTEyMDYxMTEwNTdaMFAxCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9L -cmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRcwFQYDVQQDDA5TWkFGSVIg -Uk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKxHL49ZMTml -6g3wpYwrvQKkvc0Kc6oJ5sxfgmp1qZfluwbv88BdocHSiXlY8NzrVYzuWBp7J/9K -ULMAoWoTIzOQ6C9TNm4YbA9A1jdX1wYNL5Akylf8W5L/I4BXhT9KnlI6x+a7BVAm -nr/Ttl+utT/Asms2fRfEsF2vZPMxH4UFqOAhFjxTkmJWf2Cu4nvRQJHcttB+cEAo -ag/hERt/+tzo4URz6x6r19toYmxx4FjjBkUhWQw1X21re//Hof2+0YgiwYT84zLb -eqDqCOMOXxvH480yGDkh/QoazWX3U75HQExT/iJlwnu7I1V6HXztKIwCBjsxffbH -3jOshCJtywcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AQYwHQYDVR0OBBYEFFOSo33/gnbwM9TrkmdHYTMbaDsqMA0GCSqGSIb3DQEBBQUA -A4IBAQA5UFWd5EL/pBviIMm1zD2JLUCpp0mJG7JkwznIOzawhGmFFaxGoxAhQBEg -haP+E0KR66oAwVC6xe32QUVSHfWqWndzbODzLB8yj7WAR0cDM45ZngSBPBuFE3Wu -GLJX9g100ETfIX+4YBR/4NR/uvTnpnd9ete7Whl0ZfY94yuu4xQqB5QFv+P7IXXV -lTOjkjuGXEcyQAjQzbFaT9vIABSbeCXWBbjvOXukJy6WgAiclzGNSYprre8Ryydd -fmjW9HIGwsIO03EldivvqEYL1Hv1w/Pur+6FUEOaL68PEIUovfgwIB2BAw+vZDuw -cH0mX548PojGyg434cDjkSXa3mHF ------END CERTIFICATE----- -# "T-TeleSec GlobalRoot Class 2" -# 91 E2 F5 78 8D 58 10 EB A7 BA 58 73 7D E1 54 8A -# 8E CA CD 01 45 98 BC 0B 14 3E 04 1B 17 05 25 52 ------BEGIN CERTIFICATE----- -MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx -KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd -BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl -YyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgxMDAxMTA0MDE0WhcNMzMxMDAxMjM1 -OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy -aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 -ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUd -AqSzm1nzHoqvNK38DcLZSBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiC -FoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/FvudocP05l03Sx5iRUKrERLMjfTlH6VJi -1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx9702cu+fjOlbpSD8DT6Iavq -jnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGVWOHAD3bZ -wI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGj -QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/ -WSA2AHmgoCJrjNXyYdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhy -NsZt+U2e+iKo4YFWz827n+qrkRk4r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPAC -uvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNfvNoBYimipidx5joifsFvHZVw -IEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR3p1m0IvVVGb6 -g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN -9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlP -BSeOE6Fuwg== ------END CERTIFICATE----- -# "T-TeleSec GlobalRoot Class 3" -# FD 73 DA D3 1C 64 4F F1 B4 3B EF 0C CD DA 96 71 -# 0B 9C D9 87 5E CA 7E 31 70 7A F3 E9 6D 52 2B BD ------BEGIN CERTIFICATE----- -MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx -KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd -BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl -YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1 -OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy -aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 -ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN -8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/ -RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4 -hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5 -ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM -EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj -QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1 -A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy -WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ -1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30 -6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT -91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml -e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p -TpPDpFQUWw== ------END CERTIFICATE----- -# "TeliaSonera Root CA v1" -# DD 69 36 FE 21 F8 F0 77 C1 23 A1 A5 21 C1 22 24 -# F7 22 55 B7 3E 03 A7 26 06 93 E8 A2 4B 0F A3 89 ------BEGIN CERTIFICATE----- -MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAw -NzEUMBIGA1UECgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJv -b3QgQ0EgdjEwHhcNMDcxMDE4MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYD -VQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwWVGVsaWFTb25lcmEgUm9vdCBDQSB2 -MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+6yfwIaPzaSZVfp3F -VRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA3GV1 -7CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+X -Z75Ljo1kB1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+ -/jXh7VB7qTCNGdMJjmhnXb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs -81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxHoLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkm -dtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3F0fUTPHSiXk+TT2YqGHe -Oh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJoWjiUIMu -sDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4 -pgd7gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fs -slESl1MpWtTwEhDcTwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQ -arMCpgKIv7NHfirZ1fpoeDVNAgMBAAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYD -VR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qWDNXr+nuqF+gTEjANBgkqhkiG -9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNmzqjMDfz1mgbl -dxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx -0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1Tj -TQpgcmLNkQfWpb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBed -Y2gea+zDTYa4EzAvXUYNR0PVG6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7 -Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpcc41teyWRyu5FrgZLAMzTsVlQ2jqI -OylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOTJsjrDNYmiLbAJM+7 -vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2qReW -t88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcn -HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx -SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= ------END CERTIFICATE----- -# "thawte Primary Root CA" -# 8D 72 2F 81 A9 C1 13 C0 79 1D F1 36 A2 96 6D B2 -# 6C 95 0A 97 1D B4 6B 41 99 F4 EA 54 B7 8B FB 9F ------BEGIN CERTIFICATE----- -MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB -qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf -Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw -MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV -BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw -NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j -LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG -A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl -IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs -W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta -3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk -6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6 -Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J -NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA -MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP -r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU -DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz -YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX -xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2 -/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/ -LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7 -jVaMaA== ------END CERTIFICATE----- -# "thawte Primary Root CA - G3" -# 4B 03 F4 58 07 AD 70 F2 1B FC 2C AE 71 C9 FD E4 -# 60 4C 06 4C F5 FF B6 86 BA E5 DB AA D7 FD D3 4C ------BEGIN CERTIFICATE----- -MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCB -rjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf -Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw -MDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNV -BAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0wODA0MDIwMDAwMDBa -Fw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3Rl -LCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9u -MTgwNgYDVQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXpl -ZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr8nLPvb2FvdeHsbnndm -gcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2AtP0LMqmsywCPLLEHd5N/8 -YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC+BsUa0Lf -b1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS9 -9irY7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2S -zhkGcuYMXDhpxwTWvGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUk -OQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV -HQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJKoZIhvcNAQELBQADggEBABpA -2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweKA3rD6z8KLFIW -oCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu -t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7c -KUGRIjxpp7sC8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fM -m7v/OeZWYdMKp8RcTGB7BXcmer/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZu -MdRAGmI0Nj81Aa6sY6A= ------END CERTIFICATE----- -# "TRUST2408 OCES Primary CA" -# 92 D8 09 2E E7 7B C9 20 8F 08 97 DC 05 27 18 94 -# E6 3E F2 79 33 AE 53 7F B9 83 EE F0 EA E3 EE C8 ------BEGIN CERTIFICATE----- -MIIGHDCCBASgAwIBAgIES45gAzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJE -SzESMBAGA1UEChMJVFJVU1QyNDA4MSIwIAYDVQQDExlUUlVTVDI0MDggT0NFUyBQ -cmltYXJ5IENBMB4XDTEwMDMwMzEyNDEzNFoXDTM3MTIwMzEzMTEzNFowRTELMAkG -A1UEBhMCREsxEjAQBgNVBAoTCVRSVVNUMjQwODEiMCAGA1UEAxMZVFJVU1QyNDA4 -IE9DRVMgUHJpbWFyeSBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB -AJlJodr3U1Fa+v8HnyACHV81/wLevLS0KUk58VIABl6Wfs3LLNoj5soVAZv4LBi5 -gs7E8CZ9w0F2CopW8vzM8i5HLKE4eedPdnaFqHiBZ0q5aaaQArW+qKJx1rT/AaXt -alMB63/yvJcYlXS2lpexk5H/zDBUXeEQyvfmK+slAySWT6wKxIPDwVapauFY9QaG -+VBhCa5jBstWS7A5gQfEvYqn6csZ3jW472kW6OFNz6ftBcTwufomGJBMkonf4ZLr -6t0AdRi9jflBPz3MNNRGxyjIuAmFqGocYFA/OODBRjvSHB2DygqQ8k+9tlpvzMRr -kU7jq3RKL+83G1dJ3/LTjCLz4ryEMIC/OJ/gNZfE0qXddpPtzflIPtUFVffXdbFV -1t6XZFhJ+wBHQCpJobq/BjqLWUA86upsDbfwnePtmIPRCemeXkY0qabC+2Qmd2Fe -xyZphwTyMnbqy6FG1tB65dYf3mOqStmLa3RcHn9+2dwNfUkh0tjO2FXD7drWcU0O -I9DW8oAypiPhm/QCjMU6j6t+0pzqJ/S0tdAo+BeiXK5hwk6aR+sRb608QfBbRAs3 -U/q8jSPByenggac2BtTN6cl+AA1Mfcgl8iXWNFVGegzd/VS9vINClJCe3FNVoUnR -YCKkj+x0fqxvBLopOkJkmuZw/yhgMxljUi2qYYGn90OzAgMBAAGjggESMIIBDjAP -BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjARBgNVHSAECjAIMAYGBFUd -IAAwgZcGA1UdHwSBjzCBjDAsoCqgKIYmaHR0cDovL2NybC5vY2VzLnRydXN0MjQw -OC5jb20vb2Nlcy5jcmwwXKBaoFikVjBUMQswCQYDVQQGEwJESzESMBAGA1UEChMJ -VFJVU1QyNDA4MSIwIAYDVQQDExlUUlVTVDI0MDggT0NFUyBQcmltYXJ5IENBMQ0w -CwYDVQQDEwRDUkwxMB8GA1UdIwQYMBaAFPZt+LFIs0FDAduGROUYBbdezAY3MB0G -A1UdDgQWBBT2bfixSLNBQwHbhkTlGAW3XswGNzANBgkqhkiG9w0BAQsFAAOCAgEA -VPAQGrT7dIjD3/sIbQW86f9CBPu0c7JKN6oUoRUtKqgJ2KCdcB5ANhCoyznHpu3m -/dUfVUI5hc31CaPgZyY37hch1q4/c9INcELGZVE/FWfehkH+acpdNr7j8UoRZlkN -15b/0UUBfGeiiJG/ugo4llfoPrp8bUmXEGggK3wyqIPcJatPtHwlb6ympfC2b/Ld -v/0IdIOzIOm+A89Q0utx+1cOBq72OHy8gpGb6MfncVFMoL2fjP652Ypgtr8qN9Ka -/XOazktiIf+2Pzp7hLi92hRc9QMYexrV/nnFSQoWdU8TqULFUoZ3zTEC3F/g2yj+ -FhbrgXHGo5/A4O74X+lpbY2XV47aSuw+DzcPt/EhMj2of7SA55WSgbjPMbmNX0rb -oenSIte2HRFW5Tr2W+qqkc/StixgkKdyzGLoFx/xeTWdJkZKwyjqge2wJqws2upY -EiThhC497+/mTiSuXd69eVUwKyqYp9SD2rTtNmF6TCghRM/dNsJOl+osxDVGcwvt -WIVFF/Onlu5fu1NHXdqNEfzldKDUvCfii3L2iATTZyHwU9CALE+2eIA+PIaLgnM1 -1oCfUnYBkQurTrihvzz9PryCVkLxiqRmBVvUz+D4N5G/wvvKDS6t6cPCS+hqM482 -cbBsn0R9fFLO4El62S9eH1tqOzO20OAOK65yJIsOpSE= ------END CERTIFICATE----- -# "TrustCor ECA-1" -# 5A 88 5D B1 9C 01 D9 12 C5 75 93 88 93 8C AF BB -# DF 03 1A B2 D4 8E 91 EE 15 58 9B 42 97 1D 03 9C ------BEGIN CERTIFICATE----- -MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYD -VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk -MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U -cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxFzAVBgNVBAMMDlRydXN0Q29y -IEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3MjgwN1owgZwxCzAJBgNV -BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw -IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy -dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3Ig -RUNBLTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb -3w9U73NjKYKtR8aja+3+XzP4Q1HpGjORMRegdMTUpwHmspI+ap3tDvl0mEDTPwOA -BoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23xFUfJ3zSCNV2HykVh0A5 -3ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmcp0yJF4Ou -owReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/ -wZ0+fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZF -ZtS6mFjBAgMBAAGjYzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAf -BgNVHSMEGDAWgBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/ -MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEABT41XBVwm8nHc2Fv -civUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u/ukZMjgDfxT2 -AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F -hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50 -soIipX1TH0XsJ5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BI -WJZpTdwHjFGTot+fDz2LYLSCjaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1Wi -tJ/X5g== ------END CERTIFICATE----- -# "TrustCor RootCert CA-1" -# D4 0E 9C 86 CD 8F E4 68 C1 77 69 59 F4 9E A7 74 -# FA 54 86 84 B6 C4 06 F3 90 92 61 F4 DC E2 57 5C ------BEGIN CERTIFICATE----- -MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYD -VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk -MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U -cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29y -IFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkxMjMxMTcyMzE2WjCB -pDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFuYW1h -IENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUG -A1UECwweVHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZU -cnVzdENvciBSb290Q2VydCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB -CgKCAQEAv463leLCJhJrMxnHQFgKq1mqjQCj/IDHUHuO1CAmujIS2CNUSSUQIpid -RtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4pQa81QBeCQryJ3pS/C3V -seq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0JEsq1pme -9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CV -EY4hgLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorW -hnAbJN7+KIor0Gqw/Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/ -DeOxCbeKyKsZn3MzUOcwHwYDVR0jBBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcw -DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQAD -ggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5mDo4Nvu7Zp5I -/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf -ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZ -yonnMlo2HD6CqFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djts -L1Ac59v2Z3kf9YKVmgenFK+P3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdN -zl/HHk484IkzlQsPpTLWPFp5LBk= ------END CERTIFICATE----- -# "TrustCor RootCert CA-2" -# 07 53 E9 40 37 8C 1B D5 E3 83 6E 39 5D AE A5 CB -# 83 9E 50 46 F1 BD 0E AE 19 51 CF 10 FE C7 C9 65 ------BEGIN CERTIFICATE----- -MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNV -BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw -IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy -dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEfMB0GA1UEAwwWVHJ1c3RDb3Ig -Um9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEyMzExNzI2MzlaMIGk -MQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEg -Q2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYD -VQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRy -dXN0Q29yIFJvb3RDZXJ0IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK -AoICAQCnIG7CKqJiJJWQdsg4foDSq8GbZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+ -QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9NkRvRUqdw6VC0xK5mC8tkq -1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1oYxOdqHp -2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nK -DOObXUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hape -az6LMvYHL1cEksr1/p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF -3wP+TfSvPd9cW436cOGlfifHhi5qjxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88 -oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQPeSghYA2FFn3XVDjxklb9tTNM -g9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+CtgrKAmrhQhJ8Z3 -mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh -8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAd -BgNVHQ4EFgQU2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6U -nrybPZx9mCAZ5YwwYrIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYw -DQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/hOsh80QA9z+LqBrWyOrsGS2h60COX -dKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnpkpfbsEZC89NiqpX+ -MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv2wnL -/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RX -CI/hOWB3S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYa -ZH9bDTMJBzN7Bj8RpFxwPIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW -2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dvDDqPys/cA8GiCcjl/YBeyGBCARsaU1q7 -N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYURpFHmygk71dSTlxCnKr3 -Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANExdqtvArB -As8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp -5KeXRKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu -1uwJ ------END CERTIFICATE----- -# "Trustis FPS Root CA" -# C1 B4 82 99 AB A5 20 8F E9 63 0A CE 55 CA 68 A0 -# 3E DA 5A 51 9C 88 02 A0 D3 A6 73 BE 8F 8E 55 7D ------BEGIN CERTIFICATE----- -MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBF -MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQL -ExNUcnVzdGlzIEZQUyBSb290IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTEx -MzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1RydXN0aXMgTGltaXRlZDEc -MBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQRUN+ -AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihH -iTHcDnlkH5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjj -vSkCqPoc4Vu5g6hBSLwacY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA -0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zto3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlB -OrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEAAaNTMFEwDwYDVR0TAQH/ -BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAdBgNVHQ4E -FgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01 -GX2cGE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmW -zaD+vkAMXBJV+JOCyinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP4 -1BIy+Q7DsdwyhEQsb8tGD+pmQQ9P8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZE -f1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHVl/9D7S3B2l0pKoU/rGXuhg8F -jZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYliB6XzCGcKQEN -ZetX2fNXlrtIzYE= ------END CERTIFICATE----- -# "TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1" -# 46 ED C3 68 90 46 D5 3A 45 3F B3 10 4A B8 0D CA -# EC 65 8B 26 60 EA 16 29 DD 7E 86 79 90 64 87 16 ------BEGIN CERTIFICATE----- -MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIx -GDAWBgNVBAcTD0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxp -bXNlbCB2ZSBUZWtub2xvamlrIEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0w -KwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24gTWVya2V6aSAtIEthbXUgU00xNjA0 -BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRpZmlrYXNpIC0gU3Vy -dW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYDVQQG -EwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXll -IEJpbGltc2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklU -QUsxLTArBgNVBAsTJEthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBT -TTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11IFNNIFNTTCBLb2sgU2VydGlmaWthc2kg -LSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr3UwM6q7 -a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y86Ij5iySr -LqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INr -N3wcwv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2X -YacQuFWQfw4tJzh03+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/ -iSIzL+aFCr2lqBs23tPcLG07xxO9WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4f -AJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQUZT/HiobGPN08VFw1+DrtUgxH -V8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL -BQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh -AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPf -IPP54+M638yclNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4 -lzwDGrpDxpa5RXI4s6ehlj2Re37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c -8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0jq5Rm+K37DwhuJi1/FwcJsoz7UMCf -lo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM= ------END CERTIFICATE----- -# "TWCA Global Root CA" -# 59 76 90 07 F7 68 5D 0F CD 50 87 2F 9F 95 D5 75 -# 5A 5B 2B 45 7D 81 F3 69 2B 61 0A 98 67 2F 0E 1B ------BEGIN CERTIFICATE----- -MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx -EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT -VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5 -NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsT -B1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2CnJfF -10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz -0ALfUPZVr2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfCh -MBwqoJimFb3u/Rk28OKRQ4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbH -zIh1HrtsBv+baz4X7GGqcXzGHaL3SekVtTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc -46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1WKKD+u4ZqyPpcC1jcxkt2 -yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99sy2sbZCi -laLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYP -oA/pyJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQA -BDzfuBSO6N+pjWxnkjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcE -qYSjMq+u7msXi7Kx/mzhkIyIqJdIzshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm -4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB -/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6gcFGn90xHNcgL -1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn -LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WF -H6vPNOw/KP4M8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNo -RI2T9GRwoD2dKAXDOXC4Ynsg/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+ -nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlglPx4mI88k1HtQJAH32RjJMtOcQWh -15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryPA9gK8kxkRr05YuWW -6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3mi4TW -nsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5j -wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz -aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy -KwbQBM0= ------END CERTIFICATE----- -# "TWCA Root Certification Authority" -# BF D8 8F E1 10 1C 41 AE 3E 80 1B F8 BE 56 35 0E -# E9 BA D1 A6 B9 BD 51 5E DC 5C 6D 5B 87 11 AC 44 ------BEGIN CERTIFICATE----- -MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES -MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU -V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz -WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO -LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm -aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE -AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH -K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX -RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z -rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx -3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq -hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC -MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls -XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D -lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn -aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ -YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== ------END CERTIFICATE----- -# "UCA Global Root" -# A1 F0 5C CB 80 C2 D7 10 EC 7D 47 9A BD CB B8 79 -# E5 8D 7E DB 71 49 FE 78 A8 78 84 E3 D0 BA D0 F9 ------BEGIN CERTIFICATE----- -MIIFkjCCA3qgAwIBAgIBCDANBgkqhkiG9w0BAQUFADA6MQswCQYDVQQGEwJDTjER -MA8GA1UEChMIVW5pVHJ1c3QxGDAWBgNVBAMTD1VDQSBHbG9iYWwgUm9vdDAeFw0w -ODAxMDEwMDAwMDBaFw0zNzEyMzEwMDAwMDBaMDoxCzAJBgNVBAYTAkNOMREwDwYD -VQQKEwhVbmlUcnVzdDEYMBYGA1UEAxMPVUNBIEdsb2JhbCBSb290MIICIjANBgkq -hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2rPlBlA/9nP3xDK/RqUlYjOHsGj+p9+I -A2N9Apb964fJ7uIIu527u+RBj8cwiQ9tJMAEbBSUgU2gDXRm8/CFr/hkGd656YGT -0CiFmUdCSiw8OCdKzP/5bBnXtfPvm65bNAbXj6ITBpyKhELVs6OQaG2BkO5NhOxM -cE4t3iQ5zhkAQ5N4+QiGHUPR9HK8BcBn+sBR0smFBySuOR56zUHSNqth6iur8CBV -mTxtLRwuLnWW2HKX4AzKaXPudSsVCeCObbvaE/9GqOgADKwHLx25urnRoPeZnnRc -GQVmMc8+KlL+b5/zub35wYH1N9ouTIElXfbZlJrTNYsgKDdfUet9Ysepk9H50DTL -qScmLCiQkjtVY7cXDlRzq6987DqrcDOsIfsiJrOGrCOp139tywgg8q9A9f9ER3Hd -J90TKKHqdjn5EKCgTUCkJ7JZFStsLSS3JGN490MYeg9NEePorIdCjedYcaSrbqLA -l3y74xNLytu7awj5abQEctXDRrl36v+6++nwOgw19o8PrgaEFt2UVdTvyie3AzzF -HCYq9TyopZWbhvGKiWf4xwxmse1Bv4KmAGg6IjTuHuvlb4l0T2qqaqhXZ1LUIGHB -zlPL/SR/XybfoQhplqCe/klD4tPq2sTxiDEhbhzhzfN1DiBEFsx9c3Q1RSw7gdQg -7LYJjD5IskkCAwEAAaOBojCBnzALBgNVHQ8EBAMCAQYwDAYDVR0TBAUwAwEB/zBj -BgNVHSUEXDBaBggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUFBwMDBggrBgEFBQcD -BAYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEFBQcDBwYIKwYBBQUHAwgGCCsGAQUF -BwMJMB0GA1UdDgQWBBTZw9P4gJJnzF3SOqLXcaK0xDiALTANBgkqhkiG9w0BAQUF -AAOCAgEA0Ih5ygiq9ws0oE4Jwul+NUiJcIQjL1HDKy9e21NrW3UIKlS6Mg7VxnGF -sZdJgPaE0PC6t3GUyHlrpsVE6EKirSUtVy/m1jEp+hmJVCl+t35HNmktbjK81HXa -QnO4TuWDQHOyXd/URHOmYgvbqm4FjMh/Rk85hZCdvBtUKayl1/7lWFZXbSyZoUkh -1WHGjGHhdSTBAd0tGzbDLxLMC9Z4i3WA6UG5iLHKPKkWxk4V43I29tSgQYWvimVw -TbVEEFDs7d9t5tnGwBLxSzovc+k8qe4bqi81pZufTcU0hF8mFGmzI7GJchT46U1R -IgP/SobEHOh7eQrbRyWBfvw0hKxZuFhD5D1DCVR0wtD92e9uWfdyYJl2b/Unp7uD -pEqB7CmB9HdL4UISVdSGKhK28FWbAS7d9qjjGcPORy/AeGEYWsdl/J1GW1fcfA67 -loMQfFUYCQSu0feLKj6g5lDWMDbX54s4U+xJRODPpN/xU3uLWrb2EZBL1nXz/gLz -Ka/wI3J9FO2pXd96gZ6bkiL8HvgBRUGXx2sBYb4zaPKgZYRmvOAqpGjTcezHCN6j -w8k2SjTxF+KAryAhk5Qe5hXTVGLxtTgv48y5ZwSpuuXu+RBuyy5+E6+SFP7zJ3N7 -OPxzbbm5iPZujAv1/P8JDrMtXnt145Ik4ubhWD5LKAN1axibRww= ------END CERTIFICATE----- -# "UCA Root" -# 93 E6 5E C7 62 F0 55 DC 71 8A 33 25 82 C4 1A 04 -# 43 0D 72 E3 CB 87 E8 B8 97 B6 75 16 F0 D1 AA 39 ------BEGIN CERTIFICATE----- -MIIDhDCCAmygAwIBAgIBCTANBgkqhkiG9w0BAQUFADAzMQswCQYDVQQGEwJDTjER -MA8GA1UEChMIVW5pVHJ1c3QxETAPBgNVBAMTCFVDQSBSb290MB4XDTA0MDEwMTAw -MDAwMFoXDTI5MTIzMTAwMDAwMFowMzELMAkGA1UEBhMCQ04xETAPBgNVBAoTCFVu -aVRydXN0MREwDwYDVQQDEwhVQ0EgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBALNdB8qGJn1r4vs4CQ7MgsJqGgCiFV/W6dQBt1YDAVmP9ThpJHbC -XivF9iu/r/tB/Q9a/KvXg3BNMJjRnrJ2u5LWu+kQKGkoNkTo8SzXWHwk1n8COvCB -a2FgP/Qz3m3l6ihST/ypHWN8C7rqrsRoRuTej8GnsrZYWm0dLNmMOreIy4XU9+gD -Xv2yTVDo1h//rgI/i0+WITyb1yXJHT/7mLFZ5PCpO6+zzYUs4mBGzG+OoOvwNMXx -QhhgrhLtRnUc5dipllq+3lrWeGeWW5N3UPJuG96WUUqm1ktDdSFmjXfsAoR2XEQQ -th1hbOSjIH23jboPkXXHjd+8AmCoKai9PUMCAwEAAaOBojCBnzALBgNVHQ8EBAMC -AQYwDAYDVR0TBAUwAwEB/zBjBgNVHSUEXDBaBggrBgEFBQcDAQYIKwYBBQUHAwIG -CCsGAQUFBwMDBggrBgEFBQcDBAYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEFBQcD -BwYIKwYBBQUHAwgGCCsGAQUFBwMJMB0GA1UdDgQWBBTbHzXza0z/QjFkm827Wh4d -SBC37jANBgkqhkiG9w0BAQUFAAOCAQEAOGy3iPGt+lg3dNHocN6cJ1nL5BXXoMNg -14iABMUwTD3UGusGXllH5rxmy+AI/Og17GJ9ysDawXiv5UZv+4mCI4/211NmVaDe -JRI7cTYWVRJ2+z34VFsxugAG+H1V5ad2g6pcSpemKijfvcZsCyOVjjN/Hl5AHxNU -LJzltQ7dFyiuawHTUin1Ih+QOfTcYmjwPIZH7LgFRbu3DJaUxmfLI3HQjnQi1kHr -A6i26r7EARK1s11AdgYg1GS4KUYGis4fk5oQ7vuqWrTcL9Ury/bXBYSYBZELhPc9 -+tb5evosFeo2gkO3t7jj83EB7UNDogVFwygFBzXjAaU4HoDU18PZ3g== ------END CERTIFICATE----- -# "USERTrust ECC Certification Authority" -# 4F F4 60 D5 4B 9C 86 DA BF BC FC 57 12 E0 40 0D -# 2B ED 3F BC 4D 4F BD AA 86 E0 6A DC D2 A9 AD 7A ------BEGIN CERTIFICATE----- -MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL -MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl -eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT -JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx -MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT -Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg -VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm -aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo -I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng -o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G -A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD -VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB -zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW -RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= ------END CERTIFICATE----- -# "USERTrust RSA Certification Authority" -# E7 93 C9 B0 2F D8 AA 13 E2 1C 31 22 8A CC B0 81 -# 19 64 3B 74 9C 89 89 64 B1 74 6D 46 C3 D4 CB D2 ------BEGIN CERTIFICATE----- -MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB -iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl -cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV -BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw -MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV -BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU -aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy -dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK -AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B -3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY -tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/ -Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2 -VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT -79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6 -c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT -Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l -c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee -UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE -Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd -BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G -A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF -Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO -VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3 -ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs -8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR -iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze -Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ -XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/ -qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB -VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB -L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG -jjxDah2nGN59PRbxYvnKkKj9 ------END CERTIFICATE----- -# "VeriSign Class 1 Public Primary Certification Authority - G3" -# CB B5 AF 18 5E 94 2A 24 02 F9 EA CB C0 ED 5B B8 -# 76 EE A3 C1 22 36 23 D0 04 47 E4 F3 BA 55 4B 65 ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQCLW3VWhFSFCwDPrzhIzrGkMA0GCSqGSIb3DQEBBQUAMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl -cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu -LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT -aWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD -VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT -aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ -bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu -IENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN2E1Lm0+afY8wR4 -nN493GwTFtl63SRRZsDHJlkNrAYIwpTRMx/wgzUfbhvI3qpuFU5UJ+/EbRrsC+MO -8ESlV8dAWB6jRx9x7GD2bZTIGDnt/kIYVt/kTEkQeE4BdjVjEjbdZrwBBDajVWjV -ojYJrKshJlQGrT/KFOCsyq0GHZXi+J3x4GD/wn91K0zM2v6HmSHquv4+VNfSWXjb -PG7PoBMAGrgnoeS+Z5bKoMWznN3JdZ7rMJpfo83ZrngZPyPpXNspva1VyBtUjGP2 -6KbqxzcSXKMpHgLZ2x87tNcPVkeBFQRKr4Mn0cVYiMHd9qqnoxjaaKptEVHhv2Vr -n5Z20T0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAq2aN17O6x5q25lXQBfGfMY1a -qtmqRiYPce2lrVNWYgFHKkTp/j90CxObufRNG7LRX7K20ohcs5/Ny9Sn2WCVhDr4 -wTcdYcrnsMXlkdpUpqwxga6X3s0IrLjAl4B/bnKk52kTlWUfxJM8/XmPBNQ+T+r3 -ns7NZ3xPZQL/kYVUc8f/NveGLezQXk//EZ9yBta4GvFMDSZl4kSAHsef493oCtrs -pSCAaWihT37ha88HQfqDjrw43bAuEbFrskLMmrz5SCJ5ShkPshw+IHTZasO+8ih4 -E1Z5T21Q6huwtVexN2ZYI/PcD98Kh8TvhgXVOBRgmaNL3gaWcSzy27YfpO8/7g== ------END CERTIFICATE----- -# "VeriSign Class 2 Public Primary Certification Authority - G3" -# 92 A9 D9 83 3F E1 94 4D B3 66 E8 BF AE 7A 95 B6 -# 48 0C 2D 6C 6C 2A 1B E6 5D 42 36 B6 08 FC A1 BB ------BEGIN CERTIFICATE----- -MIIEGTCCAwECEGFwy0mMX5hFKeewptlQW3owDQYJKoZIhvcNAQEFBQAwgcoxCzAJ -BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVy -aVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24s -IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNp -Z24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 -eSAtIEczMB4XDTk5MTAwMTAwMDAwMFoXDTM2MDcxNjIzNTk1OVowgcoxCzAJBgNV -BAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNp -Z24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIElu -Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24g -Q2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt -IEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArwoNwtUs22e5LeWU -J92lvuCwTY+zYVY81nzD9M0+hsuiiOLh2KRpxbXiv8GmR1BeRjmL1Za6tW8UvxDO -JxOeBUebMXoT2B/Z0wI3i60sR/COgQanDTAM6/c8DyAd3HJG7qUCyFvDyVZpTMUY -wZF7C9UTAJu878NIPkZgIIUq1ZC2zYugzDLdt/1AVbJQHFauzI13TccgTacxdu9o -koqQHgiBVrKtaaNS0MscxCM9H5n+TOgWY47GCI72MfbS+uV23bUckqNJzc0BzWjN -qWm6o+sdDZykIKbBoMXRRkwXbdKsZj+WjOCE1Db/IlnF+RFgqF8EffIa9iVCYQ/E -Srg+iQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA0JhU8wI1NQ0kdvekhktdmnLfe -xbjQ5F1fdiLAJvmEOjr5jLX77GDx6M4EsMjdpwOPMPOY36TmpDHf0xwLRtxyID+u -7gU8pDM/CzmscHhzS5kr3zDCVLCoO1Wh/hYozUK9dG6A2ydEp85EXdQbkJgNHkKU -sQAsBNB0owIFImNjzYO1+8FtYmtpdf1dcEG59b98377BMnMiIYtYgXsVkXq642RI -sH/7NiXaldDxJBQX3RiAa0YjOVT1jmIJBB2UkKab5iXiQkWquJCtvgiPqQtCGJTP -cjnhsUPgKM+351psE2tJs//jGHyJizNdrDPXp/naOlXJWBD5qu9ats9LS98q ------END CERTIFICATE----- -# "VeriSign Class 3 Public Primary Certification Authority - G3" -# EB 04 CF 5E B1 F3 9A FA 76 2F 2B B1 20 F2 96 CB -# A5 20 C1 B9 7D B1 58 95 65 B8 1C B9 A1 7B 72 44 ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl -cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu -LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT -aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD -VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT -aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ -bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu -IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b -N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t -KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu -kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm -CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ -Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu -imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te -2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe -DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC -/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p -F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt -TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== ------END CERTIFICATE----- -# "VeriSign Class 3 Public Primary Certification Authority - G4" -# 69 DD D7 EA 90 BB 57 C9 3E 13 5D C8 5E A6 FC D5 -# 48 0B 60 32 39 BD C4 54 FC 75 8B 2A 26 CF 7F 79 ------BEGIN CERTIFICATE----- -MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL -MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW -ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln -biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp -U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y -aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG -A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp -U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg -SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln -biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 -IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm -GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve -fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw -AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ -aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj -aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW -kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC -4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga -FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== ------END CERTIFICATE----- -# "VeriSign Class 3 Public Primary Certification Authority - G5" -# 9A CF AB 7E 43 C8 D8 80 D0 6B 26 2A 94 DE EE E4 -# B4 65 99 89 C3 D0 CA F1 9B AF 64 05 E4 1A B7 DF ------BEGIN CERTIFICATE----- -MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB -yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL -ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp -U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW -ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL -MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW -ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln -biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp -U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y -aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 -nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex -t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz -SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG -BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ -rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ -NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E -BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH -BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy -aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv -MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE -p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y -5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK -WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ -4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N -hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq ------END CERTIFICATE----- -# "VeriSign Universal Root Certification Authority" -# 23 99 56 11 27 A5 71 25 DE 8C EF EA 61 0D DF 2F -# A0 78 B5 C8 06 7F 4E 82 82 90 BF B8 60 E8 4B 3C ------BEGIN CERTIFICATE----- -MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCB -vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL -ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp -U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W -ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe -Fw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJVUzEX -MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0 -IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9y -IGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh -bCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF -9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWH -H26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+H -LL729fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN -/BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPT -rJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1Ud -EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEwX6FdoFsw -WTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs -exkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud -DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4 -sAPmLGd75JR3Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+ -seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz -4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+ -BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR -lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3 -7M2CYfE45k+XmCpajQ== ------END CERTIFICATE----- -# "Visa eCommerce Root" -# 69 FA C9 BD 55 FB 0A C7 8D 53 BB EE 5C F1 D5 97 -# 98 9F D0 AA AB 20 A2 51 51 BD F1 73 3E E7 D1 22 ------BEGIN CERTIFICATE----- -MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBr -MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl -cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv -bW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2WhcNMjIwNjI0MDAxNjEyWjBrMQsw -CQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5h -dGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1l -cmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h -2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4E -lpF7sDPwsRROEW+1QK8bRaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdV -ZqW1LS7YgFmypw23RuwhY/81q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq -299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0t -vz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaL -dXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD -AgEGMB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUF -AAOCAQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcR -zCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3 -LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGIxHYdkFsd -7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBuYQa7FkKMcPcw -++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt -398znM/jra6O1I7mT1GvFpLgXPYHDw== ------END CERTIFICATE----- -# "Visa Information Delivery Root CA" -# C5 7A 3A CB E8 C0 6B A1 98 8A 83 48 5B F3 26 F2 -# 44 87 75 37 98 49 DE 01 CA 43 57 1A F3 57 E7 4B ------BEGIN CERTIFICATE----- -MIID+TCCAuGgAwIBAgIQW1fXqEywr9nTb0ugMbTW4jANBgkqhkiG9w0BAQUFADB5 -MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl -cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xKjAoBgNVBAMTIVZpc2EgSW5m -b3JtYXRpb24gRGVsaXZlcnkgUm9vdCBDQTAeFw0wNTA2MjcxNzQyNDJaFw0yNTA2 -MjkxNzQyNDJaMHkxCzAJBgNVBAYTAlVTMQ0wCwYDVQQKEwRWSVNBMS8wLQYDVQQL -EyZWaXNhIEludGVybmF0aW9uYWwgU2VydmljZSBBc3NvY2lhdGlvbjEqMCgGA1UE -AxMhVmlzYSBJbmZvcm1hdGlvbiBEZWxpdmVyeSBSb290IENBMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyREA4R/QkkfpLx0cYjga/EhIPZpchH0MZsRZ -FfP6C2ITtf/Wc+MtgD4yTK0yoiXvni3d+aCtEgK3GDvkdgYrgF76ROJFZwUQjQ9l -x42gRT05DbXvWFoy7dTglCZ9z/Tt2Cnktv9oxKgmkeHY/CyfpCBg1S8xth2JlGMR -0ug/GMO5zANuegZOv438p5Lt5So+du2Gl+RMFQqEPwqN5uJSqAe0VtmB4gWdQ8on -Bj2ZAM2R73QW7UW0Igt2vA4JaSiNtaAG/Y/58VXWHGgbq7rDtNK1R30X0kJV0rGA -ib3RSwB3LpG7bOjbIucV5mQgJoVjoA1e05w6g1x/KmNTmOGRVwIDAQABo30wezAP -BgNVHRMBAf8EBTADAQH/MDkGA1UdIAQyMDAwLgYFZ4EDAgEwJTAVBggrBgEFBQcC -ARYJMS4yLjMuNC41MAwGCCsGAQUFBwICMAAwDgYDVR0PAQH/BAQDAgEGMB0GA1Ud -DgQWBBRPitp2/2d3I5qmgH1924h1hfeBejANBgkqhkiG9w0BAQUFAAOCAQEACUW1 -QdUHdDJydgDPmYt+telnG/Su+DPaf1cregzlN43bJaJosMP7NwjoJY/H2He4XLWb -5rXEkl+xH1UyUwF7mtaUoxbGxEvt8hPZSTB4da2mzXgwKvXuHyzF5Qjy1hOB0/pS -WaF9ARpVKJJ7TOJQdGKBsF2Ty4fSCLqZLgfxbqwMsd9sysXI3rDXjIhekqvbgeLz -PqZr+pfgFhwCCLSMQWl5Ll3u7Qk9wR094DZ6jj6+JCVCRUS3HyabH4OlM0Vc2K+j -INsF/64Or7GNtRf9HYEJvrPxHINxl3JVwhYj4ASeaO4KwhVbwtw94Tc/XrGcexDo -c5lC3rAi4/UZqweYCw== ------END CERTIFICATE----- -# "VRK Gov. Root CA" -# F0 08 73 3E C5 00 DC 49 87 63 CC 92 64 C6 FC EA -# 40 EC 22 00 0E 92 7D 05 3C E9 C9 0B FA 04 6C B2 ------BEGIN CERTIFICATE----- -MIIEGjCCAwKgAwIBAgIDAYagMA0GCSqGSIb3DQEBBQUAMIGjMQswCQYDVQQGEwJG -STEQMA4GA1UECBMHRmlubGFuZDEhMB8GA1UEChMYVmFlc3RvcmVraXN0ZXJpa2Vz -a3VzIENBMSkwJwYDVQQLEyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBTZXJ2aWNl -czEZMBcGA1UECxMQVmFybWVubmVwYWx2ZWx1dDEZMBcGA1UEAxMQVlJLIEdvdi4g -Um9vdCBDQTAeFw0wMjEyMTgxMzUzMDBaFw0yMzEyMTgxMzUxMDhaMIGjMQswCQYD -VQQGEwJGSTEQMA4GA1UECBMHRmlubGFuZDEhMB8GA1UEChMYVmFlc3RvcmVraXN0 -ZXJpa2Vza3VzIENBMSkwJwYDVQQLEyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBT -ZXJ2aWNlczEZMBcGA1UECxMQVmFybWVubmVwYWx2ZWx1dDEZMBcGA1UEAxMQVlJL -IEdvdi4gUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALCF -FdrIAzfQo0Y3bBseljDCWoUSZyPyu5/nioFgJ/gTqTy894aqqvTzJSm0/nWuHoGG -igWyHWWyOOi0zCia+xc28ZPVec7Bg4shT8MNrUHfeJ1I4x9CRPw8bSEga60ihCRC -jxdNwlAfZM0tOSJWiP2yY51U2kJpwMhP1xjiPshphJQ9LIDGfM6911Mf64i5psu7 -hVfvV3ZdDIvTXhJBnyHAOfQmbQj6OLOhd7HuFtjQaNq0mKWgZUZKa41+qk1guPjI -DfxxPu45h4G02fhukO4/DmHXHSto5i7hQkQmeCxY8n0Wf2HASSQqiYe2XS8pGfim -545SnkFLWg6quMJmQlMCAwEAAaNVMFMwDwYDVR0TAQH/BAUwAwEB/zARBglghkgB -hvhCAQEEBAMCAAcwDgYDVR0PAQH/BAQDAgHGMB0GA1UdDgQWBBTb6eGb0tEkC/yr -46Bn6q6cS3f0sDANBgkqhkiG9w0BAQUFAAOCAQEArX1ID1QRnljurw2bEi8hpM2b -uoRH5sklVSPj3xhYKizbXvfNVPVRJHtiZ+GxH0mvNNDrsczZog1Sf0JLiGCXzyVy -t08pLWKfT6HAVVdWDsRol5EfnGTCKTIB6dTI2riBmCguGMcs/OubUpbf9MiQGS0j -8/G7cdqehSO9Gu8u5Hp5t8OdhkktY7ktdM9lDzJmid87Ie4pbzlj2RXBbvbfgD5Q -eBmK3QOjFKU3p7UsfLYRh+cF8ry23tT/l4EohP7+bEaFEEGfTXWMB9SZZ291im/k -UJL2mdUQuMSpe/cXjUu/15WfCdxEDx4yw8DP03kN5Mc7h/CQNIghYkmSBAQfvA== ------END CERTIFICATE----- -# "XRamp Global Certification Authority" -# CE CD DC 90 50 99 D8 DA DF C5 B1 D2 09 B7 37 CB -# E2 C1 8C FB 2C 10 C0 FF 0B CF 0D 32 86 FC 1A A2 ------BEGIN CERTIFICATE----- -MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB -gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk -MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY -UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx -NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3 -dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy -dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB -dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6 -38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP -KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q -DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4 -qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa -JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi -PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P -BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs -jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0 -eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD -ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR -vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt -qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa -IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy -i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ -O+7ETPTsJ3xCwnR8gooJybQDJbw= ------END CERTIFICATE----- -` diff --git a/src/crypto/x509/root_ios_gen.go b/src/crypto/x509/root_ios_gen.go deleted file mode 100644 index 15eb1592ca..0000000000 --- a/src/crypto/x509/root_ios_gen.go +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build ignore - -// Generates root_ios.go. -// -// As of iOS 13, there is no API for querying the system trusted X.509 root -// certificates. -// -// Apple publishes the trusted root certificates for iOS and macOS on -// opensource.apple.com so we embed them into the x509 package. -// -// Note that this ignores distrusted and revoked certificates. -package main - -import ( - "archive/tar" - "bytes" - "compress/gzip" - "crypto/sha256" - "crypto/tls" - "crypto/x509" - "encoding/pem" - "flag" - "fmt" - "go/format" - "io" - "log" - "net/http" - "os" - "path" - "sort" - "strings" - "time" -) - -func main() { - var output = flag.String("output", "root_ios.go", "file name to write") - var version = flag.String("version", "", "security_certificates version") - flag.Parse() - if *version == "" { - log.Fatal("Select the latest security_certificates version from " + - "https://opensource.apple.com/source/security_certificates/") - } - - url := "https://opensource.apple.com/tarballs/security_certificates/security_certificates-%s.tar.gz" - hc := &http.Client{Timeout: 1 * time.Minute} - resp, err := hc.Get(fmt.Sprintf(url, *version)) - if err != nil { - log.Fatal(err) - } - defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - log.Fatalf("HTTP status not OK: %s", resp.Status) - } - - zr, err := gzip.NewReader(resp.Body) - if err != nil { - log.Fatal(err) - } - defer zr.Close() - - var certs []*x509.Certificate - pool := x509.NewCertPool() - - tr := tar.NewReader(zr) - for { - hdr, err := tr.Next() - if err == io.EOF { - break - } - if err != nil { - log.Fatal(err) - } - - rootsDirectory := fmt.Sprintf("security_certificates-%s/certificates/roots/", *version) - if dir, file := path.Split(hdr.Name); hdr.Typeflag != tar.TypeReg || - dir != rootsDirectory || strings.HasPrefix(file, ".") { - continue - } - - der, err := io.ReadAll(tr) - if err != nil { - log.Fatal(err) - } - - c, err := x509.ParseCertificate(der) - if err != nil { - log.Printf("Failed to parse certificate %q: %v", hdr.Name, err) - continue - } - - certs = append(certs, c) - pool.AddCert(c) - } - - // Quick smoke test to check the pool is well formed, and that we didn't end - // up trusting roots in the removed folder. - for _, c := range certs { - if c.Subject.CommonName == "Symantec Class 2 Public Primary Certification Authority - G4" { - log.Fatal("The pool includes a removed root!") - } - } - conn, err := tls.Dial("tcp", "mail.google.com:443", &tls.Config{ - RootCAs: pool, - }) - if err != nil { - log.Fatal(err) - } - conn.Close() - - certName := func(c *x509.Certificate) string { - if c.Subject.CommonName != "" { - return c.Subject.CommonName - } - if len(c.Subject.OrganizationalUnit) > 0 { - return c.Subject.OrganizationalUnit[0] - } - return c.Subject.Organization[0] - } - sort.Slice(certs, func(i, j int) bool { - if strings.ToLower(certName(certs[i])) != strings.ToLower(certName(certs[j])) { - return strings.ToLower(certName(certs[i])) < strings.ToLower(certName(certs[j])) - } - if !certs[i].NotBefore.Equal(certs[j].NotBefore) { - return certs[i].NotBefore.Before(certs[j].NotBefore) - } - fi, fj := sha256.Sum256(certs[i].Raw), sha256.Sum256(certs[j].Raw) - return bytes.Compare(fi[:], fj[:]) < 0 - }) - - out := new(bytes.Buffer) - fmt.Fprintf(out, header, *version) - fmt.Fprintf(out, "const systemRootsPEM = `\n") - - for _, c := range certs { - fmt.Fprintf(out, "# %q\n", certName(c)) - h := sha256.Sum256(c.Raw) - fmt.Fprintf(out, "# % X\n", h[:len(h)/2]) - fmt.Fprintf(out, "# % X\n", h[len(h)/2:]) - b := &pem.Block{ - Type: "CERTIFICATE", - Bytes: c.Raw, - } - if err := pem.Encode(out, b); err != nil { - log.Fatal(err) - } - } - - fmt.Fprintf(out, "`") - - source, err := format.Source(out.Bytes()) - if err != nil { - log.Fatal(err) - } - if err := os.WriteFile(*output, source, 0644); err != nil { - log.Fatal(err) - } -} - -const header = `// Code generated by root_ios_gen.go -version %s; DO NOT EDIT. -// Update the version in root.go and regenerate with "go generate". - -//go:build ios && !x509omitbundledroots -// +build ios,!x509omitbundledroots - -package x509 - -func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) { - return nil, nil -} - -func loadSystemRoots() (*CertPool, error) { - p := NewCertPool() - p.AppendCertsFromPEM([]byte(systemRootsPEM)) - return p, nil -} -` diff --git a/src/crypto/x509/root_omit.go b/src/crypto/x509/root_omit.go deleted file mode 100644 index 299d74835e..0000000000 --- a/src/crypto/x509/root_omit.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build ((darwin && arm64) || (darwin && amd64 && ios)) && x509omitbundledroots - -// This file provides the loadSystemRoots func when the -// "x509omitbundledroots" build tag has disabled bundling a copy, -// which currently on happens on darwin/arm64 (root_darwin_arm64.go). -// This then saves 256 KiB of binary size and another 560 KiB of -// runtime memory size retaining the parsed roots forever. Constrained -// environments can construct minimal x509 root CertPools on the fly -// in the crypto/tls.Config.VerifyPeerCertificate hook. - -package x509 - -import "errors" - -func loadSystemRoots() (*CertPool, error) { - return nil, errors.New("x509: system root bundling disabled") -} - -func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) { - return nil, nil -} diff --git a/src/crypto/x509/root_omit_test.go b/src/crypto/x509/root_omit_test.go deleted file mode 100644 index 1709e2ea8b..0000000000 --- a/src/crypto/x509/root_omit_test.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build ((darwin && arm64) || (darwin && amd64 && ios)) && x509omitbundledroots - -package x509 - -import ( - "strings" - "testing" -) - -func TestOmitBundledRoots(t *testing.T) { - cp, err := loadSystemRoots() - if err == nil { - t.Fatalf("loadSystemRoots = (pool %p, error %v); want non-nil error", cp, err) - } - if !strings.Contains(err.Error(), "root bundling disabled") { - t.Errorf("unexpected error doesn't mention bundling: %v", err) - } -} diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go index 1822a609da..59852d9d68 100644 --- a/src/crypto/x509/verify.go +++ b/src/crypto/x509/verify.go @@ -742,7 +742,7 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e } // Use platform verifiers, where available - if opts.Roots == nil && (runtime.GOOS == "windows" || runtime.GOOS == "darwin") { + if opts.Roots == nil && (runtime.GOOS == "windows" || runtime.GOOS == "darwin" || runtime.GOOS == "ios") { return c.systemVerify(&opts) } diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go index 5b3bf9340a..05d521c09d 100644 --- a/src/crypto/x509/verify_test.go +++ b/src/crypto/x509/verify_test.go @@ -1836,7 +1836,7 @@ func TestLongChain(t *testing.T) { } func TestSystemRootsError(t *testing.T) { - if runtime.GOOS == "windows" || runtime.GOOS == "darwin" { + if runtime.GOOS == "windows" || runtime.GOOS == "darwin" || runtime.GOOS == "ios" { t.Skip("Windows and darwin do not use (or support) systemRoots") } diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go index 949bd7f08b..3345f57075 100644 --- a/src/crypto/x509/x509_test.go +++ b/src/crypto/x509/x509_test.go @@ -1975,7 +1975,7 @@ func TestMultipleRDN(t *testing.T) { } func TestSystemCertPool(t *testing.T) { - if runtime.GOOS == "windows" || runtime.GOOS == "darwin" { + if runtime.GOOS == "windows" || runtime.GOOS == "darwin" || runtime.GOOS == "ios" { t.Skip("not implemented on Windows (Issue 16736, 18609) or darwin (Issue 46287)") } a, err := SystemCertPool() -- GitLab From f19e4001808863d2ebfe9d1975476513d030c381 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Sat, 6 Nov 2021 11:09:56 +0100 Subject: [PATCH 2031/2500] all: remove more leftover // +build lines CL 344955 and CL 359476 removed almost all // +build lines, but leaving some assembly files and generating scripts. Also, some files were added with // +build lines after CL 359476 was merged. Remove these or rename files where more appropriate. For #41184 Change-Id: I7eb85a498ed9788b42a636e775f261d755504ffa Reviewed-on: https://go-review.googlesource.com/c/go/+/361480 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/crypto/cipher/xor_ppc64x.s | 1 - src/crypto/md5/md5block_ppc64x.s | 1 - src/crypto/x509/internal/macos/corefoundation.s | 1 - src/crypto/x509/internal/macos/security.s | 1 - src/debug/pe/file_cgo_test.go | 1 - src/internal/bytealg/compare_mips64x.s | 1 - src/internal/bytealg/compare_mipsx.s | 1 - src/internal/bytealg/compare_ppc64x.s | 1 - src/internal/bytealg/count_ppc64x.s | 1 - src/internal/bytealg/equal_mips64x.s | 1 - src/internal/bytealg/equal_mipsx.s | 1 - src/internal/bytealg/equal_ppc64x.s | 1 - src/internal/bytealg/index_ppc64x.s | 1 - src/internal/bytealg/indexbyte_mips64x.s | 1 - src/internal/bytealg/indexbyte_mipsx.s | 1 - src/internal/bytealg/indexbyte_ppc64x.s | 1 - src/internal/cpu/cpu_x86.s | 1 - src/reflect/asm_mips64x.s | 1 - src/reflect/asm_mipsx.s | 1 - src/reflect/asm_ppc64x.s | 1 - src/reflect/float32reg_ppc64x.s | 1 - src/runtime/asan_amd64.s | 1 - src/runtime/asan_arm64.s | 1 - src/runtime/asm_mips64x.s | 1 - src/runtime/asm_mipsx.s | 1 - src/runtime/asm_ppc64x.s | 1 - src/runtime/atomic_mips64x.s | 1 - src/runtime/atomic_mipsx.s | 1 - src/runtime/atomic_ppc64x.s | 1 - src/runtime/duff_mips64x.s | 1 - src/runtime/duff_ppc64x.s | 1 - src/runtime/internal/atomic/atomic_mips64x.s | 1 - src/runtime/internal/atomic/atomic_mipsx.s | 1 - src/runtime/internal/atomic/atomic_ppc64x.s | 1 - src/runtime/internal/atomic/sys_nonlinux_arm.s | 1 - src/runtime/libfuzzer_amd64.s | 1 - src/runtime/libfuzzer_arm64.s | 1 - src/runtime/memclr_386.s | 1 - src/runtime/memclr_amd64.s | 1 - src/runtime/memclr_mips64x.s | 1 - src/runtime/memclr_mipsx.s | 1 - src/runtime/memclr_ppc64x.s | 1 - src/runtime/memmove_386.s | 1 - src/runtime/memmove_amd64.s | 1 - src/runtime/memmove_mips64x.s | 1 - src/runtime/memmove_mipsx.s | 1 - src/runtime/memmove_ppc64x.s | 1 - src/runtime/msan_amd64.s | 1 - src/runtime/msan_arm64.s | 1 - src/runtime/preempt_mips64x.s | 1 - src/runtime/preempt_mipsx.s | 1 - src/runtime/preempt_ppc64x.s | 1 - src/runtime/race_amd64.s | 1 - src/runtime/race_arm64.s | 1 - src/runtime/race_ppc64le.s | 1 - src/runtime/rt0_linux_mips64x.s | 2 -- src/runtime/rt0_linux_mipsx.s | 2 -- src/runtime/sys_linux_mips64x.s | 2 -- src/runtime/sys_linux_mipsx.s | 2 -- src/runtime/sys_linux_ppc64x.s | 2 -- src/runtime/time_linux_amd64.s | 1 - src/runtime/time_windows_386.s | 1 - src/runtime/time_windows_amd64.s | 1 - src/runtime/time_windows_arm.s | 1 - src/runtime/time_windows_arm64.s | 1 - src/runtime/tls_arm.s | 1 - src/runtime/tls_mips64x.s | 1 - src/runtime/tls_mipsx.s | 1 - src/runtime/tls_ppc64x.s | 1 - src/runtime/zcallback_windows.s | 1 - src/sync/atomic/asm.s | 1 - src/sync/atomic/race.s | 1 - src/syscall/asan.go | 1 - src/syscall/asan0.go | 3 +-- src/syscall/asm9_unix2_amd64.s | 1 - src/syscall/asm_linux_mips64x.s | 2 -- src/syscall/asm_linux_mipsx.s | 2 -- src/syscall/asm_linux_ppc64x.s | 2 -- src/syscall/{asm9_unix1_amd64.s => asm_netbsd_amd64.s} | 3 --- src/syscall/asm_unix_386.s | 1 - src/syscall/asm_unix_amd64.s | 1 - src/syscall/mksyscall.pl | 1 - src/syscall/mksyscall_libc.pl | 1 - 83 files changed, 1 insertion(+), 94 deletions(-) rename src/syscall/{asm9_unix1_amd64.s => asm_netbsd_amd64.s} (96%) diff --git a/src/crypto/cipher/xor_ppc64x.s b/src/crypto/cipher/xor_ppc64x.s index 2ba6d9639c..a2ec95c0be 100644 --- a/src/crypto/cipher/xor_ppc64x.s +++ b/src/crypto/cipher/xor_ppc64x.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le #include "textflag.h" diff --git a/src/crypto/md5/md5block_ppc64x.s b/src/crypto/md5/md5block_ppc64x.s index 8c28ec2473..69a20e7cad 100644 --- a/src/crypto/md5/md5block_ppc64x.s +++ b/src/crypto/md5/md5block_ppc64x.s @@ -11,7 +11,6 @@ // in the public domain. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le #include "textflag.h" diff --git a/src/crypto/x509/internal/macos/corefoundation.s b/src/crypto/x509/internal/macos/corefoundation.s index 376099caa3..e60bd8712d 100644 --- a/src/crypto/x509/internal/macos/corefoundation.s +++ b/src/crypto/x509/internal/macos/corefoundation.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin && !ios -// +build darwin,!ios #include "textflag.h" diff --git a/src/crypto/x509/internal/macos/security.s b/src/crypto/x509/internal/macos/security.s index 9c1c133489..77406a0553 100644 --- a/src/crypto/x509/internal/macos/security.s +++ b/src/crypto/x509/internal/macos/security.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin && !ios -// +build darwin,!ios #include "textflag.h" diff --git a/src/debug/pe/file_cgo_test.go b/src/debug/pe/file_cgo_test.go index 13eb4e62b2..9280de1a49 100644 --- a/src/debug/pe/file_cgo_test.go +++ b/src/debug/pe/file_cgo_test.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build cgo -// +build cgo package pe diff --git a/src/internal/bytealg/compare_mips64x.s b/src/internal/bytealg/compare_mips64x.s index b472e510bc..117a9ef631 100644 --- a/src/internal/bytealg/compare_mips64x.s +++ b/src/internal/bytealg/compare_mips64x.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips64 || mips64le -// +build mips64 mips64le #include "go_asm.h" #include "textflag.h" diff --git a/src/internal/bytealg/compare_mipsx.s b/src/internal/bytealg/compare_mipsx.s index dcc4916e56..857ac13389 100644 --- a/src/internal/bytealg/compare_mipsx.s +++ b/src/internal/bytealg/compare_mipsx.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips || mipsle -// +build mips mipsle #include "go_asm.h" #include "textflag.h" diff --git a/src/internal/bytealg/compare_ppc64x.s b/src/internal/bytealg/compare_ppc64x.s index 390a72688b..2793e44e8b 100644 --- a/src/internal/bytealg/compare_ppc64x.s +++ b/src/internal/bytealg/compare_ppc64x.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le #include "go_asm.h" #include "textflag.h" diff --git a/src/internal/bytealg/count_ppc64x.s b/src/internal/bytealg/count_ppc64x.s index dbafd06edc..43d547bb8a 100644 --- a/src/internal/bytealg/count_ppc64x.s +++ b/src/internal/bytealg/count_ppc64x.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64le || ppc64 -// +build ppc64le ppc64 #include "go_asm.h" #include "textflag.h" diff --git a/src/internal/bytealg/equal_mips64x.s b/src/internal/bytealg/equal_mips64x.s index c2f7d3997e..d92f225e8d 100644 --- a/src/internal/bytealg/equal_mips64x.s +++ b/src/internal/bytealg/equal_mips64x.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips64 || mips64le -// +build mips64 mips64le #include "go_asm.h" #include "textflag.h" diff --git a/src/internal/bytealg/equal_mipsx.s b/src/internal/bytealg/equal_mipsx.s index 11e5549e45..4c46dd4fce 100644 --- a/src/internal/bytealg/equal_mipsx.s +++ b/src/internal/bytealg/equal_mipsx.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips || mipsle -// +build mips mipsle #include "go_asm.h" #include "textflag.h" diff --git a/src/internal/bytealg/equal_ppc64x.s b/src/internal/bytealg/equal_ppc64x.s index d59154101a..bd8caa7f18 100644 --- a/src/internal/bytealg/equal_ppc64x.s +++ b/src/internal/bytealg/equal_ppc64x.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le #include "go_asm.h" #include "textflag.h" diff --git a/src/internal/bytealg/index_ppc64x.s b/src/internal/bytealg/index_ppc64x.s index ab47495427..2d2a7146f1 100644 --- a/src/internal/bytealg/index_ppc64x.s +++ b/src/internal/bytealg/index_ppc64x.s @@ -22,7 +22,6 @@ // implementation on power9. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le #include "go_asm.h" #include "textflag.h" diff --git a/src/internal/bytealg/indexbyte_mips64x.s b/src/internal/bytealg/indexbyte_mips64x.s index 0f377f5a4c..5689f84b47 100644 --- a/src/internal/bytealg/indexbyte_mips64x.s +++ b/src/internal/bytealg/indexbyte_mips64x.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips64 || mips64le -// +build mips64 mips64le #include "go_asm.h" #include "textflag.h" diff --git a/src/internal/bytealg/indexbyte_mipsx.s b/src/internal/bytealg/indexbyte_mipsx.s index bed015bbd6..1c2b104d3c 100644 --- a/src/internal/bytealg/indexbyte_mipsx.s +++ b/src/internal/bytealg/indexbyte_mipsx.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips || mipsle -// +build mips mipsle #include "go_asm.h" #include "textflag.h" diff --git a/src/internal/bytealg/indexbyte_ppc64x.s b/src/internal/bytealg/indexbyte_ppc64x.s index 27e1ad7e0d..87ef8ecffc 100644 --- a/src/internal/bytealg/indexbyte_ppc64x.s +++ b/src/internal/bytealg/indexbyte_ppc64x.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le #include "go_asm.h" #include "textflag.h" diff --git a/src/internal/cpu/cpu_x86.s b/src/internal/cpu/cpu_x86.s index 0df5da1cc7..edef21905c 100644 --- a/src/internal/cpu/cpu_x86.s +++ b/src/internal/cpu/cpu_x86.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build 386 || amd64 -// +build 386 amd64 #include "textflag.h" diff --git a/src/reflect/asm_mips64x.s b/src/reflect/asm_mips64x.s index 8d01c5fb7e..f21e34df1b 100644 --- a/src/reflect/asm_mips64x.s +++ b/src/reflect/asm_mips64x.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips64 || mips64le -// +build mips64 mips64le #include "textflag.h" #include "funcdata.h" diff --git a/src/reflect/asm_mipsx.s b/src/reflect/asm_mipsx.s index 6ea8233108..636c8a5c71 100644 --- a/src/reflect/asm_mipsx.s +++ b/src/reflect/asm_mipsx.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips || mipsle -// +build mips mipsle #include "textflag.h" #include "funcdata.h" diff --git a/src/reflect/asm_ppc64x.s b/src/reflect/asm_ppc64x.s index 1ccfb25b94..3b529be685 100644 --- a/src/reflect/asm_ppc64x.s +++ b/src/reflect/asm_ppc64x.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le #include "textflag.h" #include "funcdata.h" diff --git a/src/reflect/float32reg_ppc64x.s b/src/reflect/float32reg_ppc64x.s index 391edfa7ce..a4deb18427 100644 --- a/src/reflect/float32reg_ppc64x.s +++ b/src/reflect/float32reg_ppc64x.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le #include "textflag.h" diff --git a/src/runtime/asan_amd64.s b/src/runtime/asan_amd64.s index 01bd612dc3..e8de80399b 100644 --- a/src/runtime/asan_amd64.s +++ b/src/runtime/asan_amd64.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build asan -// +build asan #include "go_asm.h" #include "go_tls.h" diff --git a/src/runtime/asan_arm64.s b/src/runtime/asan_arm64.s index eb0f9bd71e..acae200fb5 100644 --- a/src/runtime/asan_arm64.s +++ b/src/runtime/asan_arm64.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build asan -// +build asan #include "go_asm.h" #include "textflag.h" diff --git a/src/runtime/asm_mips64x.s b/src/runtime/asm_mips64x.s index e0e5cbb704..3597ebec57 100644 --- a/src/runtime/asm_mips64x.s +++ b/src/runtime/asm_mips64x.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips64 || mips64le -// +build mips64 mips64le #include "go_asm.h" #include "go_tls.h" diff --git a/src/runtime/asm_mipsx.s b/src/runtime/asm_mipsx.s index 1b550719d1..4a086b8eb3 100644 --- a/src/runtime/asm_mipsx.s +++ b/src/runtime/asm_mipsx.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips || mipsle -// +build mips mipsle #include "go_asm.h" #include "go_tls.h" diff --git a/src/runtime/asm_ppc64x.s b/src/runtime/asm_ppc64x.s index 0e7ef7b2b8..ae14213999 100644 --- a/src/runtime/asm_ppc64x.s +++ b/src/runtime/asm_ppc64x.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le #include "go_asm.h" #include "go_tls.h" diff --git a/src/runtime/atomic_mips64x.s b/src/runtime/atomic_mips64x.s index e2118e6a20..dd6380ce40 100644 --- a/src/runtime/atomic_mips64x.s +++ b/src/runtime/atomic_mips64x.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips64 || mips64le -// +build mips64 mips64le #include "textflag.h" diff --git a/src/runtime/atomic_mipsx.s b/src/runtime/atomic_mipsx.s index 1eacd273b4..ac255fe7e6 100644 --- a/src/runtime/atomic_mipsx.s +++ b/src/runtime/atomic_mipsx.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips || mipsle -// +build mips mipsle #include "textflag.h" diff --git a/src/runtime/atomic_ppc64x.s b/src/runtime/atomic_ppc64x.s index b63de2dbd3..4742b6cf56 100644 --- a/src/runtime/atomic_ppc64x.s +++ b/src/runtime/atomic_ppc64x.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le #include "textflag.h" diff --git a/src/runtime/duff_mips64x.s b/src/runtime/duff_mips64x.s index a897d7fd9b..3a8524c78b 100644 --- a/src/runtime/duff_mips64x.s +++ b/src/runtime/duff_mips64x.s @@ -3,7 +3,6 @@ // See mkduff.go for comments. //go:build mips64 || mips64le -// +build mips64 mips64le #include "textflag.h" diff --git a/src/runtime/duff_ppc64x.s b/src/runtime/duff_ppc64x.s index eeecf13df1..a3caaa8817 100644 --- a/src/runtime/duff_ppc64x.s +++ b/src/runtime/duff_ppc64x.s @@ -3,7 +3,6 @@ // See mkduff.go for comments. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le #include "textflag.h" diff --git a/src/runtime/internal/atomic/atomic_mips64x.s b/src/runtime/internal/atomic/atomic_mips64x.s index fedfc4a175..b4411d87da 100644 --- a/src/runtime/internal/atomic/atomic_mips64x.s +++ b/src/runtime/internal/atomic/atomic_mips64x.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips64 || mips64le -// +build mips64 mips64le #include "textflag.h" diff --git a/src/runtime/internal/atomic/atomic_mipsx.s b/src/runtime/internal/atomic/atomic_mipsx.s index c0835d66ed..390e9ce7ac 100644 --- a/src/runtime/internal/atomic/atomic_mipsx.s +++ b/src/runtime/internal/atomic/atomic_mipsx.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips || mipsle -// +build mips mipsle #include "textflag.h" diff --git a/src/runtime/internal/atomic/atomic_ppc64x.s b/src/runtime/internal/atomic/atomic_ppc64x.s index 226b3b6216..04f0eadd06 100644 --- a/src/runtime/internal/atomic/atomic_ppc64x.s +++ b/src/runtime/internal/atomic/atomic_ppc64x.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le #include "textflag.h" diff --git a/src/runtime/internal/atomic/sys_nonlinux_arm.s b/src/runtime/internal/atomic/sys_nonlinux_arm.s index 04036ca970..b55bf908a2 100644 --- a/src/runtime/internal/atomic/sys_nonlinux_arm.s +++ b/src/runtime/internal/atomic/sys_nonlinux_arm.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !linux -// +build !linux #include "textflag.h" diff --git a/src/runtime/libfuzzer_amd64.s b/src/runtime/libfuzzer_amd64.s index 13645fc7af..253fe15198 100644 --- a/src/runtime/libfuzzer_amd64.s +++ b/src/runtime/libfuzzer_amd64.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build libfuzzer -// +build libfuzzer #include "go_asm.h" #include "go_tls.h" diff --git a/src/runtime/libfuzzer_arm64.s b/src/runtime/libfuzzer_arm64.s index 4ad8242804..ae0efd8c9b 100644 --- a/src/runtime/libfuzzer_arm64.s +++ b/src/runtime/libfuzzer_arm64.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build libfuzzer -// +build libfuzzer #include "go_asm.h" #include "textflag.h" diff --git a/src/runtime/memclr_386.s b/src/runtime/memclr_386.s index 2627792ced..a72e5f228d 100644 --- a/src/runtime/memclr_386.s +++ b/src/runtime/memclr_386.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !plan9 -// +build !plan9 #include "go_asm.h" #include "textflag.h" diff --git a/src/runtime/memclr_amd64.s b/src/runtime/memclr_amd64.s index 918a4b9e0e..700bbd7b9b 100644 --- a/src/runtime/memclr_amd64.s +++ b/src/runtime/memclr_amd64.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !plan9 -// +build !plan9 #include "go_asm.h" #include "textflag.h" diff --git a/src/runtime/memclr_mips64x.s b/src/runtime/memclr_mips64x.s index bc037013fe..cf3a9c4ab4 100644 --- a/src/runtime/memclr_mips64x.s +++ b/src/runtime/memclr_mips64x.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips64 || mips64le -// +build mips64 mips64le #include "go_asm.h" #include "textflag.h" diff --git a/src/runtime/memclr_mipsx.s b/src/runtime/memclr_mipsx.s index 3d21c3c414..ee3009d46b 100644 --- a/src/runtime/memclr_mipsx.s +++ b/src/runtime/memclr_mipsx.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips || mipsle -// +build mips mipsle #include "textflag.h" diff --git a/src/runtime/memclr_ppc64x.s b/src/runtime/memclr_ppc64x.s index 91aa417ca2..64132cee96 100644 --- a/src/runtime/memclr_ppc64x.s +++ b/src/runtime/memclr_ppc64x.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le #include "textflag.h" diff --git a/src/runtime/memmove_386.s b/src/runtime/memmove_386.s index 389ef88477..6d7e17fcbc 100644 --- a/src/runtime/memmove_386.s +++ b/src/runtime/memmove_386.s @@ -24,7 +24,6 @@ // THE SOFTWARE. //go:build !plan9 -// +build !plan9 #include "go_asm.h" #include "textflag.h" diff --git a/src/runtime/memmove_amd64.s b/src/runtime/memmove_amd64.s index fa0c0e414f..eeb5033fd9 100644 --- a/src/runtime/memmove_amd64.s +++ b/src/runtime/memmove_amd64.s @@ -24,7 +24,6 @@ // THE SOFTWARE. //go:build !plan9 -// +build !plan9 #include "go_asm.h" #include "textflag.h" diff --git a/src/runtime/memmove_mips64x.s b/src/runtime/memmove_mips64x.s index fef3c6be82..b69178ccd3 100644 --- a/src/runtime/memmove_mips64x.s +++ b/src/runtime/memmove_mips64x.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips64 || mips64le -// +build mips64 mips64le #include "textflag.h" diff --git a/src/runtime/memmove_mipsx.s b/src/runtime/memmove_mipsx.s index cd02fc25c4..494288cf33 100644 --- a/src/runtime/memmove_mipsx.s +++ b/src/runtime/memmove_mipsx.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips || mipsle -// +build mips mipsle #include "textflag.h" diff --git a/src/runtime/memmove_ppc64x.s b/src/runtime/memmove_ppc64x.s index b36b23f8ef..e69e71a4a1 100644 --- a/src/runtime/memmove_ppc64x.s +++ b/src/runtime/memmove_ppc64x.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le #include "textflag.h" diff --git a/src/runtime/msan_amd64.s b/src/runtime/msan_amd64.s index 1bb57a3b7e..89ed3048d0 100644 --- a/src/runtime/msan_amd64.s +++ b/src/runtime/msan_amd64.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build msan -// +build msan #include "go_asm.h" #include "go_tls.h" diff --git a/src/runtime/msan_arm64.s b/src/runtime/msan_arm64.s index 93ade8dd89..b9eff34ab6 100644 --- a/src/runtime/msan_arm64.s +++ b/src/runtime/msan_arm64.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build msan -// +build msan #include "go_asm.h" #include "textflag.h" diff --git a/src/runtime/preempt_mips64x.s b/src/runtime/preempt_mips64x.s index c1249e382e..996b592ae0 100644 --- a/src/runtime/preempt_mips64x.s +++ b/src/runtime/preempt_mips64x.s @@ -1,7 +1,6 @@ // Code generated by mkpreempt.go; DO NOT EDIT. //go:build mips64 || mips64le -// +build mips64 mips64le #include "go_asm.h" #include "textflag.h" diff --git a/src/runtime/preempt_mipsx.s b/src/runtime/preempt_mipsx.s index 70b79e05b9..7b169acd99 100644 --- a/src/runtime/preempt_mipsx.s +++ b/src/runtime/preempt_mipsx.s @@ -1,7 +1,6 @@ // Code generated by mkpreempt.go; DO NOT EDIT. //go:build mips || mipsle -// +build mips mipsle #include "go_asm.h" #include "textflag.h" diff --git a/src/runtime/preempt_ppc64x.s b/src/runtime/preempt_ppc64x.s index 7ed4021dde..2c4d02edfe 100644 --- a/src/runtime/preempt_ppc64x.s +++ b/src/runtime/preempt_ppc64x.s @@ -1,7 +1,6 @@ // Code generated by mkpreempt.go; DO NOT EDIT. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le #include "go_asm.h" #include "textflag.h" diff --git a/src/runtime/race_amd64.s b/src/runtime/race_amd64.s index d42e415dca..f055acf77d 100644 --- a/src/runtime/race_amd64.s +++ b/src/runtime/race_amd64.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build race -// +build race #include "go_asm.h" #include "go_tls.h" diff --git a/src/runtime/race_arm64.s b/src/runtime/race_arm64.s index 2b2413b6b7..798e23294a 100644 --- a/src/runtime/race_arm64.s +++ b/src/runtime/race_arm64.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build race -// +build race #include "go_asm.h" #include "funcdata.h" diff --git a/src/runtime/race_ppc64le.s b/src/runtime/race_ppc64le.s index 625c81a255..68cc5c8805 100644 --- a/src/runtime/race_ppc64le.s +++ b/src/runtime/race_ppc64le.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build race -// +build race #include "go_asm.h" #include "go_tls.h" diff --git a/src/runtime/rt0_linux_mips64x.s b/src/runtime/rt0_linux_mips64x.s index fabd8570b5..e9328b7326 100644 --- a/src/runtime/rt0_linux_mips64x.s +++ b/src/runtime/rt0_linux_mips64x.s @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (mips64 || mips64le) -// +build linux -// +build mips64 mips64le #include "textflag.h" diff --git a/src/runtime/rt0_linux_mipsx.s b/src/runtime/rt0_linux_mipsx.s index 9f5842b51a..3cbb7fc377 100644 --- a/src/runtime/rt0_linux_mipsx.s +++ b/src/runtime/rt0_linux_mipsx.s @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (mips || mipsle) -// +build linux -// +build mips mipsle #include "textflag.h" diff --git a/src/runtime/sys_linux_mips64x.s b/src/runtime/sys_linux_mips64x.s index 08e44d671b..0df2597993 100644 --- a/src/runtime/sys_linux_mips64x.s +++ b/src/runtime/sys_linux_mips64x.s @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (mips64 || mips64le) -// +build linux -// +build mips64 mips64le // // System calls and other sys.stuff for mips64, Linux diff --git a/src/runtime/sys_linux_mipsx.s b/src/runtime/sys_linux_mipsx.s index c828431899..2207e9ab98 100644 --- a/src/runtime/sys_linux_mipsx.s +++ b/src/runtime/sys_linux_mipsx.s @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (mips || mipsle) -// +build linux -// +build mips mipsle // // System calls and other sys.stuff for mips, Linux diff --git a/src/runtime/sys_linux_ppc64x.s b/src/runtime/sys_linux_ppc64x.s index 9347afaf19..dc3d89fae7 100644 --- a/src/runtime/sys_linux_ppc64x.s +++ b/src/runtime/sys_linux_ppc64x.s @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (ppc64 || ppc64le) -// +build linux -// +build ppc64 ppc64le // // System calls and other sys.stuff for ppc64, Linux diff --git a/src/runtime/time_linux_amd64.s b/src/runtime/time_linux_amd64.s index 67cfdd8fdf..1416d23230 100644 --- a/src/runtime/time_linux_amd64.s +++ b/src/runtime/time_linux_amd64.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !faketime -// +build !faketime #include "go_asm.h" #include "go_tls.h" diff --git a/src/runtime/time_windows_386.s b/src/runtime/time_windows_386.s index 19ce6910d7..b8b636ef30 100644 --- a/src/runtime/time_windows_386.s +++ b/src/runtime/time_windows_386.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !faketime -// +build !faketime #include "go_asm.h" #include "textflag.h" diff --git a/src/runtime/time_windows_amd64.s b/src/runtime/time_windows_amd64.s index 70f6a008cd..226f2b5136 100644 --- a/src/runtime/time_windows_amd64.s +++ b/src/runtime/time_windows_amd64.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !faketime -// +build !faketime #include "go_asm.h" #include "textflag.h" diff --git a/src/runtime/time_windows_arm.s b/src/runtime/time_windows_arm.s index 6552d75ff1..711af88307 100644 --- a/src/runtime/time_windows_arm.s +++ b/src/runtime/time_windows_arm.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !faketime -// +build !faketime #include "go_asm.h" #include "textflag.h" diff --git a/src/runtime/time_windows_arm64.s b/src/runtime/time_windows_arm64.s index ef5b848473..e0c7d28e15 100644 --- a/src/runtime/time_windows_arm64.s +++ b/src/runtime/time_windows_arm64.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !faketime -// +build !faketime #include "go_asm.h" #include "textflag.h" diff --git a/src/runtime/tls_arm.s b/src/runtime/tls_arm.s index 879caac9e1..83fd37e6ec 100644 --- a/src/runtime/tls_arm.s +++ b/src/runtime/tls_arm.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !windows -// +build !windows #include "go_asm.h" #include "go_tls.h" diff --git a/src/runtime/tls_mips64x.s b/src/runtime/tls_mips64x.s index 779d64ba31..ec2748e5b2 100644 --- a/src/runtime/tls_mips64x.s +++ b/src/runtime/tls_mips64x.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips64 || mips64le -// +build mips64 mips64le #include "go_asm.h" #include "go_tls.h" diff --git a/src/runtime/tls_mipsx.s b/src/runtime/tls_mipsx.s index ada8d06a9e..acc3eb5a17 100644 --- a/src/runtime/tls_mipsx.s +++ b/src/runtime/tls_mipsx.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build mips || mipsle -// +build mips mipsle #include "go_asm.h" #include "go_tls.h" diff --git a/src/runtime/tls_ppc64x.s b/src/runtime/tls_ppc64x.s index 7e935d0eb2..17aec9fc1e 100644 --- a/src/runtime/tls_ppc64x.s +++ b/src/runtime/tls_ppc64x.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le -// +build ppc64 ppc64le #include "go_asm.h" #include "go_tls.h" diff --git a/src/runtime/zcallback_windows.s b/src/runtime/zcallback_windows.s index 561527c90d..bd23d71333 100644 --- a/src/runtime/zcallback_windows.s +++ b/src/runtime/zcallback_windows.s @@ -1,7 +1,6 @@ // Code generated by wincallback.go using 'go generate'. DO NOT EDIT. //go:build 386 || amd64 -// +build 386 amd64 // runtime·callbackasm is called by external code to // execute Go implemented callback function. It is not diff --git a/src/sync/atomic/asm.s b/src/sync/atomic/asm.s index 7b8c9b9430..2022304665 100644 --- a/src/sync/atomic/asm.s +++ b/src/sync/atomic/asm.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !race -// +build !race #include "textflag.h" diff --git a/src/sync/atomic/race.s b/src/sync/atomic/race.s index 0866487cc7..90bd69f321 100644 --- a/src/sync/atomic/race.s +++ b/src/sync/atomic/race.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build race -// +build race // This file is here only to allow external functions. // The operations are implemented in src/runtime/race_amd64.s diff --git a/src/syscall/asan.go b/src/syscall/asan.go index 3199130211..eff30781e4 100644 --- a/src/syscall/asan.go +++ b/src/syscall/asan.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build asan -// +build asan package syscall diff --git a/src/syscall/asan0.go b/src/syscall/asan0.go index 7b69f4a64b..08bc44dea1 100644 --- a/src/syscall/asan0.go +++ b/src/syscall/asan0.go @@ -1,9 +1,8 @@ -// Copyright 2020 The Go Authors. All rights reserved. +// Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. //go:build !asan -// +build !asan package syscall diff --git a/src/syscall/asm9_unix2_amd64.s b/src/syscall/asm9_unix2_amd64.s index 7e5e3c52ad..649bc6024c 100644 --- a/src/syscall/asm9_unix2_amd64.s +++ b/src/syscall/asm9_unix2_amd64.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd -// +build dragonfly freebsd #include "textflag.h" #include "funcdata.h" diff --git a/src/syscall/asm_linux_mips64x.s b/src/syscall/asm_linux_mips64x.s index d18a7b8944..a75d0f7a2a 100644 --- a/src/syscall/asm_linux_mips64x.s +++ b/src/syscall/asm_linux_mips64x.s @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (mips64 || mips64le) -// +build linux -// +build mips64 mips64le #include "textflag.h" diff --git a/src/syscall/asm_linux_mipsx.s b/src/syscall/asm_linux_mipsx.s index cafa6a35c7..04f90f6edf 100644 --- a/src/syscall/asm_linux_mipsx.s +++ b/src/syscall/asm_linux_mipsx.s @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (mips || mipsle) -// +build linux -// +build mips mipsle #include "textflag.h" #include "funcdata.h" diff --git a/src/syscall/asm_linux_ppc64x.s b/src/syscall/asm_linux_ppc64x.s index eac7272f1d..044a479c00 100644 --- a/src/syscall/asm_linux_ppc64x.s +++ b/src/syscall/asm_linux_ppc64x.s @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (ppc64 || ppc64le) -// +build linux -// +build ppc64 ppc64le #include "textflag.h" diff --git a/src/syscall/asm9_unix1_amd64.s b/src/syscall/asm_netbsd_amd64.s similarity index 96% rename from src/syscall/asm9_unix1_amd64.s rename to src/syscall/asm_netbsd_amd64.s index e4609d075c..9e4dd20ad3 100644 --- a/src/syscall/asm9_unix1_amd64.s +++ b/src/syscall/asm_netbsd_amd64.s @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build netbsd -// +build netbsd - #include "textflag.h" #include "funcdata.h" diff --git a/src/syscall/asm_unix_386.s b/src/syscall/asm_unix_386.s index 9f9b7f362d..22700194cb 100644 --- a/src/syscall/asm_unix_386.s +++ b/src/syscall/asm_unix_386.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build freebsd || netbsd -// +build freebsd netbsd #include "textflag.h" #include "funcdata.h" diff --git a/src/syscall/asm_unix_amd64.s b/src/syscall/asm_unix_amd64.s index c53e1a42b6..8ee46b86b5 100644 --- a/src/syscall/asm_unix_amd64.s +++ b/src/syscall/asm_unix_amd64.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build dragonfly || freebsd || netbsd -// +build dragonfly freebsd netbsd #include "textflag.h" #include "funcdata.h" diff --git a/src/syscall/mksyscall.pl b/src/syscall/mksyscall.pl index 758948bc53..25ab911b7c 100755 --- a/src/syscall/mksyscall.pl +++ b/src/syscall/mksyscall.pl @@ -387,7 +387,6 @@ print < Date: Fri, 5 Nov 2021 09:47:54 +0800 Subject: [PATCH 2032/2500] cmd/compile: avoid adding LECall to the entry block when has opendefers The openDeferRecord always insert vardef/varlive pairs into the entry block, it may destroy the mem chain when LECall's args are writing into the same block. So create a new block before that happens. Fixes #49282 Change-Id: Ibda6c4a45d960dd412a641f5e02276f663c80785 Reviewed-on: https://go-review.googlesource.com/c/go/+/361410 Run-TryBot: Alberto Donizetti TryBot-Result: Go Bot Trust: Alberto Donizetti Trust: Than McIntosh Reviewed-by: David Chase --- src/cmd/compile/internal/ssagen/ssa.go | 12 +++++++ test/fixedbugs/issue49282.go | 44 ++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 test/fixedbugs/issue49282.go diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index b84199790f..0853242e6f 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -5075,6 +5075,18 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val for _, p := range params.InParams() { // includes receiver for interface calls ACArgs = append(ACArgs, p.Type) } + + // Split the entry block if there are open defers, because later calls to + // openDeferSave may cause a mismatch between the mem for an OpDereference + // and the call site which uses it. See #49282. + if s.curBlock.ID == s.f.Entry.ID && s.hasOpenDefers { + b := s.endBlock() + b.Kind = ssa.BlockPlain + curb := s.f.NewBlock(ssa.BlockPlain) + b.AddEdgeTo(curb) + s.startBlock(curb) + } + for i, n := range args { callArgs = append(callArgs, s.putArg(n, t.Params().Field(i).Type)) } diff --git a/test/fixedbugs/issue49282.go b/test/fixedbugs/issue49282.go new file mode 100644 index 0000000000..7543075ca1 --- /dev/null +++ b/test/fixedbugs/issue49282.go @@ -0,0 +1,44 @@ +// compile + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +//go:noinline +func g(d uintptr, a, m []int, s struct { + a, b, c, d, e int +}, u uint) { + _ = a + _ = m + _ = s + func() { + for i := 0; i < 5; i++ { + _ = a + _ = m + _, _ = s, s + } + }() +} + +var One float64 = 1.0 + +func f(d uintptr) { + var a, m []int + var s struct { + a, b, c, d, e int + } + + g(d, a, m, s, uint(One)) // Uint of not-a-constant inserts a conditional, necessary to bug + + defer func() uint { + return 0 + }() +} + +var d uintptr + +func h() { + f(d) +} -- GitLab From 3544082f75fd3d2df7af237ed9aef3ddd499ab9c Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Fri, 1 Oct 2021 10:14:32 -0700 Subject: [PATCH 2033/2500] crypto/x509: verification with system and custom roots Make system cert pools special, such that when one has extra roots added to it we run verifications twice, once using the platform verifier, if available, and once using the Go verifier, merging the results. This change re-enables SystemCertPool on Windows, but explicitly does not return anything from CertPool.Subjects (which matches the behavior of macOS). CertPool.Subjects is also marked deprecated. Fixes #46287 Fixes #16736 Change-Id: Idc1843f715ae2b2d0108e55ab942c287181a340a Reviewed-on: https://go-review.googlesource.com/c/go/+/353589 Reviewed-by: Filippo Valsorda Trust: Roland Shoemaker --- src/crypto/x509/cert_pool.go | 27 ++++--- src/crypto/x509/hybrid_pool_test.go | 95 +++++++++++++++++++++++++ src/crypto/x509/root_darwin.go | 2 +- src/crypto/x509/root_windows.go | 48 ++----------- src/crypto/x509/root_windows_test.go | 102 +++++++++++++++++++++++++++ src/crypto/x509/verify.go | 17 ++++- 6 files changed, 229 insertions(+), 62 deletions(-) create mode 100644 src/crypto/x509/hybrid_pool_test.go create mode 100644 src/crypto/x509/root_windows_test.go diff --git a/src/crypto/x509/cert_pool.go b/src/crypto/x509/cert_pool.go index d760dc11c6..873ffeee1d 100644 --- a/src/crypto/x509/cert_pool.go +++ b/src/crypto/x509/cert_pool.go @@ -8,8 +8,6 @@ import ( "bytes" "crypto/sha256" "encoding/pem" - "errors" - "runtime" "sync" ) @@ -29,6 +27,12 @@ type CertPool struct { // call getCert and otherwise negate savings from lazy getCert // funcs). haveSum map[sum224]bool + + // systemPool indicates whether this is a special pool derived from the + // system roots. If it includes additional roots, it requires doing two + // verifications, one using the roots provided by the caller, and one using + // the system platform verifier. + systemPool bool } // lazyCert is minimal metadata about a Cert and a func to retrieve it @@ -75,9 +79,10 @@ func (s *CertPool) cert(n int) (*Certificate, error) { func (s *CertPool) copy() *CertPool { p := &CertPool{ - byName: make(map[string][]int, len(s.byName)), - lazyCerts: make([]lazyCert, len(s.lazyCerts)), - haveSum: make(map[sum224]bool, len(s.haveSum)), + byName: make(map[string][]int, len(s.byName)), + lazyCerts: make([]lazyCert, len(s.lazyCerts)), + haveSum: make(map[sum224]bool, len(s.haveSum)), + systemPool: s.systemPool, } for k, v := range s.byName { indexes := make([]int, len(v)) @@ -103,15 +108,6 @@ func (s *CertPool) copy() *CertPool { // // New changes in the system cert pool might not be reflected in subsequent calls. func SystemCertPool() (*CertPool, error) { - if runtime.GOOS == "windows" { - // Issue 16736, 18609: - return nil, errors.New("crypto/x509: system root pool is not available on Windows") - } else if runtime.GOOS == "darwin" { - return nil, errors.New("crypto/x509: system root pool is not available on macOS") - } else if runtime.GOOS == "ios" { - return nil, errors.New("crypto/x509: system root pool is not available on iOS") - } - if sysRoots := systemRootsPool(); sysRoots != nil { return sysRoots.copy(), nil } @@ -243,6 +239,9 @@ func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) { // Subjects returns a list of the DER-encoded subjects of // all of the certificates in the pool. +// +// Deprecated: if s was returned by SystemCertPool, Subjects +// will not include the system roots. func (s *CertPool) Subjects() [][]byte { res := make([][]byte, s.len()) for i, lc := range s.lazyCerts { diff --git a/src/crypto/x509/hybrid_pool_test.go b/src/crypto/x509/hybrid_pool_test.go new file mode 100644 index 0000000000..d4dd9d5c22 --- /dev/null +++ b/src/crypto/x509/hybrid_pool_test.go @@ -0,0 +1,95 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509_test + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" + "internal/testenv" + "math/big" + "runtime" + "testing" + "time" +) + +func TestHybridPool(t *testing.T) { + if !(runtime.GOOS == "windows" || runtime.GOOS == "darwin" || runtime.GOOS == "ios") { + t.Skipf("platform verifier not available on %s", runtime.GOOS) + } + if !testenv.HasExternalNetwork() { + t.Skip() + } + + // Get the google.com chain, which should be valid on all platforms we + // are testing + c, err := tls.Dial("tcp", "google.com:443", &tls.Config{InsecureSkipVerify: true}) + if err != nil { + t.Fatalf("tls connection failed: %s", err) + } + googChain := c.ConnectionState().PeerCertificates + + rootTmpl := &x509.Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{CommonName: "Go test root"}, + IsCA: true, + BasicConstraintsValid: true, + NotBefore: time.Now().Add(-time.Hour), + NotAfter: time.Now().Add(time.Hour * 10), + } + k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatalf("failed to generate test key: %s", err) + } + rootDER, err := x509.CreateCertificate(rand.Reader, rootTmpl, rootTmpl, k.Public(), k) + if err != nil { + t.Fatalf("failed to create test cert: %s", err) + } + root, err := x509.ParseCertificate(rootDER) + if err != nil { + t.Fatalf("failed to parse test cert: %s", err) + } + + pool, err := x509.SystemCertPool() + if err != nil { + t.Fatalf("SystemCertPool failed: %s", err) + } + opts := x509.VerifyOptions{Roots: pool} + + _, err = googChain[0].Verify(opts) + if err != nil { + t.Fatalf("verification failed for google.com chain (empty pool): %s", err) + } + + pool.AddCert(root) + + _, err = googChain[0].Verify(opts) + if err != nil { + t.Fatalf("verification failed for google.com chain (hybrid pool): %s", err) + } + + certTmpl := &x509.Certificate{ + SerialNumber: big.NewInt(1), + NotBefore: time.Now().Add(-time.Hour), + NotAfter: time.Now().Add(time.Hour * 10), + DNSNames: []string{"example.com"}, + } + certDER, err := x509.CreateCertificate(rand.Reader, certTmpl, rootTmpl, k.Public(), k) + if err != nil { + t.Fatalf("failed to create test cert: %s", err) + } + cert, err := x509.ParseCertificate(certDER) + if err != nil { + t.Fatalf("failed to parse test cert: %s", err) + } + + _, err = cert.Verify(opts) + if err != nil { + t.Fatalf("verification failed for custom chain (hybrid pool): %s", err) + } +} diff --git a/src/crypto/x509/root_darwin.go b/src/crypto/x509/root_darwin.go index 7bc6ce09fa..a7ff1e78bb 100644 --- a/src/crypto/x509/root_darwin.go +++ b/src/crypto/x509/root_darwin.go @@ -107,5 +107,5 @@ func exportCertificate(cert macOS.CFRef) (*Certificate, error) { } func loadSystemRoots() (*CertPool, error) { - return nil, nil + return &CertPool{systemPool: true}, nil } diff --git a/src/crypto/x509/root_windows.go b/src/crypto/x509/root_windows.go index f77ea3a698..d65d8768d9 100644 --- a/src/crypto/x509/root_windows.go +++ b/src/crypto/x509/root_windows.go @@ -10,6 +10,10 @@ import ( "unsafe" ) +func loadSystemRoots() (*CertPool, error) { + return &CertPool{systemPool: true}, nil +} + // Creates a new *syscall.CertContext representing the leaf certificate in an in-memory // certificate store containing itself and all of the intermediate certificates specified // in the opts.Intermediates CertPool. @@ -271,47 +275,3 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate return chains, nil } - -func loadSystemRoots() (*CertPool, error) { - // TODO: restore this functionality on Windows. We tried to do - // it in Go 1.8 but had to revert it. See Issue 18609. - // Returning (nil, nil) was the old behavior, prior to CL 30578. - // The if statement here avoids vet complaining about - // unreachable code below. - if true { - return nil, nil - } - - const CRYPT_E_NOT_FOUND = 0x80092004 - - store, err := syscall.CertOpenSystemStore(0, syscall.StringToUTF16Ptr("ROOT")) - if err != nil { - return nil, err - } - defer syscall.CertCloseStore(store, 0) - - roots := NewCertPool() - var cert *syscall.CertContext - for { - cert, err = syscall.CertEnumCertificatesInStore(store, cert) - if err != nil { - if errno, ok := err.(syscall.Errno); ok { - if errno == CRYPT_E_NOT_FOUND { - break - } - } - return nil, err - } - if cert == nil { - break - } - // Copy the buf, since ParseCertificate does not create its own copy. - buf := (*[1 << 20]byte)(unsafe.Pointer(cert.EncodedCert))[:cert.Length:cert.Length] - buf2 := make([]byte, cert.Length) - copy(buf2, buf) - if c, err := ParseCertificate(buf2); err == nil { - roots.AddCert(c) - } - } - return roots, nil -} diff --git a/src/crypto/x509/root_windows_test.go b/src/crypto/x509/root_windows_test.go new file mode 100644 index 0000000000..ce6d9273d9 --- /dev/null +++ b/src/crypto/x509/root_windows_test.go @@ -0,0 +1,102 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x509_test + +import ( + "crypto/tls" + "crypto/x509" + "internal/testenv" + "testing" + "time" +) + +func TestPlatformVerifier(t *testing.T) { + if !testenv.HasExternalNetwork() { + t.Skip() + } + + getChain := func(host string) []*x509.Certificate { + t.Helper() + c, err := tls.Dial("tcp", host+":443", &tls.Config{InsecureSkipVerify: true}) + if err != nil { + t.Fatalf("tls connection failed: %s", err) + } + return c.ConnectionState().PeerCertificates + } + + tests := []struct { + name string + host string + verifyName string + verifyTime time.Time + expectedErr string + }{ + { + // whatever google.com serves should, hopefully, be trusted + name: "valid chain", + host: "google.com", + }, + { + name: "expired leaf", + host: "expired.badssl.com", + expectedErr: "x509: certificate has expired or is not yet valid: ", + }, + { + name: "wrong host for leaf", + host: "wrong.host.badssl.com", + verifyName: "wrong.host.badssl.com", + expectedErr: "x509: certificate is valid for *.badssl.com, badssl.com, not wrong.host.badssl.com", + }, + { + name: "self-signed leaf", + host: "self-signed.badssl.com", + expectedErr: "x509: certificate signed by unknown authority", + }, + { + name: "untrusted root", + host: "untrusted-root.badssl.com", + expectedErr: "x509: certificate signed by unknown authority", + }, + { + name: "expired leaf (custom time)", + host: "google.com", + verifyTime: time.Time{}.Add(time.Hour), + expectedErr: "x509: certificate has expired or is not yet valid: ", + }, + { + name: "valid chain (custom time)", + host: "google.com", + verifyTime: time.Now(), + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + chain := getChain(tc.host) + var opts x509.VerifyOptions + if len(chain) > 1 { + opts.Intermediates = x509.NewCertPool() + for _, c := range chain[1:] { + opts.Intermediates.AddCert(c) + } + } + if tc.verifyName != "" { + opts.DNSName = tc.verifyName + } + if !tc.verifyTime.IsZero() { + opts.CurrentTime = tc.verifyTime + } + + _, err := chain[0].Verify(opts) + if err != nil && tc.expectedErr == "" { + t.Errorf("unexpected verification error: %s", err) + } else if err != nil && err.Error() != tc.expectedErr { + t.Errorf("unexpected verification error: got %q, want %q", err.Error(), tc.expectedErr) + } else if err == nil && tc.expectedErr != "" { + t.Errorf("unexpected verification success: want %q", tc.expectedErr) + } + }) + } +} diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go index 59852d9d68..1562ee57af 100644 --- a/src/crypto/x509/verify.go +++ b/src/crypto/x509/verify.go @@ -741,9 +741,20 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e } } - // Use platform verifiers, where available - if opts.Roots == nil && (runtime.GOOS == "windows" || runtime.GOOS == "darwin" || runtime.GOOS == "ios") { - return c.systemVerify(&opts) + // Use platform verifiers, where available, if Roots is from SystemCertPool. + if runtime.GOOS == "windows" || runtime.GOOS == "darwin" || runtime.GOOS == "ios" { + if opts.Roots == nil { + return c.systemVerify(&opts) + } + if opts.Roots != nil && opts.Roots.systemPool { + platformChains, err := c.systemVerify(&opts) + // If the platform verifier succeeded, or there are no additional + // roots, return the platform verifier result. Otherwise, continue + // with the Go verifier. + if err == nil || opts.Roots.len() == 0 { + return platformChains, err + } + } } if opts.Roots == nil { -- GitLab From 565f457e81a97f80412c9979fc3510c17849381e Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 4 Nov 2021 16:22:49 -0700 Subject: [PATCH 2034/2500] cmd/compile/internal/types2: always parse tests assuming generic code We don't need to distinguish anymore as this is the new default. This removes the need to prefix test package names with "generic_". Change-Id: If9eaa0a5cffcd19deb529aca6798206f2d396ca1 Reviewed-on: https://go-review.googlesource.com/c/go/+/361408 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/api_test.go | 99 +++++++++---------- .../internal/types2/instantiate_test.go | 8 +- 2 files changed, 50 insertions(+), 57 deletions(-) diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index 30cfbe0ee4..a59c9a4eee 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -17,21 +17,14 @@ import ( . "cmd/compile/internal/types2" ) -// genericPkg is a source prefix for packages that contain generic code. -const genericPkg = "package generic_" - // brokenPkg is a source prefix for packages that are not expected to parse // or type-check cleanly. They are always parsed assuming that they contain // generic code. const brokenPkg = "package broken_" func parseSrc(path, src string) (*syntax.File, error) { - var mode syntax.Mode - if strings.HasPrefix(src, genericPkg) || strings.HasPrefix(src, brokenPkg) { - mode = syntax.AllowGenerics - } errh := func(error) {} // dummy error handler so that parsing continues in presence of errors - return syntax.Parse(syntax.NewFileBase(path), strings.NewReader(src), errh, nil, mode) + return syntax.Parse(syntax.NewFileBase(path), strings.NewReader(src), errh, nil, syntax.AllowGenerics) } func pkgFor(path, source string, info *Info) (*Package, error) { @@ -326,25 +319,25 @@ func TestTypesInfo(t *testing.T) { {brokenPkg + `x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string]invalid type`}, // parameterized functions - {genericPkg + `p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[T interface{}](T)`}, - {genericPkg + `p1; func f[T any](T) {}; var _ = f[int]`, `f[int]`, `func(int)`}, - {genericPkg + `p2; func f[T any](T) {}; func _() { f(42) }`, `f`, `func(int)`}, - {genericPkg + `p3; func f[T any](T) {}; func _() { f[int](42) }`, `f[int]`, `func(int)`}, - {genericPkg + `p4; func f[T any](T) {}; func _() { f[int](42) }`, `f`, `func[T interface{}](T)`}, - {genericPkg + `p5; func f[T any](T) {}; func _() { f(42) }`, `f(42)`, `()`}, + {`package p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[T interface{}](T)`}, + {`package p1; func f[T any](T) {}; var _ = f[int]`, `f[int]`, `func(int)`}, + {`package p2; func f[T any](T) {}; func _() { f(42) }`, `f`, `func(int)`}, + {`package p3; func f[T any](T) {}; func _() { f[int](42) }`, `f[int]`, `func(int)`}, + {`package p4; func f[T any](T) {}; func _() { f[int](42) }`, `f`, `func[T interface{}](T)`}, + {`package p5; func f[T any](T) {}; func _() { f(42) }`, `f(42)`, `()`}, // type parameters - {genericPkg + `t0; type t[] int; var _ t`, `t`, `generic_t0.t`}, // t[] is a syntax error that is ignored in this test in favor of t - {genericPkg + `t1; type t[P any] int; var _ t[int]`, `t`, `generic_t1.t[P interface{}]`}, - {genericPkg + `t2; type t[P interface{}] int; var _ t[int]`, `t`, `generic_t2.t[P interface{}]`}, - {genericPkg + `t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `generic_t3.t[P, Q interface{}]`}, + {`package t0; type t[] int; var _ t`, `t`, `t0.t`}, // t[] is a syntax error that is ignored in this test in favor of t + {`package t1; type t[P any] int; var _ t[int]`, `t`, `t1.t[P interface{}]`}, + {`package t2; type t[P interface{}] int; var _ t[int]`, `t`, `t2.t[P interface{}]`}, + {`package t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `t3.t[P, Q interface{}]`}, {brokenPkg + `t4; type t[P, Q interface{ m() }] int; var _ t[int, int]`, `t`, `broken_t4.t[P, Q interface{m()}]`}, // instantiated types must be sanitized - {genericPkg + `g0; type t[P any] int; var x struct{ f t[int] }; var _ = x.f`, `x.f`, `generic_g0.t[int]`}, + {`package g0; type t[P any] int; var x struct{ f t[int] }; var _ = x.f`, `x.f`, `g0.t[int]`}, // issue 45096 - {genericPkg + `issue45096; func _[T interface{ ~int8 | ~int16 | ~int32 }](x T) { _ = x < 0 }`, `0`, `T`}, + {`package issue45096; func _[T interface{ ~int8 | ~int16 | ~int32 }](x T) { _ = x < 0 }`, `0`, `T`}, // issue 47895 {`package p; import "unsafe"; type S struct { f int }; var s S; var _ = unsafe.Offsetof(s.f)`, `s.f`, `int`}, @@ -391,138 +384,138 @@ func TestInstanceInfo(t *testing.T) { targs []string typ string }{ - {genericPkg + `p0; func f[T any](T) {}; func _() { f(42) }`, + {`package p0; func f[T any](T) {}; func _() { f(42) }`, `f`, []string{`int`}, `func(int)`, }, - {genericPkg + `p1; func f[T any](T) T { panic(0) }; func _() { f('@') }`, + {`package p1; func f[T any](T) T { panic(0) }; func _() { f('@') }`, `f`, []string{`rune`}, `func(rune) rune`, }, - {genericPkg + `p2; func f[T any](...T) T { panic(0) }; func _() { f(0i) }`, + {`package p2; func f[T any](...T) T { panic(0) }; func _() { f(0i) }`, `f`, []string{`complex128`}, `func(...complex128) complex128`, }, - {genericPkg + `p3; func f[A, B, C any](A, *B, []C) {}; func _() { f(1.2, new(string), []byte{}) }`, + {`package p3; func f[A, B, C any](A, *B, []C) {}; func _() { f(1.2, new(string), []byte{}) }`, `f`, []string{`float64`, `string`, `byte`}, `func(float64, *string, []byte)`, }, - {genericPkg + `p4; func f[A, B any](A, *B, ...[]B) {}; func _() { f(1.2, new(byte)) }`, + {`package p4; func f[A, B any](A, *B, ...[]B) {}; func _() { f(1.2, new(byte)) }`, `f`, []string{`float64`, `byte`}, `func(float64, *byte, ...[]byte)`, }, // we don't know how to translate these but we can type-check them - {genericPkg + `q0; type T struct{}; func (T) m[P any](P) {}; func _(x T) { x.m(42) }`, + {`package q0; type T struct{}; func (T) m[P any](P) {}; func _(x T) { x.m(42) }`, `m`, []string{`int`}, `func(int)`, }, - {genericPkg + `q1; type T struct{}; func (T) m[P any](P) P { panic(0) }; func _(x T) { x.m(42) }`, + {`package q1; type T struct{}; func (T) m[P any](P) P { panic(0) }; func _(x T) { x.m(42) }`, `m`, []string{`int`}, `func(int) int`, }, - {genericPkg + `q2; type T struct{}; func (T) m[P any](...P) P { panic(0) }; func _(x T) { x.m(42) }`, + {`package q2; type T struct{}; func (T) m[P any](...P) P { panic(0) }; func _(x T) { x.m(42) }`, `m`, []string{`int`}, `func(...int) int`, }, - {genericPkg + `q3; type T struct{}; func (T) m[A, B, C any](A, *B, []C) {}; func _(x T) { x.m(1.2, new(string), []byte{}) }`, + {`package q3; type T struct{}; func (T) m[A, B, C any](A, *B, []C) {}; func _(x T) { x.m(1.2, new(string), []byte{}) }`, `m`, []string{`float64`, `string`, `byte`}, `func(float64, *string, []byte)`, }, - {genericPkg + `q4; type T struct{}; func (T) m[A, B any](A, *B, ...[]B) {}; func _(x T) { x.m(1.2, new(byte)) }`, + {`package q4; type T struct{}; func (T) m[A, B any](A, *B, ...[]B) {}; func _(x T) { x.m(1.2, new(byte)) }`, `m`, []string{`float64`, `byte`}, `func(float64, *byte, ...[]byte)`, }, - {genericPkg + `r0; type T[P any] struct{}; func (_ T[P]) m[Q any](Q) {}; func _[P any](x T[P]) { x.m(42) }`, + {`package r0; type T[P any] struct{}; func (_ T[P]) m[Q any](Q) {}; func _[P any](x T[P]) { x.m(42) }`, `m`, []string{`int`}, `func(int)`, }, // TODO(gri) record method type parameters in syntax.FuncType so we can check this - // {genericPkg + `r1; type T interface{ m[P any](P) }; func _(x T) { x.m(4.2) }`, + // {`package r1; type T interface{ m[P any](P) }; func _(x T) { x.m(4.2) }`, // `x.m`, // []string{`float64`}, // `func(float64)`, // }, - {genericPkg + `s1; func f[T any, P interface{~*T}](x T) {}; func _(x string) { f(x) }`, + {`package s1; func f[T any, P interface{~*T}](x T) {}; func _(x string) { f(x) }`, `f`, []string{`string`, `*string`}, `func(x string)`, }, - {genericPkg + `s2; func f[T any, P interface{~*T}](x []T) {}; func _(x []int) { f(x) }`, + {`package s2; func f[T any, P interface{~*T}](x []T) {}; func _(x []int) { f(x) }`, `f`, []string{`int`, `*int`}, `func(x []int)`, }, - {genericPkg + `s3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]](x []T) {}; func _(x []int) { f(x) }`, + {`package s3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]](x []T) {}; func _(x []int) { f(x) }`, `f`, []string{`int`, `chan<- int`}, `func(x []int)`, }, - {genericPkg + `s4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T) {}; func _(x []int) { f(x) }`, + {`package s4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T) {}; func _(x []int) { f(x) }`, `f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func(x []int)`, }, - {genericPkg + `t1; func f[T any, P interface{~*T}]() T { panic(0) }; func _() { _ = f[string] }`, + {`package t1; func f[T any, P interface{~*T}]() T { panic(0) }; func _() { _ = f[string] }`, `f`, []string{`string`, `*string`}, `func() string`, }, - {genericPkg + `t2; func f[T any, P interface{~*T}]() T { panic(0) }; func _() { _ = (f[string]) }`, + {`package t2; func f[T any, P interface{~*T}]() T { panic(0) }; func _() { _ = (f[string]) }`, `f`, []string{`string`, `*string`}, `func() string`, }, - {genericPkg + `t3; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = f[int] }`, + {`package t3; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = f[int] }`, `f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func() []int`, }, - {genericPkg + `t4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = f[int] }`, + {`package t4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = f[int] }`, `f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func() []int`, }, - {genericPkg + `i0; import lib "generic_lib"; func _() { lib.F(42) }`, + {`package i0; import lib "generic_lib"; func _() { lib.F(42) }`, `F`, []string{`int`}, `func(int)`, }, - {genericPkg + `type0; type T[P interface{~int}] struct{ x P }; var _ T[int]`, + {`package type0; type T[P interface{~int}] struct{ x P }; var _ T[int]`, `T`, []string{`int`}, `struct{x int}`, }, - {genericPkg + `type1; type T[P interface{~int}] struct{ x P }; var _ (T[int])`, + {`package type1; type T[P interface{~int}] struct{ x P }; var _ (T[int])`, `T`, []string{`int`}, `struct{x int}`, }, - {genericPkg + `type2; type T[P interface{~int}] struct{ x P }; var _ T[(int)]`, + {`package type2; type T[P interface{~int}] struct{ x P }; var _ T[(int)]`, `T`, []string{`int`}, `struct{x int}`, }, - {genericPkg + `type3; type T[P1 interface{~[]P2}, P2 any] struct{ x P1; y P2 }; var _ T[[]int, int]`, + {`package type3; type T[P1 interface{~[]P2}, P2 any] struct{ x P1; y P2 }; var _ T[[]int, int]`, `T`, []string{`[]int`, `int`}, `struct{x []int; y int}`, }, - {genericPkg + `type4; import lib "generic_lib"; var _ lib.T[int]`, + {`package type4; import lib "generic_lib"; var _ lib.T[int]`, `T`, []string{`int`}, `[]int`, @@ -1958,7 +1951,7 @@ func f(x T) T { return foo.F(x) } func TestInstantiate(t *testing.T) { // eventually we like more tests but this is a start - const src = genericPkg + "p; type T[P any] *T[P]" + const src = "package p; type T[P any] *T[P]" pkg, err := pkgFor(".", src, nil) if err != nil { t.Fatal(err) @@ -1996,7 +1989,7 @@ func TestInstantiateErrors(t *testing.T) { } for _, test := range tests { - src := genericPkg + "p; " + test.src + src := "package p; " + test.src pkg, err := pkgFor(".", src, nil) if err != nil { t.Fatal(err) @@ -2031,11 +2024,11 @@ func TestInstanceIdentity(t *testing.T) { } imports[name] = pkg } - makePkg(genericPkg + `lib; type T[P any] struct{}`) - makePkg(genericPkg + `a; import "generic_lib"; var A generic_lib.T[int]`) - makePkg(genericPkg + `b; import "generic_lib"; var B generic_lib.T[int]`) - a := imports["generic_a"].Scope().Lookup("A") - b := imports["generic_b"].Scope().Lookup("B") + makePkg(`package lib; type T[P any] struct{}`) + makePkg(`package a; import "lib"; var A lib.T[int]`) + makePkg(`package b; import "lib"; var B lib.T[int]`) + a := imports["a"].Scope().Lookup("A") + b := imports["b"].Scope().Lookup("B") if !Identical(a.Type(), b.Type()) { t.Errorf("mismatching types: a.A: %s, b.B: %s", a.Type(), b.Type()) } diff --git a/src/cmd/compile/internal/types2/instantiate_test.go b/src/cmd/compile/internal/types2/instantiate_test.go index a99fc5d032..4f10dd929f 100644 --- a/src/cmd/compile/internal/types2/instantiate_test.go +++ b/src/cmd/compile/internal/types2/instantiate_test.go @@ -10,7 +10,7 @@ import ( ) func TestInstantiateEquality(t *testing.T) { - const src = genericPkg + "p; type T[P any] int" + const src = "package p; type T[P any] int" pkg, err := pkgFor(".", src, nil) if err != nil { t.Fatal(err) @@ -32,7 +32,7 @@ func TestInstantiateEquality(t *testing.T) { } } func TestInstantiateNonEquality(t *testing.T) { - const src = genericPkg + "p; type T[P any] int" + const src = "package p; type T[P any] int" pkg1, err := pkgFor(".", src, nil) if err != nil { t.Fatal(err) @@ -63,7 +63,7 @@ func TestInstantiateNonEquality(t *testing.T) { } func TestMethodInstantiation(t *testing.T) { - const prefix = genericPkg + `p + const prefix = `package p type T[P any] struct{} @@ -102,7 +102,7 @@ var X T[int] } func TestImmutableSignatures(t *testing.T) { - const src = genericPkg + `p + const src = `package p type T[P any] struct{} -- GitLab From 7ca772a5bc5d7f2a391f7f2a0febc54d84acb9d7 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 4 Nov 2021 16:00:34 -0700 Subject: [PATCH 2035/2500] cmd/compile/internal/types2: make object test an external test Change-Id: I15c969a799404067f34f600da15b1a97d4857315 Reviewed-on: https://go-review.googlesource.com/c/go/+/361409 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- .../compile/internal/types2/object_test.go | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/cmd/compile/internal/types2/object_test.go b/src/cmd/compile/internal/types2/object_test.go index ed3c123023..2fb57d2377 100644 --- a/src/cmd/compile/internal/types2/object_test.go +++ b/src/cmd/compile/internal/types2/object_test.go @@ -2,17 +2,14 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package types2 +package types2_test import ( "cmd/compile/internal/syntax" - "strings" "testing" -) -func parseSrc(path, src string) (*syntax.File, error) { - return syntax.Parse(syntax.NewFileBase(path), strings.NewReader(src), nil, nil, 0) -} + . "cmd/compile/internal/types2" +) func TestIsAlias(t *testing.T) { check := func(obj *TypeName, want bool) { @@ -42,12 +39,12 @@ func TestIsAlias(t *testing.T) { {NewTypeName(nopos, nil, "t0", nil), false}, // no type yet {NewTypeName(nopos, pkg, "t0", nil), false}, // no type yet {t1, false}, // type name refers to named type and vice versa - {NewTypeName(nopos, nil, "t2", &emptyInterface), true}, // type name refers to unnamed type - {NewTypeName(nopos, pkg, "t3", n1), true}, // type name refers to named type with different type name - {NewTypeName(nopos, nil, "t4", Typ[Int32]), true}, // type name refers to basic type with different name - {NewTypeName(nopos, nil, "int32", Typ[Int32]), false}, // type name refers to basic type with same name - {NewTypeName(nopos, pkg, "int32", Typ[Int32]), true}, // type name is declared in user-defined package (outside Universe) - {NewTypeName(nopos, nil, "rune", Typ[Rune]), true}, // type name refers to basic type rune which is an alias already + {NewTypeName(nopos, nil, "t2", NewInterfaceType(nil, nil)), true}, // type name refers to unnamed type + {NewTypeName(nopos, pkg, "t3", n1), true}, // type name refers to named type with different type name + {NewTypeName(nopos, nil, "t4", Typ[Int32]), true}, // type name refers to basic type with different name + {NewTypeName(nopos, nil, "int32", Typ[Int32]), false}, // type name refers to basic type with same name + {NewTypeName(nopos, pkg, "int32", Typ[Int32]), true}, // type name is declared in user-defined package (outside Universe) + {NewTypeName(nopos, nil, "rune", Typ[Rune]), true}, // type name refers to basic type rune which is an alias already {t5, false}, // type name refers to type parameter and vice versa } { check(test.name, test.alias) -- GitLab From cfb3dc7710ba35d9932ba9f5242730a97f9ae603 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 4 Nov 2021 12:50:25 -0700 Subject: [PATCH 2036/2500] cmd/compile/internal/types2: clearer object string for type parameters - print "type parameter" rather than just "type" - print the type bound rather than the underlying type - added an object string test Change-Id: Ibb572ff35b74f2c6ccb27641154f096770541130 Reviewed-on: https://go-review.googlesource.com/c/go/+/361401 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/object.go | 21 +++-- .../compile/internal/types2/object_test.go | 78 +++++++++++++++++++ .../internal/types2/typestring_test.go | 7 +- 3 files changed, 98 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/internal/types2/object.go b/src/cmd/compile/internal/types2/object.go index c7d6709c26..d86c166c72 100644 --- a/src/cmd/compile/internal/types2/object.go +++ b/src/cmd/compile/internal/types2/object.go @@ -458,6 +458,9 @@ func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) { case *TypeName: tname = obj buf.WriteString("type") + if isTypeParam(typ) { + buf.WriteString(" parameter") + } case *Var: if obj.isField { @@ -503,18 +506,22 @@ func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) { } if tname != nil { - // We have a type object: Don't print anything more for - // basic types since there's no more information (names - // are the same; see also comment in TypeName.IsAlias). - if _, ok := typ.(*Basic); ok { + switch t := typ.(type) { + case *Basic: + // Don't print anything more for basic types since there's + // no more information. return - } - if named, _ := typ.(*Named); named != nil && named.TypeParams().Len() > 0 { - newTypeWriter(buf, qf).tParamList(named.TypeParams().list()) + case *Named: + if t.TypeParams().Len() > 0 { + newTypeWriter(buf, qf).tParamList(t.TypeParams().list()) + } } if tname.IsAlias() { buf.WriteString(" =") + } else if t, _ := typ.(*TypeParam); t != nil { + typ = t.bound } else { + // TODO(gri) should this be fromRHS for *Named? typ = under(typ) } } diff --git a/src/cmd/compile/internal/types2/object_test.go b/src/cmd/compile/internal/types2/object_test.go index 2fb57d2377..93b3dfb44b 100644 --- a/src/cmd/compile/internal/types2/object_test.go +++ b/src/cmd/compile/internal/types2/object_test.go @@ -6,6 +6,8 @@ package types2_test import ( "cmd/compile/internal/syntax" + "internal/testenv" + "strings" "testing" . "cmd/compile/internal/types2" @@ -86,3 +88,79 @@ func TestEmbeddedMethod(t *testing.T) { t.Fatalf("%s (%p) != %s (%p)", orig, orig, embed, embed) } } + +var testObjects = []struct { + src string + obj string + want string +}{ + {"import \"io\"; var r io.Reader", "r", "var p.r io.Reader"}, + + {"const c = 1.2", "c", "const p.c untyped float"}, + {"const c float64 = 3.14", "c", "const p.c float64"}, + + {"type t struct{f int}", "t", "type p.t struct{f int}"}, + {"type t func(int)", "t", "type p.t func(int)"}, + {"type t[P any] struct{f P}", "t", "type p.t[P interface{}] struct{f P}"}, + {"type t[P any] struct{f P}", "t.P", "type parameter P interface{}"}, + {"type C interface{m()}; type t[P C] struct{}", "t.P", "type parameter P p.C"}, + + {"type t = struct{f int}", "t", "type p.t = struct{f int}"}, + {"type t = func(int)", "t", "type p.t = func(int)"}, + + {"var v int", "v", "var p.v int"}, + + {"func f(int) string", "f", "func p.f(int) string"}, + {"func g[P any](x P){}", "g", "func p.g[P interface{}](x P)"}, + {"func g[P interface{~int}](x P){}", "g.P", "type parameter P interface{~int}"}, +} + +func TestObjectString(t *testing.T) { + testenv.MustHaveGoBuild(t) + + for _, test := range testObjects { + src := "package p; " + test.src + pkg, err := makePkg(src) + if err != nil { + t.Errorf("%s: %s", src, err) + continue + } + + names := strings.Split(test.obj, ".") + if len(names) != 1 && len(names) != 2 { + t.Errorf("%s: invalid object path %s", test.src, test.obj) + continue + } + obj := pkg.Scope().Lookup(names[0]) + if obj == nil { + t.Errorf("%s: %s not found", test.src, names[0]) + continue + } + if len(names) == 2 { + if typ, ok := obj.Type().(interface{ TypeParams() *TypeParamList }); ok { + obj = lookupTypeParamObj(typ.TypeParams(), names[1]) + if obj == nil { + t.Errorf("%s: %s not found", test.src, test.obj) + continue + } + } else { + t.Errorf("%s: %s has no type parameters", test.src, names[0]) + continue + } + } + + if got := obj.String(); got != test.want { + t.Errorf("%s: got %s, want %s", test.src, got, test.want) + } + } +} + +func lookupTypeParamObj(list *TypeParamList, name string) Object { + for i := 0; i < list.Len(); i++ { + tpar := list.At(i) + if tpar.Obj().Name() == name { + return tpar.Obj() + } + } + return nil +} diff --git a/src/cmd/compile/internal/types2/typestring_test.go b/src/cmd/compile/internal/types2/typestring_test.go index 0ed2934961..eda6835588 100644 --- a/src/cmd/compile/internal/types2/typestring_test.go +++ b/src/cmd/compile/internal/types2/typestring_test.go @@ -129,7 +129,12 @@ func TestTypeString(t *testing.T) { t.Errorf("%s: %s", src, err) continue } - typ := pkg.Scope().Lookup("T").Type().Underlying() + obj := pkg.Scope().Lookup("T") + if obj == nil { + t.Errorf("%s: T not found", test.src) + continue + } + typ := obj.Type().Underlying() if got := typ.String(); got != test.str { t.Errorf("%s: got %s, want %s", test.src, got, test.str) } -- GitLab From 61d789db3a52e4570596f1fd15122358deb73b77 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 4 Nov 2021 21:31:08 -0700 Subject: [PATCH 2037/2500] cmd/compile/internal/types2: report error for incomplete struct composite literal type Mark a struct as "complete" with a non-nil (but possibly zero length) fields list. Add a test when type-checking struct composite literals, the same way we do for other composite literal types. Fixes #49276. Change-Id: If44a3d790bf7032ddcd155af49bdc47b1cdff4fc Reviewed-on: https://go-review.googlesource.com/c/go/+/361412 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/expr.go | 6 +++ src/cmd/compile/internal/types2/struct.go | 14 +++++- src/cmd/compile/internal/types2/subst.go | 4 +- .../types2/testdata/fixedbugs/issue49276.go | 46 +++++++++++++++++++ 4 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue49276.go diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 95b96f2334..d618ebd372 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -1260,6 +1260,12 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin switch utyp := structure(base).(type) { case *Struct: + // Prevent crash if the struct referred to is not yet set up. + // See analogous comment for *Array. + if utyp.fields == nil { + check.error(e, "illegal cycle in type declaration") + goto Error + } if len(e.ElemList) == 0 { break } diff --git a/src/cmd/compile/internal/types2/struct.go b/src/cmd/compile/internal/types2/struct.go index 933d7ef947..8c39f5e3c4 100644 --- a/src/cmd/compile/internal/types2/struct.go +++ b/src/cmd/compile/internal/types2/struct.go @@ -14,7 +14,7 @@ import ( // A Struct represents a struct type. type Struct struct { - fields []*Var + fields []*Var // fields != nil indicates the struct is set up (possibly with len(fields) == 0) tags []string // field tags; nil if there are no tags } @@ -32,7 +32,9 @@ func NewStruct(fields []*Var, tags []string) *Struct { if len(tags) > len(fields) { panic("more tags than fields") } - return &Struct{fields: fields, tags: tags} + s := &Struct{fields: fields, tags: tags} + s.markComplete() + return s } // NumFields returns the number of fields in the struct (including blank and embedded fields). @@ -55,8 +57,15 @@ func (s *Struct) String() string { return TypeString(s, nil) } // ---------------------------------------------------------------------------- // Implementation +func (s *Struct) markComplete() { + if s.fields == nil { + s.fields = make([]*Var, 0) + } +} + func (check *Checker) structType(styp *Struct, e *syntax.StructType) { if e.FieldList == nil { + styp.markComplete() return } @@ -160,6 +169,7 @@ func (check *Checker) structType(styp *Struct, e *syntax.StructType) { styp.fields = fields styp.tags = tags + styp.markComplete() } func embeddedFieldIdent(e syntax.Expr) *syntax.Name { diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 269b284ac4..a4e46b2097 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -91,7 +91,9 @@ func (subst *subster) typ(typ Type) Type { case *Struct: if fields, copied := subst.varList(t.fields); copied { - return &Struct{fields: fields, tags: t.tags} + s := &Struct{fields: fields, tags: t.tags} + s.markComplete() + return s } case *Pointer: diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49276.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49276.go new file mode 100644 index 0000000000..8839087b50 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49276.go @@ -0,0 +1,46 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +import "unsafe" + +type S /* ERROR illegal cycle in declaration of S */ struct { + _ [unsafe.Sizeof(s)]byte +} + +var s S + +// Since f is a pointer, this case could be valid. +// But it's pathological and not worth the expense. +type T struct { + f *[unsafe.Sizeof(T /* ERROR illegal cycle in type declaration */ {})]int +} + +// a mutually recursive case using unsafe.Sizeof +type ( + A1 struct { + _ [unsafe.Sizeof(B1{})]int + } + + B1 struct { + _ [unsafe.Sizeof(A1 /* ERROR illegal cycle in type declaration */ {})]int + } +) + +// a mutually recursive case using len +type ( + A2 struct { + f [len(B2{}.f)]int + } + + B2 struct { + f [len(A2 /* ERROR illegal cycle in type declaration */ {}.f)]int + } +) + +// test case from issue +type a struct { + _ [42 - unsafe.Sizeof(a /* ERROR illegal cycle in type declaration */ {})]byte +} -- GitLab From 85493d53e3bffbd08de3a97672a5a6f10b4901a8 Mon Sep 17 00:00:00 2001 From: Arran Walker Date: Thu, 21 Oct 2021 10:39:05 +0100 Subject: [PATCH 2038/2500] archive/zip: don't read data descriptor early Go 1.17 introduced an unnecessary change to when a zip's data descriptor is read for file entries, how it is parsed and how the crc32 field is used. Before Go 1.17, the data descriptor was read immediately after a file entry's content. This continuous read is a pattern existing applications have come to rely upon (for example, where reads at specific offsets might be translated to HTTP range requests). In Go 1.17, all data descriptors are immediately read upon opening the file. This results in scattered and non-continuous reads of the archive, and depending on the underlying reader, might have severe performance implications. In addition, an additional object is now initialized for each entry, but is mostly redundant. Previously, the crc32 field in the data descriptor would return an error if it did not match the central directory's entry. This check has seemingly been unintentionally removed. If the central directory crc32 is invalid and a data descriptor is present, no error is returned. This change reverts to the previous handling of data descriptors, before CL 312310. Fixes #48374 Fixes #49089 Change-Id: I5df2878c4fcc9e500064e7175f3ab9727c82f100 Reviewed-on: https://go-review.googlesource.com/c/go/+/357489 Run-TryBot: Ian Lance Taylor Reviewed-by: Ian Lance Taylor Trust: Dmitri Shuralyov --- src/archive/zip/reader.go | 94 ++++++++----------------- src/archive/zip/reader_test.go | 122 --------------------------------- src/archive/zip/struct.go | 8 --- 3 files changed, 27 insertions(+), 197 deletions(-) diff --git a/src/archive/zip/reader.go b/src/archive/zip/reader.go index e40a2c656b..2843a5d658 100644 --- a/src/archive/zip/reader.go +++ b/src/archive/zip/reader.go @@ -125,7 +125,6 @@ func (z *Reader) init(r io.ReaderAt, size int64) error { if err != nil { return err } - f.readDataDescriptor() z.File = append(z.File, f) } if uint16(len(z.File)) != uint16(end.directoryRecords) { // only compare 16 bits here @@ -186,10 +185,15 @@ func (f *File) Open() (io.ReadCloser, error) { return nil, ErrAlgorithm } var rc io.ReadCloser = dcomp(r) + var desr io.Reader + if f.hasDataDescriptor() { + desr = io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset+size, dataDescriptorLen) + } rc = &checksumReader{ rc: rc, hash: crc32.NewIEEE(), f: f, + desr: desr, } return rc, nil } @@ -205,49 +209,13 @@ func (f *File) OpenRaw() (io.Reader, error) { return r, nil } -func (f *File) readDataDescriptor() { - if !f.hasDataDescriptor() { - return - } - - bodyOffset, err := f.findBodyOffset() - if err != nil { - f.descErr = err - return - } - - // In section 4.3.9.2 of the spec: "However ZIP64 format MAY be used - // regardless of the size of a file. When extracting, if the zip64 - // extended information extra field is present for the file the - // compressed and uncompressed sizes will be 8 byte values." - // - // Historically, this package has used the compressed and uncompressed - // sizes from the central directory to determine if the package is - // zip64. - // - // For this case we allow either the extra field or sizes to determine - // the data descriptor length. - zip64 := f.zip64 || f.isZip64() - n := int64(dataDescriptorLen) - if zip64 { - n = dataDescriptor64Len - } - size := int64(f.CompressedSize64) - r := io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset+size, n) - dd, err := readDataDescriptor(r, zip64) - if err != nil { - f.descErr = err - return - } - f.CRC32 = dd.crc32 -} - type checksumReader struct { rc io.ReadCloser hash hash.Hash32 nread uint64 // number of bytes read so far f *File - err error // sticky error + desr io.Reader // if non-nil, where to read the data descriptor + err error // sticky error } func (r *checksumReader) Stat() (fs.FileInfo, error) { @@ -268,12 +236,12 @@ func (r *checksumReader) Read(b []byte) (n int, err error) { if r.nread != r.f.UncompressedSize64 { return 0, io.ErrUnexpectedEOF } - if r.f.hasDataDescriptor() { - if r.f.descErr != nil { - if r.f.descErr == io.EOF { + if r.desr != nil { + if err1 := readDataDescriptor(r.desr, r.f); err1 != nil { + if err1 == io.EOF { err = io.ErrUnexpectedEOF } else { - err = r.f.descErr + err = err1 } } else if r.hash.Sum32() != r.f.CRC32 { err = ErrChecksum @@ -485,10 +453,8 @@ parseExtras: return nil } -func readDataDescriptor(r io.Reader, zip64 bool) (*dataDescriptor, error) { - // Create enough space for the largest possible size - var buf [dataDescriptor64Len]byte - +func readDataDescriptor(r io.Reader, f *File) error { + var buf [dataDescriptorLen]byte // The spec says: "Although not originally assigned a // signature, the value 0x08074b50 has commonly been adopted // as a signature value for the data descriptor record. @@ -497,9 +463,10 @@ func readDataDescriptor(r io.Reader, zip64 bool) (*dataDescriptor, error) { // descriptors and should account for either case when reading // ZIP files to ensure compatibility." // - // First read just those 4 bytes to see if the signature exists. + // dataDescriptorLen includes the size of the signature but + // first read just those 4 bytes to see if it exists. if _, err := io.ReadFull(r, buf[:4]); err != nil { - return nil, err + return err } off := 0 maybeSig := readBuf(buf[:4]) @@ -508,28 +475,21 @@ func readDataDescriptor(r io.Reader, zip64 bool) (*dataDescriptor, error) { // bytes. off += 4 } - - end := dataDescriptorLen - 4 - if zip64 { - end = dataDescriptor64Len - 4 + if _, err := io.ReadFull(r, buf[off:12]); err != nil { + return err } - if _, err := io.ReadFull(r, buf[off:end]); err != nil { - return nil, err + b := readBuf(buf[:12]) + if b.uint32() != f.CRC32 { + return ErrChecksum } - b := readBuf(buf[:end]) - out := &dataDescriptor{ - crc32: b.uint32(), - } + // The two sizes that follow here can be either 32 bits or 64 bits + // but the spec is not very clear on this and different + // interpretations has been made causing incompatibilities. We + // already have the sizes from the central directory so we can + // just ignore these. - if zip64 { - out.compressedSize = b.uint64() - out.uncompressedSize = b.uint64() - } else { - out.compressedSize = uint64(b.uint32()) - out.uncompressedSize = uint64(b.uint32()) - } - return out, nil + return nil } func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, err error) { diff --git a/src/archive/zip/reader_test.go b/src/archive/zip/reader_test.go index a54915316c..d1a9bdd334 100644 --- a/src/archive/zip/reader_test.go +++ b/src/archive/zip/reader_test.go @@ -1214,128 +1214,6 @@ func TestCVE202127919(t *testing.T) { } } -func TestReadDataDescriptor(t *testing.T) { - tests := []struct { - desc string - in []byte - zip64 bool - want *dataDescriptor - wantErr error - }{{ - desc: "valid 32 bit with signature", - in: []byte{ - 0x50, 0x4b, 0x07, 0x08, // signature - 0x00, 0x01, 0x02, 0x03, // crc32 - 0x04, 0x05, 0x06, 0x07, // compressed size - 0x08, 0x09, 0x0a, 0x0b, // uncompressed size - }, - want: &dataDescriptor{ - crc32: 0x03020100, - compressedSize: 0x07060504, - uncompressedSize: 0x0b0a0908, - }, - }, { - desc: "valid 32 bit without signature", - in: []byte{ - 0x00, 0x01, 0x02, 0x03, // crc32 - 0x04, 0x05, 0x06, 0x07, // compressed size - 0x08, 0x09, 0x0a, 0x0b, // uncompressed size - }, - want: &dataDescriptor{ - crc32: 0x03020100, - compressedSize: 0x07060504, - uncompressedSize: 0x0b0a0908, - }, - }, { - desc: "valid 64 bit with signature", - in: []byte{ - 0x50, 0x4b, 0x07, 0x08, // signature - 0x00, 0x01, 0x02, 0x03, // crc32 - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // compressed size - 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, // uncompressed size - }, - zip64: true, - want: &dataDescriptor{ - crc32: 0x03020100, - compressedSize: 0x0b0a090807060504, - uncompressedSize: 0x131211100f0e0d0c, - }, - }, { - desc: "valid 64 bit without signature", - in: []byte{ - 0x00, 0x01, 0x02, 0x03, // crc32 - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // compressed size - 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, // uncompressed size - }, - zip64: true, - want: &dataDescriptor{ - crc32: 0x03020100, - compressedSize: 0x0b0a090807060504, - uncompressedSize: 0x131211100f0e0d0c, - }, - }, { - desc: "invalid 32 bit with signature", - in: []byte{ - 0x50, 0x4b, 0x07, 0x08, // signature - 0x00, 0x01, 0x02, 0x03, // crc32 - 0x04, 0x05, // unexpected end - }, - wantErr: io.ErrUnexpectedEOF, - }, { - desc: "invalid 32 bit without signature", - in: []byte{ - 0x00, 0x01, 0x02, 0x03, // crc32 - 0x04, 0x05, // unexpected end - }, - wantErr: io.ErrUnexpectedEOF, - }, { - desc: "invalid 64 bit with signature", - in: []byte{ - 0x50, 0x4b, 0x07, 0x08, // signature - 0x00, 0x01, 0x02, 0x03, // crc32 - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // compressed size - 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, // unexpected end - }, - zip64: true, - wantErr: io.ErrUnexpectedEOF, - }, { - desc: "invalid 64 bit without signature", - in: []byte{ - 0x00, 0x01, 0x02, 0x03, // crc32 - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // compressed size - 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, // unexpected end - }, - zip64: true, - wantErr: io.ErrUnexpectedEOF, - }} - - for _, test := range tests { - t.Run(test.desc, func(t *testing.T) { - r := bytes.NewReader(test.in) - - desc, err := readDataDescriptor(r, test.zip64) - if err != test.wantErr { - t.Fatalf("got err %v; want nil", err) - } - if test.want == nil { - return - } - if desc == nil { - t.Fatalf("got nil DataDescriptor; want non-nil") - } - if desc.crc32 != test.want.crc32 { - t.Errorf("got CRC32 %#x; want %#x", desc.crc32, test.want.crc32) - } - if desc.compressedSize != test.want.compressedSize { - t.Errorf("got CompressedSize %#x; want %#x", desc.compressedSize, test.want.compressedSize) - } - if desc.uncompressedSize != test.want.uncompressedSize { - t.Errorf("got UncompressedSize %#x; want %#x", desc.uncompressedSize, test.want.uncompressedSize) - } - }) - } -} - func TestCVE202133196(t *testing.T) { // Archive that indicates it has 1 << 128 -1 files, // this would previously cause a panic due to attempting diff --git a/src/archive/zip/struct.go b/src/archive/zip/struct.go index ff9f605eb6..88effedc0f 100644 --- a/src/archive/zip/struct.go +++ b/src/archive/zip/struct.go @@ -390,11 +390,3 @@ func unixModeToFileMode(m uint32) fs.FileMode { } return mode } - -// dataDescriptor holds the data descriptor that optionally follows the file -// contents in the zip file. -type dataDescriptor struct { - crc32 uint32 - compressedSize uint64 - uncompressedSize uint64 -} -- GitLab From 9e6ad46bccfa7a63e768236bcd1fd54dab38e4d1 Mon Sep 17 00:00:00 2001 From: jiahua wang Date: Fri, 8 Oct 2021 09:59:15 +0800 Subject: [PATCH 2039/2500] net/http: fix spelling in documentation Change-Id: I8b0924300eafe27de98975512a78a6527a92e446 Reviewed-on: https://go-review.googlesource.com/c/go/+/354729 Reviewed-by: Ian Lance Taylor Trust: Damien Neil --- src/net/http/httputil/dump.go | 2 +- src/net/http/serve_test.go | 2 +- src/net/http/transfer.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/net/http/httputil/dump.go b/src/net/http/httputil/dump.go index 2948f27e5d..d7baecd9c1 100644 --- a/src/net/http/httputil/dump.go +++ b/src/net/http/httputil/dump.go @@ -292,7 +292,7 @@ func DumpRequest(req *http.Request, body bool) ([]byte, error) { // can detect that the lack of body was intentional. var errNoBody = errors.New("sentinel error value") -// failureToReadBody is a io.ReadCloser that just returns errNoBody on +// failureToReadBody is an io.ReadCloser that just returns errNoBody on // Read. It's swapped in when we don't actually want to consume // the body, but need a non-nil one, and want to distinguish the // error from reading the dummy body. diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index e8fb77446c..27dff2bf45 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -6557,7 +6557,7 @@ func TestDisableKeepAliveUpgrade(t *testing.T) { rwc, ok := resp.Body.(io.ReadWriteCloser) if !ok { - t.Fatalf("Response.Body is not a io.ReadWriteCloser: %T", resp.Body) + t.Fatalf("Response.Body is not an io.ReadWriteCloser: %T", resp.Body) } _, err = rwc.Write([]byte("hello")) diff --git a/src/net/http/transfer.go b/src/net/http/transfer.go index 5ff89cc17f..2be1c9fa3c 100644 --- a/src/net/http/transfer.go +++ b/src/net/http/transfer.go @@ -1030,7 +1030,7 @@ func (b *body) registerOnHitEOF(fn func()) { b.onHitEOF = fn } -// bodyLocked is a io.Reader reading from a *body when its mutex is +// bodyLocked is an io.Reader reading from a *body when its mutex is // already held. type bodyLocked struct { b *body -- GitLab From ab31dbc05b725135ca5f6fd4337a041d8433f153 Mon Sep 17 00:00:00 2001 From: smasher164 Date: Sat, 6 Nov 2021 02:59:00 -0400 Subject: [PATCH 2040/2500] doc/go1.18: strings,bytes: deprecate Title Updates #48367. Change-Id: Ib8fc6d9dd7c3c6a70fefe077615f51a71d9c42ed Reviewed-on: https://go-review.googlesource.com/c/go/+/361899 Reviewed-by: Ian Lance Taylor Trust: Dmitri Shuralyov --- doc/go1.18.html | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/doc/go1.18.html b/doc/go1.18.html index b86e907874..44c56444fc 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -214,6 +214,12 @@ Do not send CLs removing the interior tags from such phrases.

TODO: https://golang.org/cl/332771: avoid allocations in Trim/TrimLeft/TrimRight

+ +

+ The Title function is now deprecated. It doesn't + handle Unicode punctuation and language-specific capitalization rules, and is superseded by the + golang.org/x/text/cases package. +

@@ -342,6 +348,12 @@ Do not send CLs removing the interior tags from such phrases.

TODO: https://golang.org/cl/332771: avoid allocations in Trim/TrimLeft/TrimRight

+ +

+ The Title function is now deprecated. It doesn't + handle Unicode punctuation and language-specific capitalization rules, and is superseded by the + golang.org/x/text/cases package. +

-- GitLab From 3e41b18a46ea0cf033be4d9baa2d99f7c8c985dc Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 4 Nov 2021 20:00:51 -0700 Subject: [PATCH 2041/2500] cmd/compile/internal/types2: use compiler version error when configured for compiler Fixes #49368. Change-Id: I7c7575ae8bb6271160747e3f1888b144c3ab24c4 Reviewed-on: https://go-review.googlesource.com/c/go/+/361411 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/builtins.go | 4 ++-- src/cmd/compile/internal/types2/call.go | 6 +++--- src/cmd/compile/internal/types2/conversions.go | 7 +++---- src/cmd/compile/internal/types2/decl.go | 8 ++------ src/cmd/compile/internal/types2/errors.go | 10 ++++++++++ src/cmd/compile/internal/types2/expr.go | 2 +- src/cmd/compile/internal/types2/typeset.go | 6 +++--- src/cmd/compile/internal/types2/typexpr.go | 2 +- src/cmd/compile/internal/types2/version.go | 8 ++++---- src/cmd/go/testdata/script/mod_edit_go.txt | 4 ++-- test/fixedbugs/issue49368.go | 11 +++++++++++ 11 files changed, 42 insertions(+), 26 deletions(-) create mode 100644 test/fixedbugs/issue49368.go diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 548d55e10c..ade4c0a49f 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -574,7 +574,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( case _Add: // unsafe.Add(ptr unsafe.Pointer, len IntegerType) unsafe.Pointer if !check.allowVersion(check.pkg, 1, 17) { - check.error(call.Fun, "unsafe.Add requires go1.17 or later") + check.versionErrorf(call.Fun, "go1.17", "unsafe.Add") return } @@ -700,7 +700,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( case _Slice: // unsafe.Slice(ptr *T, len IntegerType) []T if !check.allowVersion(check.pkg, 1, 17) { - check.error(call.Fun, "unsafe.Slice requires go1.17 or later") + check.versionErrorf(call.Fun, "go1.17", "unsafe.Slice") return } diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 49cae5a930..74edd4d442 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -16,7 +16,7 @@ import ( // The operand x must be the evaluation of inst.X and its type must be a signature. func (check *Checker) funcInst(x *operand, inst *syntax.IndexExpr) { if !check.allowVersion(check.pkg, 1, 18) { - check.softErrorf(inst.Pos(), "function instantiation requires go1.18 or later") + check.versionErrorf(inst.Pos(), "go1.18", "function instantiation") } xlist := unpackExpr(inst.Index) @@ -363,9 +363,9 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T if sig.TypeParams().Len() > 0 { if !check.allowVersion(check.pkg, 1, 18) { if iexpr, _ := call.Fun.(*syntax.IndexExpr); iexpr != nil { - check.softErrorf(iexpr.Pos(), "function instantiation requires go1.18 or later") + check.versionErrorf(iexpr.Pos(), "go1.18", "function instantiation") } else { - check.softErrorf(call.Pos(), "implicit function instantiation requires go1.18 or later") + check.versionErrorf(call.Pos(), "go1.18", "implicit function instantiation") } } // TODO(gri) provide position information for targs so we can feed diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go index 44e8aad84f..ccabbaf0d7 100644 --- a/src/cmd/compile/internal/types2/conversions.go +++ b/src/cmd/compile/internal/types2/conversions.go @@ -7,6 +7,7 @@ package types2 import ( + "fmt" "go/constant" "unicode" ) @@ -181,11 +182,9 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { } // check != nil if cause != nil { + *cause = "conversion of slices to array pointers requires go1.17 or later" if check.conf.CompilerErrorMessages { - // compiler error message assumes a -lang flag - *cause = "conversion of slices to array pointers only supported as of -lang=go1.17" - } else { - *cause = "conversion of slices to array pointers requires go1.17 or later" + *cause += fmt.Sprintf(" (-lang was set to %s; check go.mod)", check.conf.GoVersion) } } return false diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 5d2a6c531b..5219f7e7c5 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -555,7 +555,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named check.validType(obj.typ, nil) // If typ is local, an error was already reported where typ is specified/defined. if check.isImportedConstraint(rhs) && !check.allowVersion(check.pkg, 1, 18) { - check.errorf(tdecl.Type.Pos(), "using type constraint %s requires go1.18 or later", rhs) + check.versionErrorf(tdecl.Type.Pos(), "go1.18", "using type constraint %s", rhs) } }).describef(obj, "validType(%s)", obj.Name()) @@ -570,11 +570,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named // alias declaration if alias { if !check.allowVersion(check.pkg, 1, 9) { - if check.conf.CompilerErrorMessages { - check.error(tdecl, "type aliases only supported as of -lang=go1.9") - } else { - check.error(tdecl, "type aliases requires go1.9 or later") - } + check.versionErrorf(tdecl, "go1.9", "type aliases") } obj.typ = Typ[Invalid] diff --git a/src/cmd/compile/internal/types2/errors.go b/src/cmd/compile/internal/types2/errors.go index b56d11a28b..c39652fe5e 100644 --- a/src/cmd/compile/internal/types2/errors.go +++ b/src/cmd/compile/internal/types2/errors.go @@ -230,6 +230,16 @@ func (check *Checker) softErrorf(at poser, format string, args ...interface{}) { check.err(at, check.sprintf(format, args...), true) } +func (check *Checker) versionErrorf(at poser, goVersion string, format string, args ...interface{}) { + msg := check.sprintf(format, args...) + if check.conf.CompilerErrorMessages { + msg = fmt.Sprintf("%s requires %s or later (-lang was set to %s; check go.mod)", msg, goVersion, check.conf.GoVersion) + } else { + msg = fmt.Sprintf("%s requires %s or later", msg, goVersion) + } + check.err(at, msg, true) +} + // posFor reports the left (= start) position of at. func posFor(at poser) syntax.Pos { switch x := at.(type) { diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index d618ebd372..d24532d780 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -869,7 +869,7 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) { x.mode = invalid return } else if !allUnsigned(y.typ) && !check.allowVersion(check.pkg, 1, 13) { - check.errorf(y, invalidOp+"signed shift count %s requires go1.13 or later", y) + check.versionErrorf(y, "go1.13", invalidOp+"signed shift count %s", y) x.mode = invalid return } diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index 445a62f9e0..c37a20e73e 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -271,7 +271,7 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_ tset := computeInterfaceTypeSet(check, pos, u) // If typ is local, an error was already reported where typ is specified/defined. if check != nil && check.isImportedConstraint(typ) && !check.allowVersion(check.pkg, 1, 18) { - check.errorf(pos, "embedding constraint interface %s requires go1.18 or later", typ) + check.versionErrorf(pos, "go1.18", "embedding constraint interface %s", typ) continue } if tset.comparable { @@ -283,7 +283,7 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_ terms = tset.terms case *Union: if check != nil && !check.allowVersion(check.pkg, 1, 18) { - check.errorf(pos, "embedding interface element %s requires go1.18 or later", u) + check.versionErrorf(pos, "go1.18", "embedding interface element %s", u) continue } tset := computeUnionTypeSet(check, pos, u) @@ -300,7 +300,7 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_ continue } if check != nil && !check.allowVersion(check.pkg, 1, 18) { - check.errorf(pos, "embedding non-interface type %s requires go1.18 or later", typ) + check.versionErrorf(pos, "go1.18", "embedding non-interface type %s", typ) continue } terms = termlist{{false, typ}} diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 95893fd1e1..dcd7cfebe8 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -264,7 +264,7 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) { case *syntax.IndexExpr: if !check.allowVersion(check.pkg, 1, 18) { - check.softErrorf(e.Pos(), "type instantiation requires go1.18 or later") + check.versionErrorf(e.Pos(), "go1.18", "type instantiation") } return check.instantiatedType(e.X, unpackExpr(e.Index), def) diff --git a/src/cmd/compile/internal/types2/version.go b/src/cmd/compile/internal/types2/version.go index d9d18b6f7a..b649f09c3a 100644 --- a/src/cmd/compile/internal/types2/version.go +++ b/src/cmd/compile/internal/types2/version.go @@ -21,7 +21,7 @@ func (check *Checker) langCompat(lit *syntax.BasicLit) { } // len(s) > 2 if strings.Contains(s, "_") { - check.error(lit, "underscores in numeric literals requires go1.13 or later") + check.versionErrorf(lit, "go1.13", "underscores in numeric literals") return } if s[0] != '0' { @@ -29,15 +29,15 @@ func (check *Checker) langCompat(lit *syntax.BasicLit) { } radix := s[1] if radix == 'b' || radix == 'B' { - check.error(lit, "binary literals requires go1.13 or later") + check.versionErrorf(lit, "go1.13", "binary literals") return } if radix == 'o' || radix == 'O' { - check.error(lit, "0o/0O-style octal literals requires go1.13 or later") + check.versionErrorf(lit, "go1.13", "0o/0O-style octal literals") return } if lit.Kind != syntax.IntLit && (radix == 'x' || radix == 'X') { - check.error(lit, "hexadecimal floating-point literals requires go1.13 or later") + check.versionErrorf(lit, "go1.13", "hexadecimal floating-point literals") } } diff --git a/src/cmd/go/testdata/script/mod_edit_go.txt b/src/cmd/go/testdata/script/mod_edit_go.txt index 38321d071f..7e9740fec4 100644 --- a/src/cmd/go/testdata/script/mod_edit_go.txt +++ b/src/cmd/go/testdata/script/mod_edit_go.txt @@ -2,7 +2,7 @@ env GO111MODULE=on ! go build -stderr 'type aliases only supported as of' +stderr ' type aliases requires' go mod edit -go=1.9 grep 'go 1.9' go.mod go build @@ -11,7 +11,7 @@ go build # the cached 1.9 build. (https://golang.org/issue/37804) go mod edit -go=1.8 ! go build -stderr 'type aliases only supported as of' +stderr 'type aliases requires' -- go.mod -- diff --git a/test/fixedbugs/issue49368.go b/test/fixedbugs/issue49368.go new file mode 100644 index 0000000000..2339048e3d --- /dev/null +++ b/test/fixedbugs/issue49368.go @@ -0,0 +1,11 @@ +// errorcheck -lang=go1.17 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type _ interface { + int // ERROR "embedding non-interface type int requires go1\.18 or later \(-lang was set to go1\.17; check go.mod\)" +} -- GitLab From 759eaa22adb0ab883959e4a36c19f2dfe77b5895 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sun, 7 Nov 2021 20:08:13 -0800 Subject: [PATCH 2042/2500] cmd/compile/internal/types2: remove most asX converters (cleanup) Make it explicit in the code where we call under. The asNamed and asTypeParam converters need to stay: asNamed does resolution if necessary, and asTypeParam may or may not call under() depending on the next CL. Reviewed uses of asNamed and .(*Named) for correctness. Removed unnecessary Named.resolve call in lookup. Change-Id: I2acf176925e00bd1703a00230a779aa65a8f5a51 Reviewed-on: https://go-review.googlesource.com/c/go/+/362254 Trust: Robert Griesemer Reviewed-by: Robert Findley --- .../compile/internal/types2/assignments.go | 2 +- src/cmd/compile/internal/types2/builtins.go | 8 ++-- src/cmd/compile/internal/types2/call.go | 2 +- src/cmd/compile/internal/types2/context.go | 2 +- .../compile/internal/types2/conversions.go | 21 +++++----- src/cmd/compile/internal/types2/expr.go | 6 +-- src/cmd/compile/internal/types2/index.go | 8 ++-- src/cmd/compile/internal/types2/lookup.go | 9 ++--- src/cmd/compile/internal/types2/predicates.go | 5 ++- src/cmd/compile/internal/types2/sizes.go | 2 +- src/cmd/compile/internal/types2/type.go | 39 +------------------ src/cmd/compile/internal/types2/typestring.go | 2 +- src/cmd/compile/internal/types2/typexpr.go | 2 +- 13 files changed, 36 insertions(+), 72 deletions(-) diff --git a/src/cmd/compile/internal/types2/assignments.go b/src/cmd/compile/internal/types2/assignments.go index bfc5578683..609d7d0962 100644 --- a/src/cmd/compile/internal/types2/assignments.go +++ b/src/cmd/compile/internal/types2/assignments.go @@ -71,7 +71,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { // x.typ is typed // A generic (non-instantiated) function value cannot be assigned to a variable. - if sig := asSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { + if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 { check.errorf(x, "cannot use generic function %s without instantiation in %s", x, context) } diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index ade4c0a49f..916aed40b3 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -294,7 +294,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( // (applyTypeFunc never calls f with a type parameter) f := func(typ Type) Type { assert(asTypeParam(typ) == nil) - if t := asBasic(typ); t != nil { + if t, _ := under(typ).(*Basic); t != nil { switch t.kind { case Float32: return Typ[Complex64] @@ -418,7 +418,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( // (applyTypeFunc never calls f with a type parameter) f := func(typ Type) Type { assert(asTypeParam(typ) == nil) - if t := asBasic(typ); t != nil { + if t, _ := under(typ).(*Basic); t != nil { switch t.kind { case Complex64: return Typ[Float32] @@ -704,7 +704,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( return } - typ := asPointer(x.typ) + typ, _ := under(x.typ).(*Pointer) if typ == nil { check.errorf(x, invalidArg+"%s is not a pointer", x) return @@ -894,7 +894,7 @@ func makeSig(res Type, args ...Type) *Signature { // otherwise it returns typ. func arrayPtrDeref(typ Type) Type { if p, ok := typ.(*Pointer); ok { - if a := asArray(p.base); a != nil { + if a, _ := under(p.base).(*Array); a != nil { return a } } diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 74edd4d442..3a571285c1 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -132,7 +132,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { case 1: check.expr(x, call.ArgList[0]) if x.mode != invalid { - if t := asInterface(T); t != nil { + if t, _ := under(T).(*Interface); t != nil { if !t.IsMethodSet() { check.errorf(call, "cannot use interface %s in conversion (contains specific type constraints or is comparable)", T) break diff --git a/src/cmd/compile/internal/types2/context.go b/src/cmd/compile/internal/types2/context.go index a8f8591243..63303ca422 100644 --- a/src/cmd/compile/internal/types2/context.go +++ b/src/cmd/compile/internal/types2/context.go @@ -39,7 +39,7 @@ func (ctxt *Context) TypeHash(typ Type, targs []Type) string { var buf bytes.Buffer h := newTypeHasher(&buf, ctxt) - if named, _ := typ.(*Named); named != nil && len(targs) > 0 { + if named := asNamed(typ); named != nil && len(targs) > 0 { // Don't use WriteType because we need to use the provided targs // and not any targs that might already be with the *Named type. h.typePrefix(named) diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go index ccabbaf0d7..dd89f29762 100644 --- a/src/cmd/compile/internal/types2/conversions.go +++ b/src/cmd/compile/internal/types2/conversions.go @@ -18,7 +18,7 @@ func (check *Checker) conversion(x *operand, T Type) { constArg := x.mode == constant_ constConvertibleTo := func(T Type, val *constant.Value) bool { - switch t := asBasic(T); { + switch t, _ := under(T).(*Basic); { case t == nil: // nothing to do case representableConst(x.val, check, t, val): @@ -173,9 +173,9 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { // "V a slice, T is a pointer-to-array type, // and the slice and array types have identical element types." - if s := asSlice(V); s != nil { - if p := asPointer(T); p != nil { - if a := asArray(p.Elem()); a != nil { + if s, _ := under(V).(*Slice); s != nil { + if p, _ := under(T).(*Pointer); p != nil { + if a, _ := under(p.Elem()).(*Array); a != nil { if Identical(s.Elem(), a.Elem()) { if check == nil || check.allowVersion(check.pkg, 1, 17) { return true @@ -262,26 +262,27 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { // use the toT convenience converters in the predicates below. func isUintptr(typ Type) bool { - t := asBasic(typ) + t, _ := under(typ).(*Basic) return t != nil && t.kind == Uintptr } func isUnsafePointer(typ Type) bool { - // TODO(gri): Is this asBasic(typ) instead of typ.(*Basic) correct? + // TODO(gri): Is this under(typ).(*Basic) instead of typ.(*Basic) correct? // (The former calls under(), while the latter doesn't.) // The spec does not say so, but gc claims it is. See also // issue 6326. - t := asBasic(typ) + t, _ := under(typ).(*Basic) return t != nil && t.kind == UnsafePointer } func isPointer(typ Type) bool { - return asPointer(typ) != nil + _, ok := under(typ).(*Pointer) + return ok } func isBytesOrRunes(typ Type) bool { - if s := asSlice(typ); s != nil { - t := asBasic(s.elem) + if s, _ := under(typ).(*Slice); s != nil { + t, _ := under(s.elem).(*Basic) return t != nil && (t.kind == Byte || t.kind == Rune) } return false diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index d24532d780..8125fba717 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -116,7 +116,7 @@ func (check *Checker) overflow(x *operand) { // x.typ cannot be a type parameter (type // parameters cannot be constant types). if isTyped(x.typ) { - check.representable(x, asBasic(x.typ)) + check.representable(x, under(x.typ).(*Basic)) return } @@ -617,7 +617,7 @@ func (check *Checker) updateExprType(x syntax.Expr, typ Type, final bool) { // If the new type is not final and still untyped, just // update the recorded type. if !final && isUntyped(typ) { - old.typ = asBasic(typ) + old.typ = under(typ).(*Basic) check.untyped[x] = old return } @@ -1394,7 +1394,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin duplicate := false // if the key is of interface type, the type is also significant when checking for duplicates xkey := keyVal(x.val) - if asInterface(utyp.key) != nil { + if IsInterface(utyp.key) { for _, vtyp := range visited[xkey] { if Identical(vtyp, x.typ) { duplicate = true diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index 67110704e9..f096674536 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -34,7 +34,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo return false case value: - if sig := asSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { + if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 { // function instantiation return true } @@ -72,7 +72,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo x.typ = typ.elem case *Pointer: - if typ := asArray(typ.base); typ != nil { + if typ, _ := under(typ.base).(*Array); typ != nil { valid = true length = typ.len x.mode = variable @@ -120,7 +120,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo mode = value } case *Pointer: - if t := asArray(t.base); t != nil { + if t, _ := under(t.base).(*Array); t != nil { l = t.len e = t.elem } @@ -245,7 +245,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { x.typ = &Slice{elem: u.elem} case *Pointer: - if u := asArray(u.base); u != nil { + if u, _ := under(u.base).(*Array); u != nil { valid = true length = u.len x.typ = &Slice{elem: u.elem} diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index e0fd74482a..0612400590 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -122,7 +122,6 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o seen[named] = true // look for a matching attached method - named.resolve(nil) if i, m := lookupMethod(named.methods, pkg, name); m != nil { // potential match // caution: method may not have a proper signature yet @@ -306,7 +305,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, return } - if ityp := asInterface(V); ityp != nil { + if ityp, _ := under(V).(*Interface); ityp != nil { // TODO(gri) the methods are sorted - could do this more efficiently for _, m := range T.typeSet().methods { _, f := ityp.typeSet().LookupMethod(m.pkg, m.name) @@ -417,7 +416,7 @@ func (check *Checker) assertableTo(V *Interface, T Type) (method, wrongType *Fun // no static check is required if T is an interface // spec: "If T is an interface type, x.(T) asserts that the // dynamic type of x implements the interface T." - if asInterface(T) != nil && !forceStrict { + if IsInterface(T) && !forceStrict { return } return check.missingMethod(T, V, false) @@ -435,8 +434,8 @@ func deref(typ Type) (Type, bool) { // derefStructPtr dereferences typ if it is a (named or unnamed) pointer to a // (named or unnamed) struct and returns its base. Otherwise it returns typ. func derefStructPtr(typ Type) Type { - if p := asPointer(typ); p != nil { - if asStruct(p.base) != nil { + if p, _ := under(typ).(*Pointer); p != nil { + if _, ok := under(p.base).(*Struct); ok { return p.base } } diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 7fbb91eb61..8d676ed8f6 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -72,7 +72,7 @@ func hasName(t Type) bool { // are not fully set up. func isTyped(t Type) bool { // isTyped is called with types that are not fully - // set up. Must not call asBasic()! + // set up. Must not call under()! b, _ := t.(*Basic) return b == nil || b.info&IsUntyped == 0 } @@ -84,7 +84,8 @@ func isUntyped(t Type) bool { // IsInterface reports whether t is an interface type. func IsInterface(t Type) bool { - return asInterface(t) != nil + _, ok := under(t).(*Interface) + return ok } // isTypeParam reports whether t is a type parameter. diff --git a/src/cmd/compile/internal/types2/sizes.go b/src/cmd/compile/internal/types2/sizes.go index 6a3d19d8ea..609b6f585e 100644 --- a/src/cmd/compile/internal/types2/sizes.go +++ b/src/cmd/compile/internal/types2/sizes.go @@ -243,7 +243,7 @@ func (conf *Config) offsetsof(T *Struct) []int64 { func (conf *Config) offsetof(typ Type, index []int) int64 { var o int64 for _, i := range index { - s := asStruct(typ) + s := under(typ).(*Struct) o += conf.offsetsof(s)[i] typ = s.fields[i].typ } diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 300c81f5fa..d1655c55f8 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -27,45 +27,8 @@ func under(t Type) Type { return t } -// Convenience converters - -func asBasic(t Type) *Basic { - u, _ := under(t).(*Basic) - return u -} - -func asArray(t Type) *Array { - u, _ := under(t).(*Array) - return u -} - -func asSlice(t Type) *Slice { - u, _ := under(t).(*Slice) - return u -} - -func asStruct(t Type) *Struct { - u, _ := under(t).(*Struct) - return u -} - -func asPointer(t Type) *Pointer { - u, _ := under(t).(*Pointer) - return u -} - -func asSignature(t Type) *Signature { - u, _ := under(t).(*Signature) - return u -} - -func asInterface(t Type) *Interface { - u, _ := under(t).(*Interface) - return u -} - // If the argument to asNamed, or asTypeParam is of the respective type -// (possibly after expanding resolving a *Named type), these methods return that type. +// (possibly after resolving a *Named type), these methods return that type. // Otherwise the result is nil. func asNamed(t Type) *Named { diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index f18a32016f..f151f47a5e 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -361,7 +361,7 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) { } else { // special case: // append(s, "foo"...) leads to signature func([]byte, string...) - if t := asBasic(typ); t == nil || t.kind != String { + if t, _ := under(typ).(*Basic); t == nil || t.kind != String { w.error("expected string type") continue } diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index dcd7cfebe8..a08e472703 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -148,7 +148,7 @@ func (check *Checker) varType(e syntax.Expr) Type { // are in the middle of type-checking parameter declarations that might belong to // interface methods. Delay this check to the end of type-checking. check.later(func() { - if t := asInterface(typ); t != nil { + if t, _ := under(typ).(*Interface); t != nil { pos := syntax.StartPos(e) tset := computeInterfaceTypeSet(check, pos, t) // TODO(gri) is this the correct position? if !tset.IsMethodSet() { -- GitLab From 7ee3f1427b079bb363689321b0565ba7b03de03e Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Fri, 5 Nov 2021 23:35:58 +0000 Subject: [PATCH 2043/2500] runtime: disable GC during debug call tests Currently the debug call protocol implementation we use for testing is riddled with write barriers, and called from a signal handler. This is not safe, as write barriers need a P to execute. Ideally this implementation would be rewritten to avoid the write barriers, but it's not straightforward, and needs some thought. As a temporary measure, disable GC during the debug call tests to avoid a write barrier. Note that this does not indicate a problem with real use of the debug call protocol. Only our test implementation has this issue, because it needs to get executed in a signal handler, normally a separate process is interfacing with the protocol via process signals and ptrace (and the like). Fixes #49370. Change-Id: Ic0fde5d0f4c64f9ecc9789b7dabb3954538fe0a8 Reviewed-on: https://go-review.googlesource.com/c/go/+/361896 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Michael Pratt --- src/runtime/debug_test.go | 42 ++++++++++++++++++++++++++++++++ src/runtime/export_debug_test.go | 10 +++++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/runtime/debug_test.go b/src/runtime/debug_test.go index b5db7a55f1..89ea577d64 100644 --- a/src/runtime/debug_test.go +++ b/src/runtime/debug_test.go @@ -114,6 +114,13 @@ func skipUnderDebugger(t *testing.T) { } func TestDebugCall(t *testing.T) { + // InjectDebugCall cannot be executed while a GC is actively in + // progress. Wait until the current GC is done, and turn it off. + // + // See #49370. + runtime.GC() + defer debug.SetGCPercent(debug.SetGCPercent(-1)) + g, after := startDebugCallWorker(t) defer after() @@ -143,6 +150,7 @@ func TestDebugCall(t *testing.T) { x1: 42.0, } } + if _, err := runtime.InjectDebugCall(g, fn, ®s, args, debugCallTKill, false); err != nil { t.Fatal(err) } @@ -164,6 +172,13 @@ func TestDebugCall(t *testing.T) { } func TestDebugCallLarge(t *testing.T) { + // InjectDebugCall cannot be executed while a GC is actively in + // progress. Wait until the current GC is done, and turn it off. + // + // See #49370. + runtime.GC() + defer debug.SetGCPercent(debug.SetGCPercent(-1)) + g, after := startDebugCallWorker(t) defer after() @@ -193,6 +208,13 @@ func TestDebugCallLarge(t *testing.T) { } func TestDebugCallGC(t *testing.T) { + // InjectDebugCall cannot be executed while a GC is actively in + // progress. Wait until the current GC is done, and turn it off. + // + // See #49370. + runtime.GC() + defer debug.SetGCPercent(debug.SetGCPercent(-1)) + g, after := startDebugCallWorker(t) defer after() @@ -203,6 +225,13 @@ func TestDebugCallGC(t *testing.T) { } func TestDebugCallGrowStack(t *testing.T) { + // InjectDebugCall cannot be executed while a GC is actively in + // progress. Wait until the current GC is done, and turn it off. + // + // See #49370. + runtime.GC() + defer debug.SetGCPercent(debug.SetGCPercent(-1)) + g, after := startDebugCallWorker(t) defer after() @@ -233,6 +262,12 @@ func TestDebugCallUnsafePoint(t *testing.T) { // This can deadlock if there aren't enough threads or if a GC // tries to interrupt an atomic loop (see issue #10958). defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(8)) + + // InjectDebugCall cannot be executed while a GC is actively in + // progress. Wait until the current GC is done, and turn it off. + // + // See #49370. + runtime.GC() defer debug.SetGCPercent(debug.SetGCPercent(-1)) // Test that the runtime refuses call injection at unsafe points. @@ -256,6 +291,13 @@ func TestDebugCallPanic(t *testing.T) { // This can deadlock if there aren't enough threads. defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(8)) + // InjectDebugCall cannot be executed while a GC is actively in + // progress. Wait until the current GC is done, and turn it off. + // + // See #49370. + runtime.GC() + defer debug.SetGCPercent(debug.SetGCPercent(-1)) + ready := make(chan *runtime.G) var stop uint32 defer atomic.StoreUint32(&stop, 1) diff --git a/src/runtime/export_debug_test.go b/src/runtime/export_debug_test.go index 032a9b9725..fffc99d7e5 100644 --- a/src/runtime/export_debug_test.go +++ b/src/runtime/export_debug_test.go @@ -107,6 +107,10 @@ type debugCallHandler struct { } func (h *debugCallHandler) inject(info *siginfo, ctxt *sigctxt, gp2 *g) bool { + // TODO(49370): This code is riddled with write barriers, but called from + // a signal handler. Add the go:nowritebarrierrec annotation and restructure + // this to avoid write barriers. + switch h.gp.atomicstatus { case _Grunning: if getg().m != h.mp { @@ -141,7 +145,11 @@ func (h *debugCallHandler) inject(info *siginfo, ctxt *sigctxt, gp2 *g) bool { } func (h *debugCallHandler) handle(info *siginfo, ctxt *sigctxt, gp2 *g) bool { - // Sanity check. + // TODO(49370): This code is riddled with write barriers, but called from + // a signal handler. Add the go:nowritebarrierrec annotation and restructure + // this to avoid write barriers. + + // Double-check m. if getg().m != h.mp { println("trap on wrong M", getg().m, h.mp) return false -- GitLab From 7bda349c1735fb6043b22d7a0e4542134baa6518 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Fri, 5 Nov 2021 23:47:51 +0000 Subject: [PATCH 2044/2500] runtime: disable GC in TestPanicSystemstack's subprocess TestPanicSystemstack spins up a subprocess that has 2 goroutines deadlock on a runtime lock while on the system stack, with GOMAXPROCS=2. Each goroutine is going to be running on a P, and then is going to wedge itself up on that P. If a GC is active and a worker starts executing (using a P), then it could try to preempt a goroutine that is already blocked. It won't be able to, so it'll just sit there forever trying to suspend it. At this point there are no more Ps to execute the remaining goroutine that needs to print something so the parent process can continue the test. This change fixes this issue by disabling GCs in the child process. An alternative fix could be to increase GOMAXPROCS in the child, but maybe letting the GC be on (which assumes it'll always be able to *eventually* suspend a G) is just asking for trouble. Fixes #49388. Change-Id: I405c9dad50e24e1e68f2c52a646538da15797fbe Reviewed-on: https://go-review.googlesource.com/c/go/+/361897 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Michael Pratt --- src/runtime/crash_unix_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/runtime/crash_unix_test.go b/src/runtime/crash_unix_test.go index 0d9d22aa49..0930a1b365 100644 --- a/src/runtime/crash_unix_test.go +++ b/src/runtime/crash_unix_test.go @@ -13,6 +13,7 @@ import ( "os" "os/exec" "runtime" + "runtime/debug" "strings" "sync" "syscall" @@ -211,6 +212,11 @@ func TestPanicSystemstack(t *testing.T) { func init() { if len(os.Args) >= 2 && os.Args[1] == "testPanicSystemstackInternal" { + // Complete any in-flight GCs and disable future ones. We're going to + // block goroutines on runtime locks, which aren't ever preemptible for the + // GC to scan them. + runtime.GC() + debug.SetGCPercent(-1) // Get two threads running on the system stack with // something recognizable in the stack trace. runtime.GOMAXPROCS(2) -- GitLab From 6a9d81174e6c7d205fc189a1eac56212a723c40c Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Sun, 7 Nov 2021 21:29:30 -0800 Subject: [PATCH 2045/2500] internal/fmtsort: order channels in test in memory address order Kind of a kludge, but it makes the test work reliably. Fixes #49431 Change-Id: Ic2a075ba02f80ea7efcc1b3f0f5a43649e87c0d8 Reviewed-on: https://go-review.googlesource.com/c/go/+/361918 Trust: Keith Randall Run-TryBot: Keith Randall Reviewed-by: Bryan C. Mills Reviewed-by: Cuong Manh Le --- src/internal/fmtsort/sort_test.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/internal/fmtsort/sort_test.go b/src/internal/fmtsort/sort_test.go index 5c4db1c5fa..ab063af5ba 100644 --- a/src/internal/fmtsort/sort_test.go +++ b/src/internal/fmtsort/sort_test.go @@ -9,6 +9,7 @@ import ( "internal/fmtsort" "math" "reflect" + "sort" "strings" "testing" "unsafe" @@ -188,9 +189,19 @@ func sprintKey(key reflect.Value) string { var ( ints [3]int - chans = [3]chan int{make(chan int), make(chan int), make(chan int)} + chans = makeChans() ) +func makeChans() []chan int { + cs := []chan int{make(chan int), make(chan int), make(chan int)} + // Order channels by address. See issue #49431. + // TODO: pin these pointers once pinning is available (#46787). + sort.Slice(cs, func(i, j int) bool { + return uintptr(reflect.ValueOf(cs[i]).UnsafePointer()) < uintptr(reflect.ValueOf(cs[j]).UnsafePointer()) + }) + return cs +} + func pointerMap() map[*int]string { m := make(map[*int]string) for i := 2; i >= 0; i-- { -- GitLab From 2e210b41ea5ca2fd3dcac5bc24ea932c2cac1234 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Mon, 8 Nov 2021 08:05:24 -0800 Subject: [PATCH 2046/2500] crypto/x509: remove ios build tag restriction Fixes #49435 Change-Id: I77ce12f447e727e7dc3b23de947357c27a268bd2 Reviewed-on: https://go-review.googlesource.com/c/go/+/362294 Trust: Roland Shoemaker Run-TryBot: Roland Shoemaker Reviewed-by: Bryan C. Mills --- src/crypto/x509/internal/macos/corefoundation.go | 2 +- src/crypto/x509/internal/macos/corefoundation.s | 2 +- src/crypto/x509/internal/macos/security.go | 2 +- src/crypto/x509/internal/macos/security.s | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/crypto/x509/internal/macos/corefoundation.go b/src/crypto/x509/internal/macos/corefoundation.go index 07db5c7527..cda1d95d81 100644 --- a/src/crypto/x509/internal/macos/corefoundation.go +++ b/src/crypto/x509/internal/macos/corefoundation.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build darwin && !ios +//go:build darwin // Package macOS provides cgo-less wrappers for Core Foundation and // Security.framework, similarly to how package syscall provides access to diff --git a/src/crypto/x509/internal/macos/corefoundation.s b/src/crypto/x509/internal/macos/corefoundation.s index e60bd8712d..d69f72f795 100644 --- a/src/crypto/x509/internal/macos/corefoundation.s +++ b/src/crypto/x509/internal/macos/corefoundation.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build darwin && !ios +//go:build darwin #include "textflag.h" diff --git a/src/crypto/x509/internal/macos/security.go b/src/crypto/x509/internal/macos/security.go index 2805076ccd..661844a805 100644 --- a/src/crypto/x509/internal/macos/security.go +++ b/src/crypto/x509/internal/macos/security.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build darwin && !ios +//go:build darwin package macOS diff --git a/src/crypto/x509/internal/macos/security.s b/src/crypto/x509/internal/macos/security.s index 77406a0553..cdef63f9f9 100644 --- a/src/crypto/x509/internal/macos/security.s +++ b/src/crypto/x509/internal/macos/security.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build darwin && !ios +//go:build darwin #include "textflag.h" -- GitLab From 5e6475598c4c78fe5404ea273041552e65463a21 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Tue, 9 Nov 2021 00:34:18 +0700 Subject: [PATCH 2047/2500] cmd/compile: Revert "cmd/compile/internal/types2: remove most asX converters (cleanup)" This reverts commit 759eaa22adb0ab883959e4a36c19f2dfe77b5895. Reason to revert: break unified IR builder Though the unified IR is not for go1.18, it's the only user of types2 lazy resolution APIs at this moment. And it consistently failed after CL 362254 is the sign that the change was wrong somehow. Change-Id: I6bfc3192904fe2129fd3c165f0df8761e8eb441c Reviewed-on: https://go-review.googlesource.com/c/go/+/361964 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Robert Findley --- .../compile/internal/types2/assignments.go | 2 +- src/cmd/compile/internal/types2/builtins.go | 8 ++-- src/cmd/compile/internal/types2/call.go | 2 +- src/cmd/compile/internal/types2/context.go | 2 +- .../compile/internal/types2/conversions.go | 21 +++++----- src/cmd/compile/internal/types2/expr.go | 6 +-- src/cmd/compile/internal/types2/index.go | 8 ++-- src/cmd/compile/internal/types2/lookup.go | 9 +++-- src/cmd/compile/internal/types2/predicates.go | 5 +-- src/cmd/compile/internal/types2/sizes.go | 2 +- src/cmd/compile/internal/types2/type.go | 39 ++++++++++++++++++- src/cmd/compile/internal/types2/typestring.go | 2 +- src/cmd/compile/internal/types2/typexpr.go | 2 +- 13 files changed, 72 insertions(+), 36 deletions(-) diff --git a/src/cmd/compile/internal/types2/assignments.go b/src/cmd/compile/internal/types2/assignments.go index 609d7d0962..bfc5578683 100644 --- a/src/cmd/compile/internal/types2/assignments.go +++ b/src/cmd/compile/internal/types2/assignments.go @@ -71,7 +71,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { // x.typ is typed // A generic (non-instantiated) function value cannot be assigned to a variable. - if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 { + if sig := asSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { check.errorf(x, "cannot use generic function %s without instantiation in %s", x, context) } diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 916aed40b3..ade4c0a49f 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -294,7 +294,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( // (applyTypeFunc never calls f with a type parameter) f := func(typ Type) Type { assert(asTypeParam(typ) == nil) - if t, _ := under(typ).(*Basic); t != nil { + if t := asBasic(typ); t != nil { switch t.kind { case Float32: return Typ[Complex64] @@ -418,7 +418,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( // (applyTypeFunc never calls f with a type parameter) f := func(typ Type) Type { assert(asTypeParam(typ) == nil) - if t, _ := under(typ).(*Basic); t != nil { + if t := asBasic(typ); t != nil { switch t.kind { case Complex64: return Typ[Float32] @@ -704,7 +704,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( return } - typ, _ := under(x.typ).(*Pointer) + typ := asPointer(x.typ) if typ == nil { check.errorf(x, invalidArg+"%s is not a pointer", x) return @@ -894,7 +894,7 @@ func makeSig(res Type, args ...Type) *Signature { // otherwise it returns typ. func arrayPtrDeref(typ Type) Type { if p, ok := typ.(*Pointer); ok { - if a, _ := under(p.base).(*Array); a != nil { + if a := asArray(p.base); a != nil { return a } } diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 3a571285c1..74edd4d442 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -132,7 +132,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { case 1: check.expr(x, call.ArgList[0]) if x.mode != invalid { - if t, _ := under(T).(*Interface); t != nil { + if t := asInterface(T); t != nil { if !t.IsMethodSet() { check.errorf(call, "cannot use interface %s in conversion (contains specific type constraints or is comparable)", T) break diff --git a/src/cmd/compile/internal/types2/context.go b/src/cmd/compile/internal/types2/context.go index 63303ca422..a8f8591243 100644 --- a/src/cmd/compile/internal/types2/context.go +++ b/src/cmd/compile/internal/types2/context.go @@ -39,7 +39,7 @@ func (ctxt *Context) TypeHash(typ Type, targs []Type) string { var buf bytes.Buffer h := newTypeHasher(&buf, ctxt) - if named := asNamed(typ); named != nil && len(targs) > 0 { + if named, _ := typ.(*Named); named != nil && len(targs) > 0 { // Don't use WriteType because we need to use the provided targs // and not any targs that might already be with the *Named type. h.typePrefix(named) diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go index dd89f29762..ccabbaf0d7 100644 --- a/src/cmd/compile/internal/types2/conversions.go +++ b/src/cmd/compile/internal/types2/conversions.go @@ -18,7 +18,7 @@ func (check *Checker) conversion(x *operand, T Type) { constArg := x.mode == constant_ constConvertibleTo := func(T Type, val *constant.Value) bool { - switch t, _ := under(T).(*Basic); { + switch t := asBasic(T); { case t == nil: // nothing to do case representableConst(x.val, check, t, val): @@ -173,9 +173,9 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { // "V a slice, T is a pointer-to-array type, // and the slice and array types have identical element types." - if s, _ := under(V).(*Slice); s != nil { - if p, _ := under(T).(*Pointer); p != nil { - if a, _ := under(p.Elem()).(*Array); a != nil { + if s := asSlice(V); s != nil { + if p := asPointer(T); p != nil { + if a := asArray(p.Elem()); a != nil { if Identical(s.Elem(), a.Elem()) { if check == nil || check.allowVersion(check.pkg, 1, 17) { return true @@ -262,27 +262,26 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { // use the toT convenience converters in the predicates below. func isUintptr(typ Type) bool { - t, _ := under(typ).(*Basic) + t := asBasic(typ) return t != nil && t.kind == Uintptr } func isUnsafePointer(typ Type) bool { - // TODO(gri): Is this under(typ).(*Basic) instead of typ.(*Basic) correct? + // TODO(gri): Is this asBasic(typ) instead of typ.(*Basic) correct? // (The former calls under(), while the latter doesn't.) // The spec does not say so, but gc claims it is. See also // issue 6326. - t, _ := under(typ).(*Basic) + t := asBasic(typ) return t != nil && t.kind == UnsafePointer } func isPointer(typ Type) bool { - _, ok := under(typ).(*Pointer) - return ok + return asPointer(typ) != nil } func isBytesOrRunes(typ Type) bool { - if s, _ := under(typ).(*Slice); s != nil { - t, _ := under(s.elem).(*Basic) + if s := asSlice(typ); s != nil { + t := asBasic(s.elem) return t != nil && (t.kind == Byte || t.kind == Rune) } return false diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 8125fba717..d24532d780 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -116,7 +116,7 @@ func (check *Checker) overflow(x *operand) { // x.typ cannot be a type parameter (type // parameters cannot be constant types). if isTyped(x.typ) { - check.representable(x, under(x.typ).(*Basic)) + check.representable(x, asBasic(x.typ)) return } @@ -617,7 +617,7 @@ func (check *Checker) updateExprType(x syntax.Expr, typ Type, final bool) { // If the new type is not final and still untyped, just // update the recorded type. if !final && isUntyped(typ) { - old.typ = under(typ).(*Basic) + old.typ = asBasic(typ) check.untyped[x] = old return } @@ -1394,7 +1394,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin duplicate := false // if the key is of interface type, the type is also significant when checking for duplicates xkey := keyVal(x.val) - if IsInterface(utyp.key) { + if asInterface(utyp.key) != nil { for _, vtyp := range visited[xkey] { if Identical(vtyp, x.typ) { duplicate = true diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index f096674536..67110704e9 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -34,7 +34,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo return false case value: - if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 { + if sig := asSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { // function instantiation return true } @@ -72,7 +72,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo x.typ = typ.elem case *Pointer: - if typ, _ := under(typ.base).(*Array); typ != nil { + if typ := asArray(typ.base); typ != nil { valid = true length = typ.len x.mode = variable @@ -120,7 +120,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo mode = value } case *Pointer: - if t, _ := under(t.base).(*Array); t != nil { + if t := asArray(t.base); t != nil { l = t.len e = t.elem } @@ -245,7 +245,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { x.typ = &Slice{elem: u.elem} case *Pointer: - if u, _ := under(u.base).(*Array); u != nil { + if u := asArray(u.base); u != nil { valid = true length = u.len x.typ = &Slice{elem: u.elem} diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index 0612400590..e0fd74482a 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -122,6 +122,7 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o seen[named] = true // look for a matching attached method + named.resolve(nil) if i, m := lookupMethod(named.methods, pkg, name); m != nil { // potential match // caution: method may not have a proper signature yet @@ -305,7 +306,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, return } - if ityp, _ := under(V).(*Interface); ityp != nil { + if ityp := asInterface(V); ityp != nil { // TODO(gri) the methods are sorted - could do this more efficiently for _, m := range T.typeSet().methods { _, f := ityp.typeSet().LookupMethod(m.pkg, m.name) @@ -416,7 +417,7 @@ func (check *Checker) assertableTo(V *Interface, T Type) (method, wrongType *Fun // no static check is required if T is an interface // spec: "If T is an interface type, x.(T) asserts that the // dynamic type of x implements the interface T." - if IsInterface(T) && !forceStrict { + if asInterface(T) != nil && !forceStrict { return } return check.missingMethod(T, V, false) @@ -434,8 +435,8 @@ func deref(typ Type) (Type, bool) { // derefStructPtr dereferences typ if it is a (named or unnamed) pointer to a // (named or unnamed) struct and returns its base. Otherwise it returns typ. func derefStructPtr(typ Type) Type { - if p, _ := under(typ).(*Pointer); p != nil { - if _, ok := under(p.base).(*Struct); ok { + if p := asPointer(typ); p != nil { + if asStruct(p.base) != nil { return p.base } } diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 8d676ed8f6..7fbb91eb61 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -72,7 +72,7 @@ func hasName(t Type) bool { // are not fully set up. func isTyped(t Type) bool { // isTyped is called with types that are not fully - // set up. Must not call under()! + // set up. Must not call asBasic()! b, _ := t.(*Basic) return b == nil || b.info&IsUntyped == 0 } @@ -84,8 +84,7 @@ func isUntyped(t Type) bool { // IsInterface reports whether t is an interface type. func IsInterface(t Type) bool { - _, ok := under(t).(*Interface) - return ok + return asInterface(t) != nil } // isTypeParam reports whether t is a type parameter. diff --git a/src/cmd/compile/internal/types2/sizes.go b/src/cmd/compile/internal/types2/sizes.go index 609b6f585e..6a3d19d8ea 100644 --- a/src/cmd/compile/internal/types2/sizes.go +++ b/src/cmd/compile/internal/types2/sizes.go @@ -243,7 +243,7 @@ func (conf *Config) offsetsof(T *Struct) []int64 { func (conf *Config) offsetof(typ Type, index []int) int64 { var o int64 for _, i := range index { - s := under(typ).(*Struct) + s := asStruct(typ) o += conf.offsetsof(s)[i] typ = s.fields[i].typ } diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index d1655c55f8..300c81f5fa 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -27,8 +27,45 @@ func under(t Type) Type { return t } +// Convenience converters + +func asBasic(t Type) *Basic { + u, _ := under(t).(*Basic) + return u +} + +func asArray(t Type) *Array { + u, _ := under(t).(*Array) + return u +} + +func asSlice(t Type) *Slice { + u, _ := under(t).(*Slice) + return u +} + +func asStruct(t Type) *Struct { + u, _ := under(t).(*Struct) + return u +} + +func asPointer(t Type) *Pointer { + u, _ := under(t).(*Pointer) + return u +} + +func asSignature(t Type) *Signature { + u, _ := under(t).(*Signature) + return u +} + +func asInterface(t Type) *Interface { + u, _ := under(t).(*Interface) + return u +} + // If the argument to asNamed, or asTypeParam is of the respective type -// (possibly after resolving a *Named type), these methods return that type. +// (possibly after expanding resolving a *Named type), these methods return that type. // Otherwise the result is nil. func asNamed(t Type) *Named { diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index f151f47a5e..f18a32016f 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -361,7 +361,7 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) { } else { // special case: // append(s, "foo"...) leads to signature func([]byte, string...) - if t, _ := under(typ).(*Basic); t == nil || t.kind != String { + if t := asBasic(typ); t == nil || t.kind != String { w.error("expected string type") continue } diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index a08e472703..dcd7cfebe8 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -148,7 +148,7 @@ func (check *Checker) varType(e syntax.Expr) Type { // are in the middle of type-checking parameter declarations that might belong to // interface methods. Delay this check to the end of type-checking. check.later(func() { - if t, _ := under(typ).(*Interface); t != nil { + if t := asInterface(typ); t != nil { pos := syntax.StartPos(e) tset := computeInterfaceTypeSet(check, pos, t) // TODO(gri) is this the correct position? if !tset.IsMethodSet() { -- GitLab From 830b393bcd5a3090b13cd0bd05f51e3d594807f3 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Tue, 9 Nov 2021 00:05:58 +0700 Subject: [PATCH 2048/2500] cmd/compile,cmd/go: fix long test builders CL 361411 improved error message for go version requirement, but forgot to update the test in cmd/go to match new error message. That causes longtest builders failed. This CL changes mod_vendor_goversion.txt to match compiler error, and limit fixedbugs/issue49368.go to run with -G=3 only. Updates #49368 Change-Id: I125fe0a8c2a1595066d39c03e97819e7a1274e0a Reviewed-on: https://go-review.googlesource.com/c/go/+/361963 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Robert Findley Reviewed-by: Bryan C. Mills --- src/cmd/go/testdata/script/mod_vendor_goversion.txt | 2 +- test/fixedbugs/issue49368.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/go/testdata/script/mod_vendor_goversion.txt b/src/cmd/go/testdata/script/mod_vendor_goversion.txt index a92eb73d27..9e3618a218 100644 --- a/src/cmd/go/testdata/script/mod_vendor_goversion.txt +++ b/src/cmd/go/testdata/script/mod_vendor_goversion.txt @@ -26,7 +26,7 @@ go mod vendor ! grep 1.17 vendor/modules.txt ! go build example.net/need117 stderr '^vendor[/\\]example\.net[/\\]need117[/\\]need117.go:5:1[89]:' -stderr 'conversion of slices to array pointers only supported as of -lang=go1\.17' +stderr 'conversion of slices to array pointers requires go1\.17 or later' ! grep 1.13 vendor/modules.txt go build example.net/bad114 diff --git a/test/fixedbugs/issue49368.go b/test/fixedbugs/issue49368.go index 2339048e3d..4cbf351ae0 100644 --- a/test/fixedbugs/issue49368.go +++ b/test/fixedbugs/issue49368.go @@ -1,4 +1,4 @@ -// errorcheck -lang=go1.17 +// errorcheck -G=3 -lang=go1.17 // Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style -- GitLab From ccea0b2fbe8eaf0ac69fab4aef28f300bf676d21 Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Mon, 8 Nov 2021 12:45:41 -0800 Subject: [PATCH 2049/2500] net/http: deflake TestTimeoutHandlerContextCanceled Fixes #49448 Change-Id: Ie2acff7dedbca9bd1cc0b1b3dd0a01573c7befee Reviewed-on: https://go-review.googlesource.com/c/go/+/361920 Trust: Damien Neil Run-TryBot: Damien Neil TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/net/http/serve_test.go | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index 27dff2bf45..30a6555d30 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -2520,22 +2520,28 @@ func TestTimeoutHandlerStartTimerWhenServing(t *testing.T) { func TestTimeoutHandlerContextCanceled(t *testing.T) { setParallel(t) defer afterTest(t) - sendHi := make(chan bool, 1) writeErrors := make(chan error, 1) sayHi := HandlerFunc(func(w ResponseWriter, r *Request) { w.Header().Set("Content-Type", "text/plain") - <-sendHi - _, werr := w.Write([]byte("hi")) - writeErrors <- werr + var err error + // The request context has already been canceled, but + // retry the write for a while to give the timeout handler + // a chance to notice. + for i := 0; i < 100; i++ { + _, err = w.Write([]byte("a")) + if err != nil { + break + } + time.Sleep(1 * time.Millisecond) + } + writeErrors <- err }) - ctx, cancel := context.WithTimeout(context.Background(), 1*time.Hour) - h := NewTestTimeoutHandler(sayHi, ctx) + ctx, cancel := context.WithCancel(context.Background()) cancel() + h := NewTestTimeoutHandler(sayHi, ctx) cst := newClientServerTest(t, h1Mode, h) defer cst.close() - // Succeed without timing out: - sendHi <- true res, err := cst.c.Get(cst.ts.URL) if err != nil { t.Error(err) @@ -2548,7 +2554,7 @@ func TestTimeoutHandlerContextCanceled(t *testing.T) { t.Errorf("got body %q; expected %q", g, e) } if g, e := <-writeErrors, context.Canceled; g != e { - t.Errorf("got unexpected Write error on first request: %v", g) + t.Errorf("got unexpected Write in handler: %v, want %g", g, e) } } -- GitLab From 0e39946e8df426b459103ab94256b697a6a4dd9c Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Tue, 19 Oct 2021 14:05:29 -0400 Subject: [PATCH 2050/2500] cmd/go: add workspace pruning mode This change corrects a bug in the handling of module loading of workspaces. Namely, there is an assumption by the module pruning code that if a root module is selected then the packages of that module can be resolved without loading the whole module graph. This is not true in workspace mode because two workspace modules can require different versions of a dependency. Worse, one workspace module can directly require a depencency that is transitively required by another workspace module, changing the version of that module loaded in the fully expanded graph. To correct this, a new 'workspace' pruning mode is added where the roots are the workspace modules themselves, satisfying the assumption made by the module pruning logic. The rest of this change accounts for the new pruning mode where it's used and correctly sets the requirements in this pruning mode. Change-Id: I5d4d9877e492e196681f6ee9f8f18a08b4e95c61 Reviewed-on: https://go-review.googlesource.com/c/go/+/357169 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/modload/buildlist.go | 86 +++++++++++++++++------ src/cmd/go/internal/modload/init.go | 44 ++++++------ src/cmd/go/internal/modload/load.go | 24 ++++++- src/cmd/go/internal/modload/modfile.go | 14 ++-- src/cmd/go/testdata/script/work_prune.txt | 2 +- 5 files changed, 121 insertions(+), 49 deletions(-) diff --git a/src/cmd/go/internal/modload/buildlist.go b/src/cmd/go/internal/modload/buildlist.go index 27cab0b9c8..9e56265a41 100644 --- a/src/cmd/go/internal/modload/buildlist.go +++ b/src/cmd/go/internal/modload/buildlist.go @@ -38,11 +38,17 @@ type Requirements struct { // If pruned, the graph includes only the root modules, the explicit // requirements of those root modules, and the transitive requirements of only // the root modules that do not support pruning. + // + // If workspace, the graph includes only the workspace modules, the explicit + // requirements of the workspace modules, and the transitive requirements of + // the workspace modules that do not support pruning. pruning modPruning - // rootModules is the set of module versions explicitly required by the main - // modules, sorted and capped to length. It may contain duplicates, and may - // contain multiple versions for a given module path. + // rootModules is the set of root modules of the graph, sorted and capped to + // length. It may contain duplicates, and may contain multiple versions for a + // given module path. The root modules of the groph are the set of main + // modules in workspace mode, and the main module's direct requirements + // outside workspace mode. rootModules []module.Version maxRootVersion map[string]string @@ -99,6 +105,19 @@ var requirements *Requirements // If vendoring is in effect, the caller must invoke initVendor on the returned // *Requirements before any other method. func newRequirements(pruning modPruning, rootModules []module.Version, direct map[string]bool) *Requirements { + if pruning == workspace { + return &Requirements{ + pruning: pruning, + rootModules: capVersionSlice(rootModules), + maxRootVersion: nil, + direct: direct, + } + } + + if inWorkspaceMode() && pruning != workspace { + panic("in workspace mode, but pruning is not workspace in newRequirements") + } + for i, m := range rootModules { if m.Version == "" && MainModules.Contains(m.Path) { panic(fmt.Sprintf("newRequirements called with untrimmed build list: rootModules[%v] is a main module", i)) @@ -291,13 +310,11 @@ func readModGraph(ctx context.Context, pruning modPruning, roots []module.Versio g: mvs.NewGraph(cmpVersion, MainModules.Versions()), } ) - for _, m := range MainModules.Versions() { - // Require all roots from all main modules. - _ = TODOWorkspaces("This flattens a level of the module graph, adding the dependencies " + - "of all main modules to a single requirements struct, and losing the information of which " + - "main module required which requirement. Rework the requirements struct and change this" + - "to reflect the structure of the main modules.") - mg.g.Require(m, roots) + if pruning != workspace { + if inWorkspaceMode() { + panic("pruning is not workspace in workspace mode") + } + mg.g.Require(MainModules.mustGetSingleMainModule(), roots) } var ( @@ -352,9 +369,13 @@ func readModGraph(ctx context.Context, pruning modPruning, roots []module.Versio // are sufficient to build the packages it contains. We must load its full // transitive dependency graph to be sure that we see all relevant // dependencies. - if pruning == unpruned || summary.pruning == unpruned { + if pruning != pruned || summary.pruning == unpruned { + nextPruning := summary.pruning + if pruning == unpruned { + nextPruning = unpruned + } for _, r := range summary.require { - enqueue(r, unpruned) + enqueue(r, nextPruning) } } }) @@ -424,12 +445,15 @@ func (mg *ModuleGraph) findError() error { } func (mg *ModuleGraph) allRootsSelected() bool { - for _, mm := range MainModules.Versions() { - roots, _ := mg.g.RequiredBy(mm) - for _, m := range roots { - if mg.Selected(m.Path) != m.Version { - return false - } + var roots []module.Version + if inWorkspaceMode() { + roots = MainModules.Versions() + } else { + roots, _ = mg.g.RequiredBy(MainModules.mustGetSingleMainModule()) + } + for _, m := range roots { + if mg.Selected(m.Path) != m.Version { + return false } } return true @@ -576,10 +600,29 @@ func tidyRoots(ctx context.Context, rs *Requirements, pkgs []*loadPkg) (*Require } func updateRoots(ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version, rootsImported bool) (*Requirements, error) { - if rs.pruning == unpruned { + switch rs.pruning { + case unpruned: return updateUnprunedRoots(ctx, direct, rs, add) + case pruned: + return updatePrunedRoots(ctx, direct, rs, pkgs, add, rootsImported) + case workspace: + return updateWorkspaceRoots(ctx, rs, add) + default: + panic(fmt.Sprintf("unsupported pruning mode: %v", rs.pruning)) + } +} + +func updateWorkspaceRoots(ctx context.Context, rs *Requirements, add []module.Version) (*Requirements, error) { + if len(add) != 0 { + // add should be empty in workspace mode because a non-empty add slice means + // that there are missing roots in the current pruning mode or that the + // pruning mode is being changed. But the pruning mode should always be + // 'workspace' in workspace mode and the set of roots in workspace mode is + // always complete because it's the set of workspace modules, which can't + // be edited by loading. + panic("add is not empty") } - return updatePrunedRoots(ctx, direct, rs, pkgs, add, rootsImported) + return rs, nil } // tidyPrunedRoots returns a minimal set of root requirements that maintains the @@ -1156,7 +1199,6 @@ func updateUnprunedRoots(ctx context.Context, direct map[string]bool, rs *Requir } } - // TODO(matloob): Make roots into a map. var roots []module.Version for _, mainModule := range MainModules.Versions() { min, err := mvs.Req(mainModule, rootPaths, &mvsReqs{roots: keep}) @@ -1182,6 +1224,8 @@ func updateUnprunedRoots(ctx context.Context, direct map[string]bool, rs *Requir func convertPruning(ctx context.Context, rs *Requirements, pruning modPruning) (*Requirements, error) { if rs.pruning == pruning { return rs, nil + } else if rs.pruning == workspace || pruning == workspace { + panic("attempthing to convert to/from workspace pruning and another pruning type") } if pruning == unpruned { diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 9aef5a7c33..512c9ebfbd 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -704,7 +704,7 @@ func LoadModFile(ctx context.Context) *Requirements { } } - if MainModules.Index(mainModule).goVersionV == "" { + if MainModules.Index(mainModule).goVersionV == "" && rs.pruning != workspace { // TODO(#45551): Do something more principled instead of checking // cfg.CmdName directly here. if cfg.BuildMod == "mod" && cfg.CmdName != "mod graph" && cfg.CmdName != "mod why" { @@ -987,29 +987,29 @@ func makeMainModules(ms []module.Version, rootDirs []string, modFiles []*modfile // requirementsFromModFiles returns the set of non-excluded requirements from // the global modFile. func requirementsFromModFiles(ctx context.Context, modFiles []*modfile.File) *Requirements { - rootCap := 0 - for i := range modFiles { - rootCap += len(modFiles[i].Require) - } - roots := make([]module.Version, 0, rootCap) - mPathCount := make(map[string]int) - for _, m := range MainModules.Versions() { - mPathCount[m.Path] = 1 - } + var roots []module.Version direct := map[string]bool{} - for _, modFile := range modFiles { - requirement: + var pruning modPruning + if inWorkspaceMode() { + pruning = workspace + roots = make([]module.Version, len(MainModules.Versions())) + copy(roots, MainModules.Versions()) + } else { + pruning = pruningForGoVersion(MainModules.GoVersion()) + if len(modFiles) != 1 { + panic(fmt.Errorf("requirementsFromModFiles called with %v modfiles outside workspace mode", len(modFiles))) + } + modFile := modFiles[0] + roots = make([]module.Version, 0, len(modFile.Require)) + mm := MainModules.mustGetSingleMainModule() for _, r := range modFile.Require { - // TODO(#45713): Maybe join - for _, mainModule := range MainModules.Versions() { - if index := MainModules.Index(mainModule); index != nil && index.exclude[r.Mod] { - if cfg.BuildMod == "mod" { - fmt.Fprintf(os.Stderr, "go: dropping requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version) - } else { - fmt.Fprintf(os.Stderr, "go: ignoring requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version) - } - continue requirement + if index := MainModules.Index(mm); index != nil && index.exclude[r.Mod] { + if cfg.BuildMod == "mod" { + fmt.Fprintf(os.Stderr, "go: dropping requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version) + } else { + fmt.Fprintf(os.Stderr, "go: ignoring requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version) } + continue } roots = append(roots, r.Mod) @@ -1019,7 +1019,7 @@ func requirementsFromModFiles(ctx context.Context, modFiles []*modfile.File) *Re } } module.Sort(roots) - rs := newRequirements(pruningForGoVersion(MainModules.GoVersion()), roots, direct) + rs := newRequirements(pruning, roots, direct) return rs } diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index 845bf2f8a2..83fcafead3 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -1004,7 +1004,11 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader { } var err error - ld.requirements, err = convertPruning(ctx, ld.requirements, pruningForGoVersion(ld.GoVersion)) + desiredPruning := pruningForGoVersion(ld.GoVersion) + if ld.requirements.pruning == workspace { + desiredPruning = workspace + } + ld.requirements, err = convertPruning(ctx, ld.requirements, desiredPruning) if err != nil { ld.errorf("go: %v\n", err) } @@ -1246,6 +1250,24 @@ func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err err continue } + if inWorkspaceMode() { + // In workspace mode / workspace pruning mode, the roots are the main modules + // rather than the main module's direct dependencies. The check below on the selected + // roots does not apply. + if mg, err := rs.Graph(ctx); err != nil { + return false, err + } else if _, ok := mg.RequiredBy(dep.mod); !ok { + // dep.mod is not an explicit dependency, but needs to be. + // See comment on error returned below. + pkg.err = &DirectImportFromImplicitDependencyError{ + ImporterPath: pkg.path, + ImportedPath: dep.path, + Module: dep.mod, + } + } + continue + } + if pkg.err == nil && cfg.BuildMod != "mod" { if v, ok := rs.rootSelected(dep.mod.Path); !ok || v != dep.mod.Version { // dep.mod is not an explicit dependency, but needs to be. diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index a7e92222a1..40e6ed787d 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -118,8 +118,9 @@ type requireMeta struct { type modPruning uint8 const ( - pruned modPruning = iota // transitive dependencies of modules at go 1.17 and higher are pruned out - unpruned // no transitive dependencies are pruned out + pruned modPruning = iota // transitive dependencies of modules at go 1.17 and higher are pruned out + unpruned // no transitive dependencies are pruned out + workspace // pruned to the union of modules in the workspace ) func pruningForGoVersion(goVersion string) modPruning { @@ -554,7 +555,7 @@ type retraction struct { // // The caller must not modify the returned summary. func goModSummary(m module.Version) (*modFileSummary, error) { - if m.Version == "" && MainModules.Contains(m.Path) { + if m.Version == "" && !inWorkspaceMode() && MainModules.Contains(m.Path) { panic("internal error: goModSummary called on a main module") } @@ -718,9 +719,14 @@ var rawGoModSummaryCache par.Cache // module.Version → rawGoModSummary result func rawGoModData(m module.Version) (name string, data []byte, err error) { if m.Version == "" { // m is a replacement module with only a file path. + dir := m.Path if !filepath.IsAbs(dir) { - dir = filepath.Join(replaceRelativeTo(), dir) + if inWorkspaceMode() && MainModules.Contains(m.Path) { + dir = MainModules.ModRoot(m) + } else { + dir = filepath.Join(replaceRelativeTo(), dir) + } } name = filepath.Join(dir, "go.mod") if gomodActual, ok := fsys.OverlayPath(name); ok { diff --git a/src/cmd/go/testdata/script/work_prune.txt b/src/cmd/go/testdata/script/work_prune.txt index f0fb073c4b..00c3e10663 100644 --- a/src/cmd/go/testdata/script/work_prune.txt +++ b/src/cmd/go/testdata/script/work_prune.txt @@ -14,7 +14,7 @@ # TODO(#48331): We currently load the wrong version of q. Fix this. go list -m -f '{{.Version}}' example.com/q -stdout '^v1.0.0$' # TODO(#48331): This should be 1.1.0. Fix this. +stdout '^v1.1.0$' -- go.work -- go 1.18 -- GitLab From cc4917823747752337feec5a14f700633f4e9d02 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Thu, 21 Oct 2021 14:26:55 -0400 Subject: [PATCH 2051/2500] cmd/go: rename go mod initwork and editwork to go work init and edit This brings the workspace related commands into their own namespace. Fixes #48256 Change-Id: I9d5e3d4c45798913d742c532c1571006e6f9cc57 Reviewed-on: https://go-review.googlesource.com/c/go/+/357611 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/alldocs.go | 200 ++++++++++-------- src/cmd/go/internal/modcmd/mod.go | 2 - .../{modcmd/editwork.go => workcmd/edit.go} | 97 ++++++--- .../{modcmd/initwork.go => workcmd/init.go} | 14 +- src/cmd/go/internal/workcmd/work.go | 28 +++ src/cmd/go/main.go | 2 + src/cmd/go/testdata/script/work.txt | 4 +- src/cmd/go/testdata/script/work_edit.txt | 22 +- .../testdata/script/work_replace_conflict.txt | 2 +- 9 files changed, 230 insertions(+), 141 deletions(-) rename src/cmd/go/internal/{modcmd/editwork.go => workcmd/edit.go} (74%) rename src/cmd/go/internal/{modcmd/initwork.go => workcmd/init.go} (83%) create mode 100644 src/cmd/go/internal/workcmd/work.go diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index c9426801c5..d8ebc8d61d 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -25,6 +25,7 @@ // install compile and install packages and dependencies // list list packages or modules // mod module maintenance +// work workspace maintenance // run compile and run Go program // test test packages // tool run specified go tool @@ -1055,10 +1056,8 @@ // // download download modules to local cache // edit edit go.mod from tools or scripts -// editwork edit go.work from tools or scripts // graph print module requirement graph // init initialize new module in current directory -// initwork initialize workspace file // tidy add missing and remove unused modules // vendor make vendored copy of dependencies // verify verify dependencies have expected content @@ -1218,77 +1217,6 @@ // See https://golang.org/ref/mod#go-mod-edit for more about 'go mod edit'. // // -// Edit go.work from tools or scripts -// -// Usage: -// -// go mod editwork [editing flags] [go.work] -// -// Editwork provides a command-line interface for editing go.work, -// for use primarily by tools or scripts. It only reads go.work; -// it does not look up information about the modules involved. -// If no file is specified, editwork looks for a go.work file in the current -// directory and its parent directories -// -// The editing flags specify a sequence of editing operations. -// -// The -fmt flag reformats the go.work file without making other changes. -// This reformatting is also implied by any other modifications that use or -// rewrite the go.mod file. The only time this flag is needed is if no other -// flags are specified, as in 'go mod editwork -fmt'. -// -// The -directory=path and -dropdirectory=path flags -// add and drop a directory from the go.work files set of module directories. -// -// The -replace=old[@v]=new[@v] flag adds a replacement of the given -// module path and version pair. If the @v in old@v is omitted, a -// replacement without a version on the left side is added, which applies -// to all versions of the old module path. If the @v in new@v is omitted, -// the new path should be a local module root directory, not a module -// path. Note that -replace overrides any redundant replacements for old[@v], -// so omitting @v will drop existing replacements for specific versions. -// -// The -dropreplace=old[@v] flag drops a replacement of the given -// module path and version pair. If the @v is omitted, a replacement without -// a version on the left side is dropped. -// -// The -directory, -dropdirectory, -replace, and -dropreplace, -// editing flags may be repeated, and the changes are applied in the order given. -// -// The -go=version flag sets the expected Go language version. -// -// The -print flag prints the final go.work in its text format instead of -// writing it back to go.mod. -// -// The -json flag prints the final go.work file in JSON format instead of -// writing it back to go.mod. The JSON output corresponds to these Go types: -// -// type Module struct { -// Path string -// Version string -// } -// -// type GoWork struct { -// Go string -// Directory []Directory -// Replace []Replace -// } -// -// type Directory struct { -// Path string -// ModulePath string -// } -// -// type Replace struct { -// Old Module -// New Module -// } -// -// See the workspaces design proposal at -// https://go.googlesource.com/proposal/+/master/design/45713-workspace.md for -// more information. -// -// // Print module requirement graph // // Usage: @@ -1328,23 +1256,6 @@ // See https://golang.org/ref/mod#go-mod-init for more about 'go mod init'. // // -// Initialize workspace file -// -// Usage: -// -// go mod initwork [moddirs] -// -// go mod initwork initializes and writes a new go.work file in the current -// directory, in effect creating a new workspace at the current directory. -// -// go mod initwork optionally accepts paths to the workspace modules as arguments. -// If the argument is omitted, an empty workspace with no modules will be created. -// -// See the workspaces design proposal at -// https://go.googlesource.com/proposal/+/master/design/45713-workspace.md for -// more information. -// -// // Add missing and remove unused modules // // Usage: @@ -1453,6 +1364,115 @@ // See https://golang.org/ref/mod#go-mod-why for more about 'go mod why'. // // +// Workspace maintenance +// +// Go workspace provides access to operations on worskpaces. +// +// Note that support for workspaces is built into many other commands, +// not just 'go work'. +// +// See 'go help modules' for information about Go's module system of +// which workspaces are a part. +// +// Usage: +// +// go work [arguments] +// +// The commands are: +// +// edit edit go.work from tools or scripts +// init initialize workspace file +// +// Use "go help work " for more information about a command. +// +// Edit go.work from tools or scripts +// +// Usage: +// +// go work edit [editing flags] [go.work] +// +// Editwork provides a command-line interface for editing go.work, +// for use primarily by tools or scripts. It only reads go.work; +// it does not look up information about the modules involved. +// If no file is specified, editwork looks for a go.work file in the current +// directory and its parent directories +// +// The editing flags specify a sequence of editing operations. +// +// The -fmt flag reformats the go.work file without making other changes. +// This reformatting is also implied by any other modifications that use or +// rewrite the go.mod file. The only time this flag is needed is if no other +// flags are specified, as in 'go mod editwork -fmt'. +// +// The -directory=path and -dropdirectory=path flags +// add and drop a directory from the go.work files set of module directories. +// +// The -replace=old[@v]=new[@v] flag adds a replacement of the given +// module path and version pair. If the @v in old@v is omitted, a +// replacement without a version on the left side is added, which applies +// to all versions of the old module path. If the @v in new@v is omitted, +// the new path should be a local module root directory, not a module +// path. Note that -replace overrides any redundant replacements for old[@v], +// so omitting @v will drop existing replacements for specific versions. +// +// The -dropreplace=old[@v] flag drops a replacement of the given +// module path and version pair. If the @v is omitted, a replacement without +// a version on the left side is dropped. +// +// The -directory, -dropdirectory, -replace, and -dropreplace, +// editing flags may be repeated, and the changes are applied in the order given. +// +// The -go=version flag sets the expected Go language version. +// +// The -print flag prints the final go.work in its text format instead of +// writing it back to go.mod. +// +// The -json flag prints the final go.work file in JSON format instead of +// writing it back to go.mod. The JSON output corresponds to these Go types: +// +// type Module struct { +// Path string +// Version string +// } +// +// type GoWork struct { +// Go string +// Directory []Directory +// Replace []Replace +// } +// +// type Directory struct { +// Path string +// ModulePath string +// } +// +// type Replace struct { +// Old Module +// New Module +// } +// +// See the workspaces design proposal at +// https://go.googlesource.com/proposal/+/master/design/45713-workspace.md for +// more information. +// +// +// Initialize workspace file +// +// Usage: +// +// go work init [moddirs] +// +// go mod initwork initializes and writes a new go.work file in the current +// directory, in effect creating a new workspace at the current directory. +// +// go mod initwork optionally accepts paths to the workspace modules as arguments. +// If the argument is omitted, an empty workspace with no modules will be created. +// +// See the workspaces design proposal at +// https://go.googlesource.com/proposal/+/master/design/45713-workspace.md for +// more information. +// +// // Compile and run Go program // // Usage: diff --git a/src/cmd/go/internal/modcmd/mod.go b/src/cmd/go/internal/modcmd/mod.go index 29aad58324..d72d0cacd6 100644 --- a/src/cmd/go/internal/modcmd/mod.go +++ b/src/cmd/go/internal/modcmd/mod.go @@ -23,10 +23,8 @@ See 'go help modules' for an overview of module functionality. Commands: []*base.Command{ cmdDownload, cmdEdit, - cmdEditwork, cmdGraph, cmdInit, - cmdInitwork, cmdTidy, cmdVendor, cmdVerify, diff --git a/src/cmd/go/internal/modcmd/editwork.go b/src/cmd/go/internal/workcmd/edit.go similarity index 74% rename from src/cmd/go/internal/modcmd/editwork.go rename to src/cmd/go/internal/workcmd/edit.go index 50f86366a0..f4e630f43f 100644 --- a/src/cmd/go/internal/modcmd/editwork.go +++ b/src/cmd/go/internal/workcmd/edit.go @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// go mod editwork +// go work edit -package modcmd +package workcmd import ( "bytes" @@ -14,15 +14,18 @@ import ( "context" "encoding/json" "errors" + "fmt" "os" "path/filepath" "strings" + "golang.org/x/mod/module" + "golang.org/x/mod/modfile" ) -var cmdEditwork = &base.Command{ - UsageLine: "go mod editwork [editing flags] [go.work]", +var cmdEdit = &base.Command{ + UsageLine: "go work edit [editing flags] [go.work]", Short: "edit go.work from tools or scripts", Long: `Editwork provides a command-line interface for editing go.work, for use primarily by tools or scripts. It only reads go.work; @@ -91,37 +94,42 @@ more information. } var ( - editworkFmt = cmdEditwork.Flag.Bool("fmt", false, "") - editworkGo = cmdEditwork.Flag.String("go", "", "") - editworkJSON = cmdEditwork.Flag.Bool("json", false, "") - editworkPrint = cmdEditwork.Flag.Bool("print", false, "") - workedits []func(file *modfile.WorkFile) // edits specified in flags + editFmt = cmdEdit.Flag.Bool("fmt", false, "") + editGo = cmdEdit.Flag.String("go", "", "") + editJSON = cmdEdit.Flag.Bool("json", false, "") + editPrint = cmdEdit.Flag.Bool("print", false, "") + workedits []func(file *modfile.WorkFile) // edits specified in flags ) +type flagFunc func(string) + +func (f flagFunc) String() string { return "" } +func (f flagFunc) Set(s string) error { f(s); return nil } + func init() { - cmdEditwork.Run = runEditwork // break init cycle + cmdEdit.Run = runEditwork // break init cycle - cmdEditwork.Flag.Var(flagFunc(flagEditworkDirectory), "directory", "") - cmdEditwork.Flag.Var(flagFunc(flagEditworkDropDirectory), "dropdirectory", "") - cmdEditwork.Flag.Var(flagFunc(flagEditworkReplace), "replace", "") - cmdEditwork.Flag.Var(flagFunc(flagEditworkDropReplace), "dropreplace", "") + cmdEdit.Flag.Var(flagFunc(flagEditworkDirectory), "directory", "") + cmdEdit.Flag.Var(flagFunc(flagEditworkDropDirectory), "dropdirectory", "") + cmdEdit.Flag.Var(flagFunc(flagEditworkReplace), "replace", "") + cmdEdit.Flag.Var(flagFunc(flagEditworkDropReplace), "dropreplace", "") - base.AddWorkfileFlag(&cmdEditwork.Flag) + base.AddWorkfileFlag(&cmdEdit.Flag) } func runEditwork(ctx context.Context, cmd *base.Command, args []string) { anyFlags := - *editworkGo != "" || - *editworkJSON || - *editworkPrint || - *editworkFmt || + *editGo != "" || + *editJSON || + *editPrint || + *editFmt || len(workedits) > 0 if !anyFlags { base.Fatalf("go: no flags specified (see 'go help mod editwork').") } - if *editworkJSON && *editworkPrint { + if *editJSON && *editPrint { base.Fatalf("go: cannot use both -json and -print") } @@ -136,8 +144,8 @@ func runEditwork(ctx context.Context, cmd *base.Command, args []string) { gowork = modload.WorkFilePath() } - if *editworkGo != "" { - if !modfile.GoVersionRE.MatchString(*editworkGo) { + if *editGo != "" { + if !modfile.GoVersionRE.MatchString(*editGo) { base.Fatalf(`go mod: invalid -go option; expecting something like "-go %s"`, modload.LatestGoVersion()) } } @@ -152,8 +160,8 @@ func runEditwork(ctx context.Context, cmd *base.Command, args []string) { base.Fatalf("go: errors parsing %s:\n%s", base.ShortPath(gowork), err) } - if *editworkGo != "" { - if err := workFile.AddGoStmt(*editworkGo); err != nil { + if *editGo != "" { + if err := workFile.AddGoStmt(*editGo); err != nil { base.Fatalf("go: internal error: %v", err) } } @@ -166,14 +174,14 @@ func runEditwork(ctx context.Context, cmd *base.Command, args []string) { workFile.SortBlocks() workFile.Cleanup() // clean file after edits - if *editworkJSON { - editworkPrintJSON(workFile) + if *editJSON { + editPrintJSON(workFile) return } out := modfile.Format(workFile.Syntax) - if *editworkPrint { + if *editPrint { os.Stdout.Write(out) return } @@ -213,6 +221,34 @@ func flagEditworkDropDirectory(arg string) { }) } +// allowedVersionArg returns whether a token may be used as a version in go.mod. +// We don't call modfile.CheckPathVersion, because that insists on versions +// being in semver form, but here we want to allow versions like "master" or +// "1234abcdef", which the go command will resolve the next time it runs (or +// during -fix). Even so, we need to make sure the version is a valid token. +func allowedVersionArg(arg string) bool { + return !modfile.MustQuote(arg) +} + +// parsePathVersionOptional parses path[@version], using adj to +// describe any errors. +func parsePathVersionOptional(adj, arg string, allowDirPath bool) (path, version string, err error) { + if i := strings.Index(arg, "@"); i < 0 { + path = arg + } else { + path, version = strings.TrimSpace(arg[:i]), strings.TrimSpace(arg[i+1:]) + } + if err := module.CheckImportPath(path); err != nil { + if !allowDirPath || !modfile.IsDirectoryPath(path) { + return path, version, fmt.Errorf("invalid %s path: %v", adj, err) + } + } + if path != arg && !allowedVersionArg(version) { + return path, version, fmt.Errorf("invalid %s version: %q", adj, version) + } + return path, version, nil +} + // flagReplace implements the -replace flag. func flagEditworkReplace(arg string) { var i int @@ -255,8 +291,13 @@ func flagEditworkDropReplace(arg string) { }) } +type replaceJSON struct { + Old module.Version + New module.Version +} + // editPrintJSON prints the -json output. -func editworkPrintJSON(workFile *modfile.WorkFile) { +func editPrintJSON(workFile *modfile.WorkFile) { var f workfileJSON if workFile.Go != nil { f.Go = workFile.Go.Version diff --git a/src/cmd/go/internal/modcmd/initwork.go b/src/cmd/go/internal/workcmd/init.go similarity index 83% rename from src/cmd/go/internal/modcmd/initwork.go rename to src/cmd/go/internal/workcmd/init.go index 4182aa071d..1342748023 100644 --- a/src/cmd/go/internal/modcmd/initwork.go +++ b/src/cmd/go/internal/workcmd/init.go @@ -4,7 +4,7 @@ // go mod initwork -package modcmd +package workcmd import ( "cmd/go/internal/base" @@ -17,8 +17,8 @@ var _ = modload.TODOWorkspaces("Add more documentation below. Though this is" + "enough for those trying workspaces out, there should be more through" + "documentation if the proposal is accepted and released.") -var cmdInitwork = &base.Command{ - UsageLine: "go mod initwork [moddirs]", +var cmdInit = &base.Command{ + UsageLine: "go work init [moddirs]", Short: "initialize workspace file", Long: `go mod initwork initializes and writes a new go.work file in the current directory, in effect creating a new workspace at the current directory. @@ -30,15 +30,15 @@ See the workspaces design proposal at https://go.googlesource.com/proposal/+/master/design/45713-workspace.md for more information. `, - Run: runInitwork, + Run: runInit, } func init() { - base.AddModCommonFlags(&cmdInitwork.Flag) - base.AddWorkfileFlag(&cmdInitwork.Flag) + base.AddModCommonFlags(&cmdInit.Flag) + base.AddWorkfileFlag(&cmdInit.Flag) } -func runInitwork(ctx context.Context, cmd *base.Command, args []string) { +func runInit(ctx context.Context, cmd *base.Command, args []string) { modload.InitWorkfile() modload.ForceUseModules = true diff --git a/src/cmd/go/internal/workcmd/work.go b/src/cmd/go/internal/workcmd/work.go new file mode 100644 index 0000000000..2e7f68b675 --- /dev/null +++ b/src/cmd/go/internal/workcmd/work.go @@ -0,0 +1,28 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package workcmd implements the ``go work'' command. +package workcmd + +import ( + "cmd/go/internal/base" +) + +var CmdWork = &base.Command{ + UsageLine: "go work", + Short: "workspace maintenance", + Long: `Go workspace provides access to operations on worskpaces. + +Note that support for workspaces is built into many other commands, +not just 'go work'. + +See 'go help modules' for information about Go's module system of +which workspaces are a part. +`, + + Commands: []*base.Command{ + cmdEdit, + cmdInit, + }, +} diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go index 16361e02ca..c0a1d3ccfc 100644 --- a/src/cmd/go/main.go +++ b/src/cmd/go/main.go @@ -7,6 +7,7 @@ package main import ( + "cmd/go/internal/workcmd" "context" "flag" "fmt" @@ -56,6 +57,7 @@ func init() { work.CmdInstall, list.CmdList, modcmd.CmdMod, + workcmd.CmdWork, run.CmdRun, test.CmdTest, tool.CmdTool, diff --git a/src/cmd/go/testdata/script/work.txt b/src/cmd/go/testdata/script/work.txt index 613f037615..68bd3ea08b 100644 --- a/src/cmd/go/testdata/script/work.txt +++ b/src/cmd/go/testdata/script/work.txt @@ -1,9 +1,9 @@ -! go mod initwork doesnotexist +! go work init doesnotexist stderr 'go: creating workspace file: no go.mod file exists in directory doesnotexist' go env GOWORK ! stdout . -go mod initwork ./a ./b +go work init ./a ./b cmp go.work go.work.want go env GOWORK stdout '^'$WORK'(\\|/)gopath(\\|/)src(\\|/)go.work$' diff --git a/src/cmd/go/testdata/script/work_edit.txt b/src/cmd/go/testdata/script/work_edit.txt index 979c1f98e0..060d1f0386 100644 --- a/src/cmd/go/testdata/script/work_edit.txt +++ b/src/cmd/go/testdata/script/work_edit.txt @@ -1,36 +1,36 @@ # Test editing go.work files. -go mod initwork m +go work init m cmp go.work go.work.want_initial -go mod editwork -directory n +go work edit -directory n cmp go.work go.work.want_directory_n -go mod editwork -go 1.18 +go work edit -go 1.18 cmp go.work go.work.want_go_118 -go mod editwork -dropdirectory m +go work edit -dropdirectory m cmp go.work go.work.want_dropdirectory_m -go mod editwork -replace=x.1@v1.3.0=y.1@v1.4.0 -replace='x.1@v1.4.0 = ../z' +go work edit -replace=x.1@v1.3.0=y.1@v1.4.0 -replace='x.1@v1.4.0 = ../z' cmp go.work go.work.want_add_replaces -go mod editwork -directory n -directory ../a -directory /b -directory c -directory c +go work edit -directory n -directory ../a -directory /b -directory c -directory c cmp go.work go.work.want_multidirectory -go mod editwork -dropdirectory /b -dropdirectory n +go work edit -dropdirectory /b -dropdirectory n cmp go.work go.work.want_multidropdirectory -go mod editwork -dropreplace='x.1@v1.4.0' +go work edit -dropreplace='x.1@v1.4.0' cmp go.work go.work.want_dropreplace -go mod editwork -print -go 1.19 -directory b -dropdirectory c -replace 'x.1@v1.4.0 = ../z' -dropreplace x.1 -dropreplace x.1@v1.3.0 +go work edit -print -go 1.19 -directory b -dropdirectory c -replace 'x.1@v1.4.0 = ../z' -dropreplace x.1 -dropreplace x.1@v1.3.0 cmp stdout go.work.want_print -go mod editwork -json -go 1.19 -directory b -dropdirectory c -replace 'x.1@v1.4.0 = ../z' -dropreplace x.1 -dropreplace x.1@v1.3.0 +go work edit -json -go 1.19 -directory b -dropdirectory c -replace 'x.1@v1.4.0 = ../z' -dropreplace x.1 -dropreplace x.1@v1.3.0 cmp stdout go.work.want_json -go mod editwork -print -fmt -workfile $GOPATH/src/unformatted +go work edit -print -fmt -workfile $GOPATH/src/unformatted cmp stdout formatted -- m/go.mod -- diff --git a/src/cmd/go/testdata/script/work_replace_conflict.txt b/src/cmd/go/testdata/script/work_replace_conflict.txt index a2f76d13a0..f91b63cd86 100644 --- a/src/cmd/go/testdata/script/work_replace_conflict.txt +++ b/src/cmd/go/testdata/script/work_replace_conflict.txt @@ -3,7 +3,7 @@ ! go list -m example.com/dep stderr 'go: conflicting replacements for example.com/dep@v1.0.0:\n\t./dep1\n\t./dep2\nuse "go mod editwork -replace example.com/dep@v1.0.0=\[override\]" to resolve' -go mod editwork -replace example.com/dep@v1.0.0=./dep1 +go work edit -replace example.com/dep@v1.0.0=./dep1 go list -m example.com/dep stdout 'example.com/dep v1.0.0 => ./dep1' -- GitLab From 955f9f56bf21dca045c042a2a8998a2fc04117a4 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 8 Nov 2021 13:13:30 -0800 Subject: [PATCH 2052/2500] test: add regress test for reported non-monomorphizable example Fixes #48711. Change-Id: I2ed1ef5267343d4b9f91da0618905098d178db90 Reviewed-on: https://go-review.googlesource.com/c/go/+/362394 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- test/typeparam/issue48711.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 test/typeparam/issue48711.go diff --git a/test/typeparam/issue48711.go b/test/typeparam/issue48711.go new file mode 100644 index 0000000000..d09a72e576 --- /dev/null +++ b/test/typeparam/issue48711.go @@ -0,0 +1,18 @@ +// errorcheck -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func f[T interface{ ~[]P }, P any](t T) { // ERROR "instantiation cycle" + if t == nil { + return + } + f[[]T, T]([]T{t}) +} + +func main() { + f[[]int](nil) +} -- GitLab From 67e22941dfe1555d8597e48f49ff86d3be340a36 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 8 Nov 2021 21:45:58 +0000 Subject: [PATCH 2053/2500] Revert "cmd/go: add workspace pruning mode" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts CL 357169. Reason for revert: appears to be failing on longtest SlowBot.¹ ¹https://storage.googleapis.com/go-build-log/a97c855b/linux-amd64-longtest_7c9857d4.log Change-Id: I3b94395671db78ed5fb2fb1019e7199e4ffbd272 Reviewed-on: https://go-review.googlesource.com/c/go/+/362249 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills Reviewed-by: Michael Matloob TryBot-Result: Go Bot --- src/cmd/go/internal/modload/buildlist.go | 86 ++++++----------------- src/cmd/go/internal/modload/init.go | 44 ++++++------ src/cmd/go/internal/modload/load.go | 24 +------ src/cmd/go/internal/modload/modfile.go | 14 ++-- src/cmd/go/testdata/script/work_prune.txt | 2 +- 5 files changed, 49 insertions(+), 121 deletions(-) diff --git a/src/cmd/go/internal/modload/buildlist.go b/src/cmd/go/internal/modload/buildlist.go index 9e56265a41..27cab0b9c8 100644 --- a/src/cmd/go/internal/modload/buildlist.go +++ b/src/cmd/go/internal/modload/buildlist.go @@ -38,17 +38,11 @@ type Requirements struct { // If pruned, the graph includes only the root modules, the explicit // requirements of those root modules, and the transitive requirements of only // the root modules that do not support pruning. - // - // If workspace, the graph includes only the workspace modules, the explicit - // requirements of the workspace modules, and the transitive requirements of - // the workspace modules that do not support pruning. pruning modPruning - // rootModules is the set of root modules of the graph, sorted and capped to - // length. It may contain duplicates, and may contain multiple versions for a - // given module path. The root modules of the groph are the set of main - // modules in workspace mode, and the main module's direct requirements - // outside workspace mode. + // rootModules is the set of module versions explicitly required by the main + // modules, sorted and capped to length. It may contain duplicates, and may + // contain multiple versions for a given module path. rootModules []module.Version maxRootVersion map[string]string @@ -105,19 +99,6 @@ var requirements *Requirements // If vendoring is in effect, the caller must invoke initVendor on the returned // *Requirements before any other method. func newRequirements(pruning modPruning, rootModules []module.Version, direct map[string]bool) *Requirements { - if pruning == workspace { - return &Requirements{ - pruning: pruning, - rootModules: capVersionSlice(rootModules), - maxRootVersion: nil, - direct: direct, - } - } - - if inWorkspaceMode() && pruning != workspace { - panic("in workspace mode, but pruning is not workspace in newRequirements") - } - for i, m := range rootModules { if m.Version == "" && MainModules.Contains(m.Path) { panic(fmt.Sprintf("newRequirements called with untrimmed build list: rootModules[%v] is a main module", i)) @@ -310,11 +291,13 @@ func readModGraph(ctx context.Context, pruning modPruning, roots []module.Versio g: mvs.NewGraph(cmpVersion, MainModules.Versions()), } ) - if pruning != workspace { - if inWorkspaceMode() { - panic("pruning is not workspace in workspace mode") - } - mg.g.Require(MainModules.mustGetSingleMainModule(), roots) + for _, m := range MainModules.Versions() { + // Require all roots from all main modules. + _ = TODOWorkspaces("This flattens a level of the module graph, adding the dependencies " + + "of all main modules to a single requirements struct, and losing the information of which " + + "main module required which requirement. Rework the requirements struct and change this" + + "to reflect the structure of the main modules.") + mg.g.Require(m, roots) } var ( @@ -369,13 +352,9 @@ func readModGraph(ctx context.Context, pruning modPruning, roots []module.Versio // are sufficient to build the packages it contains. We must load its full // transitive dependency graph to be sure that we see all relevant // dependencies. - if pruning != pruned || summary.pruning == unpruned { - nextPruning := summary.pruning - if pruning == unpruned { - nextPruning = unpruned - } + if pruning == unpruned || summary.pruning == unpruned { for _, r := range summary.require { - enqueue(r, nextPruning) + enqueue(r, unpruned) } } }) @@ -445,15 +424,12 @@ func (mg *ModuleGraph) findError() error { } func (mg *ModuleGraph) allRootsSelected() bool { - var roots []module.Version - if inWorkspaceMode() { - roots = MainModules.Versions() - } else { - roots, _ = mg.g.RequiredBy(MainModules.mustGetSingleMainModule()) - } - for _, m := range roots { - if mg.Selected(m.Path) != m.Version { - return false + for _, mm := range MainModules.Versions() { + roots, _ := mg.g.RequiredBy(mm) + for _, m := range roots { + if mg.Selected(m.Path) != m.Version { + return false + } } } return true @@ -600,29 +576,10 @@ func tidyRoots(ctx context.Context, rs *Requirements, pkgs []*loadPkg) (*Require } func updateRoots(ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version, rootsImported bool) (*Requirements, error) { - switch rs.pruning { - case unpruned: + if rs.pruning == unpruned { return updateUnprunedRoots(ctx, direct, rs, add) - case pruned: - return updatePrunedRoots(ctx, direct, rs, pkgs, add, rootsImported) - case workspace: - return updateWorkspaceRoots(ctx, rs, add) - default: - panic(fmt.Sprintf("unsupported pruning mode: %v", rs.pruning)) - } -} - -func updateWorkspaceRoots(ctx context.Context, rs *Requirements, add []module.Version) (*Requirements, error) { - if len(add) != 0 { - // add should be empty in workspace mode because a non-empty add slice means - // that there are missing roots in the current pruning mode or that the - // pruning mode is being changed. But the pruning mode should always be - // 'workspace' in workspace mode and the set of roots in workspace mode is - // always complete because it's the set of workspace modules, which can't - // be edited by loading. - panic("add is not empty") } - return rs, nil + return updatePrunedRoots(ctx, direct, rs, pkgs, add, rootsImported) } // tidyPrunedRoots returns a minimal set of root requirements that maintains the @@ -1199,6 +1156,7 @@ func updateUnprunedRoots(ctx context.Context, direct map[string]bool, rs *Requir } } + // TODO(matloob): Make roots into a map. var roots []module.Version for _, mainModule := range MainModules.Versions() { min, err := mvs.Req(mainModule, rootPaths, &mvsReqs{roots: keep}) @@ -1224,8 +1182,6 @@ func updateUnprunedRoots(ctx context.Context, direct map[string]bool, rs *Requir func convertPruning(ctx context.Context, rs *Requirements, pruning modPruning) (*Requirements, error) { if rs.pruning == pruning { return rs, nil - } else if rs.pruning == workspace || pruning == workspace { - panic("attempthing to convert to/from workspace pruning and another pruning type") } if pruning == unpruned { diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 512c9ebfbd..9aef5a7c33 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -704,7 +704,7 @@ func LoadModFile(ctx context.Context) *Requirements { } } - if MainModules.Index(mainModule).goVersionV == "" && rs.pruning != workspace { + if MainModules.Index(mainModule).goVersionV == "" { // TODO(#45551): Do something more principled instead of checking // cfg.CmdName directly here. if cfg.BuildMod == "mod" && cfg.CmdName != "mod graph" && cfg.CmdName != "mod why" { @@ -987,29 +987,29 @@ func makeMainModules(ms []module.Version, rootDirs []string, modFiles []*modfile // requirementsFromModFiles returns the set of non-excluded requirements from // the global modFile. func requirementsFromModFiles(ctx context.Context, modFiles []*modfile.File) *Requirements { - var roots []module.Version + rootCap := 0 + for i := range modFiles { + rootCap += len(modFiles[i].Require) + } + roots := make([]module.Version, 0, rootCap) + mPathCount := make(map[string]int) + for _, m := range MainModules.Versions() { + mPathCount[m.Path] = 1 + } direct := map[string]bool{} - var pruning modPruning - if inWorkspaceMode() { - pruning = workspace - roots = make([]module.Version, len(MainModules.Versions())) - copy(roots, MainModules.Versions()) - } else { - pruning = pruningForGoVersion(MainModules.GoVersion()) - if len(modFiles) != 1 { - panic(fmt.Errorf("requirementsFromModFiles called with %v modfiles outside workspace mode", len(modFiles))) - } - modFile := modFiles[0] - roots = make([]module.Version, 0, len(modFile.Require)) - mm := MainModules.mustGetSingleMainModule() + for _, modFile := range modFiles { + requirement: for _, r := range modFile.Require { - if index := MainModules.Index(mm); index != nil && index.exclude[r.Mod] { - if cfg.BuildMod == "mod" { - fmt.Fprintf(os.Stderr, "go: dropping requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version) - } else { - fmt.Fprintf(os.Stderr, "go: ignoring requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version) + // TODO(#45713): Maybe join + for _, mainModule := range MainModules.Versions() { + if index := MainModules.Index(mainModule); index != nil && index.exclude[r.Mod] { + if cfg.BuildMod == "mod" { + fmt.Fprintf(os.Stderr, "go: dropping requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version) + } else { + fmt.Fprintf(os.Stderr, "go: ignoring requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version) + } + continue requirement } - continue } roots = append(roots, r.Mod) @@ -1019,7 +1019,7 @@ func requirementsFromModFiles(ctx context.Context, modFiles []*modfile.File) *Re } } module.Sort(roots) - rs := newRequirements(pruning, roots, direct) + rs := newRequirements(pruningForGoVersion(MainModules.GoVersion()), roots, direct) return rs } diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index 83fcafead3..845bf2f8a2 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -1004,11 +1004,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader { } var err error - desiredPruning := pruningForGoVersion(ld.GoVersion) - if ld.requirements.pruning == workspace { - desiredPruning = workspace - } - ld.requirements, err = convertPruning(ctx, ld.requirements, desiredPruning) + ld.requirements, err = convertPruning(ctx, ld.requirements, pruningForGoVersion(ld.GoVersion)) if err != nil { ld.errorf("go: %v\n", err) } @@ -1250,24 +1246,6 @@ func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err err continue } - if inWorkspaceMode() { - // In workspace mode / workspace pruning mode, the roots are the main modules - // rather than the main module's direct dependencies. The check below on the selected - // roots does not apply. - if mg, err := rs.Graph(ctx); err != nil { - return false, err - } else if _, ok := mg.RequiredBy(dep.mod); !ok { - // dep.mod is not an explicit dependency, but needs to be. - // See comment on error returned below. - pkg.err = &DirectImportFromImplicitDependencyError{ - ImporterPath: pkg.path, - ImportedPath: dep.path, - Module: dep.mod, - } - } - continue - } - if pkg.err == nil && cfg.BuildMod != "mod" { if v, ok := rs.rootSelected(dep.mod.Path); !ok || v != dep.mod.Version { // dep.mod is not an explicit dependency, but needs to be. diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index 40e6ed787d..a7e92222a1 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -118,9 +118,8 @@ type requireMeta struct { type modPruning uint8 const ( - pruned modPruning = iota // transitive dependencies of modules at go 1.17 and higher are pruned out - unpruned // no transitive dependencies are pruned out - workspace // pruned to the union of modules in the workspace + pruned modPruning = iota // transitive dependencies of modules at go 1.17 and higher are pruned out + unpruned // no transitive dependencies are pruned out ) func pruningForGoVersion(goVersion string) modPruning { @@ -555,7 +554,7 @@ type retraction struct { // // The caller must not modify the returned summary. func goModSummary(m module.Version) (*modFileSummary, error) { - if m.Version == "" && !inWorkspaceMode() && MainModules.Contains(m.Path) { + if m.Version == "" && MainModules.Contains(m.Path) { panic("internal error: goModSummary called on a main module") } @@ -719,14 +718,9 @@ var rawGoModSummaryCache par.Cache // module.Version → rawGoModSummary result func rawGoModData(m module.Version) (name string, data []byte, err error) { if m.Version == "" { // m is a replacement module with only a file path. - dir := m.Path if !filepath.IsAbs(dir) { - if inWorkspaceMode() && MainModules.Contains(m.Path) { - dir = MainModules.ModRoot(m) - } else { - dir = filepath.Join(replaceRelativeTo(), dir) - } + dir = filepath.Join(replaceRelativeTo(), dir) } name = filepath.Join(dir, "go.mod") if gomodActual, ok := fsys.OverlayPath(name); ok { diff --git a/src/cmd/go/testdata/script/work_prune.txt b/src/cmd/go/testdata/script/work_prune.txt index 00c3e10663..f0fb073c4b 100644 --- a/src/cmd/go/testdata/script/work_prune.txt +++ b/src/cmd/go/testdata/script/work_prune.txt @@ -14,7 +14,7 @@ # TODO(#48331): We currently load the wrong version of q. Fix this. go list -m -f '{{.Version}}' example.com/q -stdout '^v1.1.0$' +stdout '^v1.0.0$' # TODO(#48331): This should be 1.1.0. Fix this. -- go.work -- go 1.18 -- GitLab From bee0c739007617c840ac29a6f8fcf9f24cbf1505 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Mon, 8 Nov 2021 13:08:58 +0700 Subject: [PATCH 2054/2500] cmd/compile: fix irgen mis-handling of ... argument when creating closure When bulding formal arguments of newly created closure, irgen forgets to set "..." field attribute, causing type mismatched between the closure function and the ONAME node represents that closure function. Fixes #49432 Change-Id: Ieddaa64980cdd3d8cea236a5a9de0204ee21ee39 Reviewed-on: https://go-review.googlesource.com/c/go/+/361961 Trust: Cuong Manh Le Trust: Dan Scales Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 1 + test/typeparam/issue49432.go | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 test/typeparam/issue49432.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 74281bc479..4ebd607c16 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -2085,6 +2085,7 @@ func startClosure(pos src.XPos, outer *ir.Func, typ *types.Type) (*ir.Func, []*t fn.Dcl = append(fn.Dcl, arg) f := types.NewField(pos, arg.Sym(), t) f.Nname = arg + f.SetIsDDD(typ.Params().Field(i).IsDDD()) formalParams = append(formalParams, f) } for i := 0; i < typ.NumResults(); i++ { diff --git a/test/typeparam/issue49432.go b/test/typeparam/issue49432.go new file mode 100644 index 0000000000..21d6ec4b70 --- /dev/null +++ b/test/typeparam/issue49432.go @@ -0,0 +1,22 @@ +// compile -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type Handler func(in ...interface{}) + +type Foo[T any] struct{} + +func (b *Foo[T]) Bar(in ...interface{}) {} + +func (b *Foo[T]) Init() { + _ = Handler(b.Bar) +} + +func main() { + c := &Foo[int]{} + c.Init() +} -- GitLab From 5344dcae4139de85b9e3d8cea81f9b65fc2bd25f Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Mon, 8 Nov 2021 15:51:05 +0700 Subject: [PATCH 2055/2500] cmd/compile: remove unneeded "==" method in pre-defined "comparable" interface Fixes #49421 Change-Id: Iecf3952346ecd278198c1000014a321e230f7fa7 Reviewed-on: https://go-review.googlesource.com/c/go/+/361962 Trust: Cuong Manh Le Trust: Dan Scales Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Dan Scales --- .../compile/internal/reflectdata/reflect.go | 6 ----- src/cmd/compile/internal/types/universe.go | 6 ++--- test/typeparam/issue49421.go | 27 +++++++++++++++++++ 3 files changed, 30 insertions(+), 9 deletions(-) create mode 100644 test/typeparam/issue49421.go diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index d396c249e4..4e20dbf29e 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -1304,12 +1304,6 @@ func writeITab(lsym *obj.LSym, typ, iface *types.Type) { break } } - if sigs[0].Sym.Name == "==" { - sigs = sigs[1:] - if len(sigs) == 0 { - break - } - } } if len(sigs) != 0 { base.Fatalf("incomplete itab") diff --git a/src/cmd/compile/internal/types/universe.go b/src/cmd/compile/internal/types/universe.go index d5239eb10c..13f62a3ab2 100644 --- a/src/cmd/compile/internal/types/universe.go +++ b/src/cmd/compile/internal/types/universe.go @@ -148,8 +148,8 @@ func makeErrorInterface() *Type { return NewInterface(NoPkg, []*Field{method}, false) } +// makeComparableInterface makes the the predefined "comparable" interface in the +// built-in package. It has a unique name, but no methods. func makeComparableInterface() *Type { - sig := NewSignature(NoPkg, FakeRecv(), nil, nil, nil) - method := NewField(src.NoXPos, LocalPkg.Lookup("=="), sig) - return NewInterface(NoPkg, []*Field{method}, false) + return NewInterface(NoPkg, nil, false) } diff --git a/test/typeparam/issue49421.go b/test/typeparam/issue49421.go new file mode 100644 index 0000000000..526e038bec --- /dev/null +++ b/test/typeparam/issue49421.go @@ -0,0 +1,27 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func main() { + var a, b foo + bar(a, b) +} + +type foo int + +func (a foo) less(b foo) bool { + return a < b +} + +type lesser[T any] interface { + less(T) bool + comparable +} + +func bar[T lesser[T]](a, b T) { + a.less(b) +} -- GitLab From 6dcf83d882a668894f4423045833e97f7e3c31cf Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Tue, 9 Nov 2021 01:23:02 +0100 Subject: [PATCH 2056/2500] runtime: revert recent Windows crashdump changes Recent changes to runtime enabled crashdumps, which under some circumstances apparently might result in memory being uploaded to Microsoft. A change like this should go through the proper proposals process where we can discuss how to gate it and what all of its implications are. This reverts CL 307372 and its cleanup CL 360617. Change-Id: If2e74015899d746831da40546c82eacacdf739e1 Reviewed-on: https://go-review.googlesource.com/c/go/+/362454 Trust: Jason A. Donenfeld Run-TryBot: Jason A. Donenfeld TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/runtime/os_windows.go | 4 -- src/runtime/panic.go | 11 ----- src/runtime/signal_windows.go | 87 +++++++++-------------------------- 3 files changed, 22 insertions(+), 80 deletions(-) diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go index 0e17e75e3e..648239fb36 100644 --- a/src/runtime/os_windows.go +++ b/src/runtime/os_windows.go @@ -40,7 +40,6 @@ const ( //go:cgo_import_dynamic runtime._LoadLibraryW LoadLibraryW%1 "kernel32.dll" //go:cgo_import_dynamic runtime._LoadLibraryA LoadLibraryA%1 "kernel32.dll" //go:cgo_import_dynamic runtime._PostQueuedCompletionStatus PostQueuedCompletionStatus%4 "kernel32.dll" -//go:cgo_import_dynamic runtime._RaiseException RaiseException%4 "kernel32.dll" //go:cgo_import_dynamic runtime._ResumeThread ResumeThread%1 "kernel32.dll" //go:cgo_import_dynamic runtime._SetConsoleCtrlHandler SetConsoleCtrlHandler%2 "kernel32.dll" //go:cgo_import_dynamic runtime._SetErrorMode SetErrorMode%1 "kernel32.dll" @@ -94,7 +93,6 @@ var ( _PostQueuedCompletionStatus, _QueryPerformanceCounter, _QueryPerformanceFrequency, - _RaiseException, _ResumeThread, _SetConsoleCtrlHandler, _SetErrorMode, @@ -122,7 +120,6 @@ var ( _AddVectoredContinueHandler, _LoadLibraryExA, _LoadLibraryExW, - _WerSetFlags, _ stdFunction // Use RtlGenRandom to generate cryptographically random data. @@ -257,7 +254,6 @@ func loadOptionalSyscalls() { _AddVectoredContinueHandler = windowsFindfunc(k32, []byte("AddVectoredContinueHandler\000")) _LoadLibraryExA = windowsFindfunc(k32, []byte("LoadLibraryExA\000")) _LoadLibraryExW = windowsFindfunc(k32, []byte("LoadLibraryExW\000")) - _WerSetFlags = windowsFindfunc(k32, []byte("WerSetFlags\000")) useLoadLibraryEx = (_LoadLibraryExW != nil && _LoadLibraryExA != nil && _AddDllDirectory != nil) var advapi32dll = []byte("advapi32.dll\000") diff --git a/src/runtime/panic.go b/src/runtime/panic.go index eec69dfdc6..3d5f4edb45 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -1002,11 +1002,6 @@ var runningPanicDefers uint32 // panicking is incremented and decremented atomically. var panicking uint32 -// tracebackprinted is zero before gopanic() prints the traceback. After -// traceback is printed, it sets to 1 so that the subsequent exception handler -// won't print the traceback again. -var tracebackprinted uint32 - // paniclk is held while printing the panic information and stack trace, // so that two concurrent panics don't overlap their output. var paniclk mutex @@ -1050,9 +1045,6 @@ func fatalthrow() { startpanic_m() if dopanic_m(gp, pc, sp) { - // At this point, traceback has already been printed. - // Set tracebackprinted to 1 to avoid printing traceback again - tracebackprinted = 1 // crash uses a decent amount of nosplit stack and we're already // low on stack in throw, so crash on the system stack (unlike // fatalpanic). @@ -1094,9 +1086,6 @@ func fatalpanic(msgs *_panic) { }) if docrash { - // At this point, traceback has already been printed. - // Set tracebackprinted to 1 to avoid printing traceback again - tracebackprinted = 1 // By crashing outside the above systemstack call, debuggers // will not be confused when generating a backtrace. // Function crash is marked nosplit to avoid stack growth. diff --git a/src/runtime/signal_windows.go b/src/runtime/signal_windows.go index b036f3c965..16c36d07f1 100644 --- a/src/runtime/signal_windows.go +++ b/src/runtime/signal_windows.go @@ -22,38 +22,6 @@ func disableWER() { stdcall1(_SetErrorMode, uintptr(errormode)|SEM_FAILCRITICALERRORS|SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX) } -// isWin7 returns true on Windows 7. Otherwise it returns false. -// -//go:nosplit -func isWin7() bool { - var maj, min, build uint32 - stdcall3(_RtlGetNtVersionNumbers, uintptr(unsafe.Pointer(&maj)), uintptr(unsafe.Pointer(&min)), uintptr(unsafe.Pointer(&build))) - return maj < 6 || (maj == 6 && min <= 1) -} - -// enableWERNoUI re-enables Windows error reporting without fault reporting UI. -// -// This is marked nosplit since it is used during crash. -// -//go:nosplit -func enableWERNoUI() bool { - if _WerSetFlags == nil { - return false - } - - // Disable Fault reporting UI - const ( - WER_FAULT_REPORTING_NO_UI = 0x0020 - ) - if stdcall1(_WerSetFlags, WER_FAULT_REPORTING_NO_UI) != 0 { - return false - } - - // re-enable Windows Error Reporting - stdcall1(_SetErrorMode, 0) - return true -} - // in sys_windows_386.s and sys_windows_amd64.s func exceptiontramp() func firstcontinuetramp() @@ -140,7 +108,6 @@ func exceptionhandler(info *exceptionrecord, r *context, gp *g) int32 { // Don't go through any more of the Windows handler chain. // Crash now. winthrow(info, r, gp) - exit(2) } // After this point, it is safe to grow the stack. @@ -229,20 +196,6 @@ func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 { } winthrow(info, r, gp) - - _, _, docrash := gotraceback() - if docrash { - // Windows 7 apears to ignore WER_FAULT_REPORTING_NO_UI - // WerSetFlags API flag. So do not call enableWERNoUI - // on Windows 7. - if !isWin7() { - // trigger crash dump creation - if enableWERNoUI() { - return _EXCEPTION_CONTINUE_SEARCH - } - } - } - exit(2) return 0 // not reached } @@ -250,6 +203,11 @@ func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 { func winthrow(info *exceptionrecord, r *context, gp *g) { _g_ := getg() + if panicking != 0 { // traceback already printed + exit(2) + } + panicking = 1 + // In case we're handling a g0 stack overflow, blow away the // g0 stack bounds so we have room to print the traceback. If // this somehow overflows the stack, the OS will trap it. @@ -271,16 +229,18 @@ func winthrow(info *exceptionrecord, r *context, gp *g) { _g_.m.throwing = 1 _g_.m.caughtsig.set(gp) - level, _, _ := gotraceback() + level, _, docrash := gotraceback() if level > 0 { - // only print traceback when it hasn't been printed - if tracebackprinted == 0 { - tracebacktrap(r.ip(), r.sp(), r.lr(), gp) - tracebackothers(gp) - tracebackprinted = 1 - } + tracebacktrap(r.ip(), r.sp(), r.lr(), gp) + tracebackothers(gp) dumpregs(r) } + + if docrash { + crash() + } + + exit(2) } func sigpanic() { @@ -352,17 +312,14 @@ func signame(sig uint32) string { //go:nosplit func crash() { - // When GOTRACEBACK==crash, raise the same exception - // from kernel32.dll, so that Windows gets a chance - // to handle the exception by creating a crash dump. - - // Get the Exception code that caused the crash - gp := getg() - exceptionCode := gp.sig - - // RaiseException() here will not be handled in exceptionhandler() - // because it comes from kernel32.dll - stdcall4(_RaiseException, uintptr(unsafe.Pointer(&exceptionCode)), 0, 0, 0) + // TODO: This routine should do whatever is needed + // to make the Windows program abort/crash as it + // would if Go was not intercepting signals. + // On Unix the routine would remove the custom signal + // handler and then raise a signal (like SIGABRT). + // Something like that should happen here. + // It's okay to leave this empty for now: if crash returns + // the ordinary exit-after-panic happens. } // gsignalStack is unused on Windows. -- GitLab From b7529c3617a64ed5d1e2a6c7a9366d4a4988a38d Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Tue, 9 Nov 2021 10:37:43 +0700 Subject: [PATCH 2057/2500] cmd/go: fix mod_get_direct https://github.com/googleapis/google-cloud-go has changed the default branch from master to main, causing mod_get_direct failed on longtest. Change-Id: I8fe0356b2ff532d1fdedbcb1e1832d7335babaa0 Reviewed-on: https://go-review.googlesource.com/c/go/+/361965 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/testdata/script/mod_get_direct.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/go/testdata/script/mod_get_direct.txt b/src/cmd/go/testdata/script/mod_get_direct.txt index 42ccbcd38a..856e05bc32 100644 --- a/src/cmd/go/testdata/script/mod_get_direct.txt +++ b/src/cmd/go/testdata/script/mod_get_direct.txt @@ -10,7 +10,7 @@ env GO111MODULE=on env GOPROXY=direct env GOSUMDB=off -go list -m cloud.google.com/go@master +go list -m cloud.google.com/go@main ! stdout 'v0.0.0-' -- go.mod -- -- GitLab From 2559a98a3cda46084cbdd3ea49217fdc8074ce7a Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Mon, 8 Nov 2021 12:13:01 -0500 Subject: [PATCH 2058/2500] testing: remove package from fuzz crasher message Fixes #48149 Change-Id: Iaf91d2c54fda809c7da90cdfb6d1d075f474c69b Reviewed-on: https://go-review.googlesource.com/c/go/+/362116 Trust: Katie Hockman Run-TryBot: Katie Hockman Reviewed-by: Bryan C. Mills Reviewed-by: Julie Qiu --- src/testing/fuzz.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 10665168f4..46c9d63df4 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -356,7 +356,7 @@ func (f *F) Fuzz(ff interface{}) { crashPath := crashErr.CrashPath() fmt.Fprintf(f.w, "Crash written to %s\n", crashPath) testName := filepath.Base(crashPath) - fmt.Fprintf(f.w, "To re-run:\ngo test %s -run=%s/%s\n", f.fuzzContext.deps.ImportPath(), f.name, testName) + fmt.Fprintf(f.w, "To re-run:\ngo test -run=%s/%s\n", f.name, testName) } } // TODO(jayconrod,katiehockman): Aggregate statistics across workers -- GitLab From e90fd9a597c03b993f900e4b1997de67b12bb4f3 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 8 Nov 2021 13:09:41 -0500 Subject: [PATCH 2059/2500] go/types: rename isX predicates to allX, add simple is_X (step 1 of 2) This is a port of CL 360955 to go/types. Note that go/types and types2 differ in handling of untyped nil within both Checker.shift and Checker.implicitTypeAndValue. A missing comment was added to Checker.indexExpr. Change-Id: Ia9149ff9c0af68213c579090902ab7989828ddd2 Reviewed-on: https://go-review.googlesource.com/c/go/+/362534 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/builtins.go | 14 +++--- src/go/types/check.go | 6 +-- src/go/types/conversions.go | 12 ++--- src/go/types/expr.go | 94 ++++++++++++++++++------------------- src/go/types/index.go | 9 ++-- src/go/types/predicates.go | 66 +++++++++++++++++--------- src/go/types/sizes.go | 2 +- src/go/types/stmt.go | 8 ++-- src/go/types/typexpr.go | 2 +- 9 files changed, 117 insertions(+), 96 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index aefac786ca..0390ac0192 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -102,7 +102,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b if x.mode == invalid { return } - if isString(x.typ) { + if allString(x.typ) { if check.Types != nil { sig := makeSig(S, S, x.typ) sig.variadic = true @@ -147,7 +147,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b var val constant.Value switch typ = arrayPtrDeref(under(x.typ)); t := typ.(type) { case *Basic: - if isString(t) && id == _Len { + if is_String(t) && id == _Len { if x.mode == constant_ { mode = constant_ val = constant.MakeInt64(int64(len(constant.StringVal(x.val)))) @@ -183,7 +183,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b if t.underIs(func(t Type) bool { switch t := arrayPtrDeref(t).(type) { case *Basic: - if isString(t) && id == _Len { + if is_String(t) && id == _Len { return true } case *Array, *Slice, *Chan: @@ -272,7 +272,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // because shifts of floats are not permitted) if x.mode == constant_ && y.mode == constant_ { toFloat := func(x *operand) { - if isNumeric(x.typ) && constant.Sign(constant.Imag(x.val)) == 0 { + if is_Numeric(x.typ) && constant.Sign(constant.Imag(x.val)) == 0 { x.typ = Typ[UntypedFloat] } } @@ -403,7 +403,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b if x.mode == constant_ { // an untyped constant number can always be considered // as a complex constant - if isNumeric(x.typ) { + if is_Numeric(x.typ) { x.typ = Typ[UntypedComplex] } } else { @@ -735,7 +735,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // assert(pred) causes a typechecker error if pred is false. // The result of assert is the value of pred if there is no error. // Note: assert is only available in self-test mode. - if x.mode != constant_ || !isBoolean(x.typ) { + if x.mode != constant_ || !is_Boolean(x.typ) { check.invalidArg(x, _Test, "%s is not a boolean constant", x) return } @@ -801,7 +801,7 @@ func structure(typ Type) Type { func structureString(typ Type) Type { var su Type if underIs(typ, func(u Type) bool { - if isString(u) { + if is_String(u) { u = NewSlice(universeByte) } if su != nil && !Identical(su, u) { diff --git a/src/go/types/check.go b/src/go/types/check.go index 3a0e4a6a23..c828cf54e4 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -419,9 +419,9 @@ func (check *Checker) recordTypeAndValue(x ast.Expr, mode operandMode, typ Type, } if mode == constant_ { assert(val != nil) - // We check is(typ, IsConstType) here as constant expressions may be + // We check allBasic(typ, IsConstType) here as constant expressions may be // recorded as type parameters. - assert(typ == Typ[Invalid] || is(typ, IsConstType)) + assert(typ == Typ[Invalid] || allBasic(typ, IsConstType)) } if m := check.Types; m != nil { m[x] = TypeAndValue{mode, typ, val} @@ -451,7 +451,7 @@ func (check *Checker) recordCommaOkTypes(x ast.Expr, a [2]Type) { if a[0] == nil || a[1] == nil { return } - assert(isTyped(a[0]) && isTyped(a[1]) && (isBoolean(a[1]) || a[1] == universeError)) + assert(isTyped(a[0]) && isTyped(a[1]) && (is_Boolean(a[1]) || a[1] == universeError)) if m := check.Types; m != nil { for { tv := m[x] diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go index a6f0714ba0..c99bd6332a 100644 --- a/src/go/types/conversions.go +++ b/src/go/types/conversions.go @@ -22,7 +22,7 @@ func (check *Checker) conversion(x *operand, T Type) { // nothing to do case representableConst(x.val, check, t, val): return true - case isInteger(x.typ) && isString(t): + case is_Integer(x.typ) && is_String(t): codepoint := unicode.ReplacementChar if i, ok := constant.Uint64Val(x.val); ok && i <= unicode.MaxRune { codepoint = rune(i) @@ -91,7 +91,7 @@ func (check *Checker) conversion(x *operand, T Type) { // (See also the TODO below.) if IsInterface(T) || constArg && !isConstType(T) || x.isNil() { final = Default(x.typ) // default type of untyped nil is untyped nil - } else if isInteger(x.typ) && isString(T) { + } else if is_Integer(x.typ) && allString(T) { final = x.typ } check.updateExprType(x.expr, final, true) @@ -195,22 +195,22 @@ func convertibleToImpl(check *Checker, V, T Type, cause *string) bool { } // "V and T are both integer or floating point types" - if isIntegerOrFloat(V) && isIntegerOrFloat(T) { + if is_IntegerOrFloat(V) && is_IntegerOrFloat(T) { return true } // "V and T are both complex types" - if isComplex(V) && isComplex(T) { + if is_Complex(V) && is_Complex(T) { return true } // "V is an integer or a slice of bytes or runes and T is a string type" - if (isInteger(V) || isBytesOrRunes(Vu)) && isString(T) { + if (is_Integer(V) || isBytesOrRunes(Vu)) && is_String(T) { return true } // "V is a string and T is a slice of bytes or runes" - if isString(V) && isBytesOrRunes(Tu) { + if is_String(V) && isBytesOrRunes(Tu) { return true } diff --git a/src/go/types/expr.go b/src/go/types/expr.go index d4de212e06..cdb18eb963 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -64,10 +64,10 @@ var unaryOpPredicates opPredicates func init() { // Setting unaryOpPredicates in init avoids declaration cycles. unaryOpPredicates = opPredicates{ - token.ADD: isNumeric, - token.SUB: isNumeric, - token.XOR: isInteger, - token.NOT: isBoolean, + token.ADD: allNumeric, + token.SUB: allNumeric, + token.XOR: allInteger, + token.NOT: allBoolean, } } @@ -212,7 +212,7 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr) { return } var prec uint - if isUnsigned(x.typ) { + if is_Unsigned(x.typ) { prec = uint(check.conf.sizeof(x.typ) * 8) } x.val = constant.UnaryOp(e.Op, x.val, prec) @@ -289,7 +289,7 @@ func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *c } switch { - case isInteger(typ): + case is_Integer(typ): x := constant.ToInt(x) if x.Kind() != constant.Int { return false @@ -344,7 +344,7 @@ func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *c return true } - case isFloat(typ): + case is_Float(typ): x := constant.ToFloat(x) if x.Kind() != constant.Float { return false @@ -374,7 +374,7 @@ func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *c unreachable() } - case isComplex(typ): + case is_Complex(typ): x := constant.ToComplex(x) if x.Kind() != constant.Complex { return false @@ -406,10 +406,10 @@ func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *c unreachable() } - case isString(typ): + case is_String(typ): return x.Kind() == constant.String - case isBoolean(typ): + case is_Boolean(typ): return x.Kind() == constant.Bool } @@ -437,7 +437,7 @@ func (check *Checker) representation(x *operand, typ *Basic) (constant.Value, er assert(x.mode == constant_) v := x.val if !representableConst(x.val, check, typ, &v) { - if isNumeric(x.typ) && isNumeric(typ) { + if is_Numeric(x.typ) && is_Numeric(typ) { // numeric conversion : error msg // // integer -> integer : overflows @@ -445,7 +445,7 @@ func (check *Checker) representation(x *operand, typ *Basic) (constant.Value, er // float -> integer : truncated // float -> float : overflows // - if !isInteger(x.typ) && isInteger(typ) { + if !is_Integer(x.typ) && is_Integer(typ) { return nil, _TruncatedFloat } else { return nil, _NumericOverflow @@ -569,7 +569,7 @@ func (check *Checker) updateExprType(x ast.Expr, typ Type, final bool) { // If x is the lhs of a shift, its final type must be integer. // We already know from the shift check that it is representable // as an integer if it is a constant. - if !isInteger(typ) { + if !is_Integer(typ) { check.invalidOp(x, _InvalidShiftOperand, "shifted operand %s (type %s) must be integer", x, typ) return } @@ -631,7 +631,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const // both x and target are untyped xkind := x.typ.(*Basic).kind tkind := target.(*Basic).kind - if isNumeric(x.typ) && isNumeric(target) { + if is_Numeric(x.typ) && is_Numeric(target) { if xkind < tkind { return target, nil, 0 } @@ -641,10 +641,10 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const return x.typ, nil, 0 } - switch t := under(target).(type) { + switch u := under(target).(type) { case *Basic: if x.mode == constant_ { - v, code := check.representation(x, t) + v, code := check.representation(x, u) if code != 0 { return nil, nil, code } @@ -656,18 +656,18 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const // the value nil. switch x.typ.(*Basic).kind { case UntypedBool: - if !isBoolean(target) { + if !is_Boolean(target) { return nil, nil, _InvalidUntypedConversion } case UntypedInt, UntypedRune, UntypedFloat, UntypedComplex: - if !isNumeric(target) { + if !is_Numeric(target) { return nil, nil, _InvalidUntypedConversion } case UntypedString: // Non-constant untyped string values are not permitted by the spec and // should not occur during normal typechecking passes, but this path is // reachable via the AssignableTo API. - if !isString(target) { + if !is_String(target) { return nil, nil, _InvalidUntypedConversion } case UntypedNil: @@ -682,7 +682,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const } case *TypeParam: // TODO(gri) review this code - doesn't look quite right - ok := t.underIs(func(t Type) bool { + ok := u.underIs(func(t Type) bool { target, _, _ := check.implicitTypeAndValue(x, t) return target != nil }) @@ -702,7 +702,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const return Typ[UntypedNil], nil, 0 } // cannot assign untyped values to non-empty interfaces - if !t.Empty() { + if !u.Empty() { return nil, nil, _InvalidUntypedConversion } return Default(x.typ), nil, 0 @@ -733,7 +733,7 @@ func (check *Checker) comparison(x, y *operand, op token.Token) { defined = Comparable(x.typ) && Comparable(y.typ) || x.isNil() && hasNil(y.typ) || y.isNil() && hasNil(x.typ) case token.LSS, token.LEQ, token.GTR, token.GEQ: // spec: The ordering operators <, <=, >, and >= apply to operands that are ordered." - defined = isOrdered(x.typ) && isOrdered(y.typ) + defined = allOrdered(x.typ) && allOrdered(y.typ) default: unreachable() } @@ -784,7 +784,7 @@ func (check *Checker) shift(x, y *operand, e ast.Expr, op token.Token) { xval = constant.ToInt(x.val) } - if isInteger(x.typ) || isUntyped(x.typ) && xval != nil && xval.Kind() == constant.Int { + if allInteger(x.typ) || isUntyped(x.typ) && xval != nil && xval.Kind() == constant.Int { // The lhs is of integer type or an untyped constant representable // as an integer. Nothing to do. } else { @@ -810,7 +810,7 @@ func (check *Checker) shift(x, y *operand, e ast.Expr, op token.Token) { if isUntyped(y.typ) { // Caution: Check for representability here, rather than in the switch - // below, because isInteger includes untyped integers (was bug #43697). + // below, because is_Integer includes untyped integers (was bug #43697). check.representable(y, Typ[Uint]) if y.mode == invalid { x.mode = invalid @@ -821,8 +821,8 @@ func (check *Checker) shift(x, y *operand, e ast.Expr, op token.Token) { // Check that RHS is otherwise at least of integer type. switch { - case isInteger(y.typ): - if !isUnsigned(y.typ) && !check.allowVersion(check.pkg, 1, 13) { + case allInteger(y.typ): + if !allUnsigned(y.typ) && !check.allowVersion(check.pkg, 1, 13) { check.invalidOp(y, _InvalidShiftCount, "signed shift count %s requires go1.13 or later", y) x.mode = invalid return @@ -847,7 +847,7 @@ func (check *Checker) shift(x, y *operand, e ast.Expr, op token.Token) { if x.val.Kind() == constant.Unknown || y.val.Kind() == constant.Unknown { x.val = constant.MakeUnknown() // ensure the correct type - see comment below - if !isInteger(x.typ) { + if !is_Integer(x.typ) { x.typ = Typ[UntypedInt] } return @@ -864,7 +864,7 @@ func (check *Checker) shift(x, y *operand, e ast.Expr, op token.Token) { // (e.g., 2.0, an untyped float) - this can only happen for untyped // non-integer numeric constants. Correct the type so that the shift // result is of integer type. - if !isInteger(x.typ) { + if !is_Integer(x.typ) { x.typ = Typ[UntypedInt] } // x is a constant so xval != nil and it must be of Int kind. @@ -910,7 +910,7 @@ func (check *Checker) shift(x, y *operand, e ast.Expr, op token.Token) { } // non-constant shift - lhs must be an integer - if !isInteger(x.typ) { + if !allInteger(x.typ) { check.invalidOp(x, _InvalidShiftOperand, "shifted operand %s must be integer", x) x.mode = invalid return @@ -924,19 +924,19 @@ var binaryOpPredicates opPredicates func init() { // Setting binaryOpPredicates in init avoids declaration cycles. binaryOpPredicates = opPredicates{ - token.ADD: isNumericOrString, - token.SUB: isNumeric, - token.MUL: isNumeric, - token.QUO: isNumeric, - token.REM: isInteger, - - token.AND: isInteger, - token.OR: isInteger, - token.XOR: isInteger, - token.AND_NOT: isInteger, - - token.LAND: isBoolean, - token.LOR: isBoolean, + token.ADD: allNumericOrString, + token.SUB: allNumeric, + token.MUL: allNumeric, + token.QUO: allNumeric, + token.REM: allInteger, + + token.AND: allInteger, + token.OR: allInteger, + token.XOR: allInteger, + token.AND_NOT: allInteger, + + token.LAND: allBoolean, + token.LOR: allBoolean, } } @@ -966,10 +966,10 @@ func (check *Checker) binary(x *operand, e ast.Expr, lhs, rhs ast.Expr, op token if IsInterface(x.typ) || IsInterface(y.typ) { return true } - if isBoolean(x.typ) != isBoolean(y.typ) { + if allBoolean(x.typ) != allBoolean(y.typ) { return false } - if isString(x.typ) != isString(y.typ) { + if allString(x.typ) != allString(y.typ) { return false } if x.isNil() && !hasNil(y.typ) { @@ -1022,14 +1022,14 @@ func (check *Checker) binary(x *operand, e ast.Expr, lhs, rhs ast.Expr, op token if op == token.QUO || op == token.REM { // check for zero divisor - if (x.mode == constant_ || isInteger(x.typ)) && y.mode == constant_ && constant.Sign(y.val) == 0 { + if (x.mode == constant_ || allInteger(x.typ)) && y.mode == constant_ && constant.Sign(y.val) == 0 { check.invalidOp(&y, _DivByZero, "division by zero") x.mode = invalid return } // check for divisor underflow in complex division (see issue 20227) - if x.mode == constant_ && y.mode == constant_ && isComplex(x.typ) { + if x.mode == constant_ && y.mode == constant_ && is_Complex(x.typ) { re, im := constant.Real(y.val), constant.Imag(y.val) re2, im2 := constant.BinaryOp(re, token.MUL, re), constant.BinaryOp(im, token.MUL, im) if constant.Sign(re2) == 0 && constant.Sign(im2) == 0 { @@ -1048,7 +1048,7 @@ func (check *Checker) binary(x *operand, e ast.Expr, lhs, rhs ast.Expr, op token return } // force integer division of integer operands - if op == token.QUO && isInteger(x.typ) { + if op == token.QUO && is_Integer(x.typ) { op = token.QUO_ASSIGN } x.val = constant.BinaryOp(x.val, op, y.val) diff --git a/src/go/types/index.go b/src/go/types/index.go index a85d314efa..5d35458011 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -47,11 +47,12 @@ func (check *Checker) indexExpr(x *operand, e *typeparams.IndexExpr) (isFuncInst return false } + // ordinary index expression valid := false length := int64(-1) // valid if >= 0 switch typ := under(x.typ).(type) { case *Basic: - if isString(typ) { + if is_String(typ) { valid = true if x.mode == constant_ { length = int64(len(constant.StringVal(x.val))) @@ -109,7 +110,7 @@ func (check *Checker) indexExpr(x *operand, e *typeparams.IndexExpr) (isFuncInst var k, e Type // k is only set for maps switch t := u.(type) { case *Basic: - if isString(t) { + if is_String(t) { e = universeByte mode = value } @@ -217,7 +218,7 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { return case *Basic: - if isString(u) { + if is_String(u) { if e.Slice3 { check.invalidOp(x, _InvalidSliceExpr, "3-index slice of string") x.mode = invalid @@ -372,7 +373,7 @@ func (check *Checker) isValidIndex(x *operand, code errorCode, what string, allo } // spec: "the index x must be of integer type or an untyped constant" - if !isInteger(x.typ) { + if !allInteger(x.typ) { check.invalidArg(x, code, "%s %s must be integer", what, x) return false } diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 3c76d15c79..4ca962e77e 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -27,33 +27,55 @@ func isGeneric(typ Type) bool { return named != nil && named.obj != nil && named.targs == nil && named.TypeParams() != nil } -func is(typ Type, what BasicInfo) bool { - switch t := under(typ).(type) { +// The is_X predicates below report whether t is an X. +// If t is a type parameter the result is false; i.e., +// these predicates don't look inside a type parameter. + +func is_Boolean(t Type) bool { return isBasic(t, IsBoolean) } +func is_Integer(t Type) bool { return isBasic(t, IsInteger) } +func is_Unsigned(t Type) bool { return isBasic(t, IsUnsigned) } +func is_Float(t Type) bool { return isBasic(t, IsFloat) } +func is_Complex(t Type) bool { return isBasic(t, IsComplex) } +func is_Numeric(t Type) bool { return isBasic(t, IsNumeric) } +func is_String(t Type) bool { return isBasic(t, IsString) } +func is_IntegerOrFloat(t Type) bool { return isBasic(t, IsInteger|IsFloat) } + +// isBasic reports whether under(t) is a basic type with the specified info. +// If t is a type parameter the result is false; i.e., +// isBasic does not look inside a type parameter. +func isBasic(t Type, info BasicInfo) bool { + u, _ := under(t).(*Basic) + return u != nil && u.info&info != 0 +} + +// The allX predicates below report whether t is an X. +// If t is a type parameter the result is true if is_X is true +// for all specified types of the type parameter's type set. +// allX is an optimized version of is_X(structure(t)) (which +// is the same as underIs(t, is_X)). + +func allBoolean(typ Type) bool { return allBasic(typ, IsBoolean) } +func allInteger(typ Type) bool { return allBasic(typ, IsInteger) } +func allUnsigned(typ Type) bool { return allBasic(typ, IsUnsigned) } +func allNumeric(typ Type) bool { return allBasic(typ, IsNumeric) } +func allString(typ Type) bool { return allBasic(typ, IsString) } +func allOrdered(typ Type) bool { return allBasic(typ, IsOrdered) } +func allNumericOrString(typ Type) bool { return allBasic(typ, IsNumeric|IsString) } + +// allBasic reports whether under(t) is a basic type with the specified info. +// If t is a type parameter, the result is true if isBasic(t, info) is true +// for all specific types of the type parameter's type set. +// allBasic(t, info) is an optimized version of isBasic(structure(t), info). +func allBasic(t Type, info BasicInfo) bool { + switch u := under(t).(type) { case *Basic: - return t.info&what != 0 + return u.info&info != 0 case *TypeParam: - return t.underIs(func(typ Type) bool { return is(typ, what) }) + return u.is(func(t *term) bool { return t != nil && isBasic(t.typ, info) }) } return false } -func isBoolean(typ Type) bool { return is(typ, IsBoolean) } -func isInteger(typ Type) bool { return is(typ, IsInteger) } -func isUnsigned(typ Type) bool { return is(typ, IsUnsigned) } -func isFloat(typ Type) bool { return is(typ, IsFloat) } -func isComplex(typ Type) bool { return is(typ, IsComplex) } -func isNumeric(typ Type) bool { return is(typ, IsNumeric) } -func isString(typ Type) bool { return is(typ, IsString) } - -// Note that if typ is a type parameter, isInteger(typ) || isFloat(typ) does not -// produce the expected result because a type set that contains both an integer -// and a floating-point type is neither (all) integers, nor (all) floats. -// Use isIntegerOrFloat instead. -func isIntegerOrFloat(typ Type) bool { return is(typ, IsInteger|IsFloat) } - -// isNumericOrString is the equivalent of isIntegerOrFloat for isNumeric(typ) || isString(typ). -func isNumericOrString(typ Type) bool { return is(typ, IsNumeric|IsString) } - // isTyped reports whether typ is typed; i.e., not an untyped // constant or boolean. isTyped may be called with types that // are not fully set up. @@ -69,8 +91,6 @@ func isUntyped(typ Type) bool { return !isTyped(typ) } -func isOrdered(typ Type) bool { return is(typ, IsOrdered) } - func isConstType(typ Type) bool { // Type parameters are never const types. t := asBasic(typ) diff --git a/src/go/types/sizes.go b/src/go/types/sizes.go index 4c85bfe057..badba82cfa 100644 --- a/src/go/types/sizes.go +++ b/src/go/types/sizes.go @@ -82,7 +82,7 @@ func (s *StdSizes) Alignof(T Type) int64 { return 1 } // complex{64,128} are aligned like [2]float{32,64}. - if isComplex(T) { + if is_Complex(T) { a /= 2 } if a > s.MaxAlign { diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index cc4eceae5d..6e69646455 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -456,7 +456,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { if x.mode == invalid { return } - if !isNumeric(x.typ) { + if !allNumeric(x.typ) { check.invalidOp(s.X, _NonNumericIncDec, "%s%s (non-numeric type %s)", s.X, s.Tok, x.typ) return } @@ -572,7 +572,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { check.simpleStmt(s.Init) var x operand check.expr(&x, s.Cond) - if x.mode != invalid && !isBoolean(x.typ) { + if x.mode != invalid && !allBoolean(x.typ) { check.error(s.Cond, _InvalidCond, "non-boolean condition in if statement") } check.stmt(inner, s.Body) @@ -804,7 +804,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { if s.Cond != nil { var x operand check.expr(&x, s.Cond) - if x.mode != invalid && !isBoolean(x.typ) { + if x.mode != invalid && !allBoolean(x.typ) { check.error(s.Cond, _InvalidCond, "non-boolean condition in for statement") } } @@ -944,7 +944,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { func rangeKeyVal(typ Type) (key, val Type) { switch typ := arrayPtrDeref(typ).(type) { case *Basic: - if isString(typ) { + if is_String(typ) { return Typ[Int], universeRune // use 'rune' name } case *Array: diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index e1d942a5c6..30e817f416 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -489,7 +489,7 @@ func (check *Checker) arrayLength(e ast.Expr) int64 { return -1 } - if isUntyped(x.typ) || isInteger(x.typ) { + if isUntyped(x.typ) || is_Integer(x.typ) { if val := constant.ToInt(x.val); val.Kind() == constant.Int { if representableConst(val, check, Typ[Int], nil) { if n, ok := constant.Int64Val(val); ok && n >= 0 { -- GitLab From 2ade8ae325e6410f9696f431e6c50479216e63ae Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 9 Nov 2021 10:20:50 -0500 Subject: [PATCH 2060/2500] go/types: rename is_X predicates back to isX (step 2 of 2) This is a port of CL 361134 to go/types. Change-Id: Ibac4365a85561b32a90b0118d48aa9302f227b2e Reviewed-on: https://go-review.googlesource.com/c/go/+/362554 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/builtins.go | 12 ++++++------ src/go/types/check.go | 2 +- src/go/types/conversions.go | 12 ++++++------ src/go/types/expr.go | 36 ++++++++++++++++++------------------ src/go/types/index.go | 6 +++--- src/go/types/predicates.go | 24 ++++++++++++------------ src/go/types/sizes.go | 2 +- src/go/types/stmt.go | 2 +- src/go/types/typexpr.go | 2 +- 9 files changed, 49 insertions(+), 49 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 0390ac0192..577a71fd60 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -147,7 +147,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b var val constant.Value switch typ = arrayPtrDeref(under(x.typ)); t := typ.(type) { case *Basic: - if is_String(t) && id == _Len { + if isString(t) && id == _Len { if x.mode == constant_ { mode = constant_ val = constant.MakeInt64(int64(len(constant.StringVal(x.val)))) @@ -183,7 +183,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b if t.underIs(func(t Type) bool { switch t := arrayPtrDeref(t).(type) { case *Basic: - if is_String(t) && id == _Len { + if isString(t) && id == _Len { return true } case *Array, *Slice, *Chan: @@ -272,7 +272,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // because shifts of floats are not permitted) if x.mode == constant_ && y.mode == constant_ { toFloat := func(x *operand) { - if is_Numeric(x.typ) && constant.Sign(constant.Imag(x.val)) == 0 { + if isNumeric(x.typ) && constant.Sign(constant.Imag(x.val)) == 0 { x.typ = Typ[UntypedFloat] } } @@ -403,7 +403,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b if x.mode == constant_ { // an untyped constant number can always be considered // as a complex constant - if is_Numeric(x.typ) { + if isNumeric(x.typ) { x.typ = Typ[UntypedComplex] } } else { @@ -735,7 +735,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // assert(pred) causes a typechecker error if pred is false. // The result of assert is the value of pred if there is no error. // Note: assert is only available in self-test mode. - if x.mode != constant_ || !is_Boolean(x.typ) { + if x.mode != constant_ || !isBoolean(x.typ) { check.invalidArg(x, _Test, "%s is not a boolean constant", x) return } @@ -801,7 +801,7 @@ func structure(typ Type) Type { func structureString(typ Type) Type { var su Type if underIs(typ, func(u Type) bool { - if is_String(u) { + if isString(u) { u = NewSlice(universeByte) } if su != nil && !Identical(su, u) { diff --git a/src/go/types/check.go b/src/go/types/check.go index c828cf54e4..1d55fb4342 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -451,7 +451,7 @@ func (check *Checker) recordCommaOkTypes(x ast.Expr, a [2]Type) { if a[0] == nil || a[1] == nil { return } - assert(isTyped(a[0]) && isTyped(a[1]) && (is_Boolean(a[1]) || a[1] == universeError)) + assert(isTyped(a[0]) && isTyped(a[1]) && (isBoolean(a[1]) || a[1] == universeError)) if m := check.Types; m != nil { for { tv := m[x] diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go index c99bd6332a..c171b2c8d6 100644 --- a/src/go/types/conversions.go +++ b/src/go/types/conversions.go @@ -22,7 +22,7 @@ func (check *Checker) conversion(x *operand, T Type) { // nothing to do case representableConst(x.val, check, t, val): return true - case is_Integer(x.typ) && is_String(t): + case isInteger(x.typ) && isString(t): codepoint := unicode.ReplacementChar if i, ok := constant.Uint64Val(x.val); ok && i <= unicode.MaxRune { codepoint = rune(i) @@ -91,7 +91,7 @@ func (check *Checker) conversion(x *operand, T Type) { // (See also the TODO below.) if IsInterface(T) || constArg && !isConstType(T) || x.isNil() { final = Default(x.typ) // default type of untyped nil is untyped nil - } else if is_Integer(x.typ) && allString(T) { + } else if isInteger(x.typ) && allString(T) { final = x.typ } check.updateExprType(x.expr, final, true) @@ -195,22 +195,22 @@ func convertibleToImpl(check *Checker, V, T Type, cause *string) bool { } // "V and T are both integer or floating point types" - if is_IntegerOrFloat(V) && is_IntegerOrFloat(T) { + if isIntegerOrFloat(V) && isIntegerOrFloat(T) { return true } // "V and T are both complex types" - if is_Complex(V) && is_Complex(T) { + if isComplex(V) && isComplex(T) { return true } // "V is an integer or a slice of bytes or runes and T is a string type" - if (is_Integer(V) || isBytesOrRunes(Vu)) && is_String(T) { + if (isInteger(V) || isBytesOrRunes(Vu)) && isString(T) { return true } // "V is a string and T is a slice of bytes or runes" - if is_String(V) && isBytesOrRunes(Tu) { + if isString(V) && isBytesOrRunes(Tu) { return true } diff --git a/src/go/types/expr.go b/src/go/types/expr.go index cdb18eb963..83022ed660 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -212,7 +212,7 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr) { return } var prec uint - if is_Unsigned(x.typ) { + if isUnsigned(x.typ) { prec = uint(check.conf.sizeof(x.typ) * 8) } x.val = constant.UnaryOp(e.Op, x.val, prec) @@ -289,7 +289,7 @@ func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *c } switch { - case is_Integer(typ): + case isInteger(typ): x := constant.ToInt(x) if x.Kind() != constant.Int { return false @@ -344,7 +344,7 @@ func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *c return true } - case is_Float(typ): + case isFloat(typ): x := constant.ToFloat(x) if x.Kind() != constant.Float { return false @@ -374,7 +374,7 @@ func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *c unreachable() } - case is_Complex(typ): + case isComplex(typ): x := constant.ToComplex(x) if x.Kind() != constant.Complex { return false @@ -406,10 +406,10 @@ func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *c unreachable() } - case is_String(typ): + case isString(typ): return x.Kind() == constant.String - case is_Boolean(typ): + case isBoolean(typ): return x.Kind() == constant.Bool } @@ -437,7 +437,7 @@ func (check *Checker) representation(x *operand, typ *Basic) (constant.Value, er assert(x.mode == constant_) v := x.val if !representableConst(x.val, check, typ, &v) { - if is_Numeric(x.typ) && is_Numeric(typ) { + if isNumeric(x.typ) && isNumeric(typ) { // numeric conversion : error msg // // integer -> integer : overflows @@ -445,7 +445,7 @@ func (check *Checker) representation(x *operand, typ *Basic) (constant.Value, er // float -> integer : truncated // float -> float : overflows // - if !is_Integer(x.typ) && is_Integer(typ) { + if !isInteger(x.typ) && isInteger(typ) { return nil, _TruncatedFloat } else { return nil, _NumericOverflow @@ -569,7 +569,7 @@ func (check *Checker) updateExprType(x ast.Expr, typ Type, final bool) { // If x is the lhs of a shift, its final type must be integer. // We already know from the shift check that it is representable // as an integer if it is a constant. - if !is_Integer(typ) { + if !isInteger(typ) { check.invalidOp(x, _InvalidShiftOperand, "shifted operand %s (type %s) must be integer", x, typ) return } @@ -631,7 +631,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const // both x and target are untyped xkind := x.typ.(*Basic).kind tkind := target.(*Basic).kind - if is_Numeric(x.typ) && is_Numeric(target) { + if isNumeric(x.typ) && isNumeric(target) { if xkind < tkind { return target, nil, 0 } @@ -656,18 +656,18 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const // the value nil. switch x.typ.(*Basic).kind { case UntypedBool: - if !is_Boolean(target) { + if !isBoolean(target) { return nil, nil, _InvalidUntypedConversion } case UntypedInt, UntypedRune, UntypedFloat, UntypedComplex: - if !is_Numeric(target) { + if !isNumeric(target) { return nil, nil, _InvalidUntypedConversion } case UntypedString: // Non-constant untyped string values are not permitted by the spec and // should not occur during normal typechecking passes, but this path is // reachable via the AssignableTo API. - if !is_String(target) { + if !isString(target) { return nil, nil, _InvalidUntypedConversion } case UntypedNil: @@ -810,7 +810,7 @@ func (check *Checker) shift(x, y *operand, e ast.Expr, op token.Token) { if isUntyped(y.typ) { // Caution: Check for representability here, rather than in the switch - // below, because is_Integer includes untyped integers (was bug #43697). + // below, because isInteger includes untyped integers (was bug #43697). check.representable(y, Typ[Uint]) if y.mode == invalid { x.mode = invalid @@ -847,7 +847,7 @@ func (check *Checker) shift(x, y *operand, e ast.Expr, op token.Token) { if x.val.Kind() == constant.Unknown || y.val.Kind() == constant.Unknown { x.val = constant.MakeUnknown() // ensure the correct type - see comment below - if !is_Integer(x.typ) { + if !isInteger(x.typ) { x.typ = Typ[UntypedInt] } return @@ -864,7 +864,7 @@ func (check *Checker) shift(x, y *operand, e ast.Expr, op token.Token) { // (e.g., 2.0, an untyped float) - this can only happen for untyped // non-integer numeric constants. Correct the type so that the shift // result is of integer type. - if !is_Integer(x.typ) { + if !isInteger(x.typ) { x.typ = Typ[UntypedInt] } // x is a constant so xval != nil and it must be of Int kind. @@ -1029,7 +1029,7 @@ func (check *Checker) binary(x *operand, e ast.Expr, lhs, rhs ast.Expr, op token } // check for divisor underflow in complex division (see issue 20227) - if x.mode == constant_ && y.mode == constant_ && is_Complex(x.typ) { + if x.mode == constant_ && y.mode == constant_ && isComplex(x.typ) { re, im := constant.Real(y.val), constant.Imag(y.val) re2, im2 := constant.BinaryOp(re, token.MUL, re), constant.BinaryOp(im, token.MUL, im) if constant.Sign(re2) == 0 && constant.Sign(im2) == 0 { @@ -1048,7 +1048,7 @@ func (check *Checker) binary(x *operand, e ast.Expr, lhs, rhs ast.Expr, op token return } // force integer division of integer operands - if op == token.QUO && is_Integer(x.typ) { + if op == token.QUO && isInteger(x.typ) { op = token.QUO_ASSIGN } x.val = constant.BinaryOp(x.val, op, y.val) diff --git a/src/go/types/index.go b/src/go/types/index.go index 5d35458011..7ef8231f0b 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -52,7 +52,7 @@ func (check *Checker) indexExpr(x *operand, e *typeparams.IndexExpr) (isFuncInst length := int64(-1) // valid if >= 0 switch typ := under(x.typ).(type) { case *Basic: - if is_String(typ) { + if isString(typ) { valid = true if x.mode == constant_ { length = int64(len(constant.StringVal(x.val))) @@ -110,7 +110,7 @@ func (check *Checker) indexExpr(x *operand, e *typeparams.IndexExpr) (isFuncInst var k, e Type // k is only set for maps switch t := u.(type) { case *Basic: - if is_String(t) { + if isString(t) { e = universeByte mode = value } @@ -218,7 +218,7 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { return case *Basic: - if is_String(u) { + if isString(u) { if e.Slice3 { check.invalidOp(x, _InvalidSliceExpr, "3-index slice of string") x.mode = invalid diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 4ca962e77e..1ecb6a8c7e 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -27,18 +27,18 @@ func isGeneric(typ Type) bool { return named != nil && named.obj != nil && named.targs == nil && named.TypeParams() != nil } -// The is_X predicates below report whether t is an X. +// The isX predicates below report whether t is an X. // If t is a type parameter the result is false; i.e., // these predicates don't look inside a type parameter. -func is_Boolean(t Type) bool { return isBasic(t, IsBoolean) } -func is_Integer(t Type) bool { return isBasic(t, IsInteger) } -func is_Unsigned(t Type) bool { return isBasic(t, IsUnsigned) } -func is_Float(t Type) bool { return isBasic(t, IsFloat) } -func is_Complex(t Type) bool { return isBasic(t, IsComplex) } -func is_Numeric(t Type) bool { return isBasic(t, IsNumeric) } -func is_String(t Type) bool { return isBasic(t, IsString) } -func is_IntegerOrFloat(t Type) bool { return isBasic(t, IsInteger|IsFloat) } +func isBoolean(t Type) bool { return isBasic(t, IsBoolean) } +func isInteger(t Type) bool { return isBasic(t, IsInteger) } +func isUnsigned(t Type) bool { return isBasic(t, IsUnsigned) } +func isFloat(t Type) bool { return isBasic(t, IsFloat) } +func isComplex(t Type) bool { return isBasic(t, IsComplex) } +func isNumeric(t Type) bool { return isBasic(t, IsNumeric) } +func isString(t Type) bool { return isBasic(t, IsString) } +func isIntegerOrFloat(t Type) bool { return isBasic(t, IsInteger|IsFloat) } // isBasic reports whether under(t) is a basic type with the specified info. // If t is a type parameter the result is false; i.e., @@ -49,10 +49,10 @@ func isBasic(t Type, info BasicInfo) bool { } // The allX predicates below report whether t is an X. -// If t is a type parameter the result is true if is_X is true +// If t is a type parameter the result is true if isX is true // for all specified types of the type parameter's type set. -// allX is an optimized version of is_X(structure(t)) (which -// is the same as underIs(t, is_X)). +// allX is an optimized version of isX(structure(t)) (which +// is the same as underIs(t, isX)). func allBoolean(typ Type) bool { return allBasic(typ, IsBoolean) } func allInteger(typ Type) bool { return allBasic(typ, IsInteger) } diff --git a/src/go/types/sizes.go b/src/go/types/sizes.go index badba82cfa..4c85bfe057 100644 --- a/src/go/types/sizes.go +++ b/src/go/types/sizes.go @@ -82,7 +82,7 @@ func (s *StdSizes) Alignof(T Type) int64 { return 1 } // complex{64,128} are aligned like [2]float{32,64}. - if is_Complex(T) { + if isComplex(T) { a /= 2 } if a > s.MaxAlign { diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index 6e69646455..11032f44dd 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -944,7 +944,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { func rangeKeyVal(typ Type) (key, val Type) { switch typ := arrayPtrDeref(typ).(type) { case *Basic: - if is_String(typ) { + if isString(typ) { return Typ[Int], universeRune // use 'rune' name } case *Array: diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 30e817f416..e1d942a5c6 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -489,7 +489,7 @@ func (check *Checker) arrayLength(e ast.Expr) int64 { return -1 } - if isUntyped(x.typ) || is_Integer(x.typ) { + if isUntyped(x.typ) || isInteger(x.typ) { if val := constant.ToInt(x.val); val.Kind() == constant.Int { if representableConst(val, check, Typ[Int], nil) { if n, ok := constant.Int64Val(val); ok && n >= 0 { -- GitLab From 47e3c4bc74f5f260cbc9c5e6d1ababde0a114a97 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 8 Nov 2021 18:10:30 -0800 Subject: [PATCH 2061/2500] cmd/compile: disable doubleCheck and remove unused checkDictionary In stencil.go, change doubleCheck to false, which will turn off some double-checking code which isn't needed generally, now that we have lots of tests of end-to-end runs. Also, removed checkDictionary() which is unused and is unlikely to be useful in the future. Change-Id: I4e5acceab80f4904b174422bae21ca82cf04f943 Reviewed-on: https://go-review.googlesource.com/c/go/+/361923 Trust: Dan Scales Run-TryBot: Dan Scales Reviewed-by: Keith Randall TryBot-Result: Go Bot --- src/cmd/compile/internal/noder/stencil.go | 50 +---------------------- 1 file changed, 1 insertion(+), 49 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 4ebd607c16..cfbbee3ceb 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -22,7 +22,7 @@ import ( ) // Enable extra consistency checks. -const doubleCheck = true +const doubleCheck = false func assert(p bool) { base.Assert(p) @@ -802,11 +802,6 @@ func (g *genInst) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes []*t // Make sure name/type of newf is set before substituting the body. newf.Body = subst.list(gf.Body) - // Add code to check that the dictionary is correct. - // TODO: must be adjusted to deal with shapes, but will go away soon when we move - // to many->1 shape to concrete mapping. - // newf.Body.Prepend(subst.checkDictionary(dictionaryName, shapes)...) - if len(subst.defnMap) > 0 { base.Fatalf("defnMap is not empty") } @@ -859,49 +854,6 @@ func (subst *subster) localvar(name *ir.Name) *ir.Name { return m } -// checkDictionary returns code that does runtime consistency checks -// between the dictionary and the types it should contain. -func (subst *subster) checkDictionary(name *ir.Name, targs []*types.Type) (code []ir.Node) { - if false { - return // checking turned off - } - // TODO: when moving to GCshape, this test will become harder. Call into - // runtime to check the expected shape is correct? - pos := name.Pos() - // Convert dictionary to *[N]uintptr - d := ir.NewConvExpr(pos, ir.OCONVNOP, types.Types[types.TUNSAFEPTR], name) - d.SetTypecheck(1) - d = ir.NewConvExpr(pos, ir.OCONVNOP, types.NewArray(types.Types[types.TUINTPTR], int64(len(targs))).PtrTo(), d) - d.SetTypecheck(1) - types.CheckSize(d.Type().Elem()) - - // Check that each type entry in the dictionary is correct. - for i, t := range targs { - if t.HasShape() { - // Check the concrete type, not the shape type. - base.Fatalf("shape type in dictionary %s %+v\n", name.Sym().Name, t) - } - want := reflectdata.TypePtr(t) - typed(types.Types[types.TUINTPTR], want) - deref := ir.NewStarExpr(pos, d) - typed(d.Type().Elem(), deref) - idx := ir.NewConstExpr(constant.MakeUint64(uint64(i)), name) // TODO: what to set orig to? - typed(types.Types[types.TUINTPTR], idx) - got := ir.NewIndexExpr(pos, deref, idx) - typed(types.Types[types.TUINTPTR], got) - cond := ir.NewBinaryExpr(pos, ir.ONE, want, got) - typed(types.Types[types.TBOOL], cond) - panicArg := ir.NewNilExpr(pos) - typed(types.NewInterface(types.LocalPkg, nil, false), panicArg) - then := ir.NewUnaryExpr(pos, ir.OPANIC, panicArg) - then.SetTypecheck(1) - x := ir.NewIfStmt(pos, cond, []ir.Node{then}, nil) - x.SetTypecheck(1) - code = append(code, x) - } - return -} - // getDictionaryEntry gets the i'th entry in the dictionary dict. func getDictionaryEntry(pos src.XPos, dict *ir.Name, i int, size int) ir.Node { // Convert dictionary to *[N]uintptr -- GitLab From 34abc12b2a24fd76cdfad531f0a229f3cbb55bc3 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 8 Nov 2021 18:08:59 +0000 Subject: [PATCH 2062/2500] cmd/compile/internal/types2: roll-forward removal of asX converters This CL reverts CL 361964, rolling forward the original CL 362254 with a fix for re-entrant expansion via type hashing (compare patchsets 1 and 2). Change-Id: I62869e50e919f42eb8d6fef5b0d7a5ec8960bd84 Reviewed-on: https://go-review.googlesource.com/c/go/+/362118 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Cuong Manh Le Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- .../compile/internal/types2/assignments.go | 2 +- src/cmd/compile/internal/types2/builtins.go | 8 ++-- src/cmd/compile/internal/types2/call.go | 2 +- src/cmd/compile/internal/types2/context.go | 3 ++ .../compile/internal/types2/conversions.go | 21 +++++----- src/cmd/compile/internal/types2/expr.go | 6 +-- src/cmd/compile/internal/types2/index.go | 8 ++-- src/cmd/compile/internal/types2/lookup.go | 9 ++--- src/cmd/compile/internal/types2/predicates.go | 5 ++- src/cmd/compile/internal/types2/sizes.go | 2 +- src/cmd/compile/internal/types2/type.go | 39 +------------------ src/cmd/compile/internal/types2/typestring.go | 2 +- src/cmd/compile/internal/types2/typexpr.go | 2 +- 13 files changed, 38 insertions(+), 71 deletions(-) diff --git a/src/cmd/compile/internal/types2/assignments.go b/src/cmd/compile/internal/types2/assignments.go index bfc5578683..609d7d0962 100644 --- a/src/cmd/compile/internal/types2/assignments.go +++ b/src/cmd/compile/internal/types2/assignments.go @@ -71,7 +71,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { // x.typ is typed // A generic (non-instantiated) function value cannot be assigned to a variable. - if sig := asSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { + if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 { check.errorf(x, "cannot use generic function %s without instantiation in %s", x, context) } diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index ade4c0a49f..916aed40b3 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -294,7 +294,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( // (applyTypeFunc never calls f with a type parameter) f := func(typ Type) Type { assert(asTypeParam(typ) == nil) - if t := asBasic(typ); t != nil { + if t, _ := under(typ).(*Basic); t != nil { switch t.kind { case Float32: return Typ[Complex64] @@ -418,7 +418,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( // (applyTypeFunc never calls f with a type parameter) f := func(typ Type) Type { assert(asTypeParam(typ) == nil) - if t := asBasic(typ); t != nil { + if t, _ := under(typ).(*Basic); t != nil { switch t.kind { case Complex64: return Typ[Float32] @@ -704,7 +704,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( return } - typ := asPointer(x.typ) + typ, _ := under(x.typ).(*Pointer) if typ == nil { check.errorf(x, invalidArg+"%s is not a pointer", x) return @@ -894,7 +894,7 @@ func makeSig(res Type, args ...Type) *Signature { // otherwise it returns typ. func arrayPtrDeref(typ Type) Type { if p, ok := typ.(*Pointer); ok { - if a := asArray(p.base); a != nil { + if a, _ := under(p.base).(*Array); a != nil { return a } } diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 74edd4d442..3a571285c1 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -132,7 +132,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { case 1: check.expr(x, call.ArgList[0]) if x.mode != invalid { - if t := asInterface(T); t != nil { + if t, _ := under(T).(*Interface); t != nil { if !t.IsMethodSet() { check.errorf(call, "cannot use interface %s in conversion (contains specific type constraints or is comparable)", T) break diff --git a/src/cmd/compile/internal/types2/context.go b/src/cmd/compile/internal/types2/context.go index a8f8591243..f6137eea43 100644 --- a/src/cmd/compile/internal/types2/context.go +++ b/src/cmd/compile/internal/types2/context.go @@ -39,6 +39,9 @@ func (ctxt *Context) TypeHash(typ Type, targs []Type) string { var buf bytes.Buffer h := newTypeHasher(&buf, ctxt) + // Caution: don't use asNamed here. TypeHash may be called for unexpanded + // types. We don't need anything other than name and type arguments below, + // which do not require expansion. if named, _ := typ.(*Named); named != nil && len(targs) > 0 { // Don't use WriteType because we need to use the provided targs // and not any targs that might already be with the *Named type. diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go index ccabbaf0d7..dd89f29762 100644 --- a/src/cmd/compile/internal/types2/conversions.go +++ b/src/cmd/compile/internal/types2/conversions.go @@ -18,7 +18,7 @@ func (check *Checker) conversion(x *operand, T Type) { constArg := x.mode == constant_ constConvertibleTo := func(T Type, val *constant.Value) bool { - switch t := asBasic(T); { + switch t, _ := under(T).(*Basic); { case t == nil: // nothing to do case representableConst(x.val, check, t, val): @@ -173,9 +173,9 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { // "V a slice, T is a pointer-to-array type, // and the slice and array types have identical element types." - if s := asSlice(V); s != nil { - if p := asPointer(T); p != nil { - if a := asArray(p.Elem()); a != nil { + if s, _ := under(V).(*Slice); s != nil { + if p, _ := under(T).(*Pointer); p != nil { + if a, _ := under(p.Elem()).(*Array); a != nil { if Identical(s.Elem(), a.Elem()) { if check == nil || check.allowVersion(check.pkg, 1, 17) { return true @@ -262,26 +262,27 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { // use the toT convenience converters in the predicates below. func isUintptr(typ Type) bool { - t := asBasic(typ) + t, _ := under(typ).(*Basic) return t != nil && t.kind == Uintptr } func isUnsafePointer(typ Type) bool { - // TODO(gri): Is this asBasic(typ) instead of typ.(*Basic) correct? + // TODO(gri): Is this under(typ).(*Basic) instead of typ.(*Basic) correct? // (The former calls under(), while the latter doesn't.) // The spec does not say so, but gc claims it is. See also // issue 6326. - t := asBasic(typ) + t, _ := under(typ).(*Basic) return t != nil && t.kind == UnsafePointer } func isPointer(typ Type) bool { - return asPointer(typ) != nil + _, ok := under(typ).(*Pointer) + return ok } func isBytesOrRunes(typ Type) bool { - if s := asSlice(typ); s != nil { - t := asBasic(s.elem) + if s, _ := under(typ).(*Slice); s != nil { + t, _ := under(s.elem).(*Basic) return t != nil && (t.kind == Byte || t.kind == Rune) } return false diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index d24532d780..8125fba717 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -116,7 +116,7 @@ func (check *Checker) overflow(x *operand) { // x.typ cannot be a type parameter (type // parameters cannot be constant types). if isTyped(x.typ) { - check.representable(x, asBasic(x.typ)) + check.representable(x, under(x.typ).(*Basic)) return } @@ -617,7 +617,7 @@ func (check *Checker) updateExprType(x syntax.Expr, typ Type, final bool) { // If the new type is not final and still untyped, just // update the recorded type. if !final && isUntyped(typ) { - old.typ = asBasic(typ) + old.typ = under(typ).(*Basic) check.untyped[x] = old return } @@ -1394,7 +1394,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin duplicate := false // if the key is of interface type, the type is also significant when checking for duplicates xkey := keyVal(x.val) - if asInterface(utyp.key) != nil { + if IsInterface(utyp.key) { for _, vtyp := range visited[xkey] { if Identical(vtyp, x.typ) { duplicate = true diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index 67110704e9..f096674536 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -34,7 +34,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo return false case value: - if sig := asSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { + if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 { // function instantiation return true } @@ -72,7 +72,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo x.typ = typ.elem case *Pointer: - if typ := asArray(typ.base); typ != nil { + if typ, _ := under(typ.base).(*Array); typ != nil { valid = true length = typ.len x.mode = variable @@ -120,7 +120,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo mode = value } case *Pointer: - if t := asArray(t.base); t != nil { + if t, _ := under(t.base).(*Array); t != nil { l = t.len e = t.elem } @@ -245,7 +245,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { x.typ = &Slice{elem: u.elem} case *Pointer: - if u := asArray(u.base); u != nil { + if u, _ := under(u.base).(*Array); u != nil { valid = true length = u.len x.typ = &Slice{elem: u.elem} diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index e0fd74482a..0612400590 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -122,7 +122,6 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o seen[named] = true // look for a matching attached method - named.resolve(nil) if i, m := lookupMethod(named.methods, pkg, name); m != nil { // potential match // caution: method may not have a proper signature yet @@ -306,7 +305,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, return } - if ityp := asInterface(V); ityp != nil { + if ityp, _ := under(V).(*Interface); ityp != nil { // TODO(gri) the methods are sorted - could do this more efficiently for _, m := range T.typeSet().methods { _, f := ityp.typeSet().LookupMethod(m.pkg, m.name) @@ -417,7 +416,7 @@ func (check *Checker) assertableTo(V *Interface, T Type) (method, wrongType *Fun // no static check is required if T is an interface // spec: "If T is an interface type, x.(T) asserts that the // dynamic type of x implements the interface T." - if asInterface(T) != nil && !forceStrict { + if IsInterface(T) && !forceStrict { return } return check.missingMethod(T, V, false) @@ -435,8 +434,8 @@ func deref(typ Type) (Type, bool) { // derefStructPtr dereferences typ if it is a (named or unnamed) pointer to a // (named or unnamed) struct and returns its base. Otherwise it returns typ. func derefStructPtr(typ Type) Type { - if p := asPointer(typ); p != nil { - if asStruct(p.base) != nil { + if p, _ := under(typ).(*Pointer); p != nil { + if _, ok := under(p.base).(*Struct); ok { return p.base } } diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 7fbb91eb61..8d676ed8f6 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -72,7 +72,7 @@ func hasName(t Type) bool { // are not fully set up. func isTyped(t Type) bool { // isTyped is called with types that are not fully - // set up. Must not call asBasic()! + // set up. Must not call under()! b, _ := t.(*Basic) return b == nil || b.info&IsUntyped == 0 } @@ -84,7 +84,8 @@ func isUntyped(t Type) bool { // IsInterface reports whether t is an interface type. func IsInterface(t Type) bool { - return asInterface(t) != nil + _, ok := under(t).(*Interface) + return ok } // isTypeParam reports whether t is a type parameter. diff --git a/src/cmd/compile/internal/types2/sizes.go b/src/cmd/compile/internal/types2/sizes.go index 6a3d19d8ea..609b6f585e 100644 --- a/src/cmd/compile/internal/types2/sizes.go +++ b/src/cmd/compile/internal/types2/sizes.go @@ -243,7 +243,7 @@ func (conf *Config) offsetsof(T *Struct) []int64 { func (conf *Config) offsetof(typ Type, index []int) int64 { var o int64 for _, i := range index { - s := asStruct(typ) + s := under(typ).(*Struct) o += conf.offsetsof(s)[i] typ = s.fields[i].typ } diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 300c81f5fa..d1655c55f8 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -27,45 +27,8 @@ func under(t Type) Type { return t } -// Convenience converters - -func asBasic(t Type) *Basic { - u, _ := under(t).(*Basic) - return u -} - -func asArray(t Type) *Array { - u, _ := under(t).(*Array) - return u -} - -func asSlice(t Type) *Slice { - u, _ := under(t).(*Slice) - return u -} - -func asStruct(t Type) *Struct { - u, _ := under(t).(*Struct) - return u -} - -func asPointer(t Type) *Pointer { - u, _ := under(t).(*Pointer) - return u -} - -func asSignature(t Type) *Signature { - u, _ := under(t).(*Signature) - return u -} - -func asInterface(t Type) *Interface { - u, _ := under(t).(*Interface) - return u -} - // If the argument to asNamed, or asTypeParam is of the respective type -// (possibly after expanding resolving a *Named type), these methods return that type. +// (possibly after resolving a *Named type), these methods return that type. // Otherwise the result is nil. func asNamed(t Type) *Named { diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index f18a32016f..f151f47a5e 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -361,7 +361,7 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) { } else { // special case: // append(s, "foo"...) leads to signature func([]byte, string...) - if t := asBasic(typ); t == nil || t.kind != String { + if t, _ := under(typ).(*Basic); t == nil || t.kind != String { w.error("expected string type") continue } diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index dcd7cfebe8..a08e472703 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -148,7 +148,7 @@ func (check *Checker) varType(e syntax.Expr) Type { // are in the middle of type-checking parameter declarations that might belong to // interface methods. Delay this check to the end of type-checking. check.later(func() { - if t := asInterface(typ); t != nil { + if t, _ := under(typ).(*Interface); t != nil { pos := syntax.StartPos(e) tset := computeInterfaceTypeSet(check, pos, t) // TODO(gri) is this the correct position? if !tset.IsMethodSet() { -- GitLab From 90f47dbba635802bb009404e321fa4759ac76d20 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Tue, 9 Nov 2021 10:59:32 -0500 Subject: [PATCH 2063/2500] runtime/pprof: include labels in profile dump For tests of pprof label support having the sample labels in the output is needed for effective debugging. For #48577 Change-Id: Ic7c5bc90cb33e8fb477f7db62d9b56a7a9d6ffa8 Reviewed-on: https://go-review.googlesource.com/c/go/+/362614 Trust: Michael Pratt Run-TryBot: Michael Pratt TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/pprof/pprof_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go index 417d5034a6..704c0c516d 100644 --- a/src/runtime/pprof/pprof_test.go +++ b/src/runtime/pprof/pprof_test.go @@ -494,6 +494,7 @@ func profileOk(t *testing.T, matches matchFunc, need []string, avoid []string, p p := parseProfile(t, prof.Bytes(), func(count uintptr, stk []*profile.Location, labels map[string][]string) { fmt.Fprintf(&buf, "%d:", count) fprintStack(&buf, stk) + fmt.Fprintf(&buf, " labels: %v\n", labels) samples += count for i, spec := range need { if matches(spec, count, stk, labels) { @@ -675,7 +676,6 @@ func fprintStack(w io.Writer, stk []*profile.Location) { } fmt.Fprintf(w, ")") } - fmt.Fprintf(w, "\n") } // Test that profiling of division operations is okay, especially on ARM. See issue 6681. -- GitLab From 15a54d627ca7a0bdf45a3d1862b35a892024cacc Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Tue, 9 Nov 2021 11:35:52 -0500 Subject: [PATCH 2064/2500] runtime: add upper half and carry bit with zero https://golang.org/cl/246763 accidentally changed this from upper + 0 + carry to upper + old vdsoSP + carry. The old value of vdsoPC is usually zero, so this typically works. However, the reentrant case will have a non-zero value, resulting in a bogus returned time. Fixes #49481 Change-Id: I0110b84277bf911804cb0ff8097aebf1b7eb100a Reviewed-on: https://go-review.googlesource.com/c/go/+/362674 Trust: Michael Pratt Run-TryBot: Michael Pratt TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/runtime/sys_linux_arm.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/sys_linux_arm.s b/src/runtime/sys_linux_arm.s index 65935de99f..ca443b699f 100644 --- a/src/runtime/sys_linux_arm.s +++ b/src/runtime/sys_linux_arm.s @@ -456,7 +456,7 @@ finish: MOVW $1000000000, R3 MULLU R0, R3, (R1, R0) ADD.S R2, R0 - ADC R4, R1 + ADC $0, R1 // Add carry bit to upper half. MOVW R0, ret_lo+0(FP) MOVW R1, ret_hi+4(FP) -- GitLab From 36dbf7f7e63f3738795bb04593c3c011e987d1f3 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 28 Oct 2021 13:22:07 -0400 Subject: [PATCH 2065/2500] cmd/go: add //go:embed all:pattern When //go:embed d matches directory d, it embeds the directory tree rooted at d, but it excludes files beginning with . and _, as well as files having problematic names that will not be packaged into modules (names such as .git and com1). After long discussions on #42328 and #43854, we decided to keep the behavior of excluding . and _ files by default, but to allow the pattern prefix 'all:' to override this default. This CL implements that change. Note that paths like .git and com1 are still excluded, as they must be, since they will never be packed into a module. Fixes #43854. Change-Id: I4f3731e14ecffd4b691fda3a0890b460027fe209 Reviewed-on: https://go-review.googlesource.com/c/go/+/359413 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Jonathan Amsterdam Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/load/pkg.go | 11 ++++++++--- src/cmd/go/testdata/script/embed.txt | 20 ++++++++++++++++++++ src/embed/embed.go | 5 +++++ 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index c6c5fb00a8..360d265de6 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -2017,13 +2017,18 @@ func resolveEmbed(pkgdir string, patterns []string) (files []string, pmap map[st for _, pattern = range patterns { pid++ + glob := pattern + all := strings.HasPrefix(pattern, "all:") + if all { + glob = pattern[len("all:"):] + } // Check pattern is valid for //go:embed. - if _, err := path.Match(pattern, ""); err != nil || !validEmbedPattern(pattern) { + if _, err := path.Match(glob, ""); err != nil || !validEmbedPattern(glob) { return nil, nil, fmt.Errorf("invalid pattern syntax") } // Glob to find matches. - match, err := fsys.Glob(pkgdir + string(filepath.Separator) + filepath.FromSlash(pattern)) + match, err := fsys.Glob(pkgdir + string(filepath.Separator) + filepath.FromSlash(glob)) if err != nil { return nil, nil, err } @@ -2086,7 +2091,7 @@ func resolveEmbed(pkgdir string, patterns []string) (files []string, pmap map[st } rel := filepath.ToSlash(path[len(pkgdir)+1:]) name := info.Name() - if path != file && (isBadEmbedName(name) || name[0] == '.' || name[0] == '_') { + if path != file && (isBadEmbedName(name) || ((name[0] == '.' || name[0] == '_') && !all)) { // Ignore bad names, assuming they won't go into modules. // Also avoid hidden files that user may not know about. // See golang.org/issue/42328. diff --git a/src/cmd/go/testdata/script/embed.txt b/src/cmd/go/testdata/script/embed.txt index 04b17cd62b..5f7f6edd77 100644 --- a/src/cmd/go/testdata/script/embed.txt +++ b/src/cmd/go/testdata/script/embed.txt @@ -60,6 +60,18 @@ rm t/x.txt ! go build m/use stderr '^x.go:5:12: pattern [*]t: cannot embed directory t: contains no embeddable files$' +# all still ignores .git and symlinks +cp x.go3 x.go +! go build -x +stderr '^x.go:5:12: pattern all:t: cannot embed directory t: contains no embeddable files$' + +# all finds dot files and underscore files +cp x.txt t/.x.txt +go build -x +rm t/.x.txt +cp x.txt t/_x.txt +go build -x + -- x.go -- package p @@ -92,6 +104,14 @@ import "embed" //go:embed *t var X embed.FS +-- x.go3 -- +package p + +import "embed" + +//go:embed all:t +var X embed.FS + -- x.txt -- hello diff --git a/src/embed/embed.go b/src/embed/embed.go index f87cc5b963..24c3a89e9b 100644 --- a/src/embed/embed.go +++ b/src/embed/embed.go @@ -80,6 +80,11 @@ // var content embed.FS // // The difference is that ‘image/*’ embeds ‘image/.tempfile’ while ‘image’ does not. +// Neither embeds ‘image/dir/.tempfile’. +// +// If a pattern begins with the prefix ‘all:’, then the rule for walking directories is changed +// to include those files beginning with ‘.’ or ‘_’. For example, ‘all:image’ embeds +// both ‘image/.tempfile’ and ‘image/dir/.tempfile’. // // The //go:embed directive can be used with both exported and unexported variables, // depending on whether the package wants to make the data available to other packages. -- GitLab From 55e6e825d4c90544248c3a725b4dee9fb45848e7 Mon Sep 17 00:00:00 2001 From: Carl Johnson Date: Tue, 31 Aug 2021 20:35:35 +0000 Subject: [PATCH 2066/2500] net/http: add MaxBytesHandler Fixes #39567 Change-Id: I226089b678a6a13d7ce69f360a23fc5bd297d550 GitHub-Last-Rev: 6435fd5881fc70a276d04df5a60440e365924b49 GitHub-Pull-Request: golang/go#48104 Reviewed-on: https://go-review.googlesource.com/c/go/+/346569 Trust: Damien Neil Trust: Ian Lance Taylor Run-TryBot: Damien Neil TryBot-Result: Go Bot Reviewed-by: Damien Neil --- src/net/http/serve_test.go | 60 ++++++++++++++++++++++++++++++++++++++ src/net/http/server.go | 9 ++++++ 2 files changed, 69 insertions(+) diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index 30a6555d30..1156b187ae 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -6682,3 +6682,63 @@ func testQuerySemicolon(t *testing.T, query string, wantX string, allowSemicolon } } } + +func TestMaxBytesHandler(t *testing.T) { + setParallel(t) + defer afterTest(t) + + for _, maxSize := range []int64{100, 1_000, 1_000_000} { + for _, requestSize := range []int64{100, 1_000, 1_000_000} { + t.Run(fmt.Sprintf("max size %d request size %d", maxSize, requestSize), + func(t *testing.T) { + testMaxBytesHandler(t, maxSize, requestSize) + }) + } + } +} + +func testMaxBytesHandler(t *testing.T, maxSize, requestSize int64) { + var ( + handlerN int64 + handlerErr error + ) + echo := HandlerFunc(func(w ResponseWriter, r *Request) { + var buf bytes.Buffer + handlerN, handlerErr = io.Copy(&buf, r.Body) + io.Copy(w, &buf) + }) + + ts := httptest.NewServer(MaxBytesHandler(echo, maxSize)) + defer ts.Close() + + c := ts.Client() + var buf strings.Builder + body := strings.NewReader(strings.Repeat("a", int(requestSize))) + res, err := c.Post(ts.URL, "text/plain", body) + if err != nil { + t.Errorf("unexpected connection error: %v", err) + } else { + _, err = io.Copy(&buf, res.Body) + res.Body.Close() + if err != nil { + t.Errorf("unexpected read error: %v", err) + } + } + if handlerN > maxSize { + t.Errorf("expected max request body %d; got %d", maxSize, handlerN) + } + if requestSize > maxSize && handlerErr == nil { + t.Error("expected error on handler side; got nil") + } + if requestSize <= maxSize { + if handlerErr != nil { + t.Errorf("%d expected nil error on handler side; got %v", requestSize, handlerErr) + } + if handlerN != requestSize { + t.Errorf("expected request of size %d; got %d", requestSize, handlerN) + } + } + if buf.Len() != int(handlerN) { + t.Errorf("expected echo of size %d; got %d", handlerN, buf.Len()) + } +} diff --git a/src/net/http/server.go b/src/net/http/server.go index 08fd478ed9..c4a2d57dd4 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -3610,3 +3610,12 @@ func tlsRecordHeaderLooksLikeHTTP(hdr [5]byte) bool { } return false } + +// MaxBytesHandler returns a Handler that runs h with its ResponseWriter and Request.Body wrapped by a MaxBytesReader. +func MaxBytesHandler(h Handler, n int64) Handler { + return HandlerFunc(func(w ResponseWriter, r *Request) { + r2 := *r + r2.Body = MaxBytesReader(w, r.Body, n) + h.ServeHTTP(w, &r2) + }) +} -- GitLab From 01103d533a086afd6c06f3eec5057d46f117d2ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Chigot?= Date: Tue, 9 Nov 2021 10:01:05 +0100 Subject: [PATCH 2067/2500] cmd/link: fix GCC startfiles names on AIX Since GCC version 11, the 64-bit version of GCC starting files are now suffixed by "_64" instead of being stored without suffix under "ppc64" multilib directory. Change-Id: Ibe53521ed24d36e5f6282e3574849b9ae11a1e9a Reviewed-on: https://go-review.googlesource.com/c/go/+/362594 Reviewed-by: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Trust: Ian Lance Taylor --- src/cmd/link/internal/ld/lib.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 01ab6474b8..91665b2ebb 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -1499,8 +1499,19 @@ func (ctxt *Link) hostlink() { } return strings.Trim(string(out), "\n") } - argv = append(argv, getPathFile("crtcxa.o")) - argv = append(argv, getPathFile("crtdbase.o")) + // Since GCC version 11, the 64-bit version of GCC starting files + // are now suffixed by "_64". Even under "-maix64" multilib directory + // "crtcxa.o" is 32-bit. + crtcxa := getPathFile("crtcxa_64.o") + if !filepath.IsAbs(crtcxa) { + crtcxa = getPathFile("crtcxa.o") + } + crtdbase := getPathFile("crtdbase_64.o") + if !filepath.IsAbs(crtdbase) { + crtdbase = getPathFile("crtdbase.o") + } + argv = append(argv, crtcxa) + argv = append(argv, crtdbase) } if ctxt.linkShared { -- GitLab From 81f37a72ea8a05ea3f5771a92b34b352769518cf Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 9 Nov 2021 11:09:13 -0500 Subject: [PATCH 2068/2500] go/types: minor cleanups in predicates.go This is a clean port of CL 360956 to go/types. Change-Id: Iac437e72bb760e7e90236a86e7473d6a440df081 Reviewed-on: https://go-review.googlesource.com/c/go/+/362615 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/predicates.go | 87 ++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 46 deletions(-) diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 1ecb6a8c7e..622c773126 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -8,25 +8,6 @@ package types import "go/token" -// hasName reports whether typ has a name. This includes -// predeclared types, defined types, and type parameters. -// hasName may be called with types that are not fully set up. -func hasName(typ Type) bool { - switch typ.(type) { - case *Basic, *Named, *TypeParam: - return true - } - return false -} - -// isGeneric reports whether a type is a generic, uninstantiated type (generic -// signatures are not included). -func isGeneric(typ Type) bool { - // A parameterized type is only instantiated if it doesn't have an instantiation already. - named, _ := typ.(*Named) - return named != nil && named.obj != nil && named.targs == nil && named.TypeParams() != nil -} - // The isX predicates below report whether t is an X. // If t is a type parameter the result is false; i.e., // these predicates don't look inside a type parameter. @@ -39,6 +20,7 @@ func isComplex(t Type) bool { return isBasic(t, IsComplex) } func isNumeric(t Type) bool { return isBasic(t, IsNumeric) } func isString(t Type) bool { return isBasic(t, IsString) } func isIntegerOrFloat(t Type) bool { return isBasic(t, IsInteger|IsFloat) } +func isConstType(t Type) bool { return isBasic(t, IsConstType) } // isBasic reports whether under(t) is a basic type with the specified info. // If t is a type parameter the result is false; i.e., @@ -76,36 +58,50 @@ func allBasic(t Type, info BasicInfo) bool { return false } -// isTyped reports whether typ is typed; i.e., not an untyped +// hasName reports whether t has a name. This includes +// predeclared types, defined types, and type parameters. +// hasName may be called with types that are not fully set up. +func hasName(t Type) bool { + switch t.(type) { + case *Basic, *Named, *TypeParam: + return true + } + return false +} + +// isTyped reports whether t is typed; i.e., not an untyped // constant or boolean. isTyped may be called with types that // are not fully set up. -func isTyped(typ Type) bool { +func isTyped(t Type) bool { // isTyped is called with types that are not fully // set up. Must not call asBasic()! - t, _ := typ.(*Basic) - return t == nil || t.info&IsUntyped == 0 + b, _ := t.(*Basic) + return b == nil || b.info&IsUntyped == 0 } -// isUntyped(typ) is the same as !isTyped(typ). -func isUntyped(typ Type) bool { - return !isTyped(typ) +// isUntyped(t) is the same as !isTyped(t). +func isUntyped(t Type) bool { + return !isTyped(t) } -func isConstType(typ Type) bool { - // Type parameters are never const types. - t := asBasic(typ) - return t != nil && t.info&IsConstType != 0 +// IsInterface reports whether t is an interface type. +func IsInterface(t Type) bool { + return asInterface(t) != nil } -// IsInterface reports whether typ is an interface type. -func IsInterface(typ Type) bool { - return asInterface(typ) != nil +// isTypeParam reports whether t is a type parameter. +func isTypeParam(t Type) bool { + _, ok := under(t).(*TypeParam) + return ok } -// isTypeParam reports whether typ is a type parameter. -func isTypeParam(typ Type) bool { - _, ok := under(typ).(*TypeParam) - return ok +// isGeneric reports whether a type is a generic, uninstantiated type +// (generic signatures are not included). +// TODO(gri) should we include signatures or assert that they are not present? +func isGeneric(t Type) bool { + // A parameterized type is only generic if it doesn't have an instantiation already. + named, _ := t.(*Named) + return named != nil && named.obj != nil && named.targs == nil && named.TypeParams() != nil } // Comparable reports whether values of type T are comparable. @@ -144,15 +140,15 @@ func comparable(T Type, seen map[Type]bool) bool { return false } -// hasNil reports whether a type includes the nil value. -func hasNil(typ Type) bool { - switch t := under(typ).(type) { +// hasNil reports whether type t includes the nil value. +func hasNil(t Type) bool { + switch u := under(t).(type) { case *Basic: - return t.kind == UnsafePointer + return u.kind == UnsafePointer case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan: return true case *TypeParam: - return t.underIs(hasNil) + return u.underIs(hasNil) } return false } @@ -394,9 +390,8 @@ func identicalTParams(x, y []*TypeParam, cmpTags bool, p *ifacePair) bool { // Default returns the default "typed" type for an "untyped" type; // it returns the incoming type for all other types. The default type // for untyped nil is untyped nil. -// -func Default(typ Type) Type { - if t, ok := typ.(*Basic); ok { +func Default(t Type) Type { + if t, ok := t.(*Basic); ok { switch t.kind { case UntypedBool: return Typ[Bool] @@ -412,5 +407,5 @@ func Default(typ Type) Type { return Typ[String] } } - return typ + return t } -- GitLab From 526b2ef0ea3a13d7e9af635918ef3ef86353f220 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 9 Nov 2021 11:14:37 -0500 Subject: [PATCH 2069/2500] go/types: check non-generic conversions first This is a clean port of CL 361269 to go/types. Change-Id: I2caaf08eabdf1707ae83ec1e628fd26f21b2b8e5 Reviewed-on: https://go-review.googlesource.com/c/go/+/362616 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/conversions.go | 119 +++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 57 deletions(-) diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go index c171b2c8d6..f73e6a0964 100644 --- a/src/go/types/conversions.go +++ b/src/go/types/conversions.go @@ -120,64 +120,8 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { return true } - // determine type parameter operands with specific type terms - Vp, _ := under(x.typ).(*TypeParam) - Tp, _ := under(T).(*TypeParam) - if Vp != nil && !Vp.hasTerms() { - Vp = nil - } - if Tp != nil && !Tp.hasTerms() { - Tp = nil - } - - errorf := func(format string, args ...interface{}) { - if check != nil && cause != nil { - msg := check.sprintf(format, args...) - if *cause != "" { - msg += "\n\t" + *cause - } - *cause = msg - } - } - - // generic cases with specific type terms - // (generic operands cannot be constants, so we can ignore x.val) - switch { - case Vp != nil && Tp != nil: - return Vp.is(func(V *term) bool { - return Tp.is(func(T *term) bool { - if !convertibleToImpl(check, V.typ, T.typ, cause) { - errorf("cannot convert %s (in %s) to %s (in %s)", V.typ, Vp, T.typ, Tp) - return false - } - return true - }) - }) - case Vp != nil: - return Vp.is(func(V *term) bool { - if !convertibleToImpl(check, V.typ, T, cause) { - errorf("cannot convert %s (in %s) to %s", V.typ, Vp, T) - return false - } - return true - }) - case Tp != nil: - return Tp.is(func(T *term) bool { - if !convertibleToImpl(check, x.typ, T.typ, cause) { - errorf("cannot convert %s to %s (in %s)", x.typ, T.typ, Tp) - return false - } - return true - }) - } - - // non-generic case - return convertibleToImpl(check, x.typ, T, cause) -} - -// convertibleToImpl should only be called by convertibleTo -func convertibleToImpl(check *Checker, V, T Type, cause *string) bool { // "V and T have identical underlying types if tags are ignored" + V := x.typ Vu := under(V) Tu := under(T) if IdenticalIgnoreTags(Vu, Tu) { @@ -241,6 +185,67 @@ func convertibleToImpl(check *Checker, V, T Type, cause *string) bool { } } + // optimization: if we don't have type parameters, we're done + Vp, _ := Vu.(*TypeParam) + Tp, _ := Tu.(*TypeParam) + if Vp == nil && Tp == nil { + return false + } + + errorf := func(format string, args ...interface{}) { + if check != nil && cause != nil { + msg := check.sprintf(format, args...) + if *cause != "" { + msg += "\n\t" + *cause + } + *cause = msg + } + } + + // generic cases with specific type terms + // (generic operands cannot be constants, so we can ignore x.val) + switch { + case Vp != nil && Tp != nil: + x := *x // don't clobber outer x + return Vp.is(func(V *term) bool { + if V == nil { + return false // no specific types + } + x.typ = V.typ + return Tp.is(func(T *term) bool { + if !x.convertibleTo(check, T.typ, cause) { + errorf("cannot convert %s (in %s) to %s (in %s)", V.typ, Vp, T.typ, Tp) + return false + } + return true + }) + }) + case Vp != nil: + x := *x // don't clobber outer x + return Vp.is(func(V *term) bool { + if V == nil { + return false // no specific types + } + x.typ = V.typ + if !x.convertibleTo(check, T, cause) { + errorf("cannot convert %s (in %s) to %s", V.typ, Vp, T) + return false + } + return true + }) + case Tp != nil: + return Tp.is(func(T *term) bool { + if T == nil { + return false // no specific types + } + if !x.convertibleTo(check, T.typ, cause) { + errorf("cannot convert %s to %s (in %s)", x.typ, T.typ, Tp) + return false + } + return true + }) + } + return false } -- GitLab From f59d36d2e3f0707c8bf2b157009ffc38a9b74d25 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 9 Nov 2021 11:19:20 -0500 Subject: [PATCH 2070/2500] go/types: make object test an external test This is a port of CL 361409 to go/types. Change-Id: I17ccf8a5b4ba715fd8a87ea2c1811700fb1157e3 Reviewed-on: https://go-review.googlesource.com/c/go/+/362538 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/object_test.go | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/go/types/object_test.go b/src/go/types/object_test.go index c12af64df7..e9a4bd6dbf 100644 --- a/src/go/types/object_test.go +++ b/src/go/types/object_test.go @@ -2,13 +2,15 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package types +package types_test import ( "go/ast" "go/parser" "go/token" "testing" + + . "go/types" ) func TestIsAlias(t *testing.T) { @@ -36,15 +38,15 @@ func TestIsAlias(t *testing.T) { name *TypeName alias bool }{ - {NewTypeName(0, nil, "t0", nil), false}, // no type yet - {NewTypeName(0, pkg, "t0", nil), false}, // no type yet - {t1, false}, // type name refers to named type and vice versa - {NewTypeName(0, nil, "t2", &emptyInterface), true}, // type name refers to unnamed type - {NewTypeName(0, pkg, "t3", n1), true}, // type name refers to named type with different type name - {NewTypeName(0, nil, "t4", Typ[Int32]), true}, // type name refers to basic type with different name - {NewTypeName(0, nil, "int32", Typ[Int32]), false}, // type name refers to basic type with same name - {NewTypeName(0, pkg, "int32", Typ[Int32]), true}, // type name is declared in user-defined package (outside Universe) - {NewTypeName(0, nil, "rune", Typ[Rune]), true}, // type name refers to basic type rune which is an alias already + {NewTypeName(0, nil, "t0", nil), false}, // no type yet + {NewTypeName(0, pkg, "t0", nil), false}, // no type yet + {t1, false}, // type name refers to named type and vice versa + {NewTypeName(0, nil, "t2", NewInterfaceType(nil, nil)), true}, // type name refers to unnamed type + {NewTypeName(0, pkg, "t3", n1), true}, // type name refers to named type with different type name + {NewTypeName(0, nil, "t4", Typ[Int32]), true}, // type name refers to basic type with different name + {NewTypeName(0, nil, "int32", Typ[Int32]), false}, // type name refers to basic type with same name + {NewTypeName(0, pkg, "int32", Typ[Int32]), true}, // type name is declared in user-defined package (outside Universe) + {NewTypeName(0, nil, "rune", Typ[Rune]), true}, // type name refers to basic type rune which is an alias already {t5, false}, // type name refers to type parameter and vice versa } { check(test.name, test.alias) -- GitLab From d3aedb72c687cc58e10755eff006a4dd45cb8e15 Mon Sep 17 00:00:00 2001 From: Chaoqun Han Date: Mon, 8 Nov 2021 22:58:51 +0800 Subject: [PATCH 2071/2500] cmd/compile: NewSelectorExpr use n.Pos instead of base.Pos Fixes #49436 Change-Id: I4c8851e7aaee631d5eb22f2ef0aea5a25e936d87 Reviewed-on: https://go-review.googlesource.com/c/go/+/361917 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: David Chase --- src/cmd/compile/internal/typecheck/subr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 1986845f64..5b5b043715 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -160,7 +160,7 @@ func AddImplicitDots(n *ir.SelectorExpr) *ir.SelectorExpr { case path != nil: // rebuild elided dots for c := len(path) - 1; c >= 0; c-- { - dot := ir.NewSelectorExpr(base.Pos, ir.ODOT, n.X, path[c].field.Sym) + dot := ir.NewSelectorExpr(n.Pos(), ir.ODOT, n.X, path[c].field.Sym) dot.SetImplicit(true) dot.SetType(path[c].field.Type) n.X = dot -- GitLab From 8c20584a8206844be705c50efe8aabb6ab9c503e Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 8 Nov 2021 13:57:50 -0800 Subject: [PATCH 2072/2500] bufio: document that NewWriter can return its argument Fixes #49446 Change-Id: Ib0b53a7dd5d567a2dd0bdf29f53d276587b60afb Reviewed-on: https://go-review.googlesource.com/c/go/+/361921 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Tobias Klauser --- src/bufio/bufio.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bufio/bufio.go b/src/bufio/bufio.go index 063a7785f3..9ea058db3e 100644 --- a/src/bufio/bufio.go +++ b/src/bufio/bufio.go @@ -593,6 +593,8 @@ func NewWriterSize(w io.Writer, size int) *Writer { } // NewWriter returns a new Writer whose buffer has the default size. +// If the argument io.Writer is already a Writer with large enough buffer size, +// it returns the underlying Writer. func NewWriter(w io.Writer) *Writer { return NewWriterSize(w, defaultBufSize) } -- GitLab From f48115c6502a3fb791dc4b37f5817024c9731ee3 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 8 Nov 2021 18:30:30 -0800 Subject: [PATCH 2073/2500] os: clarify that File.{Read,Write} use the buffer Fixes #49470 Change-Id: I81fd4b0e2eef1d8d430b5d1d10c4f824e803a75c Reviewed-on: https://go-review.googlesource.com/c/go/+/362335 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/os/file.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/os/file.go b/src/os/file.go index e717f171e7..2823128554 100644 --- a/src/os/file.go +++ b/src/os/file.go @@ -109,7 +109,7 @@ func (e *LinkError) Unwrap() error { return e.Err } -// Read reads up to len(b) bytes from the File. +// Read reads up to len(b) bytes from the File and stores them in b. // It returns the number of bytes read and any error encountered. // At end of file, Read returns 0, io.EOF. func (f *File) Read(b []byte) (n int, err error) { @@ -166,7 +166,7 @@ type onlyWriter struct { io.Writer } -// Write writes len(b) bytes to the File. +// Write writes len(b) bytes from b to the File. // It returns the number of bytes written and an error, if any. // Write returns a non-nil error when n != len(b). func (f *File) Write(b []byte) (n int, err error) { -- GitLab From 233ea216c730a1902579ab2dea6d752e02d6f6f3 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Tue, 9 Nov 2021 13:31:45 -0500 Subject: [PATCH 2074/2500] all: update vendored golang.org/x/{arch,sys,term} for Go 1.18 release The Go 1.18 code freeze has recently started. This is a time to update all golang.org/x/... module versions that contribute packages to the std and cmd modules in the standard library to latest master versions. This CL updates only the lower-level modules arch, sys, term for better bisection. The next CL will update further ones. For #36905. Change-Id: I455428c051ec49b446b8b558a6f579cd9be4d796 Reviewed-on: https://go-review.googlesource.com/c/go/+/362734 Trust: Dmitri Shuralyov Run-TryBot: Dmitri Shuralyov Reviewed-by: Heschi Kreinick TryBot-Result: Go Bot --- src/cmd/go.mod | 6 +- src/cmd/go.sum | 11 +- .../golang.org/x/arch/ppc64/ppc64asm/gnu.go | 14 +- .../golang.org/x/arch/ppc64/ppc64asm/plan9.go | 71 ++-- .../golang.org/x/arch/x86/x86asm/plan9x.go | 1 + .../golang.org/x/sys/unix/sockcmsg_linux.go | 49 +++ .../golang.org/x/sys/unix/syscall_aix.go | 22 +- .../golang.org/x/sys/unix/syscall_bsd.go | 24 +- .../golang.org/x/sys/unix/syscall_darwin.go | 21 +- .../golang.org/x/sys/unix/syscall_linux.go | 42 +-- .../golang.org/x/sys/unix/syscall_solaris.go | 16 +- .../x/sys/unix/syscall_zos_s390x.go | 16 +- .../golang.org/x/sys/unix/zerrors_linux.go | 26 ++ .../x/sys/unix/zerrors_linux_386.go | 1 + .../x/sys/unix/zerrors_linux_amd64.go | 1 + .../x/sys/unix/zerrors_linux_arm.go | 1 + .../x/sys/unix/zerrors_linux_arm64.go | 1 + .../x/sys/unix/zerrors_linux_mips.go | 1 + .../x/sys/unix/zerrors_linux_mips64.go | 1 + .../x/sys/unix/zerrors_linux_mips64le.go | 1 + .../x/sys/unix/zerrors_linux_mipsle.go | 1 + .../x/sys/unix/zerrors_linux_ppc.go | 1 + .../x/sys/unix/zerrors_linux_ppc64.go | 1 + .../x/sys/unix/zerrors_linux_ppc64le.go | 1 + .../x/sys/unix/zerrors_linux_riscv64.go | 1 + .../x/sys/unix/zerrors_linux_s390x.go | 1 + .../x/sys/unix/zerrors_linux_sparc64.go | 1 + .../golang.org/x/sys/unix/zsyscall_aix_ppc.go | 22 +- .../x/sys/unix/zsyscall_aix_ppc64.go | 20 +- .../x/sys/unix/zsyscall_aix_ppc64_gc.go | 20 +- .../x/sys/unix/zsyscall_aix_ppc64_gccgo.go | 18 +- .../x/sys/unix/zsysnum_linux_386.go | 1 + .../x/sys/unix/zsysnum_linux_amd64.go | 1 + .../x/sys/unix/zsysnum_linux_arm.go | 2 + .../x/sys/unix/zsysnum_linux_arm64.go | 1 + .../x/sys/unix/zsysnum_linux_mips.go | 1 + .../x/sys/unix/zsysnum_linux_mips64.go | 1 + .../x/sys/unix/zsysnum_linux_mips64le.go | 1 + .../x/sys/unix/zsysnum_linux_mipsle.go | 1 + .../x/sys/unix/zsysnum_linux_ppc.go | 1 + .../x/sys/unix/zsysnum_linux_ppc64.go | 1 + .../x/sys/unix/zsysnum_linux_ppc64le.go | 1 + .../x/sys/unix/zsysnum_linux_riscv64.go | 1 + .../x/sys/unix/zsysnum_linux_s390x.go | 1 + .../x/sys/unix/zsysnum_linux_sparc64.go | 1 + .../x/sys/unix/ztypes_darwin_amd64.go | 6 +- .../x/sys/unix/ztypes_darwin_arm64.go | 6 +- .../golang.org/x/sys/unix/ztypes_linux.go | 7 +- .../x/sys/unix/ztypes_openbsd_386.go | 11 +- .../x/sys/unix/ztypes_openbsd_amd64.go | 11 +- .../x/sys/unix/ztypes_openbsd_arm.go | 11 +- .../x/sys/unix/ztypes_openbsd_arm64.go | 11 +- .../x/sys/unix/ztypes_openbsd_mips64.go | 11 +- .../golang.org/x/sys/windows/aliases.go | 4 +- .../golang.org/x/sys/windows/eventlog.go | 1 + .../golang.org/x/sys/windows/mksyscall.go | 1 + .../vendor/golang.org/x/sys/windows/race.go | 1 + .../vendor/golang.org/x/sys/windows/race0.go | 1 + .../golang.org/x/sys/windows/service.go | 14 +- .../vendor/golang.org/x/sys/windows/str.go | 1 + .../golang.org/x/sys/windows/syscall.go | 1 + .../x/sys/windows/syscall_windows.go | 26 +- .../golang.org/x/sys/windows/types_windows.go | 337 +++++++++++++++++- .../x/sys/windows/zsyscall_windows.go | 120 +++++++ .../vendor/golang.org/x/term/codereview.cfg | 1 + src/cmd/vendor/golang.org/x/term/term.go | 2 + src/cmd/vendor/modules.txt | 6 +- src/go.mod | 2 +- src/go.sum | 4 +- src/vendor/golang.org/x/sys/cpu/cpu_x86.go | 7 +- src/vendor/golang.org/x/sys/cpu/cpu_x86.s | 24 -- src/vendor/modules.txt | 2 +- 72 files changed, 790 insertions(+), 267 deletions(-) create mode 100644 src/cmd/vendor/golang.org/x/term/codereview.cfg diff --git a/src/cmd/go.mod b/src/cmd/go.mod index f7802a1675..ea4e8a3104 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -4,16 +4,16 @@ go 1.18 require ( github.com/google/pprof v0.0.0-20211104044539-f987b9c94b31 - golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1 + golang.org/x/arch v0.0.0-20210923205945-b76863e36670 golang.org/x/mod v0.5.1-0.20210913215816-37dd6891021a golang.org/x/sync v0.0.0-20210220032951-036812b2e83c - golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 golang.org/x/tools v0.1.8-0.20211025211149-f916b54a1784 ) require ( github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d // indirect golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect - golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect + golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 25c25d81bd..01da0f686c 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -5,18 +5,19 @@ github.com/google/pprof v0.0.0-20211104044539-f987b9c94b31 h1:YvpxjnjGhf/vDEeYOy github.com/google/pprof v0.0.0-20211104044539-f987b9c94b31/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d h1:uGg2frlt3IcT7kbV6LEp5ONv4vmoO2FW4qSO+my/aoM= github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= -golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1 h1:MwxAfiDvuwX8Nnnc6iRDhzyMyyc2tz5tYyCP/pZcPCg= -golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/mod v0.5.1-0.20210913215816-37dd6891021a h1:55PVa91KndtPGH2lus5l2gDZqoO/x+Oa5CV0lVf8Ij8= golang.org/x/mod v0.5.1-0.20210913215816-37dd6891021a/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac h1:oN6lz7iLW/YC7un8pq+9bOLyXrprv2+DKfkJY+2LJJw= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE= -golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e h1:i6Vklmyu+fZMFYpum+sR4ZWABGW7MyIxfJZXYvcnbns= +golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/tools v0.1.8-0.20211025211149-f916b54a1784 h1:+xP+QoP2SEPgbn+07I/yJTzP+gavj0XKGS6+JU5tlck= golang.org/x/tools v0.1.8-0.20211025211149-f916b54a1784/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= diff --git a/src/cmd/vendor/golang.org/x/arch/ppc64/ppc64asm/gnu.go b/src/cmd/vendor/golang.org/x/arch/ppc64/ppc64asm/gnu.go index 225ef4fb88..b4c9bf8df6 100644 --- a/src/cmd/vendor/golang.org/x/arch/ppc64/ppc64asm/gnu.go +++ b/src/cmd/vendor/golang.org/x/arch/ppc64/ppc64asm/gnu.go @@ -297,12 +297,17 @@ func GNUSyntax(inst Inst, pc uint64) string { gnuArg(&inst, 0, inst.Args[0], PC), gnuArg(&inst, 2, inst.Args[2], PC)) startArg = 4 - } else if r == 0 { + } else { str = fmt.Sprintf("%s %s,%s,%s", opName, gnuArg(&inst, 0, inst.Args[0], PC), gnuArg(&inst, 1, inst.Args[1], PC), gnuArg(&inst, 2, inst.Args[2], PC)) startArg = 4 + if r == 1 { + // This is an illegal encoding (ra != 0 && r == 1) on ISA 3.1. + v := uint64(inst.Enc)<<32 | uint64(inst.SuffixEnc) + return fmt.Sprintf(".quad 0x%x", v) + } } buf.WriteString(str) @@ -317,11 +322,16 @@ func GNUSyntax(inst Inst, pc uint64) string { str := fmt.Sprintf("%s %s,%d", opName, gnuArg(&inst, 0, inst.Args[0], PC), d) buf.WriteString(str) startArg = 4 - } else if r == 0 { + } else { str := fmt.Sprintf("%s %s,%d(%s)", opName, gnuArg(&inst, 0, inst.Args[0], PC), d, gnuArg(&inst, 2, inst.Args[2], PC)) + if r == 1 { + // This is an invalid encoding (ra != 0 && r == 1) on ISA 3.1. + v := uint64(inst.Enc)<<32 | uint64(inst.SuffixEnc) + return fmt.Sprintf(".quad 0x%x", v) + } buf.WriteString(str) startArg = 4 } diff --git a/src/cmd/vendor/golang.org/x/arch/ppc64/ppc64asm/plan9.go b/src/cmd/vendor/golang.org/x/arch/ppc64/ppc64asm/plan9.go index 89b917320a..88e8e1c747 100644 --- a/src/cmd/vendor/golang.org/x/arch/ppc64/ppc64asm/plan9.go +++ b/src/cmd/vendor/golang.org/x/arch/ppc64/ppc64asm/plan9.go @@ -30,18 +30,7 @@ func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64)) strin break } if s := plan9Arg(&inst, i, pc, a, symname); s != "" { - // In the case for some BC instructions, a CondReg arg has - // both the CR and the branch condition encoded in its value. - // plan9Arg will return a string with the string representation - // of these values separated by a blank that will be treated - // as 2 args from this point on. - if strings.IndexByte(s, ' ') > 0 { - t := strings.Split(s, " ") - args = append(args, t[0]) - args = append(args, t[1]) - } else { - args = append(args, s) - } + args = append(args, s) } } var op string @@ -61,7 +50,7 @@ func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64)) strin case 1: return fmt.Sprintf("%s %s", op, args[0]) case 2: - if inst.Op == COPY || inst.Op == PASTECC || inst.Op == FCMPO || inst.Op == FCMPU { + if inst.Op == COPY || inst.Op == PASTECC { return op + " " + args[0] + "," + args[1] } return op + " " + args[1] + "," + args[0] @@ -97,13 +86,13 @@ func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64)) strin STQ, STFD, STFDU, STFS, STFSU: return op + " " + strings.Join(args, ",") - case CMPD, CMPDI, CMPLD, CMPLDI, CMPW, CMPWI, CMPLW, CMPLWI: - if len(args) == 2 { - return op + " " + args[0] + "," + args[1] - } else if len(args) == 3 { - return op + " " + args[0] + "," + args[1] + "," + args[2] + case FCMPU, FCMPO, CMPD, CMPDI, CMPLD, CMPLDI, CMPW, CMPWI, CMPLW, CMPLWI: + crf := int(inst.Args[0].(CondReg) - CR0) + cmpstr := op + " " + args[1] + "," + args[2] + if crf != 0 { // print CRx as the final operand if not implied (i.e BF != 0) + cmpstr += "," + args[0] } - return op + " " + args[0] + " ??" + return cmpstr case LIS: return "ADDIS $0," + args[1] + "," + args[0] @@ -152,16 +141,15 @@ func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64)) strin } return op + " " + strings.Join(args, ", ") case BC: - if int(inst.Args[0].(Imm))&0x1c == 12 { // jump on cond bit set - if len(args) == 4 { - return fmt.Sprintf("B%s %s,%s", args[1], args[2], args[3]) - } - return fmt.Sprintf("B%s %s", args[1], args[2]) - } else if int(inst.Args[0].(Imm))&0x1c == 4 && revCondMap[args[1]] != "" { // jump on cond bit not set - if len(args) == 4 { - return fmt.Sprintf("B%s %s,%s", revCondMap[args[1]], args[2], args[3]) + bo := int(inst.Args[0].(Imm)) + bi := int(inst.Args[1].(CondReg) - Cond0LT) + bcname := condName[((bo&0x8)>>1)|(bi&0x3)] + if bo&0x17 == 4 { // jump only a CR bit set/unset, no hints (at bits) set. + if bi >= 4 { + return fmt.Sprintf("B%s CR%d,%s", bcname, bi>>2, args[2]) + } else { + return fmt.Sprintf("B%s %s", bcname, args[2]) } - return fmt.Sprintf("B%s %s", revCondMap[args[1]], args[2]) } return op + " " + strings.Join(args, ",") case BCCTR: @@ -203,19 +191,14 @@ func plan9Arg(inst *Inst, argIndex int, pc uint64, arg Arg, symname func(uint64) if inst.Op == ISEL { return fmt.Sprintf("$%d", (arg - Cond0LT)) } - if arg == CR0 && (strings.HasPrefix(inst.Op.String(), "cmp") || strings.HasPrefix(inst.Op.String(), "fcmp")) { - return "" // don't show cr0 for cmp instructions - } else if arg >= CR0 { - return fmt.Sprintf("CR%d", int(arg-CR0)) - } bit := [4]string{"LT", "GT", "EQ", "SO"}[(arg-Cond0LT)%4] - if strings.HasPrefix(inst.Op.String(), "cr") { - return fmt.Sprintf("CR%d%s", int(arg-Cond0LT)/4, bit) - } if arg <= Cond0SO { return bit + } else if arg > Cond0SO && arg <= Cond7SO { + return fmt.Sprintf("CR%d%s", int(arg-Cond0LT)/4, bit) + } else { + return fmt.Sprintf("CR%d", int(arg-CR0)) } - return fmt.Sprintf("%s CR%d", bit, int(arg-Cond0LT)/4) case Imm: return fmt.Sprintf("$%d", arg) case SpReg: @@ -281,6 +264,20 @@ var revCondMap = map[string]string{ "LT": "GE", "GT": "LE", "EQ": "NE", } +// Lookup table to map BI[0:1] and BO[3] to an extended mnemonic for CR ops. +// Bits 0-1 map to a bit with a CR field, and bit 2 selects the inverted (0) +// or regular (1) extended mnemonic. +var condName = []string{ + "GE", + "LE", + "NE", + "NSO", + "LT", + "GT", + "EQ", + "SO", +} + // plan9OpMap maps an Op to its Plan 9 mnemonics, if different than its GNU mnemonics. var plan9OpMap = map[Op]string{ LWARX: "LWAR", diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x.go b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x.go index a93bffd441..59d8f97753 100644 --- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x.go +++ b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x.go @@ -204,6 +204,7 @@ var plan9Suffix = [maxOp + 1]bool{ OUT: true, POP: true, POPA: true, + POPCNT: true, PUSH: true, PUSHA: true, RCL: true, diff --git a/src/cmd/vendor/golang.org/x/sys/unix/sockcmsg_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/sockcmsg_linux.go index 8bf4570594..5f63147e06 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/sockcmsg_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/sockcmsg_linux.go @@ -34,3 +34,52 @@ func ParseUnixCredentials(m *SocketControlMessage) (*Ucred, error) { ucred := *(*Ucred)(unsafe.Pointer(&m.Data[0])) return &ucred, nil } + +// PktInfo4 encodes Inet4Pktinfo into a socket control message of type IP_PKTINFO. +func PktInfo4(info *Inet4Pktinfo) []byte { + b := make([]byte, CmsgSpace(SizeofInet4Pktinfo)) + h := (*Cmsghdr)(unsafe.Pointer(&b[0])) + h.Level = SOL_IP + h.Type = IP_PKTINFO + h.SetLen(CmsgLen(SizeofInet4Pktinfo)) + *(*Inet4Pktinfo)(h.data(0)) = *info + return b +} + +// PktInfo6 encodes Inet6Pktinfo into a socket control message of type IPV6_PKTINFO. +func PktInfo6(info *Inet6Pktinfo) []byte { + b := make([]byte, CmsgSpace(SizeofInet6Pktinfo)) + h := (*Cmsghdr)(unsafe.Pointer(&b[0])) + h.Level = SOL_IPV6 + h.Type = IPV6_PKTINFO + h.SetLen(CmsgLen(SizeofInet6Pktinfo)) + *(*Inet6Pktinfo)(h.data(0)) = *info + return b +} + +// ParseOrigDstAddr decodes a socket control message containing the original +// destination address. To receive such a message the IP_RECVORIGDSTADDR or +// IPV6_RECVORIGDSTADDR option must be enabled on the socket. +func ParseOrigDstAddr(m *SocketControlMessage) (Sockaddr, error) { + switch { + case m.Header.Level == SOL_IP && m.Header.Type == IP_ORIGDSTADDR: + pp := (*RawSockaddrInet4)(unsafe.Pointer(&m.Data[0])) + sa := new(SockaddrInet4) + p := (*[2]byte)(unsafe.Pointer(&pp.Port)) + sa.Port = int(p[0])<<8 + int(p[1]) + sa.Addr = pp.Addr + return sa, nil + + case m.Header.Level == SOL_IPV6 && m.Header.Type == IPV6_ORIGDSTADDR: + pp := (*RawSockaddrInet6)(unsafe.Pointer(&m.Data[0])) + sa := new(SockaddrInet6) + p := (*[2]byte)(unsafe.Pointer(&pp.Port)) + sa.Port = int(p[0])<<8 + int(p[1]) + sa.ZoneId = pp.Scope_id + sa.Addr = pp.Addr + return sa, nil + + default: + return nil, EINVAL + } +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_aix.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_aix.go index d8efb715ff..6192750ce3 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_aix.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_aix.go @@ -70,9 +70,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil } @@ -85,9 +83,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) sa.raw.Scope_id = sa.ZoneId - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil } @@ -261,9 +257,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { sa := new(SockaddrInet4) p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil case AF_INET6: @@ -272,9 +266,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) sa.ZoneId = pp.Scope_id - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil } return nil, EAFNOSUPPORT @@ -385,6 +377,11 @@ func (w WaitStatus) TrapCause() int { return -1 } //sys fcntl(fd int, cmd int, arg int) (val int, err error) +//sys fsyncRange(fd int, how int, start int64, length int64) (err error) = fsync_range +func Fsync(fd int) error { + return fsyncRange(fd, O_SYNC, 0, 0) +} + /* * Direct access */ @@ -401,7 +398,6 @@ func (w WaitStatus) TrapCause() int { return -1 } //sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) //sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) //sys Fdatasync(fd int) (err error) -//sys Fsync(fd int) (err error) // readdir_r //sysnb Getpgid(pid int) (pgid int, err error) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_bsd.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_bsd.go index 95ac3946b5..0ce4523261 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_bsd.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_bsd.go @@ -163,9 +163,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil } @@ -179,9 +177,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) sa.raw.Scope_id = sa.ZoneId - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil } @@ -210,9 +206,7 @@ func (sa *SockaddrDatalink) sockaddr() (unsafe.Pointer, _Socklen, error) { sa.raw.Nlen = sa.Nlen sa.raw.Alen = sa.Alen sa.raw.Slen = sa.Slen - for i := 0; i < len(sa.raw.Data); i++ { - sa.raw.Data[i] = sa.Data[i] - } + sa.raw.Data = sa.Data return unsafe.Pointer(&sa.raw), SizeofSockaddrDatalink, nil } @@ -228,9 +222,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { sa.Nlen = pp.Nlen sa.Alen = pp.Alen sa.Slen = pp.Slen - for i := 0; i < len(sa.Data); i++ { - sa.Data[i] = pp.Data[i] - } + sa.Data = pp.Data return sa, nil case AF_UNIX: @@ -262,9 +254,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { sa := new(SockaddrInet4) p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil case AF_INET6: @@ -273,9 +263,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) sa.ZoneId = pp.Scope_id - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil } return anyToSockaddrGOOS(fd, rsa) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go index a8c13317d7..8826f41435 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go @@ -430,8 +430,25 @@ func GetsockoptXucred(fd, level, opt int) (*Xucred, error) { return x, err } -func SysctlKinfoProcSlice(name string) ([]KinfoProc, error) { - mib, err := sysctlmib(name) +func SysctlKinfoProc(name string, args ...int) (*KinfoProc, error) { + mib, err := sysctlmib(name, args...) + if err != nil { + return nil, err + } + + var kinfo KinfoProc + n := uintptr(SizeofKinfoProc) + if err := sysctl(mib, (*byte)(unsafe.Pointer(&kinfo)), &n, nil, 0); err != nil { + return nil, err + } + if n != SizeofKinfoProc { + return nil, EIO + } + return &kinfo, nil +} + +func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) { + mib, err := sysctlmib(name, args...) if err != nil { return nil, err } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go index fff38a84c9..bc9dc2e10a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -372,9 +372,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil } @@ -387,9 +385,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) sa.raw.Scope_id = sa.ZoneId - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil } @@ -438,9 +434,7 @@ func (sa *SockaddrLinklayer) sockaddr() (unsafe.Pointer, _Socklen, error) { sa.raw.Hatype = sa.Hatype sa.raw.Pkttype = sa.Pkttype sa.raw.Halen = sa.Halen - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrLinklayer, nil } @@ -855,12 +849,10 @@ func (sa *SockaddrTIPC) sockaddr() (unsafe.Pointer, _Socklen, error) { if sa.Addr == nil { return nil, 0, EINVAL } - sa.raw.Family = AF_TIPC sa.raw.Scope = int8(sa.Scope) sa.raw.Addrtype = sa.Addr.tipcAddrtype() sa.raw.Addr = sa.Addr.tipcAddr() - return unsafe.Pointer(&sa.raw), SizeofSockaddrTIPC, nil } @@ -874,9 +866,7 @@ type SockaddrL2TPIP struct { func (sa *SockaddrL2TPIP) sockaddr() (unsafe.Pointer, _Socklen, error) { sa.raw.Family = AF_INET sa.raw.Conn_id = sa.ConnId - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrL2TPIP, nil } @@ -892,9 +882,7 @@ func (sa *SockaddrL2TPIP6) sockaddr() (unsafe.Pointer, _Socklen, error) { sa.raw.Family = AF_INET6 sa.raw.Conn_id = sa.ConnId sa.raw.Scope_id = sa.ZoneId - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrL2TPIP6, nil } @@ -990,9 +978,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { sa.Hatype = pp.Hatype sa.Pkttype = pp.Pkttype sa.Halen = pp.Halen - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil case AF_UNIX: @@ -1031,18 +1017,14 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { pp := (*RawSockaddrL2TPIP)(unsafe.Pointer(rsa)) sa := new(SockaddrL2TPIP) sa.ConnId = pp.Conn_id - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil default: pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)) sa := new(SockaddrInet4) p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil } @@ -1058,9 +1040,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { sa := new(SockaddrL2TPIP6) sa.ConnId = pp.Conn_id sa.ZoneId = pp.Scope_id - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil default: pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)) @@ -1068,9 +1048,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) sa.ZoneId = pp.Scope_id - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_solaris.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_solaris.go index d2a6495c7e..8b88ac2133 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_solaris.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_solaris.go @@ -92,9 +92,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil } @@ -107,9 +105,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) sa.raw.Scope_id = sa.ZoneId - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil } @@ -417,9 +413,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { sa := new(SockaddrInet4) p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil case AF_INET6: @@ -428,9 +422,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) sa.ZoneId = pp.Scope_id - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil } return nil, EAFNOSUPPORT diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go index 1ffd8bfcfb..5fb76a1468 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go @@ -67,9 +67,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil } @@ -83,9 +81,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) sa.raw.Scope_id = sa.ZoneId - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil } @@ -144,9 +140,7 @@ func anyToSockaddr(_ int, rsa *RawSockaddrAny) (Sockaddr, error) { sa := new(SockaddrInet4) p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil case AF_INET6: @@ -155,9 +149,7 @@ func anyToSockaddr(_ int, rsa *RawSockaddrAny) (Sockaddr, error) { p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) sa.ZoneId = pp.Scope_id - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil } return nil, EAFNOSUPPORT diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go index 78d4b85ece..3bbc527519 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -116,6 +116,7 @@ const ( ARPHRD_LAPB = 0x204 ARPHRD_LOCALTLK = 0x305 ARPHRD_LOOPBACK = 0x304 + ARPHRD_MCTP = 0x122 ARPHRD_METRICOM = 0x17 ARPHRD_NETLINK = 0x338 ARPHRD_NETROM = 0x0 @@ -472,6 +473,7 @@ const ( DM_DEV_WAIT = 0xc138fd08 DM_DIR = "mapper" DM_GET_TARGET_VERSION = 0xc138fd11 + DM_IMA_MEASUREMENT_FLAG = 0x80000 DM_INACTIVE_PRESENT_FLAG = 0x40 DM_INTERNAL_SUSPEND_FLAG = 0x40000 DM_IOCTL = 0xfd @@ -716,6 +718,7 @@ const ( ETH_P_LOOPBACK = 0x9000 ETH_P_MACSEC = 0x88e5 ETH_P_MAP = 0xf9 + ETH_P_MCTP = 0xfa ETH_P_MOBITEX = 0x15 ETH_P_MPLS_MC = 0x8848 ETH_P_MPLS_UC = 0x8847 @@ -751,6 +754,21 @@ const ( ETH_P_WCCP = 0x883e ETH_P_X25 = 0x805 ETH_P_XDSA = 0xf8 + EV_ABS = 0x3 + EV_CNT = 0x20 + EV_FF = 0x15 + EV_FF_STATUS = 0x17 + EV_KEY = 0x1 + EV_LED = 0x11 + EV_MAX = 0x1f + EV_MSC = 0x4 + EV_PWR = 0x16 + EV_REL = 0x2 + EV_REP = 0x14 + EV_SND = 0x12 + EV_SW = 0x5 + EV_SYN = 0x0 + EV_VERSION = 0x10001 EXABYTE_ENABLE_NEST = 0xf0 EXT2_SUPER_MAGIC = 0xef53 EXT3_SUPER_MAGIC = 0xef53 @@ -789,9 +807,11 @@ const ( FAN_DELETE_SELF = 0x400 FAN_DENY = 0x2 FAN_ENABLE_AUDIT = 0x40 + FAN_EPIDFD = -0x2 FAN_EVENT_INFO_TYPE_DFID = 0x3 FAN_EVENT_INFO_TYPE_DFID_NAME = 0x2 FAN_EVENT_INFO_TYPE_FID = 0x1 + FAN_EVENT_INFO_TYPE_PIDFD = 0x4 FAN_EVENT_METADATA_LEN = 0x18 FAN_EVENT_ON_CHILD = 0x8000000 FAN_MARK_ADD = 0x1 @@ -811,6 +831,7 @@ const ( FAN_MOVE_SELF = 0x800 FAN_NOFD = -0x1 FAN_NONBLOCK = 0x2 + FAN_NOPIDFD = -0x1 FAN_ONDIR = 0x40000000 FAN_OPEN = 0x20 FAN_OPEN_EXEC = 0x1000 @@ -821,6 +842,7 @@ const ( FAN_REPORT_DIR_FID = 0x400 FAN_REPORT_FID = 0x200 FAN_REPORT_NAME = 0x800 + FAN_REPORT_PIDFD = 0x80 FAN_REPORT_TID = 0x100 FAN_UNLIMITED_MARKS = 0x20 FAN_UNLIMITED_QUEUE = 0x10 @@ -1997,6 +2019,7 @@ const ( PR_SPEC_ENABLE = 0x2 PR_SPEC_FORCE_DISABLE = 0x8 PR_SPEC_INDIRECT_BRANCH = 0x1 + PR_SPEC_L1D_FLUSH = 0x2 PR_SPEC_NOT_AFFECTED = 0x0 PR_SPEC_PRCTL = 0x1 PR_SPEC_STORE_BYPASS = 0x0 @@ -2432,12 +2455,15 @@ const ( SMART_WRITE_THRESHOLDS = 0xd7 SMB_SUPER_MAGIC = 0x517b SOCKFS_MAGIC = 0x534f434b + SOCK_BUF_LOCK_MASK = 0x3 SOCK_DCCP = 0x6 SOCK_IOC_TYPE = 0x89 SOCK_PACKET = 0xa SOCK_RAW = 0x3 + SOCK_RCVBUF_LOCK = 0x2 SOCK_RDM = 0x4 SOCK_SEQPACKET = 0x5 + SOCK_SNDBUF_LOCK = 0x1 SOL_AAL = 0x109 SOL_ALG = 0x117 SOL_ATM = 0x108 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index 697811a460..80c790840c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -293,6 +293,7 @@ const ( SO_BPF_EXTENSIONS = 0x30 SO_BROADCAST = 0x6 SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 SO_BUSY_POLL = 0x2e SO_BUSY_POLL_BUDGET = 0x46 SO_CNX_ADVICE = 0x35 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index 7d8d93bfc4..da55638a44 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -294,6 +294,7 @@ const ( SO_BPF_EXTENSIONS = 0x30 SO_BROADCAST = 0x6 SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 SO_BUSY_POLL = 0x2e SO_BUSY_POLL_BUDGET = 0x46 SO_CNX_ADVICE = 0x35 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index f707d50894..c3da063c70 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -300,6 +300,7 @@ const ( SO_BPF_EXTENSIONS = 0x30 SO_BROADCAST = 0x6 SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 SO_BUSY_POLL = 0x2e SO_BUSY_POLL_BUDGET = 0x46 SO_CNX_ADVICE = 0x35 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index 3a67a9c852..fd9f0d1dbf 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -290,6 +290,7 @@ const ( SO_BPF_EXTENSIONS = 0x30 SO_BROADCAST = 0x6 SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 SO_BUSY_POLL = 0x2e SO_BUSY_POLL_BUDGET = 0x46 SO_CNX_ADVICE = 0x35 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index a7ccef56c5..c358ada0d3 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -293,6 +293,7 @@ const ( SO_BPF_EXTENSIONS = 0x30 SO_BROADCAST = 0x20 SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 SO_BUSY_POLL = 0x2e SO_BUSY_POLL_BUDGET = 0x46 SO_CNX_ADVICE = 0x35 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index f7b7cec910..1dc1ee16b9 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -293,6 +293,7 @@ const ( SO_BPF_EXTENSIONS = 0x30 SO_BROADCAST = 0x20 SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 SO_BUSY_POLL = 0x2e SO_BUSY_POLL_BUDGET = 0x46 SO_CNX_ADVICE = 0x35 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index 4fcacf9584..3ae187dd93 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -293,6 +293,7 @@ const ( SO_BPF_EXTENSIONS = 0x30 SO_BROADCAST = 0x20 SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 SO_BUSY_POLL = 0x2e SO_BUSY_POLL_BUDGET = 0x46 SO_CNX_ADVICE = 0x35 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index 6f6c223a2c..39895f0dd1 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -293,6 +293,7 @@ const ( SO_BPF_EXTENSIONS = 0x30 SO_BROADCAST = 0x20 SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 SO_BUSY_POLL = 0x2e SO_BUSY_POLL_BUDGET = 0x46 SO_CNX_ADVICE = 0x35 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go index 59e522bcf4..a98a45537b 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go @@ -348,6 +348,7 @@ const ( SO_BPF_EXTENSIONS = 0x30 SO_BROADCAST = 0x6 SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 SO_BUSY_POLL = 0x2e SO_BUSY_POLL_BUDGET = 0x46 SO_CNX_ADVICE = 0x35 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index d4264a0f73..0a8fbbffaa 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -352,6 +352,7 @@ const ( SO_BPF_EXTENSIONS = 0x30 SO_BROADCAST = 0x6 SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 SO_BUSY_POLL = 0x2e SO_BUSY_POLL_BUDGET = 0x46 SO_CNX_ADVICE = 0x35 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index 21cbec1dd3..cb835a1442 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -352,6 +352,7 @@ const ( SO_BPF_EXTENSIONS = 0x30 SO_BROADCAST = 0x6 SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 SO_BUSY_POLL = 0x2e SO_BUSY_POLL_BUDGET = 0x46 SO_CNX_ADVICE = 0x35 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go index 9b05bf12fc..73cf6554b0 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -281,6 +281,7 @@ const ( SO_BPF_EXTENSIONS = 0x30 SO_BROADCAST = 0x6 SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 SO_BUSY_POLL = 0x2e SO_BUSY_POLL_BUDGET = 0x46 SO_CNX_ADVICE = 0x35 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index bd82ace09a..04b6dfaf5f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -356,6 +356,7 @@ const ( SO_BPF_EXTENSIONS = 0x30 SO_BROADCAST = 0x6 SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 SO_BUSY_POLL = 0x2e SO_BUSY_POLL_BUDGET = 0x46 SO_CNX_ADVICE = 0x35 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go index 1f8bded56b..8c87d979d4 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go @@ -347,6 +347,7 @@ const ( SO_BPF_EXTENSIONS = 0x32 SO_BROADCAST = 0x20 SO_BSDCOMPAT = 0x400 + SO_BUF_LOCK = 0x51 SO_BUSY_POLL = 0x30 SO_BUSY_POLL_BUDGET = 0x49 SO_CNX_ADVICE = 0x37 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc.go index 91a23cc728..85e0cc3866 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc.go @@ -17,6 +17,7 @@ int getdirent(int, uintptr_t, size_t); int wait4(int, uintptr_t, int, uintptr_t); int ioctl(int, int, uintptr_t); int fcntl(uintptr_t, int, uintptr_t); +int fsync_range(int, int, long long, long long); int acct(uintptr_t); int chdir(uintptr_t); int chroot(uintptr_t); @@ -29,7 +30,6 @@ int fchmod(int, unsigned int); int fchmodat(int, uintptr_t, unsigned int, int); int fchownat(int, uintptr_t, int, int, int); int fdatasync(int); -int fsync(int); int getpgid(int); int getpgrp(); int getpid(); @@ -255,6 +255,16 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fsyncRange(fd int, how int, start int64, length int64) (err error) { + r0, er := C.fsync_range(C.int(fd), C.int(how), C.longlong(start), C.longlong(length)) + if r0 == -1 && er != nil { + err = er + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Acct(path string) (err error) { _p0 := uintptr(unsafe.Pointer(C.CString(path))) r0, er := C.acct(C.uintptr_t(_p0)) @@ -379,16 +389,6 @@ func Fdatasync(fd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Fsync(fd int) (err error) { - r0, er := C.fsync(C.int(fd)) - if r0 == -1 && er != nil { - err = er - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Getpgid(pid int) (pgid int, err error) { r0, er := C.getpgid(C.int(pid)) pgid = int(r0) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64.go index 33c2609b8b..f1d4a73b08 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64.go @@ -135,6 +135,16 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fsyncRange(fd int, how int, start int64, length int64) (err error) { + _, e1 := callfsync_range(fd, how, start, length) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Acct(path string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -283,16 +293,6 @@ func Fdatasync(fd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Fsync(fd int) (err error) { - _, e1 := callfsync(fd) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Getpgid(pid int) (pgid int, err error) { r0, e1 := callgetpgid(pid) pgid = int(r0) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go index 8b737fa971..2caa5adf95 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go @@ -18,6 +18,7 @@ import ( //go:cgo_import_dynamic libc_wait4 wait4 "libc.a/shr_64.o" //go:cgo_import_dynamic libc_ioctl ioctl "libc.a/shr_64.o" //go:cgo_import_dynamic libc_fcntl fcntl "libc.a/shr_64.o" +//go:cgo_import_dynamic libc_fsync_range fsync_range "libc.a/shr_64.o" //go:cgo_import_dynamic libc_acct acct "libc.a/shr_64.o" //go:cgo_import_dynamic libc_chdir chdir "libc.a/shr_64.o" //go:cgo_import_dynamic libc_chroot chroot "libc.a/shr_64.o" @@ -30,7 +31,6 @@ import ( //go:cgo_import_dynamic libc_fchmodat fchmodat "libc.a/shr_64.o" //go:cgo_import_dynamic libc_fchownat fchownat "libc.a/shr_64.o" //go:cgo_import_dynamic libc_fdatasync fdatasync "libc.a/shr_64.o" -//go:cgo_import_dynamic libc_fsync fsync "libc.a/shr_64.o" //go:cgo_import_dynamic libc_getpgid getpgid "libc.a/shr_64.o" //go:cgo_import_dynamic libc_getpgrp getpgrp "libc.a/shr_64.o" //go:cgo_import_dynamic libc_getpid getpid "libc.a/shr_64.o" @@ -136,6 +136,7 @@ import ( //go:linkname libc_wait4 libc_wait4 //go:linkname libc_ioctl libc_ioctl //go:linkname libc_fcntl libc_fcntl +//go:linkname libc_fsync_range libc_fsync_range //go:linkname libc_acct libc_acct //go:linkname libc_chdir libc_chdir //go:linkname libc_chroot libc_chroot @@ -148,7 +149,6 @@ import ( //go:linkname libc_fchmodat libc_fchmodat //go:linkname libc_fchownat libc_fchownat //go:linkname libc_fdatasync libc_fdatasync -//go:linkname libc_fsync libc_fsync //go:linkname libc_getpgid libc_getpgid //go:linkname libc_getpgrp libc_getpgrp //go:linkname libc_getpid libc_getpid @@ -257,6 +257,7 @@ var ( libc_wait4, libc_ioctl, libc_fcntl, + libc_fsync_range, libc_acct, libc_chdir, libc_chroot, @@ -269,7 +270,6 @@ var ( libc_fchmodat, libc_fchownat, libc_fdatasync, - libc_fsync, libc_getpgid, libc_getpgrp, libc_getpid, @@ -430,6 +430,13 @@ func callfcntl(fd uintptr, cmd int, arg uintptr) (r1 uintptr, e1 Errno) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func callfsync_range(fd int, how int, start int64, length int64) (r1 uintptr, e1 Errno) { + r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_fsync_range)), 4, uintptr(fd), uintptr(how), uintptr(start), uintptr(length), 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func callacct(_p0 uintptr) (r1 uintptr, e1 Errno) { r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_acct)), 1, _p0, 0, 0, 0, 0, 0) return @@ -514,13 +521,6 @@ func callfdatasync(fd int) (r1 uintptr, e1 Errno) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func callfsync(fd int) (r1 uintptr, e1 Errno) { - r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_fsync)), 1, uintptr(fd), 0, 0, 0, 0, 0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func callgetpgid(pid int) (r1 uintptr, e1 Errno) { r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_getpgid)), 1, uintptr(pid), 0, 0, 0, 0, 0) return diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gccgo.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gccgo.go index 3c260917ed..944a714b1a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gccgo.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gccgo.go @@ -16,6 +16,7 @@ int getdirent(int, uintptr_t, size_t); int wait4(int, uintptr_t, int, uintptr_t); int ioctl(int, int, uintptr_t); int fcntl(uintptr_t, int, uintptr_t); +int fsync_range(int, int, long long, long long); int acct(uintptr_t); int chdir(uintptr_t); int chroot(uintptr_t); @@ -28,7 +29,6 @@ int fchmod(int, unsigned int); int fchmodat(int, uintptr_t, unsigned int, int); int fchownat(int, uintptr_t, int, int, int); int fdatasync(int); -int fsync(int); int getpgid(int); int getpgrp(); int getpid(); @@ -199,6 +199,14 @@ func callfcntl(fd uintptr, cmd int, arg uintptr) (r1 uintptr, e1 Errno) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func callfsync_range(fd int, how int, start int64, length int64) (r1 uintptr, e1 Errno) { + r1 = uintptr(C.fsync_range(C.int(fd), C.int(how), C.longlong(start), C.longlong(length))) + e1 = syscall.GetErrno() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func callacct(_p0 uintptr) (r1 uintptr, e1 Errno) { r1 = uintptr(C.acct(C.uintptr_t(_p0))) e1 = syscall.GetErrno() @@ -295,14 +303,6 @@ func callfdatasync(fd int) (r1 uintptr, e1 Errno) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func callfsync(fd int) (r1 uintptr, e1 Errno) { - r1 = uintptr(C.fsync(C.int(fd))) - e1 = syscall.GetErrno() - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func callgetpgid(pid int) (r1 uintptr, e1 Errno) { r1 = uintptr(C.getpgid(C.int(pid))) e1 = syscall.GetErrno() diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go index aa7ce85d15..31847d2305 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go @@ -444,4 +444,5 @@ const ( SYS_LANDLOCK_ADD_RULE = 445 SYS_LANDLOCK_RESTRICT_SELF = 446 SYS_MEMFD_SECRET = 447 + SYS_PROCESS_MRELEASE = 448 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go index b830326386..3503cbbde3 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go @@ -366,4 +366,5 @@ const ( SYS_LANDLOCK_ADD_RULE = 445 SYS_LANDLOCK_RESTRICT_SELF = 446 SYS_MEMFD_SECRET = 447 + SYS_PROCESS_MRELEASE = 448 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go index d75f65a0aa..5ecd24bf68 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go @@ -7,6 +7,7 @@ package unix const ( + SYS_SYSCALL_MASK = 0 SYS_RESTART_SYSCALL = 0 SYS_EXIT = 1 SYS_FORK = 2 @@ -407,4 +408,5 @@ const ( SYS_LANDLOCK_CREATE_RULESET = 444 SYS_LANDLOCK_ADD_RULE = 445 SYS_LANDLOCK_RESTRICT_SELF = 446 + SYS_PROCESS_MRELEASE = 448 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go index 8b02f09e9b..7e5c94cc7f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go @@ -311,4 +311,5 @@ const ( SYS_LANDLOCK_ADD_RULE = 445 SYS_LANDLOCK_RESTRICT_SELF = 446 SYS_MEMFD_SECRET = 447 + SYS_PROCESS_MRELEASE = 448 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go index 026695abb1..e1e2a2bf59 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go @@ -428,4 +428,5 @@ const ( SYS_LANDLOCK_CREATE_RULESET = 4444 SYS_LANDLOCK_ADD_RULE = 4445 SYS_LANDLOCK_RESTRICT_SELF = 4446 + SYS_PROCESS_MRELEASE = 4448 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go index 7320ba9583..7651915a3a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go @@ -358,4 +358,5 @@ const ( SYS_LANDLOCK_CREATE_RULESET = 5444 SYS_LANDLOCK_ADD_RULE = 5445 SYS_LANDLOCK_RESTRICT_SELF = 5446 + SYS_PROCESS_MRELEASE = 5448 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go index 45082dd67f..a26a2c050b 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go @@ -358,4 +358,5 @@ const ( SYS_LANDLOCK_CREATE_RULESET = 5444 SYS_LANDLOCK_ADD_RULE = 5445 SYS_LANDLOCK_RESTRICT_SELF = 5446 + SYS_PROCESS_MRELEASE = 5448 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go index 570a857a56..fda9a6a991 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go @@ -428,4 +428,5 @@ const ( SYS_LANDLOCK_CREATE_RULESET = 4444 SYS_LANDLOCK_ADD_RULE = 4445 SYS_LANDLOCK_RESTRICT_SELF = 4446 + SYS_PROCESS_MRELEASE = 4448 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go index 638498d62e..e8496150d4 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go @@ -435,4 +435,5 @@ const ( SYS_LANDLOCK_CREATE_RULESET = 444 SYS_LANDLOCK_ADD_RULE = 445 SYS_LANDLOCK_RESTRICT_SELF = 446 + SYS_PROCESS_MRELEASE = 448 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go index 702beebfef..5ee0678a36 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go @@ -407,4 +407,5 @@ const ( SYS_LANDLOCK_CREATE_RULESET = 444 SYS_LANDLOCK_ADD_RULE = 445 SYS_LANDLOCK_RESTRICT_SELF = 446 + SYS_PROCESS_MRELEASE = 448 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go index bfc87ea444..29c0f9a39e 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go @@ -407,4 +407,5 @@ const ( SYS_LANDLOCK_CREATE_RULESET = 444 SYS_LANDLOCK_ADD_RULE = 445 SYS_LANDLOCK_RESTRICT_SELF = 446 + SYS_PROCESS_MRELEASE = 448 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go index a390e147d3..5c9a9a3b61 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go @@ -309,4 +309,5 @@ const ( SYS_LANDLOCK_CREATE_RULESET = 444 SYS_LANDLOCK_ADD_RULE = 445 SYS_LANDLOCK_RESTRICT_SELF = 446 + SYS_PROCESS_MRELEASE = 448 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go index 3e791e6cd2..913f50f98b 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go @@ -372,4 +372,5 @@ const ( SYS_LANDLOCK_CREATE_RULESET = 444 SYS_LANDLOCK_ADD_RULE = 445 SYS_LANDLOCK_RESTRICT_SELF = 446 + SYS_PROCESS_MRELEASE = 448 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go index 78802a5cf7..0de03a7227 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go @@ -386,4 +386,5 @@ const ( SYS_LANDLOCK_CREATE_RULESET = 444 SYS_LANDLOCK_ADD_RULE = 445 SYS_LANDLOCK_RESTRICT_SELF = 446 + SYS_PROCESS_MRELEASE = 448 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go index 7efe5ccba3..885842c0eb 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go @@ -641,13 +641,13 @@ type Eproc struct { Tdev int32 Tpgid int32 Tsess uintptr - Wmesg [8]int8 + Wmesg [8]byte Xsize int32 Xrssize int16 Xccount int16 Xswrss int16 Flag int32 - Login [12]int8 + Login [12]byte Spare [4]int32 _ [4]byte } @@ -688,7 +688,7 @@ type ExternProc struct { P_priority uint8 P_usrpri uint8 P_nice int8 - P_comm [17]int8 + P_comm [17]byte P_pgrp uintptr P_addr uintptr P_xstat uint16 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go index b23a2efe81..b23c02337d 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go @@ -641,13 +641,13 @@ type Eproc struct { Tdev int32 Tpgid int32 Tsess uintptr - Wmesg [8]int8 + Wmesg [8]byte Xsize int32 Xrssize int16 Xccount int16 Xswrss int16 Flag int32 - Login [12]int8 + Login [12]byte Spare [4]int32 _ [4]byte } @@ -688,7 +688,7 @@ type ExternProc struct { P_priority uint8 P_usrpri uint8 P_nice int8 - P_comm [17]int8 + P_comm [17]byte P_pgrp uintptr P_addr uintptr P_xstat uint16 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go index 249ecfcd4c..620a6702fe 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -3264,7 +3264,8 @@ const ( LWTUNNEL_ENCAP_BPF = 0x6 LWTUNNEL_ENCAP_SEG6_LOCAL = 0x7 LWTUNNEL_ENCAP_RPL = 0x8 - LWTUNNEL_ENCAP_MAX = 0x8 + LWTUNNEL_ENCAP_IOAM6 = 0x9 + LWTUNNEL_ENCAP_MAX = 0x9 MPLS_IPTUNNEL_UNSPEC = 0x0 MPLS_IPTUNNEL_DST = 0x1 @@ -3617,7 +3618,9 @@ const ( ETHTOOL_A_COALESCE_TX_USECS_HIGH = 0x15 ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH = 0x16 ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL = 0x17 - ETHTOOL_A_COALESCE_MAX = 0x17 + ETHTOOL_A_COALESCE_USE_CQE_MODE_TX = 0x18 + ETHTOOL_A_COALESCE_USE_CQE_MODE_RX = 0x19 + ETHTOOL_A_COALESCE_MAX = 0x19 ETHTOOL_A_PAUSE_UNSPEC = 0x0 ETHTOOL_A_PAUSE_HEADER = 0x1 ETHTOOL_A_PAUSE_AUTONEG = 0x2 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go index 2a8b1e6f73..baf5fe6504 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go @@ -564,12 +564,11 @@ type Uvmexp struct { Kmapent int32 } -const SizeofClockinfo = 0x14 +const SizeofClockinfo = 0x10 type Clockinfo struct { - Hz int32 - Tick int32 - Tickadj int32 - Stathz int32 - Profhz int32 + Hz int32 + Tick int32 + Stathz int32 + Profhz int32 } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go index b1759cf705..e21ae8ecfa 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go @@ -564,12 +564,11 @@ type Uvmexp struct { Kmapent int32 } -const SizeofClockinfo = 0x14 +const SizeofClockinfo = 0x10 type Clockinfo struct { - Hz int32 - Tick int32 - Tickadj int32 - Stathz int32 - Profhz int32 + Hz int32 + Tick int32 + Stathz int32 + Profhz int32 } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go index e807de2065..f190651cd9 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go @@ -565,12 +565,11 @@ type Uvmexp struct { Kmapent int32 } -const SizeofClockinfo = 0x14 +const SizeofClockinfo = 0x10 type Clockinfo struct { - Hz int32 - Tick int32 - Tickadj int32 - Stathz int32 - Profhz int32 + Hz int32 + Tick int32 + Stathz int32 + Profhz int32 } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go index ff3aecaee4..84747c582c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go @@ -558,12 +558,11 @@ type Uvmexp struct { Kmapent int32 } -const SizeofClockinfo = 0x14 +const SizeofClockinfo = 0x10 type Clockinfo struct { - Hz int32 - Tick int32 - Tickadj int32 - Stathz int32 - Profhz int32 + Hz int32 + Tick int32 + Stathz int32 + Profhz int32 } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go index 9ecda69174..ac5c8b6370 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go @@ -558,12 +558,11 @@ type Uvmexp struct { Kmapent int32 } -const SizeofClockinfo = 0x14 +const SizeofClockinfo = 0x10 type Clockinfo struct { - Hz int32 - Tick int32 - Tickadj int32 - Stathz int32 - Profhz int32 + Hz int32 + Tick int32 + Stathz int32 + Profhz int32 } diff --git a/src/cmd/vendor/golang.org/x/sys/windows/aliases.go b/src/cmd/vendor/golang.org/x/sys/windows/aliases.go index af3af60db9..a20ebea633 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/aliases.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/aliases.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build windows -// +build go1.9 +//go:build windows && go1.9 +// +build windows,go1.9 package windows diff --git a/src/cmd/vendor/golang.org/x/sys/windows/eventlog.go b/src/cmd/vendor/golang.org/x/sys/windows/eventlog.go index 40af946e16..2cd60645ee 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/eventlog.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/eventlog.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows // +build windows package windows diff --git a/src/cmd/vendor/golang.org/x/sys/windows/mksyscall.go b/src/cmd/vendor/golang.org/x/sys/windows/mksyscall.go index 328e3b2ace..6102910989 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/mksyscall.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/mksyscall.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build generate // +build generate package windows diff --git a/src/cmd/vendor/golang.org/x/sys/windows/race.go b/src/cmd/vendor/golang.org/x/sys/windows/race.go index a74e3e24b5..9196b089ca 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/race.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/race.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows && race // +build windows,race package windows diff --git a/src/cmd/vendor/golang.org/x/sys/windows/race0.go b/src/cmd/vendor/golang.org/x/sys/windows/race0.go index e44a3cbf67..7bae4817a0 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/race0.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/race0.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows && !race // +build windows,!race package windows diff --git a/src/cmd/vendor/golang.org/x/sys/windows/service.go b/src/cmd/vendor/golang.org/x/sys/windows/service.go index b269850d06..f8deca8397 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/service.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/service.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows // +build windows package windows @@ -16,8 +17,6 @@ const ( SC_MANAGER_ALL_ACCESS = 0xf003f ) -//sys OpenSCManager(machineName *uint16, databaseName *uint16, access uint32) (handle Handle, err error) [failretval==0] = advapi32.OpenSCManagerW - const ( SERVICE_KERNEL_DRIVER = 1 SERVICE_FILE_SYSTEM_DRIVER = 2 @@ -132,6 +131,14 @@ const ( SC_EVENT_DATABASE_CHANGE = 0 SC_EVENT_PROPERTY_CHANGE = 1 SC_EVENT_STATUS_CHANGE = 2 + + SERVICE_START_REASON_DEMAND = 0x00000001 + SERVICE_START_REASON_AUTO = 0x00000002 + SERVICE_START_REASON_TRIGGER = 0x00000004 + SERVICE_START_REASON_RESTART_ON_FAILURE = 0x00000008 + SERVICE_START_REASON_DELAYEDAUTO = 0x00000010 + + SERVICE_DYNAMIC_INFORMATION_LEVEL_START_REASON = 1 ) type SERVICE_STATUS struct { @@ -216,6 +223,7 @@ type QUERY_SERVICE_LOCK_STATUS struct { LockDuration uint32 } +//sys OpenSCManager(machineName *uint16, databaseName *uint16, access uint32) (handle Handle, err error) [failretval==0] = advapi32.OpenSCManagerW //sys CloseServiceHandle(handle Handle) (err error) = advapi32.CloseServiceHandle //sys CreateService(mgr Handle, serviceName *uint16, displayName *uint16, access uint32, srvType uint32, startType uint32, errCtl uint32, pathName *uint16, loadOrderGroup *uint16, tagId *uint32, dependencies *uint16, serviceStartName *uint16, password *uint16) (handle Handle, err error) [failretval==0] = advapi32.CreateServiceW //sys OpenService(mgr Handle, serviceName *uint16, access uint32) (handle Handle, err error) [failretval==0] = advapi32.OpenServiceW @@ -235,3 +243,5 @@ type QUERY_SERVICE_LOCK_STATUS struct { //sys NotifyServiceStatusChange(service Handle, notifyMask uint32, notifier *SERVICE_NOTIFY) (ret error) = advapi32.NotifyServiceStatusChangeW //sys SubscribeServiceChangeNotifications(service Handle, eventType uint32, callback uintptr, callbackCtx uintptr, subscription *uintptr) (ret error) = sechost.SubscribeServiceChangeNotifications? //sys UnsubscribeServiceChangeNotifications(subscription uintptr) = sechost.UnsubscribeServiceChangeNotifications? +//sys RegisterServiceCtrlHandlerEx(serviceName *uint16, handlerProc uintptr, context uintptr) (handle Handle, err error) = advapi32.RegisterServiceCtrlHandlerExW +//sys QueryServiceDynamicInformation(service Handle, infoLevel uint32, dynamicInfo unsafe.Pointer) (err error) = advapi32.QueryServiceDynamicInformation? diff --git a/src/cmd/vendor/golang.org/x/sys/windows/str.go b/src/cmd/vendor/golang.org/x/sys/windows/str.go index 917cc2aae4..4fc01434e4 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/str.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/str.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows // +build windows package windows diff --git a/src/cmd/vendor/golang.org/x/sys/windows/syscall.go b/src/cmd/vendor/golang.org/x/sys/windows/syscall.go index 6122f557a0..72074d582f 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/syscall.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/syscall.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows // +build windows // Package windows contains an interface to the low-level operating system diff --git a/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go index d3b59ae69c..2ff6aa0470 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go @@ -401,6 +401,11 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys LoadResource(module Handle, resInfo Handle) (resData Handle, err error) = kernel32.LoadResource //sys LockResource(resData Handle) (addr uintptr, err error) = kernel32.LockResource +// Version APIs +//sys GetFileVersionInfoSize(filename string, zeroHandle *Handle) (bufSize uint32, err error) = version.GetFileVersionInfoSizeW +//sys GetFileVersionInfo(filename string, handle uint32, bufSize uint32, buffer unsafe.Pointer) (err error) = version.GetFileVersionInfoW +//sys VerQueryValue(block unsafe.Pointer, subBlock string, pointerToBufferPointer unsafe.Pointer, bufSize *uint32) (err error) = version.VerQueryValueW + // Process Status API (PSAPI) //sys EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) = psapi.EnumProcesses //sys EnumProcessModules(process Handle, module *Handle, cb uint32, cbNeeded *uint32) (err error) = psapi.EnumProcessModules @@ -418,11 +423,16 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys RtlInitString(destinationString *NTString, sourceString *byte) = ntdll.RtlInitString //sys NtCreateFile(handle *Handle, access uint32, oa *OBJECT_ATTRIBUTES, iosb *IO_STATUS_BLOCK, allocationSize *int64, attributes uint32, share uint32, disposition uint32, options uint32, eabuffer uintptr, ealength uint32) (ntstatus error) = ntdll.NtCreateFile //sys NtCreateNamedPipeFile(pipe *Handle, access uint32, oa *OBJECT_ATTRIBUTES, iosb *IO_STATUS_BLOCK, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (ntstatus error) = ntdll.NtCreateNamedPipeFile +//sys NtSetInformationFile(handle Handle, iosb *IO_STATUS_BLOCK, inBuffer *byte, inBufferLen uint32, class uint32) (ntstatus error) = ntdll.NtSetInformationFile //sys RtlDosPathNameToNtPathName(dosName *uint16, ntName *NTUnicodeString, ntFileNamePart *uint16, relativeName *RTL_RELATIVE_NAME) (ntstatus error) = ntdll.RtlDosPathNameToNtPathName_U_WithStatus //sys RtlDosPathNameToRelativeNtPathName(dosName *uint16, ntName *NTUnicodeString, ntFileNamePart *uint16, relativeName *RTL_RELATIVE_NAME) (ntstatus error) = ntdll.RtlDosPathNameToRelativeNtPathName_U_WithStatus //sys RtlDefaultNpAcl(acl **ACL) (ntstatus error) = ntdll.RtlDefaultNpAcl //sys NtQueryInformationProcess(proc Handle, procInfoClass int32, procInfo unsafe.Pointer, procInfoLen uint32, retLen *uint32) (ntstatus error) = ntdll.NtQueryInformationProcess //sys NtSetInformationProcess(proc Handle, procInfoClass int32, procInfo unsafe.Pointer, procInfoLen uint32) (ntstatus error) = ntdll.NtSetInformationProcess +//sys NtQuerySystemInformation(sysInfoClass int32, sysInfo unsafe.Pointer, sysInfoLen uint32, retLen *uint32) (ntstatus error) = ntdll.NtQuerySystemInformation +//sys NtSetSystemInformation(sysInfoClass int32, sysInfo unsafe.Pointer, sysInfoLen uint32) (ntstatus error) = ntdll.NtSetSystemInformation +//sys RtlAddFunctionTable(functionTable *RUNTIME_FUNCTION, entryCount uint32, baseAddress uintptr) (ret bool) = ntdll.RtlAddFunctionTable +//sys RtlDeleteFunctionTable(functionTable *RUNTIME_FUNCTION) (ret bool) = ntdll.RtlDeleteFunctionTable // syscall interface implementation for other packages @@ -883,9 +893,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, int32, error) { p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil } @@ -905,9 +913,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, int32, error) { p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) sa.raw.Scope_id = sa.ZoneId - for i := 0; i < len(sa.Addr); i++ { - sa.raw.Addr[i] = sa.Addr[i] - } + sa.raw.Addr = sa.Addr return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil } @@ -980,9 +986,7 @@ func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) { sa := new(SockaddrInet4) p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil case AF_INET6: @@ -991,9 +995,7 @@ func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) { p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) sa.ZoneId = pp.Scope_id - for i := 0; i < len(sa.Addr); i++ { - sa.Addr[i] = pp.Addr[i] - } + sa.Addr = pp.Addr return sa, nil } return nil, syscall.EAFNOSUPPORT diff --git a/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go index 88e0ce5d0d..286dd1eab9 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go @@ -66,9 +66,21 @@ var signals = [...]string{ } const ( - FILE_LIST_DIRECTORY = 0x00000001 - FILE_APPEND_DATA = 0x00000004 + FILE_READ_DATA = 0x00000001 + FILE_READ_ATTRIBUTES = 0x00000080 + FILE_READ_EA = 0x00000008 + FILE_WRITE_DATA = 0x00000002 FILE_WRITE_ATTRIBUTES = 0x00000100 + FILE_WRITE_EA = 0x00000010 + FILE_APPEND_DATA = 0x00000004 + FILE_EXECUTE = 0x00000020 + + FILE_GENERIC_READ = STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE + FILE_GENERIC_WRITE = STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | SYNCHRONIZE + FILE_GENERIC_EXECUTE = STANDARD_RIGHTS_EXECUTE | FILE_READ_ATTRIBUTES | FILE_EXECUTE | SYNCHRONIZE + + FILE_LIST_DIRECTORY = 0x00000001 + FILE_TRAVERSE = 0x00000020 FILE_SHARE_READ = 0x00000001 FILE_SHARE_WRITE = 0x00000002 @@ -1789,7 +1801,53 @@ type reparseDataBuffer struct { } const ( - FSCTL_GET_REPARSE_POINT = 0x900A8 + FSCTL_CREATE_OR_GET_OBJECT_ID = 0x0900C0 + FSCTL_DELETE_OBJECT_ID = 0x0900A0 + FSCTL_DELETE_REPARSE_POINT = 0x0900AC + FSCTL_DUPLICATE_EXTENTS_TO_FILE = 0x098344 + FSCTL_DUPLICATE_EXTENTS_TO_FILE_EX = 0x0983E8 + FSCTL_FILESYSTEM_GET_STATISTICS = 0x090060 + FSCTL_FILE_LEVEL_TRIM = 0x098208 + FSCTL_FIND_FILES_BY_SID = 0x09008F + FSCTL_GET_COMPRESSION = 0x09003C + FSCTL_GET_INTEGRITY_INFORMATION = 0x09027C + FSCTL_GET_NTFS_VOLUME_DATA = 0x090064 + FSCTL_GET_REFS_VOLUME_DATA = 0x0902D8 + FSCTL_GET_OBJECT_ID = 0x09009C + FSCTL_GET_REPARSE_POINT = 0x0900A8 + FSCTL_GET_RETRIEVAL_POINTER_COUNT = 0x09042B + FSCTL_GET_RETRIEVAL_POINTERS = 0x090073 + FSCTL_GET_RETRIEVAL_POINTERS_AND_REFCOUNT = 0x0903D3 + FSCTL_IS_PATHNAME_VALID = 0x09002C + FSCTL_LMR_SET_LINK_TRACKING_INFORMATION = 0x1400EC + FSCTL_MARK_HANDLE = 0x0900FC + FSCTL_OFFLOAD_READ = 0x094264 + FSCTL_OFFLOAD_WRITE = 0x098268 + FSCTL_PIPE_PEEK = 0x11400C + FSCTL_PIPE_TRANSCEIVE = 0x11C017 + FSCTL_PIPE_WAIT = 0x110018 + FSCTL_QUERY_ALLOCATED_RANGES = 0x0940CF + FSCTL_QUERY_FAT_BPB = 0x090058 + FSCTL_QUERY_FILE_REGIONS = 0x090284 + FSCTL_QUERY_ON_DISK_VOLUME_INFO = 0x09013C + FSCTL_QUERY_SPARING_INFO = 0x090138 + FSCTL_READ_FILE_USN_DATA = 0x0900EB + FSCTL_RECALL_FILE = 0x090117 + FSCTL_REFS_STREAM_SNAPSHOT_MANAGEMENT = 0x090440 + FSCTL_SET_COMPRESSION = 0x09C040 + FSCTL_SET_DEFECT_MANAGEMENT = 0x098134 + FSCTL_SET_ENCRYPTION = 0x0900D7 + FSCTL_SET_INTEGRITY_INFORMATION = 0x09C280 + FSCTL_SET_INTEGRITY_INFORMATION_EX = 0x090380 + FSCTL_SET_OBJECT_ID = 0x090098 + FSCTL_SET_OBJECT_ID_EXTENDED = 0x0900BC + FSCTL_SET_REPARSE_POINT = 0x0900A4 + FSCTL_SET_SPARSE = 0x0900C4 + FSCTL_SET_ZERO_DATA = 0x0980C8 + FSCTL_SET_ZERO_ON_DEALLOCATION = 0x090194 + FSCTL_SIS_COPYFILE = 0x090100 + FSCTL_WRITE_USN_CLOSE_RECORD = 0x0900EF + MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16 * 1024 IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003 IO_REPARSE_TAG_SYMLINK = 0xA000000C @@ -2308,6 +2366,12 @@ type LIST_ENTRY struct { Blink *LIST_ENTRY } +type RUNTIME_FUNCTION struct { + BeginAddress uint32 + EndAddress uint32 + UnwindData uint32 +} + type LDR_DATA_TABLE_ENTRY struct { reserved1 [2]uintptr InMemoryOrderLinks LIST_ENTRY @@ -2498,6 +2562,60 @@ const ( FILE_PIPE_SERVER_END = 0x00000001 ) +const ( + // FileInformationClass for NtSetInformationFile + FileBasicInformation = 4 + FileRenameInformation = 10 + FileDispositionInformation = 13 + FilePositionInformation = 14 + FileEndOfFileInformation = 20 + FileValidDataLengthInformation = 39 + FileShortNameInformation = 40 + FileIoPriorityHintInformation = 43 + FileReplaceCompletionInformation = 61 + FileDispositionInformationEx = 64 + FileCaseSensitiveInformation = 71 + FileLinkInformation = 72 + FileCaseSensitiveInformationForceAccessCheck = 75 + FileKnownFolderInformation = 76 + + // Flags for FILE_RENAME_INFORMATION + FILE_RENAME_REPLACE_IF_EXISTS = 0x00000001 + FILE_RENAME_POSIX_SEMANTICS = 0x00000002 + FILE_RENAME_SUPPRESS_PIN_STATE_INHERITANCE = 0x00000004 + FILE_RENAME_SUPPRESS_STORAGE_RESERVE_INHERITANCE = 0x00000008 + FILE_RENAME_NO_INCREASE_AVAILABLE_SPACE = 0x00000010 + FILE_RENAME_NO_DECREASE_AVAILABLE_SPACE = 0x00000020 + FILE_RENAME_PRESERVE_AVAILABLE_SPACE = 0x00000030 + FILE_RENAME_IGNORE_READONLY_ATTRIBUTE = 0x00000040 + FILE_RENAME_FORCE_RESIZE_TARGET_SR = 0x00000080 + FILE_RENAME_FORCE_RESIZE_SOURCE_SR = 0x00000100 + FILE_RENAME_FORCE_RESIZE_SR = 0x00000180 + + // Flags for FILE_DISPOSITION_INFORMATION_EX + FILE_DISPOSITION_DO_NOT_DELETE = 0x00000000 + FILE_DISPOSITION_DELETE = 0x00000001 + FILE_DISPOSITION_POSIX_SEMANTICS = 0x00000002 + FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK = 0x00000004 + FILE_DISPOSITION_ON_CLOSE = 0x00000008 + FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE = 0x00000010 + + // Flags for FILE_CASE_SENSITIVE_INFORMATION + FILE_CS_FLAG_CASE_SENSITIVE_DIR = 0x00000001 + + // Flags for FILE_LINK_INFORMATION + FILE_LINK_REPLACE_IF_EXISTS = 0x00000001 + FILE_LINK_POSIX_SEMANTICS = 0x00000002 + FILE_LINK_SUPPRESS_STORAGE_RESERVE_INHERITANCE = 0x00000008 + FILE_LINK_NO_INCREASE_AVAILABLE_SPACE = 0x00000010 + FILE_LINK_NO_DECREASE_AVAILABLE_SPACE = 0x00000020 + FILE_LINK_PRESERVE_AVAILABLE_SPACE = 0x00000030 + FILE_LINK_IGNORE_READONLY_ATTRIBUTE = 0x00000040 + FILE_LINK_FORCE_RESIZE_TARGET_SR = 0x00000080 + FILE_LINK_FORCE_RESIZE_SOURCE_SR = 0x00000100 + FILE_LINK_FORCE_RESIZE_SR = 0x00000180 +) + // ProcessInformationClasses for NtQueryInformationProcess and NtSetInformationProcess. const ( ProcessBasicInformation = iota @@ -2614,6 +2732,203 @@ type PROCESS_BASIC_INFORMATION struct { InheritedFromUniqueProcessId uintptr } +// SystemInformationClasses for NtQuerySystemInformation and NtSetSystemInformation +const ( + SystemBasicInformation = iota + SystemProcessorInformation + SystemPerformanceInformation + SystemTimeOfDayInformation + SystemPathInformation + SystemProcessInformation + SystemCallCountInformation + SystemDeviceInformation + SystemProcessorPerformanceInformation + SystemFlagsInformation + SystemCallTimeInformation + SystemModuleInformation + SystemLocksInformation + SystemStackTraceInformation + SystemPagedPoolInformation + SystemNonPagedPoolInformation + SystemHandleInformation + SystemObjectInformation + SystemPageFileInformation + SystemVdmInstemulInformation + SystemVdmBopInformation + SystemFileCacheInformation + SystemPoolTagInformation + SystemInterruptInformation + SystemDpcBehaviorInformation + SystemFullMemoryInformation + SystemLoadGdiDriverInformation + SystemUnloadGdiDriverInformation + SystemTimeAdjustmentInformation + SystemSummaryMemoryInformation + SystemMirrorMemoryInformation + SystemPerformanceTraceInformation + systemObsolete0 + SystemExceptionInformation + SystemCrashDumpStateInformation + SystemKernelDebuggerInformation + SystemContextSwitchInformation + SystemRegistryQuotaInformation + SystemExtendServiceTableInformation + SystemPrioritySeperation + SystemVerifierAddDriverInformation + SystemVerifierRemoveDriverInformation + SystemProcessorIdleInformation + SystemLegacyDriverInformation + SystemCurrentTimeZoneInformation + SystemLookasideInformation + SystemTimeSlipNotification + SystemSessionCreate + SystemSessionDetach + SystemSessionInformation + SystemRangeStartInformation + SystemVerifierInformation + SystemVerifierThunkExtend + SystemSessionProcessInformation + SystemLoadGdiDriverInSystemSpace + SystemNumaProcessorMap + SystemPrefetcherInformation + SystemExtendedProcessInformation + SystemRecommendedSharedDataAlignment + SystemComPlusPackage + SystemNumaAvailableMemory + SystemProcessorPowerInformation + SystemEmulationBasicInformation + SystemEmulationProcessorInformation + SystemExtendedHandleInformation + SystemLostDelayedWriteInformation + SystemBigPoolInformation + SystemSessionPoolTagInformation + SystemSessionMappedViewInformation + SystemHotpatchInformation + SystemObjectSecurityMode + SystemWatchdogTimerHandler + SystemWatchdogTimerInformation + SystemLogicalProcessorInformation + SystemWow64SharedInformationObsolete + SystemRegisterFirmwareTableInformationHandler + SystemFirmwareTableInformation + SystemModuleInformationEx + SystemVerifierTriageInformation + SystemSuperfetchInformation + SystemMemoryListInformation + SystemFileCacheInformationEx + SystemThreadPriorityClientIdInformation + SystemProcessorIdleCycleTimeInformation + SystemVerifierCancellationInformation + SystemProcessorPowerInformationEx + SystemRefTraceInformation + SystemSpecialPoolInformation + SystemProcessIdInformation + SystemErrorPortInformation + SystemBootEnvironmentInformation + SystemHypervisorInformation + SystemVerifierInformationEx + SystemTimeZoneInformation + SystemImageFileExecutionOptionsInformation + SystemCoverageInformation + SystemPrefetchPatchInformation + SystemVerifierFaultsInformation + SystemSystemPartitionInformation + SystemSystemDiskInformation + SystemProcessorPerformanceDistribution + SystemNumaProximityNodeInformation + SystemDynamicTimeZoneInformation + SystemCodeIntegrityInformation + SystemProcessorMicrocodeUpdateInformation + SystemProcessorBrandString + SystemVirtualAddressInformation + SystemLogicalProcessorAndGroupInformation + SystemProcessorCycleTimeInformation + SystemStoreInformation + SystemRegistryAppendString + SystemAitSamplingValue + SystemVhdBootInformation + SystemCpuQuotaInformation + SystemNativeBasicInformation + systemSpare1 + SystemLowPriorityIoInformation + SystemTpmBootEntropyInformation + SystemVerifierCountersInformation + SystemPagedPoolInformationEx + SystemSystemPtesInformationEx + SystemNodeDistanceInformation + SystemAcpiAuditInformation + SystemBasicPerformanceInformation + SystemQueryPerformanceCounterInformation + SystemSessionBigPoolInformation + SystemBootGraphicsInformation + SystemScrubPhysicalMemoryInformation + SystemBadPageInformation + SystemProcessorProfileControlArea + SystemCombinePhysicalMemoryInformation + SystemEntropyInterruptTimingCallback + SystemConsoleInformation + SystemPlatformBinaryInformation + SystemThrottleNotificationInformation + SystemHypervisorProcessorCountInformation + SystemDeviceDataInformation + SystemDeviceDataEnumerationInformation + SystemMemoryTopologyInformation + SystemMemoryChannelInformation + SystemBootLogoInformation + SystemProcessorPerformanceInformationEx + systemSpare0 + SystemSecureBootPolicyInformation + SystemPageFileInformationEx + SystemSecureBootInformation + SystemEntropyInterruptTimingRawInformation + SystemPortableWorkspaceEfiLauncherInformation + SystemFullProcessInformation + SystemKernelDebuggerInformationEx + SystemBootMetadataInformation + SystemSoftRebootInformation + SystemElamCertificateInformation + SystemOfflineDumpConfigInformation + SystemProcessorFeaturesInformation + SystemRegistryReconciliationInformation + SystemEdidInformation + SystemManufacturingInformation + SystemEnergyEstimationConfigInformation + SystemHypervisorDetailInformation + SystemProcessorCycleStatsInformation + SystemVmGenerationCountInformation + SystemTrustedPlatformModuleInformation + SystemKernelDebuggerFlags + SystemCodeIntegrityPolicyInformation + SystemIsolatedUserModeInformation + SystemHardwareSecurityTestInterfaceResultsInformation + SystemSingleModuleInformation + SystemAllowedCpuSetsInformation + SystemDmaProtectionInformation + SystemInterruptCpuSetsInformation + SystemSecureBootPolicyFullInformation + SystemCodeIntegrityPolicyFullInformation + SystemAffinitizedInterruptProcessorInformation + SystemRootSiloInformation +) + +type RTL_PROCESS_MODULE_INFORMATION struct { + Section Handle + MappedBase uintptr + ImageBase uintptr + ImageSize uint32 + Flags uint32 + LoadOrderIndex uint16 + InitOrderIndex uint16 + LoadCount uint16 + OffsetToFileName uint16 + FullPathName [256]byte +} + +type RTL_PROCESS_MODULES struct { + NumberOfModules uint32 + Modules [1]RTL_PROCESS_MODULE_INFORMATION +} + // Constants for LocalAlloc flags. const ( LMEM_FIXED = 0x0 @@ -2708,6 +3023,22 @@ var ( RT_MANIFEST ResourceID = 24 ) +type VS_FIXEDFILEINFO struct { + Signature uint32 + StrucVersion uint32 + FileVersionMS uint32 + FileVersionLS uint32 + ProductVersionMS uint32 + ProductVersionLS uint32 + FileFlagsMask uint32 + FileFlags uint32 + FileOS uint32 + FileType uint32 + FileSubtype uint32 + FileDateMS uint32 + FileDateLS uint32 +} + type COAUTHIDENTITY struct { User *uint16 UserLength uint32 diff --git a/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go index 4ea788e4c4..91817d6dcb 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go @@ -51,6 +51,7 @@ var ( modshell32 = NewLazySystemDLL("shell32.dll") moduser32 = NewLazySystemDLL("user32.dll") moduserenv = NewLazySystemDLL("userenv.dll") + modversion = NewLazySystemDLL("version.dll") modwintrust = NewLazySystemDLL("wintrust.dll") modws2_32 = NewLazySystemDLL("ws2_32.dll") modwtsapi32 = NewLazySystemDLL("wtsapi32.dll") @@ -114,6 +115,7 @@ var ( procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") procQueryServiceConfig2W = modadvapi32.NewProc("QueryServiceConfig2W") procQueryServiceConfigW = modadvapi32.NewProc("QueryServiceConfigW") + procQueryServiceDynamicInformation = modadvapi32.NewProc("QueryServiceDynamicInformation") procQueryServiceLockStatusW = modadvapi32.NewProc("QueryServiceLockStatusW") procQueryServiceStatus = modadvapi32.NewProc("QueryServiceStatus") procQueryServiceStatusEx = modadvapi32.NewProc("QueryServiceStatusEx") @@ -124,6 +126,7 @@ var ( procRegQueryInfoKeyW = modadvapi32.NewProc("RegQueryInfoKeyW") procRegQueryValueExW = modadvapi32.NewProc("RegQueryValueExW") procRegisterEventSourceW = modadvapi32.NewProc("RegisterEventSourceW") + procRegisterServiceCtrlHandlerExW = modadvapi32.NewProc("RegisterServiceCtrlHandlerExW") procReportEventW = modadvapi32.NewProc("ReportEventW") procRevertToSelf = modadvapi32.NewProc("RevertToSelf") procSetEntriesInAclW = modadvapi32.NewProc("SetEntriesInAclW") @@ -365,8 +368,13 @@ var ( procNtCreateFile = modntdll.NewProc("NtCreateFile") procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile") procNtQueryInformationProcess = modntdll.NewProc("NtQueryInformationProcess") + procNtQuerySystemInformation = modntdll.NewProc("NtQuerySystemInformation") + procNtSetInformationFile = modntdll.NewProc("NtSetInformationFile") procNtSetInformationProcess = modntdll.NewProc("NtSetInformationProcess") + procNtSetSystemInformation = modntdll.NewProc("NtSetSystemInformation") + procRtlAddFunctionTable = modntdll.NewProc("RtlAddFunctionTable") procRtlDefaultNpAcl = modntdll.NewProc("RtlDefaultNpAcl") + procRtlDeleteFunctionTable = modntdll.NewProc("RtlDeleteFunctionTable") procRtlDosPathNameToNtPathName_U_WithStatus = modntdll.NewProc("RtlDosPathNameToNtPathName_U_WithStatus") procRtlDosPathNameToRelativeNtPathName_U_WithStatus = modntdll.NewProc("RtlDosPathNameToRelativeNtPathName_U_WithStatus") procRtlGetCurrentPeb = modntdll.NewProc("RtlGetCurrentPeb") @@ -402,6 +410,9 @@ var ( procCreateEnvironmentBlock = moduserenv.NewProc("CreateEnvironmentBlock") procDestroyEnvironmentBlock = moduserenv.NewProc("DestroyEnvironmentBlock") procGetUserProfileDirectoryW = moduserenv.NewProc("GetUserProfileDirectoryW") + procGetFileVersionInfoSizeW = modversion.NewProc("GetFileVersionInfoSizeW") + procGetFileVersionInfoW = modversion.NewProc("GetFileVersionInfoW") + procVerQueryValueW = modversion.NewProc("VerQueryValueW") procWinVerifyTrustEx = modwintrust.NewProc("WinVerifyTrustEx") procFreeAddrInfoW = modws2_32.NewProc("FreeAddrInfoW") procGetAddrInfoW = modws2_32.NewProc("GetAddrInfoW") @@ -966,6 +977,18 @@ func QueryServiceConfig(service Handle, serviceConfig *QUERY_SERVICE_CONFIG, buf return } +func QueryServiceDynamicInformation(service Handle, infoLevel uint32, dynamicInfo unsafe.Pointer) (err error) { + err = procQueryServiceDynamicInformation.Find() + if err != nil { + return + } + r1, _, e1 := syscall.Syscall(procQueryServiceDynamicInformation.Addr(), 3, uintptr(service), uintptr(infoLevel), uintptr(dynamicInfo)) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func QueryServiceLockStatus(mgr Handle, lockStatus *QUERY_SERVICE_LOCK_STATUS, bufSize uint32, bytesNeeded *uint32) (err error) { r1, _, e1 := syscall.Syscall6(procQueryServiceLockStatusW.Addr(), 4, uintptr(mgr), uintptr(unsafe.Pointer(lockStatus)), uintptr(bufSize), uintptr(unsafe.Pointer(bytesNeeded)), 0, 0) if r1 == 0 { @@ -1055,6 +1078,15 @@ func RegisterEventSource(uncServerName *uint16, sourceName *uint16) (handle Hand return } +func RegisterServiceCtrlHandlerEx(serviceName *uint16, handlerProc uintptr, context uintptr) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall(procRegisterServiceCtrlHandlerExW.Addr(), 3, uintptr(unsafe.Pointer(serviceName)), uintptr(handlerProc), uintptr(context)) + handle = Handle(r0) + if handle == 0 { + err = errnoErr(e1) + } + return +} + func ReportEvent(log Handle, etype uint16, category uint16, eventId uint32, usrSId uintptr, numStrings uint16, dataSize uint32, strings **uint16, rawData *byte) (err error) { r1, _, e1 := syscall.Syscall9(procReportEventW.Addr(), 9, uintptr(log), uintptr(etype), uintptr(category), uintptr(eventId), uintptr(usrSId), uintptr(numStrings), uintptr(dataSize), uintptr(unsafe.Pointer(strings)), uintptr(unsafe.Pointer(rawData))) if r1 == 0 { @@ -3160,6 +3192,22 @@ func NtQueryInformationProcess(proc Handle, procInfoClass int32, procInfo unsafe return } +func NtQuerySystemInformation(sysInfoClass int32, sysInfo unsafe.Pointer, sysInfoLen uint32, retLen *uint32) (ntstatus error) { + r0, _, _ := syscall.Syscall6(procNtQuerySystemInformation.Addr(), 4, uintptr(sysInfoClass), uintptr(sysInfo), uintptr(sysInfoLen), uintptr(unsafe.Pointer(retLen)), 0, 0) + if r0 != 0 { + ntstatus = NTStatus(r0) + } + return +} + +func NtSetInformationFile(handle Handle, iosb *IO_STATUS_BLOCK, inBuffer *byte, inBufferLen uint32, class uint32) (ntstatus error) { + r0, _, _ := syscall.Syscall6(procNtSetInformationFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(iosb)), uintptr(unsafe.Pointer(inBuffer)), uintptr(inBufferLen), uintptr(class), 0) + if r0 != 0 { + ntstatus = NTStatus(r0) + } + return +} + func NtSetInformationProcess(proc Handle, procInfoClass int32, procInfo unsafe.Pointer, procInfoLen uint32) (ntstatus error) { r0, _, _ := syscall.Syscall6(procNtSetInformationProcess.Addr(), 4, uintptr(proc), uintptr(procInfoClass), uintptr(procInfo), uintptr(procInfoLen), 0, 0) if r0 != 0 { @@ -3168,6 +3216,20 @@ func NtSetInformationProcess(proc Handle, procInfoClass int32, procInfo unsafe.P return } +func NtSetSystemInformation(sysInfoClass int32, sysInfo unsafe.Pointer, sysInfoLen uint32) (ntstatus error) { + r0, _, _ := syscall.Syscall(procNtSetSystemInformation.Addr(), 3, uintptr(sysInfoClass), uintptr(sysInfo), uintptr(sysInfoLen)) + if r0 != 0 { + ntstatus = NTStatus(r0) + } + return +} + +func RtlAddFunctionTable(functionTable *RUNTIME_FUNCTION, entryCount uint32, baseAddress uintptr) (ret bool) { + r0, _, _ := syscall.Syscall(procRtlAddFunctionTable.Addr(), 3, uintptr(unsafe.Pointer(functionTable)), uintptr(entryCount), uintptr(baseAddress)) + ret = r0 != 0 + return +} + func RtlDefaultNpAcl(acl **ACL) (ntstatus error) { r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(acl)), 0, 0) if r0 != 0 { @@ -3176,6 +3238,12 @@ func RtlDefaultNpAcl(acl **ACL) (ntstatus error) { return } +func RtlDeleteFunctionTable(functionTable *RUNTIME_FUNCTION) (ret bool) { + r0, _, _ := syscall.Syscall(procRtlDeleteFunctionTable.Addr(), 1, uintptr(unsafe.Pointer(functionTable)), 0, 0) + ret = r0 != 0 + return +} + func RtlDosPathNameToNtPathName(dosName *uint16, ntName *NTUnicodeString, ntFileNamePart *uint16, relativeName *RTL_RELATIVE_NAME) (ntstatus error) { r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U_WithStatus.Addr(), 4, uintptr(unsafe.Pointer(dosName)), uintptr(unsafe.Pointer(ntName)), uintptr(unsafe.Pointer(ntFileNamePart)), uintptr(unsafe.Pointer(relativeName)), 0, 0) if r0 != 0 { @@ -3449,6 +3517,58 @@ func GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) { return } +func GetFileVersionInfoSize(filename string, zeroHandle *Handle) (bufSize uint32, err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(filename) + if err != nil { + return + } + return _GetFileVersionInfoSize(_p0, zeroHandle) +} + +func _GetFileVersionInfoSize(filename *uint16, zeroHandle *Handle) (bufSize uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetFileVersionInfoSizeW.Addr(), 2, uintptr(unsafe.Pointer(filename)), uintptr(unsafe.Pointer(zeroHandle)), 0) + bufSize = uint32(r0) + if bufSize == 0 { + err = errnoErr(e1) + } + return +} + +func GetFileVersionInfo(filename string, handle uint32, bufSize uint32, buffer unsafe.Pointer) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(filename) + if err != nil { + return + } + return _GetFileVersionInfo(_p0, handle, bufSize, buffer) +} + +func _GetFileVersionInfo(filename *uint16, handle uint32, bufSize uint32, buffer unsafe.Pointer) (err error) { + r1, _, e1 := syscall.Syscall6(procGetFileVersionInfoW.Addr(), 4, uintptr(unsafe.Pointer(filename)), uintptr(handle), uintptr(bufSize), uintptr(buffer), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func VerQueryValue(block unsafe.Pointer, subBlock string, pointerToBufferPointer unsafe.Pointer, bufSize *uint32) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(subBlock) + if err != nil { + return + } + return _VerQueryValue(block, _p0, pointerToBufferPointer, bufSize) +} + +func _VerQueryValue(block unsafe.Pointer, subBlock *uint16, pointerToBufferPointer unsafe.Pointer, bufSize *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procVerQueryValueW.Addr(), 4, uintptr(block), uintptr(unsafe.Pointer(subBlock)), uintptr(pointerToBufferPointer), uintptr(unsafe.Pointer(bufSize)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func WinVerifyTrustEx(hwnd HWND, actionId *GUID, data *WinTrustData) (ret error) { r0, _, _ := syscall.Syscall(procWinVerifyTrustEx.Addr(), 3, uintptr(hwnd), uintptr(unsafe.Pointer(actionId)), uintptr(unsafe.Pointer(data))) if r0 != 0 { diff --git a/src/cmd/vendor/golang.org/x/term/codereview.cfg b/src/cmd/vendor/golang.org/x/term/codereview.cfg new file mode 100644 index 0000000000..3f8b14b64e --- /dev/null +++ b/src/cmd/vendor/golang.org/x/term/codereview.cfg @@ -0,0 +1 @@ +issuerepo: golang/go diff --git a/src/cmd/vendor/golang.org/x/term/term.go b/src/cmd/vendor/golang.org/x/term/term.go index 1f6a38fad2..d592708808 100644 --- a/src/cmd/vendor/golang.org/x/term/term.go +++ b/src/cmd/vendor/golang.org/x/term/term.go @@ -12,6 +12,8 @@ // panic(err) // } // defer term.Restore(int(os.Stdin.Fd()), oldState) +// +// Note that on non-Unix systems os.Stdin.Fd() may not be 0. package term // State contains the state of a terminal. diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index ad08e583fb..3a9b4f8736 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -18,7 +18,7 @@ github.com/google/pprof/third_party/svgpan # github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d ## explicit; go 1.12 github.com/ianlancetaylor/demangle -# golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1 +# golang.org/x/arch v0.0.0-20210923205945-b76863e36670 ## explicit; go 1.17 golang.org/x/arch/arm/armasm golang.org/x/arch/arm64/arm64asm @@ -42,13 +42,13 @@ golang.org/x/mod/zip # golang.org/x/sync v0.0.0-20210220032951-036812b2e83c ## explicit golang.org/x/sync/semaphore -# golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac +# golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e ## explicit; go 1.17 golang.org/x/sys/internal/unsafeheader golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows -# golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b +# golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 ## explicit; go 1.17 golang.org/x/term # golang.org/x/tools v0.1.8-0.20211025211149-f916b54a1784 diff --git a/src/go.mod b/src/go.mod index 7d982c75aa..fca8e2c8db 100644 --- a/src/go.mod +++ b/src/go.mod @@ -8,6 +8,6 @@ require ( ) require ( - golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect + golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e // indirect golang.org/x/text v0.3.7 // indirect ) diff --git a/src/go.sum b/src/go.sum index ff1279697d..8262c737b5 100644 --- a/src/go.sum +++ b/src/go.sum @@ -2,7 +2,7 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s3 golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/net v0.0.0-20211005215030-d2e5035098b3 h1:G64nFNerDErBd2KdvHvIn3Ee6ccUQBTfhDZEO0DccfU= golang.org/x/net v0.0.0-20211005215030-d2e5035098b3/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac h1:oN6lz7iLW/YC7un8pq+9bOLyXrprv2+DKfkJY+2LJJw= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e h1:i6Vklmyu+fZMFYpum+sR4ZWABGW7MyIxfJZXYvcnbns= +golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_x86.go b/src/vendor/golang.org/x/sys/cpu/cpu_x86.go index 5ea287b7ec..f5aacfc825 100644 --- a/src/vendor/golang.org/x/sys/cpu/cpu_x86.go +++ b/src/vendor/golang.org/x/sys/cpu/cpu_x86.go @@ -90,9 +90,10 @@ func archInit() { osSupportsAVX = isSet(1, eax) && isSet(2, eax) if runtime.GOOS == "darwin" { - // Check darwin commpage for AVX512 support. Necessary because: - // https://github.com/apple/darwin-xnu/blob/0a798f6738bc1db01281fc08ae024145e84df927/osfmk/i386/fpu.c#L175-L201 - osSupportsAVX512 = osSupportsAVX && darwinSupportsAVX512() + // Darwin doesn't save/restore AVX-512 mask registers correctly across signal handlers. + // Since users can't rely on mask register contents, let's not advertise AVX-512 support. + // See issue 49233. + osSupportsAVX512 = false } else { // Check if OPMASK and ZMM registers have OS support. osSupportsAVX512 = osSupportsAVX && isSet(5, eax) && isSet(6, eax) && isSet(7, eax) diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_x86.s b/src/vendor/golang.org/x/sys/cpu/cpu_x86.s index b748ba52f7..39acab2ff5 100644 --- a/src/vendor/golang.org/x/sys/cpu/cpu_x86.s +++ b/src/vendor/golang.org/x/sys/cpu/cpu_x86.s @@ -26,27 +26,3 @@ TEXT ·xgetbv(SB),NOSPLIT,$0-8 MOVL AX, eax+0(FP) MOVL DX, edx+4(FP) RET - -// func darwinSupportsAVX512() bool -TEXT ·darwinSupportsAVX512(SB), NOSPLIT, $0-1 - MOVB $0, ret+0(FP) // default to false -#ifdef GOOS_darwin // return if not darwin -#ifdef GOARCH_amd64 // return if not amd64 -// These values from: -// https://github.com/apple/darwin-xnu/blob/xnu-4570.1.46/osfmk/i386/cpu_capabilities.h -#define commpage64_base_address 0x00007fffffe00000 -#define commpage64_cpu_capabilities64 (commpage64_base_address+0x010) -#define commpage64_version (commpage64_base_address+0x01E) -#define hasAVX512F 0x0000004000000000 - MOVQ $commpage64_version, BX - CMPW (BX), $13 // cpu_capabilities64 undefined in versions < 13 - JL no_avx512 - MOVQ $commpage64_cpu_capabilities64, BX - MOVQ $hasAVX512F, CX - TESTQ (BX), CX - JZ no_avx512 - MOVB $1, ret+0(FP) -no_avx512: -#endif -#endif - RET diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index 770a08e1fb..f550e36d17 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -19,7 +19,7 @@ golang.org/x/net/idna golang.org/x/net/lif golang.org/x/net/nettest golang.org/x/net/route -# golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac +# golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e ## explicit; go 1.17 golang.org/x/sys/cpu # golang.org/x/text v0.3.7 -- GitLab From 77c473f4197b5ad4d90689d665534e598f3c0750 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Tue, 9 Nov 2021 13:31:45 -0500 Subject: [PATCH 2075/2500] all: update vendored golang.org/x/{net,text} for Go 1.18 release The Go 1.18 code freeze has recently started. This is a time to update all golang.org/x/... module versions that contribute packages to the std and cmd modules in the standard library to latest master versions. This CL updates only the net, text modules. The next CL will update further ones. For #36905. Change-Id: I9a5ac3cca22da961cfd09f3202e01e1187d42bdd Reviewed-on: https://go-review.googlesource.com/c/go/+/362735 Trust: Dmitri Shuralyov Run-TryBot: Dmitri Shuralyov TryBot-Result: Go Bot Reviewed-by: Heschi Kreinick --- src/go.mod | 4 +- src/go.sum | 8 +- src/net/http/h2_bundle.go | 368 ++++++++++++------ .../golang.org/x/net/http/httpproxy/proxy.go | 4 +- .../golang.org/x/net/http2/hpack/huffman.go | 38 +- src/vendor/golang.org/x/net/idna/go118.go | 14 + .../golang.org/x/net/idna/idna10.0.0.go | 6 +- src/vendor/golang.org/x/net/idna/idna9.0.0.go | 4 +- src/vendor/golang.org/x/net/idna/pre_go118.go | 12 + src/vendor/golang.org/x/net/idna/punycode.go | 36 +- .../golang.org/x/net/nettest/nettest.go | 14 +- .../golang.org/x/text/unicode/bidi/core.go | 6 +- src/vendor/modules.txt | 4 +- 13 files changed, 347 insertions(+), 171 deletions(-) create mode 100644 src/vendor/golang.org/x/net/idna/go118.go create mode 100644 src/vendor/golang.org/x/net/idna/pre_go118.go diff --git a/src/go.mod b/src/go.mod index fca8e2c8db..3e7b86ee25 100644 --- a/src/go.mod +++ b/src/go.mod @@ -4,10 +4,10 @@ go 1.18 require ( golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 - golang.org/x/net v0.0.0-20211005215030-d2e5035098b3 + golang.org/x/net v0.0.0-20211108170745-6635138e15ea ) require ( golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e // indirect - golang.org/x/text v0.3.7 // indirect + golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 // indirect ) diff --git a/src/go.sum b/src/go.sum index 8262c737b5..f9e5e7d4b8 100644 --- a/src/go.sum +++ b/src/go.sum @@ -1,8 +1,8 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/net v0.0.0-20211005215030-d2e5035098b3 h1:G64nFNerDErBd2KdvHvIn3Ee6ccUQBTfhDZEO0DccfU= -golang.org/x/net v0.0.0-20211005215030-d2e5035098b3/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211108170745-6635138e15ea h1:FosBMXtOc8Tp9Hbo4ltl1WJSrTVewZU8MPnTPY2HdH8= +golang.org/x/net v0.0.0-20211108170745-6635138e15ea/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e h1:i6Vklmyu+fZMFYpum+sR4ZWABGW7MyIxfJZXYvcnbns= golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 h1:GLw7MR8AfAG2GmGcmVgObFOHXYypgGjnGno25RDwn3Y= +golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0= diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go index 29226d4065..23a4d15326 100644 --- a/src/net/http/h2_bundle.go +++ b/src/net/http/h2_bundle.go @@ -6836,6 +6836,11 @@ type http2Transport struct { // Defaults to 15s. PingTimeout time.Duration + // WriteByteTimeout is the timeout after which the connection will be + // closed no data can be written to it. The timeout begins when data is + // available to write, and is extended whenever any bytes are written. + WriteByteTimeout time.Duration + // CountError, if non-nil, is called on HTTP/2 transport errors. // It's intended to increment a metric for monitoring, such // as an expvar or Prometheus metric. @@ -7006,12 +7011,17 @@ type http2ClientConn struct { // clientStream is the state for a single HTTP/2 stream. One of these // is created for each Transport.RoundTrip call. type http2clientStream struct { - cc *http2ClientConn - req *Request + cc *http2ClientConn + + // Fields of Request that we may access even after the response body is closed. + ctx context.Context + reqCancel <-chan struct{} + trace *httptrace.ClientTrace // or nil ID uint32 bufPipe http2pipe // buffered pipe with the flow-controlled response payload requestedGzip bool + isHead bool abortOnce sync.Once abort chan struct{} // closed to signal stream should end immediately @@ -7028,7 +7038,10 @@ type http2clientStream struct { inflow http2flow // guarded by cc.mu bytesRemain int64 // -1 means unknown; owned by transportResponseBody.Read readErr error // sticky read error; owned by transportResponseBody.Read - stopReqBody error // if non-nil, stop writing req body; guarded by cc.mu + + reqBody io.ReadCloser + reqBodyContentLength int64 // -1 means unknown + reqBodyClosed bool // body has been closed; guarded by cc.mu // owned by writeRequest: sentEndStream bool // sent an END_STREAM flag to the peer @@ -7068,6 +7081,10 @@ func (cs *http2clientStream) abortStreamLocked(err error) { cs.abortErr = err close(cs.abort) }) + if cs.reqBody != nil && !cs.reqBodyClosed { + cs.reqBody.Close() + cs.reqBodyClosed = true + } // TODO(dneil): Clean up tests where cs.cc.cond is nil. if cs.cc.cond != nil { // Wake up writeRequestBody if it is waiting on flow control. @@ -7075,31 +7092,43 @@ func (cs *http2clientStream) abortStreamLocked(err error) { } } -func (cs *http2clientStream) abortRequestBodyWrite(err error) { - if err == nil { - panic("nil error") - } +func (cs *http2clientStream) abortRequestBodyWrite() { cc := cs.cc cc.mu.Lock() - if cs.stopReqBody == nil { - cs.stopReqBody = err + defer cc.mu.Unlock() + if cs.reqBody != nil && !cs.reqBodyClosed { + cs.reqBody.Close() + cs.reqBodyClosed = true cc.cond.Broadcast() } - cc.mu.Unlock() } type http2stickyErrWriter struct { - w io.Writer - err *error + conn net.Conn + timeout time.Duration + err *error } func (sew http2stickyErrWriter) Write(p []byte) (n int, err error) { if *sew.err != nil { return 0, *sew.err } - n, err = sew.w.Write(p) - *sew.err = err - return + for { + if sew.timeout != 0 { + sew.conn.SetWriteDeadline(time.Now().Add(sew.timeout)) + } + nn, err := sew.conn.Write(p[n:]) + n += nn + if n < len(p) && nn > 0 && errors.Is(err, os.ErrDeadlineExceeded) { + // Keep extending the deadline so long as we're making progress. + continue + } + if sew.timeout != 0 { + sew.conn.SetWriteDeadline(time.Time{}) + } + *sew.err = err + return n, err + } } // noCachedConnError is the concrete type of ErrNoCachedConn, which @@ -7355,7 +7384,11 @@ func (t *http2Transport) newClientConn(c net.Conn, singleUse bool) (*http2Client // TODO: adjust this writer size to account for frame size + // MTU + crypto/tls record padding. - cc.bw = bufio.NewWriter(http2stickyErrWriter{c, &cc.werr}) + cc.bw = bufio.NewWriter(http2stickyErrWriter{ + conn: c, + timeout: t.WriteByteTimeout, + err: &cc.werr, + }) cc.br = bufio.NewReader(c) cc.fr = http2NewFramer(cc.bw, cc.br) if t.CountError != nil { @@ -7466,6 +7499,61 @@ func (cc *http2ClientConn) ReserveNewRequest() bool { return true } +// ClientConnState describes the state of a ClientConn. +type http2ClientConnState struct { + // Closed is whether the connection is closed. + Closed bool + + // Closing is whether the connection is in the process of + // closing. It may be closing due to shutdown, being a + // single-use connection, being marked as DoNotReuse, or + // having received a GOAWAY frame. + Closing bool + + // StreamsActive is how many streams are active. + StreamsActive int + + // StreamsReserved is how many streams have been reserved via + // ClientConn.ReserveNewRequest. + StreamsReserved int + + // StreamsPending is how many requests have been sent in excess + // of the peer's advertised MaxConcurrentStreams setting and + // are waiting for other streams to complete. + StreamsPending int + + // MaxConcurrentStreams is how many concurrent streams the + // peer advertised as acceptable. Zero means no SETTINGS + // frame has been received yet. + MaxConcurrentStreams uint32 + + // LastIdle, if non-zero, is when the connection last + // transitioned to idle state. + LastIdle time.Time +} + +// State returns a snapshot of cc's state. +func (cc *http2ClientConn) State() http2ClientConnState { + cc.wmu.Lock() + maxConcurrent := cc.maxConcurrentStreams + if !cc.seenSettings { + maxConcurrent = 0 + } + cc.wmu.Unlock() + + cc.mu.Lock() + defer cc.mu.Unlock() + return http2ClientConnState{ + Closed: cc.closed, + Closing: cc.closing || cc.singleUse || cc.doNotReuse || cc.goAway != nil, + StreamsActive: len(cc.streams), + StreamsReserved: cc.streamsReserved, + StreamsPending: cc.pendingRequests, + LastIdle: cc.lastIdle, + MaxConcurrentStreams: maxConcurrent, + } +} + // clientConnIdleState describes the suitability of a client // connection to initiate a new RoundTrip request. type http2clientConnIdleState struct { @@ -7717,15 +7805,19 @@ func (cc *http2ClientConn) decrStreamReservationsLocked() { func (cc *http2ClientConn) RoundTrip(req *Request) (*Response, error) { ctx := req.Context() cs := &http2clientStream{ - cc: cc, - req: req, - trace: httptrace.ContextClientTrace(req.Context()), - peerClosed: make(chan struct{}), - abort: make(chan struct{}), - respHeaderRecv: make(chan struct{}), - donec: make(chan struct{}), - } - go cs.doRequest() + cc: cc, + ctx: ctx, + reqCancel: req.Cancel, + isHead: req.Method == "HEAD", + reqBody: req.Body, + reqBodyContentLength: http2actualContentLength(req), + trace: httptrace.ContextClientTrace(ctx), + peerClosed: make(chan struct{}), + abort: make(chan struct{}), + respHeaderRecv: make(chan struct{}), + donec: make(chan struct{}), + } + go cs.doRequest(req) waitDone := func() error { select { @@ -7733,7 +7825,7 @@ func (cc *http2ClientConn) RoundTrip(req *Request) (*Response, error) { return nil case <-ctx.Done(): return ctx.Err() - case <-req.Cancel: + case <-cs.reqCancel: return http2errRequestCanceled } } @@ -7752,7 +7844,7 @@ func (cc *http2ClientConn) RoundTrip(req *Request) (*Response, error) { // doesn't, they'll RST_STREAM us soon enough. This is a // heuristic to avoid adding knobs to Transport. Hopefully // we can keep it. - cs.abortRequestBodyWrite(http2errStopReqBodyWrite) + cs.abortRequestBodyWrite() } res.Request = req res.TLS = cc.tlsState @@ -7769,8 +7861,11 @@ func (cc *http2ClientConn) RoundTrip(req *Request) (*Response, error) { waitDone() return nil, cs.abortErr case <-ctx.Done(): - return nil, ctx.Err() - case <-req.Cancel: + err := ctx.Err() + cs.abortStream(err) + return nil, err + case <-cs.reqCancel: + cs.abortStream(http2errRequestCanceled) return nil, http2errRequestCanceled } } @@ -7779,8 +7874,8 @@ func (cc *http2ClientConn) RoundTrip(req *Request) (*Response, error) { // doRequest runs for the duration of the request lifetime. // // It sends the request and performs post-request cleanup (closing Request.Body, etc.). -func (cs *http2clientStream) doRequest() { - err := cs.writeRequest() +func (cs *http2clientStream) doRequest(req *Request) { + err := cs.writeRequest(req) cs.cleanupWriteRequest(err) } @@ -7791,12 +7886,11 @@ func (cs *http2clientStream) doRequest() { // // It returns non-nil if the request ends otherwise. // If the returned error is StreamError, the error Code may be used in resetting the stream. -func (cs *http2clientStream) writeRequest() (err error) { +func (cs *http2clientStream) writeRequest(req *Request) (err error) { cc := cs.cc - req := cs.req - ctx := req.Context() + ctx := cs.ctx - if err := http2checkConnHeaders(cs.req); err != nil { + if err := http2checkConnHeaders(req); err != nil { return err } @@ -7808,7 +7902,7 @@ func (cs *http2clientStream) writeRequest() (err error) { } select { case cc.reqHeaderMu <- struct{}{}: - case <-req.Cancel: + case <-cs.reqCancel: return http2errRequestCanceled case <-ctx.Done(): return ctx.Err() @@ -7831,7 +7925,7 @@ func (cs *http2clientStream) writeRequest() (err error) { if !cc.t.disableCompression() && req.Header.Get("Accept-Encoding") == "" && req.Header.Get("Range") == "" && - req.Method != "HEAD" { + !cs.isHead { // Request gzip only, not deflate. Deflate is ambiguous and // not as universally supported anyway. // See: https://zlib.net/zlib_faq.html#faq39 @@ -7850,19 +7944,23 @@ func (cs *http2clientStream) writeRequest() (err error) { continueTimeout := cc.t.expectContinueTimeout() if continueTimeout != 0 && !httpguts.HeaderValuesContainsToken( - cs.req.Header["Expect"], + req.Header["Expect"], "100-continue") { continueTimeout = 0 cs.on100 = make(chan struct{}, 1) } - err = cs.encodeAndWriteHeaders() + // Past this point (where we send request headers), it is possible for + // RoundTrip to return successfully. Since the RoundTrip contract permits + // the caller to "mutate or reuse" the Request after closing the Response's Body, + // we must take care when referencing the Request from here on. + err = cs.encodeAndWriteHeaders(req) <-cc.reqHeaderMu if err != nil { return err } - hasBody := http2actualContentLength(cs.req) != 0 + hasBody := cs.reqBodyContentLength != 0 if !hasBody { cs.sentEndStream = true } else { @@ -7878,7 +7976,7 @@ func (cs *http2clientStream) writeRequest() (err error) { err = cs.abortErr case <-ctx.Done(): err = ctx.Err() - case <-req.Cancel: + case <-cs.reqCancel: err = http2errRequestCanceled } timer.Stop() @@ -7888,7 +7986,7 @@ func (cs *http2clientStream) writeRequest() (err error) { } } - if err = cs.writeRequestBody(req.Body); err != nil { + if err = cs.writeRequestBody(req); err != nil { if err != http2errStopReqBodyWrite { http2traceWroteRequest(cs.trace, err) return err @@ -7923,16 +8021,15 @@ func (cs *http2clientStream) writeRequest() (err error) { return cs.abortErr case <-ctx.Done(): return ctx.Err() - case <-req.Cancel: + case <-cs.reqCancel: return http2errRequestCanceled } } } -func (cs *http2clientStream) encodeAndWriteHeaders() error { +func (cs *http2clientStream) encodeAndWriteHeaders(req *Request) error { cc := cs.cc - req := cs.req - ctx := req.Context() + ctx := cs.ctx cc.wmu.Lock() defer cc.wmu.Unlock() @@ -7943,7 +8040,7 @@ func (cs *http2clientStream) encodeAndWriteHeaders() error { return cs.abortErr case <-ctx.Done(): return ctx.Err() - case <-req.Cancel: + case <-cs.reqCancel: return http2errRequestCanceled default: } @@ -7953,14 +8050,14 @@ func (cs *http2clientStream) encodeAndWriteHeaders() error { // we send: HEADERS{1}, CONTINUATION{0,} + DATA{0,} (DATA is // sent by writeRequestBody below, along with any Trailers, // again in form HEADERS{1}, CONTINUATION{0,}) - trailers, err := http2commaSeparatedTrailers(cs.req) + trailers, err := http2commaSeparatedTrailers(req) if err != nil { return err } hasTrailers := trailers != "" - contentLen := http2actualContentLength(cs.req) + contentLen := http2actualContentLength(req) hasBody := contentLen != 0 - hdrs, err := cc.encodeHeaders(cs.req, cs.requestedGzip, trailers, contentLen) + hdrs, err := cc.encodeHeaders(req, cs.requestedGzip, trailers, contentLen) if err != nil { return err } @@ -7979,7 +8076,6 @@ func (cs *http2clientStream) encodeAndWriteHeaders() error { // cleanupWriteRequest will send a reset to the peer. func (cs *http2clientStream) cleanupWriteRequest(err error) { cc := cs.cc - req := cs.req if cs.ID == 0 { // We were canceled before creating the stream, so return our reservation. @@ -7990,10 +8086,12 @@ func (cs *http2clientStream) cleanupWriteRequest(err error) { // Request.Body is closed by the Transport, // and in multiple cases: server replies <=299 and >299 // while still writing request body - if req.Body != nil { - if e := req.Body.Close(); err == nil { - err = e - } + cc.mu.Lock() + bodyClosed := cs.reqBodyClosed + cs.reqBodyClosed = true + cc.mu.Unlock() + if !bodyClosed && cs.reqBody != nil { + cs.reqBody.Close() } if err != nil && cs.sentEndStream { @@ -8027,7 +8125,6 @@ func (cs *http2clientStream) cleanupWriteRequest(err error) { if cs.ID != 0 { cc.forgetStreamID(cs.ID) } - close(cs.donec) cc.wmu.Lock() werr := cc.werr @@ -8035,6 +8132,8 @@ func (cs *http2clientStream) cleanupWriteRequest(err error) { if werr != nil { cc.Close() } + + close(cs.donec) } // awaitOpenSlotForStream waits until len(streams) < maxConcurrentStreams. @@ -8108,7 +8207,7 @@ func (cs *http2clientStream) frameScratchBufferLen(maxFrameSize int) int { if n > max { n = max } - if cl := http2actualContentLength(cs.req); cl != -1 && cl+1 < n { + if cl := cs.reqBodyContentLength; cl != -1 && cl+1 < n { // Add an extra byte past the declared content-length to // give the caller's Request.Body io.Reader a chance to // give us more bytes than they declared, so we can catch it @@ -8123,13 +8222,13 @@ func (cs *http2clientStream) frameScratchBufferLen(maxFrameSize int) int { var http2bufPool sync.Pool // of *[]byte -func (cs *http2clientStream) writeRequestBody(body io.Reader) (err error) { +func (cs *http2clientStream) writeRequestBody(req *Request) (err error) { cc := cs.cc + body := cs.reqBody sentEnd := false // whether we sent the final DATA frame w/ END_STREAM - req := cs.req hasTrailers := req.Trailer != nil - remainLen := http2actualContentLength(req) + remainLen := cs.reqBodyContentLength hasContentLen := remainLen != -1 cc.mu.Lock() @@ -8170,23 +8269,26 @@ func (cs *http2clientStream) writeRequestBody(body io.Reader) (err error) { return err } } - if err == io.EOF { - sawEOF = true - err = nil - } else if err != nil { - return err + if err != nil { + cc.mu.Lock() + bodyClosed := cs.reqBodyClosed + cc.mu.Unlock() + switch { + case bodyClosed: + return http2errStopReqBodyWrite + case err == io.EOF: + sawEOF = true + err = nil + default: + return err + } } remain := buf[:n] for len(remain) > 0 && err == nil { var allowed int32 allowed, err = cs.awaitFlowControl(len(remain)) - switch { - case err == http2errStopReqBodyWrite: - return err - case err == http2errStopReqBodyWriteAndCancel: - return err - case err != nil: + if err != nil { return err } cc.wmu.Lock() @@ -8217,16 +8319,26 @@ func (cs *http2clientStream) writeRequestBody(body io.Reader) (err error) { return nil } + // Since the RoundTrip contract permits the caller to "mutate or reuse" + // a request after the Response's Body is closed, verify that this hasn't + // happened before accessing the trailers. + cc.mu.Lock() + trailer := req.Trailer + err = cs.abortErr + cc.mu.Unlock() + if err != nil { + return err + } + cc.wmu.Lock() + defer cc.wmu.Unlock() var trls []byte - if hasTrailers { - trls, err = cc.encodeTrailers(req) + if len(trailer) > 0 { + trls, err = cc.encodeTrailers(trailer) if err != nil { - cc.wmu.Unlock() return err } } - defer cc.wmu.Unlock() // Two ways to send END_STREAM: either with trailers, or // with an empty DATA frame. @@ -8247,23 +8359,22 @@ func (cs *http2clientStream) writeRequestBody(body io.Reader) (err error) { // if the stream is dead. func (cs *http2clientStream) awaitFlowControl(maxBytes int) (taken int32, err error) { cc := cs.cc - req := cs.req - ctx := req.Context() + ctx := cs.ctx cc.mu.Lock() defer cc.mu.Unlock() for { if cc.closed { return 0, http2errClientConnClosed } - if cs.stopReqBody != nil { - return 0, cs.stopReqBody + if cs.reqBodyClosed { + return 0, http2errStopReqBodyWrite } select { case <-cs.abort: return 0, cs.abortErr case <-ctx.Done(): return 0, ctx.Err() - case <-req.Cancel: + case <-cs.reqCancel: return 0, http2errRequestCanceled default: } @@ -8477,11 +8588,11 @@ func http2shouldSendReqContentLength(method string, contentLength int64) bool { } // requires cc.wmu be held. -func (cc *http2ClientConn) encodeTrailers(req *Request) ([]byte, error) { +func (cc *http2ClientConn) encodeTrailers(trailer Header) ([]byte, error) { cc.hbuf.Reset() hlSize := uint64(0) - for k, vv := range req.Trailer { + for k, vv := range trailer { for _, v := range vv { hf := hpack.HeaderField{Name: k, Value: v} hlSize += uint64(hf.Size()) @@ -8491,7 +8602,7 @@ func (cc *http2ClientConn) encodeTrailers(req *Request) ([]byte, error) { return nil, http2errRequestHeaderListSize } - for k, vv := range req.Trailer { + for k, vv := range trailer { lowKey, ascii := http2asciiToLower(k) if !ascii { // Skip writing invalid headers. Per RFC 7540, Section 8.1.2, header @@ -8627,7 +8738,13 @@ func (rl *http2clientConnReadLoop) cleanup() { } cc.closed = true for _, cs := range cc.streams { - cs.abortStreamLocked(err) + select { + case <-cs.peerClosed: + // The server closed the stream before closing the conn, + // so no need to interrupt it. + default: + cs.abortStreamLocked(err) + } } cc.cond.Broadcast() cc.mu.Unlock() @@ -8869,28 +8986,35 @@ func (rl *http2clientConnReadLoop) handleResponse(cs *http2clientStream, f *http return nil, nil } - streamEnded := f.StreamEnded() - isHead := cs.req.Method == "HEAD" - if !streamEnded || isHead { - res.ContentLength = -1 - if clens := res.Header["Content-Length"]; len(clens) == 1 { - if cl, err := strconv.ParseUint(clens[0], 10, 63); err == nil { - res.ContentLength = int64(cl) - } else { - // TODO: care? unlike http/1, it won't mess up our framing, so it's - // more safe smuggling-wise to ignore. - } - } else if len(clens) > 1 { + res.ContentLength = -1 + if clens := res.Header["Content-Length"]; len(clens) == 1 { + if cl, err := strconv.ParseUint(clens[0], 10, 63); err == nil { + res.ContentLength = int64(cl) + } else { // TODO: care? unlike http/1, it won't mess up our framing, so it's // more safe smuggling-wise to ignore. } + } else if len(clens) > 1 { + // TODO: care? unlike http/1, it won't mess up our framing, so it's + // more safe smuggling-wise to ignore. + } else if f.StreamEnded() && !cs.isHead { + res.ContentLength = 0 } - if streamEnded || isHead { + if cs.isHead { res.Body = http2noBody return res, nil } + if f.StreamEnded() { + if res.ContentLength > 0 { + res.Body = http2missingBody{} + } else { + res.Body = http2noBody + } + return res, nil + } + cs.bufPipe.setBuffer(&http2dataBuffer{expected: res.ContentLength}) cs.bytesRemain = res.ContentLength res.Body = http2transportResponseBody{cs} @@ -8934,8 +9058,7 @@ func (rl *http2clientConnReadLoop) processTrailers(cs *http2clientStream, f *htt } // transportResponseBody is the concrete type of Transport.RoundTrip's -// Response.Body. It is an io.ReadCloser. On Read, it reads from cs.body. -// On Close it sends RST_STREAM if EOF wasn't already seen. +// Response.Body. It is an io.ReadCloser. type http2transportResponseBody struct { cs *http2clientStream } @@ -9018,6 +9141,8 @@ func (b http2transportResponseBody) Close() error { } cc.mu.Unlock() + // TODO(dneil): Acquiring this mutex can block indefinitely. + // Move flow control return to a goroutine? cc.wmu.Lock() // Return connection-level flow control. if unread > 0 { @@ -9032,9 +9157,9 @@ func (b http2transportResponseBody) Close() error { select { case <-cs.donec: - case <-cs.req.Context().Done(): - return cs.req.Context().Err() - case <-cs.req.Cancel: + case <-cs.ctx.Done(): + return cs.ctx.Err() + case <-cs.reqCancel: return http2errRequestCanceled } return nil @@ -9088,7 +9213,7 @@ func (rl *http2clientConnReadLoop) processData(f *http2DataFrame) error { return nil } if f.Length > 0 { - if cs.req.Method == "HEAD" && len(data) > 0 { + if cs.isHead && len(data) > 0 { cc.logf("protocol error: received DATA on a HEAD request") rl.endStreamError(cs, http2StreamError{ StreamID: f.StreamID, @@ -9157,6 +9282,12 @@ func (rl *http2clientConnReadLoop) endStream(cs *http2clientStream) { // server.go's (*stream).endStream method. if !cs.readClosed { cs.readClosed = true + // Close cs.bufPipe and cs.peerClosed with cc.mu held to avoid a + // race condition: The caller can read io.EOF from Response.Body + // and close the body before we close cs.peerClosed, causing + // cleanupWriteRequest to send a RST_STREAM. + rl.cc.mu.Lock() + defer rl.cc.mu.Unlock() cs.bufPipe.closeWithErrorAndCode(io.EOF, cs.copyTrailers) close(cs.peerClosed) } @@ -9344,19 +9475,24 @@ func (cc *http2ClientConn) Ping(ctx context.Context) error { } cc.mu.Unlock() } - cc.wmu.Lock() - if err := cc.fr.WritePing(false, p); err != nil { - cc.wmu.Unlock() - return err - } - if err := cc.bw.Flush(); err != nil { - cc.wmu.Unlock() - return err - } - cc.wmu.Unlock() + errc := make(chan error, 1) + go func() { + cc.wmu.Lock() + defer cc.wmu.Unlock() + if err := cc.fr.WritePing(false, p); err != nil { + errc <- err + return + } + if err := cc.bw.Flush(); err != nil { + errc <- err + return + } + }() select { case <-c: return nil + case err := <-errc: + return err case <-ctx.Done(): return ctx.Err() case <-cc.readerDone: @@ -9433,6 +9569,12 @@ func (t *http2Transport) logf(format string, args ...interface{}) { var http2noBody io.ReadCloser = ioutil.NopCloser(bytes.NewReader(nil)) +type http2missingBody struct{} + +func (http2missingBody) Close() error { return nil } + +func (http2missingBody) Read([]byte) (int, error) { return 0, io.ErrUnexpectedEOF } + func http2strSliceContains(ss []string, s string) bool { for _, v := range ss { if v == s { diff --git a/src/vendor/golang.org/x/net/http/httpproxy/proxy.go b/src/vendor/golang.org/x/net/http/httpproxy/proxy.go index 1415b07791..d2c8c87eab 100644 --- a/src/vendor/golang.org/x/net/http/httpproxy/proxy.go +++ b/src/vendor/golang.org/x/net/http/httpproxy/proxy.go @@ -113,8 +113,8 @@ func getEnvAny(names ...string) string { // environment, or a proxy should not be used for the given request, as // defined by NO_PROXY. // -// As a special case, if req.URL.Host is "localhost" (with or without a -// port number), then a nil URL and nil error will be returned. +// As a special case, if req.URL.Host is "localhost" or a loopback address +// (with or without a port number), then a nil URL and nil error will be returned. func (cfg *Config) ProxyFunc() func(reqURL *url.URL) (*url.URL, error) { // Preprocess the Config settings for more efficient evaluation. cfg1 := &config{ diff --git a/src/vendor/golang.org/x/net/http2/hpack/huffman.go b/src/vendor/golang.org/x/net/http2/hpack/huffman.go index a1ab2f0567..fe0b84ccd4 100644 --- a/src/vendor/golang.org/x/net/http2/hpack/huffman.go +++ b/src/vendor/golang.org/x/net/http2/hpack/huffman.go @@ -140,25 +140,29 @@ func buildRootHuffmanNode() { panic("unexpected size") } lazyRootHuffmanNode = newInternalNode() - for i, code := range huffmanCodes { - addDecoderNode(byte(i), code, huffmanCodeLen[i]) - } -} + // allocate a leaf node for each of the 256 symbols + leaves := new([256]node) + + for sym, code := range huffmanCodes { + codeLen := huffmanCodeLen[sym] + + cur := lazyRootHuffmanNode + for codeLen > 8 { + codeLen -= 8 + i := uint8(code >> codeLen) + if cur.children[i] == nil { + cur.children[i] = newInternalNode() + } + cur = cur.children[i] + } + shift := 8 - codeLen + start, end := int(uint8(code< 8 { - codeLen -= 8 - i := uint8(code >> codeLen) - if cur.children[i] == nil { - cur.children[i] = newInternalNode() + leaves[sym].sym = byte(sym) + leaves[sym].codeLen = codeLen + for i := start; i < start+end; i++ { + cur.children[i] = &leaves[sym] } - cur = cur.children[i] - } - shift := 8 - codeLen - start, end := int(uint8(code< tmax { + } else if k >= bias+tmax { t = tmax } if digit < t { break } - w *= base - t - if w >= math.MaxInt32/base { + w, overflow = madd(0, w, base-t) + if overflow { return "", punyError(encoded) } } + if len(output) >= 1024 { + return "", punyError(encoded) + } x := int32(len(output) + 1) bias = adapt(i-oldI, x, oldI == 0) n += i / x i %= x - if n > utf8.MaxRune || len(output) >= 1024 { + if n < 0 || n > utf8.MaxRune { return "", punyError(encoded) } output = append(output, 0) @@ -115,6 +119,7 @@ func encode(prefix, s string) (string, error) { if b > 0 { output = append(output, '-') } + overflow := false for remaining != 0 { m := int32(0x7fffffff) for _, r := range s { @@ -122,8 +127,8 @@ func encode(prefix, s string) (string, error) { m = r } } - delta += (m - n) * (h + 1) - if delta < 0 { + delta, overflow = madd(delta, m-n, h+1) + if overflow { return "", punyError(s) } n = m @@ -141,9 +146,9 @@ func encode(prefix, s string) (string, error) { q := delta for k := base; ; k += base { t := k - bias - if t < tmin { + if k <= bias { t = tmin - } else if t > tmax { + } else if k >= bias+tmax { t = tmax } if q < t { @@ -164,6 +169,15 @@ func encode(prefix, s string) (string, error) { return string(output), nil } +// madd computes a + (b * c), detecting overflow. +func madd(a, b, c int32) (next int32, overflow bool) { + p := int64(b) * int64(c) + if p > math.MaxInt32-int64(a) { + return 0, true + } + return a + int32(p), false +} + func decodeDigit(x byte) (digit int32, ok bool) { switch { case '0' <= x && x <= '9': diff --git a/src/vendor/golang.org/x/net/nettest/nettest.go b/src/vendor/golang.org/x/net/nettest/nettest.go index 83ba858e24..ae5413b23d 100644 --- a/src/vendor/golang.org/x/net/nettest/nettest.go +++ b/src/vendor/golang.org/x/net/nettest/nettest.go @@ -95,13 +95,8 @@ func TestableNetwork(network string) bool { // This is an internal network name for testing on the // package net of the standard library. switch runtime.GOOS { - case "android", "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "android", "fuchsia", "hurd", "ios", "js", "nacl", "plan9", "windows": return false - case "darwin", "ios": - // iOS doesn't support it. - if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" { - return false - } } case "ip", "ip4", "ip6": switch runtime.GOOS { @@ -114,15 +109,10 @@ func TestableNetwork(network string) bool { } case "unix", "unixgram": switch runtime.GOOS { - case "android", "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "android", "fuchsia", "hurd", "ios", "js", "nacl", "plan9", "windows": return false case "aix": return unixStrmDgramEnabled() - case "darwin", "ios": - // iOS does not support unix, unixgram. - if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" { - return false - } } case "unixpacket": switch runtime.GOOS { diff --git a/src/vendor/golang.org/x/text/unicode/bidi/core.go b/src/vendor/golang.org/x/text/unicode/bidi/core.go index e4c0811016..fde188a33b 100644 --- a/src/vendor/golang.org/x/text/unicode/bidi/core.go +++ b/src/vendor/golang.org/x/text/unicode/bidi/core.go @@ -495,9 +495,9 @@ func (s *isolatingRunSequence) resolveWeakTypes() { if t == NSM { s.types[i] = precedingCharacterType } else { - if t.in(LRI, RLI, FSI, PDI) { - precedingCharacterType = ON - } + // if t.in(LRI, RLI, FSI, PDI) { + // precedingCharacterType = ON + // } precedingCharacterType = t } } diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index f550e36d17..81aad95ad7 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -9,7 +9,7 @@ golang.org/x/crypto/curve25519/internal/field golang.org/x/crypto/hkdf golang.org/x/crypto/internal/subtle golang.org/x/crypto/poly1305 -# golang.org/x/net v0.0.0-20211005215030-d2e5035098b3 +# golang.org/x/net v0.0.0-20211108170745-6635138e15ea ## explicit; go 1.17 golang.org/x/net/dns/dnsmessage golang.org/x/net/http/httpguts @@ -22,7 +22,7 @@ golang.org/x/net/route # golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e ## explicit; go 1.17 golang.org/x/sys/cpu -# golang.org/x/text v0.3.7 +# golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 ## explicit; go 1.17 golang.org/x/text/secure/bidirule golang.org/x/text/transform -- GitLab From 74b9939ec4a9f41bffb4dda47205d55c28e25728 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Tue, 9 Nov 2021 13:49:45 -0500 Subject: [PATCH 2076/2500] all: update vendored golang.org/x/crypto for Go 1.18 release The Go 1.18 code freeze has recently started. This is a time to update all golang.org/x/... module versions that contribute packages to the std and cmd modules in the standard library to latest master versions. This CL updates only the crypto module, as well as the TestDependencies policy to accommodate the dependency order change done in CL 345649. The next CL will update further modules. For #36905. Change-Id: If93160d8d72ca86e9995aaf5bdfc3d2c20b4695d Reviewed-on: https://go-review.googlesource.com/c/go/+/362736 Trust: Dmitri Shuralyov Run-TryBot: Dmitri Shuralyov TryBot-Result: Go Bot Reviewed-by: Heschi Kreinick --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 ++-- src/cmd/vendor/modules.txt | 2 +- src/go.mod | 2 +- src/go.sum | 4 ++-- src/go/build/deps_test.go | 2 +- .../x/crypto/chacha20poly1305/chacha20poly1305.go | 6 +++++- .../x/crypto/chacha20poly1305/chacha20poly1305_generic.go | 2 +- .../x/crypto/chacha20poly1305/xchacha20poly1305.go | 2 +- .../x/crypto/{ => internal}/poly1305/bits_compat.go | 0 .../x/crypto/{ => internal}/poly1305/bits_go1.13.go | 0 .../x/crypto/{ => internal}/poly1305/mac_noasm.go | 0 .../golang.org/x/crypto/{ => internal}/poly1305/poly1305.go | 2 +- .../x/crypto/{ => internal}/poly1305/sum_amd64.go | 0 .../golang.org/x/crypto/{ => internal}/poly1305/sum_amd64.s | 0 .../x/crypto/{ => internal}/poly1305/sum_generic.go | 0 .../x/crypto/{ => internal}/poly1305/sum_ppc64le.go | 0 .../x/crypto/{ => internal}/poly1305/sum_ppc64le.s | 0 .../x/crypto/{ => internal}/poly1305/sum_s390x.go | 0 .../golang.org/x/crypto/{ => internal}/poly1305/sum_s390x.s | 2 +- src/vendor/modules.txt | 4 ++-- 21 files changed, 19 insertions(+), 15 deletions(-) rename src/vendor/golang.org/x/crypto/{ => internal}/poly1305/bits_compat.go (100%) rename src/vendor/golang.org/x/crypto/{ => internal}/poly1305/bits_go1.13.go (100%) rename src/vendor/golang.org/x/crypto/{ => internal}/poly1305/mac_noasm.go (100%) rename src/vendor/golang.org/x/crypto/{ => internal}/poly1305/poly1305.go (98%) rename src/vendor/golang.org/x/crypto/{ => internal}/poly1305/sum_amd64.go (100%) rename src/vendor/golang.org/x/crypto/{ => internal}/poly1305/sum_amd64.s (100%) rename src/vendor/golang.org/x/crypto/{ => internal}/poly1305/sum_generic.go (100%) rename src/vendor/golang.org/x/crypto/{ => internal}/poly1305/sum_ppc64le.go (100%) rename src/vendor/golang.org/x/crypto/{ => internal}/poly1305/sum_ppc64le.s (100%) rename src/vendor/golang.org/x/crypto/{ => internal}/poly1305/sum_s390x.go (100%) rename src/vendor/golang.org/x/crypto/{ => internal}/poly1305/sum_s390x.s (99%) diff --git a/src/cmd/go.mod b/src/cmd/go.mod index ea4e8a3104..173679c7be 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -13,7 +13,7 @@ require ( require ( github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d // indirect - golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect + golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa // indirect golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 01da0f686c..9188847173 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -7,8 +7,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d h1:uGg2frl github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa h1:idItI2DDfCokpg0N51B2VtiLdJ4vAuXC9fnCb2gACo4= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/mod v0.5.1-0.20210913215816-37dd6891021a h1:55PVa91KndtPGH2lus5l2gDZqoO/x+Oa5CV0lVf8Ij8= golang.org/x/mod v0.5.1-0.20210913215816-37dd6891021a/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 3a9b4f8736..2ac22b951b 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -24,7 +24,7 @@ golang.org/x/arch/arm/armasm golang.org/x/arch/arm64/arm64asm golang.org/x/arch/ppc64/ppc64asm golang.org/x/arch/x86/x86asm -# golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 +# golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa ## explicit; go 1.17 golang.org/x/crypto/ed25519 golang.org/x/crypto/ed25519/internal/edwards25519 diff --git a/src/go.mod b/src/go.mod index 3e7b86ee25..b8c4d5c16b 100644 --- a/src/go.mod +++ b/src/go.mod @@ -3,7 +3,7 @@ module std go 1.18 require ( - golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 + golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa golang.org/x/net v0.0.0-20211108170745-6635138e15ea ) diff --git a/src/go.sum b/src/go.sum index f9e5e7d4b8..ff1288f81d 100644 --- a/src/go.sum +++ b/src/go.sum @@ -1,5 +1,5 @@ -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa h1:idItI2DDfCokpg0N51B2VtiLdJ4vAuXC9fnCb2gACo4= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/net v0.0.0-20211108170745-6635138e15ea h1:FosBMXtOc8Tp9Hbo4ltl1WJSrTVewZU8MPnTPY2HdH8= golang.org/x/net v0.0.0-20211108170745-6635138e15ea/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e h1:i6Vklmyu+fZMFYpum+sR4ZWABGW7MyIxfJZXYvcnbns= diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 1dd65d60d9..2f68cbcffc 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -436,7 +436,7 @@ var depsRules = ` CRYPTO-MATH, NET, container/list, encoding/hex, encoding/pem < golang.org/x/crypto/internal/subtle < golang.org/x/crypto/chacha20 - < golang.org/x/crypto/poly1305 + < golang.org/x/crypto/internal/poly1305 < golang.org/x/crypto/chacha20poly1305 < golang.org/x/crypto/hkdf < crypto/x509/internal/macos diff --git a/src/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go b/src/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go index 0d7bac3f7d..93da7322bc 100644 --- a/src/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go +++ b/src/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go @@ -26,6 +26,10 @@ const ( // NonceSizeX is the size of the nonce used with the XChaCha20-Poly1305 // variant of this AEAD, in bytes. NonceSizeX = 24 + + // Overhead is the size of the Poly1305 authentication tag, and the + // difference between a ciphertext length and its plaintext. + Overhead = 16 ) type chacha20poly1305 struct { @@ -47,7 +51,7 @@ func (c *chacha20poly1305) NonceSize() int { } func (c *chacha20poly1305) Overhead() int { - return 16 + return Overhead } func (c *chacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte { diff --git a/src/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go b/src/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go index fe191d395d..96b2fd898b 100644 --- a/src/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go +++ b/src/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go @@ -8,8 +8,8 @@ import ( "encoding/binary" "golang.org/x/crypto/chacha20" + "golang.org/x/crypto/internal/poly1305" "golang.org/x/crypto/internal/subtle" - "golang.org/x/crypto/poly1305" ) func writeWithPadding(p *poly1305.MAC, b []byte) { diff --git a/src/vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go b/src/vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go index d9d46b9639..1cebfe946f 100644 --- a/src/vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go +++ b/src/vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go @@ -35,7 +35,7 @@ func (*xchacha20poly1305) NonceSize() int { } func (*xchacha20poly1305) Overhead() int { - return 16 + return Overhead } func (x *xchacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte { diff --git a/src/vendor/golang.org/x/crypto/poly1305/bits_compat.go b/src/vendor/golang.org/x/crypto/internal/poly1305/bits_compat.go similarity index 100% rename from src/vendor/golang.org/x/crypto/poly1305/bits_compat.go rename to src/vendor/golang.org/x/crypto/internal/poly1305/bits_compat.go diff --git a/src/vendor/golang.org/x/crypto/poly1305/bits_go1.13.go b/src/vendor/golang.org/x/crypto/internal/poly1305/bits_go1.13.go similarity index 100% rename from src/vendor/golang.org/x/crypto/poly1305/bits_go1.13.go rename to src/vendor/golang.org/x/crypto/internal/poly1305/bits_go1.13.go diff --git a/src/vendor/golang.org/x/crypto/poly1305/mac_noasm.go b/src/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go similarity index 100% rename from src/vendor/golang.org/x/crypto/poly1305/mac_noasm.go rename to src/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go diff --git a/src/vendor/golang.org/x/crypto/poly1305/poly1305.go b/src/vendor/golang.org/x/crypto/internal/poly1305/poly1305.go similarity index 98% rename from src/vendor/golang.org/x/crypto/poly1305/poly1305.go rename to src/vendor/golang.org/x/crypto/internal/poly1305/poly1305.go index 9d7a6af09f..4aaea810a2 100644 --- a/src/vendor/golang.org/x/crypto/poly1305/poly1305.go +++ b/src/vendor/golang.org/x/crypto/internal/poly1305/poly1305.go @@ -15,7 +15,7 @@ // used with a fixed key in order to generate one-time keys from an nonce. // However, in this package AES isn't used and the one-time key is specified // directly. -package poly1305 // import "golang.org/x/crypto/poly1305" +package poly1305 import "crypto/subtle" diff --git a/src/vendor/golang.org/x/crypto/poly1305/sum_amd64.go b/src/vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.go similarity index 100% rename from src/vendor/golang.org/x/crypto/poly1305/sum_amd64.go rename to src/vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.go diff --git a/src/vendor/golang.org/x/crypto/poly1305/sum_amd64.s b/src/vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.s similarity index 100% rename from src/vendor/golang.org/x/crypto/poly1305/sum_amd64.s rename to src/vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.s diff --git a/src/vendor/golang.org/x/crypto/poly1305/sum_generic.go b/src/vendor/golang.org/x/crypto/internal/poly1305/sum_generic.go similarity index 100% rename from src/vendor/golang.org/x/crypto/poly1305/sum_generic.go rename to src/vendor/golang.org/x/crypto/internal/poly1305/sum_generic.go diff --git a/src/vendor/golang.org/x/crypto/poly1305/sum_ppc64le.go b/src/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.go similarity index 100% rename from src/vendor/golang.org/x/crypto/poly1305/sum_ppc64le.go rename to src/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.go diff --git a/src/vendor/golang.org/x/crypto/poly1305/sum_ppc64le.s b/src/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s similarity index 100% rename from src/vendor/golang.org/x/crypto/poly1305/sum_ppc64le.s rename to src/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s diff --git a/src/vendor/golang.org/x/crypto/poly1305/sum_s390x.go b/src/vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.go similarity index 100% rename from src/vendor/golang.org/x/crypto/poly1305/sum_s390x.go rename to src/vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.go diff --git a/src/vendor/golang.org/x/crypto/poly1305/sum_s390x.s b/src/vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.s similarity index 99% rename from src/vendor/golang.org/x/crypto/poly1305/sum_s390x.s rename to src/vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.s index 69c64f8421..aa9e0494c9 100644 --- a/src/vendor/golang.org/x/crypto/poly1305/sum_s390x.s +++ b/src/vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.s @@ -18,7 +18,7 @@ // value. These limbs are, for the most part, zero extended and // placed into 64-bit vector register elements. Each vector // register is 128-bits wide and so holds 2 of these elements. -// Using 26-bit limbs allows us plenty of headroom to accomodate +// Using 26-bit limbs allows us plenty of headroom to accommodate // accumulations before and after multiplication without // overflowing either 32-bits (before multiplication) or 64-bits // (after multiplication). diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index 81aad95ad7..004b599288 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -1,4 +1,4 @@ -# golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 +# golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa ## explicit; go 1.17 golang.org/x/crypto/chacha20 golang.org/x/crypto/chacha20poly1305 @@ -7,8 +7,8 @@ golang.org/x/crypto/cryptobyte/asn1 golang.org/x/crypto/curve25519 golang.org/x/crypto/curve25519/internal/field golang.org/x/crypto/hkdf +golang.org/x/crypto/internal/poly1305 golang.org/x/crypto/internal/subtle -golang.org/x/crypto/poly1305 # golang.org/x/net v0.0.0-20211108170745-6635138e15ea ## explicit; go 1.17 golang.org/x/net/dns/dnsmessage -- GitLab From 5430203a1e7f3ba3af70b17bf2eeb61efda2ae58 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Tue, 9 Nov 2021 13:54:57 -0500 Subject: [PATCH 2077/2500] all: update vendored golang.org/x/tools for Go 1.18 release The Go 1.18 code freeze has recently started. This is a time to update all golang.org/x/... module versions that contribute packages to the std and cmd modules in the standard library to latest master versions. This CL updates only the tools module, keeping mod unchanged because its lastest commit isn't ready to be vendored yet. For #36905. Updates #49350. Change-Id: Ib39713d28a55fc9ec79058aab9919eba912def5f Reviewed-on: https://go-review.googlesource.com/c/go/+/361094 Trust: Dmitri Shuralyov Run-TryBot: Dmitri Shuralyov Reviewed-by: Heschi Kreinick TryBot-Result: Go Bot --- src/cmd/go.mod | 4 +- src/cmd/go.sum | 8 +- .../go/analysis/internal/facts/imports.go | 33 ++- .../go/analysis/passes/copylock/copylock.go | 75 ++++++- .../go/analysis/passes/ctrlflow/ctrlflow.go | 6 +- .../go/analysis/passes/nilfunc/nilfunc.go | 6 + .../tools/go/analysis/passes/printf/printf.go | 38 +++- .../tools/go/analysis/passes/printf/types.go | 211 ++++++++++++------ .../x/tools/go/analysis/passes/shift/shift.go | 26 ++- .../analysis/passes/stringintconv/string.go | 132 ++++++++--- .../testinggoroutine/testinggoroutine.go | 23 +- .../x/tools/go/analysis/passes/tests/tests.go | 10 + .../passes/unusedresult/unusedresult.go | 6 + .../x/tools/go/types/typeutil/callee.go | 30 ++- src/cmd/vendor/modules.txt | 4 +- 15 files changed, 467 insertions(+), 145 deletions(-) diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 173679c7be..facc54cee1 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -5,10 +5,10 @@ go 1.18 require ( github.com/google/pprof v0.0.0-20211104044539-f987b9c94b31 golang.org/x/arch v0.0.0-20210923205945-b76863e36670 - golang.org/x/mod v0.5.1-0.20210913215816-37dd6891021a + golang.org/x/mod v0.6.0-dev.0.20210913215816-37dd6891021a golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 - golang.org/x/tools v0.1.8-0.20211025211149-f916b54a1784 + golang.org/x/tools v0.1.8-0.20211109164901-e9000123914f ) require ( diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 9188847173..f248d84e24 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -9,8 +9,8 @@ golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VA golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa h1:idItI2DDfCokpg0N51B2VtiLdJ4vAuXC9fnCb2gACo4= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/mod v0.5.1-0.20210913215816-37dd6891021a h1:55PVa91KndtPGH2lus5l2gDZqoO/x+Oa5CV0lVf8Ij8= -golang.org/x/mod v0.5.1-0.20210913215816-37dd6891021a/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20210913215816-37dd6891021a h1:gAiIC0JKDJwXAQFyqEYxROcAzeeh5ZTwWjKORCFuQxs= +golang.org/x/mod v0.6.0-dev.0.20210913215816-37dd6891021a/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -18,7 +18,7 @@ golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e h1:i6Vklmyu+fZMFYpum+sR4ZWAB golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/tools v0.1.8-0.20211025211149-f916b54a1784 h1:+xP+QoP2SEPgbn+07I/yJTzP+gavj0XKGS6+JU5tlck= -golang.org/x/tools v0.1.8-0.20211025211149-f916b54a1784/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/tools v0.1.8-0.20211109164901-e9000123914f h1:wwsTeyXackfHvwdCKtGcDlYwO78AwwW6OwUomSMB0aI= +golang.org/x/tools v0.1.8-0.20211109164901-e9000123914f/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/internal/facts/imports.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/internal/facts/imports.go index 34740f48e0..ade0cc6fab 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/internal/facts/imports.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/internal/facts/imports.go @@ -4,7 +4,11 @@ package facts -import "go/types" +import ( + "go/types" + + "golang.org/x/tools/internal/typeparams" +) // importMap computes the import map for a package by traversing the // entire exported API each of its imports. @@ -42,9 +46,20 @@ func importMap(imports []*types.Package) map[string]*types.Package { // nop case *types.Named: if addObj(T.Obj()) { + // TODO(taking): Investigate why the Underlying type is not added here. for i := 0; i < T.NumMethods(); i++ { addObj(T.Method(i)) } + if tparams := typeparams.ForNamed(T); tparams != nil { + for i := 0; i < tparams.Len(); i++ { + addType(tparams.At(i)) + } + } + if targs := typeparams.NamedTypeArgs(T); targs != nil { + for i := 0; i < targs.Len(); i++ { + addType(targs.At(i)) + } + } } case *types.Pointer: addType(T.Elem()) @@ -60,6 +75,11 @@ func importMap(imports []*types.Package) map[string]*types.Package { case *types.Signature: addType(T.Params()) addType(T.Results()) + if tparams := typeparams.ForSignature(T); tparams != nil { + for i := 0; i < tparams.Len(); i++ { + addType(tparams.At(i)) + } + } case *types.Struct: for i := 0; i < T.NumFields(); i++ { addObj(T.Field(i)) @@ -72,6 +92,17 @@ func importMap(imports []*types.Package) map[string]*types.Package { for i := 0; i < T.NumMethods(); i++ { addObj(T.Method(i)) } + for i := 0; i < T.NumEmbeddeds(); i++ { + addType(T.EmbeddedType(i)) // walk Embedded for implicits + } + case *typeparams.Union: + for i := 0; i < T.Len(); i++ { + addType(T.Term(i).Type()) + } + case *typeparams.TypeParam: + if addObj(T.Obj()) { + addType(T.Constraint()) + } } } diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/copylock/copylock.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/copylock/copylock.go index c4ebf78571..350dc4e0fe 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/copylock/copylock.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/copylock/copylock.go @@ -17,6 +17,7 @@ import ( "golang.org/x/tools/go/analysis/passes/inspect" "golang.org/x/tools/go/analysis/passes/internal/analysisutil" "golang.org/x/tools/go/ast/inspector" + "golang.org/x/tools/internal/typeparams" ) const Doc = `check for locks erroneously passed by value @@ -145,7 +146,7 @@ func checkCopyLocksCallExpr(pass *analysis.Pass, ce *ast.CallExpr) { func checkCopyLocksFunc(pass *analysis.Pass, name string, recv *ast.FieldList, typ *ast.FuncType) { if recv != nil && len(recv.List) > 0 { expr := recv.List[0].Type - if path := lockPath(pass.Pkg, pass.TypesInfo.Types[expr].Type); path != nil { + if path := lockPath(pass.Pkg, pass.TypesInfo.Types[expr].Type, nil); path != nil { pass.ReportRangef(expr, "%s passes lock by value: %v", name, path) } } @@ -153,7 +154,7 @@ func checkCopyLocksFunc(pass *analysis.Pass, name string, recv *ast.FieldList, t if typ.Params != nil { for _, field := range typ.Params.List { expr := field.Type - if path := lockPath(pass.Pkg, pass.TypesInfo.Types[expr].Type); path != nil { + if path := lockPath(pass.Pkg, pass.TypesInfo.Types[expr].Type, nil); path != nil { pass.ReportRangef(expr, "%s passes lock by value: %v", name, path) } } @@ -199,12 +200,12 @@ func checkCopyLocksRangeVar(pass *analysis.Pass, rtok token.Token, e ast.Expr) { if typ == nil { return } - if path := lockPath(pass.Pkg, typ); path != nil { + if path := lockPath(pass.Pkg, typ, nil); path != nil { pass.Reportf(e.Pos(), "range var %s copies lock: %v", analysisutil.Format(pass.Fset, e), path) } } -type typePath []types.Type +type typePath []string // String pretty-prints a typePath. func (path typePath) String() string { @@ -215,7 +216,7 @@ func (path typePath) String() string { fmt.Fprint(&buf, " contains ") } // The human-readable path is in reverse order, outermost to innermost. - fmt.Fprint(&buf, path[n-i-1].String()) + fmt.Fprint(&buf, path[n-i-1]) } return buf.String() } @@ -234,16 +235,57 @@ func lockPathRhs(pass *analysis.Pass, x ast.Expr) typePath { return nil } } - return lockPath(pass.Pkg, pass.TypesInfo.Types[x].Type) + return lockPath(pass.Pkg, pass.TypesInfo.Types[x].Type, nil) } // lockPath returns a typePath describing the location of a lock value // contained in typ. If there is no contained lock, it returns nil. -func lockPath(tpkg *types.Package, typ types.Type) typePath { +// +// The seenTParams map is used to short-circuit infinite recursion via type +// parameters. +func lockPath(tpkg *types.Package, typ types.Type, seenTParams map[*typeparams.TypeParam]bool) typePath { if typ == nil { return nil } + if tpar, ok := typ.(*typeparams.TypeParam); ok { + if seenTParams == nil { + // Lazily allocate seenTParams, since the common case will not involve + // any type parameters. + seenTParams = make(map[*typeparams.TypeParam]bool) + } + if seenTParams[tpar] { + return nil + } + seenTParams[tpar] = true + terms, err := typeparams.StructuralTerms(tpar) + if err != nil { + return nil // invalid type + } + for _, term := range terms { + subpath := lockPath(tpkg, term.Type(), seenTParams) + if len(subpath) > 0 { + if term.Tilde() { + // Prepend a tilde to our lock path entry to clarify the resulting + // diagnostic message. Consider the following example: + // + // func _[Mutex interface{ ~sync.Mutex; M() }](m Mutex) {} + // + // Here the naive error message will be something like "passes lock + // by value: Mutex contains sync.Mutex". This is misleading because + // the local type parameter doesn't actually contain sync.Mutex, + // which lacks the M method. + // + // With tilde, it is clearer that the containment is via an + // approximation element. + subpath[len(subpath)-1] = "~" + subpath[len(subpath)-1] + } + return append(subpath, typ.String()) + } + } + return nil + } + for { atyp, ok := typ.Underlying().(*types.Array) if !ok { @@ -252,6 +294,17 @@ func lockPath(tpkg *types.Package, typ types.Type) typePath { typ = atyp.Elem() } + ttyp, ok := typ.Underlying().(*types.Tuple) + if ok { + for i := 0; i < ttyp.Len(); i++ { + subpath := lockPath(tpkg, ttyp.At(i).Type(), seenTParams) + if subpath != nil { + return append(subpath, typ.String()) + } + } + return nil + } + // We're only interested in the case in which the underlying // type is a struct. (Interfaces and pointers are safe to copy.) styp, ok := typ.Underlying().(*types.Struct) @@ -263,7 +316,7 @@ func lockPath(tpkg *types.Package, typ types.Type) typePath { // is a sync.Locker, but a value is not. This differentiates // embedded interfaces from embedded values. if types.Implements(types.NewPointer(typ), lockerType) && !types.Implements(typ, lockerType) { - return []types.Type{typ} + return []string{typ.String()} } // In go1.10, sync.noCopy did not implement Locker. @@ -272,15 +325,15 @@ func lockPath(tpkg *types.Package, typ types.Type) typePath { if named, ok := typ.(*types.Named); ok && named.Obj().Name() == "noCopy" && named.Obj().Pkg().Path() == "sync" { - return []types.Type{typ} + return []string{typ.String()} } nfields := styp.NumFields() for i := 0; i < nfields; i++ { ftyp := styp.Field(i).Type() - subpath := lockPath(tpkg, ftyp) + subpath := lockPath(tpkg, ftyp, seenTParams) if subpath != nil { - return append(subpath, typ) + return append(subpath, typ.String()) } } diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ctrlflow/ctrlflow.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ctrlflow/ctrlflow.go index 51600ffc7e..73746d6f04 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ctrlflow/ctrlflow.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ctrlflow/ctrlflow.go @@ -187,7 +187,11 @@ func (c *CFGs) callMayReturn(call *ast.CallExpr) (r bool) { return false // panic never returns } - // Is this a static call? + // Is this a static call? Also includes static functions + // parameterized by a type. Such functions may or may not + // return depending on the parameter type, but in some + // cases the answer is definite. We let ctrlflow figure + // that out. fn := typeutil.StaticCallee(c.pass.TypesInfo, call) if fn == nil { return true // callee not statically known; be conservative diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/nilfunc/nilfunc.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/nilfunc/nilfunc.go index cd42c9897f..850f6f8fae 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/nilfunc/nilfunc.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/nilfunc/nilfunc.go @@ -14,6 +14,7 @@ import ( "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis/passes/inspect" "golang.org/x/tools/go/ast/inspector" + "golang.org/x/tools/internal/typeparams" ) const Doc = `check for useless comparisons between functions and nil @@ -59,6 +60,11 @@ func run(pass *analysis.Pass) (interface{}, error) { obj = pass.TypesInfo.Uses[v] case *ast.SelectorExpr: obj = pass.TypesInfo.Uses[v.Sel] + case *ast.IndexExpr, *typeparams.IndexListExpr: + // Check generic functions such as "f[T1,T2]". + if id, ok := typeparams.GetIndexExprData(v).X.(*ast.Ident); ok { + obj = pass.TypesInfo.Uses[id] + } default: return } diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go index 4169d30e4f..0206073578 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go @@ -452,8 +452,15 @@ func stringConstantArg(pass *analysis.Pass, call *ast.CallExpr, idx int) (string if idx >= len(call.Args) { return "", false } - arg := call.Args[idx] - lit := pass.TypesInfo.Types[arg].Value + return stringConstantExpr(pass, call.Args[idx]) +} + +// stringConstantExpr returns expression's string constant value. +// +// ("", false) is returned if expression isn't a string +// constant. +func stringConstantExpr(pass *analysis.Pass, expr ast.Expr) (string, bool) { + lit := pass.TypesInfo.Types[expr].Value if lit != nil && lit.Kind() == constant.String { return constant.StringVal(lit), true } @@ -872,8 +879,12 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, state *formatState) (o return } arg := call.Args[argNum] - if !matchArgType(pass, argInt, nil, arg) { - pass.ReportRangef(call, "%s format %s uses non-int %s as argument of *", state.name, state.format, analysisutil.Format(pass.Fset, arg)) + if reason, ok := matchArgType(pass, argInt, arg); !ok { + details := "" + if reason != "" { + details = " (" + reason + ")" + } + pass.ReportRangef(call, "%s format %s uses non-int %s%s as argument of *", state.name, state.format, analysisutil.Format(pass.Fset, arg), details) return false } } @@ -890,12 +901,16 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, state *formatState) (o pass.ReportRangef(call, "%s format %s arg %s is a func value, not called", state.name, state.format, analysisutil.Format(pass.Fset, arg)) return false } - if !matchArgType(pass, v.typ, nil, arg) { + if reason, ok := matchArgType(pass, v.typ, arg); !ok { typeString := "" if typ := pass.TypesInfo.Types[arg].Type; typ != nil { typeString = typ.String() } - pass.ReportRangef(call, "%s format %s has arg %s of wrong type %s", state.name, state.format, analysisutil.Format(pass.Fset, arg), typeString) + details := "" + if reason != "" { + details = " (" + reason + ")" + } + pass.ReportRangef(call, "%s format %s has arg %s of wrong type %s%s", state.name, state.format, analysisutil.Format(pass.Fset, arg), typeString, details) return false } if v.typ&argString != 0 && v.verb != 'T' && !bytes.Contains(state.flags, []byte{'#'}) { @@ -1053,10 +1068,10 @@ func checkPrint(pass *analysis.Pass, call *ast.CallExpr, fn *types.Func) { } arg := args[0] - if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { - // Ignore trailing % character in lit.Value. + if s, ok := stringConstantExpr(pass, arg); ok { + // Ignore trailing % character // The % in "abc 0.0%" couldn't be a formatting directive. - s := strings.TrimSuffix(lit.Value, `%"`) + s = strings.TrimSuffix(s, "%") if strings.Contains(s, "%") { m := printFormatRE.FindStringSubmatch(s) if m != nil { @@ -1067,9 +1082,8 @@ func checkPrint(pass *analysis.Pass, call *ast.CallExpr, fn *types.Func) { if strings.HasSuffix(fn.Name(), "ln") { // The last item, if a string, should not have a newline. arg = args[len(args)-1] - if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { - str, _ := strconv.Unquote(lit.Value) - if strings.HasSuffix(str, "\n") { + if s, ok := stringConstantExpr(pass, arg); ok { + if strings.HasSuffix(s, "\n") { pass.ReportRangef(call, "%s arg list ends with redundant newline", fn.FullName()) } } diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/types.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/types.go index 6a5fae44f4..81bf36e1ee 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/types.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/types.go @@ -5,45 +5,60 @@ package printf import ( + "fmt" "go/ast" "go/types" "golang.org/x/tools/go/analysis" - "golang.org/x/tools/go/analysis/passes/internal/analysisutil" + "golang.org/x/tools/internal/typeparams" ) var errorType = types.Universe.Lookup("error").Type().Underlying().(*types.Interface) -// matchArgType reports an error if printf verb t is not appropriate -// for operand arg. +// matchArgType reports an error if printf verb t is not appropriate for +// operand arg. // -// typ is used only for recursive calls; external callers must supply nil. -// -// (Recursion arises from the compound types {map,chan,slice} which -// may be printed with %d etc. if that is appropriate for their element -// types.) -func matchArgType(pass *analysis.Pass, t printfArgType, typ types.Type, arg ast.Expr) bool { - return matchArgTypeInternal(pass, t, typ, arg, make(map[types.Type]bool)) -} - -// matchArgTypeInternal is the internal version of matchArgType. It carries a map -// remembering what types are in progress so we don't recur when faced with recursive -// types or mutually recursive types. -func matchArgTypeInternal(pass *analysis.Pass, t printfArgType, typ types.Type, arg ast.Expr, inProgress map[types.Type]bool) bool { +// If arg is a type parameter, the verb t must be appropriate for every type in +// the type parameter type set. +func matchArgType(pass *analysis.Pass, t printfArgType, arg ast.Expr) (reason string, ok bool) { // %v, %T accept any argument type. if t == anyType { - return true + return "", true } + + typ := pass.TypesInfo.Types[arg].Type if typ == nil { - // external call - typ = pass.TypesInfo.Types[arg].Type - if typ == nil { - return true // probably a type check problem - } + return "", true // probably a type check problem } + m := &argMatcher{t: t, seen: make(map[types.Type]bool)} + ok = m.match(typ, true) + return m.reason, ok +} + +// argMatcher recursively matches types against the printfArgType t. +// +// To short-circuit recursion, it keeps track of types that have already been +// matched (or are in the process of being matched) via the seen map. Recursion +// arises from the compound types {map,chan,slice} which may be printed with %d +// etc. if that is appropriate for their element types, as well as from type +// parameters, which are expanded to the constituents of their type set. +// +// The reason field may be set to report the cause of the mismatch. +type argMatcher struct { + t printfArgType + seen map[types.Type]bool + reason string +} + +// match checks if typ matches m's printf arg type. If topLevel is true, typ is +// the actual type of the printf arg, for which special rules apply. As a +// special case, top level type parameters pass topLevel=true when checking for +// matches among the constituents of their type set, as type arguments will +// replace the type parameter at compile time. +func (m *argMatcher) match(typ types.Type, topLevel bool) bool { // %w accepts only errors. - if t == argError { + if m.t == argError { return types.ConvertibleTo(typ, errorType) } @@ -51,86 +66,153 @@ func matchArgTypeInternal(pass *analysis.Pass, t printfArgType, typ types.Type, if isFormatter(typ) { return true } + // If we can use a string, might arg (dynamically) implement the Stringer or Error interface? - if t&argString != 0 && isConvertibleToString(pass, typ) { + if m.t&argString != 0 && isConvertibleToString(typ) { + return true + } + + if typ, _ := typ.(*typeparams.TypeParam); typ != nil { + // Avoid infinite recursion through type parameters. + if m.seen[typ] { + return true + } + m.seen[typ] = true + terms, err := typeparams.StructuralTerms(typ) + if err != nil { + return true // invalid type (possibly an empty type set) + } + + if len(terms) == 0 { + // No restrictions on the underlying of typ. Type parameters implementing + // error, fmt.Formatter, or fmt.Stringer were handled above, and %v and + // %T was handled in matchType. We're about to check restrictions the + // underlying; if the underlying type is unrestricted there must be an + // element of the type set that violates one of the arg type checks + // below, so we can safely return false here. + + if m.t == anyType { // anyType must have already been handled. + panic("unexpected printfArgType") + } + return false + } + + // Only report a reason if typ is the argument type, otherwise it won't + // make sense. Note that it is not sufficient to check if topLevel == here, + // as type parameters can have a type set consisting of other type + // parameters. + reportReason := len(m.seen) == 1 + + for _, term := range terms { + if !m.match(term.Type(), topLevel) { + if reportReason { + if term.Tilde() { + m.reason = fmt.Sprintf("contains ~%s", term.Type()) + } else { + m.reason = fmt.Sprintf("contains %s", term.Type()) + } + } + return false + } + } return true } typ = typ.Underlying() - if inProgress[typ] { - // We're already looking at this type. The call that started it will take care of it. + if m.seen[typ] { + // We've already considered typ, or are in the process of considering it. + // In case we've already considered typ, it must have been valid (else we + // would have stopped matching). In case we're in the process of + // considering it, we must avoid infinite recursion. + // + // There are some pathological cases where returning true here is + // incorrect, for example `type R struct { F []R }`, but these are + // acceptable false negatives. return true } - inProgress[typ] = true + m.seen[typ] = true switch typ := typ.(type) { case *types.Signature: - return t == argPointer + return m.t == argPointer case *types.Map: - return t == argPointer || - // Recur: map[int]int matches %d. - (matchArgTypeInternal(pass, t, typ.Key(), arg, inProgress) && matchArgTypeInternal(pass, t, typ.Elem(), arg, inProgress)) + if m.t == argPointer { + return true + } + // Recur: map[int]int matches %d. + return m.match(typ.Key(), false) && m.match(typ.Elem(), false) case *types.Chan: - return t&argPointer != 0 + return m.t&argPointer != 0 case *types.Array: // Same as slice. - if types.Identical(typ.Elem().Underlying(), types.Typ[types.Byte]) && t&argString != 0 { + if types.Identical(typ.Elem().Underlying(), types.Typ[types.Byte]) && m.t&argString != 0 { return true // %s matches []byte } // Recur: []int matches %d. - return matchArgTypeInternal(pass, t, typ.Elem(), arg, inProgress) + return m.match(typ.Elem(), false) case *types.Slice: // Same as array. - if types.Identical(typ.Elem().Underlying(), types.Typ[types.Byte]) && t&argString != 0 { + if types.Identical(typ.Elem().Underlying(), types.Typ[types.Byte]) && m.t&argString != 0 { return true // %s matches []byte } - if t == argPointer { + if m.t == argPointer { return true // %p prints a slice's 0th element } // Recur: []int matches %d. But watch out for // type T []T // If the element is a pointer type (type T[]*T), it's handled fine by the Pointer case below. - return matchArgTypeInternal(pass, t, typ.Elem(), arg, inProgress) + return m.match(typ.Elem(), false) case *types.Pointer: // Ugly, but dealing with an edge case: a known pointer to an invalid type, // probably something from a failed import. - if typ.Elem().String() == "invalid type" { - if false { - pass.Reportf(arg.Pos(), "printf argument %v is pointer to invalid or unknown type", analysisutil.Format(pass.Fset, arg)) - } + if typ.Elem() == types.Typ[types.Invalid] { return true // special case } // If it's actually a pointer with %p, it prints as one. - if t == argPointer { + if m.t == argPointer { return true } under := typ.Elem().Underlying() switch under.(type) { + case *typeparams.TypeParam: + return true // We don't know whether the logic below applies. Give up. case *types.Struct: // see below case *types.Array: // see below case *types.Slice: // see below case *types.Map: // see below default: // Check whether the rest can print pointers. - return t&argPointer != 0 + return m.t&argPointer != 0 } - // If it's a top-level pointer to a struct, array, slice, or + // If it's a top-level pointer to a struct, array, slice, type param, or // map, that's equivalent in our analysis to whether we can // print the type being pointed to. Pointers in nested levels // are not supported to minimize fmt running into loops. - if len(inProgress) > 1 { + if !topLevel { return false } - return matchArgTypeInternal(pass, t, under, arg, inProgress) + return m.match(under, false) case *types.Struct: - return matchStructArgType(pass, t, typ, arg, inProgress) + // report whether all the elements of the struct match the expected type. For + // instance, with "%d" all the elements must be printable with the "%d" format. + for i := 0; i < typ.NumFields(); i++ { + typf := typ.Field(i) + if !m.match(typf.Type(), false) { + return false + } + if m.t&argString != 0 && !typf.Exported() && isConvertibleToString(typf.Type()) { + // Issue #17798: unexported Stringer or error cannot be properly formatted. + return false + } + } + return true case *types.Interface: // There's little we can do. @@ -142,7 +224,7 @@ func matchArgTypeInternal(pass *analysis.Pass, t printfArgType, typ types.Type, switch typ.Kind() { case types.UntypedBool, types.Bool: - return t&argBool != 0 + return m.t&argBool != 0 case types.UntypedInt, types.Int, @@ -156,35 +238,32 @@ func matchArgTypeInternal(pass *analysis.Pass, t printfArgType, typ types.Type, types.Uint32, types.Uint64, types.Uintptr: - return t&argInt != 0 + return m.t&argInt != 0 case types.UntypedFloat, types.Float32, types.Float64: - return t&argFloat != 0 + return m.t&argFloat != 0 case types.UntypedComplex, types.Complex64, types.Complex128: - return t&argComplex != 0 + return m.t&argComplex != 0 case types.UntypedString, types.String: - return t&argString != 0 + return m.t&argString != 0 case types.UnsafePointer: - return t&(argPointer|argInt) != 0 + return m.t&(argPointer|argInt) != 0 case types.UntypedRune: - return t&(argInt|argRune) != 0 + return m.t&(argInt|argRune) != 0 case types.UntypedNil: return false case types.Invalid: - if false { - pass.Reportf(arg.Pos(), "printf argument %v has invalid or unknown type", analysisutil.Format(pass.Fset, arg)) - } return true // Probably a type check problem. } panic("unreachable") @@ -193,7 +272,7 @@ func matchArgTypeInternal(pass *analysis.Pass, t printfArgType, typ types.Type, return false } -func isConvertibleToString(pass *analysis.Pass, typ types.Type) bool { +func isConvertibleToString(typ types.Type) bool { if bt, ok := typ.(*types.Basic); ok && bt.Kind() == types.UntypedNil { // We explicitly don't want untyped nil, which is // convertible to both of the interfaces below, as it @@ -228,19 +307,3 @@ func hasBasicType(pass *analysis.Pass, x ast.Expr, kind types.BasicKind) bool { b, ok := t.(*types.Basic) return ok && b.Kind() == kind } - -// matchStructArgType reports whether all the elements of the struct match the expected -// type. For instance, with "%d" all the elements must be printable with the "%d" format. -func matchStructArgType(pass *analysis.Pass, t printfArgType, typ *types.Struct, arg ast.Expr, inProgress map[types.Type]bool) bool { - for i := 0; i < typ.NumFields(); i++ { - typf := typ.Field(i) - if !matchArgTypeInternal(pass, t, typf.Type(), arg, inProgress) { - return false - } - if t&argString != 0 && !typf.Exported() && isConvertibleToString(pass, typf.Type()) { - // Issue #17798: unexported Stringer or error cannot be properly formatted. - return false - } - } - return true -} diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/shift/shift.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/shift/shift.go index 1f3df07ccd..640de28e05 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/shift/shift.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/shift/shift.go @@ -14,11 +14,13 @@ import ( "go/ast" "go/constant" "go/token" + "math" "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis/passes/inspect" "golang.org/x/tools/go/analysis/passes/internal/analysisutil" "golang.org/x/tools/go/ast/inspector" + "golang.org/x/tools/internal/typeparams" ) const Doc = "check for shifts that equal or exceed the width of the integer" @@ -93,9 +95,27 @@ func checkLongShift(pass *analysis.Pass, node ast.Node, x, y ast.Expr) { if t == nil { return } - size := 8 * pass.TypesSizes.Sizeof(t) - if amt >= size { + terms, err := typeparams.StructuralTerms(t) + if err != nil { + return // invalid type + } + sizes := make(map[int64]struct{}) + for _, term := range terms { + size := 8 * pass.TypesSizes.Sizeof(term.Type()) + sizes[size] = struct{}{} + } + minSize := int64(math.MaxInt64) + for size := range sizes { + if size < minSize { + minSize = size + } + } + if amt >= minSize { ident := analysisutil.Format(pass.Fset, x) - pass.ReportRangef(node, "%s (%d bits) too small for shift of %d", ident, size, amt) + qualifier := "" + if len(sizes) > 1 { + qualifier = "may be " + } + pass.ReportRangef(node, "%s (%s%d bits) too small for shift of %d", ident, qualifier, minSize, amt) } } diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go index 7a005901e8..92fd375f23 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go @@ -10,10 +10,12 @@ import ( "fmt" "go/ast" "go/types" + "strings" "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis/passes/inspect" "golang.org/x/tools/go/ast/inspector" + "golang.org/x/tools/internal/typeparams" ) const Doc = `check for string(int) conversions @@ -36,6 +38,35 @@ var Analyzer = &analysis.Analyzer{ Run: run, } +// describe returns a string describing the type typ contained within the type +// set of inType. If non-empty, inName is used as the name of inType (this is +// necessary so that we can use alias type names that may not be reachable from +// inType itself). +func describe(typ, inType types.Type, inName string) string { + name := inName + if typ != inType { + name = typeName(typ) + } + if name == "" { + return "" + } + + var parentheticals []string + if underName := typeName(typ.Underlying()); underName != "" && underName != name { + parentheticals = append(parentheticals, underName) + } + + if typ != inType && inName != "" && inName != name { + parentheticals = append(parentheticals, "in "+inName) + } + + if len(parentheticals) > 0 { + name += " (" + strings.Join(parentheticals, ", ") + ")" + } + + return name +} + func typeName(typ types.Type) string { if v, _ := typ.(interface{ Name() string }); v != nil { return v.Name() @@ -54,6 +85,11 @@ func run(pass *analysis.Pass) (interface{}, error) { inspect.Preorder(nodeFilter, func(n ast.Node) { call := n.(*ast.CallExpr) + if len(call.Args) != 1 { + return + } + arg := call.Args[0] + // Retrieve target type name. var tname *types.TypeName switch fun := call.Fun.(type) { @@ -65,60 +101,100 @@ func run(pass *analysis.Pass) (interface{}, error) { if tname == nil { return } - target := tname.Name() - // Check that target type T in T(v) has an underlying type of string. - T, _ := tname.Type().Underlying().(*types.Basic) - if T == nil || T.Kind() != types.String { - return + // In the conversion T(v) of a value v of type V to a target type T, we + // look for types T0 in the type set of T and V0 in the type set of V, such + // that V0->T0 is a problematic conversion. If T and V are not type + // parameters, this amounts to just checking if V->T is a problematic + // conversion. + + // First, find a type T0 in T that has an underlying type of string. + T := tname.Type() + tterms, err := typeparams.StructuralTerms(T) + if err != nil { + return // invalid type } - if s := T.Name(); target != s { - target += " (" + s + ")" + + var T0 types.Type // string type in the type set of T + + for _, term := range tterms { + u, _ := term.Type().Underlying().(*types.Basic) + if u != nil && u.Kind() == types.String { + T0 = term.Type() + break + } } - // Check that type V of v has an underlying integral type that is not byte or rune. - if len(call.Args) != 1 { + if T0 == nil { + // No target types have an underlying type of string. return } - v := call.Args[0] - vtyp := pass.TypesInfo.TypeOf(v) - V, _ := vtyp.Underlying().(*types.Basic) - if V == nil || V.Info()&types.IsInteger == 0 { - return + + // Next, find a type V0 in V that has an underlying integral type that is + // not byte or rune. + V := pass.TypesInfo.TypeOf(arg) + vterms, err := typeparams.StructuralTerms(V) + if err != nil { + return // invalid type } - switch V.Kind() { - case types.Byte, types.Rune, types.UntypedRune: - return + + var V0 types.Type // integral type in the type set of V + + for _, term := range vterms { + u, _ := term.Type().Underlying().(*types.Basic) + if u != nil && u.Info()&types.IsInteger != 0 { + switch u.Kind() { + case types.Byte, types.Rune, types.UntypedRune: + continue + } + V0 = term.Type() + break + } } - // Retrieve source type name. - source := typeName(vtyp) - if source == "" { + if V0 == nil { + // No source types are non-byte or rune integer types. return } - if s := V.Name(); source != s { - source += " (" + s + ")" + + convertibleToRune := true // if true, we can suggest a fix + for _, term := range vterms { + if !types.ConvertibleTo(term.Type(), types.Typ[types.Rune]) { + convertibleToRune = false + break + } + } + + target := describe(T0, T, tname.Name()) + source := describe(V0, V, typeName(V)) + + if target == "" || source == "" { + return // something went wrong } + diag := analysis.Diagnostic{ Pos: n.Pos(), Message: fmt.Sprintf("conversion from %s to %s yields a string of one rune, not a string of digits (did you mean fmt.Sprint(x)?)", source, target), - SuggestedFixes: []analysis.SuggestedFix{ + } + + if convertibleToRune { + diag.SuggestedFixes = []analysis.SuggestedFix{ { Message: "Did you mean to convert a rune to a string?", TextEdits: []analysis.TextEdit{ { - Pos: v.Pos(), - End: v.Pos(), + Pos: arg.Pos(), + End: arg.Pos(), NewText: []byte("rune("), }, { - Pos: v.End(), - End: v.End(), + Pos: arg.End(), + End: arg.End(), NewText: []byte(")"), }, }, }, - }, + } } pass.Report(diag) }) diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine/testinggoroutine.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine/testinggoroutine.go index ce05a56cca..3d4bd49085 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine/testinggoroutine.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine/testinggoroutine.go @@ -11,6 +11,7 @@ import ( "golang.org/x/tools/go/analysis/passes/inspect" "golang.org/x/tools/go/analysis/passes/internal/analysisutil" "golang.org/x/tools/go/ast/inspector" + "golang.org/x/tools/internal/typeparams" ) const Doc = `report calls to (*testing.T).Fatal from goroutines started by a test. @@ -124,16 +125,30 @@ func typeIsTestingDotTOrB(expr ast.Expr) (string, bool) { // function literals declared in the same function, and // static calls within the same package are supported. func goStmtFun(goStmt *ast.GoStmt) ast.Node { - switch goStmt.Call.Fun.(type) { - case *ast.Ident: - id := goStmt.Call.Fun.(*ast.Ident) - // TODO(cuonglm): improve this once golang/go#48141 resolved. + switch fun := goStmt.Call.Fun.(type) { + case *ast.IndexExpr, *typeparams.IndexListExpr: + ix := typeparams.GetIndexExprData(fun) + if ix == nil { + break + } + id, _ := ix.X.(*ast.Ident) + if id == nil { + break + } if id.Obj == nil { break } if funDecl, ok := id.Obj.Decl.(ast.Node); ok { return funDecl } + case *ast.Ident: + // TODO(cuonglm): improve this once golang/go#48141 resolved. + if fun.Obj == nil { + break + } + if funDecl, ok := fun.Obj.Decl.(ast.Node); ok { + return funDecl + } case *ast.FuncLit: return goStmt.Call.Fun } diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go index 570ad5c209..2c87882496 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go @@ -16,6 +16,7 @@ import ( "unicode/utf8" "golang.org/x/tools/go/analysis" + "golang.org/x/tools/internal/typeparams" ) const Doc = `check for common mistaken usages of tests and examples @@ -170,6 +171,9 @@ func checkExampleName(pass *analysis.Pass, fn *ast.FuncDecl) { if results := fn.Type.Results; results != nil && len(results.List) != 0 { pass.Reportf(fn.Pos(), "%s should return nothing", fnName) } + if tparams := typeparams.ForFuncType(fn.Type); tparams != nil && len(tparams.List) > 0 { + pass.Reportf(fn.Pos(), "%s should not have type params", fnName) + } if fnName == "Example" { // Nothing more to do. @@ -236,6 +240,12 @@ func checkTest(pass *analysis.Pass, fn *ast.FuncDecl, prefix string) { return } + if tparams := typeparams.ForFuncType(fn.Type); tparams != nil && len(tparams.List) > 0 { + // Note: cmd/go/internal/load also errors about TestXXX and BenchmarkXXX functions with type parameters. + // We have currently decided to also warn before compilation/package loading. This can help users in IDEs. + pass.Reportf(fn.Pos(), "%s has type parameters: it will not be run by go test as a %sXXX function", fn.Name.Name, prefix) + } + if !isTestSuffix(fn.Name.Name[len(prefix):]) { pass.Reportf(fn.Pos(), "%s has malformed name: first letter after '%s' must not be lowercase", fn.Name.Name, prefix) } diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go index bececee7e9..fd94508f88 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go @@ -17,6 +17,7 @@ import ( "golang.org/x/tools/go/analysis/passes/inspect" "golang.org/x/tools/go/analysis/passes/internal/analysisutil" "golang.org/x/tools/go/ast/inspector" + "golang.org/x/tools/internal/typeparams" ) // TODO(adonovan): make this analysis modular: export a mustUseResult @@ -70,6 +71,11 @@ func run(pass *analysis.Pass) (interface{}, error) { return // a conversion, not a call } + index := typeparams.GetIndexExprData(fun) + if index != nil { + fun = index.X // If this is generic function or method call, skip the instantiation arguments + } + selector, ok := fun.(*ast.SelectorExpr) if !ok { return // neither a method call nor a qualified ident diff --git a/src/cmd/vendor/golang.org/x/tools/go/types/typeutil/callee.go b/src/cmd/vendor/golang.org/x/tools/go/types/typeutil/callee.go index 38f596daf9..2b8960332d 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/types/typeutil/callee.go +++ b/src/cmd/vendor/golang.org/x/tools/go/types/typeutil/callee.go @@ -9,13 +9,30 @@ import ( "go/types" "golang.org/x/tools/go/ast/astutil" + "golang.org/x/tools/internal/typeparams" ) // Callee returns the named target of a function call, if any: // a function, method, builtin, or variable. +// +// Functions and methods may potentially have type parameters. func Callee(info *types.Info, call *ast.CallExpr) types.Object { + fun := astutil.Unparen(call.Fun) + + // Look through type instantiation if necessary. + isInstance := false + switch fun.(type) { + case *ast.IndexExpr, *typeparams.IndexListExpr: + // When extracting the callee from an *IndexExpr, we need to check that + // it is a *types.Func and not a *types.Var. + // Example: Don't match a slice m within the expression `m[0]()`. + isInstance = true + ix := typeparams.GetIndexExprData(fun) + fun = ix.X + } + var obj types.Object - switch fun := astutil.Unparen(call.Fun).(type) { + switch fun := fun.(type) { case *ast.Ident: obj = info.Uses[fun] // type, var, builtin, or declared func case *ast.SelectorExpr: @@ -28,11 +45,18 @@ func Callee(info *types.Info, call *ast.CallExpr) types.Object { if _, ok := obj.(*types.TypeName); ok { return nil // T(x) is a conversion, not a call } + // A Func is required to match instantiations. + if _, ok := obj.(*types.Func); isInstance && !ok { + return nil // Was not a Func. + } return obj } -// StaticCallee returns the target (function or method) of a static -// function call, if any. It returns nil for calls to builtins. +// StaticCallee returns the target (function or method) of a static function +// call, if any. It returns nil for calls to builtins. +// +// Note: for calls of instantiated functions and methods, StaticCallee returns +// the corresponding generic function or method on the generic type. func StaticCallee(info *types.Info, call *ast.CallExpr) *types.Func { if f, ok := Callee(info, call).(*types.Func); ok && !interfaceMethod(f) { return f diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 2ac22b951b..3806f7171c 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -28,7 +28,7 @@ golang.org/x/arch/x86/x86asm ## explicit; go 1.17 golang.org/x/crypto/ed25519 golang.org/x/crypto/ed25519/internal/edwards25519 -# golang.org/x/mod v0.5.1-0.20210913215816-37dd6891021a +# golang.org/x/mod v0.6.0-dev.0.20210913215816-37dd6891021a ## explicit; go 1.17 golang.org/x/mod/internal/lazyregexp golang.org/x/mod/modfile @@ -51,7 +51,7 @@ golang.org/x/sys/windows # golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 ## explicit; go 1.17 golang.org/x/term -# golang.org/x/tools v0.1.8-0.20211025211149-f916b54a1784 +# golang.org/x/tools v0.1.8-0.20211109164901-e9000123914f ## explicit; go 1.17 golang.org/x/tools/cover golang.org/x/tools/go/analysis -- GitLab From a0963164e86356092074473049cca7bff52afbce Mon Sep 17 00:00:00 2001 From: David Chase Date: Tue, 9 Nov 2021 11:47:49 -0500 Subject: [PATCH 2078/2500] cmd/compile: add line number test for #49436 This enhances the existing line number test to allow a specific -gcflags (e.g., -G=3) and to permit ignoring duplicate line numbers (which is arguably a bug, but not THIS bug, and it lowers the risk of a flaky test). Limited to Linux/Darwin and amd64/arm64, also tests with "unified" mangling. And, using these new powers, adds a test. Updates #49436. Change-Id: I09c82e6a08d53edd5a752522a827e872d3e16e0b Reviewed-on: https://go-review.googlesource.com/c/go/+/362714 Trust: David Chase Run-TryBot: David Chase TryBot-Result: Go Bot Reviewed-by: Keith Randall --- .../compile/internal/ssa/debug_lines_test.go | 49 +++++++++++++++---- .../compile/internal/ssa/testdata/pushback.go | 30 ++++++++++++ 2 files changed, 70 insertions(+), 9 deletions(-) create mode 100644 src/cmd/compile/internal/ssa/testdata/pushback.go diff --git a/src/cmd/compile/internal/ssa/debug_lines_test.go b/src/cmd/compile/internal/ssa/debug_lines_test.go index da04e5b04e..0df56f5d4b 100644 --- a/src/cmd/compile/internal/ssa/debug_lines_test.go +++ b/src/cmd/compile/internal/ssa/debug_lines_test.go @@ -8,10 +8,10 @@ import ( "bufio" "bytes" "flag" + "internal/buildcfg" "runtime" "sort" - // "flag" "fmt" "internal/testenv" "io/ioutil" @@ -45,7 +45,7 @@ func testGoArch() string { return *testGoArchFlag } -func TestDebugLines(t *testing.T) { +func TestDebugLinesSayHi(t *testing.T) { // This test is potentially fragile, the goal is that debugging should step properly through "sayhi" // If the blocks are reordered in a way that changes the statement order but execution flows correctly, // then rearrange the expected numbers. Register abi and not-register-abi also have different sequences, @@ -53,16 +53,35 @@ func TestDebugLines(t *testing.T) { switch testGoArch() { case "arm64", "amd64": // register ABI - testDebugLines(t, "sayhi.go", "sayhi", []int{8, 9, 10, 11}) + testDebugLines(t, "-N -l", "sayhi.go", "sayhi", []int{8, 9, 10, 11}, false) case "arm", "386": // probably not register ABI for a while - testDebugLines(t, "sayhi.go", "sayhi", []int{9, 10, 11}) + testDebugLines(t, "-N -l", "sayhi.go", "sayhi", []int{9, 10, 11}, false) default: // expect ppc64le and riscv will pick up register ABI soonish, not sure about others t.Skip("skipped for many architectures, also changes w/ register ABI") } } +func TestDebugLinesPushback(t *testing.T) { + if runtime.GOOS != "linux" && runtime.GOOS != "darwin" { // in particular, it could be windows. + t.Skip("this test depends on creating a file with a wonky name, only works for sure on Linux and Darwin") + } + + switch testGoArch() { + default: + t.Skip("skipped for many architectures") + + case "arm64", "amd64": // register ABI + fn := "(*List[go.shape.int_0]).PushBack" + if buildcfg.Experiment.Unified { + // Unified mangles differently + fn = "(*List[int]).PushBack" + } + testDebugLines(t, "-N -l -G=3", "pushback.go", fn, []int{17, 18, 19, 20, 21, 22, 24}, true) + } +} + func TestInlineLines(t *testing.T) { if runtime.GOARCH != "amd64" && *testGoArchFlag == "" { // As of september 2021, works for everything except mips64, but still potentially fragile @@ -181,8 +200,8 @@ func testInlineStack(t *testing.T, file, function string, wantStacks [][]int) { // then verifies that the statement-marked lines in that file are the same as those in wantStmts // These files must all be short because this is super-fragile. // "go build" is run in a temporary directory that is normally deleted, unless -test.v -func testDebugLines(t *testing.T, file, function string, wantStmts []int) { - dumpBytes := compileAndDump(t, file, function, "-N -l") +func testDebugLines(t *testing.T, gcflags, file, function string, wantStmts []int, ignoreRepeats bool) { + dumpBytes := compileAndDump(t, file, function, gcflags) dump := bufio.NewScanner(bytes.NewReader(dumpBytes)) var gotStmts []int dumpLineNum := 0 @@ -201,8 +220,20 @@ func testDebugLines(t *testing.T, file, function string, wantStmts []int) { gotStmts = append(gotStmts, int(stmt)) } } - if !reflect.DeepEqual(wantStmts, gotStmts) { - t.Errorf("wanted stmts %v but got %v", wantStmts, gotStmts) - } + if ignoreRepeats { // remove repeats from gotStmts + newGotStmts := []int{gotStmts[0]} + for _, x := range gotStmts { + if x != newGotStmts[len(newGotStmts)-1] { + newGotStmts = append(newGotStmts, x) + } + } + if !reflect.DeepEqual(wantStmts, newGotStmts) { + t.Errorf("wanted stmts %v but got %v (with repeats still in: %v)", wantStmts, newGotStmts, gotStmts) + } + } else { + if !reflect.DeepEqual(wantStmts, gotStmts) { + t.Errorf("wanted stmts %v but got %v", wantStmts, gotStmts) + } + } } diff --git a/src/cmd/compile/internal/ssa/testdata/pushback.go b/src/cmd/compile/internal/ssa/testdata/pushback.go new file mode 100644 index 0000000000..754e6cbb23 --- /dev/null +++ b/src/cmd/compile/internal/ssa/testdata/pushback.go @@ -0,0 +1,30 @@ +package main + +type Node struct { + Circular bool +} + +type ExtNode[V any] struct { + v V + Node +} + +type List[V any] struct { + root *ExtNode[V] + len int +} + +func (list *List[V]) PushBack(arg V) { + if list.len == 0 { + list.root = &ExtNode[V]{v: arg} + list.root.Circular = true + list.len++ + return + } + list.len++ +} + +func main() { + var v List[int] + v.PushBack(1) +} -- GitLab From f981a9f7ded779749dca199e0893aa08529b52ec Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 9 Nov 2021 14:10:37 -0500 Subject: [PATCH 2079/2500] go/types: clearer object string for type parameters This is a port of CL 361401 to go/types. Change-Id: I5b1c7cf1d7a819b2902c304f884492ec02c7eaa1 Reviewed-on: https://go-review.googlesource.com/c/go/+/362737 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/go/types/object.go | 21 ++++++--- src/go/types/object_test.go | 78 +++++++++++++++++++++++++++++++++ src/go/types/typestring_test.go | 7 ++- 3 files changed, 98 insertions(+), 8 deletions(-) diff --git a/src/go/types/object.go b/src/go/types/object.go index a8bd62a04e..e7a4425643 100644 --- a/src/go/types/object.go +++ b/src/go/types/object.go @@ -412,6 +412,9 @@ func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) { case *TypeName: tname = obj buf.WriteString("type") + if isTypeParam(typ) { + buf.WriteString(" parameter") + } case *Var: if obj.isField { @@ -457,18 +460,22 @@ func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) { } if tname != nil { - // We have a type object: Don't print anything more for - // basic types since there's no more information (names - // are the same; see also comment in TypeName.IsAlias). - if _, ok := typ.(*Basic); ok { + switch t := typ.(type) { + case *Basic: + // Don't print anything more for basic types since there's + // no more information. return - } - if named, _ := typ.(*Named); named != nil && named.TypeParams().Len() > 0 { - newTypeWriter(buf, qf).tParamList(named.TypeParams().list()) + case *Named: + if t.TypeParams().Len() > 0 { + newTypeWriter(buf, qf).tParamList(t.TypeParams().list()) + } } if tname.IsAlias() { buf.WriteString(" =") + } else if t, _ := typ.(*TypeParam); t != nil { + typ = t.bound } else { + // TODO(gri) should this be fromRHS for *Named? typ = under(typ) } } diff --git a/src/go/types/object_test.go b/src/go/types/object_test.go index e9a4bd6dbf..46b92a4006 100644 --- a/src/go/types/object_test.go +++ b/src/go/types/object_test.go @@ -8,6 +8,8 @@ import ( "go/ast" "go/parser" "go/token" + "internal/testenv" + "strings" "testing" . "go/types" @@ -89,3 +91,79 @@ func TestEmbeddedMethod(t *testing.T) { t.Fatalf("%s (%p) != %s (%p)", orig, orig, embed, embed) } } + +var testObjects = []struct { + src string + obj string + want string +}{ + {"import \"io\"; var r io.Reader", "r", "var p.r io.Reader"}, + + {"const c = 1.2", "c", "const p.c untyped float"}, + {"const c float64 = 3.14", "c", "const p.c float64"}, + + {"type t struct{f int}", "t", "type p.t struct{f int}"}, + {"type t func(int)", "t", "type p.t func(int)"}, + {"type t[P any] struct{f P}", "t", "type p.t[P interface{}] struct{f P}"}, + {"type t[P any] struct{f P}", "t.P", "type parameter P interface{}"}, + {"type C interface{m()}; type t[P C] struct{}", "t.P", "type parameter P p.C"}, + + {"type t = struct{f int}", "t", "type p.t = struct{f int}"}, + {"type t = func(int)", "t", "type p.t = func(int)"}, + + {"var v int", "v", "var p.v int"}, + + {"func f(int) string", "f", "func p.f(int) string"}, + {"func g[P any](x P){}", "g", "func p.g[P interface{}](x P)"}, + {"func g[P interface{~int}](x P){}", "g.P", "type parameter P interface{~int}"}, +} + +func TestObjectString(t *testing.T) { + testenv.MustHaveGoBuild(t) + + for _, test := range testObjects { + src := "package p; " + test.src + pkg, err := makePkg(src) + if err != nil { + t.Errorf("%s: %s", src, err) + continue + } + + names := strings.Split(test.obj, ".") + if len(names) != 1 && len(names) != 2 { + t.Errorf("%s: invalid object path %s", test.src, test.obj) + continue + } + obj := pkg.Scope().Lookup(names[0]) + if obj == nil { + t.Errorf("%s: %s not found", test.src, names[0]) + continue + } + if len(names) == 2 { + if typ, ok := obj.Type().(interface{ TypeParams() *TypeParamList }); ok { + obj = lookupTypeParamObj(typ.TypeParams(), names[1]) + if obj == nil { + t.Errorf("%s: %s not found", test.src, test.obj) + continue + } + } else { + t.Errorf("%s: %s has no type parameters", test.src, names[0]) + continue + } + } + + if got := obj.String(); got != test.want { + t.Errorf("%s: got %s, want %s", test.src, got, test.want) + } + } +} + +func lookupTypeParamObj(list *TypeParamList, name string) Object { + for i := 0; i < list.Len(); i++ { + tpar := list.At(i) + if tpar.Obj().Name() == name { + return tpar.Obj() + } + } + return nil +} diff --git a/src/go/types/typestring_test.go b/src/go/types/typestring_test.go index 5718ffcc6c..14ab9b6002 100644 --- a/src/go/types/typestring_test.go +++ b/src/go/types/typestring_test.go @@ -133,7 +133,12 @@ func TestTypeString(t *testing.T) { t.Errorf("%s: %s", src, err) continue } - typ := pkg.Scope().Lookup("T").Type().Underlying() + obj := pkg.Scope().Lookup("T") + if obj == nil { + t.Errorf("%s: T not found", test.src) + continue + } + typ := obj.Type().Underlying() if got := typ.String(); got != test.str { t.Errorf("%s: got %s, want %s", test.src, got, test.str) } -- GitLab From b93220c9ca1935c56c01afc1d72d063f1e026f15 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 12 Oct 2021 16:50:35 -0700 Subject: [PATCH 2080/2500] encoding/xml: add generic encoding test Fixes #48521 Change-Id: Id8402bcff243c0ab19e4ec0b138b9af8c111f88d Reviewed-on: https://go-review.googlesource.com/c/go/+/355492 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/encoding/xml/marshal_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/encoding/xml/marshal_test.go b/src/encoding/xml/marshal_test.go index d2e5137afd..cb95905f5b 100644 --- a/src/encoding/xml/marshal_test.go +++ b/src/encoding/xml/marshal_test.go @@ -524,6 +524,10 @@ type IfaceAny struct { T2 T2 } +type Generic[T any] struct { + X T +} + var ( nameAttr = "Sarah" ageAttr = uint(12) @@ -641,6 +645,7 @@ var marshalTests = []struct { {Value: &Particle{HasMass: true}, ExpectXML: `true`}, {Value: &Departure{When: ParseTime("2013-01-09T00:15:00-09:00")}, ExpectXML: `2013-01-09T00:15:00-09:00`}, {Value: atomValue, ExpectXML: atomXML}, + {Value: &Generic[int]{1}, ExpectXML: `1`}, { Value: &Ship{ Name: "Heart of Gold", -- GitLab From 805b4d56364ec40f29fc7efba5de537d14036c6a Mon Sep 17 00:00:00 2001 From: Manlio Perillo Date: Sun, 16 May 2021 19:52:37 +0200 Subject: [PATCH 2081/2500] cmd/dist: wait for exit in bgwait after a fatal error Currently, when a command scheduled by bgrun fails, bgwait returns to the caller even in case the fatal error was detected. In case of a syntax error in one of the standard packages, as an example, the runInstall function will try to read the generated archive file, only to fail since the file does not exist. Since the runInstall function is called in a goroutine, cmd/dist will continue to report errors until all background goroutines are done. Update the bgwait function to wait until program termination in case of a fatal error, since returning to the caller (with an error, as an example) will cause cmd/dist to report an additional error during the next build phase. Fixes #45410 Change-Id: If89976abad70f8d6ec79b2a5a1f2306e9c034c5a Reviewed-on: https://go-review.googlesource.com/c/go/+/320311 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Dmitri Shuralyov --- src/cmd/dist/util.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cmd/dist/util.go b/src/cmd/dist/util.go index 28fe5e1d8d..8856f467d5 100644 --- a/src/cmd/dist/util.go +++ b/src/cmd/dist/util.go @@ -172,6 +172,9 @@ func bgwait(wg *sync.WaitGroup) { select { case <-done: case <-dying: + // Don't return to the caller, to avoid reporting additional errors + // to the user. + select {} } } -- GitLab From a65a095ca423c21bdd53a6a8300b501b88d60137 Mon Sep 17 00:00:00 2001 From: Manlio Perillo Date: Sat, 24 Apr 2021 16:19:07 +0200 Subject: [PATCH 2082/2500] cmd/go/internal/bug: remove duplicate code Change-Id: I8a14b2fbb44f7ed1ea126cf27adc447f33fdf6f2 Reviewed-on: https://go-review.googlesource.com/c/go/+/313170 Reviewed-by: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Trust: Cherry Mui --- src/cmd/go/internal/bug/bug.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cmd/go/internal/bug/bug.go b/src/cmd/go/internal/bug/bug.go index a81ca7d8c3..702dc2a14a 100644 --- a/src/cmd/go/internal/bug/bug.go +++ b/src/cmd/go/internal/bug/bug.go @@ -106,8 +106,9 @@ func printGoEnv(w io.Writer) { } func printGoDetails(w io.Writer) { - printCmdOut(w, "GOROOT/bin/go version: ", filepath.Join(runtime.GOROOT(), "bin/go"), "version") - printCmdOut(w, "GOROOT/bin/go tool compile -V: ", filepath.Join(runtime.GOROOT(), "bin/go"), "tool", "compile", "-V") + gocmd := filepath.Join(runtime.GOROOT(), "bin/go") + printCmdOut(w, "GOROOT/bin/go version: ", gocmd, "version") + printCmdOut(w, "GOROOT/bin/go tool compile -V: ", gocmd, "tool", "compile", "-V") } func printOSDetails(w io.Writer) { -- GitLab From 4aa0746f6abae7dc112883e79f93993a430bd340 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Tue, 19 Oct 2021 14:05:29 -0400 Subject: [PATCH 2083/2500] cmd/go: add workspace pruning mode [ this is a roll-forward of golang.org/cl/357169 with minor changes to fix the cmd/go/internal/modload tests: because they don't run the go command, some initialization isn't run on the test and modroots is empty in cases it can't be when the full command setup is done. So directly check for workFilePath != "" instead of calling inWorkspaceMode which checks that Init is called first, and check that modRoots is non empty when calling mustGetSingleMainModule.] This change corrects a bug in the handling of module loading of workspaces. Namely, there is an assumption by the module pruning code that if a root module is selected then the packages of that module can be resolved without loading the whole module graph. This is not true in workspace mode because two workspace modules can require different versions of a dependency. Worse, one workspace module can directly require a depencency that is transitively required by another workspace module, changing the version of that module loaded in the fully expanded graph. To correct this, a new 'workspace' pruning mode is added where the roots are the workspace modules themselves, satisfying the assumption made by the module pruning logic. The rest of this change accounts for the new pruning mode where it's used and correctly sets the requirements in this pruning mode. Change-Id: I8bdf4b30f669c1ded0ed8a5dd202ac8d1939bbbd Reviewed-on: https://go-review.googlesource.com/c/go/+/362754 Trust: Michael Matloob Run-TryBot: Michael Matloob Reviewed-by: Bryan C. Mills TryBot-Result: Go Bot --- src/cmd/go/internal/modload/buildlist.go | 86 ++++++++++++++++------ src/cmd/go/internal/modload/import_test.go | 2 +- src/cmd/go/internal/modload/init.go | 44 +++++------ src/cmd/go/internal/modload/load.go | 24 +++++- src/cmd/go/internal/modload/modfile.go | 14 +++- src/cmd/go/testdata/script/work_prune.txt | 2 +- 6 files changed, 122 insertions(+), 50 deletions(-) diff --git a/src/cmd/go/internal/modload/buildlist.go b/src/cmd/go/internal/modload/buildlist.go index 27cab0b9c8..0cb4a88fcb 100644 --- a/src/cmd/go/internal/modload/buildlist.go +++ b/src/cmd/go/internal/modload/buildlist.go @@ -38,11 +38,17 @@ type Requirements struct { // If pruned, the graph includes only the root modules, the explicit // requirements of those root modules, and the transitive requirements of only // the root modules that do not support pruning. + // + // If workspace, the graph includes only the workspace modules, the explicit + // requirements of the workspace modules, and the transitive requirements of + // the workspace modules that do not support pruning. pruning modPruning - // rootModules is the set of module versions explicitly required by the main - // modules, sorted and capped to length. It may contain duplicates, and may - // contain multiple versions for a given module path. + // rootModules is the set of root modules of the graph, sorted and capped to + // length. It may contain duplicates, and may contain multiple versions for a + // given module path. The root modules of the groph are the set of main + // modules in workspace mode, and the main module's direct requirements + // outside workspace mode. rootModules []module.Version maxRootVersion map[string]string @@ -99,6 +105,19 @@ var requirements *Requirements // If vendoring is in effect, the caller must invoke initVendor on the returned // *Requirements before any other method. func newRequirements(pruning modPruning, rootModules []module.Version, direct map[string]bool) *Requirements { + if pruning == workspace { + return &Requirements{ + pruning: pruning, + rootModules: capVersionSlice(rootModules), + maxRootVersion: nil, + direct: direct, + } + } + + if workFilePath != "" && pruning != workspace { + panic("in workspace mode, but pruning is not workspace in newRequirements") + } + for i, m := range rootModules { if m.Version == "" && MainModules.Contains(m.Path) { panic(fmt.Sprintf("newRequirements called with untrimmed build list: rootModules[%v] is a main module", i)) @@ -291,13 +310,11 @@ func readModGraph(ctx context.Context, pruning modPruning, roots []module.Versio g: mvs.NewGraph(cmpVersion, MainModules.Versions()), } ) - for _, m := range MainModules.Versions() { - // Require all roots from all main modules. - _ = TODOWorkspaces("This flattens a level of the module graph, adding the dependencies " + - "of all main modules to a single requirements struct, and losing the information of which " + - "main module required which requirement. Rework the requirements struct and change this" + - "to reflect the structure of the main modules.") - mg.g.Require(m, roots) + if pruning != workspace { + if inWorkspaceMode() { + panic("pruning is not workspace in workspace mode") + } + mg.g.Require(MainModules.mustGetSingleMainModule(), roots) } var ( @@ -352,9 +369,13 @@ func readModGraph(ctx context.Context, pruning modPruning, roots []module.Versio // are sufficient to build the packages it contains. We must load its full // transitive dependency graph to be sure that we see all relevant // dependencies. - if pruning == unpruned || summary.pruning == unpruned { + if pruning != pruned || summary.pruning == unpruned { + nextPruning := summary.pruning + if pruning == unpruned { + nextPruning = unpruned + } for _, r := range summary.require { - enqueue(r, unpruned) + enqueue(r, nextPruning) } } }) @@ -424,12 +445,15 @@ func (mg *ModuleGraph) findError() error { } func (mg *ModuleGraph) allRootsSelected() bool { - for _, mm := range MainModules.Versions() { - roots, _ := mg.g.RequiredBy(mm) - for _, m := range roots { - if mg.Selected(m.Path) != m.Version { - return false - } + var roots []module.Version + if inWorkspaceMode() { + roots = MainModules.Versions() + } else { + roots, _ = mg.g.RequiredBy(MainModules.mustGetSingleMainModule()) + } + for _, m := range roots { + if mg.Selected(m.Path) != m.Version { + return false } } return true @@ -576,10 +600,29 @@ func tidyRoots(ctx context.Context, rs *Requirements, pkgs []*loadPkg) (*Require } func updateRoots(ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version, rootsImported bool) (*Requirements, error) { - if rs.pruning == unpruned { + switch rs.pruning { + case unpruned: return updateUnprunedRoots(ctx, direct, rs, add) + case pruned: + return updatePrunedRoots(ctx, direct, rs, pkgs, add, rootsImported) + case workspace: + return updateWorkspaceRoots(ctx, rs, add) + default: + panic(fmt.Sprintf("unsupported pruning mode: %v", rs.pruning)) + } +} + +func updateWorkspaceRoots(ctx context.Context, rs *Requirements, add []module.Version) (*Requirements, error) { + if len(add) != 0 { + // add should be empty in workspace mode because a non-empty add slice means + // that there are missing roots in the current pruning mode or that the + // pruning mode is being changed. But the pruning mode should always be + // 'workspace' in workspace mode and the set of roots in workspace mode is + // always complete because it's the set of workspace modules, which can't + // be edited by loading. + panic("add is not empty") } - return updatePrunedRoots(ctx, direct, rs, pkgs, add, rootsImported) + return rs, nil } // tidyPrunedRoots returns a minimal set of root requirements that maintains the @@ -1156,7 +1199,6 @@ func updateUnprunedRoots(ctx context.Context, direct map[string]bool, rs *Requir } } - // TODO(matloob): Make roots into a map. var roots []module.Version for _, mainModule := range MainModules.Versions() { min, err := mvs.Req(mainModule, rootPaths, &mvsReqs{roots: keep}) @@ -1182,6 +1224,8 @@ func updateUnprunedRoots(ctx context.Context, direct map[string]bool, rs *Requir func convertPruning(ctx context.Context, rs *Requirements, pruning modPruning) (*Requirements, error) { if rs.pruning == pruning { return rs, nil + } else if rs.pruning == workspace || pruning == workspace { + panic("attempthing to convert to/from workspace pruning and another pruning type") } if pruning == unpruned { diff --git a/src/cmd/go/internal/modload/import_test.go b/src/cmd/go/internal/modload/import_test.go index 11310489ad..65a889ec52 100644 --- a/src/cmd/go/internal/modload/import_test.go +++ b/src/cmd/go/internal/modload/import_test.go @@ -69,7 +69,7 @@ func TestQueryImport(t *testing.T) { RootMode = NoRoot ctx := context.Background() - rs := newRequirements(unpruned, nil, nil) + rs := LoadModFile(ctx) for _, tt := range importTests { t.Run(strings.ReplaceAll(tt.path, "/", "_"), func(t *testing.T) { diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 9aef5a7c33..512c9ebfbd 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -704,7 +704,7 @@ func LoadModFile(ctx context.Context) *Requirements { } } - if MainModules.Index(mainModule).goVersionV == "" { + if MainModules.Index(mainModule).goVersionV == "" && rs.pruning != workspace { // TODO(#45551): Do something more principled instead of checking // cfg.CmdName directly here. if cfg.BuildMod == "mod" && cfg.CmdName != "mod graph" && cfg.CmdName != "mod why" { @@ -987,29 +987,29 @@ func makeMainModules(ms []module.Version, rootDirs []string, modFiles []*modfile // requirementsFromModFiles returns the set of non-excluded requirements from // the global modFile. func requirementsFromModFiles(ctx context.Context, modFiles []*modfile.File) *Requirements { - rootCap := 0 - for i := range modFiles { - rootCap += len(modFiles[i].Require) - } - roots := make([]module.Version, 0, rootCap) - mPathCount := make(map[string]int) - for _, m := range MainModules.Versions() { - mPathCount[m.Path] = 1 - } + var roots []module.Version direct := map[string]bool{} - for _, modFile := range modFiles { - requirement: + var pruning modPruning + if inWorkspaceMode() { + pruning = workspace + roots = make([]module.Version, len(MainModules.Versions())) + copy(roots, MainModules.Versions()) + } else { + pruning = pruningForGoVersion(MainModules.GoVersion()) + if len(modFiles) != 1 { + panic(fmt.Errorf("requirementsFromModFiles called with %v modfiles outside workspace mode", len(modFiles))) + } + modFile := modFiles[0] + roots = make([]module.Version, 0, len(modFile.Require)) + mm := MainModules.mustGetSingleMainModule() for _, r := range modFile.Require { - // TODO(#45713): Maybe join - for _, mainModule := range MainModules.Versions() { - if index := MainModules.Index(mainModule); index != nil && index.exclude[r.Mod] { - if cfg.BuildMod == "mod" { - fmt.Fprintf(os.Stderr, "go: dropping requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version) - } else { - fmt.Fprintf(os.Stderr, "go: ignoring requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version) - } - continue requirement + if index := MainModules.Index(mm); index != nil && index.exclude[r.Mod] { + if cfg.BuildMod == "mod" { + fmt.Fprintf(os.Stderr, "go: dropping requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version) + } else { + fmt.Fprintf(os.Stderr, "go: ignoring requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version) } + continue } roots = append(roots, r.Mod) @@ -1019,7 +1019,7 @@ func requirementsFromModFiles(ctx context.Context, modFiles []*modfile.File) *Re } } module.Sort(roots) - rs := newRequirements(pruningForGoVersion(MainModules.GoVersion()), roots, direct) + rs := newRequirements(pruning, roots, direct) return rs } diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index 845bf2f8a2..83fcafead3 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -1004,7 +1004,11 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader { } var err error - ld.requirements, err = convertPruning(ctx, ld.requirements, pruningForGoVersion(ld.GoVersion)) + desiredPruning := pruningForGoVersion(ld.GoVersion) + if ld.requirements.pruning == workspace { + desiredPruning = workspace + } + ld.requirements, err = convertPruning(ctx, ld.requirements, desiredPruning) if err != nil { ld.errorf("go: %v\n", err) } @@ -1246,6 +1250,24 @@ func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err err continue } + if inWorkspaceMode() { + // In workspace mode / workspace pruning mode, the roots are the main modules + // rather than the main module's direct dependencies. The check below on the selected + // roots does not apply. + if mg, err := rs.Graph(ctx); err != nil { + return false, err + } else if _, ok := mg.RequiredBy(dep.mod); !ok { + // dep.mod is not an explicit dependency, but needs to be. + // See comment on error returned below. + pkg.err = &DirectImportFromImplicitDependencyError{ + ImporterPath: pkg.path, + ImportedPath: dep.path, + Module: dep.mod, + } + } + continue + } + if pkg.err == nil && cfg.BuildMod != "mod" { if v, ok := rs.rootSelected(dep.mod.Path); !ok || v != dep.mod.Version { // dep.mod is not an explicit dependency, but needs to be. diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index a7e92222a1..40e6ed787d 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -118,8 +118,9 @@ type requireMeta struct { type modPruning uint8 const ( - pruned modPruning = iota // transitive dependencies of modules at go 1.17 and higher are pruned out - unpruned // no transitive dependencies are pruned out + pruned modPruning = iota // transitive dependencies of modules at go 1.17 and higher are pruned out + unpruned // no transitive dependencies are pruned out + workspace // pruned to the union of modules in the workspace ) func pruningForGoVersion(goVersion string) modPruning { @@ -554,7 +555,7 @@ type retraction struct { // // The caller must not modify the returned summary. func goModSummary(m module.Version) (*modFileSummary, error) { - if m.Version == "" && MainModules.Contains(m.Path) { + if m.Version == "" && !inWorkspaceMode() && MainModules.Contains(m.Path) { panic("internal error: goModSummary called on a main module") } @@ -718,9 +719,14 @@ var rawGoModSummaryCache par.Cache // module.Version → rawGoModSummary result func rawGoModData(m module.Version) (name string, data []byte, err error) { if m.Version == "" { // m is a replacement module with only a file path. + dir := m.Path if !filepath.IsAbs(dir) { - dir = filepath.Join(replaceRelativeTo(), dir) + if inWorkspaceMode() && MainModules.Contains(m.Path) { + dir = MainModules.ModRoot(m) + } else { + dir = filepath.Join(replaceRelativeTo(), dir) + } } name = filepath.Join(dir, "go.mod") if gomodActual, ok := fsys.OverlayPath(name); ok { diff --git a/src/cmd/go/testdata/script/work_prune.txt b/src/cmd/go/testdata/script/work_prune.txt index f0fb073c4b..00c3e10663 100644 --- a/src/cmd/go/testdata/script/work_prune.txt +++ b/src/cmd/go/testdata/script/work_prune.txt @@ -14,7 +14,7 @@ # TODO(#48331): We currently load the wrong version of q. Fix this. go list -m -f '{{.Version}}' example.com/q -stdout '^v1.0.0$' # TODO(#48331): This should be 1.1.0. Fix this. +stdout '^v1.1.0$' -- go.work -- go 1.18 -- GitLab From cb908f1d4dd24dad17105022df7b0e96ac1d6988 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 9 Nov 2021 14:56:39 -0500 Subject: [PATCH 2084/2500] go/types: don't return an array type with invalid length In preparation for porting CL 361412, fix a discrepancy in go/types, where [-1]T is returned for an array type with invalid length. Change-Id: Ia32f5b66c9c561ccf0c32af1922fc4690c66dbc3 Reviewed-on: https://go-review.googlesource.com/c/go/+/362738 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/api_test.go | 2 +- src/go/types/typexpr.go | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index 807bffbff6..3e10be5985 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -342,7 +342,7 @@ func TestTypesInfo(t *testing.T) { {broken + `x2; func _() { var a, b string; type x struct {f string}; z := &x{f: a; f: b;}}`, `b`, `string`}, {broken + `x3; var x = panic("");`, `panic`, `func(interface{})`}, {`package x4; func _() { panic("") }`, `panic`, `func(interface{})`}, - {broken + `x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string][-1]int`}, + {broken + `x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string]invalid type`}, // parameterized functions {genericPkg + `p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[T interface{}](T)`}, diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index e1d942a5c6..cc2bd62209 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -271,18 +271,20 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) { return check.definedType(e.X, def) case *ast.ArrayType: - if e.Len != nil { - typ := new(Array) + if e.Len == nil { + typ := new(Slice) def.setUnderlying(typ) - typ.len = check.arrayLength(e.Len) typ.elem = check.varType(e.Elt) return typ } - typ := new(Slice) + typ := new(Array) def.setUnderlying(typ) + typ.len = check.arrayLength(e.Len) typ.elem = check.varType(e.Elt) - return typ + if typ.len >= 0 { + return typ + } case *ast.Ellipsis: // dots are handled explicitly where they are legal -- GitLab From 1c86beeadfc7a370048ad58f76b1b60b5bcd06ee Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 9 Nov 2021 14:20:11 -0500 Subject: [PATCH 2085/2500] go/types: report error for incomplete struct composite literal type This is a port of CL 361412 to go/types. Change-Id: Ie5bccc7faba7ca9230e712f867b27ca9dcddba79 Reviewed-on: https://go-review.googlesource.com/c/go/+/362739 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/expr.go | 6 +++ src/go/types/struct.go | 14 +++++- src/go/types/subst.go | 4 +- .../types/testdata/fixedbugs/issue49276.go2 | 46 +++++++++++++++++++ 4 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue49276.go2 diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 83022ed660..224185b6a9 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -1230,6 +1230,12 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { switch utyp := structure(base).(type) { case *Struct: + // Prevent crash if the struct referred to is not yet set up. + // See analogous comment for *Array. + if utyp.fields == nil { + check.error(e, _Todo, "illegal cycle in type declaration") + goto Error + } if len(e.Elts) == 0 { break } diff --git a/src/go/types/struct.go b/src/go/types/struct.go index 442c7a66e3..60640ac578 100644 --- a/src/go/types/struct.go +++ b/src/go/types/struct.go @@ -15,7 +15,7 @@ import ( // A Struct represents a struct type. type Struct struct { - fields []*Var + fields []*Var // fields != nil indicates the struct is set up (possibly with len(fields) == 0) tags []string // field tags; nil if there are no tags } @@ -33,7 +33,9 @@ func NewStruct(fields []*Var, tags []string) *Struct { if len(tags) > len(fields) { panic("more tags than fields") } - return &Struct{fields: fields, tags: tags} + s := &Struct{fields: fields, tags: tags} + s.markComplete() + return s } // NumFields returns the number of fields in the struct (including blank and embedded fields). @@ -56,9 +58,16 @@ func (t *Struct) String() string { return TypeString(t, nil) } // ---------------------------------------------------------------------------- // Implementation +func (s *Struct) markComplete() { + if s.fields == nil { + s.fields = make([]*Var, 0) + } +} + func (check *Checker) structType(styp *Struct, e *ast.StructType) { list := e.Fields if list == nil { + styp.markComplete() return } @@ -161,6 +170,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) { styp.fields = fields styp.tags = tags + styp.markComplete() } func embeddedFieldIdent(e ast.Expr) *ast.Ident { diff --git a/src/go/types/subst.go b/src/go/types/subst.go index f0b79f60c6..1fac82fe8a 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -91,7 +91,9 @@ func (subst *subster) typ(typ Type) Type { case *Struct: if fields, copied := subst.varList(t.fields); copied { - return &Struct{fields: fields, tags: t.tags} + s := &Struct{fields: fields, tags: t.tags} + s.markComplete() + return s } case *Pointer: diff --git a/src/go/types/testdata/fixedbugs/issue49276.go2 b/src/go/types/testdata/fixedbugs/issue49276.go2 new file mode 100644 index 0000000000..8839087b50 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue49276.go2 @@ -0,0 +1,46 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +import "unsafe" + +type S /* ERROR illegal cycle in declaration of S */ struct { + _ [unsafe.Sizeof(s)]byte +} + +var s S + +// Since f is a pointer, this case could be valid. +// But it's pathological and not worth the expense. +type T struct { + f *[unsafe.Sizeof(T /* ERROR illegal cycle in type declaration */ {})]int +} + +// a mutually recursive case using unsafe.Sizeof +type ( + A1 struct { + _ [unsafe.Sizeof(B1{})]int + } + + B1 struct { + _ [unsafe.Sizeof(A1 /* ERROR illegal cycle in type declaration */ {})]int + } +) + +// a mutually recursive case using len +type ( + A2 struct { + f [len(B2{}.f)]int + } + + B2 struct { + f [len(A2 /* ERROR illegal cycle in type declaration */ {}.f)]int + } +) + +// test case from issue +type a struct { + _ [42 - unsafe.Sizeof(a /* ERROR illegal cycle in type declaration */ {})]byte +} -- GitLab From 795cb333d94ee7f5632500f3e2ae98012b8d73e6 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Mon, 25 Oct 2021 16:19:11 -0400 Subject: [PATCH 2086/2500] cmd/go: add go work sync command Change-Id: I09b22f05035700e1ed90bd066ee8f77c3913286a Reviewed-on: https://go-review.googlesource.com/c/go/+/358540 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/alldocs.go | 10 ++ src/cmd/go/internal/modload/buildlist.go | 13 +- src/cmd/go/internal/modload/init.go | 12 +- src/cmd/go/internal/modload/load.go | 21 +++- src/cmd/go/internal/workcmd/sync.go | 101 +++++++++++++++ src/cmd/go/internal/workcmd/work.go | 1 + src/cmd/go/testdata/script/work_sync.txt | 119 ++++++++++++++++++ .../work_sync_irrelevant_dependency.txt | 119 ++++++++++++++++++ .../script/work_sync_relevant_dependency.txt | 106 ++++++++++++++++ 9 files changed, 490 insertions(+), 12 deletions(-) create mode 100644 src/cmd/go/internal/workcmd/sync.go create mode 100644 src/cmd/go/testdata/script/work_sync.txt create mode 100644 src/cmd/go/testdata/script/work_sync_irrelevant_dependency.txt create mode 100644 src/cmd/go/testdata/script/work_sync_relevant_dependency.txt diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index d8ebc8d61d..81d2f7021d 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -1382,6 +1382,7 @@ // // edit edit go.work from tools or scripts // init initialize workspace file +// sync sync workspace build list to modules // // Use "go help work " for more information about a command. // @@ -1473,6 +1474,15 @@ // more information. // // +// Sync workspace build list to modules +// +// Usage: +// +// go work sync [moddirs] +// +// go work sync +// +// // Compile and run Go program // // Usage: diff --git a/src/cmd/go/internal/modload/buildlist.go b/src/cmd/go/internal/modload/buildlist.go index 0cb4a88fcb..f4c1311af5 100644 --- a/src/cmd/go/internal/modload/buildlist.go +++ b/src/cmd/go/internal/modload/buildlist.go @@ -614,12 +614,13 @@ func updateRoots(ctx context.Context, direct map[string]bool, rs *Requirements, func updateWorkspaceRoots(ctx context.Context, rs *Requirements, add []module.Version) (*Requirements, error) { if len(add) != 0 { - // add should be empty in workspace mode because a non-empty add slice means - // that there are missing roots in the current pruning mode or that the - // pruning mode is being changed. But the pruning mode should always be - // 'workspace' in workspace mode and the set of roots in workspace mode is - // always complete because it's the set of workspace modules, which can't - // be edited by loading. + // add should be empty in workspace mode because workspace mode implies + // -mod=readonly, which in turn implies no new requirements. The code path + // that would result in add being non-empty returns an error before it + // reaches this point: The set of modules to add comes from + // resolveMissingImports, which in turn resolves each package by calling + // queryImport. But queryImport explicitly checks for -mod=readonly, and + // return an error. panic("add is not empty") } return rs, nil diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 512c9ebfbd..a6e49c6c71 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -73,6 +73,16 @@ var ( gopath string ) +// EnterModule resets MainModules and requirements to refer to just this one module. +func EnterModule(ctx context.Context, enterModroot string) { + MainModules = nil // reset MainModules + requirements = nil + workFilePath = "" // Force module mode + + modRoots = []string{enterModroot} + LoadModFile(ctx) +} + // Variable set in InitWorkfile var ( // Set to the path to the go.work file, or "" if workspace mode is disabled. @@ -1040,7 +1050,7 @@ func setDefaultBuildMod() { // to modload functions instead of relying on an implicit setting // based on command name. switch cfg.CmdName { - case "get", "mod download", "mod init", "mod tidy": + case "get", "mod download", "mod init", "mod tidy", "work sync": // These commands are intended to update go.mod and go.sum. cfg.BuildMod = "mod" return diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index 83fcafead3..27bbfb7832 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -231,6 +231,9 @@ type PackageOpts struct { // SilenceUnmatchedWarnings suppresses the warnings normally emitted for // patterns that did not match any packages. SilenceUnmatchedWarnings bool + + // Resolve the query against this module. + MainModule module.Version } // LoadPackages identifies the set of packages matching the given patterns and @@ -256,7 +259,11 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma case m.IsLocal(): // Evaluate list of file system directories on first iteration. if m.Dirs == nil { - matchLocalDirs(ctx, m, rs) + matchModRoots := modRoots + if opts.MainModule != (module.Version{}) { + matchModRoots = []string{MainModules.ModRoot(opts.MainModule)} + } + matchLocalDirs(ctx, matchModRoots, m, rs) } // Make a copy of the directory list and translate to import paths. @@ -309,7 +316,11 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma // The initial roots are the packages in the main module. // loadFromRoots will expand that to "all". m.Errs = m.Errs[:0] - matchPackages(ctx, m, opts.Tags, omitStd, MainModules.Versions()) + matchModules := MainModules.Versions() + if opts.MainModule != (module.Version{}) { + matchModules = []module.Version{opts.MainModule} + } + matchPackages(ctx, m, opts.Tags, omitStd, matchModules) } else { // Starting with the packages in the main module, // enumerate the full list of "all". @@ -441,7 +452,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma // matchLocalDirs is like m.MatchDirs, but tries to avoid scanning directories // outside of the standard library and active modules. -func matchLocalDirs(ctx context.Context, m *search.Match, rs *Requirements) { +func matchLocalDirs(ctx context.Context, modRoots []string, m *search.Match, rs *Requirements) { if !m.IsLocal() { panic(fmt.Sprintf("internal error: resolveLocalDirs on non-local pattern %s", m.Pattern())) } @@ -460,8 +471,8 @@ func matchLocalDirs(ctx context.Context, m *search.Match, rs *Requirements) { modRoot := findModuleRoot(absDir) found := false - for _, mod := range MainModules.Versions() { - if MainModules.ModRoot(mod) == modRoot { + for _, mainModuleRoot := range modRoots { + if mainModuleRoot == modRoot { found = true break } diff --git a/src/cmd/go/internal/workcmd/sync.go b/src/cmd/go/internal/workcmd/sync.go new file mode 100644 index 0000000000..2723013bf8 --- /dev/null +++ b/src/cmd/go/internal/workcmd/sync.go @@ -0,0 +1,101 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// go work sync + +package workcmd + +import ( + "cmd/go/internal/base" + "cmd/go/internal/imports" + "cmd/go/internal/modload" + "context" + + "golang.org/x/mod/module" +) + +var _ = modload.TODOWorkspaces("Add more documentation below. Though this is" + + "enough for those trying workspaces out, there should be more through" + + "documentation if the proposal is accepted and released.") + +var cmdSync = &base.Command{ + UsageLine: "go work sync [moddirs]", + Short: "sync workspace build list to modules", + Long: `go work sync`, + Run: runSync, +} + +func init() { + base.AddModCommonFlags(&cmdSync.Flag) + base.AddWorkfileFlag(&cmdSync.Flag) +} + +func runSync(ctx context.Context, cmd *base.Command, args []string) { + modload.InitWorkfile() + + modload.ForceUseModules = true + + workGraph := modload.LoadModGraph(ctx, "") + _ = workGraph + mustSelectFor := map[module.Version][]module.Version{} + + mms := modload.MainModules + + opts := modload.PackageOpts{ + Tags: imports.AnyTags(), + VendorModulesInGOROOTSrc: true, + ResolveMissingImports: false, + LoadTests: true, + AllowErrors: true, + SilencePackageErrors: true, + SilenceUnmatchedWarnings: true, + } + for _, m := range mms.Versions() { + opts.MainModule = m + _, pkgs := modload.LoadPackages(ctx, opts, "all") + opts.MainModule = module.Version{} // reset + + var ( + mustSelect []module.Version + inMustSelect = map[module.Version]bool{} + ) + for _, pkg := range pkgs { + if r := modload.PackageModule(pkg); r.Version != "" && !inMustSelect[r] { + // r has a known version, so force that version. + mustSelect = append(mustSelect, r) + inMustSelect[r] = true + } + } + module.Sort(mustSelect) // ensure determinism + mustSelectFor[m] = mustSelect + } + + for _, m := range mms.Versions() { + // Use EnterModule to reset the global state in modload to be in + // single-module mode using the modroot of m. + modload.EnterModule(ctx, mms.ModRoot(m)) + + // Edit the build list in the same way that 'go get' would if we + // requested the relevant module versions explicitly. + changed, err := modload.EditBuildList(ctx, nil, mustSelectFor[m]) + if err != nil { + base.Errorf("go: %v", err) + } + if !changed { + continue + } + + modload.LoadPackages(ctx, modload.PackageOpts{ + Tags: imports.AnyTags(), + VendorModulesInGOROOTSrc: true, + ResolveMissingImports: false, + LoadTests: true, + AllowErrors: true, + SilencePackageErrors: true, + Tidy: true, + SilenceUnmatchedWarnings: true, + }, "all") + modload.WriteGoMod(ctx) + } +} diff --git a/src/cmd/go/internal/workcmd/work.go b/src/cmd/go/internal/workcmd/work.go index 2e7f68b675..dc1164fb77 100644 --- a/src/cmd/go/internal/workcmd/work.go +++ b/src/cmd/go/internal/workcmd/work.go @@ -24,5 +24,6 @@ which workspaces are a part. Commands: []*base.Command{ cmdEdit, cmdInit, + cmdSync, }, } diff --git a/src/cmd/go/testdata/script/work_sync.txt b/src/cmd/go/testdata/script/work_sync.txt new file mode 100644 index 0000000000..16ad8c8cfa --- /dev/null +++ b/src/cmd/go/testdata/script/work_sync.txt @@ -0,0 +1,119 @@ +go work sync +cmp a/go.mod a/want_go.mod +cmp b/go.mod b/want_go.mod + +-- go.work -- +go 1.18 + +directory ( + ./a + ./b +) + +-- a/go.mod -- +go 1.18 + +module example.com/a + +require ( + example.com/p v1.0.0 + example.com/q v1.1.0 + example.com/r v1.0.0 +) + +replace ( + example.com/p => ../p + example.com/q => ../q + example.com/r => ../r +) +-- a/want_go.mod -- +go 1.18 + +module example.com/a + +require ( + example.com/p v1.1.0 + example.com/q v1.1.0 +) + +replace ( + example.com/p => ../p + example.com/q => ../q + example.com/r => ../r +) +-- a/a.go -- +package a + +import ( + "example.com/p" + "example.com/q" +) + +func Foo() { + p.P() + q.Q() +} +-- b/go.mod -- +go 1.18 + +module example.com/b + +require ( + example.com/p v1.1.0 + example.com/q v1.0.0 +) + +replace ( + example.com/p => ../p + example.com/q => ../q +) +-- b/want_go.mod -- +go 1.18 + +module example.com/b + +require ( + example.com/p v1.1.0 + example.com/q v1.1.0 +) + +replace ( + example.com/p => ../p + example.com/q => ../q +) +-- b/b.go -- +package b + +import ( + "example.com/p" + "example.com/q" +) + +func Foo() { + p.P() + q.Q() +} +-- p/go.mod -- +go 1.18 + +module example.com/p +-- p/p.go -- +package p + +func P() {} +-- q/go.mod -- +go 1.18 + +module example.com/q +-- q/q.go -- +package q + +func Q() {} +-- r/go.mod -- +go 1.18 + +module example.com/r +-- r/q.go -- +package r + +func R() {} \ No newline at end of file diff --git a/src/cmd/go/testdata/script/work_sync_irrelevant_dependency.txt b/src/cmd/go/testdata/script/work_sync_irrelevant_dependency.txt new file mode 100644 index 0000000000..bbb8579b4f --- /dev/null +++ b/src/cmd/go/testdata/script/work_sync_irrelevant_dependency.txt @@ -0,0 +1,119 @@ +# Test of go work sync in a workspace in which some dependency needed by `a` +# appears at a lower version in the build list of `b`, but is not needed at all +# by `b` (so it should not be upgraded within b). +# +# a -> p 1.1 +# b -> q 1.0 -(through a test dependency)-> p 1.0 +go work sync +cmp a/go.mod a/want_go.mod +cmp b/go.mod b/want_go.mod + +-- go.work -- +go 1.18 + +directory ( + ./a + ./b +) + +-- a/go.mod -- +go 1.18 + +module example.com/a + +require ( + example.com/p v1.1.0 +) + +replace ( + example.com/p => ../p +) +-- a/want_go.mod -- +go 1.18 + +module example.com/a + +require ( + example.com/p v1.1.0 +) + +replace ( + example.com/p => ../p +) +-- a/a.go -- +package a + +import ( + "example.com/p" +) + +func Foo() { + p.P() +} +-- b/go.mod -- +go 1.18 + +module example.com/b + +require ( + example.com/q v1.0.0 +) + +replace ( + example.com/q => ../q +) +-- b/want_go.mod -- +go 1.18 + +module example.com/b + +require ( + example.com/q v1.0.0 +) + +replace ( + example.com/q => ../q +) +-- b/b.go -- +package b + +import ( + "example.com/q" +) + +func Foo() { + q.Q() +} +-- p/go.mod -- +go 1.18 + +module example.com/p +-- p/p.go -- +package p + +func P() {} +-- q/go.mod -- +go 1.18 + +module example.com/q + +require ( + example.com/p v1.0.0 +) + +replace ( + example.com/p => ../p +) +-- q/q.go -- +package q + +func Q() { +} +-- q/q_test.go -- +package q + +import example.com/p + +func TestQ(t *testing.T) { + p.P() +} \ No newline at end of file diff --git a/src/cmd/go/testdata/script/work_sync_relevant_dependency.txt b/src/cmd/go/testdata/script/work_sync_relevant_dependency.txt new file mode 100644 index 0000000000..e95ac26707 --- /dev/null +++ b/src/cmd/go/testdata/script/work_sync_relevant_dependency.txt @@ -0,0 +1,106 @@ +# Test of go work sync in a workspace in which some dependency in the build +# list of 'b' (but not otherwise needed by `b`, so not seen when lazy loading +# occurs) actually is relevant to `a`. +# +# a -> p 1.0 +# b -> q 1.1 -> p 1.1 +go work sync +cmp a/go.mod a/want_go.mod +cmp b/go.mod b/want_go.mod + +-- go.work -- +go 1.18 + +directory ( + ./a + ./b +) + +-- a/go.mod -- +go 1.18 + +module example.com/a + +require ( + example.com/p v1.0.0 +) + +replace ( + example.com/p => ../p +) +-- a/want_go.mod -- +go 1.18 + +module example.com/a + +require example.com/p v1.1.0 + +replace example.com/p => ../p +-- a/a.go -- +package a + +import ( + "example.com/p" +) + +func Foo() { + p.P() +} +-- b/go.mod -- +go 1.18 + +module example.com/b + +require ( + example.com/q v1.1.0 +) + +replace ( + example.com/q => ../q +) +-- b/want_go.mod -- +go 1.18 + +module example.com/b + +require ( + example.com/q v1.1.0 +) + +replace ( + example.com/q => ../q +) +-- b/b.go -- +package b + +import ( + "example.com/q" +) + +func Foo() { + q.Q() +} +-- p/go.mod -- +go 1.18 + +module example.com/p +-- p/p.go -- +package p + +func P() {} +-- q/go.mod -- +go 1.18 + +module example.com/q + +require example.com/p v1.1.0 + +replace example.com/p => ../p +-- q/q.go -- +package q + +import example.com/p + +func Q() { + p.P() +} -- GitLab From 578ada410de8065dbca46bca08a5993d1307f423 Mon Sep 17 00:00:00 2001 From: Illirgway Date: Mon, 5 Jul 2021 11:22:03 +0000 Subject: [PATCH 2087/2500] mime: keep parsing after trailing semicolon Fixes #46323 Change-Id: Ibd624b1aaa15f907b7eb965b4eaec61018a45486 GitHub-Last-Rev: 7ad670b088144a2a09860dd990c53dea75c0d40f GitHub-Pull-Request: golang/go#47029 Reviewed-on: https://go-review.googlesource.com/c/go/+/332509 Trust: Ian Lance Taylor Trust: Damien Neil Reviewed-by: Damien Neil --- src/mime/mediatype.go | 2 +- src/mime/mediatype_test.go | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/mime/mediatype.go b/src/mime/mediatype.go index 9456570cf1..6c1b095065 100644 --- a/src/mime/mediatype.go +++ b/src/mime/mediatype.go @@ -163,7 +163,7 @@ func ParseMediaType(v string) (mediatype string, params map[string]string, err e if strings.TrimSpace(rest) == ";" { // Ignore trailing semicolons. // Not an error. - return + break } // Parse error. return mediatype, nil, ErrInvalidMediaParameter diff --git a/src/mime/mediatype_test.go b/src/mime/mediatype_test.go index e91ff38d68..079c080db7 100644 --- a/src/mime/mediatype_test.go +++ b/src/mime/mediatype_test.go @@ -42,7 +42,7 @@ func TestConsumeValue(t *testing.T) { {`"My \" value"end`, "My \" value", "end"}, {`"\" rest`, "", `"\" rest`}, {`"C:\dev\go\robots.txt"`, `C:\dev\go\robots.txt`, ""}, - {`"C:\新建文件件\中文第二次测试.mp4"`, `C:\新建文件件\中文第二次测试.mp4`, ""}, + {`"C:\新建文件夹\中文第二次测试.mp4"`, `C:\新建文件夹\中文第二次测试.mp4`, ""}, } for _, test := range tests { value, rest := consumeValue(test[0]) @@ -394,10 +394,21 @@ func TestParseMediaType(t *testing.T) { // Empty string used to be mishandled. {`foo; bar=""`, "foo", m("bar", "")}, - // Microsoft browers in intranet mode do not think they need to escape \ in file name. + // Microsoft browsers in intranet mode do not think they need to escape \ in file name. {`form-data; name="file"; filename="C:\dev\go\robots.txt"`, "form-data", m("name", "file", "filename", `C:\dev\go\robots.txt`)}, - {`form-data; name="file"; filename="C:\新建文件件\中文第二次测试.mp4"`, "form-data", m("name", "file", "filename", `C:\新建文件件\中文第二次测试.mp4`)}, + {`form-data; name="file"; filename="C:\新建文件夹\中文第二次测试.mp4"`, "form-data", m("name", "file", "filename", `C:\新建文件夹\中文第二次测试.mp4`)}, + + // issue #46323 (https://github.com/golang/go/issues/46323) + { + // example from rfc2231-p.3 (https://datatracker.ietf.org/doc/html/rfc2231) + `message/external-body; access-type=URL; + URL*0="ftp://"; + URL*1="cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar";`, // <-- trailing semicolon + `message/external-body`, + m("access-type", "URL", "url", "ftp://cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar"), + }, } + for _, test := range tests { mt, params, err := ParseMediaType(test.in) if err != nil { -- GitLab From f5f94340910421baea624ca08e5f51343515cae8 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 9 Nov 2021 16:41:01 -0500 Subject: [PATCH 2088/2500] go/types: remove most asX converters (cleanup) This is a port of CL 362118 to go/types, which is itself a roll-forward of CL 362254, containing a bugfix. Change-Id: I20067c7adf56bf64fe9ad080d998a7aefbdc1053 Reviewed-on: https://go-review.googlesource.com/c/go/+/362617 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/assignments.go | 2 +- src/go/types/builtins.go | 8 ++++---- src/go/types/call.go | 2 +- src/go/types/context.go | 3 +++ src/go/types/conversions.go | 21 ++++++++++---------- src/go/types/expr.go | 6 +++--- src/go/types/index.go | 8 ++++---- src/go/types/lookup.go | 9 ++++----- src/go/types/predicates.go | 5 +++-- src/go/types/sizes.go | 2 +- src/go/types/type.go | 39 +------------------------------------ src/go/types/typestring.go | 2 +- src/go/types/typexpr.go | 2 +- 13 files changed, 38 insertions(+), 71 deletions(-) diff --git a/src/go/types/assignments.go b/src/go/types/assignments.go index 2810133a1f..923bd43b49 100644 --- a/src/go/types/assignments.go +++ b/src/go/types/assignments.go @@ -71,7 +71,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { } // A generic (non-instantiated) function value cannot be assigned to a variable. - if sig := asSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { + if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 { check.errorf(x, _Todo, "cannot use generic function %s without instantiation in %s", x, context) } diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 577a71fd60..4d3ff26b14 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -299,7 +299,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // (applyTypeFunc never calls f with a type parameter) f := func(typ Type) Type { assert(asTypeParam(typ) == nil) - if t := asBasic(typ); t != nil { + if t, _ := under(typ).(*Basic); t != nil { switch t.kind { case Float32: return Typ[Complex64] @@ -423,7 +423,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // (applyTypeFunc never calls f with a type parameter) f := func(typ Type) Type { assert(asTypeParam(typ) == nil) - if t := asBasic(typ); t != nil { + if t, _ := under(typ).(*Basic); t != nil { switch t.kind { case Complex64: return Typ[Float32] @@ -713,7 +713,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b return } - typ := asPointer(x.typ) + typ, _ := under(x.typ).(*Pointer) if typ == nil { check.invalidArg(x, _InvalidUnsafeSlice, "%s is not a pointer", x) return @@ -893,7 +893,7 @@ func makeSig(res Type, args ...Type) *Signature { // otherwise it returns typ. func arrayPtrDeref(typ Type) Type { if p, ok := typ.(*Pointer); ok { - if a := asArray(p.base); a != nil { + if a, _ := under(p.base).(*Array); a != nil { return a } } diff --git a/src/go/types/call.go b/src/go/types/call.go index a7024f5f9c..890a2c7c5a 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -141,7 +141,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { check.errorf(call.Args[0], _BadDotDotDotSyntax, "invalid use of ... in conversion to %s", T) break } - if t := asInterface(T); t != nil { + if t, _ := under(T).(*Interface); t != nil { if !t.IsMethodSet() { check.errorf(call, _Todo, "cannot use interface %s in conversion (contains specific type constraints or is comparable)", T) break diff --git a/src/go/types/context.go b/src/go/types/context.go index 99baad8d0f..7caf631b57 100644 --- a/src/go/types/context.go +++ b/src/go/types/context.go @@ -40,6 +40,9 @@ func (ctxt *Context) typeHash(typ Type, targs []Type) string { var buf bytes.Buffer h := newTypeHasher(&buf, ctxt) + // Caution: don't use asNamed here. TypeHash may be called for unexpanded + // types. We don't need anything other than name and type arguments below, + // which do not require expansion. if named, _ := typ.(*Named); named != nil && len(targs) > 0 { // Don't use WriteType because we need to use the provided targs // and not any targs that might already be with the *Named type. diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go index f73e6a0964..26bebd4ade 100644 --- a/src/go/types/conversions.go +++ b/src/go/types/conversions.go @@ -17,7 +17,7 @@ func (check *Checker) conversion(x *operand, T Type) { constArg := x.mode == constant_ constConvertibleTo := func(T Type, val *constant.Value) bool { - switch t := asBasic(T); { + switch t, _ := under(T).(*Basic); { case t == nil: // nothing to do case representableConst(x.val, check, t, val): @@ -170,9 +170,9 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { // "V is a slice, T is a pointer-to-array type, // and the slice and array types have identical element types." - if s := asSlice(V); s != nil { - if p := asPointer(T); p != nil { - if a := asArray(p.Elem()); a != nil { + if s, _ := under(V).(*Slice); s != nil { + if p, _ := under(T).(*Pointer); p != nil { + if a, _ := under(p.Elem()).(*Array); a != nil { if Identical(s.Elem(), a.Elem()) { if check == nil || check.allowVersion(check.pkg, 1, 17) { return true @@ -254,26 +254,27 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { // use the toT convenience converters in the predicates below. func isUintptr(typ Type) bool { - t := asBasic(typ) + t, _ := under(typ).(*Basic) return t != nil && t.kind == Uintptr } func isUnsafePointer(typ Type) bool { - // TODO(gri): Is this asBasic(typ) instead of typ.(*Basic) correct? + // TODO(gri): Is this under(typ).(*Basic) instead of typ.(*Basic) correct? // (The former calls under(), while the latter doesn't.) // The spec does not say so, but gc claims it is. See also // issue 6326. - t := asBasic(typ) + t, _ := under(typ).(*Basic) return t != nil && t.kind == UnsafePointer } func isPointer(typ Type) bool { - return asPointer(typ) != nil + _, ok := under(typ).(*Pointer) + return ok } func isBytesOrRunes(typ Type) bool { - if s := asSlice(typ); s != nil { - t := asBasic(s.elem) + if s, _ := under(typ).(*Slice); s != nil { + t, _ := under(s.elem).(*Basic) return t != nil && (t.kind == Byte || t.kind == Rune) } return false diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 224185b6a9..138eb2f521 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -103,7 +103,7 @@ func (check *Checker) overflow(x *operand, op token.Token, opPos token.Pos) { // x.typ cannot be a type parameter (type // parameters cannot be constant types). if isTyped(x.typ) { - check.representable(x, asBasic(x.typ)) + check.representable(x, under(x.typ).(*Basic)) return } @@ -556,7 +556,7 @@ func (check *Checker) updateExprType(x ast.Expr, typ Type, final bool) { // If the new type is not final and still untyped, just // update the recorded type. if !final && isUntyped(typ) { - old.typ = asBasic(typ) + old.typ = under(typ).(*Basic) check.untyped[x] = old return } @@ -1362,7 +1362,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { duplicate := false // if the key is of interface type, the type is also significant when checking for duplicates xkey := keyVal(x.val) - if asInterface(utyp.key) != nil { + if IsInterface(utyp.key) { for _, vtyp := range visited[xkey] { if Identical(vtyp, x.typ) { duplicate = true diff --git a/src/go/types/index.go b/src/go/types/index.go index 7ef8231f0b..cd19f50627 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -35,7 +35,7 @@ func (check *Checker) indexExpr(x *operand, e *typeparams.IndexExpr) (isFuncInst return false case value: - if sig := asSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 { + if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 { // function instantiation return true } @@ -73,7 +73,7 @@ func (check *Checker) indexExpr(x *operand, e *typeparams.IndexExpr) (isFuncInst x.typ = typ.elem case *Pointer: - if typ := asArray(typ.base); typ != nil { + if typ, _ := under(typ.base).(*Array); typ != nil { valid = true length = typ.len x.mode = variable @@ -121,7 +121,7 @@ func (check *Checker) indexExpr(x *operand, e *typeparams.IndexExpr) (isFuncInst mode = value } case *Pointer: - if t := asArray(t.base); t != nil { + if t, _ := under(t.base).(*Array); t != nil { l = t.len e = t.elem } @@ -246,7 +246,7 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { x.typ = &Slice{elem: u.elem} case *Pointer: - if u := asArray(u.base); u != nil { + if u, _ := under(u.base).(*Array); u != nil { valid = true length = u.len x.typ = &Slice{elem: u.elem} diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index afb1215af2..aae6fa206d 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -122,7 +122,6 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o seen[named] = true // look for a matching attached method - named.resolve(nil) if i, m := lookupMethod(named.methods, pkg, name); m != nil { // potential match // caution: method may not have a proper signature yet @@ -302,7 +301,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, return } - if ityp := asInterface(V); ityp != nil { + if ityp, _ := under(V).(*Interface); ityp != nil { // TODO(gri) the methods are sorted - could do this more efficiently for _, m := range T.typeSet().methods { _, f := ityp.typeSet().LookupMethod(m.pkg, m.name) @@ -400,7 +399,7 @@ func (check *Checker) assertableTo(V *Interface, T Type) (method, wrongType *Fun // no static check is required if T is an interface // spec: "If T is an interface type, x.(T) asserts that the // dynamic type of x implements the interface T." - if asInterface(T) != nil && !forceStrict { + if IsInterface(T) && !forceStrict { return } return check.missingMethod(T, V, false) @@ -418,8 +417,8 @@ func deref(typ Type) (Type, bool) { // derefStructPtr dereferences typ if it is a (named or unnamed) pointer to a // (named or unnamed) struct and returns its base. Otherwise it returns typ. func derefStructPtr(typ Type) Type { - if p := asPointer(typ); p != nil { - if asStruct(p.base) != nil { + if p, _ := under(typ).(*Pointer); p != nil { + if _, ok := under(p.base).(*Struct); ok { return p.base } } diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 622c773126..e8689a12cc 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -74,7 +74,7 @@ func hasName(t Type) bool { // are not fully set up. func isTyped(t Type) bool { // isTyped is called with types that are not fully - // set up. Must not call asBasic()! + // set up. Must not call under()! b, _ := t.(*Basic) return b == nil || b.info&IsUntyped == 0 } @@ -86,7 +86,8 @@ func isUntyped(t Type) bool { // IsInterface reports whether t is an interface type. func IsInterface(t Type) bool { - return asInterface(t) != nil + _, ok := under(t).(*Interface) + return ok } // isTypeParam reports whether t is a type parameter. diff --git a/src/go/types/sizes.go b/src/go/types/sizes.go index 4c85bfe057..9a119138dd 100644 --- a/src/go/types/sizes.go +++ b/src/go/types/sizes.go @@ -243,7 +243,7 @@ func (conf *Config) offsetsof(T *Struct) []int64 { func (conf *Config) offsetof(typ Type, index []int) int64 { var o int64 for _, i := range index { - s := asStruct(typ) + s := under(typ).(*Struct) o += conf.offsetsof(s)[i] typ = s.fields[i].typ } diff --git a/src/go/types/type.go b/src/go/types/type.go index 4247f52c31..b1e2bda4cd 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -27,45 +27,8 @@ func under(t Type) Type { return t } -// Convenience converters - -func asBasic(t Type) *Basic { - op, _ := under(t).(*Basic) - return op -} - -func asArray(t Type) *Array { - op, _ := under(t).(*Array) - return op -} - -func asSlice(t Type) *Slice { - op, _ := under(t).(*Slice) - return op -} - -func asStruct(t Type) *Struct { - op, _ := under(t).(*Struct) - return op -} - -func asPointer(t Type) *Pointer { - op, _ := under(t).(*Pointer) - return op -} - -func asSignature(t Type) *Signature { - op, _ := under(t).(*Signature) - return op -} - -func asInterface(t Type) *Interface { - op, _ := under(t).(*Interface) - return op -} - // If the argument to asNamed, or asTypeParam is of the respective type -// (possibly after expanding resolving a *Named type), these methods return that type. +// (possibly after resolving a *Named type), these methods return that type. // Otherwise the result is nil. func asNamed(t Type) *Named { diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index e138af6488..c448d25458 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -362,7 +362,7 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) { } else { // special case: // append(s, "foo"...) leads to signature func([]byte, string...) - if t := asBasic(typ); t == nil || t.kind != String { + if t, _ := under(typ).(*Basic); t == nil || t.kind != String { w.error("expected string type") continue } diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index cc2bd62209..12e0f968c2 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -145,7 +145,7 @@ func (check *Checker) varType(e ast.Expr) Type { // are in the middle of type-checking parameter declarations that might belong to // interface methods. Delay this check to the end of type-checking. check.later(func() { - if t := asInterface(typ); t != nil { + if t, _ := under(typ).(*Interface); t != nil { tset := computeInterfaceTypeSet(check, e.Pos(), t) // TODO(gri) is this the correct position? if !tset.IsMethodSet() { if tset.comparable { -- GitLab From ec86bb52ba88ff18a88719ee0f9244315fa81154 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 9 Nov 2021 18:40:38 -0500 Subject: [PATCH 2089/2500] go/types: rename Checker.cycle to Checker.validCycle This is a clean port of CL 362336 to go/types. Change-Id: Iafeae7024fbb2872b07748affcea9676324ea59e Reviewed-on: https://go-review.googlesource.com/c/go/+/362755 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/decl.go | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 8d255dcf3d..eccdec9a03 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -123,7 +123,7 @@ func (check *Checker) objDecl(obj Object, def *Named) { fallthrough case grey: - // We have a cycle. + // We have a (possibly invalid) cycle. // In the existing code, this is marked by a non-nil type // for the object except for constants and variables whose // type may be non-nil (known), or nil if it depends on the @@ -135,17 +135,17 @@ func (check *Checker) objDecl(obj Object, def *Named) { // order code. switch obj := obj.(type) { case *Const: - if check.cycle(obj) || obj.typ == nil { + if !check.validCycle(obj) || obj.typ == nil { obj.typ = Typ[Invalid] } case *Var: - if check.cycle(obj) || obj.typ == nil { + if !check.validCycle(obj) || obj.typ == nil { obj.typ = Typ[Invalid] } case *TypeName: - if check.cycle(obj) { + if !check.validCycle(obj) { // break cycle // (without this, calling underlying() // below may lead to an endless loop @@ -155,7 +155,7 @@ func (check *Checker) objDecl(obj Object, def *Named) { } case *Func: - if check.cycle(obj) { + if !check.validCycle(obj) { // Don't set obj.typ to Typ[Invalid] here // because plenty of code type-asserts that // functions have a *Signature type. Grey @@ -209,9 +209,9 @@ func (check *Checker) objDecl(obj Object, def *Named) { } } -// cycle checks if the cycle starting with obj is valid and +// validCycle checks if the cycle starting with obj is valid and // reports an error if it is not. -func (check *Checker) cycle(obj Object) (isCycle bool) { +func (check *Checker) validCycle(obj Object) (valid bool) { // The object map contains the package scope objects and the non-interface methods. if debug { info := check.objMap[obj] @@ -263,7 +263,7 @@ func (check *Checker) cycle(obj Object) (isCycle bool) { check.trace(obj.Pos(), "## cycle detected: objPath = %s->%s (len = %d)", pathString(cycle), obj.Name(), len(cycle)) check.trace(obj.Pos(), "## cycle contains: %d values, %d type definitions", nval, ndef) defer func() { - if isCycle { + if !valid { check.trace(obj.Pos(), "=> error: cycle is invalid") } }() @@ -273,19 +273,18 @@ func (check *Checker) cycle(obj Object) (isCycle bool) { // ignore them here because they are reported via the initialization // cycle check. if nval == len(cycle) { - return false + return true } // A cycle involving only types (and possibly functions) must have at least // one type definition to be permitted: If there is no type definition, we // have a sequence of alias type names which will expand ad infinitum. if nval == 0 && ndef > 0 { - return false // cycle is permitted + return true } check.cycleError(cycle) - - return true + return false } type typeInfo uint -- GitLab From 318c024b498621932ace08736c38a51fe5519a63 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 8 Nov 2021 20:17:22 -0800 Subject: [PATCH 2090/2500] cmd/compile/internal/types2: rename Checker.cycle to Checker.validCycle Also, invert the boolean result. This matches Checker.validType; it's also easier to understand. Preparation for the next CL which detects cycles through type parameter lists. Change-Id: I00a75d2359ca20827c9bf406945508716c826fc4 Reviewed-on: https://go-review.googlesource.com/c/go/+/362336 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/decl.go | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 5219f7e7c5..94cbdd2b90 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -124,7 +124,7 @@ func (check *Checker) objDecl(obj Object, def *Named) { fallthrough case grey: - // We have a cycle. + // We have a (possibly invalid) cycle. // In the existing code, this is marked by a non-nil type // for the object except for constants and variables whose // type may be non-nil (known), or nil if it depends on the @@ -136,17 +136,17 @@ func (check *Checker) objDecl(obj Object, def *Named) { // order code. switch obj := obj.(type) { case *Const: - if check.cycle(obj) || obj.typ == nil { + if !check.validCycle(obj) || obj.typ == nil { obj.typ = Typ[Invalid] } case *Var: - if check.cycle(obj) || obj.typ == nil { + if !check.validCycle(obj) || obj.typ == nil { obj.typ = Typ[Invalid] } case *TypeName: - if check.cycle(obj) { + if !check.validCycle(obj) { // break cycle // (without this, calling underlying() // below may lead to an endless loop @@ -156,7 +156,7 @@ func (check *Checker) objDecl(obj Object, def *Named) { } case *Func: - if check.cycle(obj) { + if !check.validCycle(obj) { // Don't set obj.typ to Typ[Invalid] here // because plenty of code type-asserts that // functions have a *Signature type. Grey @@ -210,9 +210,9 @@ func (check *Checker) objDecl(obj Object, def *Named) { } } -// cycle checks if the cycle starting with obj is valid and +// validCycle reports whether the cycle starting with obj is valid and // reports an error if it is not. -func (check *Checker) cycle(obj Object) (isCycle bool) { +func (check *Checker) validCycle(obj Object) (valid bool) { // The object map contains the package scope objects and the non-interface methods. if debug { info := check.objMap[obj] @@ -264,7 +264,7 @@ func (check *Checker) cycle(obj Object) (isCycle bool) { check.trace(obj.Pos(), "## cycle detected: objPath = %s->%s (len = %d)", pathString(cycle), obj.Name(), len(cycle)) check.trace(obj.Pos(), "## cycle contains: %d values, %d type definitions", nval, ndef) defer func() { - if isCycle { + if !valid { check.trace(obj.Pos(), "=> error: cycle is invalid") } }() @@ -274,19 +274,18 @@ func (check *Checker) cycle(obj Object) (isCycle bool) { // ignore them here because they are reported via the initialization // cycle check. if nval == len(cycle) { - return false + return true } // A cycle involving only types (and possibly functions) must have at least // one type definition to be permitted: If there is no type definition, we // have a sequence of alias type names which will expand ad infinitum. if nval == 0 && ndef > 0 { - return false // cycle is permitted + return true } check.cycleError(cycle) - - return true + return false } type typeInfo uint -- GitLab From cc14fcac2bc1d452841336b9aeee3b1d47880f37 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 8 Nov 2021 16:09:11 -0800 Subject: [PATCH 2091/2500] cmd/compile/internal/types2: disallow type cycles through type parameter lists If we reach a generic type that is part of a cycle and we are in a type parameter list, we have a cycle through a type parameter list, which is invalid. Fixes #49439. Change-Id: Ia6cf97e1748ca0c0e61c02841202050091365b0b Reviewed-on: https://go-review.googlesource.com/c/go/+/361922 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/check.go | 1 + src/cmd/compile/internal/types2/decl.go | 57 ++++++++++++++----- .../types2/testdata/fixedbugs/issue45550.go2 | 4 +- .../types2/testdata/fixedbugs/issue46461.go2 | 6 +- .../types2/testdata/fixedbugs/issue47796.go2 | 14 ++--- .../types2/testdata/fixedbugs/issue48529.go2 | 2 +- .../types2/testdata/fixedbugs/issue49439.go2 | 26 +++++++++ test/typeparam/issue46461.go | 4 +- test/typeparam/issue46461b.dir/a.go | 2 +- test/typeparam/issue46461b.dir/b.go | 4 +- test/typeparam/issue48280.dir/a.go | 2 +- test/typeparam/issue48306.dir/a.go | 2 +- 12 files changed, 91 insertions(+), 33 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue49439.go2 diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go index b9a76a8990..247bb5a649 100644 --- a/src/cmd/compile/internal/types2/check.go +++ b/src/cmd/compile/internal/types2/check.go @@ -46,6 +46,7 @@ type context struct { pos syntax.Pos // if valid, identifiers are looked up as if at position pos (used by Eval) iota constant.Value // value of iota in a constant declaration; nil otherwise errpos syntax.Pos // if valid, identifier position of a constant with inherited initializer + inTParamList bool // set if inside a type parameter list sig *Signature // function signature if inside a function; nil otherwise isPanic map[*syntax.CallExpr]bool // set of panic call expressions (used for termination check) hasLabel bool // set if a function makes use of labels (only ~1% of functions); unused outside functions diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 94cbdd2b90..9b643fac99 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -228,13 +228,23 @@ func (check *Checker) validCycle(obj Object) (valid bool) { assert(obj.color() >= grey) start := obj.color() - grey // index of obj in objPath cycle := check.objPath[start:] - nval := 0 // number of (constant or variable) values in the cycle - ndef := 0 // number of type definitions in the cycle + tparCycle := false // if set, the cycle is through a type parameter list + nval := 0 // number of (constant or variable) values in the cycle; valid if !generic + ndef := 0 // number of type definitions in the cycle; valid if !generic +loop: for _, obj := range cycle { switch obj := obj.(type) { case *Const, *Var: nval++ case *TypeName: + // If we reach a generic type that is part of a cycle + // and we are in a type parameter list, we have a cycle + // through a type parameter list, which is invalid. + if check.inTParamList && isGeneric(obj.typ) { + tparCycle = true + break loop + } + // Determine if the type name is an alias or not. For // package-level objects, use the object map which // provides syntactic information (which doesn't rely @@ -262,7 +272,11 @@ func (check *Checker) validCycle(obj Object) (valid bool) { if check.conf.Trace { check.trace(obj.Pos(), "## cycle detected: objPath = %s->%s (len = %d)", pathString(cycle), obj.Name(), len(cycle)) - check.trace(obj.Pos(), "## cycle contains: %d values, %d type definitions", nval, ndef) + if tparCycle { + check.trace(obj.Pos(), "## cycle contains: generic type in a type parameter list") + } else { + check.trace(obj.Pos(), "## cycle contains: %d values, %d type definitions", nval, ndef) + } defer func() { if !valid { check.trace(obj.Pos(), "=> error: cycle is invalid") @@ -270,18 +284,20 @@ func (check *Checker) validCycle(obj Object) (valid bool) { }() } - // A cycle involving only constants and variables is invalid but we - // ignore them here because they are reported via the initialization - // cycle check. - if nval == len(cycle) { - return true - } + if !tparCycle { + // A cycle involving only constants and variables is invalid but we + // ignore them here because they are reported via the initialization + // cycle check. + if nval == len(cycle) { + return true + } - // A cycle involving only types (and possibly functions) must have at least - // one type definition to be permitted: If there is no type definition, we - // have a sequence of alias type names which will expand ad infinitum. - if nval == 0 && ndef > 0 { - return true + // A cycle involving only types (and possibly functions) must have at least + // one type definition to be permitted: If there is no type definition, we + // have a sequence of alias type names which will expand ad infinitum. + if nval == 0 && ndef > 0 { + return true + } } check.cycleError(cycle) @@ -624,6 +640,19 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list []*syntax.Fiel // Example: type T[P T[P]] interface{} *dst = bindTParams(tparams) + // Signal to cycle detection that we are in a type parameter list. + // We can only be inside one type parameter list at any given time: + // function closures may appear inside a type parameter list but they + // cannot be generic, and their bodies are processed in delayed and + // sequential fashion. Note that with each new declaration, we save + // the existing context and restore it when done; thus inTParamList + // is true exactly only when we are in a specific type parameter list. + assert(!check.inTParamList) + check.inTParamList = true + defer func() { + check.inTParamList = false + }() + // Keep track of bounds for later validation. var bound Type var bounds []Type diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45550.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45550.go2 index c3e9e34b87..3eeaca0957 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45550.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45550.go2 @@ -4,7 +4,7 @@ package p -type Builder[T interface{ struct{ Builder[T] } }] struct{} +type Builder /* ERROR illegal cycle */ [T interface{ struct{ Builder[T] } }] struct{} type myBuilder struct { - Builder[myBuilder /* ERROR myBuilder does not satisfy */] + Builder[myBuilder] } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46461.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46461.go2 index 8bf31090b8..4432402a30 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46461.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46461.go2 @@ -5,16 +5,16 @@ package p // test case 1 -type T[U interface{ M() T[U] }] int +type T /* ERROR illegal cycle */ [U interface{ M() T[U] }] int type X int func (X) M() T[X] { return 0 } // test case 2 -type A[T interface{ A[T] }] interface{} +type A /* ERROR illegal cycle */ [T interface{ A[T] }] interface{} // test case 3 -type A2[U interface{ A2[U] }] interface{ M() A2[U] } +type A2 /* ERROR illegal cycle */ [U interface{ A2[U] }] interface{ M() A2[U] } type I interface{ A2[I]; M() A2[I] } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47796.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47796.go2 index 9c10683e22..6667ba4fec 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47796.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47796.go2 @@ -6,16 +6,16 @@ package p // parameterized types with self-recursive constraints type ( - T1[P T1[P]] interface{} - T2[P, Q T2[P, Q]] interface{} + T1 /* ERROR illegal cycle */ [P T1[P]] interface{} + T2 /* ERROR illegal cycle */ [P, Q T2[P, Q]] interface{} T3[P T2[P, Q], Q interface{ ~string }] interface{} - T4a[P T4a[P]] interface{ ~int } - T4b[P T4b[int]] interface{ ~int } - T4c[P T4c[string /* ERROR string does not satisfy T4c\[string\] */]] interface{ ~int } + T4a /* ERROR illegal cycle */ [P T4a[P]] interface{ ~int } + T4b /* ERROR illegal cycle */ [P T4b[int]] interface{ ~int } + T4c /* ERROR illegal cycle */ [P T4c[string]] interface{ ~int } // mutually recursive constraints - T5[P T6[P]] interface{ int } + T5 /* ERROR illegal cycle */ [P T6[P]] interface{ int } T6[P T5[P]] interface{ int } ) @@ -28,6 +28,6 @@ var ( // test case from issue -type Eq[a Eq[a]] interface { +type Eq /* ERROR illegal cycle */ [a Eq[a]] interface { Equal(that a) bool } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48529.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48529.go2 index 4f92dec7fe..a3653fa19c 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48529.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48529.go2 @@ -4,7 +4,7 @@ package p -type T[U interface{ M() T /* ERROR "got 2 arguments but 1 type parameters" */ [U, int] }] int +type T /* ERROR illegal cycle */ [U interface{ M() T[U, int] }] int type X int diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49439.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49439.go2 new file mode 100644 index 0000000000..6cc838b3b3 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49439.go2 @@ -0,0 +1,26 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +import "unsafe" + +type T0 /* ERROR illegal cycle */ [P T0[P]] struct{} + +type T1 /* ERROR illegal cycle */ [P T2[P]] struct{} +type T2[P T1[P]] struct{} + +type T3 /* ERROR illegal cycle */ [P interface{ ~struct{ f T3[int] } }] struct{} + +// valid cycle in M +type N[P M[P]] struct{} +type M[Q any] struct { F *M[Q] } + +// "crazy" case +type TC[P [unsafe.Sizeof(func() { + type T [P [unsafe.Sizeof(func(){})]byte] struct{} +})]byte] struct{} + +// test case from issue +type X /* ERROR illegal cycle */ [T any, PT X[T]] interface{} diff --git a/test/typeparam/issue46461.go b/test/typeparam/issue46461.go index 2c54a6ba28..8fdec1c073 100644 --- a/test/typeparam/issue46461.go +++ b/test/typeparam/issue46461.go @@ -1,4 +1,4 @@ -// compile -G=3 +// errorcheck -G=3 // Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style @@ -6,7 +6,7 @@ package p -type T[U interface{ M() T[U] }] int +type T[U interface{ M() T[U] }] int // ERROR "invalid recursive type T" type X int diff --git a/test/typeparam/issue46461b.dir/a.go b/test/typeparam/issue46461b.dir/a.go index 0d53b3e204..fcb414266d 100644 --- a/test/typeparam/issue46461b.dir/a.go +++ b/test/typeparam/issue46461b.dir/a.go @@ -4,4 +4,4 @@ package a -type T[U interface{ M() T[U] }] int +type T[U interface{ M() int }] int diff --git a/test/typeparam/issue46461b.dir/b.go b/test/typeparam/issue46461b.dir/b.go index 3393a375c2..a4583257ff 100644 --- a/test/typeparam/issue46461b.dir/b.go +++ b/test/typeparam/issue46461b.dir/b.go @@ -8,4 +8,6 @@ import "./a" type X int -func (X) M() a.T[X] { return 0 } +func (X) M() int { return 0 } + +type _ a.T[X] diff --git a/test/typeparam/issue48280.dir/a.go b/test/typeparam/issue48280.dir/a.go index 17859e6aa9..f66fd30e34 100644 --- a/test/typeparam/issue48280.dir/a.go +++ b/test/typeparam/issue48280.dir/a.go @@ -4,7 +4,7 @@ package a -type I[T I[T]] interface { +type I[T any] interface { F() T } diff --git a/test/typeparam/issue48306.dir/a.go b/test/typeparam/issue48306.dir/a.go index 739750b20b..fdfd86cb6d 100644 --- a/test/typeparam/issue48306.dir/a.go +++ b/test/typeparam/issue48306.dir/a.go @@ -4,6 +4,6 @@ package a -type I[T I[T]] interface { +type I[T any] interface { F() T } -- GitLab From 57dc6e247538301fb312e8ee35d3385f5d5efc28 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 9 Nov 2021 18:48:16 -0500 Subject: [PATCH 2092/2500] go/types: disallow type cycles through type parameter lists This is a port of CL 361922 to go/types. Change-Id: I790c8121a640c25fb655c926fb434d667dd59f76 Reviewed-on: https://go-review.googlesource.com/c/go/+/362756 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/check.go | 1 + src/go/types/decl.go | 57 ++++++++++++++----- .../types/testdata/fixedbugs/issue45550.go2 | 4 +- .../types/testdata/fixedbugs/issue46461.go2 | 6 +- .../types/testdata/fixedbugs/issue47796.go2 | 14 ++--- .../types/testdata/fixedbugs/issue48529.go2 | 2 +- .../types/testdata/fixedbugs/issue49439.go2 | 26 +++++++++ 7 files changed, 83 insertions(+), 27 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue49439.go2 diff --git a/src/go/types/check.go b/src/go/types/check.go index 1d55fb4342..93e6ffa761 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -48,6 +48,7 @@ type context struct { pos token.Pos // if valid, identifiers are looked up as if at position pos (used by Eval) iota constant.Value // value of iota in a constant declaration; nil otherwise errpos positioner // if set, identifier position of a constant with inherited initializer + inTParamList bool // set if inside a type parameter list sig *Signature // function signature if inside a function; nil otherwise isPanic map[*ast.CallExpr]bool // set of panic call expressions (used for termination check) hasLabel bool // set if a function makes use of labels (only ~1% of functions); unused outside functions diff --git a/src/go/types/decl.go b/src/go/types/decl.go index eccdec9a03..0188bdaaf9 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -227,13 +227,23 @@ func (check *Checker) validCycle(obj Object) (valid bool) { assert(obj.color() >= grey) start := obj.color() - grey // index of obj in objPath cycle := check.objPath[start:] - nval := 0 // number of (constant or variable) values in the cycle - ndef := 0 // number of type definitions in the cycle + tparCycle := false // if set, the cycle is through a type parameter list + nval := 0 // number of (constant or variable) values in the cycle; valid if !generic + ndef := 0 // number of type definitions in the cycle; valid if !generic +loop: for _, obj := range cycle { switch obj := obj.(type) { case *Const, *Var: nval++ case *TypeName: + // If we reach a generic type that is part of a cycle + // and we are in a type parameter list, we have a cycle + // through a type parameter list, which is invalid. + if check.context.inTParamList && isGeneric(obj.typ) { + tparCycle = true + break loop + } + // Determine if the type name is an alias or not. For // package-level objects, use the object map which // provides syntactic information (which doesn't rely @@ -261,7 +271,11 @@ func (check *Checker) validCycle(obj Object) (valid bool) { if trace { check.trace(obj.Pos(), "## cycle detected: objPath = %s->%s (len = %d)", pathString(cycle), obj.Name(), len(cycle)) - check.trace(obj.Pos(), "## cycle contains: %d values, %d type definitions", nval, ndef) + if tparCycle { + check.trace(obj.Pos(), "## cycle contains: generic type in a type parameter list") + } else { + check.trace(obj.Pos(), "## cycle contains: %d values, %d type definitions", nval, ndef) + } defer func() { if !valid { check.trace(obj.Pos(), "=> error: cycle is invalid") @@ -269,18 +283,20 @@ func (check *Checker) validCycle(obj Object) (valid bool) { }() } - // A cycle involving only constants and variables is invalid but we - // ignore them here because they are reported via the initialization - // cycle check. - if nval == len(cycle) { - return true - } + if !tparCycle { + // A cycle involving only constants and variables is invalid but we + // ignore them here because they are reported via the initialization + // cycle check. + if nval == len(cycle) { + return true + } - // A cycle involving only types (and possibly functions) must have at least - // one type definition to be permitted: If there is no type definition, we - // have a sequence of alias type names which will expand ad infinitum. - if nval == 0 && ndef > 0 { - return true + // A cycle involving only types (and possibly functions) must have at least + // one type definition to be permitted: If there is no type definition, we + // have a sequence of alias type names which will expand ad infinitum. + if nval == 0 && ndef > 0 { + return true + } } check.cycleError(cycle) @@ -676,6 +692,19 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list *ast.FieldList // Example: type T[P T[P]] interface{} *dst = bindTParams(tparams) + // Signal to cycle detection that we are in a type parameter list. + // We can only be inside one type parameter list at any given time: + // function closures may appear inside a type parameter list but they + // cannot be generic, and their bodies are processed in delayed and + // sequential fashion. Note that with each new declaration, we save + // the existing context and restore it when done; thus inTPList is + // true exactly only when we are in a specific type parameter list. + assert(!check.inTParamList) + check.inTParamList = true + defer func() { + check.inTParamList = false + }() + index := 0 var bounds []Type var posns []positioner // bound positions diff --git a/src/go/types/testdata/fixedbugs/issue45550.go2 b/src/go/types/testdata/fixedbugs/issue45550.go2 index c3e9e34b87..3eeaca0957 100644 --- a/src/go/types/testdata/fixedbugs/issue45550.go2 +++ b/src/go/types/testdata/fixedbugs/issue45550.go2 @@ -4,7 +4,7 @@ package p -type Builder[T interface{ struct{ Builder[T] } }] struct{} +type Builder /* ERROR illegal cycle */ [T interface{ struct{ Builder[T] } }] struct{} type myBuilder struct { - Builder[myBuilder /* ERROR myBuilder does not satisfy */] + Builder[myBuilder] } diff --git a/src/go/types/testdata/fixedbugs/issue46461.go2 b/src/go/types/testdata/fixedbugs/issue46461.go2 index 8bf31090b8..4432402a30 100644 --- a/src/go/types/testdata/fixedbugs/issue46461.go2 +++ b/src/go/types/testdata/fixedbugs/issue46461.go2 @@ -5,16 +5,16 @@ package p // test case 1 -type T[U interface{ M() T[U] }] int +type T /* ERROR illegal cycle */ [U interface{ M() T[U] }] int type X int func (X) M() T[X] { return 0 } // test case 2 -type A[T interface{ A[T] }] interface{} +type A /* ERROR illegal cycle */ [T interface{ A[T] }] interface{} // test case 3 -type A2[U interface{ A2[U] }] interface{ M() A2[U] } +type A2 /* ERROR illegal cycle */ [U interface{ A2[U] }] interface{ M() A2[U] } type I interface{ A2[I]; M() A2[I] } diff --git a/src/go/types/testdata/fixedbugs/issue47796.go2 b/src/go/types/testdata/fixedbugs/issue47796.go2 index 9c10683e22..6667ba4fec 100644 --- a/src/go/types/testdata/fixedbugs/issue47796.go2 +++ b/src/go/types/testdata/fixedbugs/issue47796.go2 @@ -6,16 +6,16 @@ package p // parameterized types with self-recursive constraints type ( - T1[P T1[P]] interface{} - T2[P, Q T2[P, Q]] interface{} + T1 /* ERROR illegal cycle */ [P T1[P]] interface{} + T2 /* ERROR illegal cycle */ [P, Q T2[P, Q]] interface{} T3[P T2[P, Q], Q interface{ ~string }] interface{} - T4a[P T4a[P]] interface{ ~int } - T4b[P T4b[int]] interface{ ~int } - T4c[P T4c[string /* ERROR string does not satisfy T4c\[string\] */]] interface{ ~int } + T4a /* ERROR illegal cycle */ [P T4a[P]] interface{ ~int } + T4b /* ERROR illegal cycle */ [P T4b[int]] interface{ ~int } + T4c /* ERROR illegal cycle */ [P T4c[string]] interface{ ~int } // mutually recursive constraints - T5[P T6[P]] interface{ int } + T5 /* ERROR illegal cycle */ [P T6[P]] interface{ int } T6[P T5[P]] interface{ int } ) @@ -28,6 +28,6 @@ var ( // test case from issue -type Eq[a Eq[a]] interface { +type Eq /* ERROR illegal cycle */ [a Eq[a]] interface { Equal(that a) bool } diff --git a/src/go/types/testdata/fixedbugs/issue48529.go2 b/src/go/types/testdata/fixedbugs/issue48529.go2 index 4f92dec7fe..a3653fa19c 100644 --- a/src/go/types/testdata/fixedbugs/issue48529.go2 +++ b/src/go/types/testdata/fixedbugs/issue48529.go2 @@ -4,7 +4,7 @@ package p -type T[U interface{ M() T /* ERROR "got 2 arguments but 1 type parameters" */ [U, int] }] int +type T /* ERROR illegal cycle */ [U interface{ M() T[U, int] }] int type X int diff --git a/src/go/types/testdata/fixedbugs/issue49439.go2 b/src/go/types/testdata/fixedbugs/issue49439.go2 new file mode 100644 index 0000000000..6cc838b3b3 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue49439.go2 @@ -0,0 +1,26 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +import "unsafe" + +type T0 /* ERROR illegal cycle */ [P T0[P]] struct{} + +type T1 /* ERROR illegal cycle */ [P T2[P]] struct{} +type T2[P T1[P]] struct{} + +type T3 /* ERROR illegal cycle */ [P interface{ ~struct{ f T3[int] } }] struct{} + +// valid cycle in M +type N[P M[P]] struct{} +type M[Q any] struct { F *M[Q] } + +// "crazy" case +type TC[P [unsafe.Sizeof(func() { + type T [P [unsafe.Sizeof(func(){})]byte] struct{} +})]byte] struct{} + +// test case from issue +type X /* ERROR illegal cycle */ [T any, PT X[T]] interface{} -- GitLab From 02d7eab52796574b44717d45d5def42c9068b56a Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sun, 31 Oct 2021 11:33:00 -0400 Subject: [PATCH 2093/2500] go/parser: allow parsing aliases with type parameters We already guard against this in the type checker, and it will eventually be allowed per the accepted proposal. Add a placeholder error code for the corresponding type checker error. Change-Id: I5cc2f1413ecc89ec2094f7178fdb156fb8cc2e43 Reviewed-on: https://go-review.googlesource.com/c/go/+/360235 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/parser/parser.go | 6 ++++-- src/go/parser/short_test.go | 2 +- src/go/types/decl.go | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go index 8952a2bc29..7c1a8be2fa 100644 --- a/src/go/parser/parser.go +++ b/src/go/parser/parser.go @@ -2539,9 +2539,11 @@ func (p *parser) parseGenericType(spec *ast.TypeSpec, openPos token.Pos, name0 * list := p.parseParameterList(name0, token.RBRACK) closePos := p.expect(token.RBRACK) spec.TypeParams = &ast.FieldList{Opening: openPos, List: list, Closing: closePos} - // Type alias cannot have type parameters. Accept them for robustness but complain. + // Let the type checker decide whether to accept type parameters on aliases: + // see issue #46477. if p.tok == token.ASSIGN { - p.error(p.pos, "generic type cannot be alias") + // type alias + spec.Assign = p.pos p.next() } spec.Type = p.parseType() diff --git a/src/go/parser/short_test.go b/src/go/parser/short_test.go index 20450bfe8e..90a4ec9ecd 100644 --- a/src/go/parser/short_test.go +++ b/src/go/parser/short_test.go @@ -123,6 +123,7 @@ var validWithTParamsOnly = []string{ `package p; type I1[T any /* ERROR "expected ']', found any" */ ] interface{}; type I2 interface{ I1[int] }`, `package p; type I1[T any /* ERROR "expected ']', found any" */ ] interface{}; type I2[T any] interface{ I1[T] }`, `package p; type _ interface { f[ /* ERROR "expected ';', found '\['" */ T any]() }`, + `package p; type T[P any /* ERROR "expected ']'" */ ] = T0`, } func TestValid(t *testing.T) { @@ -240,7 +241,6 @@ var invalidNoTParamErrs = []string{ // error messages produced when ParseTypeParams is set. var invalidTParamErrs = []string{ `package p; type _[_ any] int; var _ = T[] /* ERROR "expected operand" */ {}`, - `package p; type T[P any] = /* ERROR "cannot be alias" */ T0`, `package p; var _ func[ /* ERROR "cannot have type parameters" */ T any](T)`, `package p; func _[]/* ERROR "empty type parameter list" */()`, diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 0188bdaaf9..64d5bd195e 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -631,7 +631,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { if alias && tdecl.TypeParams.NumFields() != 0 { // The parser will ensure this but we may still get an invalid AST. // Complain and continue as regular type definition. - check.error(atPos(tdecl.Assign), 0, "generic type cannot be alias") + check.error(atPos(tdecl.Assign), _Todo, "generic type cannot be alias") alias = false } -- GitLab From e984240d310302764c66bb4bf84b5747e05cf8ef Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Fri, 5 Nov 2021 23:50:55 +0900 Subject: [PATCH 2094/2500] runtime: fix unworkable comments for go:nosplit Change-Id: I71c29a2dc7e5b2b6bc35093535228d2907b16b47 Reviewed-on: https://go-review.googlesource.com/c/go/+/361595 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Hajime Hoshi --- src/runtime/sys_darwin.go | 2 +- src/runtime/sys_openbsd2.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/runtime/sys_darwin.go b/src/runtime/sys_darwin.go index 0f91685d6c..9af4cf18f8 100644 --- a/src/runtime/sys_darwin.go +++ b/src/runtime/sys_darwin.go @@ -156,7 +156,7 @@ func pthread_kill_trampoline() // mmap is used to do low-level memory allocation via mmap. Don't allow stack // splits, since this function (used by sysAlloc) is called in a lot of low-level // parts of the runtime and callers often assume it won't acquire any locks. -// go:nosplit +//go:nosplit func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) (unsafe.Pointer, int) { args := struct { addr unsafe.Pointer diff --git a/src/runtime/sys_openbsd2.go b/src/runtime/sys_openbsd2.go index 7024cfa86d..c936fbb494 100644 --- a/src/runtime/sys_openbsd2.go +++ b/src/runtime/sys_openbsd2.go @@ -45,7 +45,7 @@ func thrkill_trampoline() // mmap is used to do low-level memory allocation via mmap. Don't allow stack // splits, since this function (used by sysAlloc) is called in a lot of low-level // parts of the runtime and callers often assume it won't acquire any locks. -// go:nosplit +//go:nosplit func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) (unsafe.Pointer, int) { args := struct { addr unsafe.Pointer -- GitLab From 17980dff368256a0763cf042376d3fb36d06c109 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 9 Nov 2021 20:22:26 -0800 Subject: [PATCH 2095/2500] doc: make a copy of the latest Go 1.17 spec This will allow us to compare the changes made for Go 1.18. Change-Id: I1456270b201967f5cb05e66cec556939e6e33265 Reviewed-on: https://go-review.googlesource.com/c/go/+/362894 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Ian Lance Taylor --- doc/go1.17_spec.html | 6858 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 6858 insertions(+) create mode 100644 doc/go1.17_spec.html diff --git a/doc/go1.17_spec.html b/doc/go1.17_spec.html new file mode 100644 index 0000000000..46eebb5713 --- /dev/null +++ b/doc/go1.17_spec.html @@ -0,0 +1,6858 @@ + + +

Introduction

+ +

+This is a reference manual for the Go programming language. For +more information and other documents, see golang.org. +

+ +

+Go is a general-purpose language designed with systems programming +in mind. It is strongly typed and garbage-collected and has explicit +support for concurrent programming. Programs are constructed from +packages, whose properties allow efficient management of +dependencies. +

+ +

+The grammar is compact and simple to parse, allowing for easy analysis +by automatic tools such as integrated development environments. +

+ +

Notation

+

+The syntax is specified using Extended Backus-Naur Form (EBNF): +

+ +
+Production  = production_name "=" [ Expression ] "." .
+Expression  = Alternative { "|" Alternative } .
+Alternative = Term { Term } .
+Term        = production_name | token [ "…" token ] | Group | Option | Repetition .
+Group       = "(" Expression ")" .
+Option      = "[" Expression "]" .
+Repetition  = "{" Expression "}" .
+
+ +

+Productions are expressions constructed from terms and the following +operators, in increasing precedence: +

+
+|   alternation
+()  grouping
+[]  option (0 or 1 times)
+{}  repetition (0 to n times)
+
+ +

+Lower-case production names are used to identify lexical tokens. +Non-terminals are in CamelCase. Lexical tokens are enclosed in +double quotes "" or back quotes ``. +

+ +

+The form a … b represents the set of characters from +a through b as alternatives. The horizontal +ellipsis is also used elsewhere in the spec to informally denote various +enumerations or code snippets that are not further specified. The character +(as opposed to the three characters ...) is not a token of the Go +language. +

+ +

Source code representation

+ +

+Source code is Unicode text encoded in +UTF-8. The text is not +canonicalized, so a single accented code point is distinct from the +same character constructed from combining an accent and a letter; +those are treated as two code points. For simplicity, this document +will use the unqualified term character to refer to a Unicode code point +in the source text. +

+

+Each code point is distinct; for instance, upper and lower case letters +are different characters. +

+

+Implementation restriction: For compatibility with other tools, a +compiler may disallow the NUL character (U+0000) in the source text. +

+

+Implementation restriction: For compatibility with other tools, a +compiler may ignore a UTF-8-encoded byte order mark +(U+FEFF) if it is the first Unicode code point in the source text. +A byte order mark may be disallowed anywhere else in the source. +

+ +

Characters

+ +

+The following terms are used to denote specific Unicode character classes: +

+
+newline        = /* the Unicode code point U+000A */ .
+unicode_char   = /* an arbitrary Unicode code point except newline */ .
+unicode_letter = /* a Unicode code point classified as "Letter" */ .
+unicode_digit  = /* a Unicode code point classified as "Number, decimal digit" */ .
+
+ +

+In The Unicode Standard 8.0, +Section 4.5 "General Category" defines a set of character categories. +Go treats all characters in any of the Letter categories Lu, Ll, Lt, Lm, or Lo +as Unicode letters, and those in the Number category Nd as Unicode digits. +

+ +

Letters and digits

+ +

+The underscore character _ (U+005F) is considered a letter. +

+
+letter        = unicode_letter | "_" .
+decimal_digit = "0" … "9" .
+binary_digit  = "0" | "1" .
+octal_digit   = "0" … "7" .
+hex_digit     = "0" … "9" | "A" … "F" | "a" … "f" .
+
+ +

Lexical elements

+ +

Comments

+ +

+Comments serve as program documentation. There are two forms: +

+ +
    +
  1. +Line comments start with the character sequence // +and stop at the end of the line. +
  2. +
  3. +General comments start with the character sequence /* +and stop with the first subsequent character sequence */. +
  4. +
+ +

+A comment cannot start inside a rune or +string literal, or inside a comment. +A general comment containing no newlines acts like a space. +Any other comment acts like a newline. +

+ +

Tokens

+ +

+Tokens form the vocabulary of the Go language. +There are four classes: identifiers, keywords, operators +and punctuation, and literals. White space, formed from +spaces (U+0020), horizontal tabs (U+0009), +carriage returns (U+000D), and newlines (U+000A), +is ignored except as it separates tokens +that would otherwise combine into a single token. Also, a newline or end of file +may trigger the insertion of a semicolon. +While breaking the input into tokens, +the next token is the longest sequence of characters that form a +valid token. +

+ +

Semicolons

+ +

+The formal grammar uses semicolons ";" as terminators in +a number of productions. Go programs may omit most of these semicolons +using the following two rules: +

+ +
    +
  1. +When the input is broken into tokens, a semicolon is automatically inserted +into the token stream immediately after a line's final token if that token is + +
  2. + +
  3. +To allow complex statements to occupy a single line, a semicolon +may be omitted before a closing ")" or "}". +
  4. +
+ +

+To reflect idiomatic use, code examples in this document elide semicolons +using these rules. +

+ + +

Identifiers

+ +

+Identifiers name program entities such as variables and types. +An identifier is a sequence of one or more letters and digits. +The first character in an identifier must be a letter. +

+
+identifier = letter { letter | unicode_digit } .
+
+
+a
+_x9
+ThisVariableIsExported
+αβ
+
+ +

+Some identifiers are predeclared. +

+ + +

Keywords

+ +

+The following keywords are reserved and may not be used as identifiers. +

+
+break        default      func         interface    select
+case         defer        go           map          struct
+chan         else         goto         package      switch
+const        fallthrough  if           range        type
+continue     for          import       return       var
+
+ +

Operators and punctuation

+ +

+The following character sequences represent operators +(including assignment operators) and punctuation: +

+
++    &     +=    &=     &&    ==    !=    (    )
+-    |     -=    |=     ||    <     <=    [    ]
+*    ^     *=    ^=     <-    >     >=    {    }
+/    <<    /=    <<=    ++    =     :=    ,    ;
+%    >>    %=    >>=    --    !     ...   .    :
+     &^          &^=
+
+ +

Integer literals

+ +

+An integer literal is a sequence of digits representing an +integer constant. +An optional prefix sets a non-decimal base: 0b or 0B +for binary, 0, 0o, or 0O for octal, +and 0x or 0X for hexadecimal. +A single 0 is considered a decimal zero. +In hexadecimal literals, letters a through f +and A through F represent values 10 through 15. +

+ +

+For readability, an underscore character _ may appear after +a base prefix or between successive digits; such underscores do not change +the literal's value. +

+
+int_lit        = decimal_lit | binary_lit | octal_lit | hex_lit .
+decimal_lit    = "0" | ( "1" … "9" ) [ [ "_" ] decimal_digits ] .
+binary_lit     = "0" ( "b" | "B" ) [ "_" ] binary_digits .
+octal_lit      = "0" [ "o" | "O" ] [ "_" ] octal_digits .
+hex_lit        = "0" ( "x" | "X" ) [ "_" ] hex_digits .
+
+decimal_digits = decimal_digit { [ "_" ] decimal_digit } .
+binary_digits  = binary_digit { [ "_" ] binary_digit } .
+octal_digits   = octal_digit { [ "_" ] octal_digit } .
+hex_digits     = hex_digit { [ "_" ] hex_digit } .
+
+ +
+42
+4_2
+0600
+0_600
+0o600
+0O600       // second character is capital letter 'O'
+0xBadFace
+0xBad_Face
+0x_67_7a_2f_cc_40_c6
+170141183460469231731687303715884105727
+170_141183_460469_231731_687303_715884_105727
+
+_42         // an identifier, not an integer literal
+42_         // invalid: _ must separate successive digits
+4__2        // invalid: only one _ at a time
+0_xBadFace  // invalid: _ must separate successive digits
+
+ + +

Floating-point literals

+ +

+A floating-point literal is a decimal or hexadecimal representation of a +floating-point constant. +

+ +

+A decimal floating-point literal consists of an integer part (decimal digits), +a decimal point, a fractional part (decimal digits), and an exponent part +(e or E followed by an optional sign and decimal digits). +One of the integer part or the fractional part may be elided; one of the decimal point +or the exponent part may be elided. +An exponent value exp scales the mantissa (integer and fractional part) by 10exp. +

+ +

+A hexadecimal floating-point literal consists of a 0x or 0X +prefix, an integer part (hexadecimal digits), a radix point, a fractional part (hexadecimal digits), +and an exponent part (p or P followed by an optional sign and decimal digits). +One of the integer part or the fractional part may be elided; the radix point may be elided as well, +but the exponent part is required. (This syntax matches the one given in IEEE 754-2008 §5.12.3.) +An exponent value exp scales the mantissa (integer and fractional part) by 2exp. +

+ +

+For readability, an underscore character _ may appear after +a base prefix or between successive digits; such underscores do not change +the literal value. +

+ +
+float_lit         = decimal_float_lit | hex_float_lit .
+
+decimal_float_lit = decimal_digits "." [ decimal_digits ] [ decimal_exponent ] |
+                    decimal_digits decimal_exponent |
+                    "." decimal_digits [ decimal_exponent ] .
+decimal_exponent  = ( "e" | "E" ) [ "+" | "-" ] decimal_digits .
+
+hex_float_lit     = "0" ( "x" | "X" ) hex_mantissa hex_exponent .
+hex_mantissa      = [ "_" ] hex_digits "." [ hex_digits ] |
+                    [ "_" ] hex_digits |
+                    "." hex_digits .
+hex_exponent      = ( "p" | "P" ) [ "+" | "-" ] decimal_digits .
+
+ +
+0.
+72.40
+072.40       // == 72.40
+2.71828
+1.e+0
+6.67428e-11
+1E6
+.25
+.12345E+5
+1_5.         // == 15.0
+0.15e+0_2    // == 15.0
+
+0x1p-2       // == 0.25
+0x2.p10      // == 2048.0
+0x1.Fp+0     // == 1.9375
+0X.8p-0      // == 0.5
+0X_1FFFP-16  // == 0.1249847412109375
+0x15e-2      // == 0x15e - 2 (integer subtraction)
+
+0x.p1        // invalid: mantissa has no digits
+1p-2         // invalid: p exponent requires hexadecimal mantissa
+0x1.5e-2     // invalid: hexadecimal mantissa requires p exponent
+1_.5         // invalid: _ must separate successive digits
+1._5         // invalid: _ must separate successive digits
+1.5_e1       // invalid: _ must separate successive digits
+1.5e_1       // invalid: _ must separate successive digits
+1.5e1_       // invalid: _ must separate successive digits
+
+ + +

Imaginary literals

+ +

+An imaginary literal represents the imaginary part of a +complex constant. +It consists of an integer or +floating-point literal +followed by the lower-case letter i. +The value of an imaginary literal is the value of the respective +integer or floating-point literal multiplied by the imaginary unit i. +

+ +
+imaginary_lit = (decimal_digits | int_lit | float_lit) "i" .
+
+ +

+For backward compatibility, an imaginary literal's integer part consisting +entirely of decimal digits (and possibly underscores) is considered a decimal +integer, even if it starts with a leading 0. +

+ +
+0i
+0123i         // == 123i for backward-compatibility
+0o123i        // == 0o123 * 1i == 83i
+0xabci        // == 0xabc * 1i == 2748i
+0.i
+2.71828i
+1.e+0i
+6.67428e-11i
+1E6i
+.25i
+.12345E+5i
+0x1p-2i       // == 0x1p-2 * 1i == 0.25i
+
+ + +

Rune literals

+ +

+A rune literal represents a rune constant, +an integer value identifying a Unicode code point. +A rune literal is expressed as one or more characters enclosed in single quotes, +as in 'x' or '\n'. +Within the quotes, any character may appear except newline and unescaped single +quote. A single quoted character represents the Unicode value +of the character itself, +while multi-character sequences beginning with a backslash encode +values in various formats. +

+ +

+The simplest form represents the single character within the quotes; +since Go source text is Unicode characters encoded in UTF-8, multiple +UTF-8-encoded bytes may represent a single integer value. For +instance, the literal 'a' holds a single byte representing +a literal a, Unicode U+0061, value 0x61, while +'ä' holds two bytes (0xc3 0xa4) representing +a literal a-dieresis, U+00E4, value 0xe4. +

+ +

+Several backslash escapes allow arbitrary values to be encoded as +ASCII text. There are four ways to represent the integer value +as a numeric constant: \x followed by exactly two hexadecimal +digits; \u followed by exactly four hexadecimal digits; +\U followed by exactly eight hexadecimal digits, and a +plain backslash \ followed by exactly three octal digits. +In each case the value of the literal is the value represented by +the digits in the corresponding base. +

+ +

+Although these representations all result in an integer, they have +different valid ranges. Octal escapes must represent a value between +0 and 255 inclusive. Hexadecimal escapes satisfy this condition +by construction. The escapes \u and \U +represent Unicode code points so within them some values are illegal, +in particular those above 0x10FFFF and surrogate halves. +

+ +

+After a backslash, certain single-character escapes represent special values: +

+ +
+\a   U+0007 alert or bell
+\b   U+0008 backspace
+\f   U+000C form feed
+\n   U+000A line feed or newline
+\r   U+000D carriage return
+\t   U+0009 horizontal tab
+\v   U+000B vertical tab
+\\   U+005C backslash
+\'   U+0027 single quote  (valid escape only within rune literals)
+\"   U+0022 double quote  (valid escape only within string literals)
+
+ +

+All other sequences starting with a backslash are illegal inside rune literals. +

+
+rune_lit         = "'" ( unicode_value | byte_value ) "'" .
+unicode_value    = unicode_char | little_u_value | big_u_value | escaped_char .
+byte_value       = octal_byte_value | hex_byte_value .
+octal_byte_value = `\` octal_digit octal_digit octal_digit .
+hex_byte_value   = `\` "x" hex_digit hex_digit .
+little_u_value   = `\` "u" hex_digit hex_digit hex_digit hex_digit .
+big_u_value      = `\` "U" hex_digit hex_digit hex_digit hex_digit
+                           hex_digit hex_digit hex_digit hex_digit .
+escaped_char     = `\` ( "a" | "b" | "f" | "n" | "r" | "t" | "v" | `\` | "'" | `"` ) .
+
+ +
+'a'
+'ä'
+'本'
+'\t'
+'\000'
+'\007'
+'\377'
+'\x07'
+'\xff'
+'\u12e4'
+'\U00101234'
+'\''         // rune literal containing single quote character
+'aa'         // illegal: too many characters
+'\xa'        // illegal: too few hexadecimal digits
+'\0'         // illegal: too few octal digits
+'\uDFFF'     // illegal: surrogate half
+'\U00110000' // illegal: invalid Unicode code point
+
+ + +

String literals

+ +

+A string literal represents a string constant +obtained from concatenating a sequence of characters. There are two forms: +raw string literals and interpreted string literals. +

+ +

+Raw string literals are character sequences between back quotes, as in +`foo`. Within the quotes, any character may appear except +back quote. The value of a raw string literal is the +string composed of the uninterpreted (implicitly UTF-8-encoded) characters +between the quotes; +in particular, backslashes have no special meaning and the string may +contain newlines. +Carriage return characters ('\r') inside raw string literals +are discarded from the raw string value. +

+ +

+Interpreted string literals are character sequences between double +quotes, as in "bar". +Within the quotes, any character may appear except newline and unescaped double quote. +The text between the quotes forms the +value of the literal, with backslash escapes interpreted as they +are in rune literals (except that \' is illegal and +\" is legal), with the same restrictions. +The three-digit octal (\nnn) +and two-digit hexadecimal (\xnn) escapes represent individual +bytes of the resulting string; all other escapes represent +the (possibly multi-byte) UTF-8 encoding of individual characters. +Thus inside a string literal \377 and \xFF represent +a single byte of value 0xFF=255, while ÿ, +\u00FF, \U000000FF and \xc3\xbf represent +the two bytes 0xc3 0xbf of the UTF-8 encoding of character +U+00FF. +

+ +
+string_lit             = raw_string_lit | interpreted_string_lit .
+raw_string_lit         = "`" { unicode_char | newline } "`" .
+interpreted_string_lit = `"` { unicode_value | byte_value } `"` .
+
+ +
+`abc`                // same as "abc"
+`\n
+\n`                  // same as "\\n\n\\n"
+"\n"
+"\""                 // same as `"`
+"Hello, world!\n"
+"日本語"
+"\u65e5本\U00008a9e"
+"\xff\u00FF"
+"\uD800"             // illegal: surrogate half
+"\U00110000"         // illegal: invalid Unicode code point
+
+ +

+These examples all represent the same string: +

+ +
+"日本語"                                 // UTF-8 input text
+`日本語`                                 // UTF-8 input text as a raw literal
+"\u65e5\u672c\u8a9e"                    // the explicit Unicode code points
+"\U000065e5\U0000672c\U00008a9e"        // the explicit Unicode code points
+"\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"  // the explicit UTF-8 bytes
+
+ +

+If the source code represents a character as two code points, such as +a combining form involving an accent and a letter, the result will be +an error if placed in a rune literal (it is not a single code +point), and will appear as two code points if placed in a string +literal. +

+ + +

Constants

+ +

There are boolean constants, +rune constants, +integer constants, +floating-point constants, complex constants, +and string constants. Rune, integer, floating-point, +and complex constants are +collectively called numeric constants. +

+ +

+A constant value is represented by a +rune, +integer, +floating-point, +imaginary, +or +string literal, +an identifier denoting a constant, +a constant expression, +a conversion with a result that is a constant, or +the result value of some built-in functions such as +unsafe.Sizeof applied to any value, +cap or len applied to +some expressions, +real and imag applied to a complex constant +and complex applied to numeric constants. +The boolean truth values are represented by the predeclared constants +true and false. The predeclared identifier +iota denotes an integer constant. +

+ +

+In general, complex constants are a form of +constant expression +and are discussed in that section. +

+ +

+Numeric constants represent exact values of arbitrary precision and do not overflow. +Consequently, there are no constants denoting the IEEE-754 negative zero, infinity, +and not-a-number values. +

+ +

+Constants may be typed or untyped. +Literal constants, true, false, iota, +and certain constant expressions +containing only untyped constant operands are untyped. +

+ +

+A constant may be given a type explicitly by a constant declaration +or conversion, or implicitly when used in a +variable declaration or an +assignment or as an +operand in an expression. +It is an error if the constant value +cannot be represented as a value of the respective type. +

+ +

+An untyped constant has a default type which is the type to which the +constant is implicitly converted in contexts where a typed value is required, +for instance, in a short variable declaration +such as i := 0 where there is no explicit type. +The default type of an untyped constant is bool, rune, +int, float64, complex128 or string +respectively, depending on whether it is a boolean, rune, integer, floating-point, +complex, or string constant. +

+ +

+Implementation restriction: Although numeric constants have arbitrary +precision in the language, a compiler may implement them using an +internal representation with limited precision. That said, every +implementation must: +

+ +
    +
  • Represent integer constants with at least 256 bits.
  • + +
  • Represent floating-point constants, including the parts of + a complex constant, with a mantissa of at least 256 bits + and a signed binary exponent of at least 16 bits.
  • + +
  • Give an error if unable to represent an integer constant + precisely.
  • + +
  • Give an error if unable to represent a floating-point or + complex constant due to overflow.
  • + +
  • Round to the nearest representable constant if unable to + represent a floating-point or complex constant due to limits + on precision.
  • +
+ +

+These requirements apply both to literal constants and to the result +of evaluating constant +expressions. +

+ + +

Variables

+ +

+A variable is a storage location for holding a value. +The set of permissible values is determined by the +variable's type. +

+ +

+A variable declaration +or, for function parameters and results, the signature +of a function declaration +or function literal reserves +storage for a named variable. + +Calling the built-in function new +or taking the address of a composite literal +allocates storage for a variable at run time. +Such an anonymous variable is referred to via a (possibly implicit) +pointer indirection. +

+ +

+Structured variables of array, slice, +and struct types have elements and fields that may +be addressed individually. Each such element +acts like a variable. +

+ +

+The static type (or just type) of a variable is the +type given in its declaration, the type provided in the +new call or composite literal, or the type of +an element of a structured variable. +Variables of interface type also have a distinct dynamic type, +which is the concrete type of the value assigned to the variable at run time +(unless the value is the predeclared identifier nil, +which has no type). +The dynamic type may vary during execution but values stored in interface +variables are always assignable +to the static type of the variable. +

+ +
+var x interface{}  // x is nil and has static type interface{}
+var v *T           // v has value nil, static type *T
+x = 42             // x has value 42 and dynamic type int
+x = v              // x has value (*T)(nil) and dynamic type *T
+
+ +

+A variable's value is retrieved by referring to the variable in an +expression; it is the most recent value +assigned to the variable. +If a variable has not yet been assigned a value, its value is the +zero value for its type. +

+ + +

Types

+ +

+A type determines a set of values together with operations and methods specific +to those values. A type may be denoted by a type name, if it has one, +or specified using a type literal, which composes a type from existing types. +

+ +
+Type      = TypeName | TypeLit | "(" Type ")" .
+TypeName  = identifier | QualifiedIdent .
+TypeLit   = ArrayType | StructType | PointerType | FunctionType | InterfaceType |
+	    SliceType | MapType | ChannelType .
+
+ +

+The language predeclares certain type names. +Others are introduced with type declarations. +Composite types—array, struct, pointer, function, +interface, slice, map, and channel types—may be constructed using +type literals. +

+ +

+Each type T has an underlying type: If T +is one of the predeclared boolean, numeric, or string types, or a type literal, +the corresponding underlying +type is T itself. Otherwise, T's underlying type +is the underlying type of the type to which T refers in its +type declaration. +

+ +
+type (
+	A1 = string
+	A2 = A1
+)
+
+type (
+	B1 string
+	B2 B1
+	B3 []B1
+	B4 B3
+)
+
+ +

+The underlying type of string, A1, A2, B1, +and B2 is string. +The underlying type of []B1, B3, and B4 is []B1. +

+ +

Method sets

+

+A type has a (possibly empty) method set associated with it. +The method set of an interface type is its interface. +The method set of any other type T consists of all +methods declared with receiver type T. +The method set of the corresponding pointer type *T +is the set of all methods declared with receiver *T or T +(that is, it also contains the method set of T). +Further rules apply to structs containing embedded fields, as described +in the section on struct types. +Any other type has an empty method set. +In a method set, each method must have a +unique +non-blank method name. +

+ +

+The method set of a type determines the interfaces that the +type implements +and the methods that can be called +using a receiver of that type. +

+ +

Boolean types

+ +

+A boolean type represents the set of Boolean truth values +denoted by the predeclared constants true +and false. The predeclared boolean type is bool; +it is a defined type. +

+ +

Numeric types

+ +

+A numeric type represents sets of integer or floating-point values. +The predeclared architecture-independent numeric types are: +

+ +
+uint8       the set of all unsigned  8-bit integers (0 to 255)
+uint16      the set of all unsigned 16-bit integers (0 to 65535)
+uint32      the set of all unsigned 32-bit integers (0 to 4294967295)
+uint64      the set of all unsigned 64-bit integers (0 to 18446744073709551615)
+
+int8        the set of all signed  8-bit integers (-128 to 127)
+int16       the set of all signed 16-bit integers (-32768 to 32767)
+int32       the set of all signed 32-bit integers (-2147483648 to 2147483647)
+int64       the set of all signed 64-bit integers (-9223372036854775808 to 9223372036854775807)
+
+float32     the set of all IEEE-754 32-bit floating-point numbers
+float64     the set of all IEEE-754 64-bit floating-point numbers
+
+complex64   the set of all complex numbers with float32 real and imaginary parts
+complex128  the set of all complex numbers with float64 real and imaginary parts
+
+byte        alias for uint8
+rune        alias for int32
+
+ +

+The value of an n-bit integer is n bits wide and represented using +two's complement arithmetic. +

+ +

+There is also a set of predeclared numeric types with implementation-specific sizes: +

+ +
+uint     either 32 or 64 bits
+int      same size as uint
+uintptr  an unsigned integer large enough to store the uninterpreted bits of a pointer value
+
+ +

+To avoid portability issues all numeric types are defined +types and thus distinct except +byte, which is an alias for uint8, and +rune, which is an alias for int32. +Explicit conversions +are required when different numeric types are mixed in an expression +or assignment. For instance, int32 and int +are not the same type even though they may have the same size on a +particular architecture. + + +

String types

+ +

+A string type represents the set of string values. +A string value is a (possibly empty) sequence of bytes. +The number of bytes is called the length of the string and is never negative. +Strings are immutable: once created, +it is impossible to change the contents of a string. +The predeclared string type is string; +it is a defined type. +

+ +

+The length of a string s can be discovered using +the built-in function len. +The length is a compile-time constant if the string is a constant. +A string's bytes can be accessed by integer indices +0 through len(s)-1. +It is illegal to take the address of such an element; if +s[i] is the i'th byte of a +string, &s[i] is invalid. +

+ + +

Array types

+ +

+An array is a numbered sequence of elements of a single +type, called the element type. +The number of elements is called the length of the array and is never negative. +

+ +
+ArrayType   = "[" ArrayLength "]" ElementType .
+ArrayLength = Expression .
+ElementType = Type .
+
+ +

+The length is part of the array's type; it must evaluate to a +non-negative constant +representable by a value +of type int. +The length of array a can be discovered +using the built-in function len. +The elements can be addressed by integer indices +0 through len(a)-1. +Array types are always one-dimensional but may be composed to form +multi-dimensional types. +

+ +
+[32]byte
+[2*N] struct { x, y int32 }
+[1000]*float64
+[3][5]int
+[2][2][2]float64  // same as [2]([2]([2]float64))
+
+ +

Slice types

+ +

+A slice is a descriptor for a contiguous segment of an underlying array and +provides access to a numbered sequence of elements from that array. +A slice type denotes the set of all slices of arrays of its element type. +The number of elements is called the length of the slice and is never negative. +The value of an uninitialized slice is nil. +

+ +
+SliceType = "[" "]" ElementType .
+
+ +

+The length of a slice s can be discovered by the built-in function +len; unlike with arrays it may change during +execution. The elements can be addressed by integer indices +0 through len(s)-1. The slice index of a +given element may be less than the index of the same element in the +underlying array. +

+

+A slice, once initialized, is always associated with an underlying +array that holds its elements. A slice therefore shares storage +with its array and with other slices of the same array; by contrast, +distinct arrays always represent distinct storage. +

+

+The array underlying a slice may extend past the end of the slice. +The capacity is a measure of that extent: it is the sum of +the length of the slice and the length of the array beyond the slice; +a slice of length up to that capacity can be created by +slicing a new one from the original slice. +The capacity of a slice a can be discovered using the +built-in function cap(a). +

+ +

+A new, initialized slice value for a given element type T is +made using the built-in function +make, +which takes a slice type +and parameters specifying the length and optionally the capacity. +A slice created with make always allocates a new, hidden array +to which the returned slice value refers. That is, executing +

+ +
+make([]T, length, capacity)
+
+ +

+produces the same slice as allocating an array and slicing +it, so these two expressions are equivalent: +

+ +
+make([]int, 50, 100)
+new([100]int)[0:50]
+
+ +

+Like arrays, slices are always one-dimensional but may be composed to construct +higher-dimensional objects. +With arrays of arrays, the inner arrays are, by construction, always the same length; +however with slices of slices (or arrays of slices), the inner lengths may vary dynamically. +Moreover, the inner slices must be initialized individually. +

+ +

Struct types

+ +

+A struct is a sequence of named elements, called fields, each of which has a +name and a type. Field names may be specified explicitly (IdentifierList) or +implicitly (EmbeddedField). +Within a struct, non-blank field names must +be unique. +

+ +
+StructType    = "struct" "{" { FieldDecl ";" } "}" .
+FieldDecl     = (IdentifierList Type | EmbeddedField) [ Tag ] .
+EmbeddedField = [ "*" ] TypeName .
+Tag           = string_lit .
+
+ +
+// An empty struct.
+struct {}
+
+// A struct with 6 fields.
+struct {
+	x, y int
+	u float32
+	_ float32  // padding
+	A *[]int
+	F func()
+}
+
+ +

+A field declared with a type but no explicit field name is called an embedded field. +An embedded field must be specified as +a type name T or as a pointer to a non-interface type name *T, +and T itself may not be +a pointer type. The unqualified type name acts as the field name. +

+ +
+// A struct with four embedded fields of types T1, *T2, P.T3 and *P.T4
+struct {
+	T1        // field name is T1
+	*T2       // field name is T2
+	P.T3      // field name is T3
+	*P.T4     // field name is T4
+	x, y int  // field names are x and y
+}
+
+ +

+The following declaration is illegal because field names must be unique +in a struct type: +

+ +
+struct {
+	T     // conflicts with embedded field *T and *P.T
+	*T    // conflicts with embedded field T and *P.T
+	*P.T  // conflicts with embedded field T and *T
+}
+
+ +

+A field or method f of an +embedded field in a struct x is called promoted if +x.f is a legal selector that denotes +that field or method f. +

+ +

+Promoted fields act like ordinary fields +of a struct except that they cannot be used as field names in +composite literals of the struct. +

+ +

+Given a struct type S and a defined type +T, promoted methods are included in the method set of the struct as follows: +

+
    +
  • + If S contains an embedded field T, + the method sets of S + and *S both include promoted methods with receiver + T. The method set of *S also + includes promoted methods with receiver *T. +
  • + +
  • + If S contains an embedded field *T, + the method sets of S and *S both + include promoted methods with receiver T or + *T. +
  • +
+ +

+A field declaration may be followed by an optional string literal tag, +which becomes an attribute for all the fields in the corresponding +field declaration. An empty tag string is equivalent to an absent tag. +The tags are made visible through a reflection interface +and take part in type identity for structs +but are otherwise ignored. +

+ +
+struct {
+	x, y float64 ""  // an empty tag string is like an absent tag
+	name string  "any string is permitted as a tag"
+	_    [4]byte "ceci n'est pas un champ de structure"
+}
+
+// A struct corresponding to a TimeStamp protocol buffer.
+// The tag strings define the protocol buffer field numbers;
+// they follow the convention outlined by the reflect package.
+struct {
+	microsec  uint64 `protobuf:"1"`
+	serverIP6 uint64 `protobuf:"2"`
+}
+
+ +

Pointer types

+ +

+A pointer type denotes the set of all pointers to variables of a given +type, called the base type of the pointer. +The value of an uninitialized pointer is nil. +

+ +
+PointerType = "*" BaseType .
+BaseType    = Type .
+
+ +
+*Point
+*[4]int
+
+ +

Function types

+ +

+A function type denotes the set of all functions with the same parameter +and result types. The value of an uninitialized variable of function type +is nil. +

+ +
+FunctionType   = "func" Signature .
+Signature      = Parameters [ Result ] .
+Result         = Parameters | Type .
+Parameters     = "(" [ ParameterList [ "," ] ] ")" .
+ParameterList  = ParameterDecl { "," ParameterDecl } .
+ParameterDecl  = [ IdentifierList ] [ "..." ] Type .
+
+ +

+Within a list of parameters or results, the names (IdentifierList) +must either all be present or all be absent. If present, each name +stands for one item (parameter or result) of the specified type and +all non-blank names in the signature +must be unique. +If absent, each type stands for one item of that type. +Parameter and result +lists are always parenthesized except that if there is exactly +one unnamed result it may be written as an unparenthesized type. +

+ +

+The final incoming parameter in a function signature may have +a type prefixed with .... +A function with such a parameter is called variadic and +may be invoked with zero or more arguments for that parameter. +

+ +
+func()
+func(x int) int
+func(a, _ int, z float32) bool
+func(a, b int, z float32) (bool)
+func(prefix string, values ...int)
+func(a, b int, z float64, opt ...interface{}) (success bool)
+func(int, int, float64) (float64, *[]int)
+func(n int) func(p *T)
+
+ + +

Interface types

+ +

+An interface type specifies a method set called its interface. +A variable of interface type can store a value of any type with a method set +that is any superset of the interface. Such a type is said to +implement the interface. +The value of an uninitialized variable of interface type is nil. +

+ +
+InterfaceType      = "interface" "{" { ( MethodSpec | InterfaceTypeName ) ";" } "}" .
+MethodSpec         = MethodName Signature .
+MethodName         = identifier .
+InterfaceTypeName  = TypeName .
+
+ +

+An interface type may specify methods explicitly through method specifications, +or it may embed methods of other interfaces through interface type names. +

+ +
+// A simple File interface.
+interface {
+	Read([]byte) (int, error)
+	Write([]byte) (int, error)
+	Close() error
+}
+
+ +

+The name of each explicitly specified method must be unique +and not blank. +

+ +
+interface {
+	String() string
+	String() string  // illegal: String not unique
+	_(x int)         // illegal: method must have non-blank name
+}
+
+ +

+More than one type may implement an interface. +For instance, if two types S1 and S2 +have the method set +

+ +
+func (p T) Read(p []byte) (n int, err error)
+func (p T) Write(p []byte) (n int, err error)
+func (p T) Close() error
+
+ +

+(where T stands for either S1 or S2) +then the File interface is implemented by both S1 and +S2, regardless of what other methods +S1 and S2 may have or share. +

+ +

+A type implements any interface comprising any subset of its methods +and may therefore implement several distinct interfaces. For +instance, all types implement the empty interface: +

+ +
+interface{}
+
+ +

+Similarly, consider this interface specification, +which appears within a type declaration +to define an interface called Locker: +

+ +
+type Locker interface {
+	Lock()
+	Unlock()
+}
+
+ +

+If S1 and S2 also implement +

+ +
+func (p T) Lock() { … }
+func (p T) Unlock() { … }
+
+ +

+they implement the Locker interface as well +as the File interface. +

+ +

+An interface T may use a (possibly qualified) interface type +name E in place of a method specification. This is called +embedding interface E in T. +The method set of T is the union +of the method sets of T’s explicitly declared methods and of +T’s embedded interfaces. +

+ +
+type Reader interface {
+	Read(p []byte) (n int, err error)
+	Close() error
+}
+
+type Writer interface {
+	Write(p []byte) (n int, err error)
+	Close() error
+}
+
+// ReadWriter's methods are Read, Write, and Close.
+type ReadWriter interface {
+	Reader  // includes methods of Reader in ReadWriter's method set
+	Writer  // includes methods of Writer in ReadWriter's method set
+}
+
+ +

+A union of method sets contains the (exported and non-exported) +methods of each method set exactly once, and methods with the +same names must +have identical signatures. +

+ +
+type ReadCloser interface {
+	Reader   // includes methods of Reader in ReadCloser's method set
+	Close()  // illegal: signatures of Reader.Close and Close are different
+}
+
+ +

+An interface type T may not embed itself +or any interface type that embeds T, recursively. +

+ +
+// illegal: Bad cannot embed itself
+type Bad interface {
+	Bad
+}
+
+// illegal: Bad1 cannot embed itself using Bad2
+type Bad1 interface {
+	Bad2
+}
+type Bad2 interface {
+	Bad1
+}
+
+ +

Map types

+ +

+A map is an unordered group of elements of one type, called the +element type, indexed by a set of unique keys of another type, +called the key type. +The value of an uninitialized map is nil. +

+ +
+MapType     = "map" "[" KeyType "]" ElementType .
+KeyType     = Type .
+
+ +

+The comparison operators +== and != must be fully defined +for operands of the key type; thus the key type must not be a function, map, or +slice. +If the key type is an interface type, these +comparison operators must be defined for the dynamic key values; +failure will cause a run-time panic. + +

+ +
+map[string]int
+map[*T]struct{ x, y float64 }
+map[string]interface{}
+
+ +

+The number of map elements is called its length. +For a map m, it can be discovered using the +built-in function len +and may change during execution. Elements may be added during execution +using assignments and retrieved with +index expressions; they may be removed with the +delete built-in function. +

+

+A new, empty map value is made using the built-in +function make, +which takes the map type and an optional capacity hint as arguments: +

+ +
+make(map[string]int)
+make(map[string]int, 100)
+
+ +

+The initial capacity does not bound its size: +maps grow to accommodate the number of items +stored in them, with the exception of nil maps. +A nil map is equivalent to an empty map except that no elements +may be added. + +

Channel types

+ +

+A channel provides a mechanism for +concurrently executing functions +to communicate by +sending and +receiving +values of a specified element type. +The value of an uninitialized channel is nil. +

+ +
+ChannelType = ( "chan" | "chan" "<-" | "<-" "chan" ) ElementType .
+
+ +

+The optional <- operator specifies the channel direction, +send or receive. If no direction is given, the channel is +bidirectional. +A channel may be constrained only to send or only to receive by +assignment or +explicit conversion. +

+ +
+chan T          // can be used to send and receive values of type T
+chan<- float64  // can only be used to send float64s
+<-chan int      // can only be used to receive ints
+
+ +

+The <- operator associates with the leftmost chan +possible: +

+ +
+chan<- chan int    // same as chan<- (chan int)
+chan<- <-chan int  // same as chan<- (<-chan int)
+<-chan <-chan int  // same as <-chan (<-chan int)
+chan (<-chan int)
+
+ +

+A new, initialized channel +value can be made using the built-in function +make, +which takes the channel type and an optional capacity as arguments: +

+ +
+make(chan int, 100)
+
+ +

+The capacity, in number of elements, sets the size of the buffer in the channel. +If the capacity is zero or absent, the channel is unbuffered and communication +succeeds only when both a sender and receiver are ready. Otherwise, the channel +is buffered and communication succeeds without blocking if the buffer +is not full (sends) or not empty (receives). +A nil channel is never ready for communication. +

+ +

+A channel may be closed with the built-in function +close. +The multi-valued assignment form of the +receive operator +reports whether a received value was sent before +the channel was closed. +

+ +

+A single channel may be used in +send statements, +receive operations, +and calls to the built-in functions +cap and +len +by any number of goroutines without further synchronization. +Channels act as first-in-first-out queues. +For example, if one goroutine sends values on a channel +and a second goroutine receives them, the values are +received in the order sent. +

+ +

Properties of types and values

+ +

Type identity

+ +

+Two types are either identical or different. +

+ +

+A defined type is always different from any other type. +Otherwise, two types are identical if their underlying type literals are +structurally equivalent; that is, they have the same literal structure and corresponding +components have identical types. In detail: +

+ +
    +
  • Two array types are identical if they have identical element types and + the same array length.
  • + +
  • Two slice types are identical if they have identical element types.
  • + +
  • Two struct types are identical if they have the same sequence of fields, + and if corresponding fields have the same names, and identical types, + and identical tags. + Non-exported field names from different + packages are always different.
  • + +
  • Two pointer types are identical if they have identical base types.
  • + +
  • Two function types are identical if they have the same number of parameters + and result values, corresponding parameter and result types are + identical, and either both functions are variadic or neither is. + Parameter and result names are not required to match.
  • + +
  • Two interface types are identical if they have the same set of methods + with the same names and identical function types. + Non-exported method names from different + packages are always different. The order of the methods is irrelevant.
  • + +
  • Two map types are identical if they have identical key and element types.
  • + +
  • Two channel types are identical if they have identical element types and + the same direction.
  • +
+ +

+Given the declarations +

+ +
+type (
+	A0 = []string
+	A1 = A0
+	A2 = struct{ a, b int }
+	A3 = int
+	A4 = func(A3, float64) *A0
+	A5 = func(x int, _ float64) *[]string
+)
+
+type (
+	B0 A0
+	B1 []string
+	B2 struct{ a, b int }
+	B3 struct{ a, c int }
+	B4 func(int, float64) *B0
+	B5 func(x int, y float64) *A1
+)
+
+type	C0 = B0
+
+ +

+these types are identical: +

+ +
+A0, A1, and []string
+A2 and struct{ a, b int }
+A3 and int
+A4, func(int, float64) *[]string, and A5
+
+B0 and C0
+[]int and []int
+struct{ a, b *T5 } and struct{ a, b *T5 }
+func(x int, y float64) *[]string, func(int, float64) (result *[]string), and A5
+
+ +

+B0 and B1 are different because they are new types +created by distinct type definitions; +func(int, float64) *B0 and func(x int, y float64) *[]string +are different because B0 is different from []string. +

+ + +

Assignability

+ +

+A value x is assignable to a variable of type T +("x is assignable to T") if one of the following conditions applies: +

+ +
    +
  • +x's type is identical to T. +
  • +
  • +x's type V and T have identical +underlying types and at least one of V +or T is not a defined type. +
  • +
  • +T is an interface type and +x implements T. +
  • +
  • +x is a bidirectional channel value, T is a channel type, +x's type V and T have identical element types, +and at least one of V or T is not a defined type. +
  • +
  • +x is the predeclared identifier nil and T +is a pointer, function, slice, map, channel, or interface type. +
  • +
  • +x is an untyped constant +representable +by a value of type T. +
  • +
+ + +

Representability

+ +

+A constant x is representable +by a value of type T if one of the following conditions applies: +

+ +
    +
  • +x is in the set of values determined by T. +
  • + +
  • +T is a floating-point type and x can be rounded to T's +precision without overflow. Rounding uses IEEE 754 round-to-even rules but with an IEEE +negative zero further simplified to an unsigned zero. Note that constant values never result +in an IEEE negative zero, NaN, or infinity. +
  • + +
  • +T is a complex type, and x's +components real(x) and imag(x) +are representable by values of T's component type (float32 or +float64). +
  • +
+ +
+x                   T           x is representable by a value of T because
+
+'a'                 byte        97 is in the set of byte values
+97                  rune        rune is an alias for int32, and 97 is in the set of 32-bit integers
+"foo"               string      "foo" is in the set of string values
+1024                int16       1024 is in the set of 16-bit integers
+42.0                byte        42 is in the set of unsigned 8-bit integers
+1e10                uint64      10000000000 is in the set of unsigned 64-bit integers
+2.718281828459045   float32     2.718281828459045 rounds to 2.7182817 which is in the set of float32 values
+-1e-1000            float64     -1e-1000 rounds to IEEE -0.0 which is further simplified to 0.0
+0i                  int         0 is an integer value
+(42 + 0i)           float32     42.0 (with zero imaginary part) is in the set of float32 values
+
+ +
+x                   T           x is not representable by a value of T because
+
+0                   bool        0 is not in the set of boolean values
+'a'                 string      'a' is a rune, it is not in the set of string values
+1024                byte        1024 is not in the set of unsigned 8-bit integers
+-1                  uint16      -1 is not in the set of unsigned 16-bit integers
+1.1                 int         1.1 is not an integer value
+42i                 float32     (0 + 42i) is not in the set of float32 values
+1e1000              float64     1e1000 overflows to IEEE +Inf after rounding
+
+ + +

Blocks

+ +

+A block is a possibly empty sequence of declarations and statements +within matching brace brackets. +

+ +
+Block = "{" StatementList "}" .
+StatementList = { Statement ";" } .
+
+ +

+In addition to explicit blocks in the source code, there are implicit blocks: +

+ +
    +
  1. The universe block encompasses all Go source text.
  2. + +
  3. Each package has a package block containing all + Go source text for that package.
  4. + +
  5. Each file has a file block containing all Go source text + in that file.
  6. + +
  7. Each "if", + "for", and + "switch" + statement is considered to be in its own implicit block.
  8. + +
  9. Each clause in a "switch" + or "select" statement + acts as an implicit block.
  10. +
+ +

+Blocks nest and influence scoping. +

+ + +

Declarations and scope

+ +

+A declaration binds a non-blank identifier to a +constant, +type, +variable, +function, +label, or +package. +Every identifier in a program must be declared. +No identifier may be declared twice in the same block, and +no identifier may be declared in both the file and package block. +

+ +

+The blank identifier may be used like any other identifier +in a declaration, but it does not introduce a binding and thus is not declared. +In the package block, the identifier init may only be used for +init function declarations, +and like the blank identifier it does not introduce a new binding. +

+ +
+Declaration   = ConstDecl | TypeDecl | VarDecl .
+TopLevelDecl  = Declaration | FunctionDecl | MethodDecl .
+
+ +

+The scope of a declared identifier is the extent of source text in which +the identifier denotes the specified constant, type, variable, function, label, or package. +

+ +

+Go is lexically scoped using blocks: +

+ +
    +
  1. The scope of a predeclared identifier is the universe block.
  2. + +
  3. The scope of an identifier denoting a constant, type, variable, + or function (but not method) declared at top level (outside any + function) is the package block.
  4. + +
  5. The scope of the package name of an imported package is the file block + of the file containing the import declaration.
  6. + +
  7. The scope of an identifier denoting a method receiver, function parameter, + or result variable is the function body.
  8. + +
  9. The scope of a constant or variable identifier declared + inside a function begins at the end of the ConstSpec or VarSpec + (ShortVarDecl for short variable declarations) + and ends at the end of the innermost containing block.
  10. + +
  11. The scope of a type identifier declared inside a function + begins at the identifier in the TypeSpec + and ends at the end of the innermost containing block.
  12. +
+ +

+An identifier declared in a block may be redeclared in an inner block. +While the identifier of the inner declaration is in scope, it denotes +the entity declared by the inner declaration. +

+ +

+The package clause is not a declaration; the package name +does not appear in any scope. Its purpose is to identify the files belonging +to the same package and to specify the default package name for import +declarations. +

+ + +

Label scopes

+ +

+Labels are declared by labeled statements and are +used in the "break", +"continue", and +"goto" statements. +It is illegal to define a label that is never used. +In contrast to other identifiers, labels are not block scoped and do +not conflict with identifiers that are not labels. The scope of a label +is the body of the function in which it is declared and excludes +the body of any nested function. +

+ + +

Blank identifier

+ +

+The blank identifier is represented by the underscore character _. +It serves as an anonymous placeholder instead of a regular (non-blank) +identifier and has special meaning in declarations, +as an operand, and in assignments. +

+ + +

Predeclared identifiers

+ +

+The following identifiers are implicitly declared in the +universe block: +

+
+Types:
+	bool byte complex64 complex128 error float32 float64
+	int int8 int16 int32 int64 rune string
+	uint uint8 uint16 uint32 uint64 uintptr
+
+Constants:
+	true false iota
+
+Zero value:
+	nil
+
+Functions:
+	append cap close complex copy delete imag len
+	make new panic print println real recover
+
+ + +

Exported identifiers

+ +

+An identifier may be exported to permit access to it from another package. +An identifier is exported if both: +

+
    +
  1. the first character of the identifier's name is a Unicode upper case + letter (Unicode class "Lu"); and
  2. +
  3. the identifier is declared in the package block + or it is a field name or + method name.
  4. +
+

+All other identifiers are not exported. +

+ + +

Uniqueness of identifiers

+ +

+Given a set of identifiers, an identifier is called unique if it is +different from every other in the set. +Two identifiers are different if they are spelled differently, or if they +appear in different packages and are not +exported. Otherwise, they are the same. +

+ +

Constant declarations

+ +

+A constant declaration binds a list of identifiers (the names of +the constants) to the values of a list of constant expressions. +The number of identifiers must be equal +to the number of expressions, and the nth identifier on +the left is bound to the value of the nth expression on the +right. +

+ +
+ConstDecl      = "const" ( ConstSpec | "(" { ConstSpec ";" } ")" ) .
+ConstSpec      = IdentifierList [ [ Type ] "=" ExpressionList ] .
+
+IdentifierList = identifier { "," identifier } .
+ExpressionList = Expression { "," Expression } .
+
+ +

+If the type is present, all constants take the type specified, and +the expressions must be assignable to that type. +If the type is omitted, the constants take the +individual types of the corresponding expressions. +If the expression values are untyped constants, +the declared constants remain untyped and the constant identifiers +denote the constant values. For instance, if the expression is a +floating-point literal, the constant identifier denotes a floating-point +constant, even if the literal's fractional part is zero. +

+ +
+const Pi float64 = 3.14159265358979323846
+const zero = 0.0         // untyped floating-point constant
+const (
+	size int64 = 1024
+	eof        = -1  // untyped integer constant
+)
+const a, b, c = 3, 4, "foo"  // a = 3, b = 4, c = "foo", untyped integer and string constants
+const u, v float32 = 0, 3    // u = 0.0, v = 3.0
+
+ +

+Within a parenthesized const declaration list the +expression list may be omitted from any but the first ConstSpec. +Such an empty list is equivalent to the textual substitution of the +first preceding non-empty expression list and its type if any. +Omitting the list of expressions is therefore equivalent to +repeating the previous list. The number of identifiers must be equal +to the number of expressions in the previous list. +Together with the iota constant generator +this mechanism permits light-weight declaration of sequential values: +

+ +
+const (
+	Sunday = iota
+	Monday
+	Tuesday
+	Wednesday
+	Thursday
+	Friday
+	Partyday
+	numberOfDays  // this constant is not exported
+)
+
+ + +

Iota

+ +

+Within a constant declaration, the predeclared identifier +iota represents successive untyped integer +constants. Its value is the index of the respective ConstSpec +in that constant declaration, starting at zero. +It can be used to construct a set of related constants: +

+ +
+const (
+	c0 = iota  // c0 == 0
+	c1 = iota  // c1 == 1
+	c2 = iota  // c2 == 2
+)
+
+const (
+	a = 1 << iota  // a == 1  (iota == 0)
+	b = 1 << iota  // b == 2  (iota == 1)
+	c = 3          // c == 3  (iota == 2, unused)
+	d = 1 << iota  // d == 8  (iota == 3)
+)
+
+const (
+	u         = iota * 42  // u == 0     (untyped integer constant)
+	v float64 = iota * 42  // v == 42.0  (float64 constant)
+	w         = iota * 42  // w == 84    (untyped integer constant)
+)
+
+const x = iota  // x == 0
+const y = iota  // y == 0
+
+ +

+By definition, multiple uses of iota in the same ConstSpec all have the same value: +

+ +
+const (
+	bit0, mask0 = 1 << iota, 1<<iota - 1  // bit0 == 1, mask0 == 0  (iota == 0)
+	bit1, mask1                           // bit1 == 2, mask1 == 1  (iota == 1)
+	_, _                                  //                        (iota == 2, unused)
+	bit3, mask3                           // bit3 == 8, mask3 == 7  (iota == 3)
+)
+
+ +

+This last example exploits the implicit repetition +of the last non-empty expression list. +

+ + +

Type declarations

+ +

+A type declaration binds an identifier, the type name, to a type. +Type declarations come in two forms: alias declarations and type definitions. +

+ +
+TypeDecl = "type" ( TypeSpec | "(" { TypeSpec ";" } ")" ) .
+TypeSpec = AliasDecl | TypeDef .
+
+ +

Alias declarations

+ +

+An alias declaration binds an identifier to the given type. +

+ +
+AliasDecl = identifier "=" Type .
+
+ +

+Within the scope of +the identifier, it serves as an alias for the type. +

+ +
+type (
+	nodeList = []*Node  // nodeList and []*Node are identical types
+	Polar    = polar    // Polar and polar denote identical types
+)
+
+ + +

Type definitions

+ +

+A type definition creates a new, distinct type with the same +underlying type and operations as the given type, +and binds an identifier to it. +

+ +
+TypeDef = identifier Type .
+
+ +

+The new type is called a defined type. +It is different from any other type, +including the type it is created from. +

+ +
+type (
+	Point struct{ x, y float64 }  // Point and struct{ x, y float64 } are different types
+	polar Point                   // polar and Point denote different types
+)
+
+type TreeNode struct {
+	left, right *TreeNode
+	value *Comparable
+}
+
+type Block interface {
+	BlockSize() int
+	Encrypt(src, dst []byte)
+	Decrypt(src, dst []byte)
+}
+
+ +

+A defined type may have methods associated with it. +It does not inherit any methods bound to the given type, +but the method set +of an interface type or of elements of a composite type remains unchanged: +

+ +
+// A Mutex is a data type with two methods, Lock and Unlock.
+type Mutex struct         { /* Mutex fields */ }
+func (m *Mutex) Lock()    { /* Lock implementation */ }
+func (m *Mutex) Unlock()  { /* Unlock implementation */ }
+
+// NewMutex has the same composition as Mutex but its method set is empty.
+type NewMutex Mutex
+
+// The method set of PtrMutex's underlying type *Mutex remains unchanged,
+// but the method set of PtrMutex is empty.
+type PtrMutex *Mutex
+
+// The method set of *PrintableMutex contains the methods
+// Lock and Unlock bound to its embedded field Mutex.
+type PrintableMutex struct {
+	Mutex
+}
+
+// MyBlock is an interface type that has the same method set as Block.
+type MyBlock Block
+
+ +

+Type definitions may be used to define different boolean, numeric, +or string types and associate methods with them: +

+ +
+type TimeZone int
+
+const (
+	EST TimeZone = -(5 + iota)
+	CST
+	MST
+	PST
+)
+
+func (tz TimeZone) String() string {
+	return fmt.Sprintf("GMT%+dh", tz)
+}
+
+ + +

Variable declarations

+ +

+A variable declaration creates one or more variables, +binds corresponding identifiers to them, and gives each a type and an initial value. +

+ +
+VarDecl     = "var" ( VarSpec | "(" { VarSpec ";" } ")" ) .
+VarSpec     = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) .
+
+ +
+var i int
+var U, V, W float64
+var k = 0
+var x, y float32 = -1, -2
+var (
+	i       int
+	u, v, s = 2.0, 3.0, "bar"
+)
+var re, im = complexSqrt(-1)
+var _, found = entries[name]  // map lookup; only interested in "found"
+
+ +

+If a list of expressions is given, the variables are initialized +with the expressions following the rules for assignments. +Otherwise, each variable is initialized to its zero value. +

+ +

+If a type is present, each variable is given that type. +Otherwise, each variable is given the type of the corresponding +initialization value in the assignment. +If that value is an untyped constant, it is first implicitly +converted to its default type; +if it is an untyped boolean value, it is first implicitly converted to type bool. +The predeclared value nil cannot be used to initialize a variable +with no explicit type. +

+ +
+var d = math.Sin(0.5)  // d is float64
+var i = 42             // i is int
+var t, ok = x.(T)      // t is T, ok is bool
+var n = nil            // illegal
+
+ +

+Implementation restriction: A compiler may make it illegal to declare a variable +inside a function body if the variable is +never used. +

+ +

Short variable declarations

+ +

+A short variable declaration uses the syntax: +

+ +
+ShortVarDecl = IdentifierList ":=" ExpressionList .
+
+ +

+It is shorthand for a regular variable declaration +with initializer expressions but no types: +

+ +
+"var" IdentifierList = ExpressionList .
+
+ +
+i, j := 0, 10
+f := func() int { return 7 }
+ch := make(chan int)
+r, w, _ := os.Pipe()  // os.Pipe() returns a connected pair of Files and an error, if any
+_, y, _ := coord(p)   // coord() returns three values; only interested in y coordinate
+
+ +

+Unlike regular variable declarations, a short variable declaration may redeclare +variables provided they were originally declared earlier in the same block +(or the parameter lists if the block is the function body) with the same type, +and at least one of the non-blank variables is new. +As a consequence, redeclaration can only appear in a multi-variable short declaration. +Redeclaration does not introduce a new variable; it just assigns a new value to the original. +

+ +
+field1, offset := nextField(str, 0)
+field2, offset := nextField(str, offset)  // redeclares offset
+a, a := 1, 2                              // illegal: double declaration of a or no new variable if a was declared elsewhere
+
+ +

+Short variable declarations may appear only inside functions. +In some contexts such as the initializers for +"if", +"for", or +"switch" statements, +they can be used to declare local temporary variables. +

+ +

Function declarations

+ +

+A function declaration binds an identifier, the function name, +to a function. +

+ +
+FunctionDecl = "func" FunctionName Signature [ FunctionBody ] .
+FunctionName = identifier .
+FunctionBody = Block .
+
+ +

+If the function's signature declares +result parameters, the function body's statement list must end in +a terminating statement. +

+ +
+func IndexRune(s string, r rune) int {
+	for i, c := range s {
+		if c == r {
+			return i
+		}
+	}
+	// invalid: missing return statement
+}
+
+ +

+A function declaration may omit the body. Such a declaration provides the +signature for a function implemented outside Go, such as an assembly routine. +

+ +
+func min(x int, y int) int {
+	if x < y {
+		return x
+	}
+	return y
+}
+
+func flushICache(begin, end uintptr)  // implemented externally
+
+ +

Method declarations

+ +

+A method is a function with a receiver. +A method declaration binds an identifier, the method name, to a method, +and associates the method with the receiver's base type. +

+ +
+MethodDecl = "func" Receiver MethodName Signature [ FunctionBody ] .
+Receiver   = Parameters .
+
+ +

+The receiver is specified via an extra parameter section preceding the method +name. That parameter section must declare a single non-variadic parameter, the receiver. +Its type must be a defined type T or a +pointer to a defined type T. T is called the receiver +base type. A receiver base type cannot be a pointer or interface type and +it must be defined in the same package as the method. +The method is said to be bound to its receiver base type and the method name +is visible only within selectors for type T +or *T. +

+ +

+A non-blank receiver identifier must be +unique in the method signature. +If the receiver's value is not referenced inside the body of the method, +its identifier may be omitted in the declaration. The same applies in +general to parameters of functions and methods. +

+ +

+For a base type, the non-blank names of methods bound to it must be unique. +If the base type is a struct type, +the non-blank method and field names must be distinct. +

+ +

+Given defined type Point, the declarations +

+ +
+func (p *Point) Length() float64 {
+	return math.Sqrt(p.x * p.x + p.y * p.y)
+}
+
+func (p *Point) Scale(factor float64) {
+	p.x *= factor
+	p.y *= factor
+}
+
+ +

+bind the methods Length and Scale, +with receiver type *Point, +to the base type Point. +

+ +

+The type of a method is the type of a function with the receiver as first +argument. For instance, the method Scale has type +

+ +
+func(p *Point, factor float64)
+
+ +

+However, a function declared this way is not a method. +

+ + +

Expressions

+ +

+An expression specifies the computation of a value by applying +operators and functions to operands. +

+ +

Operands

+ +

+Operands denote the elementary values in an expression. An operand may be a +literal, a (possibly qualified) +non-blank identifier denoting a +constant, +variable, or +function, +or a parenthesized expression. +

+ +

+The blank identifier may appear as an +operand only on the left-hand side of an assignment. +

+ +
+Operand     = Literal | OperandName | "(" Expression ")" .
+Literal     = BasicLit | CompositeLit | FunctionLit .
+BasicLit    = int_lit | float_lit | imaginary_lit | rune_lit | string_lit .
+OperandName = identifier | QualifiedIdent .
+
+ +

Qualified identifiers

+ +

+A qualified identifier is an identifier qualified with a package name prefix. +Both the package name and the identifier must not be +blank. +

+ +
+QualifiedIdent = PackageName "." identifier .
+
+ +

+A qualified identifier accesses an identifier in a different package, which +must be imported. +The identifier must be exported and +declared in the package block of that package. +

+ +
+math.Sin	// denotes the Sin function in package math
+
+ +

Composite literals

+ +

+Composite literals construct values for structs, arrays, slices, and maps +and create a new value each time they are evaluated. +They consist of the type of the literal followed by a brace-bound list of elements. +Each element may optionally be preceded by a corresponding key. +

+ +
+CompositeLit  = LiteralType LiteralValue .
+LiteralType   = StructType | ArrayType | "[" "..." "]" ElementType |
+                SliceType | MapType | TypeName .
+LiteralValue  = "{" [ ElementList [ "," ] ] "}" .
+ElementList   = KeyedElement { "," KeyedElement } .
+KeyedElement  = [ Key ":" ] Element .
+Key           = FieldName | Expression | LiteralValue .
+FieldName     = identifier .
+Element       = Expression | LiteralValue .
+
+ +

+The LiteralType's underlying type must be a struct, array, slice, or map type +(the grammar enforces this constraint except when the type is given +as a TypeName). +The types of the elements and keys must be assignable +to the respective field, element, and key types of the literal type; +there is no additional conversion. +The key is interpreted as a field name for struct literals, +an index for array and slice literals, and a key for map literals. +For map literals, all elements must have a key. It is an error +to specify multiple elements with the same field name or +constant key value. For non-constant map keys, see the section on +evaluation order. +

+ +

+For struct literals the following rules apply: +

+
    +
  • A key must be a field name declared in the struct type. +
  • +
  • An element list that does not contain any keys must + list an element for each struct field in the + order in which the fields are declared. +
  • +
  • If any element has a key, every element must have a key. +
  • +
  • An element list that contains keys does not need to + have an element for each struct field. Omitted fields + get the zero value for that field. +
  • +
  • A literal may omit the element list; such a literal evaluates + to the zero value for its type. +
  • +
  • It is an error to specify an element for a non-exported + field of a struct belonging to a different package. +
  • +
+ +

+Given the declarations +

+
+type Point3D struct { x, y, z float64 }
+type Line struct { p, q Point3D }
+
+ +

+one may write +

+ +
+origin := Point3D{}                            // zero value for Point3D
+line := Line{origin, Point3D{y: -4, z: 12.3}}  // zero value for line.q.x
+
+ +

+For array and slice literals the following rules apply: +

+
    +
  • Each element has an associated integer index marking + its position in the array. +
  • +
  • An element with a key uses the key as its index. The + key must be a non-negative constant + representable by + a value of type int; and if it is typed + it must be of integer type. +
  • +
  • An element without a key uses the previous element's index plus one. + If the first element has no key, its index is zero. +
  • +
+ +

+Taking the address of a composite literal +generates a pointer to a unique variable initialized +with the literal's value. +

+ +
+var pointer *Point3D = &Point3D{y: 1000}
+
+ +

+Note that the zero value for a slice or map +type is not the same as an initialized but empty value of the same type. +Consequently, taking the address of an empty slice or map composite literal +does not have the same effect as allocating a new slice or map value with +new. +

+ +
+p1 := &[]int{}    // p1 points to an initialized, empty slice with value []int{} and length 0
+p2 := new([]int)  // p2 points to an uninitialized slice with value nil and length 0
+
+ +

+The length of an array literal is the length specified in the literal type. +If fewer elements than the length are provided in the literal, the missing +elements are set to the zero value for the array element type. +It is an error to provide elements with index values outside the index range +of the array. The notation ... specifies an array length equal +to the maximum element index plus one. +

+ +
+buffer := [10]string{}             // len(buffer) == 10
+intSet := [6]int{1, 2, 3, 5}       // len(intSet) == 6
+days := [...]string{"Sat", "Sun"}  // len(days) == 2
+
+ +

+A slice literal describes the entire underlying array literal. +Thus the length and capacity of a slice literal are the maximum +element index plus one. A slice literal has the form +

+ +
+[]T{x1, x2, … xn}
+
+ +

+and is shorthand for a slice operation applied to an array: +

+ +
+tmp := [n]T{x1, x2, … xn}
+tmp[0 : n]
+
+ +

+Within a composite literal of array, slice, or map type T, +elements or map keys that are themselves composite literals may elide the respective +literal type if it is identical to the element or key type of T. +Similarly, elements or keys that are addresses of composite literals may elide +the &T when the element or key type is *T. +

+ +
+[...]Point{{1.5, -3.5}, {0, 0}}     // same as [...]Point{Point{1.5, -3.5}, Point{0, 0}}
+[][]int{{1, 2, 3}, {4, 5}}          // same as [][]int{[]int{1, 2, 3}, []int{4, 5}}
+[][]Point{{{0, 1}, {1, 2}}}         // same as [][]Point{[]Point{Point{0, 1}, Point{1, 2}}}
+map[string]Point{"orig": {0, 0}}    // same as map[string]Point{"orig": Point{0, 0}}
+map[Point]string{{0, 0}: "orig"}    // same as map[Point]string{Point{0, 0}: "orig"}
+
+type PPoint *Point
+[2]*Point{{1.5, -3.5}, {}}          // same as [2]*Point{&Point{1.5, -3.5}, &Point{}}
+[2]PPoint{{1.5, -3.5}, {}}          // same as [2]PPoint{PPoint(&Point{1.5, -3.5}), PPoint(&Point{})}
+
+ +

+A parsing ambiguity arises when a composite literal using the +TypeName form of the LiteralType appears as an operand between the +keyword and the opening brace of the block +of an "if", "for", or "switch" statement, and the composite literal +is not enclosed in parentheses, square brackets, or curly braces. +In this rare case, the opening brace of the literal is erroneously parsed +as the one introducing the block of statements. To resolve the ambiguity, +the composite literal must appear within parentheses. +

+ +
+if x == (T{a,b,c}[i]) { … }
+if (x == T{a,b,c}[i]) { … }
+
+ +

+Examples of valid array, slice, and map literals: +

+ +
+// list of prime numbers
+primes := []int{2, 3, 5, 7, 9, 2147483647}
+
+// vowels[ch] is true if ch is a vowel
+vowels := [128]bool{'a': true, 'e': true, 'i': true, 'o': true, 'u': true, 'y': true}
+
+// the array [10]float32{-1, 0, 0, 0, -0.1, -0.1, 0, 0, 0, -1}
+filter := [10]float32{-1, 4: -0.1, -0.1, 9: -1}
+
+// frequencies in Hz for equal-tempered scale (A4 = 440Hz)
+noteFrequency := map[string]float32{
+	"C0": 16.35, "D0": 18.35, "E0": 20.60, "F0": 21.83,
+	"G0": 24.50, "A0": 27.50, "B0": 30.87,
+}
+
+ + +

Function literals

+ +

+A function literal represents an anonymous function. +

+ +
+FunctionLit = "func" Signature FunctionBody .
+
+ +
+func(a, b int, z float64) bool { return a*b < int(z) }
+
+ +

+A function literal can be assigned to a variable or invoked directly. +

+ +
+f := func(x, y int) int { return x + y }
+func(ch chan int) { ch <- ACK }(replyChan)
+
+ +

+Function literals are closures: they may refer to variables +defined in a surrounding function. Those variables are then shared between +the surrounding function and the function literal, and they survive as long +as they are accessible. +

+ + +

Primary expressions

+ +

+Primary expressions are the operands for unary and binary expressions. +

+ +
+PrimaryExpr =
+	Operand |
+	Conversion |
+	MethodExpr |
+	PrimaryExpr Selector |
+	PrimaryExpr Index |
+	PrimaryExpr Slice |
+	PrimaryExpr TypeAssertion |
+	PrimaryExpr Arguments .
+
+Selector       = "." identifier .
+Index          = "[" Expression "]" .
+Slice          = "[" [ Expression ] ":" [ Expression ] "]" |
+                 "[" [ Expression ] ":" Expression ":" Expression "]" .
+TypeAssertion  = "." "(" Type ")" .
+Arguments      = "(" [ ( ExpressionList | Type [ "," ExpressionList ] ) [ "..." ] [ "," ] ] ")" .
+
+ + +
+x
+2
+(s + ".txt")
+f(3.1415, true)
+Point{1, 2}
+m["foo"]
+s[i : j + 1]
+obj.color
+f.p[i].x()
+
+ + +

Selectors

+ +

+For a primary expression x +that is not a package name, the +selector expression +

+ +
+x.f
+
+ +

+denotes the field or method f of the value x +(or sometimes *x; see below). +The identifier f is called the (field or method) selector; +it must not be the blank identifier. +The type of the selector expression is the type of f. +If x is a package name, see the section on +qualified identifiers. +

+ +

+A selector f may denote a field or method f of +a type T, or it may refer +to a field or method f of a nested +embedded field of T. +The number of embedded fields traversed +to reach f is called its depth in T. +The depth of a field or method f +declared in T is zero. +The depth of a field or method f declared in +an embedded field A in T is the +depth of f in A plus one. +

+ +

+The following rules apply to selectors: +

+ +
    +
  1. +For a value x of type T or *T +where T is not a pointer or interface type, +x.f denotes the field or method at the shallowest depth +in T where there +is such an f. +If there is not exactly one f +with shallowest depth, the selector expression is illegal. +
  2. + +
  3. +For a value x of type I where I +is an interface type, x.f denotes the actual method with name +f of the dynamic value of x. +If there is no method with name f in the +method set of I, the selector +expression is illegal. +
  4. + +
  5. +As an exception, if the type of x is a defined +pointer type and (*x).f is a valid selector expression denoting a field +(but not a method), x.f is shorthand for (*x).f. +
  6. + +
  7. +In all other cases, x.f is illegal. +
  8. + +
  9. +If x is of pointer type and has the value +nil and x.f denotes a struct field, +assigning to or evaluating x.f +causes a run-time panic. +
  10. + +
  11. +If x is of interface type and has the value +nil, calling or +evaluating the method x.f +causes a run-time panic. +
  12. +
+ +

+For example, given the declarations: +

+ +
+type T0 struct {
+	x int
+}
+
+func (*T0) M0()
+
+type T1 struct {
+	y int
+}
+
+func (T1) M1()
+
+type T2 struct {
+	z int
+	T1
+	*T0
+}
+
+func (*T2) M2()
+
+type Q *T2
+
+var t T2     // with t.T0 != nil
+var p *T2    // with p != nil and (*p).T0 != nil
+var q Q = p
+
+ +

+one may write: +

+ +
+t.z          // t.z
+t.y          // t.T1.y
+t.x          // (*t.T0).x
+
+p.z          // (*p).z
+p.y          // (*p).T1.y
+p.x          // (*(*p).T0).x
+
+q.x          // (*(*q).T0).x        (*q).x is a valid field selector
+
+p.M0()       // ((*p).T0).M0()      M0 expects *T0 receiver
+p.M1()       // ((*p).T1).M1()      M1 expects T1 receiver
+p.M2()       // p.M2()              M2 expects *T2 receiver
+t.M2()       // (&t).M2()           M2 expects *T2 receiver, see section on Calls
+
+ +

+but the following is invalid: +

+ +
+q.M0()       // (*q).M0 is valid but not a field selector
+
+ + +

Method expressions

+ +

+If M is in the method set of type T, +T.M is a function that is callable as a regular function +with the same arguments as M prefixed by an additional +argument that is the receiver of the method. +

+ +
+MethodExpr    = ReceiverType "." MethodName .
+ReceiverType  = Type .
+
+ +

+Consider a struct type T with two methods, +Mv, whose receiver is of type T, and +Mp, whose receiver is of type *T. +

+ +
+type T struct {
+	a int
+}
+func (tv  T) Mv(a int) int         { return 0 }  // value receiver
+func (tp *T) Mp(f float32) float32 { return 1 }  // pointer receiver
+
+var t T
+
+ +

+The expression +

+ +
+T.Mv
+
+ +

+yields a function equivalent to Mv but +with an explicit receiver as its first argument; it has signature +

+ +
+func(tv T, a int) int
+
+ +

+That function may be called normally with an explicit receiver, so +these five invocations are equivalent: +

+ +
+t.Mv(7)
+T.Mv(t, 7)
+(T).Mv(t, 7)
+f1 := T.Mv; f1(t, 7)
+f2 := (T).Mv; f2(t, 7)
+
+ +

+Similarly, the expression +

+ +
+(*T).Mp
+
+ +

+yields a function value representing Mp with signature +

+ +
+func(tp *T, f float32) float32
+
+ +

+For a method with a value receiver, one can derive a function +with an explicit pointer receiver, so +

+ +
+(*T).Mv
+
+ +

+yields a function value representing Mv with signature +

+ +
+func(tv *T, a int) int
+
+ +

+Such a function indirects through the receiver to create a value +to pass as the receiver to the underlying method; +the method does not overwrite the value whose address is passed in +the function call. +

+ +

+The final case, a value-receiver function for a pointer-receiver method, +is illegal because pointer-receiver methods are not in the method set +of the value type. +

+ +

+Function values derived from methods are called with function call syntax; +the receiver is provided as the first argument to the call. +That is, given f := T.Mv, f is invoked +as f(t, 7) not t.f(7). +To construct a function that binds the receiver, use a +function literal or +method value. +

+ +

+It is legal to derive a function value from a method of an interface type. +The resulting function takes an explicit receiver of that interface type. +

+ +

Method values

+ +

+If the expression x has static type T and +M is in the method set of type T, +x.M is called a method value. +The method value x.M is a function value that is callable +with the same arguments as a method call of x.M. +The expression x is evaluated and saved during the evaluation of the +method value; the saved copy is then used as the receiver in any calls, +which may be executed later. +

+ +
+type S struct { *T }
+type T int
+func (t T) M() { print(t) }
+
+t := new(T)
+s := S{T: t}
+f := t.M                    // receiver *t is evaluated and stored in f
+g := s.M                    // receiver *(s.T) is evaluated and stored in g
+*t = 42                     // does not affect stored receivers in f and g
+
+ +

+The type T may be an interface or non-interface type. +

+ +

+As in the discussion of method expressions above, +consider a struct type T with two methods, +Mv, whose receiver is of type T, and +Mp, whose receiver is of type *T. +

+ +
+type T struct {
+	a int
+}
+func (tv  T) Mv(a int) int         { return 0 }  // value receiver
+func (tp *T) Mp(f float32) float32 { return 1 }  // pointer receiver
+
+var t T
+var pt *T
+func makeT() T
+
+ +

+The expression +

+ +
+t.Mv
+
+ +

+yields a function value of type +

+ +
+func(int) int
+
+ +

+These two invocations are equivalent: +

+ +
+t.Mv(7)
+f := t.Mv; f(7)
+
+ +

+Similarly, the expression +

+ +
+pt.Mp
+
+ +

+yields a function value of type +

+ +
+func(float32) float32
+
+ +

+As with selectors, a reference to a non-interface method with a value receiver +using a pointer will automatically dereference that pointer: pt.Mv is equivalent to (*pt).Mv. +

+ +

+As with method calls, a reference to a non-interface method with a pointer receiver +using an addressable value will automatically take the address of that value: t.Mp is equivalent to (&t).Mp. +

+ +
+f := t.Mv; f(7)   // like t.Mv(7)
+f := pt.Mp; f(7)  // like pt.Mp(7)
+f := pt.Mv; f(7)  // like (*pt).Mv(7)
+f := t.Mp; f(7)   // like (&t).Mp(7)
+f := makeT().Mp   // invalid: result of makeT() is not addressable
+
+ +

+Although the examples above use non-interface types, it is also legal to create a method value +from a value of interface type. +

+ +
+var i interface { M(int) } = myVal
+f := i.M; f(7)  // like i.M(7)
+
+ + +

Index expressions

+ +

+A primary expression of the form +

+ +
+a[x]
+
+ +

+denotes the element of the array, pointer to array, slice, string or map a indexed by x. +The value x is called the index or map key, respectively. +The following rules apply: +

+ +

+If a is not a map: +

+
    +
  • the index x must be of integer type or an untyped constant
  • +
  • a constant index must be non-negative and + representable by a value of type int
  • +
  • a constant index that is untyped is given type int
  • +
  • the index x is in range if 0 <= x < len(a), + otherwise it is out of range
  • +
+ +

+For a of array type A: +

+
    +
  • a constant index must be in range
  • +
  • if x is out of range at run time, + a run-time panic occurs
  • +
  • a[x] is the array element at index x and the type of + a[x] is the element type of A
  • +
+ +

+For a of pointer to array type: +

+
    +
  • a[x] is shorthand for (*a)[x]
  • +
+ +

+For a of slice type S: +

+
    +
  • if x is out of range at run time, + a run-time panic occurs
  • +
  • a[x] is the slice element at index x and the type of + a[x] is the element type of S
  • +
+ +

+For a of string type: +

+
    +
  • a constant index must be in range + if the string a is also constant
  • +
  • if x is out of range at run time, + a run-time panic occurs
  • +
  • a[x] is the non-constant byte value at index x and the type of + a[x] is byte
  • +
  • a[x] may not be assigned to
  • +
+ +

+For a of map type M: +

+
    +
  • x's type must be + assignable + to the key type of M
  • +
  • if the map contains an entry with key x, + a[x] is the map element with key x + and the type of a[x] is the element type of M
  • +
  • if the map is nil or does not contain such an entry, + a[x] is the zero value + for the element type of M
  • +
+ +

+Otherwise a[x] is illegal. +

+ +

+An index expression on a map a of type map[K]V +used in an assignment or initialization of the special form +

+ +
+v, ok = a[x]
+v, ok := a[x]
+var v, ok = a[x]
+
+ +

+yields an additional untyped boolean value. The value of ok is +true if the key x is present in the map, and +false otherwise. +

+ +

+Assigning to an element of a nil map causes a +run-time panic. +

+ + +

Slice expressions

+ +

+Slice expressions construct a substring or slice from a string, array, pointer +to array, or slice. There are two variants: a simple form that specifies a low +and high bound, and a full form that also specifies a bound on the capacity. +

+ +

Simple slice expressions

+ +

+For a string, array, pointer to array, or slice a, the primary expression +

+ +
+a[low : high]
+
+ +

+constructs a substring or slice. The indices low and +high select which elements of operand a appear +in the result. The result has indices starting at 0 and length equal to +high - low. +After slicing the array a +

+ +
+a := [5]int{1, 2, 3, 4, 5}
+s := a[1:4]
+
+ +

+the slice s has type []int, length 3, capacity 4, and elements +

+ +
+s[0] == 2
+s[1] == 3
+s[2] == 4
+
+ +

+For convenience, any of the indices may be omitted. A missing low +index defaults to zero; a missing high index defaults to the length of the +sliced operand: +

+ +
+a[2:]  // same as a[2 : len(a)]
+a[:3]  // same as a[0 : 3]
+a[:]   // same as a[0 : len(a)]
+
+ +

+If a is a pointer to an array, a[low : high] is shorthand for +(*a)[low : high]. +

+ +

+For arrays or strings, the indices are in range if +0 <= low <= high <= len(a), +otherwise they are out of range. +For slices, the upper index bound is the slice capacity cap(a) rather than the length. +A constant index must be non-negative and +representable by a value of type +int; for arrays or constant strings, constant indices must also be in range. +If both indices are constant, they must satisfy low <= high. +If the indices are out of range at run time, a run-time panic occurs. +

+ +

+Except for untyped strings, if the sliced operand is a string or slice, +the result of the slice operation is a non-constant value of the same type as the operand. +For untyped string operands the result is a non-constant value of type string. +If the sliced operand is an array, it must be addressable +and the result of the slice operation is a slice with the same element type as the array. +

+ +

+If the sliced operand of a valid slice expression is a nil slice, the result +is a nil slice. Otherwise, if the result is a slice, it shares its underlying +array with the operand. +

+ +
+var a [10]int
+s1 := a[3:7]   // underlying array of s1 is array a; &s1[2] == &a[5]
+s2 := s1[1:4]  // underlying array of s2 is underlying array of s1 which is array a; &s2[1] == &a[5]
+s2[1] = 42     // s2[1] == s1[2] == a[5] == 42; they all refer to the same underlying array element
+
+ + +

Full slice expressions

+ +

+For an array, pointer to array, or slice a (but not a string), the primary expression +

+ +
+a[low : high : max]
+
+ +

+constructs a slice of the same type, and with the same length and elements as the simple slice +expression a[low : high]. Additionally, it controls the resulting slice's capacity +by setting it to max - low. Only the first index may be omitted; it defaults to 0. +After slicing the array a +

+ +
+a := [5]int{1, 2, 3, 4, 5}
+t := a[1:3:5]
+
+ +

+the slice t has type []int, length 2, capacity 4, and elements +

+ +
+t[0] == 2
+t[1] == 3
+
+ +

+As for simple slice expressions, if a is a pointer to an array, +a[low : high : max] is shorthand for (*a)[low : high : max]. +If the sliced operand is an array, it must be addressable. +

+ +

+The indices are in range if 0 <= low <= high <= max <= cap(a), +otherwise they are out of range. +A constant index must be non-negative and +representable by a value of type +int; for arrays, constant indices must also be in range. +If multiple indices are constant, the constants that are present must be in range relative to each +other. +If the indices are out of range at run time, a run-time panic occurs. +

+ +

Type assertions

+ +

+For an expression x of interface type +and a type T, the primary expression +

+ +
+x.(T)
+
+ +

+asserts that x is not nil +and that the value stored in x is of type T. +The notation x.(T) is called a type assertion. +

+

+More precisely, if T is not an interface type, x.(T) asserts +that the dynamic type of x is identical +to the type T. +In this case, T must implement the (interface) type of x; +otherwise the type assertion is invalid since it is not possible for x +to store a value of type T. +If T is an interface type, x.(T) asserts that the dynamic type +of x implements the interface T. +

+

+If the type assertion holds, the value of the expression is the value +stored in x and its type is T. If the type assertion is false, +a run-time panic occurs. +In other words, even though the dynamic type of x +is known only at run time, the type of x.(T) is +known to be T in a correct program. +

+ +
+var x interface{} = 7          // x has dynamic type int and value 7
+i := x.(int)                   // i has type int and value 7
+
+type I interface { m() }
+
+func f(y I) {
+	s := y.(string)        // illegal: string does not implement I (missing method m)
+	r := y.(io.Reader)     // r has type io.Reader and the dynamic type of y must implement both I and io.Reader
+	…
+}
+
+ +

+A type assertion used in an assignment or initialization of the special form +

+ +
+v, ok = x.(T)
+v, ok := x.(T)
+var v, ok = x.(T)
+var v, ok interface{} = x.(T) // dynamic types of v and ok are T and bool
+
+ +

+yields an additional untyped boolean value. The value of ok is true +if the assertion holds. Otherwise it is false and the value of v is +the zero value for type T. +No run-time panic occurs in this case. +

+ + +

Calls

+ +

+Given an expression f of function type +F, +

+ +
+f(a1, a2, … an)
+
+ +

+calls f with arguments a1, a2, … an. +Except for one special case, arguments must be single-valued expressions +assignable to the parameter types of +F and are evaluated before the function is called. +The type of the expression is the result type +of F. +A method invocation is similar but the method itself +is specified as a selector upon a value of the receiver type for +the method. +

+ +
+math.Atan2(x, y)  // function call
+var pt *Point
+pt.Scale(3.5)     // method call with receiver pt
+
+ +

+In a function call, the function value and arguments are evaluated in +the usual order. +After they are evaluated, the parameters of the call are passed by value to the function +and the called function begins execution. +The return parameters of the function are passed by value +back to the caller when the function returns. +

+ +

+Calling a nil function value +causes a run-time panic. +

+ +

+As a special case, if the return values of a function or method +g are equal in number and individually +assignable to the parameters of another function or method +f, then the call f(g(parameters_of_g)) +will invoke f after binding the return values of +g to the parameters of f in order. The call +of f must contain no parameters other than the call of g, +and g must have at least one return value. +If f has a final ... parameter, it is +assigned the return values of g that remain after +assignment of regular parameters. +

+ +
+func Split(s string, pos int) (string, string) {
+	return s[0:pos], s[pos:]
+}
+
+func Join(s, t string) string {
+	return s + t
+}
+
+if Join(Split(value, len(value)/2)) != value {
+	log.Panic("test fails")
+}
+
+ +

+A method call x.m() is valid if the method set +of (the type of) x contains m and the +argument list can be assigned to the parameter list of m. +If x is addressable and &x's method +set contains m, x.m() is shorthand +for (&x).m(): +

+ +
+var p Point
+p.Scale(3.5)
+
+ +

+There is no distinct method type and there are no method literals. +

+ +

Passing arguments to ... parameters

+ +

+If f is variadic with a final +parameter p of type ...T, then within f +the type of p is equivalent to type []T. +If f is invoked with no actual arguments for p, +the value passed to p is nil. +Otherwise, the value passed is a new slice +of type []T with a new underlying array whose successive elements +are the actual arguments, which all must be assignable +to T. The length and capacity of the slice is therefore +the number of arguments bound to p and may differ for each +call site. +

+ +

+Given the function and calls +

+
+func Greeting(prefix string, who ...string)
+Greeting("nobody")
+Greeting("hello:", "Joe", "Anna", "Eileen")
+
+ +

+within Greeting, who will have the value +nil in the first call, and +[]string{"Joe", "Anna", "Eileen"} in the second. +

+ +

+If the final argument is assignable to a slice type []T and +is followed by ..., it is passed unchanged as the value +for a ...T parameter. In this case no new slice is created. +

+ +

+Given the slice s and call +

+ +
+s := []string{"James", "Jasmine"}
+Greeting("goodbye:", s...)
+
+ +

+within Greeting, who will have the same value as s +with the same underlying array. +

+ + +

Operators

+ +

+Operators combine operands into expressions. +

+ +
+Expression = UnaryExpr | Expression binary_op Expression .
+UnaryExpr  = PrimaryExpr | unary_op UnaryExpr .
+
+binary_op  = "||" | "&&" | rel_op | add_op | mul_op .
+rel_op     = "==" | "!=" | "<" | "<=" | ">" | ">=" .
+add_op     = "+" | "-" | "|" | "^" .
+mul_op     = "*" | "/" | "%" | "<<" | ">>" | "&" | "&^" .
+
+unary_op   = "+" | "-" | "!" | "^" | "*" | "&" | "<-" .
+
+ +

+Comparisons are discussed elsewhere. +For other binary operators, the operand types must be identical +unless the operation involves shifts or untyped constants. +For operations involving constants only, see the section on +constant expressions. +

+ +

+Except for shift operations, if one operand is an untyped constant +and the other operand is not, the constant is implicitly converted +to the type of the other operand. +

+ +

+The right operand in a shift expression must have integer type +or be an untyped constant representable by a +value of type uint. +If the left operand of a non-constant shift expression is an untyped constant, +it is first implicitly converted to the type it would assume if the shift expression were +replaced by its left operand alone. +

+ +
+var a [1024]byte
+var s uint = 33
+
+// The results of the following examples are given for 64-bit ints.
+var i = 1<<s                   // 1 has type int
+var j int32 = 1<<s             // 1 has type int32; j == 0
+var k = uint64(1<<s)           // 1 has type uint64; k == 1<<33
+var m int = 1.0<<s             // 1.0 has type int; m == 1<<33
+var n = 1.0<<s == j            // 1.0 has type int32; n == true
+var o = 1<<s == 2<<s           // 1 and 2 have type int; o == false
+var p = 1<<s == 1<<33          // 1 has type int; p == true
+var u = 1.0<<s                 // illegal: 1.0 has type float64, cannot shift
+var u1 = 1.0<<s != 0           // illegal: 1.0 has type float64, cannot shift
+var u2 = 1<<s != 1.0           // illegal: 1 has type float64, cannot shift
+var v float32 = 1<<s           // illegal: 1 has type float32, cannot shift
+var w int64 = 1.0<<33          // 1.0<<33 is a constant shift expression; w == 1<<33
+var x = a[1.0<<s]              // panics: 1.0 has type int, but 1<<33 overflows array bounds
+var b = make([]byte, 1.0<<s)   // 1.0 has type int; len(b) == 1<<33
+
+// The results of the following examples are given for 32-bit ints,
+// which means the shifts will overflow.
+var mm int = 1.0<<s            // 1.0 has type int; mm == 0
+var oo = 1<<s == 2<<s          // 1 and 2 have type int; oo == true
+var pp = 1<<s == 1<<33         // illegal: 1 has type int, but 1<<33 overflows int
+var xx = a[1.0<<s]             // 1.0 has type int; xx == a[0]
+var bb = make([]byte, 1.0<<s)  // 1.0 has type int; len(bb) == 0
+
+ +

Operator precedence

+

+Unary operators have the highest precedence. +As the ++ and -- operators form +statements, not expressions, they fall +outside the operator hierarchy. +As a consequence, statement *p++ is the same as (*p)++. +

+There are five precedence levels for binary operators. +Multiplication operators bind strongest, followed by addition +operators, comparison operators, && (logical AND), +and finally || (logical OR): +

+ +
+Precedence    Operator
+    5             *  /  %  <<  >>  &  &^
+    4             +  -  |  ^
+    3             ==  !=  <  <=  >  >=
+    2             &&
+    1             ||
+
+ +

+Binary operators of the same precedence associate from left to right. +For instance, x / y * z is the same as (x / y) * z. +

+ +
++x
+23 + 3*x[i]
+x <= f()
+^a >> b
+f() || g()
+x == y+1 && <-chanInt > 0
+
+ + +

Arithmetic operators

+

+Arithmetic operators apply to numeric values and yield a result of the same +type as the first operand. The four standard arithmetic operators (+, +-, *, /) apply to integer, +floating-point, and complex types; + also applies to strings. +The bitwise logical and shift operators apply to integers only. +

+ +
++    sum                    integers, floats, complex values, strings
+-    difference             integers, floats, complex values
+*    product                integers, floats, complex values
+/    quotient               integers, floats, complex values
+%    remainder              integers
+
+&    bitwise AND            integers
+|    bitwise OR             integers
+^    bitwise XOR            integers
+&^   bit clear (AND NOT)    integers
+
+<<   left shift             integer << integer >= 0
+>>   right shift            integer >> integer >= 0
+
+ + +

Integer operators

+ +

+For two integer values x and y, the integer quotient +q = x / y and remainder r = x % y satisfy the following +relationships: +

+ +
+x = q*y + r  and  |r| < |y|
+
+ +

+with x / y truncated towards zero +("truncated division"). +

+ +
+ x     y     x / y     x % y
+ 5     3       1         2
+-5     3      -1        -2
+ 5    -3      -1         2
+-5    -3       1        -2
+
+ +

+The one exception to this rule is that if the dividend x is +the most negative value for the int type of x, the quotient +q = x / -1 is equal to x (and r = 0) +due to two's-complement integer overflow: +

+ +
+			 x, q
+int8                     -128
+int16                  -32768
+int32             -2147483648
+int64    -9223372036854775808
+
+ +

+If the divisor is a constant, it must not be zero. +If the divisor is zero at run time, a run-time panic occurs. +If the dividend is non-negative and the divisor is a constant power of 2, +the division may be replaced by a right shift, and computing the remainder may +be replaced by a bitwise AND operation: +

+ +
+ x     x / 4     x % 4     x >> 2     x & 3
+ 11      2         3         2          3
+-11     -2        -3        -3          1
+
+ +

+The shift operators shift the left operand by the shift count specified by the +right operand, which must be non-negative. If the shift count is negative at run time, +a run-time panic occurs. +The shift operators implement arithmetic shifts if the left operand is a signed +integer and logical shifts if it is an unsigned integer. +There is no upper limit on the shift count. Shifts behave +as if the left operand is shifted n times by 1 for a shift +count of n. +As a result, x << 1 is the same as x*2 +and x >> 1 is the same as +x/2 but truncated towards negative infinity. +

+ +

+For integer operands, the unary operators ++, -, and ^ are defined as +follows: +

+ +
++x                          is 0 + x
+-x    negation              is 0 - x
+^x    bitwise complement    is m ^ x  with m = "all bits set to 1" for unsigned x
+                                      and  m = -1 for signed x
+
+ + +

Integer overflow

+ +

+For unsigned integer values, the operations +, +-, *, and << are +computed modulo 2n, where n is the bit width of +the unsigned integer's type. +Loosely speaking, these unsigned integer operations +discard high bits upon overflow, and programs may rely on "wrap around". +

+

+For signed integers, the operations +, +-, *, /, and << may legally +overflow and the resulting value exists and is deterministically defined +by the signed integer representation, the operation, and its operands. +Overflow does not cause a run-time panic. +A compiler may not optimize code under the assumption that overflow does +not occur. For instance, it may not assume that x < x + 1 is always true. +

+ + +

Floating-point operators

+ +

+For floating-point and complex numbers, ++x is the same as x, +while -x is the negation of x. +The result of a floating-point or complex division by zero is not specified beyond the +IEEE-754 standard; whether a run-time panic +occurs is implementation-specific. +

+ +

+An implementation may combine multiple floating-point operations into a single +fused operation, possibly across statements, and produce a result that differs +from the value obtained by executing and rounding the instructions individually. +An explicit floating-point type conversion rounds to +the precision of the target type, preventing fusion that would discard that rounding. +

+ +

+For instance, some architectures provide a "fused multiply and add" (FMA) instruction +that computes x*y + z without rounding the intermediate result x*y. +These examples show when a Go implementation can use that instruction: +

+ +
+// FMA allowed for computing r, because x*y is not explicitly rounded:
+r  = x*y + z
+r  = z;   r += x*y
+t  = x*y; r = t + z
+*p = x*y; r = *p + z
+r  = x*y + float64(z)
+
+// FMA disallowed for computing r, because it would omit rounding of x*y:
+r  = float64(x*y) + z
+r  = z; r += float64(x*y)
+t  = float64(x*y); r = t + z
+
+ +

String concatenation

+ +

+Strings can be concatenated using the + operator +or the += assignment operator: +

+ +
+s := "hi" + string(c)
+s += " and good bye"
+
+ +

+String addition creates a new string by concatenating the operands. +

+ + +

Comparison operators

+ +

+Comparison operators compare two operands and yield an untyped boolean value. +

+ +
+==    equal
+!=    not equal
+<     less
+<=    less or equal
+>     greater
+>=    greater or equal
+
+ +

+In any comparison, the first operand +must be assignable +to the type of the second operand, or vice versa. +

+

+The equality operators == and != apply +to operands that are comparable. +The ordering operators <, <=, >, and >= +apply to operands that are ordered. +These terms and the result of the comparisons are defined as follows: +

+ +
    +
  • + Boolean values are comparable. + Two boolean values are equal if they are either both + true or both false. +
  • + +
  • + Integer values are comparable and ordered, in the usual way. +
  • + +
  • + Floating-point values are comparable and ordered, + as defined by the IEEE-754 standard. +
  • + +
  • + Complex values are comparable. + Two complex values u and v are + equal if both real(u) == real(v) and + imag(u) == imag(v). +
  • + +
  • + String values are comparable and ordered, lexically byte-wise. +
  • + +
  • + Pointer values are comparable. + Two pointer values are equal if they point to the same variable or if both have value nil. + Pointers to distinct zero-size variables may or may not be equal. +
  • + +
  • + Channel values are comparable. + Two channel values are equal if they were created by the same call to + make + or if both have value nil. +
  • + +
  • + Interface values are comparable. + Two interface values are equal if they have identical dynamic types + and equal dynamic values or if both have value nil. +
  • + +
  • + A value x of non-interface type X and + a value t of interface type T are comparable when values + of type X are comparable and + X implements T. + They are equal if t's dynamic type is identical to X + and t's dynamic value is equal to x. +
  • + +
  • + Struct values are comparable if all their fields are comparable. + Two struct values are equal if their corresponding + non-blank fields are equal. +
  • + +
  • + Array values are comparable if values of the array element type are comparable. + Two array values are equal if their corresponding elements are equal. +
  • +
+ +

+A comparison of two interface values with identical dynamic types +causes a run-time panic if values +of that type are not comparable. This behavior applies not only to direct interface +value comparisons but also when comparing arrays of interface values +or structs with interface-valued fields. +

+ +

+Slice, map, and function values are not comparable. +However, as a special case, a slice, map, or function value may +be compared to the predeclared identifier nil. +Comparison of pointer, channel, and interface values to nil +is also allowed and follows from the general rules above. +

+ +
+const c = 3 < 4            // c is the untyped boolean constant true
+
+type MyBool bool
+var x, y int
+var (
+	// The result of a comparison is an untyped boolean.
+	// The usual assignment rules apply.
+	b3        = x == y // b3 has type bool
+	b4 bool   = x == y // b4 has type bool
+	b5 MyBool = x == y // b5 has type MyBool
+)
+
+ +

Logical operators

+ +

+Logical operators apply to boolean values +and yield a result of the same type as the operands. +The right operand is evaluated conditionally. +

+ +
+&&    conditional AND    p && q  is  "if p then q else false"
+||    conditional OR     p || q  is  "if p then true else q"
+!     NOT                !p      is  "not p"
+
+ + +

Address operators

+ +

+For an operand x of type T, the address operation +&x generates a pointer of type *T to x. +The operand must be addressable, +that is, either a variable, pointer indirection, or slice indexing +operation; or a field selector of an addressable struct operand; +or an array indexing operation of an addressable array. +As an exception to the addressability requirement, x may also be a +(possibly parenthesized) +composite literal. +If the evaluation of x would cause a run-time panic, +then the evaluation of &x does too. +

+ +

+For an operand x of pointer type *T, the pointer +indirection *x denotes the variable of type T pointed +to by x. +If x is nil, an attempt to evaluate *x +will cause a run-time panic. +

+ +
+&x
+&a[f(2)]
+&Point{2, 3}
+*p
+*pf(x)
+
+var x *int = nil
+*x   // causes a run-time panic
+&*x  // causes a run-time panic
+
+ + +

Receive operator

+ +

+For an operand ch of channel type, +the value of the receive operation <-ch is the value received +from the channel ch. The channel direction must permit receive operations, +and the type of the receive operation is the element type of the channel. +The expression blocks until a value is available. +Receiving from a nil channel blocks forever. +A receive operation on a closed channel can always proceed +immediately, yielding the element type's zero value +after any previously sent values have been received. +

+ +
+v1 := <-ch
+v2 = <-ch
+f(<-ch)
+<-strobe  // wait until clock pulse and discard received value
+
+ +

+A receive expression used in an assignment or initialization of the special form +

+ +
+x, ok = <-ch
+x, ok := <-ch
+var x, ok = <-ch
+var x, ok T = <-ch
+
+ +

+yields an additional untyped boolean result reporting whether the +communication succeeded. The value of ok is true +if the value received was delivered by a successful send operation to the +channel, or false if it is a zero value generated because the +channel is closed and empty. +

+ + +

Conversions

+ +

+A conversion changes the type of an expression +to the type specified by the conversion. +A conversion may appear literally in the source, or it may be implied +by the context in which an expression appears. +

+ +

+An explicit conversion is an expression of the form T(x) +where T is a type and x is an expression +that can be converted to type T. +

+ +
+Conversion = Type "(" Expression [ "," ] ")" .
+
+ +

+If the type starts with the operator * or <-, +or if the type starts with the keyword func +and has no result list, it must be parenthesized when +necessary to avoid ambiguity: +

+ +
+*Point(p)        // same as *(Point(p))
+(*Point)(p)      // p is converted to *Point
+<-chan int(c)    // same as <-(chan int(c))
+(<-chan int)(c)  // c is converted to <-chan int
+func()(x)        // function signature func() x
+(func())(x)      // x is converted to func()
+(func() int)(x)  // x is converted to func() int
+func() int(x)    // x is converted to func() int (unambiguous)
+
+ +

+A constant value x can be converted to +type T if x is representable +by a value of T. +As a special case, an integer constant x can be explicitly converted to a +string type using the +same rule +as for non-constant x. +

+ +

+Converting a constant yields a typed constant as result. +

+ +
+uint(iota)               // iota value of type uint
+float32(2.718281828)     // 2.718281828 of type float32
+complex128(1)            // 1.0 + 0.0i of type complex128
+float32(0.49999999)      // 0.5 of type float32
+float64(-1e-1000)        // 0.0 of type float64
+string('x')              // "x" of type string
+string(0x266c)           // "♬" of type string
+MyString("foo" + "bar")  // "foobar" of type MyString
+string([]byte{'a'})      // not a constant: []byte{'a'} is not a constant
+(*int)(nil)              // not a constant: nil is not a constant, *int is not a boolean, numeric, or string type
+int(1.2)                 // illegal: 1.2 cannot be represented as an int
+string(65.0)             // illegal: 65.0 is not an integer constant
+
+ +

+A non-constant value x can be converted to type T +in any of these cases: +

+ +
    +
  • + x is assignable + to T. +
  • +
  • + ignoring struct tags (see below), + x's type and T have identical + underlying types. +
  • +
  • + ignoring struct tags (see below), + x's type and T are pointer types + that are not defined types, + and their pointer base types have identical underlying types. +
  • +
  • + x's type and T are both integer or floating + point types. +
  • +
  • + x's type and T are both complex types. +
  • +
  • + x is an integer or a slice of bytes or runes + and T is a string type. +
  • +
  • + x is a string and T is a slice of bytes or runes. +
  • +
  • + x is a slice, T is a pointer to an array, + and the slice and array types have identical element types. +
  • +
+ +

+Struct tags are ignored when comparing struct types +for identity for the purpose of conversion: +

+ +
+type Person struct {
+	Name    string
+	Address *struct {
+		Street string
+		City   string
+	}
+}
+
+var data *struct {
+	Name    string `json:"name"`
+	Address *struct {
+		Street string `json:"street"`
+		City   string `json:"city"`
+	} `json:"address"`
+}
+
+var person = (*Person)(data)  // ignoring tags, the underlying types are identical
+
+ +

+Specific rules apply to (non-constant) conversions between numeric types or +to and from a string type. +These conversions may change the representation of x +and incur a run-time cost. +All other conversions only change the type but not the representation +of x. +

+ +

+There is no linguistic mechanism to convert between pointers and integers. +The package unsafe +implements this functionality under +restricted circumstances. +

+ +

Conversions between numeric types

+ +

+For the conversion of non-constant numeric values, the following rules apply: +

+ +
    +
  1. +When converting between integer types, if the value is a signed integer, it is +sign extended to implicit infinite precision; otherwise it is zero extended. +It is then truncated to fit in the result type's size. +For example, if v := uint16(0x10F0), then uint32(int8(v)) == 0xFFFFFFF0. +The conversion always yields a valid value; there is no indication of overflow. +
  2. +
  3. +When converting a floating-point number to an integer, the fraction is discarded +(truncation towards zero). +
  4. +
  5. +When converting an integer or floating-point number to a floating-point type, +or a complex number to another complex type, the result value is rounded +to the precision specified by the destination type. +For instance, the value of a variable x of type float32 +may be stored using additional precision beyond that of an IEEE-754 32-bit number, +but float32(x) represents the result of rounding x's value to +32-bit precision. Similarly, x + 0.1 may use more than 32 bits +of precision, but float32(x + 0.1) does not. +
  6. +
+ +

+In all non-constant conversions involving floating-point or complex values, +if the result type cannot represent the value the conversion +succeeds but the result value is implementation-dependent. +

+ +

Conversions to and from a string type

+ +
    +
  1. +Converting a signed or unsigned integer value to a string type yields a +string containing the UTF-8 representation of the integer. Values outside +the range of valid Unicode code points are converted to "\uFFFD". + +
    +string('a')       // "a"
    +string(-1)        // "\ufffd" == "\xef\xbf\xbd"
    +string(0xf8)      // "\u00f8" == "ø" == "\xc3\xb8"
    +type MyString string
    +MyString(0x65e5)  // "\u65e5" == "日" == "\xe6\x97\xa5"
    +
    +
  2. + +
  3. +Converting a slice of bytes to a string type yields +a string whose successive bytes are the elements of the slice. + +
    +string([]byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'})   // "hellø"
    +string([]byte{})                                     // ""
    +string([]byte(nil))                                  // ""
    +
    +type MyBytes []byte
    +string(MyBytes{'h', 'e', 'l', 'l', '\xc3', '\xb8'})  // "hellø"
    +
    +
  4. + +
  5. +Converting a slice of runes to a string type yields +a string that is the concatenation of the individual rune values +converted to strings. + +
    +string([]rune{0x767d, 0x9d6c, 0x7fd4})   // "\u767d\u9d6c\u7fd4" == "白鵬翔"
    +string([]rune{})                         // ""
    +string([]rune(nil))                      // ""
    +
    +type MyRunes []rune
    +string(MyRunes{0x767d, 0x9d6c, 0x7fd4})  // "\u767d\u9d6c\u7fd4" == "白鵬翔"
    +
    +
  6. + +
  7. +Converting a value of a string type to a slice of bytes type +yields a slice whose successive elements are the bytes of the string. + +
    +[]byte("hellø")   // []byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'}
    +[]byte("")        // []byte{}
    +
    +MyBytes("hellø")  // []byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'}
    +
    +
  8. + +
  9. +Converting a value of a string type to a slice of runes type +yields a slice containing the individual Unicode code points of the string. + +
    +[]rune(MyString("白鵬翔"))  // []rune{0x767d, 0x9d6c, 0x7fd4}
    +[]rune("")                 // []rune{}
    +
    +MyRunes("白鵬翔")           // []rune{0x767d, 0x9d6c, 0x7fd4}
    +
    +
  10. +
+ +

Conversions from slice to array pointer

+ +

+Converting a slice to an array pointer yields a pointer to the underlying array of the slice. +If the length of the slice is less than the length of the array, +a run-time panic occurs. +

+ +
+s := make([]byte, 2, 4)
+s0 := (*[0]byte)(s)      // s0 != nil
+s1 := (*[1]byte)(s[1:])  // &s1[0] == &s[1]
+s2 := (*[2]byte)(s)      // &s2[0] == &s[0]
+s4 := (*[4]byte)(s)      // panics: len([4]byte) > len(s)
+
+var t []string
+t0 := (*[0]string)(t)    // t0 == nil
+t1 := (*[1]string)(t)    // panics: len([1]string) > len(t)
+
+u := make([]byte, 0)
+u0 := (*[0]byte)(u)      // u0 != nil
+
+ +

Constant expressions

+ +

+Constant expressions may contain only constant +operands and are evaluated at compile time. +

+ +

+Untyped boolean, numeric, and string constants may be used as operands +wherever it is legal to use an operand of boolean, numeric, or string type, +respectively. +

+ +

+A constant comparison always yields +an untyped boolean constant. If the left operand of a constant +shift expression is an untyped constant, the +result is an integer constant; otherwise it is a constant of the same +type as the left operand, which must be of +integer type. +

+ +

+Any other operation on untyped constants results in an untyped constant of the +same kind; that is, a boolean, integer, floating-point, complex, or string +constant. +If the untyped operands of a binary operation (other than a shift) are of +different kinds, the result is of the operand's kind that appears later in this +list: integer, rune, floating-point, complex. +For example, an untyped integer constant divided by an +untyped complex constant yields an untyped complex constant. +

+ +
+const a = 2 + 3.0          // a == 5.0   (untyped floating-point constant)
+const b = 15 / 4           // b == 3     (untyped integer constant)
+const c = 15 / 4.0         // c == 3.75  (untyped floating-point constant)
+const Θ float64 = 3/2      // Θ == 1.0   (type float64, 3/2 is integer division)
+const Π float64 = 3/2.     // Π == 1.5   (type float64, 3/2. is float division)
+const d = 1 << 3.0         // d == 8     (untyped integer constant)
+const e = 1.0 << 3         // e == 8     (untyped integer constant)
+const f = int32(1) << 33   // illegal    (constant 8589934592 overflows int32)
+const g = float64(2) >> 1  // illegal    (float64(2) is a typed floating-point constant)
+const h = "foo" > "bar"    // h == true  (untyped boolean constant)
+const j = true             // j == true  (untyped boolean constant)
+const k = 'w' + 1          // k == 'x'   (untyped rune constant)
+const l = "hi"             // l == "hi"  (untyped string constant)
+const m = string(k)        // m == "x"   (type string)
+const Σ = 1 - 0.707i       //            (untyped complex constant)
+const Δ = Σ + 2.0e-4       //            (untyped complex constant)
+const Φ = iota*1i - 1/1i   //            (untyped complex constant)
+
+ +

+Applying the built-in function complex to untyped +integer, rune, or floating-point constants yields +an untyped complex constant. +

+ +
+const ic = complex(0, c)   // ic == 3.75i  (untyped complex constant)
+const iΘ = complex(0, Θ)   // iΘ == 1i     (type complex128)
+
+ +

+Constant expressions are always evaluated exactly; intermediate values and the +constants themselves may require precision significantly larger than supported +by any predeclared type in the language. The following are legal declarations: +

+ +
+const Huge = 1 << 100         // Huge == 1267650600228229401496703205376  (untyped integer constant)
+const Four int8 = Huge >> 98  // Four == 4                                (type int8)
+
+ +

+The divisor of a constant division or remainder operation must not be zero: +

+ +
+3.14 / 0.0   // illegal: division by zero
+
+ +

+The values of typed constants must always be accurately +representable by values +of the constant type. The following constant expressions are illegal: +

+ +
+uint(-1)     // -1 cannot be represented as a uint
+int(3.14)    // 3.14 cannot be represented as an int
+int64(Huge)  // 1267650600228229401496703205376 cannot be represented as an int64
+Four * 300   // operand 300 cannot be represented as an int8 (type of Four)
+Four * 100   // product 400 cannot be represented as an int8 (type of Four)
+
+ +

+The mask used by the unary bitwise complement operator ^ matches +the rule for non-constants: the mask is all 1s for unsigned constants +and -1 for signed and untyped constants. +

+ +
+^1         // untyped integer constant, equal to -2
+uint8(^1)  // illegal: same as uint8(-2), -2 cannot be represented as a uint8
+^uint8(1)  // typed uint8 constant, same as 0xFF ^ uint8(1) = uint8(0xFE)
+int8(^1)   // same as int8(-2)
+^int8(1)   // same as -1 ^ int8(1) = -2
+
+ +

+Implementation restriction: A compiler may use rounding while +computing untyped floating-point or complex constant expressions; see +the implementation restriction in the section +on constants. This rounding may cause a +floating-point constant expression to be invalid in an integer +context, even if it would be integral when calculated using infinite +precision, and vice versa. +

+ + +

Order of evaluation

+ +

+At package level, initialization dependencies +determine the evaluation order of individual initialization expressions in +variable declarations. +Otherwise, when evaluating the operands of an +expression, assignment, or +return statement, +all function calls, method calls, and +communication operations are evaluated in lexical left-to-right +order. +

+ +

+For example, in the (function-local) assignment +

+
+y[f()], ok = g(h(), i()+x[j()], <-c), k()
+
+

+the function calls and communication happen in the order +f(), h(), i(), j(), +<-c, g(), and k(). +However, the order of those events compared to the evaluation +and indexing of x and the evaluation +of y is not specified. +

+ +
+a := 1
+f := func() int { a++; return a }
+x := []int{a, f()}            // x may be [1, 2] or [2, 2]: evaluation order between a and f() is not specified
+m := map[int]int{a: 1, a: 2}  // m may be {2: 1} or {2: 2}: evaluation order between the two map assignments is not specified
+n := map[int]int{a: f()}      // n may be {2: 3} or {3: 3}: evaluation order between the key and the value is not specified
+
+ +

+At package level, initialization dependencies override the left-to-right rule +for individual initialization expressions, but not for operands within each +expression: +

+ +
+var a, b, c = f() + v(), g(), sqr(u()) + v()
+
+func f() int        { return c }
+func g() int        { return a }
+func sqr(x int) int { return x*x }
+
+// functions u and v are independent of all other variables and functions
+
+ +

+The function calls happen in the order +u(), sqr(), v(), +f(), v(), and g(). +

+ +

+Floating-point operations within a single expression are evaluated according to +the associativity of the operators. Explicit parentheses affect the evaluation +by overriding the default associativity. +In the expression x + (y + z) the addition y + z +is performed before adding x. +

+ +

Statements

+ +

+Statements control execution. +

+ +
+Statement =
+	Declaration | LabeledStmt | SimpleStmt |
+	GoStmt | ReturnStmt | BreakStmt | ContinueStmt | GotoStmt |
+	FallthroughStmt | Block | IfStmt | SwitchStmt | SelectStmt | ForStmt |
+	DeferStmt .
+
+SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecStmt | Assignment | ShortVarDecl .
+
+ +

Terminating statements

+ +

+A terminating statement interrupts the regular flow of control in +a block. The following statements are terminating: +

+ +
    +
  1. + A "return" or + "goto" statement. + +
    +
  2. + +
  3. + A call to the built-in function + panic. + +
    +
  4. + +
  5. + A block in which the statement list ends in a terminating statement. + +
    +
  6. + +
  7. + An "if" statement in which: +
      +
    • the "else" branch is present, and
    • +
    • both branches are terminating statements.
    • +
    +
  8. + +
  9. + A "for" statement in which: +
      +
    • there are no "break" statements referring to the "for" statement, and
    • +
    • the loop condition is absent, and
    • +
    • the "for" statement does not use a range clause.
    • +
    +
  10. + +
  11. + A "switch" statement in which: +
      +
    • there are no "break" statements referring to the "switch" statement,
    • +
    • there is a default case, and
    • +
    • the statement lists in each case, including the default, end in a terminating + statement, or a possibly labeled "fallthrough" + statement.
    • +
    +
  12. + +
  13. + A "select" statement in which: +
      +
    • there are no "break" statements referring to the "select" statement, and
    • +
    • the statement lists in each case, including the default if present, + end in a terminating statement.
    • +
    +
  14. + +
  15. + A labeled statement labeling + a terminating statement. +
  16. +
+ +

+All other statements are not terminating. +

+ +

+A statement list ends in a terminating statement if the list +is not empty and its final non-empty statement is terminating. +

+ + +

Empty statements

+ +

+The empty statement does nothing. +

+ +
+EmptyStmt = .
+
+ + +

Labeled statements

+ +

+A labeled statement may be the target of a goto, +break or continue statement. +

+ +
+LabeledStmt = Label ":" Statement .
+Label       = identifier .
+
+ +
+Error: log.Panic("error encountered")
+
+ + +

Expression statements

+ +

+With the exception of specific built-in functions, +function and method calls and +receive operations +can appear in statement context. Such statements may be parenthesized. +

+ +
+ExpressionStmt = Expression .
+
+ +

+The following built-in functions are not permitted in statement context: +

+ +
+append cap complex imag len make new real
+unsafe.Add unsafe.Alignof unsafe.Offsetof unsafe.Sizeof unsafe.Slice
+
+ +
+h(x+y)
+f.Close()
+<-ch
+(<-ch)
+len("foo")  // illegal if len is the built-in function
+
+ + +

Send statements

+ +

+A send statement sends a value on a channel. +The channel expression must be of channel type, +the channel direction must permit send operations, +and the type of the value to be sent must be assignable +to the channel's element type. +

+ +
+SendStmt = Channel "<-" Expression .
+Channel  = Expression .
+
+ +

+Both the channel and the value expression are evaluated before communication +begins. Communication blocks until the send can proceed. +A send on an unbuffered channel can proceed if a receiver is ready. +A send on a buffered channel can proceed if there is room in the buffer. +A send on a closed channel proceeds by causing a run-time panic. +A send on a nil channel blocks forever. +

+ +
+ch <- 3  // send value 3 to channel ch
+
+ + +

IncDec statements

+ +

+The "++" and "--" statements increment or decrement their operands +by the untyped constant 1. +As with an assignment, the operand must be addressable +or a map index expression. +

+ +
+IncDecStmt = Expression ( "++" | "--" ) .
+
+ +

+The following assignment statements are semantically +equivalent: +

+ +
+IncDec statement    Assignment
+x++                 x += 1
+x--                 x -= 1
+
+ + +

Assignments

+ +
+Assignment = ExpressionList assign_op ExpressionList .
+
+assign_op = [ add_op | mul_op ] "=" .
+
+ +

+Each left-hand side operand must be addressable, +a map index expression, or (for = assignments only) the +blank identifier. +Operands may be parenthesized. +

+ +
+x = 1
+*p = f()
+a[i] = 23
+(k) = <-ch  // same as: k = <-ch
+
+ +

+An assignment operation x op= +y where op is a binary arithmetic operator +is equivalent to x = x op +(y) but evaluates x +only once. The op= construct is a single token. +In assignment operations, both the left- and right-hand expression lists +must contain exactly one single-valued expression, and the left-hand +expression must not be the blank identifier. +

+ +
+a[i] <<= 2
+i &^= 1<<n
+
+ +

+A tuple assignment assigns the individual elements of a multi-valued +operation to a list of variables. There are two forms. In the +first, the right hand operand is a single multi-valued expression +such as a function call, a channel or +map operation, or a type assertion. +The number of operands on the left +hand side must match the number of values. For instance, if +f is a function returning two values, +

+ +
+x, y = f()
+
+ +

+assigns the first value to x and the second to y. +In the second form, the number of operands on the left must equal the number +of expressions on the right, each of which must be single-valued, and the +nth expression on the right is assigned to the nth +operand on the left: +

+ +
+one, two, three = '一', '二', '三'
+
+ +

+The blank identifier provides a way to +ignore right-hand side values in an assignment: +

+ +
+_ = x       // evaluate x but ignore it
+x, _ = f()  // evaluate f() but ignore second result value
+
+ +

+The assignment proceeds in two phases. +First, the operands of index expressions +and pointer indirections +(including implicit pointer indirections in selectors) +on the left and the expressions on the right are all +evaluated in the usual order. +Second, the assignments are carried out in left-to-right order. +

+ +
+a, b = b, a  // exchange a and b
+
+x := []int{1, 2, 3}
+i := 0
+i, x[i] = 1, 2  // set i = 1, x[0] = 2
+
+i = 0
+x[i], i = 2, 1  // set x[0] = 2, i = 1
+
+x[0], x[0] = 1, 2  // set x[0] = 1, then x[0] = 2 (so x[0] == 2 at end)
+
+x[1], x[3] = 4, 5  // set x[1] = 4, then panic setting x[3] = 5.
+
+type Point struct { x, y int }
+var p *Point
+x[2], p.x = 6, 7  // set x[2] = 6, then panic setting p.x = 7
+
+i = 2
+x = []int{3, 5, 7}
+for i, x[i] = range x {  // set i, x[2] = 0, x[0]
+	break
+}
+// after this loop, i == 0 and x == []int{3, 5, 3}
+
+ +

+In assignments, each value must be assignable +to the type of the operand to which it is assigned, with the following special cases: +

+ +
    +
  1. + Any typed value may be assigned to the blank identifier. +
  2. + +
  3. + If an untyped constant + is assigned to a variable of interface type or the blank identifier, + the constant is first implicitly converted to its + default type. +
  4. + +
  5. + If an untyped boolean value is assigned to a variable of interface type or + the blank identifier, it is first implicitly converted to type bool. +
  6. +
+ +

If statements

+ +

+"If" statements specify the conditional execution of two branches +according to the value of a boolean expression. If the expression +evaluates to true, the "if" branch is executed, otherwise, if +present, the "else" branch is executed. +

+ +
+IfStmt = "if" [ SimpleStmt ";" ] Expression Block [ "else" ( IfStmt | Block ) ] .
+
+ +
+if x > max {
+	x = max
+}
+
+ +

+The expression may be preceded by a simple statement, which +executes before the expression is evaluated. +

+ +
+if x := f(); x < y {
+	return x
+} else if x > z {
+	return z
+} else {
+	return y
+}
+
+ + +

Switch statements

+ +

+"Switch" statements provide multi-way execution. +An expression or type is compared to the "cases" +inside the "switch" to determine which branch +to execute. +

+ +
+SwitchStmt = ExprSwitchStmt | TypeSwitchStmt .
+
+ +

+There are two forms: expression switches and type switches. +In an expression switch, the cases contain expressions that are compared +against the value of the switch expression. +In a type switch, the cases contain types that are compared against the +type of a specially annotated switch expression. +The switch expression is evaluated exactly once in a switch statement. +

+ +

Expression switches

+ +

+In an expression switch, +the switch expression is evaluated and +the case expressions, which need not be constants, +are evaluated left-to-right and top-to-bottom; the first one that equals the +switch expression +triggers execution of the statements of the associated case; +the other cases are skipped. +If no case matches and there is a "default" case, +its statements are executed. +There can be at most one default case and it may appear anywhere in the +"switch" statement. +A missing switch expression is equivalent to the boolean value +true. +

+ +
+ExprSwitchStmt = "switch" [ SimpleStmt ";" ] [ Expression ] "{" { ExprCaseClause } "}" .
+ExprCaseClause = ExprSwitchCase ":" StatementList .
+ExprSwitchCase = "case" ExpressionList | "default" .
+
+ +

+If the switch expression evaluates to an untyped constant, it is first implicitly +converted to its default type. +The predeclared untyped value nil cannot be used as a switch expression. +The switch expression type must be comparable. +

+ +

+If a case expression is untyped, it is first implicitly converted +to the type of the switch expression. +For each (possibly converted) case expression x and the value t +of the switch expression, x == t must be a valid comparison. +

+ +

+In other words, the switch expression is treated as if it were used to declare and +initialize a temporary variable t without explicit type; it is that +value of t against which each case expression x is tested +for equality. +

+ +

+In a case or default clause, the last non-empty statement +may be a (possibly labeled) +"fallthrough" statement to +indicate that control should flow from the end of this clause to +the first statement of the next clause. +Otherwise control flows to the end of the "switch" statement. +A "fallthrough" statement may appear as the last statement of all +but the last clause of an expression switch. +

+ +

+The switch expression may be preceded by a simple statement, which +executes before the expression is evaluated. +

+ +
+switch tag {
+default: s3()
+case 0, 1, 2, 3: s1()
+case 4, 5, 6, 7: s2()
+}
+
+switch x := f(); {  // missing switch expression means "true"
+case x < 0: return -x
+default: return x
+}
+
+switch {
+case x < y: f1()
+case x < z: f2()
+case x == 4: f3()
+}
+
+ +

+Implementation restriction: A compiler may disallow multiple case +expressions evaluating to the same constant. +For instance, the current compilers disallow duplicate integer, +floating point, or string constants in case expressions. +

+ +

Type switches

+ +

+A type switch compares types rather than values. It is otherwise similar +to an expression switch. It is marked by a special switch expression that +has the form of a type assertion +using the keyword type rather than an actual type: +

+ +
+switch x.(type) {
+// cases
+}
+
+ +

+Cases then match actual types T against the dynamic type of the +expression x. As with type assertions, x must be of +interface type, and each non-interface type +T listed in a case must implement the type of x. +The types listed in the cases of a type switch must all be +different. +

+ +
+TypeSwitchStmt  = "switch" [ SimpleStmt ";" ] TypeSwitchGuard "{" { TypeCaseClause } "}" .
+TypeSwitchGuard = [ identifier ":=" ] PrimaryExpr "." "(" "type" ")" .
+TypeCaseClause  = TypeSwitchCase ":" StatementList .
+TypeSwitchCase  = "case" TypeList | "default" .
+TypeList        = Type { "," Type } .
+
+ +

+The TypeSwitchGuard may include a +short variable declaration. +When that form is used, the variable is declared at the end of the +TypeSwitchCase in the implicit block of each clause. +In clauses with a case listing exactly one type, the variable +has that type; otherwise, the variable has the type of the expression +in the TypeSwitchGuard. +

+ +

+Instead of a type, a case may use the predeclared identifier +nil; +that case is selected when the expression in the TypeSwitchGuard +is a nil interface value. +There may be at most one nil case. +

+ +

+Given an expression x of type interface{}, +the following type switch: +

+ +
+switch i := x.(type) {
+case nil:
+	printString("x is nil")                // type of i is type of x (interface{})
+case int:
+	printInt(i)                            // type of i is int
+case float64:
+	printFloat64(i)                        // type of i is float64
+case func(int) float64:
+	printFunction(i)                       // type of i is func(int) float64
+case bool, string:
+	printString("type is bool or string")  // type of i is type of x (interface{})
+default:
+	printString("don't know the type")     // type of i is type of x (interface{})
+}
+
+ +

+could be rewritten: +

+ +
+v := x  // x is evaluated exactly once
+if v == nil {
+	i := v                                 // type of i is type of x (interface{})
+	printString("x is nil")
+} else if i, isInt := v.(int); isInt {
+	printInt(i)                            // type of i is int
+} else if i, isFloat64 := v.(float64); isFloat64 {
+	printFloat64(i)                        // type of i is float64
+} else if i, isFunc := v.(func(int) float64); isFunc {
+	printFunction(i)                       // type of i is func(int) float64
+} else {
+	_, isBool := v.(bool)
+	_, isString := v.(string)
+	if isBool || isString {
+		i := v                         // type of i is type of x (interface{})
+		printString("type is bool or string")
+	} else {
+		i := v                         // type of i is type of x (interface{})
+		printString("don't know the type")
+	}
+}
+
+ +

+The type switch guard may be preceded by a simple statement, which +executes before the guard is evaluated. +

+ +

+The "fallthrough" statement is not permitted in a type switch. +

+ +

For statements

+ +

+A "for" statement specifies repeated execution of a block. There are three forms: +The iteration may be controlled by a single condition, a "for" clause, or a "range" clause. +

+ +
+ForStmt = "for" [ Condition | ForClause | RangeClause ] Block .
+Condition = Expression .
+
+ +

For statements with single condition

+ +

+In its simplest form, a "for" statement specifies the repeated execution of +a block as long as a boolean condition evaluates to true. +The condition is evaluated before each iteration. +If the condition is absent, it is equivalent to the boolean value +true. +

+ +
+for a < b {
+	a *= 2
+}
+
+ +

For statements with for clause

+ +

+A "for" statement with a ForClause is also controlled by its condition, but +additionally it may specify an init +and a post statement, such as an assignment, +an increment or decrement statement. The init statement may be a +short variable declaration, but the post statement must not. +Variables declared by the init statement are re-used in each iteration. +

+ +
+ForClause = [ InitStmt ] ";" [ Condition ] ";" [ PostStmt ] .
+InitStmt = SimpleStmt .
+PostStmt = SimpleStmt .
+
+ +
+for i := 0; i < 10; i++ {
+	f(i)
+}
+
+ +

+If non-empty, the init statement is executed once before evaluating the +condition for the first iteration; +the post statement is executed after each execution of the block (and +only if the block was executed). +Any element of the ForClause may be empty but the +semicolons are +required unless there is only a condition. +If the condition is absent, it is equivalent to the boolean value +true. +

+ +
+for cond { S() }    is the same as    for ; cond ; { S() }
+for      { S() }    is the same as    for true     { S() }
+
+ +

For statements with range clause

+ +

+A "for" statement with a "range" clause +iterates through all entries of an array, slice, string or map, +or values received on a channel. For each entry it assigns iteration values +to corresponding iteration variables if present and then executes the block. +

+ +
+RangeClause = [ ExpressionList "=" | IdentifierList ":=" ] "range" Expression .
+
+ +

+The expression on the right in the "range" clause is called the range expression, +which may be an array, pointer to an array, slice, string, map, or channel permitting +receive operations. +As with an assignment, if present the operands on the left must be +addressable or map index expressions; they +denote the iteration variables. If the range expression is a channel, at most +one iteration variable is permitted, otherwise there may be up to two. +If the last iteration variable is the blank identifier, +the range clause is equivalent to the same clause without that identifier. +

+ +

+The range expression x is evaluated once before beginning the loop, +with one exception: if at most one iteration variable is present and +len(x) is constant, +the range expression is not evaluated. +

+ +

+Function calls on the left are evaluated once per iteration. +For each iteration, iteration values are produced as follows +if the respective iteration variables are present: +

+ +
+Range expression                          1st value          2nd value
+
+array or slice  a  [n]E, *[n]E, or []E    index    i  int    a[i]       E
+string          s  string type            index    i  int    see below  rune
+map             m  map[K]V                key      k  K      m[k]       V
+channel         c  chan E, <-chan E       element  e  E
+
+ +
    +
  1. +For an array, pointer to array, or slice value a, the index iteration +values are produced in increasing order, starting at element index 0. +If at most one iteration variable is present, the range loop produces +iteration values from 0 up to len(a)-1 and does not index into the array +or slice itself. For a nil slice, the number of iterations is 0. +
  2. + +
  3. +For a string value, the "range" clause iterates over the Unicode code points +in the string starting at byte index 0. On successive iterations, the index value will be the +index of the first byte of successive UTF-8-encoded code points in the string, +and the second value, of type rune, will be the value of +the corresponding code point. If the iteration encounters an invalid +UTF-8 sequence, the second value will be 0xFFFD, +the Unicode replacement character, and the next iteration will advance +a single byte in the string. +
  4. + +
  5. +The iteration order over maps is not specified +and is not guaranteed to be the same from one iteration to the next. +If a map entry that has not yet been reached is removed during iteration, +the corresponding iteration value will not be produced. If a map entry is +created during iteration, that entry may be produced during the iteration or +may be skipped. The choice may vary for each entry created and from one +iteration to the next. +If the map is nil, the number of iterations is 0. +
  6. + +
  7. +For channels, the iteration values produced are the successive values sent on +the channel until the channel is closed. If the channel +is nil, the range expression blocks forever. +
  8. +
+ +

+The iteration values are assigned to the respective +iteration variables as in an assignment statement. +

+ +

+The iteration variables may be declared by the "range" clause using a form of +short variable declaration +(:=). +In this case their types are set to the types of the respective iteration values +and their scope is the block of the "for" +statement; they are re-used in each iteration. +If the iteration variables are declared outside the "for" statement, +after execution their values will be those of the last iteration. +

+ +
+var testdata *struct {
+	a *[7]int
+}
+for i, _ := range testdata.a {
+	// testdata.a is never evaluated; len(testdata.a) is constant
+	// i ranges from 0 to 6
+	f(i)
+}
+
+var a [10]string
+for i, s := range a {
+	// type of i is int
+	// type of s is string
+	// s == a[i]
+	g(i, s)
+}
+
+var key string
+var val interface{}  // element type of m is assignable to val
+m := map[string]int{"mon":0, "tue":1, "wed":2, "thu":3, "fri":4, "sat":5, "sun":6}
+for key, val = range m {
+	h(key, val)
+}
+// key == last map key encountered in iteration
+// val == map[key]
+
+var ch chan Work = producer()
+for w := range ch {
+	doWork(w)
+}
+
+// empty a channel
+for range ch {}
+
+ + +

Go statements

+ +

+A "go" statement starts the execution of a function call +as an independent concurrent thread of control, or goroutine, +within the same address space. +

+ +
+GoStmt = "go" Expression .
+
+ +

+The expression must be a function or method call; it cannot be parenthesized. +Calls of built-in functions are restricted as for +expression statements. +

+ +

+The function value and parameters are +evaluated as usual +in the calling goroutine, but +unlike with a regular call, program execution does not wait +for the invoked function to complete. +Instead, the function begins executing independently +in a new goroutine. +When the function terminates, its goroutine also terminates. +If the function has any return values, they are discarded when the +function completes. +

+ +
+go Server()
+go func(ch chan<- bool) { for { sleep(10); ch <- true }} (c)
+
+ + +

Select statements

+ +

+A "select" statement chooses which of a set of possible +send or +receive +operations will proceed. +It looks similar to a +"switch" statement but with the +cases all referring to communication operations. +

+ +
+SelectStmt = "select" "{" { CommClause } "}" .
+CommClause = CommCase ":" StatementList .
+CommCase   = "case" ( SendStmt | RecvStmt ) | "default" .
+RecvStmt   = [ ExpressionList "=" | IdentifierList ":=" ] RecvExpr .
+RecvExpr   = Expression .
+
+ +

+A case with a RecvStmt may assign the result of a RecvExpr to one or +two variables, which may be declared using a +short variable declaration. +The RecvExpr must be a (possibly parenthesized) receive operation. +There can be at most one default case and it may appear anywhere +in the list of cases. +

+ +

+Execution of a "select" statement proceeds in several steps: +

+ +
    +
  1. +For all the cases in the statement, the channel operands of receive operations +and the channel and right-hand-side expressions of send statements are +evaluated exactly once, in source order, upon entering the "select" statement. +The result is a set of channels to receive from or send to, +and the corresponding values to send. +Any side effects in that evaluation will occur irrespective of which (if any) +communication operation is selected to proceed. +Expressions on the left-hand side of a RecvStmt with a short variable declaration +or assignment are not yet evaluated. +
  2. + +
  3. +If one or more of the communications can proceed, +a single one that can proceed is chosen via a uniform pseudo-random selection. +Otherwise, if there is a default case, that case is chosen. +If there is no default case, the "select" statement blocks until +at least one of the communications can proceed. +
  4. + +
  5. +Unless the selected case is the default case, the respective communication +operation is executed. +
  6. + +
  7. +If the selected case is a RecvStmt with a short variable declaration or +an assignment, the left-hand side expressions are evaluated and the +received value (or values) are assigned. +
  8. + +
  9. +The statement list of the selected case is executed. +
  10. +
+ +

+Since communication on nil channels can never proceed, +a select with only nil channels and no default case blocks forever. +

+ +
+var a []int
+var c, c1, c2, c3, c4 chan int
+var i1, i2 int
+select {
+case i1 = <-c1:
+	print("received ", i1, " from c1\n")
+case c2 <- i2:
+	print("sent ", i2, " to c2\n")
+case i3, ok := (<-c3):  // same as: i3, ok := <-c3
+	if ok {
+		print("received ", i3, " from c3\n")
+	} else {
+		print("c3 is closed\n")
+	}
+case a[f()] = <-c4:
+	// same as:
+	// case t := <-c4
+	//	a[f()] = t
+default:
+	print("no communication\n")
+}
+
+for {  // send random sequence of bits to c
+	select {
+	case c <- 0:  // note: no statement, no fallthrough, no folding of cases
+	case c <- 1:
+	}
+}
+
+select {}  // block forever
+
+ + +

Return statements

+ +

+A "return" statement in a function F terminates the execution +of F, and optionally provides one or more result values. +Any functions deferred by F +are executed before F returns to its caller. +

+ +
+ReturnStmt = "return" [ ExpressionList ] .
+
+ +

+In a function without a result type, a "return" statement must not +specify any result values. +

+
+func noResult() {
+	return
+}
+
+ +

+There are three ways to return values from a function with a result +type: +

+ +
    +
  1. The return value or values may be explicitly listed + in the "return" statement. Each expression must be single-valued + and assignable + to the corresponding element of the function's result type. +
    +func simpleF() int {
    +	return 2
    +}
    +
    +func complexF1() (re float64, im float64) {
    +	return -7.0, -4.0
    +}
    +
    +
  2. +
  3. The expression list in the "return" statement may be a single + call to a multi-valued function. The effect is as if each value + returned from that function were assigned to a temporary + variable with the type of the respective value, followed by a + "return" statement listing these variables, at which point the + rules of the previous case apply. +
    +func complexF2() (re float64, im float64) {
    +	return complexF1()
    +}
    +
    +
  4. +
  5. The expression list may be empty if the function's result + type specifies names for its result parameters. + The result parameters act as ordinary local variables + and the function may assign values to them as necessary. + The "return" statement returns the values of these variables. +
    +func complexF3() (re float64, im float64) {
    +	re = 7.0
    +	im = 4.0
    +	return
    +}
    +
    +func (devnull) Write(p []byte) (n int, _ error) {
    +	n = len(p)
    +	return
    +}
    +
    +
  6. +
+ +

+Regardless of how they are declared, all the result values are initialized to +the zero values for their type upon entry to the +function. A "return" statement that specifies results sets the result parameters before +any deferred functions are executed. +

+ +

+Implementation restriction: A compiler may disallow an empty expression list +in a "return" statement if a different entity (constant, type, or variable) +with the same name as a result parameter is in +scope at the place of the return. +

+ +
+func f(n int) (res int, err error) {
+	if _, err := f(n-1); err != nil {
+		return  // invalid return statement: err is shadowed
+	}
+	return
+}
+
+ +

Break statements

+ +

+A "break" statement terminates execution of the innermost +"for", +"switch", or +"select" statement +within the same function. +

+ +
+BreakStmt = "break" [ Label ] .
+
+ +

+If there is a label, it must be that of an enclosing +"for", "switch", or "select" statement, +and that is the one whose execution terminates. +

+ +
+OuterLoop:
+	for i = 0; i < n; i++ {
+		for j = 0; j < m; j++ {
+			switch a[i][j] {
+			case nil:
+				state = Error
+				break OuterLoop
+			case item:
+				state = Found
+				break OuterLoop
+			}
+		}
+	}
+
+ +

Continue statements

+ +

+A "continue" statement begins the next iteration of the +innermost "for" loop at its post statement. +The "for" loop must be within the same function. +

+ +
+ContinueStmt = "continue" [ Label ] .
+
+ +

+If there is a label, it must be that of an enclosing +"for" statement, and that is the one whose execution +advances. +

+ +
+RowLoop:
+	for y, row := range rows {
+		for x, data := range row {
+			if data == endOfRow {
+				continue RowLoop
+			}
+			row[x] = data + bias(x, y)
+		}
+	}
+
+ +

Goto statements

+ +

+A "goto" statement transfers control to the statement with the corresponding label +within the same function. +

+ +
+GotoStmt = "goto" Label .
+
+ +
+goto Error
+
+ +

+Executing the "goto" statement must not cause any variables to come into +scope that were not already in scope at the point of the goto. +For instance, this example: +

+ +
+	goto L  // BAD
+	v := 3
+L:
+
+ +

+is erroneous because the jump to label L skips +the creation of v. +

+ +

+A "goto" statement outside a block cannot jump to a label inside that block. +For instance, this example: +

+ +
+if n%2 == 1 {
+	goto L1
+}
+for n > 0 {
+	f()
+	n--
+L1:
+	f()
+	n--
+}
+
+ +

+is erroneous because the label L1 is inside +the "for" statement's block but the goto is not. +

+ +

Fallthrough statements

+ +

+A "fallthrough" statement transfers control to the first statement of the +next case clause in an expression "switch" statement. +It may be used only as the final non-empty statement in such a clause. +

+ +
+FallthroughStmt = "fallthrough" .
+
+ + +

Defer statements

+ +

+A "defer" statement invokes a function whose execution is deferred +to the moment the surrounding function returns, either because the +surrounding function executed a return statement, +reached the end of its function body, +or because the corresponding goroutine is panicking. +

+ +
+DeferStmt = "defer" Expression .
+
+ +

+The expression must be a function or method call; it cannot be parenthesized. +Calls of built-in functions are restricted as for +expression statements. +

+ +

+Each time a "defer" statement +executes, the function value and parameters to the call are +evaluated as usual +and saved anew but the actual function is not invoked. +Instead, deferred functions are invoked immediately before +the surrounding function returns, in the reverse order +they were deferred. That is, if the surrounding function +returns through an explicit return statement, +deferred functions are executed after any result parameters are set +by that return statement but before the function returns to its caller. +If a deferred function value evaluates +to nil, execution panics +when the function is invoked, not when the "defer" statement is executed. +

+ +

+For instance, if the deferred function is +a function literal and the surrounding +function has named result parameters that +are in scope within the literal, the deferred function may access and modify +the result parameters before they are returned. +If the deferred function has any return values, they are discarded when +the function completes. +(See also the section on handling panics.) +

+ +
+lock(l)
+defer unlock(l)  // unlocking happens before surrounding function returns
+
+// prints 3 2 1 0 before surrounding function returns
+for i := 0; i <= 3; i++ {
+	defer fmt.Print(i)
+}
+
+// f returns 42
+func f() (result int) {
+	defer func() {
+		// result is accessed after it was set to 6 by the return statement
+		result *= 7
+	}()
+	return 6
+}
+
+ +

Built-in functions

+ +

+Built-in functions are +predeclared. +They are called like any other function but some of them +accept a type instead of an expression as the first argument. +

+ +

+The built-in functions do not have standard Go types, +so they can only appear in call expressions; +they cannot be used as function values. +

+ +

Close

+ +

+For a channel c, the built-in function close(c) +records that no more values will be sent on the channel. +It is an error if c is a receive-only channel. +Sending to or closing a closed channel causes a run-time panic. +Closing the nil channel also causes a run-time panic. +After calling close, and after any previously +sent values have been received, receive operations will return +the zero value for the channel's type without blocking. +The multi-valued receive operation +returns a received value along with an indication of whether the channel is closed. +

+ + +

Length and capacity

+ +

+The built-in functions len and cap take arguments +of various types and return a result of type int. +The implementation guarantees that the result always fits into an int. +

+ +
+Call      Argument type    Result
+
+len(s)    string type      string length in bytes
+          [n]T, *[n]T      array length (== n)
+          []T              slice length
+          map[K]T          map length (number of defined keys)
+          chan T           number of elements queued in channel buffer
+
+cap(s)    [n]T, *[n]T      array length (== n)
+          []T              slice capacity
+          chan T           channel buffer capacity
+
+ +

+The capacity of a slice is the number of elements for which there is +space allocated in the underlying array. +At any time the following relationship holds: +

+ +
+0 <= len(s) <= cap(s)
+
+ +

+The length of a nil slice, map or channel is 0. +The capacity of a nil slice or channel is 0. +

+ +

+The expression len(s) is constant if +s is a string constant. The expressions len(s) and +cap(s) are constants if the type of s is an array +or pointer to an array and the expression s does not contain +channel receives or (non-constant) +function calls; in this case s is not evaluated. +Otherwise, invocations of len and cap are not +constant and s is evaluated. +

+ +
+const (
+	c1 = imag(2i)                    // imag(2i) = 2.0 is a constant
+	c2 = len([10]float64{2})         // [10]float64{2} contains no function calls
+	c3 = len([10]float64{c1})        // [10]float64{c1} contains no function calls
+	c4 = len([10]float64{imag(2i)})  // imag(2i) is a constant and no function call is issued
+	c5 = len([10]float64{imag(z)})   // invalid: imag(z) is a (non-constant) function call
+)
+var z complex128
+
+ +

Allocation

+ +

+The built-in function new takes a type T, +allocates storage for a variable of that type +at run time, and returns a value of type *T +pointing to it. +The variable is initialized as described in the section on +initial values. +

+ +
+new(T)
+
+ +

+For instance +

+ +
+type S struct { a int; b float64 }
+new(S)
+
+ +

+allocates storage for a variable of type S, +initializes it (a=0, b=0.0), +and returns a value of type *S containing the address +of the location. +

+ +

Making slices, maps and channels

+ +

+The built-in function make takes a type T, +which must be a slice, map or channel type, +optionally followed by a type-specific list of expressions. +It returns a value of type T (not *T). +The memory is initialized as described in the section on +initial values. +

+ +
+Call             Type T     Result
+
+make(T, n)       slice      slice of type T with length n and capacity n
+make(T, n, m)    slice      slice of type T with length n and capacity m
+
+make(T)          map        map of type T
+make(T, n)       map        map of type T with initial space for approximately n elements
+
+make(T)          channel    unbuffered channel of type T
+make(T, n)       channel    buffered channel of type T, buffer size n
+
+ + +

+Each of the size arguments n and m must be of integer type +or an untyped constant. +A constant size argument must be non-negative and representable +by a value of type int; if it is an untyped constant it is given type int. +If both n and m are provided and are constant, then +n must be no larger than m. +If n is negative or larger than m at run time, +a run-time panic occurs. +

+ +
+s := make([]int, 10, 100)       // slice with len(s) == 10, cap(s) == 100
+s := make([]int, 1e3)           // slice with len(s) == cap(s) == 1000
+s := make([]int, 1<<63)         // illegal: len(s) is not representable by a value of type int
+s := make([]int, 10, 0)         // illegal: len(s) > cap(s)
+c := make(chan int, 10)         // channel with a buffer size of 10
+m := make(map[string]int, 100)  // map with initial space for approximately 100 elements
+
+ +

+Calling make with a map type and size hint n will +create a map with initial space to hold n map elements. +The precise behavior is implementation-dependent. +

+ + +

Appending to and copying slices

+ +

+The built-in functions append and copy assist in +common slice operations. +For both functions, the result is independent of whether the memory referenced +by the arguments overlaps. +

+ +

+The variadic function append +appends zero or more values x +to s of type S, which must be a slice type, and +returns the resulting slice, also of type S. +The values x are passed to a parameter of type ...T +where T is the element type of +S and the respective +parameter passing rules apply. +As a special case, append also accepts a first argument +assignable to type []byte with a second argument of +string type followed by .... This form appends the +bytes of the string. +

+ +
+append(s S, x ...T) S  // T is the element type of S
+
+ +

+If the capacity of s is not large enough to fit the additional +values, append allocates a new, sufficiently large underlying +array that fits both the existing slice elements and the additional values. +Otherwise, append re-uses the underlying array. +

+ +
+s0 := []int{0, 0}
+s1 := append(s0, 2)                // append a single element     s1 == []int{0, 0, 2}
+s2 := append(s1, 3, 5, 7)          // append multiple elements    s2 == []int{0, 0, 2, 3, 5, 7}
+s3 := append(s2, s0...)            // append a slice              s3 == []int{0, 0, 2, 3, 5, 7, 0, 0}
+s4 := append(s3[3:6], s3[2:]...)   // append overlapping slice    s4 == []int{3, 5, 7, 2, 3, 5, 7, 0, 0}
+
+var t []interface{}
+t = append(t, 42, 3.1415, "foo")   //                             t == []interface{}{42, 3.1415, "foo"}
+
+var b []byte
+b = append(b, "bar"...)            // append string contents      b == []byte{'b', 'a', 'r' }
+
+ +

+The function copy copies slice elements from +a source src to a destination dst and returns the +number of elements copied. +Both arguments must have identical element type T and must be +assignable to a slice of type []T. +The number of elements copied is the minimum of +len(src) and len(dst). +As a special case, copy also accepts a destination argument assignable +to type []byte with a source argument of a string type. +This form copies the bytes from the string into the byte slice. +

+ +
+copy(dst, src []T) int
+copy(dst []byte, src string) int
+
+ +

+Examples: +

+ +
+var a = [...]int{0, 1, 2, 3, 4, 5, 6, 7}
+var s = make([]int, 6)
+var b = make([]byte, 5)
+n1 := copy(s, a[0:])            // n1 == 6, s == []int{0, 1, 2, 3, 4, 5}
+n2 := copy(s, s[2:])            // n2 == 4, s == []int{2, 3, 4, 5, 4, 5}
+n3 := copy(b, "Hello, World!")  // n3 == 5, b == []byte("Hello")
+
+ + +

Deletion of map elements

+ +

+The built-in function delete removes the element with key +k from a map m. The +type of k must be assignable +to the key type of m. +

+ +
+delete(m, k)  // remove element m[k] from map m
+
+ +

+If the map m is nil or the element m[k] +does not exist, delete is a no-op. +

+ + +

Manipulating complex numbers

+ +

+Three functions assemble and disassemble complex numbers. +The built-in function complex constructs a complex +value from a floating-point real and imaginary part, while +real and imag +extract the real and imaginary parts of a complex value. +

+ +
+complex(realPart, imaginaryPart floatT) complexT
+real(complexT) floatT
+imag(complexT) floatT
+
+ +

+The type of the arguments and return value correspond. +For complex, the two arguments must be of the same +floating-point type and the return type is the complex type +with the corresponding floating-point constituents: +complex64 for float32 arguments, and +complex128 for float64 arguments. +If one of the arguments evaluates to an untyped constant, it is first implicitly +converted to the type of the other argument. +If both arguments evaluate to untyped constants, they must be non-complex +numbers or their imaginary parts must be zero, and the return value of +the function is an untyped complex constant. +

+ +

+For real and imag, the argument must be +of complex type, and the return type is the corresponding floating-point +type: float32 for a complex64 argument, and +float64 for a complex128 argument. +If the argument evaluates to an untyped constant, it must be a number, +and the return value of the function is an untyped floating-point constant. +

+ +

+The real and imag functions together form the inverse of +complex, so for a value z of a complex type Z, +z == Z(complex(real(z), imag(z))). +

+ +

+If the operands of these functions are all constants, the return +value is a constant. +

+ +
+var a = complex(2, -2)             // complex128
+const b = complex(1.0, -1.4)       // untyped complex constant 1 - 1.4i
+x := float32(math.Cos(math.Pi/2))  // float32
+var c64 = complex(5, -x)           // complex64
+var s int = complex(1, 0)          // untyped complex constant 1 + 0i can be converted to int
+_ = complex(1, 2<<s)               // illegal: 2 assumes floating-point type, cannot shift
+var rl = real(c64)                 // float32
+var im = imag(a)                   // float64
+const c = imag(b)                  // untyped constant -1.4
+_ = imag(3 << s)                   // illegal: 3 assumes complex type, cannot shift
+
+ +

Handling panics

+ +

Two built-in functions, panic and recover, +assist in reporting and handling run-time panics +and program-defined error conditions. +

+ +
+func panic(interface{})
+func recover() interface{}
+
+ +

+While executing a function F, +an explicit call to panic or a run-time panic +terminates the execution of F. +Any functions deferred by F +are then executed as usual. +Next, any deferred functions run by F's caller are run, +and so on up to any deferred by the top-level function in the executing goroutine. +At that point, the program is terminated and the error +condition is reported, including the value of the argument to panic. +This termination sequence is called panicking. +

+ +
+panic(42)
+panic("unreachable")
+panic(Error("cannot parse"))
+
+ +

+The recover function allows a program to manage behavior +of a panicking goroutine. +Suppose a function G defers a function D that calls +recover and a panic occurs in a function on the same goroutine in which G +is executing. +When the running of deferred functions reaches D, +the return value of D's call to recover will be the value passed to the call of panic. +If D returns normally, without starting a new +panic, the panicking sequence stops. In that case, +the state of functions called between G and the call to panic +is discarded, and normal execution resumes. +Any functions deferred by G before D are then run and G's +execution terminates by returning to its caller. +

+ +

+The return value of recover is nil if any of the following conditions holds: +

+
    +
  • +panic's argument was nil; +
  • +
  • +the goroutine is not panicking; +
  • +
  • +recover was not called directly by a deferred function. +
  • +
+ +

+The protect function in the example below invokes +the function argument g and protects callers from +run-time panics raised by g. +

+ +
+func protect(g func()) {
+	defer func() {
+		log.Println("done")  // Println executes normally even if there is a panic
+		if x := recover(); x != nil {
+			log.Printf("run time panic: %v", x)
+		}
+	}()
+	log.Println("start")
+	g()
+}
+
+ + +

Bootstrapping

+ +

+Current implementations provide several built-in functions useful during +bootstrapping. These functions are documented for completeness but are not +guaranteed to stay in the language. They do not return a result. +

+ +
+Function   Behavior
+
+print      prints all arguments; formatting of arguments is implementation-specific
+println    like print but prints spaces between arguments and a newline at the end
+
+ +

+Implementation restriction: print and println need not +accept arbitrary argument types, but printing of boolean, numeric, and string +types must be supported. +

+ +

Packages

+ +

+Go programs are constructed by linking together packages. +A package in turn is constructed from one or more source files +that together declare constants, types, variables and functions +belonging to the package and which are accessible in all files +of the same package. Those elements may be +exported and used in another package. +

+ +

Source file organization

+ +

+Each source file consists of a package clause defining the package +to which it belongs, followed by a possibly empty set of import +declarations that declare packages whose contents it wishes to use, +followed by a possibly empty set of declarations of functions, +types, variables, and constants. +

+ +
+SourceFile       = PackageClause ";" { ImportDecl ";" } { TopLevelDecl ";" } .
+
+ +

Package clause

+ +

+A package clause begins each source file and defines the package +to which the file belongs. +

+ +
+PackageClause  = "package" PackageName .
+PackageName    = identifier .
+
+ +

+The PackageName must not be the blank identifier. +

+ +
+package math
+
+ +

+A set of files sharing the same PackageName form the implementation of a package. +An implementation may require that all source files for a package inhabit the same directory. +

+ +

Import declarations

+ +

+An import declaration states that the source file containing the declaration +depends on functionality of the imported package +(§Program initialization and execution) +and enables access to exported identifiers +of that package. +The import names an identifier (PackageName) to be used for access and an ImportPath +that specifies the package to be imported. +

+ +
+ImportDecl       = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) .
+ImportSpec       = [ "." | PackageName ] ImportPath .
+ImportPath       = string_lit .
+
+ +

+The PackageName is used in qualified identifiers +to access exported identifiers of the package within the importing source file. +It is declared in the file block. +If the PackageName is omitted, it defaults to the identifier specified in the +package clause of the imported package. +If an explicit period (.) appears instead of a name, all the +package's exported identifiers declared in that package's +package block will be declared in the importing source +file's file block and must be accessed without a qualifier. +

+ +

+The interpretation of the ImportPath is implementation-dependent but +it is typically a substring of the full file name of the compiled +package and may be relative to a repository of installed packages. +

+ +

+Implementation restriction: A compiler may restrict ImportPaths to +non-empty strings using only characters belonging to +Unicode's +L, M, N, P, and S general categories (the Graphic characters without +spaces) and may also exclude the characters +!"#$%&'()*,:;<=>?[\]^`{|} +and the Unicode replacement character U+FFFD. +

+ +

+Assume we have compiled a package containing the package clause +package math, which exports function Sin, and +installed the compiled package in the file identified by +"lib/math". +This table illustrates how Sin is accessed in files +that import the package after the +various types of import declaration. +

+ +
+Import declaration          Local name of Sin
+
+import   "lib/math"         math.Sin
+import m "lib/math"         m.Sin
+import . "lib/math"         Sin
+
+ +

+An import declaration declares a dependency relation between +the importing and imported package. +It is illegal for a package to import itself, directly or indirectly, +or to directly import a package without +referring to any of its exported identifiers. To import a package solely for +its side-effects (initialization), use the blank +identifier as explicit package name: +

+ +
+import _ "lib/math"
+
+ + +

An example package

+ +

+Here is a complete Go package that implements a concurrent prime sieve. +

+ +
+package main
+
+import "fmt"
+
+// Send the sequence 2, 3, 4, … to channel 'ch'.
+func generate(ch chan<- int) {
+	for i := 2; ; i++ {
+		ch <- i  // Send 'i' to channel 'ch'.
+	}
+}
+
+// Copy the values from channel 'src' to channel 'dst',
+// removing those divisible by 'prime'.
+func filter(src <-chan int, dst chan<- int, prime int) {
+	for i := range src {  // Loop over values received from 'src'.
+		if i%prime != 0 {
+			dst <- i  // Send 'i' to channel 'dst'.
+		}
+	}
+}
+
+// The prime sieve: Daisy-chain filter processes together.
+func sieve() {
+	ch := make(chan int)  // Create a new channel.
+	go generate(ch)       // Start generate() as a subprocess.
+	for {
+		prime := <-ch
+		fmt.Print(prime, "\n")
+		ch1 := make(chan int)
+		go filter(ch, ch1, prime)
+		ch = ch1
+	}
+}
+
+func main() {
+	sieve()
+}
+
+ +

Program initialization and execution

+ +

The zero value

+

+When storage is allocated for a variable, +either through a declaration or a call of new, or when +a new value is created, either through a composite literal or a call +of make, +and no explicit initialization is provided, the variable or value is +given a default value. Each element of such a variable or value is +set to the zero value for its type: false for booleans, +0 for numeric types, "" +for strings, and nil for pointers, functions, interfaces, slices, channels, and maps. +This initialization is done recursively, so for instance each element of an +array of structs will have its fields zeroed if no value is specified. +

+

+These two simple declarations are equivalent: +

+ +
+var i int
+var i int = 0
+
+ +

+After +

+ +
+type T struct { i int; f float64; next *T }
+t := new(T)
+
+ +

+the following holds: +

+ +
+t.i == 0
+t.f == 0.0
+t.next == nil
+
+ +

+The same would also be true after +

+ +
+var t T
+
+ +

Package initialization

+ +

+Within a package, package-level variable initialization proceeds stepwise, +with each step selecting the variable earliest in declaration order +which has no dependencies on uninitialized variables. +

+ +

+More precisely, a package-level variable is considered ready for +initialization if it is not yet initialized and either has +no initialization expression or +its initialization expression has no dependencies on uninitialized variables. +Initialization proceeds by repeatedly initializing the next package-level +variable that is earliest in declaration order and ready for initialization, +until there are no variables ready for initialization. +

+ +

+If any variables are still uninitialized when this +process ends, those variables are part of one or more initialization cycles, +and the program is not valid. +

+ +

+Multiple variables on the left-hand side of a variable declaration initialized +by single (multi-valued) expression on the right-hand side are initialized +together: If any of the variables on the left-hand side is initialized, all +those variables are initialized in the same step. +

+ +
+var x = a
+var a, b = f() // a and b are initialized together, before x is initialized
+
+ +

+For the purpose of package initialization, blank +variables are treated like any other variables in declarations. +

+ +

+The declaration order of variables declared in multiple files is determined +by the order in which the files are presented to the compiler: Variables +declared in the first file are declared before any of the variables declared +in the second file, and so on. +

+ +

+Dependency analysis does not rely on the actual values of the +variables, only on lexical references to them in the source, +analyzed transitively. For instance, if a variable x's +initialization expression refers to a function whose body refers to +variable y then x depends on y. +Specifically: +

+ +
    +
  • +A reference to a variable or function is an identifier denoting that +variable or function. +
  • + +
  • +A reference to a method m is a +method value or +method expression of the form +t.m, where the (static) type of t is +not an interface type, and the method m is in the +method set of t. +It is immaterial whether the resulting function value +t.m is invoked. +
  • + +
  • +A variable, function, or method x depends on a variable +y if x's initialization expression or body +(for functions and methods) contains a reference to y +or to a function or method that depends on y. +
  • +
+ +

+For example, given the declarations +

+ +
+var (
+	a = c + b  // == 9
+	b = f()    // == 4
+	c = f()    // == 5
+	d = 3      // == 5 after initialization has finished
+)
+
+func f() int {
+	d++
+	return d
+}
+
+ +

+the initialization order is d, b, c, a. +Note that the order of subexpressions in initialization expressions is irrelevant: +a = c + b and a = b + c result in the same initialization +order in this example. +

+ +

+Dependency analysis is performed per package; only references referring +to variables, functions, and (non-interface) methods declared in the current +package are considered. If other, hidden, data dependencies exists between +variables, the initialization order between those variables is unspecified. +

+ +

+For instance, given the declarations +

+ +
+var x = I(T{}).ab()   // x has an undetected, hidden dependency on a and b
+var _ = sideEffect()  // unrelated to x, a, or b
+var a = b
+var b = 42
+
+type I interface      { ab() []int }
+type T struct{}
+func (T) ab() []int   { return []int{a, b} }
+
+ +

+the variable a will be initialized after b but +whether x is initialized before b, between +b and a, or after a, and +thus also the moment at which sideEffect() is called (before +or after x is initialized) is not specified. +

+ +

+Variables may also be initialized using functions named init +declared in the package block, with no arguments and no result parameters. +

+ +
+func init() { … }
+
+ +

+Multiple such functions may be defined per package, even within a single +source file. In the package block, the init identifier can +be used only to declare init functions, yet the identifier +itself is not declared. Thus +init functions cannot be referred to from anywhere +in a program. +

+ +

+A package with no imports is initialized by assigning initial values +to all its package-level variables followed by calling all init +functions in the order they appear in the source, possibly in multiple files, +as presented to the compiler. +If a package has imports, the imported packages are initialized +before initializing the package itself. If multiple packages import +a package, the imported package will be initialized only once. +The importing of packages, by construction, guarantees that there +can be no cyclic initialization dependencies. +

+ +

+Package initialization—variable initialization and the invocation of +init functions—happens in a single goroutine, +sequentially, one package at a time. +An init function may launch other goroutines, which can run +concurrently with the initialization code. However, initialization +always sequences +the init functions: it will not invoke the next one +until the previous one has returned. +

+ +

+To ensure reproducible initialization behavior, build systems are encouraged +to present multiple files belonging to the same package in lexical file name +order to a compiler. +

+ + +

Program execution

+

+A complete program is created by linking a single, unimported package +called the main package with all the packages it imports, transitively. +The main package must +have package name main and +declare a function main that takes no +arguments and returns no value. +

+ +
+func main() { … }
+
+ +

+Program execution begins by initializing the main package and then +invoking the function main. +When that function invocation returns, the program exits. +It does not wait for other (non-main) goroutines to complete. +

+ +

Errors

+ +

+The predeclared type error is defined as +

+ +
+type error interface {
+	Error() string
+}
+
+ +

+It is the conventional interface for representing an error condition, +with the nil value representing no error. +For instance, a function to read data from a file might be defined: +

+ +
+func Read(f *File, b []byte) (n int, err error)
+
+ +

Run-time panics

+ +

+Execution errors such as attempting to index an array out +of bounds trigger a run-time panic equivalent to a call of +the built-in function panic +with a value of the implementation-defined interface type runtime.Error. +That type satisfies the predeclared interface type +error. +The exact error values that +represent distinct run-time error conditions are unspecified. +

+ +
+package runtime
+
+type Error interface {
+	error
+	// and perhaps other methods
+}
+
+ +

System considerations

+ +

Package unsafe

+ +

+The built-in package unsafe, known to the compiler +and accessible through the import path "unsafe", +provides facilities for low-level programming including operations +that violate the type system. A package using unsafe +must be vetted manually for type safety and may not be portable. +The package provides the following interface: +

+ +
+package unsafe
+
+type ArbitraryType int  // shorthand for an arbitrary Go type; it is not a real type
+type Pointer *ArbitraryType
+
+func Alignof(variable ArbitraryType) uintptr
+func Offsetof(selector ArbitraryType) uintptr
+func Sizeof(variable ArbitraryType) uintptr
+
+type IntegerType int  // shorthand for an integer type; it is not a real type
+func Add(ptr Pointer, len IntegerType) Pointer
+func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType
+
+ +

+A Pointer is a pointer type but a Pointer +value may not be dereferenced. +Any pointer or value of underlying type uintptr can be converted to +a type of underlying type Pointer and vice versa. +The effect of converting between Pointer and uintptr is implementation-defined. +

+ +
+var f float64
+bits = *(*uint64)(unsafe.Pointer(&f))
+
+type ptr unsafe.Pointer
+bits = *(*uint64)(ptr(&f))
+
+var p ptr = nil
+
+ +

+The functions Alignof and Sizeof take an expression x +of any type and return the alignment or size, respectively, of a hypothetical variable v +as if v was declared via var v = x. +

+

+The function Offsetof takes a (possibly parenthesized) selector +s.f, denoting a field f of the struct denoted by s +or *s, and returns the field offset in bytes relative to the struct's address. +If f is an embedded field, it must be reachable +without pointer indirections through fields of the struct. +For a struct s with field f: +

+ +
+uintptr(unsafe.Pointer(&s)) + unsafe.Offsetof(s.f) == uintptr(unsafe.Pointer(&s.f))
+
+ +

+Computer architectures may require memory addresses to be aligned; +that is, for addresses of a variable to be a multiple of a factor, +the variable's type's alignment. The function Alignof +takes an expression denoting a variable of any type and returns the +alignment of the (type of the) variable in bytes. For a variable +x: +

+ +
+uintptr(unsafe.Pointer(&x)) % unsafe.Alignof(x) == 0
+
+ +

+Calls to Alignof, Offsetof, and +Sizeof are compile-time constant expressions of type uintptr. +

+ +

+The function Add adds len to ptr +and returns the updated pointer unsafe.Pointer(uintptr(ptr) + uintptr(len)). +The len argument must be of integer type or an untyped constant. +A constant len argument must be representable by a value of type int; +if it is an untyped constant it is given type int. +The rules for valid uses of Pointer still apply. +

+ +

+The function Slice returns a slice whose underlying array starts at ptr +and whose length and capacity are len. +Slice(ptr, len) is equivalent to +

+ +
+(*[len]ArbitraryType)(unsafe.Pointer(ptr))[:]
+
+ +

+except that, as a special case, if ptr +is nil and len is zero, +Slice returns nil. +

+ +

+The len argument must be of integer type or an untyped constant. +A constant len argument must be non-negative and representable by a value of type int; +if it is an untyped constant it is given type int. +At run time, if len is negative, +or if ptr is nil and len is not zero, +a run-time panic occurs. +

+ +

Size and alignment guarantees

+ +

+For the numeric types, the following sizes are guaranteed: +

+ +
+type                                 size in bytes
+
+byte, uint8, int8                     1
+uint16, int16                         2
+uint32, int32, float32                4
+uint64, int64, float64, complex64     8
+complex128                           16
+
+ +

+The following minimal alignment properties are guaranteed: +

+
    +
  1. For a variable x of any type: unsafe.Alignof(x) is at least 1. +
  2. + +
  3. For a variable x of struct type: unsafe.Alignof(x) is the largest of + all the values unsafe.Alignof(x.f) for each field f of x, but at least 1. +
  4. + +
  5. For a variable x of array type: unsafe.Alignof(x) is the same as + the alignment of a variable of the array's element type. +
  6. +
+ +

+A struct or array type has size zero if it contains no fields (or elements, respectively) that have a size greater than zero. Two distinct zero-size variables may have the same address in memory. +

-- GitLab From 0aa194f7589fb5f75fc3a9c34bb69943daf6fc5c Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 9 Nov 2021 21:12:03 -0800 Subject: [PATCH 2096/2500] cmd/compile/internal/types2: use type variables consistently in Checker.conversion We have V and T and Vu and Tu. When calling the various isX predicates consistently use Vu and Tu. (We could also use V an T because the predicates call under anyway, but using Vu and Tu removes an unnecessary call to Named.under if V or T are *Named.) Also, removed some outdated comments. Change-Id: I6fcd9ce5f6292e89ac2afd597b72fd0790e84ff1 Reviewed-on: https://go-review.googlesource.com/c/go/+/362895 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- .../compile/internal/types2/conversions.go | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go index dd89f29762..7f93e2467f 100644 --- a/src/cmd/compile/internal/types2/conversions.go +++ b/src/cmd/compile/internal/types2/conversions.go @@ -142,39 +142,39 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { } // "V and T are both integer or floating point types" - if isIntegerOrFloat(V) && isIntegerOrFloat(T) { + if isIntegerOrFloat(Vu) && isIntegerOrFloat(Tu) { return true } // "V and T are both complex types" - if isComplex(V) && isComplex(T) { + if isComplex(Vu) && isComplex(Tu) { return true } // "V is an integer or a slice of bytes or runes and T is a string type" - if (isInteger(V) || isBytesOrRunes(Vu)) && isString(T) { + if (isInteger(Vu) || isBytesOrRunes(Vu)) && isString(Tu) { return true } // "V is a string and T is a slice of bytes or runes" - if isString(V) && isBytesOrRunes(Tu) { + if isString(Vu) && isBytesOrRunes(Tu) { return true } // package unsafe: // "any pointer or value of underlying type uintptr can be converted into a unsafe.Pointer" - if (isPointer(Vu) || isUintptr(Vu)) && isUnsafePointer(T) { + if (isPointer(Vu) || isUintptr(Vu)) && isUnsafePointer(Tu) { return true } // "and vice versa" - if isUnsafePointer(V) && (isPointer(Tu) || isUintptr(Tu)) { + if isUnsafePointer(Vu) && (isPointer(Tu) || isUintptr(Tu)) { return true } // "V a slice, T is a pointer-to-array type, // and the slice and array types have identical element types." - if s, _ := under(V).(*Slice); s != nil { - if p, _ := under(T).(*Pointer); p != nil { + if s, _ := Vu.(*Slice); s != nil { + if p, _ := Tu.(*Pointer); p != nil { if a, _ := under(p.Elem()).(*Array); a != nil { if Identical(s.Elem(), a.Elem()) { if check == nil || check.allowVersion(check.pkg, 1, 17) { @@ -257,20 +257,12 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { return false } -// Helper predicates for convertibleToImpl. The types provided to convertibleToImpl -// may be type parameters but they won't have specific type terms. Thus it is ok to -// use the toT convenience converters in the predicates below. - func isUintptr(typ Type) bool { t, _ := under(typ).(*Basic) return t != nil && t.kind == Uintptr } func isUnsafePointer(typ Type) bool { - // TODO(gri): Is this under(typ).(*Basic) instead of typ.(*Basic) correct? - // (The former calls under(), while the latter doesn't.) - // The spec does not say so, but gc claims it is. See also - // issue 6326. t, _ := under(typ).(*Basic) return t != nil && t.kind == UnsafePointer } -- GitLab From 8a3be150775f80850e179bd1860b286be27ca407 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 10 Nov 2021 08:12:21 -0800 Subject: [PATCH 2097/2500] cmd/compile/internal/types2: rename structure to structuralType And rename structureString to structuralString. Now that we have an updated definition for structural types in the (forthcoming) spec, name the corresponding function accordingly. No semantic changes. Change-Id: Iab838f01a37075bedf2d8bc4f166b0217672b85f Reviewed-on: https://go-review.googlesource.com/c/go/+/362994 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley TryBot-Result: Go Bot --- src/cmd/compile/internal/types2/builtins.go | 24 +++++++++---------- src/cmd/compile/internal/types2/call.go | 2 +- src/cmd/compile/internal/types2/expr.go | 2 +- src/cmd/compile/internal/types2/index.go | 2 +- src/cmd/compile/internal/types2/infer.go | 2 +- src/cmd/compile/internal/types2/predicates.go | 4 ++-- src/cmd/compile/internal/types2/stmt.go | 2 +- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 916aed40b3..4c659d65cd 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -82,7 +82,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( // of S and the respective parameter passing rules apply." S := x.typ var T Type - if s, _ := structure(S).(*Slice); s != nil { + if s, _ := structuralType(S).(*Slice); s != nil { T = s.elem } else { check.errorf(x, invalidArg+"%s is not a slice", x) @@ -327,14 +327,14 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( case _Copy: // copy(x, y []T) int - dst, _ := structure(x.typ).(*Slice) + dst, _ := structuralType(x.typ).(*Slice) var y operand arg(&y, 1) if y.mode == invalid { return } - src, _ := structureString(y.typ).(*Slice) + src, _ := structuralString(y.typ).(*Slice) if dst == nil || src == nil { check.errorf(x, invalidArg+"copy expects slice arguments; found %s and %s", x, &y) @@ -464,7 +464,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( } var min int // minimum number of arguments - switch structure(T).(type) { + switch structuralType(T).(type) { case *Slice: min = 2 case *Map, *Chan: @@ -774,14 +774,14 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( // or nil otherwise. If typ is not a type parameter, Structure returns // the underlying type. func Structure(typ Type) Type { - return structure(typ) + return structuralType(typ) } -// If typ is a type parameter, structure returns the single underlying -// type of all types in the corresponding type constraint if it exists, -// or nil otherwise. If typ is not a type parameter, structure returns +// If typ is a type parameter, structuralType returns the single underlying +// type of all types in the corresponding type constraint if it exists, or +// nil otherwise. If typ is not a type parameter, structuralType returns // the underlying type. -func structure(typ Type) Type { +func structuralType(typ Type) Type { var su Type if underIs(typ, func(u Type) bool { if su != nil && !Identical(su, u) { @@ -796,10 +796,10 @@ func structure(typ Type) Type { return nil } -// structureString is like structure but also considers []byte and -// string as "identical". In this case, if successful, the result +// structuralString is like structuralType but also considers []byte +// and string as "identical". In this case, if successful, the result // is always []byte. -func structureString(typ Type) Type { +func structuralString(typ Type) Type { var su Type if underIs(typ, func(u Type) bool { if isString(u) { diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 3a571285c1..0540feaa78 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -170,7 +170,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { cgocall := x.mode == cgofunc // a type parameter may be "called" if all types have the same signature - sig, _ := structure(x.typ).(*Signature) + sig, _ := structuralType(x.typ).(*Signature) if sig == nil { check.errorf(x, invalidOp+"cannot call non-function %s", x) x.mode = invalid diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 8125fba717..169417016f 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -1258,7 +1258,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin goto Error } - switch utyp := structure(base).(type) { + switch utyp := structuralType(base).(type) { case *Struct: // Prevent crash if the struct referred to is not yet set up. // See analogous comment for *Array. diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index f096674536..10e85ef6e1 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -210,7 +210,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { valid := false length := int64(-1) // valid if >= 0 - switch u := structure(x.typ).(type) { + switch u := structuralType(x.typ).(type) { case nil: check.errorf(x, invalidOp+"cannot slice %s: type set has no single underlying type", x) x.mode = invalid diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index 24c461f1c3..4f85a5894c 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -378,7 +378,7 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type, // If a constraint has a structural type, unify the corresponding type parameter with it. for _, tpar := range tparams { - sbound := structure(tpar) + sbound := structuralType(tpar) if sbound != nil { // If the structural type is the underlying type of a single // defined type in the constraint, use that defined type instead. diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 8d676ed8f6..f1fd33c5de 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -31,7 +31,7 @@ func isBasic(t Type, info BasicInfo) bool { // The allX predicates below report whether t is an X. // If t is a type parameter the result is true if isX is true // for all specified types of the type parameter's type set. -// allX is an optimized version of isX(structure(t)) (which +// allX is an optimized version of isX(structuralType(t)) (which // is the same as underIs(t, isX)). func allBoolean(t Type) bool { return allBasic(t, IsBoolean) } @@ -45,7 +45,7 @@ func allNumericOrString(t Type) bool { return allBasic(t, IsNumeric|IsString) } // allBasic reports whether under(t) is a basic type with the specified info. // If t is a type parameter, the result is true if isBasic(t, info) is true // for all specific types of the type parameter's type set. -// allBasic(t, info) is an optimized version of isBasic(structure(t), info). +// allBasic(t, info) is an optimized version of isBasic(structuralType(t), info). func allBasic(t Type, info BasicInfo) bool { switch u := under(t).(type) { case *Basic: diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index eaf420aca7..39b24398d7 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -836,7 +836,7 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s if x.mode != invalid { // Ranging over a type parameter is permitted if it has a single underlying type. var cause string - u := structure(x.typ) + u := structuralType(x.typ) switch t := u.(type) { case nil: cause = "type set has no single underlying type" -- GitLab From 097aaa9cd68fdce10b81fbba43fbb6569a95b53f Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 10 Nov 2021 11:21:57 -0500 Subject: [PATCH 2098/2500] go/doc: don't treat functions returning type parameters as constructors Functions returning type parameters were erroneously being interpreted as 'constructors' of their type parameter, resulting in them being excluded from documentation. Fix this by explicitly excluding type parameters when looking for defined type names among function results. Fixes #49477 Change-Id: I22510f655f47e192a852332df5b91740f46c51eb Reviewed-on: https://go-review.googlesource.com/c/go/+/362758 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Jonathan Amsterdam TryBot-Result: Go Bot --- src/go/doc/reader.go | 21 +++++++++++++++++++++ src/go/doc/testdata/generics.0.golden | 6 ++++++ src/go/doc/testdata/generics.1.golden | 6 ++++++ src/go/doc/testdata/generics.2.golden | 6 ++++++ src/go/doc/testdata/generics.go | 13 +++++++++++++ 5 files changed, 52 insertions(+) diff --git a/src/go/doc/reader.go b/src/go/doc/reader.go index 348b9b59a0..7ff868f062 100644 --- a/src/go/doc/reader.go +++ b/src/go/doc/reader.go @@ -425,6 +425,11 @@ func (r *reader) readFunc(fun *ast.FuncDecl) { factoryType = t.Elt } if n, imp := baseTypeName(factoryType); !imp && r.isVisible(n) && !r.isPredeclared(n) { + if lookupTypeParam(n, fun.Type.TypeParams) != nil { + // Issue #49477: don't associate fun with its type parameter result. + // A type parameter is not a defined type. + continue + } if t := r.lookupType(n); t != nil { typ = t numResultTypes++ @@ -446,6 +451,22 @@ func (r *reader) readFunc(fun *ast.FuncDecl) { r.funcs.set(fun, r.mode&PreserveAST != 0) } +// lookupTypeParam searches for type parameters named name within the tparams +// field list, returning the relevant identifier if found, or nil if not. +func lookupTypeParam(name string, tparams *ast.FieldList) *ast.Ident { + if tparams == nil { + return nil + } + for _, field := range tparams.List { + for _, id := range field.Names { + if id.Name == name { + return id + } + } + } + return nil +} + var ( noteMarker = `([A-Z][A-Z]+)\(([^)]+)\):?` // MARKER(uid), MARKER at least 2 chars, uid at least 1 char noteMarkerRx = lazyregexp.New(`^[ \t]*` + noteMarker) // MARKER(uid) at text start diff --git a/src/go/doc/testdata/generics.0.golden b/src/go/doc/testdata/generics.0.golden index a6dbcf673c..91c874c84d 100644 --- a/src/go/doc/testdata/generics.0.golden +++ b/src/go/doc/testdata/generics.0.golden @@ -14,6 +14,12 @@ FUNCTIONS // Func has an instantiated constraint. func Func[T Constraint[string, Type[int]]]() + // Single is not a factory function. + func Single[T any]() *T + + // Slice is not a factory function. + func Slice[T any]() []T + TYPES // AFuncType demonstrates filtering of parameters and type ... diff --git a/src/go/doc/testdata/generics.1.golden b/src/go/doc/testdata/generics.1.golden index c0548b5e96..923a4ce5d9 100644 --- a/src/go/doc/testdata/generics.1.golden +++ b/src/go/doc/testdata/generics.1.golden @@ -14,6 +14,12 @@ FUNCTIONS // Func has an instantiated constraint. func Func[T Constraint[string, Type[int]]]() + // Single is not a factory function. + func Single[T any]() *T + + // Slice is not a factory function. + func Slice[T any]() []T + TYPES // AFuncType demonstrates filtering of parameters and type ... diff --git a/src/go/doc/testdata/generics.2.golden b/src/go/doc/testdata/generics.2.golden index a6dbcf673c..91c874c84d 100644 --- a/src/go/doc/testdata/generics.2.golden +++ b/src/go/doc/testdata/generics.2.golden @@ -14,6 +14,12 @@ FUNCTIONS // Func has an instantiated constraint. func Func[T Constraint[string, Type[int]]]() + // Single is not a factory function. + func Single[T any]() *T + + // Slice is not a factory function. + func Slice[T any]() []T + TYPES // AFuncType demonstrates filtering of parameters and type ... diff --git a/src/go/doc/testdata/generics.go b/src/go/doc/testdata/generics.go index b5debba437..ba7187e4dd 100644 --- a/src/go/doc/testdata/generics.go +++ b/src/go/doc/testdata/generics.go @@ -59,3 +59,16 @@ func AnotherFunc[T ~struct{ f int }](_ struct{ f int }) {} // don't filter type parameters (to be consistent with function declarations), // but DO filter the RHS. type AFuncType[T ~struct{ f int }] func(_ struct{ f int }) + +// See issue #49477: type parameters should not be interpreted as named types +// for the purpose of determining whether a function is a factory function. + +// Slice is not a factory function. +func Slice[T any]() []T { + return nil +} + +// Single is not a factory function. +func Single[T any]() *T { + return nil +} -- GitLab From 6406e09f69c70b10cab58702f10456a3e9a83bef Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 10 Nov 2021 08:33:26 -0800 Subject: [PATCH 2099/2500] cmd/compile/internal/types2: move some functions into different files (cleanup) - move structuralType/structuralString into type.go - move functions exported for the compiler into compilersupport.go - updated/added comments - removed AsNamed and AsInterface - not needed by compiler No semantic changes. Change-Id: Ia454a49edafd627c2a25b0b71db4aa93ddd7f1f2 Reviewed-on: https://go-review.googlesource.com/c/go/+/362995 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/noder/decl.go | 2 +- src/cmd/compile/internal/noder/expr.go | 4 +- src/cmd/compile/internal/types2/builtins.go | 50 ------------- .../internal/types2/compilersupport.go | 34 +++++++++ src/cmd/compile/internal/types2/type.go | 74 ++++++++++--------- 5 files changed, 78 insertions(+), 86 deletions(-) create mode 100644 src/cmd/compile/internal/types2/compilersupport.go diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go index 82455f7d4a..0143fd3d45 100644 --- a/src/cmd/compile/internal/noder/decl.go +++ b/src/cmd/compile/internal/noder/decl.go @@ -94,7 +94,7 @@ func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) { if recv != nil { t2 := deref2(recv.Type()) // This is a method, so set g.curDecl to recvTypeName.methName instead. - g.curDecl = types2.AsNamed(t2).Obj().Name() + "." + g.curDecl + g.curDecl = t2.(*types2.Named).Obj().Name() + "." + g.curDecl } fn := ir.NewFunc(g.pos(decl)) diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 24e6dbefe7..6891d1ec30 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -266,7 +266,7 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto if wantPtr { recvType2Base = types2.AsPointer(recvType2).Elem() } - if types2.AsNamed(recvType2Base).TypeParams().Len() > 0 { + if recvType2Base.(*types2.Named).TypeParams().Len() > 0 { // recvType2 is the original generic type that is // instantiated for this method call. // selinfo.Recv() is the instantiated type @@ -338,7 +338,7 @@ func (g *irgen) compLit(typ types2.Type, lit *syntax.CompositeLit) ir.Node { return typed(g.typ(typ), n) } - _, isStruct := types2.Structure(typ).(*types2.Struct) + _, isStruct := types2.StructuralType(typ).(*types2.Struct) exprs := make([]ir.Node, len(lit.ElemList)) for i, elem := range lit.ElemList { diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 4c659d65cd..5c3f0aac8a 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -767,56 +767,6 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( return true } -// Structure is exported for the compiler. - -// If typ is a type parameter, Structure returns the single underlying -// type of all types in the corresponding type constraint if it exists, -// or nil otherwise. If typ is not a type parameter, Structure returns -// the underlying type. -func Structure(typ Type) Type { - return structuralType(typ) -} - -// If typ is a type parameter, structuralType returns the single underlying -// type of all types in the corresponding type constraint if it exists, or -// nil otherwise. If typ is not a type parameter, structuralType returns -// the underlying type. -func structuralType(typ Type) Type { - var su Type - if underIs(typ, func(u Type) bool { - if su != nil && !Identical(su, u) { - return false - } - // su == nil || Identical(su, u) - su = u - return true - }) { - return su - } - return nil -} - -// structuralString is like structuralType but also considers []byte -// and string as "identical". In this case, if successful, the result -// is always []byte. -func structuralString(typ Type) Type { - var su Type - if underIs(typ, func(u Type) bool { - if isString(u) { - u = NewSlice(universeByte) - } - if su != nil && !Identical(su, u) { - return false - } - // su == nil || Identical(su, u) - su = u - return true - }) { - return su - } - return nil -} - // hasVarSize reports if the size of type t is variable due to type parameters. func hasVarSize(t Type) bool { switch t := under(t).(type) { diff --git a/src/cmd/compile/internal/types2/compilersupport.go b/src/cmd/compile/internal/types2/compilersupport.go new file mode 100644 index 0000000000..1e79bbf9be --- /dev/null +++ b/src/cmd/compile/internal/types2/compilersupport.go @@ -0,0 +1,34 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Helper functions exported for the compiler. +// Do not use internally. + +package types2 + +// If t is a pointer, AsPointer returns that type, otherwise it returns nil. +func AsPointer(t Type) *Pointer { + u, _ := t.Underlying().(*Pointer) + return u +} + +// If t is a signature, AsSignature returns that type, otherwise it returns nil. +func AsSignature(t Type) *Signature { + u, _ := t.Underlying().(*Signature) + return u +} + +// If t is a type parameter, AsTypeParam returns that type, otherwise it returns nil. +func AsTypeParam(t Type) *TypeParam { + u, _ := t.Underlying().(*TypeParam) + return u +} + +// If t is a type parameter, StructuralType returns the single underlying +// type of all types in the type parameter's type constraint if it exists, +// or nil otherwise. If t is not a type parameter, StructuralType returns +// the underlying type of t. +func StructuralType(t Type) Type { + return structuralType(t) +} diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index d1655c55f8..64f25c6dac 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -27,10 +27,47 @@ func under(t Type) Type { return t } -// If the argument to asNamed, or asTypeParam is of the respective type -// (possibly after resolving a *Named type), these methods return that type. -// Otherwise the result is nil. +// If typ is a type parameter, structuralType returns the single underlying +// type of all types in the corresponding type constraint if it exists, or +// nil otherwise. If typ is not a type parameter, structuralType returns +// the underlying type. +func structuralType(typ Type) Type { + var su Type + if underIs(typ, func(u Type) bool { + if su != nil && !Identical(su, u) { + return false + } + // su == nil || Identical(su, u) + su = u + return true + }) { + return su + } + return nil +} + +// structuralString is like structuralType but also considers []byte +// and string as "identical". In this case, if successful, the result +// is always []byte. +func structuralString(typ Type) Type { + var su Type + if underIs(typ, func(u Type) bool { + if isString(u) { + u = NewSlice(universeByte) + } + if su != nil && !Identical(su, u) { + return false + } + // su == nil || Identical(su, u) + su = u + return true + }) { + return su + } + return nil +} +// If t is a defined type, asNamed returns that type (possibly after resolving it), otherwise it returns nil. func asNamed(t Type) *Named { e, _ := t.(*Named) if e != nil { @@ -39,37 +76,8 @@ func asNamed(t Type) *Named { return e } +// If t is a type parameter, asTypeParam returns that type, otherwise it returns nil. func asTypeParam(t Type) *TypeParam { u, _ := under(t).(*TypeParam) return u } - -// Helper functions exported for the compiler. -// These functions assume type checking has completed -// and Type.Underlying() is returning the fully set up -// underlying type. Do not use internally. - -func AsPointer(t Type) *Pointer { - u, _ := t.Underlying().(*Pointer) - return u -} - -func AsNamed(t Type) *Named { - u, _ := t.(*Named) - return u -} - -func AsSignature(t Type) *Signature { - u, _ := t.Underlying().(*Signature) - return u -} - -func AsInterface(t Type) *Interface { - u, _ := t.Underlying().(*Interface) - return u -} - -func AsTypeParam(t Type) *TypeParam { - u, _ := t.Underlying().(*TypeParam) - return u -} -- GitLab From 23dd389ac6ef59210580614c4a73e0d0a13c2911 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 10 Nov 2021 09:33:53 -0800 Subject: [PATCH 2100/2500] cmd/compile/internal/types2: refer to structural rather than single underlying type in errors This brings the error messages in sync with the terminology that will be used it the spec. Change-Id: Ia05993776c649be9eb2cdf948a583b9a49f9b192 Reviewed-on: https://go-review.googlesource.com/c/go/+/362997 Reviewed-by: Robert Findley Trust: Robert Griesemer --- src/cmd/compile/internal/types2/builtins.go | 2 +- src/cmd/compile/internal/types2/index.go | 2 +- src/cmd/compile/internal/types2/stmt.go | 4 ++-- .../internal/types2/testdata/check/builtins.go2 | 6 +++--- .../internal/types2/testdata/check/typeparams.go2 | 12 ++++++------ 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 5c3f0aac8a..fa0fc1e5e6 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -470,7 +470,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( case *Map, *Chan: min = 1 case nil: - check.errorf(arg0, invalidArg+"cannot make %s; type set has no single underlying type", arg0) + check.errorf(arg0, invalidArg+"cannot make %s: no structural type", arg0) return default: check.errorf(arg0, invalidArg+"cannot make %s; type must be slice, map, or channel", arg0) diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index 10e85ef6e1..10fb57c321 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -212,7 +212,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { length := int64(-1) // valid if >= 0 switch u := structuralType(x.typ).(type) { case nil: - check.errorf(x, invalidOp+"cannot slice %s: type set has no single underlying type", x) + check.errorf(x, invalidOp+"cannot slice %s: %s has no structural type", x, x.typ) x.mode = invalid return diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index 39b24398d7..2d41489152 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -834,12 +834,12 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s // determine key/value types var key, val Type if x.mode != invalid { - // Ranging over a type parameter is permitted if it has a single underlying type. + // Ranging over a type parameter is permitted if it has a structural type. var cause string u := structuralType(x.typ) switch t := u.(type) { case nil: - cause = "type set has no single underlying type" + cause = check.sprintf("%s has no structural type", x.typ) case *Chan: if sValue != nil { check.softErrorf(sValue, "range over %s permits only one iteration variable", &x) diff --git a/src/cmd/compile/internal/types2/testdata/check/builtins.go2 b/src/cmd/compile/internal/types2/testdata/check/builtins.go2 index d1067a190f..48a39891bf 100644 --- a/src/cmd/compile/internal/types2/testdata/check/builtins.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/builtins.go2 @@ -148,7 +148,7 @@ func _[ _ = make /* ERROR expects 2 or 3 arguments */ (S1) _ = make(S1, 10, 20) _ = make /* ERROR expects 2 or 3 arguments */ (S1, 10, 20, 30) - _ = make(S2 /* ERROR cannot make .* no single underlying type */ , 10) + _ = make(S2 /* ERROR cannot make S2: no structural type */ , 10) type M0 map[string]int _ = make(map[string]int) @@ -156,7 +156,7 @@ func _[ _ = make(M1) _ = make(M1, 10) _ = make/* ERROR expects 1 or 2 arguments */(M1, 10, 20) - _ = make(M2 /* ERROR cannot make .* no single underlying type */ ) + _ = make(M2 /* ERROR cannot make M2: no structural type */ ) type C0 chan int _ = make(chan int) @@ -164,7 +164,7 @@ func _[ _ = make(C1) _ = make(C1, 10) _ = make/* ERROR expects 1 or 2 arguments */(C1, 10, 20) - _ = make(C2 /* ERROR cannot make .* no single underlying type */ ) + _ = make(C2 /* ERROR cannot make C2: no structural type */ ) _ = make(C3) } diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 index a1bf6c262f..9e7960a474 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 @@ -134,7 +134,7 @@ func _[T interface{ ~string }] (x T, i, j, k int) { var _ T = x /* ERROR 3-index type myByte1 []byte type myByte2 []byte func _[T interface{ []byte | myByte1 | myByte2 }] (x T, i, j, k int) { var _ T = x[i:j:k] } -func _[T interface{ []byte | myByte1 | []int }] (x T, i, j, k int) { var _ T = x[ /* ERROR no single underlying type */ i:j:k] } +func _[T interface{ []byte | myByte1 | []int }] (x T, i, j, k int) { var _ T = x[ /* ERROR no structural type */ i:j:k] } // len/cap built-ins @@ -210,7 +210,7 @@ func _[ for _, _ /* ERROR permits only one iteration variable */ = range c1 {} var c2 C2 - for range c2 /* ERROR cannot range over c2.*no single underlying type */ {} + for range c2 /* ERROR cannot range over c2.*no structural type */ {} var c3 C3 for range c3 /* ERROR receive from send-only channel */ {} @@ -226,7 +226,7 @@ func _[ for _, _ = range s1 {} var s2 S2 - for range s2 /* ERROR cannot range over s2.*no single underlying type */ {} + for range s2 /* ERROR cannot range over s2.*no structural type */ {} var a0 []int for range a0 {} @@ -239,7 +239,7 @@ func _[ for _, _ = range a1 {} var a2 A2 - for range a2 /* ERROR cannot range over a2.*no single underlying type */ {} + for range a2 /* ERROR cannot range over a2.*no structural type */ {} var p0 *[10]int for range p0 {} @@ -252,7 +252,7 @@ func _[ for _, _ = range p1 {} var p2 P2 - for range p2 /* ERROR cannot range over p2.*no single underlying type */ {} + for range p2 /* ERROR cannot range over p2.*no structural type */ {} var m0 map[string]int for range m0 {} @@ -265,7 +265,7 @@ func _[ for _, _ = range m1 {} var m2 M2 - for range m2 /* ERROR cannot range over m2.*no single underlying type */ {} + for range m2 /* ERROR cannot range over m2.*no structural type */ {} } // type inference checks -- GitLab From b2d826c09f0f73cd9dc0022a2b052543e8bf4c06 Mon Sep 17 00:00:00 2001 From: emahiro Date: Thu, 21 Oct 2021 18:01:10 +0900 Subject: [PATCH 2101/2500] internal/cache: document 'go clean -fuzzcache' in README Fixes: #48900 Change-Id: I9235441886ed7cbdfdcbd283480f52d9216c3ea2 Reviewed-on: https://go-review.googlesource.com/c/go/+/357233 Reviewed-by: Bryan C. Mills Reviewed-by: Katie Hockman Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Trust: Katie Hockman --- src/cmd/go/internal/cache/default.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cmd/go/internal/cache/default.go b/src/cmd/go/internal/cache/default.go index 0b1c1e0c20..426dddfb97 100644 --- a/src/cmd/go/internal/cache/default.go +++ b/src/cmd/go/internal/cache/default.go @@ -30,6 +30,7 @@ var ( // README as a courtesy to explain where it came from. const cacheREADME = `This directory holds cached build artifacts from the Go build system. Run "go clean -cache" if the directory is getting too large. +Run "go clean -fuzzcache" to delete the fuzz cache. See golang.org to learn more about Go. ` -- GitLab From a881409960a2a8117c99dcc0c91ab74885a3c53a Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Wed, 10 Nov 2021 20:14:15 +0000 Subject: [PATCH 2102/2500] runtime: rewrite TestPhysicalMemoryUtilization This test changes TestPhysicalMemoryUtilization to be simpler, more robust, and more honest about what's going on. Fixes #49411. Change-Id: I913ef055c6e166c104c62595c1597d44db62018c Reviewed-on: https://go-review.googlesource.com/c/go/+/362978 Trust: Michael Knyszek Run-TryBot: Michael Knyszek Reviewed-by: David Chase --- src/runtime/testdata/testprog/gc.go | 121 ++++++++++++---------------- 1 file changed, 53 insertions(+), 68 deletions(-) diff --git a/src/runtime/testdata/testprog/gc.go b/src/runtime/testdata/testprog/gc.go index 74732cd9f4..6484c36139 100644 --- a/src/runtime/testdata/testprog/gc.go +++ b/src/runtime/testdata/testprog/gc.go @@ -132,81 +132,75 @@ func GCFairness2() { func GCPhys() { // This test ensures that heap-growth scavenging is working as intended. // - // It sets up a specific scenario: it allocates two pairs of objects whose - // sizes sum to size. One object in each pair is "small" (though must be - // large enough to be considered a large object by the runtime) and one is - // large. The small objects are kept while the large objects are freed, - // creating two large unscavenged holes in the heap. The heap goal should - // also be small as a result (so size must be at least as large as the - // minimum heap size). We then allocate one large object, bigger than both - // pairs of objects combined. This allocation, because it will tip - // HeapSys-HeapReleased well above the heap goal, should trigger heap-growth - // scavenging and scavenge most, if not all, of the large holes we created - // earlier. + // It attempts to construct a sizeable "swiss cheese" heap, with many + // allocChunk-sized holes. Then, it triggers a heap growth by trying to + // allocate as much memory as would fit in those holes. + // + // The heap growth should cause a large number of those holes to be + // returned to the OS. + const ( - // Size must be also large enough to be considered a large - // object (not in any size-segregated span). - size = 4 << 20 - split = 64 << 10 - objects = 2 + allocTotal = 32 << 20 + allocChunk = 64 << 10 + allocs = allocTotal / allocChunk // The page cache could hide 64 8-KiB pages from the scavenger today. maxPageCache = (8 << 10) * 64 - - // Reduce GOMAXPROCS down to 4 if it's greater. We need to bound the amount - // of memory held in the page cache because the scavenger can't reach it. - // The page cache will hold at most maxPageCache of memory per-P, so this - // bounds the amount of memory hidden from the scavenger to 4*maxPageCache - // at most. - maxProcs = 4 ) - // Set GOGC so that this test operates under consistent assumptions. + // Set GC percent just so this test is a little more consistent in the + // face of varying environments. debug.SetGCPercent(100) - procs := runtime.GOMAXPROCS(-1) - if procs > maxProcs { - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs)) - procs = runtime.GOMAXPROCS(-1) - } - // Save objects which we want to survive, and condemn objects which we don't. - // Note that we condemn objects in this way and release them all at once in - // order to avoid having the GC start freeing up these objects while the loop - // is still running and filling in the holes we intend to make. - saved := make([][]byte, 0, objects+1) - condemned := make([][]byte, 0, objects) - for i := 0; i < 2*objects; i++ { + + // Set GOMAXPROCS to 1 to minimize the amount of memory held in the page cache, + // and to reduce the chance that the background scavenger gets scheduled. + defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1)) + + // Allocate allocTotal bytes of memory in allocChunk byte chunks. + // Alternate between whether the chunk will be held live or will be + // condemned to GC to create holes in the heap. + saved := make([][]byte, allocs/2+1) + condemned := make([][]byte, allocs/2) + for i := 0; i < allocs; i++ { + b := make([]byte, allocChunk) if i%2 == 0 { - saved = append(saved, make([]byte, split)) + saved = append(saved, b) } else { - condemned = append(condemned, make([]byte, size-split)) + condemned = append(condemned, b) } } - condemned = nil - // Clean up the heap. This will free up every other object created above - // (i.e. everything in condemned) creating holes in the heap. - // Also, if the condemned objects are still being swept, its possible that - // the scavenging that happens as a result of the next allocation won't see - // the holes at all. We call runtime.GC() twice here so that when we allocate - // our large object there's no race with sweeping. - runtime.GC() + + // Run a GC cycle just so we're at a consistent state. runtime.GC() - // Perform one big allocation which should also scavenge any holes. - // - // The heap goal will rise after this object is allocated, so it's very - // important that we try to do all the scavenging in a single allocation - // that exceeds the heap goal. Otherwise the rising heap goal could foil our - // test. - saved = append(saved, make([]byte, objects*size)) - // Clean up the heap again just to put it in a known state. + + // Drop the only reference to all the condemned memory. + condemned = nil + + // Clear the condemned memory. runtime.GC() + + // At this point, the background scavenger is likely running + // and could pick up the work, so the next line of code doesn't + // end up doing anything. That's fine. What's important is that + // this test fails somewhat regularly if the runtime doesn't + // scavenge on heap growth, and doesn't fail at all otherwise. + + // Make a large allocation that in theory could fit, but won't + // because we turned the heap into swiss cheese. + saved = append(saved, make([]byte, allocTotal/2)) + // heapBacked is an estimate of the amount of physical memory used by // this test. HeapSys is an estimate of the size of the mapped virtual // address space (which may or may not be backed by physical pages) // whereas HeapReleased is an estimate of the amount of bytes returned // to the OS. Their difference then roughly corresponds to the amount // of virtual address space that is backed by physical pages. + // + // heapBacked also subtracts out maxPageCache bytes of memory because + // this is memory that may be hidden from the scavenger per-P. Since + // GOMAXPROCS=1 here, that's fine. var stats runtime.MemStats runtime.ReadMemStats(&stats) - heapBacked := stats.HeapSys - stats.HeapReleased + heapBacked := stats.HeapSys - stats.HeapReleased - maxPageCache // If heapBacked does not exceed the heap goal by more than retainExtraPercent // then the scavenger is working as expected; the newly-created holes have been // scavenged immediately as part of the allocations which cannot fit in the holes. @@ -216,19 +210,9 @@ func GCPhys() { // to other allocations that happen during this test we may still see some physical // memory over-use. overuse := (float64(heapBacked) - float64(stats.HeapAlloc)) / float64(stats.HeapAlloc) - // Compute the threshold. - // - // In theory, this threshold should just be zero, but that's not possible in practice. - // Firstly, the runtime's page cache can hide up to maxPageCache of free memory from the - // scavenger per P. To account for this, we increase the threshold by the ratio between the - // total amount the runtime could hide from the scavenger to the amount of memory we expect - // to be able to scavenge here, which is (size-split)*objects. This computation is the crux - // GOMAXPROCS above; if GOMAXPROCS is too high the threshold just becomes 100%+ since the - // amount of memory being allocated is fixed. Then we add 5% to account for noise, such as - // other allocations this test may have performed that we don't explicitly account for The - // baseline threshold here is around 11% for GOMAXPROCS=1, capping out at around 30% for - // GOMAXPROCS=4. - threshold := 0.05 + float64(procs)*maxPageCache/float64((size-split)*objects) + // Check against our overuse threshold, which is what the scavenger always reserves + // to encourage allocation of memory that doesn't need to be faulted in. + const threshold = 0.1 if overuse <= threshold { fmt.Println("OK") return @@ -243,6 +227,7 @@ func GCPhys() { "(alloc: %d, goal: %d, sys: %d, rel: %d, objs: %d)\n", threshold*100, overuse*100, stats.HeapAlloc, stats.NextGC, stats.HeapSys, stats.HeapReleased, len(saved)) runtime.KeepAlive(saved) + runtime.KeepAlive(condemned) } // Test that defer closure is correctly scanned when the stack is scanned. -- GitLab From f410786c5f12d0cc4f44ce9daf8d0883df39a2f6 Mon Sep 17 00:00:00 2001 From: Paschalis Tsilias Date: Wed, 28 Jul 2021 17:03:21 +0300 Subject: [PATCH 2103/2500] cmd/go: add 'go mod vendor -o' flag Adds a new flag to 'go mod vendor' which overrides the default 'vendor' destination directory. This can be helpful for writing the vendor tree to a temporary location for use by other tools. The argument can be a relative or an absolute path. This flag has no other influence on how the command behaves. Fixes #47327 Change-Id: I4502931127616b181dc90a2066d2fb57bfe48f96 Reviewed-on: https://go-review.googlesource.com/c/go/+/338149 Reviewed-by: Bryan C. Mills Reviewed-by: Jay Conrod Trust: Bryan C. Mills Trust: Jay Conrod Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot --- src/cmd/go/alldocs.go | 7 +++- src/cmd/go/internal/modcmd/vendor.go | 21 ++++++++++-- src/cmd/go/testdata/script/mod_vendor.txt | 42 +++++++++++++++++++++++ 3 files changed, 66 insertions(+), 4 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 81d2f7021d..ff144f9847 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -1295,7 +1295,7 @@ // // Usage: // -// go mod vendor [-e] [-v] +// go mod vendor [-e] [-v] [-o outdir] // // Vendor resets the main module's vendor directory to include all packages // needed to build and test all the main module's packages. @@ -1307,6 +1307,11 @@ // The -e flag causes vendor to attempt to proceed despite errors // encountered while loading packages. // +// The -o flag causes vendor to create the vendor directory at the given +// path instead of "vendor". The go command can only use a vendor directory +// named "vendor" within the module root directory, so this flag is +// primarily useful for other tools. +// // See https://golang.org/ref/mod#go-mod-vendor for more about 'go mod vendor'. // // diff --git a/src/cmd/go/internal/modcmd/vendor.go b/src/cmd/go/internal/modcmd/vendor.go index 484e095cc7..ef123700aa 100644 --- a/src/cmd/go/internal/modcmd/vendor.go +++ b/src/cmd/go/internal/modcmd/vendor.go @@ -31,7 +31,7 @@ import ( ) var cmdVendor = &base.Command{ - UsageLine: "go mod vendor [-e] [-v]", + UsageLine: "go mod vendor [-e] [-v] [-o outdir]", Short: "make vendored copy of dependencies", Long: ` Vendor resets the main module's vendor directory to include all packages @@ -44,16 +44,23 @@ modules and packages to standard error. The -e flag causes vendor to attempt to proceed despite errors encountered while loading packages. +The -o flag causes vendor to create the vendor directory at the given +path instead of "vendor". The go command can only use a vendor directory +named "vendor" within the module root directory, so this flag is +primarily useful for other tools. + See https://golang.org/ref/mod#go-mod-vendor for more about 'go mod vendor'. `, Run: runVendor, } -var vendorE bool // if true, report errors but proceed anyway +var vendorE bool // if true, report errors but proceed anyway +var vendorO string // if set, overrides the default output directory func init() { cmdVendor.Flag.BoolVar(&cfg.BuildV, "v", false, "") cmdVendor.Flag.BoolVar(&vendorE, "e", false, "") + cmdVendor.Flag.StringVar(&vendorO, "o", "", "") base.AddModCommonFlags(&cmdVendor.Flag) } @@ -74,7 +81,15 @@ func runVendor(ctx context.Context, cmd *base.Command, args []string) { } _, pkgs := modload.LoadPackages(ctx, loadOpts, "all") - vdir := filepath.Join(modload.VendorDir()) + var vdir string + switch { + case filepath.IsAbs(vendorO): + vdir = vendorO + case vendorO != "": + vdir = filepath.Join(base.Cwd(), vendorO) + default: + vdir = filepath.Join(modload.VendorDir()) + } if err := os.RemoveAll(vdir); err != nil { base.Fatalf("go: %v", err) } diff --git a/src/cmd/go/testdata/script/mod_vendor.txt b/src/cmd/go/testdata/script/mod_vendor.txt index 4eb80c2332..a2727ddf7f 100644 --- a/src/cmd/go/testdata/script/mod_vendor.txt +++ b/src/cmd/go/testdata/script/mod_vendor.txt @@ -82,6 +82,48 @@ exists vendor/mysite/myname/mypkg/LICENSE.txt ! exists vendor/x/x2 ! exists vendor/x/x2/LICENSE +# 'go mod vendor' should work with an alternative vendor directory if the -o flag is provided. +go mod vendor -v -o alternative-vendor-dir +exists alternative-vendor-dir/modules.txt +exists alternative-vendor-dir/a/foo/LICENSE + +# 'go mod vendor' should interpret paths relative to the current working directory when the -o flag is provided. +mkdir dir1 +mkdir dir2 + +cd dir1 +go mod vendor -v -o relative-vendor-dir + +go mod vendor -v -o ../dir2/relative-vendor-dir + +cd .. +exists dir1/relative-vendor-dir/modules.txt +exists dir1/relative-vendor-dir/a/foo/LICENSE +exists dir2/relative-vendor-dir/modules.txt +exists dir2/relative-vendor-dir/a/foo/LICENSE + +# 'go mod vendor' should fall back to the default 'vendor' directory when an empty argument is passed to the -o flag +# the same behavior should be exhibited both on the module root directory, as well as nested subdirectories + +go mod vendor -v -o '' +exists vendor/modules.txt + +env GOFLAGS=-o=foo +go mod vendor -v -o '' +exists vendor/modules.txt +env GOFLAGS='' + +mkdir -p nested/dir +cd nested/dir +go mod vendor -v -o '' +! exists vendor/ +exists ../../vendor/modules.txt +cd ../.. + +# 'go mod vendor' should work with absolute paths as well +go mod vendor -v -o $WORK/tmp/absolute-vendor-dir +exists $WORK/tmp/absolute-vendor-dir/modules.txt + [short] stop # 'go build' and 'go test' using vendored packages should succeed. -- GitLab From 229b90931312aa1686f4bace25d1f40f896884ad Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 10 Nov 2021 11:39:18 -0800 Subject: [PATCH 2104/2500] cmd/compile: don't do Resolve on OKEY identifiers during import For generic functions, we can export untransformed OKEY nodes, and the key identifier is written as an ONONAME. But in this case, we do not want to call Resolve() on the identifier, since we may resolve to a global type (as happens in this issue) or other global symbol with the same name, if it exists. We just want to keep the key identifier as an Ident node. To solve this, I added an extra bool when exporting an ONONAME entry, which indicates if this entry is for a key or for a global (external) symbol. When the bool is true (this is for a key), we avoid calling Resolve(). Fixes #49497 Change-Id: Ic8fa93d37bcad2110e0e0d060080b733e07e35d7 Reviewed-on: https://go-review.googlesource.com/c/go/+/363074 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/typecheck/iexport.go | 6 ++++- src/cmd/compile/internal/typecheck/iimport.go | 8 +++++- test/typeparam/issue49497.dir/a.go | 26 +++++++++++++++++++ test/typeparam/issue49497.dir/main.go | 11 ++++++++ test/typeparam/issue49497.go | 7 +++++ 5 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 test/typeparam/issue49497.dir/a.go create mode 100644 test/typeparam/issue49497.dir/main.go create mode 100644 test/typeparam/issue49497.go diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index f685851e40..bf12ba803b 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -1735,6 +1735,8 @@ func (w *exportWriter) expr(n ir.Node) { n := n.(*ir.Name) if (n.Class == ir.PEXTERN || n.Class == ir.PFUNC) && !ir.IsBlank(n) { w.op(ir.ONONAME) + // Indicate that this is not an OKEY entry. + w.bool(false) w.qualifiedIdent(n) if go117ExportTypes { w.typ(n.Type()) @@ -1761,7 +1763,9 @@ func (w *exportWriter) expr(n ir.Node) { case ir.ONONAME: w.op(ir.ONONAME) - // This should only be for OKEY nodes in generic functions + // This can only be for OKEY nodes in generic functions. Mark it + // as a key entry. + w.bool(true) s := n.Sym() w.string(s.Name) w.pkg(s.Pkg) diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 26bc838ed9..09f87df580 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -1315,9 +1315,15 @@ func (r *importReader) node() ir.Node { return n case ir.ONONAME: + isKey := r.bool() n := r.qualifiedIdent() if go117ExportTypes { - n2 := Resolve(n) + var n2 ir.Node = n + // Key ONONAME entries should not be resolved - they should + // stay as identifiers. + if !isKey { + n2 = Resolve(n) + } typ := r.typ() if n2.Type() == nil { n2.SetType(typ) diff --git a/test/typeparam/issue49497.dir/a.go b/test/typeparam/issue49497.dir/a.go new file mode 100644 index 0000000000..86062d446f --- /dev/null +++ b/test/typeparam/issue49497.dir/a.go @@ -0,0 +1,26 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +func F[T any]() A[T] { + var x A[T] + return x +} + +type A[T any] struct { + b B[T] +} + +func (a A[T]) M() C[T] { + return C[T]{ + B: a.b, + } +} + +type B[T any] struct{} + +type C[T any] struct { + B B[T] +} diff --git a/test/typeparam/issue49497.dir/main.go b/test/typeparam/issue49497.dir/main.go new file mode 100644 index 0000000000..3725e5591e --- /dev/null +++ b/test/typeparam/issue49497.dir/main.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "a" + +func main() { + a.F[string]() +} diff --git a/test/typeparam/issue49497.go b/test/typeparam/issue49497.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/issue49497.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From 96c94c2c831a5c074d33e2b7b553e91eb602e6bd Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 10 Nov 2021 12:11:03 -0800 Subject: [PATCH 2105/2500] cmd/compile/internal/types2: slightly relax notion of structural type If we have all channel types in a constraint, there is no structural type if they don't all have the same channel direction (and identical element types, of course). By allowing different channel types for the purposes of the structural type, as long as there is not a send-only _and_ a receive- only channel in the type set, we make it possible to find a useful, if restricted by channel direction, structural type where before there was none. So if we have unrestricted and send-only channels, the structural type is the send-only channel, and vice versa. For all operations on channels that rely on a structural type, it's always ok to have an unrestricted channel, so this is not affecting their behavior. But it makes those operations more flexible in the presence of type parameters containing mixed channel types. For constraint type inference, where we currently may not infer a channel at all, this change allows us to infer a more restricted channel (send- or receive-only). If the inferred channel type is a valid type argument we win; if not we haven't lost anything. Use structuralType for send and receive operations and adjust related error messages (the error message that change are the ones involving type parameters, so historic error messages are preserved). Fixes #45920. Change-Id: If3a64d29c37e7734d3163df330f8b02dd032bc60 Reviewed-on: https://go-review.googlesource.com/c/go/+/363075 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley --- .../internal/types2/compilersupport.go | 10 ++-- src/cmd/compile/internal/types2/expr.go | 34 ++++++------ src/cmd/compile/internal/types2/stmt.go | 32 +++++------ .../types2/testdata/check/typeparams.go2 | 2 +- .../types2/testdata/fixedbugs/issue43671.go2 | 6 +-- .../types2/testdata/fixedbugs/issue45920.go2 | 17 ++++++ .../types2/testdata/fixedbugs/issue47115.go2 | 4 +- src/cmd/compile/internal/types2/type.go | 53 ++++++++++++++++--- 8 files changed, 102 insertions(+), 56 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue45920.go2 diff --git a/src/cmd/compile/internal/types2/compilersupport.go b/src/cmd/compile/internal/types2/compilersupport.go index 1e79bbf9be..31112d4e41 100644 --- a/src/cmd/compile/internal/types2/compilersupport.go +++ b/src/cmd/compile/internal/types2/compilersupport.go @@ -25,10 +25,12 @@ func AsTypeParam(t Type) *TypeParam { return u } -// If t is a type parameter, StructuralType returns the single underlying -// type of all types in the type parameter's type constraint if it exists, -// or nil otherwise. If t is not a type parameter, StructuralType returns -// the underlying type of t. +// If typ is a type parameter, structuralType returns the single underlying +// type of all types in the corresponding type constraint if it exists, or +// nil otherwise. If the type set contains only unrestricted and restricted +// channel types (with identical element types), the single underlying type +// is the restricted channel type if the restrictions are always the same. +// If typ is not a type parameter, structuralType returns the underlying type. func StructuralType(t Type) Type { return structuralType(t) } diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 169417016f..0b3fe23e80 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -187,29 +187,25 @@ func (check *Checker) unary(x *operand, e *syntax.Operation) { return case syntax.Recv: - var elem Type - if !underIs(x.typ, func(u Type) bool { - ch, _ := u.(*Chan) - if ch == nil { - check.errorf(x, invalidOp+"cannot receive from non-channel %s", x) - return false - } - if ch.dir == SendOnly { - check.errorf(x, invalidOp+"cannot receive from send-only channel %s", x) - return false - } - if elem != nil && !Identical(ch.elem, elem) { - check.errorf(x, invalidOp+"channels of %s must have the same element type", x) - return false - } - elem = ch.elem - return true - }) { + u := structuralType(x.typ) + if u == nil { + check.errorf(x, invalidOp+"cannot receive from %s: no structural type", x) + x.mode = invalid + return + } + ch, _ := u.(*Chan) + if ch == nil { + check.errorf(x, invalidOp+"cannot receive from non-channel %s", x) + x.mode = invalid + return + } + if ch.dir == SendOnly { + check.errorf(x, invalidOp+"cannot receive from send-only channel %s", x) x.mode = invalid return } x.mode = commaok - x.typ = elem + x.typ = ch.elem check.hasCallOrRecv = true return } diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index 2d41489152..f9c07e38cd 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -408,27 +408,21 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) { if ch.mode == invalid || val.mode == invalid { return } - var elem Type - if !underIs(ch.typ, func(u Type) bool { - uch, _ := u.(*Chan) - if uch == nil { - check.errorf(s, invalidOp+"cannot send to non-channel %s", &ch) - return false - } - if uch.dir == RecvOnly { - check.errorf(s, invalidOp+"cannot send to receive-only channel %s", &ch) - return false - } - if elem != nil && !Identical(uch.elem, elem) { - check.errorf(s, invalidOp+"channels of %s must have the same element type", &ch) - return false - } - elem = uch.elem - return true - }) { + u := structuralType(ch.typ) + if u == nil { + check.errorf(s, invalidOp+"cannot send to %s: no structural type", &ch) return } - check.assignment(&val, elem, "send") + uch, _ := u.(*Chan) + if uch == nil { + check.errorf(s, invalidOp+"cannot send to non-channel %s", &ch) + return + } + if uch.dir == RecvOnly { + check.errorf(s, invalidOp+"cannot send to receive-only channel %s", &ch) + return + } + check.assignment(&val, uch.elem, "send") case *syntax.AssignStmt: lhs := unpackExpr(s.Lhs) diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 index 9e7960a474..b1d02efdb5 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 @@ -210,7 +210,7 @@ func _[ for _, _ /* ERROR permits only one iteration variable */ = range c1 {} var c2 C2 - for range c2 /* ERROR cannot range over c2.*no structural type */ {} + for range c2 {} var c3 C3 for range c3 /* ERROR receive from send-only channel */ {} diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43671.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43671.go2 index 6cc3801cc9..46ac51ebdd 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43671.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43671.go2 @@ -12,11 +12,11 @@ type C4 interface{ chan int | chan<- int } type C5[T any] interface{ ~chan T | <-chan T } func _[T any](ch T) { - <-ch // ERROR cannot receive from non-channel + <-ch // ERROR cannot receive from ch .* no structural type } func _[T C0](ch T) { - <-ch // ERROR cannot receive from non-channel + <-ch // ERROR cannot receive from non-channel ch } func _[T C1](ch T) { @@ -28,7 +28,7 @@ func _[T C2](ch T) { } func _[T C3](ch T) { - <-ch // ERROR channels of ch .* must have the same element type + <-ch // ERROR cannot receive from ch .* no structural type } func _[T C4](ch T) { diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45920.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45920.go2 new file mode 100644 index 0000000000..ef9ca9fede --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45920.go2 @@ -0,0 +1,17 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func f1[T any, C chan T | <-chan T](ch C) {} + +func _(ch chan int) { f1(ch) } +func _(ch <-chan int) { f1(ch) } +func _(ch chan<- int) { f1( /* ERROR chan<- int does not satisfy chan T\|<-chan T */ ch) } + +func f2[T any, C chan T | chan<- T](ch C) {} + +func _(ch chan int) { f2(ch) } +func _(ch <-chan int) { f2( /* ERROR <-chan int does not satisfy chan T\|chan<- T */ ch) } +func _(ch chan<- int) { f2(ch) } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47115.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47115.go2 index 00828eb997..83a8f3a5da 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47115.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47115.go2 @@ -12,7 +12,7 @@ type C4 interface{ chan int | chan<- int } type C5[T any] interface{ ~chan T | chan<- T } func _[T any](ch T) { - ch /* ERROR cannot send to non-channel */ <- 0 + ch /* ERROR cannot send to ch .* no structural type */ <- 0 } func _[T C0](ch T) { @@ -28,7 +28,7 @@ func _[T C2](ch T) { } func _[T C3](ch T) { - ch /* ERROR channels of ch .* must have the same element type */ <- 0 + ch /* ERROR cannot send to ch .* no structural type */ <- 0 } func _[T C4](ch T) { diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 64f25c6dac..316e834a77 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -27,17 +27,51 @@ func under(t Type) Type { return t } +// If x and y are identical, match returns x. +// If x and y are identical channels but for their direction +// and one of them is unrestricted, match returns the channel +// with the restricted direction. +// In all other cases, match returns nil. +func match(x, y Type) Type { + // Common case: we don't have channels. + if Identical(x, y) { + return x + } + + // We may have channels that differ in direction only. + if x, _ := x.(*Chan); x != nil { + if y, _ := y.(*Chan); y != nil && Identical(x.elem, y.elem) { + // We have channels that differ in direction only. + // If there's an unrestricted channel, select the restricted one. + switch { + case x.dir == SendRecv: + return y + case y.dir == SendRecv: + return x + } + } + } + + // types are different + return nil +} + // If typ is a type parameter, structuralType returns the single underlying // type of all types in the corresponding type constraint if it exists, or -// nil otherwise. If typ is not a type parameter, structuralType returns -// the underlying type. +// nil otherwise. If the type set contains only unrestricted and restricted +// channel types (with identical element types), the single underlying type +// is the restricted channel type if the restrictions are always the same. +// If typ is not a type parameter, structuralType returns the underlying type. func structuralType(typ Type) Type { var su Type if underIs(typ, func(u Type) bool { - if su != nil && !Identical(su, u) { - return false + if su != nil { + u = match(su, u) + if u == nil { + return false + } } - // su == nil || Identical(su, u) + // su == nil || match(su, u) != nil su = u return true }) { @@ -55,10 +89,13 @@ func structuralString(typ Type) Type { if isString(u) { u = NewSlice(universeByte) } - if su != nil && !Identical(su, u) { - return false + if su != nil { + u = match(su, u) + if u == nil { + return false + } } - // su == nil || Identical(su, u) + // su == nil || match(su, u) != nil su = u return true }) { -- GitLab From 23f653df963ddf3ae618290edbb0c55530fcf483 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 10 Nov 2021 13:36:23 -0800 Subject: [PATCH 2106/2500] cmd/compile/internal/types2: remove structuralString in favor of inlined code structuralString was used only in one place (for built-in copy). Remove it in favor of custom and more efficient inlined code. Follow-up on feedback received for CL 363075. Change-Id: Ic5857c47255c5c712be7971aae4542fef9960fe6 Reviewed-on: https://go-review.googlesource.com/c/go/+/363154 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley TryBot-Result: Go Bot --- src/cmd/compile/internal/types2/builtins.go | 21 +++++++++++++++++- src/cmd/compile/internal/types2/type.go | 24 --------------------- 2 files changed, 20 insertions(+), 25 deletions(-) diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index fa0fc1e5e6..2bc084038f 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -334,7 +334,26 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( if y.mode == invalid { return } - src, _ := structuralString(y.typ).(*Slice) + // src, _ := structuralType(y.typ).(*Slice); but also accepts strings + var src *Slice + var elem Type // == src.elem if valid + if underIs(y.typ, func(u Type) bool { + switch u := u.(type) { + case *Basic: + if isString(u) && (elem == nil || Identical(elem, universeByte)) { + elem = universeByte + return true + } + case *Slice: + if elem == nil || Identical(elem, u.elem) { + elem = u.elem + return true + } + } + return false + }) { + src = NewSlice(elem) + } if dst == nil || src == nil { check.errorf(x, invalidArg+"copy expects slice arguments; found %s and %s", x, &y) diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 316e834a77..c8c0f36e5c 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -80,30 +80,6 @@ func structuralType(typ Type) Type { return nil } -// structuralString is like structuralType but also considers []byte -// and string as "identical". In this case, if successful, the result -// is always []byte. -func structuralString(typ Type) Type { - var su Type - if underIs(typ, func(u Type) bool { - if isString(u) { - u = NewSlice(universeByte) - } - if su != nil { - u = match(su, u) - if u == nil { - return false - } - } - // su == nil || match(su, u) != nil - su = u - return true - }) { - return su - } - return nil -} - // If t is a defined type, asNamed returns that type (possibly after resolving it), otherwise it returns nil. func asNamed(t Type) *Named { e, _ := t.(*Named) -- GitLab From 4d0683965bd05aee6845bf6849c85c4bf2bb10d4 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Fri, 5 Nov 2021 13:02:09 +0100 Subject: [PATCH 2107/2500] net: do more faithful conversion from AddrPort to UDPAddr A UDPAddr with a nil IP is a valid state, representing an AF-agnostic unspecified address, so checking for addr.IsValid() isn't correct; remove that, as it's only needed in the UDP rx path where it can be added. Secondly, forcing everything to be IPv6 also is not correct, and was likely done when the missing .AsSlice() made doing the right thing less ergonomic. Fix this by using .AsSlice(), which properly preserves IP version. Change-Id: Idd1eaecd4076f32a843f859a0a9802ef98f956d3 Reviewed-on: https://go-review.googlesource.com/c/go/+/361478 Trust: Jason A. Donenfeld Trust: Josh Bleecher Snyder Run-TryBot: Jason A. Donenfeld TryBot-Result: Go Bot Reviewed-by: Russ Cox --- src/net/udpsock.go | 16 +++++++--------- src/net/udpsock_test.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/net/udpsock.go b/src/net/udpsock.go index 622b1f83fb..6d29a39edf 100644 --- a/src/net/udpsock.go +++ b/src/net/udpsock.go @@ -99,16 +99,12 @@ func ResolveUDPAddr(network, address string) (*UDPAddr, error) { return addrs.forResolve(network, address).(*UDPAddr), nil } -// UDPAddrFromAddrPort returns addr as a UDPAddr. -// -// If addr is not valid, it returns nil. +// UDPAddrFromAddrPort returns addr as a UDPAddr. If addr.IsValid() is false, +// then the returned UDPAddr will contain a nil IP field, indicating an +// address family-agnostic unspecified address. func UDPAddrFromAddrPort(addr netip.AddrPort) *UDPAddr { - if !addr.IsValid() { - return nil - } - ip16 := addr.Addr().As16() return &UDPAddr{ - IP: IP(ip16[:]), + IP: addr.Addr().AsSlice(), Zone: addr.Addr().Zone(), Port: int(addr.Port()), } @@ -189,7 +185,9 @@ func (c *UDPConn) ReadFromUDPAddrPort(b []byte) (n int, addr netip.AddrPort, err func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) { var ap netip.AddrPort n, oobn, flags, ap, err = c.ReadMsgUDPAddrPort(b, oob) - addr = UDPAddrFromAddrPort(ap) + if ap.IsValid() { + addr = UDPAddrFromAddrPort(ap) + } return } diff --git a/src/net/udpsock_test.go b/src/net/udpsock_test.go index 9fe74f47a2..01b8d39216 100644 --- a/src/net/udpsock_test.go +++ b/src/net/udpsock_test.go @@ -603,3 +603,35 @@ func BenchmarkWriteToReadFromUDPAddrPort(b *testing.B) { } } } + +func TestUDPIPVersionReadMsg(t *testing.T) { + conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) + if err != nil { + t.Fatal(err) + } + defer conn.Close() + daddr := conn.LocalAddr().(*UDPAddr).AddrPort() + buf := make([]byte, 8) + _, err = conn.WriteToUDPAddrPort(buf, daddr) + if err != nil { + t.Fatal(err) + } + _, _, _, saddr, err := conn.ReadMsgUDPAddrPort(buf, nil) + if err != nil { + t.Fatal(err) + } + if !saddr.Addr().Is4() { + t.Error("returned AddrPort is not IPv4") + } + _, err = conn.WriteToUDPAddrPort(buf, daddr) + if err != nil { + t.Fatal(err) + } + _, _, _, soldaddr, err := conn.ReadMsgUDP(buf, nil) + if err != nil { + t.Fatal(err) + } + if len(soldaddr.IP) != 4 { + t.Error("returned UDPAddr is not IPv4") + } +} -- GitLab From 3949faf72e8285622ebfdf3bd573125dcd5453d2 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 10 Nov 2021 16:06:18 -0800 Subject: [PATCH 2108/2500] test: add test that was miscompiled by gccgo For #49512 Change-Id: Ic08652a4ec611b27150bf10b1118c1395715e5d0 Reviewed-on: https://go-review.googlesource.com/c/go/+/363156 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Cherry Mui Reviewed-by: Than McIntosh --- test/fixedbugs/issue49512.go | 54 ++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 test/fixedbugs/issue49512.go diff --git a/test/fixedbugs/issue49512.go b/test/fixedbugs/issue49512.go new file mode 100644 index 0000000000..597aec8486 --- /dev/null +++ b/test/fixedbugs/issue49512.go @@ -0,0 +1,54 @@ +// run + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type S struct{ + m1Called, m2Called bool +} + +func (s *S) M1(int) (int, int) { + s.m1Called = true + return 0, 0 +} + +func (s *S) M2(int) (int, int) { + s.m2Called = true + return 0, 0 +} + +type C struct { + calls []func(int) (int, int) +} + +func makeC() Funcs { + return &C{} +} + +func (c *C) Add(fn func(int) (int, int)) Funcs { + c.calls = append(c.calls, fn) + return c +} + +func (c *C) Call() { + for _, fn := range c.calls { + fn(0) + } +} + +type Funcs interface { + Add(func(int) (int, int)) Funcs + Call() +} + +func main() { + s := &S{} + c := makeC().Add(s.M1).Add(s.M2) + c.Call() + if !s.m1Called || !s.m2Called { + panic("missed method call") + } +} -- GitLab From d5a5a13ad987db9bcdda8c6cecb84ed8583ea68d Mon Sep 17 00:00:00 2001 From: Changkun Ou Date: Mon, 26 Jul 2021 10:56:30 +0200 Subject: [PATCH 2109/2500] sync: clarify the validity to call Map methods inside Range This change clarifies that calling all Map methods inside the callback of Range is allowed. For further assurance, a nested range call test is also added. Fixes #46399 Change-Id: I0a766a5c1470e6b573ec35df1ccd62b2e46f1561 Reviewed-on: https://go-review.googlesource.com/c/go/+/337389 Reviewed-by: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Trust: Ian Lance Taylor --- src/sync/map.go | 5 +++-- src/sync/map_test.go | 50 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/sync/map.go b/src/sync/map.go index dfb62dd3e8..7a6c82e5c3 100644 --- a/src/sync/map.go +++ b/src/sync/map.go @@ -311,8 +311,9 @@ func (e *entry) delete() (value interface{}, ok bool) { // // Range does not necessarily correspond to any consistent snapshot of the Map's // contents: no key will be visited more than once, but if the value for any key -// is stored or deleted concurrently, Range may reflect any mapping for that key -// from any point during the Range call. +// is stored or deleted concurrently (including by f), Range may reflect any +// mapping for that key from any point during the Range call. Range does not +// block other methods on the receiver; even f itself may call any method on m. // // Range may be O(N) with the number of elements in the map even if f returns // false after a constant number of calls. diff --git a/src/sync/map_test.go b/src/sync/map_test.go index 7f163caa5c..c4a8f8b99a 100644 --- a/src/sync/map_test.go +++ b/src/sync/map_test.go @@ -195,3 +195,53 @@ func TestIssue40999(t *testing.T) { runtime.GC() } } + +func TestMapRangeNestedCall(t *testing.T) { // Issue 46399 + var m sync.Map + for i, v := range [3]string{"hello", "world", "Go"} { + m.Store(i, v) + } + m.Range(func(key, value interface{}) bool { + m.Range(func(key, value interface{}) bool { + // We should be able to load the key offered in the Range callback, + // because there are no concurrent Delete involved in this tested map. + if v, ok := m.Load(key); !ok || !reflect.DeepEqual(v, value) { + t.Fatalf("Nested Range loads unexpected value, got %+v want %+v", v, value) + } + + // We didn't keep 42 and a value into the map before, if somehow we loaded + // a value from such a key, meaning there must be an internal bug regarding + // nested range in the Map. + if _, loaded := m.LoadOrStore(42, "dummy"); loaded { + t.Fatalf("Nested Range loads unexpected value, want store a new value") + } + + // Try to Store then LoadAndDelete the corresponding value with the key + // 42 to the Map. In this case, the key 42 and associated value should be + // removed from the Map. Therefore any future range won't observe key 42 + // as we checked in above. + val := "sync.Map" + m.Store(42, val) + if v, loaded := m.LoadAndDelete(42); !loaded || !reflect.DeepEqual(v, val) { + t.Fatalf("Nested Range loads unexpected value, got %v, want %v", v, val) + } + return true + }) + + // Remove key from Map on-the-fly. + m.Delete(key) + return true + }) + + // After a Range of Delete, all keys should be removed and any + // further Range won't invoke the callback. Hence length remains 0. + length := 0 + m.Range(func(key, value interface{}) bool { + length++ + return true + }) + + if length != 0 { + t.Fatalf("Unexpected sync.Map size, got %v want %v", length, 0) + } +} -- GitLab From 4b27d40b508a1d37ffcd84a411408309804d2a2a Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 10 Nov 2021 09:35:59 -0800 Subject: [PATCH 2110/2500] misc/cgo/testshared: correct test of gccgo version number We still don't run the gccgo tests, because they don't run in module mode. But now we at least get the version number check right. Change-Id: Ifde4512c30605d1cb7e3a521f381a05c783549b7 Reviewed-on: https://go-review.googlesource.com/c/go/+/362996 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Than McIntosh TryBot-Result: Go Bot --- misc/cgo/testshared/shared_test.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/misc/cgo/testshared/shared_test.go b/misc/cgo/testshared/shared_test.go index 672811fe0e..d5d018f151 100644 --- a/misc/cgo/testshared/shared_test.go +++ b/misc/cgo/testshared/shared_test.go @@ -20,6 +20,7 @@ import ( "regexp" "runtime" "sort" + "strconv" "strings" "testing" "time" @@ -694,7 +695,15 @@ func requireGccgo(t *testing.T) { if err != nil { t.Fatalf("%s -dumpversion failed: %v\n%s", gccgoPath, err, output) } - if string(output) < "5" { + dot := bytes.Index(output, []byte{'.'}) + if dot > 0 { + output = output[:dot] + } + major, err := strconv.Atoi(string(output)) + if err != nil { + t.Skipf("can't parse gccgo version number %s", output) + } + if major < 5 { t.Skipf("gccgo too old (%s)", strings.TrimSpace(string(output))) } -- GitLab From 99fa49e4b7f74fb21cc811270fe42c9b7fa99668 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 9 Nov 2021 16:17:50 -0800 Subject: [PATCH 2111/2500] lib/time, time/tzdata: update to 2021e Doing this a little early in the release cycle as there have been some changes in the handling of old timezones. They should continue to work as expected, but more testing time may be useful. For #22487 Change-Id: I3686fed79a052c46112445055044cff5842f2a45 Reviewed-on: https://go-review.googlesource.com/c/go/+/362874 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Tobias Klauser --- lib/time/update.bash | 4 +- lib/time/zoneinfo.zip | Bin 424214 -> 425837 bytes src/time/tzdata/zipdata.go | 13753 ++++++++++++++++++----------------- 3 files changed, 6892 insertions(+), 6865 deletions(-) diff --git a/lib/time/update.bash b/lib/time/update.bash index e088ea6b90..feb95e2e53 100755 --- a/lib/time/update.bash +++ b/lib/time/update.bash @@ -8,8 +8,8 @@ # Consult https://www.iana.org/time-zones for the latest versions. # Versions to use. -CODE=2021a -DATA=2021a +CODE=2021e +DATA=2021e set -e rm -rf work diff --git a/lib/time/zoneinfo.zip b/lib/time/zoneinfo.zip index d32fbba5175174b72ca42df853941f5a7122fad6..a859b4113b75fdc2f6e1685a13a80a85bffc03bd 100644 GIT binary patch delta 74247 zcmbRCN%HMKNxlGYW)?065KwN)44%j*quRvZoe09E72FJrEF!K93@pL%j0~s>CyN-X zh=EjrFsjPQjVdXVXS-^#fDD}M;G~FKT`xpUf+0?`F0zDAGh||!{M9f3qLxQPnV@<9 zU6gREL2{dmiaKs}P`5oWR>P&{B1`z@ViRL_h{Lw)XyR6Q3Zkai4wqrm3m-5>Pri`B zGMUdl0irlZ9#^PfQ7ov2%PUwEn>(r!bm~EEg0@d@2xeuS9Iq1saqmhF4P2&fER3F< zC6otIcis(`$&*1Ln&5841W_ocF0Sa8nV6ee85+XLzzj-hAdH&YFuga?A7=`=$O4Us zJ3@HfkSlzP4dRCXF5;8@rMYo=3?-?TDB?`&AdfLAl`=vM&9lXsK2btyhK~Yni=pWg z6i6=lrHMI-Bn8ssEu1*h0E(v$^WzJt={kliyqgmR3ZXtb>59{5@USnk#~DA3Do|ft z!=1}PL7Ar61+`F69hZfe31hO5Dhb(d78}mMzsM2}@wf>)%;Vlt_<{*sgguagW|Vke zJZhl{)YAy38h9WHs*6vqF~F5JvG_lXk+7lF%D4h_GTdTNrnoDM%VN~>e}Wt?^QJf2 zF{Vt`k+*?life*6lLbnqP-McJ%hoeJgC>oc`gnYcR15rf5m)q0EGR9>$CHClJyoqN zIaykUlVIj7vBBk5EU`0_1y@K-hUXmzC-KQ^J-G;43@R0TN)z)^NGuhO=;F#Dr~#0v zfUCMexV4cBm*>IdJU{ma7D&u`jck z+hQiSZD6 zKpphQ84Z{LrIU&;p>N)kIs=-{6BF@8+vd-S8PFzD$`V`&2Nd*a+YJ~QGa*W+JKkc% zmmjyEzr|R~3=W9NF1dJ0qVUa^b7w;oPUmW3)FLt$^|Ub><498Az}0DIoCGyBvWd}v zfYSGj)921$=GgwWg>g0{%%&ge!mDfg9xW!0?djc&`=Pc3++)NS8`~e;V+?>~Iz+Z; z`++M6QBo&36sPxC;4U`;1sKz}$FnoS;&EjNu6P6m&Saa=4zQV%8!B<7P*8lwZ|dW^>)&YkWbjyE3Dw%aSiGTG!OTkz(b;;jV``=`yoX(q^P+n>&2 zwt@6OrvEE(({_`+a2ml9JF#8Z0xZ;Ymu-lV_Yx0M~%<`gQuZceqo3qa7opf}L!)LXEicZ}N_{ z_{y}+q3ar;f!DbLpTg~)sf>M)cGL6=1$b-s?Ma1r% zVbC=&Ha1}3atsbJ;X)f~Y6-vw<{YCWSVjtE3j$^nY?qm!a~rY~e>l$(D0 z4lAc5?jaPk+GzS*W=1`{cDS=JW-@{8$Ypooo9-jYC^voHT~;pKc7XF^GcRK!L|bV| zl+^TG8Adq;uhOhieB(P{jjjh6)1ak=ha{su4!41oK9OW>gepDFiL=Q8399;7m^bRRkja7K3AIVE5?YkD+p@79~Ogo`~8QYE=Y`6 zKOht%$o0zf9C_R^Qn;HXdONoQV;j`lnKFzzctU8p>j6fA?LxAQVG#9`C6D2%xTiDD zWr^NyIgRl!qdh1=!7~>F1A_ok``sl!H#09YnYg|ttlKa>>KXnlSJS}S2dx7y&STWV z;ic_@^BJq5mD-6=Ts{FMjm>dku;$k6IXG)SMA;tv7*{QZs{sY6ozhm|t=Q4vD=5^;z#*d~JZqitjFg?VjxS6PKI8A#nevIn-vOczi8|$$L`yH(!bG zWCZ7N72eLA=?^LxMU?!rGV>DC@x?RPnygLGj?DCp%y?TQ)6d^xw(R6KLCVXwg>GhecyxWfpGZ{kNywM4N zazfNM(-%&~*;GWz%3x8^=iD$`^g*j@^7!HVT^@_$IoMU1A2S+amG6I zA(M<0SsZbRQq9|B~e&rQF>+`Y2E(XxAX^BZg=_uF1E*$Pp6)V8=|q^%-XnBMnP|)lTL+j5o6T{h2u?uR1&h zqPSu%KE<1P=CL!OHnk=vrsHZ;qQo4;c#8~N#={gRK@@Udz*RVIKe&=P5i;#IecOIU zeA#I`qUkW%?K7@Q1QaWi?|%LWws?A~0297!KRLmjWBY*}%vzB8bGoWM{(5YiJ>z$% z(&T8od3n0PJ4Tl2-=i7tLmX1#hqDg?axtXzo370get!kgR>AvY7pC@7qI+D1#C!uQAs|L zbB*wp-Yx^2&IAQf%Jc|BMmxMM%;1uEpVH(^d@T=H>A^A?Ztq!kCcLqj%)wL)4H}aN zxU0^>2aLzSNqoBXL;M*MoPWCd#rsSIqQwhf~%G|HrXaArKP($zkUMBeW`;{zn9-^+@?-@`A7UTA15&`B?)P!9#zS_fOih zm5qU6E8FCcJ8(_vA)DM=gx6ED#Zk<7XW!gQ6H`)i@=FU+No$5{_2X@ZZ{OR`_yC%2 zwx-}LtU=ind5rW;Jl=YD`Zjw;{_PVI7+*lL#q@(~aT-0nF`p@Vd*nLCN=Q1N?yHHn z&_-?~tWm{jEZD^kYK)vvQxC7f84mEmdV1Vi#&~c?h>`Vk=T-&=1`tN>2)UP5Cgu@U zU8V|whIA*%^0$NN88@pPK#Kvn>RI=IXw9n*2N;={8UO!3SqU1#J$`_J<^TWFE}$XY zs}~sfKts5?1}324TN6_d$-rf!YhYrBK8QQra6A6e`rvj(L1+e7{eiPd56Z34+jsn6 zj6$p9Cf6({p_I&him%VG`Oj16h|=^h6($8u(4sRCMqPM@wjlES_4bF;XX)dtXhG{I zrsuRV>3~br>9bXESL2N;DbuZ0VJh48nDEs}pjog=h?yE%Ot`vM;6%1Zi|IHtk!7pm zwjMNO`A?Ne8>&=S6Q}*4##_Sl6Piph5C<3=;dVfyO2YIDMojwP$}NvYvT_y!1H-K8 zc?Nh*kDtENnbi$qdYlClzQ+4@B=0$x;BEL#-msTr`#lq;8mJco3~`1A$crh{KNvFE zLma_ujMKfKFrGfum}xmgO1~tn;SrUd>LCx~w%tU=W ziy=zw-r%)=`T|L2{_VHkF!4a$d+{)S{~;XV(t}s!_DelX zOQDAPOvS5o`mL!wb$?wI7dtnb)7#Kj988$=3UDCUHn_9NRBFWSR~2 znsF6g_r^~@UB%=JiHT4)W}Hixz-7V*xYulo@kbh{5d%)e=O#(@tYTnb0AYA4cFD}i z#8V-Go3PUlEn$j+xXa`d-q3+0z{{WD39#-o-dbim?-_W+r#a*7NrBP`sP5p{{@dPiw~+`XKYSe`{ybhLsHdI8!$$VZ~49S7BnE9v;91 zZR!Y0GUIEYZeJkDEDd#qYztmjZ(q~Gqy%+^Of`O`NJZJg0GufiI74mw!b>c>q1_7) z31(c?BRK1B{0}RXxWsX0n(dC_%*@bm75|UhiJ(#rVW2o8P8Wjxy^N9hG_*~+Hw0&} zf|NosMnot)W0bPubSo&v;-{~7gQc#wtMDe=>1$e;__z10W)g<_@AYq-{@bqjhv^eE zB{rrKk(CwFn0le=rQC2Di|*nR2XHsg9mScWr^g>;+5kyk%rkI$4piJnPmeEVg(@|4 zz?mySLA-sh1H5DwK7>E(Am#O&?zp{$B|q?P$LU`181d5WOvw`w%;oN?xlc^4>VeuNgPT9UbgM|~SRId_e z6oM+H`02I3nV_Tbb0*<8RckVn9Mse|H8@=iPD3@dOe#>N#_TwAC|K!1cIFDGQl6Li zqk6$hc#zqx$K8Sh6+WQa8WI_AeepXLsn88tfxqfRPZ2yja2kz1kUM7w(=%uh_fi;V z(;6Jx+p9#FVGYlRzi@^KBKE*z3-dZ^5@s=j#ugrwGKt~n2Y~{dF?4%M8IuK5J*fW? z613$3hz=EL1oub6jHZG4VSnd>=?I|;2z|F6Oh4VhUt2&%<7Cr)A=fyWFT>-`U8JT z-28(HHVyqE9B29l`4+y6wmyO>9AbF(7QDH0`}ZwOLeK!~gh;Oi=&P64cW>9-$LCpOJw9 zgt=fnz2MaRQiA??|CK2iYMU(=&SnG1BgpOi`PXsQKHyLWO%HB2xWOa{38Lw4-*Kvk z7!7WjKKRb$2uU+b>Tw1Xo}B*hF8-8;GmWG3tTCZ?oj7U3KFfcko$62#Z71`uDDZGWl) z@^$PvCc()U3M8j5P-o78_AS4!?)vV3w7qMB)rbtj^ukU7yL?*O#SDF*8$V}{h8-M zV#})$imWtNEs%~66d-g(Nz)9Nqh zFfuTJFsQzCDoU)%%+U`|Eyi14f;yPs9g&deH|fS3oahVBd^>Tr^ueKzzD_%!6|Z{m z7C~1~^9s~thhcUG83yOXyu=ieX2et%;!VhqmC6uLH?PDQ<;W{iLuTPO5ovFq#ZvrT zLZrQYY8!DDzDTP#rnmItR0axZqy_ZT|4qTGbUI>lIK=zPJ8*g*WHkD+*mt{_CGhmV zCMUSFY_H~FeaARGbuY8N3wms_fnqZwGbfdl>CK`;%(xbMp|?(v78Kpsi!;Zg>&n^3 z%mf`q+<%-I*Z#8YACEI1Vm1bOiCt#itXLKX1`uWed8sssP(x=scqxPtNOwX`Z{0^m z1_lsjW{_cUbqyg@C`7Mh&0?JHc!}8>5^D{Yn5FPU!)Ev~4AXaCXU4TY2o%5DFNd)7 zKo{U#yo)n#r!zifPMe;3k68p_f9*Y-!8HBjaptt`qW76&n4Lhrg=J(A4GJsQl4MdM zf9Fe_gI?1OD_N7K2fSjI0dHtoS-q%m`o$;AA~HsJf)nJEr0KI?GE13(TsL3uNku*b z0|N+yiW;!%obkm6$kr-IC^SB0#x*qvQk67a{28+}cv2=WEhWPHjD9V>MF$&7QC zhG8Wu)Vuy)aGM2=il<+gr6JZ9yuz&%>_WEJFc;2yP9TC!Uob<*O%%T4tZhNzT?G#6 zIe&6z7BMg|fG|=}>l)(=HL&w{y=ImMCko`)f+Y%fUqXoj5?2uauYZTz|6sdZ-!n^t zhZ1hq>@_cDU|;}Y&`<(2W#}3bN*YPiZ@z`5{1(a0oZzG}eg7|JHXP*wB;nishK2jh z*94rH{|1_Pv#zFW0EH$9BZsIN!4Q@B1oh>F1iu#`AA&H7FA2xW@At6iPkoFx`XS*D z&MT%nUbI01#P1n_06Fsv79f3Za0duD&8ob`S7?Md69^7yE;{o8cY0_1$Xp9aK+<^f zEo!;YqCHCm;@AJ52>7-3GqV&pe4c)`NS=P-1G6X*MdgHd%+g>@9lX@BfFhfw=u*B8wMv$$sua7JQ>z+jF>BmO_U*E=*w&SBy$bFG@|q6F}P= zWm%v*>89V~WWlv=0o*7-GTcjy1>e9GXvUOf`vWnSe&}G1>3sYlfn@Y71H49W*D++7 z3iYD?A)KZn2in#XIF*6@<#LjR57yA!!Gfz%3sxGmljRB2^5S-!?wr2x5=;Dc-VT-m zsIhGP_>G;(&+-}CC2v@U(^!xTrh`|B$uDP_4-MI}Mx5%mZ){{)09EE0z=Ci1a65M$ zOFGmA7h~}US3(?%DO72H9{v;~o6o`mb%6Z^7V+u(C$aG1s0fi0;)N+VU4Wv@2B+7- zb6SuY%zRsxTBsY28sQIwP-7NLXzZ#M;#E2wJhs2HkR=3abowQn854OuM6o0bt`Tie z>~3e5Vu1~$B}d^5Tgc$|*C>`7P}?QTak>^965H37v%rolm>`TdEkb;zF2W)YHG9r) z-1R$Xl3=_3ANb5+T`ddV1$;=Utkeo;fPq7T&6)*vDA3>4cufWOZu{1-z)r2$lZ7+& zfKB$!W^sU~U%?XmN*9!{ltP0+ekR^v+rDWgizw98$xb*;-9E8}V5a&bOG4tJNsDtp^go0!Raq##~xaVGp~V6oSwtQ z!n-|j6$|Vzf*oDXW$Piq@@QJyzx48dy)^!W2o2NSaDho@zXwL zj_vnZS$;#+yUXHKk6bJ*UyMKS&6cpZLF4J0Dp4ki^58Ua`o>0<=m67GpqATTz!~_+A@p?`PH%%vM6Ke* zr*BAP!8x4(ZXAIZBd7&4bFO1$U|2VOwh0Tq(G|wt?aPx{!E<`$3Xs{YjP2)AS!Xj% zPtRcOhcxw1&%s&fY-gOyVgU7VPCs6+VB}0$4V+;P+4HnsgCzi(-Y&W0%$nd}LMlzo zt8hAFdtns|Y`;_3S)85%n}{@1mvEg0*N_{iSD!Zh$8{DlL(pJN_7a_K_G}CcAk4%d z!{F|Oue}M5FGvvg-ot4Ha^~lK%7SZf6XFukV2laKCCDQLpdA~;kLBRfu1l!D59yzP zhaZt`2MwvY`-Tvw8{E4=)(z^KxEH0S=9OnAXW$7;g!j!s-go8vrOVFDzyQJ=3^EKJ z`FZKt`FZJhOaR9^(gN49%pL?N-4^#*6`LE0xslk;=lvk=>7dhr8i z2ASNb5D9aTadi zB@Q>gvp_eTZT^TeH-Z*=q)ZR|!~$L0Zt@MM`w*T;{EXY?i!9O8zkg+5kQTPtv9aPRr@$6~w-AG~H`AAO=~o#T7(f_QI(Q`(5Og2f>dj{y zthk1jCvPl_o?gny+6}fVzTPN$JtG4H2!rhM$xNywI2Qpvd>K3!@o%p5$y_D|1`r0# zMfeh&ivTx*t9e*uq4m-nK2~CL++99ayj?@^{$@y);}ONL6zRB(g95C$MhK90?Sp;$ zwRh$u&=5QbgMAx}cTg8R)D$evDgkj*zBtYVuzjI8>mg=SP}vyPFvUTLg@FNtLDOA+ ziDijd1UGtt&wBz_a!H%ke-~z9U;trICFd7Ks8mJTBFUkG(~00Ts%6P~2O4jM>a4Oc zpowJ=#yhz@@tOe-cwZ+20|O6(3`0O-a%Ng)vc6wtDc;@SjdqOj;5`to_ZMdQfSNyF zm+eSkWcvR_UKa#-hf188DQD2(L*h}LJd+`!1h z3}S*pDBJ-WLL3YX+b%Hh=o%PI|EJ5U2=SzXDNdWF3(jYZ-oDwCl?^(|u-%*$*KpqS zkLIvrNLV6phA_C|Ss1|zt$4nLu;LuS0~OU1Ls@kpu5>nG#Wm0ci3&ulDeK|P$zbab z>A?*B=8fN>lYLlq!Mg>|e6~zH%)r0^!k~o_u(TVQSb#5Efr{APaMogo7X%G(+Xh;8 z1v;{L`Z@#FT!?Z7Z=5~`H!OC0vzkLxGREPI6>up(Eshns@AzT_E6yeeD7=d!VL|iD z5O*Mg9NS~WIuT;~XFdGhia)}{F}+)#wF#nJ%pG@fgKvRY>&^;oAk6m1okBqCPR<9i z!q(j$^22R1xDY`kk*7g8!xm-jV>HCg%r3+RhKL9Lz*yqJx(s5bryK4_14YGiH&*D% zK2IH-wnLIWcp2^s9aaZ$w=&sHUvCW~1H+o>5A9fSc0^D&j55kiPq%0Nzz!-glJl2M zzc`msetL-mt0(vz2~dHwhJk?rg!zz4Ztujr5`x=hsaR5Jx#A8oP?|(bY4?L!@ho19 zo?aQk3OyV_(HMWMfeqei%-RNtx+Re~BLq~=BOf-vWrH)JfwLy40R}Nt+8L*7A+d}& z?BG`z&V&v&6j9_H@xh&YPz$HMW~}%IdSS6Ry*`48b$XmRYbeCkTz0ra4wQZ#z<(!afkUp=f!2vpPNDI%LSh8b+p zyAMuI{}~w=Kp13EkUv3-z$ajUH6w5JfN1u{*Kh!(a-=;T7m9Fp;}H86!QBS-aDj^( zSQr>U7}RYDDJ{yzdqo;#vIp!&{c&j*)=@ zgh2^BoZu+M_UM(Yi=cfU#?`F&2I;qZXTzuIPOrnM6f^`{G(BfMD;FfxCq}YKn7(iX zHM|_tz!x5chOk2JGsNgkGcw6BBd+6|zHt|;1j~X(M~3P0dsxNlv39^wwS45LZf{~> zU;tqr1__X*V7#D_myv-1YQIZjc485+j#$;m$-IDpfnfoIHvCFZ7r zjvOP>YybALO4uxD+{XlWm19z7N)~ANi%1g|?q`*-UeMUV3^&0eu_&=9l~|8W|F?}* zqJBYR5DVM@|I)-y!F<)a!ag?#@jy8E`WO4u%F{Kf}2#XB>vI3uw*5!DPlMy%b=D#5y-@iRZeWCb-* zC)AL^6);;^n$&tB1C!R-2re}z^#Jt3JK{F zcRXK07zn#W7H2$bqEt-^(i`HN85kHq7&RB3Rh_Q4iMU)Cw$|nSDMkhc5JrvXS!!^f zdS@gSmE@NaUEo2>hv^nEY=SHc8rNz}7dSv)xlsy;sd{h^dV#mJ5NDv-%%adG3=9muAObbUml(iJ^v%yJ$}aS7>3DG6a^mV(zIc%m8+=!6O+@#X%5~3Rd$bpVpnx+`T4fRdT zNlZekWZ@O0AVYvRYH9#G%XUFyyb0U{x1!Y4lKk>KqLXC87H~63%M@;eQ(|5g=l}vD zLl;_(enuGJotd5pI_8Tw15VjpeE`0+l!1W(HDLCdA>5Q%T%3qItohLchJQ1-`8d-Y zZh~)8Vp3ur(UtY|f(@(^Rtp;ETfj|lPAx4Vx^@7!&21Mnid)0=JApQ|SCY^G1%<5j zg2u-PBVZR16Bn}6L2+BZpmD7Y!VQVJiP^Xk7)JU+PP3?0T$wH0NT0;?d_3hBA6k+% zj9~+{stfGk1~?Yyrh@kO6Xz-1J(x0kgptX~_)OG7brZ5TQB$Cu!*s)qtRloT8Ifx| z)I!zL5$-OZ(xlSdq{QM3qDvldbv2!B8>=wOf<|_y>9X5cC5ds4P)T0a9~K4%5JrtU zA!oRAoI&j_VoM6d0)gq_`&s#H7Bq%U+T{b~n!U6Ylp#%rKwh~}?;VAFJ0KaS)Z)nsbb-pi@F?KPsFff2H zYE_kpWL!vQRw?+TZQ|UBe1)0_+>Hzj3mR7kFfceyZY~s6BhIAhil4!qr&WOr)9pSJ z*WQ9(ZwbD@4S8_DGZ+yn?X7aI$GcfRhPxe4IRwIOA`ou@9V)jHd zT9AVVHIp_(PA|MjTqgA@iRxiwW?%qe)E-zx6vBrAiFxUHnMEa~poM6}1$W^|t$J(l z-QJ+vF;QafSS-S1U!<$7i8dIAxrgHr=7R3Dp1$)ZD>qSDN&X`^X&i`Wm~QitxZ(sk z^ikXM(y0h%1ee5nXO@)UsSQvI-u=v_pPw*JUw({LC}KgQSQ^5lpw#5dG@>i(YyUp0 zZee0z0AW2I7VFR4?1!4+Yu%P1`tLqz#Xy?4s%W{Nz6?w!W^l=H6F1}XNk$l z>4&ed3fC`a^v^?>7S2leD#00@=h}F~Unix5p ziOV9}^|on&7CC{iG~6SgLer%lY?_=FaRz}7znK0oo=qfjLF1ZcM7a7U<|URAov4ws z3L;!V&Y954FuCW41hFN!!eel^WkMU0OH%Vv@+les3y)>~T zHJ5~XGgMJ1?Isfg0|=v*nR~hzCihp05!qXOX%HfIk&%G`gi%{0k9rZ#^D8aQCN|kY zLt2ahRPdq(_0N8W>G$5VN)yvmvYKTWa-Wfb0fbR2-JcT>4hv4sFG?*=sw^(eOCi>Q zbM2=GUSbuCUeKsE8Ofx?{P=*x(j20j;Z4F-j}9>~Fn};>3}{ZD{_h~G6j7!A{_Ehh zU@-&X68D_MC#A7`04HT8J<-I1_g}x&CUJ{3=EqY7#R4Fo!8i~3EABAeBuqAe&!>qMD&8j>dgofd{gs4 z7Xhc@si9CSD4U%U?N68(7(f^`GNQLn=Q~Q|FmJ;v@JK+%E`&>b65|6BtB8%h>HDs* zN`x(FtlEt*!4Z7DJaL8aE0u%$H!v_TfG}$A?c6`T@d~RHF++C9O>@+euI&KB^gr(y zC5SAA!PPyKK%^p2t)F!e;Xm)xypq!7>`HxN1BqE``oasWVk`?9w;r6n`vR*HQALv7 z1#ma;+R^Dz7g&{u$ppxg=cp|`*3$^*gPI?a`9(xmBssQg_lYrzGcbrTf({=!YkLoW^UwepEiWnb3D=}~#hU%l*D+nJs=B1Zr<`Cc6)wx}_dK2^X zvS+M9whJ07t|Cl|Ow2AVNh~2YVyEX^W0kO5&{%vEVMK67W~$<7HpEPS7}x$(N+KS_xHfgSn>g^dAj_4;+*kd|JSFWE)@vNp*Z8{ zXNXB}IT`tg4U2P-uz2_lqV?ZhRzaeIzaQfGzds@R_TOXWB__(>e+cRVM>+F?M!D$= zZnKI_w|PKhFMG{>Rte?>ji%EX@34wa?~^A!!u{`qLpqLmdiH%*Iimcx{xY}&mdM69 z{mf-b3!Xz9jPUU=7f_v@Nql#A_MMfsx7czR7;dqlF9+Gni7?hVBQrTMo#?in%nix8 z1&j;~AdFi5JrH1={$L)X1d)A3Iqh0e&?o^2qqgCV<&fA~t=V4M9(nJdSb85lqqwbNl^f$*ePX7`Y7=Z`K%1_lsD?P}UP zAq;j(%>fU1)f2UN4|#hZY6u9pAk1`0%_AX>3$|6C6lR(({Ek(KbwOj62jlb&QyE2x zEE;hqkdt1Fll2c0J@e4`8eDyC_nAKTHE|;_)$HtdPBAkufG}#3+8clf3)hs~e8_ea z;$jWbvd(1yH?0wU9neVJ#SnzC!6oq_8Tq-1WDW44#@yM^>HQChEV}Ezfd@d2g&|x5 znjJ_jDgv$6CeDXjLiWBkWny3eVbtLmvj~K-pw)Z2iKV&$MVWcYC^ds610#HO0mfK} zbffM{P=W_x)ZDZ?ig9w_5iugu6(kxUv4C3eOp0Ng{O}9W>B=yH4b&6qk41RRHLo}o zbfhn_J&Ni7F0o2DENHxyh%m!BzqlkZK8S=i&h-9s;9{IFnQ{7>bHt6_Acq2KJ+?L# z$t|TtiOGpXH;a~wXI~#p=|oZC&bNR=EpOX=`%7gfH104WU8h= zcur)=A@__`B78yP z!jdT6x=;0tlh?M%5Lr4vsw@TuVI~F!85DE;n;55GJVoS4lI|IBy4caeIJv%8ib%V8 z-xe3>F)=WJFsdIM+8L)WKf@|dOh_=^@atL4#J~W;QYbz+*vUA(@D!^8QBC;^r@=lr z(8D_ZD6|{@U}j(d zVbqS2=|slK|7*mFY&1^?b(L%uG*(YVxX3xNGMD)E1Jez^gWD4k)291=C$4L2aW;xI zpOJw9gb_&`RPl?=LO8=Wu__UC$q2EP$97$#v?q*W3=B^g(Yvynt4n^=@xoRL^Y^g79pKV?tuW?*0dVboU4hox|n>-7T?i$Kc*GI1{A#HiB#nJ;XY zW@KOhVbp2S@5|r@>-%I9Gq%9SzyR9aIz9h6xb}`%fiS>15!A9EIxQXEv3m9g1_lNY zMve9Ol?X!vGV)XNGO492iiVSCSa-Sd^Mabf=*{ST^Cz zdUH&XFe3v42%|=5`4fbpUWvJhxH{SCSTfVIp6*HC7#SEq7&S(P zpCL^3O-xQDe$B{qxu@W^WZ;YGR!@l=n?f#JQ9bAN8sUtP{36iU6tPXoYY(qB%wc4h ze*Gq^AnSrgk57z~*MAiwwn?pT#0HvuF#LkB-!BpG{s^>@(s~uG1cuu2kR%7GaS94DC> z7(f^`q}=$Kre9b~^cbxQQm+g(F-8kBO~3zuxKjP`NzV(R%nS@5jOv^@;z;3Jl$e(i z4>~@A*i?P?aM|POB_CKtSQj+fN;6IG{Xkst#>o1)b1MS_0|=ugM{5}*_mozWu#z5j zvyu#; zJdL|0utLiDKabces-N=ie2ddy$q zMwhKl1ek*s!GbVqV81d#aY{&0eohXt`T1Dqcf%HjdIp9TjN#>{#wf-H<(FiTu!k#; zMY3`h0|NsHqYk`nH9;}gr8GBxy4-(Oequs@>UuWNaRG}=nWpDjFi8-3Ucjanuhm4E5;F@@i7*jj z;PgUC@TRj(9#HMhi8;xoCB(0T4PM%q`kjG+0fbR2p{t%yBLnjDNR9@rD}eSXh#uM0DXlOX|+4I}8jAAdDIn2Yi_r>cP?Kou8APNW90} z_rCS{$i%<^!l*_*@`Jk3DX}Ook%)c9$_$XmSe_Oa>%hps0K%w7N(N2e$jc^7Oo#UP z`uj5P7#J8p7&YwX2SeTEo0ykL{P3v#^0;3aObiSeObl)es3u+tftu)8Qdva&GKT5( z5^NF{3mWUgq1t^(nG&3?C<)emD+;PRFtLRA!+fUSWdSGnZP8HOo<-TECB-mIoOCA#%R&x z-TQ`tfdPb3oyD60byjdOl$1&I@Yb%yNe6?N7#Kj9 z6J-pKCmUv9ei@dXC-vAHbStY)$e&|jU;trM^A_ep&2vvAekYNY;HyPXnHU&A7}dD? zO+`@i{Bwy&JAdFh%dDcL^>71XF zpG*8~L&rDgmKh8T3^N#}|7K$2t6$LARtq&LEHf2c6A@i)ILRK91~tP$7}a%YbxdojFyUnUq;XeA1eJUV;sDazjoN)C}Lm^u&}zqI2T( z^_<|8w6GPb-#f7+BR4TG1^4k2Xu~UrKn9(2j=Yl6OWs z)PSJO%EXimVq5a(CQ0?IVqjnZVbttv)B!cnC6nOxeNf*JQWyI?m{NpG^^V0E*%^sRiCC%u?6rXUqnQ8m85kHq7`2#PVo8?6*2P{@W4fHH7NzB8a#CTCom74xQ0o;PsUk^3Gr8EgoT%twg^gac!hkn3x zdw~wKB);SFw&&wSP=yATTn{0KiF2;tzckeU;ts%&|Z23YHV<3UV36dKK8?<>aopLN0-hl1oh5A7`1A6 zdlYJDNInTIdgS^GwJ1D z7^Y_mvGLk0Xnb%QYEnRDeqMTIBEjMkQCixFfn)Rj8K?=7so9AosYRK2q@31?e5(^` z$SYrfnj4azU5RVFSQldn(WaeWwt@PMAdK1?v$;6^fg~GIN1j?nZvV)|$iM)?sHMb> z%TQN&gVqpb;I3BDisIF0@3X#RVqkd3H2pR|xUZpc6>5@mMket^@`pKTcGsC07(f^` z`A6M=n&+LEo1BqYg7-j`c$AFE9CYh#C=&w%2%~zp@;1~^zs%(PV&dm^rpG|~4I=lT z`h63#L9?<%XLEyCE$J*K1_lsDb&}+LsF6;YpvDrO;h1{VM&;FWbKDD<7#KhpHRw)0 zgc=!GSyh>nUzCEFf*~*i!!%WQEod_*2%|c)@d;BsWDqzqwJ5cWV0#*#ua-pJpYV){ zfdPb3CnUR{L!B91l$w&4nw_6hiMLEbKW$D%5S(H6zJeO#n376#(Sh93L=C*w*HGh} zGxGD&3kfv1P+J3v0$>+~y@eVPnv<9p@03`QPjosFe>7*a5eowY2&1~|<9n!~Ua3W; z#fgyZNLY3wVOv>ms{pR&vcEu$a7xWADkZvAK0RIrJo(b|ooV`qUreGzZX2A}QIjx> znSlX>QH#Q9KcMb#%q3y1@by%+(lRCnhO+5mGHm=-3mQxQK#g%qOwULmzT-5#krmu% zGx!hH@0D1YSWrrQcWyeL5ICNd7?>eh!m+S~_%UEjQBTj$ObiSlj9Qr&BR%rtoij4yeKT>n4O^DWkp?G`mHbdcf>ZN}?TTjxcL(Q%EM#C{ z0AbW5(jy2p&pWY%;J8&RauNx?8)KBn#J~W;sI9LOA*h*-Ik|}?#2*^42jWF3QK)t& z(27c;TM)=49jYIH!VC;a&53s`%Phk)5{A~jgify%NkN?inqDC~)lYxJ!zN+Bpz*9M zR5xgVGP|@YFO`H@lIhUFymtyvL%d7N6N%rw46Zhz1S02wmTK%!WM*&#ZD}aUOeQoH ztOhm#v|K!QuRu1a7XZSjweN35=IIj+n29aTxAX1I-O0$n0K%wQ*g_S_VQz`3MfpUJ zGQa4JY{*^9%D@1^sHR$}Bbn-01v;M#PclGh{vDd`w{|@P0|N-7&VL)|PPbQLBkJgu z95t4i3@i)`AdFfr=;$H2%qg`fx0Lwy6(khJAi;=Qzn2+Jf3M6YO3Wf+LrwFwpb!IL zRJWCzOn;}uM%;RqdKEU%1tWP@(`T!&NfNabqDBea=Z>>Q3W4B~#Jn65)-`}`-f&pZ zxYq&2jChaKoK)g>1x&9~W|Od8(Ae#WWQucQULpzSwd<>b{lCe1y089S=0X?XqY$ z=IQyN%;H40%g*mUC1u3OzyQLiN$`|AvM<6@i-~R`F1oYplvMyD1A`UD_9+)nWJ6s` zlZl^ypKhQIj-umU(|y$0h&mcMV&|*^(5)~ajG8rO`ysm{xH2V=_(bda=~>ik=IL(Q zY(h~B8gqk?P4dW3N-QEepp19jyR68_zyQLiHCO{cz<1RxbR0z&(>ul?u0-G zZLk)B=;<4^h#NHMPpi8+lbL}5gi*_8*LY^6)E=B)T0(52Ef^X<(_OUKKnv5=laWnw z1~uG@h;N7YBe@VYFn^~pBe~EqB{e58GX=d`su#g^uIq^)Dd|@X3=ANQ>h%X%$Oil6 z7ZLAuQt1UothW#k%?F$ zs6cRw#2;O7Bets$*(68M#c{;7`;i@oy8bS*6xql~(19oAnR(bM05R;dU(*dVz;#hb zC9**-iACl3yG_VV;^`AK!3AhX74!5BQA9U|W&o`Flzf^e;u-8d{c9h@=J?| zzn365-}qJ#==35GMr{*MX+k#H$HSA@#?W+79I`BE>~EdEP>qeaD`!AU59?nz#&t3? zI29#UW#$lSZ-VPYP;(P>%I+LS1_lsD?PSbH7)DgZ0=ldgWa4x?eQ-QCbi*CvlIjQA zk&!|4sMhqidf@Sob-i#i9FwsRr(+vUpFRhoeQG~kyK5rxbt8Bsr|ApFNt2lwKuwes z;@445*Ea-bz{?1&zWJaHio~b!x=nnNVeAYHAdH$=pG}9m$1k-!Ex$A`B?sG-PCWzm z9Ekfo)z0~FlVLp;Vv{TKd8*I>NPBSVTF@A^3~p*E?ouJ4~jnU zos7g4W1*JH`;1r_7(f`c#k6Q6+)U`D;W#{sc^oa|=zPe@`KX4WUpw{v8gUk%h8JRh$ zM3*Dc!P1DWb*Nhb)DJOFZ#=|I^!Zwa#^8oe$?@sE#zeNO6-?M9OcylrondBh4h}JM zb|E?prstY~gO2S2GlMe;mm?+Q^wxc3WMBYcW_Z|vng$E6Ff+Ik9|@qVL8h~qg2%+p zUt?x)O|L8FDy zi4W0xrr;1g1JP#cN_=EM(;}Eccn6dqk33^$a4jJ?i~`mPu7vt5!OIqyoh~ znEe@K76_x7XYm?go+&}|pvFy)b6}G&ThRChsyV7OhxoBWLpwGJ^97A_-@q-_H7DBQ zdzRn{iJ-S|&Dti!YW^-++&Epqo=wDJK_lBcxB9&#H3_ z@uCeBj3A5}l;^*~ouN&1shfKGWgy5X5az5$DLI?JAH{3P4glipGEy3piZVM>=fos+#p)DX|53WCNAav^*5?$7Vau%pX1;U7H&OoWA z|1aD%grl7s>XmFsn?P7u;qVV`fG*MQ*&|uW0ye;WLE~2>1BkDBphFF-{xdVUmKNm~ z5Z^^WZmgn?mApn6=2DtOU>aSHnG2L`Axq!0m*{M>XJcRhVbneu7aI%AfljG8X(V+2 zT~d^ffSUCn3?B9a74_h=fhO`m%$(jD$R|8y z5`FJ^>4vj^elRgGfH10S-x|V=4b7=c%*!t;&L;jkvwgm75>X2p^-bZ1IF%-6B!bS@ zA-0J$b<4cxo0%CHKp3@{;Io*%(36e0^WE#bzzLqy2JR5w#FU~;qW6FFoDjVb06lOG zHEUnAhZ`B3pN4OhV+!h$!iUa37v5uJU;ts%Fi&@a8|jl(nv|18%E=m_Vyk{ZW4{aB zjNt72f-Lm;7@X5Fv6+IU*O(X>Kp53oTioDAI)Y|jvomllOvIM8d)?S1Y!)~%R;y+ zllU!k4-dX(?O|qM=wW8?K-+R9md`;jMUSYpsKU$FWz69WSXqo#@(<#2NY zKqpiZT{KNU=m#zVHdVn52uaMz$;`vi!oWN?b9zEBcqz-=TDS?$8JWeIdBm?MogNng z&bK!k;6{We78NHF9b?D=gBswwr|bI>IclC51fER2+0HWk;z|}`FBd^>a-+`Si*&(# z<5`@O8lRsQ?~AK+#|+l&dZe~IYJQtP0dBB+X=+hkG4TsQkarfKmT>CR;f6x?7EJf| zW@96&Rj=;}p5Z()6K;ZIZgEL!QA%Pi(OJ&U37m**=fTZzDk?25PR$|uRM_cuuHeqa z)kV`cxDZzwMX{D&pTxw#0K%yG>CY0lJ3w2{^RSn)Sh6U*1v1^;m5o1gLF3isaFc=) zixRU^%W&%gwdS0ayp|kaV_uTU#Hv(WMNY5Q-C?L8i!stD-$ro9sKXhjiA#%y!Gw-z3|CksUKo~WiCtiiS z&8ajcv4Dg%gP>!o>Op5zfiP-g=Ee=Uss6>pUnsS@AsIf7i8@zy@HPvBTViraKHB)-Py00nw;ScytjuxQIMfiI{x_ja8Pt2D^a-lcpy` zu!)&3XjFc~!r)$%nwnQm!obk&;!$t=?h|rTS>cfQ`8!m z&rplci$CB#^G(c2$t)xOMhIv`Ot*+(6SQ8?xalX{B} z6S;NZK{U80y!AKSPT#}~qQi8D_v-VY@C0GhFs=VH-7ktrH{6W^cf9=m!rc&*TAG)M zr;bP4!aThmk`tu=u`qa&a4rV&#w9kCc|~0|RtC@FqQq3}T~aK~UDbM|Ks2ZF zu`>8%CRGyM{Qoys`sDNnMrYzymt11%y%C`64<9)BG}#E_9PGt>DIcqucy+ za9Q{T$pGKXlyVYIZknG0t|-sxBAgJAm_x!4l-tD3Zy6XEKp1rdX{8?P^oyaa#CA2_ zDA;zcVPIeYVN`=2>Lc9dnwOGVlvIk=n#a?apI0BadTJOW0|N-7wk~cMAeoz%NPOF1 z`n)vo*nO!H!T`6#?8N*uqLcTlgSXC4e;CCkVzZzz+!$d@NMc523DH|=r}yT8hZj^# z5GI5tW)oc@PoI+t-uU_fNq<0MdVV~JAU4lUUziMTN1QdCzBie;(#mXmaCI940|N-7 zmYQ?T5IzY>EJ`dVx&}G(*)s7k0|P@nh(PUCW}71njZ7>c)??e>Pd|2yfq?;pQC(SV zfiTc7zce=$$(2_4v#g6*^TKWh1_lsDP3Dc3(>G+ZNf0%1(o+B)^$WK`c1KZKeh!{f zL{Mk^rr*s6kJ?VRW}W^Zf>n&jgSB6Ix0c;yU|;}Y)Fxb(&2+w0;-dfFRukQ83=9k) zj2f^LZ4n*{$j?h8{(gx^)=}RGGB`0eA1O)UH?r|@ITvWhGYAVZOn;Tj z#uc@oQOgNooO@zUVgV`LC)}~DGJRtvaf=S7=b1}=VqjnZVbn~n zyD$p_Lp_KE0Tii`M`(6+jp@-MkK) z&YwZt*$K#91JtpYo#E5@(}^3aN3Ic2U7{6@@M3UcCYByIt`7IR3o?;@EDQ|OS0u54 z?!dbcgD?rQUyaz}afPGkzv-ac^cc}kJWWePnCV!6XJJqp+E|IqmHnlFG^ukWWg+M4t0O^vOV@%l|V#W)+o`rW3h=p}r|I z82LCb)PD2(JXVH)AZKF3{^;7UwV*yT2&48qw-&H61O$gz1fX}DrEp)6EA|ua8!+GT=R!659|j@{zKr zLuVXStPG&*sIW}Mi{mJpr`r{S1LsE_D+6(Rpuk(8kk|2}dTB{LD+8%}U+RNlBLg5B z5!j&7fv^TvhR|T52L{3#rZ@<(Fff2HYR6?V#2{>2f9vs$3z!N9vR!0mU;trMufA#l zJIygCu^8{UiYT+t$k%zpicUw6w-+@2>j0YvDyMWI6B0zXTc-<@f}=628*GGQPHHLW z&J<#kC~_MW)sGqdU;{l8%M&vRHM}B0-T)^L<5}(}F0e5$fH3Obg^mee^FV$iVejzt z{UzXu}5V*hFmLAa^rROUZ2uz~&Lx!w82? z=^tH!Ob~^2 zc1m~@qPpOLinxMLX<}YVVrU2_12f3cAdJP~8yqHEf*dV!ULfxjBLf2nb2G>=IHnb4 zCMW89l_n81qCiM{vw?mcBiNafgf;NEa(X}rtMO!ei!89($+uNi@hJue)O`glh++k2 zd;taW|MryY%o|uBs#mDtivy7A$p-oYn?2R@Anu;L+#Fv7qdEMF1R>Kmr%K*pgE(cA z0U^bcoed)(Y8lPMCr2r86CWzOZSbWEw6yj>MSSv0F?^;^-rz79<`TjN!{g?(89v36 z4q8l3H@AV9%fgR0G~o7&I;rCc1xN(KG90fWzNE3aKyd*yl6Tuk%H?I1<`BpgXu+1i zg3l>vikIlB;d3|Ke~be73`N8PD9#S(5Eo|$HN_PjlQL7X67xv&VYe2(#J~B2)>dc$ zMtb4%9a>Ou3E_?E0-+vAlK8=+i7&`d%2szr!VZ8Z%d_I*lWo0uh&6nozxZSuYhFCc zAs&RA4~m;kW8&iGF(ZM%(4Jhv6aop5Toduh`-})X1XhVm^v7p5nxpkt@r58LV{Jaj zYRnFC$wzB^85_;y7F>5Rs%sl<^vhT1T+*;dL%NKONM>mxLiMg@xDT2P*hnfN&|J zAifF;6jq2@Uz!o0@6jBPK zs+O-|bUme{E=C7Ik3aoyu%^tA&b+z?!UJ z>W}i*faQ;F@B_;q`>+8le|%ySSpI||4_N+W2|Jj7O2`2$e>&6(tUl*-yA3$VFFm|m z0SeOF3vYuJ+;Lhh0pj0n<^vmWPx;;q5dVJaWHA2$TQZpc(Cs)_{ln+e!RjBY{{qWD zK5+^x|CCb?EdO-nKZ(g3-StD5nOKnE|NsBbfSTSc8yHzYGy@j{13L!;ABbe+^YIN~ z&^9nIGGK6ru#62DxZHh147kwR;*u%~cv2fAE6Bsz*YgbtC2K?$(DjievO8ct9bYpS zlvyU9nOK>zoOx6TnWn&oO8Ia|Q+m5Jq;2Q({q4VoE+Cr+~aQ zy*`_nLr?&eI967wJO$A^T9cnny6m9K$jk(V|Nozm208SEGy}{3|5qiSkC~c0ze# zy1;1`md*dRPl0qkr!&hk;;jh{x;){2P4z}|NCP>+2+6wP_{XKfPu@$ zclwTEMj1$2+M33Qx64osrr}r{SK%IQ7 zg|PDYR>s#*)BW1vovh$IkE>wzO)Sbx&o3d6=ZPtZrYk-pm}Vg!-ujGj8N|cW*NfuSGwEOn#IrKV zgo+RC?HiIA*`ZO@aRINfps?RAaglK+B;8K-%T~je4lX>g+Wa9q6Mqfom{*dSUP_f3 zuHv8?artxdlcNUs99|%#z1@hNsgDKRoIXQ$1 zd{Ag@PB_%S%mFGwRd_pdrazp`C^G$n8YAJ+34NCBx$2Bl7_C8ikt-fvq~h1Hi10`) zS=G+uf`#}hhUuVsWHa-k9A+Dk^Db^|OM1u5zyQL0NY3+1EG|wgC6Glxp=24$z`y{n z8YY`Nb%E-~(_h{PfanXq+z){0i^?Wo{w3uv;Ev9vidhG?H+*N@!!&)NIiv6N1Lll8 zEdT#+FPk2-ky)NKJcPkDczUG@qYgMLOg5Q}FR@NH@MW~xZa;xJ7LvB7&og3_nEu|2 zksnV&+3w)Y*a*#$FA@pnG;lL|dP@@H6tIh?pNwL}Tm67qKzE!N`M2jrGwMUF$!Eh` zvusC{|I=L}7`5>@9u)A~??k{VfyvYN6LQRC10$Bn1_u(ruAdy6Cn=kfm`xyhHy_Ab z0S(d3>G+$Ipj_8EgP99D3e^^c&pn$zL_L5OT9*#uZFhqGnRe-4ik1p$`Qs4 zi1NveHwm>;Hw)i72K8c(7|yz-P>fl1;sTcG3Gqz&(^J)$_&4|Vl|k&7eod7LUv`^Z zps2q+Q;n${s$AkcPFrB}QqxzSXS@xGC$|~+(mg12Hs73~!VIqM9?jbNdmaM=0|=wE zaEnrlO9(dcKxWx9GcYiKFb^op#@QC^0nxLsd4sd;yr0$#j7*IG|4%vsYV*#W0BZC0 zH!yI3I*Go)Aq)Z29bYpFgB?D-Se|f>Vpm|i1W|qADBg?#a@!`~thH6yrK6+Lm9VGRQV7$X;}?xmH9d4wuVkbhl4 z@c&dbt3C_&3kz3c37iC5L9yo zow)h!2onPX2rEo}@L6>F*ITRt68L9NVJ3j9_3qkja+3}I%1xg69B-u#(xmtz6H;VN zPI!W^X}chNpO=dJh9roejX#t*uGczx)Goxv03YNBh={k-v}6Oy?Ork z45;GuZwa;dH+#HGgDU3!MaUVGwO;dY-uA1A2^@wp4Lf5d^Z!zk^C`_FW;hD0JN9D{ z#JcG@%mn)vlRe%EY!_u=41)|LMBccz_8Jod!?no`&n2hty~oN)Aj&~CvBD-6maUH% z+aR`1*7=Js3c)cW@dy?((^rWz5$MKiZ?}_R;)JC3>6yYzga&Jn`j3+t=isa8!9y9F z=gv6CD0eM{1F)zI|Glx23Zu8pkMI$1gPoK7zaHB+HAEPfLYM@R3zlh@T zO;BG_Lcuw)GMC^4GQ3+kuMBStgG!q1`sIw@A$euGoD0EjB~l|Q{sqCB95Q_R^95rx z#D>WqdT~`q_}X2S`w6;hJLdt$qtJHO!fL#;eUlI58E-eQVXTH^;>m4S@kKtQ4<&sq z3DWXHPL0SdFZZI)rt6n8@^8=JVR`{c6w~b=FiI!}WaOvjWmXXA zrhxTdc)+*>;<$Nigo|tN00Bg~<2w9)0rhOIuVc)GEK>q?E%8+bNWIF*!lwz9Xq%Uw zZh@{jnzjq?C>Ur-h1zcDNb%j-c%v6wXMl&lx9j&XcQQJFT1&`jR0ye`?_QdilA4oW zT98U0l!-~E(~tV#4b1HZzKqkMIgEWG{&^Nf{mly}_Cs>-BWy(Xjqg2}~8@fHZ6RI9Oo*#?rjroR&)*k{__D#)k;3GV5iZ{e)bkc;H) zCk`=hgXRmBSva-8`nB5+h_Wi9Rf3ZRCg3XkLE4B)bju_NmR;M;BpFXaVr06vH2x@= zkZLjgwKNlS#5shYaB1>_pQ#pN_~di(1WUSI+nISc7bI+j2ArEL6QP{HebxnLL5T9n zotp`zr_C~3JRz=`9-PmJe{4cX8>#7^??Wg_Av)ow0|-ZV(G=!7h(jjt2*l^=%?d%r z(3Iz~nQ%hAznO6hq?VZMvIbva45}D5-&g}3@tz)GgSYn%Qoa4H4Py)>Gfs}p!nE`kVb)e4sx3w-j$4pIjiMKYiLV#%xH5z`7iNvjx<-nY^6wJVbSm z3E^0gGiB6(#LD#3oOtUIaDc>cG4??Vkt<;Y$Lgl1hcn&;H**n-1m+&V7mgrHNLnNS z@oCyLym7hx!ZgMJs4wTn5)2eXx_+&Qe>Cqyl>YWQC8j7y`kOv|8$q+TpZ~&`2@S#4 zCj@5i}BXLlM57$xA!k$%!ZW1@X3kE zx8m^i;K-VYn7(WkUZ+nNn82jJ+;%l1G%zb3;tw5As}iYOexsORu@7GVHhF;v%l3j2 zMlGl{zD@)S#qD>T8110pAMqN$t3Wj^QWPud;`K8qxo>ya#QY3eoKM|=uV4hJ-mI}P z2`#dwd#%M=Dv%djPt=(dh-+j`|Dl1m3Z0&y$&>=gr)K(iRf0UY{iHsVHZ-sPFk-^j zW}bA=Wcp-drWlCX*R}9g&D$NcnLa_yJ)w!$T#z#+pP9}(Jza|_2Ry9B%lFA(x~>Kj zzM>1#IC;J?f`Jh4Rl!2H2-7`r@0P&yOFf}kDtm;_+vFdy@$~5Lyha>c=}wxLsfZlNVHJ=OHG1>nA52G@dSZn8^(i_ET!{wkJWUpp%Cg znhM^X!fW#MfYVH~z`KpivSPf>voJ7#FnG5SD0DnhlZx<8EFpImrd#DP32dJq&$N(v zI^zTu<>`DyOrg_HB{O-7n&_G6n^>Z+9-90buSY<6cDv17CR=DZojx6J_=5uJ_jD$2 zNFdeD!=JMs%wsBts5}ylS0&gLK`~5gpiz~x4X^U)3dKy8+c~x~bwkzL{m0+l0JZPV z{%4AZIEJH=V317HWM$btr;=$q)Pl#Jc(qKwaF|Jddbt-Y=jtxPn;^j6UH^}z12WG$ zJ#s(ZVqyD%{Y*!p4mnW7gs+9MU7?ui2vli}8(~K{l(KGy#{7#?yfF`Q^YqLLrrD4% zR8PShARyJ-x2G^AK#QibcD!x@m6On_E@lB?gTd+50#w|bbFXpiACNHDE$#p@eTc5-iH@`Wf~JBN_b+Q?b;`a`^CgM2tWpqhncd-fwH1!$UJ7h}fN zm4%iv+Y>%8i9(uH(|^pu>!9fdyv)|yr_W{*f+nFq3e5OQSa2+Z%RwjEW74e*3=AL) zF9$=5N^=V{an}{#9j72OET;3cWg0gq8oe0WViR_~9>y zK(*2I?qf_`+k5<(rbEN{wk$KD*68#fH<)<0SIaTiLiMQM$7>NHE_dE%l7i_8BCKa? z5Yrb(;*!q5n*+f%tjJ(m08zd92;Oi4m3LOtb1PYwLX_Lr<1N6zwKgQ2?$^V^=|KoV z7j4fCWs+es2j%pRb88>%Wno|dVNO_1cTcRsw+aB7q`?bL7>l=C=P@ln)S3a)6N;F8 zaMYR(9e9h`=?glTIw4*+yGpp&C)eTb2lG4Pin%&ML&3u{(Tv-O+jWJ4OVqgGacxCCBlbcvlNvN^}4GnD<7G{Q? zr7-=VGhT0jLIKib2zFsog@)W~Zf1M~+NeFD1}TEM7~(TXa8xxBbkBB}Cb3zOSdMm6kCvFn}-*ton9JOwUM3Od*hp!ND)^mkBoV zIO{v!;0F)=BU<3PdkE&w?Ys6c&4z}s%SOD)A%)z%jj-ltBOf!qkv5Rirz2Wbe47YI z-`q`1r=gvu={xb}4p8`l1}wlMZ5`j7Tc$V8V-lXezKw|s&j<=?e(isP*9wsPx63|d zs(^;hEJ3{0BFIIE?upk0R0c9+{K!eOc7&yoV| z%2a;A8?PY4x3hg^ngDeR+XlSh0;+QLr_b2Hv;tC&*{;Xybo5l?H3P5PK_O$j{oxFF zw)e>-?09gW7~+~^ip+9E4nf=LG833-wV3`umpKe#aE>j()V}?nE%Qmp62qon3Q@CJ z85m|y?=xY>w*?gx_>5iKB}|!hn6`(QGxsq~x9w-*pZuXzaypL{a}LCED?P%NpV4F9 z0?j-#9r0FMAUh`;=<{wjcVcdZmS-(S%=o4tL0Yz7S7pwHD(6&UCNyn2-QXGv%l5R7 zEU@9q8Y_Z&AcLt8Kc9BMs~nuJ;72M=Kj6%acM&9L;o|gE7iMjU;clt~LkQws@DP0X z%(>i<*bG!>mc~=SfP#s!Yx^yAP;826fnsxl9+SfKV>-+w9-yiKHarZX!DBY1#U(|F zIi!sf&uzt95^WdoXHJKv1kQB4fjIdg)t}=5T?&BZY*Mq2kcy{{W@szqO(2npr2op{YhUq!QEGBdH$fEzaAj}OoUK4M0Gy4H5W z%E1fKA?}_&AAec`nU1s&@8M*^$`R|Pre`c;#y0~E$~8y}oW4xQn^Hllw<9*`P2aqV zuuqXzHZ<%ZXgb<@3qw$)`D~W&zFZ~-1`uXukYR9kC6v~|?!2&{S&_*FWB{nPg<&?3 z0U4P&sie%zHXX-VI6w!`z~ijb@62Q2*e-X1`4_ZYH$8-NI2>6Y@+wG~GX&d<(|rnA z`6rhjGTZ*@46_=u5y*?|GV^A|vM?}!Fbl|wgtrER0|~J%aQgZy%o2FoHsDOR-Qp_q zLTDTC?lop9JnF&5gHLA!J8%~FPyHLL3=AL)a-eHw5uqUfkO^BmSb89<>89&F!tcHV zZ<)=e?|Z~70m)Xk9uXIi+lwAE$3V`xfTa--4R&KmGAXI#!Aty|K8IJ#eh{~*etOpklb%!Vg=rh|j)&TD2Vh?BGlJKk*i z!I#X^5aoBj;`b}q^x|*KQeamp{pi;RyGq)EkWauGHC{tCewQq6oId{}v#7KYA&m~N zn9ZiIe#Zmq-sqp6P|xZIcH7G8MTKCuO~3z~h!Bf?0ShsK=XghqKyhL=efe{k zgA(2n46y)6*fze$uM+H2@ei=5VEasj@;RSj$|ruquN)i!>fd3$oc)mqUmAUa`BLx~ ze&t}(SNwuG=Gh1QjsbhM<|9mb!593dgO#&?g*j&KUuIc+Spbx4AVL21JAQ+~&hGgE zbH{FCf;{jGv$QFwY@V<8q#~bzfdPcs8Dtn-!NrO*p#%*|p%B-_{=^?jVAp;A3C%Me zvoEqh6Z9`)67+9aRIh%6-x_e}I=+SaD&W>HW{{6S80IT?UqUrAC|CG_CpGs-RDDzdW}DkBHZEkj|g`>`3DV{7Rk+=;A9|eNhqa()6a`fuynBF zKhZ7YbqOrE)>OdfIc*bJU_*-%Y%ByvnF6F)K0|AK?|Cfvre8qqgY9?bu`ol&IsXZ; z;A`qmFKA%Y-#$T*1=fJ!T1D9LGgq<1K?g4iby*0lZP?DD$MPB4_WKfxS2<{)Q-6DR z9E&{EcvE2(e8cIW2@C!0r-fPiq3Wju<2|An95@;wEH+T*JYGaNEOlI2CP5o_YbOv^ zjucammlIZwWcu#2cw-9ecF%JxAyBvfUPD-U=UNt4XgZiCfj1;Urh|t+`F62%K)w6O zlW@W;@?x=s9LV$Q>a`1VSQ!{V7<3?yYiUt_L8`t_W^oeU#f-2l!Pvch!yy(OrtMd< zS*I~g&&gx$g%tEB)A0r)CxC{*VRr`Mxd!7H_>IF-=UH^^<C<)mSva=;)nF-rmYD~t2!`19fNGX-sEg`P5e_1O(=5>SP18%A z2)YQlK$z=7Fv^jY7wjbH81(Y~S26w&1?9co5*ATt-V;56H;SiUXkyggzU&0cRcN^! zCx+JppmH3gB{H7}uMaTPb1lVhK6pTR?ot*fXmtHHBpm*|Ml7%;=+E2nDhE4f`UF81 z&h2d-EHj{fR>{H}Mxbl}9^Bi$HH!s$RLpdxF2ZdXq=Kye6pOf$b4F%yW*$)o%WX$W zf-h9@#`yLCH5Ps*@N$g@|C*nkWny3eVbF37XzlKuS(IN!pd}6Re*-sH=-2FH7{B4 zj(&p13XDO$dE|aCXqS(>Z-_Qg<8!!l6F0gC9z;d98#F)(Iw_q%k_3e!bkx!C4GX>% zhG3OuATPRd{?cV76n*oE&IkO#3hsLD`M?6*fOhi( z!AOI&qmb4WaDQPTb|Q!KJHc8Gelq;@-amK~KX?Jcbe+E}(AD_&f8b60ptVP}KUtu= zregl$bqK`lpK!B}{le=MP{2b^XXKoo`kMuM@POP`76J=gz!zA77g{E^X61u+B!Dnz zp3gHcB{MNk-#0OX&?r5`t+9V#;c(z5!4e4(#sWX^dJJOr`X4Z}wZ7ps8x+RJzQMxS z=L_C;DadT&>5sm!Sb(#Zb$vkZ6?O&&5C&x}&mw~7A%TK@JJMDrYc^I~i$kEZJ;=+f z*K)DqEB!!*W9;O1^DS_bQPeDg+f-lRcGY?GxO(hD2u^a%=`mB~4z(;Pz&jB5| z8SVf&ax*o6frEiz+XV*DO&QY<8n7xt66$SJypEkNV9shay~d0cx}a^oEzU53WytCJ zcC1|x!y7FKss?Xnm$PKeh3L4W%ZhKHce;ZfE954`=@mA39S(~2>0Gv~6Cvit`w(== z^!GljeGt|EOz>W01#*SO^!d81mJsF74DdP{WS z(;!eO@%|_eM#7@W8QqNS+K;Kx$*F?`y&p_Vz?J?)GP4DHjSl3DRiogVnasLul` z>A=@{)R}ut|C7vmX?hYLi`4Y@DXh?DZoeh|ggilm$#}Y!6{|TUA+I*W>sC;imkLq& zErb>CR8K$%>mqPxzVY>r-1Q6$3?K~Z%m*YUXQpK)>-%Mv5^C6jf+ihwo(7UPLwrEz zXxwo&O#l_>0wt#`zy*537EpnnumDt`$9aIxP)-eC5CENOt!rp#WWb2GcquMFsQvA0KyOhya_a#!3KbLk%43hWJJy&!Ld=4F

|0|N+y_Edxh>qAR<+_AyH5E7M{W(2y; zYxYZKWl+3KM>|#V%pz7oo3ghf9c{O2I^K2%$OfbX?WbpS<5iA08*uuom3Rwdu)#=| zNiA%^YcNPTxYq|MKxQl?=tucR zRi{p3U|;}YP@xhUtRI}1n@?z@0li}6>BL(iBAtIay{sR<`#=ZhAUZ0#>+lv(;Is_R zNk$W$4!mPzU;trIS`H_;S{c5wHjQ!mi4Clf@u-IfU$gcwGcbTKXgn%hH#ih`dWM`2 zf<7~QZVRg6MR#q-ZVyNB9Dq;H85tI?3SHXvdutIKKVvU$~m{r1RNuw|m+yv*;(vn1CwNIaagjK?NNnP-U%nbU0|N;2qj>9_5Zp}HoOs8?%u*bQSqQZ41~q9+=Q#lOnynPv z4Bz~`qWrQ<;uGZg-C(b2NyClsDJ@RSCfb0H9M$chD{MiS7sY2^5JoyB<|bz6;|wf* z^r8ZkORSeP?v;T%$}cl97t~%ME{RWv`f7(P+yL*)^u!#Zi<(n*S07AeU|;}YR9`j8 z!Hsmvgj`;R!%Y~zI=cfLTXFJm6TCC?iZc?6i4N@P?~a0FD_Q|=gkwrdW^ueDC^_N` zU$o$z{ACLFK}H4!5Jt^oX^L=jLrU{NH?3gtTN*QFO2nNCa+TpmIwj_1mF5uZ%IW&r zY!a+X8qHJ~Cg-z=I$?1M7KbdC-JHCIfq?;p1yPbCi|X`-{j3rWL=?Hmh6te;!mP$H zSwKKkjX1|l2c_fsC5_DL$YGFPN^~+r4pu%Chx|hr>6nz6k_DQG!tN*mjEZ>gK2}gg zd_n{6D#x7k%+#V{qNC=`F;)rtC5_Lt;3oLxmnLQ>XXKZZ5N*hXo#5=SSsQLhaAJOZ zNPaHSrRsE<9pLP+QU`8?OJY%cYH@sUVoqWr(d9dGU51)yw&}u6_9;y&%}q)y&OnPj zDR65COkjjGsL8{!q_IVBdi-%#QF|hi93N4)#gvIK1f1@ymo$bOz+LZ~ zn3I@07Jl&r+uRM4ej*pnHC-$9Kv<|U2R(=Q%i6(_Ytf$DWO zW4JTi6O;0b@`)9DZ8S2?V%^l?C(Q5EY=H`owxk;~ZM(3|X0OQ{rlxVg^xd5PIYl|+{g(4te%0d9gzerY1;&L!ePY)kKq zWBVBx7(iG6rRdajgd6FbpPrbKS)5Ud-C5Y0T=Lt%MUIgZ+z^+34|FflNIFlwu$!xL_(V{$TXMO9lR*vO0-~Fm$T#_*=AVdF{s@N#m&AK# zmXr|PbSONjWxbJsfdPb3-CGtg{oD=W`kwbW=FET2z`y{)sBS9>L^#bUu_!4qh4?ZS za+gFd1H%Ib1_o4Pmj)q>bu7uu&dx(O?3fFHtM+ zJrM|_L-LDC@`*3QZFWkuKVf2E0AY}!)BUcpa@a0uY>z}3=~85!*qqm#I<&={rjv6 ziU$xzO>Du52)6~L7U$=bmJr<{h9tJ>pN_E#)h}rbOhK3wToNCWk)NALbWYvRT>2U0 zMG!`FbF zHZd?TfG}$ROe+K7G~dLclFU3%oifdPb3{j8CRFxaa!FBP=5oVeto zw@=FMIWq$T2%|RL%yOp-o+Ym7w(3-q<5>m<1`tNgxhaJRhdJdW<|XR}Cnk}Qn(I}9 zv=%I5W?%qeR6o}jA&hn|%}h)py7HJl@h7W9#FEC`GK2}9d8K8UM7IV)6@}7nGBGfK zFls$fR5{(@0;?1;{didF0?~*(2C8dk)G$o{_?F0`cmD@g&_Kka8iwh2J`iU!;|;%_ z)l3WwAS{Ja(rPp^OuyI3DCM7V(eG)WU4Z<=g2C26&OwVazlqb@l8(Y1XaWOG4 zfUqQrK@-{-rt>#2$`EOgf_P_bAtM6=2#cZ^^tOXxdgBLHX=0+rTi5kh3KIhZ2#ceb zvbKw1`rRHzDI%TYs~SdVD@t#$d80YZ5EiTYwVqgGa)X;g=&oDi< zol%C!@uy_XZ+T z2GFo9YC+pF6UorTqRjMs?3HIdmeI9mJ>8SOF)}cKFskqTXCa%KoSI2=_wmZU=gOdA zRuD!ulXXdB?;M8d3J+ODhzhfsSKu(qnv3L+)RLUU?8Fk{TO9wMef45xVPF7ZWXCLN zDCi4I-lb_r@F{bMu2 zP{$(N(`!e$Z~V(DLQJS5 zpU#HbT;<<8eZfT{2f$*Vuu8-(X%sq$@Jmo;e!NprVqP-Qk+tz|Q^gAg1_lsDZMQKT zW|;2yib%J}zGRh%TheH91mPC&s8xJeYEA~xjzO+jQJYlU#~7y9u`!AhJIa6X1-N~X zbAn;|y%(%9#I#^vsT|zDfq{Vmgi)I}A5S5C<(dN;$SzAv$tQYzX`Rjzf0L8U3=ANQ zI*jt}G{R)ZltiMNV$&O6gZ=mSJj3*PuUW;2@t;>oR1YIF0|N-7`fu)agew9P^V0J& zi%LpC+s25i*Fx8nOn>~HRg`r}$H)-KAjinSfLd(TzeSkpky@0SUz|xo-8H@U2RLKBe8({T{!vD8BEvs`UxUMz zk%0k(Q5)bEpApUpPRuLGk9Wz>&CE+DvP@*N3<9+>rWbB!6=7Y{c;pMi^z|`}qC`6D z+QX|2a~K&IKo~X4Px^{*mTziBW^#VKb0+9=2IBHtz37S446uDRsP$m=cZA9ArIm@q zPfvk73ThjJFlr#?|3H`ts#fAB?{4KHwklZn2t04*@DpK%OKM3`KJf!o(|K-zTWCCg zr$4;KDnfJ%E$GC}Z%3FI7(f`caTNhJNp!N$JuV`PN@TMXP+EJ142+WlA1V`RPIv7# zIgoom7`0c`&kQn0c>1o}tUSc@&yG%t>H(Po!l))KV}qC!O{7T=_J4f}G6jU?Q2e%+ z6JnCtT~BsbT~;ibA`w8hVug&mhPt}#FuA#eGcyB2J%~UJMR9wCp?;YKndw+ZZ?F#DAh-5WQ~qKngrP2}d1a~4PMXphz63&R zp?m&-lipu9#_4%4i0^6EUSI_+U;gHau-UJ)l;}Rj^q%kFF*05sgnsA5ykuNUPBE7+ zr6q~j$0e~0OCl#p)QB$& zLm28_l$w{Af<60y?nlKKzv=r8Zp=A`Bg_cOFHS5Xer$94`7dB2{Gt#>I42e*CKEpm zH(l>7D`>S|Xf(nI-_)W^93H_EI@1e3f!Ca$iJ9K}iMY{uX>RWnP%Z*t)VBP+c*f}o z|5+u88F@OqWA*G03=9k)j2bO@$xx?nps?ynFH#^5?5Me z#~B4n?qp$L0AbYepR<{a(*xEKpDRIQWA#fKujC=z1L`>B$2%qyzXZp4mivhdYzzz_ zj9OYBDnOX)ms%blnO}sN<4thvx>%ba^l}vg0|N-77GHPD8K-Z!O61_W%qLa}$0d#D zDv+E4T8Ec`Jv(7Zg`hkNuB9E8H2$ta7~@`=n39^4Us`~55*gbZ@^t>^;Pia5db;*= zR%v1yX;!lgL+&#&Fn};>T%WH;I3+kazbLghsj|2t8GVy?s*Wbbs8)LXGjQBb zo;tny8LK2wTKX@8%ivGb5i#wNn3I{7SV3&eO!s>LuC5QyW1Rk1fKh_TmQr+Z!2~8& z1_lsD&C*Q^rvLv%TuaH~Y!qugBLf2nqZ)El$w)SMRaDKx)8j`f9o2?sr%T7O9FHLgQp@k zuSM7inm0-<%S=fna-_>L2zf&&Y7KW{Bja>|(?q5%A4WFN#vtYG2)B47mXR{}z`%tv#x6z{ z1_lsDuFmV1G%h@ZFf$}GtCWNQsAgxsbBdXP0fbT0_v>Q_LtRsH^Yd_w*5Ny1?5)N>1($qwSEg4#C2pDII-Mmrrh<%bA%fPCgc-@i)9Nol3=ANQ8a`?draOKiGAGu40WYxEeTZ;|Pi8LB z&6AXsm9t8i85lqqH5v9jntt&Kab@-FJ1cE(u`w`!FmeuA(&+OH;VkEj%;ZF3$K)-8 ze9IQ{t1>d=GN>}5?_kJ(i!c>j1Qrz$zef(T+!eCg6*X<&f5$j|{WT(MfZUJZmLcB< zgi}H?O7l`ui{hOUNf>l|$tq#Dr18vWgfXsp#kf0cSX!9V7cjDcHs^}}K$zi_m_fo` z$OqrRi$ghnBMblqYf&obm;&Ou6{=oWUk5WXFn};>5@2Uyn)Zjt^*`$$gBOe}W@dtq zAUftHXXFKwUH9Hz$Q!D(^F5Wnchd)R=iA%{1LWmr;b+v3Hv*;B=d* zh;WNjeqwxBW-;-5?2*$OYPpo8%rre&Ni;_zS zZMHyO_8c@9|)8m-gh?=9GTK#!tIWq$T2%{PjtBT^RfW(|!*q9>W zAw{bb0p=U0FJ@sAwp-FDuZdz(NKt+c@%wJyGqXuBFKLvT&c(teMNIE{>MOR(M;RCx zKp3^|tkgqshf87^jy=U#igRARPX?_F(?2n>2}Lbw?9fLsDY!Dfoanm!gvcGo84L^z zAdEVB7;Z2gG2=4>0|N-72JTlQlpt|V1mF5VTtTv_#Vhs#vp5681!e{Y)Y`$wglW2>6%(=5 z1M;DusM$5Zf@%7GQzi*w3lGrIB0+B*H`y>TID&JgKC%7trPJAuEMa0`0AbY5+-Do6 z=?ff~#K^novbI!=mOiIit#y3~X$B23$%STBz3CksoJZ?}k zLNYRQlW=T>#H`+?zvBm==kgk+JuEXduOyR%LoudLkOudjPrE}M5Sf@q!pw|WR*ctq z76t|oMwIWMA&k==Py;8B}QIo3xcF=uasD9^+{JiwSOyZZPsXvPOKc9ht z0ff2W2?*q-4gOFwy%Ur09)iG&8c7ABY@jKh$pKL9PKg;siNsH`PQS50p-!Al!czcVl}h=2%GL#1P;3vjX#wK)m-kZ{yw z85Ik4Sx9OI_~dZnoRy-=dgB=r1H&^WhI+JpiN&c<6T@;6Q!>l)i%ar}E>x@pUo8T~ zDhP9;M8o0?sHy(wWt23&^PK`Xz$xu?HdJ>=VrD@q(feZUBiBoU_H%+TYR=)$gBs|P zm`rHByc*)Xso3D%LTi{A7(f^`GOhBbPv9XgGS6Rce+X*rfiP-h>J>v>6_i<-n36$k zRi*XBVPz*H14Abx!}JOTHeQw`jX#Q~8;B9-oOA9quRv3kAdDJFCrhEuam*!Q$~@uZ zl^EzzPz>&^P+==l>E7VNy((**&*BUy>9+L*8Y!F6G z-FG+Y5wID=xDhXka-d7Ud=4t&36Wt*%)UzF%WvV7SIK-BO*6&wfc` zZa>r{&~X{rrB!*UB-E_a&&h#n_P$9_L!2@}>4E6-d%7(bIEmU#h3fY%P0k>psnVj! zyY~$P0|N-7M*fj$P!od_39XbtIg0@Ks8ZB;`#K$FBI5K?;wnGQ0+|R<6oRk-N-bqO zlZnA``ep$(;hiODca#XBXI5Wf?poY#dNRQiE1YHGN@3TkLDXbW66_uo3#0|N-7=IW_ypoaQoCg&HEFz71>@u|UjsD8(kRHCO*aW`6iz>IUrAmT7RaKZqk z3r$f^&(BN@3?PhJZ76Sqx-U2}J0mfN_#Qw=ql9}L69WSXqo$46El?vJbqY&}&kNHZ zLb`4Lw?VZBROaWUS0)nQOA>!HXR{Ft0|N-7CXIjFp=Nre7L^t!;vO2svfXZ;3b@r! zu?K2|OKEXNVqOx_1Lo7`@Pi9f-F;94obz+?bBRAR%QABNM=nMN1`tL~n_2szCVGR` zexV;A23~duCIY+}QM*dd8h6OS4u3`+E8KNpdYlv+afesgLgI_{5Y!cp#Tn^|NyIO& zn%*@z$e`Js`I{P>lpF&Ib>)cqf9K30+f3c>HtM z;-rH?ObiSlj9Q{@ILgG}SPyE;c;uH6y|9P5eY4FACI$u&Mm5j%1k}?`iP=QAY4e-Y zr}~2KN&{ikoLz7lYMysSVqQum@tam>y^^@{gNcCwgi*&A_nn&_C_~)%;;HuPc+ku% z2&2XX()ODjQ8md)Wm>{y!_nwfYdyk9ZJmO9HF6f`7YE9-^66%3-c%O z0TS<-7#KhpHTv})!p%!hOu;v<$jBszGK$v7%_d>7q%rvk)PTUm5)!(P3pv2WxcyV8 zZs)|DqOP zt{bPX69Ccgfk{!sLl9 zYe5_IKp53Ys_ak`BU6h~%kY+!^(bkmJ2)?7Ap-*g2&1+N^tqr$dMB2UG*sUa>`dvzsh##$7_^VEASPwe7h3F~UL(~1%g6`V_Vbm$xLs0X;#yKYz zq{fG(7NrpG#ew?Jpf2?D^KlzQLF+Y{(NA&QCkJsU*yP}n#Jn8hSIag1Qiz((%D@1^ zsMVyb62w#!u(7_0DXE#bk0{01W7Mb#URA)PF@3Hkadqwb8uQKf7#SEq7_}AYqXTgX z*dfk|d5Odyx4WHhZ|+V;hI)pbjOYtHi}jF9bxSPDCmaD-nD)9I;CU8nwWow$XU{TrD=@b^(A+lV@4dxX^66w>FVl?m!Np&o^hD ze%_f`l32&pX|PE|E@^bOK=PwoVk!v%7d~??Hz=WjFlrRLT1|hi!A8^(EU?@Pq7iK} zP>$7fU}kVEEiNfa%pqYxL&VNm1s%)`3?Mw6+k}m$eo134ib;OK;ly^%`qS#J&SYj_ z0AbXmVdKJ#R(CL44*ofMQg`9{`{d6!4**U?LDS5;f z&aR)HMZIPYVqkd9jDAAPKk2fGPK~B_T11*nkNJDmqb7@ggCefww^gdlS(CtZEvyjbjElnn2KnCOtmL-iA zIn&qb5xHAut|7Rn&Mla}(~ym*v$5=_?iF%nWMBYc)DX)oL3X-NW?o7v36tHRqCo;w zE`Ts2&200d?oYr{b9_+u7^Iq`;?RsBLf2nqm~gi z)yUoqNG&2hwdEV%3YzY$&nCjMq;Y%A^k{wJR&XM_1$97vM?JDz!c&WhZdAh({&aQ| zHUaA;jYf^gCOLxc4#YO;1M0V-4d{Rt2G+lIWNc+-a4Jfy%FH3Um5F@z9cnY!31OIP zA`za7fVOGUzj}8rVq{^G(40 z`;cC^8KlJ2bWi}BzI8P1XJ!C38&mL~KaboMn|{w6+@&rCDBvCIX5_I$D|X>^-4{l6J;wJq{KG}P=UzHoY=8F6hcs%_e>@y>1hqWEeXGLl}EK1KMS6r7Ph^`lXhq<(KBAK<;WKF5r>(5}@XJ ziH&fBL3ty!2s|I^$V|lPL&zH`P>Wd69n91F_b`hQ+lsz#0Zv#Cb}=(JgKkG8&QqYq zE)285QxmAs+qIXO!8s!{Cza^JmnMgkt1_lsDE$UD0Wu89qIJ2lDajrt%2#h+7 zmomNIlDK&qo9>x%psQ>_m>upj(8|({$C(+NgG0=mL6_SS=OA{Od9z|!7#Kj9g+XF^ zy%ig0{gTF&r$!B0-0AW~(7(f^?It5BT#ZM7#F(halH?)>F-SMJrx+5ewG@ijt&?amG z)BvR){rX@7%$GFYK{CLCpc9}5Oz*J=2giixaNBhajfmBaeA_Z=Vd4G)VjlSJW{}!)SV<8#u;!KfrYp9XfrY zW|kn2fG}$4>_eEQO+;wJ2BfpDrfdKi2EwSJQ}Pk+JY6$lLkD->*8Bu9E;Pg$WS9mq z4Yn5TSt_vPcoV80l()@6CJXmH~?e-(f*nK&JLWl9lyXe>k@7I z^g0JN3DYHw-w>LKb@=puZeV+teMQ(ybcr@y&<(uCA^ICavmx;X(j7?QF7zFuJ2Wq| zEVZbZ_&K?w65D=*k`oA{CaDupBSFP0{>lbr$;Lrfuy<;IKpX^$KoSb)1$Jx_W=k54 ze?oLemF5t=E^7LEH*l-v2~;o0-9(3Di{xfbSlXNU3t~CQ=|q<_;GS>&TSwpD%nYuj zMfnB9_YS7k7ZiXdAVC;))~*j>7$A(Pr^#-p>_`%0Ay+M~ngvdjgCjH^j&Szp^0AbX= zSd;Md`2oc3;SNijboo9L0|N-74rAMh!MzifpOc=SUWB=#gc--;Ab;(wDILsWkSP|_ z4ri+5^o9OJjujV%gU75bW#KMyO3eYegXp2+>?Jze?AaI?Ko~U@CCE>o7)s;{5Rg0S zmo&amg}Wm-u_!SsmH3-QGnRTqFJNY10AbXG$gcr6)Hg8)_e^~~`f&X5uTyRXvM?}! zFshMXwc$nvBo-0BPyOkMh~*C%85lqqH7)cQuuNz4A}-I}pHp_em63q~gi%Lhwj06S z<(QX}Uqt-m@~^AcF3e$NVDJVJsAW`(3EWVh%;F^C$D^j#1+qy*Eon@*f*TN8m64ub zl#j7+3Rg0Z%@iz!?4v=Spg&~8GX0_(i!iZcM0+E^b;l!nxLZOpi%8jktQZV7pw$U( zKmh3c5u!87^!vWx0(-tI+<>UW^rBRv?`N30W#046%nS@5j9MBUac7yn;UWvsM{mf5 zflI?f-YnA}&LlnvC-{IH%GLpJ4}>Lx4#fZu`4Q9po5lT8{{|}q0|=w0F|!c3nJ%SC zcy=scE@{2%&n6MJq%kxKZh~)S9^Ng+D66WXvX#RcnHd;B7}ZUOW2gBNx4{^>3`8}f zI}z?Guhb$E4qbq6UIDH2LCxfX8E`X6+`sbh;A_?%W(EcjMs?@9tmzIx#Cf*ogy;p( zxjZ0@S}Hc?!5tQypGN%5>6xVOMxf&umM~3!=EufYzob#T5N=XfW=>uv@k;^4gC}l2 z$i%<^!l+(kE`girlv+em64MU=ZxQ7#hnoPZol5eF-r+fYLo|3kRkI3if>UWqVgU(L zWYcv6!MU%X7H&ikzN3@TmaR=#`Stu%CI$u&My+`=8sP>yl_qB-f-XG4)mFpIeFY)l z17O^zcZU!+Hf?LWMC=F)0|N-7IwZ9n?hyCPq#{sNP4ueOLb2KQicb zrptzc+aIsiu}nAYVj*@B1n%5fx)tsY=Zwta%sk@vw0!z?T6p>sFYqFWjXS3Q@glBM z_uyaiQ`qGtsFk43Zn#^#GmD6?BJBP>oj04AfnhfDboCH$C1}47Zc=z+QE_59u`!0b zIih$7Zlq6sUJ9P3JjTiUy`Yd;(zyHt+yvkJyhP&f^Fuy&33V}q$62_M{>6B2b3{At z23pV>UV!Tl$WKYnFUllz@(0p3EdzgWtr~d=ZU!++%#oKhtZqnFDP&+^0AbYmlc4J? z3~q_ZCHVx_*486!h(nG$CX{JXmK!V#?oQ;S0aRDj-vgPWi!|MtMeq&^(3Br&t`me& z=R5yDVPSChC3?PddSfh`gz=Kb)lb3Nh@W%>YcyZd82JpWk@&enkkh9t*0YHiEoo$b z4%STc@IGvkatlZw$upcA;=m)FX)jn9K*tMZlW@Aw^nY>SWV!w|3xfyov&qPds8J(5 z<_!yjXL2ejYd#pJ*KK7LH+}2a_nw8pGcP4GF^~B9<@*V25)Mlm&m*+@CRXN`5Pv!S z4)4|Hr+;8#1Krhn?E~Ba-l;|DrKvf@SIj#%MXdqtp#)*nhS1WFa8rE~b5b(PQn3yv zieOtgJY6pt+#_iF1UDlnwKOjiPl1Zo9-nTQ1YYYH{CT=>5*twmOmFF(acn;W0|N-7 zu9pe;GTlFcxYc`!ty%e?BV0fjwHS{13ipd|Vg}JIO(a)MUv-3)*M3Q(+BdjK&iT3d zMMQ4^QpvHs1deo;C5<}Yr~4-oxo)&40o(xm{T*R%Mq+wC*7(F4oe$%|+3nU3gaP@< z#Op^s#)}1|&|dSCg~5}!^SfBV`yi&DNd`M*A0sP+XK_(tD$%WIRix8|Q8T{*8!LlX zVs0YQ^`ft35Yv}+=~o#T7(f_xkYH?E}7K_wv{ zD+Acg(-Uog!4IC9)#aJ19iLaENWt>U|Ekpxh)O49B4mQZ#m-q!wVcrc>9E4aH7(f`Y zXb-d=AyS%^!7s5aF^lNpX8M72u!mO5voiQa5!tl&dZSO81Rw1Is^HLQC%P-AMCAvs!_)&Ie3IhWJ2qTYeS}$o7G(;F0keEY!|984g0k|FV z#&CLk9&y7Ar<8VN-eO>20AWH7yZZmJ)Ny@(J7Q(sc|B3?Pg;^Sa&) zVWxLxQD#YIZX)sNu&d@y==6nIY$B0M8dsVlOma)iPRvgux>Q3hpHN%8-4@f=l@d9K zIiVPwEdE$eUsFun3D&SE1jQg~vQV;}E|^JV9b;Dt&d+~r5&jQP%*i2siq+&oKSW)|-90sSn+mv`mf@h~zlfHAy`2Gu#69S}x37LYLG@!2x*FarYv z2&1;bS)EuJ>S4uxWMToa2|bTRvJ!Os0SKe+-Q#sexDj;KT)Z#j<}%zSqaTF;Dk4~y zG=6nvo$lz&Doo`0*vQ2yYC4p0MRrj}9tkJE9x`6AClGW-ItZhhYVC$F)jcscDU@H^MExiA9B_sl~+KEortrxVnvjfdPb3z4*d= zdSVW72W_4~O82OlbDIysZ6QU(UsKxndPgqkT!8hUh7_ui`+X5c`el|9-J?Y=$WZHy zEq(|SgA;S}QEF}(2GC(XIF{>7cgP2)uwH+J3GStdL=VEddHxfLV`N|eVbst!3`Ce1 zoS2EPU#5*V2GRJqoC^|m=$8du51P(cKx7N7rwHt`i@^wYIOUh7CuZi6bjRlX<^}Pf zv<1Sb@%SPHVRCq4Hnw<_#CqsXfYpJX=?gO1MC_L|ZV5#g5|W>no>-DtKz#OgECKuR zO&G!u=L`}q(|vXD)_Kr~3kah|-?wmtks*m0nYfz^7|W9)FL~F1LJNdZ$Ab<>APfcF znVFcAoR~-aic#ci8W0Ws7*K^bEfQg}V`*|WDFcd;rc!3#85kHq7`5pB96NnuE^%w0 z5Yr?K45alvhHo8% zt5_LAgNg3jPhV354*dxbZO}F%v5|m$-5lypg-7*ZXW-v93+pt4lPGwg(oW<#b2Bpo z0|=uwVHw)N2Kr_uXJn=mKTL>x10kw`C%V7}I_9L7)`Kn$A=b|-3hl-}m>C#A7_|X) ztq*J>WL6_lH@GCR2y4B9QLWU2vM2I2@2D=7oD4SCH@`HmgoKMXkT1VRjhuq%U;`bC zGOP0Q5<^3XYr&-C$Tsi zr9FhVB>4kL%V!pYHDk1;@aZksR((>KiGcxx`B8df3zmRQ1NluC8nyV63J>xu?({v? z;2iyD8Q2Vu#PY;U+&x6Jh7`CIsbA74vx1cYx}gSNIS(4{1EnLQiB1RJF)}cKFlxzs zVg)NhIPpW&;B|ej(1m@d6A+(Qu`-0~28ZGc2$XP;tq1S!*t?FE0sr0%RyL47(wNei Prk!M9$Xd_Jz`y_iOud@B diff --git a/src/time/tzdata/zipdata.go b/src/time/tzdata/zipdata.go index 60c0784008..09ca148770 100644 --- a/src/time/tzdata/zipdata.go +++ b/src/time/tzdata/zipdata.go @@ -16,375 +16,454 @@ package tzdata -const zipdata = "PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x1c\x00Africa/UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00" + - "\x04\xe8\x03\x00\x00PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\x0e\x00\x1c\x00Africa/NairobiUT\t\x00\x03\x15\xac\x0e`\x15\xac" + - "\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" + - "\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\x14\xff\xff\xff\xff\x8b\xff\xd1\xfc" + - "\xff\xff\xff\xff\xb1\xee\xdaX\xff\xff\xff\xff\xb4\xc7\xe0\xd0\xff\xff\xff\xff\xc1\xed\xadX\xff\xff\xff\xff\xcclz\xd4\x01\x02\x01\x03\x02\x00\x00\"\x84\x00\x00\x00\x00#(\x00\x04\x00\x00*0\x00\n\x00\x00&\xac\x00" + - "\x0eLMT\x00+0230\x00EAT\x00+0245\x00\nEAT-3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\x0f\x00\x1c\x00Af" + - "rica/FreetownUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x92\xe6\x92H\x01\xff\xff\xfc8\x00\x00\x00\x00\x00\x00\x00\x04LMT\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00" + - "\x00\xf1c9R\x9f\x1b\xeb\xdd2\x02\x00\x002\x02\x00\x00\f\x00\x1c\x00Africa/CeutaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00" + - "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00\x05\x00\x00\x00\x16\xff\xff\xff\xff~6\xb5\x00\xff\xff\xff\xff\x9e\xd6up\xff\xff\xff\xff\x9f\xa1n`" + - "\xff\xff\xff\xff\xaa\x05\xefp\xff\xff\xff\xff\xaa\xe7n\x00\xff\xff\xff\xff\xadɧ\xf0\xff\xff\xff\xff\xae\xa72\x00\xff\xff\xff\xff\xaf\xa0Op\xff\xff\xff\xff\xb0\x87\x14\x00\xff\xff\xff\xff\xb1\x89z\x00\xff\xff\xff\xff" + - "\xb2p0\x80\xff\xff\xff\xff\xfb%r@\xff\xff\xff\xff\xfb\xc2\xefp\x00\x00\x00\x00\bk\x84\x80\x00\x00\x00\x00\b\xc6m\xf0\x00\x00\x00\x00\v\xe8\f\x00\x00\x00\x00\x00\faG\xf0\x00\x00\x00\x00\r\xc9?\x80" + - "\x00\x00\x00\x00\x0e\x8e\xf2p\x00\x00\x00\x00\x0f\xd3Q\x80\x00\x00\x00\x00\x10'\xa3p\x00\x00\x00\x00\x1a\xb7\xa6\x00\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00" + - "!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#\xa8^`\x00\x00\x00\x00?sWP\x00\x00\x00\x00@\x91z\xe0\x00\x00\x00\x00A\\s\xd0\x00\x00\x00\x00Bq\\\xe0" + - "\x00\x00\x00\x00C\xe0\x00\x00\x00\x00E\x12\xfdP\x00\x00\x00\x00F1 \xe0\x00\x00\x00\x00F\xe0jP\x00\x00\x00\x00H\x11\x02\xe0\x00\x00\x00\x00H\xb7\x11\xd0\x00\x00\x00\x00" + - "I\xf0\xe4\xe0\x00\x00\x00\x00J\x8d\xb9P\x00\x00\x00\x00K\xda\x01`\x00\x00\x00\x00La\xbd\xd0\x00\x00\x00\x00L\x89X\xe0\x00\x00\x00\x00L\xa4\xfaP\x00\x00\x00\x00Su8\xe0\x00\x00\x00\x00S\xac\x89\xd0" + - "\x00\x00\x00\x00Sڼ`\x00\x00\x00\x00T$\x82P\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\x1dU\x00\x00\x00\x00*0\x01\x04\x00\x00\x1c \x00\tLMT\x00EEST\x00EET\x00\nEET-2" + - "\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RV\xadD\xef\xca\x01\x00\x00\xca\x01\x00\x00\x0f\x00\x1c\x00Africa/KhartoumUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`u" + - "x\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00" + - "\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00#\x00\x00\x00\x04\x00\x00\x00\x11\xff\xff\xff\xff\xb6\xa3\xda\x00\x00\x00\x00" + - "\x00\x00\x9e\x17\xe0\x00\x00\x00\x00\x01z4P\x00\x00\x00\x00\x02}\xf9\xe0\x00\x00\x00\x00\x03[g\xd0\x00\x00\x00\x00\x04`~\xe0\x00\x00\x00\x00\x05=\xec\xd0\x00\x00\x00\x00\x06@`\xe0\x00\x00\x00\x00\a\x1f " + - "P\x00\x00\x00\x00\b B\xe0\x00\x00\x00\x00\t\x00S\xd0\x00\x00\x00\x00\n\x00$\xe0\x00\x00\x00\x00\n\xe1\x87P\x00\x00\x00\x00\v\xe0\x06\xe0\x00\x00\x00\x00\f\xc4\fP\x00\x00\x00\x00\r\xbf\xe8\xe0\x00\x00\x00" + - "\x00\x0e\xa5?\xd0\x00\x00\x00\x00\x0f\xa9\x05`\x00\x00\x00\x00\x10\x86sP\x00\x00\x00\x00\x11\x88\xe7`\x00\x00\x00\x00\x12g\xa6\xd0\x00\x00\x00\x00\x13h\xc9`\x00\x00\x00\x00\x14J+\xd0\x00\x00\x00\x00\x15H\xab" + - "`\x00\x00\x00\x00\x16+_P\x00\x00\x00\x00\x17(\x8d`\x00\x00\x00\x00\x18\f\x92\xd0\x00\x00\x00\x00\x19\bo`\x00\x00\x00\x00\x19\xed\xc6P\x00\x00\x00\x00\x1a\xf1\x8b\xe0\x00\x00\x00\x00\x1b\xd0KP\x00\x00\x00" + - "\x00\x1c\xd1m\xe0\x00\x00\x00\x00\x1d\xb1~\xd0\x00\x00\x00\x008\x80E \x00\x00\x00\x00Y\xf8\xe4P\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x03\x02\x00\x00\x1e\x80\x00\x00\x00\x00*0\x01\x04\x00\x00\x1c \x00\t\x00\x00*0\x00\rLMT\x00CAST\x00CAT\x00EAT\x00\nCAT-2\nPK\x03\x04\n\x00\x00\x00" + - "\x00\x00\xf1c9R\xcc\fTξ\x00\x00\x00\xbe\x00\x00\x00\x0e\x00\x1c\x00Africa/MbabaneUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04" + - "\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\t\xff\xff\xff\xffm{A@\xff\xff\xff\xff\x82F\xcfh\xff\xff\xff\xff\xcc" + - "\xae\x8c\x80\xff\xff\xff\xff͞op\xff\xff\xff\xffΎn\x80\xff\xff\xff\xff\xcf~Qp\x01\x03\x02\x03\x02\x03\x00\x00\x1a@\x00\x00\x00\x00\x15\x18\x00\x04\x00\x00*0\x01\x04\x00\x00\x1c \x00\x04LMT" + - "\x00SAST\x00\nSAST-2\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R)\xae\x8eo&\a\x00\x00&\a\x00\x00\x0f\x00\x1c\x00Africa/El_AaiunU" + - "T\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xba\x00\x00\x00\x06\x00\x00" + - "\x00\x10\xff\xff\xff\xff\xbcH\xf0\xe0\x00\x00\x00\x00\vѰ\x90\x00\x00\x00\x00\v\xe8\f\x00\x00\x00\x00\x00\faG\xf0\x00\x00\x00\x00\r\xc9?\x80\x00\x00\x00\x00\x0e\x8e\xf2p\x00\x00\x00\x00\x0f\xd3Q\x80\x00\x00" + - "\x00\x00\x10'\xa3p\x00\x00\x00\x00HA\xe6\x80\x00\x00\x00\x00H\xbb\"p\x00\x00\x00\x00J#\x1a\x00\x00\x00\x00\x00J\x8d\xd5p\x00\x00\x00\x00K\xdc\xc0\x80\x00\x00\x00\x00L]\xe5p\x00\x00\x00\x00M\x97" + - "\xb8\x80\x00\x00\x00\x00N4\x8c\xf0\x00\x00\x00\x00O\x9c\xa0\xa0\x00\x00\x00\x00P\b\xbb\xa0\x00\x00\x00\x00P1\x9a \x00\x00\x00\x00Pg\xa7\xa0\x00\x00\x00\x00Q|\x82\xa0\x00\x00\x00\x00Q\xd8ˠ\x00\x00" + - "\x00\x00R\x05\x9e\xa0\x00\x00\x00\x00Rls\xa0\x00\x00\x00\x00S7z\xa0\x00\x00\x00\x00S\xae!\xa0\x00\x00\x00\x00S\xdcF \x00\x00\x00\x00TLU\xa0\x00\x00\x00\x00U\x17\\\xa0\x00\x00\x00\x00U|" + - "\xe0 \x00\x00\x00\x00U\xab\x04\xa0\x00\x00\x00\x00V,7\xa0\x00\x00\x00\x00V\xf7>\xa0\x00\x00\x00\x00WS\x87\xa0\x00\x00\x00\x00W\x81\xac \x00\x00\x00\x00X\x15T \x00\x00\x00\x00X\xd7 \xa0\x00\x00" + - "\x00\x00Y \xf4\xa0\x00\x00\x00\x00YXS\xa0\x00\x00\x00\x00Y\xf56 \x00\x00\x00\x00Z\xb7\x02\xa0\x00\x00\x00\x00Z\xf7\x9c \x00\x00\x00\x00[%\xc0\xa0\x00\x00\x00\x00[\xd5\x18 \x00\x00\x00\x00\\\xce" + - "C\xa0\x00\x00\x00\x00\\\xfch \x00\x00\x00\x00^\x9b\xb0\xa0\x00\x00\x00\x00^\xd3\x0f\xa0\x00\x00\x00\x00`rX \x00\x00\x00\x00`\xa0|\xa0\x00\x00\x00\x00b?\xc5 \x00\x00\x00\x00bw$ \x00\x00" + - "\x00\x00d\x16l\xa0\x00\x00\x00\x00dMˠ\x00\x00\x00\x00e\xed\x14 \x00\x00\x00\x00f\x1b8\xa0\x00\x00\x00\x00g\xba\x81 \x00\x00\x00\x00g\xf1\xe0 \x00\x00\x00\x00i\x91(\xa0\x00\x00\x00\x00i\xbf" + - "M \x00\x00\x00\x00kg\xd0 \x00\x00\x00\x00k\x95\xf4\xa0\x00\x00\x00\x00m5= \x00\x00\x00\x00ml\x9c \x00\x00\x00\x00o\v\xe4\xa0\x00\x00\x00\x00o:\t \x00\x00\x00\x00p\xd9Q\xa0\x00\x00" + - "\x00\x00q\x10\xb0\xa0\x00\x00\x00\x00r\xaf\xf9 \x00\x00\x00\x00r\xe7X \x00\x00\x00\x00t\x86\xa0\xa0\x00\x00\x00\x00t\xb4\xc5 \x00\x00\x00\x00vT\r\xa0\x00\x00\x00\x00v\x8bl\xa0\x00\x00\x00\x00x*" + - "\xb5 \x00\x00\x00\x00xX٠\x00\x00\x00\x00y\xf8\" \x00\x00\x00\x00z/\x81 \x00\x00\x00\x00{\xceɠ\x00\x00\x00\x00|\x06(\xa0\x00\x00\x00\x00}\xa5q \x00\x00\x00\x00}ӕ\xa0\x00\x00" + - "\x00\x00\u007fr\xde \x00\x00\x00\x00\u007f\xaa= \x00\x00\x00\x00\x81I\x85\xa0\x00\x00\x00\x00\x81\x80\xe4\xa0\x00\x00\x00\x00\x83 - \x00\x00\x00\x00\x83NQ\xa0\x00\x00\x00\x00\x84\xed\x9a \x00\x00\x00\x00\x85$" + - "\xf9 \x00\x00\x00\x00\x86\xc4A\xa0\x00\x00\x00\x00\x86\xf2f \x00\x00\x00\x00\x88\x91\xae\xa0\x00\x00\x00\x00\x88\xc9\r\xa0\x00\x00\x00\x00\x8ahV \x00\x00\x00\x00\x8a\x9f\xb5 \x00\x00\x00\x00\x8c>\xfd\xa0\x00\x00" + - "\x00\x00\x8cm\" \x00\x00\x00\x00\x8e\fj\xa0\x00\x00\x00\x00\x8eCɠ\x00\x00\x00\x00\x8f\xe3\x12 \x00\x00\x00\x00\x90\x1aq \x00\x00\x00\x00\x91\xb9\xb9\xa0\x00\x00\x00\x00\x91\xe7\xde \x00\x00\x00\x00\x93\x87" + - "&\xa0\x00\x00\x00\x00\x93\xbe\x85\xa0\x00\x00\x00\x00\x95]\xce \x00\x00\x00\x00\x95\x8b\xf2\xa0\x00\x00\x00\x00\x97+; \x00\x00\x00\x00\x97b\x9a \x00\x00\x00\x00\x99\x01\xe2\xa0\x00\x00\x00\x00\x999A\xa0\x00\x00" + - "\x00\x00\x9a؊ \x00\x00\x00\x00\x9b\x06\xae\xa0\x00\x00\x00\x00\x9c\xa5\xf7 \x00\x00\x00\x00\x9c\xddV \x00\x00\x00\x00\x9e|\x9e\xa0\x00\x00\x00\x00\x9e\xb3\xfd\xa0\x00\x00\x00\x00\xa0SF \x00\x00\x00\x00\xa0\x81" + - "j\xa0\x00\x00\x00\x00\xa2 \xb3 \x00\x00\x00\x00\xa2X\x12 \x00\x00\x00\x00\xa3\xf7Z\xa0\x00\x00\x00\x00\xa4%\u007f \x00\x00\x00\x00\xa5\xc4Ǡ\x00\x00\x00\x00\xa5\xfc&\xa0\x00\x00\x00\x00\xa7\x9bo \x00\x00" + - "\x00\x00\xa7\xd2\xce \x00\x00\x00\x00\xa9r\x16\xa0\x00\x00\x00\x00\xa9\xa0; \x00\x00\x00\x00\xab?\x83\xa0\x00\x00\x00\x00\xabv\xe2\xa0\x00\x00\x00\x00\xad\x16+ \x00\x00\x00\x00\xadM\x8a \x00\x00\x00\x00\xae\xec" + - "Ҡ\x00\x00\x00\x00\xaf\x1a\xf7 \x00\x00\x00\x00\xb0\xba?\xa0\x00\x00\x00\x00\xb0\xf1\x9e\xa0\x00\x00\x00\x00\xb2\x90\xe7 \x00\x00\x00\x00\xb2\xbf\v\xa0\x00\x00\x00\x00\xb4^T \x00\x00\x00\x00\xb4\x95\xb3 \x00\x00" + - "\x00\x00\xb64\xfb\xa0\x00\x00\x00\x00\xb6lZ\xa0\x00\x00\x00\x00\xb8\v\xa3 \x00\x00\x00\x00\xb89Ǡ\x00\x00\x00\x00\xb9\xd9\x10 \x00\x00\x00\x00\xba\x10o \x00\x00\x00\x00\xbb\xaf\xb7\xa0\x00\x00\x00\x00\xbb\xe7" + - "\x16\xa0\x00\x00\x00\x00\xbd\x86_ \x00\x00\x00\x00\xbd\xb4\x83\xa0\x00\x00\x00\x00\xbfS\xcc \x00\x00\x00\x00\xbf\x8b+ \x00\x00\x00\x00\xc1*s\xa0\x00\x00\x00\x00\xc1X\x98 \x00\x00\x00\x00\xc2\xf7\xe0\xa0\x00\x00" + - "\x00\x00\xc3/?\xa0\x00\x00\x00\x00\xc4Έ \x00\x00\x00\x00\xc5\x05\xe7 \x00\x00\x00\x00ƥ/\xa0\x00\x00\x00\x00\xc6\xd3T \x00\x00\x00\x00\xc8r\x9c\xa0\x00\x00\x00\x00ȩ\xfb\xa0\x00\x00\x00\x00\xcaI" + - "D \x00\x00\x00\x00ʀ\xa3 \x00\x00\x00\x00\xcc\x1f\xeb\xa0\x00\x00\x00\x00\xccN\x10 \x00\x00\x00\x00\xcd\xedX\xa0\x00\x00\x00\x00\xce$\xb7\xa0\x00\x00\x00\x00\xcf\xc4\x00 \x00\x00\x00\x00\xcf\xf2$\xa0\x00\x00" + - "\x00\x00ёm \x00\x00\x00\x00\xd1\xc8\xcc \x00\x00\x00\x00\xd3h\x14\xa0\x00\x00\x00\x00ӟs\xa0\x00\x00\x00\x00\xd5>\xbc \x00\x00\x00\x00\xd5l\xe0\xa0\x00\x00\x00\x00\xd7\f) \x00\x00\x00\x00\xd7C" + - "\x88 \x00\x00\x00\x00\xd8\xe2Р\x00\x00\x00\x00\xd9\x1a/\xa0\x00\x00\x00\x00ڹx \x00\x00\x00\x00\xda眠\x00\x00\x00\x00܆\xe5 \x00\x00\x00\x00ܾD \x01\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05" + - "\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05" + - "\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\xff\xff\xf3\xa0" + - "\x00\x00\xff\xff\xf1\xf0\x00\x04\x00\x00\x0e\x10\x01\b\x00\x00\x00\x00\x00\f\x00\x00\x00\x00\x01\f\x00\x00\x0e\x10\x00\bLMT\x00-01\x00+01\x00+00\x00\n<+01>-1\nPK\x03" + - "\x04\n\x00\x00\x00\x00\x00\xf1c9R6\x99rU\xa4\x00\x00\x00\xa4\x00\x00\x00\x0f\x00\x1c\x00Africa/MonroviaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01" + - "\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00" + - "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\f\xff\xff\xff\xffZz\xa6\x9c\xff\xff\xff\xff\xa0_l" + - "\x9c\x00\x00\x00\x00\x03\xcaZn\x01\x02\x03\xff\xff\xf5\xe4\x00\x00\xff\xff\xf5\xe4\x00\x04\xff\xff\xf5\x92\x00\x04\x00\x00\x00\x00\x00\bLMT\x00MMT\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00" + - "\x00\x00\x00\x00\xf1c9R \x1b\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\r\x00\x1c\x00Africa/LusakaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00" + - "\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif" + - "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x82F\xc5\xf4\x01\x00\x00\x1e\x8c\x00\x00\x00\x00\x1c \x00" + - "\x04LMT\x00CAT\x00\nCAT-2\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\r\x00\x1c\x00Africa/BamakoU" + - "T\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00" + - "\x00\b\xff\xff\xff\xff\x92\xe6\x92H\x01\xff\xff\xfc8\x00\x00\x00\x00\x00\x00\x00\x04LMT\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4" + - "\x00\x00\x00\r\x00\x1c\x00Africa/NiameyUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xff\x86\xabp\xd1\xff\xff\xff\xff\x8cP`\x00\xff\xff\xff\xff\x96\xaaC\xd1\xff\xff\xff\xff\xa1Q\xefx\x01\x00\x02\x03\x00" + - "\x00\x03/\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\a\b\x00\b\x00\x00\x0e\x10\x00\x0eLMT\x00GMT\x00+0030\x00WAT\x00\nWAT-1\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c" + - "9R \x1b\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\r\x00\x1c\x00Africa/KigaliUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00T" + - "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x82F\xc5\xf4\x01\x00\x00\x1e\x8c\x00\x00\x00\x00\x1c \x00\x04LMT\x00C" + - "AT\x00\nCAT-2\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xca>\xd5\xe0\x95\x00\x00\x00\x95\x00\x00\x00\r\x00\x1c\x00Africa/BissauUT\t\x00\x03\x15\xac" + - "\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff" + - "\x92朐\x00\x00\x00\x00\tga\x10\x01\x02\xff\xff\xf1d\x00\x00\xff\xff\xf1\xf0\x00\x04\x00\x00\x00\x00\x00\bLMT\x00-01\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00" + - "\xf1c9R\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\x0f\x00\x1c\x00Africa/KinshasaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8" + - "\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00" + +const zipdata = "PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x1c\x00Africa/UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00" + + "\x04S_\x01\x00PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS \x1b\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\x0f\x00\x1c\x00Africa/GaboroneUT\t\x00\x03\x82\x0f\x8ba\x82" + + "\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00" + + "\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x82F\xc5" + + "\xf4\x01\x00\x00\x1e\x8c\x00\x00\x00\x00\x1c \x00\x04LMT\x00CAT\x00\nCAT-2\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\f\x00\x1c\x00A" + + "frica/DakarUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x92\xe6\x92H\x01\xff\xff\xfc8\x00\x00\x00\x00\x00\x00\x00\x04LMT\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00#" + + "\x82iS\xaa\x81\t\x03\xa0\x00\x00\x00\xa0\x00\x00\x00\x0f\x00\x1c\x00Africa/NdjamenaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_" + + "\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff\xff\x92\xe6\x80d\x00\x00\x00\x00\x12fqp\x00\x00\x00\x00\x13&\xde" + + "`\x01\x02\x01\x00\x00\x0e\x1c\x00\x00\x00\x00\x0e\x10\x00\x04\x00\x00\x1c \x01\bLMT\x00WAT\x00WAST\x00\nWAT-1\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xf1\b{\x87" + + "\x82\x00\x00\x00\x82\x00\x00\x00\x0e\x00\x1c\x00Africa/AbidjanUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x92\xe6\x92H\x01\xff\xff\xfc8\x00\x00\x00\x00\x00\x00\x00\x04LMT\x00GMT\x00\nG" + + "MT0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS \x1b\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\r\x00\x1c\x00Africa/HarareUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8ba" + + "ux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00" + + "\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x82F\xc5\xf4\x01\x00" + + "\x00\x1e\x8c\x00\x00\x00\x00\x1c \x00\x04LMT\x00CAT\x00\nCAT-2\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\x12\x00\x1c\x00Afri" + + "ca/OuagadougouUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x92\xe6\x92H\x01\xff\xff\xfc8\x00\x00\x00\x00\x00\x00\x00\x04LMT\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00" + + "\x00\x00#\x82iSd\x01\x05\x89\u007f\a\x00\x00\u007f\a\x00\x00\x11\x00\x1c\x00Africa/CasablancaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E" + + "\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + + "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc5\x00\x00\x00\x05\x00\x00\x00\f\xff\xff\xff\xff\x96Q\xf9\x9c\xff\xff\xff\xff\xc6\xff\x14\x80\xff\xff" + + "\xff\xff\xc7X\xacp\xff\xff\xff\xff\xc7\xd9\xed\x80\xff\xff\xff\xffҡ2\xf0\xff\xff\xff\xff\xdb5\xa4\x00\xff\xff\xff\xff\xdb\xee'\xf0\xff\xff\xff\xff\xfb%r@\xff\xff\xff\xff\xfb\xc2\xefp\x00\x00\x00\x00\bk" + + "\x84\x80\x00\x00\x00\x00\b\xc6m\xf0\x00\x00\x00\x00\v\xe8\f\x00\x00\x00\x00\x00\faG\xf0\x00\x00\x00\x00\r\xc9?\x80\x00\x00\x00\x00\x0e\x8e\xf2p\x00\x00\x00\x00\x0f\xd3Q\x80\x00\x00\x00\x00\x10'\xa3p\x00\x00" + + "\x00\x00\x1a\xb7\xa6\x00\x00\x00\x00\x00\x1e\x18o\xf0\x00\x00\x00\x00HA\xe6\x80\x00\x00\x00\x00H\xbb\"p\x00\x00\x00\x00J#\x1a\x00\x00\x00\x00\x00J\x8d\xd5p\x00\x00\x00\x00K\xdc\xc0\x80\x00\x00\x00\x00L]" + + "\xe5p\x00\x00\x00\x00M\x97\xb8\x80\x00\x00\x00\x00N4\x8c\xf0\x00\x00\x00\x00O\x9c\xa0\xa0\x00\x00\x00\x00P\b\xbb\xa0\x00\x00\x00\x00P1\x9a \x00\x00\x00\x00Pg\xa7\xa0\x00\x00\x00\x00Q|\x82\xa0\x00\x00" + + "\x00\x00Q\xd8ˠ\x00\x00\x00\x00R\x05\x9e\xa0\x00\x00\x00\x00Rls\xa0\x00\x00\x00\x00S7z\xa0\x00\x00\x00\x00S\xae!\xa0\x00\x00\x00\x00S\xdcF \x00\x00\x00\x00TLU\xa0\x00\x00\x00\x00U\x17" + + "\\\xa0\x00\x00\x00\x00U|\xe0 \x00\x00\x00\x00U\xab\x04\xa0\x00\x00\x00\x00V,7\xa0\x00\x00\x00\x00V\xf7>\xa0\x00\x00\x00\x00WS\x87\xa0\x00\x00\x00\x00W\x81\xac \x00\x00\x00\x00X\x15T \x00\x00" + + "\x00\x00X\xd7 \xa0\x00\x00\x00\x00Y \xf4\xa0\x00\x00\x00\x00YXS\xa0\x00\x00\x00\x00Y\xf56 \x00\x00\x00\x00Z\xb7\x02\xa0\x00\x00\x00\x00Z\xf7\x9c \x00\x00\x00\x00[%\xc0\xa0\x00\x00\x00\x00[\xd5" + + "\x18 \x00\x00\x00\x00\\\xceC\xa0\x00\x00\x00\x00\\\xfch \x00\x00\x00\x00^\x9b\xb0\xa0\x00\x00\x00\x00^\xd3\x0f\xa0\x00\x00\x00\x00`rX \x00\x00\x00\x00`\xa0|\xa0\x00\x00\x00\x00b?\xc5 \x00\x00" + + "\x00\x00bw$ \x00\x00\x00\x00d\x16l\xa0\x00\x00\x00\x00dMˠ\x00\x00\x00\x00e\xed\x14 \x00\x00\x00\x00f\x1b8\xa0\x00\x00\x00\x00g\xba\x81 \x00\x00\x00\x00g\xf1\xe0 \x00\x00\x00\x00i\x91" + + "(\xa0\x00\x00\x00\x00i\xbfM \x00\x00\x00\x00kg\xd0 \x00\x00\x00\x00k\x95\xf4\xa0\x00\x00\x00\x00m5= \x00\x00\x00\x00ml\x9c \x00\x00\x00\x00o\v\xe4\xa0\x00\x00\x00\x00o:\t \x00\x00" + + "\x00\x00p\xd9Q\xa0\x00\x00\x00\x00q\x10\xb0\xa0\x00\x00\x00\x00r\xaf\xf9 \x00\x00\x00\x00r\xe7X \x00\x00\x00\x00t\x86\xa0\xa0\x00\x00\x00\x00t\xb4\xc5 \x00\x00\x00\x00vT\r\xa0\x00\x00\x00\x00v\x8b" + + "l\xa0\x00\x00\x00\x00x*\xb5 \x00\x00\x00\x00xX٠\x00\x00\x00\x00y\xf8\" \x00\x00\x00\x00z/\x81 \x00\x00\x00\x00{\xceɠ\x00\x00\x00\x00|\x06(\xa0\x00\x00\x00\x00}\xa5q \x00\x00" + + "\x00\x00}ӕ\xa0\x00\x00\x00\x00\u007fr\xde \x00\x00\x00\x00\u007f\xaa= \x00\x00\x00\x00\x81I\x85\xa0\x00\x00\x00\x00\x81\x80\xe4\xa0\x00\x00\x00\x00\x83 - \x00\x00\x00\x00\x83NQ\xa0\x00\x00\x00\x00\x84\xed" + + "\x9a \x00\x00\x00\x00\x85$\xf9 \x00\x00\x00\x00\x86\xc4A\xa0\x00\x00\x00\x00\x86\xf2f \x00\x00\x00\x00\x88\x91\xae\xa0\x00\x00\x00\x00\x88\xc9\r\xa0\x00\x00\x00\x00\x8ahV \x00\x00\x00\x00\x8a\x9f\xb5 \x00\x00" + + "\x00\x00\x8c>\xfd\xa0\x00\x00\x00\x00\x8cm\" \x00\x00\x00\x00\x8e\fj\xa0\x00\x00\x00\x00\x8eCɠ\x00\x00\x00\x00\x8f\xe3\x12 \x00\x00\x00\x00\x90\x1aq \x00\x00\x00\x00\x91\xb9\xb9\xa0\x00\x00\x00\x00\x91\xe7" + + "\xde \x00\x00\x00\x00\x93\x87&\xa0\x00\x00\x00\x00\x93\xbe\x85\xa0\x00\x00\x00\x00\x95]\xce \x00\x00\x00\x00\x95\x8b\xf2\xa0\x00\x00\x00\x00\x97+; \x00\x00\x00\x00\x97b\x9a \x00\x00\x00\x00\x99\x01\xe2\xa0\x00\x00" + + "\x00\x00\x999A\xa0\x00\x00\x00\x00\x9a؊ \x00\x00\x00\x00\x9b\x06\xae\xa0\x00\x00\x00\x00\x9c\xa5\xf7 \x00\x00\x00\x00\x9c\xddV \x00\x00\x00\x00\x9e|\x9e\xa0\x00\x00\x00\x00\x9e\xb3\xfd\xa0\x00\x00\x00\x00\xa0S" + + "F \x00\x00\x00\x00\xa0\x81j\xa0\x00\x00\x00\x00\xa2 \xb3 \x00\x00\x00\x00\xa2X\x12 \x00\x00\x00\x00\xa3\xf7Z\xa0\x00\x00\x00\x00\xa4%\u007f \x00\x00\x00\x00\xa5\xc4Ǡ\x00\x00\x00\x00\xa5\xfc&\xa0\x00\x00" + + "\x00\x00\xa7\x9bo \x00\x00\x00\x00\xa7\xd2\xce \x00\x00\x00\x00\xa9r\x16\xa0\x00\x00\x00\x00\xa9\xa0; \x00\x00\x00\x00\xab?\x83\xa0\x00\x00\x00\x00\xabv\xe2\xa0\x00\x00\x00\x00\xad\x16+ \x00\x00\x00\x00\xadM" + + "\x8a \x00\x00\x00\x00\xae\xecҠ\x00\x00\x00\x00\xaf\x1a\xf7 \x00\x00\x00\x00\xb0\xba?\xa0\x00\x00\x00\x00\xb0\xf1\x9e\xa0\x00\x00\x00\x00\xb2\x90\xe7 \x00\x00\x00\x00\xb2\xbf\v\xa0\x00\x00\x00\x00\xb4^T \x00\x00" + + "\x00\x00\xb4\x95\xb3 \x00\x00\x00\x00\xb64\xfb\xa0\x00\x00\x00\x00\xb6lZ\xa0\x00\x00\x00\x00\xb8\v\xa3 \x00\x00\x00\x00\xb89Ǡ\x00\x00\x00\x00\xb9\xd9\x10 \x00\x00\x00\x00\xba\x10o \x00\x00\x00\x00\xbb\xaf" + + "\xb7\xa0\x00\x00\x00\x00\xbb\xe7\x16\xa0\x00\x00\x00\x00\xbd\x86_ \x00\x00\x00\x00\xbd\xb4\x83\xa0\x00\x00\x00\x00\xbfS\xcc \x00\x00\x00\x00\xbf\x8b+ \x00\x00\x00\x00\xc1*s\xa0\x00\x00\x00\x00\xc1X\x98 \x00\x00" + + "\x00\x00\xc2\xf7\xe0\xa0\x00\x00\x00\x00\xc3/?\xa0\x00\x00\x00\x00\xc4Έ \x00\x00\x00\x00\xc5\x05\xe7 \x00\x00\x00\x00ƥ/\xa0\x00\x00\x00\x00\xc6\xd3T \x00\x00\x00\x00\xc8r\x9c\xa0\x00\x00\x00\x00ȩ" + + "\xfb\xa0\x00\x00\x00\x00\xcaID \x00\x00\x00\x00ʀ\xa3 \x00\x00\x00\x00\xcc\x1f\xeb\xa0\x00\x00\x00\x00\xccN\x10 \x00\x00\x00\x00\xcd\xedX\xa0\x00\x00\x00\x00\xce$\xb7\xa0\x00\x00\x00\x00\xcf\xc4\x00 \x00\x00" + + "\x00\x00\xcf\xf2$\xa0\x00\x00\x00\x00ёm \x00\x00\x00\x00\xd1\xc8\xcc \x00\x00\x00\x00\xd3h\x14\xa0\x00\x00\x00\x00ӟs\xa0\x00\x00\x00\x00\xd5>\xbc \x00\x00\x00\x00\xd5l\xe0\xa0\x00\x00\x00\x00\xd7\f" + + ") \x00\x00\x00\x00\xd7C\x88 \x00\x00\x00\x00\xd8\xe2Р\x00\x00\x00\x00\xd9\x1a/\xa0\x00\x00\x00\x00ڹx \x00\x00\x00\x00\xda眠\x00\x00\x00\x00܆\xe5 \x00\x00\x00\x00ܾD \x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x03\x04\x03\x04\x03\x04\x03\x04" + + "\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04" + + "\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04" + + "\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\xff\xff\xf8\xe4\x00\x00\x00\x00\x0e\x10\x01\x04\x00\x00\x00\x00\x00\b\x00\x00\x0e\x10\x00\x04\x00\x00\x00\x00\x01\bLMT\x00+01\x00+00\x00\n<+" + + "01>-1\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\x14\x00\x1c\x00Africa/Dar_es_SalaamUT\t\x00" + + "\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\x14\xff" + + "\xff\xff\xff\x8b\xff\xd1\xfc\xff\xff\xff\xff\xb1\xee\xdaX\xff\xff\xff\xff\xb4\xc7\xe0\xd0\xff\xff\xff\xff\xc1\xed\xadX\xff\xff\xff\xff\xcclz\xd4\x01\x02\x01\x03\x02\x00\x00\"\x84\x00\x00\x00\x00#(\x00\x04\x00\x00*0" + + "\x00\n\x00\x00&\xac\x00\x0eLMT\x00+0230\x00EAT\x00+0245\x00\nEAT-3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00" + + "\x00\x11\x00\x1c\x00Africa/Porto-NovoUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xff\x86\xabp\xd1\xff\xff\xff\xff\x8cP`\x00\xff\xff\xff\xff\x96\xaaC\xd1\xff\xff\xff\xff\xa1Q\xefx\x01\x00\x02" + + "\x03\x00\x00\x03/\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\a\b\x00\b\x00\x00\x0e\x10\x00\x0eLMT\x00GMT\x00+0030\x00WAT\x00\nWAT-1\nPK\x03\x04\n\x00\x00\x00\x00\x00" + + "#\x82iS\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\x0f\x00\x1c\x00Africa/KinshasaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S" + + "_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xff\x86\xabp\xd1\xff\xff\xff\xff\x8cP`\x00\xff\xff\xff\xff\x96\xaa" + "C\xd1\xff\xff\xff\xff\xa1Q\xefx\x01\x00\x02\x03\x00\x00\x03/\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\a\b\x00\b\x00\x00\x0e\x10\x00\x0eLMT\x00GMT\x00+0030\x00WAT\x00\nWAT" + - "-1\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\x12\x00\x1c\x00Africa/Addis_AbabaUT\t\x00\x03\x15\xac\x0e`" + - "\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00" + - "\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\x14\xff\xff\xff\xff\x8b\xff" + - "\xd1\xfc\xff\xff\xff\xff\xb1\xee\xdaX\xff\xff\xff\xff\xb4\xc7\xe0\xd0\xff\xff\xff\xff\xc1\xed\xadX\xff\xff\xff\xff\xcclz\xd4\x01\x02\x01\x03\x02\x00\x00\"\x84\x00\x00\x00\x00#(\x00\x04\x00\x00*0\x00\n\x00\x00&" + - "\xac\x00\x0eLMT\x00+0230\x00EAT\x00+0245\x00\nEAT-3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x93\xf4\x94\v\xc1\x01\x00\x00\xc1\x01\x00\x00\f\x00\x1c\x00" + - "Africa/TunisUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\"\x00\x00\x00\x04\x00\x00\x00\x11\xff\xff\xff\xffYF\x13\xf4\xff\xff\xff\xff\x91`PO\xff\xff\xff\xff\xc6:\x88\xe0\xff\xff\xff\xff\xc7X\x9e`\xff\xff\xff\xff\xc7\xdb\"\xe0\xff\xff\xff\xff\xca" + - "\xe2T\xe0\xff\xff\xff\xff˭i\xf0\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\xcd\xc2\x16\x00\xff\xff\xff\xff\xcd̰\x10\xff\xff\xff\xff\u03a25\x00\xff\xff\xff\xffϒ4\x10\xff" + - "\xff\xff\xffЉ\xe3\xe0\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd2N\x16`\x00\x00\x00\x00\r\xc7\xdf\xf0\x00\x00\x00\x00\x0e\x89\xacp\x00\x00\x00\x00\x0f\xaad\xf0\x00\x00\x00\x00\x10t\x1ap\x00\x00\x00\x00\"" + - "\xa3:\xf0\x00\x00\x00\x00#<(\xf0\x00\x00\x00\x00$,\x19\xf0\x00\x00\x00\x00%\x1c\n\xf0\x00\x00\x00\x00&<\xc3p\x00\x00\x00\x00'\x05'p\x00\x00\x00\x00Bt\r\xf0\x00\x00\x00\x00C<\x80\x00\x00" + - "\x00\x00\x00D%\xe7\x90\x00\x00\x00\x00EC\xfd\x10\x00\x00\x00\x00F\x05ɐ\x00\x00\x00\x00G#\xdf\x10\x00\x00\x00\x00G\xee\xe6\x10\x00\x00\x00\x00I\x03\xc1\x10\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x00\x00\t\x8c\x00\x00\x00\x00\x021\x00\x04\x00\x00\x1c \x01\b\x00\x00\x0e\x10\x00\rLMT\x00PMT\x00CEST\x00CE" + - "T\x00\nCET-1\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\r\x00\x1c\x00Africa/BanjulUT\t\x00\x03\x15\xac\x0e" + - "`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" + - "\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x92" + - "\xe6\x92H\x01\xff\xff\xfc8\x00\x00\x00\x00\x00\x00\x00\x04LMT\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\x12\x00\x1c\x00" + - "Africa/OuagadougouUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x92\xe6\x92H\x01\xff\xff\xfc8\x00\x00\x00\x00\x00\x00\x00\x04LMT\x00GMT\x00\nGMT0\nPK\x03\x04" + - "\n\x00\x00\x00\x00\x00\xf1c9R\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\x11\x00\x1c\x00Africa/LibrevilleUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00" + - "\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00" + - "\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xff\x86\xabp\xd1\xff\xff\xff\xff\x8cP" + - "`\x00\xff\xff\xff\xff\x96\xaaC\xd1\xff\xff\xff\xff\xa1Q\xefx\x01\x00\x02\x03\x00\x00\x03/\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\a\b\x00\b\x00\x00\x0e\x10\x00\x0eLMT\x00GMT\x00+0030\x00" + - "WAT\x00\nWAT-1\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\x12\x00\x1c\x00Africa/BrazzavilleU" + - "T\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00" + - "\x00\x12\xff\xff\xff\xff\x86\xabp\xd1\xff\xff\xff\xff\x8cP`\x00\xff\xff\xff\xff\x96\xaaC\xd1\xff\xff\xff\xff\xa1Q\xefx\x01\x00\x02\x03\x00\x00\x03/\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\a\b\x00\b\x00\x00\x0e\x10" + - "\x00\x0eLMT\x00GMT\x00+0030\x00WAT\x00\nWAT-1\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\r\x00\x1c\x00Afr" + - "ica/BanguiUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xff\x86\xabp\xd1\xff\xff\xff\xff\x8cP`\x00\xff\xff\xff\xff\x96\xaaC\xd1\xff\xff\xff\xff\xa1Q\xefx\x01\x00\x02\x03\x00\x00\x03/\x00\x00\x00\x00\x00\x00\x00" + - "\x04\x00\x00\a\b\x00\b\x00\x00\x0e\x10\x00\x0eLMT\x00GMT\x00+0030\x00WAT\x00\nWAT-1\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xf1\b{\x87\x82\x00\x00\x00" + - "\x82\x00\x00\x00\x0e\x00\x1c\x00Africa/AbidjanUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x92\xe6\x92H\x01\xff\xff\xfc8\x00\x00\x00\x00\x00\x00\x00\x04LMT\x00GMT\x00\nGMT0\n" + - "PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RÊ\x0e\xc0\xd6\x01\x00\x00\xd6\x01\x00\x00\x0e\x00\x1c\x00Africa/AlgiersUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v" + - "\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00" + - "\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\"\x00\x00\x00\x06\x00\x00\x00\x1a\xff\xff\xff\xffkɛ$\xff\xff\xff\xff\x91" + - "`PO\xff\xff\xff\xff\x9bGx\xf0\xff\xff\xff\xff\x9b\xd7,p\xff\xff\xff\xff\x9c\xbc\x91p\xff\xff\xff\xff\x9d\xc0H\xf0\xff\xff\xff\xff\x9e\x89\xfep\xff\xff\xff\xff\x9f\xa0*\xf0\xff\xff\xff\xff\xa0`\xa5\xf0\xff" + - "\xff\xff\xff\xa1\x80\f\xf0\xff\xff\xff\xff\xa2.\x12\xf0\xff\xff\xff\xff\xa3zL\xf0\xff\xff\xff\xff\xa45\x81\xf0\xff\xff\xff\xff\xa4\xb8\x06p\xff\xff\xff\xff\xc6\xff\x06p\xff\xff\xff\xff\xc7X\xba\x80\xff\xff\xff\xff\xc7" + - "\xda\t\xa0\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЊ\x00\x00\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd2N$p\xff\xff\xff\xff\xd4K\ap\xff\xff\xff\xff\xe5\xce\xd3\x00\xff\xff\xff\xff\xf3\\\xb0\xf0\x00" + - "\x00\x00\x00\x02x\xc1\xf0\x00\x00\x00\x00\x03C\xc8\xf0\x00\x00\x00\x00\r\xcf\xd7\x00\x00\x00\x00\x00\x0e\xadD\xf0\x00\x00\x00\x00\x0fxZ\x00\x00\x00\x00\x00\x10hY\x10\x00\x00\x00\x00\x12vCp\x00\x00\x00\x00\x13" + - "fB\x80\x00\x00\x00\x00\x14_|\x10\x00\x00\x00\x00\x15O_\x00\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x05\x04\x05\x04\x05\x03\x05\x03\x02\x03\x02\x05\x04\x05\x03\x02\x03\x05\x00\x00\x02\xdc\x00\x00\x00" + - "\x00\x021\x00\x04\x00\x00\x0e\x10\x01\b\x00\x00\x00\x00\x00\r\x00\x00\x1c \x01\x11\x00\x00\x0e\x10\x00\x16LMT\x00PMT\x00WEST\x00WET\x00CEST\x00CET\x00\nCET-" + - "1\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\x11\x00\x1c\x00Africa/NouakchottUT\t\x00\x03\x15\xac\x0e`\x15\xac" + - "\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" + - "\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x92\xe6\x92H" + - "\x01\xff\xff\xfc8\x00\x00\x00\x00\x00\x00\x00\x04LMT\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xc1\n\x8a\x84\xad\x00\x00\x00\xad\x00\x00\x00\x0f\x00\x1c\x00Afr" + - "ica/Sao_TomeUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\f\xff\xff\xff\xff^<\xfd0\xff\xff\xff\xff\x92掀\x00\x00\x00\x00ZI\x88\x10\x00\x00\x00\x00\\*\xbb\x90\x01\x02\x03\x02\x00\x00\x06P\x00\x00\xff\xff\xf7" + - "c\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x0e\x10\x00\bLMT\x00GMT\x00WAT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\x14" + - "\x00\x1c\x00Africa/Dar_es_SalaamUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\x14\xff\xff\xff\xff\x8b\xff\xd1\xfc\xff\xff\xff\xff\xb1\xee\xdaX\xff\xff\xff\xff\xb4\xc7\xe0\xd0\xff\xff\xff\xff\xc1\xed\xadX\xff\xff" + - "\xff\xff\xcclz\xd4\x01\x02\x01\x03\x02\x00\x00\"\x84\x00\x00\x00\x00#(\x00\x04\x00\x00*0\x00\n\x00\x00&\xac\x00\x0eLMT\x00+0230\x00EAT\x00+0245\x00\nEAT-" + - "3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R \x1b\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\x11\x00\x1c\x00Africa/LubumbashiUT\t\x00\x03\x15\xac\x0e`\x15\xac" + - "\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" + - "\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x82F\xc5\xf4" + - "\x01\x00\x00\x1e\x8c\x00\x00\x00\x00\x1c \x00\x04LMT\x00CAT\x00\nCAT-2\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\x0e\x00\x1c\x00Af" + - "rica/KampalaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\x14\xff\xff\xff\xff\x8b\xff\xd1\xfc\xff\xff\xff\xff\xb1\xee\xdaX\xff\xff\xff\xff\xb4\xc7\xe0\xd0\xff\xff\xff\xff\xc1\xed\xadX\xff\xff\xff\xff\xcclz\xd4\x01\x02\x01\x03\x02" + - "\x00\x00\"\x84\x00\x00\x00\x00#(\x00\x04\x00\x00*0\x00\n\x00\x00&\xac\x00\x0eLMT\x00+0230\x00EAT\x00+0245\x00\nEAT-3\nPK\x03\x04\n\x00\x00\x00\x00" + - "\x00\xf1c9R \x1b\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\x0f\x00\x1c\x00Africa/BlantyreUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04" + - "\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x82F\xc5\xf4\x01\x00\x00\x1e\x8c\x00\x00\x00\x00\x1c \x00\x04" + - "LMT\x00CAT\x00\nCAT-2\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\r\x00\x1c\x00Africa/MalaboUT" + - "\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00" + - "\x12\xff\xff\xff\xff\x86\xabp\xd1\xff\xff\xff\xff\x8cP`\x00\xff\xff\xff\xff\x96\xaaC\xd1\xff\xff\xff\xff\xa1Q\xefx\x01\x00\x02\x03\x00\x00\x03/\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\a\b\x00\b\x00\x00\x0e\x10\x00" + - "\x0eLMT\x00GMT\x00+0030\x00WAT\x00\nWAT-1\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xaa\x81\t\x03\xa0\x00\x00\x00\xa0\x00\x00\x00\x0f\x00\x1c\x00Afri" + - "ca/NdjamenaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x03\x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff\xff\x92\xe6\x80d\x00\x00\x00\x00\x12fqp\x00\x00\x00\x00\x13&\xde`\x01\x02\x01\x00\x00\x0e\x1c\x00\x00\x00\x00\x0e\x10\x00\x04\x00\x00\x1c \x01\bL" + - "MT\x00WAT\x00WAST\x00\nWAT-1\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\x0f\x00\x1c\x00Africa/Timb" + - "uktuUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00" + - "\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x92\xe6\x92H\x01\xff\xff\xfc8\x00\x00\x00\x00\x00\x00\x00\x04LMT\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R \x1b\xb0_" + - "\x83\x00\x00\x00\x83\x00\x00\x00\x0f\x00\x1c\x00Africa/GaboroneUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2" + + "-1\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\x12\x00\x1c\x00Africa/BrazzavilleUT\t\x00\x03\x82\x0f\x8ba" + + "\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00" + + "\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xff\x86\xab" + + "p\xd1\xff\xff\xff\xff\x8cP`\x00\xff\xff\xff\xff\x96\xaaC\xd1\xff\xff\xff\xff\xa1Q\xefx\x01\x00\x02\x03\x00\x00\x03/\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\a\b\x00\b\x00\x00\x0e\x10\x00\x0eLMT\x00GM" + + "T\x00+0030\x00WAT\x00\nWAT-1\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\x10\x00\x1c\x00Africa/Moga" + + "dishuUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05" + + "\x00\x00\x00\x04\x00\x00\x00\x14\xff\xff\xff\xff\x8b\xff\xd1\xfc\xff\xff\xff\xff\xb1\xee\xdaX\xff\xff\xff\xff\xb4\xc7\xe0\xd0\xff\xff\xff\xff\xc1\xed\xadX\xff\xff\xff\xff\xcclz\xd4\x01\x02\x01\x03\x02\x00\x00\"\x84\x00\x00\x00" + + "\x00#(\x00\x04\x00\x00*0\x00\n\x00\x00&\xac\x00\x0eLMT\x00+0230\x00EAT\x00+0245\x00\nEAT-3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xc1\n" + + "\x8a\x84\xad\x00\x00\x00\xad\x00\x00\x00\x0f\x00\x1c\x00Africa/Sao_TomeUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZi" + + "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\f\xff\xff\xff\xff^<\xfd0\xff\xff\xff\xff\x92掀\x00\x00\x00\x00ZI\x88\x10\x00\x00\x00\x00" + + "\\*\xbb\x90\x01\x02\x03\x02\x00\x00\x06P\x00\x00\xff\xff\xf7c\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x0e\x10\x00\bLMT\x00GMT\x00WAT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00" + + "#\x82iS\xcc\fTξ\x00\x00\x00\xbe\x00\x00\x00\x13\x00\x1c\x00Africa/JohannesburgUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E" + + "\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + + "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\t\xff\xff\xff\xffm{A@\xff\xff\xff\xff\x82F\xcfh\xff\xff" + + "\xff\xff̮\x8c\x80\xff\xff\xff\xff͞op\xff\xff\xff\xffΎn\x80\xff\xff\xff\xff\xcf~Qp\x01\x03\x02\x03\x02\x03\x00\x00\x1a@\x00\x00\x00\x00\x15\x18\x00\x04\x00\x00*0\x01\x04\x00\x00\x1c \x00\x04" + + "LMT\x00SAST\x00\nSAST-2\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSm)\xb8P~\x02\x00\x00~\x02\x00\x00\x0f\x00\x1c\x00Africa/Windho" + + "ekUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x005\x00\x00\x00" + + "\x06\x00\x00\x00\x17\xff\xff\xff\xffm{Kx\xff\xff\xff\xff\x82F\xcfh\xff\xff\xff\xff̮\x8c\x80\xff\xff\xff\xff͞op\x00\x00\x00\x00&\x06\xa7\xe0\x00\x00\x00\x00-\x8c\xc7`\x00\x00\x00\x00.i\x1c" + + "\x10\x00\x00\x00\x00/}\xe9\x00\x00\x00\x00\x000H\xfe\x10\x00\x00\x00\x001g\x05\x80\x00\x00\x00\x002(\xe0\x10\x00\x00\x00\x003F\xe7\x80\x00\x00\x00\x004\x11\xfc\x90\x00\x00\x00\x005&ɀ\x00\x00\x00" + + "\x005\xf1ސ\x00\x00\x00\x007\x06\xab\x80\x00\x00\x00\x007\xd1\xc0\x90\x00\x00\x00\x008捀\x00\x00\x00\x009\xb1\xa2\x90\x00\x00\x00\x00:\xc6o\x80\x00\x00\x00\x00;\x91\x84\x90\x00\x00\x00\x00<\xaf\x8c" + + "\x00\x00\x00\x00\x00=qf\x90\x00\x00\x00\x00>\x8fn\x00\x00\x00\x00\x00?Z\x83\x10\x00\x00\x00\x00@oP\x00\x00\x00\x00\x00A:e\x10\x00\x00\x00\x00BO2\x00\x00\x00\x00\x00C\x1aG\x10\x00\x00\x00" + + "\x00D/\x14\x00\x00\x00\x00\x00D\xfa)\x10\x00\x00\x00\x00F\x0e\xf6\x00\x00\x00\x00\x00F\xda\v\x10\x00\x00\x00\x00G\xf8\x12\x80\x00\x00\x00\x00H\xc3'\x90\x00\x00\x00\x00I\xd7\xf4\x80\x00\x00\x00\x00J\xa3\t" + + "\x90\x00\x00\x00\x00K\xb7ր\x00\x00\x00\x00L\x82\xeb\x90\x00\x00\x00\x00M\x97\xb8\x80\x00\x00\x00\x00Nb͐\x00\x00\x00\x00Ow\x9a\x80\x00\x00\x00\x00PB\xaf\x90\x00\x00\x00\x00Q`\xb7\x00\x00\x00\x00" + + "\x00R\"\x91\x90\x00\x00\x00\x00S@\x99\x00\x00\x00\x00\x00T\v\xae\x10\x00\x00\x00\x00U {\x00\x00\x00\x00\x00U\xeb\x90\x10\x00\x00\x00\x00W\x00]\x00\x00\x00\x00\x00W\xcbr\x10\x00\x00\x00\x00X\xe0?" + + "\x00\x00\x00\x00\x00Y\xabT\x10\x01\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05" + + "\x04\x05\x00\x00\x10\b\x00\x00\x00\x00\x15\x18\x00\x04\x00\x00\x1c \x00\n\x00\x00*0\x01\n\x00\x00\x0e\x10\x01\x0f\x00\x00\x1c \x00\x13LMT\x00+0130\x00SAST\x00WAT\x00CAT" + + "\x00\nCAT-2\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\r\x00\x1c\x00Africa/NiameyUT\t\x00\x03\x82\x0f\x8ba" + + "\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00" + + "\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xff\x86\xab" + + "p\xd1\xff\xff\xff\xff\x8cP`\x00\xff\xff\xff\xff\x96\xaaC\xd1\xff\xff\xff\xff\xa1Q\xefx\x01\x00\x02\x03\x00\x00\x03/\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\a\b\x00\b\x00\x00\x0e\x10\x00\x0eLMT\x00GM" + + "T\x00+0030\x00WAT\x00\nWAT-1\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\x0e\x00\x1c\x00Africa/Nair" + + "obiUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00" + + "\x00\x04\x00\x00\x00\x14\xff\xff\xff\xff\x8b\xff\xd1\xfc\xff\xff\xff\xff\xb1\xee\xdaX\xff\xff\xff\xff\xb4\xc7\xe0\xd0\xff\xff\xff\xff\xc1\xed\xadX\xff\xff\xff\xff\xcclz\xd4\x01\x02\x01\x03\x02\x00\x00\"\x84\x00\x00\x00\x00#" + + "(\x00\x04\x00\x00*0\x00\n\x00\x00&\xac\x00\x0eLMT\x00+0230\x00EAT\x00+0245\x00\nEAT-3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS)\xae\x8eo" + + "&\a\x00\x00&\a\x00\x00\x0f\x00\x1c\x00Africa/El_AaiunUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x82F\xc5\xf4\x01\x00\x00\x1e\x8c\x00\x00\x00\x00\x1c \x00\x04LMT\x00CAT\x00\n" + - "CAT-2\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rd\x01\x05\x89\u007f\a\x00\x00\u007f\a\x00\x00\x11\x00\x1c\x00Africa/CasablancaUT\t\x00\x03\x15\xac" + - "\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc5\x00\x00\x00\x05\x00\x00\x00\f\xff\xff\xff\xff" + - "\x96Q\xf9\x9c\xff\xff\xff\xff\xc6\xff\x14\x80\xff\xff\xff\xff\xc7X\xacp\xff\xff\xff\xff\xc7\xd9\xed\x80\xff\xff\xff\xffҡ2\xf0\xff\xff\xff\xff\xdb5\xa4\x00\xff\xff\xff\xff\xdb\xee'\xf0\xff\xff\xff\xff\xfb%r@" + - "\xff\xff\xff\xff\xfb\xc2\xefp\x00\x00\x00\x00\bk\x84\x80\x00\x00\x00\x00\b\xc6m\xf0\x00\x00\x00\x00\v\xe8\f\x00\x00\x00\x00\x00\faG\xf0\x00\x00\x00\x00\r\xc9?\x80\x00\x00\x00\x00\x0e\x8e\xf2p\x00\x00\x00\x00" + - "\x0f\xd3Q\x80\x00\x00\x00\x00\x10'\xa3p\x00\x00\x00\x00\x1a\xb7\xa6\x00\x00\x00\x00\x00\x1e\x18o\xf0\x00\x00\x00\x00HA\xe6\x80\x00\x00\x00\x00H\xbb\"p\x00\x00\x00\x00J#\x1a\x00\x00\x00\x00\x00J\x8d\xd5p" + - "\x00\x00\x00\x00K\xdc\xc0\x80\x00\x00\x00\x00L]\xe5p\x00\x00\x00\x00M\x97\xb8\x80\x00\x00\x00\x00N4\x8c\xf0\x00\x00\x00\x00O\x9c\xa0\xa0\x00\x00\x00\x00P\b\xbb\xa0\x00\x00\x00\x00P1\x9a \x00\x00\x00\x00" + - "Pg\xa7\xa0\x00\x00\x00\x00Q|\x82\xa0\x00\x00\x00\x00Q\xd8ˠ\x00\x00\x00\x00R\x05\x9e\xa0\x00\x00\x00\x00Rls\xa0\x00\x00\x00\x00S7z\xa0\x00\x00\x00\x00S\xae!\xa0\x00\x00\x00\x00S\xdcF " + - "\x00\x00\x00\x00TLU\xa0\x00\x00\x00\x00U\x17\\\xa0\x00\x00\x00\x00U|\xe0 \x00\x00\x00\x00U\xab\x04\xa0\x00\x00\x00\x00V,7\xa0\x00\x00\x00\x00V\xf7>\xa0\x00\x00\x00\x00WS\x87\xa0\x00\x00\x00\x00" + - "W\x81\xac \x00\x00\x00\x00X\x15T \x00\x00\x00\x00X\xd7 \xa0\x00\x00\x00\x00Y \xf4\xa0\x00\x00\x00\x00YXS\xa0\x00\x00\x00\x00Y\xf56 \x00\x00\x00\x00Z\xb7\x02\xa0\x00\x00\x00\x00Z\xf7\x9c " + - "\x00\x00\x00\x00[%\xc0\xa0\x00\x00\x00\x00[\xd5\x18 \x00\x00\x00\x00\\\xceC\xa0\x00\x00\x00\x00\\\xfch \x00\x00\x00\x00^\x9b\xb0\xa0\x00\x00\x00\x00^\xd3\x0f\xa0\x00\x00\x00\x00`rX \x00\x00\x00\x00" + - "`\xa0|\xa0\x00\x00\x00\x00b?\xc5 \x00\x00\x00\x00bw$ \x00\x00\x00\x00d\x16l\xa0\x00\x00\x00\x00dMˠ\x00\x00\x00\x00e\xed\x14 \x00\x00\x00\x00f\x1b8\xa0\x00\x00\x00\x00g\xba\x81 " + - "\x00\x00\x00\x00g\xf1\xe0 \x00\x00\x00\x00i\x91(\xa0\x00\x00\x00\x00i\xbfM \x00\x00\x00\x00kg\xd0 \x00\x00\x00\x00k\x95\xf4\xa0\x00\x00\x00\x00m5= \x00\x00\x00\x00ml\x9c \x00\x00\x00\x00" + - "o\v\xe4\xa0\x00\x00\x00\x00o:\t \x00\x00\x00\x00p\xd9Q\xa0\x00\x00\x00\x00q\x10\xb0\xa0\x00\x00\x00\x00r\xaf\xf9 \x00\x00\x00\x00r\xe7X \x00\x00\x00\x00t\x86\xa0\xa0\x00\x00\x00\x00t\xb4\xc5 " + - "\x00\x00\x00\x00vT\r\xa0\x00\x00\x00\x00v\x8bl\xa0\x00\x00\x00\x00x*\xb5 \x00\x00\x00\x00xX٠\x00\x00\x00\x00y\xf8\" \x00\x00\x00\x00z/\x81 \x00\x00\x00\x00{\xceɠ\x00\x00\x00\x00" + - "|\x06(\xa0\x00\x00\x00\x00}\xa5q \x00\x00\x00\x00}ӕ\xa0\x00\x00\x00\x00\u007fr\xde \x00\x00\x00\x00\u007f\xaa= \x00\x00\x00\x00\x81I\x85\xa0\x00\x00\x00\x00\x81\x80\xe4\xa0\x00\x00\x00\x00\x83 - " + - "\x00\x00\x00\x00\x83NQ\xa0\x00\x00\x00\x00\x84\xed\x9a \x00\x00\x00\x00\x85$\xf9 \x00\x00\x00\x00\x86\xc4A\xa0\x00\x00\x00\x00\x86\xf2f \x00\x00\x00\x00\x88\x91\xae\xa0\x00\x00\x00\x00\x88\xc9\r\xa0\x00\x00\x00\x00" + - "\x8ahV \x00\x00\x00\x00\x8a\x9f\xb5 \x00\x00\x00\x00\x8c>\xfd\xa0\x00\x00\x00\x00\x8cm\" \x00\x00\x00\x00\x8e\fj\xa0\x00\x00\x00\x00\x8eCɠ\x00\x00\x00\x00\x8f\xe3\x12 \x00\x00\x00\x00\x90\x1aq " + - "\x00\x00\x00\x00\x91\xb9\xb9\xa0\x00\x00\x00\x00\x91\xe7\xde \x00\x00\x00\x00\x93\x87&\xa0\x00\x00\x00\x00\x93\xbe\x85\xa0\x00\x00\x00\x00\x95]\xce \x00\x00\x00\x00\x95\x8b\xf2\xa0\x00\x00\x00\x00\x97+; \x00\x00\x00\x00" + - "\x97b\x9a \x00\x00\x00\x00\x99\x01\xe2\xa0\x00\x00\x00\x00\x999A\xa0\x00\x00\x00\x00\x9a؊ \x00\x00\x00\x00\x9b\x06\xae\xa0\x00\x00\x00\x00\x9c\xa5\xf7 \x00\x00\x00\x00\x9c\xddV \x00\x00\x00\x00\x9e|\x9e\xa0" + - "\x00\x00\x00\x00\x9e\xb3\xfd\xa0\x00\x00\x00\x00\xa0SF \x00\x00\x00\x00\xa0\x81j\xa0\x00\x00\x00\x00\xa2 \xb3 \x00\x00\x00\x00\xa2X\x12 \x00\x00\x00\x00\xa3\xf7Z\xa0\x00\x00\x00\x00\xa4%\u007f \x00\x00\x00\x00" + - "\xa5\xc4Ǡ\x00\x00\x00\x00\xa5\xfc&\xa0\x00\x00\x00\x00\xa7\x9bo \x00\x00\x00\x00\xa7\xd2\xce \x00\x00\x00\x00\xa9r\x16\xa0\x00\x00\x00\x00\xa9\xa0; \x00\x00\x00\x00\xab?\x83\xa0\x00\x00\x00\x00\xabv\xe2\xa0" + - "\x00\x00\x00\x00\xad\x16+ \x00\x00\x00\x00\xadM\x8a \x00\x00\x00\x00\xae\xecҠ\x00\x00\x00\x00\xaf\x1a\xf7 \x00\x00\x00\x00\xb0\xba?\xa0\x00\x00\x00\x00\xb0\xf1\x9e\xa0\x00\x00\x00\x00\xb2\x90\xe7 \x00\x00\x00\x00" + - "\xb2\xbf\v\xa0\x00\x00\x00\x00\xb4^T \x00\x00\x00\x00\xb4\x95\xb3 \x00\x00\x00\x00\xb64\xfb\xa0\x00\x00\x00\x00\xb6lZ\xa0\x00\x00\x00\x00\xb8\v\xa3 \x00\x00\x00\x00\xb89Ǡ\x00\x00\x00\x00\xb9\xd9\x10 " + - "\x00\x00\x00\x00\xba\x10o \x00\x00\x00\x00\xbb\xaf\xb7\xa0\x00\x00\x00\x00\xbb\xe7\x16\xa0\x00\x00\x00\x00\xbd\x86_ \x00\x00\x00\x00\xbd\xb4\x83\xa0\x00\x00\x00\x00\xbfS\xcc \x00\x00\x00\x00\xbf\x8b+ \x00\x00\x00\x00" + - "\xc1*s\xa0\x00\x00\x00\x00\xc1X\x98 \x00\x00\x00\x00\xc2\xf7\xe0\xa0\x00\x00\x00\x00\xc3/?\xa0\x00\x00\x00\x00\xc4Έ \x00\x00\x00\x00\xc5\x05\xe7 \x00\x00\x00\x00ƥ/\xa0\x00\x00\x00\x00\xc6\xd3T " + - "\x00\x00\x00\x00\xc8r\x9c\xa0\x00\x00\x00\x00ȩ\xfb\xa0\x00\x00\x00\x00\xcaID \x00\x00\x00\x00ʀ\xa3 \x00\x00\x00\x00\xcc\x1f\xeb\xa0\x00\x00\x00\x00\xccN\x10 \x00\x00\x00\x00\xcd\xedX\xa0\x00\x00\x00\x00" + - "\xce$\xb7\xa0\x00\x00\x00\x00\xcf\xc4\x00 \x00\x00\x00\x00\xcf\xf2$\xa0\x00\x00\x00\x00ёm \x00\x00\x00\x00\xd1\xc8\xcc \x00\x00\x00\x00\xd3h\x14\xa0\x00\x00\x00\x00ӟs\xa0\x00\x00\x00\x00\xd5>\xbc " + - "\x00\x00\x00\x00\xd5l\xe0\xa0\x00\x00\x00\x00\xd7\f) \x00\x00\x00\x00\xd7C\x88 \x00\x00\x00\x00\xd8\xe2Р\x00\x00\x00\x00\xd9\x1a/\xa0\x00\x00\x00\x00ڹx \x00\x00\x00\x00\xda眠\x00\x00\x00\x00" + - "܆\xe5 \x00\x00\x00\x00ܾD \x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04" + - "\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04" + - "\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\xff\xff\xf8\xe4\x00\x00\x00\x00\x0e\x10\x01\x04\x00\x00\x00\x00\x00\b\x00\x00\x0e\x10\x00\x04\x00\x00\x00\x00\x01\bL" + - "MT\x00+01\x00+00\x00\n<+01>-1\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R \x1b\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\r\x00\x1c\x00Africa/Map" + - "utoUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xba\x00\x00\x00\x06\x00\x00\x00\x10\xff\xff\xff\xff\xbcH\xf0\xe0\x00\x00\x00\x00\vѰ\x90\x00\x00\x00\x00\v\xe8\f\x00\x00\x00\x00\x00\fa" + + "G\xf0\x00\x00\x00\x00\r\xc9?\x80\x00\x00\x00\x00\x0e\x8e\xf2p\x00\x00\x00\x00\x0f\xd3Q\x80\x00\x00\x00\x00\x10'\xa3p\x00\x00\x00\x00HA\xe6\x80\x00\x00\x00\x00H\xbb\"p\x00\x00\x00\x00J#\x1a\x00\x00\x00" + + "\x00\x00J\x8d\xd5p\x00\x00\x00\x00K\xdc\xc0\x80\x00\x00\x00\x00L]\xe5p\x00\x00\x00\x00M\x97\xb8\x80\x00\x00\x00\x00N4\x8c\xf0\x00\x00\x00\x00O\x9c\xa0\xa0\x00\x00\x00\x00P\b\xbb\xa0\x00\x00\x00\x00P1" + + "\x9a \x00\x00\x00\x00Pg\xa7\xa0\x00\x00\x00\x00Q|\x82\xa0\x00\x00\x00\x00Q\xd8ˠ\x00\x00\x00\x00R\x05\x9e\xa0\x00\x00\x00\x00Rls\xa0\x00\x00\x00\x00S7z\xa0\x00\x00\x00\x00S\xae!\xa0\x00\x00" + + "\x00\x00S\xdcF \x00\x00\x00\x00TLU\xa0\x00\x00\x00\x00U\x17\\\xa0\x00\x00\x00\x00U|\xe0 \x00\x00\x00\x00U\xab\x04\xa0\x00\x00\x00\x00V,7\xa0\x00\x00\x00\x00V\xf7>\xa0\x00\x00\x00\x00WS" + + "\x87\xa0\x00\x00\x00\x00W\x81\xac \x00\x00\x00\x00X\x15T \x00\x00\x00\x00X\xd7 \xa0\x00\x00\x00\x00Y \xf4\xa0\x00\x00\x00\x00YXS\xa0\x00\x00\x00\x00Y\xf56 \x00\x00\x00\x00Z\xb7\x02\xa0\x00\x00" + + "\x00\x00Z\xf7\x9c \x00\x00\x00\x00[%\xc0\xa0\x00\x00\x00\x00[\xd5\x18 \x00\x00\x00\x00\\\xceC\xa0\x00\x00\x00\x00\\\xfch \x00\x00\x00\x00^\x9b\xb0\xa0\x00\x00\x00\x00^\xd3\x0f\xa0\x00\x00\x00\x00`r" + + "X \x00\x00\x00\x00`\xa0|\xa0\x00\x00\x00\x00b?\xc5 \x00\x00\x00\x00bw$ \x00\x00\x00\x00d\x16l\xa0\x00\x00\x00\x00dMˠ\x00\x00\x00\x00e\xed\x14 \x00\x00\x00\x00f\x1b8\xa0\x00\x00" + + "\x00\x00g\xba\x81 \x00\x00\x00\x00g\xf1\xe0 \x00\x00\x00\x00i\x91(\xa0\x00\x00\x00\x00i\xbfM \x00\x00\x00\x00kg\xd0 \x00\x00\x00\x00k\x95\xf4\xa0\x00\x00\x00\x00m5= \x00\x00\x00\x00ml" + + "\x9c \x00\x00\x00\x00o\v\xe4\xa0\x00\x00\x00\x00o:\t \x00\x00\x00\x00p\xd9Q\xa0\x00\x00\x00\x00q\x10\xb0\xa0\x00\x00\x00\x00r\xaf\xf9 \x00\x00\x00\x00r\xe7X \x00\x00\x00\x00t\x86\xa0\xa0\x00\x00" + + "\x00\x00t\xb4\xc5 \x00\x00\x00\x00vT\r\xa0\x00\x00\x00\x00v\x8bl\xa0\x00\x00\x00\x00x*\xb5 \x00\x00\x00\x00xX٠\x00\x00\x00\x00y\xf8\" \x00\x00\x00\x00z/\x81 \x00\x00\x00\x00{\xce" + + "ɠ\x00\x00\x00\x00|\x06(\xa0\x00\x00\x00\x00}\xa5q \x00\x00\x00\x00}ӕ\xa0\x00\x00\x00\x00\u007fr\xde \x00\x00\x00\x00\u007f\xaa= \x00\x00\x00\x00\x81I\x85\xa0\x00\x00\x00\x00\x81\x80\xe4\xa0\x00\x00" + + "\x00\x00\x83 - \x00\x00\x00\x00\x83NQ\xa0\x00\x00\x00\x00\x84\xed\x9a \x00\x00\x00\x00\x85$\xf9 \x00\x00\x00\x00\x86\xc4A\xa0\x00\x00\x00\x00\x86\xf2f \x00\x00\x00\x00\x88\x91\xae\xa0\x00\x00\x00\x00\x88\xc9" + + "\r\xa0\x00\x00\x00\x00\x8ahV \x00\x00\x00\x00\x8a\x9f\xb5 \x00\x00\x00\x00\x8c>\xfd\xa0\x00\x00\x00\x00\x8cm\" \x00\x00\x00\x00\x8e\fj\xa0\x00\x00\x00\x00\x8eCɠ\x00\x00\x00\x00\x8f\xe3\x12 \x00\x00" + + "\x00\x00\x90\x1aq \x00\x00\x00\x00\x91\xb9\xb9\xa0\x00\x00\x00\x00\x91\xe7\xde \x00\x00\x00\x00\x93\x87&\xa0\x00\x00\x00\x00\x93\xbe\x85\xa0\x00\x00\x00\x00\x95]\xce \x00\x00\x00\x00\x95\x8b\xf2\xa0\x00\x00\x00\x00\x97+" + + "; \x00\x00\x00\x00\x97b\x9a \x00\x00\x00\x00\x99\x01\xe2\xa0\x00\x00\x00\x00\x999A\xa0\x00\x00\x00\x00\x9a؊ \x00\x00\x00\x00\x9b\x06\xae\xa0\x00\x00\x00\x00\x9c\xa5\xf7 \x00\x00\x00\x00\x9c\xddV \x00\x00" + + "\x00\x00\x9e|\x9e\xa0\x00\x00\x00\x00\x9e\xb3\xfd\xa0\x00\x00\x00\x00\xa0SF \x00\x00\x00\x00\xa0\x81j\xa0\x00\x00\x00\x00\xa2 \xb3 \x00\x00\x00\x00\xa2X\x12 \x00\x00\x00\x00\xa3\xf7Z\xa0\x00\x00\x00\x00\xa4%" + + "\u007f \x00\x00\x00\x00\xa5\xc4Ǡ\x00\x00\x00\x00\xa5\xfc&\xa0\x00\x00\x00\x00\xa7\x9bo \x00\x00\x00\x00\xa7\xd2\xce \x00\x00\x00\x00\xa9r\x16\xa0\x00\x00\x00\x00\xa9\xa0; \x00\x00\x00\x00\xab?\x83\xa0\x00\x00" + + "\x00\x00\xabv\xe2\xa0\x00\x00\x00\x00\xad\x16+ \x00\x00\x00\x00\xadM\x8a \x00\x00\x00\x00\xae\xecҠ\x00\x00\x00\x00\xaf\x1a\xf7 \x00\x00\x00\x00\xb0\xba?\xa0\x00\x00\x00\x00\xb0\xf1\x9e\xa0\x00\x00\x00\x00\xb2\x90" + + "\xe7 \x00\x00\x00\x00\xb2\xbf\v\xa0\x00\x00\x00\x00\xb4^T \x00\x00\x00\x00\xb4\x95\xb3 \x00\x00\x00\x00\xb64\xfb\xa0\x00\x00\x00\x00\xb6lZ\xa0\x00\x00\x00\x00\xb8\v\xa3 \x00\x00\x00\x00\xb89Ǡ\x00\x00" + + "\x00\x00\xb9\xd9\x10 \x00\x00\x00\x00\xba\x10o \x00\x00\x00\x00\xbb\xaf\xb7\xa0\x00\x00\x00\x00\xbb\xe7\x16\xa0\x00\x00\x00\x00\xbd\x86_ \x00\x00\x00\x00\xbd\xb4\x83\xa0\x00\x00\x00\x00\xbfS\xcc \x00\x00\x00\x00\xbf\x8b" + + "+ \x00\x00\x00\x00\xc1*s\xa0\x00\x00\x00\x00\xc1X\x98 \x00\x00\x00\x00\xc2\xf7\xe0\xa0\x00\x00\x00\x00\xc3/?\xa0\x00\x00\x00\x00\xc4Έ \x00\x00\x00\x00\xc5\x05\xe7 \x00\x00\x00\x00ƥ/\xa0\x00\x00" + + "\x00\x00\xc6\xd3T \x00\x00\x00\x00\xc8r\x9c\xa0\x00\x00\x00\x00ȩ\xfb\xa0\x00\x00\x00\x00\xcaID \x00\x00\x00\x00ʀ\xa3 \x00\x00\x00\x00\xcc\x1f\xeb\xa0\x00\x00\x00\x00\xccN\x10 \x00\x00\x00\x00\xcd\xed" + + "X\xa0\x00\x00\x00\x00\xce$\xb7\xa0\x00\x00\x00\x00\xcf\xc4\x00 \x00\x00\x00\x00\xcf\xf2$\xa0\x00\x00\x00\x00ёm \x00\x00\x00\x00\xd1\xc8\xcc \x00\x00\x00\x00\xd3h\x14\xa0\x00\x00\x00\x00ӟs\xa0\x00\x00" + + "\x00\x00\xd5>\xbc \x00\x00\x00\x00\xd5l\xe0\xa0\x00\x00\x00\x00\xd7\f) \x00\x00\x00\x00\xd7C\x88 \x00\x00\x00\x00\xd8\xe2Р\x00\x00\x00\x00\xd9\x1a/\xa0\x00\x00\x00\x00ڹx \x00\x00\x00\x00\xda\xe7" + + "\x9c\xa0\x00\x00\x00\x00܆\xe5 \x00\x00\x00\x00ܾD \x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05" + + "\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05" + + "\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\xff\xff\xf3\xa0\x00\x00\xff\xff\xf1\xf0\x00\x04\x00\x00\x0e\x10\x01\b\x00\x00\x00\x00\x00\f\x00\x00\x00\x00\x01\f\x00\x00\x0e\x10\x00\b" + + "LMT\x00-01\x00+01\x00+00\x00\n<+01>-1\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS \x1b\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\r\x00\x1c\x00Afric" + + "a/LusakaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x82F\xc5\xf4\x01\x00\x00\x1e\x8c\x00\x00\x00\x00\x1c \x00\x04LMT\x00CAT\x00\nCAT-2\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82i" + + "S\x93\xf4\x94\v\xc1\x01\x00\x00\xc1\x01\x00\x00\f\x00\x1c\x00Africa/TunisUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZi" + + "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\"\x00\x00\x00\x04\x00\x00\x00\x11\xff\xff\xff\xffYF\x13\xf4\xff\xff\xff\xff\x91`PO\xff\xff\xff\xff\xc6:\x88\xe0\xff\xff\xff\xff" + + "\xc7X\x9e`\xff\xff\xff\xff\xc7\xdb\"\xe0\xff\xff\xff\xff\xca\xe2T\xe0\xff\xff\xff\xff˭i\xf0\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\xcd\xc2\x16\x00\xff\xff\xff\xff\xcd̰\x10" + + "\xff\xff\xff\xff\u03a25\x00\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЉ\xe3\xe0\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd2N\x16`\x00\x00\x00\x00\r\xc7\xdf\xf0\x00\x00\x00\x00\x0e\x89\xacp\x00\x00\x00\x00" + + "\x0f\xaad\xf0\x00\x00\x00\x00\x10t\x1ap\x00\x00\x00\x00\"\xa3:\xf0\x00\x00\x00\x00#<(\xf0\x00\x00\x00\x00$,\x19\xf0\x00\x00\x00\x00%\x1c\n\xf0\x00\x00\x00\x00&<\xc3p\x00\x00\x00\x00'\x05'p" + + "\x00\x00\x00\x00Bt\r\xf0\x00\x00\x00\x00C<\x80\x00\x00\x00\x00\x00D%\xe7\x90\x00\x00\x00\x00EC\xfd\x10\x00\x00\x00\x00F\x05ɐ\x00\x00\x00\x00G#\xdf\x10\x00\x00\x00\x00G\xee\xe6\x10\x00\x00\x00\x00" + + "I\x03\xc1\x10\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x00\x00\t\x8c\x00\x00\x00\x00\x021\x00\x04\x00\x00\x1c \x01\b\x00\x00\x0e\x10" + + "\x00\rLMT\x00PMT\x00CEST\x00CET\x00\nCET-1\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xcc\fTξ\x00\x00\x00\xbe\x00\x00\x00\r\x00\x1c\x00Afri" + + "ca/MaseruUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\t\xff\xff\xff\xffm{A@\xff\xff\xff\xff\x82F\xcfh\xff\xff\xff\xff̮\x8c\x80\xff\xff\xff\xff͞op\xff\xff\xff\xffΎn\x80\xff\xff\xff\xff\xcf~Qp" + + "\x01\x03\x02\x03\x02\x03\x00\x00\x1a@\x00\x00\x00\x00\x15\x18\x00\x04\x00\x00*0\x01\x04\x00\x00\x1c \x00\x04LMT\x00SAST\x00\nSAST-2\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82i" + + "S\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\v\x00\x1c\x00Africa/LomeUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif" + + "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x92\xe6\x92H\x01\xff\xff\xfc8\x00\x00\x00\x00\x00\x00\x00\x04LMT\x00GMT\x00" + + "\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\r\x00\x1c\x00Africa/DoualaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f" + + "\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" + + "\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xff\x86\xabp\xd1" + + "\xff\xff\xff\xff\x8cP`\x00\xff\xff\xff\xff\x96\xaaC\xd1\xff\xff\xff\xff\xa1Q\xefx\x01\x00\x02\x03\x00\x00\x03/\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\a\b\x00\b\x00\x00\x0e\x10\x00\x0eLMT\x00GMT\x00" + + "+0030\x00WAT\x00\nWAT-1\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS \x1b\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\x10\x00\x1c\x00Africa/Bujumb" + + "uraUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00" + - "\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x82F\xc5\xf4\x01\x00\x00\x1e\x8c\x00\x00\x00\x00\x1c \x00\x04LMT\x00CAT\x00\nCAT-2\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xa7\x1d\xb3c" + - "\xb4\x00\x00\x00\xb4\x00\x00\x00\f\x00\x1c\x00Africa/LagosUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xff\x86\xabp\xd1\xff\xff\xff\xff\x8cP`\x00\xff\xff\xff\xff\x96\xaaC\xd1\xff\xff\xff\xff\xa1Q\xefx\x01" + - "\x00\x02\x03\x00\x00\x03/\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\a\b\x00\b\x00\x00\x0e\x10\x00\x0eLMT\x00GMT\x00+0030\x00WAT\x00\nWAT-1\nPK\x03\x04\n\x00\x00\x00" + - "\x00\x00\xf1c9R\xcc\fTξ\x00\x00\x00\xbe\x00\x00\x00\r\x00\x1c\x00Africa/MaseruUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8" + - "\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\t\xff\xff\xff\xffm{A@\xff\xff\xff\xff\x82F\xcfh\xff\xff\xff\xff̮" + - "\x8c\x80\xff\xff\xff\xff͞op\xff\xff\xff\xffΎn\x80\xff\xff\xff\xff\xcf~Qp\x01\x03\x02\x03\x02\x03\x00\x00\x1a@\x00\x00\x00\x00\x15\x18\x00\x04\x00\x00*0\x01\x04\x00\x00\x1c \x00\x04LMT\x00" + - "SAST\x00\nSAST-2\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\x11\x00\x1c\x00Africa/Porto-Novo" + - "UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00" + - "\x00\x00\x12\xff\xff\xff\xff\x86\xabp\xd1\xff\xff\xff\xff\x8cP`\x00\xff\xff\xff\xff\x96\xaaC\xd1\xff\xff\xff\xff\xa1Q\xefx\x01\x00\x02\x03\x00\x00\x03/\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\a\b\x00\b\x00\x00\x0e" + - "\x10\x00\x0eLMT\x00GMT\x00+0030\x00WAT\x00\nWAT-1\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\x0e\x00\x1c\x00Af" + - "rica/ConakryUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x82F\xc5\xf4\x01\x00\x00\x1e\x8c\x00\x00\x00\x00\x1c \x00\x04LMT\x00CAT\x00\nCAT-2\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSV\xadD\xef" + + "\xca\x01\x00\x00\xca\x01\x00\x00\x0f\x00\x1c\x00Africa/KhartoumUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00#\x00\x00\x00\x04\x00\x00\x00\x11\xff\xff\xff\xff\xb6\xa3\xda\x00\x00\x00\x00\x00\x00\x9e\x17\xe0\x00\x00\x00\x00\x01z4P\x00\x00\x00\x00\x02}" + + "\xf9\xe0\x00\x00\x00\x00\x03[g\xd0\x00\x00\x00\x00\x04`~\xe0\x00\x00\x00\x00\x05=\xec\xd0\x00\x00\x00\x00\x06@`\xe0\x00\x00\x00\x00\a\x1f P\x00\x00\x00\x00\b B\xe0\x00\x00\x00\x00\t\x00S\xd0\x00\x00" + + "\x00\x00\n\x00$\xe0\x00\x00\x00\x00\n\xe1\x87P\x00\x00\x00\x00\v\xe0\x06\xe0\x00\x00\x00\x00\f\xc4\fP\x00\x00\x00\x00\r\xbf\xe8\xe0\x00\x00\x00\x00\x0e\xa5?\xd0\x00\x00\x00\x00\x0f\xa9\x05`\x00\x00\x00\x00\x10\x86" + + "sP\x00\x00\x00\x00\x11\x88\xe7`\x00\x00\x00\x00\x12g\xa6\xd0\x00\x00\x00\x00\x13h\xc9`\x00\x00\x00\x00\x14J+\xd0\x00\x00\x00\x00\x15H\xab`\x00\x00\x00\x00\x16+_P\x00\x00\x00\x00\x17(\x8d`\x00\x00" + + "\x00\x00\x18\f\x92\xd0\x00\x00\x00\x00\x19\bo`\x00\x00\x00\x00\x19\xed\xc6P\x00\x00\x00\x00\x1a\xf1\x8b\xe0\x00\x00\x00\x00\x1b\xd0KP\x00\x00\x00\x00\x1c\xd1m\xe0\x00\x00\x00\x00\x1d\xb1~\xd0\x00\x00\x00\x008\x80" + + "E \x00\x00\x00\x00Y\xf8\xe4P\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x02\x00\x00\x1e\x80\x00\x00\x00\x00*0\x01\x04\x00\x00\x1c" + + " \x00\t\x00\x00*0\x00\rLMT\x00CAST\x00CAT\x00EAT\x00\nCAT-2\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\r" + + "\x00\x1c\x00Africa/AsmaraUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\x14\xff\xff\xff\xff\x8b\xff\xd1\xfc\xff\xff\xff\xff\xb1\xee\xdaX\xff\xff\xff\xff\xb4\xc7\xe0\xd0\xff\xff\xff\xff\xc1\xed\xadX\xff\xff\xff\xff\xcclz\xd4\x01" + + "\x02\x01\x03\x02\x00\x00\"\x84\x00\x00\x00\x00#(\x00\x04\x00\x00*0\x00\n\x00\x00&\xac\x00\x0eLMT\x00+0230\x00EAT\x00+0245\x00\nEAT-3\nPK\x03\x04\n" + + "\x00\x00\x00\x00\x00#\x82iS\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\x0e\x00\x1c\x00Africa/ConakryUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E" + + "\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + + "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x92\xe6\x92H\x01\xff\xff\xfc8\x00\x00\x00\x00\x00" + + "\x00\x00\x04LMT\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSÊ\x0e\xc0\xd6\x01\x00\x00\xd6\x01\x00\x00\x0e\x00\x1c\x00Africa/Algier" + + "sUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\"\x00\x00\x00\x06" + + "\x00\x00\x00\x1a\xff\xff\xff\xffkɛ$\xff\xff\xff\xff\x91`PO\xff\xff\xff\xff\x9bGx\xf0\xff\xff\xff\xff\x9b\xd7,p\xff\xff\xff\xff\x9c\xbc\x91p\xff\xff\xff\xff\x9d\xc0H\xf0\xff\xff\xff\xff\x9e\x89\xfep" + + "\xff\xff\xff\xff\x9f\xa0*\xf0\xff\xff\xff\xff\xa0`\xa5\xf0\xff\xff\xff\xff\xa1\x80\f\xf0\xff\xff\xff\xff\xa2.\x12\xf0\xff\xff\xff\xff\xa3zL\xf0\xff\xff\xff\xff\xa45\x81\xf0\xff\xff\xff\xff\xa4\xb8\x06p\xff\xff\xff\xff" + + "\xc6\xff\x06p\xff\xff\xff\xff\xc7X\xba\x80\xff\xff\xff\xff\xc7\xda\t\xa0\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЊ\x00\x00\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd2N$p\xff\xff\xff\xff\xd4K\ap" + + "\xff\xff\xff\xff\xe5\xce\xd3\x00\xff\xff\xff\xff\xf3\\\xb0\xf0\x00\x00\x00\x00\x02x\xc1\xf0\x00\x00\x00\x00\x03C\xc8\xf0\x00\x00\x00\x00\r\xcf\xd7\x00\x00\x00\x00\x00\x0e\xadD\xf0\x00\x00\x00\x00\x0fxZ\x00\x00\x00\x00\x00" + + "\x10hY\x10\x00\x00\x00\x00\x12vCp\x00\x00\x00\x00\x13fB\x80\x00\x00\x00\x00\x14_|\x10\x00\x00\x00\x00\x15O_\x00\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x05\x04\x05\x04\x05\x03\x05\x03" + + "\x02\x03\x02\x05\x04\x05\x03\x02\x03\x05\x00\x00\x02\xdc\x00\x00\x00\x00\x021\x00\x04\x00\x00\x0e\x10\x01\b\x00\x00\x00\x00\x00\r\x00\x00\x1c \x01\x11\x00\x00\x0e\x10\x00\x16LMT\x00PMT\x00WEST\x00W" + + "ET\x00CEST\x00CET\x00\nCET-1\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\r\x00\x1c\x00Africa/Bang" + + "uiUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00" + + "\x04\x00\x00\x00\x12\xff\xff\xff\xff\x86\xabp\xd1\xff\xff\xff\xff\x8cP`\x00\xff\xff\xff\xff\x96\xaaC\xd1\xff\xff\xff\xff\xa1Q\xefx\x01\x00\x02\x03\x00\x00\x03/\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\a\b\x00\b\x00" + + "\x00\x0e\x10\x00\x0eLMT\x00GMT\x00+0030\x00WAT\x00\nWAT-1\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\x11\x00\x1c\x00" + + "Africa/LibrevilleUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xff\x86\xabp\xd1\xff\xff\xff\xff\x8cP`\x00\xff\xff\xff\xff\x96\xaaC\xd1\xff\xff\xff\xff\xa1Q\xefx\x01\x00\x02\x03\x00\x00\x03/" + + "\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\a\b\x00\b\x00\x00\x0e\x10\x00\x0eLMT\x00GMT\x00+0030\x00WAT\x00\nWAT-1\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x14" + + "\xcf\x10n\xca\x01\x00\x00\xca\x01\x00\x00\v\x00\x1c\x00Africa/JubaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00#\x00\x00\x00\x04\x00\x00\x00\x11\xff\xff\xff\xff\xb6\xa3\xda\xdc\x00\x00\x00\x00\x00\x9e\x17\xe0\x00\x00\x00\x00\x01z4P\x00\x00\x00\x00\x02}\xf9" + + "\xe0\x00\x00\x00\x00\x03[g\xd0\x00\x00\x00\x00\x04`~\xe0\x00\x00\x00\x00\x05=\xec\xd0\x00\x00\x00\x00\x06@`\xe0\x00\x00\x00\x00\a\x1f P\x00\x00\x00\x00\b B\xe0\x00\x00\x00\x00\t\x00S\xd0\x00\x00\x00" + + "\x00\n\x00$\xe0\x00\x00\x00\x00\n\xe1\x87P\x00\x00\x00\x00\v\xe0\x06\xe0\x00\x00\x00\x00\f\xc4\fP\x00\x00\x00\x00\r\xbf\xe8\xe0\x00\x00\x00\x00\x0e\xa5?\xd0\x00\x00\x00\x00\x0f\xa9\x05`\x00\x00\x00\x00\x10\x86s" + + "P\x00\x00\x00\x00\x11\x88\xe7`\x00\x00\x00\x00\x12g\xa6\xd0\x00\x00\x00\x00\x13h\xc9`\x00\x00\x00\x00\x14J+\xd0\x00\x00\x00\x00\x15H\xab`\x00\x00\x00\x00\x16+_P\x00\x00\x00\x00\x17(\x8d`\x00\x00\x00" + + "\x00\x18\f\x92\xd0\x00\x00\x00\x00\x19\bo`\x00\x00\x00\x00\x19\xed\xc6P\x00\x00\x00\x00\x1a\xf1\x8b\xe0\x00\x00\x00\x00\x1b\xd0KP\x00\x00\x00\x00\x1c\xd1m\xe0\x00\x00\x00\x00\x1d\xb1~\xd0\x00\x00\x00\x008\x80E" + + " \x00\x00\x00\x00`\x17\x1aP\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x02\x00\x00\x1d\xa4\x00\x00\x00\x00*0\x01\x04\x00\x00\x1c " + + "\x00\t\x00\x00*0\x00\rLMT\x00CAST\x00CAT\x00EAT\x00\nCAT-2\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS6\x99rU\xa4\x00\x00\x00\xa4\x00\x00\x00\x0f\x00" + + "\x1c\x00Africa/MonroviaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\f\xff\xff\xff\xffZz\xa6\x9c\xff\xff\xff\xff\xa0_l\x9c\x00\x00\x00\x00\x03\xcaZn\x01\x02\x03\xff\xff\xf5\xe4\x00\x00\xff\xff\xf5\xe4\x00\x04\xff" + + "\xff\xf5\x92\x00\x04\x00\x00\x00\x00\x00\bLMT\x00MMT\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\x0f\x00\x1c\x00A" + + "frica/DjiboutiUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\x14\xff\xff\xff\xff\x8b\xff\xd1\xfc\xff\xff\xff\xff\xb1\xee\xdaX\xff\xff\xff\xff\xb4\xc7\xe0\xd0\xff\xff\xff\xff\xc1\xed\xadX\xff\xff\xff\xff\xcclz\xd4\x01\x02\x01" + + "\x03\x02\x00\x00\"\x84\x00\x00\x00\x00#(\x00\x04\x00\x00*0\x00\n\x00\x00&\xac\x00\x0eLMT\x00+0230\x00EAT\x00+0245\x00\nEAT-3\nPK\x03\x04\n\x00\x00" + + "\x00\x00\x00#\x82iS\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\x0f\x00\x1c\x00Africa/TimbuktuUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00" + + "\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZi" + + "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x92\xe6\x92H\x01\xff\xff\xfc8\x00\x00\x00\x00\x00\x00" + + "\x00\x04LMT\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\r\x00\x1c\x00Africa/MalaboU" + + "T\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00" + + "\x00\x12\xff\xff\xff\xff\x86\xabp\xd1\xff\xff\xff\xff\x8cP`\x00\xff\xff\xff\xff\x96\xaaC\xd1\xff\xff\xff\xff\xa1Q\xefx\x01\x00\x02\x03\x00\x00\x03/\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\a\b\x00\b\x00\x00\x0e\x10" + + "\x00\x0eLMT\x00GMT\x00+0030\x00WAT\x00\nWAT-1\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\x0f\x00\x1c\x00Afr" + + "ica/FreetownUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x92\xe6\x92H\x01\xff\xff\xfc8\x00\x00\x00\x00\x00\x00\x00\x04LMT\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00" + - "\xf1c9R\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\r\x00\x1c\x00Africa/DoualaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00" + + "#\x82iS\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\r\x00\x1c\x00Africa/BanjulUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01" + "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xff\x86\xabp\xd1\xff\xff\xff\xff\x8cP`\x00\xff\xff\xff\xff\x96\xaaC\xd1" + - "\xff\xff\xff\xff\xa1Q\xefx\x01\x00\x02\x03\x00\x00\x03/\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\a\b\x00\b\x00\x00\x0e\x10\x00\x0eLMT\x00GMT\x00+0030\x00WAT\x00\nWAT-1" + - "\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\x10\x00\x1c\x00Africa/MogadishuUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`" + - "ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00" + - "\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\x14\xff\xff\xff\xff\x8b\xff\xd1\xfc\xff\xff" + - "\xff\xff\xb1\xee\xdaX\xff\xff\xff\xff\xb4\xc7\xe0\xd0\xff\xff\xff\xff\xc1\xed\xadX\xff\xff\xff\xff\xcclz\xd4\x01\x02\x01\x03\x02\x00\x00\"\x84\x00\x00\x00\x00#(\x00\x04\x00\x00*0\x00\n\x00\x00&\xac\x00\x0eL" + - "MT\x00+0230\x00EAT\x00+0245\x00\nEAT-3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\f\x00\x1c\x00Afri" + - "ca/DakarUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x92\xe6\x92H\x01\xff\xff\xfc8\x00\x00\x00\x00\x00\x00\x00\x04LMT\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R" + - "_\u007f2[\xaf\x01\x00\x00\xaf\x01\x00\x00\x0e\x00\x1c\x00Africa/TripoliUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZ" + - "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x04\x00\x00\x00\x11\xff\xff\xff\xff\xa1\xf2\xc1$\xff\xff\xff\xffݻ\xb1\x10\xff\xff\xff\xff\xde#\xad`\xff\xff\xff" + - "\xff\xe1x\xd2\x10\xff\xff\xff\xff\xe1\xe7e\xe0\xff\xff\xff\xff\xe5/?p\xff\xff\xff\xff\xe5\xa9\xcc\xe0\xff\xff\xff\xff\xebN\xc6\xf0\x00\x00\x00\x00\x16\x92B`\x00\x00\x00\x00\x17\b\xf7p\x00\x00\x00\x00\x17\xfa+" + - "\xe0\x00\x00\x00\x00\x18\xea*\xf0\x00\x00\x00\x00\x19\xdb_`\x00\x00\x00\x00\x1a̯\xf0\x00\x00\x00\x00\x1b\xbd\xe4`\x00\x00\x00\x00\x1c\xb4z\xf0\x00\x00\x00\x00\x1d\x9f\x17\xe0\x00\x00\x00\x00\x1e\x93\vp\x00\x00\x00" + - "\x00\x1f\x82\xee`\x00\x00\x00\x00 pJp\x00\x00\x00\x00!a~\xe0\x00\x00\x00\x00\"R\xcfp\x00\x00\x00\x00#D\x03\xe0\x00\x00\x00\x00$4\x02\xf0\x00\x00\x00\x00%%7`\x00\x00\x00\x00&@\xb7" + - "\xf0\x00\x00\x00\x002N\xf1`\x00\x00\x00\x003D6p\x00\x00\x00\x0045j\xe0\x00\x00\x00\x00P\x9d\x99\x00\x00\x00\x00\x00QTـ\x00\x00\x00\x00Ri\xb4\x80\x02\x01\x02\x01\x02\x01\x02\x03\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x02\x01\x03\x02\x01\x03\x00\x00\f\\\x00\x00\x00\x00\x1c \x01\x04\x00\x00\x0e\x10\x00\t\x00\x00\x1c \x00\rLMT\x00CEST\x00CET\x00EE" + - "T\x00\nEET-2\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R \x1b\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\r\x00\x1c\x00Africa/HarareUT\t\x00\x03\x15\xac\x0e" + - "`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x92\xe6\x92H\x01\xff\xff\xfc8\x00\x00\x00\x00\x00\x00\x00\x04LMT" + + "\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS \x1b\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\r\x00\x1c\x00Africa/KigaliUT\t\x00\x03\x82" + + "\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff" + + "\xff\x82F\xc5\xf4\x01\x00\x00\x1e\x8c\x00\x00\x00\x00\x1c \x00\x04LMT\x00CAT\x00\nCAT-2\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xca>\xd5\xe0\x95\x00\x00\x00\x95\x00\x00\x00\r" + + "\x00\x1c\x00Africa/BissauUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x92朐\x00\x00\x00\x00\tga\x10\x01\x02\xff\xff\xf1d\x00\x00\xff\xff\xf1\xf0\x00\x04\x00\x00\x00\x00\x00\bLMT\x00-" + + "01\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xcc\fTξ\x00\x00\x00\xbe\x00\x00\x00\x0e\x00\x1c\x00Africa/MbabaneUT\t" + + "\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\t" + + "\xff\xff\xff\xffm{A@\xff\xff\xff\xff\x82F\xcfh\xff\xff\xff\xff̮\x8c\x80\xff\xff\xff\xff͞op\xff\xff\xff\xffΎn\x80\xff\xff\xff\xff\xcf~Qp\x01\x03\x02\x03\x02\x03\x00\x00\x1a@\x00\x00" + + "\x00\x00\x15\x18\x00\x04\x00\x00*0\x01\x04\x00\x00\x1c \x00\x04LMT\x00SAST\x00\nSAST-2\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x9f\x1b\xeb\xdd2\x02\x00\x002\x02\x00" + + "\x00\f\x00\x1c\x00Africa/CeutaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00\x05\x00\x00\x00\x16\xff\xff\xff\xff~6\xb5\x00\xff\xff\xff\xff\x9e\xd6up\xff\xff\xff\xff\x9f\xa1n`\xff\xff\xff\xff\xaa\x05\xefp\xff\xff\xff\xff\xaa\xe7n\x00" + + "\xff\xff\xff\xff\xadɧ\xf0\xff\xff\xff\xff\xae\xa72\x00\xff\xff\xff\xff\xaf\xa0Op\xff\xff\xff\xff\xb0\x87\x14\x00\xff\xff\xff\xff\xb1\x89z\x00\xff\xff\xff\xff\xb2p0\x80\xff\xff\xff\xff\xfb%r@\xff\xff\xff\xff" + + "\xfb\xc2\xefp\x00\x00\x00\x00\bk\x84\x80\x00\x00\x00\x00\b\xc6m\xf0\x00\x00\x00\x00\v\xe8\f\x00\x00\x00\x00\x00\faG\xf0\x00\x00\x00\x00\r\xc9?\x80\x00\x00\x00\x00\x0e\x8e\xf2p\x00\x00\x00\x00\x0f\xd3Q\x80" + + "\x00\x00\x00\x00\x10'\xa3p\x00\x00\x00\x00\x1a\xb7\xa6\x00\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00" + + "#\x8fn\x00\x00\x00\x00\x00?Z\x83" + - "\x10\x00\x00\x00\x00@oP\x00\x00\x00\x00\x00A:e\x10\x00\x00\x00\x00BO2\x00\x00\x00\x00\x00C\x1aG\x10\x00\x00\x00\x00D/\x14\x00\x00\x00\x00\x00D\xfa)\x10\x00\x00\x00\x00F\x0e\xf6\x00\x00\x00\x00" + - "\x00F\xda\v\x10\x00\x00\x00\x00G\xf8\x12\x80\x00\x00\x00\x00H\xc3'\x90\x00\x00\x00\x00I\xd7\xf4\x80\x00\x00\x00\x00J\xa3\t\x90\x00\x00\x00\x00K\xb7ր\x00\x00\x00\x00L\x82\xeb\x90\x00\x00\x00\x00M\x97\xb8" + - "\x80\x00\x00\x00\x00Nb͐\x00\x00\x00\x00Ow\x9a\x80\x00\x00\x00\x00PB\xaf\x90\x00\x00\x00\x00Q`\xb7\x00\x00\x00\x00\x00R\"\x91\x90\x00\x00\x00\x00S@\x99\x00\x00\x00\x00\x00T\v\xae\x10\x00\x00\x00" + - "\x00U {\x00\x00\x00\x00\x00U\xeb\x90\x10\x00\x00\x00\x00W\x00]\x00\x00\x00\x00\x00W\xcbr\x10\x00\x00\x00\x00X\xe0?\x00\x00\x00\x00\x00Y\xabT\x10\x01\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05" + - "\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x00\x00\x10\b\x00\x00\x00\x00\x15\x18\x00\x04\x00\x00\x1c \x00\n\x00\x00*0" + - "\x01\n\x00\x00\x0e\x10\x01\x0f\x00\x00\x1c \x00\x13LMT\x00+0130\x00SAST\x00WAT\x00CAT\x00\nCAT-2\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xee\xc4" + - "h2\xbc\x02\x00\x00\xbc\x02\x00\x00\f\x00\x1c\x00Africa/AccraUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\x9a\x1d\x944\xff\xff\xff\xff\xa1\xc0\xb4\x80\xff\xff\xff\xff\xa1\xf2\xe4\xf0\xff\xff\xff\xff\xa34\x97" + - "\xa0\xff\xff\xff\xff\xa3\xd5i\xf0\xff\xff\xff\xff\xa5\x15\xcb \xff\xff\xff\xff\xa5\xb6\x9dp\xff\xff\xff\xff\xa6\xf6\xfe\xa0\xff\xff\xff\xff\xa7\x97\xd0\xf0\xff\xff\xff\xff\xa8\xd82 \xff\xff\xff\xff\xa9y\x04p\xff\xff\xff" + - "\xff\xaa\xba\xb7 \xff\xff\xff\xff\xab[\x89p\xff\xff\xff\xff\xac\x9b\xea\xa0\xff\xff\xff\xff\xad<\xbc\xf0\xff\xff\xff\xff\xae}\x1e \xff\xff\xff\xff\xaf\x1d\xf0p\xff\xff\xff\xff\xb0^Q\xa0\xff\xff\xff\xff\xb0\xff#" + - "\xf0\xff\xff\xff\xff\xb2@֠\xff\xff\xff\xff\xb2\xe1\xa8\xf0\xff\xff\xff\xff\xb4\"\n \xff\xff\xff\xff\xb4\xc2\xdcp\xff\xff\xff\xff\xb6\x03=\xa0\xff\xff\xff\xff\xb6\xa4\x0f\xf0\xff\xff\xff\xff\xb7\xe4q \xff\xff\xff" + - "\xff\xb8\x85Cp\xff\xff\xff\xff\xb9\xc6\xf6 \xff\xff\xff\xff\xbag\xc8p\xff\xff\xff\xff\xbb\xa8)\xa0\xff\xff\xff\xff\xbcH\xfb\xf0\xff\xff\xff\xff\xbd\x89] \xff\xff\xff\xff\xbe*/p\xff\xff\xff\xff\xbfj\x90" + - "\xa0\xff\xff\xff\xff\xc0\vb\xf0\xff\xff\xff\xff\xc1M\x15\xa0\xff\xff\xff\xff\xc1\xed\xe7\xf0\xff\xff\xff\xff\xc3.I \xff\xff\xff\xff\xc3\xcf\x1bp\xff\xff\xff\xff\xc5\x0f|\xa0\xff\xff\xff\xffŰN\xf0\xff\xff\xff" + - "\xff\xc6\xf0\xb0 \xff\xff\xff\xffǑ\x82p\xff\xff\xff\xff\xc81\f\xa0\xff\xff\xff\xff\xc9t\ap\xff\xff\xff\xff\xca\x12@ \xff\xff\xff\xff\xcbU:\xf0\xff\xff\xff\xffˇ<\x80\xff\xff\xff\xff\xd2\xe1\xd3" + - "x\xff\xff\xff\xffۡ\xdb \xff\xff\xff\xff\xdcB\xab\x18\xff\xff\xff\xff݃\x0e\xa0\xff\xff\xff\xff\xde#ޘ\xff\xff\xff\xff\xdfe\x93\xa0\xff\xff\xff\xff\xe0\x06c\x98\xff\xff\xff\xff\xe1F\xc7 \xff\xff\xff" + - "\xff\xe1\xe7\x97\x18\xff\xff\xff\xff\xe3'\xfa\xa0\xff\xff\xff\xff\xe3\xc8ʘ\xff\xff\xff\xff\xe5\t. \xff\xff\xff\xff\xe5\xa9\xfe\x18\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\xff\xff\xff\xcc\x00\x00\x00\x00\x04\xb0\x01\x04\x00\x00\x00\x00\x00\n\x00\x00\a\b" + - "\x00\x0e\x00\x00\a\b\x01\x0eLMT\x00+0020\x00GMT\x00+0030\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00" + - "\v\x00\x1c\x00Africa/LomeUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x92\xe6\x92H\x01\xff\xff\xfc8\x00\x00\x00\x00\x00\x00\x00\x04LMT\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00" + - "\x00\x00\x00\xf1c9R\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\x0f\x00\x1c\x00Africa/DjiboutiUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00" + - "\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZi" + - "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\x14\xff\xff\xff\xff\x8b\xff\xd1\xfc\xff\xff\xff\xff\xb1\xee\xdaX\xff\xff\xff" + - "\xff\xb4\xc7\xe0\xd0\xff\xff\xff\xff\xc1\xed\xadX\xff\xff\xff\xff\xcclz\xd4\x01\x02\x01\x03\x02\x00\x00\"\x84\x00\x00\x00\x00#(\x00\x04\x00\x00*0\x00\n\x00\x00&\xac\x00\x0eLMT\x00+0230\x00" + - "EAT\x00+0245\x00\nEAT-3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\x00\x1c\x00America/UT\t\x00\x03" + - "\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x82\x13z\xe2\xc2\x00\x00\x00\xc2\x00\x00\x00\x13\x00\x1c\x00America" + - "/TegucigalpaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\xa4LKD\x00\x00\x00\x00 \x9a\xdc\xe0\x00\x00\x00\x00!\\\x9bP\x00\x00\x00\x00\"z\xbe\xe0\x00\x00\x00\x00#<}P\x00\x00\x00\x00D" + - "]\x8c\xe0\x00\x00\x00\x00D\xd6\xc8\xd0\x02\x01\x02\x01\x02\x01\x02\xff\xff\xae<\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\bLMT\x00CDT\x00CST\x00\nCST6\nPK\x03\x04\n\x00" + - "\x00\x00\x00\x00\xf1c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00\x00\x00\x10\x00\x1c\x00America/St_KittsUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8" + - "\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00T" + - "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x9373\xac\x01\xff\xff\xc6T\x00\x00\xff\xff" + - "\xc7\xc0\x00\x04LMT\x00AST\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x13\x00\x1c\x00America/Puer" + - "to_RicoUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x82F\xc5\xf4\x01\x00\x00\x1e\x8c\x00\x00\x00\x00\x1c \x00\x04LMT\x00CAT\x00\nCAT-2\nPK\x03\x04\n\x00\x00" + + "\x00\x00\x00#\x82iS\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\r\x00\x1c\x00Africa/BamakoUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04" + + "S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x92\xe6\x92H\x01\xff\xff\xfc8\x00\x00\x00\x00\x00\x00\x00\x04" + + "LMT\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\f\x00\x1c\x00Africa/LagosUT\t\x00" + + "\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x12\xff" + + "\xff\xff\xff\x86\xabp\xd1\xff\xff\xff\xff\x8cP`\x00\xff\xff\xff\xff\x96\xaaC\xd1\xff\xff\xff\xff\xa1Q\xefx\x01\x00\x02\x03\x00\x00\x03/\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\a\b\x00\b\x00\x00\x0e\x10\x00\x0eL" + + "MT\x00GMT\x00+0030\x00WAT\x00\nWAT-1\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\r\x00\x1c\x00Africa" + + "/AsmeraUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x05\x00\x00\x00\x04\x00\x00\x00\x14\xff\xff\xff\xff\x8b\xff\xd1\xfc\xff\xff\xff\xff\xb1\xee\xdaX\xff\xff\xff\xff\xb4\xc7\xe0\xd0\xff\xff\xff\xff\xc1\xed\xadX\xff\xff\xff\xff\xcclz\xd4\x01\x02\x01\x03\x02\x00\x00\"\x84\x00" + + "\x00\x00\x00#(\x00\x04\x00\x00*0\x00\n\x00\x00&\xac\x00\x0eLMT\x00+0230\x00EAT\x00+0245\x00\nEAT-3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS" + + "\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\f\x00\x1c\x00Africa/AccraUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif" + + "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x92\xe6\x92H\x01\xff\xff\xfc8\x00\x00\x00\x00\x00\x00\x00\x04LMT\x00GMT\x00" + + "\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\r\x00\x1c\x00Africa/LuandaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f" + + "\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" + + "\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xff\x86\xabp\xd1" + + "\xff\xff\xff\xff\x8cP`\x00\xff\xff\xff\xff\x96\xaaC\xd1\xff\xff\xff\xff\xa1Q\xefx\x01\x00\x02\x03\x00\x00\x03/\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\a\b\x00\b\x00\x00\x0e\x10\x00\x0eLMT\x00GMT\x00" + + "+0030\x00WAT\x00\nWAT-1\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS \x1b\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\x11\x00\x1c\x00Africa/Lubumb" + + "ashiUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00" + + "\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x82F\xc5\xf4\x01\x00\x00\x1e\x8c\x00\x00\x00\x00\x1c \x00\x04LMT\x00CAT\x00\nCAT-2\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb4\x8d\x98" + + "ƿ\x00\x00\x00\xbf\x00\x00\x00\x12\x00\x1c\x00Africa/Addis_AbabaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00T" + + "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\x14\xff\xff\xff\xff\x8b\xff\xd1\xfc\xff\xff\xff\xff\xb1\xee\xdaX\xff\xff\xff\xff\xb4\xc7\xe0\xd0\xff\xff" + + "\xff\xff\xc1\xed\xadX\xff\xff\xff\xff\xcclz\xd4\x01\x02\x01\x03\x02\x00\x00\"\x84\x00\x00\x00\x00#(\x00\x04\x00\x00*0\x00\n\x00\x00&\xac\x00\x0eLMT\x00+0230\x00EAT\x00+02" + + "45\x00\nEAT-3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x12tnj\xfc\x04\x00\x00\xfc\x04\x00\x00\f\x00\x1c\x00Africa/CairoUT\t\x00\x03\x82\x0f\x8b" + + "a\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" + + "\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\u007f\x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff\xff}" + + "\xbdM\xab\xff\xff\xff\xffȓ\xb4\xe0\xff\xff\xff\xff\xc8\xfa{\xd0\xff\xff\xff\xff\xc9\xfc\xef\xe0\xff\xff\xff\xff\xca\xc7\xe8\xd0\xff\xff\xff\xff\xcbˮ`\xff\xff\xff\xff\xcc\xdf)\xd0\xff\xff\xff\xffͬ\xe1\xe0\xff" + + "\xff\xff\xff\xce\xc6\xf4\xd0\xff\xff\xff\xffϏf\xe0\xff\xff\xff\xffЩy\xd0\xff\xff\xff\xffф`\xe0\xff\xff\xff\xffҊ\xadP\xff\xff\xff\xff\xe86c`\xff\xff\xff\xff\xe8\xf4-P\xff\xff\xff\xff\xea" + + "\v\xb9`\xff\xff\xff\xff\xea\xd5`\xd0\xff\xff\xff\xff\xeb\xec\xfa\xf0\xff\xff\xff\xff\xec\xb5m\x00\xff\xff\xff\xff\xed\xcf\u007f\xf0\xff\xff\xff\xff\xee\x97\xf2\x00\xff\xff\xff\xffﰳp\xff\xff\xff\xff\xf0y%\x80\xff" + + "\xff\xff\xff\xf1\x91\xe6\xf0\xff\xff\xff\xff\xf2ZY\x00\xff\xff\xff\xff\xf3s\x1ap\xff\xff\xff\xff\xf4;\x8c\x80\xff\xff\xff\xff\xf5U\x9fp\xff\xff\xff\xff\xf6\x1e\x11\x80\xff\xff\xff\xff\xf76\xd2\xf0\xff\xff\xff\xff\xf7" + + "\xffE\x00\xff\xff\xff\xff\xf9\x18\x06p\xff\xff\xff\xff\xf9\xe1\xca\x00\xff\xff\xff\xff\xfa\xf99\xf0\xff\xff\xff\xff\xfb\xc2\xfd\x80\xff\xff\xff\xff\xfc۾\xf0\xff\xff\xff\xff\xfd\xa5\x82\x80\xff\xff\xff\xff\xfe\xbc\xf2p\xff" + + "\xff\xff\xff\xff\x86\xb6\x00\x00\x00\x00\x00\x00\x9e%\xf0\x00\x00\x00\x00\x01g\xe9\x80\x00\x00\x00\x00\x02\u007fYp\x00\x00\x00\x00\x03I\x1d\x00\x00\x00\x00\x00\x04a\xdep\x00\x00\x00\x00\x05+\xa2\x00\x00\x00\x00\x00\x06" + + "C\x11\xf0\x00\x00\x00\x00\a\fՀ\x00\x00\x00\x00\b$Ep\x00\x00\x00\x00\b\xee\t\x00\x00\x00\x00\x00\n\x05x\xf0\x00\x00\x00\x00\n\xcf<\x80\x00\x00\x00\x00\v\xe7\xfd\xf0\x00\x00\x00\x00\f\xb1\xc1\x80\x00" + + "\x00\x00\x00\r\xc91p\x00\x00\x00\x00\x0e\x92\xf5\x00\x00\x00\x00\x00\x0f\xaad\xf0\x00\x00\x00\x00\x10t(\x80\x00\x00\x00\x00\x11\x8b\x98p\x00\x00\x00\x00\x12U\\\x00\x00\x00\x00\x00\x13n\x1dp\x00\x00\x00\x00\x14" + + "7\xe1\x00\x00\x00\x00\x00\x15OP\xf0\x00\x00\x00\x00\x16\x19\x14\x80\x00\x00\x00\x00\x17\xa0\x93\xf0\x00\x00\x00\x00\x17\xfaH\x00\x00\x00\x00\x00\x19p\xa3\xf0\x00\x00\x00\x00\x19\xdb{\x80\x00\x00\x00\x00\x1a\xf4<\xf0\x00" + + "\x00\x00\x00\x1b\xbe\x00\x80\x00\x00\x00\x00\x1c\xd5pp\x00\x00\x00\x00\x1d\x9f4\x00\x00\x00\x00\x00\x1e\xb6\xa3\xf0\x00\x00\x00\x00\x1f\x80g\x80\x00\x00\x00\x00 \x97\xd7p\x00\x00\x00\x00!a\x9b\x00\x00\x00\x00\x00\"" + + "z\\p\x00\x00\x00\x00#D \x00\x00\x00\x00\x00$b'p\x00\x00\x00\x00%%S\x80\x00\x00\x00\x00&<\xc3p\x00\x00\x00\x00'\x06\x87\x00\x00\x00\x00\x00(\x1d\xf6\xf0\x00\x00\x00\x00(纀\x00" + + "\x00\x00\x00*\x00{\xf0\x00\x00\x00\x00*\xca?\x80\x00\x00\x00\x00+\xe1\xafp\x00\x00\x00\x00,\xabs\x00\x00\x00\x00\x00-\xc2\xe2\xf0\x00\x00\x00\x00.\x8c\xa6\x80\x00\x00\x00\x00/\xa0\x13\xe0\x00\x00\x00\x000" + + "k\f\xd0\x00\x00\x00\x001\u007f\xf5\xe0\x00\x00\x00\x002J\xee\xd0\x00\x00\x00\x003_\xd7\xe0\x00\x00\x00\x004*\xd0\xd0\x00\x00\x00\x005?\xb9\xe0\x00\x00\x00\x006\n\xb2\xd0\x00\x00\x00\x007(\xd6`\x00" + + "\x00\x00\x007\xf3\xcfP\x00\x00\x00\x009\b\xb8`\x00\x00\x00\x009ӱP\x00\x00\x00\x00:\xe8\x9a`\x00\x00\x00\x00;\xb3\x93P\x00\x00\x00\x00<\xc8|`\x00\x00\x00\x00=\x93uP\x00\x00\x00\x00>" + + "\xa8^`\x00\x00\x00\x00?sWP\x00\x00\x00\x00@\x91z\xe0\x00\x00\x00\x00A\\s\xd0\x00\x00\x00\x00Bq\\\xe0\x00\x00\x00\x00C\xe0\x00\x00\x00\x00E\x12\xfdP\x00" + + "\x00\x00\x00F1 \xe0\x00\x00\x00\x00F\xe0jP\x00\x00\x00\x00H\x11\x02\xe0\x00\x00\x00\x00H\xb7\x11\xd0\x00\x00\x00\x00I\xf0\xe4\xe0\x00\x00\x00\x00J\x8d\xb9P\x00\x00\x00\x00K\xda\x01`\x00\x00\x00\x00L" + + "a\xbd\xd0\x00\x00\x00\x00L\x89X\xe0\x00\x00\x00\x00L\xa4\xfaP\x00\x00\x00\x00Su8\xe0\x00\x00\x00\x00S\xac\x89\xd0\x00\x00\x00\x00Sڼ`\x00\x00\x00\x00T$\x82P\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00" + + "\x1dU\x00\x00\x00\x00*0\x01\x04\x00\x00\x1c \x00\tLMT\x00EEST\x00EET\x00\nEET-2\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS_\u007f2[\xaf\x01\x00\x00\xaf\x01" + + "\x00\x00\x0e\x00\x1c\x00Africa/TripoliUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x04\x00\x00\x00\x11\xff\xff\xff\xff\xa1\xf2\xc1$\xff\xff\xff\xffݻ\xb1\x10\xff\xff\xff\xff\xde#\xad`\xff\xff\xff\xff\xe1x\xd2\x10\xff\xff\xff\xff\xe1" + + "\xe7e\xe0\xff\xff\xff\xff\xe5/?p\xff\xff\xff\xff\xe5\xa9\xcc\xe0\xff\xff\xff\xff\xebN\xc6\xf0\x00\x00\x00\x00\x16\x92B`\x00\x00\x00\x00\x17\b\xf7p\x00\x00\x00\x00\x17\xfa+\xe0\x00\x00\x00\x00\x18\xea*\xf0\x00" + + "\x00\x00\x00\x19\xdb_`\x00\x00\x00\x00\x1a̯\xf0\x00\x00\x00\x00\x1b\xbd\xe4`\x00\x00\x00\x00\x1c\xb4z\xf0\x00\x00\x00\x00\x1d\x9f\x17\xe0\x00\x00\x00\x00\x1e\x93\vp\x00\x00\x00\x00\x1f\x82\xee`\x00\x00\x00\x00 " + + "pJp\x00\x00\x00\x00!a~\xe0\x00\x00\x00\x00\"R\xcfp\x00\x00\x00\x00#D\x03\xe0\x00\x00\x00\x00$4\x02\xf0\x00\x00\x00\x00%%7`\x00\x00\x00\x00&@\xb7\xf0\x00\x00\x00\x002N\xf1`\x00" + + "\x00\x00\x003D6p\x00\x00\x00\x0045j\xe0\x00\x00\x00\x00P\x9d\x99\x00\x00\x00\x00\x00QTـ\x00\x00\x00\x00Ri\xb4\x80\x02\x01\x02\x01\x02\x01\x02\x03\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x03\x02\x01\x03\x02\x01\x03\x00\x00\f\\\x00\x00\x00\x00\x1c \x01\x04\x00\x00\x0e\x10\x00\t\x00\x00\x1c \x00\rLMT\x00CEST\x00CET\x00EET\x00\nEET-2\nP" + + "K\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\x11\x00\x1c\x00Africa/NouakchottUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8bau" + + "x\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00" + + "\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x92\xe6\x92H\x01\xff\xff" + + "\xfc8\x00\x00\x00\x00\x00\x00\x00\x04LMT\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\x0e\x00\x1c\x00Africa" + + "/KampalaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\x14\xff\xff\xff\xff\x8b\xff\xd1\xfc\xff\xff\xff\xff\xb1\xee\xdaX\xff\xff\xff\xff\xb4\xc7\xe0\xd0\xff\xff\xff\xff\xc1\xed\xadX\xff\xff\xff\xff\xcclz\xd4\x01\x02\x01\x03\x02\x00\x00\"\x84" + + "\x00\x00\x00\x00#(\x00\x04\x00\x00*0\x00\n\x00\x00&\xac\x00\x0eLMT\x00+0230\x00EAT\x00+0245\x00\nEAT-3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82i" + + "S\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\x00\x1c\x00America/UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x03\x04\n\x00\x00" + + "\x00\x00\x00#\x82iS\xd0v\x01\x8a\x01\x04\x00\x00\x01\x04\x00\x00\x0f\x00\x1c\x00America/TijuanaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00" + + "\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZi" + + "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00^\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff\xa5\xb6\xf6\x80\xff\xff\xff\xff\xa9yOp\xff\xff\xff" + + "\xff\xaf\xf2|\xf0\xff\xff\xff\xff\xb6fdp\xff\xff\xff\xff\xb7\x1b\x10\x00\xff\xff\xff\xff\xb8\n\xf2\xf0\xff\xff\xff\xff\xcbꍀ\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xffҙ\xbap\xff\xff\xff\xff\xd7\x1bY" + + "\x00\xff\xff\xff\xffؑ\xb4\xf0\xff\xff\xff\xff\xe2~K\x90\xff\xff\xff\xff\xe3IR\x90\xff\xff\xff\xff\xe4^-\x90\xff\xff\xff\xff\xe5)4\x90\xff\xff\xff\xff\xe6GJ\x10\xff\xff\xff\xff\xe7\x12Q\x10\xff\xff\xff" + + "\xff\xe8',\x10\xff\xff\xff\xff\xe8\xf23\x10\xff\xff\xff\xff\xea\a\x0e\x10\xff\xff\xff\xff\xea\xd2\x15\x10\xff\xff\xff\xff\xeb\xe6\xf0\x10\xff\xff\xff\xff\xec\xb1\xf7\x10\xff\xff\xff\xff\xed\xc6\xd2\x10\xff\xff\xff\xff\xee\x91\xd9" + + "\x10\x00\x00\x00\x00\v\u0be0\x00\x00\x00\x00\f\xd9\xcd\x10\x00\x00\x00\x00\r\xc0\x91\xa0\x00\x00\x00\x00\x0e\xb9\xaf\x10\x00\x00\x00\x00\x0f\xa9\xae \x00\x00\x00\x00\x10\x99\x91\x10\x00\x00\x00\x00\x11\x89\x90 \x00\x00\x00" + + "\x00\x12ys\x10\x00\x00\x00\x00\x13ir \x00\x00\x00\x00\x14YU\x10\x00\x00\x00\x00\x15IT \x00\x00\x00\x00\x1697\x10\x00\x00\x00\x00\x17)6 \x00\x00\x00\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18" + + " \x00\x00\x00\x00\x1a\x025\x90\x00\x00\x00\x00\x1a\xf24\xa0\x00\x00\x00\x00\x1b\xe2\x17\x90\x00\x00\x00\x00\x1c\xd2\x16\xa0\x00\x00\x00\x00\x1d\xc1\xf9\x90\x00\x00\x00\x00\x1e\xb1\xf8\xa0\x00\x00\x00\x00\x1f\xa1ې\x00\x00\x00" + + "\x00 v+ \x00\x00\x00\x00!\x81\xbd\x90\x00\x00\x00\x00\"V\r \x00\x00\x00\x00#j\xda\x10\x00\x00\x00\x00$5\xef \x00\x00\x00\x00%J\xbc\x10\x00\x00\x00\x00&\x15\xd1 \x00\x00\x00\x00'*\x9e" + + "\x10\x00\x00\x00\x00'\xfe\xed\xa0\x00\x00\x00\x00)\n\x80\x10\x00\x00\x00\x00)\xdeϠ\x00\x00\x00\x00*\xeab\x10\x00\x00\x00\x00+\xbe\xb1\xa0\x00\x00\x00\x00,\xd3~\x90\x00\x00\x00\x00-\x9e\x93\xa0\x00\x00\x00" + + "\x00.\xb3`\x90\x00\x00\x00\x00/~u\xa0\x00\x00\x00\x000\x93B\x90\x00\x00\x00\x001g\x92 \x00\x00\x00\x002s$\x90\x00\x00\x00\x003Gt \x00\x00\x00\x004S\x06\x90\x00\x00\x00\x005'V" + + " \x00\x00\x00\x0062\xe8\x90\x00\x00\x00\x007\a8 \x00\x00\x00\x008\x1c\x05\x10\x00\x00\x00\x008\xe7\x1a \x00\x00\x00\x009\xfb\xe7\x10\x00\x00\x00\x00:\xc6\xfc \x00\x00\x00\x00;\xdb\xc9\x10\x00\x00\x00" + + "\x00<\xb0\x18\xa0\x00\x00\x00\x00=\xbb\xab\x10\x00\x00\x00\x00>\x8f\xfa\xa0\x00\x00\x00\x00?\x9b\x8d\x10\x00\x00\x00\x00@oܠ\x00\x00\x00\x00A\x84\xa9\x90\x00\x00\x00\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b" + + "\x90\x00\x00\x00\x00D/\xa0\xa0\x00\x00\x00\x00EDm\x90\x00\x00\x00\x00F\x0f\x82\xa0\x00\x00\x00\x00G$O\x90\x00\x00\x00\x00G\xf8\x9f \x00\x00\x00\x00I\x041\x90\x00\x00\x00\x00I\u0601 \x00\x00\x00" + + "\x00J\xe4\x13\x90\x00\x00\x00\x00K\x9c\xb3\xa0\x01\x02\x01\x02\x03\x02\x04\x05\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\xff\xff\x92L\x00\x00\xff\xff\x9d\x90\x00\x04\xff" + + "\xff\x8f\x80\x00\b\xff\xff\x9d\x90\x01\f\xff\xff\x9d\x90\x01\x10\xff\xff\x9d\x90\x01\x14LMT\x00MST\x00PST\x00PDT\x00PWT\x00PPT\x00\nPST8PDT,M3.2" + + ".0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x14\x00\x1c\x00America/Blanc-Sablo" + + "nUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04" + + "\x00\x00\x00\x10\xff\xff\xff\xffz敹\xff\xff\xff\xff\xcb\xf62\xc0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\x01\x03\x02\x01\xff\xff\xc2\a\x00\x00\xff\xff\xc7\xc0\x00\x04\xff\xff\xd5\xd0\x01\b\xff\xff" + + "\xd5\xd0\x01\fLMT\x00AST\x00APT\x00AWT\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb4\x82s\x1dT\x01\x00\x00T\x01\x00\x00\x11\x00\x1c\x00Amer" + + "ica/ChihuahuaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x13\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\xa5\xb6\xe8p\xff\xff\xff\xff\xaf\xf2n\xe0\xff\xff\xff\xff\xb6fV`\xff\xff\xff\xff\xb7C\xd2`\xff\xff\xff\xff\xb8\f6`\xff\xff\xff\xff" + + "\xb8\xfd\x86\xf0\x00\x00\x00\x001gv\x00\x00\x00\x00\x002s\bp\x00\x00\x00\x003GX\x00\x00\x00\x00\x004R\xeap\x00\x00\x00\x005'H\x10\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a*\x10" + + "\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe7\f\x10\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xf5\x12\x90\x00\x00\x00\x00;\xb6\xd1\x00\x00\x00\x00\x00<\xb0\n\x90\x01\x02\x01\x02\x01\x02\x03\x02\x03\x02\x04\x01" + + "\x04\x01\x04\x01\x04\x01\x04\xff\xff\x9c\x8c\x00\x00\xff\xff\x9d\x90\x00\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xab\xa0\x01\x10LMT\x00MST\x00CST\x00CDT\x00MDT\x00\nMS" + + "T7MDT,M4.1.0,M10.5.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSԾ\xe7#\x95\x00\x00\x00\x95\x00\x00\x00\x10\x00\x1c\x00America/A" + + "tikokanUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xffi\x87&\x10\xff\xff\xff\xff\x8b\xf4a\xe8\x01\x02\xff\xff\xb5p\x00\x00\xff\xff\xb5\x18\x00\x04\xff\xff\xb9\xb0\x00\bLMT\x00CMT\x00EST\x00\nE" + + "ST5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS?_p\x99\x0e\x05\x00\x00\x0e\x05\x00\x00\x10\x00\x1c\x00America/WinnipegUT\t\x00\x03\x82\x0f\x8ba\x82" + + "\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00" + + "\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00}\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xffd\xe4\xb0" + + "\x94\xff\xff\xff\xff\x9b\x01\xfb\xe0\xff\xff\xff\xff\x9búP\xff\xff\xff\xff\x9e\xb8\xa1\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\u00a0;\x80\xff\xff\xff\xff\xc3O\x84\xf0\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff" + + "\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xffӈh\x00\xff\xff\xff\xff\xd4S`\xf0\xff\xff\xff\xff\xd5U\xd5\x00\xff\xff\xff\xff\xd6 \xcd\xf0\xff\xff\xff\xff\xd75\xb7\x00\xff\xff\xff\xff\xd8\x00\xaf" + + "\xf0\xff\xff\xff\xff\xd9\x15\x99\x00\xff\xff\xff\xff\xd9\xe0\x91\xf0\xff\xff\xff\xff\xdb\x00\a\x00\xff\xff\xff\xff\xdb\xc8\\\xf0\xff\xff\xff\xff\xdcޗ\x80\xff\xff\xff\xffݩ\x90p\xff\xff\xff\xff\u07bey\x80\xff\xff\xff" + + "\xff߉rp\xff\xff\xff\xff\xe0\x9e[\x80\xff\xff\xff\xff\xe1iTp\xff\xff\xff\xff\xe2~=\x80\xff\xff\xff\xff\xe3I6p\xff\xff\xff\xff\xe4^\x1f\x80\xff\xff\xff\xff\xe5)\x18p\xff\xff\xff\xff\xe6G<" + + "\x00\xff\xff\xff\xff\xe7\x124\xf0\xff\xff\xff\xff\xe8'\x1e\x00\xff\xff\xff\xff\xe8\xf2\x16\xf0\xff\xff\xff\xff\xea\a\x00\x00\xff\xff\xff\xff\xea\xd1\xf8\xf0\xff\xff\xff\xff\xeb\xe6\xe2\x00\xff\xff\xff\xff\xec\xd6\xc4\xf0\xff\xff\xff" + + "\xff\xed\xc6\xc4\x00\xff\xff\xff\xff\ue47c\xf0\xff\xff\xff\xff\xf3o\xa4\x80\xff\xff\xff\xff\xf41b\xf0\xff\xff\xff\xff\xf9\x0fJ\x80\xff\xff\xff\xff\xfa\bv\x00\xff\xff\xff\xff\xfa\xf8g\x00\xff\xff\xff\xff\xfb\xe8X" + + "\x00\xff\xff\xff\xff\xfc\xd8I\x00\xff\xff\xff\xff\xfd\xc8:\x00\xff\xff\xff\xff\xfe\xb8+\x00\xff\xff\xff\xff\xff\xa8\x1c\x00\x00\x00\x00\x00\x00\x98\r\x00\x00\x00\x00\x00\x01\x87\xfe\x00\x00\x00\x00\x00\x02w\xef\x00\x00\x00\x00" + + "\x00\x03q\x1a\x80\x00\x00\x00\x00\x04a\v\x80\x00\x00\x00\x00\x05P\xfc\x80\x00\x00\x00\x00\x06@\xed\x80\x00\x00\x00\x00\a0ހ\x00\x00\x00\x00\b π\x00\x00\x00\x00\t\x10\xc0\x80\x00\x00\x00\x00\n\x00\xb1" + + "\x80\x00\x00\x00\x00\n\xf0\xa2\x80\x00\x00\x00\x00\v\xe0\x93\x80\x00\x00\x00\x00\fٿ\x00\x00\x00\x00\x00\r\xc0u\x80\x00\x00\x00\x00\x0e\xb9\xa1\x00\x00\x00\x00\x00\x0f\xa9\x92\x00\x00\x00\x00\x00\x10\x99\x83\x00\x00\x00\x00" + + "\x00\x11\x89t\x00\x00\x00\x00\x00\x12ye\x00\x00\x00\x00\x00\x13iV\x00\x00\x00\x00\x00\x14YG\x00\x00\x00\x00\x00\x15I8\x00\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17)\x1a\x00\x00\x00\x00\x00\x18\"E" + + "\x80\x00\x00\x00\x00\x19\b\xfc\x00\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2\x18\x80\x00\x00\x00\x00\x1b\xe2\t\x80\x00\x00\x00\x00\x1c\xd1\xfa\x80\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1܀\x00\x00\x00" + + "\x00\x1f\xa1̀\x00\x00\x00\x00 v\x0f\x00\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xf1\x00\x00\x00\x00\x00#j\xcc\x00\x00\x00\x00\x00$5\xd3\x00\x00\x00\x00\x00%J\xae\x00\x00\x00\x00\x00&\x15\xb5" + + "\x00\x00\x00\x00\x00'*\x90\x00\x00\x00\x00\x00'\xfeр\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\u07b3\x80\x00\x00\x00\x00*\xeaT\x00\x00\x00\x00\x00+\xbe\x95\x80\x00\x00\x00\x00,\xd3p\x80\x00\x00\x00" + + "\x00-\x9ew\x80\x00\x00\x00\x00.\xb3R\x80\x00\x00\x00\x00/~Y\x80\x00\x00\x00\x000\x934\x80\x00\x00\x00\x001gv\x00\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003GX\x00\x00\x00\x00\x004R\xf8" + + "\x80\x00\x00\x00\x005':\x00\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a\x1c\x00\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xc6\xe0\x00\x00\x00\x00" + + "\x00;ۻ\x00\x00\x00\x00\x00<\xaf\xfc\x80\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8fހ\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@o\xc0\x80\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00BO\xa2" + + "\x80\x00\x00\x00\x00Cd}\x80\x00\x00\x00\x00D/\x84\x80\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7\x00\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xa4\xec\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0" + + "\x01\f\xff\xff\xb9\xb0\x01\x10LMT\x00CDT\x00CST\x00CWT\x00CPT\x00\nCST6CDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00" + + "\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\r\x00\x1c\x00America/ArubaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S" + + "_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffz敹\xff\xff\xff\xff\xcb\xf62\xc0\xff\xff\xff\xff\xd2#" + + "\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\x01\x03\x02\x01\xff\xff\xc2\a\x00\x00\xff\xff\xc7\xc0\x00\x04\xff\xff\xd5\xd0\x01\b\xff\xff\xd5\xd0\x01\fLMT\x00AST\x00APT\x00AWT\x00\nAST4\n" + + "PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSJtZ\x8c\x01\x03\x00\x00\x01\x03\x00\x00\x13\x00\x1c\x00America/PangnirtungUT\t\x00\x03\x82\x0f\x8ba\x82\x0f" + + "\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" + + "\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\n\x00\x00\x00)\xff\xff\xff\xff\xa3\xd5R\x80" + + "\xff\xff\xff\xffˈ\xe2`\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\xff\xff\xff\xff\xf7/0@\xff\xff\xff\xff\xf8([\xc0\x00\x00\x00\x00\x13i9\xe0\x00\x00\x00\x00\x14Y\x1c\xd0\x00\x00\x00\x00" + + "\x15I\x1b\xe0\x00\x00\x00\x00\x168\xfe\xd0\x00\x00\x00\x00\x17(\xfd\xe0\x00\x00\x00\x00\x18\"\x1bP\x00\x00\x00\x00\x19\b\xdf\xe0\x00\x00\x00\x00\x1a\x01\xfdP\x00\x00\x00\x00\x1a\xf1\xfc`\x00\x00\x00\x00\x1b\xe1\xdfP" + + "\x00\x00\x00\x00\x1c\xd1\xde`\x00\x00\x00\x00\x1d\xc1\xc1P\x00\x00\x00\x00\x1e\xb1\xc0`\x00\x00\x00\x00\x1f\xa1\xa3P\x00\x00\x00\x00 u\xf2\xe0\x00\x00\x00\x00!\x81\x85P\x00\x00\x00\x00\"U\xd4\xe0\x00\x00\x00\x00" + + "#j\xa1\xd0\x00\x00\x00\x00$5\xb6\xe0\x00\x00\x00\x00%J\x83\xd0\x00\x00\x00\x00&\x15\x98\xe0\x00\x00\x00\x00'*e\xd0\x00\x00\x00\x00'\xfe\xb5`\x00\x00\x00\x00)\nG\xd0\x00\x00\x00\x00)ޗ`" + + "\x00\x00\x00\x00*\xea)\xd0\x00\x00\x00\x00+\xbey`\x00\x00\x00\x00,\xd3FP\x00\x00\x00\x00-\x9e[`\x00\x00\x00\x00.\xb3(P\x00\x00\x00\x00/~=`\x00\x00\x00\x000\x93\x18`\x00\x00\x00\x00" + + "1gg\xf0\x00\x00\x00\x002r\xfa`\x00\x00\x00\x003GI\xf0\x00\x00\x00\x004R\xdc`\x00\x00\x00\x005'+\xf0\x00\x00\x00\x0062\xbe`\x00\x00\x00\x007\a\r\xf0\x00\x00\x00\x008\x1b\xda\xe0" + + "\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xca\xf0\x00\x00\x00\x00:\xc6\xd1\xf0\x00\x00\x00\x00;۞\xe0\x00\x00\x00\x00<\xaf\xeep\x00\x00\x00\x00=\xbb\x80\xe0\x00\x00\x00\x00>\x8f\xd0p\x00\x00\x00\x00" + + "?\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0" + + "\x03\x01\x02\x03\x04\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x06\a\x06\a\x06\a\x06\a\x06\b\t\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a" + + "\x06\x00\x00\x00\x00\x00\x00\xff\xff\xd5\xd0\x01\x04\xff\xff\xd5\xd0\x01\b\xff\xff\xc7\xc0\x00\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x01\x15\xff\xff\xc7\xc0\x01\x19\xff\xff\xb9\xb0\x00\x1d\xff\xff\xab\xa0\x00!\xff\xff\xb9\xb0\x01" + + "%-00\x00AWT\x00APT\x00AST\x00ADDT\x00ADT\x00EDT\x00EST\x00CST\x00CDT\x00\nEST5EDT,M3.2.0,M1" + + "1.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x12\x00\x1c\x00America/MontserratUT\t\x00\x03\x82" + + "\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff" + + "\xffz敹\xff\xff\xff\xff\xcb\xf62\xc0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\x01\x03\x02\x01\xff\xff\xc2\a\x00\x00\xff\xff\xc7\xc0\x00\x04\xff\xff\xd5\xd0\x01\b\xff\xff\xd5\xd0\x01\fLMT" + + "\x00AST\x00APT\x00AWT\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x12\x00\x1c\x00America/Kra" + + "lendijkUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x04\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffz敹\xff\xff\xff\xff\xcb\xf62\xc0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\x01\x03\x02\x01\xff\xff\xc2\a\x00\x00\xff\xff\xc7\xc0\x00\x04\xff\xff" + - "\xd5\xd0\x01\b\xff\xff\xd5\xd0\x01\fLMT\x00AST\x00APT\x00AWT\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xdf\b\x9c\x9f\xe7\x00\x00\x00\xe7\x00\x00\x00\x10\x00" + - "\x1c\x00America/BarbadosUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff\xa9y$\xe5\xff\xff\xff\xff\xb8\x85c\xe5\x00\x00\x00\x00\x0e\x00\xf2\xe0\x00\x00\x00\x00\x0e\x94\x8c\xd0\x00\x00\x00\x00\x0f\x97\x00" + - "\xe0\x00\x00\x00\x00\x10tn\xd0\x00\x00\x00\x00\x11v\xe2\xe0\x00\x00\x00\x00\x12TP\xd0\x00\x00\x00\x00\x13_\xff`\x00\x00\x00\x00\x140>P\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\xff\xff\xc8\x1b\x00\x00\xff\xff\xc8" + - "\x1b\x00\x04\xff\xff\xd5\xd0\x01\b\xff\xff\xc7\xc0\x00\fLMT\x00BMT\x00ADT\x00AST\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x14\xc1r8\xe0\x00\x00\x00\xe0" + - "\x00\x00\x00\x10\x00\x1c\x00America/AtikokanUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xffr\xee\x84d\xff\xff\xff\xff\x9e\xb8\xa1\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xc8\xf8W`\xff\xff" + - "\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\x02\x01\x02\x01\x03\x04\x05\xff\xff\xaa\x1c\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff" + - "\xff\xb9\xb0\x00\x14LMT\x00CDT\x00CST\x00CWT\x00CPT\x00EST\x00\nEST5\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00\x00" + - "\x00\x10\x00\x1c\x00America/DominicaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00" + + "\xd5\xd0\x01\b\xff\xff\xd5\xd0\x01\fLMT\x00AST\x00APT\x00AWT\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xf6\"\x12\xfe\x0e\x05\x00\x00\x0e\x05\x00\x00\x13\x00" + + "\x1c\x00America/Los_AngelesUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x9373\xac\x01\xff\xff\xc6T\x00\x00\xff\xff\xc7\xc0\x00\x04LMT\x00AST\x00\nAST4\nP" + - "K\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xac\x8a\x83S\xd4\x00\x00\x00\xd4\x00\x00\x00\x11\x00\x1c\x00America/GuatemalaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`u" + - "x\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00" + - "\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x9f\x9d\xea\xdc\x00\x00\x00" + - "\x00\aU\xac`\x00\x00\x00\x00\a͖\xd0\x00\x00\x00\x00\x19,x`\x00\x00\x00\x00\x19\xcf\xe4P\x00\x00\x00\x00'\xea\xee\xe0\x00\x00\x00\x00(\xc8\\\xd0\x00\x00\x00\x00DTR`\x00\x00\x00\x00E\x1fK" + - "P\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xff\xab$\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\bLMT\x00CDT\x00CST\x00\nCST6\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R" + - "\x1e+}\x15\xb4\x02\x00\x00\xb4\x02\x00\x00\x14\x00\x1c\x00America/Rankin_InletUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04" + - "\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00:\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xff\xe7\x8cn\x00\xff\xff\xff\xff\xf7/L`\xff\xff\xff\xff\xf8" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00}\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff^\x04\x1a\xc0\xff\xff\xff\xff\x9e\xa6H\xa0\xff\xff\xff\xff\x9f\xbb\x15\x90\xff\xff\xff\xff\xa0\x86*\xa0\xff\xff\xff\xff" + + "\xa1\x9a\xf7\x90\xff\xff\xff\xffˉ\x1a\xa0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a&\x10\xff\xff\xff\xff\xd6\xfet\\\xff\xff\xff\xff\u0600\xad\x90\xff\xff\xff\xff\xda\xfeÐ\xff\xff\xff\xff\xdb\xc0\x90\x10" + + "\xff\xff\xff\xff\xdcޥ\x90\xff\xff\xff\xffݩ\xac\x90\xff\xff\xff\xff\u07be\x87\x90\xff\xff\xff\xff߉\x8e\x90\xff\xff\xff\xff\xe0\x9ei\x90\xff\xff\xff\xff\xe1ip\x90\xff\xff\xff\xff\xe2~K\x90\xff\xff\xff\xff" + + "\xe3IR\x90\xff\xff\xff\xff\xe4^-\x90\xff\xff\xff\xff\xe5)4\x90\xff\xff\xff\xff\xe6GJ\x10\xff\xff\xff\xff\xe7\x12Q\x10\xff\xff\xff\xff\xe8',\x10\xff\xff\xff\xff\xe8\xf23\x10\xff\xff\xff\xff\xea\a\x0e\x10" + + "\xff\xff\xff\xff\xea\xd2\x15\x10\xff\xff\xff\xff\xeb\xe6\xf0\x10\xff\xff\xff\xff\xec\xb1\xf7\x10\xff\xff\xff\xff\xed\xc6\xd2\x10\xff\xff\xff\xff\xee\x91\xd9\x10\xff\xff\xff\xff\xef\xaf\xee\x90\xff\xff\xff\xff\xf0q\xbb\x10\xff\xff\xff\xff" + + "\xf1\x8fА\xff\xff\xff\xff\xf2\u007f\xc1\x90\xff\xff\xff\xff\xf3o\xb2\x90\xff\xff\xff\xff\xf4_\xa3\x90\xff\xff\xff\xff\xf5O\x94\x90\xff\xff\xff\xff\xf6?\x85\x90\xff\xff\xff\xff\xf7/v\x90\xff\xff\xff\xff\xf8(\xa2\x10" + + "\xff\xff\xff\xff\xf9\x0fX\x90\xff\xff\xff\xff\xfa\b\x84\x10\xff\xff\xff\xff\xfa\xf8\x83 \xff\xff\xff\xff\xfb\xe8f\x10\xff\xff\xff\xff\xfc\xd8e \xff\xff\xff\xff\xfd\xc8H\x10\xff\xff\xff\xff\xfe\xb8G \xff\xff\xff\xff" + + "\xff\xa8*\x10\x00\x00\x00\x00\x00\x98) \x00\x00\x00\x00\x01\x88\f\x10\x00\x00\x00\x00\x02x\v \x00\x00\x00\x00\x03q(\x90\x00\x00\x00\x00\x04a'\xa0\x00\x00\x00\x00\x05Q\n\x90\x00\x00\x00\x00\x06A\t\xa0" + + "\x00\x00\x00\x00\a0\xec\x90\x00\x00\x00\x00\a\x8dC\xa0\x00\x00\x00\x00\t\x10ΐ\x00\x00\x00\x00\t\xad\xbf \x00\x00\x00\x00\n\xf0\xb0\x90\x00\x00\x00\x00\v\u0be0\x00\x00\x00\x00\f\xd9\xcd\x10\x00\x00\x00\x00" + + "\r\xc0\x91\xa0\x00\x00\x00\x00\x0e\xb9\xaf\x10\x00\x00\x00\x00\x0f\xa9\xae \x00\x00\x00\x00\x10\x99\x91\x10\x00\x00\x00\x00\x11\x89\x90 \x00\x00\x00\x00\x12ys\x10\x00\x00\x00\x00\x13ir \x00\x00\x00\x00\x14YU\x10" + + "\x00\x00\x00\x00\x15IT \x00\x00\x00\x00\x1697\x10\x00\x00\x00\x00\x17)6 \x00\x00\x00\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18 \x00\x00\x00\x00\x1a\x025\x90\x00\x00\x00\x00\x1a\xf24\xa0\x00\x00\x00\x00" + + "\x1b\xe2\x17\x90\x00\x00\x00\x00\x1c\xd2\x16\xa0\x00\x00\x00\x00\x1d\xc1\xf9\x90\x00\x00\x00\x00\x1e\xb1\xf8\xa0\x00\x00\x00\x00\x1f\xa1ې\x00\x00\x00\x00 v+ \x00\x00\x00\x00!\x81\xbd\x90\x00\x00\x00\x00\"V\r " + + "\x00\x00\x00\x00#j\xda\x10\x00\x00\x00\x00$5\xef \x00\x00\x00\x00%J\xbc\x10\x00\x00\x00\x00&\x15\xd1 \x00\x00\x00\x00'*\x9e\x10\x00\x00\x00\x00'\xfe\xed\xa0\x00\x00\x00\x00)\n\x80\x10\x00\x00\x00\x00" + + ")\xdeϠ\x00\x00\x00\x00*\xeab\x10\x00\x00\x00\x00+\xbe\xb1\xa0\x00\x00\x00\x00,\xd3~\x90\x00\x00\x00\x00-\x9e\x93\xa0\x00\x00\x00\x00.\xb3`\x90\x00\x00\x00\x00/~u\xa0\x00\x00\x00\x000\x93B\x90" + + "\x00\x00\x00\x001g\x92 \x00\x00\x00\x002s$\x90\x00\x00\x00\x003Gt \x00\x00\x00\x004S\x06\x90\x00\x00\x00\x005'V \x00\x00\x00\x0062\xe8\x90\x00\x00\x00\x007\a8 \x00\x00\x00\x00" + + "8\x1c\x05\x10\x00\x00\x00\x008\xe7\x1a \x00\x00\x00\x009\xfb\xe7\x10\x00\x00\x00\x00:\xc6\xfc \x00\x00\x00\x00;\xdb\xc9\x10\x00\x00\x00\x00<\xb0\x18\xa0\x00\x00\x00\x00=\xbb\xab\x10\x00\x00\x00\x00>\x8f\xfa\xa0" + + "\x00\x00\x00\x00?\x9b\x8d\x10\x00\x00\x00\x00@oܠ\x00\x00\x00\x00A\x84\xa9\x90\x00\x00\x00\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b\x90\x00\x00\x00\x00D/\xa0\xa0\x00\x00\x00\x00EDm\x90\x00\x00\x00\x00" + + "E\xf3\xd3 \x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\x91&\x00\x00\xff\xff\x9d\x90\x01\x04\xff\xff\x8f\x80\x00\b\xff\xff\x9d\x90\x01\f\xff\xff\x9d\x90\x01\x10LMT\x00PDT\x00PST\x00PWT\x00PPT\x00\n" + + "PST8PDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x10\x00\x1c\x00America" + + "/St_KittsUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffz敹\xff\xff\xff\xff\xcb\xf62\xc0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\x01\x03\x02\x01\xff\xff\xc2\a\x00\x00\xff\xff\xc7\xc0\x00\x04" + + "\xff\xff\xd5\xd0\x01\b\xff\xff\xd5\xd0\x01\fLMT\x00AST\x00APT\x00AWT\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xbf\x03u\xf3\xe4\x01\x00\x00\xe4\x01\x00\x00" + + "\x0e\x00\x1c\x00America/RecifeUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96\xaag\xb8\xff\xff\xff\xff\xb8\x0fI\xe0\xff\xff\xff\xff\xb8\xfd@\xa0\xff\xff\xff\xff\xb9\xf140\xff\xff\xff\xff\xba\xdet" + + " \xff\xff\xff\xff\xda8\xae0\xff\xff\xff\xff\xda\xeb\xfa0\xff\xff\xff\xff\xdc\x19\xe1\xb0\xff\xff\xff\xffܹY \xff\xff\xff\xff\xdd\xfb\x150\xff\xff\xff\xffޛ\xde \xff\xff\xff\xff\xdfݚ0\xff\xff\xff" + + "\xff\xe0T3 \xff\xff\xff\xff\xf4\x97\xff\xb0\xff\xff\xff\xff\xf5\x05^ \xff\xff\xff\xff\xf6\xc0d0\xff\xff\xff\xff\xf7\x0e\x1e\xa0\xff\xff\xff\xff\xf8Q,0\xff\xff\xff\xff\xf8\xc7\xc5 \xff\xff\xff\xff\xfa\n\xd2" + + "\xb0\xff\xff\xff\xff\xfa\xa8\xf8\xa0\xff\xff\xff\xff\xfb\xec\x060\xff\xff\xff\xff\xfc\x8b}\xa0\x00\x00\x00\x00\x1dɎ0\x00\x00\x00\x00\x1exנ\x00\x00\x00\x00\x1f\xa05\xb0\x00\x00\x00\x00 3Ϡ\x00\x00\x00" + + "\x00!\x81i0\x00\x00\x00\x00\"\vȠ\x00\x00\x00\x00#X\x10\xb0\x00\x00\x00\x00#\xe2p \x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xd4\xc7 \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xb8\x85" + + " \x00\x00\x00\x009\xdf\xe30\x00\x00\x00\x009\xe9\x0f\xa0\x00\x00\x00\x00;\xc8\xff\xb0\x00\x00\x00\x003\nPK\x03\x04\n\x00\x00\x00\x00\x00" + + "#\x82iS\xd6\xfe\xf3%\xb4\x02\x00\x00\xb4\x02\x00\x00\x10\x00\x1c\x00America/ResoluteUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04" + + "S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00:\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xff\xd5\xfb\x81\x80\xff\xff\xff\xff\xf7/L`\xff\xff\xff\xff\xf8" + "(w\xe0\x00\x00\x00\x00\x13iV\x00\x00\x00\x00\x00\x14Y8\xf0\x00\x00\x00\x00\x15I8\x00\x00\x00\x00\x00\x169\x1a\xf0\x00\x00\x00\x00\x17)\x1a\x00\x00\x00\x00\x00\x18\"7p\x00\x00\x00\x00\x19\b\xfc\x00\x00" + "\x00\x00\x00\x1a\x02\x19p\x00\x00\x00\x00\x1a\xf2\x18\x80\x00\x00\x00\x00\x1b\xe1\xfbp\x00\x00\x00\x00\x1c\xd1\xfa\x80\x00\x00\x00\x00\x1d\xc1\xddp\x00\x00\x00\x00\x1e\xb1܀\x00\x00\x00\x00\x1f\xa1\xbfp\x00\x00\x00\x00 " + "v\x0f\x00\x00\x00\x00\x00!\x81\xa1p\x00\x00\x00\x00\"U\xf1\x00\x00\x00\x00\x00#j\xbd\xf0\x00\x00\x00\x00$5\xd3\x00\x00\x00\x00\x00%J\x9f\xf0\x00\x00\x00\x00&\x15\xb5\x00\x00\x00\x00\x00'*\x81\xf0\x00" + @@ -393,97 +472,40 @@ const zipdata = "PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00 "\x00\x00\x0062\xccp\x00\x00\x00\x007\a\x1c\x00\x00\x00\x00\x008\x1b\xe8\xf0\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xca\xf0\x00\x00\x00\x00:\xc6\xe0\x00\x00\x00\x00\x00;۬\xf0\x00\x00\x00\x00<" + "\xaf\xfc\x80\x00\x00\x00\x00=\xbb\x8e\xf0\x00\x00\x00\x00>\x8fހ\x00\x00\x00\x00?\x9bp\xf0\x00\x00\x00\x00@o\xc0\x80\x00\x00\x00\x00A\x84\x8dp\x00\x00\x00\x00BO\xa2\x80\x00\x00\x00\x00Cdop\x00" + "\x00\x00\x00D/\x84\x80\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7\x00\x02\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x04\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x00\x00\x00\x00\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff\xab\xa0\x00\t\xff\xff\xb9\xb0\x01\r\xff\xff\xb9\xb0\x00\x11-00\x00CDDT\x00" + - "CST\x00CDT\x00EST\x00\nCST6CDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00" + - "\x00\x00\x0f\x00\x1c\x00America/TortolaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00" + + "\x03\x02\x03\x02\x03\x02\x03\x04\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x03\x00\x00\x00\x00\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff\xab\xa0\x00\t\xff\xff\xb9\xb0\x01\r\xff\xff\xb9\xb0\x00\x11-00\x00CDDT\x00" + + "CST\x00CDT\x00EST\x00\nCST6CDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSR\xc8\xd9\xf6\xc4\x02\x00\x00\xc4\x02" + + "\x00\x00\x11\x00\x1c\x00America/CatamarcaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xaf,\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff" + + "\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex" + + "\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff" + + "\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ" + + "\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff" + + "\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c" + + "50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00" + + "\x00\x00'!\x0f0\x00\x00\x00\x00'\xd0X\xa0\x00\x00\x00\x00)\x00\xff@\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf" + + "*\xb0\x00\x00\x00\x00@\xbb\xf10\x00\x00\x00\x00@\xd5\v\xc0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x02\x04\x05\x04\x05\x03\x05\x02\x05\x04\x05\xff\xff\xc2T\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff" + + "\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xae,\xa44\xc9\x03\x00" + + "\x00\xc9\x03\x00\x00\f\x00\x1c\x00America/AtkaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x9373\xac\x01\xff\xff\xc6T\x00\x00\xff\xff\xc7\xc0\x00\x04LMT\x00AST\x00\nAST4\nP" + - "K\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R<\xb9\x18\x87\xe4\x02\x00\x00\xe4\x02\x00\x00\x0f\x00\x1c\x00America/IqaluitUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v" + - "\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00" + - "\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<\x00\x00\x00\b\x00\x00\x00!\xff\xff\xff\xff\xccl\xa1\x80\xff\xff\xff\xff\xd2" + - "#\xf4p\xff\xff\xff\xff\xd2`\xfb\xe0\xff\xff\xff\xff\xf7/>P\xff\xff\xff\xff\xf8(i\xd0\x00\x00\x00\x00\x13iG\xf0\x00\x00\x00\x00\x14Y*\xe0\x00\x00\x00\x00\x15I)\xf0\x00\x00\x00\x00\x169\f\xe0\x00" + - "\x00\x00\x00\x17)\v\xf0\x00\x00\x00\x00\x18\")`\x00\x00\x00\x00\x19\b\xed\xf0\x00\x00\x00\x00\x1a\x02\v`\x00\x00\x00\x00\x1a\xf2\np\x00\x00\x00\x00\x1b\xe1\xed`\x00\x00\x00\x00\x1c\xd1\xecp\x00\x00\x00\x00\x1d" + - "\xc1\xcf`\x00\x00\x00\x00\x1e\xb1\xcep\x00\x00\x00\x00\x1f\xa1\xb1`\x00\x00\x00\x00 v\x00\xf0\x00\x00\x00\x00!\x81\x93`\x00\x00\x00\x00\"U\xe2\xf0\x00\x00\x00\x00#j\xaf\xe0\x00\x00\x00\x00$5\xc4\xf0\x00" + - "\x00\x00\x00%J\x91\xe0\x00\x00\x00\x00&\x15\xa6\xf0\x00\x00\x00\x00'*s\xe0\x00\x00\x00\x00'\xfe\xc3p\x00\x00\x00\x00)\nU\xe0\x00\x00\x00\x00)ޥp\x00\x00\x00\x00*\xea7\xe0\x00\x00\x00\x00+" + - "\xbe\x87p\x00\x00\x00\x00,\xd3T`\x00\x00\x00\x00-\x9eip\x00\x00\x00\x00.\xb36`\x00\x00\x00\x00/~Kp\x00\x00\x00\x000\x93\x18`\x00\x00\x00\x001gg\xf0\x00\x00\x00\x002r\xfa`\x00" + - "\x00\x00\x003GI\xf0\x00\x00\x00\x004R\xdc`\x00\x00\x00\x005'+\xf0\x00\x00\x00\x0062\xbe`\x00\x00\x00\x007\a\r\xf0\x00\x00\x00\x008\x1b\xda\xe0\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009" + - "\xfb\xca\xf0\x00\x00\x00\x00:\xc6\xd1\xf0\x00\x00\x00\x00;۞\xe0\x00\x00\x00\x00<\xaf\xeep\x00\x00\x00\x00=\xbb\x80\xe0\x00\x00\x00\x00>\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00" + - "\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x05\x01\x02\x03\x02\x04\x02\x04\x02\x04\x02\x04\x02" + - "\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x06\a\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x00\x00\x00\x00\x00\x00\xff\xff\xc7\xc0\x01\x04\xff" + - "\xff\xb9\xb0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xc7\xc0\x01\x11\xff\xff\xc7\xc0\x01\x15\xff\xff\xab\xa0\x00\x19\xff\xff\xb9\xb0\x01\x1d-00\x00EPT\x00EST\x00EDDT\x00EDT\x00EWT\x00" + - "CST\x00CDT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xd7\b\\\xc6&\x02\x00\x00&\x02\x00\x00\x10\x00" + - "\x1c\x00America/MiquelonUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff\x91\xb68\xa8\x00\x00\x00\x00\x13nc\xc0\x00\x00\x00\x00 u\xe4\xd0\x00\x00\x00\x00!\x81w@\x00\x00\x00\x00\"U\xc6" + - "\xd0\x00\x00\x00\x00#j\x93\xc0\x00\x00\x00\x00$5\xa8\xd0\x00\x00\x00\x00%Ju\xc0\x00\x00\x00\x00&\x15\x8a\xd0\x00\x00\x00\x00'*W\xc0\x00\x00\x00\x00'\xfe\xa7P\x00\x00\x00\x00)\n9\xc0\x00\x00\x00" + - "\x00)މP\x00\x00\x00\x00*\xea\x1b\xc0\x00\x00\x00\x00+\xbekP\x00\x00\x00\x00,\xd38@\x00\x00\x00\x00-\x9eMP\x00\x00\x00\x00.\xb3\x1a@\x00\x00\x00\x00/~/P\x00\x00\x00\x000\x92\xfc" + - "@\x00\x00\x00\x001gK\xd0\x00\x00\x00\x002r\xde@\x00\x00\x00\x003G-\xd0\x00\x00\x00\x004R\xc0@\x00\x00\x00\x005'\x0f\xd0\x00\x00\x00\x0062\xa2@\x00\x00\x00\x007\x06\xf1\xd0\x00\x00\x00" + - "\x008\x1b\xbe\xc0\x00\x00\x00\x008\xe6\xd3\xd0\x00\x00\x00\x009\xfb\xa0\xc0\x00\x00\x00\x00:Ƶ\xd0\x00\x00\x00\x00;ۂ\xc0\x00\x00\x00\x00<\xaf\xd2P\x00\x00\x00\x00=\xbbd\xc0\x00\x00\x00\x00>\x8f\xb4" + - "P\x00\x00\x00\x00?\x9bF\xc0\x00\x00\x00\x00@o\x96P\x00\x00\x00\x00A\x84c@\x00\x00\x00\x00BOxP\x00\x00\x00\x00CdE@\x00\x00\x00\x00D/ZP\x00\x00\x00\x00ED'@\x00\x00\x00" + - "\x00E\xf3\x8c\xd0\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\xff\xff\xcbX\x00\x00\xff\xff\xc7\xc0\x00\x04" + - "\xff\xff\xd5\xd0\x00\b\xff\xff\xe3\xe0\x01\fLMT\x00AST\x00-03\x00-02\x00\n<-03>3<-02>,M3.2.0,M11.1.0\nPK\x03\x04" + - "\n\x00\x00\x00\x00\x00\xf1c9R\xb4\x11Z\xde\xe4\x01\x00\x00\xe4\x01\x00\x00\x11\x00\x1c\x00America/FortalezaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00" + - "\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00" + - "\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96\xaak\x18\xff\xff\xff\xff\xb8\x0f" + - "I\xe0\xff\xff\xff\xff\xb8\xfd@\xa0\xff\xff\xff\xff\xb9\xf140\xff\xff\xff\xff\xba\xdet \xff\xff\xff\xff\xda8\xae0\xff\xff\xff\xff\xda\xeb\xfa0\xff\xff\xff\xff\xdc\x19\xe1\xb0\xff\xff\xff\xffܹY \xff\xff" + - "\xff\xff\xdd\xfb\x150\xff\xff\xff\xffޛ\xde \xff\xff\xff\xff\xdfݚ0\xff\xff\xff\xff\xe0T3 \xff\xff\xff\xff\xf4\x97\xff\xb0\xff\xff\xff\xff\xf5\x05^ \xff\xff\xff\xff\xf6\xc0d0\xff\xff\xff\xff\xf7\x0e" + - "\x1e\xa0\xff\xff\xff\xff\xf8Q,0\xff\xff\xff\xff\xf8\xc7\xc5 \xff\xff\xff\xff\xfa\nҰ\xff\xff\xff\xff\xfa\xa8\xf8\xa0\xff\xff\xff\xff\xfb\xec\x060\xff\xff\xff\xff\xfc\x8b}\xa0\x00\x00\x00\x00\x1dɎ0\x00\x00" + - "\x00\x00\x1exנ\x00\x00\x00\x00\x1f\xa05\xb0\x00\x00\x00\x00 3Ϡ\x00\x00\x00\x00!\x81i0\x00\x00\x00\x00\"\vȠ\x00\x00\x00\x00#X\x10\xb0\x00\x00\x00\x00#\xe2p \x00\x00\x00\x00%7" + - "\xf2\xb0\x00\x00\x00\x00%\xd4\xc7 \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xb8\x85 \x00\x00\x00\x009\xdf\xe30\x00\x00\x00\x009\xf2J \x00\x00\x00\x00;\xc8\xff\xb0\x00\x00\x00\x003\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xd6\xfe\xf3%\xb4\x02\x00\x00\xb4\x02\x00\x00\x10\x00\x1c\x00America/Resolut" + - "eUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00:\x00\x00\x00\x05" + - "\x00\x00\x00\x15\xff\xff\xff\xff\xd5\xfb\x81\x80\xff\xff\xff\xff\xf7/L`\xff\xff\xff\xff\xf8(w\xe0\x00\x00\x00\x00\x13iV\x00\x00\x00\x00\x00\x14Y8\xf0\x00\x00\x00\x00\x15I8\x00\x00\x00\x00\x00\x169\x1a\xf0" + - "\x00\x00\x00\x00\x17)\x1a\x00\x00\x00\x00\x00\x18\"7p\x00\x00\x00\x00\x19\b\xfc\x00\x00\x00\x00\x00\x1a\x02\x19p\x00\x00\x00\x00\x1a\xf2\x18\x80\x00\x00\x00\x00\x1b\xe1\xfbp\x00\x00\x00\x00\x1c\xd1\xfa\x80\x00\x00\x00\x00" + - "\x1d\xc1\xddp\x00\x00\x00\x00\x1e\xb1܀\x00\x00\x00\x00\x1f\xa1\xbfp\x00\x00\x00\x00 v\x0f\x00\x00\x00\x00\x00!\x81\xa1p\x00\x00\x00\x00\"U\xf1\x00\x00\x00\x00\x00#j\xbd\xf0\x00\x00\x00\x00$5\xd3\x00" + - "\x00\x00\x00\x00%J\x9f\xf0\x00\x00\x00\x00&\x15\xb5\x00\x00\x00\x00\x00'*\x81\xf0\x00\x00\x00\x00'\xfeр\x00\x00\x00\x00)\nc\xf0\x00\x00\x00\x00)\u07b3\x80\x00\x00\x00\x00*\xeaE\xf0\x00\x00\x00\x00" + - "+\xbe\x95\x80\x00\x00\x00\x00,\xd3bp\x00\x00\x00\x00-\x9ew\x80\x00\x00\x00\x00.\xb3Dp\x00\x00\x00\x00/~Y\x80\x00\x00\x00\x000\x93&p\x00\x00\x00\x001gv\x00\x00\x00\x00\x002s\bp" + - "\x00\x00\x00\x003GX\x00\x00\x00\x00\x004R\xeap\x00\x00\x00\x005':\x00\x00\x00\x00\x0062\xccp\x00\x00\x00\x007\a\x1c\x00\x00\x00\x00\x008\x1b\xe8\xf0\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x00" + - "9\xfb\xca\xf0\x00\x00\x00\x00:\xc6\xe0\x00\x00\x00\x00\x00;۬\xf0\x00\x00\x00\x00<\xaf\xfc\x80\x00\x00\x00\x00=\xbb\x8e\xf0\x00\x00\x00\x00>\x8fހ\x00\x00\x00\x00?\x9bp\xf0\x00\x00\x00\x00@o\xc0\x80" + - "\x00\x00\x00\x00A\x84\x8dp\x00\x00\x00\x00BO\xa2\x80\x00\x00\x00\x00Cdop\x00\x00\x00\x00D/\x84\x80\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7\x00\x02\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x03\x00\x00\x00\x00\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff" + - "\xab\xa0\x00\t\xff\xff\xb9\xb0\x01\r\xff\xff\xb9\xb0\x00\x11-00\x00CDDT\x00CST\x00CDT\x00EST\x00\nCST6CDT,M3.2.0,M11.1.0" + - "\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00\x00\x00\x11\x00\x1c\x00America/St_ThomasUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e" + - "`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01" + - "\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x9373\xac\x01" + - "\xff\xff\xc6T\x00\x00\xff\xff\xc7\xc0\x00\x04LMT\x00AST\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xbf\x03u\xf3\xe4\x01\x00\x00\xe4\x01\x00\x00\x0e\x00\x1c\x00Amer" + - "ica/RecifeUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00'\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96\xaag\xb8\xff\xff\xff\xff\xb8\x0fI\xe0\xff\xff\xff\xff\xb8\xfd@\xa0\xff\xff\xff\xff\xb9\xf140\xff\xff\xff\xff\xba\xdet \xff\xff\xff\xff\xda8\xae" + - "0\xff\xff\xff\xff\xda\xeb\xfa0\xff\xff\xff\xff\xdc\x19\xe1\xb0\xff\xff\xff\xffܹY \xff\xff\xff\xff\xdd\xfb\x150\xff\xff\xff\xffޛ\xde \xff\xff\xff\xff\xdfݚ0\xff\xff\xff\xff\xe0T3 \xff\xff\xff" + - "\xff\xf4\x97\xff\xb0\xff\xff\xff\xff\xf5\x05^ \xff\xff\xff\xff\xf6\xc0d0\xff\xff\xff\xff\xf7\x0e\x1e\xa0\xff\xff\xff\xff\xf8Q,0\xff\xff\xff\xff\xf8\xc7\xc5 \xff\xff\xff\xff\xfa\nҰ\xff\xff\xff\xff\xfa\xa8\xf8" + - "\xa0\xff\xff\xff\xff\xfb\xec\x060\xff\xff\xff\xff\xfc\x8b}\xa0\x00\x00\x00\x00\x1dɎ0\x00\x00\x00\x00\x1exנ\x00\x00\x00\x00\x1f\xa05\xb0\x00\x00\x00\x00 3Ϡ\x00\x00\x00\x00!\x81i0\x00\x00\x00" + - "\x00\"\vȠ\x00\x00\x00\x00#X\x10\xb0\x00\x00\x00\x00#\xe2p \x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xd4\xc7 \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xb8\x85 \x00\x00\x00\x009\xdf\xe3" + - "0\x00\x00\x00\x009\xe9\x0f\xa0\x00\x00\x00\x00;\xc8\xff\xb0\x00\x00\x00\x003\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x19vv\xa0" + - "\x97\x00\x00\x00\x97\x00\x00\x00\x0f\x00\x1c\x00America/CuracaoUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xff\x93\x1e.#\xff\xff\xff\xff\xf6\x98\xecH\x01\x02\xff\xff\xbf]\x00\x00\xff\xff\xc0\xb8\x00\x04" + - "\xff\xff\xc7\xc0\x00\nLMT\x00-0430\x00AST\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xa7\x17jҲ\x00\x00\x00\xb2\x00\x00\x00\x12\x00\x1c\x00Amer" + - "ica/MartiniqueUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x11\xff\xff\xff\xffi\x87\x14\xc4\xff\xff\xff\xff\x91\xa3\xc8D\x00\x00\x00\x00\x13Mn@\x00\x00\x00\x00\x144\x16\xb0\x01\x02\x03\x02\xff\xffƼ\x00\x00\xff" + - "\xffƼ\x00\x04\xff\xff\xc7\xc0\x00\t\xff\xff\xd5\xd0\x01\rLMT\x00FFMT\x00AST\x00ADT\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R?\xc9\x1c\xd4\xc6\x03" + - "\x00\x00\xc6\x03\x00\x00\x0e\x00\x1c\x00America/JuneauUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00S\x00\x00\x00\n\x00\x00\x00&\xff\xff\xff\xff?\xc2\xfd\xd1\xff\xff\xff\xff}\x872\xc5\xff\xff\xff\xffˉ\x1a\xa0\xff\xff\xff\xff\xd2#\xf4p\xff" + - "\xff\xff\xff\xd2a&\x10\xff\xff\xff\xff\xfe\xb8G \xff\xff\xff\xff\xff\xa8*\x10\x00\x00\x00\x00\x00\x98) \x00\x00\x00\x00\x01\x88\f\x10\x00\x00\x00\x00\x02x\v \x00\x00\x00\x00\x03q(\x90\x00\x00\x00\x00\x04" + - "a'\xa0\x00\x00\x00\x00\x05Q\n\x90\x00\x00\x00\x00\x06A\t\xa0\x00\x00\x00\x00\a0\xec\x90\x00\x00\x00\x00\a\x8dC\xa0\x00\x00\x00\x00\t\x10ΐ\x00\x00\x00\x00\t\xad\xbf \x00\x00\x00\x00\n\xf0\xb0\x90\x00" + - "\x00\x00\x00\v\u0be0\x00\x00\x00\x00\f\xd9\xcd\x10\x00\x00\x00\x00\r\xc0\x91\xa0\x00\x00\x00\x00\x0e\xb9\xaf\x10\x00\x00\x00\x00\x0f\xa9\xae \x00\x00\x00\x00\x10\x99\x91\x10\x00\x00\x00\x00\x11\x89\x90 \x00\x00\x00\x00\x12" + - "ys\x10\x00\x00\x00\x00\x13ir \x00\x00\x00\x00\x14Yc \x00\x00\x00\x00\x15IT \x00\x00\x00\x00\x1697\x10\x00\x00\x00\x00\x17)6 \x00\x00\x00\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18 \x00" + - "\x00\x00\x00\x1a\x025\x90\x00\x00\x00\x00\x1a+\x14\x10\x00\x00\x00\x00\x1a\xf2B\xb0\x00\x00\x00\x00\x1b\xe2%\xa0\x00\x00\x00\x00\x1c\xd2$\xb0\x00\x00\x00\x00\x1d\xc2\a\xa0\x00\x00\x00\x00\x1e\xb2\x06\xb0\x00\x00\x00\x00\x1f" + - "\xa1\xe9\xa0\x00\x00\x00\x00 v90\x00\x00\x00\x00!\x81ˠ\x00\x00\x00\x00\"V\x1b0\x00\x00\x00\x00#j\xe8 \x00\x00\x00\x00$5\xfd0\x00\x00\x00\x00%J\xca \x00\x00\x00\x00&\x15\xdf0\x00" + - "\x00\x00\x00'*\xac \x00\x00\x00\x00'\xfe\xfb\xb0\x00\x00\x00\x00)\n\x8e \x00\x00\x00\x00)\xdeݰ\x00\x00\x00\x00*\xeap \x00\x00\x00\x00+\xbe\xbf\xb0\x00\x00\x00\x00,ӌ\xa0\x00\x00\x00\x00-" + - "\x9e\xa1\xb0\x00\x00\x00\x00.\xb3n\xa0\x00\x00\x00\x00/~\x83\xb0\x00\x00\x00\x000\x93P\xa0\x00\x00\x00\x001g\xa00\x00\x00\x00\x002s2\xa0\x00\x00\x00\x003G\x820\x00\x00\x00\x004S\x14\xa0\x00" + - "\x00\x00\x005'd0\x00\x00\x00\x0062\xf6\xa0\x00\x00\x00\x007\aF0\x00\x00\x00\x008\x1c\x13 \x00\x00\x00\x008\xe7(0\x00\x00\x00\x009\xfb\xf5 \x00\x00\x00\x00:\xc7\n0\x00\x00\x00\x00;" + - "\xdb\xd7 \x00\x00\x00\x00<\xb0&\xb0\x00\x00\x00\x00=\xbb\xb9 \x00\x00\x00\x00>\x90\b\xb0\x00\x00\x00\x00?\x9b\x9b \x00\x00\x00\x00@o\xea\xb0\x00\x00\x00\x00A\x84\xb7\xa0\x00\x00\x00\x00BO̰\x00" + - "\x00\x00\x00Cd\x99\xa0\x00\x00\x00\x00D/\xae\xb0\x00\x00\x00\x00ED{\xa0\x00\x00\x00\x00E\xf3\xe10\x01\x02\x03\x04\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x06\x02" + - "\x05\x02\x05\x02\x05\a\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\x00\x00\xd3{\x00\x00" + - "\xff\xff\x81\xfb\x00\x00\xff\xff\x8f\x80\x00\x04\xff\xff\x9d\x90\x01\b\xff\xff\x9d\x90\x01\f\xff\xff\x9d\x90\x01\x10\xff\xff\x8f\x80\x01\x14\xff\xff\x81p\x00\x18\xff\xff\x8f\x80\x01\x1c\xff\xff\x81p\x00!LMT\x00PS" + - "T\x00PWT\x00PPT\x00PDT\x00YDT\x00YST\x00AKDT\x00AKST\x00\nAKST9AKDT,M3.2.0,M11.1.0\nPK" + - "\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R.\xbe\x1a>\xe7\x03\x00\x00\xe7\x03\x00\x00\r\x00\x1c\x00America/BoiseUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04" + - "\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00T\x00\x00\x00\n\x00\x00\x00!\xff\xff\xff\xff?\xc2\xfd\xd1\xff\xff\xff\xff}\x87Z^\xff\xff\xff\xffˉD\xd0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff" + + "\xd2aP@\xff\xff\xff\xff\xfa\xd2U\xb0\xff\xff\xff\xff\xfe\xb8qP\xff\xff\xff\xff\xff\xa8T@\x00\x00\x00\x00\x00\x98SP\x00\x00\x00\x00\x01\x886@\x00\x00\x00\x00\x02x5P\x00\x00\x00\x00\x03qR\xc0" + + "\x00\x00\x00\x00\x04aQ\xd0\x00\x00\x00\x00\x05Q4\xc0\x00\x00\x00\x00\x06A3\xd0\x00\x00\x00\x00\a1\x16\xc0\x00\x00\x00\x00\a\x8dm\xd0\x00\x00\x00\x00\t\x10\xf8\xc0\x00\x00\x00\x00\t\xad\xe9P\x00\x00\x00\x00" + + "\n\xf0\xda\xc0\x00\x00\x00\x00\v\xe0\xd9\xd0\x00\x00\x00\x00\f\xd9\xf7@\x00\x00\x00\x00\r\xc0\xbb\xd0\x00\x00\x00\x00\x0e\xb9\xd9@\x00\x00\x00\x00\x0f\xa9\xd8P\x00\x00\x00\x00\x10\x99\xbb@\x00\x00\x00\x00\x11\x89\xbaP" + + "\x00\x00\x00\x00\x12y\x9d@\x00\x00\x00\x00\x13i\x9cP\x00\x00\x00\x00\x14Y\u007f@\x00\x00\x00\x00\x15I~P\x00\x00\x00\x00\x169a@\x00\x00\x00\x00\x17)`P\x00\x00\x00\x00\x18\"}\xc0\x00\x00\x00\x00" + + "\x19\tBP\x00\x00\x00\x00\x1a\x02_\xc0\x00\x00\x00\x00\x1a+\" \x00\x00\x00\x00\x1a\xf2P\xc0\x00\x00\x00\x00\x1b\xe23\xb0\x00\x00\x00\x00\x1c\xd22\xc0\x00\x00\x00\x00\x1d\xc2\x15\xb0\x00\x00\x00\x00\x1e\xb2\x14\xc0" + + "\x00\x00\x00\x00\x1f\xa1\xf7\xb0\x00\x00\x00\x00 vG@\x00\x00\x00\x00!\x81ٰ\x00\x00\x00\x00\"V)@\x00\x00\x00\x00#j\xf60\x00\x00\x00\x00$6\v@\x00\x00\x00\x00%J\xd80\x00\x00\x00\x00" + + "&\x15\xed@\x00\x00\x00\x00'*\xba0\x00\x00\x00\x00'\xff\t\xc0\x00\x00\x00\x00)\n\x9c0\x00\x00\x00\x00)\xde\xeb\xc0\x00\x00\x00\x00*\xea~0\x00\x00\x00\x00+\xbe\xcd\xc0\x00\x00\x00\x00,Ӛ\xb0" + + "\x00\x00\x00\x00-\x9e\xaf\xc0\x00\x00\x00\x00.\xb3|\xb0\x00\x00\x00\x00/~\x91\xc0\x00\x00\x00\x000\x93^\xb0\x00\x00\x00\x001g\xae@\x00\x00\x00\x002s@\xb0\x00\x00\x00\x003G\x90@\x00\x00\x00\x00" + + "4S\"\xb0\x00\x00\x00\x005'r@\x00\x00\x00\x0063\x04\xb0\x00\x00\x00\x007\aT@\x00\x00\x00\x008\x1c!0\x00\x00\x00\x008\xe76@\x00\x00\x00\x009\xfc\x030\x00\x00\x00\x00:\xc7\x18@" + + "\x00\x00\x00\x00;\xdb\xe50\x00\x00\x00\x00<\xb04\xc0\x00\x00\x00\x00=\xbb\xc70\x00\x00\x00\x00>\x90\x16\xc0\x00\x00\x00\x00?\x9b\xa90\x00\x00\x00\x00@o\xf8\xc0\x00\x00\x00\x00A\x84Ű\x00\x00\x00\x00" + + "BO\xda\xc0\x00\x00\x00\x00Cd\xa7\xb0\x00\x00\x00\x00D/\xbc\xc0\x00\x00\x00\x00ED\x89\xb0\x00\x00\x00\x00E\xf3\xef@\x01\x02\x03\x04\x02\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05" + + "\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\a\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b" + + "\x00\x00\xab\xe2\x00\x00\xff\xffZb\x00\x00\xff\xffeP\x00\x04\xff\xffs`\x01\b\xff\xffs`\x01\f\xff\xffeP\x00\x10\xff\xffs`\x01\x14\xff\xffs`\x00\x18\xff\xff\x81p\x01\x1d\xff\xffs`\x00\x19" + + "LMT\x00NST\x00NWT\x00NPT\x00BST\x00BDT\x00AHST\x00HDT\x00\nHST10HDT,M3.2.0,M11.1.0\nPK" + + "\x03\x04\n\x00\x00\x00\x00\x00#\x82iS.\xbe\x1a>\xe7\x03\x00\x00\xe7\x03\x00\x00\r\x00\x1c\x00America/BoiseUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04" + + "\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" + "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Z\x00\x00\x00\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x04\x1a\xc0\xff\xff\xff\xff\x9e\xa6H\xa0" + "\xff\xff\xff\xff\x9f\xbb\x15\x90\xff\xff\xff\xff\xa0\x86*\xa0\xff\xff\xff\xff\xa1\x9a\xf7\x90\xff\xff\xff\xff\xa8FL \xff\xff\xff\xffˉ\f\x90\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff" + "\xfa\xf8u\x10\xff\xff\xff\xff\xfb\xe8X\x00\xff\xff\xff\xff\xfc\xd8W\x10\xff\xff\xff\xff\xfd\xc8:\x00\xff\xff\xff\xff\xfe\xb89\x10\xff\xff\xff\xff\xff\xa8\x1c\x00\x00\x00\x00\x00\x00\x98\x1b\x10\x00\x00\x00\x00\x01\x87\xfe\x00" + @@ -499,296 +521,191 @@ const zipdata = "PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00 "A\x84\x9b\x80\x00\x00\x00\x00BO\xb0\x90\x00\x00\x00\x00Cd}\x80\x00\x00\x00\x00D/\x92\x90\x00\x00\x00\x00ED_\x80\x00\x00\x00\x00E\xf3\xc5\x10\x02\x01\x02\x01\x02\x05\x03\x04\x05\x06\x05\x06\x05\x06\x05\x06" + "\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06" + "\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\xff\xff\x93\x0f\x00\x00\xff\xff\x9d\x90\x01\x04\xff\xff\x8f\x80\x00\b\xff\xff\xab\xa0\x01\f\xff\xff\xab\xa0\x01\x10\xff\xff\x9d\x90\x00\x14\xff\xff\xab\xa0\x01\x18LMT\x00" + - "PDT\x00PST\x00MWT\x00MPT\x00MST\x00MDT\x00\nMST7MDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c" + - "9R\xaaʂA\xcd\x00\x00\x00\xcd\x00\x00\x00\x14\x00\x1c\x00America/Blanc-SablonUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00" + - "\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZi" + - "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff^=9\f\xff\xff\xff\xff\x9e\xb8\x85`\xff\xff\xff" + - "\xff\x9f\xba\xddP\xff\xff\xff\xffˈ\xe2`\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\x02\x01\x02\x03\x04\x02\xff\xff\xcat\x00\x00\xff\xff\xd5\xd0\x01\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff" + - "\xff\xd5\xd0\x01\x10LMT\x00ADT\x00AST\x00AWT\x00APT\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\u007f$*\xa0\xa6\x03\x00\x00\xa6\x03\x00\x00\x0e\x00\x1c" + - "\x00America/CuiabaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00Y\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96\xaa{\x94\xff\xff\xff\xff\xb8\x0fW\xf0\xff\xff\xff\xff\xb8\xfdN\xb0\xff\xff\xff\xff\xb9\xf1B@\xff\xff\xff\xff\xbaނ0\xff\xff" + - "\xff\xff\xda8\xbc@\xff\xff\xff\xff\xda\xec\b@\xff\xff\xff\xff\xdc\x19\xef\xc0\xff\xff\xff\xffܹg0\xff\xff\xff\xff\xdd\xfb#@\xff\xff\xff\xffޛ\xec0\xff\xff\xff\xff\xdfݨ@\xff\xff\xff\xff\xe0T" + - "A0\xff\xff\xff\xff\xf4\x98\r\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf6\xc0r@\xff\xff\xff\xff\xf7\x0e,\xb0\xff\xff\xff\xff\xf8Q:@\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xfa\n\xe0\xc0\xff\xff" + - "\xff\xff\xfa\xa9\x06\xb0\xff\xff\xff\xff\xfb\xec\x14@\xff\xff\xff\xff\xfc\x8b\x8b\xb0\x00\x00\x00\x00\x1dɜ@\x00\x00\x00\x00\x1ex\xe5\xb0\x00\x00\x00\x00\x1f\xa0C\xc0\x00\x00\x00\x00 3ݰ\x00\x00\x00\x00!\x81" + - "w@\x00\x00\x00\x00\"\vְ\x00\x00\x00\x00#X\x1e\xc0\x00\x00\x00\x00#\xe2~0\x00\x00\x00\x00%8\x00\xc0\x00\x00\x00\x00%\xd4\xd50\x00\x00\x00\x00'!\x1d@\x00\x00\x00\x00'\xbd\xf1\xb0\x00\x00" + - "\x00\x00)\x00\xff@\x00\x00\x00\x00)\x94\x990\x00\x00\x00\x00*\xea\x1b\xc0\x00\x00\x00\x00+k@\xb0\x00\x00\x00\x00,\xc0\xc3@\x00\x00\x00\x00-f\xd20\x00\x00\x00\x00.\xa0\xa5@\x00\x00\x00\x00/F" + - "\xb40\x00\x00\x00\x000\x80\x87@\x00\x00\x00\x001\x1d[\xb0\x00\x00\x00\x002W.\xc0\x00\x00\x00\x003\x06x0\x00\x00\x00\x0048b@\x00\x00\x00\x004\xf8\xcf0\x00\x00\x00\x006 -@\x00\x00" + - "\x00\x006\xcfv\xb0\x00\x00\x00\x007\xf6\xd4\xc0\x00\x00\x00\x008\xb8\x930\x00\x00\x00\x009\xdf\xf1@\x00\x00\x00\x00:\x8f:\xb0\x00\x00\x00\x00;\xc9\r\xc0\x00\x00\x00\x00N\xfe\xb0\x00\x00\x00\x00A\x87\x06@\x00\x00\x00\x00B\x17\xfd0\x00\x00\x00\x00CQ\xd0@\x00\x00\x00\x00C\xf7\xdf0\x00\x00\x00\x00EMa\xc0\x00\x00\x00\x00E\xe0\xfb\xb0\x00\x00" + - "\x00\x00G\x11\x94@\x00\x00\x00\x00G\xb7\xa30\x00\x00\x00\x00H\xfa\xb0\xc0\x00\x00\x00\x00I\x97\x850\x00\x00\x00\x00Jڒ\xc0\x00\x00\x00\x00K\x80\xa1\xb0\x00\x00\x00\x00L\xbat\xc0\x00\x00\x00\x00M`" + - "\x83\xb0\x00\x00\x00\x00N\x9aV\xc0\x00\x00\x00\x00OI\xa00\x00\x00\x00\x00P\x83s@\x00\x00\x00\x00Q G\xb0\x00\x00\x00\x00RcU@\x00\x00\x00\x00S\x00)\xb0\x00\x00\x00\x00TC7@\x00\x00" + - "\x00\x00T\xe9F0\x00\x00\x00\x00V#\x19@\x00\x00\x00\x00V\xc9(0\x00\x00\x00\x00X\x02\xfb@\x00\x00\x00\x00X\xa9\n0\x00\x00\x00\x00Y\xe2\xdd@\x00\x00\x00\x00Z\x88\xec0\x00\x00\x00\x00[\xde" + - "n\xc0\x00\x00\x00\x00\\h\xce0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xff\xcbl\x00\x00\xff\xff\xd5\xd0\x01\x04\xff\xff\xc7\xc0\x00\bLMT" + - "\x00-03\x00-04\x00\n<-04>4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xf7\xe9 y\xbd\x02\x00\x00\xbd\x02\x00\x00\x0e\x00\x1c\x00America/Inuvi" + - "kUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00;\x00\x00\x00\x05" + - "\x00\x00\x00\x15\xff\xff\xff\xff\xe0\x06N\x80\xff\xff\xff\xff\xf7/h\x80\xff\xff\xff\xff\xf8(\x94\x00\x00\x00\x00\x00\x11\x89\x90 \x00\x00\x00\x00\x13id\x10\x00\x00\x00\x00\x14YG\x00\x00\x00\x00\x00\x15IF\x10" + + "PDT\x00PST\x00MWT\x00MPT\x00MST\x00MDT\x00\nMST7MDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82" + + "iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15\x00\x1c\x00America/North_Dakota/UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E" + + "\x00\x00\x04S_\x01\x00PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSR\x1b\x8b(\xde\x03\x00\x00\xde\x03\x00\x00\x1e\x00\x1c\x00America/North_Dakota/Ne" + + "w_SalemUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00Y\x00\x00\x00\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x04\f\xb0\xff\xff\xff\xff\x9e\xa6:\x90\xff\xff\xff\xff\x9f\xbb\a\x80\xff\xff\xff\xff\xa0\x86\x1c\x90\xff\xff\xff\xff\xa1\x9a\xe9\x80\xff\xff\xff\xffˉ\f\x90\xff\xff" + + "\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff\xfa\xf8u\x10\xff\xff\xff\xff\xfb\xe8X\x00\xff\xff\xff\xff\xfc\xd8W\x10\xff\xff\xff\xff\xfd\xc8:\x00\xff\xff\xff\xff\xfe\xb89\x10\xff\xff\xff\xff\xff\xa8" + + "\x1c\x00\x00\x00\x00\x00\x00\x98\x1b\x10\x00\x00\x00\x00\x01\x87\xfe\x00\x00\x00\x00\x00\x02w\xfd\x10\x00\x00\x00\x00\x03q\x1a\x80\x00\x00\x00\x00\x04a\x19\x90\x00\x00\x00\x00\x05P\xfc\x80\x00\x00\x00\x00\x06@\xfb\x90\x00\x00" + + "\x00\x00\a0ހ\x00\x00\x00\x00\a\x8d5\x90\x00\x00\x00\x00\t\x10\xc0\x80\x00\x00\x00\x00\t\xad\xb1\x10\x00\x00\x00\x00\n\xf0\xa2\x80\x00\x00\x00\x00\vࡐ\x00\x00\x00\x00\fٿ\x00\x00\x00\x00\x00\r\xc0" + + "\x83\x90\x00\x00\x00\x00\x0e\xb9\xa1\x00\x00\x00\x00\x00\x0f\xa9\xa0\x10\x00\x00\x00\x00\x10\x99\x83\x00\x00\x00\x00\x00\x11\x89\x82\x10\x00\x00\x00\x00\x12ye\x00\x00\x00\x00\x00\x13id\x10\x00\x00\x00\x00\x14YG\x00\x00\x00" + + "\x00\x00\x15IF\x10\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17)(\x10\x00\x00\x00\x00\x18\"E\x80\x00\x00\x00\x00\x19\t\n\x10\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2&\x90\x00\x00\x00\x00\x1b\xe2" + + "\t\x80\x00\x00\x00\x00\x1c\xd2\b\x90\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1\xea\x90\x00\x00\x00\x00\x1f\xa1̀\x00\x00\x00\x00 v\x1d\x10\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xff\x10\x00\x00" + + "\x00\x00#j\xcc\x00\x00\x00\x00\x00$5\xe1\x10\x00\x00\x00\x00%J\xae\x00\x00\x00\x00\x00&\x15\xc3\x10\x00\x00\x00\x00'*\x90\x00\x00\x00\x00\x00'\xfeߐ\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\xde" + + "\xc1\x90\x00\x00\x00\x00*\xeaT\x00\x00\x00\x00\x00+\xbe\xa3\x90\x00\x00\x00\x00,\xd3p\x80\x00\x00\x00\x00-\x9e\x85\x90\x00\x00\x00\x00.\xb3R\x80\x00\x00\x00\x00/~g\x90\x00\x00\x00\x000\x934\x80\x00\x00" + + "\x00\x001g\x84\x10\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003Gf\x10\x00\x00\x00\x004R\xf8\x80\x00\x00\x00\x005'H\x10\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b" + + "\xf7\x00\x00\x00\x00\x008\xe7\f\x10\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xc6\xee\x10\x00\x00\x00\x00;ۻ\x00\x00\x00\x00\x00<\xb0\n\x90\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8f\xec\x90\x00\x00" + + "\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@o\xc0\x80\x00\x00\x00\x00A\x84\x8dp\x00\x00\x00\x00BO\xa2\x80\x00\x00\x00\x00Cdop\x00\x00\x00\x00D/\x84\x80\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3" + + "\xb7\x00\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x06\x05\x06\x05\x06\x05\x06\x05\xff\xff\xa0\xed\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\f\xff\xff\xab\xa0\x01" + + "\x10\xff\xff\xb9\xb0\x01\x14\xff\xff\xab\xa0\x00\x18LMT\x00MDT\x00MST\x00MWT\x00MPT\x00CDT\x00CST\x00\nCST6CDT,M3.2.0,M11" + + ".1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSH\xeam\xef\xde\x03\x00\x00\xde\x03\x00\x00\x1b\x00\x1c\x00America/North_Dakota/Cent" + + "erUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Y\x00\x00\x00" + + "\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x04\f\xb0\xff\xff\xff\xff\x9e\xa6:\x90\xff\xff\xff\xff\x9f\xbb\a\x80\xff\xff\xff\xff\xa0\x86\x1c\x90\xff\xff\xff\xff\xa1\x9a\xe9\x80\xff\xff\xff\xffˉ\f\x90\xff\xff\xff\xff\xd2#\xf4" + + "p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff\xfa\xf8u\x10\xff\xff\xff\xff\xfb\xe8X\x00\xff\xff\xff\xff\xfc\xd8W\x10\xff\xff\xff\xff\xfd\xc8:\x00\xff\xff\xff\xff\xfe\xb89\x10\xff\xff\xff\xff\xff\xa8\x1c\x00\x00\x00\x00" + + "\x00\x00\x98\x1b\x10\x00\x00\x00\x00\x01\x87\xfe\x00\x00\x00\x00\x00\x02w\xfd\x10\x00\x00\x00\x00\x03q\x1a\x80\x00\x00\x00\x00\x04a\x19\x90\x00\x00\x00\x00\x05P\xfc\x80\x00\x00\x00\x00\x06@\xfb\x90\x00\x00\x00\x00\a0\xde" + + "\x80\x00\x00\x00\x00\a\x8d5\x90\x00\x00\x00\x00\t\x10\xc0\x80\x00\x00\x00\x00\t\xad\xb1\x10\x00\x00\x00\x00\n\xf0\xa2\x80\x00\x00\x00\x00\vࡐ\x00\x00\x00\x00\fٿ\x00\x00\x00\x00\x00\r\xc0\x83\x90\x00\x00\x00" + + "\x00\x0e\xb9\xa1\x00\x00\x00\x00\x00\x0f\xa9\xa0\x10\x00\x00\x00\x00\x10\x99\x83\x00\x00\x00\x00\x00\x11\x89\x82\x10\x00\x00\x00\x00\x12ye\x00\x00\x00\x00\x00\x13id\x10\x00\x00\x00\x00\x14YG\x00\x00\x00\x00\x00\x15IF" + + "\x10\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17)(\x10\x00\x00\x00\x00\x18\"E\x80\x00\x00\x00\x00\x19\t\n\x10\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2&\x90\x00\x00\x00\x00\x1b\xe2\t\x80\x00\x00\x00" + + "\x00\x1c\xd2\b\x90\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1\xea\x90\x00\x00\x00\x00\x1f\xa1̀\x00\x00\x00\x00 v\x1d\x10\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xff\x10\x00\x00\x00\x00#j\xcc" + + "\x00\x00\x00\x00\x00$5\xe1\x10\x00\x00\x00\x00%J\xae\x00\x00\x00\x00\x00&\x15\xc3\x10\x00\x00\x00\x00'*\x90\x00\x00\x00\x00\x00'\xfeߐ\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\xde\xc1\x90\x00\x00\x00" + + "\x00*\xeaT\x00\x00\x00\x00\x00+\xbe\x95\x80\x00\x00\x00\x00,\xd3bp\x00\x00\x00\x00-\x9ew\x80\x00\x00\x00\x00.\xb3Dp\x00\x00\x00\x00/~Y\x80\x00\x00\x00\x000\x93&p\x00\x00\x00\x001gv" + + "\x00\x00\x00\x00\x002s\bp\x00\x00\x00\x003GX\x00\x00\x00\x00\x004R\xeap\x00\x00\x00\x005':\x00\x00\x00\x00\x0062\xccp\x00\x00\x00\x007\a\x1c\x00\x00\x00\x00\x008\x1b\xe8\xf0\x00\x00\x00" + + "\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xca\xf0\x00\x00\x00\x00:\xc6\xe0\x00\x00\x00\x00\x00;۬\xf0\x00\x00\x00\x00<\xaf\xfc\x80\x00\x00\x00\x00=\xbb\x8e\xf0\x00\x00\x00\x00>\x8fހ\x00\x00\x00\x00?\x9bp" + + "\xf0\x00\x00\x00\x00@o\xc0\x80\x00\x00\x00\x00A\x84\x8dp\x00\x00\x00\x00BO\xa2\x80\x00\x00\x00\x00Cdop\x00\x00\x00\x00D/\x84\x80\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7\x00\x02\x01\x02" + + "\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x06\x05\x06\x05" + + "\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\xff\xff\xa1\b\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\f\xff\xff\xab\xa0\x01\x10\xff\xff\xb9\xb0" + + "\x01\x14\xff\xff\xab\xa0\x00\x18LMT\x00MDT\x00MST\x00MWT\x00MPT\x00CDT\x00CST\x00\nCST6CDT,M3.2.0,M11.1.0\n" + + "PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb7.\xb6*\x13\x04\x00\x00\x13\x04\x00\x00\x1b\x00\x1c\x00America/North_Dakota/BeulahUT\t" + + "\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x00\x00\x00\x06\x00\x00\x00\x18" + + "\xff\xff\xff\xff^\x04\f\xb0\xff\xff\xff\xff\x9e\xa6:\x90\xff\xff\xff\xff\x9f\xbb\a\x80\xff\xff\xff\xff\xa0\x86\x1c\x90\xff\xff\xff\xff\xa1\x9a\xe9\x80\xff\xff\xff\xffˉ\f\x90\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff" + + "\xd2a\x18\x00\xff\xff\xff\xff\xfa\xf8u\x10\xff\xff\xff\xff\xfb\xe8X\x00\xff\xff\xff\xff\xfc\xd8W\x10\xff\xff\xff\xff\xfd\xc8:\x00\xff\xff\xff\xff\xfe\xb89\x10\xff\xff\xff\xff\xff\xa8\x1c\x00\x00\x00\x00\x00\x00\x98\x1b\x10" + + "\x00\x00\x00\x00\x01\x87\xfe\x00\x00\x00\x00\x00\x02w\xfd\x10\x00\x00\x00\x00\x03q\x1a\x80\x00\x00\x00\x00\x04a\x19\x90\x00\x00\x00\x00\x05P\xfc\x80\x00\x00\x00\x00\x06@\xfb\x90\x00\x00\x00\x00\a0ހ\x00\x00\x00\x00" + + "\a\x8d5\x90\x00\x00\x00\x00\t\x10\xc0\x80\x00\x00\x00\x00\t\xad\xb1\x10\x00\x00\x00\x00\n\xf0\xa2\x80\x00\x00\x00\x00\vࡐ\x00\x00\x00\x00\fٿ\x00\x00\x00\x00\x00\r\xc0\x83\x90\x00\x00\x00\x00\x0e\xb9\xa1\x00" + + "\x00\x00\x00\x00\x0f\xa9\xa0\x10\x00\x00\x00\x00\x10\x99\x83\x00\x00\x00\x00\x00\x11\x89\x82\x10\x00\x00\x00\x00\x12ye\x00\x00\x00\x00\x00\x13id\x10\x00\x00\x00\x00\x14YG\x00\x00\x00\x00\x00\x15IF\x10\x00\x00\x00\x00" + + "\x169)\x00\x00\x00\x00\x00\x17)(\x10\x00\x00\x00\x00\x18\"E\x80\x00\x00\x00\x00\x19\t\n\x10\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2&\x90\x00\x00\x00\x00\x1b\xe2\t\x80\x00\x00\x00\x00\x1c\xd2\b\x90" + + "\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1\xea\x90\x00\x00\x00\x00\x1f\xa1̀\x00\x00\x00\x00 v\x1d\x10\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xff\x10\x00\x00\x00\x00#j\xcc\x00\x00\x00\x00\x00" + + "$5\xe1\x10\x00\x00\x00\x00%J\xae\x00\x00\x00\x00\x00&\x15\xc3\x10\x00\x00\x00\x00'*\x90\x00\x00\x00\x00\x00'\xfeߐ\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\xde\xc1\x90\x00\x00\x00\x00*\xeaT\x00" + + "\x00\x00\x00\x00+\xbe\xa3\x90\x00\x00\x00\x00,\xd3p\x80\x00\x00\x00\x00-\x9e\x85\x90\x00\x00\x00\x00.\xb3R\x80\x00\x00\x00\x00/~g\x90\x00\x00\x00\x000\x934\x80\x00\x00\x00\x001g\x84\x10\x00\x00\x00\x00" + + "2s\x16\x80\x00\x00\x00\x003Gf\x10\x00\x00\x00\x004R\xf8\x80\x00\x00\x00\x005'H\x10\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe7\f\x10" + + "\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xc6\xee\x10\x00\x00\x00\x00;ۻ\x00\x00\x00\x00\x00<\xb0\n\x90\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8f\xec\x90\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00" + + "@oΐ\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00BO\xb0\x90\x00\x00\x00\x00Cd}\x80\x00\x00\x00\x00D/\x92\x90\x00\x00\x00\x00ED_\x80\x00\x00\x00\x00E\xf3\xc5\x10\x00\x00\x00\x00G-|\x00" + + "\x00\x00\x00\x00Gӧ\x10\x00\x00\x00\x00I\r^\x00\x00\x00\x00\x00I\xb3\x89\x10\x00\x00\x00\x00J\xed@\x00\x00\x00\x00\x00K\x9c\xa5\x90\x00\x00\x00\x00L\xd6\\\x80\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x05\xff\xff\xa0\x95\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\f\xff\xff\xab\xa0\x01\x10\xff\xff\xab\xa0\x00\x14" + + "LMT\x00MDT\x00MST\x00MWT\x00MPT\x00CST\x00\nCST6CDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82" + + "iSa\xcb'\xe9\x9c\x01\x00\x00\x9c\x01\x00\x00\x0e\x00\x1c\x00America/ManausUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00" + + "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96\xaa\u007fD\xff\xff\xff\xff\xb8\x0fW\xf0\xff\xff\xff\xff\xb8\xfdN\xb0\xff" + + "\xff\xff\xff\xb9\xf1B@\xff\xff\xff\xff\xbaނ0\xff\xff\xff\xff\xda8\xbc@\xff\xff\xff\xff\xda\xec\b@\xff\xff\xff\xff\xdc\x19\xef\xc0\xff\xff\xff\xffܹg0\xff\xff\xff\xff\xdd\xfb#@\xff\xff\xff\xff\xde" + + "\x9b\xec0\xff\xff\xff\xff\xdfݨ@\xff\xff\xff\xff\xe0TA0\xff\xff\xff\xff\xf4\x98\r\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf6\xc0r@\xff\xff\xff\xff\xf7\x0e,\xb0\xff\xff\xff\xff\xf8Q:@\xff" + + "\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xfa\n\xe0\xc0\xff\xff\xff\xff\xfa\xa9\x06\xb0\xff\xff\xff\xff\xfb\xec\x14@\xff\xff\xff\xff\xfc\x8b\x8b\xb0\x00\x00\x00\x00\x1dɜ@\x00\x00\x00\x00\x1ex\xe5\xb0\x00\x00\x00\x00\x1f" + + "\xa0C\xc0\x00\x00\x00\x00 3ݰ\x00\x00\x00\x00!\x81w@\x00\x00\x00\x00\"\vְ\x00\x00\x00\x00,\xc0\xc3@\x00\x00\x00\x00-f\xd20\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xffǼ\x00\x00\xff\xff\xd5\xd0\x01\x04\xff\xff\xc7\xc0\x00\bLMT\x00-03\x00-04\x00\n<-04>4\nPK\x03\x04\n\x00\x00\x00" + + "\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x15\x00\x1c\x00America/Port_of_SpainUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00" + + "\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00" + + "\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffz敹\xff\xff\xff\xff\xcb\xf6" + + "2\xc0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\x01\x03\x02\x01\xff\xff\xc2\a\x00\x00\xff\xff\xc7\xc0\x00\x04\xff\xff\xd5\xd0\x01\b\xff\xff\xd5\xd0\x01\fLMT\x00AST\x00APT\x00AW" + + "T\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSŒZ\x8c\xc4\x02\x00\x00\xc4\x02\x00\x00\x0f\x00\x1c\x00America/MendozaUT\t\x00\x03\x82\x0f" + + "\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xff" + + "r\x9c\xb2\x04\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0" + + "\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff" + + "\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@" + + "\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff" + + "\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0" + + "\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00" + + "#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'\x194@\x00\x00\x00\x00'\xcdð\x00\x00\x00\x00(\xfag\xc0\x00\x00\x00\x00)\xb0H\xb0" + + "\x00\x00\x00\x00*\xe0\xe1@\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00@\xb0\x13\xb0\x00\x00\x00\x00AV>\xc0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00" + + "G\xdc\u007f \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x02\x03\x02\x03\x02\x04\x05\x03" + + "\x05\x02\x05\x04\x05\xff\xff\xbf|\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02" + + "\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xac\x8a\x83S\xd4\x00\x00\x00\xd4\x00\x00\x00\x11\x00\x1c\x00America/GuatemalaUT\t\x00" + + "\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x03\x00\x00\x00\f\xff" + + "\xff\xff\xff\x9f\x9d\xea\xdc\x00\x00\x00\x00\aU\xac`\x00\x00\x00\x00\a͖\xd0\x00\x00\x00\x00\x19,x`\x00\x00\x00\x00\x19\xcf\xe4P\x00\x00\x00\x00'\xea\xee\xe0\x00\x00\x00\x00(\xc8\\\xd0\x00\x00\x00\x00D" + + "TR`\x00\x00\x00\x00E\x1fKP\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xff\xab$\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\bLMT\x00CDT\x00CST\x00\nCST6\nPK\x03\x04" + + "\n\x00\x00\x00\x00\x00#\x82iSU!\x12f\xd9\x02\x00\x00\xd9\x02\x00\x00\x13\x00\x1c\x00America/YellowknifeUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux" + + "\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00" + + "\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x06\x00\x00\x00\x19\xff\xff\xff\xff\xbe*\x18\x00\xff\xff\xff\xff" + + "ˉ\f\x90\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff\xf7/Zp\xff\xff\xff\xff\xf8(\x85\xf0\x00\x00\x00\x00\x13id\x10\x00\x00\x00\x00\x14YG\x00\x00\x00\x00\x00\x15IF\x10" + "\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17)(\x10\x00\x00\x00\x00\x18\"E\x80\x00\x00\x00\x00\x19\t\n\x10\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2&\x90\x00\x00\x00\x00\x1b\xe2\t\x80\x00\x00\x00\x00" + "\x1c\xd2\b\x90\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1\xea\x90\x00\x00\x00\x00\x1f\xa1̀\x00\x00\x00\x00 v\x1d\x10\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xff\x10\x00\x00\x00\x00#j\xcc\x00" + "\x00\x00\x00\x00$5\xe1\x10\x00\x00\x00\x00%J\xae\x00\x00\x00\x00\x00&\x15\xc3\x10\x00\x00\x00\x00'*\x90\x00\x00\x00\x00\x00'\xfeߐ\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\xde\xc1\x90\x00\x00\x00\x00" + "*\xeaT\x00\x00\x00\x00\x00+\xbe\xa3\x90\x00\x00\x00\x00,\xd3p\x80\x00\x00\x00\x00-\x9e\x85\x90\x00\x00\x00\x00.\xb3R\x80\x00\x00\x00\x00/~g\x90\x00\x00\x00\x000\x934\x80\x00\x00\x00\x001g\x84\x10" + "\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003Gf\x10\x00\x00\x00\x004R\xf8\x80\x00\x00\x00\x005'H\x10\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x00" + "8\xe7\f\x10\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xc6\xee\x10\x00\x00\x00\x00;ۻ\x00\x00\x00\x00\x00<\xb0\n\x90\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8f\xec\x90\x00\x00\x00\x00?\x9b\u007f\x00" + - "\x00\x00\x00\x00@oΐ\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00BO\xb0\x90\x00\x00\x00\x00Cd}\x80\x00\x00\x00\x00D/\x92\x90\x00\x00\x00\x00ED_\x80\x00\x00\x00\x00E\xf3\xc5\x10\x02\x01\x02\x03" + - "\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x00\x00\x00\x00\x00" + - "\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x8f\x80\x00\t\xff\xff\x9d\x90\x00\r\xff\xff\xab\xa0\x01\x11-00\x00PDDT\x00PST\x00MST\x00MDT\x00\nMST7MDT,M3.2." + - "0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RU!\x12f\xd9\x02\x00\x00\xd9\x02\x00\x00\x13\x00\x1c\x00America/YellowknifeU" + - "T\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x06\x00\x00" + - "\x00\x19\xff\xff\xff\xff\xbe*\x18\x00\xff\xff\xff\xffˉ\f\x90\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff\xf7/Zp\xff\xff\xff\xff\xf8(\x85\xf0\x00\x00\x00\x00\x13id\x10\x00\x00" + - "\x00\x00\x14YG\x00\x00\x00\x00\x00\x15IF\x10\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17)(\x10\x00\x00\x00\x00\x18\"E\x80\x00\x00\x00\x00\x19\t\n\x10\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2" + - "&\x90\x00\x00\x00\x00\x1b\xe2\t\x80\x00\x00\x00\x00\x1c\xd2\b\x90\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1\xea\x90\x00\x00\x00\x00\x1f\xa1̀\x00\x00\x00\x00 v\x1d\x10\x00\x00\x00\x00!\x81\xaf\x80\x00\x00" + - "\x00\x00\"U\xff\x10\x00\x00\x00\x00#j\xcc\x00\x00\x00\x00\x00$5\xe1\x10\x00\x00\x00\x00%J\xae\x00\x00\x00\x00\x00&\x15\xc3\x10\x00\x00\x00\x00'*\x90\x00\x00\x00\x00\x00'\xfeߐ\x00\x00\x00\x00)\n" + - "r\x00\x00\x00\x00\x00)\xde\xc1\x90\x00\x00\x00\x00*\xeaT\x00\x00\x00\x00\x00+\xbe\xa3\x90\x00\x00\x00\x00,\xd3p\x80\x00\x00\x00\x00-\x9e\x85\x90\x00\x00\x00\x00.\xb3R\x80\x00\x00\x00\x00/~g\x90\x00\x00" + - "\x00\x000\x934\x80\x00\x00\x00\x001g\x84\x10\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003Gf\x10\x00\x00\x00\x004R\xf8\x80\x00\x00\x00\x005'H\x10\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a" + - "*\x10\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe7\f\x10\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xc6\xee\x10\x00\x00\x00\x00;ۻ\x00\x00\x00\x00\x00<\xb0\n\x90\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00" + - "\x00\x00>\x8f\xec\x90\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@oΐ\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00BO\xb0\x90\x00\x00\x00\x00Cd}\x80\x00\x00\x00\x00D/\x92\x90\x00\x00\x00\x00ED" + - "_\x80\x00\x00\x00\x00E\xf3\xc5\x10\x03\x01\x02\x03\x04\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03" + - "\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x00\x00\x00\x00\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\xab\xa0\x01\b\xff\xff\x9d\x90\x00\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xab\xa0\x01\x15-00\x00MWT\x00MPT\x00M" + - "ST\x00MDDT\x00MDT\x00\nMST7MDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x10\x00\x1c\x00America/Indiana/UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x03\x04\n\x00\x00\x00\x00\x00" + - "\xf1c9R$ \x873\xf8\x03\x00\x00\xf8\x03\x00\x00\x14\x00\x1c\x00America/Indiana/KnoxUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8" + - "\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00T" + - "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00]\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff" + - "\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xd5U\xd5\x00\xff\xff\xff\xff\xd6" + - " \xcd\xf0\xff\xff\xff\xff\xd75\xb7\x00\xff\xff\xff\xff\xd8\x00\xaf\xf0\xff\xff\xff\xff\xd9\x15\x99\x00\xff\xff\xff\xff\xd9\xe0\x91\xf0\xff\xff\xff\xff\xda\xfe\xb5\x80\xff\xff\xff\xff\xdb\xc0s\xf0\xff\xff\xff\xff\xdcޗ\x80\xff" + - "\xff\xff\xffݩ\x90p\xff\xff\xff\xff\u07bey\x80\xff\xff\xff\xff߉rp\xff\xff\xff\xff\xe0\x9e[\x80\xff\xff\xff\xff\xe1iTp\xff\xff\xff\xff\xe2~=\x80\xff\xff\xff\xff\xe3I6p\xff\xff\xff\xff\xe4" + - "^\x1f\x80\xff\xff\xff\xff\xe5W<\xf0\xff\xff\xff\xff\xe6G<\x00\xff\xff\xff\xff\xe77\x1e\xf0\xff\xff\xff\xff\xe8'\x1e\x00\xff\xff\xff\xff\xe8\xf2\x16\xf0\xff\xff\xff\xff\xea\a\x00\x00\xff\xff\xff\xff\xea\xd1\xf8\xf0\xff" + - "\xff\xff\xff\xeb\xe6\xe2\x00\xff\xff\xff\xff\xec\xd6\xc4\xf0\xff\xff\xff\xff\xed\xc6\xc4\x00\xff\xff\xff\xff\xee\xbf\xe1p\xff\xff\xff\xff\xef\xaf\xe0\x80\xff\xff\xff\xff\xf0\x9f\xc3p\xff\xff\xff\xff\xf1\x8f\u0080\xff\xff\xff\xff\xf4" + - "_\x87p\xff\xff\xff\xff\xfa\xf8g\x00\xff\xff\xff\xff\xfb\xe8I\xf0\xff\xff\xff\xff\xfc\xd8I\x00\xff\xff\xff\xff\xfd\xc8+\xf0\xff\xff\xff\xff\xfe\xb8+\x00\xff\xff\xff\xff\xff\xa8\r\xf0\x00\x00\x00\x00\x00\x98\r\x00\x00" + - "\x00\x00\x00\x01\x87\xef\xf0\x00\x00\x00\x00\x02w\xef\x00\x00\x00\x00\x00\x03q\fp\x00\x00\x00\x00\x04a\v\x80\x00\x00\x00\x00\x05P\xeep\x00\x00\x00\x00\x06@\xed\x80\x00\x00\x00\x00\a0\xd0p\x00\x00\x00\x00\a" + - "\x8d'\x80\x00\x00\x00\x00\t\x10\xb2p\x00\x00\x00\x00\t\xad\xa3\x00\x00\x00\x00\x00\n\xf0\x94p\x00\x00\x00\x00\v\xe0\x93\x80\x00\x00\x00\x00\fٰ\xf0\x00\x00\x00\x00\r\xc0u\x80\x00\x00\x00\x00\x0e\xb9\x92\xf0\x00" + - "\x00\x00\x00\x0f\xa9\x92\x00\x00\x00\x00\x00\x10\x99t\xf0\x00\x00\x00\x00\x11\x89t\x00\x00\x00\x00\x00\x12yV\xf0\x00\x00\x00\x00\x13iV\x00\x00\x00\x00\x00\x14Y8\xf0\x00\x00\x00\x00\x15I8\x00\x00\x00\x00\x00\x16" + - "9\x1a\xf0\x00\x00\x00\x00\x17)\x1a\x00\x00\x00\x00\x00\x18\"7p\x00\x00\x00\x00\x19\b\xfc\x00\x00\x00\x00\x00\x1a\x02\x19p\x00\x00\x00\x00\x1a\xf2\x18\x80\x00\x00\x00\x00\x1b\xe1\xfbp\x00\x00\x00\x00\x1c\xd1\xfa\x80\x00" + - "\x00\x00\x00\x1d\xc1\xddp\x00\x00\x00\x00\x1e\xb1܀\x00\x00\x00\x00\x1f\xa1\xbfp\x00\x00\x00\x00 v\x0f\x00\x00\x00\x00\x00!\x81\xa1p\x00\x00\x00\x00\"U\xf1\x00\x00\x00\x00\x00#j\xbd\xf0\x00\x00\x00\x00$" + - "5\xd3\x00\x00\x00\x00\x00%J\x9f\xf0\x00\x00\x00\x00&\x15\xb5\x00\x00\x00\x00\x00'*\x81\xf0\x00\x00\x00\x00'\xfeр\x00\x00\x00\x00)\nc\xf0\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDQp\x00" + - "\x00\x00\x00E\xf3\xb7\x00\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x05\x01\x02\x01\xff\xff\xae\xca\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff" + - "\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14LMT\x00CDT\x00CST\x00CWT\x00CPT\x00EST\x00\nCST6CDT,M3.2.0,M11." + - "1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x01\xd8N\x8c\xab\x02\x00\x00\xab\x02\x00\x00\x1a\x00\x1c\x00America/Indiana/Petersburg" + - "UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x06\x00" + - "\x00\x00\x18\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff" + - "\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xe4g=\xe0\xff\xff\xff\xff\xe5)\x18p\xff\xff\xff\xff\xe6G<\x00\xff\xff\xff\xff\xe7\x124\xf0\xff\xff\xff\xff\xe8'\x1e\x00\xff\xff\xff\xff\xe8\xf2\x16\xf0\xff\xff\xff\xff\xea" + - "\a\x00\x00\xff\xff\xff\xff\xea\xd1\xf8\xf0\xff\xff\xff\xff\xeb\xe6\xe2\x00\xff\xff\xff\xff\xec\xb1\xda\xf0\xff\xff\xff\xff\xed\xc6\xc4\x00\xff\xff\xff\xff\ue47c\xf0\xff\xff\xff\xff\xef\xaf\xe0\x80\xff\xff\xff\xff\xf0\x9f\xc3p\xff" + - "\xff\xff\xff\xf1\x8f\u0080\xff\xff\xff\xff\xf2\u007f\xa5p\xff\xff\xff\xff\xf3o\xa4\x80\xff\xff\xff\xff\xf4_\x87p\xff\xff\xff\xff\xf5O\x86\x80\xff\xff\xff\xff\xf6?ip\xff\xff\xff\xff\xf7/h\x80\xff\xff\xff\xff\xfa" + - "\bg\xf0\xff\xff\xff\xff\xfa\xf8g\x00\xff\xff\xff\xff\xfb\xe8I\xf0\xff\xff\xff\xff\xfc\xd8I\x00\xff\xff\xff\xff\xfd\xc8+\xf0\xff\xff\xff\xff\xfe\xb8+\x00\xff\xff\xff\xff\xff\xa8\r\xf0\x00\x00\x00\x00\x00\x98\r\x00\x00" + - "\x00\x00\x00\x01\x87\xef\xf0\x00\x00\x00\x00\x02w\xef\x00\x00\x00\x00\x00\x03q\fp\x00\x00\x00\x00\x04a\v\x80\x00\x00\x00\x00\x05P\xeep\x00\x00\x00\x00\x06@\xed\x80\x00\x00\x00\x00\a0\xd0p\x00\x00\x00\x00\a" + - "\x8d'\x80\x00\x00\x00\x00\t\x10\xb2p\x00\x00\x00\x00\t\xad\xa3\x00\x00\x00\x00\x00\n\xf0\x94p\x00\x00\x00\x00\v\xe0\x93\x80\x00\x00\x00\x00\fٰ\xf0\x00\x00\x00\x00\r\xc0u\x80\x00\x00\x00\x00\x0e\xb9\x92\xf0\x00" + - "\x00\x00\x00D/vp\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7\x00\x00\x00\x00\x00G-m\xf0\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x05\x01\x02\x01\x05\xff\xff\xae-\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9" + - "\xb0\x00\x14LMT\x00CDT\x00CST\x00CWT\x00CPT\x00EST\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00" + - "\x00\xf1c9Rp\xb6{\xc9\x13\x02\x00\x00\x13\x02\x00\x00\x1c\x00\x1c\x00America/Indiana/IndianapolisUT\t\x00\x03\x15\xac\x0e`\x15\xac" + - "\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" + - "\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00&\x00\x00\x00\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x03\xfe\xa0" + - "\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xff\xcaW\"\x80\xff\xff\xff\xff\xca\xd8Gp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff" + - "\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xd3u\xf3\x00\xff\xff\xff\xff\xd4@\xeb\xf0\xff\xff\xff\xff\xd5U\xd5\x00\xff\xff\xff\xff\xd6 \xcd\xf0\xff\xff\xff\xff\xd75\xb7\x00\xff\xff\xff\xff\xd8\x00\xaf\xf0" + - "\xff\xff\xff\xff\xd9\x15\x99\x00\xff\xff\xff\xff\xd9\xe0\x91\xf0\xff\xff\xff\xff\xda\xfe\xb5\x80\xff\xff\xff\xff\xdb\xc0s\xf0\xff\xff\xff\xff\xdcޗ\x80\xff\xff\xff\xffݩ\x90p\xff\xff\xff\xff\u07bey\x80\xff\xff\xff\xff" + - "߉rp\xff\xff\xff\xff\xe0\x9e[\x80\xff\xff\xff\xff\xe1iTp\xff\xff\xff\xff\xe2~=\x80\xff\xff\xff\xff\xe3I6p\xff\xff\xff\xff\xe4^\x1f\x80\xff\xff\xff\xff\xe8\xf2\x16\xf0\xff\xff\xff\xff\xea\a\x00\x00" + - "\xff\xff\xff\xff\xfe\xb8\x1c\xf0\xff\xff\xff\xff\xff\xa7\xff\xe0\x00\x00\x00\x00\x00\x97\xfe\xf0\x00\x00\x00\x00\x01\x87\xe1\xe0\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01" + - "\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05\x02\x05\x06\x05\x06\x05\x06\x05\x06\xff\xff\xaf:\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff" + - "\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14\xff\xff\xc7\xc0\x01\x18LMT\x00CDT\x00CST\x00CWT\x00CPT\x00EST\x00EDT\x00\nEST5EDT,M3.2.0," + - "M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RصK\xa6\n\x02\x00\x00\n\x02\x00\x00\x19\x00\x1c\x00America/Indiana/Tell_C" + - "ityUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00%\x00\x00" + - "\x00\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#" + - "\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xe4g=\xe0\xff\xff\xff\xff\xe5)\x18p\xff\xff\xff\xff\xe6G<\x00\xff\xff\xff\xff\xe7\x124\xf0\xff\xff\xff\xff\xe8'\x1e\x00\xff\xff\xff\xff\xe8\xf2\x16\xf0\xff\xff" + - "\xff\xff\xea\a\x00\x00\xff\xff\xff\xff\xea\xd1\xf8\xf0\xff\xff\xff\xff\xeb\xe6\xe2\x00\xff\xff\xff\xff\xec\xb1\xda\xf0\xff\xff\xff\xff\xed\xc6\xc4\x00\xff\xff\xff\xff\ue47c\xf0\xff\xff\xff\xff\xef\xaf\xe0\x80\xff\xff\xff\xff\xf0\x9f" + - "\xc3p\xff\xff\xff\xff\xf1\x8f\u0080\xff\xff\xff\xff\xf2\u007f\xa5p\xff\xff\xff\xff\xf3o\xa4\x80\xff\xff\xff\xff\xf4_\x87p\xff\xff\xff\xff\xf5O\x86\x80\xff\xff\xff\xff\xfb\xe8I\xf0\xff\xff\xff\xff\xfc\xd8I\x00\xff\xff" + - "\xff\xff\xfd\xc8+\xf0\xff\xff\xff\xff\xfe\xb8+\x00\xff\xff\xff\xff\xff\xa7\xff\xe0\x00\x00\x00\x00\x00\x97\xfe\xf0\x00\x00\x00\x00\x01\x87\xe1\xe0\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3" + - "\xb7\x00\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05\x02\x01\x02\x06\x05\x06\x05\x01\x02\x01\xff\xff\xae\xa9\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9" + - "\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14\xff\xff\xc7\xc0\x01\x18LMT\x00CDT\x00CST\x00CWT\x00CPT\x00EST\x00EDT\x00\nCST6CDT,M3" + - ".2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R \x17\x89}q\x01\x00\x00q\x01\x00\x00\x15\x00\x1c\x00America/Indiana/V" + - "evayUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x00" + - "\x00\x00\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2" + - "#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xe2~=\x80\xff\xff\xff\xff\xfe\xb8\x1c\xf0\xff\xff\xff\xff\xff\xa7\xff\xe0\x00\x00\x00\x00\x00\x97\xfe\xf0\x00\x00\x00\x00\x01\x87\xe1\xe0\x00\x00\x00\x00\x02w\xe0\xf0\x00" + - "\x00\x00\x00\x03p\xfe`\x00\x00\x00\x00\x04`\xfdp\x00\x00\x00\x00\x05P\xe0`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x02\x03\x04\x02\x05\x06\x05\x06\x05" + - "\x06\x05\x06\x05\x06\x05\x06\xff\xff\xb0@\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14\xff\xff\xc7\xc0\x01\x18LMT\x00CDT\x00CST" + - "\x00CWT\x00CPT\x00EST\x00EDT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RK-E\xfad" + - "\x02\x00\x00d\x02\x00\x00\x17\x00\x1c\x00America/Indiana/WinamacUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03" + - "\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00/\x00\x00\x00\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9" + - "p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xd3u\xf3\x00\xff\xff\xff\xff\xd4@\xeb\xf0\xff\xff\xff" + - "\xff\xd5U\xd5\x00\xff\xff\xff\xff\xd6 \xcd\xf0\xff\xff\xff\xff\xd75\xb7\x00\xff\xff\xff\xff\xd8\x00\xaf\xf0\xff\xff\xff\xff\xd9\x15\x99\x00\xff\xff\xff\xff\xd9\xe0\x91\xf0\xff\xff\xff\xff\xda\xfe\xb5\x80\xff\xff\xff\xff\xdb\xc0s" + - "\xf0\xff\xff\xff\xff\xdcޗ\x80\xff\xff\xff\xffݩ\x90p\xff\xff\xff\xff\u07bey\x80\xff\xff\xff\xff߉rp\xff\xff\xff\xff\xe0\x9e[\x80\xff\xff\xff\xff\xe1iTp\xff\xff\xff\xff\xe2~=\x80\xff\xff\xff" + - "\xff\xe3I6p\xff\xff\xff\xff\xe4^\x1f\x80\xff\xff\xff\xff\xe5W<\xf0\xff\xff\xff\xff\xe6G<\x00\xff\xff\xff\xff\xe77\x1e\xf0\xff\xff\xff\xff\xe8'\x1e\x00\xff\xff\xff\xff\xe8\xf2\x16\xf0\xff\xff\xff\xff\xea\a\x00" + - "\x00\xff\xff\xff\xff\xea\xd1\xf8\xf0\xff\xff\xff\xff\xeb\xe6\xe2\x00\xff\xff\xff\xff\xec\xb1\xda\xf0\xff\xff\xff\xff\xed\xc6\xc4\x00\xff\xff\xff\xff\ue47c\xf0\xff\xff\xff\xff\xef\xaf\xe0\x80\xff\xff\xff\xff\xfe\xb8\x1c\xf0\xff\xff\xff" + - "\xff\xff\xa7\xff\xe0\x00\x00\x00\x00\x00\x97\xfe\xf0\x00\x00\x00\x00\x01\x87\xe1\xe0\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7\x00\x00\x00\x00\x00G-_\xe0\x02\x01\x02\x01\x02\x03\x04" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05\x06\x05\x06\x05\x01\x02\x06\x05\xff\xff\xae\xcf\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff" + - "\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14\xff\xff\xc7\xc0\x01\x18LMT\x00CDT\x00CST\x00CWT\x00CPT\x00EST\x00EDT\x00\nEST5EDT,M" + - "3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RM/U\x9f7\x02\x00\x007\x02\x00\x00\x17\x00\x1c\x00America/Indiana/" + - "MarengoUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00*\x00\x00\x00\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xffˈ\xfe\x80\xff\xff" + - "\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xdcޗ\x80\xff\xff\xff\xffݩ\x90p\xff\xff\xff\xff\xe2~=\x80\xff\xff\xff\xff\xe3I6p\xff\xff\xff\xff\xe4^\x1f\x80\xff\xff\xff\xff\xe5)" + - "\x18p\xff\xff\xff\xff\xe6G<\x00\xff\xff\xff\xff\xe7\x124\xf0\xff\xff\xff\xff\xe8'\x1e\x00\xff\xff\xff\xff\xe8\xf2\x16\xf0\xff\xff\xff\xff\xea\a\x00\x00\xff\xff\xff\xff\xea\xd1\xf8\xf0\xff\xff\xff\xff\xeb\xe6\xe2\x00\xff\xff" + - "\xff\xff\xec\xb1\xda\xf0\xff\xff\xff\xff\xed\xc6\xc4\x00\xff\xff\xff\xff\ue47c\xf0\xff\xff\xff\xff\xef\xaf\xe0\x80\xff\xff\xff\xff\xfe\xb8\x1c\xf0\xff\xff\xff\xff\xff\xa7\xff\xe0\x00\x00\x00\x00\x00\x97\xfe\xf0\x00\x00\x00\x00\x01\x87" + - "\xe1\xe0\x00\x00\x00\x00\x02w\xe0\xf0\x00\x00\x00\x00\x03p\xfe`\x00\x00\x00\x00\x04`\xfdp\x00\x00\x00\x00\x05P\xe0`\x00\x00\x00\x00\x06@\xdfp\x00\x00\x00\x00\a0\xc2`\x00\x00\x00\x00\a\x8d\x19p\x00\x00" + - "\x00\x00\t\x10\xb2p\x00\x00\x00\x00\t\xad\x94\xf0\x00\x00\x00\x00\n\xf0\x86`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x01\x05\x06\x05\x06\x05\x06\xff\xff\xaf\r\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff" + - "\xb9\xb0\x00\x14\xff\xff\xc7\xc0\x01\x18LMT\x00CDT\x00CST\x00CWT\x00CPT\x00EST\x00EDT\x00\nEST5EDT,M3.2.0,M11.1." + - "0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\r\xedsp.\x02\x00\x00.\x02\x00\x00\x19\x00\x1c\x00America/Indiana/VincennesUT\t" + - "\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00)\x00\x00\x00\a\x00\x00\x00\x1c" + - "\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff" + - "\xd2a\t\xf0\xff\xff\xff\xff\xd3u\xf3\x00\xff\xff\xff\xff\xd4@\xeb\xf0\xff\xff\xff\xff\xe0\x9e[\x80\xff\xff\xff\xff\xe1iTp\xff\xff\xff\xff\xe2~=\x80\xff\xff\xff\xff\xe3I6p\xff\xff\xff\xff\xe4g=\xe0" + - "\xff\xff\xff\xff\xe5)\x18p\xff\xff\xff\xff\xe6G<\x00\xff\xff\xff\xff\xe7\x124\xf0\xff\xff\xff\xff\xe8'\x1e\x00\xff\xff\xff\xff\xe8\xf2\x16\xf0\xff\xff\xff\xff\xea\a\x00\x00\xff\xff\xff\xff\xea\xd1\xf8\xf0\xff\xff\xff\xff" + - "\xeb\xe6\xe2\x00\xff\xff\xff\xff\xec\xb1\xda\xf0\xff\xff\xff\xff\xed\xc6\xc4\x00\xff\xff\xff\xff\xee\xbf\xe1p\xff\xff\xff\xff\xef\xaf\xe0\x80\xff\xff\xff\xff\xf0q\x9e\xf0\xff\xff\xff\xff\xf1\x8f\u0080\xff\xff\xff\xff\xf2\u007f\xa5p" + - "\xff\xff\xff\xff\xf3o\xa4\x80\xff\xff\xff\xff\xf4_\x87p\xff\xff\xff\xff\xf5O\x86\x80\xff\xff\xff\xff\xfe\xb8\x1c\xf0\xff\xff\xff\xff\xff\xa7\xff\xe0\x00\x00\x00\x00\x00\x97\xfe\xf0\x00\x00\x00\x00\x01\x87\xe1\xe0\x00\x00\x00\x00" + - "D/vp\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7\x00\x00\x00\x00\x00G-m\xf0\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x05\x06\x05\x06\x05\x01\x02\x01\x05\xff\xff\xad\xf1\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14\xff\xff\xc7\xc0\x01\x18LMT\x00CDT\x00C" + - "ST\x00CWT\x00CPT\x00EST\x00EDT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rc)\xf6" + - ")\xb3\x00\x00\x00\xb3\x00\x00\x00\x0e\x00\x1c\x00America/BogotaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff^\x9c4\xf0\xff\xff\xff\xff\x98XUp\x00\x00\x00\x00*\x03sP\x00\x00\x00\x00+\xbe" + - "]@\x01\x03\x02\x03\xff\xff\xba\x90\x00\x00\xff\xff\xba\x90\x00\x04\xff\xff\xc7\xc0\x01\b\xff\xff\xb9\xb0\x00\fLMT\x00BMT\x00-04\x00-05\x00\n<-05>5\nPK\x03\x04\n\x00" + - "\x00\x00\x00\x00\xf1c9R.\xf9\xc0\x1e\xd5\x05\x00\x00\xd5\x05\x00\x00\x0f\x00\x1c\x00America/MonctonUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03" + - "\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + - "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x92\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff^\x1e\xed\xbc\xff\xff\xff\xff\x80\xf1\xb6P\xff\xff" + - "\xff\xff\x9e\xb8\x85`\xff\xff\xff\xff\x9f\xba\xddP\xff\xff\xff\xff\xbb<8\xd0\xff\xff\xff\xff\xbb\xb4#@\xff\xff\xff\xff\xbd\x1c\x1a\xd0\xff\xff\xff\xff\xbd\x94\x05@\xff\xff\xff\xff\xbe\xfb\xfc\xd0\xff\xff\xff\xff\xbfs" + - "\xe7@\xff\xff\xff\xff\xc0\xdb\xde\xd0\xff\xff\xff\xff\xc1S\xc9@\xff\xff\xff\xff»\xc0\xd0\xff\xff\xff\xff\xc33\xab@\xff\xff\xff\xffě\xa2\xd0\xff\xff\xff\xff\xc5\x13\x8d@\xff\xff\xff\xff\xc6p\xf8\xd0\xff\xff" + - "\xff\xff\xc7\r\xcd@\xff\xff\xff\xff\xc8H\xf1\xd0\xff\xff\xff\xff\xc8\xed\xaf@\xff\xff\xff\xff\xca\x16^\xd0\xff\xff\xff\xff\xca\xd6\xcb\xc0\xff\xff\xff\xffˈ\xe2`\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`" + - "\xed\xd0\xff\xff\xff\xff\xd3u\xd6\xe0\xff\xff\xff\xff\xd4@\xcf\xd0\xff\xff\xff\xff\xd5U\xb8\xe0\xff\xff\xff\xff\xd6 \xb1\xd0\xff\xff\xff\xff\xd75\x9a\xe0\xff\xff\xff\xff\xd8\x00\x93\xd0\xff\xff\xff\xff\xd9\x15|\xe0\xff\xff" + - "\xff\xff\xd9\xe0u\xd0\xff\xff\xff\xff\xda\xfe\x99`\xff\xff\xff\xff\xdb\xc0W\xd0\xff\xff\xff\xff\xdc\xde{`\xff\xff\xff\xffݩtP\xff\xff\xff\xff\u07be]`\xff\xff\xff\xff߉VP\xff\xff\xff\xff\xe0\x9e" + - "?`\xff\xff\xff\xff\xe1i8P\xff\xff\xff\xff\xe2~!`\xff\xff\xff\xff\xe3I\x1aP\xff\xff\xff\xff\xe4^\x03`\xff\xff\xff\xff\xe5(\xfcP\xff\xff\xff\xff\xe6G\x1f\xe0\xff\xff\xff\xff\xe7\x12\x18\xd0\xff\xff" + - "\xff\xff\xe8'\x01\xe0\xff\xff\xff\xff\xe9\x16\xe4\xd0\xff\xff\xff\xff\xea\x06\xe3\xe0\xff\xff\xff\xff\xea\xf6\xc6\xd0\xff\xff\xff\xff\xeb\xe6\xc5\xe0\xff\xff\xff\xff\xec֨\xd0\xff\xff\xff\xff\xedƧ\xe0\xff\xff\xff\xff\xee\xbf" + - "\xc5P\xff\xff\xff\xff\xef\xaf\xc4`\xff\xff\xff\xff\xf0\x9f\xa7P\xff\xff\xff\xff\xf1\x8f\xa6`\xff\xff\xff\xff\xf2\u007f\x89P\xff\xff\xff\xff\xf3o\x88`\xff\xff\xff\xff\xf4_kP\xff\xff\xff\xff\xf5Oj`\xff\xff" + - "\xff\xff\xf6?MP\xff\xff\xff\xff\xf7/L`\xff\xff\xff\xff\xf8(i\xd0\xff\xff\xff\xff\xf9\x0f.`\xff\xff\xff\xff\xfa\bK\xd0\xff\xff\xff\xff\xfa\xf8J\xe0\xff\xff\xff\xff\xfb\xe8-\xd0\xff\xff\xff\xff\xfc\xd8" + - ",\xe0\xff\xff\xff\xff\xfd\xc8\x0f\xd0\xff\xff\xff\xff\xfe\xb8\x0e\xe0\xff\xff\xff\xff\xff\xa7\xf1\xd0\x00\x00\x00\x00\x00\x97\xf0\xe0\x00\x00\x00\x00\x01\x87\xd3\xd0\x00\x00\x00\x00\x02w\xd2\xe0\x00\x00\x00\x00\x03p\xf0P\x00\x00" + - "\x00\x00\x04`\xef`\x00\x00\x00\x00\x05P\xd2P\x00\x00\x00\x00\b \xb3`\x00\x00\x00\x00\t\x10\x96P\x00\x00\x00\x00\n\x00\x95`\x00\x00\x00\x00\n\xf0xP\x00\x00\x00\x00\v\xe0w`\x00\x00\x00\x00\f\xd9" + - "\x94\xd0\x00\x00\x00\x00\r\xc0Y`\x00\x00\x00\x00\x0e\xb9v\xd0\x00\x00\x00\x00\x0f\xa9u\xe0\x00\x00\x00\x00\x10\x99X\xd0\x00\x00\x00\x00\x11\x89W\xe0\x00\x00\x00\x00\x12y:\xd0\x00\x00\x00\x00\x13i9\xe0\x00\x00" + - "\x00\x00\x14Y\x1c\xd0\x00\x00\x00\x00\x15I\x1b\xe0\x00\x00\x00\x00\x168\xfe\xd0\x00\x00\x00\x00\x17(\xfd\xe0\x00\x00\x00\x00\x18\"\x1bP\x00\x00\x00\x00\x19\b\xdf\xe0\x00\x00\x00\x00\x1a\x01\xfdP\x00\x00\x00\x00\x1a\xf1" + - "\xfc`\x00\x00\x00\x00\x1b\xe1\xdfP\x00\x00\x00\x00\x1c\xd1\xde`\x00\x00\x00\x00\x1d\xc1\xc1P\x00\x00\x00\x00\x1e\xb1\xc0`\x00\x00\x00\x00\x1f\xa1\xa3P\x00\x00\x00\x00 u\xf2\xe0\x00\x00\x00\x00!\x81\x85P\x00\x00" + - "\x00\x00\"U\xd4\xe0\x00\x00\x00\x00#j\xa1\xd0\x00\x00\x00\x00$5\xb6\xe0\x00\x00\x00\x00%J\x83\xd0\x00\x00\x00\x00&\x15\x98\xe0\x00\x00\x00\x00'*e\xd0\x00\x00\x00\x00'\xfe\xb5`\x00\x00\x00\x00)\n" + - "G\xd0\x00\x00\x00\x00)ޗ`\x00\x00\x00\x00*\xea)\xd0\x00\x00\x00\x00+\xbe]|\x00\x00\x00\x00,\xd3*l\x00\x00\x00\x00-\x9e?|\x00\x00\x00\x00.\xb3\fl\x00\x00\x00\x00/~!|\x00\x00" + - "\x00\x000\x92\xeel\x00\x00\x00\x001g=\xfc\x00\x00\x00\x002r\xd0l\x00\x00\x00\x003G\x1f\xfc\x00\x00\x00\x004R\xb2l\x00\x00\x00\x005'\x01\xfc\x00\x00\x00\x0062\x94l\x00\x00\x00\x007\x06" + - "\xe3\xfc\x00\x00\x00\x008\x1b\xb0\xec\x00\x00\x00\x008\xe6\xc5\xfc\x00\x00\x00\x009\xfb\x92\xec\x00\x00\x00\x00:Ƨ\xfc\x00\x00\x00\x00;\xdbt\xec\x00\x00\x00\x00<\xaf\xc4|\x00\x00\x00\x00=\xbbV\xec\x00\x00" + - "\x00\x00>\x8f\xa6|\x00\x00\x00\x00?\x9b8\xec\x00\x00\x00\x00@o\x88|\x00\x00\x00\x00A\x84Ul\x00\x00\x00\x00BOj|\x00\x00\x00\x00Cd7l\x00\x00\x00\x00D/L|\x00\x00\x00\x00ED" + - "\x19l\x00\x00\x00\x00E\xf3\x9a\xe0\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x05\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\xff\xff\xc3D\x00\x00\xff\xff\xb9\xb0\x00\x04\xff\xff\xd5\xd0\x01\b\xff\xff\xc7\xc0\x00\f" + - "\xff\xff\xd5\xd0\x01\x10\xff\xff\xd5\xd0\x01\x14LMT\x00EST\x00ADT\x00AST\x00AWT\x00APT\x00\nAST4ADT,M3.2.0,M11.1.0\n" + - "PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00\x00\x00\x0f\x00\x1c\x00America/MarigotUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux" + - "\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00" + - "\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x9373\xac\x01\xff\xff\xc6" + - "T\x00\x00\xff\xff\xc7\xc0\x00\x04LMT\x00AST\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R挋\x92\xf6\x01\x00\x00\xf6\x01\x00\x00\x0e\x00\x1c\x00America" + - "/MaceioUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00)\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96\xaah|\xff\xff\xff\xff\xb8\x0fI\xe0\xff\xff\xff\xff\xb8\xfd@\xa0\xff\xff\xff\xff\xb9\xf140\xff\xff\xff\xff\xba\xdet \xff\xff\xff\xff\xda8\xae0\xff\xff" + - "\xff\xff\xda\xeb\xfa0\xff\xff\xff\xff\xdc\x19\xe1\xb0\xff\xff\xff\xffܹY \xff\xff\xff\xff\xdd\xfb\x150\xff\xff\xff\xffޛ\xde \xff\xff\xff\xff\xdfݚ0\xff\xff\xff\xff\xe0T3 \xff\xff\xff\xff\xf4\x97" + - "\xff\xb0\xff\xff\xff\xff\xf5\x05^ \xff\xff\xff\xff\xf6\xc0d0\xff\xff\xff\xff\xf7\x0e\x1e\xa0\xff\xff\xff\xff\xf8Q,0\xff\xff\xff\xff\xf8\xc7\xc5 \xff\xff\xff\xff\xfa\nҰ\xff\xff\xff\xff\xfa\xa8\xf8\xa0\xff\xff" + - "\xff\xff\xfb\xec\x060\xff\xff\xff\xff\xfc\x8b}\xa0\x00\x00\x00\x00\x1dɎ0\x00\x00\x00\x00\x1exנ\x00\x00\x00\x00\x1f\xa05\xb0\x00\x00\x00\x00 3Ϡ\x00\x00\x00\x00!\x81i0\x00\x00\x00\x00\"\v" + - "Ƞ\x00\x00\x00\x00#X\x10\xb0\x00\x00\x00\x00#\xe2p \x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xd4\xc7 \x00\x00\x00\x000\x80y0\x00\x00\x00\x001\x1dM\xa0\x00\x00\x00\x007\xf6ư\x00\x00" + - "\x00\x008\xb8\x85 \x00\x00\x00\x009\xdf\xe30\x00\x00\x00\x009\xf2J \x00\x00\x00\x00;\xc8\xff\xb0\x00\x00\x00\x003\nPK\x03" + - "\x04\n\x00\x00\x00\x00\x00\xf1c9RԾ\xe7#\x95\x00\x00\x00\x95\x00\x00\x00\x0e\x00\x1c\x00America/PanamaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04" + - "\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" + - "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xffi\x87&\x10\xff\xff\xff\xff\x8b\xf4a\xe8" + - "\x01\x02\xff\xff\xb5p\x00\x00\xff\xff\xb5\x18\x00\x04\xff\xff\xb9\xb0\x00\bLMT\x00CMT\x00EST\x00\nEST5\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xa2\x81\xbfyS\x02\x00\x00" + - "S\x02\x00\x00\x12\x00\x1c\x00America/MetlakatlaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,\x00\x00\x00\b\x00\x00\x00\x1e\xff\xff\xff\xff?\xc2\xfd\xd1\xff\xff\xff\xff}\x870\x1a\xff\xff\xff\xffˉ\x1a\xa0\xff\xff\xff\xff\xd2#\xf4" + - "p\xff\xff\xff\xff\xd2a&\x10\xff\xff\xff\xff\xfe\xb8G \xff\xff\xff\xff\xff\xa8*\x10\x00\x00\x00\x00\x00\x98) \x00\x00\x00\x00\x01\x88\f\x10\x00\x00\x00\x00\x02x\v \x00\x00\x00\x00\x03q(\x90\x00\x00\x00" + - "\x00\x04a'\xa0\x00\x00\x00\x00\x05Q\n\x90\x00\x00\x00\x00\x06A\t\xa0\x00\x00\x00\x00\a0\xec\x90\x00\x00\x00\x00\a\x8dC\xa0\x00\x00\x00\x00\t\x10ΐ\x00\x00\x00\x00\t\xad\xbf \x00\x00\x00\x00\n\xf0\xb0" + - "\x90\x00\x00\x00\x00\v\u0be0\x00\x00\x00\x00\f\xd9\xcd\x10\x00\x00\x00\x00\r\xc0\x91\xa0\x00\x00\x00\x00\x0e\xb9\xaf\x10\x00\x00\x00\x00\x0f\xa9\xae \x00\x00\x00\x00\x10\x99\x91\x10\x00\x00\x00\x00\x11\x89\x90 \x00\x00\x00" + - "\x00\x12ys\x10\x00\x00\x00\x00\x13ir \x00\x00\x00\x00\x14YU\x10\x00\x00\x00\x00\x15IT \x00\x00\x00\x00\x1697\x10\x00\x00\x00\x00\x17)6 \x00\x00\x00\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18" + - " \x00\x00\x00\x00\x1a\x025\x90\x00\x00\x00\x00V5\xe2\xa0\x00\x00\x00\x00V\xe5H0\x00\x00\x00\x00X\x1e\xff \x00\x00\x00\x00X\xc5*0\x00\x00\x00\x00Y\xfe\xe1 \x00\x00\x00\x00Z\xa5\f0\x00\x00\x00" + - "\x00[\xde\xc3 \x00\x00\x00\x00\\DF\xa0\x00\x00\x00\x00\\\x84\xee0\x01\x02\x03\x04\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x06\a\x06\a" + - "\x06\a\x02\x06\a\x00\x00\xd6&\x00\x00\xff\xff\x84\xa6\x00\x00\xff\xff\x8f\x80\x00\x04\xff\xff\x9d\x90\x01\b\xff\xff\x9d\x90\x01\f\xff\xff\x9d\x90\x01\x10\xff\xff\x81p\x00\x14\xff\xff\x8f\x80\x01\x19LMT\x00PST" + - "\x00PWT\x00PPT\x00PDT\x00AKST\x00AKDT\x00\nAKST9AKDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1" + - "c9R\xfe\xe6\xf5J\x05\x04\x00\x00\x05\x04\x00\x00\x0e\x00\x1c\x00America/DawsonUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00" + - "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00]\x00\x00\x00\t\x00\x00\x00%\xff\xff\xff\xff}\x86\x8e\xb4\xff\xff\xff\xff\x9e\xb8˰\xff\xff\xff\xff\x9f\xbb#\xa0" + - "\xff\xff\xff\xff\xa0\xd0\f\xb0\xff\xff\xff\xff\xa1\xa2Ҁ\xff\xff\xff\xffˉ(\xb0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a4 \xff\xff\xff\xff\xf7/v\x90\xff\xff\xff\xff\xf8(\xa2\x10\x00\x00\x00\x00" + - "\a0\xec\x90\x00\x00\x00\x00\x13ir \x00\x00\x00\x00\x14YU\x10\x00\x00\x00\x00\x15IT \x00\x00\x00\x00\x1697\x10\x00\x00\x00\x00\x17)6 \x00\x00\x00\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18 " + - "\x00\x00\x00\x00\x1a\x025\x90\x00\x00\x00\x00\x1a\xf24\xa0\x00\x00\x00\x00\x1b\xe2\x17\x90\x00\x00\x00\x00\x1c\xd2\x16\xa0\x00\x00\x00\x00\x1d\xc1\xf9\x90\x00\x00\x00\x00\x1e\xb1\xf8\xa0\x00\x00\x00\x00\x1f\xa1ې\x00\x00\x00\x00" + - " v+ \x00\x00\x00\x00!\x81\xbd\x90\x00\x00\x00\x00\"V\r \x00\x00\x00\x00#j\xda\x10\x00\x00\x00\x00$5\xef \x00\x00\x00\x00%J\xbc\x10\x00\x00\x00\x00&\x15\xd1 \x00\x00\x00\x00'*\x9e\x10" + - "\x00\x00\x00\x00'\xfe\xed\xa0\x00\x00\x00\x00)\n\x80\x10\x00\x00\x00\x00)\xdeϠ\x00\x00\x00\x00*\xeab\x10\x00\x00\x00\x00+\xbe\xb1\xa0\x00\x00\x00\x00,\xd3~\x90\x00\x00\x00\x00-\x9e\x93\xa0\x00\x00\x00\x00" + - ".\xb3`\x90\x00\x00\x00\x00/~u\xa0\x00\x00\x00\x000\x93B\x90\x00\x00\x00\x001g\x92 \x00\x00\x00\x002s$\x90\x00\x00\x00\x003Gt \x00\x00\x00\x004S\x06\x90\x00\x00\x00\x005'V " + - "\x00\x00\x00\x0062\xe8\x90\x00\x00\x00\x007\a8 \x00\x00\x00\x008\x1c\x05\x10\x00\x00\x00\x008\xe7\x1a \x00\x00\x00\x009\xfb\xe7\x10\x00\x00\x00\x00:\xc6\xfc \x00\x00\x00\x00;\xdb\xc9\x10\x00\x00\x00\x00" + - "<\xb0\x18\xa0\x00\x00\x00\x00=\xbb\xab\x10\x00\x00\x00\x00>\x8f\xfa\xa0\x00\x00\x00\x00?\x9b\x8d\x10\x00\x00\x00\x00@oܠ\x00\x00\x00\x00A\x84\xa9\x90\x00\x00\x00\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b\x90" + - "\x00\x00\x00\x00D/\xa0\xa0\x00\x00\x00\x00EDm\x90\x00\x00\x00\x00E\xf3\xd3 \x00\x00\x00\x00G-\x8a\x10\x00\x00\x00\x00Gӵ \x00\x00\x00\x00I\rl\x10\x00\x00\x00\x00I\xb3\x97 \x00\x00\x00\x00" + - "J\xedN\x10\x00\x00\x00\x00K\x9c\xb3\xa0\x00\x00\x00\x00L\xd6j\x90\x00\x00\x00\x00M|\x95\xa0\x00\x00\x00\x00N\xb6L\x90\x00\x00\x00\x00O\\w\xa0\x00\x00\x00\x00P\x96.\x90\x00\x00\x00\x00Q3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00\x00\x00\x0f\x00\x1c\x00America/AntiguaUT" + - "\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00" + - "\b\xff\xff\xff\xff\x9373\xac\x01\xff\xff\xc6T\x00\x00\xff\xff\xc7\xc0\x00\x04LMT\x00AST\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x11\x00\x1c\x00America/Kentucky/UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x03\x04\n\x00\x00\x00\x00" + - "\x00\xf1c9R\xdf\xe5\x8d\xc4\xda\x04\x00\x00\xda\x04\x00\x00\x1b\x00\x1c\x00America/Kentucky/LouisvilleUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e" + - "`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01" + - "\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00u\x00\x00\x00\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x03\xfe\xa0\xff" + - "\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xff\xa4s\xf7\x00\xff\xff\xff\xff\xa5\x16\x11p\xff\xff\xff\xff\xca\rN\x80\xff\xff\xff\xff\xca" + - "\xd8Gp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xd3u\xd7\x1c\xff\xff\xff\xffӤ\tp\xff\xff\xff\xff\xda\xfe\xb5\x80\xff\xff\xff\xff\xdb\xc0s\xf0\xff" + - "\xff\xff\xff\xdcޗ\x80\xff\xff\xff\xffݩ\x90p\xff\xff\xff\xff\u07bey\x80\xff\xff\xff\xff߉rp\xff\xff\xff\xff\xe0\x9e[\x80\xff\xff\xff\xff\xe1iTp\xff\xff\xff\xff\xe2~=\x80\xff\xff\xff\xff\xe3" + - "I6p\xff\xff\xff\xff\xe4^\x1f\x80\xff\xff\xff\xff\xe5)\x18p\xff\xff\xff\xff\xe6G<\x00\xff\xff\xff\xff\xe77\x1e\xf0\xff\xff\xff\xff\xe8'\x1e\x00\xff\xff\xff\xff\xe9\x17\x00\xf0\xff\xff\xff\xff\xea\a\x00\x00\xff" + - "\xff\xff\xff\xea\xf6\xe2\xf0\xff\xff\xff\xff\xeb\xe6\xe2\x00\xff\xff\xff\xff\xec\xd6\xc4\xf0\xff\xff\xff\xff\xed\xc6\xc4\x00\xff\xff\xff\xff\xee\xbf\xe1p\xff\xff\xff\xff\xef\xaf\xe0\x80\xff\xff\xff\xff\xf0\x1e\x90p\xff\xff\xff\xff\xfc" + - "\xd8:\xf0\xff\xff\xff\xff\xfd\xc8\x1d\xe0\xff\xff\xff\xff\xfe\xb8\x1c\xf0\xff\xff\xff\xff\xff\xa7\xff\xe0\x00\x00\x00\x00\x00\x97\xfe\xf0\x00\x00\x00\x00\x01\x87\xe1\xe0\x00\x00\x00\x00\x02w\xe0\xf0\x00\x00\x00\x00\x03p\xfe`\x00" + - "\x00\x00\x00\x04`\xfdp\x00\x00\x00\x00\x05P\xe0`\x00\x00\x00\x00\x06@\xdfp\x00\x00\x00\x00\a0\xc2`\x00\x00\x00\x00\a\x8d\x19p\x00\x00\x00\x00\t\x10\xb2p\x00\x00\x00\x00\t\xad\x94\xf0\x00\x00\x00\x00\n" + - "\xf0\x86`\x00\x00\x00\x00\v\xe0\x85p\x00\x00\x00\x00\f٢\xe0\x00\x00\x00\x00\r\xc0gp\x00\x00\x00\x00\x0e\xb9\x84\xe0\x00\x00\x00\x00\x0f\xa9\x83\xf0\x00\x00\x00\x00\x10\x99f\xe0\x00\x00\x00\x00\x11\x89e\xf0\x00" + - "\x00\x00\x00\x12yH\xe0\x00\x00\x00\x00\x13iG\xf0\x00\x00\x00\x00\x14Y*\xe0\x00\x00\x00\x00\x15I)\xf0\x00\x00\x00\x00\x169\f\xe0\x00\x00\x00\x00\x17)\v\xf0\x00\x00\x00\x00\x18\")`\x00\x00\x00\x00\x19" + - "\b\xed\xf0\x00\x00\x00\x00\x1a\x02\v`\x00\x00\x00\x00\x1a\xf2\np\x00\x00\x00\x00\x1b\xe1\xed`\x00\x00\x00\x00\x1c\xd1\xecp\x00\x00\x00\x00\x1d\xc1\xcf`\x00\x00\x00\x00\x1e\xb1\xcep\x00\x00\x00\x00\x1f\xa1\xb1`\x00" + - "\x00\x00\x00 v\x00\xf0\x00\x00\x00\x00!\x81\x93`\x00\x00\x00\x00\"U\xe2\xf0\x00\x00\x00\x00#j\xaf\xe0\x00\x00\x00\x00$5\xc4\xf0\x00\x00\x00\x00%J\x91\xe0\x00\x00\x00\x00&\x15\xa6\xf0\x00\x00\x00\x00'" + - "*s\xe0\x00\x00\x00\x00'\xfe\xc3p\x00\x00\x00\x00)\nU\xe0\x00\x00\x00\x00)ޥp\x00\x00\x00\x00*\xea7\xe0\x00\x00\x00\x00+\xbe\x87p\x00\x00\x00\x00,\xd3T`\x00\x00\x00\x00-\x9eip\x00" + - "\x00\x00\x00.\xb36`\x00\x00\x00\x00/~Kp\x00\x00\x00\x000\x93\x18`\x00\x00\x00\x001gg\xf0\x00\x00\x00\x002r\xfa`\x00\x00\x00\x003GI\xf0\x00\x00\x00\x004R\xdc`\x00\x00\x00\x005" + - "'+\xf0\x00\x00\x00\x0062\xbe`\x00\x00\x00\x007\a\r\xf0\x00\x00\x00\x008\x1b\xda\xe0\x00\x00\x00\x008\xe6\xef\xf0\x00\x00\x00\x009\xfb\xbc\xe0\x00\x00\x00\x00:\xc6\xd1\xf0\x00\x00\x00\x00;۞\xe0\x00" + - "\x00\x00\x00<\xaf\xeep\x00\x00\x00\x00=\xbb\x80\xe0\x00\x00\x00\x00>\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00C" + - "da`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x01\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06" + - "\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\xff\xff\xaf\x9a\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14" + - "\xff\xff\xc7\xc0\x01\x18LMT\x00CDT\x00CST\x00CWT\x00CPT\x00EST\x00EDT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK" + - "\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x03\x1a|J\xcc\x03\x00\x00\xcc\x03\x00\x00\x1b\x00\x1c\x00America/Kentucky/MonticelloUT\t\x00\x03" + - "\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00W\x00\x00\x00\a\x00\x00\x00\x1c\xff\xff" + - "\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a" + - "\t\xf0\xff\xff\xff\xff\xfc\xd8I\x00\xff\xff\xff\xff\xfd\xc8+\xf0\xff\xff\xff\xff\xfe\xb8+\x00\xff\xff\xff\xff\xff\xa8\r\xf0\x00\x00\x00\x00\x00\x98\r\x00\x00\x00\x00\x00\x01\x87\xef\xf0\x00\x00\x00\x00\x02w\xef\x00\x00\x00" + - "\x00\x00\x03q\fp\x00\x00\x00\x00\x04a\v\x80\x00\x00\x00\x00\x05P\xeep\x00\x00\x00\x00\x06@\xed\x80\x00\x00\x00\x00\a0\xd0p\x00\x00\x00\x00\a\x8d'\x80\x00\x00\x00\x00\t\x10\xb2p\x00\x00\x00\x00\t\xad" + - "\xa3\x00\x00\x00\x00\x00\n\xf0\x94p\x00\x00\x00\x00\v\xe0\x93\x80\x00\x00\x00\x00\fٰ\xf0\x00\x00\x00\x00\r\xc0u\x80\x00\x00\x00\x00\x0e\xb9\x92\xf0\x00\x00\x00\x00\x0f\xa9\x92\x00\x00\x00\x00\x00\x10\x99t\xf0\x00\x00" + - "\x00\x00\x11\x89t\x00\x00\x00\x00\x00\x12yV\xf0\x00\x00\x00\x00\x13iV\x00\x00\x00\x00\x00\x14Y8\xf0\x00\x00\x00\x00\x15I8\x00\x00\x00\x00\x00\x169\x1a\xf0\x00\x00\x00\x00\x17)\x1a\x00\x00\x00\x00\x00\x18\"" + - "7p\x00\x00\x00\x00\x19\b\xfc\x00\x00\x00\x00\x00\x1a\x02\x19p\x00\x00\x00\x00\x1a\xf2\x18\x80\x00\x00\x00\x00\x1b\xe1\xfbp\x00\x00\x00\x00\x1c\xd1\xfa\x80\x00\x00\x00\x00\x1d\xc1\xddp\x00\x00\x00\x00\x1e\xb1܀\x00\x00" + - "\x00\x00\x1f\xa1\xbfp\x00\x00\x00\x00 v\x0f\x00\x00\x00\x00\x00!\x81\xa1p\x00\x00\x00\x00\"U\xf1\x00\x00\x00\x00\x00#j\xbd\xf0\x00\x00\x00\x00$5\xd3\x00\x00\x00\x00\x00%J\x9f\xf0\x00\x00\x00\x00&\x15" + - "\xb5\x00\x00\x00\x00\x00'*\x81\xf0\x00\x00\x00\x00'\xfeр\x00\x00\x00\x00)\nc\xf0\x00\x00\x00\x00)\u07b3\x80\x00\x00\x00\x00*\xeaE\xf0\x00\x00\x00\x00+\xbe\x95\x80\x00\x00\x00\x00,\xd3bp\x00\x00" + - "\x00\x00-\x9ew\x80\x00\x00\x00\x00.\xb3Dp\x00\x00\x00\x00/~Y\x80\x00\x00\x00\x000\x93&p\x00\x00\x00\x001gv\x00\x00\x00\x00\x002s\bp\x00\x00\x00\x003GX\x00\x00\x00\x00\x004R" + - "\xeap\x00\x00\x00\x005':\x00\x00\x00\x00\x0062\xccp\x00\x00\x00\x007\a\x1c\x00\x00\x00\x00\x008\x1b\xe8\xf0\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xca\xf0\x00\x00\x00\x00:\xc6\xd1\xf0\x00\x00" + - "\x00\x00;۞\xe0\x00\x00\x00\x00<\xaf\xeep\x00\x00\x00\x00=\xbb\x80\xe0\x00\x00\x00\x00>\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO" + - "\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06" + - "\x05\xff\xff\xb0t\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xc7\xc0\x01\x14\xff\xff\xb9\xb0\x00\x18LMT\x00CDT\x00CST\x00CWT\x00C" + - "PT\x00EDT\x00EST\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R$\r\x89l\xe4\x01\x00\x00\xe4\x01\x00" + - "\x00\x0f\x00\x1c\x00America/OjinagaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00#\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\xa5\xb6\xe8p\xff\xff\xff\xff\xaf\xf2n\xe0\xff\xff\xff\xff\xb6fV`\xff\xff\xff\xff\xb7C\xd2`\xff\xff\xff\xff\xb8" + - "\f6`\xff\xff\xff\xff\xb8\xfd\x86\xf0\x00\x00\x00\x001gv\x00\x00\x00\x00\x002s\bp\x00\x00\x00\x003GX\x00\x00\x00\x00\x004R\xeap\x00\x00\x00\x005'H\x10\x00\x00\x00\x0062ڀ\x00" + - "\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe7\f\x10\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xf5\x12\x90\x00\x00\x00\x00;\xb6\xd1\x00\x00\x00\x00\x00<\xb0\n\x90\x00\x00\x00\x00=" + - "\xbb\x9d\x00\x00\x00\x00\x00>\x8f\xec\x90\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@oΐ\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00BO\xb0\x90\x00\x00\x00\x00Cd}\x80\x00\x00\x00\x00D/\x92\x90\x00" + - "\x00\x00\x00ED_\x80\x00\x00\x00\x00F\x0ft\x90\x00\x00\x00\x00G$A\x80\x00\x00\x00\x00G\xf8\x91\x10\x00\x00\x00\x00I\x04#\x80\x00\x00\x00\x00I\xd8s\x10\x00\x00\x00\x00J\xe4\x05\x80\x00\x00\x00\x00K" + - "\x9c\xa5\x90\x01\x02\x01\x02\x01\x02\x03\x02\x03\x02\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\xff\xff\x9e\x1c\x00\x00\xff\xff\x9d\x90\x00\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0" + - "\x01\f\xff\xff\xab\xa0\x01\x10LMT\x00MST\x00CST\x00CDT\x00MDT\x00\nMST7MDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00" + - "\x00\x00\xf1c9R\x19vv\xa0\x97\x00\x00\x00\x97\x00\x00\x00\r\x00\x1c\x00America/ArubaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8" + - "\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xff\x93\x1e.#\xff\xff\xff\xff\xf6\x98\xecH\x01\x02\xff\xff\xbf]" + - "\x00\x00\xff\xff\xc0\xb8\x00\x04\xff\xff\xc7\xc0\x00\nLMT\x00-0430\x00AST\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x81{\xc1\x92\xbc\x03\x00\x00\xbc\x03\x00\x00" + - "\r\x00\x1c\x00America/SitkaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00@oΐ\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00BO\xb0\x90\x00\x00\x00\x00Cd}\x80\x00\x00\x00\x00D/\x92\x90\x00\x00\x00\x00ED_\x80\x00\x00\x00\x00E\xf3\xc5\x10\x03\x01\x02\x03" + + "\x04\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x00\x00\x00" + + "\x00\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\xab\xa0\x01\b\xff\xff\x9d\x90\x00\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xab\xa0\x01\x15-00\x00MWT\x00MPT\x00MST\x00MDDT\x00MDT\x00\nM" + + "ST7MDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xe90T\x16\xd1\x01\x00\x00\xd1\x01\x00\x00\f\x00\x1c\x00America/" + + "NuukUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\"\x00" + + "\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x9b\x80h\x00\x00\x00\x00\x00\x13M|P\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17" + + "\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00" + + "\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#3<-02>,M3.5" + + ".0/-2,M10.5.0/-1\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x15\x00\x1c\x00America/St_Ba" + + "rthelemyUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffz敹\xff\xff\xff\xff\xcb\xf62\xc0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\x01\x03\x02\x01\xff\xff\xc2\a\x00\x00\xff\xff\xc7\xc0\x00\x04\xff" + + "\xff\xd5\xd0\x01\b\xff\xff\xd5\xd0\x01\fLMT\x00AST\x00APT\x00AWT\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS:\x9a1T\xdf\x01\x00\x00\xdf\x01\x00\x00\x14" + + "\x00\x1c\x00America/ScoresbysundUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\"\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\x9b\x80L\x18\x00\x00\x00\x00\x13Mn@\x00\x00\x00\x00\x144$\xc0\x00\x00\x00\x00\x15#\xf9\xa0\x00\x00" + + "\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac" + + "\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#1<+00>,M3.5.0/0,M10.5.0/1\nPK\x03\x04\n\x00\x00\x00\x00\x00" + + "#\x82iS\x9d?\xdfڸ\x03\x00\x00\xb8\x03\x00\x00\x11\x00\x1c\x00America/Sao_PauloUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00" + + "\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif" + + "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00[\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96\xaar\xb4\xff\xff\xff\xff\xb8\x0fI\xe0\xff\xff\xff\xff" + + "\xb8\xfd@\xa0\xff\xff\xff\xff\xb9\xf140\xff\xff\xff\xff\xba\xdet \xff\xff\xff\xff\xda8\xae0\xff\xff\xff\xff\xda\xeb\xfa0\xff\xff\xff\xff\xdc\x19\xe1\xb0\xff\xff\xff\xffܹY \xff\xff\xff\xff\xdd\xfb\x150" + + "\xff\xff\xff\xffޛ\xde \xff\xff\xff\xff\xdfݚ0\xff\xff\xff\xff\xe0T3 \xff\xff\xff\xff\xf4Z\t0\xff\xff\xff\xff\xf5\x05^ \xff\xff\xff\xff\xf6\xc0d0\xff\xff\xff\xff\xf7\x0e\x1e\xa0\xff\xff\xff\xff" + + "\xf8Q,0\xff\xff\xff\xff\xf8\xc7\xc5 \xff\xff\xff\xff\xfa\nҰ\xff\xff\xff\xff\xfa\xa8\xf8\xa0\xff\xff\xff\xff\xfb\xec\x060\xff\xff\xff\xff\xfc\x8b}\xa0\x00\x00\x00\x00\x1dɎ0\x00\x00\x00\x00\x1exנ" + + "\x00\x00\x00\x00\x1f\xa05\xb0\x00\x00\x00\x00 3Ϡ\x00\x00\x00\x00!\x81i0\x00\x00\x00\x00\"\vȠ\x00\x00\x00\x00#X\x10\xb0\x00\x00\x00\x00#\xe2p \x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00" + + "%\xd4\xc7 \x00\x00\x00\x00'!\x0f0\x00\x00\x00\x00'\xbd\xe3\xa0\x00\x00\x00\x00)\x00\xf10\x00\x00\x00\x00)\x94\x8b \x00\x00\x00\x00*\xea\r\xb0\x00\x00\x00\x00+k2\xa0\x00\x00\x00\x00,\xc0\xb50" + + "\x00\x00\x00\x00-f\xc4 \x00\x00\x00\x00.\xa0\x970\x00\x00\x00\x00/F\xa6 \x00\x00\x00\x000\x80y0\x00\x00\x00\x001\x1dM\xa0\x00\x00\x00\x002W \xb0\x00\x00\x00\x003\x06j \x00\x00\x00\x00" + + "48T0\x00\x00\x00\x004\xf8\xc1 \x00\x00\x00\x006 \x1f0\x00\x00\x00\x006\xcfh\xa0\x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xb8\x85 \x00\x00\x00\x009\xdf\xe30\x00\x00\x00\x00:\x8f,\xa0" + + "\x00\x00\x00\x00;\xc8\xff\xb0\x00\x00\x00\x00N\xf0\xa0\x00\x00\x00\x00?\x91\xfe0\x00\x00\x00\x00@.Ҡ\x00\x00\x00\x00A\x86\xf80\x00\x00\x00\x00" + + "B\x17\xef \x00\x00\x00\x00CQ\xc20\x00\x00\x00\x00C\xf7\xd1 \x00\x00\x00\x00EMS\xb0\x00\x00\x00\x00E\xe0\xed\xa0\x00\x00\x00\x00G\x11\x860\x00\x00\x00\x00G\xb7\x95 \x00\x00\x00\x00H\xfa\xa2\xb0" + + "\x00\x00\x00\x00I\x97w \x00\x00\x00\x00Jڄ\xb0\x00\x00\x00\x00K\x80\x93\xa0\x00\x00\x00\x00L\xbaf\xb0\x00\x00\x00\x00M`u\xa0\x00\x00\x00\x00N\x9aH\xb0\x00\x00\x00\x00OI\x92 \x00\x00\x00\x00" + + "P\x83e0\x00\x00\x00\x00Q 9\xa0\x00\x00\x00\x00RcG0\x00\x00\x00\x00S\x00\x1b\xa0\x00\x00\x00\x00TC)0\x00\x00\x00\x00T\xe98 \x00\x00\x00\x00V#\v0\x00\x00\x00\x00V\xc9\x1a " + + "\x00\x00\x00\x00X\x02\xed0\x00\x00\x00\x00X\xa8\xfc \x00\x00\x00\x00Y\xe2\xcf0\x00\x00\x00\x00Z\x88\xde \x00\x00\x00\x00[\xde`\xb0\x00\x00\x00\x00\\h\xc0 \x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xff\xd4L\x00\x00\xff\xff\xe3\xe0\x01\x04\xff\xff\xd5\xd0\x00\bLMT\x00-02\x00-03\x00\n<-03>3\nPK\x03" + + "\x04\n\x00\x00\x00\x00\x00#\x82iS\x82\x13z\xe2\xc2\x00\x00\x00\xc2\x00\x00\x00\x13\x00\x1c\x00America/TegucigalpaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8bau" + + "x\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00" + + "\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\xa4LKD\x00\x00\x00" + + "\x00 \x9a\xdc\xe0\x00\x00\x00\x00!\\\x9bP\x00\x00\x00\x00\"z\xbe\xe0\x00\x00\x00\x00#<}P\x00\x00\x00\x00D]\x8c\xe0\x00\x00\x00\x00D\xd6\xc8\xd0\x02\x01\x02\x01\x02\x01\x02\xff\xff\xae<\x00\x00\xff\xff" + + "\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\bLMT\x00CDT\x00CST\x00\nCST6\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSM\x94\xc7Kp\x03\x00\x00p\x03\x00\x00\x11\x00\x1c\x00Am" + + "erica/Glace_BayUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00O\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\x80\xf1\xa84\xff\xff\xff\xff\x9e\xb8\x85`\xff\xff\xff\xff\x9f\xba\xddP\xff\xff\xff\xffˈ\xe2`\xff\xff\xff\xff\xd2#\xf4p\xff\xff" + + "\xff\xff\xd2`\xed\xd0\xff\xff\xff\xff\xe0\x9e?`\xff\xff\xff\xff\xe1i8P\x00\x00\x00\x00\x04`\xef`\x00\x00\x00\x00\x05P\xd2P\x00\x00\x00\x00\x06@\xd1`\x00\x00\x00\x00\a0\xb4P\x00\x00\x00\x00\b " + + "\xb3`\x00\x00\x00\x00\t\x10\x96P\x00\x00\x00\x00\n\x00\x95`\x00\x00\x00\x00\n\xf0xP\x00\x00\x00\x00\v\xe0w`\x00\x00\x00\x00\fٔ\xd0\x00\x00\x00\x00\r\xc0Y`\x00\x00\x00\x00\x0e\xb9v\xd0\x00\x00" + + "\x00\x00\x0f\xa9u\xe0\x00\x00\x00\x00\x10\x99X\xd0\x00\x00\x00\x00\x11\x89W\xe0\x00\x00\x00\x00\x12y:\xd0\x00\x00\x00\x00\x13i9\xe0\x00\x00\x00\x00\x14Y\x1c\xd0\x00\x00\x00\x00\x15I\x1b\xe0\x00\x00\x00\x00\x168" + + "\xfe\xd0\x00\x00\x00\x00\x17(\xfd\xe0\x00\x00\x00\x00\x18\"\x1bP\x00\x00\x00\x00\x19\b\xdf\xe0\x00\x00\x00\x00\x1a\x01\xfdP\x00\x00\x00\x00\x1a\xf1\xfc`\x00\x00\x00\x00\x1b\xe1\xdfP\x00\x00\x00\x00\x1c\xd1\xde`\x00\x00" + + "\x00\x00\x1d\xc1\xc1P\x00\x00\x00\x00\x1e\xb1\xc0`\x00\x00\x00\x00\x1f\xa1\xa3P\x00\x00\x00\x00 u\xf2\xe0\x00\x00\x00\x00!\x81\x85P\x00\x00\x00\x00\"U\xd4\xe0\x00\x00\x00\x00#j\xa1\xd0\x00\x00\x00\x00$5" + + "\xb6\xe0\x00\x00\x00\x00%J\x83\xd0\x00\x00\x00\x00&\x15\x98\xe0\x00\x00\x00\x00'*e\xd0\x00\x00\x00\x00'\xfe\xb5`\x00\x00\x00\x00)\nG\xd0\x00\x00\x00\x00)ޗ`\x00\x00\x00\x00*\xea)\xd0\x00\x00" + + "\x00\x00+\xbey`\x00\x00\x00\x00,\xd3FP\x00\x00\x00\x00-\x9e[`\x00\x00\x00\x00.\xb3(P\x00\x00\x00\x00/~=`\x00\x00\x00\x000\x93\nP\x00\x00\x00\x001gY\xe0\x00\x00\x00\x002r" + + "\xecP\x00\x00\x00\x003G;\xe0\x00\x00\x00\x004R\xceP\x00\x00\x00\x005'\x1d\xe0\x00\x00\x00\x0062\xb0P\x00\x00\x00\x007\x06\xff\xe0\x00\x00\x00\x008\x1b\xcc\xd0\x00\x00\x00\x008\xe6\xe1\xe0\x00\x00" + + "\x00\x009\xfb\xae\xd0\x00\x00\x00\x00:\xc6\xc3\xe0\x00\x00\x00\x00;ې\xd0\x00\x00\x00\x00<\xaf\xe0`\x00\x00\x00\x00=\xbbr\xd0\x00\x00\x00\x00>\x8f\xc2`\x00\x00\x00\x00?\x9bT\xd0\x00\x00\x00\x00@o" + + "\xa4`\x00\x00\x00\x00A\x84qP\x00\x00\x00\x00BO\x86`\x00\x00\x00\x00CdSP\x00\x00\x00\x00D/h`\x00\x00\x00\x00ED5P\x00\x00\x00\x00E\xf3\x9a\xe0\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xc7\xcc\x00\x00\xff\xff\xd5\xd0\x01\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xd5\xd0\x01\x10LMT\x00ADT\x00AST\x00AWT\x00APT\x00\n" + + "AST4ADT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x8f\x19Ԇ\x12\x02\x00\x00\x12\x02\x00\x00\x16\x00\x1c\x00America" + + "/Bahia_BanderasUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00'\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff\xa5\xb6\xe8p\xff\xff\xff\xff\xaf\xf2n\xe0\xff\xff\xff\xff\xb6fV`\xff\xff\xff\xff\xb7C\xd2`\xff\xff\xff\xff\xb8\f6`\xff\xff" + + "\xff\xff\xb8\xfd\x86\xf0\xff\xff\xff\xff\xcb\xeaq`\xff\xff\xff\xffؑ\xb4\xf0\x00\x00\x00\x00\x00\x00p\x80\x00\x00\x00\x001g\x84\x10\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003Gf\x10\x00\x00\x00\x004R" + + "\xf8\x80\x00\x00\x00\x005'H\x10\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe7\f\x10\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xf5\x12\x90\x00\x00" + + "\x00\x00;\xb6\xd1\x00\x00\x00\x00\x00<\xb0\n\x90\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8f\xec\x90\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@oΐ\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00BO" + + "\xb0\x90\x00\x00\x00\x00Cd}\x80\x00\x00\x00\x00D/\x92\x90\x00\x00\x00\x00ED_\x80\x00\x00\x00\x00F\x0ft\x90\x00\x00\x00\x00G$A\x80\x00\x00\x00\x00G\xf8\x91\x10\x00\x00\x00\x00I\x04#\x80\x00\x00" + + "\x00\x00I\xd8s\x10\x00\x00\x00\x00J\xe4\x05\x80\x00\x00\x00\x00K\xb8U\x10\x00\x00\x00\x00L\xcd\x13\xf0\x01\x02\x01\x02\x01\x02\x01\x03\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04" + + "\x01\x04\x01\x04\x01\x04\x01\x05\x02\xff\xff\x9dT\x00\x00\xff\xff\x9d\x90\x00\x04\xff\xff\xab\xa0\x00\b\xff\xff\x8f\x80\x00\f\xff\xff\xab\xa0\x01\x10\xff\xff\xb9\xb0\x01\x14LMT\x00MST\x00CST\x00PST" + + "\x00MDT\x00CDT\x00\nCST6CDT,M4.1.0,M10.5.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xef\xf0R\x8a\xc4\x02\x00\x00\xc4\x02\x00\x00\x0f" + + "\x00\x1c\x00America/RosarioUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xad\xb0\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f" + + "@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff" + + "\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*" + + "0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff" + + "\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C" + + "\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff" + + "\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'!\x0f" + + "0\x00\x00\x00\x00'\xd0X\xa0\x00\x00\x00\x00)\x00\xff@\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00" + + "\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x00\x00\x00\x00H\xfa\xa2\xb0\x00\x00\x00\x00I\xbca \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x02\x04\x05\x04\x05\x03\x05\x04\x05\x04\x05\xff\xff\xc3\xd0\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10" + + "\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x81{\xc1\x92\xbc\x03\x00\x00\xbc\x03\x00\x00" + + "\r\x00\x1c\x00America/SitkaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00S\x00\x00\x00\t\x00\x00\x00\"\xff\xff\xff\xff?\xc2\xfd\xd1\xff\xff\xff\xff}\x873\x99\xff\xff\xff\xffˉ\x1a\xa0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a&\x10" + "\xff\xff\xff\xff\xfe\xb8G \xff\xff\xff\xff\xff\xa8*\x10\x00\x00\x00\x00\x00\x98) \x00\x00\x00\x00\x01\x88\f\x10\x00\x00\x00\x00\x02x\v \x00\x00\x00\x00\x03q(\x90\x00\x00\x00\x00\x04a'\xa0\x00\x00\x00\x00" + @@ -804,1117 +721,1540 @@ const zipdata = "PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00 "\x00\x00\x00\x00D/\xae\xb0\x00\x00\x00\x00ED{\xa0\x00\x00\x00\x00E\xf3\xe10\x01\x02\x03\x04\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x06\b" + "\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\x00\x00ҧ\x00\x00\xff\xff\x81'\x00\x00\xff" + "\xff\x8f\x80\x00\x04\xff\xff\x9d\x90\x01\b\xff\xff\x9d\x90\x01\f\xff\xff\x9d\x90\x01\x10\xff\xff\x81p\x00\x14\xff\xff\x8f\x80\x01\x18\xff\xff\x81p\x00\x1dLMT\x00PST\x00PWT\x00PPT\x00PDT" + - "\x00YST\x00AKDT\x00AKST\x00\nAKST9AKDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rѱ\x86b\xee" + - "\x03\x00\x00\xee\x03\x00\x00\x0e\x00\x1c\x00America/NassauUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00]\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\x937B\x8a\xff\xff\xff\xff\xcb\xf4\xefP\xff\xff\xff\xff\xd0\xfaG\xc0\xff\xff\xff\xff\xd1#4P" + - "\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2x\x9a\xc0\xff\xff\xff\xff\xf5Oxp\xff\xff\xff\xff\xf6?[`\xff\xff\xff\xff\xf7/Zp\xff\xff\xff\xff\xf8(w\xe0\xff\xff\xff\xff\xf9\x0f\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00" + - "@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x03\x02\x04\x02" + - "\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02" + - "\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\xff\xff\xb7v\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x01\f\xff\xff\xc7\xc0\x01\x10LMT\x00E" + - "WT\x00EST\x00EPT\x00EDT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x9d?\xdfڸ\x03\x00" + - "\x00\xb8\x03\x00\x00\x11\x00\x1c\x00America/Sao_PauloUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00" + + "\x00YST\x00AKDT\x00AKST\x00\nAKST9AKDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS):\x17-\x88" + + "\x06\x00\x00\x88\x06\x00\x00\x0f\x00\x1c\x00America/HalifaxUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00[\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96\xaar\xb4\xff\xff\xff\xff\xb8\x0fI\xe0\xff\xff\xff\xff\xb8\xfd@\xa0\xff\xff\xff\xff\xb9\xf14" + - "0\xff\xff\xff\xff\xba\xdet \xff\xff\xff\xff\xda8\xae0\xff\xff\xff\xff\xda\xeb\xfa0\xff\xff\xff\xff\xdc\x19\xe1\xb0\xff\xff\xff\xffܹY \xff\xff\xff\xff\xdd\xfb\x150\xff\xff\xff\xffޛ\xde \xff\xff\xff" + - "\xff\xdfݚ0\xff\xff\xff\xff\xe0T3 \xff\xff\xff\xff\xf4Z\t0\xff\xff\xff\xff\xf5\x05^ \xff\xff\xff\xff\xf6\xc0d0\xff\xff\xff\xff\xf7\x0e\x1e\xa0\xff\xff\xff\xff\xf8Q,0\xff\xff\xff\xff\xf8\xc7\xc5" + - " \xff\xff\xff\xff\xfa\nҰ\xff\xff\xff\xff\xfa\xa8\xf8\xa0\xff\xff\xff\xff\xfb\xec\x060\xff\xff\xff\xff\xfc\x8b}\xa0\x00\x00\x00\x00\x1dɎ0\x00\x00\x00\x00\x1exנ\x00\x00\x00\x00\x1f\xa05\xb0\x00\x00\x00" + - "\x00 3Ϡ\x00\x00\x00\x00!\x81i0\x00\x00\x00\x00\"\vȠ\x00\x00\x00\x00#X\x10\xb0\x00\x00\x00\x00#\xe2p \x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xd4\xc7 \x00\x00\x00\x00'!\x0f" + - "0\x00\x00\x00\x00'\xbd\xe3\xa0\x00\x00\x00\x00)\x00\xf10\x00\x00\x00\x00)\x94\x8b \x00\x00\x00\x00*\xea\r\xb0\x00\x00\x00\x00+k2\xa0\x00\x00\x00\x00,\xc0\xb50\x00\x00\x00\x00-f\xc4 \x00\x00\x00" + - "\x00.\xa0\x970\x00\x00\x00\x00/F\xa6 \x00\x00\x00\x000\x80y0\x00\x00\x00\x001\x1dM\xa0\x00\x00\x00\x002W \xb0\x00\x00\x00\x003\x06j \x00\x00\x00\x0048T0\x00\x00\x00\x004\xf8\xc1" + - " \x00\x00\x00\x006 \x1f0\x00\x00\x00\x006\xcfh\xa0\x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xb8\x85 \x00\x00\x00\x009\xdf\xe30\x00\x00\x00\x00:\x8f,\xa0\x00\x00\x00\x00;\xc8\xff\xb0\x00\x00\x00" + - "\x00N\xf0\xa0\x00\x00\x00\x00?\x91\xfe0\x00\x00\x00\x00@.Ҡ\x00\x00\x00\x00A\x86\xf80\x00\x00\x00\x00B\x17\xef \x00\x00\x00\x00CQ\xc2" + - "0\x00\x00\x00\x00C\xf7\xd1 \x00\x00\x00\x00EMS\xb0\x00\x00\x00\x00E\xe0\xed\xa0\x00\x00\x00\x00G\x11\x860\x00\x00\x00\x00G\xb7\x95 \x00\x00\x00\x00H\xfa\xa2\xb0\x00\x00\x00\x00I\x97w \x00\x00\x00" + - "\x00Jڄ\xb0\x00\x00\x00\x00K\x80\x93\xa0\x00\x00\x00\x00L\xbaf\xb0\x00\x00\x00\x00M`u\xa0\x00\x00\x00\x00N\x9aH\xb0\x00\x00\x00\x00OI\x92 \x00\x00\x00\x00P\x83e0\x00\x00\x00\x00Q 9" + - "\xa0\x00\x00\x00\x00RcG0\x00\x00\x00\x00S\x00\x1b\xa0\x00\x00\x00\x00TC)0\x00\x00\x00\x00T\xe98 \x00\x00\x00\x00V#\v0\x00\x00\x00\x00V\xc9\x1a \x00\x00\x00\x00X\x02\xed0\x00\x00\x00" + - "\x00X\xa8\xfc \x00\x00\x00\x00Y\xe2\xcf0\x00\x00\x00\x00Z\x88\xde \x00\x00\x00\x00[\xde`\xb0\x00\x00\x00\x00\\h\xc0 \x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa7\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\x80\xf1\xab\xa0\xff\xff\xff\xff\x9a\xe4\xde\xc0\xff\xff\xff\xff\x9b\xd6\x130\xff\xff\xff\xff\x9e\xb8\x85" + + "`\xff\xff\xff\xff\x9f\xba\xddP\xff\xff\xff\xff\xa2\x9d\x17@\xff\xff\xff\xff\xa30\xb10\xff\xff\xff\xff\xa4zV@\xff\xff\xff\xff\xa5\x1b\x1f0\xff\xff\xff\xff\xa6S\xa0\xc0\xff\xff\xff\xff\xa6\xfcR\xb0\xff\xff\xff" + + "\xff\xa8<\xbd@\xff\xff\xff\xff\xa8\xdc4\xb0\xff\xff\xff\xff\xaa\x1c\x9f@\xff\xff\xff\xff\xaa\xcd:0\xff\xff\xff\xff\xab\xfc\x81@\xff\xff\xff\xff\xac\xbf\x910\xff\xff\xff\xff\xad\xee\xd8@\xff\xff\xff\xff\xae\x8c\xfe" + + "0\xff\xff\xff\xff\xaf\xbcE@\xff\xff\xff\xff\xb0\u007fU0\xff\xff\xff\xff\xb1\xae\x9c@\xff\xff\xff\xff\xb2Kp\xb0\xff\xff\xff\xff\xb3\x8e~@\xff\xff\xff\xff\xb4$\xbb0\xff\xff\xff\xff\xb5n`@\xff\xff\xff" + + "\xff\xb6\x15\xc0\xb0\xff\xff\xff\xff\xb7NB@\xff\xff\xff\xff\xb8\b\x17\xb0\xff\xff\xff\xff\xb9$\xe9\xc0\xff\xff\xff\xff\xb9\xe7\xf9\xb0\xff\xff\xff\xff\xbb\x04\xcb\xc0\xff\xff\xff\xff\xbb\xd1\x160\xff\xff\xff\xff\xbd\x00]" + + "@\xff\xff\xff\xff\xbd\x9d1\xb0\xff\xff\xff\xff\xbe\xf2\xb4@\xff\xff\xff\xff\xbf\x90\xda0\xff\xff\xff\xff\xc0\xd3\xe7\xc0\xff\xff\xff\xff\xc1^G0\xff\xff\xff\xff\u008d\x8e@\xff\xff\xff\xff\xc3P\x9e0\xff\xff\xff" + + "\xff\xc4mp@\xff\xff\xff\xff\xc50\x800\xff\xff\xff\xff\xc6r<@\xff\xff\xff\xff\xc7\x10b0\xff\xff\xff\xff\xc86n\xc0\xff\xff\xff\xff\xc8\xf9~\xb0\xff\xff\xff\xff\xca\x16P\xc0\xff\xff\xff\xff\xca\xd9`" + + "\xb0\xff\xff\xff\xffˈ\xe2`\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\xff\xff\xff\xff\xd3u\xd6\xe0\xff\xff\xff\xff\xd4@\xcf\xd0\xff\xff\xff\xff\xd5U\xb8\xe0\xff\xff\xff\xff\xd6 \xb1\xd0\xff\xff\xff" + + "\xff\xd75\x9a\xe0\xff\xff\xff\xff\xd8\x00\x93\xd0\xff\xff\xff\xff\xd9\x15|\xe0\xff\xff\xff\xff\xd9\xe0u\xd0\xff\xff\xff\xff\xdc\xde{`\xff\xff\xff\xffݩtP\xff\xff\xff\xff\u07be]`\xff\xff\xff\xff߉V" + + "P\xff\xff\xff\xff\xe0\x9e?`\xff\xff\xff\xff\xe1i8P\xff\xff\xff\xff\xe2~!`\xff\xff\xff\xff\xe3I\x1aP\xff\xff\xff\xff\xe6G\x1f\xe0\xff\xff\xff\xff\xe7\x12\x18\xd0\xff\xff\xff\xff\xe8'\x01\xe0\xff\xff\xff" + + "\xff\xe8\xf1\xfa\xd0\xff\xff\xff\xff\xea\x06\xe3\xe0\xff\xff\xff\xff\xea\xd1\xdc\xd0\xff\xff\xff\xff\xeb\xe6\xc5\xe0\xff\xff\xff\xff챾\xd0\xff\xff\xff\xff\xf1\x8f\xa6`\xff\xff\xff\xff\xf2\u007f\x89P\xff\xff\xff\xff\xf3o\x88" + + "`\xff\xff\xff\xff\xf4_kP\xff\xff\xff\xff\xf5Oj`\xff\xff\xff\xff\xf6?MP\xff\xff\xff\xff\xf7/L`\xff\xff\xff\xff\xf8(i\xd0\xff\xff\xff\xff\xf9\x0f.`\xff\xff\xff\xff\xfa\bK\xd0\xff\xff\xff" + + "\xff\xfa\xf8J\xe0\xff\xff\xff\xff\xfb\xe8-\xd0\xff\xff\xff\xff\xfc\xd8,\xe0\xff\xff\xff\xff\xfd\xc8\x0f\xd0\xff\xff\xff\xff\xfe\xb8\x0e\xe0\xff\xff\xff\xff\xff\xa7\xf1\xd0\x00\x00\x00\x00\x00\x97\xf0\xe0\x00\x00\x00\x00\x01\x87\xd3" + + "\xd0\x00\x00\x00\x00\x02w\xd2\xe0\x00\x00\x00\x00\x03p\xf0P\x00\x00\x00\x00\x04`\xef`\x00\x00\x00\x00\x05P\xd2P\x00\x00\x00\x00\x06@\xd1`\x00\x00\x00\x00\a0\xb4P\x00\x00\x00\x00\b \xb3`\x00\x00\x00" + + "\x00\t\x10\x96P\x00\x00\x00\x00\n\x00\x95`\x00\x00\x00\x00\n\xf0xP\x00\x00\x00\x00\v\xe0w`\x00\x00\x00\x00\fٔ\xd0\x00\x00\x00\x00\r\xc0Y`\x00\x00\x00\x00\x0e\xb9v\xd0\x00\x00\x00\x00\x0f\xa9u" + + "\xe0\x00\x00\x00\x00\x10\x99X\xd0\x00\x00\x00\x00\x11\x89W\xe0\x00\x00\x00\x00\x12y:\xd0\x00\x00\x00\x00\x13i9\xe0\x00\x00\x00\x00\x14Y\x1c\xd0\x00\x00\x00\x00\x15I\x1b\xe0\x00\x00\x00\x00\x168\xfe\xd0\x00\x00\x00" + + "\x00\x17(\xfd\xe0\x00\x00\x00\x00\x18\"\x1bP\x00\x00\x00\x00\x19\b\xdf\xe0\x00\x00\x00\x00\x1a\x01\xfdP\x00\x00\x00\x00\x1a\xf1\xfc`\x00\x00\x00\x00\x1b\xe1\xdfP\x00\x00\x00\x00\x1c\xd1\xde`\x00\x00\x00\x00\x1d\xc1\xc1" + + "P\x00\x00\x00\x00\x1e\xb1\xc0`\x00\x00\x00\x00\x1f\xa1\xa3P\x00\x00\x00\x00 u\xf2\xe0\x00\x00\x00\x00!\x81\x85P\x00\x00\x00\x00\"U\xd4\xe0\x00\x00\x00\x00#j\xa1\xd0\x00\x00\x00\x00$5\xb6\xe0\x00\x00\x00" + + "\x00%J\x83\xd0\x00\x00\x00\x00&\x15\x98\xe0\x00\x00\x00\x00'*e\xd0\x00\x00\x00\x00'\xfe\xb5`\x00\x00\x00\x00)\nG\xd0\x00\x00\x00\x00)ޗ`\x00\x00\x00\x00*\xea)\xd0\x00\x00\x00\x00+\xbey" + + "`\x00\x00\x00\x00,\xd3FP\x00\x00\x00\x00-\x9e[`\x00\x00\x00\x00.\xb3(P\x00\x00\x00\x00/~=`\x00\x00\x00\x000\x93\nP\x00\x00\x00\x001gY\xe0\x00\x00\x00\x002r\xecP\x00\x00\x00" + + "\x003G;\xe0\x00\x00\x00\x004R\xceP\x00\x00\x00\x005'\x1d\xe0\x00\x00\x00\x0062\xb0P\x00\x00\x00\x007\x06\xff\xe0\x00\x00\x00\x008\x1b\xcc\xd0\x00\x00\x00\x008\xe6\xe1\xe0\x00\x00\x00\x009\xfb\xae" + + "\xd0\x00\x00\x00\x00:\xc6\xc3\xe0\x00\x00\x00\x00;ې\xd0\x00\x00\x00\x00<\xaf\xe0`\x00\x00\x00\x00=\xbbr\xd0\x00\x00\x00\x00>\x8f\xc2`\x00\x00\x00\x00?\x9bT\xd0\x00\x00\x00\x00@o\xa4`\x00\x00\x00" + + "\x00A\x84qP\x00\x00\x00\x00BO\x86`\x00\x00\x00\x00CdSP\x00\x00\x00\x00D/h`\x00\x00\x00\x00ED5P\x00\x00\x00\x00E\xf3\x9a\xe0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xc4`\x00\x00\xff\xff\xd5\xd0\x01\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xd5\xd0" + + "\x01\x10LMT\x00ADT\x00AST\x00AWT\x00APT\x00\nAST4ADT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS" + + "\xc1Ȇ\x90\x05\x04\x00\x00\x05\x04\x00\x00\x12\x00\x1c\x00America/WhitehorseUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_" + + "\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00]\x00\x00\x00\t\x00\x00\x00%\xff\xff\xff\xff}\x86\x8a\x9c\xff\xff\xff\xff\x9e\xb8˰\xff\xff\xff\xff\x9f\xbb#" + + "\xa0\xff\xff\xff\xff\xa0\xd0\f\xb0\xff\xff\xff\xff\xa1\xa2Ҁ\xff\xff\xff\xffˉ(\xb0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a4 \xff\xff\xff\xff\xf7/v\x90\xff\xff\xff\xff\xf8(\xa2\x10\xff\xff\xff" + + "\xff\xfb\x1d_\x10\x00\x00\x00\x00\x13ir \x00\x00\x00\x00\x14YU\x10\x00\x00\x00\x00\x15IT \x00\x00\x00\x00\x1697\x10\x00\x00\x00\x00\x17)6 \x00\x00\x00\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18" + + " \x00\x00\x00\x00\x1a\x025\x90\x00\x00\x00\x00\x1a\xf24\xa0\x00\x00\x00\x00\x1b\xe2\x17\x90\x00\x00\x00\x00\x1c\xd2\x16\xa0\x00\x00\x00\x00\x1d\xc1\xf9\x90\x00\x00\x00\x00\x1e\xb1\xf8\xa0\x00\x00\x00\x00\x1f\xa1ې\x00\x00\x00" + + "\x00 v+ \x00\x00\x00\x00!\x81\xbd\x90\x00\x00\x00\x00\"V\r \x00\x00\x00\x00#j\xda\x10\x00\x00\x00\x00$5\xef \x00\x00\x00\x00%J\xbc\x10\x00\x00\x00\x00&\x15\xd1 \x00\x00\x00\x00'*\x9e" + + "\x10\x00\x00\x00\x00'\xfe\xed\xa0\x00\x00\x00\x00)\n\x80\x10\x00\x00\x00\x00)\xdeϠ\x00\x00\x00\x00*\xeab\x10\x00\x00\x00\x00+\xbe\xb1\xa0\x00\x00\x00\x00,\xd3~\x90\x00\x00\x00\x00-\x9e\x93\xa0\x00\x00\x00" + + "\x00.\xb3`\x90\x00\x00\x00\x00/~u\xa0\x00\x00\x00\x000\x93B\x90\x00\x00\x00\x001g\x92 \x00\x00\x00\x002s$\x90\x00\x00\x00\x003Gt \x00\x00\x00\x004S\x06\x90\x00\x00\x00\x005'V" + + " \x00\x00\x00\x0062\xe8\x90\x00\x00\x00\x007\a8 \x00\x00\x00\x008\x1c\x05\x10\x00\x00\x00\x008\xe7\x1a \x00\x00\x00\x009\xfb\xe7\x10\x00\x00\x00\x00:\xc6\xfc \x00\x00\x00\x00;\xdb\xc9\x10\x00\x00\x00" + + "\x00<\xb0\x18\xa0\x00\x00\x00\x00=\xbb\xab\x10\x00\x00\x00\x00>\x8f\xfa\xa0\x00\x00\x00\x00?\x9b\x8d\x10\x00\x00\x00\x00@oܠ\x00\x00\x00\x00A\x84\xa9\x90\x00\x00\x00\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b" + + "\x90\x00\x00\x00\x00D/\xa0\xa0\x00\x00\x00\x00EDm\x90\x00\x00\x00\x00E\xf3\xd3 \x00\x00\x00\x00G-\x8a\x10\x00\x00\x00\x00Gӵ \x00\x00\x00\x00I\rl\x10\x00\x00\x00\x00I\xb3\x97 \x00\x00\x00" + + "\x00J\xedN\x10\x00\x00\x00\x00K\x9c\xb3\xa0\x00\x00\x00\x00L\xd6j\x90\x00\x00\x00\x00M|\x95\xa0\x00\x00\x00\x00N\xb6L\x90\x00\x00\x00\x00O\\w\xa0\x00\x00\x00\x00P\x96.\x90\x00\x00\x00\x00Q4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSc)\xf6)\xb3\x00\x00\x00\xb3\x00" + + "\x00\x00\x0e\x00\x1c\x00America/BogotaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff^\x9c4\xf0\xff\xff\xff\xff\x98XUp\x00\x00\x00\x00*\x03sP\x00\x00\x00\x00+\xbe]@\x01\x03\x02\x03\xff" + + "\xff\xba\x90\x00\x00\xff\xff\xba\x90\x00\x04\xff\xff\xc7\xc0\x01\b\xff\xff\xb9\xb0\x00\fLMT\x00BMT\x00-04\x00-05\x00\n<-05>5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82i" + + "S8O:\xbf\x95\x03\x00\x00\x95\x03\x00\x00\x11\x00\x1c\x00America/MenomineeUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_" + + "\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00R\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xffawIc\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9" + + "p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xd3u\xf3\x00\xff\xff\xff\xff\xd4@\xeb\xf0\xff\xff\xff" + + "\xff\xf9\x0fJ\x80\xff\xff\xff\xff\xfa\bg\xf0\xff\xff\xff\xff\xfe\xb8+\x00\x00\x00\x00\x00\x06@\xdfp\x00\x00\x00\x00\a0\xd0p\x00\x00\x00\x00\a\x8d'\x80\x00\x00\x00\x00\t\x10\xb2p\x00\x00\x00\x00\t\xad\xa3" + + "\x00\x00\x00\x00\x00\n\xf0\x94p\x00\x00\x00\x00\v\xe0\x93\x80\x00\x00\x00\x00\fٰ\xf0\x00\x00\x00\x00\r\xc0u\x80\x00\x00\x00\x00\x0e\xb9\x92\xf0\x00\x00\x00\x00\x0f\xa9\x92\x00\x00\x00\x00\x00\x10\x99t\xf0\x00\x00\x00" + + "\x00\x11\x89t\x00\x00\x00\x00\x00\x12yV\xf0\x00\x00\x00\x00\x13iV\x00\x00\x00\x00\x00\x14Y8\xf0\x00\x00\x00\x00\x15I8\x00\x00\x00\x00\x00\x169\x1a\xf0\x00\x00\x00\x00\x17)\x1a\x00\x00\x00\x00\x00\x18\"7" + + "p\x00\x00\x00\x00\x19\b\xfc\x00\x00\x00\x00\x00\x1a\x02\x19p\x00\x00\x00\x00\x1a\xf2\x18\x80\x00\x00\x00\x00\x1b\xe1\xfbp\x00\x00\x00\x00\x1c\xd1\xfa\x80\x00\x00\x00\x00\x1d\xc1\xddp\x00\x00\x00\x00\x1e\xb1܀\x00\x00\x00" + + "\x00\x1f\xa1\xbfp\x00\x00\x00\x00 v\x0f\x00\x00\x00\x00\x00!\x81\xa1p\x00\x00\x00\x00\"U\xf1\x00\x00\x00\x00\x00#j\xbd\xf0\x00\x00\x00\x00$5\xd3\x00\x00\x00\x00\x00%J\x9f\xf0\x00\x00\x00\x00&\x15\xb5" + + "\x00\x00\x00\x00\x00'*\x81\xf0\x00\x00\x00\x00'\xfeр\x00\x00\x00\x00)\nc\xf0\x00\x00\x00\x00)\u07b3\x80\x00\x00\x00\x00*\xeaE\xf0\x00\x00\x00\x00+\xbe\x95\x80\x00\x00\x00\x00,\xd3bp\x00\x00\x00" + + "\x00-\x9ew\x80\x00\x00\x00\x00.\xb3Dp\x00\x00\x00\x00/~Y\x80\x00\x00\x00\x000\x93&p\x00\x00\x00\x001gv\x00\x00\x00\x00\x002s\bp\x00\x00\x00\x003GX\x00\x00\x00\x00\x004R\xea" + + "p\x00\x00\x00\x005':\x00\x00\x00\x00\x0062\xccp\x00\x00\x00\x007\a\x1c\x00\x00\x00\x00\x008\x1b\xe8\xf0\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xca\xf0\x00\x00\x00\x00:\xc6\xe0\x00\x00\x00\x00" + + "\x00;۬\xf0\x00\x00\x00\x00<\xaf\xfc\x80\x00\x00\x00\x00=\xbb\x8e\xf0\x00\x00\x00\x00>\x8fހ\x00\x00\x00\x00?\x9bp\xf0\x00\x00\x00\x00@o\xc0\x80\x00\x00\x00\x00A\x84\x8dp\x00\x00\x00\x00BO\xa2" + + "\x80\x00\x00\x00\x00Cdop\x00\x00\x00\x00D/\x84\x80\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7\x00\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x05\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xad\xdd\x00" + + "\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14LMT\x00CDT\x00CST\x00CWT\x00CPT\x00EST\x00\nCST6" + + "CDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS<\xb9\x18\x87\xe4\x02\x00\x00\xe4\x02\x00\x00\x0f\x00\x1c\x00America/Iqa" + + "luitUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<\x00" + + "\x00\x00\b\x00\x00\x00!\xff\xff\xff\xff\xccl\xa1\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xfb\xe0\xff\xff\xff\xff\xf7/>P\xff\xff\xff\xff\xf8(i\xd0\x00\x00\x00\x00\x13iG\xf0\x00\x00\x00\x00\x14" + + "Y*\xe0\x00\x00\x00\x00\x15I)\xf0\x00\x00\x00\x00\x169\f\xe0\x00\x00\x00\x00\x17)\v\xf0\x00\x00\x00\x00\x18\")`\x00\x00\x00\x00\x19\b\xed\xf0\x00\x00\x00\x00\x1a\x02\v`\x00\x00\x00\x00\x1a\xf2\np\x00" + + "\x00\x00\x00\x1b\xe1\xed`\x00\x00\x00\x00\x1c\xd1\xecp\x00\x00\x00\x00\x1d\xc1\xcf`\x00\x00\x00\x00\x1e\xb1\xcep\x00\x00\x00\x00\x1f\xa1\xb1`\x00\x00\x00\x00 v\x00\xf0\x00\x00\x00\x00!\x81\x93`\x00\x00\x00\x00\"" + + "U\xe2\xf0\x00\x00\x00\x00#j\xaf\xe0\x00\x00\x00\x00$5\xc4\xf0\x00\x00\x00\x00%J\x91\xe0\x00\x00\x00\x00&\x15\xa6\xf0\x00\x00\x00\x00'*s\xe0\x00\x00\x00\x00'\xfe\xc3p\x00\x00\x00\x00)\nU\xe0\x00" + + "\x00\x00\x00)ޥp\x00\x00\x00\x00*\xea7\xe0\x00\x00\x00\x00+\xbe\x87p\x00\x00\x00\x00,\xd3T`\x00\x00\x00\x00-\x9eip\x00\x00\x00\x00.\xb36`\x00\x00\x00\x00/~Kp\x00\x00\x00\x000" + + "\x93\x18`\x00\x00\x00\x001gg\xf0\x00\x00\x00\x002r\xfa`\x00\x00\x00\x003GI\xf0\x00\x00\x00\x004R\xdc`\x00\x00\x00\x005'+\xf0\x00\x00\x00\x0062\xbe`\x00\x00\x00\x007\a\r\xf0\x00" + + "\x00\x00\x008\x1b\xda\xe0\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xca\xf0\x00\x00\x00\x00:\xc6\xd1\xf0\x00\x00\x00\x00;۞\xe0\x00\x00\x00\x00<\xaf\xeep\x00\x00\x00\x00=\xbb\x80\xe0\x00\x00\x00\x00>" + + "\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00" + + "\x00\x00\x00E\xf3\xa8\xf0\x05\x01\x02\x03\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x06\a\x02\x04\x02\x04\x02\x04\x02" + + "\x04\x02\x04\x02\x04\x02\x04\x00\x00\x00\x00\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xc7\xc0\x01\x11\xff\xff\xc7\xc0\x01\x15\xff\xff\xab\xa0\x00\x19\xff\xff\xb9\xb0\x01\x1d-00\x00E" + + "PT\x00EST\x00EDDT\x00EDT\x00EWT\x00CST\x00CDT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00" + + "\x00\x00#\x82iS\xad`\x12\xe9\xaa\x00\x00\x00\xaa\x00\x00\x00\x0e\x00\x1c\x00America/La_PazUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04" + + "S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffi\x87\x1bd\xff\xff\xff\xff\xb8\x1e\x96\xe4\xff\xff\xff\xff\xb8" + + "\xee\xd5\xd4\x01\x02\x03\xff\xff\xc0\x1c\x00\x00\xff\xff\xc0\x1c\x00\x04\xff\xff\xce,\x01\b\xff\xff\xc7\xc0\x00\fLMT\x00CMT\x00BST\x00-04\x00\n<-04>4\nPK\x03\x04\n\x00" + + "\x00\x00\x00\x00#\x82iS\xae,\xa44\xc9\x03\x00\x00\xc9\x03\x00\x00\f\x00\x1c\x00America/AdakUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04" + + "S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00T\x00\x00\x00\n\x00\x00\x00!\xff\xff\xff\xff?\xc2\xfd\xd1\xff\xff\xff\xff}\x87Z^\xff\xff\xff\xff\xcb" + + "\x89D\xd0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2aP@\xff\xff\xff\xff\xfa\xd2U\xb0\xff\xff\xff\xff\xfe\xb8qP\xff\xff\xff\xff\xff\xa8T@\x00\x00\x00\x00\x00\x98SP\x00\x00\x00\x00\x01\x886@\x00" + + "\x00\x00\x00\x02x5P\x00\x00\x00\x00\x03qR\xc0\x00\x00\x00\x00\x04aQ\xd0\x00\x00\x00\x00\x05Q4\xc0\x00\x00\x00\x00\x06A3\xd0\x00\x00\x00\x00\a1\x16\xc0\x00\x00\x00\x00\a\x8dm\xd0\x00\x00\x00\x00\t" + + "\x10\xf8\xc0\x00\x00\x00\x00\t\xad\xe9P\x00\x00\x00\x00\n\xf0\xda\xc0\x00\x00\x00\x00\v\xe0\xd9\xd0\x00\x00\x00\x00\f\xd9\xf7@\x00\x00\x00\x00\r\xc0\xbb\xd0\x00\x00\x00\x00\x0e\xb9\xd9@\x00\x00\x00\x00\x0f\xa9\xd8P\x00" + + "\x00\x00\x00\x10\x99\xbb@\x00\x00\x00\x00\x11\x89\xbaP\x00\x00\x00\x00\x12y\x9d@\x00\x00\x00\x00\x13i\x9cP\x00\x00\x00\x00\x14Y\u007f@\x00\x00\x00\x00\x15I~P\x00\x00\x00\x00\x169a@\x00\x00\x00\x00\x17" + + ")`P\x00\x00\x00\x00\x18\"}\xc0\x00\x00\x00\x00\x19\tBP\x00\x00\x00\x00\x1a\x02_\xc0\x00\x00\x00\x00\x1a+\" \x00\x00\x00\x00\x1a\xf2P\xc0\x00\x00\x00\x00\x1b\xe23\xb0\x00\x00\x00\x00\x1c\xd22\xc0\x00" + + "\x00\x00\x00\x1d\xc2\x15\xb0\x00\x00\x00\x00\x1e\xb2\x14\xc0\x00\x00\x00\x00\x1f\xa1\xf7\xb0\x00\x00\x00\x00 vG@\x00\x00\x00\x00!\x81ٰ\x00\x00\x00\x00\"V)@\x00\x00\x00\x00#j\xf60\x00\x00\x00\x00$" + + "6\v@\x00\x00\x00\x00%J\xd80\x00\x00\x00\x00&\x15\xed@\x00\x00\x00\x00'*\xba0\x00\x00\x00\x00'\xff\t\xc0\x00\x00\x00\x00)\n\x9c0\x00\x00\x00\x00)\xde\xeb\xc0\x00\x00\x00\x00*\xea~0\x00" + + "\x00\x00\x00+\xbe\xcd\xc0\x00\x00\x00\x00,Ӛ\xb0\x00\x00\x00\x00-\x9e\xaf\xc0\x00\x00\x00\x00.\xb3|\xb0\x00\x00\x00\x00/~\x91\xc0\x00\x00\x00\x000\x93^\xb0\x00\x00\x00\x001g\xae@\x00\x00\x00\x002" + + "s@\xb0\x00\x00\x00\x003G\x90@\x00\x00\x00\x004S\"\xb0\x00\x00\x00\x005'r@\x00\x00\x00\x0063\x04\xb0\x00\x00\x00\x007\aT@\x00\x00\x00\x008\x1c!0\x00\x00\x00\x008\xe76@\x00" + + "\x00\x00\x009\xfc\x030\x00\x00\x00\x00:\xc7\x18@\x00\x00\x00\x00;\xdb\xe50\x00\x00\x00\x00<\xb04\xc0\x00\x00\x00\x00=\xbb\xc70\x00\x00\x00\x00>\x90\x16\xc0\x00\x00\x00\x00?\x9b\xa90\x00\x00\x00\x00@" + + "o\xf8\xc0\x00\x00\x00\x00A\x84Ű\x00\x00\x00\x00BO\xda\xc0\x00\x00\x00\x00Cd\xa7\xb0\x00\x00\x00\x00D/\xbc\xc0\x00\x00\x00\x00ED\x89\xb0\x00\x00\x00\x00E\xf3\xef@\x01\x02\x03\x04\x02\x05\x06\x05\x06" + + "\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\a\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t" + + "\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\x00\x00\xab\xe2\x00\x00\xff\xffZb\x00\x00\xff\xffeP\x00\x04\xff\xffs`\x01\b\xff\xffs`\x01\f\xff\xffeP\x00\x10\xff\xffs`\x01\x14\xff\xffs" + + "`\x00\x18\xff\xff\x81p\x01\x1d\xff\xffs`\x00\x19LMT\x00NST\x00NWT\x00NPT\x00BST\x00BDT\x00AHST\x00HDT\x00\nHST10HDT,M3" + + ".2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xea$\xc1\xbf\xb0\x00\x00\x00\xb0\x00\x00\x00\x13\x00\x1c\x00America/El_Salvad" + + "orUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00" + + "\x03\x00\x00\x00\f\xff\xff\xff\xff\xa3զ \x00\x00\x00\x00 \x9a\xdc\xe0\x00\x00\x00\x00!\\\x9bP\x00\x00\x00\x00\"z\xbe\xe0\x00\x00\x00\x00#<}P\x02\x01\x02\x01\x02\xff\xff\xac`\x00\x00\xff\xff\xb9\xb0" + + "\x01\x04\xff\xff\xab\xa0\x00\bLMT\x00CDT\x00CST\x00\nCST6\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSԾ\xe7#\x95\x00\x00\x00\x95\x00\x00\x00\x15\x00\x1c\x00Amer" + + "ica/Coral_HarbourUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xffi\x87&\x10\xff\xff\xff\xff\x8b\xf4a\xe8\x01\x02\xff\xff\xb5p\x00\x00\xff\xff\xb5\x18\x00\x04\xff\xff\xb9\xb0\x00\bLMT\x00" + + "CMT\x00EST\x00\nEST5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x1c\x00America/Kentucky" + + "/UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x03\x1a|J\xcc\x03\x00\x00\xcc\x03\x00\x00\x1b\x00\x1c\x00A" + + "merica/Kentucky/MonticelloUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00W\x00\x00\x00\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e" + + "\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xfc\xd8I\x00\xff\xff\xff\xff\xfd\xc8+\xf0\xff\xff\xff\xff\xfe\xb8+\x00\xff\xff\xff" + + "\xff\xff\xa8\r\xf0\x00\x00\x00\x00\x00\x98\r\x00\x00\x00\x00\x00\x01\x87\xef\xf0\x00\x00\x00\x00\x02w\xef\x00\x00\x00\x00\x00\x03q\fp\x00\x00\x00\x00\x04a\v\x80\x00\x00\x00\x00\x05P\xeep\x00\x00\x00\x00\x06@\xed" + + "\x80\x00\x00\x00\x00\a0\xd0p\x00\x00\x00\x00\a\x8d'\x80\x00\x00\x00\x00\t\x10\xb2p\x00\x00\x00\x00\t\xad\xa3\x00\x00\x00\x00\x00\n\xf0\x94p\x00\x00\x00\x00\v\xe0\x93\x80\x00\x00\x00\x00\fٰ\xf0\x00\x00\x00" + + "\x00\r\xc0u\x80\x00\x00\x00\x00\x0e\xb9\x92\xf0\x00\x00\x00\x00\x0f\xa9\x92\x00\x00\x00\x00\x00\x10\x99t\xf0\x00\x00\x00\x00\x11\x89t\x00\x00\x00\x00\x00\x12yV\xf0\x00\x00\x00\x00\x13iV\x00\x00\x00\x00\x00\x14Y8" + + "\xf0\x00\x00\x00\x00\x15I8\x00\x00\x00\x00\x00\x169\x1a\xf0\x00\x00\x00\x00\x17)\x1a\x00\x00\x00\x00\x00\x18\"7p\x00\x00\x00\x00\x19\b\xfc\x00\x00\x00\x00\x00\x1a\x02\x19p\x00\x00\x00\x00\x1a\xf2\x18\x80\x00\x00\x00" + + "\x00\x1b\xe1\xfbp\x00\x00\x00\x00\x1c\xd1\xfa\x80\x00\x00\x00\x00\x1d\xc1\xddp\x00\x00\x00\x00\x1e\xb1܀\x00\x00\x00\x00\x1f\xa1\xbfp\x00\x00\x00\x00 v\x0f\x00\x00\x00\x00\x00!\x81\xa1p\x00\x00\x00\x00\"U\xf1" + + "\x00\x00\x00\x00\x00#j\xbd\xf0\x00\x00\x00\x00$5\xd3\x00\x00\x00\x00\x00%J\x9f\xf0\x00\x00\x00\x00&\x15\xb5\x00\x00\x00\x00\x00'*\x81\xf0\x00\x00\x00\x00'\xfeр\x00\x00\x00\x00)\nc\xf0\x00\x00\x00" + + "\x00)\u07b3\x80\x00\x00\x00\x00*\xeaE\xf0\x00\x00\x00\x00+\xbe\x95\x80\x00\x00\x00\x00,\xd3bp\x00\x00\x00\x00-\x9ew\x80\x00\x00\x00\x00.\xb3Dp\x00\x00\x00\x00/~Y\x80\x00\x00\x00\x000\x93&" + + "p\x00\x00\x00\x001gv\x00\x00\x00\x00\x002s\bp\x00\x00\x00\x003GX\x00\x00\x00\x00\x004R\xeap\x00\x00\x00\x005':\x00\x00\x00\x00\x0062\xccp\x00\x00\x00\x007\a\x1c\x00\x00\x00\x00" + + "\x008\x1b\xe8\xf0\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xca\xf0\x00\x00\x00\x00:\xc6\xd1\xf0\x00\x00\x00\x00;۞\xe0\x00\x00\x00\x00<\xaf\xeep\x00\x00\x00\x00=\xbb\x80\xe0\x00\x00\x00\x00>\x8f\xd0" + + "p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00" + + "\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\xff\xff\xb0t\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0" + + "\x01\x10\xff\xff\xc7\xc0\x01\x14\xff\xff\xb9\xb0\x00\x18LMT\x00CDT\x00CST\x00CWT\x00CPT\x00EDT\x00EST\x00\nEST5EDT,M3.2.0,M1" + + "1.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xdf\xe5\x8d\xc4\xda\x04\x00\x00\xda\x04\x00\x00\x1b\x00\x1c\x00America/Kentucky/Louisvi" + + "lleUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00u\x00\x00" + + "\x00\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xff\xa4s\xf7\x00\xff\xff\xff\xff\xa5\x16" + + "\x11p\xff\xff\xff\xff\xca\rN\x80\xff\xff\xff\xff\xca\xd8Gp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xd3u\xd7\x1c\xff\xff\xff\xffӤ\tp\xff\xff" + + "\xff\xff\xda\xfe\xb5\x80\xff\xff\xff\xff\xdb\xc0s\xf0\xff\xff\xff\xff\xdcޗ\x80\xff\xff\xff\xffݩ\x90p\xff\xff\xff\xff\u07bey\x80\xff\xff\xff\xff߉rp\xff\xff\xff\xff\xe0\x9e[\x80\xff\xff\xff\xff\xe1i" + + "Tp\xff\xff\xff\xff\xe2~=\x80\xff\xff\xff\xff\xe3I6p\xff\xff\xff\xff\xe4^\x1f\x80\xff\xff\xff\xff\xe5)\x18p\xff\xff\xff\xff\xe6G<\x00\xff\xff\xff\xff\xe77\x1e\xf0\xff\xff\xff\xff\xe8'\x1e\x00\xff\xff" + + "\xff\xff\xe9\x17\x00\xf0\xff\xff\xff\xff\xea\a\x00\x00\xff\xff\xff\xff\xea\xf6\xe2\xf0\xff\xff\xff\xff\xeb\xe6\xe2\x00\xff\xff\xff\xff\xec\xd6\xc4\xf0\xff\xff\xff\xff\xed\xc6\xc4\x00\xff\xff\xff\xff\xee\xbf\xe1p\xff\xff\xff\xff\xef\xaf" + + "\xe0\x80\xff\xff\xff\xff\xf0\x1e\x90p\xff\xff\xff\xff\xfc\xd8:\xf0\xff\xff\xff\xff\xfd\xc8\x1d\xe0\xff\xff\xff\xff\xfe\xb8\x1c\xf0\xff\xff\xff\xff\xff\xa7\xff\xe0\x00\x00\x00\x00\x00\x97\xfe\xf0\x00\x00\x00\x00\x01\x87\xe1\xe0\x00\x00" + + "\x00\x00\x02w\xe0\xf0\x00\x00\x00\x00\x03p\xfe`\x00\x00\x00\x00\x04`\xfdp\x00\x00\x00\x00\x05P\xe0`\x00\x00\x00\x00\x06@\xdfp\x00\x00\x00\x00\a0\xc2`\x00\x00\x00\x00\a\x8d\x19p\x00\x00\x00\x00\t\x10" + + "\xb2p\x00\x00\x00\x00\t\xad\x94\xf0\x00\x00\x00\x00\n\xf0\x86`\x00\x00\x00\x00\v\xe0\x85p\x00\x00\x00\x00\f٢\xe0\x00\x00\x00\x00\r\xc0gp\x00\x00\x00\x00\x0e\xb9\x84\xe0\x00\x00\x00\x00\x0f\xa9\x83\xf0\x00\x00" + + "\x00\x00\x10\x99f\xe0\x00\x00\x00\x00\x11\x89e\xf0\x00\x00\x00\x00\x12yH\xe0\x00\x00\x00\x00\x13iG\xf0\x00\x00\x00\x00\x14Y*\xe0\x00\x00\x00\x00\x15I)\xf0\x00\x00\x00\x00\x169\f\xe0\x00\x00\x00\x00\x17)" + + "\v\xf0\x00\x00\x00\x00\x18\")`\x00\x00\x00\x00\x19\b\xed\xf0\x00\x00\x00\x00\x1a\x02\v`\x00\x00\x00\x00\x1a\xf2\np\x00\x00\x00\x00\x1b\xe1\xed`\x00\x00\x00\x00\x1c\xd1\xecp\x00\x00\x00\x00\x1d\xc1\xcf`\x00\x00" + + "\x00\x00\x1e\xb1\xcep\x00\x00\x00\x00\x1f\xa1\xb1`\x00\x00\x00\x00 v\x00\xf0\x00\x00\x00\x00!\x81\x93`\x00\x00\x00\x00\"U\xe2\xf0\x00\x00\x00\x00#j\xaf\xe0\x00\x00\x00\x00$5\xc4\xf0\x00\x00\x00\x00%J" + + "\x91\xe0\x00\x00\x00\x00&\x15\xa6\xf0\x00\x00\x00\x00'*s\xe0\x00\x00\x00\x00'\xfe\xc3p\x00\x00\x00\x00)\nU\xe0\x00\x00\x00\x00)ޥp\x00\x00\x00\x00*\xea7\xe0\x00\x00\x00\x00+\xbe\x87p\x00\x00" + + "\x00\x00,\xd3T`\x00\x00\x00\x00-\x9eip\x00\x00\x00\x00.\xb36`\x00\x00\x00\x00/~Kp\x00\x00\x00\x000\x93\x18`\x00\x00\x00\x001gg\xf0\x00\x00\x00\x002r\xfa`\x00\x00\x00\x003G" + + "I\xf0\x00\x00\x00\x004R\xdc`\x00\x00\x00\x005'+\xf0\x00\x00\x00\x0062\xbe`\x00\x00\x00\x007\a\r\xf0\x00\x00\x00\x008\x1b\xda\xe0\x00\x00\x00\x008\xe6\xef\xf0\x00\x00\x00\x009\xfb\xbc\xe0\x00\x00" + + "\x00\x00:\xc6\xd1\xf0\x00\x00\x00\x00;۞\xe0\x00\x00\x00\x00<\xaf\xeep\x00\x00\x00\x00=\xbb\x80\xe0\x00\x00\x00\x00>\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00A\x84" + + "\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x01\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05" + + "\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\xff\xff\xaf\x9a\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9" + + "\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14\xff\xff\xc7\xc0\x01\x18LMT\x00CDT\x00CST\x00CWT\x00CPT\x00EST\x00EDT\x00\nEST5EDT,M3" + + ".2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS3\x9aG\xc8\xd0\x06\x00\x00\xd0\x06\x00\x00\x10\x00\x1c\x00America/New_YorkU" + + "T\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaf\x00\x00\x00\x05\x00\x00" + + "\x00\x14\xff\xff\xff\xff^\x03\xf0\x90\xff\xff\xff\xff\x9e\xa6\x1ep\xff\xff\xff\xff\x9f\xba\xeb`\xff\xff\xff\xff\xa0\x86\x00p\xff\xff\xff\xff\xa1\x9a\xcd`\xff\xff\xff\xff\xa2e\xe2p\xff\xff\xff\xff\xa3\x83\xe9\xe0\xff\xff" + + "\xff\xff\xa4j\xaep\xff\xff\xff\xff\xa55\xa7`\xff\xff\xff\xff\xa6S\xca\xf0\xff\xff\xff\xff\xa7\x15\x89`\xff\xff\xff\xff\xa83\xac\xf0\xff\xff\xff\xff\xa8\xfe\xa5\xe0\xff\xff\xff\xff\xaa\x13\x8e\xf0\xff\xff\xff\xff\xaa\xde" + + "\x87\xe0\xff\xff\xff\xff\xab\xf3p\xf0\xff\xff\xff\xff\xac\xbei\xe0\xff\xff\xff\xff\xad\xd3R\xf0\xff\xff\xff\xff\xae\x9eK\xe0\xff\xff\xff\xff\xaf\xb34\xf0\xff\xff\xff\xff\xb0~-\xe0\xff\xff\xff\xff\xb1\x9cQp\xff\xff" + + "\xff\xff\xb2gJ`\xff\xff\xff\xff\xb3|3p\xff\xff\xff\xff\xb4G,`\xff\xff\xff\xff\xb5\\\x15p\xff\xff\xff\xff\xb6'\x0e`\xff\xff\xff\xff\xb7;\xf7p\xff\xff\xff\xff\xb8\x06\xf0`\xff\xff\xff\xff\xb9\x1b" + + "\xd9p\xff\xff\xff\xff\xb9\xe6\xd2`\xff\xff\xff\xff\xbb\x04\xf5\xf0\xff\xff\xff\xff\xbbƴ`\xff\xff\xff\xff\xbc\xe4\xd7\xf0\xff\xff\xff\xff\xbd\xaf\xd0\xe0\xff\xff\xff\xff\xbeĹ\xf0\xff\xff\xff\xff\xbf\x8f\xb2\xe0\xff\xff" + + "\xff\xff\xc0\xa4\x9b\xf0\xff\xff\xff\xff\xc1o\x94\xe0\xff\xff\xff\xff\u0084}\xf0\xff\xff\xff\xff\xc3Ov\xe0\xff\xff\xff\xff\xc4d_\xf0\xff\xff\xff\xff\xc5/X\xe0\xff\xff\xff\xff\xc6M|p\xff\xff\xff\xff\xc7\x0f" + + ":\xe0\xff\xff\xff\xff\xc8-^p\xff\xff\xff\xff\xc8\xf8W`\xff\xff\xff\xff\xca\r@p\xff\xff\xff\xff\xca\xd89`\xff\xff\xff\xffˈ\xf0p\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xfb\xe0\xff\xff" + + "\xff\xff\xd3u\xe4\xf0\xff\xff\xff\xff\xd4@\xdd\xe0\xff\xff\xff\xff\xd5U\xc6\xf0\xff\xff\xff\xff\xd6 \xbf\xe0\xff\xff\xff\xff\xd75\xa8\xf0\xff\xff\xff\xff\xd8\x00\xa1\xe0\xff\xff\xff\xff\xd9\x15\x8a\xf0\xff\xff\xff\xff\xd9\xe0" + + "\x83\xe0\xff\xff\xff\xff\xda\xfe\xa7p\xff\xff\xff\xff\xdb\xc0e\xe0\xff\xff\xff\xff\xdcމp\xff\xff\xff\xffݩ\x82`\xff\xff\xff\xff\u07bekp\xff\xff\xff\xff߉d`\xff\xff\xff\xff\xe0\x9eMp\xff\xff" + + "\xff\xff\xe1iF`\xff\xff\xff\xff\xe2~/p\xff\xff\xff\xff\xe3I(`\xff\xff\xff\xff\xe4^\x11p\xff\xff\xff\xff\xe5W.\xe0\xff\xff\xff\xff\xe6G-\xf0\xff\xff\xff\xff\xe77\x10\xe0\xff\xff\xff\xff\xe8'" + + "\x0f\xf0\xff\xff\xff\xff\xe9\x16\xf2\xe0\xff\xff\xff\xff\xea\x06\xf1\xf0\xff\xff\xff\xff\xea\xf6\xd4\xe0\xff\xff\xff\xff\xeb\xe6\xd3\xf0\xff\xff\xff\xff\xecֶ\xe0\xff\xff\xff\xff\xedƵ\xf0\xff\xff\xff\xff\xee\xbf\xd3`\xff\xff" + + "\xff\xff\xef\xaf\xd2p\xff\xff\xff\xff\xf0\x9f\xb5`\xff\xff\xff\xff\xf1\x8f\xb4p\xff\xff\xff\xff\xf2\u007f\x97`\xff\xff\xff\xff\xf3o\x96p\xff\xff\xff\xff\xf4_y`\xff\xff\xff\xff\xf5Oxp\xff\xff\xff\xff\xf6?" + + "[`\xff\xff\xff\xff\xf7/Zp\xff\xff\xff\xff\xf8(w\xe0\xff\xff\xff\xff\xf9\x0f\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00" + + "\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\xff\xff\xd4L\x00\x00\xff\xff\xe3\xe0\x01\x04\xff\xff\xd5\xd0\x00\bLMT\x00-02\x00-03\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R" + - "g\xf5K\x89\xa2\x01\x00\x00\xa2\x01\x00\x00\x12\x00\x1c\x00America/Rio_BrancoUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03" + - "\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x00\x00\x00\x04\x00\x00\x00\f\xff\xff\xff\xff\x96\xaa\x86\x90\xff\xff\xff\xff\xb8\x0ff\x00\xff\xff\xff\xff\xb8\xfd\\" + - "\xc0\xff\xff\xff\xff\xb9\xf1PP\xff\xff\xff\xff\xbaސ@\xff\xff\xff\xff\xda8\xcaP\xff\xff\xff\xff\xda\xec\x16P\xff\xff\xff\xff\xdc\x19\xfd\xd0\xff\xff\xff\xffܹu@\xff\xff\xff\xff\xdd\xfb1P\xff\xff\xff" + - "\xffޛ\xfa@\xff\xff\xff\xff\xdfݶP\xff\xff\xff\xff\xe0TO@\xff\xff\xff\xff\xf4\x98\x1b\xd0\xff\xff\xff\xff\xf5\x05z@\xff\xff\xff\xff\xf6\xc0\x80P\xff\xff\xff\xff\xf7\x0e:\xc0\xff\xff\xff\xff\xf8QH" + - "P\xff\xff\xff\xff\xf8\xc7\xe1@\xff\xff\xff\xff\xfa\n\xee\xd0\xff\xff\xff\xff\xfa\xa9\x14\xc0\xff\xff\xff\xff\xfb\xec\"P\xff\xff\xff\xff\xfc\x8b\x99\xc0\x00\x00\x00\x00\x1dɪP\x00\x00\x00\x00\x1ex\xf3\xc0\x00\x00\x00" + - "\x00\x1f\xa0Q\xd0\x00\x00\x00\x00 3\xeb\xc0\x00\x00\x00\x00!\x81\x85P\x00\x00\x00\x00\"\v\xe4\xc0\x00\x00\x00\x00H`\u007fP\x00\x00\x00\x00R\u007f\x04\xc0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x02\xff\xff\xc0p\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x00\x04LMT\x00-04\x00-05\x00\n<-05>5\n" + - "PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xb1݂x\xe8\x00\x00\x00\xe8\x00\x00\x00\x12\x00\x1c\x00America/Costa_RicaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e" + - "`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01" + - "\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x04\x00\x00\x00\x11\xff\xff\xff\xffi\x87*M\xff" + - "\xff\xff\xff\xa3\xe8\x16M\x00\x00\x00\x00\x116I`\x00\x00\x00\x00\x11\xb7nP\x00\x00\x00\x00\x13\x16+`\x00\x00\x00\x00\x13\x97PP\x00\x00\x00\x00'\x97\xe0`\x00\x00\x00\x00(n\xb6\xd0\x00\x00\x00\x00)" + - "w\xc2`\x00\x00\x00\x00)\xc2\xd9\xd0\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\xff\xff\xb13\x00\x00\xff\xff\xb13\x00\x04\xff\xff\xb9\xb0\x01\t\xff\xff\xab\xa0\x00\rLMT\x00SJMT\x00CDT\x00CS" + - "T\x00\nCST6\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x1b\x81-\xa9\x8a\x01\x00\x00\x8a\x01\x00\x00\x13\x00\x1c\x00America/Porto_VelhoUT\t" + - "\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00\x03\x00\x00\x00\f" + - "\xff\xff\xff\xff\x96\xaa\x82\xe8\xff\xff\xff\xff\xb8\x0fW\xf0\xff\xff\xff\xff\xb8\xfdN\xb0\xff\xff\xff\xff\xb9\xf1B@\xff\xff\xff\xff\xbaނ0\xff\xff\xff\xff\xda8\xbc@\xff\xff\xff\xff\xda\xec\b@\xff\xff\xff\xff" + - "\xdc\x19\xef\xc0\xff\xff\xff\xffܹg0\xff\xff\xff\xff\xdd\xfb#@\xff\xff\xff\xffޛ\xec0\xff\xff\xff\xff\xdfݨ@\xff\xff\xff\xff\xe0TA0\xff\xff\xff\xff\xf4\x98\r\xc0\xff\xff\xff\xff\xf5\x05l0" + - "\xff\xff\xff\xff\xf6\xc0r@\xff\xff\xff\xff\xf7\x0e,\xb0\xff\xff\xff\xff\xf8Q:@\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xfa\n\xe0\xc0\xff\xff\xff\xff\xfa\xa9\x06\xb0\xff\xff\xff\xff\xfb\xec\x14@\xff\xff\xff\xff" + - "\xfc\x8b\x8b\xb0\x00\x00\x00\x00\x1dɜ@\x00\x00\x00\x00\x1ex\xe5\xb0\x00\x00\x00\x00\x1f\xa0C\xc0\x00\x00\x00\x00 3ݰ\x00\x00\x00\x00!\x81w@\x00\x00\x00\x00\"\vְ\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xff\xc4\x18\x00\x00\xff\xff\xd5\xd0\x01\x04\xff\xff\xc7\xc0\x00\bLMT\x00-03\x00-04\x00\n<-04>4\nP" + - "K\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rp\xb6{\xc9\x13\x02\x00\x00\x13\x02\x00\x00\x14\x00\x1c\x00America/IndianapolisUT\t\x00\x03\x15\xac\x0e`\x15\xac" + - "\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" + - "\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00&\x00\x00\x00\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x03\xfe\xa0" + - "\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xff\xcaW\"\x80\xff\xff\xff\xff\xca\xd8Gp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff" + - "\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xd3u\xf3\x00\xff\xff\xff\xff\xd4@\xeb\xf0\xff\xff\xff\xff\xd5U\xd5\x00\xff\xff\xff\xff\xd6 \xcd\xf0\xff\xff\xff\xff\xd75\xb7\x00\xff\xff\xff\xff\xd8\x00\xaf\xf0" + - "\xff\xff\xff\xff\xd9\x15\x99\x00\xff\xff\xff\xff\xd9\xe0\x91\xf0\xff\xff\xff\xff\xda\xfe\xb5\x80\xff\xff\xff\xff\xdb\xc0s\xf0\xff\xff\xff\xff\xdcޗ\x80\xff\xff\xff\xffݩ\x90p\xff\xff\xff\xff\u07bey\x80\xff\xff\xff\xff" + - "߉rp\xff\xff\xff\xff\xe0\x9e[\x80\xff\xff\xff\xff\xe1iTp\xff\xff\xff\xff\xe2~=\x80\xff\xff\xff\xff\xe3I6p\xff\xff\xff\xff\xe4^\x1f\x80\xff\xff\xff\xff\xe8\xf2\x16\xf0\xff\xff\xff\xff\xea\a\x00\x00" + - "\xff\xff\xff\xff\xfe\xb8\x1c\xf0\xff\xff\xff\xff\xff\xa7\xff\xe0\x00\x00\x00\x00\x00\x97\xfe\xf0\x00\x00\x00\x00\x01\x87\xe1\xe0\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01" + - "\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05\x02\x05\x06\x05\x06\x05\x06\x05\x06\xff\xff\xaf:\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff" + - "\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14\xff\xff\xc7\xc0\x01\x18LMT\x00CDT\x00CST\x00CWT\x00CPT\x00EST\x00EDT\x00\nEST5EDT,M3.2.0," + - "M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xb4T\xbd\xeb5\x02\x00\x005\x02\x00\x00\x16\x00\x1c\x00America/Port-au-Prince" + - "UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-\x00\x00\x00\x04\x00" + - "\x00\x00\x11\xff\xff\xff\xffi\x87\x1fP\xff\xff\xff\xff\x9cnq\xfc\x00\x00\x00\x00\x19\x1bF\xd0\x00\x00\x00\x00\x1a\x01\xef@\x00\x00\x00\x00\x1a\xf1\xeeP\x00\x00\x00\x00\x1b\xe1\xd1@\x00\x00\x00\x00\x1c\xd1\xd0P\x00" + - "\x00\x00\x00\x1d\xc1\xb3@\x00\x00\x00\x00\x1e\xb1\xb2P\x00\x00\x00\x00\x1f\xa1\x95@\x00\x00\x00\x00 \x91\x94P\x00\x00\x00\x00!\x81w@\x00\x00\x00\x00\"U\xd4\xe0\x00\x00\x00\x00#j\xaf\xe0\x00\x00\x00\x00$" + - "5\xb6\xe0\x00\x00\x00\x00%J\x91\xe0\x00\x00\x00\x00&\x15\x98\xe0\x00\x00\x00\x00'*s\xe0\x00\x00\x00\x00'\xfe\xb5`\x00\x00\x00\x00)\nU\xe0\x00\x00\x00\x00)ޗ`\x00\x00\x00\x00*\xea7\xe0\x00" + - "\x00\x00\x00+\xbey`\x00\x00\x00\x00,\xd3T`\x00\x00\x00\x00-\x9e[`\x00\x00\x00\x00.\xb36`\x00\x00\x00\x00/~=`\x00\x00\x00\x000\x93\x18`\x00\x00\x00\x001gY\xe0\x00\x00\x00\x002" + - "r\xfa`\x00\x00\x00\x003G;\xe0\x00\x00\x00\x004R\xdc`\x00\x00\x00\x00BOxP\x00\x00\x00\x00CdE@\x00\x00\x00\x00D/ZP\x00\x00\x00\x00ED'@\x00\x00\x00\x00O\\Mp\x00" + - "\x00\x00\x00P\x96\x04`\x00\x00\x00\x00Q\x90\x16\xc0\x00" + - "\x00\x00\x00?\x9b\xa90\x00\x00\x00\x00@o\xf8\xc0\x00\x00\x00\x00A\x84Ű\x00\x00\x00\x00BO\xda\xc0\x00\x00\x00\x00Cd\xa7\xb0\x00\x00\x00\x00D/\xbc\xc0\x00\x00\x00\x00ED\x89\xb0\x00\x00\x00\x00E" + - "\xf3\xef@\x01\x02\x03\x04\x02\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\a\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t" + - "\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\x00\x00\xab\xe2\x00\x00\xff\xffZb\x00\x00\xff\xffeP\x00\x04\xff\xffs`\x01\b\xff\xffs`\x01\f\xff\xffe" + - "P\x00\x10\xff\xffs`\x01\x14\xff\xffs`\x00\x18\xff\xff\x81p\x01\x1d\xff\xffs`\x00\x19LMT\x00NST\x00NWT\x00NPT\x00BST\x00BDT\x00AHST\x00HDT\x00" + - "\nHST10HDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R~\xb2\x0e\x19V\a\x00\x00V\a\x00\x00\x10\x00\x1c\x00Ameri" + - "ca/St_JohnsUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\xbb\x00\x00\x00\b\x00\x00\x00\x19\xff\xff\xff\xff^=4\xec\xff\xff\xff\xff\x9c\xcfb\f\xff\xff\xff\xff\x9d\xa4\xe6\xfc\xff\xff\xff\xff\x9e\xb8~\x8c\xff\xff\xff\xff\x9f\xba\xd6|\xff\xff\xff\xff\xa0\xb6" + - "\x88\xdc\xff\xff\xff\xff\xa18\xffL\xff\xff\xff\xff\xa2\x95\x19\\\xff\xff\xff\xff\xa3\x84\xfcL\xff\xff\xff\xff\xa4t\xfb\\\xff\xff\xff\xff\xa5d\xdeL\xff\xff\xff\xff\xa6^\x17\xdc\xff\xff\xff\xff\xa7D\xc0L\xff\xff" + - "\xff\xff\xa8=\xf9\xdc\xff\xff\xff\xff\xa9$\xa2L\xff\xff\xff\xff\xaa\x1d\xdb\xdc\xff\xff\xff\xff\xab\x04\x84L\xff\xff\xff\xff\xab\xfd\xbd\xdc\xff\xff\xff\xff\xac\xe4fL\xff\xff\xff\xff\xadݟ\xdc\xff\xff\xff\xff\xae\xcd" + - "\x82\xcc\xff\xff\xff\xff\xaf\xbd\x81\xdc\xff\xff\xff\xff\xb0\xadd\xcc\xff\xff\xff\xff\xb1\xa6\x9e\\\xff\xff\xff\xff\xb2\x8dF\xcc\xff\xff\xff\xff\xb3\x86\x80\\\xff\xff\xff\xff\xb4m(\xcc\xff\xff\xff\xff\xb5fb\\\xff\xff" + - "\xff\xff\xb6M\n\xcc\xff\xff\xff\xff\xb7FD\\\xff\xff\xff\xff\xb8,\xec\xcc\xff\xff\xff\xff\xb9&&\\\xff\xff\xff\xff\xba\x16\tL\xff\xff\xff\xff\xbb\x0fB\xdc\xff\xff\xff\xff\xbb\xf5\xebL\xff\xff\xff\xff\xbc\xef" + - "$\xdc\xff\xff\xff\xff\xbd\xd5\xcdL\xff\xff\xff\xff\xbe\x9eMl\xff\xff\xff\xff\xbe\xcf\x06\xa8\xff\xff\xff\xff\xbf\xb5\xaf\x18\xff\xff\xff\xff\xc0\xb818\xff\xff\xff\xff\xc1y\xef\xa8\xff\xff\xff\xff\u0098\x138\xff\xff" + - "\xff\xff\xc3YѨ\xff\xff\xff\xff\xc4w\xf58\xff\xff\xff\xff\xc59\xb3\xa8\xff\xff\xff\xff\xc6a\x11\xb8\xff\xff\xff\xff\xc7\x19\x95\xa8\xff\xff\xff\xff\xc8@\xf3\xb8\xff\xff\xff\xff\xc9\x02\xb2(\xff\xff\xff\xff\xca " + - "ո\xff\xff\xff\xff\xca\xe2\x94(\xff\xff\xff\xff\xcc\x00\xb7\xb8\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xe6\xc8\xff\xff\xff\xffӈD\xd8\xff\xff\xff\xff\xd4J\x03H\xff\xff\xff\xff\xd5h&\xd8\xff\xff" + - "\xff\xff\xd6)\xe5H\xff\xff\xff\xff\xd7H\b\xd8\xff\xff\xff\xff\xd8\t\xc7H\xff\xff\xff\xff\xd9'\xea\xd8\xff\xff\xff\xff\xd9\xe9\xa9H\xff\xff\xff\xff\xdb\x11\aX\xff\xff\xff\xff\xdb\xd2\xc5\xc8\xff\xff\xff\xff\xdc\xde" + - "tX\xff\xff\xff\xffݩmH\xff\xff\xff\xff\u07beVX\xff\xff\xff\xff߉OH\xff\xff\xff\xff\xe0\x9e8X\xff\xff\xff\xff\xe1i1H\xff\xff\xff\xff\xe2~\x1aX\xff\xff\xff\xff\xe3I\x13H\xff\xff" + - "\xff\xff\xe4]\xfcX\xff\xff\xff\xff\xe5(\xf5H\xff\xff\xff\xff\xe6G\x18\xd8\xff\xff\xff\xff\xe7\x12\x11\xc8\xff\xff\xff\xff\xe8&\xfa\xd8\xff\xff\xff\xff\xe8\xf1\xf3\xc8\xff\xff\xff\xff\xea\x06\xdc\xd8\xff\xff\xff\xff\xea\xd1" + - "\xd5\xc8\xff\xff\xff\xff\xeb\xe6\xbe\xd8\xff\xff\xff\xff챷\xc8\xff\xff\xff\xff\xedƠ\xd8\xff\xff\xff\xff\ueffeH\xff\xff\xff\xffﯽX\xff\xff\xff\xff\xf0\x9f\xa0H\xff\xff\xff\xff\xf1\x8f\x9fX\xff\xff" + - "\xff\xff\xf2\u007f\x82H\xff\xff\xff\xff\xf3o\x81X\xff\xff\xff\xff\xf4_dH\xff\xff\xff\xff\xf5OcX\xff\xff\xff\xff\xf6?FH\xff\xff\xff\xff\xf7/EX\xff\xff\xff\xff\xf8(b\xc8\xff\xff\xff\xff\xf9\x0f" + - "'X\xff\xff\xff\xff\xfa\bD\xc8\xff\xff\xff\xff\xfa\xf8C\xd8\xff\xff\xff\xff\xfb\xe8&\xc8\xff\xff\xff\xff\xfc\xd8%\xd8\xff\xff\xff\xff\xfd\xc8\b\xc8\xff\xff\xff\xff\xfe\xb8\a\xd8\xff\xff\xff\xff\xff\xa7\xea\xc8\x00\x00" + - "\x00\x00\x00\x97\xe9\xd8\x00\x00\x00\x00\x01\x87\xcc\xc8\x00\x00\x00\x00\x02w\xcb\xd8\x00\x00\x00\x00\x03p\xe9H\x00\x00\x00\x00\x04`\xe8X\x00\x00\x00\x00\x05P\xcbH\x00\x00\x00\x00\x06@\xcaX\x00\x00\x00\x00\a0" + - "\xadH\x00\x00\x00\x00\b \xacX\x00\x00\x00\x00\t\x10\x8fH\x00\x00\x00\x00\n\x00\x8eX\x00\x00\x00\x00\n\xf0qH\x00\x00\x00\x00\v\xe0pX\x00\x00\x00\x00\fٍ\xc8\x00\x00\x00\x00\r\xc0RX\x00\x00" + - "\x00\x00\x0e\xb9o\xc8\x00\x00\x00\x00\x0f\xa9n\xd8\x00\x00\x00\x00\x10\x99Q\xc8\x00\x00\x00\x00\x11\x89P\xd8\x00\x00\x00\x00\x12y3\xc8\x00\x00\x00\x00\x13i2\xd8\x00\x00\x00\x00\x14Y\x15\xc8\x00\x00\x00\x00\x15I" + - "\x14\xd8\x00\x00\x00\x00\x168\xf7\xc8\x00\x00\x00\x00\x17(\xf6\xd8\x00\x00\x00\x00\x18\"\x14H\x00\x00\x00\x00\x19\b\xd8\xd8\x00\x00\x00\x00\x1a\x01\xf6H\x00\x00\x00\x00\x1a\xf1\xf5X\x00\x00\x00\x00\x1b\xe1\xd8H\x00\x00" + - "\x00\x00\x1c\xd1\xd7X\x00\x00\x00\x00\x1d\xc1\xbaH\x00\x00\x00\x00\x1e\xb1\xb9X\x00\x00\x00\x00\x1f\xa1\x9cH\x00\x00\x00\x00 u\xcf\xf4\x00\x00\x00\x00!\x81bd\x00\x00\x00\x00\"U\xb1\xf4\x00\x00\x00\x00#j" + - "p\xd4\x00\x00\x00\x00$5\x93\xf4\x00\x00\x00\x00%J`\xe4\x00\x00\x00\x00&\x15u\xf4\x00\x00\x00\x00'*B\xe4\x00\x00\x00\x00'\xfe\x92t\x00\x00\x00\x00)\n$\xe4\x00\x00\x00\x00)\xdett\x00\x00" + - "\x00\x00*\xea\x06\xe4\x00\x00\x00\x00+\xbeVt\x00\x00\x00\x00,\xd3#d\x00\x00\x00\x00-\x9e8t\x00\x00\x00\x00.\xb3\x05d\x00\x00\x00\x00/~\x1at\x00\x00\x00\x000\x92\xe7d\x00\x00\x00\x001g" + - "6\xf4\x00\x00\x00\x002r\xc9d\x00\x00\x00\x003G\x18\xf4\x00\x00\x00\x004R\xabd\x00\x00\x00\x005&\xfa\xf4\x00\x00\x00\x0062\x8dd\x00\x00\x00\x007\x06\xdc\xf4\x00\x00\x00\x008\x1b\xa9\xe4\x00\x00" + - "\x00\x008\xe6\xbe\xf4\x00\x00\x00\x009\xfb\x8b\xe4\x00\x00\x00\x00:Ơ\xf4\x00\x00\x00\x00;\xdbm\xe4\x00\x00\x00\x00<\xaf\xbdt\x00\x00\x00\x00=\xbbO\xe4\x00\x00\x00\x00>\x8f\x9ft\x00\x00\x00\x00?\x9b" + - "1\xe4\x00\x00\x00\x00@o\x81t\x00\x00\x00\x00A\x84Nd\x00\x00\x00\x00BOct\x00\x00\x00\x00Cd0d\x00\x00\x00\x00D/Et\x00\x00\x00\x00ED\x12d\x00\x00\x00\x00E\xf3w\xf4\x00\x00" + - "\x00\x00G-.\xe4\x00\x00\x00\x00G\xd3Y\xf4\x00\x00\x00\x00I\r\x10\xe4\x00\x00\x00\x00I\xb3;\xf4\x00\x00\x00\x00J\xec\xf2\xe4\x00\x00\x00\x00K\x9cXt\x00\x00\x00\x00L\xd6\x0fd\x00\x00\x00\x00M|" + - ":t\x00\x00\x00\x00N\xb6\rH\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04" + - "\x03\x04\x06\x05\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03" + - "\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\a\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03" + - "\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\xff\xffΔ\x00\x00\xff\xffܤ\x01\x04\xff\xffΔ\x00\b\xff\xff\xdc\xd8\x01\x04\xff\xff\xce\xc8\x00\b\xff\xff\xdc\xd8\x01\f\xff\xff\xdc\xd8\x01\x10\xff" + - "\xff\xea\xe8\x01\x14LMT\x00NDT\x00NST\x00NPT\x00NWT\x00NDDT\x00\nNST3:30NDT,M3.2.0,M11.1.0\nPK\x03" + - "\x04\n\x00\x00\x00\x00\x00\xf1c9RJtZ\x8c\x01\x03\x00\x00\x01\x03\x00\x00\x13\x00\x1c\x00America/PangnirtungUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`u" + - "x\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00" + - "\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\n\x00\x00\x00)\xff\xff\xff\xff\xa3\xd5R\x80\xff\xff\xff" + - "\xffˈ\xe2`\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\xff\xff\xff\xff\xf7/0@\xff\xff\xff\xff\xf8([\xc0\x00\x00\x00\x00\x13i9\xe0\x00\x00\x00\x00\x14Y\x1c\xd0\x00\x00\x00\x00\x15I\x1b" + - "\xe0\x00\x00\x00\x00\x168\xfe\xd0\x00\x00\x00\x00\x17(\xfd\xe0\x00\x00\x00\x00\x18\"\x1bP\x00\x00\x00\x00\x19\b\xdf\xe0\x00\x00\x00\x00\x1a\x01\xfdP\x00\x00\x00\x00\x1a\xf1\xfc`\x00\x00\x00\x00\x1b\xe1\xdfP\x00\x00\x00" + - "\x00\x1c\xd1\xde`\x00\x00\x00\x00\x1d\xc1\xc1P\x00\x00\x00\x00\x1e\xb1\xc0`\x00\x00\x00\x00\x1f\xa1\xa3P\x00\x00\x00\x00 u\xf2\xe0\x00\x00\x00\x00!\x81\x85P\x00\x00\x00\x00\"U\xd4\xe0\x00\x00\x00\x00#j\xa1" + - "\xd0\x00\x00\x00\x00$5\xb6\xe0\x00\x00\x00\x00%J\x83\xd0\x00\x00\x00\x00&\x15\x98\xe0\x00\x00\x00\x00'*e\xd0\x00\x00\x00\x00'\xfe\xb5`\x00\x00\x00\x00)\nG\xd0\x00\x00\x00\x00)ޗ`\x00\x00\x00" + - "\x00*\xea)\xd0\x00\x00\x00\x00+\xbey`\x00\x00\x00\x00,\xd3FP\x00\x00\x00\x00-\x9e[`\x00\x00\x00\x00.\xb3(P\x00\x00\x00\x00/~=`\x00\x00\x00\x000\x93\x18`\x00\x00\x00\x001gg" + - "\xf0\x00\x00\x00\x002r\xfa`\x00\x00\x00\x003GI\xf0\x00\x00\x00\x004R\xdc`\x00\x00\x00\x005'+\xf0\x00\x00\x00\x0062\xbe`\x00\x00\x00\x007\a\r\xf0\x00\x00\x00\x008\x1b\xda\xe0\x00\x00\x00" + - "\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xca\xf0\x00\x00\x00\x00:\xc6\xd1\xf0\x00\x00\x00\x00;۞\xe0\x00\x00\x00\x00<\xaf\xeep\x00\x00\x00\x00=\xbb\x80\xe0\x00\x00\x00\x00>\x8f\xd0p\x00\x00\x00\x00?\x9bb" + - "\xe0\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x03\x01\x02" + - "\x03\x04\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x06\a\x06\a\x06\a\x06\a\x06\b\t\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\x00\x00" + - "\x00\x00\x00\x00\xff\xff\xd5\xd0\x01\x04\xff\xff\xd5\xd0\x01\b\xff\xff\xc7\xc0\x00\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x01\x15\xff\xff\xc7\xc0\x01\x19\xff\xff\xb9\xb0\x00\x1d\xff\xff\xab\xa0\x00!\xff\xff\xb9\xb0\x01%-0" + - "0\x00AWT\x00APT\x00AST\x00ADDT\x00ADT\x00EDT\x00EST\x00CST\x00CDT\x00\nEST5EDT,M3.2.0,M11.1" + - ".0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RU\xactA\xb5\x01\x00\x00\xb5\x01\x00\x00\x11\x00\x1c\x00America/MatamorosUT\t\x00\x03\x15\xac\x0e`\x15" + - "\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00" + - "\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\xa5\xb6\xda" + - "`\x00\x00\x00\x00\"U\xf1\x00\x00\x00\x00\x00#j\xbd\xf0\x00\x00\x00\x001gv\x00\x00\x00\x00\x002s\bp\x00\x00\x00\x003GX\x00\x00\x00\x00\x004R\xeap\x00\x00\x00\x005':\x00\x00\x00\x00" + - "\x0062\xccp\x00\x00\x00\x007\a\x1c\x00\x00\x00\x00\x008\x1b\xe8\xf0\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xca\xf0\x00\x00\x00\x00:\xf5\x04\x80\x00\x00\x00\x00;\xb6\xc2\xf0\x00\x00\x00\x00<\xaf\xfc" + - "\x80\x00\x00\x00\x00=\xbb\x8e\xf0\x00\x00\x00\x00>\x8fހ\x00\x00\x00\x00?\x9bp\xf0\x00\x00\x00\x00@o\xc0\x80\x00\x00\x00\x00A\x84\x8dp\x00\x00\x00\x00BO\xa2\x80\x00\x00\x00\x00Cdop\x00\x00\x00" + - "\x00D/\x84\x80\x00\x00\x00\x00EDQp\x00\x00\x00\x00F\x0ff\x80\x00\x00\x00\x00G$3p\x00\x00\x00\x00G\xf8\x83\x00\x00\x00\x00\x00I\x04\x15p\x00\x00\x00\x00I\xd8e\x00\x00\x00\x00\x00J\xe3\xf7" + - "p\x00\x00\x00\x00K\x9c\x97\x80\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xff\xa2@\x00\x00\xff\xff\xab\xa0\x00\x04\xff\xff\xb9\xb0\x01\bL" + - "MT\x00CST\x00CDT\x00\nCST6CDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rs\xb0\xeau\xb4\x01\x00\x00\xb4\x01\x00" + - "\x00\x10\x00\x1c\x00America/EirunepeUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xba\x9e\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x01\f\xff\xff\xc7\xc0\x01\x10LMT\x00EDT\x00EST\x00E" + + "WT\x00EPT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSl=\xad\xbe\x16\x01\x00\x00\x16\x01\x00\x00\x10\x00\x1c" + + "\x00America/BarbadosUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xff\x92@\xa9e\xff\xff\xff\xff\xcb\xe3\xcb\xd0\xff\xff\xff\xff̔\x82\xe0\xff\xff\xff\xff\xcd\xd6\"\xd0\xff\xff\xff\xff\xce|M\xe0" + + "\xff\xff\xff\xffϛ\xa6\xd0\xff\xff\xff\xff\xd0ej`\x00\x00\x00\x00\x0e\x00\xf2\xe0\x00\x00\x00\x00\x0e\x94\x8c\xd0\x00\x00\x00\x00\x0f\x97\x00\xe0\x00\x00\x00\x00\x10tn\xd0\x00\x00\x00\x00\x11v\xe2\xe0\x00\x00\x00\x00" + + "\x12TP\xd0\x00\x00\x00\x00\x13_\xff`\x00\x00\x00\x00\x140>P\x02\x01\x02\x01\x02\x03\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xff\xc8\x1b\x00\x00\xff\xff\xd5\xd0\x01\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xce\xc8\x01\fL" + + "MT\x00ADT\x00AST\x00-0330\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x13\x00\x1c\x00America" + + "/Puerto_RicoUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffz敹\xff\xff\xff\xff\xcb\xf62\xc0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\x01\x03\x02\x01\xff\xff\xc2\a\x00\x00\xff\xff\xc7" + + "\xc0\x00\x04\xff\xff\xd5\xd0\x01\b\xff\xff\xd5\xd0\x01\fLMT\x00AST\x00APT\x00AWT\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1" + + "\x00\x00\x00\x10\x00\x1c\x00America/AnguillaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffz敹\xff\xff\xff\xff\xcb\xf62\xc0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\x01\x03" + + "\x02\x01\xff\xff\xc2\a\x00\x00\xff\xff\xc7\xc0\x00\x04\xff\xff\xd5\xd0\x01\b\xff\xff\xd5\xd0\x01\fLMT\x00AST\x00APT\x00AWT\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82" + + "iS,\xdb~\xab\xb2\x03\x00\x00\xb2\x03\x00\x00\x0f\x00\x1c\x00America/YakutatUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01" + + "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00S\x00\x00\x00\b\x00\x00\x00\x1e\xff\xff\xff\xff?\xc2\xfd\xd1\xff\xff\xff\xff}\x877\xbf\xff\xff\xff\xffˉ(\xb0" + + "\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a4 \xff\xff\xff\xff\xfe\xb8U0\xff\xff\xff\xff\xff\xa88 \x00\x00\x00\x00\x00\x9870\x00\x00\x00\x00\x01\x88\x1a \x00\x00\x00\x00\x02x\x190\x00\x00\x00\x00" + + "\x03q6\xa0\x00\x00\x00\x00\x04a5\xb0\x00\x00\x00\x00\x05Q\x18\xa0\x00\x00\x00\x00\x06A\x17\xb0\x00\x00\x00\x00\a0\xfa\xa0\x00\x00\x00\x00\a\x8dQ\xb0\x00\x00\x00\x00\t\x10ܠ\x00\x00\x00\x00\t\xad\xcd0" + + "\x00\x00\x00\x00\n\xf0\xbe\xa0\x00\x00\x00\x00\v\u0f70\x00\x00\x00\x00\f\xd9\xdb \x00\x00\x00\x00\r\xc0\x9f\xb0\x00\x00\x00\x00\x0e\xb9\xbd \x00\x00\x00\x00\x0f\xa9\xbc0\x00\x00\x00\x00\x10\x99\x9f \x00\x00\x00\x00" + + "\x11\x89\x9e0\x00\x00\x00\x00\x12y\x81 \x00\x00\x00\x00\x13i\x800\x00\x00\x00\x00\x14Yc \x00\x00\x00\x00\x15Ib0\x00\x00\x00\x00\x169E \x00\x00\x00\x00\x17)D0\x00\x00\x00\x00\x18\"a\xa0" + + "\x00\x00\x00\x00\x19\t&0\x00\x00\x00\x00\x1a\x02C\xa0\x00\x00\x00\x00\x1a+\x14\x10\x00\x00\x00\x00\x1a\xf2B\xb0\x00\x00\x00\x00\x1b\xe2%\xa0\x00\x00\x00\x00\x1c\xd2$\xb0\x00\x00\x00\x00\x1d\xc2\a\xa0\x00\x00\x00\x00" + + "\x1e\xb2\x06\xb0\x00\x00\x00\x00\x1f\xa1\xe9\xa0\x00\x00\x00\x00 v90\x00\x00\x00\x00!\x81ˠ\x00\x00\x00\x00\"V\x1b0\x00\x00\x00\x00#j\xe8 \x00\x00\x00\x00$5\xfd0\x00\x00\x00\x00%J\xca " + + "\x00\x00\x00\x00&\x15\xdf0\x00\x00\x00\x00'*\xac \x00\x00\x00\x00'\xfe\xfb\xb0\x00\x00\x00\x00)\n\x8e \x00\x00\x00\x00)\xdeݰ\x00\x00\x00\x00*\xeap \x00\x00\x00\x00+\xbe\xbf\xb0\x00\x00\x00\x00" + + ",ӌ\xa0\x00\x00\x00\x00-\x9e\xa1\xb0\x00\x00\x00\x00.\xb3n\xa0\x00\x00\x00\x00/~\x83\xb0\x00\x00\x00\x000\x93P\xa0\x00\x00\x00\x001g\xa00\x00\x00\x00\x002s2\xa0\x00\x00\x00\x003G\x820" + + "\x00\x00\x00\x004S\x14\xa0\x00\x00\x00\x005'd0\x00\x00\x00\x0062\xf6\xa0\x00\x00\x00\x007\aF0\x00\x00\x00\x008\x1c\x13 \x00\x00\x00\x008\xe7(0\x00\x00\x00\x009\xfb\xf5 \x00\x00\x00\x00" + + ":\xc7\n0\x00\x00\x00\x00;\xdb\xd7 \x00\x00\x00\x00<\xb0&\xb0\x00\x00\x00\x00=\xbb\xb9 \x00\x00\x00\x00>\x90\b\xb0\x00\x00\x00\x00?\x9b\x9b \x00\x00\x00\x00@o\xea\xb0\x00\x00\x00\x00A\x84\xb7\xa0" + + "\x00\x00\x00\x00BO̰\x00\x00\x00\x00Cd\x99\xa0\x00\x00\x00\x00D/\xae\xb0\x00\x00\x00\x00ED{\xa0\x00\x00\x00\x00E\xf3\xe10\x01\x02\x03\x04\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05" + + "\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a" + + "\x06\a\x06\x00\x00\u0381\x00\x00\xff\xff}\x01\x00\x00\xff\xff\x81p\x00\x04\xff\xff\x8f\x80\x01\b\xff\xff\x8f\x80\x01\f\xff\xff\x8f\x80\x01\x10\xff\xff\x8f\x80\x01\x14\xff\xff\x81p\x00\x19LMT\x00YST\x00Y" + + "WT\x00YPT\x00YDT\x00AKDT\x00AKST\x00\nAKST9AKDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82i" + + "SV\x80\x94@\x12\x04\x00\x00\x12\x04\x00\x00\x10\x00\x1c\x00America/ShiprockUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01" + + "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00a\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff^\x04\f\xb0\xff\xff\xff\xff\x9e\xa6:\x90\xff\xff\xff\xff\x9f\xbb\a\x80" + + "\xff\xff\xff\xff\xa0\x86\x1c\x90\xff\xff\xff\xff\xa1\x9a\xe9\x80\xff\xff\xff\xff\xa2e\xfe\x90\xff\xff\xff\xff\xa3\x84\x06\x00\xff\xff\xff\xff\xa4E\xe0\x90\xff\xff\xff\xff\xa4\x8f\xa6\x80\xff\xff\xff\xffˉ\f\x90\xff\xff\xff\xff" + + "\xd2#\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff\xf7/v\x90\xff\xff\xff\xff\xf8(\x94\x00\xff\xff\xff\xff\xf9\x0fX\x90\xff\xff\xff\xff\xfa\bv\x00\xff\xff\xff\xff\xfa\xf8u\x10\xff\xff\xff\xff\xfb\xe8X\x00" + + "\xff\xff\xff\xff\xfc\xd8W\x10\xff\xff\xff\xff\xfd\xc8:\x00\xff\xff\xff\xff\xfe\xb89\x10\xff\xff\xff\xff\xff\xa8\x1c\x00\x00\x00\x00\x00\x00\x98\x1b\x10\x00\x00\x00\x00\x01\x87\xfe\x00\x00\x00\x00\x00\x02w\xfd\x10\x00\x00\x00\x00" + + "\x03q\x1a\x80\x00\x00\x00\x00\x04a\x19\x90\x00\x00\x00\x00\x05P\xfc\x80\x00\x00\x00\x00\x06@\xfb\x90\x00\x00\x00\x00\a0ހ\x00\x00\x00\x00\a\x8d5\x90\x00\x00\x00\x00\t\x10\xc0\x80\x00\x00\x00\x00\t\xad\xb1\x10" + + "\x00\x00\x00\x00\n\xf0\xa2\x80\x00\x00\x00\x00\vࡐ\x00\x00\x00\x00\fٿ\x00\x00\x00\x00\x00\r\xc0\x83\x90\x00\x00\x00\x00\x0e\xb9\xa1\x00\x00\x00\x00\x00\x0f\xa9\xa0\x10\x00\x00\x00\x00\x10\x99\x83\x00\x00\x00\x00\x00" + + "\x11\x89\x82\x10\x00\x00\x00\x00\x12ye\x00\x00\x00\x00\x00\x13id\x10\x00\x00\x00\x00\x14YG\x00\x00\x00\x00\x00\x15IF\x10\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17)(\x10\x00\x00\x00\x00\x18\"E\x80" + + "\x00\x00\x00\x00\x19\t\n\x10\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2&\x90\x00\x00\x00\x00\x1b\xe2\t\x80\x00\x00\x00\x00\x1c\xd2\b\x90\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1\xea\x90\x00\x00\x00\x00" + + "\x1f\xa1̀\x00\x00\x00\x00 v\x1d\x10\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xff\x10\x00\x00\x00\x00#j\xcc\x00\x00\x00\x00\x00$5\xe1\x10\x00\x00\x00\x00%J\xae\x00\x00\x00\x00\x00&\x15\xc3\x10" + + "\x00\x00\x00\x00'*\x90\x00\x00\x00\x00\x00'\xfeߐ\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\xde\xc1\x90\x00\x00\x00\x00*\xeaT\x00\x00\x00\x00\x00+\xbe\xa3\x90\x00\x00\x00\x00,\xd3p\x80\x00\x00\x00\x00" + + "-\x9e\x85\x90\x00\x00\x00\x00.\xb3R\x80\x00\x00\x00\x00/~g\x90\x00\x00\x00\x000\x934\x80\x00\x00\x00\x001g\x84\x10\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003Gf\x10\x00\x00\x00\x004R\xf8\x80" + + "\x00\x00\x00\x005'H\x10\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe7\f\x10\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xc6\xee\x10\x00\x00\x00\x00" + + ";ۻ\x00\x00\x00\x00\x00<\xb0\n\x90\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8f\xec\x90\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@oΐ\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00BO\xb0\x90" + + "\x00\x00\x00\x00Cd}\x80\x00\x00\x00\x00D/\x92\x90\x00\x00\x00\x00ED_\x80\x00\x00\x00\x00E\xf3\xc5\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\x9d\x94\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\f\xff\xff\xab\xa0\x01\x10LMT\x00MDT\x00MST\x00MWT\x00MPT\x00\n" + + "MST7MDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00\x1c\x00America" + + "/Argentina/UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSR\xc8\xd9\xf6\xc4\x02\x00" + + "\x00\xc4\x02\x00\x00\x1b\x00\x1c\x00America/Argentina/CatamarcaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04" + + "S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xaf,\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6" + + "{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff" + + "\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4" + + "\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff" + + "\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf6" + + "2\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff" + + "\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%" + + "7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'!\x0f0\x00\x00\x00\x00'\xd0X\xa0\x00\x00\x00\x00)\x00\xff@\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x99W \x00" + + "\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00@\xbb\xf10\x00\x00\x00\x00@\xd5\v\xc0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x02\x04\x05\x04\x05\x03\x05\x02\x05\x04\x05\xff\xff\xc2T\x00\x00\xff\xff\xc3\xd0\x00\x04" + + "\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00" + + "\x00\x00#\x82iSR\xc8\xd9\xf6\xc4\x02\x00\x00\xc4\x02\x00\x00 \x00\x1c\x00America/Argentina/ComodRivadaviaUT\t\x00\x03\x82" + + "\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff" + + "\xffr\x9c\xaf,\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3" + + "\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff" + + "\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94" + + "@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff" + + "\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36" + + "\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00" + + "\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'!\x0f0\x00\x00\x00\x00'\xd0X\xa0\x00\x00\x00\x00)\x00\xff@\x00\x00\x00\x00)\xb0:" + + "\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00@\xbb\xf10\x00\x00\x00\x00@\xd5\v\xc0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00" + + "\x00G\xdc\u007f \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x02\x04\x05\x04\x05" + + "\x03\x05\x02\x05\x04\x05\xff\xff\xc2T\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-0" + + "2\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSŒZ\x8c\xc4\x02\x00\x00\xc4\x02\x00\x00\x19\x00\x1c\x00America/Argentina/Me" + + "ndozaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=" + + "\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xb2\x04\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff" + + "\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0" + + "\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff" + + "\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0" + + "\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff" + + "\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0" + + "\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'\x194@\x00\x00\x00\x00'\xcdð\x00\x00\x00\x00" + + "(\xfag\xc0\x00\x00\x00\x00)\xb0H\xb0\x00\x00\x00\x00*\xe0\xe1@\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00@\xb0\x13\xb0\x00\x00\x00\x00AV>\xc0" + + "\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04" + + "\x05\x04\x05\x04\x02\x03\x02\x03\x02\x04\x05\x03\x05\x02\x05\x04\x05\xff\xff\xbf|\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT" + + "\x00-04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x8b}\xb6\x1e\xc4\x02\x00\x00\xc4\x02\x00\x00\x19\x00\x1c\x00America/A" + + "rgentina/UshuaiaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xb1\x88\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff" + + "\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf" + + "\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff" + + "\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3" + + ")5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff" + + "\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff" + + "\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'!\x0f0\x00" + + "\x00\x00\x00'\xd0X\xa0\x00\x00\x00\x00)\x00\xf10\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00@" + + "\xb9N0\x00\x00\x00\x00@\xd5\v\xc0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x03\x05\x02\x05\x04\x05\xff\xff\xbf\xf8\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff" + + "\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSm\aD\x0e\xcd\x02\x00\x00\xcd\x02\x00\x00\x1a\x00" + + "\x1c\x00America/Argentina/La_RiojaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif" + + "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xb0,\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7" + + "\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff" + + "\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5" + + "`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff" + + "\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6" + + "柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff" + + "\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%" + + "\xf0v\xa0\x00\x00\x00\x00'!\x0f0\x00\x00\x00\x00'͵\xa0\x00\x00\x00\x00(&&@\x00\x00\x00\x00)\x00\xf10\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x99W \x00" + + "\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00@\xbb\xf10\x00\x00\x00\x00@\xd5\v\xc0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x02\x05\x04\x05\x04\x05\x03\x05\x02\x05\x04\x05\xff\xff\xc1T\x00\x00\xff\xff\xc3\xd0\x00" + + "\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00" + + "\x00\x00\x00#\x82iSutZ\x1a\xb2\x02\x00\x00\xb2\x02\x00\x00\x17\x00\x1c\x00America/Argentina/JujuyUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8bau" + + "x\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00" + + "\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00;\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xae\xb8\xff\xff\xff" + + "\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1" + + "@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff" + + "\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1" + + "\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff" + + "\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35" + + "\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00" + + "\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'*W\xc0\x00\x00\x00\x00'\xe2۰\x00\x00\x00\x00(\xee\x8a@\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd3" + + "0\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x02\x03\x02\x04\x05\x04\x05\x03\x05\x04\x05\xff\xff\xc2\xc8\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff" + + "\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x1c\x80" + + "\xb9\\\xcd\x02\x00\x00\xcd\x02\x00\x00\x1a\x00\x1c\x00America/Argentina/San_LuisUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14" + + "E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00T" + + "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xaf\xb4\xff\xff\xff\xff\xa2\x92\x8f0\xff" + + "\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc" + + "\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff" + + "\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca" + + "\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff" + + "\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc" + + "\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00" + + "\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xfd\xa5\xa0\x00\x00\x00\x00'\x194@\x00\x00\x00\x00'\xcdð\x00\x00\x00\x00(G\x1b\xc0\x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00@" + + "\xba\x9f\xb0\x00\x00\x00\x00A\x030@\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\x93\xfc\xa0\x00\x00\x00\x00G\xd3R\xb0\x00\x00\x00\x00H\xf1v@\x00\x00\x00\x00I\xb34\xb0\x00\x00\x00\x00J\xd1X@\x01" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x02\x03\x02\x05\x03\x05\x02\x05\x04\x03\x02\x03\x02" + + "\x05\xff\xff\xc1\xcc\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02\x00\n<-" + + "03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xe0\xbf\xf5\xe5\xc4\x02\x00\x00\xc4\x02\x00\x00\x1e\x00\x1c\x00America/Argentina/Buenos_" + + "AiresUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=" + + "\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xa8L\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff" + + "\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0" + + "\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff" + + "\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0" + + "\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff" + + "\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0" + + "\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'!\x0f0\x00\x00\x00\x00'\xd0X\xa0\x00\x00\x00\x00" + + ")\x00\xf10\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f " + + "\x00\x00\x00\x00H\xfa\xa2\xb0\x00\x00\x00\x00I\xbca \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04" + + "\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x03\x05\x04\x05\x04\x05\xff\xff\xc94\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT" + + "\x00-04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x8ep\xb4c\xc4\x02\x00\x00\xc4\x02\x00\x00\x1e\x00\x1c\x00America/A" + + "rgentina/Rio_GallegosUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!\x00\x00\x00\x04\x00\x00\x00\f\xff\xff\xff\xff\x96\xaa\x88\x80\xff\xff\xff\xff\xb8\x0ff\x00\xff\xff\xff\xff\xb8\xfd\\\xc0\xff\xff\xff\xff\xb9\xf1PP\xff\xff\xff\xff" + - "\xbaސ@\xff\xff\xff\xff\xda8\xcaP\xff\xff\xff\xff\xda\xec\x16P\xff\xff\xff\xff\xdc\x19\xfd\xd0\xff\xff\xff\xffܹu@\xff\xff\xff\xff\xdd\xfb1P\xff\xff\xff\xffޛ\xfa@\xff\xff\xff\xff\xdfݶP" + - "\xff\xff\xff\xff\xe0TO@\xff\xff\xff\xff\xf4\x98\x1b\xd0\xff\xff\xff\xff\xf5\x05z@\xff\xff\xff\xff\xf6\xc0\x80P\xff\xff\xff\xff\xf7\x0e:\xc0\xff\xff\xff\xff\xf8QHP\xff\xff\xff\xff\xf8\xc7\xe1@\xff\xff\xff\xff" + - "\xfa\n\xee\xd0\xff\xff\xff\xff\xfa\xa9\x14\xc0\xff\xff\xff\xff\xfb\xec\"P\xff\xff\xff\xff\xfc\x8b\x99\xc0\x00\x00\x00\x00\x1dɪP\x00\x00\x00\x00\x1ex\xf3\xc0\x00\x00\x00\x00\x1f\xa0Q\xd0\x00\x00\x00\x00 3\xeb\xc0" + - "\x00\x00\x00\x00!\x81\x85P\x00\x00\x00\x00\"\v\xe4\xc0\x00\x00\x00\x00,\xc0\xd1P\x00\x00\x00\x00-f\xe0@\x00\x00\x00\x00H`\u007fP\x00\x00\x00\x00R\u007f\x04\xc0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x02\xff\xff\xbe\x80\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x00\x04LMT\x00-04\x00-05\x00\n<-" + - "05>5\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RV\x80\x94@\x12\x04\x00\x00\x12\x04\x00\x00\x10\x00\x1c\x00America/ShiprockUT\t\x00\x03\x15\xac\x0e`" + - "\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00" + - "\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00a\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff^\x04" + - "\f\xb0\xff\xff\xff\xff\x9e\xa6:\x90\xff\xff\xff\xff\x9f\xbb\a\x80\xff\xff\xff\xff\xa0\x86\x1c\x90\xff\xff\xff\xff\xa1\x9a\xe9\x80\xff\xff\xff\xff\xa2e\xfe\x90\xff\xff\xff\xff\xa3\x84\x06\x00\xff\xff\xff\xff\xa4E\xe0\x90\xff\xff" + - "\xff\xff\xa4\x8f\xa6\x80\xff\xff\xff\xffˉ\f\x90\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff\xf7/v\x90\xff\xff\xff\xff\xf8(\x94\x00\xff\xff\xff\xff\xf9\x0fX\x90\xff\xff\xff\xff\xfa\b" + - "v\x00\xff\xff\xff\xff\xfa\xf8u\x10\xff\xff\xff\xff\xfb\xe8X\x00\xff\xff\xff\xff\xfc\xd8W\x10\xff\xff\xff\xff\xfd\xc8:\x00\xff\xff\xff\xff\xfe\xb89\x10\xff\xff\xff\xff\xff\xa8\x1c\x00\x00\x00\x00\x00\x00\x98\x1b\x10\x00\x00" + - "\x00\x00\x01\x87\xfe\x00\x00\x00\x00\x00\x02w\xfd\x10\x00\x00\x00\x00\x03q\x1a\x80\x00\x00\x00\x00\x04a\x19\x90\x00\x00\x00\x00\x05P\xfc\x80\x00\x00\x00\x00\x06@\xfb\x90\x00\x00\x00\x00\a0ހ\x00\x00\x00\x00\a\x8d" + - "5\x90\x00\x00\x00\x00\t\x10\xc0\x80\x00\x00\x00\x00\t\xad\xb1\x10\x00\x00\x00\x00\n\xf0\xa2\x80\x00\x00\x00\x00\vࡐ\x00\x00\x00\x00\fٿ\x00\x00\x00\x00\x00\r\xc0\x83\x90\x00\x00\x00\x00\x0e\xb9\xa1\x00\x00\x00" + - "\x00\x00\x0f\xa9\xa0\x10\x00\x00\x00\x00\x10\x99\x83\x00\x00\x00\x00\x00\x11\x89\x82\x10\x00\x00\x00\x00\x12ye\x00\x00\x00\x00\x00\x13id\x10\x00\x00\x00\x00\x14YG\x00\x00\x00\x00\x00\x15IF\x10\x00\x00\x00\x00\x169" + - ")\x00\x00\x00\x00\x00\x17)(\x10\x00\x00\x00\x00\x18\"E\x80\x00\x00\x00\x00\x19\t\n\x10\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2&\x90\x00\x00\x00\x00\x1b\xe2\t\x80\x00\x00\x00\x00\x1c\xd2\b\x90\x00\x00" + - "\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1\xea\x90\x00\x00\x00\x00\x1f\xa1̀\x00\x00\x00\x00 v\x1d\x10\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xff\x10\x00\x00\x00\x00#j\xcc\x00\x00\x00\x00\x00$5" + - "\xe1\x10\x00\x00\x00\x00%J\xae\x00\x00\x00\x00\x00&\x15\xc3\x10\x00\x00\x00\x00'*\x90\x00\x00\x00\x00\x00'\xfeߐ\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\xde\xc1\x90\x00\x00\x00\x00*\xeaT\x00\x00\x00" + - "\x00\x00+\xbe\xa3\x90\x00\x00\x00\x00,\xd3p\x80\x00\x00\x00\x00-\x9e\x85\x90\x00\x00\x00\x00.\xb3R\x80\x00\x00\x00\x00/~g\x90\x00\x00\x00\x000\x934\x80\x00\x00\x00\x001g\x84\x10\x00\x00\x00\x002s" + - "\x16\x80\x00\x00\x00\x003Gf\x10\x00\x00\x00\x004R\xf8\x80\x00\x00\x00\x005'H\x10\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe7\f\x10\x00\x00" + - "\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xc6\xee\x10\x00\x00\x00\x00;ۻ\x00\x00\x00\x00\x00<\xb0\n\x90\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8f\xec\x90\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@o" + - "ΐ\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00BO\xb0\x90\x00\x00\x00\x00Cd}\x80\x00\x00\x00\x00D/\x92\x90\x00\x00\x00\x00ED_\x80\x00\x00\x00\x00E\xf3\xc5\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03" + - "\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\x9d\x94\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\f\xff\xff\xab\xa0\x01\x10LMT" + - "\x00MDT\x00MST\x00MWT\x00MPT\x00\nMST7MDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xe90T\x16\xd1" + - "\x01\x00\x00\xd1\x01\x00\x00\x0f\x00\x1c\x00America/GodthabUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif3\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\"\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x9b\x80h\x00\x00\x00\x00\x00\x13M|P\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb" + - "\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00" + - "\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#3<-02>,M3.5.0/-2,M10.5.0/-1\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RU\r\xf7\xd3\xc7\x01\x00" + - "\x00\xc7\x01\x00\x00\r\x00\x1c\x00America/ThuleUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\"\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x9b\x80w\xfc\x00\x00\x00\x00'\xf5z\xe0\x00\x00\x00\x00(\xe5]\xd0\x00\x00\x00\x00)\xd5\\\xe0\x00\x00\x00" + - "\x00*\xc5?\xd0\x00\x00\x00\x00+\xbey`\x00\x00\x00\x00,\xd3FP\x00\x00\x00\x00-\x9e[`\x00\x00\x00\x00.\xb3(P\x00\x00\x00\x00/~=`\x00\x00\x00\x000\x93\nP\x00\x00\x00\x001gY" + - "\xe0\x00\x00\x00\x002r\xecP\x00\x00\x00\x003G;\xe0\x00\x00\x00\x004R\xceP\x00\x00\x00\x005'\x1d\xe0\x00\x00\x00\x0062\xb0P\x00\x00\x00\x007\x06\xff\xe0\x00\x00\x00\x008\x1b\xcc\xd0\x00\x00\x00" + - "\x008\xe6\xe1\xe0\x00\x00\x00\x009\xfb\xae\xd0\x00\x00\x00\x00:\xc6\xc3\xe0\x00\x00\x00\x00;ې\xd0\x00\x00\x00\x00<\xaf\xe0`\x00\x00\x00\x00=\xbbr\xd0\x00\x00\x00\x00>\x8f\xc2`\x00\x00\x00\x00?\x9bT" + - "\xd0\x00\x00\x00\x00@o\xa4`\x00\x00\x00\x00A\x84qP\x00\x00\x00\x00BO\x86`\x00\x00\x00\x00CdSP\x00\x00\x00\x00D/h`\x00\x00\x00\x00ED5P\x00\x00\x00\x00E\xf3\x9a\xe0\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xbf\x84\x00\x00\xff\xff\xd5\xd0\x01\x04\xff\xff\xc7\xc0\x00\bLMT\x00ADT\x00AST" + - "\x00\nAST4ADT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xe5s\xb3\\'\x01\x00\x00'\x01\x00\x00\x0f\x00\x1c\x00Ameri" + - "ca/ManaguaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x10\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xffi\x87,d\xff\xff\xff\xff\xbd-H\xe8\x00\x00\x00\x00\x06Ct`\x00\x00\x00\x00\t\xa4>P\x00\x00\x00\x00\x11Q\xf8\xe0\x00\x00\x00\x00\x11\xd4o" + - "P\x00\x00\x00\x00\x131\xda\xe0\x00\x00\x00\x00\x13\xb4QP\x00\x00\x00\x00)a\x91 \x00\x00\x00\x00*\xc1KP\x00\x00\x00\x00+C\xdd\xe0\x00\x00\x00\x002\xc9\xefP\x00\x00\x00\x00BX\xc0\xe0\x00\x00\x00" + - "\x00C?iP\x00\x00\x00\x00DTn\x80\x00\x00\x00\x00E\x1fY`\x01\x02\x03\x02\x04\x02\x04\x02\x03\x02\x03\x02\x04\x02\x04\x02\xff\xff\xaf\x1c\x00\x00\xff\xff\xaf\x18\x00\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x00" + - "\f\xff\xff\xb9\xb0\x01\x10LMT\x00MMT\x00CST\x00EST\x00CDT\x00\nCST6\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RM\x94\xc7Kp\x03\x00\x00p\x03\x00\x00\x11" + - "\x00\x1c\x00America/Glace_BayUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00O\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\x80\xf1\xa84\xff\xff\xff\xff\x9e\xb8\x85`\xff\xff\xff\xff\x9f\xba\xddP\xff\xff\xff\xffˈ\xe2`\xff\xff\xff\xff\xd2" + - "#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\xff\xff\xff\xff\xe0\x9e?`\xff\xff\xff\xff\xe1i8P\x00\x00\x00\x00\x04`\xef`\x00\x00\x00\x00\x05P\xd2P\x00\x00\x00\x00\x06@\xd1`\x00\x00\x00\x00\a0\xb4P\x00" + - "\x00\x00\x00\b \xb3`\x00\x00\x00\x00\t\x10\x96P\x00\x00\x00\x00\n\x00\x95`\x00\x00\x00\x00\n\xf0xP\x00\x00\x00\x00\v\xe0w`\x00\x00\x00\x00\fٔ\xd0\x00\x00\x00\x00\r\xc0Y`\x00\x00\x00\x00\x0e" + - "\xb9v\xd0\x00\x00\x00\x00\x0f\xa9u\xe0\x00\x00\x00\x00\x10\x99X\xd0\x00\x00\x00\x00\x11\x89W\xe0\x00\x00\x00\x00\x12y:\xd0\x00\x00\x00\x00\x13i9\xe0\x00\x00\x00\x00\x14Y\x1c\xd0\x00\x00\x00\x00\x15I\x1b\xe0\x00" + - "\x00\x00\x00\x168\xfe\xd0\x00\x00\x00\x00\x17(\xfd\xe0\x00\x00\x00\x00\x18\"\x1bP\x00\x00\x00\x00\x19\b\xdf\xe0\x00\x00\x00\x00\x1a\x01\xfdP\x00\x00\x00\x00\x1a\xf1\xfc`\x00\x00\x00\x00\x1b\xe1\xdfP\x00\x00\x00\x00\x1c" + - "\xd1\xde`\x00\x00\x00\x00\x1d\xc1\xc1P\x00\x00\x00\x00\x1e\xb1\xc0`\x00\x00\x00\x00\x1f\xa1\xa3P\x00\x00\x00\x00 u\xf2\xe0\x00\x00\x00\x00!\x81\x85P\x00\x00\x00\x00\"U\xd4\xe0\x00\x00\x00\x00#j\xa1\xd0\x00" + - "\x00\x00\x00$5\xb6\xe0\x00\x00\x00\x00%J\x83\xd0\x00\x00\x00\x00&\x15\x98\xe0\x00\x00\x00\x00'*e\xd0\x00\x00\x00\x00'\xfe\xb5`\x00\x00\x00\x00)\nG\xd0\x00\x00\x00\x00)ޗ`\x00\x00\x00\x00*" + - "\xea)\xd0\x00\x00\x00\x00+\xbey`\x00\x00\x00\x00,\xd3FP\x00\x00\x00\x00-\x9e[`\x00\x00\x00\x00.\xb3(P\x00\x00\x00\x00/~=`\x00\x00\x00\x000\x93\nP\x00\x00\x00\x001gY\xe0\x00" + - "\x00\x00\x002r\xecP\x00\x00\x00\x003G;\xe0\x00\x00\x00\x004R\xceP\x00\x00\x00\x005'\x1d\xe0\x00\x00\x00\x0062\xb0P\x00\x00\x00\x007\x06\xff\xe0\x00\x00\x00\x008\x1b\xcc\xd0\x00\x00\x00\x008" + - "\xe6\xe1\xe0\x00\x00\x00\x009\xfb\xae\xd0\x00\x00\x00\x00:\xc6\xc3\xe0\x00\x00\x00\x00;ې\xd0\x00\x00\x00\x00<\xaf\xe0`\x00\x00\x00\x00=\xbbr\xd0\x00\x00\x00\x00>\x8f\xc2`\x00\x00\x00\x00?\x9bT\xd0\x00" + - "\x00\x00\x00@o\xa4`\x00\x00\x00\x00A\x84qP\x00\x00\x00\x00BO\x86`\x00\x00\x00\x00CdSP\x00\x00\x00\x00D/h`\x00\x00\x00\x00ED5P\x00\x00\x00\x00E\xf3\x9a\xe0\x02\x01\x02\x03\x04" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xc7\xcc\x00\x00\xff\xff\xd5\xd0\x01\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xd5\xd0\x01\x10LMT\x00ADT\x00AST\x00AWT\x00" + - "APT\x00\nAST4ADT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R⚵\xfb\x9e\x00\x00\x00\x9e\x00\x00\x00\x0f\x00\x1c\x00Am" + - "erica/CrestonUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff^=p\xbc\xff\xff\xff\xff\x9b\xd6Kp\xff\xff\xff\xff\x9e\xf9;\x00\x01\x02\x01\xff\xff\x92\xc4\x00\x00\xff\xff\x9d\x90\x00\x04\xff\xff\x8f\x80\x00" + - "\bLMT\x00MST\x00PST\x00\nMST7\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RB\xa0=:\x1e\x01\x00\x00\x1e\x01\x00\x00\x12\x00\x1c\x00America/Her" + - "mosilloUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x0f\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\xa5\xb6\xe8p\xff\xff\xff\xff\xaf\xf2n\xe0\xff\xff\xff\xff\xb6fV`\xff\xff\xff\xff\xb7C\xd2`\xff\xff\xff\xff\xb8\f6`\xff\xff\xff\xff\xb8\xfd\x86\xf0\xff\xff" + - "\xff\xff\xcb\xeaq`\xff\xff\xff\xffؑ\xb4\xf0\x00\x00\x00\x00\x00\x00p\x80\x00\x00\x00\x001g\x84\x10\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003Gf\x10\x00\x00\x00\x004R\xf8\x80\x00\x00\x00\x005'" + - "H\x10\x00\x00\x00\x0062ڀ\x01\x02\x01\x02\x01\x02\x01\x03\x01\x04\x01\x04\x01\x04\x01\xff\xff\x97\xf8\x00\x00\xff\xff\x9d\x90\x00\x04\xff\xff\xab\xa0\x00\b\xff\xff\x8f\x80\x00\f\xff\xff\xab\xa0\x01\x10LMT\x00M" + - "ST\x00CST\x00PST\x00MDT\x00\nMST7\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xd0v\x01\x8a\x01\x04\x00\x00\x01\x04\x00\x00\x14\x00\x1c\x00America/S" + - "anta_IsabelUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00^\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff\xa5\xb6\xf6\x80\xff\xff\xff\xff\xa9yOp\xff\xff\xff\xff\xaf\xf2|\xf0\xff\xff\xff\xff\xb6fdp\xff\xff\xff\xff\xb7\x1b\x10\x00\xff\xff\xff\xff\xb8\n" + - "\xf2\xf0\xff\xff\xff\xff\xcbꍀ\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xffҙ\xbap\xff\xff\xff\xff\xd7\x1bY\x00\xff\xff\xff\xffؑ\xb4\xf0\xff\xff\xff\xff\xe2~K\x90\xff\xff\xff\xff\xe3IR\x90\xff\xff" + - "\xff\xff\xe4^-\x90\xff\xff\xff\xff\xe5)4\x90\xff\xff\xff\xff\xe6GJ\x10\xff\xff\xff\xff\xe7\x12Q\x10\xff\xff\xff\xff\xe8',\x10\xff\xff\xff\xff\xe8\xf23\x10\xff\xff\xff\xff\xea\a\x0e\x10\xff\xff\xff\xff\xea\xd2" + - "\x15\x10\xff\xff\xff\xff\xeb\xe6\xf0\x10\xff\xff\xff\xff\xec\xb1\xf7\x10\xff\xff\xff\xff\xed\xc6\xd2\x10\xff\xff\xff\xff\xee\x91\xd9\x10\x00\x00\x00\x00\v\u0be0\x00\x00\x00\x00\f\xd9\xcd\x10\x00\x00\x00\x00\r\xc0\x91\xa0\x00\x00" + - "\x00\x00\x0e\xb9\xaf\x10\x00\x00\x00\x00\x0f\xa9\xae \x00\x00\x00\x00\x10\x99\x91\x10\x00\x00\x00\x00\x11\x89\x90 \x00\x00\x00\x00\x12ys\x10\x00\x00\x00\x00\x13ir \x00\x00\x00\x00\x14YU\x10\x00\x00\x00\x00\x15I" + - "T \x00\x00\x00\x00\x1697\x10\x00\x00\x00\x00\x17)6 \x00\x00\x00\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18 \x00\x00\x00\x00\x1a\x025\x90\x00\x00\x00\x00\x1a\xf24\xa0\x00\x00\x00\x00\x1b\xe2\x17\x90\x00\x00" + - "\x00\x00\x1c\xd2\x16\xa0\x00\x00\x00\x00\x1d\xc1\xf9\x90\x00\x00\x00\x00\x1e\xb1\xf8\xa0\x00\x00\x00\x00\x1f\xa1ې\x00\x00\x00\x00 v+ \x00\x00\x00\x00!\x81\xbd\x90\x00\x00\x00\x00\"V\r \x00\x00\x00\x00#j" + - "\xda\x10\x00\x00\x00\x00$5\xef \x00\x00\x00\x00%J\xbc\x10\x00\x00\x00\x00&\x15\xd1 \x00\x00\x00\x00'*\x9e\x10\x00\x00\x00\x00'\xfe\xed\xa0\x00\x00\x00\x00)\n\x80\x10\x00\x00\x00\x00)\xdeϠ\x00\x00" + - "\x00\x00*\xeab\x10\x00\x00\x00\x00+\xbe\xb1\xa0\x00\x00\x00\x00,\xd3~\x90\x00\x00\x00\x00-\x9e\x93\xa0\x00\x00\x00\x00.\xb3`\x90\x00\x00\x00\x00/~u\xa0\x00\x00\x00\x000\x93B\x90\x00\x00\x00\x001g" + - "\x92 \x00\x00\x00\x002s$\x90\x00\x00\x00\x003Gt \x00\x00\x00\x004S\x06\x90\x00\x00\x00\x005'V \x00\x00\x00\x0062\xe8\x90\x00\x00\x00\x007\a8 \x00\x00\x00\x008\x1c\x05\x10\x00\x00" + - "\x00\x008\xe7\x1a \x00\x00\x00\x009\xfb\xe7\x10\x00\x00\x00\x00:\xc6\xfc \x00\x00\x00\x00;\xdb\xc9\x10\x00\x00\x00\x00<\xb0\x18\xa0\x00\x00\x00\x00=\xbb\xab\x10\x00\x00\x00\x00>\x8f\xfa\xa0\x00\x00\x00\x00?\x9b" + - "\x8d\x10\x00\x00\x00\x00@oܠ\x00\x00\x00\x00A\x84\xa9\x90\x00\x00\x00\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b\x90\x00\x00\x00\x00D/\xa0\xa0\x00\x00\x00\x00EDm\x90\x00\x00\x00\x00F\x0f\x82\xa0\x00\x00" + - "\x00\x00G$O\x90\x00\x00\x00\x00G\xf8\x9f \x00\x00\x00\x00I\x041\x90\x00\x00\x00\x00I\u0601 \x00\x00\x00\x00J\xe4\x13\x90\x00\x00\x00\x00K\x9c\xb3\xa0\x01\x02\x01\x02\x03\x02\x04\x05\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\xff\xff\x92L\x00\x00\xff\xff\x9d\x90\x00\x04\xff\xff\x8f\x80\x00\b\xff\xff\x9d\x90\x01\f\xff\xff\x9d\x90\x01\x10\xff\xff\x9d\x90\x01\x14LMT\x00" + - "MST\x00PST\x00PDT\x00PWT\x00PPT\x00\nPST8PDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RP\x0f" + - "(\b=\x01\x00\x00=\x01\x00\x00\x15\x00\x1c\x00America/Santo_DomingoUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8" + - "\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\x06\x00\x00\x00\x1b\xff\xff\xff\xffi\x87\x1d\b\xff\xff\xff\xff\xba\xdfB`\xff\xff\xff\xff\xfa\b" + - "K\xd0\xff\xff\xff\xff\xfa\xa7\xc3@\xff\xff\xff\xff\xff\xa7\xf1\xd0\x00\x00\x00\x00\x00C{\xc8\x00\x00\x00\x00\x01\x87\xd3\xd0\x00\x00\x00\x00\x01\xfa\u007fH\x00\x00\x00\x00\x03p\xf0P\x00\x00\x00\x00\x03\xdd\x04H\x00\x00" + - "\x00\x00\x05P\xd2P\x00\x00\x00\x00\x05\xbf\x89H\x00\x00\x00\x00\a0\xb4P\x00\x00\x00\x00\a\xa0\xbc\xc8\x00\x00\x00\x00\t\x10\x96P\x00\x00\x00\x009\xfb\xbc\xe0\x00\x00\x00\x00:)\xe1`\x01\x03\x02\x03\x04\x03" + - "\x04\x03\x04\x03\x04\x03\x04\x03\x05\x03\x05\xff\xff\xbex\x00\x00\xff\xff\xbe`\x00\x04\xff\xff\xc7\xc0\x01\t\xff\xff\xb9\xb0\x00\r\xff\xff\xc0\xb8\x01\x11\xff\xff\xc7\xc0\x00\x17LMT\x00SDMT\x00EDT\x00" + - "EST\x00-0430\x00AST\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00\x00\x00\x12\x00\x1c\x00America/St" + - "_VincentUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x9373\xac\x01\xff\xff\xc6T\x00\x00\xff\xff\xc7\xc0\x00\x04LMT\x00AST\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R" + - "\xd6\xe1Հ\x9c\x01\x00\x00\x9c\x01\x00\x00\x13\x00\x1c\x00America/Mexico_CityUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8" + - "\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1b\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\xa5\xb6\xe8p\xff\xff\xff\xff\xaf\xf2n\xe0\xff\xff\xff\xff\xb6f" + - "V`\xff\xff\xff\xff\xb7C\xd2`\xff\xff\xff\xff\xb8\f6`\xff\xff\xff\xff\xb8\xfd\x86\xf0\xff\xff\xff\xff\xc5ް`\xff\xff\xff\xffƗ4P\xff\xff\xff\xff\xc9U\xf1\xe0\xff\xff\xff\xff\xc9\xea\xddP\xff\xff" + - "\xff\xff\xcf\x02\xc6\xe0\xff\xff\xff\xffϷVP\xff\xff\xff\xffڙ\x15\xe0\xff\xff\xff\xff\xdbv\x83\xd0\x00\x00\x00\x001gv\x00\x00\x00\x00\x002s\bp\x00\x00\x00\x003GX\x00\x00\x00\x00\x004R" + - "\xeap\x00\x00\x00\x005':\x00\x00\x00\x00\x0062\xccp\x00\x00\x00\x007\a\x1c\x00\x00\x00\x00\x008\x1b\xe8\xf0\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xca\xf0\x00\x00\x00\x00:\xf5\x04\x80\x00\x00" + - "\x00\x00;\xb6\xc2\xf0\x00\x00\x00\x00<\xaf\xfc\x80\x01\x02\x01\x02\x01\x02\x03\x02\x03\x02\x04\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\xff\xff\xa3\f\x00\x00\xff\xff\x9d\x90\x00\x04\xff\xff\xab\xa0\x00\b\xff" + - "\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10LMT\x00MST\x00CST\x00CDT\x00CWT\x00\nCST6CDT,M4.1.0,M10.5.0\nPK\x03\x04\n" + - "\x00\x00\x00\x00\x00\xf1c9R\x15\xc8\xcb\x00\xac\x00\x00\x00\xac\x00\x00\x00\x0e\x00\x1c\x00America/GuyanaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03" + - "\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + - "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xff\x98\xd9y\x88\x00\x00\x00\x00\n}\xb4<\x00\x00" + - "\x00\x00'\u007f\xfb0\x01\x02\x03\xff\xff\xc9x\x00\x00\xff\xff\xcbD\x00\x04\xff\xff\xd5\xd0\x00\n\xff\xff\xc7\xc0\x00\x0eLMT\x00-0345\x00-03\x00-04\x00\n<-04>4\nP" + - "K\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00\x00\x00\x15\x00\x1c\x00America/Port_of_SpainUT\t\x00\x03\x15\xac\x0e`\x15" + - "\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00" + - "\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x9373" + - "\xac\x01\xff\xff\xc6T\x00\x00\xff\xff\xc7\xc0\x00\x04LMT\x00AST\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R>\x14\xe7\x03\x83\x03\x00\x00\x83\x03\x00\x00\x0f\x00\x1c\x00Am" + - "erica/DetroitUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00P\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff\x85\xbd\"[\xff\xff\xff\xff\x99<\x94\x00\xff\xff\xff\xffˈ\xf0p\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xfb\xe0\xff\xff\xff\xff" + - "\xd75\xa8\xf0\xff\xff\xff\xff\xd8\x00\xa1\xe0\xff\xff\xff\xff\xfb3\x90\x8c\xff\xff\xff\xff\xfb\xe8;\xe0\xff\xff\xff\xff\xfc\xd8:\xf0\xff\xff\xff\xff\xfd\xc8\x1d\xe0\x00\x00\x00\x00\x06@\xdfp\x00\x00\x00\x00\a0\xc2`" + - "\x00\x00\x00\x00\a\x8d\x19p\x00\x00\x00\x00\t\x10\xa4`\x00\x00\x00\x00\n\x00\xa3p\x00\x00\x00\x00\n\xf0\x86`\x00\x00\x00\x00\v\xe0\x85p\x00\x00\x00\x00\f٢\xe0\x00\x00\x00\x00\r\xc0gp\x00\x00\x00\x00" + - "\x0e\xb9\x84\xe0\x00\x00\x00\x00\x0f\xa9\x83\xf0\x00\x00\x00\x00\x10\x99f\xe0\x00\x00\x00\x00\x11\x89e\xf0\x00\x00\x00\x00\x12yH\xe0\x00\x00\x00\x00\x13iG\xf0\x00\x00\x00\x00\x14Y*\xe0\x00\x00\x00\x00\x15I)\xf0" + - "\x00\x00\x00\x00\x169\f\xe0\x00\x00\x00\x00\x17)\v\xf0\x00\x00\x00\x00\x18\")`\x00\x00\x00\x00\x19\b\xed\xf0\x00\x00\x00\x00\x1a\x02\v`\x00\x00\x00\x00\x1a\xf2\np\x00\x00\x00\x00\x1b\xe1\xed`\x00\x00\x00\x00" + - "\x1c\xd1\xecp\x00\x00\x00\x00\x1d\xc1\xcf`\x00\x00\x00\x00\x1e\xb1\xcep\x00\x00\x00\x00\x1f\xa1\xb1`\x00\x00\x00\x00 v\x00\xf0\x00\x00\x00\x00!\x81\x93`\x00\x00\x00\x00\"U\xe2\xf0\x00\x00\x00\x00#j\xaf\xe0" + - "\x00\x00\x00\x00$5\xc4\xf0\x00\x00\x00\x00%J\x91\xe0\x00\x00\x00\x00&\x15\xa6\xf0\x00\x00\x00\x00'*s\xe0\x00\x00\x00\x00'\xfe\xc3p\x00\x00\x00\x00)\nU\xe0\x00\x00\x00\x00)ޥp\x00\x00\x00\x00" + - "*\xea7\xe0\x00\x00\x00\x00+\xbe\x87p\x00\x00\x00\x00,\xd3T`\x00\x00\x00\x00-\x9eip\x00\x00\x00\x00.\xb36`\x00\x00\x00\x00/~Kp\x00\x00\x00\x000\x93\x18`\x00\x00\x00\x001gg\xf0" + - "\x00\x00\x00\x002r\xfa`\x00\x00\x00\x003GI\xf0\x00\x00\x00\x004R\xdc`\x00\x00\x00\x005'+\xf0\x00\x00\x00\x0062\xbe`\x00\x00\x00\x007\a\r\xf0\x00\x00\x00\x008\x1b\xda\xe0\x00\x00\x00\x00" + - "8\xe6\xef\xf0\x00\x00\x00\x009\xfb\xbc\xe0\x00\x00\x00\x00:\xc6\xd1\xf0\x00\x00\x00\x00;۞\xe0\x00\x00\x00\x00<\xaf\xeep\x00\x00\x00\x00=\xbb\x80\xe0\x00\x00\x00\x00>\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0" + - "\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x01\x02\x03\x04" + - "\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05" + - "\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\xff\xff\xb2%\x00\x00\xff\xff\xab\xa0\x00\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x01\f\xff\xff\xc7\xc0\x01\x10\xff\xff\xc7\xc0\x01\x14LMT\x00CST\x00" + - "EST\x00EWT\x00EPT\x00EDT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x12\x00\x1c\x00America/Argentina/UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x03\x04" + - "\n\x00\x00\x00\x00\x00\xf1c9RR\xc8\xd9\xf6\xc4\x02\x00\x00\xc4\x02\x00\x00\x1b\x00\x1c\x00America/Argentina/CatamarcaUT\t\x00\x03\x15\xac" + - "\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xb2d\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff" + + "\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0" + + "\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff" + + "\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0" + + "\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff" + + "\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50" + + "\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00" + + "'!\x0f0\x00\x00\x00\x00'\xd0X\xa0\x00\x00\x00\x00)\x00\xf10\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0" + + "\x00\x00\x00\x00@\xbb\xf10\x00\x00\x00\x00@\xd5\v\xc0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x03\x05\x02\x05\x04\x05\xff\xff\xbf\x1c\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3" + + "\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xfcz=\xe1\xcd\x02\x00\x00\xcd" + + "\x02\x00\x00\x1a\x00\x1c\x00America/Argentina/San_JuanUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01" + + "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xb1\xbc\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@" + + "\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff" + + "\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0" + + "\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff" + + "\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@" + + "\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff" + + "\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0" + + "\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'!\x0f0\x00\x00\x00\x00'͵\xa0\x00\x00\x00\x00(&&@\x00\x00\x00\x00)\x00\xf10\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00" + + "+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00@\xba\x9f\xb0\x00\x00\x00\x00A\x030@\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x01\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x02\x05\x04\x05\x04\x05\x03\x05\x02\x05\x04\x05\xff\xff\xbf\xc4\x00\x00" + + "\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02\x00\n<-03>3\nPK" + + "\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xef\xf0R\x8a\xc4\x02\x00\x00\xc4\x02\x00\x00\x19\x00\x1c\x00America/Argentina/CordobaUT\t\x00\x03\x82\x0f" + + "\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xff" + - "r\x9c\xaf,\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0" + + "r\x9c\xad\xb0\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0" + "\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff" + "\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@" + "\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff" + "\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0" + "\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00" + "#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'!\x0f0\x00\x00\x00\x00'\xd0X\xa0\x00\x00\x00\x00)\x00\xff@\x00\x00\x00\x00)\xb0:\xa0" + - "\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00@\xbb\xf10\x00\x00\x00\x00@\xd5\v\xc0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00" + - "G\xdc\u007f \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x02\x04\x05\x04\x05\x03" + - "\x05\x02\x05\x04\x05\xff\xff\xc2T\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02" + - "\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RR\xc8\xd9\xf6\xc4\x02\x00\x00\xc4\x02\x00\x00 \x00\x1c\x00America/Argentina/Com" + - "odRivadaviaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00=\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xaf,\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4" + - "p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff" + - "\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A" + - "7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff" + - "\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7" + - "\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00" + - "\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'!\x0f0\x00\x00\x00\x00'\xd0" + - "X\xa0\x00\x00\x00\x00)\x00\xff@\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00@\xbb\xf10\x00\x00" + - "\x00\x00@\xd5\v\xc0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x02\x04\x05\x04\x05\x03\x05\x02\x05\x04\x05\xff\xff\xc2T\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fL" + - "MT\x00CMT\x00-04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x8b}\xb6\x1e\xc4\x02\x00\x00\xc4\x02\x00\x00\x19\x00\x1c\x00Ame" + - "rica/Argentina/UshuaiaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xb1\x88\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff" + - "\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n" + - "\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff" + - "\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed" + - "\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff" + - "\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c5" + - "0\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00" + - "\x00'!\x0f0\x00\x00\x00\x00'\xd0X\xa0\x00\x00\x00\x00)\x00\xf10\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*" + - "\xb0\x00\x00\x00\x00@\xb9N0\x00\x00\x00\x00@\xd5\v\xc0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x03\x05\x02\x05\x04\x05\xff\xff\xbf\xf8\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff" + - "\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RŒZ\x8c\xc4\x02\x00\x00" + - "\xc4\x02\x00\x00\x19\x00\x1c\x00America/Argentina/MendozaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00" + + "\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x00\x00\x00\x00H\xfa\xa2\xb0\x00\x00\x00\x00" + + "I\xbca \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x02\x04\x05\x04\x05\x03" + + "\x05\x04\x05\x04\x05\xff\xff\xc3\xd0\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02" + + "\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSY\xd8֭\xd6\x02\x00\x00\xd6\x02\x00\x00\x19\x00\x1c\x00America/Argentina/Tuc" + + "umanUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\x00" + + "\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xae\xa4\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba" + + "\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff" + + "\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7" + + "\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff" + + "\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9" + + "\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00" + + "\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'!\x0f0\x00\x00\x00\x00'\xd0X\xa0\x00\x00\x00\x00)" + + "\x00\xff@\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00@\xbb\xf10\x00\x00\x00\x00@\xcb\xd1@\x00" + + "\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x00\x00\x00\x00H\xfa\xa2\xb0\x00\x00\x00\x00I\xbca \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x02\x04\x05\x04\x05\x03\x05\x02\x05\x04\x05\x04\x05\xff\xff\xc2\xdc\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff" + + "\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSt*\x9b!\xb2\x02\x00\x00" + + "\xb2\x02\x00\x00\x17\x00\x1c\x00America/Argentina/SaltaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00T" + + "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00;\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xae\xd4\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff" + + "\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9" + + "\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff" + + "\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM" + + "\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff" + + "\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xac" + + "R@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00" + + "\x00\x00%\xf0v\xa0\x00\x00\x00\x00'!\x0f0\x00\x00\x00\x00'\xd0X\xa0\x00\x00\x00\x00)\x00\xff@\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6" + + "ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x02\x04\x05\x04\x05\x03\x05\x04\x05\xff\xff¬\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00" + + "\fLMT\x00CMT\x00-04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSp\xb6{\xc9\x13\x02\x00\x00\x13\x02\x00\x00\x14\x00\x1c\x00A" + + "merica/IndianapolisUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00&\x00\x00\x00\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a" + + "\xdbp\xff\xff\xff\xff\xcaW\"\x80\xff\xff\xff\xff\xca\xd8Gp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xd3u\xf3\x00\xff\xff\xff\xff\xd4@\xeb\xf0\xff\xff" + + "\xff\xff\xd5U\xd5\x00\xff\xff\xff\xff\xd6 \xcd\xf0\xff\xff\xff\xff\xd75\xb7\x00\xff\xff\xff\xff\xd8\x00\xaf\xf0\xff\xff\xff\xff\xd9\x15\x99\x00\xff\xff\xff\xff\xd9\xe0\x91\xf0\xff\xff\xff\xff\xda\xfe\xb5\x80\xff\xff\xff\xff\xdb\xc0" + + "s\xf0\xff\xff\xff\xff\xdcޗ\x80\xff\xff\xff\xffݩ\x90p\xff\xff\xff\xff\u07bey\x80\xff\xff\xff\xff߉rp\xff\xff\xff\xff\xe0\x9e[\x80\xff\xff\xff\xff\xe1iTp\xff\xff\xff\xff\xe2~=\x80\xff\xff" + + "\xff\xff\xe3I6p\xff\xff\xff\xff\xe4^\x1f\x80\xff\xff\xff\xff\xe8\xf2\x16\xf0\xff\xff\xff\xff\xea\a\x00\x00\xff\xff\xff\xff\xfe\xb8\x1c\xf0\xff\xff\xff\xff\xff\xa7\xff\xe0\x00\x00\x00\x00\x00\x97\xfe\xf0\x00\x00\x00\x00\x01\x87" + + "\xe1\xe0\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05\x02\x05\x06\x05\x06" + + "\x05\x06\x05\x06\xff\xff\xaf:\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14\xff\xff\xc7\xc0\x01\x18LMT\x00CDT\x00CST\x00CW" + + "T\x00CPT\x00EST\x00EDT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00" + + "\xb1\x00\x00\x00\x10\x00\x1c\x00America/DominicaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffz敹\xff\xff\xff\xff\xcb\xf62\xc0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\x01" + + "\x03\x02\x01\xff\xff\xc2\a\x00\x00\xff\xff\xc7\xc0\x00\x04\xff\xff\xd5\xd0\x01\b\xff\xff\xd5\xd0\x01\fLMT\x00AST\x00APT\x00AWT\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00#" + + "\x82iS\x9bܩ=\xda\x06\x00\x00\xda\x06\x00\x00\x0f\x00\x1c\x00America/ChicagoUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_" + + "\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaf\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9" + + "p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xff\xa2\xcbt\x00\xff\xff\xff\xff\xa3\x83\xf7\xf0\xff\xff\xff\xff\xa4EҀ\xff\xff\xff\xff\xa5c\xd9\xf0\xff\xff\xff\xff\xa6S\xd9\x00\xff\xff\xff" + + "\xff\xa7\x15\x97p\xff\xff\xff\xff\xa83\xbb\x00\xff\xff\xff\xff\xa8\xfe\xb3\xf0\xff\xff\xff\xff\xaa\x13\x9d\x00\xff\xff\xff\xff\xaaޕ\xf0\xff\xff\xff\xff\xab\xf3\u007f\x00\xff\xff\xff\xff\xac\xbew\xf0\xff\xff\xff\xff\xad\xd3a" + + "\x00\xff\xff\xff\xff\xae\x9eY\xf0\xff\xff\xff\xff\xaf\xb3C\x00\xff\xff\xff\xff\xb0~;\xf0\xff\xff\xff\xff\xb1\x9c_\x80\xff\xff\xff\xff\xb2gXp\xff\xff\xff\xff\xb3|A\x80\xff\xff\xff\xff\xb4G:p\xff\xff\xff" + + "\xff\xb5\\#\x80\xff\xff\xff\xff\xb6'\x1cp\xff\xff\xff\xff\xb7<\x05\x80\xff\xff\xff\xff\xb8\x06\xfep\xff\xff\xff\xff\xb9\x1b\xe7\x80\xff\xff\xff\xff\xb9\xe6\xe0p\xff\xff\xff\xff\xbb\x05\x04\x00\xff\xff\xff\xff\xbb\xc6\xc2" + + "p\xff\xff\xff\xff\xbc\xe4\xe6\x00\xff\xff\xff\xff\xbd\xaf\xde\xf0\xff\xff\xff\xff\xbe\xc4\xc8\x00\xff\xff\xff\xff\xbf\x8f\xc0\xf0\xff\xff\xff\xff\xc0Z\xd6\x00\xff\xff\xff\xff\xc1\xb0\x8fހ\x00\x00\x00\x00?\x9bp" + + "\xf0\x00\x00\x00\x00@o\xc0\x80\x00\x00\x00\x00A\x84\x8dp\x00\x00\x00\x00BO\xa2\x80\x00\x00\x00\x00Cdop\x00\x00\x00\x00D/\x84\x80\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7\x00\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x04\x05\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xad\xd4\x00\x00\xff\xff" + + "\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x00\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x01\x14LMT\x00CDT\x00CST\x00EST\x00CWT\x00CPT\x00\nCST6CDT" + + ",M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x1c\xd8\x19\x9dp\x01\x00\x00p\x01\x00\x00\x15\x00\x1c\x00America/Swift_" + + "CurrentUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x17\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff\x86\xfd\x96\x18\xff\xff\xff\xff\x9e\xb8\xaf\x90\xff\xff\xff\xff\x9f\xbb\a\x80\xff\xff\xff\xffˉ\f\x90\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff" + + "\xff\xff\xd3v\x01\x10\xff\xff\xff\xff\xd4So\x00\xff\xff\xff\xff\xd5U\xe3\x10\xff\xff\xff\xff\xd6 \xdc\x00\xff\xff\xff\xff\xd75\xc5\x10\xff\xff\xff\xff\xd8\x00\xbe\x00\xff\xff\xff\xff\xd9\x15\xa7\x10\xff\xff\xff\xff\xd9\xe0" + + "\xa0\x00\xff\xff\xff\xff\xe8',\x10\xff\xff\xff\xff\xe9\x17\x0f\x00\xff\xff\xff\xff\xeb\xe6\xf0\x10\xff\xff\xff\xff\xec\xd6\xd3\x00\xff\xff\xff\xff\xed\xc6\xd2\x10\xff\xff\xff\xff\xee\x91\xcb\x00\xff\xff\xff\xff\xef\xaf\xee\x90\xff\xff" + + "\xff\xff\xf0q\xad\x00\x00\x00\x00\x00\x04a\x19\x90\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05\xff\xff\x9a\xe8\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01" + + "\f\xff\xff\xab\xa0\x01\x10\xff\xff\xab\xa0\x00\x14LMT\x00MDT\x00MST\x00MWT\x00MPT\x00CST\x00\nCST6\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x1e+}" + + "\x15\xb4\x02\x00\x00\xb4\x02\x00\x00\x14\x00\x1c\x00America/Rankin_InletUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01" + "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xb2\x04\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@" + - "\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff" + - "\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0" + - "\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff" + - "\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@" + - "\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff" + - "\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0" + - "\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'\x194@\x00\x00\x00\x00'\xcdð\x00\x00\x00\x00(\xfag\xc0\x00\x00\x00\x00)\xb0H\xb0\x00\x00\x00\x00*\xe0\xe1@\x00\x00\x00\x00+\x99W \x00\x00\x00\x00" + - "7\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00@\xb0\x13\xb0\x00\x00\x00\x00AV>\xc0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x02\x03\x02\x03\x02\x04\x05\x03\x05\x02\x05\x04\x05\xff\xff\xbf|\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7" + - "\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1" + - "c9R\xe0\xbf\xf5\xe5\xc4\x02\x00\x00\xc4\x02\x00\x00\x1e\x00\x1c\x00America/Argentina/Buenos_AiresUT\t\x00\x03\x15\xac\x0e`\x15\xac" + - "\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" + - "\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xa8L" + - "\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff" + - "\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30" + - "\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff" + - "\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0" + - "\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff" + - "\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0" + - "\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'!\x0f0\x00\x00\x00\x00'\xd0X\xa0\x00\x00\x00\x00)\x00\xf10\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00" + - "*\xe0\xd30\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x00\x00\x00\x00H\xfa\xa2\xb0\x00\x00\x00\x00I\xbca " + - "\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x03\x05\x04\x05\x04" + - "\x05\xff\xff\xc94\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02\x00\n<-" + - "03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rm\aD\x0e\xcd\x02\x00\x00\xcd\x02\x00\x00\x1a\x00\x1c\x00America/Argentina/La_Rioj" + - "aUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>\x00\x00\x00\x06" + - "\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xb0,\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0" + - "\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff" + - "\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0" + - "\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff" + - "\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@" + - "\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00" + - "\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'!\x0f0\x00\x00\x00\x00'͵\xa0\x00\x00\x00\x00(&&@" + - "\x00\x00\x00\x00)\x00\xf10\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00@\xbb\xf10\x00\x00\x00\x00" + - "@\xd5\v\xc0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x02\x05\x04\x05\x04\x05\x03\x05\x02\x05\x04\x05\xff\xff\xc1T\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLM" + - "T\x00CMT\x00-04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x8ep\xb4c\xc4\x02\x00\x00\xc4\x02\x00\x00\x1e\x00\x1c\x00Amer" + - "ica/Argentina/Rio_GallegosUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xb2d\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1a\xc9" + - "\xb0\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff" + - "\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04" + - "@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff" + - "\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6\xe6\x9f" + - "\xb0\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff" + - "\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v" + - "\xa0\x00\x00\x00\x00'!\x0f0\x00\x00\x00\x00'\xd0X\xa0\x00\x00\x00\x00)\x00\xf10\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00" + - "\x008\xbf*\xb0\x00\x00\x00\x00@\xbb\xf10\x00\x00\x00\x00@\xd5\v\xc0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x03\x05\x02\x05\x04\x05\xff\xff\xbf\x1c\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0" + - "\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RutZ\x1a" + - "\xb2\x02\x00\x00\xb2\x02\x00\x00\x17\x00\x1c\x00America/Argentina/JujuyUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8" + - "\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00;\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xae\xb8\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{" + - "R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff" + - "\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c" + - "\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff" + - "\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62" + - "\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff" + - "\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7" + - "\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'*W\xc0\x00\x00\x00\x00'\xe2۰\x00\x00\x00\x00(\xee\x8a@\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x99W \x00\x00" + - "\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x02\x03\x02\x04\x05\x04\x05\x03\x05\x04\x05\xff\xff\xc2\xc8\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff" + - "\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xfcz=\xe1\xcd\x02\x00\x00\xcd\x02\x00\x00\x1a" + - "\x00\x1c\x00America/Argentina/San_JuanUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZi" + - "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xb1\xbc\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff" + - "\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0" + - "\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff" + - "\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0" + - "\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff" + - "\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@" + - "\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00" + - "%\xf0v\xa0\x00\x00\x00\x00'!\x0f0\x00\x00\x00\x00'͵\xa0\x00\x00\x00\x00(&&@\x00\x00\x00\x00)\x00\xf10\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x99W " + - "\x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00@\xba\x9f\xb0\x00\x00\x00\x00A\x030@\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x02\x05\x04\x05\x04\x05\x03\x05\x02\x05\x04\x05\xff\xff\xbf\xc4\x00\x00\xff\xff\xc3\xd0" + - "\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00" + - "\x00\x00\x00\x00\xf1c9R\x1c\x80\xb9\\\xcd\x02\x00\x00\xcd\x02\x00\x00\x1a\x00\x1c\x00America/Argentina/San_LuisUT\t\x00\x03\x15\xac\x0e`\x15" + - "\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00" + - "\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xaf" + - "\xb4\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff" + - "\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc3" + - "0\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff" + - "\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6" + - "\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff" + - "\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5" + - "\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xfd\xa5\xa0\x00\x00\x00\x00'\x194@\x00\x00\x00\x00'\xcdð\x00\x00\x00\x00(G\x1b\xc0\x00\x00\x00\x007\xf6ư\x00\x00\x00" + - "\x008\xbf*\xb0\x00\x00\x00\x00@\xba\x9f\xb0\x00\x00\x00\x00A\x030@\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\x93\xfc\xa0\x00\x00\x00\x00G\xd3R\xb0\x00\x00\x00\x00H\xf1v@\x00\x00\x00\x00I\xb34" + - "\xb0\x00\x00\x00\x00J\xd1X@\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x02\x03\x02" + - "\x05\x03\x05\x02\x05\x04\x03\x02\x03\x02\x05\xff\xff\xc1\xcc\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-" + - "03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rt*\x9b!\xb2\x02\x00\x00\xb2\x02\x00\x00\x17\x00\x1c\x00America/Argenti" + - "na/SaltaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00;\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xae\xd4\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff" + - "\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0" + - "Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff" + - "\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4" + - "Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff" + - "\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a" + - "\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'!\x0f0\x00\x00\x00\x00'\xd0X\xa0\x00" + - "\x00\x00\x00)\x00\xff@\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G" + - "\xdc\u007f \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x02\x04\x05\x04\x05\x03\x05" + - "\x04\x05\xff\xff¬\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02\x00\n<" + - "-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RY\xd8֭\xd6\x02\x00\x00\xd6\x02\x00\x00\x19\x00\x1c\x00America/Argentina/Tucuma" + - "nUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\x00\x00\x00\x06" + - "\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xae\xa4\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0" + - "\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff" + - "\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0" + - "\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff" + - "\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@" + - "\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00" + - "\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'!\x0f0\x00\x00\x00\x00'\xd0X\xa0\x00\x00\x00\x00)\x00\xff@" + - "\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00@\xbb\xf10\x00\x00\x00\x00@\xcb\xd1@\x00\x00\x00\x00" + - "Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x00\x00\x00\x00H\xfa\xa2\xb0\x00\x00\x00\x00I\xbca \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x02\x04\x05\x04\x05\x03\x05\x02\x05\x04\x05\x04\x05\xff\xff\xc2\xdc\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01" + - "\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xef\xf0R\x8a\xc4\x02\x00\x00\xc4\x02\x00" + - "\x00\x19\x00\x1c\x00America/Argentina/CordobaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZ" + - "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xad\xb0\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff" + - "\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4" + - "\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff" + - "\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff" + - "0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff" + - "\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR" + - "@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00" + - "\x00%\xf0v\xa0\x00\x00\x00\x00'!\x0f0\x00\x00\x00\x00'\xd0X\xa0\x00\x00\x00\x00)\x00\xff@\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6\xc6" + - "\xb0\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x00\x00\x00\x00H\xfa\xa2\xb0\x00\x00\x00\x00I\xbca \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x02\x04\x05\x04\x05\x03\x05\x04\x05\x04\x05\xff\xff\xc3\xd0\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b" + - "\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R" + - "\xe3\xc9I\xd0U\x03\x00\x00U\x03\x00\x00\x12\x00\x1c\x00America/Grand_TurkUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03" + - "\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00L\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xffi\x87\x1e0\xff\xff\xff\xff\x93\x0f\xb4\xfe\x00\x00\x00\x00\x11\x89e" + - "\xf0\x00\x00\x00\x00\x12yH\xe0\x00\x00\x00\x00\x13iG\xf0\x00\x00\x00\x00\x14Y*\xe0\x00\x00\x00\x00\x15I)\xf0\x00\x00\x00\x00\x169\f\xe0\x00\x00\x00\x00\x17)\v\xf0\x00\x00\x00\x00\x18\")`\x00\x00\x00" + - "\x00\x19\b\xed\xf0\x00\x00\x00\x00\x1a\x02\v`\x00\x00\x00\x00\x1a\xf2\np\x00\x00\x00\x00\x1b\xe1\xed`\x00\x00\x00\x00\x1c\xd1\xecp\x00\x00\x00\x00\x1d\xc1\xcf`\x00\x00\x00\x00\x1e\xb1\xcep\x00\x00\x00\x00\x1f\xa1\xb1" + - "`\x00\x00\x00\x00 v\x00\xf0\x00\x00\x00\x00!\x81\x93`\x00\x00\x00\x00\"U\xe2\xf0\x00\x00\x00\x00#j\xaf\xe0\x00\x00\x00\x00$5\xc4\xf0\x00\x00\x00\x00%J\x91\xe0\x00\x00\x00\x00&\x15\xa6\xf0\x00\x00\x00" + - "\x00'*s\xe0\x00\x00\x00\x00'\xfe\xc3p\x00\x00\x00\x00)\nU\xe0\x00\x00\x00\x00)ޥp\x00\x00\x00\x00*\xea7\xe0\x00\x00\x00\x00+\xbe\x87p\x00\x00\x00\x00,\xd3T`\x00\x00\x00\x00-\x9ei" + - "p\x00\x00\x00\x00.\xb36`\x00\x00\x00\x00/~Kp\x00\x00\x00\x000\x93\x18`\x00\x00\x00\x001gg\xf0\x00\x00\x00\x002r\xfa`\x00\x00\x00\x003GI\xf0\x00\x00\x00\x004R\xdc`\x00\x00\x00" + - "\x005'+\xf0\x00\x00\x00\x0062\xbe`\x00\x00\x00\x007\a\r\xf0\x00\x00\x00\x008\x1b\xda\xe0\x00\x00\x00\x008\xe6\xef\xf0\x00\x00\x00\x009\xfb\xbc\xe0\x00\x00\x00\x00:\xc6\xd1\xf0\x00\x00\x00\x00;۞" + - "\xe0\x00\x00\x00\x00<\xaf\xeep\x00\x00\x00\x00=\xbb\x80\xe0\x00\x00\x00\x00>\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00" + - "\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x00\x00\x00\x00G-_\xe0\x00\x00\x00\x00Gӊ\xf0\x00\x00\x00\x00I\rA\xe0\x00\x00\x00\x00I\xb3l" + - "\xf0\x00\x00\x00\x00J\xed#\xe0\x00\x00\x00\x00K\x9c\x89p\x00\x00\x00\x00L\xd6@`\x00\x00\x00\x00M|kp\x00\x00\x00\x00N\xb6\"`\x00\x00\x00\x00O\\Mp\x00\x00\x00\x00P\x96\x04`\x00\x00\x00" + - "\x00Q\x8f\xec\x90\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@oΐ\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00B" + - "O\xb0\x90\x00\x00\x00\x00Cd}\x80\x00\x00\x00\x00D/\x92\x90\x00\x00\x00\x00ED_\x80\x00\x00\x00\x00F\x0ft\x90\x00\x00\x00\x00G$A\x80\x00\x00\x00\x00G\xf8\x91\x10\x00\x00\x00\x00I\x04#\x80\x00" + - "\x00\x00\x00I\xd8s\x10\x00\x00\x00\x00J\xe4\x05\x80\x00\x00\x00\x00K\xb8U\x10\x00\x00\x00\x00L\xcd\x13\xf0\x01\x02\x01\x02\x01\x02\x01\x03\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01" + - "\x04\x01\x04\x01\x04\x01\x04\x01\x05\x02\xff\xff\x9dT\x00\x00\xff\xff\x9d\x90\x00\x04\xff\xff\xab\xa0\x00\b\xff\xff\x8f\x80\x00\f\xff\xff\xab\xa0\x01\x10\xff\xff\xb9\xb0\x01\x14LMT\x00MST\x00CST\x00PS" + - "T\x00MDT\x00CDT\x00\nCST6CDT,M4.1.0,M10.5.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00\x00\x00" + - "\x0e\x00\x1c\x00America/VirginUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x9373\xac\x01\xff\xff\xc6T\x00\x00\xff\xff\xc7\xc0\x00\x04LMT\x00AST\x00\nAST4\nPK\x03\x04" + - "\n\x00\x00\x00\x00\x00\xf1c9R\xa1'\a\xbd\x97\x00\x00\x00\x97\x00\x00\x00\x0f\x00\x1c\x00America/CayenneUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04" + - "\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" + - "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x91\xf4+\x90\xff\xff\xff\xff\xfb\xc35\xc0" + - "\x01\x02\xff\xff\xce\xf0\x00\x00\xff\xff\xc7\xc0\x00\x04\xff\xff\xd5\xd0\x00\bLMT\x00-04\x00-03\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rg\xcag\xe7\x82\x00" + - "\x00\x00\x82\x00\x00\x00\x12\x00\x1c\x00America/MontserratUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif" + - "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x9373\xac\x01\xff\xff\xc6T\x00\x00\xff\xff\xc7\xc0\x00\x04LMT\x00AST\x00" + - "\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R?_p\x99\x0e\x05\x00\x00\x0e\x05\x00\x00\x10\x00\x1c\x00America/WinnipegUT\t\x00\x03\x15\xac\x0e" + - "`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" + - "\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00}\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xffd" + - "䰔\xff\xff\xff\xff\x9b\x01\xfb\xe0\xff\xff\xff\xff\x9búP\xff\xff\xff\xff\x9e\xb8\xa1\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\u00a0;\x80\xff\xff\xff\xff\xc3O\x84\xf0\xff\xff\xff\xffˈ\xfe\x80\xff" + - "\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xffӈh\x00\xff\xff\xff\xff\xd4S`\xf0\xff\xff\xff\xff\xd5U\xd5\x00\xff\xff\xff\xff\xd6 \xcd\xf0\xff\xff\xff\xff\xd75\xb7\x00\xff\xff\xff\xff\xd8" + - "\x00\xaf\xf0\xff\xff\xff\xff\xd9\x15\x99\x00\xff\xff\xff\xff\xd9\xe0\x91\xf0\xff\xff\xff\xff\xdb\x00\a\x00\xff\xff\xff\xff\xdb\xc8\\\xf0\xff\xff\xff\xff\xdcޗ\x80\xff\xff\xff\xffݩ\x90p\xff\xff\xff\xff\u07bey\x80\xff" + - "\xff\xff\xff߉rp\xff\xff\xff\xff\xe0\x9e[\x80\xff\xff\xff\xff\xe1iTp\xff\xff\xff\xff\xe2~=\x80\xff\xff\xff\xff\xe3I6p\xff\xff\xff\xff\xe4^\x1f\x80\xff\xff\xff\xff\xe5)\x18p\xff\xff\xff\xff\xe6" + - "G<\x00\xff\xff\xff\xff\xe7\x124\xf0\xff\xff\xff\xff\xe8'\x1e\x00\xff\xff\xff\xff\xe8\xf2\x16\xf0\xff\xff\xff\xff\xea\a\x00\x00\xff\xff\xff\xff\xea\xd1\xf8\xf0\xff\xff\xff\xff\xeb\xe6\xe2\x00\xff\xff\xff\xff\xec\xd6\xc4\xf0\xff" + - "\xff\xff\xff\xed\xc6\xc4\x00\xff\xff\xff\xff\ue47c\xf0\xff\xff\xff\xff\xf3o\xa4\x80\xff\xff\xff\xff\xf41b\xf0\xff\xff\xff\xff\xf9\x0fJ\x80\xff\xff\xff\xff\xfa\bv\x00\xff\xff\xff\xff\xfa\xf8g\x00\xff\xff\xff\xff\xfb" + - "\xe8X\x00\xff\xff\xff\xff\xfc\xd8I\x00\xff\xff\xff\xff\xfd\xc8:\x00\xff\xff\xff\xff\xfe\xb8+\x00\xff\xff\xff\xff\xff\xa8\x1c\x00\x00\x00\x00\x00\x00\x98\r\x00\x00\x00\x00\x00\x01\x87\xfe\x00\x00\x00\x00\x00\x02w\xef\x00\x00" + - "\x00\x00\x00\x03q\x1a\x80\x00\x00\x00\x00\x04a\v\x80\x00\x00\x00\x00\x05P\xfc\x80\x00\x00\x00\x00\x06@\xed\x80\x00\x00\x00\x00\a0ހ\x00\x00\x00\x00\b π\x00\x00\x00\x00\t\x10\xc0\x80\x00\x00\x00\x00\n" + - "\x00\xb1\x80\x00\x00\x00\x00\n\xf0\xa2\x80\x00\x00\x00\x00\v\xe0\x93\x80\x00\x00\x00\x00\fٿ\x00\x00\x00\x00\x00\r\xc0u\x80\x00\x00\x00\x00\x0e\xb9\xa1\x00\x00\x00\x00\x00\x0f\xa9\x92\x00\x00\x00\x00\x00\x10\x99\x83\x00\x00" + - "\x00\x00\x00\x11\x89t\x00\x00\x00\x00\x00\x12ye\x00\x00\x00\x00\x00\x13iV\x00\x00\x00\x00\x00\x14YG\x00\x00\x00\x00\x00\x15I8\x00\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17)\x1a\x00\x00\x00\x00\x00\x18" + - "\"E\x80\x00\x00\x00\x00\x19\b\xfc\x00\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2\x18\x80\x00\x00\x00\x00\x1b\xe2\t\x80\x00\x00\x00\x00\x1c\xd1\xfa\x80\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1܀\x00" + - "\x00\x00\x00\x1f\xa1̀\x00\x00\x00\x00 v\x0f\x00\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xf1\x00\x00\x00\x00\x00#j\xcc\x00\x00\x00\x00\x00$5\xd3\x00\x00\x00\x00\x00%J\xae\x00\x00\x00\x00\x00&" + - "\x15\xb5\x00\x00\x00\x00\x00'*\x90\x00\x00\x00\x00\x00'\xfeр\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\u07b3\x80\x00\x00\x00\x00*\xeaT\x00\x00\x00\x00\x00+\xbe\x95\x80\x00\x00\x00\x00,\xd3p\x80\x00" + - "\x00\x00\x00-\x9ew\x80\x00\x00\x00\x00.\xb3R\x80\x00\x00\x00\x00/~Y\x80\x00\x00\x00\x000\x934\x80\x00\x00\x00\x001gv\x00\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003GX\x00\x00\x00\x00\x004" + - "R\xf8\x80\x00\x00\x00\x005':\x00\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a\x1c\x00\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xc6\xe0\x00\x00" + - "\x00\x00\x00;ۻ\x00\x00\x00\x00\x00<\xaf\xfc\x80\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8fހ\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@o\xc0\x80\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00B" + - "O\xa2\x80\x00\x00\x00\x00Cd}\x80\x00\x00\x00\x00D/\x84\x80\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7\x00\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00:\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xff\xe7\x8cn\x00\xff\xff\xff\xff\xf7/L`\xff\xff\xff\xff\xf8(w\xe0" + + "\x00\x00\x00\x00\x13iV\x00\x00\x00\x00\x00\x14Y8\xf0\x00\x00\x00\x00\x15I8\x00\x00\x00\x00\x00\x169\x1a\xf0\x00\x00\x00\x00\x17)\x1a\x00\x00\x00\x00\x00\x18\"7p\x00\x00\x00\x00\x19\b\xfc\x00\x00\x00\x00\x00" + + "\x1a\x02\x19p\x00\x00\x00\x00\x1a\xf2\x18\x80\x00\x00\x00\x00\x1b\xe1\xfbp\x00\x00\x00\x00\x1c\xd1\xfa\x80\x00\x00\x00\x00\x1d\xc1\xddp\x00\x00\x00\x00\x1e\xb1܀\x00\x00\x00\x00\x1f\xa1\xbfp\x00\x00\x00\x00 v\x0f\x00" + + "\x00\x00\x00\x00!\x81\xa1p\x00\x00\x00\x00\"U\xf1\x00\x00\x00\x00\x00#j\xbd\xf0\x00\x00\x00\x00$5\xd3\x00\x00\x00\x00\x00%J\x9f\xf0\x00\x00\x00\x00&\x15\xb5\x00\x00\x00\x00\x00'*\x81\xf0\x00\x00\x00\x00" + + "'\xfeр\x00\x00\x00\x00)\nc\xf0\x00\x00\x00\x00)\u07b3\x80\x00\x00\x00\x00*\xeaE\xf0\x00\x00\x00\x00+\xbe\x95\x80\x00\x00\x00\x00,\xd3bp\x00\x00\x00\x00-\x9ew\x80\x00\x00\x00\x00.\xb3Dp" + + "\x00\x00\x00\x00/~Y\x80\x00\x00\x00\x000\x93&p\x00\x00\x00\x001gv\x00\x00\x00\x00\x002s\bp\x00\x00\x00\x003GX\x00\x00\x00\x00\x004R\xeap\x00\x00\x00\x005':\x00\x00\x00\x00\x00" + + "62\xccp\x00\x00\x00\x007\a\x1c\x00\x00\x00\x00\x008\x1b\xe8\xf0\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xca\xf0\x00\x00\x00\x00:\xc6\xe0\x00\x00\x00\x00\x00;۬\xf0\x00\x00\x00\x00<\xaf\xfc\x80" + + "\x00\x00\x00\x00=\xbb\x8e\xf0\x00\x00\x00\x00>\x8fހ\x00\x00\x00\x00?\x9bp\xf0\x00\x00\x00\x00@o\xc0\x80\x00\x00\x00\x00A\x84\x8dp\x00\x00\x00\x00BO\xa2\x80\x00\x00\x00\x00Cdop\x00\x00\x00\x00" + + "D/\x84\x80\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7\x00\x02\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x04\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x00\x00\x00\x00\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff\xab\xa0\x00\t\xff\xff\xb9\xb0\x01\r\xff\xff\xb9\xb0\x00\x11-00\x00CDDT\x00CST" + + "\x00CDT\x00EST\x00\nCST6CDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSԾ\xe7#\x95\x00\x00\x00\x95\x00\x00\x00\x0e" + + "\x00\x1c\x00America/PanamaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xffi\x87&\x10\xff\xff\xff\xff\x8b\xf4a\xe8\x01\x02\xff\xff\xb5p\x00\x00\xff\xff\xb5\x18\x00\x04\xff\xff\xb9\xb0\x00\bLMT\x00" + + "CMT\x00EST\x00\nEST5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xe90T\x16\xd1\x01\x00\x00\xd1\x01\x00\x00\x0f\x00\x1c\x00America/GodthabU" + + "T\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\"\x00\x00\x00\x03\x00\x00" + + "\x00\f\xff\xff\xff\xff\x9b\x80h\x00\x00\x00\x00\x00\x13M|P\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00" + + "\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|" + + "\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#3<-02>,M3.5.0/-2" + + ",M10.5.0/-1\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x89غ\xee\x15\x04\x00\x00\x15\x04\x00\x00\x0e\x00\x1c\x00America/BelizeUT\t\x00" + + "\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\x00\x00\x00\x06\x00\x00\x00\x1a\xff" + + "\xff\xff\xff\x93^ٰ\xff\xff\xff\xff\x9f\x9f;\xe0\xff\xff\xff\xff\xa0EQ\xd8\xff\xff\xff\xff\xa1\u007f\x1d\xe0\xff\xff\xff\xff\xa2.nX\xff\xff\xff\xff\xa3^\xff\xe0\xff\xff\xff\xff\xa4\x0ePX\xff\xff\xff\xff\xa5" + + ">\xe1\xe0\xff\xff\xff\xff\xa5\xee2X\xff\xff\xff\xff\xa7'\xfe`\xff\xff\xff\xff\xa7\xce\x14X\xff\xff\xff\xff\xa9\a\xe0`\xff\xff\xff\xff\xa9\xad\xf6X\xff\xff\xff\xff\xaa\xe7\xc2`\xff\xff\xff\xff\xab\x97\x12\xd8\xff" + + "\xff\xff\xff\xacǤ`\xff\xff\xff\xff\xadv\xf4\xd8\xff\xff\xff\xff\xae\xa7\x86`\xff\xff\xff\xff\xafV\xd6\xd8\xff\xff\xff\xff\xb0\x87h`\xff\xff\xff\xff\xb16\xb8\xd8\xff\xff\xff\xff\xb2p\x84\xe0\xff\xff\xff\xff\xb3" + + "\x16\x9a\xd8\xff\xff\xff\xff\xb4Pf\xe0\xff\xff\xff\xff\xb4\xf6|\xd8\xff\xff\xff\xff\xb60H\xe0\xff\xff\xff\xff\xb6ߙX\xff\xff\xff\xff\xb8\x10*\xe0\xff\xff\xff\xff\xb8\xbf{X\xff\xff\xff\xff\xb9\xf0\f\xe0\xff" + + "\xff\xff\xff\xba\x9f]X\xff\xff\xff\xff\xbb\xd9)`\xff\xff\xff\xff\xbc\u007f?X\xff\xff\xff\xff\xbd\xb9\v`\xff\xff\xff\xff\xbe_!X\xff\xff\xff\xff\xbf\x98\xed`\xff\xff\xff\xff\xc0?\x03X\xff\xff\xff\xff\xc1" + + "x\xcf`\xff\xff\xff\xff\xc2(\x1f\xd8\xff\xff\xff\xff\xc3X\xb1`\xff\xff\xff\xff\xc4\b\x01\xd8\xff\xff\xff\xff\xc58\x93`\xff\xff\xff\xff\xc5\xe7\xe3\xd8\xff\xff\xff\xff\xc7!\xaf\xe0\xff\xff\xff\xff\xc7\xc7\xc5\xd8\xff" + + "\xff\xff\xff\xc9\x01\x91\xe0\xff\xff\xff\xffɧ\xa7\xd8\xff\xff\xff\xff\xca\xe1s\xe0\xff\xff\xff\xffː\xc4X\xff\xff\xff\xff\xcc@\"\xe0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2\xc6qP\xff\xff\xff\xff\xd6" + + ")\xfa`\xff\xff\xff\xff\xd6\xd9J\xd8\xff\xff\xff\xff\xd8\t\xdc`\xff\xff\xff\xffع,\xd8\xff\xff\xff\xff\xd9\xe9\xbe`\xff\xff\xff\xffڙ\x0e\xd8\xff\xff\xff\xff\xdb\xd2\xda\xe0\xff\xff\xff\xff\xdcx\xf0\xd8\xff" + + "\xff\xff\xffݲ\xbc\xe0\xff\xff\xff\xff\xdeX\xd2\xd8\xff\xff\xff\xffߒ\x9e\xe0\xff\xff\xff\xff\xe0A\xefX\xff\xff\xff\xff\xe1r\x80\xe0\xff\xff\xff\xff\xe2!\xd1X\xff\xff\xff\xff\xe3Rb\xe0\xff\xff\xff\xff\xe4" + + "\x01\xb3X\xff\xff\xff\xff\xe52D\xe0\xff\xff\xff\xff\xe5\xe1\x95X\xff\xff\xff\xff\xe7\x1ba`\xff\xff\xff\xff\xe7\xc1wX\xff\xff\xff\xff\xe8\xfbC`\xff\xff\xff\xff\xe9\xa1YX\xff\xff\xff\xff\xea\xdb%`\xff" + + "\xff\xff\xff\xeb\x8au\xd8\xff\xff\xff\xff\xec\xbb\a`\xff\xff\xff\xff\xedjW\xd8\xff\xff\xff\xff\xee\x9a\xe9`\xff\xff\xff\xff\xefJ9\xd8\xff\xff\xff\xff\xf0\x84\x05\xe0\xff\xff\xff\xff\xf1*\x1b\xd8\xff\xff\xff\xff\xf2" + + "c\xe7\xe0\xff\xff\xff\xff\xf3\t\xfd\xd8\xff\xff\xff\xff\xf4C\xc9\xe0\xff\xff\xff\xff\xf4\xe9\xdf\xd8\xff\xff\xff\xff\xf6#\xab\xe0\xff\xff\xff\xff\xf6\xd2\xfcX\xff\xff\xff\xff\xf8\x03\x8d\xe0\xff\xff\xff\xff\xf8\xb2\xdeX\xff" + + "\xff\xff\xff\xf9\xe3o\xe0\xff\xff\xff\xff\xfa\x92\xc0X\xff\xff\xff\xff\xfb̌`\xff\xff\xff\xff\xfcr\xa2X\x00\x00\x00\x00\ab\xdb`\x00\x00\x00\x00\a\xb9\xd0P\x00\x00\x00\x00\x18aq`\x00\x00\x00\x00\x18" + + "\xab7P\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05\x02\x05\x02\xff\xff\xadP\x00\x00\xff\xff\xb2\xa8\x01\x04\xff\xff\xab\xa0\x00\n\xff" + + "\xff\xb9\xb0\x01\x0e\xff\xff\xb9\xb0\x01\x12\xff\xff\xb9\xb0\x01\x16LMT\x00-0530\x00CST\x00CWT\x00CPT\x00CDT\x00\nCST6\nPK\x03\x04\n\x00\x00\x00\x00\x00#" + + "\x82iS\xd7\b\\\xc6&\x02\x00\x00&\x02\x00\x00\x10\x00\x1c\x00America/MiquelonUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S" + + "_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff\x91\xb68\xa8\x00\x00\x00\x00\x13nc\xc0\x00\x00\x00\x00 u" + + "\xe4\xd0\x00\x00\x00\x00!\x81w@\x00\x00\x00\x00\"U\xc6\xd0\x00\x00\x00\x00#j\x93\xc0\x00\x00\x00\x00$5\xa8\xd0\x00\x00\x00\x00%Ju\xc0\x00\x00\x00\x00&\x15\x8a\xd0\x00\x00\x00\x00'*W\xc0\x00\x00" + + "\x00\x00'\xfe\xa7P\x00\x00\x00\x00)\n9\xc0\x00\x00\x00\x00)މP\x00\x00\x00\x00*\xea\x1b\xc0\x00\x00\x00\x00+\xbekP\x00\x00\x00\x00,\xd38@\x00\x00\x00\x00-\x9eMP\x00\x00\x00\x00.\xb3" + + "\x1a@\x00\x00\x00\x00/~/P\x00\x00\x00\x000\x92\xfc@\x00\x00\x00\x001gK\xd0\x00\x00\x00\x002r\xde@\x00\x00\x00\x003G-\xd0\x00\x00\x00\x004R\xc0@\x00\x00\x00\x005'\x0f\xd0\x00\x00" + + "\x00\x0062\xa2@\x00\x00\x00\x007\x06\xf1\xd0\x00\x00\x00\x008\x1b\xbe\xc0\x00\x00\x00\x008\xe6\xd3\xd0\x00\x00\x00\x009\xfb\xa0\xc0\x00\x00\x00\x00:Ƶ\xd0\x00\x00\x00\x00;ۂ\xc0\x00\x00\x00\x00<\xaf" + + "\xd2P\x00\x00\x00\x00=\xbbd\xc0\x00\x00\x00\x00>\x8f\xb4P\x00\x00\x00\x00?\x9bF\xc0\x00\x00\x00\x00@o\x96P\x00\x00\x00\x00A\x84c@\x00\x00\x00\x00BOxP\x00\x00\x00\x00CdE@\x00\x00" + + "\x00\x00D/ZP\x00\x00\x00\x00ED'@\x00\x00\x00\x00E\xf3\x8c\xd0\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x03\xff\xff\xcbX\x00\x00\xff\xff\xc7\xc0\x00\x04\xff\xff\xd5\xd0\x00\b\xff\xff\xe3\xe0\x01\fLMT\x00AST\x00-03\x00-02\x00\n<-03>3<-02>,M3" + + ".2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSB\xa0=:\x1e\x01\x00\x00\x1e\x01\x00\x00\x12\x00\x1c\x00America/Hermosill" + + "oUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\x05" + + "\x00\x00\x00\x14\xff\xff\xff\xff\xa5\xb6\xe8p\xff\xff\xff\xff\xaf\xf2n\xe0\xff\xff\xff\xff\xb6fV`\xff\xff\xff\xff\xb7C\xd2`\xff\xff\xff\xff\xb8\f6`\xff\xff\xff\xff\xb8\xfd\x86\xf0\xff\xff\xff\xff\xcb\xeaq`" + + "\xff\xff\xff\xffؑ\xb4\xf0\x00\x00\x00\x00\x00\x00p\x80\x00\x00\x00\x001g\x84\x10\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003Gf\x10\x00\x00\x00\x004R\xf8\x80\x00\x00\x00\x005'H\x10\x00\x00\x00\x00" + + "62ڀ\x01\x02\x01\x02\x01\x02\x01\x03\x01\x04\x01\x04\x01\x04\x01\xff\xff\x97\xf8\x00\x00\xff\xff\x9d\x90\x00\x04\xff\xff\xab\xa0\x00\b\xff\xff\x8f\x80\x00\f\xff\xff\xab\xa0\x01\x10LMT\x00MST\x00CST" + + "\x00PST\x00MDT\x00\nMST7\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS>\x14\xe7\x03\x83\x03\x00\x00\x83\x03\x00\x00\x0f\x00\x1c\x00America/Detroit" + + "UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00P\x00\x00\x00\x06\x00" + + "\x00\x00\x18\xff\xff\xff\xff\x85\xbd\"[\xff\xff\xff\xff\x99<\x94\x00\xff\xff\xff\xffˈ\xf0p\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xfb\xe0\xff\xff\xff\xff\xd75\xa8\xf0\xff\xff\xff\xff\xd8\x00\xa1\xe0\xff" + + "\xff\xff\xff\xfb3\x90\x8c\xff\xff\xff\xff\xfb\xe8;\xe0\xff\xff\xff\xff\xfc\xd8:\xf0\xff\xff\xff\xff\xfd\xc8\x1d\xe0\x00\x00\x00\x00\x06@\xdfp\x00\x00\x00\x00\a0\xc2`\x00\x00\x00\x00\a\x8d\x19p\x00\x00\x00\x00\t" + + "\x10\xa4`\x00\x00\x00\x00\n\x00\xa3p\x00\x00\x00\x00\n\xf0\x86`\x00\x00\x00\x00\v\xe0\x85p\x00\x00\x00\x00\f٢\xe0\x00\x00\x00\x00\r\xc0gp\x00\x00\x00\x00\x0e\xb9\x84\xe0\x00\x00\x00\x00\x0f\xa9\x83\xf0\x00" + + "\x00\x00\x00\x10\x99f\xe0\x00\x00\x00\x00\x11\x89e\xf0\x00\x00\x00\x00\x12yH\xe0\x00\x00\x00\x00\x13iG\xf0\x00\x00\x00\x00\x14Y*\xe0\x00\x00\x00\x00\x15I)\xf0\x00\x00\x00\x00\x169\f\xe0\x00\x00\x00\x00\x17" + + ")\v\xf0\x00\x00\x00\x00\x18\")`\x00\x00\x00\x00\x19\b\xed\xf0\x00\x00\x00\x00\x1a\x02\v`\x00\x00\x00\x00\x1a\xf2\np\x00\x00\x00\x00\x1b\xe1\xed`\x00\x00\x00\x00\x1c\xd1\xecp\x00\x00\x00\x00\x1d\xc1\xcf`\x00" + + "\x00\x00\x00\x1e\xb1\xcep\x00\x00\x00\x00\x1f\xa1\xb1`\x00\x00\x00\x00 v\x00\xf0\x00\x00\x00\x00!\x81\x93`\x00\x00\x00\x00\"U\xe2\xf0\x00\x00\x00\x00#j\xaf\xe0\x00\x00\x00\x00$5\xc4\xf0\x00\x00\x00\x00%" + + "J\x91\xe0\x00\x00\x00\x00&\x15\xa6\xf0\x00\x00\x00\x00'*s\xe0\x00\x00\x00\x00'\xfe\xc3p\x00\x00\x00\x00)\nU\xe0\x00\x00\x00\x00)ޥp\x00\x00\x00\x00*\xea7\xe0\x00\x00\x00\x00+\xbe\x87p\x00" + + "\x00\x00\x00,\xd3T`\x00\x00\x00\x00-\x9eip\x00\x00\x00\x00.\xb36`\x00\x00\x00\x00/~Kp\x00\x00\x00\x000\x93\x18`\x00\x00\x00\x001gg\xf0\x00\x00\x00\x002r\xfa`\x00\x00\x00\x003" + + "GI\xf0\x00\x00\x00\x004R\xdc`\x00\x00\x00\x005'+\xf0\x00\x00\x00\x0062\xbe`\x00\x00\x00\x007\a\r\xf0\x00\x00\x00\x008\x1b\xda\xe0\x00\x00\x00\x008\xe6\xef\xf0\x00\x00\x00\x009\xfb\xbc\xe0\x00" + + "\x00\x00\x00:\xc6\xd1\xf0\x00\x00\x00\x00;۞\xe0\x00\x00\x00\x00<\xaf\xeep\x00\x00\x00\x00=\xbb\x80\xe0\x00\x00\x00\x00>\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00A" + + "\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x01\x02\x03\x04\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02" + + "\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02" + + "\x05\x02\x05\xff\xff\xb2%\x00\x00\xff\xff\xab\xa0\x00\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x01\f\xff\xff\xc7\xc0\x01\x10\xff\xff\xc7\xc0\x01\x14LMT\x00CST\x00EST\x00EWT\x00EPT\x00E" + + "DT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb4\x11Z\xde\xe4\x01\x00\x00\xe4\x01\x00\x00\x11\x00\x1c\x00Ame" + + "rica/FortalezaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00'\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96\xaak\x18\xff\xff\xff\xff\xb8\x0fI\xe0\xff\xff\xff\xff\xb8\xfd@\xa0\xff\xff\xff\xff\xb9\xf140\xff\xff\xff\xff\xba\xdet \xff\xff\xff" + + "\xff\xda8\xae0\xff\xff\xff\xff\xda\xeb\xfa0\xff\xff\xff\xff\xdc\x19\xe1\xb0\xff\xff\xff\xffܹY \xff\xff\xff\xff\xdd\xfb\x150\xff\xff\xff\xffޛ\xde \xff\xff\xff\xff\xdfݚ0\xff\xff\xff\xff\xe0T3" + + " \xff\xff\xff\xff\xf4\x97\xff\xb0\xff\xff\xff\xff\xf5\x05^ \xff\xff\xff\xff\xf6\xc0d0\xff\xff\xff\xff\xf7\x0e\x1e\xa0\xff\xff\xff\xff\xf8Q,0\xff\xff\xff\xff\xf8\xc7\xc5 \xff\xff\xff\xff\xfa\nҰ\xff\xff\xff" + + "\xff\xfa\xa8\xf8\xa0\xff\xff\xff\xff\xfb\xec\x060\xff\xff\xff\xff\xfc\x8b}\xa0\x00\x00\x00\x00\x1dɎ0\x00\x00\x00\x00\x1exנ\x00\x00\x00\x00\x1f\xa05\xb0\x00\x00\x00\x00 3Ϡ\x00\x00\x00\x00!\x81i" + + "0\x00\x00\x00\x00\"\vȠ\x00\x00\x00\x00#X\x10\xb0\x00\x00\x00\x00#\xe2p \x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xd4\xc7 \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xb8\x85 \x00\x00\x00" + + "\x009\xdf\xe30\x00\x00\x00\x009\xf2J \x00\x00\x00\x00;\xc8\xff\xb0\x00\x00\x00\x003\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS" + + "$\r\x89l\xe4\x01\x00\x00\xe4\x01\x00\x00\x0f\x00\x1c\x00America/OjinagaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00T" + + "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00#\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\xa5\xb6\xe8p\xff\xff\xff\xff\xaf\xf2n\xe0\xff\xff\xff\xff\xb6fV`\xff\xff" + + "\xff\xff\xb7C\xd2`\xff\xff\xff\xff\xb8\f6`\xff\xff\xff\xff\xb8\xfd\x86\xf0\x00\x00\x00\x001gv\x00\x00\x00\x00\x002s\bp\x00\x00\x00\x003GX\x00\x00\x00\x00\x004R\xeap\x00\x00\x00\x005'" + + "H\x10\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe7\f\x10\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xf5\x12\x90\x00\x00\x00\x00;\xb6\xd1\x00\x00\x00" + + "\x00\x00<\xb0\n\x90\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8f\xec\x90\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@oΐ\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00BO\xb0\x90\x00\x00\x00\x00Cd" + + "}\x80\x00\x00\x00\x00D/\x92\x90\x00\x00\x00\x00ED_\x80\x00\x00\x00\x00F\x0ft\x90\x00\x00\x00\x00G$A\x80\x00\x00\x00\x00G\xf8\x91\x10\x00\x00\x00\x00I\x04#\x80\x00\x00\x00\x00I\xd8s\x10\x00\x00" + + "\x00\x00J\xe4\x05\x80\x00\x00\x00\x00K\x9c\xa5\x90\x01\x02\x01\x02\x01\x02\x03\x02\x03\x02\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\xff\xff\x9e\x1c\x00\x00\xff\xff\x9d\x90\x00" + + "\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xab\xa0\x01\x10LMT\x00MST\x00CST\x00CDT\x00MDT\x00\nMST7MDT,M3.2.0,M11.1" + + ".0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS5\x11Q\x06\xd1\x03\x00\x00\xd1\x03\x00\x00\x11\x00\x1c\x00America/AnchorageUT\t\x00\x03\x82\x0f\x8ba\x82" + + "\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00" + + "\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00T\x00\x00\x00\n\x00\x00\x00(\xff\xff\xff\xff?\xc2\xfd" + + "\xd1\xff\xff\xff\xff}\x87AH\xff\xff\xff\xffˉ6\xc0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2aB0\xff\xff\xff\xff\xfa\xd2G\xa0\xff\xff\xff\xff\xfe\xb8c@\xff\xff\xff\xff\xff\xa8F0\x00\x00\x00" + + "\x00\x00\x98E@\x00\x00\x00\x00\x01\x88(0\x00\x00\x00\x00\x02x'@\x00\x00\x00\x00\x03qD\xb0\x00\x00\x00\x00\x04aC\xc0\x00\x00\x00\x00\x05Q&\xb0\x00\x00\x00\x00\x06A%\xc0\x00\x00\x00\x00\a1\b" + + "\xb0\x00\x00\x00\x00\a\x8d_\xc0\x00\x00\x00\x00\t\x10\xea\xb0\x00\x00\x00\x00\t\xad\xdb@\x00\x00\x00\x00\n\xf0̰\x00\x00\x00\x00\v\xe0\xcb\xc0\x00\x00\x00\x00\f\xd9\xe90\x00\x00\x00\x00\r\xc0\xad\xc0\x00\x00\x00" + + "\x00\x0e\xb9\xcb0\x00\x00\x00\x00\x0f\xa9\xca@\x00\x00\x00\x00\x10\x99\xad0\x00\x00\x00\x00\x11\x89\xac@\x00\x00\x00\x00\x12y\x8f0\x00\x00\x00\x00\x13i\x8e@\x00\x00\x00\x00\x14Yq0\x00\x00\x00\x00\x15Ip" + + "@\x00\x00\x00\x00\x169S0\x00\x00\x00\x00\x17)R@\x00\x00\x00\x00\x18\"o\xb0\x00\x00\x00\x00\x19\t4@\x00\x00\x00\x00\x1a\x02Q\xb0\x00\x00\x00\x00\x1a+\x14\x10\x00\x00\x00\x00\x1a\xf2B\xb0\x00\x00\x00" + + "\x00\x1b\xe2%\xa0\x00\x00\x00\x00\x1c\xd2$\xb0\x00\x00\x00\x00\x1d\xc2\a\xa0\x00\x00\x00\x00\x1e\xb2\x06\xb0\x00\x00\x00\x00\x1f\xa1\xe9\xa0\x00\x00\x00\x00 v90\x00\x00\x00\x00!\x81ˠ\x00\x00\x00\x00\"V\x1b" + + "0\x00\x00\x00\x00#j\xe8 \x00\x00\x00\x00$5\xfd0\x00\x00\x00\x00%J\xca \x00\x00\x00\x00&\x15\xdf0\x00\x00\x00\x00'*\xac \x00\x00\x00\x00'\xfe\xfb\xb0\x00\x00\x00\x00)\n\x8e \x00\x00\x00" + + "\x00)\xdeݰ\x00\x00\x00\x00*\xeap \x00\x00\x00\x00+\xbe\xbf\xb0\x00\x00\x00\x00,ӌ\xa0\x00\x00\x00\x00-\x9e\xa1\xb0\x00\x00\x00\x00.\xb3n\xa0\x00\x00\x00\x00/~\x83\xb0\x00\x00\x00\x000\x93P" + + "\xa0\x00\x00\x00\x001g\xa00\x00\x00\x00\x002s2\xa0\x00\x00\x00\x003G\x820\x00\x00\x00\x004S\x14\xa0\x00\x00\x00\x005'd0\x00\x00\x00\x0062\xf6\xa0\x00\x00\x00\x007\aF0\x00\x00\x00" + + "\x008\x1c\x13 \x00\x00\x00\x008\xe7(0\x00\x00\x00\x009\xfb\xf5 \x00\x00\x00\x00:\xc7\n0\x00\x00\x00\x00;\xdb\xd7 \x00\x00\x00\x00<\xb0&\xb0\x00\x00\x00\x00=\xbb\xb9 \x00\x00\x00\x00>\x90\b" + + "\xb0\x00\x00\x00\x00?\x9b\x9b \x00\x00\x00\x00@o\xea\xb0\x00\x00\x00\x00A\x84\xb7\xa0\x00\x00\x00\x00BO̰\x00\x00\x00\x00Cd\x99\xa0\x00\x00\x00\x00D/\xae\xb0\x00\x00\x00\x00ED{\xa0\x00\x00\x00" + + "\x00E\xf3\xe10\x01\x02\x03\x04\x02\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\a\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t" + + "\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\x00\x00\xc4\xf8\x00\x00\xff\xffsx\x00\x00\xff\xffs`\x00\x04\xff\xff\x81p\x01\b\xff\xff\x81p\x01\f\xff" + + "\xffs`\x00\x10\xff\xff\x81p\x01\x15\xff\xff\x81p\x00\x1a\xff\xff\x8f\x80\x01\x1e\xff\xff\x81p\x00#LMT\x00AST\x00AWT\x00APT\x00AHST\x00AHDT\x00YST\x00A" + + "KDT\x00AKST\x00\nAKST9AKDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSU9#\xbe2\x05\x00\x002\x05\x00" + + "\x00\x11\x00\x1c\x00America/VancouverUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x81\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff^=v\xec\xff\xff\xff\xff\x9e\xb8\xbd\xa0\xff\xff\xff\xff\x9f\xbb\x15\x90\xff\xff\xff\xffˉ\x1a\xa0\xff\xff\xff" + + "\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a&\x10\xff\xff\xff\xff\xd3v\x0f \xff\xff\xff\xff\xd4A\b\x10\xff\xff\xff\xff\xd5U\xf1 \xff\xff\xff\xff\xd6 \xea\x10\xff\xff\xff\xff\xd75\xd3 \xff\xff\xff\xff\xd8\x00\xcc" + + "\x10\xff\xff\xff\xff\xd9\x15\xb5 \xff\xff\xff\xff\xd9\xe0\xae\x10\xff\xff\xff\xff\xda\xfeѠ\xff\xff\xff\xff\xdb\xc0\x90\x10\xff\xff\xff\xff\xdc\u07b3\xa0\xff\xff\xff\xffݩ\xac\x90\xff\xff\xff\xff\u07be\x95\xa0\xff\xff\xff" + + "\xff߉\x8e\x90\xff\xff\xff\xff\xe0\x9ew\xa0\xff\xff\xff\xff\xe1ip\x90\xff\xff\xff\xff\xe2~Y\xa0\xff\xff\xff\xff\xe3IR\x90\xff\xff\xff\xff\xe4^;\xa0\xff\xff\xff\xff\xe5)4\x90\xff\xff\xff\xff\xe6GX" + + " \xff\xff\xff\xff\xe7\x12Q\x10\xff\xff\xff\xff\xe8': \xff\xff\xff\xff\xe8\xf23\x10\xff\xff\xff\xff\xea\a\x1c \xff\xff\xff\xff\xea\xd2\x15\x10\xff\xff\xff\xff\xeb\xe6\xfe \xff\xff\xff\xff\xec\xb1\xf7\x10\xff\xff\xff" + + "\xff\xed\xc6\xe0 \xff\xff\xff\xff\xee\x91\xd9\x10\xff\xff\xff\xff\xef\xaf\xfc\xa0\xff\xff\xff\xff\xf0q\xbb\x10\xff\xff\xff\xff\xf1\x8fޠ\xff\xff\xff\xff\xf2\u007f\xc1\x90\xff\xff\xff\xff\xf3o\xc0\xa0\xff\xff\xff\xff\xf4_\xa3" + + "\x90\xff\xff\xff\xff\xf5O\xa2\xa0\xff\xff\xff\xff\xf6?\x85\x90\xff\xff\xff\xff\xf7/\x84\xa0\xff\xff\xff\xff\xf8(\xa2\x10\xff\xff\xff\xff\xf9\x0ff\xa0\xff\xff\xff\xff\xfa\b\x84\x10\xff\xff\xff\xff\xfa\xf8\x83 \xff\xff\xff" + + "\xff\xfb\xe8f\x10\xff\xff\xff\xff\xfc\xd8e \xff\xff\xff\xff\xfd\xc8H\x10\xff\xff\xff\xff\xfe\xb8G \xff\xff\xff\xff\xff\xa8*\x10\x00\x00\x00\x00\x00\x98) \x00\x00\x00\x00\x01\x88\f\x10\x00\x00\x00\x00\x02x\v" + + " \x00\x00\x00\x00\x03q(\x90\x00\x00\x00\x00\x04a'\xa0\x00\x00\x00\x00\x05Q\n\x90\x00\x00\x00\x00\x06A\t\xa0\x00\x00\x00\x00\a0\xec\x90\x00\x00\x00\x00\b \xeb\xa0\x00\x00\x00\x00\t\x10ΐ\x00\x00\x00" + + "\x00\n\x00͠\x00\x00\x00\x00\n\xf0\xb0\x90\x00\x00\x00\x00\v\u0be0\x00\x00\x00\x00\f\xd9\xcd\x10\x00\x00\x00\x00\r\xc0\x91\xa0\x00\x00\x00\x00\x0e\xb9\xaf\x10\x00\x00\x00\x00\x0f\xa9\xae \x00\x00\x00\x00\x10\x99\x91" + + "\x10\x00\x00\x00\x00\x11\x89\x90 \x00\x00\x00\x00\x12ys\x10\x00\x00\x00\x00\x13ir \x00\x00\x00\x00\x14YU\x10\x00\x00\x00\x00\x15IT \x00\x00\x00\x00\x1697\x10\x00\x00\x00\x00\x17)6 \x00\x00\x00" + + "\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18 \x00\x00\x00\x00\x1a\x025\x90\x00\x00\x00\x00\x1a\xf24\xa0\x00\x00\x00\x00\x1b\xe2\x17\x90\x00\x00\x00\x00\x1c\xd2\x16\xa0\x00\x00\x00\x00\x1d\xc1\xf9\x90\x00\x00\x00\x00\x1e\xb1\xf8" + + "\xa0\x00\x00\x00\x00\x1f\xa1ې\x00\x00\x00\x00 v+ \x00\x00\x00\x00!\x81\xbd\x90\x00\x00\x00\x00\"V\r \x00\x00\x00\x00#j\xda\x10\x00\x00\x00\x00$5\xef \x00\x00\x00\x00%J\xbc\x10\x00\x00\x00" + + "\x00&\x15\xd1 \x00\x00\x00\x00'*\x9e\x10\x00\x00\x00\x00'\xfe\xed\xa0\x00\x00\x00\x00)\n\x80\x10\x00\x00\x00\x00)\xdeϠ\x00\x00\x00\x00*\xeab\x10\x00\x00\x00\x00+\xbe\xb1\xa0\x00\x00\x00\x00,\xd3~" + + "\x90\x00\x00\x00\x00-\x9e\x93\xa0\x00\x00\x00\x00.\xb3`\x90\x00\x00\x00\x00/~u\xa0\x00\x00\x00\x000\x93B\x90\x00\x00\x00\x001g\x92 \x00\x00\x00\x002s$\x90\x00\x00\x00\x003Gt \x00\x00\x00" + + "\x004S\x06\x90\x00\x00\x00\x005'V \x00\x00\x00\x0062\xe8\x90\x00\x00\x00\x007\a8 \x00\x00\x00\x008\x1c\x05\x10\x00\x00\x00\x008\xe7\x1a \x00\x00\x00\x009\xfb\xe7\x10\x00\x00\x00\x00:\xc6\xfc" + + " \x00\x00\x00\x00;\xdb\xc9\x10\x00\x00\x00\x00<\xb0\x18\xa0\x00\x00\x00\x00=\xbb\xab\x10\x00\x00\x00\x00>\x8f\xfa\xa0\x00\x00\x00\x00?\x9b\x8d\x10\x00\x00\x00\x00@oܠ\x00\x00\x00\x00A\x84\xa9\x90\x00\x00\x00" + + "\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b\x90\x00\x00\x00\x00D/\xa0\xa0\x00\x00\x00\x00EDm\x90\x00\x00\x00\x00E\xf3\xd3 \x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xa4\xec\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff" + - "\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10LMT\x00CDT\x00CST\x00CWT\x00CPT\x00\nCST6CDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00" + - "\x00\x00\x00\x00\xf1c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00\x00\x00\x10\x00\x1c\x00America/AnguillaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8" + - "\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00T" + - "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x9373\xac\x01\xff\xff\xc6T\x00\x00\xff\xff" + - "\xc7\xc0\x00\x04LMT\x00AST\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RŒZ\x8c\xc4\x02\x00\x00\xc4\x02\x00\x00\x0f\x00\x1c\x00America/Mend" + - "ozaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00" + - "\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xb2\x04\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17" + - "}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff" + - "\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0" + - "\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff" + - "\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4" + - "w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00" + - "\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'\x194@\x00\x00\x00\x00'\xcdð\x00\x00\x00\x00(\xfa" + - "g\xc0\x00\x00\x00\x00)\xb0H\xb0\x00\x00\x00\x00*\xe0\xe1@\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00@\xb0\x13\xb0\x00\x00\x00\x00AV>\xc0\x00\x00" + - "\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04" + - "\x05\x04\x02\x03\x02\x03\x02\x04\x05\x03\x05\x02\x05\x04\x05\xff\xff\xbf|\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-" + - "04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x04,2h\x99\x01\x00\x00\x99\x01\x00\x00\x10\x00\x1c\x00America/San" + - "taremUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1e" + - "\x00\x00\x00\x04\x00\x00\x00\f\xff\xff\xff\xff\x96\xaazH\xff\xff\xff\xff\xb8\x0fW\xf0\xff\xff\xff\xff\xb8\xfdN\xb0\xff\xff\xff\xff\xb9\xf1B@\xff\xff\xff\xff\xbaނ0\xff\xff\xff\xff\xda8\xbc@\xff\xff\xff\xff" + - "\xda\xec\b@\xff\xff\xff\xff\xdc\x19\xef\xc0\xff\xff\xff\xffܹg0\xff\xff\xff\xff\xdd\xfb#@\xff\xff\xff\xffޛ\xec0\xff\xff\xff\xff\xdfݨ@\xff\xff\xff\xff\xe0TA0\xff\xff\xff\xff\xf4\x98\r\xc0" + - "\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf6\xc0r@\xff\xff\xff\xff\xf7\x0e,\xb0\xff\xff\xff\xff\xf8Q:@\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xfa\n\xe0\xc0\xff\xff\xff\xff\xfa\xa9\x06\xb0\xff\xff\xff\xff" + - "\xfb\xec\x14@\xff\xff\xff\xff\xfc\x8b\x8b\xb0\x00\x00\x00\x00\x1dɜ@\x00\x00\x00\x00\x1ex\xe5\xb0\x00\x00\x00\x00\x1f\xa0C\xc0\x00\x00\x00\x00 3ݰ\x00\x00\x00\x00!\x81w@\x00\x00\x00\x00\"\vְ" + - "\x00\x00\x00\x00H`q@\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\xff\xff̸\x00\x00\xff\xff\xd5\xd0\x01\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0" + - "\x00\x04LMT\x00-03\x00-04\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00\x00\x00\x10\x00\x1c\x00America/" + - "St_LuciaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x9373\xac\x01\xff\xff\xc6T\x00\x00\xff\xff\xc7\xc0\x00\x04LMT\x00AST\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R" + - "Ծ\xe7#\x95\x00\x00\x00\x95\x00\x00\x00\x0e\x00\x1c\x00America/CaymanUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZ" + - "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xffi\x87&\x10\xff\xff\xff\xff\x8b\xf4a\xe8\x01\x02\xff\xff\xb5p\x00\x00\xff\xff\xb5" + - "\x18\x00\x04\xff\xff\xb9\xb0\x00\bLMT\x00CMT\x00EST\x00\nEST5\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rp\x1b\xceRC\x03\x00\x00C\x03\x00\x00\x0f\x00\x1c\x00Ame" + - "rica/NipigonUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00J\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xffr\xee\x81@\xff\xff\xff\xff\x9e\xb8\x93p\xff\xff\xff\xff\x9f\xba\xeb`\xff\xff\xff\xff\xc8\xf8IP\xff\xff\xff\xffˈ\xf0p\xff\xff\xff\xff\xd2" + - "#\xf4p\xff\xff\xff\xff\xd2`\xfb\xe0\x00\x00\x00\x00\b \xc1p\x00\x00\x00\x00\t\x10\xa4`\x00\x00\x00\x00\n\x00\xa3p\x00\x00\x00\x00\n\xf0\x86`\x00\x00\x00\x00\v\xe0\x85p\x00\x00\x00\x00\f٢\xe0\x00" + - "\x00\x00\x00\r\xc0gp\x00\x00\x00\x00\x0e\xb9\x84\xe0\x00\x00\x00\x00\x0f\xa9\x83\xf0\x00\x00\x00\x00\x10\x99f\xe0\x00\x00\x00\x00\x11\x89e\xf0\x00\x00\x00\x00\x12yH\xe0\x00\x00\x00\x00\x13iG\xf0\x00\x00\x00\x00\x14" + - "Y*\xe0\x00\x00\x00\x00\x15I)\xf0\x00\x00\x00\x00\x169\f\xe0\x00\x00\x00\x00\x17)\v\xf0\x00\x00\x00\x00\x18\")`\x00\x00\x00\x00\x19\b\xed\xf0\x00\x00\x00\x00\x1a\x02\v`\x00\x00\x00\x00\x1a\xf2\np\x00" + - "\x00\x00\x00\x1b\xe1\xed`\x00\x00\x00\x00\x1c\xd1\xecp\x00\x00\x00\x00\x1d\xc1\xcf`\x00\x00\x00\x00\x1e\xb1\xcep\x00\x00\x00\x00\x1f\xa1\xb1`\x00\x00\x00\x00 v\x00\xf0\x00\x00\x00\x00!\x81\x93`\x00\x00\x00\x00\"" + - "U\xe2\xf0\x00\x00\x00\x00#j\xaf\xe0\x00\x00\x00\x00$5\xc4\xf0\x00\x00\x00\x00%J\x91\xe0\x00\x00\x00\x00&\x15\xa6\xf0\x00\x00\x00\x00'*s\xe0\x00\x00\x00\x00'\xfe\xc3p\x00\x00\x00\x00)\nU\xe0\x00" + - "\x00\x00\x00)ޥp\x00\x00\x00\x00*\xea7\xe0\x00\x00\x00\x00+\xbe\x87p\x00\x00\x00\x00,\xd3T`\x00\x00\x00\x00-\x9eip\x00\x00\x00\x00.\xb36`\x00\x00\x00\x00/~Kp\x00\x00\x00\x000" + - "\x93\x18`\x00\x00\x00\x001gg\xf0\x00\x00\x00\x002r\xfa`\x00\x00\x00\x003GI\xf0\x00\x00\x00\x004R\xdc`\x00\x00\x00\x005'+\xf0\x00\x00\x00\x0062\xbe`\x00\x00\x00\x007\a\r\xf0\x00" + - "\x00\x00\x008\x1b\xda\xe0\x00\x00\x00\x008\xe6\xef\xf0\x00\x00\x00\x009\xfb\xbc\xe0\x00\x00\x00\x00:\xc6\xd1\xf0\x00\x00\x00\x00;۞\xe0\x00\x00\x00\x00<\xaf\xeep\x00\x00\x00\x00=\xbb\x80\xe0\x00\x00\x00\x00>" + - "\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00" + - "\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xad@\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x01\f\xff\xff\xc7\xc0\x01\x10LMT\x00EDT\x00E" + - "ST\x00EWT\x00EPT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RV\x80\x94@\x12\x04\x00\x00\x12\x04\x00" + - "\x00\x0e\x00\x1c\x00America/DenverUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00a\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff^\x04\f\xb0\xff\xff\xff\xff\x9e\xa6:\x90\xff\xff\xff\xff\x9f\xbb\a\x80\xff\xff\xff\xff\xa0\x86\x1c\x90\xff\xff\xff\xff\xa1\x9a" + - "\xe9\x80\xff\xff\xff\xff\xa2e\xfe\x90\xff\xff\xff\xff\xa3\x84\x06\x00\xff\xff\xff\xff\xa4E\xe0\x90\xff\xff\xff\xff\xa4\x8f\xa6\x80\xff\xff\xff\xffˉ\f\x90\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff" + - "\xff\xff\xf7/v\x90\xff\xff\xff\xff\xf8(\x94\x00\xff\xff\xff\xff\xf9\x0fX\x90\xff\xff\xff\xff\xfa\bv\x00\xff\xff\xff\xff\xfa\xf8u\x10\xff\xff\xff\xff\xfb\xe8X\x00\xff\xff\xff\xff\xfc\xd8W\x10\xff\xff\xff\xff\xfd\xc8" + - ":\x00\xff\xff\xff\xff\xfe\xb89\x10\xff\xff\xff\xff\xff\xa8\x1c\x00\x00\x00\x00\x00\x00\x98\x1b\x10\x00\x00\x00\x00\x01\x87\xfe\x00\x00\x00\x00\x00\x02w\xfd\x10\x00\x00\x00\x00\x03q\x1a\x80\x00\x00\x00\x00\x04a\x19\x90\x00\x00" + - "\x00\x00\x05P\xfc\x80\x00\x00\x00\x00\x06@\xfb\x90\x00\x00\x00\x00\a0ހ\x00\x00\x00\x00\a\x8d5\x90\x00\x00\x00\x00\t\x10\xc0\x80\x00\x00\x00\x00\t\xad\xb1\x10\x00\x00\x00\x00\n\xf0\xa2\x80\x00\x00\x00\x00\v\xe0" + - "\xa1\x90\x00\x00\x00\x00\fٿ\x00\x00\x00\x00\x00\r\xc0\x83\x90\x00\x00\x00\x00\x0e\xb9\xa1\x00\x00\x00\x00\x00\x0f\xa9\xa0\x10\x00\x00\x00\x00\x10\x99\x83\x00\x00\x00\x00\x00\x11\x89\x82\x10\x00\x00\x00\x00\x12ye\x00\x00\x00" + - "\x00\x00\x13id\x10\x00\x00\x00\x00\x14YG\x00\x00\x00\x00\x00\x15IF\x10\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17)(\x10\x00\x00\x00\x00\x18\"E\x80\x00\x00\x00\x00\x19\t\n\x10\x00\x00\x00\x00\x1a\x02" + - "'\x80\x00\x00\x00\x00\x1a\xf2&\x90\x00\x00\x00\x00\x1b\xe2\t\x80\x00\x00\x00\x00\x1c\xd2\b\x90\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1\xea\x90\x00\x00\x00\x00\x1f\xa1̀\x00\x00\x00\x00 v\x1d\x10\x00\x00" + - "\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xff\x10\x00\x00\x00\x00#j\xcc\x00\x00\x00\x00\x00$5\xe1\x10\x00\x00\x00\x00%J\xae\x00\x00\x00\x00\x00&\x15\xc3\x10\x00\x00\x00\x00'*\x90\x00\x00\x00\x00\x00'\xfe" + - "ߐ\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\xde\xc1\x90\x00\x00\x00\x00*\xeaT\x00\x00\x00\x00\x00+\xbe\xa3\x90\x00\x00\x00\x00,\xd3p\x80\x00\x00\x00\x00-\x9e\x85\x90\x00\x00\x00\x00.\xb3R\x80\x00\x00" + - "\x00\x00/~g\x90\x00\x00\x00\x000\x934\x80\x00\x00\x00\x001g\x84\x10\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003Gf\x10\x00\x00\x00\x004R\xf8\x80\x00\x00\x00\x005'H\x10\x00\x00\x00\x0062" + - "ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe7\f\x10\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xc6\xee\x10\x00\x00\x00\x00;ۻ\x00\x00\x00\x00\x00<\xb0\n\x90\x00\x00" + - "\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8f\xec\x90\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@oΐ\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00BO\xb0\x90\x00\x00\x00\x00Cd}\x80\x00\x00\x00\x00D/" + - "\x92\x90\x00\x00\x00\x00ED_\x80\x00\x00\x00\x00E\xf3\xc5\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\x9d\x94\x00" + - "\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\f\xff\xff\xab\xa0\x01\x10LMT\x00MDT\x00MST\x00MWT\x00MPT\x00\nMST7MDT,M3.2.0" + - ",M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R+\x10`ȫ\x02\x00\x00\xab\x02\x00\x00\x14\x00\x1c\x00America/Dawson_CreekU" + - "T\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00:\x00\x00\x00\x06\x00\x00" + - "\x00\x18\xff\xff\xff\xff^=t8\xff\xff\xff\xff\x9e\xb8\xbd\xa0\xff\xff\xff\xff\x9f\xbb\x15\x90\xff\xff\xff\xffˉ\x1a\xa0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a&\x10\xff\xff\xff\xff\xd5U\xf1 \xff\xff" + - "\xff\xff\xd6 \xea\x10\xff\xff\xff\xff\xd75\xd3 \xff\xff\xff\xff\xd8\x00\xcc\x10\xff\xff\xff\xff\xd9\x15\xb5 \xff\xff\xff\xff\xd9\xe0\xae\x10\xff\xff\xff\xff\xda\xfeѠ\xff\xff\xff\xff\xdb\xc0\x90\x10\xff\xff\xff\xff\xdc\xde" + - "\xb3\xa0\xff\xff\xff\xffݩ\xac\x90\xff\xff\xff\xff\u07be\x95\xa0\xff\xff\xff\xff߉\x8e\x90\xff\xff\xff\xff\xe0\x9ew\xa0\xff\xff\xff\xff\xe1ip\x90\xff\xff\xff\xff\xe2~Y\xa0\xff\xff\xff\xff\xe3IR\x90\xff\xff" + - "\xff\xff\xe4^;\xa0\xff\xff\xff\xff\xe5)4\x90\xff\xff\xff\xff\xe6GX \xff\xff\xff\xff\xe7\x12Q\x10\xff\xff\xff\xff\xe8': \xff\xff\xff\xff\xe8\xf23\x10\xff\xff\xff\xff\xea\a\x1c \xff\xff\xff\xff\xea\xd2" + - "\x15\x10\xff\xff\xff\xff\xeb\xe6\xfe \xff\xff\xff\xff\xec\xb1\xf7\x10\xff\xff\xff\xff\xed\xc6\xe0 \xff\xff\xff\xff\xee\x91\xd9\x10\xff\xff\xff\xff\xef\xaf\xfc\xa0\xff\xff\xff\xff\xf0q\xbb\x10\xff\xff\xff\xff\xf1\x8fޠ\xff\xff" + - "\xff\xff\xf2\u007f\xc1\x90\xff\xff\xff\xff\xf3o\xc0\xa0\xff\xff\xff\xff\xf4_\xa3\x90\xff\xff\xff\xff\xf5O\xa2\xa0\xff\xff\xff\xff\xf6?\x85\x90\xff\xff\xff\xff\xf7/\x84\xa0\xff\xff\xff\xff\xf8(\xa2\x10\xff\xff\xff\xff\xf9\x0f" + - "f\xa0\xff\xff\xff\xff\xfa\b\x84\x10\xff\xff\xff\xff\xfa\xf8\x83 \xff\xff\xff\xff\xfb\xe8f\x10\xff\xff\xff\xff\xfc\xd8e \xff\xff\xff\xff\xfd\xc8H\x10\xff\xff\xff\xff\xfe\xb8G \xff\xff\xff\xff\xff\xa8*\x10\x00\x00" + - "\x00\x00\x00\x98) \x00\x00\x00\x00\x01\x88\f\x10\x00\x00\x00\x00\x02x\v \x00\x00\x00\x00\x03q(\x90\x00\x00\x00\x00\x04a'\xa0\x00\x00\x00\x00\x05\x01\xf0\x90\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x05\xff\xff\x8fH\x00\x00\xff\xff\x9d\x90\x01\x04\xff\xff\x8f\x80" + - "\x00\b\xff\xff\x9d\x90\x01\f\xff\xff\x9d\x90\x01\x10\xff\xff\x9d\x90\x00\x14LMT\x00PDT\x00PST\x00PWT\x00PPT\x00MST\x00\nMST7\nPK\x03\x04\n\x00\x00\x00\x00\x00" + - "\xf1c9R\xe90T\x16\xd1\x01\x00\x00\xd1\x01\x00\x00\f\x00\x1c\x00America/NuukUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00" + - "TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\"\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x9b\x80h\x00\x00\x00\x00\x00\x13M|P\x00\x00\x00\x00\x143\xfa\x90\x00" + - "\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b" + - "\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00" + - "\x00\x00\x00#3<-02>,M3.5.0/-2,M10.5.0/-1\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xf2" + - "\x04\xde\xdd\x11\x02\x00\x00\x11\x02\x00\x00\x0e\x00\x1c\x00America/CancunUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZi" + - "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00*\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\xa5\xb6\xda`\x00\x00\x00\x00\x16\x86\xd5`\x00\x00\x00\x001gg\xf0\x00\x00\x00\x00" + - "2r\xfa`\x00\x00\x00\x003GI\xf0\x00\x00\x00\x004R\xdc`\x00\x00\x00\x005'+\xf0\x00\x00\x00\x005\xc4\x00`\x00\x00\x00\x0062\xccp\x00\x00\x00\x007\a\x1c\x00\x00\x00\x00\x008\x1b\xe8\xf0" + - "\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xca\xf0\x00\x00\x00\x00:\xf5\x04\x80\x00\x00\x00\x00;\xb6\xc2\xf0\x00\x00\x00\x00<\xaf\xfc\x80\x00\x00\x00\x00=\xbb\x8e\xf0\x00\x00\x00\x00>\x8fހ\x00\x00\x00\x00" + - "?\x9bp\xf0\x00\x00\x00\x00@o\xc0\x80\x00\x00\x00\x00A\x84\x8dp\x00\x00\x00\x00BO\xa2\x80\x00\x00\x00\x00Cdop\x00\x00\x00\x00D/\x84\x80\x00\x00\x00\x00EDQp\x00\x00\x00\x00F\x0ff\x80" + - "\x00\x00\x00\x00G$3p\x00\x00\x00\x00G\xf8\x83\x00\x00\x00\x00\x00I\x04\x15p\x00\x00\x00\x00I\xd8e\x00\x00\x00\x00\x00J\xe3\xf7p\x00\x00\x00\x00K\xb8G\x00\x00\x00\x00\x00L\xcd\x13\xf0\x00\x00\x00\x00" + - "M\x98)\x00\x00\x00\x00\x00N\xac\xf5\xf0\x00\x00\x00\x00Ox\v\x00\x00\x00\x00\x00P\x8c\xd7\xf0\x00\x00\x00\x00Qa'\x80\x00\x00\x00\x00Rl\xb9\xf0\x00\x00\x00\x00SA\t\x80\x00\x00\x00\x00TL\x9b\xf0" + - "\x00\x00\x00\x00T\xcd\xdd\x00\x01\x03\x02\x03\x02\x03\x02\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x03\xff\xff\xae\xa8\x00\x00\xff\xff\xab\xa0" + - "\x00\x04\xff\xff\xc7\xc0\x01\b\xff\xff\xb9\xb0\x00\f\xff\xff\xb9\xb0\x01\x10LMT\x00CST\x00EDT\x00EST\x00CDT\x00\nEST5\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R" + - "n\xab\xd5\xf9\xcf\x03\x00\x00\xcf\x03\x00\x00\f\x00\x1c\x00America/NomeUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif" + - "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00T\x00\x00\x00\n\x00\x00\x00&\xff\xff\xff\xff?\xc2\xfd\xd1\xff\xff\xff\xff}\x87O\xd2\xff\xff\xff\xffˉD\xd0\xff\xff\xff\xff\xd2" + - "#\xf4p\xff\xff\xff\xff\xd2aP@\xff\xff\xff\xff\xfa\xd2U\xb0\xff\xff\xff\xff\xfe\xb8qP\xff\xff\xff\xff\xff\xa8T@\x00\x00\x00\x00\x00\x98SP\x00\x00\x00\x00\x01\x886@\x00\x00\x00\x00\x02x5P\x00" + - "\x00\x00\x00\x03qR\xc0\x00\x00\x00\x00\x04aQ\xd0\x00\x00\x00\x00\x05Q4\xc0\x00\x00\x00\x00\x06A3\xd0\x00\x00\x00\x00\a1\x16\xc0\x00\x00\x00\x00\a\x8dm\xd0\x00\x00\x00\x00\t\x10\xf8\xc0\x00\x00\x00\x00\t" + - "\xad\xe9P\x00\x00\x00\x00\n\xf0\xda\xc0\x00\x00\x00\x00\v\xe0\xd9\xd0\x00\x00\x00\x00\f\xd9\xf7@\x00\x00\x00\x00\r\xc0\xbb\xd0\x00\x00\x00\x00\x0e\xb9\xd9@\x00\x00\x00\x00\x0f\xa9\xd8P\x00\x00\x00\x00\x10\x99\xbb@\x00" + - "\x00\x00\x00\x11\x89\xbaP\x00\x00\x00\x00\x12y\x9d@\x00\x00\x00\x00\x13i\x9cP\x00\x00\x00\x00\x14Y\u007f@\x00\x00\x00\x00\x15I~P\x00\x00\x00\x00\x169a@\x00\x00\x00\x00\x17)`P\x00\x00\x00\x00\x18" + - "\"}\xc0\x00\x00\x00\x00\x19\tBP\x00\x00\x00\x00\x1a\x02_\xc0\x00\x00\x00\x00\x1a+\x14\x10\x00\x00\x00\x00\x1a\xf2B\xb0\x00\x00\x00\x00\x1b\xe2%\xa0\x00\x00\x00\x00\x1c\xd2$\xb0\x00\x00\x00\x00\x1d\xc2\a\xa0\x00" + - "\x00\x00\x00\x1e\xb2\x06\xb0\x00\x00\x00\x00\x1f\xa1\xe9\xa0\x00\x00\x00\x00 v90\x00\x00\x00\x00!\x81ˠ\x00\x00\x00\x00\"V\x1b0\x00\x00\x00\x00#j\xe8 \x00\x00\x00\x00$5\xfd0\x00\x00\x00\x00%" + - "J\xca \x00\x00\x00\x00&\x15\xdf0\x00\x00\x00\x00'*\xac \x00\x00\x00\x00'\xfe\xfb\xb0\x00\x00\x00\x00)\n\x8e \x00\x00\x00\x00)\xdeݰ\x00\x00\x00\x00*\xeap \x00\x00\x00\x00+\xbe\xbf\xb0\x00" + - "\x00\x00\x00,ӌ\xa0\x00\x00\x00\x00-\x9e\xa1\xb0\x00\x00\x00\x00.\xb3n\xa0\x00\x00\x00\x00/~\x83\xb0\x00\x00\x00\x000\x93P\xa0\x00\x00\x00\x001g\xa00\x00\x00\x00\x002s2\xa0\x00\x00\x00\x003" + - "G\x820\x00\x00\x00\x004S\x14\xa0\x00\x00\x00\x005'd0\x00\x00\x00\x0062\xf6\xa0\x00\x00\x00\x007\aF0\x00\x00\x00\x008\x1c\x13 \x00\x00\x00\x008\xe7(0\x00\x00\x00\x009\xfb\xf5 \x00" + - "\x00\x00\x00:\xc7\n0\x00\x00\x00\x00;\xdb\xd7 \x00\x00\x00\x00<\xb0&\xb0\x00\x00\x00\x00=\xbb\xb9 \x00\x00\x00\x00>\x90\b\xb0\x00\x00\x00\x00?\x9b\x9b \x00\x00\x00\x00@o\xea\xb0\x00\x00\x00\x00A" + - "\x84\xb7\xa0\x00\x00\x00\x00BO̰\x00\x00\x00\x00Cd\x99\xa0\x00\x00\x00\x00D/\xae\xb0\x00\x00\x00\x00ED{\xa0\x00\x00\x00\x00E\xf3\xe10\x01\x02\x03\x04\x02\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06" + - "\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\a\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t" + - "\b\t\b\t\b\t\b\x00\x00\xb6n\x00\x00\xff\xffd\xee\x00\x00\xff\xffeP\x00\x04\xff\xffs`\x01\b\xff\xffs`\x01\f\xff\xffeP\x00\x10\xff\xffs`\x01\x14\xff\xff\x81p\x00\x18\xff\xff\x8f\x80\x01" + - "\x1c\xff\xff\x81p\x00!LMT\x00NST\x00NWT\x00NPT\x00BST\x00BDT\x00YST\x00AKDT\x00AKST\x00\nAKST9AKDT,M3.2" + - ".0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R,\xdb~\xab\xb2\x03\x00\x00\xb2\x03\x00\x00\x0f\x00\x1c\x00America/YakutatUT\t\x00" + - "\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00S\x00\x00\x00\b\x00\x00\x00\x1e\xff" + - "\xff\xff\xff?\xc2\xfd\xd1\xff\xff\xff\xff}\x877\xbf\xff\xff\xff\xffˉ(\xb0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a4 \xff\xff\xff\xff\xfe\xb8U0\xff\xff\xff\xff\xff\xa88 \x00\x00\x00\x00\x00" + - "\x9870\x00\x00\x00\x00\x01\x88\x1a \x00\x00\x00\x00\x02x\x190\x00\x00\x00\x00\x03q6\xa0\x00\x00\x00\x00\x04a5\xb0\x00\x00\x00\x00\x05Q\x18\xa0\x00\x00\x00\x00\x06A\x17\xb0\x00\x00\x00\x00\a0\xfa\xa0\x00" + - "\x00\x00\x00\a\x8dQ\xb0\x00\x00\x00\x00\t\x10ܠ\x00\x00\x00\x00\t\xad\xcd0\x00\x00\x00\x00\n\xf0\xbe\xa0\x00\x00\x00\x00\v\u0f70\x00\x00\x00\x00\f\xd9\xdb \x00\x00\x00\x00\r\xc0\x9f\xb0\x00\x00\x00\x00\x0e" + - "\xb9\xbd \x00\x00\x00\x00\x0f\xa9\xbc0\x00\x00\x00\x00\x10\x99\x9f \x00\x00\x00\x00\x11\x89\x9e0\x00\x00\x00\x00\x12y\x81 \x00\x00\x00\x00\x13i\x800\x00\x00\x00\x00\x14Yc \x00\x00\x00\x00\x15Ib0\x00" + - "\x00\x00\x00\x169E \x00\x00\x00\x00\x17)D0\x00\x00\x00\x00\x18\"a\xa0\x00\x00\x00\x00\x19\t&0\x00\x00\x00\x00\x1a\x02C\xa0\x00\x00\x00\x00\x1a+\x14\x10\x00\x00\x00\x00\x1a\xf2B\xb0\x00\x00\x00\x00\x1b" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\x8c\x94\x00\x00\xff\xff\x9d\x90\x01\x04\xff\xff" + + "\x8f\x80\x00\b\xff\xff\x9d\x90\x01\f\xff\xff\x9d\x90\x01\x10LMT\x00PDT\x00PST\x00PWT\x00PPT\x00\nPST8PDT,M3.2.0,M11.1.0\n" + + "PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSg\xf5K\x89\xa2\x01\x00\x00\xa2\x01\x00\x00\x12\x00\x1c\x00America/Porto_AcreUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8b" + + "aux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01" + + "\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x00\x00\x00\x04\x00\x00\x00\f\xff\xff\xff\xff\x96\xaa\x86\x90\xff" + + "\xff\xff\xff\xb8\x0ff\x00\xff\xff\xff\xff\xb8\xfd\\\xc0\xff\xff\xff\xff\xb9\xf1PP\xff\xff\xff\xff\xbaސ@\xff\xff\xff\xff\xda8\xcaP\xff\xff\xff\xff\xda\xec\x16P\xff\xff\xff\xff\xdc\x19\xfd\xd0\xff\xff\xff\xff\xdc" + + "\xb9u@\xff\xff\xff\xff\xdd\xfb1P\xff\xff\xff\xffޛ\xfa@\xff\xff\xff\xff\xdfݶP\xff\xff\xff\xff\xe0TO@\xff\xff\xff\xff\xf4\x98\x1b\xd0\xff\xff\xff\xff\xf5\x05z@\xff\xff\xff\xff\xf6\xc0\x80P\xff" + + "\xff\xff\xff\xf7\x0e:\xc0\xff\xff\xff\xff\xf8QHP\xff\xff\xff\xff\xf8\xc7\xe1@\xff\xff\xff\xff\xfa\n\xee\xd0\xff\xff\xff\xff\xfa\xa9\x14\xc0\xff\xff\xff\xff\xfb\xec\"P\xff\xff\xff\xff\xfc\x8b\x99\xc0\x00\x00\x00\x00\x1d" + + "ɪP\x00\x00\x00\x00\x1ex\xf3\xc0\x00\x00\x00\x00\x1f\xa0Q\xd0\x00\x00\x00\x00 3\xeb\xc0\x00\x00\x00\x00!\x81\x85P\x00\x00\x00\x00\"\v\xe4\xc0\x00\x00\x00\x00H`\u007fP\x00\x00\x00\x00R\u007f\x04\xc0\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x02\xff\xff\xc0p\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x00\x04LMT\x00-0" + + "4\x00-05\x00\n<-05>5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSd\xa9y\x9at\x03\x00\x00t\x03\x00\x00\x10\x00\x1c\x00America/Asuncion" + + "UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00O\x00\x00\x00\x05\x00" + + "\x00\x00\x10\xff\xff\xff\xffi\x87\x11\x90\xff\xff\xff\xff\xb8\x17\xf5\x90\x00\x00\x00\x00\x05+\xda@\x00\x00\x00\x00\a\xfc\xf0\xb0\x00\x00\x00\x00\n\xcft\xc0\x00\x00\x00\x00\v\x97ʰ\x00\x00\x00\x00\f\xb1\xf9\xc0\x00" + + "\x00\x00\x00\rx\xfe0\x00\x00\x00\x00\x0e\x93-@\x00\x00\x00\x00\x0fZ1\xb0\x00\x00\x00\x00\x10t`\xc0\x00\x00\x00\x00\x11dC\xb0\x00\x00\x00\x00\x12U\x94@\x00\x00\x00\x00\x13FȰ\x00\x00\x00\x00\x14" + + "8\x19@\x00\x00\x00\x00\x15'\xfc0\x00\x00\x00\x00\x16\x19L\xc0\x00\x00\x00\x00\x17\t/\xb0\x00\x00\x00\x00\x17\xfa\x80@\x00\x00\x00\x00\x18\xeac0\x00\x00\x00\x00\x19۳\xc0\x00\x00\x00\x00\x1a\xcc\xe80\x00" + + "\x00\x00\x00\x1b\xbe8\xc0\x00\x00\x00\x00\x1c\xae\x1b\xb0\x00\x00\x00\x00\x1d\x9fl@\x00\x00\x00\x00\x1e\x8fO0\x00\x00\x00\x00\x1f\x80\x9f\xc0\x00\x00\x00\x00 p\x82\xb0\x00\x00\x00\x00!a\xd3@\x00\x00\x00\x00\"" + + "S\a\xb0\x00\x00\x00\x00#DX@\x00\x00\x00\x00$4;0\x00\x00\x00\x00%A;@\x00\x00\x00\x00&\x15n\xb0\x00\x00\x00\x00'\x06\xbf@\x00\x00\x00\x00'\xf6\xa20\x00\x00\x00\x00(\xee\x8a@\x00" + + "\x00\x00\x00)\xb0H\xb0\x00\x00\x00\x00*Ͻ\xc0\x00\x00\x00\x00+\xb9\t0\x00\x00\x00\x00,\xab\xab@\x00\x00\x00\x00-p\f\xb0\x00\x00\x00\x00.\x8c\xde\xc0\x00\x00\x00\x00/O\xee\xb0\x00\x00\x00\x000" + + "n\x12@\x00\x00\x00\x0016h0\x00\x00\x00\x002W.\xc0\x00\x00\x00\x003\x0f\xb2\xb0\x00\x00\x00\x0047\x10\xc0\x00\x00\x00\x004\xf8\xcf0\x00\x00\x00\x006\x16\xf2\xc0\x00\x00\x00\x006\xe1\xeb\xb0\x00" + + "\x00\x00\x007\xf6\xd4\xc0\x00\x00\x00\x008\xc1Ͱ\x00\x00\x00\x009ֶ\xc0\x00\x00\x00\x00:\xa1\xaf\xb0\x00\x00\x00\x00;\xbf\xd3@\x00\x00\x00\x00<\xaf\xb60\x00\x00\x00\x00=q\x90\xc0\x00\x00\x00\x00>" + + "\x8f\x980\x00\x00\x00\x00?Z\xad@\x00\x00\x00\x00@oz0\x00\x00\x00\x00Aq\xee@\x00\x00\x00\x00B3\xac\xb0\x00\x00\x00\x00CQ\xd0@\x00\x00\x00\x00D\x13\x8e\xb0\x00\x00\x00\x00E1\xb2@\x00" + + "\x00\x00\x00E\xf3p\xb0\x00\x00\x00\x00G\x1a\xce\xc0\x00\x00\x00\x00G\xd3R\xb0\x00\x00\x00\x00H\xfa\xb0\xc0\x00\x00\x00\x00I\xb34\xb0\x00\x00\x00\x00Jڒ\xc0\x00\x00\x00\x00K\xc1;0\x00\x00\x00\x00L" + + "\xa7\xff\xc0\x00\x00\x00\x00M\xa1\x1d0\x00\x00\x00\x00N\x87\xe1\xc0\x00\x00\x00\x00O\x80\xff0\x00\x00\x00\x00Pp\xfe@\x01\x02\x03\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04" + + "\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\xff\xff\xc9\xf0\x00\x00" + + "\xff\xff\xc9\xf0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x00\f\xff\xff\xd5\xd0\x01\fLMT\x00AMT\x00-04\x00-03\x00\n<-04>4<-03>,M10.1.0" + + "/0,M3.4.0/0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS?\xc9\x1c\xd4\xc6\x03\x00\x00\xc6\x03\x00\x00\x0e\x00\x1c\x00America/JuneauUT\t\x00" + + "\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00S\x00\x00\x00\n\x00\x00\x00&\xff" + + "\xff\xff\xff?\xc2\xfd\xd1\xff\xff\xff\xff}\x872\xc5\xff\xff\xff\xffˉ\x1a\xa0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a&\x10\xff\xff\xff\xff\xfe\xb8G \xff\xff\xff\xff\xff\xa8*\x10\x00\x00\x00\x00\x00" + + "\x98) \x00\x00\x00\x00\x01\x88\f\x10\x00\x00\x00\x00\x02x\v \x00\x00\x00\x00\x03q(\x90\x00\x00\x00\x00\x04a'\xa0\x00\x00\x00\x00\x05Q\n\x90\x00\x00\x00\x00\x06A\t\xa0\x00\x00\x00\x00\a0\xec\x90\x00" + + "\x00\x00\x00\a\x8dC\xa0\x00\x00\x00\x00\t\x10ΐ\x00\x00\x00\x00\t\xad\xbf \x00\x00\x00\x00\n\xf0\xb0\x90\x00\x00\x00\x00\v\u0be0\x00\x00\x00\x00\f\xd9\xcd\x10\x00\x00\x00\x00\r\xc0\x91\xa0\x00\x00\x00\x00\x0e" + + "\xb9\xaf\x10\x00\x00\x00\x00\x0f\xa9\xae \x00\x00\x00\x00\x10\x99\x91\x10\x00\x00\x00\x00\x11\x89\x90 \x00\x00\x00\x00\x12ys\x10\x00\x00\x00\x00\x13ir \x00\x00\x00\x00\x14Yc \x00\x00\x00\x00\x15IT \x00" + + "\x00\x00\x00\x1697\x10\x00\x00\x00\x00\x17)6 \x00\x00\x00\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18 \x00\x00\x00\x00\x1a\x025\x90\x00\x00\x00\x00\x1a+\x14\x10\x00\x00\x00\x00\x1a\xf2B\xb0\x00\x00\x00\x00\x1b" + "\xe2%\xa0\x00\x00\x00\x00\x1c\xd2$\xb0\x00\x00\x00\x00\x1d\xc2\a\xa0\x00\x00\x00\x00\x1e\xb2\x06\xb0\x00\x00\x00\x00\x1f\xa1\xe9\xa0\x00\x00\x00\x00 v90\x00\x00\x00\x00!\x81ˠ\x00\x00\x00\x00\"V\x1b0\x00" + "\x00\x00\x00#j\xe8 \x00\x00\x00\x00$5\xfd0\x00\x00\x00\x00%J\xca \x00\x00\x00\x00&\x15\xdf0\x00\x00\x00\x00'*\xac \x00\x00\x00\x00'\xfe\xfb\xb0\x00\x00\x00\x00)\n\x8e \x00\x00\x00\x00)" + "\xdeݰ\x00\x00\x00\x00*\xeap \x00\x00\x00\x00+\xbe\xbf\xb0\x00\x00\x00\x00,ӌ\xa0\x00\x00\x00\x00-\x9e\xa1\xb0\x00\x00\x00\x00.\xb3n\xa0\x00\x00\x00\x00/~\x83\xb0\x00\x00\x00\x000\x93P\xa0\x00" + "\x00\x00\x001g\xa00\x00\x00\x00\x002s2\xa0\x00\x00\x00\x003G\x820\x00\x00\x00\x004S\x14\xa0\x00\x00\x00\x005'd0\x00\x00\x00\x0062\xf6\xa0\x00\x00\x00\x007\aF0\x00\x00\x00\x008" + "\x1c\x13 \x00\x00\x00\x008\xe7(0\x00\x00\x00\x009\xfb\xf5 \x00\x00\x00\x00:\xc7\n0\x00\x00\x00\x00;\xdb\xd7 \x00\x00\x00\x00<\xb0&\xb0\x00\x00\x00\x00=\xbb\xb9 \x00\x00\x00\x00>\x90\b\xb0\x00" + "\x00\x00\x00?\x9b\x9b \x00\x00\x00\x00@o\xea\xb0\x00\x00\x00\x00A\x84\xb7\xa0\x00\x00\x00\x00BO̰\x00\x00\x00\x00Cd\x99\xa0\x00\x00\x00\x00D/\xae\xb0\x00\x00\x00\x00ED{\xa0\x00\x00\x00\x00E" + - "\xf3\xe10\x01\x02\x03\x04\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06" + - "\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\x00\x00\u0381\x00\x00\xff\xff}\x01\x00\x00\xff\xff\x81p\x00\x04\xff\xff\x8f\x80\x01\b\xff\xff\x8f\x80\x01\f\xff\xff\x8f\x80" + - "\x01\x10\xff\xff\x8f\x80\x01\x14\xff\xff\x81p\x00\x19LMT\x00YST\x00YWT\x00YPT\x00YDT\x00AKDT\x00AKST\x00\nAKST9AKDT,M3.2." + - "0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00\x00\x00\x0f\x00\x1c\x00America/GrenadaUT\t\x00\x03" + - "\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff" + - "\xff\xff\x9373\xac\x01\xff\xff\xc6T\x00\x00\xff\xff\xc7\xc0\x00\x04LMT\x00AST\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xef\xf0R\x8a\xc4\x02\x00\x00\xc4\x02\x00\x00\x0f" + - "\x00\x1c\x00America/RosarioUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xad\xb0\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f" + - "@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff" + - "\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*" + - "0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff" + - "\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C" + - "\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff" + - "\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'!\x0f" + - "0\x00\x00\x00\x00'\xd0X\xa0\x00\x00\x00\x00)\x00\xff@\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00" + - "\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x00\x00\x00\x00H\xfa\xa2\xb0\x00\x00\x00\x00I\xbca \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x02\x04\x05\x04\x05\x03\x05\x04\x05\x04\x05\xff\xff\xc3\xd0\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10" + - "\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xac\x8e\xee\x13\xbe\x00\x00\x00\xbe\x00\x00\x00" + - "\x0f\x00\x1c\x00America/CaracasUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + + "\xf3\xe10\x01\x02\x03\x04\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x06\x02\x05\x02\x05\x02\x05\a\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b" + + "\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\x00\x00\xd3{\x00\x00\xff\xff\x81\xfb\x00\x00\xff\xff\x8f\x80\x00\x04\xff\xff\x9d\x90\x01\b\xff\xff\x9d\x90\x01\f\xff\xff\x9d\x90" + + "\x01\x10\xff\xff\x8f\x80\x01\x14\xff\xff\x81p\x00\x18\xff\xff\x8f\x80\x01\x1c\xff\xff\x81p\x00!LMT\x00PST\x00PWT\x00PPT\x00PDT\x00YDT\x00YST\x00AKDT\x00A" + + "KST\x00\nAKST9AKDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xf6@\rm\xa8\x05\x00\x00\xa8\x05\x00\x00\x13\x00\x1c\x00" + + "America/Fort_NelsonUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xffi\x87\x1a@\xff\xff\xff\xff\x93\x1e,<\xff\xff\xff\xff\xf6\x98\xecH\x00\x00\x00\x00G[\x92p\x00\x00\x00\x00W%" + - "\xa9p\x01\x02\x03\x02\x03\xff\xff\xc1@\x00\x00\xff\xff\xc1D\x00\x04\xff\xff\xc0\xb8\x00\b\xff\xff\xc7\xc0\x00\x0eLMT\x00CMT\x00-0430\x00-04\x00\n<-04>4\nPK\x03" + - "\x04\n\x00\x00\x00\x00\x00\xf1c9Ro_\x00v/\x01\x00\x00/\x01\x00\x00\x0e\x00\x1c\x00America/MeridaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04" + - "\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" + - "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff\xa5\xb6\xda`\x00\x00\x00\x00\x16\x86\xd5`" + - "\x00\x00\x00\x00\x18LKP\x00\x00\x00\x001gv\x00\x00\x00\x00\x002s\bp\x00\x00\x00\x003GX\x00\x00\x00\x00\x004R\xeap\x00\x00\x00\x005':\x00\x00\x00\x00\x0062\xccp\x00\x00\x00\x00" + - "7\a\x1c\x00\x00\x00\x00\x008\x1b\xe8\xf0\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xca\xf0\x00\x00\x00\x00:\xf5\x04\x80\x00\x00\x00\x00;\xb6\xc2\xf0\x00\x00\x00\x00<\xaf\xfc\x80\x01\x02\x01\x03\x01\x03\x01\x03" + - "\x01\x03\x01\x03\x01\x03\x01\x03\xff\xff\xab\xfc\x00\x00\xff\xff\xab\xa0\x00\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xb9\xb0\x01\fLMT\x00CST\x00EST\x00CDT\x00\nCST6CDT,M4." + - "1.0,M10.5.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xe0\xbf\xf5\xe5\xc4\x02\x00\x00\xc4\x02\x00\x00\x14\x00\x1c\x00America/Buenos_Air" + - "esUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00" + - "\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xa8L\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}" + - "\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff" + - "\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf" + - "0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff" + - "\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w" + - "@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00" + - "\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'!\x0f0\x00\x00\x00\x00'\xd0X\xa0\x00\x00\x00\x00)\x00\xf1" + - "0\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x00\x00\x00" + - "\x00H\xfa\xa2\xb0\x00\x00\x00\x00I\xbca \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05" + - "\x04\x05\x04\x05\x04\x05\x04\x05\x03\x05\x04\x05\x04\x05\xff\xff\xc94\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-0" + - "4\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x1b\vKdC\x03\x00\x00C\x03\x00\x00\x13\x00\x1c\x00America/Rain" + - "y_RiverUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00J\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xffr\xee\x87(\xff\xff\xff\xff\x9e\xb8\xa1\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xc8\xf8W`\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff" + - "\xff\xff\xd2a\t\xf0\x00\x00\x00\x00\b π\x00\x00\x00\x00\t\x10\xb2p\x00\x00\x00\x00\n\x00\xb1\x80\x00\x00\x00\x00\n\xf0\x94p\x00\x00\x00\x00\v\xe0\x93\x80\x00\x00\x00\x00\fٰ\xf0\x00\x00\x00\x00\r\xc0" + - "u\x80\x00\x00\x00\x00\x0e\xb9\x92\xf0\x00\x00\x00\x00\x0f\xa9\x92\x00\x00\x00\x00\x00\x10\x99t\xf0\x00\x00\x00\x00\x11\x89t\x00\x00\x00\x00\x00\x12yV\xf0\x00\x00\x00\x00\x13iV\x00\x00\x00\x00\x00\x14Y8\xf0\x00\x00" + - "\x00\x00\x15I8\x00\x00\x00\x00\x00\x169\x1a\xf0\x00\x00\x00\x00\x17)\x1a\x00\x00\x00\x00\x00\x18\"7p\x00\x00\x00\x00\x19\b\xfc\x00\x00\x00\x00\x00\x1a\x02\x19p\x00\x00\x00\x00\x1a\xf2\x18\x80\x00\x00\x00\x00\x1b\xe1" + - "\xfbp\x00\x00\x00\x00\x1c\xd1\xfa\x80\x00\x00\x00\x00\x1d\xc1\xddp\x00\x00\x00\x00\x1e\xb1܀\x00\x00\x00\x00\x1f\xa1\xbfp\x00\x00\x00\x00 v\x0f\x00\x00\x00\x00\x00!\x81\xa1p\x00\x00\x00\x00\"U\xf1\x00\x00\x00" + - "\x00\x00#j\xbd\xf0\x00\x00\x00\x00$5\xd3\x00\x00\x00\x00\x00%J\x9f\xf0\x00\x00\x00\x00&\x15\xb5\x00\x00\x00\x00\x00'*\x81\xf0\x00\x00\x00\x00'\xfeр\x00\x00\x00\x00)\nc\xf0\x00\x00\x00\x00)\xde" + - "\xb3\x80\x00\x00\x00\x00*\xeaE\xf0\x00\x00\x00\x00+\xbe\x95\x80\x00\x00\x00\x00,\xd3bp\x00\x00\x00\x00-\x9ew\x80\x00\x00\x00\x00.\xb3Dp\x00\x00\x00\x00/~Y\x80\x00\x00\x00\x000\x93&p\x00\x00" + - "\x00\x001gv\x00\x00\x00\x00\x002s\bp\x00\x00\x00\x003GX\x00\x00\x00\x00\x004R\xeap\x00\x00\x00\x005':\x00\x00\x00\x00\x0062\xccp\x00\x00\x00\x007\a\x1c\x00\x00\x00\x00\x008\x1b" + - "\xe8\xf0\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xca\xf0\x00\x00\x00\x00:\xc6\xe0\x00\x00\x00\x00\x00;۬\xf0\x00\x00\x00\x00<\xaf\xfc\x80\x00\x00\x00\x00=\xbb\x8e\xf0\x00\x00\x00\x00>\x8fހ\x00\x00" + - "\x00\x00?\x9bp\xf0\x00\x00\x00\x00@o\xc0\x80\x00\x00\x00\x00A\x84\x8dp\x00\x00\x00\x00BO\xa2\x80\x00\x00\x00\x00Cdop\x00\x00\x00\x00D/\x84\x80\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3" + - "\xb7\x00\x02\x01\x02\x01\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xa7X\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10LMT\x00CDT\x00CST\x00CW" + - "T\x00CPT\x00\nCST6CDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rø\xab\x9b\xf0\x00\x00\x00\xf0\x00\x00\x00\x0f\x00\x1c\x00" + - "America/PhoenixUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\v\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff^\x04\f\xb0\xff\xff\xff\xff\x9e\xa6:\x90\xff\xff\xff\xff\x9f\xbb\a\x80\xff\xff\xff\xff\xa0\x86\x1c\x90\xff\xff\xff\xff\xa1\x9a\xe9\x80\xff\xff" + - "\xff\xffˉ\f\x90\xff\xff\xff\xff\xcf\x17\xdf\x1c\xff\xff\xff\xffϏ\xe5\xac\xff\xff\xff\xffЁ\x1a\x1c\xff\xff\xff\xff\xfa\xf8u\x10\xff\xff\xff\xff\xfb\xe8X\x00\x02\x01\x02\x01\x02\x03\x02\x03\x02\x01\x02\xff\xff\x96" + - "\xee\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\fLMT\x00MDT\x00MST\x00MWT\x00\nMST7\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xdf\xe5\x8d" + - "\xc4\xda\x04\x00\x00\xda\x04\x00\x00\x12\x00\x1c\x00America/LouisvilleUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00T" + - "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00u\x00\x00\x00\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff" + - "\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xff\xa4s\xf7\x00\xff\xff\xff\xff\xa5\x16\x11p\xff\xff\xff\xff\xca\rN\x80\xff\xff\xff\xff\xca\xd8Gp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#" + - "\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xd3u\xd7\x1c\xff\xff\xff\xffӤ\tp\xff\xff\xff\xff\xda\xfe\xb5\x80\xff\xff\xff\xff\xdb\xc0s\xf0\xff\xff\xff\xff\xdcޗ\x80\xff\xff\xff\xffݩ\x90p\xff\xff" + - "\xff\xff\u07bey\x80\xff\xff\xff\xff߉rp\xff\xff\xff\xff\xe0\x9e[\x80\xff\xff\xff\xff\xe1iTp\xff\xff\xff\xff\xe2~=\x80\xff\xff\xff\xff\xe3I6p\xff\xff\xff\xff\xe4^\x1f\x80\xff\xff\xff\xff\xe5)" + - "\x18p\xff\xff\xff\xff\xe6G<\x00\xff\xff\xff\xff\xe77\x1e\xf0\xff\xff\xff\xff\xe8'\x1e\x00\xff\xff\xff\xff\xe9\x17\x00\xf0\xff\xff\xff\xff\xea\a\x00\x00\xff\xff\xff\xff\xea\xf6\xe2\xf0\xff\xff\xff\xff\xeb\xe6\xe2\x00\xff\xff" + - "\xff\xff\xec\xd6\xc4\xf0\xff\xff\xff\xff\xed\xc6\xc4\x00\xff\xff\xff\xff\xee\xbf\xe1p\xff\xff\xff\xff\xef\xaf\xe0\x80\xff\xff\xff\xff\xf0\x1e\x90p\xff\xff\xff\xff\xfc\xd8:\xf0\xff\xff\xff\xff\xfd\xc8\x1d\xe0\xff\xff\xff\xff\xfe\xb8" + - "\x1c\xf0\xff\xff\xff\xff\xff\xa7\xff\xe0\x00\x00\x00\x00\x00\x97\xfe\xf0\x00\x00\x00\x00\x01\x87\xe1\xe0\x00\x00\x00\x00\x02w\xe0\xf0\x00\x00\x00\x00\x03p\xfe`\x00\x00\x00\x00\x04`\xfdp\x00\x00\x00\x00\x05P\xe0`\x00\x00" + - "\x00\x00\x06@\xdfp\x00\x00\x00\x00\a0\xc2`\x00\x00\x00\x00\a\x8d\x19p\x00\x00\x00\x00\t\x10\xb2p\x00\x00\x00\x00\t\xad\x94\xf0\x00\x00\x00\x00\n\xf0\x86`\x00\x00\x00\x00\v\xe0\x85p\x00\x00\x00\x00\f\xd9" + - "\xa2\xe0\x00\x00\x00\x00\r\xc0gp\x00\x00\x00\x00\x0e\xb9\x84\xe0\x00\x00\x00\x00\x0f\xa9\x83\xf0\x00\x00\x00\x00\x10\x99f\xe0\x00\x00\x00\x00\x11\x89e\xf0\x00\x00\x00\x00\x12yH\xe0\x00\x00\x00\x00\x13iG\xf0\x00\x00" + - "\x00\x00\x14Y*\xe0\x00\x00\x00\x00\x15I)\xf0\x00\x00\x00\x00\x169\f\xe0\x00\x00\x00\x00\x17)\v\xf0\x00\x00\x00\x00\x18\")`\x00\x00\x00\x00\x19\b\xed\xf0\x00\x00\x00\x00\x1a\x02\v`\x00\x00\x00\x00\x1a\xf2" + - "\np\x00\x00\x00\x00\x1b\xe1\xed`\x00\x00\x00\x00\x1c\xd1\xecp\x00\x00\x00\x00\x1d\xc1\xcf`\x00\x00\x00\x00\x1e\xb1\xcep\x00\x00\x00\x00\x1f\xa1\xb1`\x00\x00\x00\x00 v\x00\xf0\x00\x00\x00\x00!\x81\x93`\x00\x00" + - "\x00\x00\"U\xe2\xf0\x00\x00\x00\x00#j\xaf\xe0\x00\x00\x00\x00$5\xc4\xf0\x00\x00\x00\x00%J\x91\xe0\x00\x00\x00\x00&\x15\xa6\xf0\x00\x00\x00\x00'*s\xe0\x00\x00\x00\x00'\xfe\xc3p\x00\x00\x00\x00)\n" + - "U\xe0\x00\x00\x00\x00)ޥp\x00\x00\x00\x00*\xea7\xe0\x00\x00\x00\x00+\xbe\x87p\x00\x00\x00\x00,\xd3T`\x00\x00\x00\x00-\x9eip\x00\x00\x00\x00.\xb36`\x00\x00\x00\x00/~Kp\x00\x00" + - "\x00\x000\x93\x18`\x00\x00\x00\x001gg\xf0\x00\x00\x00\x002r\xfa`\x00\x00\x00\x003GI\xf0\x00\x00\x00\x004R\xdc`\x00\x00\x00\x005'+\xf0\x00\x00\x00\x0062\xbe`\x00\x00\x00\x007\a" + - "\r\xf0\x00\x00\x00\x008\x1b\xda\xe0\x00\x00\x00\x008\xe6\xef\xf0\x00\x00\x00\x009\xfb\xbc\xe0\x00\x00\x00\x00:\xc6\xd1\xf0\x00\x00\x00\x00;۞\xe0\x00\x00\x00\x00<\xaf\xeep\x00\x00\x00\x00=\xbb\x80\xe0\x00\x00" + - "\x00\x00>\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00ED" + - "C`\x00\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05" + - "\x01\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05" + - "\x06\x05\x06\x05\x06\x05\x06\xff\xff\xaf\x9a\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14\xff\xff\xc7\xc0\x01\x18LMT\x00CDT\x00CST" + - "\x00CWT\x00CPT\x00EST\x00EDT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rk^2S\xb9" + - "\x04\x00\x00\xb9\x04\x00\x00\x14\x00\x1c\x00America/Punta_ArenasUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00T" + - "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00t\x00\x00\x00\a\x00\x00\x00\x14\xff\xff\xff\xffi\x87\x1d\xfc\xff\xff\xff\xff\x8f0GF\xff\xff\xff\xff\x9b\\\xe5P\xff\xff" + - "\xff\xff\x9f|\xe2\xc6\xff\xff\xff\xff\xa1\x00q\xc0\xff\xff\xff\xff\xb0^w\xc6\xff\xff\xff\xff\xb1w=@\xff\xff\xff\xff\xb2A\x00\xd0\xff\xff\xff\xff\xb3Xp\xc0\xff\xff\xff\xff\xb4\"4P\xff\xff\xff\xff\xb59" + - "\xa4@\xff\xff\xff\xff\xb6\x03g\xd0\xff\xff\xff\xff\xb7\x1a\xd7\xc0\xff\xff\xff\xff\xb7\xe4\x9bP\xff\xff\xff\xff\xb8\xfd\\\xc0\xff\xff\xff\xff\xb9\xc7 P\xff\xff\xff\xff\xcc\x1cn@\xff\xff\xff\xff\xccl\xe7\xd0\xff\xff" + - "\xff\xff\xd53U\xc0\xff\xff\xff\xff\xd5v\x92@\xff\xff\xff\xff\xfd\xd1<@\xff\xff\xff\xff\xfe\x92\xfa\xb0\xff\xff\xff\xff\xff\xcc\xcd\xc0\x00\x00\x00\x00\x00rܰ\x00\x00\x00\x00\x01uP\xc0\x00\x00\x00\x00\x02@" + - "I\xb0\x00\x00\x00\x00\x03U2\xc0\x00\x00\x00\x00\x04 +\xb0\x00\x00\x00\x00\x05>O@\x00\x00\x00\x00\x06\x00\r\xb0\x00\x00\x00\x00\a\v\xbc@\x00\x00\x00\x00\a\xdf\xef\xb0\x00\x00\x00\x00\b\xfe\x13@\x00\x00" + - "\x00\x00\t\xbfѰ\x00\x00\x00\x00\n\xdd\xf5@\x00\x00\x00\x00\v\xa8\xee0\x00\x00\x00\x00\f\xbd\xd7@\x00\x00\x00\x00\r\x88\xd00\x00\x00\x00\x00\x0e\x9d\xb9@\x00\x00\x00\x00\x0fh\xb20\x00\x00\x00\x00\x10\x86" + - "\xd5\xc0\x00\x00\x00\x00\x11H\x940\x00\x00\x00\x00\x12f\xb7\xc0\x00\x00\x00\x00\x13(v0\x00\x00\x00\x00\x14F\x99\xc0\x00\x00\x00\x00\x15\x11\x92\xb0\x00\x00\x00\x00\x16&{\xc0\x00\x00\x00\x00\x16\xf1t\xb0\x00\x00" + - "\x00\x00\x18\x06]\xc0\x00\x00\x00\x00\x18\xd1V\xb0\x00\x00\x00\x00\x19\xe6?\xc0\x00\x00\x00\x00\x1a\xb18\xb0\x00\x00\x00\x00\x1b\xcf\\@\x00\x00\x00\x00\x1c\x91\x1a\xb0\x00\x00\x00\x00\x1d\xaf>@\x00\x00\x00\x00\x1ep" + - "\xfc\xb0\x00\x00\x00\x00\x1f\x8f @\x00\x00\x00\x00 \u007f\x030\x00\x00\x00\x00!o\x02@\x00\x00\x00\x00\"9\xfb0\x00\x00\x00\x00#N\xe4@\x00\x00\x00\x00$\x19\xdd0\x00\x00\x00\x00%8\x00\xc0\x00\x00" + - "\x00\x00%\xf9\xbf0\x00\x00\x00\x00&\xf2\xf8\xc0\x00\x00\x00\x00'١0\x00\x00\x00\x00(\xf7\xc4\xc0\x00\x00\x00\x00)½\xb0\x00\x00\x00\x00*צ\xc0\x00\x00\x00\x00+\xa2\x9f\xb0\x00\x00\x00\x00,\xb7" + - "\x88\xc0\x00\x00\x00\x00-\x82\x81\xb0\x00\x00\x00\x00.\x97j\xc0\x00\x00\x00\x00/bc\xb0\x00\x00\x00\x000\x80\x87@\x00\x00\x00\x001BE\xb0\x00\x00\x00\x002`i@\x00\x00\x00\x003=\xd70\x00\x00" + - "\x00\x004@K@\x00\x00\x00\x005\vD0\x00\x00\x00\x006\r\xb8@\x00\x00\x00\x007\x06հ\x00\x00\x00\x008\x00\x0f@\x00\x00\x00\x008\xcb\b0\x00\x00\x00\x009\xe9+\xc0\x00\x00\x00\x00:\xaa" + - "\xea0\x00\x00\x00\x00;\xc9\r\xc0\x00\x00\x00\x00<\x8a\xcc0\x00\x00\x00\x00=\xa8\xef\xc0\x00\x00\x00\x00>j\xae0\x00\x00\x00\x00?\x88\xd1\xc0\x00\x00\x00\x00@Sʰ\x00\x00\x00\x00Ah\xb3\xc0\x00\x00" + - "\x00\x00B3\xac\xb0\x00\x00\x00\x00CH\x95\xc0\x00\x00\x00\x00D\x13\x8e\xb0\x00\x00\x00\x00E1\xb2@\x00\x00\x00\x00E\xf3p\xb0\x00\x00\x00\x00G\x11\x94@\x00\x00\x00\x00G\xef\x020\x00\x00\x00\x00H\xf1" + - "v@\x00\x00\x00\x00I\xbco0\x00\x00\x00\x00J\xd1X@\x00\x00\x00\x00K\xb8\x00\xb0\x00\x00\x00\x00L\xb1:@\x00\x00\x00\x00M\xc6\a0\x00\x00\x00\x00NP\x82\xc0\x00\x00\x00\x00O\x9c\xae\xb0\x00\x00" + - "\x00\x00PB\xd9\xc0\x00\x00\x00\x00Q|\x90\xb0\x00\x00\x00\x00R+\xf6@\x00\x00\x00\x00S\\r\xb0\x00\x00\x00\x00T\v\xd8@\x00\x00\x00\x00W7\xe60\x00\x00\x00\x00W\xaf\xec\xc0\x00\x00\x00\x00XC" + - "\x86\xb0\x01\x02\x01\x03\x01\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x03\x02\x03\x02\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03" + - "\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x06\xff\xff" + - "\xbd\x84\x00\x00\xff\xff\xbd\xba\x00\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x00\f\xff\xff\xc7\xc0\x01\f\xff\xff\xd5\xd0\x01\x10\xff\xff\xd5\xd0\x00\x10LMT\x00SMT\x00-05\x00-04\x00-03\x00" + - "\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rg\xf5K\x89\xa2\x01\x00\x00\xa2\x01\x00\x00\x12\x00\x1c\x00America/Porto_AcreUT\t\x00" + - "\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x00\x00\x00\x04\x00\x00\x00\f\xff" + - "\xff\xff\xff\x96\xaa\x86\x90\xff\xff\xff\xff\xb8\x0ff\x00\xff\xff\xff\xff\xb8\xfd\\\xc0\xff\xff\xff\xff\xb9\xf1PP\xff\xff\xff\xff\xbaސ@\xff\xff\xff\xff\xda8\xcaP\xff\xff\xff\xff\xda\xec\x16P\xff\xff\xff\xff\xdc" + - "\x19\xfd\xd0\xff\xff\xff\xffܹu@\xff\xff\xff\xff\xdd\xfb1P\xff\xff\xff\xffޛ\xfa@\xff\xff\xff\xff\xdfݶP\xff\xff\xff\xff\xe0TO@\xff\xff\xff\xff\xf4\x98\x1b\xd0\xff\xff\xff\xff\xf5\x05z@\xff" + - "\xff\xff\xff\xf6\xc0\x80P\xff\xff\xff\xff\xf7\x0e:\xc0\xff\xff\xff\xff\xf8QHP\xff\xff\xff\xff\xf8\xc7\xe1@\xff\xff\xff\xff\xfa\n\xee\xd0\xff\xff\xff\xff\xfa\xa9\x14\xc0\xff\xff\xff\xff\xfb\xec\"P\xff\xff\xff\xff\xfc" + - "\x8b\x99\xc0\x00\x00\x00\x00\x1dɪP\x00\x00\x00\x00\x1ex\xf3\xc0\x00\x00\x00\x00\x1f\xa0Q\xd0\x00\x00\x00\x00 3\xeb\xc0\x00\x00\x00\x00!\x81\x85P\x00\x00\x00\x00\"\v\xe4\xc0\x00\x00\x00\x00H`\u007fP\x00" + - "\x00\x00\x00R\u007f\x04\xc0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x02\xff\xff\xc0p\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0" + - "\x00\x04LMT\x00-04\x00-05\x00\n<-05>5\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R3\x9aG\xc8\xd0\x06\x00\x00\xd0\x06\x00\x00\x10\x00\x1c\x00America/" + - "New_YorkUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\xaf\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff^\x03\xf0\x90\xff\xff\xff\xff\x9e\xa6\x1ep\xff\xff\xff\xff\x9f\xba\xeb`\xff\xff\xff\xff\xa0\x86\x00p\xff\xff\xff\xff\xa1\x9a\xcd`\xff\xff\xff\xff\xa2e\xe2p\xff" + - "\xff\xff\xff\xa3\x83\xe9\xe0\xff\xff\xff\xff\xa4j\xaep\xff\xff\xff\xff\xa55\xa7`\xff\xff\xff\xff\xa6S\xca\xf0\xff\xff\xff\xff\xa7\x15\x89`\xff\xff\xff\xff\xa83\xac\xf0\xff\xff\xff\xff\xa8\xfe\xa5\xe0\xff\xff\xff\xff\xaa" + - "\x13\x8e\xf0\xff\xff\xff\xff\xaaއ\xe0\xff\xff\xff\xff\xab\xf3p\xf0\xff\xff\xff\xff\xac\xbei\xe0\xff\xff\xff\xff\xad\xd3R\xf0\xff\xff\xff\xff\xae\x9eK\xe0\xff\xff\xff\xff\xaf\xb34\xf0\xff\xff\xff\xff\xb0~-\xe0\xff" + - "\xff\xff\xff\xb1\x9cQp\xff\xff\xff\xff\xb2gJ`\xff\xff\xff\xff\xb3|3p\xff\xff\xff\xff\xb4G,`\xff\xff\xff\xff\xb5\\\x15p\xff\xff\xff\xff\xb6'\x0e`\xff\xff\xff\xff\xb7;\xf7p\xff\xff\xff\xff\xb8" + - "\x06\xf0`\xff\xff\xff\xff\xb9\x1b\xd9p\xff\xff\xff\xff\xb9\xe6\xd2`\xff\xff\xff\xff\xbb\x04\xf5\xf0\xff\xff\xff\xff\xbbƴ`\xff\xff\xff\xff\xbc\xe4\xd7\xf0\xff\xff\xff\xff\xbd\xaf\xd0\xe0\xff\xff\xff\xff\xbeĹ\xf0\xff" + - "\xff\xff\xff\xbf\x8f\xb2\xe0\xff\xff\xff\xff\xc0\xa4\x9b\xf0\xff\xff\xff\xff\xc1o\x94\xe0\xff\xff\xff\xff\u0084}\xf0\xff\xff\xff\xff\xc3Ov\xe0\xff\xff\xff\xff\xc4d_\xf0\xff\xff\xff\xff\xc5/X\xe0\xff\xff\xff\xff\xc6" + - "M|p\xff\xff\xff\xff\xc7\x0f:\xe0\xff\xff\xff\xff\xc8-^p\xff\xff\xff\xff\xc8\xf8W`\xff\xff\xff\xff\xca\r@p\xff\xff\xff\xff\xca\xd89`\xff\xff\xff\xffˈ\xf0p\xff\xff\xff\xff\xd2#\xf4p\xff" + - "\xff\xff\xff\xd2`\xfb\xe0\xff\xff\xff\xff\xd3u\xe4\xf0\xff\xff\xff\xff\xd4@\xdd\xe0\xff\xff\xff\xff\xd5U\xc6\xf0\xff\xff\xff\xff\xd6 \xbf\xe0\xff\xff\xff\xff\xd75\xa8\xf0\xff\xff\xff\xff\xd8\x00\xa1\xe0\xff\xff\xff\xff\xd9" + - "\x15\x8a\xf0\xff\xff\xff\xff\xd9\xe0\x83\xe0\xff\xff\xff\xff\xda\xfe\xa7p\xff\xff\xff\xff\xdb\xc0e\xe0\xff\xff\xff\xff\xdcމp\xff\xff\xff\xffݩ\x82`\xff\xff\xff\xff\u07bekp\xff\xff\xff\xff߉d`\xff" + - "\xff\xff\xff\xe0\x9eMp\xff\xff\xff\xff\xe1iF`\xff\xff\xff\xff\xe2~/p\xff\xff\xff\xff\xe3I(`\xff\xff\xff\xff\xe4^\x11p\xff\xff\xff\xff\xe5W.\xe0\xff\xff\xff\xff\xe6G-\xf0\xff\xff\xff\xff\xe7" + - "7\x10\xe0\xff\xff\xff\xff\xe8'\x0f\xf0\xff\xff\xff\xff\xe9\x16\xf2\xe0\xff\xff\xff\xff\xea\x06\xf1\xf0\xff\xff\xff\xff\xea\xf6\xd4\xe0\xff\xff\xff\xff\xeb\xe6\xd3\xf0\xff\xff\xff\xff\xecֶ\xe0\xff\xff\xff\xff\xedƵ\xf0\xff" + - "\xff\xff\xff\xee\xbf\xd3`\xff\xff\xff\xff\xef\xaf\xd2p\xff\xff\xff\xff\xf0\x9f\xb5`\xff\xff\xff\xff\xf1\x8f\xb4p\xff\xff\xff\xff\xf2\u007f\x97`\xff\xff\xff\xff\xf3o\x96p\xff\xff\xff\xff\xf4_y`\xff\xff\xff\xff\xf5" + - "Oxp\xff\xff\xff\xff\xf6?[`\xff\xff\xff\xff\xf7/Zp\xff\xff\xff\xff\xf8(w\xe0\xff\xff\xff\xff\xf9\x0f\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00" + - "\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xba\x9e\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x01\f\xff\xff\xc7\xc0\x01\x10LMT\x00" + - "EDT\x00EST\x00EWT\x00EPT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xad`\x12\xe9\xaa\x00" + - "\x00\x00\xaa\x00\x00\x00\x0e\x00\x1c\x00America/La_PazUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8f\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff^=v\x87\xff\xff\xff\xff\x9e\xb8\xbd\xa0\xff\xff\xff\xff\x9f\xbb\x15\x90\xff\xff\xff\xffˉ\x1a\xa0\xff\xff\xff\xff\xd2#" + + "\xf4p\xff\xff\xff\xff\xd2a&\x10\xff\xff\xff\xff\xd5U\xf1 \xff\xff\xff\xff\xd6 \xea\x10\xff\xff\xff\xff\xd75\xd3 \xff\xff\xff\xff\xd8\x00\xcc\x10\xff\xff\xff\xff\xd9\x15\xb5 \xff\xff\xff\xff\xd9\xe0\xae\x10\xff\xff" + + "\xff\xff\xda\xfeѠ\xff\xff\xff\xff\xdb\xc0\x90\x10\xff\xff\xff\xff\xdc\u07b3\xa0\xff\xff\xff\xffݩ\xac\x90\xff\xff\xff\xff\u07be\x95\xa0\xff\xff\xff\xff߉\x8e\x90\xff\xff\xff\xff\xe0\x9ew\xa0\xff\xff\xff\xff\xe1i" + + "p\x90\xff\xff\xff\xff\xe2~Y\xa0\xff\xff\xff\xff\xe3IR\x90\xff\xff\xff\xff\xe4^;\xa0\xff\xff\xff\xff\xe5)4\x90\xff\xff\xff\xff\xe6GX \xff\xff\xff\xff\xe7\x12Q\x10\xff\xff\xff\xff\xe8': \xff\xff" + + "\xff\xff\xe8\xf23\x10\xff\xff\xff\xff\xea\a\x1c \xff\xff\xff\xff\xea\xd2\x15\x10\xff\xff\xff\xff\xeb\xe6\xfe \xff\xff\xff\xff\xec\xb1\xf7\x10\xff\xff\xff\xff\xed\xc6\xe0 \xff\xff\xff\xff\xee\x91\xd9\x10\xff\xff\xff\xff\xef\xaf" + + "\xfc\xa0\xff\xff\xff\xff\xf0q\xbb\x10\xff\xff\xff\xff\xf1\x8fޠ\xff\xff\xff\xff\xf2\u007f\xc1\x90\xff\xff\xff\xff\xf3o\xc0\xa0\xff\xff\xff\xff\xf4_\xa3\x90\xff\xff\xff\xff\xf5O\xa2\xa0\xff\xff\xff\xff\xf6?\x85\x90\xff\xff" + + "\xff\xff\xf7/\x84\xa0\xff\xff\xff\xff\xf8(\xa2\x10\xff\xff\xff\xff\xf9\x0ff\xa0\xff\xff\xff\xff\xfa\b\x84\x10\xff\xff\xff\xff\xfa\xf8\x83 \xff\xff\xff\xff\xfb\xe8f\x10\xff\xff\xff\xff\xfc\xd8e \xff\xff\xff\xff\xfd\xc8" + + "H\x10\xff\xff\xff\xff\xfe\xb8G \xff\xff\xff\xff\xff\xa8*\x10\x00\x00\x00\x00\x00\x98) \x00\x00\x00\x00\x01\x88\f\x10\x00\x00\x00\x00\x02x\v \x00\x00\x00\x00\x03q(\x90\x00\x00\x00\x00\x04a'\xa0\x00\x00" + + "\x00\x00\x05Q\n\x90\x00\x00\x00\x00\x06A\t\xa0\x00\x00\x00\x00\a0\xec\x90\x00\x00\x00\x00\b \xeb\xa0\x00\x00\x00\x00\t\x10ΐ\x00\x00\x00\x00\n\x00͠\x00\x00\x00\x00\n\xf0\xb0\x90\x00\x00\x00\x00\v\xe0" + + "\xaf\xa0\x00\x00\x00\x00\f\xd9\xcd\x10\x00\x00\x00\x00\r\xc0\x91\xa0\x00\x00\x00\x00\x0e\xb9\xaf\x10\x00\x00\x00\x00\x0f\xa9\xae \x00\x00\x00\x00\x10\x99\x91\x10\x00\x00\x00\x00\x11\x89\x90 \x00\x00\x00\x00\x12ys\x10\x00\x00" + + "\x00\x00\x13ir \x00\x00\x00\x00\x14YU\x10\x00\x00\x00\x00\x15IT \x00\x00\x00\x00\x1697\x10\x00\x00\x00\x00\x17)6 \x00\x00\x00\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18 \x00\x00\x00\x00\x1a\x02" + + "5\x90\x00\x00\x00\x00\x1a\xf24\xa0\x00\x00\x00\x00\x1b\xe2\x17\x90\x00\x00\x00\x00\x1c\xd2\x16\xa0\x00\x00\x00\x00\x1d\xc1\xf9\x90\x00\x00\x00\x00\x1e\xb1\xf8\xa0\x00\x00\x00\x00\x1f\xa1ې\x00\x00\x00\x00 v+ \x00\x00" + + "\x00\x00!\x81\xbd\x90\x00\x00\x00\x00\"V\r \x00\x00\x00\x00#j\xda\x10\x00\x00\x00\x00$5\xef \x00\x00\x00\x00%J\xbc\x10\x00\x00\x00\x00&\x15\xd1 \x00\x00\x00\x00'*\x9e\x10\x00\x00\x00\x00'\xfe" + + "\xed\xa0\x00\x00\x00\x00)\n\x80\x10\x00\x00\x00\x00)\xdeϠ\x00\x00\x00\x00*\xeab\x10\x00\x00\x00\x00+\xbe\xb1\xa0\x00\x00\x00\x00,\xd3~\x90\x00\x00\x00\x00-\x9e\x93\xa0\x00\x00\x00\x00.\xb3`\x90\x00\x00" + + "\x00\x00/~u\xa0\x00\x00\x00\x000\x93B\x90\x00\x00\x00\x001g\x92 \x00\x00\x00\x002s$\x90\x00\x00\x00\x003Gt \x00\x00\x00\x004S\x06\x90\x00\x00\x00\x005'V \x00\x00\x00\x0062" + + "\xe8\x90\x00\x00\x00\x007\a8 \x00\x00\x00\x008\x1c\x05\x10\x00\x00\x00\x008\xe7\x1a \x00\x00\x00\x009\xfb\xe7\x10\x00\x00\x00\x00:\xc6\xfc \x00\x00\x00\x00;\xdb\xc9\x10\x00\x00\x00\x00<\xb0\x18\xa0\x00\x00" + + "\x00\x00=\xbb\xab\x10\x00\x00\x00\x00>\x8f\xfa\xa0\x00\x00\x00\x00?\x9b\x8d\x10\x00\x00\x00\x00@oܠ\x00\x00\x00\x00A\x84\xa9\x90\x00\x00\x00\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b\x90\x00\x00\x00\x00D/" + + "\xa0\xa0\x00\x00\x00\x00EDm\x90\x00\x00\x00\x00E\xf3\xd3 \x00\x00\x00\x00G-\x8a\x10\x00\x00\x00\x00Gӵ \x00\x00\x00\x00I\rl\x10\x00\x00\x00\x00I\xb3\x97 \x00\x00\x00\x00J\xedN\x10\x00\x00" + + "\x00\x00K\x9c\xb3\xa0\x00\x00\x00\x00L\xd6j\x90\x00\x00\x00\x00M|\x95\xa0\x00\x00\x00\x00N\xb6L\x90\x00\x00\x00\x00O\\w\xa0\x00\x00\x00\x00P\x96.\x90\x00\x00\x00\x00Q3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSV\x80\x94@\x12\x04" + + "\x00\x00\x12\x04\x00\x00\x0e\x00\x1c\x00America/DenverUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffi\x87\x1bd\xff\xff\xff\xff\xb8\x1e\x96\xe4\xff\xff\xff\xff\xb8\xee\xd5\xd4\x01\x02\x03\xff\xff\xc0\x1c\x00\x00" + - "\xff\xff\xc0\x1c\x00\x04\xff\xff\xce,\x01\b\xff\xff\xc7\xc0\x00\fLMT\x00CMT\x00BST\x00-04\x00\n<-04>4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xb7-2f" + - "\xe4\x01\x00\x00\xe4\x01\x00\x00\x0f\x00\x1c\x00America/NoronhaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96\xaaed\xff\xff\xff\xff\xb8\x0f;\xd0\xff\xff\xff\xff\xb8\xfd2\x90\xff\xff\xff\xff\xb9\xf1" + - "& \xff\xff\xff\xff\xba\xdef\x10\xff\xff\xff\xff\xda8\xa0 \xff\xff\xff\xff\xda\xeb\xec \xff\xff\xff\xff\xdc\x19Ӡ\xff\xff\xff\xffܹK\x10\xff\xff\xff\xff\xdd\xfb\a \xff\xff\xff\xffޛ\xd0\x10\xff\xff" + - "\xff\xff\xdf\u074c \xff\xff\xff\xff\xe0T%\x10\xff\xff\xff\xff\xf4\x97\xf1\xa0\xff\xff\xff\xff\xf5\x05P\x10\xff\xff\xff\xff\xf6\xc0V \xff\xff\xff\xff\xf7\x0e\x10\x90\xff\xff\xff\xff\xf8Q\x1e \xff\xff\xff\xff\xf8\xc7" + - "\xb7\x10\xff\xff\xff\xff\xfa\nĠ\xff\xff\xff\xff\xfa\xa8\xea\x90\xff\xff\xff\xff\xfb\xeb\xf8 \xff\xff\xff\xff\xfc\x8bo\x90\x00\x00\x00\x00\x1dɀ \x00\x00\x00\x00\x1exɐ\x00\x00\x00\x00\x1f\xa0'\xa0\x00\x00" + - "\x00\x00 3\xc1\x90\x00\x00\x00\x00!\x81[ \x00\x00\x00\x00\"\v\xba\x90\x00\x00\x00\x00#X\x02\xa0\x00\x00\x00\x00#\xe2b\x10\x00\x00\x00\x00%7\xe4\xa0\x00\x00\x00\x00%Թ\x10\x00\x00\x00\x007\xf6" + - "\xb8\xa0\x00\x00\x00\x008\xb8w\x10\x00\x00\x00\x009\xdf\xd5 \x00\x00\x00\x009\xe9\x01\x90\x00\x00\x00\x00;\xc8\xf1\xa0\x00\x00\x00\x002\nP" + - "K\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00\x00\x00\x12\x00\x1c\x00America/GuadeloupeUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`" + - "ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00" + - "\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x9373\xac\x01\xff" + - "\xff\xc6T\x00\x00\xff\xff\xc7\xc0\x00\x04LMT\x00AST\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x1e\xfbn۸\x03\x00\x00\xb8\x03\x00\x00\x14\x00\x1c\x00Ameri" + - "ca/Campo_GrandeUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00a\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff^\x04\f\xb0\xff\xff\xff\xff\x9e\xa6:\x90\xff\xff\xff\xff\x9f\xbb\a\x80\xff\xff\xff\xff\xa0\x86\x1c\x90\xff" + + "\xff\xff\xff\xa1\x9a\xe9\x80\xff\xff\xff\xff\xa2e\xfe\x90\xff\xff\xff\xff\xa3\x84\x06\x00\xff\xff\xff\xff\xa4E\xe0\x90\xff\xff\xff\xff\xa4\x8f\xa6\x80\xff\xff\xff\xffˉ\f\x90\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2" + + "a\x18\x00\xff\xff\xff\xff\xf7/v\x90\xff\xff\xff\xff\xf8(\x94\x00\xff\xff\xff\xff\xf9\x0fX\x90\xff\xff\xff\xff\xfa\bv\x00\xff\xff\xff\xff\xfa\xf8u\x10\xff\xff\xff\xff\xfb\xe8X\x00\xff\xff\xff\xff\xfc\xd8W\x10\xff" + + "\xff\xff\xff\xfd\xc8:\x00\xff\xff\xff\xff\xfe\xb89\x10\xff\xff\xff\xff\xff\xa8\x1c\x00\x00\x00\x00\x00\x00\x98\x1b\x10\x00\x00\x00\x00\x01\x87\xfe\x00\x00\x00\x00\x00\x02w\xfd\x10\x00\x00\x00\x00\x03q\x1a\x80\x00\x00\x00\x00\x04" + + "a\x19\x90\x00\x00\x00\x00\x05P\xfc\x80\x00\x00\x00\x00\x06@\xfb\x90\x00\x00\x00\x00\a0ހ\x00\x00\x00\x00\a\x8d5\x90\x00\x00\x00\x00\t\x10\xc0\x80\x00\x00\x00\x00\t\xad\xb1\x10\x00\x00\x00\x00\n\xf0\xa2\x80\x00" + + "\x00\x00\x00\vࡐ\x00\x00\x00\x00\fٿ\x00\x00\x00\x00\x00\r\xc0\x83\x90\x00\x00\x00\x00\x0e\xb9\xa1\x00\x00\x00\x00\x00\x0f\xa9\xa0\x10\x00\x00\x00\x00\x10\x99\x83\x00\x00\x00\x00\x00\x11\x89\x82\x10\x00\x00\x00\x00\x12" + + "ye\x00\x00\x00\x00\x00\x13id\x10\x00\x00\x00\x00\x14YG\x00\x00\x00\x00\x00\x15IF\x10\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17)(\x10\x00\x00\x00\x00\x18\"E\x80\x00\x00\x00\x00\x19\t\n\x10\x00" + + "\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2&\x90\x00\x00\x00\x00\x1b\xe2\t\x80\x00\x00\x00\x00\x1c\xd2\b\x90\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1\xea\x90\x00\x00\x00\x00\x1f\xa1̀\x00\x00\x00\x00 " + + "v\x1d\x10\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xff\x10\x00\x00\x00\x00#j\xcc\x00\x00\x00\x00\x00$5\xe1\x10\x00\x00\x00\x00%J\xae\x00\x00\x00\x00\x00&\x15\xc3\x10\x00\x00\x00\x00'*\x90\x00\x00" + + "\x00\x00\x00'\xfeߐ\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\xde\xc1\x90\x00\x00\x00\x00*\xeaT\x00\x00\x00\x00\x00+\xbe\xa3\x90\x00\x00\x00\x00,\xd3p\x80\x00\x00\x00\x00-\x9e\x85\x90\x00\x00\x00\x00." + + "\xb3R\x80\x00\x00\x00\x00/~g\x90\x00\x00\x00\x000\x934\x80\x00\x00\x00\x001g\x84\x10\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003Gf\x10\x00\x00\x00\x004R\xf8\x80\x00\x00\x00\x005'H\x10\x00" + + "\x00\x00\x0062ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe7\f\x10\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xc6\xee\x10\x00\x00\x00\x00;ۻ\x00\x00\x00\x00\x00<" + + "\xb0\n\x90\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8f\xec\x90\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@oΐ\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00BO\xb0\x90\x00\x00\x00\x00Cd}\x80\x00" + + "\x00\x00\x00D/\x92\x90\x00\x00\x00\x00ED_\x80\x00\x00\x00\x00E\xf3\xc5\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\xff\xff\x9d\x94\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\f\xff\xff\xab\xa0\x01\x10LMT\x00MDT\x00MST\x00MWT\x00MPT\x00\nMST7MDT,M" + + "3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSp\xb6{\xc9\x13\x02\x00\x00\x13\x02\x00\x00\x12\x00\x1c\x00America/Fort_Way" + + "neUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00&\x00\x00\x00" + + "\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xff\xcaW\"\x80\xff\xff\xff\xff\xca\xd8G" + + "p\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xd3u\xf3\x00\xff\xff\xff\xff\xd4@\xeb\xf0\xff\xff\xff\xff\xd5U\xd5\x00\xff\xff\xff\xff\xd6 \xcd\xf0\xff\xff\xff" + + "\xff\xd75\xb7\x00\xff\xff\xff\xff\xd8\x00\xaf\xf0\xff\xff\xff\xff\xd9\x15\x99\x00\xff\xff\xff\xff\xd9\xe0\x91\xf0\xff\xff\xff\xff\xda\xfe\xb5\x80\xff\xff\xff\xff\xdb\xc0s\xf0\xff\xff\xff\xff\xdcޗ\x80\xff\xff\xff\xffݩ\x90" + + "p\xff\xff\xff\xff\u07bey\x80\xff\xff\xff\xff߉rp\xff\xff\xff\xff\xe0\x9e[\x80\xff\xff\xff\xff\xe1iTp\xff\xff\xff\xff\xe2~=\x80\xff\xff\xff\xff\xe3I6p\xff\xff\xff\xff\xe4^\x1f\x80\xff\xff\xff" + + "\xff\xe8\xf2\x16\xf0\xff\xff\xff\xff\xea\a\x00\x00\xff\xff\xff\xff\xfe\xb8\x1c\xf0\xff\xff\xff\xff\xff\xa7\xff\xe0\x00\x00\x00\x00\x00\x97\xfe\xf0\x00\x00\x00\x00\x01\x87\xe1\xe0\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC" + + "`\x00\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05\x02\x05\x06\x05\x06\x05\x06\x05\x06\xff\xff\xaf:\x00\x00\xff\xff\xb9\xb0\x01\x04\xff" + + "\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14\xff\xff\xc7\xc0\x01\x18LMT\x00CDT\x00CST\x00CWT\x00CPT\x00EST\x00EDT\x00\nES" + + "T5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSg\xf5K\x89\xa2\x01\x00\x00\xa2\x01\x00\x00\x12\x00\x1c\x00America/R" + + "io_BrancoUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x1f\x00\x00\x00\x04\x00\x00\x00\f\xff\xff\xff\xff\x96\xaa\x86\x90\xff\xff\xff\xff\xb8\x0ff\x00\xff\xff\xff\xff\xb8\xfd\\\xc0\xff\xff\xff\xff\xb9\xf1PP\xff\xff\xff\xff\xbaސ@\xff\xff\xff\xff\xda8\xcaP" + + "\xff\xff\xff\xff\xda\xec\x16P\xff\xff\xff\xff\xdc\x19\xfd\xd0\xff\xff\xff\xffܹu@\xff\xff\xff\xff\xdd\xfb1P\xff\xff\xff\xffޛ\xfa@\xff\xff\xff\xff\xdfݶP\xff\xff\xff\xff\xe0TO@\xff\xff\xff\xff" + + "\xf4\x98\x1b\xd0\xff\xff\xff\xff\xf5\x05z@\xff\xff\xff\xff\xf6\xc0\x80P\xff\xff\xff\xff\xf7\x0e:\xc0\xff\xff\xff\xff\xf8QHP\xff\xff\xff\xff\xf8\xc7\xe1@\xff\xff\xff\xff\xfa\n\xee\xd0\xff\xff\xff\xff\xfa\xa9\x14\xc0" + + "\xff\xff\xff\xff\xfb\xec\"P\xff\xff\xff\xff\xfc\x8b\x99\xc0\x00\x00\x00\x00\x1dɪP\x00\x00\x00\x00\x1ex\xf3\xc0\x00\x00\x00\x00\x1f\xa0Q\xd0\x00\x00\x00\x00 3\xeb\xc0\x00\x00\x00\x00!\x81\x85P\x00\x00\x00\x00" + + "\"\v\xe4\xc0\x00\x00\x00\x00H`\u007fP\x00\x00\x00\x00R\u007f\x04\xc0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x02\xff\xff\xc0p\x00\x00\xff\xff\xc7" + + "\xc0\x01\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x00\x04LMT\x00-04\x00-05\x00\n<-05>5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x1e\xfbn۸\x03\x00\x00\xb8\x03\x00" + + "\x00\x14\x00\x1c\x00America/Campo_GrandeUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00[\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96\xaaz4\xff\xff\xff\xff\xb8\x0fW\xf0\xff\xff\xff\xff\xb8\xfdN\xb0\xff\xff\xff\xff\xb9\xf1B@" + + "\xff\xff\xff\xff\xbaނ0\xff\xff\xff\xff\xda8\xbc@\xff\xff\xff\xff\xda\xec\b@\xff\xff\xff\xff\xdc\x19\xef\xc0\xff\xff\xff\xffܹg0\xff\xff\xff\xff\xdd\xfb#@\xff\xff\xff\xffޛ\xec0\xff\xff\xff\xff" + + "\xdfݨ@\xff\xff\xff\xff\xe0TA0\xff\xff\xff\xff\xf4\x98\r\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf6\xc0r@\xff\xff\xff\xff\xf7\x0e,\xb0\xff\xff\xff\xff\xf8Q:@\xff\xff\xff\xff\xf8\xc7\xd30" + + "\xff\xff\xff\xff\xfa\n\xe0\xc0\xff\xff\xff\xff\xfa\xa9\x06\xb0\xff\xff\xff\xff\xfb\xec\x14@\xff\xff\xff\xff\xfc\x8b\x8b\xb0\x00\x00\x00\x00\x1dɜ@\x00\x00\x00\x00\x1ex\xe5\xb0\x00\x00\x00\x00\x1f\xa0C\xc0\x00\x00\x00\x00" + + " 3ݰ\x00\x00\x00\x00!\x81w@\x00\x00\x00\x00\"\vְ\x00\x00\x00\x00#X\x1e\xc0\x00\x00\x00\x00#\xe2~0\x00\x00\x00\x00%8\x00\xc0\x00\x00\x00\x00%\xd4\xd50\x00\x00\x00\x00'!\x1d@" + + "\x00\x00\x00\x00'\xbd\xf1\xb0\x00\x00\x00\x00)\x00\xff@\x00\x00\x00\x00)\x94\x990\x00\x00\x00\x00*\xea\x1b\xc0\x00\x00\x00\x00+k@\xb0\x00\x00\x00\x00,\xc0\xc3@\x00\x00\x00\x00-f\xd20\x00\x00\x00\x00" + + ".\xa0\xa5@\x00\x00\x00\x00/F\xb40\x00\x00\x00\x000\x80\x87@\x00\x00\x00\x001\x1d[\xb0\x00\x00\x00\x002W.\xc0\x00\x00\x00\x003\x06x0\x00\x00\x00\x0048b@\x00\x00\x00\x004\xf8\xcf0" + + "\x00\x00\x00\x006 -@\x00\x00\x00\x006\xcfv\xb0\x00\x00\x00\x007\xf6\xd4\xc0\x00\x00\x00\x008\xb8\x930\x00\x00\x00\x009\xdf\xf1@\x00\x00\x00\x00:\x8f:\xb0\x00\x00\x00\x00;\xc9\r\xc0\x00\x00\x00\x00" + + "N\xfe\xb0\x00\x00\x00\x00?\x92\f@\x00\x00\x00\x00@.\xe0\xb0\x00\x00\x00\x00A\x87\x06@\x00\x00\x00\x00B\x17\xfd0\x00\x00\x00\x00CQ\xd0@" + + "\x00\x00\x00\x00C\xf7\xdf0\x00\x00\x00\x00EMa\xc0\x00\x00\x00\x00E\xe0\xfb\xb0\x00\x00\x00\x00G\x11\x94@\x00\x00\x00\x00G\xb7\xa30\x00\x00\x00\x00H\xfa\xb0\xc0\x00\x00\x00\x00I\x97\x850\x00\x00\x00\x00" + + "Jڒ\xc0\x00\x00\x00\x00K\x80\xa1\xb0\x00\x00\x00\x00L\xbat\xc0\x00\x00\x00\x00M`\x83\xb0\x00\x00\x00\x00N\x9aV\xc0\x00\x00\x00\x00OI\xa00\x00\x00\x00\x00P\x83s@\x00\x00\x00\x00Q G\xb0" + + "\x00\x00\x00\x00RcU@\x00\x00\x00\x00S\x00)\xb0\x00\x00\x00\x00TC7@\x00\x00\x00\x00T\xe9F0\x00\x00\x00\x00V#\x19@\x00\x00\x00\x00V\xc9(0\x00\x00\x00\x00X\x02\xfb@\x00\x00\x00\x00" + + "X\xa9\n0\x00\x00\x00\x00Y\xe2\xdd@\x00\x00\x00\x00Z\x88\xec0\x00\x00\x00\x00[\xden\xc0\x00\x00\x00\x00\\h\xce0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\xff\xff\xcc\xcc\x00\x00\xff\xff\xd5\xd0\x01\x04\xff\xff\xc7\xc0\x00\bLMT\x00-03\x00-04\x00\n<-04>4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS{" + + "\a\a\xdc\xca\x03\x00\x00\xca\x03\x00\x00\x10\x00\x1c\x00America/EdmontonUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00T" + + "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Y\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\x88\xde\xce\xe0\xff\xff\xff\xff\x9e\xb8\xaf\x90\xff\xff\xff\xff\x9f\xbb\a\x80\xff\xff" + + "\xff\xff\xa0\x98\x91\x90\xff\xff\xff\xff\xa0҅\x80\xff\xff\xff\xff\xa2\x8a\xe8\x90\xff\xff\xff\xff\xa3\x84\x06\x00\xff\xff\xff\xff\xa4jʐ\xff\xff\xff\xff\xa55À\xff\xff\xff\xff\xa6S\xe7\x10\xff\xff\xff\xff\xa7\x15" + + "\xa5\x80\xff\xff\xff\xff\xa83\xc9\x10\xff\xff\xff\xff\xa8\xfe\xc2\x00\xff\xff\xff\xffˉ\f\x90\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff\xd5U\xe3\x10\xff\xff\xff\xff\xd6 \xdc\x00\x00\x00" + + "\x00\x00\x04a\x19\x90\x00\x00\x00\x00\x05P\xfc\x80\x00\x00\x00\x00\x06@\xfb\x90\x00\x00\x00\x00\a0ހ\x00\x00\x00\x00\b ݐ\x00\x00\x00\x00\t\x10\xc0\x80\x00\x00\x00\x00\n\x00\xbf\x90\x00\x00\x00\x00\n\xf0" + + "\xa2\x80\x00\x00\x00\x00\vࡐ\x00\x00\x00\x00\fٿ\x00\x00\x00\x00\x00\r\xc0\x83\x90\x00\x00\x00\x00\x0e\xb9\xa1\x00\x00\x00\x00\x00\x0f\xa9\xa0\x10\x00\x00\x00\x00\x10\x99\x83\x00\x00\x00\x00\x00\x11\x89\x82\x10\x00\x00" + + "\x00\x00\x12ye\x00\x00\x00\x00\x00\x13id\x10\x00\x00\x00\x00\x14YG\x00\x00\x00\x00\x00\x15IF\x10\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17)(\x10\x00\x00\x00\x00\x18\"E\x80\x00\x00\x00\x00\x19\t" + + "\n\x10\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2&\x90\x00\x00\x00\x00\x1b\xe2\t\x80\x00\x00\x00\x00\x1c\xd2\b\x90\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1\xea\x90\x00\x00\x00\x00\x1f\xa1̀\x00\x00" + + "\x00\x00 v\x1d\x10\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xff\x10\x00\x00\x00\x00#j\xcc\x00\x00\x00\x00\x00$5\xe1\x10\x00\x00\x00\x00%J\xae\x00\x00\x00\x00\x00&\x15\xc3\x10\x00\x00\x00\x00'*" + + "\x90\x00\x00\x00\x00\x00'\xfeߐ\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\xde\xc1\x90\x00\x00\x00\x00*\xeaT\x00\x00\x00\x00\x00+\xbe\xa3\x90\x00\x00\x00\x00,\xd3p\x80\x00\x00\x00\x00-\x9e\x85\x90\x00\x00" + + "\x00\x00.\xb3R\x80\x00\x00\x00\x00/~g\x90\x00\x00\x00\x000\x934\x80\x00\x00\x00\x001g\x84\x10\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003Gf\x10\x00\x00\x00\x004R\xf8\x80\x00\x00\x00\x005'" + + "H\x10\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe7\f\x10\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xc6\xee\x10\x00\x00\x00\x00;ۻ\x00\x00\x00" + + "\x00\x00<\xb0\n\x90\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8f\xec\x90\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@oΐ\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00BO\xb0\x90\x00\x00\x00\x00Cd" + + "}\x80\x00\x00\x00\x00D/\x92\x90\x00\x00\x00\x00ED_\x80\x00\x00\x00\x00E\xf3\xc5\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\x95\xa0\x00" + + "\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\f\xff\xff\xab\xa0\x01\x10LMT\x00MDT\x00MST\x00MWT\x00MPT\x00\nMST7MDT,M3.2.0" + + ",M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x11\x00\x1c\x00America/St_ThomasUT\t\x00" + + "\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x10\xff" + + "\xff\xff\xffz敹\xff\xff\xff\xff\xcb\xf62\xc0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\x01\x03\x02\x01\xff\xff\xc2\a\x00\x00\xff\xff\xc7\xc0\x00\x04\xff\xff\xd5\xd0\x01\b\xff\xff\xd5\xd0\x01\fL" + + "MT\x00AST\x00APT\x00AWT\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x0e\x00\x1c\x00America/V" + + "irginUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04" + + "\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffz敹\xff\xff\xff\xff\xcb\xf62\xc0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\x01\x03\x02\x01\xff\xff\xc2\a\x00\x00\xff\xff\xc7\xc0\x00\x04\xff\xff\xd5\xd0" + + "\x01\b\xff\xff\xd5\xd0\x01\fLMT\x00AST\x00APT\x00AWT\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSMv\xa1\x0f%\x01\x00\x00%\x01\x00\x00\x11\x00\x1c\x00" + + "America/MonterreyUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\xa5\xb6\xda`\x00\x00\x00\x00\"U\xf1\x00\x00\x00\x00\x00#j\xbd\xf0\x00\x00\x00\x001gv\x00\x00\x00\x00\x002s\bp" + + "\x00\x00\x00\x003GX\x00\x00\x00\x00\x004R\xeap\x00\x00\x00\x005':\x00\x00\x00\x00\x0062\xccp\x00\x00\x00\x007\a\x1c\x00\x00\x00\x00\x008\x1b\xe8\xf0\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x00" + + "9\xfb\xca\xf0\x00\x00\x00\x00:\xf5\x04\x80\x00\x00\x00\x00;\xb6\xc2\xf0\x00\x00\x00\x00<\xaf\xfc\x80\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xff\xa1\xf4\x00\x00\xff\xff\xab\xa0\x00\x04\xff\xff\xb9\xb0" + + "\x01\bLMT\x00CST\x00CDT\x00\nCST6CDT,M4.1.0,M10.5.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb4T\xbd\xeb5\x02\x00\x00" + + "5\x02\x00\x00\x16\x00\x1c\x00America/Port-au-PrinceUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZ" + + "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-\x00\x00\x00\x04\x00\x00\x00\x11\xff\xff\xff\xffi\x87\x1fP\xff\xff\xff\xff\x9cnq\xfc\x00\x00\x00\x00\x19\x1bF\xd0\x00\x00\x00" + + "\x00\x1a\x01\xef@\x00\x00\x00\x00\x1a\xf1\xeeP\x00\x00\x00\x00\x1b\xe1\xd1@\x00\x00\x00\x00\x1c\xd1\xd0P\x00\x00\x00\x00\x1d\xc1\xb3@\x00\x00\x00\x00\x1e\xb1\xb2P\x00\x00\x00\x00\x1f\xa1\x95@\x00\x00\x00\x00 \x91\x94" + + "P\x00\x00\x00\x00!\x81w@\x00\x00\x00\x00\"U\xd4\xe0\x00\x00\x00\x00#j\xaf\xe0\x00\x00\x00\x00$5\xb6\xe0\x00\x00\x00\x00%J\x91\xe0\x00\x00\x00\x00&\x15\x98\xe0\x00\x00\x00\x00'*s\xe0\x00\x00\x00" + + "\x00'\xfe\xb5`\x00\x00\x00\x00)\nU\xe0\x00\x00\x00\x00)ޗ`\x00\x00\x00\x00*\xea7\xe0\x00\x00\x00\x00+\xbey`\x00\x00\x00\x00,\xd3T`\x00\x00\x00\x00-\x9e[`\x00\x00\x00\x00.\xb36" + + "`\x00\x00\x00\x00/~=`\x00\x00\x00\x000\x93\x18`\x00\x00\x00\x001gY\xe0\x00\x00\x00\x002r\xfa`\x00\x00\x00\x003G;\xe0\x00\x00\x00\x004R\xdc`\x00\x00\x00\x00BOxP\x00\x00\x00" + + "\x00CdE@\x00\x00\x00\x00D/ZP\x00\x00\x00\x00ED'@\x00\x00\x00\x00O\\Mp\x00\x00\x00\x00P\x96\x04`\x00\x00\x00\x00Q4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x12\x00\x1c\x00America/St_Vince" + + "ntUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00" + + "\x04\x00\x00\x00\x10\xff\xff\xff\xffz敹\xff\xff\xff\xff\xcb\xf62\xc0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\x01\x03\x02\x01\xff\xff\xc2\a\x00\x00\xff\xff\xc7\xc0\x00\x04\xff\xff\xd5\xd0\x01\b\xff" + + "\xff\xd5\xd0\x01\fLMT\x00AST\x00APT\x00AWT\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xd0v\x01\x8a\x01\x04\x00\x00\x01\x04\x00\x00\x10\x00\x1c\x00Ame" + + "rica/EnsenadaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00^\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff\xa5\xb6\xf6\x80\xff\xff\xff\xff\xa9yOp\xff\xff\xff\xff\xaf\xf2|\xf0\xff\xff\xff\xff\xb6fdp\xff\xff\xff\xff\xb7\x1b\x10\x00\xff\xff\xff\xff" + + "\xb8\n\xf2\xf0\xff\xff\xff\xff\xcbꍀ\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xffҙ\xbap\xff\xff\xff\xff\xd7\x1bY\x00\xff\xff\xff\xffؑ\xb4\xf0\xff\xff\xff\xff\xe2~K\x90\xff\xff\xff\xff\xe3IR\x90" + + "\xff\xff\xff\xff\xe4^-\x90\xff\xff\xff\xff\xe5)4\x90\xff\xff\xff\xff\xe6GJ\x10\xff\xff\xff\xff\xe7\x12Q\x10\xff\xff\xff\xff\xe8',\x10\xff\xff\xff\xff\xe8\xf23\x10\xff\xff\xff\xff\xea\a\x0e\x10\xff\xff\xff\xff" + + "\xea\xd2\x15\x10\xff\xff\xff\xff\xeb\xe6\xf0\x10\xff\xff\xff\xff\xec\xb1\xf7\x10\xff\xff\xff\xff\xed\xc6\xd2\x10\xff\xff\xff\xff\xee\x91\xd9\x10\x00\x00\x00\x00\v\u0be0\x00\x00\x00\x00\f\xd9\xcd\x10\x00\x00\x00\x00\r\xc0\x91\xa0" + + "\x00\x00\x00\x00\x0e\xb9\xaf\x10\x00\x00\x00\x00\x0f\xa9\xae \x00\x00\x00\x00\x10\x99\x91\x10\x00\x00\x00\x00\x11\x89\x90 \x00\x00\x00\x00\x12ys\x10\x00\x00\x00\x00\x13ir \x00\x00\x00\x00\x14YU\x10\x00\x00\x00\x00" + + "\x15IT \x00\x00\x00\x00\x1697\x10\x00\x00\x00\x00\x17)6 \x00\x00\x00\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18 \x00\x00\x00\x00\x1a\x025\x90\x00\x00\x00\x00\x1a\xf24\xa0\x00\x00\x00\x00\x1b\xe2\x17\x90" + + "\x00\x00\x00\x00\x1c\xd2\x16\xa0\x00\x00\x00\x00\x1d\xc1\xf9\x90\x00\x00\x00\x00\x1e\xb1\xf8\xa0\x00\x00\x00\x00\x1f\xa1ې\x00\x00\x00\x00 v+ \x00\x00\x00\x00!\x81\xbd\x90\x00\x00\x00\x00\"V\r \x00\x00\x00\x00" + + "#j\xda\x10\x00\x00\x00\x00$5\xef \x00\x00\x00\x00%J\xbc\x10\x00\x00\x00\x00&\x15\xd1 \x00\x00\x00\x00'*\x9e\x10\x00\x00\x00\x00'\xfe\xed\xa0\x00\x00\x00\x00)\n\x80\x10\x00\x00\x00\x00)\xdeϠ" + + "\x00\x00\x00\x00*\xeab\x10\x00\x00\x00\x00+\xbe\xb1\xa0\x00\x00\x00\x00,\xd3~\x90\x00\x00\x00\x00-\x9e\x93\xa0\x00\x00\x00\x00.\xb3`\x90\x00\x00\x00\x00/~u\xa0\x00\x00\x00\x000\x93B\x90\x00\x00\x00\x00" + + "1g\x92 \x00\x00\x00\x002s$\x90\x00\x00\x00\x003Gt \x00\x00\x00\x004S\x06\x90\x00\x00\x00\x005'V \x00\x00\x00\x0062\xe8\x90\x00\x00\x00\x007\a8 \x00\x00\x00\x008\x1c\x05\x10" + + "\x00\x00\x00\x008\xe7\x1a \x00\x00\x00\x009\xfb\xe7\x10\x00\x00\x00\x00:\xc6\xfc \x00\x00\x00\x00;\xdb\xc9\x10\x00\x00\x00\x00<\xb0\x18\xa0\x00\x00\x00\x00=\xbb\xab\x10\x00\x00\x00\x00>\x8f\xfa\xa0\x00\x00\x00\x00" + + "?\x9b\x8d\x10\x00\x00\x00\x00@oܠ\x00\x00\x00\x00A\x84\xa9\x90\x00\x00\x00\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b\x90\x00\x00\x00\x00D/\xa0\xa0\x00\x00\x00\x00EDm\x90\x00\x00\x00\x00F\x0f\x82\xa0" + + "\x00\x00\x00\x00G$O\x90\x00\x00\x00\x00G\xf8\x9f \x00\x00\x00\x00I\x041\x90\x00\x00\x00\x00I\u0601 \x00\x00\x00\x00J\xe4\x13\x90\x00\x00\x00\x00K\x9c\xb3\xa0\x01\x02\x01\x02\x03\x02\x04\x05\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\xff\xff\x92L\x00\x00\xff\xff\x9d\x90\x00\x04\xff\xff\x8f\x80\x00\b\xff\xff\x9d\x90\x01\f\xff\xff\x9d\x90\x01\x10\xff\xff\x9d\x90\x01\x14LM" + + "T\x00MST\x00PST\x00PDT\x00PWT\x00PPT\x00\nPST8PDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS" + + "\xb1݂x\xe8\x00\x00\x00\xe8\x00\x00\x00\x12\x00\x1c\x00America/Costa_RicaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_" + + "\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x04\x00\x00\x00\x11\xff\xff\xff\xffi\x87*M\xff\xff\xff\xff\xa3\xe8\x16M\x00\x00\x00\x00\x116I" + + "`\x00\x00\x00\x00\x11\xb7nP\x00\x00\x00\x00\x13\x16+`\x00\x00\x00\x00\x13\x97PP\x00\x00\x00\x00'\x97\xe0`\x00\x00\x00\x00(n\xb6\xd0\x00\x00\x00\x00)w\xc2`\x00\x00\x00\x00)\xc2\xd9\xd0\x01\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\xff\xff\xb13\x00\x00\xff\xff\xb13\x00\x04\xff\xff\xb9\xb0\x01\t\xff\xff\xab\xa0\x00\rLMT\x00SJMT\x00CDT\x00CST\x00\nCST6\nPK\x03\x04\n\x00" + + "\x00\x00\x00\x00#\x82iS\xa2\x81\xbfyS\x02\x00\x00S\x02\x00\x00\x12\x00\x1c\x00America/MetlakatlaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01" + + "\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00" + + "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,\x00\x00\x00\b\x00\x00\x00\x1e\xff\xff\xff\xff?\xc2\xfd\xd1\xff\xff\xff\xff}\x870" + + "\x1a\xff\xff\xff\xffˉ\x1a\xa0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a&\x10\xff\xff\xff\xff\xfe\xb8G \xff\xff\xff\xff\xff\xa8*\x10\x00\x00\x00\x00\x00\x98) \x00\x00\x00\x00\x01\x88\f\x10\x00\x00\x00" + + "\x00\x02x\v \x00\x00\x00\x00\x03q(\x90\x00\x00\x00\x00\x04a'\xa0\x00\x00\x00\x00\x05Q\n\x90\x00\x00\x00\x00\x06A\t\xa0\x00\x00\x00\x00\a0\xec\x90\x00\x00\x00\x00\a\x8dC\xa0\x00\x00\x00\x00\t\x10\xce" + + "\x90\x00\x00\x00\x00\t\xad\xbf \x00\x00\x00\x00\n\xf0\xb0\x90\x00\x00\x00\x00\v\u0be0\x00\x00\x00\x00\f\xd9\xcd\x10\x00\x00\x00\x00\r\xc0\x91\xa0\x00\x00\x00\x00\x0e\xb9\xaf\x10\x00\x00\x00\x00\x0f\xa9\xae \x00\x00\x00" + + "\x00\x10\x99\x91\x10\x00\x00\x00\x00\x11\x89\x90 \x00\x00\x00\x00\x12ys\x10\x00\x00\x00\x00\x13ir \x00\x00\x00\x00\x14YU\x10\x00\x00\x00\x00\x15IT \x00\x00\x00\x00\x1697\x10\x00\x00\x00\x00\x17)6" + + " \x00\x00\x00\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18 \x00\x00\x00\x00\x1a\x025\x90\x00\x00\x00\x00V5\xe2\xa0\x00\x00\x00\x00V\xe5H0\x00\x00\x00\x00X\x1e\xff \x00\x00\x00\x00X\xc5*0\x00\x00\x00" + + "\x00Y\xfe\xe1 \x00\x00\x00\x00Z\xa5\f0\x00\x00\x00\x00[\xde\xc3 \x00\x00\x00\x00\\DF\xa0\x00\x00\x00\x00\\\x84\xee0\x01\x02\x03\x04\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02" + + "\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x06\a\x06\a\x06\a\x02\x06\a\x00\x00\xd6&\x00\x00\xff\xff\x84\xa6\x00\x00\xff\xff\x8f\x80\x00\x04\xff\xff\x9d\x90\x01\b\xff\xff\x9d\x90\x01\f\xff\xff\x9d\x90\x01\x10\xff\xff\x81" + + "p\x00\x14\xff\xff\x8f\x80\x01\x19LMT\x00PST\x00PWT\x00PPT\x00PDT\x00AKST\x00AKDT\x00\nAKST9AKDT,M3.2.0,M11" + + ".1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x0f\x00\x1c\x00America/CuracaoUT\t\x00\x03\x82\x0f\x8ba\x82" + + "\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00" + + "\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffz\xe6\x95" + + "\xb9\xff\xff\xff\xff\xcb\xf62\xc0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\x01\x03\x02\x01\xff\xff\xc2\a\x00\x00\xff\xff\xc7\xc0\x00\x04\xff\xff\xd5\xd0\x01\b\xff\xff\xd5\xd0\x01\fLMT\x00AST" + + "\x00APT\x00AWT\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xa7\x17jҲ\x00\x00\x00\xb2\x00\x00\x00\x12\x00\x1c\x00America/Martini" + + "queUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00" + + "\x00\x04\x00\x00\x00\x11\xff\xff\xff\xffi\x87\x14\xc4\xff\xff\xff\xff\x91\xa3\xc8D\x00\x00\x00\x00\x13Mn@\x00\x00\x00\x00\x144\x16\xb0\x01\x02\x03\x02\xff\xffƼ\x00\x00\xff\xffƼ\x00\x04\xff\xff\xc7\xc0\x00\t" + + "\xff\xff\xd5\xd0\x01\rLMT\x00FFMT\x00AST\x00ADT\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS~\xb2\x0e\x19V\a\x00\x00V\a\x00\x00\x10\x00\x1c\x00A" + + "merica/St_JohnsUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00[\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96\xaaz4\xff\xff\xff\xff\xb8\x0fW\xf0\xff\xff\xff\xff\xb8\xfdN\xb0\xff\xff\xff\xff\xb9\xf1B@\xff\xff\xff\xff\xbaނ0\xff\xff" + - "\xff\xff\xda8\xbc@\xff\xff\xff\xff\xda\xec\b@\xff\xff\xff\xff\xdc\x19\xef\xc0\xff\xff\xff\xffܹg0\xff\xff\xff\xff\xdd\xfb#@\xff\xff\xff\xffޛ\xec0\xff\xff\xff\xff\xdfݨ@\xff\xff\xff\xff\xe0T" + - "A0\xff\xff\xff\xff\xf4\x98\r\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf6\xc0r@\xff\xff\xff\xff\xf7\x0e,\xb0\xff\xff\xff\xff\xf8Q:@\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xfa\n\xe0\xc0\xff\xff" + - "\xff\xff\xfa\xa9\x06\xb0\xff\xff\xff\xff\xfb\xec\x14@\xff\xff\xff\xff\xfc\x8b\x8b\xb0\x00\x00\x00\x00\x1dɜ@\x00\x00\x00\x00\x1ex\xe5\xb0\x00\x00\x00\x00\x1f\xa0C\xc0\x00\x00\x00\x00 3ݰ\x00\x00\x00\x00!\x81" + - "w@\x00\x00\x00\x00\"\vְ\x00\x00\x00\x00#X\x1e\xc0\x00\x00\x00\x00#\xe2~0\x00\x00\x00\x00%8\x00\xc0\x00\x00\x00\x00%\xd4\xd50\x00\x00\x00\x00'!\x1d@\x00\x00\x00\x00'\xbd\xf1\xb0\x00\x00" + - "\x00\x00)\x00\xff@\x00\x00\x00\x00)\x94\x990\x00\x00\x00\x00*\xea\x1b\xc0\x00\x00\x00\x00+k@\xb0\x00\x00\x00\x00,\xc0\xc3@\x00\x00\x00\x00-f\xd20\x00\x00\x00\x00.\xa0\xa5@\x00\x00\x00\x00/F" + - "\xb40\x00\x00\x00\x000\x80\x87@\x00\x00\x00\x001\x1d[\xb0\x00\x00\x00\x002W.\xc0\x00\x00\x00\x003\x06x0\x00\x00\x00\x0048b@\x00\x00\x00\x004\xf8\xcf0\x00\x00\x00\x006 -@\x00\x00" + - "\x00\x006\xcfv\xb0\x00\x00\x00\x007\xf6\xd4\xc0\x00\x00\x00\x008\xb8\x930\x00\x00\x00\x009\xdf\xf1@\x00\x00\x00\x00:\x8f:\xb0\x00\x00\x00\x00;\xc9\r\xc0\x00\x00\x00\x00N\xfe\xb0\x00\x00\x00\x00?\x92\f@\x00\x00\x00\x00@.\xe0\xb0\x00\x00\x00\x00A\x87\x06@\x00\x00\x00\x00B\x17\xfd0\x00\x00\x00\x00CQ\xd0@\x00\x00\x00\x00C\xf7\xdf0\x00\x00" + - "\x00\x00EMa\xc0\x00\x00\x00\x00E\xe0\xfb\xb0\x00\x00\x00\x00G\x11\x94@\x00\x00\x00\x00G\xb7\xa30\x00\x00\x00\x00H\xfa\xb0\xc0\x00\x00\x00\x00I\x97\x850\x00\x00\x00\x00Jڒ\xc0\x00\x00\x00\x00K\x80" + - "\xa1\xb0\x00\x00\x00\x00L\xbat\xc0\x00\x00\x00\x00M`\x83\xb0\x00\x00\x00\x00N\x9aV\xc0\x00\x00\x00\x00OI\xa00\x00\x00\x00\x00P\x83s@\x00\x00\x00\x00Q G\xb0\x00\x00\x00\x00RcU@\x00\x00" + - "\x00\x00S\x00)\xb0\x00\x00\x00\x00TC7@\x00\x00\x00\x00T\xe9F0\x00\x00\x00\x00V#\x19@\x00\x00\x00\x00V\xc9(0\x00\x00\x00\x00X\x02\xfb@\x00\x00\x00\x00X\xa9\n0\x00\x00\x00\x00Y\xe2" + - "\xdd@\x00\x00\x00\x00Z\x88\xec0\x00\x00\x00\x00[\xden\xc0\x00\x00\x00\x00\\h\xce0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xff\xcc" + - "\xcc\x00\x00\xff\xff\xd5\xd0\x01\x04\xff\xff\xc7\xc0\x00\bLMT\x00-03\x00-04\x00\n<-04>4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R:\x9a1T\xdf\x01\x00\x00\xdf\x01\x00" + - "\x00\x14\x00\x1c\x00America/ScoresbysundUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbb\x00\x00\x00\b\x00\x00\x00\x19\xff\xff\xff\xff^=4\xec\xff\xff\xff\xff\x9c\xcfb\f\xff\xff\xff\xff\x9d\xa4\xe6\xfc\xff\xff\xff\xff\x9e\xb8~\x8c\xff\xff\xff\xff\x9f\xba\xd6|\xff\xff" + + "\xff\xff\xa0\xb6\x88\xdc\xff\xff\xff\xff\xa18\xffL\xff\xff\xff\xff\xa2\x95\x19\\\xff\xff\xff\xff\xa3\x84\xfcL\xff\xff\xff\xff\xa4t\xfb\\\xff\xff\xff\xff\xa5d\xdeL\xff\xff\xff\xff\xa6^\x17\xdc\xff\xff\xff\xff\xa7D" + + "\xc0L\xff\xff\xff\xff\xa8=\xf9\xdc\xff\xff\xff\xff\xa9$\xa2L\xff\xff\xff\xff\xaa\x1d\xdb\xdc\xff\xff\xff\xff\xab\x04\x84L\xff\xff\xff\xff\xab\xfd\xbd\xdc\xff\xff\xff\xff\xac\xe4fL\xff\xff\xff\xff\xadݟ\xdc\xff\xff" + + "\xff\xff\xae͂\xcc\xff\xff\xff\xff\xaf\xbd\x81\xdc\xff\xff\xff\xff\xb0\xadd\xcc\xff\xff\xff\xff\xb1\xa6\x9e\\\xff\xff\xff\xff\xb2\x8dF\xcc\xff\xff\xff\xff\xb3\x86\x80\\\xff\xff\xff\xff\xb4m(\xcc\xff\xff\xff\xff\xb5f" + + "b\\\xff\xff\xff\xff\xb6M\n\xcc\xff\xff\xff\xff\xb7FD\\\xff\xff\xff\xff\xb8,\xec\xcc\xff\xff\xff\xff\xb9&&\\\xff\xff\xff\xff\xba\x16\tL\xff\xff\xff\xff\xbb\x0fB\xdc\xff\xff\xff\xff\xbb\xf5\xebL\xff\xff" + + "\xff\xff\xbc\xef$\xdc\xff\xff\xff\xff\xbd\xd5\xcdL\xff\xff\xff\xff\xbe\x9eMl\xff\xff\xff\xff\xbe\xcf\x06\xa8\xff\xff\xff\xff\xbf\xb5\xaf\x18\xff\xff\xff\xff\xc0\xb818\xff\xff\xff\xff\xc1y\xef\xa8\xff\xff\xff\xff\u0098" + + "\x138\xff\xff\xff\xff\xc3YѨ\xff\xff\xff\xff\xc4w\xf58\xff\xff\xff\xff\xc59\xb3\xa8\xff\xff\xff\xff\xc6a\x11\xb8\xff\xff\xff\xff\xc7\x19\x95\xa8\xff\xff\xff\xff\xc8@\xf3\xb8\xff\xff\xff\xff\xc9\x02\xb2(\xff\xff" + + "\xff\xff\xca ո\xff\xff\xff\xff\xca\xe2\x94(\xff\xff\xff\xff\xcc\x00\xb7\xb8\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xe6\xc8\xff\xff\xff\xffӈD\xd8\xff\xff\xff\xff\xd4J\x03H\xff\xff\xff\xff\xd5h" + + "&\xd8\xff\xff\xff\xff\xd6)\xe5H\xff\xff\xff\xff\xd7H\b\xd8\xff\xff\xff\xff\xd8\t\xc7H\xff\xff\xff\xff\xd9'\xea\xd8\xff\xff\xff\xff\xd9\xe9\xa9H\xff\xff\xff\xff\xdb\x11\aX\xff\xff\xff\xff\xdb\xd2\xc5\xc8\xff\xff" + + "\xff\xff\xdc\xdetX\xff\xff\xff\xffݩmH\xff\xff\xff\xff\u07beVX\xff\xff\xff\xff߉OH\xff\xff\xff\xff\xe0\x9e8X\xff\xff\xff\xff\xe1i1H\xff\xff\xff\xff\xe2~\x1aX\xff\xff\xff\xff\xe3I" + + "\x13H\xff\xff\xff\xff\xe4]\xfcX\xff\xff\xff\xff\xe5(\xf5H\xff\xff\xff\xff\xe6G\x18\xd8\xff\xff\xff\xff\xe7\x12\x11\xc8\xff\xff\xff\xff\xe8&\xfa\xd8\xff\xff\xff\xff\xe8\xf1\xf3\xc8\xff\xff\xff\xff\xea\x06\xdc\xd8\xff\xff" + + "\xff\xff\xea\xd1\xd5\xc8\xff\xff\xff\xff\xeb\xe6\xbe\xd8\xff\xff\xff\xff챷\xc8\xff\xff\xff\xff\xedƠ\xd8\xff\xff\xff\xff\ueffeH\xff\xff\xff\xffﯽX\xff\xff\xff\xff\xf0\x9f\xa0H\xff\xff\xff\xff\xf1\x8f" + + "\x9fX\xff\xff\xff\xff\xf2\u007f\x82H\xff\xff\xff\xff\xf3o\x81X\xff\xff\xff\xff\xf4_dH\xff\xff\xff\xff\xf5OcX\xff\xff\xff\xff\xf6?FH\xff\xff\xff\xff\xf7/EX\xff\xff\xff\xff\xf8(b\xc8\xff\xff" + + "\xff\xff\xf9\x0f'X\xff\xff\xff\xff\xfa\bD\xc8\xff\xff\xff\xff\xfa\xf8C\xd8\xff\xff\xff\xff\xfb\xe8&\xc8\xff\xff\xff\xff\xfc\xd8%\xd8\xff\xff\xff\xff\xfd\xc8\b\xc8\xff\xff\xff\xff\xfe\xb8\a\xd8\xff\xff\xff\xff\xff\xa7" + + "\xea\xc8\x00\x00\x00\x00\x00\x97\xe9\xd8\x00\x00\x00\x00\x01\x87\xcc\xc8\x00\x00\x00\x00\x02w\xcb\xd8\x00\x00\x00\x00\x03p\xe9H\x00\x00\x00\x00\x04`\xe8X\x00\x00\x00\x00\x05P\xcbH\x00\x00\x00\x00\x06@\xcaX\x00\x00" + + "\x00\x00\a0\xadH\x00\x00\x00\x00\b \xacX\x00\x00\x00\x00\t\x10\x8fH\x00\x00\x00\x00\n\x00\x8eX\x00\x00\x00\x00\n\xf0qH\x00\x00\x00\x00\v\xe0pX\x00\x00\x00\x00\fٍ\xc8\x00\x00\x00\x00\r\xc0" + + "RX\x00\x00\x00\x00\x0e\xb9o\xc8\x00\x00\x00\x00\x0f\xa9n\xd8\x00\x00\x00\x00\x10\x99Q\xc8\x00\x00\x00\x00\x11\x89P\xd8\x00\x00\x00\x00\x12y3\xc8\x00\x00\x00\x00\x13i2\xd8\x00\x00\x00\x00\x14Y\x15\xc8\x00\x00" + + "\x00\x00\x15I\x14\xd8\x00\x00\x00\x00\x168\xf7\xc8\x00\x00\x00\x00\x17(\xf6\xd8\x00\x00\x00\x00\x18\"\x14H\x00\x00\x00\x00\x19\b\xd8\xd8\x00\x00\x00\x00\x1a\x01\xf6H\x00\x00\x00\x00\x1a\xf1\xf5X\x00\x00\x00\x00\x1b\xe1" + + "\xd8H\x00\x00\x00\x00\x1c\xd1\xd7X\x00\x00\x00\x00\x1d\xc1\xbaH\x00\x00\x00\x00\x1e\xb1\xb9X\x00\x00\x00\x00\x1f\xa1\x9cH\x00\x00\x00\x00 u\xcf\xf4\x00\x00\x00\x00!\x81bd\x00\x00\x00\x00\"U\xb1\xf4\x00\x00" + + "\x00\x00#jp\xd4\x00\x00\x00\x00$5\x93\xf4\x00\x00\x00\x00%J`\xe4\x00\x00\x00\x00&\x15u\xf4\x00\x00\x00\x00'*B\xe4\x00\x00\x00\x00'\xfe\x92t\x00\x00\x00\x00)\n$\xe4\x00\x00\x00\x00)\xde" + + "tt\x00\x00\x00\x00*\xea\x06\xe4\x00\x00\x00\x00+\xbeVt\x00\x00\x00\x00,\xd3#d\x00\x00\x00\x00-\x9e8t\x00\x00\x00\x00.\xb3\x05d\x00\x00\x00\x00/~\x1at\x00\x00\x00\x000\x92\xe7d\x00\x00" + + "\x00\x001g6\xf4\x00\x00\x00\x002r\xc9d\x00\x00\x00\x003G\x18\xf4\x00\x00\x00\x004R\xabd\x00\x00\x00\x005&\xfa\xf4\x00\x00\x00\x0062\x8dd\x00\x00\x00\x007\x06\xdc\xf4\x00\x00\x00\x008\x1b" + + "\xa9\xe4\x00\x00\x00\x008\xe6\xbe\xf4\x00\x00\x00\x009\xfb\x8b\xe4\x00\x00\x00\x00:Ơ\xf4\x00\x00\x00\x00;\xdbm\xe4\x00\x00\x00\x00<\xaf\xbdt\x00\x00\x00\x00=\xbbO\xe4\x00\x00\x00\x00>\x8f\x9ft\x00\x00" + + "\x00\x00?\x9b1\xe4\x00\x00\x00\x00@o\x81t\x00\x00\x00\x00A\x84Nd\x00\x00\x00\x00BOct\x00\x00\x00\x00Cd0d\x00\x00\x00\x00D/Et\x00\x00\x00\x00ED\x12d\x00\x00\x00\x00E\xf3" + + "w\xf4\x00\x00\x00\x00G-.\xe4\x00\x00\x00\x00G\xd3Y\xf4\x00\x00\x00\x00I\r\x10\xe4\x00\x00\x00\x00I\xb3;\xf4\x00\x00\x00\x00J\xec\xf2\xe4\x00\x00\x00\x00K\x9cXt\x00\x00\x00\x00L\xd6\x0fd\x00\x00" + + "\x00\x00M|:t\x00\x00\x00\x00N\xb6\rH\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04" + + "\x03\x04\x03\x04\x03\x04\x06\x05\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03" + + "\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\a\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03" + + "\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\xff\xffΔ\x00\x00\xff\xffܤ\x01\x04\xff\xffΔ\x00\b\xff\xff\xdc\xd8\x01\x04\xff\xff\xce\xc8\x00\b\xff\xff\xdc\xd8\x01\f\xff\xff\xdc" + + "\xd8\x01\x10\xff\xff\xea\xe8\x01\x14LMT\x00NDT\x00NST\x00NPT\x00NWT\x00NDDT\x00\nNST3:30NDT,M3.2.0,M11.1.0" + + "\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSutZ\x1a\xb2\x02\x00\x00\xb2\x02\x00\x00\r\x00\x1c\x00America/JujuyUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v" + + "\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00" + + "\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00;\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xae\xb8\xff\xff\xff\xff\xa2" + + "\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff" + + "\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3" + + "~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff" + + "\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5" + + "\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff" + + "\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$" + + "\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'*W\xc0\x00\x00\x00\x00'\xe2۰\x00\x00\x00\x00(\xee\x8a@\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00" + + "\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x02\x03\x02\x04\x05\x04\x05\x03\x05\x04\x05\xff\xff\xc2\xc8\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0" + + "\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSP\x0f(\b" + + "=\x01\x00\x00=\x01\x00\x00\x15\x00\x1c\x00America/Santo_DomingoUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01" + + "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\x06\x00\x00\x00\x1b\xff\xff\xff\xffi\x87\x1d\b\xff\xff\xff\xff\xba\xdfB`\xff\xff\xff\xff\xfa\bK\xd0" + + "\xff\xff\xff\xff\xfa\xa7\xc3@\xff\xff\xff\xff\xff\xa7\xf1\xd0\x00\x00\x00\x00\x00C{\xc8\x00\x00\x00\x00\x01\x87\xd3\xd0\x00\x00\x00\x00\x01\xfa\u007fH\x00\x00\x00\x00\x03p\xf0P\x00\x00\x00\x00\x03\xdd\x04H\x00\x00\x00\x00" + + "\x05P\xd2P\x00\x00\x00\x00\x05\xbf\x89H\x00\x00\x00\x00\a0\xb4P\x00\x00\x00\x00\a\xa0\xbc\xc8\x00\x00\x00\x00\t\x10\x96P\x00\x00\x00\x009\xfb\xbc\xe0\x00\x00\x00\x00:)\xe1`\x01\x03\x02\x03\x04\x03\x04\x03" + + "\x04\x03\x04\x03\x04\x03\x05\x03\x05\xff\xff\xbex\x00\x00\xff\xff\xbe`\x00\x04\xff\xff\xc7\xc0\x01\t\xff\xff\xb9\xb0\x00\r\xff\xff\xc0\xb8\x01\x11\xff\xff\xc7\xc0\x00\x17LMT\x00SDMT\x00EDT\x00ES" + + "T\x00-0430\x00AST\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\u0096dK~\x02\x00\x00~\x02\x00\x00\x0e\x00\x1c\x00America/Regi" + + "naUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x005\x00\x00\x00" + + "\x06\x00\x00\x00\x18\xff\xff\xff\xff\x86\xfd\x93\x1c\xff\xff\xff\xff\x9e\xb8\xaf\x90\xff\xff\xff\xff\x9f\xbb\a\x80\xff\xff\xff\xff\xb5eO\xf0\xff\xff\xff\xff\xb60H\xe0\xff\xff\xff\xff\xb7E1\xf0\xff\xff\xff\xff\xb8\x10*" + + "\xe0\xff\xff\xff\xff\xb9%\x13\xf0\xff\xff\xff\xff\xb9\xf0\f\xe0\xff\xff\xff\xff\xbb\x0e0p\xff\xff\xff\xff\xbb\xcf\xee\xe0\xff\xff\xff\xff\xbc\xee\x12p\xff\xff\xff\xff\xbd\xb9\v`\xff\xff\xff\xff\xc2r\b\xf0\xff\xff\xff" + + "\xff\xc3a\xeb\xe0\xff\xff\xff\xff\xc4Q\xea\xf0\xff\xff\xff\xff\xc58\x93`\xff\xff\xff\xff\xc61\xcc\xf0\xff\xff\xff\xff\xc7!\xaf\xe0\xff\xff\xff\xff\xc8\x1a\xe9p\xff\xff\xff\xff\xc9\n\xcc`\xff\xff\xff\xff\xc9\xfa\xcb" + + "p\xff\xff\xff\xff\xca\xea\xae`\xff\xff\xff\xffˉ\f\x90\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff\xd3c\x8c\x10\xff\xff\xff\xff\xd4So\x00\xff\xff\xff\xff\xd5U\xe3\x10\xff\xff\xff" + + "\xff\xd6 \xdc\x00\xff\xff\xff\xff\xd75\xc5\x10\xff\xff\xff\xff\xd8\x00\xbe\x00\xff\xff\xff\xff\xd9\x15\xa7\x10\xff\xff\xff\xff\xd9\xe0\xa0\x00\xff\xff\xff\xff\xda\xfeÐ\xff\xff\xff\xff\xdb\xc0\x82\x00\xff\xff\xff\xff\xdcޥ" + + "\x90\xff\xff\xff\xffݩ\x9e\x80\xff\xff\xff\xff\u07be\x87\x90\xff\xff\xff\xff߉\x80\x80\xff\xff\xff\xff\xe0\x9ei\x90\xff\xff\xff\xff\xe1ib\x80\xff\xff\xff\xff\xe2~K\x90\xff\xff\xff\xff\xe3ID\x80\xff\xff\xff" + + "\xff\xe4^-\x90\xff\xff\xff\xff\xe5)&\x80\xff\xff\xff\xff\xe6GJ\x10\xff\xff\xff\xff\xe7\x12C\x00\xff\xff\xff\xff\xe8',\x10\xff\xff\xff\xff\xe8\xf2%\x00\xff\xff\xff\xff\xeb\xe6\xf0\x10\xff\xff\xff\xff\xec\xd6\xd3" + + "\x00\xff\xff\xff\xff\xed\xc6\xd2\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x05\xff\xff\x9d\xe4\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\f\xff\xff\xab\xa0\x01\x10\xff\xff\xab\xa0\x00\x14LMT\x00MDT\x00MST\x00MWT\x00MPT\x00CS" + + "T\x00\nCST6\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSp\x1b\xceRC\x03\x00\x00C\x03\x00\x00\x0f\x00\x1c\x00America/NipigonUT\t\x00\x03\x82\x0f" + + "\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00J\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff" + + "r\xee\x81@\xff\xff\xff\xff\x9e\xb8\x93p\xff\xff\xff\xff\x9f\xba\xeb`\xff\xff\xff\xff\xc8\xf8IP\xff\xff\xff\xffˈ\xf0p\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xfb\xe0\x00\x00\x00\x00\b \xc1p" + + "\x00\x00\x00\x00\t\x10\xa4`\x00\x00\x00\x00\n\x00\xa3p\x00\x00\x00\x00\n\xf0\x86`\x00\x00\x00\x00\v\xe0\x85p\x00\x00\x00\x00\f٢\xe0\x00\x00\x00\x00\r\xc0gp\x00\x00\x00\x00\x0e\xb9\x84\xe0\x00\x00\x00\x00" + + "\x0f\xa9\x83\xf0\x00\x00\x00\x00\x10\x99f\xe0\x00\x00\x00\x00\x11\x89e\xf0\x00\x00\x00\x00\x12yH\xe0\x00\x00\x00\x00\x13iG\xf0\x00\x00\x00\x00\x14Y*\xe0\x00\x00\x00\x00\x15I)\xf0\x00\x00\x00\x00\x169\f\xe0" + + "\x00\x00\x00\x00\x17)\v\xf0\x00\x00\x00\x00\x18\")`\x00\x00\x00\x00\x19\b\xed\xf0\x00\x00\x00\x00\x1a\x02\v`\x00\x00\x00\x00\x1a\xf2\np\x00\x00\x00\x00\x1b\xe1\xed`\x00\x00\x00\x00\x1c\xd1\xecp\x00\x00\x00\x00" + + "\x1d\xc1\xcf`\x00\x00\x00\x00\x1e\xb1\xcep\x00\x00\x00\x00\x1f\xa1\xb1`\x00\x00\x00\x00 v\x00\xf0\x00\x00\x00\x00!\x81\x93`\x00\x00\x00\x00\"U\xe2\xf0\x00\x00\x00\x00#j\xaf\xe0\x00\x00\x00\x00$5\xc4\xf0" + + "\x00\x00\x00\x00%J\x91\xe0\x00\x00\x00\x00&\x15\xa6\xf0\x00\x00\x00\x00'*s\xe0\x00\x00\x00\x00'\xfe\xc3p\x00\x00\x00\x00)\nU\xe0\x00\x00\x00\x00)ޥp\x00\x00\x00\x00*\xea7\xe0\x00\x00\x00\x00" + + "+\xbe\x87p\x00\x00\x00\x00,\xd3T`\x00\x00\x00\x00-\x9eip\x00\x00\x00\x00.\xb36`\x00\x00\x00\x00/~Kp\x00\x00\x00\x000\x93\x18`\x00\x00\x00\x001gg\xf0\x00\x00\x00\x002r\xfa`" + + "\x00\x00\x00\x003GI\xf0\x00\x00\x00\x004R\xdc`\x00\x00\x00\x005'+\xf0\x00\x00\x00\x0062\xbe`\x00\x00\x00\x007\a\r\xf0\x00\x00\x00\x008\x1b\xda\xe0\x00\x00\x00\x008\xe6\xef\xf0\x00\x00\x00\x00" + + "9\xfb\xbc\xe0\x00\x00\x00\x00:\xc6\xd1\xf0\x00\x00\x00\x00;۞\xe0\x00\x00\x00\x00<\xaf\xeep\x00\x00\x00\x00=\xbb\x80\xe0\x00\x00\x00\x00>\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00@o\xb2p" + + "\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x03\x04\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\xff\xff\xad@\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x01\f\xff\xff\xc7\xc0\x01\x10LMT\x00EDT\x00EST\x00EWT\x00EPT\x00\nEST5EDT" + + ",M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSo_\x00v/\x01\x00\x00/\x01\x00\x00\x0e\x00\x1c\x00America/Merida" + + "UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x04\x00" + + "\x00\x00\x10\xff\xff\xff\xff\xa5\xb6\xda`\x00\x00\x00\x00\x16\x86\xd5`\x00\x00\x00\x00\x18LKP\x00\x00\x00\x001gv\x00\x00\x00\x00\x002s\bp\x00\x00\x00\x003GX\x00\x00\x00\x00\x004R\xeap\x00" + + "\x00\x00\x005':\x00\x00\x00\x00\x0062\xccp\x00\x00\x00\x007\a\x1c\x00\x00\x00\x00\x008\x1b\xe8\xf0\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xca\xf0\x00\x00\x00\x00:\xf5\x04\x80\x00\x00\x00\x00;" + + "\xb6\xc2\xf0\x00\x00\x00\x00<\xaf\xfc\x80\x01\x02\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\xff\xff\xab\xfc\x00\x00\xff\xff\xab\xa0\x00\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xb9\xb0\x01\fLMT\x00CST\x00E" + + "ST\x00CDT\x00\nCST6CDT,M4.1.0,M10.5.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSn\xab\xd5\xf9\xcf\x03\x00\x00\xcf\x03\x00\x00\f\x00\x1c" + + "\x00America/NomeUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00T\x00\x00\x00\n\x00\x00\x00&\xff\xff\xff\xff?\xc2\xfd\xd1\xff\xff\xff\xff}\x87O\xd2\xff\xff\xff\xffˉD\xd0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2aP@\xff\xff\xff\xff" + + "\xfa\xd2U\xb0\xff\xff\xff\xff\xfe\xb8qP\xff\xff\xff\xff\xff\xa8T@\x00\x00\x00\x00\x00\x98SP\x00\x00\x00\x00\x01\x886@\x00\x00\x00\x00\x02x5P\x00\x00\x00\x00\x03qR\xc0\x00\x00\x00\x00\x04aQ\xd0" + + "\x00\x00\x00\x00\x05Q4\xc0\x00\x00\x00\x00\x06A3\xd0\x00\x00\x00\x00\a1\x16\xc0\x00\x00\x00\x00\a\x8dm\xd0\x00\x00\x00\x00\t\x10\xf8\xc0\x00\x00\x00\x00\t\xad\xe9P\x00\x00\x00\x00\n\xf0\xda\xc0\x00\x00\x00\x00" + + "\v\xe0\xd9\xd0\x00\x00\x00\x00\f\xd9\xf7@\x00\x00\x00\x00\r\xc0\xbb\xd0\x00\x00\x00\x00\x0e\xb9\xd9@\x00\x00\x00\x00\x0f\xa9\xd8P\x00\x00\x00\x00\x10\x99\xbb@\x00\x00\x00\x00\x11\x89\xbaP\x00\x00\x00\x00\x12y\x9d@" + + "\x00\x00\x00\x00\x13i\x9cP\x00\x00\x00\x00\x14Y\u007f@\x00\x00\x00\x00\x15I~P\x00\x00\x00\x00\x169a@\x00\x00\x00\x00\x17)`P\x00\x00\x00\x00\x18\"}\xc0\x00\x00\x00\x00\x19\tBP\x00\x00\x00\x00" + + "\x1a\x02_\xc0\x00\x00\x00\x00\x1a+\x14\x10\x00\x00\x00\x00\x1a\xf2B\xb0\x00\x00\x00\x00\x1b\xe2%\xa0\x00\x00\x00\x00\x1c\xd2$\xb0\x00\x00\x00\x00\x1d\xc2\a\xa0\x00\x00\x00\x00\x1e\xb2\x06\xb0\x00\x00\x00\x00\x1f\xa1\xe9\xa0" + + "\x00\x00\x00\x00 v90\x00\x00\x00\x00!\x81ˠ\x00\x00\x00\x00\"V\x1b0\x00\x00\x00\x00#j\xe8 \x00\x00\x00\x00$5\xfd0\x00\x00\x00\x00%J\xca \x00\x00\x00\x00&\x15\xdf0\x00\x00\x00\x00" + + "'*\xac \x00\x00\x00\x00'\xfe\xfb\xb0\x00\x00\x00\x00)\n\x8e \x00\x00\x00\x00)\xdeݰ\x00\x00\x00\x00*\xeap \x00\x00\x00\x00+\xbe\xbf\xb0\x00\x00\x00\x00,ӌ\xa0\x00\x00\x00\x00-\x9e\xa1\xb0" + + "\x00\x00\x00\x00.\xb3n\xa0\x00\x00\x00\x00/~\x83\xb0\x00\x00\x00\x000\x93P\xa0\x00\x00\x00\x001g\xa00\x00\x00\x00\x002s2\xa0\x00\x00\x00\x003G\x820\x00\x00\x00\x004S\x14\xa0\x00\x00\x00\x00" + + "5'd0\x00\x00\x00\x0062\xf6\xa0\x00\x00\x00\x007\aF0\x00\x00\x00\x008\x1c\x13 \x00\x00\x00\x008\xe7(0\x00\x00\x00\x009\xfb\xf5 \x00\x00\x00\x00:\xc7\n0\x00\x00\x00\x00;\xdb\xd7 " + + "\x00\x00\x00\x00<\xb0&\xb0\x00\x00\x00\x00=\xbb\xb9 \x00\x00\x00\x00>\x90\b\xb0\x00\x00\x00\x00?\x9b\x9b \x00\x00\x00\x00@o\xea\xb0\x00\x00\x00\x00A\x84\xb7\xa0\x00\x00\x00\x00BO̰\x00\x00\x00\x00" + + "Cd\x99\xa0\x00\x00\x00\x00D/\xae\xb0\x00\x00\x00\x00ED{\xa0\x00\x00\x00\x00E\xf3\xe10\x01\x02\x03\x04\x02\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05" + + "\x06\x05\x06\a\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\x00\x00\xb6n\x00\x00\xff\xff" + + "d\xee\x00\x00\xff\xffeP\x00\x04\xff\xffs`\x01\b\xff\xffs`\x01\f\xff\xffeP\x00\x10\xff\xffs`\x01\x14\xff\xff\x81p\x00\x18\xff\xff\x8f\x80\x01\x1c\xff\xff\x81p\x00!LMT\x00NST\x00" + + "NWT\x00NPT\x00BST\x00BDT\x00YST\x00AKDT\x00AKST\x00\nAKST9AKDT,M3.2.0,M11.1.0\nPK\x03\x04" + + "\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x1c\x00America/Indiana/UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01" + + "\x04\x14E\x00\x00\x04S_\x01\x00PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSصK\xa6\n\x02\x00\x00\n\x02\x00\x00\x19\x00\x1c\x00America/Indiana/Tell" + + "_CityUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00%" + + "\x00\x00\x00\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff" + + "\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xe4g=\xe0\xff\xff\xff\xff\xe5)\x18p\xff\xff\xff\xff\xe6G<\x00\xff\xff\xff\xff\xe7\x124\xf0\xff\xff\xff\xff\xe8'\x1e\x00\xff\xff\xff\xff\xe8\xf2\x16\xf0" + + "\xff\xff\xff\xff\xea\a\x00\x00\xff\xff\xff\xff\xea\xd1\xf8\xf0\xff\xff\xff\xff\xeb\xe6\xe2\x00\xff\xff\xff\xff\xec\xb1\xda\xf0\xff\xff\xff\xff\xed\xc6\xc4\x00\xff\xff\xff\xff\ue47c\xf0\xff\xff\xff\xff\xef\xaf\xe0\x80\xff\xff\xff\xff" + + "\xf0\x9f\xc3p\xff\xff\xff\xff\xf1\x8f\u0080\xff\xff\xff\xff\xf2\u007f\xa5p\xff\xff\xff\xff\xf3o\xa4\x80\xff\xff\xff\xff\xf4_\x87p\xff\xff\xff\xff\xf5O\x86\x80\xff\xff\xff\xff\xfb\xe8I\xf0\xff\xff\xff\xff\xfc\xd8I\x00" + + "\xff\xff\xff\xff\xfd\xc8+\xf0\xff\xff\xff\xff\xfe\xb8+\x00\xff\xff\xff\xff\xff\xa7\xff\xe0\x00\x00\x00\x00\x00\x97\xfe\xf0\x00\x00\x00\x00\x01\x87\xe1\xe0\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDQp\x00\x00\x00\x00" + + "E\xf3\xb7\x00\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05\x02\x01\x02\x06\x05\x06\x05\x01\x02\x01\xff\xff\xae\xa9\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff" + + "\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14\xff\xff\xc7\xc0\x01\x18LMT\x00CDT\x00CST\x00CWT\x00CPT\x00EST\x00EDT\x00\nCST6CDT," + + "M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSp\xb6{\xc9\x13\x02\x00\x00\x13\x02\x00\x00\x1c\x00\x1c\x00America/Indiana" + + "/IndianapolisUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00&\x00\x00\x00\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xff" + + "\xcaW\"\x80\xff\xff\xff\xff\xca\xd8Gp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xd3u\xf3\x00\xff\xff\xff\xff\xd4@\xeb\xf0\xff\xff\xff\xff\xd5U\xd5\x00" + + "\xff\xff\xff\xff\xd6 \xcd\xf0\xff\xff\xff\xff\xd75\xb7\x00\xff\xff\xff\xff\xd8\x00\xaf\xf0\xff\xff\xff\xff\xd9\x15\x99\x00\xff\xff\xff\xff\xd9\xe0\x91\xf0\xff\xff\xff\xff\xda\xfe\xb5\x80\xff\xff\xff\xff\xdb\xc0s\xf0\xff\xff\xff\xff" + + "\xdcޗ\x80\xff\xff\xff\xffݩ\x90p\xff\xff\xff\xff\u07bey\x80\xff\xff\xff\xff߉rp\xff\xff\xff\xff\xe0\x9e[\x80\xff\xff\xff\xff\xe1iTp\xff\xff\xff\xff\xe2~=\x80\xff\xff\xff\xff\xe3I6p" + + "\xff\xff\xff\xff\xe4^\x1f\x80\xff\xff\xff\xff\xe8\xf2\x16\xf0\xff\xff\xff\xff\xea\a\x00\x00\xff\xff\xff\xff\xfe\xb8\x1c\xf0\xff\xff\xff\xff\xff\xa7\xff\xe0\x00\x00\x00\x00\x00\x97\xfe\xf0\x00\x00\x00\x00\x01\x87\xe1\xe0\x00\x00\x00\x00" + + "D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05\x02\x05\x06\x05\x06\x05\x06\x05\x06\xff\xff" + + "\xaf:\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14\xff\xff\xc7\xc0\x01\x18LMT\x00CDT\x00CST\x00CWT\x00CPT\x00" + + "EST\x00EDT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSM/U\x9f7\x02\x00\x007\x02\x00\x00\x17\x00" + + "\x1c\x00America/Indiana/MarengoUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\"\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\x9b\x80L\x18\x00\x00\x00\x00\x13Mn@\x00\x00\x00\x00\x144$\xc0\x00\x00\x00\x00\x15#\xf9\xa0" + - "\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00" + - "\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#1<+00>,M3.5.0/0,M10.5.0/1\nPK\x03\x04\n\x00\x00\x00" + - "\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15\x00\x1c\x00America/North_Dakota/UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00" + - "\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RH\xeam\xef\xde\x03\x00\x00\xde\x03\x00\x00\x1b\x00\x1c\x00America/North_Dakot" + - "a/CenterUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00Y\x00\x00\x00\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x04\f\xb0\xff\xff\xff\xff\x9e\xa6:\x90\xff\xff\xff\xff\x9f\xbb\a\x80\xff\xff\xff\xff\xa0\x86\x1c\x90\xff\xff\xff\xff\xa1\x9a\xe9\x80\xff\xff\xff\xffˉ\f\x90\xff" + - "\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff\xfa\xf8u\x10\xff\xff\xff\xff\xfb\xe8X\x00\xff\xff\xff\xff\xfc\xd8W\x10\xff\xff\xff\xff\xfd\xc8:\x00\xff\xff\xff\xff\xfe\xb89\x10\xff\xff\xff\xff\xff" + - "\xa8\x1c\x00\x00\x00\x00\x00\x00\x98\x1b\x10\x00\x00\x00\x00\x01\x87\xfe\x00\x00\x00\x00\x00\x02w\xfd\x10\x00\x00\x00\x00\x03q\x1a\x80\x00\x00\x00\x00\x04a\x19\x90\x00\x00\x00\x00\x05P\xfc\x80\x00\x00\x00\x00\x06@\xfb\x90\x00" + - "\x00\x00\x00\a0ހ\x00\x00\x00\x00\a\x8d5\x90\x00\x00\x00\x00\t\x10\xc0\x80\x00\x00\x00\x00\t\xad\xb1\x10\x00\x00\x00\x00\n\xf0\xa2\x80\x00\x00\x00\x00\vࡐ\x00\x00\x00\x00\fٿ\x00\x00\x00\x00\x00\r" + - "\xc0\x83\x90\x00\x00\x00\x00\x0e\xb9\xa1\x00\x00\x00\x00\x00\x0f\xa9\xa0\x10\x00\x00\x00\x00\x10\x99\x83\x00\x00\x00\x00\x00\x11\x89\x82\x10\x00\x00\x00\x00\x12ye\x00\x00\x00\x00\x00\x13id\x10\x00\x00\x00\x00\x14YG\x00\x00" + - "\x00\x00\x00\x15IF\x10\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17)(\x10\x00\x00\x00\x00\x18\"E\x80\x00\x00\x00\x00\x19\t\n\x10\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2&\x90\x00\x00\x00\x00\x1b" + - "\xe2\t\x80\x00\x00\x00\x00\x1c\xd2\b\x90\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1\xea\x90\x00\x00\x00\x00\x1f\xa1̀\x00\x00\x00\x00 v\x1d\x10\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xff\x10\x00" + - "\x00\x00\x00#j\xcc\x00\x00\x00\x00\x00$5\xe1\x10\x00\x00\x00\x00%J\xae\x00\x00\x00\x00\x00&\x15\xc3\x10\x00\x00\x00\x00'*\x90\x00\x00\x00\x00\x00'\xfeߐ\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)" + - "\xde\xc1\x90\x00\x00\x00\x00*\xeaT\x00\x00\x00\x00\x00+\xbe\x95\x80\x00\x00\x00\x00,\xd3bp\x00\x00\x00\x00-\x9ew\x80\x00\x00\x00\x00.\xb3Dp\x00\x00\x00\x00/~Y\x80\x00\x00\x00\x000\x93&p\x00" + - "\x00\x00\x001gv\x00\x00\x00\x00\x002s\bp\x00\x00\x00\x003GX\x00\x00\x00\x00\x004R\xeap\x00\x00\x00\x005':\x00\x00\x00\x00\x0062\xccp\x00\x00\x00\x007\a\x1c\x00\x00\x00\x00\x008" + - "\x1b\xe8\xf0\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xca\xf0\x00\x00\x00\x00:\xc6\xe0\x00\x00\x00\x00\x00;۬\xf0\x00\x00\x00\x00<\xaf\xfc\x80\x00\x00\x00\x00=\xbb\x8e\xf0\x00\x00\x00\x00>\x8fހ\x00" + - "\x00\x00\x00?\x9bp\xf0\x00\x00\x00\x00@o\xc0\x80\x00\x00\x00\x00A\x84\x8dp\x00\x00\x00\x00BO\xa2\x80\x00\x00\x00\x00Cdop\x00\x00\x00\x00D/\x84\x80\x00\x00\x00\x00EDQp\x00\x00\x00\x00E" + - "\xf3\xb7\x00\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\xff\xff\xa1\b\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\f\xff\xff\xab\xa0" + - "\x01\x10\xff\xff\xb9\xb0\x01\x14\xff\xff\xab\xa0\x00\x18LMT\x00MDT\x00MST\x00MWT\x00MPT\x00CDT\x00CST\x00\nCST6CDT,M3.2.0,M1" + - "1.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RR\x1b\x8b(\xde\x03\x00\x00\xde\x03\x00\x00\x1e\x00\x1c\x00America/North_Dakota/New" + - "_SalemUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "Y\x00\x00\x00\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x04\f\xb0\xff\xff\xff\xff\x9e\xa6:\x90\xff\xff\xff\xff\x9f\xbb\a\x80\xff\xff\xff\xff\xa0\x86\x1c\x90\xff\xff\xff\xff\xa1\x9a\xe9\x80\xff\xff\xff\xffˉ\f\x90\xff\xff\xff" + - "\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff\xfa\xf8u\x10\xff\xff\xff\xff\xfb\xe8X\x00\xff\xff\xff\xff\xfc\xd8W\x10\xff\xff\xff\xff\xfd\xc8:\x00\xff\xff\xff\xff\xfe\xb89\x10\xff\xff\xff\xff\xff\xa8\x1c" + - "\x00\x00\x00\x00\x00\x00\x98\x1b\x10\x00\x00\x00\x00\x01\x87\xfe\x00\x00\x00\x00\x00\x02w\xfd\x10\x00\x00\x00\x00\x03q\x1a\x80\x00\x00\x00\x00\x04a\x19\x90\x00\x00\x00\x00\x05P\xfc\x80\x00\x00\x00\x00\x06@\xfb\x90\x00\x00\x00" + - "\x00\a0ހ\x00\x00\x00\x00\a\x8d5\x90\x00\x00\x00\x00\t\x10\xc0\x80\x00\x00\x00\x00\t\xad\xb1\x10\x00\x00\x00\x00\n\xf0\xa2\x80\x00\x00\x00\x00\vࡐ\x00\x00\x00\x00\fٿ\x00\x00\x00\x00\x00\r\xc0\x83" + - "\x90\x00\x00\x00\x00\x0e\xb9\xa1\x00\x00\x00\x00\x00\x0f\xa9\xa0\x10\x00\x00\x00\x00\x10\x99\x83\x00\x00\x00\x00\x00\x11\x89\x82\x10\x00\x00\x00\x00\x12ye\x00\x00\x00\x00\x00\x13id\x10\x00\x00\x00\x00\x14YG\x00\x00\x00\x00" + - "\x00\x15IF\x10\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17)(\x10\x00\x00\x00\x00\x18\"E\x80\x00\x00\x00\x00\x19\t\n\x10\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2&\x90\x00\x00\x00\x00\x1b\xe2\t" + - "\x80\x00\x00\x00\x00\x1c\xd2\b\x90\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1\xea\x90\x00\x00\x00\x00\x1f\xa1̀\x00\x00\x00\x00 v\x1d\x10\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xff\x10\x00\x00\x00" + - "\x00#j\xcc\x00\x00\x00\x00\x00$5\xe1\x10\x00\x00\x00\x00%J\xae\x00\x00\x00\x00\x00&\x15\xc3\x10\x00\x00\x00\x00'*\x90\x00\x00\x00\x00\x00'\xfeߐ\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\xde\xc1" + - "\x90\x00\x00\x00\x00*\xeaT\x00\x00\x00\x00\x00+\xbe\xa3\x90\x00\x00\x00\x00,\xd3p\x80\x00\x00\x00\x00-\x9e\x85\x90\x00\x00\x00\x00.\xb3R\x80\x00\x00\x00\x00/~g\x90\x00\x00\x00\x000\x934\x80\x00\x00\x00" + - "\x001g\x84\x10\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003Gf\x10\x00\x00\x00\x004R\xf8\x80\x00\x00\x00\x005'H\x10\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b\xf7" + - "\x00\x00\x00\x00\x008\xe7\f\x10\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xc6\xee\x10\x00\x00\x00\x00;ۻ\x00\x00\x00\x00\x00<\xb0\n\x90\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8f\xec\x90\x00\x00\x00" + - "\x00?\x9b\u007f\x00\x00\x00\x00\x00@o\xc0\x80\x00\x00\x00\x00A\x84\x8dp\x00\x00\x00\x00BO\xa2\x80\x00\x00\x00\x00Cdop\x00\x00\x00\x00D/\x84\x80\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7" + - "\x00\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x06\x05\x06\x05\x06\x05\x06\x05\xff\xff\xa0\xed\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\f\xff\xff\xab\xa0\x01\x10" + - "\xff\xff\xb9\xb0\x01\x14\xff\xff\xab\xa0\x00\x18LMT\x00MDT\x00MST\x00MWT\x00MPT\x00CDT\x00CST\x00\nCST6CDT,M3.2.0,M11." + - "1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xb7.\xb6*\x13\x04\x00\x00\x13\x04\x00\x00\x1b\x00\x1c\x00America/North_Dakota/Beula" + - "hUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x00\x00\x00\x06" + - "\x00\x00\x00\x18\xff\xff\xff\xff^\x04\f\xb0\xff\xff\xff\xff\x9e\xa6:\x90\xff\xff\xff\xff\x9f\xbb\a\x80\xff\xff\xff\xff\xa0\x86\x1c\x90\xff\xff\xff\xff\xa1\x9a\xe9\x80\xff\xff\xff\xffˉ\f\x90\xff\xff\xff\xff\xd2#\xf4p" + - "\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff\xfa\xf8u\x10\xff\xff\xff\xff\xfb\xe8X\x00\xff\xff\xff\xff\xfc\xd8W\x10\xff\xff\xff\xff\xfd\xc8:\x00\xff\xff\xff\xff\xfe\xb89\x10\xff\xff\xff\xff\xff\xa8\x1c\x00\x00\x00\x00\x00" + - "\x00\x98\x1b\x10\x00\x00\x00\x00\x01\x87\xfe\x00\x00\x00\x00\x00\x02w\xfd\x10\x00\x00\x00\x00\x03q\x1a\x80\x00\x00\x00\x00\x04a\x19\x90\x00\x00\x00\x00\x05P\xfc\x80\x00\x00\x00\x00\x06@\xfb\x90\x00\x00\x00\x00\a0ހ" + - "\x00\x00\x00\x00\a\x8d5\x90\x00\x00\x00\x00\t\x10\xc0\x80\x00\x00\x00\x00\t\xad\xb1\x10\x00\x00\x00\x00\n\xf0\xa2\x80\x00\x00\x00\x00\vࡐ\x00\x00\x00\x00\fٿ\x00\x00\x00\x00\x00\r\xc0\x83\x90\x00\x00\x00\x00" + - "\x0e\xb9\xa1\x00\x00\x00\x00\x00\x0f\xa9\xa0\x10\x00\x00\x00\x00\x10\x99\x83\x00\x00\x00\x00\x00\x11\x89\x82\x10\x00\x00\x00\x00\x12ye\x00\x00\x00\x00\x00\x13id\x10\x00\x00\x00\x00\x14YG\x00\x00\x00\x00\x00\x15IF\x10" + - "\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17)(\x10\x00\x00\x00\x00\x18\"E\x80\x00\x00\x00\x00\x19\t\n\x10\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2&\x90\x00\x00\x00\x00\x1b\xe2\t\x80\x00\x00\x00\x00" + - "\x1c\xd2\b\x90\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1\xea\x90\x00\x00\x00\x00\x1f\xa1̀\x00\x00\x00\x00 v\x1d\x10\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xff\x10\x00\x00\x00\x00#j\xcc\x00" + - "\x00\x00\x00\x00$5\xe1\x10\x00\x00\x00\x00%J\xae\x00\x00\x00\x00\x00&\x15\xc3\x10\x00\x00\x00\x00'*\x90\x00\x00\x00\x00\x00'\xfeߐ\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\xde\xc1\x90\x00\x00\x00\x00" + - "*\xeaT\x00\x00\x00\x00\x00+\xbe\xa3\x90\x00\x00\x00\x00,\xd3p\x80\x00\x00\x00\x00-\x9e\x85\x90\x00\x00\x00\x00.\xb3R\x80\x00\x00\x00\x00/~g\x90\x00\x00\x00\x000\x934\x80\x00\x00\x00\x001g\x84\x10" + - "\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003Gf\x10\x00\x00\x00\x004R\xf8\x80\x00\x00\x00\x005'H\x10\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x00" + - "8\xe7\f\x10\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xc6\xee\x10\x00\x00\x00\x00;ۻ\x00\x00\x00\x00\x00<\xb0\n\x90\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8f\xec\x90\x00\x00\x00\x00?\x9b\u007f\x00" + - "\x00\x00\x00\x00@oΐ\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00BO\xb0\x90\x00\x00\x00\x00Cd}\x80\x00\x00\x00\x00D/\x92\x90\x00\x00\x00\x00ED_\x80\x00\x00\x00\x00E\xf3\xc5\x10\x00\x00\x00\x00" + - "G-|\x00\x00\x00\x00\x00Gӧ\x10\x00\x00\x00\x00I\r^\x00\x00\x00\x00\x00I\xb3\x89\x10\x00\x00\x00\x00J\xed@\x00\x00\x00\x00\x00K\x9c\xa5\x90\x00\x00\x00\x00L\xd6\\\x80\x02\x01\x02\x01\x02\x03\x04\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x05\xff\xff\xa0\x95\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\f\xff\xff\xab\xa0\x01\x10\xff\xff" + - "\xab\xa0\x00\x14LMT\x00MDT\x00MST\x00MWT\x00MPT\x00CST\x00\nCST6CDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00" + - "\x00\x00\xf1c9R\x1d\xf7\a ,\x06\x00\x00,\x06\x00\x00\x11\x00\x1c\x00America/Goose_BayUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03" + - "\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + - "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x98\x00\x00\x00\n\x00\x00\x00!\xff\xff\xff\xff^=<$\xff\xff\xff\xff\x9e\xb8~\x8c\xff\xff" + - "\xff\xff\x9f\xba\xd6|\xff\xff\xff\xff\xbe\x9eMl\xff\xff\xff\xff\xc0\xb818\xff\xff\xff\xff\xc1y\xef\xa8\xff\xff\xff\xff\u0098\x138\xff\xff\xff\xff\xc3YѨ\xff\xff\xff\xff\xc4w\xf58\xff\xff\xff\xff\xc59" + - "\xb3\xa8\xff\xff\xff\xff\xc6a\x11\xb8\xff\xff\xff\xff\xc7\x19\x95\xa8\xff\xff\xff\xff\xc8@\xf3\xb8\xff\xff\xff\xff\xc9\x02\xb2(\xff\xff\xff\xff\xca ո\xff\xff\xff\xff\xca\xe2\x94(\xff\xff\xff\xff\xcc\x00\xb7\xb8\xff\xff" + - "\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xe6\xc8\xff\xff\xff\xffӈD\xd8\xff\xff\xff\xff\xd4J\x03H\xff\xff\xff\xff\xd5h&\xd8\xff\xff\xff\xff\xd6)\xe5H\xff\xff\xff\xff\xd7H\b\xd8\xff\xff\xff\xff\xd8\t" + - "\xc7H\xff\xff\xff\xff\xd9'\xea\xd8\xff\xff\xff\xff\xd9\xe9\xa9H\xff\xff\xff\xff\xdb\x11\aX\xff\xff\xff\xff\xdb\xd2\xc5\xc8\xff\xff\xff\xff\xdc\xdetX\xff\xff\xff\xffݩmH\xff\xff\xff\xff\u07beVX\xff\xff" + - "\xff\xff߉OH\xff\xff\xff\xff\xe0\x9e8X\xff\xff\xff\xff\xe1i1H\xff\xff\xff\xff\xe2~\x1aX\xff\xff\xff\xff\xe3I\x13H\xff\xff\xff\xff\xe4]\xfcX\xff\xff\xff\xff\xe5(\xf5H\xff\xff\xff\xff\xe6G" + - "\x18\xd8\xff\xff\xff\xff\xe7\x12\x11\xc8\xff\xff\xff\xff\xe8&\xfa\xd8\xff\xff\xff\xff\xe8\xf1\xf3\xc8\xff\xff\xff\xff\xea\x06\xdc\xd8\xff\xff\xff\xff\xea\xd1\xd5\xc8\xff\xff\xff\xff\xeb\xe6\xbe\xd8\xff\xff\xff\xff챷\xc8\xff\xff" + - "\xff\xff\xedƠ\xd8\xff\xff\xff\xff\ueffeH\xff\xff\xff\xffﯽX\xff\xff\xff\xff\xf0\x9f\xa0H\xff\xff\xff\xff\xf1\x8f\x9fX\xff\xff\xff\xff\xf2\u007f\x82H\xff\xff\xff\xff\xf3o\x81X\xff\xff\xff\xff\xf4_" + - "dH\xff\xff\xff\xff\xf5OcX\xff\xff\xff\xff\xf6?FH\xff\xff\xff\xff\xf7/EX\xff\xff\xff\xff\xf8(b\xc8\xff\xff\xff\xff\xf8\xdakX\xff\xff\xff\xff\xf9\x0f.`\xff\xff\xff\xff\xfa\bK\xd0\xff\xff" + - "\xff\xff\xfa\xf8J\xe0\xff\xff\xff\xff\xfb\xe8-\xd0\xff\xff\xff\xff\xfc\xd8,\xe0\xff\xff\xff\xff\xfd\xc8\x0f\xd0\xff\xff\xff\xff\xfe\xb8\x0e\xe0\xff\xff\xff\xff\xff\xa7\xf1\xd0\x00\x00\x00\x00\x00\x97\xf0\xe0\x00\x00\x00\x00\x01\x87" + - "\xd3\xd0\x00\x00\x00\x00\x02w\xd2\xe0\x00\x00\x00\x00\x03p\xf0P\x00\x00\x00\x00\x04`\xef`\x00\x00\x00\x00\x05P\xd2P\x00\x00\x00\x00\x06@\xd1`\x00\x00\x00\x00\a0\xb4P\x00\x00\x00\x00\b \xb3`\x00\x00" + - "\x00\x00\t\x10\x96P\x00\x00\x00\x00\n\x00\x95`\x00\x00\x00\x00\n\xf0xP\x00\x00\x00\x00\v\xe0w`\x00\x00\x00\x00\fٔ\xd0\x00\x00\x00\x00\r\xc0Y`\x00\x00\x00\x00\x0e\xb9v\xd0\x00\x00\x00\x00\x0f\xa9" + - "u\xe0\x00\x00\x00\x00\x10\x99X\xd0\x00\x00\x00\x00\x11\x89W\xe0\x00\x00\x00\x00\x12y:\xd0\x00\x00\x00\x00\x13i9\xe0\x00\x00\x00\x00\x14Y\x1c\xd0\x00\x00\x00\x00\x15I\x1b\xe0\x00\x00\x00\x00\x168\xfe\xd0\x00\x00" + - "\x00\x00\x17(\xfd\xe0\x00\x00\x00\x00\x18\"\x1bP\x00\x00\x00\x00\x19\b\xdf\xe0\x00\x00\x00\x00\x1a\x01\xfdP\x00\x00\x00\x00\x1a\xf1\xfc`\x00\x00\x00\x00\x1b\xe1\xdfP\x00\x00\x00\x00\x1c\xd1\xde`\x00\x00\x00\x00\x1d\xc1" + - "\xc1P\x00\x00\x00\x00\x1e\xb1\xc0`\x00\x00\x00\x00\x1f\xa1\xa3P\x00\x00\x00\x00 u\xd6\xfc\x00\x00\x00\x00!\x81il\x00\x00\x00\x00\"U\xb8\xfc\x00\x00\x00\x00#jw\xdc\x00\x00\x00\x00$5\x9a\xfc\x00\x00" + - "\x00\x00%Jg\xec\x00\x00\x00\x00&\x15|\xfc\x00\x00\x00\x00'*I\xec\x00\x00\x00\x00'\xfe\x99|\x00\x00\x00\x00)\n+\xec\x00\x00\x00\x00)\xde{|\x00\x00\x00\x00*\xea\r\xec\x00\x00\x00\x00+\xbe" + - "]|\x00\x00\x00\x00,\xd3*l\x00\x00\x00\x00-\x9e?|\x00\x00\x00\x00.\xb3\fl\x00\x00\x00\x00/~!|\x00\x00\x00\x000\x92\xeel\x00\x00\x00\x001g=\xfc\x00\x00\x00\x002r\xd0l\x00\x00" + - "\x00\x003G\x1f\xfc\x00\x00\x00\x004R\xb2l\x00\x00\x00\x005'\x01\xfc\x00\x00\x00\x0062\x94l\x00\x00\x00\x007\x06\xe3\xfc\x00\x00\x00\x008\x1b\xb0\xec\x00\x00\x00\x008\xe6\xc5\xfc\x00\x00\x00\x009\xfb" + - "\x92\xec\x00\x00\x00\x00:Ƨ\xfc\x00\x00\x00\x00;\xdbt\xec\x00\x00\x00\x00<\xaf\xc4|\x00\x00\x00\x00=\xbbV\xec\x00\x00\x00\x00>\x8f\xa6|\x00\x00\x00\x00?\x9b8\xec\x00\x00\x00\x00@o\x88|\x00\x00" + - "\x00\x00A\x84Ul\x00\x00\x00\x00BOj|\x00\x00\x00\x00Cd7l\x00\x00\x00\x00D/L|\x00\x00\x00\x00ED\x19l\x00\x00\x00\x00E\xf3~\xfc\x00\x00\x00\x00G-5\xec\x00\x00\x00\x00G\xd3" + - "`\xfc\x00\x00\x00\x00I\r\x17\xec\x00\x00\x00\x00I\xb3B\xfc\x00\x00\x00\x00J\xec\xf9\xec\x00\x00\x00\x00K\x9c_|\x00\x00\x00\x00L\xd6\x16l\x00\x00\x00\x00M|A|\x00\x00\x00\x00N\xb6\x14P\x01\x02" + - "\x01\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x06\x05\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\b\a\b" + - "\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\t\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b" + - "\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\xff\xff\xc7\\\x00\x00\xff\xffΔ\x00\x04\xff\xffܤ\x01\b\xff\xff\xce\xc8\x00\x04\xff\xff\xdc\xd8\x01\b" + - "\xff\xff\xdc\xd8\x01\f\xff\xff\xdc\xd8\x01\x10\xff\xff\xd5\xd0\x01\x14\xff\xff\xc7\xc0\x00\x18\xff\xff\xe3\xe0\x01\x1cLMT\x00NST\x00NDT\x00NPT\x00NWT\x00ADT\x00AST\x00AD" + - "DT\x00\nAST4ADT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rp\xb6{\xc9\x13\x02\x00\x00\x13\x02\x00\x00\x12\x00\x1c\x00Ame" + - "rica/Fort_WayneUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00*\x00\x00\x00\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80" + + "\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xdcޗ\x80\xff\xff\xff\xffݩ\x90p\xff\xff\xff\xff\xe2~=\x80\xff\xff\xff\xff" + + "\xe3I6p\xff\xff\xff\xff\xe4^\x1f\x80\xff\xff\xff\xff\xe5)\x18p\xff\xff\xff\xff\xe6G<\x00\xff\xff\xff\xff\xe7\x124\xf0\xff\xff\xff\xff\xe8'\x1e\x00\xff\xff\xff\xff\xe8\xf2\x16\xf0\xff\xff\xff\xff\xea\a\x00\x00" + + "\xff\xff\xff\xff\xea\xd1\xf8\xf0\xff\xff\xff\xff\xeb\xe6\xe2\x00\xff\xff\xff\xff\xec\xb1\xda\xf0\xff\xff\xff\xff\xed\xc6\xc4\x00\xff\xff\xff\xff\ue47c\xf0\xff\xff\xff\xff\xef\xaf\xe0\x80\xff\xff\xff\xff\xfe\xb8\x1c\xf0\xff\xff\xff\xff" + + "\xff\xa7\xff\xe0\x00\x00\x00\x00\x00\x97\xfe\xf0\x00\x00\x00\x00\x01\x87\xe1\xe0\x00\x00\x00\x00\x02w\xe0\xf0\x00\x00\x00\x00\x03p\xfe`\x00\x00\x00\x00\x04`\xfdp\x00\x00\x00\x00\x05P\xe0`\x00\x00\x00\x00\x06@\xdfp" + + "\x00\x00\x00\x00\a0\xc2`\x00\x00\x00\x00\a\x8d\x19p\x00\x00\x00\x00\t\x10\xb2p\x00\x00\x00\x00\t\xad\x94\xf0\x00\x00\x00\x00\n\xf0\x86`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00" + + "E\xf3\xa8\xf0\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x01\x05\x06\x05\x06\x05\x06\xff\xff\xaf\r\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff" + + "\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14\xff\xff\xc7\xc0\x01\x18LMT\x00CDT\x00CST\x00CWT\x00CPT\x00EST\x00EDT\x00\nEST" + + "5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\r\xedsp.\x02\x00\x00.\x02\x00\x00\x19\x00\x1c\x00America/In" + + "diana/VincennesUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00&\x00\x00\x00\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff" + - "\xff\xff\xcaW\"\x80\xff\xff\xff\xff\xca\xd8Gp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xd3u\xf3\x00\xff\xff\xff\xff\xd4@\xeb\xf0\xff\xff\xff\xff\xd5U" + - "\xd5\x00\xff\xff\xff\xff\xd6 \xcd\xf0\xff\xff\xff\xff\xd75\xb7\x00\xff\xff\xff\xff\xd8\x00\xaf\xf0\xff\xff\xff\xff\xd9\x15\x99\x00\xff\xff\xff\xff\xd9\xe0\x91\xf0\xff\xff\xff\xff\xda\xfe\xb5\x80\xff\xff\xff\xff\xdb\xc0s\xf0\xff\xff" + - "\xff\xff\xdcޗ\x80\xff\xff\xff\xffݩ\x90p\xff\xff\xff\xff\u07bey\x80\xff\xff\xff\xff߉rp\xff\xff\xff\xff\xe0\x9e[\x80\xff\xff\xff\xff\xe1iTp\xff\xff\xff\xff\xe2~=\x80\xff\xff\xff\xff\xe3I" + - "6p\xff\xff\xff\xff\xe4^\x1f\x80\xff\xff\xff\xff\xe8\xf2\x16\xf0\xff\xff\xff\xff\xea\a\x00\x00\xff\xff\xff\xff\xfe\xb8\x1c\xf0\xff\xff\xff\xff\xff\xa7\xff\xe0\x00\x00\x00\x00\x00\x97\xfe\xf0\x00\x00\x00\x00\x01\x87\xe1\xe0\x00\x00" + - "\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05\x02\x05\x06\x05\x06\x05\x06\x05\x06" + - "\xff\xff\xaf:\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14\xff\xff\xc7\xc0\x01\x18LMT\x00CDT\x00CST\x00CWT\x00CP" + - "T\x00EST\x00EDT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R):\x17-\x88\x06\x00\x00\x88\x06\x00\x00" + - "\x0f\x00\x1c\x00America/HalifaxUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa7\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\x80\xf1\xab\xa0\xff\xff\xff\xff\x9a\xe4\xde\xc0\xff\xff\xff\xff\x9b\xd6\x130\xff\xff\xff\xff\x9e\xb8\x85`\xff\xff\xff\xff\x9f\xba" + - "\xddP\xff\xff\xff\xff\xa2\x9d\x17@\xff\xff\xff\xff\xa30\xb10\xff\xff\xff\xff\xa4zV@\xff\xff\xff\xff\xa5\x1b\x1f0\xff\xff\xff\xff\xa6S\xa0\xc0\xff\xff\xff\xff\xa6\xfcR\xb0\xff\xff\xff\xff\xa8<\xbd@\xff\xff" + - "\xff\xff\xa8\xdc4\xb0\xff\xff\xff\xff\xaa\x1c\x9f@\xff\xff\xff\xff\xaa\xcd:0\xff\xff\xff\xff\xab\xfc\x81@\xff\xff\xff\xff\xac\xbf\x910\xff\xff\xff\xff\xad\xee\xd8@\xff\xff\xff\xff\xae\x8c\xfe0\xff\xff\xff\xff\xaf\xbc" + - "E@\xff\xff\xff\xff\xb0\u007fU0\xff\xff\xff\xff\xb1\xae\x9c@\xff\xff\xff\xff\xb2Kp\xb0\xff\xff\xff\xff\xb3\x8e~@\xff\xff\xff\xff\xb4$\xbb0\xff\xff\xff\xff\xb5n`@\xff\xff\xff\xff\xb6\x15\xc0\xb0\xff\xff" + - "\xff\xff\xb7NB@\xff\xff\xff\xff\xb8\b\x17\xb0\xff\xff\xff\xff\xb9$\xe9\xc0\xff\xff\xff\xff\xb9\xe7\xf9\xb0\xff\xff\xff\xff\xbb\x04\xcb\xc0\xff\xff\xff\xff\xbb\xd1\x160\xff\xff\xff\xff\xbd\x00]@\xff\xff\xff\xff\xbd\x9d" + - "1\xb0\xff\xff\xff\xff\xbe\xf2\xb4@\xff\xff\xff\xff\xbf\x90\xda0\xff\xff\xff\xff\xc0\xd3\xe7\xc0\xff\xff\xff\xff\xc1^G0\xff\xff\xff\xff\u008d\x8e@\xff\xff\xff\xff\xc3P\x9e0\xff\xff\xff\xff\xc4mp@\xff\xff" + - "\xff\xff\xc50\x800\xff\xff\xff\xff\xc6r<@\xff\xff\xff\xff\xc7\x10b0\xff\xff\xff\xff\xc86n\xc0\xff\xff\xff\xff\xc8\xf9~\xb0\xff\xff\xff\xff\xca\x16P\xc0\xff\xff\xff\xff\xca\xd9`\xb0\xff\xff\xff\xffˈ" + - "\xe2`\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\xff\xff\xff\xff\xd3u\xd6\xe0\xff\xff\xff\xff\xd4@\xcf\xd0\xff\xff\xff\xff\xd5U\xb8\xe0\xff\xff\xff\xff\xd6 \xb1\xd0\xff\xff\xff\xff\xd75\x9a\xe0\xff\xff" + - "\xff\xff\xd8\x00\x93\xd0\xff\xff\xff\xff\xd9\x15|\xe0\xff\xff\xff\xff\xd9\xe0u\xd0\xff\xff\xff\xff\xdc\xde{`\xff\xff\xff\xffݩtP\xff\xff\xff\xff\u07be]`\xff\xff\xff\xff߉VP\xff\xff\xff\xff\xe0\x9e" + - "?`\xff\xff\xff\xff\xe1i8P\xff\xff\xff\xff\xe2~!`\xff\xff\xff\xff\xe3I\x1aP\xff\xff\xff\xff\xe6G\x1f\xe0\xff\xff\xff\xff\xe7\x12\x18\xd0\xff\xff\xff\xff\xe8'\x01\xe0\xff\xff\xff\xff\xe8\xf1\xfa\xd0\xff\xff" + - "\xff\xff\xea\x06\xe3\xe0\xff\xff\xff\xff\xea\xd1\xdc\xd0\xff\xff\xff\xff\xeb\xe6\xc5\xe0\xff\xff\xff\xff챾\xd0\xff\xff\xff\xff\xf1\x8f\xa6`\xff\xff\xff\xff\xf2\u007f\x89P\xff\xff\xff\xff\xf3o\x88`\xff\xff\xff\xff\xf4_" + - "kP\xff\xff\xff\xff\xf5Oj`\xff\xff\xff\xff\xf6?MP\xff\xff\xff\xff\xf7/L`\xff\xff\xff\xff\xf8(i\xd0\xff\xff\xff\xff\xf9\x0f.`\xff\xff\xff\xff\xfa\bK\xd0\xff\xff\xff\xff\xfa\xf8J\xe0\xff\xff" + - "\xff\xff\xfb\xe8-\xd0\xff\xff\xff\xff\xfc\xd8,\xe0\xff\xff\xff\xff\xfd\xc8\x0f\xd0\xff\xff\xff\xff\xfe\xb8\x0e\xe0\xff\xff\xff\xff\xff\xa7\xf1\xd0\x00\x00\x00\x00\x00\x97\xf0\xe0\x00\x00\x00\x00\x01\x87\xd3\xd0\x00\x00\x00\x00\x02w" + - "\xd2\xe0\x00\x00\x00\x00\x03p\xf0P\x00\x00\x00\x00\x04`\xef`\x00\x00\x00\x00\x05P\xd2P\x00\x00\x00\x00\x06@\xd1`\x00\x00\x00\x00\a0\xb4P\x00\x00\x00\x00\b \xb3`\x00\x00\x00\x00\t\x10\x96P\x00\x00" + - "\x00\x00\n\x00\x95`\x00\x00\x00\x00\n\xf0xP\x00\x00\x00\x00\v\xe0w`\x00\x00\x00\x00\fٔ\xd0\x00\x00\x00\x00\r\xc0Y`\x00\x00\x00\x00\x0e\xb9v\xd0\x00\x00\x00\x00\x0f\xa9u\xe0\x00\x00\x00\x00\x10\x99" + - "X\xd0\x00\x00\x00\x00\x11\x89W\xe0\x00\x00\x00\x00\x12y:\xd0\x00\x00\x00\x00\x13i9\xe0\x00\x00\x00\x00\x14Y\x1c\xd0\x00\x00\x00\x00\x15I\x1b\xe0\x00\x00\x00\x00\x168\xfe\xd0\x00\x00\x00\x00\x17(\xfd\xe0\x00\x00" + - "\x00\x00\x18\"\x1bP\x00\x00\x00\x00\x19\b\xdf\xe0\x00\x00\x00\x00\x1a\x01\xfdP\x00\x00\x00\x00\x1a\xf1\xfc`\x00\x00\x00\x00\x1b\xe1\xdfP\x00\x00\x00\x00\x1c\xd1\xde`\x00\x00\x00\x00\x1d\xc1\xc1P\x00\x00\x00\x00\x1e\xb1" + - "\xc0`\x00\x00\x00\x00\x1f\xa1\xa3P\x00\x00\x00\x00 u\xf2\xe0\x00\x00\x00\x00!\x81\x85P\x00\x00\x00\x00\"U\xd4\xe0\x00\x00\x00\x00#j\xa1\xd0\x00\x00\x00\x00$5\xb6\xe0\x00\x00\x00\x00%J\x83\xd0\x00\x00" + - "\x00\x00&\x15\x98\xe0\x00\x00\x00\x00'*e\xd0\x00\x00\x00\x00'\xfe\xb5`\x00\x00\x00\x00)\nG\xd0\x00\x00\x00\x00)ޗ`\x00\x00\x00\x00*\xea)\xd0\x00\x00\x00\x00+\xbey`\x00\x00\x00\x00,\xd3" + - "FP\x00\x00\x00\x00-\x9e[`\x00\x00\x00\x00.\xb3(P\x00\x00\x00\x00/~=`\x00\x00\x00\x000\x93\nP\x00\x00\x00\x001gY\xe0\x00\x00\x00\x002r\xecP\x00\x00\x00\x003G;\xe0\x00\x00" + - "\x00\x004R\xceP\x00\x00\x00\x005'\x1d\xe0\x00\x00\x00\x0062\xb0P\x00\x00\x00\x007\x06\xff\xe0\x00\x00\x00\x008\x1b\xcc\xd0\x00\x00\x00\x008\xe6\xe1\xe0\x00\x00\x00\x009\xfb\xae\xd0\x00\x00\x00\x00:\xc6" + - "\xc3\xe0\x00\x00\x00\x00;ې\xd0\x00\x00\x00\x00<\xaf\xe0`\x00\x00\x00\x00=\xbbr\xd0\x00\x00\x00\x00>\x8f\xc2`\x00\x00\x00\x00?\x9bT\xd0\x00\x00\x00\x00@o\xa4`\x00\x00\x00\x00A\x84qP\x00\x00" + - "\x00\x00BO\x86`\x00\x00\x00\x00CdSP\x00\x00\x00\x00D/h`\x00\x00\x00\x00ED5P\x00\x00\x00\x00E\xf3\x9a\xe0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xc4`\x00\x00\xff\xff\xd5\xd0\x01\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xd5\xd0\x01\x10LMT\x00A" + - "DT\x00AST\x00AWT\x00APT\x00\nAST4ADT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x1c\xd8\x19\x9dp\x01\x00" + - "\x00p\x01\x00\x00\x15\x00\x1c\x00America/Swift_CurrentUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZ" + - "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff\x86\xfd\x96\x18\xff\xff\xff\xff\x9e\xb8\xaf\x90\xff\xff\xff\xff\x9f\xbb\a\x80\xff\xff\xff" + - "\xffˉ\f\x90\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff\xd3v\x01\x10\xff\xff\xff\xff\xd4So\x00\xff\xff\xff\xff\xd5U\xe3\x10\xff\xff\xff\xff\xd6 \xdc\x00\xff\xff\xff\xff\xd75\xc5" + - "\x10\xff\xff\xff\xff\xd8\x00\xbe\x00\xff\xff\xff\xff\xd9\x15\xa7\x10\xff\xff\xff\xff\xd9\xe0\xa0\x00\xff\xff\xff\xff\xe8',\x10\xff\xff\xff\xff\xe9\x17\x0f\x00\xff\xff\xff\xff\xeb\xe6\xf0\x10\xff\xff\xff\xff\xec\xd6\xd3\x00\xff\xff\xff" + - "\xff\xed\xc6\xd2\x10\xff\xff\xff\xff\xee\x91\xcb\x00\xff\xff\xff\xff\xef\xaf\xee\x90\xff\xff\xff\xff\xf0q\xad\x00\x00\x00\x00\x00\x04a\x19\x90\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05" + - "\xff\xff\x9a\xe8\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\f\xff\xff\xab\xa0\x01\x10\xff\xff\xab\xa0\x00\x14LMT\x00MDT\x00MST\x00MWT\x00MPT\x00CST\x00" + - "\nCST6\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R[Sp\x90\x02\x05\x00\x00\x02\x05\x00\x00\x10\x00\x1c\x00America/SantiagoUT\t\x00\x03\x15\xac\x0e" + - "`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" + - "\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00z\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffi" + - "\x87\x1d\xc6\xff\xff\xff\xff\x8f0GF\xff\xff\xff\xff\x9b\\\xe5P\xff\xff\xff\xff\x9f|\xe2\xc6\xff\xff\xff\xff\xa1\x00q\xc0\xff\xff\xff\xff\xb0^w\xc6\xff\xff\xff\xff\xb1w=@\xff\xff\xff\xff\xb2A\x00\xd0\xff" + - "\xff\xff\xff\xb3Xp\xc0\xff\xff\xff\xff\xb4\"4P\xff\xff\xff\xff\xb59\xa4@\xff\xff\xff\xff\xb6\x03g\xd0\xff\xff\xff\xff\xb7\x1a\xd7\xc0\xff\xff\xff\xff\xb7\xe4\x9bP\xff\xff\xff\xff\xb8\xfd\\\xc0\xff\xff\xff\xff\xb9" + - "\xc7 P\xff\xff\xff\xff\xcc\x1cn@\xff\xff\xff\xff\xccl\xe7\xd0\xff\xff\xff\xff\xd3\u070f\xc0\xff\xff\xff\xff\xd4\x1bɰ\xff\xff\xff\xff\xd53U\xc0\xff\xff\xff\xff\xd5v\x92@\xff\xff\xff\xff\xfd\xd1<@\xff" + - "\xff\xff\xff\xfe\x92\xfa\xb0\xff\xff\xff\xff\xff\xcc\xcd\xc0\x00\x00\x00\x00\x00rܰ\x00\x00\x00\x00\x01uP\xc0\x00\x00\x00\x00\x02@I\xb0\x00\x00\x00\x00\x03U2\xc0\x00\x00\x00\x00\x04 +\xb0\x00\x00\x00\x00\x05" + - ">O@\x00\x00\x00\x00\x06\x00\r\xb0\x00\x00\x00\x00\a\v\xbc@\x00\x00\x00\x00\a\xdf\xef\xb0\x00\x00\x00\x00\b\xfe\x13@\x00\x00\x00\x00\t\xbfѰ\x00\x00\x00\x00\n\xdd\xf5@\x00\x00\x00\x00\v\xa8\xee0\x00" + - "\x00\x00\x00\f\xbd\xd7@\x00\x00\x00\x00\r\x88\xd00\x00\x00\x00\x00\x0e\x9d\xb9@\x00\x00\x00\x00\x0fh\xb20\x00\x00\x00\x00\x10\x86\xd5\xc0\x00\x00\x00\x00\x11H\x940\x00\x00\x00\x00\x12f\xb7\xc0\x00\x00\x00\x00\x13" + - "(v0\x00\x00\x00\x00\x14F\x99\xc0\x00\x00\x00\x00\x15\x11\x92\xb0\x00\x00\x00\x00\x16&{\xc0\x00\x00\x00\x00\x16\xf1t\xb0\x00\x00\x00\x00\x18\x06]\xc0\x00\x00\x00\x00\x18\xd1V\xb0\x00\x00\x00\x00\x19\xe6?\xc0\x00" + - "\x00\x00\x00\x1a\xb18\xb0\x00\x00\x00\x00\x1b\xcf\\@\x00\x00\x00\x00\x1c\x91\x1a\xb0\x00\x00\x00\x00\x1d\xaf>@\x00\x00\x00\x00\x1ep\xfc\xb0\x00\x00\x00\x00\x1f\x8f @\x00\x00\x00\x00 \u007f\x030\x00\x00\x00\x00!" + - "o\x02@\x00\x00\x00\x00\"9\xfb0\x00\x00\x00\x00#N\xe4@\x00\x00\x00\x00$\x19\xdd0\x00\x00\x00\x00%8\x00\xc0\x00\x00\x00\x00%\xf9\xbf0\x00\x00\x00\x00&\xf2\xf8\xc0\x00\x00\x00\x00'١0\x00" + - "\x00\x00\x00(\xf7\xc4\xc0\x00\x00\x00\x00)½\xb0\x00\x00\x00\x00*צ\xc0\x00\x00\x00\x00+\xa2\x9f\xb0\x00\x00\x00\x00,\xb7\x88\xc0\x00\x00\x00\x00-\x82\x81\xb0\x00\x00\x00\x00.\x97j\xc0\x00\x00\x00\x00/" + - "bc\xb0\x00\x00\x00\x000\x80\x87@\x00\x00\x00\x001BE\xb0\x00\x00\x00\x002`i@\x00\x00\x00\x003=\xd70\x00\x00\x00\x004@K@\x00\x00\x00\x005\vD0\x00\x00\x00\x006\r\xb8@\x00" + - "\x00\x00\x007\x06հ\x00\x00\x00\x008\x00\x0f@\x00\x00\x00\x008\xcb\b0\x00\x00\x00\x009\xe9+\xc0\x00\x00\x00\x00:\xaa\xea0\x00\x00\x00\x00;\xc9\r\xc0\x00\x00\x00\x00<\x8a\xcc0\x00\x00\x00\x00=" + - "\xa8\xef\xc0\x00\x00\x00\x00>j\xae0\x00\x00\x00\x00?\x88\xd1\xc0\x00\x00\x00\x00@Sʰ\x00\x00\x00\x00Ah\xb3\xc0\x00\x00\x00\x00B3\xac\xb0\x00\x00\x00\x00CH\x95\xc0\x00\x00\x00\x00D\x13\x8e\xb0\x00" + - "\x00\x00\x00E1\xb2@\x00\x00\x00\x00E\xf3p\xb0\x00\x00\x00\x00G\x11\x94@\x00\x00\x00\x00G\xef\x020\x00\x00\x00\x00H\xf1v@\x00\x00\x00\x00I\xbco0\x00\x00\x00\x00J\xd1X@\x00\x00\x00\x00K" + - "\xb8\x00\xb0\x00\x00\x00\x00L\xb1:@\x00\x00\x00\x00M\xc6\a0\x00\x00\x00\x00NP\x82\xc0\x00\x00\x00\x00O\x9c\xae\xb0\x00\x00\x00\x00PB\xd9\xc0\x00\x00\x00\x00Q|\x90\xb0\x00\x00\x00\x00R+\xf6@\x00" + - "\x00\x00\x00S\\r\xb0\x00\x00\x00\x00T\v\xd8@\x00\x00\x00\x00W7\xe60\x00\x00\x00\x00W\xaf\xec\xc0\x00\x00\x00\x00Y\x17\xc80\x00\x00\x00\x00Y\x8f\xce\xc0\x00\x00\x00\x00Z\xf7\xaa0\x00\x00\x00\x00[" + - "o\xb0\xc0\x00\x00\x00\x00\\\xa9g\xb0\x01\x02\x01\x03\x01\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x03\x02\x03\x05\x03\x02\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05" + - "\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05" + - "\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\xff\xff\xbd\xba\x00\x00\xff\xff\xbd\xba\x00\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x00\f\xff\xff\xc7\xc0\x01\f\xff\xff\xd5\xd0\x01\x10LMT\x00SMT\x00-05" + - "\x00-04\x00-03\x00\n<-04>4<-03>,M9.1.6/24,M4.1.6/24\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R8\xcdZ\x05" + - "o\x01\x00\x00o\x01\x00\x00\x10\x00\x1c\x00America/MazatlanUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00)\x00\x00\x00\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff" + + "\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xd3u\xf3\x00\xff\xff\xff\xff\xd4@\xeb\xf0\xff\xff\xff\xff\xe0\x9e[\x80\xff\xff\xff\xff\xe1iTp\xff\xff\xff\xff\xe2~" + + "=\x80\xff\xff\xff\xff\xe3I6p\xff\xff\xff\xff\xe4g=\xe0\xff\xff\xff\xff\xe5)\x18p\xff\xff\xff\xff\xe6G<\x00\xff\xff\xff\xff\xe7\x124\xf0\xff\xff\xff\xff\xe8'\x1e\x00\xff\xff\xff\xff\xe8\xf2\x16\xf0\xff\xff" + + "\xff\xff\xea\a\x00\x00\xff\xff\xff\xff\xea\xd1\xf8\xf0\xff\xff\xff\xff\xeb\xe6\xe2\x00\xff\xff\xff\xff\xec\xb1\xda\xf0\xff\xff\xff\xff\xed\xc6\xc4\x00\xff\xff\xff\xff\xee\xbf\xe1p\xff\xff\xff\xff\xef\xaf\xe0\x80\xff\xff\xff\xff\xf0q" + + "\x9e\xf0\xff\xff\xff\xff\xf1\x8f\u0080\xff\xff\xff\xff\xf2\u007f\xa5p\xff\xff\xff\xff\xf3o\xa4\x80\xff\xff\xff\xff\xf4_\x87p\xff\xff\xff\xff\xf5O\x86\x80\xff\xff\xff\xff\xfe\xb8\x1c\xf0\xff\xff\xff\xff\xff\xa7\xff\xe0\x00\x00" + + "\x00\x00\x00\x97\xfe\xf0\x00\x00\x00\x00\x01\x87\xe1\xe0\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7\x00\x00\x00\x00\x00G-m\xf0\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05\x06\x05\x06\x05\x01\x02\x01\x05\xff\xff\xad\xf1\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9" + + "\xb0\x00\x14\xff\xff\xc7\xc0\x01\x18LMT\x00CDT\x00CST\x00CWT\x00CPT\x00EST\x00EDT\x00\nEST5EDT,M3.2.0,M11.1.0" + + "\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x01\xd8N\x8c\xab\x02\x00\x00\xab\x02\x00\x00\x1a\x00\x1c\x00America/Indiana/PetersburgUT\t" + + "\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x06\x00\x00\x00\x18" + + "\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff" + + "\xd2a\t\xf0\xff\xff\xff\xff\xe4g=\xe0\xff\xff\xff\xff\xe5)\x18p\xff\xff\xff\xff\xe6G<\x00\xff\xff\xff\xff\xe7\x124\xf0\xff\xff\xff\xff\xe8'\x1e\x00\xff\xff\xff\xff\xe8\xf2\x16\xf0\xff\xff\xff\xff\xea\a\x00\x00" + + "\xff\xff\xff\xff\xea\xd1\xf8\xf0\xff\xff\xff\xff\xeb\xe6\xe2\x00\xff\xff\xff\xff\xec\xb1\xda\xf0\xff\xff\xff\xff\xed\xc6\xc4\x00\xff\xff\xff\xff\ue47c\xf0\xff\xff\xff\xff\xef\xaf\xe0\x80\xff\xff\xff\xff\xf0\x9f\xc3p\xff\xff\xff\xff" + + "\xf1\x8f\u0080\xff\xff\xff\xff\xf2\u007f\xa5p\xff\xff\xff\xff\xf3o\xa4\x80\xff\xff\xff\xff\xf4_\x87p\xff\xff\xff\xff\xf5O\x86\x80\xff\xff\xff\xff\xf6?ip\xff\xff\xff\xff\xf7/h\x80\xff\xff\xff\xff\xfa\bg\xf0" + + "\xff\xff\xff\xff\xfa\xf8g\x00\xff\xff\xff\xff\xfb\xe8I\xf0\xff\xff\xff\xff\xfc\xd8I\x00\xff\xff\xff\xff\xfd\xc8+\xf0\xff\xff\xff\xff\xfe\xb8+\x00\xff\xff\xff\xff\xff\xa8\r\xf0\x00\x00\x00\x00\x00\x98\r\x00\x00\x00\x00\x00" + + "\x01\x87\xef\xf0\x00\x00\x00\x00\x02w\xef\x00\x00\x00\x00\x00\x03q\fp\x00\x00\x00\x00\x04a\v\x80\x00\x00\x00\x00\x05P\xeep\x00\x00\x00\x00\x06@\xed\x80\x00\x00\x00\x00\a0\xd0p\x00\x00\x00\x00\a\x8d'\x80" + + "\x00\x00\x00\x00\t\x10\xb2p\x00\x00\x00\x00\t\xad\xa3\x00\x00\x00\x00\x00\n\xf0\x94p\x00\x00\x00\x00\v\xe0\x93\x80\x00\x00\x00\x00\fٰ\xf0\x00\x00\x00\x00\r\xc0u\x80\x00\x00\x00\x00\x0e\xb9\x92\xf0\x00\x00\x00\x00" + + "D/vp\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7\x00\x00\x00\x00\x00G-m\xf0\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x05\x01\x02\x01\x05\xff\xff\xae-\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14" + + "LMT\x00CDT\x00CST\x00CWT\x00CPT\x00EST\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82" + + "iSK-E\xfad\x02\x00\x00d\x02\x00\x00\x17\x00\x1c\x00America/Indiana/WinamacUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04" + + "\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" + + "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00/\x00\x00\x00\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80" + + "\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xd3u\xf3\x00\xff\xff\xff\xff" + + "\xd4@\xeb\xf0\xff\xff\xff\xff\xd5U\xd5\x00\xff\xff\xff\xff\xd6 \xcd\xf0\xff\xff\xff\xff\xd75\xb7\x00\xff\xff\xff\xff\xd8\x00\xaf\xf0\xff\xff\xff\xff\xd9\x15\x99\x00\xff\xff\xff\xff\xd9\xe0\x91\xf0\xff\xff\xff\xff\xda\xfe\xb5\x80" + + "\xff\xff\xff\xff\xdb\xc0s\xf0\xff\xff\xff\xff\xdcޗ\x80\xff\xff\xff\xffݩ\x90p\xff\xff\xff\xff\u07bey\x80\xff\xff\xff\xff߉rp\xff\xff\xff\xff\xe0\x9e[\x80\xff\xff\xff\xff\xe1iTp\xff\xff\xff\xff" + + "\xe2~=\x80\xff\xff\xff\xff\xe3I6p\xff\xff\xff\xff\xe4^\x1f\x80\xff\xff\xff\xff\xe5W<\xf0\xff\xff\xff\xff\xe6G<\x00\xff\xff\xff\xff\xe77\x1e\xf0\xff\xff\xff\xff\xe8'\x1e\x00\xff\xff\xff\xff\xe8\xf2\x16\xf0" + + "\xff\xff\xff\xff\xea\a\x00\x00\xff\xff\xff\xff\xea\xd1\xf8\xf0\xff\xff\xff\xff\xeb\xe6\xe2\x00\xff\xff\xff\xff\xec\xb1\xda\xf0\xff\xff\xff\xff\xed\xc6\xc4\x00\xff\xff\xff\xff\ue47c\xf0\xff\xff\xff\xff\xef\xaf\xe0\x80\xff\xff\xff\xff" + + "\xfe\xb8\x1c\xf0\xff\xff\xff\xff\xff\xa7\xff\xe0\x00\x00\x00\x00\x00\x97\xfe\xf0\x00\x00\x00\x00\x01\x87\xe1\xe0\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7\x00\x00\x00\x00\x00G-_\xe0" + + "\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05\x06\x05\x06\x05\x01\x02\x06\x05\xff\xff\xae\xcf\x00\x00\xff\xff\xb9\xb0\x01\x04\xff" + + "\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14\xff\xff\xc7\xc0\x01\x18LMT\x00CDT\x00CST\x00CWT\x00CPT\x00EST\x00EDT\x00\nES" + + "T5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS \x17\x89}q\x01\x00\x00q\x01\x00\x00\x15\x00\x1c\x00America/I" + + "ndiana/VevayUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xff\xcb" + + "\x88\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xe2~=\x80\xff\xff\xff\xff\xfe\xb8\x1c\xf0\xff\xff\xff\xff\xff\xa7\xff\xe0\x00\x00\x00\x00\x00\x97\xfe\xf0\x00\x00\x00\x00\x01\x87\xe1\xe0\x00" + + "\x00\x00\x00\x02w\xe0\xf0\x00\x00\x00\x00\x03p\xfe`\x00\x00\x00\x00\x04`\xfdp\x00\x00\x00\x00\x05P\xe0`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x02" + + "\x03\x04\x02\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\xff\xff\xb0@\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14\xff\xff\xc7\xc0\x01\x18LMT" + + "\x00CDT\x00CST\x00CWT\x00CPT\x00EST\x00EDT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#" + + "\x82iS$ \x873\xf8\x03\x00\x00\xf8\x03\x00\x00\x14\x00\x1c\x00America/Indiana/KnoxUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E" + + "\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + + "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00]\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff" + + "\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xd5U\xd5\x00\xff\xff\xff\xff\xd6 " + + "\xcd\xf0\xff\xff\xff\xff\xd75\xb7\x00\xff\xff\xff\xff\xd8\x00\xaf\xf0\xff\xff\xff\xff\xd9\x15\x99\x00\xff\xff\xff\xff\xd9\xe0\x91\xf0\xff\xff\xff\xff\xda\xfe\xb5\x80\xff\xff\xff\xff\xdb\xc0s\xf0\xff\xff\xff\xff\xdcޗ\x80\xff\xff" + + "\xff\xffݩ\x90p\xff\xff\xff\xff\u07bey\x80\xff\xff\xff\xff߉rp\xff\xff\xff\xff\xe0\x9e[\x80\xff\xff\xff\xff\xe1iTp\xff\xff\xff\xff\xe2~=\x80\xff\xff\xff\xff\xe3I6p\xff\xff\xff\xff\xe4^" + + "\x1f\x80\xff\xff\xff\xff\xe5W<\xf0\xff\xff\xff\xff\xe6G<\x00\xff\xff\xff\xff\xe77\x1e\xf0\xff\xff\xff\xff\xe8'\x1e\x00\xff\xff\xff\xff\xe8\xf2\x16\xf0\xff\xff\xff\xff\xea\a\x00\x00\xff\xff\xff\xff\xea\xd1\xf8\xf0\xff\xff" + + "\xff\xff\xeb\xe6\xe2\x00\xff\xff\xff\xff\xec\xd6\xc4\xf0\xff\xff\xff\xff\xed\xc6\xc4\x00\xff\xff\xff\xff\xee\xbf\xe1p\xff\xff\xff\xff\xef\xaf\xe0\x80\xff\xff\xff\xff\xf0\x9f\xc3p\xff\xff\xff\xff\xf1\x8f\u0080\xff\xff\xff\xff\xf4_" + + "\x87p\xff\xff\xff\xff\xfa\xf8g\x00\xff\xff\xff\xff\xfb\xe8I\xf0\xff\xff\xff\xff\xfc\xd8I\x00\xff\xff\xff\xff\xfd\xc8+\xf0\xff\xff\xff\xff\xfe\xb8+\x00\xff\xff\xff\xff\xff\xa8\r\xf0\x00\x00\x00\x00\x00\x98\r\x00\x00\x00" + + "\x00\x00\x01\x87\xef\xf0\x00\x00\x00\x00\x02w\xef\x00\x00\x00\x00\x00\x03q\fp\x00\x00\x00\x00\x04a\v\x80\x00\x00\x00\x00\x05P\xeep\x00\x00\x00\x00\x06@\xed\x80\x00\x00\x00\x00\a0\xd0p\x00\x00\x00\x00\a\x8d" + + "'\x80\x00\x00\x00\x00\t\x10\xb2p\x00\x00\x00\x00\t\xad\xa3\x00\x00\x00\x00\x00\n\xf0\x94p\x00\x00\x00\x00\v\xe0\x93\x80\x00\x00\x00\x00\fٰ\xf0\x00\x00\x00\x00\r\xc0u\x80\x00\x00\x00\x00\x0e\xb9\x92\xf0\x00\x00" + + "\x00\x00\x0f\xa9\x92\x00\x00\x00\x00\x00\x10\x99t\xf0\x00\x00\x00\x00\x11\x89t\x00\x00\x00\x00\x00\x12yV\xf0\x00\x00\x00\x00\x13iV\x00\x00\x00\x00\x00\x14Y8\xf0\x00\x00\x00\x00\x15I8\x00\x00\x00\x00\x00\x169" + + "\x1a\xf0\x00\x00\x00\x00\x17)\x1a\x00\x00\x00\x00\x00\x18\"7p\x00\x00\x00\x00\x19\b\xfc\x00\x00\x00\x00\x00\x1a\x02\x19p\x00\x00\x00\x00\x1a\xf2\x18\x80\x00\x00\x00\x00\x1b\xe1\xfbp\x00\x00\x00\x00\x1c\xd1\xfa\x80\x00\x00" + + "\x00\x00\x1d\xc1\xddp\x00\x00\x00\x00\x1e\xb1܀\x00\x00\x00\x00\x1f\xa1\xbfp\x00\x00\x00\x00 v\x0f\x00\x00\x00\x00\x00!\x81\xa1p\x00\x00\x00\x00\"U\xf1\x00\x00\x00\x00\x00#j\xbd\xf0\x00\x00\x00\x00$5" + + "\xd3\x00\x00\x00\x00\x00%J\x9f\xf0\x00\x00\x00\x00&\x15\xb5\x00\x00\x00\x00\x00'*\x81\xf0\x00\x00\x00\x00'\xfeр\x00\x00\x00\x00)\nc\xf0\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDQp\x00\x00" + + "\x00\x00E\xf3\xb7\x00\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x05\x01\x02\x01\xff\xff\xae\xca\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9" + + "\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14LMT\x00CDT\x00CST\x00CWT\x00CPT\x00EST\x00\nCST6CDT,M3.2.0,M11.1" + + ".0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSԾ\xe7#\x95\x00\x00\x00\x95\x00\x00\x00\x0e\x00\x1c\x00America/CaymanUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8ba" + + "ux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00" + + "\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xffi\x87&\x10\xff\xff" + + "\xff\xff\x8b\xf4a\xe8\x01\x02\xff\xff\xb5p\x00\x00\xff\xff\xb5\x18\x00\x04\xff\xff\xb9\xb0\x00\bLMT\x00CMT\x00EST\x00\nEST5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xe9\x8c" + + "\xb4$q\x03\x00\x00q\x03\x00\x00\x13\x00\x1c\x00America/Thunder_BayUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01" + + "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00N\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xffr\xee\x82,\xff\xff\xff\xff\x8f${\xe0\xff\xff\xff\xffˈ\xf0p" + + "\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xfb\xe0\x00\x00\x00\x00\x00\x97\xfe\xf0\x00\x00\x00\x00\x01\x87\xe1\xe0\x00\x00\x00\x00\x02w\xe0\xf0\x00\x00\x00\x00\x03p\xfe`\x00\x00\x00\x00\x04`\xfdp\x00\x00\x00\x00" + + "\x05P\xe0`\x00\x00\x00\x00\b \xc1p\x00\x00\x00\x00\t\x10\xa4`\x00\x00\x00\x00\n\x00\xa3p\x00\x00\x00\x00\n\xf0\x86`\x00\x00\x00\x00\v\xe0\x85p\x00\x00\x00\x00\f٢\xe0\x00\x00\x00\x00\r\xc0gp" + + "\x00\x00\x00\x00\x0e\xb9\x84\xe0\x00\x00\x00\x00\x0f\xa9\x83\xf0\x00\x00\x00\x00\x10\x99f\xe0\x00\x00\x00\x00\x11\x89e\xf0\x00\x00\x00\x00\x12yH\xe0\x00\x00\x00\x00\x13iG\xf0\x00\x00\x00\x00\x14Y*\xe0\x00\x00\x00\x00" + + "\x15I)\xf0\x00\x00\x00\x00\x169\f\xe0\x00\x00\x00\x00\x17)\v\xf0\x00\x00\x00\x00\x18\")`\x00\x00\x00\x00\x19\b\xed\xf0\x00\x00\x00\x00\x1a\x02\v`\x00\x00\x00\x00\x1a\xf2\np\x00\x00\x00\x00\x1b\xe1\xed`" + + "\x00\x00\x00\x00\x1c\xd1\xecp\x00\x00\x00\x00\x1d\xc1\xcf`\x00\x00\x00\x00\x1e\xb1\xcep\x00\x00\x00\x00\x1f\xa1\xb1`\x00\x00\x00\x00 v\x00\xf0\x00\x00\x00\x00!\x81\x93`\x00\x00\x00\x00\"U\xe2\xf0\x00\x00\x00\x00" + + "#j\xaf\xe0\x00\x00\x00\x00$5\xc4\xf0\x00\x00\x00\x00%J\x91\xe0\x00\x00\x00\x00&\x15\xa6\xf0\x00\x00\x00\x00'*s\xe0\x00\x00\x00\x00'\xfe\xc3p\x00\x00\x00\x00)\nU\xe0\x00\x00\x00\x00)ޥp" + + "\x00\x00\x00\x00*\xea7\xe0\x00\x00\x00\x00+\xbe\x87p\x00\x00\x00\x00,\xd3T`\x00\x00\x00\x00-\x9eip\x00\x00\x00\x00.\xb36`\x00\x00\x00\x00/~Kp\x00\x00\x00\x000\x93\x18`\x00\x00\x00\x00" + + "1gg\xf0\x00\x00\x00\x002r\xfa`\x00\x00\x00\x003GI\xf0\x00\x00\x00\x004R\xdc`\x00\x00\x00\x005'+\xf0\x00\x00\x00\x0062\xbe`\x00\x00\x00\x007\a\r\xf0\x00\x00\x00\x008\x1b\xda\xe0" + + "\x00\x00\x00\x008\xe6\xef\xf0\x00\x00\x00\x009\xfb\xbc\xe0\x00\x00\x00\x00:\xc6\xd1\xf0\x00\x00\x00\x00;۞\xe0\x00\x00\x00\x00<\xaf\xeep\x00\x00\x00\x00=\xbb\x80\xe0\x00\x00\x00\x00>\x8f\xd0p\x00\x00\x00\x00" + + "?\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0" + + "\x01\x02\x03\x04\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05" + + "\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\xff\xff\xacT\x00\x00\xff\xff\xab\xa0\x00\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x01\f\xff\xff\xc7\xc0\x01\x10\xff\xff\xc7\xc0\x01\x14LMT\x00CS" + + "T\x00EST\x00EWT\x00EPT\x00EDT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS8\xcdZ\x05" + + "o\x01\x00\x00o\x01\x00\x00\x10\x00\x1c\x00America/MazatlanUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif" + "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\xa5\xb6\xe8p\xff\xff\xff\xff\xaf\xf2n\xe0\xff\xff\xff\xff\xb6fV`\xff\xff\xff\xff\xb7" + "C\xd2`\xff\xff\xff\xff\xb8\f6`\xff\xff\xff\xff\xb8\xfd\x86\xf0\xff\xff\xff\xff\xcb\xeaq`\xff\xff\xff\xffؑ\xb4\xf0\x00\x00\x00\x00\x00\x00p\x80\x00\x00\x00\x001g\x84\x10\x00\x00\x00\x002s\x16\x80\x00" + "\x00\x00\x003Gf\x10\x00\x00\x00\x004R\xf8\x80\x00\x00\x00\x005'H\x10\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe7\f\x10\x00\x00\x00\x009" + "\xfb\xd9\x00\x00\x00\x00\x00:\xf5\x12\x90\x00\x00\x00\x00;\xb6\xd1\x00\x00\x00\x00\x00<\xb0\n\x90\x01\x02\x01\x02\x01\x02\x01\x03\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\xff\xff\x9c<\x00\x00\xff\xff\x9d\x90\x00" + "\x04\xff\xff\xab\xa0\x00\b\xff\xff\x8f\x80\x00\f\xff\xff\xab\xa0\x01\x10LMT\x00MST\x00CST\x00PST\x00MDT\x00\nMST7MDT,M4.1.0,M10.5" + - ".0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00\x00\x00\x15\x00\x1c\x00America/St_BarthelemyUT\t\x00\x03\x15" + - "\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff" + - "\xff\x9373\xac\x01\xff\xff\xc6T\x00\x00\xff\xff\xc7\xc0\x00\x04LMT\x00AST\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x89غ\xee\x15\x04\x00\x00\x15\x04\x00\x00\x0e\x00" + - "\x1c\x00America/BelizeUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\x00\x00\x00\x06\x00\x00\x00\x1a\xff\xff\xff\xff\x93^ٰ\xff\xff\xff\xff\x9f\x9f;\xe0\xff\xff\xff\xff\xa0EQ\xd8\xff\xff\xff\xff\xa1\u007f\x1d\xe0\xff\xff\xff\xff\xa2.nX\xff" + - "\xff\xff\xff\xa3^\xff\xe0\xff\xff\xff\xff\xa4\x0ePX\xff\xff\xff\xff\xa5>\xe1\xe0\xff\xff\xff\xff\xa5\xee2X\xff\xff\xff\xff\xa7'\xfe`\xff\xff\xff\xff\xa7\xce\x14X\xff\xff\xff\xff\xa9\a\xe0`\xff\xff\xff\xff\xa9" + - "\xad\xf6X\xff\xff\xff\xff\xaa\xe7\xc2`\xff\xff\xff\xff\xab\x97\x12\xd8\xff\xff\xff\xff\xacǤ`\xff\xff\xff\xff\xadv\xf4\xd8\xff\xff\xff\xff\xae\xa7\x86`\xff\xff\xff\xff\xafV\xd6\xd8\xff\xff\xff\xff\xb0\x87h`\xff" + - "\xff\xff\xff\xb16\xb8\xd8\xff\xff\xff\xff\xb2p\x84\xe0\xff\xff\xff\xff\xb3\x16\x9a\xd8\xff\xff\xff\xff\xb4Pf\xe0\xff\xff\xff\xff\xb4\xf6|\xd8\xff\xff\xff\xff\xb60H\xe0\xff\xff\xff\xff\xb6ߙX\xff\xff\xff\xff\xb8" + - "\x10*\xe0\xff\xff\xff\xff\xb8\xbf{X\xff\xff\xff\xff\xb9\xf0\f\xe0\xff\xff\xff\xff\xba\x9f]X\xff\xff\xff\xff\xbb\xd9)`\xff\xff\xff\xff\xbc\u007f?X\xff\xff\xff\xff\xbd\xb9\v`\xff\xff\xff\xff\xbe_!X\xff" + - "\xff\xff\xff\xbf\x98\xed`\xff\xff\xff\xff\xc0?\x03X\xff\xff\xff\xff\xc1x\xcf`\xff\xff\xff\xff\xc2(\x1f\xd8\xff\xff\xff\xff\xc3X\xb1`\xff\xff\xff\xff\xc4\b\x01\xd8\xff\xff\xff\xff\xc58\x93`\xff\xff\xff\xff\xc5" + - "\xe7\xe3\xd8\xff\xff\xff\xff\xc7!\xaf\xe0\xff\xff\xff\xff\xc7\xc7\xc5\xd8\xff\xff\xff\xff\xc9\x01\x91\xe0\xff\xff\xff\xffɧ\xa7\xd8\xff\xff\xff\xff\xca\xe1s\xe0\xff\xff\xff\xffː\xc4X\xff\xff\xff\xff\xcc@\"\xe0\xff" + - "\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2\xc6qP\xff\xff\xff\xff\xd6)\xfa`\xff\xff\xff\xff\xd6\xd9J\xd8\xff\xff\xff\xff\xd8\t\xdc`\xff\xff\xff\xffع,\xd8\xff\xff\xff\xff\xd9\xe9\xbe`\xff\xff\xff\xff\xda" + - "\x99\x0e\xd8\xff\xff\xff\xff\xdb\xd2\xda\xe0\xff\xff\xff\xff\xdcx\xf0\xd8\xff\xff\xff\xffݲ\xbc\xe0\xff\xff\xff\xff\xdeX\xd2\xd8\xff\xff\xff\xffߒ\x9e\xe0\xff\xff\xff\xff\xe0A\xefX\xff\xff\xff\xff\xe1r\x80\xe0\xff" + - "\xff\xff\xff\xe2!\xd1X\xff\xff\xff\xff\xe3Rb\xe0\xff\xff\xff\xff\xe4\x01\xb3X\xff\xff\xff\xff\xe52D\xe0\xff\xff\xff\xff\xe5\xe1\x95X\xff\xff\xff\xff\xe7\x1ba`\xff\xff\xff\xff\xe7\xc1wX\xff\xff\xff\xff\xe8" + - "\xfbC`\xff\xff\xff\xff\xe9\xa1YX\xff\xff\xff\xff\xea\xdb%`\xff\xff\xff\xff\xeb\x8au\xd8\xff\xff\xff\xff\xec\xbb\a`\xff\xff\xff\xff\xedjW\xd8\xff\xff\xff\xff\xee\x9a\xe9`\xff\xff\xff\xff\xefJ9\xd8\xff" + - "\xff\xff\xff\xf0\x84\x05\xe0\xff\xff\xff\xff\xf1*\x1b\xd8\xff\xff\xff\xff\xf2c\xe7\xe0\xff\xff\xff\xff\xf3\t\xfd\xd8\xff\xff\xff\xff\xf4C\xc9\xe0\xff\xff\xff\xff\xf4\xe9\xdf\xd8\xff\xff\xff\xff\xf6#\xab\xe0\xff\xff\xff\xff\xf6" + - "\xd2\xfcX\xff\xff\xff\xff\xf8\x03\x8d\xe0\xff\xff\xff\xff\xf8\xb2\xdeX\xff\xff\xff\xff\xf9\xe3o\xe0\xff\xff\xff\xff\xfa\x92\xc0X\xff\xff\xff\xff\xfb̌`\xff\xff\xff\xff\xfcr\xa2X\x00\x00\x00\x00\ab\xdb`\x00" + - "\x00\x00\x00\a\xb9\xd0P\x00\x00\x00\x00\x18aq`\x00\x00\x00\x00\x18\xab7P\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05\x02\x05" + - "\x02\xff\xff\xadP\x00\x00\xff\xff\xb2\xa8\x01\x04\xff\xff\xab\xa0\x00\n\xff\xff\xb9\xb0\x01\x0e\xff\xff\xb9\xb0\x01\x12\xff\xff\xb9\xb0\x01\x16LMT\x00-0530\x00CST\x00CWT\x00CPT\x00C" + - "DT\x00\nCST6\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xcd\xc3v\xe3\xb3\x00\x00\x00\xb3\x00\x00\x00\x11\x00\x1c\x00America/GuayaquilUT\t\x00" + - "\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x10\xff" + - "\xff\xff\xffi\x87&X\xff\xff\xff\xff\xb6\xa4B\x18\x00\x00\x00\x00+\x16\xfc\xd0\x00\x00\x00\x00+q\xe6@\x01\x03\x02\x03\xff\xff\xb5(\x00\x00\xff\xff\xb6h\x00\x04\xff\xff\xc7\xc0\x01\b\xff\xff\xb9\xb0\x00\fL" + - "MT\x00QMT\x00-04\x00-05\x00\n<-05>5\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xc0\x98\x00\b\xc9\x03\x00\x00\xc9\x03\x00\x00\x12\x00\x1c\x00America" + - "/MontevideoUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + ".0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb7-2f\xe4\x01\x00\x00\xe4\x01\x00\x00\x0f\x00\x1c\x00America/NoronhaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8b" + + "aux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01" + + "\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96\xaaed\xff" + + "\xff\xff\xff\xb8\x0f;\xd0\xff\xff\xff\xff\xb8\xfd2\x90\xff\xff\xff\xff\xb9\xf1& \xff\xff\xff\xff\xba\xdef\x10\xff\xff\xff\xff\xda8\xa0 \xff\xff\xff\xff\xda\xeb\xec \xff\xff\xff\xff\xdc\x19Ӡ\xff\xff\xff\xff\xdc" + + "\xb9K\x10\xff\xff\xff\xff\xdd\xfb\a \xff\xff\xff\xffޛ\xd0\x10\xff\xff\xff\xff\xdf\u074c \xff\xff\xff\xff\xe0T%\x10\xff\xff\xff\xff\xf4\x97\xf1\xa0\xff\xff\xff\xff\xf5\x05P\x10\xff\xff\xff\xff\xf6\xc0V \xff" + + "\xff\xff\xff\xf7\x0e\x10\x90\xff\xff\xff\xff\xf8Q\x1e \xff\xff\xff\xff\xf8Ƿ\x10\xff\xff\xff\xff\xfa\nĠ\xff\xff\xff\xff\xfa\xa8\xea\x90\xff\xff\xff\xff\xfb\xeb\xf8 \xff\xff\xff\xff\xfc\x8bo\x90\x00\x00\x00\x00\x1d" + + "ɀ \x00\x00\x00\x00\x1exɐ\x00\x00\x00\x00\x1f\xa0'\xa0\x00\x00\x00\x00 3\xc1\x90\x00\x00\x00\x00!\x81[ \x00\x00\x00\x00\"\v\xba\x90\x00\x00\x00\x00#X\x02\xa0\x00\x00\x00\x00#\xe2b\x10\x00" + + "\x00\x00\x00%7\xe4\xa0\x00\x00\x00\x00%Թ\x10\x00\x00\x00\x007\xf6\xb8\xa0\x00\x00\x00\x008\xb8w\x10\x00\x00\x00\x009\xdf\xd5 \x00\x00\x00\x009\xe9\x01\x90\x00\x00\x00\x00;\xc8\xf1\xa0\x00\x00\x00\x00<" + + "o\x00\x90\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xff\xe1\x9c\x00\x00\xff\xff\xf1\xf0\x01\x04\xff\xff\xe3\xe0\x00\b" + + "LMT\x00-01\x00-02\x00\n<-02>2\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xe0\xbf\xf5\xe5\xc4\x02\x00\x00\xc4\x02\x00\x00\x14\x00\x1c\x00America/Bu" + + "enos_AiresUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00=\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xa8L\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p" + + "0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff" + + "\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7" + + "\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff" + + "\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd3" + + "0\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00" + + "\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'!\x0f0\x00\x00\x00\x00'\xd0X" + + "\xa0\x00\x00\x00\x00)\x00\xf10\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00" + + "\x00G\xdc\u007f \x00\x00\x00\x00H\xfa\xa2\xb0\x00\x00\x00\x00I\xbca \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x03\x05\x04\x05\x04\x05\xff\xff\xc94\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLM" + + "T\x00CMT\x00-04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x0f\x00\x1c\x00Amer" + + "ica/TortolaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00V\x00\x00\x00\t\x00\x00\x00&\xff\xff\xff\xff\x8c4\xe53\xff\xff\xff\xff\xa2\x92\x87\xb3\xff\xff\xff\xff\xa8\xff\xdb@\xff\xff\xff\xff\xa9\xf1\x0f\xb0\xff\xff\xff\xff\xaa\xe2Y8\xff\xff\xff\xff\xab\xd2" + - "C0\xff\xff\xff\xff\xacÌ\xb8\xff\xff\xff\xff\xad\xb3v\xb0\xff\xff\xff\xff\xbb\xf4\xb5\xb8\xff\xff\xff\xff\xbc\xbf\xb5\xb0\xff\xff\xff\xff\xbdԗ\xb8\xff\xff\xff\xff\xbe\x9f\x97\xb0\xff\xff\xff\xff\xbf\xb4y\xb8\xff\xff" + - "\xff\xff\xc0\u007fy\xb0\xff\xff\xff\xff\xc1\x94[\xb8\xff\xff\xff\xff\xc2_[\xb0\xff\xff\xff\xff\xc3}x8\xff\xff\xff\xff\xc4?=\xb0\xff\xff\xff\xff\xc5]Z8\xff\xff\xff\xff\xc6\x1f\x1f\xb0\xff\xff\xff\xff\xc7\x18" + - "R8\xff\xff\xff\xff\xc8\b<0\xff\xff\xff\xff\xc9\x1d\x1e8\xff\xff\xff\xff\xc9\xe8\x1e0\xff\xff\xff\xffʋ\x9f8\xff\xff\xff\xff\xcd\x1e\xc60\xff\xff\xff\xff͕f(\xff\xff\xff\xff\xec\v\x85\xb0\xff\xff" + - "\xff\xff\xec\xf25(\xff\xff\xff\xff\xedEJ\xb0\xff\xff\xff\xff\xed\x85\xd6 \xff\xff\xff\xff\xf7\x13r\xb0\xff\xff\xff\xff\xf7\xfa\x1b \xff\xff\xff\xff\xfc\xfe>0\xff\xff\xff\xff\xfd\xf6\x11(\x00\x00\x00\x00\x00\x96" + - "u0\x00\x00\x00\x00\x00\xd8R \x00\x00\x00\x00\x04W\x8a\xb0\x00\x00\x00\x00\x04\xc6:\xa0\x00\x00\x00\x00\a\x96\x1b\xb0\x00\x00\x00\x00\a\xdfژ\x00\x00\x00\x00\bƟ(\x00\x00\x00\x00\tZN0\x00\x00" + - "\x00\x00\t\xdbs \x00\x00\x00\x00\r\x1a\x120\x00\x00\x00\x00\r\u007f\x87\xa0\x00\x00\x00\x00\x0e\xe7\u007f0\x00\x00\x00\x00\x0f_i\xa0\x00\x00\x00\x00\x10\xd9\xd60\x00\x00\x00\x00\x11?K\xa0\x00\x00\x00\x00\x11\x89" + - "-\xb0\x00\x00\x00\x00\x131\xa2\xa0\x00\x00\x00\x00!\xc3T0\x00\x00\x00\x00\"'x \x00\x00\x00\x00#\xa1\xe4\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%Jg\xb0\x00\x00\x00\x00%\xe7< \x00\x00" + - "\x00\x00'!\x0f0\x00\x00\x00\x00'\xd0X\xa0\x00\x00\x00\x00)\n+\xb0\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x90\x1c\xa0\x00\x00\x00\x00AL\xf60\x00\x00\x00\x00BF" + - "/\xc0\x00\x00\x00\x00CH\xa3\xd0\x00\x00\x00\x00D\x13\x9c\xc0\x00\x00\x00\x00E\x1fKP\x00\x00\x00\x00E\xf3~\xc0\x00\x00\x00\x00G\bg\xd0\x00\x00\x00\x00G\xd3`\xc0\x00\x00\x00\x00H\xe8I\xd0\x00\x00" + - "\x00\x00I\xb3B\xc0\x00\x00\x00\x00J\xc8+\xd0\x00\x00\x00\x00K\x9c_@\x00\x00\x00\x00L\xa8\r\xd0\x00\x00\x00\x00M|A@\x00\x00\x00\x00N\x87\xef\xd0\x00\x00\x00\x00O\\#@\x00\x00\x00\x00Pq" + - "\fP\x00\x00\x00\x00Q<\x05@\x00\x00\x00\x00RP\xeeP\x00\x00\x00\x00S\x1b\xe7@\x00\x00\x00\x00T0\xd0P\x00\x00\x00\x00T\xfb\xc9@\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03" + - "\x04\x03\x04\x03\x04\x03\x04\x06\x05\x06\x05\a\x05\a\x05\x06\x05\a\x05\a\x05\b\x06\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05" + - "\a\x05\a\x05\a\x05\a\x05\xff\xff\xcbM\x00\x00\xff\xff\xcbM\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xce\xc8\x00\f\xff\xff\xd5\xd0\x01\x12\xff\xff\xd5\xd0\x00\x12\xff\xff\xdc\xd8\x01\x16\xff\xff\xe3\xe0\x01\x1c\xff\xff\xea\xe8" + - "\x01 LMT\x00MMT\x00-04\x00-0330\x00-03\x00-0230\x00-02\x00-0130\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c" + - "9R\xf6\"\x12\xfe\x0e\x05\x00\x00\x0e\x05\x00\x00\x13\x00\x1c\x00America/Los_AngelesUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00" + - "\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif" + - "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00}\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff^\x04\x1a\xc0\xff\xff\xff\xff\x9e\xa6H\xa0\xff\xff\xff\xff" + - "\x9f\xbb\x15\x90\xff\xff\xff\xff\xa0\x86*\xa0\xff\xff\xff\xff\xa1\x9a\xf7\x90\xff\xff\xff\xffˉ\x1a\xa0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a&\x10\xff\xff\xff\xff\xd6\xfet\\\xff\xff\xff\xff\u0600\xad\x90" + - "\xff\xff\xff\xff\xda\xfeÐ\xff\xff\xff\xff\xdb\xc0\x90\x10\xff\xff\xff\xff\xdcޥ\x90\xff\xff\xff\xffݩ\xac\x90\xff\xff\xff\xff\u07be\x87\x90\xff\xff\xff\xff߉\x8e\x90\xff\xff\xff\xff\xe0\x9ei\x90\xff\xff\xff\xff" + - "\xe1ip\x90\xff\xff\xff\xff\xe2~K\x90\xff\xff\xff\xff\xe3IR\x90\xff\xff\xff\xff\xe4^-\x90\xff\xff\xff\xff\xe5)4\x90\xff\xff\xff\xff\xe6GJ\x10\xff\xff\xff\xff\xe7\x12Q\x10\xff\xff\xff\xff\xe8',\x10" + - "\xff\xff\xff\xff\xe8\xf23\x10\xff\xff\xff\xff\xea\a\x0e\x10\xff\xff\xff\xff\xea\xd2\x15\x10\xff\xff\xff\xff\xeb\xe6\xf0\x10\xff\xff\xff\xff\xec\xb1\xf7\x10\xff\xff\xff\xff\xed\xc6\xd2\x10\xff\xff\xff\xff\xee\x91\xd9\x10\xff\xff\xff\xff" + - "\xef\xaf\xee\x90\xff\xff\xff\xff\xf0q\xbb\x10\xff\xff\xff\xff\xf1\x8fА\xff\xff\xff\xff\xf2\u007f\xc1\x90\xff\xff\xff\xff\xf3o\xb2\x90\xff\xff\xff\xff\xf4_\xa3\x90\xff\xff\xff\xff\xf5O\x94\x90\xff\xff\xff\xff\xf6?\x85\x90" + - "\xff\xff\xff\xff\xf7/v\x90\xff\xff\xff\xff\xf8(\xa2\x10\xff\xff\xff\xff\xf9\x0fX\x90\xff\xff\xff\xff\xfa\b\x84\x10\xff\xff\xff\xff\xfa\xf8\x83 \xff\xff\xff\xff\xfb\xe8f\x10\xff\xff\xff\xff\xfc\xd8e \xff\xff\xff\xff" + - "\xfd\xc8H\x10\xff\xff\xff\xff\xfe\xb8G \xff\xff\xff\xff\xff\xa8*\x10\x00\x00\x00\x00\x00\x98) \x00\x00\x00\x00\x01\x88\f\x10\x00\x00\x00\x00\x02x\v \x00\x00\x00\x00\x03q(\x90\x00\x00\x00\x00\x04a'\xa0" + - "\x00\x00\x00\x00\x05Q\n\x90\x00\x00\x00\x00\x06A\t\xa0\x00\x00\x00\x00\a0\xec\x90\x00\x00\x00\x00\a\x8dC\xa0\x00\x00\x00\x00\t\x10ΐ\x00\x00\x00\x00\t\xad\xbf \x00\x00\x00\x00\n\xf0\xb0\x90\x00\x00\x00\x00" + - "\v\u0be0\x00\x00\x00\x00\f\xd9\xcd\x10\x00\x00\x00\x00\r\xc0\x91\xa0\x00\x00\x00\x00\x0e\xb9\xaf\x10\x00\x00\x00\x00\x0f\xa9\xae \x00\x00\x00\x00\x10\x99\x91\x10\x00\x00\x00\x00\x11\x89\x90 \x00\x00\x00\x00\x12ys\x10" + - "\x00\x00\x00\x00\x13ir \x00\x00\x00\x00\x14YU\x10\x00\x00\x00\x00\x15IT \x00\x00\x00\x00\x1697\x10\x00\x00\x00\x00\x17)6 \x00\x00\x00\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18 \x00\x00\x00\x00" + - "\x1a\x025\x90\x00\x00\x00\x00\x1a\xf24\xa0\x00\x00\x00\x00\x1b\xe2\x17\x90\x00\x00\x00\x00\x1c\xd2\x16\xa0\x00\x00\x00\x00\x1d\xc1\xf9\x90\x00\x00\x00\x00\x1e\xb1\xf8\xa0\x00\x00\x00\x00\x1f\xa1ې\x00\x00\x00\x00 v+ " + - "\x00\x00\x00\x00!\x81\xbd\x90\x00\x00\x00\x00\"V\r \x00\x00\x00\x00#j\xda\x10\x00\x00\x00\x00$5\xef \x00\x00\x00\x00%J\xbc\x10\x00\x00\x00\x00&\x15\xd1 \x00\x00\x00\x00'*\x9e\x10\x00\x00\x00\x00" + - "'\xfe\xed\xa0\x00\x00\x00\x00)\n\x80\x10\x00\x00\x00\x00)\xdeϠ\x00\x00\x00\x00*\xeab\x10\x00\x00\x00\x00+\xbe\xb1\xa0\x00\x00\x00\x00,\xd3~\x90\x00\x00\x00\x00-\x9e\x93\xa0\x00\x00\x00\x00.\xb3`\x90" + - "\x00\x00\x00\x00/~u\xa0\x00\x00\x00\x000\x93B\x90\x00\x00\x00\x001g\x92 \x00\x00\x00\x002s$\x90\x00\x00\x00\x003Gt \x00\x00\x00\x004S\x06\x90\x00\x00\x00\x005'V \x00\x00\x00\x00" + - "62\xe8\x90\x00\x00\x00\x007\a8 \x00\x00\x00\x008\x1c\x05\x10\x00\x00\x00\x008\xe7\x1a \x00\x00\x00\x009\xfb\xe7\x10\x00\x00\x00\x00:\xc6\xfc \x00\x00\x00\x00;\xdb\xc9\x10\x00\x00\x00\x00<\xb0\x18\xa0" + - "\x00\x00\x00\x00=\xbb\xab\x10\x00\x00\x00\x00>\x8f\xfa\xa0\x00\x00\x00\x00?\x9b\x8d\x10\x00\x00\x00\x00@oܠ\x00\x00\x00\x00A\x84\xa9\x90\x00\x00\x00\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b\x90\x00\x00\x00\x00" + - "D/\xa0\xa0\x00\x00\x00\x00EDm\x90\x00\x00\x00\x00E\xf3\xd3 \x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\x91&\x00\x00\xff\xff\x9d\x90\x01\x04\xff\xff\x8f\x80\x00\b\xff\xff\x9d\x90\x01\f\xff\xff\x9d\x90\x01\x10LMT\x00P" + - "DT\x00PST\x00PWT\x00PPT\x00\nPST8PDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\a\x1c\x9e\x9a]\x04\x00" + - "\x00]\x04\x00\x00\x0e\x00\x1c\x00America/HavanaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffz敹\xff\xff\xff\xff\xcb\xf62\xc0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\x01\x03\x02\x01\xff\xff\xc2\a\x00\x00\xff\xff\xc7\xc0" + + "\x00\x04\xff\xff\xd5\xd0\x01\b\xff\xff\xd5\xd0\x01\fLMT\x00AST\x00APT\x00AWT\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xa1'\a\xbd\x97\x00\x00\x00\x97\x00" + + "\x00\x00\x0f\x00\x1c\x00America/CayenneUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x91\xf4+\x90\xff\xff\xff\xff\xfb\xc35\xc0\x01\x02\xff\xff\xce\xf0\x00\x00\xff\xff\xc7\xc0\x00\x04\xff\xff\xd5\xd0\x00\b" + + "LMT\x00-04\x00-03\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x10\x00\x1c\x00America/St" + + "_LuciaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x04\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffz敹\xff\xff\xff\xff\xcb\xf62\xc0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\x01\x03\x02\x01\xff\xff\xc2\a\x00\x00\xff\xff\xc7\xc0\x00\x04\xff\xff\xd5" + + "\xd0\x01\b\xff\xff\xd5\xd0\x01\fLMT\x00AST\x00APT\x00AWT\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSk\xc2\rx\xbf\x01\x00\x00\xbf\x01\x00\x00\x14\x00\x1c" + + "\x00America/DanmarkshavnUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\"\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff\x9b\x80I\x00\x00\x00\x00\x00\x13M|P\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00" + + "\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10" + + "\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xfe7\xa1\x87\x1b\x01\x00" + + "\x00\x1b\x01\x00\x00\f\x00\x1c\x00America/LimaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x04\x00\x00\x00\f\xff\xff\xff\xffi\x87#\xbc\xff\xff\xff\xff\x8ct@\xd4\xff\xff\xff\xff\xc3\xcfJP\xff\xff\xff\xff\xc4E\xe3@\xff\xff\xff\xff" + + "\xc5/J\xd0\xff\xff\xff\xff\xc6\x1f-\xc0\xff\xff\xff\xff\xc7\x0f,\xd0\xff\xff\xff\xff\xc7\xff\x0f\xc0\x00\x00\x00\x00\x1e\x18\xc4P\x00\x00\x00\x00\x1e\x8f]@\x00\x00\x00\x00\x1f\xf9\xf7\xd0\x00\x00\x00\x00 p\x90\xc0" + + "\x00\x00\x00\x00%\x9e\xe3\xd0\x00\x00\x00\x00&\x15|\xc0\x00\x00\x00\x00-%\x03P\x00\x00\x00\x00-\x9b\x9c@\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\xff\xff\xb7\xc4\x00\x00\xff\xff\xb7\xac\x00\x00" + + "\xff\xff\xc7\xc0\x01\x04\xff\xff\xb9\xb0\x00\bLMT\x00-04\x00-05\x00\n<-05>5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xac\x8e\xee\x13\xbe\x00\x00\x00\xbe\x00\x00\x00\x0f\x00" + + "\x1c\x00America/CaracasUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xffi\x87\x1a@\xff\xff\xff\xff\x93\x1e,<\xff\xff\xff\xff\xf6\x98\xecH\x00\x00\x00\x00G[\x92p\x00\x00\x00\x00W%\xa9p" + + "\x01\x02\x03\x02\x03\xff\xff\xc1@\x00\x00\xff\xff\xc1D\x00\x04\xff\xff\xc0\xb8\x00\b\xff\xff\xc7\xc0\x00\x0eLMT\x00CMT\x00-0430\x00-04\x00\n<-04>4\nPK\x03\x04\n" + + "\x00\x00\x00\x00\x00#\x82iSø\xab\x9b\xf0\x00\x00\x00\xf0\x00\x00\x00\x0f\x00\x1c\x00America/PhoenixUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14" + + "E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00T" + + "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\v\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff^\x04\f\xb0\xff\xff\xff\xff\x9e\xa6:\x90\xff" + + "\xff\xff\xff\x9f\xbb\a\x80\xff\xff\xff\xff\xa0\x86\x1c\x90\xff\xff\xff\xff\xa1\x9a\xe9\x80\xff\xff\xff\xffˉ\f\x90\xff\xff\xff\xff\xcf\x17\xdf\x1c\xff\xff\xff\xffϏ\xe5\xac\xff\xff\xff\xffЁ\x1a\x1c\xff\xff\xff\xff\xfa" + + "\xf8u\x10\xff\xff\xff\xff\xfb\xe8X\x00\x02\x01\x02\x01\x02\x03\x02\x03\x02\x01\x02\xff\xff\x96\xee\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\fLMT\x00MDT\x00MST\x00MW" + + "T\x00\nMST7\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS<\x01V\rP\x02\x00\x00P\x02\x00\x00\x11\x00\x1c\x00America/AraguainaUT\t\x00\x03" + + "\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x003\x00\x00\x00\x03\x00\x00\x00\f\xff\xff" + + "\xff\xff\x96\xaat0\xff\xff\xff\xff\xb8\x0fI\xe0\xff\xff\xff\xff\xb8\xfd@\xa0\xff\xff\xff\xff\xb9\xf140\xff\xff\xff\xff\xba\xdet \xff\xff\xff\xff\xda8\xae0\xff\xff\xff\xff\xda\xeb\xfa0\xff\xff\xff\xff\xdc\x19" + + "\xe1\xb0\xff\xff\xff\xffܹY \xff\xff\xff\xff\xdd\xfb\x150\xff\xff\xff\xffޛ\xde \xff\xff\xff\xff\xdfݚ0\xff\xff\xff\xff\xe0T3 \xff\xff\xff\xff\xf4\x97\xff\xb0\xff\xff\xff\xff\xf5\x05^ \xff\xff" + + "\xff\xff\xf6\xc0d0\xff\xff\xff\xff\xf7\x0e\x1e\xa0\xff\xff\xff\xff\xf8Q,0\xff\xff\xff\xff\xf8\xc7\xc5 \xff\xff\xff\xff\xfa\nҰ\xff\xff\xff\xff\xfa\xa8\xf8\xa0\xff\xff\xff\xff\xfb\xec\x060\xff\xff\xff\xff\xfc\x8b" + + "}\xa0\x00\x00\x00\x00\x1dɎ0\x00\x00\x00\x00\x1exנ\x00\x00\x00\x00\x1f\xa05\xb0\x00\x00\x00\x00 3Ϡ\x00\x00\x00\x00!\x81i0\x00\x00\x00\x00\"\vȠ\x00\x00\x00\x00#X\x10\xb0\x00\x00" + + "\x00\x00#\xe2p \x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xd4\xc7 \x00\x00\x00\x000\x80y0\x00\x00\x00\x001\x1dM\xa0\x00\x00\x00\x002W \xb0\x00\x00\x00\x003\x06j \x00\x00\x00\x0048" + + "T0\x00\x00\x00\x004\xf8\xc1 \x00\x00\x00\x006 \x1f0\x00\x00\x00\x006\xcfh\xa0\x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xb8\x85 \x00\x00\x00\x009\xdf\xe30\x00\x00\x00\x00:\x8f,\xa0\x00\x00" + + "\x00\x00;\xc8\xff\xb0\x00\x00\x00\x00N\xf0\xa0\x00\x00\x00\x00P\x83e0\x00\x00\x00\x00Q 9\xa0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xff\xd2\xd0\x00\x00\xff\xff\xe3\xe0\x01\x04\xff\xff\xd5\xd0\x00\bLMT\x00-" + + "02\x00-03\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x15\x00\x1c\x00America/Lower_P" + + "rincesUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x04\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffz敹\xff\xff\xff\xff\xcb\xf62\xc0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\x01\x03\x02\x01\xff\xff\xc2\a\x00\x00\xff\xff\xc7\xc0\x00\x04\xff\xff\xd5" + + "\xd0\x01\b\xff\xff\xd5\xd0\x01\fLMT\x00AST\x00APT\x00AWT\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSk^2S\xb9\x04\x00\x00\xb9\x04\x00\x00\x14\x00\x1c" + + "\x00America/Punta_ArenasUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00t\x00\x00\x00\a\x00\x00\x00\x14\xff\xff\xff\xffi\x87\x1d\xfc\xff\xff\xff\xff\x8f0GF\xff\xff\xff\xff\x9b\\\xe5P\xff\xff\xff\xff\x9f|\xe2\xc6\xff\xff\xff\xff" + + "\xa1\x00q\xc0\xff\xff\xff\xff\xb0^w\xc6\xff\xff\xff\xff\xb1w=@\xff\xff\xff\xff\xb2A\x00\xd0\xff\xff\xff\xff\xb3Xp\xc0\xff\xff\xff\xff\xb4\"4P\xff\xff\xff\xff\xb59\xa4@\xff\xff\xff\xff\xb6\x03g\xd0" + + "\xff\xff\xff\xff\xb7\x1a\xd7\xc0\xff\xff\xff\xff\xb7\xe4\x9bP\xff\xff\xff\xff\xb8\xfd\\\xc0\xff\xff\xff\xff\xb9\xc7 P\xff\xff\xff\xff\xcc\x1cn@\xff\xff\xff\xff\xccl\xe7\xd0\xff\xff\xff\xff\xd53U\xc0\xff\xff\xff\xff" + + "\xd5v\x92@\xff\xff\xff\xff\xfd\xd1<@\xff\xff\xff\xff\xfe\x92\xfa\xb0\xff\xff\xff\xff\xff\xcc\xcd\xc0\x00\x00\x00\x00\x00rܰ\x00\x00\x00\x00\x01uP\xc0\x00\x00\x00\x00\x02@I\xb0\x00\x00\x00\x00\x03U2\xc0" + + "\x00\x00\x00\x00\x04 +\xb0\x00\x00\x00\x00\x05>O@\x00\x00\x00\x00\x06\x00\r\xb0\x00\x00\x00\x00\a\v\xbc@\x00\x00\x00\x00\a\xdf\xef\xb0\x00\x00\x00\x00\b\xfe\x13@\x00\x00\x00\x00\t\xbfѰ\x00\x00\x00\x00" + + "\n\xdd\xf5@\x00\x00\x00\x00\v\xa8\xee0\x00\x00\x00\x00\f\xbd\xd7@\x00\x00\x00\x00\r\x88\xd00\x00\x00\x00\x00\x0e\x9d\xb9@\x00\x00\x00\x00\x0fh\xb20\x00\x00\x00\x00\x10\x86\xd5\xc0\x00\x00\x00\x00\x11H\x940" + + "\x00\x00\x00\x00\x12f\xb7\xc0\x00\x00\x00\x00\x13(v0\x00\x00\x00\x00\x14F\x99\xc0\x00\x00\x00\x00\x15\x11\x92\xb0\x00\x00\x00\x00\x16&{\xc0\x00\x00\x00\x00\x16\xf1t\xb0\x00\x00\x00\x00\x18\x06]\xc0\x00\x00\x00\x00" + + "\x18\xd1V\xb0\x00\x00\x00\x00\x19\xe6?\xc0\x00\x00\x00\x00\x1a\xb18\xb0\x00\x00\x00\x00\x1b\xcf\\@\x00\x00\x00\x00\x1c\x91\x1a\xb0\x00\x00\x00\x00\x1d\xaf>@\x00\x00\x00\x00\x1ep\xfc\xb0\x00\x00\x00\x00\x1f\x8f @" + + "\x00\x00\x00\x00 \u007f\x030\x00\x00\x00\x00!o\x02@\x00\x00\x00\x00\"9\xfb0\x00\x00\x00\x00#N\xe4@\x00\x00\x00\x00$\x19\xdd0\x00\x00\x00\x00%8\x00\xc0\x00\x00\x00\x00%\xf9\xbf0\x00\x00\x00\x00" + + "&\xf2\xf8\xc0\x00\x00\x00\x00'١0\x00\x00\x00\x00(\xf7\xc4\xc0\x00\x00\x00\x00)½\xb0\x00\x00\x00\x00*צ\xc0\x00\x00\x00\x00+\xa2\x9f\xb0\x00\x00\x00\x00,\xb7\x88\xc0\x00\x00\x00\x00-\x82\x81\xb0" + + "\x00\x00\x00\x00.\x97j\xc0\x00\x00\x00\x00/bc\xb0\x00\x00\x00\x000\x80\x87@\x00\x00\x00\x001BE\xb0\x00\x00\x00\x002`i@\x00\x00\x00\x003=\xd70\x00\x00\x00\x004@K@\x00\x00\x00\x00" + + "5\vD0\x00\x00\x00\x006\r\xb8@\x00\x00\x00\x007\x06հ\x00\x00\x00\x008\x00\x0f@\x00\x00\x00\x008\xcb\b0\x00\x00\x00\x009\xe9+\xc0\x00\x00\x00\x00:\xaa\xea0\x00\x00\x00\x00;\xc9\r\xc0" + + "\x00\x00\x00\x00<\x8a\xcc0\x00\x00\x00\x00=\xa8\xef\xc0\x00\x00\x00\x00>j\xae0\x00\x00\x00\x00?\x88\xd1\xc0\x00\x00\x00\x00@Sʰ\x00\x00\x00\x00Ah\xb3\xc0\x00\x00\x00\x00B3\xac\xb0\x00\x00\x00\x00" + + "CH\x95\xc0\x00\x00\x00\x00D\x13\x8e\xb0\x00\x00\x00\x00E1\xb2@\x00\x00\x00\x00E\xf3p\xb0\x00\x00\x00\x00G\x11\x94@\x00\x00\x00\x00G\xef\x020\x00\x00\x00\x00H\xf1v@\x00\x00\x00\x00I\xbco0" + + "\x00\x00\x00\x00J\xd1X@\x00\x00\x00\x00K\xb8\x00\xb0\x00\x00\x00\x00L\xb1:@\x00\x00\x00\x00M\xc6\a0\x00\x00\x00\x00NP\x82\xc0\x00\x00\x00\x00O\x9c\xae\xb0\x00\x00\x00\x00PB\xd9\xc0\x00\x00\x00\x00" + + "Q|\x90\xb0\x00\x00\x00\x00R+\xf6@\x00\x00\x00\x00S\\r\xb0\x00\x00\x00\x00T\v\xd8@\x00\x00\x00\x00W7\xe60\x00\x00\x00\x00W\xaf\xec\xc0\x00\x00\x00\x00XC\x86\xb0\x01\x02\x01\x03\x01\x04\x02\x04" + + "\x02\x04\x02\x04\x02\x04\x02\x03\x02\x03\x02\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03" + + "\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x06\xff\xff\xbd\x84\x00\x00\xff\xff\xbd\xba\x00\x04" + + "\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x00\f\xff\xff\xc7\xc0\x01\f\xff\xff\xd5\xd0\x01\x10\xff\xff\xd5\xd0\x00\x10LMT\x00SMT\x00-05\x00-04\x00-03\x00\n<-03>3\nPK" + + "\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x1d`̟\x00\x03\x00\x00\x00\x03\x00\x00\x15\x00\x1c\x00America/Cambridge_BayUT\t\x00\x03\x82\x0f\x8ba\x82\x0f" + + "\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" + + "\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>\x00\x00\x00\t\x00\x00\x00%\xff\xff\xff\xff\xa1\xf2̀" + + "\xff\xff\xff\xffˉ\f\x90\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff\xf7/Zp\xff\xff\xff\xff\xf8(\x85\xf0\x00\x00\x00\x00\x13id\x10\x00\x00\x00\x00\x14YG\x00\x00\x00\x00\x00" + + "\x15IF\x10\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17)(\x10\x00\x00\x00\x00\x18\"E\x80\x00\x00\x00\x00\x19\t\n\x10\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2&\x90\x00\x00\x00\x00\x1b\xe2\t\x80" + + "\x00\x00\x00\x00\x1c\xd2\b\x90\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1\xea\x90\x00\x00\x00\x00\x1f\xa1̀\x00\x00\x00\x00 v\x1d\x10\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xff\x10\x00\x00\x00\x00" + + "#j\xcc\x00\x00\x00\x00\x00$5\xe1\x10\x00\x00\x00\x00%J\xae\x00\x00\x00\x00\x00&\x15\xc3\x10\x00\x00\x00\x00'*\x90\x00\x00\x00\x00\x00'\xfeߐ\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\xde\xc1\x90" + + "\x00\x00\x00\x00*\xeaT\x00\x00\x00\x00\x00+\xbe\xa3\x90\x00\x00\x00\x00,\xd3p\x80\x00\x00\x00\x00-\x9e\x85\x90\x00\x00\x00\x00.\xb3R\x80\x00\x00\x00\x00/~g\x90\x00\x00\x00\x000\x934\x80\x00\x00\x00\x00" + + "1g\x84\x10\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003Gf\x10\x00\x00\x00\x004R\xf8\x80\x00\x00\x00\x005'H\x10\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b\xf7\x00" + + "\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xca\xf0\x00\x00\x00\x00:\x04\xe9P\x00\x00\x00\x00:\xc6\xee\x10\x00\x00\x00\x00;ۻ\x00\x00\x00\x00\x00<\xb0\n\x90\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00" + + ">\x8f\xec\x90\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@oΐ\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00BO\xb0\x90\x00\x00\x00\x00Cd}\x80\x00\x00\x00\x00D/\x92\x90\x00\x00\x00\x00ED_\x80" + + "\x00\x00\x00\x00E\xf3\xc5\x10\x03\x01\x02\x03\x04\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\a\x06\b\a\x05\x03\x05" + + "\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x00\x00\x00\x00\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\xab\xa0\x01\b\xff\xff\x9d\x90\x00\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xab\xa0\x01\x15\xff\xff\xb9\xb0\x01\x19\xff\xff\xab\xa0\x00\x1d\xff\xff" + + "\xb9\xb0\x00!-00\x00MWT\x00MPT\x00MST\x00MDDT\x00MDT\x00CDT\x00CST\x00EST\x00\nMST7MDT,M3.2.0,M11" + + ".1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSӿ\x92\xbc\xb5\x06\x00\x00\xb5\x06\x00\x00\x10\x00\x1c\x00America/MontrealUT\t\x00\x03\x82\x0f\x8ba" + + "\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00" + + "\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xac\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xffr\xee" + + "x\xec\xff\xff\xff\xff\x9e\xb8\x93p\xff\xff\xff\xff\x9f\xba\xeb`\xff\xff\xff\xff\xa0\x87.\xc8\xff\xff\xff\xff\xa1\x9a\xb1@\xff\xff\xff\xff\xa2\x94\x06\xf0\xff\xff\xff\xff\xa3U\xa9@\xff\xff\xff\xff\xa4\x86]\xf0\xff\xff" + + "\xff\xff\xa5(x`\xff\xff\xff\xff\xa6f?\xf0\xff\xff\xff\xff\xa7\fN\xe0\xff\xff\xff\xff\xa8F!\xf0\xff\xff\xff\xff\xa8\xec0\xe0\xff\xff\xff\xff\xaa\x1c\xc9p\xff\xff\xff\xff\xaa\xd5M`\xff\xff\xff\xff\xab\xfc" + + "\xabp\xff\xff\xff\xff\xac\xb5/`\xff\xff\xff\xff\xad܍p\xff\xff\xff\xff\xae\x95\x11`\xff\xff\xff\xff\xaf\xbcop\xff\xff\xff\xff\xb0~-\xe0\xff\xff\xff\xff\xb1\x9cQp\xff\xff\xff\xff\xb2gJ`\xff\xff" + + "\xff\xff\xb3|3p\xff\xff\xff\xff\xb4G,`\xff\xff\xff\xff\xb5\\\x15p\xff\xff\xff\xff\xb6'\x0e`\xff\xff\xff\xff\xb7;\xf7p\xff\xff\xff\xff\xb8\x06\xf0`\xff\xff\xff\xff\xb9%\x13\xf0\xff\xff\xff\xff\xb9\xe6" + + "\xd2`\xff\xff\xff\xff\xbb\x04\xf5\xf0\xff\xff\xff\xff\xbb\xcf\xee\xe0\xff\xff\xff\xff\xbc\xe4\xd7\xf0\xff\xff\xff\xff\xbd\xaf\xd0\xe0\xff\xff\xff\xff\xbeĹ\xf0\xff\xff\xff\xff\xbf\x8f\xb2\xe0\xff\xff\xff\xff\xc0\xa4\x9b\xf0\xff\xff" + + "\xff\xff\xc1o\x94\xe0\xff\xff\xff\xff\u0084}\xf0\xff\xff\xff\xff\xc3Ov\xe0\xff\xff\xff\xff\xc4d_\xf0\xff\xff\xff\xff\xc5/X\xe0\xff\xff\xff\xff\xc6M|p\xff\xff\xff\xff\xc7\x0f:\xe0\xff\xff\xff\xff\xc8-" + + "^p\xff\xff\xff\xffˈ\xf0p\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xfb\xe0\xff\xff\xff\xff\xd3u\xe4\xf0\xff\xff\xff\xff\xd4@\xdd\xe0\xff\xff\xff\xff\xd5U\xaa\xd0\xff\xff\xff\xff\xd6 \xa3\xc0\xff\xff" + + "\xff\xff\xd75\x8c\xd0\xff\xff\xff\xff\xd8\x00\x85\xc0\xff\xff\xff\xff\xd9\x15n\xd0\xff\xff\xff\xff\xda3v@\xff\xff\xff\xff\xda\xfe\xa7p\xff\xff\xff\xff\xdc\x13t`\xff\xff\xff\xff\xdcމp\xff\xff\xff\xffݩ" + + "\x82`\xff\xff\xff\xff\u07bekp\xff\xff\xff\xff߉d`\xff\xff\xff\xff\xe0\x9eMp\xff\xff\xff\xff\xe1iF`\xff\xff\xff\xff\xe2~/p\xff\xff\xff\xff\xe3I(`\xff\xff\xff\xff\xe4^\x11p\xff\xff" + + "\xff\xff\xe5)\n`\xff\xff\xff\xff\xe6G-\xf0\xff\xff\xff\xff\xe7\x12&\xe0\xff\xff\xff\xff\xe8'\x0f\xf0\xff\xff\xff\xff\xe9\x16\xf2\xe0\xff\xff\xff\xff\xea\x06\xf1\xf0\xff\xff\xff\xff\xea\xf6\xd4\xe0\xff\xff\xff\xff\xeb\xe6" + + "\xd3\xf0\xff\xff\xff\xff\xecֶ\xe0\xff\xff\xff\xff\xedƵ\xf0\xff\xff\xff\xff\xee\xbf\xd3`\xff\xff\xff\xff\xef\xaf\xd2p\xff\xff\xff\xff\xf0\x9f\xb5`\xff\xff\xff\xff\xf1\x8f\xb4p\xff\xff\xff\xff\xf2\u007f\x97`\xff\xff" + + "\xff\xff\xf3o\x96p\xff\xff\xff\xff\xf4_y`\xff\xff\xff\xff\xf5Oxp\xff\xff\xff\xff\xf6?[`\xff\xff\xff\xff\xf7/Zp\xff\xff\xff\xff\xf8(w\xe0\xff\xff\xff\xff\xf9\x0f\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00@o" + + "\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xb5\x94\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff\xb9\xb0\x00\b" + + "\xff\xff\xc7\xc0\x01\f\xff\xff\xc7\xc0\x01\x10LMT\x00EDT\x00EST\x00EWT\x00EPT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04" + + "\n\x00\x00\x00\x00\x00#\x82iS\x04,2h\x99\x01\x00\x00\x99\x01\x00\x00\x10\x00\x1c\x00America/SantaremUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01" + + "\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00" + + "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x04\x00\x00\x00\f\xff\xff\xff\xff\x96\xaazH\xff\xff\xff\xff\xb8\x0fW" + + "\xf0\xff\xff\xff\xff\xb8\xfdN\xb0\xff\xff\xff\xff\xb9\xf1B@\xff\xff\xff\xff\xbaނ0\xff\xff\xff\xff\xda8\xbc@\xff\xff\xff\xff\xda\xec\b@\xff\xff\xff\xff\xdc\x19\xef\xc0\xff\xff\xff\xffܹg0\xff\xff\xff" + + "\xff\xdd\xfb#@\xff\xff\xff\xffޛ\xec0\xff\xff\xff\xff\xdfݨ@\xff\xff\xff\xff\xe0TA0\xff\xff\xff\xff\xf4\x98\r\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf6\xc0r@\xff\xff\xff\xff\xf7\x0e," + + "\xb0\xff\xff\xff\xff\xf8Q:@\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xfa\n\xe0\xc0\xff\xff\xff\xff\xfa\xa9\x06\xb0\xff\xff\xff\xff\xfb\xec\x14@\xff\xff\xff\xff\xfc\x8b\x8b\xb0\x00\x00\x00\x00\x1dɜ@\x00\x00\x00" + + "\x00\x1ex\xe5\xb0\x00\x00\x00\x00\x1f\xa0C\xc0\x00\x00\x00\x00 3ݰ\x00\x00\x00\x00!\x81w@\x00\x00\x00\x00\"\vְ\x00\x00\x00\x00H`q@\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\xff\xff̸\x00\x00\xff\xff\xd5\xd0\x01\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x00\x04LMT\x00-03\x00-04\x00\n<-03>3\nP" + + "K\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xf2\x04\xde\xdd\x11\x02\x00\x00\x11\x02\x00\x00\x0e\x00\x1c\x00America/CancunUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00" + + "\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00" + + "\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00*\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\xa5\xb6\xda`\x00\x00\x00\x00\x16\x86" + + "\xd5`\x00\x00\x00\x001gg\xf0\x00\x00\x00\x002r\xfa`\x00\x00\x00\x003GI\xf0\x00\x00\x00\x004R\xdc`\x00\x00\x00\x005'+\xf0\x00\x00\x00\x005\xc4\x00`\x00\x00\x00\x0062\xccp\x00\x00" + + "\x00\x007\a\x1c\x00\x00\x00\x00\x008\x1b\xe8\xf0\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xca\xf0\x00\x00\x00\x00:\xf5\x04\x80\x00\x00\x00\x00;\xb6\xc2\xf0\x00\x00\x00\x00<\xaf\xfc\x80\x00\x00\x00\x00=\xbb" + + "\x8e\xf0\x00\x00\x00\x00>\x8fހ\x00\x00\x00\x00?\x9bp\xf0\x00\x00\x00\x00@o\xc0\x80\x00\x00\x00\x00A\x84\x8dp\x00\x00\x00\x00BO\xa2\x80\x00\x00\x00\x00Cdop\x00\x00\x00\x00D/\x84\x80\x00\x00" + + "\x00\x00EDQp\x00\x00\x00\x00F\x0ff\x80\x00\x00\x00\x00G$3p\x00\x00\x00\x00G\xf8\x83\x00\x00\x00\x00\x00I\x04\x15p\x00\x00\x00\x00I\xd8e\x00\x00\x00\x00\x00J\xe3\xf7p\x00\x00\x00\x00K\xb8" + + "G\x00\x00\x00\x00\x00L\xcd\x13\xf0\x00\x00\x00\x00M\x98)\x00\x00\x00\x00\x00N\xac\xf5\xf0\x00\x00\x00\x00Ox\v\x00\x00\x00\x00\x00P\x8c\xd7\xf0\x00\x00\x00\x00Qa'\x80\x00\x00\x00\x00Rl\xb9\xf0\x00\x00" + + "\x00\x00SA\t\x80\x00\x00\x00\x00TL\x9b\xf0\x00\x00\x00\x00T\xcd\xdd\x00\x01\x03\x02\x03\x02\x03\x02\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04" + + "\x01\x04\x01\x03\xff\xff\xae\xa8\x00\x00\xff\xff\xab\xa0\x00\x04\xff\xff\xc7\xc0\x01\b\xff\xff\xb9\xb0\x00\f\xff\xff\xb9\xb0\x01\x10LMT\x00CST\x00EDT\x00EST\x00CDT\x00\nEST5\n" + + "PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSU\xactA\xb5\x01\x00\x00\xb5\x01\x00\x00\x11\x00\x1c\x00America/MatamorosUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8ba" + + "ux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00" + + "\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\xa5\xb6\xda`\x00\x00" + + "\x00\x00\"U\xf1\x00\x00\x00\x00\x00#j\xbd\xf0\x00\x00\x00\x001gv\x00\x00\x00\x00\x002s\bp\x00\x00\x00\x003GX\x00\x00\x00\x00\x004R\xeap\x00\x00\x00\x005':\x00\x00\x00\x00\x0062" + + "\xccp\x00\x00\x00\x007\a\x1c\x00\x00\x00\x00\x008\x1b\xe8\xf0\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xca\xf0\x00\x00\x00\x00:\xf5\x04\x80\x00\x00\x00\x00;\xb6\xc2\xf0\x00\x00\x00\x00<\xaf\xfc\x80\x00\x00" + + "\x00\x00=\xbb\x8e\xf0\x00\x00\x00\x00>\x8fހ\x00\x00\x00\x00?\x9bp\xf0\x00\x00\x00\x00@o\xc0\x80\x00\x00\x00\x00A\x84\x8dp\x00\x00\x00\x00BO\xa2\x80\x00\x00\x00\x00Cdop\x00\x00\x00\x00D/" + + "\x84\x80\x00\x00\x00\x00EDQp\x00\x00\x00\x00F\x0ff\x80\x00\x00\x00\x00G$3p\x00\x00\x00\x00G\xf8\x83\x00\x00\x00\x00\x00I\x04\x15p\x00\x00\x00\x00I\xd8e\x00\x00\x00\x00\x00J\xe3\xf7p\x00\x00" + + "\x00\x00K\x9c\x97\x80\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xff\xa2@\x00\x00\xff\xff\xab\xa0\x00\x04\xff\xff\xb9\xb0\x01\bLMT\x00" + + "CST\x00CDT\x00\nCST6CDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSs\xb0\xeau\xb4\x01\x00\x00\xb4\x01\x00\x00\x10\x00" + + "\x1c\x00America/EirunepeUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!\x00\x00\x00\x04\x00\x00\x00\f\xff\xff\xff\xff\x96\xaa\x88\x80\xff\xff\xff\xff\xb8\x0ff\x00\xff\xff\xff\xff\xb8\xfd\\\xc0\xff\xff\xff\xff\xb9\xf1PP\xff\xff\xff\xff\xbaސ" + + "@\xff\xff\xff\xff\xda8\xcaP\xff\xff\xff\xff\xda\xec\x16P\xff\xff\xff\xff\xdc\x19\xfd\xd0\xff\xff\xff\xffܹu@\xff\xff\xff\xff\xdd\xfb1P\xff\xff\xff\xffޛ\xfa@\xff\xff\xff\xff\xdfݶP\xff\xff\xff" + + "\xff\xe0TO@\xff\xff\xff\xff\xf4\x98\x1b\xd0\xff\xff\xff\xff\xf5\x05z@\xff\xff\xff\xff\xf6\xc0\x80P\xff\xff\xff\xff\xf7\x0e:\xc0\xff\xff\xff\xff\xf8QHP\xff\xff\xff\xff\xf8\xc7\xe1@\xff\xff\xff\xff\xfa\n\xee" + + "\xd0\xff\xff\xff\xff\xfa\xa9\x14\xc0\xff\xff\xff\xff\xfb\xec\"P\xff\xff\xff\xff\xfc\x8b\x99\xc0\x00\x00\x00\x00\x1dɪP\x00\x00\x00\x00\x1ex\xf3\xc0\x00\x00\x00\x00\x1f\xa0Q\xd0\x00\x00\x00\x00 3\xeb\xc0\x00\x00\x00" + + "\x00!\x81\x85P\x00\x00\x00\x00\"\v\xe4\xc0\x00\x00\x00\x00,\xc0\xd1P\x00\x00\x00\x00-f\xe0@\x00\x00\x00\x00H`\u007fP\x00\x00\x00\x00R\u007f\x04\xc0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x02\xff\xff\xbe\x80\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x00\x04LMT\x00-04\x00-05\x00\n<-05>" + + "5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xd0v\x01\x8a\x01\x04\x00\x00\x01\x04\x00\x00\x14\x00\x1c\x00America/Santa_IsabelUT\t\x00\x03\x82\x0f\x8b" + + "a\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" + + "\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00^\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff\xa5" + + "\xb6\xf6\x80\xff\xff\xff\xff\xa9yOp\xff\xff\xff\xff\xaf\xf2|\xf0\xff\xff\xff\xff\xb6fdp\xff\xff\xff\xff\xb7\x1b\x10\x00\xff\xff\xff\xff\xb8\n\xf2\xf0\xff\xff\xff\xff\xcbꍀ\xff\xff\xff\xff\xd2#\xf4p\xff" + + "\xff\xff\xffҙ\xbap\xff\xff\xff\xff\xd7\x1bY\x00\xff\xff\xff\xffؑ\xb4\xf0\xff\xff\xff\xff\xe2~K\x90\xff\xff\xff\xff\xe3IR\x90\xff\xff\xff\xff\xe4^-\x90\xff\xff\xff\xff\xe5)4\x90\xff\xff\xff\xff\xe6" + + "GJ\x10\xff\xff\xff\xff\xe7\x12Q\x10\xff\xff\xff\xff\xe8',\x10\xff\xff\xff\xff\xe8\xf23\x10\xff\xff\xff\xff\xea\a\x0e\x10\xff\xff\xff\xff\xea\xd2\x15\x10\xff\xff\xff\xff\xeb\xe6\xf0\x10\xff\xff\xff\xff\xec\xb1\xf7\x10\xff" + + "\xff\xff\xff\xed\xc6\xd2\x10\xff\xff\xff\xff\xee\x91\xd9\x10\x00\x00\x00\x00\v\u0be0\x00\x00\x00\x00\f\xd9\xcd\x10\x00\x00\x00\x00\r\xc0\x91\xa0\x00\x00\x00\x00\x0e\xb9\xaf\x10\x00\x00\x00\x00\x0f\xa9\xae \x00\x00\x00\x00\x10" + + "\x99\x91\x10\x00\x00\x00\x00\x11\x89\x90 \x00\x00\x00\x00\x12ys\x10\x00\x00\x00\x00\x13ir \x00\x00\x00\x00\x14YU\x10\x00\x00\x00\x00\x15IT \x00\x00\x00\x00\x1697\x10\x00\x00\x00\x00\x17)6 \x00" + + "\x00\x00\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18 \x00\x00\x00\x00\x1a\x025\x90\x00\x00\x00\x00\x1a\xf24\xa0\x00\x00\x00\x00\x1b\xe2\x17\x90\x00\x00\x00\x00\x1c\xd2\x16\xa0\x00\x00\x00\x00\x1d\xc1\xf9\x90\x00\x00\x00\x00\x1e" + + "\xb1\xf8\xa0\x00\x00\x00\x00\x1f\xa1ې\x00\x00\x00\x00 v+ \x00\x00\x00\x00!\x81\xbd\x90\x00\x00\x00\x00\"V\r \x00\x00\x00\x00#j\xda\x10\x00\x00\x00\x00$5\xef \x00\x00\x00\x00%J\xbc\x10\x00" + + "\x00\x00\x00&\x15\xd1 \x00\x00\x00\x00'*\x9e\x10\x00\x00\x00\x00'\xfe\xed\xa0\x00\x00\x00\x00)\n\x80\x10\x00\x00\x00\x00)\xdeϠ\x00\x00\x00\x00*\xeab\x10\x00\x00\x00\x00+\xbe\xb1\xa0\x00\x00\x00\x00," + + "\xd3~\x90\x00\x00\x00\x00-\x9e\x93\xa0\x00\x00\x00\x00.\xb3`\x90\x00\x00\x00\x00/~u\xa0\x00\x00\x00\x000\x93B\x90\x00\x00\x00\x001g\x92 \x00\x00\x00\x002s$\x90\x00\x00\x00\x003Gt \x00" + + "\x00\x00\x004S\x06\x90\x00\x00\x00\x005'V \x00\x00\x00\x0062\xe8\x90\x00\x00\x00\x007\a8 \x00\x00\x00\x008\x1c\x05\x10\x00\x00\x00\x008\xe7\x1a \x00\x00\x00\x009\xfb\xe7\x10\x00\x00\x00\x00:" + + "\xc6\xfc \x00\x00\x00\x00;\xdb\xc9\x10\x00\x00\x00\x00<\xb0\x18\xa0\x00\x00\x00\x00=\xbb\xab\x10\x00\x00\x00\x00>\x8f\xfa\xa0\x00\x00\x00\x00?\x9b\x8d\x10\x00\x00\x00\x00@oܠ\x00\x00\x00\x00A\x84\xa9\x90\x00" + + "\x00\x00\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b\x90\x00\x00\x00\x00D/\xa0\xa0\x00\x00\x00\x00EDm\x90\x00\x00\x00\x00F\x0f\x82\xa0\x00\x00\x00\x00G$O\x90\x00\x00\x00\x00G\xf8\x9f \x00\x00\x00\x00I" + + "\x041\x90\x00\x00\x00\x00I\u0601 \x00\x00\x00\x00J\xe4\x13\x90\x00\x00\x00\x00K\x9c\xb3\xa0\x01\x02\x01\x02\x03\x02\x04\x05\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\xff\xff\x92L\x00\x00\xff\xff\x9d\x90\x00\x04\xff\xff\x8f\x80\x00\b\xff\xff\x9d\x90\x01\f\xff\xff\x9d\x90\x01\x10\xff\xff\x9d\x90\x01\x14LMT\x00MST\x00PST\x00PDT\x00PWT\x00PPT" + + "\x00\nPST8PDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x0f\x00\x1c\x00Ameri" + + "ca/GrenadaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffz敹\xff\xff\xff\xff\xcb\xf62\xc0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\x01\x03\x02\x01\xff\xff\xc2\a\x00\x00\xff\xff\xc7\xc0\x00" + + "\x04\xff\xff\xd5\xd0\x01\b\xff\xff\xd5\xd0\x01\fLMT\x00AST\x00APT\x00AWT\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00" + + "\x00\x0f\x00\x1c\x00America/MarigotUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffz敹\xff\xff\xff\xff\xcb\xf62\xc0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\x01\x03\x02\x01\xff" + + "\xff\xc2\a\x00\x00\xff\xff\xc7\xc0\x00\x04\xff\xff\xd5\xd0\x01\b\xff\xff\xd5\xd0\x01\fLMT\x00AST\x00APT\x00AWT\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xf7" + + "\xe9 y\xbd\x02\x00\x00\xbd\x02\x00\x00\x0e\x00\x1c\x00America/InuvikUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZi" + + "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00;\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xff\xe0\x06N\x80\xff\xff\xff\xff\xf7/h\x80\xff\xff\xff\xff\xf8(\x94\x00\x00\x00\x00\x00" + + "\x11\x89\x90 \x00\x00\x00\x00\x13id\x10\x00\x00\x00\x00\x14YG\x00\x00\x00\x00\x00\x15IF\x10\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17)(\x10\x00\x00\x00\x00\x18\"E\x80\x00\x00\x00\x00\x19\t\n\x10" + + "\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2&\x90\x00\x00\x00\x00\x1b\xe2\t\x80\x00\x00\x00\x00\x1c\xd2\b\x90\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1\xea\x90\x00\x00\x00\x00\x1f\xa1̀\x00\x00\x00\x00" + + " v\x1d\x10\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xff\x10\x00\x00\x00\x00#j\xcc\x00\x00\x00\x00\x00$5\xe1\x10\x00\x00\x00\x00%J\xae\x00\x00\x00\x00\x00&\x15\xc3\x10\x00\x00\x00\x00'*\x90\x00" + + "\x00\x00\x00\x00'\xfeߐ\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\xde\xc1\x90\x00\x00\x00\x00*\xeaT\x00\x00\x00\x00\x00+\xbe\xa3\x90\x00\x00\x00\x00,\xd3p\x80\x00\x00\x00\x00-\x9e\x85\x90\x00\x00\x00\x00" + + ".\xb3R\x80\x00\x00\x00\x00/~g\x90\x00\x00\x00\x000\x934\x80\x00\x00\x00\x001g\x84\x10\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003Gf\x10\x00\x00\x00\x004R\xf8\x80\x00\x00\x00\x005'H\x10" + + "\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe7\f\x10\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xc6\xee\x10\x00\x00\x00\x00;ۻ\x00\x00\x00\x00\x00" + + "<\xb0\n\x90\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8f\xec\x90\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@oΐ\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00BO\xb0\x90\x00\x00\x00\x00Cd}\x80" + + "\x00\x00\x00\x00D/\x92\x90\x00\x00\x00\x00ED_\x80\x00\x00\x00\x00E\xf3\xc5\x10\x02\x01\x02\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03" + + "\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x00\x00\x00\x00\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x8f\x80\x00\t\xff\xff\x9d\x90\x00\r\xff\xff\xab\xa0\x01\x11-00\x00PDD" + + "T\x00PST\x00MST\x00MDT\x00\nMST7MDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xe5s\xb3\\'\x01\x00\x00" + + "'\x01\x00\x00\x0f\x00\x1c\x00America/ManaguaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffi\x87(\xb8\xff\xff\xff\xff\xacb\u0080\xff\xff\xff\xff\xb1ӔP\xff\xff\xff\xff\xb2t]@\xff\xff" + - "\xff\xff\xc8[f\xd0\xff\xff\xff\xff\xc8\xd3Q@\xff\xff\xff\xff\xca;H\xd0\xff\xff\xff\xffʼm\xc0\xff\xff\xff\xff\xcc$eP\xff\xff\xff\xff̜O\xc0\xff\xff\xff\xff\xd1\xc4\vP\xff\xff\xff\xff\xd2;" + - "\xf5\xc0\xff\xff\xff\xffӣ\xedP\xff\xff\xff\xff\xd4\x1b\xd7\xc0\xff\xff\xff\xff\xf7`\x05\xd0\xff\xff\xff\xff\xf7\xff}@\xff\xff\xff\xff\xf9=D\xd0\xff\xff\xff\xff\xf9\xe3S\xc0\xff\xff\xff\xff\xfa\xdb;\xd0\xff\xff" + - "\xff\xff\xfb\xa7\x86@\xff\xff\xff\xff\xfcũ\xd0\xff\xff\xff\xff\xfd\x87h@\xff\xff\xff\xff\xfe\xb8\x00\xd0\xff\xff\xff\xff\xff\xa7\xe3\xc0\x00\x00\x00\x00\x00\x97\xe2\xd0\x00\x00\x00\x00\x01\x87\xc5\xc0\x00\x00\x00\x00\x02w" + - "\xc4\xd0\x00\x00\x00\x00\x03p\xe2@\x00\x00\x00\x00\x04`\xe1P\x00\x00\x00\x00\x055\x14\xc0\x00\x00\x00\x00\x06@\xc3P\x00\x00\x00\x00\a\x16H@\x00\x00\x00\x00\b \xa5P\x00\x00\x00\x00\b\xf7{\xc0\x00\x00" + - "\x00\x00\n\x00\x87P\x00\x00\x00\x00\n\xf0j@\x00\x00\x00\x00\v\xe0iP\x00\x00\x00\x00\fن\xc0\x00\x00\x00\x00\r\xc0KP\x00\x00\x00\x00\x0e\xb9h\xc0\x00\x00\x00\x00\x0f\xb2\xa2P\x00\x00\x00\x00\x10}" + - "\x9b@\x00\x00\x00\x00\x11Q\xea\xd0\x00\x00\x00\x00\x12f\xb7\xc0\x00\x00\x00\x00\x131\xcc\xd0\x00\x00\x00\x00\x14F\x99\xc0\x00\x00\x00\x00\x15[\x82\xd0\x00\x00\x00\x00\x16&{\xc0\x00\x00\x00\x00\x17;d\xd0\x00\x00" + - "\x00\x00\x18\x06]\xc0\x00\x00\x00\x00\x19\x1bF\xd0\x00\x00\x00\x00\x19\xe6?\xc0\x00\x00\x00\x00\x1a\xfb(\xd0\x00\x00\x00\x00\x1b\xcf\\@\x00\x00\x00\x00\x1c\xdb\n\xd0\x00\x00\x00\x00\x1d\xaf>@\x00\x00\x00\x00\x1ez" + - "SP\x00\x00\x00\x00\x1f\x8f @\x00\x00\x00\x00 Z5P\x00\x00\x00\x00!o\x02@\x00\x00\x00\x00\"CQ\xd0\x00\x00\x00\x00#N\xe4@\x00\x00\x00\x00$#3\xd0\x00\x00\x00\x00%.\xc6@\x00\x00" + - "\x00\x00&\x15\x8a\xd0\x00\x00\x00\x00'\x17\xe2\xc0\x00\x00\x00\x00'\xfe\xa7P\x00\x00\x00\x00(\xf7\xd2\xd0\x00\x00\x00\x00)މP\x00\x00\x00\x00*״\xd0\x00\x00\x00\x00+\xbekP\x00\x00\x00\x00,\xb7" + - "\x96\xd0\x00\x00\x00\x00-\x9eMP\x00\x00\x00\x00.\x97x\xd0\x00\x00\x00\x00/~/P\x00\x00\x00\x000wZ\xd0\x00\x00\x00\x001gK\xd0\x00\x00\x00\x002W<\xd0\x00\x00\x00\x003G-\xd0\x00\x00" + - "\x00\x004@YP\x00\x00\x00\x005\x1d\xd5P\x00\x00\x00\x0062\xb0P\x00\x00\x00\x006\xfd\xb7P\x00\x00\x00\x008\x1b\xcc\xd0\x00\x00\x00\x008\xe6\xd3\xd0\x00\x00\x00\x009\xfb\xae\xd0\x00\x00\x00\x00:\xc6" + - "\xb5\xd0\x00\x00\x00\x00;ې\xd0\x00\x00\x00\x00<\xaf\xd2P\x00\x00\x00\x00=\xbbr\xd0\x00\x00\x00\x00>\x8f\xb4P\x00\x00\x00\x00?\x9bT\xd0\x00\x00\x00\x00@f[\xd0\x00\x00\x00\x00ED5P\x00\x00" + - "\x00\x00E\xf3\x8c\xd0\x00\x00\x00\x00G$\x17P\x00\x00\x00\x00GܩP\x00\x00\x00\x00I\x03\xf9P\x00\x00\x00\x00I\xb3P\xd0\x00\x00\x00\x00J\xe3\xdbP\x00\x00\x00\x00K\x9cmP\x00\x00\x00\x00L\xcc" + - "\xf7\xd0\x00\x00\x00\x00M\x85\x89\xd0\x00\x00\x00\x00N\xbfN\xd0\x00\x00\x00\x00Ow\xe0\xd0\x00\x00\x00\x00P\x95\xf6P\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xffi\x87,d\xff\xff\xff\xff\xbd-H\xe8\x00\x00\x00\x00\x06Ct`\x00\x00\x00\x00\t\xa4>P\x00\x00" + + "\x00\x00\x11Q\xf8\xe0\x00\x00\x00\x00\x11\xd4oP\x00\x00\x00\x00\x131\xda\xe0\x00\x00\x00\x00\x13\xb4QP\x00\x00\x00\x00)a\x91 \x00\x00\x00\x00*\xc1KP\x00\x00\x00\x00+C\xdd\xe0\x00\x00\x00\x002\xc9" + + "\xefP\x00\x00\x00\x00BX\xc0\xe0\x00\x00\x00\x00C?iP\x00\x00\x00\x00DTn\x80\x00\x00\x00\x00E\x1fY`\x01\x02\x03\x02\x04\x02\x04\x02\x03\x02\x03\x02\x04\x02\x04\x02\xff\xff\xaf\x1c\x00\x00\xff\xff\xaf\x18" + + "\x00\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x00\f\xff\xff\xb9\xb0\x01\x10LMT\x00MMT\x00CST\x00EST\x00CDT\x00\nCST6\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS" + + "\xfe\xe6\xf5J\x05\x04\x00\x00\x05\x04\x00\x00\x0e\x00\x1c\x00America/DawsonUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZ" + + "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00]\x00\x00\x00\t\x00\x00\x00%\xff\xff\xff\xff}\x86\x8e\xb4\xff\xff\xff\xff\x9e\xb8˰\xff\xff\xff\xff\x9f\xbb#\xa0\xff\xff\xff" + + "\xff\xa0\xd0\f\xb0\xff\xff\xff\xff\xa1\xa2Ҁ\xff\xff\xff\xffˉ(\xb0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a4 \xff\xff\xff\xff\xf7/v\x90\xff\xff\xff\xff\xf8(\xa2\x10\x00\x00\x00\x00\a0\xec" + + "\x90\x00\x00\x00\x00\x13ir \x00\x00\x00\x00\x14YU\x10\x00\x00\x00\x00\x15IT \x00\x00\x00\x00\x1697\x10\x00\x00\x00\x00\x17)6 \x00\x00\x00\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18 \x00\x00\x00" + + "\x00\x1a\x025\x90\x00\x00\x00\x00\x1a\xf24\xa0\x00\x00\x00\x00\x1b\xe2\x17\x90\x00\x00\x00\x00\x1c\xd2\x16\xa0\x00\x00\x00\x00\x1d\xc1\xf9\x90\x00\x00\x00\x00\x1e\xb1\xf8\xa0\x00\x00\x00\x00\x1f\xa1ې\x00\x00\x00\x00 v+" + + " \x00\x00\x00\x00!\x81\xbd\x90\x00\x00\x00\x00\"V\r \x00\x00\x00\x00#j\xda\x10\x00\x00\x00\x00$5\xef \x00\x00\x00\x00%J\xbc\x10\x00\x00\x00\x00&\x15\xd1 \x00\x00\x00\x00'*\x9e\x10\x00\x00\x00" + + "\x00'\xfe\xed\xa0\x00\x00\x00\x00)\n\x80\x10\x00\x00\x00\x00)\xdeϠ\x00\x00\x00\x00*\xeab\x10\x00\x00\x00\x00+\xbe\xb1\xa0\x00\x00\x00\x00,\xd3~\x90\x00\x00\x00\x00-\x9e\x93\xa0\x00\x00\x00\x00.\xb3`" + + "\x90\x00\x00\x00\x00/~u\xa0\x00\x00\x00\x000\x93B\x90\x00\x00\x00\x001g\x92 \x00\x00\x00\x002s$\x90\x00\x00\x00\x003Gt \x00\x00\x00\x004S\x06\x90\x00\x00\x00\x005'V \x00\x00\x00" + + "\x0062\xe8\x90\x00\x00\x00\x007\a8 \x00\x00\x00\x008\x1c\x05\x10\x00\x00\x00\x008\xe7\x1a \x00\x00\x00\x009\xfb\xe7\x10\x00\x00\x00\x00:\xc6\xfc \x00\x00\x00\x00;\xdb\xc9\x10\x00\x00\x00\x00<\xb0\x18" + + "\xa0\x00\x00\x00\x00=\xbb\xab\x10\x00\x00\x00\x00>\x8f\xfa\xa0\x00\x00\x00\x00?\x9b\x8d\x10\x00\x00\x00\x00@oܠ\x00\x00\x00\x00A\x84\xa9\x90\x00\x00\x00\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b\x90\x00\x00\x00" + + "\x00D/\xa0\xa0\x00\x00\x00\x00EDm\x90\x00\x00\x00\x00E\xf3\xd3 \x00\x00\x00\x00G-\x8a\x10\x00\x00\x00\x00Gӵ \x00\x00\x00\x00I\rl\x10\x00\x00\x00\x00I\xb3\x97 \x00\x00\x00\x00J\xedN" + + "\x10\x00\x00\x00\x00K\x9c\xb3\xa0\x00\x00\x00\x00L\xd6j\x90\x00\x00\x00\x00M|\x95\xa0\x00\x00\x00\x00N\xb6L\x90\x00\x00\x00\x00O\\w\xa0\x00\x00\x00\x00P\x96.\x90\x00\x00\x00\x00Q\x8f\xa6|\x00\x00\x00\x00?\x9b8\xec\x00\x00\x00\x00@o\x88|\x00\x00\x00\x00A\x84Ul\x00\x00\x00\x00BOj|\x00\x00\x00\x00Cd7l\x00" + + "\x00\x00\x00D/L|\x00\x00\x00\x00ED\x19l\x00\x00\x00\x00E\xf3\x9a\xe0\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x05\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\xff\xff\xb2\xc8\x00\x00\xff\xff\xb2\xc0\x00\x04\xff\xff\xc7\xc0\x01\b\xff\xff\xb9\xb0\x00\fLMT\x00HMT\x00CDT\x00CST\x00" + - "\nCST5CDT,M3.2.0/0,M11.1.0/1\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R8O:\xbf\x95\x03\x00\x00\x95\x03\x00\x00\x11\x00\x1c\x00Am" + - "erica/MenomineeUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00R\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xffawIc\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff" + - "\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xd3u\xf3\x00\xff\xff\xff\xff\xd4@\xeb\xf0\xff\xff\xff\xff\xf9\x0fJ\x80\xff\xff\xff\xff\xfa\bg\xf0\xff\xff\xff\xff\xfe\xb8" + - "+\x00\x00\x00\x00\x00\x06@\xdfp\x00\x00\x00\x00\a0\xd0p\x00\x00\x00\x00\a\x8d'\x80\x00\x00\x00\x00\t\x10\xb2p\x00\x00\x00\x00\t\xad\xa3\x00\x00\x00\x00\x00\n\xf0\x94p\x00\x00\x00\x00\v\xe0\x93\x80\x00\x00" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\xff\xff\xc3D\x00\x00\xff\xff\xb9\xb0\x00" + + "\x04\xff\xff\xd5\xd0\x01\b\xff\xff\xc7\xc0\x00\f\xff\xff\xd5\xd0\x01\x10\xff\xff\xd5\xd0\x01\x14LMT\x00EST\x00ADT\x00AST\x00AWT\x00APT\x00\nAST4ADT,M3" + + ".2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS[Sp\x90\x02\x05\x00\x00\x02\x05\x00\x00\x10\x00\x1c\x00America/SantiagoU" + + "T\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00z\x00\x00\x00\x06\x00\x00" + + "\x00\x14\xff\xff\xff\xffi\x87\x1d\xc6\xff\xff\xff\xff\x8f0GF\xff\xff\xff\xff\x9b\\\xe5P\xff\xff\xff\xff\x9f|\xe2\xc6\xff\xff\xff\xff\xa1\x00q\xc0\xff\xff\xff\xff\xb0^w\xc6\xff\xff\xff\xff\xb1w=@\xff\xff" + + "\xff\xff\xb2A\x00\xd0\xff\xff\xff\xff\xb3Xp\xc0\xff\xff\xff\xff\xb4\"4P\xff\xff\xff\xff\xb59\xa4@\xff\xff\xff\xff\xb6\x03g\xd0\xff\xff\xff\xff\xb7\x1a\xd7\xc0\xff\xff\xff\xff\xb7\xe4\x9bP\xff\xff\xff\xff\xb8\xfd" + + "\\\xc0\xff\xff\xff\xff\xb9\xc7 P\xff\xff\xff\xff\xcc\x1cn@\xff\xff\xff\xff\xccl\xe7\xd0\xff\xff\xff\xff\xd3\u070f\xc0\xff\xff\xff\xff\xd4\x1bɰ\xff\xff\xff\xff\xd53U\xc0\xff\xff\xff\xff\xd5v\x92@\xff\xff" + + "\xff\xff\xfd\xd1<@\xff\xff\xff\xff\xfe\x92\xfa\xb0\xff\xff\xff\xff\xff\xcc\xcd\xc0\x00\x00\x00\x00\x00rܰ\x00\x00\x00\x00\x01uP\xc0\x00\x00\x00\x00\x02@I\xb0\x00\x00\x00\x00\x03U2\xc0\x00\x00\x00\x00\x04 " + + "+\xb0\x00\x00\x00\x00\x05>O@\x00\x00\x00\x00\x06\x00\r\xb0\x00\x00\x00\x00\a\v\xbc@\x00\x00\x00\x00\a\xdf\xef\xb0\x00\x00\x00\x00\b\xfe\x13@\x00\x00\x00\x00\t\xbfѰ\x00\x00\x00\x00\n\xdd\xf5@\x00\x00" + + "\x00\x00\v\xa8\xee0\x00\x00\x00\x00\f\xbd\xd7@\x00\x00\x00\x00\r\x88\xd00\x00\x00\x00\x00\x0e\x9d\xb9@\x00\x00\x00\x00\x0fh\xb20\x00\x00\x00\x00\x10\x86\xd5\xc0\x00\x00\x00\x00\x11H\x940\x00\x00\x00\x00\x12f" + + "\xb7\xc0\x00\x00\x00\x00\x13(v0\x00\x00\x00\x00\x14F\x99\xc0\x00\x00\x00\x00\x15\x11\x92\xb0\x00\x00\x00\x00\x16&{\xc0\x00\x00\x00\x00\x16\xf1t\xb0\x00\x00\x00\x00\x18\x06]\xc0\x00\x00\x00\x00\x18\xd1V\xb0\x00\x00" + + "\x00\x00\x19\xe6?\xc0\x00\x00\x00\x00\x1a\xb18\xb0\x00\x00\x00\x00\x1b\xcf\\@\x00\x00\x00\x00\x1c\x91\x1a\xb0\x00\x00\x00\x00\x1d\xaf>@\x00\x00\x00\x00\x1ep\xfc\xb0\x00\x00\x00\x00\x1f\x8f @\x00\x00\x00\x00 \u007f" + + "\x030\x00\x00\x00\x00!o\x02@\x00\x00\x00\x00\"9\xfb0\x00\x00\x00\x00#N\xe4@\x00\x00\x00\x00$\x19\xdd0\x00\x00\x00\x00%8\x00\xc0\x00\x00\x00\x00%\xf9\xbf0\x00\x00\x00\x00&\xf2\xf8\xc0\x00\x00" + + "\x00\x00'١0\x00\x00\x00\x00(\xf7\xc4\xc0\x00\x00\x00\x00)½\xb0\x00\x00\x00\x00*צ\xc0\x00\x00\x00\x00+\xa2\x9f\xb0\x00\x00\x00\x00,\xb7\x88\xc0\x00\x00\x00\x00-\x82\x81\xb0\x00\x00\x00\x00.\x97" + + "j\xc0\x00\x00\x00\x00/bc\xb0\x00\x00\x00\x000\x80\x87@\x00\x00\x00\x001BE\xb0\x00\x00\x00\x002`i@\x00\x00\x00\x003=\xd70\x00\x00\x00\x004@K@\x00\x00\x00\x005\vD0\x00\x00" + + "\x00\x006\r\xb8@\x00\x00\x00\x007\x06հ\x00\x00\x00\x008\x00\x0f@\x00\x00\x00\x008\xcb\b0\x00\x00\x00\x009\xe9+\xc0\x00\x00\x00\x00:\xaa\xea0\x00\x00\x00\x00;\xc9\r\xc0\x00\x00\x00\x00<\x8a" + + "\xcc0\x00\x00\x00\x00=\xa8\xef\xc0\x00\x00\x00\x00>j\xae0\x00\x00\x00\x00?\x88\xd1\xc0\x00\x00\x00\x00@Sʰ\x00\x00\x00\x00Ah\xb3\xc0\x00\x00\x00\x00B3\xac\xb0\x00\x00\x00\x00CH\x95\xc0\x00\x00" + + "\x00\x00D\x13\x8e\xb0\x00\x00\x00\x00E1\xb2@\x00\x00\x00\x00E\xf3p\xb0\x00\x00\x00\x00G\x11\x94@\x00\x00\x00\x00G\xef\x020\x00\x00\x00\x00H\xf1v@\x00\x00\x00\x00I\xbco0\x00\x00\x00\x00J\xd1" + + "X@\x00\x00\x00\x00K\xb8\x00\xb0\x00\x00\x00\x00L\xb1:@\x00\x00\x00\x00M\xc6\a0\x00\x00\x00\x00NP\x82\xc0\x00\x00\x00\x00O\x9c\xae\xb0\x00\x00\x00\x00PB\xd9\xc0\x00\x00\x00\x00Q|\x90\xb0\x00\x00" + + "\x00\x00R+\xf6@\x00\x00\x00\x00S\\r\xb0\x00\x00\x00\x00T\v\xd8@\x00\x00\x00\x00W7\xe60\x00\x00\x00\x00W\xaf\xec\xc0\x00\x00\x00\x00Y\x17\xc80\x00\x00\x00\x00Y\x8f\xce\xc0\x00\x00\x00\x00Z\xf7" + + "\xaa0\x00\x00\x00\x00[o\xb0\xc0\x00\x00\x00\x00\\\xa9g\xb0\x01\x02\x01\x03\x01\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x03\x02\x03\x05\x03\x02\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03" + + "\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03" + + "\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\xff\xff\xbd\xba\x00\x00\xff\xff\xbd\xba\x00\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x00\f\xff\xff\xc7\xc0\x01\f\xff\xff\xd5\xd0\x01\x10LMT\x00" + + "SMT\x00-05\x00-04\x00-03\x00\n<-04>4<-03>,M9.1.6/24,M4.1.6/24\nPK\x03\x04\n\x00\x00\x00\x00\x00#" + + "\x82iSø\xab\x9b\xf0\x00\x00\x00\xf0\x00\x00\x00\x0f\x00\x1c\x00America/CrestonUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_" + + "\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\v\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff^\x04\f\xb0\xff\xff\xff\xff\x9e\xa6:\x90\xff\xff\xff\xff\x9f\xbb\a" + + "\x80\xff\xff\xff\xff\xa0\x86\x1c\x90\xff\xff\xff\xff\xa1\x9a\xe9\x80\xff\xff\xff\xffˉ\f\x90\xff\xff\xff\xff\xcf\x17\xdf\x1c\xff\xff\xff\xffϏ\xe5\xac\xff\xff\xff\xffЁ\x1a\x1c\xff\xff\xff\xff\xfa\xf8u\x10\xff\xff\xff" + + "\xff\xfb\xe8X\x00\x02\x01\x02\x01\x02\x03\x02\x03\x02\x01\x02\xff\xff\x96\xee\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\fLMT\x00MDT\x00MST\x00MWT\x00\nMST" + + "7\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xef\xf0R\x8a\xc4\x02\x00\x00\xc4\x02\x00\x00\x0f\x00\x1c\x00America/CordobaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8ba" + + "ux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00" + + "\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xad\xb0\xff\xff" + + "\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8" + + "\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff" + + "\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM" + + "\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff" + + "\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc3" + + "5\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00" + + "\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'!\x0f0\x00\x00\x00\x00'\xd0X\xa0\x00\x00\x00\x00)\x00\xff@\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0" + + "\xd30\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x00\x00\x00\x00H\xfa\xa2\xb0\x00\x00\x00\x00I\xbca \x01\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04\x02\x04\x05\x04\x05\x03\x05\x04\x05\x04\x05\xff" + + "\xff\xc3\xd0\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02\x00\n<-03" + + ">3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS%J\xd5\xebS\x01\x00\x00S\x01\x00\x00\x0f\x00\x1c\x00America/JamaicaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8b" + + "aux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01" + + "\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffi\x87#~\xff" + + "\xff\xff\xff\x93\x0f\xb4\xfe\x00\x00\x00\x00\a\x8d\x19p\x00\x00\x00\x00\t\x10\xa4`\x00\x00\x00\x00\t\xad\x94\xf0\x00\x00\x00\x00\n\xf0\x86`\x00\x00\x00\x00\v\xe0\x85p\x00\x00\x00\x00\f٢\xe0\x00\x00\x00\x00\r" + + "\xc0gp\x00\x00\x00\x00\x0e\xb9\x84\xe0\x00\x00\x00\x00\x0f\xa9\x83\xf0\x00\x00\x00\x00\x10\x99f\xe0\x00\x00\x00\x00\x11\x89e\xf0\x00\x00\x00\x00\x12yH\xe0\x00\x00\x00\x00\x13iG\xf0\x00\x00\x00\x00\x14Y*\xe0\x00" + + "\x00\x00\x00\x15I)\xf0\x00\x00\x00\x00\x169\f\xe0\x00\x00\x00\x00\x17)\v\xf0\x00\x00\x00\x00\x18\")`\x00\x00\x00\x00\x19\b\xed\xf0\x00\x00\x00\x00\x1a\x02\v`\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\xff\xff\xb8\x02\x00\x00\xff\xff\xb8\x02\x00\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x01\fLMT\x00KMT\x00EST\x00EDT\x00\nEST5\nPK\x03\x04\n" + + "\x00\x00\x00\x00\x00#\x82iS挋\x92\xf6\x01\x00\x00\xf6\x01\x00\x00\x0e\x00\x1c\x00America/MaceioUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E" + + "\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + + "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00)\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96\xaah|\xff\xff\xff\xff\xb8\x0fI\xe0\xff\xff" + + "\xff\xff\xb8\xfd@\xa0\xff\xff\xff\xff\xb9\xf140\xff\xff\xff\xff\xba\xdet \xff\xff\xff\xff\xda8\xae0\xff\xff\xff\xff\xda\xeb\xfa0\xff\xff\xff\xff\xdc\x19\xe1\xb0\xff\xff\xff\xffܹY \xff\xff\xff\xff\xdd\xfb" + + "\x150\xff\xff\xff\xffޛ\xde \xff\xff\xff\xff\xdfݚ0\xff\xff\xff\xff\xe0T3 \xff\xff\xff\xff\xf4\x97\xff\xb0\xff\xff\xff\xff\xf5\x05^ \xff\xff\xff\xff\xf6\xc0d0\xff\xff\xff\xff\xf7\x0e\x1e\xa0\xff\xff" + + "\xff\xff\xf8Q,0\xff\xff\xff\xff\xf8\xc7\xc5 \xff\xff\xff\xff\xfa\nҰ\xff\xff\xff\xff\xfa\xa8\xf8\xa0\xff\xff\xff\xff\xfb\xec\x060\xff\xff\xff\xff\xfc\x8b}\xa0\x00\x00\x00\x00\x1dɎ0\x00\x00\x00\x00\x1ex" + + "נ\x00\x00\x00\x00\x1f\xa05\xb0\x00\x00\x00\x00 3Ϡ\x00\x00\x00\x00!\x81i0\x00\x00\x00\x00\"\vȠ\x00\x00\x00\x00#X\x10\xb0\x00\x00\x00\x00#\xe2p \x00\x00\x00\x00%7\xf2\xb0\x00\x00" + + "\x00\x00%\xd4\xc7 \x00\x00\x00\x000\x80y0\x00\x00\x00\x001\x1dM\xa0\x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xb8\x85 \x00\x00\x00\x009\xdf\xe30\x00\x00\x00\x009\xf2J \x00\x00\x00\x00;\xc8" + + "\xff\xb0\x00\x00\x00\x003\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS+\x10`ȫ\x02\x00\x00\xab\x02\x00\x00\x14\x00\x1c\x00A" + + "merica/Dawson_CreekUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00:\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff^=t8\xff\xff\xff\xff\x9e\xb8\xbd\xa0\xff\xff\xff\xff\x9f\xbb\x15\x90\xff\xff\xff\xffˉ\x1a\xa0\xff\xff\xff\xff\xd2#" + + "\xf4p\xff\xff\xff\xff\xd2a&\x10\xff\xff\xff\xff\xd5U\xf1 \xff\xff\xff\xff\xd6 \xea\x10\xff\xff\xff\xff\xd75\xd3 \xff\xff\xff\xff\xd8\x00\xcc\x10\xff\xff\xff\xff\xd9\x15\xb5 \xff\xff\xff\xff\xd9\xe0\xae\x10\xff\xff" + + "\xff\xff\xda\xfeѠ\xff\xff\xff\xff\xdb\xc0\x90\x10\xff\xff\xff\xff\xdc\u07b3\xa0\xff\xff\xff\xffݩ\xac\x90\xff\xff\xff\xff\u07be\x95\xa0\xff\xff\xff\xff߉\x8e\x90\xff\xff\xff\xff\xe0\x9ew\xa0\xff\xff\xff\xff\xe1i" + + "p\x90\xff\xff\xff\xff\xe2~Y\xa0\xff\xff\xff\xff\xe3IR\x90\xff\xff\xff\xff\xe4^;\xa0\xff\xff\xff\xff\xe5)4\x90\xff\xff\xff\xff\xe6GX \xff\xff\xff\xff\xe7\x12Q\x10\xff\xff\xff\xff\xe8': \xff\xff" + + "\xff\xff\xe8\xf23\x10\xff\xff\xff\xff\xea\a\x1c \xff\xff\xff\xff\xea\xd2\x15\x10\xff\xff\xff\xff\xeb\xe6\xfe \xff\xff\xff\xff\xec\xb1\xf7\x10\xff\xff\xff\xff\xed\xc6\xe0 \xff\xff\xff\xff\xee\x91\xd9\x10\xff\xff\xff\xff\xef\xaf" + + "\xfc\xa0\xff\xff\xff\xff\xf0q\xbb\x10\xff\xff\xff\xff\xf1\x8fޠ\xff\xff\xff\xff\xf2\u007f\xc1\x90\xff\xff\xff\xff\xf3o\xc0\xa0\xff\xff\xff\xff\xf4_\xa3\x90\xff\xff\xff\xff\xf5O\xa2\xa0\xff\xff\xff\xff\xf6?\x85\x90\xff\xff" + + "\xff\xff\xf7/\x84\xa0\xff\xff\xff\xff\xf8(\xa2\x10\xff\xff\xff\xff\xf9\x0ff\xa0\xff\xff\xff\xff\xfa\b\x84\x10\xff\xff\xff\xff\xfa\xf8\x83 \xff\xff\xff\xff\xfb\xe8f\x10\xff\xff\xff\xff\xfc\xd8e \xff\xff\xff\xff\xfd\xc8" + + "H\x10\xff\xff\xff\xff\xfe\xb8G \xff\xff\xff\xff\xff\xa8*\x10\x00\x00\x00\x00\x00\x98) \x00\x00\x00\x00\x01\x88\f\x10\x00\x00\x00\x00\x02x\v \x00\x00\x00\x00\x03q(\x90\x00\x00\x00\x00\x04a'\xa0\x00\x00" + + "\x00\x00\x05\x01\xf0\x90\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x05\xff\xff\x8fH\x00\x00\xff\xff\x9d\x90\x01\x04\xff\xff\x8f\x80\x00\b\xff\xff\x9d\x90\x01\f\xff\xff\x9d\x90\x01\x10\xff\xff\x9d\x90\x00\x14LMT\x00PDT\x00PST\x00PWT\x00PPT\x00" + + "MST\x00\nMST7\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSӿ\x92\xbc\xb5\x06\x00\x00\xb5\x06\x00\x00\x0f\x00\x1c\x00America/TorontoUT\t\x00\x03" + + "\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xac\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff" + + "\xff\xffr\xeex\xec\xff\xff\xff\xff\x9e\xb8\x93p\xff\xff\xff\xff\x9f\xba\xeb`\xff\xff\xff\xff\xa0\x87.\xc8\xff\xff\xff\xff\xa1\x9a\xb1@\xff\xff\xff\xff\xa2\x94\x06\xf0\xff\xff\xff\xff\xa3U\xa9@\xff\xff\xff\xff\xa4\x86" + + "]\xf0\xff\xff\xff\xff\xa5(x`\xff\xff\xff\xff\xa6f?\xf0\xff\xff\xff\xff\xa7\fN\xe0\xff\xff\xff\xff\xa8F!\xf0\xff\xff\xff\xff\xa8\xec0\xe0\xff\xff\xff\xff\xaa\x1c\xc9p\xff\xff\xff\xff\xaa\xd5M`\xff\xff" + + "\xff\xff\xab\xfc\xabp\xff\xff\xff\xff\xac\xb5/`\xff\xff\xff\xff\xad܍p\xff\xff\xff\xff\xae\x95\x11`\xff\xff\xff\xff\xaf\xbcop\xff\xff\xff\xff\xb0~-\xe0\xff\xff\xff\xff\xb1\x9cQp\xff\xff\xff\xff\xb2g" + + "J`\xff\xff\xff\xff\xb3|3p\xff\xff\xff\xff\xb4G,`\xff\xff\xff\xff\xb5\\\x15p\xff\xff\xff\xff\xb6'\x0e`\xff\xff\xff\xff\xb7;\xf7p\xff\xff\xff\xff\xb8\x06\xf0`\xff\xff\xff\xff\xb9%\x13\xf0\xff\xff" + + "\xff\xff\xb9\xe6\xd2`\xff\xff\xff\xff\xbb\x04\xf5\xf0\xff\xff\xff\xff\xbb\xcf\xee\xe0\xff\xff\xff\xff\xbc\xe4\xd7\xf0\xff\xff\xff\xff\xbd\xaf\xd0\xe0\xff\xff\xff\xff\xbeĹ\xf0\xff\xff\xff\xff\xbf\x8f\xb2\xe0\xff\xff\xff\xff\xc0\xa4" + + "\x9b\xf0\xff\xff\xff\xff\xc1o\x94\xe0\xff\xff\xff\xff\u0084}\xf0\xff\xff\xff\xff\xc3Ov\xe0\xff\xff\xff\xff\xc4d_\xf0\xff\xff\xff\xff\xc5/X\xe0\xff\xff\xff\xff\xc6M|p\xff\xff\xff\xff\xc7\x0f:\xe0\xff\xff" + + "\xff\xff\xc8-^p\xff\xff\xff\xffˈ\xf0p\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xfb\xe0\xff\xff\xff\xff\xd3u\xe4\xf0\xff\xff\xff\xff\xd4@\xdd\xe0\xff\xff\xff\xff\xd5U\xaa\xd0\xff\xff\xff\xff\xd6 " + + "\xa3\xc0\xff\xff\xff\xff\xd75\x8c\xd0\xff\xff\xff\xff\xd8\x00\x85\xc0\xff\xff\xff\xff\xd9\x15n\xd0\xff\xff\xff\xff\xda3v@\xff\xff\xff\xff\xda\xfe\xa7p\xff\xff\xff\xff\xdc\x13t`\xff\xff\xff\xff\xdcމp\xff\xff" + + "\xff\xffݩ\x82`\xff\xff\xff\xff\u07bekp\xff\xff\xff\xff߉d`\xff\xff\xff\xff\xe0\x9eMp\xff\xff\xff\xff\xe1iF`\xff\xff\xff\xff\xe2~/p\xff\xff\xff\xff\xe3I(`\xff\xff\xff\xff\xe4^" + + "\x11p\xff\xff\xff\xff\xe5)\n`\xff\xff\xff\xff\xe6G-\xf0\xff\xff\xff\xff\xe7\x12&\xe0\xff\xff\xff\xff\xe8'\x0f\xf0\xff\xff\xff\xff\xe9\x16\xf2\xe0\xff\xff\xff\xff\xea\x06\xf1\xf0\xff\xff\xff\xff\xea\xf6\xd4\xe0\xff\xff" + + "\xff\xff\xeb\xe6\xd3\xf0\xff\xff\xff\xff\xecֶ\xe0\xff\xff\xff\xff\xedƵ\xf0\xff\xff\xff\xff\xee\xbf\xd3`\xff\xff\xff\xff\xef\xaf\xd2p\xff\xff\xff\xff\xf0\x9f\xb5`\xff\xff\xff\xff\xf1\x8f\xb4p\xff\xff\xff\xff\xf2\u007f" + + "\x97`\xff\xff\xff\xff\xf3o\x96p\xff\xff\xff\xff\xf4_y`\xff\xff\xff\xff\xf5Oxp\xff\xff\xff\xff\xf6?[`\xff\xff\xff\xff\xf7/Zp\xff\xff\xff\xff\xf8(w\xe0\xff\xff\xff\xff\xf9\x0f\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0\x00\x00" + + "\x00\x00@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xb5\x94\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff" + + "\xb9\xb0\x00\b\xff\xff\xc7\xc0\x01\f\xff\xff\xc7\xc0\x01\x10LMT\x00EDT\x00EST\x00EWT\x00EPT\x00\nEST5EDT,M3.2.0,M11.1.0\n" + + "PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xd6\xe1Հ\x9c\x01\x00\x00\x9c\x01\x00\x00\x13\x00\x1c\x00America/Mexico_CityUT\t\x00\x03\x82\x0f\x8ba\x82\x0f" + + "\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" + + "\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1b\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\xa5\xb6\xe8p" + + "\xff\xff\xff\xff\xaf\xf2n\xe0\xff\xff\xff\xff\xb6fV`\xff\xff\xff\xff\xb7C\xd2`\xff\xff\xff\xff\xb8\f6`\xff\xff\xff\xff\xb8\xfd\x86\xf0\xff\xff\xff\xff\xc5ް`\xff\xff\xff\xffƗ4P\xff\xff\xff\xff" + + "\xc9U\xf1\xe0\xff\xff\xff\xff\xc9\xea\xddP\xff\xff\xff\xff\xcf\x02\xc6\xe0\xff\xff\xff\xffϷVP\xff\xff\xff\xffڙ\x15\xe0\xff\xff\xff\xff\xdbv\x83\xd0\x00\x00\x00\x001gv\x00\x00\x00\x00\x002s\bp" + + "\x00\x00\x00\x003GX\x00\x00\x00\x00\x004R\xeap\x00\x00\x00\x005':\x00\x00\x00\x00\x0062\xccp\x00\x00\x00\x007\a\x1c\x00\x00\x00\x00\x008\x1b\xe8\xf0\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x00" + + "9\xfb\xca\xf0\x00\x00\x00\x00:\xf5\x04\x80\x00\x00\x00\x00;\xb6\xc2\xf0\x00\x00\x00\x00<\xaf\xfc\x80\x01\x02\x01\x02\x01\x02\x03\x02\x03\x02\x04\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\xff\xff\xa3\f\x00" + + "\x00\xff\xff\x9d\x90\x00\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10LMT\x00MST\x00CST\x00CDT\x00CWT\x00\nCST6CDT,M4.1.0" + + ",M10.5.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSӿ\x92\xbc\xb5\x06\x00\x00\xb5\x06\x00\x00\x0e\x00\x1c\x00America/NassauUT\t\x00\x03\x82\x0f" + + "\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xac\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff" + + "r\xeex\xec\xff\xff\xff\xff\x9e\xb8\x93p\xff\xff\xff\xff\x9f\xba\xeb`\xff\xff\xff\xff\xa0\x87.\xc8\xff\xff\xff\xff\xa1\x9a\xb1@\xff\xff\xff\xff\xa2\x94\x06\xf0\xff\xff\xff\xff\xa3U\xa9@\xff\xff\xff\xff\xa4\x86]\xf0" + + "\xff\xff\xff\xff\xa5(x`\xff\xff\xff\xff\xa6f?\xf0\xff\xff\xff\xff\xa7\fN\xe0\xff\xff\xff\xff\xa8F!\xf0\xff\xff\xff\xff\xa8\xec0\xe0\xff\xff\xff\xff\xaa\x1c\xc9p\xff\xff\xff\xff\xaa\xd5M`\xff\xff\xff\xff" + + "\xab\xfc\xabp\xff\xff\xff\xff\xac\xb5/`\xff\xff\xff\xff\xad܍p\xff\xff\xff\xff\xae\x95\x11`\xff\xff\xff\xff\xaf\xbcop\xff\xff\xff\xff\xb0~-\xe0\xff\xff\xff\xff\xb1\x9cQp\xff\xff\xff\xff\xb2gJ`" + + "\xff\xff\xff\xff\xb3|3p\xff\xff\xff\xff\xb4G,`\xff\xff\xff\xff\xb5\\\x15p\xff\xff\xff\xff\xb6'\x0e`\xff\xff\xff\xff\xb7;\xf7p\xff\xff\xff\xff\xb8\x06\xf0`\xff\xff\xff\xff\xb9%\x13\xf0\xff\xff\xff\xff" + + "\xb9\xe6\xd2`\xff\xff\xff\xff\xbb\x04\xf5\xf0\xff\xff\xff\xff\xbb\xcf\xee\xe0\xff\xff\xff\xff\xbc\xe4\xd7\xf0\xff\xff\xff\xff\xbd\xaf\xd0\xe0\xff\xff\xff\xff\xbeĹ\xf0\xff\xff\xff\xff\xbf\x8f\xb2\xe0\xff\xff\xff\xff\xc0\xa4\x9b\xf0" + + "\xff\xff\xff\xff\xc1o\x94\xe0\xff\xff\xff\xff\u0084}\xf0\xff\xff\xff\xff\xc3Ov\xe0\xff\xff\xff\xff\xc4d_\xf0\xff\xff\xff\xff\xc5/X\xe0\xff\xff\xff\xff\xc6M|p\xff\xff\xff\xff\xc7\x0f:\xe0\xff\xff\xff\xff" + + "\xc8-^p\xff\xff\xff\xffˈ\xf0p\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xfb\xe0\xff\xff\xff\xff\xd3u\xe4\xf0\xff\xff\xff\xff\xd4@\xdd\xe0\xff\xff\xff\xff\xd5U\xaa\xd0\xff\xff\xff\xff\xd6 \xa3\xc0" + + "\xff\xff\xff\xff\xd75\x8c\xd0\xff\xff\xff\xff\xd8\x00\x85\xc0\xff\xff\xff\xff\xd9\x15n\xd0\xff\xff\xff\xff\xda3v@\xff\xff\xff\xff\xda\xfe\xa7p\xff\xff\xff\xff\xdc\x13t`\xff\xff\xff\xff\xdcމp\xff\xff\xff\xff" + + "ݩ\x82`\xff\xff\xff\xff\u07bekp\xff\xff\xff\xff߉d`\xff\xff\xff\xff\xe0\x9eMp\xff\xff\xff\xff\xe1iF`\xff\xff\xff\xff\xe2~/p\xff\xff\xff\xff\xe3I(`\xff\xff\xff\xff\xe4^\x11p" + + "\xff\xff\xff\xff\xe5)\n`\xff\xff\xff\xff\xe6G-\xf0\xff\xff\xff\xff\xe7\x12&\xe0\xff\xff\xff\xff\xe8'\x0f\xf0\xff\xff\xff\xff\xe9\x16\xf2\xe0\xff\xff\xff\xff\xea\x06\xf1\xf0\xff\xff\xff\xff\xea\xf6\xd4\xe0\xff\xff\xff\xff" + + "\xeb\xe6\xd3\xf0\xff\xff\xff\xff\xecֶ\xe0\xff\xff\xff\xff\xedƵ\xf0\xff\xff\xff\xff\xee\xbf\xd3`\xff\xff\xff\xff\xef\xaf\xd2p\xff\xff\xff\xff\xf0\x9f\xb5`\xff\xff\xff\xff\xf1\x8f\xb4p\xff\xff\xff\xff\xf2\u007f\x97`" + + "\xff\xff\xff\xff\xf3o\x96p\xff\xff\xff\xff\xf4_y`\xff\xff\xff\xff\xf5Oxp\xff\xff\xff\xff\xf6?[`\xff\xff\xff\xff\xf7/Zp\xff\xff\xff\xff\xf8(w\xe0\xff\xff\xff\xff\xf9\x0f\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00" + + "@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xb5\x94\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff\xb9\xb0" + + "\x00\b\xff\xff\xc7\xc0\x01\f\xff\xff\xc7\xc0\x01\x10LMT\x00EDT\x00EST\x00EWT\x00EPT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK" + + "\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\u007f$*\xa0\xa6\x03\x00\x00\xa6\x03\x00\x00\x0e\x00\x1c\x00America/CuiabaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01" + + "\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00" + + "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Y\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96\xaa{\x94\xff\xff\xff\xff\xb8\x0fW" + + "\xf0\xff\xff\xff\xff\xb8\xfdN\xb0\xff\xff\xff\xff\xb9\xf1B@\xff\xff\xff\xff\xbaނ0\xff\xff\xff\xff\xda8\xbc@\xff\xff\xff\xff\xda\xec\b@\xff\xff\xff\xff\xdc\x19\xef\xc0\xff\xff\xff\xffܹg0\xff\xff\xff" + + "\xff\xdd\xfb#@\xff\xff\xff\xffޛ\xec0\xff\xff\xff\xff\xdfݨ@\xff\xff\xff\xff\xe0TA0\xff\xff\xff\xff\xf4\x98\r\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf6\xc0r@\xff\xff\xff\xff\xf7\x0e," + + "\xb0\xff\xff\xff\xff\xf8Q:@\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xfa\n\xe0\xc0\xff\xff\xff\xff\xfa\xa9\x06\xb0\xff\xff\xff\xff\xfb\xec\x14@\xff\xff\xff\xff\xfc\x8b\x8b\xb0\x00\x00\x00\x00\x1dɜ@\x00\x00\x00" + + "\x00\x1ex\xe5\xb0\x00\x00\x00\x00\x1f\xa0C\xc0\x00\x00\x00\x00 3ݰ\x00\x00\x00\x00!\x81w@\x00\x00\x00\x00\"\vְ\x00\x00\x00\x00#X\x1e\xc0\x00\x00\x00\x00#\xe2~0\x00\x00\x00\x00%8\x00" + + "\xc0\x00\x00\x00\x00%\xd4\xd50\x00\x00\x00\x00'!\x1d@\x00\x00\x00\x00'\xbd\xf1\xb0\x00\x00\x00\x00)\x00\xff@\x00\x00\x00\x00)\x94\x990\x00\x00\x00\x00*\xea\x1b\xc0\x00\x00\x00\x00+k@\xb0\x00\x00\x00" + + "\x00,\xc0\xc3@\x00\x00\x00\x00-f\xd20\x00\x00\x00\x00.\xa0\xa5@\x00\x00\x00\x00/F\xb40\x00\x00\x00\x000\x80\x87@\x00\x00\x00\x001\x1d[\xb0\x00\x00\x00\x002W.\xc0\x00\x00\x00\x003\x06x" + + "0\x00\x00\x00\x0048b@\x00\x00\x00\x004\xf8\xcf0\x00\x00\x00\x006 -@\x00\x00\x00\x006\xcfv\xb0\x00\x00\x00\x007\xf6\xd4\xc0\x00\x00\x00\x008\xb8\x930\x00\x00\x00\x009\xdf\xf1@\x00\x00\x00" + + "\x00:\x8f:\xb0\x00\x00\x00\x00;\xc9\r\xc0\x00\x00\x00\x00N\xfe\xb0\x00\x00\x00\x00A\x87\x06@\x00\x00\x00\x00B\x17\xfd0\x00\x00\x00\x00CQ\xd0" + + "@\x00\x00\x00\x00C\xf7\xdf0\x00\x00\x00\x00EMa\xc0\x00\x00\x00\x00E\xe0\xfb\xb0\x00\x00\x00\x00G\x11\x94@\x00\x00\x00\x00G\xb7\xa30\x00\x00\x00\x00H\xfa\xb0\xc0\x00\x00\x00\x00I\x97\x850\x00\x00\x00" + + "\x00Jڒ\xc0\x00\x00\x00\x00K\x80\xa1\xb0\x00\x00\x00\x00L\xbat\xc0\x00\x00\x00\x00M`\x83\xb0\x00\x00\x00\x00N\x9aV\xc0\x00\x00\x00\x00OI\xa00\x00\x00\x00\x00P\x83s@\x00\x00\x00\x00Q G" + + "\xb0\x00\x00\x00\x00RcU@\x00\x00\x00\x00S\x00)\xb0\x00\x00\x00\x00TC7@\x00\x00\x00\x00T\xe9F0\x00\x00\x00\x00V#\x19@\x00\x00\x00\x00V\xc9(0\x00\x00\x00\x00X\x02\xfb@\x00\x00\x00" + + "\x00X\xa9\n0\x00\x00\x00\x00Y\xe2\xdd@\x00\x00\x00\x00Z\x88\xec0\x00\x00\x00\x00[\xden\xc0\x00\x00\x00\x00\\h\xce0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\xff\xff\xcbl\x00\x00\xff\xff\xd5\xd0\x01\x04\xff\xff\xc7\xc0\x00\bLMT\x00-03\x00-04\x00\n<-04>4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSq\xc9" + + "*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x12\x00\x1c\x00America/GuadeloupeUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00" + + "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffz敹\xff\xff\xff\xff\xcb\xf62\xc0\xff\xff\xff\xff\xd2#\xf4p\xff" + + "\xff\xff\xff\xd2`\xed\xd0\x01\x03\x02\x01\xff\xff\xc2\a\x00\x00\xff\xff\xc7\xc0\x00\x04\xff\xff\xd5\xd0\x01\b\xff\xff\xd5\xd0\x01\fLMT\x00AST\x00APT\x00AWT\x00\nAST4\nPK\x03" + + "\x04\n\x00\x00\x00\x00\x00#\x82iS\x1d\xf7\a ,\x06\x00\x00,\x06\x00\x00\x11\x00\x1c\x00America/Goose_BayUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v" + + "\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00" + + "\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x98\x00\x00\x00\n\x00\x00\x00!\xff\xff\xff\xff^=<$\xff\xff\xff\xff\x9e" + + "\xb8~\x8c\xff\xff\xff\xff\x9f\xba\xd6|\xff\xff\xff\xff\xbe\x9eMl\xff\xff\xff\xff\xc0\xb818\xff\xff\xff\xff\xc1y\xef\xa8\xff\xff\xff\xff\u0098\x138\xff\xff\xff\xff\xc3YѨ\xff\xff\xff\xff\xc4w\xf58\xff" + + "\xff\xff\xff\xc59\xb3\xa8\xff\xff\xff\xff\xc6a\x11\xb8\xff\xff\xff\xff\xc7\x19\x95\xa8\xff\xff\xff\xff\xc8@\xf3\xb8\xff\xff\xff\xff\xc9\x02\xb2(\xff\xff\xff\xff\xca ո\xff\xff\xff\xff\xca\xe2\x94(\xff\xff\xff\xff\xcc" + + "\x00\xb7\xb8\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xe6\xc8\xff\xff\xff\xffӈD\xd8\xff\xff\xff\xff\xd4J\x03H\xff\xff\xff\xff\xd5h&\xd8\xff\xff\xff\xff\xd6)\xe5H\xff\xff\xff\xff\xd7H\b\xd8\xff" + + "\xff\xff\xff\xd8\t\xc7H\xff\xff\xff\xff\xd9'\xea\xd8\xff\xff\xff\xff\xd9\xe9\xa9H\xff\xff\xff\xff\xdb\x11\aX\xff\xff\xff\xff\xdb\xd2\xc5\xc8\xff\xff\xff\xff\xdc\xdetX\xff\xff\xff\xffݩmH\xff\xff\xff\xff\xde" + + "\xbeVX\xff\xff\xff\xff߉OH\xff\xff\xff\xff\xe0\x9e8X\xff\xff\xff\xff\xe1i1H\xff\xff\xff\xff\xe2~\x1aX\xff\xff\xff\xff\xe3I\x13H\xff\xff\xff\xff\xe4]\xfcX\xff\xff\xff\xff\xe5(\xf5H\xff" + + "\xff\xff\xff\xe6G\x18\xd8\xff\xff\xff\xff\xe7\x12\x11\xc8\xff\xff\xff\xff\xe8&\xfa\xd8\xff\xff\xff\xff\xe8\xf1\xf3\xc8\xff\xff\xff\xff\xea\x06\xdc\xd8\xff\xff\xff\xff\xea\xd1\xd5\xc8\xff\xff\xff\xff\xeb\xe6\xbe\xd8\xff\xff\xff\xff\xec" + + "\xb1\xb7\xc8\xff\xff\xff\xff\xedƠ\xd8\xff\xff\xff\xff\ueffeH\xff\xff\xff\xffﯽX\xff\xff\xff\xff\xf0\x9f\xa0H\xff\xff\xff\xff\xf1\x8f\x9fX\xff\xff\xff\xff\xf2\u007f\x82H\xff\xff\xff\xff\xf3o\x81X\xff" + + "\xff\xff\xff\xf4_dH\xff\xff\xff\xff\xf5OcX\xff\xff\xff\xff\xf6?FH\xff\xff\xff\xff\xf7/EX\xff\xff\xff\xff\xf8(b\xc8\xff\xff\xff\xff\xf8\xdakX\xff\xff\xff\xff\xf9\x0f.`\xff\xff\xff\xff\xfa" + + "\bK\xd0\xff\xff\xff\xff\xfa\xf8J\xe0\xff\xff\xff\xff\xfb\xe8-\xd0\xff\xff\xff\xff\xfc\xd8,\xe0\xff\xff\xff\xff\xfd\xc8\x0f\xd0\xff\xff\xff\xff\xfe\xb8\x0e\xe0\xff\xff\xff\xff\xff\xa7\xf1\xd0\x00\x00\x00\x00\x00\x97\xf0\xe0\x00" + + "\x00\x00\x00\x01\x87\xd3\xd0\x00\x00\x00\x00\x02w\xd2\xe0\x00\x00\x00\x00\x03p\xf0P\x00\x00\x00\x00\x04`\xef`\x00\x00\x00\x00\x05P\xd2P\x00\x00\x00\x00\x06@\xd1`\x00\x00\x00\x00\a0\xb4P\x00\x00\x00\x00\b" + + " \xb3`\x00\x00\x00\x00\t\x10\x96P\x00\x00\x00\x00\n\x00\x95`\x00\x00\x00\x00\n\xf0xP\x00\x00\x00\x00\v\xe0w`\x00\x00\x00\x00\fٔ\xd0\x00\x00\x00\x00\r\xc0Y`\x00\x00\x00\x00\x0e\xb9v\xd0\x00" + + "\x00\x00\x00\x0f\xa9u\xe0\x00\x00\x00\x00\x10\x99X\xd0\x00\x00\x00\x00\x11\x89W\xe0\x00\x00\x00\x00\x12y:\xd0\x00\x00\x00\x00\x13i9\xe0\x00\x00\x00\x00\x14Y\x1c\xd0\x00\x00\x00\x00\x15I\x1b\xe0\x00\x00\x00\x00\x16" + + "8\xfe\xd0\x00\x00\x00\x00\x17(\xfd\xe0\x00\x00\x00\x00\x18\"\x1bP\x00\x00\x00\x00\x19\b\xdf\xe0\x00\x00\x00\x00\x1a\x01\xfdP\x00\x00\x00\x00\x1a\xf1\xfc`\x00\x00\x00\x00\x1b\xe1\xdfP\x00\x00\x00\x00\x1c\xd1\xde`\x00" + + "\x00\x00\x00\x1d\xc1\xc1P\x00\x00\x00\x00\x1e\xb1\xc0`\x00\x00\x00\x00\x1f\xa1\xa3P\x00\x00\x00\x00 u\xd6\xfc\x00\x00\x00\x00!\x81il\x00\x00\x00\x00\"U\xb8\xfc\x00\x00\x00\x00#jw\xdc\x00\x00\x00\x00$" + + "5\x9a\xfc\x00\x00\x00\x00%Jg\xec\x00\x00\x00\x00&\x15|\xfc\x00\x00\x00\x00'*I\xec\x00\x00\x00\x00'\xfe\x99|\x00\x00\x00\x00)\n+\xec\x00\x00\x00\x00)\xde{|\x00\x00\x00\x00*\xea\r\xec\x00" + + "\x00\x00\x00+\xbe]|\x00\x00\x00\x00,\xd3*l\x00\x00\x00\x00-\x9e?|\x00\x00\x00\x00.\xb3\fl\x00\x00\x00\x00/~!|\x00\x00\x00\x000\x92\xeel\x00\x00\x00\x001g=\xfc\x00\x00\x00\x002" + + "r\xd0l\x00\x00\x00\x003G\x1f\xfc\x00\x00\x00\x004R\xb2l\x00\x00\x00\x005'\x01\xfc\x00\x00\x00\x0062\x94l\x00\x00\x00\x007\x06\xe3\xfc\x00\x00\x00\x008\x1b\xb0\xec\x00\x00\x00\x008\xe6\xc5\xfc\x00" + + "\x00\x00\x009\xfb\x92\xec\x00\x00\x00\x00:Ƨ\xfc\x00\x00\x00\x00;\xdbt\xec\x00\x00\x00\x00<\xaf\xc4|\x00\x00\x00\x00=\xbbV\xec\x00\x00\x00\x00>\x8f\xa6|\x00\x00\x00\x00?\x9b8\xec\x00\x00\x00\x00@" + + "o\x88|\x00\x00\x00\x00A\x84Ul\x00\x00\x00\x00BOj|\x00\x00\x00\x00Cd7l\x00\x00\x00\x00D/L|\x00\x00\x00\x00ED\x19l\x00\x00\x00\x00E\xf3~\xfc\x00\x00\x00\x00G-5\xec\x00" + + "\x00\x00\x00G\xd3`\xfc\x00\x00\x00\x00I\r\x17\xec\x00\x00\x00\x00I\xb3B\xfc\x00\x00\x00\x00J\xec\xf9\xec\x00\x00\x00\x00K\x9c_|\x00\x00\x00\x00L\xd6\x16l\x00\x00\x00\x00M|A|\x00\x00\x00\x00N" + + "\xb6\x14P\x01\x02\x01\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x06\x05\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03" + + "\x04\x03\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\t\b\a\b\a\b\a\b\a\b\a\b\a" + + "\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\xff\xff\xc7\\\x00\x00\xff\xffΔ\x00\x04\xff\xffܤ\x01\b\xff\xff\xce\xc8\x00\x04\xff" + + "\xff\xdc\xd8\x01\b\xff\xff\xdc\xd8\x01\f\xff\xff\xdc\xd8\x01\x10\xff\xff\xd5\xd0\x01\x14\xff\xff\xc7\xc0\x00\x18\xff\xff\xe3\xe0\x01\x1cLMT\x00NST\x00NDT\x00NPT\x00NWT\x00ADT\x00A" + + "ST\x00ADDT\x00\nAST4ADT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xdf\xe5\x8d\xc4\xda\x04\x00\x00\xda\x04\x00\x00\x12\x00" + + "\x1c\x00America/LouisvilleUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00u\x00\x00\x00\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1" + + "\x9a\xdbp\xff\xff\xff\xff\xa4s\xf7\x00\xff\xff\xff\xff\xa5\x16\x11p\xff\xff\xff\xff\xca\rN\x80\xff\xff\xff\xff\xca\xd8Gp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff" + + "\xff\xff\xff\xd3u\xd7\x1c\xff\xff\xff\xffӤ\tp\xff\xff\xff\xff\xda\xfe\xb5\x80\xff\xff\xff\xff\xdb\xc0s\xf0\xff\xff\xff\xff\xdcޗ\x80\xff\xff\xff\xffݩ\x90p\xff\xff\xff\xff\u07bey\x80\xff\xff\xff\xff\xdf" + + "\x89rp\xff\xff\xff\xff\xe0\x9e[\x80\xff\xff\xff\xff\xe1iTp\xff\xff\xff\xff\xe2~=\x80\xff\xff\xff\xff\xe3I6p\xff\xff\xff\xff\xe4^\x1f\x80\xff\xff\xff\xff\xe5)\x18p\xff\xff\xff\xff\xe6G<\x00\xff" + + "\xff\xff\xff\xe77\x1e\xf0\xff\xff\xff\xff\xe8'\x1e\x00\xff\xff\xff\xff\xe9\x17\x00\xf0\xff\xff\xff\xff\xea\a\x00\x00\xff\xff\xff\xff\xea\xf6\xe2\xf0\xff\xff\xff\xff\xeb\xe6\xe2\x00\xff\xff\xff\xff\xec\xd6\xc4\xf0\xff\xff\xff\xff\xed" + + "\xc6\xc4\x00\xff\xff\xff\xff\xee\xbf\xe1p\xff\xff\xff\xff\xef\xaf\xe0\x80\xff\xff\xff\xff\xf0\x1e\x90p\xff\xff\xff\xff\xfc\xd8:\xf0\xff\xff\xff\xff\xfd\xc8\x1d\xe0\xff\xff\xff\xff\xfe\xb8\x1c\xf0\xff\xff\xff\xff\xff\xa7\xff\xe0\x00" + + "\x00\x00\x00\x00\x97\xfe\xf0\x00\x00\x00\x00\x01\x87\xe1\xe0\x00\x00\x00\x00\x02w\xe0\xf0\x00\x00\x00\x00\x03p\xfe`\x00\x00\x00\x00\x04`\xfdp\x00\x00\x00\x00\x05P\xe0`\x00\x00\x00\x00\x06@\xdfp\x00\x00\x00\x00\a" + + "0\xc2`\x00\x00\x00\x00\a\x8d\x19p\x00\x00\x00\x00\t\x10\xb2p\x00\x00\x00\x00\t\xad\x94\xf0\x00\x00\x00\x00\n\xf0\x86`\x00\x00\x00\x00\v\xe0\x85p\x00\x00\x00\x00\f٢\xe0\x00\x00\x00\x00\r\xc0gp\x00" + + "\x00\x00\x00\x0e\xb9\x84\xe0\x00\x00\x00\x00\x0f\xa9\x83\xf0\x00\x00\x00\x00\x10\x99f\xe0\x00\x00\x00\x00\x11\x89e\xf0\x00\x00\x00\x00\x12yH\xe0\x00\x00\x00\x00\x13iG\xf0\x00\x00\x00\x00\x14Y*\xe0\x00\x00\x00\x00\x15" + + "I)\xf0\x00\x00\x00\x00\x169\f\xe0\x00\x00\x00\x00\x17)\v\xf0\x00\x00\x00\x00\x18\")`\x00\x00\x00\x00\x19\b\xed\xf0\x00\x00\x00\x00\x1a\x02\v`\x00\x00\x00\x00\x1a\xf2\np\x00\x00\x00\x00\x1b\xe1\xed`\x00" + + "\x00\x00\x00\x1c\xd1\xecp\x00\x00\x00\x00\x1d\xc1\xcf`\x00\x00\x00\x00\x1e\xb1\xcep\x00\x00\x00\x00\x1f\xa1\xb1`\x00\x00\x00\x00 v\x00\xf0\x00\x00\x00\x00!\x81\x93`\x00\x00\x00\x00\"U\xe2\xf0\x00\x00\x00\x00#" + + "j\xaf\xe0\x00\x00\x00\x00$5\xc4\xf0\x00\x00\x00\x00%J\x91\xe0\x00\x00\x00\x00&\x15\xa6\xf0\x00\x00\x00\x00'*s\xe0\x00\x00\x00\x00'\xfe\xc3p\x00\x00\x00\x00)\nU\xe0\x00\x00\x00\x00)ޥp\x00" + + "\x00\x00\x00*\xea7\xe0\x00\x00\x00\x00+\xbe\x87p\x00\x00\x00\x00,\xd3T`\x00\x00\x00\x00-\x9eip\x00\x00\x00\x00.\xb36`\x00\x00\x00\x00/~Kp\x00\x00\x00\x000\x93\x18`\x00\x00\x00\x001" + + "gg\xf0\x00\x00\x00\x002r\xfa`\x00\x00\x00\x003GI\xf0\x00\x00\x00\x004R\xdc`\x00\x00\x00\x005'+\xf0\x00\x00\x00\x0062\xbe`\x00\x00\x00\x007\a\r\xf0\x00\x00\x00\x008\x1b\xda\xe0\x00" + + "\x00\x00\x008\xe6\xef\xf0\x00\x00\x00\x009\xfb\xbc\xe0\x00\x00\x00\x00:\xc6\xd1\xf0\x00\x00\x00\x00;۞\xe0\x00\x00\x00\x00<\xaf\xeep\x00\x00\x00\x00=\xbb\x80\xe0\x00\x00\x00\x00>\x8f\xd0p\x00\x00\x00\x00?" + + "\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x01\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06" + + "\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\xff\xff\xaf\x9a" + + "\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14\xff\xff\xc7\xc0\x01\x18LMT\x00CDT\x00CST\x00CWT\x00CPT\x00ES" + + "T\x00EDT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x1b\vKdC\x03\x00\x00C\x03\x00\x00\x13\x00\x1c\x00" + + "America/Rainy_RiverUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00J\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xffr\xee\x87(\xff\xff\xff\xff\x9e\xb8\xa1\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xc8\xf8W`\xff\xff\xff\xffˈ" + + "\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\x00\x00\x00\x00\b π\x00\x00\x00\x00\t\x10\xb2p\x00\x00\x00\x00\n\x00\xb1\x80\x00\x00\x00\x00\n\xf0\x94p\x00\x00\x00\x00\v\xe0\x93\x80\x00\x00" + "\x00\x00\fٰ\xf0\x00\x00\x00\x00\r\xc0u\x80\x00\x00\x00\x00\x0e\xb9\x92\xf0\x00\x00\x00\x00\x0f\xa9\x92\x00\x00\x00\x00\x00\x10\x99t\xf0\x00\x00\x00\x00\x11\x89t\x00\x00\x00\x00\x00\x12yV\xf0\x00\x00\x00\x00\x13i" + "V\x00\x00\x00\x00\x00\x14Y8\xf0\x00\x00\x00\x00\x15I8\x00\x00\x00\x00\x00\x169\x1a\xf0\x00\x00\x00\x00\x17)\x1a\x00\x00\x00\x00\x00\x18\"7p\x00\x00\x00\x00\x19\b\xfc\x00\x00\x00\x00\x00\x1a\x02\x19p\x00\x00" + "\x00\x00\x1a\xf2\x18\x80\x00\x00\x00\x00\x1b\xe1\xfbp\x00\x00\x00\x00\x1c\xd1\xfa\x80\x00\x00\x00\x00\x1d\xc1\xddp\x00\x00\x00\x00\x1e\xb1܀\x00\x00\x00\x00\x1f\xa1\xbfp\x00\x00\x00\x00 v\x0f\x00\x00\x00\x00\x00!\x81" + @@ -1923,1782 +2263,1477 @@ const zipdata = "PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00 "Y\x80\x00\x00\x00\x000\x93&p\x00\x00\x00\x001gv\x00\x00\x00\x00\x002s\bp\x00\x00\x00\x003GX\x00\x00\x00\x00\x004R\xeap\x00\x00\x00\x005':\x00\x00\x00\x00\x0062\xccp\x00\x00" + "\x00\x007\a\x1c\x00\x00\x00\x00\x008\x1b\xe8\xf0\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xca\xf0\x00\x00\x00\x00:\xc6\xe0\x00\x00\x00\x00\x00;۬\xf0\x00\x00\x00\x00<\xaf\xfc\x80\x00\x00\x00\x00=\xbb" + "\x8e\xf0\x00\x00\x00\x00>\x8fހ\x00\x00\x00\x00?\x9bp\xf0\x00\x00\x00\x00@o\xc0\x80\x00\x00\x00\x00A\x84\x8dp\x00\x00\x00\x00BO\xa2\x80\x00\x00\x00\x00Cdop\x00\x00\x00\x00D/\x84\x80\x00\x00" + - "\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7\x00\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x05\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xad\xdd\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f" + - "\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14LMT\x00CDT\x00CST\x00CWT\x00CPT\x00EST\x00\nCST6CDT,M3.2.0,M11.1.0\n" + - "PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RutZ\x1a\xb2\x02\x00\x00\xb2\x02\x00\x00\r\x00\x1c\x00America/JujuyUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00" + - "\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00" + - "\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00;\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffr\x9c\xae\xb8\xff\xff\xff\xff\xa2\x92" + - "\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff" + - "\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~" + - "\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff" + - "\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05" + - "l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff" + - "\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10" + - "\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'*W\xc0\x00\x00\x00\x00'\xe2۰\x00\x00\x00\x00(\xee\x8a@\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00" + - "\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x02\x03\x02\x04\x05\x04\x05\x03\x05\x04\x05\xff\xff\xc2\xc8\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01" + - "\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xd0v\x01\x8a\x01" + - "\x04\x00\x00\x01\x04\x00\x00\x0f\x00\x1c\x00America/TijuanaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00^\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff\xa5\xb6\xf6\x80\xff\xff\xff\xff\xa9yOp\xff\xff\xff\xff\xaf\xf2|\xf0\xff\xff\xff\xff\xb6fd" + - "p\xff\xff\xff\xff\xb7\x1b\x10\x00\xff\xff\xff\xff\xb8\n\xf2\xf0\xff\xff\xff\xff\xcbꍀ\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xffҙ\xbap\xff\xff\xff\xff\xd7\x1bY\x00\xff\xff\xff\xffؑ\xb4\xf0\xff\xff\xff" + - "\xff\xe2~K\x90\xff\xff\xff\xff\xe3IR\x90\xff\xff\xff\xff\xe4^-\x90\xff\xff\xff\xff\xe5)4\x90\xff\xff\xff\xff\xe6GJ\x10\xff\xff\xff\xff\xe7\x12Q\x10\xff\xff\xff\xff\xe8',\x10\xff\xff\xff\xff\xe8\xf23" + - "\x10\xff\xff\xff\xff\xea\a\x0e\x10\xff\xff\xff\xff\xea\xd2\x15\x10\xff\xff\xff\xff\xeb\xe6\xf0\x10\xff\xff\xff\xff\xec\xb1\xf7\x10\xff\xff\xff\xff\xed\xc6\xd2\x10\xff\xff\xff\xff\xee\x91\xd9\x10\x00\x00\x00\x00\v\u0be0\x00\x00\x00" + - "\x00\f\xd9\xcd\x10\x00\x00\x00\x00\r\xc0\x91\xa0\x00\x00\x00\x00\x0e\xb9\xaf\x10\x00\x00\x00\x00\x0f\xa9\xae \x00\x00\x00\x00\x10\x99\x91\x10\x00\x00\x00\x00\x11\x89\x90 \x00\x00\x00\x00\x12ys\x10\x00\x00\x00\x00\x13ir" + - " \x00\x00\x00\x00\x14YU\x10\x00\x00\x00\x00\x15IT \x00\x00\x00\x00\x1697\x10\x00\x00\x00\x00\x17)6 \x00\x00\x00\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18 \x00\x00\x00\x00\x1a\x025\x90\x00\x00\x00" + - "\x00\x1a\xf24\xa0\x00\x00\x00\x00\x1b\xe2\x17\x90\x00\x00\x00\x00\x1c\xd2\x16\xa0\x00\x00\x00\x00\x1d\xc1\xf9\x90\x00\x00\x00\x00\x1e\xb1\xf8\xa0\x00\x00\x00\x00\x1f\xa1ې\x00\x00\x00\x00 v+ \x00\x00\x00\x00!\x81\xbd" + - "\x90\x00\x00\x00\x00\"V\r \x00\x00\x00\x00#j\xda\x10\x00\x00\x00\x00$5\xef \x00\x00\x00\x00%J\xbc\x10\x00\x00\x00\x00&\x15\xd1 \x00\x00\x00\x00'*\x9e\x10\x00\x00\x00\x00'\xfe\xed\xa0\x00\x00\x00" + - "\x00)\n\x80\x10\x00\x00\x00\x00)\xdeϠ\x00\x00\x00\x00*\xeab\x10\x00\x00\x00\x00+\xbe\xb1\xa0\x00\x00\x00\x00,\xd3~\x90\x00\x00\x00\x00-\x9e\x93\xa0\x00\x00\x00\x00.\xb3`\x90\x00\x00\x00\x00/~u" + - "\xa0\x00\x00\x00\x000\x93B\x90\x00\x00\x00\x001g\x92 \x00\x00\x00\x002s$\x90\x00\x00\x00\x003Gt \x00\x00\x00\x004S\x06\x90\x00\x00\x00\x005'V \x00\x00\x00\x0062\xe8\x90\x00\x00\x00" + - "\x007\a8 \x00\x00\x00\x008\x1c\x05\x10\x00\x00\x00\x008\xe7\x1a \x00\x00\x00\x009\xfb\xe7\x10\x00\x00\x00\x00:\xc6\xfc \x00\x00\x00\x00;\xdb\xc9\x10\x00\x00\x00\x00<\xb0\x18\xa0\x00\x00\x00\x00=\xbb\xab" + - "\x10\x00\x00\x00\x00>\x8f\xfa\xa0\x00\x00\x00\x00?\x9b\x8d\x10\x00\x00\x00\x00@oܠ\x00\x00\x00\x00A\x84\xa9\x90\x00\x00\x00\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b\x90\x00\x00\x00\x00D/\xa0\xa0\x00\x00\x00" + - "\x00EDm\x90\x00\x00\x00\x00F\x0f\x82\xa0\x00\x00\x00\x00G$O\x90\x00\x00\x00\x00G\xf8\x9f \x00\x00\x00\x00I\x041\x90\x00\x00\x00\x00I\u0601 \x00\x00\x00\x00J\xe4\x13\x90\x00\x00\x00\x00K\x9c\xb3" + - "\xa0\x01\x02\x01\x02\x03\x02\x04\x05\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\xff\xff\x92L\x00\x00\xff\xff\x9d\x90\x00\x04\xff\xff\x8f\x80\x00\b\xff\xff\x9d\x90\x01\f\xff" + - "\xff\x9d\x90\x01\x10\xff\xff\x9d\x90\x01\x14LMT\x00MST\x00PST\x00PDT\x00PWT\x00PPT\x00\nPST8PDT,M3.2.0,M11.1.0\nP" + - "K\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R{\a\a\xdc\xca\x03\x00\x00\xca\x03\x00\x00\x10\x00\x1c\x00America/EdmontonUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux" + - "\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00" + - "\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Y\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\x88\xde\xce\xe0\xff\xff\xff\xff" + - "\x9e\xb8\xaf\x90\xff\xff\xff\xff\x9f\xbb\a\x80\xff\xff\xff\xff\xa0\x98\x91\x90\xff\xff\xff\xff\xa0҅\x80\xff\xff\xff\xff\xa2\x8a\xe8\x90\xff\xff\xff\xff\xa3\x84\x06\x00\xff\xff\xff\xff\xa4jʐ\xff\xff\xff\xff\xa55À" + - "\xff\xff\xff\xff\xa6S\xe7\x10\xff\xff\xff\xff\xa7\x15\xa5\x80\xff\xff\xff\xff\xa83\xc9\x10\xff\xff\xff\xff\xa8\xfe\xc2\x00\xff\xff\xff\xffˉ\f\x90\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff" + - "\xd5U\xe3\x10\xff\xff\xff\xff\xd6 \xdc\x00\x00\x00\x00\x00\x04a\x19\x90\x00\x00\x00\x00\x05P\xfc\x80\x00\x00\x00\x00\x06@\xfb\x90\x00\x00\x00\x00\a0ހ\x00\x00\x00\x00\b ݐ\x00\x00\x00\x00\t\x10\xc0\x80" + - "\x00\x00\x00\x00\n\x00\xbf\x90\x00\x00\x00\x00\n\xf0\xa2\x80\x00\x00\x00\x00\vࡐ\x00\x00\x00\x00\fٿ\x00\x00\x00\x00\x00\r\xc0\x83\x90\x00\x00\x00\x00\x0e\xb9\xa1\x00\x00\x00\x00\x00\x0f\xa9\xa0\x10\x00\x00\x00\x00" + - "\x10\x99\x83\x00\x00\x00\x00\x00\x11\x89\x82\x10\x00\x00\x00\x00\x12ye\x00\x00\x00\x00\x00\x13id\x10\x00\x00\x00\x00\x14YG\x00\x00\x00\x00\x00\x15IF\x10\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17)(\x10" + - "\x00\x00\x00\x00\x18\"E\x80\x00\x00\x00\x00\x19\t\n\x10\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2&\x90\x00\x00\x00\x00\x1b\xe2\t\x80\x00\x00\x00\x00\x1c\xd2\b\x90\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00" + - "\x1e\xb1\xea\x90\x00\x00\x00\x00\x1f\xa1̀\x00\x00\x00\x00 v\x1d\x10\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xff\x10\x00\x00\x00\x00#j\xcc\x00\x00\x00\x00\x00$5\xe1\x10\x00\x00\x00\x00%J\xae\x00" + - "\x00\x00\x00\x00&\x15\xc3\x10\x00\x00\x00\x00'*\x90\x00\x00\x00\x00\x00'\xfeߐ\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\xde\xc1\x90\x00\x00\x00\x00*\xeaT\x00\x00\x00\x00\x00+\xbe\xa3\x90\x00\x00\x00\x00" + - ",\xd3p\x80\x00\x00\x00\x00-\x9e\x85\x90\x00\x00\x00\x00.\xb3R\x80\x00\x00\x00\x00/~g\x90\x00\x00\x00\x000\x934\x80\x00\x00\x00\x001g\x84\x10\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003Gf\x10" + - "\x00\x00\x00\x004R\xf8\x80\x00\x00\x00\x005'H\x10\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe7\f\x10\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00" + - ":\xc6\xee\x10\x00\x00\x00\x00;ۻ\x00\x00\x00\x00\x00<\xb0\n\x90\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8f\xec\x90\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@oΐ\x00\x00\x00\x00A\x84\x9b\x80" + - "\x00\x00\x00\x00BO\xb0\x90\x00\x00\x00\x00Cd}\x80\x00\x00\x00\x00D/\x92\x90\x00\x00\x00\x00ED_\x80\x00\x00\x00\x00E\xf3\xc5\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\x95\xa0\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\f\xff\xff\xab\xa0\x01\x10LMT\x00MDT\x00MST\x00MWT\x00MPT\x00\n" + - "MST7MDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xb4\x82s\x1dT\x01\x00\x00T\x01\x00\x00\x11\x00\x1c\x00America" + - "/ChihuahuaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x13\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\xa5\xb6\xe8p\xff\xff\xff\xff\xaf\xf2n\xe0\xff\xff\xff\xff\xb6fV`\xff\xff\xff\xff\xb7C\xd2`\xff\xff\xff\xff\xb8\f6`\xff\xff\xff\xff\xb8\xfd\x86" + - "\xf0\x00\x00\x00\x001gv\x00\x00\x00\x00\x002s\bp\x00\x00\x00\x003GX\x00\x00\x00\x00\x004R\xeap\x00\x00\x00\x005'H\x10\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00" + - "\x008\x1b\xf7\x00\x00\x00\x00\x008\xe7\f\x10\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xf5\x12\x90\x00\x00\x00\x00;\xb6\xd1\x00\x00\x00\x00\x00<\xb0\n\x90\x01\x02\x01\x02\x01\x02\x03\x02\x03\x02\x04\x01\x04\x01\x04" + - "\x01\x04\x01\x04\xff\xff\x9c\x8c\x00\x00\xff\xff\x9d\x90\x00\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xab\xa0\x01\x10LMT\x00MST\x00CST\x00CDT\x00MDT\x00\nMST7M" + - "DT,M4.1.0,M10.5.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x1d`̟\x00\x03\x00\x00\x00\x03\x00\x00\x15\x00\x1c\x00America/Camb" + - "ridge_BayUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00>\x00\x00\x00\t\x00\x00\x00%\xff\xff\xff\xff\xa1\xf2̀\xff\xff\xff\xffˉ\f\x90\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff\xf7/Zp\xff\xff\xff\xff\xf8(\x85\xf0" + - "\x00\x00\x00\x00\x13id\x10\x00\x00\x00\x00\x14YG\x00\x00\x00\x00\x00\x15IF\x10\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17)(\x10\x00\x00\x00\x00\x18\"E\x80\x00\x00\x00\x00\x19\t\n\x10\x00\x00\x00\x00" + - "\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2&\x90\x00\x00\x00\x00\x1b\xe2\t\x80\x00\x00\x00\x00\x1c\xd2\b\x90\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1\xea\x90\x00\x00\x00\x00\x1f\xa1̀\x00\x00\x00\x00 v\x1d\x10" + - "\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xff\x10\x00\x00\x00\x00#j\xcc\x00\x00\x00\x00\x00$5\xe1\x10\x00\x00\x00\x00%J\xae\x00\x00\x00\x00\x00&\x15\xc3\x10\x00\x00\x00\x00'*\x90\x00\x00\x00\x00\x00" + - "'\xfeߐ\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\xde\xc1\x90\x00\x00\x00\x00*\xeaT\x00\x00\x00\x00\x00+\xbe\xa3\x90\x00\x00\x00\x00,\xd3p\x80\x00\x00\x00\x00-\x9e\x85\x90\x00\x00\x00\x00.\xb3R\x80" + - "\x00\x00\x00\x00/~g\x90\x00\x00\x00\x000\x934\x80\x00\x00\x00\x001g\x84\x10\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003Gf\x10\x00\x00\x00\x004R\xf8\x80\x00\x00\x00\x005'H\x10\x00\x00\x00\x00" + - "62ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xca\xf0\x00\x00\x00\x00:\x04\xe9P\x00\x00\x00\x00:\xc6\xee\x10\x00\x00\x00\x00;ۻ\x00" + - "\x00\x00\x00\x00<\xb0\n\x90\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8f\xec\x90\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@oΐ\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00BO\xb0\x90\x00\x00\x00\x00" + - "Cd}\x80\x00\x00\x00\x00D/\x92\x90\x00\x00\x00\x00ED_\x80\x00\x00\x00\x00E\xf3\xc5\x10\x03\x01\x02\x03\x04\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03" + - "\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\a\x06\b\a\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x00\x00\x00\x00\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\xab\xa0\x01\b\xff\xff\x9d\x90\x00\f\xff\xff\xb9\xb0\x01\x10" + - "\xff\xff\xab\xa0\x01\x15\xff\xff\xb9\xb0\x01\x19\xff\xff\xab\xa0\x00\x1d\xff\xff\xb9\xb0\x00!-00\x00MWT\x00MPT\x00MST\x00MDDT\x00MDT\x00CDT\x00CST\x00EST" + - "\x00\nMST7MDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xc1Ȇ\x90\x05\x04\x00\x00\x05\x04\x00\x00\x12\x00\x1c\x00Ameri" + - "ca/WhitehorseUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00]\x00\x00\x00\t\x00\x00\x00%\xff\xff\xff\xff}\x86\x8a\x9c\xff\xff\xff\xff\x9e\xb8˰\xff\xff\xff\xff\x9f\xbb#\xa0\xff\xff\xff\xff\xa0\xd0\f\xb0\xff\xff\xff\xff\xa1\xa2Ҁ\xff\xff\xff\xff" + - "ˉ(\xb0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a4 \xff\xff\xff\xff\xf7/v\x90\xff\xff\xff\xff\xf8(\xa2\x10\xff\xff\xff\xff\xfb\x1d_\x10\x00\x00\x00\x00\x13ir \x00\x00\x00\x00\x14YU\x10" + - "\x00\x00\x00\x00\x15IT \x00\x00\x00\x00\x1697\x10\x00\x00\x00\x00\x17)6 \x00\x00\x00\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18 \x00\x00\x00\x00\x1a\x025\x90\x00\x00\x00\x00\x1a\xf24\xa0\x00\x00\x00\x00" + - "\x1b\xe2\x17\x90\x00\x00\x00\x00\x1c\xd2\x16\xa0\x00\x00\x00\x00\x1d\xc1\xf9\x90\x00\x00\x00\x00\x1e\xb1\xf8\xa0\x00\x00\x00\x00\x1f\xa1ې\x00\x00\x00\x00 v+ \x00\x00\x00\x00!\x81\xbd\x90\x00\x00\x00\x00\"V\r " + - "\x00\x00\x00\x00#j\xda\x10\x00\x00\x00\x00$5\xef \x00\x00\x00\x00%J\xbc\x10\x00\x00\x00\x00&\x15\xd1 \x00\x00\x00\x00'*\x9e\x10\x00\x00\x00\x00'\xfe\xed\xa0\x00\x00\x00\x00)\n\x80\x10\x00\x00\x00\x00" + - ")\xdeϠ\x00\x00\x00\x00*\xeab\x10\x00\x00\x00\x00+\xbe\xb1\xa0\x00\x00\x00\x00,\xd3~\x90\x00\x00\x00\x00-\x9e\x93\xa0\x00\x00\x00\x00.\xb3`\x90\x00\x00\x00\x00/~u\xa0\x00\x00\x00\x000\x93B\x90" + - "\x00\x00\x00\x001g\x92 \x00\x00\x00\x002s$\x90\x00\x00\x00\x003Gt \x00\x00\x00\x004S\x06\x90\x00\x00\x00\x005'V \x00\x00\x00\x0062\xe8\x90\x00\x00\x00\x007\a8 \x00\x00\x00\x00" + - "8\x1c\x05\x10\x00\x00\x00\x008\xe7\x1a \x00\x00\x00\x009\xfb\xe7\x10\x00\x00\x00\x00:\xc6\xfc \x00\x00\x00\x00;\xdb\xc9\x10\x00\x00\x00\x00<\xb0\x18\xa0\x00\x00\x00\x00=\xbb\xab\x10\x00\x00\x00\x00>\x8f\xfa\xa0" + - "\x00\x00\x00\x00?\x9b\x8d\x10\x00\x00\x00\x00@oܠ\x00\x00\x00\x00A\x84\xa9\x90\x00\x00\x00\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b\x90\x00\x00\x00\x00D/\xa0\xa0\x00\x00\x00\x00EDm\x90\x00\x00\x00\x00" + - "E\xf3\xd3 \x00\x00\x00\x00G-\x8a\x10\x00\x00\x00\x00Gӵ \x00\x00\x00\x00I\rl\x10\x00\x00\x00\x00I\xb3\x97 \x00\x00\x00\x00J\xedN\x10\x00\x00\x00\x00K\x9c\xb3\xa0\x00\x00\x00\x00L\xd6j\x90" + - "\x00\x00\x00\x00M|\x95\xa0\x00\x00\x00\x00N\xb6L\x90\x00\x00\x00\x00O\\w\xa0\x00\x00\x00\x00P\x96.\x90\x00\x00\x00\x00Q\x8f\xfa\xa0\x00\x00\x00\x00?\x9b\x8d\x10\x00\x00\x00\x00@oܠ\x00\x00\x00\x00A\x84\xa9\x90\x00\x00" + - "\x00\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b\x90\x00\x00\x00\x00D/\xa0\xa0\x00\x00\x00\x00EDm\x90\x00\x00\x00\x00E\xf3\xd3 \x00\x00\x00\x00G-\x8a\x10\x00\x00\x00\x00Gӵ \x00\x00\x00\x00I\r" + - "l\x10\x00\x00\x00\x00I\xb3\x97 \x00\x00\x00\x00J\xedN\x10\x00\x00\x00\x00K\x9c\xb3\xa0\x00\x00\x00\x00L\xd6j\x90\x00\x00\x00\x00M|\x95\xa0\x00\x00\x00\x00N\xb6L\x90\x00\x00\x00\x00O\\w\xa0\x00\x00" + - "\x00\x00P\x96.\x90\x00\x00\x00\x00Q\x90\x16\xc0\x00\x00\x00\x00?\x9b\xa90\x00\x00\x00\x00@o\xf8\xc0\x00\x00\x00\x00A\x84Ű\x00\x00\x00\x00BO\xda\xc0\x00\x00\x00\x00Cd\xa7\xb0\x00\x00\x00\x00D/\xbc\xc0\x00\x00\x00\x00" + - "ED\x89\xb0\x00\x00\x00\x00E\xf3\xef@\x01\x02\x03\x04\x02\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\a\t\b\t\b\t\b\t\b\t\b\t\b" + - "\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\x00\x00\xab\xe2\x00\x00\xff\xffZb\x00\x00\xff\xffeP\x00\x04\xff\xffs`\x01\b" + - "\xff\xffs`\x01\f\xff\xffeP\x00\x10\xff\xffs`\x01\x14\xff\xffs`\x00\x18\xff\xff\x81p\x01\x1d\xff\xffs`\x00\x19LMT\x00NST\x00NWT\x00NPT\x00BST\x00BDT\x00" + - "AHST\x00HDT\x00\nHST10HDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Ra\xcb'\xe9\x9c\x01\x00\x00\x9c\x01\x00\x00" + - "\x0e\x00\x1c\x00America/ManausUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96\xaa\u007fD\xff\xff\xff\xff\xb8\x0fW\xf0\xff\xff\xff\xff\xb8\xfdN\xb0\xff\xff\xff\xff\xb9\xf1B@\xff\xff\xff\xff\xbaނ" + - "0\xff\xff\xff\xff\xda8\xbc@\xff\xff\xff\xff\xda\xec\b@\xff\xff\xff\xff\xdc\x19\xef\xc0\xff\xff\xff\xffܹg0\xff\xff\xff\xff\xdd\xfb#@\xff\xff\xff\xffޛ\xec0\xff\xff\xff\xff\xdfݨ@\xff\xff\xff" + - "\xff\xe0TA0\xff\xff\xff\xff\xf4\x98\r\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf6\xc0r@\xff\xff\xff\xff\xf7\x0e,\xb0\xff\xff\xff\xff\xf8Q:@\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xfa\n\xe0" + - "\xc0\xff\xff\xff\xff\xfa\xa9\x06\xb0\xff\xff\xff\xff\xfb\xec\x14@\xff\xff\xff\xff\xfc\x8b\x8b\xb0\x00\x00\x00\x00\x1dɜ@\x00\x00\x00\x00\x1ex\xe5\xb0\x00\x00\x00\x00\x1f\xa0C\xc0\x00\x00\x00\x00 3ݰ\x00\x00\x00" + - "\x00!\x81w@\x00\x00\x00\x00\"\vְ\x00\x00\x00\x00,\xc0\xc3@\x00\x00\x00\x00-f\xd20\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\xff\xffǼ\x00\x00\xff\xff\xd5\xd0\x01\x04\xff\xff\xc7\xc0\x00\bLMT\x00-03\x00-04\x00\n<-04>4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xf1\xf9\x1dɻ\x00\x00\x00" + - "\xbb\x00\x00\x00\x12\x00\x1c\x00America/ParamariboUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x12\xff\xff\xff\xff\x91\x05\x8e\xb8\xff\xff\xff\xff\xbe*K\xc4\xff\xff\xff\xff\xd2b,\xb4\x00\x00\x00\x00\x1b\xbe1" + - "\xb8\x01\x02\x03\x04\xff\xff\xccH\x00\x00\xff\xff\xcc<\x00\x04\xff\xff\xccL\x00\x04\xff\xff\xce\xc8\x00\b\xff\xff\xd5\xd0\x00\x0eLMT\x00PMT\x00-0330\x00-03\x00\n<-03>3" + - "\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xfe7\xa1\x87\x1b\x01\x00\x00\x1b\x01\x00\x00\f\x00\x1c\x00America/LimaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00" + - "\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00" + - "\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x04\x00\x00\x00\f\xff\xff\xff\xffi\x87#\xbc\xff\xff\xff\xff\x8ct" + - "@\xd4\xff\xff\xff\xff\xc3\xcfJP\xff\xff\xff\xff\xc4E\xe3@\xff\xff\xff\xff\xc5/J\xd0\xff\xff\xff\xff\xc6\x1f-\xc0\xff\xff\xff\xff\xc7\x0f,\xd0\xff\xff\xff\xff\xc7\xff\x0f\xc0\x00\x00\x00\x00\x1e\x18\xc4P\x00\x00" + - "\x00\x00\x1e\x8f]@\x00\x00\x00\x00\x1f\xf9\xf7\xd0\x00\x00\x00\x00 p\x90\xc0\x00\x00\x00\x00%\x9e\xe3\xd0\x00\x00\x00\x00&\x15|\xc0\x00\x00\x00\x00-%\x03P\x00\x00\x00\x00-\x9b\x9c@\x01\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\xff\xff\xb7\xc4\x00\x00\xff\xff\xb7\xac\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff\xb9\xb0\x00\bLMT\x00-04\x00-05\x00\n<-05>5\nPK\x03\x04\n\x00" + - "\x00\x00\x00\x00\xf1c9Rd\xa9y\x9at\x03\x00\x00t\x03\x00\x00\x10\x00\x1c\x00America/AsuncionUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8" + - "\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00T" + - "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00O\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xffi\x87\x11\x90\xff\xff\xff\xff\xb8\x17\xf5\x90\x00" + - "\x00\x00\x00\x05+\xda@\x00\x00\x00\x00\a\xfc\xf0\xb0\x00\x00\x00\x00\n\xcft\xc0\x00\x00\x00\x00\v\x97ʰ\x00\x00\x00\x00\f\xb1\xf9\xc0\x00\x00\x00\x00\rx\xfe0\x00\x00\x00\x00\x0e\x93-@\x00\x00\x00\x00\x0f" + - "Z1\xb0\x00\x00\x00\x00\x10t`\xc0\x00\x00\x00\x00\x11dC\xb0\x00\x00\x00\x00\x12U\x94@\x00\x00\x00\x00\x13FȰ\x00\x00\x00\x00\x148\x19@\x00\x00\x00\x00\x15'\xfc0\x00\x00\x00\x00\x16\x19L\xc0\x00" + - "\x00\x00\x00\x17\t/\xb0\x00\x00\x00\x00\x17\xfa\x80@\x00\x00\x00\x00\x18\xeac0\x00\x00\x00\x00\x19۳\xc0\x00\x00\x00\x00\x1a\xcc\xe80\x00\x00\x00\x00\x1b\xbe8\xc0\x00\x00\x00\x00\x1c\xae\x1b\xb0\x00\x00\x00\x00\x1d" + - "\x9fl@\x00\x00\x00\x00\x1e\x8fO0\x00\x00\x00\x00\x1f\x80\x9f\xc0\x00\x00\x00\x00 p\x82\xb0\x00\x00\x00\x00!a\xd3@\x00\x00\x00\x00\"S\a\xb0\x00\x00\x00\x00#DX@\x00\x00\x00\x00$4;0\x00" + - "\x00\x00\x00%A;@\x00\x00\x00\x00&\x15n\xb0\x00\x00\x00\x00'\x06\xbf@\x00\x00\x00\x00'\xf6\xa20\x00\x00\x00\x00(\xee\x8a@\x00\x00\x00\x00)\xb0H\xb0\x00\x00\x00\x00*Ͻ\xc0\x00\x00\x00\x00+" + - "\xb9\t0\x00\x00\x00\x00,\xab\xab@\x00\x00\x00\x00-p\f\xb0\x00\x00\x00\x00.\x8c\xde\xc0\x00\x00\x00\x00/O\xee\xb0\x00\x00\x00\x000n\x12@\x00\x00\x00\x0016h0\x00\x00\x00\x002W.\xc0\x00" + - "\x00\x00\x003\x0f\xb2\xb0\x00\x00\x00\x0047\x10\xc0\x00\x00\x00\x004\xf8\xcf0\x00\x00\x00\x006\x16\xf2\xc0\x00\x00\x00\x006\xe1\xeb\xb0\x00\x00\x00\x007\xf6\xd4\xc0\x00\x00\x00\x008\xc1Ͱ\x00\x00\x00\x009" + - "ֶ\xc0\x00\x00\x00\x00:\xa1\xaf\xb0\x00\x00\x00\x00;\xbf\xd3@\x00\x00\x00\x00<\xaf\xb60\x00\x00\x00\x00=q\x90\xc0\x00\x00\x00\x00>\x8f\x980\x00\x00\x00\x00?Z\xad@\x00\x00\x00\x00@oz0\x00" + - "\x00\x00\x00Aq\xee@\x00\x00\x00\x00B3\xac\xb0\x00\x00\x00\x00CQ\xd0@\x00\x00\x00\x00D\x13\x8e\xb0\x00\x00\x00\x00E1\xb2@\x00\x00\x00\x00E\xf3p\xb0\x00\x00\x00\x00G\x1a\xce\xc0\x00\x00\x00\x00G" + - "\xd3R\xb0\x00\x00\x00\x00H\xfa\xb0\xc0\x00\x00\x00\x00I\xb34\xb0\x00\x00\x00\x00Jڒ\xc0\x00\x00\x00\x00K\xc1;0\x00\x00\x00\x00L\xa7\xff\xc0\x00\x00\x00\x00M\xa1\x1d0\x00\x00\x00\x00N\x87\xe1\xc0\x00" + - "\x00\x00\x00O\x80\xff0\x00\x00\x00\x00Pp\xfe@\x01\x02\x03\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04" + - "\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\xff\xff\xc9\xf0\x00\x00\xff\xff\xc9\xf0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x00\f\xff\xff" + - "\xd5\xd0\x01\fLMT\x00AMT\x00-04\x00-03\x00\n<-04>4<-03>,M10.1.0/0,M3.4.0/0\nPK\x03\x04\n\x00\x00\x00" + - "\x00\x00\xf1c9R\x9bܩ=\xda\x06\x00\x00\xda\x06\x00\x00\x0f\x00\x1c\x00America/ChicagoUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00" + - "\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif" + - "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaf\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff" + - "\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xff\xa2\xcbt\x00\xff\xff\xff\xff\xa3\x83\xf7\xf0\xff\xff\xff\xff\xa4EҀ\xff\xff\xff\xff\xa5c\xd9\xf0\xff\xff\xff\xff\xa6S\xd9\x00" + - "\xff\xff\xff\xff\xa7\x15\x97p\xff\xff\xff\xff\xa83\xbb\x00\xff\xff\xff\xff\xa8\xfe\xb3\xf0\xff\xff\xff\xff\xaa\x13\x9d\x00\xff\xff\xff\xff\xaaޕ\xf0\xff\xff\xff\xff\xab\xf3\u007f\x00\xff\xff\xff\xff\xac\xbew\xf0\xff\xff\xff\xff" + - "\xad\xd3a\x00\xff\xff\xff\xff\xae\x9eY\xf0\xff\xff\xff\xff\xaf\xb3C\x00\xff\xff\xff\xff\xb0~;\xf0\xff\xff\xff\xff\xb1\x9c_\x80\xff\xff\xff\xff\xb2gXp\xff\xff\xff\xff\xb3|A\x80\xff\xff\xff\xff\xb4G:p" + - "\xff\xff\xff\xff\xb5\\#\x80\xff\xff\xff\xff\xb6'\x1cp\xff\xff\xff\xff\xb7<\x05\x80\xff\xff\xff\xff\xb8\x06\xfep\xff\xff\xff\xff\xb9\x1b\xe7\x80\xff\xff\xff\xff\xb9\xe6\xe0p\xff\xff\xff\xff\xbb\x05\x04\x00\xff\xff\xff\xff" + - "\xbb\xc6\xc2p\xff\xff\xff\xff\xbc\xe4\xe6\x00\xff\xff\xff\xff\xbd\xaf\xde\xf0\xff\xff\xff\xff\xbe\xc4\xc8\x00\xff\xff\xff\xff\xbf\x8f\xc0\xf0\xff\xff\xff\xff\xc0Z\xd6\x00\xff\xff\xff\xff\xc1\xb0\x8fހ\x00\x00\x00\x00" + - "?\x9bp\xf0\x00\x00\x00\x00@o\xc0\x80\x00\x00\x00\x00A\x84\x8dp\x00\x00\x00\x00BO\xa2\x80\x00\x00\x00\x00Cdop\x00\x00\x00\x00D/\x84\x80\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7\x00" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x04\x05\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xad\xd4\x00" + - "\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x00\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x01\x14LMT\x00CDT\x00CST\x00EST\x00CWT\x00CPT\x00\nCST6" + - "CDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RMv\xa1\x0f%\x01\x00\x00%\x01\x00\x00\x11\x00\x1c\x00America/Mon" + - "terreyUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x10\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\xa5\xb6\xda`\x00\x00\x00\x00\"U\xf1\x00\x00\x00\x00\x00#j\xbd\xf0\x00\x00\x00\x001gv\x00\x00\x00\x00\x002s\bp\x00\x00\x00\x003GX\x00\x00\x00\x00" + - "\x004R\xeap\x00\x00\x00\x005':\x00\x00\x00\x00\x0062\xccp\x00\x00\x00\x007\a\x1c\x00\x00\x00\x00\x008\x1b\xe8\xf0\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xca\xf0\x00\x00\x00\x00:\xf5\x04" + - "\x80\x00\x00\x00\x00;\xb6\xc2\xf0\x00\x00\x00\x00<\xaf\xfc\x80\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xff\xa1\xf4\x00\x00\xff\xff\xab\xa0\x00\x04\xff\xff\xb9\xb0\x01\bLMT\x00CST\x00C" + - "DT\x00\nCST6CDT,M4.1.0,M10.5.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x14\xc1r8\xe0\x00\x00\x00\xe0\x00\x00\x00\x15\x00\x1c\x00Ame" + - "rica/Coral_HarbourUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xffr\xee\x84d\xff\xff\xff\xff\x9e\xb8\xa1\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xc8\xf8W`\xff\xff\xff\xffˈ\xfe" + - "\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\x02\x01\x02\x01\x03\x04\x05\xff\xff\xaa\x1c\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14" + - "LMT\x00CDT\x00CST\x00CWT\x00CPT\x00EST\x00\nEST5\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R錴$q\x03\x00\x00q\x03\x00\x00\x13\x00\x1c\x00" + - "America/Thunder_BayUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00N\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xffr\xee\x82,\xff\xff\xff\xff\x8f${\xe0\xff\xff\xff\xffˈ\xf0p\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`" + - "\xfb\xe0\x00\x00\x00\x00\x00\x97\xfe\xf0\x00\x00\x00\x00\x01\x87\xe1\xe0\x00\x00\x00\x00\x02w\xe0\xf0\x00\x00\x00\x00\x03p\xfe`\x00\x00\x00\x00\x04`\xfdp\x00\x00\x00\x00\x05P\xe0`\x00\x00\x00\x00\b \xc1p\x00\x00" + - "\x00\x00\t\x10\xa4`\x00\x00\x00\x00\n\x00\xa3p\x00\x00\x00\x00\n\xf0\x86`\x00\x00\x00\x00\v\xe0\x85p\x00\x00\x00\x00\f٢\xe0\x00\x00\x00\x00\r\xc0gp\x00\x00\x00\x00\x0e\xb9\x84\xe0\x00\x00\x00\x00\x0f\xa9" + - "\x83\xf0\x00\x00\x00\x00\x10\x99f\xe0\x00\x00\x00\x00\x11\x89e\xf0\x00\x00\x00\x00\x12yH\xe0\x00\x00\x00\x00\x13iG\xf0\x00\x00\x00\x00\x14Y*\xe0\x00\x00\x00\x00\x15I)\xf0\x00\x00\x00\x00\x169\f\xe0\x00\x00" + - "\x00\x00\x17)\v\xf0\x00\x00\x00\x00\x18\")`\x00\x00\x00\x00\x19\b\xed\xf0\x00\x00\x00\x00\x1a\x02\v`\x00\x00\x00\x00\x1a\xf2\np\x00\x00\x00\x00\x1b\xe1\xed`\x00\x00\x00\x00\x1c\xd1\xecp\x00\x00\x00\x00\x1d\xc1" + - "\xcf`\x00\x00\x00\x00\x1e\xb1\xcep\x00\x00\x00\x00\x1f\xa1\xb1`\x00\x00\x00\x00 v\x00\xf0\x00\x00\x00\x00!\x81\x93`\x00\x00\x00\x00\"U\xe2\xf0\x00\x00\x00\x00#j\xaf\xe0\x00\x00\x00\x00$5\xc4\xf0\x00\x00" + - "\x00\x00%J\x91\xe0\x00\x00\x00\x00&\x15\xa6\xf0\x00\x00\x00\x00'*s\xe0\x00\x00\x00\x00'\xfe\xc3p\x00\x00\x00\x00)\nU\xe0\x00\x00\x00\x00)ޥp\x00\x00\x00\x00*\xea7\xe0\x00\x00\x00\x00+\xbe" + - "\x87p\x00\x00\x00\x00,\xd3T`\x00\x00\x00\x00-\x9eip\x00\x00\x00\x00.\xb36`\x00\x00\x00\x00/~Kp\x00\x00\x00\x000\x93\x18`\x00\x00\x00\x001gg\xf0\x00\x00\x00\x002r\xfa`\x00\x00" + - "\x00\x003GI\xf0\x00\x00\x00\x004R\xdc`\x00\x00\x00\x005'+\xf0\x00\x00\x00\x0062\xbe`\x00\x00\x00\x007\a\r\xf0\x00\x00\x00\x008\x1b\xda\xe0\x00\x00\x00\x008\xe6\xef\xf0\x00\x00\x00\x009\xfb" + - "\xbc\xe0\x00\x00\x00\x00:\xc6\xd1\xf0\x00\x00\x00\x00;۞\xe0\x00\x00\x00\x00<\xaf\xeep\x00\x00\x00\x00=\xbb\x80\xe0\x00\x00\x00\x00>\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00\x00" + - "\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x01\x02\x03\x04\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05" + - "\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05" + - "\x02\x05\x02\x05\xff\xff\xacT\x00\x00\xff\xff\xab\xa0\x00\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x01\f\xff\xff\xc7\xc0\x01\x10\xff\xff\xc7\xc0\x01\x14LMT\x00CST\x00EST\x00EWT\x00EPT\x00" + - "EDT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xd0v\x01\x8a\x01\x04\x00\x00\x01\x04\x00\x00\x10\x00\x1c\x00Am" + - "erica/EnsenadaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00^\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff\xa5\xb6\xf6\x80\xff\xff\xff\xff\xa9yOp\xff\xff\xff\xff\xaf\xf2|\xf0\xff\xff\xff\xff\xb6fdp\xff\xff\xff\xff\xb7\x1b\x10\x00\xff\xff\xff" + - "\xff\xb8\n\xf2\xf0\xff\xff\xff\xff\xcbꍀ\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xffҙ\xbap\xff\xff\xff\xff\xd7\x1bY\x00\xff\xff\xff\xffؑ\xb4\xf0\xff\xff\xff\xff\xe2~K\x90\xff\xff\xff\xff\xe3IR" + - "\x90\xff\xff\xff\xff\xe4^-\x90\xff\xff\xff\xff\xe5)4\x90\xff\xff\xff\xff\xe6GJ\x10\xff\xff\xff\xff\xe7\x12Q\x10\xff\xff\xff\xff\xe8',\x10\xff\xff\xff\xff\xe8\xf23\x10\xff\xff\xff\xff\xea\a\x0e\x10\xff\xff\xff" + - "\xff\xea\xd2\x15\x10\xff\xff\xff\xff\xeb\xe6\xf0\x10\xff\xff\xff\xff\xec\xb1\xf7\x10\xff\xff\xff\xff\xed\xc6\xd2\x10\xff\xff\xff\xff\xee\x91\xd9\x10\x00\x00\x00\x00\v\u0be0\x00\x00\x00\x00\f\xd9\xcd\x10\x00\x00\x00\x00\r\xc0\x91" + - "\xa0\x00\x00\x00\x00\x0e\xb9\xaf\x10\x00\x00\x00\x00\x0f\xa9\xae \x00\x00\x00\x00\x10\x99\x91\x10\x00\x00\x00\x00\x11\x89\x90 \x00\x00\x00\x00\x12ys\x10\x00\x00\x00\x00\x13ir \x00\x00\x00\x00\x14YU\x10\x00\x00\x00" + - "\x00\x15IT \x00\x00\x00\x00\x1697\x10\x00\x00\x00\x00\x17)6 \x00\x00\x00\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18 \x00\x00\x00\x00\x1a\x025\x90\x00\x00\x00\x00\x1a\xf24\xa0\x00\x00\x00\x00\x1b\xe2\x17" + - "\x90\x00\x00\x00\x00\x1c\xd2\x16\xa0\x00\x00\x00\x00\x1d\xc1\xf9\x90\x00\x00\x00\x00\x1e\xb1\xf8\xa0\x00\x00\x00\x00\x1f\xa1ې\x00\x00\x00\x00 v+ \x00\x00\x00\x00!\x81\xbd\x90\x00\x00\x00\x00\"V\r \x00\x00\x00" + - "\x00#j\xda\x10\x00\x00\x00\x00$5\xef \x00\x00\x00\x00%J\xbc\x10\x00\x00\x00\x00&\x15\xd1 \x00\x00\x00\x00'*\x9e\x10\x00\x00\x00\x00'\xfe\xed\xa0\x00\x00\x00\x00)\n\x80\x10\x00\x00\x00\x00)\xde\xcf" + - "\xa0\x00\x00\x00\x00*\xeab\x10\x00\x00\x00\x00+\xbe\xb1\xa0\x00\x00\x00\x00,\xd3~\x90\x00\x00\x00\x00-\x9e\x93\xa0\x00\x00\x00\x00.\xb3`\x90\x00\x00\x00\x00/~u\xa0\x00\x00\x00\x000\x93B\x90\x00\x00\x00" + - "\x001g\x92 \x00\x00\x00\x002s$\x90\x00\x00\x00\x003Gt \x00\x00\x00\x004S\x06\x90\x00\x00\x00\x005'V \x00\x00\x00\x0062\xe8\x90\x00\x00\x00\x007\a8 \x00\x00\x00\x008\x1c\x05" + - "\x10\x00\x00\x00\x008\xe7\x1a \x00\x00\x00\x009\xfb\xe7\x10\x00\x00\x00\x00:\xc6\xfc \x00\x00\x00\x00;\xdb\xc9\x10\x00\x00\x00\x00<\xb0\x18\xa0\x00\x00\x00\x00=\xbb\xab\x10\x00\x00\x00\x00>\x8f\xfa\xa0\x00\x00\x00" + - "\x00?\x9b\x8d\x10\x00\x00\x00\x00@oܠ\x00\x00\x00\x00A\x84\xa9\x90\x00\x00\x00\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b\x90\x00\x00\x00\x00D/\xa0\xa0\x00\x00\x00\x00EDm\x90\x00\x00\x00\x00F\x0f\x82" + - "\xa0\x00\x00\x00\x00G$O\x90\x00\x00\x00\x00G\xf8\x9f \x00\x00\x00\x00I\x041\x90\x00\x00\x00\x00I\u0601 \x00\x00\x00\x00J\xe4\x13\x90\x00\x00\x00\x00K\x9c\xb3\xa0\x01\x02\x01\x02\x03\x02\x04\x05\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\xff\xff\x92L\x00\x00\xff\xff\x9d\x90\x00\x04\xff\xff\x8f\x80\x00\b\xff\xff\x9d\x90\x01\f\xff\xff\x9d\x90\x01\x10\xff\xff\x9d\x90\x01\x14L" + - "MT\x00MST\x00PST\x00PDT\x00PWT\x00PPT\x00\nPST8PDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9" + - "ROKjǪ\x02\x00\x00\xaa\x02\x00\x00\r\x00\x1c\x00America/BahiaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZ" + + "\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7\x00\x02\x01\x02\x01\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xa7X\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10LM" + + "T\x00CDT\x00CST\x00CWT\x00CPT\x00\nCST6CDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xc0\x98\x00\b" + + "\xc9\x03\x00\x00\xc9\x03\x00\x00\x12\x00\x1c\x00America/MontevideoUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZ" + "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96\xaak\x1c\xff\xff\xff\xff\xb8\x0fI\xe0\xff\xff\xff\xff\xb8\xfd@\xa0\xff\xff\xff" + - "\xff\xb9\xf140\xff\xff\xff\xff\xba\xdet \xff\xff\xff\xff\xda8\xae0\xff\xff\xff\xff\xda\xeb\xfa0\xff\xff\xff\xff\xdc\x19\xe1\xb0\xff\xff\xff\xffܹY \xff\xff\xff\xff\xdd\xfb\x150\xff\xff\xff\xffޛ\xde" + - " \xff\xff\xff\xff\xdfݚ0\xff\xff\xff\xff\xe0T3 \xff\xff\xff\xff\xf4\x97\xff\xb0\xff\xff\xff\xff\xf5\x05^ \xff\xff\xff\xff\xf6\xc0d0\xff\xff\xff\xff\xf7\x0e\x1e\xa0\xff\xff\xff\xff\xf8Q,0\xff\xff\xff" + - "\xff\xf8\xc7\xc5 \xff\xff\xff\xff\xfa\nҰ\xff\xff\xff\xff\xfa\xa8\xf8\xa0\xff\xff\xff\xff\xfb\xec\x060\xff\xff\xff\xff\xfc\x8b}\xa0\x00\x00\x00\x00\x1dɎ0\x00\x00\x00\x00\x1exנ\x00\x00\x00\x00\x1f\xa05" + - "\xb0\x00\x00\x00\x00 3Ϡ\x00\x00\x00\x00!\x81i0\x00\x00\x00\x00\"\vȠ\x00\x00\x00\x00#X\x10\xb0\x00\x00\x00\x00#\xe2p \x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xd4\xc7 \x00\x00\x00" + - "\x00'!\x0f0\x00\x00\x00\x00'\xbd\xe3\xa0\x00\x00\x00\x00)\x00\xf10\x00\x00\x00\x00)\x94\x8b \x00\x00\x00\x00*\xea\r\xb0\x00\x00\x00\x00+k2\xa0\x00\x00\x00\x00,\xc0\xb50\x00\x00\x00\x00-f\xc4" + - " \x00\x00\x00\x00.\xa0\x970\x00\x00\x00\x00/F\xa6 \x00\x00\x00\x000\x80y0\x00\x00\x00\x001\x1dM\xa0\x00\x00\x00\x002W \xb0\x00\x00\x00\x003\x06j \x00\x00\x00\x0048T0\x00\x00\x00" + - "\x004\xf8\xc1 \x00\x00\x00\x006 \x1f0\x00\x00\x00\x006\xcfh\xa0\x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xb8\x85 \x00\x00\x00\x009\xdf\xe30\x00\x00\x00\x00:\x8f,\xa0\x00\x00\x00\x00;\xc8\xff" + - "\xb0\x00\x00\x00\x00N\xf0\xa0\x00\x00\x00\x00N\x9aH\xb0\x00\x00\x00\x00OI\x92 \x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xff\xdb\xe4\x00\x00\xff\xff\xe3\xe0\x01\x04\xff\xff\xd5\xd0\x00\b" + - "LMT\x00-02\x00-03\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rӿ\x92\xbc\xb5\x06\x00\x00\xb5\x06\x00\x00\x10\x00\x1c\x00America/Mo" + - "ntrealUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\xac\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xffr\xeex\xec\xff\xff\xff\xff\x9e\xb8\x93p\xff\xff\xff\xff\x9f\xba\xeb`\xff\xff\xff\xff\xa0\x87.\xc8\xff\xff\xff\xff\xa1\x9a\xb1@\xff\xff\xff\xff\xa2\x94\x06\xf0\xff\xff\xff" + - "\xff\xa3U\xa9@\xff\xff\xff\xff\xa4\x86]\xf0\xff\xff\xff\xff\xa5(x`\xff\xff\xff\xff\xa6f?\xf0\xff\xff\xff\xff\xa7\fN\xe0\xff\xff\xff\xff\xa8F!\xf0\xff\xff\xff\xff\xa8\xec0\xe0\xff\xff\xff\xff\xaa\x1c\xc9" + - "p\xff\xff\xff\xff\xaa\xd5M`\xff\xff\xff\xff\xab\xfc\xabp\xff\xff\xff\xff\xac\xb5/`\xff\xff\xff\xff\xad܍p\xff\xff\xff\xff\xae\x95\x11`\xff\xff\xff\xff\xaf\xbcop\xff\xff\xff\xff\xb0~-\xe0\xff\xff\xff" + - "\xff\xb1\x9cQp\xff\xff\xff\xff\xb2gJ`\xff\xff\xff\xff\xb3|3p\xff\xff\xff\xff\xb4G,`\xff\xff\xff\xff\xb5\\\x15p\xff\xff\xff\xff\xb6'\x0e`\xff\xff\xff\xff\xb7;\xf7p\xff\xff\xff\xff\xb8\x06\xf0" + - "`\xff\xff\xff\xff\xb9%\x13\xf0\xff\xff\xff\xff\xb9\xe6\xd2`\xff\xff\xff\xff\xbb\x04\xf5\xf0\xff\xff\xff\xff\xbb\xcf\xee\xe0\xff\xff\xff\xff\xbc\xe4\xd7\xf0\xff\xff\xff\xff\xbd\xaf\xd0\xe0\xff\xff\xff\xff\xbeĹ\xf0\xff\xff\xff" + - "\xff\xbf\x8f\xb2\xe0\xff\xff\xff\xff\xc0\xa4\x9b\xf0\xff\xff\xff\xff\xc1o\x94\xe0\xff\xff\xff\xff\u0084}\xf0\xff\xff\xff\xff\xc3Ov\xe0\xff\xff\xff\xff\xc4d_\xf0\xff\xff\xff\xff\xc5/X\xe0\xff\xff\xff\xff\xc6M|" + - "p\xff\xff\xff\xff\xc7\x0f:\xe0\xff\xff\xff\xff\xc8-^p\xff\xff\xff\xffˈ\xf0p\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xfb\xe0\xff\xff\xff\xff\xd3u\xe4\xf0\xff\xff\xff\xff\xd4@\xdd\xe0\xff\xff\xff" + - "\xff\xd5U\xaa\xd0\xff\xff\xff\xff\xd6 \xa3\xc0\xff\xff\xff\xff\xd75\x8c\xd0\xff\xff\xff\xff\xd8\x00\x85\xc0\xff\xff\xff\xff\xd9\x15n\xd0\xff\xff\xff\xff\xda3v@\xff\xff\xff\xff\xda\xfe\xa7p\xff\xff\xff\xff\xdc\x13t" + - "`\xff\xff\xff\xff\xdcމp\xff\xff\xff\xffݩ\x82`\xff\xff\xff\xff\u07bekp\xff\xff\xff\xff߉d`\xff\xff\xff\xff\xe0\x9eMp\xff\xff\xff\xff\xe1iF`\xff\xff\xff\xff\xe2~/p\xff\xff\xff" + - "\xff\xe3I(`\xff\xff\xff\xff\xe4^\x11p\xff\xff\xff\xff\xe5)\n`\xff\xff\xff\xff\xe6G-\xf0\xff\xff\xff\xff\xe7\x12&\xe0\xff\xff\xff\xff\xe8'\x0f\xf0\xff\xff\xff\xff\xe9\x16\xf2\xe0\xff\xff\xff\xff\xea\x06\xf1" + - "\xf0\xff\xff\xff\xff\xea\xf6\xd4\xe0\xff\xff\xff\xff\xeb\xe6\xd3\xf0\xff\xff\xff\xff\xecֶ\xe0\xff\xff\xff\xff\xedƵ\xf0\xff\xff\xff\xff\xee\xbf\xd3`\xff\xff\xff\xff\xef\xaf\xd2p\xff\xff\xff\xff\xf0\x9f\xb5`\xff\xff\xff" + - "\xff\xf1\x8f\xb4p\xff\xff\xff\xff\xf2\u007f\x97`\xff\xff\xff\xff\xf3o\x96p\xff\xff\xff\xff\xf4_y`\xff\xff\xff\xff\xf5Oxp\xff\xff\xff\xff\xf6?[`\xff\xff\xff\xff\xf7/Zp\xff\xff\xff\xff\xf8(w" + - "\xe0\xff\xff\xff\xff\xf9\x0f\x8f\xd0" + - "p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00" + - "\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x03\x04\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xb5" + - "\x94\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x01\f\xff\xff\xc7\xc0\x01\x10LMT\x00EDT\x00EST\x00EWT\x00EPT\x00\nEST5EDT,M3.2" + - ".0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R%J\xd5\xebS\x01\x00\x00S\x01\x00\x00\x0f\x00\x1c\x00America/JamaicaUT\t\x00" + - "\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16\x00\x00\x00\x04\x00\x00\x00\x10\xff" + - "\xff\xff\xffi\x87#~\xff\xff\xff\xff\x93\x0f\xb4\xfe\x00\x00\x00\x00\a\x8d\x19p\x00\x00\x00\x00\t\x10\xa4`\x00\x00\x00\x00\t\xad\x94\xf0\x00\x00\x00\x00\n\xf0\x86`\x00\x00\x00\x00\v\xe0\x85p\x00\x00\x00\x00\f" + - "٢\xe0\x00\x00\x00\x00\r\xc0gp\x00\x00\x00\x00\x0e\xb9\x84\xe0\x00\x00\x00\x00\x0f\xa9\x83\xf0\x00\x00\x00\x00\x10\x99f\xe0\x00\x00\x00\x00\x11\x89e\xf0\x00\x00\x00\x00\x12yH\xe0\x00\x00\x00\x00\x13iG\xf0\x00" + - "\x00\x00\x00\x14Y*\xe0\x00\x00\x00\x00\x15I)\xf0\x00\x00\x00\x00\x169\f\xe0\x00\x00\x00\x00\x17)\v\xf0\x00\x00\x00\x00\x18\")`\x00\x00\x00\x00\x19\b\xed\xf0\x00\x00\x00\x00\x1a\x02\v`\x01\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\xff\xff\xb8\x02\x00\x00\xff\xff\xb8\x02\x00\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x01\fLMT\x00KMT\x00EST\x00EDT\x00\nES" + - "T5\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R5\x11Q\x06\xd1\x03\x00\x00\xd1\x03\x00\x00\x11\x00\x1c\x00America/AnchorageUT\t\x00\x03\x15\xac\x0e`\x15" + - "\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00" + - "\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00T\x00\x00\x00\n\x00\x00\x00(\xff\xff\xff\xff?\xc2\xfd" + - "\xd1\xff\xff\xff\xff}\x87AH\xff\xff\xff\xffˉ6\xc0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2aB0\xff\xff\xff\xff\xfa\xd2G\xa0\xff\xff\xff\xff\xfe\xb8c@\xff\xff\xff\xff\xff\xa8F0\x00\x00\x00" + - "\x00\x00\x98E@\x00\x00\x00\x00\x01\x88(0\x00\x00\x00\x00\x02x'@\x00\x00\x00\x00\x03qD\xb0\x00\x00\x00\x00\x04aC\xc0\x00\x00\x00\x00\x05Q&\xb0\x00\x00\x00\x00\x06A%\xc0\x00\x00\x00\x00\a1\b" + - "\xb0\x00\x00\x00\x00\a\x8d_\xc0\x00\x00\x00\x00\t\x10\xea\xb0\x00\x00\x00\x00\t\xad\xdb@\x00\x00\x00\x00\n\xf0̰\x00\x00\x00\x00\v\xe0\xcb\xc0\x00\x00\x00\x00\f\xd9\xe90\x00\x00\x00\x00\r\xc0\xad\xc0\x00\x00\x00" + - "\x00\x0e\xb9\xcb0\x00\x00\x00\x00\x0f\xa9\xca@\x00\x00\x00\x00\x10\x99\xad0\x00\x00\x00\x00\x11\x89\xac@\x00\x00\x00\x00\x12y\x8f0\x00\x00\x00\x00\x13i\x8e@\x00\x00\x00\x00\x14Yq0\x00\x00\x00\x00\x15Ip" + - "@\x00\x00\x00\x00\x169S0\x00\x00\x00\x00\x17)R@\x00\x00\x00\x00\x18\"o\xb0\x00\x00\x00\x00\x19\t4@\x00\x00\x00\x00\x1a\x02Q\xb0\x00\x00\x00\x00\x1a+\x14\x10\x00\x00\x00\x00\x1a\xf2B\xb0\x00\x00\x00" + - "\x00\x1b\xe2%\xa0\x00\x00\x00\x00\x1c\xd2$\xb0\x00\x00\x00\x00\x1d\xc2\a\xa0\x00\x00\x00\x00\x1e\xb2\x06\xb0\x00\x00\x00\x00\x1f\xa1\xe9\xa0\x00\x00\x00\x00 v90\x00\x00\x00\x00!\x81ˠ\x00\x00\x00\x00\"V\x1b" + - "0\x00\x00\x00\x00#j\xe8 \x00\x00\x00\x00$5\xfd0\x00\x00\x00\x00%J\xca \x00\x00\x00\x00&\x15\xdf0\x00\x00\x00\x00'*\xac \x00\x00\x00\x00'\xfe\xfb\xb0\x00\x00\x00\x00)\n\x8e \x00\x00\x00" + - "\x00)\xdeݰ\x00\x00\x00\x00*\xeap \x00\x00\x00\x00+\xbe\xbf\xb0\x00\x00\x00\x00,ӌ\xa0\x00\x00\x00\x00-\x9e\xa1\xb0\x00\x00\x00\x00.\xb3n\xa0\x00\x00\x00\x00/~\x83\xb0\x00\x00\x00\x000\x93P" + - "\xa0\x00\x00\x00\x001g\xa00\x00\x00\x00\x002s2\xa0\x00\x00\x00\x003G\x820\x00\x00\x00\x004S\x14\xa0\x00\x00\x00\x005'd0\x00\x00\x00\x0062\xf6\xa0\x00\x00\x00\x007\aF0\x00\x00\x00" + - "\x008\x1c\x13 \x00\x00\x00\x008\xe7(0\x00\x00\x00\x009\xfb\xf5 \x00\x00\x00\x00:\xc7\n0\x00\x00\x00\x00;\xdb\xd7 \x00\x00\x00\x00<\xb0&\xb0\x00\x00\x00\x00=\xbb\xb9 \x00\x00\x00\x00>\x90\b" + - "\xb0\x00\x00\x00\x00?\x9b\x9b \x00\x00\x00\x00@o\xea\xb0\x00\x00\x00\x00A\x84\xb7\xa0\x00\x00\x00\x00BO̰\x00\x00\x00\x00Cd\x99\xa0\x00\x00\x00\x00D/\xae\xb0\x00\x00\x00\x00ED{\xa0\x00\x00\x00" + - "\x00E\xf3\xe10\x01\x02\x03\x04\x02\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\a\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t" + - "\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\x00\x00\xc4\xf8\x00\x00\xff\xffsx\x00\x00\xff\xffs`\x00\x04\xff\xff\x81p\x01\b\xff\xff\x81p\x01\f\xff" + - "\xffs`\x00\x10\xff\xff\x81p\x01\x15\xff\xff\x81p\x00\x1a\xff\xff\x8f\x80\x01\x1e\xff\xff\x81p\x00#LMT\x00AST\x00AWT\x00APT\x00AHST\x00AHDT\x00YST\x00A" + - "KDT\x00AKST\x00\nAKST9AKDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rk\xc2\rx\xbf\x01\x00\x00\xbf\x01\x00" + - "\x00\x14\x00\x1c\x00America/DanmarkshavnUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\"\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff\x9b\x80I\x00\x00\x00\x00\x00\x13M|P\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90" + - "\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00" + - "\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#N\xf0\xa0\x00\x00\x00\x00P\x83e0\x00\x00\x00\x00Q 9\xa0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xff\xd2\xd0\x00\x00\xff\xff\xe3\xe0\x01\x04\xff\xff\xd5\xd0\x00\bLMT\x00-0" + - "2\x00-03\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xef\xf0R\x8a\xc4\x02\x00\x00\xc4\x02\x00\x00\x0f\x00\x1c\x00America/CordobaU" + - "T\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x06\x00\x00" + - "\x00\x14\xff\xff\xff\xffr\x9c\xad\xb0\xff\xff\xff\xff\xa2\x92\x8f0\xff\xff\xff\xff\xb6{R@\xff\xff\xff\xff\xb7\x1aɰ\xff\xff\xff\xff\xb8\x1e\x8f@\xff\xff\xff\xff\xb8\xd4p0\xff\xff\xff\xff\xba\x17}\xc0\xff\xff" + - "\xff\xff\xba\xb5\xa3\xb0\xff\xff\xff\xff\xbb\xf8\xb1@\xff\xff\xff\xff\xbc\x96\xd70\xff\xff\xff\xff\xbd\xd9\xe4\xc0\xff\xff\xff\xff\xbex\n\xb0\xff\xff\xff\xff\xbf\xbb\x18@\xff\xff\xff\xff\xc0Z\x8f\xb0\xff\xff\xff\xff\xc1\x9d" + - "\x9d@\xff\xff\xff\xff\xc2;\xc30\xff\xff\xff\xff\xc3~\xd0\xc0\xff\xff\xff\xff\xc4\x1c\xf6\xb0\xff\xff\xff\xff\xc5`\x04@\xff\xff\xff\xff\xc5\xfe*0\xff\xff\xff\xff\xc7A7\xc0\xff\xff\xff\xff\xc7\xe0\xaf0\xff\xff" + - "\xff\xffȁ\x94@\xff\xff\xff\xff\xcaM\xa1\xb0\xff\xff\xff\xff\xca\xee\x86\xc0\xff\xff\xff\xff\xceM\xff0\xff\xff\xff\xffΰ\xed\xc0\xff\xff\xff\xff\xd3)5\xb0\xff\xff\xff\xff\xd4Cd\xc0\xff\xff\xff\xff\xf4=" + - "\b0\xff\xff\xff\xff\xf4\x9f\xf6\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf62\x10@\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff" + - "\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$" + - "o\xa0\x00\x00\x00\x00#\x94\xb5\xb0\x00\x00\x00\x00$\x10\x94\xa0\x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xf0v\xa0\x00\x00\x00\x00'!\x0f0\x00\x00\x00\x00'\xd0X\xa0\x00\x00\x00\x00)\x00\xff@\x00\x00" + - "\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00\x00+\x99W \x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xbf*\xb0\x00\x00\x00\x00Gw\t\xb0\x00\x00\x00\x00G\xdc\u007f \x00\x00\x00\x00H\xfa" + - "\xa2\xb0\x00\x00\x00\x00I\xbca \x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x04\x05\x04\x05\x04\x05\x04" + - "\x02\x04\x05\x04\x05\x03\x05\x04\x05\x04\x05\xff\xff\xc3\xd0\x00\x00\xff\xff\xc3\xd0\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\fLMT\x00CMT\x00-04\x00-" + - "03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\u0096dK~\x02\x00\x00~\x02\x00\x00\x0e\x00\x1c\x00America/ReginaU" + - "T\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x005\x00\x00\x00\x06\x00\x00" + - "\x00\x18\xff\xff\xff\xff\x86\xfd\x93\x1c\xff\xff\xff\xff\x9e\xb8\xaf\x90\xff\xff\xff\xff\x9f\xbb\a\x80\xff\xff\xff\xff\xb5eO\xf0\xff\xff\xff\xff\xb60H\xe0\xff\xff\xff\xff\xb7E1\xf0\xff\xff\xff\xff\xb8\x10*\xe0\xff\xff" + - "\xff\xff\xb9%\x13\xf0\xff\xff\xff\xff\xb9\xf0\f\xe0\xff\xff\xff\xff\xbb\x0e0p\xff\xff\xff\xff\xbb\xcf\xee\xe0\xff\xff\xff\xff\xbc\xee\x12p\xff\xff\xff\xff\xbd\xb9\v`\xff\xff\xff\xff\xc2r\b\xf0\xff\xff\xff\xff\xc3a" + - "\xeb\xe0\xff\xff\xff\xff\xc4Q\xea\xf0\xff\xff\xff\xff\xc58\x93`\xff\xff\xff\xff\xc61\xcc\xf0\xff\xff\xff\xff\xc7!\xaf\xe0\xff\xff\xff\xff\xc8\x1a\xe9p\xff\xff\xff\xff\xc9\n\xcc`\xff\xff\xff\xff\xc9\xfa\xcbp\xff\xff" + - "\xff\xff\xca\xea\xae`\xff\xff\xff\xffˉ\f\x90\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff\xd3c\x8c\x10\xff\xff\xff\xff\xd4So\x00\xff\xff\xff\xff\xd5U\xe3\x10\xff\xff\xff\xff\xd6 " + - "\xdc\x00\xff\xff\xff\xff\xd75\xc5\x10\xff\xff\xff\xff\xd8\x00\xbe\x00\xff\xff\xff\xff\xd9\x15\xa7\x10\xff\xff\xff\xff\xd9\xe0\xa0\x00\xff\xff\xff\xff\xda\xfeÐ\xff\xff\xff\xff\xdb\xc0\x82\x00\xff\xff\xff\xff\xdcޥ\x90\xff\xff" + - "\xff\xffݩ\x9e\x80\xff\xff\xff\xff\u07be\x87\x90\xff\xff\xff\xff߉\x80\x80\xff\xff\xff\xff\xe0\x9ei\x90\xff\xff\xff\xff\xe1ib\x80\xff\xff\xff\xff\xe2~K\x90\xff\xff\xff\xff\xe3ID\x80\xff\xff\xff\xff\xe4^" + - "-\x90\xff\xff\xff\xff\xe5)&\x80\xff\xff\xff\xff\xe6GJ\x10\xff\xff\xff\xff\xe7\x12C\x00\xff\xff\xff\xff\xe8',\x10\xff\xff\xff\xff\xe8\xf2%\x00\xff\xff\xff\xff\xeb\xe6\xf0\x10\xff\xff\xff\xff\xec\xd6\xd3\x00\xff\xff" + - "\xff\xff\xed\xc6\xd2\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05\xff" + - "\xff\x9d\xe4\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\f\xff\xff\xab\xa0\x01\x10\xff\xff\xab\xa0\x00\x14LMT\x00MDT\x00MST\x00MWT\x00MPT\x00CST\x00\n" + - "CST6\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x85-\xb9\xf8\x8a\x01\x00\x00\x8a\x01\x00\x00\r\x00\x1c\x00America/BelemUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e" + - "`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01" + - "\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96\xaatt\xff" + - "\xff\xff\xff\xb8\x0fI\xe0\xff\xff\xff\xff\xb8\xfd@\xa0\xff\xff\xff\xff\xb9\xf140\xff\xff\xff\xff\xba\xdet \xff\xff\xff\xff\xda8\xae0\xff\xff\xff\xff\xda\xeb\xfa0\xff\xff\xff\xff\xdc\x19\xe1\xb0\xff\xff\xff\xff\xdc" + - "\xb9Y \xff\xff\xff\xff\xdd\xfb\x150\xff\xff\xff\xffޛ\xde \xff\xff\xff\xff\xdfݚ0\xff\xff\xff\xff\xe0T3 \xff\xff\xff\xff\xf4\x97\xff\xb0\xff\xff\xff\xff\xf5\x05^ \xff\xff\xff\xff\xf6\xc0d0\xff" + - "\xff\xff\xff\xf7\x0e\x1e\xa0\xff\xff\xff\xff\xf8Q,0\xff\xff\xff\xff\xf8\xc7\xc5 \xff\xff\xff\xff\xfa\nҰ\xff\xff\xff\xff\xfa\xa8\xf8\xa0\xff\xff\xff\xff\xfb\xec\x060\xff\xff\xff\xff\xfc\x8b}\xa0\x00\x00\x00\x00\x1d" + - "Ɏ0\x00\x00\x00\x00\x1exנ\x00\x00\x00\x00\x1f\xa05\xb0\x00\x00\x00\x00 3Ϡ\x00\x00\x00\x00!\x81i0\x00\x00\x00\x00\"\vȠ\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xffҌ\x00\x00\xff\xff\xe3\xe0\x01\x04\xff\xff\xd5\xd0\x00\bLMT\x00-02\x00-03\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00" + - "\xf1c9Rӿ\x92\xbc\xb5\x06\x00\x00\xb5\x06\x00\x00\x0f\x00\x1c\x00America/TorontoUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8" + - "\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xac\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xffr\xeex\xec\xff\xff\xff\xff\x9e\xb8\x93p\xff\xff\xff\xff\x9f\xba" + - "\xeb`\xff\xff\xff\xff\xa0\x87.\xc8\xff\xff\xff\xff\xa1\x9a\xb1@\xff\xff\xff\xff\xa2\x94\x06\xf0\xff\xff\xff\xff\xa3U\xa9@\xff\xff\xff\xff\xa4\x86]\xf0\xff\xff\xff\xff\xa5(x`\xff\xff\xff\xff\xa6f?\xf0\xff\xff" + - "\xff\xff\xa7\fN\xe0\xff\xff\xff\xff\xa8F!\xf0\xff\xff\xff\xff\xa8\xec0\xe0\xff\xff\xff\xff\xaa\x1c\xc9p\xff\xff\xff\xff\xaa\xd5M`\xff\xff\xff\xff\xab\xfc\xabp\xff\xff\xff\xff\xac\xb5/`\xff\xff\xff\xff\xad\xdc" + - "\x8dp\xff\xff\xff\xff\xae\x95\x11`\xff\xff\xff\xff\xaf\xbcop\xff\xff\xff\xff\xb0~-\xe0\xff\xff\xff\xff\xb1\x9cQp\xff\xff\xff\xff\xb2gJ`\xff\xff\xff\xff\xb3|3p\xff\xff\xff\xff\xb4G,`\xff\xff" + - "\xff\xff\xb5\\\x15p\xff\xff\xff\xff\xb6'\x0e`\xff\xff\xff\xff\xb7;\xf7p\xff\xff\xff\xff\xb8\x06\xf0`\xff\xff\xff\xff\xb9%\x13\xf0\xff\xff\xff\xff\xb9\xe6\xd2`\xff\xff\xff\xff\xbb\x04\xf5\xf0\xff\xff\xff\xff\xbb\xcf" + - "\xee\xe0\xff\xff\xff\xff\xbc\xe4\xd7\xf0\xff\xff\xff\xff\xbd\xaf\xd0\xe0\xff\xff\xff\xff\xbeĹ\xf0\xff\xff\xff\xff\xbf\x8f\xb2\xe0\xff\xff\xff\xff\xc0\xa4\x9b\xf0\xff\xff\xff\xff\xc1o\x94\xe0\xff\xff\xff\xff\u0084}\xf0\xff\xff" + - "\xff\xff\xc3Ov\xe0\xff\xff\xff\xff\xc4d_\xf0\xff\xff\xff\xff\xc5/X\xe0\xff\xff\xff\xff\xc6M|p\xff\xff\xff\xff\xc7\x0f:\xe0\xff\xff\xff\xff\xc8-^p\xff\xff\xff\xffˈ\xf0p\xff\xff\xff\xff\xd2#" + - "\xf4p\xff\xff\xff\xff\xd2`\xfb\xe0\xff\xff\xff\xff\xd3u\xe4\xf0\xff\xff\xff\xff\xd4@\xdd\xe0\xff\xff\xff\xff\xd5U\xaa\xd0\xff\xff\xff\xff\xd6 \xa3\xc0\xff\xff\xff\xff\xd75\x8c\xd0\xff\xff\xff\xff\xd8\x00\x85\xc0\xff\xff" + - "\xff\xff\xd9\x15n\xd0\xff\xff\xff\xff\xda3v@\xff\xff\xff\xff\xda\xfe\xa7p\xff\xff\xff\xff\xdc\x13t`\xff\xff\xff\xff\xdcމp\xff\xff\xff\xffݩ\x82`\xff\xff\xff\xff\u07bekp\xff\xff\xff\xff߉" + - "d`\xff\xff\xff\xff\xe0\x9eMp\xff\xff\xff\xff\xe1iF`\xff\xff\xff\xff\xe2~/p\xff\xff\xff\xff\xe3I(`\xff\xff\xff\xff\xe4^\x11p\xff\xff\xff\xff\xe5)\n`\xff\xff\xff\xff\xe6G-\xf0\xff\xff" + - "\xff\xff\xe7\x12&\xe0\xff\xff\xff\xff\xe8'\x0f\xf0\xff\xff\xff\xff\xe9\x16\xf2\xe0\xff\xff\xff\xff\xea\x06\xf1\xf0\xff\xff\xff\xff\xea\xf6\xd4\xe0\xff\xff\xff\xff\xeb\xe6\xd3\xf0\xff\xff\xff\xff\xecֶ\xe0\xff\xff\xff\xff\xed\xc6" + - "\xb5\xf0\xff\xff\xff\xff\xee\xbf\xd3`\xff\xff\xff\xff\xef\xaf\xd2p\xff\xff\xff\xff\xf0\x9f\xb5`\xff\xff\xff\xff\xf1\x8f\xb4p\xff\xff\xff\xff\xf2\u007f\x97`\xff\xff\xff\xff\xf3o\x96p\xff\xff\xff\xff\xf4_y`\xff\xff" + - "\xff\xff\xf5Oxp\xff\xff\xff\xff\xf6?[`\xff\xff\xff\xff\xf7/Zp\xff\xff\xff\xff\xf8(w\xe0\xff\xff\xff\xff\xf9\x0f\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO" + - "\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xb5\x94\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x01\f\xff\xff\xc7\xc0\x01\x10LMT\x00" + - "EDT\x00EST\x00EWT\x00EPT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RU9#\xbe2\x05" + - "\x00\x002\x05\x00\x00\x11\x00\x1c\x00America/VancouverUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x81\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff^=v\xec\xff\xff\xff\xff\x9e\xb8\xbd\xa0\xff\xff\xff\xff\x9f\xbb\x15\x90\xff\xff\xff\xffˉ" + - "\x1a\xa0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a&\x10\xff\xff\xff\xff\xd3v\x0f \xff\xff\xff\xff\xd4A\b\x10\xff\xff\xff\xff\xd5U\xf1 \xff\xff\xff\xff\xd6 \xea\x10\xff\xff\xff\xff\xd75\xd3 \xff\xff" + - "\xff\xff\xd8\x00\xcc\x10\xff\xff\xff\xff\xd9\x15\xb5 \xff\xff\xff\xff\xd9\xe0\xae\x10\xff\xff\xff\xff\xda\xfeѠ\xff\xff\xff\xff\xdb\xc0\x90\x10\xff\xff\xff\xff\xdc\u07b3\xa0\xff\xff\xff\xffݩ\xac\x90\xff\xff\xff\xff\u07be" + - "\x95\xa0\xff\xff\xff\xff߉\x8e\x90\xff\xff\xff\xff\xe0\x9ew\xa0\xff\xff\xff\xff\xe1ip\x90\xff\xff\xff\xff\xe2~Y\xa0\xff\xff\xff\xff\xe3IR\x90\xff\xff\xff\xff\xe4^;\xa0\xff\xff\xff\xff\xe5)4\x90\xff\xff" + - "\xff\xff\xe6GX \xff\xff\xff\xff\xe7\x12Q\x10\xff\xff\xff\xff\xe8': \xff\xff\xff\xff\xe8\xf23\x10\xff\xff\xff\xff\xea\a\x1c \xff\xff\xff\xff\xea\xd2\x15\x10\xff\xff\xff\xff\xeb\xe6\xfe \xff\xff\xff\xff\xec\xb1" + - "\xf7\x10\xff\xff\xff\xff\xed\xc6\xe0 \xff\xff\xff\xff\xee\x91\xd9\x10\xff\xff\xff\xff\xef\xaf\xfc\xa0\xff\xff\xff\xff\xf0q\xbb\x10\xff\xff\xff\xff\xf1\x8fޠ\xff\xff\xff\xff\xf2\u007f\xc1\x90\xff\xff\xff\xff\xf3o\xc0\xa0\xff\xff" + - "\xff\xff\xf4_\xa3\x90\xff\xff\xff\xff\xf5O\xa2\xa0\xff\xff\xff\xff\xf6?\x85\x90\xff\xff\xff\xff\xf7/\x84\xa0\xff\xff\xff\xff\xf8(\xa2\x10\xff\xff\xff\xff\xf9\x0ff\xa0\xff\xff\xff\xff\xfa\b\x84\x10\xff\xff\xff\xff\xfa\xf8" + - "\x83 \xff\xff\xff\xff\xfb\xe8f\x10\xff\xff\xff\xff\xfc\xd8e \xff\xff\xff\xff\xfd\xc8H\x10\xff\xff\xff\xff\xfe\xb8G \xff\xff\xff\xff\xff\xa8*\x10\x00\x00\x00\x00\x00\x98) \x00\x00\x00\x00\x01\x88\f\x10\x00\x00" + - "\x00\x00\x02x\v \x00\x00\x00\x00\x03q(\x90\x00\x00\x00\x00\x04a'\xa0\x00\x00\x00\x00\x05Q\n\x90\x00\x00\x00\x00\x06A\t\xa0\x00\x00\x00\x00\a0\xec\x90\x00\x00\x00\x00\b \xeb\xa0\x00\x00\x00\x00\t\x10" + - "ΐ\x00\x00\x00\x00\n\x00͠\x00\x00\x00\x00\n\xf0\xb0\x90\x00\x00\x00\x00\v\u0be0\x00\x00\x00\x00\f\xd9\xcd\x10\x00\x00\x00\x00\r\xc0\x91\xa0\x00\x00\x00\x00\x0e\xb9\xaf\x10\x00\x00\x00\x00\x0f\xa9\xae \x00\x00" + - "\x00\x00\x10\x99\x91\x10\x00\x00\x00\x00\x11\x89\x90 \x00\x00\x00\x00\x12ys\x10\x00\x00\x00\x00\x13ir \x00\x00\x00\x00\x14YU\x10\x00\x00\x00\x00\x15IT \x00\x00\x00\x00\x1697\x10\x00\x00\x00\x00\x17)" + - "6 \x00\x00\x00\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18 \x00\x00\x00\x00\x1a\x025\x90\x00\x00\x00\x00\x1a\xf24\xa0\x00\x00\x00\x00\x1b\xe2\x17\x90\x00\x00\x00\x00\x1c\xd2\x16\xa0\x00\x00\x00\x00\x1d\xc1\xf9\x90\x00\x00" + - "\x00\x00\x1e\xb1\xf8\xa0\x00\x00\x00\x00\x1f\xa1ې\x00\x00\x00\x00 v+ \x00\x00\x00\x00!\x81\xbd\x90\x00\x00\x00\x00\"V\r \x00\x00\x00\x00#j\xda\x10\x00\x00\x00\x00$5\xef \x00\x00\x00\x00%J" + - "\xbc\x10\x00\x00\x00\x00&\x15\xd1 \x00\x00\x00\x00'*\x9e\x10\x00\x00\x00\x00'\xfe\xed\xa0\x00\x00\x00\x00)\n\x80\x10\x00\x00\x00\x00)\xdeϠ\x00\x00\x00\x00*\xeab\x10\x00\x00\x00\x00+\xbe\xb1\xa0\x00\x00" + - "\x00\x00,\xd3~\x90\x00\x00\x00\x00-\x9e\x93\xa0\x00\x00\x00\x00.\xb3`\x90\x00\x00\x00\x00/~u\xa0\x00\x00\x00\x000\x93B\x90\x00\x00\x00\x001g\x92 \x00\x00\x00\x002s$\x90\x00\x00\x00\x003G" + - "t \x00\x00\x00\x004S\x06\x90\x00\x00\x00\x005'V \x00\x00\x00\x0062\xe8\x90\x00\x00\x00\x007\a8 \x00\x00\x00\x008\x1c\x05\x10\x00\x00\x00\x008\xe7\x1a \x00\x00\x00\x009\xfb\xe7\x10\x00\x00" + - "\x00\x00:\xc6\xfc \x00\x00\x00\x00;\xdb\xc9\x10\x00\x00\x00\x00<\xb0\x18\xa0\x00\x00\x00\x00=\xbb\xab\x10\x00\x00\x00\x00>\x8f\xfa\xa0\x00\x00\x00\x00?\x9b\x8d\x10\x00\x00\x00\x00@oܠ\x00\x00\x00\x00A\x84" + - "\xa9\x90\x00\x00\x00\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b\x90\x00\x00\x00\x00D/\xa0\xa0\x00\x00\x00\x00EDm\x90\x00\x00\x00\x00E\xf3\xd3 \x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\x8c\x94\x00\x00\xff\xff\x9d" + - "\x90\x01\x04\xff\xff\x8f\x80\x00\b\xff\xff\x9d\x90\x01\f\xff\xff\x9d\x90\x01\x10LMT\x00PDT\x00PST\x00PWT\x00PPT\x00\nPST8PDT,M3.2.0,M11" + - ".1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xf8Dz\x97\xae\x01\x00\x00\xae\x01\x00\x00\x11\x00\x1c\x00America/Boa_VistaUT\t\x00\x03\x15\xac\x0e" + - "`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" + - "\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96" + - "\xaa\u007f\xe0\xff\xff\xff\xff\xb8\x0fW\xf0\xff\xff\xff\xff\xb8\xfdN\xb0\xff\xff\xff\xff\xb9\xf1B@\xff\xff\xff\xff\xbaނ0\xff\xff\xff\xff\xda8\xbc@\xff\xff\xff\xff\xda\xec\b@\xff\xff\xff\xff\xdc\x19\xef\xc0\xff" + - "\xff\xff\xffܹg0\xff\xff\xff\xff\xdd\xfb#@\xff\xff\xff\xffޛ\xec0\xff\xff\xff\xff\xdfݨ@\xff\xff\xff\xff\xe0TA0\xff\xff\xff\xff\xf4\x98\r\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf6" + - "\xc0r@\xff\xff\xff\xff\xf7\x0e,\xb0\xff\xff\xff\xff\xf8Q:@\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xfa\n\xe0\xc0\xff\xff\xff\xff\xfa\xa9\x06\xb0\xff\xff\xff\xff\xfb\xec\x14@\xff\xff\xff\xff\xfc\x8b\x8b\xb0\x00" + - "\x00\x00\x00\x1dɜ@\x00\x00\x00\x00\x1ex\xe5\xb0\x00\x00\x00\x00\x1f\xa0C\xc0\x00\x00\x00\x00 3ݰ\x00\x00\x00\x00!\x81w@\x00\x00\x00\x00\"\vְ\x00\x00\x00\x007\xf6\xd4\xc0\x00\x00\x00\x008" + - "\xb8\x930\x00\x00\x00\x009\xdf\xf1@\x00\x00\x00\x009\xe9\x1d\xb0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xff\xc7 \x00\x00\xff\xff" + - "\xd5\xd0\x01\x04\xff\xff\xc7\xc0\x00\bLMT\x00-03\x00-04\x00\n<-04>4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x19vv\xa0\x97\x00\x00\x00\x97\x00\x00\x00\x15\x00\x1c\x00" + - "America/Lower_PrincesUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xff\x93\x1e.#\xff\xff\xff\xff\xf6\x98\xecH\x01\x02\xff\xff\xbf]\x00\x00\xff\xff\xc0\xb8\x00\x04\xff\xff\xc7\xc0\x00\n" + - "LMT\x00-0430\x00AST\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\v\x00\x1c\x00Antarctica" + - "/UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xc2\v\xae\b\x85\x00\x00\x00\x85\x00\x00\x00\x11\x00\x1c\x00A" + - "ntarctica/VostokUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\xe9X\x89\x80\x01\x00\x00\x00\x00\x00\x00\x00\x00T`\x00\x04-00\x00+06\x00\n<+06>-6\nPK\x03" + - "\x04\n\x00\x00\x00\x00\x00\xf1c9R\x95{\xf3\xa9w\x03\x00\x00w\x03\x00\x00\x11\x00\x1c\x00Antarctica/PalmerUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v" + - "\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00" + - "\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00R\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xf6\x98\xad\x00\xff\xff\xff\xff\xf6" + - "柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff" + - "\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00\x170\xbc\xb0\x00\x00\x00\x00\x18\x06]\xc0\x00\x00\x00\x00\x18\xd1V\xb0\x00\x00\x00\x00\x19" + - "\xe6?\xc0\x00\x00\x00\x00\x1a\xb18\xb0\x00\x00\x00\x00\x1b\xcf\\@\x00\x00\x00\x00\x1c\x91\x1a\xb0\x00\x00\x00\x00\x1d\xaf>@\x00\x00\x00\x00\x1ep\xfc\xb0\x00\x00\x00\x00\x1f\x8f @\x00\x00\x00\x00 \u007f\x030\x00" + - "\x00\x00\x00!o\x02@\x00\x00\x00\x00\"9\xfb0\x00\x00\x00\x00#N\xe4@\x00\x00\x00\x00$\x19\xdd0\x00\x00\x00\x00%8\x00\xc0\x00\x00\x00\x00%\xf9\xbf0\x00\x00\x00\x00&\xf2\xf8\xc0\x00\x00\x00\x00'" + - "١0\x00\x00\x00\x00(\xf7\xc4\xc0\x00\x00\x00\x00)½\xb0\x00\x00\x00\x00*צ\xc0\x00\x00\x00\x00+\xa2\x9f\xb0\x00\x00\x00\x00,\xb7\x88\xc0\x00\x00\x00\x00-\x82\x81\xb0\x00\x00\x00\x00.\x97j\xc0\x00" + - "\x00\x00\x00/bc\xb0\x00\x00\x00\x000\x80\x87@\x00\x00\x00\x001BE\xb0\x00\x00\x00\x002`i@\x00\x00\x00\x003=\xd70\x00\x00\x00\x004@K@\x00\x00\x00\x005\vD0\x00\x00\x00\x006" + - "\r\xb8@\x00\x00\x00\x007\x06հ\x00\x00\x00\x008\x00\x0f@\x00\x00\x00\x008\xcb\b0\x00\x00\x00\x009\xe9+\xc0\x00\x00\x00\x00:\xaa\xea0\x00\x00\x00\x00;\xc9\r\xc0\x00\x00\x00\x00<\x8a\xcc0\x00" + - "\x00\x00\x00=\xa8\xef\xc0\x00\x00\x00\x00>j\xae0\x00\x00\x00\x00?\x88\xd1\xc0\x00\x00\x00\x00@Sʰ\x00\x00\x00\x00Ah\xb3\xc0\x00\x00\x00\x00B3\xac\xb0\x00\x00\x00\x00CH\x95\xc0\x00\x00\x00\x00D" + - "\x13\x8e\xb0\x00\x00\x00\x00E1\xb2@\x00\x00\x00\x00E\xf3p\xb0\x00\x00\x00\x00G\x11\x94@\x00\x00\x00\x00G\xef\x020\x00\x00\x00\x00H\xf1v@\x00\x00\x00\x00I\xbco0\x00\x00\x00\x00J\xd1X@\x00" + - "\x00\x00\x00K\xb8\x00\xb0\x00\x00\x00\x00L\xb1:@\x00\x00\x00\x00M\xc6\a0\x00\x00\x00\x00NP\x82\xc0\x00\x00\x00\x00O\x9c\xae\xb0\x00\x00\x00\x00PB\xd9\xc0\x00\x00\x00\x00Q|\x90\xb0\x00\x00\x00\x00R" + - "+\xf6@\x00\x00\x00\x00S\\r\xb0\x00\x00\x00\x00T\v\xd8@\x00\x00\x00\x00W7\xe60\x00\x00\x00\x00W\xaf\xec\xc0\x00\x00\x00\x00XC\x86\xb0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x04\x03\x04\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x04\x00\x00\x00\x00\x00\x00\xff\xff\xc7\xc0\x00\x04\xff\xff\xd5\xd0\x01\b\xff\xff\xe3\xe0\x01\f\xff\xff\xd5\xd0\x00\b-00\x00-04\x00-03\x00-02\x00\n<-03>3\nP" + - "K\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R:\xc8P7\xb1\x00\x00\x00\xb1\x00\x00\x00\x10\x00\x1c\x00Antarctica/TrollUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux" + - "\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00" + - "\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\x00\x00\x00\x00B\rG\x00\x00\x00\x00\x00" + - "BF\x05\x90\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x1c \x01\x04\x00\x00\x00\x00\x00\b-00\x00+02\x00+00\x00\n<+00>0<+02>-2,M3.5.0/1," + - "M10.5.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rb\xb2\xaf\xf7\x13\x04\x00\x00\x13\x04\x00\x00\x12\x00\x1c\x00Antarctica/McMurdoUT" + - "\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x00\x00\x00\x06\x00\x00\x00" + - "\x13\xff\xff\xff\xffA\xb7L\xa8\xff\xff\xff\xff\xb0\xb4\xb2\xe8\xff\xff\xff\xff\xb1Q\x87X\xff\xff\xff\xff\xb2x\xe5h\xff\xff\xff\xff\xb3C\xe5`\xff\xff\xff\xff\xb4X\xc7h\xff\xff\xff\xff\xb5#\xc7`\xff\xff\xff" + - "\xff\xb68\xa9h\xff\xff\xff\xff\xb7\x03\xa9`\xff\xff\xff\xff\xb8\x18\x8bh\xff\xff\xff\xff\xb8\xec\xc5\xe0\xff\xff\xff\xff\xb9\xf8mh\xff\xff\xff\xff\xba̧\xe0\xff\xff\xff\xff\xbb\xd8Oh\xff\xff\xff\xff\xbc\xe3\xe8" + - "\xe0\xff\xff\xff\xff\xbd\xae\xf6\xe8\xff\xff\xff\xff\xbe\xc3\xca\xe0\xff\xff\xff\xff\xbf\x8e\xd8\xe8\xff\xff\xff\xff\xc0\xa3\xac\xe0\xff\xff\xff\xff\xc1n\xba\xe8\xff\xff\xff\xff\u0083\x8e\xe0\xff\xff\xff\xff\xc3N\x9c\xe8\xff\xff\xff" + - "\xff\xc4cp\xe0\xff\xff\xff\xff\xc5.~\xe8\xff\xff\xff\xff\xc6L\x8d`\xff\xff\xff\xff\xc7\x0e`\xe8\xff\xff\xff\xff\xc8,o`\xff\xff\xff\xff\xc8\xf7}h\xff\xff\xff\xff\xd2ښ@\x00\x00\x00\x00\t\x18\xfd" + - "\xe0\x00\x00\x00\x00\t\xac\xa5\xe0\x00\x00\x00\x00\n\xef\xa5`\x00\x00\x00\x00\v\x9e\xfc\xe0\x00\x00\x00\x00\f\xd8\xc1\xe0\x00\x00\x00\x00\r~\xde\xe0\x00\x00\x00\x00\x0e\xb8\xa3\xe0\x00\x00\x00\x00\x0f^\xc0\xe0\x00\x00\x00" + - "\x00\x10\x98\x85\xe0\x00\x00\x00\x00\x11>\xa2\xe0\x00\x00\x00\x00\x12xg\xe0\x00\x00\x00\x00\x13\x1e\x84\xe0\x00\x00\x00\x00\x14XI\xe0\x00\x00\x00\x00\x14\xfef\xe0\x00\x00\x00\x00\x168+\xe0\x00\x00\x00\x00\x16\xe7\x83" + - "`\x00\x00\x00\x00\x18!H`\x00\x00\x00\x00\x18\xc7e`\x00\x00\x00\x00\x1a\x01*`\x00\x00\x00\x00\x1a\xa7G`\x00\x00\x00\x00\x1b\xe1\f`\x00\x00\x00\x00\x1c\x87)`\x00\x00\x00\x00\x1d\xc0\xee`\x00\x00\x00" + - "\x00\x1eg\v`\x00\x00\x00\x00\x1f\xa0\xd0`\x00\x00\x00\x00 F\xed`\x00\x00\x00\x00!\x80\xb2`\x00\x00\x00\x00\"0\t\xe0\x00\x00\x00\x00#i\xce\xe0\x00\x00\x00\x00$\x0f\xeb\xe0\x00\x00\x00\x00%.\x01" + - "`\x00\x00\x00\x00&\x02B\xe0\x00\x00\x00\x00'\r\xe3`\x00\x00\x00\x00'\xe2$\xe0\x00\x00\x00\x00(\xed\xc5`\x00\x00\x00\x00)\xc2\x06\xe0\x00\x00\x00\x00*ͧ`\x00\x00\x00\x00+\xab#`\x00\x00\x00" + - "\x00,\xad\x89`\x00\x00\x00\x00-\x8b\x05`\x00\x00\x00\x00.\x8dk`\x00\x00\x00\x00/j\xe7`\x00\x00\x00\x000mM`\x00\x00\x00\x001J\xc9`\x00\x00\x00\x002Vi\xe0\x00\x00\x00\x003*\xab" + - "`\x00\x00\x00\x0046K\xe0\x00\x00\x00\x005\n\x8d`\x00\x00\x00\x006\x16-\xe0\x00\x00\x00\x006\xf3\xa9\xe0\x00\x00\x00\x007\xf6\x0f\xe0\x00\x00\x00\x008Ӌ\xe0\x00\x00\x00\x009\xd5\xf1\xe0\x00\x00\x00" + - "\x00:\xb3m\xe0\x00\x00\x00\x00;\xbf\x0e`\x00\x00\x00\x00<\x93O\xe0\x00\x00\x00\x00=\x9e\xf0`\x00\x00\x00\x00>s1\xe0\x00\x00\x00\x00?~\xd2`\x00\x00\x00\x00@\\N`\x00\x00\x00\x00A^\xb4" + - "`\x00\x00\x00\x00B<0`\x00\x00\x00\x00C>\x96`\x00\x00\x00\x00D\x1c\x12`\x00\x00\x00\x00E\x1ex`\x00\x00\x00\x00E\xfb\xf4`\x00\x00\x00\x00F\xfeZ`\x02\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05" + - "\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x00\x00\xa3\xd8\x00\x00\x00\x00\xaf\xc8\x01\x04\x00\x00\xa1\xb8\x00\t\x00\x00\xa8\xc0\x01\x04\x00\x00\xb6\xd0\x01\x0e\x00\x00\xa8\xc0\x00" + - "\x04LMT\x00NZST\x00NZMT\x00NZDT\x00\nNZST-12NZDT,M9.5.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1" + - "c9R\x95\xea\x06\xd3\xc5\x00\x00\x00\xc5\x00\x00\x00\x10\x00\x1c\x00Antarctica/DavisUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8" + - "\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\xe7\x9c@\x00\xff\xff\xff\xff\xf6G\xdf\x10\xff\xff\xff\xff\xfeG" + - "\xab\x00\x00\x00\x00\x00J\xda\x140\x00\x00\x00\x00K\x97\xfa@\x00\x00\x00\x00N\xa9\xaa0\x00\x00\x00\x00OC\xf7\xc0\x01\x00\x01\x02\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00bp\x00\x04\x00\x00FP\x00\b-" + - "00\x00+07\x00+05\x00\n<+07>-7\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\r\x0e\xf20\x85\x00\x00\x00\x85\x00\x00\x00\x10\x00\x1c\x00Antarctica" + - "/SyowaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\xe7\xb1X\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00*0\x00\x04-00\x00+03\x00\n<+03>-3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9" + - "R\xc8\x14\xdcA\x98\x00\x00\x00\x98\x00\x00\x00\x19\x00\x1c\x00Antarctica/DumontDUrvilleUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01" + - "\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00" + - "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xffԼv\x80\xff\xff\xff\xff\xde4`" + - "`\xff\xff\xff\xff\xe7<\x02\x80\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x8c\xa0\x00\x04-00\x00+10\x00\n<+10>-10\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xd7N\xab\x8b" + - "\x98\x00\x00\x00\x98\x00\x00\x00\x11\x00\x1c\x00Antarctica/MawsonUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZi" + - "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\xe2 2\x80\x00\x00\x00\x00J\xda\"@\x01\x02\x00\x00\x00\x00\x00\x00\x00\x00T`" + - "\x00\x04\x00\x00FP\x00\b-00\x00+06\x00+05\x00\n<+05>-5\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RƉ\xf71\x84\x00\x00\x00\x84\x00\x00\x00\x12\x00\x1c\x00A" + - "ntarctica/RotheraUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\x00\x00\x00\x00\r\x02-\x00\x01\x00\x00\x00\x00\x00\x00\xff\xff\xd5\xd0\x00\x04-00\x00-03\x00\n<-03>3\nPK\x03" + - "\x04\n\x00\x00\x00\x00\x00\xf1c9R\xddzAh\xf3\x00\x00\x00\xf3\x00\x00\x00\x10\x00\x1c\x00Antarctica/CaseyUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00" + - "\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00" + - "\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\f\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\xfe\x1è\x00\x00\x00\x00J\xda" + - "\x06 \x00\x00\x00\x00K\x8f\xca\xf0\x00\x00\x00\x00N\xa9\x9c \x00\x00\x00\x00OC͐\x00\x00\x00\x00X\n;\x80\x00\x00\x00\x00Z\xa4\x0f\x10\x00\x00\x00\x00[\xb9\x14@\x00\x00\x00\x00\\\x8d\x1d\x80\x00\x00" + - "\x00\x00]\x96E0\x00\x00\x00\x00^c\xc5\x00\x00\x00\x00\x00_x\xa0<\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\x00\x00\x00\x00\x00\x00p\x80\x00\x04\x00\x00\x9a\xb0\x00\b-00\x00+08\x00" + - "+11\x00\n<+11>-11\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xb2\x84J]\xd0\x03\x00\x00\xd0\x03\x00\x00\x14\x00\x1c\x00Antarctica/Macqu" + - "arieUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00[\x00" + - "\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xff|\x05\x16\x00\xff\xff\xff\xff\x9b\xd5x\x80\xff\xff\xff\xff\x9c\xbc/\x00\xff\xff\xff\xff\xa0\x87\xb4`\xff\xff\xff\xff\xd7\fh\x00\xff\xff\xff\xff\xfb\u008d\x00\xff\xff\xff\xff\xfc" + - "\xb2~\x00\xff\xff\xff\xff\xfd\xc7Y\x00\xff\xff\xff\xff\xfev\xb0\x80\xff\xff\xff\xff\xff\xa7;\x00\x00\x00\x00\x00\x00V\x92\x80\x00\x00\x00\x00\x01\x87\x1d\x00\x00\x00\x00\x00\x02?\xaf\x00\x00\x00\x00\x00\x03p9\x80\x00" + - "\x00\x00\x00\x04\r\x1c\x00\x00\x00\x00\x00\x05P\x1b\x80\x00\x00\x00\x00\x05\xf68\x80\x00\x00\x00\x00\a/\xfd\x80\x00\x00\x00\x00\a\xd6\x1a\x80\x00\x00\x00\x00\t\x0f߀\x00\x00\x00\x00\t\xb5\xfc\x80\x00\x00\x00\x00\n" + - "\xef\xc1\x80\x00\x00\x00\x00\v\x9f\x19\x00\x00\x00\x00\x00\f\xd8\xde\x00\x00\x00\x00\x00\r~\xfb\x00\x00\x00\x00\x00\x0e\xb8\xc0\x00\x00\x00\x00\x00\x0f^\xdd\x00\x00\x00\x00\x00\x10\x98\xa2\x00\x00\x00\x00\x00\x11>\xbf\x00\x00" + - "\x00\x00\x00\x12x\x84\x00\x00\x00\x00\x00\x13\x1e\xa1\x00\x00\x00\x00\x00\x14Xf\x00\x00\x00\x00\x00\x14\xfe\x83\x00\x00\x00\x00\x00\x168H\x00\x00\x00\x00\x00\x17\x03O\x00\x00\x00\x00\x00\x18!d\x80\x00\x00\x00\x00\x18" + - "\xe31\x00\x00\x00\x00\x00\x1a\x01F\x80\x00\x00\x00\x00\x1a\xa7c\x80\x00\x00\x00\x00\x1b\xe1(\x80\x00\x00\x00\x00\x1c\x87E\x80\x00\x00\x00\x00\x1d\xc1\n\x80\x00\x00\x00\x00\x1eg'\x80\x00\x00\x00\x00\x1f\x97\xb2\x00\x00" + - "\x00\x00\x00 Y~\x80\x00\x00\x00\x00!\x80\u0380\x00\x00\x00\x00\"B\x9b\x00\x00\x00\x00\x00#i\xeb\x00\x00\x00\x00\x00$\"}\x00\x00\x00\x00\x00%I\xcd\x00\x00\x00\x00\x00&\x02_\x00\x00\x00\x00\x00'" + - ")\xaf\x00\x00\x00\x00\x00'\xf4\xb6\x00\x00\x00\x00\x00(\xed\xe1\x80\x00\x00\x00\x00)Ԙ\x00\x00\x00\x00\x00*\xcdÀ\x00\x00\x00\x00+\xb4z\x00\x00\x00\x00\x00,\xad\xa5\x80\x00\x00\x00\x00-\x94\\\x00\x00" + - "\x00\x00\x00.\x8d\x87\x80\x00\x00\x00\x00/t>\x00\x00\x00\x00\x000mi\x80\x00\x00\x00\x001]Z\x80\x00\x00\x00\x002V\x86\x00\x00\x00\x00\x003=<\x80\x00\x00\x00\x0046h\x00\x00\x00\x00\x005" + - "\x1d\x1e\x80\x00\x00\x00\x006\x16J\x00\x00\x00\x00\x006\xfd\x00\x80\x00\x00\x00\x007\xf6,\x00\x00\x00\x00\x008\xdc\xe2\x80\x00\x00\x00\x009\xa7\xe9\x80\x00\x00\x00\x00:\xbcĀ\x00\x00\x00\x00;\xbf*\x80\x00" + - "\x00\x00\x00<\xa5\xe1\x00\x00\x00\x00\x00=\x9f\f\x80\x00\x00\x00\x00>\x85\xc3\x00\x00\x00\x00\x00?~\xee\x80\x00\x00\x00\x00@e\xa5\x00\x00\x00\x00\x00A^Ѐ\x00\x00\x00\x00BE\x87\x00\x00\x00\x00\x00C" + - ">\xb2\x80\x00\x00\x00\x00D.\xa3\x80\x00\x00\x00\x00E\x1e\x94\x80\x00\x00\x00\x00F\x05K\x00\x00\x00\x00\x00G\a\xb1\x00\x00\x00\x00\x00G\xf7\xa2\x00\x00\x00\x00\x00H\xe7\x93\x00\x00\x00\x00\x00Iׄ\x00\x00" + - "\x00\x00\x00J\xc7u\x00\x00\x00\x00\x00M\x97H\x00\x01\x02\x01\x00\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x8c\xa0\x00\x04\x00\x00" + - "\x9a\xb0\x01\t-00\x00AEST\x00AEDT\x00\nAEST-10AEDT,M10.1.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c" + - "9Rb\xb2\xaf\xf7\x13\x04\x00\x00\x13\x04\x00\x00\x15\x00\x1c\x00Antarctica/South_PoleUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03" + - "\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + - "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x00\x00\x00\x06\x00\x00\x00\x13\xff\xff\xff\xffA\xb7L\xa8\xff\xff\xff\xff\xb0\xb4\xb2\xe8\xff\xff" + - "\xff\xff\xb1Q\x87X\xff\xff\xff\xff\xb2x\xe5h\xff\xff\xff\xff\xb3C\xe5`\xff\xff\xff\xff\xb4X\xc7h\xff\xff\xff\xff\xb5#\xc7`\xff\xff\xff\xff\xb68\xa9h\xff\xff\xff\xff\xb7\x03\xa9`\xff\xff\xff\xff\xb8\x18" + - "\x8bh\xff\xff\xff\xff\xb8\xec\xc5\xe0\xff\xff\xff\xff\xb9\xf8mh\xff\xff\xff\xff\xba̧\xe0\xff\xff\xff\xff\xbb\xd8Oh\xff\xff\xff\xff\xbc\xe3\xe8\xe0\xff\xff\xff\xff\xbd\xae\xf6\xe8\xff\xff\xff\xff\xbe\xc3\xca\xe0\xff\xff" + - "\xff\xff\xbf\x8e\xd8\xe8\xff\xff\xff\xff\xc0\xa3\xac\xe0\xff\xff\xff\xff\xc1n\xba\xe8\xff\xff\xff\xff\u0083\x8e\xe0\xff\xff\xff\xff\xc3N\x9c\xe8\xff\xff\xff\xff\xc4cp\xe0\xff\xff\xff\xff\xc5.~\xe8\xff\xff\xff\xff\xc6L" + - "\x8d`\xff\xff\xff\xff\xc7\x0e`\xe8\xff\xff\xff\xff\xc8,o`\xff\xff\xff\xff\xc8\xf7}h\xff\xff\xff\xff\xd2ښ@\x00\x00\x00\x00\t\x18\xfd\xe0\x00\x00\x00\x00\t\xac\xa5\xe0\x00\x00\x00\x00\n\xef\xa5`\x00\x00" + - "\x00\x00\v\x9e\xfc\xe0\x00\x00\x00\x00\f\xd8\xc1\xe0\x00\x00\x00\x00\r~\xde\xe0\x00\x00\x00\x00\x0e\xb8\xa3\xe0\x00\x00\x00\x00\x0f^\xc0\xe0\x00\x00\x00\x00\x10\x98\x85\xe0\x00\x00\x00\x00\x11>\xa2\xe0\x00\x00\x00\x00\x12x" + - "g\xe0\x00\x00\x00\x00\x13\x1e\x84\xe0\x00\x00\x00\x00\x14XI\xe0\x00\x00\x00\x00\x14\xfef\xe0\x00\x00\x00\x00\x168+\xe0\x00\x00\x00\x00\x16\xe7\x83`\x00\x00\x00\x00\x18!H`\x00\x00\x00\x00\x18\xc7e`\x00\x00" + - "\x00\x00\x1a\x01*`\x00\x00\x00\x00\x1a\xa7G`\x00\x00\x00\x00\x1b\xe1\f`\x00\x00\x00\x00\x1c\x87)`\x00\x00\x00\x00\x1d\xc0\xee`\x00\x00\x00\x00\x1eg\v`\x00\x00\x00\x00\x1f\xa0\xd0`\x00\x00\x00\x00 F" + - "\xed`\x00\x00\x00\x00!\x80\xb2`\x00\x00\x00\x00\"0\t\xe0\x00\x00\x00\x00#i\xce\xe0\x00\x00\x00\x00$\x0f\xeb\xe0\x00\x00\x00\x00%.\x01`\x00\x00\x00\x00&\x02B\xe0\x00\x00\x00\x00'\r\xe3`\x00\x00" + - "\x00\x00'\xe2$\xe0\x00\x00\x00\x00(\xed\xc5`\x00\x00\x00\x00)\xc2\x06\xe0\x00\x00\x00\x00*ͧ`\x00\x00\x00\x00+\xab#`\x00\x00\x00\x00,\xad\x89`\x00\x00\x00\x00-\x8b\x05`\x00\x00\x00\x00.\x8d" + - "k`\x00\x00\x00\x00/j\xe7`\x00\x00\x00\x000mM`\x00\x00\x00\x001J\xc9`\x00\x00\x00\x002Vi\xe0\x00\x00\x00\x003*\xab`\x00\x00\x00\x0046K\xe0\x00\x00\x00\x005\n\x8d`\x00\x00" + - "\x00\x006\x16-\xe0\x00\x00\x00\x006\xf3\xa9\xe0\x00\x00\x00\x007\xf6\x0f\xe0\x00\x00\x00\x008Ӌ\xe0\x00\x00\x00\x009\xd5\xf1\xe0\x00\x00\x00\x00:\xb3m\xe0\x00\x00\x00\x00;\xbf\x0e`\x00\x00\x00\x00<\x93" + - "O\xe0\x00\x00\x00\x00=\x9e\xf0`\x00\x00\x00\x00>s1\xe0\x00\x00\x00\x00?~\xd2`\x00\x00\x00\x00@\\N`\x00\x00\x00\x00A^\xb4`\x00\x00\x00\x00B<0`\x00\x00\x00\x00C>\x96`\x00\x00" + - "\x00\x00D\x1c\x12`\x00\x00\x00\x00E\x1ex`\x00\x00\x00\x00E\xfb\xf4`\x00\x00\x00\x00F\xfeZ`\x02\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x05\x04" + - "\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04" + - "\x05\x04\x05\x04\x05\x04\x00\x00\xa3\xd8\x00\x00\x00\x00\xaf\xc8\x01\x04\x00\x00\xa1\xb8\x00\t\x00\x00\xa8\xc0\x01\x04\x00\x00\xb6\xd0\x01\x0e\x00\x00\xa8\xc0\x00\x04LMT\x00NZST\x00NZMT\x00NZDT" + - "\x00\nNZST-12NZDT,M9.5.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x1c\x00" + - "Arctic/UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xa5\x97\aĤ\x02\x00\x00\xa4\x02\x00" + - "\x00\x13\x00\x1c\x00Arctic/LongyearbyenUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00:\x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff\xffr\xee$l\xff\xff\xff\xff\x9b'\xe3\x00\xff\xff\xff\xff\x9b\xd4{`\xff\xff\xff\xffȷM`\xff" + - "\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd2b\a\x10\xff\xff\xff\xff\xeb" + - "\xaf \x90\xff\xff\xff\xff\xec\xa8L\x10\xff\xff\xff\xff\xed\x98=\x10\xff\xff\xff\xff\xee\x88.\x10\xff\xff\xff\xff\xefx\x1f\x10\xff\xff\xff\xff\xf0h\x10\x10\xff\xff\xff\xff\xf1X\x01\x10\xff\xff\xff\xff\xf2G\xf2\x10\xff" + - "\xff\xff\xff\xf37\xe3\x10\xff\xff\xff\xff\xf4'\xd4\x10\xff\xff\xff\xff\xf5\x17\xc5\x10\xff\xff\xff\xff\xf6\x10\xf0\x90\xff\xff\xff\xff\xf7/\x06\x10\xff\xff\xff\xff\xf7\xf0Ґ\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x14" + - "3\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00" + - "\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"" + - "LT\x10\x00\x00\x00\x00#\x85\xfb@\x00\x00\x00\x00?\x9a\xd6@\x00\x00\x00\x00@e\xdd@\x00\x00\x00\x00A\x83\xf2\xc0\x00\x00\x00\x00BE\xbf@\x00\x00" + - "\x00\x00Cc\xd4\xc0\x00\x00\x00\x00D%\xa1@\x00\x00\x00\x00EC\xb6\xc0\x00\x00\x00\x00F\x05\x83@\x00\x00\x00\x00G#\x98\xc0\x00\x00\x00\x00G\xee\x9f\xc0\x00\x00\x00\x00I\x03z\xc0\x00\x00\x00\x00I\xce" + - "\x81\xc0\x00\x00\x00\x00J\xe3\\\xc0\x00\x00\x00\x00K\xaec\xc0\x00\x00\x00\x00L\xccy@\x00\x00\x00\x00M\x8eE\xc0\x00\x00\x00\x00TK\xf30\x00\x00\x00\x00WI\xf8\xc0\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x03\x01\x03\x00\x00O" + - "\xa7\x00\x00\x00\x00T`\x00\x04\x00\x00p\x80\x01\b\x00\x00bp\x00\f\x00\x00bp\x01\fLMT\x00+06\x00+08\x00+07\x00\n<+07>-7\nPK\x03\x04\n\x00\x00\x00" + - "\x00\x00\xf1c9R\x81z&\x80k\x02\x00\x00k\x02\x00\x00\x0f\x00\x1c\x00Asia/ChoibalsanUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00" + - "\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif" + - "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x003\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xff\x86\xd3\xe7(\x00\x00\x00\x00\x0f\vܐ\x00\x00\x00\x00" + - "\x18\xe9Ȁ\x00\x00\x00\x00\x19\xda\xee\xe0\x00\x00\x00\x00\x1a\xcc?p\x00\x00\x00\x00\x1b\xbc\"`\x00\x00\x00\x00\x1c\xac!p\x00\x00\x00\x00\x1d\x9c\x04`\x00\x00\x00\x00\x1e\x8c\x03p\x00\x00\x00\x00\x1f{\xe6`" + - "\x00\x00\x00\x00 k\xe5p\x00\x00\x00\x00![\xc8`\x00\x00\x00\x00\"K\xc7p\x00\x00\x00\x00#;\xaa`\x00\x00\x00\x00$+\xa9p\x00\x00\x00\x00%\x1b\x8c`\x00\x00\x00\x00&\v\x8bp\x00\x00\x00\x00" + - "'\x04\xa8\xe0\x00\x00\x00\x00'\xf4\xa7\xf0\x00\x00\x00\x00(\xe4\x8a\xe0\x00\x00\x00\x00)ԉ\xf0\x00\x00\x00\x00*\xc4l\xe0\x00\x00\x00\x00+\xb4k\xf0\x00\x00\x00\x00,\xa4N\xe0\x00\x00\x00\x00-\x94M\xf0" + - "\x00\x00\x00\x00.\x840\xe0\x00\x00\x00\x00/t/\xf0\x00\x00\x00\x000d\x12\xe0\x00\x00\x00\x001]Lp\x00\x00\x00\x002M/`\x00\x00\x00\x003=.p\x00\x00\x00\x004-\x11`\x00\x00\x00\x00" + - "5\x1d\x10p\x00\x00\x00\x006\f\xf3`\x00\x00\x00\x00:饐\x00\x00\x00\x00;\xb4\x9e\x80\x00\x00\x00\x00<\xa4\x9d\x90\x00\x00\x00\x00=\x94\x80\x80\x00\x00\x00\x00>\x84\u007f\x90\x00\x00\x00\x00?tb\x80" + - "\x00\x00\x00\x00@da\x90\x00\x00\x00\x00ATD\x80\x00\x00\x00\x00BDC\x90\x00\x00\x00\x00C4&\x80\x00\x00\x00\x00D$%\x90\x00\x00\x00\x00E\x1dC\x00\x00\x00\x00\x00G\xef\xaa\xf0\x00\x00\x00\x00" + - "U\x15\x9a\xa0\x00\x00\x00\x00V\x05ap\x00\x00\x00\x00V\xf5|\xa0\x00\x00\x00\x00W\xe5Cp\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03" + - "\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x02\x05\x02\x05\x02\x00\x00kX\x00\x00\x00\x00bp\x00\x04\x00\x00p\x80\x00\b\x00\x00~\x90\x00\f\x00\x00\x8c\xa0\x01\x10\x00\x00~\x90\x01\fLMT\x00+" + - "07\x00+08\x00+09\x00+10\x00\n<+08>-8\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rj$\xcd\xf4\x9a\x00\x00\x00\x9a\x00\x00\x00\v\x00\x1c\x00Asia/T" + - "himbuUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02" + - "\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xff\xd5\xe6\x15t\x00\x00\x00\x00!aM\xa8\x01\x02\x00\x00T\f\x00\x00\x00\x00MX\x00\x04\x00\x00T`\x00\nLMT\x00+0530\x00+06\x00\n<" + - "+06>-6\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x88\xf6C\x84\x98\x00\x00\x00\x98\x00\x00\x00\x0e\x00\x1c\x00Asia/VientianeUT\t\x00\x03\x15\xac\x0e`" + - "\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00" + - "\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xffV\xb6" + - "\x85\xc4\xff\xff\xff\xff\xa2jg\xc4\x01\x02\x00\x00^<\x00\x00\x00\x00^<\x00\x04\x00\x00bp\x00\bLMT\x00BMT\x00+07\x00\n<+07>-7\nPK\x03\x04\n\x00\x00\x00\x00" + - "\x00\xf1c9Rʇ{_\xbb\x00\x00\x00\xbb\x00\x00\x00\v\x00\x1c\x00Asia/YangonUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00V\x00\x00\x00\t\x00\x00\x00&\xff\xff\xff\xff\x8c4\xe53\xff\xff\xff\xff\xa2\x92\x87\xb3\xff\xff\xff\xff\xa8\xff\xdb@\xff\xff\xff" + + "\xff\xa9\xf1\x0f\xb0\xff\xff\xff\xff\xaa\xe2Y8\xff\xff\xff\xff\xab\xd2C0\xff\xff\xff\xff\xacÌ\xb8\xff\xff\xff\xff\xad\xb3v\xb0\xff\xff\xff\xff\xbb\xf4\xb5\xb8\xff\xff\xff\xff\xbc\xbf\xb5\xb0\xff\xff\xff\xff\xbdԗ" + + "\xb8\xff\xff\xff\xff\xbe\x9f\x97\xb0\xff\xff\xff\xff\xbf\xb4y\xb8\xff\xff\xff\xff\xc0\u007fy\xb0\xff\xff\xff\xff\xc1\x94[\xb8\xff\xff\xff\xff\xc2_[\xb0\xff\xff\xff\xff\xc3}x8\xff\xff\xff\xff\xc4?=\xb0\xff\xff\xff" + + "\xff\xc5]Z8\xff\xff\xff\xff\xc6\x1f\x1f\xb0\xff\xff\xff\xff\xc7\x18R8\xff\xff\xff\xff\xc8\b<0\xff\xff\xff\xff\xc9\x1d\x1e8\xff\xff\xff\xff\xc9\xe8\x1e0\xff\xff\xff\xffʋ\x9f8\xff\xff\xff\xff\xcd\x1e\xc6" + + "0\xff\xff\xff\xff͕f(\xff\xff\xff\xff\xec\v\x85\xb0\xff\xff\xff\xff\xec\xf25(\xff\xff\xff\xff\xedEJ\xb0\xff\xff\xff\xff\xed\x85\xd6 \xff\xff\xff\xff\xf7\x13r\xb0\xff\xff\xff\xff\xf7\xfa\x1b \xff\xff\xff" + + "\xff\xfc\xfe>0\xff\xff\xff\xff\xfd\xf6\x11(\x00\x00\x00\x00\x00\x96u0\x00\x00\x00\x00\x00\xd8R \x00\x00\x00\x00\x04W\x8a\xb0\x00\x00\x00\x00\x04\xc6:\xa0\x00\x00\x00\x00\a\x96\x1b\xb0\x00\x00\x00\x00\a\xdf\xda" + + "\x98\x00\x00\x00\x00\bƟ(\x00\x00\x00\x00\tZN0\x00\x00\x00\x00\t\xdbs \x00\x00\x00\x00\r\x1a\x120\x00\x00\x00\x00\r\u007f\x87\xa0\x00\x00\x00\x00\x0e\xe7\u007f0\x00\x00\x00\x00\x0f_i\xa0\x00\x00\x00" + + "\x00\x10\xd9\xd60\x00\x00\x00\x00\x11?K\xa0\x00\x00\x00\x00\x11\x89-\xb0\x00\x00\x00\x00\x131\xa2\xa0\x00\x00\x00\x00!\xc3T0\x00\x00\x00\x00\"'x \x00\x00\x00\x00#\xa1\xe4\xb0\x00\x00\x00\x00$\x10\x94" + + "\xa0\x00\x00\x00\x00%Jg\xb0\x00\x00\x00\x00%\xe7< \x00\x00\x00\x00'!\x0f0\x00\x00\x00\x00'\xd0X\xa0\x00\x00\x00\x00)\n+\xb0\x00\x00\x00\x00)\xb0:\xa0\x00\x00\x00\x00*\xe0\xd30\x00\x00\x00" + + "\x00+\x90\x1c\xa0\x00\x00\x00\x00AL\xf60\x00\x00\x00\x00BF/\xc0\x00\x00\x00\x00CH\xa3\xd0\x00\x00\x00\x00D\x13\x9c\xc0\x00\x00\x00\x00E\x1fKP\x00\x00\x00\x00E\xf3~\xc0\x00\x00\x00\x00G\bg" + + "\xd0\x00\x00\x00\x00G\xd3`\xc0\x00\x00\x00\x00H\xe8I\xd0\x00\x00\x00\x00I\xb3B\xc0\x00\x00\x00\x00J\xc8+\xd0\x00\x00\x00\x00K\x9c_@\x00\x00\x00\x00L\xa8\r\xd0\x00\x00\x00\x00M|A@\x00\x00\x00" + + "\x00N\x87\xef\xd0\x00\x00\x00\x00O\\#@\x00\x00\x00\x00Pq\fP\x00\x00\x00\x00Q<\x05@\x00\x00\x00\x00RP\xeeP\x00\x00\x00\x00S\x1b\xe7@\x00\x00\x00\x00T0\xd0P\x00\x00\x00\x00T\xfb\xc9" + + "@\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x06\x05\x06\x05\a\x05\a\x05\x06\x05\a\x05\a\x05\b\x06\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a" + + "\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\xff\xff\xcbM\x00\x00\xff\xff\xcbM\x00\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xce\xc8\x00\f\xff\xff\xd5\xd0\x01\x12\xff\xff\xd5" + + "\xd0\x00\x12\xff\xff\xdc\xd8\x01\x16\xff\xff\xe3\xe0\x01\x1c\xff\xff\xea\xe8\x01 LMT\x00MMT\x00-04\x00-0330\x00-03\x00-0230\x00-02\x00-0130\x00\n" + + "<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS$ \x873\xf8\x03\x00\x00\xf8\x03\x00\x00\x0f\x00\x1c\x00America/Knox_INUT\t\x00\x03\x82\x0f\x8b" + + "a\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" + + "\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00]\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff^" + + "\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff" + + "\xff\xff\xff\xd5U\xd5\x00\xff\xff\xff\xff\xd6 \xcd\xf0\xff\xff\xff\xff\xd75\xb7\x00\xff\xff\xff\xff\xd8\x00\xaf\xf0\xff\xff\xff\xff\xd9\x15\x99\x00\xff\xff\xff\xff\xd9\xe0\x91\xf0\xff\xff\xff\xff\xda\xfe\xb5\x80\xff\xff\xff\xff\xdb" + + "\xc0s\xf0\xff\xff\xff\xff\xdcޗ\x80\xff\xff\xff\xffݩ\x90p\xff\xff\xff\xff\u07bey\x80\xff\xff\xff\xff߉rp\xff\xff\xff\xff\xe0\x9e[\x80\xff\xff\xff\xff\xe1iTp\xff\xff\xff\xff\xe2~=\x80\xff" + + "\xff\xff\xff\xe3I6p\xff\xff\xff\xff\xe4^\x1f\x80\xff\xff\xff\xff\xe5W<\xf0\xff\xff\xff\xff\xe6G<\x00\xff\xff\xff\xff\xe77\x1e\xf0\xff\xff\xff\xff\xe8'\x1e\x00\xff\xff\xff\xff\xe8\xf2\x16\xf0\xff\xff\xff\xff\xea" + + "\a\x00\x00\xff\xff\xff\xff\xea\xd1\xf8\xf0\xff\xff\xff\xff\xeb\xe6\xe2\x00\xff\xff\xff\xff\xec\xd6\xc4\xf0\xff\xff\xff\xff\xed\xc6\xc4\x00\xff\xff\xff\xff\xee\xbf\xe1p\xff\xff\xff\xff\xef\xaf\xe0\x80\xff\xff\xff\xff\xf0\x9f\xc3p\xff" + + "\xff\xff\xff\xf1\x8f\u0080\xff\xff\xff\xff\xf4_\x87p\xff\xff\xff\xff\xfa\xf8g\x00\xff\xff\xff\xff\xfb\xe8I\xf0\xff\xff\xff\xff\xfc\xd8I\x00\xff\xff\xff\xff\xfd\xc8+\xf0\xff\xff\xff\xff\xfe\xb8+\x00\xff\xff\xff\xff\xff" + + "\xa8\r\xf0\x00\x00\x00\x00\x00\x98\r\x00\x00\x00\x00\x00\x01\x87\xef\xf0\x00\x00\x00\x00\x02w\xef\x00\x00\x00\x00\x00\x03q\fp\x00\x00\x00\x00\x04a\v\x80\x00\x00\x00\x00\x05P\xeep\x00\x00\x00\x00\x06@\xed\x80\x00" + + "\x00\x00\x00\a0\xd0p\x00\x00\x00\x00\a\x8d'\x80\x00\x00\x00\x00\t\x10\xb2p\x00\x00\x00\x00\t\xad\xa3\x00\x00\x00\x00\x00\n\xf0\x94p\x00\x00\x00\x00\v\xe0\x93\x80\x00\x00\x00\x00\fٰ\xf0\x00\x00\x00\x00\r" + + "\xc0u\x80\x00\x00\x00\x00\x0e\xb9\x92\xf0\x00\x00\x00\x00\x0f\xa9\x92\x00\x00\x00\x00\x00\x10\x99t\xf0\x00\x00\x00\x00\x11\x89t\x00\x00\x00\x00\x00\x12yV\xf0\x00\x00\x00\x00\x13iV\x00\x00\x00\x00\x00\x14Y8\xf0\x00" + + "\x00\x00\x00\x15I8\x00\x00\x00\x00\x00\x169\x1a\xf0\x00\x00\x00\x00\x17)\x1a\x00\x00\x00\x00\x00\x18\"7p\x00\x00\x00\x00\x19\b\xfc\x00\x00\x00\x00\x00\x1a\x02\x19p\x00\x00\x00\x00\x1a\xf2\x18\x80\x00\x00\x00\x00\x1b" + + "\xe1\xfbp\x00\x00\x00\x00\x1c\xd1\xfa\x80\x00\x00\x00\x00\x1d\xc1\xddp\x00\x00\x00\x00\x1e\xb1܀\x00\x00\x00\x00\x1f\xa1\xbfp\x00\x00\x00\x00 v\x0f\x00\x00\x00\x00\x00!\x81\xa1p\x00\x00\x00\x00\"U\xf1\x00\x00" + + "\x00\x00\x00#j\xbd\xf0\x00\x00\x00\x00$5\xd3\x00\x00\x00\x00\x00%J\x9f\xf0\x00\x00\x00\x00&\x15\xb5\x00\x00\x00\x00\x00'*\x81\xf0\x00\x00\x00\x00'\xfeр\x00\x00\x00\x00)\nc\xf0\x00\x00\x00\x00D" + + "/vp\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7\x00\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x05\x01\x02\x01\xff\xff\xae\xca\x00\x00\xff\xff" + + "\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14LMT\x00CDT\x00CST\x00CWT\x00CPT\x00EST\x00\nCST6CDT" + + ",M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xe3\xc9I\xd0U\x03\x00\x00U\x03\x00\x00\x12\x00\x1c\x00America/Grand_" + + "TurkUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00L\x00" + + "\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xffi\x87\x1e0\xff\xff\xff\xff\x93\x0f\xb4\xfe\x00\x00\x00\x00\x11\x89e\xf0\x00\x00\x00\x00\x12yH\xe0\x00\x00\x00\x00\x13iG\xf0\x00\x00\x00\x00\x14Y*\xe0\x00\x00\x00\x00\x15" + + "I)\xf0\x00\x00\x00\x00\x169\f\xe0\x00\x00\x00\x00\x17)\v\xf0\x00\x00\x00\x00\x18\")`\x00\x00\x00\x00\x19\b\xed\xf0\x00\x00\x00\x00\x1a\x02\v`\x00\x00\x00\x00\x1a\xf2\np\x00\x00\x00\x00\x1b\xe1\xed`\x00" + + "\x00\x00\x00\x1c\xd1\xecp\x00\x00\x00\x00\x1d\xc1\xcf`\x00\x00\x00\x00\x1e\xb1\xcep\x00\x00\x00\x00\x1f\xa1\xb1`\x00\x00\x00\x00 v\x00\xf0\x00\x00\x00\x00!\x81\x93`\x00\x00\x00\x00\"U\xe2\xf0\x00\x00\x00\x00#" + + "j\xaf\xe0\x00\x00\x00\x00$5\xc4\xf0\x00\x00\x00\x00%J\x91\xe0\x00\x00\x00\x00&\x15\xa6\xf0\x00\x00\x00\x00'*s\xe0\x00\x00\x00\x00'\xfe\xc3p\x00\x00\x00\x00)\nU\xe0\x00\x00\x00\x00)ޥp\x00" + + "\x00\x00\x00*\xea7\xe0\x00\x00\x00\x00+\xbe\x87p\x00\x00\x00\x00,\xd3T`\x00\x00\x00\x00-\x9eip\x00\x00\x00\x00.\xb36`\x00\x00\x00\x00/~Kp\x00\x00\x00\x000\x93\x18`\x00\x00\x00\x001" + + "gg\xf0\x00\x00\x00\x002r\xfa`\x00\x00\x00\x003GI\xf0\x00\x00\x00\x004R\xdc`\x00\x00\x00\x005'+\xf0\x00\x00\x00\x0062\xbe`\x00\x00\x00\x007\a\r\xf0\x00\x00\x00\x008\x1b\xda\xe0\x00" + + "\x00\x00\x008\xe6\xef\xf0\x00\x00\x00\x009\xfb\xbc\xe0\x00\x00\x00\x00:\xc6\xd1\xf0\x00\x00\x00\x00;۞\xe0\x00\x00\x00\x00<\xaf\xeep\x00\x00\x00\x00=\xbb\x80\xe0\x00\x00\x00\x00>\x8f\xd0p\x00\x00\x00\x00?" + + "\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x00" + + "\x00\x00\x00G-_\xe0\x00\x00\x00\x00Gӊ\xf0\x00\x00\x00\x00I\rA\xe0\x00\x00\x00\x00I\xb3l\xf0\x00\x00\x00\x00J\xed#\xe0\x00\x00\x00\x00K\x9c\x89p\x00\x00\x00\x00L\xd6@`\x00\x00\x00\x00M" + + "|kp\x00\x00\x00\x00N\xb6\"`\x00\x00\x00\x00O\\Mp\x00\x00\x00\x00P\x96\x04`\x00\x00\x00\x00Q-6:30\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R6j\\J\xcf\x04\x00\x00\xcf\x04\x00\x00\v\x00\x1c\x00Asia/HebronUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e" + - "`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01" + - "\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00u\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xff}\xbdJ\x19\xff" + - "\xff\xff\xff\xc8Y\xcf\x00\xff\xff\xff\xff\xc8\xfa\xa6\x00\xff\xff\xff\xff\xc98\x9c\x80\xff\xff\xff\xff\xcc\xe5\xeb\x80\xff\xff\xff\xffͬ\xfe\x00\xff\xff\xff\xff\xce\xc7\x1f\x00\xff\xff\xff\xffϏ\x83\x00\xff\xff\xff\xff\xd0" + - "\xa9\xa4\x00\xff\xff\xff\xffф}\x00\xff\xff\xff\xffҊ׀\xff\xff\xff\xff\xd3e\xb0\x80\xff\xff\xff\xff\xd4l\v\x00\xff\xff\xff\xff\xe86c`\xff\xff\xff\xff\xe8\xf4-P\xff\xff\xff\xff\xea\v\xb9`\xff" + - "\xff\xff\xff\xea\xd5`\xd0\xff\xff\xff\xff\xeb\xec\xfa\xf0\xff\xff\xff\xff\xec\xb5m\x00\xff\xff\xff\xff\xed\xcf\u007f\xf0\xff\xff\xff\xff\xee\x97\xf2\x00\xff\xff\xff\xffﰳp\xff\xff\xff\xff\xf0y%\x80\xff\xff\xff\xff\xf1" + - "\x91\xe6\xf0\xff\xff\xff\xff\xf2ZY\x00\xff\xff\xff\xff\xf3s\x1ap\xff\xff\xff\xff\xf4;\x8c\x80\xff\xff\xff\xff\xf5U\x9fp\xff\xff\xff\xff\xf6\x1e\x11\x80\xff\xff\xff\xff\xf76\xd2\xf0\xff\xff\xff\xff\xf7\xffE\x00\xff" + - "\xff\xff\xff\xf9\x18\x06p\xff\xff\xff\xff\xf9\xe1\xca\x00\xff\xff\xff\xff\xfa\xf99\xf0\xff\xff\xff\xff\xfb'BP\x00\x00\x00\x00\b|\x8b\xe0\x00\x00\x00\x00\b\xfd\xb0\xd0\x00\x00\x00\x00\t\xf6\xea`\x00\x00\x00\x00\n" + - "\xa63\xd0\x00\x00\x00\x00\x13\xe9\xfc`\x00\x00\x00\x00\x14![`\x00\x00\x00\x00\x1a\xfa\xc6`\x00\x00\x00\x00\x1b\x8en`\x00\x00\x00\x00\x1c\xbe\xf8\xe0\x00\x00\x00\x00\x1dw|\xd0\x00\x00\x00\x00\x1e\xcc\xff`\x00" + - "\x00\x00\x00\x1f`\x99P\x00\x00\x00\x00 \x82\xb1`\x00\x00\x00\x00!I\xb5\xd0\x00\x00\x00\x00\"^\x9e\xe0\x00\x00\x00\x00# ]P\x00\x00\x00\x00$Z0`\x00\x00\x00\x00%\x00?P\x00\x00\x00\x00&" + - "\v\xed\xe0\x00\x00\x00\x00&\xd6\xe6\xd0\x00\x00\x00\x00'\xeb\xcf\xe0\x00\x00\x00\x00(\xc0\x03P\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xa9\x1f\xd0\x00\x00\x00\x00+\xbbe\xe0\x00\x00\x00\x00,\x89\x01\xd0\x00" + - "\x00\x00\x00-\x9bG\xe0\x00\x00\x00\x00._\xa9P\x00\x00\x00\x00/{)\xe0\x00\x00\x00\x000H\xc5\xd0\x00\x00\x00\x000\xe7\a\xe0\x00\x00\x00\x001dF`\x00\x00\x00\x002A\xc2`\x00\x00\x00\x003" + - "D(`\x00\x00\x00\x004!\xa4`\x00\x00\x00\x005$\n`\x00\x00\x00\x006\x01\x86`\x00\x00\x00\x007\x16a`\x00\x00\x00\x008\x06DP\x00\x00\x00\x008\xff}\xe0\x00\x00\x00\x009\xef`\xd0\x00" + - "\x00\x00\x00:\xdf_\xe0\x00\x00\x00\x00;\xcfB\xd0\x00\x00\x00\x00<\xbfA\xe0\x00\x00\x00\x00=\xaf$\xd0\x00\x00\x00\x00>\x9f#\xe0\x00\x00\x00\x00?\x8f\x06\xd0\x00\x00\x00\x00@\u007f\x05\xe0\x00\x00\x00\x00A" + - "\\\x81\xe0\x00\x00\x00\x00B^\xe7\xe0\x00\x00\x00\x00CA\xb7\xf0\x00\x00\x00\x00D-\xa6`\x00\x00\x00\x00E\x12\xfdP\x00\x00\x00\x00F\x0e\xd9\xe0\x00\x00\x00\x00F\xe8op\x00\x00\x00\x00G\xec\x18\xe0\x00" + - "\x00\x00\x00H\xbb\x06P\x00\x00\x00\x00I\xcb\xfa\xe0\x00\x00\x00\x00J\xa0<`\x00\x00\x00\x00K\xab\xdc\xe0\x00\x00\x00\x00La\xbd\xd0\x00\x00\x00\x00M\x94\xf9\x9c\x00\x00\x00\x00N5\xc2P\x00\x00\x00\x00N" + - "\\\v\xe0\x00\x00\x00\x00N\x84\xdcP\x00\x00\x00\x00Ot\xdb`\x00\x00\x00\x00P[\x91\xe0\x00\x00\x00\x00QT\xbd`\x00\x00\x00\x00RD\xa0P\x00\x00\x00\x00S4\x9f`\x00\x00\x00\x00TIlP\x00" + - "\x00\x00\x00U\x15\xd2\xe0\x00\x00\x00\x00V)\\`\x00\x00\x00\x00V\xf5\xc2\xf0\x00\x00\x00\x00X\x13\xca`\x00\x00\x00\x00Xդ\xf0\x00\x00\x00\x00Y\xf3\xac`\x00\x00\x00\x00Z\xb5\x86\xf0\x00\x00\x00\x00[" + - "ӎ`\x00\x00\x00\x00\\\x9dC\xe0\x00\x00\x00\x00]\xb3bP\x00\x00\x00\x00^~w`\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00 \xe7\x00\x00\x00\x00*0\x01\x04\x00\x00\x1c \x00\t\x00\x00*0\x01\r\x00\x00\x1c \x00\x11LMT\x00EE" + - "ST\x00EET\x00IDT\x00IST\x00\nEET-2EEST,M3.4.4/48,M10.4.4/49\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9" + - "R*\xe4@\xa9\x89\x01\x00\x00\x89\x01\x00\x00\x0e\x00\x1c\x00Asia/ChongqingUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00T" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffi\x87&X\xff\xff\xff\xff\xb6\xa4B\x18\x00\x00\x00\x00+\x16\xfc\xd0\x00" + + "\x00\x00\x00+q\xe6@\x01\x03\x02\x03\xff\xff\xb5(\x00\x00\xff\xff\xb6h\x00\x04\xff\xff\xc7\xc0\x01\b\xff\xff\xb9\xb0\x00\fLMT\x00QMT\x00-04\x00-05\x00\n<-05>5\nP" + + "K\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x01\x05\xf3\x89\xb5\x00\x00\x00\xb5\x00\x00\x00\x0e\x00\x1c\x00America/GuyanaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00" + + "\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00" + + "\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xff\x92\x1d\x0f\x87\xff\xff\xff\xff\x98\xd9" + + "{@\x00\x00\x00\x00\n\u007f\x05\xbc\x00\x00\x00\x00)\xd5@\xc0\x01\x02\x03\x01\xff\xff\xc9y\x00\x00\xff\xff\xc7\xc0\x00\x04\xff\xff\xcbD\x00\b\xff\xff\xd5\xd0\x00\x0eLMT\x00-04\x00-0345\x00" + + "-03\x00\n<-04>4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\a\x1c\x9e\x9a]\x04\x00\x00]\x04\x00\x00\x0e\x00\x1c\x00America/HavanaUT\t\x00" + + "\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\x00\x00\x00\x04\x00\x00\x00\x10\xff" + + "\xff\xff\xffi\x87(\xb8\xff\xff\xff\xff\xacb\u0080\xff\xff\xff\xff\xb1ӔP\xff\xff\xff\xff\xb2t]@\xff\xff\xff\xff\xc8[f\xd0\xff\xff\xff\xff\xc8\xd3Q@\xff\xff\xff\xff\xca;H\xd0\xff\xff\xff\xff\xca" + + "\xbcm\xc0\xff\xff\xff\xff\xcc$eP\xff\xff\xff\xff̜O\xc0\xff\xff\xff\xff\xd1\xc4\vP\xff\xff\xff\xff\xd2;\xf5\xc0\xff\xff\xff\xffӣ\xedP\xff\xff\xff\xff\xd4\x1b\xd7\xc0\xff\xff\xff\xff\xf7`\x05\xd0\xff" + + "\xff\xff\xff\xf7\xff}@\xff\xff\xff\xff\xf9=D\xd0\xff\xff\xff\xff\xf9\xe3S\xc0\xff\xff\xff\xff\xfa\xdb;\xd0\xff\xff\xff\xff\xfb\xa7\x86@\xff\xff\xff\xff\xfcũ\xd0\xff\xff\xff\xff\xfd\x87h@\xff\xff\xff\xff\xfe" + + "\xb8\x00\xd0\xff\xff\xff\xff\xff\xa7\xe3\xc0\x00\x00\x00\x00\x00\x97\xe2\xd0\x00\x00\x00\x00\x01\x87\xc5\xc0\x00\x00\x00\x00\x02w\xc4\xd0\x00\x00\x00\x00\x03p\xe2@\x00\x00\x00\x00\x04`\xe1P\x00\x00\x00\x00\x055\x14\xc0\x00" + + "\x00\x00\x00\x06@\xc3P\x00\x00\x00\x00\a\x16H@\x00\x00\x00\x00\b \xa5P\x00\x00\x00\x00\b\xf7{\xc0\x00\x00\x00\x00\n\x00\x87P\x00\x00\x00\x00\n\xf0j@\x00\x00\x00\x00\v\xe0iP\x00\x00\x00\x00\f" + + "ن\xc0\x00\x00\x00\x00\r\xc0KP\x00\x00\x00\x00\x0e\xb9h\xc0\x00\x00\x00\x00\x0f\xb2\xa2P\x00\x00\x00\x00\x10}\x9b@\x00\x00\x00\x00\x11Q\xea\xd0\x00\x00\x00\x00\x12f\xb7\xc0\x00\x00\x00\x00\x131\xcc\xd0\x00" + + "\x00\x00\x00\x14F\x99\xc0\x00\x00\x00\x00\x15[\x82\xd0\x00\x00\x00\x00\x16&{\xc0\x00\x00\x00\x00\x17;d\xd0\x00\x00\x00\x00\x18\x06]\xc0\x00\x00\x00\x00\x19\x1bF\xd0\x00\x00\x00\x00\x19\xe6?\xc0\x00\x00\x00\x00\x1a" + + "\xfb(\xd0\x00\x00\x00\x00\x1b\xcf\\@\x00\x00\x00\x00\x1c\xdb\n\xd0\x00\x00\x00\x00\x1d\xaf>@\x00\x00\x00\x00\x1ezSP\x00\x00\x00\x00\x1f\x8f @\x00\x00\x00\x00 Z5P\x00\x00\x00\x00!o\x02@\x00" + + "\x00\x00\x00\"CQ\xd0\x00\x00\x00\x00#N\xe4@\x00\x00\x00\x00$#3\xd0\x00\x00\x00\x00%.\xc6@\x00\x00\x00\x00&\x15\x8a\xd0\x00\x00\x00\x00'\x17\xe2\xc0\x00\x00\x00\x00'\xfe\xa7P\x00\x00\x00\x00(" + + "\xf7\xd2\xd0\x00\x00\x00\x00)މP\x00\x00\x00\x00*״\xd0\x00\x00\x00\x00+\xbekP\x00\x00\x00\x00,\xb7\x96\xd0\x00\x00\x00\x00-\x9eMP\x00\x00\x00\x00.\x97x\xd0\x00\x00\x00\x00/~/P\x00" + + "\x00\x00\x000wZ\xd0\x00\x00\x00\x001gK\xd0\x00\x00\x00\x002W<\xd0\x00\x00\x00\x003G-\xd0\x00\x00\x00\x004@YP\x00\x00\x00\x005\x1d\xd5P\x00\x00\x00\x0062\xb0P\x00\x00\x00\x006" + + "\xfd\xb7P\x00\x00\x00\x008\x1b\xcc\xd0\x00\x00\x00\x008\xe6\xd3\xd0\x00\x00\x00\x009\xfb\xae\xd0\x00\x00\x00\x00:Ƶ\xd0\x00\x00\x00\x00;ې\xd0\x00\x00\x00\x00<\xaf\xd2P\x00\x00\x00\x00=\xbbr\xd0\x00" + + "\x00\x00\x00>\x8f\xb4P\x00\x00\x00\x00?\x9bT\xd0\x00\x00\x00\x00@f[\xd0\x00\x00\x00\x00ED5P\x00\x00\x00\x00E\xf3\x8c\xd0\x00\x00\x00\x00G$\x17P\x00\x00\x00\x00GܩP\x00\x00\x00\x00I" + + "\x03\xf9P\x00\x00\x00\x00I\xb3P\xd0\x00\x00\x00\x00J\xe3\xdbP\x00\x00\x00\x00K\x9cmP\x00\x00\x00\x00L\xcc\xf7\xd0\x00\x00\x00\x00M\x85\x89\xd0\x00\x00\x00\x00N\xbfN\xd0\x00\x00\x00\x00Ow\xe0\xd0\x00" + + "\x00\x00\x00P\x95\xf6P\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\xff\xff\xb2\xc8\x00\x00\xff" + + "\xff\xb2\xc0\x00\x04\xff\xff\xc7\xc0\x01\b\xff\xff\xb9\xb0\x00\fLMT\x00HMT\x00CDT\x00CST\x00\nCST5CDT,M3.2.0/0,M11.1.0/1" + + "\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSOKjǪ\x02\x00\x00\xaa\x02\x00\x00\r\x00\x1c\x00America/BahiaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v" + + "\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00" + + "\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96\xaak\x1c\xff\xff\xff\xff\xb8" + + "\x0fI\xe0\xff\xff\xff\xff\xb8\xfd@\xa0\xff\xff\xff\xff\xb9\xf140\xff\xff\xff\xff\xba\xdet \xff\xff\xff\xff\xda8\xae0\xff\xff\xff\xff\xda\xeb\xfa0\xff\xff\xff\xff\xdc\x19\xe1\xb0\xff\xff\xff\xffܹY \xff" + + "\xff\xff\xff\xdd\xfb\x150\xff\xff\xff\xffޛ\xde \xff\xff\xff\xff\xdfݚ0\xff\xff\xff\xff\xe0T3 \xff\xff\xff\xff\xf4\x97\xff\xb0\xff\xff\xff\xff\xf5\x05^ \xff\xff\xff\xff\xf6\xc0d0\xff\xff\xff\xff\xf7" + + "\x0e\x1e\xa0\xff\xff\xff\xff\xf8Q,0\xff\xff\xff\xff\xf8\xc7\xc5 \xff\xff\xff\xff\xfa\nҰ\xff\xff\xff\xff\xfa\xa8\xf8\xa0\xff\xff\xff\xff\xfb\xec\x060\xff\xff\xff\xff\xfc\x8b}\xa0\x00\x00\x00\x00\x1dɎ0\x00" + + "\x00\x00\x00\x1exנ\x00\x00\x00\x00\x1f\xa05\xb0\x00\x00\x00\x00 3Ϡ\x00\x00\x00\x00!\x81i0\x00\x00\x00\x00\"\vȠ\x00\x00\x00\x00#X\x10\xb0\x00\x00\x00\x00#\xe2p \x00\x00\x00\x00%" + + "7\xf2\xb0\x00\x00\x00\x00%\xd4\xc7 \x00\x00\x00\x00'!\x0f0\x00\x00\x00\x00'\xbd\xe3\xa0\x00\x00\x00\x00)\x00\xf10\x00\x00\x00\x00)\x94\x8b \x00\x00\x00\x00*\xea\r\xb0\x00\x00\x00\x00+k2\xa0\x00" + + "\x00\x00\x00,\xc0\xb50\x00\x00\x00\x00-f\xc4 \x00\x00\x00\x00.\xa0\x970\x00\x00\x00\x00/F\xa6 \x00\x00\x00\x000\x80y0\x00\x00\x00\x001\x1dM\xa0\x00\x00\x00\x002W \xb0\x00\x00\x00\x003" + + "\x06j \x00\x00\x00\x0048T0\x00\x00\x00\x004\xf8\xc1 \x00\x00\x00\x006 \x1f0\x00\x00\x00\x006\xcfh\xa0\x00\x00\x00\x007\xf6ư\x00\x00\x00\x008\xb8\x85 \x00\x00\x00\x009\xdf\xe30\x00" + + "\x00\x00\x00:\x8f,\xa0\x00\x00\x00\x00;\xc8\xff\xb0\x00\x00\x00\x00N\xf0\xa0\x00\x00\x00\x00N\x9aH\xb0\x00\x00\x00\x00OI\x92 \x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xff\xdb\xe4" + + "\x00\x00\xff\xff\xe3\xe0\x01\x04\xff\xff\xd5\xd0\x00\bLMT\x00-02\x00-03\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00" + + "\x0f\x00\x1c\x00America/AntiguaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffz敹\xff\xff\xff\xff\xcb\xf62\xc0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\x01\x03\x02\x01\xff\xff" + + "\xc2\a\x00\x00\xff\xff\xc7\xc0\x00\x04\xff\xff\xd5\xd0\x01\b\xff\xff\xd5\xd0\x01\fLMT\x00AST\x00APT\x00AWT\x00\nAST4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSU\r" + + "\xf7\xd3\xc7\x01\x00\x00\xc7\x01\x00\x00\r\x00\x1c\x00America/ThuleUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\"\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x9b\x80w\xfc\x00\x00\x00\x00'\xf5z\xe0\x00\x00\x00\x00(\xe5]\xd0\x00\x00\x00\x00)\xd5" + + "\\\xe0\x00\x00\x00\x00*\xc5?\xd0\x00\x00\x00\x00+\xbey`\x00\x00\x00\x00,\xd3FP\x00\x00\x00\x00-\x9e[`\x00\x00\x00\x00.\xb3(P\x00\x00\x00\x00/~=`\x00\x00\x00\x000\x93\nP\x00\x00" + + "\x00\x001gY\xe0\x00\x00\x00\x002r\xecP\x00\x00\x00\x003G;\xe0\x00\x00\x00\x004R\xceP\x00\x00\x00\x005'\x1d\xe0\x00\x00\x00\x0062\xb0P\x00\x00\x00\x007\x06\xff\xe0\x00\x00\x00\x008\x1b" + + "\xcc\xd0\x00\x00\x00\x008\xe6\xe1\xe0\x00\x00\x00\x009\xfb\xae\xd0\x00\x00\x00\x00:\xc6\xc3\xe0\x00\x00\x00\x00;ې\xd0\x00\x00\x00\x00<\xaf\xe0`\x00\x00\x00\x00=\xbbr\xd0\x00\x00\x00\x00>\x8f\xc2`\x00\x00" + + "\x00\x00?\x9bT\xd0\x00\x00\x00\x00@o\xa4`\x00\x00\x00\x00A\x84qP\x00\x00\x00\x00BO\x86`\x00\x00\x00\x00CdSP\x00\x00\x00\x00D/h`\x00\x00\x00\x00ED5P\x00\x00\x00\x00E\xf3" + + "\x9a\xe0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xbf\x84\x00\x00\xff\xff\xd5\xd0\x01\x04\xff\xff\xc7\xc0\x00\bLMT\x00AD" + + "T\x00AST\x00\nAST4ADT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\v\x00\x1c\x00" + + "Antarctica/UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xcfׇ\xe1\x85\x00\x00" + + "\x00\x85\x00\x00\x00\x10\x00\x1c\x00Antarctica/SyowaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\xd5\x1b6\xb4\x01\x00\x00+\xcc\x00\x00\x00\x00*0\x00\x04LMT\x00+03\x00\n<+" + + "03>-3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xc2\v\xae\b\x85\x00\x00\x00\x85\x00\x00\x00\x11\x00\x1c\x00Antarctica/VostokUT\t\x00\x03\x82\x0f" + + "\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff" + + "\xe9X\x89\x80\x01\x00\x00\x00\x00\x00\x00\x00\x00T`\x00\x04-00\x00+06\x00\n<+06>-6\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x95\xea\x06\xd3\xc5\x00\x00\x00\xc5\x00\x00\x00" + + "\x10\x00\x1c\x00Antarctica/DavisUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\xe7\x9c@\x00\xff\xff\xff\xff\xf6G\xdf\x10\xff\xff\xff\xff\xfeG\xab\x00\x00\x00\x00\x00J\xda\x140\x00\x00\x00\x00K" + + "\x97\xfa@\x00\x00\x00\x00N\xa9\xaa0\x00\x00\x00\x00OC\xf7\xc0\x01\x00\x01\x02\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00bp\x00\x04\x00\x00FP\x00\b-00\x00+07\x00+05\x00\n<+0" + + "7>-7\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSb\xb2\xaf\xf7\x13\x04\x00\x00\x13\x04\x00\x00\x12\x00\x1c\x00Antarctica/McMurdoUT\t\x00\x03\x82\x0f" + + "\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x00\x00\x00\x06\x00\x00\x00\x13\xff\xff\xff\xff" + + "A\xb7L\xa8\xff\xff\xff\xff\xb0\xb4\xb2\xe8\xff\xff\xff\xff\xb1Q\x87X\xff\xff\xff\xff\xb2x\xe5h\xff\xff\xff\xff\xb3C\xe5`\xff\xff\xff\xff\xb4X\xc7h\xff\xff\xff\xff\xb5#\xc7`\xff\xff\xff\xff\xb68\xa9h" + + "\xff\xff\xff\xff\xb7\x03\xa9`\xff\xff\xff\xff\xb8\x18\x8bh\xff\xff\xff\xff\xb8\xec\xc5\xe0\xff\xff\xff\xff\xb9\xf8mh\xff\xff\xff\xff\xba̧\xe0\xff\xff\xff\xff\xbb\xd8Oh\xff\xff\xff\xff\xbc\xe3\xe8\xe0\xff\xff\xff\xff" + + "\xbd\xae\xf6\xe8\xff\xff\xff\xff\xbe\xc3\xca\xe0\xff\xff\xff\xff\xbf\x8e\xd8\xe8\xff\xff\xff\xff\xc0\xa3\xac\xe0\xff\xff\xff\xff\xc1n\xba\xe8\xff\xff\xff\xff\u0083\x8e\xe0\xff\xff\xff\xff\xc3N\x9c\xe8\xff\xff\xff\xff\xc4cp\xe0" + + "\xff\xff\xff\xff\xc5.~\xe8\xff\xff\xff\xff\xc6L\x8d`\xff\xff\xff\xff\xc7\x0e`\xe8\xff\xff\xff\xff\xc8,o`\xff\xff\xff\xff\xc8\xf7}h\xff\xff\xff\xff\xd2ښ@\x00\x00\x00\x00\t\x18\xfd\xe0\x00\x00\x00\x00" + + "\t\xac\xa5\xe0\x00\x00\x00\x00\n\xef\xa5`\x00\x00\x00\x00\v\x9e\xfc\xe0\x00\x00\x00\x00\f\xd8\xc1\xe0\x00\x00\x00\x00\r~\xde\xe0\x00\x00\x00\x00\x0e\xb8\xa3\xe0\x00\x00\x00\x00\x0f^\xc0\xe0\x00\x00\x00\x00\x10\x98\x85\xe0" + + "\x00\x00\x00\x00\x11>\xa2\xe0\x00\x00\x00\x00\x12xg\xe0\x00\x00\x00\x00\x13\x1e\x84\xe0\x00\x00\x00\x00\x14XI\xe0\x00\x00\x00\x00\x14\xfef\xe0\x00\x00\x00\x00\x168+\xe0\x00\x00\x00\x00\x16\xe7\x83`\x00\x00\x00\x00" + + "\x18!H`\x00\x00\x00\x00\x18\xc7e`\x00\x00\x00\x00\x1a\x01*`\x00\x00\x00\x00\x1a\xa7G`\x00\x00\x00\x00\x1b\xe1\f`\x00\x00\x00\x00\x1c\x87)`\x00\x00\x00\x00\x1d\xc0\xee`\x00\x00\x00\x00\x1eg\v`" + + "\x00\x00\x00\x00\x1f\xa0\xd0`\x00\x00\x00\x00 F\xed`\x00\x00\x00\x00!\x80\xb2`\x00\x00\x00\x00\"0\t\xe0\x00\x00\x00\x00#i\xce\xe0\x00\x00\x00\x00$\x0f\xeb\xe0\x00\x00\x00\x00%.\x01`\x00\x00\x00\x00" + + "&\x02B\xe0\x00\x00\x00\x00'\r\xe3`\x00\x00\x00\x00'\xe2$\xe0\x00\x00\x00\x00(\xed\xc5`\x00\x00\x00\x00)\xc2\x06\xe0\x00\x00\x00\x00*ͧ`\x00\x00\x00\x00+\xab#`\x00\x00\x00\x00,\xad\x89`" + + "\x00\x00\x00\x00-\x8b\x05`\x00\x00\x00\x00.\x8dk`\x00\x00\x00\x00/j\xe7`\x00\x00\x00\x000mM`\x00\x00\x00\x001J\xc9`\x00\x00\x00\x002Vi\xe0\x00\x00\x00\x003*\xab`\x00\x00\x00\x00" + + "46K\xe0\x00\x00\x00\x005\n\x8d`\x00\x00\x00\x006\x16-\xe0\x00\x00\x00\x006\xf3\xa9\xe0\x00\x00\x00\x007\xf6\x0f\xe0\x00\x00\x00\x008Ӌ\xe0\x00\x00\x00\x009\xd5\xf1\xe0\x00\x00\x00\x00:\xb3m\xe0" + + "\x00\x00\x00\x00;\xbf\x0e`\x00\x00\x00\x00<\x93O\xe0\x00\x00\x00\x00=\x9e\xf0`\x00\x00\x00\x00>s1\xe0\x00\x00\x00\x00?~\xd2`\x00\x00\x00\x00@\\N`\x00\x00\x00\x00A^\xb4`\x00\x00\x00\x00" + + "B<0`\x00\x00\x00\x00C>\x96`\x00\x00\x00\x00D\x1c\x12`\x00\x00\x00\x00E\x1ex`\x00\x00\x00\x00E\xfb\xf4`\x00\x00\x00\x00F\xfeZ`\x02\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04" + + "\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x00\x00\xa3\xd8\x00\x00\x00\x00\xaf\xc8\x01\x04\x00\x00\xa1\xb8\x00\t\x00\x00\xa8\xc0\x01\x04\x00\x00\xb6\xd0\x01\x0e\x00\x00\xa8\xc0\x00\x04LMT\x00" + + "NZST\x00NZMT\x00NZDT\x00\nNZST-12NZDT,M9.5.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x95{" + + "\xf3\xa9w\x03\x00\x00w\x03\x00\x00\x11\x00\x1c\x00Antarctica/PalmerUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00T" + "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff~6C)\xff\xff\xff\xff\xa0\x97\xa2\x80\xff\xff\xff\xff\xa1y\x04\xf0\xff\xff" + - "\xff\xff\xc8Y^\x80\xff\xff\xff\xff\xc9\t\xf9p\xff\xff\xff\xff\xc9ӽ\x00\xff\xff\xff\xff\xcb\x05\x8a\xf0\xff\xff\xff\xff\xcb|@\x00\xff\xff\xff\xff\xd2;>\xf0\xff\xff\xff\xffӋ{\x80\xff\xff\xff\xff\xd4B" + - "\xad\xf0\xff\xff\xff\xff\xd5E\"\x00\xff\xff\xff\xff\xd6L\xbf\xf0\xff\xff\xff\xff\xd7<\xbf\x00\xff\xff\xff\xff\xd8\x06fp\xff\xff\xff\xff\xd9\x1d\xf2\x80\xff\xff\xff\xff\xd9A|\xf0\x00\x00\x00\x00\x1e\xbaR \x00\x00" + - "\x00\x00\x1fi\x9b\x90\x00\x00\x00\x00 ~\x84\xa0\x00\x00\x00\x00!I}\x90\x00\x00\x00\x00\"g\xa1 \x00\x00\x00\x00#)_\x90\x00\x00\x00\x00$G\x83 \x00\x00\x00\x00%\x12|\x10\x00\x00\x00\x00&'" + - "e \x00\x00\x00\x00&\xf2^\x10\x00\x00\x00\x00(\aG \x00\x00\x00\x00(\xd2@\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00q\xd7\x00" + - "\x00\x00\x00~\x90\x01\x04\x00\x00p\x80\x00\bLMT\x00CDT\x00CST\x00\nCST-8\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R'\xe2\\\xff\x9f\x00\x00\x00\x9f\x00\x00\x00\n\x00" + - "\x1c\x00Asia/KabulUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xffi\x86\x9a\xa0\xff\xff\xff\xff\xd0\xf9\xd7@\x01\x02\x00\x00@\xe0\x00\x00\x00\x008@\x00\x04\x00\x00?H\x00\bLMT\x00+04\x00+" + - "0430\x00\n<+0430>-4:30\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xdav\x19z\x98\x00\x00\x00\x98\x00\x00\x00\f\x00\x1c\x00Asia/Bahrai" + - "nUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03" + - "\x00\x00\x00\f\xff\xff\xff\xff\xa1\xf2\x9d0\x00\x00\x00\x00\x04\x8a\x92\xc0\x01\x02\x00\x000P\x00\x00\x00\x008@\x00\x04\x00\x00*0\x00\bLMT\x00+04\x00+03\x00\n<+03>-3" + - "\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xf9l\x03\x12\xf8\x02\x00\x00\xf8\x02\x00\x00\f\x00\x1c\x00Asia/IrkutskUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00" + - "\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00" + - "\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00B\x00\x00\x00\a\x00\x00\x00\x14\xff\xff\xff\xffV\xb6\x82?\xff\xff\xff\xff\xa2\x12" + - "\x0f\xbf\xff\xff\xff\xff\xb5\xa3\xd3\x10\x00\x00\x00\x00\x15'a\x80\x00\x00\x00\x00\x16\x18\x95\xf0\x00\x00\x00\x00\x17\b\x95\x00\x00\x00\x00\x00\x17\xf9\xc9p\x00\x00\x00\x00\x18\xe9Ȁ\x00\x00\x00\x00\x19\xda\xfc\xf0\x00\x00" + - "\x00\x00\x1a\xccM\x80\x00\x00\x00\x00\x1b\xbcZ\xa0\x00\x00\x00\x00\x1c\xacK\xa0\x00\x00\x00\x00\x1d\x9c<\xa0\x00\x00\x00\x00\x1e\x8c-\xa0\x00\x00\x00\x00\x1f|\x1e\xa0\x00\x00\x00\x00 l\x0f\xa0\x00\x00\x00\x00!\\" + - "\x00\xa0\x00\x00\x00\x00\"K\xf1\xa0\x00\x00\x00\x00#;\xe2\xa0\x00\x00\x00\x00$+Ӡ\x00\x00\x00\x00%\x1bĠ\x00\x00\x00\x00&\v\xb5\xa0\x00\x00\x00\x00'\x04\xe1 \x00\x00\x00\x00'\xf4\xd2 \x00\x00" + - "\x00\x00(\xe4\xd10\x00\x00\x00\x00)xy0\x00\x00\x00\x00)Դ \x00\x00\x00\x00*ĥ \x00\x00\x00\x00+\xb4\x96 \x00\x00\x00\x00,\xa4\x87 \x00\x00\x00\x00-\x94x \x00\x00\x00\x00.\x84" + - "i \x00\x00\x00\x00/tZ \x00\x00\x00\x000dK \x00\x00\x00\x001]v\xa0\x00\x00\x00\x002rQ\xa0\x00\x00\x00\x003=X\xa0\x00\x00\x00\x004R3\xa0\x00\x00\x00\x005\x1d:\xa0\x00\x00" + - "\x00\x0062\x15\xa0\x00\x00\x00\x006\xfd\x1c\xa0\x00\x00\x00\x008\x1b2 \x00\x00\x00\x008\xdc\xfe\xa0\x00\x00\x00\x009\xfb\x14 \x00\x00\x00\x00:\xbc\xe0\xa0\x00\x00\x00\x00;\xda\xf6 \x00\x00\x00\x00<\xa5" + - "\xfd \x00\x00\x00\x00=\xba\xd8 \x00\x00\x00\x00>\x85\xdf \x00\x00\x00\x00?\x9a\xba \x00\x00\x00\x00@e\xc1 \x00\x00\x00\x00A\x83֠\x00\x00\x00\x00BE\xa3 \x00\x00\x00\x00Cc\xb8\xa0\x00\x00" + - "\x00\x00D%\x85 \x00\x00\x00\x00EC\x9a\xa0\x00\x00\x00\x00F\x05g \x00\x00\x00\x00G#|\xa0\x00\x00\x00\x00G\ue0e0\x00\x00\x00\x00I\x03^\xa0\x00\x00\x00\x00I\xcee\xa0\x00\x00\x00\x00J\xe3" + - "@\xa0\x00\x00\x00\x00K\xaeG\xa0\x00\x00\x00\x00L\xcc] \x00\x00\x00\x00M\x8e)\xa0\x00\x00\x00\x00TK\xd7\x10\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x05\x02\x04" + - "\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x06\x04\x00\x00a\xc1\x00\x00\x00\x00a\xc1\x00\x04\x00\x00bp\x00\b\x00\x00" + - "~\x90\x01\f\x00\x00p\x80\x00\x10\x00\x00p\x80\x01\x10\x00\x00~\x90\x00\fLMT\x00IMT\x00+07\x00+09\x00+08\x00\n<+08>-8\nPK\x03\x04\n\x00\x00\x00\x00" + - "\x00\xf1c9RO\xb0\x03\xe9\xe5\x02\x00\x00\xe5\x02\x00\x00\f\x00\x1c\x00Asia/YakutskUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00R\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xf6\x98\xad\x00\xff\xff\xff\xff\xf6柰\xff\xff\xff\xff\xf8\x13C\xc0\xff\xff" + + "\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xf9\xf4w@\xff\xff\xff\xff\xfa\xd36\xb0\xff\xff\xff\xff\xfb\xc35\xc0\xff\xff\xff\xff\xfc\xbcS0\xff\xff\xff\xff\xfd\xacR@\xff\xff\xff\xff\xfe\x9c50\xff\xff\xff\xff\xff\x8c" + + "4@\x00\x00\x00\x00\a\xa3J\xb0\x00\x00\x00\x00\b$o\xa0\x00\x00\x00\x00\x170\xbc\xb0\x00\x00\x00\x00\x18\x06]\xc0\x00\x00\x00\x00\x18\xd1V\xb0\x00\x00\x00\x00\x19\xe6?\xc0\x00\x00\x00\x00\x1a\xb18\xb0\x00\x00" + + "\x00\x00\x1b\xcf\\@\x00\x00\x00\x00\x1c\x91\x1a\xb0\x00\x00\x00\x00\x1d\xaf>@\x00\x00\x00\x00\x1ep\xfc\xb0\x00\x00\x00\x00\x1f\x8f @\x00\x00\x00\x00 \u007f\x030\x00\x00\x00\x00!o\x02@\x00\x00\x00\x00\"9" + + "\xfb0\x00\x00\x00\x00#N\xe4@\x00\x00\x00\x00$\x19\xdd0\x00\x00\x00\x00%8\x00\xc0\x00\x00\x00\x00%\xf9\xbf0\x00\x00\x00\x00&\xf2\xf8\xc0\x00\x00\x00\x00'١0\x00\x00\x00\x00(\xf7\xc4\xc0\x00\x00" + + "\x00\x00)½\xb0\x00\x00\x00\x00*צ\xc0\x00\x00\x00\x00+\xa2\x9f\xb0\x00\x00\x00\x00,\xb7\x88\xc0\x00\x00\x00\x00-\x82\x81\xb0\x00\x00\x00\x00.\x97j\xc0\x00\x00\x00\x00/bc\xb0\x00\x00\x00\x000\x80" + + "\x87@\x00\x00\x00\x001BE\xb0\x00\x00\x00\x002`i@\x00\x00\x00\x003=\xd70\x00\x00\x00\x004@K@\x00\x00\x00\x005\vD0\x00\x00\x00\x006\r\xb8@\x00\x00\x00\x007\x06հ\x00\x00" + + "\x00\x008\x00\x0f@\x00\x00\x00\x008\xcb\b0\x00\x00\x00\x009\xe9+\xc0\x00\x00\x00\x00:\xaa\xea0\x00\x00\x00\x00;\xc9\r\xc0\x00\x00\x00\x00<\x8a\xcc0\x00\x00\x00\x00=\xa8\xef\xc0\x00\x00\x00\x00>j" + + "\xae0\x00\x00\x00\x00?\x88\xd1\xc0\x00\x00\x00\x00@Sʰ\x00\x00\x00\x00Ah\xb3\xc0\x00\x00\x00\x00B3\xac\xb0\x00\x00\x00\x00CH\x95\xc0\x00\x00\x00\x00D\x13\x8e\xb0\x00\x00\x00\x00E1\xb2@\x00\x00" + + "\x00\x00E\xf3p\xb0\x00\x00\x00\x00G\x11\x94@\x00\x00\x00\x00G\xef\x020\x00\x00\x00\x00H\xf1v@\x00\x00\x00\x00I\xbco0\x00\x00\x00\x00J\xd1X@\x00\x00\x00\x00K\xb8\x00\xb0\x00\x00\x00\x00L\xb1" + + ":@\x00\x00\x00\x00M\xc6\a0\x00\x00\x00\x00NP\x82\xc0\x00\x00\x00\x00O\x9c\xae\xb0\x00\x00\x00\x00PB\xd9\xc0\x00\x00\x00\x00Q|\x90\xb0\x00\x00\x00\x00R+\xf6@\x00\x00\x00\x00S\\r\xb0\x00\x00" + + "\x00\x00T\v\xd8@\x00\x00\x00\x00W7\xe60\x00\x00\x00\x00W\xaf\xec\xc0\x00\x00\x00\x00XC\x86\xb0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x04\x03\x04\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x04\x00\x00\x00\x00\x00\x00\xff\xff" + + "\xc7\xc0\x00\x04\xff\xff\xd5\xd0\x01\b\xff\xff\xe3\xe0\x01\f\xff\xff\xd5\xd0\x00\b-00\x00-04\x00-03\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS" + + ":\xc8P7\xb1\x00\x00\x00\xb1\x00\x00\x00\x10\x00\x1c\x00Antarctica/TrollUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00" + + "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\x00\x00\x00\x00B\rG\x00\x00\x00\x00\x00BF\x05\x90\x02\x01\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x1c \x01\x04\x00\x00\x00\x00\x00\b-00\x00+02\x00+00\x00\n<+00>0<+02>-2,M3.5.0/1,M10.5.0/3\nPK\x03" + + "\x04\n\x00\x00\x00\x00\x00#\x82iSƉ\xf71\x84\x00\x00\x00\x84\x00\x00\x00\x12\x00\x1c\x00Antarctica/RotheraUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux" + + "\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00" + + "\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\x00\x00\x00\x00\r\x02-\x00\x01\x00\x00\x00" + + "\x00\x00\x00\xff\xff\xd5\xd0\x00\x04-00\x00-03\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSn\x04\x19y\x9a\x00\x00\x00\x9a\x00\x00\x00\x19\x00\x1c\x00Antar" + + "ctica/DumontDUrvilleUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff\xffV\xb6Z\b\xff\xff\xff\xffr\xed\xa4\x90\x01\x02\x00\x00\x89\xf8\x00\x00\x00\x00\x89\xf0\x00\x04\x00\x00\x8c\xa0\x00\tL" + + "MT\x00PMMT\x00+10\x00\n<+10>-10\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSb\xb2\xaf\xf7\x13\x04\x00\x00\x13\x04\x00\x00\x15\x00\x1c\x00Antarcti" + + "ca/South_PoleUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00`\x00\x00\x00\x06\x00\x00\x00\x13\xff\xff\xff\xffA\xb7L\xa8\xff\xff\xff\xff\xb0\xb4\xb2\xe8\xff\xff\xff\xff\xb1Q\x87X\xff\xff\xff\xff\xb2x\xe5h\xff\xff\xff\xff\xb3C\xe5`\xff\xff\xff\xff" + + "\xb4X\xc7h\xff\xff\xff\xff\xb5#\xc7`\xff\xff\xff\xff\xb68\xa9h\xff\xff\xff\xff\xb7\x03\xa9`\xff\xff\xff\xff\xb8\x18\x8bh\xff\xff\xff\xff\xb8\xec\xc5\xe0\xff\xff\xff\xff\xb9\xf8mh\xff\xff\xff\xff\xba̧\xe0" + + "\xff\xff\xff\xff\xbb\xd8Oh\xff\xff\xff\xff\xbc\xe3\xe8\xe0\xff\xff\xff\xff\xbd\xae\xf6\xe8\xff\xff\xff\xff\xbe\xc3\xca\xe0\xff\xff\xff\xff\xbf\x8e\xd8\xe8\xff\xff\xff\xff\xc0\xa3\xac\xe0\xff\xff\xff\xff\xc1n\xba\xe8\xff\xff\xff\xff" + + "\u0083\x8e\xe0\xff\xff\xff\xff\xc3N\x9c\xe8\xff\xff\xff\xff\xc4cp\xe0\xff\xff\xff\xff\xc5.~\xe8\xff\xff\xff\xff\xc6L\x8d`\xff\xff\xff\xff\xc7\x0e`\xe8\xff\xff\xff\xff\xc8,o`\xff\xff\xff\xff\xc8\xf7}h" + + "\xff\xff\xff\xff\xd2ښ@\x00\x00\x00\x00\t\x18\xfd\xe0\x00\x00\x00\x00\t\xac\xa5\xe0\x00\x00\x00\x00\n\xef\xa5`\x00\x00\x00\x00\v\x9e\xfc\xe0\x00\x00\x00\x00\f\xd8\xc1\xe0\x00\x00\x00\x00\r~\xde\xe0\x00\x00\x00\x00" + + "\x0e\xb8\xa3\xe0\x00\x00\x00\x00\x0f^\xc0\xe0\x00\x00\x00\x00\x10\x98\x85\xe0\x00\x00\x00\x00\x11>\xa2\xe0\x00\x00\x00\x00\x12xg\xe0\x00\x00\x00\x00\x13\x1e\x84\xe0\x00\x00\x00\x00\x14XI\xe0\x00\x00\x00\x00\x14\xfef\xe0" + + "\x00\x00\x00\x00\x168+\xe0\x00\x00\x00\x00\x16\xe7\x83`\x00\x00\x00\x00\x18!H`\x00\x00\x00\x00\x18\xc7e`\x00\x00\x00\x00\x1a\x01*`\x00\x00\x00\x00\x1a\xa7G`\x00\x00\x00\x00\x1b\xe1\f`\x00\x00\x00\x00" + + "\x1c\x87)`\x00\x00\x00\x00\x1d\xc0\xee`\x00\x00\x00\x00\x1eg\v`\x00\x00\x00\x00\x1f\xa0\xd0`\x00\x00\x00\x00 F\xed`\x00\x00\x00\x00!\x80\xb2`\x00\x00\x00\x00\"0\t\xe0\x00\x00\x00\x00#i\xce\xe0" + + "\x00\x00\x00\x00$\x0f\xeb\xe0\x00\x00\x00\x00%.\x01`\x00\x00\x00\x00&\x02B\xe0\x00\x00\x00\x00'\r\xe3`\x00\x00\x00\x00'\xe2$\xe0\x00\x00\x00\x00(\xed\xc5`\x00\x00\x00\x00)\xc2\x06\xe0\x00\x00\x00\x00" + + "*ͧ`\x00\x00\x00\x00+\xab#`\x00\x00\x00\x00,\xad\x89`\x00\x00\x00\x00-\x8b\x05`\x00\x00\x00\x00.\x8dk`\x00\x00\x00\x00/j\xe7`\x00\x00\x00\x000mM`\x00\x00\x00\x001J\xc9`" + + "\x00\x00\x00\x002Vi\xe0\x00\x00\x00\x003*\xab`\x00\x00\x00\x0046K\xe0\x00\x00\x00\x005\n\x8d`\x00\x00\x00\x006\x16-\xe0\x00\x00\x00\x006\xf3\xa9\xe0\x00\x00\x00\x007\xf6\x0f\xe0\x00\x00\x00\x00" + + "8Ӌ\xe0\x00\x00\x00\x009\xd5\xf1\xe0\x00\x00\x00\x00:\xb3m\xe0\x00\x00\x00\x00;\xbf\x0e`\x00\x00\x00\x00<\x93O\xe0\x00\x00\x00\x00=\x9e\xf0`\x00\x00\x00\x00>s1\xe0\x00\x00\x00\x00?~\xd2`" + + "\x00\x00\x00\x00@\\N`\x00\x00\x00\x00A^\xb4`\x00\x00\x00\x00B<0`\x00\x00\x00\x00C>\x96`\x00\x00\x00\x00D\x1c\x12`\x00\x00\x00\x00E\x1ex`\x00\x00\x00\x00E\xfb\xf4`\x00\x00\x00\x00" + + "F\xfeZ`\x02\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04" + + "\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x00\x00\xa3\xd8\x00\x00\x00\x00\xaf\xc8\x01\x04\x00\x00\xa1\xb8\x00\t\x00\x00" + + "\xa8\xc0\x01\x04\x00\x00\xb6\xd0\x01\x0e\x00\x00\xa8\xc0\x00\x04LMT\x00NZST\x00NZMT\x00NZDT\x00\nNZST-12NZDT,M9.5.0,M4.1." + + "0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb2\x84J]\xd0\x03\x00\x00\xd0\x03\x00\x00\x14\x00\x1c\x00Antarctica/MacquarieUT\t\x00\x03\x82" + + "\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00[\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff" + + "\xff|\x05\x16\x00\xff\xff\xff\xff\x9b\xd5x\x80\xff\xff\xff\xff\x9c\xbc/\x00\xff\xff\xff\xff\xa0\x87\xb4`\xff\xff\xff\xff\xd7\fh\x00\xff\xff\xff\xff\xfb\u008d\x00\xff\xff\xff\xff\xfc\xb2~\x00\xff\xff\xff\xff\xfd\xc7Y" + + "\x00\xff\xff\xff\xff\xfev\xb0\x80\xff\xff\xff\xff\xff\xa7;\x00\x00\x00\x00\x00\x00V\x92\x80\x00\x00\x00\x00\x01\x87\x1d\x00\x00\x00\x00\x00\x02?\xaf\x00\x00\x00\x00\x00\x03p9\x80\x00\x00\x00\x00\x04\r\x1c\x00\x00\x00\x00" + + "\x00\x05P\x1b\x80\x00\x00\x00\x00\x05\xf68\x80\x00\x00\x00\x00\a/\xfd\x80\x00\x00\x00\x00\a\xd6\x1a\x80\x00\x00\x00\x00\t\x0f߀\x00\x00\x00\x00\t\xb5\xfc\x80\x00\x00\x00\x00\n\xef\xc1\x80\x00\x00\x00\x00\v\x9f\x19" + + "\x00\x00\x00\x00\x00\f\xd8\xde\x00\x00\x00\x00\x00\r~\xfb\x00\x00\x00\x00\x00\x0e\xb8\xc0\x00\x00\x00\x00\x00\x0f^\xdd\x00\x00\x00\x00\x00\x10\x98\xa2\x00\x00\x00\x00\x00\x11>\xbf\x00\x00\x00\x00\x00\x12x\x84\x00\x00\x00\x00" + + "\x00\x13\x1e\xa1\x00\x00\x00\x00\x00\x14Xf\x00\x00\x00\x00\x00\x14\xfe\x83\x00\x00\x00\x00\x00\x168H\x00\x00\x00\x00\x00\x17\x03O\x00\x00\x00\x00\x00\x18!d\x80\x00\x00\x00\x00\x18\xe31\x00\x00\x00\x00\x00\x1a\x01F" + + "\x80\x00\x00\x00\x00\x1a\xa7c\x80\x00\x00\x00\x00\x1b\xe1(\x80\x00\x00\x00\x00\x1c\x87E\x80\x00\x00\x00\x00\x1d\xc1\n\x80\x00\x00\x00\x00\x1eg'\x80\x00\x00\x00\x00\x1f\x97\xb2\x00\x00\x00\x00\x00 Y~\x80\x00\x00\x00" + + "\x00!\x80\u0380\x00\x00\x00\x00\"B\x9b\x00\x00\x00\x00\x00#i\xeb\x00\x00\x00\x00\x00$\"}\x00\x00\x00\x00\x00%I\xcd\x00\x00\x00\x00\x00&\x02_\x00\x00\x00\x00\x00')\xaf\x00\x00\x00\x00\x00'\xf4\xb6" + + "\x00\x00\x00\x00\x00(\xed\xe1\x80\x00\x00\x00\x00)Ԙ\x00\x00\x00\x00\x00*\xcdÀ\x00\x00\x00\x00+\xb4z\x00\x00\x00\x00\x00,\xad\xa5\x80\x00\x00\x00\x00-\x94\\\x00\x00\x00\x00\x00.\x8d\x87\x80\x00\x00\x00" + + "\x00/t>\x00\x00\x00\x00\x000mi\x80\x00\x00\x00\x001]Z\x80\x00\x00\x00\x002V\x86\x00\x00\x00\x00\x003=<\x80\x00\x00\x00\x0046h\x00\x00\x00\x00\x005\x1d\x1e\x80\x00\x00\x00\x006\x16J" + + "\x00\x00\x00\x00\x006\xfd\x00\x80\x00\x00\x00\x007\xf6,\x00\x00\x00\x00\x008\xdc\xe2\x80\x00\x00\x00\x009\xa7\xe9\x80\x00\x00\x00\x00:\xbcĀ\x00\x00\x00\x00;\xbf*\x80\x00\x00\x00\x00<\xa5\xe1\x00\x00\x00\x00" + + "\x00=\x9f\f\x80\x00\x00\x00\x00>\x85\xc3\x00\x00\x00\x00\x00?~\xee\x80\x00\x00\x00\x00@e\xa5\x00\x00\x00\x00\x00A^Ѐ\x00\x00\x00\x00BE\x87\x00\x00\x00\x00\x00C>\xb2\x80\x00\x00\x00\x00D.\xa3" + + "\x80\x00\x00\x00\x00E\x1e\x94\x80\x00\x00\x00\x00F\x05K\x00\x00\x00\x00\x00G\a\xb1\x00\x00\x00\x00\x00G\xf7\xa2\x00\x00\x00\x00\x00H\xe7\x93\x00\x00\x00\x00\x00Iׄ\x00\x00\x00\x00\x00J\xc7u\x00\x00\x00\x00" + + "\x00M\x97H\x00\x01\x02\x01\x00\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x8c\xa0\x00\x04\x00\x00\x9a\xb0\x01\t-00\x00AE" + + "ST\x00AEDT\x00\nAEST-10AEDT,M10.1.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xd7N\xab\x8b\x98\x00\x00\x00" + + "\x98\x00\x00\x00\x11\x00\x1c\x00Antarctica/MawsonUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\xe2 2\x80\x00\x00\x00\x00J\xda\"@\x01\x02\x00\x00\x00\x00\x00\x00\x00\x00T`\x00\x04\x00\x00" + + "FP\x00\b-00\x00+06\x00+05\x00\n<+05>-5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xddzAh\xf3\x00\x00\x00\xf3\x00\x00\x00\x10\x00\x1c\x00Antar" + + "ctica/CaseyUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\f\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\xfe\x1è\x00\x00\x00\x00J\xda\x06 \x00\x00\x00\x00K\x8f\xca\xf0\x00\x00\x00\x00N\xa9\x9c \x00\x00\x00\x00OC͐\x00\x00\x00\x00X\n" + + ";\x80\x00\x00\x00\x00Z\xa4\x0f\x10\x00\x00\x00\x00[\xb9\x14@\x00\x00\x00\x00\\\x8d\x1d\x80\x00\x00\x00\x00]\x96E0\x00\x00\x00\x00^c\xc5\x00\x00\x00\x00\x00_x\xa0<\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x00\x00\x00\x00\x00\x00\x00\x00p\x80\x00\x04\x00\x00\x9a\xb0\x00\b-00\x00+08\x00+11\x00\n<+11>-11\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x1c\x00Arctic/UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x03\x04\n\x00\x00\x00\x00\x00#\x82i" + + "S\xa5\x97\aĤ\x02\x00\x00\xa4\x02\x00\x00\x13\x00\x1c\x00Arctic/LongyearbyenUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04" + + "S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00:\x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff\xffr\xee$l\xff\xff\xff\xff\x9b'\xe3\x00\xff\xff\xff\xff\x9b" + + "\xd4{`\xff\xff\xff\xffȷM`\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff\xff\xd1r\x16\x10\xff" + + "\xff\xff\xff\xd2b\a\x10\xff\xff\xff\xff\xeb\xaf \x90\xff\xff\xff\xff\xec\xa8L\x10\xff\xff\xff\xff\xed\x98=\x10\xff\xff\xff\xff\xee\x88.\x10\xff\xff\xff\xff\xefx\x1f\x10\xff\xff\xff\xff\xf0h\x10\x10\xff\xff\xff\xff\xf1" + + "X\x01\x10\xff\xff\xff\xff\xf2G\xf2\x10\xff\xff\xff\xff\xf37\xe3\x10\xff\xff\xff\xff\xf4'\xd4\x10\xff\xff\xff\xff\xf5\x17\xc5\x10\xff\xff\xff\xff\xf6\x10\xf0\x90\xff\xff\xff\xff\xf7/\x06\x10\xff\xff\xff\xff\xf7\xf0Ґ\x00" + + "\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19" + + "Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00" + + "\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#\x85\xfb@\x00\x00\x00\x00?\x9a\xc80\x00\x00\x00\x00@e\xdd@\x00\x00\x00\x00@\xddǰ\x00\x00\x00\x00A\x84\x1c\xf0\x00\x00\x00\x00" + + "BE\xe9p\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x05\x02\x05\x02\x05\x02\x05\x04\x03\x04\x03\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x05\x02\x04\x00\x00)\xff" + + "\x00\x00\x00\x00)\xff\x00\x04\x00\x00*0\x00\t\x00\x00FP\x01\r\x00\x008@\x00\x11\x00\x008@\x01\x11LMT\x00TBMT\x00+03\x00+05\x00+04\x00\n<+04>-" + + "4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xee\xf0BB\xff\x01\x00\x00\xff\x01\x00\x00\v\x00\x1c\x00Asia/TaipeiUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00" + + "\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00" + + "\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00)\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xfft\xce\xf0\x18\xff\xff\xff\xff\xc3U" + + "I\x80\xff\xff\xff\xff\xd2TY\x80\xff\xff\xff\xffӋ{\x80\xff\xff\xff\xff\xd4B\xad\xf0\xff\xff\xff\xff\xd5E\"\x00\xff\xff\xff\xff\xd6L\xbf\xf0\xff\xff\xff\xff\xd7<\xbf\x00\xff\xff\xff\xff\xd8\x06fp\xff\xff" + + "\xff\xff\xd9\x1d\xf2\x80\xff\xff\xff\xff\xd9\xe7\x99\xf0\xff\xff\xff\xff\xda\xff&\x00\xff\xff\xff\xff\xdb\xc8\xcdp\xff\xff\xff\xff\xdc\xe0Y\x80\xff\xff\xff\xffݪ\x00\xf0\xff\xff\xff\xff\xders\x00\xff\xff\xff\xffߵ" + + "dp\xff\xff\xff\xff\xe0|\x85\x00\xff\xff\xff\xffᖗ\xf0\xff\xff\xff\xff\xe2]\xb8\x80\xff\xff\xff\xff\xe3w\xcbp\xff\xff\xff\xff\xe4>\xec\x00\xff\xff\xff\xff\xe50 p\xff\xff\xff\xff\xe6!q\x00\xff\xff" + + "\xff\xff\xe7\x12\xa5p\xff\xff\xff\xff\xe8\x02\xa4\x80\xff\xff\xff\xff\xe8\xf3\xd8\xf0\xff\xff\xff\xff\xe9\xe3\xd8\x00\xff\xff\xff\xff\xea\xd5\fp\xff\xff\xff\xff\xeb\xc5\v\x80\xff\xff\xff\xff\xec\xb6?\xf0\xff\xff\xff\xff\xed\xf7" + + "\xfc\x00\xff\xff\xff\xff\xee\x98\xc4\xf0\xff\xff\xff\xff\xef\xd9/\x80\xff\xff\xff\xff\xf0y\xf8p\x00\x00\x00\x00\a\xfcV\x00\x00\x00\x00\x00\b\xed\x8ap\x00\x00\x00\x00\t݉\x80\x00\x00\x00\x00\nν\xf0\x00\x00" + + "\x00\x00\x11ۡ\x80\x00\x00\x00\x00\x12T\xddp\x01\x02\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x00\x00q\xe8\x00" + + "\x00\x00\x00p\x80\x00\x04\x00\x00~\x90\x00\b\x00\x00~\x90\x01\fLMT\x00CST\x00JST\x00CDT\x00\nCST-8\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x9a\x1a\xdc\xca" + + "\xdc\x00\x00\x00\xdc\x00\x00\x00\r\x00\x1c\x00Asia/CalcuttaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x05\x00\x00\x00\x16\xff\xff\xff\xff&\xba\x18(\xff\xff\xff\xffC\xe7\xeb0\xff\xff\xff\xff\x87\x9d\xbc\xba\xff\xff\xff\xff\xcaی(" + + "\xff\xff\xff\xff\xcc\x05q\x18\xff\xff\xff\xff̕2\xa8\xff\xff\xff\xff\xd2t\x12\x98\x01\x02\x03\x04\x03\x04\x03\x00\x00R\xd8\x00\x00\x00\x00R\xd0\x00\x04\x00\x00KF\x00\b\x00\x00MX\x00\f\x00\x00[h\x01" + + "\x10LMT\x00HMT\x00MMT\x00IST\x00+0630\x00\nIST-5:30\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSS\xa5\x81e\xf7\x00\x00\x00\xf7\x00\x00\x00\x0e" + + "\x00\x1c\x00Asia/PontianakUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\x00\x00\x00\a\x00\x00\x00\x1f\xff\xff\xff\xff\x8b\xff\x8e\x00\xff\xff\xff\xff\xba\x16\xdf\x00\xff\xff\xff\xff\xcby\xa4\b\xff\xff\xff\xff\xd2V\xeep\xff\xff\xff\xff\xd7<\xc6\b" + + "\xff\xff\xff\xff\xda\xff&\x00\xff\xff\xff\xff\xf4\xb5\xbe\x88\x00\x00\x00\x00!\xdat\x80\x01\x02\x03\x02\x04\x02\x05\x06\x00\x00f\x80\x00\x00\x00\x00f\x80\x00\x04\x00\x00ix\x00\b\x00\x00~\x90\x00\x0e\x00\x00p\x80" + + "\x00\x12\x00\x00p\x80\x00\x16\x00\x00bp\x00\x1bLMT\x00PMT\x00+0730\x00+09\x00+08\x00WITA\x00WIB\x00\nWIB-7\nPK\x03\x04\n\x00\x00\x00" + + "\x00\x00#\x82iS\xdb\xfa\xb5\xbeg\x02\x00\x00g\x02\x00\x00\v\x00\x1c\x00Asia/AqtobeUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01" + "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00A\x00\x00\x00\x06\x00\x00\x00\x10\xff\xff\xff\xff\xa1\xdb\xea^\xff\xff\xff\xff\xb5\xa3\xc5\x00\x00\x00\x00\x00\x15'Sp" + - "\x00\x00\x00\x00\x16\x18\x87\xe0\x00\x00\x00\x00\x17\b\x86\xf0\x00\x00\x00\x00\x17\xf9\xbb`\x00\x00\x00\x00\x18\xe9\xbap\x00\x00\x00\x00\x19\xda\xee\xe0\x00\x00\x00\x00\x1a\xcc?p\x00\x00\x00\x00\x1b\xbcL\x90\x00\x00\x00\x00" + - "\x1c\xac=\x90\x00\x00\x00\x00\x1d\x9c.\x90\x00\x00\x00\x00\x1e\x8c\x1f\x90\x00\x00\x00\x00\x1f|\x10\x90\x00\x00\x00\x00 l\x01\x90\x00\x00\x00\x00![\xf2\x90\x00\x00\x00\x00\"K\xe3\x90\x00\x00\x00\x00#;Ԑ" + - "\x00\x00\x00\x00$+Ő\x00\x00\x00\x00%\x1b\xb6\x90\x00\x00\x00\x00&\v\xa7\x90\x00\x00\x00\x00'\x04\xd3\x10\x00\x00\x00\x00'\xf4\xc4\x10\x00\x00\x00\x00(\xe4\xc3 \x00\x00\x00\x00)xk \x00\x00\x00\x00" + - ")Ԧ\x10\x00\x00\x00\x00*ė\x10\x00\x00\x00\x00+\xb4\x88\x10\x00\x00\x00\x00,\xa4y\x10\x00\x00\x00\x00-\x94j\x10\x00\x00\x00\x00.\x84[\x10\x00\x00\x00\x00/tL\x10\x00\x00\x00\x000d=\x10" + - "\x00\x00\x00\x001]h\x90\x00\x00\x00\x002rC\x90\x00\x00\x00\x003=J\x90\x00\x00\x00\x004R%\x90\x00\x00\x00\x005\x1d,\x90\x00\x00\x00\x0062\a\x90\x00\x00\x00\x006\xfd\x0e\x90\x00\x00\x00\x00" + - "8\x1b$\x10\x00\x00\x00\x008\xdc\xf0\x90\x00\x00\x00\x009\xfb\x06\x10\x00\x00\x00\x00:\xbcҐ\x00\x00\x00\x00;\xda\xe8\x10\x00\x00\x00\x00<\xa5\xef\x10\x00\x00\x00\x00=\xba\xca\x10\x00\x00\x00\x00>\x85\xd1\x10" + - "\x00\x00\x00\x00?\x9a\xac\x10\x00\x00\x00\x00@e\xb3\x10\x00\x00\x00\x00A\x83Ȑ\x00\x00\x00\x00BE\x95\x10\x00\x00\x00\x00Cc\xaa\x90\x00\x00\x00\x00D%w\x10\x00\x00\x00\x00EC\x8c\x90\x00\x00\x00\x00" + - "F\x05Y\x10\x00\x00\x00\x00G#n\x90\x00\x00\x00\x00G\xeeu\x90\x00\x00\x00\x00I\x03P\x90\x00\x00\x00\x00I\xceW\x90\x00\x00\x00\x00J\xe32\x90\x00\x00\x00\x00K\xae9\x90\x00\x00\x00\x00L\xccO\x10" + - "\x00\x00\x00\x00M\x8e\x1b\x90\x00\x00\x00\x00TK\xc9\x00\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x05\x03\x00\x00y\xa2\x00\x00\x00\x00p\x80\x00\x04\x00\x00\x8c\xa0\x01\b\x00\x00~\x90\x00\f\x00\x00~\x90\x01\f\x00\x00\x8c\xa0\x00\bLMT" + - "\x00+08\x00+10\x00+09\x00\n<+09>-9\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R.>[K\xab\x00\x00\x00\xab\x00\x00\x00\r\x00\x1c\x00Asia/Jay" + - "apuraUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03" + - "\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xff\xba\x16\xc1\x98\xff\xff\xff\xff\xd0X\xb9\xf0\xff\xff\xff\xff\xf4\xb5\xa2h\x01\x02\x03\x00\x00\x83\xe8\x00\x00\x00\x00~\x90\x00\x04\x00\x00\x85\x98\x00\b\x00\x00~\x90\x00\x0eL" + - "MT\x00+09\x00+0930\x00WIT\x00\nWIT-9\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RE\t\xfa-\a\x03\x00\x00\a\x03\x00\x00\x0e\x00\x1c\x00Asia/H" + - "ong_KongUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00E\x00\x00\x00\x05\x00\x00\x00\x16\xff\xff\xff\xff\x85ic\x90\xff\xff\xff\xff\xcaM10\xff\xff\xff\xff\xcaۓ0\xff\xff\xff\xff\xcbKqx\xff\xff\xff\xffҠސ\xff\xff\xff\xff\xd3k׀\xff" + - "\xff\xff\xffԓX\xb8\xff\xff\xff\xff\xd5B\xb08\xff\xff\xff\xff\xd6s:\xb8\xff\xff\xff\xff\xd7>A\xb8\xff\xff\xff\xff\xd8.2\xb8\xff\xff\xff\xff\xd8\xf99\xb8\xff\xff\xff\xff\xda\x0e\x14\xb8\xff\xff\xff\xff\xda" + - "\xd9\x1b\xb8\xff\xff\xff\xff\xdb\xed\xf6\xb8\xff\xff\xff\xffܸ\xfd\xb8\xff\xff\xff\xff\xdd\xcdظ\xff\xff\xff\xffޢ\x1a8\xff\xff\xff\xff߶\xf58\xff\xff\xff\xff\xe0\x81\xfc8\xff\xff\xff\xff\xe1\x96\xc9(\xff" + - "\xff\xff\xff\xe2Oi8\xff\xff\xff\xff\xe3v\xab(\xff\xff\xff\xff\xe4/K8\xff\xff\xff\xff\xe5_Ǩ\xff\xff\xff\xff\xe6\x0f-8\xff\xff\xff\xff\xe7?\xa9\xa8\xff\xff\xff\xff\xe7\xf8I\xb8\xff\xff\xff\xff\xe9" + - "\x1f\x8b\xa8\xff\xff\xff\xff\xe9\xd8+\xb8\xff\xff\xff\xff\xea\xffm\xa8\xff\xff\xff\xff\xeb\xb8\r\xb8\xff\xff\xff\xff\xec\xdfO\xa8\xff\xff\xff\xff\xed\x97\xef\xb8\xff\xff\xff\xff\xee\xc8l(\xff\xff\xff\xff\xefwѸ\xff" + - "\xff\xff\xff\xf0\xa8N(\xff\xff\xff\xff\xf1W\xb3\xb8\xff\xff\xff\xff\xf2\x880(\xff\xff\xff\xff\xf3@\xd08\xff\xff\xff\xff\xf4h\x12(\xff\xff\xff\xff\xf5 \xb28\xff\xff\xff\xff\xf6G\xf4(\xff\xff\xff\xff\xf7" + - "%~8\xff\xff\xff\xff\xf8\x15a(\xff\xff\xff\xff\xf9\x05`8\xff\xff\xff\xff\xf9\xf5C(\xff\xff\xff\xff\xfa\xe5B8\xff\xff\xff\xff\xfb\xde_\xa8\xff\xff\xff\xff\xfc\xce^\xb8\xff\xff\xff\xff\xfd\xbeA\xa8\xff" + - "\xff\xff\xff\xfe\xae@\xb8\xff\xff\xff\xff\xff\x9e#\xa8\x00\x00\x00\x00\x00\x8e\"\xb8\x00\x00\x00\x00\x01~\x05\xa8\x00\x00\x00\x00\x02n\x04\xb8\x00\x00\x00\x00\x03]\xe7\xa8\x00\x00\x00\x00\x04M\xe6\xb8\x00\x00\x00\x00\x05" + - "G\x04(\x00\x00\x00\x00\x067\x038\x00\x00\x00\x00\a&\xe6(\x00\x00\x00\x00\a\x83=8\x00\x00\x00\x00\t\x06\xc8(\x00\x00\x00\x00\t\xf6\xc78\x00\x00\x00\x00\n\xe6\xaa(\x00\x00\x00\x00\v֩8\x00" + - "\x00\x00\x00\fƌ(\x00\x00\x00\x00\x11\x9b98\x00\x00\x00\x00\x12ol\xa8\x01\x02\x03\x04\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00k\n\x00\x00\x00\x00p\x80\x00\x04\x00\x00~\x90\x01\b\x00\x00w\x88\x01\r\x00\x00~\x90" + - "\x00\x12LMT\x00HKT\x00HKST\x00HKWT\x00JST\x00\nHKT-8\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RS\xa5\x81e\xf7\x00\x00\x00\xf7\x00\x00\x00\x0e\x00\x1c" + - "\x00Asia/PontianakUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x003\x00\x00\x00\x06\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x19\x8eh\xff\xff\xff\xff\xb5\xa3\xfd@\x00\x00\x00\x00\x15'\x8b\xb0" + + "\x00\x00\x00\x00\x16\x18\xc0 \x00\x00\x00\x00\x17\b\xb1 \x00\x00\x00\x00\x17\xf9\xf3\xa0\x00\x00\x00\x00\x18\xe9\xf2\xb0\x00\x00\x00\x00\x19\xdb' \x00\x00\x00\x00\x1a\xccw\xb0\x00\x00\x00\x00\x1b\xbc\x84\xd0\x00\x00\x00\x00" + + "\x1c\xacu\xd0\x00\x00\x00\x00\x1d\x9cf\xd0\x00\x00\x00\x00\x1e\x8cW\xd0\x00\x00\x00\x00\x1f|H\xd0\x00\x00\x00\x00 l9\xd0\x00\x00\x00\x00!\\*\xd0\x00\x00\x00\x00\"L\x1b\xd0\x00\x00\x00\x00#<\f\xd0" + + "\x00\x00\x00\x00$+\xfd\xd0\x00\x00\x00\x00%\x1b\xee\xd0\x00\x00\x00\x00&\v\xdf\xd0\x00\x00\x00\x00'\x05\vP\x00\x00\x00\x00'\xf4\xfcP\x00\x00\x00\x00(\xe4\xfb`\x00\x00\x00\x00)x\xa3`\x00\x00\x00\x00" + + ")\xd4\xdeP\x00\x00\x00\x00*\xc4\xcfP\x00\x00\x00\x00+\xb4\xc0P\x00\x00\x00\x00,\xa4\xb1P\x00\x00\x00\x00-\x94\xa2P\x00\x00\x00\x00.\x84\x93P\x00\x00\x00\x00/t\x84P\x00\x00\x00\x000duP" + + "\x00\x00\x00\x001]\xa0\xd0\x00\x00\x00\x002r{\xd0\x00\x00\x00\x003=\x82\xd0\x00\x00\x00\x004R]\xd0\x00\x00\x00\x005\x1dd\xd0\x00\x00\x00\x0062?\xd0\x00\x00\x00\x006\xfdF\xd0\x00\x00\x00\x00" + + "8\x1b\\P\x00\x00\x00\x008\xdd(\xd0\x00\x00\x00\x009\xfb>P\x00\x00\x00\x00:\xbd\n\xd0\x00\x00\x00\x00;\xdb P\x00\x00\x00\x00<\xa6'P\x00\x00\x00\x00=\xbb\x02P\x00\x00\x00\x00>\x86\tP" + + "\x00\x00\x00\x00?\x9a\xe4P\x00\x00\x00\x00@e\xebP\x00\x00\x00\x00A\x84\x00\xd0\x01\x02\x03\x04\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x00\x005\x98\x00\x00\x00\x008@\x00\x04\x00\x00FP\x00\b\x00\x00T`\x01\f\x00\x00T`\x00\f\x00\x00FP\x01\bLMT\x00+04\x00+" + + "05\x00+06\x00\n<+05>-5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x9a\x1a\xdc\xca\xdc\x00\x00\x00\xdc\x00\x00\x00\f\x00\x1c\x00Asia/KolkataUT" + + "\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x05\x00\x00\x00" + + "\x16\xff\xff\xff\xff&\xba\x18(\xff\xff\xff\xffC\xe7\xeb0\xff\xff\xff\xff\x87\x9d\xbc\xba\xff\xff\xff\xff\xcaی(\xff\xff\xff\xff\xcc\x05q\x18\xff\xff\xff\xff̕2\xa8\xff\xff\xff\xff\xd2t\x12\x98\x01\x02\x03" + + "\x04\x03\x04\x03\x00\x00R\xd8\x00\x00\x00\x00R\xd0\x00\x04\x00\x00KF\x00\b\x00\x00MX\x00\f\x00\x00[h\x01\x10LMT\x00HMT\x00MMT\x00IST\x00+0630\x00\nIST" + + "-5:30\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x87\xbd\xedL\xf1\x02\x00\x00\xf1\x02\x00\x00\f\x00\x1c\x00Asia/BarnaulUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8b" + + "aux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01" + + "\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00C\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xa1\xd5}\xfc\xff" + + "\xff\xff\xff\xb5\xa3\xe1 \x00\x00\x00\x00\x15'o\x90\x00\x00\x00\x00\x16\x18\xa4\x00\x00\x00\x00\x00\x17\b\xa3\x10\x00\x00\x00\x00\x17\xf9׀\x00\x00\x00\x00\x18\xe9\u0590\x00\x00\x00\x00\x19\xdb\v\x00\x00\x00\x00\x00\x1a" + + "\xcc[\x90\x00\x00\x00\x00\x1b\xbch\xb0\x00\x00\x00\x00\x1c\xacY\xb0\x00\x00\x00\x00\x1d\x9cJ\xb0\x00\x00\x00\x00\x1e\x8c;\xb0\x00\x00\x00\x00\x1f|,\xb0\x00\x00\x00\x00 l\x1d\xb0\x00\x00\x00\x00!\\\x0e\xb0\x00" + + "\x00\x00\x00\"K\xff\xb0\x00\x00\x00\x00#;\xf0\xb0\x00\x00\x00\x00$+\xe1\xb0\x00\x00\x00\x00%\x1bҰ\x00\x00\x00\x00&\vð\x00\x00\x00\x00'\x04\xef0\x00\x00\x00\x00'\xf4\xe00\x00\x00\x00\x00(" + + "\xe4\xdf@\x00\x00\x00\x00)x\x87@\x00\x00\x00\x00)\xd4\xc20\x00\x00\x00\x00*ij0\x00\x00\x00\x00+\xb4\xa40\x00\x00\x00\x00,\xa4\x950\x00\x00\x00\x00-\x94\x860\x00\x00\x00\x00.\x84w0\x00" + + "\x00\x00\x00/th0\x00\x00\x00\x00/\xc7L\x80\x00\x00\x00\x000dg@\x00\x00\x00\x001]\x92\xc0\x00\x00\x00\x002rm\xc0\x00\x00\x00\x003=t\xc0\x00\x00\x00\x004RO\xc0\x00\x00\x00\x005" + + "\x1dV\xc0\x00\x00\x00\x00621\xc0\x00\x00\x00\x006\xfd8\xc0\x00\x00\x00\x008\x1bN@\x00\x00\x00\x008\xdd\x1a\xc0\x00\x00\x00\x009\xfb0@\x00\x00\x00\x00:\xbc\xfc\xc0\x00\x00\x00\x00;\xdb\x12@\x00" + + "\x00\x00\x00<\xa6\x19@\x00\x00\x00\x00=\xba\xf4@\x00\x00\x00\x00>\x85\xfb@\x00\x00\x00\x00?\x9a\xd6@\x00\x00\x00\x00@e\xdd@\x00\x00\x00\x00A\x83\xf2\xc0\x00\x00\x00\x00BE\xbf@\x00\x00\x00\x00C" + + "c\xd4\xc0\x00\x00\x00\x00D%\xa1@\x00\x00\x00\x00EC\xb6\xc0\x00\x00\x00\x00F\x05\x83@\x00\x00\x00\x00G#\x98\xc0\x00\x00\x00\x00G\xee\x9f\xc0\x00\x00\x00\x00I\x03z\xc0\x00\x00\x00\x00I\u0381\xc0\x00" + + "\x00\x00\x00J\xe3\\\xc0\x00\x00\x00\x00K\xaec\xc0\x00\x00\x00\x00L\xccy@\x00\x00\x00\x00M\x8eE\xc0\x00\x00\x00\x00TK\xf30\x00\x00\x00\x00V\xf6\xea@\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x03\x02\x03\x02\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x03\x01\x03\x00\x00N\x84\x00\x00" + + "\x00\x00T`\x00\x04\x00\x00p\x80\x01\b\x00\x00bp\x00\f\x00\x00bp\x01\fLMT\x00+06\x00+08\x00+07\x00\n<+07>-7\nPK\x03\x04\n\x00\x00\x00\x00\x00#" + + "\x82iS\xa7f^]@\x01\x00\x00@\x01\x00\x00\f\x00\x1c\x00Asia/KuchingUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00T" + + "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00\x00\x00\x05\x00\x00\x00\x18\xff\xff\xff\xff\xad\x8a\x06\x90\xff\xff\xff\xff\xbagG\x88\xff\xff\xff\xff\xbf{'\x80\xff\xff" + + "\xff\xff\xbf\xf3\x1bP\xff\xff\xff\xff\xc1]\xac\x80\xff\xff\xff\xff\xc1ՠP\xff\xff\xff\xff\xc3>\xe0\x00\xff\xff\xff\xffö\xd3\xd0\xff\xff\xff\xff\xc5 \x13\x80\xff\xff\xff\xffŘ\aP\xff\xff\xff\xff\xc7\x01" + + "G\x00\xff\xff\xff\xff\xc7y:\xd0\xff\xff\xff\xff\xc8\xe3\xcc\x00\xff\xff\xff\xff\xc9[\xbf\xd0\xff\xff\xff\xff\xca\xc4\xff\x80\xff\xff\xff\xff\xcb<\xf3P\xff\xff\xff\xffˑX\x00\xff\xff\xff\xff\xd2Hm\xf0\x01\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x03\x00\x00gp\x00\x00\x00\x00ix\x00\x04\x00\x00u0\x01\n\x00\x00p\x80\x00\x10\x00\x00~\x90\x00\x14LMT\x00+0730\x00+082" + + "0\x00+08\x00+09\x00\n<+08>-8\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSǯ\xdf\x1c\xee\x00\x00\x00\xee\x00\x00\x00\v\x00\x1c\x00Asia/Manila" + + "UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x05\x00" + + "\x00\x00\x10\xff\xff\xff\xff\x14\xe1\xdc\x10\xff\xff\xff\xff{\x1f?\x90\xff\xff\xff\xff\xc1\x9c\xf4\x80\xff\xff\xff\xff\xc2\x160p\xff\xff\xff\xff\xcb\xf2\xe7\x00\xff\xff\xff\xffЩ%p\xff\xff\xff\xff\xe2l9\x00\xff" + + "\xff\xff\xff\xe2բ\xf0\x00\x00\x00\x00\x0fuF\x80\x00\x00\x00\x00\x10fz\xf0\x01\x03\x02\x03\x04\x03\x02\x03\x02\x03\xff\xff\x1f\xf0\x00\x00\x00\x00qp\x00\x00\x00\x00~\x90\x01\x04\x00\x00p\x80\x00\b\x00\x00~" + + "\x90\x00\fLMT\x00PDT\x00PST\x00JST\x00\nPST-8\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS?\xa7^\xfah\x02\x00\x00h\x02\x00\x00\v\x00\x1c\x00Asia" + + "/AtyrauUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x002\x00\x00\x00\a\x00\x00\x00\x14\xff\xff\xff\xff\xaa\x19\x93P\xff\xff\xff\xff\xb5\xa4\vP\x00\x00\x00\x00\x16\x18\xce0\x00\x00\x00\x00\x17\b\xb1 \x00\x00\x00\x00\x17\xf9\xf3\xa0\x00\x00\x00\x00\x18\xe9\xf2\xb0\x00\x00" + + "\x00\x00\x19\xdb' \x00\x00\x00\x00\x1a\xccw\xb0\x00\x00\x00\x00\x1b\xbc\x84\xd0\x00\x00\x00\x00\x1c\xacu\xd0\x00\x00\x00\x00\x1d\x9cf\xd0\x00\x00\x00\x00\x1e\x8cW\xd0\x00\x00\x00\x00\x1f|H\xd0\x00\x00\x00\x00 l" + + "9\xd0\x00\x00\x00\x00!\\*\xd0\x00\x00\x00\x00\"L\x1b\xd0\x00\x00\x00\x00#<\f\xd0\x00\x00\x00\x00$+\xfd\xd0\x00\x00\x00\x00%\x1b\xee\xd0\x00\x00\x00\x00&\v\xdf\xd0\x00\x00\x00\x00'\x05\vP\x00\x00" + + "\x00\x00'\xf4\xfcP\x00\x00\x00\x00(\xe4\xfb`\x00\x00\x00\x00)x\xa3`\x00\x00\x00\x00)\xd4\xdeP\x00\x00\x00\x00*\xc4\xcfP\x00\x00\x00\x00+\xb4\xc0P\x00\x00\x00\x00,\xa4\xb1P\x00\x00\x00\x00-\x94" + + "\xa2P\x00\x00\x00\x00.\x84\x93P\x00\x00\x00\x00/t\x84P\x00\x00\x00\x000duP\x00\x00\x00\x001]\xa0\xd0\x00\x00\x00\x002r{\xd0\x00\x00\x00\x003=\x82\xd0\x00\x00\x00\x004R]\xd0\x00\x00" + + "\x00\x005\x1dd\xd0\x00\x00\x00\x0062?\xd0\x00\x00\x00\x006\xfdF\xd0\x00\x00\x00\x008\x1bj`\x00\x00\x00\x008\xdd6\xe0\x00\x00\x00\x009\xfbL`\x00\x00\x00\x00:\xbd\x18\xe0\x00\x00\x00\x00;\xdb" + + ".`\x00\x00\x00\x00<\xa65`\x00\x00\x00\x00=\xbb\x10`\x00\x00\x00\x00>\x86\x17`\x00\x00\x00\x00?\x9a\xf2`\x00\x00\x00\x00@e\xf9`\x00\x00\x00\x00A\x84\x0e\xe0\x01\x02\x03\x04\x02\x04\x02\x04\x02\x04" + + "\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x05\x06\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x02\x00\x000\xb0\x00\x00\x00\x00*0\x00\x04\x00\x00FP\x00\b\x00\x00" + + "T`\x00\f\x00\x00T`\x01\f\x00\x00FP\x01\b\x00\x008@\x00\x10LMT\x00+03\x00+05\x00+06\x00+04\x00\n<+05>-5\nPK\x03\x04\n\x00\x00\x00\x00" + + "\x00#\x82iS\x1d?v\f\x17\x03\x00\x00\x17\x03\x00\x00\n\x00\x1c\x00Asia/MacaoUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00T" + + "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\x85i[\x8e\xff\xff\xff\xff\xcbGu\xf0\xff\xff\xff\xff\xcb\xf2\xca\xe0\xff\xff" + + "\xff\xff\xcc\xfb\xbaP\xff\xff\xff\xff\xcd\xd3\xfe`\xff\xff\xff\xffΝ\xa5\xd0\xff\xff\xff\xff\xd2azp\xff\xff\xff\xff\xd3x\xf8p\xff\xff\xff\xff\xd4B\xad\xf0\xff\xff\xff\xff\xd5K\xabp\xff\xff\xff\xff\xd6t" + + "L\xf0\xff\xff\xff\xff\xd7?S\xf0\xff\xff\xff\xff\xd8/D\xf0\xff\xff\xff\xff\xd8\xf8\xfap\xff\xff\xff\xff\xda\r\xd5p\xff\xff\xff\xff\xda\xd8\xdcp\xff\xff\xff\xff\xdb\xed\xb7p\xff\xff\xff\xffܸ\xbep\xff\xff" + + "\xff\xff\xdd\xce\xea\xf0\xff\xff\xff\xffޡ\xda\xf0\xff\xff\xff\xff߶\xb5\xf0\xff\xff\xff\xff\xe0\x81\xbc\xf0\xff\xff\xff\xffᖗ\xf0\xff\xff\xff\xff\xe2O)\xf0\xff\xff\xff\xff\xe3vy\xf0\xff\xff\xff\xff\xe4/" + + "\v\xf0\xff\xff\xff\xff\xe5_\x96p\xff\xff\xff\xff\xe6\x0e\xed\xf0\xff\xff\xff\xff\xe7?\xa9\xa8\xff\xff\xff\xff\xe7\xf8I\xb8\xff\xff\xff\xff\xe9\x1f\x8b\xa8\xff\xff\xff\xff\xe9\xd8+\xb8\xff\xff\xff\xff\xea\xffm\xa8\xff\xff" + + "\xff\xff\xeb\xb8\r\xb8\xff\xff\xff\xff\xec\xdfO\xa8\xff\xff\xff\xff\xed\x97\xef\xb8\xff\xff\xff\xff\xee\xc8l(\xff\xff\xff\xff\xefwѸ\xff\xff\xff\xff\xf0\xa8N(\xff\xff\xff\xff\xf1W\xb3\xb8\xff\xff\xff\xff\xf2\x88" + + "0(\xff\xff\xff\xff\xf3@\xd08\xff\xff\xff\xff\xf4h\x12(\xff\xff\xff\xff\xf5 \xb28\xff\xff\xff\xff\xf6G\xf4(\xff\xff\xff\xff\xf7%~8\xff\xff\xff\xff\xf8\x15S\x18\xff\xff\xff\xff\xf9\x05`8\xff\xff" + + "\xff\xff\xf9\xf55\x18\xff\xff\xff\xff\xfa\xe5B8\xff\xff\xff\xff\xfb\xde_\xa8\xff\xff\xff\xff\xfc\xce^\xb8\xff\xff\xff\xff\xfd\xbeA\xa8\xff\xff\xff\xff\xfe\xae@\xb8\xff\xff\xff\xff\xff\x9e#\xa8\x00\x00\x00\x00\x00\x8e" + + "\"\xb8\x00\x00\x00\x00\x01~\x05\xa8\x00\x00\x00\x00\x02n\x04\xb8\x00\x00\x00\x00\x03]\xe7\xa8\x00\x00\x00\x00\x04M\xe6\xb8\x00\x00\x00\x00\x05G\x04(\x00\x00\x00\x00\x067\x038\x00\x00\x00\x00\a&\xe6(\x00\x00" + + "\x00\x00\a\x83=8\x00\x00\x00\x00\t\x06\xc8(\x00\x00\x00\x00\t\xf6\xc78\x00\x00\x00\x00\n\xe6\xaa(\x00\x00\x00\x00\v֩8\x00\x00\x00\x00\fƌ(\x00\x00\x00\x00\x11\x9b98\x00\x00\x00\x00\x12o" + + "l\xa8\x01\x03\x02\x03\x02\x03\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04" + + "\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x00\x00jr\x00\x00\x00\x00p\x80\x00\x04\x00\x00\x8c\xa0\x01\b\x00\x00~\x90\x00\f\x00\x00~\x90\x01\x10LMT\x00CST\x00+10\x00+09\x00C" + + "DT\x00\nCST-8\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xdav\x19z\x98\x00\x00\x00\x98\x00\x00\x00\n\x00\x1c\x00Asia/QatarUT\t\x00\x03\x82\x0f\x8ba\x82" + + "\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00" + + "\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\xa1\xf2\x9d" + + "0\x00\x00\x00\x00\x04\x8a\x92\xc0\x01\x02\x00\x000P\x00\x00\x00\x008@\x00\x04\x00\x00*0\x00\bLMT\x00+04\x00+03\x00\n<+03>-3\nPK\x03\x04\n\x00\x00\x00\x00\x00" + + "#\x82iS\xf9l\x03\x12\xf8\x02\x00\x00\xf8\x02\x00\x00\f\x00\x1c\x00Asia/IrkutskUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00" + + "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00B\x00\x00\x00\a\x00\x00\x00\x14\xff\xff\xff\xffV\xb6\x82?\xff\xff\xff\xff\xa2\x12\x0f\xbf\xff\xff\xff\xff\xb5\xa3\xd3\x10\x00" + + "\x00\x00\x00\x15'a\x80\x00\x00\x00\x00\x16\x18\x95\xf0\x00\x00\x00\x00\x17\b\x95\x00\x00\x00\x00\x00\x17\xf9\xc9p\x00\x00\x00\x00\x18\xe9Ȁ\x00\x00\x00\x00\x19\xda\xfc\xf0\x00\x00\x00\x00\x1a\xccM\x80\x00\x00\x00\x00\x1b" + + "\xbcZ\xa0\x00\x00\x00\x00\x1c\xacK\xa0\x00\x00\x00\x00\x1d\x9c<\xa0\x00\x00\x00\x00\x1e\x8c-\xa0\x00\x00\x00\x00\x1f|\x1e\xa0\x00\x00\x00\x00 l\x0f\xa0\x00\x00\x00\x00!\\\x00\xa0\x00\x00\x00\x00\"K\xf1\xa0\x00" + + "\x00\x00\x00#;\xe2\xa0\x00\x00\x00\x00$+Ӡ\x00\x00\x00\x00%\x1bĠ\x00\x00\x00\x00&\v\xb5\xa0\x00\x00\x00\x00'\x04\xe1 \x00\x00\x00\x00'\xf4\xd2 \x00\x00\x00\x00(\xe4\xd10\x00\x00\x00\x00)" + + "xy0\x00\x00\x00\x00)Դ \x00\x00\x00\x00*ĥ \x00\x00\x00\x00+\xb4\x96 \x00\x00\x00\x00,\xa4\x87 \x00\x00\x00\x00-\x94x \x00\x00\x00\x00.\x84i \x00\x00\x00\x00/tZ \x00" + + "\x00\x00\x000dK \x00\x00\x00\x001]v\xa0\x00\x00\x00\x002rQ\xa0\x00\x00\x00\x003=X\xa0\x00\x00\x00\x004R3\xa0\x00\x00\x00\x005\x1d:\xa0\x00\x00\x00\x0062\x15\xa0\x00\x00\x00\x006" + + "\xfd\x1c\xa0\x00\x00\x00\x008\x1b2 \x00\x00\x00\x008\xdc\xfe\xa0\x00\x00\x00\x009\xfb\x14 \x00\x00\x00\x00:\xbc\xe0\xa0\x00\x00\x00\x00;\xda\xf6 \x00\x00\x00\x00<\xa5\xfd \x00\x00\x00\x00=\xba\xd8 \x00" + + "\x00\x00\x00>\x85\xdf \x00\x00\x00\x00?\x9a\xba \x00\x00\x00\x00@e\xc1 \x00\x00\x00\x00A\x83֠\x00\x00\x00\x00BE\xa3 \x00\x00\x00\x00Cc\xb8\xa0\x00\x00\x00\x00D%\x85 \x00\x00\x00\x00E" + + "C\x9a\xa0\x00\x00\x00\x00F\x05g \x00\x00\x00\x00G#|\xa0\x00\x00\x00\x00G\ue0e0\x00\x00\x00\x00I\x03^\xa0\x00\x00\x00\x00I\xcee\xa0\x00\x00\x00\x00J\xe3@\xa0\x00\x00\x00\x00K\xaeG\xa0\x00" + + "\x00\x00\x00L\xcc] \x00\x00\x00\x00M\x8e)\xa0\x00\x00\x00\x00TK\xd7\x10\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x05\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03" + + "\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x06\x04\x00\x00a\xc1\x00\x00\x00\x00a\xc1\x00\x04\x00\x00bp\x00\b\x00\x00~\x90\x01\f\x00\x00p\x80\x00\x10\x00" + + "\x00p\x80\x01\x10\x00\x00~\x90\x00\fLMT\x00IMT\x00+07\x00+09\x00+08\x00\n<+08>-8\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xe8\xf0\xdeV\xe0\x04" + + "\x00\x00\xe0\x04\x00\x00\v\x00\x1c\x00Asia/HebronUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif3\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00w\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xff}\xbdJ\x19\xff\xff\xff\xff\xc8Y\xcf\x00\xff\xff\xff\xff\xc8\xfa\xa6\x00\xff\xff\xff\xff\xc98\x9c\x80\xff\xff\xff\xff" + + "\xcc\xe5\xeb\x80\xff\xff\xff\xffͬ\xfe\x00\xff\xff\xff\xff\xce\xc7\x1f\x00\xff\xff\xff\xffϏ\x83\x00\xff\xff\xff\xffЩ\xa4\x00\xff\xff\xff\xffф}\x00\xff\xff\xff\xffҊ׀\xff\xff\xff\xff\xd3e\xb0\x80" + + "\xff\xff\xff\xff\xd4l\v\x00\xff\xff\xff\xff\xe86c`\xff\xff\xff\xff\xe8\xf4-P\xff\xff\xff\xff\xea\v\xb9`\xff\xff\xff\xff\xea\xd5`\xd0\xff\xff\xff\xff\xeb\xec\xfa\xf0\xff\xff\xff\xff\xec\xb5m\x00\xff\xff\xff\xff" + + "\xed\xcf\u007f\xf0\xff\xff\xff\xff\xee\x97\xf2\x00\xff\xff\xff\xffﰳp\xff\xff\xff\xff\xf0y%\x80\xff\xff\xff\xff\xf1\x91\xe6\xf0\xff\xff\xff\xff\xf2ZY\x00\xff\xff\xff\xff\xf3s\x1ap\xff\xff\xff\xff\xf4;\x8c\x80" + + "\xff\xff\xff\xff\xf5U\x9fp\xff\xff\xff\xff\xf6\x1e\x11\x80\xff\xff\xff\xff\xf76\xd2\xf0\xff\xff\xff\xff\xf7\xffE\x00\xff\xff\xff\xff\xf9\x18\x06p\xff\xff\xff\xff\xf9\xe1\xca\x00\xff\xff\xff\xff\xfa\xf99\xf0\xff\xff\xff\xff" + + "\xfb'BP\x00\x00\x00\x00\b|\x8b\xe0\x00\x00\x00\x00\b\xfd\xb0\xd0\x00\x00\x00\x00\t\xf6\xea`\x00\x00\x00\x00\n\xa63\xd0\x00\x00\x00\x00\x13\xe9\xfc`\x00\x00\x00\x00\x14![`\x00\x00\x00\x00\x1a\xfa\xc6`" + + "\x00\x00\x00\x00\x1b\x8en`\x00\x00\x00\x00\x1c\xbe\xf8\xe0\x00\x00\x00\x00\x1dw|\xd0\x00\x00\x00\x00\x1e\xcc\xff`\x00\x00\x00\x00\x1f`\x99P\x00\x00\x00\x00 \x82\xb1`\x00\x00\x00\x00!I\xb5\xd0\x00\x00\x00\x00" + + "\"^\x9e\xe0\x00\x00\x00\x00# ]P\x00\x00\x00\x00$Z0`\x00\x00\x00\x00%\x00?P\x00\x00\x00\x00&\v\xed\xe0\x00\x00\x00\x00&\xd6\xe6\xd0\x00\x00\x00\x00'\xeb\xcf\xe0\x00\x00\x00\x00(\xc0\x03P" + + "\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xa9\x1f\xd0\x00\x00\x00\x00+\xbbe\xe0\x00\x00\x00\x00,\x89\x01\xd0\x00\x00\x00\x00-\x9bG\xe0\x00\x00\x00\x00._\xa9P\x00\x00\x00\x00/{)\xe0\x00\x00\x00\x00" + + "0H\xc5\xd0\x00\x00\x00\x000\xe7\a\xe0\x00\x00\x00\x001dF`\x00\x00\x00\x002A\xc2`\x00\x00\x00\x003D(`\x00\x00\x00\x004!\xa4`\x00\x00\x00\x005$\n`\x00\x00\x00\x006\x01\x86`" + + "\x00\x00\x00\x007\x16a`\x00\x00\x00\x008\x06DP\x00\x00\x00\x008\xff}\xe0\x00\x00\x00\x009\xef`\xd0\x00\x00\x00\x00:\xdf_\xe0\x00\x00\x00\x00;\xcfB\xd0\x00\x00\x00\x00<\xbfA\xe0\x00\x00\x00\x00" + + "=\xaf$\xd0\x00\x00\x00\x00>\x9f#\xe0\x00\x00\x00\x00?\x8f\x06\xd0\x00\x00\x00\x00@\u007f\x05\xe0\x00\x00\x00\x00A\\\x81\xe0\x00\x00\x00\x00B^\xe7\xe0\x00\x00\x00\x00CA\xb7\xf0\x00\x00\x00\x00D-\xa6`" + + "\x00\x00\x00\x00E\x12\xfdP\x00\x00\x00\x00F\x0e\xd9\xe0\x00\x00\x00\x00F\xe8op\x00\x00\x00\x00G\xec\x18\xe0\x00\x00\x00\x00H\xbb\x06P\x00\x00\x00\x00I\xcb\xfa\xe0\x00\x00\x00\x00J\xa0<`\x00\x00\x00\x00" + + "K\xab\xdc\xe0\x00\x00\x00\x00La\xbd\xd0\x00\x00\x00\x00M\x94\xf9\x9c\x00\x00\x00\x00N5\xc2P\x00\x00\x00\x00N\\\v\xe0\x00\x00\x00\x00N\x84\xdcP\x00\x00\x00\x00Ot\xdb`\x00\x00\x00\x00P[\x91\xe0" + + "\x00\x00\x00\x00QT\xbd`\x00\x00\x00\x00RD\xa0P\x00\x00\x00\x00S4\x9f`\x00\x00\x00\x00TIlP\x00\x00\x00\x00U\x15\xd2\xe0\x00\x00\x00\x00V)\\`\x00\x00\x00\x00V\xf5\xc2\xf0\x00\x00\x00\x00" + + "X\x13\xca`\x00\x00\x00\x00Xդ\xf0\x00\x00\x00\x00Y\xf3\xac`\x00\x00\x00\x00Z\xb5\x86\xf0\x00\x00\x00\x00[ӎ`\x00\x00\x00\x00\\\x9dC\xe0\x00\x00\x00\x00]\xb3bP\x00\x00\x00\x00^~w`" + + "\x00\x00\x00\x00_\x93R`\x00\x00\x00\x00`^Y`\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03" + + "\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00 \xe7\x00\x00\x00\x00*0\x01\x04\x00\x00\x1c \x00\t\x00\x00*0\x01\r\x00\x00\x1c \x00\x11LMT\x00EEST\x00EET\x00ID" + + "T\x00IST\x00\nEET-2EEST,M3.4.4/48,M10.5.5/1\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS]S\xbb\x12\xac\x03\x00\x00\xac" + + "\x03\x00\x00\x0e\x00\x1c\x00Asia/FamagustaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00V\x00\x00\x00\x04\x00\x00\x00\x11\xff\xff\xff\xff\xa5w\x1e,\x00\x00\x00\x00\t\xed\xaf\xe0\x00\x00\x00\x00\nݒ\xd0\x00\x00\x00\x00\v\xfad\xe0\x00\x00\x00\x00" + + "\f\xbe\xc6P\x00\x00\x00\x00\r\xa49`\x00\x00\x00\x00\x0e\x8a\xe1\xd0\x00\x00\x00\x00\x0f\x84\x1b`\x00\x00\x00\x00\x10uO\xd0\x00\x00\x00\x00\x11c\xfd`\x00\x00\x00\x00\x12S\xe0P\x00\x00\x00\x00\x13M\x19\xe0" + + "\x00\x00\x00\x00\x143\xc2P\x00\x00\x00\x00\x15#\xc1`\x00\x00\x00\x00\x16\x13\xa4P\x00\x00\x00\x00\x17\x03\xa3`\x00\x00\x00\x00\x17\xf3\x86P\x00\x00\x00\x00\x18\xe3\x85`\x00\x00\x00\x00\x19\xd3hP\x00\x00\x00\x00" + + "\x1a\xc3g`\x00\x00\x00\x00\x1b\xbc\x84\xd0\x00\x00\x00\x00\x1c\xac\x83\xe0\x00\x00\x00\x00\x1d\x9cf\xd0\x00\x00\x00\x00\x1e\x8ce\xe0\x00\x00\x00\x00\x1f|H\xd0\x00\x00\x00\x00 lG\xe0\x00\x00\x00\x00!\\*\xd0" + + "\x00\x00\x00\x00\"L)\xe0\x00\x00\x00\x00#<\f\xd0\x00\x00\x00\x00$,\v\xe0\x00\x00\x00\x00%\x1b\xee\xd0\x00\x00\x00\x00&\v\xed\xe0\x00\x00\x00\x00'\x05\vP\x00\x00\x00\x00'\xf5\n`\x00\x00\x00\x00" + + "(\xe4\xedP\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xc4\xcfP\x00\x00\x00\x00+\xb4\xce`\x00\x00\x00\x00,\xa4\xb1P\x00\x00\x00\x00-\x94\xb0`\x00\x00\x00\x00.\x84\x93P\x00\x00\x00\x00/t\x92`" + + "\x00\x00\x00\x000duP\x00\x00\x00\x001]\xae\xe0\x00\x00\x00\x002M\x91\xd0\x00\x00\x00\x003=\x90\xe0\x00\x00\x00\x004-s\xd0\x00\x00\x00\x005\x1dr\xe0\x00\x00\x00\x0062x\x10\x00\x00\x00\x00" + + "6\xfd\u007f\x10\x00\x00\x00\x008\x1b\x94\x90\x00\x00\x00\x008\xdda\x10\x00\x00\x00\x009\xfbv\x90\x00\x00\x00\x00:\xbdC\x10\x00\x00\x00\x00;\xdbX\x90\x00\x00\x00\x00<\xa6_\x90\x00\x00\x00\x00=\xbb:\x90" + + "\x00\x00\x00\x00>\x86A\x90\x00\x00\x00\x00?\x9b\x1c\x90\x00\x00\x00\x00@f#\x90\x00\x00\x00\x00A\x849\x10\x00\x00\x00\x00BF\x05\x90\x00\x00\x00\x00Cd\x1b\x10\x00\x00\x00\x00D%\xe7\x90\x00\x00\x00\x00" + + "EC\xfd\x10\x00\x00\x00\x00F\x05ɐ\x00\x00\x00\x00G#\xdf\x10\x00\x00\x00\x00G\xee\xe6\x10\x00\x00\x00\x00I\x03\xc1\x10\x00\x00\x00\x00I\xce\xc8\x10\x00\x00\x00\x00J\xe3\xa3\x10\x00\x00\x00\x00K\xae\xaa\x10" + + "\x00\x00\x00\x00L̿\x90\x00\x00\x00\x00M\x8e\x8c\x10\x00\x00\x00\x00N\xac\xa1\x90\x00\x00\x00\x00Onn\x10\x00\x00\x00\x00P\x8c\x83\x90\x00\x00\x00\x00QW\x8a\x90\x00\x00\x00\x00Rle\x90\x00\x00\x00\x00" + + "S7l\x90\x00\x00\x00\x00TLG\x90\x00\x00\x00\x00U\x17N\x90\x00\x00\x00\x00V,)\x90\x00\x00\x00\x00V\xf70\x90\x00\x00\x00\x00W\xd0\u007f\xd0\x00\x00\x00\x00Y\xf5(\x10\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x03\x02\x00\x00\x1f\xd4\x00\x00\x00\x00*0\x01\x04\x00\x00\x1c \x00\t\x00\x00*0\x00\rLMT\x00EEST\x00EET\x00+03\x00\n" + + "EET-2EEST,M3.5.0/3,M10.5.0/4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x84)\r\xbd\xec\x00\x00\x00\xec\x00\x00\x00\v\x00\x1c\x00A" + + "sia/SaigonUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\t\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xff\x88\x8cC\x80\xff\xff\xff\xff\x91\xa3+\n\xff\xff\xff\xff\xcd5\xe6\x80\xff\xff\xff\xff\xd1Y\xcep\xff\xff\xff\xff\xd2;>\xf0\xff\xff\xff\xff\xd52\xbb" + + "\x10\xff\xff\xff\xff\xe4\xb6\xe4\x80\xff\xff\xff\xff\xed/\x98\x00\x00\x00\x00\x00\n=\xc7\x00\x01\x02\x03\x04\x02\x03\x02\x03\x02\x00\x00d\x00\x00\x00\x00\x00c\xf6\x00\x04\x00\x00bp\x00\t\x00\x00p\x80\x00\r\x00\x00" + + "~\x90\x00\x11LMT\x00PLMT\x00+07\x00+08\x00+09\x00\n<+07>-7\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS*\xe4@\xa9\x89\x01\x00\x00\x89\x01\x00\x00" + + "\v\x00\x1c\x00Asia/HarbinUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\x00\x00\x00\a\x00\x00\x00\x1f\xff\xff\xff\xff\x8b\xff\x8e\x00\xff\xff\xff\xff\xba\x16\xdf\x00\xff\xff\xff\xff\xcby\xa4\b\xff\xff\xff\xff\xd2V\xeep\xff\xff\xff\xff\xd7<\xc6\b\xff\xff" + - "\xff\xff\xda\xff&\x00\xff\xff\xff\xff\xf4\xb5\xbe\x88\x00\x00\x00\x00!\xdat\x80\x01\x02\x03\x02\x04\x02\x05\x06\x00\x00f\x80\x00\x00\x00\x00f\x80\x00\x04\x00\x00ix\x00\b\x00\x00~\x90\x00\x0e\x00\x00p\x80\x00\x12" + - "\x00\x00p\x80\x00\x16\x00\x00bp\x00\x1bLMT\x00PMT\x00+0730\x00+09\x00+08\x00WITA\x00WIB\x00\nWIB-7\nPK\x03\x04\n\x00\x00\x00\x00\x00" + - "\xf1c9R;\u007fP\x8d\xd4\a\x00\x00\xd4\a\x00\x00\v\x00\x1c\x00Asia/TehranUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00T" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff~6C)\xff\xff\xff\xff\xa0\x97\xa2\x80\xff\xff\xff\xff\xa1y\x04\xf0\xff\xff\xff\xff\xc8Y^\x80\xff\xff\xff\xff\xc9\t\xf9p\xff\xff" + + "\xff\xff\xc9ӽ\x00\xff\xff\xff\xff\xcb\x05\x8a\xf0\xff\xff\xff\xff\xcb|@\x00\xff\xff\xff\xff\xd2;>\xf0\xff\xff\xff\xffӋ{\x80\xff\xff\xff\xff\xd4B\xad\xf0\xff\xff\xff\xff\xd5E\"\x00\xff\xff\xff\xff\xd6L" + + "\xbf\xf0\xff\xff\xff\xff\xd7<\xbf\x00\xff\xff\xff\xff\xd8\x06fp\xff\xff\xff\xff\xd9\x1d\xf2\x80\xff\xff\xff\xff\xd9A|\xf0\x00\x00\x00\x00\x1e\xbaR \x00\x00\x00\x00\x1fi\x9b\x90\x00\x00\x00\x00 ~\x84\xa0\x00\x00" + + "\x00\x00!I}\x90\x00\x00\x00\x00\"g\xa1 \x00\x00\x00\x00#)_\x90\x00\x00\x00\x00$G\x83 \x00\x00\x00\x00%\x12|\x10\x00\x00\x00\x00&'e \x00\x00\x00\x00&\xf2^\x10\x00\x00\x00\x00(\a" + + "G \x00\x00\x00\x00(\xd2@\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00q\xd7\x00\x00\x00\x00~\x90\x01\x04\x00\x00p\x80\x00\bLMT" + + "\x00CDT\x00CST\x00\nCST-8\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xba\xa3b\xc1R\x02\x00\x00R\x02\x00\x00\t\x00\x1c\x00Asia/HovdUT\t\x00\x03" + + "\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x002\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff" + + "\xff\xff\x86\xd3\xfc\x94\x00\x00\x00\x00\x0f\v\xea\xa0\x00\x00\x00\x00\x18\xe9\u0590\x00\x00\x00\x00\x19\xdb\v\x00\x00\x00\x00\x00\x1a\xcc[\x90\x00\x00\x00\x00\x1b\xbc>\x80\x00\x00\x00\x00\x1c\xac=\x90\x00\x00\x00\x00\x1d\x9c" + + " \x80\x00\x00\x00\x00\x1e\x8c\x1f\x90\x00\x00\x00\x00\x1f|\x02\x80\x00\x00\x00\x00 l\x01\x90\x00\x00\x00\x00![\xe4\x80\x00\x00\x00\x00\"K\xe3\x90\x00\x00\x00\x00#;ƀ\x00\x00\x00\x00$+Ő\x00\x00" + + "\x00\x00%\x1b\xa8\x80\x00\x00\x00\x00&\v\xa7\x90\x00\x00\x00\x00'\x04\xc5\x00\x00\x00\x00\x00'\xf4\xc4\x10\x00\x00\x00\x00(\xe4\xa7\x00\x00\x00\x00\x00)Ԧ\x10\x00\x00\x00\x00*ĉ\x00\x00\x00\x00\x00+\xb4" + + "\x88\x10\x00\x00\x00\x00,\xa4k\x00\x00\x00\x00\x00-\x94j\x10\x00\x00\x00\x00.\x84M\x00\x00\x00\x00\x00/tL\x10\x00\x00\x00\x000d/\x00\x00\x00\x00\x001]h\x90\x00\x00\x00\x002MK\x80\x00\x00" + + "\x00\x003=J\x90\x00\x00\x00\x004--\x80\x00\x00\x00\x005\x1d,\x90\x00\x00\x00\x006\r\x0f\x80\x00\x00\x00\x00:\xe9\xc1\xb0\x00\x00\x00\x00;\xb4\xba\xa0\x00\x00\x00\x00<\xa4\xb9\xb0\x00\x00\x00\x00=\x94" + + "\x9c\xa0\x00\x00\x00\x00>\x84\x9b\xb0\x00\x00\x00\x00?t~\xa0\x00\x00\x00\x00@d}\xb0\x00\x00\x00\x00AT`\xa0\x00\x00\x00\x00BD_\xb0\x00\x00\x00\x00C4B\xa0\x00\x00\x00\x00D$A\xb0\x00\x00" + + "\x00\x00E\x1d_ \x00\x00\x00\x00U\x15\xa8\xb0\x00\x00\x00\x00V\x05o\x80\x00\x00\x00\x00V\xf5\x8a\xb0\x00\x00\x00\x00W\xe5Q\x80\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x00\x00U\xec\x00\x00\x00\x00T`\x00\x04\x00\x00p\x80\x01\b\x00\x00bp\x00\fLMT\x00+06\x00" + + "+08\x00+07\x00\n<+07>-7\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xa9z\xc8\x1f\xce\x04\x00\x00\xce\x04\x00\x00\t\x00\x1c\x00Asia/GazaUT\t\x00" + + "\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00u\x00\x00\x00\x05\x00\x00\x00\x15\xff" + + "\xff\xff\xff}\xbdJ\xb0\xff\xff\xff\xff\xc8Y\xcf\x00\xff\xff\xff\xff\xc8\xfa\xa6\x00\xff\xff\xff\xff\xc98\x9c\x80\xff\xff\xff\xff\xcc\xe5\xeb\x80\xff\xff\xff\xffͬ\xfe\x00\xff\xff\xff\xff\xce\xc7\x1f\x00\xff\xff\xff\xff\xcf" + + "\x8f\x83\x00\xff\xff\xff\xffЩ\xa4\x00\xff\xff\xff\xffф}\x00\xff\xff\xff\xffҊ׀\xff\xff\xff\xff\xd3e\xb0\x80\xff\xff\xff\xff\xd4l\v\x00\xff\xff\xff\xff\xe86c`\xff\xff\xff\xff\xe8\xf4-P\xff" + + "\xff\xff\xff\xea\v\xb9`\xff\xff\xff\xff\xea\xd5`\xd0\xff\xff\xff\xff\xeb\xec\xfa\xf0\xff\xff\xff\xff\xec\xb5m\x00\xff\xff\xff\xff\xed\xcf\u007f\xf0\xff\xff\xff\xff\xee\x97\xf2\x00\xff\xff\xff\xffﰳp\xff\xff\xff\xff\xf0" + + "y%\x80\xff\xff\xff\xff\xf1\x91\xe6\xf0\xff\xff\xff\xff\xf2ZY\x00\xff\xff\xff\xff\xf3s\x1ap\xff\xff\xff\xff\xf4;\x8c\x80\xff\xff\xff\xff\xf5U\x9fp\xff\xff\xff\xff\xf6\x1e\x11\x80\xff\xff\xff\xff\xf76\xd2\xf0\xff" + + "\xff\xff\xff\xf7\xffE\x00\xff\xff\xff\xff\xf9\x18\x06p\xff\xff\xff\xff\xf9\xe1\xca\x00\xff\xff\xff\xff\xfa\xf99\xf0\xff\xff\xff\xff\xfb'BP\x00\x00\x00\x00\b|\x8b\xe0\x00\x00\x00\x00\b\xfd\xb0\xd0\x00\x00\x00\x00\t" + + "\xf6\xea`\x00\x00\x00\x00\n\xa63\xd0\x00\x00\x00\x00\x13\xe9\xfc`\x00\x00\x00\x00\x14![`\x00\x00\x00\x00\x1a\xfa\xc6`\x00\x00\x00\x00\x1b\x8en`\x00\x00\x00\x00\x1c\xbe\xf8\xe0\x00\x00\x00\x00\x1dw|\xd0\x00" + + "\x00\x00\x00\x1e\xcc\xff`\x00\x00\x00\x00\x1f`\x99P\x00\x00\x00\x00 \x82\xb1`\x00\x00\x00\x00!I\xb5\xd0\x00\x00\x00\x00\"^\x9e\xe0\x00\x00\x00\x00# ]P\x00\x00\x00\x00$Z0`\x00\x00\x00\x00%" + + "\x00?P\x00\x00\x00\x00&\v\xed\xe0\x00\x00\x00\x00&\xd6\xe6\xd0\x00\x00\x00\x00'\xeb\xcf\xe0\x00\x00\x00\x00(\xc0\x03P\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xa9\x1f\xd0\x00\x00\x00\x00+\xbbe\xe0\x00" + + "\x00\x00\x00,\x89\x01\xd0\x00\x00\x00\x00-\x9bG\xe0\x00\x00\x00\x00._\xa9P\x00\x00\x00\x00/{)\xe0\x00\x00\x00\x000H\xc5\xd0\x00\x00\x00\x000\xe7\a\xe0\x00\x00\x00\x001dF`\x00\x00\x00\x002" + + "A\xc2`\x00\x00\x00\x003D(`\x00\x00\x00\x004!\xa4`\x00\x00\x00\x005$\n`\x00\x00\x00\x006\x01\x86`\x00\x00\x00\x007\x16a`\x00\x00\x00\x008\x06DP\x00\x00\x00\x008\xff}\xe0\x00" + + "\x00\x00\x009\xef`\xd0\x00\x00\x00\x00:\xdf_\xe0\x00\x00\x00\x00;\xcfB\xd0\x00\x00\x00\x00<\xbfA\xe0\x00\x00\x00\x00=\xaf$\xd0\x00\x00\x00\x00>\x9f#\xe0\x00\x00\x00\x00?\x8f\x06\xd0\x00\x00\x00\x00@" + + "\u007f\x05\xe0\x00\x00\x00\x00A\\\x81\xe0\x00\x00\x00\x00B^\xe7\xe0\x00\x00\x00\x00CA\xb7\xf0\x00\x00\x00\x00D-\xa6`\x00\x00\x00\x00E\x12\xfdP\x00\x00\x00\x00F\x0e\xd9\xe0\x00\x00\x00\x00F\xe8op\x00" + + "\x00\x00\x00G\xec\x18\xe0\x00\x00\x00\x00H\xb7\x11\xd0\x00\x00\x00\x00I\xcb\xfa\xe0\x00\x00\x00\x00J\xa0<`\x00\x00\x00\x00K\xad.\x9c\x00\x00\x00\x00La\xbd\xd0\x00\x00\x00\x00M\x94\xf9\x9c\x00\x00\x00\x00N" + + "5\xc2P\x00\x00\x00\x00Ot\xdb`\x00\x00\x00\x00P[\x91\xe0\x00\x00\x00\x00QT\xbd`\x00\x00\x00\x00RD\xa0P\x00\x00\x00\x00S4\x9f`\x00\x00\x00\x00TIlP\x00\x00\x00\x00U\x15\xd2\xe0\x00" + + "\x00\x00\x00V)\\`\x00\x00\x00\x00V\xf5\xc2\xf0\x00\x00\x00\x00X\x13\xca`\x00\x00\x00\x00Xդ\xf0\x00\x00\x00\x00Y\xf3\xac`\x00\x00\x00\x00Z\xb5\x86\xf0\x00\x00\x00\x00[ӎ`\x00\x00\x00\x00\\" + + "\x9dC\xe0\x00\x00\x00\x00]\xb3bP\x00\x00\x00\x00^~w`\x00\x00\x00\x00_\x93R`\x00\x00\x00\x00`^Y`\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00 P\x00\x00\x00\x00*0\x01\x04\x00\x00\x1c \x00\t\x00\x00*0\x01\r\x00\x00\x1c " + + "\x00\x11LMT\x00EEST\x00EET\x00IDT\x00IST\x00\nEET-2EEST,M3.4.4/48,M10.5.5/1\nPK\x03\x04\n\x00" + + "\x00\x00\x00\x00#\x82iS:\x11\xea\xa2\xe5\x02\x00\x00\xe5\x02\x00\x00\t\x00\x1c\x00Asia/OmskUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01" + + "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00A\x00\x00\x00\x06\x00\x00\x00\x10\xff\xff\xff\xff\xa1\xb3@\xb6\xff\xff\xff\xff\xb5\xa3\xef0\x00\x00\x00\x00\x15'}\xa0" + + "\x00\x00\x00\x00\x16\x18\xb2\x10\x00\x00\x00\x00\x17\b\xb1 \x00\x00\x00\x00\x17\xf9\xe5\x90\x00\x00\x00\x00\x18\xe9\xe4\xa0\x00\x00\x00\x00\x19\xdb\x19\x10\x00\x00\x00\x00\x1a\xcci\xa0\x00\x00\x00\x00\x1b\xbcv\xc0\x00\x00\x00\x00" + + "\x1c\xacg\xc0\x00\x00\x00\x00\x1d\x9cX\xc0\x00\x00\x00\x00\x1e\x8cI\xc0\x00\x00\x00\x00\x1f|:\xc0\x00\x00\x00\x00 l+\xc0\x00\x00\x00\x00!\\\x1c\xc0\x00\x00\x00\x00\"L\r\xc0\x00\x00\x00\x00#;\xfe\xc0" + + "\x00\x00\x00\x00$+\xef\xc0\x00\x00\x00\x00%\x1b\xe0\xc0\x00\x00\x00\x00&\v\xd1\xc0\x00\x00\x00\x00'\x04\xfd@\x00\x00\x00\x00'\xf4\xee@\x00\x00\x00\x00(\xe4\xedP\x00\x00\x00\x00)x\x95P\x00\x00\x00\x00" + + ")\xd4\xd0@\x00\x00\x00\x00*\xc4\xc1@\x00\x00\x00\x00+\xb4\xb2@\x00\x00\x00\x00,\xa4\xa3@\x00\x00\x00\x00-\x94\x94@\x00\x00\x00\x00.\x84\x85@\x00\x00\x00\x00/tv@\x00\x00\x00\x000dg@" + + "\x00\x00\x00\x001]\x92\xc0\x00\x00\x00\x002rm\xc0\x00\x00\x00\x003=t\xc0\x00\x00\x00\x004RO\xc0\x00\x00\x00\x005\x1dV\xc0\x00\x00\x00\x00621\xc0\x00\x00\x00\x006\xfd8\xc0\x00\x00\x00\x00" + + "8\x1bN@\x00\x00\x00\x008\xdd\x1a\xc0\x00\x00\x00\x009\xfb0@\x00\x00\x00\x00:\xbc\xfc\xc0\x00\x00\x00\x00;\xdb\x12@\x00\x00\x00\x00<\xa6\x19@\x00\x00\x00\x00=\xba\xf4@\x00\x00\x00\x00>\x85\xfb@" + + "\x00\x00\x00\x00?\x9a\xd6@\x00\x00\x00\x00@e\xdd@\x00\x00\x00\x00A\x83\xf2\xc0\x00\x00\x00\x00BE\xbf@\x00\x00\x00\x00Cc\xd4\xc0\x00\x00\x00\x00D%\xa1@\x00\x00\x00\x00EC\xb6\xc0\x00\x00\x00\x00" + + "F\x05\x83@\x00\x00\x00\x00G#\x98\xc0\x00\x00\x00\x00G\xee\x9f\xc0\x00\x00\x00\x00I\x03z\xc0\x00\x00\x00\x00I\u0381\xc0\x00\x00\x00\x00J\xe3\\\xc0\x00\x00\x00\x00K\xaec\xc0\x00\x00\x00\x00L\xccy@" + + "\x00\x00\x00\x00M\x8eE\xc0\x00\x00\x00\x00TK\xf30\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x05\x03\x00\x00D\xca\x00\x00\x00\x00FP\x00\x04\x00\x00bp\x01\b\x00\x00T`\x00\f\x00\x00T`\x01\f\x00\x00bp\x00\bLMT" + + "\x00+05\x00+07\x00+06\x00\n<+06>-6\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS?Y\xaf\x19\xe7\x00\x00\x00\xe7\x00\x00\x00\n\x00\x1c\x00Asia/Dac" + + "caUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00" + + "\x06\x00\x00\x00\x1c\xff\xff\xff\xffi\x86\x86\xbc\xff\xff\xff\xff\xcaۆ\xb0\xff\xff\xff\xff\xcc\x05q\x18\xff\xff\xff\xff̕2\xa8\xff\xff\xff\xffݨҘ\x00\x00\x00\x00J;\xc4\x10\x00\x00\x00\x00K<\xd8" + + "\x90\x01\x02\x03\x02\x04\x05\x04\x00\x00T\xc4\x00\x00\x00\x00R\xd0\x00\x04\x00\x00[h\x00\b\x00\x00MX\x00\x0e\x00\x00T`\x00\x14\x00\x00bp\x01\x18LMT\x00HMT\x00+0630\x00+0" + + "530\x00+06\x00+07\x00\n<+06>-6\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSB\x1d\xc6\x1b\x85\x00\x00\x00\x85\x00\x00\x00\v\x00\x1c\x00Asia/Urum" + + "qiUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" + + "\x02\x00\x00\x00\b\xff\xff\xff\xff\xb0\xfe\xbad\x01\x00\x00R\x1c\x00\x00\x00\x00T`\x00\x04LMT\x00+06\x00\n<+06>-6\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS?Y\xaf" + + "\x19\xe7\x00\x00\x00\xe7\x00\x00\x00\n\x00\x1c\x00Asia/DhakaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x1c\xff\xff\xff\xffi\x86\x86\xbc\xff\xff\xff\xff\xcaۆ\xb0\xff\xff\xff\xff\xcc\x05q\x18\xff\xff\xff\xff̕2\xa8\xff\xff" + + "\xff\xffݨҘ\x00\x00\x00\x00J;\xc4\x10\x00\x00\x00\x00K<ؐ\x01\x02\x03\x02\x04\x05\x04\x00\x00T\xc4\x00\x00\x00\x00R\xd0\x00\x04\x00\x00[h\x00\b\x00\x00MX\x00\x0e\x00\x00T`\x00\x14\x00" + + "\x00bp\x01\x18LMT\x00HMT\x00+0630\x00+0530\x00+06\x00+07\x00\n<+06>-6\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSE\t\xfa-" + + "\a\x03\x00\x00\a\x03\x00\x00\x0e\x00\x1c\x00Asia/Hong_KongUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00E\x00\x00\x00\x05\x00\x00\x00\x16\xff\xff\xff\xff\x85ic\x90\xff\xff\xff\xff\xcaM10\xff\xff\xff\xff\xcaۓ0\xff\xff\xff\xff\xcbKq" + + "x\xff\xff\xff\xffҠސ\xff\xff\xff\xff\xd3k׀\xff\xff\xff\xffԓX\xb8\xff\xff\xff\xff\xd5B\xb08\xff\xff\xff\xff\xd6s:\xb8\xff\xff\xff\xff\xd7>A\xb8\xff\xff\xff\xff\xd8.2\xb8\xff\xff\xff" + + "\xff\xd8\xf99\xb8\xff\xff\xff\xff\xda\x0e\x14\xb8\xff\xff\xff\xff\xda\xd9\x1b\xb8\xff\xff\xff\xff\xdb\xed\xf6\xb8\xff\xff\xff\xffܸ\xfd\xb8\xff\xff\xff\xff\xdd\xcdظ\xff\xff\xff\xffޢ\x1a8\xff\xff\xff\xff߶\xf5" + + "8\xff\xff\xff\xff\xe0\x81\xfc8\xff\xff\xff\xff\xe1\x96\xc9(\xff\xff\xff\xff\xe2Oi8\xff\xff\xff\xff\xe3v\xab(\xff\xff\xff\xff\xe4/K8\xff\xff\xff\xff\xe5_Ǩ\xff\xff\xff\xff\xe6\x0f-8\xff\xff\xff" + + "\xff\xe7?\xa9\xa8\xff\xff\xff\xff\xe7\xf8I\xb8\xff\xff\xff\xff\xe9\x1f\x8b\xa8\xff\xff\xff\xff\xe9\xd8+\xb8\xff\xff\xff\xff\xea\xffm\xa8\xff\xff\xff\xff\xeb\xb8\r\xb8\xff\xff\xff\xff\xec\xdfO\xa8\xff\xff\xff\xff\xed\x97\xef" + + "\xb8\xff\xff\xff\xff\xee\xc8l(\xff\xff\xff\xff\xefwѸ\xff\xff\xff\xff\xf0\xa8N(\xff\xff\xff\xff\xf1W\xb3\xb8\xff\xff\xff\xff\xf2\x880(\xff\xff\xff\xff\xf3@\xd08\xff\xff\xff\xff\xf4h\x12(\xff\xff\xff" + + "\xff\xf5 \xb28\xff\xff\xff\xff\xf6G\xf4(\xff\xff\xff\xff\xf7%~8\xff\xff\xff\xff\xf8\x15a(\xff\xff\xff\xff\xf9\x05`8\xff\xff\xff\xff\xf9\xf5C(\xff\xff\xff\xff\xfa\xe5B8\xff\xff\xff\xff\xfb\xde_" + + "\xa8\xff\xff\xff\xff\xfc\xce^\xb8\xff\xff\xff\xff\xfd\xbeA\xa8\xff\xff\xff\xff\xfe\xae@\xb8\xff\xff\xff\xff\xff\x9e#\xa8\x00\x00\x00\x00\x00\x8e\"\xb8\x00\x00\x00\x00\x01~\x05\xa8\x00\x00\x00\x00\x02n\x04\xb8\x00\x00\x00" + + "\x00\x03]\xe7\xa8\x00\x00\x00\x00\x04M\xe6\xb8\x00\x00\x00\x00\x05G\x04(\x00\x00\x00\x00\x067\x038\x00\x00\x00\x00\a&\xe6(\x00\x00\x00\x00\a\x83=8\x00\x00\x00\x00\t\x06\xc8(\x00\x00\x00\x00\t\xf6\xc7" + + "8\x00\x00\x00\x00\n\xe6\xaa(\x00\x00\x00\x00\v֩8\x00\x00\x00\x00\fƌ(\x00\x00\x00\x00\x11\x9b98\x00\x00\x00\x00\x12ol\xa8\x01\x02\x03\x04\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00k\n\x00\x00\x00\x00p\x80" + + "\x00\x04\x00\x00~\x90\x01\b\x00\x00w\x88\x01\r\x00\x00~\x90\x00\x12LMT\x00HKT\x00HKST\x00HKWT\x00JST\x00\nHKT-8\nPK\x03\x04\n\x00\x00\x00\x00\x00#" + + "\x82iS\\\x91\x87\xbb\xf7\x00\x00\x00\xf7\x00\x00\x00\f\x00\x1c\x00Asia/ColomboUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00T" + "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc9\x00\x00\x00\x06\x00\x00\x00\x1c\xff\xff\xff\xff\x9al}\xc8\xff\xff\xff\xff\xd2\xdb\x12\xc8\x00\x00\x00\x00\x0e\xbb\xa2H\x00\x00" + - "\x00\x00\x0ft-@\x00\x00\x00\x00\x10\x8e@0\x00\x00\x00\x00\x10\xed:@\x00\x00\x00\x00\x11Ug\xc8\x00\x00\x00\x00\x12EJ\xb8\x00\x00\x00\x00\x137\xec\xc8\x00\x00\x00\x00\x14-\x15\xb8\x00\x00\x00\x00( " + - "v\xc8\x00\x00\x00\x00(\u06dd\xb8\x00\x00\x00\x00)˜\xc8\x00\x00\x00\x00*\xbe\"\xb8\x00\x00\x00\x00+\xac\xd0H\x00\x00\x00\x00,\x9fV8\x00\x00\x00\x00-\x8e\x03\xc8\x00\x00\x00\x00.\x80\x89\xb8\x00\x00" + - "\x00\x00/o7H\x00\x00\x00\x000a\xbd8\x00\x00\x00\x001Pj\xc8\x00\x00\x00\x002B\xf0\xb8\x00\x00\x00\x0032\xef\xc8\x00\x00\x00\x004%u\xb8\x00\x00\x00\x005\x14#H\x00\x00\x00\x006\x06" + - "\xa98\x00\x00\x00\x006\xf5V\xc8\x00\x00\x00\x007\xe7ܸ\x00\x00\x00\x008֊H\x00\x00\x00\x009\xc9\x108\x00\x00\x00\x00:\xb9\x0fH\x00\x00\x00\x00;\xab\x958\x00\x00\x00\x00<\x9aB\xc8\x00\x00" + - "\x00\x00=\x8cȸ\x00\x00\x00\x00>{vH\x00\x00\x00\x00?m\xfc8\x00\x00\x00\x00@\\\xa9\xc8\x00\x00\x00\x00AO/\xb8\x00\x00\x00\x00B?.\xc8\x00\x00\x00\x00C1\xb4\xb8\x00\x00\x00\x00G\xe2" + - "\xc9H\x00\x00\x00\x00H\xd5O8\x00\x00\x00\x00I\xc5NH\x00\x00\x00\x00J\xb7\xd48\x00\x00\x00\x00K\xa6\x81\xc8\x00\x00\x00\x00L\x99\a\xb8\x00\x00\x00\x00M\x87\xb5H\x00\x00\x00\x00Nz;8\x00\x00" + - "\x00\x00Oh\xe8\xc8\x00\x00\x00\x00P[n\xb8\x00\x00\x00\x00QKm\xc8\x00\x00\x00\x00R=\xf3\xb8\x00\x00\x00\x00S,\xa1H\x00\x00\x00\x00T\x1f'8\x00\x00\x00\x00U\r\xd4\xc8\x00\x00\x00\x00V\x00" + - "Z\xb8\x00\x00\x00\x00V\xef\bH\x00\x00\x00\x00W\xe1\x8e8\x00\x00\x00\x00XэH\x00\x00\x00\x00Y\xc4\x138\x00\x00\x00\x00Z\xb2\xc0\xc8\x00\x00\x00\x00[\xa5F\xb8\x00\x00\x00\x00\\\x93\xf4H\x00\x00" + - "\x00\x00]\x86z8\x00\x00\x00\x00^u'\xc8\x00\x00\x00\x00_g\xad\xb8\x00\x00\x00\x00`W\xac\xc8\x00\x00\x00\x00aJ2\xb8\x00\x00\x00\x00b8\xe0H\x00\x00\x00\x00c+f8\x00\x00\x00\x00d\x1a" + - "\x13\xc8\x00\x00\x00\x00e\f\x99\xb8\x00\x00\x00\x00e\xfbGH\x00\x00\x00\x00f\xed\xcd8\x00\x00\x00\x00g\xdd\xccH\x00\x00\x00\x00h\xd0R8\x00\x00\x00\x00i\xbe\xff\xc8\x00\x00\x00\x00j\xb1\x85\xb8\x00\x00" + - "\x00\x00k\xa03H\x00\x00\x00\x00l\x92\xb98\x00\x00\x00\x00m\x81f\xc8\x00\x00\x00\x00ns\xec\xb8\x00\x00\x00\x00ob\x9aH\x00\x00\x00\x00pU 8\x00\x00\x00\x00qE\x1fH\x00\x00\x00\x00r7" + - "\xa58\x00\x00\x00\x00s&R\xc8\x00\x00\x00\x00t\x18ظ\x00\x00\x00\x00u\a\x86H\x00\x00\x00\x00u\xfa\f8\x00\x00\x00\x00v\xe8\xb9\xc8\x00\x00\x00\x00w\xdb?\xb8\x00\x00\x00\x00x\xcb>\xc8\x00\x00" + - "\x00\x00y\xbdĸ\x00\x00\x00\x00z\xacrH\x00\x00\x00\x00{\x9e\xf88\x00\x00\x00\x00|\x8d\xa5\xc8\x00\x00\x00\x00}\x80+\xb8\x00\x00\x00\x00~n\xd9H\x00\x00\x00\x00\u007fa_8\x00\x00\x00\x00\x80Q" + - "^H\x00\x00\x00\x00\x81C\xe48\x00\x00\x00\x00\x822\x91\xc8\x00\x00\x00\x00\x83%\x17\xb8\x00\x00\x00\x00\x84\x13\xc5H\x00\x00\x00\x00\x85\x06K8\x00\x00\x00\x00\x85\xf4\xf8\xc8\x00\x00\x00\x00\x86\xe7~\xb8\x00\x00" + - "\x00\x00\x87\xd7}\xc8\x00\x00\x00\x00\x88\xca\x03\xb8\x00\x00\x00\x00\x89\xb8\xb1H\x00\x00\x00\x00\x8a\xab78\x00\x00\x00\x00\x8b\x99\xe4\xc8\x00\x00\x00\x00\x8c\x8cj\xb8\x00\x00\x00\x00\x8d{\x18H\x00\x00\x00\x00\x8em" + - "\x9e8\x00\x00\x00\x00\x8f]\x9dH\x00\x00\x00\x00\x90P#8\x00\x00\x00\x00\x91>\xd0\xc8\x00\x00\x00\x00\x921V\xb8\x00\x00\x00\x00\x93 \x04H\x00\x00\x00\x00\x94\x12\x8a8\x00\x00\x00\x00\x95\x017\xc8\x00\x00" + - "\x00\x00\x95\xf3\xbd\xb8\x00\x00\x00\x00\x96\xe3\xbc\xc8\x00\x00\x00\x00\x97\xd6B\xb8\x00\x00\x00\x00\x98\xc4\xf0H\x00\x00\x00\x00\x99\xb7v8\x00\x00\x00\x00\x9a\xa6#\xc8\x00\x00\x00\x00\x9b\x98\xa9\xb8\x00\x00\x00\x00\x9c\x87" + - "WH\x00\x00\x00\x00\x9dy\xdd8\x00\x00\x00\x00\x9ei\xdcH\x00\x00\x00\x00\x9f\\b8\x00\x00\x00\x00\xa0K\x0f\xc8\x00\x00\x00\x00\xa1=\x95\xb8\x00\x00\x00\x00\xa2,CH\x00\x00\x00\x00\xa3\x1e\xc98\x00\x00" + - "\x00\x00\xa4\rv\xc8\x00\x00\x00\x00\xa4\xff\xfc\xb8\x00\x00\x00\x00\xa5\xef\xfb\xc8\x00\x00\x00\x00\xa6⁸\x00\x00\x00\x00\xa7\xd1/H\x00\x00\x00\x00\xa8õ8\x00\x00\x00\x00\xa9\xb2b\xc8\x00\x00\x00\x00\xaa\xa4" + - "\xe8\xb8\x00\x00\x00\x00\xab\x93\x96H\x00\x00\x00\x00\xac\x86\x1c8\x00\x00\x00\x00\xadt\xc9\xc8\x00\x00\x00\x00\xaegO\xb8\x00\x00\x00\x00\xafWN\xc8\x00\x00\x00\x00\xb0IԸ\x00\x00\x00\x00\xb18\x82H\x00\x00" + - "\x00\x00\xb2+\b8\x00\x00\x00\x00\xb3\x19\xb5\xc8\x00\x00\x00\x00\xb4\f;\xb8\x00\x00\x00\x00\xb4\xfa\xe9H\x00\x00\x00\x00\xb5\xedo8\x00\x00\x00\x00\xb6\xddnH\x00\x00\x00\x00\xb7\xcf\xf48\x00\x00\x00\x00\xb8\xbe" + - "\xa1\xc8\x00\x00\x00\x00\xb9\xb1'\xb8\x00\x00\x00\x00\xba\x9f\xd5H\x00\x00\x00\x00\xbb\x92[8\x00\x00\x00\x00\xbc\x81\b\xc8\x00\x00\x00\x00\xbds\x8e\xb8\x00\x00\x00\x00\xbec\x8d\xc8\x00\x00\x00\x00\xbfV\x13\xb8\x00\x00" + - "\x00\x00\xc0D\xc1H\x00\x00\x00\x00\xc17G8\x00\x00\x00\x00\xc2%\xf4\xc8\x00\x00\x00\x00\xc3\x18z\xb8\x00\x00\x00\x00\xc4\a(H\x00\x00\x00\x00\xc4\xf9\xae8\x00\x00\x00\x00\xc5\xe9\xadH\x00\x00\x00\x00\xc6\xdc" + - "38\x00\x00\x00\x00\xc7\xca\xe0\xc8\x00\x00\x00\x00Ƚf\xb8\x00\x00\x00\x00ɬ\x14H\x00\x00\x00\x00ʞ\x9a8\x00\x00\x00\x00ˍG\xc8\x00\x00\x00\x00\xcc\u007f\u0378\x00\x00\x00\x00\xcdo\xcc\xc8\x00\x00" + - "\x00\x00\xcebR\xb8\x00\x00\x00\x00\xcfQ\x00H\x00\x00\x00\x00\xd0C\x868\x00\x00\x00\x00\xd123\xc8\x00\x00\x00\x00\xd2$\xb9\xb8\x00\x00\x00\x00\xd3\x13gH\x00\x00\x00\x00\xd4\x05\xed8\x00\x00\x00\x00\xd4\xf5" + - "\xecH\x00\x00\x00\x00\xd5\xe8r8\x00\x00\x00\x00\xd6\xd7\x1f\xc8\x00\x00\x00\x00\xd7ɥ\xb8\x00\x00\x00\x00ظSH\x00\x00\x00\x00٪\xd98\x00\x00\x00\x00ڙ\x86\xc8\x00\x00\x00\x00ی\f\xb8\x00\x00" + - "\x00\x00\xdc|\v\xc8\x00\x00\x00\x00\xddn\x91\xb8\x00\x00\x00\x00\xde]?H\x01\x02\x04\x03\x04\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02" + - "\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02" + - "\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02" + - "\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x00\x0008\x00\x00\x00\x0008\x00\x04\x00\x0018\x00" + - "\b\x00\x00FP\x01\x0e\x00\x008@\x00\x12\x00\x00?H\x01\x16LMT\x00TMT\x00+0330\x00+05\x00+04\x00+0430\x00\n<+0330>-3:30" + - "<+0430>,J79/24,J263/24\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rd%\x05\xd8\xe6\x02\x00\x00\xe6\x02\x00\x00\x10\x00\x1c\x00Asia/Vl" + - "adivostokUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00A\x00\x00\x00\x06\x00\x00\x00\x10\xff\xff\xff\xff\xa7YG]\xff\xff\xff\xff\xb5\xa3\xb6\xf0\x00\x00\x00\x00\x15'E`\x00\x00\x00\x00\x16\x18y\xd0\x00\x00\x00\x00\x17\bx\xe0\x00\x00\x00\x00\x17\xf9\xadP" + - "\x00\x00\x00\x00\x18\xe9\xac`\x00\x00\x00\x00\x19\xda\xe0\xd0\x00\x00\x00\x00\x1a\xcc1`\x00\x00\x00\x00\x1b\xbc>\x80\x00\x00\x00\x00\x1c\xac/\x80\x00\x00\x00\x00\x1d\x9c \x80\x00\x00\x00\x00\x1e\x8c\x11\x80\x00\x00\x00\x00" + - "\x1f|\x02\x80\x00\x00\x00\x00 k\xf3\x80\x00\x00\x00\x00![\xe4\x80\x00\x00\x00\x00\"KՀ\x00\x00\x00\x00#;ƀ\x00\x00\x00\x00$+\xb7\x80\x00\x00\x00\x00%\x1b\xa8\x80\x00\x00\x00\x00&\v\x99\x80" + - "\x00\x00\x00\x00'\x04\xc5\x00\x00\x00\x00\x00'\xf4\xb6\x00\x00\x00\x00\x00(\xe4\xb5\x10\x00\x00\x00\x00)x]\x10\x00\x00\x00\x00)Ԙ\x00\x00\x00\x00\x00*ĉ\x00\x00\x00\x00\x00+\xb4z\x00\x00\x00\x00\x00" + - ",\xa4k\x00\x00\x00\x00\x00-\x94\\\x00\x00\x00\x00\x00.\x84M\x00\x00\x00\x00\x00/t>\x00\x00\x00\x00\x000d/\x00\x00\x00\x00\x001]Z\x80\x00\x00\x00\x002r5\x80\x00\x00\x00\x003=<\x80" + - "\x00\x00\x00\x004R\x17\x80\x00\x00\x00\x005\x1d\x1e\x80\x00\x00\x00\x0061\xf9\x80\x00\x00\x00\x006\xfd\x00\x80\x00\x00\x00\x008\x1b\x16\x00\x00\x00\x00\x008\xdc\xe2\x80\x00\x00\x00\x009\xfa\xf8\x00\x00\x00\x00\x00" + - ":\xbcĀ\x00\x00\x00\x00;\xda\xda\x00\x00\x00\x00\x00<\xa5\xe1\x00\x00\x00\x00\x00=\xba\xbc\x00\x00\x00\x00\x00>\x85\xc3\x00\x00\x00\x00\x00?\x9a\x9e\x00\x00\x00\x00\x00@e\xa5\x00\x00\x00\x00\x00A\x83\xba\x80" + - "\x00\x00\x00\x00BE\x87\x00\x00\x00\x00\x00Cc\x9c\x80\x00\x00\x00\x00D%i\x00\x00\x00\x00\x00EC~\x80\x00\x00\x00\x00F\x05K\x00\x00\x00\x00\x00G#`\x80\x00\x00\x00\x00G\xeeg\x80\x00\x00\x00\x00" + - "I\x03B\x80\x00\x00\x00\x00I\xceI\x80\x00\x00\x00\x00J\xe3$\x80\x00\x00\x00\x00K\xae+\x80\x00\x00\x00\x00L\xccA\x00\x00\x00\x00\x00M\x8e\r\x80\x00\x00\x00\x00TK\xba\xf0\x01\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x05\x03\x00\x00{" + - "\xa3\x00\x00\x00\x00~\x90\x00\x04\x00\x00\x9a\xb0\x01\b\x00\x00\x8c\xa0\x00\f\x00\x00\x8c\xa0\x01\f\x00\x00\x9a\xb0\x00\bLMT\x00+09\x00+11\x00+10\x00\n<+10>-10\nP" + - "K\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R:\x11\xea\xa2\xe5\x02\x00\x00\xe5\x02\x00\x00\t\x00\x1c\x00Asia/OmskUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00" + - "\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZi" + - "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00A\x00\x00\x00\x06\x00\x00\x00\x10\xff\xff\xff\xff\xa1\xb3@\xb6\xff\xff\xff\xff\xb5\xa3\xef0\x00\x00\x00" + - "\x00\x15'}\xa0\x00\x00\x00\x00\x16\x18\xb2\x10\x00\x00\x00\x00\x17\b\xb1 \x00\x00\x00\x00\x17\xf9\xe5\x90\x00\x00\x00\x00\x18\xe9\xe4\xa0\x00\x00\x00\x00\x19\xdb\x19\x10\x00\x00\x00\x00\x1a\xcci\xa0\x00\x00\x00\x00\x1b\xbcv" + - "\xc0\x00\x00\x00\x00\x1c\xacg\xc0\x00\x00\x00\x00\x1d\x9cX\xc0\x00\x00\x00\x00\x1e\x8cI\xc0\x00\x00\x00\x00\x1f|:\xc0\x00\x00\x00\x00 l+\xc0\x00\x00\x00\x00!\\\x1c\xc0\x00\x00\x00\x00\"L\r\xc0\x00\x00\x00" + - "\x00#;\xfe\xc0\x00\x00\x00\x00$+\xef\xc0\x00\x00\x00\x00%\x1b\xe0\xc0\x00\x00\x00\x00&\v\xd1\xc0\x00\x00\x00\x00'\x04\xfd@\x00\x00\x00\x00'\xf4\xee@\x00\x00\x00\x00(\xe4\xedP\x00\x00\x00\x00)x\x95" + - "P\x00\x00\x00\x00)\xd4\xd0@\x00\x00\x00\x00*\xc4\xc1@\x00\x00\x00\x00+\xb4\xb2@\x00\x00\x00\x00,\xa4\xa3@\x00\x00\x00\x00-\x94\x94@\x00\x00\x00\x00.\x84\x85@\x00\x00\x00\x00/tv@\x00\x00\x00" + - "\x000dg@\x00\x00\x00\x001]\x92\xc0\x00\x00\x00\x002rm\xc0\x00\x00\x00\x003=t\xc0\x00\x00\x00\x004RO\xc0\x00\x00\x00\x005\x1dV\xc0\x00\x00\x00\x00621\xc0\x00\x00\x00\x006\xfd8" + - "\xc0\x00\x00\x00\x008\x1bN@\x00\x00\x00\x008\xdd\x1a\xc0\x00\x00\x00\x009\xfb0@\x00\x00\x00\x00:\xbc\xfc\xc0\x00\x00\x00\x00;\xdb\x12@\x00\x00\x00\x00<\xa6\x19@\x00\x00\x00\x00=\xba\xf4@\x00\x00\x00" + - "\x00>\x85\xfb@\x00\x00\x00\x00?\x9a\xd6@\x00\x00\x00\x00@e\xdd@\x00\x00\x00\x00A\x83\xf2\xc0\x00\x00\x00\x00BE\xbf@\x00\x00\x00\x00Cc\xd4\xc0\x00\x00\x00\x00D%\xa1@\x00\x00\x00\x00EC\xb6" + - "\xc0\x00\x00\x00\x00F\x05\x83@\x00\x00\x00\x00G#\x98\xc0\x00\x00\x00\x00G\xee\x9f\xc0\x00\x00\x00\x00I\x03z\xc0\x00\x00\x00\x00I\u0381\xc0\x00\x00\x00\x00J\xe3\\\xc0\x00\x00\x00\x00K\xaec\xc0\x00\x00\x00" + - "\x00L\xccy@\x00\x00\x00\x00M\x8eE\xc0\x00\x00\x00\x00TK\xf30\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x05\x03\x00\x00D\xca\x00\x00\x00\x00FP\x00\x04\x00\x00bp\x01\b\x00\x00T`\x00\f\x00\x00T`\x01\f\x00\x00bp" + - "\x00\bLMT\x00+05\x00+07\x00+06\x00\n<+06>-6\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xee\xf0BB\xff\x01\x00\x00\xff\x01\x00\x00\v\x00\x1c\x00Asi" + - "a/TaipeiUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00)\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xfft\xce\xf0\x18\xff\xff\xff\xff\xc3UI\x80\xff\xff\xff\xff\xd2TY\x80\xff\xff\xff\xffӋ{\x80\xff\xff\xff\xff\xd4B\xad\xf0\xff\xff\xff\xff\xd5E\"\x00\xff" + - "\xff\xff\xff\xd6L\xbf\xf0\xff\xff\xff\xff\xd7<\xbf\x00\xff\xff\xff\xff\xd8\x06fp\xff\xff\xff\xff\xd9\x1d\xf2\x80\xff\xff\xff\xff\xd9\xe7\x99\xf0\xff\xff\xff\xff\xda\xff&\x00\xff\xff\xff\xff\xdb\xc8\xcdp\xff\xff\xff\xff\xdc" + - "\xe0Y\x80\xff\xff\xff\xffݪ\x00\xf0\xff\xff\xff\xff\xders\x00\xff\xff\xff\xffߵdp\xff\xff\xff\xff\xe0|\x85\x00\xff\xff\xff\xffᖗ\xf0\xff\xff\xff\xff\xe2]\xb8\x80\xff\xff\xff\xff\xe3w\xcbp\xff" + - "\xff\xff\xff\xe4>\xec\x00\xff\xff\xff\xff\xe50 p\xff\xff\xff\xff\xe6!q\x00\xff\xff\xff\xff\xe7\x12\xa5p\xff\xff\xff\xff\xe8\x02\xa4\x80\xff\xff\xff\xff\xe8\xf3\xd8\xf0\xff\xff\xff\xff\xe9\xe3\xd8\x00\xff\xff\xff\xff\xea" + - "\xd5\fp\xff\xff\xff\xff\xeb\xc5\v\x80\xff\xff\xff\xff\xec\xb6?\xf0\xff\xff\xff\xff\xed\xf7\xfc\x00\xff\xff\xff\xff\xee\x98\xc4\xf0\xff\xff\xff\xff\xef\xd9/\x80\xff\xff\xff\xff\xf0y\xf8p\x00\x00\x00\x00\a\xfcV\x00\x00" + - "\x00\x00\x00\b\xed\x8ap\x00\x00\x00\x00\t݉\x80\x00\x00\x00\x00\nν\xf0\x00\x00\x00\x00\x11ۡ\x80\x00\x00\x00\x00\x12T\xddp\x01\x02\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01" + - "\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x00\x00q\xe8\x00\x00\x00\x00p\x80\x00\x04\x00\x00~\x90\x00\b\x00\x00~\x90\x01\fLMT\x00CST\x00JST\x00CDT\x00" + - "\nCST-8\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R?Y\xaf\x19\xe7\x00\x00\x00\xe7\x00\x00\x00\n\x00\x1c\x00Asia/DaccaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`" + - "ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00" + - "\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x1c\xff\xff\xff\xffi\x86\x86\xbc\xff\xff" + - "\xff\xff\xcaۆ\xb0\xff\xff\xff\xff\xcc\x05q\x18\xff\xff\xff\xff̕2\xa8\xff\xff\xff\xffݨҘ\x00\x00\x00\x00J;\xc4\x10\x00\x00\x00\x00K<ؐ\x01\x02\x03\x02\x04\x05\x04\x00\x00T\xc4\x00\x00\x00" + - "\x00R\xd0\x00\x04\x00\x00[h\x00\b\x00\x00MX\x00\x0e\x00\x00T`\x00\x14\x00\x00bp\x01\x18LMT\x00HMT\x00+0630\x00+0530\x00+06\x00+07\x00\n<+" + - "06>-6\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R]S\xbb\x12\xac\x03\x00\x00\xac\x03\x00\x00\x0e\x00\x1c\x00Asia/FamagustaUT\t\x00\x03\x15\xac\x0e`\x15" + - "\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00" + - "\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00V\x00\x00\x00\x04\x00\x00\x00\x11\xff\xff\xff\xff\xa5w\x1e" + - ",\x00\x00\x00\x00\t\xed\xaf\xe0\x00\x00\x00\x00\nݒ\xd0\x00\x00\x00\x00\v\xfad\xe0\x00\x00\x00\x00\f\xbe\xc6P\x00\x00\x00\x00\r\xa49`\x00\x00\x00\x00\x0e\x8a\xe1\xd0\x00\x00\x00\x00\x0f\x84\x1b`\x00\x00\x00" + - "\x00\x10uO\xd0\x00\x00\x00\x00\x11c\xfd`\x00\x00\x00\x00\x12S\xe0P\x00\x00\x00\x00\x13M\x19\xe0\x00\x00\x00\x00\x143\xc2P\x00\x00\x00\x00\x15#\xc1`\x00\x00\x00\x00\x16\x13\xa4P\x00\x00\x00\x00\x17\x03\xa3" + - "`\x00\x00\x00\x00\x17\xf3\x86P\x00\x00\x00\x00\x18\xe3\x85`\x00\x00\x00\x00\x19\xd3hP\x00\x00\x00\x00\x1a\xc3g`\x00\x00\x00\x00\x1b\xbc\x84\xd0\x00\x00\x00\x00\x1c\xac\x83\xe0\x00\x00\x00\x00\x1d\x9cf\xd0\x00\x00\x00" + - "\x00\x1e\x8ce\xe0\x00\x00\x00\x00\x1f|H\xd0\x00\x00\x00\x00 lG\xe0\x00\x00\x00\x00!\\*\xd0\x00\x00\x00\x00\"L)\xe0\x00\x00\x00\x00#<\f\xd0\x00\x00\x00\x00$,\v\xe0\x00\x00\x00\x00%\x1b\xee" + - "\xd0\x00\x00\x00\x00&\v\xed\xe0\x00\x00\x00\x00'\x05\vP\x00\x00\x00\x00'\xf5\n`\x00\x00\x00\x00(\xe4\xedP\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xc4\xcfP\x00\x00\x00\x00+\xb4\xce`\x00\x00\x00" + - "\x00,\xa4\xb1P\x00\x00\x00\x00-\x94\xb0`\x00\x00\x00\x00.\x84\x93P\x00\x00\x00\x00/t\x92`\x00\x00\x00\x000duP\x00\x00\x00\x001]\xae\xe0\x00\x00\x00\x002M\x91\xd0\x00\x00\x00\x003=\x90" + - "\xe0\x00\x00\x00\x004-s\xd0\x00\x00\x00\x005\x1dr\xe0\x00\x00\x00\x0062x\x10\x00\x00\x00\x006\xfd\u007f\x10\x00\x00\x00\x008\x1b\x94\x90\x00\x00\x00\x008\xdda\x10\x00\x00\x00\x009\xfbv\x90\x00\x00\x00" + - "\x00:\xbdC\x10\x00\x00\x00\x00;\xdbX\x90\x00\x00\x00\x00<\xa6_\x90\x00\x00\x00\x00=\xbb:\x90\x00\x00\x00\x00>\x86A\x90\x00\x00\x00\x00?\x9b\x1c\x90\x00\x00\x00\x00@f#\x90\x00\x00\x00\x00A\x849" + - "\x10\x00\x00\x00\x00BF\x05\x90\x00\x00\x00\x00Cd\x1b\x10\x00\x00\x00\x00D%\xe7\x90\x00\x00\x00\x00EC\xfd\x10\x00\x00\x00\x00F\x05ɐ\x00\x00\x00\x00G#\xdf\x10\x00\x00\x00\x00G\xee\xe6\x10\x00\x00\x00" + - "\x00I\x03\xc1\x10\x00\x00\x00\x00I\xce\xc8\x10\x00\x00\x00\x00J\xe3\xa3\x10\x00\x00\x00\x00K\xae\xaa\x10\x00\x00\x00\x00L̿\x90\x00\x00\x00\x00M\x8e\x8c\x10\x00\x00\x00\x00N\xac\xa1\x90\x00\x00\x00\x00Onn" + - "\x10\x00\x00\x00\x00P\x8c\x83\x90\x00\x00\x00\x00QW\x8a\x90\x00\x00\x00\x00Rle\x90\x00\x00\x00\x00S7l\x90\x00\x00\x00\x00TLG\x90\x00\x00\x00\x00U\x17N\x90\x00\x00\x00\x00V,)\x90\x00\x00\x00" + - "\x00V\xf70\x90\x00\x00\x00\x00W\xd0\u007f\xd0\x00\x00\x00\x00Y\xf5(\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x03\x02\x00\x00\x1f\xd4\x00\x00\x00\x00*0\x01\x04\x00" + - "\x00\x1c \x00\t\x00\x00*0\x00\rLMT\x00EEST\x00EET\x00+03\x00\nEET-2EEST,M3.5.0/3,M10.5.0/4\nPK" + - "\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xcfׇ\xe1\x85\x00\x00\x00\x85\x00\x00\x00\v\x00\x1c\x00Asia/RiyadhUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03" + - "\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + - "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\xd5\x1b6\xb4\x01\x00\x00+\xcc\x00\x00\x00\x00*" + - "0\x00\x04LMT\x00+03\x00\n<+03>-3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R*\xe4@\xa9\x89\x01\x00\x00\x89\x01\x00\x00\x0e\x00\x1c\x00Asia/Chung" + - "kingUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d\x00" + - "\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff~6C)\xff\xff\xff\xff\xa0\x97\xa2\x80\xff\xff\xff\xff\xa1y\x04\xf0\xff\xff\xff\xff\xc8Y^\x80\xff\xff\xff\xff\xc9\t\xf9p\xff\xff\xff\xff\xc9ӽ\x00\xff\xff\xff\xff\xcb" + - "\x05\x8a\xf0\xff\xff\xff\xff\xcb|@\x00\xff\xff\xff\xff\xd2;>\xf0\xff\xff\xff\xffӋ{\x80\xff\xff\xff\xff\xd4B\xad\xf0\xff\xff\xff\xff\xd5E\"\x00\xff\xff\xff\xff\xd6L\xbf\xf0\xff\xff\xff\xff\xd7<\xbf\x00\xff" + - "\xff\xff\xff\xd8\x06fp\xff\xff\xff\xff\xd9\x1d\xf2\x80\xff\xff\xff\xff\xd9A|\xf0\x00\x00\x00\x00\x1e\xbaR \x00\x00\x00\x00\x1fi\x9b\x90\x00\x00\x00\x00 ~\x84\xa0\x00\x00\x00\x00!I}\x90\x00\x00\x00\x00\"" + - "g\xa1 \x00\x00\x00\x00#)_\x90\x00\x00\x00\x00$G\x83 \x00\x00\x00\x00%\x12|\x10\x00\x00\x00\x00&'e \x00\x00\x00\x00&\xf2^\x10\x00\x00\x00\x00(\aG \x00\x00\x00\x00(\xd2@\x10\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00q\xd7\x00\x00\x00\x00~\x90\x01\x04\x00\x00p\x80\x00\bLMT\x00CDT\x00CST\x00\nC" + - "ST-8\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xceG|\xea\x13\x03\x00\x00\x13\x03\x00\x00\n\x00\x1c\x00Asia/AmmanUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux" + - "\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00" + - "\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00F\x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff\xff\xb6\xa3\xd6\xd0\x00\x00\x00\x00" + - "\x06ry\xe0\x00\x00\x00\x00\a\f\xabP\x00\x00\x00\x00\b$7`\x00\x00\x00\x00\b\xed\xde\xd0\x00\x00\x00\x00\n\x05j\xe0\x00\x00\x00\x00\n\xcf\x12P\x00\x00\x00\x00\v\xe7\xef\xe0\x00\x00\x00\x00\f\xdau\xd0" + - "\x00\x00\x00\x00\r\xc9#`\x00\x00\x00\x00\x0e\x92\xca\xd0\x00\x00\x00\x00\x0f\xa9\x05`\x00\x00\x00\x00\x10r\xac\xd0\x00\x00\x00\x00\x1c\xad\xd5`\x00\x00\x00\x00\x1d\x9f\t\xd0\x00\x00\x00\x00\x1e\x92\xfd`\x00\x00\x00\x00" + - "\x1f\x82\xe0P\x00\x00\x00\x00 r\xdf`\x00\x00\x00\x00!b\xc2P\x00\x00\x00\x00\"R\xc1`\x00\x00\x00\x00#K\xde\xd0\x00\x00\x00\x00$d\xbc`\x00\x00\x00\x00%+\xc0\xd0\x00\x00\x00\x00&7o`" + - "\x00\x00\x00\x00'\v\xa2\xd0\x00\x00\x00\x00(\vs\xe0\x00\x00\x00\x00(\xe2JP\x00\x00\x00\x00)\xe4\xbe`\x00\x00\x00\x00*\xcbf\xd0\x00\x00\x00\x00+\xbbe\xe0\x00\x00\x00\x00,\xabH\xd0\x00\x00\x00\x00" + - "-\x9bG\xe0\x00\x00\x00\x00.x\xb5\xd0\x00\x00\x00\x00/\x84d`\x00\x00\x00\x000X\xa5\xe0\x00\x00\x00\x001dF`\x00\x00\x00\x002A\xc2`\x00\x00\x00\x003D(`\x00\x00\x00\x004!\xa4`" + - "\x00\x00\x00\x005$\n`\x00\x00\x00\x006\x01\x86`\x00\x00\x00\x007z\x93`\x00\x00\x00\x007\xea\xa2\xe0\x00\x00\x00\x008\xe2|\xe0\x00\x00\x00\x009ӿ`\x00\x00\x00\x00:\xc2^\xe0\x00\x00\x00\x00" + - ";\xb3\xa1`\x00\x00\x00\x00<\xa3\x92`\x00\x00\x00\x00=\x93\x83`\x00\x00\x00\x00>\x83t`\x00\x00\x00\x00?\x98O`\x00\x00\x00\x00@cV`\x00\x00\x00\x00An\xf6\xe0\x00\x00\x00\x00BLr\xe0" + - "\x00\x00\x00\x00C" + + "-5:30\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x88\xf6C\x84\x98\x00\x00\x00\x98\x00\x00\x00\x0e\x00\x1c\x00Asia/VientianeUT\t\x00\x03\x82\x0f\x8ba\x82" + + "\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00" + + "\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xffV\xb6\x85" + + "\xc4\xff\xff\xff\xff\xa2jg\xc4\x01\x02\x00\x00^<\x00\x00\x00\x00^<\x00\x04\x00\x00bp\x00\bLMT\x00BMT\x00+07\x00\n<+07>-7\nPK\x03\x04\n\x00\x00\x00\x00\x00" + + "#\x82iSB\x1d\xc6\x1b\x85\x00\x00\x00\x85\x00\x00\x00\f\x00\x1c\x00Asia/KashgarUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00" + + "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\xb0\xfe\xbad\x01\x00\x00R\x1c\x00\x00\x00\x00T`\x00\x04LMT\x00" + + "+06\x00\n<+06>-6\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS)p\x1cX\xf1\x02\x00\x00\xf1\x02\x00\x00\x10\x00\x1c\x00Asia/NovosibirskU" + + "T\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00C\x00\x00\x00\x05\x00\x00" + + "\x00\x10\xff\xff\xff\xff\xa1\xdb\x19$\xff\xff\xff\xff\xb5\xa3\xe1 \x00\x00\x00\x00\x15'o\x90\x00\x00\x00\x00\x16\x18\xa4\x00\x00\x00\x00\x00\x17\b\xa3\x10\x00\x00\x00\x00\x17\xf9׀\x00\x00\x00\x00\x18\xe9\u0590\x00\x00" + + "\x00\x00\x19\xdb\v\x00\x00\x00\x00\x00\x1a\xcc[\x90\x00\x00\x00\x00\x1b\xbch\xb0\x00\x00\x00\x00\x1c\xacY\xb0\x00\x00\x00\x00\x1d\x9cJ\xb0\x00\x00\x00\x00\x1e\x8c;\xb0\x00\x00\x00\x00\x1f|,\xb0\x00\x00\x00\x00 l" + + "\x1d\xb0\x00\x00\x00\x00!\\\x0e\xb0\x00\x00\x00\x00\"K\xff\xb0\x00\x00\x00\x00#;\xf0\xb0\x00\x00\x00\x00$+\xe1\xb0\x00\x00\x00\x00%\x1bҰ\x00\x00\x00\x00&\vð\x00\x00\x00\x00'\x04\xef0\x00\x00" + + "\x00\x00'\xf4\xe00\x00\x00\x00\x00(\xe4\xdf@\x00\x00\x00\x00)x\x87@\x00\x00\x00\x00)\xd4\xc20\x00\x00\x00\x00*ij0\x00\x00\x00\x00+\xb4\xa40\x00\x00\x00\x00+\xfeN\x00\x00\x00\x00\x00,\xa4" + + "\xa3@\x00\x00\x00\x00-\x94\x94@\x00\x00\x00\x00.\x84\x85@\x00\x00\x00\x00/tv@\x00\x00\x00\x000dg@\x00\x00\x00\x001]\x92\xc0\x00\x00\x00\x002rm\xc0\x00\x00\x00\x003=t\xc0\x00\x00" + + "\x00\x004RO\xc0\x00\x00\x00\x005\x1dV\xc0\x00\x00\x00\x00621\xc0\x00\x00\x00\x006\xfd8\xc0\x00\x00\x00\x008\x1bN@\x00\x00\x00\x008\xdd\x1a\xc0\x00\x00\x00\x009\xfb0@\x00\x00\x00\x00:\xbc" + + "\xfc\xc0\x00\x00\x00\x00;\xdb\x12@\x00\x00\x00\x00<\xa6\x19@\x00\x00\x00\x00=\xba\xf4@\x00\x00\x00\x00>\x85\xfb@\x00\x00\x00\x00?\x9a\xd6@\x00\x00\x00\x00@e\xdd@\x00\x00\x00\x00A\x83\xf2\xc0\x00\x00" + + "\x00\x00BE\xbf@\x00\x00\x00\x00Cc\xd4\xc0\x00\x00\x00\x00D%\xa1@\x00\x00\x00\x00EC\xb6\xc0\x00\x00\x00\x00F\x05\x83@\x00\x00\x00\x00G#\x98\xc0\x00\x00\x00\x00G\xee\x9f\xc0\x00\x00\x00\x00I\x03" + + "z\xc0\x00\x00\x00\x00I\u0381\xc0\x00\x00\x00\x00J\xe3\\\xc0\x00\x00\x00\x00K\xaec\xc0\x00\x00\x00\x00L\xccy@\x00\x00\x00\x00M\x8eE\xc0\x00\x00\x00\x00TK\xf30\x00\x00\x00\x00W\x93\xcc\xc0\x01\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01" + + "\x04\x01\x03\x01\x03\x00\x00M\xbc\x00\x00\x00\x00T`\x00\x04\x00\x00p\x80\x01\b\x00\x00bp\x00\f\x00\x00bp\x01\fLMT\x00+06\x00+08\x00+07\x00\n<+07>-7\n" + + "PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xe4_P\x18\xef\x02\x00\x00\xef\x02\x00\x00\f\x00\x1c\x00Asia/MagadanUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01" + + "\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00" + + "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00B\x00\x00\x00\x06\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x196\xa0\xff\xff\xff\xff\xb5\xa3\xa8" + + "\xe0\x00\x00\x00\x00\x15'7P\x00\x00\x00\x00\x16\x18k\xc0\x00\x00\x00\x00\x17\bj\xd0\x00\x00\x00\x00\x17\xf9\x9f@\x00\x00\x00\x00\x18\xe9\x9eP\x00\x00\x00\x00\x19\xda\xd2\xc0\x00\x00\x00\x00\x1a\xcc#P\x00\x00\x00" + + "\x00\x1b\xbc0p\x00\x00\x00\x00\x1c\xac!p\x00\x00\x00\x00\x1d\x9c\x12p\x00\x00\x00\x00\x1e\x8c\x03p\x00\x00\x00\x00\x1f{\xf4p\x00\x00\x00\x00 k\xe5p\x00\x00\x00\x00![\xd6p\x00\x00\x00\x00\"K\xc7" + + "p\x00\x00\x00\x00#;\xb8p\x00\x00\x00\x00$+\xa9p\x00\x00\x00\x00%\x1b\x9ap\x00\x00\x00\x00&\v\x8bp\x00\x00\x00\x00'\x04\xb6\xf0\x00\x00\x00\x00'\xf4\xa7\xf0\x00\x00\x00\x00(\xe4\xa7\x00\x00\x00\x00" + + "\x00)xO\x00\x00\x00\x00\x00)ԉ\xf0\x00\x00\x00\x00*\xc4z\xf0\x00\x00\x00\x00+\xb4k\xf0\x00\x00\x00\x00,\xa4\\\xf0\x00\x00\x00\x00-\x94M\xf0\x00\x00\x00\x00.\x84>\xf0\x00\x00\x00\x00/t/" + + "\xf0\x00\x00\x00\x000d \xf0\x00\x00\x00\x001]Lp\x00\x00\x00\x002r'p\x00\x00\x00\x003=.p\x00\x00\x00\x004R\tp\x00\x00\x00\x005\x1d\x10p\x00\x00\x00\x0061\xebp\x00\x00\x00" + + "\x006\xfc\xf2p\x00\x00\x00\x008\x1b\a\xf0\x00\x00\x00\x008\xdc\xd4p\x00\x00\x00\x009\xfa\xe9\xf0\x00\x00\x00\x00:\xbc\xb6p\x00\x00\x00\x00;\xda\xcb\xf0\x00\x00\x00\x00<\xa5\xd2\xf0\x00\x00\x00\x00=\xba\xad" + + "\xf0\x00\x00\x00\x00>\x85\xb4\xf0\x00\x00\x00\x00?\x9a\x8f\xf0\x00\x00\x00\x00@e\x96\xf0\x00\x00\x00\x00A\x83\xacp\x00\x00\x00\x00BEx\xf0\x00\x00\x00\x00Cc\x8ep\x00\x00\x00\x00D%Z\xf0\x00\x00\x00" + + "\x00ECpp\x00\x00\x00\x00F\x05<\xf0\x00\x00\x00\x00G#Rp\x00\x00\x00\x00G\xeeYp\x00\x00\x00\x00I\x034p\x00\x00\x00\x00I\xce;p\x00\x00\x00\x00J\xe3\x16p\x00\x00\x00\x00K\xae\x1d" + + "p\x00\x00\x00\x00L\xcc2\xf0\x00\x00\x00\x00M\x8d\xffp\x00\x00\x00\x00TK\xac\xe0\x00\x00\x00\x00W\x1b\x9c\x00\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x05\x01\x03\x00\x00\x8d`\x00\x00\x00\x00\x8c\xa0\x00\x04\x00\x00\xa8\xc0\x01\b\x00\x00\x9a" + + "\xb0\x00\f\x00\x00\x9a\xb0\x01\f\x00\x00\xa8\xc0\x00\bLMT\x00+10\x00+12\x00+11\x00\n<+11>-11\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x8bSnT\xa1" + + "\x00\x00\x00\xa1\x00\x00\x00\x0e\x00\x1c\x00Asia/KathmanduUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x10\xff\xff\xff\xff\xa1\xf2}\x84\x00\x00\x00\x00\x1e\x180\xa8\x01\x02\x00\x00O\xfc\x00\x00\x00\x00MX\x00\x04\x00\x00" + - "P\xdc\x00\nLMT\x00+0530\x00+0545\x00\n<+0545>-5:45\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R*\xe4@\xa9\x89\x01\x00\x00\x89\x01\x00\x00" + - "\r\x00\x1c\x00Asia/ShanghaiUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff~6C)\xff\xff\xff\xff\xa0\x97\xa2\x80\xff\xff\xff\xff\xa1y\x04\xf0\xff\xff\xff\xff\xc8Y^\x80\xff\xff\xff\xff\xc9\t\xf9p" + - "\xff\xff\xff\xff\xc9ӽ\x00\xff\xff\xff\xff\xcb\x05\x8a\xf0\xff\xff\xff\xff\xcb|@\x00\xff\xff\xff\xff\xd2;>\xf0\xff\xff\xff\xffӋ{\x80\xff\xff\xff\xff\xd4B\xad\xf0\xff\xff\xff\xff\xd5E\"\x00\xff\xff\xff\xff" + - "\xd6L\xbf\xf0\xff\xff\xff\xff\xd7<\xbf\x00\xff\xff\xff\xff\xd8\x06fp\xff\xff\xff\xff\xd9\x1d\xf2\x80\xff\xff\xff\xff\xd9A|\xf0\x00\x00\x00\x00\x1e\xbaR \x00\x00\x00\x00\x1fi\x9b\x90\x00\x00\x00\x00 ~\x84\xa0" + - "\x00\x00\x00\x00!I}\x90\x00\x00\x00\x00\"g\xa1 \x00\x00\x00\x00#)_\x90\x00\x00\x00\x00$G\x83 \x00\x00\x00\x00%\x12|\x10\x00\x00\x00\x00&'e \x00\x00\x00\x00&\xf2^\x10\x00\x00\x00\x00" + - "(\aG \x00\x00\x00\x00(\xd2@\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00q\xd7\x00\x00\x00\x00~\x90\x01\x04\x00\x00p\x80\x00\bL" + - "MT\x00CDT\x00CST\x00\nCST-8\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xd5ΜGp\x02\x00\x00p\x02\x00\x00\x0e\x00\x1c\x00Asia/Qyzylor" + - "daUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004\x00\x00\x00" + - "\x06\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x19\x86\xa0\xff\xff\xff\xff\xb5\xa3\xfd@\x00\x00\x00\x00\x15'\x8b\xb0\x00\x00\x00\x00\x16\x18\xc0 \x00\x00\x00\x00\x17\b\xb1 \x00\x00\x00\x00\x17\xf9\xf3\xa0\x00\x00\x00\x00\x18\xe9\xf2" + - "\xb0\x00\x00\x00\x00\x19\xdb' \x00\x00\x00\x00\x1a\xccw\xb0\x00\x00\x00\x00\x1b\xbc\x84\xd0\x00\x00\x00\x00\x1c\xacu\xd0\x00\x00\x00\x00\x1d\x9cf\xd0\x00\x00\x00\x00\x1e\x8cW\xd0\x00\x00\x00\x00\x1f|H\xd0\x00\x00\x00" + - "\x00 l9\xd0\x00\x00\x00\x00!\\*\xd0\x00\x00\x00\x00\"L\x1b\xd0\x00\x00\x00\x00#<\f\xd0\x00\x00\x00\x00$+\xfd\xd0\x00\x00\x00\x00%\x1b\xee\xd0\x00\x00\x00\x00&\v\xdf\xd0\x00\x00\x00\x00'\x05\v" + - "P\x00\x00\x00\x00'\xf4\xfcP\x00\x00\x00\x00(\xe4\xfb`\x00\x00\x00\x00)x\x95P\x00\x00\x00\x00)\xd4\xd0@\x00\x00\x00\x00*\xc4\xcfP\x00\x00\x00\x00+\xb4\xc0P\x00\x00\x00\x00,\xa4\xb1P\x00\x00\x00" + - "\x00-\x94\xa2P\x00\x00\x00\x00.\x84\x93P\x00\x00\x00\x00/t\x84P\x00\x00\x00\x000duP\x00\x00\x00\x001]\xa0\xd0\x00\x00\x00\x002r{\xd0\x00\x00\x00\x003=\x82\xd0\x00\x00\x00\x004R]" + - "\xd0\x00\x00\x00\x005\x1dd\xd0\x00\x00\x00\x0062?\xd0\x00\x00\x00\x006\xfdF\xd0\x00\x00\x00\x008\x1b\\P\x00\x00\x00\x008\xdd(\xd0\x00\x00\x00\x009\xfb>P\x00\x00\x00\x00:\xbd\n\xd0\x00\x00\x00" + - "\x00;\xdb P\x00\x00\x00\x00<\xa6'P\x00\x00\x00\x00=\xbb\x02P\x00\x00\x00\x00>\x86\tP\x00\x00\x00\x00?\x9a\xe4P\x00\x00\x00\x00@e\xebP\x00\x00\x00\x00A\x84\x00\xd0\x00\x00\x00\x00\\\x1b\xd8" + - "\xa0\x01\x02\x03\x04\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x02\x04\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x02\x00\x00=`\x00\x00\x00" + - "\x008@\x00\x04\x00\x00FP\x00\b\x00\x00T`\x01\f\x00\x00T`\x00\f\x00\x00FP\x01\bLMT\x00+04\x00+05\x00+06\x00\n<+05>-5\nPK\x03\x04\n\x00" + - "\x00\x00\x00\x00\xf1c9R\x17✳2\x04\x00\x002\x04\x00\x00\r\x00\x1c\x00Asia/Tel_AvivUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00" + - "\x04\xe8\x03\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif" + - "3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xffV\xb6\xc2\xfa\xff\xff\xff\xff\x9e0E\x88\xff\xff\xff\xff" + - "\xc8Y\xcf\x00\xff\xff\xff\xff\xc8\xfa\xa6\x00\xff\xff\xff\xff\xc98\x9c\x80\xff\xff\xff\xff\xcc\xe5\xeb\x80\xff\xff\xff\xffͬ\xfe\x00\xff\xff\xff\xff\xce\xc7\x1f\x00\xff\xff\xff\xffϏ\x83\x00\xff\xff\xff\xffЩ\xa4\x00" + - "\xff\xff\xff\xffф}\x00\xff\xff\xff\xffҊ׀\xff\xff\xff\xff\xd3e\xb0\x80\xff\xff\xff\xff\xd4l\v\x00\xff\xff\xff\xff\xd7Z0\x80\xff\xff\xff\xff\xd7\xdfX\x00\xff\xff\xff\xff\xd8/À\xff\xff\xff\xff" + - "\xd9\x1ec\x00\xff\xff\xff\xff\xda\x10\xf7\x00\xff\xff\xff\xff\xda\xeb\xd0\x00\xff\xff\xff\xff۴4\x00\xff\xff\xff\xffܹ=\x00\xff\xff\xff\xff\xdd\xe0\x8d\x00\xff\xff\xff\xff\u07b4\u0380\xff\xff\xff\xffߤ\xbf\x80" + - "\xff\xff\xff\xff\xe0\x8bv\x00\xff\xff\xff\xff\xe1V}\x00\xff\xff\xff\xff\xe2\xbef\x80\xff\xff\xff\xff\xe36_\x00\xff\xff\xff\xff\xe4\x9eH\x80\xff\xff\xff\xff\xe5\x16A\x00\xff\xff\xff\xff\xe6t\xf0\x00\xff\xff\xff\xff" + - "\xe7\x11Ҁ\xff\xff\xff\xff\xe8&\xad\x80\xff\xff\xff\xff\xe8\xe8z\x00\x00\x00\x00\x00\b|\x8b\xe0\x00\x00\x00\x00\b\xfd\xb0\xd0\x00\x00\x00\x00\t\xf6\xea`\x00\x00\x00\x00\n\xa63\xd0\x00\x00\x00\x00\x13\xe9\xfc`" + - "\x00\x00\x00\x00\x14![`\x00\x00\x00\x00\x1a\xfa\xc6`\x00\x00\x00\x00\x1b\x8en`\x00\x00\x00\x00\x1c\xbe\xf8\xe0\x00\x00\x00\x00\x1dw|\xd0\x00\x00\x00\x00\x1e\xcc\xff`\x00\x00\x00\x00\x1f`\x99P\x00\x00\x00\x00" + - " \x82\xb1`\x00\x00\x00\x00!I\xb5\xd0\x00\x00\x00\x00\"^\x9e\xe0\x00\x00\x00\x00# ]P\x00\x00\x00\x00$Z0`\x00\x00\x00\x00%\x00?P\x00\x00\x00\x00&\v\xed\xe0\x00\x00\x00\x00&\xd6\xe6\xd0" + - "\x00\x00\x00\x00'\xeb\xcf\xe0\x00\x00\x00\x00(\xc0\x03P\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xa9\x1f\xd0\x00\x00\x00\x00+\xbbe\xe0\x00\x00\x00\x00,\x89\x01\xd0\x00\x00\x00\x00-\x9bG\xe0\x00\x00\x00\x00" + - "._\xa9P\x00\x00\x00\x00/{)\xe0\x00\x00\x00\x000H\xc5\xd0\x00\x00\x00\x001H\x96\xe0\x00\x00\x00\x002\x83\x82p\x00\x00\x00\x00?|\x9f\xe0\x00\x00\x00\x00@s6p\x00\x00\x00\x00AP\xa4`\x00\x00\x00\x00BL\x8f\x00\x00\x00\x00\x00CHOp" + - "\x00\x00\x00\x00D,q\x00\x00\x00\x00\x00E\x1e\xf6\xf0\x00\x00\x00\x00F\fS\x00\x00\x00\x00\x00F\xecc\xf0\x00\x00\x00\x00G\xec5\x00\x00\x00\x00\x00H\xe7\xf5p\x00\x00\x00\x00I\xcc\x17\x00\x00\x00\x00\x00" + - "J\xbe\x9c\xf0\x00\x00\x00\x00K\xab\xf9\x00\x00\x00\x00\x00L\x8c\t\xf0\x00\x00\x00\x00M\x95\x15\x80\x00\x00\x00\x00N\x87\x9bp\x00\x00\x00\x00Ot\xf7\x80\x00\x00\x00\x00P^B\xf0\x00\x00\x00\x00QTـ" + - "\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x00\x00!\x06\x00\x00\x00\x00 \xf8\x00\x04\x00\x00*0\x01\b\x00\x00" + - "\x1c \x00\f\x00\x008@\x01\x10LMT\x00JMT\x00IDT\x00IST\x00IDDT\x00\nIST-2IDT,M3.4.4/26,M10.5.0\nP" + - "K\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xb2\xe27Yn\x01\x00\x00n\x01\x00\x00\r\x00\x1c\x00Asia/TashkentUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01" + - "\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00" + - "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x19\x83\t\xff\xff\xff\xff\xb5\xa3\xef" + - "0\x00\x00\x00\x00\x15'}\xa0\x00\x00\x00\x00\x16\x18\xb2\x10\x00\x00\x00\x00\x17\b\xb1 \x00\x00\x00\x00\x17\xf9\xe5\x90\x00\x00\x00\x00\x18\xe9\xe4\xa0\x00\x00\x00\x00\x19\xdb\x19\x10\x00\x00\x00\x00\x1a\xcci\xa0\x00\x00\x00" + - "\x00\x1b\xbcv\xc0\x00\x00\x00\x00\x1c\xacg\xc0\x00\x00\x00\x00\x1d\x9cX\xc0\x00\x00\x00\x00\x1e\x8cI\xc0\x00\x00\x00\x00\x1f|:\xc0\x00\x00\x00\x00 l+\xc0\x00\x00\x00\x00!\\\x1c\xc0\x00\x00\x00\x00\"L\r" + - "\xc0\x00\x00\x00\x00#;\xfe\xc0\x00\x00\x00\x00$+\xef\xc0\x00\x00\x00\x00%\x1b\xe0\xc0\x00\x00\x00\x00&\v\xd1\xc0\x00\x00\x00\x00'\x04\xfd@\x00\x00\x00\x00'\xf4\xee@\x00\x00\x00\x00(\xe4\xedP\x01\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x00\x00@\xf7\x00\x00\x00\x00FP\x00\x04\x00\x00bp\x01\b\x00\x00T`\x00\f\x00\x00T`\x01\fLMT\x00+05\x00+" + - "07\x00+06\x00\n<+05>-5\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xcfׇ\xe1\x85\x00\x00\x00\x85\x00\x00\x00\v\x00\x1c\x00Asia/KuwaitUT\t" + - "\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b" + - "\xff\xff\xff\xff\xd5\x1b6\xb4\x01\x00\x00+\xcc\x00\x00\x00\x00*0\x00\x04LMT\x00+03\x00\n<+03>-3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RB\x1d\xc6\x1b\x85\x00\x00\x00" + - "\x85\x00\x00\x00\v\x00\x1c\x00Asia/UrumqiUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\xb0\xfe\xbad\x01\x00\x00R\x1c\x00\x00\x00\x00T`\x00\x04LMT\x00+06\x00\n<+06>-6\n" + - "PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Re\x1bb2w\x01\x00\x00w\x01\x00\x00\x0e\x00\x1c\x00Asia/AshkhabadUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v" + - "\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00" + - "\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x19\x8dD\xff\xff\xff\xff\xb5" + - "\xa3\xfd@\x00\x00\x00\x00\x15'\x8b\xb0\x00\x00\x00\x00\x16\x18\xc0 \x00\x00\x00\x00\x17\b\xbf0\x00\x00\x00\x00\x17\xf9\xf3\xa0\x00\x00\x00\x00\x18\xe9\xf2\xb0\x00\x00\x00\x00\x19\xdb' \x00\x00\x00\x00\x1a\xccw\xb0\x00" + - "\x00\x00\x00\x1b\xbc\x84\xd0\x00\x00\x00\x00\x1c\xacu\xd0\x00\x00\x00\x00\x1d\x9cf\xd0\x00\x00\x00\x00\x1e\x8cW\xd0\x00\x00\x00\x00\x1f|H\xd0\x00\x00\x00\x00 l9\xd0\x00\x00\x00\x00!\\*\xd0\x00\x00\x00\x00\"" + - "L\x1b\xd0\x00\x00\x00\x00#<\f\xd0\x00\x00\x00\x00$+\xfd\xd0\x00\x00\x00\x00%\x1b\xee\xd0\x00\x00\x00\x00&\v\xdf\xd0\x00\x00\x00\x00'\x05\vP\x00\x00\x00\x00'\xf4\xfcP\x00\x00\x00\x00(\xe4\xfb`\x00" + - "\x00\x00\x00)x\xa3`\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x00\x006\xbc\x00\x00\x00\x008@\x00\x04\x00\x00T`\x01\b\x00\x00FP\x00\f\x00\x00FP" + - "\x01\fLMT\x00+04\x00+06\x00+05\x00\n<+05>-5\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xf0\x9cf>\xd7\x02\x00\x00\xd7\x02\x00\x00\x0e\x00\x1c\x00Asi" + - "a/KamchatkaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00@\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xa7R\x96\xc4\xff\xff\xff\xff\xb5\xa3\x9a\xd0\x00\x00\x00\x00\x15')@\x00\x00\x00\x00\x16\x18]\xb0\x00\x00\x00\x00\x17\b\\\xc0\x00\x00\x00\x00\x17\xf9" + - "\x910\x00\x00\x00\x00\x18\xe9\x90@\x00\x00\x00\x00\x19\xdaİ\x00\x00\x00\x00\x1a\xcc\x15@\x00\x00\x00\x00\x1b\xbc\"`\x00\x00\x00\x00\x1c\xac\x13`\x00\x00\x00\x00\x1d\x9c\x04`\x00\x00\x00\x00\x1e\x8b\xf5`\x00\x00" + - "\x00\x00\x1f{\xe6`\x00\x00\x00\x00 k\xd7`\x00\x00\x00\x00![\xc8`\x00\x00\x00\x00\"K\xb9`\x00\x00\x00\x00#;\xaa`\x00\x00\x00\x00$+\x9b`\x00\x00\x00\x00%\x1b\x8c`\x00\x00\x00\x00&\v" + - "}`\x00\x00\x00\x00'\x04\xa8\xe0\x00\x00\x00\x00'\xf4\x99\xe0\x00\x00\x00\x00(\xe4\x98\xf0\x00\x00\x00\x00)x@\xf0\x00\x00\x00\x00)\xd4{\xe0\x00\x00\x00\x00*\xc4l\xe0\x00\x00\x00\x00+\xb4]\xe0\x00\x00" + - "\x00\x00,\xa4N\xe0\x00\x00\x00\x00-\x94?\xe0\x00\x00\x00\x00.\x840\xe0\x00\x00\x00\x00/t!\xe0\x00\x00\x00\x000d\x12\xe0\x00\x00\x00\x001]>`\x00\x00\x00\x002r\x19`\x00\x00\x00\x003=" + - " `\x00\x00\x00\x004Q\xfb`\x00\x00\x00\x005\x1d\x02`\x00\x00\x00\x0061\xdd`\x00\x00\x00\x006\xfc\xe4`\x00\x00\x00\x008\x1a\xf9\xe0\x00\x00\x00\x008\xdc\xc6`\x00\x00\x00\x009\xfa\xdb\xe0\x00\x00" + - "\x00\x00:\xbc\xa8`\x00\x00\x00\x00;ڽ\xe0\x00\x00\x00\x00<\xa5\xc4\xe0\x00\x00\x00\x00=\xba\x9f\xe0\x00\x00\x00\x00>\x85\xa6\xe0\x00\x00\x00\x00?\x9a\x81\xe0\x00\x00\x00\x00@e\x88\xe0\x00\x00\x00\x00A\x83" + - "\x9e`\x00\x00\x00\x00BEj\xe0\x00\x00\x00\x00Cc\x80`\x00\x00\x00\x00D%L\xe0\x00\x00\x00\x00ECb`\x00\x00\x00\x00F\x05.\xe0\x00\x00\x00\x00G#D`\x00\x00\x00\x00G\xeeK`\x00\x00" + - "\x00\x00I\x03&`\x00\x00\x00\x00I\xce-`\x00\x00\x00\x00J\xe3\b`\x00\x00\x00\x00K\xae\x0f`\x00\x00\x00\x00L\xcc2\xf0\x00\x00\x00\x00M\x8d\xffp\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x00\x00\x94\xbc\x00\x00\x00\x00\x9a\xb0" + - "\x00\x04\x00\x00\xb6\xd0\x01\b\x00\x00\xa8\xc0\x00\f\x00\x00\xa8\xc0\x01\fLMT\x00+11\x00+13\x00+12\x00\n<+12>-12\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R" + - "\x87\xbd\xedL\xf1\x02\x00\x00\xf1\x02\x00\x00\f\x00\x1c\x00Asia/BarnaulUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif" + - "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00C\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xa1\xd5}\xfc\xff\xff\xff\xff\xb5\xa3\xe1 \x00\x00\x00\x00\x15'o\x90\x00\x00\x00\x00\x16" + - "\x18\xa4\x00\x00\x00\x00\x00\x17\b\xa3\x10\x00\x00\x00\x00\x17\xf9׀\x00\x00\x00\x00\x18\xe9\u0590\x00\x00\x00\x00\x19\xdb\v\x00\x00\x00\x00\x00\x1a\xcc[\x90\x00\x00\x00\x00\x1b\xbch\xb0\x00\x00\x00\x00\x1c\xacY\xb0\x00" + - "\x00\x00\x00\x1d\x9cJ\xb0\x00\x00\x00\x00\x1e\x8c;\xb0\x00\x00\x00\x00\x1f|,\xb0\x00\x00\x00\x00 l\x1d\xb0\x00\x00\x00\x00!\\\x0e\xb0\x00\x00\x00\x00\"K\xff\xb0\x00\x00\x00\x00#;\xf0\xb0\x00\x00\x00\x00$" + - "+\xe1\xb0\x00\x00\x00\x00%\x1bҰ\x00\x00\x00\x00&\vð\x00\x00\x00\x00'\x04\xef0\x00\x00\x00\x00'\xf4\xe00\x00\x00\x00\x00(\xe4\xdf@\x00\x00\x00\x00)x\x87@\x00\x00\x00\x00)\xd4\xc20\x00" + - "\x00\x00\x00*ij0\x00\x00\x00\x00+\xb4\xa40\x00\x00\x00\x00,\xa4\x950\x00\x00\x00\x00-\x94\x860\x00\x00\x00\x00.\x84w0\x00\x00\x00\x00/th0\x00\x00\x00\x00/\xc7L\x80\x00\x00\x00\x000" + - "dg@\x00\x00\x00\x001]\x92\xc0\x00\x00\x00\x002rm\xc0\x00\x00\x00\x003=t\xc0\x00\x00\x00\x004RO\xc0\x00\x00\x00\x005\x1dV\xc0\x00\x00\x00\x00621\xc0\x00\x00\x00\x006\xfd8\xc0\x00" + - "\x00\x00\x008\x1bN@\x00\x00\x00\x008\xdd\x1a\xc0\x00\x00\x00\x009\xfb0@\x00\x00\x00\x00:\xbc\xfc\xc0\x00\x00\x00\x00;\xdb\x12@\x00\x00\x00\x00<\xa6\x19@\x00\x00\x00\x00=\xba\xf4@\x00\x00\x00\x00>" + - "\x85\xfb@\x00\x00\x00\x00?\x9a\xd6@\x00\x00\x00\x00@e\xdd@\x00\x00\x00\x00A\x83\xf2\xc0\x00\x00\x00\x00BE\xbf@\x00\x00\x00\x00Cc\xd4\xc0\x00\x00\x00\x00D%\xa1@\x00\x00\x00\x00EC\xb6\xc0\x00" + - "\x00\x00\x00F\x05\x83@\x00\x00\x00\x00G#\x98\xc0\x00\x00\x00\x00G\xee\x9f\xc0\x00\x00\x00\x00I\x03z\xc0\x00\x00\x00\x00I\u0381\xc0\x00\x00\x00\x00J\xe3\\\xc0\x00\x00\x00\x00K\xaec\xc0\x00\x00\x00\x00L" + - "\xccy@\x00\x00\x00\x00M\x8eE\xc0\x00\x00\x00\x00TK\xf30\x00\x00\x00\x00V\xf6\xea@\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x03\x02\x03\x02\x04" + - "\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x03\x01\x03\x00\x00N\x84\x00\x00\x00\x00T`\x00\x04\x00\x00p\x80\x01\b\x00\x00bp\x00\f\x00\x00" + - "bp\x01\fLMT\x00+06\x00+08\x00+07\x00\n<+07>-7\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x8a\x9a\x90\xf7\xd6\x02\x00\x00\xd6\x02\x00\x00\x11\x00\x1c\x00A" + - "sia/NovokuznetskUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "P\xdc\x00\nLMT\x00+0530\x00+0545\x00\n<+0545>-5:45\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x88\xf6C\x84\x98\x00\x00\x00\x98\x00\x00\x00" + + "\f\x00\x1c\x00Asia/BangkokUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x18 \xc0\xff\xff\xff\xff\xb5\xa3\xe1 \x00\x00\x00\x00\x15'o\x90\x00\x00\x00\x00\x16\x18\xa4\x00\x00\x00\x00\x00\x17\b\xa3\x10\x00" + - "\x00\x00\x00\x17\xf9׀\x00\x00\x00\x00\x18\xe9\u0590\x00\x00\x00\x00\x19\xdb\v\x00\x00\x00\x00\x00\x1a\xcc[\x90\x00\x00\x00\x00\x1b\xbch\xb0\x00\x00\x00\x00\x1c\xacY\xb0\x00\x00\x00\x00\x1d\x9cJ\xb0\x00\x00\x00\x00\x1e" + - "\x8c;\xb0\x00\x00\x00\x00\x1f|,\xb0\x00\x00\x00\x00 l\x1d\xb0\x00\x00\x00\x00!\\\x0e\xb0\x00\x00\x00\x00\"K\xff\xb0\x00\x00\x00\x00#;\xf0\xb0\x00\x00\x00\x00$+\xe1\xb0\x00\x00\x00\x00%\x1bҰ\x00" + - "\x00\x00\x00&\vð\x00\x00\x00\x00'\x04\xef0\x00\x00\x00\x00'\xf4\xe00\x00\x00\x00\x00(\xe4\xdf@\x00\x00\x00\x00)x\x87@\x00\x00\x00\x00)\xd4\xc20\x00\x00\x00\x00*ij0\x00\x00\x00\x00+" + - "\xb4\xa40\x00\x00\x00\x00,\xa4\x950\x00\x00\x00\x00-\x94\x860\x00\x00\x00\x00.\x84w0\x00\x00\x00\x00/th0\x00\x00\x00\x000dY0\x00\x00\x00\x001]\x84\xb0\x00\x00\x00\x002r_\xb0\x00" + - "\x00\x00\x003=f\xb0\x00\x00\x00\x004RA\xb0\x00\x00\x00\x005\x1dH\xb0\x00\x00\x00\x0062#\xb0\x00\x00\x00\x006\xfd*\xb0\x00\x00\x00\x008\x1b@0\x00\x00\x00\x008\xdd\f\xb0\x00\x00\x00\x009" + - "\xfb\"0\x00\x00\x00\x00:\xbc\xee\xb0\x00\x00\x00\x00;\xdb\x040\x00\x00\x00\x00<\xa6\v0\x00\x00\x00\x00=\xba\xe60\x00\x00\x00\x00>\x85\xed0\x00\x00\x00\x00?\x9a\xc80\x00\x00\x00\x00@e\xcf0\x00" + - "\x00\x00\x00A\x83\xe4\xb0\x00\x00\x00\x00BE\xb10\x00\x00\x00\x00Ccư\x00\x00\x00\x00D%\x930\x00\x00\x00\x00EC\xa8\xb0\x00\x00\x00\x00F\x05u0\x00\x00\x00\x00G#\x8a\xb0\x00\x00\x00\x00G" + - "\ue470\x00\x00\x00\x00I\x03l\xb0\x00\x00\x00\x00I\xces\xb0\x00\x00\x00\x00J\xe3N\xb0\x00\x00\x00\x00K\xaeU\xb0\x00\x00\x00\x00L\xccy@\x00\x00\x00\x00M\x8eE\xc0\x01\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x00\x00Q\xc0\x00" + - "\x00\x00\x00T`\x00\x04\x00\x00p\x80\x01\b\x00\x00bp\x00\f\x00\x00bp\x01\fLMT\x00+06\x00+08\x00+07\x00\n<+07>-7\nPK\x03\x04\n\x00\x00\x00\x00\x00" + - "\xf1c9R0]*\x1bj\x02\x00\x00j\x02\x00\x00\f\x00\x1c\x00Asia/BishkekUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00" + - "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x19~\x10\xff\xff\xff\xff\xb5\xa3\xef0\x00\x00\x00\x00\x15'}\xa0\x00" + - "\x00\x00\x00\x16\x18\xb2\x10\x00\x00\x00\x00\x17\b\xb1 \x00\x00\x00\x00\x17\xf9\xe5\x90\x00\x00\x00\x00\x18\xe9\xe4\xa0\x00\x00\x00\x00\x19\xdb\x19\x10\x00\x00\x00\x00\x1a\xcci\xa0\x00\x00\x00\x00\x1b\xbcv\xc0\x00\x00\x00\x00\x1c" + - "\xacg\xc0\x00\x00\x00\x00\x1d\x9cX\xc0\x00\x00\x00\x00\x1e\x8cI\xc0\x00\x00\x00\x00\x1f|:\xc0\x00\x00\x00\x00 l+\xc0\x00\x00\x00\x00!\\\x1c\xc0\x00\x00\x00\x00\"L\r\xc0\x00\x00\x00\x00#;\xfe\xc0\x00" + - "\x00\x00\x00$+\xef\xc0\x00\x00\x00\x00%\x1b\xe0\xc0\x00\x00\x00\x00&\v\xd1\xc0\x00\x00\x00\x00'\x04\xfd@\x00\x00\x00\x00'\xf4\xee@\x00\x00\x00\x00(\xbe\xa3\xc0\x00\x00\x00\x00)\xe770\x00\x00\x00\x00*" + - "ĥ \x00\x00\x00\x00+\xc7\x190\x00\x00\x00\x00,\xa4\x87 \x00\x00\x00\x00-\xa6\xfb0\x00\x00\x00\x00.\x84i \x00\x00\x00\x00/\x86\xdd0\x00\x00\x00\x000dK \x00\x00\x00\x001f\xbf0\x00" + - "\x00\x00\x002Mg\xa0\x00\x00\x00\x003=\x89\xd8\x00\x00\x00\x004RV\xc8\x00\x00\x00\x005\x1dk\xd8\x00\x00\x00\x00628\xc8\x00\x00\x00\x006\xfdM\xd8\x00\x00\x00\x008\x1bUH\x00\x00\x00\x008" + - "\xdd/\xd8\x00\x00\x00\x009\xfb7H\x00\x00\x00\x00:\xbd\x11\xd8\x00\x00\x00\x00;\xdb\x19H\x00\x00\x00\x00<\xa6.X\x00\x00\x00\x00=\xba\xfbH\x00\x00\x00\x00>\x86\x10X\x00\x00\x00\x00?\x9a\xddH\x00" + - "\x00\x00\x00@e\xf2X\x00\x00\x00\x00A\x83\xf9\xc8\x00\x00\x00\x00BE\xd4X\x00\x00\x00\x00B\xfb\x92 \x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x04\x01\x04\x01\x04" + - "\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x03\x00\x00E\xf0\x00\x00\x00\x00FP\x00\x04\x00\x00bp\x01\b\x00\x00T`\x00\f\x00\x00T`\x01\fLMT\x00+05" + - "\x00+07\x00+06\x00\n<+06>-6\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xa7f^]@\x01\x00\x00@\x01\x00\x00\f\x00\x1c\x00Asia/Kuching" + - "UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00\x00\x00\x05\x00" + - "\x00\x00\x18\xff\xff\xff\xff\xad\x8a\x06\x90\xff\xff\xff\xff\xbagG\x88\xff\xff\xff\xff\xbf{'\x80\xff\xff\xff\xff\xbf\xf3\x1bP\xff\xff\xff\xff\xc1]\xac\x80\xff\xff\xff\xff\xc1ՠP\xff\xff\xff\xff\xc3>\xe0\x00\xff" + - "\xff\xff\xffö\xd3\xd0\xff\xff\xff\xff\xc5 \x13\x80\xff\xff\xff\xffŘ\aP\xff\xff\xff\xff\xc7\x01G\x00\xff\xff\xff\xff\xc7y:\xd0\xff\xff\xff\xff\xc8\xe3\xcc\x00\xff\xff\xff\xff\xc9[\xbf\xd0\xff\xff\xff\xff\xca" + - "\xc4\xff\x80\xff\xff\xff\xff\xcb<\xf3P\xff\xff\xff\xffˑX\x00\xff\xff\xff\xff\xd2Hm\xf0\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x03\x00\x00gp\x00\x00\x00\x00ix\x00\x04\x00\x00u" + - "0\x01\n\x00\x00p\x80\x00\x10\x00\x00~\x90\x00\x14LMT\x00+0730\x00+0820\x00+08\x00+09\x00\n<+08>-8\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c" + - "9R\x84)\r\xbd\xec\x00\x00\x00\xec\x00\x00\x00\v\x00\x1c\x00Asia/SaigonUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZi" + - "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xff\x88\x8cC\x80\xff\xff\xff\xff\x91\xa3+\n\xff\xff\xff\xff\xcd5\xe6\x80\xff\xff\xff\xff" + - "\xd1Y\xcep\xff\xff\xff\xff\xd2;>\xf0\xff\xff\xff\xff\xd52\xbb\x10\xff\xff\xff\xff\xe4\xb6\xe4\x80\xff\xff\xff\xff\xed/\x98\x00\x00\x00\x00\x00\n=\xc7\x00\x01\x02\x03\x04\x02\x03\x02\x03\x02\x00\x00d\x00\x00\x00\x00" + - "\x00c\xf6\x00\x04\x00\x00bp\x00\t\x00\x00p\x80\x00\r\x00\x00~\x90\x00\x11LMT\x00PLMT\x00+07\x00+08\x00+09\x00\n<+07>-7\nPK\x03\x04\n\x00\x00" + - "\x00\x00\x00\xf1c9R\x06\xaa>\xa8\x00\x01\x00\x00\x00\x01\x00\x00\x0e\x00\x1c\x00Asia/SingaporeUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00" + - "\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif" + - "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\x00\x00\x00\b\x00\x00\x00 \xff\xff\xff\xff~6S\xa3\xff\xff\xff\xff\x86\x83\x85\xa3\xff\xff\xff\xff" + - "\xbagN\x90\xff\xff\xff\xff\xc0\n\xe4`\xff\xff\xff\xffʳ\xe5`\xff\xff\xff\xffˑ_\b\xff\xff\xff\xff\xd2Hm\xf0\x00\x00\x00\x00\x16\x91\xf5\b\x01\x02\x03\x04\x05\x06\x05\a\x00\x00a]\x00\x00\x00\x00" + - "a]\x00\x04\x00\x00bp\x00\b\x00\x00g \x01\f\x00\x00g \x00\f\x00\x00ix\x00\x12\x00\x00~\x90\x00\x18\x00\x00p\x80\x00\x1cLMT\x00SMT\x00+07\x00+0720\x00+0" + - "730\x00+09\x00+08\x00\n<+08>-8\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R)p\x1cX\xf1\x02\x00\x00\xf1\x02\x00\x00\x10\x00\x1c\x00Asia/Novo" + - "sibirskUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00C\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xa1\xdb\x19$\xff\xff\xff\xff\xb5\xa3\xe1 \x00\x00\x00\x00\x15'o\x90\x00\x00\x00\x00\x16\x18\xa4\x00\x00\x00\x00\x00\x17\b\xa3\x10\x00\x00\x00\x00\x17\xf9׀\x00\x00" + - "\x00\x00\x18\xe9\u0590\x00\x00\x00\x00\x19\xdb\v\x00\x00\x00\x00\x00\x1a\xcc[\x90\x00\x00\x00\x00\x1b\xbch\xb0\x00\x00\x00\x00\x1c\xacY\xb0\x00\x00\x00\x00\x1d\x9cJ\xb0\x00\x00\x00\x00\x1e\x8c;\xb0\x00\x00\x00\x00\x1f|" + - ",\xb0\x00\x00\x00\x00 l\x1d\xb0\x00\x00\x00\x00!\\\x0e\xb0\x00\x00\x00\x00\"K\xff\xb0\x00\x00\x00\x00#;\xf0\xb0\x00\x00\x00\x00$+\xe1\xb0\x00\x00\x00\x00%\x1bҰ\x00\x00\x00\x00&\vð\x00\x00" + - "\x00\x00'\x04\xef0\x00\x00\x00\x00'\xf4\xe00\x00\x00\x00\x00(\xe4\xdf@\x00\x00\x00\x00)x\x87@\x00\x00\x00\x00)\xd4\xc20\x00\x00\x00\x00*ij0\x00\x00\x00\x00+\xb4\xa40\x00\x00\x00\x00+\xfe" + - "N\x00\x00\x00\x00\x00,\xa4\xa3@\x00\x00\x00\x00-\x94\x94@\x00\x00\x00\x00.\x84\x85@\x00\x00\x00\x00/tv@\x00\x00\x00\x000dg@\x00\x00\x00\x001]\x92\xc0\x00\x00\x00\x002rm\xc0\x00\x00" + - "\x00\x003=t\xc0\x00\x00\x00\x004RO\xc0\x00\x00\x00\x005\x1dV\xc0\x00\x00\x00\x00621\xc0\x00\x00\x00\x006\xfd8\xc0\x00\x00\x00\x008\x1bN@\x00\x00\x00\x008\xdd\x1a\xc0\x00\x00\x00\x009\xfb" + - "0@\x00\x00\x00\x00:\xbc\xfc\xc0\x00\x00\x00\x00;\xdb\x12@\x00\x00\x00\x00<\xa6\x19@\x00\x00\x00\x00=\xba\xf4@\x00\x00\x00\x00>\x85\xfb@\x00\x00\x00\x00?\x9a\xd6@\x00\x00\x00\x00@e\xdd@\x00\x00" + - "\x00\x00A\x83\xf2\xc0\x00\x00\x00\x00BE\xbf@\x00\x00\x00\x00Cc\xd4\xc0\x00\x00\x00\x00D%\xa1@\x00\x00\x00\x00EC\xb6\xc0\x00\x00\x00\x00F\x05\x83@\x00\x00\x00\x00G#\x98\xc0\x00\x00\x00\x00G\xee" + - "\x9f\xc0\x00\x00\x00\x00I\x03z\xc0\x00\x00\x00\x00I\u0381\xc0\x00\x00\x00\x00J\xe3\\\xc0\x00\x00\x00\x00K\xaec\xc0\x00\x00\x00\x00L\xccy@\x00\x00\x00\x00M\x8eE\xc0\x00\x00\x00\x00TK\xf30\x00\x00" + - "\x00\x00W\x93\xcc\xc0\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01" + - "\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x03\x01\x03\x00\x00M\xbc\x00\x00\x00\x00T`\x00\x04\x00\x00p\x80\x01\b\x00\x00bp\x00\f\x00\x00bp\x01\fLMT\x00+06\x00+08\x00+07\x00\n" + - "<+07>-7\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R?\xa7^\xfah\x02\x00\x00h\x02\x00\x00\v\x00\x1c\x00Asia/AtyrauUT\t\x00\x03\x15\xac\x0e`\x15\xac" + - "\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" + - "\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x002\x00\x00\x00\a\x00\x00\x00\x14\xff\xff\xff\xff\xaa\x19\x93P" + - "\xff\xff\xff\xff\xb5\xa4\vP\x00\x00\x00\x00\x16\x18\xce0\x00\x00\x00\x00\x17\b\xb1 \x00\x00\x00\x00\x17\xf9\xf3\xa0\x00\x00\x00\x00\x18\xe9\xf2\xb0\x00\x00\x00\x00\x19\xdb' \x00\x00\x00\x00\x1a\xccw\xb0\x00\x00\x00\x00" + - "\x1b\xbc\x84\xd0\x00\x00\x00\x00\x1c\xacu\xd0\x00\x00\x00\x00\x1d\x9cf\xd0\x00\x00\x00\x00\x1e\x8cW\xd0\x00\x00\x00\x00\x1f|H\xd0\x00\x00\x00\x00 l9\xd0\x00\x00\x00\x00!\\*\xd0\x00\x00\x00\x00\"L\x1b\xd0" + - "\x00\x00\x00\x00#<\f\xd0\x00\x00\x00\x00$+\xfd\xd0\x00\x00\x00\x00%\x1b\xee\xd0\x00\x00\x00\x00&\v\xdf\xd0\x00\x00\x00\x00'\x05\vP\x00\x00\x00\x00'\xf4\xfcP\x00\x00\x00\x00(\xe4\xfb`\x00\x00\x00\x00" + - ")x\xa3`\x00\x00\x00\x00)\xd4\xdeP\x00\x00\x00\x00*\xc4\xcfP\x00\x00\x00\x00+\xb4\xc0P\x00\x00\x00\x00,\xa4\xb1P\x00\x00\x00\x00-\x94\xa2P\x00\x00\x00\x00.\x84\x93P\x00\x00\x00\x00/t\x84P" + - "\x00\x00\x00\x000duP\x00\x00\x00\x001]\xa0\xd0\x00\x00\x00\x002r{\xd0\x00\x00\x00\x003=\x82\xd0\x00\x00\x00\x004R]\xd0\x00\x00\x00\x005\x1dd\xd0\x00\x00\x00\x0062?\xd0\x00\x00\x00\x00" + - "6\xfdF\xd0\x00\x00\x00\x008\x1bj`\x00\x00\x00\x008\xdd6\xe0\x00\x00\x00\x009\xfbL`\x00\x00\x00\x00:\xbd\x18\xe0\x00\x00\x00\x00;\xdb.`\x00\x00\x00\x00<\xa65`\x00\x00\x00\x00=\xbb\x10`" + - "\x00\x00\x00\x00>\x86\x17`\x00\x00\x00\x00?\x9a\xf2`\x00\x00\x00\x00@e\xf9`\x00\x00\x00\x00A\x84\x0e\xe0\x01\x02\x03\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x05\x06\x02\x04\x02\x04\x02" + - "\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x02\x00\x000\xb0\x00\x00\x00\x00*0\x00\x04\x00\x00FP\x00\b\x00\x00T`\x00\f\x00\x00T`\x01\f\x00\x00FP\x01\b\x00\x00" + - "8@\x00\x10LMT\x00+03\x00+05\x00+06\x00+04\x00\n<+05>-5\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x88έ\xe2\xbd\x04\x00\x00\xbd\x04\x00\x00\t" + - "\x00\x1c\x00Asia/GazaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00s\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xff}\xbdJ\xb0\xff\xff\xff\xff\xc8Y\xcf\x00\xff\xff\xff\xff\xc8\xfa\xa6\x00\xff\xff\xff\xff\xc98\x9c\x80\xff\xff\xff\xff\xcc\xe5\xeb\x80\xff\xff\xff\xff\xcd" + - "\xac\xfe\x00\xff\xff\xff\xff\xce\xc7\x1f\x00\xff\xff\xff\xffϏ\x83\x00\xff\xff\xff\xffЩ\xa4\x00\xff\xff\xff\xffф}\x00\xff\xff\xff\xffҊ׀\xff\xff\xff\xff\xd3e\xb0\x80\xff\xff\xff\xff\xd4l\v\x00\xff" + - "\xff\xff\xff\xe86c`\xff\xff\xff\xff\xe8\xf4-P\xff\xff\xff\xff\xea\v\xb9`\xff\xff\xff\xff\xea\xd5`\xd0\xff\xff\xff\xff\xeb\xec\xfa\xf0\xff\xff\xff\xff\xec\xb5m\x00\xff\xff\xff\xff\xed\xcf\u007f\xf0\xff\xff\xff\xff\xee" + - "\x97\xf2\x00\xff\xff\xff\xffﰳp\xff\xff\xff\xff\xf0y%\x80\xff\xff\xff\xff\xf1\x91\xe6\xf0\xff\xff\xff\xff\xf2ZY\x00\xff\xff\xff\xff\xf3s\x1ap\xff\xff\xff\xff\xf4;\x8c\x80\xff\xff\xff\xff\xf5U\x9fp\xff" + - "\xff\xff\xff\xf6\x1e\x11\x80\xff\xff\xff\xff\xf76\xd2\xf0\xff\xff\xff\xff\xf7\xffE\x00\xff\xff\xff\xff\xf9\x18\x06p\xff\xff\xff\xff\xf9\xe1\xca\x00\xff\xff\xff\xff\xfa\xf99\xf0\xff\xff\xff\xff\xfb'BP\x00\x00\x00\x00\b" + - "|\x8b\xe0\x00\x00\x00\x00\b\xfd\xb0\xd0\x00\x00\x00\x00\t\xf6\xea`\x00\x00\x00\x00\n\xa63\xd0\x00\x00\x00\x00\x13\xe9\xfc`\x00\x00\x00\x00\x14![`\x00\x00\x00\x00\x1a\xfa\xc6`\x00\x00\x00\x00\x1b\x8en`\x00" + - "\x00\x00\x00\x1c\xbe\xf8\xe0\x00\x00\x00\x00\x1dw|\xd0\x00\x00\x00\x00\x1e\xcc\xff`\x00\x00\x00\x00\x1f`\x99P\x00\x00\x00\x00 \x82\xb1`\x00\x00\x00\x00!I\xb5\xd0\x00\x00\x00\x00\"^\x9e\xe0\x00\x00\x00\x00#" + - " ]P\x00\x00\x00\x00$Z0`\x00\x00\x00\x00%\x00?P\x00\x00\x00\x00&\v\xed\xe0\x00\x00\x00\x00&\xd6\xe6\xd0\x00\x00\x00\x00'\xeb\xcf\xe0\x00\x00\x00\x00(\xc0\x03P\x00\x00\x00\x00)\xd4\xec`\x00" + - "\x00\x00\x00*\xa9\x1f\xd0\x00\x00\x00\x00+\xbbe\xe0\x00\x00\x00\x00,\x89\x01\xd0\x00\x00\x00\x00-\x9bG\xe0\x00\x00\x00\x00._\xa9P\x00\x00\x00\x00/{)\xe0\x00\x00\x00\x000H\xc5\xd0\x00\x00\x00\x000" + - "\xe7\a\xe0\x00\x00\x00\x001dF`\x00\x00\x00\x002A\xc2`\x00\x00\x00\x003D(`\x00\x00\x00\x004!\xa4`\x00\x00\x00\x005$\n`\x00\x00\x00\x006\x01\x86`\x00\x00\x00\x007\x16a`\x00" + - "\x00\x00\x008\x06DP\x00\x00\x00\x008\xff}\xe0\x00\x00\x00\x009\xef`\xd0\x00\x00\x00\x00:\xdf_\xe0\x00\x00\x00\x00;\xcfB\xd0\x00\x00\x00\x00<\xbfA\xe0\x00\x00\x00\x00=\xaf$\xd0\x00\x00\x00\x00>" + - "\x9f#\xe0\x00\x00\x00\x00?\x8f\x06\xd0\x00\x00\x00\x00@\u007f\x05\xe0\x00\x00\x00\x00A\\\x81\xe0\x00\x00\x00\x00B^\xe7\xe0\x00\x00\x00\x00CA\xb7\xf0\x00\x00\x00\x00D-\xa6`\x00\x00\x00\x00E\x12\xfdP\x00" + - "\x00\x00\x00F\x0e\xd9\xe0\x00\x00\x00\x00F\xe8op\x00\x00\x00\x00G\xec\x18\xe0\x00\x00\x00\x00H\xb7\x11\xd0\x00\x00\x00\x00I\xcb\xfa\xe0\x00\x00\x00\x00J\xa0<`\x00\x00\x00\x00K\xad.\x9c\x00\x00\x00\x00L" + - "a\xbd\xd0\x00\x00\x00\x00M\x94\xf9\x9c\x00\x00\x00\x00N5\xc2P\x00\x00\x00\x00Ot\xdb`\x00\x00\x00\x00P[\x91\xe0\x00\x00\x00\x00QT\xbd`\x00\x00\x00\x00RD\xa0P\x00\x00\x00\x00S4\x9f`\x00" + - "\x00\x00\x00TIlP\x00\x00\x00\x00U\x15\xd2\xe0\x00\x00\x00\x00V)\\`\x00\x00\x00\x00V\xf5\xc2\xf0\x00\x00\x00\x00X\x13\xca`\x00\x00\x00\x00Xդ\xf0\x00\x00\x00\x00Y\xf3\xac`\x00\x00\x00\x00Z" + - "\xb5\x86\xf0\x00\x00\x00\x00[ӎ`\x00\x00\x00\x00\\\x9dC\xe0\x00\x00\x00\x00]\xb3bP\x00\x00\x00\x00^~w`\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00 P\x00\x00\x00\x00*0\x01\x04\x00\x00\x1c \x00\t\x00\x00*0\x01\r\x00\x00\x1c \x00\x11" + - "LMT\x00EEST\x00EET\x00IDT\x00IST\x00\nEET-2EEST,M3.4.4/48,M10.4.4/49\nPK\x03\x04\n\x00\x00" + - "\x00\x00\x00\xf1c9RΒ\x1a\x8c\xaa\x00\x00\x00\xaa\x00\x00\x00\t\x00\x1c\x00Asia/DiliUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00" + - "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x92\xe6\x18\xc4\xff\xff\xff\xff˙2\xf0\x00\x00\x00\x00\v\xea0p\x00" + - "\x00\x00\x009Ù\x00\x01\x02\x01\x02\x00\x00u\xbc\x00\x00\x00\x00p\x80\x00\x04\x00\x00~\x90\x00\bLMT\x00+08\x00+09\x00\n<+09>-9\nPK\x03\x04\n\x00\x00\x00\x00\x00" + - "\xf1c9R\xab\xcd\xdf\x05\xee\x02\x00\x00\xee\x02\x00\x00\n\x00\x1c\x00Asia/ChitaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZ" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xffV\xb6\x85\xc4\xff\xff\xff\xff\xa2jg\xc4\x01\x02\x00\x00^<\x00\x00\x00\x00^<\x00\x04\x00\x00bp\x00\bLMT\x00B" + + "MT\x00+07\x00\n<+07>-7\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xcfׇ\xe1\x85\x00\x00\x00\x85\x00\x00\x00\v\x00\x1c\x00Asia/RiyadhUT\t" + + "\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b" + + "\xff\xff\xff\xff\xd5\x1b6\xb4\x01\x00\x00+\xcc\x00\x00\x00\x00*0\x00\x04LMT\x00+03\x00\n<+03>-3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSΒ\x1a\x8c\xaa\x00\x00\x00" + + "\xaa\x00\x00\x00\t\x00\x1c\x00Asia/DiliUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x92\xe6\x18\xc4\xff\xff\xff\xff˙2\xf0\x00\x00\x00\x00\v\xea0p\x00\x00\x00\x009Ù\x00\x01\x02\x01\x02\x00\x00u\xbc" + + "\x00\x00\x00\x00p\x80\x00\x04\x00\x00~\x90\x00\bLMT\x00+08\x00+09\x00\n<+09>-9\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSL\xe0\x91y\xe5\x02\x00\x00\xe5\x02\x00" + + "\x00\x10\x00\x1c\x00Asia/KrasnoyarskUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00A\x00\x00\x00\x06\x00\x00\x00\x10\xff\xff\xff\xff\xa1\xf9\r\xf2\xff\xff\xff\xff\xb5\xa3\xe1 \x00\x00\x00\x00\x15'o\x90\x00\x00\x00\x00\x16\x18\xa4\x00\x00\x00\x00\x00" + + "\x17\b\xa3\x10\x00\x00\x00\x00\x17\xf9׀\x00\x00\x00\x00\x18\xe9\u0590\x00\x00\x00\x00\x19\xdb\v\x00\x00\x00\x00\x00\x1a\xcc[\x90\x00\x00\x00\x00\x1b\xbch\xb0\x00\x00\x00\x00\x1c\xacY\xb0\x00\x00\x00\x00\x1d\x9cJ\xb0" + + "\x00\x00\x00\x00\x1e\x8c;\xb0\x00\x00\x00\x00\x1f|,\xb0\x00\x00\x00\x00 l\x1d\xb0\x00\x00\x00\x00!\\\x0e\xb0\x00\x00\x00\x00\"K\xff\xb0\x00\x00\x00\x00#;\xf0\xb0\x00\x00\x00\x00$+\xe1\xb0\x00\x00\x00\x00" + + "%\x1bҰ\x00\x00\x00\x00&\vð\x00\x00\x00\x00'\x04\xef0\x00\x00\x00\x00'\xf4\xe00\x00\x00\x00\x00(\xe4\xdf@\x00\x00\x00\x00)x\x87@\x00\x00\x00\x00)\xd4\xc20\x00\x00\x00\x00*ij0" + + "\x00\x00\x00\x00+\xb4\xa40\x00\x00\x00\x00,\xa4\x950\x00\x00\x00\x00-\x94\x860\x00\x00\x00\x00.\x84w0\x00\x00\x00\x00/th0\x00\x00\x00\x000dY0\x00\x00\x00\x001]\x84\xb0\x00\x00\x00\x00" + + "2r_\xb0\x00\x00\x00\x003=f\xb0\x00\x00\x00\x004RA\xb0\x00\x00\x00\x005\x1dH\xb0\x00\x00\x00\x0062#\xb0\x00\x00\x00\x006\xfd*\xb0\x00\x00\x00\x008\x1b@0\x00\x00\x00\x008\xdd\f\xb0" + + "\x00\x00\x00\x009\xfb\"0\x00\x00\x00\x00:\xbc\xee\xb0\x00\x00\x00\x00;\xdb\x040\x00\x00\x00\x00<\xa6\v0\x00\x00\x00\x00=\xba\xe60\x00\x00\x00\x00>\x85\xed0\x00\x00\x00\x00?\x9a\xc80\x00\x00\x00\x00" + + "@e\xcf0\x00\x00\x00\x00A\x83\xe4\xb0\x00\x00\x00\x00BE\xb10\x00\x00\x00\x00Ccư\x00\x00\x00\x00D%\x930\x00\x00\x00\x00EC\xa8\xb0\x00\x00\x00\x00F\x05u0\x00\x00\x00\x00G#\x8a\xb0" + + "\x00\x00\x00\x00G\ue470\x00\x00\x00\x00I\x03l\xb0\x00\x00\x00\x00I\xces\xb0\x00\x00\x00\x00J\xe3N\xb0\x00\x00\x00\x00K\xaeU\xb0\x00\x00\x00\x00L\xcck0\x00\x00\x00\x00M\x8e7\xb0\x00\x00\x00\x00" + + "TK\xe5 \x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x05\x03\x00\x00W\x0e\x00\x00\x00\x00T`\x00\x04\x00\x00p\x80\x01\b\x00\x00bp\x00\f\x00\x00bp\x01\f\x00\x00p\x80\x00\bLMT\x00+06\x00+08\x00+07" + + "\x00\n<+07>-7\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x83g\x95M\a\x03\x00\x00\a\x03\x00\x00\r\x00\x1c\x00Asia/KhandygaUT\t\x00\x03\x82\x0f" + + "\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00C\x00\x00\x00\b\x00\x00\x00\x14\xff\xff\xff\xff" + + "\xa1\xdb\xe4\xeb\xff\xff\xff\xff\xb5\xa3\xc5\x00\x00\x00\x00\x00\x15'Sp\x00\x00\x00\x00\x16\x18\x87\xe0\x00\x00\x00\x00\x17\b\x86\xf0\x00\x00\x00\x00\x17\xf9\xbb`\x00\x00\x00\x00\x18\xe9\xbap\x00\x00\x00\x00\x19\xda\xee\xe0" + + "\x00\x00\x00\x00\x1a\xcc?p\x00\x00\x00\x00\x1b\xbcL\x90\x00\x00\x00\x00\x1c\xac=\x90\x00\x00\x00\x00\x1d\x9c.\x90\x00\x00\x00\x00\x1e\x8c\x1f\x90\x00\x00\x00\x00\x1f|\x10\x90\x00\x00\x00\x00 l\x01\x90\x00\x00\x00\x00" + + "![\xf2\x90\x00\x00\x00\x00\"K\xe3\x90\x00\x00\x00\x00#;Ԑ\x00\x00\x00\x00$+Ő\x00\x00\x00\x00%\x1b\xb6\x90\x00\x00\x00\x00&\v\xa7\x90\x00\x00\x00\x00'\x04\xd3\x10\x00\x00\x00\x00'\xf4\xc4\x10" + + "\x00\x00\x00\x00(\xe4\xc3 \x00\x00\x00\x00)xk \x00\x00\x00\x00)Ԧ\x10\x00\x00\x00\x00*ė\x10\x00\x00\x00\x00+\xb4\x88\x10\x00\x00\x00\x00,\xa4y\x10\x00\x00\x00\x00-\x94j\x10\x00\x00\x00\x00" + + ".\x84[\x10\x00\x00\x00\x00/tL\x10\x00\x00\x00\x000d=\x10\x00\x00\x00\x001]h\x90\x00\x00\x00\x002rC\x90\x00\x00\x00\x003=J\x90\x00\x00\x00\x004R%\x90\x00\x00\x00\x005\x1d,\x90" + + "\x00\x00\x00\x0062\a\x90\x00\x00\x00\x006\xfd\x0e\x90\x00\x00\x00\x008\x1b$\x10\x00\x00\x00\x008\xdc\xf0\x90\x00\x00\x00\x009\xfb\x06\x10\x00\x00\x00\x00:\xbcҐ\x00\x00\x00\x00;\xda\xe8\x10\x00\x00\x00\x00" + + "<\xa5\xef\x10\x00\x00\x00\x00=\xba\xca\x10\x00\x00\x00\x00>\x85\xd1\x10\x00\x00\x00\x00?\x9a\xac\x10\x00\x00\x00\x00?\xf2\xe4p\x00\x00\x00\x00@e\xa5\x00\x00\x00\x00\x00A\x83\xba\x80\x00\x00\x00\x00BE\x87\x00" + + "\x00\x00\x00\x00Cc\x9c\x80\x00\x00\x00\x00D%i\x00\x00\x00\x00\x00EC~\x80\x00\x00\x00\x00F\x05K\x00\x00\x00\x00\x00G#`\x80\x00\x00\x00\x00G\xeeg\x80\x00\x00\x00\x00I\x03B\x80\x00\x00\x00\x00" + + "I\xceI\x80\x00\x00\x00\x00J\xe3$\x80\x00\x00\x00\x00K\xae+\x80\x00\x00\x00\x00L\xccA\x00\x00\x00\x00\x00M\x8e\r\x80\x00\x00\x00\x00Nn\x02P\x00\x00\x00\x00TK\xc9\x00\x01\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\a\x06\x03\x00" + + "\x00\u007f\x15\x00\x00\x00\x00p\x80\x00\x04\x00\x00\x8c\xa0\x01\b\x00\x00~\x90\x00\f\x00\x00~\x90\x01\f\x00\x00\x9a\xb0\x01\x10\x00\x00\x8c\xa0\x00\b\x00\x00\x9a\xb0\x00\x10LMT\x00+08\x00+10\x00+" + + "09\x00+11\x00\n<+09>-9\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x81z&\x80k\x02\x00\x00k\x02\x00\x00\x0f\x00\x1c\x00Asia/Choibalsa" + + "nUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x003\x00\x00\x00\x06" + + "\x00\x00\x00\x14\xff\xff\xff\xff\x86\xd3\xe7(\x00\x00\x00\x00\x0f\vܐ\x00\x00\x00\x00\x18\xe9Ȁ\x00\x00\x00\x00\x19\xda\xee\xe0\x00\x00\x00\x00\x1a\xcc?p\x00\x00\x00\x00\x1b\xbc\"`\x00\x00\x00\x00\x1c\xac!p" + + "\x00\x00\x00\x00\x1d\x9c\x04`\x00\x00\x00\x00\x1e\x8c\x03p\x00\x00\x00\x00\x1f{\xe6`\x00\x00\x00\x00 k\xe5p\x00\x00\x00\x00![\xc8`\x00\x00\x00\x00\"K\xc7p\x00\x00\x00\x00#;\xaa`\x00\x00\x00\x00" + + "$+\xa9p\x00\x00\x00\x00%\x1b\x8c`\x00\x00\x00\x00&\v\x8bp\x00\x00\x00\x00'\x04\xa8\xe0\x00\x00\x00\x00'\xf4\xa7\xf0\x00\x00\x00\x00(\xe4\x8a\xe0\x00\x00\x00\x00)ԉ\xf0\x00\x00\x00\x00*\xc4l\xe0" + + "\x00\x00\x00\x00+\xb4k\xf0\x00\x00\x00\x00,\xa4N\xe0\x00\x00\x00\x00-\x94M\xf0\x00\x00\x00\x00.\x840\xe0\x00\x00\x00\x00/t/\xf0\x00\x00\x00\x000d\x12\xe0\x00\x00\x00\x001]Lp\x00\x00\x00\x00" + + "2M/`\x00\x00\x00\x003=.p\x00\x00\x00\x004-\x11`\x00\x00\x00\x005\x1d\x10p\x00\x00\x00\x006\f\xf3`\x00\x00\x00\x00:饐\x00\x00\x00\x00;\xb4\x9e\x80\x00\x00\x00\x00<\xa4\x9d\x90" + + "\x00\x00\x00\x00=\x94\x80\x80\x00\x00\x00\x00>\x84\u007f\x90\x00\x00\x00\x00?tb\x80\x00\x00\x00\x00@da\x90\x00\x00\x00\x00ATD\x80\x00\x00\x00\x00BDC\x90\x00\x00\x00\x00C4&\x80\x00\x00\x00\x00" + + "D$%\x90\x00\x00\x00\x00E\x1dC\x00\x00\x00\x00\x00G\xef\xaa\xf0\x00\x00\x00\x00U\x15\x9a\xa0\x00\x00\x00\x00V\x05ap\x00\x00\x00\x00V\xf5|\xa0\x00\x00\x00\x00W\xe5Cp\x01\x02\x04\x03\x04\x03\x04\x03" + + "\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x02\x05\x02\x05\x02\x00\x00kX\x00\x00\x00\x00bp\x00\x04\x00\x00p\x80\x00" + + "\b\x00\x00~\x90\x00\f\x00\x00\x8c\xa0\x01\x10\x00\x00~\x90\x01\fLMT\x00+07\x00+08\x00+09\x00+10\x00\n<+08>-8\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82" + + "iSw\x86\x8d^\x03\x03\x00\x00\x03\x03\x00\x00\r\x00\x1c\x00Asia/Ust-NeraUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00T" + + "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00B\x00\x00\x00\b\x00\x00\x00\x18\xff\xff\xff\xff\xa1\xdbݺ\xff\xff\xff\xff\xb5\xa3\xc5\x00\x00\x00\x00\x00\x15'Sp\x00\x00" + + "\x00\x00\x16\x18k\xc0\x00\x00\x00\x00\x17\bj\xd0\x00\x00\x00\x00\x17\xf9\x9f@\x00\x00\x00\x00\x18\xe9\x9eP\x00\x00\x00\x00\x19\xda\xd2\xc0\x00\x00\x00\x00\x1a\xcc#P\x00\x00\x00\x00\x1b\xbc0p\x00\x00\x00\x00\x1c\xac" + + "!p\x00\x00\x00\x00\x1d\x9c\x12p\x00\x00\x00\x00\x1e\x8c\x03p\x00\x00\x00\x00\x1f{\xf4p\x00\x00\x00\x00 k\xe5p\x00\x00\x00\x00![\xd6p\x00\x00\x00\x00\"K\xc7p\x00\x00\x00\x00#;\xb8p\x00\x00" + + "\x00\x00$+\xa9p\x00\x00\x00\x00%\x1b\x9ap\x00\x00\x00\x00&\v\x8bp\x00\x00\x00\x00'\x04\xb6\xf0\x00\x00\x00\x00'\xf4\xa7\xf0\x00\x00\x00\x00(\xe4\xa7\x00\x00\x00\x00\x00)xO\x00\x00\x00\x00\x00)\xd4" + + "\x89\xf0\x00\x00\x00\x00*\xc4z\xf0\x00\x00\x00\x00+\xb4k\xf0\x00\x00\x00\x00,\xa4\\\xf0\x00\x00\x00\x00-\x94M\xf0\x00\x00\x00\x00.\x84>\xf0\x00\x00\x00\x00/t/\xf0\x00\x00\x00\x000d \xf0\x00\x00" + + "\x00\x001]Lp\x00\x00\x00\x002r'p\x00\x00\x00\x003=.p\x00\x00\x00\x004R\tp\x00\x00\x00\x005\x1d\x10p\x00\x00\x00\x0061\xebp\x00\x00\x00\x006\xfc\xf2p\x00\x00\x00\x008\x1b" + + "\a\xf0\x00\x00\x00\x008\xdc\xd4p\x00\x00\x00\x009\xfa\xe9\xf0\x00\x00\x00\x00:\xbc\xb6p\x00\x00\x00\x00;\xda\xcb\xf0\x00\x00\x00\x00<\xa5\xd2\xf0\x00\x00\x00\x00=\xba\xad\xf0\x00\x00\x00\x00>\x85\xb4\xf0\x00\x00" + + "\x00\x00?\x9a\x8f\xf0\x00\x00\x00\x00@e\x96\xf0\x00\x00\x00\x00A\x83\xacp\x00\x00\x00\x00BEx\xf0\x00\x00\x00\x00Cc\x8ep\x00\x00\x00\x00D%Z\xf0\x00\x00\x00\x00ECpp\x00\x00\x00\x00F\x05" + + "<\xf0\x00\x00\x00\x00G#Rp\x00\x00\x00\x00G\xeeYp\x00\x00\x00\x00I\x034p\x00\x00\x00\x00I\xce;p\x00\x00\x00\x00J\xe3\x16p\x00\x00\x00\x00K\xae\x1dp\x00\x00\x00\x00L\xcc2\xf0\x00\x00" + + "\x00\x00M\x8d\xffp\x00\x00\x00\x00Nm\xf4@\x00\x00\x00\x00TK\xba\xf0\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x05\x06\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04" + + "\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\a\x03\x06\x00\x00\x86F\x00\x00\x00\x00p\x80\x00\x04\x00\x00~\x90\x00\b\x00\x00\x9a\xb0\x00\f\x00\x00\xa8\xc0\x01\x10\x00\x00" + + "\x9a\xb0\x01\f\x00\x00\x8c\xa0\x00\x14\x00\x00\xa8\xc0\x00\x10LMT\x00+08\x00+09\x00+11\x00+12\x00+10\x00\n<+10>-10\nPK\x03\x04\n\x00\x00\x00\x00\x00" + + "#\x82iSe\x1bb2w\x01\x00\x00w\x01\x00\x00\x0e\x00\x1c\x00Asia/AshkhabadUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_" + + "\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x19\x8dD\xff\xff\xff\xff\xb5\xa3\xfd@\x00\x00\x00\x00\x15'\x8b" + + "\xb0\x00\x00\x00\x00\x16\x18\xc0 \x00\x00\x00\x00\x17\b\xbf0\x00\x00\x00\x00\x17\xf9\xf3\xa0\x00\x00\x00\x00\x18\xe9\xf2\xb0\x00\x00\x00\x00\x19\xdb' \x00\x00\x00\x00\x1a\xccw\xb0\x00\x00\x00\x00\x1b\xbc\x84\xd0\x00\x00\x00" + + "\x00\x1c\xacu\xd0\x00\x00\x00\x00\x1d\x9cf\xd0\x00\x00\x00\x00\x1e\x8cW\xd0\x00\x00\x00\x00\x1f|H\xd0\x00\x00\x00\x00 l9\xd0\x00\x00\x00\x00!\\*\xd0\x00\x00\x00\x00\"L\x1b\xd0\x00\x00\x00\x00#<\f" + + "\xd0\x00\x00\x00\x00$+\xfd\xd0\x00\x00\x00\x00%\x1b\xee\xd0\x00\x00\x00\x00&\v\xdf\xd0\x00\x00\x00\x00'\x05\vP\x00\x00\x00\x00'\xf4\xfcP\x00\x00\x00\x00(\xe4\xfb`\x00\x00\x00\x00)x\xa3`\x01\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x00\x006\xbc\x00\x00\x00\x008@\x00\x04\x00\x00T`\x01\b\x00\x00FP\x00\f\x00\x00FP\x01\fLMT\x00+04\x00" + + "+06\x00+05\x00\n<+05>-5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS'\xe2\\\xff\x9f\x00\x00\x00\x9f\x00\x00\x00\n\x00\x1c\x00Asia/KabulUT\t" + + "\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x0e" + + "\xff\xff\xff\xffi\x86\x9a\xa0\xff\xff\xff\xff\xd0\xf9\xd7@\x01\x02\x00\x00@\xe0\x00\x00\x00\x008@\x00\x04\x00\x00?H\x00\bLMT\x00+04\x00+0430\x00\n<+0430>-4" + + ":30\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xa1\xfax\x98g\x02\x00\x00g\x02\x00\x00\r\x00\x1c\x00Asia/QostanayUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8ba" + + "ux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00" + + "\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x003\x00\x00\x00\x06\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x19\x88\\\xff\xff" + + "\xff\xff\xb5\xa3\xfd@\x00\x00\x00\x00\x15'\x8b\xb0\x00\x00\x00\x00\x16\x18\xc0 \x00\x00\x00\x00\x17\b\xb1 \x00\x00\x00\x00\x17\xf9\xf3\xa0\x00\x00\x00\x00\x18\xe9\xf2\xb0\x00\x00\x00\x00\x19\xdb' \x00\x00\x00\x00\x1a\xcc" + + "w\xb0\x00\x00\x00\x00\x1b\xbc\x84\xd0\x00\x00\x00\x00\x1c\xacu\xd0\x00\x00\x00\x00\x1d\x9cf\xd0\x00\x00\x00\x00\x1e\x8cW\xd0\x00\x00\x00\x00\x1f|H\xd0\x00\x00\x00\x00 l9\xd0\x00\x00\x00\x00!\\*\xd0\x00\x00" + + "\x00\x00\"L\x1b\xd0\x00\x00\x00\x00#<\f\xd0\x00\x00\x00\x00$+\xfd\xd0\x00\x00\x00\x00%\x1b\xee\xd0\x00\x00\x00\x00&\v\xdf\xd0\x00\x00\x00\x00'\x05\vP\x00\x00\x00\x00'\xf4\xfcP\x00\x00\x00\x00(\xe4" + + "\xfb`\x00\x00\x00\x00)x\xa3`\x00\x00\x00\x00)\xd4\xdeP\x00\x00\x00\x00*\xc4\xcfP\x00\x00\x00\x00+\xb4\xc0P\x00\x00\x00\x00,\xa4\xb1P\x00\x00\x00\x00-\x94\xa2P\x00\x00\x00\x00.\x84\x93P\x00\x00" + + "\x00\x00/t\x84P\x00\x00\x00\x000duP\x00\x00\x00\x001]\xa0\xd0\x00\x00\x00\x002r{\xd0\x00\x00\x00\x003=\x82\xd0\x00\x00\x00\x004R]\xd0\x00\x00\x00\x005\x1dd\xd0\x00\x00\x00\x0062" + + "?\xd0\x00\x00\x00\x006\xfdF\xd0\x00\x00\x00\x008\x1b\\P\x00\x00\x00\x008\xdd(\xd0\x00\x00\x00\x009\xfb>P\x00\x00\x00\x00:\xbd\n\xd0\x00\x00\x00\x00;\xdb P\x00\x00\x00\x00<\xa6'P\x00\x00" + + "\x00\x00=\xbb\x02P\x00\x00\x00\x00>\x86\tP\x00\x00\x00\x00?\x9a\xe4P\x00\x00\x00\x00@e\xebP\x00\x00\x00\x00A\x84\x00\xd0\x01\x02\x03\x04\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x05\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x00\x00;\xa4\x00\x00\x00\x008@\x00\x04\x00\x00FP\x00\b\x00\x00T`\x01\f\x00\x00T`\x00\f\x00" + + "\x00FP\x01\bLMT\x00+04\x00+05\x00+06\x00\n<+06>-6\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb2\xe27Yn\x01\x00\x00n\x01\x00\x00\r\x00\x1c\x00" + + "Asia/TashkentUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x19\x83\t\xff\xff\xff\xff\xb5\xa3\xef0\x00\x00\x00\x00\x15'}\xa0\x00\x00\x00\x00\x16\x18\xb2\x10\x00\x00\x00\x00\x17\b\xb1 \x00\x00\x00\x00" + + "\x17\xf9\xe5\x90\x00\x00\x00\x00\x18\xe9\xe4\xa0\x00\x00\x00\x00\x19\xdb\x19\x10\x00\x00\x00\x00\x1a\xcci\xa0\x00\x00\x00\x00\x1b\xbcv\xc0\x00\x00\x00\x00\x1c\xacg\xc0\x00\x00\x00\x00\x1d\x9cX\xc0\x00\x00\x00\x00\x1e\x8cI\xc0" + + "\x00\x00\x00\x00\x1f|:\xc0\x00\x00\x00\x00 l+\xc0\x00\x00\x00\x00!\\\x1c\xc0\x00\x00\x00\x00\"L\r\xc0\x00\x00\x00\x00#;\xfe\xc0\x00\x00\x00\x00$+\xef\xc0\x00\x00\x00\x00%\x1b\xe0\xc0\x00\x00\x00\x00" + + "&\v\xd1\xc0\x00\x00\x00\x00'\x04\xfd@\x00\x00\x00\x00'\xf4\xee@\x00\x00\x00\x00(\xe4\xedP\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x00\x00@\xf7\x00\x00\x00\x00" + + "FP\x00\x04\x00\x00bp\x01\b\x00\x00T`\x00\f\x00\x00T`\x01\fLMT\x00+05\x00+07\x00+06\x00\n<+05>-5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82i" + + "S*\xe4@\xa9\x89\x01\x00\x00\x89\x01\x00\x00\r\x00\x1c\x00Asia/ShanghaiUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZ" + "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00B\x00\x00\x00\x06\x00\x00\x00\x10\xff\xff\xff\xff\xa1\xdb\xf9\xa0\xff\xff\xff\xff\xb5\xa3\xc5\x00\x00\x00\x00\x00\x15'Sp\x00\x00\x00" + - "\x00\x16\x18\x87\xe0\x00\x00\x00\x00\x17\b\x86\xf0\x00\x00\x00\x00\x17\xf9\xbb`\x00\x00\x00\x00\x18\xe9\xbap\x00\x00\x00\x00\x19\xda\xee\xe0\x00\x00\x00\x00\x1a\xcc?p\x00\x00\x00\x00\x1b\xbcL\x90\x00\x00\x00\x00\x1c\xac=" + - "\x90\x00\x00\x00\x00\x1d\x9c.\x90\x00\x00\x00\x00\x1e\x8c\x1f\x90\x00\x00\x00\x00\x1f|\x10\x90\x00\x00\x00\x00 l\x01\x90\x00\x00\x00\x00![\xf2\x90\x00\x00\x00\x00\"K\xe3\x90\x00\x00\x00\x00#;Ԑ\x00\x00\x00" + - "\x00$+Ő\x00\x00\x00\x00%\x1b\xb6\x90\x00\x00\x00\x00&\v\xa7\x90\x00\x00\x00\x00'\x04\xd3\x10\x00\x00\x00\x00'\xf4\xc4\x10\x00\x00\x00\x00(\xe4\xc3 \x00\x00\x00\x00)xk \x00\x00\x00\x00)Ԧ" + - "\x10\x00\x00\x00\x00*ė\x10\x00\x00\x00\x00+\xb4\x88\x10\x00\x00\x00\x00,\xa4y\x10\x00\x00\x00\x00-\x94j\x10\x00\x00\x00\x00.\x84[\x10\x00\x00\x00\x00/tL\x10\x00\x00\x00\x000d=\x10\x00\x00\x00" + - "\x001]h\x90\x00\x00\x00\x002rC\x90\x00\x00\x00\x003=J\x90\x00\x00\x00\x004R%\x90\x00\x00\x00\x005\x1d,\x90\x00\x00\x00\x0062\a\x90\x00\x00\x00\x006\xfd\x0e\x90\x00\x00\x00\x008\x1b$" + - "\x10\x00\x00\x00\x008\xdc\xf0\x90\x00\x00\x00\x009\xfb\x06\x10\x00\x00\x00\x00:\xbcҐ\x00\x00\x00\x00;\xda\xe8\x10\x00\x00\x00\x00<\xa5\xef\x10\x00\x00\x00\x00=\xba\xca\x10\x00\x00\x00\x00>\x85\xd1\x10\x00\x00\x00" + - "\x00?\x9a\xac\x10\x00\x00\x00\x00@e\xb3\x10\x00\x00\x00\x00A\x83Ȑ\x00\x00\x00\x00BE\x95\x10\x00\x00\x00\x00Cc\xaa\x90\x00\x00\x00\x00D%w\x10\x00\x00\x00\x00EC\x8c\x90\x00\x00\x00\x00F\x05Y" + - "\x10\x00\x00\x00\x00G#n\x90\x00\x00\x00\x00G\xeeu\x90\x00\x00\x00\x00I\x03P\x90\x00\x00\x00\x00I\xceW\x90\x00\x00\x00\x00J\xe32\x90\x00\x00\x00\x00K\xae9\x90\x00\x00\x00\x00L\xccO\x10\x00\x00\x00" + - "\x00M\x8e\x1b\x90\x00\x00\x00\x00TK\xc9\x00\x00\x00\x00\x00V\xf6\xce \x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x05\x01\x03\x00\x00j`\x00\x00\x00\x00p\x80\x00\x04\x00\x00\x8c\xa0\x01\b\x00\x00~\x90\x00\f\x00\x00~\x90\x01\f\x00\x00\x8c" + - "\xa0\x00\bLMT\x00+08\x00+10\x00+09\x00\n<+09>-9\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xb2\xb9\xf4\xb6R\x02\x00\x00R\x02\x00\x00\x0f\x00\x1c\x00As" + - "ia/Ulan_BatorUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff~6C)\xff\xff\xff\xff\xa0\x97\xa2\x80\xff\xff\xff\xff\xa1y\x04\xf0\xff\xff\xff" + + "\xff\xc8Y^\x80\xff\xff\xff\xff\xc9\t\xf9p\xff\xff\xff\xff\xc9ӽ\x00\xff\xff\xff\xff\xcb\x05\x8a\xf0\xff\xff\xff\xff\xcb|@\x00\xff\xff\xff\xff\xd2;>\xf0\xff\xff\xff\xffӋ{\x80\xff\xff\xff\xff\xd4B\xad" + + "\xf0\xff\xff\xff\xff\xd5E\"\x00\xff\xff\xff\xff\xd6L\xbf\xf0\xff\xff\xff\xff\xd7<\xbf\x00\xff\xff\xff\xff\xd8\x06fp\xff\xff\xff\xff\xd9\x1d\xf2\x80\xff\xff\xff\xff\xd9A|\xf0\x00\x00\x00\x00\x1e\xbaR \x00\x00\x00" + + "\x00\x1fi\x9b\x90\x00\x00\x00\x00 ~\x84\xa0\x00\x00\x00\x00!I}\x90\x00\x00\x00\x00\"g\xa1 \x00\x00\x00\x00#)_\x90\x00\x00\x00\x00$G\x83 \x00\x00\x00\x00%\x12|\x10\x00\x00\x00\x00&'e" + + " \x00\x00\x00\x00&\xf2^\x10\x00\x00\x00\x00(\aG \x00\x00\x00\x00(\xd2@\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00q\xd7\x00\x00" + + "\x00\x00~\x90\x01\x04\x00\x00p\x80\x00\bLMT\x00CDT\x00CST\x00\nCST-8\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xdav\x19z\x98\x00\x00\x00\x98\x00\x00\x00\f\x00\x1c" + + "\x00Asia/BahrainUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x002\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff\x86\xd3\xeeL\x00\x00\x00\x00\x0f\vܐ\x00\x00\x00\x00\x18\xe9Ȁ\x00\x00\x00\x00\x19\xda\xfc\xf0\x00\x00\x00\x00\x1a\xccM\x80\x00\x00\x00\x00" + - "\x1b\xbc0p\x00\x00\x00\x00\x1c\xac/\x80\x00\x00\x00\x00\x1d\x9c\x12p\x00\x00\x00\x00\x1e\x8c\x11\x80\x00\x00\x00\x00\x1f{\xf4p\x00\x00\x00\x00 k\xf3\x80\x00\x00\x00\x00![\xd6p\x00\x00\x00\x00\"KՀ" + - "\x00\x00\x00\x00#;\xb8p\x00\x00\x00\x00$+\xb7\x80\x00\x00\x00\x00%\x1b\x9ap\x00\x00\x00\x00&\v\x99\x80\x00\x00\x00\x00'\x04\xb6\xf0\x00\x00\x00\x00'\xf4\xb6\x00\x00\x00\x00\x00(\xe4\x98\xf0\x00\x00\x00\x00" + - ")Ԙ\x00\x00\x00\x00\x00*\xc4z\xf0\x00\x00\x00\x00+\xb4z\x00\x00\x00\x00\x00,\xa4\\\xf0\x00\x00\x00\x00-\x94\\\x00\x00\x00\x00\x00.\x84>\xf0\x00\x00\x00\x00/t>\x00\x00\x00\x00\x000d \xf0" + - "\x00\x00\x00\x001]Z\x80\x00\x00\x00\x002M=p\x00\x00\x00\x003=<\x80\x00\x00\x00\x004-\x1fp\x00\x00\x00\x005\x1d\x1e\x80\x00\x00\x00\x006\r\x01p\x00\x00\x00\x00:鳠\x00\x00\x00\x00" + - ";\xb4\xac\x90\x00\x00\x00\x00<\xa4\xab\xa0\x00\x00\x00\x00=\x94\x8e\x90\x00\x00\x00\x00>\x84\x8d\xa0\x00\x00\x00\x00?tp\x90\x00\x00\x00\x00@do\xa0\x00\x00\x00\x00ATR\x90\x00\x00\x00\x00BDQ\xa0" + - "\x00\x00\x00\x00C44\x90\x00\x00\x00\x00D$3\xa0\x00\x00\x00\x00E\x1dQ\x10\x00\x00\x00\x00U\x15\x9a\xa0\x00\x00\x00\x00V\x05ap\x00\x00\x00\x00V\xf5|\xa0\x00\x00\x00\x00W\xe5Cp\x01\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x00\x00d4\x00\x00\x00\x00bp\x00\x04\x00\x00" + - "~\x90\x01\b\x00\x00p\x80\x00\fLMT\x00+07\x00+09\x00+08\x00\n<+08>-8\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rw\rD\an\x01\x00\x00n\x01\x00" + - "\x00\x0e\x00\x1c\x00Asia/SamarkandUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\xa1\xf2\x9d0\x00\x00\x00\x00\x04\x8a\x92\xc0\x01\x02\x00\x000P\x00\x00\x00\x008@\x00\x04\x00\x00*0\x00\bLMT\x00+04\x00" + + "+03\x00\n<+03>-3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSʇ{_\xbb\x00\x00\x00\xbb\x00\x00\x00\f\x00\x1c\x00Asia/RangoonUT\t\x00\x03" + + "\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff" + + "\xff\xffV\xb6\x89\xd1\xff\xff\xff\xff\xa1\xf2sQ\xff\xff\xff\xff\xcb\xf2\xfc\x18\xff\xff\xff\xffњg\xf0\x01\x02\x03\x02\x00\x00Z/\x00\x00\x00\x00Z/\x00\x04\x00\x00[h\x00\b\x00\x00~\x90\x00\x0eLM" + + "T\x00RMT\x00+0630\x00+09\x00\n<+0630>-6:30\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS*\xe4@\xa9\x89\x01\x00\x00\x89\x01\x00\x00\x0e\x00\x1c\x00" + + "Asia/ChungkingUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff~6C)\xff\xff\xff\xff\xa0\x97\xa2\x80\xff\xff\xff\xff\xa1y\x04\xf0\xff\xff\xff\xff\xc8Y^\x80\xff\xff\xff\xff\xc9\t\xf9p\xff\xff\xff" + + "\xff\xc9ӽ\x00\xff\xff\xff\xff\xcb\x05\x8a\xf0\xff\xff\xff\xff\xcb|@\x00\xff\xff\xff\xff\xd2;>\xf0\xff\xff\xff\xffӋ{\x80\xff\xff\xff\xff\xd4B\xad\xf0\xff\xff\xff\xff\xd5E\"\x00\xff\xff\xff\xff\xd6L\xbf" + + "\xf0\xff\xff\xff\xff\xd7<\xbf\x00\xff\xff\xff\xff\xd8\x06fp\xff\xff\xff\xff\xd9\x1d\xf2\x80\xff\xff\xff\xff\xd9A|\xf0\x00\x00\x00\x00\x1e\xbaR \x00\x00\x00\x00\x1fi\x9b\x90\x00\x00\x00\x00 ~\x84\xa0\x00\x00\x00" + + "\x00!I}\x90\x00\x00\x00\x00\"g\xa1 \x00\x00\x00\x00#)_\x90\x00\x00\x00\x00$G\x83 \x00\x00\x00\x00%\x12|\x10\x00\x00\x00\x00&'e \x00\x00\x00\x00&\xf2^\x10\x00\x00\x00\x00(\aG" + + " \x00\x00\x00\x00(\xd2@\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00q\xd7\x00\x00\x00\x00~\x90\x01\x04\x00\x00p\x80\x00\bLMT\x00" + + "CDT\x00CST\x00\nCST-8\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS;\u007fP\x8d\xd4\a\x00\x00\xd4\a\x00\x00\v\x00\x1c\x00Asia/TehranUT\t\x00" + + "\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc9\x00\x00\x00\x06\x00\x00\x00\x1c\xff" + + "\xff\xff\xff\x9al}\xc8\xff\xff\xff\xff\xd2\xdb\x12\xc8\x00\x00\x00\x00\x0e\xbb\xa2H\x00\x00\x00\x00\x0ft-@\x00\x00\x00\x00\x10\x8e@0\x00\x00\x00\x00\x10\xed:@\x00\x00\x00\x00\x11Ug\xc8\x00\x00\x00\x00\x12" + + "EJ\xb8\x00\x00\x00\x00\x137\xec\xc8\x00\x00\x00\x00\x14-\x15\xb8\x00\x00\x00\x00( v\xc8\x00\x00\x00\x00(\u06dd\xb8\x00\x00\x00\x00)˜\xc8\x00\x00\x00\x00*\xbe\"\xb8\x00\x00\x00\x00+\xac\xd0H\x00" + + "\x00\x00\x00,\x9fV8\x00\x00\x00\x00-\x8e\x03\xc8\x00\x00\x00\x00.\x80\x89\xb8\x00\x00\x00\x00/o7H\x00\x00\x00\x000a\xbd8\x00\x00\x00\x001Pj\xc8\x00\x00\x00\x002B\xf0\xb8\x00\x00\x00\x003" + + "2\xef\xc8\x00\x00\x00\x004%u\xb8\x00\x00\x00\x005\x14#H\x00\x00\x00\x006\x06\xa98\x00\x00\x00\x006\xf5V\xc8\x00\x00\x00\x007\xe7ܸ\x00\x00\x00\x008֊H\x00\x00\x00\x009\xc9\x108\x00" + + "\x00\x00\x00:\xb9\x0fH\x00\x00\x00\x00;\xab\x958\x00\x00\x00\x00<\x9aB\xc8\x00\x00\x00\x00=\x8cȸ\x00\x00\x00\x00>{vH\x00\x00\x00\x00?m\xfc8\x00\x00\x00\x00@\\\xa9\xc8\x00\x00\x00\x00A" + + "O/\xb8\x00\x00\x00\x00B?.\xc8\x00\x00\x00\x00C1\xb4\xb8\x00\x00\x00\x00G\xe2\xc9H\x00\x00\x00\x00H\xd5O8\x00\x00\x00\x00I\xc5NH\x00\x00\x00\x00J\xb7\xd48\x00\x00\x00\x00K\xa6\x81\xc8\x00" + + "\x00\x00\x00L\x99\a\xb8\x00\x00\x00\x00M\x87\xb5H\x00\x00\x00\x00Nz;8\x00\x00\x00\x00Oh\xe8\xc8\x00\x00\x00\x00P[n\xb8\x00\x00\x00\x00QKm\xc8\x00\x00\x00\x00R=\xf3\xb8\x00\x00\x00\x00S" + + ",\xa1H\x00\x00\x00\x00T\x1f'8\x00\x00\x00\x00U\r\xd4\xc8\x00\x00\x00\x00V\x00Z\xb8\x00\x00\x00\x00V\xef\bH\x00\x00\x00\x00W\xe1\x8e8\x00\x00\x00\x00XэH\x00\x00\x00\x00Y\xc4\x138\x00" + + "\x00\x00\x00Z\xb2\xc0\xc8\x00\x00\x00\x00[\xa5F\xb8\x00\x00\x00\x00\\\x93\xf4H\x00\x00\x00\x00]\x86z8\x00\x00\x00\x00^u'\xc8\x00\x00\x00\x00_g\xad\xb8\x00\x00\x00\x00`W\xac\xc8\x00\x00\x00\x00a" + + "J2\xb8\x00\x00\x00\x00b8\xe0H\x00\x00\x00\x00c+f8\x00\x00\x00\x00d\x1a\x13\xc8\x00\x00\x00\x00e\f\x99\xb8\x00\x00\x00\x00e\xfbGH\x00\x00\x00\x00f\xed\xcd8\x00\x00\x00\x00g\xdd\xccH\x00" + + "\x00\x00\x00h\xd0R8\x00\x00\x00\x00i\xbe\xff\xc8\x00\x00\x00\x00j\xb1\x85\xb8\x00\x00\x00\x00k\xa03H\x00\x00\x00\x00l\x92\xb98\x00\x00\x00\x00m\x81f\xc8\x00\x00\x00\x00ns\xec\xb8\x00\x00\x00\x00o" + + "b\x9aH\x00\x00\x00\x00pU 8\x00\x00\x00\x00qE\x1fH\x00\x00\x00\x00r7\xa58\x00\x00\x00\x00s&R\xc8\x00\x00\x00\x00t\x18ظ\x00\x00\x00\x00u\a\x86H\x00\x00\x00\x00u\xfa\f8\x00" + + "\x00\x00\x00v\xe8\xb9\xc8\x00\x00\x00\x00w\xdb?\xb8\x00\x00\x00\x00x\xcb>\xc8\x00\x00\x00\x00y\xbdĸ\x00\x00\x00\x00z\xacrH\x00\x00\x00\x00{\x9e\xf88\x00\x00\x00\x00|\x8d\xa5\xc8\x00\x00\x00\x00}" + + "\x80+\xb8\x00\x00\x00\x00~n\xd9H\x00\x00\x00\x00\u007fa_8\x00\x00\x00\x00\x80Q^H\x00\x00\x00\x00\x81C\xe48\x00\x00\x00\x00\x822\x91\xc8\x00\x00\x00\x00\x83%\x17\xb8\x00\x00\x00\x00\x84\x13\xc5H\x00" + + "\x00\x00\x00\x85\x06K8\x00\x00\x00\x00\x85\xf4\xf8\xc8\x00\x00\x00\x00\x86\xe7~\xb8\x00\x00\x00\x00\x87\xd7}\xc8\x00\x00\x00\x00\x88\xca\x03\xb8\x00\x00\x00\x00\x89\xb8\xb1H\x00\x00\x00\x00\x8a\xab78\x00\x00\x00\x00\x8b" + + "\x99\xe4\xc8\x00\x00\x00\x00\x8c\x8cj\xb8\x00\x00\x00\x00\x8d{\x18H\x00\x00\x00\x00\x8em\x9e8\x00\x00\x00\x00\x8f]\x9dH\x00\x00\x00\x00\x90P#8\x00\x00\x00\x00\x91>\xd0\xc8\x00\x00\x00\x00\x921V\xb8\x00" + + "\x00\x00\x00\x93 \x04H\x00\x00\x00\x00\x94\x12\x8a8\x00\x00\x00\x00\x95\x017\xc8\x00\x00\x00\x00\x95\xf3\xbd\xb8\x00\x00\x00\x00\x96\xe3\xbc\xc8\x00\x00\x00\x00\x97\xd6B\xb8\x00\x00\x00\x00\x98\xc4\xf0H\x00\x00\x00\x00\x99" + + "\xb7v8\x00\x00\x00\x00\x9a\xa6#\xc8\x00\x00\x00\x00\x9b\x98\xa9\xb8\x00\x00\x00\x00\x9c\x87WH\x00\x00\x00\x00\x9dy\xdd8\x00\x00\x00\x00\x9ei\xdcH\x00\x00\x00\x00\x9f\\b8\x00\x00\x00\x00\xa0K\x0f\xc8\x00" + + "\x00\x00\x00\xa1=\x95\xb8\x00\x00\x00\x00\xa2,CH\x00\x00\x00\x00\xa3\x1e\xc98\x00\x00\x00\x00\xa4\rv\xc8\x00\x00\x00\x00\xa4\xff\xfc\xb8\x00\x00\x00\x00\xa5\xef\xfb\xc8\x00\x00\x00\x00\xa6⁸\x00\x00\x00\x00\xa7" + + "\xd1/H\x00\x00\x00\x00\xa8õ8\x00\x00\x00\x00\xa9\xb2b\xc8\x00\x00\x00\x00\xaa\xa4\xe8\xb8\x00\x00\x00\x00\xab\x93\x96H\x00\x00\x00\x00\xac\x86\x1c8\x00\x00\x00\x00\xadt\xc9\xc8\x00\x00\x00\x00\xaegO\xb8\x00" + + "\x00\x00\x00\xafWN\xc8\x00\x00\x00\x00\xb0IԸ\x00\x00\x00\x00\xb18\x82H\x00\x00\x00\x00\xb2+\b8\x00\x00\x00\x00\xb3\x19\xb5\xc8\x00\x00\x00\x00\xb4\f;\xb8\x00\x00\x00\x00\xb4\xfa\xe9H\x00\x00\x00\x00\xb5" + + "\xedo8\x00\x00\x00\x00\xb6\xddnH\x00\x00\x00\x00\xb7\xcf\xf48\x00\x00\x00\x00\xb8\xbe\xa1\xc8\x00\x00\x00\x00\xb9\xb1'\xb8\x00\x00\x00\x00\xba\x9f\xd5H\x00\x00\x00\x00\xbb\x92[8\x00\x00\x00\x00\xbc\x81\b\xc8\x00" + + "\x00\x00\x00\xbds\x8e\xb8\x00\x00\x00\x00\xbec\x8d\xc8\x00\x00\x00\x00\xbfV\x13\xb8\x00\x00\x00\x00\xc0D\xc1H\x00\x00\x00\x00\xc17G8\x00\x00\x00\x00\xc2%\xf4\xc8\x00\x00\x00\x00\xc3\x18z\xb8\x00\x00\x00\x00\xc4" + + "\a(H\x00\x00\x00\x00\xc4\xf9\xae8\x00\x00\x00\x00\xc5\xe9\xadH\x00\x00\x00\x00\xc6\xdc38\x00\x00\x00\x00\xc7\xca\xe0\xc8\x00\x00\x00\x00Ƚf\xb8\x00\x00\x00\x00ɬ\x14H\x00\x00\x00\x00ʞ\x9a8\x00" + + "\x00\x00\x00ˍG\xc8\x00\x00\x00\x00\xcc\u007f\u0378\x00\x00\x00\x00\xcdo\xcc\xc8\x00\x00\x00\x00\xcebR\xb8\x00\x00\x00\x00\xcfQ\x00H\x00\x00\x00\x00\xd0C\x868\x00\x00\x00\x00\xd123\xc8\x00\x00\x00\x00\xd2" + + "$\xb9\xb8\x00\x00\x00\x00\xd3\x13gH\x00\x00\x00\x00\xd4\x05\xed8\x00\x00\x00\x00\xd4\xf5\xecH\x00\x00\x00\x00\xd5\xe8r8\x00\x00\x00\x00\xd6\xd7\x1f\xc8\x00\x00\x00\x00\xd7ɥ\xb8\x00\x00\x00\x00ظSH\x00" + + "\x00\x00\x00٪\xd98\x00\x00\x00\x00ڙ\x86\xc8\x00\x00\x00\x00ی\f\xb8\x00\x00\x00\x00\xdc|\v\xc8\x00\x00\x00\x00\xddn\x91\xb8\x00\x00\x00\x00\xde]?H\x01\x02\x04\x03\x04\x02\x05\x02\x05\x02\x05\x02\x05" + + "\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05" + + "\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05" + + "\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05" + + "\x02\x05\x02\x05\x02\x05\x02\x05\x00\x0008\x00\x00\x00\x0008\x00\x04\x00\x0018\x00\b\x00\x00FP\x01\x0e\x00\x008@\x00\x12\x00\x00?H\x01\x16LMT\x00TMT\x00+0330\x00+0" + + "5\x00+04\x00+0430\x00\n<+0330>-3:30<+0430>,J79/24,J263/24\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82" + + "iS\aW\x10Ѱ\x04\x00\x00\xb0\x04\x00\x00\r\x00\x1c\x00Asia/IstanbulUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00T" + + "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00s\x00\x00\x00\x06\x00\x00\x00\x19\xff\xff\xff\xffV\xb6\xc8\xd8\xff\xff\xff\xff\x90\x8b\xf5\x98\xff\xff\xff\xff\x9b\f\x17`\xff\xff" + + "\xff\xff\x9bվ\xd0\xff\xff\xff\xff\xa2ec\xe0\xff\xff\xff\xff\xa3{\x82P\xff\xff\xff\xff\xa4N\x80`\xff\xff\xff\xff\xa5?\xb4\xd0\xff\xff\xff\xff\xa6%'\xe0\xff\xff\xff\xff\xa7'\u007f\xd0\xff\xff\xff\xff\xaa(" + + "(`\xff\xff\xff\xff\xaa\xe1\xfd\xd0\xff\xff\xff\xff\xab\xf9\x89\xe0\xff\xff\xff\xff\xac\xc31P\xff\xff\xff\xffȁ?\xe0\xff\xff\xff\xff\xc9\x01\x13P\xff\xff\xff\xff\xc9J\xf5`\xff\xff\xff\xff\xca\u0380P\xff\xff" + + "\xff\xff\xcbˮ`\xff\xff\xff\xff\xd2k\tP\xff\xff\xff\xffӢ9`\xff\xff\xff\xff\xd4C\x02P\xff\xff\xff\xff\xd5L\r\xe0\xff\xff\xff\xff\xd6){\xd0\xff\xff\xff\xff\xd7+\xef\xe0\xff\xff\xff\xff\xd8\t" + + "]\xd0\xff\xff\xff\xff\xd9\x02\x97`\xff\xff\xff\xff\xd9\xe9?\xd0\xff\xff\xff\xff\xda\xeb\xb3\xe0\xff\xff\xff\xff\xdb\xd2\\P\xff\xff\xff\xff\xdc\xd4\xd0`\xff\xff\xff\xffݲ>P\xff\xff\xff\xff\xf1\xf4\xb9`\xff\xff" + + "\xff\xff\xf4b\xefP\xff\xff\xff\xff\xf5h\x06`\xff\xff\xff\xff\xf6\x1f8\xd0\x00\x00\x00\x00\x06n\x93p\x00\x00\x00\x00\a9\x9ap\x00\x00\x00\x00\a\xfbu\x00\x00\x00\x00\x00\t\x19|p\x00\x00\x00\x00\t\xd0" + + "\xcb\x00\x00\x00\x00\x00\n\xf9^p\x00\x00\x00\x00\v\xb1\xfe\x80\x00\x00\x00\x00\f\xd9@p\x00\x00\x00\x00\r\xa4U\x80\x00\x00\x00\x00\x0e\xa6\xadp\x00\x00\x00\x00\x0f\x847\x80\x00\x00\x00\x00\x0f\xf8\x11P\x00\x00" + + "\x00\x00\x19\x89\xb0p\x00\x00\x00\x00\x19ܰ\xe0\x00\x00\x00\x00\x1b\xe6\xd0\xf0\x00\x00\x00\x00\x1c\xc6\xef\xf0\x00\x00\x00\x00\x1d\x9b1p\x00\x00\x00\x00\x1e\x8cs\xf0\x00\x00\x00\x00\x1f|d\xf0\x00\x00\x00\x00 l" + + "U\xf0\x00\x00\x00\x00!\\F\xf0\x00\x00\x00\x00\"L7\xf0\x00\x00\x00\x00#<(\xf0\x00\x00\x00\x00$,\x19\xf0\x00\x00\x00\x00%\x1c\n\xf0\x00\x00\x00\x00&\v\xfb\xf0\x00\x00\x00\x00'\x05'p\x00\x00" + + "\x00\x00'\xf5\x18p\x00\x00\x00\x00(\xe5\tp\x00\x00\x00\x00)\xd4\xfap\x00\x00\x00\x00*\xc4\xebp\x00\x00\x00\x00+\xb4\xdcp\x00\x00\x00\x00,\xa4\xcdp\x00\x00\x00\x00-\x8b\x83\xf0\x00\x00\x00\x00.\x84" + + "\xafp\x00\x00\x00\x00/t\xa0p\x00\x00\x00\x000d\x91p\x00\x00\x00\x001]\xbc\xf0\x00\x00\x00\x002r\x97\xf0\x00\x00\x00\x003=\x9e\xf0\x00\x00\x00\x004Ry\xf0\x00\x00\x00\x005\x1d\x80\xf0\x00\x00" + + "\x00\x0062[\xf0\x00\x00\x00\x006\xfdb\xf0\x00\x00\x00\x008\x1bxp\x00\x00\x00\x008\xddD\xf0\x00\x00\x00\x009\xfbZp\x00\x00\x00\x00:\xbd&\xf0\x00\x00\x00\x00;\xdb\x86%p\x00\x00\x00\x00?\x9b\x00p\x00\x00\x00\x00@f\ap\x00\x00\x00\x00A\x84\x1c\xf0\x00\x00\x00\x00BE\xe9p\x00\x00\x00\x00Cc\xfe\xf0\x00\x00" + + "\x00\x00D%\xcbp\x00\x00\x00\x00EC\xe0\xf0\x00\x00\x00\x00F\x05ɐ\x00\x00\x00\x00G#\xdf\x10\x00\x00\x00\x00G\xee\xe6\x10\x00\x00\x00\x00I\x03\xc1\x10\x00\x00\x00\x00I\xce\xc8\x10\x00\x00\x00\x00J\xe3" + + "\xa3\x10\x00\x00\x00\x00K\xae\xaa\x10\x00\x00\x00\x00L̿\x90\x00\x00\x00\x00M\x8fݐ\x00\x00\x00\x00N\xac\xa1\x90\x00\x00\x00\x00Onn\x10\x00\x00\x00\x00P\x8c\x83\x90\x00\x00\x00\x00QW\x8a\x90\x00\x00" + + "\x00\x00Rle\x90\x00\x00\x00\x00S8\xbe\x10\x00\x00\x00\x00TLG\x90\x00\x00\x00\x00U\x17N\x90\x00\x00\x00\x00V>\x9e\x90\x00\x00\x00\x00V\xf70\x90\x00\x00\x00\x00W\xcf.P\x01\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x04\x05\x04\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x04\x00\x00\x1b(\x00\x00\x00\x00\x1bh\x00" + + "\x04\x00\x00*0\x01\b\x00\x00\x1c \x00\r\x00\x00*0\x00\x11\x00\x008@\x01\x15LMT\x00IMT\x00EEST\x00EET\x00+03\x00+04\x00\n<+03>-3\nP" + + "K\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xed\x8c\xf1\x91\x85\x00\x00\x00\x85\x00\x00\x00\n\x00\x1c\x00Asia/DubaiUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E" + + "\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + + "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\xa1\xf2\x99\xa8\x01\x00\x003\xd8\x00\x00\x00\x008" + + "@\x00\x04LMT\x00+04\x00\n<+04>-4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSb\xadű\xf8\x00\x00\x00\xf8\x00\x00\x00\f\x00\x1c\x00Asia/Jakar" + + "taUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\x00\x00\x00" + + "\a\x00\x00\x00 \xff\xff\xff\xff?fI`\xff\xff\xff\xff\xa9x\x85\xe0\xff\xff\xff\xff\xba\x16\xde`\xff\xff\xff\xff˿\x83\x88\xff\xff\xff\xff\xd2V\xeep\xff\xff\xff\xff\xd7<\xc6\b\xff\xff\xff\xff\xda\xff&" + + "\x00\xff\xff\xff\xff\xf4\xb5\xbe\x88\x01\x02\x03\x04\x03\x05\x03\x06\x00\x00d \x00\x00\x00\x00d \x00\x04\x00\x00g \x00\b\x00\x00ix\x00\x0e\x00\x00~\x90\x00\x14\x00\x00p\x80\x00\x18\x00\x00bp\x00\x1cL" + + "MT\x00BMT\x00+0720\x00+0730\x00+09\x00+08\x00WIB\x00\nWIB-7\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xed\x8c\xf1\x91\x85\x00\x00\x00" + + "\x85\x00\x00\x00\v\x00\x1c\x00Asia/MuscatUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x19\x857\xff\xff\xff\xff\xb5\xa3\xfd@\x00\x00\x00\x00\x15'\x8b\xb0\x00\x00\x00\x00\x16\x18\xc0 \x00\x00\x00\x00\x17\b" + - "\xb1 \x00\x00\x00\x00\x17\xf9\xf3\xa0\x00\x00\x00\x00\x18\xe9\xf2\xb0\x00\x00\x00\x00\x19\xdb' \x00\x00\x00\x00\x1a\xccw\xb0\x00\x00\x00\x00\x1b\xbc\x84\xd0\x00\x00\x00\x00\x1c\xacu\xd0\x00\x00\x00\x00\x1d\x9cf\xd0\x00\x00" + - "\x00\x00\x1e\x8cW\xd0\x00\x00\x00\x00\x1f|H\xd0\x00\x00\x00\x00 l9\xd0\x00\x00\x00\x00!\\*\xd0\x00\x00\x00\x00\"L\x1b\xd0\x00\x00\x00\x00#<\f\xd0\x00\x00\x00\x00$+\xfd\xd0\x00\x00\x00\x00%\x1b" + - "\xee\xd0\x00\x00\x00\x00&\v\xdf\xd0\x00\x00\x00\x00'\x05\vP\x00\x00\x00\x00'\xf4\xfcP\x00\x00\x00\x00(\xe4\xedP\x01\x02\x03\x04\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x00\x00" + - ">\xc9\x00\x00\x00\x008@\x00\x04\x00\x00FP\x00\b\x00\x00T`\x01\f\x00\x00T`\x00\fLMT\x00+04\x00+05\x00+06\x00\n<+05>-5\nPK\x03\x04\n\x00\x00" + - "\x00\x00\x00\xf1c9R\x03R\xda\xedU\x02\x00\x00U\x02\x00\x00\f\x00\x1c\x00Asia/NicosiaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8" + - "\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x001\x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff\xff\xa5w\x1e\xb8\x00\x00\x00\x00\t\xed\xaf\xe0\x00\x00\x00\x00\n\xdd" + - "\x92\xd0\x00\x00\x00\x00\v\xfad\xe0\x00\x00\x00\x00\f\xbe\xc6P\x00\x00\x00\x00\r\xa49`\x00\x00\x00\x00\x0e\x8a\xe1\xd0\x00\x00\x00\x00\x0f\x84\x1b`\x00\x00\x00\x00\x10uO\xd0\x00\x00\x00\x00\x11c\xfd`\x00\x00" + - "\x00\x00\x12S\xe0P\x00\x00\x00\x00\x13M\x19\xe0\x00\x00\x00\x00\x143\xc2P\x00\x00\x00\x00\x15#\xc1`\x00\x00\x00\x00\x16\x13\xa4P\x00\x00\x00\x00\x17\x03\xa3`\x00\x00\x00\x00\x17\xf3\x86P\x00\x00\x00\x00\x18\xe3" + - "\x85`\x00\x00\x00\x00\x19\xd3hP\x00\x00\x00\x00\x1a\xc3g`\x00\x00\x00\x00\x1b\xbc\x84\xd0\x00\x00\x00\x00\x1c\xac\x83\xe0\x00\x00\x00\x00\x1d\x9cf\xd0\x00\x00\x00\x00\x1e\x8ce\xe0\x00\x00\x00\x00\x1f|H\xd0\x00\x00" + - "\x00\x00 lG\xe0\x00\x00\x00\x00!\\*\xd0\x00\x00\x00\x00\"L)\xe0\x00\x00\x00\x00#<\f\xd0\x00\x00\x00\x00$,\v\xe0\x00\x00\x00\x00%\x1b\xee\xd0\x00\x00\x00\x00&\v\xed\xe0\x00\x00\x00\x00'\x05" + - "\vP\x00\x00\x00\x00'\xf5\n`\x00\x00\x00\x00(\xe4\xedP\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xc4\xcfP\x00\x00\x00\x00+\xb4\xce`\x00\x00\x00\x00,\xa4\xb1P\x00\x00\x00\x00-\x94\xb0`\x00\x00" + - "\x00\x00.\x84\x93P\x00\x00\x00\x00/t\x92`\x00\x00\x00\x000duP\x00\x00\x00\x001]\xae\xe0\x00\x00\x00\x002M\x91\xd0\x00\x00\x00\x003=\x90\xe0\x00\x00\x00\x004-s\xd0\x00\x00\x00\x005\x1d" + - "r\xe0\x00\x00\x00\x0062x\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00" + - "\x00\x1fH\x00\x00\x00\x00*0\x01\x04\x00\x00\x1c \x00\tLMT\x00EEST\x00EET\x00\nEET-2EEST,M3.5.0/3,M10.5.0/4\n" + - "PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xcfׇ\xe1\x85\x00\x00\x00\x85\x00\x00\x00\t\x00\x1c\x00Asia/AdenUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03" + - "\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + - "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\xd5\x1b6\xb4\x01\x00\x00+\xcc\x00\x00\x00\x00*" + - "0\x00\x04LMT\x00+03\x00\n<+03>-3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R?Y\xaf\x19\xe7\x00\x00\x00\xe7\x00\x00\x00\n\x00\x1c\x00Asia/Dhaka" + - "UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x06\x00" + - "\x00\x00\x1c\xff\xff\xff\xffi\x86\x86\xbc\xff\xff\xff\xff\xcaۆ\xb0\xff\xff\xff\xff\xcc\x05q\x18\xff\xff\xff\xff̕2\xa8\xff\xff\xff\xffݨҘ\x00\x00\x00\x00J;\xc4\x10\x00\x00\x00\x00K<ؐ\x01" + - "\x02\x03\x02\x04\x05\x04\x00\x00T\xc4\x00\x00\x00\x00R\xd0\x00\x04\x00\x00[h\x00\b\x00\x00MX\x00\x0e\x00\x00T`\x00\x14\x00\x00bp\x01\x18LMT\x00HMT\x00+0630\x00+053" + - "0\x00+06\x00+07\x00\n<+06>-6\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R)\x15II\xf3\x02\x00\x00\xf3\x02\x00\x00\r\x00\x1c\x00Asia/Sakhal" + - "inUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00B\x00\x00\x00" + - "\x06\x00\x00\x00\x14\xff\xff\xff\xff\x86\xf0\u0378\xff\xff\xff\xff\xd20\xb2\xf0\x00\x00\x00\x00\x15'7P\x00\x00\x00\x00\x16\x18k\xc0\x00\x00\x00\x00\x17\bj\xd0\x00\x00\x00\x00\x17\xf9\x9f@\x00\x00\x00\x00\x18\xe9\x9e" + - "P\x00\x00\x00\x00\x19\xda\xd2\xc0\x00\x00\x00\x00\x1a\xcc#P\x00\x00\x00\x00\x1b\xbc0p\x00\x00\x00\x00\x1c\xac!p\x00\x00\x00\x00\x1d\x9c\x12p\x00\x00\x00\x00\x1e\x8c\x03p\x00\x00\x00\x00\x1f{\xf4p\x00\x00\x00" + - "\x00 k\xe5p\x00\x00\x00\x00![\xd6p\x00\x00\x00\x00\"K\xc7p\x00\x00\x00\x00#;\xb8p\x00\x00\x00\x00$+\xa9p\x00\x00\x00\x00%\x1b\x9ap\x00\x00\x00\x00&\v\x8bp\x00\x00\x00\x00'\x04\xb6" + - "\xf0\x00\x00\x00\x00'\xf4\xa7\xf0\x00\x00\x00\x00(\xe4\xa7\x00\x00\x00\x00\x00)xO\x00\x00\x00\x00\x00)ԉ\xf0\x00\x00\x00\x00*\xc4z\xf0\x00\x00\x00\x00+\xb4k\xf0\x00\x00\x00\x00,\xa4\\\xf0\x00\x00\x00" + - "\x00-\x94M\xf0\x00\x00\x00\x00.\x84>\xf0\x00\x00\x00\x00/t/\xf0\x00\x00\x00\x000d \xf0\x00\x00\x00\x001]Lp\x00\x00\x00\x002r'p\x00\x00\x00\x003=.p\x00\x00\x00\x004R\x17" + - "\x80\x00\x00\x00\x005\x1d\x1e\x80\x00\x00\x00\x0061\xf9\x80\x00\x00\x00\x006\xfd\x00\x80\x00\x00\x00\x008\x1b\x16\x00\x00\x00\x00\x008\xdc\xe2\x80\x00\x00\x00\x009\xfa\xf8\x00\x00\x00\x00\x00:\xbcĀ\x00\x00\x00" + - "\x00;\xda\xda\x00\x00\x00\x00\x00<\xa5\xe1\x00\x00\x00\x00\x00=\xba\xbc\x00\x00\x00\x00\x00>\x85\xc3\x00\x00\x00\x00\x00?\x9a\x9e\x00\x00\x00\x00\x00@e\xa5\x00\x00\x00\x00\x00A\x83\xba\x80\x00\x00\x00\x00BE\x87" + - "\x00\x00\x00\x00\x00Cc\x9c\x80\x00\x00\x00\x00D%i\x00\x00\x00\x00\x00EC~\x80\x00\x00\x00\x00F\x05K\x00\x00\x00\x00\x00G#`\x80\x00\x00\x00\x00G\xeeg\x80\x00\x00\x00\x00I\x03B\x80\x00\x00\x00" + - "\x00I\xceI\x80\x00\x00\x00\x00J\xe3$\x80\x00\x00\x00\x00K\xae+\x80\x00\x00\x00\x00L\xccA\x00\x00\x00\x00\x00M\x8e\r\x80\x00\x00\x00\x00TK\xba\xf0\x00\x00\x00\x00V\xf6\xb2\x00\x01\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x05\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x03\x05\x03\x00" + - "\x00\x85\xc8\x00\x00\x00\x00~\x90\x00\x04\x00\x00\xa8\xc0\x01\b\x00\x00\x9a\xb0\x00\f\x00\x00\x9a\xb0\x01\f\x00\x00\x8c\xa0\x00\x10LMT\x00+09\x00+12\x00+11\x00+10\x00\n<+11" + - ">-11\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RT\x81\x18G^\x02\x00\x00^\x02\x00\x00\n\x00\x1c\x00Asia/AqtauUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux" + - "\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00" + - "\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x002\x00\x00\x00\x06\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x19\x94\xe0\xff\xff\xff\xff" + - "\xb5\xa3\xfd@\x00\x00\x00\x00\x16\x18\xce0\x00\x00\x00\x00\x17\b\xb1 \x00\x00\x00\x00\x17\xf9\xf3\xa0\x00\x00\x00\x00\x18\xe9\xf2\xb0\x00\x00\x00\x00\x19\xdb' \x00\x00\x00\x00\x1a\xccw\xb0\x00\x00\x00\x00\x1b\xbc\x84\xd0" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\xa1\xf2\x99\xa8\x01\x00\x003\xd8\x00\x00\x00\x008@\x00\x04LMT\x00+04\x00\n<+04>-4\n" + + "PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xef\\\xf4q\x17\x04\x00\x00\x17\x04\x00\x00\r\x00\x1c\x00Asia/DamascusUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00" + + "\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00" + + "\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00c\x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff\xff\xa1\xf2\xabx\xff\xff\xff\xff\xa2\x81" + + "/\x80\xff\xff\xff\xff\xa3^\x9dp\xff\xff\xff\xff\xa4a\x11\x80\xff\xff\xff\xff\xa5>\u007fp\xff\xff\xff\xff\xa6@\xf3\x80\xff\xff\xff\xff\xa7\x1eap\xff\xff\xff\xff\xa8 Հ\xff\xff\xff\xff\xa9\a}\xf0\xff\xff" + + "\xff\xff\xf1\x8fR\x00\xff\xff\xff\xff\xf2[\x9cp\xff\xff\xff\xff\xf3s(\x80\xff\xff\xff\xff\xf4;~p\xff\xff\xff\xff\xf5U\xad\x80\xff\xff\xff\xff\xf6\x1fT\xf0\xff\xff\xff\xff\xf76\xe1\x00\xff\xff\xff\xff\xf7\xff" + + "6\xf0\xff\xff\xff\xff\xf9\x0e\xda\x00\xff\xff\xff\xff\xf9\xe1\xbb\xf0\xff\xff\xff\xff\xfa\xf9H\x00\xff\xff\xff\xff\xfb\xc2\xefp\xff\xff\xff\xff\xfc\xdb\xcd\x00\xff\xff\xff\xff\xfd\xa5tp\xff\xff\xff\xff\xfe\xbd\x00\x80\xff\xff" + + "\xff\xff\xff\x86\xa7\xf0\x00\x00\x00\x00\x00\x9e4\x00\x00\x00\x00\x00\x01g\xdbp\x00\x00\x00\x00\x02\u007fg\x80\x00\x00\x00\x00\x03I\x0e\xf0\x00\x00\x00\x00\x04a\xec\x80\x00\x00\x00\x00\x05+\x93\xf0\x00\x00\x00\x00\x06C" + + " \x00\x00\x00\x00\x00\a\f\xc7p\x00\x00\x00\x00\b$S\x80\x00\x00\x00\x00\b\xed\xfa\xf0\x00\x00\x00\x00\n\x05\x87\x00\x00\x00\x00\x00\n\xcf.p\x00\x00\x00\x00\v\xe8\f\x00\x00\x00\x00\x00\f\xb1\xb3p\x00\x00" + + "\x00\x00\r\xc9?\x80\x00\x00\x00\x00\x0ekY\xf0\x00\x00\x00\x00\x0f\xaas\x00\x00\x00\x00\x00\x10L\x8dp\x00\x00\x00\x00\x18\xf4\xc5\x00\x00\x00\x00\x00\x19\xdbmp\x00\x00\x00\x00\x1a\xd7J\x00\x00\x00\x00\x00\x1b\xbd" + + "\xf2p\x00\x00\x00\x00\x1eU#\x00\x00\x00\x00\x00\x1f\x8a\xe5p\x00\x00\x00\x00 Gz\x00\x00\x00\x00\x00!\x89\x19\xf0\x00\x00\x00\x00\"\xe2`\x00\x00\x00\x0041hP\x00\x00\x00\x005\x1e\xc4`\x00\x00\x00\x006\x12\x9b\xd0\x00\x00\x00\x007\x02\x9a\xe0\x00\x00\x00\x007\xf3\xcfP\x00\x00\x00\x008\xe5\x1f\xe0\x00\x00\x00\x009\xd6" + + "TP\x00\x00\x00\x00:\xc6S`\x00\x00\x00\x00;\xb7\x87\xd0\x00\x00\x00\x00<\xa7\x86\xe0\x00\x00\x00\x00=\x98\xbbP\x00\x00\x00\x00>\x88\xba`\x00\x00\x00\x00?y\xee\xd0\x00\x00\x00\x00@k?`\x00\x00" + + "\x00\x00A\\s\xd0\x00\x00\x00\x00BLr\xe0\x00\x00\x00\x00C=\xa7P\x00\x00\x00\x00D-\xa6`\x00\x00\x00\x00E\x12\xfdP\x00\x00\x00\x00F\f6\xe0\x00\x00\x00\x00G*>P\x00\x00\x00\x00G\xf5" + + "S`\x00\x00\x00\x00I\vq\xd0\x00\x00\x00\x00I\xcb\xfa\xe0\x00\x00\x00\x00J\xea\x02P\x00\x00\x00\x00K\xb5\x17`\x00\x00\x00\x00L\xc9\xe4P\x00\x00\x00\x00M\x94\xf9`\x00\x00\x00\x00N\xa9\xc6P\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\"\b\x00\x00\x00\x00*0\x01\x04\x00\x00\x1c \x00\tLMT\x00E" + + "EST\x00EET\x00\nEET-2EEST,M3.5.5/0,M10.5.5/0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSO\xb0\x03\xe9\xe5\x02\x00\x00" + + "\xe5\x02\x00\x00\f\x00\x1c\x00Asia/YakutskUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00A\x00\x00\x00\x06\x00\x00\x00\x10\xff\xff\xff\xff\xa1\xdb\xea^\xff\xff\xff\xff\xb5\xa3\xc5\x00\x00\x00\x00\x00\x15'Sp\x00\x00\x00\x00\x16\x18\x87\xe0\x00\x00\x00\x00\x17" + + "\b\x86\xf0\x00\x00\x00\x00\x17\xf9\xbb`\x00\x00\x00\x00\x18\xe9\xbap\x00\x00\x00\x00\x19\xda\xee\xe0\x00\x00\x00\x00\x1a\xcc?p\x00\x00\x00\x00\x1b\xbcL\x90\x00\x00\x00\x00\x1c\xac=\x90\x00\x00\x00\x00\x1d\x9c.\x90\x00" + + "\x00\x00\x00\x1e\x8c\x1f\x90\x00\x00\x00\x00\x1f|\x10\x90\x00\x00\x00\x00 l\x01\x90\x00\x00\x00\x00![\xf2\x90\x00\x00\x00\x00\"K\xe3\x90\x00\x00\x00\x00#;Ԑ\x00\x00\x00\x00$+Ő\x00\x00\x00\x00%" + + "\x1b\xb6\x90\x00\x00\x00\x00&\v\xa7\x90\x00\x00\x00\x00'\x04\xd3\x10\x00\x00\x00\x00'\xf4\xc4\x10\x00\x00\x00\x00(\xe4\xc3 \x00\x00\x00\x00)xk \x00\x00\x00\x00)Ԧ\x10\x00\x00\x00\x00*ė\x10\x00" + + "\x00\x00\x00+\xb4\x88\x10\x00\x00\x00\x00,\xa4y\x10\x00\x00\x00\x00-\x94j\x10\x00\x00\x00\x00.\x84[\x10\x00\x00\x00\x00/tL\x10\x00\x00\x00\x000d=\x10\x00\x00\x00\x001]h\x90\x00\x00\x00\x002" + + "rC\x90\x00\x00\x00\x003=J\x90\x00\x00\x00\x004R%\x90\x00\x00\x00\x005\x1d,\x90\x00\x00\x00\x0062\a\x90\x00\x00\x00\x006\xfd\x0e\x90\x00\x00\x00\x008\x1b$\x10\x00\x00\x00\x008\xdc\xf0\x90\x00" + + "\x00\x00\x009\xfb\x06\x10\x00\x00\x00\x00:\xbcҐ\x00\x00\x00\x00;\xda\xe8\x10\x00\x00\x00\x00<\xa5\xef\x10\x00\x00\x00\x00=\xba\xca\x10\x00\x00\x00\x00>\x85\xd1\x10\x00\x00\x00\x00?\x9a\xac\x10\x00\x00\x00\x00@" + + "e\xb3\x10\x00\x00\x00\x00A\x83Ȑ\x00\x00\x00\x00BE\x95\x10\x00\x00\x00\x00Cc\xaa\x90\x00\x00\x00\x00D%w\x10\x00\x00\x00\x00EC\x8c\x90\x00\x00\x00\x00F\x05Y\x10\x00\x00\x00\x00G#n\x90\x00" + + "\x00\x00\x00G\xeeu\x90\x00\x00\x00\x00I\x03P\x90\x00\x00\x00\x00I\xceW\x90\x00\x00\x00\x00J\xe32\x90\x00\x00\x00\x00K\xae9\x90\x00\x00\x00\x00L\xccO\x10\x00\x00\x00\x00M\x8e\x1b\x90\x00\x00\x00\x00T" + + "K\xc9\x00\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x05\x03\x00\x00y\xa2\x00\x00\x00\x00p\x80\x00\x04\x00\x00\x8c\xa0\x01\b\x00\x00~\x90\x00\f\x00\x00~\x90\x01\f\x00\x00\x8c\xa0\x00\bLMT\x00+08\x00+10\x00+09\x00" + + "\n<+09>-9\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSj$\xcd\xf4\x9a\x00\x00\x00\x9a\x00\x00\x00\f\x00\x1c\x00Asia/ThimphuUT\t\x00\x03\x82\x0f\x8ba" + + "\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00" + + "\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xff\xd5\xe6" + + "\x15t\x00\x00\x00\x00!aM\xa8\x01\x02\x00\x00T\f\x00\x00\x00\x00MX\x00\x04\x00\x00T`\x00\nLMT\x00+0530\x00+06\x00\n<+06>-6\nPK\x03\x04\n\x00\x00" + + "\x00\x00\x00#\x82iSw\rD\an\x01\x00\x00n\x01\x00\x00\x0e\x00\x1c\x00Asia/SamarkandUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00" + + "\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif" + + "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x19\x857\xff\xff\xff\xff\xb5\xa3\xfd@\x00\x00\x00\x00" + + "\x15'\x8b\xb0\x00\x00\x00\x00\x16\x18\xc0 \x00\x00\x00\x00\x17\b\xb1 \x00\x00\x00\x00\x17\xf9\xf3\xa0\x00\x00\x00\x00\x18\xe9\xf2\xb0\x00\x00\x00\x00\x19\xdb' \x00\x00\x00\x00\x1a\xccw\xb0\x00\x00\x00\x00\x1b\xbc\x84\xd0" + "\x00\x00\x00\x00\x1c\xacu\xd0\x00\x00\x00\x00\x1d\x9cf\xd0\x00\x00\x00\x00\x1e\x8cW\xd0\x00\x00\x00\x00\x1f|H\xd0\x00\x00\x00\x00 l9\xd0\x00\x00\x00\x00!\\*\xd0\x00\x00\x00\x00\"L\x1b\xd0\x00\x00\x00\x00" + - "#<\f\xd0\x00\x00\x00\x00$+\xfd\xd0\x00\x00\x00\x00%\x1b\xee\xd0\x00\x00\x00\x00&\v\xdf\xd0\x00\x00\x00\x00'\x05\vP\x00\x00\x00\x00'\xf4\xfcP\x00\x00\x00\x00(\xe4\xfb`\x00\x00\x00\x00)x\xa3`" + - "\x00\x00\x00\x00)\xd4\xdeP\x00\x00\x00\x00*\xc4\xcfP\x00\x00\x00\x00+\xb4\xc0P\x00\x00\x00\x00,\xa4\xb1P\x00\x00\x00\x00-\x94\xa2P\x00\x00\x00\x00.\x84\x93P\x00\x00\x00\x00/t\x92`\x00\x00\x00\x00" + - "0d\x83`\x00\x00\x00\x001]\xae\xe0\x00\x00\x00\x002r\x89\xe0\x00\x00\x00\x003=\x90\xe0\x00\x00\x00\x004Rk\xe0\x00\x00\x00\x005\x1dr\xe0\x00\x00\x00\x0062M\xe0\x00\x00\x00\x006\xfdT\xe0" + - "\x00\x00\x00\x008\x1bj`\x00\x00\x00\x008\xdd6\xe0\x00\x00\x00\x009\xfbL`\x00\x00\x00\x00:\xbd\x18\xe0\x00\x00\x00\x00;\xdb.`\x00\x00\x00\x00<\xa65`\x00\x00\x00\x00=\xbb\x10`\x00\x00\x00\x00" + - ">\x86\x17`\x00\x00\x00\x00?\x9a\xf2`\x00\x00\x00\x00@e\xf9`\x00\x00\x00\x00A\x84\x0e\xe0\x01\x02\x03\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x05\x01\x02\x04\x02\x04\x02\x04\x01\x05\x01" + - "\x05\x01\x05\x01\x05\x01\x05\x01\x05\x01\x05\x01\x05\x01\x05\x01\x05\x02\x00\x00/ \x00\x00\x00\x008@\x00\x04\x00\x00FP\x00\b\x00\x00T`\x00\f\x00\x00T`\x01\f\x00\x00FP\x01\bLMT\x00+0" + - "4\x00+05\x00+06\x00\n<+05>-5\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x8a\xc1\x1eB\xb7\x00\x00\x00\xb7\x00\x00\x00\x0e\x00\x1c\x00Asia/Pyongy" + - "angUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00" + - "\x00\x04\x00\x00\x00\f\xff\xff\xff\xff\x8b\xd7\xf1\x9c\xff\xff\xff\xff\x92\xe6\x16\xf8\xff\xff\xff\xff\xd2/ap\x00\x00\x00\x00U\xce\x02p\x00\x00\x00\x00Z\xecup\x01\x02\x03\x01\x03\x00\x00u\xe4\x00\x00\x00\x00w" + - "\x88\x00\x04\x00\x00~\x90\x00\b\x00\x00~\x90\x00\x04LMT\x00KST\x00JST\x00\nKST-9\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x17✳2\x04\x00\x002\x04\x00\x00" + - "\x0e\x00\x1c\x00Asia/JerusalemUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xffV\xb6\xc2\xfa\xff\xff\xff\xff\x9e0E\x88\xff\xff\xff\xff\xc8Y\xcf\x00\xff\xff\xff\xff\xc8\xfa\xa6\x00\xff\xff\xff\xff\xc98\x9c" + - "\x80\xff\xff\xff\xff\xcc\xe5\xeb\x80\xff\xff\xff\xffͬ\xfe\x00\xff\xff\xff\xff\xce\xc7\x1f\x00\xff\xff\xff\xffϏ\x83\x00\xff\xff\xff\xffЩ\xa4\x00\xff\xff\xff\xffф}\x00\xff\xff\xff\xffҊ׀\xff\xff\xff" + - "\xff\xd3e\xb0\x80\xff\xff\xff\xff\xd4l\v\x00\xff\xff\xff\xff\xd7Z0\x80\xff\xff\xff\xff\xd7\xdfX\x00\xff\xff\xff\xff\xd8/À\xff\xff\xff\xff\xd9\x1ec\x00\xff\xff\xff\xff\xda\x10\xf7\x00\xff\xff\xff\xff\xda\xeb\xd0" + - "\x00\xff\xff\xff\xff۴4\x00\xff\xff\xff\xffܹ=\x00\xff\xff\xff\xff\xdd\xe0\x8d\x00\xff\xff\xff\xff\u07b4\u0380\xff\xff\xff\xffߤ\xbf\x80\xff\xff\xff\xff\xe0\x8bv\x00\xff\xff\xff\xff\xe1V}\x00\xff\xff\xff" + - "\xff\xe2\xbef\x80\xff\xff\xff\xff\xe36_\x00\xff\xff\xff\xff\xe4\x9eH\x80\xff\xff\xff\xff\xe5\x16A\x00\xff\xff\xff\xff\xe6t\xf0\x00\xff\xff\xff\xff\xe7\x11Ҁ\xff\xff\xff\xff\xe8&\xad\x80\xff\xff\xff\xff\xe8\xe8z" + - "\x00\x00\x00\x00\x00\b|\x8b\xe0\x00\x00\x00\x00\b\xfd\xb0\xd0\x00\x00\x00\x00\t\xf6\xea`\x00\x00\x00\x00\n\xa63\xd0\x00\x00\x00\x00\x13\xe9\xfc`\x00\x00\x00\x00\x14![`\x00\x00\x00\x00\x1a\xfa\xc6`\x00\x00\x00" + - "\x00\x1b\x8en`\x00\x00\x00\x00\x1c\xbe\xf8\xe0\x00\x00\x00\x00\x1dw|\xd0\x00\x00\x00\x00\x1e\xcc\xff`\x00\x00\x00\x00\x1f`\x99P\x00\x00\x00\x00 \x82\xb1`\x00\x00\x00\x00!I\xb5\xd0\x00\x00\x00\x00\"^\x9e" + - "\xe0\x00\x00\x00\x00# ]P\x00\x00\x00\x00$Z0`\x00\x00\x00\x00%\x00?P\x00\x00\x00\x00&\v\xed\xe0\x00\x00\x00\x00&\xd6\xe6\xd0\x00\x00\x00\x00'\xeb\xcf\xe0\x00\x00\x00\x00(\xc0\x03P\x00\x00\x00" + - "\x00)\xd4\xec`\x00\x00\x00\x00*\xa9\x1f\xd0\x00\x00\x00\x00+\xbbe\xe0\x00\x00\x00\x00,\x89\x01\xd0\x00\x00\x00\x00-\x9bG\xe0\x00\x00\x00\x00._\xa9P\x00\x00\x00\x00/{)\xe0\x00\x00\x00\x000H\xc5" + - "\xd0\x00\x00\x00\x001H\x96\xe0\x00\x00\x00\x002\x83\x82" + - "p\x00\x00\x00\x00?|\x9f\xe0\x00\x00\x00\x00@s6p\x00\x00\x00\x00AP\xa4`\x00\x00\x00\x00BL\x8f\x00\x00\x00\x00\x00CHOp\x00\x00\x00\x00D,q\x00\x00\x00\x00\x00E\x1e\xf6\xf0\x00\x00\x00" + - "\x00F\fS\x00\x00\x00\x00\x00F\xecc\xf0\x00\x00\x00\x00G\xec5\x00\x00\x00\x00\x00H\xe7\xf5p\x00\x00\x00\x00I\xcc\x17\x00\x00\x00\x00\x00J\xbe\x9c\xf0\x00\x00\x00\x00K\xab\xf9\x00\x00\x00\x00\x00L\x8c\t" + - "\xf0\x00\x00\x00\x00M\x95\x15\x80\x00\x00\x00\x00N\x87\x9bp\x00\x00\x00\x00Ot\xf7\x80\x00\x00\x00\x00P^B\xf0\x00\x00\x00\x00QTـ\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x00\x00!\x06\x00\x00\x00\x00 \xf8\x00\x04\x00\x00*0\x01\b\x00\x00\x1c \x00\f\x00\x008@\x01\x10LMT\x00JMT\x00I" + - "DT\x00IST\x00IDDT\x00\nIST-2IDT,M3.4.4/26,M10.5.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R's\x96\x1en\x01" + - "\x00\x00n\x01\x00\x00\r\x00\x1c\x00Asia/DushanbeUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x19\x83\x80\xff\xff\xff\xff\xb5\xa3\xef0\x00\x00\x00\x00\x15'}\xa0\x00\x00\x00\x00\x16\x18\xb2\x10\x00\x00" + - "\x00\x00\x17\b\xb1 \x00\x00\x00\x00\x17\xf9\xe5\x90\x00\x00\x00\x00\x18\xe9\xe4\xa0\x00\x00\x00\x00\x19\xdb\x19\x10\x00\x00\x00\x00\x1a\xcci\xa0\x00\x00\x00\x00\x1b\xbcv\xc0\x00\x00\x00\x00\x1c\xacg\xc0\x00\x00\x00\x00\x1d\x9c" + - "X\xc0\x00\x00\x00\x00\x1e\x8cI\xc0\x00\x00\x00\x00\x1f|:\xc0\x00\x00\x00\x00 l+\xc0\x00\x00\x00\x00!\\\x1c\xc0\x00\x00\x00\x00\"L\r\xc0\x00\x00\x00\x00#;\xfe\xc0\x00\x00\x00\x00$+\xef\xc0\x00\x00" + - "\x00\x00%\x1b\xe0\xc0\x00\x00\x00\x00&\v\xd1\xc0\x00\x00\x00\x00'\x04\xfd@\x00\x00\x00\x00'\xf4\xee@\x00\x00\x00\x00(ʏP\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x04\x01\x00\x00@\x80\x00\x00\x00\x00FP\x00\x04\x00\x00bp\x01\b\x00\x00T`\x00\f\x00\x00T`\x01\fLMT\x00+05\x00+07\x00+06\x00\n<+05>-5\nPK\x03" + - "\x04\n\x00\x00\x00\x00\x00\xf1c9R\\\x91\x87\xbb\xf7\x00\x00\x00\xf7\x00\x00\x00\f\x00\x1c\x00Asia/ColomboUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03" + - "\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + - "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\x00\x00\x00\a\x00\x00\x00\x18\xff\xff\xff\xffV\xb6\x99$\xff\xff\xff\xff\x87\x9d\xbd\x1c\xff\xff" + - "\xff\xff\xcbZ\x1c(\xff\xff\xff\xff̕+\xa0\xff\xff\xff\xff\xd2u\x808\x00\x00\x00\x001\xa6\x00(\x00\x00\x00\x002q\x00 \x00\x00\x00\x00D?\xea(\x01\x02\x03\x04\x02\x05\x06\x02\x00\x00J\xdc\x00\x00" + - "\x00\x00J\xe4\x00\x04\x00\x00MX\x00\b\x00\x00T`\x01\x0e\x00\x00[h\x01\x12\x00\x00[h\x00\x12\x00\x00T`\x00\x0eLMT\x00MMT\x00+0530\x00+06\x00+0630\x00" + - "\n<+0530>-5:30\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R9Y\xb7\xf1\n\x01\x00\x00\n\x01\x00\x00\f\x00\x1c\x00Asia/KarachiUT\t\x00" + - "\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\v\x00\x00\x00\x06\x00\x00\x00\x1d\xff" + - "\xff\xff\xff\x89~\xfc\xa4\xff\xff\xff\xff̕2\xa8\xff\xff\xff\xff\xd2t\x12\x98\xff\xff\xff\xffݨ\xe0\xa8\x00\x00\x00\x00\x02O\xab0\x00\x00\x00\x00<\xafE\xb0\x00\x00\x00\x00=\x9f(\xa0\x00\x00\x00\x00H" + - "A\xa00\x00\x00\x00\x00I\vG\xa0\x00\x00\x00\x00I\xe4\xdd0\x00\x00\x00\x00J\xec{ \x01\x02\x01\x03\x05\x04\x05\x04\x05\x04\x05\x00\x00>\xdc\x00\x00\x00\x00MX\x00\x04\x00\x00[h\x01\n\x00\x00FP" + - "\x00\x10\x00\x00T`\x01\x14\x00\x00FP\x00\x19LMT\x00+0530\x00+0630\x00+05\x00PKST\x00PKT\x00\nPKT-5\nPK\x03\x04\n\x00\x00\x00\x00\x00" + - "\xf1c9R恸\x1e\x00\x01\x00\x00\x00\x01\x00\x00\x11\x00\x1c\x00Asia/Kuala_LumpurUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00" + - "\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif" + - "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\x00\x00\x00\b\x00\x00\x00 \xff\xff\xff\xff~6U\xaa\xff\xff\xff\xff\x86\x83\x85\xa3\xff\xff\xff\xff" + - "\xbagN\x90\xff\xff\xff\xff\xc0\n\xe4`\xff\xff\xff\xffʳ\xe5`\xff\xff\xff\xffˑ_\b\xff\xff\xff\xff\xd2Hm\xf0\x00\x00\x00\x00\x16\x91\xf5\b\x01\x02\x03\x04\x05\x06\x05\a\x00\x00_V\x00\x00\x00\x00" + - "a]\x00\x04\x00\x00bp\x00\b\x00\x00g \x01\f\x00\x00g \x00\f\x00\x00ix\x00\x12\x00\x00~\x90\x00\x18\x00\x00p\x80\x00\x1cLMT\x00SMT\x00+07\x00+0720\x00+0" + - "730\x00+09\x00+08\x00\n<+08>-8\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Re\x1bb2w\x01\x00\x00w\x01\x00\x00\r\x00\x1c\x00Asia/Ashg" + - "abatUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x00" + - "\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x19\x8dD\xff\xff\xff\xff\xb5\xa3\xfd@\x00\x00\x00\x00\x15'\x8b\xb0\x00\x00\x00\x00\x16\x18\xc0 \x00\x00\x00\x00\x17\b\xbf0\x00\x00\x00\x00\x17\xf9\xf3\xa0\x00\x00\x00\x00\x18" + - "\xe9\xf2\xb0\x00\x00\x00\x00\x19\xdb' \x00\x00\x00\x00\x1a\xccw\xb0\x00\x00\x00\x00\x1b\xbc\x84\xd0\x00\x00\x00\x00\x1c\xacu\xd0\x00\x00\x00\x00\x1d\x9cf\xd0\x00\x00\x00\x00\x1e\x8cW\xd0\x00\x00\x00\x00\x1f|H\xd0\x00" + - "\x00\x00\x00 l9\xd0\x00\x00\x00\x00!\\*\xd0\x00\x00\x00\x00\"L\x1b\xd0\x00\x00\x00\x00#<\f\xd0\x00\x00\x00\x00$+\xfd\xd0\x00\x00\x00\x00%\x1b\xee\xd0\x00\x00\x00\x00&\v\xdf\xd0\x00\x00\x00\x00'" + - "\x05\vP\x00\x00\x00\x00'\xf4\xfcP\x00\x00\x00\x00(\xe4\xfb`\x00\x00\x00\x00)x\xa3`\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x00\x006\xbc\x00\x00\x00\x00" + - "8@\x00\x04\x00\x00T`\x01\b\x00\x00FP\x00\f\x00\x00FP\x01\fLMT\x00+04\x00+06\x00+05\x00\n<+05>-5\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9" + - "R\x9a\x1a\xdc\xca\xdc\x00\x00\x00\xdc\x00\x00\x00\f\x00\x1c\x00Asia/KolkataUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZi" + + "#<\f\xd0\x00\x00\x00\x00$+\xfd\xd0\x00\x00\x00\x00%\x1b\xee\xd0\x00\x00\x00\x00&\v\xdf\xd0\x00\x00\x00\x00'\x05\vP\x00\x00\x00\x00'\xf4\xfcP\x00\x00\x00\x00(\xe4\xedP\x01\x02\x03\x04\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x00\x00>\xc9\x00\x00\x00\x008@\x00\x04\x00\x00FP\x00\b\x00\x00T`\x01\f\x00\x00T`\x00\fLMT\x00+04\x00+05\x00+0" + + "6\x00\n<+05>-5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSV\xe0\xe7!\xe7\x02\x00\x00\xe7\x02\x00\x00\v\x00\x1c\x00Asia/AnadyrUT\t\x00\x03\x82\x0f\x8b" + + "a\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" + + "\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\a\x00\x00\x00\x14\xff\xff\xff\xff\xaa" + + "\x19\x1d\x9c\xff\xff\xff\xff\xb5\xa3\x8c\xc0\x00\x00\x00\x00\x15'\x1b0\x00\x00\x00\x00\x16\x18O\xa0\x00\x00\x00\x00\x17\bN\xb0\x00\x00\x00\x00\x17\xf9\x910\x00\x00\x00\x00\x18\xe9\x90@\x00\x00\x00\x00\x19\xdaİ\x00" + + "\x00\x00\x00\x1a\xcc\x15@\x00\x00\x00\x00\x1b\xbc\"`\x00\x00\x00\x00\x1c\xac\x13`\x00\x00\x00\x00\x1d\x9c\x04`\x00\x00\x00\x00\x1e\x8b\xf5`\x00\x00\x00\x00\x1f{\xe6`\x00\x00\x00\x00 k\xd7`\x00\x00\x00\x00!" + + "[\xc8`\x00\x00\x00\x00\"K\xb9`\x00\x00\x00\x00#;\xaa`\x00\x00\x00\x00$+\x9b`\x00\x00\x00\x00%\x1b\x8c`\x00\x00\x00\x00&\v}`\x00\x00\x00\x00'\x04\xa8\xe0\x00\x00\x00\x00'\xf4\x99\xe0\x00" + + "\x00\x00\x00(\xe4\x98\xf0\x00\x00\x00\x00)x@\xf0\x00\x00\x00\x00)\xd4{\xe0\x00\x00\x00\x00*\xc4l\xe0\x00\x00\x00\x00+\xb4]\xe0\x00\x00\x00\x00,\xa4N\xe0\x00\x00\x00\x00-\x94?\xe0\x00\x00\x00\x00." + + "\x840\xe0\x00\x00\x00\x00/t!\xe0\x00\x00\x00\x000d\x12\xe0\x00\x00\x00\x001]>`\x00\x00\x00\x002r\x19`\x00\x00\x00\x003= `\x00\x00\x00\x004Q\xfb`\x00\x00\x00\x005\x1d\x02`\x00" + + "\x00\x00\x0061\xdd`\x00\x00\x00\x006\xfc\xe4`\x00\x00\x00\x008\x1a\xf9\xe0\x00\x00\x00\x008\xdc\xc6`\x00\x00\x00\x009\xfa\xdb\xe0\x00\x00\x00\x00:\xbc\xa8`\x00\x00\x00\x00;ڽ\xe0\x00\x00\x00\x00<" + + "\xa5\xc4\xe0\x00\x00\x00\x00=\xba\x9f\xe0\x00\x00\x00\x00>\x85\xa6\xe0\x00\x00\x00\x00?\x9a\x81\xe0\x00\x00\x00\x00@e\x88\xe0\x00\x00\x00\x00A\x83\x9e`\x00\x00\x00\x00BEj\xe0\x00\x00\x00\x00Cc\x80`\x00" + + "\x00\x00\x00D%L\xe0\x00\x00\x00\x00ECb`\x00\x00\x00\x00F\x05.\xe0\x00\x00\x00\x00G#D`\x00\x00\x00\x00G\xeeK`\x00\x00\x00\x00I\x03&`\x00\x00\x00\x00I\xce-`\x00\x00\x00\x00J" + + "\xe3\b`\x00\x00\x00\x00K\xae\x0f`\x00\x00\x00\x00L\xcc2\xf0\x00\x00\x00\x00M\x8d\xffp\x01\x03\x02\x03\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x05\x06\x01\x04\x01\x04\x01\x04\x01\x04\x01" + + "\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x05\x06\x01\x00\x00\xa6d\x00\x00\x00\x00\xa8\xc0\x00\x04\x00\x00\xc4\xe0\x01\b\x00\x00\xb6\xd0\x00\f\x00\x00\xb6\xd0\x01" + + "\f\x00\x00\xa8\xc0\x01\x04\x00\x00\x9a\xb0\x00\x10LMT\x00+12\x00+14\x00+13\x00+11\x00\n<+12>-12\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSd%\x05" + + "\xd8\xe6\x02\x00\x00\xe6\x02\x00\x00\x10\x00\x1c\x00Asia/VladivostokUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZi" + "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x05\x00\x00\x00\x16\xff\xff\xff\xff&\xba\x18(\xff\xff\xff\xffC\xe7\xeb0\xff\xff\xff\xff\x87\x9d\xbc\xba\xff\xff\xff\xff" + - "\xcaی(\xff\xff\xff\xff\xcc\x05q\x18\xff\xff\xff\xff̕2\xa8\xff\xff\xff\xff\xd2t\x12\x98\x01\x02\x03\x04\x03\x04\x03\x00\x00R\xd8\x00\x00\x00\x00R\xd0\x00\x04\x00\x00KF\x00\b\x00\x00MX\x00\f\x00" + - "\x00[h\x01\x10LMT\x00HMT\x00MMT\x00IST\x00+0630\x00\nIST-5:30\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RB\x1d\xc6\x1b\x85\x00\x00\x00\x85" + - "\x00\x00\x00\f\x00\x1c\x00Asia/KashgarUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\xb0\xfe\xbad\x01\x00\x00R\x1c\x00\x00\x00\x00T`\x00\x04LMT\x00+06\x00\n<+06>-6\n" + - "PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xba\xa3b\xc1R\x02\x00\x00R\x02\x00\x00\t\x00\x1c\x00Asia/HovdUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03" + - "\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + - "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x002\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff\x86\xd3\xfc\x94\x00\x00\x00\x00\x0f\v\xea\xa0\x00\x00" + - "\x00\x00\x18\xe9\u0590\x00\x00\x00\x00\x19\xdb\v\x00\x00\x00\x00\x00\x1a\xcc[\x90\x00\x00\x00\x00\x1b\xbc>\x80\x00\x00\x00\x00\x1c\xac=\x90\x00\x00\x00\x00\x1d\x9c \x80\x00\x00\x00\x00\x1e\x8c\x1f\x90\x00\x00\x00\x00\x1f|" + - "\x02\x80\x00\x00\x00\x00 l\x01\x90\x00\x00\x00\x00![\xe4\x80\x00\x00\x00\x00\"K\xe3\x90\x00\x00\x00\x00#;ƀ\x00\x00\x00\x00$+Ő\x00\x00\x00\x00%\x1b\xa8\x80\x00\x00\x00\x00&\v\xa7\x90\x00\x00" + - "\x00\x00'\x04\xc5\x00\x00\x00\x00\x00'\xf4\xc4\x10\x00\x00\x00\x00(\xe4\xa7\x00\x00\x00\x00\x00)Ԧ\x10\x00\x00\x00\x00*ĉ\x00\x00\x00\x00\x00+\xb4\x88\x10\x00\x00\x00\x00,\xa4k\x00\x00\x00\x00\x00-\x94" + - "j\x10\x00\x00\x00\x00.\x84M\x00\x00\x00\x00\x00/tL\x10\x00\x00\x00\x000d/\x00\x00\x00\x00\x001]h\x90\x00\x00\x00\x002MK\x80\x00\x00\x00\x003=J\x90\x00\x00\x00\x004--\x80\x00\x00" + - "\x00\x005\x1d,\x90\x00\x00\x00\x006\r\x0f\x80\x00\x00\x00\x00:\xe9\xc1\xb0\x00\x00\x00\x00;\xb4\xba\xa0\x00\x00\x00\x00<\xa4\xb9\xb0\x00\x00\x00\x00=\x94\x9c\xa0\x00\x00\x00\x00>\x84\x9b\xb0\x00\x00\x00\x00?t" + - "~\xa0\x00\x00\x00\x00@d}\xb0\x00\x00\x00\x00AT`\xa0\x00\x00\x00\x00BD_\xb0\x00\x00\x00\x00C4B\xa0\x00\x00\x00\x00D$A\xb0\x00\x00\x00\x00E\x1d_ \x00\x00\x00\x00U\x15\xa8\xb0\x00\x00" + - "\x00\x00V\x05o\x80\x00\x00\x00\x00V\xf5\x8a\xb0\x00\x00\x00\x00W\xe5Q\x80\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x00\x00U\xec\x00\x00\x00\x00T`\x00\x04\x00\x00p\x80\x01\b\x00\x00bp\x00\fLMT\x00+06\x00+08\x00+07\x00\n<+07>-7" + - "\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x03\x87\xb3<\xe8\x02\x00\x00\xe8\x02\x00\x00\t\x00\x1c\x00Asia/BakuUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8" + - "\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00T" + - "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00B\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x19\x95D\xff\xff\xff\xff\xe7\xda\fP\x00" + - "\x00\x00\x00\x15'\x99\xc0\x00\x00\x00\x00\x16\x18\xce0\x00\x00\x00\x00\x17\b\xcd@\x00\x00\x00\x00\x17\xfa\x01\xb0\x00\x00\x00\x00\x18\xea\x00\xc0\x00\x00\x00\x00\x19\xdb50\x00\x00\x00\x00\x1a̅\xc0\x00\x00\x00\x00\x1b" + - "\xbc\x92\xe0\x00\x00\x00\x00\x1c\xac\x83\xe0\x00\x00\x00\x00\x1d\x9ct\xe0\x00\x00\x00\x00\x1e\x8ce\xe0\x00\x00\x00\x00\x1f|V\xe0\x00\x00\x00\x00 lG\xe0\x00\x00\x00\x00!\\8\xe0\x00\x00\x00\x00\"L)\xe0\x00" + - "\x00\x00\x00#<\x1a\xe0\x00\x00\x00\x00$,\v\xe0\x00\x00\x00\x00%\x1b\xfc\xe0\x00\x00\x00\x00&\v\xed\xe0\x00\x00\x00\x00'\x05\x19`\x00\x00\x00\x00'\xf5\n`\x00\x00\x00\x00(\xe5\tp\x00\x00\x00\x00)" + - "\xd4\xfap\x00\x00\x00\x00*\xc4\xebp\x00\x00\x00\x001]\xd9\x10\x00\x00\x00\x002r\xb4\x10\x00\x00\x00\x003=\xad\x00\x00\x00\x00\x004R\x88\x00\x00\x00\x00\x005\x1d\x8f\x00\x00\x00\x00\x0062j\x00\x00" + - "\x00\x00\x006\xfdq\x00\x00\x00\x00\x008\x1b\x86\x80\x00\x00\x00\x008\xddS\x00\x00\x00\x00\x009\xfbh\x80\x00\x00\x00\x00:\xbd5\x00\x00\x00\x00\x00;\xdbJ\x80\x00\x00\x00\x00<\xa6Q\x80\x00\x00\x00\x00=" + - "\xbb,\x80\x00\x00\x00\x00>\x863\x80\x00\x00\x00\x00?\x9b\x0e\x80\x00\x00\x00\x00@f\x15\x80\x00\x00\x00\x00A\x84+\x00\x00\x00\x00\x00BE\xf7\x80\x00\x00\x00\x00Cd\r\x00\x00\x00\x00\x00D%ـ\x00" + - "\x00\x00\x00EC\xef\x00\x00\x00\x00\x00F\x05\xbb\x80\x00\x00\x00\x00G#\xd1\x00\x00\x00\x00\x00G\xee\xd8\x00\x00\x00\x00\x00I\x03\xb3\x00\x00\x00\x00\x00Iκ\x00\x00\x00\x00\x00J\xe3\x95\x00\x00\x00\x00\x00K" + - "\xae\x9c\x00\x00\x00\x00\x00Ḻ\x80\x00\x00\x00\x00M\x8e~\x00\x00\x00\x00\x00N\xac\x93\x80\x00\x00\x00\x00On`\x00\x00\x00\x00\x00P\x8cu\x80\x00\x00\x00\x00QW|\x80\x00\x00\x00\x00RlW\x80\x00" + - "\x00\x00\x00S7^\x80\x00\x00\x00\x00TL9\x80\x00\x00\x00\x00U\x17@\x80\x00\x00\x00\x00V,\x1b\x80\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x04\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x00\x00.\xbc\x00\x00\x00\x00*0\x00\x04\x00\x00FP\x01\b\x00\x008@\x00" + - "\f\x00\x008@\x01\fLMT\x00+03\x00+05\x00+04\x00\n<+04>-4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x83g\x95M\a\x03\x00\x00\a\x03\x00\x00\r\x00" + - "\x1c\x00Asia/KhandygaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00A\x00\x00\x00\x06\x00\x00\x00\x10\xff\xff\xff\xff\xa7YG]\xff\xff\xff\xff\xb5\xa3\xb6\xf0\x00\x00\x00\x00\x15'E`\x00\x00\x00\x00" + + "\x16\x18y\xd0\x00\x00\x00\x00\x17\bx\xe0\x00\x00\x00\x00\x17\xf9\xadP\x00\x00\x00\x00\x18\xe9\xac`\x00\x00\x00\x00\x19\xda\xe0\xd0\x00\x00\x00\x00\x1a\xcc1`\x00\x00\x00\x00\x1b\xbc>\x80\x00\x00\x00\x00\x1c\xac/\x80" + + "\x00\x00\x00\x00\x1d\x9c \x80\x00\x00\x00\x00\x1e\x8c\x11\x80\x00\x00\x00\x00\x1f|\x02\x80\x00\x00\x00\x00 k\xf3\x80\x00\x00\x00\x00![\xe4\x80\x00\x00\x00\x00\"KՀ\x00\x00\x00\x00#;ƀ\x00\x00\x00\x00" + + "$+\xb7\x80\x00\x00\x00\x00%\x1b\xa8\x80\x00\x00\x00\x00&\v\x99\x80\x00\x00\x00\x00'\x04\xc5\x00\x00\x00\x00\x00'\xf4\xb6\x00\x00\x00\x00\x00(\xe4\xb5\x10\x00\x00\x00\x00)x]\x10\x00\x00\x00\x00)Ԙ\x00" + + "\x00\x00\x00\x00*ĉ\x00\x00\x00\x00\x00+\xb4z\x00\x00\x00\x00\x00,\xa4k\x00\x00\x00\x00\x00-\x94\\\x00\x00\x00\x00\x00.\x84M\x00\x00\x00\x00\x00/t>\x00\x00\x00\x00\x000d/\x00\x00\x00\x00\x00" + + "1]Z\x80\x00\x00\x00\x002r5\x80\x00\x00\x00\x003=<\x80\x00\x00\x00\x004R\x17\x80\x00\x00\x00\x005\x1d\x1e\x80\x00\x00\x00\x0061\xf9\x80\x00\x00\x00\x006\xfd\x00\x80\x00\x00\x00\x008\x1b\x16\x00" + + "\x00\x00\x00\x008\xdc\xe2\x80\x00\x00\x00\x009\xfa\xf8\x00\x00\x00\x00\x00:\xbcĀ\x00\x00\x00\x00;\xda\xda\x00\x00\x00\x00\x00<\xa5\xe1\x00\x00\x00\x00\x00=\xba\xbc\x00\x00\x00\x00\x00>\x85\xc3\x00\x00\x00\x00\x00" + + "?\x9a\x9e\x00\x00\x00\x00\x00@e\xa5\x00\x00\x00\x00\x00A\x83\xba\x80\x00\x00\x00\x00BE\x87\x00\x00\x00\x00\x00Cc\x9c\x80\x00\x00\x00\x00D%i\x00\x00\x00\x00\x00EC~\x80\x00\x00\x00\x00F\x05K\x00" + + "\x00\x00\x00\x00G#`\x80\x00\x00\x00\x00G\xeeg\x80\x00\x00\x00\x00I\x03B\x80\x00\x00\x00\x00I\xceI\x80\x00\x00\x00\x00J\xe3$\x80\x00\x00\x00\x00K\xae+\x80\x00\x00\x00\x00L\xccA\x00\x00\x00\x00\x00" + + "M\x8e\r\x80\x00\x00\x00\x00TK\xba\xf0\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x05\x03\x00\x00{\xa3\x00\x00\x00\x00~\x90\x00\x04\x00\x00\x9a\xb0\x01\b\x00\x00\x8c\xa0\x00\f\x00\x00\x8c\xa0\x01\f\x00\x00\x9a\xb0\x00\bLMT\x00+09" + + "\x00+11\x00+10\x00\n<+10>-10\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSj$\xcd\xf4\x9a\x00\x00\x00\x9a\x00\x00\x00\v\x00\x1c\x00Asia/Thimbu" + + "UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00" + + "\x00\x00\x0e\xff\xff\xff\xff\xd5\xe6\x15t\x00\x00\x00\x00!aM\xa8\x01\x02\x00\x00T\f\x00\x00\x00\x00MX\x00\x04\x00\x00T`\x00\nLMT\x00+0530\x00+06\x00\n<+06>-" + + "6\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS恸\x1e\x00\x01\x00\x00\x00\x01\x00\x00\x11\x00\x1c\x00Asia/Kuala_LumpurUT\t\x00\x03\x82\x0f\x8ba\x82\x0f" + + "\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" + + "\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\x00\x00\x00\b\x00\x00\x00 \xff\xff\xff\xff~6U\xaa" + + "\xff\xff\xff\xff\x86\x83\x85\xa3\xff\xff\xff\xff\xbagN\x90\xff\xff\xff\xff\xc0\n\xe4`\xff\xff\xff\xffʳ\xe5`\xff\xff\xff\xffˑ_\b\xff\xff\xff\xff\xd2Hm\xf0\x00\x00\x00\x00\x16\x91\xf5\b\x01\x02\x03\x04" + + "\x05\x06\x05\a\x00\x00_V\x00\x00\x00\x00a]\x00\x04\x00\x00bp\x00\b\x00\x00g \x01\f\x00\x00g \x00\f\x00\x00ix\x00\x12\x00\x00~\x90\x00\x18\x00\x00p\x80\x00\x1cLMT\x00SMT\x00" + + "+07\x00+0720\x00+0730\x00+09\x00+08\x00\n<+08>-8\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x06\xaa>\xa8\x00\x01\x00\x00\x00\x01\x00\x00\x0e" + + "\x00\x1c\x00Asia/SingaporeUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\x00\x00\x00\b\x00\x00\x00 \xff\xff\xff\xff~6S\xa3\xff\xff\xff\xff\x86\x83\x85\xa3\xff\xff\xff\xff\xbagN\x90\xff\xff\xff\xff\xc0\n\xe4`\xff\xff\xff\xffʳ\xe5`" + + "\xff\xff\xff\xffˑ_\b\xff\xff\xff\xff\xd2Hm\xf0\x00\x00\x00\x00\x16\x91\xf5\b\x01\x02\x03\x04\x05\x06\x05\a\x00\x00a]\x00\x00\x00\x00a]\x00\x04\x00\x00bp\x00\b\x00\x00g \x01\f\x00\x00g " + + "\x00\f\x00\x00ix\x00\x12\x00\x00~\x90\x00\x18\x00\x00p\x80\x00\x1cLMT\x00SMT\x00+07\x00+0720\x00+0730\x00+09\x00+08\x00\n<+08>-8" + + "\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS[u\x99q\xf1\x02\x00\x00\xf1\x02\x00\x00\n\x00\x1c\x00Asia/TomskUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04" + + "\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" + + "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00C\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xa1\xe5N\xd9\xff\xff\xff\xff\xb5\xa3\xe1 " + + "\x00\x00\x00\x00\x15'o\x90\x00\x00\x00\x00\x16\x18\xa4\x00\x00\x00\x00\x00\x17\b\xa3\x10\x00\x00\x00\x00\x17\xf9׀\x00\x00\x00\x00\x18\xe9\u0590\x00\x00\x00\x00\x19\xdb\v\x00\x00\x00\x00\x00\x1a\xcc[\x90\x00\x00\x00\x00" + + "\x1b\xbch\xb0\x00\x00\x00\x00\x1c\xacY\xb0\x00\x00\x00\x00\x1d\x9cJ\xb0\x00\x00\x00\x00\x1e\x8c;\xb0\x00\x00\x00\x00\x1f|,\xb0\x00\x00\x00\x00 l\x1d\xb0\x00\x00\x00\x00!\\\x0e\xb0\x00\x00\x00\x00\"K\xff\xb0" + + "\x00\x00\x00\x00#;\xf0\xb0\x00\x00\x00\x00$+\xe1\xb0\x00\x00\x00\x00%\x1bҰ\x00\x00\x00\x00&\vð\x00\x00\x00\x00'\x04\xef0\x00\x00\x00\x00'\xf4\xe00\x00\x00\x00\x00(\xe4\xdf@\x00\x00\x00\x00" + + ")x\x87@\x00\x00\x00\x00)\xd4\xc20\x00\x00\x00\x00*ij0\x00\x00\x00\x00+\xb4\xa40\x00\x00\x00\x00,\xa4\x950\x00\x00\x00\x00-\x94\x860\x00\x00\x00\x00.\x84w0\x00\x00\x00\x00/th0" + + "\x00\x00\x00\x000dY0\x00\x00\x00\x001]\x84\xb0\x00\x00\x00\x002r_\xb0\x00\x00\x00\x003=f\xb0\x00\x00\x00\x004RA\xb0\x00\x00\x00\x005\x1dH\xb0\x00\x00\x00\x0062#\xb0\x00\x00\x00\x00" + + "6\xfd*\xb0\x00\x00\x00\x008\x1b@0\x00\x00\x00\x008\xdd\f\xb0\x00\x00\x00\x009\xfb\"0\x00\x00\x00\x00:\xbc\xee\xb0\x00\x00\x00\x00;\xdb\x040\x00\x00\x00\x00<\xa6\v0\x00\x00\x00\x00<\xce\xe9\xb0" + + "\x00\x00\x00\x00=\xba\xf4@\x00\x00\x00\x00>\x85\xfb@\x00\x00\x00\x00?\x9a\xd6@\x00\x00\x00\x00@e\xdd@\x00\x00\x00\x00A\x83\xf2\xc0\x00\x00\x00\x00BE\xbf@\x00\x00\x00\x00Cc\xd4\xc0\x00\x00\x00\x00" + + "D%\xa1@\x00\x00\x00\x00EC\xb6\xc0\x00\x00\x00\x00F\x05\x83@\x00\x00\x00\x00G#\x98\xc0\x00\x00\x00\x00G\xee\x9f\xc0\x00\x00\x00\x00I\x03z\xc0\x00\x00\x00\x00I\u0381\xc0\x00\x00\x00\x00J\xe3\\\xc0" + + "\x00\x00\x00\x00K\xaec\xc0\x00\x00\x00\x00L\xccy@\x00\x00\x00\x00M\x8eE\xc0\x00\x00\x00\x00TK\xf30\x00\x00\x00\x00WI\xf8\xc0\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x04\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x03\x01\x03\x00\x00O\xa7\x00\x00\x00\x00T`\x00\x04\x00" + + "\x00p\x80\x01\b\x00\x00bp\x00\f\x00\x00bp\x01\fLMT\x00+06\x00+08\x00+07\x00\n<+07>-7\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSe\x1bb2" + + "w\x01\x00\x00w\x01\x00\x00\r\x00\x1c\x00Asia/AshgabatUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x19\x8dD\xff\xff\xff\xff\xb5\xa3\xfd@\x00\x00\x00\x00\x15'\x8b\xb0\x00\x00\x00\x00\x16\x18\xc0 " + + "\x00\x00\x00\x00\x17\b\xbf0\x00\x00\x00\x00\x17\xf9\xf3\xa0\x00\x00\x00\x00\x18\xe9\xf2\xb0\x00\x00\x00\x00\x19\xdb' \x00\x00\x00\x00\x1a\xccw\xb0\x00\x00\x00\x00\x1b\xbc\x84\xd0\x00\x00\x00\x00\x1c\xacu\xd0\x00\x00\x00\x00" + + "\x1d\x9cf\xd0\x00\x00\x00\x00\x1e\x8cW\xd0\x00\x00\x00\x00\x1f|H\xd0\x00\x00\x00\x00 l9\xd0\x00\x00\x00\x00!\\*\xd0\x00\x00\x00\x00\"L\x1b\xd0\x00\x00\x00\x00#<\f\xd0\x00\x00\x00\x00$+\xfd\xd0" + + "\x00\x00\x00\x00%\x1b\xee\xd0\x00\x00\x00\x00&\v\xdf\xd0\x00\x00\x00\x00'\x05\vP\x00\x00\x00\x00'\xf4\xfcP\x00\x00\x00\x00(\xe4\xfb`\x00\x00\x00\x00)x\xa3`\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x00\x006\xbc\x00\x00\x00\x008@\x00\x04\x00\x00T`\x01\b\x00\x00FP\x00\f\x00\x00FP\x01\fLMT\x00+04\x00+06\x00+05\x00\n" + + "<+05>-5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSʇ{_\xbb\x00\x00\x00\xbb\x00\x00\x00\v\x00\x1c\x00Asia/YangonUT\t\x00\x03\x82\x0f\x8ba\x82\x0f" + + "\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" + + "\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xffV\xb6\x89\xd1" + + "\xff\xff\xff\xff\xa1\xf2sQ\xff\xff\xff\xff\xcb\xf2\xfc\x18\xff\xff\xff\xffњg\xf0\x01\x02\x03\x02\x00\x00Z/\x00\x00\x00\x00Z/\x00\x04\x00\x00[h\x00\b\x00\x00~\x90\x00\x0eLMT\x00RMT\x00" + + "+0630\x00+09\x00\n<+0630>-6:30\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x8a\xc1\x1eB\xb7\x00\x00\x00\xb7\x00\x00\x00\x0e\x00\x1c\x00Asia/P" + + "yongyangUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\f\xff\xff\xff\xff\x8b\xd7\xf1\x9c\xff\xff\xff\xff\x92\xe6\x16\xf8\xff\xff\xff\xff\xd2/ap\x00\x00\x00\x00U\xce\x02p\x00\x00\x00\x00Z\xecup\x01\x02\x03\x01\x03\x00\x00u\xe4" + + "\x00\x00\x00\x00w\x88\x00\x04\x00\x00~\x90\x00\b\x00\x00~\x90\x00\x04LMT\x00KST\x00JST\x00\nKST-9\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x9a\xea\x18\xd4\xf8\x02\x00" + + "\x00\xf8\x02\x00\x00\x12\x00\x1c\x00Asia/YekaterinburgUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00B\x00\x00\x00\a\x00\x00\x00\x14\xff\xff\xff\xff\x9b_\t'\xff\xff\xff\xff\xa1\x12\xb1\xff\xff\xff\xff\xff\xb5\xa3\xfd@\x00\x00\x00\x00\x15'" + + "\x8b\xb0\x00\x00\x00\x00\x16\x18\xc0 \x00\x00\x00\x00\x17\b\xbf0\x00\x00\x00\x00\x17\xf9\xf3\xa0\x00\x00\x00\x00\x18\xe9\xf2\xb0\x00\x00\x00\x00\x19\xdb' \x00\x00\x00\x00\x1a\xccw\xb0\x00\x00\x00\x00\x1b\xbc\x84\xd0\x00\x00" + + "\x00\x00\x1c\xacu\xd0\x00\x00\x00\x00\x1d\x9cf\xd0\x00\x00\x00\x00\x1e\x8cW\xd0\x00\x00\x00\x00\x1f|H\xd0\x00\x00\x00\x00 l9\xd0\x00\x00\x00\x00!\\*\xd0\x00\x00\x00\x00\"L\x1b\xd0\x00\x00\x00\x00#<" + + "\f\xd0\x00\x00\x00\x00$+\xfd\xd0\x00\x00\x00\x00%\x1b\xee\xd0\x00\x00\x00\x00&\v\xdf\xd0\x00\x00\x00\x00'\x05\vP\x00\x00\x00\x00'\xf4\xfcP\x00\x00\x00\x00(\xe4\xfb`\x00\x00\x00\x00)x\xa3`\x00\x00" + + "\x00\x00)\xd4\xdeP\x00\x00\x00\x00*\xc4\xcfP\x00\x00\x00\x00+\xb4\xc0P\x00\x00\x00\x00,\xa4\xb1P\x00\x00\x00\x00-\x94\xa2P\x00\x00\x00\x00.\x84\x93P\x00\x00\x00\x00/t\x84P\x00\x00\x00\x000d" + + "uP\x00\x00\x00\x001]\xa0\xd0\x00\x00\x00\x002r{\xd0\x00\x00\x00\x003=\x82\xd0\x00\x00\x00\x004R]\xd0\x00\x00\x00\x005\x1dd\xd0\x00\x00\x00\x0062?\xd0\x00\x00\x00\x006\xfdF\xd0\x00\x00" + + "\x00\x008\x1b\\P\x00\x00\x00\x008\xdd(\xd0\x00\x00\x00\x009\xfb>P\x00\x00\x00\x00:\xbd\n\xd0\x00\x00\x00\x00;\xdb P\x00\x00\x00\x00<\xa6'P\x00\x00\x00\x00=\xbb\x02P\x00\x00\x00\x00>\x86" + + "\tP\x00\x00\x00\x00?\x9a\xe4P\x00\x00\x00\x00@e\xebP\x00\x00\x00\x00A\x84\x00\xd0\x00\x00\x00\x00BE\xcdP\x00\x00\x00\x00Cc\xe2\xd0\x00\x00\x00\x00D%\xafP\x00\x00\x00\x00EC\xc4\xd0\x00\x00" + + "\x00\x00F\x05\x91P\x00\x00\x00\x00G#\xa6\xd0\x00\x00\x00\x00G\xee\xad\xd0\x00\x00\x00\x00I\x03\x88\xd0\x00\x00\x00\x00IΏ\xd0\x00\x00\x00\x00J\xe3j\xd0\x00\x00\x00\x00K\xaeq\xd0\x00\x00\x00\x00L\xcc" + + "\x87P\x00\x00\x00\x00M\x8eS\xd0\x00\x00\x00\x00TL\x01@\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x05\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04" + + "\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x06\x04\x00\x008\xd9\x00\x00\x00\x004\xc1\x00\x04\x00\x008@\x00\b\x00\x00T`\x01\f\x00\x00FP\x00\x10\x00\x00FP\x01\x10" + + "\x00\x00T`\x00\fLMT\x00PMT\x00+04\x00+06\x00+05\x00\n<+05>-5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x02\xf4\xaeg\xd5\x00\x00\x00\xd5\x00\x00" + + "\x00\n\x00\x1c\x00Asia/TokyoUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00C\x00\x00\x00\b\x00\x00\x00\x14\xff\xff\xff\xff\xa1\xdb\xe4\xeb\xff\xff\xff\xff\xb5\xa3\xc5\x00\x00\x00\x00\x00\x15'Sp\x00\x00\x00\x00\x16\x18\x87\xe0\x00\x00\x00\x00\x17\b\x86\xf0\x00\x00" + - "\x00\x00\x17\xf9\xbb`\x00\x00\x00\x00\x18\xe9\xbap\x00\x00\x00\x00\x19\xda\xee\xe0\x00\x00\x00\x00\x1a\xcc?p\x00\x00\x00\x00\x1b\xbcL\x90\x00\x00\x00\x00\x1c\xac=\x90\x00\x00\x00\x00\x1d\x9c.\x90\x00\x00\x00\x00\x1e\x8c" + - "\x1f\x90\x00\x00\x00\x00\x1f|\x10\x90\x00\x00\x00\x00 l\x01\x90\x00\x00\x00\x00![\xf2\x90\x00\x00\x00\x00\"K\xe3\x90\x00\x00\x00\x00#;Ԑ\x00\x00\x00\x00$+Ő\x00\x00\x00\x00%\x1b\xb6\x90\x00\x00" + - "\x00\x00&\v\xa7\x90\x00\x00\x00\x00'\x04\xd3\x10\x00\x00\x00\x00'\xf4\xc4\x10\x00\x00\x00\x00(\xe4\xc3 \x00\x00\x00\x00)xk \x00\x00\x00\x00)Ԧ\x10\x00\x00\x00\x00*ė\x10\x00\x00\x00\x00+\xb4" + - "\x88\x10\x00\x00\x00\x00,\xa4y\x10\x00\x00\x00\x00-\x94j\x10\x00\x00\x00\x00.\x84[\x10\x00\x00\x00\x00/tL\x10\x00\x00\x00\x000d=\x10\x00\x00\x00\x001]h\x90\x00\x00\x00\x002rC\x90\x00\x00" + - "\x00\x003=J\x90\x00\x00\x00\x004R%\x90\x00\x00\x00\x005\x1d,\x90\x00\x00\x00\x0062\a\x90\x00\x00\x00\x006\xfd\x0e\x90\x00\x00\x00\x008\x1b$\x10\x00\x00\x00\x008\xdc\xf0\x90\x00\x00\x00\x009\xfb" + - "\x06\x10\x00\x00\x00\x00:\xbcҐ\x00\x00\x00\x00;\xda\xe8\x10\x00\x00\x00\x00<\xa5\xef\x10\x00\x00\x00\x00=\xba\xca\x10\x00\x00\x00\x00>\x85\xd1\x10\x00\x00\x00\x00?\x9a\xac\x10\x00\x00\x00\x00?\xf2\xe4p\x00\x00" + - "\x00\x00@e\xa5\x00\x00\x00\x00\x00A\x83\xba\x80\x00\x00\x00\x00BE\x87\x00\x00\x00\x00\x00Cc\x9c\x80\x00\x00\x00\x00D%i\x00\x00\x00\x00\x00EC~\x80\x00\x00\x00\x00F\x05K\x00\x00\x00\x00\x00G#" + - "`\x80\x00\x00\x00\x00G\xeeg\x80\x00\x00\x00\x00I\x03B\x80\x00\x00\x00\x00I\xceI\x80\x00\x00\x00\x00J\xe3$\x80\x00\x00\x00\x00K\xae+\x80\x00\x00\x00\x00L\xccA\x00\x00\x00\x00\x00M\x8e\r\x80\x00\x00" + - "\x00\x00Nn\x02P\x00\x00\x00\x00TK\xc9\x00\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\a\x06\x03\x00\x00\u007f\x15\x00\x00\x00\x00p\x80\x00\x04\x00\x00\x8c\xa0\x01\b\x00\x00~\x90\x00\f\x00\x00~\x90\x01\f\x00\x00\x9a\xb0\x01\x10\x00\x00\x8c" + - "\xa0\x00\b\x00\x00\x9a\xb0\x00\x10LMT\x00+08\x00+10\x00+09\x00+11\x00\n<+09>-9\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x9a\xea\x18\xd4\xf8\x02\x00\x00" + - "\xf8\x02\x00\x00\x12\x00\x1c\x00Asia/YekaterinburgUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00B\x00\x00\x00\a\x00\x00\x00\x14\xff\xff\xff\xff\x9b_\t'\xff\xff\xff\xff\xa1\x12\xb1\xff\xff\xff\xff\xff\xb5\xa3\xfd@\x00\x00\x00\x00\x15'\x8b" + - "\xb0\x00\x00\x00\x00\x16\x18\xc0 \x00\x00\x00\x00\x17\b\xbf0\x00\x00\x00\x00\x17\xf9\xf3\xa0\x00\x00\x00\x00\x18\xe9\xf2\xb0\x00\x00\x00\x00\x19\xdb' \x00\x00\x00\x00\x1a\xccw\xb0\x00\x00\x00\x00\x1b\xbc\x84\xd0\x00\x00\x00" + - "\x00\x1c\xacu\xd0\x00\x00\x00\x00\x1d\x9cf\xd0\x00\x00\x00\x00\x1e\x8cW\xd0\x00\x00\x00\x00\x1f|H\xd0\x00\x00\x00\x00 l9\xd0\x00\x00\x00\x00!\\*\xd0\x00\x00\x00\x00\"L\x1b\xd0\x00\x00\x00\x00#<\f" + - "\xd0\x00\x00\x00\x00$+\xfd\xd0\x00\x00\x00\x00%\x1b\xee\xd0\x00\x00\x00\x00&\v\xdf\xd0\x00\x00\x00\x00'\x05\vP\x00\x00\x00\x00'\xf4\xfcP\x00\x00\x00\x00(\xe4\xfb`\x00\x00\x00\x00)x\xa3`\x00\x00\x00" + - "\x00)\xd4\xdeP\x00\x00\x00\x00*\xc4\xcfP\x00\x00\x00\x00+\xb4\xc0P\x00\x00\x00\x00,\xa4\xb1P\x00\x00\x00\x00-\x94\xa2P\x00\x00\x00\x00.\x84\x93P\x00\x00\x00\x00/t\x84P\x00\x00\x00\x000du" + - "P\x00\x00\x00\x001]\xa0\xd0\x00\x00\x00\x002r{\xd0\x00\x00\x00\x003=\x82\xd0\x00\x00\x00\x004R]\xd0\x00\x00\x00\x005\x1dd\xd0\x00\x00\x00\x0062?\xd0\x00\x00\x00\x006\xfdF\xd0\x00\x00\x00" + - "\x008\x1b\\P\x00\x00\x00\x008\xdd(\xd0\x00\x00\x00\x009\xfb>P\x00\x00\x00\x00:\xbd\n\xd0\x00\x00\x00\x00;\xdb P\x00\x00\x00\x00<\xa6'P\x00\x00\x00\x00=\xbb\x02P\x00\x00\x00\x00>\x86\t" + - "P\x00\x00\x00\x00?\x9a\xe4P\x00\x00\x00\x00@e\xebP\x00\x00\x00\x00A\x84\x00\xd0\x00\x00\x00\x00BE\xcdP\x00\x00\x00\x00Cc\xe2\xd0\x00\x00\x00\x00D%\xafP\x00\x00\x00\x00EC\xc4\xd0\x00\x00\x00" + - "\x00F\x05\x91P\x00\x00\x00\x00G#\xa6\xd0\x00\x00\x00\x00G\xee\xad\xd0\x00\x00\x00\x00I\x03\x88\xd0\x00\x00\x00\x00IΏ\xd0\x00\x00\x00\x00J\xe3j\xd0\x00\x00\x00\x00K\xaeq\xd0\x00\x00\x00\x00L̇" + - "P\x00\x00\x00\x00M\x8eS\xd0\x00\x00\x00\x00TL\x01@\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x05\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03" + - "\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x06\x04\x00\x008\xd9\x00\x00\x00\x004\xc1\x00\x04\x00\x008@\x00\b\x00\x00T`\x01\f\x00\x00FP\x00\x10\x00\x00FP\x01\x10\x00" + - "\x00T`\x00\fLMT\x00PMT\x00+04\x00+06\x00+05\x00\n<+05>-5\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rʇ{_\xbb\x00\x00\x00\xbb\x00\x00\x00" + - "\f\x00\x1c\x00Asia/RangoonUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xffV\xb6\x89\xd1\xff\xff\xff\xff\xa1\xf2sQ\xff\xff\xff\xff\xcb\xf2\xfc\x18\xff\xff\xff\xffњg\xf0\x01\x02\x03\x02\x00\x00Z/\x00" + - "\x00\x00\x00Z/\x00\x04\x00\x00[h\x00\b\x00\x00~\x90\x00\x0eLMT\x00RMT\x00+0630\x00+09\x00\n<+0630>-6:30\nPK\x03\x04\n\x00\x00\x00\x00" + - "\x00\xf1c9Rǯ\xdf\x1c\xee\x00\x00\x00\xee\x00\x00\x00\v\x00\x1c\x00Asia/ManilaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xffe¤p\xff\xff\xff\xff\xd7>\x02p\xff\xff\xff\xff\xd7\xedY\xf0\xff\xff\xff\xff\xd8\xf8\xfap\xff\xff\xff\xff\xd9\xcd;\xf0\xff\xff" + + "\xff\xff\xdb\a\x00\xf0\xff\xff\xff\xffۭ\x1d\xf0\xff\xff\xff\xff\xdc\xe6\xe2\xf0\xff\xff\xff\xff\u074c\xff\xf0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\x83\x03\x00\x00\x00\x00\x8c\xa0\x01\x04\x00\x00~\x90\x00\bLMT" + + "\x00JDT\x00JST\x00\nJST-9\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb2\xb9\xf4\xb6R\x02\x00\x00R\x02\x00\x00\x10\x00\x1c\x00Asia/Ulaanbaat" + + "arUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x002\x00\x00\x00" + + "\x04\x00\x00\x00\x10\xff\xff\xff\xff\x86\xd3\xeeL\x00\x00\x00\x00\x0f\vܐ\x00\x00\x00\x00\x18\xe9Ȁ\x00\x00\x00\x00\x19\xda\xfc\xf0\x00\x00\x00\x00\x1a\xccM\x80\x00\x00\x00\x00\x1b\xbc0p\x00\x00\x00\x00\x1c\xac/" + + "\x80\x00\x00\x00\x00\x1d\x9c\x12p\x00\x00\x00\x00\x1e\x8c\x11\x80\x00\x00\x00\x00\x1f{\xf4p\x00\x00\x00\x00 k\xf3\x80\x00\x00\x00\x00![\xd6p\x00\x00\x00\x00\"KՀ\x00\x00\x00\x00#;\xb8p\x00\x00\x00" + + "\x00$+\xb7\x80\x00\x00\x00\x00%\x1b\x9ap\x00\x00\x00\x00&\v\x99\x80\x00\x00\x00\x00'\x04\xb6\xf0\x00\x00\x00\x00'\xf4\xb6\x00\x00\x00\x00\x00(\xe4\x98\xf0\x00\x00\x00\x00)Ԙ\x00\x00\x00\x00\x00*\xc4z" + + "\xf0\x00\x00\x00\x00+\xb4z\x00\x00\x00\x00\x00,\xa4\\\xf0\x00\x00\x00\x00-\x94\\\x00\x00\x00\x00\x00.\x84>\xf0\x00\x00\x00\x00/t>\x00\x00\x00\x00\x000d \xf0\x00\x00\x00\x001]Z\x80\x00\x00\x00" + + "\x002M=p\x00\x00\x00\x003=<\x80\x00\x00\x00\x004-\x1fp\x00\x00\x00\x005\x1d\x1e\x80\x00\x00\x00\x006\r\x01p\x00\x00\x00\x00:鳠\x00\x00\x00\x00;\xb4\xac\x90\x00\x00\x00\x00<\xa4\xab" + + "\xa0\x00\x00\x00\x00=\x94\x8e\x90\x00\x00\x00\x00>\x84\x8d\xa0\x00\x00\x00\x00?tp\x90\x00\x00\x00\x00@do\xa0\x00\x00\x00\x00ATR\x90\x00\x00\x00\x00BDQ\xa0\x00\x00\x00\x00C44\x90\x00\x00\x00" + + "\x00D$3\xa0\x00\x00\x00\x00E\x1dQ\x10\x00\x00\x00\x00U\x15\x9a\xa0\x00\x00\x00\x00V\x05ap\x00\x00\x00\x00V\xf5|\xa0\x00\x00\x00\x00W\xe5Cp\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x00\x00d4\x00\x00\x00\x00bp\x00\x04\x00\x00~\x90\x01\b\x00\x00p\x80\x00\fL" + + "MT\x00+07\x00+09\x00+08\x00\n<+08>-8\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS9Y\xb7\xf1\n\x01\x00\x00\n\x01\x00\x00\f\x00\x1c\x00Asia/K" + + "arachiUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\v\x00\x00\x00\x06\x00\x00\x00\x1d\xff\xff\xff\xff\x89~\xfc\xa4\xff\xff\xff\xff̕2\xa8\xff\xff\xff\xff\xd2t\x12\x98\xff\xff\xff\xffݨ\xe0\xa8\x00\x00\x00\x00\x02O\xab0\x00\x00\x00\x00<\xafE\xb0\x00\x00\x00" + + "\x00=\x9f(\xa0\x00\x00\x00\x00HA\xa00\x00\x00\x00\x00I\vG\xa0\x00\x00\x00\x00I\xe4\xdd0\x00\x00\x00\x00J\xec{ \x01\x02\x01\x03\x05\x04\x05\x04\x05\x04\x05\x00\x00>\xdc\x00\x00\x00\x00MX\x00\x04" + + "\x00\x00[h\x01\n\x00\x00FP\x00\x10\x00\x00T`\x01\x14\x00\x00FP\x00\x19LMT\x00+0530\x00+0630\x00+05\x00PKST\x00PKT\x00\nPKT-5\n" + + "PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xab\xcd\xdf\x05\xee\x02\x00\x00\xee\x02\x00\x00\n\x00\x1c\x00Asia/ChitaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14" + + "E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00T" + + "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00B\x00\x00\x00\x06\x00\x00\x00\x10\xff\xff\xff\xff\xa1\xdb\xf9\xa0\xff\xff\xff\xff\xb5\xa3\xc5\x00\x00" + + "\x00\x00\x00\x15'Sp\x00\x00\x00\x00\x16\x18\x87\xe0\x00\x00\x00\x00\x17\b\x86\xf0\x00\x00\x00\x00\x17\xf9\xbb`\x00\x00\x00\x00\x18\xe9\xbap\x00\x00\x00\x00\x19\xda\xee\xe0\x00\x00\x00\x00\x1a\xcc?p\x00\x00\x00\x00\x1b" + + "\xbcL\x90\x00\x00\x00\x00\x1c\xac=\x90\x00\x00\x00\x00\x1d\x9c.\x90\x00\x00\x00\x00\x1e\x8c\x1f\x90\x00\x00\x00\x00\x1f|\x10\x90\x00\x00\x00\x00 l\x01\x90\x00\x00\x00\x00![\xf2\x90\x00\x00\x00\x00\"K\xe3\x90\x00" + + "\x00\x00\x00#;Ԑ\x00\x00\x00\x00$+Ő\x00\x00\x00\x00%\x1b\xb6\x90\x00\x00\x00\x00&\v\xa7\x90\x00\x00\x00\x00'\x04\xd3\x10\x00\x00\x00\x00'\xf4\xc4\x10\x00\x00\x00\x00(\xe4\xc3 \x00\x00\x00\x00)" + + "xk \x00\x00\x00\x00)Ԧ\x10\x00\x00\x00\x00*ė\x10\x00\x00\x00\x00+\xb4\x88\x10\x00\x00\x00\x00,\xa4y\x10\x00\x00\x00\x00-\x94j\x10\x00\x00\x00\x00.\x84[\x10\x00\x00\x00\x00/tL\x10\x00" + + "\x00\x00\x000d=\x10\x00\x00\x00\x001]h\x90\x00\x00\x00\x002rC\x90\x00\x00\x00\x003=J\x90\x00\x00\x00\x004R%\x90\x00\x00\x00\x005\x1d,\x90\x00\x00\x00\x0062\a\x90\x00\x00\x00\x006" + + "\xfd\x0e\x90\x00\x00\x00\x008\x1b$\x10\x00\x00\x00\x008\xdc\xf0\x90\x00\x00\x00\x009\xfb\x06\x10\x00\x00\x00\x00:\xbcҐ\x00\x00\x00\x00;\xda\xe8\x10\x00\x00\x00\x00<\xa5\xef\x10\x00\x00\x00\x00=\xba\xca\x10\x00" + + "\x00\x00\x00>\x85\xd1\x10\x00\x00\x00\x00?\x9a\xac\x10\x00\x00\x00\x00@e\xb3\x10\x00\x00\x00\x00A\x83Ȑ\x00\x00\x00\x00BE\x95\x10\x00\x00\x00\x00Cc\xaa\x90\x00\x00\x00\x00D%w\x10\x00\x00\x00\x00E" + + "C\x8c\x90\x00\x00\x00\x00F\x05Y\x10\x00\x00\x00\x00G#n\x90\x00\x00\x00\x00G\xeeu\x90\x00\x00\x00\x00I\x03P\x90\x00\x00\x00\x00I\xceW\x90\x00\x00\x00\x00J\xe32\x90\x00\x00\x00\x00K\xae9\x90\x00" + + "\x00\x00\x00L\xccO\x10\x00\x00\x00\x00M\x8e\x1b\x90\x00\x00\x00\x00TK\xc9\x00\x00\x00\x00\x00V\xf6\xce \x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x05\x01\x03\x00\x00j`\x00\x00\x00\x00p\x80\x00\x04\x00\x00\x8c\xa0\x01\b\x00\x00~\x90\x00" + + "\f\x00\x00~\x90\x01\f\x00\x00\x8c\xa0\x00\bLMT\x00+08\x00+10\x00+09\x00\n<+09>-9\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xf0\x9cf>\xd7\x02\x00\x00" + + "\xd7\x02\x00\x00\x0e\x00\x1c\x00Asia/KamchatkaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xa7R\x96\xc4\xff\xff\xff\xff\xb5\xa3\x9a\xd0\x00\x00\x00\x00\x15')@\x00\x00\x00\x00\x16\x18]\xb0\x00\x00\x00" + + "\x00\x17\b\\\xc0\x00\x00\x00\x00\x17\xf9\x910\x00\x00\x00\x00\x18\xe9\x90@\x00\x00\x00\x00\x19\xdaİ\x00\x00\x00\x00\x1a\xcc\x15@\x00\x00\x00\x00\x1b\xbc\"`\x00\x00\x00\x00\x1c\xac\x13`\x00\x00\x00\x00\x1d\x9c\x04" + + "`\x00\x00\x00\x00\x1e\x8b\xf5`\x00\x00\x00\x00\x1f{\xe6`\x00\x00\x00\x00 k\xd7`\x00\x00\x00\x00![\xc8`\x00\x00\x00\x00\"K\xb9`\x00\x00\x00\x00#;\xaa`\x00\x00\x00\x00$+\x9b`\x00\x00\x00" + + "\x00%\x1b\x8c`\x00\x00\x00\x00&\v}`\x00\x00\x00\x00'\x04\xa8\xe0\x00\x00\x00\x00'\xf4\x99\xe0\x00\x00\x00\x00(\xe4\x98\xf0\x00\x00\x00\x00)x@\xf0\x00\x00\x00\x00)\xd4{\xe0\x00\x00\x00\x00*\xc4l" + + "\xe0\x00\x00\x00\x00+\xb4]\xe0\x00\x00\x00\x00,\xa4N\xe0\x00\x00\x00\x00-\x94?\xe0\x00\x00\x00\x00.\x840\xe0\x00\x00\x00\x00/t!\xe0\x00\x00\x00\x000d\x12\xe0\x00\x00\x00\x001]>`\x00\x00\x00" + + "\x002r\x19`\x00\x00\x00\x003= `\x00\x00\x00\x004Q\xfb`\x00\x00\x00\x005\x1d\x02`\x00\x00\x00\x0061\xdd`\x00\x00\x00\x006\xfc\xe4`\x00\x00\x00\x008\x1a\xf9\xe0\x00\x00\x00\x008\xdc\xc6" + + "`\x00\x00\x00\x009\xfa\xdb\xe0\x00\x00\x00\x00:\xbc\xa8`\x00\x00\x00\x00;ڽ\xe0\x00\x00\x00\x00<\xa5\xc4\xe0\x00\x00\x00\x00=\xba\x9f\xe0\x00\x00\x00\x00>\x85\xa6\xe0\x00\x00\x00\x00?\x9a\x81\xe0\x00\x00\x00" + + "\x00@e\x88\xe0\x00\x00\x00\x00A\x83\x9e`\x00\x00\x00\x00BEj\xe0\x00\x00\x00\x00Cc\x80`\x00\x00\x00\x00D%L\xe0\x00\x00\x00\x00ECb`\x00\x00\x00\x00F\x05.\xe0\x00\x00\x00\x00G#D" + + "`\x00\x00\x00\x00G\xeeK`\x00\x00\x00\x00I\x03&`\x00\x00\x00\x00I\xce-`\x00\x00\x00\x00J\xe3\b`\x00\x00\x00\x00K\xae\x0f`\x00\x00\x00\x00L\xcc2\xf0\x00\x00\x00\x00M\x8d\xffp\x01\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01" + + "\x03\x00\x00\x94\xbc\x00\x00\x00\x00\x9a\xb0\x00\x04\x00\x00\xb6\xd0\x01\b\x00\x00\xa8\xc0\x00\f\x00\x00\xa8\xc0\x01\fLMT\x00+11\x00+13\x00+12\x00\n<+12>-12\nPK\x03" + + "\x04\n\x00\x00\x00\x00\x00#\x82iS\x03R\xda\xedU\x02\x00\x00U\x02\x00\x00\f\x00\x1c\x00Asia/NicosiaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E" + + "\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + + "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x001\x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff\xff\xa5w\x1e\xb8\x00\x00\x00\x00\t\xed\xaf\xe0\x00\x00" + + "\x00\x00\nݒ\xd0\x00\x00\x00\x00\v\xfad\xe0\x00\x00\x00\x00\f\xbe\xc6P\x00\x00\x00\x00\r\xa49`\x00\x00\x00\x00\x0e\x8a\xe1\xd0\x00\x00\x00\x00\x0f\x84\x1b`\x00\x00\x00\x00\x10uO\xd0\x00\x00\x00\x00\x11c" + + "\xfd`\x00\x00\x00\x00\x12S\xe0P\x00\x00\x00\x00\x13M\x19\xe0\x00\x00\x00\x00\x143\xc2P\x00\x00\x00\x00\x15#\xc1`\x00\x00\x00\x00\x16\x13\xa4P\x00\x00\x00\x00\x17\x03\xa3`\x00\x00\x00\x00\x17\xf3\x86P\x00\x00" + + "\x00\x00\x18\xe3\x85`\x00\x00\x00\x00\x19\xd3hP\x00\x00\x00\x00\x1a\xc3g`\x00\x00\x00\x00\x1b\xbc\x84\xd0\x00\x00\x00\x00\x1c\xac\x83\xe0\x00\x00\x00\x00\x1d\x9cf\xd0\x00\x00\x00\x00\x1e\x8ce\xe0\x00\x00\x00\x00\x1f|" + + "H\xd0\x00\x00\x00\x00 lG\xe0\x00\x00\x00\x00!\\*\xd0\x00\x00\x00\x00\"L)\xe0\x00\x00\x00\x00#<\f\xd0\x00\x00\x00\x00$,\v\xe0\x00\x00\x00\x00%\x1b\xee\xd0\x00\x00\x00\x00&\v\xed\xe0\x00\x00" + + "\x00\x00'\x05\vP\x00\x00\x00\x00'\xf5\n`\x00\x00\x00\x00(\xe4\xedP\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xc4\xcfP\x00\x00\x00\x00+\xb4\xce`\x00\x00\x00\x00,\xa4\xb1P\x00\x00\x00\x00-\x94" + + "\xb0`\x00\x00\x00\x00.\x84\x93P\x00\x00\x00\x00/t\x92`\x00\x00\x00\x000duP\x00\x00\x00\x001]\xae\xe0\x00\x00\x00\x002M\x91\xd0\x00\x00\x00\x003=\x90\xe0\x00\x00\x00\x004-s\xd0\x00\x00" + + "\x00\x005\x1dr\xe0\x00\x00\x00\x0062x\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x00\x00\x1fH\x00\x00\x00\x00*0\x01\x04\x00\x00\x1c \x00\tLMT\x00EEST\x00EET\x00\nEET-2EEST,M3.5.0/3,M10.5." + + "0/4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS`\xc9\xd4\\\xbe\x00\x00\x00\xbe\x00\x00\x00\r\x00\x1c\x00Asia/MakassarUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8ba" + + "ux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00" + + "\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xff\xa1\xf2]\x90\xff\xff" + + "\xff\xff\xba\x16Ր\xff\xff\xff\xffˈ\x1d\x80\xff\xff\xff\xff\xd2V\xeep\x01\x02\x03\x04\x00\x00o\xf0\x00\x00\x00\x00o\xf0\x00\x04\x00\x00p\x80\x00\b\x00\x00~\x90\x00\f\x00\x00p\x80\x00\x10LMT\x00" + + "MMT\x00+08\x00+09\x00WITA\x00\nWITA-8\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS0]*\x1bj\x02\x00\x00j\x02\x00\x00\f\x00\x1c\x00Asia/" + + "BishkekUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x004\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x19~\x10\xff\xff\xff\xff\xb5\xa3\xef0\x00\x00\x00\x00\x15'}\xa0\x00\x00\x00\x00\x16\x18\xb2\x10\x00\x00\x00\x00\x17\b\xb1 \x00\x00\x00\x00\x17\xf9\xe5\x90\x00\x00" + + "\x00\x00\x18\xe9\xe4\xa0\x00\x00\x00\x00\x19\xdb\x19\x10\x00\x00\x00\x00\x1a\xcci\xa0\x00\x00\x00\x00\x1b\xbcv\xc0\x00\x00\x00\x00\x1c\xacg\xc0\x00\x00\x00\x00\x1d\x9cX\xc0\x00\x00\x00\x00\x1e\x8cI\xc0\x00\x00\x00\x00\x1f|" + + ":\xc0\x00\x00\x00\x00 l+\xc0\x00\x00\x00\x00!\\\x1c\xc0\x00\x00\x00\x00\"L\r\xc0\x00\x00\x00\x00#;\xfe\xc0\x00\x00\x00\x00$+\xef\xc0\x00\x00\x00\x00%\x1b\xe0\xc0\x00\x00\x00\x00&\v\xd1\xc0\x00\x00" + + "\x00\x00'\x04\xfd@\x00\x00\x00\x00'\xf4\xee@\x00\x00\x00\x00(\xbe\xa3\xc0\x00\x00\x00\x00)\xe770\x00\x00\x00\x00*ĥ \x00\x00\x00\x00+\xc7\x190\x00\x00\x00\x00,\xa4\x87 \x00\x00\x00\x00-\xa6" + + "\xfb0\x00\x00\x00\x00.\x84i \x00\x00\x00\x00/\x86\xdd0\x00\x00\x00\x000dK \x00\x00\x00\x001f\xbf0\x00\x00\x00\x002Mg\xa0\x00\x00\x00\x003=\x89\xd8\x00\x00\x00\x004RV\xc8\x00\x00" + + "\x00\x005\x1dk\xd8\x00\x00\x00\x00628\xc8\x00\x00\x00\x006\xfdM\xd8\x00\x00\x00\x008\x1bUH\x00\x00\x00\x008\xdd/\xd8\x00\x00\x00\x009\xfb7H\x00\x00\x00\x00:\xbd\x11\xd8\x00\x00\x00\x00;\xdb" + + "\x19H\x00\x00\x00\x00<\xa6.X\x00\x00\x00\x00=\xba\xfbH\x00\x00\x00\x00>\x86\x10X\x00\x00\x00\x00?\x9a\xddH\x00\x00\x00\x00@e\xf2X\x00\x00\x00\x00A\x83\xf9\xc8\x00\x00\x00\x00BE\xd4X\x00\x00" + + "\x00\x00B\xfb\x92 \x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x03\x00\x00" + + "E\xf0\x00\x00\x00\x00FP\x00\x04\x00\x00bp\x01\b\x00\x00T`\x00\f\x00\x00T`\x01\fLMT\x00+05\x00+07\x00+06\x00\n<+06>-6\nPK\x03\x04\n\x00\x00" + + "\x00\x00\x00#\x82iS\xd5ΜGp\x02\x00\x00p\x02\x00\x00\x0e\x00\x1c\x00Asia/QyzylordaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00" + + "\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif" + + "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004\x00\x00\x00\x06\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x19\x86\xa0\xff\xff\xff\xff\xb5\xa3\xfd@\x00\x00\x00\x00" + + "\x15'\x8b\xb0\x00\x00\x00\x00\x16\x18\xc0 \x00\x00\x00\x00\x17\b\xb1 \x00\x00\x00\x00\x17\xf9\xf3\xa0\x00\x00\x00\x00\x18\xe9\xf2\xb0\x00\x00\x00\x00\x19\xdb' \x00\x00\x00\x00\x1a\xccw\xb0\x00\x00\x00\x00\x1b\xbc\x84\xd0" + + "\x00\x00\x00\x00\x1c\xacu\xd0\x00\x00\x00\x00\x1d\x9cf\xd0\x00\x00\x00\x00\x1e\x8cW\xd0\x00\x00\x00\x00\x1f|H\xd0\x00\x00\x00\x00 l9\xd0\x00\x00\x00\x00!\\*\xd0\x00\x00\x00\x00\"L\x1b\xd0\x00\x00\x00\x00" + + "#<\f\xd0\x00\x00\x00\x00$+\xfd\xd0\x00\x00\x00\x00%\x1b\xee\xd0\x00\x00\x00\x00&\v\xdf\xd0\x00\x00\x00\x00'\x05\vP\x00\x00\x00\x00'\xf4\xfcP\x00\x00\x00\x00(\xe4\xfb`\x00\x00\x00\x00)x\x95P" + + "\x00\x00\x00\x00)\xd4\xd0@\x00\x00\x00\x00*\xc4\xcfP\x00\x00\x00\x00+\xb4\xc0P\x00\x00\x00\x00,\xa4\xb1P\x00\x00\x00\x00-\x94\xa2P\x00\x00\x00\x00.\x84\x93P\x00\x00\x00\x00/t\x84P\x00\x00\x00\x00" + + "0duP\x00\x00\x00\x001]\xa0\xd0\x00\x00\x00\x002r{\xd0\x00\x00\x00\x003=\x82\xd0\x00\x00\x00\x004R]\xd0\x00\x00\x00\x005\x1dd\xd0\x00\x00\x00\x0062?\xd0\x00\x00\x00\x006\xfdF\xd0" + + "\x00\x00\x00\x008\x1b\\P\x00\x00\x00\x008\xdd(\xd0\x00\x00\x00\x009\xfb>P\x00\x00\x00\x00:\xbd\n\xd0\x00\x00\x00\x00;\xdb P\x00\x00\x00\x00<\xa6'P\x00\x00\x00\x00=\xbb\x02P\x00\x00\x00\x00" + + ">\x86\tP\x00\x00\x00\x00?\x9a\xe4P\x00\x00\x00\x00@e\xebP\x00\x00\x00\x00A\x84\x00\xd0\x00\x00\x00\x00\\\x1bؠ\x01\x02\x03\x04\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x02" + + "\x04\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x02\x00\x00=`\x00\x00\x00\x008@\x00\x04\x00\x00FP\x00\b\x00\x00T`\x01\f\x00\x00T`\x00\f\x00\x00" + + "FP\x01\bLMT\x00+04\x00+05\x00+06\x00\n<+05>-5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x02\x95-\xad\xc4\x02\x00\x00\xc4\x02\x00\x00\f\x00\x1c\x00A" + + "sia/YerevanUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00>\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x19\x9aH\xff\xff\xff\xff\xe7\xda\fP\x00\x00\x00\x00\x15'\x99\xc0\x00\x00\x00\x00\x16\x18\xce0\x00\x00\x00\x00\x17\b\xcd@\x00\x00\x00\x00\x17\xfa" + + "\x01\xb0\x00\x00\x00\x00\x18\xea\x00\xc0\x00\x00\x00\x00\x19\xdb50\x00\x00\x00\x00\x1a̅\xc0\x00\x00\x00\x00\x1b\xbc\x92\xe0\x00\x00\x00\x00\x1c\xac\x83\xe0\x00\x00\x00\x00\x1d\x9ct\xe0\x00\x00\x00\x00\x1e\x8ce\xe0\x00\x00" + + "\x00\x00\x1f|V\xe0\x00\x00\x00\x00 lG\xe0\x00\x00\x00\x00!\\8\xe0\x00\x00\x00\x00\"L)\xe0\x00\x00\x00\x00#<\x1a\xe0\x00\x00\x00\x00$,\v\xe0\x00\x00\x00\x00%\x1b\xfc\xe0\x00\x00\x00\x00&\v" + + "\xed\xe0\x00\x00\x00\x00'\x05\x19`\x00\x00\x00\x00'\xf5\n`\x00\x00\x00\x00(\xe5\tp\x00\x00\x00\x00)\xd4\xfap\x00\x00\x00\x00*\xc4\xebp\x00\x00\x00\x00+\xb4\xdcp\x00\x00\x00\x00,\xa4\xcdp\x00\x00" + + "\x00\x00-\x94\xbep\x00\x00\x00\x00.\x84\xafp\x00\x00\x00\x00/t\xa0p\x00\x00\x00\x000d\x91p\x00\x00\x00\x003=\x90\xe0\x00\x00\x00\x004Rk\xe0\x00\x00\x00\x005\x1dr\xe0\x00\x00\x00\x0062" + + "M\xe0\x00\x00\x00\x006\xfdT\xe0\x00\x00\x00\x008\x1bj`\x00\x00\x00\x008\xdd6\xe0\x00\x00\x00\x009\xfbL`\x00\x00\x00\x00:\xbd\x18\xe0\x00\x00\x00\x00;\xdb.`\x00\x00\x00\x00<\xa65`\x00\x00" + + "\x00\x00=\xbb\x10`\x00\x00\x00\x00>\x86\x17`\x00\x00\x00\x00?\x9a\xf2`\x00\x00\x00\x00@e\xf9`\x00\x00\x00\x00A\x84\x0e\xe0\x00\x00\x00\x00BE\xdb`\x00\x00\x00\x00Cc\xf0\xe0\x00\x00\x00\x00D%" + + "\xbd`\x00\x00\x00\x00EC\xd2\xe0\x00\x00\x00\x00F\x05\x9f`\x00\x00\x00\x00G#\xb4\xe0\x00\x00\x00\x00G\xee\xbb\xe0\x00\x00\x00\x00I\x03\x96\xe0\x00\x00\x00\x00IΝ\xe0\x00\x00\x00\x00J\xe3x\xe0\x00\x00" + + "\x00\x00K\xae\u007f\xe0\x00\x00\x00\x00L̕`\x00\x00\x00\x00M\x8ea\xe0\x00\x00\x00\x00N\xacw`\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x04\x01\x04\x01\x04\x01" + + "\x04\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x00\x00)\xb8\x00\x00\x00\x00*0\x00\x04\x00\x00FP\x01\b\x00\x008@\x00\f\x00\x008@" + + "\x01\fLMT\x00+03\x00+05\x00+04\x00\n<+04>-4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xa4Zߐ\xe6\x02\x00\x00\xe6\x02\x00\x00\x12\x00\x1c\x00Asi" + + "a/SrednekolymskUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00A\x00\x00\x00\x06\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x193\xe4\xff\xff\xff\xff\xb5\xa3\xa8\xe0\x00\x00\x00\x00\x15'7P\x00\x00\x00\x00\x16\x18k\xc0\x00\x00\x00\x00\x17\bj\xd0\x00\x00" + + "\x00\x00\x17\xf9\x9f@\x00\x00\x00\x00\x18\xe9\x9eP\x00\x00\x00\x00\x19\xda\xd2\xc0\x00\x00\x00\x00\x1a\xcc#P\x00\x00\x00\x00\x1b\xbc0p\x00\x00\x00\x00\x1c\xac!p\x00\x00\x00\x00\x1d\x9c\x12p\x00\x00\x00\x00\x1e\x8c" + + "\x03p\x00\x00\x00\x00\x1f{\xf4p\x00\x00\x00\x00 k\xe5p\x00\x00\x00\x00![\xd6p\x00\x00\x00\x00\"K\xc7p\x00\x00\x00\x00#;\xb8p\x00\x00\x00\x00$+\xa9p\x00\x00\x00\x00%\x1b\x9ap\x00\x00" + + "\x00\x00&\v\x8bp\x00\x00\x00\x00'\x04\xb6\xf0\x00\x00\x00\x00'\xf4\xa7\xf0\x00\x00\x00\x00(\xe4\xa7\x00\x00\x00\x00\x00)xO\x00\x00\x00\x00\x00)ԉ\xf0\x00\x00\x00\x00*\xc4z\xf0\x00\x00\x00\x00+\xb4" + + "k\xf0\x00\x00\x00\x00,\xa4\\\xf0\x00\x00\x00\x00-\x94M\xf0\x00\x00\x00\x00.\x84>\xf0\x00\x00\x00\x00/t/\xf0\x00\x00\x00\x000d \xf0\x00\x00\x00\x001]Lp\x00\x00\x00\x002r'p\x00\x00" + + "\x00\x003=.p\x00\x00\x00\x004R\tp\x00\x00\x00\x005\x1d\x10p\x00\x00\x00\x0061\xebp\x00\x00\x00\x006\xfc\xf2p\x00\x00\x00\x008\x1b\a\xf0\x00\x00\x00\x008\xdc\xd4p\x00\x00\x00\x009\xfa" + + "\xe9\xf0\x00\x00\x00\x00:\xbc\xb6p\x00\x00\x00\x00;\xda\xcb\xf0\x00\x00\x00\x00<\xa5\xd2\xf0\x00\x00\x00\x00=\xba\xad\xf0\x00\x00\x00\x00>\x85\xb4\xf0\x00\x00\x00\x00?\x9a\x8f\xf0\x00\x00\x00\x00@e\x96\xf0\x00\x00" + + "\x00\x00A\x83\xacp\x00\x00\x00\x00BEx\xf0\x00\x00\x00\x00Cc\x8ep\x00\x00\x00\x00D%Z\xf0\x00\x00\x00\x00ECpp\x00\x00\x00\x00F\x05<\xf0\x00\x00\x00\x00G#Rp\x00\x00\x00\x00G\xee" + + "Yp\x00\x00\x00\x00I\x034p\x00\x00\x00\x00I\xce;p\x00\x00\x00\x00J\xe3\x16p\x00\x00\x00\x00K\xae\x1dp\x00\x00\x00\x00L\xcc2\xf0\x00\x00\x00\x00M\x8d\xffp\x00\x00\x00\x00TK\xac\xe0\x01\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x05\x03\x00\x00\x90\x1c\x00\x00\x00\x00\x8c\xa0\x00\x04\x00\x00\xa8\xc0\x01\b\x00\x00\x9a\xb0\x00\f\x00\x00\x9a\xb0\x01\f\x00\x00\xa8\xc0\x00\bLMT\x00+10\x00+12\x00+11\x00\n<+11" + + ">-11\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xcfׇ\xe1\x85\x00\x00\x00\x85\x00\x00\x00\t\x00\x1c\x00Asia/AdenUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v" + + "\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00" + + "\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\xd5\x1b6\xb4\x01\x00\x00+\xcc" + + "\x00\x00\x00\x00*0\x00\x04LMT\x00+03\x00\n<+03>-3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS*\xe4@\xa9\x89\x01\x00\x00\x89\x01\x00\x00\x0e\x00\x1c\x00Asia/" + + "ChongqingUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x1d\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff~6C)\xff\xff\xff\xff\xa0\x97\xa2\x80\xff\xff\xff\xff\xa1y\x04\xf0\xff\xff\xff\xff\xc8Y^\x80\xff\xff\xff\xff\xc9\t\xf9p\xff\xff\xff\xff\xc9ӽ\x00" + + "\xff\xff\xff\xff\xcb\x05\x8a\xf0\xff\xff\xff\xff\xcb|@\x00\xff\xff\xff\xff\xd2;>\xf0\xff\xff\xff\xffӋ{\x80\xff\xff\xff\xff\xd4B\xad\xf0\xff\xff\xff\xff\xd5E\"\x00\xff\xff\xff\xff\xd6L\xbf\xf0\xff\xff\xff\xff" + + "\xd7<\xbf\x00\xff\xff\xff\xff\xd8\x06fp\xff\xff\xff\xff\xd9\x1d\xf2\x80\xff\xff\xff\xff\xd9A|\xf0\x00\x00\x00\x00\x1e\xbaR \x00\x00\x00\x00\x1fi\x9b\x90\x00\x00\x00\x00 ~\x84\xa0\x00\x00\x00\x00!I}\x90" + + "\x00\x00\x00\x00\"g\xa1 \x00\x00\x00\x00#)_\x90\x00\x00\x00\x00$G\x83 \x00\x00\x00\x00%\x12|\x10\x00\x00\x00\x00&'e \x00\x00\x00\x00&\xf2^\x10\x00\x00\x00\x00(\aG \x00\x00\x00\x00" + + "(\xd2@\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00q\xd7\x00\x00\x00\x00~\x90\x01\x04\x00\x00p\x80\x00\bLMT\x00CDT\x00C" + + "ST\x00\nCST-8\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb2\xb9\xf4\xb6R\x02\x00\x00R\x02\x00\x00\x0f\x00\x1c\x00Asia/Ulan_BatorUT\t\x00\x03" + + "\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x002\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff" + + "\xff\xff\x86\xd3\xeeL\x00\x00\x00\x00\x0f\vܐ\x00\x00\x00\x00\x18\xe9Ȁ\x00\x00\x00\x00\x19\xda\xfc\xf0\x00\x00\x00\x00\x1a\xccM\x80\x00\x00\x00\x00\x1b\xbc0p\x00\x00\x00\x00\x1c\xac/\x80\x00\x00\x00\x00\x1d\x9c" + + "\x12p\x00\x00\x00\x00\x1e\x8c\x11\x80\x00\x00\x00\x00\x1f{\xf4p\x00\x00\x00\x00 k\xf3\x80\x00\x00\x00\x00![\xd6p\x00\x00\x00\x00\"KՀ\x00\x00\x00\x00#;\xb8p\x00\x00\x00\x00$+\xb7\x80\x00\x00" + + "\x00\x00%\x1b\x9ap\x00\x00\x00\x00&\v\x99\x80\x00\x00\x00\x00'\x04\xb6\xf0\x00\x00\x00\x00'\xf4\xb6\x00\x00\x00\x00\x00(\xe4\x98\xf0\x00\x00\x00\x00)Ԙ\x00\x00\x00\x00\x00*\xc4z\xf0\x00\x00\x00\x00+\xb4" + + "z\x00\x00\x00\x00\x00,\xa4\\\xf0\x00\x00\x00\x00-\x94\\\x00\x00\x00\x00\x00.\x84>\xf0\x00\x00\x00\x00/t>\x00\x00\x00\x00\x000d \xf0\x00\x00\x00\x001]Z\x80\x00\x00\x00\x002M=p\x00\x00" + + "\x00\x003=<\x80\x00\x00\x00\x004-\x1fp\x00\x00\x00\x005\x1d\x1e\x80\x00\x00\x00\x006\r\x01p\x00\x00\x00\x00:鳠\x00\x00\x00\x00;\xb4\xac\x90\x00\x00\x00\x00<\xa4\xab\xa0\x00\x00\x00\x00=\x94" + + "\x8e\x90\x00\x00\x00\x00>\x84\x8d\xa0\x00\x00\x00\x00?tp\x90\x00\x00\x00\x00@do\xa0\x00\x00\x00\x00ATR\x90\x00\x00\x00\x00BDQ\xa0\x00\x00\x00\x00C44\x90\x00\x00\x00\x00D$3\xa0\x00\x00" + + "\x00\x00E\x1dQ\x10\x00\x00\x00\x00U\x15\x9a\xa0\x00\x00\x00\x00V\x05ap\x00\x00\x00\x00V\xf5|\xa0\x00\x00\x00\x00W\xe5Cp\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x00\x00d4\x00\x00\x00\x00bp\x00\x04\x00\x00~\x90\x01\b\x00\x00p\x80\x00\fLMT\x00+07\x00" + + "+09\x00+08\x00\n<+08>-8\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x17✳2\x04\x00\x002\x04\x00\x00\x0e\x00\x1c\x00Asia/Jerusale" + + "mUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\x00\x00\x00\x05" + + "\x00\x00\x00\x15\xff\xff\xff\xffV\xb6\xc2\xfa\xff\xff\xff\xff\x9e0E\x88\xff\xff\xff\xff\xc8Y\xcf\x00\xff\xff\xff\xff\xc8\xfa\xa6\x00\xff\xff\xff\xff\xc98\x9c\x80\xff\xff\xff\xff\xcc\xe5\xeb\x80\xff\xff\xff\xffͬ\xfe\x00" + + "\xff\xff\xff\xff\xce\xc7\x1f\x00\xff\xff\xff\xffϏ\x83\x00\xff\xff\xff\xffЩ\xa4\x00\xff\xff\xff\xffф}\x00\xff\xff\xff\xffҊ׀\xff\xff\xff\xff\xd3e\xb0\x80\xff\xff\xff\xff\xd4l\v\x00\xff\xff\xff\xff" + + "\xd7Z0\x80\xff\xff\xff\xff\xd7\xdfX\x00\xff\xff\xff\xff\xd8/À\xff\xff\xff\xff\xd9\x1ec\x00\xff\xff\xff\xff\xda\x10\xf7\x00\xff\xff\xff\xff\xda\xeb\xd0\x00\xff\xff\xff\xff۴4\x00\xff\xff\xff\xffܹ=\x00" + + "\xff\xff\xff\xff\xdd\xe0\x8d\x00\xff\xff\xff\xff\u07b4\u0380\xff\xff\xff\xffߤ\xbf\x80\xff\xff\xff\xff\xe0\x8bv\x00\xff\xff\xff\xff\xe1V}\x00\xff\xff\xff\xff\xe2\xbef\x80\xff\xff\xff\xff\xe36_\x00\xff\xff\xff\xff" + + "\xe4\x9eH\x80\xff\xff\xff\xff\xe5\x16A\x00\xff\xff\xff\xff\xe6t\xf0\x00\xff\xff\xff\xff\xe7\x11Ҁ\xff\xff\xff\xff\xe8&\xad\x80\xff\xff\xff\xff\xe8\xe8z\x00\x00\x00\x00\x00\b|\x8b\xe0\x00\x00\x00\x00\b\xfd\xb0\xd0" + + "\x00\x00\x00\x00\t\xf6\xea`\x00\x00\x00\x00\n\xa63\xd0\x00\x00\x00\x00\x13\xe9\xfc`\x00\x00\x00\x00\x14![`\x00\x00\x00\x00\x1a\xfa\xc6`\x00\x00\x00\x00\x1b\x8en`\x00\x00\x00\x00\x1c\xbe\xf8\xe0\x00\x00\x00\x00" + + "\x1dw|\xd0\x00\x00\x00\x00\x1e\xcc\xff`\x00\x00\x00\x00\x1f`\x99P\x00\x00\x00\x00 \x82\xb1`\x00\x00\x00\x00!I\xb5\xd0\x00\x00\x00\x00\"^\x9e\xe0\x00\x00\x00\x00# ]P\x00\x00\x00\x00$Z0`" + + "\x00\x00\x00\x00%\x00?P\x00\x00\x00\x00&\v\xed\xe0\x00\x00\x00\x00&\xd6\xe6\xd0\x00\x00\x00\x00'\xeb\xcf\xe0\x00\x00\x00\x00(\xc0\x03P\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xa9\x1f\xd0\x00\x00\x00\x00" + + "+\xbbe\xe0\x00\x00\x00\x00,\x89\x01\xd0\x00\x00\x00\x00-\x9bG\xe0\x00\x00\x00\x00._\xa9P\x00\x00\x00\x00/{)\xe0\x00\x00\x00\x000H\xc5\xd0\x00\x00\x00\x001H\x96\xe0\x00\x00\x00\x002\x83\x82p\x00\x00\x00\x00?|\x9f\xe0\x00\x00\x00\x00@s6p" + + "\x00\x00\x00\x00AP\xa4`\x00\x00\x00\x00BL\x8f\x00\x00\x00\x00\x00CHOp\x00\x00\x00\x00D,q\x00\x00\x00\x00\x00E\x1e\xf6\xf0\x00\x00\x00\x00F\fS\x00\x00\x00\x00\x00F\xecc\xf0\x00\x00\x00\x00" + + "G\xec5\x00\x00\x00\x00\x00H\xe7\xf5p\x00\x00\x00\x00I\xcc\x17\x00\x00\x00\x00\x00J\xbe\x9c\xf0\x00\x00\x00\x00K\xab\xf9\x00\x00\x00\x00\x00L\x8c\t\xf0\x00\x00\x00\x00M\x95\x15\x80\x00\x00\x00\x00N\x87\x9bp" + + "\x00\x00\x00\x00Ot\xf7\x80\x00\x00\x00\x00P^B\xf0\x00\x00\x00\x00QTـ\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x00\x00!\x06\x00\x00\x00\x00 \xf8\x00\x04\x00\x00*0\x01\b\x00\x00\x1c \x00\f\x00\x008@\x01\x10LMT\x00JMT\x00IDT\x00IST\x00IDDT\x00\nIST-" + + "2IDT,M3.4.4/26,M10.5.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xc7\x11\xe1[\xdc\x02\x00\x00\xdc\x02\x00\x00\v\x00\x1c\x00Asia/Be" + + "irutUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00" + + "\x00\x00\x03\x00\x00\x00\r\xff\xff\xff\xffV\xb6¸\xff\xff\xff\xff\xa2ec\xe0\xff\xff\xff\xff\xa3{\x82P\xff\xff\xff\xff\xa4N\x80`\xff\xff\xff\xff\xa5?\xb4\xd0\xff\xff\xff\xff\xa6%'\xe0\xff\xff\xff\xff\xa7" + + "'\u007f\xd0\xff\xff\xff\xff\xa8)\xf3\xe0\xff\xff\xff\xff\xa8\xeb\xb2P\xff\xff\xff\xff\xe8*\x85\xe0\xff\xff\xff\xff\xe8\xf4-P\xff\xff\xff\xff\xea\v\xb9`\xff\xff\xff\xff\xea\xd5`\xd0\xff\xff\xff\xff\xeb\xec\xec\xe0\xff" + + "\xff\xff\xff추P\xff\xff\xff\xff\xed\xcfq\xe0\xff\xff\xff\xff\xee\x99\x19P\xff\xff\xff\xffﰥ`\xff\xff\xff\xff\xf0zL\xd0\x00\x00\x00\x00\x04\xa6^`\x00\x00\x00\x00\x05+w\xd0\x00\x00\x00\x00\x06" + + "C\x03\xe0\x00\x00\x00\x00\a\f\xabP\x00\x00\x00\x00\b$7`\x00\x00\x00\x00\b\xed\xde\xd0\x00\x00\x00\x00\n\x05j\xe0\x00\x00\x00\x00\n\xcf\x12P\x00\x00\x00\x00\v\xe7\xef\xe0\x00\x00\x00\x00\f\xb1\x97P\x00" + + "\x00\x00\x00\r\xc9#`\x00\x00\x00\x00\x0e\x92\xca\xd0\x00\x00\x00\x00\x0f\xa9\x05`\x00\x00\x00\x00\x10r\xac\xd0\x00\x00\x00\x00\x1a\xf4.\xe0\x00\x00\x00\x00\x1bќ\xd0\x00\x00\x00\x00\x1c\xd5b`\x00\x00\x00\x00\x1d" + + "\xb2\xd0P\x00\x00\x00\x00\x1e\xb6\x95\xe0\x00\x00\x00\x00\x1f\x94\x03\xd0\x00\x00\x00\x00 \x97\xc9`\x00\x00\x00\x00!u7P\x00\x00\x00\x00\"\xa3,\xe0\x00\x00\x00\x00#W\xbcP\x00\x00\x00\x00$g_`\x00" + + "\x00\x00\x00%8\xef\xd0\x00\x00\x00\x00&<\xb5`\x00\x00\x00\x00'\x1a#P\x00\x00\x00\x00(\x1d\xe8\xe0\x00\x00\x00\x00(\xfbV\xd0\x00\x00\x00\x00*\x00m\xe0\x00\x00\x00\x00*\xce\t\xd0\x00\x00\x00\x00+" + + "\xb4\xce`\x00\x00\x00\x00,\xa4\xb1P\x00\x00\x00\x00-\x94\xb0`\x00\x00\x00\x00.\x84\x93P\x00\x00\x00\x00/t\x92`\x00\x00\x00\x000duP\x00\x00\x00\x001]\xae\xe0\x00\x00\x00\x002M\x91\xd0\x00" + + "\x00\x00\x003=\x90\xe0\x00\x00\x00\x004-s\xd0\x00\x00\x00\x005\x1dr\xe0\x00\x00\x00\x006\rU\xd0\x00\x00\x00\x006\xfdT\xe0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00!H\x00\x00\x00\x00*0\x01\x04\x00\x00\x1c \x00" + + "\tLMT\x00EEST\x00EET\x00\nEET-2EEST,M3.5.0/0,M10.5.0/0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS`\xc9" + + "\xd4\\\xbe\x00\x00\x00\xbe\x00\x00\x00\x12\x00\x1c\x00Asia/Ujung_PandangUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00" + "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\x14\xe1\xdc\x10\xff\xff\xff\xff{\x1f?\x90\xff\xff\xff\xff\xc1\x9c\xf4\x80\xff" + - "\xff\xff\xff\xc2\x160p\xff\xff\xff\xff\xcb\xf2\xe7\x00\xff\xff\xff\xffЩ%p\xff\xff\xff\xff\xe2l9\x00\xff\xff\xff\xff\xe2բ\xf0\x00\x00\x00\x00\x0fuF\x80\x00\x00\x00\x00\x10fz\xf0\x01\x03\x02\x03\x04" + - "\x03\x02\x03\x02\x03\xff\xff\x1f\xf0\x00\x00\x00\x00qp\x00\x00\x00\x00~\x90\x01\x04\x00\x00p\x80\x00\b\x00\x00~\x90\x00\fLMT\x00PDT\x00PST\x00JST\x00\nPST-8\nPK" + - "\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x1d?v\f\x17\x03\x00\x00\x17\x03\x00\x00\n\x00\x1c\x00Asia/MacaoUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00" + - "\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZi" + - "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\x85i[\x8e\xff\xff\xff\xff\xcbGu\xf0\xff\xff\xff" + - "\xff\xcb\xf2\xca\xe0\xff\xff\xff\xff\xcc\xfb\xbaP\xff\xff\xff\xff\xcd\xd3\xfe`\xff\xff\xff\xffΝ\xa5\xd0\xff\xff\xff\xff\xd2azp\xff\xff\xff\xff\xd3x\xf8p\xff\xff\xff\xff\xd4B\xad\xf0\xff\xff\xff\xff\xd5K\xab" + - "p\xff\xff\xff\xff\xd6tL\xf0\xff\xff\xff\xff\xd7?S\xf0\xff\xff\xff\xff\xd8/D\xf0\xff\xff\xff\xff\xd8\xf8\xfap\xff\xff\xff\xff\xda\r\xd5p\xff\xff\xff\xff\xda\xd8\xdcp\xff\xff\xff\xff\xdb\xed\xb7p\xff\xff\xff" + - "\xffܸ\xbep\xff\xff\xff\xff\xdd\xce\xea\xf0\xff\xff\xff\xffޡ\xda\xf0\xff\xff\xff\xff߶\xb5\xf0\xff\xff\xff\xff\xe0\x81\xbc\xf0\xff\xff\xff\xffᖗ\xf0\xff\xff\xff\xff\xe2O)\xf0\xff\xff\xff\xff\xe3vy" + - "\xf0\xff\xff\xff\xff\xe4/\v\xf0\xff\xff\xff\xff\xe5_\x96p\xff\xff\xff\xff\xe6\x0e\xed\xf0\xff\xff\xff\xff\xe7?\xa9\xa8\xff\xff\xff\xff\xe7\xf8I\xb8\xff\xff\xff\xff\xe9\x1f\x8b\xa8\xff\xff\xff\xff\xe9\xd8+\xb8\xff\xff\xff" + - "\xff\xea\xffm\xa8\xff\xff\xff\xff\xeb\xb8\r\xb8\xff\xff\xff\xff\xec\xdfO\xa8\xff\xff\xff\xff\xed\x97\xef\xb8\xff\xff\xff\xff\xee\xc8l(\xff\xff\xff\xff\xefwѸ\xff\xff\xff\xff\xf0\xa8N(\xff\xff\xff\xff\xf1W\xb3" + - "\xb8\xff\xff\xff\xff\xf2\x880(\xff\xff\xff\xff\xf3@\xd08\xff\xff\xff\xff\xf4h\x12(\xff\xff\xff\xff\xf5 \xb28\xff\xff\xff\xff\xf6G\xf4(\xff\xff\xff\xff\xf7%~8\xff\xff\xff\xff\xf8\x15S\x18\xff\xff\xff" + - "\xff\xf9\x05`8\xff\xff\xff\xff\xf9\xf55\x18\xff\xff\xff\xff\xfa\xe5B8\xff\xff\xff\xff\xfb\xde_\xa8\xff\xff\xff\xff\xfc\xce^\xb8\xff\xff\xff\xff\xfd\xbeA\xa8\xff\xff\xff\xff\xfe\xae@\xb8\xff\xff\xff\xff\xff\x9e#" + - "\xa8\x00\x00\x00\x00\x00\x8e\"\xb8\x00\x00\x00\x00\x01~\x05\xa8\x00\x00\x00\x00\x02n\x04\xb8\x00\x00\x00\x00\x03]\xe7\xa8\x00\x00\x00\x00\x04M\xe6\xb8\x00\x00\x00\x00\x05G\x04(\x00\x00\x00\x00\x067\x038\x00\x00\x00" + - "\x00\a&\xe6(\x00\x00\x00\x00\a\x83=8\x00\x00\x00\x00\t\x06\xc8(\x00\x00\x00\x00\t\xf6\xc78\x00\x00\x00\x00\n\xe6\xaa(\x00\x00\x00\x00\v֩8\x00\x00\x00\x00\fƌ(\x00\x00\x00\x00\x11\x9b9" + - "8\x00\x00\x00\x00\x12ol\xa8\x01\x03\x02\x03\x02\x03\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01" + - "\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x00\x00jr\x00\x00\x00\x00p\x80\x00\x04\x00\x00\x8c\xa0\x01\b\x00\x00~\x90\x00\f\x00\x00~\x90\x01\x10LMT\x00CST\x00+1" + - "0\x00+09\x00CDT\x00\nCST-8\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RS\xdd\\2a\x02\x00\x00a\x02\x00\x00\v\x00\x1c\x00Asia/AlmatyUT" + - "\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x003\x00\x00\x00\x05\x00\x00\x00" + - "\x10\xff\xff\xff\xff\xaa\x19{\xdc\xff\xff\xff\xff\xb5\xa3\xef0\x00\x00\x00\x00\x15'}\xa0\x00\x00\x00\x00\x16\x18\xb2\x10\x00\x00\x00\x00\x17\b\xb1 \x00\x00\x00\x00\x17\xf9\xe5\x90\x00\x00\x00\x00\x18\xe9\xe4\xa0\x00\x00\x00" + - "\x00\x19\xdb\x19\x10\x00\x00\x00\x00\x1a\xcci\xa0\x00\x00\x00\x00\x1b\xbcv\xc0\x00\x00\x00\x00\x1c\xacg\xc0\x00\x00\x00\x00\x1d\x9cX\xc0\x00\x00\x00\x00\x1e\x8cI\xc0\x00\x00\x00\x00\x1f|:\xc0\x00\x00\x00\x00 l+" + - "\xc0\x00\x00\x00\x00!\\\x1c\xc0\x00\x00\x00\x00\"L\r\xc0\x00\x00\x00\x00#;\xfe\xc0\x00\x00\x00\x00$+\xef\xc0\x00\x00\x00\x00%\x1b\xe0\xc0\x00\x00\x00\x00&\v\xd1\xc0\x00\x00\x00\x00'\x04\xfd@\x00\x00\x00" + - "\x00'\xf4\xee@\x00\x00\x00\x00(\xe4\xedP\x00\x00\x00\x00)x\x95P\x00\x00\x00\x00)\xd4\xd0@\x00\x00\x00\x00*\xc4\xc1@\x00\x00\x00\x00+\xb4\xb2@\x00\x00\x00\x00,\xa4\xa3@\x00\x00\x00\x00-\x94\x94" + - "@\x00\x00\x00\x00.\x84\x85@\x00\x00\x00\x00/tv@\x00\x00\x00\x000dg@\x00\x00\x00\x001]\x92\xc0\x00\x00\x00\x002rm\xc0\x00\x00\x00\x003=t\xc0\x00\x00\x00\x004RO\xc0\x00\x00\x00" + - "\x005\x1dV\xc0\x00\x00\x00\x00621\xc0\x00\x00\x00\x006\xfd8\xc0\x00\x00\x00\x008\x1bN@\x00\x00\x00\x008\xdd\x1a\xc0\x00\x00\x00\x009\xfb0@\x00\x00\x00\x00:\xbc\xfc\xc0\x00\x00\x00\x00;\xdb\x12" + - "@\x00\x00\x00\x00<\xa6\x19@\x00\x00\x00\x00=\xba\xf4@\x00\x00\x00\x00>\x85\xfb@\x00\x00\x00\x00?\x9a\xd6@\x00\x00\x00\x00@e\xdd@\x00\x00\x00\x00A\x83\xf2\xc0\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x00\x00H$\x00\x00\x00\x00FP\x00\x04\x00\x00bp\x01\b\x00\x00" + - "T`\x00\f\x00\x00T`\x01\fLMT\x00+05\x00+07\x00+06\x00\n<+06>-6\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RѾ\xa8\xc7u\x02\x00\x00u\x02\x00" + - "\x00\f\x00\x1c\x00Asia/TbilisiUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004\x00\x00\x00\x06\x00\x00\x00\x15\xff\xff\xff\xffV\xb6\xba\x01\xff\xff\xff\xff\xaa\x19\x9a\x01\xff\xff\xff\xff\xe7\xda\fP\x00\x00\x00\x00\x15'\x99\xc0\x00\x00\x00\x00\x16\x18\xce0" + - "\x00\x00\x00\x00\x17\b\xcd@\x00\x00\x00\x00\x17\xfa\x01\xb0\x00\x00\x00\x00\x18\xea\x00\xc0\x00\x00\x00\x00\x19\xdb50\x00\x00\x00\x00\x1a̅\xc0\x00\x00\x00\x00\x1b\xbc\x92\xe0\x00\x00\x00\x00\x1c\xac\x83\xe0\x00\x00\x00\x00" + - "\x1d\x9ct\xe0\x00\x00\x00\x00\x1e\x8ce\xe0\x00\x00\x00\x00\x1f|V\xe0\x00\x00\x00\x00 lG\xe0\x00\x00\x00\x00!\\8\xe0\x00\x00\x00\x00\"L)\xe0\x00\x00\x00\x00#<\x1a\xe0\x00\x00\x00\x00$,\v\xe0" + - "\x00\x00\x00\x00%\x1b\xfc\xe0\x00\x00\x00\x00&\v\xed\xe0\x00\x00\x00\x00'\x05\x19`\x00\x00\x00\x00'\xf5\n`\x00\x00\x00\x00(\xe5\tp\x00\x00\x00\x00)\xd4\xdeP\x00\x00\x00\x00*\xc4\xc1@\x00\x00\x00\x00" + - "+\xb4\xc0P\x00\x00\x00\x00,\xa4\xa3@\x00\x00\x00\x00-\x94\xa2P\x00\x00\x00\x00.\x84\x85@\x00\x00\x00\x00/tv@\x00\x00\x00\x000dY0\x00\x00\x00\x001]\x92\xc0\x00\x00\x00\x003=f\xb0" + - "\x00\x00\x00\x004RA\xb0\x00\x00\x00\x005\x1dV\xc0\x00\x00\x00\x0062#\xb0\x00\x00\x00\x006\xfd8\xc0\x00\x00\x00\x008\x1b@0\x00\x00\x00\x008\xdd\x1a\xc0\x00\x00\x00\x009\xfb\"0\x00\x00\x00\x00" + - ":\xbc\xfc\xc0\x00\x00\x00\x00;\xdb\x040\x00\x00\x00\x00<\xa6\x19@\x00\x00\x00\x00=\xba\xe60\x00\x00\x00\x00>\x85\xfb@\x00\x00\x00\x00?\x9a\xc80\x00\x00\x00\x00@e\xdd@\x00\x00\x00\x00@\xddǰ" + - "\x00\x00\x00\x00A\x84\x1c\xf0\x00\x00\x00\x00BE\xe9p\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x05\x02\x05\x02\x05\x02\x05\x04\x03\x04\x03\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04" + - "\x03\x04\x03\x04\x03\x05\x02\x04\x00\x00)\xff\x00\x00\x00\x00)\xff\x00\x04\x00\x00*0\x00\t\x00\x00FP\x01\r\x00\x008@\x00\x11\x00\x008@\x01\x11LMT\x00TBMT\x00+03\x00+05" + - "\x00+04\x00\n<+04>-4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x88\xf6C\x84\x98\x00\x00\x00\x98\x00\x00\x00\x0f\x00\x1c\x00Asia/Phnom_PenhU" + - "T\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00" + - "\x00\f\xff\xff\xff\xffV\xb6\x85\xc4\xff\xff\xff\xff\xa2jg\xc4\x01\x02\x00\x00^<\x00\x00\x00\x00^<\x00\x04\x00\x00bp\x00\bLMT\x00BMT\x00+07\x00\n<+07>-7\nP" + - "K\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x1d?v\f\x17\x03\x00\x00\x17\x03\x00\x00\n\x00\x1c\x00Asia/MacauUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03" + - "\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + - "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\x85i[\x8e\xff\xff\xff\xff\xcbGu\xf0\xff\xff" + - "\xff\xff\xcb\xf2\xca\xe0\xff\xff\xff\xff\xcc\xfb\xbaP\xff\xff\xff\xff\xcd\xd3\xfe`\xff\xff\xff\xffΝ\xa5\xd0\xff\xff\xff\xff\xd2azp\xff\xff\xff\xff\xd3x\xf8p\xff\xff\xff\xff\xd4B\xad\xf0\xff\xff\xff\xff\xd5K" + - "\xabp\xff\xff\xff\xff\xd6tL\xf0\xff\xff\xff\xff\xd7?S\xf0\xff\xff\xff\xff\xd8/D\xf0\xff\xff\xff\xff\xd8\xf8\xfap\xff\xff\xff\xff\xda\r\xd5p\xff\xff\xff\xff\xda\xd8\xdcp\xff\xff\xff\xff\xdb\xed\xb7p\xff\xff" + - "\xff\xffܸ\xbep\xff\xff\xff\xff\xdd\xce\xea\xf0\xff\xff\xff\xffޡ\xda\xf0\xff\xff\xff\xff߶\xb5\xf0\xff\xff\xff\xff\xe0\x81\xbc\xf0\xff\xff\xff\xffᖗ\xf0\xff\xff\xff\xff\xe2O)\xf0\xff\xff\xff\xff\xe3v" + - "y\xf0\xff\xff\xff\xff\xe4/\v\xf0\xff\xff\xff\xff\xe5_\x96p\xff\xff\xff\xff\xe6\x0e\xed\xf0\xff\xff\xff\xff\xe7?\xa9\xa8\xff\xff\xff\xff\xe7\xf8I\xb8\xff\xff\xff\xff\xe9\x1f\x8b\xa8\xff\xff\xff\xff\xe9\xd8+\xb8\xff\xff" + - "\xff\xff\xea\xffm\xa8\xff\xff\xff\xff\xeb\xb8\r\xb8\xff\xff\xff\xff\xec\xdfO\xa8\xff\xff\xff\xff\xed\x97\xef\xb8\xff\xff\xff\xff\xee\xc8l(\xff\xff\xff\xff\xefwѸ\xff\xff\xff\xff\xf0\xa8N(\xff\xff\xff\xff\xf1W" + - "\xb3\xb8\xff\xff\xff\xff\xf2\x880(\xff\xff\xff\xff\xf3@\xd08\xff\xff\xff\xff\xf4h\x12(\xff\xff\xff\xff\xf5 \xb28\xff\xff\xff\xff\xf6G\xf4(\xff\xff\xff\xff\xf7%~8\xff\xff\xff\xff\xf8\x15S\x18\xff\xff" + - "\xff\xff\xf9\x05`8\xff\xff\xff\xff\xf9\xf55\x18\xff\xff\xff\xff\xfa\xe5B8\xff\xff\xff\xff\xfb\xde_\xa8\xff\xff\xff\xff\xfc\xce^\xb8\xff\xff\xff\xff\xfd\xbeA\xa8\xff\xff\xff\xff\xfe\xae@\xb8\xff\xff\xff\xff\xff\x9e" + - "#\xa8\x00\x00\x00\x00\x00\x8e\"\xb8\x00\x00\x00\x00\x01~\x05\xa8\x00\x00\x00\x00\x02n\x04\xb8\x00\x00\x00\x00\x03]\xe7\xa8\x00\x00\x00\x00\x04M\xe6\xb8\x00\x00\x00\x00\x05G\x04(\x00\x00\x00\x00\x067\x038\x00\x00" + - "\x00\x00\a&\xe6(\x00\x00\x00\x00\a\x83=8\x00\x00\x00\x00\t\x06\xc8(\x00\x00\x00\x00\t\xf6\xc78\x00\x00\x00\x00\n\xe6\xaa(\x00\x00\x00\x00\v֩8\x00\x00\x00\x00\fƌ(\x00\x00\x00\x00\x11\x9b" + - "98\x00\x00\x00\x00\x12ol\xa8\x01\x03\x02\x03\x02\x03\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04" + - "\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x00\x00jr\x00\x00\x00\x00p\x80\x00\x04\x00\x00\x8c\xa0\x01\b\x00\x00~\x90\x00\f\x00\x00~\x90\x01\x10LMT\x00CST\x00+" + - "10\x00+09\x00CDT\x00\nCST-8\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xe4_P\x18\xef\x02\x00\x00\xef\x02\x00\x00\f\x00\x1c\x00Asia/Magadan" + - "UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00B\x00\x00\x00\x06\x00" + - "\x00\x00\x10\xff\xff\xff\xff\xaa\x196\xa0\xff\xff\xff\xff\xb5\xa3\xa8\xe0\x00\x00\x00\x00\x15'7P\x00\x00\x00\x00\x16\x18k\xc0\x00\x00\x00\x00\x17\bj\xd0\x00\x00\x00\x00\x17\xf9\x9f@\x00\x00\x00\x00\x18\xe9\x9eP\x00" + - "\x00\x00\x00\x19\xda\xd2\xc0\x00\x00\x00\x00\x1a\xcc#P\x00\x00\x00\x00\x1b\xbc0p\x00\x00\x00\x00\x1c\xac!p\x00\x00\x00\x00\x1d\x9c\x12p\x00\x00\x00\x00\x1e\x8c\x03p\x00\x00\x00\x00\x1f{\xf4p\x00\x00\x00\x00 " + - "k\xe5p\x00\x00\x00\x00![\xd6p\x00\x00\x00\x00\"K\xc7p\x00\x00\x00\x00#;\xb8p\x00\x00\x00\x00$+\xa9p\x00\x00\x00\x00%\x1b\x9ap\x00\x00\x00\x00&\v\x8bp\x00\x00\x00\x00'\x04\xb6\xf0\x00" + - "\x00\x00\x00'\xf4\xa7\xf0\x00\x00\x00\x00(\xe4\xa7\x00\x00\x00\x00\x00)xO\x00\x00\x00\x00\x00)ԉ\xf0\x00\x00\x00\x00*\xc4z\xf0\x00\x00\x00\x00+\xb4k\xf0\x00\x00\x00\x00,\xa4\\\xf0\x00\x00\x00\x00-" + - "\x94M\xf0\x00\x00\x00\x00.\x84>\xf0\x00\x00\x00\x00/t/\xf0\x00\x00\x00\x000d \xf0\x00\x00\x00\x001]Lp\x00\x00\x00\x002r'p\x00\x00\x00\x003=.p\x00\x00\x00\x004R\tp\x00" + - "\x00\x00\x005\x1d\x10p\x00\x00\x00\x0061\xebp\x00\x00\x00\x006\xfc\xf2p\x00\x00\x00\x008\x1b\a\xf0\x00\x00\x00\x008\xdc\xd4p\x00\x00\x00\x009\xfa\xe9\xf0\x00\x00\x00\x00:\xbc\xb6p\x00\x00\x00\x00;" + - "\xda\xcb\xf0\x00\x00\x00\x00<\xa5\xd2\xf0\x00\x00\x00\x00=\xba\xad\xf0\x00\x00\x00\x00>\x85\xb4\xf0\x00\x00\x00\x00?\x9a\x8f\xf0\x00\x00\x00\x00@e\x96\xf0\x00\x00\x00\x00A\x83\xacp\x00\x00\x00\x00BEx\xf0\x00" + - "\x00\x00\x00Cc\x8ep\x00\x00\x00\x00D%Z\xf0\x00\x00\x00\x00ECpp\x00\x00\x00\x00F\x05<\xf0\x00\x00\x00\x00G#Rp\x00\x00\x00\x00G\xeeYp\x00\x00\x00\x00I\x034p\x00\x00\x00\x00I" + - "\xce;p\x00\x00\x00\x00J\xe3\x16p\x00\x00\x00\x00K\xae\x1dp\x00\x00\x00\x00L\xcc2\xf0\x00\x00\x00\x00M\x8d\xffp\x00\x00\x00\x00TK\xac\xe0\x00\x00\x00\x00W\x1b\x9c\x00\x01\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x05\x01\x03\x00\x00\x8d" + - "`\x00\x00\x00\x00\x8c\xa0\x00\x04\x00\x00\xa8\xc0\x01\b\x00\x00\x9a\xb0\x00\f\x00\x00\x9a\xb0\x01\f\x00\x00\xa8\xc0\x00\bLMT\x00+10\x00+12\x00+11\x00\n<+11>-11\nP" + - "K\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xdav\x19z\x98\x00\x00\x00\x98\x00\x00\x00\n\x00\x1c\x00Asia/QatarUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03" + - "\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + - "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\xa1\xf2\x9d0\x00\x00\x00\x00\x04\x8a\x92\xc0\x01\x02" + - "\x00\x000P\x00\x00\x00\x008@\x00\x04\x00\x00*0\x00\bLMT\x00+04\x00+03\x00\n<+03>-3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x9a\x1a\xdc\xca\xdc\x00\x00" + - "\x00\xdc\x00\x00\x00\r\x00\x1c\x00Asia/CalcuttaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xff\xa1\xf2]\x90\xff\xff\xff\xff\xba\x16Ր\xff\xff\xff\xffˈ\x1d\x80\xff" + + "\xff\xff\xff\xd2V\xeep\x01\x02\x03\x04\x00\x00o\xf0\x00\x00\x00\x00o\xf0\x00\x04\x00\x00p\x80\x00\b\x00\x00~\x90\x00\f\x00\x00p\x80\x00\x10LMT\x00MMT\x00+08\x00+09\x00WIT" + + "A\x00\nWITA-8\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x9e\x88|`\x9a\x03\x00\x00\x9a\x03\x00\x00\n\x00\x1c\x00Asia/AmmanUT\t\x00\x03\x82\x0f\x8ba\x82" + + "\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00" + + "\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00U\x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff\xff\xb6\xa3\xd6" + + "\xd0\x00\x00\x00\x00\x06ry\xe0\x00\x00\x00\x00\a\f\xabP\x00\x00\x00\x00\b$7`\x00\x00\x00\x00\b\xed\xde\xd0\x00\x00\x00\x00\n\x05j\xe0\x00\x00\x00\x00\n\xcf\x12P\x00\x00\x00\x00\v\xe7\xef\xe0\x00\x00\x00" + + "\x00\f\xdau\xd0\x00\x00\x00\x00\r\xc9#`\x00\x00\x00\x00\x0e\x92\xca\xd0\x00\x00\x00\x00\x0f\xa9\x05`\x00\x00\x00\x00\x10r\xac\xd0\x00\x00\x00\x00\x1c\xad\xd5`\x00\x00\x00\x00\x1d\x9f\t\xd0\x00\x00\x00\x00\x1e\x92\xfd" + + "`\x00\x00\x00\x00\x1f\x82\xe0P\x00\x00\x00\x00 r\xdf`\x00\x00\x00\x00!b\xc2P\x00\x00\x00\x00\"R\xc1`\x00\x00\x00\x00#K\xde\xd0\x00\x00\x00\x00$d\xbc`\x00\x00\x00\x00%+\xc0\xd0\x00\x00\x00" + + "\x00&7o`\x00\x00\x00\x00'\v\xa2\xd0\x00\x00\x00\x00(\vs\xe0\x00\x00\x00\x00(\xe2JP\x00\x00\x00\x00)\xe4\xbe`\x00\x00\x00\x00*\xcbf\xd0\x00\x00\x00\x00+\xbbe\xe0\x00\x00\x00\x00,\xabH" + + "\xd0\x00\x00\x00\x00-\x9bG\xe0\x00\x00\x00\x00.x\xb5\xd0\x00\x00\x00\x00/\x84d`\x00\x00\x00\x000X\xa5\xe0\x00\x00\x00\x001dF`\x00\x00\x00\x002A\xc2`\x00\x00\x00\x003D(`\x00\x00\x00" + + "\x004!\xa4`\x00\x00\x00\x005$\n`\x00\x00\x00\x006\x01\x86`\x00\x00\x00\x007z\x93`\x00\x00\x00\x007\xea\xa2\xe0\x00\x00\x00\x008\xe2|\xe0\x00\x00\x00\x009ӿ`\x00\x00\x00\x00:\xc2^" + + "\xe0\x00\x00\x00\x00;\xb3\xa1`\x00\x00\x00\x00<\xa3\x92`\x00\x00\x00\x00=\x93\x83`\x00\x00\x00\x00>\x83t`\x00\x00\x00\x00?\x98O`\x00\x00\x00\x00@cV`\x00\x00\x00\x00An\xf6\xe0\x00\x00\x00" + + "\x00BLr\xe0\x00\x00\x00\x00C\xf0\x00\x00\x00\x00/t>\x00\x00\x00\x00\x000" + - "d \xf0\x00\x00\x00\x001]Z\x80\x00\x00\x00\x002M=p\x00\x00\x00\x003=<\x80\x00\x00\x00\x004-\x1fp\x00\x00\x00\x005\x1d\x1e\x80\x00\x00\x00\x006\r\x01p\x00\x00\x00\x00:鳠\x00" + - "\x00\x00\x00;\xb4\xac\x90\x00\x00\x00\x00<\xa4\xab\xa0\x00\x00\x00\x00=\x94\x8e\x90\x00\x00\x00\x00>\x84\x8d\xa0\x00\x00\x00\x00?tp\x90\x00\x00\x00\x00@do\xa0\x00\x00\x00\x00ATR\x90\x00\x00\x00\x00B" + - "DQ\xa0\x00\x00\x00\x00C44\x90\x00\x00\x00\x00D$3\xa0\x00\x00\x00\x00E\x1dQ\x10\x00\x00\x00\x00U\x15\x9a\xa0\x00\x00\x00\x00V\x05ap\x00\x00\x00\x00V\xf5|\xa0\x00\x00\x00\x00W\xe5Cp\x01" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x00\x00d4\x00\x00\x00\x00bp\x00" + - "\x04\x00\x00~\x90\x01\b\x00\x00p\x80\x00\fLMT\x00+07\x00+09\x00+08\x00\n<+08>-8\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xa4Zߐ\xe6\x02\x00\x00" + - "\xe6\x02\x00\x00\x12\x00\x1c\x00Asia/SrednekolymskUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00A\x00\x00\x00\x06\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x193\xe4\xff\xff\xff\xff\xb5\xa3\xa8\xe0\x00\x00\x00\x00\x15'7P\x00\x00\x00\x00\x16\x18k" + - "\xc0\x00\x00\x00\x00\x17\bj\xd0\x00\x00\x00\x00\x17\xf9\x9f@\x00\x00\x00\x00\x18\xe9\x9eP\x00\x00\x00\x00\x19\xda\xd2\xc0\x00\x00\x00\x00\x1a\xcc#P\x00\x00\x00\x00\x1b\xbc0p\x00\x00\x00\x00\x1c\xac!p\x00\x00\x00" + - "\x00\x1d\x9c\x12p\x00\x00\x00\x00\x1e\x8c\x03p\x00\x00\x00\x00\x1f{\xf4p\x00\x00\x00\x00 k\xe5p\x00\x00\x00\x00![\xd6p\x00\x00\x00\x00\"K\xc7p\x00\x00\x00\x00#;\xb8p\x00\x00\x00\x00$+\xa9" + - "p\x00\x00\x00\x00%\x1b\x9ap\x00\x00\x00\x00&\v\x8bp\x00\x00\x00\x00'\x04\xb6\xf0\x00\x00\x00\x00'\xf4\xa7\xf0\x00\x00\x00\x00(\xe4\xa7\x00\x00\x00\x00\x00)xO\x00\x00\x00\x00\x00)ԉ\xf0\x00\x00\x00" + - "\x00*\xc4z\xf0\x00\x00\x00\x00+\xb4k\xf0\x00\x00\x00\x00,\xa4\\\xf0\x00\x00\x00\x00-\x94M\xf0\x00\x00\x00\x00.\x84>\xf0\x00\x00\x00\x00/t/\xf0\x00\x00\x00\x000d \xf0\x00\x00\x00\x001]L" + - "p\x00\x00\x00\x002r'p\x00\x00\x00\x003=.p\x00\x00\x00\x004R\tp\x00\x00\x00\x005\x1d\x10p\x00\x00\x00\x0061\xebp\x00\x00\x00\x006\xfc\xf2p\x00\x00\x00\x008\x1b\a\xf0\x00\x00\x00" + - "\x008\xdc\xd4p\x00\x00\x00\x009\xfa\xe9\xf0\x00\x00\x00\x00:\xbc\xb6p\x00\x00\x00\x00;\xda\xcb\xf0\x00\x00\x00\x00<\xa5\xd2\xf0\x00\x00\x00\x00=\xba\xad\xf0\x00\x00\x00\x00>\x85\xb4\xf0\x00\x00\x00\x00?\x9a\x8f" + - "\xf0\x00\x00\x00\x00@e\x96\xf0\x00\x00\x00\x00A\x83\xacp\x00\x00\x00\x00BEx\xf0\x00\x00\x00\x00Cc\x8ep\x00\x00\x00\x00D%Z\xf0\x00\x00\x00\x00ECpp\x00\x00\x00\x00F\x05<\xf0\x00\x00\x00" + - "\x00G#Rp\x00\x00\x00\x00G\xeeYp\x00\x00\x00\x00I\x034p\x00\x00\x00\x00I\xce;p\x00\x00\x00\x00J\xe3\x16p\x00\x00\x00\x00K\xae\x1dp\x00\x00\x00\x00L\xcc2\xf0\x00\x00\x00\x00M\x8d\xff" + - "p\x00\x00\x00\x00TK\xac\xe0\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x05\x03\x00\x00\x90\x1c\x00\x00\x00\x00\x8c\xa0\x00\x04\x00\x00\xa8\xc0\x01\b\x00\x00\x9a\xb0\x00\f\x00\x00\x9a\xb0\x01\f\x00\x00\xa8\xc0\x00\bLMT\x00+10\x00+1" + - "2\x00+11\x00\n<+11>-11\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xdb\xfa\xb5\xbeg\x02\x00\x00g\x02\x00\x00\v\x00\x1c\x00Asia/AqtobeUT\t" + - "\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x003\x00\x00\x00\x06\x00\x00\x00\x10" + - "\xff\xff\xff\xff\xaa\x19\x8eh\xff\xff\xff\xff\xb5\xa3\xfd@\x00\x00\x00\x00\x15'\x8b\xb0\x00\x00\x00\x00\x16\x18\xc0 \x00\x00\x00\x00\x17\b\xb1 \x00\x00\x00\x00\x17\xf9\xf3\xa0\x00\x00\x00\x00\x18\xe9\xf2\xb0\x00\x00\x00\x00" + - "\x19\xdb' \x00\x00\x00\x00\x1a\xccw\xb0\x00\x00\x00\x00\x1b\xbc\x84\xd0\x00\x00\x00\x00\x1c\xacu\xd0\x00\x00\x00\x00\x1d\x9cf\xd0\x00\x00\x00\x00\x1e\x8cW\xd0\x00\x00\x00\x00\x1f|H\xd0\x00\x00\x00\x00 l9\xd0" + - "\x00\x00\x00\x00!\\*\xd0\x00\x00\x00\x00\"L\x1b\xd0\x00\x00\x00\x00#<\f\xd0\x00\x00\x00\x00$+\xfd\xd0\x00\x00\x00\x00%\x1b\xee\xd0\x00\x00\x00\x00&\v\xdf\xd0\x00\x00\x00\x00'\x05\vP\x00\x00\x00\x00" + - "'\xf4\xfcP\x00\x00\x00\x00(\xe4\xfb`\x00\x00\x00\x00)x\xa3`\x00\x00\x00\x00)\xd4\xdeP\x00\x00\x00\x00*\xc4\xcfP\x00\x00\x00\x00+\xb4\xc0P\x00\x00\x00\x00,\xa4\xb1P\x00\x00\x00\x00-\x94\xa2P" + - "\x00\x00\x00\x00.\x84\x93P\x00\x00\x00\x00/t\x84P\x00\x00\x00\x000duP\x00\x00\x00\x001]\xa0\xd0\x00\x00\x00\x002r{\xd0\x00\x00\x00\x003=\x82\xd0\x00\x00\x00\x004R]\xd0\x00\x00\x00\x00" + - "5\x1dd\xd0\x00\x00\x00\x0062?\xd0\x00\x00\x00\x006\xfdF\xd0\x00\x00\x00\x008\x1b\\P\x00\x00\x00\x008\xdd(\xd0\x00\x00\x00\x009\xfb>P\x00\x00\x00\x00:\xbd\n\xd0\x00\x00\x00\x00;\xdb P" + - "\x00\x00\x00\x00<\xa6'P\x00\x00\x00\x00=\xbb\x02P\x00\x00\x00\x00>\x86\tP\x00\x00\x00\x00?\x9a\xe4P\x00\x00\x00\x00@e\xebP\x00\x00\x00\x00A\x84\x00\xd0\x01\x02\x03\x04\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x00\x005\x98\x00\x00\x00\x008@\x00\x04\x00\x00FP\x00\b\x00\x00T" + - "`\x01\f\x00\x00T`\x00\f\x00\x00FP\x01\bLMT\x00+04\x00+05\x00+06\x00\n<+05>-5\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rw\x86\x8d^\x03\x03" + - "\x00\x00\x03\x03\x00\x00\r\x00\x1c\x00Asia/Ust-NeraUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x006\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffi\x86\xb1\xdc\xff\xff\xff\xff\x9e0<\xe0\x00\x00\x00\x00\x170hP\x00\x00\x00\x00\x17\xfa\x0f\xc0\x00\x00\x00" + + "\x00\x18\xe8\xbdP\x00\x00\x00\x00\x19\xdbC@\x00\x00\x00\x00\x1a̓\xd0\x00\x00\x00\x00\x1b\xbd\xc8@\x00\x00\x00\x00\x1c\xad\xc7P\x00\x00\x00\x00\x1d\x9ct\xe0\x00\x00\x00\x00\x1e\x8ce\xe0\x00\x00\x00\x00\x1f|V" + + "\xe0\x00\x00\x00\x00 lG\xe0\x00\x00\x00\x00!\\8\xe0\x00\x00\x00\x00\"L)\xe0\x00\x00\x00\x00#<\x1a\xe0\x00\x00\x00\x00$,\v\xe0\x00\x00\x00\x00%\x1b\xfc\xe0\x00\x00\x00\x00&\v\xed\xe0\x00\x00\x00" + + "\x00'\x05\x19`\x00\x00\x00\x00'\xf6x\x00\x00\x00\x00\x00(纀\x00\x00\x00\x00)\xd8\xfd\x00\x00\x00\x00\x00*\xca?\x80\x00\x00\x00\x00+\xba0\x80\x00\x00\x00\x00,\xabs\x00\x00\x00\x00\x00-\x9bd" + + "\x00\x00\x00\x00\x00.\x8c\xa6\x80\x00\x00\x00\x00/|\x97\x80\x00\x00\x00\x000m\xda\x00\x00\x00\x00\x001_\x1c\x80\x00\x00\x00\x002P_\x00\x00\x00\x00\x003@P\x00\x00\x00\x00\x0041\x92\x80\x00\x00\x00" + + "\x005!\x83\x80\x00\x00\x00\x006\x12\xc6\x00\x00\x00\x00\x007\x02\xb7\x00\x00\x00\x00\x007\xf3\xf9\x80\x00\x00\x00\x008\xe5<\x00\x00\x00\x00\x009\xd6~\x80\x00\x00\x00\x00:\xc6o\x80\x00\x00\x00\x00;\xb7\xb2" + + "\x00\x00\x00\x00\x00<\xa7\xa3\x00\x00\x00\x00\x00=\x98\xe5\x80\x00\x00\x00\x00>\x88ր\x00\x00\x00\x00?z\x19\x00\x00\x00\x00\x00@k[\x80\x00\x00\x00\x00A\\\x9e\x00\x00\x00\x00\x00BL\x8f\x00\x00\x00\x00" + + "\x00C=р\x00\x00\x00\x00D-\u0080\x00\x00\x00\x00E\x1f\x05\x00\x00\x00\x00\x00F\x0e\xf6\x00\x00\x00\x00\x00G\x008\x80\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x00\x00)\xa4\x00\x00\x00\x00)\xa0\x00\x04\x00\x00*0\x00\b\x00\x008@\x01\fLMT\x00B" + + "MT\x00+03\x00+04\x00\n<+03>-3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS.>[K\xab\x00\x00\x00\xab\x00\x00\x00\r\x00\x1c\x00Asia/Jayap" + + "uraUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00" + + "\x00\x04\x00\x00\x00\x12\xff\xff\xff\xff\xba\x16\xc1\x98\xff\xff\xff\xff\xd0X\xb9\xf0\xff\xff\xff\xff\xf4\xb5\xa2h\x01\x02\x03\x00\x00\x83\xe8\x00\x00\x00\x00~\x90\x00\x04\x00\x00\x85\x98\x00\b\x00\x00~\x90\x00\x0eLMT" + + "\x00+09\x00+0930\x00WIT\x00\nWIT-9\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iST\x81\x18G^\x02\x00\x00^\x02\x00\x00\n\x00\x1c\x00Asia/Aqt" + + "auUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x002\x00\x00\x00" + + "\x06\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x19\x94\xe0\xff\xff\xff\xff\xb5\xa3\xfd@\x00\x00\x00\x00\x16\x18\xce0\x00\x00\x00\x00\x17\b\xb1 \x00\x00\x00\x00\x17\xf9\xf3\xa0\x00\x00\x00\x00\x18\xe9\xf2\xb0\x00\x00\x00\x00\x19\xdb'" + + " \x00\x00\x00\x00\x1a\xccw\xb0\x00\x00\x00\x00\x1b\xbc\x84\xd0\x00\x00\x00\x00\x1c\xacu\xd0\x00\x00\x00\x00\x1d\x9cf\xd0\x00\x00\x00\x00\x1e\x8cW\xd0\x00\x00\x00\x00\x1f|H\xd0\x00\x00\x00\x00 l9\xd0\x00\x00\x00" + + "\x00!\\*\xd0\x00\x00\x00\x00\"L\x1b\xd0\x00\x00\x00\x00#<\f\xd0\x00\x00\x00\x00$+\xfd\xd0\x00\x00\x00\x00%\x1b\xee\xd0\x00\x00\x00\x00&\v\xdf\xd0\x00\x00\x00\x00'\x05\vP\x00\x00\x00\x00'\xf4\xfc" + + "P\x00\x00\x00\x00(\xe4\xfb`\x00\x00\x00\x00)x\xa3`\x00\x00\x00\x00)\xd4\xdeP\x00\x00\x00\x00*\xc4\xcfP\x00\x00\x00\x00+\xb4\xc0P\x00\x00\x00\x00,\xa4\xb1P\x00\x00\x00\x00-\x94\xa2P\x00\x00\x00" + + "\x00.\x84\x93P\x00\x00\x00\x00/t\x92`\x00\x00\x00\x000d\x83`\x00\x00\x00\x001]\xae\xe0\x00\x00\x00\x002r\x89\xe0\x00\x00\x00\x003=\x90\xe0\x00\x00\x00\x004Rk\xe0\x00\x00\x00\x005\x1dr" + + "\xe0\x00\x00\x00\x0062M\xe0\x00\x00\x00\x006\xfdT\xe0\x00\x00\x00\x008\x1bj`\x00\x00\x00\x008\xdd6\xe0\x00\x00\x00\x009\xfbL`\x00\x00\x00\x00:\xbd\x18\xe0\x00\x00\x00\x00;\xdb.`\x00\x00\x00" + + "\x00<\xa65`\x00\x00\x00\x00=\xbb\x10`\x00\x00\x00\x00>\x86\x17`\x00\x00\x00\x00?\x9a\xf2`\x00\x00\x00\x00@e\xf9`\x00\x00\x00\x00A\x84\x0e\xe0\x01\x02\x03\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02" + + "\x04\x02\x04\x02\x04\x02\x05\x01\x02\x04\x02\x04\x02\x04\x01\x05\x01\x05\x01\x05\x01\x05\x01\x05\x01\x05\x01\x05\x01\x05\x01\x05\x01\x05\x02\x00\x00/ \x00\x00\x00\x008@\x00\x04\x00\x00FP\x00\b\x00\x00T`\x00\f\x00" + + "\x00T`\x01\f\x00\x00FP\x01\bLMT\x00+04\x00+05\x00+06\x00\n<+05>-5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS)\x15II\xf3\x02\x00\x00\xf3\x02" + + "\x00\x00\r\x00\x1c\x00Asia/SakhalinUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00B\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xff\x86\xf0\u0378\xff\xff\xff\xff\xd20\xb2\xf0\x00\x00\x00\x00\x15'7P\x00\x00\x00\x00\x16\x18k\xc0\x00\x00\x00\x00\x17\b" + + "j\xd0\x00\x00\x00\x00\x17\xf9\x9f@\x00\x00\x00\x00\x18\xe9\x9eP\x00\x00\x00\x00\x19\xda\xd2\xc0\x00\x00\x00\x00\x1a\xcc#P\x00\x00\x00\x00\x1b\xbc0p\x00\x00\x00\x00\x1c\xac!p\x00\x00\x00\x00\x1d\x9c\x12p\x00\x00" + + "\x00\x00\x1e\x8c\x03p\x00\x00\x00\x00\x1f{\xf4p\x00\x00\x00\x00 k\xe5p\x00\x00\x00\x00![\xd6p\x00\x00\x00\x00\"K\xc7p\x00\x00\x00\x00#;\xb8p\x00\x00\x00\x00$+\xa9p\x00\x00\x00\x00%\x1b" + + "\x9ap\x00\x00\x00\x00&\v\x8bp\x00\x00\x00\x00'\x04\xb6\xf0\x00\x00\x00\x00'\xf4\xa7\xf0\x00\x00\x00\x00(\xe4\xa7\x00\x00\x00\x00\x00)xO\x00\x00\x00\x00\x00)ԉ\xf0\x00\x00\x00\x00*\xc4z\xf0\x00\x00" + + "\x00\x00+\xb4k\xf0\x00\x00\x00\x00,\xa4\\\xf0\x00\x00\x00\x00-\x94M\xf0\x00\x00\x00\x00.\x84>\xf0\x00\x00\x00\x00/t/\xf0\x00\x00\x00\x000d \xf0\x00\x00\x00\x001]Lp\x00\x00\x00\x002r" + + "'p\x00\x00\x00\x003=.p\x00\x00\x00\x004R\x17\x80\x00\x00\x00\x005\x1d\x1e\x80\x00\x00\x00\x0061\xf9\x80\x00\x00\x00\x006\xfd\x00\x80\x00\x00\x00\x008\x1b\x16\x00\x00\x00\x00\x008\xdc\xe2\x80\x00\x00" + + "\x00\x009\xfa\xf8\x00\x00\x00\x00\x00:\xbcĀ\x00\x00\x00\x00;\xda\xda\x00\x00\x00\x00\x00<\xa5\xe1\x00\x00\x00\x00\x00=\xba\xbc\x00\x00\x00\x00\x00>\x85\xc3\x00\x00\x00\x00\x00?\x9a\x9e\x00\x00\x00\x00\x00@e" + + "\xa5\x00\x00\x00\x00\x00A\x83\xba\x80\x00\x00\x00\x00BE\x87\x00\x00\x00\x00\x00Cc\x9c\x80\x00\x00\x00\x00D%i\x00\x00\x00\x00\x00EC~\x80\x00\x00\x00\x00F\x05K\x00\x00\x00\x00\x00G#`\x80\x00\x00" + + "\x00\x00G\xeeg\x80\x00\x00\x00\x00I\x03B\x80\x00\x00\x00\x00I\xceI\x80\x00\x00\x00\x00J\xe3$\x80\x00\x00\x00\x00K\xae+\x80\x00\x00\x00\x00L\xccA\x00\x00\x00\x00\x00M\x8e\r\x80\x00\x00\x00\x00TK" + + "\xba\xf0\x00\x00\x00\x00V\xf6\xb2\x00\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x05\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04" + + "\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x03\x05\x03\x00\x00\x85\xc8\x00\x00\x00\x00~\x90\x00\x04\x00\x00\xa8\xc0\x01\b\x00\x00\x9a\xb0\x00\f\x00\x00\x9a\xb0\x01\f\x00\x00\x8c\xa0\x00\x10LMT\x00+09\x00" + + "+12\x00+11\x00+10\x00\n<+11>-11\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x03\x87\xb3<\xe8\x02\x00\x00\xe8\x02\x00\x00\t\x00\x1c\x00Asia/Bak" + + "uUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00B\x00\x00\x00\x05" + + "\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x19\x95D\xff\xff\xff\xff\xe7\xda\fP\x00\x00\x00\x00\x15'\x99\xc0\x00\x00\x00\x00\x16\x18\xce0\x00\x00\x00\x00\x17\b\xcd@\x00\x00\x00\x00\x17\xfa\x01\xb0\x00\x00\x00\x00\x18\xea\x00\xc0" + + "\x00\x00\x00\x00\x19\xdb50\x00\x00\x00\x00\x1a̅\xc0\x00\x00\x00\x00\x1b\xbc\x92\xe0\x00\x00\x00\x00\x1c\xac\x83\xe0\x00\x00\x00\x00\x1d\x9ct\xe0\x00\x00\x00\x00\x1e\x8ce\xe0\x00\x00\x00\x00\x1f|V\xe0\x00\x00\x00\x00" + + " lG\xe0\x00\x00\x00\x00!\\8\xe0\x00\x00\x00\x00\"L)\xe0\x00\x00\x00\x00#<\x1a\xe0\x00\x00\x00\x00$,\v\xe0\x00\x00\x00\x00%\x1b\xfc\xe0\x00\x00\x00\x00&\v\xed\xe0\x00\x00\x00\x00'\x05\x19`" + + "\x00\x00\x00\x00'\xf5\n`\x00\x00\x00\x00(\xe5\tp\x00\x00\x00\x00)\xd4\xfap\x00\x00\x00\x00*\xc4\xebp\x00\x00\x00\x001]\xd9\x10\x00\x00\x00\x002r\xb4\x10\x00\x00\x00\x003=\xad\x00\x00\x00\x00\x00" + + "4R\x88\x00\x00\x00\x00\x005\x1d\x8f\x00\x00\x00\x00\x0062j\x00\x00\x00\x00\x006\xfdq\x00\x00\x00\x00\x008\x1b\x86\x80\x00\x00\x00\x008\xddS\x00\x00\x00\x00\x009\xfbh\x80\x00\x00\x00\x00:\xbd5\x00" + + "\x00\x00\x00\x00;\xdbJ\x80\x00\x00\x00\x00<\xa6Q\x80\x00\x00\x00\x00=\xbb,\x80\x00\x00\x00\x00>\x863\x80\x00\x00\x00\x00?\x9b\x0e\x80\x00\x00\x00\x00@f\x15\x80\x00\x00\x00\x00A\x84+\x00\x00\x00\x00\x00" + + "BE\xf7\x80\x00\x00\x00\x00Cd\r\x00\x00\x00\x00\x00D%ـ\x00\x00\x00\x00EC\xef\x00\x00\x00\x00\x00F\x05\xbb\x80\x00\x00\x00\x00G#\xd1\x00\x00\x00\x00\x00G\xee\xd8\x00\x00\x00\x00\x00I\x03\xb3\x00" + + "\x00\x00\x00\x00Iκ\x00\x00\x00\x00\x00J\xe3\x95\x00\x00\x00\x00\x00K\xae\x9c\x00\x00\x00\x00\x00Ḻ\x80\x00\x00\x00\x00M\x8e~\x00\x00\x00\x00\x00N\xac\x93\x80\x00\x00\x00\x00On`\x00\x00\x00\x00\x00" + + "P\x8cu\x80\x00\x00\x00\x00QW|\x80\x00\x00\x00\x00RlW\x80\x00\x00\x00\x00S7^\x80\x00\x00\x00\x00TL9\x80\x00\x00\x00\x00U\x17@\x80\x00\x00\x00\x00V,\x1b\x80\x01\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x04\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x00\x00" + + ".\xbc\x00\x00\x00\x00*0\x00\x04\x00\x00FP\x01\b\x00\x008@\x00\f\x00\x008@\x01\fLMT\x00+03\x00+05\x00+04\x00\n<+04>-4\nPK\x03\x04\n\x00\x00" + + "\x00\x00\x00#\x82iS&\xe9\xd1\xd8q\x02\x00\x00q\x02\x00\x00\t\x00\x1c\x00Asia/OralUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00" + + "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x003\x00\x00\x00\a\x00\x00\x00\x14\xff\xff\xff\xff\xaa\x19\x93\xdc\xff\xff\xff\xff\xb5\xa4\vP\x00\x00\x00\x00\x15'\x8b\xb0\x00" + + "\x00\x00\x00\x16\x18\xc0 \x00\x00\x00\x00\x17\b\xb1 \x00\x00\x00\x00\x17\xf9\xf3\xa0\x00\x00\x00\x00\x18\xe9\xf2\xb0\x00\x00\x00\x00\x19\xdb' \x00\x00\x00\x00\x1a\xccw\xb0\x00\x00\x00\x00\x1b\xbc\x84\xd0\x00\x00\x00\x00\x1c" + + "\xacu\xd0\x00\x00\x00\x00\x1d\x9cf\xd0\x00\x00\x00\x00\x1e\x8cW\xd0\x00\x00\x00\x00\x1f|H\xd0\x00\x00\x00\x00 l9\xd0\x00\x00\x00\x00!\\*\xd0\x00\x00\x00\x00\"L\x1b\xd0\x00\x00\x00\x00#<\f\xd0\x00" + + "\x00\x00\x00$+\xfd\xd0\x00\x00\x00\x00%\x1b\xfc\xe0\x00\x00\x00\x00&\v\xed\xe0\x00\x00\x00\x00'\x05\x19`\x00\x00\x00\x00'\xf5\n`\x00\x00\x00\x00(\xe4\xfb`\x00\x00\x00\x00)x\xa3`\x00\x00\x00\x00)" + + "\xd4\xdeP\x00\x00\x00\x00*\xc4\xdd`\x00\x00\x00\x00+\xb4\xce`\x00\x00\x00\x00,\xa4\xbf`\x00\x00\x00\x00-\x94\xb0`\x00\x00\x00\x00.\x84\xa1`\x00\x00\x00\x00/t\x92`\x00\x00\x00\x000d\x83`\x00" + + "\x00\x00\x001]\xae\xe0\x00\x00\x00\x002r\x89\xe0\x00\x00\x00\x003=\x90\xe0\x00\x00\x00\x004Rk\xe0\x00\x00\x00\x005\x1dr\xe0\x00\x00\x00\x0062M\xe0\x00\x00\x00\x006\xfdT\xe0\x00\x00\x00\x008" + + "\x1bj`\x00\x00\x00\x008\xdd6\xe0\x00\x00\x00\x009\xfbL`\x00\x00\x00\x00:\xbd\x18\xe0\x00\x00\x00\x00;\xdb.`\x00\x00\x00\x00<\xa65`\x00\x00\x00\x00=\xbb\x10`\x00\x00\x00\x00>\x86\x17`\x00" + + "\x00\x00\x00?\x9a\xf2`\x00\x00\x00\x00@e\xf9`\x00\x00\x00\x00A\x84\x0e\xe0\x01\x02\x03\x04\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x06\x05\x06\x05\x06\x02\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06" + + "\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x02\x00\x000$\x00\x00\x00\x00*0\x00\x04\x00\x00FP\x00\b\x00\x00T`\x01\f\x00\x00T`\x00\f\x00\x00FP\x01\b\x00\x008@\x00\x10LMT\x00" + + "+03\x00+05\x00+06\x00+04\x00\n<+05>-5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x88\xf6C\x84\x98\x00\x00\x00\x98\x00\x00\x00\x0f\x00\x1c\x00Asia/" + + "Phnom_PenhUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xffV\xb6\x85\xc4\xff\xff\xff\xff\xa2jg\xc4\x01\x02\x00\x00^<\x00\x00\x00\x00^<\x00\x04\x00\x00bp\x00\bLMT\x00BMT\x00+07" + + "\x00\n<+07>-7\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS's\x96\x1en\x01\x00\x00n\x01\x00\x00\r\x00\x1c\x00Asia/DushanbeUT\t\x00\x03\x82\x0f" + + "\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff" + + "\xaa\x19\x83\x80\xff\xff\xff\xff\xb5\xa3\xef0\x00\x00\x00\x00\x15'}\xa0\x00\x00\x00\x00\x16\x18\xb2\x10\x00\x00\x00\x00\x17\b\xb1 \x00\x00\x00\x00\x17\xf9\xe5\x90\x00\x00\x00\x00\x18\xe9\xe4\xa0\x00\x00\x00\x00\x19\xdb\x19\x10" + + "\x00\x00\x00\x00\x1a\xcci\xa0\x00\x00\x00\x00\x1b\xbcv\xc0\x00\x00\x00\x00\x1c\xacg\xc0\x00\x00\x00\x00\x1d\x9cX\xc0\x00\x00\x00\x00\x1e\x8cI\xc0\x00\x00\x00\x00\x1f|:\xc0\x00\x00\x00\x00 l+\xc0\x00\x00\x00\x00" + + "!\\\x1c\xc0\x00\x00\x00\x00\"L\r\xc0\x00\x00\x00\x00#;\xfe\xc0\x00\x00\x00\x00$+\xef\xc0\x00\x00\x00\x00%\x1b\xe0\xc0\x00\x00\x00\x00&\v\xd1\xc0\x00\x00\x00\x00'\x04\xfd@\x00\x00\x00\x00'\xf4\xee@" + + "\x00\x00\x00\x00(ʏP\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x00\x00@\x80\x00\x00\x00\x00FP\x00\x04\x00\x00bp\x01\b\x00\x00T`\x00\f\x00\x00T`" + + "\x01\fLMT\x00+05\x00+07\x00+06\x00\n<+05>-5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x84)\r\xbd\xec\x00\x00\x00\xec\x00\x00\x00\x10\x00\x1c\x00Asi" + + "a/Ho_Chi_MinhUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xff\x88\x8cC\x80\xff\xff\xff\xff\x91\xa3+\n\xff\xff\xff\xff\xcd5\xe6\x80\xff\xff\xff\xff\xd1Y\xcep\xff\xff\xff\xff\xd2;>\xf0\xff\xff\xff\xff" + + "\xd52\xbb\x10\xff\xff\xff\xff\xe4\xb6\xe4\x80\xff\xff\xff\xff\xed/\x98\x00\x00\x00\x00\x00\n=\xc7\x00\x01\x02\x03\x04\x02\x03\x02\x03\x02\x00\x00d\x00\x00\x00\x00\x00c\xf6\x00\x04\x00\x00bp\x00\t\x00\x00p\x80\x00" + + "\r\x00\x00~\x90\x00\x11LMT\x00PLMT\x00+07\x00+08\x00+09\x00\n<+07>-7\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xc7X,Y\x9f\x01\x00\x00\x9f" + + "\x01\x00\x00\n\x00\x1c\x00Asia/SeoulUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00\x06\x00\x00\x00\x10\xff\xff\xff\xff\x8b\xd7\xf0x\xff\xff\xff\xff\x92\xe6\x16\xf8\xff\xff\xff\xff\xd2C'\xf0\xff\xff\xff\xff\xd7e\x8fp\xff\xff\xff\xff\xd7\xee\x9d`" + + "\xff\xff\xff\xff\xd8\xf8\xfap\xff\xff\xff\xff\xd9\xcd-\xe0\xff\xff\xff\xff\xda\u05ca\xf0\xff\xff\xff\xffۭ\x0f\xe0\xff\xff\xff\xff\xdc\xe6\xe2\xf0\xff\xff\xff\xff\u074c\xf1\xe0\xff\xff\xff\xff\xe2O)\xf0\xff\xff\xff\xff" + + "\xe4k\xb7\xf8\xff\xff\xff\xff\xe5\x13\x18h\xff\xff\xff\xff\xe6b\x03x\xff\xff\xff\xff\xe7\x11L\xe8\xff\xff\xff\xff\xe8/px\xff\xff\xff\xff\xe8\xe7\xf4h\xff\xff\xff\xff\xea\x0fRx\xff\xff\xff\xff\xea\xc7\xd6h" + + "\xff\xff\xff\xff\xeb\xef4x\xff\xff\xff\xff째h\xff\xff\xff\xff\xed\xcf\x16x\xff\xff\xff\xff\ue1dah\xff\xff\xff\xff\xf05qx\x00\x00\x00\x00 \xa3`\x90\x00\x00\x00\x00!ng\x90\x00\x00\x00\x00" + + "\"\x83B\x90\x00\x00\x00\x00#NI\x90\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x01\x05\x01\x05\x01\x05\x01\x05\x01\x05\x01\x05\x01\x04\x03\x04\x03\x04\x00\x00w\b\x00\x00\x00\x00w\x88\x00\x04\x00\x00~\x90\x00\b\x00" + + "\x00\x8c\xa0\x01\f\x00\x00~\x90\x00\x04\x00\x00\x85\x98\x01\fLMT\x00KST\x00JST\x00KDT\x00\nKST-9\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x8bSnT\xa1\x00" + + "\x00\x00\xa1\x00\x00\x00\r\x00\x1c\x00Asia/KatmanduUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00B\x00\x00\x00\b\x00\x00\x00\x18\xff\xff\xff\xff\xa1\xdbݺ\xff\xff\xff\xff\xb5\xa3\xc5\x00\x00\x00\x00\x00\x15'Sp\x00\x00\x00\x00\x16\x18k\xc0\x00\x00" + - "\x00\x00\x17\bj\xd0\x00\x00\x00\x00\x17\xf9\x9f@\x00\x00\x00\x00\x18\xe9\x9eP\x00\x00\x00\x00\x19\xda\xd2\xc0\x00\x00\x00\x00\x1a\xcc#P\x00\x00\x00\x00\x1b\xbc0p\x00\x00\x00\x00\x1c\xac!p\x00\x00\x00\x00\x1d\x9c" + - "\x12p\x00\x00\x00\x00\x1e\x8c\x03p\x00\x00\x00\x00\x1f{\xf4p\x00\x00\x00\x00 k\xe5p\x00\x00\x00\x00![\xd6p\x00\x00\x00\x00\"K\xc7p\x00\x00\x00\x00#;\xb8p\x00\x00\x00\x00$+\xa9p\x00\x00" + - "\x00\x00%\x1b\x9ap\x00\x00\x00\x00&\v\x8bp\x00\x00\x00\x00'\x04\xb6\xf0\x00\x00\x00\x00'\xf4\xa7\xf0\x00\x00\x00\x00(\xe4\xa7\x00\x00\x00\x00\x00)xO\x00\x00\x00\x00\x00)ԉ\xf0\x00\x00\x00\x00*\xc4" + - "z\xf0\x00\x00\x00\x00+\xb4k\xf0\x00\x00\x00\x00,\xa4\\\xf0\x00\x00\x00\x00-\x94M\xf0\x00\x00\x00\x00.\x84>\xf0\x00\x00\x00\x00/t/\xf0\x00\x00\x00\x000d \xf0\x00\x00\x00\x001]Lp\x00\x00" + - "\x00\x002r'p\x00\x00\x00\x003=.p\x00\x00\x00\x004R\tp\x00\x00\x00\x005\x1d\x10p\x00\x00\x00\x0061\xebp\x00\x00\x00\x006\xfc\xf2p\x00\x00\x00\x008\x1b\a\xf0\x00\x00\x00\x008\xdc" + - "\xd4p\x00\x00\x00\x009\xfa\xe9\xf0\x00\x00\x00\x00:\xbc\xb6p\x00\x00\x00\x00;\xda\xcb\xf0\x00\x00\x00\x00<\xa5\xd2\xf0\x00\x00\x00\x00=\xba\xad\xf0\x00\x00\x00\x00>\x85\xb4\xf0\x00\x00\x00\x00?\x9a\x8f\xf0\x00\x00" + - "\x00\x00@e\x96\xf0\x00\x00\x00\x00A\x83\xacp\x00\x00\x00\x00BEx\xf0\x00\x00\x00\x00Cc\x8ep\x00\x00\x00\x00D%Z\xf0\x00\x00\x00\x00ECpp\x00\x00\x00\x00F\x05<\xf0\x00\x00\x00\x00G#" + - "Rp\x00\x00\x00\x00G\xeeYp\x00\x00\x00\x00I\x034p\x00\x00\x00\x00I\xce;p\x00\x00\x00\x00J\xe3\x16p\x00\x00\x00\x00K\xae\x1dp\x00\x00\x00\x00L\xcc2\xf0\x00\x00\x00\x00M\x8d\xffp\x00\x00" + - "\x00\x00Nm\xf4@\x00\x00\x00\x00TK\xba\xf0\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x05\x06\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04" + - "\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\a\x03\x06\x00\x00\x86F\x00\x00\x00\x00p\x80\x00\x04\x00\x00~\x90\x00\b\x00\x00\x9a\xb0\x00\f\x00\x00\xa8\xc0\x01\x10\x00\x00\x9a\xb0\x01\f\x00\x00\x8c\xa0" + - "\x00\x14\x00\x00\xa8\xc0\x00\x10LMT\x00+08\x00+09\x00+11\x00+12\x00+10\x00\n<+10>-10\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RL\xe0\x91y" + - "\xe5\x02\x00\x00\xe5\x02\x00\x00\x10\x00\x1c\x00Asia/KrasnoyarskUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif" + - "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00A\x00\x00\x00\x06\x00\x00\x00\x10\xff\xff\xff\xff\xa1\xf9\r\xf2\xff\xff\xff\xff\xb5\xa3\xe1 \x00\x00\x00\x00\x15'o\x90\x00\x00\x00\x00\x16" + - "\x18\xa4\x00\x00\x00\x00\x00\x17\b\xa3\x10\x00\x00\x00\x00\x17\xf9׀\x00\x00\x00\x00\x18\xe9\u0590\x00\x00\x00\x00\x19\xdb\v\x00\x00\x00\x00\x00\x1a\xcc[\x90\x00\x00\x00\x00\x1b\xbch\xb0\x00\x00\x00\x00\x1c\xacY\xb0\x00" + - "\x00\x00\x00\x1d\x9cJ\xb0\x00\x00\x00\x00\x1e\x8c;\xb0\x00\x00\x00\x00\x1f|,\xb0\x00\x00\x00\x00 l\x1d\xb0\x00\x00\x00\x00!\\\x0e\xb0\x00\x00\x00\x00\"K\xff\xb0\x00\x00\x00\x00#;\xf0\xb0\x00\x00\x00\x00$" + - "+\xe1\xb0\x00\x00\x00\x00%\x1bҰ\x00\x00\x00\x00&\vð\x00\x00\x00\x00'\x04\xef0\x00\x00\x00\x00'\xf4\xe00\x00\x00\x00\x00(\xe4\xdf@\x00\x00\x00\x00)x\x87@\x00\x00\x00\x00)\xd4\xc20\x00" + - "\x00\x00\x00*ij0\x00\x00\x00\x00+\xb4\xa40\x00\x00\x00\x00,\xa4\x950\x00\x00\x00\x00-\x94\x860\x00\x00\x00\x00.\x84w0\x00\x00\x00\x00/th0\x00\x00\x00\x000dY0\x00\x00\x00\x001" + - "]\x84\xb0\x00\x00\x00\x002r_\xb0\x00\x00\x00\x003=f\xb0\x00\x00\x00\x004RA\xb0\x00\x00\x00\x005\x1dH\xb0\x00\x00\x00\x0062#\xb0\x00\x00\x00\x006\xfd*\xb0\x00\x00\x00\x008\x1b@0\x00" + - "\x00\x00\x008\xdd\f\xb0\x00\x00\x00\x009\xfb\"0\x00\x00\x00\x00:\xbc\xee\xb0\x00\x00\x00\x00;\xdb\x040\x00\x00\x00\x00<\xa6\v0\x00\x00\x00\x00=\xba\xe60\x00\x00\x00\x00>\x85\xed0\x00\x00\x00\x00?" + - "\x9a\xc80\x00\x00\x00\x00@e\xcf0\x00\x00\x00\x00A\x83\xe4\xb0\x00\x00\x00\x00BE\xb10\x00\x00\x00\x00Ccư\x00\x00\x00\x00D%\x930\x00\x00\x00\x00EC\xa8\xb0\x00\x00\x00\x00F\x05u0\x00" + - "\x00\x00\x00G#\x8a\xb0\x00\x00\x00\x00G\ue470\x00\x00\x00\x00I\x03l\xb0\x00\x00\x00\x00I\xces\xb0\x00\x00\x00\x00J\xe3N\xb0\x00\x00\x00\x00K\xaeU\xb0\x00\x00\x00\x00L\xcck0\x00\x00\x00\x00M" + - "\x8e7\xb0\x00\x00\x00\x00TK\xe5 \x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x05\x03\x00\x00W\x0e\x00\x00\x00\x00T`\x00\x04\x00\x00p\x80\x01\b\x00\x00bp\x00\f\x00\x00bp\x01\f\x00\x00p\x80\x00\bLMT\x00+06\x00" + - "+08\x00+07\x00\n<+07>-7\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xc7X,Y\x9f\x01\x00\x00\x9f\x01\x00\x00\n\x00\x1c\x00Asia/SeoulUT\t" + - "\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00\x06\x00\x00\x00\x10" + - "\xff\xff\xff\xff\x8b\xd7\xf0x\xff\xff\xff\xff\x92\xe6\x16\xf8\xff\xff\xff\xff\xd2C'\xf0\xff\xff\xff\xff\xd7e\x8fp\xff\xff\xff\xff\xd7\xee\x9d`\xff\xff\xff\xff\xd8\xf8\xfap\xff\xff\xff\xff\xd9\xcd-\xe0\xff\xff\xff\xff" + - "\xda\u05ca\xf0\xff\xff\xff\xffۭ\x0f\xe0\xff\xff\xff\xff\xdc\xe6\xe2\xf0\xff\xff\xff\xff\u074c\xf1\xe0\xff\xff\xff\xff\xe2O)\xf0\xff\xff\xff\xff\xe4k\xb7\xf8\xff\xff\xff\xff\xe5\x13\x18h\xff\xff\xff\xff\xe6b\x03x" + - "\xff\xff\xff\xff\xe7\x11L\xe8\xff\xff\xff\xff\xe8/px\xff\xff\xff\xff\xe8\xe7\xf4h\xff\xff\xff\xff\xea\x0fRx\xff\xff\xff\xff\xea\xc7\xd6h\xff\xff\xff\xff\xeb\xef4x\xff\xff\xff\xff째h\xff\xff\xff\xff" + - "\xed\xcf\x16x\xff\xff\xff\xff\ue1dah\xff\xff\xff\xff\xf05qx\x00\x00\x00\x00 \xa3`\x90\x00\x00\x00\x00!ng\x90\x00\x00\x00\x00\"\x83B\x90\x00\x00\x00\x00#NI\x90\x01\x02\x04\x03\x04\x03\x04\x03" + - "\x04\x03\x04\x01\x05\x01\x05\x01\x05\x01\x05\x01\x05\x01\x05\x01\x04\x03\x04\x03\x04\x00\x00w\b\x00\x00\x00\x00w\x88\x00\x04\x00\x00~\x90\x00\b\x00\x00\x8c\xa0\x01\f\x00\x00~\x90\x00\x04\x00\x00\x85\x98\x01\fLMT" + - "\x00KST\x00JST\x00KDT\x00\nKST-9\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Ry\x19\xe0N\x9a\x00\x00\x00\x9a\x00\x00\x00\v\x00\x1c\x00Asia/Brune" + - "iUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03" + - "\x00\x00\x00\x0e\xff\xff\xff\xff\xad\x8a\x02D\xff\xff\xff\xff\xbagG\x88\x01\x02\x00\x00k\xbc\x00\x00\x00\x00ix\x00\x04\x00\x00p\x80\x00\nLMT\x00+0730\x00+08\x00\n<+08>" + - "-8\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xd7e&uv\x02\x00\x00v\x02\x00\x00\f\x00\x1c\x00Asia/BaghdadUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux" + - "\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00" + - "\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x006\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffi\x86\xb1\xdc\xff\xff\xff\xff" + - "\x9e0<\xe0\x00\x00\x00\x00\x170hP\x00\x00\x00\x00\x17\xfa\x0f\xc0\x00\x00\x00\x00\x18\xe8\xbdP\x00\x00\x00\x00\x19\xdbC@\x00\x00\x00\x00\x1a̓\xd0\x00\x00\x00\x00\x1b\xbd\xc8@\x00\x00\x00\x00\x1c\xad\xc7P" + - "\x00\x00\x00\x00\x1d\x9ct\xe0\x00\x00\x00\x00\x1e\x8ce\xe0\x00\x00\x00\x00\x1f|V\xe0\x00\x00\x00\x00 lG\xe0\x00\x00\x00\x00!\\8\xe0\x00\x00\x00\x00\"L)\xe0\x00\x00\x00\x00#<\x1a\xe0\x00\x00\x00\x00" + - "$,\v\xe0\x00\x00\x00\x00%\x1b\xfc\xe0\x00\x00\x00\x00&\v\xed\xe0\x00\x00\x00\x00'\x05\x19`\x00\x00\x00\x00'\xf6x\x00\x00\x00\x00\x00(纀\x00\x00\x00\x00)\xd8\xfd\x00\x00\x00\x00\x00*\xca?\x80" + - "\x00\x00\x00\x00+\xba0\x80\x00\x00\x00\x00,\xabs\x00\x00\x00\x00\x00-\x9bd\x00\x00\x00\x00\x00.\x8c\xa6\x80\x00\x00\x00\x00/|\x97\x80\x00\x00\x00\x000m\xda\x00\x00\x00\x00\x001_\x1c\x80\x00\x00\x00\x00" + - "2P_\x00\x00\x00\x00\x003@P\x00\x00\x00\x00\x0041\x92\x80\x00\x00\x00\x005!\x83\x80\x00\x00\x00\x006\x12\xc6\x00\x00\x00\x00\x007\x02\xb7\x00\x00\x00\x00\x007\xf3\xf9\x80\x00\x00\x00\x008\xe5<\x00" + - "\x00\x00\x00\x009\xd6~\x80\x00\x00\x00\x00:\xc6o\x80\x00\x00\x00\x00;\xb7\xb2\x00\x00\x00\x00\x00<\xa7\xa3\x00\x00\x00\x00\x00=\x98\xe5\x80\x00\x00\x00\x00>\x88ր\x00\x00\x00\x00?z\x19\x00\x00\x00\x00\x00" + - "@k[\x80\x00\x00\x00\x00A\\\x9e\x00\x00\x00\x00\x00BL\x8f\x00\x00\x00\x00\x00C=р\x00\x00\x00\x00D-\u0080\x00\x00\x00\x00E\x1f\x05\x00\x00\x00\x00\x00F\x0e\xf6\x00\x00\x00\x00\x00G\x008\x80" + - "\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x00\x00)\xa4\x00\x00" + - "\x00\x00)\xa0\x00\x04\x00\x00*0\x00\b\x00\x008@\x01\fLMT\x00BMT\x00+03\x00+04\x00\n<+03>-3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R`\xc9\xd4" + - "\\\xbe\x00\x00\x00\xbe\x00\x00\x00\x12\x00\x1c\x00Asia/Ujung_PandangUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00T" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x10\xff\xff\xff\xff\xa1\xf2}\x84\x00\x00\x00\x00\x1e\x180\xa8\x01\x02\x00\x00O\xfc\x00\x00\x00\x00MX\x00\x04\x00\x00P\xdc" + + "\x00\nLMT\x00+0530\x00+0545\x00\n<+0545>-5:45\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSS\xdd\\2a\x02\x00\x00a\x02\x00\x00\v\x00" + + "\x1c\x00Asia/AlmatyUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x003\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x19{\xdc\xff\xff\xff\xff\xb5\xa3\xef0\x00\x00\x00\x00\x15'}\xa0\x00\x00\x00\x00\x16\x18\xb2\x10\x00\x00\x00\x00\x17\b\xb1 \x00\x00\x00\x00" + + "\x17\xf9\xe5\x90\x00\x00\x00\x00\x18\xe9\xe4\xa0\x00\x00\x00\x00\x19\xdb\x19\x10\x00\x00\x00\x00\x1a\xcci\xa0\x00\x00\x00\x00\x1b\xbcv\xc0\x00\x00\x00\x00\x1c\xacg\xc0\x00\x00\x00\x00\x1d\x9cX\xc0\x00\x00\x00\x00\x1e\x8cI\xc0" + + "\x00\x00\x00\x00\x1f|:\xc0\x00\x00\x00\x00 l+\xc0\x00\x00\x00\x00!\\\x1c\xc0\x00\x00\x00\x00\"L\r\xc0\x00\x00\x00\x00#;\xfe\xc0\x00\x00\x00\x00$+\xef\xc0\x00\x00\x00\x00%\x1b\xe0\xc0\x00\x00\x00\x00" + + "&\v\xd1\xc0\x00\x00\x00\x00'\x04\xfd@\x00\x00\x00\x00'\xf4\xee@\x00\x00\x00\x00(\xe4\xedP\x00\x00\x00\x00)x\x95P\x00\x00\x00\x00)\xd4\xd0@\x00\x00\x00\x00*\xc4\xc1@\x00\x00\x00\x00+\xb4\xb2@" + + "\x00\x00\x00\x00,\xa4\xa3@\x00\x00\x00\x00-\x94\x94@\x00\x00\x00\x00.\x84\x85@\x00\x00\x00\x00/tv@\x00\x00\x00\x000dg@\x00\x00\x00\x001]\x92\xc0\x00\x00\x00\x002rm\xc0\x00\x00\x00\x00" + + "3=t\xc0\x00\x00\x00\x004RO\xc0\x00\x00\x00\x005\x1dV\xc0\x00\x00\x00\x00621\xc0\x00\x00\x00\x006\xfd8\xc0\x00\x00\x00\x008\x1bN@\x00\x00\x00\x008\xdd\x1a\xc0\x00\x00\x00\x009\xfb0@" + + "\x00\x00\x00\x00:\xbc\xfc\xc0\x00\x00\x00\x00;\xdb\x12@\x00\x00\x00\x00<\xa6\x19@\x00\x00\x00\x00=\xba\xf4@\x00\x00\x00\x00>\x85\xfb@\x00\x00\x00\x00?\x9a\xd6@\x00\x00\x00\x00@e\xdd@\x00\x00\x00\x00" + + "A\x83\xf2\xc0\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x00\x00H$\x00" + + "\x00\x00\x00FP\x00\x04\x00\x00bp\x01\b\x00\x00T`\x00\f\x00\x00T`\x01\fLMT\x00+05\x00+07\x00+06\x00\n<+06>-6\nPK\x03\x04\n\x00\x00\x00\x00\x00" + + "#\x82iSy\x19\xe0N\x9a\x00\x00\x00\x9a\x00\x00\x00\v\x00\x1c\x00Asia/BruneiUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00T" + "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xff\xa1\xf2]\x90\xff\xff\xff\xff\xba\x16Ր\xff\xff\xff\xffˈ\x1d\x80\xff\xff" + - "\xff\xff\xd2V\xeep\x01\x02\x03\x04\x00\x00o\xf0\x00\x00\x00\x00o\xf0\x00\x04\x00\x00p\x80\x00\b\x00\x00~\x90\x00\f\x00\x00p\x80\x00\x10LMT\x00MMT\x00+08\x00+09\x00WITA" + - "\x00\nWITA-8\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RV\xe0\xe7!\xe7\x02\x00\x00\xe7\x02\x00\x00\v\x00\x1c\x00Asia/AnadyrUT\t\x00\x03\x15\xac\x0e`\x15" + - "\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00" + - "\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\a\x00\x00\x00\x14\xff\xff\xff\xff\xaa\x19\x1d" + - "\x9c\xff\xff\xff\xff\xb5\xa3\x8c\xc0\x00\x00\x00\x00\x15'\x1b0\x00\x00\x00\x00\x16\x18O\xa0\x00\x00\x00\x00\x17\bN\xb0\x00\x00\x00\x00\x17\xf9\x910\x00\x00\x00\x00\x18\xe9\x90@\x00\x00\x00\x00\x19\xdaİ\x00\x00\x00" + - "\x00\x1a\xcc\x15@\x00\x00\x00\x00\x1b\xbc\"`\x00\x00\x00\x00\x1c\xac\x13`\x00\x00\x00\x00\x1d\x9c\x04`\x00\x00\x00\x00\x1e\x8b\xf5`\x00\x00\x00\x00\x1f{\xe6`\x00\x00\x00\x00 k\xd7`\x00\x00\x00\x00![\xc8" + - "`\x00\x00\x00\x00\"K\xb9`\x00\x00\x00\x00#;\xaa`\x00\x00\x00\x00$+\x9b`\x00\x00\x00\x00%\x1b\x8c`\x00\x00\x00\x00&\v}`\x00\x00\x00\x00'\x04\xa8\xe0\x00\x00\x00\x00'\xf4\x99\xe0\x00\x00\x00" + - "\x00(\xe4\x98\xf0\x00\x00\x00\x00)x@\xf0\x00\x00\x00\x00)\xd4{\xe0\x00\x00\x00\x00*\xc4l\xe0\x00\x00\x00\x00+\xb4]\xe0\x00\x00\x00\x00,\xa4N\xe0\x00\x00\x00\x00-\x94?\xe0\x00\x00\x00\x00.\x840" + - "\xe0\x00\x00\x00\x00/t!\xe0\x00\x00\x00\x000d\x12\xe0\x00\x00\x00\x001]>`\x00\x00\x00\x002r\x19`\x00\x00\x00\x003= `\x00\x00\x00\x004Q\xfb`\x00\x00\x00\x005\x1d\x02`\x00\x00\x00" + - "\x0061\xdd`\x00\x00\x00\x006\xfc\xe4`\x00\x00\x00\x008\x1a\xf9\xe0\x00\x00\x00\x008\xdc\xc6`\x00\x00\x00\x009\xfa\xdb\xe0\x00\x00\x00\x00:\xbc\xa8`\x00\x00\x00\x00;ڽ\xe0\x00\x00\x00\x00<\xa5\xc4" + - "\xe0\x00\x00\x00\x00=\xba\x9f\xe0\x00\x00\x00\x00>\x85\xa6\xe0\x00\x00\x00\x00?\x9a\x81\xe0\x00\x00\x00\x00@e\x88\xe0\x00\x00\x00\x00A\x83\x9e`\x00\x00\x00\x00BEj\xe0\x00\x00\x00\x00Cc\x80`\x00\x00\x00" + - "\x00D%L\xe0\x00\x00\x00\x00ECb`\x00\x00\x00\x00F\x05.\xe0\x00\x00\x00\x00G#D`\x00\x00\x00\x00G\xeeK`\x00\x00\x00\x00I\x03&`\x00\x00\x00\x00I\xce-`\x00\x00\x00\x00J\xe3\b" + - "`\x00\x00\x00\x00K\xae\x0f`\x00\x00\x00\x00L\xcc2\xf0\x00\x00\x00\x00M\x8d\xffp\x01\x03\x02\x03\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x05\x06\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01" + - "\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x05\x06\x01\x00\x00\xa6d\x00\x00\x00\x00\xa8\xc0\x00\x04\x00\x00\xc4\xe0\x01\b\x00\x00\xb6\xd0\x00\f\x00\x00\xb6\xd0\x01\f\x00" + - "\x00\xa8\xc0\x01\x04\x00\x00\x9a\xb0\x00\x10LMT\x00+12\x00+14\x00+13\x00+11\x00\n<+12>-12\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xed\x8c\xf1\x91\x85" + - "\x00\x00\x00\x85\x00\x00\x00\v\x00\x1c\x00Asia/MuscatUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\xa1\xf2\x99\xa8\x01\x00\x003\xd8\x00\x00\x00\x008@\x00\x04LMT\x00+04\x00\n<+04>" + - "-4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x84)\r\xbd\xec\x00\x00\x00\xec\x00\x00\x00\x10\x00\x1c\x00Asia/Ho_Chi_MinhUT\t\x00\x03\x15\xac\x0e`\x15\xac" + - "\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" + - "\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xff\x88\x8cC\x80" + - "\xff\xff\xff\xff\x91\xa3+\n\xff\xff\xff\xff\xcd5\xe6\x80\xff\xff\xff\xff\xd1Y\xcep\xff\xff\xff\xff\xd2;>\xf0\xff\xff\xff\xff\xd52\xbb\x10\xff\xff\xff\xff\xe4\xb6\xe4\x80\xff\xff\xff\xff\xed/\x98\x00\x00\x00\x00\x00" + - "\n=\xc7\x00\x01\x02\x03\x04\x02\x03\x02\x03\x02\x00\x00d\x00\x00\x00\x00\x00c\xf6\x00\x04\x00\x00bp\x00\t\x00\x00p\x80\x00\r\x00\x00~\x90\x00\x11LMT\x00PLMT\x00+07\x00+08\x00" + - "+09\x00\n<+07>-7\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xef\\\xf4q\x17\x04\x00\x00\x17\x04\x00\x00\r\x00\x1c\x00Asia/DamascusUT\t\x00" + - "\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00c\x00\x00\x00\x03\x00\x00\x00\r\xff" + - "\xff\xff\xff\xa1\xf2\xabx\xff\xff\xff\xff\xa2\x81/\x80\xff\xff\xff\xff\xa3^\x9dp\xff\xff\xff\xff\xa4a\x11\x80\xff\xff\xff\xff\xa5>\u007fp\xff\xff\xff\xff\xa6@\xf3\x80\xff\xff\xff\xff\xa7\x1eap\xff\xff\xff\xff\xa8" + - " Հ\xff\xff\xff\xff\xa9\a}\xf0\xff\xff\xff\xff\xf1\x8fR\x00\xff\xff\xff\xff\xf2[\x9cp\xff\xff\xff\xff\xf3s(\x80\xff\xff\xff\xff\xf4;~p\xff\xff\xff\xff\xf5U\xad\x80\xff\xff\xff\xff\xf6\x1fT\xf0\xff" + - "\xff\xff\xff\xf76\xe1\x00\xff\xff\xff\xff\xf7\xff6\xf0\xff\xff\xff\xff\xf9\x0e\xda\x00\xff\xff\xff\xff\xf9\xe1\xbb\xf0\xff\xff\xff\xff\xfa\xf9H\x00\xff\xff\xff\xff\xfb\xc2\xefp\xff\xff\xff\xff\xfc\xdb\xcd\x00\xff\xff\xff\xff\xfd" + - "\xa5tp\xff\xff\xff\xff\xfe\xbd\x00\x80\xff\xff\xff\xff\xff\x86\xa7\xf0\x00\x00\x00\x00\x00\x9e4\x00\x00\x00\x00\x00\x01g\xdbp\x00\x00\x00\x00\x02\u007fg\x80\x00\x00\x00\x00\x03I\x0e\xf0\x00\x00\x00\x00\x04a\xec\x80\x00" + - "\x00\x00\x00\x05+\x93\xf0\x00\x00\x00\x00\x06C \x00\x00\x00\x00\x00\a\f\xc7p\x00\x00\x00\x00\b$S\x80\x00\x00\x00\x00\b\xed\xfa\xf0\x00\x00\x00\x00\n\x05\x87\x00\x00\x00\x00\x00\n\xcf.p\x00\x00\x00\x00\v" + - "\xe8\f\x00\x00\x00\x00\x00\f\xb1\xb3p\x00\x00\x00\x00\r\xc9?\x80\x00\x00\x00\x00\x0ekY\xf0\x00\x00\x00\x00\x0f\xaas\x00\x00\x00\x00\x00\x10L\x8dp\x00\x00\x00\x00\x18\xf4\xc5\x00\x00\x00\x00\x00\x19\xdbmp\x00" + - "\x00\x00\x00\x1a\xd7J\x00\x00\x00\x00\x00\x1b\xbd\xf2p\x00\x00\x00\x00\x1eU#\x00\x00\x00\x00\x00\x1f\x8a\xe5p\x00\x00\x00\x00 Gz\x00\x00\x00\x00\x00!\x89\x19\xf0\x00\x00\x00\x00\"\xe2`\x00\x00\x00\x0041hP\x00\x00\x00\x005\x1e\xc4`\x00\x00\x00\x006\x12\x9b\xd0\x00\x00\x00\x007\x02\x9a\xe0\x00\x00\x00\x007\xf3\xcfP\x00" + - "\x00\x00\x008\xe5\x1f\xe0\x00\x00\x00\x009\xd6TP\x00\x00\x00\x00:\xc6S`\x00\x00\x00\x00;\xb7\x87\xd0\x00\x00\x00\x00<\xa7\x86\xe0\x00\x00\x00\x00=\x98\xbbP\x00\x00\x00\x00>\x88\xba`\x00\x00\x00\x00?" + - "y\xee\xd0\x00\x00\x00\x00@k?`\x00\x00\x00\x00A\\s\xd0\x00\x00\x00\x00BLr\xe0\x00\x00\x00\x00C=\xa7P\x00\x00\x00\x00D-\xa6`\x00\x00\x00\x00E\x12\xfdP\x00\x00\x00\x00F\f6\xe0\x00" + - "\x00\x00\x00G*>P\x00\x00\x00\x00G\xf5S`\x00\x00\x00\x00I\vq\xd0\x00\x00\x00\x00I\xcb\xfa\xe0\x00\x00\x00\x00J\xea\x02P\x00\x00\x00\x00K\xb5\x17`\x00\x00\x00\x00L\xc9\xe4P\x00\x00\x00\x00M" + - "\x94\xf9`\x00\x00\x00\x00N\xa9\xc6P\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\"\b\x00\x00\x00\x00*0" + - "\x01\x04\x00\x00\x1c \x00\tLMT\x00EEST\x00EET\x00\nEET-2EEST,M3.5.5/0,M10.5.5/0\nPK\x03\x04\n\x00\x00\x00\x00" + - "\x00\xf1c9Rj$\xcd\xf4\x9a\x00\x00\x00\x9a\x00\x00\x00\f\x00\x1c\x00Asia/ThimphuUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00" + - "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xff\xd5\xe6\x15t\x00\x00\x00\x00!aM\xa8\x01\x02\x00\x00T\f\x00\x00" + - "\x00\x00MX\x00\x04\x00\x00T`\x00\nLMT\x00+0530\x00+06\x00\n<+06>-6\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x88\xf6C\x84\x98\x00\x00\x00\x98\x00\x00" + - "\x00\f\x00\x1c\x00Asia/BangkokUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xffV\xb6\x85\xc4\xff\xff\xff\xff\xa2jg\xc4\x01\x02\x00\x00^<\x00\x00\x00\x00^<\x00\x04\x00\x00bp\x00\bLMT\x00" + - "BMT\x00+07\x00\n<+07>-7\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x02\x95-\xad\xc4\x02\x00\x00\xc4\x02\x00\x00\f\x00\x1c\x00Asia/YerevanU" + - "T\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>\x00\x00\x00\x05\x00\x00" + - "\x00\x10\xff\xff\xff\xff\xaa\x19\x9aH\xff\xff\xff\xff\xe7\xda\fP\x00\x00\x00\x00\x15'\x99\xc0\x00\x00\x00\x00\x16\x18\xce0\x00\x00\x00\x00\x17\b\xcd@\x00\x00\x00\x00\x17\xfa\x01\xb0\x00\x00\x00\x00\x18\xea\x00\xc0\x00\x00" + - "\x00\x00\x19\xdb50\x00\x00\x00\x00\x1a̅\xc0\x00\x00\x00\x00\x1b\xbc\x92\xe0\x00\x00\x00\x00\x1c\xac\x83\xe0\x00\x00\x00\x00\x1d\x9ct\xe0\x00\x00\x00\x00\x1e\x8ce\xe0\x00\x00\x00\x00\x1f|V\xe0\x00\x00\x00\x00 l" + - "G\xe0\x00\x00\x00\x00!\\8\xe0\x00\x00\x00\x00\"L)\xe0\x00\x00\x00\x00#<\x1a\xe0\x00\x00\x00\x00$,\v\xe0\x00\x00\x00\x00%\x1b\xfc\xe0\x00\x00\x00\x00&\v\xed\xe0\x00\x00\x00\x00'\x05\x19`\x00\x00" + - "\x00\x00'\xf5\n`\x00\x00\x00\x00(\xe5\tp\x00\x00\x00\x00)\xd4\xfap\x00\x00\x00\x00*\xc4\xebp\x00\x00\x00\x00+\xb4\xdcp\x00\x00\x00\x00,\xa4\xcdp\x00\x00\x00\x00-\x94\xbep\x00\x00\x00\x00.\x84" + - "\xafp\x00\x00\x00\x00/t\xa0p\x00\x00\x00\x000d\x91p\x00\x00\x00\x003=\x90\xe0\x00\x00\x00\x004Rk\xe0\x00\x00\x00\x005\x1dr\xe0\x00\x00\x00\x0062M\xe0\x00\x00\x00\x006\xfdT\xe0\x00\x00" + - "\x00\x008\x1bj`\x00\x00\x00\x008\xdd6\xe0\x00\x00\x00\x009\xfbL`\x00\x00\x00\x00:\xbd\x18\xe0\x00\x00\x00\x00;\xdb.`\x00\x00\x00\x00<\xa65`\x00\x00\x00\x00=\xbb\x10`\x00\x00\x00\x00>\x86" + - "\x17`\x00\x00\x00\x00?\x9a\xf2`\x00\x00\x00\x00@e\xf9`\x00\x00\x00\x00A\x84\x0e\xe0\x00\x00\x00\x00BE\xdb`\x00\x00\x00\x00Cc\xf0\xe0\x00\x00\x00\x00D%\xbd`\x00\x00\x00\x00EC\xd2\xe0\x00\x00" + - "\x00\x00F\x05\x9f`\x00\x00\x00\x00G#\xb4\xe0\x00\x00\x00\x00G\xee\xbb\xe0\x00\x00\x00\x00I\x03\x96\xe0\x00\x00\x00\x00IΝ\xe0\x00\x00\x00\x00J\xe3x\xe0\x00\x00\x00\x00K\xae\u007f\xe0\x00\x00\x00\x00L\xcc" + - "\x95`\x00\x00\x00\x00M\x8ea\xe0\x00\x00\x00\x00N\xacw`\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x04\x01\x04\x01\x04\x01\x04\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x00\x00)\xb8\x00\x00\x00\x00*0\x00\x04\x00\x00FP\x01\b\x00\x008@\x00\f\x00\x008@\x01\fLMT\x00+03\x00+0" + - "5\x00+04\x00\n<+04>-4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x8bSnT\xa1\x00\x00\x00\xa1\x00\x00\x00\r\x00\x1c\x00Asia/KatmanduUT" + - "\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00" + - "\x10\xff\xff\xff\xff\xa1\xf2}\x84\x00\x00\x00\x00\x1e\x180\xa8\x01\x02\x00\x00O\xfc\x00\x00\x00\x00MX\x00\x04\x00\x00P\xdc\x00\nLMT\x00+0530\x00+0545\x00\n<+0545" + - ">-5:45\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R&\xe9\xd1\xd8q\x02\x00\x00q\x02\x00\x00\t\x00\x1c\x00Asia/OralUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`u" + - "x\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00" + - "\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x003\x00\x00\x00\a\x00\x00\x00\x14\xff\xff\xff\xff\xaa\x19\x93\xdc\xff\xff\xff" + - "\xff\xb5\xa4\vP\x00\x00\x00\x00\x15'\x8b\xb0\x00\x00\x00\x00\x16\x18\xc0 \x00\x00\x00\x00\x17\b\xb1 \x00\x00\x00\x00\x17\xf9\xf3\xa0\x00\x00\x00\x00\x18\xe9\xf2\xb0\x00\x00\x00\x00\x19\xdb' \x00\x00\x00\x00\x1a\xccw" + - "\xb0\x00\x00\x00\x00\x1b\xbc\x84\xd0\x00\x00\x00\x00\x1c\xacu\xd0\x00\x00\x00\x00\x1d\x9cf\xd0\x00\x00\x00\x00\x1e\x8cW\xd0\x00\x00\x00\x00\x1f|H\xd0\x00\x00\x00\x00 l9\xd0\x00\x00\x00\x00!\\*\xd0\x00\x00\x00" + - "\x00\"L\x1b\xd0\x00\x00\x00\x00#<\f\xd0\x00\x00\x00\x00$+\xfd\xd0\x00\x00\x00\x00%\x1b\xfc\xe0\x00\x00\x00\x00&\v\xed\xe0\x00\x00\x00\x00'\x05\x19`\x00\x00\x00\x00'\xf5\n`\x00\x00\x00\x00(\xe4\xfb" + - "`\x00\x00\x00\x00)x\xa3`\x00\x00\x00\x00)\xd4\xdeP\x00\x00\x00\x00*\xc4\xdd`\x00\x00\x00\x00+\xb4\xce`\x00\x00\x00\x00,\xa4\xbf`\x00\x00\x00\x00-\x94\xb0`\x00\x00\x00\x00.\x84\xa1`\x00\x00\x00" + - "\x00/t\x92`\x00\x00\x00\x000d\x83`\x00\x00\x00\x001]\xae\xe0\x00\x00\x00\x002r\x89\xe0\x00\x00\x00\x003=\x90\xe0\x00\x00\x00\x004Rk\xe0\x00\x00\x00\x005\x1dr\xe0\x00\x00\x00\x0062M" + - "\xe0\x00\x00\x00\x006\xfdT\xe0\x00\x00\x00\x008\x1bj`\x00\x00\x00\x008\xdd6\xe0\x00\x00\x00\x009\xfbL`\x00\x00\x00\x00:\xbd\x18\xe0\x00\x00\x00\x00;\xdb.`\x00\x00\x00\x00<\xa65`\x00\x00\x00" + - "\x00=\xbb\x10`\x00\x00\x00\x00>\x86\x17`\x00\x00\x00\x00?\x9a\xf2`\x00\x00\x00\x00@e\xf9`\x00\x00\x00\x00A\x84\x0e\xe0\x01\x02\x03\x04\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x06\x05\x06\x05" + - "\x06\x02\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x02\x00\x000$\x00\x00\x00\x00*0\x00\x04\x00\x00FP\x00\b\x00\x00T`\x01\f\x00\x00T`\x00\f\x00\x00" + - "FP\x01\b\x00\x008@\x00\x10LMT\x00+03\x00+05\x00+06\x00+04\x00\n<+05>-5\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x02\xf4\xaeg\xd5\x00\x00" + - "\x00\xd5\x00\x00\x00\n\x00\x1c\x00Asia/TokyoUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xffe¤p\xff\xff\xff\xff\xd7>\x02p\xff\xff\xff\xff\xd7\xedY\xf0\xff\xff\xff\xff\xd8\xf8\xfap\xff\xff\xff\xff\xd9\xcd" + - ";\xf0\xff\xff\xff\xff\xdb\a\x00\xf0\xff\xff\xff\xffۭ\x1d\xf0\xff\xff\xff\xff\xdc\xe6\xe2\xf0\xff\xff\xff\xff\u074c\xff\xf0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\x83\x03\x00\x00\x00\x00\x8c\xa0\x01\x04\x00\x00~\x90\x00" + - "\bLMT\x00JDT\x00JST\x00\nJST-9\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\aW\x10Ѱ\x04\x00\x00\xb0\x04\x00\x00\r\x00\x1c\x00Asia/Istan" + - "bulUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00s\x00\x00" + - "\x00\x06\x00\x00\x00\x19\xff\xff\xff\xffV\xb6\xc8\xd8\xff\xff\xff\xff\x90\x8b\xf5\x98\xff\xff\xff\xff\x9b\f\x17`\xff\xff\xff\xff\x9bվ\xd0\xff\xff\xff\xff\xa2ec\xe0\xff\xff\xff\xff\xa3{\x82P\xff\xff\xff\xff\xa4N" + - "\x80`\xff\xff\xff\xff\xa5?\xb4\xd0\xff\xff\xff\xff\xa6%'\xe0\xff\xff\xff\xff\xa7'\u007f\xd0\xff\xff\xff\xff\xaa((`\xff\xff\xff\xff\xaa\xe1\xfd\xd0\xff\xff\xff\xff\xab\xf9\x89\xe0\xff\xff\xff\xff\xac\xc31P\xff\xff" + - "\xff\xffȁ?\xe0\xff\xff\xff\xff\xc9\x01\x13P\xff\xff\xff\xff\xc9J\xf5`\xff\xff\xff\xff\xca\u0380P\xff\xff\xff\xff\xcbˮ`\xff\xff\xff\xff\xd2k\tP\xff\xff\xff\xffӢ9`\xff\xff\xff\xff\xd4C" + - "\x02P\xff\xff\xff\xff\xd5L\r\xe0\xff\xff\xff\xff\xd6){\xd0\xff\xff\xff\xff\xd7+\xef\xe0\xff\xff\xff\xff\xd8\t]\xd0\xff\xff\xff\xff\xd9\x02\x97`\xff\xff\xff\xff\xd9\xe9?\xd0\xff\xff\xff\xff\xda\xeb\xb3\xe0\xff\xff" + - "\xff\xff\xdb\xd2\\P\xff\xff\xff\xff\xdc\xd4\xd0`\xff\xff\xff\xffݲ>P\xff\xff\xff\xff\xf1\xf4\xb9`\xff\xff\xff\xff\xf4b\xefP\xff\xff\xff\xff\xf5h\x06`\xff\xff\xff\xff\xf6\x1f8\xd0\x00\x00\x00\x00\x06n" + - "\x93p\x00\x00\x00\x00\a9\x9ap\x00\x00\x00\x00\a\xfbu\x00\x00\x00\x00\x00\t\x19|p\x00\x00\x00\x00\t\xd0\xcb\x00\x00\x00\x00\x00\n\xf9^p\x00\x00\x00\x00\v\xb1\xfe\x80\x00\x00\x00\x00\f\xd9@p\x00\x00" + - "\x00\x00\r\xa4U\x80\x00\x00\x00\x00\x0e\xa6\xadp\x00\x00\x00\x00\x0f\x847\x80\x00\x00\x00\x00\x0f\xf8\x11P\x00\x00\x00\x00\x19\x89\xb0p\x00\x00\x00\x00\x19ܰ\xe0\x00\x00\x00\x00\x1b\xe6\xd0\xf0\x00\x00\x00\x00\x1c\xc6" + - "\xef\xf0\x00\x00\x00\x00\x1d\x9b1p\x00\x00\x00\x00\x1e\x8cs\xf0\x00\x00\x00\x00\x1f|d\xf0\x00\x00\x00\x00 lU\xf0\x00\x00\x00\x00!\\F\xf0\x00\x00\x00\x00\"L7\xf0\x00\x00\x00\x00#<(\xf0\x00\x00" + - "\x00\x00$,\x19\xf0\x00\x00\x00\x00%\x1c\n\xf0\x00\x00\x00\x00&\v\xfb\xf0\x00\x00\x00\x00'\x05'p\x00\x00\x00\x00'\xf5\x18p\x00\x00\x00\x00(\xe5\tp\x00\x00\x00\x00)\xd4\xfap\x00\x00\x00\x00*\xc4" + - "\xebp\x00\x00\x00\x00+\xb4\xdcp\x00\x00\x00\x00,\xa4\xcdp\x00\x00\x00\x00-\x8b\x83\xf0\x00\x00\x00\x00.\x84\xafp\x00\x00\x00\x00/t\xa0p\x00\x00\x00\x000d\x91p\x00\x00\x00\x001]\xbc\xf0\x00\x00" + - "\x00\x002r\x97\xf0\x00\x00\x00\x003=\x9e\xf0\x00\x00\x00\x004Ry\xf0\x00\x00\x00\x005\x1d\x80\xf0\x00\x00\x00\x0062[\xf0\x00\x00\x00\x006\xfdb\xf0\x00\x00\x00\x008\x1bxp\x00\x00\x00\x008\xdd" + - "D\xf0\x00\x00\x00\x009\xfbZp\x00\x00\x00\x00:\xbd&\xf0\x00\x00\x00\x00;\xdb\x86%p\x00\x00\x00\x00?\x9b\x00p\x00\x00" + - "\x00\x00@f\ap\x00\x00\x00\x00A\x84\x1c\xf0\x00\x00\x00\x00BE\xe9p\x00\x00\x00\x00Cc\xfe\xf0\x00\x00\x00\x00D%\xcbp\x00\x00\x00\x00EC\xe0\xf0\x00\x00\x00\x00F\x05ɐ\x00\x00\x00\x00G#" + - "\xdf\x10\x00\x00\x00\x00G\xee\xe6\x10\x00\x00\x00\x00I\x03\xc1\x10\x00\x00\x00\x00I\xce\xc8\x10\x00\x00\x00\x00J\xe3\xa3\x10\x00\x00\x00\x00K\xae\xaa\x10\x00\x00\x00\x00L̿\x90\x00\x00\x00\x00M\x8fݐ\x00\x00" + - "\x00\x00N\xac\xa1\x90\x00\x00\x00\x00Onn\x10\x00\x00\x00\x00P\x8c\x83\x90\x00\x00\x00\x00QW\x8a\x90\x00\x00\x00\x00Rle\x90\x00\x00\x00\x00S8\xbe\x10\x00\x00\x00\x00TLG\x90\x00\x00\x00\x00U\x17" + - "N\x90\x00\x00\x00\x00V>\x9e\x90\x00\x00\x00\x00V\xf70\x90\x00\x00\x00\x00W\xcf.P\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x04\x05\x04\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x04\x00\x00\x1b(\x00\x00\x00\x00\x1bh\x00\x04\x00\x00*0\x01\b\x00\x00\x1c \x00\r\x00\x00*0\x00\x11\x00\x008@\x01\x15LMT" + - "\x00IMT\x00EEST\x00EET\x00+03\x00+04\x00\n<+03>-3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xc7\x11\xe1[\xdc\x02\x00\x00\xdc\x02\x00\x00\v\x00\x1c" + - "\x00Asia/BeirutUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xff\xad\x8a\x02D\xff\xff\xff\xff\xbagG\x88\x01\x02\x00\x00k\xbc\x00\x00\x00\x00" + + "ix\x00\x04\x00\x00p\x80\x00\nLMT\x00+0730\x00+08\x00\n<+08>-8\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x17✳2\x04\x00\x002\x04\x00\x00\r" + + "\x00\x1c\x00Asia/Tel_AvivUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xffV\xb6\xc2\xfa\xff\xff\xff\xff\x9e0E\x88\xff\xff\xff\xff\xc8Y\xcf\x00\xff\xff\xff\xff\xc8\xfa\xa6\x00\xff\xff\xff\xff\xc98\x9c\x80\xff" + + "\xff\xff\xff\xcc\xe5\xeb\x80\xff\xff\xff\xffͬ\xfe\x00\xff\xff\xff\xff\xce\xc7\x1f\x00\xff\xff\xff\xffϏ\x83\x00\xff\xff\xff\xffЩ\xa4\x00\xff\xff\xff\xffф}\x00\xff\xff\xff\xffҊ׀\xff\xff\xff\xff\xd3" + + "e\xb0\x80\xff\xff\xff\xff\xd4l\v\x00\xff\xff\xff\xff\xd7Z0\x80\xff\xff\xff\xff\xd7\xdfX\x00\xff\xff\xff\xff\xd8/À\xff\xff\xff\xff\xd9\x1ec\x00\xff\xff\xff\xff\xda\x10\xf7\x00\xff\xff\xff\xff\xda\xeb\xd0\x00\xff" + + "\xff\xff\xff۴4\x00\xff\xff\xff\xffܹ=\x00\xff\xff\xff\xff\xdd\xe0\x8d\x00\xff\xff\xff\xff\u07b4\u0380\xff\xff\xff\xffߤ\xbf\x80\xff\xff\xff\xff\xe0\x8bv\x00\xff\xff\xff\xff\xe1V}\x00\xff\xff\xff\xff\xe2" + + "\xbef\x80\xff\xff\xff\xff\xe36_\x00\xff\xff\xff\xff\xe4\x9eH\x80\xff\xff\xff\xff\xe5\x16A\x00\xff\xff\xff\xff\xe6t\xf0\x00\xff\xff\xff\xff\xe7\x11Ҁ\xff\xff\xff\xff\xe8&\xad\x80\xff\xff\xff\xff\xe8\xe8z\x00\x00" + + "\x00\x00\x00\b|\x8b\xe0\x00\x00\x00\x00\b\xfd\xb0\xd0\x00\x00\x00\x00\t\xf6\xea`\x00\x00\x00\x00\n\xa63\xd0\x00\x00\x00\x00\x13\xe9\xfc`\x00\x00\x00\x00\x14![`\x00\x00\x00\x00\x1a\xfa\xc6`\x00\x00\x00\x00\x1b" + + "\x8en`\x00\x00\x00\x00\x1c\xbe\xf8\xe0\x00\x00\x00\x00\x1dw|\xd0\x00\x00\x00\x00\x1e\xcc\xff`\x00\x00\x00\x00\x1f`\x99P\x00\x00\x00\x00 \x82\xb1`\x00\x00\x00\x00!I\xb5\xd0\x00\x00\x00\x00\"^\x9e\xe0\x00" + + "\x00\x00\x00# ]P\x00\x00\x00\x00$Z0`\x00\x00\x00\x00%\x00?P\x00\x00\x00\x00&\v\xed\xe0\x00\x00\x00\x00&\xd6\xe6\xd0\x00\x00\x00\x00'\xeb\xcf\xe0\x00\x00\x00\x00(\xc0\x03P\x00\x00\x00\x00)" + + "\xd4\xec`\x00\x00\x00\x00*\xa9\x1f\xd0\x00\x00\x00\x00+\xbbe\xe0\x00\x00\x00\x00,\x89\x01\xd0\x00\x00\x00\x00-\x9bG\xe0\x00\x00\x00\x00._\xa9P\x00\x00\x00\x00/{)\xe0\x00\x00\x00\x000H\xc5\xd0\x00" + + "\x00\x00\x001H\x96\xe0\x00\x00\x00\x002\x83\x82p\x00" + + "\x00\x00\x00?|\x9f\xe0\x00\x00\x00\x00@s6p\x00\x00\x00\x00AP\xa4`\x00\x00\x00\x00BL\x8f\x00\x00\x00\x00\x00CHOp\x00\x00\x00\x00D,q\x00\x00\x00\x00\x00E\x1e\xf6\xf0\x00\x00\x00\x00F" + + "\fS\x00\x00\x00\x00\x00F\xecc\xf0\x00\x00\x00\x00G\xec5\x00\x00\x00\x00\x00H\xe7\xf5p\x00\x00\x00\x00I\xcc\x17\x00\x00\x00\x00\x00J\xbe\x9c\xf0\x00\x00\x00\x00K\xab\xf9\x00\x00\x00\x00\x00L\x8c\t\xf0\x00" + + "\x00\x00\x00M\x95\x15\x80\x00\x00\x00\x00N\x87\x9bp\x00\x00\x00\x00Ot\xf7\x80\x00\x00\x00\x00P^B\xf0\x00\x00\x00\x00QTـ\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x00\x00!\x06\x00\x00\x00\x00 \xf8\x00\x04\x00\x00*0\x01\b\x00\x00\x1c \x00\f\x00\x008@\x01\x10LMT\x00JMT\x00IDT" + + "\x00IST\x00IDDT\x00\nIST-2IDT,M3.4.4/26,M10.5.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x1d?v\f\x17\x03\x00\x00" + + "\x17\x03\x00\x00\n\x00\x1c\x00Asia/MacauUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\x85i[\x8e\xff\xff\xff\xff\xcbGu\xf0\xff\xff\xff\xff\xcb\xf2\xca\xe0\xff\xff\xff\xff\xcc\xfb\xbaP\xff\xff\xff\xff\xcd\xd3\xfe" + + "`\xff\xff\xff\xffΝ\xa5\xd0\xff\xff\xff\xff\xd2azp\xff\xff\xff\xff\xd3x\xf8p\xff\xff\xff\xff\xd4B\xad\xf0\xff\xff\xff\xff\xd5K\xabp\xff\xff\xff\xff\xd6tL\xf0\xff\xff\xff\xff\xd7?S\xf0\xff\xff\xff" + + "\xff\xd8/D\xf0\xff\xff\xff\xff\xd8\xf8\xfap\xff\xff\xff\xff\xda\r\xd5p\xff\xff\xff\xff\xda\xd8\xdcp\xff\xff\xff\xff\xdb\xed\xb7p\xff\xff\xff\xffܸ\xbep\xff\xff\xff\xff\xdd\xce\xea\xf0\xff\xff\xff\xffޡ\xda" + + "\xf0\xff\xff\xff\xff߶\xb5\xf0\xff\xff\xff\xff\xe0\x81\xbc\xf0\xff\xff\xff\xffᖗ\xf0\xff\xff\xff\xff\xe2O)\xf0\xff\xff\xff\xff\xe3vy\xf0\xff\xff\xff\xff\xe4/\v\xf0\xff\xff\xff\xff\xe5_\x96p\xff\xff\xff" + + "\xff\xe6\x0e\xed\xf0\xff\xff\xff\xff\xe7?\xa9\xa8\xff\xff\xff\xff\xe7\xf8I\xb8\xff\xff\xff\xff\xe9\x1f\x8b\xa8\xff\xff\xff\xff\xe9\xd8+\xb8\xff\xff\xff\xff\xea\xffm\xa8\xff\xff\xff\xff\xeb\xb8\r\xb8\xff\xff\xff\xff\xec\xdfO" + + "\xa8\xff\xff\xff\xff\xed\x97\xef\xb8\xff\xff\xff\xff\xee\xc8l(\xff\xff\xff\xff\xefwѸ\xff\xff\xff\xff\xf0\xa8N(\xff\xff\xff\xff\xf1W\xb3\xb8\xff\xff\xff\xff\xf2\x880(\xff\xff\xff\xff\xf3@\xd08\xff\xff\xff" + + "\xff\xf4h\x12(\xff\xff\xff\xff\xf5 \xb28\xff\xff\xff\xff\xf6G\xf4(\xff\xff\xff\xff\xf7%~8\xff\xff\xff\xff\xf8\x15S\x18\xff\xff\xff\xff\xf9\x05`8\xff\xff\xff\xff\xf9\xf55\x18\xff\xff\xff\xff\xfa\xe5B" + + "8\xff\xff\xff\xff\xfb\xde_\xa8\xff\xff\xff\xff\xfc\xce^\xb8\xff\xff\xff\xff\xfd\xbeA\xa8\xff\xff\xff\xff\xfe\xae@\xb8\xff\xff\xff\xff\xff\x9e#\xa8\x00\x00\x00\x00\x00\x8e\"\xb8\x00\x00\x00\x00\x01~\x05\xa8\x00\x00\x00" + + "\x00\x02n\x04\xb8\x00\x00\x00\x00\x03]\xe7\xa8\x00\x00\x00\x00\x04M\xe6\xb8\x00\x00\x00\x00\x05G\x04(\x00\x00\x00\x00\x067\x038\x00\x00\x00\x00\a&\xe6(\x00\x00\x00\x00\a\x83=8\x00\x00\x00\x00\t\x06\xc8" + + "(\x00\x00\x00\x00\t\xf6\xc78\x00\x00\x00\x00\n\xe6\xaa(\x00\x00\x00\x00\v֩8\x00\x00\x00\x00\fƌ(\x00\x00\x00\x00\x11\x9b98\x00\x00\x00\x00\x12ol\xa8\x01\x03\x02\x03\x02\x03\x01\x04\x01\x04\x01" + + "\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01" + + "\x00\x00jr\x00\x00\x00\x00p\x80\x00\x04\x00\x00\x8c\xa0\x01\b\x00\x00~\x90\x00\f\x00\x00~\x90\x01\x10LMT\x00CST\x00+10\x00+09\x00CDT\x00\nCST-8\nPK\x03" + + "\x04\n\x00\x00\x00\x00\x00#\x82iS\x8a\x9a\x90\xf7\xd6\x02\x00\x00\xd6\x02\x00\x00\x11\x00\x1c\x00Asia/NovokuznetskUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v" + + "\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00" + + "\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x18 \xc0\xff\xff\xff\xff\xb5" + + "\xa3\xe1 \x00\x00\x00\x00\x15'o\x90\x00\x00\x00\x00\x16\x18\xa4\x00\x00\x00\x00\x00\x17\b\xa3\x10\x00\x00\x00\x00\x17\xf9׀\x00\x00\x00\x00\x18\xe9\u0590\x00\x00\x00\x00\x19\xdb\v\x00\x00\x00\x00\x00\x1a\xcc[\x90\x00" + + "\x00\x00\x00\x1b\xbch\xb0\x00\x00\x00\x00\x1c\xacY\xb0\x00\x00\x00\x00\x1d\x9cJ\xb0\x00\x00\x00\x00\x1e\x8c;\xb0\x00\x00\x00\x00\x1f|,\xb0\x00\x00\x00\x00 l\x1d\xb0\x00\x00\x00\x00!\\\x0e\xb0\x00\x00\x00\x00\"" + + "K\xff\xb0\x00\x00\x00\x00#;\xf0\xb0\x00\x00\x00\x00$+\xe1\xb0\x00\x00\x00\x00%\x1bҰ\x00\x00\x00\x00&\vð\x00\x00\x00\x00'\x04\xef0\x00\x00\x00\x00'\xf4\xe00\x00\x00\x00\x00(\xe4\xdf@\x00" + + "\x00\x00\x00)x\x87@\x00\x00\x00\x00)\xd4\xc20\x00\x00\x00\x00*ij0\x00\x00\x00\x00+\xb4\xa40\x00\x00\x00\x00,\xa4\x950\x00\x00\x00\x00-\x94\x860\x00\x00\x00\x00.\x84w0\x00\x00\x00\x00/" + + "th0\x00\x00\x00\x000dY0\x00\x00\x00\x001]\x84\xb0\x00\x00\x00\x002r_\xb0\x00\x00\x00\x003=f\xb0\x00\x00\x00\x004RA\xb0\x00\x00\x00\x005\x1dH\xb0\x00\x00\x00\x0062#\xb0\x00" + + "\x00\x00\x006\xfd*\xb0\x00\x00\x00\x008\x1b@0\x00\x00\x00\x008\xdd\f\xb0\x00\x00\x00\x009\xfb\"0\x00\x00\x00\x00:\xbc\xee\xb0\x00\x00\x00\x00;\xdb\x040\x00\x00\x00\x00<\xa6\v0\x00\x00\x00\x00=" + + "\xba\xe60\x00\x00\x00\x00>\x85\xed0\x00\x00\x00\x00?\x9a\xc80\x00\x00\x00\x00@e\xcf0\x00\x00\x00\x00A\x83\xe4\xb0\x00\x00\x00\x00BE\xb10\x00\x00\x00\x00Ccư\x00\x00\x00\x00D%\x930\x00" + + "\x00\x00\x00EC\xa8\xb0\x00\x00\x00\x00F\x05u0\x00\x00\x00\x00G#\x8a\xb0\x00\x00\x00\x00G\ue470\x00\x00\x00\x00I\x03l\xb0\x00\x00\x00\x00I\xces\xb0\x00\x00\x00\x00J\xe3N\xb0\x00\x00\x00\x00K" + + "\xaeU\xb0\x00\x00\x00\x00L\xccy@\x00\x00\x00\x00M\x8eE\xc0\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x03\x00\x00Q\xc0\x00\x00\x00\x00T`\x00\x04\x00\x00p\x80\x01\b\x00\x00bp\x00\f\x00\x00bp\x01\fLMT\x00+06" + + "\x00+08\x00+07\x00\n<+07>-7\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xcfׇ\xe1\x85\x00\x00\x00\x85\x00\x00\x00\v\x00\x1c\x00Asia/KuwaitU" + + "T\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00" + + "\x00\b\xff\xff\xff\xff\xd5\x1b6\xb4\x01\x00\x00+\xcc\x00\x00\x00\x00*0\x00\x04LMT\x00+03\x00\n<+03>-3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\t\x00\x1c\x00Atlantic/UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x03\x04\n\x00\x00\x00\x00\x00#\x82i" + + "Sm\xbd\x10k\xf1\x02\x00\x00\xf1\x02\x00\x00\x12\x00\x1c\x00Atlantic/ReykjavikUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S" + + "_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00D\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff\x8b`\x83\xa0\xff\xff\xff\xff\x9c\x91\x1e\x00\xff\xff\xff\xff\x9d\xd1" + + "\x88\x90\xff\xff\xff\xff\x9erQ\x80\xff\xff\xff\xff\x9f\xd5\x03\x10\xff\xff\xff\xff\xa0S\x85\x00\xff\xff\xff\xff\xa1\xb66\x90\xff\xff\xff\xff\xa4<'\x80\xff\xff\xff\xff\xa4\xb9t\x10\xff\xff\xff\xff\xc6M\x1a\x00\xff\xff" + + "\xff\xff\xc7=' \xff\xff\xff\xff\xc7\xda\x17\xb0\xff\xff\xff\xff\xc9&C\xa0\xff\xff\xff\xff\xc9\xc3& \xff\xff\xff\xff\xcb\x06%\xa0\xff\xff\xff\xffˬB\xa0\xff\xff\xff\xff\xcc\xdc\xcd \xff\xff\xff\xff͌" + + "$\xa0\xff\xff\xff\xffμ\xaf \xff\xff\xff\xff\xcfl\x06\xa0\xff\xff\xff\xffМ\x91 \xff\xff\xff\xff\xd1K\xe8\xa0\xff\xff\xff\xff҅\xad\xa0\xff\xff\xff\xff\xd3+ʠ\xff\xff\xff\xff\xd4e\x8f\xa0\xff\xff" + + "\xff\xff\xd59\xd1 \xff\xff\xff\xff\xd6Eq\xa0\xff\xff\xff\xff\xd7\x19\xb3 \xff\xff\xff\xff\xd8%S\xa0\xff\xff\xff\xff\xd8\xf9\x95 \xff\xff\xff\xff\xda\x0ep \xff\xff\xff\xff\xda\xd9w \xff\xff\xff\xff\xdb\xe5" + + "\x17\xa0\xff\xff\xff\xffܹY \xff\xff\xff\xff\xdd\xce4 \xff\xff\xff\xffޢu\xa0\xff\xff\xff\xff߮\x16 \xff\xff\xff\xff\xe0\x82W\xa0\xff\xff\xff\xff\xe1\x8d\xf8 \xff\xff\xff\xff\xe2b9\xa0\xff\xff" + + "\xff\xff\xe3m\xda \xff\xff\xff\xff\xe4B\x1b\xa0\xff\xff\xff\xff\xe5M\xbc \xff\xff\xff\xff\xe6!\xfd\xa0\xff\xff\xff\xff\xe76ؠ\xff\xff\xff\xff\xe8\v\x1a \xff\xff\xff\xff\xe9\x16\xba\xa0\xff\xff\xff\xff\xe9\xea" + + "\xfc \xff\xff\xff\xff\xea\xf6\x9c\xa0\xff\xff\xff\xff\xeb\xca\xde \xff\xff\xff\xff\xec\xd6~\xa0\xff\xff\xff\xff\xed\xaa\xc0 \xff\xff\xff\xff\xee\xb6`\xa0\xff\xff\xff\xff\uf2a2 \xff\xff\xff\xff\xf0\x96B\xa0\xff\xff" + + "\xff\xff\xf1j\x84 \xff\xff\xff\xff\xf2\u007f_ \xff\xff\xff\xff\xf3S\xa0\xa0\xff\xff\xff\xff\xf4_A \xff\xff\xff\xff\xf53\x82\xa0\xff\xff\xff\xff\xf6?# \xff\xff\xff\xff\xf7\x13d\xa0\xff\xff\xff\xff\xf8\x1f" + + "\x05 \xff\xff\xff\xff\xf8\xf3F\xa0\xff\xff\xff\xff\xf9\xfe\xe7 \xff\xff\xff\xff\xfa\xd3(\xa0\xff\xff\xff\xff\xfb\xe8\x03\xa0\xff\xff\xff\xff\xfc\xbcE \x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\xff\xff\xeb`\x00\x00\x00\x00\x00\x00" + + "\x01\x04\xff\xff\xf1\xf0\x00\b\x00\x00\x00\x00\x00\fLMT\x00+00\x00-01\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb7\x0e\xbdm\xb9\x01\x00\x00\xb9\x01" + + "\x00\x00\x0f\x00\x1c\x00Atlantic/FaeroeUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff\xff\x8bm\xa4X\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00" + + "\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10" + + "\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#\x90\xff\xff\xff\xff\xb3r" + + "\xa4\x90\xff\xff\xff\xff\xb4P \x90\xff\xff\xff\xff\xb72h\x90\xff\xff\xff\xff\xb8\x0f\xe4\x90\xff\xff\xff\xff\xb8\xffՐ\xff\xff\xff\xff\xb9\xefƐ\xff\xff\xff\xff\xbc\xc8\xd4\x10\xff\xff\xff\xff\xbd\xb8\xc5\x10\xff\xff" + + "\xff\xff\xbe\x9f{\x90\xff\xff\xff\xff\xbf\x98\xa7\x10\xff\xff\xff\xff\xc0\x9b\r\x10\xff\xff\xff\xff\xc1x\x89\x10\xff\xff\xff\xff\xc2hz\x10\xff\xff\xff\xff\xc3Xk\x10\xff\xff\xff\xff\xc4?!\x90\xff\xff\xff\xff\xc58" + + "M\x10\xff\xff\xff\xff\xc6:\xb3\x10\xff\xff\xff\xff\xc7XȐ\xff\xff\xff\xff\xc7\xd9\xfb\x90\xff\xff\xff\xff\xc9\x01K\x90\xff\xff\xff\xff\xc9\xf1<\x90\xff\xff\xff\xff\xca\xe2\u007f\x10\xff\xff\xff\xff˵o\x10\xff\xff" + + "\xff\xff\xcb\xec\xc0\x00\xff\xff\xff\xff̀h\x00\xff\xff\xff\xff\xccܿ\x10\xff\xff\xff\xff͕Q\x10\xff\xff\xff\xff\xcd\xc3g\x80\xff\xff\xff\xff\xcer\xbf\x00\xff\xff\xff\xff\xce\xc5ې\xff\xff\xff\xff\xcfu" + + "3\x10\xff\xff\xff\xffϬ\x84\x00\xff\xff\xff\xff\xd0R\xa1\x00\xff\xff\xff\xffХ\xbd\x90\xff\xff\xff\xff\xd1U\x15\x10\xff\xff\xff\xffьf\x00\xff\xff\xff\xff\xd22\x83\x00\xff\xff\xff\xff҅\x9f\x90\xff\xff" + + "\xff\xff\xd3Y\xe1\x10\xff\xff\xff\xff\xd4I\xd2\x10\xff\xff\xff\xff\xd59\xed@\xff\xff\xff\xff\xd6)\xde@\xff\xff\xff\xff\xd7\x19\xcf@\xff\xff\xff\xff\xd8\t\xc0@\xff\xff\xff\xff\xd8\xf9\xb1@\xff\xff\xff\xff\xd9\xe9" + + "\xa2@\xff\xff\xff\xff\xdaٓ@\xff\xff\xff\xff\xdbɄ@\xff\xff\xff\xffܹu@\xff\xff\xff\xffݲ\xa0\xc0\xff\xff\xff\xffޢ\x91\xc0\xff\xff\xff\xffߒ\x82\xc0\xff\xff\xff\xff\xe0\x82s\xc0\xff\xff" + + "\xff\xff\xe1rd\xc0\xff\xff\xff\xff\xe2bU\xc0\xff\xff\xff\xff\xe3RF\xc0\xff\xff\xff\xff\xe4B7\xc0\xff\xff\xff\xff\xe52(\xc0\xff\xff\xff\xff\xe6\"\x19\xc0\xff\xff\xff\xff\xe7\x1bE@\xff\xff\xff\xff\xe8\v" + + "6@\xff\xff\xff\xff\xe8\xfb'@\xff\xff\xff\xff\xe9\xeb\x18@\xff\xff\xff\xff\xea\xdb\t@\xff\xff\xff\xff\xeb\xca\xfa@\xff\xff\xff\xff\xec\xba\xeb@\xff\xff\xff\xff\xed\xaa\xdc@\xff\xff\xff\xff\xee\x9a\xcd@\xff\xff" + + "\xff\xff\uf2be@\xff\xff\xff\xff\xf0z\xaf@\xff\xff\xff\xff\xf1j\xa0@\xff\xff\xff\xff\xf2c\xcb\xc0\xff\xff\xff\xff\xf3S\xbc\xc0\xff\xff\xff\xff\xf4C\xad\xc0\xff\xff\xff\xff\xf53\x9e\xc0\xff\xff\xff\xff\xf6#" + + "\x8f\xc0\xff\xff\xff\xff\xf7\x13\x80\xc0\xff\xff\xff\xff\xf8\x03q\xc0\xff\xff\xff\xff\xf8\xf3b\xc0\x00\x00\x00\x00\r\x9b)\x10\x00\x00\x00\x00\x0e\x8b\x1a\x10\x00\x00\x00\x00\x0f\x84E\x90\x00\x00\x00\x00\x10t6\x90\x00\x00" + + "\x00\x00\x11d'\x90\x00\x00\x00\x00\x12T&\xa0\x00\x00\x00\x00\x13D\t\x90\x00\x00\x00\x00\x144\b\xa0\x00\x00\x00\x00\x15#\xf9\xa0\x00\x00\x00\x00\x16\x13\xea\xa0\x00\x00\x00\x00\x17\x03۠\x00\x00\x00\x00\x17\xf3" + + "̠\x00\x00\x00\x00\x18\xe3˰\x00\x00\x00\x00\x19Ӯ\xa0\x00\x00\x00\x00\x1aß\xa0\x00\x00\x00\x00\x1b\xbc\xcb \x00\x00\x00\x00\x1c\xac\xbc \x00\x00\x00\x00\x1d\x9c\xad \x00\x00\x00\x00\x1e\x8c\x9e \x00\x00" + + "\x00\x00\x1f|\x8f \x00\x00\x00\x00 l\x80 \x00\x00\x00\x00!\\q \x00\x00\x00\x00\"Lb \x00\x00\x00\x00#1<+00>,M3.5.0/0,M10.5.0/1\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\u0097N\xad\xaf\x00\x00\x00\xaf\x00" + + "\x00\x00\x13\x00\x1c\x00Atlantic/Cape_VerdeUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\f\xff\xff\xff\xff\x92檠\xff\xff\xff\xff̕\x9c \xff\xff\xff\xff\xd2t|\x10\x00\x00\x00\x00\v\x17\xf7@" + + "\x01\x02\x01\x03\xff\xff\xe9\xf4\x00\x00\xff\xff\xe3\xe0\x00\x04\xff\xff\xf1\xf0\x01\b\xff\xff\xf1\xf0\x00\bLMT\x00-02\x00-01\x00\n<-01>1\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82" + + "iSl&\x04\x99\x00\x04\x00\x00\x00\x04\x00\x00\x10\x00\x1c\x00Atlantic/BermudaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_" + + "\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00_\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xffi\x87\x18F\xff\xff\xff\xff\x9c̮F\xff\xff\xff\xff\x9d\xb7K" + + "6\xff\xff\xff\xff\x9e\xb8m\xc6\xff\xff\xff\xff\x9f\x84\xb86\xff\xff\xff\xff\xb4\xc3\x1d\xe6\xff\xff\xff\xff\xcbb\xa6\xe0\xff\xff\xff\xff\xccӼ\xd0\xff\xff\xff\xff͞\xd1\xe0\xff\xff\xff\xff\xce\xc6\x13\xd0\xff\xff\xff" + + "\xff\xcfuy`\xff\xff\xff\xffЯ0P\xff\xff\xff\xff\xd1U[`\xff\xff\xff\xffҏ\x12P\xff\xff\xff\xff\xd5qh`\xff\xff\xff\xff\xd6\x0e<\xd0\xff\xff\xff\xff\xd7Z\x84\xe0\xff\xff\xff\xff\xd7\xe4\xe4" + + "P\xff\xff\xff\xff\xd9:f\xe0\xff\xff\xff\xff\xd9\xc4\xc6P\xff\xff\xff\xff\xdb#\x83`\xff\xff\xff\xffۤ\xa8P\xff\xff\xff\xff\xdd\x03e`\xff\xff\xff\xff݄\x8aP\xff\xff\xff\xff\xde\xe3G`\xff\xff\xff" + + "\xff\xdfm\xa6\xd0\xff\xff\xff\xff\xe6l\t\xe0\xff\xff\xff\xff\xe77\x02\xd0\x00\x00\x00\x00\b \xb3`\x00\x00\x00\x00\t\x10\x96P\x00\x00\x00\x00\n\x00\x95`\x00\x00\x00\x00\n\xf0xP\x00\x00\x00\x00\v\xe0w" + + "`\x00\x00\x00\x00\fٔ\xd0\x00\x00\x00\x00\r\xc0Y`\x00\x00\x00\x00\x0e\xb9v\xd0\x00\x00\x00\x00\x0f\xa9u\xe0\x00\x00\x00\x00\x10\x99X\xd0\x00\x00\x00\x00\x11\x89W\xe0\x00\x00\x00\x00\x12y:\xd0\x00\x00\x00" + + "\x00\x13i9\xe0\x00\x00\x00\x00\x14Y\x1c\xd0\x00\x00\x00\x00\x15I\x1b\xe0\x00\x00\x00\x00\x168\xfe\xd0\x00\x00\x00\x00\x17(\xfd\xe0\x00\x00\x00\x00\x18\"\x1bP\x00\x00\x00\x00\x19\b\xdf\xe0\x00\x00\x00\x00\x1a\x01\xfd" + + "P\x00\x00\x00\x00\x1a\xf1\xfc`\x00\x00\x00\x00\x1b\xe1\xdfP\x00\x00\x00\x00\x1c\xd1\xde`\x00\x00\x00\x00\x1d\xc1\xc1P\x00\x00\x00\x00\x1e\xb1\xc0`\x00\x00\x00\x00\x1f\xa1\xa3P\x00\x00\x00\x00 u\xf2\xe0\x00\x00\x00" + + "\x00!\x81\x85P\x00\x00\x00\x00\"U\xd4\xe0\x00\x00\x00\x00#j\xa1\xd0\x00\x00\x00\x00$5\xb6\xe0\x00\x00\x00\x00%J\x83\xd0\x00\x00\x00\x00&\x15\x98\xe0\x00\x00\x00\x00'*e\xd0\x00\x00\x00\x00'\xfe\xb5" + + "`\x00\x00\x00\x00)\nG\xd0\x00\x00\x00\x00)ޗ`\x00\x00\x00\x00*\xea)\xd0\x00\x00\x00\x00+\xbey`\x00\x00\x00\x00,\xd3FP\x00\x00\x00\x00-\x9e[`\x00\x00\x00\x00.\xb3(P\x00\x00\x00" + + "\x00/~=`\x00\x00\x00\x000\x93\nP\x00\x00\x00\x001gY\xe0\x00\x00\x00\x002r\xecP\x00\x00\x00\x003G;\xe0\x00\x00\x00\x004R\xceP\x00\x00\x00\x005'\x1d\xe0\x00\x00\x00\x0062\xb0" + + "P\x00\x00\x00\x007\x06\xff\xe0\x00\x00\x00\x008\x1b\xcc\xd0\x00\x00\x00\x008\xe6\xe1\xe0\x00\x00\x00\x009\xfb\xae\xd0\x00\x00\x00\x00:\xc6\xc3\xe0\x00\x00\x00\x00;ې\xd0\x00\x00\x00\x00<\xaf\xe0`\x00\x00\x00" + + "\x00=\xbbr\xd0\x00\x00\x00\x00>\x8f\xc2`\x00\x00\x00\x00?\x9bT\xd0\x00\x00\x00\x00@o\xa4`\x00\x00\x00\x00A\x84qP\x00\x00\x00\x00BO\x86`\x00\x00\x00\x00CdSP\x00\x00\x00\x00D/h" + + "`\x00\x00\x00\x00ED5P\x00\x00\x00\x00E\xf3\x9a\xe0\x02\x01\x02\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03" + + "\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\xff\xff\xc3:\x00\x00\xff\xff" + + "\xd1J\x01\x04\xff\xff\xc3:\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xc7\xc0\x00\x10LMT\x00BST\x00BMT\x00ADT\x00AST\x00\nAST4ADT,M3.2.0,M1" + + "1.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb7\x0e\xbdm\xb9\x01\x00\x00\xb9\x01\x00\x00\x0e\x00\x1c\x00Atlantic/FaroeUT\t\x00\x03\x82\x0f\x8ba\x82" + + "\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00" + + "\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff\xff\x8bm\xa4" + + "X\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00" + + "\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT" + + "\x10\x00\x00\x00\x00#\xa2)P\x00\x00\x00\x00?Z\xc9`\x00\x00\x00\x00@" + + "\x82\vP\x00\x00\x00\x00A:\xab`\x00\x00\x00\x00Ba\xedP\x00\x00\x00\x00C\x1a\x8d`\x00\x00\x00\x00DA\xcfP\x00\x00\x00\x00D\xfao`\x00\x00\x00\x00F!\xb1P\x00\x00\x00\x00F\xdaQ`\x00" + + "\x00\x00\x00H\n\xcd\xd0\x00\x00\x00\x00H\xc3m\xe0\x00\x00\x00\x00I\xea\xaf\xd0\x00\x00\x00\x00J\xa3O\xe0\x00\x00\x00\x00Kʑ\xd0\x00\x00\x00\x00L\x831\xe0\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x05\x04\x05\x04\x05\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x05\xff\xff\xc9" + + "\xc4\x00\x00\xff\xff\xc9\xc4\x00\x04\xff\xff\xd5\xd0\x01\b\xff\xff\xc7\xc0\x00\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\bLMT\x00SMT\x00-03\x00-04\x00-02\x00\n<-03>3" + + "\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\x12\x00\x1c\x00Atlantic/St_HelenaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f" + + "\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" + + "\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x92\xe6\x92H" + + "\x01\xff\xff\xfc8\x00\x00\x00\x00\x00\x00\x00\x04LMT\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xaf|7\xb3\xde\x01\x00\x00\xde\x01\x00\x00\x0f\x00\x1c\x00Atl" + + "antic/CanaryUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff\xffV\xb6¸\xff\xff\xff\xff\xa2ec\xe0\xff\xff\xff\xff\xa3{\x82P\xff\xff\xff\xff\xa4N\x80`\xff\xff\xff\xff\xa5?\xb4\xd0\xff\xff\xff\xff\xa6" + - "%'\xe0\xff\xff\xff\xff\xa7'\u007f\xd0\xff\xff\xff\xff\xa8)\xf3\xe0\xff\xff\xff\xff\xa8\xeb\xb2P\xff\xff\xff\xff\xe8*\x85\xe0\xff\xff\xff\xff\xe8\xf4-P\xff\xff\xff\xff\xea\v\xb9`\xff\xff\xff\xff\xea\xd5`\xd0\xff" + - "\xff\xff\xff\xeb\xec\xec\xe0\xff\xff\xff\xff추P\xff\xff\xff\xff\xed\xcfq\xe0\xff\xff\xff\xff\xee\x99\x19P\xff\xff\xff\xffﰥ`\xff\xff\xff\xff\xf0zL\xd0\x00\x00\x00\x00\x04\xa6^`\x00\x00\x00\x00\x05" + - "+w\xd0\x00\x00\x00\x00\x06C\x03\xe0\x00\x00\x00\x00\a\f\xabP\x00\x00\x00\x00\b$7`\x00\x00\x00\x00\b\xed\xde\xd0\x00\x00\x00\x00\n\x05j\xe0\x00\x00\x00\x00\n\xcf\x12P\x00\x00\x00\x00\v\xe7\xef\xe0\x00" + - "\x00\x00\x00\f\xb1\x97P\x00\x00\x00\x00\r\xc9#`\x00\x00\x00\x00\x0e\x92\xca\xd0\x00\x00\x00\x00\x0f\xa9\x05`\x00\x00\x00\x00\x10r\xac\xd0\x00\x00\x00\x00\x1a\xf4.\xe0\x00\x00\x00\x00\x1bќ\xd0\x00\x00\x00\x00\x1c" + - "\xd5b`\x00\x00\x00\x00\x1d\xb2\xd0P\x00\x00\x00\x00\x1e\xb6\x95\xe0\x00\x00\x00\x00\x1f\x94\x03\xd0\x00\x00\x00\x00 \x97\xc9`\x00\x00\x00\x00!u7P\x00\x00\x00\x00\"\xa3,\xe0\x00\x00\x00\x00#W\xbcP\x00" + - "\x00\x00\x00$g_`\x00\x00\x00\x00%8\xef\xd0\x00\x00\x00\x00&<\xb5`\x00\x00\x00\x00'\x1a#P\x00\x00\x00\x00(\x1d\xe8\xe0\x00\x00\x00\x00(\xfbV\xd0\x00\x00\x00\x00*\x00m\xe0\x00\x00\x00\x00*" + - "\xce\t\xd0\x00\x00\x00\x00+\xb4\xce`\x00\x00\x00\x00,\xa4\xb1P\x00\x00\x00\x00-\x94\xb0`\x00\x00\x00\x00.\x84\x93P\x00\x00\x00\x00/t\x92`\x00\x00\x00\x000duP\x00\x00\x00\x001]\xae\xe0\x00" + - "\x00\x00\x002M\x91\xd0\x00\x00\x00\x003=\x90\xe0\x00\x00\x00\x004-s\xd0\x00\x00\x00\x005\x1dr\xe0\x00\x00\x00\x006\rU\xd0\x00\x00\x00\x006\xfdT\xe0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00!H\x00\x00\x00\x00*" + - "0\x01\x04\x00\x00\x1c \x00\tLMT\x00EEST\x00EET\x00\nEET-2EEST,M3.5.0/0,M10.5.0/0\nPK\x03\x04\n\x00\x00\x00" + - "\x00\x00\xf1c9Rb\xadű\xf8\x00\x00\x00\xf8\x00\x00\x00\f\x00\x1c\x00Asia/JakartaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03" + - "\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\x00\x00\x00\a\x00\x00\x00 \xff\xff\xff\xff?fI`\xff\xff\xff\xff\xa9x\x85\xe0\xff\xff\xff\xff\xba\x16\xde" + - "`\xff\xff\xff\xff˿\x83\x88\xff\xff\xff\xff\xd2V\xeep\xff\xff\xff\xff\xd7<\xc6\b\xff\xff\xff\xff\xda\xff&\x00\xff\xff\xff\xff\xf4\xb5\xbe\x88\x01\x02\x03\x04\x03\x05\x03\x06\x00\x00d \x00\x00\x00\x00d \x00" + - "\x04\x00\x00g \x00\b\x00\x00ix\x00\x0e\x00\x00~\x90\x00\x14\x00\x00p\x80\x00\x18\x00\x00bp\x00\x1cLMT\x00BMT\x00+0720\x00+0730\x00+09\x00+08\x00W" + - "IB\x00\nWIB-7\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xed\x8c\xf1\x91\x85\x00\x00\x00\x85\x00\x00\x00\n\x00\x1c\x00Asia/DubaiUT\t\x00\x03\x15\xac\x0e`\x15" + - "\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00" + - "\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\xa1\xf2\x99" + - "\xa8\x01\x00\x003\xd8\x00\x00\x00\x008@\x00\x04LMT\x00+04\x00\n<+04>-4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xa1\xfax\x98g\x02\x00\x00g\x02\x00\x00\r\x00\x1c" + - "\x00Asia/QostanayUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x003\x00\x00\x00\x06\x00\x00\x00\x10\xff\xff\xff\xff\xaa\x19\x88\\\xff\xff\xff\xff\xb5\xa3\xfd@\x00\x00\x00\x00\x15'\x8b\xb0\x00\x00\x00\x00\x16\x18\xc0 \x00\x00\x00\x00\x17\b\xb1 \x00\x00\x00" + - "\x00\x17\xf9\xf3\xa0\x00\x00\x00\x00\x18\xe9\xf2\xb0\x00\x00\x00\x00\x19\xdb' \x00\x00\x00\x00\x1a\xccw\xb0\x00\x00\x00\x00\x1b\xbc\x84\xd0\x00\x00\x00\x00\x1c\xacu\xd0\x00\x00\x00\x00\x1d\x9cf\xd0\x00\x00\x00\x00\x1e\x8cW" + - "\xd0\x00\x00\x00\x00\x1f|H\xd0\x00\x00\x00\x00 l9\xd0\x00\x00\x00\x00!\\*\xd0\x00\x00\x00\x00\"L\x1b\xd0\x00\x00\x00\x00#<\f\xd0\x00\x00\x00\x00$+\xfd\xd0\x00\x00\x00\x00%\x1b\xee\xd0\x00\x00\x00" + - "\x00&\v\xdf\xd0\x00\x00\x00\x00'\x05\vP\x00\x00\x00\x00'\xf4\xfcP\x00\x00\x00\x00(\xe4\xfb`\x00\x00\x00\x00)x\xa3`\x00\x00\x00\x00)\xd4\xdeP\x00\x00\x00\x00*\xc4\xcfP\x00\x00\x00\x00+\xb4\xc0" + - "P\x00\x00\x00\x00,\xa4\xb1P\x00\x00\x00\x00-\x94\xa2P\x00\x00\x00\x00.\x84\x93P\x00\x00\x00\x00/t\x84P\x00\x00\x00\x000duP\x00\x00\x00\x001]\xa0\xd0\x00\x00\x00\x002r{\xd0\x00\x00\x00" + - "\x003=\x82\xd0\x00\x00\x00\x004R]\xd0\x00\x00\x00\x005\x1dd\xd0\x00\x00\x00\x0062?\xd0\x00\x00\x00\x006\xfdF\xd0\x00\x00\x00\x008\x1b\\P\x00\x00\x00\x008\xdd(\xd0\x00\x00\x00\x009\xfb>" + - "P\x00\x00\x00\x00:\xbd\n\xd0\x00\x00\x00\x00;\xdb P\x00\x00\x00\x00<\xa6'P\x00\x00\x00\x00=\xbb\x02P\x00\x00\x00\x00>\x86\tP\x00\x00\x00\x00?\x9a\xe4P\x00\x00\x00\x00@e\xebP\x00\x00\x00" + - "\x00A\x84\x00\xd0\x01\x02\x03\x04\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x05\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x00\x00;\xa4" + - "\x00\x00\x00\x008@\x00\x04\x00\x00FP\x00\b\x00\x00T`\x01\f\x00\x00T`\x00\f\x00\x00FP\x01\bLMT\x00+04\x00+05\x00+06\x00\n<+06>-6\nPK\x03" + - "\x04\n\x00\x00\x00\x00\x00\xf1c9R*\xe4@\xa9\x89\x01\x00\x00\x89\x01\x00\x00\v\x00\x1c\x00Asia/HarbinUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00" + - "\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZi" + - "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff~6C)\xff\xff\xff\xff\xa0\x97\xa2\x80\xff\xff\xff" + - "\xff\xa1y\x04\xf0\xff\xff\xff\xff\xc8Y^\x80\xff\xff\xff\xff\xc9\t\xf9p\xff\xff\xff\xff\xc9ӽ\x00\xff\xff\xff\xff\xcb\x05\x8a\xf0\xff\xff\xff\xff\xcb|@\x00\xff\xff\xff\xff\xd2;>\xf0\xff\xff\xff\xffӋ{" + - "\x80\xff\xff\xff\xff\xd4B\xad\xf0\xff\xff\xff\xff\xd5E\"\x00\xff\xff\xff\xff\xd6L\xbf\xf0\xff\xff\xff\xff\xd7<\xbf\x00\xff\xff\xff\xff\xd8\x06fp\xff\xff\xff\xff\xd9\x1d\xf2\x80\xff\xff\xff\xff\xd9A|\xf0\x00\x00\x00" + - "\x00\x1e\xbaR \x00\x00\x00\x00\x1fi\x9b\x90\x00\x00\x00\x00 ~\x84\xa0\x00\x00\x00\x00!I}\x90\x00\x00\x00\x00\"g\xa1 \x00\x00\x00\x00#)_\x90\x00\x00\x00\x00$G\x83 \x00\x00\x00\x00%\x12|" + - "\x10\x00\x00\x00\x00&'e \x00\x00\x00\x00&\xf2^\x10\x00\x00\x00\x00(\aG \x00\x00\x00\x00(\xd2@\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x00\x00q\xd7\x00\x00\x00\x00~\x90\x01\x04\x00\x00p\x80\x00\bLMT\x00CDT\x00CST\x00\nCST-8\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\t\x00\x1c\x00Atlantic/UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R" + - "\u0097N\xad\xaf\x00\x00\x00\xaf\x00\x00\x00\x13\x00\x1c\x00Atlantic/Cape_VerdeUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8" + - "\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\f\xff\xff\xff\xff\x92檠\xff\xff\xff\xff̕\x9c \xff\xff\xff\xff\xd2t" + - "|\x10\x00\x00\x00\x00\v\x17\xf7@\x01\x02\x01\x03\xff\xff\xe9\xf4\x00\x00\xff\xff\xe3\xe0\x00\x04\xff\xff\xf1\xf0\x01\b\xff\xff\xf1\xf0\x00\bLMT\x00-02\x00-01\x00\n<-01>1\nPK" + - "\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xe7\xcf^\xb0\x15\x03\x00\x00\x15\x03\x00\x00\x10\x00\x1c\x00Atlantic/StanleyUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v" + - "\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00" + - "\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00F\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffi\x87\x11\xbc\xff\xff\xff\xff\x93" + - "D_<\xff\xff\xff\xff\xc3OZ\xc0\xff\xff\xff\xff\xc46\x030\xff\xff\xff\xff\xc5/<\xc0\xff\xff\xff\xff\xc6\x15\xe50\xff\xff\xff\xff\xc7\x18Y@\xff\xff\xff\xff\xc7\xff\x01\xb0\xff\xff\xff\xff\xc8\xf8;@\xff" + - "\xff\xff\xff\xc9\xde\xe3\xb0\xff\xff\xff\xff\xca\xd8\x1d@\xff\xff\xff\xff˾Ű\xff\xff\xff\xff̷\xff@\xff\xff\xff\xff\xcd6\x810\x00\x00\x00\x00\x19\x11\xfe@\x00\x00\x00\x00\x19Ӽ\xb0\x00\x00\x00\x00\x1a" + - "\xf1\xc4 \x00\x00\x00\x00\x1b\xaad0\x00\x00\x00\x00\x1cѦ \x00\x00\x00\x00\x1d\x8aF0\x00\x00\x00\x00\x1e\xa8[\xb0\x00\x00\x00\x00\x1fj6@\x00\x00\x00\x00 \x88=\xb0\x00\x00\x00\x00!J\x18@\x00" + - "\x00\x00\x00\"h\x1f\xb0\x00\x00\x00\x00#)\xfa@\x00\x00\x00\x00$H\x01\xb0\x00\x00\x00\x00%\t\xdc@\x00\x00\x00\x00&1\x1e0\x00\x00\x00\x00&\xe9\xbe@\x00\x00\x00\x00(\x11\x000\x00\x00\x00\x00(" + - "\xd2\xda\xc0\x00\x00\x00\x00)\xf0\xe20\x00\x00\x00\x00*\xb2\xbc\xc0\x00\x00\x00\x00+\xd0\xc40\x00\x00\x00\x00,\x92\x9e\xc0\x00\x00\x00\x00-\xb0\xa60\x00\x00\x00\x00.r\x80\xc0\x00\x00\x00\x00/\x90\x880\x00" + - "\x00\x00\x000Rb\xc0\x00\x00\x00\x001y\xa4\xb0\x00\x00\x00\x002;\u007f@\x00\x00\x00\x003Y\x86\xb0\x00\x00\x00\x004\x1ba@\x00\x00\x00\x0059h\xb0\x00\x00\x00\x005\xfbC@\x00\x00\x00\x007" + - "\x19J\xb0\x00\x00\x00\x007\xdb%@\x00\x00\x00\x008\xf9,\xb0\x00\x00\x00\x009\xbb\a@\x00\x00\x00\x00:\xd9*\xd0\x00\x00\x00\x00;\x91\xca\xe0\x00\x00\x00\x00<\xc2GP\x00\x00\x00\x00=q\xac\xe0\x00" + - "\x00\x00\x00>\xa2)P\x00\x00\x00\x00?Z\xc9`\x00\x00\x00\x00@\x82\vP\x00\x00\x00\x00A:\xab`\x00\x00\x00\x00Ba\xedP\x00\x00\x00\x00C\x1a\x8d`\x00\x00\x00\x00DA\xcfP\x00\x00\x00\x00D" + - "\xfao`\x00\x00\x00\x00F!\xb1P\x00\x00\x00\x00F\xdaQ`\x00\x00\x00\x00H\n\xcd\xd0\x00\x00\x00\x00H\xc3m\xe0\x00\x00\x00\x00I\xea\xaf\xd0\x00\x00\x00\x00J\xa3O\xe0\x00\x00\x00\x00Kʑ\xd0\x00" + - "\x00\x00\x00L\x831\xe0\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x05\x04\x05\x04\x05\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x05\xff\xff\xc9\xc4\x00\x00\xff\xff\xc9\xc4\x00\x04\xff\xff\xd5\xd0\x01\b\xff\xff\xc7\xc0\x00\f\xff\xff\xe3\xe0\x01\x10\xff\xff\xd5\xd0\x00\bLMT\x00SMT" + - "\x00-03\x00-04\x00-02\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x82\xfa Z\x9b\x05\x00\x00\x9b\x05\x00\x00\x10\x00\x1c\x00Atlantic/" + - "MadeiraUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x8a\x00\x00\x00\a\x00\x00\x00\x1d\xff\xff\xff\xff^=\x13X\xff\xff\xff\xff\x92朐\xff\xff\xff\xff\x9bK{\x80\xff\xff\xff\xff\x9b\xfeՐ\xff\xff\xff\xff\x9c\x9c\xfb\x80\xff\xff\xff\xff\x9dɑ\x80\xff\xff" + - "\xff\xff\x9e\u007f\x80\x80\xff\xff\xff\xff\x9f\xaa\xc5\x00\xff\xff\xff\xff\xa0_b\x80\xff\xff\xff\xff\xa1\x8b\xf8\x80\xff\xff\xff\xff\xa2A\xe7\x80\xff\xff\xff\xff\xa3n}\x80\xff\xff\xff\xff\xa4#\x1b\x00\xff\xff\xff\xff\xa5O" + - "\xb1\x00\xff\xff\xff\xff\xaa\x05\xfd\x80\xff\xff\xff\xff\xaa\xf4\x9d\x00\xff\xff\xff\xff\xadɶ\x00\xff\xff\xff\xff\xae\xa72\x00\xff\xff\xff\xff\xaf\xa0]\x80\xff\xff\xff\xff\xb0\x87\x14\x00\xff\xff\xff\xff\xb1\x89z\x00\xff\xff" + - "\xff\xff\xb2p0\x80\xff\xff\xff\xff\xb3r\x96\x80\xff\xff\xff\xff\xb4P\x12\x80\xff\xff\xff\xff\xb72Z\x80\xff\xff\xff\xff\xb8\x0fր\xff\xff\xff\xff\xb8\xffǀ\xff\xff\xff\xff\xb9︀\xff\xff\xff\xff\xbc\xc8" + - "\xc6\x00\xff\xff\xff\xff\xbd\xb8\xb7\x00\xff\xff\xff\xff\xbe\x9fm\x80\xff\xff\xff\xff\xbf\x98\x99\x00\xff\xff\xff\xff\xc0\x9a\xff\x00\xff\xff\xff\xff\xc1x{\x00\xff\xff\xff\xff\xc2hl\x00\xff\xff\xff\xff\xc3X]\x00\xff\xff" + - "\xff\xff\xc4?\x13\x80\xff\xff\xff\xff\xc58?\x00\xff\xff\xff\xff\xc6:\xa5\x00\xff\xff\xff\xff\xc7X\xba\x80\xff\xff\xff\xff\xc7\xd9\xed\x80\xff\xff\xff\xff\xc9\x01=\x80\xff\xff\xff\xff\xc9\xf1.\x80\xff\xff\xff\xff\xca\xe2" + - "q\x00\xff\xff\xff\xff˵a\x00\xff\xff\xff\xff\xcb\xec\xb1\xf0\xff\xff\xff\xff̀Y\xf0\xff\xff\xff\xff\xccܱ\x00\xff\xff\xff\xff͕C\x00\xff\xff\xff\xff\xcd\xc3Yp\xff\xff\xff\xff\xcer\xb0\xf0\xff\xff" + - "\xff\xff\xce\xc5̀\xff\xff\xff\xff\xcfu%\x00\xff\xff\xff\xffϬu\xf0\xff\xff\xff\xff\xd0R\x92\xf0\xff\xff\xff\xffХ\xaf\x80\xff\xff\xff\xff\xd1U\a\x00\xff\xff\xff\xffьW\xf0\xff\xff\xff\xff\xd22" + - "t\xf0\xff\xff\xff\xff҅\x91\x80\xff\xff\xff\xff\xd3Y\xd3\x00\xff\xff\xff\xff\xd4I\xc4\x00\xff\xff\xff\xff\xd59\xdf0\xff\xff\xff\xff\xd6)\xd00\xff\xff\xff\xff\xd7\x19\xc10\xff\xff\xff\xff\xd8\t\xb20\xff\xff" + - "\xff\xff\xd8\xf9\xa30\xff\xff\xff\xff\xd9\xe9\x940\xff\xff\xff\xffܹg0\xff\xff\xff\xffݲ\x92\xb0\xff\xff\xff\xffޢ\x83\xb0\xff\xff\xff\xffߒt\xb0\xff\xff\xff\xff\xe0\x82e\xb0\xff\xff\xff\xff\xe1r" + - "V\xb0\xff\xff\xff\xff\xe2bG\xb0\xff\xff\xff\xff\xe3R8\xb0\xff\xff\xff\xff\xe4B)\xb0\xff\xff\xff\xff\xe52\x1a\xb0\xff\xff\xff\xff\xe6\"\v\xb0\xff\xff\xff\xff\xe7\x1b70\xff\xff\xff\xff\xe8\v(0\xff\xff" + - "\xff\xff\xe8\xfb\x190\xff\xff\xff\xff\xe9\xeb\n0\xff\xff\xff\xff\xea\xda\xfb0\xff\xff\xff\xff\xeb\xca\xec0\xff\xff\xff\xff\xec\xba\xdd0\xff\xff\xff\xff\xed\xaa\xce0\xff\xff\xff\xff\ue6bf0\xff\xff\xff\xff\xef\x8a" + - "\xb00\xff\xff\xff\xff\xf0z\xa10\xff\xff\xff\xff\xf1j\x920\xff\xff\xff\xff\xf2c\xbd\xb0\xff\xff\xff\xff\xf3S\xae\xb0\xff\xff\xff\xff\xf4C\x9f\xb0\xff\xff\xff\xff\xf53\x90\xb0\xff\xff\xff\xff\xf6#\x81\xb0\xff\xff" + - "\xff\xff\xf7\x13r\xb0\xff\xff\xff\xff\xf8\x03c\xb0\xff\xff\xff\xff\xf8\xf3T\xb0\x00\x00\x00\x00\r\x9b\x1b\x00\x00\x00\x00\x00\x0e\x8b\f\x00\x00\x00\x00\x00\x0f\x847\x80\x00\x00\x00\x00\x10t(\x80\x00\x00\x00\x00\x11d" + - "\x19\x80\x00\x00\x00\x00\x12T\x18\x90\x00\x00\x00\x00\x13C\xfb\x80\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00" + - "\x00\x00\x18㽠\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|" + - "\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#\x8f\xc2`\x00\x00\x00\x00?" + - "\x9bT\xd0\x00\x00\x00\x00@o\xa4`\x00\x00\x00\x00A\x84qP\x00\x00\x00\x00BO\x86`\x00\x00\x00\x00CdSP\x00\x00\x00\x00D/h`\x00\x00\x00\x00ED5P\x00\x00\x00\x00E\xf3\x9a\xe0\x02" + - "\x01\x02\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03" + - "\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\xff\xff\xc3:\x00\x00\xff\xff\xd1J\x01\x04\xff\xff\xc3:\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff" + - "\xc7\xc0\x00\x10LMT\x00BST\x00BMT\x00ADT\x00AST\x00\nAST4ADT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c" + - "9R\xaf|7\xb3\xde\x01\x00\x00\xde\x01\x00\x00\x0f\x00\x1c\x00Atlantic/CanaryUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00" + - "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00#\x00\x00\x00\x04\x00\x00\x00\x11\xff\xff\xff\xff\xa6\x04\\\xf0\xff\xff\xff\xff\xd4A\xf7 \x00\x00\x00\x00\x13M6\x00" + - "\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00" + - "\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10" + - "\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#2\nPK\x03\x04\n\x00\x00\x00\x00" + - "\x00\xf1c9R\xb7\x0e\xbdm\xb9\x01\x00\x00\xb9\x01\x00\x00\x0f\x00\x1c\x00Atlantic/FaeroeUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04" + - "\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff\xff\x8bm\xa4X\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16" + + "\x00\x00\x00\x00\x00\x00#\x00\x00\x00\x04\x00\x00\x00\x11\xff\xff\xff\xff\xa6\x04\\\xf0\xff\xff\xff\xff\xd4A\xf7 \x00\x00\x00\x00\x13M6\x00\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16" + "\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00" + "\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#\x90\xff\xff\xff\xff\xb3r\xa4\x90\xff\xff\xff\xff\xb4P \x90\xff\xff\xff\xff\xb72h\x90\xff\xff\xff\xff\xb8\x0f\xe4\x90\xff\xff\xff\xff\xb8\xffՐ\xff\xff\xff\xff\xb9\xefƐ\xff\xff\xff" + - "\xff\xbc\xc8\xd4\x10\xff\xff\xff\xff\xbd\xb8\xc5\x10\xff\xff\xff\xff\xbe\x9f{\x90\xff\xff\xff\xff\xbf\x98\xa7\x10\xff\xff\xff\xff\xc0\x9b\r\x10\xff\xff\xff\xff\xc1x\x89\x10\xff\xff\xff\xff\xc2hz\x10\xff\xff\xff\xff\xc3Xk" + - "\x10\xff\xff\xff\xff\xc4?!\x90\xff\xff\xff\xff\xc58M\x10\xff\xff\xff\xff\xc6:\xb3\x10\xff\xff\xff\xff\xc7XȐ\xff\xff\xff\xff\xc7\xd9\xfb\x90\xff\xff\xff\xff\xc9\x01K\x90\xff\xff\xff\xff\xc9\xf1<\x90\xff\xff\xff" + - "\xff\xca\xe2\u007f\x10\xff\xff\xff\xff˵o\x10\xff\xff\xff\xff\xcb\xec\xc0\x00\xff\xff\xff\xff̀h\x00\xff\xff\xff\xff\xccܿ\x10\xff\xff\xff\xff͕Q\x10\xff\xff\xff\xff\xcd\xc3g\x80\xff\xff\xff\xff\xcer\xbf" + - "\x00\xff\xff\xff\xff\xce\xc5ې\xff\xff\xff\xff\xcfu3\x10\xff\xff\xff\xffϬ\x84\x00\xff\xff\xff\xff\xd0R\xa1\x00\xff\xff\xff\xffХ\xbd\x90\xff\xff\xff\xff\xd1U\x15\x10\xff\xff\xff\xffьf\x00\xff\xff\xff" + - "\xff\xd22\x83\x00\xff\xff\xff\xff҅\x9f\x90\xff\xff\xff\xff\xd3Y\xe1\x10\xff\xff\xff\xff\xd4I\xd2\x10\xff\xff\xff\xff\xd59\xed@\xff\xff\xff\xff\xd6)\xde@\xff\xff\xff\xff\xd7\x19\xcf@\xff\xff\xff\xff\xd8\t\xc0" + - "@\xff\xff\xff\xff\xd8\xf9\xb1@\xff\xff\xff\xff\xd9\xe9\xa2@\xff\xff\xff\xffܹu@\xff\xff\xff\xffݲ\xa0\xc0\xff\xff\xff\xffޢ\x91\xc0\xff\xff\xff\xffߒ\x82\xc0\xff\xff\xff\xff\xe0\x82s\xc0\xff\xff\xff" + - "\xff\xe1rd\xc0\xff\xff\xff\xff\xe2bU\xc0\xff\xff\xff\xff\xe3RF\xc0\xff\xff\xff\xff\xe4B7\xc0\xff\xff\xff\xff\xe52(\xc0\xff\xff\xff\xff\xe6\"\x19\xc0\xff\xff\xff\xff\xe7\x1bE@\xff\xff\xff\xff\xe8\v6" + - "@\xff\xff\xff\xff\xe8\xfb'@\xff\xff\xff\xff\xe9\xeb\x18@\xff\xff\xff\xff\xea\xdb\t@\xff\xff\xff\xff\xeb\xca\xfa@\xff\xff\xff\xff\xec\xba\xeb@\xff\xff\xff\xff\xed\xaa\xdc@\xff\xff\xff\xff\xee\x9a\xcd@\xff\xff\xff" + - "\xff\uf2be@\xff\xff\xff\xff\xf0z\xaf@\xff\xff\xff\xff\xf1j\xa0@\xff\xff\xff\xff\xf2c\xcb\xc0\xff\xff\xff\xff\xf3S\xbc\xc0\xff\xff\xff\xff\xf4C\xad\xc0\xff\xff\xff\xff\xf53\x9e\xc0\xff\xff\xff\xff\xf6#\x8f" + - "\xc0\xff\xff\xff\xff\xf7\x13\x80\xc0\xff\xff\xff\xff\xf8\x03q\xc0\xff\xff\xff\xff\xf8\xf3b\xc0\x00\x00\x00\x00\r\x9b)\x10\x00\x00\x00\x00\x0e\x8b\x1a\x10\x00\x00\x00\x00\x0f\x84E\x90\x00\x00\x00\x00\x10t6\x90\x00\x00\x00" + - "\x00\x11d'\x90\x00\x00\x00\x00\x12T&\xa0\x00\x00\x00\x00\x13D\t\x90\x00\x00\x00\x00\x144\b\xa0\x00\x00\x00\x00\x15#\xf9\xa0\x00\x00\x00\x00\x16\x13\xea\xa0\x00\x00\x00\x00\x17\x03۠\x00\x00\x00\x00\x17\xf3\xcc" + - "\xa0\x00\x00\x00\x00\x18\xe3˰\x00\x00\x00\x00\x19Ӯ\xa0\x00\x00\x00\x00\x1aß\xa0\x00\x00\x00\x00\x1b\xbc\xcb \x00\x00\x00\x00\x1c\xac\xbc \x00\x00\x00\x00\x1d\x9c\xad \x00\x00\x00\x00\x1e\x8c\x9e \x00\x00\x00" + - "\x00\x1f|\x8f \x00\x00\x00\x00 l\x80 \x00\x00\x00\x00!\\q \x00\x00\x00\x00\"Lb \x00\x00\x00\x00#1<+00>,M3.5.0/0,M10.5.0/1\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n" + - "\x00\x1c\x00Australia/UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RX\xb9\x9ap\x88" + - "\x03\x00\x00\x88\x03\x00\x00\r\x00\x1c\x00Australia/NSWUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00S\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xffs\x16\u007f<\xff\xff\xff\xff\x9cN\u0080\xff\xff\xff\xff\x9c\xbc/\x00\xff\xff\xff\xff\xcbT\xb3\x00\xff" + - "\xff\xff\xff\xcb\xc7e\x80\xff\xff\xff\xff̷V\x80\xff\xff\xff\xffͧG\x80\xff\xff\xff\xffΠs\x00\xff\xff\xff\xffχ)\x80\x00\x00\x00\x00\x03p9\x80\x00\x00\x00\x00\x04\r\x1c\x00\x00\x00\x00\x00\x05" + - "P\x1b\x80\x00\x00\x00\x00\x05\xf68\x80\x00\x00\x00\x00\a/\xfd\x80\x00\x00\x00\x00\a\xd6\x1a\x80\x00\x00\x00\x00\t\x0f߀\x00\x00\x00\x00\t\xb5\xfc\x80\x00\x00\x00\x00\n\xef\xc1\x80\x00\x00\x00\x00\v\x9f\x19\x00\x00" + - "\x00\x00\x00\f\xd8\xde\x00\x00\x00\x00\x00\r~\xfb\x00\x00\x00\x00\x00\x0e\xb8\xc0\x00\x00\x00\x00\x00\x0f^\xdd\x00\x00\x00\x00\x00\x10\x98\xa2\x00\x00\x00\x00\x00\x11>\xbf\x00\x00\x00\x00\x00\x12x\x84\x00\x00\x00\x00\x00\x13" + - "\x1e\xa1\x00\x00\x00\x00\x00\x14Xf\x00\x00\x00\x00\x00\x14\xfe\x83\x00\x00\x00\x00\x00\x168H\x00\x00\x00\x00\x00\x17\f\x89\x80\x00\x00\x00\x00\x18!d\x80\x00\x00\x00\x00\x18ǁ\x80\x00\x00\x00\x00\x1a\x01F\x80\x00" + - "\x00\x00\x00\x1a\xa7c\x80\x00\x00\x00\x00\x1b\xe1(\x80\x00\x00\x00\x00\x1c\x87E\x80\x00\x00\x00\x00\x1d\xc1\n\x80\x00\x00\x00\x00\x1ey\x9c\x80\x00\x00\x00\x00\x1f\x97\xb2\x00\x00\x00\x00\x00 Y~\x80\x00\x00\x00\x00!" + - "\x80\u0380\x00\x00\x00\x00\"B\x9b\x00\x00\x00\x00\x00#i\xeb\x00\x00\x00\x00\x00$\"}\x00\x00\x00\x00\x00%I\xcd\x00\x00\x00\x00\x00%\xef\xea\x00\x00\x00\x00\x00')\xaf\x00\x00\x00\x00\x00'\xcf\xcc\x00\x00" + - "\x00\x00\x00)\t\x91\x00\x00\x00\x00\x00)\xaf\xae\x00\x00\x00\x00\x00*\xe9s\x00\x00\x00\x00\x00+\x98ʀ\x00\x00\x00\x00,ҏ\x80\x00\x00\x00\x00-x\xac\x80\x00\x00\x00\x00.\xb2q\x80\x00\x00\x00\x00/" + - "X\x8e\x80\x00\x00\x00\x000\x92S\x80\x00\x00\x00\x001]Z\x80\x00\x00\x00\x002r5\x80\x00\x00\x00\x003=<\x80\x00\x00\x00\x004R\x17\x80\x00\x00\x00\x005\x1d\x1e\x80\x00\x00\x00\x0061\xf9\x80\x00" + - "\x00\x00\x006\xfd\x00\x80\x00\x00\x00\x008\x1b\x16\x00\x00\x00\x00\x008\xdc\xe2\x80\x00\x00\x00\x009\xa7\xe9\x80\x00\x00\x00\x00:\xbcĀ\x00\x00\x00\x00;\xda\xda\x00\x00\x00\x00\x00<\xa5\xe1\x00\x00\x00\x00\x00=" + - "\xba\xbc\x00\x00\x00\x00\x00>\x85\xc3\x00\x00\x00\x00\x00?\x9a\x9e\x00\x00\x00\x00\x00@e\xa5\x00\x00\x00\x00\x00A\x83\xba\x80\x00\x00\x00\x00BE\x87\x00\x00\x00\x00\x00Cc\x9c\x80\x00\x00\x00\x00D.\xa3\x80\x00" + - "\x00\x00\x00EC~\x80\x00\x00\x00\x00F\x05K\x00\x00\x00\x00\x00G#`\x80\x00\x00\x00\x00G\xf7\xa2\x00\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\x8d\xc4\x00\x00" + - "\x00\x00\x9a\xb0\x01\x04\x00\x00\x8c\xa0\x00\tLMT\x00AEDT\x00AEST\x00\nAEST-10AEDT,M10.1.0,M4.1.0/3\nPK\x03\x04" + - "\n\x00\x00\x00\x00\x00\xf1c9R\x8ff~ՙ\x03\x00\x00\x99\x03\x00\x00\x12\x00\x1c\x00Australia/AdelaideUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v" + - "\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00" + - "\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00T\x00\x00\x00\x04\x00\x00\x00\x0e\xff\xff\xff\xffs\x16\x8b\x14\xff\xff\xff\xff{" + - "\x12\x03p\xff\xff\xff\xff\x9cNɈ\xff\xff\xff\xff\x9c\xbc6\b\xff\xff\xff\xff\xcbT\xba\b\xff\xff\xff\xff\xcb\xc7l\x88\xff\xff\xff\xff̷]\x88\xff\xff\xff\xffͧN\x88\xff\xff\xff\xffΠz\b\xff" + - "\xff\xff\xffχ0\x88\x00\x00\x00\x00\x03p@\x88\x00\x00\x00\x00\x04\r#\b\x00\x00\x00\x00\x05P\"\x88\x00\x00\x00\x00\x05\xf6?\x88\x00\x00\x00\x00\a0\x04\x88\x00\x00\x00\x00\a\xd6!\x88\x00\x00\x00\x00\t" + - "\x0f\xe6\x88\x00\x00\x00\x00\t\xb6\x03\x88\x00\x00\x00\x00\n\xefȈ\x00\x00\x00\x00\v\x9f \b\x00\x00\x00\x00\f\xd8\xe5\b\x00\x00\x00\x00\r\u007f\x02\b\x00\x00\x00\x00\x0e\xb8\xc7\b\x00\x00\x00\x00\x0f^\xe4\b\x00" + - "\x00\x00\x00\x10\x98\xa9\b\x00\x00\x00\x00\x11>\xc6\b\x00\x00\x00\x00\x12x\x8b\b\x00\x00\x00\x00\x13\x1e\xa8\b\x00\x00\x00\x00\x14Xm\b\x00\x00\x00\x00\x14\xfe\x8a\b\x00\x00\x00\x00\x168O\b\x00\x00\x00\x00\x16" + - "禈\x00\x00\x00\x00\x18!k\x88\x00\x00\x00\x00\x18Lj\x88\x00\x00\x00\x00\x1a\x01M\x88\x00\x00\x00\x00\x1a\xa7j\x88\x00\x00\x00\x00\x1b\xe1/\x88\x00\x00\x00\x00\x1c\x87L\x88\x00\x00\x00\x00\x1d\xc1\x11\x88\x00" + - "\x00\x00\x00\x1ey\xa3\x88\x00\x00\x00\x00\x1f\x97\xb9\b\x00\x00\x00\x00 Y\x85\x88\x00\x00\x00\x00!\x80Ո\x00\x00\x00\x00\"B\xa2\b\x00\x00\x00\x00#i\xf2\b\x00\x00\x00\x00$\"\x84\b\x00\x00\x00\x00%" + - "I\xd4\b\x00\x00\x00\x00&\x02f\b\x00\x00\x00\x00')\xb6\b\x00\x00\x00\x00'\xcf\xd3\b\x00\x00\x00\x00)\t\x98\b\x00\x00\x00\x00)\xcbd\x88\x00\x00\x00\x00*\xe9z\b\x00\x00\x00\x00+\x98ш\x00" + - "\x00\x00\x00,Җ\x88\x00\x00\x00\x00-\x8b(\x88\x00\x00\x00\x00.\xb2x\x88\x00\x00\x00\x00/tE\b\x00\x00\x00\x000\x92Z\x88\x00\x00\x00\x001]a\x88\x00\x00\x00\x002r<\x88\x00\x00\x00\x003" + - "=C\x88\x00\x00\x00\x004R\x1e\x88\x00\x00\x00\x005\x1d%\x88\x00\x00\x00\x0062\x00\x88\x00\x00\x00\x006\xfd\a\x88\x00\x00\x00\x008\x1b\x1d\b\x00\x00\x00\x008\xdc\xe9\x88\x00\x00\x00\x009\xfa\xff\b\x00" + - "\x00\x00\x00:\xbcˈ\x00\x00\x00\x00;\xda\xe1\b\x00\x00\x00\x00<\xa5\xe8\b\x00\x00\x00\x00=\xba\xc3\b\x00\x00\x00\x00>\x85\xca\b\x00\x00\x00\x00?\x9a\xa5\b\x00\x00\x00\x00@e\xac\b\x00\x00\x00\x00A" + - "\x83\xc1\x88\x00\x00\x00\x00BE\x8e\b\x00\x00\x00\x00Cc\xa3\x88\x00\x00\x00\x00D.\xaa\x88\x00\x00\x00\x00EC\x85\x88\x00\x00\x00\x00F\x05R\b\x00\x00\x00\x00G#g\x88\x00\x00\x00\x00G\xf7\xa9\b\x01" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x00\x00\x81\xec\x00\x00\x00\x00~\x90\x00\x04\x00\x00\x93\xa8\x01\t\x00\x00\x85\x98\x00\x04LMT\x00ACST\x00ACDT" + - "\x00\nACST-9:30ACDT,M10.1.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x9b\xe1\xc1\xa9\x88\x03\x00\x00\x88\x03\x00\x00\x12" + - "\x00\x1c\x00Australia/VictoriaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00S\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xffs\x16\x85\x18\xff\xff\xff\xff\x9cN\u0080\xff\xff\xff\xff\x9c\xbc/\x00\xff\xff\xff\xff\xcbT\xb3\x00\xff\xff\xff\xff" + - "\xcb\xc7e\x80\xff\xff\xff\xff̷V\x80\xff\xff\xff\xffͧG\x80\xff\xff\xff\xffΠs\x00\xff\xff\xff\xffχ)\x80\x00\x00\x00\x00\x03p9\x80\x00\x00\x00\x00\x04\r\x1c\x00\x00\x00\x00\x00\x05P\x1b\x80" + - "\x00\x00\x00\x00\x05\xf68\x80\x00\x00\x00\x00\a/\xfd\x80\x00\x00\x00\x00\a\xd6\x1a\x80\x00\x00\x00\x00\t\x0f߀\x00\x00\x00\x00\t\xb5\xfc\x80\x00\x00\x00\x00\n\xef\xc1\x80\x00\x00\x00\x00\v\x9f\x19\x00\x00\x00\x00\x00" + - "\f\xd8\xde\x00\x00\x00\x00\x00\r~\xfb\x00\x00\x00\x00\x00\x0e\xb8\xc0\x00\x00\x00\x00\x00\x0f^\xdd\x00\x00\x00\x00\x00\x10\x98\xa2\x00\x00\x00\x00\x00\x11>\xbf\x00\x00\x00\x00\x00\x12x\x84\x00\x00\x00\x00\x00\x13\x1e\xa1\x00" + - "\x00\x00\x00\x00\x14Xf\x00\x00\x00\x00\x00\x14\xfe\x83\x00\x00\x00\x00\x00\x168H\x00\x00\x00\x00\x00\x16矀\x00\x00\x00\x00\x18!d\x80\x00\x00\x00\x00\x18ǁ\x80\x00\x00\x00\x00\x1a\x01F\x80\x00\x00\x00\x00" + - "\x1a\xa7c\x80\x00\x00\x00\x00\x1b\xe1(\x80\x00\x00\x00\x00\x1c\x87E\x80\x00\x00\x00\x00\x1d\xc1\n\x80\x00\x00\x00\x00\x1ey\x9c\x80\x00\x00\x00\x00\x1f\x97\xb2\x00\x00\x00\x00\x00 Y~\x80\x00\x00\x00\x00!w\x94\x00" + - "\x00\x00\x00\x00\"B\x9b\x00\x00\x00\x00\x00#i\xeb\x00\x00\x00\x00\x00$\"}\x00\x00\x00\x00\x00%I\xcd\x00\x00\x00\x00\x00&\x02_\x00\x00\x00\x00\x00')\xaf\x00\x00\x00\x00\x00'\xcf\xcc\x00\x00\x00\x00\x00" + - ")\t\x91\x00\x00\x00\x00\x00)\xaf\xae\x00\x00\x00\x00\x00*\xe9s\x00\x00\x00\x00\x00+\x98ʀ\x00\x00\x00\x00,ҏ\x80\x00\x00\x00\x00-x\xac\x80\x00\x00\x00\x00.\xb2q\x80\x00\x00\x00\x00/t>\x00" + - "\x00\x00\x00\x000\x92S\x80\x00\x00\x00\x001]Z\x80\x00\x00\x00\x002r5\x80\x00\x00\x00\x003=<\x80\x00\x00\x00\x004R\x17\x80\x00\x00\x00\x005\x1d\x1e\x80\x00\x00\x00\x0061\xf9\x80\x00\x00\x00\x00" + - "6\xfd\x00\x80\x00\x00\x00\x008\x1b\x16\x00\x00\x00\x00\x008\xdc\xe2\x80\x00\x00\x00\x009\xa7\xe9\x80\x00\x00\x00\x00:\xbcĀ\x00\x00\x00\x00;\xda\xda\x00\x00\x00\x00\x00<\xa5\xe1\x00\x00\x00\x00\x00=\xba\xbc\x00" + - "\x00\x00\x00\x00>\x85\xc3\x00\x00\x00\x00\x00?\x9a\x9e\x00\x00\x00\x00\x00@e\xa5\x00\x00\x00\x00\x00A\x83\xba\x80\x00\x00\x00\x00BE\x87\x00\x00\x00\x00\x00Cc\x9c\x80\x00\x00\x00\x00D.\xa3\x80\x00\x00\x00\x00" + - "EC~\x80\x00\x00\x00\x00F\x05K\x00\x00\x00\x00\x00G#`\x80\x00\x00\x00\x00G\xf7\xa2\x00\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\x87\xe8\x00\x00\x00\x00\x9a" + - "\xb0\x01\x04\x00\x00\x8c\xa0\x00\tLMT\x00AEDT\x00AEST\x00\nAEST-10AEDT,M10.1.0,M4.1.0/3\nPK\x03\x04\n\x00\x00" + - "\x00\x00\x00\xf1c9Ro3\xdaR\xb4\x02\x00\x00\xb4\x02\x00\x00\r\x00\x1c\x00Australia/LHIUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04" + - "\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x05\x00\x00\x00\x19\xff\xff\xff\xffs\x16w\xdc\x00\x00\x00\x00\x14\xfef\xe0\x00\x00\x00\x00\x16" + - "8@\xf8\x00\x00\x00\x00\x16\xe7\x8ah\x00\x00\x00\x00\x18!]x\x00\x00\x00\x00\x18\xc7lh\x00\x00\x00\x00\x1a\x01?x\x00\x00\x00\x00\x1a\xa7Nh\x00\x00\x00\x00\x1b\xe1!x\x00\x00\x00\x00\x1c\x870h\x00" + - "\x00\x00\x00\x1d\xc1\x03x\x00\x00\x00\x00\x1ey\x8ep\x00\x00\x00\x00\x1f\x97\xaa\xf8\x00\x00\x00\x00 Ypp\x00\x00\x00\x00!\x80\xc7x\x00\x00\x00\x00\"B\x8c\xf0\x00\x00\x00\x00#i\xe3\xf8\x00\x00\x00\x00$" + - "\"n\xf0\x00\x00\x00\x00%I\xc5\xf8\x00\x00\x00\x00%\xef\xdb\xf0\x00\x00\x00\x00')\xa7\xf8\x00\x00\x00\x00'Ͻ\xf0\x00\x00\x00\x00)\t\x89\xf8\x00\x00\x00\x00)\xaf\x9f\xf0\x00\x00\x00\x00*\xe9k\xf8\x00" + - "\x00\x00\x00+\x98\xbcp\x00\x00\x00\x00,҈x\x00\x00\x00\x00-x\x9ep\x00\x00\x00\x00.\xb2jx\x00\x00\x00\x00/X\x80p\x00\x00\x00\x000\x92Lx\x00\x00\x00\x001]Lp\x00\x00\x00\x002" + - "r.x\x00\x00\x00\x003=.p\x00\x00\x00\x004R\x10x\x00\x00\x00\x005\x1d\x10p\x00\x00\x00\x0061\xf2x\x00\x00\x00\x006\xfc\xf2p\x00\x00\x00\x008\x1b\x0e\xf8\x00\x00\x00\x008\xdc\xd4p\x00" + - "\x00\x00\x009\xa7\xe2x\x00\x00\x00\x00:\xbc\xb6p\x00\x00\x00\x00;\xda\xd2\xf8\x00\x00\x00\x00<\xa5\xd2\xf0\x00\x00\x00\x00=\xba\xb4\xf8\x00\x00\x00\x00>\x85\xb4\xf0\x00\x00\x00\x00?\x9a\x96\xf8\x00\x00\x00\x00@" + - "e\x96\xf0\x00\x00\x00\x00A\x83\xb3x\x00\x00\x00\x00BEx\xf0\x00\x00\x00\x00Cc\x95x\x00\x00\x00\x00D.\x95p\x00\x00\x00\x00ECwx\x00\x00\x00\x00F\x05<\xf0\x00\x00\x00\x00G#Yx\x00" + - "\x00\x00\x00G\xf7\x93\xf0\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04" + - "\x03\x04\x03\x00\x00\x95$\x00\x00\x00\x00\x8c\xa0\x00\x04\x00\x00\xa1\xb8\x01\t\x00\x00\x93\xa8\x00\x0f\x00\x00\x9a\xb0\x01\x15LMT\x00AEST\x00+1130\x00+1030\x00+11\x00\n<" + - "+1030>-10:30<+11>-11,M10.1.0,M4.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xc8R\x1a\x1b\xea\x00\x00\x00\xea\x00" + - "\x00\x00\x0f\x00\x1c\x00Australia/NorthUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x04\x00\x00\x00\x0e\xff\xff\xff\xffs\x16\x92X\xff\xff\xff\xff{\x12\x03p\xff\xff\xff\xff\x9cNɈ\xff\xff\xff\xff\x9c\xbc6\b\xff\xff\xff\xff" + - "\xcbT\xba\b\xff\xff\xff\xff\xcb\xc7l\x88\xff\xff\xff\xff̷]\x88\xff\xff\xff\xffͧN\x88\xff\xff\xff\xffΠz\b\xff\xff\xff\xffχ0\x88\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x00\x00z\xa8\x00\x00" + - "\x00\x00~\x90\x00\x04\x00\x00\x93\xa8\x01\t\x00\x00\x85\x98\x00\x04LMT\x00ACST\x00ACDT\x00\nACST-9:30\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xc8R\x1a" + - "\x1b\xea\x00\x00\x00\xea\x00\x00\x00\x10\x00\x1c\x00Australia/DarwinUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZi" + - "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x04\x00\x00\x00\x0e\xff\xff\xff\xffs\x16\x92X\xff\xff\xff\xff{\x12\x03p\xff\xff\xff\xff\x9cNɈ\xff\xff\xff\xff" + - "\x9c\xbc6\b\xff\xff\xff\xff\xcbT\xba\b\xff\xff\xff\xff\xcb\xc7l\x88\xff\xff\xff\xff̷]\x88\xff\xff\xff\xffͧN\x88\xff\xff\xff\xffΠz\b\xff\xff\xff\xffχ0\x88\x01\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x00\x00z\xa8\x00\x00\x00\x00~\x90\x00\x04\x00\x00\x93\xa8\x01\t\x00\x00\x85\x98\x00\x04LMT\x00ACST\x00ACDT\x00\nACST-9:30\nPK\x03\x04\n\x00\x00\x00\x00" + - "\x00\xf1c9R\xbd\xca#\u007f\xad\x03\x00\x00\xad\x03\x00\x00\x14\x00\x1c\x00Australia/YancowinnaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04" + - "\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" + - "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00U\x00\x00\x00\x05\x00\x00\x00\x13\xff\xff\xff\xffs\x16\x88d\xff\xff\xff\xffv\x04\xa5\xe0" + - "\xff\xff\xff\xff{\x12\x03p\xff\xff\xff\xff\x9cNɈ\xff\xff\xff\xff\x9c\xbc6\b\xff\xff\xff\xff\xcbT\xba\b\xff\xff\xff\xff\xcb\xc7l\x88\xff\xff\xff\xff̷]\x88\xff\xff\xff\xffͧN\x88\xff\xff\xff\xff" + - "Πz\b\xff\xff\xff\xffχ0\x88\x00\x00\x00\x00\x03p@\x88\x00\x00\x00\x00\x04\r#\b\x00\x00\x00\x00\x05P\"\x88\x00\x00\x00\x00\x05\xf6?\x88\x00\x00\x00\x00\a0\x04\x88\x00\x00\x00\x00\a\xd6!\x88" + - "\x00\x00\x00\x00\t\x0f\xe6\x88\x00\x00\x00\x00\t\xb6\x03\x88\x00\x00\x00\x00\n\xefȈ\x00\x00\x00\x00\v\x9f \b\x00\x00\x00\x00\f\xd8\xe5\b\x00\x00\x00\x00\r\u007f\x02\b\x00\x00\x00\x00\x0e\xb8\xc7\b\x00\x00\x00\x00" + - "\x0f^\xe4\b\x00\x00\x00\x00\x10\x98\xa9\b\x00\x00\x00\x00\x11>\xc6\b\x00\x00\x00\x00\x12x\x8b\b\x00\x00\x00\x00\x13\x1e\xa8\b\x00\x00\x00\x00\x14Xm\b\x00\x00\x00\x00\x14\xfe\x8a\b\x00\x00\x00\x00\x168O\b" + - "\x00\x00\x00\x00\x17\f\x90\x88\x00\x00\x00\x00\x18!k\x88\x00\x00\x00\x00\x18Lj\x88\x00\x00\x00\x00\x1a\x01M\x88\x00\x00\x00\x00\x1a\xa7j\x88\x00\x00\x00\x00\x1b\xe1/\x88\x00\x00\x00\x00\x1c\x87L\x88\x00\x00\x00\x00" + - "\x1d\xc1\x11\x88\x00\x00\x00\x00\x1ey\xa3\x88\x00\x00\x00\x00\x1f\x97\xb9\b\x00\x00\x00\x00 Y\x85\x88\x00\x00\x00\x00!\x80Ո\x00\x00\x00\x00\"B\xa2\b\x00\x00\x00\x00#i\xf2\b\x00\x00\x00\x00$\"\x84\b" + - "\x00\x00\x00\x00%I\xd4\b\x00\x00\x00\x00%\xef\xf1\b\x00\x00\x00\x00')\xb6\b\x00\x00\x00\x00'\xcf\xd3\b\x00\x00\x00\x00)\t\x98\b\x00\x00\x00\x00)\xaf\xb5\b\x00\x00\x00\x00*\xe9z\b\x00\x00\x00\x00" + - "+\x98ш\x00\x00\x00\x00,Җ\x88\x00\x00\x00\x00-x\xb3\x88\x00\x00\x00\x00.\xb2x\x88\x00\x00\x00\x00/X\x95\x88\x00\x00\x00\x000\x92Z\x88\x00\x00\x00\x001]a\x88\x00\x00\x00\x002r<\x88" + - "\x00\x00\x00\x003=C\x88\x00\x00\x00\x004R\x1e\x88\x00\x00\x00\x005\x1d%\x88\x00\x00\x00\x0062\x00\x88\x00\x00\x00\x006\xfd\a\x88\x00\x00\x00\x008\x1b\x1d\b\x00\x00\x00\x008\xdc\xe9\x88\x00\x00\x00\x00" + - "9\xfa\xff\b\x00\x00\x00\x00:\xbcˈ\x00\x00\x00\x00;\xda\xe1\b\x00\x00\x00\x00<\xa5\xe8\b\x00\x00\x00\x00=\xba\xc3\b\x00\x00\x00\x00>\x85\xca\b\x00\x00\x00\x00?\x9a\xa5\b\x00\x00\x00\x00@e\xac\b" + - "\x00\x00\x00\x00A\x83\xc1\x88\x00\x00\x00\x00BE\x8e\b\x00\x00\x00\x00Cc\xa3\x88\x00\x00\x00\x00D.\xaa\x88\x00\x00\x00\x00EC\x85\x88\x00\x00\x00\x00F\x05R\b\x00\x00\x00\x00G#g\x88\x00\x00\x00\x00" + - "G\xf7\xa9\b\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03" + - "\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x00\x00\x84\x9c\x00\x00\x00\x00\x8c\xa0\x00\x04\x00\x00~\x90\x00\t\x00\x00\x93\xa8\x01\x0e\x00\x00\x85\x98\x00\tL" + - "MT\x00AEST\x00ACST\x00ACDT\x00\nACST-9:30ACDT,M10.1.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00" + - "\xf1c9R3\xba\xde\xd3!\x01\x00\x00!\x01\x00\x00\x14\x00\x1c\x00Australia/QueenslandUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8" + - "\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00T" + - "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xffr\xed\x9f\b\xff\xff\xff\xff\x9cN\u0080\xff" + - "\xff\xff\xff\x9c\xbc/\x00\xff\xff\xff\xff\xcbT\xb3\x00\xff\xff\xff\xff\xcb\xc7e\x80\xff\xff\xff\xff̷V\x80\xff\xff\xff\xffͧG\x80\xff\xff\xff\xffΠs\x00\xff\xff\xff\xffχ)\x80\x00\x00\x00\x00\x03" + - "p9\x80\x00\x00\x00\x00\x04\r\x1c\x00\x00\x00\x00\x00%I\xcd\x00\x00\x00\x00\x00%\xef\xea\x00\x00\x00\x00\x00')\xaf\x00\x00\x00\x00\x00'\xcf\xcc\x00\x00\x00\x00\x00)\t\x91\x00\x00\x00\x00\x00)\xaf\xae\x00\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\x8fx\x00\x00\x00\x00\x9a\xb0\x01\x04\x00\x00\x8c\xa0\x00\tLMT\x00AEDT\x00AEST\x00\nAEST-10\nPK\x03" + - "\x04\n\x00\x00\x00\x00\x00\xf1c9RX\xb9\x9ap\x88\x03\x00\x00\x88\x03\x00\x00\x10\x00\x1c\x00Australia/SydneyUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00" + - "\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00" + - "\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00S\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xffs\x16\u007f<\xff\xff\xff\xff\x9cN" + - "\u0080\xff\xff\xff\xff\x9c\xbc/\x00\xff\xff\xff\xff\xcbT\xb3\x00\xff\xff\xff\xff\xcb\xc7e\x80\xff\xff\xff\xff̷V\x80\xff\xff\xff\xffͧG\x80\xff\xff\xff\xffΠs\x00\xff\xff\xff\xffχ)\x80\x00\x00" + - "\x00\x00\x03p9\x80\x00\x00\x00\x00\x04\r\x1c\x00\x00\x00\x00\x00\x05P\x1b\x80\x00\x00\x00\x00\x05\xf68\x80\x00\x00\x00\x00\a/\xfd\x80\x00\x00\x00\x00\a\xd6\x1a\x80\x00\x00\x00\x00\t\x0f߀\x00\x00\x00\x00\t\xb5" + - "\xfc\x80\x00\x00\x00\x00\n\xef\xc1\x80\x00\x00\x00\x00\v\x9f\x19\x00\x00\x00\x00\x00\f\xd8\xde\x00\x00\x00\x00\x00\r~\xfb\x00\x00\x00\x00\x00\x0e\xb8\xc0\x00\x00\x00\x00\x00\x0f^\xdd\x00\x00\x00\x00\x00\x10\x98\xa2\x00\x00\x00" + - "\x00\x00\x11>\xbf\x00\x00\x00\x00\x00\x12x\x84\x00\x00\x00\x00\x00\x13\x1e\xa1\x00\x00\x00\x00\x00\x14Xf\x00\x00\x00\x00\x00\x14\xfe\x83\x00\x00\x00\x00\x00\x168H\x00\x00\x00\x00\x00\x17\f\x89\x80\x00\x00\x00\x00\x18!" + - "d\x80\x00\x00\x00\x00\x18ǁ\x80\x00\x00\x00\x00\x1a\x01F\x80\x00\x00\x00\x00\x1a\xa7c\x80\x00\x00\x00\x00\x1b\xe1(\x80\x00\x00\x00\x00\x1c\x87E\x80\x00\x00\x00\x00\x1d\xc1\n\x80\x00\x00\x00\x00\x1ey\x9c\x80\x00\x00" + - "\x00\x00\x1f\x97\xb2\x00\x00\x00\x00\x00 Y~\x80\x00\x00\x00\x00!\x80\u0380\x00\x00\x00\x00\"B\x9b\x00\x00\x00\x00\x00#i\xeb\x00\x00\x00\x00\x00$\"}\x00\x00\x00\x00\x00%I\xcd\x00\x00\x00\x00\x00%\xef" + - "\xea\x00\x00\x00\x00\x00')\xaf\x00\x00\x00\x00\x00'\xcf\xcc\x00\x00\x00\x00\x00)\t\x91\x00\x00\x00\x00\x00)\xaf\xae\x00\x00\x00\x00\x00*\xe9s\x00\x00\x00\x00\x00+\x98ʀ\x00\x00\x00\x00,ҏ\x80\x00\x00" + - "\x00\x00-x\xac\x80\x00\x00\x00\x00.\xb2q\x80\x00\x00\x00\x00/X\x8e\x80\x00\x00\x00\x000\x92S\x80\x00\x00\x00\x001]Z\x80\x00\x00\x00\x002r5\x80\x00\x00\x00\x003=<\x80\x00\x00\x00\x004R" + - "\x17\x80\x00\x00\x00\x005\x1d\x1e\x80\x00\x00\x00\x0061\xf9\x80\x00\x00\x00\x006\xfd\x00\x80\x00\x00\x00\x008\x1b\x16\x00\x00\x00\x00\x008\xdc\xe2\x80\x00\x00\x00\x009\xa7\xe9\x80\x00\x00\x00\x00:\xbcĀ\x00\x00" + - "\x00\x00;\xda\xda\x00\x00\x00\x00\x00<\xa5\xe1\x00\x00\x00\x00\x00=\xba\xbc\x00\x00\x00\x00\x00>\x85\xc3\x00\x00\x00\x00\x00?\x9a\x9e\x00\x00\x00\x00\x00@e\xa5\x00\x00\x00\x00\x00A\x83\xba\x80\x00\x00\x00\x00BE" + - "\x87\x00\x00\x00\x00\x00Cc\x9c\x80\x00\x00\x00\x00D.\xa3\x80\x00\x00\x00\x00EC~\x80\x00\x00\x00\x00F\x05K\x00\x00\x00\x00\x00G#`\x80\x00\x00\x00\x00G\xf7\xa2\x00\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x00\x00\x00+\xb4\xf8\x90\x00\x00\x00\x00,\xa4\xe9\x90\x00\x00\x00\x00-\x94ڐ\x00\x00\x00\x00.\x84ː\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000d\xad\x90\x00\x00\x00\x001]\xd9\x10\x01\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\xff\xff\xf1\x90\x00\x00\xff\xff\xf1\xf0\x00\x04\x00\x00\x00\x00\x00\b\x00\x00\x0e\x10\x01\fLMT\x00-0" + + "1\x00WET\x00WEST\x00\nWET0WEST,M3.5.0/1,M10.5.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x0f-\xadׄ\x00\x00\x00" + + "\x84\x00\x00\x00\x16\x00\x1c\x00Atlantic/South_GeorgiaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZ" + + "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xffi\x86\xfd\xc0\x01\xff\xff\xdd\xc0\x00\x00\xff\xff\xe3\xe0\x00\x04LMT\x00-0" + + "2\x00\n<-02>2\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x1c\x00Australia/UT\t\x00\x03\x82\x0f\x8ba\x82" + + "\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS?\x95\xbd\x12E\x01\x00\x00E\x01\x00\x00\x12\x00\x1c\x00Australia/Li" + + "ndemanUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x15\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xffr\xed\xa2\xd4\xff\xff\xff\xff\x9cN\u0080\xff\xff\xff\xff\x9c\xbc/\x00\xff\xff\xff\xff\xcbT\xb3\x00\xff\xff\xff\xff\xcb\xc7e\x80\xff\xff\xff\xff̷V\x80\xff\xff\xff" + + "\xffͧG\x80\xff\xff\xff\xffΠs\x00\xff\xff\xff\xffχ)\x80\x00\x00\x00\x00\x03p9\x80\x00\x00\x00\x00\x04\r\x1c\x00\x00\x00\x00\x00%I\xcd\x00\x00\x00\x00\x00%\xef\xea\x00\x00\x00\x00\x00')\xaf" + + "\x00\x00\x00\x00\x00'\xcf\xcc\x00\x00\x00\x00\x00)\t\x91\x00\x00\x00\x00\x00)\xaf\xae\x00\x00\x00\x00\x00*\xe9s\x00\x00\x00\x00\x00+\x98ʀ\x00\x00\x00\x00,ҏ\x80\x00\x00\x00\x00-x\xac\x80\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\x8b\xac\x00\x00\x00\x00\x9a\xb0\x01\x04\x00\x00\x8c\xa0\x00\tLMT\x00AEDT\x00AEST\x00\nAEST-10\nP" + + "K\x03\x04\n\x00\x00\x00\x00\x00#\x82iS3\xba\xde\xd3!\x01\x00\x00!\x01\x00\x00\x14\x00\x1c\x00Australia/QueenslandUT\t\x00\x03\x82\x0f\x8ba\x82\x0f" + + "\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" + + "\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xffr\xed\x9f\b" + + "\xff\xff\xff\xff\x9cN\u0080\xff\xff\xff\xff\x9c\xbc/\x00\xff\xff\xff\xff\xcbT\xb3\x00\xff\xff\xff\xff\xcb\xc7e\x80\xff\xff\xff\xff̷V\x80\xff\xff\xff\xffͧG\x80\xff\xff\xff\xffΠs\x00\xff\xff\xff\xff" + + "χ)\x80\x00\x00\x00\x00\x03p9\x80\x00\x00\x00\x00\x04\r\x1c\x00\x00\x00\x00\x00%I\xcd\x00\x00\x00\x00\x00%\xef\xea\x00\x00\x00\x00\x00')\xaf\x00\x00\x00\x00\x00'\xcf\xcc\x00\x00\x00\x00\x00)\t\x91\x00" + + "\x00\x00\x00\x00)\xaf\xae\x00\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\x8fx\x00\x00\x00\x00\x9a\xb0\x01\x04\x00\x00\x8c\xa0\x00\tLMT\x00AEDT\x00AEST\x00\nAE" + + "ST-10\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSϻ\xca\x1a2\x01\x00\x002\x01\x00\x00\x0e\x00\x1c\x00Australia/WestUT\t\x00\x03\x82\x0f\x8ba\x82" + + "\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00" + + "\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xfft\xa6\x16" + + "\xe4\xff\xff\xff\xff\x9cNޠ\xff\xff\xff\xff\x9c\xbcK \xff\xff\xff\xff\xcbT\xcf \xff\xff\xff\xff\xcbǁ\xa0\xff\xff\xff\xff̷r\xa0\xff\xff\xff\xffͧc\xa0\x00\x00\x00\x00\t\x0f\xfb\xa0\x00\x00\x00" + + "\x00\t\xb6\x18\xa0\x00\x00\x00\x00\x1a\x01b\xa0\x00\x00\x00\x00\x1a\xa7\u007f\xa0\x00\x00\x00\x00)%\\\xa0\x00\x00\x00\x00)\xaf\xca \x00\x00\x00\x00Eq\xbf \x00\x00\x00\x00F\x05g \x00\x00\x00\x00G#|" + + "\xa0\x00\x00\x00\x00G\ue0e0\x00\x00\x00\x00I\x03^\xa0\x00\x00\x00\x00I\xcee\xa0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00l\x9c\x00\x00\x00\x00~\x90\x01\x04\x00\x00p\x80" + + "\x00\tLMT\x00AWDT\x00AWST\x00\nAWST-8\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xa2ܺ\xca:\x01\x00\x00:\x01\x00\x00\x0f\x00\x1c\x00Austra" + + "lia/EuclaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x13\x00\x00\x00\x03\x00\x00\x00\x10\xff\xff\xff\xfft\xa6\n\xb0\xff\xff\xff\xff\x9cN\xd4\x14\xff\xff\xff\xff\x9c\xbc@\x94\xff\xff\xff\xff\xcbTĔ\xff\xff\xff\xff\xcb\xc7w\x14\xff\xff\xff\xff̷h\x14" + + "\xff\xff\xff\xffͧY\x14\x00\x00\x00\x00\t\x0f\xf1\x14\x00\x00\x00\x00\t\xb6\x0e\x14\x00\x00\x00\x00\x1a\x01X\x14\x00\x00\x00\x00\x1a\xa7u\x14\x00\x00\x00\x00)%R\x14\x00\x00\x00\x00)\xaf\xbf\x94\x00\x00\x00\x00" + + "Eq\xb4\x94\x00\x00\x00\x00F\x05\\\x94\x00\x00\x00\x00G#r\x14\x00\x00\x00\x00G\xeey\x14\x00\x00\x00\x00I\x03T\x14\x00\x00\x00\x00I\xce[\x14\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x00\x00x\xd0\x00\x00\x00\x00\x89\x1c\x01\x04\x00\x00{\f\x00\nLMT\x00+0945\x00+0845\x00\n<+0845>-8:45\nPK\x03\x04\n\x00\x00\x00\x00" + + "\x00#\x82iS\x9b\xe1\xc1\xa9\x88\x03\x00\x00\x88\x03\x00\x00\x12\x00\x1c\x00Australia/VictoriaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E" + + "\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + + "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00S\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xffs\x16\x85\x18\xff\xff\xff\xff\x9cN\u0080\xff\xff" + + "\xff\xff\x9c\xbc/\x00\xff\xff\xff\xff\xcbT\xb3\x00\xff\xff\xff\xff\xcb\xc7e\x80\xff\xff\xff\xff̷V\x80\xff\xff\xff\xffͧG\x80\xff\xff\xff\xffΠs\x00\xff\xff\xff\xffχ)\x80\x00\x00\x00\x00\x03p" + + "9\x80\x00\x00\x00\x00\x04\r\x1c\x00\x00\x00\x00\x00\x05P\x1b\x80\x00\x00\x00\x00\x05\xf68\x80\x00\x00\x00\x00\a/\xfd\x80\x00\x00\x00\x00\a\xd6\x1a\x80\x00\x00\x00\x00\t\x0f߀\x00\x00\x00\x00\t\xb5\xfc\x80\x00\x00" + + "\x00\x00\n\xef\xc1\x80\x00\x00\x00\x00\v\x9f\x19\x00\x00\x00\x00\x00\f\xd8\xde\x00\x00\x00\x00\x00\r~\xfb\x00\x00\x00\x00\x00\x0e\xb8\xc0\x00\x00\x00\x00\x00\x0f^\xdd\x00\x00\x00\x00\x00\x10\x98\xa2\x00\x00\x00\x00\x00\x11>" + + "\xbf\x00\x00\x00\x00\x00\x12x\x84\x00\x00\x00\x00\x00\x13\x1e\xa1\x00\x00\x00\x00\x00\x14Xf\x00\x00\x00\x00\x00\x14\xfe\x83\x00\x00\x00\x00\x00\x168H\x00\x00\x00\x00\x00\x16矀\x00\x00\x00\x00\x18!d\x80\x00\x00" + + "\x00\x00\x18ǁ\x80\x00\x00\x00\x00\x1a\x01F\x80\x00\x00\x00\x00\x1a\xa7c\x80\x00\x00\x00\x00\x1b\xe1(\x80\x00\x00\x00\x00\x1c\x87E\x80\x00\x00\x00\x00\x1d\xc1\n\x80\x00\x00\x00\x00\x1ey\x9c\x80\x00\x00\x00\x00\x1f\x97" + + "\xb2\x00\x00\x00\x00\x00 Y~\x80\x00\x00\x00\x00!w\x94\x00\x00\x00\x00\x00\"B\x9b\x00\x00\x00\x00\x00#i\xeb\x00\x00\x00\x00\x00$\"}\x00\x00\x00\x00\x00%I\xcd\x00\x00\x00\x00\x00&\x02_\x00\x00\x00" + + "\x00\x00')\xaf\x00\x00\x00\x00\x00'\xcf\xcc\x00\x00\x00\x00\x00)\t\x91\x00\x00\x00\x00\x00)\xaf\xae\x00\x00\x00\x00\x00*\xe9s\x00\x00\x00\x00\x00+\x98ʀ\x00\x00\x00\x00,ҏ\x80\x00\x00\x00\x00-x" + + "\xac\x80\x00\x00\x00\x00.\xb2q\x80\x00\x00\x00\x00/t>\x00\x00\x00\x00\x000\x92S\x80\x00\x00\x00\x001]Z\x80\x00\x00\x00\x002r5\x80\x00\x00\x00\x003=<\x80\x00\x00\x00\x004R\x17\x80\x00\x00" + + "\x00\x005\x1d\x1e\x80\x00\x00\x00\x0061\xf9\x80\x00\x00\x00\x006\xfd\x00\x80\x00\x00\x00\x008\x1b\x16\x00\x00\x00\x00\x008\xdc\xe2\x80\x00\x00\x00\x009\xa7\xe9\x80\x00\x00\x00\x00:\xbcĀ\x00\x00\x00\x00;\xda" + + "\xda\x00\x00\x00\x00\x00<\xa5\xe1\x00\x00\x00\x00\x00=\xba\xbc\x00\x00\x00\x00\x00>\x85\xc3\x00\x00\x00\x00\x00?\x9a\x9e\x00\x00\x00\x00\x00@e\xa5\x00\x00\x00\x00\x00A\x83\xba\x80\x00\x00\x00\x00BE\x87\x00\x00\x00" + + "\x00\x00Cc\x9c\x80\x00\x00\x00\x00D.\xa3\x80\x00\x00\x00\x00EC~\x80\x00\x00\x00\x00F\x05K\x00\x00\x00\x00\x00G#`\x80\x00\x00\x00\x00G\xf7\xa2\x00\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\x87\xe8\x00\x00\x00\x00\x9a\xb0\x01\x04\x00\x00\x8c\xa0\x00\tLMT\x00AEDT\x00AEST\x00\nAEST-10AEDT,M10.1." + + "0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSX\xb9\x9ap\x88\x03\x00\x00\x88\x03\x00\x00\x10\x00\x1c\x00Australia/SydneyUT\t" + + "\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00S\x00\x00\x00\x03\x00\x00\x00\x0e" + + "\xff\xff\xff\xffs\x16\u007f<\xff\xff\xff\xff\x9cN\u0080\xff\xff\xff\xff\x9c\xbc/\x00\xff\xff\xff\xff\xcbT\xb3\x00\xff\xff\xff\xff\xcb\xc7e\x80\xff\xff\xff\xff̷V\x80\xff\xff\xff\xffͧG\x80\xff\xff\xff\xff" + + "Πs\x00\xff\xff\xff\xffχ)\x80\x00\x00\x00\x00\x03p9\x80\x00\x00\x00\x00\x04\r\x1c\x00\x00\x00\x00\x00\x05P\x1b\x80\x00\x00\x00\x00\x05\xf68\x80\x00\x00\x00\x00\a/\xfd\x80\x00\x00\x00\x00\a\xd6\x1a\x80" + + "\x00\x00\x00\x00\t\x0f߀\x00\x00\x00\x00\t\xb5\xfc\x80\x00\x00\x00\x00\n\xef\xc1\x80\x00\x00\x00\x00\v\x9f\x19\x00\x00\x00\x00\x00\f\xd8\xde\x00\x00\x00\x00\x00\r~\xfb\x00\x00\x00\x00\x00\x0e\xb8\xc0\x00\x00\x00\x00\x00" + + "\x0f^\xdd\x00\x00\x00\x00\x00\x10\x98\xa2\x00\x00\x00\x00\x00\x11>\xbf\x00\x00\x00\x00\x00\x12x\x84\x00\x00\x00\x00\x00\x13\x1e\xa1\x00\x00\x00\x00\x00\x14Xf\x00\x00\x00\x00\x00\x14\xfe\x83\x00\x00\x00\x00\x00\x168H\x00" + + "\x00\x00\x00\x00\x17\f\x89\x80\x00\x00\x00\x00\x18!d\x80\x00\x00\x00\x00\x18ǁ\x80\x00\x00\x00\x00\x1a\x01F\x80\x00\x00\x00\x00\x1a\xa7c\x80\x00\x00\x00\x00\x1b\xe1(\x80\x00\x00\x00\x00\x1c\x87E\x80\x00\x00\x00\x00" + + "\x1d\xc1\n\x80\x00\x00\x00\x00\x1ey\x9c\x80\x00\x00\x00\x00\x1f\x97\xb2\x00\x00\x00\x00\x00 Y~\x80\x00\x00\x00\x00!\x80\u0380\x00\x00\x00\x00\"B\x9b\x00\x00\x00\x00\x00#i\xeb\x00\x00\x00\x00\x00$\"}\x00" + + "\x00\x00\x00\x00%I\xcd\x00\x00\x00\x00\x00%\xef\xea\x00\x00\x00\x00\x00')\xaf\x00\x00\x00\x00\x00'\xcf\xcc\x00\x00\x00\x00\x00)\t\x91\x00\x00\x00\x00\x00)\xaf\xae\x00\x00\x00\x00\x00*\xe9s\x00\x00\x00\x00\x00" + + "+\x98ʀ\x00\x00\x00\x00,ҏ\x80\x00\x00\x00\x00-x\xac\x80\x00\x00\x00\x00.\xb2q\x80\x00\x00\x00\x00/X\x8e\x80\x00\x00\x00\x000\x92S\x80\x00\x00\x00\x001]Z\x80\x00\x00\x00\x002r5\x80" + + "\x00\x00\x00\x003=<\x80\x00\x00\x00\x004R\x17\x80\x00\x00\x00\x005\x1d\x1e\x80\x00\x00\x00\x0061\xf9\x80\x00\x00\x00\x006\xfd\x00\x80\x00\x00\x00\x008\x1b\x16\x00\x00\x00\x00\x008\xdc\xe2\x80\x00\x00\x00\x00" + + "9\xa7\xe9\x80\x00\x00\x00\x00:\xbcĀ\x00\x00\x00\x00;\xda\xda\x00\x00\x00\x00\x00<\xa5\xe1\x00\x00\x00\x00\x00=\xba\xbc\x00\x00\x00\x00\x00>\x85\xc3\x00\x00\x00\x00\x00?\x9a\x9e\x00\x00\x00\x00\x00@e\xa5\x00" + + "\x00\x00\x00\x00A\x83\xba\x80\x00\x00\x00\x00BE\x87\x00\x00\x00\x00\x00Cc\x9c\x80\x00\x00\x00\x00D.\xa3\x80\x00\x00\x00\x00EC~\x80\x00\x00\x00\x00F\x05K\x00\x00\x00\x00\x00G#`\x80\x00\x00\x00\x00" + + "G\xf7\xa2\x00\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\x8d\xc4\x00\x00\x00\x00\x9a\xb0\x01\x04\x00\x00\x8c\xa0\x00\tLMT\x00AEDT\x00AEST\x00\n" + + "AEST-10AEDT,M10.1.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSE\xf2\xe6Z\xeb\x03\x00\x00\xeb\x03\x00\x00\x10\x00\x1c\x00A" + + "ustralia/HobartUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00^\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xfft.\x00\xe4\xff\xff\xff\xff\x9b\xd5x\x80\xff\xff\xff\xff\x9c\xbc/\x00\xff\xff\xff\xff\x9d\xdaD\x80\xff\xff\xff\xff\x9e\x80a\x80\xff\xff" + + "\xff\xff\x9f\xba&\x80\xff\xff\xff\xff\xa0`C\x80\xff\xff\xff\xff\xcbT\xb3\x00\xff\xff\xff\xff\xcb\xc7e\x80\xff\xff\xff\xff̷V\x80\xff\xff\xff\xffͧG\x80\xff\xff\xff\xffΠs\x00\xff\xff\xff\xffχ" + + ")\x80\xff\xff\xff\xff\xfb\u008d\x00\xff\xff\xff\xff\xfc\xb2~\x00\xff\xff\xff\xff\xfd\xc7Y\x00\xff\xff\xff\xff\xfev\xb0\x80\xff\xff\xff\xff\xff\xa7;\x00\x00\x00\x00\x00\x00V\x92\x80\x00\x00\x00\x00\x01\x87\x1d\x00\x00\x00" + + "\x00\x00\x02?\xaf\x00\x00\x00\x00\x00\x03p9\x80\x00\x00\x00\x00\x04\r\x1c\x00\x00\x00\x00\x00\x05P\x1b\x80\x00\x00\x00\x00\x05\xf68\x80\x00\x00\x00\x00\a/\xfd\x80\x00\x00\x00\x00\a\xd6\x1a\x80\x00\x00\x00\x00\t\x0f" + + "߀\x00\x00\x00\x00\t\xb5\xfc\x80\x00\x00\x00\x00\n\xef\xc1\x80\x00\x00\x00\x00\v\x9f\x19\x00\x00\x00\x00\x00\f\xd8\xde\x00\x00\x00\x00\x00\r~\xfb\x00\x00\x00\x00\x00\x0e\xb8\xc0\x00\x00\x00\x00\x00\x0f^\xdd\x00\x00\x00" + + "\x00\x00\x10\x98\xa2\x00\x00\x00\x00\x00\x11>\xbf\x00\x00\x00\x00\x00\x12x\x84\x00\x00\x00\x00\x00\x13\x1e\xa1\x00\x00\x00\x00\x00\x14Xf\x00\x00\x00\x00\x00\x14\xfe\x83\x00\x00\x00\x00\x00\x168H\x00\x00\x00\x00\x00\x17\x03" + + "O\x00\x00\x00\x00\x00\x18!d\x80\x00\x00\x00\x00\x18\xe31\x00\x00\x00\x00\x00\x1a\x01F\x80\x00\x00\x00\x00\x1a\xa7c\x80\x00\x00\x00\x00\x1b\xe1(\x80\x00\x00\x00\x00\x1c\x87E\x80\x00\x00\x00\x00\x1d\xc1\n\x80\x00\x00" + + "\x00\x00\x1eg'\x80\x00\x00\x00\x00\x1f\x97\xb2\x00\x00\x00\x00\x00 Y~\x80\x00\x00\x00\x00!\x80\u0380\x00\x00\x00\x00\"B\x9b\x00\x00\x00\x00\x00#i\xeb\x00\x00\x00\x00\x00$\"}\x00\x00\x00\x00\x00%I" + + "\xcd\x00\x00\x00\x00\x00&\x02_\x00\x00\x00\x00\x00')\xaf\x00\x00\x00\x00\x00'\xf4\xb6\x00\x00\x00\x00\x00(\xed\xe1\x80\x00\x00\x00\x00)Ԙ\x00\x00\x00\x00\x00*\xcdÀ\x00\x00\x00\x00+\xb4z\x00\x00\x00" + + "\x00\x00,\xad\xa5\x80\x00\x00\x00\x00-\x94\\\x00\x00\x00\x00\x00.\x8d\x87\x80\x00\x00\x00\x00/t>\x00\x00\x00\x00\x000mi\x80\x00\x00\x00\x001]Z\x80\x00\x00\x00\x002V\x86\x00\x00\x00\x00\x003=" + + "<\x80\x00\x00\x00\x0046h\x00\x00\x00\x00\x005\x1d\x1e\x80\x00\x00\x00\x006\x16J\x00\x00\x00\x00\x006\xfd\x00\x80\x00\x00\x00\x007\xf6,\x00\x00\x00\x00\x008\xdc\xe2\x80\x00\x00\x00\x009\xa7\xe9\x80\x00\x00" + + "\x00\x00:\xbcĀ\x00\x00\x00\x00;\xbf*\x80\x00\x00\x00\x00<\xa5\xe1\x00\x00\x00\x00\x00=\x9f\f\x80\x00\x00\x00\x00>\x85\xc3\x00\x00\x00\x00\x00?~\xee\x80\x00\x00\x00\x00@e\xa5\x00\x00\x00\x00\x00A^" + + "Ѐ\x00\x00\x00\x00BE\x87\x00\x00\x00\x00\x00C>\xb2\x80\x00\x00\x00\x00D.\xa3\x80\x00\x00\x00\x00E\x1e\x94\x80\x00\x00\x00\x00F\x05K\x00\x00\x00\x00\x00G\a\xb1\x00\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\x8d\xc4\x00\x00\x00\x00\x9a\xb0\x01\x04\x00\x00\x8c\xa0\x00\tLMT\x00AEDT\x00AEST\x00\nAEST-10AEDT,M1" + - "0.1.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RE\xf2\xe6Z\xeb\x03\x00\x00\xeb\x03\x00\x00\x12\x00\x1c\x00Australia/Tasma" + - "niaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00^\x00\x00" + - "\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xfft.\x00\xe4\xff\xff\xff\xff\x9b\xd5x\x80\xff\xff\xff\xff\x9c\xbc/\x00\xff\xff\xff\xff\x9d\xdaD\x80\xff\xff\xff\xff\x9e\x80a\x80\xff\xff\xff\xff\x9f\xba&\x80\xff\xff\xff\xff\xa0`" + - "C\x80\xff\xff\xff\xff\xcbT\xb3\x00\xff\xff\xff\xff\xcb\xc7e\x80\xff\xff\xff\xff̷V\x80\xff\xff\xff\xffͧG\x80\xff\xff\xff\xffΠs\x00\xff\xff\xff\xffχ)\x80\xff\xff\xff\xff\xfb\u008d\x00\xff\xff" + - "\xff\xff\xfc\xb2~\x00\xff\xff\xff\xff\xfd\xc7Y\x00\xff\xff\xff\xff\xfev\xb0\x80\xff\xff\xff\xff\xff\xa7;\x00\x00\x00\x00\x00\x00V\x92\x80\x00\x00\x00\x00\x01\x87\x1d\x00\x00\x00\x00\x00\x02?\xaf\x00\x00\x00\x00\x00\x03p" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00\x8a\x1c\x00\x00\x00\x00\x9a\xb0\x01\x04\x00\x00\x8c\xa0\x00\tLMT\x00AEDT\x00AEST\x00\nAES" + + "T-10AEDT,M10.1.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS3\xba\xde\xd3!\x01\x00\x00!\x01\x00\x00\x12\x00\x1c\x00Aust" + + "ralia/BrisbaneUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xffr\xed\x9f\b\xff\xff\xff\xff\x9cN\u0080\xff\xff\xff\xff\x9c\xbc/\x00\xff\xff\xff\xff\xcbT\xb3\x00\xff\xff\xff\xff\xcb\xc7e\x80\xff\xff\xff" + + "\xff̷V\x80\xff\xff\xff\xffͧG\x80\xff\xff\xff\xffΠs\x00\xff\xff\xff\xffχ)\x80\x00\x00\x00\x00\x03p9\x80\x00\x00\x00\x00\x04\r\x1c\x00\x00\x00\x00\x00%I\xcd\x00\x00\x00\x00\x00%\xef\xea" + + "\x00\x00\x00\x00\x00')\xaf\x00\x00\x00\x00\x00'\xcf\xcc\x00\x00\x00\x00\x00)\t\x91\x00\x00\x00\x00\x00)\xaf\xae\x00\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\x8fx\x00\x00\x00\x00\x9a\xb0" + + "\x01\x04\x00\x00\x8c\xa0\x00\tLMT\x00AEDT\x00AEST\x00\nAEST-10\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSo3\xdaR\xb4\x02\x00\x00\xb4\x02\x00\x00\x13\x00\x1c" + + "\x00Australia/Lord_HoweUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x05\x00\x00\x00\x19\xff\xff\xff\xffs\x16w\xdc\x00\x00\x00\x00\x14\xfef\xe0\x00\x00\x00\x00\x168@\xf8\x00\x00\x00\x00\x16\xe7\x8ah\x00\x00\x00\x00\x18" + + "!]x\x00\x00\x00\x00\x18\xc7lh\x00\x00\x00\x00\x1a\x01?x\x00\x00\x00\x00\x1a\xa7Nh\x00\x00\x00\x00\x1b\xe1!x\x00\x00\x00\x00\x1c\x870h\x00\x00\x00\x00\x1d\xc1\x03x\x00\x00\x00\x00\x1ey\x8ep\x00" + + "\x00\x00\x00\x1f\x97\xaa\xf8\x00\x00\x00\x00 Ypp\x00\x00\x00\x00!\x80\xc7x\x00\x00\x00\x00\"B\x8c\xf0\x00\x00\x00\x00#i\xe3\xf8\x00\x00\x00\x00$\"n\xf0\x00\x00\x00\x00%I\xc5\xf8\x00\x00\x00\x00%" + + "\xef\xdb\xf0\x00\x00\x00\x00')\xa7\xf8\x00\x00\x00\x00'Ͻ\xf0\x00\x00\x00\x00)\t\x89\xf8\x00\x00\x00\x00)\xaf\x9f\xf0\x00\x00\x00\x00*\xe9k\xf8\x00\x00\x00\x00+\x98\xbcp\x00\x00\x00\x00,҈x\x00" + + "\x00\x00\x00-x\x9ep\x00\x00\x00\x00.\xb2jx\x00\x00\x00\x00/X\x80p\x00\x00\x00\x000\x92Lx\x00\x00\x00\x001]Lp\x00\x00\x00\x002r.x\x00\x00\x00\x003=.p\x00\x00\x00\x004" + + "R\x10x\x00\x00\x00\x005\x1d\x10p\x00\x00\x00\x0061\xf2x\x00\x00\x00\x006\xfc\xf2p\x00\x00\x00\x008\x1b\x0e\xf8\x00\x00\x00\x008\xdc\xd4p\x00\x00\x00\x009\xa7\xe2x\x00\x00\x00\x00:\xbc\xb6p\x00" + + "\x00\x00\x00;\xda\xd2\xf8\x00\x00\x00\x00<\xa5\xd2\xf0\x00\x00\x00\x00=\xba\xb4\xf8\x00\x00\x00\x00>\x85\xb4\xf0\x00\x00\x00\x00?\x9a\x96\xf8\x00\x00\x00\x00@e\x96\xf0\x00\x00\x00\x00A\x83\xb3x\x00\x00\x00\x00B" + + "Ex\xf0\x00\x00\x00\x00Cc\x95x\x00\x00\x00\x00D.\x95p\x00\x00\x00\x00ECwx\x00\x00\x00\x00F\x05<\xf0\x00\x00\x00\x00G#Yx\x00\x00\x00\x00G\xf7\x93\xf0\x01\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x00\x00\x95$\x00\x00\x00\x00\x8c\xa0\x00\x04\x00" + + "\x00\xa1\xb8\x01\t\x00\x00\x93\xa8\x00\x0f\x00\x00\x9a\xb0\x01\x15LMT\x00AEST\x00+1130\x00+1030\x00+11\x00\n<+1030>-10:30<+11" + + ">-11,M10.1.0,M4.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSE\xf2\xe6Z\xeb\x03\x00\x00\xeb\x03\x00\x00\x10\x00\x1c\x00Australia/" + + "CurrieUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "^\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xfft.\x00\xe4\xff\xff\xff\xff\x9b\xd5x\x80\xff\xff\xff\xff\x9c\xbc/\x00\xff\xff\xff\xff\x9d\xdaD\x80\xff\xff\xff\xff\x9e\x80a\x80\xff\xff\xff\xff\x9f\xba&\x80\xff\xff\xff" + + "\xff\xa0`C\x80\xff\xff\xff\xff\xcbT\xb3\x00\xff\xff\xff\xff\xcb\xc7e\x80\xff\xff\xff\xff̷V\x80\xff\xff\xff\xffͧG\x80\xff\xff\xff\xffΠs\x00\xff\xff\xff\xffχ)\x80\xff\xff\xff\xff\xfb\u008d" + + "\x00\xff\xff\xff\xff\xfc\xb2~\x00\xff\xff\xff\xff\xfd\xc7Y\x00\xff\xff\xff\xff\xfev\xb0\x80\xff\xff\xff\xff\xff\xa7;\x00\x00\x00\x00\x00\x00V\x92\x80\x00\x00\x00\x00\x01\x87\x1d\x00\x00\x00\x00\x00\x02?\xaf\x00\x00\x00\x00" + + "\x00\x03p9\x80\x00\x00\x00\x00\x04\r\x1c\x00\x00\x00\x00\x00\x05P\x1b\x80\x00\x00\x00\x00\x05\xf68\x80\x00\x00\x00\x00\a/\xfd\x80\x00\x00\x00\x00\a\xd6\x1a\x80\x00\x00\x00\x00\t\x0f߀\x00\x00\x00\x00\t\xb5\xfc" + + "\x80\x00\x00\x00\x00\n\xef\xc1\x80\x00\x00\x00\x00\v\x9f\x19\x00\x00\x00\x00\x00\f\xd8\xde\x00\x00\x00\x00\x00\r~\xfb\x00\x00\x00\x00\x00\x0e\xb8\xc0\x00\x00\x00\x00\x00\x0f^\xdd\x00\x00\x00\x00\x00\x10\x98\xa2\x00\x00\x00\x00" + + "\x00\x11>\xbf\x00\x00\x00\x00\x00\x12x\x84\x00\x00\x00\x00\x00\x13\x1e\xa1\x00\x00\x00\x00\x00\x14Xf\x00\x00\x00\x00\x00\x14\xfe\x83\x00\x00\x00\x00\x00\x168H\x00\x00\x00\x00\x00\x17\x03O\x00\x00\x00\x00\x00\x18!d" + + "\x80\x00\x00\x00\x00\x18\xe31\x00\x00\x00\x00\x00\x1a\x01F\x80\x00\x00\x00\x00\x1a\xa7c\x80\x00\x00\x00\x00\x1b\xe1(\x80\x00\x00\x00\x00\x1c\x87E\x80\x00\x00\x00\x00\x1d\xc1\n\x80\x00\x00\x00\x00\x1eg'\x80\x00\x00\x00" + + "\x00\x1f\x97\xb2\x00\x00\x00\x00\x00 Y~\x80\x00\x00\x00\x00!\x80\u0380\x00\x00\x00\x00\"B\x9b\x00\x00\x00\x00\x00#i\xeb\x00\x00\x00\x00\x00$\"}\x00\x00\x00\x00\x00%I\xcd\x00\x00\x00\x00\x00&\x02_" + + "\x00\x00\x00\x00\x00')\xaf\x00\x00\x00\x00\x00'\xf4\xb6\x00\x00\x00\x00\x00(\xed\xe1\x80\x00\x00\x00\x00)Ԙ\x00\x00\x00\x00\x00*\xcdÀ\x00\x00\x00\x00+\xb4z\x00\x00\x00\x00\x00,\xad\xa5\x80\x00\x00\x00" + + "\x00-\x94\\\x00\x00\x00\x00\x00.\x8d\x87\x80\x00\x00\x00\x00/t>\x00\x00\x00\x00\x000mi\x80\x00\x00\x00\x001]Z\x80\x00\x00\x00\x002V\x86\x00\x00\x00\x00\x003=<\x80\x00\x00\x00\x0046h" + + "\x00\x00\x00\x00\x005\x1d\x1e\x80\x00\x00\x00\x006\x16J\x00\x00\x00\x00\x006\xfd\x00\x80\x00\x00\x00\x007\xf6,\x00\x00\x00\x00\x008\xdc\xe2\x80\x00\x00\x00\x009\xa7\xe9\x80\x00\x00\x00\x00:\xbcĀ\x00\x00\x00" + + "\x00;\xbf*\x80\x00\x00\x00\x00<\xa5\xe1\x00\x00\x00\x00\x00=\x9f\f\x80\x00\x00\x00\x00>\x85\xc3\x00\x00\x00\x00\x00?~\xee\x80\x00\x00\x00\x00@e\xa5\x00\x00\x00\x00\x00A^Ѐ\x00\x00\x00\x00BE\x87" + + "\x00\x00\x00\x00\x00C>\xb2\x80\x00\x00\x00\x00D.\xa3\x80\x00\x00\x00\x00E\x1e\x94\x80\x00\x00\x00\x00F\x05K\x00\x00\x00\x00\x00G\a\xb1\x00\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00\x8a\x1c\x00\x00\x00\x00\x9a\xb0\x01\x04\x00\x00\x8c\xa0\x00\tLMT\x00AEDT\x00AEST\x00\nAEST-10AEDT," + + "M10.1.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x8ff~ՙ\x03\x00\x00\x99\x03\x00\x00\x0f\x00\x1c\x00Australia/Sou" + + "thUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00T\x00\x00\x00" + + "\x04\x00\x00\x00\x0e\xff\xff\xff\xffs\x16\x8b\x14\xff\xff\xff\xff{\x12\x03p\xff\xff\xff\xff\x9cNɈ\xff\xff\xff\xff\x9c\xbc6\b\xff\xff\xff\xff\xcbT\xba\b\xff\xff\xff\xff\xcb\xc7l\x88\xff\xff\xff\xff̷]" + + "\x88\xff\xff\xff\xffͧN\x88\xff\xff\xff\xffΠz\b\xff\xff\xff\xffχ0\x88\x00\x00\x00\x00\x03p@\x88\x00\x00\x00\x00\x04\r#\b\x00\x00\x00\x00\x05P\"\x88\x00\x00\x00\x00\x05\xf6?\x88\x00\x00\x00" + + "\x00\a0\x04\x88\x00\x00\x00\x00\a\xd6!\x88\x00\x00\x00\x00\t\x0f\xe6\x88\x00\x00\x00\x00\t\xb6\x03\x88\x00\x00\x00\x00\n\xefȈ\x00\x00\x00\x00\v\x9f \b\x00\x00\x00\x00\f\xd8\xe5\b\x00\x00\x00\x00\r\u007f\x02" + + "\b\x00\x00\x00\x00\x0e\xb8\xc7\b\x00\x00\x00\x00\x0f^\xe4\b\x00\x00\x00\x00\x10\x98\xa9\b\x00\x00\x00\x00\x11>\xc6\b\x00\x00\x00\x00\x12x\x8b\b\x00\x00\x00\x00\x13\x1e\xa8\b\x00\x00\x00\x00\x14Xm\b\x00\x00\x00" + + "\x00\x14\xfe\x8a\b\x00\x00\x00\x00\x168O\b\x00\x00\x00\x00\x16禈\x00\x00\x00\x00\x18!k\x88\x00\x00\x00\x00\x18Lj\x88\x00\x00\x00\x00\x1a\x01M\x88\x00\x00\x00\x00\x1a\xa7j\x88\x00\x00\x00\x00\x1b\xe1/" + + "\x88\x00\x00\x00\x00\x1c\x87L\x88\x00\x00\x00\x00\x1d\xc1\x11\x88\x00\x00\x00\x00\x1ey\xa3\x88\x00\x00\x00\x00\x1f\x97\xb9\b\x00\x00\x00\x00 Y\x85\x88\x00\x00\x00\x00!\x80Ո\x00\x00\x00\x00\"B\xa2\b\x00\x00\x00" + + "\x00#i\xf2\b\x00\x00\x00\x00$\"\x84\b\x00\x00\x00\x00%I\xd4\b\x00\x00\x00\x00&\x02f\b\x00\x00\x00\x00')\xb6\b\x00\x00\x00\x00'\xcf\xd3\b\x00\x00\x00\x00)\t\x98\b\x00\x00\x00\x00)\xcbd" + + "\x88\x00\x00\x00\x00*\xe9z\b\x00\x00\x00\x00+\x98ш\x00\x00\x00\x00,Җ\x88\x00\x00\x00\x00-\x8b(\x88\x00\x00\x00\x00.\xb2x\x88\x00\x00\x00\x00/tE\b\x00\x00\x00\x000\x92Z\x88\x00\x00\x00" + + "\x001]a\x88\x00\x00\x00\x002r<\x88\x00\x00\x00\x003=C\x88\x00\x00\x00\x004R\x1e\x88\x00\x00\x00\x005\x1d%\x88\x00\x00\x00\x0062\x00\x88\x00\x00\x00\x006\xfd\a\x88\x00\x00\x00\x008\x1b\x1d" + + "\b\x00\x00\x00\x008\xdc\xe9\x88\x00\x00\x00\x009\xfa\xff\b\x00\x00\x00\x00:\xbcˈ\x00\x00\x00\x00;\xda\xe1\b\x00\x00\x00\x00<\xa5\xe8\b\x00\x00\x00\x00=\xba\xc3\b\x00\x00\x00\x00>\x85\xca\b\x00\x00\x00" + + "\x00?\x9a\xa5\b\x00\x00\x00\x00@e\xac\b\x00\x00\x00\x00A\x83\xc1\x88\x00\x00\x00\x00BE\x8e\b\x00\x00\x00\x00Cc\xa3\x88\x00\x00\x00\x00D.\xaa\x88\x00\x00\x00\x00EC\x85\x88\x00\x00\x00\x00F\x05R" + + "\b\x00\x00\x00\x00G#g\x88\x00\x00\x00\x00G\xf7\xa9\b\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x00\x00\x81\xec\x00\x00\x00\x00~\x90\x00\x04\x00\x00\x93\xa8\x01\t\x00" + + "\x00\x85\x98\x00\x04LMT\x00ACST\x00ACDT\x00\nACST-9:30ACDT,M10.1.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00" + + "\x00#\x82iSX\xb9\x9ap\x88\x03\x00\x00\x88\x03\x00\x00\x12\x00\x1c\x00Australia/CanberraUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E" + + "\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + + "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00S\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xffs\x16\u007f<\xff\xff\xff\xff\x9cN\u0080\xff\xff" + + "\xff\xff\x9c\xbc/\x00\xff\xff\xff\xff\xcbT\xb3\x00\xff\xff\xff\xff\xcb\xc7e\x80\xff\xff\xff\xff̷V\x80\xff\xff\xff\xffͧG\x80\xff\xff\xff\xffΠs\x00\xff\xff\xff\xffχ)\x80\x00\x00\x00\x00\x03p" + "9\x80\x00\x00\x00\x00\x04\r\x1c\x00\x00\x00\x00\x00\x05P\x1b\x80\x00\x00\x00\x00\x05\xf68\x80\x00\x00\x00\x00\a/\xfd\x80\x00\x00\x00\x00\a\xd6\x1a\x80\x00\x00\x00\x00\t\x0f߀\x00\x00\x00\x00\t\xb5\xfc\x80\x00\x00" + "\x00\x00\n\xef\xc1\x80\x00\x00\x00\x00\v\x9f\x19\x00\x00\x00\x00\x00\f\xd8\xde\x00\x00\x00\x00\x00\r~\xfb\x00\x00\x00\x00\x00\x0e\xb8\xc0\x00\x00\x00\x00\x00\x0f^\xdd\x00\x00\x00\x00\x00\x10\x98\xa2\x00\x00\x00\x00\x00\x11>" + - "\xbf\x00\x00\x00\x00\x00\x12x\x84\x00\x00\x00\x00\x00\x13\x1e\xa1\x00\x00\x00\x00\x00\x14Xf\x00\x00\x00\x00\x00\x14\xfe\x83\x00\x00\x00\x00\x00\x168H\x00\x00\x00\x00\x00\x17\x03O\x00\x00\x00\x00\x00\x18!d\x80\x00\x00" + - "\x00\x00\x18\xe31\x00\x00\x00\x00\x00\x1a\x01F\x80\x00\x00\x00\x00\x1a\xa7c\x80\x00\x00\x00\x00\x1b\xe1(\x80\x00\x00\x00\x00\x1c\x87E\x80\x00\x00\x00\x00\x1d\xc1\n\x80\x00\x00\x00\x00\x1eg'\x80\x00\x00\x00\x00\x1f\x97" + - "\xb2\x00\x00\x00\x00\x00 Y~\x80\x00\x00\x00\x00!\x80\u0380\x00\x00\x00\x00\"B\x9b\x00\x00\x00\x00\x00#i\xeb\x00\x00\x00\x00\x00$\"}\x00\x00\x00\x00\x00%I\xcd\x00\x00\x00\x00\x00&\x02_\x00\x00\x00" + - "\x00\x00')\xaf\x00\x00\x00\x00\x00'\xf4\xb6\x00\x00\x00\x00\x00(\xed\xe1\x80\x00\x00\x00\x00)Ԙ\x00\x00\x00\x00\x00*\xcdÀ\x00\x00\x00\x00+\xb4z\x00\x00\x00\x00\x00,\xad\xa5\x80\x00\x00\x00\x00-\x94" + - "\\\x00\x00\x00\x00\x00.\x8d\x87\x80\x00\x00\x00\x00/t>\x00\x00\x00\x00\x000mi\x80\x00\x00\x00\x001]Z\x80\x00\x00\x00\x002V\x86\x00\x00\x00\x00\x003=<\x80\x00\x00\x00\x0046h\x00\x00\x00" + - "\x00\x005\x1d\x1e\x80\x00\x00\x00\x006\x16J\x00\x00\x00\x00\x006\xfd\x00\x80\x00\x00\x00\x007\xf6,\x00\x00\x00\x00\x008\xdc\xe2\x80\x00\x00\x00\x009\xa7\xe9\x80\x00\x00\x00\x00:\xbcĀ\x00\x00\x00\x00;\xbf" + - "*\x80\x00\x00\x00\x00<\xa5\xe1\x00\x00\x00\x00\x00=\x9f\f\x80\x00\x00\x00\x00>\x85\xc3\x00\x00\x00\x00\x00?~\xee\x80\x00\x00\x00\x00@e\xa5\x00\x00\x00\x00\x00A^Ѐ\x00\x00\x00\x00BE\x87\x00\x00\x00" + - "\x00\x00C>\xb2\x80\x00\x00\x00\x00D.\xa3\x80\x00\x00\x00\x00E\x1e\x94\x80\x00\x00\x00\x00F\x05K\x00\x00\x00\x00\x00G\a\xb1\x00\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\xbf\x00\x00\x00\x00\x00\x12x\x84\x00\x00\x00\x00\x00\x13\x1e\xa1\x00\x00\x00\x00\x00\x14Xf\x00\x00\x00\x00\x00\x14\xfe\x83\x00\x00\x00\x00\x00\x168H\x00\x00\x00\x00\x00\x17\f\x89\x80\x00\x00\x00\x00\x18!d\x80\x00\x00" + + "\x00\x00\x18ǁ\x80\x00\x00\x00\x00\x1a\x01F\x80\x00\x00\x00\x00\x1a\xa7c\x80\x00\x00\x00\x00\x1b\xe1(\x80\x00\x00\x00\x00\x1c\x87E\x80\x00\x00\x00\x00\x1d\xc1\n\x80\x00\x00\x00\x00\x1ey\x9c\x80\x00\x00\x00\x00\x1f\x97" + + "\xb2\x00\x00\x00\x00\x00 Y~\x80\x00\x00\x00\x00!\x80\u0380\x00\x00\x00\x00\"B\x9b\x00\x00\x00\x00\x00#i\xeb\x00\x00\x00\x00\x00$\"}\x00\x00\x00\x00\x00%I\xcd\x00\x00\x00\x00\x00%\xef\xea\x00\x00\x00" + + "\x00\x00')\xaf\x00\x00\x00\x00\x00'\xcf\xcc\x00\x00\x00\x00\x00)\t\x91\x00\x00\x00\x00\x00)\xaf\xae\x00\x00\x00\x00\x00*\xe9s\x00\x00\x00\x00\x00+\x98ʀ\x00\x00\x00\x00,ҏ\x80\x00\x00\x00\x00-x" + + "\xac\x80\x00\x00\x00\x00.\xb2q\x80\x00\x00\x00\x00/X\x8e\x80\x00\x00\x00\x000\x92S\x80\x00\x00\x00\x001]Z\x80\x00\x00\x00\x002r5\x80\x00\x00\x00\x003=<\x80\x00\x00\x00\x004R\x17\x80\x00\x00" + + "\x00\x005\x1d\x1e\x80\x00\x00\x00\x0061\xf9\x80\x00\x00\x00\x006\xfd\x00\x80\x00\x00\x00\x008\x1b\x16\x00\x00\x00\x00\x008\xdc\xe2\x80\x00\x00\x00\x009\xa7\xe9\x80\x00\x00\x00\x00:\xbcĀ\x00\x00\x00\x00;\xda" + + "\xda\x00\x00\x00\x00\x00<\xa5\xe1\x00\x00\x00\x00\x00=\xba\xbc\x00\x00\x00\x00\x00>\x85\xc3\x00\x00\x00\x00\x00?\x9a\x9e\x00\x00\x00\x00\x00@e\xa5\x00\x00\x00\x00\x00A\x83\xba\x80\x00\x00\x00\x00BE\x87\x00\x00\x00" + + "\x00\x00Cc\x9c\x80\x00\x00\x00\x00D.\xa3\x80\x00\x00\x00\x00EC~\x80\x00\x00\x00\x00F\x05K\x00\x00\x00\x00\x00G#`\x80\x00\x00\x00\x00G\xf7\xa2\x00\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00\x8a\x1c\x00\x00\x00\x00\x9a\xb0\x01\x04\x00\x00\x8c\xa0\x00\tLMT\x00AEDT\x00AEST\x00\nAEST-10AEDT,M10" + - ".1.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x8ff~ՙ\x03\x00\x00\x99\x03\x00\x00\x0f\x00\x1c\x00Australia/SouthU" + - "T\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\x8d\xc4\x00\x00\x00\x00\x9a\xb0\x01\x04\x00\x00\x8c\xa0\x00\tLMT\x00AEDT\x00AEST\x00\nAEST-10AEDT,M10.1." + + "0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x8ff~ՙ\x03\x00\x00\x99\x03\x00\x00\x12\x00\x1c\x00Australia/AdelaideU" + + "T\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00T\x00\x00\x00\x04\x00\x00" + "\x00\x0e\xff\xff\xff\xffs\x16\x8b\x14\xff\xff\xff\xff{\x12\x03p\xff\xff\xff\xff\x9cNɈ\xff\xff\xff\xff\x9c\xbc6\b\xff\xff\xff\xff\xcbT\xba\b\xff\xff\xff\xff\xcb\xc7l\x88\xff\xff\xff\xff̷]\x88\xff\xff" + "\xff\xffͧN\x88\xff\xff\xff\xffΠz\b\xff\xff\xff\xffχ0\x88\x00\x00\x00\x00\x03p@\x88\x00\x00\x00\x00\x04\r#\b\x00\x00\x00\x00\x05P\"\x88\x00\x00\x00\x00\x05\xf6?\x88\x00\x00\x00\x00\a0" + @@ -3713,1629 +3748,1234 @@ const zipdata = "PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00 "\xa5\b\x00\x00\x00\x00@e\xac\b\x00\x00\x00\x00A\x83\xc1\x88\x00\x00\x00\x00BE\x8e\b\x00\x00\x00\x00Cc\xa3\x88\x00\x00\x00\x00D.\xaa\x88\x00\x00\x00\x00EC\x85\x88\x00\x00\x00\x00F\x05R\b\x00\x00" + "\x00\x00G#g\x88\x00\x00\x00\x00G\xf7\xa9\b\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x00\x00\x81\xec\x00\x00\x00\x00~\x90\x00\x04\x00\x00\x93\xa8\x01\t\x00\x00\x85\x98" + - "\x00\x04LMT\x00ACST\x00ACDT\x00\nACST-9:30ACDT,M10.1.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c" + - "9RX\xb9\x9ap\x88\x03\x00\x00\x88\x03\x00\x00\x12\x00\x1c\x00Australia/CanberraUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04" + - "\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00S\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xffs\x16\u007f<\xff\xff\xff\xff\x9cN\u0080\xff\xff\xff\xff\x9c" + - "\xbc/\x00\xff\xff\xff\xff\xcbT\xb3\x00\xff\xff\xff\xff\xcb\xc7e\x80\xff\xff\xff\xff̷V\x80\xff\xff\xff\xffͧG\x80\xff\xff\xff\xffΠs\x00\xff\xff\xff\xffχ)\x80\x00\x00\x00\x00\x03p9\x80\x00" + - "\x00\x00\x00\x04\r\x1c\x00\x00\x00\x00\x00\x05P\x1b\x80\x00\x00\x00\x00\x05\xf68\x80\x00\x00\x00\x00\a/\xfd\x80\x00\x00\x00\x00\a\xd6\x1a\x80\x00\x00\x00\x00\t\x0f߀\x00\x00\x00\x00\t\xb5\xfc\x80\x00\x00\x00\x00\n" + - "\xef\xc1\x80\x00\x00\x00\x00\v\x9f\x19\x00\x00\x00\x00\x00\f\xd8\xde\x00\x00\x00\x00\x00\r~\xfb\x00\x00\x00\x00\x00\x0e\xb8\xc0\x00\x00\x00\x00\x00\x0f^\xdd\x00\x00\x00\x00\x00\x10\x98\xa2\x00\x00\x00\x00\x00\x11>\xbf\x00\x00" + - "\x00\x00\x00\x12x\x84\x00\x00\x00\x00\x00\x13\x1e\xa1\x00\x00\x00\x00\x00\x14Xf\x00\x00\x00\x00\x00\x14\xfe\x83\x00\x00\x00\x00\x00\x168H\x00\x00\x00\x00\x00\x17\f\x89\x80\x00\x00\x00\x00\x18!d\x80\x00\x00\x00\x00\x18" + - "ǁ\x80\x00\x00\x00\x00\x1a\x01F\x80\x00\x00\x00\x00\x1a\xa7c\x80\x00\x00\x00\x00\x1b\xe1(\x80\x00\x00\x00\x00\x1c\x87E\x80\x00\x00\x00\x00\x1d\xc1\n\x80\x00\x00\x00\x00\x1ey\x9c\x80\x00\x00\x00\x00\x1f\x97\xb2\x00\x00" + - "\x00\x00\x00 Y~\x80\x00\x00\x00\x00!\x80\u0380\x00\x00\x00\x00\"B\x9b\x00\x00\x00\x00\x00#i\xeb\x00\x00\x00\x00\x00$\"}\x00\x00\x00\x00\x00%I\xcd\x00\x00\x00\x00\x00%\xef\xea\x00\x00\x00\x00\x00'" + - ")\xaf\x00\x00\x00\x00\x00'\xcf\xcc\x00\x00\x00\x00\x00)\t\x91\x00\x00\x00\x00\x00)\xaf\xae\x00\x00\x00\x00\x00*\xe9s\x00\x00\x00\x00\x00+\x98ʀ\x00\x00\x00\x00,ҏ\x80\x00\x00\x00\x00-x\xac\x80\x00" + - "\x00\x00\x00.\xb2q\x80\x00\x00\x00\x00/X\x8e\x80\x00\x00\x00\x000\x92S\x80\x00\x00\x00\x001]Z\x80\x00\x00\x00\x002r5\x80\x00\x00\x00\x003=<\x80\x00\x00\x00\x004R\x17\x80\x00\x00\x00\x005" + - "\x1d\x1e\x80\x00\x00\x00\x0061\xf9\x80\x00\x00\x00\x006\xfd\x00\x80\x00\x00\x00\x008\x1b\x16\x00\x00\x00\x00\x008\xdc\xe2\x80\x00\x00\x00\x009\xa7\xe9\x80\x00\x00\x00\x00:\xbcĀ\x00\x00\x00\x00;\xda\xda\x00\x00" + - "\x00\x00\x00<\xa5\xe1\x00\x00\x00\x00\x00=\xba\xbc\x00\x00\x00\x00\x00>\x85\xc3\x00\x00\x00\x00\x00?\x9a\x9e\x00\x00\x00\x00\x00@e\xa5\x00\x00\x00\x00\x00A\x83\xba\x80\x00\x00\x00\x00BE\x87\x00\x00\x00\x00\x00C" + - "c\x9c\x80\x00\x00\x00\x00D.\xa3\x80\x00\x00\x00\x00EC~\x80\x00\x00\x00\x00F\x05K\x00\x00\x00\x00\x00G#`\x80\x00\x00\x00\x00G\xf7\xa2\x00\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x00\x00\x8d\xc4\x00\x00\x00\x00\x9a\xb0\x01\x04\x00\x00\x8c\xa0\x00\tLMT\x00AEDT\x00AEST\x00\nAEST-10AEDT,M10.1.0,M" + - "4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RE\xf2\xe6Z\xeb\x03\x00\x00\xeb\x03\x00\x00\x10\x00\x1c\x00Australia/CurrieUT\t\x00\x03\x15" + - "\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00^\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff" + - "\xfft.\x00\xe4\xff\xff\xff\xff\x9b\xd5x\x80\xff\xff\xff\xff\x9c\xbc/\x00\xff\xff\xff\xff\x9d\xdaD\x80\xff\xff\xff\xff\x9e\x80a\x80\xff\xff\xff\xff\x9f\xba&\x80\xff\xff\xff\xff\xa0`C\x80\xff\xff\xff\xff\xcbT\xb3" + - "\x00\xff\xff\xff\xff\xcb\xc7e\x80\xff\xff\xff\xff̷V\x80\xff\xff\xff\xffͧG\x80\xff\xff\xff\xffΠs\x00\xff\xff\xff\xffχ)\x80\xff\xff\xff\xff\xfb\u008d\x00\xff\xff\xff\xff\xfc\xb2~\x00\xff\xff\xff" + - "\xff\xfd\xc7Y\x00\xff\xff\xff\xff\xfev\xb0\x80\xff\xff\xff\xff\xff\xa7;\x00\x00\x00\x00\x00\x00V\x92\x80\x00\x00\x00\x00\x01\x87\x1d\x00\x00\x00\x00\x00\x02?\xaf\x00\x00\x00\x00\x00\x03p9\x80\x00\x00\x00\x00\x04\r\x1c" + - "\x00\x00\x00\x00\x00\x05P\x1b\x80\x00\x00\x00\x00\x05\xf68\x80\x00\x00\x00\x00\a/\xfd\x80\x00\x00\x00\x00\a\xd6\x1a\x80\x00\x00\x00\x00\t\x0f߀\x00\x00\x00\x00\t\xb5\xfc\x80\x00\x00\x00\x00\n\xef\xc1\x80\x00\x00\x00" + - "\x00\v\x9f\x19\x00\x00\x00\x00\x00\f\xd8\xde\x00\x00\x00\x00\x00\r~\xfb\x00\x00\x00\x00\x00\x0e\xb8\xc0\x00\x00\x00\x00\x00\x0f^\xdd\x00\x00\x00\x00\x00\x10\x98\xa2\x00\x00\x00\x00\x00\x11>\xbf\x00\x00\x00\x00\x00\x12x\x84" + - "\x00\x00\x00\x00\x00\x13\x1e\xa1\x00\x00\x00\x00\x00\x14Xf\x00\x00\x00\x00\x00\x14\xfe\x83\x00\x00\x00\x00\x00\x168H\x00\x00\x00\x00\x00\x17\x03O\x00\x00\x00\x00\x00\x18!d\x80\x00\x00\x00\x00\x18\xe31\x00\x00\x00\x00" + - "\x00\x1a\x01F\x80\x00\x00\x00\x00\x1a\xa7c\x80\x00\x00\x00\x00\x1b\xe1(\x80\x00\x00\x00\x00\x1c\x87E\x80\x00\x00\x00\x00\x1d\xc1\n\x80\x00\x00\x00\x00\x1eg'\x80\x00\x00\x00\x00\x1f\x97\xb2\x00\x00\x00\x00\x00 Y~" + - "\x80\x00\x00\x00\x00!\x80\u0380\x00\x00\x00\x00\"B\x9b\x00\x00\x00\x00\x00#i\xeb\x00\x00\x00\x00\x00$\"}\x00\x00\x00\x00\x00%I\xcd\x00\x00\x00\x00\x00&\x02_\x00\x00\x00\x00\x00')\xaf\x00\x00\x00\x00" + - "\x00'\xf4\xb6\x00\x00\x00\x00\x00(\xed\xe1\x80\x00\x00\x00\x00)Ԙ\x00\x00\x00\x00\x00*\xcdÀ\x00\x00\x00\x00+\xb4z\x00\x00\x00\x00\x00,\xad\xa5\x80\x00\x00\x00\x00-\x94\\\x00\x00\x00\x00\x00.\x8d\x87" + - "\x80\x00\x00\x00\x00/t>\x00\x00\x00\x00\x000mi\x80\x00\x00\x00\x001]Z\x80\x00\x00\x00\x002V\x86\x00\x00\x00\x00\x003=<\x80\x00\x00\x00\x0046h\x00\x00\x00\x00\x005\x1d\x1e\x80\x00\x00\x00" + - "\x006\x16J\x00\x00\x00\x00\x006\xfd\x00\x80\x00\x00\x00\x007\xf6,\x00\x00\x00\x00\x008\xdc\xe2\x80\x00\x00\x00\x009\xa7\xe9\x80\x00\x00\x00\x00:\xbcĀ\x00\x00\x00\x00;\xbf*\x80\x00\x00\x00\x00<\xa5\xe1" + - "\x00\x00\x00\x00\x00=\x9f\f\x80\x00\x00\x00\x00>\x85\xc3\x00\x00\x00\x00\x00?~\xee\x80\x00\x00\x00\x00@e\xa5\x00\x00\x00\x00\x00A^Ѐ\x00\x00\x00\x00BE\x87\x00\x00\x00\x00\x00C>\xb2\x80\x00\x00\x00" + - "\x00D.\xa3\x80\x00\x00\x00\x00E\x1e\x94\x80\x00\x00\x00\x00F\x05K\x00\x00\x00\x00\x00G\a\xb1\x00\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x00\x00\x8a\x1c\x00\x00\x00\x00\x9a\xb0\x01\x04\x00\x00\x8c\xa0\x00\tLMT\x00AEDT\x00AEST\x00\nAEST-10AEDT,M10.1.0,M4.1" + - ".0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xa2ܺ\xca:\x01\x00\x00:\x01\x00\x00\x0f\x00\x1c\x00Australia/EuclaUT\t\x00\x03\x15\xac\x0e`\x15" + - "\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00" + - "\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x00\x00\x00\x03\x00\x00\x00\x10\xff\xff\xff\xfft\xa6\n" + - "\xb0\xff\xff\xff\xff\x9cN\xd4\x14\xff\xff\xff\xff\x9c\xbc@\x94\xff\xff\xff\xff\xcbTĔ\xff\xff\xff\xff\xcb\xc7w\x14\xff\xff\xff\xff̷h\x14\xff\xff\xff\xffͧY\x14\x00\x00\x00\x00\t\x0f\xf1\x14\x00\x00\x00" + - "\x00\t\xb6\x0e\x14\x00\x00\x00\x00\x1a\x01X\x14\x00\x00\x00\x00\x1a\xa7u\x14\x00\x00\x00\x00)%R\x14\x00\x00\x00\x00)\xaf\xbf\x94\x00\x00\x00\x00Eq\xb4\x94\x00\x00\x00\x00F\x05\\\x94\x00\x00\x00\x00G#r" + - "\x14\x00\x00\x00\x00G\xeey\x14\x00\x00\x00\x00I\x03T\x14\x00\x00\x00\x00I\xce[\x14\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00x\xd0\x00\x00\x00\x00\x89\x1c\x01\x04\x00\x00{\f" + - "\x00\nLMT\x00+0945\x00+0845\x00\n<+0845>-8:45\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RE\xf2\xe6Z\xeb\x03\x00\x00\xeb\x03\x00\x00\x10\x00" + - "\x1c\x00Australia/HobartUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00^\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xfft.\x00\xe4\xff\xff\xff\xff\x9b\xd5x\x80\xff\xff\xff\xff\x9c\xbc/\x00\xff\xff\xff\xff\x9d\xdaD\x80\xff\xff\xff\xff\x9e\x80a" + - "\x80\xff\xff\xff\xff\x9f\xba&\x80\xff\xff\xff\xff\xa0`C\x80\xff\xff\xff\xff\xcbT\xb3\x00\xff\xff\xff\xff\xcb\xc7e\x80\xff\xff\xff\xff̷V\x80\xff\xff\xff\xffͧG\x80\xff\xff\xff\xffΠs\x00\xff\xff\xff" + - "\xffχ)\x80\xff\xff\xff\xff\xfb\u008d\x00\xff\xff\xff\xff\xfc\xb2~\x00\xff\xff\xff\xff\xfd\xc7Y\x00\xff\xff\xff\xff\xfev\xb0\x80\xff\xff\xff\xff\xff\xa7;\x00\x00\x00\x00\x00\x00V\x92\x80\x00\x00\x00\x00\x01\x87\x1d" + - "\x00\x00\x00\x00\x00\x02?\xaf\x00\x00\x00\x00\x00\x03p9\x80\x00\x00\x00\x00\x04\r\x1c\x00\x00\x00\x00\x00\x05P\x1b\x80\x00\x00\x00\x00\x05\xf68\x80\x00\x00\x00\x00\a/\xfd\x80\x00\x00\x00\x00\a\xd6\x1a\x80\x00\x00\x00" + - "\x00\t\x0f߀\x00\x00\x00\x00\t\xb5\xfc\x80\x00\x00\x00\x00\n\xef\xc1\x80\x00\x00\x00\x00\v\x9f\x19\x00\x00\x00\x00\x00\f\xd8\xde\x00\x00\x00\x00\x00\r~\xfb\x00\x00\x00\x00\x00\x0e\xb8\xc0\x00\x00\x00\x00\x00\x0f^\xdd" + - "\x00\x00\x00\x00\x00\x10\x98\xa2\x00\x00\x00\x00\x00\x11>\xbf\x00\x00\x00\x00\x00\x12x\x84\x00\x00\x00\x00\x00\x13\x1e\xa1\x00\x00\x00\x00\x00\x14Xf\x00\x00\x00\x00\x00\x14\xfe\x83\x00\x00\x00\x00\x00\x168H\x00\x00\x00\x00" + - "\x00\x17\x03O\x00\x00\x00\x00\x00\x18!d\x80\x00\x00\x00\x00\x18\xe31\x00\x00\x00\x00\x00\x1a\x01F\x80\x00\x00\x00\x00\x1a\xa7c\x80\x00\x00\x00\x00\x1b\xe1(\x80\x00\x00\x00\x00\x1c\x87E\x80\x00\x00\x00\x00\x1d\xc1\n" + - "\x80\x00\x00\x00\x00\x1eg'\x80\x00\x00\x00\x00\x1f\x97\xb2\x00\x00\x00\x00\x00 Y~\x80\x00\x00\x00\x00!\x80\u0380\x00\x00\x00\x00\"B\x9b\x00\x00\x00\x00\x00#i\xeb\x00\x00\x00\x00\x00$\"}\x00\x00\x00\x00" + - "\x00%I\xcd\x00\x00\x00\x00\x00&\x02_\x00\x00\x00\x00\x00')\xaf\x00\x00\x00\x00\x00'\xf4\xb6\x00\x00\x00\x00\x00(\xed\xe1\x80\x00\x00\x00\x00)Ԙ\x00\x00\x00\x00\x00*\xcdÀ\x00\x00\x00\x00+\xb4z" + - "\x00\x00\x00\x00\x00,\xad\xa5\x80\x00\x00\x00\x00-\x94\\\x00\x00\x00\x00\x00.\x8d\x87\x80\x00\x00\x00\x00/t>\x00\x00\x00\x00\x000mi\x80\x00\x00\x00\x001]Z\x80\x00\x00\x00\x002V\x86\x00\x00\x00\x00" + - "\x003=<\x80\x00\x00\x00\x0046h\x00\x00\x00\x00\x005\x1d\x1e\x80\x00\x00\x00\x006\x16J\x00\x00\x00\x00\x006\xfd\x00\x80\x00\x00\x00\x007\xf6,\x00\x00\x00\x00\x008\xdc\xe2\x80\x00\x00\x00\x009\xa7\xe9" + - "\x80\x00\x00\x00\x00:\xbcĀ\x00\x00\x00\x00;\xbf*\x80\x00\x00\x00\x00<\xa5\xe1\x00\x00\x00\x00\x00=\x9f\f\x80\x00\x00\x00\x00>\x85\xc3\x00\x00\x00\x00\x00?~\xee\x80\x00\x00\x00\x00@e\xa5\x00\x00\x00\x00" + - "\x00A^Ѐ\x00\x00\x00\x00BE\x87\x00\x00\x00\x00\x00C>\xb2\x80\x00\x00\x00\x00D.\xa3\x80\x00\x00\x00\x00E\x1e\x94\x80\x00\x00\x00\x00F\x05K\x00\x00\x00\x00\x00G\a\xb1\x00\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00\x8a\x1c\x00\x00\x00\x00\x9a\xb0\x01\x04\x00\x00\x8c\xa0\x00\tLMT\x00AEDT\x00AEST\x00\n" + - "AEST-10AEDT,M10.1.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xbd\xca#\u007f\xad\x03\x00\x00\xad\x03\x00\x00\x15\x00\x1c\x00A" + - "ustralia/Broken_HillUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00U\x00\x00\x00\x05\x00\x00\x00\x13\xff\xff\xff\xffs\x16\x88d\xff\xff\xff\xffv\x04\xa5\xe0\xff\xff\xff\xff{\x12\x03p\xff\xff\xff\xff\x9cNɈ\xff\xff\xff\xff\x9c" + - "\xbc6\b\xff\xff\xff\xff\xcbT\xba\b\xff\xff\xff\xff\xcb\xc7l\x88\xff\xff\xff\xff̷]\x88\xff\xff\xff\xffͧN\x88\xff\xff\xff\xffΠz\b\xff\xff\xff\xffχ0\x88\x00\x00\x00\x00\x03p@\x88\x00" + - "\x00\x00\x00\x04\r#\b\x00\x00\x00\x00\x05P\"\x88\x00\x00\x00\x00\x05\xf6?\x88\x00\x00\x00\x00\a0\x04\x88\x00\x00\x00\x00\a\xd6!\x88\x00\x00\x00\x00\t\x0f\xe6\x88\x00\x00\x00\x00\t\xb6\x03\x88\x00\x00\x00\x00\n" + - "\xefȈ\x00\x00\x00\x00\v\x9f \b\x00\x00\x00\x00\f\xd8\xe5\b\x00\x00\x00\x00\r\u007f\x02\b\x00\x00\x00\x00\x0e\xb8\xc7\b\x00\x00\x00\x00\x0f^\xe4\b\x00\x00\x00\x00\x10\x98\xa9\b\x00\x00\x00\x00\x11>\xc6\b\x00" + - "\x00\x00\x00\x12x\x8b\b\x00\x00\x00\x00\x13\x1e\xa8\b\x00\x00\x00\x00\x14Xm\b\x00\x00\x00\x00\x14\xfe\x8a\b\x00\x00\x00\x00\x168O\b\x00\x00\x00\x00\x17\f\x90\x88\x00\x00\x00\x00\x18!k\x88\x00\x00\x00\x00\x18" + - "Lj\x88\x00\x00\x00\x00\x1a\x01M\x88\x00\x00\x00\x00\x1a\xa7j\x88\x00\x00\x00\x00\x1b\xe1/\x88\x00\x00\x00\x00\x1c\x87L\x88\x00\x00\x00\x00\x1d\xc1\x11\x88\x00\x00\x00\x00\x1ey\xa3\x88\x00\x00\x00\x00\x1f\x97\xb9\b\x00" + - "\x00\x00\x00 Y\x85\x88\x00\x00\x00\x00!\x80Ո\x00\x00\x00\x00\"B\xa2\b\x00\x00\x00\x00#i\xf2\b\x00\x00\x00\x00$\"\x84\b\x00\x00\x00\x00%I\xd4\b\x00\x00\x00\x00%\xef\xf1\b\x00\x00\x00\x00'" + - ")\xb6\b\x00\x00\x00\x00'\xcf\xd3\b\x00\x00\x00\x00)\t\x98\b\x00\x00\x00\x00)\xaf\xb5\b\x00\x00\x00\x00*\xe9z\b\x00\x00\x00\x00+\x98ш\x00\x00\x00\x00,Җ\x88\x00\x00\x00\x00-x\xb3\x88\x00" + - "\x00\x00\x00.\xb2x\x88\x00\x00\x00\x00/X\x95\x88\x00\x00\x00\x000\x92Z\x88\x00\x00\x00\x001]a\x88\x00\x00\x00\x002r<\x88\x00\x00\x00\x003=C\x88\x00\x00\x00\x004R\x1e\x88\x00\x00\x00\x005" + - "\x1d%\x88\x00\x00\x00\x0062\x00\x88\x00\x00\x00\x006\xfd\a\x88\x00\x00\x00\x008\x1b\x1d\b\x00\x00\x00\x008\xdc\xe9\x88\x00\x00\x00\x009\xfa\xff\b\x00\x00\x00\x00:\xbcˈ\x00\x00\x00\x00;\xda\xe1\b\x00" + - "\x00\x00\x00<\xa5\xe8\b\x00\x00\x00\x00=\xba\xc3\b\x00\x00\x00\x00>\x85\xca\b\x00\x00\x00\x00?\x9a\xa5\b\x00\x00\x00\x00@e\xac\b\x00\x00\x00\x00A\x83\xc1\x88\x00\x00\x00\x00BE\x8e\b\x00\x00\x00\x00C" + - "c\xa3\x88\x00\x00\x00\x00D.\xaa\x88\x00\x00\x00\x00EC\x85\x88\x00\x00\x00\x00F\x05R\b\x00\x00\x00\x00G#g\x88\x00\x00\x00\x00G\xf7\xa9\b\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04" + - "\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04" + - "\x03\x04\x03\x04\x03\x04\x03\x04\x00\x00\x84\x9c\x00\x00\x00\x00\x8c\xa0\x00\x04\x00\x00~\x90\x00\t\x00\x00\x93\xa8\x01\x0e\x00\x00\x85\x98\x00\tLMT\x00AEST\x00ACST\x00ACDT\x00\nAC" + - "ST-9:30ACDT,M10.1.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R?\x95\xbd\x12E\x01\x00\x00E\x01\x00\x00\x12\x00\x1c\x00A" + - "ustralia/LindemanUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xffr\xed\xa2\xd4\xff\xff\xff\xff\x9cN\u0080\xff\xff\xff\xff\x9c\xbc/\x00\xff\xff\xff\xff\xcbT\xb3\x00\xff\xff\xff\xff\xcb\xc7e\x80" + - "\xff\xff\xff\xff̷V\x80\xff\xff\xff\xffͧG\x80\xff\xff\xff\xffΠs\x00\xff\xff\xff\xffχ)\x80\x00\x00\x00\x00\x03p9\x80\x00\x00\x00\x00\x04\r\x1c\x00\x00\x00\x00\x00%I\xcd\x00\x00\x00\x00\x00" + - "%\xef\xea\x00\x00\x00\x00\x00')\xaf\x00\x00\x00\x00\x00'\xcf\xcc\x00\x00\x00\x00\x00)\t\x91\x00\x00\x00\x00\x00)\xaf\xae\x00\x00\x00\x00\x00*\xe9s\x00\x00\x00\x00\x00+\x98ʀ\x00\x00\x00\x00,ҏ\x80" + - "\x00\x00\x00\x00-x\xac\x80\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\x8b\xac\x00\x00\x00\x00\x9a\xb0\x01\x04\x00\x00\x8c\xa0\x00\tLMT\x00AEDT\x00AEST" + - "\x00\nAEST-10\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x9b\xe1\xc1\xa9\x88\x03\x00\x00\x88\x03\x00\x00\x13\x00\x1c\x00Australia/MelbourneU" + - "T\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00S\x00\x00\x00\x03\x00\x00" + - "\x00\x0e\xff\xff\xff\xffs\x16\x85\x18\xff\xff\xff\xff\x9cN\u0080\xff\xff\xff\xff\x9c\xbc/\x00\xff\xff\xff\xff\xcbT\xb3\x00\xff\xff\xff\xff\xcb\xc7e\x80\xff\xff\xff\xff̷V\x80\xff\xff\xff\xffͧG\x80\xff\xff" + - "\xff\xffΠs\x00\xff\xff\xff\xffχ)\x80\x00\x00\x00\x00\x03p9\x80\x00\x00\x00\x00\x04\r\x1c\x00\x00\x00\x00\x00\x05P\x1b\x80\x00\x00\x00\x00\x05\xf68\x80\x00\x00\x00\x00\a/\xfd\x80\x00\x00\x00\x00\a\xd6" + - "\x1a\x80\x00\x00\x00\x00\t\x0f߀\x00\x00\x00\x00\t\xb5\xfc\x80\x00\x00\x00\x00\n\xef\xc1\x80\x00\x00\x00\x00\v\x9f\x19\x00\x00\x00\x00\x00\f\xd8\xde\x00\x00\x00\x00\x00\r~\xfb\x00\x00\x00\x00\x00\x0e\xb8\xc0\x00\x00\x00" + - "\x00\x00\x0f^\xdd\x00\x00\x00\x00\x00\x10\x98\xa2\x00\x00\x00\x00\x00\x11>\xbf\x00\x00\x00\x00\x00\x12x\x84\x00\x00\x00\x00\x00\x13\x1e\xa1\x00\x00\x00\x00\x00\x14Xf\x00\x00\x00\x00\x00\x14\xfe\x83\x00\x00\x00\x00\x00\x168" + - "H\x00\x00\x00\x00\x00\x16矀\x00\x00\x00\x00\x18!d\x80\x00\x00\x00\x00\x18ǁ\x80\x00\x00\x00\x00\x1a\x01F\x80\x00\x00\x00\x00\x1a\xa7c\x80\x00\x00\x00\x00\x1b\xe1(\x80\x00\x00\x00\x00\x1c\x87E\x80\x00\x00" + - "\x00\x00\x1d\xc1\n\x80\x00\x00\x00\x00\x1ey\x9c\x80\x00\x00\x00\x00\x1f\x97\xb2\x00\x00\x00\x00\x00 Y~\x80\x00\x00\x00\x00!w\x94\x00\x00\x00\x00\x00\"B\x9b\x00\x00\x00\x00\x00#i\xeb\x00\x00\x00\x00\x00$\"" + - "}\x00\x00\x00\x00\x00%I\xcd\x00\x00\x00\x00\x00&\x02_\x00\x00\x00\x00\x00')\xaf\x00\x00\x00\x00\x00'\xcf\xcc\x00\x00\x00\x00\x00)\t\x91\x00\x00\x00\x00\x00)\xaf\xae\x00\x00\x00\x00\x00*\xe9s\x00\x00\x00" + - "\x00\x00+\x98ʀ\x00\x00\x00\x00,ҏ\x80\x00\x00\x00\x00-x\xac\x80\x00\x00\x00\x00.\xb2q\x80\x00\x00\x00\x00/t>\x00\x00\x00\x00\x000\x92S\x80\x00\x00\x00\x001]Z\x80\x00\x00\x00\x002r" + - "5\x80\x00\x00\x00\x003=<\x80\x00\x00\x00\x004R\x17\x80\x00\x00\x00\x005\x1d\x1e\x80\x00\x00\x00\x0061\xf9\x80\x00\x00\x00\x006\xfd\x00\x80\x00\x00\x00\x008\x1b\x16\x00\x00\x00\x00\x008\xdc\xe2\x80\x00\x00" + - "\x00\x009\xa7\xe9\x80\x00\x00\x00\x00:\xbcĀ\x00\x00\x00\x00;\xda\xda\x00\x00\x00\x00\x00<\xa5\xe1\x00\x00\x00\x00\x00=\xba\xbc\x00\x00\x00\x00\x00>\x85\xc3\x00\x00\x00\x00\x00?\x9a\x9e\x00\x00\x00\x00\x00@e" + - "\xa5\x00\x00\x00\x00\x00A\x83\xba\x80\x00\x00\x00\x00BE\x87\x00\x00\x00\x00\x00Cc\x9c\x80\x00\x00\x00\x00D.\xa3\x80\x00\x00\x00\x00EC~\x80\x00\x00\x00\x00F\x05K\x00\x00\x00\x00\x00G#`\x80\x00\x00" + - "\x00\x00G\xf7\xa2\x00\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\x87\xe8\x00\x00\x00\x00\x9a\xb0\x01\x04\x00\x00\x8c\xa0\x00\tLMT\x00AEDT\x00AEST" + - "\x00\nAEST-10AEDT,M10.1.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R3\xba\xde\xd3!\x01\x00\x00!\x01\x00\x00\x12\x00\x1c" + - "\x00Australia/BrisbaneUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x04LMT\x00ACST\x00ACDT\x00\nACST-9:30ACDT,M10.1.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82" + + "iS\xc8R\x1a\x1b\xea\x00\x00\x00\xea\x00\x00\x00\x0f\x00\x1c\x00Australia/NorthUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01" + + "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x04\x00\x00\x00\x0e\xff\xff\xff\xffs\x16\x92X\xff\xff\xff\xff{\x12\x03p\xff\xff\xff\xff\x9cNɈ" + + "\xff\xff\xff\xff\x9c\xbc6\b\xff\xff\xff\xff\xcbT\xba\b\xff\xff\xff\xff\xcb\xc7l\x88\xff\xff\xff\xff̷]\x88\xff\xff\xff\xffͧN\x88\xff\xff\xff\xffΠz\b\xff\xff\xff\xffχ0\x88\x01\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x00\x00z\xa8\x00\x00\x00\x00~\x90\x00\x04\x00\x00\x93\xa8\x01\t\x00\x00\x85\x98\x00\x04LMT\x00ACST\x00ACDT\x00\nACST-9:30\nPK\x03\x04\n" + + "\x00\x00\x00\x00\x00#\x82iSϻ\xca\x1a2\x01\x00\x002\x01\x00\x00\x0f\x00\x1c\x00Australia/PerthUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14" + + "E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00T" + + "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xfft\xa6\x16\xe4\xff\xff\xff\xff\x9cNޠ\xff" + + "\xff\xff\xff\x9c\xbcK \xff\xff\xff\xff\xcbT\xcf \xff\xff\xff\xff\xcbǁ\xa0\xff\xff\xff\xff̷r\xa0\xff\xff\xff\xffͧc\xa0\x00\x00\x00\x00\t\x0f\xfb\xa0\x00\x00\x00\x00\t\xb6\x18\xa0\x00\x00\x00\x00\x1a" + + "\x01b\xa0\x00\x00\x00\x00\x1a\xa7\u007f\xa0\x00\x00\x00\x00)%\\\xa0\x00\x00\x00\x00)\xaf\xca \x00\x00\x00\x00Eq\xbf \x00\x00\x00\x00F\x05g \x00\x00\x00\x00G#|\xa0\x00\x00\x00\x00G\ue0e0\x00" + + "\x00\x00\x00I\x03^\xa0\x00\x00\x00\x00I\xcee\xa0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00l\x9c\x00\x00\x00\x00~\x90\x01\x04\x00\x00p\x80\x00\tLMT\x00AWDT" + + "\x00AWST\x00\nAWST-8\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xbd\xca#\u007f\xad\x03\x00\x00\xad\x03\x00\x00\x15\x00\x1c\x00Australia/Broken" + + "_HillUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00U" + + "\x00\x00\x00\x05\x00\x00\x00\x13\xff\xff\xff\xffs\x16\x88d\xff\xff\xff\xffv\x04\xa5\xe0\xff\xff\xff\xff{\x12\x03p\xff\xff\xff\xff\x9cNɈ\xff\xff\xff\xff\x9c\xbc6\b\xff\xff\xff\xff\xcbT\xba\b\xff\xff\xff\xff" + + "\xcb\xc7l\x88\xff\xff\xff\xff̷]\x88\xff\xff\xff\xffͧN\x88\xff\xff\xff\xffΠz\b\xff\xff\xff\xffχ0\x88\x00\x00\x00\x00\x03p@\x88\x00\x00\x00\x00\x04\r#\b\x00\x00\x00\x00\x05P\"\x88" + + "\x00\x00\x00\x00\x05\xf6?\x88\x00\x00\x00\x00\a0\x04\x88\x00\x00\x00\x00\a\xd6!\x88\x00\x00\x00\x00\t\x0f\xe6\x88\x00\x00\x00\x00\t\xb6\x03\x88\x00\x00\x00\x00\n\xefȈ\x00\x00\x00\x00\v\x9f \b\x00\x00\x00\x00" + + "\f\xd8\xe5\b\x00\x00\x00\x00\r\u007f\x02\b\x00\x00\x00\x00\x0e\xb8\xc7\b\x00\x00\x00\x00\x0f^\xe4\b\x00\x00\x00\x00\x10\x98\xa9\b\x00\x00\x00\x00\x11>\xc6\b\x00\x00\x00\x00\x12x\x8b\b\x00\x00\x00\x00\x13\x1e\xa8\b" + + "\x00\x00\x00\x00\x14Xm\b\x00\x00\x00\x00\x14\xfe\x8a\b\x00\x00\x00\x00\x168O\b\x00\x00\x00\x00\x17\f\x90\x88\x00\x00\x00\x00\x18!k\x88\x00\x00\x00\x00\x18Lj\x88\x00\x00\x00\x00\x1a\x01M\x88\x00\x00\x00\x00" + + "\x1a\xa7j\x88\x00\x00\x00\x00\x1b\xe1/\x88\x00\x00\x00\x00\x1c\x87L\x88\x00\x00\x00\x00\x1d\xc1\x11\x88\x00\x00\x00\x00\x1ey\xa3\x88\x00\x00\x00\x00\x1f\x97\xb9\b\x00\x00\x00\x00 Y\x85\x88\x00\x00\x00\x00!\x80Ո" + + "\x00\x00\x00\x00\"B\xa2\b\x00\x00\x00\x00#i\xf2\b\x00\x00\x00\x00$\"\x84\b\x00\x00\x00\x00%I\xd4\b\x00\x00\x00\x00%\xef\xf1\b\x00\x00\x00\x00')\xb6\b\x00\x00\x00\x00'\xcf\xd3\b\x00\x00\x00\x00" + + ")\t\x98\b\x00\x00\x00\x00)\xaf\xb5\b\x00\x00\x00\x00*\xe9z\b\x00\x00\x00\x00+\x98ш\x00\x00\x00\x00,Җ\x88\x00\x00\x00\x00-x\xb3\x88\x00\x00\x00\x00.\xb2x\x88\x00\x00\x00\x00/X\x95\x88" + + "\x00\x00\x00\x000\x92Z\x88\x00\x00\x00\x001]a\x88\x00\x00\x00\x002r<\x88\x00\x00\x00\x003=C\x88\x00\x00\x00\x004R\x1e\x88\x00\x00\x00\x005\x1d%\x88\x00\x00\x00\x0062\x00\x88\x00\x00\x00\x00" + + "6\xfd\a\x88\x00\x00\x00\x008\x1b\x1d\b\x00\x00\x00\x008\xdc\xe9\x88\x00\x00\x00\x009\xfa\xff\b\x00\x00\x00\x00:\xbcˈ\x00\x00\x00\x00;\xda\xe1\b\x00\x00\x00\x00<\xa5\xe8\b\x00\x00\x00\x00=\xba\xc3\b" + + "\x00\x00\x00\x00>\x85\xca\b\x00\x00\x00\x00?\x9a\xa5\b\x00\x00\x00\x00@e\xac\b\x00\x00\x00\x00A\x83\xc1\x88\x00\x00\x00\x00BE\x8e\b\x00\x00\x00\x00Cc\xa3\x88\x00\x00\x00\x00D.\xaa\x88\x00\x00\x00\x00" + + "EC\x85\x88\x00\x00\x00\x00F\x05R\b\x00\x00\x00\x00G#g\x88\x00\x00\x00\x00G\xf7\xa9\b\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03" + + "\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x00\x00\x84\x9c\x00\x00\x00" + + "\x00\x8c\xa0\x00\x04\x00\x00~\x90\x00\t\x00\x00\x93\xa8\x01\x0e\x00\x00\x85\x98\x00\tLMT\x00AEST\x00ACST\x00ACDT\x00\nACST-9:30ACDT,M10" + + ".1.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSX\xb9\x9ap\x88\x03\x00\x00\x88\x03\x00\x00\r\x00\x1c\x00Australia/ACTUT\t" + + "\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00S\x00\x00\x00\x03\x00\x00\x00\x0e" + + "\xff\xff\xff\xffs\x16\u007f<\xff\xff\xff\xff\x9cN\u0080\xff\xff\xff\xff\x9c\xbc/\x00\xff\xff\xff\xff\xcbT\xb3\x00\xff\xff\xff\xff\xcb\xc7e\x80\xff\xff\xff\xff̷V\x80\xff\xff\xff\xffͧG\x80\xff\xff\xff\xff" + + "Πs\x00\xff\xff\xff\xffχ)\x80\x00\x00\x00\x00\x03p9\x80\x00\x00\x00\x00\x04\r\x1c\x00\x00\x00\x00\x00\x05P\x1b\x80\x00\x00\x00\x00\x05\xf68\x80\x00\x00\x00\x00\a/\xfd\x80\x00\x00\x00\x00\a\xd6\x1a\x80" + + "\x00\x00\x00\x00\t\x0f߀\x00\x00\x00\x00\t\xb5\xfc\x80\x00\x00\x00\x00\n\xef\xc1\x80\x00\x00\x00\x00\v\x9f\x19\x00\x00\x00\x00\x00\f\xd8\xde\x00\x00\x00\x00\x00\r~\xfb\x00\x00\x00\x00\x00\x0e\xb8\xc0\x00\x00\x00\x00\x00" + + "\x0f^\xdd\x00\x00\x00\x00\x00\x10\x98\xa2\x00\x00\x00\x00\x00\x11>\xbf\x00\x00\x00\x00\x00\x12x\x84\x00\x00\x00\x00\x00\x13\x1e\xa1\x00\x00\x00\x00\x00\x14Xf\x00\x00\x00\x00\x00\x14\xfe\x83\x00\x00\x00\x00\x00\x168H\x00" + + "\x00\x00\x00\x00\x17\f\x89\x80\x00\x00\x00\x00\x18!d\x80\x00\x00\x00\x00\x18ǁ\x80\x00\x00\x00\x00\x1a\x01F\x80\x00\x00\x00\x00\x1a\xa7c\x80\x00\x00\x00\x00\x1b\xe1(\x80\x00\x00\x00\x00\x1c\x87E\x80\x00\x00\x00\x00" + + "\x1d\xc1\n\x80\x00\x00\x00\x00\x1ey\x9c\x80\x00\x00\x00\x00\x1f\x97\xb2\x00\x00\x00\x00\x00 Y~\x80\x00\x00\x00\x00!\x80\u0380\x00\x00\x00\x00\"B\x9b\x00\x00\x00\x00\x00#i\xeb\x00\x00\x00\x00\x00$\"}\x00" + + "\x00\x00\x00\x00%I\xcd\x00\x00\x00\x00\x00%\xef\xea\x00\x00\x00\x00\x00')\xaf\x00\x00\x00\x00\x00'\xcf\xcc\x00\x00\x00\x00\x00)\t\x91\x00\x00\x00\x00\x00)\xaf\xae\x00\x00\x00\x00\x00*\xe9s\x00\x00\x00\x00\x00" + + "+\x98ʀ\x00\x00\x00\x00,ҏ\x80\x00\x00\x00\x00-x\xac\x80\x00\x00\x00\x00.\xb2q\x80\x00\x00\x00\x00/X\x8e\x80\x00\x00\x00\x000\x92S\x80\x00\x00\x00\x001]Z\x80\x00\x00\x00\x002r5\x80" + + "\x00\x00\x00\x003=<\x80\x00\x00\x00\x004R\x17\x80\x00\x00\x00\x005\x1d\x1e\x80\x00\x00\x00\x0061\xf9\x80\x00\x00\x00\x006\xfd\x00\x80\x00\x00\x00\x008\x1b\x16\x00\x00\x00\x00\x008\xdc\xe2\x80\x00\x00\x00\x00" + + "9\xa7\xe9\x80\x00\x00\x00\x00:\xbcĀ\x00\x00\x00\x00;\xda\xda\x00\x00\x00\x00\x00<\xa5\xe1\x00\x00\x00\x00\x00=\xba\xbc\x00\x00\x00\x00\x00>\x85\xc3\x00\x00\x00\x00\x00?\x9a\x9e\x00\x00\x00\x00\x00@e\xa5\x00" + + "\x00\x00\x00\x00A\x83\xba\x80\x00\x00\x00\x00BE\x87\x00\x00\x00\x00\x00Cc\x9c\x80\x00\x00\x00\x00D.\xa3\x80\x00\x00\x00\x00EC~\x80\x00\x00\x00\x00F\x05K\x00\x00\x00\x00\x00G#`\x80\x00\x00\x00\x00" + + "G\xf7\xa2\x00\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\x8d\xc4\x00\x00\x00\x00\x9a\xb0\x01\x04\x00\x00\x8c\xa0\x00\tLMT\x00AEDT\x00AEST\x00\n" + + "AEST-10AEDT,M10.1.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xbd\xca#\u007f\xad\x03\x00\x00\xad\x03\x00\x00\x14\x00\x1c\x00A" + + "ustralia/YancowinnaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xffr\xed\x9f\b\xff\xff\xff\xff\x9cN\u0080\xff\xff\xff\xff\x9c\xbc/\x00\xff\xff\xff\xff\xcbT\xb3\x00\xff\xff\xff\xff\xcb\xc7" + - "e\x80\xff\xff\xff\xff̷V\x80\xff\xff\xff\xffͧG\x80\xff\xff\xff\xffΠs\x00\xff\xff\xff\xffχ)\x80\x00\x00\x00\x00\x03p9\x80\x00\x00\x00\x00\x04\r\x1c\x00\x00\x00\x00\x00%I\xcd\x00\x00\x00" + - "\x00\x00%\xef\xea\x00\x00\x00\x00\x00')\xaf\x00\x00\x00\x00\x00'\xcf\xcc\x00\x00\x00\x00\x00)\t\x91\x00\x00\x00\x00\x00)\xaf\xae\x00\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\x8fx\x00" + - "\x00\x00\x00\x9a\xb0\x01\x04\x00\x00\x8c\xa0\x00\tLMT\x00AEDT\x00AEST\x00\nAEST-10\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rϻ\xca\x1a2\x01\x00\x002\x01" + - "\x00\x00\x0f\x00\x1c\x00Australia/PerthUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xfft\xa6\x16\xe4\xff\xff\xff\xff\x9cNޠ\xff\xff\xff\xff\x9c\xbcK \xff\xff\xff\xff\xcbT\xcf \xff\xff\xff\xff" + - "\xcbǁ\xa0\xff\xff\xff\xff̷r\xa0\xff\xff\xff\xffͧc\xa0\x00\x00\x00\x00\t\x0f\xfb\xa0\x00\x00\x00\x00\t\xb6\x18\xa0\x00\x00\x00\x00\x1a\x01b\xa0\x00\x00\x00\x00\x1a\xa7\u007f\xa0\x00\x00\x00\x00)%\\\xa0" + - "\x00\x00\x00\x00)\xaf\xca \x00\x00\x00\x00Eq\xbf \x00\x00\x00\x00F\x05g \x00\x00\x00\x00G#|\xa0\x00\x00\x00\x00G\ue0e0\x00\x00\x00\x00I\x03^\xa0\x00\x00\x00\x00I\xcee\xa0\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00l\x9c\x00\x00\x00\x00~\x90\x01\x04\x00\x00p\x80\x00\tLMT\x00AWDT\x00AWST\x00\nAWST-8\nPK\x03\x04\n" + - "\x00\x00\x00\x00\x00\xf1c9Ro3\xdaR\xb4\x02\x00\x00\xb4\x02\x00\x00\x13\x00\x1c\x00Australia/Lord_HoweUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v" + - "\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00" + - "\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x05\x00\x00\x00\x19\xff\xff\xff\xffs\x16w\xdc\x00\x00\x00\x00\x14" + - "\xfef\xe0\x00\x00\x00\x00\x168@\xf8\x00\x00\x00\x00\x16\xe7\x8ah\x00\x00\x00\x00\x18!]x\x00\x00\x00\x00\x18\xc7lh\x00\x00\x00\x00\x1a\x01?x\x00\x00\x00\x00\x1a\xa7Nh\x00\x00\x00\x00\x1b\xe1!x\x00" + - "\x00\x00\x00\x1c\x870h\x00\x00\x00\x00\x1d\xc1\x03x\x00\x00\x00\x00\x1ey\x8ep\x00\x00\x00\x00\x1f\x97\xaa\xf8\x00\x00\x00\x00 Ypp\x00\x00\x00\x00!\x80\xc7x\x00\x00\x00\x00\"B\x8c\xf0\x00\x00\x00\x00#" + - "i\xe3\xf8\x00\x00\x00\x00$\"n\xf0\x00\x00\x00\x00%I\xc5\xf8\x00\x00\x00\x00%\xef\xdb\xf0\x00\x00\x00\x00')\xa7\xf8\x00\x00\x00\x00'Ͻ\xf0\x00\x00\x00\x00)\t\x89\xf8\x00\x00\x00\x00)\xaf\x9f\xf0\x00" + - "\x00\x00\x00*\xe9k\xf8\x00\x00\x00\x00+\x98\xbcp\x00\x00\x00\x00,҈x\x00\x00\x00\x00-x\x9ep\x00\x00\x00\x00.\xb2jx\x00\x00\x00\x00/X\x80p\x00\x00\x00\x000\x92Lx\x00\x00\x00\x001" + - "]Lp\x00\x00\x00\x002r.x\x00\x00\x00\x003=.p\x00\x00\x00\x004R\x10x\x00\x00\x00\x005\x1d\x10p\x00\x00\x00\x0061\xf2x\x00\x00\x00\x006\xfc\xf2p\x00\x00\x00\x008\x1b\x0e\xf8\x00" + - "\x00\x00\x008\xdc\xd4p\x00\x00\x00\x009\xa7\xe2x\x00\x00\x00\x00:\xbc\xb6p\x00\x00\x00\x00;\xda\xd2\xf8\x00\x00\x00\x00<\xa5\xd2\xf0\x00\x00\x00\x00=\xba\xb4\xf8\x00\x00\x00\x00>\x85\xb4\xf0\x00\x00\x00\x00?" + - "\x9a\x96\xf8\x00\x00\x00\x00@e\x96\xf0\x00\x00\x00\x00A\x83\xb3x\x00\x00\x00\x00BEx\xf0\x00\x00\x00\x00Cc\x95x\x00\x00\x00\x00D.\x95p\x00\x00\x00\x00ECwx\x00\x00\x00\x00F\x05<\xf0\x00" + - "\x00\x00\x00G#Yx\x00\x00\x00\x00G\xf7\x93\xf0\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04" + - "\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x00\x00\x95$\x00\x00\x00\x00\x8c\xa0\x00\x04\x00\x00\xa1\xb8\x01\t\x00\x00\x93\xa8\x00\x0f\x00\x00\x9a\xb0\x01\x15LMT\x00AEST\x00+1130\x00+103" + - "0\x00+11\x00\n<+1030>-10:30<+11>-11,M10.1.0,M4.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rϻ" + - "\xca\x1a2\x01\x00\x002\x01\x00\x00\x0e\x00\x1c\x00Australia/WestUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif" + - "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xfft\xa6\x16\xe4\xff\xff\xff\xff\x9cNޠ\xff\xff\xff\xff\x9c\xbcK \xff\xff\xff\xff\xcb" + - "T\xcf \xff\xff\xff\xff\xcbǁ\xa0\xff\xff\xff\xff̷r\xa0\xff\xff\xff\xffͧc\xa0\x00\x00\x00\x00\t\x0f\xfb\xa0\x00\x00\x00\x00\t\xb6\x18\xa0\x00\x00\x00\x00\x1a\x01b\xa0\x00\x00\x00\x00\x1a\xa7\u007f\xa0\x00" + - "\x00\x00\x00)%\\\xa0\x00\x00\x00\x00)\xaf\xca \x00\x00\x00\x00Eq\xbf \x00\x00\x00\x00F\x05g \x00\x00\x00\x00G#|\xa0\x00\x00\x00\x00G\ue0e0\x00\x00\x00\x00I\x03^\xa0\x00\x00\x00\x00I" + - "\xcee\xa0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00l\x9c\x00\x00\x00\x00~\x90\x01\x04\x00\x00p\x80\x00\tLMT\x00AWDT\x00AWST\x00\nAWST-" + - "8\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RX\xb9\x9ap\x88\x03\x00\x00\x88\x03\x00\x00\r\x00\x1c\x00Australia/ACTUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux" + - "\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00" + - "\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00S\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xffs\x16\u007f<\xff\xff\xff\xff" + - "\x9cN\u0080\xff\xff\xff\xff\x9c\xbc/\x00\xff\xff\xff\xff\xcbT\xb3\x00\xff\xff\xff\xff\xcb\xc7e\x80\xff\xff\xff\xff̷V\x80\xff\xff\xff\xffͧG\x80\xff\xff\xff\xffΠs\x00\xff\xff\xff\xffχ)\x80" + - "\x00\x00\x00\x00\x03p9\x80\x00\x00\x00\x00\x04\r\x1c\x00\x00\x00\x00\x00\x05P\x1b\x80\x00\x00\x00\x00\x05\xf68\x80\x00\x00\x00\x00\a/\xfd\x80\x00\x00\x00\x00\a\xd6\x1a\x80\x00\x00\x00\x00\t\x0f߀\x00\x00\x00\x00" + - "\t\xb5\xfc\x80\x00\x00\x00\x00\n\xef\xc1\x80\x00\x00\x00\x00\v\x9f\x19\x00\x00\x00\x00\x00\f\xd8\xde\x00\x00\x00\x00\x00\r~\xfb\x00\x00\x00\x00\x00\x0e\xb8\xc0\x00\x00\x00\x00\x00\x0f^\xdd\x00\x00\x00\x00\x00\x10\x98\xa2\x00" + - "\x00\x00\x00\x00\x11>\xbf\x00\x00\x00\x00\x00\x12x\x84\x00\x00\x00\x00\x00\x13\x1e\xa1\x00\x00\x00\x00\x00\x14Xf\x00\x00\x00\x00\x00\x14\xfe\x83\x00\x00\x00\x00\x00\x168H\x00\x00\x00\x00\x00\x17\f\x89\x80\x00\x00\x00\x00" + - "\x18!d\x80\x00\x00\x00\x00\x18ǁ\x80\x00\x00\x00\x00\x1a\x01F\x80\x00\x00\x00\x00\x1a\xa7c\x80\x00\x00\x00\x00\x1b\xe1(\x80\x00\x00\x00\x00\x1c\x87E\x80\x00\x00\x00\x00\x1d\xc1\n\x80\x00\x00\x00\x00\x1ey\x9c\x80" + - "\x00\x00\x00\x00\x1f\x97\xb2\x00\x00\x00\x00\x00 Y~\x80\x00\x00\x00\x00!\x80\u0380\x00\x00\x00\x00\"B\x9b\x00\x00\x00\x00\x00#i\xeb\x00\x00\x00\x00\x00$\"}\x00\x00\x00\x00\x00%I\xcd\x00\x00\x00\x00\x00" + - "%\xef\xea\x00\x00\x00\x00\x00')\xaf\x00\x00\x00\x00\x00'\xcf\xcc\x00\x00\x00\x00\x00)\t\x91\x00\x00\x00\x00\x00)\xaf\xae\x00\x00\x00\x00\x00*\xe9s\x00\x00\x00\x00\x00+\x98ʀ\x00\x00\x00\x00,ҏ\x80" + - "\x00\x00\x00\x00-x\xac\x80\x00\x00\x00\x00.\xb2q\x80\x00\x00\x00\x00/X\x8e\x80\x00\x00\x00\x000\x92S\x80\x00\x00\x00\x001]Z\x80\x00\x00\x00\x002r5\x80\x00\x00\x00\x003=<\x80\x00\x00\x00\x00" + - "4R\x17\x80\x00\x00\x00\x005\x1d\x1e\x80\x00\x00\x00\x0061\xf9\x80\x00\x00\x00\x006\xfd\x00\x80\x00\x00\x00\x008\x1b\x16\x00\x00\x00\x00\x008\xdc\xe2\x80\x00\x00\x00\x009\xa7\xe9\x80\x00\x00\x00\x00:\xbcĀ" + - "\x00\x00\x00\x00;\xda\xda\x00\x00\x00\x00\x00<\xa5\xe1\x00\x00\x00\x00\x00=\xba\xbc\x00\x00\x00\x00\x00>\x85\xc3\x00\x00\x00\x00\x00?\x9a\x9e\x00\x00\x00\x00\x00@e\xa5\x00\x00\x00\x00\x00A\x83\xba\x80\x00\x00\x00\x00" + - "BE\x87\x00\x00\x00\x00\x00Cc\x9c\x80\x00\x00\x00\x00D.\xa3\x80\x00\x00\x00\x00EC~\x80\x00\x00\x00\x00F\x05K\x00\x00\x00\x00\x00G#`\x80\x00\x00\x00\x00G\xf7\xa2\x00\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\x8d\xc4\x00\x00\x00\x00\x9a\xb0\x01\x04\x00\x00\x8c\xa0\x00\tLMT\x00AEDT\x00AEST\x00\nAEST-10AEDT," + - "M10.1.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x1c\x00Brazil/UT\t\x00\x03\x15" + - "\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x9d?\xdfڸ\x03\x00\x00\xb8\x03\x00\x00\v\x00\x1c\x00Brazil/E" + - "astUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00[\x00\x00" + - "\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96\xaar\xb4\xff\xff\xff\xff\xb8\x0fI\xe0\xff\xff\xff\xff\xb8\xfd@\xa0\xff\xff\xff\xff\xb9\xf140\xff\xff\xff\xff\xba\xdet \xff\xff\xff\xff\xda8\xae0\xff\xff\xff\xff\xda\xeb" + - "\xfa0\xff\xff\xff\xff\xdc\x19\xe1\xb0\xff\xff\xff\xffܹY \xff\xff\xff\xff\xdd\xfb\x150\xff\xff\xff\xffޛ\xde \xff\xff\xff\xff\xdfݚ0\xff\xff\xff\xff\xe0T3 \xff\xff\xff\xff\xf4Z\t0\xff\xff" + - "\xff\xff\xf5\x05^ \xff\xff\xff\xff\xf6\xc0d0\xff\xff\xff\xff\xf7\x0e\x1e\xa0\xff\xff\xff\xff\xf8Q,0\xff\xff\xff\xff\xf8\xc7\xc5 \xff\xff\xff\xff\xfa\nҰ\xff\xff\xff\xff\xfa\xa8\xf8\xa0\xff\xff\xff\xff\xfb\xec" + - "\x060\xff\xff\xff\xff\xfc\x8b}\xa0\x00\x00\x00\x00\x1dɎ0\x00\x00\x00\x00\x1exנ\x00\x00\x00\x00\x1f\xa05\xb0\x00\x00\x00\x00 3Ϡ\x00\x00\x00\x00!\x81i0\x00\x00\x00\x00\"\vȠ\x00\x00" + - "\x00\x00#X\x10\xb0\x00\x00\x00\x00#\xe2p \x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xd4\xc7 \x00\x00\x00\x00'!\x0f0\x00\x00\x00\x00'\xbd\xe3\xa0\x00\x00\x00\x00)\x00\xf10\x00\x00\x00\x00)\x94" + - "\x8b \x00\x00\x00\x00*\xea\r\xb0\x00\x00\x00\x00+k2\xa0\x00\x00\x00\x00,\xc0\xb50\x00\x00\x00\x00-f\xc4 \x00\x00\x00\x00.\xa0\x970\x00\x00\x00\x00/F\xa6 \x00\x00\x00\x000\x80y0\x00\x00" + - "\x00\x001\x1dM\xa0\x00\x00\x00\x002W \xb0\x00\x00\x00\x003\x06j \x00\x00\x00\x0048T0\x00\x00\x00\x004\xf8\xc1 \x00\x00\x00\x006 \x1f0\x00\x00\x00\x006\xcfh\xa0\x00\x00\x00\x007\xf6" + - "ư\x00\x00\x00\x008\xb8\x85 \x00\x00\x00\x009\xdf\xe30\x00\x00\x00\x00:\x8f,\xa0\x00\x00\x00\x00;\xc8\xff\xb0\x00\x00\x00\x00N\xf0\xa0\x00\x00" + - "\x00\x00?\x91\xfe0\x00\x00\x00\x00@.Ҡ\x00\x00\x00\x00A\x86\xf80\x00\x00\x00\x00B\x17\xef \x00\x00\x00\x00CQ\xc20\x00\x00\x00\x00C\xf7\xd1 \x00\x00\x00\x00EMS\xb0\x00\x00\x00\x00E\xe0" + - "\xed\xa0\x00\x00\x00\x00G\x11\x860\x00\x00\x00\x00G\xb7\x95 \x00\x00\x00\x00H\xfa\xa2\xb0\x00\x00\x00\x00I\x97w \x00\x00\x00\x00Jڄ\xb0\x00\x00\x00\x00K\x80\x93\xa0\x00\x00\x00\x00L\xbaf\xb0\x00\x00" + - "\x00\x00M`u\xa0\x00\x00\x00\x00N\x9aH\xb0\x00\x00\x00\x00OI\x92 \x00\x00\x00\x00P\x83e0\x00\x00\x00\x00Q 9\xa0\x00\x00\x00\x00RcG0\x00\x00\x00\x00S\x00\x1b\xa0\x00\x00\x00\x00TC" + - ")0\x00\x00\x00\x00T\xe98 \x00\x00\x00\x00V#\v0\x00\x00\x00\x00V\xc9\x1a \x00\x00\x00\x00X\x02\xed0\x00\x00\x00\x00X\xa8\xfc \x00\x00\x00\x00Y\xe2\xcf0\x00\x00\x00\x00Z\x88\xde \x00\x00" + - "\x00\x00[\xde`\xb0\x00\x00\x00\x00\\h\xc0 \x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xff\xd4L\x00\x00\xff\xff\xe3\xe0\x01\x04\xff\xff\xd5" + - "\xd0\x00\bLMT\x00-02\x00-03\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rg\xf5K\x89\xa2\x01\x00\x00\xa2\x01\x00\x00\v\x00\x1c\x00Brazil/" + - "AcreUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x00" + - "\x00\x00\x04\x00\x00\x00\f\xff\xff\xff\xff\x96\xaa\x86\x90\xff\xff\xff\xff\xb8\x0ff\x00\xff\xff\xff\xff\xb8\xfd\\\xc0\xff\xff\xff\xff\xb9\xf1PP\xff\xff\xff\xff\xbaސ@\xff\xff\xff\xff\xda8\xcaP\xff\xff\xff\xff\xda" + - "\xec\x16P\xff\xff\xff\xff\xdc\x19\xfd\xd0\xff\xff\xff\xffܹu@\xff\xff\xff\xff\xdd\xfb1P\xff\xff\xff\xffޛ\xfa@\xff\xff\xff\xff\xdfݶP\xff\xff\xff\xff\xe0TO@\xff\xff\xff\xff\xf4\x98\x1b\xd0\xff" + - "\xff\xff\xff\xf5\x05z@\xff\xff\xff\xff\xf6\xc0\x80P\xff\xff\xff\xff\xf7\x0e:\xc0\xff\xff\xff\xff\xf8QHP\xff\xff\xff\xff\xf8\xc7\xe1@\xff\xff\xff\xff\xfa\n\xee\xd0\xff\xff\xff\xff\xfa\xa9\x14\xc0\xff\xff\xff\xff\xfb" + - "\xec\"P\xff\xff\xff\xff\xfc\x8b\x99\xc0\x00\x00\x00\x00\x1dɪP\x00\x00\x00\x00\x1ex\xf3\xc0\x00\x00\x00\x00\x1f\xa0Q\xd0\x00\x00\x00\x00 3\xeb\xc0\x00\x00\x00\x00!\x81\x85P\x00\x00\x00\x00\"\v\xe4\xc0\x00" + - "\x00\x00\x00H`\u007fP\x00\x00\x00\x00R\u007f\x04\xc0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x02\xff\xff\xc0p\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff" + - "\xb9\xb0\x00\b\xff\xff\xc7\xc0\x00\x04LMT\x00-04\x00-05\x00\n<-05>5\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xb7-2f\xe4\x01\x00\x00\xe4\x01\x00\x00\x10\x00\x1c\x00" + - "Brazil/DeNoronhaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00U\x00\x00\x00\x05\x00\x00\x00\x13\xff\xff\xff\xffs\x16\x88d\xff\xff\xff\xffv\x04\xa5\xe0\xff\xff\xff\xff{\x12\x03p\xff\xff\xff\xff\x9cNɈ\xff\xff\xff\xff\x9c\xbc" + + "6\b\xff\xff\xff\xff\xcbT\xba\b\xff\xff\xff\xff\xcb\xc7l\x88\xff\xff\xff\xff̷]\x88\xff\xff\xff\xffͧN\x88\xff\xff\xff\xffΠz\b\xff\xff\xff\xffχ0\x88\x00\x00\x00\x00\x03p@\x88\x00\x00" + + "\x00\x00\x04\r#\b\x00\x00\x00\x00\x05P\"\x88\x00\x00\x00\x00\x05\xf6?\x88\x00\x00\x00\x00\a0\x04\x88\x00\x00\x00\x00\a\xd6!\x88\x00\x00\x00\x00\t\x0f\xe6\x88\x00\x00\x00\x00\t\xb6\x03\x88\x00\x00\x00\x00\n\xef" + + "Ȉ\x00\x00\x00\x00\v\x9f \b\x00\x00\x00\x00\f\xd8\xe5\b\x00\x00\x00\x00\r\u007f\x02\b\x00\x00\x00\x00\x0e\xb8\xc7\b\x00\x00\x00\x00\x0f^\xe4\b\x00\x00\x00\x00\x10\x98\xa9\b\x00\x00\x00\x00\x11>\xc6\b\x00\x00" + + "\x00\x00\x12x\x8b\b\x00\x00\x00\x00\x13\x1e\xa8\b\x00\x00\x00\x00\x14Xm\b\x00\x00\x00\x00\x14\xfe\x8a\b\x00\x00\x00\x00\x168O\b\x00\x00\x00\x00\x17\f\x90\x88\x00\x00\x00\x00\x18!k\x88\x00\x00\x00\x00\x18\xc7" + + "\x88\x88\x00\x00\x00\x00\x1a\x01M\x88\x00\x00\x00\x00\x1a\xa7j\x88\x00\x00\x00\x00\x1b\xe1/\x88\x00\x00\x00\x00\x1c\x87L\x88\x00\x00\x00\x00\x1d\xc1\x11\x88\x00\x00\x00\x00\x1ey\xa3\x88\x00\x00\x00\x00\x1f\x97\xb9\b\x00\x00" + + "\x00\x00 Y\x85\x88\x00\x00\x00\x00!\x80Ո\x00\x00\x00\x00\"B\xa2\b\x00\x00\x00\x00#i\xf2\b\x00\x00\x00\x00$\"\x84\b\x00\x00\x00\x00%I\xd4\b\x00\x00\x00\x00%\xef\xf1\b\x00\x00\x00\x00')" + + "\xb6\b\x00\x00\x00\x00'\xcf\xd3\b\x00\x00\x00\x00)\t\x98\b\x00\x00\x00\x00)\xaf\xb5\b\x00\x00\x00\x00*\xe9z\b\x00\x00\x00\x00+\x98ш\x00\x00\x00\x00,Җ\x88\x00\x00\x00\x00-x\xb3\x88\x00\x00" + + "\x00\x00.\xb2x\x88\x00\x00\x00\x00/X\x95\x88\x00\x00\x00\x000\x92Z\x88\x00\x00\x00\x001]a\x88\x00\x00\x00\x002r<\x88\x00\x00\x00\x003=C\x88\x00\x00\x00\x004R\x1e\x88\x00\x00\x00\x005\x1d" + + "%\x88\x00\x00\x00\x0062\x00\x88\x00\x00\x00\x006\xfd\a\x88\x00\x00\x00\x008\x1b\x1d\b\x00\x00\x00\x008\xdc\xe9\x88\x00\x00\x00\x009\xfa\xff\b\x00\x00\x00\x00:\xbcˈ\x00\x00\x00\x00;\xda\xe1\b\x00\x00" + + "\x00\x00<\xa5\xe8\b\x00\x00\x00\x00=\xba\xc3\b\x00\x00\x00\x00>\x85\xca\b\x00\x00\x00\x00?\x9a\xa5\b\x00\x00\x00\x00@e\xac\b\x00\x00\x00\x00A\x83\xc1\x88\x00\x00\x00\x00BE\x8e\b\x00\x00\x00\x00Cc" + + "\xa3\x88\x00\x00\x00\x00D.\xaa\x88\x00\x00\x00\x00EC\x85\x88\x00\x00\x00\x00F\x05R\b\x00\x00\x00\x00G#g\x88\x00\x00\x00\x00G\xf7\xa9\b\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03" + + "\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03" + + "\x04\x03\x04\x03\x04\x03\x04\x00\x00\x84\x9c\x00\x00\x00\x00\x8c\xa0\x00\x04\x00\x00~\x90\x00\t\x00\x00\x93\xa8\x01\x0e\x00\x00\x85\x98\x00\tLMT\x00AEST\x00ACST\x00ACDT\x00\nACS" + + "T-9:30ACDT,M10.1.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xc8R\x1a\x1b\xea\x00\x00\x00\xea\x00\x00\x00\x10\x00\x1c\x00Au" + + "stralia/DarwinUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x04\x00\x00\x00\x0e\xff\xff\xff\xffs\x16\x92X\xff\xff\xff\xff{\x12\x03p\xff\xff\xff\xff\x9cNɈ\xff\xff\xff\xff\x9c\xbc6\b\xff\xff\xff\xff\xcbT\xba\b\xff\xff\xff" + + "\xff\xcb\xc7l\x88\xff\xff\xff\xff̷]\x88\xff\xff\xff\xffͧN\x88\xff\xff\xff\xffΠz\b\xff\xff\xff\xffχ0\x88\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x00\x00z\xa8\x00\x00\x00\x00~\x90\x00\x04\x00" + + "\x00\x93\xa8\x01\t\x00\x00\x85\x98\x00\x04LMT\x00ACST\x00ACDT\x00\nACST-9:30\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSE\xf2\xe6Z\xeb\x03\x00\x00\xeb\x03" + + "\x00\x00\x12\x00\x1c\x00Australia/TasmaniaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00^\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xfft.\x00\xe4\xff\xff\xff\xff\x9b\xd5x\x80\xff\xff\xff\xff\x9c\xbc/\x00\xff\xff\xff\xff\x9d\xdaD\x80\xff" + + "\xff\xff\xff\x9e\x80a\x80\xff\xff\xff\xff\x9f\xba&\x80\xff\xff\xff\xff\xa0`C\x80\xff\xff\xff\xff\xcbT\xb3\x00\xff\xff\xff\xff\xcb\xc7e\x80\xff\xff\xff\xff̷V\x80\xff\xff\xff\xffͧG\x80\xff\xff\xff\xff\xce" + + "\xa0s\x00\xff\xff\xff\xffχ)\x80\xff\xff\xff\xff\xfb\u008d\x00\xff\xff\xff\xff\xfc\xb2~\x00\xff\xff\xff\xff\xfd\xc7Y\x00\xff\xff\xff\xff\xfev\xb0\x80\xff\xff\xff\xff\xff\xa7;\x00\x00\x00\x00\x00\x00V\x92\x80\x00" + + "\x00\x00\x00\x01\x87\x1d\x00\x00\x00\x00\x00\x02?\xaf\x00\x00\x00\x00\x00\x03p9\x80\x00\x00\x00\x00\x04\r\x1c\x00\x00\x00\x00\x00\x05P\x1b\x80\x00\x00\x00\x00\x05\xf68\x80\x00\x00\x00\x00\a/\xfd\x80\x00\x00\x00\x00\a" + + "\xd6\x1a\x80\x00\x00\x00\x00\t\x0f߀\x00\x00\x00\x00\t\xb5\xfc\x80\x00\x00\x00\x00\n\xef\xc1\x80\x00\x00\x00\x00\v\x9f\x19\x00\x00\x00\x00\x00\f\xd8\xde\x00\x00\x00\x00\x00\r~\xfb\x00\x00\x00\x00\x00\x0e\xb8\xc0\x00\x00" + + "\x00\x00\x00\x0f^\xdd\x00\x00\x00\x00\x00\x10\x98\xa2\x00\x00\x00\x00\x00\x11>\xbf\x00\x00\x00\x00\x00\x12x\x84\x00\x00\x00\x00\x00\x13\x1e\xa1\x00\x00\x00\x00\x00\x14Xf\x00\x00\x00\x00\x00\x14\xfe\x83\x00\x00\x00\x00\x00\x16" + + "8H\x00\x00\x00\x00\x00\x17\x03O\x00\x00\x00\x00\x00\x18!d\x80\x00\x00\x00\x00\x18\xe31\x00\x00\x00\x00\x00\x1a\x01F\x80\x00\x00\x00\x00\x1a\xa7c\x80\x00\x00\x00\x00\x1b\xe1(\x80\x00\x00\x00\x00\x1c\x87E\x80\x00" + + "\x00\x00\x00\x1d\xc1\n\x80\x00\x00\x00\x00\x1eg'\x80\x00\x00\x00\x00\x1f\x97\xb2\x00\x00\x00\x00\x00 Y~\x80\x00\x00\x00\x00!\x80\u0380\x00\x00\x00\x00\"B\x9b\x00\x00\x00\x00\x00#i\xeb\x00\x00\x00\x00\x00$" + + "\"}\x00\x00\x00\x00\x00%I\xcd\x00\x00\x00\x00\x00&\x02_\x00\x00\x00\x00\x00')\xaf\x00\x00\x00\x00\x00'\xf4\xb6\x00\x00\x00\x00\x00(\xed\xe1\x80\x00\x00\x00\x00)Ԙ\x00\x00\x00\x00\x00*\xcdÀ\x00" + + "\x00\x00\x00+\xb4z\x00\x00\x00\x00\x00,\xad\xa5\x80\x00\x00\x00\x00-\x94\\\x00\x00\x00\x00\x00.\x8d\x87\x80\x00\x00\x00\x00/t>\x00\x00\x00\x00\x000mi\x80\x00\x00\x00\x001]Z\x80\x00\x00\x00\x002" + + "V\x86\x00\x00\x00\x00\x003=<\x80\x00\x00\x00\x0046h\x00\x00\x00\x00\x005\x1d\x1e\x80\x00\x00\x00\x006\x16J\x00\x00\x00\x00\x006\xfd\x00\x80\x00\x00\x00\x007\xf6,\x00\x00\x00\x00\x008\xdc\xe2\x80\x00" + + "\x00\x00\x009\xa7\xe9\x80\x00\x00\x00\x00:\xbcĀ\x00\x00\x00\x00;\xbf*\x80\x00\x00\x00\x00<\xa5\xe1\x00\x00\x00\x00\x00=\x9f\f\x80\x00\x00\x00\x00>\x85\xc3\x00\x00\x00\x00\x00?~\xee\x80\x00\x00\x00\x00@" + + "e\xa5\x00\x00\x00\x00\x00A^Ѐ\x00\x00\x00\x00BE\x87\x00\x00\x00\x00\x00C>\xb2\x80\x00\x00\x00\x00D.\xa3\x80\x00\x00\x00\x00E\x1e\x94\x80\x00\x00\x00\x00F\x05K\x00\x00\x00\x00\x00G\a\xb1\x00\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00\x8a\x1c\x00\x00\x00\x00\x9a\xb0\x01\x04\x00\x00\x8c\xa0\x00\tLMT\x00AEDT\x00" + + "AEST\x00\nAEST-10AEDT,M10.1.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x9b\xe1\xc1\xa9\x88\x03\x00\x00\x88\x03\x00" + + "\x00\x13\x00\x1c\x00Australia/MelbourneUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00S\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xffs\x16\x85\x18\xff\xff\xff\xff\x9cN\u0080\xff\xff\xff\xff\x9c\xbc/\x00\xff\xff\xff\xff\xcbT\xb3\x00\xff" + + "\xff\xff\xff\xcb\xc7e\x80\xff\xff\xff\xff̷V\x80\xff\xff\xff\xffͧG\x80\xff\xff\xff\xffΠs\x00\xff\xff\xff\xffχ)\x80\x00\x00\x00\x00\x03p9\x80\x00\x00\x00\x00\x04\r\x1c\x00\x00\x00\x00\x00\x05" + + "P\x1b\x80\x00\x00\x00\x00\x05\xf68\x80\x00\x00\x00\x00\a/\xfd\x80\x00\x00\x00\x00\a\xd6\x1a\x80\x00\x00\x00\x00\t\x0f߀\x00\x00\x00\x00\t\xb5\xfc\x80\x00\x00\x00\x00\n\xef\xc1\x80\x00\x00\x00\x00\v\x9f\x19\x00\x00" + + "\x00\x00\x00\f\xd8\xde\x00\x00\x00\x00\x00\r~\xfb\x00\x00\x00\x00\x00\x0e\xb8\xc0\x00\x00\x00\x00\x00\x0f^\xdd\x00\x00\x00\x00\x00\x10\x98\xa2\x00\x00\x00\x00\x00\x11>\xbf\x00\x00\x00\x00\x00\x12x\x84\x00\x00\x00\x00\x00\x13" + + "\x1e\xa1\x00\x00\x00\x00\x00\x14Xf\x00\x00\x00\x00\x00\x14\xfe\x83\x00\x00\x00\x00\x00\x168H\x00\x00\x00\x00\x00\x16矀\x00\x00\x00\x00\x18!d\x80\x00\x00\x00\x00\x18ǁ\x80\x00\x00\x00\x00\x1a\x01F\x80\x00" + + "\x00\x00\x00\x1a\xa7c\x80\x00\x00\x00\x00\x1b\xe1(\x80\x00\x00\x00\x00\x1c\x87E\x80\x00\x00\x00\x00\x1d\xc1\n\x80\x00\x00\x00\x00\x1ey\x9c\x80\x00\x00\x00\x00\x1f\x97\xb2\x00\x00\x00\x00\x00 Y~\x80\x00\x00\x00\x00!" + + "w\x94\x00\x00\x00\x00\x00\"B\x9b\x00\x00\x00\x00\x00#i\xeb\x00\x00\x00\x00\x00$\"}\x00\x00\x00\x00\x00%I\xcd\x00\x00\x00\x00\x00&\x02_\x00\x00\x00\x00\x00')\xaf\x00\x00\x00\x00\x00'\xcf\xcc\x00\x00" + + "\x00\x00\x00)\t\x91\x00\x00\x00\x00\x00)\xaf\xae\x00\x00\x00\x00\x00*\xe9s\x00\x00\x00\x00\x00+\x98ʀ\x00\x00\x00\x00,ҏ\x80\x00\x00\x00\x00-x\xac\x80\x00\x00\x00\x00.\xb2q\x80\x00\x00\x00\x00/" + + "t>\x00\x00\x00\x00\x000\x92S\x80\x00\x00\x00\x001]Z\x80\x00\x00\x00\x002r5\x80\x00\x00\x00\x003=<\x80\x00\x00\x00\x004R\x17\x80\x00\x00\x00\x005\x1d\x1e\x80\x00\x00\x00\x0061\xf9\x80\x00" + + "\x00\x00\x006\xfd\x00\x80\x00\x00\x00\x008\x1b\x16\x00\x00\x00\x00\x008\xdc\xe2\x80\x00\x00\x00\x009\xa7\xe9\x80\x00\x00\x00\x00:\xbcĀ\x00\x00\x00\x00;\xda\xda\x00\x00\x00\x00\x00<\xa5\xe1\x00\x00\x00\x00\x00=" + + "\xba\xbc\x00\x00\x00\x00\x00>\x85\xc3\x00\x00\x00\x00\x00?\x9a\x9e\x00\x00\x00\x00\x00@e\xa5\x00\x00\x00\x00\x00A\x83\xba\x80\x00\x00\x00\x00BE\x87\x00\x00\x00\x00\x00Cc\x9c\x80\x00\x00\x00\x00D.\xa3\x80\x00" + + "\x00\x00\x00EC~\x80\x00\x00\x00\x00F\x05K\x00\x00\x00\x00\x00G#`\x80\x00\x00\x00\x00G\xf7\xa2\x00\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\x87\xe8\x00\x00" + + "\x00\x00\x9a\xb0\x01\x04\x00\x00\x8c\xa0\x00\tLMT\x00AEDT\x00AEST\x00\nAEST-10AEDT,M10.1.0,M4.1.0/3\nPK\x03\x04" + + "\n\x00\x00\x00\x00\x00#\x82iSo3\xdaR\xb4\x02\x00\x00\xb4\x02\x00\x00\r\x00\x1c\x00Australia/LHIUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E" + + "\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + + "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x05\x00\x00\x00\x19\xff\xff\xff\xffs\x16w\xdc\x00\x00\x00\x00\x14\xfef\xe0\x00\x00" + + "\x00\x00\x168@\xf8\x00\x00\x00\x00\x16\xe7\x8ah\x00\x00\x00\x00\x18!]x\x00\x00\x00\x00\x18\xc7lh\x00\x00\x00\x00\x1a\x01?x\x00\x00\x00\x00\x1a\xa7Nh\x00\x00\x00\x00\x1b\xe1!x\x00\x00\x00\x00\x1c\x87" + + "0h\x00\x00\x00\x00\x1d\xc1\x03x\x00\x00\x00\x00\x1ey\x8ep\x00\x00\x00\x00\x1f\x97\xaa\xf8\x00\x00\x00\x00 Ypp\x00\x00\x00\x00!\x80\xc7x\x00\x00\x00\x00\"B\x8c\xf0\x00\x00\x00\x00#i\xe3\xf8\x00\x00" + + "\x00\x00$\"n\xf0\x00\x00\x00\x00%I\xc5\xf8\x00\x00\x00\x00%\xef\xdb\xf0\x00\x00\x00\x00')\xa7\xf8\x00\x00\x00\x00'Ͻ\xf0\x00\x00\x00\x00)\t\x89\xf8\x00\x00\x00\x00)\xaf\x9f\xf0\x00\x00\x00\x00*\xe9" + + "k\xf8\x00\x00\x00\x00+\x98\xbcp\x00\x00\x00\x00,҈x\x00\x00\x00\x00-x\x9ep\x00\x00\x00\x00.\xb2jx\x00\x00\x00\x00/X\x80p\x00\x00\x00\x000\x92Lx\x00\x00\x00\x001]Lp\x00\x00" + + "\x00\x002r.x\x00\x00\x00\x003=.p\x00\x00\x00\x004R\x10x\x00\x00\x00\x005\x1d\x10p\x00\x00\x00\x0061\xf2x\x00\x00\x00\x006\xfc\xf2p\x00\x00\x00\x008\x1b\x0e\xf8\x00\x00\x00\x008\xdc" + + "\xd4p\x00\x00\x00\x009\xa7\xe2x\x00\x00\x00\x00:\xbc\xb6p\x00\x00\x00\x00;\xda\xd2\xf8\x00\x00\x00\x00<\xa5\xd2\xf0\x00\x00\x00\x00=\xba\xb4\xf8\x00\x00\x00\x00>\x85\xb4\xf0\x00\x00\x00\x00?\x9a\x96\xf8\x00\x00" + + "\x00\x00@e\x96\xf0\x00\x00\x00\x00A\x83\xb3x\x00\x00\x00\x00BEx\xf0\x00\x00\x00\x00Cc\x95x\x00\x00\x00\x00D.\x95p\x00\x00\x00\x00ECwx\x00\x00\x00\x00F\x05<\xf0\x00\x00\x00\x00G#" + + "Yx\x00\x00\x00\x00G\xf7\x93\xf0\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03" + + "\x04\x03\x04\x03\x04\x03\x00\x00\x95$\x00\x00\x00\x00\x8c\xa0\x00\x04\x00\x00\xa1\xb8\x01\t\x00\x00\x93\xa8\x00\x0f\x00\x00\x9a\xb0\x01\x15LMT\x00AEST\x00+1130\x00+1030\x00+11" + + "\x00\n<+1030>-10:30<+11>-11,M10.1.0,M4.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSX\xb9\x9ap\x88\x03\x00" + + "\x00\x88\x03\x00\x00\r\x00\x1c\x00Australia/NSWUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00S\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xffs\x16\u007f<\xff\xff\xff\xff\x9cN\u0080\xff\xff\xff\xff\x9c\xbc/\x00\xff\xff\xff\xff\xcbT\xb3\x00\xff\xff\xff" + + "\xff\xcb\xc7e\x80\xff\xff\xff\xff̷V\x80\xff\xff\xff\xffͧG\x80\xff\xff\xff\xffΠs\x00\xff\xff\xff\xffχ)\x80\x00\x00\x00\x00\x03p9\x80\x00\x00\x00\x00\x04\r\x1c\x00\x00\x00\x00\x00\x05P\x1b" + + "\x80\x00\x00\x00\x00\x05\xf68\x80\x00\x00\x00\x00\a/\xfd\x80\x00\x00\x00\x00\a\xd6\x1a\x80\x00\x00\x00\x00\t\x0f߀\x00\x00\x00\x00\t\xb5\xfc\x80\x00\x00\x00\x00\n\xef\xc1\x80\x00\x00\x00\x00\v\x9f\x19\x00\x00\x00\x00" + + "\x00\f\xd8\xde\x00\x00\x00\x00\x00\r~\xfb\x00\x00\x00\x00\x00\x0e\xb8\xc0\x00\x00\x00\x00\x00\x0f^\xdd\x00\x00\x00\x00\x00\x10\x98\xa2\x00\x00\x00\x00\x00\x11>\xbf\x00\x00\x00\x00\x00\x12x\x84\x00\x00\x00\x00\x00\x13\x1e\xa1" + + "\x00\x00\x00\x00\x00\x14Xf\x00\x00\x00\x00\x00\x14\xfe\x83\x00\x00\x00\x00\x00\x168H\x00\x00\x00\x00\x00\x17\f\x89\x80\x00\x00\x00\x00\x18!d\x80\x00\x00\x00\x00\x18ǁ\x80\x00\x00\x00\x00\x1a\x01F\x80\x00\x00\x00" + + "\x00\x1a\xa7c\x80\x00\x00\x00\x00\x1b\xe1(\x80\x00\x00\x00\x00\x1c\x87E\x80\x00\x00\x00\x00\x1d\xc1\n\x80\x00\x00\x00\x00\x1ey\x9c\x80\x00\x00\x00\x00\x1f\x97\xb2\x00\x00\x00\x00\x00 Y~\x80\x00\x00\x00\x00!\x80\xce" + + "\x80\x00\x00\x00\x00\"B\x9b\x00\x00\x00\x00\x00#i\xeb\x00\x00\x00\x00\x00$\"}\x00\x00\x00\x00\x00%I\xcd\x00\x00\x00\x00\x00%\xef\xea\x00\x00\x00\x00\x00')\xaf\x00\x00\x00\x00\x00'\xcf\xcc\x00\x00\x00\x00" + + "\x00)\t\x91\x00\x00\x00\x00\x00)\xaf\xae\x00\x00\x00\x00\x00*\xe9s\x00\x00\x00\x00\x00+\x98ʀ\x00\x00\x00\x00,ҏ\x80\x00\x00\x00\x00-x\xac\x80\x00\x00\x00\x00.\xb2q\x80\x00\x00\x00\x00/X\x8e" + + "\x80\x00\x00\x00\x000\x92S\x80\x00\x00\x00\x001]Z\x80\x00\x00\x00\x002r5\x80\x00\x00\x00\x003=<\x80\x00\x00\x00\x004R\x17\x80\x00\x00\x00\x005\x1d\x1e\x80\x00\x00\x00\x0061\xf9\x80\x00\x00\x00" + + "\x006\xfd\x00\x80\x00\x00\x00\x008\x1b\x16\x00\x00\x00\x00\x008\xdc\xe2\x80\x00\x00\x00\x009\xa7\xe9\x80\x00\x00\x00\x00:\xbcĀ\x00\x00\x00\x00;\xda\xda\x00\x00\x00\x00\x00<\xa5\xe1\x00\x00\x00\x00\x00=\xba\xbc" + + "\x00\x00\x00\x00\x00>\x85\xc3\x00\x00\x00\x00\x00?\x9a\x9e\x00\x00\x00\x00\x00@e\xa5\x00\x00\x00\x00\x00A\x83\xba\x80\x00\x00\x00\x00BE\x87\x00\x00\x00\x00\x00Cc\x9c\x80\x00\x00\x00\x00D.\xa3\x80\x00\x00\x00" + + "\x00EC~\x80\x00\x00\x00\x00F\x05K\x00\x00\x00\x00\x00G#`\x80\x00\x00\x00\x00G\xf7\xa2\x00\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\x8d\xc4\x00\x00\x00\x00" + + "\x9a\xb0\x01\x04\x00\x00\x8c\xa0\x00\tLMT\x00AEDT\x00AEST\x00\nAEST-10AEDT,M10.1.0,M4.1.0/3\nPK\x03\x04\n\x00" + + "\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x1c\x00Brazil/UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00P" + + "K\x03\x04\n\x00\x00\x00\x00\x00#\x82iSa\xcb'\xe9\x9c\x01\x00\x00\x9c\x01\x00\x00\v\x00\x1c\x00Brazil/WestUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14" + + "E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00T" + + "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96\xaa\u007fD\xff\xff\xff\xff\xb8\x0fW\xf0\xff" + + "\xff\xff\xff\xb8\xfdN\xb0\xff\xff\xff\xff\xb9\xf1B@\xff\xff\xff\xff\xbaނ0\xff\xff\xff\xff\xda8\xbc@\xff\xff\xff\xff\xda\xec\b@\xff\xff\xff\xff\xdc\x19\xef\xc0\xff\xff\xff\xffܹg0\xff\xff\xff\xff\xdd" + + "\xfb#@\xff\xff\xff\xffޛ\xec0\xff\xff\xff\xff\xdfݨ@\xff\xff\xff\xff\xe0TA0\xff\xff\xff\xff\xf4\x98\r\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf6\xc0r@\xff\xff\xff\xff\xf7\x0e,\xb0\xff" + + "\xff\xff\xff\xf8Q:@\xff\xff\xff\xff\xf8\xc7\xd30\xff\xff\xff\xff\xfa\n\xe0\xc0\xff\xff\xff\xff\xfa\xa9\x06\xb0\xff\xff\xff\xff\xfb\xec\x14@\xff\xff\xff\xff\xfc\x8b\x8b\xb0\x00\x00\x00\x00\x1dɜ@\x00\x00\x00\x00\x1e" + + "x\xe5\xb0\x00\x00\x00\x00\x1f\xa0C\xc0\x00\x00\x00\x00 3ݰ\x00\x00\x00\x00!\x81w@\x00\x00\x00\x00\"\vְ\x00\x00\x00\x00,\xc0\xc3@\x00\x00\x00\x00-f\xd20\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xffǼ\x00\x00\xff\xff\xd5\xd0\x01\x04\xff\xff\xc7\xc0\x00\bLMT\x00-03\x00-04\x00\n<-04>4\n" + + "PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb7-2f\xe4\x01\x00\x00\xe4\x01\x00\x00\x10\x00\x1c\x00Brazil/DeNoronhaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8bau" + + "x\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00" + + "\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96\xaaed\xff\xff\xff" + + "\xff\xb8\x0f;\xd0\xff\xff\xff\xff\xb8\xfd2\x90\xff\xff\xff\xff\xb9\xf1& \xff\xff\xff\xff\xba\xdef\x10\xff\xff\xff\xff\xda8\xa0 \xff\xff\xff\xff\xda\xeb\xec \xff\xff\xff\xff\xdc\x19Ӡ\xff\xff\xff\xffܹK" + + "\x10\xff\xff\xff\xff\xdd\xfb\a \xff\xff\xff\xffޛ\xd0\x10\xff\xff\xff\xff\xdf\u074c \xff\xff\xff\xff\xe0T%\x10\xff\xff\xff\xff\xf4\x97\xf1\xa0\xff\xff\xff\xff\xf5\x05P\x10\xff\xff\xff\xff\xf6\xc0V \xff\xff\xff" + + "\xff\xf7\x0e\x10\x90\xff\xff\xff\xff\xf8Q\x1e \xff\xff\xff\xff\xf8Ƿ\x10\xff\xff\xff\xff\xfa\nĠ\xff\xff\xff\xff\xfa\xa8\xea\x90\xff\xff\xff\xff\xfb\xeb\xf8 \xff\xff\xff\xff\xfc\x8bo\x90\x00\x00\x00\x00\x1dɀ" + + " \x00\x00\x00\x00\x1exɐ\x00\x00\x00\x00\x1f\xa0'\xa0\x00\x00\x00\x00 3\xc1\x90\x00\x00\x00\x00!\x81[ \x00\x00\x00\x00\"\v\xba\x90\x00\x00\x00\x00#X\x02\xa0\x00\x00\x00\x00#\xe2b\x10\x00\x00\x00" + + "\x00%7\xe4\xa0\x00\x00\x00\x00%Թ\x10\x00\x00\x00\x007\xf6\xb8\xa0\x00\x00\x00\x008\xb8w\x10\x00\x00\x00\x009\xdf\xd5 \x00\x00\x00\x009\xe9\x01\x90\x00\x00\x00\x00;\xc8\xf1\xa0\x00\x00\x00\x002\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSg\xf5K\x89\xa2\x01\x00\x00\xa2\x01\x00\x00\v\x00\x1c\x00Brazil/AcreU" + + "T\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x00\x00\x00\x04\x00\x00" + + "\x00\f\xff\xff\xff\xff\x96\xaa\x86\x90\xff\xff\xff\xff\xb8\x0ff\x00\xff\xff\xff\xff\xb8\xfd\\\xc0\xff\xff\xff\xff\xb9\xf1PP\xff\xff\xff\xff\xbaސ@\xff\xff\xff\xff\xda8\xcaP\xff\xff\xff\xff\xda\xec\x16P\xff\xff" + + "\xff\xff\xdc\x19\xfd\xd0\xff\xff\xff\xffܹu@\xff\xff\xff\xff\xdd\xfb1P\xff\xff\xff\xffޛ\xfa@\xff\xff\xff\xff\xdfݶP\xff\xff\xff\xff\xe0TO@\xff\xff\xff\xff\xf4\x98\x1b\xd0\xff\xff\xff\xff\xf5\x05" + + "z@\xff\xff\xff\xff\xf6\xc0\x80P\xff\xff\xff\xff\xf7\x0e:\xc0\xff\xff\xff\xff\xf8QHP\xff\xff\xff\xff\xf8\xc7\xe1@\xff\xff\xff\xff\xfa\n\xee\xd0\xff\xff\xff\xff\xfa\xa9\x14\xc0\xff\xff\xff\xff\xfb\xec\"P\xff\xff" + + "\xff\xff\xfc\x8b\x99\xc0\x00\x00\x00\x00\x1dɪP\x00\x00\x00\x00\x1ex\xf3\xc0\x00\x00\x00\x00\x1f\xa0Q\xd0\x00\x00\x00\x00 3\xeb\xc0\x00\x00\x00\x00!\x81\x85P\x00\x00\x00\x00\"\v\xe4\xc0\x00\x00\x00\x00H`" + + "\u007fP\x00\x00\x00\x00R\u007f\x04\xc0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x02\xff\xff\xc0p\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff\xb9\xb0\x00\b\xff" + + "\xff\xc7\xc0\x00\x04LMT\x00-04\x00-05\x00\n<-05>5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x9d?\xdfڸ\x03\x00\x00\xb8\x03\x00\x00\v\x00\x1c\x00Brazi" + + "l/EastUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "[\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96\xaar\xb4\xff\xff\xff\xff\xb8\x0fI\xe0\xff\xff\xff\xff\xb8\xfd@\xa0\xff\xff\xff\xff\xb9\xf140\xff\xff\xff\xff\xba\xdet \xff\xff\xff\xff\xda8\xae0\xff\xff\xff" + + "\xff\xda\xeb\xfa0\xff\xff\xff\xff\xdc\x19\xe1\xb0\xff\xff\xff\xffܹY \xff\xff\xff\xff\xdd\xfb\x150\xff\xff\xff\xffޛ\xde \xff\xff\xff\xff\xdfݚ0\xff\xff\xff\xff\xe0T3 \xff\xff\xff\xff\xf4Z\t" + + "0\xff\xff\xff\xff\xf5\x05^ \xff\xff\xff\xff\xf6\xc0d0\xff\xff\xff\xff\xf7\x0e\x1e\xa0\xff\xff\xff\xff\xf8Q,0\xff\xff\xff\xff\xf8\xc7\xc5 \xff\xff\xff\xff\xfa\nҰ\xff\xff\xff\xff\xfa\xa8\xf8\xa0\xff\xff\xff" + + "\xff\xfb\xec\x060\xff\xff\xff\xff\xfc\x8b}\xa0\x00\x00\x00\x00\x1dɎ0\x00\x00\x00\x00\x1exנ\x00\x00\x00\x00\x1f\xa05\xb0\x00\x00\x00\x00 3Ϡ\x00\x00\x00\x00!\x81i0\x00\x00\x00\x00\"\v\xc8" + + "\xa0\x00\x00\x00\x00#X\x10\xb0\x00\x00\x00\x00#\xe2p \x00\x00\x00\x00%7\xf2\xb0\x00\x00\x00\x00%\xd4\xc7 \x00\x00\x00\x00'!\x0f0\x00\x00\x00\x00'\xbd\xe3\xa0\x00\x00\x00\x00)\x00\xf10\x00\x00\x00" + + "\x00)\x94\x8b \x00\x00\x00\x00*\xea\r\xb0\x00\x00\x00\x00+k2\xa0\x00\x00\x00\x00,\xc0\xb50\x00\x00\x00\x00-f\xc4 \x00\x00\x00\x00.\xa0\x970\x00\x00\x00\x00/F\xa6 \x00\x00\x00\x000\x80y" + + "0\x00\x00\x00\x001\x1dM\xa0\x00\x00\x00\x002W \xb0\x00\x00\x00\x003\x06j \x00\x00\x00\x0048T0\x00\x00\x00\x004\xf8\xc1 \x00\x00\x00\x006 \x1f0\x00\x00\x00\x006\xcfh\xa0\x00\x00\x00" + + "\x007\xf6ư\x00\x00\x00\x008\xb8\x85 \x00\x00\x00\x009\xdf\xe30\x00\x00\x00\x00:\x8f,\xa0\x00\x00\x00\x00;\xc8\xff\xb0\x00\x00\x00\x00N\xf0" + + "\xa0\x00\x00\x00\x00?\x91\xfe0\x00\x00\x00\x00@.Ҡ\x00\x00\x00\x00A\x86\xf80\x00\x00\x00\x00B\x17\xef \x00\x00\x00\x00CQ\xc20\x00\x00\x00\x00C\xf7\xd1 \x00\x00\x00\x00EMS\xb0\x00\x00\x00" + + "\x00E\xe0\xed\xa0\x00\x00\x00\x00G\x11\x860\x00\x00\x00\x00G\xb7\x95 \x00\x00\x00\x00H\xfa\xa2\xb0\x00\x00\x00\x00I\x97w \x00\x00\x00\x00Jڄ\xb0\x00\x00\x00\x00K\x80\x93\xa0\x00\x00\x00\x00L\xbaf" + + "\xb0\x00\x00\x00\x00M`u\xa0\x00\x00\x00\x00N\x9aH\xb0\x00\x00\x00\x00OI\x92 \x00\x00\x00\x00P\x83e0\x00\x00\x00\x00Q 9\xa0\x00\x00\x00\x00RcG0\x00\x00\x00\x00S\x00\x1b\xa0\x00\x00\x00" + + "\x00TC)0\x00\x00\x00\x00T\xe98 \x00\x00\x00\x00V#\v0\x00\x00\x00\x00V\xc9\x1a \x00\x00\x00\x00X\x02\xed0\x00\x00\x00\x00X\xa8\xfc \x00\x00\x00\x00Y\xe2\xcf0\x00\x00\x00\x00Z\x88\xde" + + " \x00\x00\x00\x00[\xde`\xb0\x00\x00\x00\x00\\h\xc0 \x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xff\xd4L\x00\x00\xff\xff\xe3\xe0\x01\x04" + + "\xff\xff\xd5\xd0\x00\bLMT\x00-02\x00-03\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x1c\x00Cana" + + "da/UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS{\a\a\xdc\xca\x03\x00\x00\xca\x03\x00\x00\x0f\x00\x1c" + + "\x00Canada/MountainUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96\xaaed\xff\xff\xff\xff\xb8\x0f;\xd0\xff\xff\xff\xff\xb8\xfd2\x90\xff\xff\xff\xff\xb9\xf1& \xff\xff\xff\xff\xba\xdef\x10\xff" + - "\xff\xff\xff\xda8\xa0 \xff\xff\xff\xff\xda\xeb\xec \xff\xff\xff\xff\xdc\x19Ӡ\xff\xff\xff\xffܹK\x10\xff\xff\xff\xff\xdd\xfb\a \xff\xff\xff\xffޛ\xd0\x10\xff\xff\xff\xff\xdf\u074c \xff\xff\xff\xff\xe0" + - "T%\x10\xff\xff\xff\xff\xf4\x97\xf1\xa0\xff\xff\xff\xff\xf5\x05P\x10\xff\xff\xff\xff\xf6\xc0V \xff\xff\xff\xff\xf7\x0e\x10\x90\xff\xff\xff\xff\xf8Q\x1e \xff\xff\xff\xff\xf8Ƿ\x10\xff\xff\xff\xff\xfa\nĠ\xff" + - "\xff\xff\xff\xfa\xa8\xea\x90\xff\xff\xff\xff\xfb\xeb\xf8 \xff\xff\xff\xff\xfc\x8bo\x90\x00\x00\x00\x00\x1dɀ \x00\x00\x00\x00\x1exɐ\x00\x00\x00\x00\x1f\xa0'\xa0\x00\x00\x00\x00 3\xc1\x90\x00\x00\x00\x00!" + - "\x81[ \x00\x00\x00\x00\"\v\xba\x90\x00\x00\x00\x00#X\x02\xa0\x00\x00\x00\x00#\xe2b\x10\x00\x00\x00\x00%7\xe4\xa0\x00\x00\x00\x00%Թ\x10\x00\x00\x00\x007\xf6\xb8\xa0\x00\x00\x00\x008\xb8w\x10\x00" + - "\x00\x00\x009\xdf\xd5 \x00\x00\x00\x009\xe9\x01\x90\x00\x00\x00\x00;\xc8\xf1\xa0\x00\x00\x00\x002\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c" + - "9Ra\xcb'\xe9\x9c\x01\x00\x00\x9c\x01\x00\x00\v\x00\x1c\x00Brazil/WestUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZi" + - "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x96\xaa\u007fD\xff\xff\xff\xff\xb8\x0fW\xf0\xff\xff\xff\xff\xb8\xfdN\xb0\xff\xff\xff\xff" + - "\xb9\xf1B@\xff\xff\xff\xff\xbaނ0\xff\xff\xff\xff\xda8\xbc@\xff\xff\xff\xff\xda\xec\b@\xff\xff\xff\xff\xdc\x19\xef\xc0\xff\xff\xff\xffܹg0\xff\xff\xff\xff\xdd\xfb#@\xff\xff\xff\xffޛ\xec0" + - "\xff\xff\xff\xff\xdfݨ@\xff\xff\xff\xff\xe0TA0\xff\xff\xff\xff\xf4\x98\r\xc0\xff\xff\xff\xff\xf5\x05l0\xff\xff\xff\xff\xf6\xc0r@\xff\xff\xff\xff\xf7\x0e,\xb0\xff\xff\xff\xff\xf8Q:@\xff\xff\xff\xff" + - "\xf8\xc7\xd30\xff\xff\xff\xff\xfa\n\xe0\xc0\xff\xff\xff\xff\xfa\xa9\x06\xb0\xff\xff\xff\xff\xfb\xec\x14@\xff\xff\xff\xff\xfc\x8b\x8b\xb0\x00\x00\x00\x00\x1dɜ@\x00\x00\x00\x00\x1ex\xe5\xb0\x00\x00\x00\x00\x1f\xa0C\xc0" + - "\x00\x00\x00\x00 3ݰ\x00\x00\x00\x00!\x81w@\x00\x00\x00\x00\"\vְ\x00\x00\x00\x00,\xc0\xc3@\x00\x00\x00\x00-f\xd20\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\xff\xffǼ\x00\x00\xff\xff\xd5\xd0\x01\x04\xff\xff\xc7\xc0\x00\bLMT\x00-03\x00-04\x00\n<-04>4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1" + - "c9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x1c\x00Canada/UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x03\x04\n\x00" + - "\x00\x00\x00\x00\xf1c9RU9#\xbe2\x05\x00\x002\x05\x00\x00\x0e\x00\x1c\x00Canada/PacificUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00" + - "\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZi" + - "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x81\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff^=v\xec\xff\xff\xff\xff\x9e\xb8\xbd\xa0\xff\xff\xff" + - "\xff\x9f\xbb\x15\x90\xff\xff\xff\xffˉ\x1a\xa0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a&\x10\xff\xff\xff\xff\xd3v\x0f \xff\xff\xff\xff\xd4A\b\x10\xff\xff\xff\xff\xd5U\xf1 \xff\xff\xff\xff\xd6 \xea" + - "\x10\xff\xff\xff\xff\xd75\xd3 \xff\xff\xff\xff\xd8\x00\xcc\x10\xff\xff\xff\xff\xd9\x15\xb5 \xff\xff\xff\xff\xd9\xe0\xae\x10\xff\xff\xff\xff\xda\xfeѠ\xff\xff\xff\xff\xdb\xc0\x90\x10\xff\xff\xff\xff\xdc\u07b3\xa0\xff\xff\xff" + - "\xffݩ\xac\x90\xff\xff\xff\xff\u07be\x95\xa0\xff\xff\xff\xff߉\x8e\x90\xff\xff\xff\xff\xe0\x9ew\xa0\xff\xff\xff\xff\xe1ip\x90\xff\xff\xff\xff\xe2~Y\xa0\xff\xff\xff\xff\xe3IR\x90\xff\xff\xff\xff\xe4^;" + - "\xa0\xff\xff\xff\xff\xe5)4\x90\xff\xff\xff\xff\xe6GX \xff\xff\xff\xff\xe7\x12Q\x10\xff\xff\xff\xff\xe8': \xff\xff\xff\xff\xe8\xf23\x10\xff\xff\xff\xff\xea\a\x1c \xff\xff\xff\xff\xea\xd2\x15\x10\xff\xff\xff" + - "\xff\xeb\xe6\xfe \xff\xff\xff\xff\xec\xb1\xf7\x10\xff\xff\xff\xff\xed\xc6\xe0 \xff\xff\xff\xff\xee\x91\xd9\x10\xff\xff\xff\xff\xef\xaf\xfc\xa0\xff\xff\xff\xff\xf0q\xbb\x10\xff\xff\xff\xff\xf1\x8fޠ\xff\xff\xff\xff\xf2\u007f\xc1" + - "\x90\xff\xff\xff\xff\xf3o\xc0\xa0\xff\xff\xff\xff\xf4_\xa3\x90\xff\xff\xff\xff\xf5O\xa2\xa0\xff\xff\xff\xff\xf6?\x85\x90\xff\xff\xff\xff\xf7/\x84\xa0\xff\xff\xff\xff\xf8(\xa2\x10\xff\xff\xff\xff\xf9\x0ff\xa0\xff\xff\xff" + - "\xff\xfa\b\x84\x10\xff\xff\xff\xff\xfa\xf8\x83 \xff\xff\xff\xff\xfb\xe8f\x10\xff\xff\xff\xff\xfc\xd8e \xff\xff\xff\xff\xfd\xc8H\x10\xff\xff\xff\xff\xfe\xb8G \xff\xff\xff\xff\xff\xa8*\x10\x00\x00\x00\x00\x00\x98)" + - " \x00\x00\x00\x00\x01\x88\f\x10\x00\x00\x00\x00\x02x\v \x00\x00\x00\x00\x03q(\x90\x00\x00\x00\x00\x04a'\xa0\x00\x00\x00\x00\x05Q\n\x90\x00\x00\x00\x00\x06A\t\xa0\x00\x00\x00\x00\a0\xec\x90\x00\x00\x00" + - "\x00\b \xeb\xa0\x00\x00\x00\x00\t\x10ΐ\x00\x00\x00\x00\n\x00͠\x00\x00\x00\x00\n\xf0\xb0\x90\x00\x00\x00\x00\v\u0be0\x00\x00\x00\x00\f\xd9\xcd\x10\x00\x00\x00\x00\r\xc0\x91\xa0\x00\x00\x00\x00\x0e\xb9\xaf" + - "\x10\x00\x00\x00\x00\x0f\xa9\xae \x00\x00\x00\x00\x10\x99\x91\x10\x00\x00\x00\x00\x11\x89\x90 \x00\x00\x00\x00\x12ys\x10\x00\x00\x00\x00\x13ir \x00\x00\x00\x00\x14YU\x10\x00\x00\x00\x00\x15IT \x00\x00\x00" + - "\x00\x1697\x10\x00\x00\x00\x00\x17)6 \x00\x00\x00\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18 \x00\x00\x00\x00\x1a\x025\x90\x00\x00\x00\x00\x1a\xf24\xa0\x00\x00\x00\x00\x1b\xe2\x17\x90\x00\x00\x00\x00\x1c\xd2\x16" + - "\xa0\x00\x00\x00\x00\x1d\xc1\xf9\x90\x00\x00\x00\x00\x1e\xb1\xf8\xa0\x00\x00\x00\x00\x1f\xa1ې\x00\x00\x00\x00 v+ \x00\x00\x00\x00!\x81\xbd\x90\x00\x00\x00\x00\"V\r \x00\x00\x00\x00#j\xda\x10\x00\x00\x00" + - "\x00$5\xef \x00\x00\x00\x00%J\xbc\x10\x00\x00\x00\x00&\x15\xd1 \x00\x00\x00\x00'*\x9e\x10\x00\x00\x00\x00'\xfe\xed\xa0\x00\x00\x00\x00)\n\x80\x10\x00\x00\x00\x00)\xdeϠ\x00\x00\x00\x00*\xeab" + - "\x10\x00\x00\x00\x00+\xbe\xb1\xa0\x00\x00\x00\x00,\xd3~\x90\x00\x00\x00\x00-\x9e\x93\xa0\x00\x00\x00\x00.\xb3`\x90\x00\x00\x00\x00/~u\xa0\x00\x00\x00\x000\x93B\x90\x00\x00\x00\x001g\x92 \x00\x00\x00" + - "\x002s$\x90\x00\x00\x00\x003Gt \x00\x00\x00\x004S\x06\x90\x00\x00\x00\x005'V \x00\x00\x00\x0062\xe8\x90\x00\x00\x00\x007\a8 \x00\x00\x00\x008\x1c\x05\x10\x00\x00\x00\x008\xe7\x1a" + - " \x00\x00\x00\x009\xfb\xe7\x10\x00\x00\x00\x00:\xc6\xfc \x00\x00\x00\x00;\xdb\xc9\x10\x00\x00\x00\x00<\xb0\x18\xa0\x00\x00\x00\x00=\xbb\xab\x10\x00\x00\x00\x00>\x8f\xfa\xa0\x00\x00\x00\x00?\x9b\x8d\x10\x00\x00\x00" + - "\x00@oܠ\x00\x00\x00\x00A\x84\xa9\x90\x00\x00\x00\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b\x90\x00\x00\x00\x00D/\xa0\xa0\x00\x00\x00\x00EDm\x90\x00\x00\x00\x00E\xf3\xd3 \x02\x01\x02\x03\x04\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\xff\xff\x8c\x94\x00\x00\xff\xff\x9d\x90\x01\x04\xff\xff\x8f\x80\x00\b\xff\xff\x9d\x90\x01\f\xff\xff\x9d\x90\x01\x10LMT\x00PDT\x00PST\x00PWT\x00PPT\x00\nPST8PDT" + - ",M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R?_p\x99\x0e\x05\x00\x00\x0e\x05\x00\x00\x0e\x00\x1c\x00Canada/Central" + - "UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00}\x00\x00\x00\x05\x00" + - "\x00\x00\x14\xff\xff\xff\xffd䰔\xff\xff\xff\xff\x9b\x01\xfb\xe0\xff\xff\xff\xff\x9búP\xff\xff\xff\xff\x9e\xb8\xa1\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\u00a0;\x80\xff\xff\xff\xff\xc3O\x84\xf0\xff" + - "\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xffӈh\x00\xff\xff\xff\xff\xd4S`\xf0\xff\xff\xff\xff\xd5U\xd5\x00\xff\xff\xff\xff\xd6 \xcd\xf0\xff\xff\xff\xff\xd7" + - "5\xb7\x00\xff\xff\xff\xff\xd8\x00\xaf\xf0\xff\xff\xff\xff\xd9\x15\x99\x00\xff\xff\xff\xff\xd9\xe0\x91\xf0\xff\xff\xff\xff\xdb\x00\a\x00\xff\xff\xff\xff\xdb\xc8\\\xf0\xff\xff\xff\xff\xdcޗ\x80\xff\xff\xff\xffݩ\x90p\xff" + - "\xff\xff\xff\u07bey\x80\xff\xff\xff\xff߉rp\xff\xff\xff\xff\xe0\x9e[\x80\xff\xff\xff\xff\xe1iTp\xff\xff\xff\xff\xe2~=\x80\xff\xff\xff\xff\xe3I6p\xff\xff\xff\xff\xe4^\x1f\x80\xff\xff\xff\xff\xe5" + - ")\x18p\xff\xff\xff\xff\xe6G<\x00\xff\xff\xff\xff\xe7\x124\xf0\xff\xff\xff\xff\xe8'\x1e\x00\xff\xff\xff\xff\xe8\xf2\x16\xf0\xff\xff\xff\xff\xea\a\x00\x00\xff\xff\xff\xff\xea\xd1\xf8\xf0\xff\xff\xff\xff\xeb\xe6\xe2\x00\xff" + - "\xff\xff\xff\xec\xd6\xc4\xf0\xff\xff\xff\xff\xed\xc6\xc4\x00\xff\xff\xff\xff\ue47c\xf0\xff\xff\xff\xff\xf3o\xa4\x80\xff\xff\xff\xff\xf41b\xf0\xff\xff\xff\xff\xf9\x0fJ\x80\xff\xff\xff\xff\xfa\bv\x00\xff\xff\xff\xff\xfa" + - "\xf8g\x00\xff\xff\xff\xff\xfb\xe8X\x00\xff\xff\xff\xff\xfc\xd8I\x00\xff\xff\xff\xff\xfd\xc8:\x00\xff\xff\xff\xff\xfe\xb8+\x00\xff\xff\xff\xff\xff\xa8\x1c\x00\x00\x00\x00\x00\x00\x98\r\x00\x00\x00\x00\x00\x01\x87\xfe\x00\x00" + - "\x00\x00\x00\x02w\xef\x00\x00\x00\x00\x00\x03q\x1a\x80\x00\x00\x00\x00\x04a\v\x80\x00\x00\x00\x00\x05P\xfc\x80\x00\x00\x00\x00\x06@\xed\x80\x00\x00\x00\x00\a0ހ\x00\x00\x00\x00\b π\x00\x00\x00\x00\t" + - "\x10\xc0\x80\x00\x00\x00\x00\n\x00\xb1\x80\x00\x00\x00\x00\n\xf0\xa2\x80\x00\x00\x00\x00\v\xe0\x93\x80\x00\x00\x00\x00\fٿ\x00\x00\x00\x00\x00\r\xc0u\x80\x00\x00\x00\x00\x0e\xb9\xa1\x00\x00\x00\x00\x00\x0f\xa9\x92\x00\x00" + - "\x00\x00\x00\x10\x99\x83\x00\x00\x00\x00\x00\x11\x89t\x00\x00\x00\x00\x00\x12ye\x00\x00\x00\x00\x00\x13iV\x00\x00\x00\x00\x00\x14YG\x00\x00\x00\x00\x00\x15I8\x00\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17" + - ")\x1a\x00\x00\x00\x00\x00\x18\"E\x80\x00\x00\x00\x00\x19\b\xfc\x00\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2\x18\x80\x00\x00\x00\x00\x1b\xe2\t\x80\x00\x00\x00\x00\x1c\xd1\xfa\x80\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00" + - "\x00\x00\x00\x1e\xb1܀\x00\x00\x00\x00\x1f\xa1̀\x00\x00\x00\x00 v\x0f\x00\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xf1\x00\x00\x00\x00\x00#j\xcc\x00\x00\x00\x00\x00$5\xd3\x00\x00\x00\x00\x00%" + - "J\xae\x00\x00\x00\x00\x00&\x15\xb5\x00\x00\x00\x00\x00'*\x90\x00\x00\x00\x00\x00'\xfeр\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\u07b3\x80\x00\x00\x00\x00*\xeaT\x00\x00\x00\x00\x00+\xbe\x95\x80\x00" + - "\x00\x00\x00,\xd3p\x80\x00\x00\x00\x00-\x9ew\x80\x00\x00\x00\x00.\xb3R\x80\x00\x00\x00\x00/~Y\x80\x00\x00\x00\x000\x934\x80\x00\x00\x00\x001gv\x00\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003" + - "GX\x00\x00\x00\x00\x004R\xf8\x80\x00\x00\x00\x005':\x00\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a\x1c\x00\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xd9\x00\x00" + - "\x00\x00\x00:\xc6\xe0\x00\x00\x00\x00\x00;ۻ\x00\x00\x00\x00\x00<\xaf\xfc\x80\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8fހ\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@o\xc0\x80\x00\x00\x00\x00A" + - "\x84\x9b\x80\x00\x00\x00\x00BO\xa2\x80\x00\x00\x00\x00Cd}\x80\x00\x00\x00\x00D/\x84\x80\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7\x00\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Y\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\x88\xde\xce\xe0\xff\xff\xff\xff\x9e\xb8\xaf\x90\xff\xff\xff\xff\x9f\xbb\a\x80\xff\xff\xff\xff\xa0\x98\x91\x90\xff\xff\xff\xff\xa0҅\x80\xff" + + "\xff\xff\xff\xa2\x8a\xe8\x90\xff\xff\xff\xff\xa3\x84\x06\x00\xff\xff\xff\xff\xa4jʐ\xff\xff\xff\xff\xa55À\xff\xff\xff\xff\xa6S\xe7\x10\xff\xff\xff\xff\xa7\x15\xa5\x80\xff\xff\xff\xff\xa83\xc9\x10\xff\xff\xff\xff\xa8" + + "\xfe\xc2\x00\xff\xff\xff\xffˉ\f\x90\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff\xd5U\xe3\x10\xff\xff\xff\xff\xd6 \xdc\x00\x00\x00\x00\x00\x04a\x19\x90\x00\x00\x00\x00\x05P\xfc\x80\x00" + + "\x00\x00\x00\x06@\xfb\x90\x00\x00\x00\x00\a0ހ\x00\x00\x00\x00\b ݐ\x00\x00\x00\x00\t\x10\xc0\x80\x00\x00\x00\x00\n\x00\xbf\x90\x00\x00\x00\x00\n\xf0\xa2\x80\x00\x00\x00\x00\vࡐ\x00\x00\x00\x00\f" + + "ٿ\x00\x00\x00\x00\x00\r\xc0\x83\x90\x00\x00\x00\x00\x0e\xb9\xa1\x00\x00\x00\x00\x00\x0f\xa9\xa0\x10\x00\x00\x00\x00\x10\x99\x83\x00\x00\x00\x00\x00\x11\x89\x82\x10\x00\x00\x00\x00\x12ye\x00\x00\x00\x00\x00\x13id\x10\x00" + + "\x00\x00\x00\x14YG\x00\x00\x00\x00\x00\x15IF\x10\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17)(\x10\x00\x00\x00\x00\x18\"E\x80\x00\x00\x00\x00\x19\t\n\x10\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a" + + "\xf2&\x90\x00\x00\x00\x00\x1b\xe2\t\x80\x00\x00\x00\x00\x1c\xd2\b\x90\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1\xea\x90\x00\x00\x00\x00\x1f\xa1̀\x00\x00\x00\x00 v\x1d\x10\x00\x00\x00\x00!\x81\xaf\x80\x00" + + "\x00\x00\x00\"U\xff\x10\x00\x00\x00\x00#j\xcc\x00\x00\x00\x00\x00$5\xe1\x10\x00\x00\x00\x00%J\xae\x00\x00\x00\x00\x00&\x15\xc3\x10\x00\x00\x00\x00'*\x90\x00\x00\x00\x00\x00'\xfeߐ\x00\x00\x00\x00)" + + "\nr\x00\x00\x00\x00\x00)\xde\xc1\x90\x00\x00\x00\x00*\xeaT\x00\x00\x00\x00\x00+\xbe\xa3\x90\x00\x00\x00\x00,\xd3p\x80\x00\x00\x00\x00-\x9e\x85\x90\x00\x00\x00\x00.\xb3R\x80\x00\x00\x00\x00/~g\x90\x00" + + "\x00\x00\x000\x934\x80\x00\x00\x00\x001g\x84\x10\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003Gf\x10\x00\x00\x00\x004R\xf8\x80\x00\x00\x00\x005'H\x10\x00\x00\x00\x0062ڀ\x00\x00\x00\x007" + + "\a*\x10\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe7\f\x10\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xc6\xee\x10\x00\x00\x00\x00;ۻ\x00\x00\x00\x00\x00<\xb0\n\x90\x00\x00\x00\x00=\xbb\x9d\x00\x00" + + "\x00\x00\x00>\x8f\xec\x90\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@oΐ\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00BO\xb0\x90\x00\x00\x00\x00Cd}\x80\x00\x00\x00\x00D/\x92\x90\x00\x00\x00\x00E" + + "D_\x80\x00\x00\x00\x00E\xf3\xc5\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\x95\xa0\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff" + + "\xab\xa0\x01\f\xff\xff\xab\xa0\x01\x10LMT\x00MDT\x00MST\x00MWT\x00MPT\x00\nMST7MDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00" + + "\x00\x00\x00\x00#\x82iS~\xb2\x0e\x19V\a\x00\x00V\a\x00\x00\x13\x00\x1c\x00Canada/NewfoundlandUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00" + + "\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00" + + "\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbb\x00\x00\x00\b\x00\x00\x00\x19\xff\xff\xff\xff^=4\xec\xff\xff\xff\xff\x9c\xcf" + + "b\f\xff\xff\xff\xff\x9d\xa4\xe6\xfc\xff\xff\xff\xff\x9e\xb8~\x8c\xff\xff\xff\xff\x9f\xba\xd6|\xff\xff\xff\xff\xa0\xb6\x88\xdc\xff\xff\xff\xff\xa18\xffL\xff\xff\xff\xff\xa2\x95\x19\\\xff\xff\xff\xff\xa3\x84\xfcL\xff\xff" + + "\xff\xff\xa4t\xfb\\\xff\xff\xff\xff\xa5d\xdeL\xff\xff\xff\xff\xa6^\x17\xdc\xff\xff\xff\xff\xa7D\xc0L\xff\xff\xff\xff\xa8=\xf9\xdc\xff\xff\xff\xff\xa9$\xa2L\xff\xff\xff\xff\xaa\x1d\xdb\xdc\xff\xff\xff\xff\xab\x04" + + "\x84L\xff\xff\xff\xff\xab\xfd\xbd\xdc\xff\xff\xff\xff\xac\xe4fL\xff\xff\xff\xff\xadݟ\xdc\xff\xff\xff\xff\xae͂\xcc\xff\xff\xff\xff\xaf\xbd\x81\xdc\xff\xff\xff\xff\xb0\xadd\xcc\xff\xff\xff\xff\xb1\xa6\x9e\\\xff\xff" + + "\xff\xff\xb2\x8dF\xcc\xff\xff\xff\xff\xb3\x86\x80\\\xff\xff\xff\xff\xb4m(\xcc\xff\xff\xff\xff\xb5fb\\\xff\xff\xff\xff\xb6M\n\xcc\xff\xff\xff\xff\xb7FD\\\xff\xff\xff\xff\xb8,\xec\xcc\xff\xff\xff\xff\xb9&" + + "&\\\xff\xff\xff\xff\xba\x16\tL\xff\xff\xff\xff\xbb\x0fB\xdc\xff\xff\xff\xff\xbb\xf5\xebL\xff\xff\xff\xff\xbc\xef$\xdc\xff\xff\xff\xff\xbd\xd5\xcdL\xff\xff\xff\xff\xbe\x9eMl\xff\xff\xff\xff\xbe\xcf\x06\xa8\xff\xff" + + "\xff\xff\xbf\xb5\xaf\x18\xff\xff\xff\xff\xc0\xb818\xff\xff\xff\xff\xc1y\xef\xa8\xff\xff\xff\xff\u0098\x138\xff\xff\xff\xff\xc3YѨ\xff\xff\xff\xff\xc4w\xf58\xff\xff\xff\xff\xc59\xb3\xa8\xff\xff\xff\xff\xc6a" + + "\x11\xb8\xff\xff\xff\xff\xc7\x19\x95\xa8\xff\xff\xff\xff\xc8@\xf3\xb8\xff\xff\xff\xff\xc9\x02\xb2(\xff\xff\xff\xff\xca ո\xff\xff\xff\xff\xca\xe2\x94(\xff\xff\xff\xff\xcc\x00\xb7\xb8\xff\xff\xff\xff\xd2#\xf4p\xff\xff" + + "\xff\xff\xd2`\xe6\xc8\xff\xff\xff\xffӈD\xd8\xff\xff\xff\xff\xd4J\x03H\xff\xff\xff\xff\xd5h&\xd8\xff\xff\xff\xff\xd6)\xe5H\xff\xff\xff\xff\xd7H\b\xd8\xff\xff\xff\xff\xd8\t\xc7H\xff\xff\xff\xff\xd9'" + + "\xea\xd8\xff\xff\xff\xff\xd9\xe9\xa9H\xff\xff\xff\xff\xdb\x11\aX\xff\xff\xff\xff\xdb\xd2\xc5\xc8\xff\xff\xff\xff\xdc\xdetX\xff\xff\xff\xffݩmH\xff\xff\xff\xff\u07beVX\xff\xff\xff\xff߉OH\xff\xff" + + "\xff\xff\xe0\x9e8X\xff\xff\xff\xff\xe1i1H\xff\xff\xff\xff\xe2~\x1aX\xff\xff\xff\xff\xe3I\x13H\xff\xff\xff\xff\xe4]\xfcX\xff\xff\xff\xff\xe5(\xf5H\xff\xff\xff\xff\xe6G\x18\xd8\xff\xff\xff\xff\xe7\x12" + + "\x11\xc8\xff\xff\xff\xff\xe8&\xfa\xd8\xff\xff\xff\xff\xe8\xf1\xf3\xc8\xff\xff\xff\xff\xea\x06\xdc\xd8\xff\xff\xff\xff\xea\xd1\xd5\xc8\xff\xff\xff\xff\xeb\xe6\xbe\xd8\xff\xff\xff\xff챷\xc8\xff\xff\xff\xff\xedƠ\xd8\xff\xff" + + "\xff\xff\ueffeH\xff\xff\xff\xffﯽX\xff\xff\xff\xff\xf0\x9f\xa0H\xff\xff\xff\xff\xf1\x8f\x9fX\xff\xff\xff\xff\xf2\u007f\x82H\xff\xff\xff\xff\xf3o\x81X\xff\xff\xff\xff\xf4_dH\xff\xff\xff\xff\xf5O" + + "cX\xff\xff\xff\xff\xf6?FH\xff\xff\xff\xff\xf7/EX\xff\xff\xff\xff\xf8(b\xc8\xff\xff\xff\xff\xf9\x0f'X\xff\xff\xff\xff\xfa\bD\xc8\xff\xff\xff\xff\xfa\xf8C\xd8\xff\xff\xff\xff\xfb\xe8&\xc8\xff\xff" + + "\xff\xff\xfc\xd8%\xd8\xff\xff\xff\xff\xfd\xc8\b\xc8\xff\xff\xff\xff\xfe\xb8\a\xd8\xff\xff\xff\xff\xff\xa7\xea\xc8\x00\x00\x00\x00\x00\x97\xe9\xd8\x00\x00\x00\x00\x01\x87\xcc\xc8\x00\x00\x00\x00\x02w\xcb\xd8\x00\x00\x00\x00\x03p" + + "\xe9H\x00\x00\x00\x00\x04`\xe8X\x00\x00\x00\x00\x05P\xcbH\x00\x00\x00\x00\x06@\xcaX\x00\x00\x00\x00\a0\xadH\x00\x00\x00\x00\b \xacX\x00\x00\x00\x00\t\x10\x8fH\x00\x00\x00\x00\n\x00\x8eX\x00\x00" + + "\x00\x00\n\xf0qH\x00\x00\x00\x00\v\xe0pX\x00\x00\x00\x00\fٍ\xc8\x00\x00\x00\x00\r\xc0RX\x00\x00\x00\x00\x0e\xb9o\xc8\x00\x00\x00\x00\x0f\xa9n\xd8\x00\x00\x00\x00\x10\x99Q\xc8\x00\x00\x00\x00\x11\x89" + + "P\xd8\x00\x00\x00\x00\x12y3\xc8\x00\x00\x00\x00\x13i2\xd8\x00\x00\x00\x00\x14Y\x15\xc8\x00\x00\x00\x00\x15I\x14\xd8\x00\x00\x00\x00\x168\xf7\xc8\x00\x00\x00\x00\x17(\xf6\xd8\x00\x00\x00\x00\x18\"\x14H\x00\x00" + + "\x00\x00\x19\b\xd8\xd8\x00\x00\x00\x00\x1a\x01\xf6H\x00\x00\x00\x00\x1a\xf1\xf5X\x00\x00\x00\x00\x1b\xe1\xd8H\x00\x00\x00\x00\x1c\xd1\xd7X\x00\x00\x00\x00\x1d\xc1\xbaH\x00\x00\x00\x00\x1e\xb1\xb9X\x00\x00\x00\x00\x1f\xa1" + + "\x9cH\x00\x00\x00\x00 u\xcf\xf4\x00\x00\x00\x00!\x81bd\x00\x00\x00\x00\"U\xb1\xf4\x00\x00\x00\x00#jp\xd4\x00\x00\x00\x00$5\x93\xf4\x00\x00\x00\x00%J`\xe4\x00\x00\x00\x00&\x15u\xf4\x00\x00" + + "\x00\x00'*B\xe4\x00\x00\x00\x00'\xfe\x92t\x00\x00\x00\x00)\n$\xe4\x00\x00\x00\x00)\xdett\x00\x00\x00\x00*\xea\x06\xe4\x00\x00\x00\x00+\xbeVt\x00\x00\x00\x00,\xd3#d\x00\x00\x00\x00-\x9e" + + "8t\x00\x00\x00\x00.\xb3\x05d\x00\x00\x00\x00/~\x1at\x00\x00\x00\x000\x92\xe7d\x00\x00\x00\x001g6\xf4\x00\x00\x00\x002r\xc9d\x00\x00\x00\x003G\x18\xf4\x00\x00\x00\x004R\xabd\x00\x00" + + "\x00\x005&\xfa\xf4\x00\x00\x00\x0062\x8dd\x00\x00\x00\x007\x06\xdc\xf4\x00\x00\x00\x008\x1b\xa9\xe4\x00\x00\x00\x008\xe6\xbe\xf4\x00\x00\x00\x009\xfb\x8b\xe4\x00\x00\x00\x00:Ơ\xf4\x00\x00\x00\x00;\xdb" + + "m\xe4\x00\x00\x00\x00<\xaf\xbdt\x00\x00\x00\x00=\xbbO\xe4\x00\x00\x00\x00>\x8f\x9ft\x00\x00\x00\x00?\x9b1\xe4\x00\x00\x00\x00@o\x81t\x00\x00\x00\x00A\x84Nd\x00\x00\x00\x00BOct\x00\x00" + + "\x00\x00Cd0d\x00\x00\x00\x00D/Et\x00\x00\x00\x00ED\x12d\x00\x00\x00\x00E\xf3w\xf4\x00\x00\x00\x00G-.\xe4\x00\x00\x00\x00G\xd3Y\xf4\x00\x00\x00\x00I\r\x10\xe4\x00\x00\x00\x00I\xb3" + + ";\xf4\x00\x00\x00\x00J\xec\xf2\xe4\x00\x00\x00\x00K\x9cXt\x00\x00\x00\x00L\xd6\x0fd\x00\x00\x00\x00M|:t\x00\x00\x00\x00N\xb6\rH\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x06\x05\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03" + + "\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03" + + "\x04\a\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\xff\xffΔ\x00\x00\xff\xffܤ\x01" + + "\x04\xff\xffΔ\x00\b\xff\xff\xdc\xd8\x01\x04\xff\xff\xce\xc8\x00\b\xff\xff\xdc\xd8\x01\f\xff\xff\xdc\xd8\x01\x10\xff\xff\xea\xe8\x01\x14LMT\x00NDT\x00NST\x00NPT\x00NWT\x00NDD" + + "T\x00\nNST3:30NDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS):\x17-\x88\x06\x00\x00\x88\x06\x00\x00\x0f\x00\x1c\x00C" + + "anada/AtlanticUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\xa7\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\x80\xf1\xab\xa0\xff\xff\xff\xff\x9a\xe4\xde\xc0\xff\xff\xff\xff\x9b\xd6\x130\xff\xff\xff\xff\x9e\xb8\x85`\xff\xff\xff\xff\x9f\xba\xddP\xff\xff\xff" + + "\xff\xa2\x9d\x17@\xff\xff\xff\xff\xa30\xb10\xff\xff\xff\xff\xa4zV@\xff\xff\xff\xff\xa5\x1b\x1f0\xff\xff\xff\xff\xa6S\xa0\xc0\xff\xff\xff\xff\xa6\xfcR\xb0\xff\xff\xff\xff\xa8<\xbd@\xff\xff\xff\xff\xa8\xdc4" + + "\xb0\xff\xff\xff\xff\xaa\x1c\x9f@\xff\xff\xff\xff\xaa\xcd:0\xff\xff\xff\xff\xab\xfc\x81@\xff\xff\xff\xff\xac\xbf\x910\xff\xff\xff\xff\xad\xee\xd8@\xff\xff\xff\xff\xae\x8c\xfe0\xff\xff\xff\xff\xaf\xbcE@\xff\xff\xff" + + "\xff\xb0\u007fU0\xff\xff\xff\xff\xb1\xae\x9c@\xff\xff\xff\xff\xb2Kp\xb0\xff\xff\xff\xff\xb3\x8e~@\xff\xff\xff\xff\xb4$\xbb0\xff\xff\xff\xff\xb5n`@\xff\xff\xff\xff\xb6\x15\xc0\xb0\xff\xff\xff\xff\xb7NB" + + "@\xff\xff\xff\xff\xb8\b\x17\xb0\xff\xff\xff\xff\xb9$\xe9\xc0\xff\xff\xff\xff\xb9\xe7\xf9\xb0\xff\xff\xff\xff\xbb\x04\xcb\xc0\xff\xff\xff\xff\xbb\xd1\x160\xff\xff\xff\xff\xbd\x00]@\xff\xff\xff\xff\xbd\x9d1\xb0\xff\xff\xff" + + "\xff\xbe\xf2\xb4@\xff\xff\xff\xff\xbf\x90\xda0\xff\xff\xff\xff\xc0\xd3\xe7\xc0\xff\xff\xff\xff\xc1^G0\xff\xff\xff\xff\u008d\x8e@\xff\xff\xff\xff\xc3P\x9e0\xff\xff\xff\xff\xc4mp@\xff\xff\xff\xff\xc50\x80" + + "0\xff\xff\xff\xff\xc6r<@\xff\xff\xff\xff\xc7\x10b0\xff\xff\xff\xff\xc86n\xc0\xff\xff\xff\xff\xc8\xf9~\xb0\xff\xff\xff\xff\xca\x16P\xc0\xff\xff\xff\xff\xca\xd9`\xb0\xff\xff\xff\xffˈ\xe2`\xff\xff\xff" + + "\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\xff\xff\xff\xff\xd3u\xd6\xe0\xff\xff\xff\xff\xd4@\xcf\xd0\xff\xff\xff\xff\xd5U\xb8\xe0\xff\xff\xff\xff\xd6 \xb1\xd0\xff\xff\xff\xff\xd75\x9a\xe0\xff\xff\xff\xff\xd8\x00\x93" + + "\xd0\xff\xff\xff\xff\xd9\x15|\xe0\xff\xff\xff\xff\xd9\xe0u\xd0\xff\xff\xff\xff\xdc\xde{`\xff\xff\xff\xffݩtP\xff\xff\xff\xff\u07be]`\xff\xff\xff\xff߉VP\xff\xff\xff\xff\xe0\x9e?`\xff\xff\xff" + + "\xff\xe1i8P\xff\xff\xff\xff\xe2~!`\xff\xff\xff\xff\xe3I\x1aP\xff\xff\xff\xff\xe6G\x1f\xe0\xff\xff\xff\xff\xe7\x12\x18\xd0\xff\xff\xff\xff\xe8'\x01\xe0\xff\xff\xff\xff\xe8\xf1\xfa\xd0\xff\xff\xff\xff\xea\x06\xe3" + + "\xe0\xff\xff\xff\xff\xea\xd1\xdc\xd0\xff\xff\xff\xff\xeb\xe6\xc5\xe0\xff\xff\xff\xff챾\xd0\xff\xff\xff\xff\xf1\x8f\xa6`\xff\xff\xff\xff\xf2\u007f\x89P\xff\xff\xff\xff\xf3o\x88`\xff\xff\xff\xff\xf4_kP\xff\xff\xff" + + "\xff\xf5Oj`\xff\xff\xff\xff\xf6?MP\xff\xff\xff\xff\xf7/L`\xff\xff\xff\xff\xf8(i\xd0\xff\xff\xff\xff\xf9\x0f.`\xff\xff\xff\xff\xfa\bK\xd0\xff\xff\xff\xff\xfa\xf8J\xe0\xff\xff\xff\xff\xfb\xe8-" + + "\xd0\xff\xff\xff\xff\xfc\xd8,\xe0\xff\xff\xff\xff\xfd\xc8\x0f\xd0\xff\xff\xff\xff\xfe\xb8\x0e\xe0\xff\xff\xff\xff\xff\xa7\xf1\xd0\x00\x00\x00\x00\x00\x97\xf0\xe0\x00\x00\x00\x00\x01\x87\xd3\xd0\x00\x00\x00\x00\x02w\xd2\xe0\x00\x00\x00" + + "\x00\x03p\xf0P\x00\x00\x00\x00\x04`\xef`\x00\x00\x00\x00\x05P\xd2P\x00\x00\x00\x00\x06@\xd1`\x00\x00\x00\x00\a0\xb4P\x00\x00\x00\x00\b \xb3`\x00\x00\x00\x00\t\x10\x96P\x00\x00\x00\x00\n\x00\x95" + + "`\x00\x00\x00\x00\n\xf0xP\x00\x00\x00\x00\v\xe0w`\x00\x00\x00\x00\fٔ\xd0\x00\x00\x00\x00\r\xc0Y`\x00\x00\x00\x00\x0e\xb9v\xd0\x00\x00\x00\x00\x0f\xa9u\xe0\x00\x00\x00\x00\x10\x99X\xd0\x00\x00\x00" + + "\x00\x11\x89W\xe0\x00\x00\x00\x00\x12y:\xd0\x00\x00\x00\x00\x13i9\xe0\x00\x00\x00\x00\x14Y\x1c\xd0\x00\x00\x00\x00\x15I\x1b\xe0\x00\x00\x00\x00\x168\xfe\xd0\x00\x00\x00\x00\x17(\xfd\xe0\x00\x00\x00\x00\x18\"\x1b" + + "P\x00\x00\x00\x00\x19\b\xdf\xe0\x00\x00\x00\x00\x1a\x01\xfdP\x00\x00\x00\x00\x1a\xf1\xfc`\x00\x00\x00\x00\x1b\xe1\xdfP\x00\x00\x00\x00\x1c\xd1\xde`\x00\x00\x00\x00\x1d\xc1\xc1P\x00\x00\x00\x00\x1e\xb1\xc0`\x00\x00\x00" + + "\x00\x1f\xa1\xa3P\x00\x00\x00\x00 u\xf2\xe0\x00\x00\x00\x00!\x81\x85P\x00\x00\x00\x00\"U\xd4\xe0\x00\x00\x00\x00#j\xa1\xd0\x00\x00\x00\x00$5\xb6\xe0\x00\x00\x00\x00%J\x83\xd0\x00\x00\x00\x00&\x15\x98" + + "\xe0\x00\x00\x00\x00'*e\xd0\x00\x00\x00\x00'\xfe\xb5`\x00\x00\x00\x00)\nG\xd0\x00\x00\x00\x00)ޗ`\x00\x00\x00\x00*\xea)\xd0\x00\x00\x00\x00+\xbey`\x00\x00\x00\x00,\xd3FP\x00\x00\x00" + + "\x00-\x9e[`\x00\x00\x00\x00.\xb3(P\x00\x00\x00\x00/~=`\x00\x00\x00\x000\x93\nP\x00\x00\x00\x001gY\xe0\x00\x00\x00\x002r\xecP\x00\x00\x00\x003G;\xe0\x00\x00\x00\x004R\xce" + + "P\x00\x00\x00\x005'\x1d\xe0\x00\x00\x00\x0062\xb0P\x00\x00\x00\x007\x06\xff\xe0\x00\x00\x00\x008\x1b\xcc\xd0\x00\x00\x00\x008\xe6\xe1\xe0\x00\x00\x00\x009\xfb\xae\xd0\x00\x00\x00\x00:\xc6\xc3\xe0\x00\x00\x00" + + "\x00;ې\xd0\x00\x00\x00\x00<\xaf\xe0`\x00\x00\x00\x00=\xbbr\xd0\x00\x00\x00\x00>\x8f\xc2`\x00\x00\x00\x00?\x9bT\xd0\x00\x00\x00\x00@o\xa4`\x00\x00\x00\x00A\x84qP\x00\x00\x00\x00BO\x86" + + "`\x00\x00\x00\x00CdSP\x00\x00\x00\x00D/h`\x00\x00\x00\x00ED5P\x00\x00\x00\x00E\xf3\x9a\xe0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xa4\xec\x00\x00\xff\xff\xb9\xb0\x01\x04" + - "\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10LMT\x00CDT\x00CST\x00CWT\x00CPT\x00\nCST6CDT,M3.2.0,M11.1." + - "0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R):\x17-\x88\x06\x00\x00\x88\x06\x00\x00\x0f\x00\x1c\x00Canada/AtlanticUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`" + - "ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00" + - "\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa7\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\x80\xf1\xab\xa0\xff\xff" + - "\xff\xff\x9a\xe4\xde\xc0\xff\xff\xff\xff\x9b\xd6\x130\xff\xff\xff\xff\x9e\xb8\x85`\xff\xff\xff\xff\x9f\xba\xddP\xff\xff\xff\xff\xa2\x9d\x17@\xff\xff\xff\xff\xa30\xb10\xff\xff\xff\xff\xa4zV@\xff\xff\xff\xff\xa5\x1b" + - "\x1f0\xff\xff\xff\xff\xa6S\xa0\xc0\xff\xff\xff\xff\xa6\xfcR\xb0\xff\xff\xff\xff\xa8<\xbd@\xff\xff\xff\xff\xa8\xdc4\xb0\xff\xff\xff\xff\xaa\x1c\x9f@\xff\xff\xff\xff\xaa\xcd:0\xff\xff\xff\xff\xab\xfc\x81@\xff\xff" + - "\xff\xff\xac\xbf\x910\xff\xff\xff\xff\xad\xee\xd8@\xff\xff\xff\xff\xae\x8c\xfe0\xff\xff\xff\xff\xaf\xbcE@\xff\xff\xff\xff\xb0\u007fU0\xff\xff\xff\xff\xb1\xae\x9c@\xff\xff\xff\xff\xb2Kp\xb0\xff\xff\xff\xff\xb3\x8e" + - "~@\xff\xff\xff\xff\xb4$\xbb0\xff\xff\xff\xff\xb5n`@\xff\xff\xff\xff\xb6\x15\xc0\xb0\xff\xff\xff\xff\xb7NB@\xff\xff\xff\xff\xb8\b\x17\xb0\xff\xff\xff\xff\xb9$\xe9\xc0\xff\xff\xff\xff\xb9\xe7\xf9\xb0\xff\xff" + - "\xff\xff\xbb\x04\xcb\xc0\xff\xff\xff\xff\xbb\xd1\x160\xff\xff\xff\xff\xbd\x00]@\xff\xff\xff\xff\xbd\x9d1\xb0\xff\xff\xff\xff\xbe\xf2\xb4@\xff\xff\xff\xff\xbf\x90\xda0\xff\xff\xff\xff\xc0\xd3\xe7\xc0\xff\xff\xff\xff\xc1^" + - "G0\xff\xff\xff\xff\u008d\x8e@\xff\xff\xff\xff\xc3P\x9e0\xff\xff\xff\xff\xc4mp@\xff\xff\xff\xff\xc50\x800\xff\xff\xff\xff\xc6r<@\xff\xff\xff\xff\xc7\x10b0\xff\xff\xff\xff\xc86n\xc0\xff\xff" + - "\xff\xff\xc8\xf9~\xb0\xff\xff\xff\xff\xca\x16P\xc0\xff\xff\xff\xff\xca\xd9`\xb0\xff\xff\xff\xffˈ\xe2`\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xed\xd0\xff\xff\xff\xff\xd3u\xd6\xe0\xff\xff\xff\xff\xd4@" + - "\xcf\xd0\xff\xff\xff\xff\xd5U\xb8\xe0\xff\xff\xff\xff\xd6 \xb1\xd0\xff\xff\xff\xff\xd75\x9a\xe0\xff\xff\xff\xff\xd8\x00\x93\xd0\xff\xff\xff\xff\xd9\x15|\xe0\xff\xff\xff\xff\xd9\xe0u\xd0\xff\xff\xff\xff\xdc\xde{`\xff\xff" + - "\xff\xffݩtP\xff\xff\xff\xff\u07be]`\xff\xff\xff\xff߉VP\xff\xff\xff\xff\xe0\x9e?`\xff\xff\xff\xff\xe1i8P\xff\xff\xff\xff\xe2~!`\xff\xff\xff\xff\xe3I\x1aP\xff\xff\xff\xff\xe6G" + - "\x1f\xe0\xff\xff\xff\xff\xe7\x12\x18\xd0\xff\xff\xff\xff\xe8'\x01\xe0\xff\xff\xff\xff\xe8\xf1\xfa\xd0\xff\xff\xff\xff\xea\x06\xe3\xe0\xff\xff\xff\xff\xea\xd1\xdc\xd0\xff\xff\xff\xff\xeb\xe6\xc5\xe0\xff\xff\xff\xff챾\xd0\xff\xff" + - "\xff\xff\xf1\x8f\xa6`\xff\xff\xff\xff\xf2\u007f\x89P\xff\xff\xff\xff\xf3o\x88`\xff\xff\xff\xff\xf4_kP\xff\xff\xff\xff\xf5Oj`\xff\xff\xff\xff\xf6?MP\xff\xff\xff\xff\xf7/L`\xff\xff\xff\xff\xf8(" + - "i\xd0\xff\xff\xff\xff\xf9\x0f.`\xff\xff\xff\xff\xfa\bK\xd0\xff\xff\xff\xff\xfa\xf8J\xe0\xff\xff\xff\xff\xfb\xe8-\xd0\xff\xff\xff\xff\xfc\xd8,\xe0\xff\xff\xff\xff\xfd\xc8\x0f\xd0\xff\xff\xff\xff\xfe\xb8\x0e\xe0\xff\xff" + - "\xff\xff\xff\xa7\xf1\xd0\x00\x00\x00\x00\x00\x97\xf0\xe0\x00\x00\x00\x00\x01\x87\xd3\xd0\x00\x00\x00\x00\x02w\xd2\xe0\x00\x00\x00\x00\x03p\xf0P\x00\x00\x00\x00\x04`\xef`\x00\x00\x00\x00\x05P\xd2P\x00\x00\x00\x00\x06@" + - "\xd1`\x00\x00\x00\x00\a0\xb4P\x00\x00\x00\x00\b \xb3`\x00\x00\x00\x00\t\x10\x96P\x00\x00\x00\x00\n\x00\x95`\x00\x00\x00\x00\n\xf0xP\x00\x00\x00\x00\v\xe0w`\x00\x00\x00\x00\fٔ\xd0\x00\x00" + - "\x00\x00\r\xc0Y`\x00\x00\x00\x00\x0e\xb9v\xd0\x00\x00\x00\x00\x0f\xa9u\xe0\x00\x00\x00\x00\x10\x99X\xd0\x00\x00\x00\x00\x11\x89W\xe0\x00\x00\x00\x00\x12y:\xd0\x00\x00\x00\x00\x13i9\xe0\x00\x00\x00\x00\x14Y" + - "\x1c\xd0\x00\x00\x00\x00\x15I\x1b\xe0\x00\x00\x00\x00\x168\xfe\xd0\x00\x00\x00\x00\x17(\xfd\xe0\x00\x00\x00\x00\x18\"\x1bP\x00\x00\x00\x00\x19\b\xdf\xe0\x00\x00\x00\x00\x1a\x01\xfdP\x00\x00\x00\x00\x1a\xf1\xfc`\x00\x00" + - "\x00\x00\x1b\xe1\xdfP\x00\x00\x00\x00\x1c\xd1\xde`\x00\x00\x00\x00\x1d\xc1\xc1P\x00\x00\x00\x00\x1e\xb1\xc0`\x00\x00\x00\x00\x1f\xa1\xa3P\x00\x00\x00\x00 u\xf2\xe0\x00\x00\x00\x00!\x81\x85P\x00\x00\x00\x00\"U" + - "\xd4\xe0\x00\x00\x00\x00#j\xa1\xd0\x00\x00\x00\x00$5\xb6\xe0\x00\x00\x00\x00%J\x83\xd0\x00\x00\x00\x00&\x15\x98\xe0\x00\x00\x00\x00'*e\xd0\x00\x00\x00\x00'\xfe\xb5`\x00\x00\x00\x00)\nG\xd0\x00\x00" + - "\x00\x00)ޗ`\x00\x00\x00\x00*\xea)\xd0\x00\x00\x00\x00+\xbey`\x00\x00\x00\x00,\xd3FP\x00\x00\x00\x00-\x9e[`\x00\x00\x00\x00.\xb3(P\x00\x00\x00\x00/~=`\x00\x00\x00\x000\x93" + - "\nP\x00\x00\x00\x001gY\xe0\x00\x00\x00\x002r\xecP\x00\x00\x00\x003G;\xe0\x00\x00\x00\x004R\xceP\x00\x00\x00\x005'\x1d\xe0\x00\x00\x00\x0062\xb0P\x00\x00\x00\x007\x06\xff\xe0\x00\x00" + - "\x00\x008\x1b\xcc\xd0\x00\x00\x00\x008\xe6\xe1\xe0\x00\x00\x00\x009\xfb\xae\xd0\x00\x00\x00\x00:\xc6\xc3\xe0\x00\x00\x00\x00;ې\xd0\x00\x00\x00\x00<\xaf\xe0`\x00\x00\x00\x00=\xbbr\xd0\x00\x00\x00\x00>\x8f" + - "\xc2`\x00\x00\x00\x00?\x9bT\xd0\x00\x00\x00\x00@o\xa4`\x00\x00\x00\x00A\x84qP\x00\x00\x00\x00BO\x86`\x00\x00\x00\x00CdSP\x00\x00\x00\x00D/h`\x00\x00\x00\x00ED5P\x00\x00" + - "\x00\x00E\xf3\x9a\xe0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xc4`\x00\x00\xff" + - "\xff\xd5\xd0\x01\x04\xff\xff\xc7\xc0\x00\b\xff\xff\xd5\xd0\x01\f\xff\xff\xd5\xd0\x01\x10LMT\x00ADT\x00AST\x00AWT\x00APT\x00\nAST4ADT,M3.2.0,M" + - "11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R{\a\a\xdc\xca\x03\x00\x00\xca\x03\x00\x00\x0f\x00\x1c\x00Canada/MountainUT\t\x00\x03\x15\xac\x0e" + - "`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" + - "\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Y\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\x88" + - "\xde\xce\xe0\xff\xff\xff\xff\x9e\xb8\xaf\x90\xff\xff\xff\xff\x9f\xbb\a\x80\xff\xff\xff\xff\xa0\x98\x91\x90\xff\xff\xff\xff\xa0҅\x80\xff\xff\xff\xff\xa2\x8a\xe8\x90\xff\xff\xff\xff\xa3\x84\x06\x00\xff\xff\xff\xff\xa4jʐ\xff" + - "\xff\xff\xff\xa55À\xff\xff\xff\xff\xa6S\xe7\x10\xff\xff\xff\xff\xa7\x15\xa5\x80\xff\xff\xff\xff\xa83\xc9\x10\xff\xff\xff\xff\xa8\xfe\xc2\x00\xff\xff\xff\xffˉ\f\x90\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2" + - "a\x18\x00\xff\xff\xff\xff\xd5U\xe3\x10\xff\xff\xff\xff\xd6 \xdc\x00\x00\x00\x00\x00\x04a\x19\x90\x00\x00\x00\x00\x05P\xfc\x80\x00\x00\x00\x00\x06@\xfb\x90\x00\x00\x00\x00\a0ހ\x00\x00\x00\x00\b ݐ\x00" + - "\x00\x00\x00\t\x10\xc0\x80\x00\x00\x00\x00\n\x00\xbf\x90\x00\x00\x00\x00\n\xf0\xa2\x80\x00\x00\x00\x00\vࡐ\x00\x00\x00\x00\fٿ\x00\x00\x00\x00\x00\r\xc0\x83\x90\x00\x00\x00\x00\x0e\xb9\xa1\x00\x00\x00\x00\x00\x0f" + - "\xa9\xa0\x10\x00\x00\x00\x00\x10\x99\x83\x00\x00\x00\x00\x00\x11\x89\x82\x10\x00\x00\x00\x00\x12ye\x00\x00\x00\x00\x00\x13id\x10\x00\x00\x00\x00\x14YG\x00\x00\x00\x00\x00\x15IF\x10\x00\x00\x00\x00\x169)\x00\x00" + - "\x00\x00\x00\x17)(\x10\x00\x00\x00\x00\x18\"E\x80\x00\x00\x00\x00\x19\t\n\x10\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2&\x90\x00\x00\x00\x00\x1b\xe2\t\x80\x00\x00\x00\x00\x1c\xd2\b\x90\x00\x00\x00\x00\x1d" + - "\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1\xea\x90\x00\x00\x00\x00\x1f\xa1̀\x00\x00\x00\x00 v\x1d\x10\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xff\x10\x00\x00\x00\x00#j\xcc\x00\x00\x00\x00\x00$5\xe1\x10\x00" + - "\x00\x00\x00%J\xae\x00\x00\x00\x00\x00&\x15\xc3\x10\x00\x00\x00\x00'*\x90\x00\x00\x00\x00\x00'\xfeߐ\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\xde\xc1\x90\x00\x00\x00\x00*\xeaT\x00\x00\x00\x00\x00+" + - "\xbe\xa3\x90\x00\x00\x00\x00,\xd3p\x80\x00\x00\x00\x00-\x9e\x85\x90\x00\x00\x00\x00.\xb3R\x80\x00\x00\x00\x00/~g\x90\x00\x00\x00\x000\x934\x80\x00\x00\x00\x001g\x84\x10\x00\x00\x00\x002s\x16\x80\x00" + - "\x00\x00\x003Gf\x10\x00\x00\x00\x004R\xf8\x80\x00\x00\x00\x005'H\x10\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe7\f\x10\x00\x00\x00\x009" + - "\xfb\xd9\x00\x00\x00\x00\x00:\xc6\xee\x10\x00\x00\x00\x00;ۻ\x00\x00\x00\x00\x00<\xb0\n\x90\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8f\xec\x90\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@oΐ\x00" + - "\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00BO\xb0\x90\x00\x00\x00\x00Cd}\x80\x00\x00\x00\x00D/\x92\x90\x00\x00\x00\x00ED_\x80\x00\x00\x00\x00E\xf3\xc5\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\x95\xa0\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\f\xff\xff\xab\xa0\x01\x10LMT\x00MDT\x00MST\x00MW" + - "T\x00MPT\x00\nMST7MDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xc1Ȇ\x90\x05\x04\x00\x00\x05\x04\x00\x00\f\x00\x1c\x00" + - "Canada/YukonUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00]\x00\x00\x00\t\x00\x00\x00%\xff\xff\xff\xff}\x86\x8a\x9c\xff\xff\xff\xff\x9e\xb8˰\xff\xff\xff\xff\x9f\xbb#\xa0\xff\xff\xff\xff\xa0\xd0\f\xb0\xff\xff\xff\xff\xa1\xa2Ҁ\xff\xff\xff\xff\xcb" + - "\x89(\xb0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a4 \xff\xff\xff\xff\xf7/v\x90\xff\xff\xff\xff\xf8(\xa2\x10\xff\xff\xff\xff\xfb\x1d_\x10\x00\x00\x00\x00\x13ir \x00\x00\x00\x00\x14YU\x10\x00" + - "\x00\x00\x00\x15IT \x00\x00\x00\x00\x1697\x10\x00\x00\x00\x00\x17)6 \x00\x00\x00\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18 \x00\x00\x00\x00\x1a\x025\x90\x00\x00\x00\x00\x1a\xf24\xa0\x00\x00\x00\x00\x1b" + - "\xe2\x17\x90\x00\x00\x00\x00\x1c\xd2\x16\xa0\x00\x00\x00\x00\x1d\xc1\xf9\x90\x00\x00\x00\x00\x1e\xb1\xf8\xa0\x00\x00\x00\x00\x1f\xa1ې\x00\x00\x00\x00 v+ \x00\x00\x00\x00!\x81\xbd\x90\x00\x00\x00\x00\"V\r \x00" + - "\x00\x00\x00#j\xda\x10\x00\x00\x00\x00$5\xef \x00\x00\x00\x00%J\xbc\x10\x00\x00\x00\x00&\x15\xd1 \x00\x00\x00\x00'*\x9e\x10\x00\x00\x00\x00'\xfe\xed\xa0\x00\x00\x00\x00)\n\x80\x10\x00\x00\x00\x00)" + - "\xdeϠ\x00\x00\x00\x00*\xeab\x10\x00\x00\x00\x00+\xbe\xb1\xa0\x00\x00\x00\x00,\xd3~\x90\x00\x00\x00\x00-\x9e\x93\xa0\x00\x00\x00\x00.\xb3`\x90\x00\x00\x00\x00/~u\xa0\x00\x00\x00\x000\x93B\x90\x00" + - "\x00\x00\x001g\x92 \x00\x00\x00\x002s$\x90\x00\x00\x00\x003Gt \x00\x00\x00\x004S\x06\x90\x00\x00\x00\x005'V \x00\x00\x00\x0062\xe8\x90\x00\x00\x00\x007\a8 \x00\x00\x00\x008" + - "\x1c\x05\x10\x00\x00\x00\x008\xe7\x1a \x00\x00\x00\x009\xfb\xe7\x10\x00\x00\x00\x00:\xc6\xfc \x00\x00\x00\x00;\xdb\xc9\x10\x00\x00\x00\x00<\xb0\x18\xa0\x00\x00\x00\x00=\xbb\xab\x10\x00\x00\x00\x00>\x8f\xfa\xa0\x00" + - "\x00\x00\x00?\x9b\x8d\x10\x00\x00\x00\x00@oܠ\x00\x00\x00\x00A\x84\xa9\x90\x00\x00\x00\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b\x90\x00\x00\x00\x00D/\xa0\xa0\x00\x00\x00\x00EDm\x90\x00\x00\x00\x00E" + - "\xf3\xd3 \x00\x00\x00\x00G-\x8a\x10\x00\x00\x00\x00Gӵ \x00\x00\x00\x00I\rl\x10\x00\x00\x00\x00I\xb3\x97 \x00\x00\x00\x00J\xedN\x10\x00\x00\x00\x00K\x9c\xb3\xa0\x00\x00\x00\x00L\xd6j\x90\x00" + - "\x00\x00\x00M|\x95\xa0\x00\x00\x00\x00N\xb6L\x90\x00\x00\x00\x00O\\w\xa0\x00\x00\x00\x00P\x96.\x90\x00\x00\x00\x00Q" + + "\x8f\xfa\xa0\x00\x00\x00\x00?\x9b\x8d\x10\x00\x00\x00\x00@oܠ\x00\x00\x00\x00A\x84\xa9\x90\x00\x00\x00\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b\x90\x00\x00\x00\x00D/\xa0\xa0\x00\x00\x00\x00EDm\x90\x00" + + "\x00\x00\x00E\xf3\xd3 \x00\x00\x00\x00G-\x8a\x10\x00\x00\x00\x00Gӵ \x00\x00\x00\x00I\rl\x10\x00\x00\x00\x00I\xb3\x97 \x00\x00\x00\x00J\xedN\x10\x00\x00\x00\x00K\x9c\xb3\xa0\x00\x00\x00\x00L" + + "\xd6j\x90\x00\x00\x00\x00M|\x95\xa0\x00\x00\x00\x00N\xb6L\x90\x00\x00\x00\x00O\\w\xa0\x00\x00\x00\x00P\x96.\x90\x00\x00\x00\x00Q\x8f\x9ft\x00\x00\x00\x00?\x9b1\xe4\x00\x00\x00\x00@o\x81t\x00\x00\x00\x00A\x84Nd\x00\x00\x00\x00BOct\x00\x00\x00\x00Cd0" + - "d\x00\x00\x00\x00D/Et\x00\x00\x00\x00ED\x12d\x00\x00\x00\x00E\xf3w\xf4\x00\x00\x00\x00G-.\xe4\x00\x00\x00\x00G\xd3Y\xf4\x00\x00\x00\x00I\r\x10\xe4\x00\x00\x00\x00I\xb3;\xf4\x00\x00\x00" + - "\x00J\xec\xf2\xe4\x00\x00\x00\x00K\x9cXt\x00\x00\x00\x00L\xd6\x0fd\x00\x00\x00\x00M|:t\x00\x00\x00\x00N\xb6\rH\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x06\x05\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04" + - "\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\a\x04\x03\x04" + - "\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\xff\xffΔ\x00\x00\xff\xffܤ\x01\x04\xff\xffΔ" + - "\x00\b\xff\xff\xdc\xd8\x01\x04\xff\xff\xce\xc8\x00\b\xff\xff\xdc\xd8\x01\f\xff\xff\xdc\xd8\x01\x10\xff\xff\xea\xe8\x01\x14LMT\x00NDT\x00NST\x00NPT\x00NWT\x00NDDT\x00\nNS" + - "T3:30NDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rӿ\x92\xbc\xb5\x06\x00\x00\xb5\x06\x00\x00\x0e\x00\x1c\x00Canada" + - "/EasternUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\xac\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xffr\xeex\xec\xff\xff\xff\xff\x9e\xb8\x93p\xff\xff\xff\xff\x9f\xba\xeb`\xff\xff\xff\xff\xa0\x87.\xc8\xff\xff\xff\xff\xa1\x9a\xb1@\xff\xff\xff\xff\xa2\x94\x06\xf0\xff" + - "\xff\xff\xff\xa3U\xa9@\xff\xff\xff\xff\xa4\x86]\xf0\xff\xff\xff\xff\xa5(x`\xff\xff\xff\xff\xa6f?\xf0\xff\xff\xff\xff\xa7\fN\xe0\xff\xff\xff\xff\xa8F!\xf0\xff\xff\xff\xff\xa8\xec0\xe0\xff\xff\xff\xff\xaa" + - "\x1c\xc9p\xff\xff\xff\xff\xaa\xd5M`\xff\xff\xff\xff\xab\xfc\xabp\xff\xff\xff\xff\xac\xb5/`\xff\xff\xff\xff\xad܍p\xff\xff\xff\xff\xae\x95\x11`\xff\xff\xff\xff\xaf\xbcop\xff\xff\xff\xff\xb0~-\xe0\xff" + - "\xff\xff\xff\xb1\x9cQp\xff\xff\xff\xff\xb2gJ`\xff\xff\xff\xff\xb3|3p\xff\xff\xff\xff\xb4G,`\xff\xff\xff\xff\xb5\\\x15p\xff\xff\xff\xff\xb6'\x0e`\xff\xff\xff\xff\xb7;\xf7p\xff\xff\xff\xff\xb8" + - "\x06\xf0`\xff\xff\xff\xff\xb9%\x13\xf0\xff\xff\xff\xff\xb9\xe6\xd2`\xff\xff\xff\xff\xbb\x04\xf5\xf0\xff\xff\xff\xff\xbb\xcf\xee\xe0\xff\xff\xff\xff\xbc\xe4\xd7\xf0\xff\xff\xff\xff\xbd\xaf\xd0\xe0\xff\xff\xff\xff\xbeĹ\xf0\xff" + - "\xff\xff\xff\xbf\x8f\xb2\xe0\xff\xff\xff\xff\xc0\xa4\x9b\xf0\xff\xff\xff\xff\xc1o\x94\xe0\xff\xff\xff\xff\u0084}\xf0\xff\xff\xff\xff\xc3Ov\xe0\xff\xff\xff\xff\xc4d_\xf0\xff\xff\xff\xff\xc5/X\xe0\xff\xff\xff\xff\xc6" + - "M|p\xff\xff\xff\xff\xc7\x0f:\xe0\xff\xff\xff\xff\xc8-^p\xff\xff\xff\xffˈ\xf0p\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xfb\xe0\xff\xff\xff\xff\xd3u\xe4\xf0\xff\xff\xff\xff\xd4@\xdd\xe0\xff" + - "\xff\xff\xff\xd5U\xaa\xd0\xff\xff\xff\xff\xd6 \xa3\xc0\xff\xff\xff\xff\xd75\x8c\xd0\xff\xff\xff\xff\xd8\x00\x85\xc0\xff\xff\xff\xff\xd9\x15n\xd0\xff\xff\xff\xff\xda3v@\xff\xff\xff\xff\xda\xfe\xa7p\xff\xff\xff\xff\xdc" + - "\x13t`\xff\xff\xff\xff\xdcމp\xff\xff\xff\xffݩ\x82`\xff\xff\xff\xff\u07bekp\xff\xff\xff\xff߉d`\xff\xff\xff\xff\xe0\x9eMp\xff\xff\xff\xff\xe1iF`\xff\xff\xff\xff\xe2~/p\xff" + - "\xff\xff\xff\xe3I(`\xff\xff\xff\xff\xe4^\x11p\xff\xff\xff\xff\xe5)\n`\xff\xff\xff\xff\xe6G-\xf0\xff\xff\xff\xff\xe7\x12&\xe0\xff\xff\xff\xff\xe8'\x0f\xf0\xff\xff\xff\xff\xe9\x16\xf2\xe0\xff\xff\xff\xff\xea" + - "\x06\xf1\xf0\xff\xff\xff\xff\xea\xf6\xd4\xe0\xff\xff\xff\xff\xeb\xe6\xd3\xf0\xff\xff\xff\xff\xecֶ\xe0\xff\xff\xff\xff\xedƵ\xf0\xff\xff\xff\xff\xee\xbf\xd3`\xff\xff\xff\xff\xef\xaf\xd2p\xff\xff\xff\xff\xf0\x9f\xb5`\xff" + - "\xff\xff\xff\xf1\x8f\xb4p\xff\xff\xff\xff\xf2\u007f\x97`\xff\xff\xff\xff\xf3o\x96p\xff\xff\xff\xff\xf4_y`\xff\xff\xff\xff\xf5Oxp\xff\xff\xff\xff\xf6?[`\xff\xff\xff\xff\xf7/Zp\xff\xff\xff\xff\xf8" + - "(w\xe0\xff\xff\xff\xff\xf9\x0f" + - "\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00" + - "\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x03\x04\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff" + - "\xff\xb5\x94\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x01\f\xff\xff\xc7\xc0\x01\x10LMT\x00EDT\x00EST\x00EWT\x00EPT\x00\nEST5EDT,M3" + - ".2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\u0096dK~\x02\x00\x00~\x02\x00\x00\x13\x00\x1c\x00Canada/Saskatchew" + - "anUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x005\x00\x00\x00" + - "\x06\x00\x00\x00\x18\xff\xff\xff\xff\x86\xfd\x93\x1c\xff\xff\xff\xff\x9e\xb8\xaf\x90\xff\xff\xff\xff\x9f\xbb\a\x80\xff\xff\xff\xff\xb5eO\xf0\xff\xff\xff\xff\xb60H\xe0\xff\xff\xff\xff\xb7E1\xf0\xff\xff\xff\xff\xb8\x10*" + - "\xe0\xff\xff\xff\xff\xb9%\x13\xf0\xff\xff\xff\xff\xb9\xf0\f\xe0\xff\xff\xff\xff\xbb\x0e0p\xff\xff\xff\xff\xbb\xcf\xee\xe0\xff\xff\xff\xff\xbc\xee\x12p\xff\xff\xff\xff\xbd\xb9\v`\xff\xff\xff\xff\xc2r\b\xf0\xff\xff\xff" + - "\xff\xc3a\xeb\xe0\xff\xff\xff\xff\xc4Q\xea\xf0\xff\xff\xff\xff\xc58\x93`\xff\xff\xff\xff\xc61\xcc\xf0\xff\xff\xff\xff\xc7!\xaf\xe0\xff\xff\xff\xff\xc8\x1a\xe9p\xff\xff\xff\xff\xc9\n\xcc`\xff\xff\xff\xff\xc9\xfa\xcb" + - "p\xff\xff\xff\xff\xca\xea\xae`\xff\xff\xff\xffˉ\f\x90\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff\xd3c\x8c\x10\xff\xff\xff\xff\xd4So\x00\xff\xff\xff\xff\xd5U\xe3\x10\xff\xff\xff" + - "\xff\xd6 \xdc\x00\xff\xff\xff\xff\xd75\xc5\x10\xff\xff\xff\xff\xd8\x00\xbe\x00\xff\xff\xff\xff\xd9\x15\xa7\x10\xff\xff\xff\xff\xd9\xe0\xa0\x00\xff\xff\xff\xff\xda\xfeÐ\xff\xff\xff\xff\xdb\xc0\x82\x00\xff\xff\xff\xff\xdcޥ" + - "\x90\xff\xff\xff\xffݩ\x9e\x80\xff\xff\xff\xff\u07be\x87\x90\xff\xff\xff\xff߉\x80\x80\xff\xff\xff\xff\xe0\x9ei\x90\xff\xff\xff\xff\xe1ib\x80\xff\xff\xff\xff\xe2~K\x90\xff\xff\xff\xff\xe3ID\x80\xff\xff\xff" + - "\xff\xe4^-\x90\xff\xff\xff\xff\xe5)&\x80\xff\xff\xff\xff\xe6GJ\x10\xff\xff\xff\xff\xe7\x12C\x00\xff\xff\xff\xff\xe8',\x10\xff\xff\xff\xff\xe8\xf2%\x00\xff\xff\xff\xff\xeb\xe6\xf0\x10\xff\xff\xff\xff\xec\xd6\xd3" + - "\x00\xff\xff\xff\xff\xed\xc6\xd2\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x05\xff\xff\x9d\xe4\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\f\xff\xff\xab\xa0\x01\x10\xff\xff\xab\xa0\x00\x14LMT\x00MDT\x00MST\x00MWT\x00MPT\x00CS" + - "T\x00\nCST6\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xe6\x9aM\xbem\x02\x00\x00m\x02\x00\x00\x03\x00\x1c\x00CETUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04" + - "\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" + - "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x005\x00\x00\x00\x02\x00\x00\x00\t\xff\xff\xff\xff\x9b\f\x17`\xff\xff\xff\xff\x9b\xd5\xda\xf0" + - "\xff\xff\xff\xff\x9cٮ\x90\xff\xff\xff\xff\x9d\xa4\xb5\x90\xff\xff\xff\xff\x9e\xb9\x90\x90\xff\xff\xff\xff\x9f\x84\x97\x90\xff\xff\xff\xff\xc8\tq\x90\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff" + - "\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd2N@\x90\x00\x00\x00\x00\r\xa4c\x90\x00\x00\x00\x00\x0e\x8b\x1a\x10\x00\x00\x00\x00\x0f\x84E\x90" + - "\x00\x00\x00\x00\x10t6\x90\x00\x00\x00\x00\x11d'\x90\x00\x00\x00\x00\x12T\x18\x90\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00" + - "\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10" + - "\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#O@\x00\x00\x00\x00\x06\x00\r" + - "\xb0\x00\x00\x00\x00\a\v\xbc@\x00\x00\x00\x00\a\xdf\xef\xb0\x00\x00\x00\x00\b\xfe\x13@\x00\x00\x00\x00\t\xbfѰ\x00\x00\x00\x00\n\xdd\xf5@\x00\x00\x00\x00\v\xa8\xee0\x00\x00\x00\x00\f\xbd\xd7@\x00\x00\x00" + - "\x00\r\x88\xd00\x00\x00\x00\x00\x0e\x9d\xb9@\x00\x00\x00\x00\x0fh\xb20\x00\x00\x00\x00\x10\x86\xd5\xc0\x00\x00\x00\x00\x11H\x940\x00\x00\x00\x00\x12f\xb7\xc0\x00\x00\x00\x00\x13(v0\x00\x00\x00\x00\x14F\x99" + - "\xc0\x00\x00\x00\x00\x15\x11\x92\xb0\x00\x00\x00\x00\x16&{\xc0\x00\x00\x00\x00\x16\xf1t\xb0\x00\x00\x00\x00\x18\x06]\xc0\x00\x00\x00\x00\x18\xd1V\xb0\x00\x00\x00\x00\x19\xe6?\xc0\x00\x00\x00\x00\x1a\xb18\xb0\x00\x00\x00" + - "\x00\x1b\xcf\\@\x00\x00\x00\x00\x1c\x91\x1a\xb0\x00\x00\x00\x00\x1d\xaf>@\x00\x00\x00\x00\x1ep\xfc\xb0\x00\x00\x00\x00\x1f\x8f @\x00\x00\x00\x00 \u007f\x030\x00\x00\x00\x00!o\x02@\x00\x00\x00\x00\"9\xfb" + - "0\x00\x00\x00\x00#N\xe4@\x00\x00\x00\x00$\x19\xdd0\x00\x00\x00\x00%8\x00\xc0\x00\x00\x00\x00%\xf9\xbf0\x00\x00\x00\x00&\xf2\xf8\xc0\x00\x00\x00\x00'١0\x00\x00\x00\x00(\xf7\xc4\xc0\x00\x00\x00" + - "\x00)½\xb0\x00\x00\x00\x00*צ\xc0\x00\x00\x00\x00+\xa2\x9f\xb0\x00\x00\x00\x00,\xb7\x88\xc0\x00\x00\x00\x00-\x82\x81\xb0\x00\x00\x00\x00.\x97j\xc0\x00\x00\x00\x00/bc\xb0\x00\x00\x00\x000\x80\x87" + - "@\x00\x00\x00\x001BE\xb0\x00\x00\x00\x002`i@\x00\x00\x00\x003=\xd70\x00\x00\x00\x004@K@\x00\x00\x00\x005\vD0\x00\x00\x00\x006\r\xb8@\x00\x00\x00\x007\x06հ\x00\x00\x00" + - "\x008\x00\x0f@\x00\x00\x00\x008\xcb\b0\x00\x00\x00\x009\xe9+\xc0\x00\x00\x00\x00:\xaa\xea0\x00\x00\x00\x00;\xc9\r\xc0\x00\x00\x00\x00<\x8a\xcc0\x00\x00\x00\x00=\xa8\xef\xc0\x00\x00\x00\x00>j\xae" + - "0\x00\x00\x00\x00?\x88\xd1\xc0\x00\x00\x00\x00@Sʰ\x00\x00\x00\x00Ah\xb3\xc0\x00\x00\x00\x00B3\xac\xb0\x00\x00\x00\x00CH\x95\xc0\x00\x00\x00\x00D\x13\x8e\xb0\x00\x00\x00\x00E1\xb2@\x00\x00\x00" + - "\x00E\xf3p\xb0\x00\x00\x00\x00G\x11\x94@\x00\x00\x00\x00G\xef\x020\x00\x00\x00\x00H\xf1v@\x00\x00\x00\x00I\xbco0\x00\x00\x00\x00J\xd1X@\x00\x00\x00\x00K\xb8\x00\xb0\x00\x00\x00\x00L\xb1:" + - "@\x00\x00\x00\x00M\xc6\a0\x00\x00\x00\x00NP\x82\xc0\x00\x00\x00\x00O\x9c\xae\xb0\x00\x00\x00\x00PB\xd9\xc0\x00\x00\x00\x00Q|\x90\xb0\x00\x00\x00\x00R+\xf6@\x00\x00\x00\x00S\\r\xb0\x00\x00\x00" + - "\x00T\v\xd8@\x00\x00\x00\x00W7\xe60\x00\x00\x00\x00W\xaf\xec\xc0\x00\x00\x00\x00Y\x17\xc80\x00\x00\x00\x00Y\x8f\xce\xc0\x00\x00\x00\x00Z\xf7\xaa0\x00\x00\x00\x00[o\xb0\xc0\x00\x00\x00\x00\\\xa9g" + - "\xb0\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05" + - "\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\xff\xff\x99x\x00\x00\xff\xff\x99x\x00\x04\xff\xff\xab\xa0\x01" + - "\b\xff\xff\x9d\x90\x00\f\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\x10LMT\x00EMT\x00-06\x00-07\x00-05\x00\n<-06>6<-05>,M9.1.6/2" + - "2,M4.1.6/22\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R[Sp\x90\x02\x05\x00\x00\x02\x05\x00\x00\x11\x00\x1c\x00Chile/ContinentalU" + - "T\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00z\x00\x00\x00\x06\x00\x00" + - "\x00\x14\xff\xff\xff\xffi\x87\x1d\xc6\xff\xff\xff\xff\x8f0GF\xff\xff\xff\xff\x9b\\\xe5P\xff\xff\xff\xff\x9f|\xe2\xc6\xff\xff\xff\xff\xa1\x00q\xc0\xff\xff\xff\xff\xb0^w\xc6\xff\xff\xff\xff\xb1w=@\xff\xff" + - "\xff\xff\xb2A\x00\xd0\xff\xff\xff\xff\xb3Xp\xc0\xff\xff\xff\xff\xb4\"4P\xff\xff\xff\xff\xb59\xa4@\xff\xff\xff\xff\xb6\x03g\xd0\xff\xff\xff\xff\xb7\x1a\xd7\xc0\xff\xff\xff\xff\xb7\xe4\x9bP\xff\xff\xff\xff\xb8\xfd" + - "\\\xc0\xff\xff\xff\xff\xb9\xc7 P\xff\xff\xff\xff\xcc\x1cn@\xff\xff\xff\xff\xccl\xe7\xd0\xff\xff\xff\xff\xd3\u070f\xc0\xff\xff\xff\xff\xd4\x1bɰ\xff\xff\xff\xff\xd53U\xc0\xff\xff\xff\xff\xd5v\x92@\xff\xff" + - "\xff\xff\xfd\xd1<@\xff\xff\xff\xff\xfe\x92\xfa\xb0\xff\xff\xff\xff\xff\xcc\xcd\xc0\x00\x00\x00\x00\x00rܰ\x00\x00\x00\x00\x01uP\xc0\x00\x00\x00\x00\x02@I\xb0\x00\x00\x00\x00\x03U2\xc0\x00\x00\x00\x00\x04 " + - "+\xb0\x00\x00\x00\x00\x05>O@\x00\x00\x00\x00\x06\x00\r\xb0\x00\x00\x00\x00\a\v\xbc@\x00\x00\x00\x00\a\xdf\xef\xb0\x00\x00\x00\x00\b\xfe\x13@\x00\x00\x00\x00\t\xbfѰ\x00\x00\x00\x00\n\xdd\xf5@\x00\x00" + - "\x00\x00\v\xa8\xee0\x00\x00\x00\x00\f\xbd\xd7@\x00\x00\x00\x00\r\x88\xd00\x00\x00\x00\x00\x0e\x9d\xb9@\x00\x00\x00\x00\x0fh\xb20\x00\x00\x00\x00\x10\x86\xd5\xc0\x00\x00\x00\x00\x11H\x940\x00\x00\x00\x00\x12f" + - "\xb7\xc0\x00\x00\x00\x00\x13(v0\x00\x00\x00\x00\x14F\x99\xc0\x00\x00\x00\x00\x15\x11\x92\xb0\x00\x00\x00\x00\x16&{\xc0\x00\x00\x00\x00\x16\xf1t\xb0\x00\x00\x00\x00\x18\x06]\xc0\x00\x00\x00\x00\x18\xd1V\xb0\x00\x00" + - "\x00\x00\x19\xe6?\xc0\x00\x00\x00\x00\x1a\xb18\xb0\x00\x00\x00\x00\x1b\xcf\\@\x00\x00\x00\x00\x1c\x91\x1a\xb0\x00\x00\x00\x00\x1d\xaf>@\x00\x00\x00\x00\x1ep\xfc\xb0\x00\x00\x00\x00\x1f\x8f @\x00\x00\x00\x00 \u007f" + - "\x030\x00\x00\x00\x00!o\x02@\x00\x00\x00\x00\"9\xfb0\x00\x00\x00\x00#N\xe4@\x00\x00\x00\x00$\x19\xdd0\x00\x00\x00\x00%8\x00\xc0\x00\x00\x00\x00%\xf9\xbf0\x00\x00\x00\x00&\xf2\xf8\xc0\x00\x00" + - "\x00\x00'١0\x00\x00\x00\x00(\xf7\xc4\xc0\x00\x00\x00\x00)½\xb0\x00\x00\x00\x00*צ\xc0\x00\x00\x00\x00+\xa2\x9f\xb0\x00\x00\x00\x00,\xb7\x88\xc0\x00\x00\x00\x00-\x82\x81\xb0\x00\x00\x00\x00.\x97" + - "j\xc0\x00\x00\x00\x00/bc\xb0\x00\x00\x00\x000\x80\x87@\x00\x00\x00\x001BE\xb0\x00\x00\x00\x002`i@\x00\x00\x00\x003=\xd70\x00\x00\x00\x004@K@\x00\x00\x00\x005\vD0\x00\x00" + - "\x00\x006\r\xb8@\x00\x00\x00\x007\x06հ\x00\x00\x00\x008\x00\x0f@\x00\x00\x00\x008\xcb\b0\x00\x00\x00\x009\xe9+\xc0\x00\x00\x00\x00:\xaa\xea0\x00\x00\x00\x00;\xc9\r\xc0\x00\x00\x00\x00<\x8a" + - "\xcc0\x00\x00\x00\x00=\xa8\xef\xc0\x00\x00\x00\x00>j\xae0\x00\x00\x00\x00?\x88\xd1\xc0\x00\x00\x00\x00@Sʰ\x00\x00\x00\x00Ah\xb3\xc0\x00\x00\x00\x00B3\xac\xb0\x00\x00\x00\x00CH\x95\xc0\x00\x00" + - "\x00\x00D\x13\x8e\xb0\x00\x00\x00\x00E1\xb2@\x00\x00\x00\x00E\xf3p\xb0\x00\x00\x00\x00G\x11\x94@\x00\x00\x00\x00G\xef\x020\x00\x00\x00\x00H\xf1v@\x00\x00\x00\x00I\xbco0\x00\x00\x00\x00J\xd1" + - "X@\x00\x00\x00\x00K\xb8\x00\xb0\x00\x00\x00\x00L\xb1:@\x00\x00\x00\x00M\xc6\a0\x00\x00\x00\x00NP\x82\xc0\x00\x00\x00\x00O\x9c\xae\xb0\x00\x00\x00\x00PB\xd9\xc0\x00\x00\x00\x00Q|\x90\xb0\x00\x00" + - "\x00\x00R+\xf6@\x00\x00\x00\x00S\\r\xb0\x00\x00\x00\x00T\v\xd8@\x00\x00\x00\x00W7\xe60\x00\x00\x00\x00W\xaf\xec\xc0\x00\x00\x00\x00Y\x17\xc80\x00\x00\x00\x00Y\x8f\xce\xc0\x00\x00\x00\x00Z\xf7" + - "\xaa0\x00\x00\x00\x00[o\xb0\xc0\x00\x00\x00\x00\\\xa9g\xb0\x01\x02\x01\x03\x01\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x03\x02\x03\x05\x03\x02\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03" + - "\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03" + - "\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\xff\xff\xbd\xba\x00\x00\xff\xff\xbd\xba\x00\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x00\f\xff\xff\xc7\xc0\x01\f\xff\xff\xd5\xd0\x01\x10LMT\x00" + - "SMT\x00-05\x00-04\x00-03\x00\n<-04>4<-03>,M9.1.6/24,M4.1.6/24\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1" + - "c9R<\x8b\x99\x1e\xb7\x03\x00\x00\xb7\x03\x00\x00\a\x00\x1c\x00CST6CDTUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00X\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdb" + - "p\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xfa\xf8g\x00\xff\xff\xff\xff\xfb\xe8I\xf0\xff\xff\xff\xff\xfc\xd8I\x00\xff\xff\xff\xff\xfd\xc8+\xf0\xff\xff\xff" + - "\xff\xfe\xb8+\x00\xff\xff\xff\xff\xff\xa8\r\xf0\x00\x00\x00\x00\x00\x98\r\x00\x00\x00\x00\x00\x01\x87\xef\xf0\x00\x00\x00\x00\x02w\xef\x00\x00\x00\x00\x00\x03q\fp\x00\x00\x00\x00\x04a\v\x80\x00\x00\x00\x00\x05P\xee" + - "p\x00\x00\x00\x00\x06@\xed\x80\x00\x00\x00\x00\a0\xd0p\x00\x00\x00\x00\a\x8d'\x80\x00\x00\x00\x00\t\x10\xb2p\x00\x00\x00\x00\t\xad\xa3\x00\x00\x00\x00\x00\n\xf0\x94p\x00\x00\x00\x00\v\xe0\x93\x80\x00\x00\x00" + - "\x00\fٰ\xf0\x00\x00\x00\x00\r\xc0u\x80\x00\x00\x00\x00\x0e\xb9\x92\xf0\x00\x00\x00\x00\x0f\xa9\x92\x00\x00\x00\x00\x00\x10\x99t\xf0\x00\x00\x00\x00\x11\x89t\x00\x00\x00\x00\x00\x12yV\xf0\x00\x00\x00\x00\x13iV" + - "\x00\x00\x00\x00\x00\x14Y8\xf0\x00\x00\x00\x00\x15I8\x00\x00\x00\x00\x00\x169\x1a\xf0\x00\x00\x00\x00\x17)\x1a\x00\x00\x00\x00\x00\x18\"7p\x00\x00\x00\x00\x19\b\xfc\x00\x00\x00\x00\x00\x1a\x02\x19p\x00\x00\x00" + - "\x00\x1a\xf2\x18\x80\x00\x00\x00\x00\x1b\xe1\xfbp\x00\x00\x00\x00\x1c\xd1\xfa\x80\x00\x00\x00\x00\x1d\xc1\xddp\x00\x00\x00\x00\x1e\xb1܀\x00\x00\x00\x00\x1f\xa1\xbfp\x00\x00\x00\x00 v\x0f\x00\x00\x00\x00\x00!\x81\xa1" + - "p\x00\x00\x00\x00\"U\xf1\x00\x00\x00\x00\x00#j\xbd\xf0\x00\x00\x00\x00$5\xd3\x00\x00\x00\x00\x00%J\x9f\xf0\x00\x00\x00\x00&\x15\xb5\x00\x00\x00\x00\x00'*\x81\xf0\x00\x00\x00\x00'\xfeр\x00\x00\x00" + - "\x00)\nc\xf0\x00\x00\x00\x00)\u07b3\x80\x00\x00\x00\x00*\xeaE\xf0\x00\x00\x00\x00+\xbe\x95\x80\x00\x00\x00\x00,\xd3bp\x00\x00\x00\x00-\x9ew\x80\x00\x00\x00\x00.\xb3Dp\x00\x00\x00\x00/~Y" + - "\x80\x00\x00\x00\x000\x93&p\x00\x00\x00\x001gv\x00\x00\x00\x00\x002s\bp\x00\x00\x00\x003GX\x00\x00\x00\x00\x004R\xeap\x00\x00\x00\x005':\x00\x00\x00\x00\x0062\xccp\x00\x00\x00" + - "\x007\a\x1c\x00\x00\x00\x00\x008\x1b\xe8\xf0\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xca\xf0\x00\x00\x00\x00:\xc6\xe0\x00\x00\x00\x00\x00;۬\xf0\x00\x00\x00\x00<\xaf\xfc\x80\x00\x00\x00\x00=\xbb\x8e" + - "\xf0\x00\x00\x00\x00>\x8fހ\x00\x00\x00\x00?\x9bp\xf0\x00\x00\x00\x00@o\xc0\x80\x00\x00\x00\x00A\x84\x8dp\x00\x00\x00\x00BO\xa2\x80\x00\x00\x00\x00Cdop\x00\x00\x00\x00D/\x84\x80\x00\x00\x00" + - "\x00EDQp\x00\x00\x00\x00E\xf3\xb7\x00\x01\x00\x01\x00\x02\x03\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00" + - "\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\xff\xff\xab\xa0\x00\x04\xff\xff\xb9\xb0\x01\x00\xff\xff\xb9\xb0\x01\b\xff" + - "\xff\xb9\xb0\x01\fCDT\x00CST\x00CWT\x00CPT\x00\nCST6CDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\a" + - "\x1c\x9e\x9a]\x04\x00\x00]\x04\x00\x00\x04\x00\x1c\x00CubaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffi\x87(\xb8\xff\xff\xff\xff\xacb\u0080\xff\xff\xff\xff\xb1ӔP\xff\xff\xff\xff\xb2t]@\xff\xff\xff\xff\xc8[" + - "f\xd0\xff\xff\xff\xff\xc8\xd3Q@\xff\xff\xff\xff\xca;H\xd0\xff\xff\xff\xffʼm\xc0\xff\xff\xff\xff\xcc$eP\xff\xff\xff\xff̜O\xc0\xff\xff\xff\xff\xd1\xc4\vP\xff\xff\xff\xff\xd2;\xf5\xc0\xff\xff" + - "\xff\xffӣ\xedP\xff\xff\xff\xff\xd4\x1b\xd7\xc0\xff\xff\xff\xff\xf7`\x05\xd0\xff\xff\xff\xff\xf7\xff}@\xff\xff\xff\xff\xf9=D\xd0\xff\xff\xff\xff\xf9\xe3S\xc0\xff\xff\xff\xff\xfa\xdb;\xd0\xff\xff\xff\xff\xfb\xa7" + - "\x86@\xff\xff\xff\xff\xfcũ\xd0\xff\xff\xff\xff\xfd\x87h@\xff\xff\xff\xff\xfe\xb8\x00\xd0\xff\xff\xff\xff\xff\xa7\xe3\xc0\x00\x00\x00\x00\x00\x97\xe2\xd0\x00\x00\x00\x00\x01\x87\xc5\xc0\x00\x00\x00\x00\x02w\xc4\xd0\x00\x00" + - "\x00\x00\x03p\xe2@\x00\x00\x00\x00\x04`\xe1P\x00\x00\x00\x00\x055\x14\xc0\x00\x00\x00\x00\x06@\xc3P\x00\x00\x00\x00\a\x16H@\x00\x00\x00\x00\b \xa5P\x00\x00\x00\x00\b\xf7{\xc0\x00\x00\x00\x00\n\x00" + - "\x87P\x00\x00\x00\x00\n\xf0j@\x00\x00\x00\x00\v\xe0iP\x00\x00\x00\x00\fن\xc0\x00\x00\x00\x00\r\xc0KP\x00\x00\x00\x00\x0e\xb9h\xc0\x00\x00\x00\x00\x0f\xb2\xa2P\x00\x00\x00\x00\x10}\x9b@\x00\x00" + - "\x00\x00\x11Q\xea\xd0\x00\x00\x00\x00\x12f\xb7\xc0\x00\x00\x00\x00\x131\xcc\xd0\x00\x00\x00\x00\x14F\x99\xc0\x00\x00\x00\x00\x15[\x82\xd0\x00\x00\x00\x00\x16&{\xc0\x00\x00\x00\x00\x17;d\xd0\x00\x00\x00\x00\x18\x06" + - "]\xc0\x00\x00\x00\x00\x19\x1bF\xd0\x00\x00\x00\x00\x19\xe6?\xc0\x00\x00\x00\x00\x1a\xfb(\xd0\x00\x00\x00\x00\x1b\xcf\\@\x00\x00\x00\x00\x1c\xdb\n\xd0\x00\x00\x00\x00\x1d\xaf>@\x00\x00\x00\x00\x1ezSP\x00\x00" + - "\x00\x00\x1f\x8f @\x00\x00\x00\x00 Z5P\x00\x00\x00\x00!o\x02@\x00\x00\x00\x00\"CQ\xd0\x00\x00\x00\x00#N\xe4@\x00\x00\x00\x00$#3\xd0\x00\x00\x00\x00%.\xc6@\x00\x00\x00\x00&\x15" + - "\x8a\xd0\x00\x00\x00\x00'\x17\xe2\xc0\x00\x00\x00\x00'\xfe\xa7P\x00\x00\x00\x00(\xf7\xd2\xd0\x00\x00\x00\x00)މP\x00\x00\x00\x00*״\xd0\x00\x00\x00\x00+\xbekP\x00\x00\x00\x00,\xb7\x96\xd0\x00\x00" + - "\x00\x00-\x9eMP\x00\x00\x00\x00.\x97x\xd0\x00\x00\x00\x00/~/P\x00\x00\x00\x000wZ\xd0\x00\x00\x00\x001gK\xd0\x00\x00\x00\x002W<\xd0\x00\x00\x00\x003G-\xd0\x00\x00\x00\x004@" + - "YP\x00\x00\x00\x005\x1d\xd5P\x00\x00\x00\x0062\xb0P\x00\x00\x00\x006\xfd\xb7P\x00\x00\x00\x008\x1b\xcc\xd0\x00\x00\x00\x008\xe6\xd3\xd0\x00\x00\x00\x009\xfb\xae\xd0\x00\x00\x00\x00:Ƶ\xd0\x00\x00" + - "\x00\x00;ې\xd0\x00\x00\x00\x00<\xaf\xd2P\x00\x00\x00\x00=\xbbr\xd0\x00\x00\x00\x00>\x8f\xb4P\x00\x00\x00\x00?\x9bT\xd0\x00\x00\x00\x00@f[\xd0\x00\x00\x00\x00ED5P\x00\x00\x00\x00E\xf3" + - "\x8c\xd0\x00\x00\x00\x00G$\x17P\x00\x00\x00\x00GܩP\x00\x00\x00\x00I\x03\xf9P\x00\x00\x00\x00I\xb3P\xd0\x00\x00\x00\x00J\xe3\xdbP\x00\x00\x00\x00K\x9cmP\x00\x00\x00\x00L\xcc\xf7\xd0\x00\x00" + - "\x00\x00M\x85\x89\xd0\x00\x00\x00\x00N\xbfN\xd0\x00\x00\x00\x00Ow\xe0\xd0\x00\x00\x00\x00P\x95\xf6P\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\xff\xff\xb2\xc8\x00\x00\xff\xff\xb2\xc0\x00\x04\xff\xff\xc7\xc0\x01\b\xff\xff\xb9\xb0\x00\fLMT\x00HMT\x00CDT\x00CST\x00\nCST" + - "5CDT,M3.2.0/0,M11.1.0/1\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R`l\x8d~\xf1\x01\x00\x00\xf1\x01\x00\x00\x03\x00\x1c\x00EETUT\t" + - "\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\x00\x00\x00\x02\x00\x00\x00\t" + - "\x00\x00\x00\x00\r\xa4c\x90\x00\x00\x00\x00\x0e\x8b\x1a\x10\x00\x00\x00\x00\x0f\x84E\x90\x00\x00\x00\x00\x10t6\x90\x00\x00\x00\x00\x11d'\x90\x00\x00\x00\x00\x12T\x18\x90\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00" + - "\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90" + - "\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00" + - "\"LT\x10\x00\x00\x00\x00#\xa8^`\x00\x00\x00\x00?sWP\x00\x00\x00\x00@\x91z\xe0\x00\x00\x00\x00A\\s\xd0\x00\x00\x00\x00Bq\\\xe0" + - "\x00\x00\x00\x00C\xe0\x00\x00\x00\x00E\x12\xfdP\x00\x00\x00\x00F1 \xe0\x00\x00\x00\x00F\xe0jP\x00\x00\x00\x00H\x11\x02\xe0\x00\x00\x00\x00H\xb7\x11\xd0\x00\x00\x00\x00" + - "I\xf0\xe4\xe0\x00\x00\x00\x00J\x8d\xb9P\x00\x00\x00\x00K\xda\x01`\x00\x00\x00\x00La\xbd\xd0\x00\x00\x00\x00L\x89X\xe0\x00\x00\x00\x00L\xa4\xfaP\x00\x00\x00\x00Su8\xe0\x00\x00\x00\x00S\xac\x89\xd0" + - "\x00\x00\x00\x00Sڼ`\x00\x00\x00\x00T$\x82P\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\b\xff\xff\x81d\x00\x00\xff\xff\x8f\x80\x01\x04\xff\xff\x81p\x00\b\xff\xff\x8f\x80\x01\f\xff\xff\x8f\x80\x01\x10\xff\xff\x9d\x90\x01\x14\xff\xff\x8f\x80\x00\x19\xff\xff" + + "\x9d\x90\x01\x1d\xff\xff\x9d\x90\x00!LMT\x00YDT\x00YST\x00YWT\x00YPT\x00YDDT\x00PST\x00PDT\x00MST\x00\nMST7\nPK\x03\x04\n\x00\x00" + + "\x00\x00\x00#\x82iSӿ\x92\xbc\xb5\x06\x00\x00\xb5\x06\x00\x00\x0e\x00\x1c\x00Canada/EasternUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00" + + "\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif" + + "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xac\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xffr\xeex\xec\xff\xff\xff\xff\x9e\xb8\x93p\xff\xff\xff\xff" + + "\x9f\xba\xeb`\xff\xff\xff\xff\xa0\x87.\xc8\xff\xff\xff\xff\xa1\x9a\xb1@\xff\xff\xff\xff\xa2\x94\x06\xf0\xff\xff\xff\xff\xa3U\xa9@\xff\xff\xff\xff\xa4\x86]\xf0\xff\xff\xff\xff\xa5(x`\xff\xff\xff\xff\xa6f?\xf0" + + "\xff\xff\xff\xff\xa7\fN\xe0\xff\xff\xff\xff\xa8F!\xf0\xff\xff\xff\xff\xa8\xec0\xe0\xff\xff\xff\xff\xaa\x1c\xc9p\xff\xff\xff\xff\xaa\xd5M`\xff\xff\xff\xff\xab\xfc\xabp\xff\xff\xff\xff\xac\xb5/`\xff\xff\xff\xff" + + "\xad܍p\xff\xff\xff\xff\xae\x95\x11`\xff\xff\xff\xff\xaf\xbcop\xff\xff\xff\xff\xb0~-\xe0\xff\xff\xff\xff\xb1\x9cQp\xff\xff\xff\xff\xb2gJ`\xff\xff\xff\xff\xb3|3p\xff\xff\xff\xff\xb4G,`" + + "\xff\xff\xff\xff\xb5\\\x15p\xff\xff\xff\xff\xb6'\x0e`\xff\xff\xff\xff\xb7;\xf7p\xff\xff\xff\xff\xb8\x06\xf0`\xff\xff\xff\xff\xb9%\x13\xf0\xff\xff\xff\xff\xb9\xe6\xd2`\xff\xff\xff\xff\xbb\x04\xf5\xf0\xff\xff\xff\xff" + + "\xbb\xcf\xee\xe0\xff\xff\xff\xff\xbc\xe4\xd7\xf0\xff\xff\xff\xff\xbd\xaf\xd0\xe0\xff\xff\xff\xff\xbeĹ\xf0\xff\xff\xff\xff\xbf\x8f\xb2\xe0\xff\xff\xff\xff\xc0\xa4\x9b\xf0\xff\xff\xff\xff\xc1o\x94\xe0\xff\xff\xff\xff\u0084}\xf0" + + "\xff\xff\xff\xff\xc3Ov\xe0\xff\xff\xff\xff\xc4d_\xf0\xff\xff\xff\xff\xc5/X\xe0\xff\xff\xff\xff\xc6M|p\xff\xff\xff\xff\xc7\x0f:\xe0\xff\xff\xff\xff\xc8-^p\xff\xff\xff\xffˈ\xf0p\xff\xff\xff\xff" + + "\xd2#\xf4p\xff\xff\xff\xff\xd2`\xfb\xe0\xff\xff\xff\xff\xd3u\xe4\xf0\xff\xff\xff\xff\xd4@\xdd\xe0\xff\xff\xff\xff\xd5U\xaa\xd0\xff\xff\xff\xff\xd6 \xa3\xc0\xff\xff\xff\xff\xd75\x8c\xd0\xff\xff\xff\xff\xd8\x00\x85\xc0" + + "\xff\xff\xff\xff\xd9\x15n\xd0\xff\xff\xff\xff\xda3v@\xff\xff\xff\xff\xda\xfe\xa7p\xff\xff\xff\xff\xdc\x13t`\xff\xff\xff\xff\xdcމp\xff\xff\xff\xffݩ\x82`\xff\xff\xff\xff\u07bekp\xff\xff\xff\xff" + + "߉d`\xff\xff\xff\xff\xe0\x9eMp\xff\xff\xff\xff\xe1iF`\xff\xff\xff\xff\xe2~/p\xff\xff\xff\xff\xe3I(`\xff\xff\xff\xff\xe4^\x11p\xff\xff\xff\xff\xe5)\n`\xff\xff\xff\xff\xe6G-\xf0" + + "\xff\xff\xff\xff\xe7\x12&\xe0\xff\xff\xff\xff\xe8'\x0f\xf0\xff\xff\xff\xff\xe9\x16\xf2\xe0\xff\xff\xff\xff\xea\x06\xf1\xf0\xff\xff\xff\xff\xea\xf6\xd4\xe0\xff\xff\xff\xff\xeb\xe6\xd3\xf0\xff\xff\xff\xff\xecֶ\xe0\xff\xff\xff\xff" + + "\xedƵ\xf0\xff\xff\xff\xff\xee\xbf\xd3`\xff\xff\xff\xff\xef\xaf\xd2p\xff\xff\xff\xff\xf0\x9f\xb5`\xff\xff\xff\xff\xf1\x8f\xb4p\xff\xff\xff\xff\xf2\u007f\x97`\xff\xff\xff\xff\xf3o\x96p\xff\xff\xff\xff\xf4_y`" + + "\xff\xff\xff\xff\xf5Oxp\xff\xff\xff\xff\xf6?[`\xff\xff\xff\xff\xf7/Zp\xff\xff\xff\xff\xf8(w\xe0\xff\xff\xff\xff\xf9\x0f\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00" + + "BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\x1dU\x00\x00\x00\x00*0\x01\x04\x00\x00\x1c \x00\tLMT\x00EEST\x00EET\x00\nEET-2" + - "\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x9a\v\xf9/\xd8\x05\x00\x00\xd8\x05\x00\x00\x04\x00\x1c\x00EireUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8" + - "\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x91\x00\x00\x00\b\x00\x00\x00\x14\xff\xff\xff\xffW\xd1\n\xdc\xff\xff\xff\xff\x9b&\xb3\x91\xff\xff\xff\xff\x9b\xd6" + - "\v\x11\xff\xff\xff\xff\x9c\xcf0\xa0\xff\xff\xff\xff\x9d\xa4à\xff\xff\xff\xff\x9e\x9c\x9d\xa0\xff\xff\xff\xff\x9f\x97\x1a\xa0\xff\xff\xff\xff\xa0\x85\xba \xff\xff\xff\xff\xa1v\xfc\xa0\xff\xff\xff\xff\xa2e\x9c \xff\xff" + - "\xff\xff\xa3{Ƞ\xff\xff\xff\xff\xa4N\xb8\xa0\xff\xff\xff\xff\xa5?\xfb \xff\xff\xff\xff\xa6%` \xff\xff\xff\xff\xa7'\xc6 \xff\xff\xff\xff\xa8*, \xff\xff\xff\xff\xa8\xeb\xf8\xa0\xff\xff\xff\xff\xaa\x00" + - "Ӡ\xff\xff\xff\xff\xaa\xd5\x15 \xff\xff\xff\xff\xab\xe9\xf0 \xff\xff\xff\xff\xac\xc7l \xff\xff\xff\xff\xad\xc9\xd2 \xff\xff\xff\xff\xae\xa7N \xff\xff\xff\xff\xaf\xa0y\xa0\xff\xff\xff\xff\xb0\x870 \xff\xff" + - "\xff\xff\xb1\x92Р\xff\xff\xff\xff\xb2pL\xa0\xff\xff\xff\xff\xb3r\xb2\xa0\xff\xff\xff\xff\xb4P.\xa0\xff\xff\xff\xff\xb5IZ \xff\xff\xff\xff\xb60\x10\xa0\xff\xff\xff\xff\xb72v\xa0\xff\xff\xff\xff\xb8\x0f" + - "\xf2\xa0\xff\xff\xff\xff\xb9\x12X\xa0\xff\xff\xff\xff\xb9\xefԠ\xff\xff\xff\xff\xba\xe9\x00 \xff\xff\xff\xff\xbb\xd8\xf1 \xff\xff\xff\xff\xbc\xdbW \xff\xff\xff\xff\xbd\xb8\xd3 \xff\xff\xff\xff\xbe\xb1\xfe\xa0\xff\xff" + - "\xff\xff\xbf\x98\xb5 \xff\xff\xff\xff\xc0\x9b\x1b \xff\xff\xff\xff\xc1x\x97 \xff\xff\xff\xff\xc2z\xfd \xff\xff\xff\xff\xc3Xy \xff\xff\xff\xff\xc4Q\xa4\xa0\xff\xff\xff\xff\xc58[ \xff\xff\xff\xff\xc6:" + - "\xc1 \xff\xff\xff\xff\xc7X֠\xff\xff\xff\xff\xc7\xda\t\xa0\xff\xff\xff\xff\xd4I\xe0 \xff\xff\xff\xff\xd5\x1e!\xa0\xff\xff\xff\xff\xd6N\xac \xff\xff\xff\xff\xd7,( \xff\xff\xff\xff\xd8.\x8e \xff\xff" + - "\xff\xff\xd8\xf9\x95 \xff\xff\xff\xff\xda\x0ep \xff\xff\xff\xff\xda\xeb\xec \xff\xff\xff\xff\xdb\xe5\x17\xa0\xff\xff\xff\xff\xdc\xcb\xce \xff\xff\xff\xff\xdd\xc4\xf9\xa0\xff\xff\xff\xff\u07b4\xea\xa0\xff\xff\xff\xff߮" + - "\x16 \xff\xff\xff\xff\xe0\x94̠\xff\xff\xff\xff\xe1rH\xa0\xff\xff\xff\xff\xe2kt \xff\xff\xff\xff\xe3R*\xa0\xff\xff\xff\xff\xe4T\x90\xa0\xff\xff\xff\xff\xe52\f\xa0\xff\xff\xff\xff\xe6=\xad \xff\xff" + - "\xff\xff\xe7\x1b) \xff\xff\xff\xff\xe8\x14T\xa0\xff\xff\xff\xff\xe8\xfb\v \xff\xff\xff\xff\xe9\xfdq \xff\xff\xff\xff\xea\xda\xed \xff\xff\xff\xff\xeb\xddS \xff\xff\xff\xff\xec\xba\xcf \xff\xff\xff\xff\xed\xb3" + - "\xfa\xa0\xff\xff\xff\xff\ue6b1 \xff\xff\xff\xff\xef\x81g\xa0\xff\xff\xff\xff\xf0\x9f} \xff\xff\xff\xff\xf1aI\xa0\xff\xff\xff\xff\xf2\u007f_ \xff\xff\xff\xff\xf3Jf \xff\xff\xff\xff\xf4_A \xff\xff" + - "\xff\xff\xf5!\r\xa0\xff\xff\xff\xff\xf6?# \xff\xff\xff\xff\xf7\x00\xef\xa0\xff\xff\xff\xff\xf8\x1f\x05 \xff\xff\xff\xff\xf8\xe0Ѡ\xff\xff\xff\xff\xf9\xfe\xe7 \xff\xff\xff\xff\xfa\xc0\xb3\xa0\xff\xff\xff\xff\xfb\xe8" + - "\x03\xa0\xff\xff\xff\xff\xfc{\xab\xa0\xff\xff\xff\xff\xfdǻp\x00\x00\x00\x00\x03p\xc6 \x00\x00\x00\x00\x04)X \x00\x00\x00\x00\x05P\xa8 \x00\x00\x00\x00\x06\t: \x00\x00\x00\x00\a0\x8a \x00\x00" + - "\x00\x00\a\xe9\x1c \x00\x00\x00\x00\t\x10l \x00\x00\x00\x00\t\xc8\xfe \x00\x00\x00\x00\n\xf0N \x00\x00\x00\x00\v\xb2\x1a\xa0\x00\x00\x00\x00\f\xd00 \x00\x00\x00\x00\r\x91\xfc\xa0\x00\x00\x00\x00\x0e\xb0" + - "\x12 \x00\x00\x00\x00\x0fqޠ\x00\x00\x00\x00\x10\x99.\xa0\x00\x00\x00\x00\x11Q\xc0\xa0\x00\x00\x00\x00\x12y\x10\xa0\x00\x00\x00\x00\x131\xa2\xa0\x00\x00\x00\x00\x14X\xf2\xa0\x00\x00\x00\x00\x15#\xeb\x90\x00\x00" + - "\x00\x00\x168Ɛ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x18\x18\xa8\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19\xf8\x8a\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xe1\xa7\x10\x00\x00\x00\x00\x1c\xac" + - "\xae\x10\x00\x00\x00\x00\x1d\xc1\x89\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f\xa1k\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\x81M\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#a/\x10\x00\x00" + - "\x00\x00$,6\x10\x00\x00\x00\x00%JK\x90\x00\x00\x00\x00&\f\x18\x10\x00\x00\x00\x00'*-\x90\x00\x00\x00\x00'\xf54\x90\x00\x00\x00\x00)\n\x0f\x90\x00\x00\x00\x00)\xd5\x16\x90\x00\x00\x00\x00*\xe9" + - "\xf1\x90\x00\x00\x00\x00+\xb4\xf8\x90\x00\x00\x00\x00,\xc9Ӑ\x00\x00\x00\x00-\x94ڐ\x00\x00\x00\x00.\xa9\xb5\x90\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000\x89\x97\x90\x00\x00\x00\x001]\xd9\x10\x01\x02" + - "\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05" + - "\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06" + - "\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\xff\xff\xfa$\x00\x00\xff\xff\xfa\x0f\x00\x04\x00\x00\b\x1f\x01\b\x00\x00\x0e\x10\x01\f\x00\x00\x00\x00\x00\x10\x00\x00\x0e\x10\x01\b\x00" + - "\x00\x00\x00\x01\x10\x00\x00\x0e\x10\x00\bLMT\x00DMT\x00IST\x00BST\x00GMT\x00\nIST-1GMT0,M10.5.0,M3.5.0/1\nP" + - "K\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RtX\xbe\xe4o\x00\x00\x00o\x00\x00\x00\x03\x00\x1c\x00ESTUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00" + - "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xff\xb9\xb0\x00\x00EST\x00\nEST5\nPK\x03\x04\n\x00\x00\x00\x00" + - "\x00\xf1c9R\xe7/\xebT\xb7\x03\x00\x00\xb7\x03\x00\x00\a\x00\x1c\x00EST5EDTUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif" + - "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00X\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff\x9e\xa6\x1ep\xff\xff\xff\xff\x9f\xba\xeb`\xff\xff\xff\xff\xa0\x86\x00p\xff\xff\xff\xff\xa1" + - "\x9a\xcd`\xff\xff\xff\xffˈ\xf0p\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xfb\xe0\xff\xff\xff\xff\xfa\xf8X\xf0\xff\xff\xff\xff\xfb\xe8;\xe0\xff\xff\xff\xff\xfc\xd8:\xf0\xff\xff\xff\xff\xfd\xc8\x1d\xe0\xff" + - "\xff\xff\xff\xfe\xb8\x1c\xf0\xff\xff\xff\xff\xff\xa7\xff\xe0\x00\x00\x00\x00\x00\x97\xfe\xf0\x00\x00\x00\x00\x01\x87\xe1\xe0\x00\x00\x00\x00\x02w\xe0\xf0\x00\x00\x00\x00\x03p\xfe`\x00\x00\x00\x00\x04`\xfdp\x00\x00\x00\x00\x05" + - "P\xe0`\x00\x00\x00\x00\x06@\xdfp\x00\x00\x00\x00\a0\xc2`\x00\x00\x00\x00\a\x8d\x19p\x00\x00\x00\x00\t\x10\xa4`\x00\x00\x00\x00\t\xad\x94\xf0\x00\x00\x00\x00\n\xf0\x86`\x00\x00\x00\x00\v\xe0\x85p\x00" + - "\x00\x00\x00\f٢\xe0\x00\x00\x00\x00\r\xc0gp\x00\x00\x00\x00\x0e\xb9\x84\xe0\x00\x00\x00\x00\x0f\xa9\x83\xf0\x00\x00\x00\x00\x10\x99f\xe0\x00\x00\x00\x00\x11\x89e\xf0\x00\x00\x00\x00\x12yH\xe0\x00\x00\x00\x00\x13" + - "iG\xf0\x00\x00\x00\x00\x14Y*\xe0\x00\x00\x00\x00\x15I)\xf0\x00\x00\x00\x00\x169\f\xe0\x00\x00\x00\x00\x17)\v\xf0\x00\x00\x00\x00\x18\")`\x00\x00\x00\x00\x19\b\xed\xf0\x00\x00\x00\x00\x1a\x02\v`\x00" + - "\x00\x00\x00\x1a\xf2\np\x00\x00\x00\x00\x1b\xe1\xed`\x00\x00\x00\x00\x1c\xd1\xecp\x00\x00\x00\x00\x1d\xc1\xcf`\x00\x00\x00\x00\x1e\xb1\xcep\x00\x00\x00\x00\x1f\xa1\xb1`\x00\x00\x00\x00 v\x00\xf0\x00\x00\x00\x00!" + - "\x81\x93`\x00\x00\x00\x00\"U\xe2\xf0\x00\x00\x00\x00#j\xaf\xe0\x00\x00\x00\x00$5\xc4\xf0\x00\x00\x00\x00%J\x91\xe0\x00\x00\x00\x00&\x15\xa6\xf0\x00\x00\x00\x00'*s\xe0\x00\x00\x00\x00'\xfe\xc3p\x00" + - "\x00\x00\x00)\nU\xe0\x00\x00\x00\x00)ޥp\x00\x00\x00\x00*\xea7\xe0\x00\x00\x00\x00+\xbe\x87p\x00\x00\x00\x00,\xd3T`\x00\x00\x00\x00-\x9eip\x00\x00\x00\x00.\xb36`\x00\x00\x00\x00/" + - "~Kp\x00\x00\x00\x000\x93\x18`\x00\x00\x00\x001gg\xf0\x00\x00\x00\x002r\xfa`\x00\x00\x00\x003GI\xf0\x00\x00\x00\x004R\xdc`\x00\x00\x00\x005'+\xf0\x00\x00\x00\x0062\xbe`\x00" + - "\x00\x00\x007\a\r\xf0\x00\x00\x00\x008\x1b\xda\xe0\x00\x00\x00\x008\xe6\xef\xf0\x00\x00\x00\x009\xfb\xbc\xe0\x00\x00\x00\x00:\xc6\xd1\xf0\x00\x00\x00\x00;۞\xe0\x00\x00\x00\x00<\xaf\xeep\x00\x00\x00\x00=" + - "\xbb\x80\xe0\x00\x00\x00\x00>\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00" + - "\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x01\x00\x01\x00\x02\x03\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00" + - "\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\xff\xff\xb9\xb0\x00\x04\xff\xff\xc7\xc0\x01\x00\xff\xff\xc7\xc0\x01" + - "\b\xff\xff\xc7\xc0\x01\fEDT\x00EST\x00EWT\x00EPT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9" + - "R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x1c\x00Etc/UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x03\x04\n\x00\x00\x00\x00\x00\xf1" + - "c9RP\xda\xfa\x03o\x00\x00\x00o\x00\x00\x00\t\x00\x1c\x00Etc/GMT+0UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif" + - "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9" + - "RP\xda\xfa\x03o\x00\x00\x00o\x00\x00\x00\r\x00\x1c\x00Etc/GreenwichUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZ" + - "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1" + - "c9RP\xda\xfa\x03o\x00\x00\x00o\x00\x00\x00\t\x00\x1c\x00Etc/GMT-0UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif" + - "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9" + - "R\xd4X\x9b\xf3q\x00\x00\x00q\x00\x00\x00\t\x00\x1c\x00Etc/GMT+5UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xff\xb9\xb0\x00\x00-05\x00\n<-05>5\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9" + - "R\xf7\x1ac\xc3r\x00\x00\x00r\x00\x00\x00\t\x00\x1c\x00Etc/GMT-1UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x0e\x10\x00\x00+01\x00\n<+01>-1\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c" + - "9R5\xb8\xe8\x86q\x00\x00\x00q\x00\x00\x00\t\x00\x1c\x00Etc/GMT+1UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xff\xf1\xf0\x00\x00-01\x00\n<-01>1\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c" + - "9R\"\xf8\x8f/q\x00\x00\x00q\x00\x00\x00\t\x00\x1c\x00Etc/GMT+8UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xff\x8f\x80\x00\x00-08\x00\n<-08>8\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c" + - "9R\xf7\x19s\x81s\x00\x00\x00s\x00\x00\x00\n\x00\x1c\x00Etc/GMT-12UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif" + - "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\xa8\xc0\x00\x00+12\x00\n<+12>-12\nPK\x03\x04\n\x00\x00\x00\x00" + - "\x00\xf1c9R\x9f.\xe4xo\x00\x00\x00o\x00\x00\x00\a\x00\x1c\x00Etc/UCTUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif" + - "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00UTC\x00\nUTC0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9" + - "R\xa9{\xa2qq\x00\x00\x00q\x00\x00\x00\t\x00\x1c\x00Etc/GMT+2UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xb5\x94\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x01\f\xff\xff\xc7\xc0\x01\x10LM" + + "T\x00EDT\x00EST\x00EWT\x00EPT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSU9#\xbe" + + "2\x05\x00\x002\x05\x00\x00\x0e\x00\x1c\x00Canada/PacificUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xff\xe3\xe0\x00\x00-02\x00\n<-02>2\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9" + - "R\xb2\xab\xd1Is\x00\x00\x00s\x00\x00\x00\n\x00\x1c\x00Etc/GMT-11UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x9a\xb0\x00\x00+11\x00\n<+11>-11\nPK\x03\x04\n\x00\x00\x00\x00\x00" + - "\xf1c9R\xd0\xfaFDq\x00\x00\x00q\x00\x00\x00\t\x00\x1c\x00Etc/GMT+4UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZi" + - "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xff\xc7\xc0\x00\x00-04\x00\n<-04>4\nPK\x03\x04\n\x00\x00\x00\x00\x00" + - "\xf1c9R\x9c\xfcm\x99r\x00\x00\x00r\x00\x00\x00\t\x00\x1c\x00Etc/GMT-3UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZi" + - "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00*0\x00\x00+03\x00\n<+03>-3\nPK\x03\x04\n\x00\x00\x00\x00" + - "\x00\xf1c9R!\xd6~wr\x00\x00\x00r\x00\x00\x00\t\x00\x1c\x00Etc/GMT-5UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZ" + - "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00FP\x00\x00+05\x00\n<+05>-5\nPK\x03\x04\n\x00\x00\x00" + - "\x00\x00\xf1c9Re\xcb\xe9Qq\x00\x00\x00q\x00\x00\x00\t\x00\x1c\x00Etc/GMT+3UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00T" + - "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xff\xd5\xd0\x00\x00-03\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00" + - "\x00\x00\xf1c9R\xd9|\xbd7s\x00\x00\x00s\x00\x00\x00\n\x00\x1c\x00Etc/GMT-10UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00" + - "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x8c\xa0\x00\x00+10\x00\n<+10>-10\nPK\x03\x04\n" + - "\x00\x00\x00\x00\x00\xf1c9R\xe5\xf38cr\x00\x00\x00r\x00\x00\x00\n\x00\x1c\x00Etc/GMT+12UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8" + - "\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xffW@\x00\x00-12\x00\n<-12>12\nPK\x03" + - "\x04\n\x00\x00\x00\x00\x00\xf1c9R\xfc\x19@\xb9r\x00\x00\x00r\x00\x00\x00\t\x00\x1c\x00Etc/GMT-9UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04" + - "\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00~\x90\x00\x00+09\x00\n<+09>-9\nPK" + - "\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x90`N\xe8s\x00\x00\x00s\x00\x00\x00\n\x00\x1c\x00Etc/GMT-13UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00" + - "\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZi" + - "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\xb6\xd0\x00\x00+13\x00\n<+13>-13" + - "\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RP\xda\xfa\x03o\x00\x00\x00o\x00\x00\x00\b\x00\x1c\x00Etc/GMT0UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03" + - "\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + - "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00GMT\x00\nGMT0\nPK" + - "\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x8e\x1569r\x00\x00\x00r\x00\x00\x00\n\x00\x1c\x00Etc/GMT+10UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00" + - "\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZi" + - "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xffs`\x00\x00-10\x00\n<-10>10\n" + - "PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rj\xd5d\xb0r\x00\x00\x00r\x00\x00\x00\t\x00\x1c\x00Etc/GMT-6UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03" + - "\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + - "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00T`\x00\x00+06\x00\n<+06>-6" + - "\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x9f.\xe4xo\x00\x00\x00o\x00\x00\x00\a\x00\x1c\x00Etc/UTCUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00" + - "\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZi" + - "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00UTC\x00\nUTC0\nPK\x03" + - "\x04\n\x00\x00\x00\x00\x00\xf1c9R\x84+\x9a$q\x00\x00\x00q\x00\x00\x00\t\x00\x1c\x00Etc/GMT+7UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04" + - "\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xff\x9d\x90\x00\x00-07\x00\n<-07>7\nPK\x03" + - "\x04\n\x00\x00\x00\x00\x00\xf1c9RH\x9b\xd1\x04q\x00\x00\x00q\x00\x00\x00\t\x00\x1c\x00Etc/GMT+6UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04" + - "\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xff\xab\xa0\x00\x00-06\x00\n<-06>6\nPK\x03" + - "\x04\n\x00\x00\x00\x00\x00\xf1c9RJ0p-r\x00\x00\x00r\x00\x00\x00\t\x00\x1c\x00Etc/GMT-7UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04" + - "\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00bp\x00\x00+07\x00\n<+07>-7\nPK" + - "\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RP\xda\xfa\x03o\x00\x00\x00o\x00\x00\x00\a\x00\x1c\x00Etc/GMTUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8" + - "\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00" + - "\x00\x00\x00\x00\xf1c9R\xbc\x19y\x04r\x00\x00\x00r\x00\x00\x00\t\x00\x1c\x00Etc/GMT-2UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00" + - "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x1c \x00\x00+02\x00\n<+02>-2\nPK\x03\x04\n" + - "\x00\x00\x00\x00\x00\xf1c9R,{\xdc;s\x00\x00\x00s\x00\x00\x00\n\x00\x1c\x00Etc/GMT-14UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8" + - "\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\xc4\xe0\x00\x00+14\x00\n<+14>-14\nPK" + - "\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x9f.\xe4xo\x00\x00\x00o\x00\x00\x00\r\x00\x1c\x00Etc/UniversalUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04" + - "\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" + - "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00UTC\x00\nUTC0\n" + - "PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xc5\x18\xb6\xfbr\x00\x00\x00r\x00\x00\x00\t\x00\x1c\x00Etc/GMT-8UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03" + - "\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + - "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00p\x80\x00\x00+08\x00\n<+08>-8" + - "\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R)\xb9\xbe\x9dr\x00\x00\x00r\x00\x00\x00\n\x00\x1c\x00Etc/GMT+11UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04" + - "\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" + - "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xffeP\x00\x00-11\x00\n<-11>" + - "11\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x9f.\xe4xo\x00\x00\x00o\x00\x00\x00\b\x00\x1c\x00Etc/ZuluUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04" + - "\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" + - "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00UTC\x00\nUTC0\n" + - "PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rk\x19-4" + - "\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x84\x19\xb3\tq\x00\x00\x00q\x00\x00\x00\t\x00\x1c\x00Etc/GMT+9UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8" + - "\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00T" + - "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xff\x81p\x00\x00-09\x00\n<-09>9" + - "\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x1c\x00Europe/UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00" + - "\x00\x04\xe8\x03\x00\x00PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x95\u007fpp\xdc\x02\x00\x00\xdc\x02\x00\x00\r\x00\x1c\x00Europe/SamaraUT\t\x00\x03\x15\xac\x0e`\x15\xac" + - "\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" + - "\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x06\x00\x00\x00\x10\xff\xff\xff\xff\xa1\x009\x80" + - "\xff\xff\xff\xff\xb5\xa4\vP\x00\x00\x00\x00\x15'\x99\xc0\x00\x00\x00\x00\x16\x18\xce0\x00\x00\x00\x00\x17\b\xcd@\x00\x00\x00\x00\x17\xfa\x01\xb0\x00\x00\x00\x00\x18\xea\x00\xc0\x00\x00\x00\x00\x19\xdb50\x00\x00\x00\x00" + - "\x1a̅\xc0\x00\x00\x00\x00\x1b\xbc\x92\xe0\x00\x00\x00\x00\x1c\xac\x83\xe0\x00\x00\x00\x00\x1d\x9ct\xe0\x00\x00\x00\x00\x1e\x8ce\xe0\x00\x00\x00\x00\x1f|V\xe0\x00\x00\x00\x00 lG\xe0\x00\x00\x00\x00!\\8\xe0" + - "\x00\x00\x00\x00\"L)\xe0\x00\x00\x00\x00#<\x1a\xe0\x00\x00\x00\x00$,\v\xe0\x00\x00\x00\x00%\x1c\n\xf0\x00\x00\x00\x00&\v\xfb\xf0\x00\x00\x00\x00'\x05'p\x00\x00\x00\x00'\xf5\x18p\x00\x00\x00\x00" + - "(\xe5\x17\x80\x00\x00\x00\x00)\x00\xc7\x00\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xc4\xdd`\x00\x00\x00\x00+\xb4\xce`\x00\x00\x00\x00,\xa4\xbf`\x00\x00\x00\x00-\x94\xb0`\x00\x00\x00\x00.\x84\xa1`" + - "\x00\x00\x00\x00/t\x92`\x00\x00\x00\x000d\x83`\x00\x00\x00\x001]\xae\xe0\x00\x00\x00\x002r\x89\xe0\x00\x00\x00\x003=\x90\xe0\x00\x00\x00\x004Rk\xe0\x00\x00\x00\x005\x1dr\xe0\x00\x00\x00\x00" + - "62M\xe0\x00\x00\x00\x006\xfdT\xe0\x00\x00\x00\x008\x1bj`\x00\x00\x00\x008\xdd6\xe0\x00\x00\x00\x009\xfbL`\x00\x00\x00\x00:\xbd\x18\xe0\x00\x00\x00\x00;\xdb.`\x00\x00\x00\x00<\xa65`" + - "\x00\x00\x00\x00=\xbb\x10`\x00\x00\x00\x00>\x86\x17`\x00\x00\x00\x00?\x9a\xf2`\x00\x00\x00\x00@e\xf9`\x00\x00\x00\x00A\x84\x0e\xe0\x00\x00\x00\x00BE\xdb`\x00\x00\x00\x00Cc\xf0\xe0\x00\x00\x00\x00" + - "D%\xbd`\x00\x00\x00\x00EC\xd2\xe0\x00\x00\x00\x00F\x05\x9f`\x00\x00\x00\x00G#\xb4\xe0\x00\x00\x00\x00G\xee\xbb\xe0\x00\x00\x00\x00I\x03\x96\xe0\x00\x00\x00\x00IΝ\xe0\x00\x00\x00\x00J\xe3x\xe0" + - "\x00\x00\x00\x00K\xae\u007f\xe0\x00\x00\x00\x00Ḷp\x00\x00\x00\x00M\x8eo\xf0\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x04\x01\x04\x01\x05\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x04\x01\x02\x00\x00.\xf4\x00\x00\x00\x00*0\x00\x04\x00\x008@\x00\b\x00\x00FP\x01\f\x00\x008@\x01\b\x00\x00" + - "*0\x01\x04LMT\x00+03\x00+04\x00+05\x00\n<+04>-4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rk\xa4,\xb6?\x06\x00\x00?\x06\x00\x00\x0e\x00\x1c\x00E" + - "urope/BelfastUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x9f\x00\x00\x00\x05\x00\x00\x00\x11\xff\xff\xff\xff\x1a]\t\xcb\xff\xff\xff\xff\x9b&\xad\xa0\xff\xff\xff\xff\x9b\xd6\x05 \xff\xff\xff\xff\x9c\xcf0\xa0\xff\xff\xff\xff\x9d\xa4à\xff\xff\xff\xff" + - "\x9e\x9c\x9d\xa0\xff\xff\xff\xff\x9f\x97\x1a\xa0\xff\xff\xff\xff\xa0\x85\xba \xff\xff\xff\xff\xa1v\xfc\xa0\xff\xff\xff\xff\xa2e\x9c \xff\xff\xff\xff\xa3{Ƞ\xff\xff\xff\xff\xa4N\xb8\xa0\xff\xff\xff\xff\xa5?\xfb " + - "\xff\xff\xff\xff\xa6%` \xff\xff\xff\xff\xa7'\xc6 \xff\xff\xff\xff\xa8*, \xff\xff\xff\xff\xa8\xeb\xf8\xa0\xff\xff\xff\xff\xaa\x00Ӡ\xff\xff\xff\xff\xaa\xd5\x15 \xff\xff\xff\xff\xab\xe9\xf0 \xff\xff\xff\xff" + - "\xac\xc7l \xff\xff\xff\xff\xad\xc9\xd2 \xff\xff\xff\xff\xae\xa7N \xff\xff\xff\xff\xaf\xa0y\xa0\xff\xff\xff\xff\xb0\x870 \xff\xff\xff\xff\xb1\x92Р\xff\xff\xff\xff\xb2pL\xa0\xff\xff\xff\xff\xb3r\xb2\xa0" + - "\xff\xff\xff\xff\xb4P.\xa0\xff\xff\xff\xff\xb5IZ \xff\xff\xff\xff\xb60\x10\xa0\xff\xff\xff\xff\xb72v\xa0\xff\xff\xff\xff\xb8\x0f\xf2\xa0\xff\xff\xff\xff\xb9\x12X\xa0\xff\xff\xff\xff\xb9\xefԠ\xff\xff\xff\xff" + - "\xba\xe9\x00 \xff\xff\xff\xff\xbb\xd8\xf1 \xff\xff\xff\xff\xbc\xdbW \xff\xff\xff\xff\xbd\xb8\xd3 \xff\xff\xff\xff\xbe\xb1\xfe\xa0\xff\xff\xff\xff\xbf\x98\xb5 \xff\xff\xff\xff\xc0\x9b\x1b \xff\xff\xff\xff\xc1x\x97 " + - "\xff\xff\xff\xff\xc2z\xfd \xff\xff\xff\xff\xc3Xy \xff\xff\xff\xff\xc4Q\xa4\xa0\xff\xff\xff\xff\xc58[ \xff\xff\xff\xff\xc6:\xc1 \xff\xff\xff\xff\xc7X֠\xff\xff\xff\xff\xc7\xda\t\xa0\xff\xff\xff\xff" + - "\xca\x16&\x90\xff\xff\xff\xffʗY\x90\xff\xff\xff\xff\xcb\xd1\x1e\x90\xff\xff\xff\xff\xccw;\x90\xff\xff\xff\xffͱ\x00\x90\xff\xff\xff\xff\xce`X\x10\xff\xff\xff\xffϐ\xe2\x90\xff\xff\xff\xff\xd0n^\x90" + - "\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd1\xfb2\x10\xff\xff\xff\xff\xd2i\xfe \xff\xff\xff\xff\xd3c)\xa0\xff\xff\xff\xff\xd4I\xe0 \xff\xff\xff\xff\xd5\x1e!\xa0\xff\xff\xff\xff\xd5B\xfd\x90\xff\xff\xff\xff" + - "\xd5\xdf\xe0\x10\xff\xff\xff\xff\xd6N\xac \xff\xff\xff\xff\xd6\xfe\x03\xa0\xff\xff\xff\xff\xd8.\x8e \xff\xff\xff\xff\xd8\xf9\x95 \xff\xff\xff\xff\xda\x0ep \xff\xff\xff\xff\xda\xeb\xec \xff\xff\xff\xff\xdb\xe5\x17\xa0" + - "\xff\xff\xff\xff\xdc\xcb\xce \xff\xff\xff\xff\xdd\xc4\xf9\xa0\xff\xff\xff\xff\u07b4\xea\xa0\xff\xff\xff\xff߮\x16 \xff\xff\xff\xff\xe0\x94̠\xff\xff\xff\xff\xe1rH\xa0\xff\xff\xff\xff\xe2kt \xff\xff\xff\xff" + - "\xe3R*\xa0\xff\xff\xff\xff\xe4T\x90\xa0\xff\xff\xff\xff\xe52\f\xa0\xff\xff\xff\xff\xe6=\xad \xff\xff\xff\xff\xe7\x1b) \xff\xff\xff\xff\xe8\x14T\xa0\xff\xff\xff\xff\xe8\xfb\v \xff\xff\xff\xff\xe9\xfdq " + - "\xff\xff\xff\xff\xea\xda\xed \xff\xff\xff\xff\xeb\xddS \xff\xff\xff\xff\xec\xba\xcf \xff\xff\xff\xff\xed\xb3\xfa\xa0\xff\xff\xff\xff\ue6b1 \xff\xff\xff\xff\xef\x81g\xa0\xff\xff\xff\xff\xf0\x9f} \xff\xff\xff\xff" + - "\xf1aI\xa0\xff\xff\xff\xff\xf2\u007f_ \xff\xff\xff\xff\xf3Jf \xff\xff\xff\xff\xf4_A \xff\xff\xff\xff\xf5!\r\xa0\xff\xff\xff\xff\xf6?# \xff\xff\xff\xff\xf7\x00\xef\xa0\xff\xff\xff\xff\xf8\x1f\x05 " + - "\xff\xff\xff\xff\xf8\xe0Ѡ\xff\xff\xff\xff\xf9\xfe\xe7 \xff\xff\xff\xff\xfa\xc0\xb3\xa0\xff\xff\xff\xff\xfb\xe8\x03\xa0\xff\xff\xff\xff\xfc{\xab\xa0\xff\xff\xff\xff\xfdǻp\x00\x00\x00\x00\x03p\xc6 \x00\x00\x00\x00" + - "\x04)X \x00\x00\x00\x00\x05P\xa8 \x00\x00\x00\x00\x06\t: \x00\x00\x00\x00\a0\x8a \x00\x00\x00\x00\a\xe9\x1c \x00\x00\x00\x00\t\x10l \x00\x00\x00\x00\t\xc8\xfe \x00\x00\x00\x00\n\xf0N " + - "\x00\x00\x00\x00\v\xb2\x1a\xa0\x00\x00\x00\x00\f\xd00 \x00\x00\x00\x00\r\x91\xfc\xa0\x00\x00\x00\x00\x0e\xb0\x12 \x00\x00\x00\x00\x0fqޠ\x00\x00\x00\x00\x10\x99.\xa0\x00\x00\x00\x00\x11Q\xc0\xa0\x00\x00\x00\x00" + - "\x12y\x10\xa0\x00\x00\x00\x00\x131\xa2\xa0\x00\x00\x00\x00\x14X\xf2\xa0\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x168Ɛ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x18\x18\xa8\x90\x00\x00\x00\x00\x18㯐" + - "\x00\x00\x00\x00\x19\xf8\x8a\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xe1\xa7\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\xc1\x89\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f\xa1k\x10\x00\x00\x00\x00" + - " lr\x10\x00\x00\x00\x00!\x81M\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#a/\x10\x00\x00\x00\x00$,6\x10\x00\x00\x00\x00%JK\x90\x00\x00\x00\x00&\f\x18\x10\x00\x00\x00\x00'*-\x90" + - "\x00\x00\x00\x00'\xf54\x90\x00\x00\x00\x00)\n\x0f\x90\x00\x00\x00\x00)\xd5\x16\x90\x00\x00\x00\x00*\xe9\xf1\x90\x00\x00\x00\x00+\xb4\xf8\x90\x00\x00\x00\x00,\xc9Ӑ\x00\x00\x00\x00-\x94ڐ\x00\x00\x00\x00" + - ".\xa9\xb5\x90\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000\x89\x97\x90\x00\x00\x00\x001]\xd9\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x02\x01\x02\x01\x03\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\xff\xff\xff\xb5\x00\x00\x00\x00\x0e\x10\x01\x04\x00\x00\x00\x00\x00\b\x00\x00\x1c \x01\f\x00\x00\x0e\x10\x00\x04LMT\x00BST\x00GMT\x00BDST\x00\nGMT0B" + - "ST,M3.5.0/1,M10.5.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Ro\xbc\x831O\x04\x00\x00O\x04\x00\x00\x0f\x00\x1c\x00Europe/Bru" + - "sselsUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f" + - "\x00\x00\x00\x06\x00\x00\x00\x1a\xff\xff\xff\xffV\xb6\xdf\xe6\xff\xff\xff\xffm\xe8\xc8\x00\xff\xff\xff\xff\x98DI\x80\xff\xff\xff\xff\x9b\f%p\xff\xff\xff\xff\x9b\xd5\xda\xf0\xff\xff\xff\xff\x9cٮ\x90\xff\xff\xff\xff" + - "\x9d\xa4\xb5\x90\xff\xff\xff\xff\x9e\xb9\x90\x90\xff\xff\xff\xff\x9f\x84\x97\x90\xff\xff\xff\xff\x9f\xce\xf80\xff\xff\xff\xff\xa0`\xa5\xf0\xff\xff\xff\xff\xa1~\xbbp\xff\xff\xff\xff\xa2.\x12\xf0\xff\xff\xff\xff\xa3zL\xf0" + - "\xff\xff\xff\xff\xa45\x81\xf0\xff\xff\xff\xff\xa5^#p\xff\xff\xff\xff\xa6%5\xf0\xff\xff\xff\xff\xa7'\x9b\xf0\xff\xff\xff\xff\xa8*\x01\xf0\xff\xff\xff\xff\xa9\a}\xf0\xff\xff\xff\xff\xa9\xee4p\xff\xff\xff\xff" + - "\xaa\xe7_\xf0\xff\xff\xff\xff\xab\xd7P\xf0\xff\xff\xff\xff\xac\xc7A\xf0\xff\xff\xff\xff\xadɧ\xf0\xff\xff\xff\xff\xae\xa7#\xf0\xff\xff\xff\xff\xaf\xa0Op\xff\xff\xff\xff\xb0\x87\x05\xf0\xff\xff\xff\xff\xb1\x89k\xf0" + - "\xff\xff\xff\xff\xb2pL\xa0\xff\xff\xff\xff\xb3r\xb2\xa0\xff\xff\xff\xff\xb4P.\xa0\xff\xff\xff\xff\xb5IZ \xff\xff\xff\xff\xb60\x10\xa0\xff\xff\xff\xff\xb72v\xa0\xff\xff\xff\xff\xb8\x0f\xf2\xa0\xff\xff\xff\xff" + - "\xb8\xff\xe3\xa0\xff\xff\xff\xff\xb9\xefԠ\xff\xff\xff\xff\xba\u058b \xff\xff\xff\xff\xbb\xd8\xf1 \xff\xff\xff\xff\xbc\xc8\xe2 \xff\xff\xff\xff\xbd\xb8\xd3 \xff\xff\xff\xff\xbe\x9f\x89\xa0\xff\xff\xff\xff\xbf\x98\xb5 " + - "\xff\xff\xff\xff\xc0\x9b\x1b \xff\xff\xff\xff\xc1x\x97 \xff\xff\xff\xff\xc2h\x88 \xff\xff\xff\xff\xc3Xy \xff\xff\xff\xff\xc4?/\xa0\xff\xff\xff\xff\xc58[ \xff\xff\xff\xff\xc6:\xc1 \xff\xff\xff\xff" + - "\xc7X֠\xff\xff\xff\xff\xc7\xda\t\xa0\xff\xff\xff\xff\xc8J\x19 \xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xff\xd0n^\x90" + - "\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd2N@\x90\xff\xff\xff\xffӑ@\x10\xff\xff\xff\xff\xd4K#\x90\x00\x00\x00\x00\r\xa4c\x90\x00\x00\x00\x00\x0e\x8b\x1a\x10\x00\x00\x00\x00\x0f\x84E\x90\x00\x00\x00\x00" + - "\x10t6\x90\x00\x00\x00\x00\x11d'\x90\x00\x00\x00\x00\x12T\x18\x90\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐" + - "\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00" + - "\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#\x86%p\x00\x00\x00\x00?\x9b\x00" + - "p\x00\x00\x00\x00@f\ap\x00\x00\x00\x00A\x84\x1c\xf0\x00\x00\x00\x00BE\xe9p\x00\x00\x00\x00Cc\xfe\xf0\x00\x00\x00\x00D%\xcbp\x00\x00\x00\x00EC\xe0\xf0\x00\x00\x00\x00F\x05\xadp\x00\x00\x00" + - "\x00G#\xc2\xf0\x00\x00\x00\x00G\xee\xc9\xf0\x00\x00\x00\x00I\x03\xa4\xf0\x00\x00\x00\x00IΫ\xf0\x00\x00\x00\x00J\xe3\x86\xf0\x00\x00\x00\x00K\xae\x8d\xf0\x00\x00\x00\x00Ḷp\x00\x00\x00\x00M\x8eo" + - "\xf0\x00\x00\x00\x00TL\x1d`\x00\x00\x00\x00[\xd4\xed\xf0\x00\x00\x00\x00_\xe7\xb2`\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x04\x01\x04\x01\x04\x01\x02\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01" + - "\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x02\x01\x02\x01\x00\x00)\xa4\x00\x00\x00\x00*0\x00\x04\x00\x008@\x00\b\x00\x00FP\x01\f\x00\x008@\x01\b" + - "LMT\x00+03\x00+04\x00+05\x00\n<+03>-3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RO+j\x94\x88\x03\x00\x00\x88\x03\x00\x00\x12\x00\x1c\x00Europ" + - "e/KaliningradUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00P\x00\x00\x00\b\x00\x00\x00\"\xff\xff\xff\xffo\xa2[H\xff\xff\xff\xff\x9b\f\x17`\xff\xff\xff\xff\x9b\xd5\xda\xf0\xff\xff\xff\xff\x9cٮ\x90\xff\xff\xff\xff\x9d\xa4\xb5\x90\xff\xff\xff\xff" + - "\x9e\xb9\x90\x90\xff\xff\xff\xff\x9f\x84\x97\x90\xff\xff\xff\xff\xc8\tq\x90\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЂ%\x10" + - "\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd1|w\xe0\xff\xff\xff\xffѕ\x84`\xff\xff\xff\xffҊ\xadP\xff\xff\xff\xff\xd3Y\xb6\xe0\x00\x00\x00\x00\x15'\xa7\xd0\x00\x00\x00\x00\x16\x18\xdc@\x00\x00\x00\x00" + - "\x17\b\xdbP\x00\x00\x00\x00\x17\xfa\x0f\xc0\x00\x00\x00\x00\x18\xea\x0e\xd0\x00\x00\x00\x00\x19\xdbC@\x00\x00\x00\x00\x1a̓\xd0\x00\x00\x00\x00\x1b\xbc\xa0\xf0\x00\x00\x00\x00\x1c\xac\x91\xf0\x00\x00\x00\x00\x1d\x9c\x82\xf0" + - "\x00\x00\x00\x00\x1e\x8cs\xf0\x00\x00\x00\x00\x1f|d\xf0\x00\x00\x00\x00 lU\xf0\x00\x00\x00\x00!\\F\xf0\x00\x00\x00\x00\"L7\xf0\x00\x00\x00\x00#<(\xf0\x00\x00\x00\x00$,\x19\xf0\x00\x00\x00\x00" + - "%\x1c\x19\x00\x00\x00\x00\x00&\f\n\x00\x00\x00\x00\x00'\x055\x80\x00\x00\x00\x00'\xf5&\x80\x00\x00\x00\x00(\xe5\x17\x80\x00\x00\x00\x00)\xd5\b\x80\x00\x00\x00\x00*\xc4\xf9\x80\x00\x00\x00\x00+\xb4\xea\x80" + - "\x00\x00\x00\x00,\xa4ۀ\x00\x00\x00\x00-\x94̀\x00\x00\x00\x00.\x84\xbd\x80\x00\x00\x00\x00/t\xae\x80\x00\x00\x00\x000d\x9f\x80\x00\x00\x00\x001]\xcb\x00\x00\x00\x00\x002r\xa6\x00\x00\x00\x00\x00" + - "3=\xad\x00\x00\x00\x00\x004R\x88\x00\x00\x00\x00\x005\x1d\x8f\x00\x00\x00\x00\x0062j\x00\x00\x00\x00\x006\xfdq\x00\x00\x00\x00\x008\x1b\x86\x80\x00\x00\x00\x008\xddS\x00\x00\x00\x00\x009\xfbh\x80" + - "\x00\x00\x00\x00:\xbd5\x00\x00\x00\x00\x00;\xdbJ\x80\x00\x00\x00\x00<\xa6Q\x80\x00\x00\x00\x00=\xbb,\x80\x00\x00\x00\x00>\x863\x80\x00\x00\x00\x00?\x9b\x0e\x80\x00\x00\x00\x00@f\x15\x80\x00\x00\x00\x00" + - "A\x84+\x00\x00\x00\x00\x00BE\xf7\x80\x00\x00\x00\x00Cd\r\x00\x00\x00\x00\x00D%ـ\x00\x00\x00\x00EC\xef\x00\x00\x00\x00\x00F\x05\xbb\x80\x00\x00\x00\x00G#\xd1\x00\x00\x00\x00\x00G\xee\xd8\x00" + - "\x00\x00\x00\x00I\x03\xb3\x00\x00\x00\x00\x00Iκ\x00\x00\x00\x00\x00J\xe3\x95\x00\x00\x00\x00\x00K\xae\x9c\x00\x00\x00\x00\x00Ḻ\x80\x00\x00\x00\x00M\x8e~\x00\x00\x00\x00\x00TL+p\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x04\x03\x04\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04" + - "\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\a\x04\x00\x00\x138\x00\x00\x00\x00\x1c \x01\x04\x00\x00\x0e\x10\x00\t\x00\x00*0\x01\r\x00\x00\x1c \x00\x12\x00\x008@\x01\x16\x00\x00*0\x00\x1a\x00\x00" + - "*0\x00\x1eLMT\x00CEST\x00CET\x00EEST\x00EET\x00MSD\x00MSK\x00+03\x00\nEET-2\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xe1" + - "C\xf9\xa1\xde\x01\x00\x00\xde\x01\x00\x00\x0f\x00\x1c\x00Europe/BelgradeUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZ" + - "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$\x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff\xff^<\xf0H\xff\xff\xff\xff\xca\x025\xe0\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff" + - "\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff\xffѡ\x8c\x10\xff\xff\xff\xff\xd2N@\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ" + - "\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00" + - "\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#1\x90\xff\xff\xff\xff\xd4I\xd2\x10\xff\xff\xff\xff\xd5\x1d\xf7p\xff\xff\xff\xff\xd6)\x97\xf0\xff\xff\xff\xff\xd6뀐\xff\xff\xff\xff" + - "\xd8\t\x96\x10\xff\xff\xff\xff\xf93\xb5\xf0\xff\xff\xff\xff\xf9\xd9\xc4\xe0\xff\xff\xff\xff\xfb\x1c\xd2p\xff\xff\xff\xff\xfb\xb9\xb4\xf0\xff\xff\xff\xff\xfc\xfc\xb4p\xff\xff\xff\xff\xfd\x99\x96\xf0\xff\xff\xff\xff\xfe\xe5\xd0\xf0" + - "\xff\xff\xff\xff\xff\x82\xb3p\x00\x00\x00\x00\x00Ų\xf0\x00\x00\x00\x00\x01b\x95p\x00\x00\x00\x00\x02\x9cZp\x00\x00\x00\x00\x03Bwp\x00\x00\x00\x00\x04\x85v\xf0\x00\x00\x00\x00\x05+\x93\xf0\x00\x00\x00\x00" + - "\x06\x1a3p\x00\x00\x00\x00\a\n$p\x00\x00\x00\x00\b\x17\x16p\x00\x00\x00\x00\b\xda4p\x00\x00\x00\x00\t\xf7\x14\x90\x00\x00\x00\x00\n\xc2\r\x80\x00\x00\x00\x00\v\xd6\xf6\x90\x00\x00\x00\x00\f\xa1\xef\x80" + - "\x00\x00\x00\x00\r\xb6ؐ\x00\x00\x00\x00\x0e\x81р\x00\x00\x00\x00\x0f\x96\xba\x90\x00\x00\x00\x00\x10a\xb3\x80\x00\x00\x00\x00\x11v\x9c\x90\x00\x00\x00\x00\x12A\x95\x80\x00\x00\x00\x00\x13E[\x10\x00\x00\x00\x00" + - "\x14*\xb2\x00\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90" + - "\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00" + - "\"LT\x10\x00\x00\x00\x00#\x86%p\x00\x00\x00\x00?\x9b\x00p\x00\x00\x00\x00@f\ap\x00\x00\x00\x00A\x84\x1c\xf0\x00\x00\x00\x00BE\xe9p\x00\x00\x00\x00Cc\xfe\xf0\x00\x00\x00\x00D" + - "%\xcbp\x00\x00\x00\x00EC\xe0\xf0\x00\x00\x00\x00F\x05\xadp\x00\x00\x00\x00G#\xc2\xf0\x00\x00\x00\x00G\xee\xc9\xf0\x00\x00\x00\x00I\x03\xa4\xf0\x00\x00\x00\x00IΫ\xf0\x00\x00\x00\x00J\xe3\x86\xf0\x00" + - "\x00\x00\x00K\xae\x8d\xf0\x00\x00\x00\x00Ḷp\x00\x00\x00\x00M\x8eo\xf0\x00\x00\x00\x00TL\x1d`\x00\x00\x00\x00V\xf7\x14p\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x04" + - "\x01\x03\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x03\x01\x03\x00\x00-\f\x00\x00\x00\x00*0\x00\x04\x00\x00FP\x01" + - "\b\x00\x008@\x00\f\x00\x008@\x01\fLMT\x00+03\x00+05\x00+04\x00\n<+04>-4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xea\xc48\xde\\\x02\x00\x00" + - "\\\x02\x00\x00\r\x00\x1c\x00Europe/TiraneUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x002\x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff\xff\x96\xaa4h\xff\xff\xff\xff\xc8m\x87p\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff" + - "\u0378\xe9\x90\x00\x00\x00\x00\b(9\xf0\x00\x00\x00\x00\b\xef>`\x00\x00\x00\x00\n\x05x\xf0\x00\x00\x00\x00\n\xd0q\xe0\x00\x00\x00\x00\v\xe9Op\x00\x00\x00\x00\f\xb4H`\x00\x00\x00\x00\r\xd2k\xf0" + - "\x00\x00\x00\x00\x0e\x94*`\x00\x00\x00\x00\x0f\xb0\xfcp\x00\x00\x00\x00\x10t\f`\x00\x00\x00\x00\x11\x90\xdep\x00\x00\x00\x00\x12S\xee`\x00\x00\x00\x00\x13p\xc0p\x00\x00\x00\x00\x14;\xb9`\x00\x00\x00\x00" + - "\x15H\xb9p\x00\x00\x00\x00\x16\x13\xb2`\x00\x00\x00\x00\x171\xd5\xf0\x00\x00\x00\x00\x17\xfc\xce\xe0\x00\x00\x00\x00\x19\x00\x94p\x00\x00\x00\x00\x19\xdb_`\x00\x00\x00\x00\x1a̯\xf0\x00\x00\x00\x00\x1b\xbc\xbd\x10" + - "\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00" + - "#(\xe8L\xff\xff\xff\xffp\xbc\x81p\xff\xff\xff\xff\x9b8\xf8p\xff\xff\xff\xff\x9b\xd5\xcc\xe0\xff\xff\xff\xff\x9c\xc5\xcb\xf0\xff\xff\xff\xff\x9d\xb7\x00`\xff\xff\xff\xff\x9e\x89" + - "\xfep\xff\xff\xff\xff\x9f\xa0\x1c\xe0\xff\xff\xff\xff\xa0`\xa5\xf0\xff\xff\xff\xff\xa1~\xad`\xff\xff\xff\xff\xa2\\7p\xff\xff\xff\xff\xa3L\x1a`\xff\xff\xff\xff\xc8l5\xf0\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff" + - "\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xff\xd0n^\x90\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd2L\xd2\xf0\xff\xff\xff\xff\xd3>1\x90\xff\xff\xff\xff\xd4I" + - "\xd2\x10\xff\xff\xff\xff\xd5\x1d\xf7p\xff\xff\xff\xff\xd6)\x97\xf0\xff\xff\xff\xff\xd6뀐\xff\xff\xff\xff\xd8\t\x96\x10\xff\xff\xff\xff\xf93\xb5\xf0\xff\xff\xff\xff\xf9\xd9\xc4\xe0\xff\xff\xff\xff\xfb\x1c\xd2p\xff\xff" + - "\xff\xff\xfb\xb9\xb4\xf0\xff\xff\xff\xff\xfc\xfc\xb4p\xff\xff\xff\xff\xfd\x99\x96\xf0\xff\xff\xff\xff\xfe\xe5\xd0\xf0\xff\xff\xff\xff\xff\x82\xb3p\x00\x00\x00\x00\x00Ų\xf0\x00\x00\x00\x00\x01b\x95p\x00\x00\x00\x00\x02\x9c" + - "Zp\x00\x00\x00\x00\x03Bwp\x00\x00\x00\x00\x04\x85v\xf0\x00\x00\x00\x00\x05+\x93\xf0\x00\x00\x00\x00\x06n\x93p\x00\x00\x00\x00\a\vu\xf0\x00\x00\x00\x00\bE:\xf0\x00\x00\x00\x00\b\xebW\xf0\x00\x00" + - "\x00\x00\n.Wp\x00\x00\x00\x00\n\xcb9\xf0\x00\x00\x00\x00\f\x0e9p\x00\x00\x00\x00\f\xab\x1b\xf0\x00\x00\x00\x00\r\xe4\xe0\xf0\x00\x00\x00\x00\x0e\x8a\xfd\xf0\x00\x00\x00\x00\x0f\xcd\xfdp\x00\x00\x00\x00\x10t" + - "\x1ap\x00\x00\x00\x00\x11\xad\xdfp\x00\x00\x00\x00\x12S\xfcp\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00" + - "\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c" + - "\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#(\xe8L\xff\xff\xff\xffp\xbc\x81p\xff\xff\xff\xff\x9b8\xf8p\xff\xff\xff\xff\x9b\xd5\xcc\xe0\xff\xff\xff\xff\x9c\xc5\xcb\xf0\xff\xff\xff\xff\x9d\xb7\x00`\xff\xff" + - "\xff\xff\x9e\x89\xfep\xff\xff\xff\xff\x9f\xa0\x1c\xe0\xff\xff\xff\xff\xa0`\xa5\xf0\xff\xff\xff\xff\xa1~\xad`\xff\xff\xff\xff\xa2\\7p\xff\xff\xff\xff\xa3L\x1a`\xff\xff\xff\xff\xc8l5\xf0\xff\xff\xff\xff\xcc\xe7" + - "K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xff\xd0n^\x90\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd2L\xd2\xf0\xff\xff\xff\xff\xd3>1\x90\xff\xff" + - "\xff\xff\xd4I\xd2\x10\xff\xff\xff\xff\xd5\x1d\xf7p\xff\xff\xff\xff\xd6)\x97\xf0\xff\xff\xff\xff\xd6뀐\xff\xff\xff\xff\xd8\t\x96\x10\xff\xff\xff\xff\xf93\xb5\xf0\xff\xff\xff\xff\xf9\xd9\xc4\xe0\xff\xff\xff\xff\xfb\x1c" + - "\xd2p\xff\xff\xff\xff\xfb\xb9\xb4\xf0\xff\xff\xff\xff\xfc\xfc\xb4p\xff\xff\xff\xff\xfd\x99\x96\xf0\xff\xff\xff\xff\xfe\xe5\xd0\xf0\xff\xff\xff\xff\xff\x82\xb3p\x00\x00\x00\x00\x00Ų\xf0\x00\x00\x00\x00\x01b\x95p\x00\x00" + - "\x00\x00\x02\x9cZp\x00\x00\x00\x00\x03Bwp\x00\x00\x00\x00\x04\x85v\xf0\x00\x00\x00\x00\x05+\x93\xf0\x00\x00\x00\x00\x06n\x93p\x00\x00\x00\x00\a\vu\xf0\x00\x00\x00\x00\bE:\xf0\x00\x00\x00\x00\b\xeb" + - "W\xf0\x00\x00\x00\x00\n.Wp\x00\x00\x00\x00\n\xcb9\xf0\x00\x00\x00\x00\f\x0e9p\x00\x00\x00\x00\f\xab\x1b\xf0\x00\x00\x00\x00\r\xe4\xe0\xf0\x00\x00\x00\x00\x0e\x8a\xfd\xf0\x00\x00\x00\x00\x0f\xcd\xfdp\x00\x00" + - "\x00\x00\x10t\x1ap\x00\x00\x00\x00\x11\xad\xdfp\x00\x00\x00\x00\x12S\xfcp\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03" + - "͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00" + - "\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#\x863\x80\x00\x00\x00\x00?\x9b\x0e\x80\x00\x00\x00\x00@f\x15\x80\x00\x00\x00\x00A\x84+\x00\x00\x00\x00\x00BE\xf7\x80\x00\x00\x00\x00Cd\r\x00\x00\x00\x00\x00D%ـ\x00\x00" + - "\x00\x00EC\xef\x00\x00\x00\x00\x00F\x05\xbb\x80\x00\x00\x00\x00G#\xd1\x00\x00\x00\x00\x00G\xee\xd8\x00\x00\x00\x00\x00I\x03\xb3\x00\x00\x00\x00\x00Iκ\x00\x00\x00\x00\x00J\xe3\x95\x00\x00\x00\x00\x00K\xae" + - "\x9c\x00\x00\x00\x00\x00Ḻ\x80\x00\x00\x00\x00M\x8e~\x00\x01\x02\x03\x05\x04\x05\x04\x05\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a" + - "\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\b\x00\x00\x19\xd8\x00\x00\x00\x00\x19\xc8\x00\x04\x00\x00\x1c \x00\b\x00\x00*0\x00\f\x00\x00\x0e\x10\x00\x10\x00\x00\x1c " + - "\x01\x14\x00\x008@\x01\x19\x00\x00*0\x01\x1d\x00\x00*0\x00\"LMT\x00MMT\x00EET\x00MSK\x00CET\x00CEST\x00MSD\x00EEST\x00+03\x00\n<" + - "+03>-3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RZk#V\x81\x03\x00\x00\x81\x03\x00\x00\r\x00\x1c\x00Europe/MadridUT\t\x00\x03\x15\xac\x0e`\x15" + - "\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00" + - "\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00O\x00\x00\x00\x06\x00\x00\x00\x1b\xff\xff\xff\xff~6\xb5" + - "\x00\xff\xff\xff\xff\x9e\xba\xc5\xf0\xff\xff\xff\xff\x9f\xa09\x00\xff\xff\xff\xff\xa0\x90\x1b\xf0\xff\xff\xff\xff\xa1\x81l\x80\xff\xff\xff\xff\xaa\x05\xefp\xff\xff\xff\xff\xaa\xe7n\x00\xff\xff\xff\xff\xadɧ\xf0\xff\xff\xff" + - "\xff\xae\xa72\x00\xff\xff\xff\xff\xaf\xa0Op\xff\xff\xff\xff\xb0\x87\x14\x00\xff\xff\xff\xff\xb1\x89z\x00\xff\xff\xff\xff\xb2p0\x80\xff\xff\xff\xff\xb3r\x88p\xff\xff\xff\xff\xb4P\x12\x80\xff\xff\xff\xff\xc2\xc9\xec" + - "\xf0\xff\xff\xff\xff\xc3X]\x00\xff\xff\xff\xff\xc4H?\xf0\xff\xff\xff\xff\xc4m\x1b\xe0\xff\xff\xff\xff\xc59t`\xff\xff\xff\xff\xc7![\x80\xff\xff\xff\xff\xc7\xf5\x8e\xf0\xff\xff\xff\xff\xcb\xf5\xde`\xff\xff\xff" + - "\xff̕q\xf0\xff\xff\xff\xff\xcd\xc3K`\xff\xff\xff\xffΠ\xd5p\xff\xff\xff\xffϣ-`\xff\xff\xff\xffЀ\xb7p\xff\xff\xff\xffу\x0f`\xff\xff\xff\xff\xd2`\x99p\xff\xff\xff\xff\xd3b\xf1" + - "`\xff\xff\xff\xff\xd4@{p\xff\xff\xff\xff\xd9\x1eF\xe0\xff\xff\xff\xff\xd9\xe9[\xf0\x00\x00\x00\x00\b\r\xcd\xe0\x00\x00\x00\x00\b\xf4\x92p\x00\x00\x00\x00\t\xed\xaf\xe0\x00\x00\x00\x00\n\xd4tp\x00\x00\x00" + - "\x00\v\xbb\x1c\xe0\x00\x00\x00\x00\f\xab\x1b\xf0\x00\x00\x00\x00\r\xa49`\x00\x00\x00\x00\x0e\x8a\xfd\xf0\x00\x00\x00\x00\x0f\x84E\x90\x00\x00\x00\x00\x10t6\x90\x00\x00\x00\x00\x11d'\x90\x00\x00\x00\x00\x12T\x18" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x81\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff^=v\xec\xff\xff\xff\xff\x9e\xb8\xbd\xa0\xff\xff\xff\xff\x9f\xbb\x15\x90\xff\xff\xff\xffˉ\x1a" + + "\xa0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a&\x10\xff\xff\xff\xff\xd3v\x0f \xff\xff\xff\xff\xd4A\b\x10\xff\xff\xff\xff\xd5U\xf1 \xff\xff\xff\xff\xd6 \xea\x10\xff\xff\xff\xff\xd75\xd3 \xff\xff\xff" + + "\xff\xd8\x00\xcc\x10\xff\xff\xff\xff\xd9\x15\xb5 \xff\xff\xff\xff\xd9\xe0\xae\x10\xff\xff\xff\xff\xda\xfeѠ\xff\xff\xff\xff\xdb\xc0\x90\x10\xff\xff\xff\xff\xdc\u07b3\xa0\xff\xff\xff\xffݩ\xac\x90\xff\xff\xff\xff\u07be\x95" + + "\xa0\xff\xff\xff\xff߉\x8e\x90\xff\xff\xff\xff\xe0\x9ew\xa0\xff\xff\xff\xff\xe1ip\x90\xff\xff\xff\xff\xe2~Y\xa0\xff\xff\xff\xff\xe3IR\x90\xff\xff\xff\xff\xe4^;\xa0\xff\xff\xff\xff\xe5)4\x90\xff\xff\xff" + + "\xff\xe6GX \xff\xff\xff\xff\xe7\x12Q\x10\xff\xff\xff\xff\xe8': \xff\xff\xff\xff\xe8\xf23\x10\xff\xff\xff\xff\xea\a\x1c \xff\xff\xff\xff\xea\xd2\x15\x10\xff\xff\xff\xff\xeb\xe6\xfe \xff\xff\xff\xff\xec\xb1\xf7" + + "\x10\xff\xff\xff\xff\xed\xc6\xe0 \xff\xff\xff\xff\xee\x91\xd9\x10\xff\xff\xff\xff\xef\xaf\xfc\xa0\xff\xff\xff\xff\xf0q\xbb\x10\xff\xff\xff\xff\xf1\x8fޠ\xff\xff\xff\xff\xf2\u007f\xc1\x90\xff\xff\xff\xff\xf3o\xc0\xa0\xff\xff\xff" + + "\xff\xf4_\xa3\x90\xff\xff\xff\xff\xf5O\xa2\xa0\xff\xff\xff\xff\xf6?\x85\x90\xff\xff\xff\xff\xf7/\x84\xa0\xff\xff\xff\xff\xf8(\xa2\x10\xff\xff\xff\xff\xf9\x0ff\xa0\xff\xff\xff\xff\xfa\b\x84\x10\xff\xff\xff\xff\xfa\xf8\x83" + + " \xff\xff\xff\xff\xfb\xe8f\x10\xff\xff\xff\xff\xfc\xd8e \xff\xff\xff\xff\xfd\xc8H\x10\xff\xff\xff\xff\xfe\xb8G \xff\xff\xff\xff\xff\xa8*\x10\x00\x00\x00\x00\x00\x98) \x00\x00\x00\x00\x01\x88\f\x10\x00\x00\x00" + + "\x00\x02x\v \x00\x00\x00\x00\x03q(\x90\x00\x00\x00\x00\x04a'\xa0\x00\x00\x00\x00\x05Q\n\x90\x00\x00\x00\x00\x06A\t\xa0\x00\x00\x00\x00\a0\xec\x90\x00\x00\x00\x00\b \xeb\xa0\x00\x00\x00\x00\t\x10\xce" + + "\x90\x00\x00\x00\x00\n\x00͠\x00\x00\x00\x00\n\xf0\xb0\x90\x00\x00\x00\x00\v\u0be0\x00\x00\x00\x00\f\xd9\xcd\x10\x00\x00\x00\x00\r\xc0\x91\xa0\x00\x00\x00\x00\x0e\xb9\xaf\x10\x00\x00\x00\x00\x0f\xa9\xae \x00\x00\x00" + + "\x00\x10\x99\x91\x10\x00\x00\x00\x00\x11\x89\x90 \x00\x00\x00\x00\x12ys\x10\x00\x00\x00\x00\x13ir \x00\x00\x00\x00\x14YU\x10\x00\x00\x00\x00\x15IT \x00\x00\x00\x00\x1697\x10\x00\x00\x00\x00\x17)6" + + " \x00\x00\x00\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18 \x00\x00\x00\x00\x1a\x025\x90\x00\x00\x00\x00\x1a\xf24\xa0\x00\x00\x00\x00\x1b\xe2\x17\x90\x00\x00\x00\x00\x1c\xd2\x16\xa0\x00\x00\x00\x00\x1d\xc1\xf9\x90\x00\x00\x00" + + "\x00\x1e\xb1\xf8\xa0\x00\x00\x00\x00\x1f\xa1ې\x00\x00\x00\x00 v+ \x00\x00\x00\x00!\x81\xbd\x90\x00\x00\x00\x00\"V\r \x00\x00\x00\x00#j\xda\x10\x00\x00\x00\x00$5\xef \x00\x00\x00\x00%J\xbc" + + "\x10\x00\x00\x00\x00&\x15\xd1 \x00\x00\x00\x00'*\x9e\x10\x00\x00\x00\x00'\xfe\xed\xa0\x00\x00\x00\x00)\n\x80\x10\x00\x00\x00\x00)\xdeϠ\x00\x00\x00\x00*\xeab\x10\x00\x00\x00\x00+\xbe\xb1\xa0\x00\x00\x00" + + "\x00,\xd3~\x90\x00\x00\x00\x00-\x9e\x93\xa0\x00\x00\x00\x00.\xb3`\x90\x00\x00\x00\x00/~u\xa0\x00\x00\x00\x000\x93B\x90\x00\x00\x00\x001g\x92 \x00\x00\x00\x002s$\x90\x00\x00\x00\x003Gt" + + " \x00\x00\x00\x004S\x06\x90\x00\x00\x00\x005'V \x00\x00\x00\x0062\xe8\x90\x00\x00\x00\x007\a8 \x00\x00\x00\x008\x1c\x05\x10\x00\x00\x00\x008\xe7\x1a \x00\x00\x00\x009\xfb\xe7\x10\x00\x00\x00" + + "\x00:\xc6\xfc \x00\x00\x00\x00;\xdb\xc9\x10\x00\x00\x00\x00<\xb0\x18\xa0\x00\x00\x00\x00=\xbb\xab\x10\x00\x00\x00\x00>\x8f\xfa\xa0\x00\x00\x00\x00?\x9b\x8d\x10\x00\x00\x00\x00@oܠ\x00\x00\x00\x00A\x84\xa9" + + "\x90\x00\x00\x00\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b\x90\x00\x00\x00\x00D/\xa0\xa0\x00\x00\x00\x00EDm\x90\x00\x00\x00\x00E\xf3\xd3 \x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\x8c\x94\x00\x00\xff\xff\x9d\x90" + + "\x01\x04\xff\xff\x8f\x80\x00\b\xff\xff\x9d\x90\x01\f\xff\xff\x9d\x90\x01\x10LMT\x00PDT\x00PST\x00PWT\x00PPT\x00\nPST8PDT,M3.2.0,M11." + + "1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS?_p\x99\x0e\x05\x00\x00\x0e\x05\x00\x00\x0e\x00\x1c\x00Canada/CentralUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8b" + + "aux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01" + + "\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00}\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xffd䰔\xff" + + "\xff\xff\xff\x9b\x01\xfb\xe0\xff\xff\xff\xff\x9búP\xff\xff\xff\xff\x9e\xb8\xa1\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\u00a0;\x80\xff\xff\xff\xff\xc3O\x84\xf0\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2" + + "#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xffӈh\x00\xff\xff\xff\xff\xd4S`\xf0\xff\xff\xff\xff\xd5U\xd5\x00\xff\xff\xff\xff\xd6 \xcd\xf0\xff\xff\xff\xff\xd75\xb7\x00\xff\xff\xff\xff\xd8\x00\xaf\xf0\xff" + + "\xff\xff\xff\xd9\x15\x99\x00\xff\xff\xff\xff\xd9\xe0\x91\xf0\xff\xff\xff\xff\xdb\x00\a\x00\xff\xff\xff\xff\xdb\xc8\\\xf0\xff\xff\xff\xff\xdcޗ\x80\xff\xff\xff\xffݩ\x90p\xff\xff\xff\xff\u07bey\x80\xff\xff\xff\xff\xdf" + + "\x89rp\xff\xff\xff\xff\xe0\x9e[\x80\xff\xff\xff\xff\xe1iTp\xff\xff\xff\xff\xe2~=\x80\xff\xff\xff\xff\xe3I6p\xff\xff\xff\xff\xe4^\x1f\x80\xff\xff\xff\xff\xe5)\x18p\xff\xff\xff\xff\xe6G<\x00\xff" + + "\xff\xff\xff\xe7\x124\xf0\xff\xff\xff\xff\xe8'\x1e\x00\xff\xff\xff\xff\xe8\xf2\x16\xf0\xff\xff\xff\xff\xea\a\x00\x00\xff\xff\xff\xff\xea\xd1\xf8\xf0\xff\xff\xff\xff\xeb\xe6\xe2\x00\xff\xff\xff\xff\xec\xd6\xc4\xf0\xff\xff\xff\xff\xed" + + "\xc6\xc4\x00\xff\xff\xff\xff\ue47c\xf0\xff\xff\xff\xff\xf3o\xa4\x80\xff\xff\xff\xff\xf41b\xf0\xff\xff\xff\xff\xf9\x0fJ\x80\xff\xff\xff\xff\xfa\bv\x00\xff\xff\xff\xff\xfa\xf8g\x00\xff\xff\xff\xff\xfb\xe8X\x00\xff" + + "\xff\xff\xff\xfc\xd8I\x00\xff\xff\xff\xff\xfd\xc8:\x00\xff\xff\xff\xff\xfe\xb8+\x00\xff\xff\xff\xff\xff\xa8\x1c\x00\x00\x00\x00\x00\x00\x98\r\x00\x00\x00\x00\x00\x01\x87\xfe\x00\x00\x00\x00\x00\x02w\xef\x00\x00\x00\x00\x00\x03" + + "q\x1a\x80\x00\x00\x00\x00\x04a\v\x80\x00\x00\x00\x00\x05P\xfc\x80\x00\x00\x00\x00\x06@\xed\x80\x00\x00\x00\x00\a0ހ\x00\x00\x00\x00\b π\x00\x00\x00\x00\t\x10\xc0\x80\x00\x00\x00\x00\n\x00\xb1\x80\x00" + + "\x00\x00\x00\n\xf0\xa2\x80\x00\x00\x00\x00\v\xe0\x93\x80\x00\x00\x00\x00\fٿ\x00\x00\x00\x00\x00\r\xc0u\x80\x00\x00\x00\x00\x0e\xb9\xa1\x00\x00\x00\x00\x00\x0f\xa9\x92\x00\x00\x00\x00\x00\x10\x99\x83\x00\x00\x00\x00\x00\x11" + + "\x89t\x00\x00\x00\x00\x00\x12ye\x00\x00\x00\x00\x00\x13iV\x00\x00\x00\x00\x00\x14YG\x00\x00\x00\x00\x00\x15I8\x00\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17)\x1a\x00\x00\x00\x00\x00\x18\"E\x80\x00" + + "\x00\x00\x00\x19\b\xfc\x00\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2\x18\x80\x00\x00\x00\x00\x1b\xe2\t\x80\x00\x00\x00\x00\x1c\xd1\xfa\x80\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1܀\x00\x00\x00\x00\x1f" + + "\xa1̀\x00\x00\x00\x00 v\x0f\x00\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xf1\x00\x00\x00\x00\x00#j\xcc\x00\x00\x00\x00\x00$5\xd3\x00\x00\x00\x00\x00%J\xae\x00\x00\x00\x00\x00&\x15\xb5\x00\x00" + + "\x00\x00\x00'*\x90\x00\x00\x00\x00\x00'\xfeр\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\u07b3\x80\x00\x00\x00\x00*\xeaT\x00\x00\x00\x00\x00+\xbe\x95\x80\x00\x00\x00\x00,\xd3p\x80\x00\x00\x00\x00-" + + "\x9ew\x80\x00\x00\x00\x00.\xb3R\x80\x00\x00\x00\x00/~Y\x80\x00\x00\x00\x000\x934\x80\x00\x00\x00\x001gv\x00\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003GX\x00\x00\x00\x00\x004R\xf8\x80\x00" + + "\x00\x00\x005':\x00\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a\x1c\x00\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe6\xfe\x00\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xc6\xe0\x00\x00\x00\x00\x00;" + + "ۻ\x00\x00\x00\x00\x00<\xaf\xfc\x80\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8fހ\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@o\xc0\x80\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00BO\xa2\x80\x00" + + "\x00\x00\x00Cd}\x80\x00\x00\x00\x00D/\x84\x80\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7\x00\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xa4\xec\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f" + + "\xff\xff\xb9\xb0\x01\x10LMT\x00CDT\x00CST\x00CWT\x00CPT\x00\nCST6CDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00" + + "#\x82iS\u0096dK~\x02\x00\x00~\x02\x00\x00\x13\x00\x1c\x00Canada/SaskatchewanUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E" + + "\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + + "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x005\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff\x86\xfd\x93\x1c\xff\xff\xff\xff\x9e\xb8\xaf\x90\xff\xff" + + "\xff\xff\x9f\xbb\a\x80\xff\xff\xff\xff\xb5eO\xf0\xff\xff\xff\xff\xb60H\xe0\xff\xff\xff\xff\xb7E1\xf0\xff\xff\xff\xff\xb8\x10*\xe0\xff\xff\xff\xff\xb9%\x13\xf0\xff\xff\xff\xff\xb9\xf0\f\xe0\xff\xff\xff\xff\xbb\x0e" + + "0p\xff\xff\xff\xff\xbb\xcf\xee\xe0\xff\xff\xff\xff\xbc\xee\x12p\xff\xff\xff\xff\xbd\xb9\v`\xff\xff\xff\xff\xc2r\b\xf0\xff\xff\xff\xff\xc3a\xeb\xe0\xff\xff\xff\xff\xc4Q\xea\xf0\xff\xff\xff\xff\xc58\x93`\xff\xff" + + "\xff\xff\xc61\xcc\xf0\xff\xff\xff\xff\xc7!\xaf\xe0\xff\xff\xff\xff\xc8\x1a\xe9p\xff\xff\xff\xff\xc9\n\xcc`\xff\xff\xff\xff\xc9\xfa\xcbp\xff\xff\xff\xff\xca\xea\xae`\xff\xff\xff\xffˉ\f\x90\xff\xff\xff\xff\xd2#" + + "\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff\xd3c\x8c\x10\xff\xff\xff\xff\xd4So\x00\xff\xff\xff\xff\xd5U\xe3\x10\xff\xff\xff\xff\xd6 \xdc\x00\xff\xff\xff\xff\xd75\xc5\x10\xff\xff\xff\xff\xd8\x00\xbe\x00\xff\xff" + + "\xff\xff\xd9\x15\xa7\x10\xff\xff\xff\xff\xd9\xe0\xa0\x00\xff\xff\xff\xff\xda\xfeÐ\xff\xff\xff\xff\xdb\xc0\x82\x00\xff\xff\xff\xff\xdcޥ\x90\xff\xff\xff\xffݩ\x9e\x80\xff\xff\xff\xff\u07be\x87\x90\xff\xff\xff\xff߉" + + "\x80\x80\xff\xff\xff\xff\xe0\x9ei\x90\xff\xff\xff\xff\xe1ib\x80\xff\xff\xff\xff\xe2~K\x90\xff\xff\xff\xff\xe3ID\x80\xff\xff\xff\xff\xe4^-\x90\xff\xff\xff\xff\xe5)&\x80\xff\xff\xff\xff\xe6GJ\x10\xff\xff" + + "\xff\xff\xe7\x12C\x00\xff\xff\xff\xff\xe8',\x10\xff\xff\xff\xff\xe8\xf2%\x00\xff\xff\xff\xff\xeb\xe6\xf0\x10\xff\xff\xff\xff\xec\xd6\xd3\x00\xff\xff\xff\xff\xed\xc6\xd2\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05\xff\xff\x9d\xe4\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab" + + "\xa0\x01\f\xff\xff\xab\xa0\x01\x10\xff\xff\xab\xa0\x00\x14LMT\x00MDT\x00MST\x00MWT\x00MPT\x00CST\x00\nCST6\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xe6" + + "\x9aM\xbem\x02\x00\x00m\x02\x00\x00\x03\x00\x1c\x00CETUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x005\x00\x00\x00\x02\x00\x00\x00\t\xff\xff\xff\xff\x9b\f\x17`\xff\xff\xff\xff\x9b\xd5\xda\xf0\xff\xff\xff\xff\x9cٮ\x90\xff\xff\xff\xff\x9d\xa4\xb5\x90\xff\xff\xff\xff\x9e\xb9\x90" + + "\x90\xff\xff\xff\xff\x9f\x84\x97\x90\xff\xff\xff\xff\xc8\tq\x90\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff" + + "\xff\xd1r\x16\x10\xff\xff\xff\xff\xd2N@\x90\x00\x00\x00\x00\r\xa4c\x90\x00\x00\x00\x00\x0e\x8b\x1a\x10\x00\x00\x00\x00\x0f\x84E\x90\x00\x00\x00\x00\x10t6\x90\x00\x00\x00\x00\x11d'\x90\x00\x00\x00\x00\x12T\x18" + "\x90\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00" + "\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr" + "\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#\xf2y\xff\xff\xff\xff\x9e*\xee\xf9\xff\xff\xff\xff\x9e\xf79i\xff\xff\xff\xff\x9f\x84W\xf9\xff\xff\xff\xff\xa0\xd8l\xe9\xff\xff\xff\xff" + - "\xa1\x009\x80\xff\xff\xff\xff\xa1<\xa6@\xff\xff\xff\xff\xa4\x10m\xc0\xff\xff\xff\xff\xa4=2\xb0\xff\xff\xff\xff\xa5\x15h\xb0\xff\xff\xff\xff\xa5=\x03\xc0\xff\xff\xff\xff\xa7\x1eEP\xff\xff\xff\xff\xb5\xa4\x19`" + - "\x00\x00\x00\x00\x15'\xa7\xd0\x00\x00\x00\x00\x16\x18\xdc@\x00\x00\x00\x00\x17\b\xdbP\x00\x00\x00\x00\x17\xfa\x0f\xc0\x00\x00\x00\x00\x18\xea\x0e\xd0\x00\x00\x00\x00\x19\xdbC@\x00\x00\x00\x00\x1a̓\xd0\x00\x00\x00\x00" + - "\x1b\xbc\xa0\xf0\x00\x00\x00\x00\x1c\xac\x91\xf0\x00\x00\x00\x00\x1d\x9c\x82\xf0\x00\x00\x00\x00\x1e\x8cs\xf0\x00\x00\x00\x00\x1f|d\xf0\x00\x00\x00\x00 lU\xf0\x00\x00\x00\x00!\\F\xf0\x00\x00\x00\x00\"L7\xf0" + - "\x00\x00\x00\x00#<(\xf0\x00\x00\x00\x00$,\x19\xf0\x00\x00\x00\x00%\x1c\n\xf0\x00\x00\x00\x00&\v\xfb\xf0\x00\x00\x00\x00'\x05'p\x00\x00\x00\x00'\xf5\x18p\x00\x00\x00\x00(\xe5\x17\x80\x00\x00\x00\x00" + - ")x\xbf\x80\x00\x00\x00\x00)\xd4\xfap\x00\x00\x00\x00*\xc4\xebp\x00\x00\x00\x00+\xb4\xdcp\x00\x00\x00\x00,\xa4\xcdp\x00\x00\x00\x00-\x94\xbep\x00\x00\x00\x00.\x84\xafp\x00\x00\x00\x00/t\xa0p" + - "\x00\x00\x00\x000d\x91p\x00\x00\x00\x001]\xbc\xf0\x00\x00\x00\x002r\x97\xf0\x00\x00\x00\x003=\x9e\xf0\x00\x00\x00\x004Ry\xf0\x00\x00\x00\x005\x1d\x80\xf0\x00\x00\x00\x0062[\xf0\x00\x00\x00\x00" + - "6\xfdb\xf0\x00\x00\x00\x008\x1bxp\x00\x00\x00\x008\xddD\xf0\x00\x00\x00\x009\xfbZp\x00\x00\x00\x00:\xbd&\xf0\x00\x00\x00\x00;\xdb\x86%p\x00\x00\x00\x00?\x9b\x00p\x00\x00\x00\x00@f\ap\x00\x00\x00\x00A\x84\x1c\xf0\x00\x00\x00\x00BE\xe9p\x00\x00\x00\x00Cc\xfe\xf0\x00\x00\x00\x00D%\xcbp\x00\x00\x00\x00" + - "EC\xe0\xf0\x00\x00\x00\x00F\x05\xadp\x00\x00\x00\x00G#\xc2\xf0\x00\x00\x00\x00G\xee\xc9\xf0\x00\x00\x00\x00I\x03\xa4\xf0\x00\x00\x00\x00IΫ\xf0\x00\x00\x00\x00J\xe3\x86\xf0\x00\x00\x00\x00K\xae\x8d\xf0" + - "\x00\x00\x00\x00Ḷp\x00\x00\x00\x00M\x8eo\xf0\x00\x00\x00\x00TL\x1d`\x01\x03\x02\x03\x04\x02\x04\x05\x06\x05\a\x05\x06\b\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\t" + - "\b\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\n\x06\x00\x00#9\x00\x00\x00\x00#9\x00\x04\x00\x001\x87\x01\b" + - "\x00\x00#w\x00\x04\x00\x00?\x97\x01\f\x00\x008@\x01\x11\x00\x00*0\x00\x15\x00\x00FP\x01\x19\x00\x00\x1c \x00\x1d\x00\x00*0\x01!\x00\x008@\x00\x15LMT\x00MMT\x00MST\x00" + - "MDST\x00MSD\x00MSK\x00+05\x00EET\x00EEST\x00\nMSK-3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x8c\xc8\x15\xd0P\x02\x00\x00P\x02\x00\x00\f" + - "\x00\x1c\x00Europe/SofiaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00-\x00\x00\x00\x06\x00\x00\x00\x1a\xff\xff\xff\xffV\xb6\xce$\xff\xff\xff\xffr\xc3\xe3\x18\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff" + - "\xff\xffϒ4\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff\xff\xd1r$ \x00\x00\x00\x00\x11c\xefP\x00\x00\x00\x00\x12U?\xe0\x00\x00\x00\x00\x13M\v\xd0\x00\x00\x00\x00\x145!\xe0\x00\x00\x00\x00\x15," + - "\xed\xd0\x00\x00\x00\x00\x16\x13\xc0p\x00\x00\x00\x00\x17\f\xcf\xd0\x00\x00\x00\x00\x17\xf3\xb0\x80\x00\x00\x00\x00\x18㡀\x00\x00\x00\x00\x19Ӓ\x80\x00\x00\x00\x00\x1aÃ\x80\x00\x00\x00\x00\x1b\xbc\xaf\x00\x00\x00" + - "\x00\x00\x1c\xac\xa0\x00\x00\x00\x00\x00\x1d\x9c\x91\x00\x00\x00\x00\x00\x1e\x8c\x82\x00\x00\x00\x00\x00\x1f|s\x00\x00\x00\x00\x00 ld\x00\x00\x00\x00\x00!\\U\x00\x00\x00\x00\x00\"LF\x00\x00\x00\x00\x00#<" + - "7\x00\x00\x00\x00\x00$,(\x00\x00\x00\x00\x00%\x1c\x19\x00\x00\x00\x00\x00&\f\n\x00\x00\x00\x00\x00'\x055\x80\x00\x00\x00\x00'\xf5\n`\x00\x00\x00\x00(\xe4\xedP\x00\x00\x00\x00)\xd4\xec`\x00\x00" + - "\x00\x00*\xc4\xcfP\x00\x00\x00\x00+\xb4\xce`\x00\x00\x00\x00,\xa4\xb1P\x00\x00\x00\x00-\x94\xb0`\x00\x00\x00\x00.\x84\x93P\x00\x00\x00\x00/t\x92`\x00\x00\x00\x000duP\x00\x00\x00\x001]" + - "\xae\xe0\x00\x00\x00\x002r{\xd0\x00\x00\x00\x003=\xbb\x10\x01\x02\x03\x04\x03\x04\x03\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02" + - "\x05\x02\x05\x00\x00\x15\xdc\x00\x00\x00\x00\x1bh\x00\x04\x00\x00\x1c \x00\b\x00\x00\x0e\x10\x00\f\x00\x00\x1c \x01\x10\x00\x00*0\x01\x15LMT\x00IMT\x00EET\x00CET\x00CEST\x00" + - "EEST\x00\nEET-2EEST,M3.5.0/3,M10.5.0/4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xccb\xf72\xa4\x02\x00\x00\xa4\x02\x00" + - "\x00\x0e\x00\x1c\x00Europe/VilniusUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x003\x00\x00\x00\t\x00\x00\x00&\xff\xff\xff\xffV\xb6\xccD\xff\xff\xff\xff\x9cO\x1fP\xff\xff\xff\xff\xa1\x85J\x98\xff\xff\xff\xff\xa2\xf10\xf0\xff\xff\xff\xff\xa3f" + - "x`\xff\xff\xff\xffȬ\xcfp\xff\xff\xff\xff\xcaY*\xd0\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xff\xd00=\xe0\x00\x00" + - "\x00\x00\x15'\xa7\xd0\x00\x00\x00\x00\x16\x18\xdc@\x00\x00\x00\x00\x17\b\xdbP\x00\x00\x00\x00\x17\xfa\x0f\xc0\x00\x00\x00\x00\x18\xea\x0e\xd0\x00\x00\x00\x00\x19\xdbC@\x00\x00\x00\x00\x1a̓\xd0\x00\x00\x00\x00\x1b\xbc" + - "\xa0\xf0\x00\x00\x00\x00\x1c\xac\x91\xf0\x00\x00\x00\x00\x1d\x9c\x82\xf0\x00\x00\x00\x00\x1e\x8cs\xf0\x00\x00\x00\x00\x1f|d\xf0\x00\x00\x00\x00 lU\xf0\x00\x00\x00\x00!\\F\xf0\x00\x00\x00\x00\"L7\xf0\x00\x00" + - "\x00\x00#<(\xf0\x00\x00\x00\x00$,\x19\xf0\x00\x00\x00\x00%\x1c\x19\x00\x00\x00\x00\x00&\f\n\x00\x00\x00\x00\x00'\x055\x80\x00\x00\x00\x00'\xf5&\x80\x00\x00\x00\x00(\xe5\x17\x80\x00\x00\x00\x00)\xd5" + - "\b\x80\x00\x00\x00\x00*\xc4\xf9\x80\x00\x00\x00\x00+\xb4\xea\x80\x00\x00\x00\x00,\xa4ۀ\x00\x00\x00\x00-\x94̀\x00\x00\x00\x00.\x84\xbd\x80\x00\x00\x00\x00/t\xae\x80\x00\x00\x00\x000d\x9f\x80\x00\x00" + - "\x00\x001]\xcb\x00\x00\x00\x00\x002r\xa6\x00\x00\x00\x00\x003=\xad\x00\x00\x00\x00\x004R\x88\x00\x00\x00\x00\x005\x1d\x9d\x10\x00\x00\x00\x0062x\x10\x00\x00\x00\x006\xfd\u007f\x10\x00\x00\x00\x008\x1b" + - "\x94\x90\x00\x00\x00\x00>\x86A\x90\x01\x02\x03\x04\x03\x05\x06\x03\x06\x03\x06\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\b\x04\b\x04\b\x04\b\x04\b\x04\b\x04\b\x04\b\x04\b\x04\x06\x03\x06\x04" + - "\b\x00\x00\x17\xbc\x00\x00\x00\x00\x13\xb0\x00\x04\x00\x00\x16h\x00\b\x00\x00\x0e\x10\x00\f\x00\x00\x1c \x00\x10\x00\x00*0\x00\x14\x00\x00\x1c \x01\x18\x00\x008@\x01\x1d\x00\x00*0\x01!LMT\x00W" + - "MT\x00KMT\x00CET\x00EET\x00MSK\x00CEST\x00MSD\x00EEST\x00\nEET-2EEST,M3.5.0/3,M10.5.0" + - "/4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x17S\x91\xb3\xc1\x02\x00\x00\xc1\x02\x00\x00\r\x00\x1c\x00Europe/BerlinUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`u" + - "x\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00" + - "\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xffo\xa2a\xf8\xff\xff\xff" + - "\xff\x9b\f\x17`\xff\xff\xff\xff\x9b\xd5\xda\xf0\xff\xff\xff\xff\x9cٮ\x90\xff\xff\xff\xff\x9d\xa4\xb5\x90\xff\xff\xff\xff\x9e\xb9\x90\x90\xff\xff\xff\xff\x9f\x84\x97\x90\xff\xff\xff\xff\xc8\tq\x90\xff\xff\xff\xff\xcc\xe7K" + - "\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xffѶ\x96\x00\xff\xff\xff\xff\xd2X\xbe\x80\xff\xff\xff" + - "\xffҡO\x10\xff\xff\xff\xff\xd3c\x1b\x90\xff\xff\xff\xff\xd4K#\x90\xff\xff\xff\xff\xd59\xd1 \xff\xff\xff\xff\xd5g\xe7\x90\xff\xff\xff\xffըs\x00\xff\xff\xff\xff\xd6)\xb4\x10\xff\xff\xff\xff\xd7,\x1a" + - "\x10\xff\xff\xff\xff\xd8\t\x96\x10\xff\xff\xff\xff\xd9\x02\xc1\x90\xff\xff\xff\xff\xd9\xe9x\x10\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00" + + "\x90\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000d\xad\x90\x00\x00\x00\x001]\xd9\x10\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01" + + "\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x05\x00\x00\x1c \x01\x00CEST\x00CET\x00\nCET-1CEST,M3.5.0,M10" + + ".5.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x1c\x00Chile/UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00" + + "\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS[Sp\x90\x02\x05\x00\x00\x02\x05\x00\x00\x11\x00\x1c\x00Chile/ContinentalUT" + + "\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00z\x00\x00\x00\x06\x00\x00\x00" + + "\x14\xff\xff\xff\xffi\x87\x1d\xc6\xff\xff\xff\xff\x8f0GF\xff\xff\xff\xff\x9b\\\xe5P\xff\xff\xff\xff\x9f|\xe2\xc6\xff\xff\xff\xff\xa1\x00q\xc0\xff\xff\xff\xff\xb0^w\xc6\xff\xff\xff\xff\xb1w=@\xff\xff\xff" + + "\xff\xb2A\x00\xd0\xff\xff\xff\xff\xb3Xp\xc0\xff\xff\xff\xff\xb4\"4P\xff\xff\xff\xff\xb59\xa4@\xff\xff\xff\xff\xb6\x03g\xd0\xff\xff\xff\xff\xb7\x1a\xd7\xc0\xff\xff\xff\xff\xb7\xe4\x9bP\xff\xff\xff\xff\xb8\xfd\\" + + "\xc0\xff\xff\xff\xff\xb9\xc7 P\xff\xff\xff\xff\xcc\x1cn@\xff\xff\xff\xff\xccl\xe7\xd0\xff\xff\xff\xff\xd3\u070f\xc0\xff\xff\xff\xff\xd4\x1bɰ\xff\xff\xff\xff\xd53U\xc0\xff\xff\xff\xff\xd5v\x92@\xff\xff\xff" + + "\xff\xfd\xd1<@\xff\xff\xff\xff\xfe\x92\xfa\xb0\xff\xff\xff\xff\xff\xcc\xcd\xc0\x00\x00\x00\x00\x00rܰ\x00\x00\x00\x00\x01uP\xc0\x00\x00\x00\x00\x02@I\xb0\x00\x00\x00\x00\x03U2\xc0\x00\x00\x00\x00\x04 +" + + "\xb0\x00\x00\x00\x00\x05>O@\x00\x00\x00\x00\x06\x00\r\xb0\x00\x00\x00\x00\a\v\xbc@\x00\x00\x00\x00\a\xdf\xef\xb0\x00\x00\x00\x00\b\xfe\x13@\x00\x00\x00\x00\t\xbfѰ\x00\x00\x00\x00\n\xdd\xf5@\x00\x00\x00" + + "\x00\v\xa8\xee0\x00\x00\x00\x00\f\xbd\xd7@\x00\x00\x00\x00\r\x88\xd00\x00\x00\x00\x00\x0e\x9d\xb9@\x00\x00\x00\x00\x0fh\xb20\x00\x00\x00\x00\x10\x86\xd5\xc0\x00\x00\x00\x00\x11H\x940\x00\x00\x00\x00\x12f\xb7" + + "\xc0\x00\x00\x00\x00\x13(v0\x00\x00\x00\x00\x14F\x99\xc0\x00\x00\x00\x00\x15\x11\x92\xb0\x00\x00\x00\x00\x16&{\xc0\x00\x00\x00\x00\x16\xf1t\xb0\x00\x00\x00\x00\x18\x06]\xc0\x00\x00\x00\x00\x18\xd1V\xb0\x00\x00\x00" + + "\x00\x19\xe6?\xc0\x00\x00\x00\x00\x1a\xb18\xb0\x00\x00\x00\x00\x1b\xcf\\@\x00\x00\x00\x00\x1c\x91\x1a\xb0\x00\x00\x00\x00\x1d\xaf>@\x00\x00\x00\x00\x1ep\xfc\xb0\x00\x00\x00\x00\x1f\x8f @\x00\x00\x00\x00 \u007f\x03" + + "0\x00\x00\x00\x00!o\x02@\x00\x00\x00\x00\"9\xfb0\x00\x00\x00\x00#N\xe4@\x00\x00\x00\x00$\x19\xdd0\x00\x00\x00\x00%8\x00\xc0\x00\x00\x00\x00%\xf9\xbf0\x00\x00\x00\x00&\xf2\xf8\xc0\x00\x00\x00" + + "\x00'١0\x00\x00\x00\x00(\xf7\xc4\xc0\x00\x00\x00\x00)½\xb0\x00\x00\x00\x00*צ\xc0\x00\x00\x00\x00+\xa2\x9f\xb0\x00\x00\x00\x00,\xb7\x88\xc0\x00\x00\x00\x00-\x82\x81\xb0\x00\x00\x00\x00.\x97j" + + "\xc0\x00\x00\x00\x00/bc\xb0\x00\x00\x00\x000\x80\x87@\x00\x00\x00\x001BE\xb0\x00\x00\x00\x002`i@\x00\x00\x00\x003=\xd70\x00\x00\x00\x004@K@\x00\x00\x00\x005\vD0\x00\x00\x00" + + "\x006\r\xb8@\x00\x00\x00\x007\x06հ\x00\x00\x00\x008\x00\x0f@\x00\x00\x00\x008\xcb\b0\x00\x00\x00\x009\xe9+\xc0\x00\x00\x00\x00:\xaa\xea0\x00\x00\x00\x00;\xc9\r\xc0\x00\x00\x00\x00<\x8a\xcc" + + "0\x00\x00\x00\x00=\xa8\xef\xc0\x00\x00\x00\x00>j\xae0\x00\x00\x00\x00?\x88\xd1\xc0\x00\x00\x00\x00@Sʰ\x00\x00\x00\x00Ah\xb3\xc0\x00\x00\x00\x00B3\xac\xb0\x00\x00\x00\x00CH\x95\xc0\x00\x00\x00" + + "\x00D\x13\x8e\xb0\x00\x00\x00\x00E1\xb2@\x00\x00\x00\x00E\xf3p\xb0\x00\x00\x00\x00G\x11\x94@\x00\x00\x00\x00G\xef\x020\x00\x00\x00\x00H\xf1v@\x00\x00\x00\x00I\xbco0\x00\x00\x00\x00J\xd1X" + + "@\x00\x00\x00\x00K\xb8\x00\xb0\x00\x00\x00\x00L\xb1:@\x00\x00\x00\x00M\xc6\a0\x00\x00\x00\x00NP\x82\xc0\x00\x00\x00\x00O\x9c\xae\xb0\x00\x00\x00\x00PB\xd9\xc0\x00\x00\x00\x00Q|\x90\xb0\x00\x00\x00" + + "\x00R+\xf6@\x00\x00\x00\x00S\\r\xb0\x00\x00\x00\x00T\v\xd8@\x00\x00\x00\x00W7\xe60\x00\x00\x00\x00W\xaf\xec\xc0\x00\x00\x00\x00Y\x17\xc80\x00\x00\x00\x00Y\x8f\xce\xc0\x00\x00\x00\x00Z\xf7\xaa" + + "0\x00\x00\x00\x00[o\xb0\xc0\x00\x00\x00\x00\\\xa9g\xb0\x01\x02\x01\x03\x01\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x03\x02\x03\x05\x03\x02\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05" + + "\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05" + + "\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\xff\xff\xbd\xba\x00\x00\xff\xff\xbd\xba\x00\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x00\f\xff\xff\xc7\xc0\x01\f\xff\xff\xd5\xd0\x01\x10LMT\x00S" + + "MT\x00-05\x00-04\x00-03\x00\n<-04>4<-03>,M9.1.6/24,M4.1.6/24\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82" + + "iS\xee\xd0\x1cYN\x04\x00\x00N\x04\x00\x00\x12\x00\x1c\x00Chile/EasterIslandUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04" + + "S_\x01\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffi\x87B\b\xff\xff\xff\xff\xb9\xc7@\x88\xff\xff\xff\xff\xfd" + + "\xd1<@\xff\xff\xff\xff\xfe\x92\xfa\xb0\xff\xff\xff\xff\xff\xcc\xcd\xc0\x00\x00\x00\x00\x00rܰ\x00\x00\x00\x00\x01uP\xc0\x00\x00\x00\x00\x02@I\xb0\x00\x00\x00\x00\x03U2\xc0\x00\x00\x00\x00\x04 +\xb0\x00" + + "\x00\x00\x00\x05>O@\x00\x00\x00\x00\x06\x00\r\xb0\x00\x00\x00\x00\a\v\xbc@\x00\x00\x00\x00\a\xdf\xef\xb0\x00\x00\x00\x00\b\xfe\x13@\x00\x00\x00\x00\t\xbfѰ\x00\x00\x00\x00\n\xdd\xf5@\x00\x00\x00\x00\v" + + "\xa8\xee0\x00\x00\x00\x00\f\xbd\xd7@\x00\x00\x00\x00\r\x88\xd00\x00\x00\x00\x00\x0e\x9d\xb9@\x00\x00\x00\x00\x0fh\xb20\x00\x00\x00\x00\x10\x86\xd5\xc0\x00\x00\x00\x00\x11H\x940\x00\x00\x00\x00\x12f\xb7\xc0\x00" + + "\x00\x00\x00\x13(v0\x00\x00\x00\x00\x14F\x99\xc0\x00\x00\x00\x00\x15\x11\x92\xb0\x00\x00\x00\x00\x16&{\xc0\x00\x00\x00\x00\x16\xf1t\xb0\x00\x00\x00\x00\x18\x06]\xc0\x00\x00\x00\x00\x18\xd1V\xb0\x00\x00\x00\x00\x19" + + "\xe6?\xc0\x00\x00\x00\x00\x1a\xb18\xb0\x00\x00\x00\x00\x1b\xcf\\@\x00\x00\x00\x00\x1c\x91\x1a\xb0\x00\x00\x00\x00\x1d\xaf>@\x00\x00\x00\x00\x1ep\xfc\xb0\x00\x00\x00\x00\x1f\x8f @\x00\x00\x00\x00 \u007f\x030\x00" + + "\x00\x00\x00!o\x02@\x00\x00\x00\x00\"9\xfb0\x00\x00\x00\x00#N\xe4@\x00\x00\x00\x00$\x19\xdd0\x00\x00\x00\x00%8\x00\xc0\x00\x00\x00\x00%\xf9\xbf0\x00\x00\x00\x00&\xf2\xf8\xc0\x00\x00\x00\x00'" + + "١0\x00\x00\x00\x00(\xf7\xc4\xc0\x00\x00\x00\x00)½\xb0\x00\x00\x00\x00*צ\xc0\x00\x00\x00\x00+\xa2\x9f\xb0\x00\x00\x00\x00,\xb7\x88\xc0\x00\x00\x00\x00-\x82\x81\xb0\x00\x00\x00\x00.\x97j\xc0\x00" + + "\x00\x00\x00/bc\xb0\x00\x00\x00\x000\x80\x87@\x00\x00\x00\x001BE\xb0\x00\x00\x00\x002`i@\x00\x00\x00\x003=\xd70\x00\x00\x00\x004@K@\x00\x00\x00\x005\vD0\x00\x00\x00\x006" + + "\r\xb8@\x00\x00\x00\x007\x06հ\x00\x00\x00\x008\x00\x0f@\x00\x00\x00\x008\xcb\b0\x00\x00\x00\x009\xe9+\xc0\x00\x00\x00\x00:\xaa\xea0\x00\x00\x00\x00;\xc9\r\xc0\x00\x00\x00\x00<\x8a\xcc0\x00" + + "\x00\x00\x00=\xa8\xef\xc0\x00\x00\x00\x00>j\xae0\x00\x00\x00\x00?\x88\xd1\xc0\x00\x00\x00\x00@Sʰ\x00\x00\x00\x00Ah\xb3\xc0\x00\x00\x00\x00B3\xac\xb0\x00\x00\x00\x00CH\x95\xc0\x00\x00\x00\x00D" + + "\x13\x8e\xb0\x00\x00\x00\x00E1\xb2@\x00\x00\x00\x00E\xf3p\xb0\x00\x00\x00\x00G\x11\x94@\x00\x00\x00\x00G\xef\x020\x00\x00\x00\x00H\xf1v@\x00\x00\x00\x00I\xbco0\x00\x00\x00\x00J\xd1X@\x00" + + "\x00\x00\x00K\xb8\x00\xb0\x00\x00\x00\x00L\xb1:@\x00\x00\x00\x00M\xc6\a0\x00\x00\x00\x00NP\x82\xc0\x00\x00\x00\x00O\x9c\xae\xb0\x00\x00\x00\x00PB\xd9\xc0\x00\x00\x00\x00Q|\x90\xb0\x00\x00\x00\x00R" + + "+\xf6@\x00\x00\x00\x00S\\r\xb0\x00\x00\x00\x00T\v\xd8@\x00\x00\x00\x00W7\xe60\x00\x00\x00\x00W\xaf\xec\xc0\x00\x00\x00\x00Y\x17\xc80\x00\x00\x00\x00Y\x8f\xce\xc0\x00\x00\x00\x00Z\xf7\xaa0\x00" + + "\x00\x00\x00[o\xb0\xc0\x00\x00\x00\x00\\\xa9g\xb0\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05" + + "\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\xff\xff\x99" + + "x\x00\x00\xff\xff\x99x\x00\x04\xff\xff\xab\xa0\x01\b\xff\xff\x9d\x90\x00\f\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\x10LMT\x00EMT\x00-06\x00-07\x00-05\x00\n<-06>6" + + "<-05>,M9.1.6/22,M4.1.6/22\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS<\x8b\x99\x1e\xb7\x03\x00\x00\xb7\x03\x00\x00\a\x00\x1c\x00CST6" + + "CDTUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00X\x00\x00" + + "\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a" + + "\t\xf0\xff\xff\xff\xff\xfa\xf8g\x00\xff\xff\xff\xff\xfb\xe8I\xf0\xff\xff\xff\xff\xfc\xd8I\x00\xff\xff\xff\xff\xfd\xc8+\xf0\xff\xff\xff\xff\xfe\xb8+\x00\xff\xff\xff\xff\xff\xa8\r\xf0\x00\x00\x00\x00\x00\x98\r\x00\x00\x00" + + "\x00\x00\x01\x87\xef\xf0\x00\x00\x00\x00\x02w\xef\x00\x00\x00\x00\x00\x03q\fp\x00\x00\x00\x00\x04a\v\x80\x00\x00\x00\x00\x05P\xeep\x00\x00\x00\x00\x06@\xed\x80\x00\x00\x00\x00\a0\xd0p\x00\x00\x00\x00\a\x8d" + + "'\x80\x00\x00\x00\x00\t\x10\xb2p\x00\x00\x00\x00\t\xad\xa3\x00\x00\x00\x00\x00\n\xf0\x94p\x00\x00\x00\x00\v\xe0\x93\x80\x00\x00\x00\x00\fٰ\xf0\x00\x00\x00\x00\r\xc0u\x80\x00\x00\x00\x00\x0e\xb9\x92\xf0\x00\x00" + + "\x00\x00\x0f\xa9\x92\x00\x00\x00\x00\x00\x10\x99t\xf0\x00\x00\x00\x00\x11\x89t\x00\x00\x00\x00\x00\x12yV\xf0\x00\x00\x00\x00\x13iV\x00\x00\x00\x00\x00\x14Y8\xf0\x00\x00\x00\x00\x15I8\x00\x00\x00\x00\x00\x169" + + "\x1a\xf0\x00\x00\x00\x00\x17)\x1a\x00\x00\x00\x00\x00\x18\"7p\x00\x00\x00\x00\x19\b\xfc\x00\x00\x00\x00\x00\x1a\x02\x19p\x00\x00\x00\x00\x1a\xf2\x18\x80\x00\x00\x00\x00\x1b\xe1\xfbp\x00\x00\x00\x00\x1c\xd1\xfa\x80\x00\x00" + + "\x00\x00\x1d\xc1\xddp\x00\x00\x00\x00\x1e\xb1܀\x00\x00\x00\x00\x1f\xa1\xbfp\x00\x00\x00\x00 v\x0f\x00\x00\x00\x00\x00!\x81\xa1p\x00\x00\x00\x00\"U\xf1\x00\x00\x00\x00\x00#j\xbd\xf0\x00\x00\x00\x00$5" + + "\xd3\x00\x00\x00\x00\x00%J\x9f\xf0\x00\x00\x00\x00&\x15\xb5\x00\x00\x00\x00\x00'*\x81\xf0\x00\x00\x00\x00'\xfeр\x00\x00\x00\x00)\nc\xf0\x00\x00\x00\x00)\u07b3\x80\x00\x00\x00\x00*\xeaE\xf0\x00\x00" + + "\x00\x00+\xbe\x95\x80\x00\x00\x00\x00,\xd3bp\x00\x00\x00\x00-\x9ew\x80\x00\x00\x00\x00.\xb3Dp\x00\x00\x00\x00/~Y\x80\x00\x00\x00\x000\x93&p\x00\x00\x00\x001gv\x00\x00\x00\x00\x002s" + + "\bp\x00\x00\x00\x003GX\x00\x00\x00\x00\x004R\xeap\x00\x00\x00\x005':\x00\x00\x00\x00\x0062\xccp\x00\x00\x00\x007\a\x1c\x00\x00\x00\x00\x008\x1b\xe8\xf0\x00\x00\x00\x008\xe6\xfe\x00\x00\x00" + + "\x00\x009\xfb\xca\xf0\x00\x00\x00\x00:\xc6\xe0\x00\x00\x00\x00\x00;۬\xf0\x00\x00\x00\x00<\xaf\xfc\x80\x00\x00\x00\x00=\xbb\x8e\xf0\x00\x00\x00\x00>\x8fހ\x00\x00\x00\x00?\x9bp\xf0\x00\x00\x00\x00@o" + + "\xc0\x80\x00\x00\x00\x00A\x84\x8dp\x00\x00\x00\x00BO\xa2\x80\x00\x00\x00\x00Cdop\x00\x00\x00\x00D/\x84\x80\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7\x00\x01\x00\x01\x00\x02\x03\x00\x01\x00\x01" + + "\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01" + + "\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\xff\xff\xab\xa0\x00\x04\xff\xff\xb9\xb0\x01\x00\xff\xff\xb9\xb0\x01\b\xff\xff\xb9\xb0\x01\fCDT\x00CST\x00CWT\x00CPT\x00\nC" + + "ST6CDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\a\x1c\x9e\x9a]\x04\x00\x00]\x04\x00\x00\x04\x00\x1c\x00CubaUT\t\x00" + + "\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\x00\x00\x00\x04\x00\x00\x00\x10\xff" + + "\xff\xff\xffi\x87(\xb8\xff\xff\xff\xff\xacb\u0080\xff\xff\xff\xff\xb1ӔP\xff\xff\xff\xff\xb2t]@\xff\xff\xff\xff\xc8[f\xd0\xff\xff\xff\xff\xc8\xd3Q@\xff\xff\xff\xff\xca;H\xd0\xff\xff\xff\xff\xca" + + "\xbcm\xc0\xff\xff\xff\xff\xcc$eP\xff\xff\xff\xff̜O\xc0\xff\xff\xff\xff\xd1\xc4\vP\xff\xff\xff\xff\xd2;\xf5\xc0\xff\xff\xff\xffӣ\xedP\xff\xff\xff\xff\xd4\x1b\xd7\xc0\xff\xff\xff\xff\xf7`\x05\xd0\xff" + + "\xff\xff\xff\xf7\xff}@\xff\xff\xff\xff\xf9=D\xd0\xff\xff\xff\xff\xf9\xe3S\xc0\xff\xff\xff\xff\xfa\xdb;\xd0\xff\xff\xff\xff\xfb\xa7\x86@\xff\xff\xff\xff\xfcũ\xd0\xff\xff\xff\xff\xfd\x87h@\xff\xff\xff\xff\xfe" + + "\xb8\x00\xd0\xff\xff\xff\xff\xff\xa7\xe3\xc0\x00\x00\x00\x00\x00\x97\xe2\xd0\x00\x00\x00\x00\x01\x87\xc5\xc0\x00\x00\x00\x00\x02w\xc4\xd0\x00\x00\x00\x00\x03p\xe2@\x00\x00\x00\x00\x04`\xe1P\x00\x00\x00\x00\x055\x14\xc0\x00" + + "\x00\x00\x00\x06@\xc3P\x00\x00\x00\x00\a\x16H@\x00\x00\x00\x00\b \xa5P\x00\x00\x00\x00\b\xf7{\xc0\x00\x00\x00\x00\n\x00\x87P\x00\x00\x00\x00\n\xf0j@\x00\x00\x00\x00\v\xe0iP\x00\x00\x00\x00\f" + + "ن\xc0\x00\x00\x00\x00\r\xc0KP\x00\x00\x00\x00\x0e\xb9h\xc0\x00\x00\x00\x00\x0f\xb2\xa2P\x00\x00\x00\x00\x10}\x9b@\x00\x00\x00\x00\x11Q\xea\xd0\x00\x00\x00\x00\x12f\xb7\xc0\x00\x00\x00\x00\x131\xcc\xd0\x00" + + "\x00\x00\x00\x14F\x99\xc0\x00\x00\x00\x00\x15[\x82\xd0\x00\x00\x00\x00\x16&{\xc0\x00\x00\x00\x00\x17;d\xd0\x00\x00\x00\x00\x18\x06]\xc0\x00\x00\x00\x00\x19\x1bF\xd0\x00\x00\x00\x00\x19\xe6?\xc0\x00\x00\x00\x00\x1a" + + "\xfb(\xd0\x00\x00\x00\x00\x1b\xcf\\@\x00\x00\x00\x00\x1c\xdb\n\xd0\x00\x00\x00\x00\x1d\xaf>@\x00\x00\x00\x00\x1ezSP\x00\x00\x00\x00\x1f\x8f @\x00\x00\x00\x00 Z5P\x00\x00\x00\x00!o\x02@\x00" + + "\x00\x00\x00\"CQ\xd0\x00\x00\x00\x00#N\xe4@\x00\x00\x00\x00$#3\xd0\x00\x00\x00\x00%.\xc6@\x00\x00\x00\x00&\x15\x8a\xd0\x00\x00\x00\x00'\x17\xe2\xc0\x00\x00\x00\x00'\xfe\xa7P\x00\x00\x00\x00(" + + "\xf7\xd2\xd0\x00\x00\x00\x00)މP\x00\x00\x00\x00*״\xd0\x00\x00\x00\x00+\xbekP\x00\x00\x00\x00,\xb7\x96\xd0\x00\x00\x00\x00-\x9eMP\x00\x00\x00\x00.\x97x\xd0\x00\x00\x00\x00/~/P\x00" + + "\x00\x00\x000wZ\xd0\x00\x00\x00\x001gK\xd0\x00\x00\x00\x002W<\xd0\x00\x00\x00\x003G-\xd0\x00\x00\x00\x004@YP\x00\x00\x00\x005\x1d\xd5P\x00\x00\x00\x0062\xb0P\x00\x00\x00\x006" + + "\xfd\xb7P\x00\x00\x00\x008\x1b\xcc\xd0\x00\x00\x00\x008\xe6\xd3\xd0\x00\x00\x00\x009\xfb\xae\xd0\x00\x00\x00\x00:Ƶ\xd0\x00\x00\x00\x00;ې\xd0\x00\x00\x00\x00<\xaf\xd2P\x00\x00\x00\x00=\xbbr\xd0\x00" + + "\x00\x00\x00>\x8f\xb4P\x00\x00\x00\x00?\x9bT\xd0\x00\x00\x00\x00@f[\xd0\x00\x00\x00\x00ED5P\x00\x00\x00\x00E\xf3\x8c\xd0\x00\x00\x00\x00G$\x17P\x00\x00\x00\x00GܩP\x00\x00\x00\x00I" + + "\x03\xf9P\x00\x00\x00\x00I\xb3P\xd0\x00\x00\x00\x00J\xe3\xdbP\x00\x00\x00\x00K\x9cmP\x00\x00\x00\x00L\xcc\xf7\xd0\x00\x00\x00\x00M\x85\x89\xd0\x00\x00\x00\x00N\xbfN\xd0\x00\x00\x00\x00Ow\xe0\xd0\x00" + + "\x00\x00\x00P\x95\xf6P\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\xff\xff\xb2\xc8\x00\x00\xff" + + "\xff\xb2\xc0\x00\x04\xff\xff\xc7\xc0\x01\b\xff\xff\xb9\xb0\x00\fLMT\x00HMT\x00CDT\x00CST\x00\nCST5CDT,M3.2.0/0,M11.1.0/1" + + "\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS`l\x8d~\xf1\x01\x00\x00\xf1\x01\x00\x00\x03\x00\x1c\x00EETUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_" + + "\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\x00\x00\x00\x02\x00\x00\x00\t\x00\x00\x00\x00\r\xa4c\x90\x00\x00\x00\x00\x0e\x8b\x1a\x10\x00\x00\x00\x00\x0f\x84E" + + "\x90\x00\x00\x00\x00\x10t6\x90\x00\x00\x00\x00\x11d'\x90\x00\x00\x00\x00\x12T\x18\x90\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00" + "\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f" + "\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#\x86%p\x00\x00\x00\x00?\x9b" + - "\x00p\x00\x00\x00\x00@f\ap\x00\x00\x00\x00A\x84\x1c\xf0\x00\x00\x00\x00BE\xe9p\x00\x00\x00\x00Cc\xfe\xf0\x00\x00\x00\x00D%\xcbp\x00\x00\x00\x00EC\xe0\xf0\x00\x00\x00\x00F\x05\xadp\x00\x00" + - "\x00\x00G#\xc2\xf0\x00\x00\x00\x00G\xee\xc9\xf0\x00\x00\x00\x00I\x03\xa4\xf0\x00\x00\x00\x00IΫ\xf0\x00\x00\x00\x00J\xe3\x86\xf0\x00\x00\x00\x00K\xae\x8d\xf0\x00\x00\x00\x00Ḷp\x00\x00\x00\x00M\x8e" + - "o\xf0\x00\x00\x00\x00TL\x1d`\x00\x00\x00\x00XCNp\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x04\x01\x04\x01\x03\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04" + - "\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x03\x01\x03\x00\x00+2\x00\x00\x00\x00*0\x00\x04\x00\x00FP\x01\b\x00\x008@\x00\f\x00\x008@\x01\fLMT\x00+03\x00" + - "+05\x00+04\x00\n<+04>-4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xe6Kf\xab\xfe\x02\x00\x00\xfe\x02\x00\x00\x0f\x00\x1c\x00Europe/Budape" + - "stUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00D\x00\x00\x00" + - "\x03\x00\x00\x00\r\xff\xff\xff\xffk\x17\x91\x9c\xff\xff\xff\xff\x9b\f\x17`\xff\xff\xff\xff\x9b\xd5\xda\xf0\xff\xff\xff\xff\x9cٮ\x90\xff\xff\xff\xff\x9d\xa4\xb5\x90\xff\xff\xff\xff\x9e\xb9\x90\x90\xff\xff\xff\xff\x9f\x84\x97" + - "\x90\xff\xff\xff\xff\xa0\x9a\xc4\x10\xff\xff\xff\xff\xa1dy\x90\xff\xff\xff\xff\xa2p\x1a\x10\xff\xff\xff\xff\xa3M\x96\x10\xff\xff\xff\xff\xc9\xf3\xb5`\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff" + - "\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff\xffљx\xe0\xff\xff\xff\xffҊ\xc9p\xff\xff\xff\xff\xd3P\xa6\x90\xff\xff\xff\xff\xd4K\x15\x80\xff\xff\xff\xff\xd59\xc3" + - "\x10\xff\xff\xff\xff\xd6)\xb4\x10\xff\xff\xff\xff\xd7\x19\xa5\x10\xff\xff\xff\xff\xd8\t\x96\x10\xff\xff\xff\xff\xd9\x02\xc1\x90\xff\xff\xff\xff\xd9\xe9x\x10\xff\xff\xff\xff⢨\xf0\xff\xff\xff\xff\xe3Q\xf2`\xff\xff\xff" + - "\xff䂧\x10\xff\xff\xff\xff\xe51\xfe\x90\xff\xff\xff\xff\xe6t\xfe\x10\xff\xff\xff\xff\xe7\x11\xe0\x90\xff\xff\xff\xff\xe8T\xe0\x10\xff\xff\xff\xff\xe8\xf1\u0090\x00\x00\x00\x00\x13M'\xf0\x00\x00\x00\x00\x143\xde" + - "p\x00\x00\x00\x00\x15#\xcfp\x00\x00\x00\x00\x16\x13\xc0p\x00\x00\x00\x00\x17\x03\xb1p\x00\x00\x00\x00\x17\xf3\xa2p\x00\x00\x00\x00\x18\xe3\x93p\x00\x00\x00\x00\x19ӄp\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00" + - "\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT" + - "\x10\x00\x00\x00\x00#(\xe8L\xff\xff\xff\xffp\xbc\x81p\xff\xff\xff\xff\x9b8\xf8p\xff\xff\xff\xff\x9b\xd5\xcc\xe0\xff\xff\xff\xff\x9c\xc5\xcb\xf0\xff\xff\xff\xff\x9d\xb7\x00`\xff\xff\xff\xff\x9e\x89\xfep\xff\xff\xff\xff" + - "\x9f\xa0\x1c\xe0\xff\xff\xff\xff\xa0`\xa5\xf0\xff\xff\xff\xff\xa1~\xad`\xff\xff\xff\xff\xa2\\7p\xff\xff\xff\xff\xa3L\x1a`\xff\xff\xff\xff\xc8l5\xf0\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90" + - "\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xff\xd0n^\x90\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd2L\xd2\xf0\xff\xff\xff\xff\xd3>1\x90\xff\xff\xff\xff\xd4I\xd2\x10\xff\xff\xff\xff" + - "\xd5\x1d\xf7p\xff\xff\xff\xff\xd6)\x97\xf0\xff\xff\xff\xff\xd6뀐\xff\xff\xff\xff\xd8\t\x96\x10\xff\xff\xff\xff\xf93\xb5\xf0\xff\xff\xff\xff\xf9\xd9\xc4\xe0\xff\xff\xff\xff\xfb\x1c\xd2p\xff\xff\xff\xff\xfb\xb9\xb4\xf0" + - "\xff\xff\xff\xff\xfc\xfc\xb4p\xff\xff\xff\xff\xfd\x99\x96\xf0\xff\xff\xff\xff\xfe\xe5\xd0\xf0\xff\xff\xff\xff\xff\x82\xb3p\x00\x00\x00\x00\x00Ų\xf0\x00\x00\x00\x00\x01b\x95p\x00\x00\x00\x00\x02\x9cZp\x00\x00\x00\x00" + - "\x03Bwp\x00\x00\x00\x00\x04\x85v\xf0\x00\x00\x00\x00\x05+\x93\xf0\x00\x00\x00\x00\x06n\x93p\x00\x00\x00\x00\a\vu\xf0\x00\x00\x00\x00\bE:\xf0\x00\x00\x00\x00\b\xebW\xf0\x00\x00\x00\x00\n.Wp" + - "\x00\x00\x00\x00\n\xcb9\xf0\x00\x00\x00\x00\f\x0e9p\x00\x00\x00\x00\f\xab\x1b\xf0\x00\x00\x00\x00\r\xe4\xe0\xf0\x00\x00\x00\x00\x0e\x8a\xfd\xf0\x00\x00\x00\x00\x0f\xcd\xfdp\x00\x00\x00\x00\x10t\x1ap\x00\x00\x00\x00" + - "\x11\xad\xdfp\x00\x00\x00\x00\x12S\xfcp\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90" + - "\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00" + - "\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#\xf3`\xff\xff\xff\xff\xb9\xef\x9c`\xff\xff\xff\xff\xbaߍ`\xff\xff\xff\xff\xbb\xcf~`\xff\xff\xff\xff\xbcȩ\xe0\xff\xff\xff" + - "\xff\xbd\xb8\x9a\xe0\xff\xff\xff\xff\xbe\xa8\x8b\xe0\xff\xff\xff\xff\xbf\x98|\xe0\xff\xff\xff\xff\xc0\x88m\xe0\xff\xff\xff\xff\xc1x^\xe0\xff\xff\xff\xff\xc2hO\xe0\xff\xff\xff\xff\xc3X@\xe0\xff\xff\xff\xff\xc4H1" + - "\xe0\xff\xff\xff\xff\xc58\"\xe0\xff\xff\xff\xff\xc6(\x13\xe0\xff\xff\xff\xff\xc7\x18\x04\xe0\x00\x00\x00\x00\x11\xad\xd1`\x00\x00\x00\x00\x12S\xe0P\x00\x00\x00\x00\x13M\v\xd0\x00\x00\x00\x00\x143\xd0`\x00\x00\x00" + - "\x00\x15#݀\x00\x00\x00\x00\x16\x13\u0380\x00\x00\x00\x00\x17\x03\xbf\x80\x00\x00\x00\x00\x17\xf3\xb0\x80\x00\x00\x00\x00\x18㡀\x00\x00\x00\x00\x19Ӓ\x80\x00\x00\x00\x00\x1aÃ\x80\x00\x00\x00\x00\x1b\xbc\xaf" + - "\x00\x00\x00\x00\x00\x1c\xac\xa0\x00\x00\x00\x00\x00\x1d\x9c\x91\x00\x00\x00\x00\x00\x1e\x8c\x82\x00\x00\x00\x00\x00\x1f|s\x00\x00\x00\x00\x00 ld\x00\x00\x00\x00\x00!\\U\x00\x00\x00\x00\x00\"LF\x00\x00\x00\x00" + - "\x00#<7\x00\x00\x00\x00\x00$,(\x00\x00\x00\x00\x00%\x1c\x19\x00\x00\x00\x00\x00&\f\n\x00\x00\x00\x00\x00'\x055\x80\x00\x00\x00\x00'\xf5\n`\x00\x00\x00\x00(\xe4\xfb`\x00\x00\x00\x00)\xd4\xec" + - "`\x00\x00\x00\x00*\xc4\xdd`\x00\x00\x00\x00+\xb4\xce`\x00\x00\x00\x00,\xa4\xbf`\x00\x00\x00\x00-\x94\xb0`\x00\x00\x00\x00.\x84\x93P\x00\x00\x00\x00/t\x92`\x00\x00\x00\x000duP\x00\x00\x00" + - "\x001]\xae\xe0\x00\x00\x00\x002r{\xd0\x00\x00\x00\x003=\xbb\x10\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x00\x00\x18x\x00\x00\x00\x00\x18x\x00\x04\x00\x00*0\x01\b\x00\x00\x1c \x00\rLMT\x00BMT\x00EEST\x00EET\x00\nEE" + - "T-2EEST,M3.5.0/3,M10.5.0/4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RIo\x11{\xd3\x02\x00\x00\xd3\x02\x00\x00\x11\x00\x1c\x00Eur" + - "ope/BratislavaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x90\x00\x00\x00\x00,\xa4\xe9\x90\x00\x00\x00\x00-\x94ڐ\x00\x00\x00\x00.\x84ː\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000d\xad\x90\x00\x00\x00\x001]\xd9\x10\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01" + + "\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x00\x1c \x00\x05\x00\x00*0\x01\x00EEST\x00EET\x00\nEET-2EEST," + + "M3.5.0/3,M10.5.0/4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x12tnj\xfc\x04\x00\x00\xfc\x04\x00\x00\x05\x00\x1c\x00EgyptUT\t\x00\x03\x82" + + "\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\u007f\x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff" + + "\xff}\xbdM\xab\xff\xff\xff\xffȓ\xb4\xe0\xff\xff\xff\xff\xc8\xfa{\xd0\xff\xff\xff\xff\xc9\xfc\xef\xe0\xff\xff\xff\xff\xca\xc7\xe8\xd0\xff\xff\xff\xff\xcbˮ`\xff\xff\xff\xff\xcc\xdf)\xd0\xff\xff\xff\xffͬ\xe1" + + "\xe0\xff\xff\xff\xff\xce\xc6\xf4\xd0\xff\xff\xff\xffϏf\xe0\xff\xff\xff\xffЩy\xd0\xff\xff\xff\xffф`\xe0\xff\xff\xff\xffҊ\xadP\xff\xff\xff\xff\xe86c`\xff\xff\xff\xff\xe8\xf4-P\xff\xff\xff" + + "\xff\xea\v\xb9`\xff\xff\xff\xff\xea\xd5`\xd0\xff\xff\xff\xff\xeb\xec\xfa\xf0\xff\xff\xff\xff\xec\xb5m\x00\xff\xff\xff\xff\xed\xcf\u007f\xf0\xff\xff\xff\xff\xee\x97\xf2\x00\xff\xff\xff\xffﰳp\xff\xff\xff\xff\xf0y%" + + "\x80\xff\xff\xff\xff\xf1\x91\xe6\xf0\xff\xff\xff\xff\xf2ZY\x00\xff\xff\xff\xff\xf3s\x1ap\xff\xff\xff\xff\xf4;\x8c\x80\xff\xff\xff\xff\xf5U\x9fp\xff\xff\xff\xff\xf6\x1e\x11\x80\xff\xff\xff\xff\xf76\xd2\xf0\xff\xff\xff" + + "\xff\xf7\xffE\x00\xff\xff\xff\xff\xf9\x18\x06p\xff\xff\xff\xff\xf9\xe1\xca\x00\xff\xff\xff\xff\xfa\xf99\xf0\xff\xff\xff\xff\xfb\xc2\xfd\x80\xff\xff\xff\xff\xfc۾\xf0\xff\xff\xff\xff\xfd\xa5\x82\x80\xff\xff\xff\xff\xfe\xbc\xf2" + + "p\xff\xff\xff\xff\xff\x86\xb6\x00\x00\x00\x00\x00\x00\x9e%\xf0\x00\x00\x00\x00\x01g\xe9\x80\x00\x00\x00\x00\x02\u007fYp\x00\x00\x00\x00\x03I\x1d\x00\x00\x00\x00\x00\x04a\xdep\x00\x00\x00\x00\x05+\xa2\x00\x00\x00\x00" + + "\x00\x06C\x11\xf0\x00\x00\x00\x00\a\fՀ\x00\x00\x00\x00\b$Ep\x00\x00\x00\x00\b\xee\t\x00\x00\x00\x00\x00\n\x05x\xf0\x00\x00\x00\x00\n\xcf<\x80\x00\x00\x00\x00\v\xe7\xfd\xf0\x00\x00\x00\x00\f\xb1\xc1" + + "\x80\x00\x00\x00\x00\r\xc91p\x00\x00\x00\x00\x0e\x92\xf5\x00\x00\x00\x00\x00\x0f\xaad\xf0\x00\x00\x00\x00\x10t(\x80\x00\x00\x00\x00\x11\x8b\x98p\x00\x00\x00\x00\x12U\\\x00\x00\x00\x00\x00\x13n\x1dp\x00\x00\x00" + + "\x00\x147\xe1\x00\x00\x00\x00\x00\x15OP\xf0\x00\x00\x00\x00\x16\x19\x14\x80\x00\x00\x00\x00\x17\xa0\x93\xf0\x00\x00\x00\x00\x17\xfaH\x00\x00\x00\x00\x00\x19p\xa3\xf0\x00\x00\x00\x00\x19\xdb{\x80\x00\x00\x00\x00\x1a\xf4<" + + "\xf0\x00\x00\x00\x00\x1b\xbe\x00\x80\x00\x00\x00\x00\x1c\xd5pp\x00\x00\x00\x00\x1d\x9f4\x00\x00\x00\x00\x00\x1e\xb6\xa3\xf0\x00\x00\x00\x00\x1f\x80g\x80\x00\x00\x00\x00 \x97\xd7p\x00\x00\x00\x00!a\x9b\x00\x00\x00\x00" + + "\x00\"z\\p\x00\x00\x00\x00#D \x00\x00\x00\x00\x00$b'p\x00\x00\x00\x00%%S\x80\x00\x00\x00\x00&<\xc3p\x00\x00\x00\x00'\x06\x87\x00\x00\x00\x00\x00(\x1d\xf6\xf0\x00\x00\x00\x00(\xe7\xba" + + "\x80\x00\x00\x00\x00*\x00{\xf0\x00\x00\x00\x00*\xca?\x80\x00\x00\x00\x00+\xe1\xafp\x00\x00\x00\x00,\xabs\x00\x00\x00\x00\x00-\xc2\xe2\xf0\x00\x00\x00\x00.\x8c\xa6\x80\x00\x00\x00\x00/\xa0\x13\xe0\x00\x00\x00" + + "\x000k\f\xd0\x00\x00\x00\x001\u007f\xf5\xe0\x00\x00\x00\x002J\xee\xd0\x00\x00\x00\x003_\xd7\xe0\x00\x00\x00\x004*\xd0\xd0\x00\x00\x00\x005?\xb9\xe0\x00\x00\x00\x006\n\xb2\xd0\x00\x00\x00\x007(\xd6" + + "`\x00\x00\x00\x007\xf3\xcfP\x00\x00\x00\x009\b\xb8`\x00\x00\x00\x009ӱP\x00\x00\x00\x00:\xe8\x9a`\x00\x00\x00\x00;\xb3\x93P\x00\x00\x00\x00<\xc8|`\x00\x00\x00\x00=\x93uP\x00\x00\x00" + + "\x00>\xa8^`\x00\x00\x00\x00?sWP\x00\x00\x00\x00@\x91z\xe0\x00\x00\x00\x00A\\s\xd0\x00\x00\x00\x00Bq\\\xe0\x00\x00\x00\x00C\xe0\x00\x00\x00\x00E\x12\xfd" + + "P\x00\x00\x00\x00F1 \xe0\x00\x00\x00\x00F\xe0jP\x00\x00\x00\x00H\x11\x02\xe0\x00\x00\x00\x00H\xb7\x11\xd0\x00\x00\x00\x00I\xf0\xe4\xe0\x00\x00\x00\x00J\x8d\xb9P\x00\x00\x00\x00K\xda\x01`\x00\x00\x00" + + "\x00La\xbd\xd0\x00\x00\x00\x00L\x89X\xe0\x00\x00\x00\x00L\xa4\xfaP\x00\x00\x00\x00Su8\xe0\x00\x00\x00\x00S\xac\x89\xd0\x00\x00\x00\x00Sڼ`\x00\x00\x00\x00T$\x82P\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x00\x00\x1dU\x00\x00\x00\x00*0\x01\x04\x00\x00\x1c \x00\tLMT\x00EEST\x00EET\x00\nEET-2\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x9a\v\xf9/\xd8\x05\x00\x00" + + "\xd8\x05\x00\x00\x04\x00\x1c\x00EireUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x91\x00\x00\x00\b\x00\x00\x00\x14\xff\xff\xff\xffW\xd1\n\xdc\xff\xff\xff\xff\x9b&\xb3\x91\xff\xff\xff\xff\x9b\xd6\v\x11\xff\xff\xff\xff\x9c\xcf0\xa0\xff\xff\xff\xff\x9d\xa4à\xff\xff\xff\xff\x9e" + + "\x9c\x9d\xa0\xff\xff\xff\xff\x9f\x97\x1a\xa0\xff\xff\xff\xff\xa0\x85\xba \xff\xff\xff\xff\xa1v\xfc\xa0\xff\xff\xff\xff\xa2e\x9c \xff\xff\xff\xff\xa3{Ƞ\xff\xff\xff\xff\xa4N\xb8\xa0\xff\xff\xff\xff\xa5?\xfb \xff" + + "\xff\xff\xff\xa6%` \xff\xff\xff\xff\xa7'\xc6 \xff\xff\xff\xff\xa8*, \xff\xff\xff\xff\xa8\xeb\xf8\xa0\xff\xff\xff\xff\xaa\x00Ӡ\xff\xff\xff\xff\xaa\xd5\x15 \xff\xff\xff\xff\xab\xe9\xf0 \xff\xff\xff\xff\xac" + + "\xc7l \xff\xff\xff\xff\xad\xc9\xd2 \xff\xff\xff\xff\xae\xa7N \xff\xff\xff\xff\xaf\xa0y\xa0\xff\xff\xff\xff\xb0\x870 \xff\xff\xff\xff\xb1\x92Р\xff\xff\xff\xff\xb2pL\xa0\xff\xff\xff\xff\xb3r\xb2\xa0\xff" + + "\xff\xff\xff\xb4P.\xa0\xff\xff\xff\xff\xb5IZ \xff\xff\xff\xff\xb60\x10\xa0\xff\xff\xff\xff\xb72v\xa0\xff\xff\xff\xff\xb8\x0f\xf2\xa0\xff\xff\xff\xff\xb9\x12X\xa0\xff\xff\xff\xff\xb9\xefԠ\xff\xff\xff\xff\xba" + + "\xe9\x00 \xff\xff\xff\xff\xbb\xd8\xf1 \xff\xff\xff\xff\xbc\xdbW \xff\xff\xff\xff\xbd\xb8\xd3 \xff\xff\xff\xff\xbe\xb1\xfe\xa0\xff\xff\xff\xff\xbf\x98\xb5 \xff\xff\xff\xff\xc0\x9b\x1b \xff\xff\xff\xff\xc1x\x97 \xff" + + "\xff\xff\xff\xc2z\xfd \xff\xff\xff\xff\xc3Xy \xff\xff\xff\xff\xc4Q\xa4\xa0\xff\xff\xff\xff\xc58[ \xff\xff\xff\xff\xc6:\xc1 \xff\xff\xff\xff\xc7X֠\xff\xff\xff\xff\xc7\xda\t\xa0\xff\xff\xff\xff\xd4" + + "I\xe0 \xff\xff\xff\xff\xd5\x1e!\xa0\xff\xff\xff\xff\xd6N\xac \xff\xff\xff\xff\xd7,( \xff\xff\xff\xff\xd8.\x8e \xff\xff\xff\xff\xd8\xf9\x95 \xff\xff\xff\xff\xda\x0ep \xff\xff\xff\xff\xda\xeb\xec \xff" + + "\xff\xff\xff\xdb\xe5\x17\xa0\xff\xff\xff\xff\xdc\xcb\xce \xff\xff\xff\xff\xdd\xc4\xf9\xa0\xff\xff\xff\xff\u07b4\xea\xa0\xff\xff\xff\xff߮\x16 \xff\xff\xff\xff\xe0\x94̠\xff\xff\xff\xff\xe1rH\xa0\xff\xff\xff\xff\xe2" + + "kt \xff\xff\xff\xff\xe3R*\xa0\xff\xff\xff\xff\xe4T\x90\xa0\xff\xff\xff\xff\xe52\f\xa0\xff\xff\xff\xff\xe6=\xad \xff\xff\xff\xff\xe7\x1b) \xff\xff\xff\xff\xe8\x14T\xa0\xff\xff\xff\xff\xe8\xfb\v \xff" + + "\xff\xff\xff\xe9\xfdq \xff\xff\xff\xff\xea\xda\xed \xff\xff\xff\xff\xeb\xddS \xff\xff\xff\xff\xec\xba\xcf \xff\xff\xff\xff\xed\xb3\xfa\xa0\xff\xff\xff\xff\ue6b1 \xff\xff\xff\xff\xef\x81g\xa0\xff\xff\xff\xff\xf0" + + "\x9f} \xff\xff\xff\xff\xf1aI\xa0\xff\xff\xff\xff\xf2\u007f_ \xff\xff\xff\xff\xf3Jf \xff\xff\xff\xff\xf4_A \xff\xff\xff\xff\xf5!\r\xa0\xff\xff\xff\xff\xf6?# \xff\xff\xff\xff\xf7\x00\xef\xa0\xff" + + "\xff\xff\xff\xf8\x1f\x05 \xff\xff\xff\xff\xf8\xe0Ѡ\xff\xff\xff\xff\xf9\xfe\xe7 \xff\xff\xff\xff\xfa\xc0\xb3\xa0\xff\xff\xff\xff\xfb\xe8\x03\xa0\xff\xff\xff\xff\xfc{\xab\xa0\xff\xff\xff\xff\xfdǻp\x00\x00\x00\x00\x03" + + "p\xc6 \x00\x00\x00\x00\x04)X \x00\x00\x00\x00\x05P\xa8 \x00\x00\x00\x00\x06\t: \x00\x00\x00\x00\a0\x8a \x00\x00\x00\x00\a\xe9\x1c \x00\x00\x00\x00\t\x10l \x00\x00\x00\x00\t\xc8\xfe \x00" + + "\x00\x00\x00\n\xf0N \x00\x00\x00\x00\v\xb2\x1a\xa0\x00\x00\x00\x00\f\xd00 \x00\x00\x00\x00\r\x91\xfc\xa0\x00\x00\x00\x00\x0e\xb0\x12 \x00\x00\x00\x00\x0fqޠ\x00\x00\x00\x00\x10\x99.\xa0\x00\x00\x00\x00\x11" + + "Q\xc0\xa0\x00\x00\x00\x00\x12y\x10\xa0\x00\x00\x00\x00\x131\xa2\xa0\x00\x00\x00\x00\x14X\xf2\xa0\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x168Ɛ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x18\x18\xa8\x90\x00" + + "\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19\xf8\x8a\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xe1\xa7\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\xc1\x89\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f" + + "\xa1k\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\x81M\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#a/\x10\x00\x00\x00\x00$,6\x10\x00\x00\x00\x00%JK\x90\x00\x00\x00\x00&\f\x18\x10\x00" + + "\x00\x00\x00'*-\x90\x00\x00\x00\x00'\xf54\x90\x00\x00\x00\x00)\n\x0f\x90\x00\x00\x00\x00)\xd5\x16\x90\x00\x00\x00\x00*\xe9\xf1\x90\x00\x00\x00\x00+\xb4\xf8\x90\x00\x00\x00\x00,\xc9Ӑ\x00\x00\x00\x00-" + + "\x94ڐ\x00\x00\x00\x00.\xa9\xb5\x90\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000\x89\x97\x90\x00\x00\x00\x001]\xd9\x10\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04" + + "\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04" + + "\x05\x04\x05\x04\x05\x04\x05\x04\x05\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a" + + "\xff\xff\xfa$\x00\x00\xff\xff\xfa\x0f\x00\x04\x00\x00\b\x1f\x01\b\x00\x00\x0e\x10\x01\f\x00\x00\x00\x00\x00\x10\x00\x00\x0e\x10\x01\b\x00\x00\x00\x00\x01\x10\x00\x00\x0e\x10\x00\bLMT\x00DMT\x00IST\x00" + + "BST\x00GMT\x00\nIST-1GMT0,M10.5.0,M3.5.0/1\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iStX\xbe\xe4o\x00\x00\x00o\x00" + + "\x00\x00\x03\x00\x1c\x00ESTUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xff\xb9\xb0\x00\x00EST\x00\nEST5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xe7/\xebT\xb7\x03\x00\x00\xb7\x03\x00\x00\a\x00\x1c\x00ES" + + "T5EDTUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00X" + + "\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff\x9e\xa6\x1ep\xff\xff\xff\xff\x9f\xba\xeb`\xff\xff\xff\xff\xa0\x86\x00p\xff\xff\xff\xff\xa1\x9a\xcd`\xff\xff\xff\xffˈ\xf0p\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff" + + "\xd2`\xfb\xe0\xff\xff\xff\xff\xfa\xf8X\xf0\xff\xff\xff\xff\xfb\xe8;\xe0\xff\xff\xff\xff\xfc\xd8:\xf0\xff\xff\xff\xff\xfd\xc8\x1d\xe0\xff\xff\xff\xff\xfe\xb8\x1c\xf0\xff\xff\xff\xff\xff\xa7\xff\xe0\x00\x00\x00\x00\x00\x97\xfe\xf0" + + "\x00\x00\x00\x00\x01\x87\xe1\xe0\x00\x00\x00\x00\x02w\xe0\xf0\x00\x00\x00\x00\x03p\xfe`\x00\x00\x00\x00\x04`\xfdp\x00\x00\x00\x00\x05P\xe0`\x00\x00\x00\x00\x06@\xdfp\x00\x00\x00\x00\a0\xc2`\x00\x00\x00\x00" + + "\a\x8d\x19p\x00\x00\x00\x00\t\x10\xa4`\x00\x00\x00\x00\t\xad\x94\xf0\x00\x00\x00\x00\n\xf0\x86`\x00\x00\x00\x00\v\xe0\x85p\x00\x00\x00\x00\f٢\xe0\x00\x00\x00\x00\r\xc0gp\x00\x00\x00\x00\x0e\xb9\x84\xe0" + + "\x00\x00\x00\x00\x0f\xa9\x83\xf0\x00\x00\x00\x00\x10\x99f\xe0\x00\x00\x00\x00\x11\x89e\xf0\x00\x00\x00\x00\x12yH\xe0\x00\x00\x00\x00\x13iG\xf0\x00\x00\x00\x00\x14Y*\xe0\x00\x00\x00\x00\x15I)\xf0\x00\x00\x00\x00" + + "\x169\f\xe0\x00\x00\x00\x00\x17)\v\xf0\x00\x00\x00\x00\x18\")`\x00\x00\x00\x00\x19\b\xed\xf0\x00\x00\x00\x00\x1a\x02\v`\x00\x00\x00\x00\x1a\xf2\np\x00\x00\x00\x00\x1b\xe1\xed`\x00\x00\x00\x00\x1c\xd1\xecp" + + "\x00\x00\x00\x00\x1d\xc1\xcf`\x00\x00\x00\x00\x1e\xb1\xcep\x00\x00\x00\x00\x1f\xa1\xb1`\x00\x00\x00\x00 v\x00\xf0\x00\x00\x00\x00!\x81\x93`\x00\x00\x00\x00\"U\xe2\xf0\x00\x00\x00\x00#j\xaf\xe0\x00\x00\x00\x00" + + "$5\xc4\xf0\x00\x00\x00\x00%J\x91\xe0\x00\x00\x00\x00&\x15\xa6\xf0\x00\x00\x00\x00'*s\xe0\x00\x00\x00\x00'\xfe\xc3p\x00\x00\x00\x00)\nU\xe0\x00\x00\x00\x00)ޥp\x00\x00\x00\x00*\xea7\xe0" + + "\x00\x00\x00\x00+\xbe\x87p\x00\x00\x00\x00,\xd3T`\x00\x00\x00\x00-\x9eip\x00\x00\x00\x00.\xb36`\x00\x00\x00\x00/~Kp\x00\x00\x00\x000\x93\x18`\x00\x00\x00\x001gg\xf0\x00\x00\x00\x00" + + "2r\xfa`\x00\x00\x00\x003GI\xf0\x00\x00\x00\x004R\xdc`\x00\x00\x00\x005'+\xf0\x00\x00\x00\x0062\xbe`\x00\x00\x00\x007\a\r\xf0\x00\x00\x00\x008\x1b\xda\xe0\x00\x00\x00\x008\xe6\xef\xf0" + + "\x00\x00\x00\x009\xfb\xbc\xe0\x00\x00\x00\x00:\xc6\xd1\xf0\x00\x00\x00\x00;۞\xe0\x00\x00\x00\x00<\xaf\xeep\x00\x00\x00\x00=\xbb\x80\xe0\x00\x00\x00\x00>\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00" + + "@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x01\x00\x01\x00\x02\x03\x00\x01" + + "\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01" + + "\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\xff\xff\xb9\xb0\x00\x04\xff\xff\xc7\xc0\x01\x00\xff\xff\xc7\xc0\x01\b\xff\xff\xc7\xc0\x01\fEDT\x00EST\x00EWT\x00EPT\x00" + + "\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x1c\x00Etc/UT" + + "\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb2\xab\xd1Is\x00\x00\x00s\x00\x00\x00\n\x00\x1c\x00Etc/" + + "GMT-11UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x9a\xb0\x00\x00+11\x00\n<+11>-11\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xa9{\xa2qq\x00\x00\x00q\x00\x00\x00\t\x00\x1c\x00E" + + "tc/GMT+2UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xff\xe3\xe0\x00\x00-02\x00\n<-02>2\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x9f.\xe4xo\x00\x00\x00o\x00\x00\x00\a\x00\x1c\x00E" + + "tc/UCTUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00UTC\x00\nUTC0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xf7\x1ac\xc3r\x00\x00\x00r\x00\x00\x00\t\x00\x1c\x00Etc/G" + + "MT-1UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x01\x00\x00\x00\x04\x00\x00\x0e\x10\x00\x00+01\x00\n<+01>-1\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSP\xda\xfa\x03o\x00\x00\x00o\x00\x00\x00\t\x00\x1c\x00Etc/" + + "GMT+0UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\"\xf8\x8f/q\x00\x00\x00q\x00\x00\x00\t\x00\x1c\x00Etc/GM" + + "T+8UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x01\x00\x00\x00\x04\xff\xff\x8f\x80\x00\x00-08\x00\n<-08>8\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xd4X\x9b\xf3q\x00\x00\x00q\x00\x00\x00\t\x00\x1c\x00Etc/GM" + + "T+5UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x01\x00\x00\x00\x04\xff\xff\xb9\xb0\x00\x00-05\x00\n<-05>5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x9f.\xe4xo\x00\x00\x00o\x00\x00\x00\b\x00\x1c\x00Etc/Zu" + + "luUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00UTC\x00\nUTC0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSJ0p-r\x00\x00\x00r\x00\x00\x00\t\x00\x1c\x00Etc/GMT-7" + + "UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00" + + "\x00\x00\x04\x00\x00bp\x00\x00+07\x00\n<+07>-7\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xd0\xfaFDq\x00\x00\x00q\x00\x00\x00\t\x00\x1c\x00Etc/GMT+" + + "4UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" + + "\x00\x00\x00\x04\xff\xff\xc7\xc0\x00\x00-04\x00\n<-04>4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xf7\x19s\x81s\x00\x00\x00s\x00\x00\x00\n\x00\x1c\x00Etc/GMT-" + + "12UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x01\x00\x00\x00\x04\x00\x00\xa8\xc0\x00\x00+12\x00\n<+12>-12\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x9f.\xe4xo\x00\x00\x00o\x00\x00\x00\r\x00\x1c\x00Etc/U" + + "niversalUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00UTC\x00\nUTC0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x9c\xfcm\x99r\x00\x00\x00r\x00\x00\x00\t\x00\x1c\x00Etc" + + "/GMT-3UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00*0\x00\x00+03\x00\n<+03>-3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSP\xda\xfa\x03o\x00\x00\x00o\x00\x00\x00\a\x00\x1c\x00Et" + + "c/GMTUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xfc\x19@\xb9r\x00\x00\x00r\x00\x00\x00\t\x00\x1c\x00Etc/GM" + + "T-9UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x01\x00\x00\x00\x04\x00\x00~\x90\x00\x00+09\x00\n<+09>-9\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xd9|\xbd7s\x00\x00\x00s\x00\x00\x00\n\x00\x1c\x00Etc/G" + + "MT-10UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x8c\xa0\x00\x00+10\x00\n<+10>-10\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x84\x19\xb3\tq\x00\x00\x00q\x00\x00\x00\t\x00\x1c\x00Et" + + "c/GMT+9UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xff\x81p\x00\x00-09\x00\n<-09>9\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS!\xd6~wr\x00\x00\x00r\x00\x00\x00\t\x00\x1c\x00Et" + + "c/GMT-5UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00FP\x00\x00+05\x00\n<+05>-5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSj\xd5d\xb0r\x00\x00\x00r\x00\x00\x00\t\x00\x1c\x00E" + + "tc/GMT-6UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00T`\x00\x00+06\x00\n<+06>-6\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x90`N\xe8s\x00\x00\x00s\x00\x00\x00\n\x00\x1c\x00" + + "Etc/GMT-13UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\xb6\xd0\x00\x00+13\x00\n<+13>-13\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSP\xda\xfa\x03o\x00\x00\x00o\x00\x00\x00\r" + + "\x00\x1c\x00Etc/GreenwichUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS5\xb8\xe8\x86q\x00\x00\x00q\x00\x00" + + "\x00\t\x00\x1c\x00Etc/GMT+1UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xff\x1eI\x92\xf8\xff\xff\xff\xffl\xcf\xea\xf8\xff\xff\xff\xff\x9b\f\x17`\xff\xff\xff\xff\x9b\xd5\xda\xf0\xff\xff\xff\xff\x9cٮ\x90\xff\xff\xff" + - "\xff\x9d\xa4\xb5\x90\xff\xff\xff\xff\x9e\xb9\x90\x90\xff\xff\xff\xff\x9f\x84\x97\x90\xff\xff\xff\xff\xc8\tq\x90\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4" + - "\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd2b\a\x10\xff\xff\xff\xffӀ\x1c\x90\xff\xff\xff\xff\xd4I\xd2\x10\xff\xff\xff\xffԓ\xb4 \xff\xff\xff\xff\xd5\x02r \xff\xff\xff" + - "\xff\xd5L8\x10\xff\xff\xff\xff\xd6)\xb4\x10\xff\xff\xff\xff\xd7,\x1a\x10\xff\xff\xff\xff\xd8\t\x96\x10\xff\xff\xff\xff\xd9\x01p\x10\xff\xff\xff\xff\xd9\xe9x\x10\x00\x00\x00\x00\x11d'\x90\x00\x00\x00\x00\x12T\x18" + - "\x90\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xff\xf1\xf0\x00\x00-01\x00\n<-01>1\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSe\xcb\xe9Qq\x00\x00\x00q\x00\x00" + + "\x00\t\x00\x1c\x00Etc/GMT+3UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xff\xd5\xd0\x00\x00-03\x00\n<-03>3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x9f.\xe4xo\x00\x00\x00o\x00\x00" + + "\x00\a\x00\x1c\x00Etc/UTCUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00UTC\x00\nUTC0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x8e\x1569r\x00\x00\x00r\x00\x00\x00\n\x00\x1c" + + "\x00Etc/GMT+10UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xffs`\x00\x00-10\x00\n<-10>10\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSP\xda\xfa\x03o\x00\x00\x00o\x00\x00\x00\t" + + "\x00\x1c\x00Etc/GMT-0UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x84+\x9a$q\x00\x00\x00q\x00\x00\x00\t\x00\x1c" + + "\x00Etc/GMT+7UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xff\x9d\x90\x00\x00-07\x00\n<-07>7\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xe5\xf38cr\x00\x00\x00r\x00\x00\x00\n\x00\x1c" + + "\x00Etc/GMT+12UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xffW@\x00\x00-12\x00\n<-12>12\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSH\x9b\xd1\x04q\x00\x00\x00q\x00\x00\x00\t" + + "\x00\x1c\x00Etc/GMT+6UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xff\xab\xa0\x00\x00-06\x00\n<-06>6\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xc5\x18\xb6\xfbr\x00\x00\x00r\x00\x00\x00\t" + + "\x00\x1c\x00Etc/GMT-8UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00p\x80\x00\x00+08\x00\n<+08>-8\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS)\xb9\xbe\x9dr\x00\x00\x00r\x00\x00\x00" + + "\n\x00\x1c\x00Etc/GMT+11UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xffeP\x00\x00-11\x00\n<-11>11\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS,{\xdc;s\x00\x00\x00s\x00" + + "\x00\x00\n\x00\x1c\x00Etc/GMT-14UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\xc4\xe0\x00\x00+14\x00\n<+14>-14\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSP\xda\xfa\x03o\x00\x00" + + "\x00o\x00\x00\x00\b\x00\x1c\x00Etc/GMT0UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSk\x19-4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xbc\x19y\x04r\x00\x00\x00r" + + "\x00\x00\x00\t\x00\x1c\x00Etc/GMT-2UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x1c \x00\x00+02\x00\n<+02>-2\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\a\x00\x1c\x00Europe/UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x9a\v\xf9" + + "/\xd8\x05\x00\x00\xd8\x05\x00\x00\r\x00\x1c\x00Europe/DublinUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x91\x00\x00\x00\b\x00\x00\x00\x14\xff\xff\xff\xffW\xd1\n\xdc\xff\xff\xff\xff\x9b&\xb3\x91\xff\xff\xff\xff\x9b\xd6\v\x11\xff\xff\xff\xff\x9c\xcf0" + + "\xa0\xff\xff\xff\xff\x9d\xa4à\xff\xff\xff\xff\x9e\x9c\x9d\xa0\xff\xff\xff\xff\x9f\x97\x1a\xa0\xff\xff\xff\xff\xa0\x85\xba \xff\xff\xff\xff\xa1v\xfc\xa0\xff\xff\xff\xff\xa2e\x9c \xff\xff\xff\xff\xa3{Ƞ\xff\xff\xff" + + "\xff\xa4N\xb8\xa0\xff\xff\xff\xff\xa5?\xfb \xff\xff\xff\xff\xa6%` \xff\xff\xff\xff\xa7'\xc6 \xff\xff\xff\xff\xa8*, \xff\xff\xff\xff\xa8\xeb\xf8\xa0\xff\xff\xff\xff\xaa\x00Ӡ\xff\xff\xff\xff\xaa\xd5\x15" + + " \xff\xff\xff\xff\xab\xe9\xf0 \xff\xff\xff\xff\xac\xc7l \xff\xff\xff\xff\xad\xc9\xd2 \xff\xff\xff\xff\xae\xa7N \xff\xff\xff\xff\xaf\xa0y\xa0\xff\xff\xff\xff\xb0\x870 \xff\xff\xff\xff\xb1\x92Р\xff\xff\xff" + + "\xff\xb2pL\xa0\xff\xff\xff\xff\xb3r\xb2\xa0\xff\xff\xff\xff\xb4P.\xa0\xff\xff\xff\xff\xb5IZ \xff\xff\xff\xff\xb60\x10\xa0\xff\xff\xff\xff\xb72v\xa0\xff\xff\xff\xff\xb8\x0f\xf2\xa0\xff\xff\xff\xff\xb9\x12X" + + "\xa0\xff\xff\xff\xff\xb9\xefԠ\xff\xff\xff\xff\xba\xe9\x00 \xff\xff\xff\xff\xbb\xd8\xf1 \xff\xff\xff\xff\xbc\xdbW \xff\xff\xff\xff\xbd\xb8\xd3 \xff\xff\xff\xff\xbe\xb1\xfe\xa0\xff\xff\xff\xff\xbf\x98\xb5 \xff\xff\xff" + + "\xff\xc0\x9b\x1b \xff\xff\xff\xff\xc1x\x97 \xff\xff\xff\xff\xc2z\xfd \xff\xff\xff\xff\xc3Xy \xff\xff\xff\xff\xc4Q\xa4\xa0\xff\xff\xff\xff\xc58[ \xff\xff\xff\xff\xc6:\xc1 \xff\xff\xff\xff\xc7X\xd6" + + "\xa0\xff\xff\xff\xff\xc7\xda\t\xa0\xff\xff\xff\xff\xd4I\xe0 \xff\xff\xff\xff\xd5\x1e!\xa0\xff\xff\xff\xff\xd6N\xac \xff\xff\xff\xff\xd7,( \xff\xff\xff\xff\xd8.\x8e \xff\xff\xff\xff\xd8\xf9\x95 \xff\xff\xff" + + "\xff\xda\x0ep \xff\xff\xff\xff\xda\xeb\xec \xff\xff\xff\xff\xdb\xe5\x17\xa0\xff\xff\xff\xff\xdc\xcb\xce \xff\xff\xff\xff\xdd\xc4\xf9\xa0\xff\xff\xff\xff\u07b4\xea\xa0\xff\xff\xff\xff߮\x16 \xff\xff\xff\xff\xe0\x94\xcc" + + "\xa0\xff\xff\xff\xff\xe1rH\xa0\xff\xff\xff\xff\xe2kt \xff\xff\xff\xff\xe3R*\xa0\xff\xff\xff\xff\xe4T\x90\xa0\xff\xff\xff\xff\xe52\f\xa0\xff\xff\xff\xff\xe6=\xad \xff\xff\xff\xff\xe7\x1b) \xff\xff\xff" + + "\xff\xe8\x14T\xa0\xff\xff\xff\xff\xe8\xfb\v \xff\xff\xff\xff\xe9\xfdq \xff\xff\xff\xff\xea\xda\xed \xff\xff\xff\xff\xeb\xddS \xff\xff\xff\xff\xec\xba\xcf \xff\xff\xff\xff\xed\xb3\xfa\xa0\xff\xff\xff\xff\ue6b1" + + " \xff\xff\xff\xff\xef\x81g\xa0\xff\xff\xff\xff\xf0\x9f} \xff\xff\xff\xff\xf1aI\xa0\xff\xff\xff\xff\xf2\u007f_ \xff\xff\xff\xff\xf3Jf \xff\xff\xff\xff\xf4_A \xff\xff\xff\xff\xf5!\r\xa0\xff\xff\xff" + + "\xff\xf6?# \xff\xff\xff\xff\xf7\x00\xef\xa0\xff\xff\xff\xff\xf8\x1f\x05 \xff\xff\xff\xff\xf8\xe0Ѡ\xff\xff\xff\xff\xf9\xfe\xe7 \xff\xff\xff\xff\xfa\xc0\xb3\xa0\xff\xff\xff\xff\xfb\xe8\x03\xa0\xff\xff\xff\xff\xfc{\xab" + + "\xa0\xff\xff\xff\xff\xfdǻp\x00\x00\x00\x00\x03p\xc6 \x00\x00\x00\x00\x04)X \x00\x00\x00\x00\x05P\xa8 \x00\x00\x00\x00\x06\t: \x00\x00\x00\x00\a0\x8a \x00\x00\x00\x00\a\xe9\x1c \x00\x00\x00" + + "\x00\t\x10l \x00\x00\x00\x00\t\xc8\xfe \x00\x00\x00\x00\n\xf0N \x00\x00\x00\x00\v\xb2\x1a\xa0\x00\x00\x00\x00\f\xd00 \x00\x00\x00\x00\r\x91\xfc\xa0\x00\x00\x00\x00\x0e\xb0\x12 \x00\x00\x00\x00\x0fq\xde" + + "\xa0\x00\x00\x00\x00\x10\x99.\xa0\x00\x00\x00\x00\x11Q\xc0\xa0\x00\x00\x00\x00\x12y\x10\xa0\x00\x00\x00\x00\x131\xa2\xa0\x00\x00\x00\x00\x14X\xf2\xa0\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x168Ɛ\x00\x00\x00" + + "\x00\x17\x03͐\x00\x00\x00\x00\x18\x18\xa8\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19\xf8\x8a\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xe1\xa7\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\xc1\x89" + + "\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f\xa1k\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\x81M\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#a/\x10\x00\x00\x00\x00$,6\x10\x00\x00\x00" + + "\x00%JK\x90\x00\x00\x00\x00&\f\x18\x10\x00\x00\x00\x00'*-\x90\x00\x00\x00\x00'\xf54\x90\x00\x00\x00\x00)\n\x0f\x90\x00\x00\x00\x00)\xd5\x16\x90\x00\x00\x00\x00*\xe9\xf1\x90\x00\x00\x00\x00+\xb4\xf8" + + "\x90\x00\x00\x00\x00,\xc9Ӑ\x00\x00\x00\x00-\x94ڐ\x00\x00\x00\x00.\xa9\xb5\x90\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000\x89\x97\x90\x00\x00\x00\x001]\xd9\x10\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04" + + "\x03\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04" + + "\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a" + + "\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\x06\a\xff\xff\xfa$\x00\x00\xff\xff\xfa\x0f\x00\x04\x00\x00\b\x1f\x01\b\x00\x00\x0e\x10\x01\f\x00\x00\x00\x00\x00\x10\x00\x00\x0e\x10\x01\b\x00\x00\x00\x00\x01\x10\x00\x00\x0e\x10" + + "\x00\bLMT\x00DMT\x00IST\x00BST\x00GMT\x00\nIST-1GMT0,M10.5.0,M3.5.0/1\nPK\x03\x04\n\x00\x00\x00\x00\x00" + + "#\x82iSk\xa4,\xb6?\x06\x00\x00?\x06\x00\x00\x0e\x00\x1c\x00Europe/BelfastUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_" + + "\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9f\x00\x00\x00\x05\x00\x00\x00\x11\xff\xff\xff\xff\x1a]\t\xcb\xff\xff\xff\xff\x9b&\xad\xa0\xff\xff\xff\xff\x9b\xd6\x05" + + " \xff\xff\xff\xff\x9c\xcf0\xa0\xff\xff\xff\xff\x9d\xa4à\xff\xff\xff\xff\x9e\x9c\x9d\xa0\xff\xff\xff\xff\x9f\x97\x1a\xa0\xff\xff\xff\xff\xa0\x85\xba \xff\xff\xff\xff\xa1v\xfc\xa0\xff\xff\xff\xff\xa2e\x9c \xff\xff\xff" + + "\xff\xa3{Ƞ\xff\xff\xff\xff\xa4N\xb8\xa0\xff\xff\xff\xff\xa5?\xfb \xff\xff\xff\xff\xa6%` \xff\xff\xff\xff\xa7'\xc6 \xff\xff\xff\xff\xa8*, \xff\xff\xff\xff\xa8\xeb\xf8\xa0\xff\xff\xff\xff\xaa\x00\xd3" + + "\xa0\xff\xff\xff\xff\xaa\xd5\x15 \xff\xff\xff\xff\xab\xe9\xf0 \xff\xff\xff\xff\xac\xc7l \xff\xff\xff\xff\xad\xc9\xd2 \xff\xff\xff\xff\xae\xa7N \xff\xff\xff\xff\xaf\xa0y\xa0\xff\xff\xff\xff\xb0\x870 \xff\xff\xff" + + "\xff\xb1\x92Р\xff\xff\xff\xff\xb2pL\xa0\xff\xff\xff\xff\xb3r\xb2\xa0\xff\xff\xff\xff\xb4P.\xa0\xff\xff\xff\xff\xb5IZ \xff\xff\xff\xff\xb60\x10\xa0\xff\xff\xff\xff\xb72v\xa0\xff\xff\xff\xff\xb8\x0f\xf2" + + "\xa0\xff\xff\xff\xff\xb9\x12X\xa0\xff\xff\xff\xff\xb9\xefԠ\xff\xff\xff\xff\xba\xe9\x00 \xff\xff\xff\xff\xbb\xd8\xf1 \xff\xff\xff\xff\xbc\xdbW \xff\xff\xff\xff\xbd\xb8\xd3 \xff\xff\xff\xff\xbe\xb1\xfe\xa0\xff\xff\xff" + + "\xff\xbf\x98\xb5 \xff\xff\xff\xff\xc0\x9b\x1b \xff\xff\xff\xff\xc1x\x97 \xff\xff\xff\xff\xc2z\xfd \xff\xff\xff\xff\xc3Xy \xff\xff\xff\xff\xc4Q\xa4\xa0\xff\xff\xff\xff\xc58[ \xff\xff\xff\xff\xc6:\xc1" + + " \xff\xff\xff\xff\xc7X֠\xff\xff\xff\xff\xc7\xda\t\xa0\xff\xff\xff\xff\xca\x16&\x90\xff\xff\xff\xffʗY\x90\xff\xff\xff\xff\xcb\xd1\x1e\x90\xff\xff\xff\xff\xccw;\x90\xff\xff\xff\xffͱ\x00\x90\xff\xff\xff" + + "\xff\xce`X\x10\xff\xff\xff\xffϐ\xe2\x90\xff\xff\xff\xff\xd0n^\x90\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd1\xfb2\x10\xff\xff\xff\xff\xd2i\xfe \xff\xff\xff\xff\xd3c)\xa0\xff\xff\xff\xff\xd4I\xe0" + + " \xff\xff\xff\xff\xd5\x1e!\xa0\xff\xff\xff\xff\xd5B\xfd\x90\xff\xff\xff\xff\xd5\xdf\xe0\x10\xff\xff\xff\xff\xd6N\xac \xff\xff\xff\xff\xd6\xfe\x03\xa0\xff\xff\xff\xff\xd8.\x8e \xff\xff\xff\xff\xd8\xf9\x95 \xff\xff\xff" + + "\xff\xda\x0ep \xff\xff\xff\xff\xda\xeb\xec \xff\xff\xff\xff\xdb\xe5\x17\xa0\xff\xff\xff\xff\xdc\xcb\xce \xff\xff\xff\xff\xdd\xc4\xf9\xa0\xff\xff\xff\xff\u07b4\xea\xa0\xff\xff\xff\xff߮\x16 \xff\xff\xff\xff\xe0\x94\xcc" + + "\xa0\xff\xff\xff\xff\xe1rH\xa0\xff\xff\xff\xff\xe2kt \xff\xff\xff\xff\xe3R*\xa0\xff\xff\xff\xff\xe4T\x90\xa0\xff\xff\xff\xff\xe52\f\xa0\xff\xff\xff\xff\xe6=\xad \xff\xff\xff\xff\xe7\x1b) \xff\xff\xff" + + "\xff\xe8\x14T\xa0\xff\xff\xff\xff\xe8\xfb\v \xff\xff\xff\xff\xe9\xfdq \xff\xff\xff\xff\xea\xda\xed \xff\xff\xff\xff\xeb\xddS \xff\xff\xff\xff\xec\xba\xcf \xff\xff\xff\xff\xed\xb3\xfa\xa0\xff\xff\xff\xff\ue6b1" + + " \xff\xff\xff\xff\xef\x81g\xa0\xff\xff\xff\xff\xf0\x9f} \xff\xff\xff\xff\xf1aI\xa0\xff\xff\xff\xff\xf2\u007f_ \xff\xff\xff\xff\xf3Jf \xff\xff\xff\xff\xf4_A \xff\xff\xff\xff\xf5!\r\xa0\xff\xff\xff" + + "\xff\xf6?# \xff\xff\xff\xff\xf7\x00\xef\xa0\xff\xff\xff\xff\xf8\x1f\x05 \xff\xff\xff\xff\xf8\xe0Ѡ\xff\xff\xff\xff\xf9\xfe\xe7 \xff\xff\xff\xff\xfa\xc0\xb3\xa0\xff\xff\xff\xff\xfb\xe8\x03\xa0\xff\xff\xff\xff\xfc{\xab" + + "\xa0\xff\xff\xff\xff\xfdǻp\x00\x00\x00\x00\x03p\xc6 \x00\x00\x00\x00\x04)X \x00\x00\x00\x00\x05P\xa8 \x00\x00\x00\x00\x06\t: \x00\x00\x00\x00\a0\x8a \x00\x00\x00\x00\a\xe9\x1c \x00\x00\x00" + + "\x00\t\x10l \x00\x00\x00\x00\t\xc8\xfe \x00\x00\x00\x00\n\xf0N \x00\x00\x00\x00\v\xb2\x1a\xa0\x00\x00\x00\x00\f\xd00 \x00\x00\x00\x00\r\x91\xfc\xa0\x00\x00\x00\x00\x0e\xb0\x12 \x00\x00\x00\x00\x0fq\xde" + + "\xa0\x00\x00\x00\x00\x10\x99.\xa0\x00\x00\x00\x00\x11Q\xc0\xa0\x00\x00\x00\x00\x12y\x10\xa0\x00\x00\x00\x00\x131\xa2\xa0\x00\x00\x00\x00\x14X\xf2\xa0\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x168Ɛ\x00\x00\x00" + + "\x00\x17\x03͐\x00\x00\x00\x00\x18\x18\xa8\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19\xf8\x8a\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xe1\xa7\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\xc1\x89" + + "\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f\xa1k\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\x81M\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#a/\x10\x00\x00\x00\x00$,6\x10\x00\x00\x00" + + "\x00%JK\x90\x00\x00\x00\x00&\f\x18\x10\x00\x00\x00\x00'*-\x90\x00\x00\x00\x00'\xf54\x90\x00\x00\x00\x00)\n\x0f\x90\x00\x00\x00\x00)\xd5\x16\x90\x00\x00\x00\x00*\xe9\xf1\x90\x00\x00\x00\x00+\xb4\xf8" + + "\x90\x00\x00\x00\x00,\xc9Ӑ\x00\x00\x00\x00-\x94ڐ\x00\x00\x00\x00.\xa9\xb5\x90\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000\x89\x97\x90\x00\x00\x00\x001]\xd9\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x02\x01\x02\x01\x03\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xff\xb5\x00\x00\x00\x00\x0e\x10\x01\x04\x00\x00\x00\x00\x00\b\x00\x00\x1c \x01\f\x00\x00\x0e\x10\x00\x04LM" + + "T\x00BST\x00GMT\x00BDST\x00\nGMT0BST,M3.5.0/1,M10.5.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSDd#\xc4\xf1" + + "\x01\x00\x00\xf1\x01\x00\x00\x0f\x00\x1c\x00Europe/BusingenUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00%\x00\x00\x00\x04\x00\x00\x00\x11\xff\xff\xff\xff$\xf0\xea\x80\xff\xff\xff\xffq\xd4\x06\x86\xff\xff\xff\xff\xca\x17j\x00\xff\xff\xff\xff\xca\xe2q" + + "\x00\xff\xff\xff\xff\xcb\xf7L\x00\xff\xff\xff\xff\xcc\xc2S\x00\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00" + "\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr" + "\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#\xf3`\xff\xff\xff\xff\xb9\xef\x9c`\xff\xff\xff\xff\xbaߍ`\xff\xff\xff\xff\xbb\xcf~`\xff\xff\xff\xff\xbcȩ\xe0\xff\xff\xff\xff\xbd\xb8\x9a\xe0\xff\xff\xff\xff\xbe\xa8\x8b\xe0\xff\xff\xff\xff\xbf\x98" + - "|\xe0\xff\xff\xff\xff\xc0\x88m\xe0\xff\xff\xff\xff\xc1x^\xe0\xff\xff\xff\xff\xc2hO\xe0\xff\xff\xff\xff\xc3X@\xe0\xff\xff\xff\xff\xc4H1\xe0\xff\xff\xff\xff\xc58\"\xe0\xff\xff\xff\xff\xc6(\x13\xe0\xff\xff" + - "\xff\xff\xc7\x18\x04\xe0\xff\xff\xff\xffȼ\x93`\xff\xff\xff\xff\xcaw}P\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xff\xd0N" + - "\x90`\x00\x00\x00\x00\x15'\xa7\xd0\x00\x00\x00\x00\x16\x18\xdc@\x00\x00\x00\x00\x17\b\xdbP\x00\x00\x00\x00\x17\xfa\x0f\xc0\x00\x00\x00\x00\x18\xea\x0e\xd0\x00\x00\x00\x00\x19\xdbC@\x00\x00\x00\x00\x1a̓\xd0\x00\x00" + - "\x00\x00\x1b\xbc\xa0\xf0\x00\x00\x00\x00\x1c\xac\x91\xf0\x00\x00\x00\x00\x1d\x9c\x82\xf0\x00\x00\x00\x00\x1e\x8cs\xf0\x00\x00\x00\x00\x1f|d\xf0\x00\x00\x00\x00 lU\xf0\x00\x00\x00\x00!\\F\xf0\x00\x00\x00\x00\"L" + - "7\xf0\x00\x00\x00\x00#<(\xf0\x00\x00\x00\x00$,\x19\xf0\x00\x00\x00\x00%\x1c\n\xf0\x00\x00\x00\x00&\v\xfb\xf0\x00\x00\x00\x00&CL\xe0\x00\x00\x00\x00'\x055\x80\x00\x00\x00\x00'\xf5&\x80\x00\x00" + - "\x00\x00(\xe5\x17\x80\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xc4\xcfP\x00\x00\x00\x00+\xb4\xce`\x00\x00\x00\x00,\xa4\xb1P\x00\x00\x00\x00-\x94\xb0`\x00\x00\x00\x00.\x84\x93P\x00\x00\x00\x00/t" + - "\x92`\x00\x00\x00\x000duP\x00\x00\x00\x001]\xae\xe0\x00\x00\x00\x002r{\xd0\x00\x00\x00\x003=\xad\x00\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x06\x05\x06\x05\x06\b" + - "\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x00\x00\x1b\b\x00\x00\x00\x00\x1a\xf4\x00\x04\x00\x00\x18x\x00\b\x00\x00*0\x01\f\x00\x00" + - "\x1c \x00\x11\x00\x00\x0e\x10\x00\x15\x00\x00\x1c \x01\x19\x00\x008@\x01\x1e\x00\x00*0\x00\"LMT\x00CMT\x00BMT\x00EEST\x00EET\x00CET\x00CEST\x00MS" + - "D\x00MSK\x00\nEET-2EEST,M3.5.0,M10.5.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xe1C\xf9\xa1\xde\x01\x00\x00\xde\x01\x00\x00" + - "\x10\x00\x1c\x00Europe/LjubljanaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$\x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff\xff^<\xf0H\xff\xff\xff\xff\xca\x025\xe0\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\xce" + - "\xa2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff\xffѡ\x8c\x10\xff\xff\xff\xff\xd2N@\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00" + + "\x90\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000d\xad\x90\x00\x00\x00\x001]\xd9\x10\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x00\x00\b\x00\x00\x00\x00\x00\x06\xfa\x00\x04\x00\x00\x1c \x01\b\x00\x00\x0e\x10\x00\rLMT\x00BMT\x00CEST\x00CET\x00\nCET-1CEST,M3.5.0" + + ",M10.5.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xe1C\xf9\xa1\xde\x01\x00\x00\xde\x01\x00\x00\r\x00\x1c\x00Europe/ZagrebUT\t\x00\x03\x82" + + "\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$\x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff" + + "\xff^<\xf0H\xff\xff\xff\xff\xca\x025\xe0\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff\xffѡ\x8c" + + "\x10\xff\xff\xff\xff\xd2N@\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00" + + "\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#\x86%p\x00\x00\x00\x00?\x9b\x00p\x00\x00\x00\x00@f\ap" + + "\x00\x00\x00\x00A\x84\x1c\xf0\x00\x00\x00\x00BE\xe9p\x00\x00\x00\x00Cc\xfe\xf0\x00\x00\x00\x00D%\xcbp\x00\x00\x00\x00EC\xe0\xf0\x00\x00\x00\x00F\x05\xadp\x00\x00\x00\x00G#\xc2\xf0\x00\x00\x00\x00" + + "G\xee\xc9\xf0\x00\x00\x00\x00I\x03\xa4\xf0\x00\x00\x00\x00IΫ\xf0\x00\x00\x00\x00J\xe3\x86\xf0\x00\x00\x00\x00K\xae\x8d\xf0\x00\x00\x00\x00Ḷp\x00\x00\x00\x00M\x8eo\xf0\x00\x00\x00\x00TL\x1d`" + + "\x00\x00\x00\x00[\xd4\xed\xf0\x00\x00\x00\x00_\xe7\xb2`\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x04\x01\x04\x01\x04\x01\x02\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04" + + "\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x02\x01\x02\x01\x00\x00)\xa4\x00\x00\x00\x00*0\x00\x04\x00\x008@\x00\b\x00\x00FP\x01\f\x00\x008@\x01\bLMT\x00+03\x00+" + + "04\x00+05\x00\n<+03>-3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSDd#\xc4\xf1\x01\x00\x00\xf1\x01\x00\x00\r\x00\x1c\x00Europe/ZurichU" + + "T\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00%\x00\x00\x00\x04\x00\x00" + + "\x00\x11\xff\xff\xff\xff$\xf0\xea\x80\xff\xff\xff\xffq\xd4\x06\x86\xff\xff\xff\xff\xca\x17j\x00\xff\xff\xff\xff\xca\xe2q\x00\xff\xff\xff\xff\xcb\xf7L\x00\xff\xff\xff\xff\xcc\xc2S\x00\x00\x00\x00\x00\x15#\xeb\x90\x00\x00" + + "\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac" + + "\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#\x86A\x90\x00\x00\x00\x00?" + - "\x9b\x1c\x90\x00\x00\x00\x00@f#\x90\x00\x00\x00\x00A\x849\x10\x00\x00\x00\x00BF\x05\x90\x00\x00\x00\x00Cd\x1b\x10\x00\x00\x00\x00D%\xe7\x90\x00\x00\x00\x00EC\xfd\x10\x00\x00\x00\x00F\x05ɐ\x00" + - "\x00\x00\x00G#\xdf\x10\x00\x00\x00\x00G\xee\xe6\x10\x00\x00\x00\x00I\x03\xc1\x10\x00\x00\x00\x00I\xce\xc8\x10\x00\x00\x00\x00J\xe3\xa3\x10\x00\x00\x00\x00K\xae\xaa\x10\x00\x00\x00\x00L̿\x90\x00\x00\x00\x00M" + - "\x8e\x8c\x10\x00\x00\x00\x00N\xac\xa1\x90\x00\x00\x00\x00Onn\x10\x00\x00\x00\x00P\x8c\x83\x90\x00\x00\x00\x00QW\x8a\x90\x00\x00\x00\x00Rle\x90\x00\x00\x00\x00S7^\x80\x00\x00\x00\x00TL\x1d`\x01" + - "\x02\x03\x05\x04\x05\x04\x05\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x02\a\x02\a\x02\a\x06\x03\x06\x03\x06\x03\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02" + - "\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\b\x03\x00\x00\x1f\xf8\x00\x00\x00\x00\x1f\xe0\x00\x04\x00\x00\x1c \x00\b\x00\x00*0\x00\f\x00\x00\x0e\x10\x00\x10\x00\x00\x1c \x01\x14\x00\x008@\x01\x19\x00\x00*0" + - "\x01\x1d\x00\x008@\x00\fLMT\x00SMT\x00EET\x00MSK\x00CET\x00CEST\x00MSD\x00EEST\x00\nMSK-3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1" + - "c9R8I\xdeN%\x02\x00\x00%\x02\x00\x00\v\x00\x1c\x00Europe/KievUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZ" + + "d\xad\x90\x00\x00\x00\x001]\xd9\x10\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x00\x00\x06\xec\x00\x00\x00" + + "\x00\x021\x00\x04\x00\x00\x0e\x10\x01\b\x00\x00\x00\x00\x00\r\x00\x00\x1c \x01\x11\x00\x00\x1c \x01\x16\x00\x00\x0e\x10\x00\x1bLMT\x00PMT\x00WEST\x00WET\x00WEMT\x00CES" + + "T\x00CET\x00\nCET-1CEST,M3.5.0,M10.5.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xf2\xfa\xcb\x130\x02\x00\x000\x02\x00\x00" + + "\x11\x00\x1c\x00Europe/ZaporozhyeUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\x00\x00\x00\b\x00\x00\x00$\xff\xff\xff\xffV\xb6\xc3\b\xff\xff\xff\xff\xaa\x19\xa30\xff\xff\xff\xff\xb5\xa4\x19`\xff\xff\xff\xffʪ\xe7\xd0\xff\xff\xff\xff" + + "\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffν\xd6p\x00\x00\x00\x00\x15'\xa7\xd0\x00\x00\x00\x00\x16\x18\xdc@\x00\x00\x00\x00\x17\b\xdbP\x00\x00\x00\x00\x17\xfa\x0f\xc0" + + "\x00\x00\x00\x00\x18\xea\x0e\xd0\x00\x00\x00\x00\x19\xdbC@\x00\x00\x00\x00\x1a̓\xd0\x00\x00\x00\x00\x1b\xbc\xa0\xf0\x00\x00\x00\x00\x1c\xac\x91\xf0\x00\x00\x00\x00\x1d\x9c\x82\xf0\x00\x00\x00\x00\x1e\x8cs\xf0\x00\x00\x00\x00" + + "\x1f|d\xf0\x00\x00\x00\x00 lU\xf0\x00\x00\x00\x00!\\F\xf0\x00\x00\x00\x00\"L7\xf0\x00\x00\x00\x00#<(\xf0\x00\x00\x00\x00$,\x19\xf0\x00\x00\x00\x00%\x1c\n\xf0\x00\x00\x00\x00&\v\xfb\xf0" + + "\x00\x00\x00\x00'\x05'p\x00\x00\x00\x00'\xf5\x18p\x00\x00\x00\x00(\xe4\xedP\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xc4\xcfP\x00\x00\x00\x00+\xb4\xce`\x00\x00\x00\x00,\xa4\xb1P\x00\x00\x00\x00" + + "-\x94\xb0`\x00\x00\x00\x00.\x84\x93P\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000d\xad\x90\x00\x00\x00\x001]\xd9\x10\x01\x02\x03\x05\x04\x05\x04\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03" + + "\x06\x03\x06\x03\a\x02\a\x02\a\x02\a\x02\a\x02\a\x00\x00 \xf8\x00\x00\x00\x00 \xd0\x00\x04\x00\x00\x1c \x00\n\x00\x00*0\x00\x0e\x00\x00\x0e\x10\x00\x12\x00\x00\x1c \x01\x16\x00\x008@\x01\x1b\x00\x00*" + + "0\x01\x1fLMT\x00+0220\x00EET\x00MSK\x00CET\x00CEST\x00MSD\x00EEST\x00\nEET-2EEST,M3.5.0/3,M" + + "10.5.0/4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS==\xa4\x16\xc4\x04\x00\x00\xc4\x04\x00\x00\x10\x00\x1c\x00Europe/GibraltarUT\t\x00\x03" + + "\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00s\x00\x00\x00\x06\x00\x00\x00\x1a\xff\xff" + + "\xff\xffW\xd1\n\x04\xff\xff\xff\xff\x9b&\xad\xa0\xff\xff\xff\xff\x9b\xd6\x05 \xff\xff\xff\xff\x9c\xcf0\xa0\xff\xff\xff\xff\x9d\xa4à\xff\xff\xff\xff\x9e\x9c\x9d\xa0\xff\xff\xff\xff\x9f\x97\x1a\xa0\xff\xff\xff\xff\xa0\x85" + + "\xba \xff\xff\xff\xff\xa1v\xfc\xa0\xff\xff\xff\xff\xa2e\x9c \xff\xff\xff\xff\xa3{Ƞ\xff\xff\xff\xff\xa4N\xb8\xa0\xff\xff\xff\xff\xa5?\xfb \xff\xff\xff\xff\xa6%` \xff\xff\xff\xff\xa7'\xc6 \xff\xff" + + "\xff\xff\xa8*, \xff\xff\xff\xff\xa8\xeb\xf8\xa0\xff\xff\xff\xff\xaa\x00Ӡ\xff\xff\xff\xff\xaa\xd5\x15 \xff\xff\xff\xff\xab\xe9\xf0 \xff\xff\xff\xff\xac\xc7l \xff\xff\xff\xff\xad\xc9\xd2 \xff\xff\xff\xff\xae\xa7" + + "N \xff\xff\xff\xff\xaf\xa0y\xa0\xff\xff\xff\xff\xb0\x870 \xff\xff\xff\xff\xb1\x92Р\xff\xff\xff\xff\xb2pL\xa0\xff\xff\xff\xff\xb3r\xb2\xa0\xff\xff\xff\xff\xb4P.\xa0\xff\xff\xff\xff\xb5IZ \xff\xff" + + "\xff\xff\xb60\x10\xa0\xff\xff\xff\xff\xb72v\xa0\xff\xff\xff\xff\xb8\x0f\xf2\xa0\xff\xff\xff\xff\xb9\x12X\xa0\xff\xff\xff\xff\xb9\xefԠ\xff\xff\xff\xff\xba\xe9\x00 \xff\xff\xff\xff\xbb\xd8\xf1 \xff\xff\xff\xff\xbc\xdb" + + "W \xff\xff\xff\xff\xbd\xb8\xd3 \xff\xff\xff\xff\xbe\xb1\xfe\xa0\xff\xff\xff\xff\xbf\x98\xb5 \xff\xff\xff\xff\xc0\x9b\x1b \xff\xff\xff\xff\xc1x\x97 \xff\xff\xff\xff\xc2z\xfd \xff\xff\xff\xff\xc3Xy \xff\xff" + + "\xff\xff\xc4Q\xa4\xa0\xff\xff\xff\xff\xc58[ \xff\xff\xff\xff\xc6:\xc1 \xff\xff\xff\xff\xc7X֠\xff\xff\xff\xff\xc7\xda\t\xa0\xff\xff\xff\xff\xca\x16&\x90\xff\xff\xff\xffʗY\x90\xff\xff\xff\xff\xcb\xd1" + + "\x1e\x90\xff\xff\xff\xff\xccw;\x90\xff\xff\xff\xffͱ\x00\x90\xff\xff\xff\xff\xce`X\x10\xff\xff\xff\xffϐ\xe2\x90\xff\xff\xff\xff\xd0n^\x90\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd1\xfb2\x10\xff\xff" + + "\xff\xff\xd2i\xfe \xff\xff\xff\xff\xd3c)\xa0\xff\xff\xff\xff\xd4I\xe0 \xff\xff\xff\xff\xd5\x1e!\xa0\xff\xff\xff\xff\xd5B\xfd\x90\xff\xff\xff\xff\xd5\xdf\xe0\x10\xff\xff\xff\xff\xd6N\xac \xff\xff\xff\xff\xd6\xfe" + + "\x03\xa0\xff\xff\xff\xff\xd8.\x8e \xff\xff\xff\xff\xd8\xf9\x95 \xff\xff\xff\xff\xda\x0ep \xff\xff\xff\xff\xda\xeb\xec \xff\xff\xff\xff\xdb\xe5\x17\xa0\xff\xff\xff\xff\xdc\xcb\xce \xff\xff\xff\xff\xdd\xc4\xf9\xa0\xff\xff" + + "\xff\xff\u07b4\xea\xa0\xff\xff\xff\xff߮\x16 \xff\xff\xff\xff\xe0\x94̠\xff\xff\xff\xff\xe1rH\xa0\xff\xff\xff\xff\xe2kt \xff\xff\xff\xff\xe3R*\xa0\xff\xff\xff\xff\xe4T\x90\xa0\xff\xff\xff\xff\xe52" + + "\f\xa0\xff\xff\xff\xff\xe6=\xad \xff\xff\xff\xff\xe7\x1b) \xff\xff\xff\xff\xe8\x14T\xa0\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00" + + "\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\" + + "c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#\x86%p\x00\x00\x00\x00?\x9b\x00p\x00\x00\x00\x00@f\ap\x00\x00\x00\x00A\x84\x1c\xf0\x00\x00\x00\x00BE\xe9p\x00" + - "\x00\x00\x00Cc\xfe\xf0\x00\x00\x00\x00D%\xcbp\x00\x00\x00\x00EC\xe0\xf0\x00\x00\x00\x00F\x05\xadp\x00\x00\x00\x00G#\xc2\xf0\x00\x00\x00\x00G\xee\xc9\xf0\x00\x00\x00\x00I\x03\xa4\xf0\x00\x00\x00\x00I" + - "Ϋ\xf0\x00\x00\x00\x00J\xe3\x86\xf0\x00\x00\x00\x00K\xae\x8d\xf0\x00\x00\x00\x00Ḷp\x00\x00\x00\x00M\x8eo\xf0\x00\x00\x00\x00TL\x1d`\x00\x00\x00\x00V\xf7\x14p\x01\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x04\x01\x05\x06\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x03\x01\x03\x00\x00-" + - "`\x00\x00\x00\x00*0\x00\x04\x00\x00FP\x01\b\x00\x008@\x00\f\x00\x008@\x01\f\x00\x00*0\x01\x04\x00\x00\x1c \x00\x10LMT\x00+03\x00+05\x00+04\x00+02\x00\n" + - "<+04>-4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xd9L\xf6\xf7\xf1\x01\x00\x00\xf1\x01\x00\x00\x10\x00\x1c\x00Europe/StockholmUT\t\x00\x03\x15" + - "\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00%\x00\x00\x00\x04\x00\x00\x00\x11\xff\xff\xff" + - "\xffT՟\x94\xff\xff\xff\xff|Usb\xff\xff\xff\xff\x9b\x1e\x8c`\xff\xff\xff\xff\x9b\xd5\xda\xf0\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13\xdc" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\x00\x00\x00\a\x00\x00\x00\x16\xff\xff\xff\xff\x84\xa2\xad\xbc\xff\xff\xff\xff\x9b\x1e\x8c`\xff\xff\xff\xff\x9b\xd5\xda\xf0\xff\xff\xff" + + "\xff\x9c\xea\xa7\xe0\xff\xff\xff\xff\x9d\xa4\x99p\xff\xff\xff\xff\x9e\xb9\x90\x90\xff\xff\xff\xff\x9f\x84\x97\x90\xff\xff\xff\xff\x9f\xe0\xc4p\xff\xff\xff\xff\xa0`\xa5\xf0\xff\xff\xff\xff\xa1~\xe5\xa0\xff\xff\xff\xff\xa2.\x12" + + "\xf0\xff\xff\xff\xff\xa3zi\x10\xff\xff\xff\xff\xa45\x81\xf0\xff\xff\xff\xff\xa5^?\x90\xff\xff\xff\xff\xa6%5\xf0\xff\xff\xff\xff\xa7'\xaa\x00\xff\xff\xff\xff\xa8*\x01\xf0\xff\xff\xff\xff\xa9\a\x9a\x10\xff\xff\xff" + + "\xff\xa9\xee4p\xff\xff\xff\xff\xaa\xe7n\x00\xff\xff\xff\xff\xabآp\xff\xff\xff\xff\xac\xc7P\x00\xff\xff\xff\xff\xadɧ\xf0\xff\xff\xff\xff\xae\xa72\x00\xff\xff\xff\xff\xaf\xa0Op\xff\xff\xff\xff\xb0\x87\x14" + + "\x00\xff\xff\xff\xff\xb1\x89k\xf0\xff\xff\xff\xff\xb2p0\x80\xff\xff\xff\xff\xb3r\x88p\xff\xff\xff\xff\xb4P.\xa0\xff\xff\xff\xff\xb5IZ \xff\xff\xff\xff\xb60\x10\xa0\xff\xff\xff\xff\xb72v\xa0\xff\xff\xff" + + "\xff\xb8\x0f\xf2\xa0\xff\xff\xff\xff\xb8\xff\xe3\xa0\xff\xff\xff\xff\xb9\xefԠ\xff\xff\xff\xff\xba\u058b \xff\xff\xff\xff\xbb\xd8\xf1 \xff\xff\xff\xff\xbc\xc8\xe2 \xff\xff\xff\xff\xbd\xb8\xd3 \xff\xff\xff\xff\xbe\x9f\x89" + + "\xa0\xff\xff\xff\xff\xbf\x98\xb5 \xff\xff\xff\xff\xc0\x9b\x1b \xff\xff\xff\xff\xc1x\x97 \xff\xff\xff\xff\xc2h\x88 \xff\xff\xff\xff\xc3Xy \xff\xff\xff\xff\xc4?/\xa0\xff\xff\xff\xff\xc58[ \xff\xff\xff" + + "\xff\xc6:\xc1 \xff\xff\xff\xff\xc7X֠\xff\xff\xff\xff\xc7\xda\t\xa0\xff\xff\xff\xff\xc8B0 \xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4" + + "\x10\xff\xff\xff\xff\xd0o\xb0\x10\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd2N@\x90\xff\xff\xff\xffӑ@\x10\xff\xff\xff\xff\xd4K#\x90\x00\x00\x00\x00\r\xa4c\x90\x00\x00\x00\x00\x0e\x8b\x1a\x10\x00\x00\x00" + + "\x00\x0f\x84E\x90\x00\x00\x00\x00\x10t6\x90\x00\x00\x00\x00\x11d'\x90\x00\x00\x00\x00\x12T\x18\x90\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13\xdc" + "\x90\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00" + "\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#\xf3`\xff\xff\xff\xff\xb9\xef\x9c`\xff\xff\xff\xff\xbaߍ`\xff\xff\xff\xff\xbb\xcf~" + - "`\xff\xff\xff\xff\xbcȩ\xe0\xff\xff\xff\xff\xbd\xb8\x9a\xe0\xff\xff\xff\xff\xbe\xa8\x8b\xe0\xff\xff\xff\xff\xbf\x98|\xe0\xff\xff\xff\xff\xc0\x88m\xe0\xff\xff\xff\xff\xc1x^\xe0\xff\xff\xff\xff\xc2hO\xe0\xff\xff\xff" + - "\xff\xc3X@\xe0\xff\xff\xff\xff\xc4H1\xe0\xff\xff\xff\xff\xc58\"\xe0\xff\xff\xff\xff\xc6(\x13\xe0\xff\xff\xff\xff\xc7\x18\x04\xe0\xff\xff\xff\xffȼ\x93`\xff\xff\xff\xff\xcaw}P\xff\xff\xff\xff\xcc\xe7K" + - "\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xff\xd0N\x90`\x00\x00\x00\x00\x15'\xa7\xd0\x00\x00\x00\x00\x16\x18\xdc@\x00\x00\x00\x00\x17\b\xdbP\x00\x00\x00" + - "\x00\x17\xfa\x0f\xc0\x00\x00\x00\x00\x18\xea\x0e\xd0\x00\x00\x00\x00\x19\xdbC@\x00\x00\x00\x00\x1a̓\xd0\x00\x00\x00\x00\x1b\xbc\xa0\xf0\x00\x00\x00\x00\x1c\xac\x91\xf0\x00\x00\x00\x00\x1d\x9c\x82\xf0\x00\x00\x00\x00\x1e\x8cs" + - "\xf0\x00\x00\x00\x00\x1f|d\xf0\x00\x00\x00\x00 lU\xf0\x00\x00\x00\x00!\\F\xf0\x00\x00\x00\x00\"L7\xf0\x00\x00\x00\x00#<(\xf0\x00\x00\x00\x00$,\x19\xf0\x00\x00\x00\x00%\x1c\n\xf0\x00\x00\x00" + - "\x00&\v\xfb\xf0\x00\x00\x00\x00&CL\xe0\x00\x00\x00\x00'\x055\x80\x00\x00\x00\x00'\xf5&\x80\x00\x00\x00\x00(\xe5\x17\x80\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xc4\xcfP\x00\x00\x00\x00+\xb4\xce" + - "`\x00\x00\x00\x00,\xa4\xb1P\x00\x00\x00\x00-\x94\xb0`\x00\x00\x00\x00.\x84\x93P\x00\x00\x00\x00/t\x92`\x00\x00\x00\x000duP\x00\x00\x00\x001]\xae\xe0\x00\x00\x00\x002r{\xd0\x00\x00\x00" + - "\x003=\xad\x00\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x06\x05\x06\x05\x06\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04" + - "\x03\x04\x03\x04\x03\x00\x00\x1b\b\x00\x00\x00\x00\x1a\xf4\x00\x04\x00\x00\x18x\x00\b\x00\x00*0\x01\f\x00\x00\x1c \x00\x11\x00\x00\x0e\x10\x00\x15\x00\x00\x1c \x01\x19\x00\x008@\x01\x1e\x00\x00*0\x00\"L" + - "MT\x00CMT\x00BMT\x00EEST\x00EET\x00CET\x00CEST\x00MSD\x00MSK\x00\nEET-2EEST,M3.5.0,M10.5" + - ".0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xf2\xfa\xcb\x130\x02\x00\x000\x02\x00\x00\x11\x00\x1c\x00Europe/ZaporozhyeUT\t\x00\x03\x15\xac\x0e" + - "`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" + - "\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\x00\x00\x00\b\x00\x00\x00$\xff\xff\xff\xffV" + - "\xb6\xc3\b\xff\xff\xff\xff\xaa\x19\xa30\xff\xff\xff\xff\xb5\xa4\x19`\xff\xff\xff\xffʪ\xe7\xd0\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffν\xd6p\x00" + - "\x00\x00\x00\x15'\xa7\xd0\x00\x00\x00\x00\x16\x18\xdc@\x00\x00\x00\x00\x17\b\xdbP\x00\x00\x00\x00\x17\xfa\x0f\xc0\x00\x00\x00\x00\x18\xea\x0e\xd0\x00\x00\x00\x00\x19\xdbC@\x00\x00\x00\x00\x1a̓\xd0\x00\x00\x00\x00\x1b" + - "\xbc\xa0\xf0\x00\x00\x00\x00\x1c\xac\x91\xf0\x00\x00\x00\x00\x1d\x9c\x82\xf0\x00\x00\x00\x00\x1e\x8cs\xf0\x00\x00\x00\x00\x1f|d\xf0\x00\x00\x00\x00 lU\xf0\x00\x00\x00\x00!\\F\xf0\x00\x00\x00\x00\"L7\xf0\x00" + - "\x00\x00\x00#<(\xf0\x00\x00\x00\x00$,\x19\xf0\x00\x00\x00\x00%\x1c\n\xf0\x00\x00\x00\x00&\v\xfb\xf0\x00\x00\x00\x00'\x05'p\x00\x00\x00\x00'\xf5\x18p\x00\x00\x00\x00(\xe4\xedP\x00\x00\x00\x00)" + - "\xd4\xec`\x00\x00\x00\x00*\xc4\xcfP\x00\x00\x00\x00+\xb4\xce`\x00\x00\x00\x00,\xa4\xb1P\x00\x00\x00\x00-\x94\xb0`\x00\x00\x00\x00.\x84\x93P\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000d\xad\x90\x00" + - "\x00\x00\x001]\xd9\x10\x01\x02\x03\x05\x04\x05\x04\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\a\x02\a\x02\a\x02\a\x02\a\x02\a\x00\x00 \xf8\x00\x00\x00\x00 \xd0\x00\x04\x00\x00" + - "\x1c \x00\n\x00\x00*0\x00\x0e\x00\x00\x0e\x10\x00\x12\x00\x00\x1c \x01\x16\x00\x008@\x01\x1b\x00\x00*0\x01\x1fLMT\x00+0220\x00EET\x00MSK\x00CET\x00CEST" + - "\x00MSD\x00EEST\x00\nEET-2EEST,M3.5.0/3,M10.5.0/4\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xe0\xfe\x83\xe5\xcd\x02" + - "\x00\x00\xcd\x02\x00\x00\f\x00\x1c\x00Europe/KirovUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xa1\x009\x80\xff\xff\xff\xff\xb5\xa4\vP\x00\x00\x00\x00\x15'\x99\xc0\x00\x00\x00\x00\x16\x18\xce0\x00\x00\x00" + - "\x00\x17\b\xcd@\x00\x00\x00\x00\x17\xfa\x01\xb0\x00\x00\x00\x00\x18\xea\x00\xc0\x00\x00\x00\x00\x19\xdb50\x00\x00\x00\x00\x1a̅\xc0\x00\x00\x00\x00\x1b\xbc\x92\xe0\x00\x00\x00\x00\x1c\xac\x83\xe0\x00\x00\x00\x00\x1d\x9ct" + - "\xe0\x00\x00\x00\x00\x1e\x8ce\xe0\x00\x00\x00\x00\x1f|V\xe0\x00\x00\x00\x00 lG\xe0\x00\x00\x00\x00!\\8\xe0\x00\x00\x00\x00\"L)\xe0\x00\x00\x00\x00#<\x1a\xe0\x00\x00\x00\x00$,\v\xe0\x00\x00\x00" + - "\x00%\x1c\n\xf0\x00\x00\x00\x00&\v\xfb\xf0\x00\x00\x00\x00'\x05'p\x00\x00\x00\x00'\xf5\x18p\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xc4\xebp\x00\x00\x00\x00+\xb4\xdcp\x00\x00\x00\x00,\xa4\xcd" + - "p\x00\x00\x00\x00-\x94\xbep\x00\x00\x00\x00.\x84\xafp\x00\x00\x00\x00/t\xa0p\x00\x00\x00\x000d\x91p\x00\x00\x00\x001]\xbc\xf0\x00\x00\x00\x002r\x97\xf0\x00\x00\x00\x003=\x9e\xf0\x00\x00\x00" + - "\x004Ry\xf0\x00\x00\x00\x005\x1d\x80\xf0\x00\x00\x00\x0062[\xf0\x00\x00\x00\x006\xfdb\xf0\x00\x00\x00\x008\x1bxp\x00\x00\x00\x008\xddD\xf0\x00\x00\x00\x009\xfbZp\x00\x00\x00\x00:\xbd&" + - "\xf0\x00\x00\x00\x00;\xdb\x86%p\x00\x00\x00\x00?\x9b\x00p\x00\x00\x00\x00@f\ap\x00\x00\x00\x00A\x84\x1c\xf0\x00\x00\x00" + - "\x00BE\xe9p\x00\x00\x00\x00Cc\xfe\xf0\x00\x00\x00\x00D%\xcbp\x00\x00\x00\x00EC\xe0\xf0\x00\x00\x00\x00F\x05\xadp\x00\x00\x00\x00G#\xc2\xf0\x00\x00\x00\x00G\xee\xc9\xf0\x00\x00\x00\x00I\x03\xa4" + - "\xf0\x00\x00\x00\x00IΫ\xf0\x00\x00\x00\x00J\xe3\x86\xf0\x00\x00\x00\x00K\xae\x8d\xf0\x00\x00\x00\x00Ḷp\x00\x00\x00\x00M\x8eo\xf0\x00\x00\x00\x00TL\x1d`\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x04\x01\x04\x01\x03\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x03\x01\x00\x00.\x98\x00\x00\x00\x00" + - "*0\x00\x04\x00\x00FP\x01\b\x00\x008@\x00\f\x00\x008@\x01\fLMT\x00+03\x00+05\x00+04\x00\n<+03>-3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9" + - "R>\xfe垛\x03\x00\x00\x9b\x03\x00\x00\r\x00\x1c\x00Europe/WarsawUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZ" + - "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00R\x00\x00\x00\x06\x00\x00\x00\x1a\xff\xff\xff\xffV\xb6\xd0P\xff\xff\xff\xff\x99\xa8*\xd0\xff\xff\xff\xff\x9b\f\x17`\xff\xff\xff" + - "\xff\x9b\xd5\xda\xf0\xff\xff\xff\xff\x9cٮ\x90\xff\xff\xff\xff\x9d\xa4\xb5\x90\xff\xff\xff\xff\x9e\xb9\x90\x90\xff\xff\xff\xff\x9f\x84\x97\x90\xff\xff\xff\xff\xa0\x9a\xb6\x00\xff\xff\xff\xff\xa1e\xbd\x00\xff\xff\xff\xff\xa6}|" + - "`\xff\xff\xff\xff\xc8v\xde\x10\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЄ\xba\x00\xff\xff\xff\xffѕ\x92p\xff\xff\xff" + - "\xffҊ\xbb`\xff\xff\xff\xff\xd3b\xffp\xff\xff\xff\xff\xd4K#\x90\xff\xff\xff\xff\xd5^\xad\x10\xff\xff\xff\xff\xd6)\xb4\x10\xff\xff\xff\xff\xd7,\x1a\x10\xff\xff\xff\xff\xd8\t\x96\x10\xff\xff\xff\xff\xd9\x02\xc1" + - "\x90\xff\xff\xff\xff\xd9\xe9x\x10\xff\xff\xff\xff\xe8T\xd2\x00\xff\xff\xff\xff\xe8\xf1\xb4\x80\xff\xff\xff\xff\xe9᥀\xff\xff\xff\xff\xeaі\x80\xff\xff\xff\xff\xec\x14\x96\x00\xff\xff\xff\xff캳\x00\xff\xff\xff" + - "\xff\xed\xaa\xa4\x00\xff\xff\xff\xff\ue695\x00\xff\xff\xff\xff\xef\xd4Z\x00\xff\xff\xff\xff\xf0zw\x00\xff\xff\xff\xff\xf1\xb4<\x00\xff\xff\xff\xff\xf2ZY\x00\xff\xff\xff\xff\xf3\x94\x1e\x00\xff\xff\xff\xff\xf4:;" + - "\x00\xff\xff\xff\xff\xf5}:\x80\xff\xff\xff\xff\xf6\x1a\x1d\x00\x00\x00\x00\x00\r\xa4U\x80\x00\x00\x00\x00\x0e\x8b\f\x00\x00\x00\x00\x00\x0f\x847\x80\x00\x00\x00\x00\x10t(\x80\x00\x00\x00\x00\x11d\x19\x80\x00\x00\x00" + - "\x00\x12T\n\x80\x00\x00\x00\x00\x13M6\x00\x00\x00\x00\x00\x143\xec\x80\x00\x00\x00\x00\x15#݀\x00\x00\x00\x00\x16\x13\u0380\x00\x00\x00\x00\x17\x03\xbf\x80\x00\x00\x00\x00\x17\xf3\xb0\x80\x00\x00\x00\x00\x18\xe3\xa1" + - "\x80\x00\x00\x00\x00\x19Ӓ\x80\x00\x00\x00\x00\x1aÃ\x80\x00\x00\x00\x00\x1b\xbc\xaf\x00\x00\x00\x00\x00\x1c\xac\xa0\x00\x00\x00\x00\x00\x1d\x9c\x91\x00\x00\x00\x00\x00\x1e\x8c\x82\x00\x00\x00\x00\x00\x1f|s\x00\x00\x00\x00" + - "\x00 ld\x00\x00\x00\x00\x00!\\U\x00\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#\x86%p\x00\x00\x00\x00?\x9b\x00p\x00\x00\x00\x00@f\ap\x00\x00\x00\x00A\x84\x1c\xf0\x00\x00\x00\x00BE\xe9p\x00\x00\x00\x00Cc\xfe\xf0\x00\x00" + + "\x00\x00D%\xcbp\x00\x00\x00\x00EC\xe0\xf0\x00\x00\x00\x00F\x05\xadp\x00\x00\x00\x00G#\xc2\xf0\x00\x00\x00\x00G\xee\xc9\xf0\x00\x00\x00\x00I\x03\xa4\xf0\x00\x00\x00\x00IΫ\xf0\x00\x00\x00\x00J\xe3" + + "\x86\xf0\x00\x00\x00\x00K\xae\x8d\xf0\x00\x00\x00\x00Ḷp\x00\x00\x00\x00M\x8eo\xf0\x00\x00\x00\x00TL\x1d`\x00\x00\x00\x00V\xf7\x14p\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x04\x01\x04\x01\x05\x06\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x03\x01\x03\x00\x00-`\x00\x00\x00\x00*0\x00\x04" + + "\x00\x00FP\x01\b\x00\x008@\x00\f\x00\x008@\x01\f\x00\x00*0\x01\x04\x00\x00\x1c \x00\x10LMT\x00+03\x00+05\x00+04\x00+02\x00\n<+04>-4\nP" + + "K\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x90\xa9\xf5ϕ\x02\x00\x00\x95\x02\x00\x00\x10\x00\x1c\x00Europe/BucharestUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux" + + "\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00" + + "\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x007\x00\x00\x00\x04\x00\x00\x00\x11\xff\xff\xff\xffl\xcf\xe0\b\xff\xff\xff\xff" + + "\xb7\xb0\xd2\b\xff\xff\xff\xff\xb9>\xf3`\xff\xff\xff\xff\xb9\xef\x9c`\xff\xff\xff\xff\xbaߍ`\xff\xff\xff\xff\xbb\xcf~`\xff\xff\xff\xff\xbcȩ\xe0\xff\xff\xff\xff\xbd\xb8\x9a\xe0\xff\xff\xff\xff\xbe\xa8\x8b\xe0" + + "\xff\xff\xff\xff\xbf\x98|\xe0\xff\xff\xff\xff\xc0\x88m\xe0\xff\xff\xff\xff\xc1x^\xe0\xff\xff\xff\xff\xc2hO\xe0\xff\xff\xff\xff\xc3X@\xe0\xff\xff\xff\xff\xc4H1\xe0\xff\xff\xff\xff\xc58\"\xe0\xff\xff\xff\xff" + + "\xc6(\x13\xe0\xff\xff\xff\xff\xc7\x18\x04\xe0\x00\x00\x00\x00\x11\xad\xd1`\x00\x00\x00\x00\x12S\xe0P\x00\x00\x00\x00\x13M\v\xd0\x00\x00\x00\x00\x143\xd0`\x00\x00\x00\x00\x15#݀\x00\x00\x00\x00\x16\x13\u0380" + + "\x00\x00\x00\x00\x17\x03\xbf\x80\x00\x00\x00\x00\x17\xf3\xb0\x80\x00\x00\x00\x00\x18㡀\x00\x00\x00\x00\x19Ӓ\x80\x00\x00\x00\x00\x1aÃ\x80\x00\x00\x00\x00\x1b\xbc\xaf\x00\x00\x00\x00\x00\x1c\xac\xa0\x00\x00\x00\x00\x00" + + "\x1d\x9c\x91\x00\x00\x00\x00\x00\x1e\x8c\x82\x00\x00\x00\x00\x00\x1f|s\x00\x00\x00\x00\x00 ld\x00\x00\x00\x00\x00!\\U\x00\x00\x00\x00\x00\"LF\x00\x00\x00\x00\x00#<7\x00\x00\x00\x00\x00$,(\x00" + + "\x00\x00\x00\x00%\x1c\x19\x00\x00\x00\x00\x00&\f\n\x00\x00\x00\x00\x00'\x055\x80\x00\x00\x00\x00'\xf5\n`\x00\x00\x00\x00(\xe4\xfb`\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xc4\xdd`\x00\x00\x00\x00" + + "+\xb4\xce`\x00\x00\x00\x00,\xa4\xbf`\x00\x00\x00\x00-\x94\xb0`\x00\x00\x00\x00.\x84\x93P\x00\x00\x00\x00/t\x92`\x00\x00\x00\x000duP\x00\x00\x00\x001]\xae\xe0\x00\x00\x00\x002r{\xd0" + + "\x00\x00\x00\x003=\xbb\x10\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x00\x00\x18x\x00\x00\x00\x00\x18x\x00\x04\x00\x00*0\x01\b\x00\x00\x1c \x00\rLMT\x00BMT\x00EEST\x00EET\x00\nEET-2EEST,M3.5." + + "0/3,M10.5.0/4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x95\xb4\x9e\xe7\xb3\x03\x00\x00\xb3\x03\x00\x00\x0e\x00\x1c\x00Europe/VaticanUT" + + "\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00W\x00\x00\x00\x04\x00\x00\x00" + + "\x11\xff\xff\xff\xff>(\xe8L\xff\xff\xff\xffp\xbc\x81p\xff\xff\xff\xff\x9b8\xf8p\xff\xff\xff\xff\x9b\xd5\xcc\xe0\xff\xff\xff\xff\x9c\xc5\xcb\xf0\xff\xff\xff\xff\x9d\xb7\x00`\xff\xff\xff\xff\x9e\x89\xfep\xff\xff\xff" + + "\xff\x9f\xa0\x1c\xe0\xff\xff\xff\xff\xa0`\xa5\xf0\xff\xff\xff\xff\xa1~\xad`\xff\xff\xff\xff\xa2\\7p\xff\xff\xff\xff\xa3L\x1a`\xff\xff\xff\xff\xc8l5\xf0\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17" + + "\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xff\xd0n^\x90\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd2L\xd2\xf0\xff\xff\xff\xff\xd3>1\x90\xff\xff\xff\xff\xd4I\xd2\x10\xff\xff\xff" + + "\xff\xd5\x1d\xf7p\xff\xff\xff\xff\xd6)\x97\xf0\xff\xff\xff\xff\xd6뀐\xff\xff\xff\xff\xd8\t\x96\x10\xff\xff\xff\xff\xf93\xb5\xf0\xff\xff\xff\xff\xf9\xd9\xc4\xe0\xff\xff\xff\xff\xfb\x1c\xd2p\xff\xff\xff\xff\xfb\xb9\xb4" + + "\xf0\xff\xff\xff\xff\xfc\xfc\xb4p\xff\xff\xff\xff\xfd\x99\x96\xf0\xff\xff\xff\xff\xfe\xe5\xd0\xf0\xff\xff\xff\xff\xff\x82\xb3p\x00\x00\x00\x00\x00Ų\xf0\x00\x00\x00\x00\x01b\x95p\x00\x00\x00\x00\x02\x9cZp\x00\x00\x00" + + "\x00\x03Bwp\x00\x00\x00\x00\x04\x85v\xf0\x00\x00\x00\x00\x05+\x93\xf0\x00\x00\x00\x00\x06n\x93p\x00\x00\x00\x00\a\vu\xf0\x00\x00\x00\x00\bE:\xf0\x00\x00\x00\x00\b\xebW\xf0\x00\x00\x00\x00\n.W" + + "p\x00\x00\x00\x00\n\xcb9\xf0\x00\x00\x00\x00\f\x0e9p\x00\x00\x00\x00\f\xab\x1b\xf0\x00\x00\x00\x00\r\xe4\xe0\xf0\x00\x00\x00\x00\x0e\x8a\xfd\xf0\x00\x00\x00\x00\x0f\xcd\xfdp\x00\x00\x00\x00\x10t\x1ap\x00\x00\x00" + + "\x00\x11\xad\xdfp\x00\x00\x00\x00\x12S\xfcp\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe" + + "\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00" + + "\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#P\xff\xff\xff\xff\xf1\xf4\xb9`\xff\xff\xff\xff\xf4b\xefP\xff\xff\xff\xff\xf5h\x06" + - "`\xff\xff\xff\xff\xf6\x1f8\xd0\x00\x00\x00\x00\x06n\x93p\x00\x00\x00\x00\a9\x9ap\x00\x00\x00\x00\a\xfbu\x00\x00\x00\x00\x00\t\x19|p\x00\x00\x00\x00\t\xd0\xcb\x00\x00\x00\x00\x00\n\xf9^p\x00\x00\x00" + - "\x00\v\xb1\xfe\x80\x00\x00\x00\x00\f\xd9@p\x00\x00\x00\x00\r\xa4U\x80\x00\x00\x00\x00\x0e\xa6\xadp\x00\x00\x00\x00\x0f\x847\x80\x00\x00\x00\x00\x0f\xf8\x11P\x00\x00\x00\x00\x19\x89\xb0p\x00\x00\x00\x00\x19ܰ" + - "\xe0\x00\x00\x00\x00\x1b\xe6\xd0\xf0\x00\x00\x00\x00\x1c\xc6\xef\xf0\x00\x00\x00\x00\x1d\x9b1p\x00\x00\x00\x00\x1e\x8cs\xf0\x00\x00\x00\x00\x1f|d\xf0\x00\x00\x00\x00 lU\xf0\x00\x00\x00\x00!\\F\xf0\x00\x00\x00" + - "\x00\"L7\xf0\x00\x00\x00\x00#<(\xf0\x00\x00\x00\x00$,\x19\xf0\x00\x00\x00\x00%\x1c\n\xf0\x00\x00\x00\x00&\v\xfb\xf0\x00\x00\x00\x00'\x05'p\x00\x00\x00\x00'\xf5\x18p\x00\x00\x00\x00(\xe5\t" + - "p\x00\x00\x00\x00)\xd4\xfap\x00\x00\x00\x00*\xc4\xebp\x00\x00\x00\x00+\xb4\xdcp\x00\x00\x00\x00,\xa4\xcdp\x00\x00\x00\x00-\x8b\x83\xf0\x00\x00\x00\x00.\x84\xafp\x00\x00\x00\x00/t\xa0p\x00\x00\x00" + - "\x000d\x91p\x00\x00\x00\x001]\xbc\xf0\x00\x00\x00\x002r\x97\xf0\x00\x00\x00\x003=\x9e\xf0\x00\x00\x00\x004Ry\xf0\x00\x00\x00\x005\x1d\x80\xf0\x00\x00\x00\x0062[\xf0\x00\x00\x00\x006\xfdb" + - "\xf0\x00\x00\x00\x008\x1bxp\x00\x00\x00\x008\xddD\xf0\x00\x00\x00\x009\xfbZp\x00\x00\x00\x00:\xbd&\xf0\x00\x00\x00\x00;\xdb\x86%p\x00\x00\x00\x00?\x9b\x00p\x00\x00\x00\x00@f\ap\x00\x00\x00\x00A\x84\x1c\xf0\x00\x00\x00\x00BE\xe9p\x00\x00\x00\x00Cc\xfe\xf0\x00\x00\x00\x00D%\xcbp\x00\x00\x00\x00EC\xe0" + - "\xf0\x00\x00\x00\x00F\x05ɐ\x00\x00\x00\x00G#\xdf\x10\x00\x00\x00\x00G\xee\xe6\x10\x00\x00\x00\x00I\x03\xc1\x10\x00\x00\x00\x00I\xce\xc8\x10\x00\x00\x00\x00J\xe3\xa3\x10\x00\x00\x00\x00K\xae\xaa\x10\x00\x00\x00" + - "\x00L̿\x90\x00\x00\x00\x00M\x8fݐ\x00\x00\x00\x00N\xac\xa1\x90\x00\x00\x00\x00Onn\x10\x00\x00\x00\x00P\x8c\x83\x90\x00\x00\x00\x00QW\x8a\x90\x00\x00\x00\x00Rle\x90\x00\x00\x00\x00S8\xbe" + - "\x10\x00\x00\x00\x00TLG\x90\x00\x00\x00\x00U\x17N\x90\x00\x00\x00\x00V>\x9e\x90\x00\x00\x00\x00V\xf70\x90\x00\x00\x00\x00W\xcf.P\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x04\x05\x04\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x04\x00\x00\x1b(\x00\x00\x00\x00\x1bh\x00\x04\x00\x00*0\x01\b\x00\x00\x1c \x00\r" + - "\x00\x00*0\x00\x11\x00\x008@\x01\x15LMT\x00IMT\x00EEST\x00EET\x00+03\x00+04\x00\n<+03>-3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R" + - "\xab\x80c$q\x00\x00\x00q\x00\x00\x00\a\x00\x1c\x00FactoryUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$\x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff\xff^<\xf0H\xff\xff\xff\xff\xca\x025\xe0\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C" + + "\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff\xffѡ\x8c\x10\xff\xff\xff\xff\xd2N@\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00" + + "\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT" + + "\x10\x00\x00\x00\x00#\x86%p\x00\x00\x00\x00?\x9b\x00p\x00\x00\x00\x00@f\ap\x00\x00\x00" + + "\x00A\x84\x1c\xf0\x00\x00\x00\x00BE\xe9p\x00\x00\x00\x00Cc\xfe\xf0\x00\x00\x00\x00D%\xcbp\x00\x00\x00\x00EC\xe0\xf0\x00\x00\x00\x00F\x05\xadp\x00\x00\x00\x00G#\xc2\xf0\x00\x00\x00\x00G\xee\xc9" + + "\xf0\x00\x00\x00\x00I\x03\xa4\xf0\x00\x00\x00\x00IΫ\xf0\x00\x00\x00\x00J\xe3\x86\xf0\x00\x00\x00\x00K\xae\x8d\xf0\x00\x00\x00\x00Ḷp\x00\x00\x00\x00M\x8eo\xf0\x00\x00\x00\x00TL\x1d`\x00\x00\x00" + + "\x00V\xf7\x14p\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x04\x01\x03\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01" + + "\x04\x01\x04\x01\x04\x01\x03\x01\x03\x00\x00-\f\x00\x00\x00\x00*0\x00\x04\x00\x00FP\x01\b\x00\x008@\x00\f\x00\x008@\x01\fLMT\x00+03\x00+05\x00+04\x00\n<+04" + + ">-4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSߜvυ\x01\x00\x00\x85\x01\x00\x00\x0e\x00\x1c\x00Europe/AndorraUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8b" + + "aux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01" + + "\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x04\x00\x00\x00\x11\xff\xff\xff\xff~6\xb3\x94\xff" + + "\xff\xff\xff\xd4A\xdb\x00\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"" + + "LT\x10\x00\x00\x00\x00#\x86A\x90\x01\x02\x03\x04\x03\x05\x06\x03\x06\x03\x06\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\a\x05\b\x04\b\x04\b\x04\b\x04\b\x04\b\x04" + + "\b\x04\b\x04\b\x04\x06\x03\x06\x04\b\x00\x00\x17\xbc\x00\x00\x00\x00\x13\xb0\x00\x04\x00\x00\x16h\x00\b\x00\x00\x0e\x10\x00\f\x00\x00\x1c \x00\x10\x00\x00*0\x00\x14\x00\x00\x1c \x01\x18\x00\x008@\x01\x1d\x00" + + "\x00*0\x01!LMT\x00WMT\x00KMT\x00CET\x00EET\x00MSK\x00CEST\x00MSD\x00EEST\x00\nEET-2EEST,M3.5.0" + + "/3,M10.5.0/4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\aW\x10Ѱ\x04\x00\x00\xb0\x04\x00\x00\x0f\x00\x1c\x00Europe/IstanbulUT" + + "\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00s\x00\x00\x00\x06\x00\x00\x00" + + "\x19\xff\xff\xff\xffV\xb6\xc8\xd8\xff\xff\xff\xff\x90\x8b\xf5\x98\xff\xff\xff\xff\x9b\f\x17`\xff\xff\xff\xff\x9bվ\xd0\xff\xff\xff\xff\xa2ec\xe0\xff\xff\xff\xff\xa3{\x82P\xff\xff\xff\xff\xa4N\x80`\xff\xff\xff" + + "\xff\xa5?\xb4\xd0\xff\xff\xff\xff\xa6%'\xe0\xff\xff\xff\xff\xa7'\u007f\xd0\xff\xff\xff\xff\xaa((`\xff\xff\xff\xff\xaa\xe1\xfd\xd0\xff\xff\xff\xff\xab\xf9\x89\xe0\xff\xff\xff\xff\xac\xc31P\xff\xff\xff\xffȁ?" + + "\xe0\xff\xff\xff\xff\xc9\x01\x13P\xff\xff\xff\xff\xc9J\xf5`\xff\xff\xff\xff\xca\u0380P\xff\xff\xff\xff\xcbˮ`\xff\xff\xff\xff\xd2k\tP\xff\xff\xff\xffӢ9`\xff\xff\xff\xff\xd4C\x02P\xff\xff\xff" + + "\xff\xd5L\r\xe0\xff\xff\xff\xff\xd6){\xd0\xff\xff\xff\xff\xd7+\xef\xe0\xff\xff\xff\xff\xd8\t]\xd0\xff\xff\xff\xff\xd9\x02\x97`\xff\xff\xff\xff\xd9\xe9?\xd0\xff\xff\xff\xff\xda\xeb\xb3\xe0\xff\xff\xff\xff\xdb\xd2\\" + + "P\xff\xff\xff\xff\xdc\xd4\xd0`\xff\xff\xff\xffݲ>P\xff\xff\xff\xff\xf1\xf4\xb9`\xff\xff\xff\xff\xf4b\xefP\xff\xff\xff\xff\xf5h\x06`\xff\xff\xff\xff\xf6\x1f8\xd0\x00\x00\x00\x00\x06n\x93p\x00\x00\x00" + + "\x00\a9\x9ap\x00\x00\x00\x00\a\xfbu\x00\x00\x00\x00\x00\t\x19|p\x00\x00\x00\x00\t\xd0\xcb\x00\x00\x00\x00\x00\n\xf9^p\x00\x00\x00\x00\v\xb1\xfe\x80\x00\x00\x00\x00\f\xd9@p\x00\x00\x00\x00\r\xa4U" + + "\x80\x00\x00\x00\x00\x0e\xa6\xadp\x00\x00\x00\x00\x0f\x847\x80\x00\x00\x00\x00\x0f\xf8\x11P\x00\x00\x00\x00\x19\x89\xb0p\x00\x00\x00\x00\x19ܰ\xe0\x00\x00\x00\x00\x1b\xe6\xd0\xf0\x00\x00\x00\x00\x1c\xc6\xef\xf0\x00\x00\x00" + + "\x00\x1d\x9b1p\x00\x00\x00\x00\x1e\x8cs\xf0\x00\x00\x00\x00\x1f|d\xf0\x00\x00\x00\x00 lU\xf0\x00\x00\x00\x00!\\F\xf0\x00\x00\x00\x00\"L7\xf0\x00\x00\x00\x00#<(\xf0\x00\x00\x00\x00$,\x19" + + "\xf0\x00\x00\x00\x00%\x1c\n\xf0\x00\x00\x00\x00&\v\xfb\xf0\x00\x00\x00\x00'\x05'p\x00\x00\x00\x00'\xf5\x18p\x00\x00\x00\x00(\xe5\tp\x00\x00\x00\x00)\xd4\xfap\x00\x00\x00\x00*\xc4\xebp\x00\x00\x00" + + "\x00+\xb4\xdcp\x00\x00\x00\x00,\xa4\xcdp\x00\x00\x00\x00-\x8b\x83\xf0\x00\x00\x00\x00.\x84\xafp\x00\x00\x00\x00/t\xa0p\x00\x00\x00\x000d\x91p\x00\x00\x00\x001]\xbc\xf0\x00\x00\x00\x002r\x97" + + "\xf0\x00\x00\x00\x003=\x9e\xf0\x00\x00\x00\x004Ry\xf0\x00\x00\x00\x005\x1d\x80\xf0\x00\x00\x00\x0062[\xf0\x00\x00\x00\x006\xfdb\xf0\x00\x00\x00\x008\x1bxp\x00\x00\x00\x008\xddD\xf0\x00\x00\x00" + + "\x009\xfbZp\x00\x00\x00\x00:\xbd&\xf0\x00\x00\x00\x00;\xdb\x86%p\x00\x00\x00\x00?\x9b\x00p\x00\x00\x00\x00@f\a" + + "p\x00\x00\x00\x00A\x84\x1c\xf0\x00\x00\x00\x00BE\xe9p\x00\x00\x00\x00Cc\xfe\xf0\x00\x00\x00\x00D%\xcbp\x00\x00\x00\x00EC\xe0\xf0\x00\x00\x00\x00F\x05ɐ\x00\x00\x00\x00G#\xdf\x10\x00\x00\x00" + + "\x00G\xee\xe6\x10\x00\x00\x00\x00I\x03\xc1\x10\x00\x00\x00\x00I\xce\xc8\x10\x00\x00\x00\x00J\xe3\xa3\x10\x00\x00\x00\x00K\xae\xaa\x10\x00\x00\x00\x00L̿\x90\x00\x00\x00\x00M\x8fݐ\x00\x00\x00\x00N\xac\xa1" + + "\x90\x00\x00\x00\x00Onn\x10\x00\x00\x00\x00P\x8c\x83\x90\x00\x00\x00\x00QW\x8a\x90\x00\x00\x00\x00Rle\x90\x00\x00\x00\x00S8\xbe\x10\x00\x00\x00\x00TLG\x90\x00\x00\x00\x00U\x17N\x90\x00\x00\x00" + + "\x00V>\x9e\x90\x00\x00\x00\x00V\xf70\x90\x00\x00\x00\x00W\xcf.P\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x04\x05\x04\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x04\x00\x00\x1b(\x00\x00\x00\x00\x1bh\x00\x04\x00\x00*0\x01\b\x00\x00\x1c \x00\r\x00\x00*0\x00\x11\x00\x008@\x01\x15LMT\x00IMT\x00" + + "EEST\x00EET\x00+03\x00+04\x00\n<+03>-3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSO+j\x94\x88\x03\x00\x00\x88\x03\x00\x00\x12\x00\x1c\x00Euro" + + "pe/KaliningradUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00P\x00\x00\x00\b\x00\x00\x00\"\xff\xff\xff\xffo\xa2[H\xff\xff\xff\xff\x9b\f\x17`\xff\xff\xff\xff\x9b\xd5\xda\xf0\xff\xff\xff\xff\x9cٮ\x90\xff\xff\xff\xff\x9d\xa4\xb5\x90\xff\xff\xff" + + "\xff\x9e\xb9\x90\x90\xff\xff\xff\xff\x9f\x84\x97\x90\xff\xff\xff\xff\xc8\tq\x90\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЂ%" + + "\x10\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd1|w\xe0\xff\xff\xff\xffѕ\x84`\xff\xff\xff\xffҊ\xadP\xff\xff\xff\xff\xd3Y\xb6\xe0\x00\x00\x00\x00\x15'\xa7\xd0\x00\x00\x00\x00\x16\x18\xdc@\x00\x00\x00" + + "\x00\x17\b\xdbP\x00\x00\x00\x00\x17\xfa\x0f\xc0\x00\x00\x00\x00\x18\xea\x0e\xd0\x00\x00\x00\x00\x19\xdbC@\x00\x00\x00\x00\x1a̓\xd0\x00\x00\x00\x00\x1b\xbc\xa0\xf0\x00\x00\x00\x00\x1c\xac\x91\xf0\x00\x00\x00\x00\x1d\x9c\x82" + + "\xf0\x00\x00\x00\x00\x1e\x8cs\xf0\x00\x00\x00\x00\x1f|d\xf0\x00\x00\x00\x00 lU\xf0\x00\x00\x00\x00!\\F\xf0\x00\x00\x00\x00\"L7\xf0\x00\x00\x00\x00#<(\xf0\x00\x00\x00\x00$,\x19\xf0\x00\x00\x00" + + "\x00%\x1c\x19\x00\x00\x00\x00\x00&\f\n\x00\x00\x00\x00\x00'\x055\x80\x00\x00\x00\x00'\xf5&\x80\x00\x00\x00\x00(\xe5\x17\x80\x00\x00\x00\x00)\xd5\b\x80\x00\x00\x00\x00*\xc4\xf9\x80\x00\x00\x00\x00+\xb4\xea" + + "\x80\x00\x00\x00\x00,\xa4ۀ\x00\x00\x00\x00-\x94̀\x00\x00\x00\x00.\x84\xbd\x80\x00\x00\x00\x00/t\xae\x80\x00\x00\x00\x000d\x9f\x80\x00\x00\x00\x001]\xcb\x00\x00\x00\x00\x002r\xa6\x00\x00\x00\x00" + + "\x003=\xad\x00\x00\x00\x00\x004R\x88\x00\x00\x00\x00\x005\x1d\x8f\x00\x00\x00\x00\x0062j\x00\x00\x00\x00\x006\xfdq\x00\x00\x00\x00\x008\x1b\x86\x80\x00\x00\x00\x008\xddS\x00\x00\x00\x00\x009\xfbh" + + "\x80\x00\x00\x00\x00:\xbd5\x00\x00\x00\x00\x00;\xdbJ\x80\x00\x00\x00\x00<\xa6Q\x80\x00\x00\x00\x00=\xbb,\x80\x00\x00\x00\x00>\x863\x80\x00\x00\x00\x00?\x9b\x0e\x80\x00\x00\x00\x00@f\x15\x80\x00\x00\x00" + + "\x00A\x84+\x00\x00\x00\x00\x00BE\xf7\x80\x00\x00\x00\x00Cd\r\x00\x00\x00\x00\x00D%ـ\x00\x00\x00\x00EC\xef\x00\x00\x00\x00\x00F\x05\xbb\x80\x00\x00\x00\x00G#\xd1\x00\x00\x00\x00\x00G\xee\xd8" + + "\x00\x00\x00\x00\x00I\x03\xb3\x00\x00\x00\x00\x00Iκ\x00\x00\x00\x00\x00J\xe3\x95\x00\x00\x00\x00\x00K\xae\x9c\x00\x00\x00\x00\x00Ḻ\x80\x00\x00\x00\x00M\x8e~\x00\x00\x00\x00\x00TL+p\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x04\x03\x04\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03" + + "\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\a\x04\x00\x00\x138\x00\x00\x00\x00\x1c \x01\x04\x00\x00\x0e\x10\x00\t\x00\x00*0\x01\r\x00\x00\x1c \x00\x12\x00\x008@\x01\x16\x00\x00*0\x00\x1a\x00" + + "\x00*0\x00\x1eLMT\x00CEST\x00CET\x00EEST\x00EET\x00MSD\x00MSK\x00+03\x00\nEET-2\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS" + + "WI\xc3\u007f(\x03\x00\x00(\x03\x00\x00\f\x00\x1c\x00Europe/MinskUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif" + + "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00D\x00\x00\x00\t\x00\x00\x00&\xff\xff\xff\xffV\xb6\xca(\xff\xff\xff\xff\xaa\x19\xaa8\xff\xff\xff\xff\xb5\xa4\x19`\xff\xff\xff\xff\xca" + + "^p\xd0\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xff\xd0\n\x02`\x00\x00\x00\x00\x15'\xa7\xd0\x00\x00\x00\x00\x16\x18\xdc@\x00" + + "\x00\x00\x00\x17\b\xdbP\x00\x00\x00\x00\x17\xfa\x0f\xc0\x00\x00\x00\x00\x18\xea\x0e\xd0\x00\x00\x00\x00\x19\xdbC@\x00\x00\x00\x00\x1a̓\xd0\x00\x00\x00\x00\x1b\xbc\xa0\xf0\x00\x00\x00\x00\x1c\xac\x91\xf0\x00\x00\x00\x00\x1d" + + "\x9c\x82\xf0\x00\x00\x00\x00\x1e\x8cs\xf0\x00\x00\x00\x00\x1f|d\xf0\x00\x00\x00\x00 lU\xf0\x00\x00\x00\x00!\\F\xf0\x00\x00\x00\x00\"L7\xf0\x00\x00\x00\x00#<(\xf0\x00\x00\x00\x00$,\x19\xf0\x00" + + "\x00\x00\x00%\x1c\n\xf0\x00\x00\x00\x00'\xf5\x18p\x00\x00\x00\x00(\xe5\x17\x80\x00\x00\x00\x00)\xd5\b\x80\x00\x00\x00\x00*\xc4\xf9\x80\x00\x00\x00\x00+\xb4\xea\x80\x00\x00\x00\x00,\xa4ۀ\x00\x00\x00\x00-" + + "\x94̀\x00\x00\x00\x00.\x84\xbd\x80\x00\x00\x00\x00/t\xae\x80\x00\x00\x00\x000d\x9f\x80\x00\x00\x00\x001]\xcb\x00\x00\x00\x00\x002r\xa6\x00\x00\x00\x00\x003=\xad\x00\x00\x00\x00\x004R\x88\x00\x00" + + "\x00\x00\x005\x1d\x8f\x00\x00\x00\x00\x0062j\x00\x00\x00\x00\x006\xfdq\x00\x00\x00\x00\x008\x1b\x86\x80\x00\x00\x00\x008\xddS\x00\x00\x00\x00\x009\xfbh\x80\x00\x00\x00\x00:\xbd5\x00\x00\x00\x00\x00;" + + "\xdbJ\x80\x00\x00\x00\x00<\xa6Q\x80\x00\x00\x00\x00=\xbb,\x80\x00\x00\x00\x00>\x863\x80\x00\x00\x00\x00?\x9b\x0e\x80\x00\x00\x00\x00@f\x15\x80\x00\x00\x00\x00A\x84+\x00\x00\x00\x00\x00BE\xf7\x80\x00" + + "\x00\x00\x00Cd\r\x00\x00\x00\x00\x00D%ـ\x00\x00\x00\x00EC\xef\x00\x00\x00\x00\x00F\x05\xbb\x80\x00\x00\x00\x00G#\xd1\x00\x00\x00\x00\x00G\xee\xd8\x00\x00\x00\x00\x00I\x03\xb3\x00\x00\x00\x00\x00I" + + "κ\x00\x00\x00\x00\x00J\xe3\x95\x00\x00\x00\x00\x00K\xae\x9c\x00\x00\x00\x00\x00Ḻ\x80\x00\x00\x00\x00M\x8e~\x00\x01\x02\x03\x05\x04\x05\x04\x05\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03" + + "\x06\x03\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\b\x00\x00\x19\xd8\x00\x00\x00\x00\x19\xc8\x00\x04\x00\x00\x1c \x00" + + "\b\x00\x00*0\x00\f\x00\x00\x0e\x10\x00\x10\x00\x00\x1c \x01\x14\x00\x008@\x01\x19\x00\x00*0\x01\x1d\x00\x00*0\x00\"LMT\x00MMT\x00EET\x00MSK\x00CET\x00CES" + + "T\x00MSD\x00EEST\x00+03\x00\n<+03>-3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x1b8\xfel\xd6\x02\x00\x00\xd6\x02\x00\x00\x0e\x00\x1c\x00Europe" + + "/SaratovUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00@\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\xa1\x009\x80\xff\xff\xff\xff\xb5\xa4\vP\x00\x00\x00\x00\x15'\x99\xc0\x00\x00\x00\x00\x16\x18\xce0\x00\x00\x00\x00\x17\b\xcd@\x00\x00\x00\x00\x17\xfa\x01\xb0\x00" + + "\x00\x00\x00\x18\xea\x00\xc0\x00\x00\x00\x00\x19\xdb50\x00\x00\x00\x00\x1a̅\xc0\x00\x00\x00\x00\x1b\xbc\x92\xe0\x00\x00\x00\x00\x1c\xac\x83\xe0\x00\x00\x00\x00\x1d\x9ct\xe0\x00\x00\x00\x00\x1e\x8ce\xe0\x00\x00\x00\x00\x1f" + + "|V\xe0\x00\x00\x00\x00 lG\xe0\x00\x00\x00\x00!\\8\xe0\x00\x00\x00\x00\"L)\xe0\x00\x00\x00\x00#<(\xf0\x00\x00\x00\x00$,\x19\xf0\x00\x00\x00\x00%\x1c\n\xf0\x00\x00\x00\x00&\v\xfb\xf0\x00" + + "\x00\x00\x00'\x05'p\x00\x00\x00\x00'\xf5\x18p\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xc4\xebp\x00\x00\x00\x00+\xb4\xdcp\x00\x00\x00\x00,\xa4\xcdp\x00\x00\x00\x00-\x94\xbep\x00\x00\x00\x00." + + "\x84\xafp\x00\x00\x00\x00/t\xa0p\x00\x00\x00\x000d\x91p\x00\x00\x00\x001]\xbc\xf0\x00\x00\x00\x002r\x97\xf0\x00\x00\x00\x003=\x9e\xf0\x00\x00\x00\x004Ry\xf0\x00\x00\x00\x005\x1d\x80\xf0\x00" + + "\x00\x00\x0062[\xf0\x00\x00\x00\x006\xfdb\xf0\x00\x00\x00\x008\x1bxp\x00\x00\x00\x008\xddD\xf0\x00\x00\x00\x009\xfbZp\x00\x00\x00\x00:\xbd&\xf0\x00\x00\x00\x00;\xdb\x86%p\x00\x00\x00\x00?\x9b\x00p\x00\x00\x00\x00@f\ap\x00\x00\x00\x00A\x84\x1c\xf0\x00\x00\x00\x00BE\xe9p\x00\x00\x00\x00Cc\xfe\xf0\x00" + + "\x00\x00\x00D%\xcbp\x00\x00\x00\x00EC\xe0\xf0\x00\x00\x00\x00F\x05\xadp\x00\x00\x00\x00G#\xc2\xf0\x00\x00\x00\x00G\xee\xc9\xf0\x00\x00\x00\x00I\x03\xa4\xf0\x00\x00\x00\x00IΫ\xf0\x00\x00\x00\x00J" + + "\xe3\x86\xf0\x00\x00\x00\x00K\xae\x8d\xf0\x00\x00\x00\x00Ḷp\x00\x00\x00\x00M\x8eo\xf0\x00\x00\x00\x00TL\x1d`\x00\x00\x00\x00XCNp\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04" + + "\x01\x04\x01\x04\x01\x03\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x03\x01\x03\x00\x00+2\x00\x00\x00\x00*0\x00\x04\x00" + + "\x00FP\x01\b\x00\x008@\x00\f\x00\x008@\x01\fLMT\x00+03\x00+05\x00+04\x00\n<+04>-4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x92\xfc\f+" + + "o\x02\x00\x00o\x02\x00\x00\x11\x00\x1c\x00Europe/CopenhagenUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZi" + + "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x003\x00\x00\x00\x04\x00\x00\x00\x11\xff\xff\xff\xffi\x86ϴ\xff\xff\xff\xffq\f\xef4\xff\xff\xff\xff\x9b\x1e\x8c`\xff\xff\xff\xff" + + "\x9bվ\xd0\xff\xff\xff\xff\xc8CWp\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff\xff\xd1r\x16\x10" + + "\xff\xff\xff\xff\xd2$\x10\x90\xff\xff\xff\xff\xd3y\x85\x10\xff\xff\xff\xff\xd4\x1b\xad\x90\xff\xff\xff\xff\xd5^\xad\x10\xff\xff\xff\xff\xd5\xdf\xe0\x10\xff\xff\xff\xff\xd7Gɐ\xff\xff\xff\xff\u05ff\xc2\x10\x00\x00\x00\x00" + + "\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90" + + "\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00" + + "!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#\x86\x17`\x00\x00\x00\x00?\x9a\xf2`\x00\x00\x00\x00@e\xf9`\x00\x00\x00\x00A\x84\x0e\xe0\x00\x00\x00\x00BE" + + "\xdb`\x00\x00\x00\x00Cc\xf0\xe0\x00\x00\x00\x00D%\xbd`\x00\x00\x00\x00EC\xd2\xe0\x00\x00\x00\x00F\x05\x9f`\x00\x00\x00\x00G#\xb4\xe0\x00\x00\x00\x00G\xee\xbb\xe0\x00\x00\x00\x00I\x03\x96\xe0\x00\x00" + + "\x00\x00IΝ\xe0\x00\x00\x00\x00J\xe3x\xe0\x00\x00\x00\x00K\xae\u007f\xe0\x00\x00\x00\x00Ḷp\x00\x00\x00\x00M\x8eo\xf0\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x04\x01\x04\x01" + + "\x05\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x04\x01\x02\x00\x00.\xf4\x00\x00\x00\x00*0\x00\x04\x00\x008@\x00\b" + + "\x00\x00FP\x01\f\x00\x008@\x01\b\x00\x00*0\x01\x04LMT\x00+03\x00+04\x00+05\x00\n<+04>-4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x95\xb4\x9e" + + "\xe7\xb3\x03\x00\x00\xb3\x03\x00\x00\v\x00\x1c\x00Europe/RomeUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00W\x00\x00\x00\x04\x00\x00\x00\x11\xff\xff\xff\xff>(\xe8L\xff\xff\xff\xffp\xbc\x81p\xff\xff\xff\xff\x9b8\xf8p\xff\xff\xff\xff\x9b\xd5\xcc\xe0\xff" + + "\xff\xff\xff\x9c\xc5\xcb\xf0\xff\xff\xff\xff\x9d\xb7\x00`\xff\xff\xff\xff\x9e\x89\xfep\xff\xff\xff\xff\x9f\xa0\x1c\xe0\xff\xff\xff\xff\xa0`\xa5\xf0\xff\xff\xff\xff\xa1~\xad`\xff\xff\xff\xff\xa2\\7p\xff\xff\xff\xff\xa3" + + "L\x1a`\xff\xff\xff\xff\xc8l5\xf0\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xff\xd0n^\x90\xff\xff\xff\xff\xd1r\x16\x10\xff" + + "\xff\xff\xff\xd2L\xd2\xf0\xff\xff\xff\xff\xd3>1\x90\xff\xff\xff\xff\xd4I\xd2\x10\xff\xff\xff\xff\xd5\x1d\xf7p\xff\xff\xff\xff\xd6)\x97\xf0\xff\xff\xff\xff\xd6뀐\xff\xff\xff\xff\xd8\t\x96\x10\xff\xff\xff\xff\xf9" + + "3\xb5\xf0\xff\xff\xff\xff\xf9\xd9\xc4\xe0\xff\xff\xff\xff\xfb\x1c\xd2p\xff\xff\xff\xff\xfb\xb9\xb4\xf0\xff\xff\xff\xff\xfc\xfc\xb4p\xff\xff\xff\xff\xfd\x99\x96\xf0\xff\xff\xff\xff\xfe\xe5\xd0\xf0\xff\xff\xff\xff\xff\x82\xb3p\x00" + + "\x00\x00\x00\x00Ų\xf0\x00\x00\x00\x00\x01b\x95p\x00\x00\x00\x00\x02\x9cZp\x00\x00\x00\x00\x03Bwp\x00\x00\x00\x00\x04\x85v\xf0\x00\x00\x00\x00\x05+\x93\xf0\x00\x00\x00\x00\x06n\x93p\x00\x00\x00\x00\a" + + "\vu\xf0\x00\x00\x00\x00\bE:\xf0\x00\x00\x00\x00\b\xebW\xf0\x00\x00\x00\x00\n.Wp\x00\x00\x00\x00\n\xcb9\xf0\x00\x00\x00\x00\f\x0e9p\x00\x00\x00\x00\f\xab\x1b\xf0\x00\x00\x00\x00\r\xe4\xe0\xf0\x00" + + "\x00\x00\x00\x0e\x8a\xfd\xf0\x00\x00\x00\x00\x0f\xcd\xfdp\x00\x00\x00\x00\x10t\x1ap\x00\x00\x00\x00\x11\xad\xdfp\x00\x00\x00\x00\x12S\xfcp\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15" + + "#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00" + + "\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#" + + "0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rk\xa4" + - ",\xb6?\x06\x00\x00?\x06\x00\x00\x02\x00\x1c\x00GBUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9f\x00\x00\x00\x05\x00\x00\x00\x11\xff\xff\xff\xff\x1a]\t\xcb\xff\xff\xff\xff\x9b&\xad\xa0\xff\xff\xff\xff\x9b\xd6\x05 \xff\xff\xff\xff\x9c\xcf0\xa0\xff\xff\xff\xff\x9d\xa4à\xff" + - "\xff\xff\xff\x9e\x9c\x9d\xa0\xff\xff\xff\xff\x9f\x97\x1a\xa0\xff\xff\xff\xff\xa0\x85\xba \xff\xff\xff\xff\xa1v\xfc\xa0\xff\xff\xff\xff\xa2e\x9c \xff\xff\xff\xff\xa3{Ƞ\xff\xff\xff\xff\xa4N\xb8\xa0\xff\xff\xff\xff\xa5" + - "?\xfb \xff\xff\xff\xff\xa6%` \xff\xff\xff\xff\xa7'\xc6 \xff\xff\xff\xff\xa8*, \xff\xff\xff\xff\xa8\xeb\xf8\xa0\xff\xff\xff\xff\xaa\x00Ӡ\xff\xff\xff\xff\xaa\xd5\x15 \xff\xff\xff\xff\xab\xe9\xf0 \xff" + - "\xff\xff\xff\xac\xc7l \xff\xff\xff\xff\xad\xc9\xd2 \xff\xff\xff\xff\xae\xa7N \xff\xff\xff\xff\xaf\xa0y\xa0\xff\xff\xff\xff\xb0\x870 \xff\xff\xff\xff\xb1\x92Р\xff\xff\xff\xff\xb2pL\xa0\xff\xff\xff\xff\xb3" + - "r\xb2\xa0\xff\xff\xff\xff\xb4P.\xa0\xff\xff\xff\xff\xb5IZ \xff\xff\xff\xff\xb60\x10\xa0\xff\xff\xff\xff\xb72v\xa0\xff\xff\xff\xff\xb8\x0f\xf2\xa0\xff\xff\xff\xff\xb9\x12X\xa0\xff\xff\xff\xff\xb9\xefԠ\xff" + - "\xff\xff\xff\xba\xe9\x00 \xff\xff\xff\xff\xbb\xd8\xf1 \xff\xff\xff\xff\xbc\xdbW \xff\xff\xff\xff\xbd\xb8\xd3 \xff\xff\xff\xff\xbe\xb1\xfe\xa0\xff\xff\xff\xff\xbf\x98\xb5 \xff\xff\xff\xff\xc0\x9b\x1b \xff\xff\xff\xff\xc1" + - "x\x97 \xff\xff\xff\xff\xc2z\xfd \xff\xff\xff\xff\xc3Xy \xff\xff\xff\xff\xc4Q\xa4\xa0\xff\xff\xff\xff\xc58[ \xff\xff\xff\xff\xc6:\xc1 \xff\xff\xff\xff\xc7X֠\xff\xff\xff\xff\xc7\xda\t\xa0\xff" + - "\xff\xff\xff\xca\x16&\x90\xff\xff\xff\xffʗY\x90\xff\xff\xff\xff\xcb\xd1\x1e\x90\xff\xff\xff\xff\xccw;\x90\xff\xff\xff\xffͱ\x00\x90\xff\xff\xff\xff\xce`X\x10\xff\xff\xff\xffϐ\xe2\x90\xff\xff\xff\xff\xd0" + - "n^\x90\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd1\xfb2\x10\xff\xff\xff\xff\xd2i\xfe \xff\xff\xff\xff\xd3c)\xa0\xff\xff\xff\xff\xd4I\xe0 \xff\xff\xff\xff\xd5\x1e!\xa0\xff\xff\xff\xff\xd5B\xfd\x90\xff" + - "\xff\xff\xff\xd5\xdf\xe0\x10\xff\xff\xff\xff\xd6N\xac \xff\xff\xff\xff\xd6\xfe\x03\xa0\xff\xff\xff\xff\xd8.\x8e \xff\xff\xff\xff\xd8\xf9\x95 \xff\xff\xff\xff\xda\x0ep \xff\xff\xff\xff\xda\xeb\xec \xff\xff\xff\xff\xdb" + - "\xe5\x17\xa0\xff\xff\xff\xff\xdc\xcb\xce \xff\xff\xff\xff\xdd\xc4\xf9\xa0\xff\xff\xff\xff\u07b4\xea\xa0\xff\xff\xff\xff߮\x16 \xff\xff\xff\xff\xe0\x94̠\xff\xff\xff\xff\xe1rH\xa0\xff\xff\xff\xff\xe2kt \xff" + - "\xff\xff\xff\xe3R*\xa0\xff\xff\xff\xff\xe4T\x90\xa0\xff\xff\xff\xff\xe52\f\xa0\xff\xff\xff\xff\xe6=\xad \xff\xff\xff\xff\xe7\x1b) \xff\xff\xff\xff\xe8\x14T\xa0\xff\xff\xff\xff\xe8\xfb\v \xff\xff\xff\xff\xe9" + - "\xfdq \xff\xff\xff\xff\xea\xda\xed \xff\xff\xff\xff\xeb\xddS \xff\xff\xff\xff\xec\xba\xcf \xff\xff\xff\xff\xed\xb3\xfa\xa0\xff\xff\xff\xff\ue6b1 \xff\xff\xff\xff\xef\x81g\xa0\xff\xff\xff\xff\xf0\x9f} \xff" + - "\xff\xff\xff\xf1aI\xa0\xff\xff\xff\xff\xf2\u007f_ \xff\xff\xff\xff\xf3Jf \xff\xff\xff\xff\xf4_A \xff\xff\xff\xff\xf5!\r\xa0\xff\xff\xff\xff\xf6?# \xff\xff\xff\xff\xf7\x00\xef\xa0\xff\xff\xff\xff\xf8" + - "\x1f\x05 \xff\xff\xff\xff\xf8\xe0Ѡ\xff\xff\xff\xff\xf9\xfe\xe7 \xff\xff\xff\xff\xfa\xc0\xb3\xa0\xff\xff\xff\xff\xfb\xe8\x03\xa0\xff\xff\xff\xff\xfc{\xab\xa0\xff\xff\xff\xff\xfdǻp\x00\x00\x00\x00\x03p\xc6 \x00" + - "\x00\x00\x00\x04)X \x00\x00\x00\x00\x05P\xa8 \x00\x00\x00\x00\x06\t: \x00\x00\x00\x00\a0\x8a \x00\x00\x00\x00\a\xe9\x1c \x00\x00\x00\x00\t\x10l \x00\x00\x00\x00\t\xc8\xfe \x00\x00\x00\x00\n" + - "\xf0N \x00\x00\x00\x00\v\xb2\x1a\xa0\x00\x00\x00\x00\f\xd00 \x00\x00\x00\x00\r\x91\xfc\xa0\x00\x00\x00\x00\x0e\xb0\x12 \x00\x00\x00\x00\x0fqޠ\x00\x00\x00\x00\x10\x99.\xa0\x00\x00\x00\x00\x11Q\xc0\xa0\x00" + - "\x00\x00\x00\x12y\x10\xa0\x00\x00\x00\x00\x131\xa2\xa0\x00\x00\x00\x00\x14X\xf2\xa0\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x168Ɛ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x18\x18\xa8\x90\x00\x00\x00\x00\x18" + - "㯐\x00\x00\x00\x00\x19\xf8\x8a\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xe1\xa7\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\xc1\x89\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f\xa1k\x10\x00" + - "\x00\x00\x00 lr\x10\x00\x00\x00\x00!\x81M\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#a/\x10\x00\x00\x00\x00$,6\x10\x00\x00\x00\x00%JK\x90\x00\x00\x00\x00&\f\x18\x10\x00\x00\x00\x00'" + - "*-\x90\x00\x00\x00\x00'\xf54\x90\x00\x00\x00\x00)\n\x0f\x90\x00\x00\x00\x00)\xd5\x16\x90\x00\x00\x00\x00*\xe9\xf1\x90\x00\x00\x00\x00+\xb4\xf8\x90\x00\x00\x00\x00,\xc9Ӑ\x00\x00\x00\x00-\x94ڐ\x00" + - "\x00\x00\x00.\xa9\xb5\x90\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000\x89\x97\x90\x00\x00\x00\x001]\xd9\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x02\x01\x02\x01\x03\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xff\xb5\x00\x00\x00\x00\x0e\x10\x01\x04\x00\x00\x00\x00\x00\b\x00\x00\x1c \x01\f\x00\x00\x0e\x10\x00\x04LMT\x00BST\x00GMT\x00BDST\x00\nGM" + - "T0BST,M3.5.0/1,M10.5.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rk\xa4,\xb6?\x06\x00\x00?\x06\x00\x00\a\x00\x1c\x00GB-Eire" + - "UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x005\x00\x00\x00\t\x00\x00\x00&\xff\xff\xff\xffV\xb6\xcd^\xff\xff\xff\xff\x9e\xb9\x87\xfe\xff\xff\xff\xff\x9f\x84\x8e\xfe\xff\xff\xff\xff\xa0\x88F~\xff\xff" + + "\xff\xff\xa0˂\xfe\xff\xff\xff\xff\xad\xe7\xf1\xde\xff\xff\xff\xffȯd`\xff\xff\xff\xff\xcabeP\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ" + + "4\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff\xffА\x89p\x00\x00\x00\x00\x15'\xa7\xd0\x00\x00\x00\x00\x16\x18\xdc@\x00\x00\x00\x00\x17\b\xdbP\x00\x00\x00\x00\x17\xfa\x0f\xc0\x00\x00\x00\x00\x18\xea\x0e\xd0\x00\x00" + + "\x00\x00\x19\xdbC@\x00\x00\x00\x00\x1a̓\xd0\x00\x00\x00\x00\x1b\xbc\xa0\xf0\x00\x00\x00\x00\x1c\xac\x91\xf0\x00\x00\x00\x00\x1d\x9c\x82\xf0\x00\x00\x00\x00\x1e\x8cs\xf0\x00\x00\x00\x00\x1f|d\xf0\x00\x00\x00\x00 l" + + "U\xf0\x00\x00\x00\x00!\\F\xf0\x00\x00\x00\x00\"L7\xf0\x00\x00\x00\x00#<(\xf0\x00\x00\x00\x00$,\x19\xf0\x00\x00\x00\x00%\x1c\x19\x00\x00\x00\x00\x00&\f\n\x00\x00\x00\x00\x00'\x055\x80\x00\x00" + + "\x00\x00'\xf5&\x80\x00\x00\x00\x00(\xe5\x17\x80\x00\x00\x00\x00)\xd5\b\x80\x00\x00\x00\x00*\xc4\xf9\x80\x00\x00\x00\x00+\xb4\xea\x80\x00\x00\x00\x00,\xa4ۀ\x00\x00\x00\x00-\x94̀\x00\x00\x00\x00.\x84" + + "\xbd\x80\x00\x00\x00\x00/t\xae\x80\x00\x00\x00\x000d\x9f\x80\x00\x00\x00\x001]\xcb\x00\x00\x00\x00\x002M\xbc\x00\x00\x00\x00\x003=\xbb\x10\x00\x00\x00\x004R\x96\x10\x00\x00\x00\x005\x1d\x9d\x10\x00\x00" + + "\x00\x0062x\x10\x00\x00\x00\x006\xfd\u007f\x10\x00\x00\x00\x008\x1b\x94\x90\x00\x00\x00\x00:\xbdC\x10\x01\x02\x01\x02\x01\x03\x04\x06\x05\x06\x05\x06\x05\x04\a\x04\a\x04\a\x04\a\x04\a\x04\a\x04\a\x04\a\x04" + + "\b\x03\b\x03\b\x03\b\x03\b\x03\b\x03\b\x03\b\x03\b\x03\b\x03\b\x03\b\x00\x00\x16\xa2\x00\x00\x00\x00\x16\xa2\x00\x04\x00\x00$\xb2\x01\b\x00\x00\x1c \x00\f\x00\x00*0\x00\x10\x00\x00\x0e\x10\x00\x14\x00" + + "\x00\x1c \x01\x18\x00\x008@\x01\x1d\x00\x00*0\x01!LMT\x00RMT\x00LST\x00EET\x00MSK\x00CET\x00CEST\x00MSD\x00EEST\x00\nEET-" + + "2EEST,M3.5.0/3,M10.5.0/4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xe1\xc1\xeb\x05\x8c\x03\x00\x00\x8c\x03\x00\x00\r\x00\x1c\x00Europ" + + "e/MoscowUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00N\x00\x00\x00\v\x00\x00\x00&\xff\xff\xff\xffV\xb6\xc0\xc7\xff\xff\xff\xff\x9b_\x1e\xc7\xff\xff\xff\xff\x9d>\xf2y\xff\xff\xff\xff\x9e*\xee\xf9\xff\xff\xff\xff\x9e\xf79i\xff\xff\xff\xff\x9f\x84W\xf9\xff" + + "\xff\xff\xff\xa0\xd8l\xe9\xff\xff\xff\xff\xa1\x009\x80\xff\xff\xff\xff\xa1<\xa6@\xff\xff\xff\xff\xa4\x10m\xc0\xff\xff\xff\xff\xa4=2\xb0\xff\xff\xff\xff\xa5\x15h\xb0\xff\xff\xff\xff\xa5=\x03\xc0\xff\xff\xff\xff\xa7" + + "\x1eEP\xff\xff\xff\xff\xb5\xa4\x19`\x00\x00\x00\x00\x15'\xa7\xd0\x00\x00\x00\x00\x16\x18\xdc@\x00\x00\x00\x00\x17\b\xdbP\x00\x00\x00\x00\x17\xfa\x0f\xc0\x00\x00\x00\x00\x18\xea\x0e\xd0\x00\x00\x00\x00\x19\xdbC@\x00" + + "\x00\x00\x00\x1a̓\xd0\x00\x00\x00\x00\x1b\xbc\xa0\xf0\x00\x00\x00\x00\x1c\xac\x91\xf0\x00\x00\x00\x00\x1d\x9c\x82\xf0\x00\x00\x00\x00\x1e\x8cs\xf0\x00\x00\x00\x00\x1f|d\xf0\x00\x00\x00\x00 lU\xf0\x00\x00\x00\x00!" + + "\\F\xf0\x00\x00\x00\x00\"L7\xf0\x00\x00\x00\x00#<(\xf0\x00\x00\x00\x00$,\x19\xf0\x00\x00\x00\x00%\x1c\n\xf0\x00\x00\x00\x00&\v\xfb\xf0\x00\x00\x00\x00'\x05'p\x00\x00\x00\x00'\xf5\x18p\x00" + + "\x00\x00\x00(\xe5\x17\x80\x00\x00\x00\x00)x\xbf\x80\x00\x00\x00\x00)\xd4\xfap\x00\x00\x00\x00*\xc4\xebp\x00\x00\x00\x00+\xb4\xdcp\x00\x00\x00\x00,\xa4\xcdp\x00\x00\x00\x00-\x94\xbep\x00\x00\x00\x00." + + "\x84\xafp\x00\x00\x00\x00/t\xa0p\x00\x00\x00\x000d\x91p\x00\x00\x00\x001]\xbc\xf0\x00\x00\x00\x002r\x97\xf0\x00\x00\x00\x003=\x9e\xf0\x00\x00\x00\x004Ry\xf0\x00\x00\x00\x005\x1d\x80\xf0\x00" + + "\x00\x00\x0062[\xf0\x00\x00\x00\x006\xfdb\xf0\x00\x00\x00\x008\x1bxp\x00\x00\x00\x008\xddD\xf0\x00\x00\x00\x009\xfbZp\x00\x00\x00\x00:\xbd&\xf0\x00\x00\x00\x00;\xdb\x86%p\x00\x00\x00\x00?\x9b\x00p\x00\x00\x00\x00@f\ap\x00\x00\x00\x00A\x84\x1c\xf0\x00\x00\x00\x00BE\xe9p\x00\x00\x00\x00Cc\xfe\xf0\x00" + + "\x00\x00\x00D%\xcbp\x00\x00\x00\x00EC\xe0\xf0\x00\x00\x00\x00F\x05\xadp\x00\x00\x00\x00G#\xc2\xf0\x00\x00\x00\x00G\xee\xc9\xf0\x00\x00\x00\x00I\x03\xa4\xf0\x00\x00\x00\x00IΫ\xf0\x00\x00\x00\x00J" + + "\xe3\x86\xf0\x00\x00\x00\x00K\xae\x8d\xf0\x00\x00\x00\x00Ḷp\x00\x00\x00\x00M\x8eo\xf0\x00\x00\x00\x00TL\x1d`\x01\x03\x02\x03\x04\x02\x04\x05\x06\x05\a\x05\x06\b\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06" + + "\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\t\b\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\n\x06\x00\x00#9\x00\x00\x00" + + "\x00#9\x00\x04\x00\x001\x87\x01\b\x00\x00#w\x00\x04\x00\x00?\x97\x01\f\x00\x008@\x01\x11\x00\x00*0\x00\x15\x00\x00FP\x01\x19\x00\x00\x1c \x00\x1d\x00\x00*0\x01!\x00\x008@\x00\x15L" + + "MT\x00MMT\x00MST\x00MDST\x00MSD\x00MSK\x00+05\x00EET\x00EEST\x00\nMSK-3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x17S" + + "\x91\xb3\xc1\x02\x00\x00\xc1\x02\x00\x00\r\x00\x1c\x00Europe/BerlinUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xffo\xa2a\xf8\xff\xff\xff\xff\x9b\f\x17`\xff\xff\xff\xff\x9b\xd5\xda\xf0\xff\xff\xff\xff\x9c\xd9" + + "\xae\x90\xff\xff\xff\xff\x9d\xa4\xb5\x90\xff\xff\xff\xff\x9e\xb9\x90\x90\xff\xff\xff\xff\x9f\x84\x97\x90\xff\xff\xff\xff\xc8\tq\x90\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff" + + "\xff\xffϒ4\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xffѶ\x96\x00\xff\xff\xff\xff\xd2X\xbe\x80\xff\xff\xff\xffҡO\x10\xff\xff\xff\xff\xd3c\x1b\x90\xff\xff\xff\xff\xd4K" + + "#\x90\xff\xff\xff\xff\xd59\xd1 \xff\xff\xff\xff\xd5g\xe7\x90\xff\xff\xff\xffըs\x00\xff\xff\xff\xff\xd6)\xb4\x10\xff\xff\xff\xff\xd7,\x1a\x10\xff\xff\xff\xff\xd8\t\x96\x10\xff\xff\xff\xff\xd9\x02\xc1\x90\xff\xff" + + "\xff\xff\xd9\xe9x\x10\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18\xe3" + + "\xaf\x90\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00" + + "\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#\x86A\x90\x00\x00\x00\x00?\x9b\x1c\x90\x00\x00\x00\x00@f#\x90\x00\x00\x00\x00A\x849\x10\x00\x00\x00\x00BF\x05\x90\x00\x00" + + "\x00\x00Cd\x1b\x10\x00\x00\x00\x00D%\xe7\x90\x00\x00\x00\x00EC\xfd\x10\x00\x00\x00\x00F\x05ɐ\x00\x00\x00\x00G#\xdf\x10\x00\x00\x00\x00G\xee\xe6\x10\x00\x00\x00\x00I\x03\xc1\x10\x00\x00\x00\x00I\xce" + + "\xc8\x10\x00\x00\x00\x00J\xe3\xa3\x10\x00\x00\x00\x00K\xae\xaa\x10\x00\x00\x00\x00L̿\x90\x00\x00\x00\x00M\x8e\x8c\x10\x00\x00\x00\x00N\xac\xa1\x90\x00\x00\x00\x00Onn\x10\x00\x00\x00\x00P\x8c\x83\x90\x00\x00" + + "\x00\x00QW\x8a\x90\x00\x00\x00\x00Rle\x90\x00\x00\x00\x00S7^\x80\x00\x00\x00\x00TL\x1d`\x01\x02\x03\x05\x04\x05\x04\x05\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x02\a\x02" + + "\a\x02\a\x06\x03\x06\x03\x06\x03\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\a\x02\b\x03\x00\x00\x1f\xf8\x00\x00\x00\x00\x1f\xe0\x00\x04\x00\x00\x1c" + + " \x00\b\x00\x00*0\x00\f\x00\x00\x0e\x10\x00\x10\x00\x00\x1c \x01\x14\x00\x008@\x01\x19\x00\x00*0\x01\x1d\x00\x008@\x00\fLMT\x00SMT\x00EET\x00MSK\x00CET\x00C" + + "EST\x00MSD\x00EEST\x00\nMSK-3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSIo\x11{\xd3\x02\x00\x00\xd3\x02\x00\x00\r\x00\x1c\x00Europe/Pra" + + "gueUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x00\x00" + + "\x00\x05\x00\x00\x00\x15\xff\xff\xff\xff\x1eI\x92\xf8\xff\xff\xff\xffl\xcf\xea\xf8\xff\xff\xff\xff\x9b\f\x17`\xff\xff\xff\xff\x9b\xd5\xda\xf0\xff\xff\xff\xff\x9cٮ\x90\xff\xff\xff\xff\x9d\xa4\xb5\x90\xff\xff\xff\xff\x9e\xb9" + + "\x90\x90\xff\xff\xff\xff\x9f\x84\x97\x90\xff\xff\xff\xff\xc8\tq\x90\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЂ%\x10\xff\xff" + + "\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd2b\a\x10\xff\xff\xff\xffӀ\x1c\x90\xff\xff\xff\xff\xd4I\xd2\x10\xff\xff\xff\xffԓ\xb4 \xff\xff\xff\xff\xd5\x02r \xff\xff\xff\xff\xd5L8\x10\xff\xff\xff\xff\xd6)" + + "\xb4\x10\xff\xff\xff\xff\xd7,\x1a\x10\xff\xff\xff\xff\xd8\t\x96\x10\xff\xff\xff\xff\xd9\x01p\x10\xff\xff\xff\xff\xd9\xe9x\x10\x00\x00\x00\x00\x11d'\x90\x00\x00\x00\x00\x12T\x18\x90\x00\x00\x00\x00\x13MD\x10\x00\x00" + + "\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1a\xc3" + + "\x91\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00" + + "\x00\x00\"LT\x10\x00\x00\x00\x00#\xf3`\xff\xff\xff\xff\xb9\xef\x9c`\xff\xff\xff\xff\xbaߍ`\xff\xff\xff\xff\xbb\xcf~`\xff\xff\xff\xff\xbcȩ\xe0\xff\xff\xff\xff\xbd\xb8\x9a" + + "\xe0\xff\xff\xff\xff\xbe\xa8\x8b\xe0\xff\xff\xff\xff\xbf\x98|\xe0\xff\xff\xff\xff\xc0\x88m\xe0\xff\xff\xff\xff\xc1x^\xe0\xff\xff\xff\xff\xc2hO\xe0\xff\xff\xff\xff\xc3X@\xe0\xff\xff\xff\xff\xc4H1\xe0\xff\xff\xff" + + "\xff\xc58\"\xe0\xff\xff\xff\xff\xc6(\x13\xe0\xff\xff\xff\xff\xc7\x18\x04\xe0\xff\xff\xff\xffȼ\x93`\xff\xff\xff\xff\xcaw}P\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C" + + "\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xff\xd0N\x90`\x00\x00\x00\x00\x15'\xa7\xd0\x00\x00\x00\x00\x16\x18\xdc@\x00\x00\x00\x00\x17\b\xdbP\x00\x00\x00\x00\x17\xfa\x0f\xc0\x00\x00\x00\x00\x18\xea\x0e\xd0\x00\x00\x00" + + "\x00\x19\xdbC@\x00\x00\x00\x00\x1a̓\xd0\x00\x00\x00\x00\x1b\xbc\xa0\xf0\x00\x00\x00\x00\x1c\xac\x91\xf0\x00\x00\x00\x00\x1d\x9c\x82\xf0\x00\x00\x00\x00\x1e\x8cs\xf0\x00\x00\x00\x00\x1f|d\xf0\x00\x00\x00\x00 lU" + + "\xf0\x00\x00\x00\x00!\\F\xf0\x00\x00\x00\x00\"L7\xf0\x00\x00\x00\x00#<(\xf0\x00\x00\x00\x00$,\x19\xf0\x00\x00\x00\x00%\x1c\n\xf0\x00\x00\x00\x00&\v\xfb\xf0\x00\x00\x00\x00&CL\xe0\x00\x00\x00" + + "\x00'\x055\x80\x00\x00\x00\x00'\xf5&\x80\x00\x00\x00\x00(\xe5\x17\x80\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xc4\xcfP\x00\x00\x00\x00+\xb4\xce`\x00\x00\x00\x00,\xa4\xb1P\x00\x00\x00\x00-\x94\xb0" + + "`\x00\x00\x00\x00.\x84\x93P\x00\x00\x00\x00/t\x92`\x00\x00\x00\x000duP\x00\x00\x00\x001]\xae\xe0\x00\x00\x00\x002r{\xd0\x00\x00\x00\x003=\xad\x00\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04" + + "\x03\x04\x03\x04\x03\x04\x03\x04\x03\x06\x05\x06\x05\x06\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x00\x00\x1b\b\x00\x00\x00\x00\x1a\xf4\x00" + + "\x04\x00\x00\x18x\x00\b\x00\x00*0\x01\f\x00\x00\x1c \x00\x11\x00\x00\x0e\x10\x00\x15\x00\x00\x1c \x01\x19\x00\x008@\x01\x1e\x00\x00*0\x00\"LMT\x00CMT\x00BMT\x00EEST\x00" + + "EET\x00CET\x00CEST\x00MSD\x00MSK\x00\nEET-2EEST,M3.5.0,M10.5.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00#" + + "\x82iS>\xfe垛\x03\x00\x00\x9b\x03\x00\x00\r\x00\x1c\x00Europe/WarsawUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00" + + "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00R\x00\x00\x00\x06\x00\x00\x00\x1a\xff\xff\xff\xffV\xb6\xd0P\xff\xff\xff\xff\x99\xa8*\xd0\xff\xff\xff\xff\x9b\f\x17`\xff" + + "\xff\xff\xff\x9b\xd5\xda\xf0\xff\xff\xff\xff\x9cٮ\x90\xff\xff\xff\xff\x9d\xa4\xb5\x90\xff\xff\xff\xff\x9e\xb9\x90\x90\xff\xff\xff\xff\x9f\x84\x97\x90\xff\xff\xff\xff\xa0\x9a\xb6\x00\xff\xff\xff\xff\xa1e\xbd\x00\xff\xff\xff\xff\xa6" + + "}|`\xff\xff\xff\xff\xc8v\xde\x10\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЄ\xba\x00\xff\xff\xff\xffѕ\x92p\xff" + + "\xff\xff\xffҊ\xbb`\xff\xff\xff\xff\xd3b\xffp\xff\xff\xff\xff\xd4K#\x90\xff\xff\xff\xff\xd5^\xad\x10\xff\xff\xff\xff\xd6)\xb4\x10\xff\xff\xff\xff\xd7,\x1a\x10\xff\xff\xff\xff\xd8\t\x96\x10\xff\xff\xff\xff\xd9" + + "\x02\xc1\x90\xff\xff\xff\xff\xd9\xe9x\x10\xff\xff\xff\xff\xe8T\xd2\x00\xff\xff\xff\xff\xe8\xf1\xb4\x80\xff\xff\xff\xff\xe9᥀\xff\xff\xff\xff\xeaі\x80\xff\xff\xff\xff\xec\x14\x96\x00\xff\xff\xff\xff캳\x00\xff" + + "\xff\xff\xff\xed\xaa\xa4\x00\xff\xff\xff\xff\ue695\x00\xff\xff\xff\xff\xef\xd4Z\x00\xff\xff\xff\xff\xf0zw\x00\xff\xff\xff\xff\xf1\xb4<\x00\xff\xff\xff\xff\xf2ZY\x00\xff\xff\xff\xff\xf3\x94\x1e\x00\xff\xff\xff\xff\xf4" + + ":;\x00\xff\xff\xff\xff\xf5}:\x80\xff\xff\xff\xff\xf6\x1a\x1d\x00\x00\x00\x00\x00\r\xa4U\x80\x00\x00\x00\x00\x0e\x8b\f\x00\x00\x00\x00\x00\x0f\x847\x80\x00\x00\x00\x00\x10t(\x80\x00\x00\x00\x00\x11d\x19\x80\x00" + + "\x00\x00\x00\x12T\n\x80\x00\x00\x00\x00\x13M6\x00\x00\x00\x00\x00\x143\xec\x80\x00\x00\x00\x00\x15#݀\x00\x00\x00\x00\x16\x13\u0380\x00\x00\x00\x00\x17\x03\xbf\x80\x00\x00\x00\x00\x17\xf3\xb0\x80\x00\x00\x00\x00\x18" + + "㡀\x00\x00\x00\x00\x19Ӓ\x80\x00\x00\x00\x00\x1aÃ\x80\x00\x00\x00\x00\x1b\xbc\xaf\x00\x00\x00\x00\x00\x1c\xac\xa0\x00\x00\x00\x00\x00\x1d\x9c\x91\x00\x00\x00\x00\x00\x1e\x8c\x82\x00\x00\x00\x00\x00\x1f|s\x00\x00" + + "\x00\x00\x00 ld\x00\x00\x00\x00\x00!\\U\x00\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#A\xb8\xff\xff\xff\xff\xd8.2\xb8\xff\xff\xff\xff\xd8\xf99\xb8\xff\xff\xff\xff\xda" + - "\x0e\x14\xb8\xff\xff\xff\xff\xda\xd9\x1b\xb8\xff\xff\xff\xff\xdb\xed\xf6\xb8\xff\xff\xff\xffܸ\xfd\xb8\xff\xff\xff\xff\xdd\xcdظ\xff\xff\xff\xffޢ\x1a8\xff\xff\xff\xff߶\xf58\xff\xff\xff\xff\xe0\x81\xfc8\xff" + - "\xff\xff\xff\xe1\x96\xc9(\xff\xff\xff\xff\xe2Oi8\xff\xff\xff\xff\xe3v\xab(\xff\xff\xff\xff\xe4/K8\xff\xff\xff\xff\xe5_Ǩ\xff\xff\xff\xff\xe6\x0f-8\xff\xff\xff\xff\xe7?\xa9\xa8\xff\xff\xff\xff\xe7" + - "\xf8I\xb8\xff\xff\xff\xff\xe9\x1f\x8b\xa8\xff\xff\xff\xff\xe9\xd8+\xb8\xff\xff\xff\xff\xea\xffm\xa8\xff\xff\xff\xff\xeb\xb8\r\xb8\xff\xff\xff\xff\xec\xdfO\xa8\xff\xff\xff\xff\xed\x97\xef\xb8\xff\xff\xff\xff\xee\xc8l(\xff" + - "\xff\xff\xff\xefwѸ\xff\xff\xff\xff\xf0\xa8N(\xff\xff\xff\xff\xf1W\xb3\xb8\xff\xff\xff\xff\xf2\x880(\xff\xff\xff\xff\xf3@\xd08\xff\xff\xff\xff\xf4h\x12(\xff\xff\xff\xff\xf5 \xb28\xff\xff\xff\xff\xf6" + - "G\xf4(\xff\xff\xff\xff\xf7%~8\xff\xff\xff\xff\xf8\x15a(\xff\xff\xff\xff\xf9\x05`8\xff\xff\xff\xff\xf9\xf5C(\xff\xff\xff\xff\xfa\xe5B8\xff\xff\xff\xff\xfb\xde_\xa8\xff\xff\xff\xff\xfc\xce^\xb8\xff" + - "\xff\xff\xff\xfd\xbeA\xa8\xff\xff\xff\xff\xfe\xae@\xb8\xff\xff\xff\xff\xff\x9e#\xa8\x00\x00\x00\x00\x00\x8e\"\xb8\x00\x00\x00\x00\x01~\x05\xa8\x00\x00\x00\x00\x02n\x04\xb8\x00\x00\x00\x00\x03]\xe7\xa8\x00\x00\x00\x00\x04" + - "M\xe6\xb8\x00\x00\x00\x00\x05G\x04(\x00\x00\x00\x00\x067\x038\x00\x00\x00\x00\a&\xe6(\x00\x00\x00\x00\a\x83=8\x00\x00\x00\x00\t\x06\xc8(\x00\x00\x00\x00\t\xf6\xc78\x00\x00\x00\x00\n\xe6\xaa(\x00" + - "\x00\x00\x00\v֩8\x00\x00\x00\x00\fƌ(\x00\x00\x00\x00\x11\x9b98\x00\x00\x00\x00\x12ol\xa8\x01\x02\x03\x04\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00k\n\x00\x00\x00\x00p\x80\x00\x04\x00\x00~\x90\x01\b\x00\x00" + - "w\x88\x01\r\x00\x00~\x90\x00\x12LMT\x00HKT\x00HKST\x00HKWT\x00JST\x00\nHKT-8\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R=\xf7\xfawp\x00\x00" + - "\x00p\x00\x00\x00\x03\x00\x1c\x00HSTUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "10.5.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSk\xa4,\xb6?\x06\x00\x00?\x06\x00\x00\x0f\x00\x1c\x00Europe/GuernseyUT\t\x00\x03\x82\x0f\x8b" + + "a\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" + + "\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9f\x00\x00\x00\x05\x00\x00\x00\x11\xff\xff\xff\xff\x1a" + + "]\t\xcb\xff\xff\xff\xff\x9b&\xad\xa0\xff\xff\xff\xff\x9b\xd6\x05 \xff\xff\xff\xff\x9c\xcf0\xa0\xff\xff\xff\xff\x9d\xa4à\xff\xff\xff\xff\x9e\x9c\x9d\xa0\xff\xff\xff\xff\x9f\x97\x1a\xa0\xff\xff\xff\xff\xa0\x85\xba \xff" + + "\xff\xff\xff\xa1v\xfc\xa0\xff\xff\xff\xff\xa2e\x9c \xff\xff\xff\xff\xa3{Ƞ\xff\xff\xff\xff\xa4N\xb8\xa0\xff\xff\xff\xff\xa5?\xfb \xff\xff\xff\xff\xa6%` \xff\xff\xff\xff\xa7'\xc6 \xff\xff\xff\xff\xa8" + + "*, \xff\xff\xff\xff\xa8\xeb\xf8\xa0\xff\xff\xff\xff\xaa\x00Ӡ\xff\xff\xff\xff\xaa\xd5\x15 \xff\xff\xff\xff\xab\xe9\xf0 \xff\xff\xff\xff\xac\xc7l \xff\xff\xff\xff\xad\xc9\xd2 \xff\xff\xff\xff\xae\xa7N \xff" + + "\xff\xff\xff\xaf\xa0y\xa0\xff\xff\xff\xff\xb0\x870 \xff\xff\xff\xff\xb1\x92Р\xff\xff\xff\xff\xb2pL\xa0\xff\xff\xff\xff\xb3r\xb2\xa0\xff\xff\xff\xff\xb4P.\xa0\xff\xff\xff\xff\xb5IZ \xff\xff\xff\xff\xb6" + + "0\x10\xa0\xff\xff\xff\xff\xb72v\xa0\xff\xff\xff\xff\xb8\x0f\xf2\xa0\xff\xff\xff\xff\xb9\x12X\xa0\xff\xff\xff\xff\xb9\xefԠ\xff\xff\xff\xff\xba\xe9\x00 \xff\xff\xff\xff\xbb\xd8\xf1 \xff\xff\xff\xff\xbc\xdbW \xff" + + "\xff\xff\xff\xbd\xb8\xd3 \xff\xff\xff\xff\xbe\xb1\xfe\xa0\xff\xff\xff\xff\xbf\x98\xb5 \xff\xff\xff\xff\xc0\x9b\x1b \xff\xff\xff\xff\xc1x\x97 \xff\xff\xff\xff\xc2z\xfd \xff\xff\xff\xff\xc3Xy \xff\xff\xff\xff\xc4" + + "Q\xa4\xa0\xff\xff\xff\xff\xc58[ \xff\xff\xff\xff\xc6:\xc1 \xff\xff\xff\xff\xc7X֠\xff\xff\xff\xff\xc7\xda\t\xa0\xff\xff\xff\xff\xca\x16&\x90\xff\xff\xff\xffʗY\x90\xff\xff\xff\xff\xcb\xd1\x1e\x90\xff" + + "\xff\xff\xff\xccw;\x90\xff\xff\xff\xffͱ\x00\x90\xff\xff\xff\xff\xce`X\x10\xff\xff\xff\xffϐ\xe2\x90\xff\xff\xff\xff\xd0n^\x90\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd1\xfb2\x10\xff\xff\xff\xff\xd2" + + "i\xfe \xff\xff\xff\xff\xd3c)\xa0\xff\xff\xff\xff\xd4I\xe0 \xff\xff\xff\xff\xd5\x1e!\xa0\xff\xff\xff\xff\xd5B\xfd\x90\xff\xff\xff\xff\xd5\xdf\xe0\x10\xff\xff\xff\xff\xd6N\xac \xff\xff\xff\xff\xd6\xfe\x03\xa0\xff" + + "\xff\xff\xff\xd8.\x8e \xff\xff\xff\xff\xd8\xf9\x95 \xff\xff\xff\xff\xda\x0ep \xff\xff\xff\xff\xda\xeb\xec \xff\xff\xff\xff\xdb\xe5\x17\xa0\xff\xff\xff\xff\xdc\xcb\xce \xff\xff\xff\xff\xdd\xc4\xf9\xa0\xff\xff\xff\xff\xde" + + "\xb4\xea\xa0\xff\xff\xff\xff߮\x16 \xff\xff\xff\xff\xe0\x94̠\xff\xff\xff\xff\xe1rH\xa0\xff\xff\xff\xff\xe2kt \xff\xff\xff\xff\xe3R*\xa0\xff\xff\xff\xff\xe4T\x90\xa0\xff\xff\xff\xff\xe52\f\xa0\xff" + + "\xff\xff\xff\xe6=\xad \xff\xff\xff\xff\xe7\x1b) \xff\xff\xff\xff\xe8\x14T\xa0\xff\xff\xff\xff\xe8\xfb\v \xff\xff\xff\xff\xe9\xfdq \xff\xff\xff\xff\xea\xda\xed \xff\xff\xff\xff\xeb\xddS \xff\xff\xff\xff\xec" + + "\xba\xcf \xff\xff\xff\xff\xed\xb3\xfa\xa0\xff\xff\xff\xff\ue6b1 \xff\xff\xff\xff\xef\x81g\xa0\xff\xff\xff\xff\xf0\x9f} \xff\xff\xff\xff\xf1aI\xa0\xff\xff\xff\xff\xf2\u007f_ \xff\xff\xff\xff\xf3Jf \xff" + + "\xff\xff\xff\xf4_A \xff\xff\xff\xff\xf5!\r\xa0\xff\xff\xff\xff\xf6?# \xff\xff\xff\xff\xf7\x00\xef\xa0\xff\xff\xff\xff\xf8\x1f\x05 \xff\xff\xff\xff\xf8\xe0Ѡ\xff\xff\xff\xff\xf9\xfe\xe7 \xff\xff\xff\xff\xfa" + + "\xc0\xb3\xa0\xff\xff\xff\xff\xfb\xe8\x03\xa0\xff\xff\xff\xff\xfc{\xab\xa0\xff\xff\xff\xff\xfdǻp\x00\x00\x00\x00\x03p\xc6 \x00\x00\x00\x00\x04)X \x00\x00\x00\x00\x05P\xa8 \x00\x00\x00\x00\x06\t: \x00" + + "\x00\x00\x00\a0\x8a \x00\x00\x00\x00\a\xe9\x1c \x00\x00\x00\x00\t\x10l \x00\x00\x00\x00\t\xc8\xfe \x00\x00\x00\x00\n\xf0N \x00\x00\x00\x00\v\xb2\x1a\xa0\x00\x00\x00\x00\f\xd00 \x00\x00\x00\x00\r" + + "\x91\xfc\xa0\x00\x00\x00\x00\x0e\xb0\x12 \x00\x00\x00\x00\x0fqޠ\x00\x00\x00\x00\x10\x99.\xa0\x00\x00\x00\x00\x11Q\xc0\xa0\x00\x00\x00\x00\x12y\x10\xa0\x00\x00\x00\x00\x131\xa2\xa0\x00\x00\x00\x00\x14X\xf2\xa0\x00" + + "\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x168Ɛ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x18\x18\xa8\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19\xf8\x8a\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b" + + "\xe1\xa7\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\xc1\x89\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f\xa1k\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\x81M\x10\x00\x00\x00\x00\"LT\x10\x00" + + "\x00\x00\x00#a/\x10\x00\x00\x00\x00$,6\x10\x00\x00\x00\x00%JK\x90\x00\x00\x00\x00&\f\x18\x10\x00\x00\x00\x00'*-\x90\x00\x00\x00\x00'\xf54\x90\x00\x00\x00\x00)\n\x0f\x90\x00\x00\x00\x00)" + + "\xd5\x16\x90\x00\x00\x00\x00*\xe9\xf1\x90\x00\x00\x00\x00+\xb4\xf8\x90\x00\x00\x00\x00,\xc9Ӑ\x00\x00\x00\x00-\x94ڐ\x00\x00\x00\x00.\xa9\xb5\x90\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000\x89\x97\x90\x00" + + "\x00\x00\x001]\xd9\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x03\x01\x03" + + "\x01\x03\x01\x03\x01\x03\x01\x02\x01\x02\x01\x03\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x04\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xff\xb5\x00\x00\x00\x00\x0e\x10\x01\x04\x00\x00" + + "\x00\x00\x00\b\x00\x00\x1c \x01\f\x00\x00\x0e\x10\x00\x04LMT\x00BST\x00GMT\x00BDST\x00\nGMT0BST,M3.5.0/1,M10.5.0\nP" + + "K\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x03R\xda\xedU\x02\x00\x00U\x02\x00\x00\x0e\x00\x1c\x00Europe/NicosiaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00" + + "\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00" + + "\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x001\x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff\xff\xa5w\x1e\xb8\x00\x00\x00\x00\t\xed" + + "\xaf\xe0\x00\x00\x00\x00\nݒ\xd0\x00\x00\x00\x00\v\xfad\xe0\x00\x00\x00\x00\f\xbe\xc6P\x00\x00\x00\x00\r\xa49`\x00\x00\x00\x00\x0e\x8a\xe1\xd0\x00\x00\x00\x00\x0f\x84\x1b`\x00\x00\x00\x00\x10uO\xd0\x00\x00" + + "\x00\x00\x11c\xfd`\x00\x00\x00\x00\x12S\xe0P\x00\x00\x00\x00\x13M\x19\xe0\x00\x00\x00\x00\x143\xc2P\x00\x00\x00\x00\x15#\xc1`\x00\x00\x00\x00\x16\x13\xa4P\x00\x00\x00\x00\x17\x03\xa3`\x00\x00\x00\x00\x17\xf3" + + "\x86P\x00\x00\x00\x00\x18\xe3\x85`\x00\x00\x00\x00\x19\xd3hP\x00\x00\x00\x00\x1a\xc3g`\x00\x00\x00\x00\x1b\xbc\x84\xd0\x00\x00\x00\x00\x1c\xac\x83\xe0\x00\x00\x00\x00\x1d\x9cf\xd0\x00\x00\x00\x00\x1e\x8ce\xe0\x00\x00" + + "\x00\x00\x1f|H\xd0\x00\x00\x00\x00 lG\xe0\x00\x00\x00\x00!\\*\xd0\x00\x00\x00\x00\"L)\xe0\x00\x00\x00\x00#<\f\xd0\x00\x00\x00\x00$,\v\xe0\x00\x00\x00\x00%\x1b\xee\xd0\x00\x00\x00\x00&\v" + + "\xed\xe0\x00\x00\x00\x00'\x05\vP\x00\x00\x00\x00'\xf5\n`\x00\x00\x00\x00(\xe4\xedP\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xc4\xcfP\x00\x00\x00\x00+\xb4\xce`\x00\x00\x00\x00,\xa4\xb1P\x00\x00" + + "\x00\x00-\x94\xb0`\x00\x00\x00\x00.\x84\x93P\x00\x00\x00\x00/t\x92`\x00\x00\x00\x000duP\x00\x00\x00\x001]\xae\xe0\x00\x00\x00\x002M\x91\xd0\x00\x00\x00\x003=\x90\xe0\x00\x00\x00\x004-" + + "s\xd0\x00\x00\x00\x005\x1dr\xe0\x00\x00\x00\x0062x\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x00\x00\x1fH\x00\x00\x00\x00*0\x01\x04\x00\x00\x1c \x00\tLMT\x00EEST\x00EET\x00\nEET-2EEST,M3.5.0/3,M1" + + "0.5.0/4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xc9\a\xa0\xe1/\x04\x00\x00/\x04\x00\x00\x10\x00\x1c\x00Europe/AmsterdamUT\t\x00\x03\x82" + + "\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00a\x00\x00\x00\a\x00\x00\x00!\xff\xff\xff" + + "\xff\x02\x12Ql\xff\xff\xff\xff\x9b\f.\xec\xff\xff\xff\xff\x9b\xd5\xd6\\\xff\xff\xff\xff\x9cٸ\f\xff\xff\xff\xff\x9d\xa4\xbf\f\xff\xff\xff\xff\x9e\xa7%\f\xff\xff\xff\xff\x9f\x97\x16\f\xff\xff\xff\xff\xa0\x90A" + + "\x8c\xff\xff\xff\xff\xa1v\xf8\f\xff\xff\xff\xff\xa2p#\x8c\xff\xff\xff\xff\xa3V\xda\f\xff\xff\xff\xff\xa4P\x05\x8c\xff\xff\xff\xff\xa56\xbc\f\xff\xff\xff\xff\xa6%[\x8c\xff\xff\xff\xff\xa7'\xc1\x8c\xff\xff\xff" + + "\xff\xa8^\xe3\x8c\xff\xff\xff\xff\xa9\a\xa3\x8c\xff\xff\xff\xff\xa9\xeeZ\f\xff\xff\xff\xff\xaa煌\xff\xff\xff\xff\xac'\xe2\f\xff\xff\xff\xff\xac\xc7g\x8c\xff\xff\xff\xff\xad\xedf\f\xff\xff\xff\xff\xae\xa7I" + + "\x8c\xff\xff\xff\xff\xafΙ\x8c\xff\xff\xff\xff\xb0\x87+\x8c\xff\xff\xff\xff\xb1\xb1\x1e\x8c\xff\xff\xff\xff\xb2pH\f\xff\xff\xff\xff\xb3\x92R\f\xff\xff\xff\xff\xb4P*\f\xff\xff\xff\xff\xb5s\x85\x8c\xff\xff\xff" + + "\xff\xb60\f\f\xff\xff\xff\xff\xb7T\xb9\f\xff\xff\xff\xff\xb8\x0f\xee\f\xff\xff\xff\xff\xb9@x\x8c\xff\xff\xff\xff\xb9\xef\xd0\f\xff\xff\xff\xff\xbb\x18q\x8c\xff\xff\xff\xff\xbb\xd8\xec\x8c\xff\xff\xff\xff\xbc\xf9\xa5" + + "\f\xff\xff\xff\xff\xbd\xb8Ό\xff\xff\xff\xff\xbe\xda،\xff\xff\xff\xff\xbf\x98\xb0\x8c\xff\xff\xff\xff\xc0\xbd]\x8c\xff\xff\xff\xff\xc1x\x92\x8c\xff\xff\xff\xff§ˌ\xff\xff\xff\xff\xc2\xdc]\\\xff\xff\xff" + + "\xff\xc3Xtp\xff\xff\xff\xff\xc4\u007f\xc4p\xff\xff\xff\xff\xc58Vp\xff\xff\xff\xff\xc6`\xf7\xf0\xff\xff\xff\xff\xc7!r\xf0\xff\xff\xff\xff\xc8D\xb2P\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17" + + "\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd2N@\x90\x00\x00\x00\x00\r\xa4c\x90\x00\x00\x00\x00\x0e\x8b\x1a\x10\x00\x00\x00" + + "\x00\x0f\x84E\x90\x00\x00\x00\x00\x10t6\x90\x00\x00\x00\x00\x11d'\x90\x00\x00\x00\x00\x12T\x18\x90\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13\xdc" + + "\x90\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00" + + "\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#\x86%p\x00\x00\x00\x00?\x9b\x00p\x00\x00\x00\x00@f\ap\x00\x00\x00\x00A\x84\x1c\xf0\x00\x00\x00\x00BE\xe9p\x00\x00\x00\x00Cc\xfe" + + "\xf0\x00\x00\x00\x00D%\xcbp\x00\x00\x00\x00EC\xe0\xf0\x00\x00\x00\x00F\x05\xadp\x00\x00\x00\x00G#\xc2\xf0\x00\x00\x00\x00G\xee\xc9\xf0\x00\x00\x00\x00I\x03\xa4\xf0\x00\x00\x00\x00IΫ\xf0\x00\x00\x00" + + "\x00J\xe3\x86\xf0\x00\x00\x00\x00K\xae\x8d\xf0\x00\x00\x00\x00Ḷp\x00\x00\x00\x00M\x8eo\xf0\x00\x00\x00\x00TL\x1d`\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x01\x04\x01\x03" + + "\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x03\x01\x00\x00.\x98\x00\x00\x00\x00*0\x00\x04\x00\x00FP\x01\b\x00\x00" + + "8@\x00\f\x00\x008@\x01\fLMT\x00+03\x00+05\x00+04\x00\n<+03>-3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xea\xc48\xde\\\x02\x00\x00\\\x02\x00" + + "\x00\r\x00\x1c\x00Europe/TiraneUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x002\x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff\xff\x96\xaa4h\xff\xff\xff\xff\xc8m\x87p\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u0378\xe9" + + "\x90\x00\x00\x00\x00\b(9\xf0\x00\x00\x00\x00\b\xef>`\x00\x00\x00\x00\n\x05x\xf0\x00\x00\x00\x00\n\xd0q\xe0\x00\x00\x00\x00\v\xe9Op\x00\x00\x00\x00\f\xb4H`\x00\x00\x00\x00\r\xd2k\xf0\x00\x00\x00" + + "\x00\x0e\x94*`\x00\x00\x00\x00\x0f\xb0\xfcp\x00\x00\x00\x00\x10t\f`\x00\x00\x00\x00\x11\x90\xdep\x00\x00\x00\x00\x12S\xee`\x00\x00\x00\x00\x13p\xc0p\x00\x00\x00\x00\x14;\xb9`\x00\x00\x00\x00\x15H\xb9" + + "p\x00\x00\x00\x00\x16\x13\xb2`\x00\x00\x00\x00\x171\xd5\xf0\x00\x00\x00\x00\x17\xfc\xce\xe0\x00\x00\x00\x00\x19\x00\x94p\x00\x00\x00\x00\x19\xdb_`\x00\x00\x00\x00\x1a̯\xf0\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00" + + "\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#\xc8\x00\x00\x00\x00y\xbdĸ\x00\x00\x00\x00z\xacrH\x00\x00\x00\x00{\x9e\xf88\x00\x00\x00\x00|\x8d\xa5\xc8\x00\x00\x00\x00}\x80+" + - "\xb8\x00\x00\x00\x00~n\xd9H\x00\x00\x00\x00\u007fa_8\x00\x00\x00\x00\x80Q^H\x00\x00\x00\x00\x81C\xe48\x00\x00\x00\x00\x822\x91\xc8\x00\x00\x00\x00\x83%\x17\xb8\x00\x00\x00\x00\x84\x13\xc5H\x00\x00\x00" + - "\x00\x85\x06K8\x00\x00\x00\x00\x85\xf4\xf8\xc8\x00\x00\x00\x00\x86\xe7~\xb8\x00\x00\x00\x00\x87\xd7}\xc8\x00\x00\x00\x00\x88\xca\x03\xb8\x00\x00\x00\x00\x89\xb8\xb1H\x00\x00\x00\x00\x8a\xab78\x00\x00\x00\x00\x8b\x99\xe4" + - "\xc8\x00\x00\x00\x00\x8c\x8cj\xb8\x00\x00\x00\x00\x8d{\x18H\x00\x00\x00\x00\x8em\x9e8\x00\x00\x00\x00\x8f]\x9dH\x00\x00\x00\x00\x90P#8\x00\x00\x00\x00\x91>\xd0\xc8\x00\x00\x00\x00\x921V\xb8\x00\x00\x00" + - "\x00\x93 \x04H\x00\x00\x00\x00\x94\x12\x8a8\x00\x00\x00\x00\x95\x017\xc8\x00\x00\x00\x00\x95\xf3\xbd\xb8\x00\x00\x00\x00\x96\xe3\xbc\xc8\x00\x00\x00\x00\x97\xd6B\xb8\x00\x00\x00\x00\x98\xc4\xf0H\x00\x00\x00\x00\x99\xb7v" + - "8\x00\x00\x00\x00\x9a\xa6#\xc8\x00\x00\x00\x00\x9b\x98\xa9\xb8\x00\x00\x00\x00\x9c\x87WH\x00\x00\x00\x00\x9dy\xdd8\x00\x00\x00\x00\x9ei\xdcH\x00\x00\x00\x00\x9f\\b8\x00\x00\x00\x00\xa0K\x0f\xc8\x00\x00\x00" + - "\x00\xa1=\x95\xb8\x00\x00\x00\x00\xa2,CH\x00\x00\x00\x00\xa3\x1e\xc98\x00\x00\x00\x00\xa4\rv\xc8\x00\x00\x00\x00\xa4\xff\xfc\xb8\x00\x00\x00\x00\xa5\xef\xfb\xc8\x00\x00\x00\x00\xa6⁸\x00\x00\x00\x00\xa7\xd1/" + - "H\x00\x00\x00\x00\xa8õ8\x00\x00\x00\x00\xa9\xb2b\xc8\x00\x00\x00\x00\xaa\xa4\xe8\xb8\x00\x00\x00\x00\xab\x93\x96H\x00\x00\x00\x00\xac\x86\x1c8\x00\x00\x00\x00\xadt\xc9\xc8\x00\x00\x00\x00\xaegO\xb8\x00\x00\x00" + - "\x00\xafWN\xc8\x00\x00\x00\x00\xb0IԸ\x00\x00\x00\x00\xb18\x82H\x00\x00\x00\x00\xb2+\b8\x00\x00\x00\x00\xb3\x19\xb5\xc8\x00\x00\x00\x00\xb4\f;\xb8\x00\x00\x00\x00\xb4\xfa\xe9H\x00\x00\x00\x00\xb5\xedo" + - "8\x00\x00\x00\x00\xb6\xddnH\x00\x00\x00\x00\xb7\xcf\xf48\x00\x00\x00\x00\xb8\xbe\xa1\xc8\x00\x00\x00\x00\xb9\xb1'\xb8\x00\x00\x00\x00\xba\x9f\xd5H\x00\x00\x00\x00\xbb\x92[8\x00\x00\x00\x00\xbc\x81\b\xc8\x00\x00\x00" + - "\x00\xbds\x8e\xb8\x00\x00\x00\x00\xbec\x8d\xc8\x00\x00\x00\x00\xbfV\x13\xb8\x00\x00\x00\x00\xc0D\xc1H\x00\x00\x00\x00\xc17G8\x00\x00\x00\x00\xc2%\xf4\xc8\x00\x00\x00\x00\xc3\x18z\xb8\x00\x00\x00\x00\xc4\a(" + - "H\x00\x00\x00\x00\xc4\xf9\xae8\x00\x00\x00\x00\xc5\xe9\xadH\x00\x00\x00\x00\xc6\xdc38\x00\x00\x00\x00\xc7\xca\xe0\xc8\x00\x00\x00\x00Ƚf\xb8\x00\x00\x00\x00ɬ\x14H\x00\x00\x00\x00ʞ\x9a8\x00\x00\x00" + - "\x00ˍG\xc8\x00\x00\x00\x00\xcc\u007f\u0378\x00\x00\x00\x00\xcdo\xcc\xc8\x00\x00\x00\x00\xcebR\xb8\x00\x00\x00\x00\xcfQ\x00H\x00\x00\x00\x00\xd0C\x868\x00\x00\x00\x00\xd123\xc8\x00\x00\x00\x00\xd2$\xb9" + - "\xb8\x00\x00\x00\x00\xd3\x13gH\x00\x00\x00\x00\xd4\x05\xed8\x00\x00\x00\x00\xd4\xf5\xecH\x00\x00\x00\x00\xd5\xe8r8\x00\x00\x00\x00\xd6\xd7\x1f\xc8\x00\x00\x00\x00\xd7ɥ\xb8\x00\x00\x00\x00ظSH\x00\x00\x00" + - "\x00٪\xd98\x00\x00\x00\x00ڙ\x86\xc8\x00\x00\x00\x00ی\f\xb8\x00\x00\x00\x00\xdc|\v\xc8\x00\x00\x00\x00\xddn\x91\xb8\x00\x00\x00\x00\xde]?H\x01\x02\x04\x03\x04\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05" + - "\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05" + - "\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05" + - "\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05" + - "\x02\x05\x02\x05\x02\x05\x00\x0008\x00\x00\x00\x0008\x00\x04\x00\x0018\x00\b\x00\x00FP\x01\x0e\x00\x008@\x00\x12\x00\x00?H\x01\x16LMT\x00TMT\x00+0330\x00+05\x00" + - "+04\x00+0430\x00\n<+0330>-3:30<+0430>,J79/24,J263/24\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R" + - "\x17✳2\x04\x00\x002\x04\x00\x00\x06\x00\x1c\x00IsraelUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif3\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xffV\xb6\xc2\xfa\xff\xff\xff\xff\x9e0E\x88\xff\xff\xff\xff\xc8Y\xcf\x00\xff\xff\xff\xff\xc8\xfa\xa6\x00\xff\xff\xff" + - "\xff\xc98\x9c\x80\xff\xff\xff\xff\xcc\xe5\xeb\x80\xff\xff\xff\xffͬ\xfe\x00\xff\xff\xff\xff\xce\xc7\x1f\x00\xff\xff\xff\xffϏ\x83\x00\xff\xff\xff\xffЩ\xa4\x00\xff\xff\xff\xffф}\x00\xff\xff\xff\xffҊ\xd7" + - "\x80\xff\xff\xff\xff\xd3e\xb0\x80\xff\xff\xff\xff\xd4l\v\x00\xff\xff\xff\xff\xd7Z0\x80\xff\xff\xff\xff\xd7\xdfX\x00\xff\xff\xff\xff\xd8/À\xff\xff\xff\xff\xd9\x1ec\x00\xff\xff\xff\xff\xda\x10\xf7\x00\xff\xff\xff" + - "\xff\xda\xeb\xd0\x00\xff\xff\xff\xff۴4\x00\xff\xff\xff\xffܹ=\x00\xff\xff\xff\xff\xdd\xe0\x8d\x00\xff\xff\xff\xff\u07b4\u0380\xff\xff\xff\xffߤ\xbf\x80\xff\xff\xff\xff\xe0\x8bv\x00\xff\xff\xff\xff\xe1V}" + - "\x00\xff\xff\xff\xff\xe2\xbef\x80\xff\xff\xff\xff\xe36_\x00\xff\xff\xff\xff\xe4\x9eH\x80\xff\xff\xff\xff\xe5\x16A\x00\xff\xff\xff\xff\xe6t\xf0\x00\xff\xff\xff\xff\xe7\x11Ҁ\xff\xff\xff\xff\xe8&\xad\x80\xff\xff\xff" + - "\xff\xe8\xe8z\x00\x00\x00\x00\x00\b|\x8b\xe0\x00\x00\x00\x00\b\xfd\xb0\xd0\x00\x00\x00\x00\t\xf6\xea`\x00\x00\x00\x00\n\xa63\xd0\x00\x00\x00\x00\x13\xe9\xfc`\x00\x00\x00\x00\x14![`\x00\x00\x00\x00\x1a\xfa\xc6" + - "`\x00\x00\x00\x00\x1b\x8en`\x00\x00\x00\x00\x1c\xbe\xf8\xe0\x00\x00\x00\x00\x1dw|\xd0\x00\x00\x00\x00\x1e\xcc\xff`\x00\x00\x00\x00\x1f`\x99P\x00\x00\x00\x00 \x82\xb1`\x00\x00\x00\x00!I\xb5\xd0\x00\x00\x00" + - "\x00\"^\x9e\xe0\x00\x00\x00\x00# ]P\x00\x00\x00\x00$Z0`\x00\x00\x00\x00%\x00?P\x00\x00\x00\x00&\v\xed\xe0\x00\x00\x00\x00&\xd6\xe6\xd0\x00\x00\x00\x00'\xeb\xcf\xe0\x00\x00\x00\x00(\xc0\x03" + - "P\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xa9\x1f\xd0\x00\x00\x00\x00+\xbbe\xe0\x00\x00\x00\x00,\x89\x01\xd0\x00\x00\x00\x00-\x9bG\xe0\x00\x00\x00\x00._\xa9P\x00\x00\x00\x00/{)\xe0\x00\x00\x00" + - "\x000H\xc5\xd0\x00\x00\x00\x001H\x96\xe0\x00\x00\x00\x002\x83\x82p\x00\x00\x00\x00?|\x9f\xe0\x00\x00\x00\x00@s6p\x00\x00\x00\x00AP\xa4`\x00\x00\x00\x00BL\x8f\x00\x00\x00\x00\x00CHOp\x00\x00\x00\x00D,q\x00\x00\x00\x00\x00E\x1e\xf6" + - "\xf0\x00\x00\x00\x00F\fS\x00\x00\x00\x00\x00F\xecc\xf0\x00\x00\x00\x00G\xec5\x00\x00\x00\x00\x00H\xe7\xf5p\x00\x00\x00\x00I\xcc\x17\x00\x00\x00\x00\x00J\xbe\x9c\xf0\x00\x00\x00\x00K\xab\xf9\x00\x00\x00\x00" + - "\x00L\x8c\t\xf0\x00\x00\x00\x00M\x95\x15\x80\x00\x00\x00\x00N\x87\x9bp\x00\x00\x00\x00Ot\xf7\x80\x00\x00\x00\x00P^B\xf0\x00\x00\x00\x00QTـ\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x00\x00!\x06\x00\x00\x00\x00 \xf8\x00\x04\x00\x00*0\x01\b\x00\x00\x1c \x00\f\x00\x008@\x01\x10LMT\x00J" + - "MT\x00IDT\x00IST\x00IDDT\x00\nIST-2IDT,M3.4.4/26,M10.5.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R%J" + - "\xd5\xebS\x01\x00\x00S\x01\x00\x00\a\x00\x1c\x00JamaicaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffi\x87#~\xff\xff\xff\xff\x93\x0f\xb4\xfe\x00\x00\x00\x00\a\x8d\x19p\x00\x00\x00\x00\t\x10\xa4`\x00\x00\x00\x00" + - "\t\xad\x94\xf0\x00\x00\x00\x00\n\xf0\x86`\x00\x00\x00\x00\v\xe0\x85p\x00\x00\x00\x00\f٢\xe0\x00\x00\x00\x00\r\xc0gp\x00\x00\x00\x00\x0e\xb9\x84\xe0\x00\x00\x00\x00\x0f\xa9\x83\xf0\x00\x00\x00\x00\x10\x99f\xe0" + - "\x00\x00\x00\x00\x11\x89e\xf0\x00\x00\x00\x00\x12yH\xe0\x00\x00\x00\x00\x13iG\xf0\x00\x00\x00\x00\x14Y*\xe0\x00\x00\x00\x00\x15I)\xf0\x00\x00\x00\x00\x169\f\xe0\x00\x00\x00\x00\x17)\v\xf0\x00\x00\x00\x00" + - "\x18\")`\x00\x00\x00\x00\x19\b\xed\xf0\x00\x00\x00\x00\x1a\x02\v`\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\xff\xff\xb8\x02\x00\x00\xff\xff\xb8\x02\x00\x04\xff\xff\xb9\xb0\x00\b" + - "\xff\xff\xc7\xc0\x01\fLMT\x00KMT\x00EST\x00EDT\x00\nEST5\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x02\xf4\xaeg\xd5\x00\x00\x00\xd5\x00\x00\x00\x05\x00\x1c\x00Ja" + - "panUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\t\x00\x00" + - "\x00\x03\x00\x00\x00\f\xff\xff\xff\xffe¤p\xff\xff\xff\xff\xd7>\x02p\xff\xff\xff\xff\xd7\xedY\xf0\xff\xff\xff\xff\xd8\xf8\xfap\xff\xff\xff\xff\xd9\xcd;\xf0\xff\xff\xff\xff\xdb\a\x00\xf0\xff\xff\xff\xffۭ" + - "\x1d\xf0\xff\xff\xff\xff\xdc\xe6\xe2\xf0\xff\xff\xff\xff\u074c\xff\xf0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\x83\x03\x00\x00\x00\x00\x8c\xa0\x01\x04\x00\x00~\x90\x00\bLMT\x00JDT\x00JST\x00\nJS" + - "T-9\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xf6\xe8]*\xdb\x00\x00\x00\xdb\x00\x00\x00\t\x00\x1c\x00KwajaleinUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00" + - "\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00" + - "\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff~6\x18 \xff\xff\xff\xff\xc1\xed" + - "5\xd0\xff\xff\xff\xff\xc9\xea\n`\xff\xff\xff\xff\xcfF\x81\xf0\xff\xff\xff\xff\xff\x86\x1bP\x00\x00\x00\x00,v\x0e@\x01\x02\x03\x01\x04\x05\x00\x00\x9c\xe0\x00\x00\x00\x00\x9a\xb0\x00\x04\x00\x00\x8c\xa0\x00\b\x00\x00" + - "~\x90\x00\f\xff\xffW@\x00\x10\x00\x00\xa8\xc0\x00\x14LMT\x00+11\x00+10\x00+09\x00-12\x00+12\x00\n<+12>-12\nPK\x03\x04\n\x00\x00\x00\x00\x00" + - "\xf1c9R_\u007f2[\xaf\x01\x00\x00\xaf\x01\x00\x00\x05\x00\x1c\x00LibyaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x04\x00\x00\x00\x11\xff\xff\xff\xff\xa1\xf2\xc1$\xff\xff\xff\xffݻ\xb1\x10\xff\xff\xff\xff\xde#\xad`\xff\xff\xff\xff\xe1x\xd2\x10" + - "\xff\xff\xff\xff\xe1\xe7e\xe0\xff\xff\xff\xff\xe5/?p\xff\xff\xff\xff\xe5\xa9\xcc\xe0\xff\xff\xff\xff\xebN\xc6\xf0\x00\x00\x00\x00\x16\x92B`\x00\x00\x00\x00\x17\b\xf7p\x00\x00\x00\x00\x17\xfa+\xe0\x00\x00\x00\x00" + - "\x18\xea*\xf0\x00\x00\x00\x00\x19\xdb_`\x00\x00\x00\x00\x1a̯\xf0\x00\x00\x00\x00\x1b\xbd\xe4`\x00\x00\x00\x00\x1c\xb4z\xf0\x00\x00\x00\x00\x1d\x9f\x17\xe0\x00\x00\x00\x00\x1e\x93\vp\x00\x00\x00\x00\x1f\x82\xee`" + - "\x00\x00\x00\x00 pJp\x00\x00\x00\x00!a~\xe0\x00\x00\x00\x00\"R\xcfp\x00\x00\x00\x00#D\x03\xe0\x00\x00\x00\x00$4\x02\xf0\x00\x00\x00\x00%%7`\x00\x00\x00\x00&@\xb7\xf0\x00\x00\x00\x00" + - "2N\xf1`\x00\x00\x00\x003D6p\x00\x00\x00\x0045j\xe0\x00\x00\x00\x00P\x9d\x99\x00\x00\x00\x00\x00QTـ\x00\x00\x00\x00Ri\xb4\x80\x02\x01\x02\x01\x02\x01\x02\x03\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x02\x01\x03\x02\x01\x03\x00\x00\f\\\x00\x00\x00\x00\x1c \x01\x04\x00\x00\x0e\x10\x00\t\x00\x00\x1c \x00\rLMT\x00CEST\x00CET\x00EET\x00\nEE" + - "T-2\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xfe\x9d\x1b\xc9m\x02\x00\x00m\x02\x00\x00\x03\x00\x1c\x00METUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00" + - "\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif" + - "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x005\x00\x00\x00\x02\x00\x00\x00\t\xff\xff\xff\xff\x9b\f\x17`\xff\xff\xff\xff\x9b\xd5\xda\xf0\xff\xff\xff\xff" + - "\x9cٮ\x90\xff\xff\xff\xff\x9d\xa4\xb5\x90\xff\xff\xff\xff\x9e\xb9\x90\x90\xff\xff\xff\xff\x9f\x84\x97\x90\xff\xff\xff\xff\xc8\tq\x90\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10" + - "\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd2N@\x90\x00\x00\x00\x00\r\xa4c\x90\x00\x00\x00\x00\x0e\x8b\x1a\x10\x00\x00\x00\x00\x0f\x84E\x90\x00\x00\x00\x00" + - "\x10t6\x90\x00\x00\x00\x00\x11d'\x90\x00\x00\x00\x00\x12T\x18\x90\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐" + + "\x00\x00\x00\x00\x00\x00&\x00\x00\x00\b\x00\x00\x00\"\xff\xff\xff\xffV\xb6\xc7d\xff\xff\xff\xff\xaa\x19\xa7d\xff\xff\xff\xff\xb5\xa4\x19`\xff\xff\xff\xff\xca\xcd.\xd0\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xff\xcd" + + "\xa9\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xff\xceͨp\x00\x00\x00\x00\x15'\xa7\xd0\x00\x00\x00\x00\x16\x18\xdc@\x00\x00\x00\x00\x17\b\xdbP\x00\x00\x00\x00\x17\xfa\x0f\xc0\x00\x00\x00\x00\x18\xea\x0e\xd0\x00" + + "\x00\x00\x00\x19\xdbC@\x00\x00\x00\x00\x1a̓\xd0\x00\x00\x00\x00\x1b\xbc\xa0\xf0\x00\x00\x00\x00\x1c\xac\x91\xf0\x00\x00\x00\x00\x1d\x9c\x82\xf0\x00\x00\x00\x00\x1e\x8cs\xf0\x00\x00\x00\x00\x1f|d\xf0\x00\x00\x00\x00 " + + "lU\xf0\x00\x00\x00\x00!\\F\xf0\x00\x00\x00\x00\"L7\xf0\x00\x00\x00\x00#<(\xf0\x00\x00\x00\x00$,\x19\xf0\x00\x00\x00\x00%\x1c\n\xf0\x00\x00\x00\x00&\v\xfb\xf0\x00\x00\x00\x00&\x8d \xe0\x00" + + "\x00\x00\x00(\xe5\x17\x80\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xc4\xcfP\x00\x00\x00\x00+\xb4\xce`\x00\x00\x00\x00,\xa4\xb1P\x00\x00\x00\x00-\x94\xb0`\x00\x00\x00\x00.\x84\x93P\x00\x00\x00\x00/" + + "t\xbc\x90\x00\x00\x00\x000d\xad\x90\x00\x00\x00\x001]\xd9\x10\x01\x02\x03\x05\x04\x05\x04\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\a\x02\a\x02\a\x02\a\x02\a\x02\a\x00\x00\x1c" + + "\x9c\x00\x00\x00\x00\x1c\x9c\x00\x04\x00\x00\x1c \x00\b\x00\x00*0\x00\f\x00\x00\x0e\x10\x00\x10\x00\x00\x1c \x01\x14\x00\x008@\x01\x19\x00\x00*0\x01\x1dLMT\x00KMT\x00EET\x00MSK" + + "\x00CET\x00CEST\x00MSD\x00EEST\x00\nEET-2EEST,M3.5.0/3,M10.5.0/4\nPK\x03\x04\n\x00\x00\x00\x00\x00#" + + "\x82iSI\xb8\xbc\xd3\xf3\x02\x00\x00\xf3\x02\x00\x00\x0f\x00\x1c\x00Europe/TiraspolUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_" + + "\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<\x00\x00\x00\t\x00\x00\x00&\xff\xff\xff\xffV\xb6\xc8\xf8\xff\xff\xff\xff\x9ek\x9f\f\xff\xff\xff\xff\xb7\xb0\xd2" + + "\b\xff\xff\xff\xff\xb9>\xf3`\xff\xff\xff\xff\xb9\xef\x9c`\xff\xff\xff\xff\xbaߍ`\xff\xff\xff\xff\xbb\xcf~`\xff\xff\xff\xff\xbcȩ\xe0\xff\xff\xff\xff\xbd\xb8\x9a\xe0\xff\xff\xff\xff\xbe\xa8\x8b\xe0\xff\xff\xff" + + "\xff\xbf\x98|\xe0\xff\xff\xff\xff\xc0\x88m\xe0\xff\xff\xff\xff\xc1x^\xe0\xff\xff\xff\xff\xc2hO\xe0\xff\xff\xff\xff\xc3X@\xe0\xff\xff\xff\xff\xc4H1\xe0\xff\xff\xff\xff\xc58\"\xe0\xff\xff\xff\xff\xc6(\x13" + + "\xe0\xff\xff\xff\xff\xc7\x18\x04\xe0\xff\xff\xff\xffȼ\x93`\xff\xff\xff\xff\xcaw}P\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff" + + "\xff\xd0N\x90`\x00\x00\x00\x00\x15'\xa7\xd0\x00\x00\x00\x00\x16\x18\xdc@\x00\x00\x00\x00\x17\b\xdbP\x00\x00\x00\x00\x17\xfa\x0f\xc0\x00\x00\x00\x00\x18\xea\x0e\xd0\x00\x00\x00\x00\x19\xdbC@\x00\x00\x00\x00\x1a̓" + + "\xd0\x00\x00\x00\x00\x1b\xbc\xa0\xf0\x00\x00\x00\x00\x1c\xac\x91\xf0\x00\x00\x00\x00\x1d\x9c\x82\xf0\x00\x00\x00\x00\x1e\x8cs\xf0\x00\x00\x00\x00\x1f|d\xf0\x00\x00\x00\x00 lU\xf0\x00\x00\x00\x00!\\F\xf0\x00\x00\x00" + + "\x00\"L7\xf0\x00\x00\x00\x00#<(\xf0\x00\x00\x00\x00$,\x19\xf0\x00\x00\x00\x00%\x1c\n\xf0\x00\x00\x00\x00&\v\xfb\xf0\x00\x00\x00\x00&CL\xe0\x00\x00\x00\x00'\x055\x80\x00\x00\x00\x00'\xf5&" + + "\x80\x00\x00\x00\x00(\xe5\x17\x80\x00\x00\x00\x00)\xd4\xec`\x00\x00\x00\x00*\xc4\xcfP\x00\x00\x00\x00+\xb4\xce`\x00\x00\x00\x00,\xa4\xb1P\x00\x00\x00\x00-\x94\xb0`\x00\x00\x00\x00.\x84\x93P\x00\x00\x00" + + "\x00/t\x92`\x00\x00\x00\x000duP\x00\x00\x00\x001]\xae\xe0\x00\x00\x00\x002r{\xd0\x00\x00\x00\x003=\xad\x00\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x06\x05\x06" + + "\x05\x06\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\b\a\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x00\x00\x1b\b\x00\x00\x00\x00\x1a\xf4\x00\x04\x00\x00\x18x\x00\b\x00\x00*0\x01" + + "\f\x00\x00\x1c \x00\x11\x00\x00\x0e\x10\x00\x15\x00\x00\x1c \x01\x19\x00\x008@\x01\x1e\x00\x00*0\x00\"LMT\x00CMT\x00BMT\x00EEST\x00EET\x00CET\x00CEST" + + "\x00MSD\x00MSK\x00\nEET-2EEST,M3.5.0,M10.5.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSh\xa5J[\xa0\x03\x00\x00\xa0" + + "\x03\x00\x00\f\x00\x1c\x00Europe/MaltaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00V\x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff\xffp\xbd\xd3d\xff\xff\xff\xff\x9b8\xf8p\xff\xff\xff\xff\x9b\xd5\xcc\xe0\xff\xff\xff\xff\x9c\xc5\xcb\xf0\xff\xff\xff\xff\x9d\xb7" + + "\x00`\xff\xff\xff\xff\x9e\x89\xfep\xff\xff\xff\xff\x9f\xa0\x1c\xe0\xff\xff\xff\xff\xa0`\xa5\xf0\xff\xff\xff\xff\xa1~\xad`\xff\xff\xff\xff\xa2\\7p\xff\xff\xff\xff\xa3L\x1a`\xff\xff\xff\xff\xc8l5\xf0\xff\xff" + + "\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϐ\xe2\x90\xff\xff\xff\xff\xd0n^\x90\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd2L\xd2\xf0\xff\xff\xff\xff\xd3>" + + "1\x90\xff\xff\xff\xff\xd4I\xd2\x10\xff\xff\xff\xff\xd5\x1d\xf7p\xff\xff\xff\xff\xd6)\x97\xf0\xff\xff\xff\xff\xd6뀐\xff\xff\xff\xff\xd8\t\x96\x10\xff\xff\xff\xff\xf93\xb5\xf0\xff\xff\xff\xff\xf9\xd9\xc4\xe0\xff\xff" + + "\xff\xff\xfb\x1c\xd2p\xff\xff\xff\xff\xfb\xb9\xb4\xf0\xff\xff\xff\xff\xfc\xfc\xb4p\xff\xff\xff\xff\xfd\x99\x96\xf0\xff\xff\xff\xff\xfe\xe5\xd0\xf0\xff\xff\xff\xff\xff\x82\xb3p\x00\x00\x00\x00\x00Ų\xf0\x00\x00\x00\x00\x01b" + + "\x95p\x00\x00\x00\x00\x02\x9cZp\x00\x00\x00\x00\x03Bwp\x00\x00\x00\x00\x04\x85v\xf0\x00\x00\x00\x00\x05+\x93\xf0\x00\x00\x00\x00\x06\x1a3p\x00\x00\x00\x00\a\n$p\x00\x00\x00\x00\b\x17\x16p\x00\x00" + + "\x00\x00\b\xda4p\x00\x00\x00\x00\t\xf7\x14\x90\x00\x00\x00\x00\n\xc2\r\x80\x00\x00\x00\x00\v\xd6\xf6\x90\x00\x00\x00\x00\f\xa1\xef\x80\x00\x00\x00\x00\r\xb6ؐ\x00\x00\x00\x00\x0e\x81р\x00\x00\x00\x00\x0f\x96" + + "\xba\x90\x00\x00\x00\x00\x10a\xb3\x80\x00\x00\x00\x00\x11v\x9c\x90\x00\x00\x00\x00\x12A\x95\x80\x00\x00\x00\x00\x13E[\x10\x00\x00\x00\x00\x14*\xb2\x00\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00" + + "\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c" + + "\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#(\xe8L\xff\xff\xff\xffp\xbc\x81p\xff\xff\xff\xff\x9b8\xf8p\xff\xff\xff\xff\x9b\xd5\xcc\xe0\xff\xff\xff\xff\x9c\xc5\xcb\xf0\xff\xff\xff\xff\x9d\xb7\x00`\xff\xff\xff\xff\x9e\x89\xfe" + + "p\xff\xff\xff\xff\x9f\xa0\x1c\xe0\xff\xff\xff\xff\xa0`\xa5\xf0\xff\xff\xff\xff\xa1~\xad`\xff\xff\xff\xff\xa2\\7p\xff\xff\xff\xff\xa3L\x1a`\xff\xff\xff\xff\xc8l5\xf0\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff" + + "\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xff\xd0n^\x90\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd2L\xd2\xf0\xff\xff\xff\xff\xd3>1\x90\xff\xff\xff\xff\xd4I\xd2" + + "\x10\xff\xff\xff\xff\xd5\x1d\xf7p\xff\xff\xff\xff\xd6)\x97\xf0\xff\xff\xff\xff\xd6뀐\xff\xff\xff\xff\xd8\t\x96\x10\xff\xff\xff\xff\xf93\xb5\xf0\xff\xff\xff\xff\xf9\xd9\xc4\xe0\xff\xff\xff\xff\xfb\x1c\xd2p\xff\xff\xff" + + "\xff\xfb\xb9\xb4\xf0\xff\xff\xff\xff\xfc\xfc\xb4p\xff\xff\xff\xff\xfd\x99\x96\xf0\xff\xff\xff\xff\xfe\xe5\xd0\xf0\xff\xff\xff\xff\xff\x82\xb3p\x00\x00\x00\x00\x00Ų\xf0\x00\x00\x00\x00\x01b\x95p\x00\x00\x00\x00\x02\x9cZ" + + "p\x00\x00\x00\x00\x03Bwp\x00\x00\x00\x00\x04\x85v\xf0\x00\x00\x00\x00\x05+\x93\xf0\x00\x00\x00\x00\x06n\x93p\x00\x00\x00\x00\a\vu\xf0\x00\x00\x00\x00\bE:\xf0\x00\x00\x00\x00\b\xebW\xf0\x00\x00\x00" + + "\x00\n.Wp\x00\x00\x00\x00\n\xcb9\xf0\x00\x00\x00\x00\f\x0e9p\x00\x00\x00\x00\f\xab\x1b\xf0\x00\x00\x00\x00\r\xe4\xe0\xf0\x00\x00\x00\x00\x0e\x8a\xfd\xf0\x00\x00\x00\x00\x0f\xcd\xfdp\x00\x00\x00\x00\x10t\x1a" + + "p\x00\x00\x00\x00\x11\xad\xdfp\x00\x00\x00\x00\x12S\xfcp\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00" + + "\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90" + + "\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#\x8f\xfa\xa0\x00\x00\x00\x00?\x9b\x8d\x10\x00\x00\x00\x00@oܠ\x00\x00\x00\x00A\x84\xa9\x90\x00\x00\x00\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b\x90\x00\x00\x00\x00D/\xa0\xa0\x00\x00\x00\x00EDm\x90" + - "\x00\x00\x00\x00F\x0f\x82\xa0\x00\x00\x00\x00G$O\x90\x00\x00\x00\x00G\xf8\x9f \x00\x00\x00\x00I\x041\x90\x00\x00\x00\x00I\u0601 \x00\x00\x00\x00J\xe4\x13\x90\x00\x00\x00\x00K\x9c\xb3\xa0\x01\x02\x01\x02" + - "\x03\x02\x04\x05\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\xff\xff\x92L\x00\x00\xff\xff\x9d\x90\x00\x04\xff\xff\x8f\x80\x00\b\xff\xff\x9d\x90\x01\f\xff\xff\x9d\x90\x01\x10" + - "\xff\xff\x9d\x90\x01\x14LMT\x00MST\x00PST\x00PDT\x00PWT\x00PPT\x00\nPST8PDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00" + - "\x00\x00\x00\x00\xf1c9R8\xcdZ\x05o\x01\x00\x00o\x01\x00\x00\x0e\x00\x1c\x00Mexico/BajaSurUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00" + - "\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZi" + - "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff\xa5\xb6\xe8p\xff\xff\xff\xff\xaf\xf2n\xe0\xff\xff\xff" + - "\xff\xb6fV`\xff\xff\xff\xff\xb7C\xd2`\xff\xff\xff\xff\xb8\f6`\xff\xff\xff\xff\xb8\xfd\x86\xf0\xff\xff\xff\xff\xcb\xeaq`\xff\xff\xff\xffؑ\xb4\xf0\x00\x00\x00\x00\x00\x00p\x80\x00\x00\x00\x001g\x84" + - "\x10\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003Gf\x10\x00\x00\x00\x004R\xf8\x80\x00\x00\x00\x005'H\x10\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00" + - "\x008\xe7\f\x10\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xf5\x12\x90\x00\x00\x00\x00;\xb6\xd1\x00\x00\x00\x00\x00<\xb0\n\x90\x01\x02\x01\x02\x01\x02\x01\x03\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\x01\x04\xff" + - "\xff\x9c<\x00\x00\xff\xff\x9d\x90\x00\x04\xff\xff\xab\xa0\x00\b\xff\xff\x8f\x80\x00\f\xff\xff\xab\xa0\x01\x10LMT\x00MST\x00CST\x00PST\x00MDT\x00\nMST7MDT,M4" + - ".1.0,M10.5.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xf5\x8d\x99\x92o\x00\x00\x00o\x00\x00\x00\x03\x00\x1c\x00MSTUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`u" + - "x\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00" + - "\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xff\x9d\x90\x00\x00MST\x00\n" + - "MST7\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xe6h\xcac\xb7\x03\x00\x00\xb7\x03\x00\x00\a\x00\x1c\x00MST7MDTUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01" + - "\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00" + - "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00X\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff\x9e\xa6:\x90\xff\xff\xff\xff\x9f\xbb\a" + - "\x80\xff\xff\xff\xff\xa0\x86\x1c\x90\xff\xff\xff\xff\xa1\x9a\xe9\x80\xff\xff\xff\xffˉ\f\x90\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff\xfa\xf8u\x10\xff\xff\xff\xff\xfb\xe8X\x00\xff\xff\xff" + - "\xff\xfc\xd8W\x10\xff\xff\xff\xff\xfd\xc8:\x00\xff\xff\xff\xff\xfe\xb89\x10\xff\xff\xff\xff\xff\xa8\x1c\x00\x00\x00\x00\x00\x00\x98\x1b\x10\x00\x00\x00\x00\x01\x87\xfe\x00\x00\x00\x00\x00\x02w\xfd\x10\x00\x00\x00\x00\x03q\x1a" + - "\x80\x00\x00\x00\x00\x04a\x19\x90\x00\x00\x00\x00\x05P\xfc\x80\x00\x00\x00\x00\x06@\xfb\x90\x00\x00\x00\x00\a0ހ\x00\x00\x00\x00\a\x8d5\x90\x00\x00\x00\x00\t\x10\xc0\x80\x00\x00\x00\x00\t\xad\xb1\x10\x00\x00\x00" + - "\x00\n\xf0\xa2\x80\x00\x00\x00\x00\vࡐ\x00\x00\x00\x00\fٿ\x00\x00\x00\x00\x00\r\xc0\x83\x90\x00\x00\x00\x00\x0e\xb9\xa1\x00\x00\x00\x00\x00\x0f\xa9\xa0\x10\x00\x00\x00\x00\x10\x99\x83\x00\x00\x00\x00\x00\x11\x89\x82" + - "\x10\x00\x00\x00\x00\x12ye\x00\x00\x00\x00\x00\x13id\x10\x00\x00\x00\x00\x14YG\x00\x00\x00\x00\x00\x15IF\x10\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17)(\x10\x00\x00\x00\x00\x18\"E\x80\x00\x00\x00" + - "\x00\x19\t\n\x10\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2&\x90\x00\x00\x00\x00\x1b\xe2\t\x80\x00\x00\x00\x00\x1c\xd2\b\x90\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1\xea\x90\x00\x00\x00\x00\x1f\xa1\xcd" + - "\x80\x00\x00\x00\x00 v\x1d\x10\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xff\x10\x00\x00\x00\x00#j\xcc\x00\x00\x00\x00\x00$5\xe1\x10\x00\x00\x00\x00%J\xae\x00\x00\x00\x00\x00&\x15\xc3\x10\x00\x00\x00" + - "\x00'*\x90\x00\x00\x00\x00\x00'\xfeߐ\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\xde\xc1\x90\x00\x00\x00\x00*\xeaT\x00\x00\x00\x00\x00+\xbe\xa3\x90\x00\x00\x00\x00,\xd3p\x80\x00\x00\x00\x00-\x9e\x85" + - "\x90\x00\x00\x00\x00.\xb3R\x80\x00\x00\x00\x00/~g\x90\x00\x00\x00\x000\x934\x80\x00\x00\x00\x001g\x84\x10\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003Gf\x10\x00\x00\x00\x004R\xf8\x80\x00\x00\x00" + - "\x005'H\x10\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe7\f\x10\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xc6\xee\x10\x00\x00\x00\x00;ۻ" + - "\x00\x00\x00\x00\x00<\xb0\n\x90\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8f\xec\x90\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@oΐ\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00BO\xb0\x90\x00\x00\x00" + - "\x00Cd}\x80\x00\x00\x00\x00D/\x92\x90\x00\x00\x00\x00ED_\x80\x00\x00\x00\x00E\xf3\xc5\x10\x01\x00\x01\x00\x02\x03\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00" + - "\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\xff\xff\x9d" + - "\x90\x00\x04\xff\xff\xab\xa0\x01\x00\xff\xff\xab\xa0\x01\b\xff\xff\xab\xa0\x01\fMDT\x00MST\x00MWT\x00MPT\x00\nMST7MDT,M3.2.0,M11.1.0" + - "\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RV\x80\x94@\x12\x04\x00\x00\x12\x04\x00\x00\x06\x00\x1c\x00NavajoUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00" + - "\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif" + - "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00a\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff^\x04\f\xb0\xff\xff\xff\xff\x9e\xa6:\x90\xff\xff\xff\xff" + - "\x9f\xbb\a\x80\xff\xff\xff\xff\xa0\x86\x1c\x90\xff\xff\xff\xff\xa1\x9a\xe9\x80\xff\xff\xff\xff\xa2e\xfe\x90\xff\xff\xff\xff\xa3\x84\x06\x00\xff\xff\xff\xff\xa4E\xe0\x90\xff\xff\xff\xff\xa4\x8f\xa6\x80\xff\xff\xff\xffˉ\f\x90" + - "\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff\xf7/v\x90\xff\xff\xff\xff\xf8(\x94\x00\xff\xff\xff\xff\xf9\x0fX\x90\xff\xff\xff\xff\xfa\bv\x00\xff\xff\xff\xff\xfa\xf8u\x10\xff\xff\xff\xff" + - "\xfb\xe8X\x00\xff\xff\xff\xff\xfc\xd8W\x10\xff\xff\xff\xff\xfd\xc8:\x00\xff\xff\xff\xff\xfe\xb89\x10\xff\xff\xff\xff\xff\xa8\x1c\x00\x00\x00\x00\x00\x00\x98\x1b\x10\x00\x00\x00\x00\x01\x87\xfe\x00\x00\x00\x00\x00\x02w\xfd\x10" + - "\x00\x00\x00\x00\x03q\x1a\x80\x00\x00\x00\x00\x04a\x19\x90\x00\x00\x00\x00\x05P\xfc\x80\x00\x00\x00\x00\x06@\xfb\x90\x00\x00\x00\x00\a0ހ\x00\x00\x00\x00\a\x8d5\x90\x00\x00\x00\x00\t\x10\xc0\x80\x00\x00\x00\x00" + - "\t\xad\xb1\x10\x00\x00\x00\x00\n\xf0\xa2\x80\x00\x00\x00\x00\vࡐ\x00\x00\x00\x00\fٿ\x00\x00\x00\x00\x00\r\xc0\x83\x90\x00\x00\x00\x00\x0e\xb9\xa1\x00\x00\x00\x00\x00\x0f\xa9\xa0\x10\x00\x00\x00\x00\x10\x99\x83\x00" + - "\x00\x00\x00\x00\x11\x89\x82\x10\x00\x00\x00\x00\x12ye\x00\x00\x00\x00\x00\x13id\x10\x00\x00\x00\x00\x14YG\x00\x00\x00\x00\x00\x15IF\x10\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17)(\x10\x00\x00\x00\x00" + - "\x18\"E\x80\x00\x00\x00\x00\x19\t\n\x10\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2&\x90\x00\x00\x00\x00\x1b\xe2\t\x80\x00\x00\x00\x00\x1c\xd2\b\x90\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1\xea\x90" + - "\x00\x00\x00\x00\x1f\xa1̀\x00\x00\x00\x00 v\x1d\x10\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xff\x10\x00\x00\x00\x00#j\xcc\x00\x00\x00\x00\x00$5\xe1\x10\x00\x00\x00\x00%J\xae\x00\x00\x00\x00\x00" + - "&\x15\xc3\x10\x00\x00\x00\x00'*\x90\x00\x00\x00\x00\x00'\xfeߐ\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\xde\xc1\x90\x00\x00\x00\x00*\xeaT\x00\x00\x00\x00\x00+\xbe\xa3\x90\x00\x00\x00\x00,\xd3p\x80" + - "\x00\x00\x00\x00-\x9e\x85\x90\x00\x00\x00\x00.\xb3R\x80\x00\x00\x00\x00/~g\x90\x00\x00\x00\x000\x934\x80\x00\x00\x00\x001g\x84\x10\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003Gf\x10\x00\x00\x00\x00" + - "4R\xf8\x80\x00\x00\x00\x005'H\x10\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe7\f\x10\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xc6\xee\x10" + - "\x00\x00\x00\x00;ۻ\x00\x00\x00\x00\x00<\xb0\n\x90\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8f\xec\x90\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@oΐ\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00" + - "BO\xb0\x90\x00\x00\x00\x00Cd}\x80\x00\x00\x00\x00D/\x92\x90\x00\x00\x00\x00ED_\x80\x00\x00\x00\x00E\xf3\xc5\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\x9d\x94\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\f\xff\xff\xab\xa0\x01\x10LMT\x00MDT\x00MST\x00MWT\x00M" + - "PT\x00\nMST7MDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rb\xb2\xaf\xf7\x13\x04\x00\x00\x13\x04\x00\x00\x02\x00\x1c\x00NZU" + - "T\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x00\x00\x00\x06\x00\x00" + - "\x00\x13\xff\xff\xff\xffA\xb7L\xa8\xff\xff\xff\xff\xb0\xb4\xb2\xe8\xff\xff\xff\xff\xb1Q\x87X\xff\xff\xff\xff\xb2x\xe5h\xff\xff\xff\xff\xb3C\xe5`\xff\xff\xff\xff\xb4X\xc7h\xff\xff\xff\xff\xb5#\xc7`\xff\xff" + - "\xff\xff\xb68\xa9h\xff\xff\xff\xff\xb7\x03\xa9`\xff\xff\xff\xff\xb8\x18\x8bh\xff\xff\xff\xff\xb8\xec\xc5\xe0\xff\xff\xff\xff\xb9\xf8mh\xff\xff\xff\xff\xba̧\xe0\xff\xff\xff\xff\xbb\xd8Oh\xff\xff\xff\xff\xbc\xe3" + - "\xe8\xe0\xff\xff\xff\xff\xbd\xae\xf6\xe8\xff\xff\xff\xff\xbe\xc3\xca\xe0\xff\xff\xff\xff\xbf\x8e\xd8\xe8\xff\xff\xff\xff\xc0\xa3\xac\xe0\xff\xff\xff\xff\xc1n\xba\xe8\xff\xff\xff\xff\u0083\x8e\xe0\xff\xff\xff\xff\xc3N\x9c\xe8\xff\xff" + - "\xff\xff\xc4cp\xe0\xff\xff\xff\xff\xc5.~\xe8\xff\xff\xff\xff\xc6L\x8d`\xff\xff\xff\xff\xc7\x0e`\xe8\xff\xff\xff\xff\xc8,o`\xff\xff\xff\xff\xc8\xf7}h\xff\xff\xff\xff\xd2ښ@\x00\x00\x00\x00\t\x18" + - "\xfd\xe0\x00\x00\x00\x00\t\xac\xa5\xe0\x00\x00\x00\x00\n\xef\xa5`\x00\x00\x00\x00\v\x9e\xfc\xe0\x00\x00\x00\x00\f\xd8\xc1\xe0\x00\x00\x00\x00\r~\xde\xe0\x00\x00\x00\x00\x0e\xb8\xa3\xe0\x00\x00\x00\x00\x0f^\xc0\xe0\x00\x00" + - "\x00\x00\x10\x98\x85\xe0\x00\x00\x00\x00\x11>\xa2\xe0\x00\x00\x00\x00\x12xg\xe0\x00\x00\x00\x00\x13\x1e\x84\xe0\x00\x00\x00\x00\x14XI\xe0\x00\x00\x00\x00\x14\xfef\xe0\x00\x00\x00\x00\x168+\xe0\x00\x00\x00\x00\x16\xe7" + - "\x83`\x00\x00\x00\x00\x18!H`\x00\x00\x00\x00\x18\xc7e`\x00\x00\x00\x00\x1a\x01*`\x00\x00\x00\x00\x1a\xa7G`\x00\x00\x00\x00\x1b\xe1\f`\x00\x00\x00\x00\x1c\x87)`\x00\x00\x00\x00\x1d\xc0\xee`\x00\x00" + - "\x00\x00\x1eg\v`\x00\x00\x00\x00\x1f\xa0\xd0`\x00\x00\x00\x00 F\xed`\x00\x00\x00\x00!\x80\xb2`\x00\x00\x00\x00\"0\t\xe0\x00\x00\x00\x00#i\xce\xe0\x00\x00\x00\x00$\x0f\xeb\xe0\x00\x00\x00\x00%." + - "\x01`\x00\x00\x00\x00&\x02B\xe0\x00\x00\x00\x00'\r\xe3`\x00\x00\x00\x00'\xe2$\xe0\x00\x00\x00\x00(\xed\xc5`\x00\x00\x00\x00)\xc2\x06\xe0\x00\x00\x00\x00*ͧ`\x00\x00\x00\x00+\xab#`\x00\x00" + - "\x00\x00,\xad\x89`\x00\x00\x00\x00-\x8b\x05`\x00\x00\x00\x00.\x8dk`\x00\x00\x00\x00/j\xe7`\x00\x00\x00\x000mM`\x00\x00\x00\x001J\xc9`\x00\x00\x00\x002Vi\xe0\x00\x00\x00\x003*" + - "\xab`\x00\x00\x00\x0046K\xe0\x00\x00\x00\x005\n\x8d`\x00\x00\x00\x006\x16-\xe0\x00\x00\x00\x006\xf3\xa9\xe0\x00\x00\x00\x007\xf6\x0f\xe0\x00\x00\x00\x008Ӌ\xe0\x00\x00\x00\x009\xd5\xf1\xe0\x00\x00" + - "\x00\x00:\xb3m\xe0\x00\x00\x00\x00;\xbf\x0e`\x00\x00\x00\x00<\x93O\xe0\x00\x00\x00\x00=\x9e\xf0`\x00\x00\x00\x00>s1\xe0\x00\x00\x00\x00?~\xd2`\x00\x00\x00\x00@\\N`\x00\x00\x00\x00A^" + - "\xb4`\x00\x00\x00\x00B<0`\x00\x00\x00\x00C>\x96`\x00\x00\x00\x00D\x1c\x12`\x00\x00\x00\x00E\x1ex`\x00\x00\x00\x00E\xfb\xf4`\x00\x00\x00\x00F\xfeZ`\x02\x01\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04" + - "\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x00\x00\xa3\xd8\x00\x00\x00\x00\xaf\xc8\x01\x04\x00\x00\xa1\xb8\x00\t\x00\x00\xa8\xc0\x01\x04\x00\x00\xb6\xd0\x01\x0e\x00\x00\xa8\xc0" + - "\x00\x04LMT\x00NZST\x00NZMT\x00NZDT\x00\nNZST-12NZDT,M9.5.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00" + - "\xf1c9R\x96\xc5FF(\x03\x00\x00(\x03\x00\x00\a\x00\x1c\x00NZ-CHATUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00E\x00\x00\x00\x04\x00\x00\x00\x16\xff\xff\xff\xffA\xb7D\x84\xff\xff\xff\xff\xd2ږ\xbc\x00\x00\x00\x00\t\x18\xfd\xe0\x00\x00\x00\x00\t\xac" + - "\xa5\xe0\x00\x00\x00\x00\n\xef\xa5`\x00\x00\x00\x00\v\x9e\xfc\xe0\x00\x00\x00\x00\f\xd8\xc1\xe0\x00\x00\x00\x00\r~\xde\xe0\x00\x00\x00\x00\x0e\xb8\xa3\xe0\x00\x00\x00\x00\x0f^\xc0\xe0\x00\x00\x00\x00\x10\x98\x85\xe0\x00\x00" + - "\x00\x00\x11>\xa2\xe0\x00\x00\x00\x00\x12xg\xe0\x00\x00\x00\x00\x13\x1e\x84\xe0\x00\x00\x00\x00\x14XI\xe0\x00\x00\x00\x00\x14\xfef\xe0\x00\x00\x00\x00\x168+\xe0\x00\x00\x00\x00\x16\xe7\x83`\x00\x00\x00\x00\x18!" + - "H`\x00\x00\x00\x00\x18\xc7e`\x00\x00\x00\x00\x1a\x01*`\x00\x00\x00\x00\x1a\xa7G`\x00\x00\x00\x00\x1b\xe1\f`\x00\x00\x00\x00\x1c\x87)`\x00\x00\x00\x00\x1d\xc0\xee`\x00\x00\x00\x00\x1eg\v`\x00\x00" + - "\x00\x00\x1f\xa0\xd0`\x00\x00\x00\x00 F\xed`\x00\x00\x00\x00!\x80\xb2`\x00\x00\x00\x00\"0\t\xe0\x00\x00\x00\x00#i\xce\xe0\x00\x00\x00\x00$\x0f\xeb\xe0\x00\x00\x00\x00%.\x01`\x00\x00\x00\x00&\x02" + - "B\xe0\x00\x00\x00\x00'\r\xe3`\x00\x00\x00\x00'\xe2$\xe0\x00\x00\x00\x00(\xed\xc5`\x00\x00\x00\x00)\xc2\x06\xe0\x00\x00\x00\x00*ͧ`\x00\x00\x00\x00+\xab#`\x00\x00\x00\x00,\xad\x89`\x00\x00" + - "\x00\x00-\x8b\x05`\x00\x00\x00\x00.\x8dk`\x00\x00\x00\x00/j\xe7`\x00\x00\x00\x000mM`\x00\x00\x00\x001J\xc9`\x00\x00\x00\x002Vi\xe0\x00\x00\x00\x003*\xab`\x00\x00\x00\x0046" + - "K\xe0\x00\x00\x00\x005\n\x8d`\x00\x00\x00\x006\x16-\xe0\x00\x00\x00\x006\xf3\xa9\xe0\x00\x00\x00\x007\xf6\x0f\xe0\x00\x00\x00\x008Ӌ\xe0\x00\x00\x00\x009\xd5\xf1\xe0\x00\x00\x00\x00:\xb3m\xe0\x00\x00" + - "\x00\x00;\xbf\x0e`\x00\x00\x00\x00<\x93O\xe0\x00\x00\x00\x00=\x9e\xf0`\x00\x00\x00\x00>s1\xe0\x00\x00\x00\x00?~\xd2`\x00\x00\x00\x00@\\N`\x00\x00\x00\x00A^\xb4`\x00\x00\x00\x00B<" + - "0`\x00\x00\x00\x00C>\x96`\x00\x00\x00\x00D\x1c\x12`\x00\x00\x00\x00E\x1ex`\x00\x00\x00\x00E\xfb\xf4`\x00\x00\x00\x00F\xfeZ`\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x00\x00\xab\xfc\x00\x00\x00\x00\xac" + - "D\x00\x04\x00\x00\xc1\\\x01\n\x00\x00\xb3L\x00\x10LMT\x00+1215\x00+1345\x00+1245\x00\n<+1245>-12:45<+1345>,M" + - "9.5.0/2:45,M4.1.0/3:45\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\x00\x1c\x00Pacific" + - "/UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xee\xd0\x1cYN\x04\x00\x00N\x04\x00\x00\x0e\x00\x1c\x00P" + - "acific/EasterUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00f\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffi\x87B\b\xff\xff\xff\xff\xb9\xc7@\x88\xff\xff\xff\xff\xfd\xd1<@\xff\xff\xff\xff\xfe\x92\xfa\xb0\xff\xff\xff\xff\xff\xcc\xcd\xc0\x00\x00\x00\x00" + - "\x00rܰ\x00\x00\x00\x00\x01uP\xc0\x00\x00\x00\x00\x02@I\xb0\x00\x00\x00\x00\x03U2\xc0\x00\x00\x00\x00\x04 +\xb0\x00\x00\x00\x00\x05>O@\x00\x00\x00\x00\x06\x00\r\xb0\x00\x00\x00\x00\a\v\xbc@" + - "\x00\x00\x00\x00\a\xdf\xef\xb0\x00\x00\x00\x00\b\xfe\x13@\x00\x00\x00\x00\t\xbfѰ\x00\x00\x00\x00\n\xdd\xf5@\x00\x00\x00\x00\v\xa8\xee0\x00\x00\x00\x00\f\xbd\xd7@\x00\x00\x00\x00\r\x88\xd00\x00\x00\x00\x00" + - "\x0e\x9d\xb9@\x00\x00\x00\x00\x0fh\xb20\x00\x00\x00\x00\x10\x86\xd5\xc0\x00\x00\x00\x00\x11H\x940\x00\x00\x00\x00\x12f\xb7\xc0\x00\x00\x00\x00\x13(v0\x00\x00\x00\x00\x14F\x99\xc0\x00\x00\x00\x00\x15\x11\x92\xb0" + - "\x00\x00\x00\x00\x16&{\xc0\x00\x00\x00\x00\x16\xf1t\xb0\x00\x00\x00\x00\x18\x06]\xc0\x00\x00\x00\x00\x18\xd1V\xb0\x00\x00\x00\x00\x19\xe6?\xc0\x00\x00\x00\x00\x1a\xb18\xb0\x00\x00\x00\x00\x1b\xcf\\@\x00\x00\x00\x00" + - "\x1c\x91\x1a\xb0\x00\x00\x00\x00\x1d\xaf>@\x00\x00\x00\x00\x1ep\xfc\xb0\x00\x00\x00\x00\x1f\x8f @\x00\x00\x00\x00 \u007f\x030\x00\x00\x00\x00!o\x02@\x00\x00\x00\x00\"9\xfb0\x00\x00\x00\x00#N\xe4@" + - "\x00\x00\x00\x00$\x19\xdd0\x00\x00\x00\x00%8\x00\xc0\x00\x00\x00\x00%\xf9\xbf0\x00\x00\x00\x00&\xf2\xf8\xc0\x00\x00\x00\x00'١0\x00\x00\x00\x00(\xf7\xc4\xc0\x00\x00\x00\x00)½\xb0\x00\x00\x00\x00" + - "*צ\xc0\x00\x00\x00\x00+\xa2\x9f\xb0\x00\x00\x00\x00,\xb7\x88\xc0\x00\x00\x00\x00-\x82\x81\xb0\x00\x00\x00\x00.\x97j\xc0\x00\x00\x00\x00/bc\xb0\x00\x00\x00\x000\x80\x87@\x00\x00\x00\x001BE\xb0" + - "\x00\x00\x00\x002`i@\x00\x00\x00\x003=\xd70\x00\x00\x00\x004@K@\x00\x00\x00\x005\vD0\x00\x00\x00\x006\r\xb8@\x00\x00\x00\x007\x06հ\x00\x00\x00\x008\x00\x0f@\x00\x00\x00\x00" + - "8\xcb\b0\x00\x00\x00\x009\xe9+\xc0\x00\x00\x00\x00:\xaa\xea0\x00\x00\x00\x00;\xc9\r\xc0\x00\x00\x00\x00<\x8a\xcc0\x00\x00\x00\x00=\xa8\xef\xc0\x00\x00\x00\x00>j\xae0\x00\x00\x00\x00?\x88\xd1\xc0" + - "\x00\x00\x00\x00@Sʰ\x00\x00\x00\x00Ah\xb3\xc0\x00\x00\x00\x00B3\xac\xb0\x00\x00\x00\x00CH\x95\xc0\x00\x00\x00\x00D\x13\x8e\xb0\x00\x00\x00\x00E1\xb2@\x00\x00\x00\x00E\xf3p\xb0\x00\x00\x00\x00" + - "G\x11\x94@\x00\x00\x00\x00G\xef\x020\x00\x00\x00\x00H\xf1v@\x00\x00\x00\x00I\xbco0\x00\x00\x00\x00J\xd1X@\x00\x00\x00\x00K\xb8\x00\xb0\x00\x00\x00\x00L\xb1:@\x00\x00\x00\x00M\xc6\a0" + - "\x00\x00\x00\x00NP\x82\xc0\x00\x00\x00\x00O\x9c\xae\xb0\x00\x00\x00\x00PB\xd9\xc0\x00\x00\x00\x00Q|\x90\xb0\x00\x00\x00\x00R+\xf6@\x00\x00\x00\x00S\\r\xb0\x00\x00\x00\x00T\v\xd8@\x00\x00\x00\x00" + - "W7\xe60\x00\x00\x00\x00W\xaf\xec\xc0\x00\x00\x00\x00Y\x17\xc80\x00\x00\x00\x00Y\x8f\xce\xc0\x00\x00\x00\x00Z\xf7\xaa0\x00\x00\x00\x00[o\xb0\xc0\x00\x00\x00\x00\\\xa9g\xb0\x01\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04" + - "\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\xff\xff\x99x\x00\x00\xff\xff\x99x\x00\x04\xff\xff\xab\xa0\x01\b\xff\xff\x9d\x90\x00\f\xff\xff" + - "\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\x10LMT\x00EMT\x00-06\x00-07\x00-05\x00\n<-06>6<-05>,M9.1.6/22,M4.1.6/" + - "22\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xfa\x0fA\x05\x99\x00\x00\x00\x99\x00\x00\x00\x10\x00\x1c\x00Pacific/PitcairnUT\t\x00\x03\x15\xac\x0e`\x15\xac" + - "\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" + - "\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xff~7.\xf4" + - "\x00\x00\x00\x005DB\b\x01\x02\xff\xff\x86\f\x00\x00\xff\xff\x88x\x00\x04\xff\xff\x8f\x80\x00\nLMT\x00-0830\x00-08\x00\n<-08>8\nPK\x03\x04\n\x00\x00\x00\x00\x00" + - "\xf1c9R3\x03\x1f\f\xac\x00\x00\x00\xac\x00\x00\x00\x11\x00\x1c\x00Pacific/EnderburyUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00" + - "\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif" + - "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff~7Ud\x00\x00\x00\x00\x12V\x04\xc0\x00\x00\x00\x00" + - "/\x059\xb0\x01\x02\x03\xff\xff_\x9c\x00\x00\xff\xffW@\x00\x04\xff\xffeP\x00\b\x00\x00\xb6\xd0\x00\fLMT\x00-12\x00-11\x00+13\x00\n<+13>-13\nPK\x03" + - "\x04\n\x00\x00\x00\x00\x00\xf1c9Ra\vೆ\x00\x00\x00\x86\x00\x00\x00\x10\x00\x1c\x00Pacific/FunafutiUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00" + - "\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00" + - "\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff~6\f\xfc\x01\x00\x00\xa8\x04\x00" + - "\x00\x00\x00\xa8\xc0\x00\x04LMT\x00+12\x00\n<+12>-12\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\u07b54-\xd6\x00\x00\x00\xd6\x00\x00\x00\x0e\x00\x1c\x00Pacif" + - "ic/PonapeUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + ",\xa4\xe9\x90\x00\x00\x00\x00-\x94ڐ\x00\x00\x00\x00.\x84ː\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000d\xad\x90\x00\x00\x00\x001]\xd9\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00\n\x14\x00\x00\x00\x00\x1c \x01\x04\x00\x00\x0e\x10\x00\t" + + "LMT\x00CEST\x00CET\x00\nCET-1CEST,M3.5.0,M10.5.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xab\x80c$q" + + "\x00\x00\x00q\x00\x00\x00\a\x00\x1c\x00FactoryUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00-00\x00\n<-00>0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSk\xa4,\xb6?\x06\x00" + + "\x00?\x06\x00\x00\x02\x00\x1c\x00GBUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x9f\x00\x00\x00\x05\x00\x00\x00\x11\xff\xff\xff\xff\x1a]\t\xcb\xff\xff\xff\xff\x9b&\xad\xa0\xff\xff\xff\xff\x9b\xd6\x05 \xff\xff\xff\xff\x9c\xcf0\xa0\xff\xff\xff\xff\x9d\xa4à\xff\xff\xff\xff\x9e\x9c" + + "\x9d\xa0\xff\xff\xff\xff\x9f\x97\x1a\xa0\xff\xff\xff\xff\xa0\x85\xba \xff\xff\xff\xff\xa1v\xfc\xa0\xff\xff\xff\xff\xa2e\x9c \xff\xff\xff\xff\xa3{Ƞ\xff\xff\xff\xff\xa4N\xb8\xa0\xff\xff\xff\xff\xa5?\xfb \xff\xff" + + "\xff\xff\xa6%` \xff\xff\xff\xff\xa7'\xc6 \xff\xff\xff\xff\xa8*, \xff\xff\xff\xff\xa8\xeb\xf8\xa0\xff\xff\xff\xff\xaa\x00Ӡ\xff\xff\xff\xff\xaa\xd5\x15 \xff\xff\xff\xff\xab\xe9\xf0 \xff\xff\xff\xff\xac\xc7" + + "l \xff\xff\xff\xff\xad\xc9\xd2 \xff\xff\xff\xff\xae\xa7N \xff\xff\xff\xff\xaf\xa0y\xa0\xff\xff\xff\xff\xb0\x870 \xff\xff\xff\xff\xb1\x92Р\xff\xff\xff\xff\xb2pL\xa0\xff\xff\xff\xff\xb3r\xb2\xa0\xff\xff" + + "\xff\xff\xb4P.\xa0\xff\xff\xff\xff\xb5IZ \xff\xff\xff\xff\xb60\x10\xa0\xff\xff\xff\xff\xb72v\xa0\xff\xff\xff\xff\xb8\x0f\xf2\xa0\xff\xff\xff\xff\xb9\x12X\xa0\xff\xff\xff\xff\xb9\xefԠ\xff\xff\xff\xff\xba\xe9" + + "\x00 \xff\xff\xff\xff\xbb\xd8\xf1 \xff\xff\xff\xff\xbc\xdbW \xff\xff\xff\xff\xbd\xb8\xd3 \xff\xff\xff\xff\xbe\xb1\xfe\xa0\xff\xff\xff\xff\xbf\x98\xb5 \xff\xff\xff\xff\xc0\x9b\x1b \xff\xff\xff\xff\xc1x\x97 \xff\xff" + + "\xff\xff\xc2z\xfd \xff\xff\xff\xff\xc3Xy \xff\xff\xff\xff\xc4Q\xa4\xa0\xff\xff\xff\xff\xc58[ \xff\xff\xff\xff\xc6:\xc1 \xff\xff\xff\xff\xc7X֠\xff\xff\xff\xff\xc7\xda\t\xa0\xff\xff\xff\xff\xca\x16" + + "&\x90\xff\xff\xff\xffʗY\x90\xff\xff\xff\xff\xcb\xd1\x1e\x90\xff\xff\xff\xff\xccw;\x90\xff\xff\xff\xffͱ\x00\x90\xff\xff\xff\xff\xce`X\x10\xff\xff\xff\xffϐ\xe2\x90\xff\xff\xff\xff\xd0n^\x90\xff\xff" + + "\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd1\xfb2\x10\xff\xff\xff\xff\xd2i\xfe \xff\xff\xff\xff\xd3c)\xa0\xff\xff\xff\xff\xd4I\xe0 \xff\xff\xff\xff\xd5\x1e!\xa0\xff\xff\xff\xff\xd5B\xfd\x90\xff\xff\xff\xff\xd5\xdf" + + "\xe0\x10\xff\xff\xff\xff\xd6N\xac \xff\xff\xff\xff\xd6\xfe\x03\xa0\xff\xff\xff\xff\xd8.\x8e \xff\xff\xff\xff\xd8\xf9\x95 \xff\xff\xff\xff\xda\x0ep \xff\xff\xff\xff\xda\xeb\xec \xff\xff\xff\xff\xdb\xe5\x17\xa0\xff\xff" + + "\xff\xff\xdc\xcb\xce \xff\xff\xff\xff\xdd\xc4\xf9\xa0\xff\xff\xff\xff\u07b4\xea\xa0\xff\xff\xff\xff߮\x16 \xff\xff\xff\xff\xe0\x94̠\xff\xff\xff\xff\xe1rH\xa0\xff\xff\xff\xff\xe2kt \xff\xff\xff\xff\xe3R" + + "*\xa0\xff\xff\xff\xff\xe4T\x90\xa0\xff\xff\xff\xff\xe52\f\xa0\xff\xff\xff\xff\xe6=\xad \xff\xff\xff\xff\xe7\x1b) \xff\xff\xff\xff\xe8\x14T\xa0\xff\xff\xff\xff\xe8\xfb\v \xff\xff\xff\xff\xe9\xfdq \xff\xff" + + "\xff\xff\xea\xda\xed \xff\xff\xff\xff\xeb\xddS \xff\xff\xff\xff\xec\xba\xcf \xff\xff\xff\xff\xed\xb3\xfa\xa0\xff\xff\xff\xff\ue6b1 \xff\xff\xff\xff\xef\x81g\xa0\xff\xff\xff\xff\xf0\x9f} \xff\xff\xff\xff\xf1a" + + "I\xa0\xff\xff\xff\xff\xf2\u007f_ \xff\xff\xff\xff\xf3Jf \xff\xff\xff\xff\xf4_A \xff\xff\xff\xff\xf5!\r\xa0\xff\xff\xff\xff\xf6?# \xff\xff\xff\xff\xf7\x00\xef\xa0\xff\xff\xff\xff\xf8\x1f\x05 \xff\xff" + + "\xff\xff\xf8\xe0Ѡ\xff\xff\xff\xff\xf9\xfe\xe7 \xff\xff\xff\xff\xfa\xc0\xb3\xa0\xff\xff\xff\xff\xfb\xe8\x03\xa0\xff\xff\xff\xff\xfc{\xab\xa0\xff\xff\xff\xff\xfdǻp\x00\x00\x00\x00\x03p\xc6 \x00\x00\x00\x00\x04)" + + "X \x00\x00\x00\x00\x05P\xa8 \x00\x00\x00\x00\x06\t: \x00\x00\x00\x00\a0\x8a \x00\x00\x00\x00\a\xe9\x1c \x00\x00\x00\x00\t\x10l \x00\x00\x00\x00\t\xc8\xfe \x00\x00\x00\x00\n\xf0N \x00\x00" + + "\x00\x00\v\xb2\x1a\xa0\x00\x00\x00\x00\f\xd00 \x00\x00\x00\x00\r\x91\xfc\xa0\x00\x00\x00\x00\x0e\xb0\x12 \x00\x00\x00\x00\x0fqޠ\x00\x00\x00\x00\x10\x99.\xa0\x00\x00\x00\x00\x11Q\xc0\xa0\x00\x00\x00\x00\x12y" + + "\x10\xa0\x00\x00\x00\x00\x131\xa2\xa0\x00\x00\x00\x00\x14X\xf2\xa0\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x168Ɛ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x18\x18\xa8\x90\x00\x00\x00\x00\x18㯐\x00\x00" + + "\x00\x00\x19\xf8\x8a\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xe1\xa7\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\xc1\x89\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f\xa1k\x10\x00\x00\x00\x00 l" + + "r\x10\x00\x00\x00\x00!\x81M\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#a/\x10\x00\x00\x00\x00$,6\x10\x00\x00\x00\x00%JK\x90\x00\x00\x00\x00&\f\x18\x10\x00\x00\x00\x00'*-\x90\x00\x00" + + "\x00\x00'\xf54\x90\x00\x00\x00\x00)\n\x0f\x90\x00\x00\x00\x00)\xd5\x16\x90\x00\x00\x00\x00*\xe9\xf1\x90\x00\x00\x00\x00+\xb4\xf8\x90\x00\x00\x00\x00,\xc9Ӑ\x00\x00\x00\x00-\x94ڐ\x00\x00\x00\x00.\xa9" + + "\xb5\x90\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000\x89\x97\x90\x00\x00\x00\x001]\xd9\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x02\x01\x02\x01\x03\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\xff\xff\xff\xb5\x00\x00\x00\x00\x0e\x10\x01\x04\x00\x00\x00\x00\x00\b\x00\x00\x1c \x01\f\x00\x00\x0e\x10\x00\x04LMT\x00BST\x00GMT\x00BDST\x00\nGMT0BST" + + ",M3.5.0/1,M10.5.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSk\xa4,\xb6?\x06\x00\x00?\x06\x00\x00\a\x00\x1c\x00GB-EireUT\t\x00\x03" + + "\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9f\x00\x00\x00\x05\x00\x00\x00\x11\xff\xff" + + "\xff\xff\x1a]\t\xcb\xff\xff\xff\xff\x9b&\xad\xa0\xff\xff\xff\xff\x9b\xd6\x05 \xff\xff\xff\xff\x9c\xcf0\xa0\xff\xff\xff\xff\x9d\xa4à\xff\xff\xff\xff\x9e\x9c\x9d\xa0\xff\xff\xff\xff\x9f\x97\x1a\xa0\xff\xff\xff\xff\xa0\x85" + + "\xba \xff\xff\xff\xff\xa1v\xfc\xa0\xff\xff\xff\xff\xa2e\x9c \xff\xff\xff\xff\xa3{Ƞ\xff\xff\xff\xff\xa4N\xb8\xa0\xff\xff\xff\xff\xa5?\xfb \xff\xff\xff\xff\xa6%` \xff\xff\xff\xff\xa7'\xc6 \xff\xff" + + "\xff\xff\xa8*, \xff\xff\xff\xff\xa8\xeb\xf8\xa0\xff\xff\xff\xff\xaa\x00Ӡ\xff\xff\xff\xff\xaa\xd5\x15 \xff\xff\xff\xff\xab\xe9\xf0 \xff\xff\xff\xff\xac\xc7l \xff\xff\xff\xff\xad\xc9\xd2 \xff\xff\xff\xff\xae\xa7" + + "N \xff\xff\xff\xff\xaf\xa0y\xa0\xff\xff\xff\xff\xb0\x870 \xff\xff\xff\xff\xb1\x92Р\xff\xff\xff\xff\xb2pL\xa0\xff\xff\xff\xff\xb3r\xb2\xa0\xff\xff\xff\xff\xb4P.\xa0\xff\xff\xff\xff\xb5IZ \xff\xff" + + "\xff\xff\xb60\x10\xa0\xff\xff\xff\xff\xb72v\xa0\xff\xff\xff\xff\xb8\x0f\xf2\xa0\xff\xff\xff\xff\xb9\x12X\xa0\xff\xff\xff\xff\xb9\xefԠ\xff\xff\xff\xff\xba\xe9\x00 \xff\xff\xff\xff\xbb\xd8\xf1 \xff\xff\xff\xff\xbc\xdb" + + "W \xff\xff\xff\xff\xbd\xb8\xd3 \xff\xff\xff\xff\xbe\xb1\xfe\xa0\xff\xff\xff\xff\xbf\x98\xb5 \xff\xff\xff\xff\xc0\x9b\x1b \xff\xff\xff\xff\xc1x\x97 \xff\xff\xff\xff\xc2z\xfd \xff\xff\xff\xff\xc3Xy \xff\xff" + + "\xff\xff\xc4Q\xa4\xa0\xff\xff\xff\xff\xc58[ \xff\xff\xff\xff\xc6:\xc1 \xff\xff\xff\xff\xc7X֠\xff\xff\xff\xff\xc7\xda\t\xa0\xff\xff\xff\xff\xca\x16&\x90\xff\xff\xff\xffʗY\x90\xff\xff\xff\xff\xcb\xd1" + + "\x1e\x90\xff\xff\xff\xff\xccw;\x90\xff\xff\xff\xffͱ\x00\x90\xff\xff\xff\xff\xce`X\x10\xff\xff\xff\xffϐ\xe2\x90\xff\xff\xff\xff\xd0n^\x90\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd1\xfb2\x10\xff\xff" + + "\xff\xff\xd2i\xfe \xff\xff\xff\xff\xd3c)\xa0\xff\xff\xff\xff\xd4I\xe0 \xff\xff\xff\xff\xd5\x1e!\xa0\xff\xff\xff\xff\xd5B\xfd\x90\xff\xff\xff\xff\xd5\xdf\xe0\x10\xff\xff\xff\xff\xd6N\xac \xff\xff\xff\xff\xd6\xfe" + + "\x03\xa0\xff\xff\xff\xff\xd8.\x8e \xff\xff\xff\xff\xd8\xf9\x95 \xff\xff\xff\xff\xda\x0ep \xff\xff\xff\xff\xda\xeb\xec \xff\xff\xff\xff\xdb\xe5\x17\xa0\xff\xff\xff\xff\xdc\xcb\xce \xff\xff\xff\xff\xdd\xc4\xf9\xa0\xff\xff" + + "\xff\xff\u07b4\xea\xa0\xff\xff\xff\xff߮\x16 \xff\xff\xff\xff\xe0\x94̠\xff\xff\xff\xff\xe1rH\xa0\xff\xff\xff\xff\xe2kt \xff\xff\xff\xff\xe3R*\xa0\xff\xff\xff\xff\xe4T\x90\xa0\xff\xff\xff\xff\xe52" + + "\f\xa0\xff\xff\xff\xff\xe6=\xad \xff\xff\xff\xff\xe7\x1b) \xff\xff\xff\xff\xe8\x14T\xa0\xff\xff\xff\xff\xe8\xfb\v \xff\xff\xff\xff\xe9\xfdq \xff\xff\xff\xff\xea\xda\xed \xff\xff\xff\xff\xeb\xddS \xff\xff" + + "\xff\xff\xec\xba\xcf \xff\xff\xff\xff\xed\xb3\xfa\xa0\xff\xff\xff\xff\ue6b1 \xff\xff\xff\xff\xef\x81g\xa0\xff\xff\xff\xff\xf0\x9f} \xff\xff\xff\xff\xf1aI\xa0\xff\xff\xff\xff\xf2\u007f_ \xff\xff\xff\xff\xf3J" + + "f \xff\xff\xff\xff\xf4_A \xff\xff\xff\xff\xf5!\r\xa0\xff\xff\xff\xff\xf6?# \xff\xff\xff\xff\xf7\x00\xef\xa0\xff\xff\xff\xff\xf8\x1f\x05 \xff\xff\xff\xff\xf8\xe0Ѡ\xff\xff\xff\xff\xf9\xfe\xe7 \xff\xff" + + "\xff\xff\xfa\xc0\xb3\xa0\xff\xff\xff\xff\xfb\xe8\x03\xa0\xff\xff\xff\xff\xfc{\xab\xa0\xff\xff\xff\xff\xfdǻp\x00\x00\x00\x00\x03p\xc6 \x00\x00\x00\x00\x04)X \x00\x00\x00\x00\x05P\xa8 \x00\x00\x00\x00\x06\t" + + ": \x00\x00\x00\x00\a0\x8a \x00\x00\x00\x00\a\xe9\x1c \x00\x00\x00\x00\t\x10l \x00\x00\x00\x00\t\xc8\xfe \x00\x00\x00\x00\n\xf0N \x00\x00\x00\x00\v\xb2\x1a\xa0\x00\x00\x00\x00\f\xd00 \x00\x00" + + "\x00\x00\r\x91\xfc\xa0\x00\x00\x00\x00\x0e\xb0\x12 \x00\x00\x00\x00\x0fqޠ\x00\x00\x00\x00\x10\x99.\xa0\x00\x00\x00\x00\x11Q\xc0\xa0\x00\x00\x00\x00\x12y\x10\xa0\x00\x00\x00\x00\x131\xa2\xa0\x00\x00\x00\x00\x14X" + + "\xf2\xa0\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x168Ɛ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x18\x18\xa8\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19\xf8\x8a\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00" + + "\x00\x00\x1b\xe1\xa7\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\xc1\x89\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f\xa1k\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\x81M\x10\x00\x00\x00\x00\"L" + + "T\x10\x00\x00\x00\x00#a/\x10\x00\x00\x00\x00$,6\x10\x00\x00\x00\x00%JK\x90\x00\x00\x00\x00&\f\x18\x10\x00\x00\x00\x00'*-\x90\x00\x00\x00\x00'\xf54\x90\x00\x00\x00\x00)\n\x0f\x90\x00\x00" + + "\x00\x00)\xd5\x16\x90\x00\x00\x00\x00*\xe9\xf1\x90\x00\x00\x00\x00+\xb4\xf8\x90\x00\x00\x00\x00,\xc9Ӑ\x00\x00\x00\x00-\x94ڐ\x00\x00\x00\x00.\xa9\xb5\x90\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000\x89" + + "\x97\x90\x00\x00\x00\x001]\xd9\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x02\x01\x02\x01\x03\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x04\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xff\xb5\x00\x00\x00\x00\x0e\x10\x01" + + "\x04\x00\x00\x00\x00\x00\b\x00\x00\x1c \x01\f\x00\x00\x0e\x10\x00\x04LMT\x00BST\x00GMT\x00BDST\x00\nGMT0BST,M3.5.0/1,M10.5." + + "0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSP\xda\xfa\x03o\x00\x00\x00o\x00\x00\x00\x03\x00\x1c\x00GMTUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S" + + "_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00" + + "\x00\x00\x00\x00#\x82iSP\xda\xfa\x03o\x00\x00\x00o\x00\x00\x00\x05\x00\x1c\x00GMT+0UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZi" + + "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82" + + "iSP\xda\xfa\x03o\x00\x00\x00o\x00\x00\x00\x05\x00\x1c\x00GMT-0UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSP\xda\xfa\x03" + + "o\x00\x00\x00o\x00\x00\x00\x04\x00\x1c\x00GMT0UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSP\xda\xfa\x03o\x00\x00\x00o\x00\x00" + + "\x00\t\x00\x1c\x00GreenwichUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00GMT\x00\nGMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSE\t\xfa-\a\x03\x00\x00\a\x03\x00\x00\b" + + "\x00\x1c\x00HongkongUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00E\x00\x00\x00\x05\x00\x00\x00\x16\xff\xff\xff\xff\x85ic\x90\xff\xff\xff\xff\xcaM10\xff\xff\xff\xff\xcaۓ0\xff\xff\xff\xff\xcbKqx\xff\xff\xff\xffҠސ\xff\xff\xff\xff\xd3k" + + "׀\xff\xff\xff\xffԓX\xb8\xff\xff\xff\xff\xd5B\xb08\xff\xff\xff\xff\xd6s:\xb8\xff\xff\xff\xff\xd7>A\xb8\xff\xff\xff\xff\xd8.2\xb8\xff\xff\xff\xff\xd8\xf99\xb8\xff\xff\xff\xff\xda\x0e\x14\xb8\xff\xff" + + "\xff\xff\xda\xd9\x1b\xb8\xff\xff\xff\xff\xdb\xed\xf6\xb8\xff\xff\xff\xffܸ\xfd\xb8\xff\xff\xff\xff\xdd\xcdظ\xff\xff\xff\xffޢ\x1a8\xff\xff\xff\xff߶\xf58\xff\xff\xff\xff\xe0\x81\xfc8\xff\xff\xff\xff\xe1\x96" + + "\xc9(\xff\xff\xff\xff\xe2Oi8\xff\xff\xff\xff\xe3v\xab(\xff\xff\xff\xff\xe4/K8\xff\xff\xff\xff\xe5_Ǩ\xff\xff\xff\xff\xe6\x0f-8\xff\xff\xff\xff\xe7?\xa9\xa8\xff\xff\xff\xff\xe7\xf8I\xb8\xff\xff" + + "\xff\xff\xe9\x1f\x8b\xa8\xff\xff\xff\xff\xe9\xd8+\xb8\xff\xff\xff\xff\xea\xffm\xa8\xff\xff\xff\xff\xeb\xb8\r\xb8\xff\xff\xff\xff\xec\xdfO\xa8\xff\xff\xff\xff\xed\x97\xef\xb8\xff\xff\xff\xff\xee\xc8l(\xff\xff\xff\xff\xefw" + + "Ѹ\xff\xff\xff\xff\xf0\xa8N(\xff\xff\xff\xff\xf1W\xb3\xb8\xff\xff\xff\xff\xf2\x880(\xff\xff\xff\xff\xf3@\xd08\xff\xff\xff\xff\xf4h\x12(\xff\xff\xff\xff\xf5 \xb28\xff\xff\xff\xff\xf6G\xf4(\xff\xff" + + "\xff\xff\xf7%~8\xff\xff\xff\xff\xf8\x15a(\xff\xff\xff\xff\xf9\x05`8\xff\xff\xff\xff\xf9\xf5C(\xff\xff\xff\xff\xfa\xe5B8\xff\xff\xff\xff\xfb\xde_\xa8\xff\xff\xff\xff\xfc\xce^\xb8\xff\xff\xff\xff\xfd\xbe" + + "A\xa8\xff\xff\xff\xff\xfe\xae@\xb8\xff\xff\xff\xff\xff\x9e#\xa8\x00\x00\x00\x00\x00\x8e\"\xb8\x00\x00\x00\x00\x01~\x05\xa8\x00\x00\x00\x00\x02n\x04\xb8\x00\x00\x00\x00\x03]\xe7\xa8\x00\x00\x00\x00\x04M\xe6\xb8\x00\x00" + + "\x00\x00\x05G\x04(\x00\x00\x00\x00\x067\x038\x00\x00\x00\x00\a&\xe6(\x00\x00\x00\x00\a\x83=8\x00\x00\x00\x00\t\x06\xc8(\x00\x00\x00\x00\t\xf6\xc78\x00\x00\x00\x00\n\xe6\xaa(\x00\x00\x00\x00\v\xd6" + + "\xa98\x00\x00\x00\x00\fƌ(\x00\x00\x00\x00\x11\x9b98\x00\x00\x00\x00\x12ol\xa8\x01\x02\x03\x04\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00k\n\x00\x00\x00\x00p\x80\x00\x04\x00\x00~\x90\x01\b\x00\x00w\x88\x01\r\x00" + + "\x00~\x90\x00\x12LMT\x00HKT\x00HKST\x00HKWT\x00JST\x00\nHKT-8\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS=\xf7\xfawp\x00\x00\x00p\x00\x00\x00" + + "\x03\x00\x1c\x00HSTUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xffs`\x00\x00HST\x00\nHST10\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSm\xbd\x10k\xf1\x02\x00\x00\xf1\x02\x00\x00\a\x00\x1c\x00Ice" + + "landUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00D\x00" + + "\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff\x8b`\x83\xa0\xff\xff\xff\xff\x9c\x91\x1e\x00\xff\xff\xff\xff\x9dш\x90\xff\xff\xff\xff\x9erQ\x80\xff\xff\xff\xff\x9f\xd5\x03\x10\xff\xff\xff\xff\xa0S\x85\x00\xff\xff\xff\xff\xa1" + + "\xb66\x90\xff\xff\xff\xff\xa4<'\x80\xff\xff\xff\xff\xa4\xb9t\x10\xff\xff\xff\xff\xc6M\x1a\x00\xff\xff\xff\xff\xc7=' \xff\xff\xff\xff\xc7\xda\x17\xb0\xff\xff\xff\xff\xc9&C\xa0\xff\xff\xff\xff\xc9\xc3& \xff" + + "\xff\xff\xff\xcb\x06%\xa0\xff\xff\xff\xffˬB\xa0\xff\xff\xff\xff\xcc\xdc\xcd \xff\xff\xff\xff͌$\xa0\xff\xff\xff\xffμ\xaf \xff\xff\xff\xff\xcfl\x06\xa0\xff\xff\xff\xffМ\x91 \xff\xff\xff\xff\xd1" + + "K\xe8\xa0\xff\xff\xff\xff҅\xad\xa0\xff\xff\xff\xff\xd3+ʠ\xff\xff\xff\xff\xd4e\x8f\xa0\xff\xff\xff\xff\xd59\xd1 \xff\xff\xff\xff\xd6Eq\xa0\xff\xff\xff\xff\xd7\x19\xb3 \xff\xff\xff\xff\xd8%S\xa0\xff" + + "\xff\xff\xff\xd8\xf9\x95 \xff\xff\xff\xff\xda\x0ep \xff\xff\xff\xff\xda\xd9w \xff\xff\xff\xff\xdb\xe5\x17\xa0\xff\xff\xff\xffܹY \xff\xff\xff\xff\xdd\xce4 \xff\xff\xff\xffޢu\xa0\xff\xff\xff\xff\xdf" + + "\xae\x16 \xff\xff\xff\xff\xe0\x82W\xa0\xff\xff\xff\xff\xe1\x8d\xf8 \xff\xff\xff\xff\xe2b9\xa0\xff\xff\xff\xff\xe3m\xda \xff\xff\xff\xff\xe4B\x1b\xa0\xff\xff\xff\xff\xe5M\xbc \xff\xff\xff\xff\xe6!\xfd\xa0\xff" + + "\xff\xff\xff\xe76ؠ\xff\xff\xff\xff\xe8\v\x1a \xff\xff\xff\xff\xe9\x16\xba\xa0\xff\xff\xff\xff\xe9\xea\xfc \xff\xff\xff\xff\xea\xf6\x9c\xa0\xff\xff\xff\xff\xeb\xca\xde \xff\xff\xff\xff\xec\xd6~\xa0\xff\xff\xff\xff\xed" + + "\xaa\xc0 \xff\xff\xff\xff\xee\xb6`\xa0\xff\xff\xff\xff\uf2a2 \xff\xff\xff\xff\xf0\x96B\xa0\xff\xff\xff\xff\xf1j\x84 \xff\xff\xff\xff\xf2\u007f_ \xff\xff\xff\xff\xf3S\xa0\xa0\xff\xff\xff\xff\xf4_A \xff" + + "\xff\xff\xff\xf53\x82\xa0\xff\xff\xff\xff\xf6?# \xff\xff\xff\xff\xf7\x13d\xa0\xff\xff\xff\xff\xf8\x1f\x05 \xff\xff\xff\xff\xf8\xf3F\xa0\xff\xff\xff\xff\xf9\xfe\xe7 \xff\xff\xff\xff\xfa\xd3(\xa0\xff\xff\xff\xff\xfb" + + "\xe8\x03\xa0\xff\xff\xff\xff\xfc\xbcE \x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\xff\xff\xeb`\x00\x00\x00\x00\x00\x00\x01\x04\xff\xff\xf1\xf0\x00\b\x00\x00\x00\x00\x00\fLMT\x00+00\x00-01\x00GMT\x00\n" + + "GMT0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x1c\x00Indian/UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01" + + "\x04\x14E\x00\x00\x04S_\x01\x00PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSͲ\xfb\xf6\x8c\x00\x00\x00\x8c\x00\x00\x00\f\x00\x1c\x00Indian/CocosUT\t\x00\x03\x82\x0f\x8b" + + "a\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" + + "\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\n\xff\xff\xff\xff|" + + "U&\xa4\x01\x00\x00Z\xdc\x00\x00\x00\x00[h\x00\x04LMT\x00+0630\x00\n<+0630>-6:30\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb4\x8d\x98ƿ\x00" + + "\x00\x00\xbf\x00\x00\x00\x13\x00\x1c\x00Indian/AntananarivoUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZi" + + "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\x14\xff\xff\xff\xff\x8b\xff\xd1\xfc\xff\xff\xff\xff\xb1\xee\xdaX\xff\xff\xff\xff\xb4\xc7\xe0\xd0\xff\xff\xff\xff" + + "\xc1\xed\xadX\xff\xff\xff\xff\xcclz\xd4\x01\x02\x01\x03\x02\x00\x00\"\x84\x00\x00\x00\x00#(\x00\x04\x00\x00*0\x00\n\x00\x00&\xac\x00\x0eLMT\x00+0230\x00EAT\x00+0245" + + "\x00\nEAT-3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSx\xb0W\x14\x98\x00\x00\x00\x98\x00\x00\x00\r\x00\x1c\x00Indian/ChagosUT\t\x00\x03\x82\x0f\x8ba" + + "\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00" + + "\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x89~" + + "\xf7\x9c\x00\x00\x00\x000\xe6ݰ\x01\x02\x00\x00C\xe4\x00\x00\x00\x00FP\x00\x04\x00\x00T`\x00\bLMT\x00+05\x00+06\x00\n<+06>-6\nPK\x03\x04\n\x00\x00\x00\x00" + + "\x00#\x82iS\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\x0e\x00\x1c\x00Indian/MayotteUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S" + + "_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\x14\xff\xff\xff\xff\x8b\xff\xd1\xfc\xff\xff\xff\xff\xb1\xee\xdaX\xff\xff\xff\xff\xb4\xc7" + + "\xe0\xd0\xff\xff\xff\xff\xc1\xed\xadX\xff\xff\xff\xff\xcclz\xd4\x01\x02\x01\x03\x02\x00\x00\"\x84\x00\x00\x00\x00#(\x00\x04\x00\x00*0\x00\n\x00\x00&\xac\x00\x0eLMT\x00+0230\x00EAT" + + "\x00+0245\x00\nEAT-3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS$l=҅\x00\x00\x00\x85\x00\x00\x00\x10\x00\x1c\x00Indian/Christmas" + + "UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00" + + "\x00\x00\b\xff\xff\xff\xffs\x16\xa9\xe4\x01\x00\x00c\x1c\x00\x00\x00\x00bp\x00\x04LMT\x00+07\x00\n<+07>-7\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb9\xb2Z\xac\x98" + + "\x00\x00\x00\x98\x00\x00\x00\x0f\x00\x1c\x00Indian/MaldivesUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xffV\xb6\x9f\x18\xff\xff\xff\xff\xed/Ø\x01\x02\x00\x00D\xe8\x00\x00\x00\x00D\xe8\x00\x04\x00" + + "\x00FP\x00\bLMT\x00MMT\x00+05\x00\n<+05>-5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\r\x00\x1c\x00Indi" + + "an/ComoroUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\a\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\x14\xe1\xb9,\xff\xff\xff\xff~6 \xac\xff\xff\xff\xff\x98\x11\x95\xd0\xff\xff\xff\xff\xa09\xf9\xf0\xff\xff\xff\xff\xc1\xed5\xd0\xff\xff\xff\xff\xc9\xea\n`" + - "\xff\xff\xff\xff\xd2\x11\x0e\xf0\x01\x02\x03\x02\x04\x03\x02\xff\xffB\xd4\x00\x00\x00\x00\x94T\x00\x00\x00\x00\x9a\xb0\x00\x04\x00\x00~\x90\x00\b\x00\x00\x8c\xa0\x00\fLMT\x00+11\x00+09\x00+10" + - "\x00\n<+11>-11\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xb7\xef\x97\xc6\xc6\x00\x00\x00\xc6\x00\x00\x00\x0e\x00\x1c\x00Pacific/NoumeaUT\t\x00\x03" + - "\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x03\x00\x00\x00\f\xff\xff" + - "\xff\xff\x92\xf5\xc4t\x00\x00\x00\x00\x0e\xe6\xbaP\x00\x00\x00\x00\x0fV\xbb\xc0\x00\x00\x00\x00\x10ƜP\x00\x00\x00\x00\x117\xef@\x00\x00\x00\x002\xa0K\xf0\x00\x00\x00\x003\x18Dp\x02\x01\x02\x01\x02\x01" + - "\x02\x00\x00\x9c\f\x00\x00\x00\x00\xa8\xc0\x01\x04\x00\x00\x9a\xb0\x00\bLMT\x00+12\x00+11\x00\n<+11>-11\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x80\xf8vܔ" + - "\x00\x00\x00\x94\x00\x00\x00\r\x00\x1c\x00Pacific/PalauUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\b\xff\xff\xff\xff\x14\xe1\xcfl\xff\xff\xff\xff~66\xec\x01\x02\xff\xff,\x94\x00\x00\x00\x00~\x14\x00\x00\x00\x00~" + - "\x90\x00\x04LMT\x00+09\x00\n<+09>-9\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xeaK\x85v\xdd\x00\x00\x00\xdd\x00\x00\x00\x10\x00\x1c\x00Pacific/Jo" + - "hnstonUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\x14\xff\xff\xff\xff\x8b\xff\xd1\xfc\xff\xff\xff\xff\xb1\xee\xdaX\xff\xff\xff\xff\xb4\xc7\xe0\xd0\xff\xff\xff\xff\xc1\xed\xadX\xff\xff\xff\xff\xcclz\xd4\x01\x02\x01\x03\x02\x00\x00\"" + + "\x84\x00\x00\x00\x00#(\x00\x04\x00\x00*0\x00\n\x00\x00&\xac\x00\x0eLMT\x00+0230\x00EAT\x00+0245\x00\nEAT-3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82" + + "iS\x96\xed=\x98\xb3\x00\x00\x00\xb3\x00\x00\x00\x10\x00\x1c\x00Indian/MauritiusUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_" + + "\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x89\u007f\x05\x98\x00\x00\x00\x00\x18\x05\xed@\x00\x00\x00\x00\x18\xdbr" + + "0\x00\x00\x00\x00I\x03\x96\xe0\x00\x00\x00\x00IΏ\xd0\x02\x01\x02\x01\x02\x00\x005\xe8\x00\x00\x00\x00FP\x01\x04\x00\x008@\x00\bLMT\x00+05\x00+04\x00\n<+04>-4" + + "\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSa\x85jo\x85\x00\x00\x00\x85\x00\x00\x00\v\x00\x1c\x00Indian/MaheUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01" + + "\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00" + + "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x89\u007f\a\x84\x01\x00\x003\xfc\x00\x00" + + "\x00\x008@\x00\x04LMT\x00+04\x00\n<+04>-4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb8K\xabυ\x00\x00\x00\x85\x00\x00\x00\x10\x00\x1c\x00Indian/" + + "KerguelenUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\xdaab\x80\x01\x00\x00\x00\x00\x00\x00\x00\x00FP\x00\x04-00\x00+05\x00\n<+05>-5\nPK\x03\x04\n\x00\x00\x00\x00\x00" + + "#\x82iSy(\xb6\x8f\x85\x00\x00\x00\x85\x00\x00\x00\x0e\x00\x1c\x00Indian/ReunionUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_" + + "\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x91\xcc9\x80\x01\x00\x004\x00\x00\x00\x00\x008@\x00\x04LM" + + "T\x00+04\x00\n<+04>-4\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS;\u007fP\x8d\xd4\a\x00\x00\xd4\a\x00\x00\x04\x00\x1c\x00IranUT\t\x00\x03\x82\x0f\x8ba\x82\x0f" + + "\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" + + "\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc9\x00\x00\x00\x06\x00\x00\x00\x1c\xff\xff\xff\xff\x9al}\xc8" + + "\xff\xff\xff\xff\xd2\xdb\x12\xc8\x00\x00\x00\x00\x0e\xbb\xa2H\x00\x00\x00\x00\x0ft-@\x00\x00\x00\x00\x10\x8e@0\x00\x00\x00\x00\x10\xed:@\x00\x00\x00\x00\x11Ug\xc8\x00\x00\x00\x00\x12EJ\xb8\x00\x00\x00\x00" + + "\x137\xec\xc8\x00\x00\x00\x00\x14-\x15\xb8\x00\x00\x00\x00( v\xc8\x00\x00\x00\x00(\u06dd\xb8\x00\x00\x00\x00)˜\xc8\x00\x00\x00\x00*\xbe\"\xb8\x00\x00\x00\x00+\xac\xd0H\x00\x00\x00\x00,\x9fV8" + + "\x00\x00\x00\x00-\x8e\x03\xc8\x00\x00\x00\x00.\x80\x89\xb8\x00\x00\x00\x00/o7H\x00\x00\x00\x000a\xbd8\x00\x00\x00\x001Pj\xc8\x00\x00\x00\x002B\xf0\xb8\x00\x00\x00\x0032\xef\xc8\x00\x00\x00\x00" + + "4%u\xb8\x00\x00\x00\x005\x14#H\x00\x00\x00\x006\x06\xa98\x00\x00\x00\x006\xf5V\xc8\x00\x00\x00\x007\xe7ܸ\x00\x00\x00\x008֊H\x00\x00\x00\x009\xc9\x108\x00\x00\x00\x00:\xb9\x0fH" + + "\x00\x00\x00\x00;\xab\x958\x00\x00\x00\x00<\x9aB\xc8\x00\x00\x00\x00=\x8cȸ\x00\x00\x00\x00>{vH\x00\x00\x00\x00?m\xfc8\x00\x00\x00\x00@\\\xa9\xc8\x00\x00\x00\x00AO/\xb8\x00\x00\x00\x00" + + "B?.\xc8\x00\x00\x00\x00C1\xb4\xb8\x00\x00\x00\x00G\xe2\xc9H\x00\x00\x00\x00H\xd5O8\x00\x00\x00\x00I\xc5NH\x00\x00\x00\x00J\xb7\xd48\x00\x00\x00\x00K\xa6\x81\xc8\x00\x00\x00\x00L\x99\a\xb8" + + "\x00\x00\x00\x00M\x87\xb5H\x00\x00\x00\x00Nz;8\x00\x00\x00\x00Oh\xe8\xc8\x00\x00\x00\x00P[n\xb8\x00\x00\x00\x00QKm\xc8\x00\x00\x00\x00R=\xf3\xb8\x00\x00\x00\x00S,\xa1H\x00\x00\x00\x00" + + "T\x1f'8\x00\x00\x00\x00U\r\xd4\xc8\x00\x00\x00\x00V\x00Z\xb8\x00\x00\x00\x00V\xef\bH\x00\x00\x00\x00W\xe1\x8e8\x00\x00\x00\x00XэH\x00\x00\x00\x00Y\xc4\x138\x00\x00\x00\x00Z\xb2\xc0\xc8" + + "\x00\x00\x00\x00[\xa5F\xb8\x00\x00\x00\x00\\\x93\xf4H\x00\x00\x00\x00]\x86z8\x00\x00\x00\x00^u'\xc8\x00\x00\x00\x00_g\xad\xb8\x00\x00\x00\x00`W\xac\xc8\x00\x00\x00\x00aJ2\xb8\x00\x00\x00\x00" + + "b8\xe0H\x00\x00\x00\x00c+f8\x00\x00\x00\x00d\x1a\x13\xc8\x00\x00\x00\x00e\f\x99\xb8\x00\x00\x00\x00e\xfbGH\x00\x00\x00\x00f\xed\xcd8\x00\x00\x00\x00g\xdd\xccH\x00\x00\x00\x00h\xd0R8" + + "\x00\x00\x00\x00i\xbe\xff\xc8\x00\x00\x00\x00j\xb1\x85\xb8\x00\x00\x00\x00k\xa03H\x00\x00\x00\x00l\x92\xb98\x00\x00\x00\x00m\x81f\xc8\x00\x00\x00\x00ns\xec\xb8\x00\x00\x00\x00ob\x9aH\x00\x00\x00\x00" + + "pU 8\x00\x00\x00\x00qE\x1fH\x00\x00\x00\x00r7\xa58\x00\x00\x00\x00s&R\xc8\x00\x00\x00\x00t\x18ظ\x00\x00\x00\x00u\a\x86H\x00\x00\x00\x00u\xfa\f8\x00\x00\x00\x00v\xe8\xb9\xc8" + + "\x00\x00\x00\x00w\xdb?\xb8\x00\x00\x00\x00x\xcb>\xc8\x00\x00\x00\x00y\xbdĸ\x00\x00\x00\x00z\xacrH\x00\x00\x00\x00{\x9e\xf88\x00\x00\x00\x00|\x8d\xa5\xc8\x00\x00\x00\x00}\x80+\xb8\x00\x00\x00\x00" + + "~n\xd9H\x00\x00\x00\x00\u007fa_8\x00\x00\x00\x00\x80Q^H\x00\x00\x00\x00\x81C\xe48\x00\x00\x00\x00\x822\x91\xc8\x00\x00\x00\x00\x83%\x17\xb8\x00\x00\x00\x00\x84\x13\xc5H\x00\x00\x00\x00\x85\x06K8" + + "\x00\x00\x00\x00\x85\xf4\xf8\xc8\x00\x00\x00\x00\x86\xe7~\xb8\x00\x00\x00\x00\x87\xd7}\xc8\x00\x00\x00\x00\x88\xca\x03\xb8\x00\x00\x00\x00\x89\xb8\xb1H\x00\x00\x00\x00\x8a\xab78\x00\x00\x00\x00\x8b\x99\xe4\xc8\x00\x00\x00\x00" + + "\x8c\x8cj\xb8\x00\x00\x00\x00\x8d{\x18H\x00\x00\x00\x00\x8em\x9e8\x00\x00\x00\x00\x8f]\x9dH\x00\x00\x00\x00\x90P#8\x00\x00\x00\x00\x91>\xd0\xc8\x00\x00\x00\x00\x921V\xb8\x00\x00\x00\x00\x93 \x04H" + + "\x00\x00\x00\x00\x94\x12\x8a8\x00\x00\x00\x00\x95\x017\xc8\x00\x00\x00\x00\x95\xf3\xbd\xb8\x00\x00\x00\x00\x96\xe3\xbc\xc8\x00\x00\x00\x00\x97\xd6B\xb8\x00\x00\x00\x00\x98\xc4\xf0H\x00\x00\x00\x00\x99\xb7v8\x00\x00\x00\x00" + + "\x9a\xa6#\xc8\x00\x00\x00\x00\x9b\x98\xa9\xb8\x00\x00\x00\x00\x9c\x87WH\x00\x00\x00\x00\x9dy\xdd8\x00\x00\x00\x00\x9ei\xdcH\x00\x00\x00\x00\x9f\\b8\x00\x00\x00\x00\xa0K\x0f\xc8\x00\x00\x00\x00\xa1=\x95\xb8" + + "\x00\x00\x00\x00\xa2,CH\x00\x00\x00\x00\xa3\x1e\xc98\x00\x00\x00\x00\xa4\rv\xc8\x00\x00\x00\x00\xa4\xff\xfc\xb8\x00\x00\x00\x00\xa5\xef\xfb\xc8\x00\x00\x00\x00\xa6⁸\x00\x00\x00\x00\xa7\xd1/H\x00\x00\x00\x00" + + "\xa8õ8\x00\x00\x00\x00\xa9\xb2b\xc8\x00\x00\x00\x00\xaa\xa4\xe8\xb8\x00\x00\x00\x00\xab\x93\x96H\x00\x00\x00\x00\xac\x86\x1c8\x00\x00\x00\x00\xadt\xc9\xc8\x00\x00\x00\x00\xaegO\xb8\x00\x00\x00\x00\xafWN\xc8" + + "\x00\x00\x00\x00\xb0IԸ\x00\x00\x00\x00\xb18\x82H\x00\x00\x00\x00\xb2+\b8\x00\x00\x00\x00\xb3\x19\xb5\xc8\x00\x00\x00\x00\xb4\f;\xb8\x00\x00\x00\x00\xb4\xfa\xe9H\x00\x00\x00\x00\xb5\xedo8\x00\x00\x00\x00" + + "\xb6\xddnH\x00\x00\x00\x00\xb7\xcf\xf48\x00\x00\x00\x00\xb8\xbe\xa1\xc8\x00\x00\x00\x00\xb9\xb1'\xb8\x00\x00\x00\x00\xba\x9f\xd5H\x00\x00\x00\x00\xbb\x92[8\x00\x00\x00\x00\xbc\x81\b\xc8\x00\x00\x00\x00\xbds\x8e\xb8" + + "\x00\x00\x00\x00\xbec\x8d\xc8\x00\x00\x00\x00\xbfV\x13\xb8\x00\x00\x00\x00\xc0D\xc1H\x00\x00\x00\x00\xc17G8\x00\x00\x00\x00\xc2%\xf4\xc8\x00\x00\x00\x00\xc3\x18z\xb8\x00\x00\x00\x00\xc4\a(H\x00\x00\x00\x00" + + "\xc4\xf9\xae8\x00\x00\x00\x00\xc5\xe9\xadH\x00\x00\x00\x00\xc6\xdc38\x00\x00\x00\x00\xc7\xca\xe0\xc8\x00\x00\x00\x00Ƚf\xb8\x00\x00\x00\x00ɬ\x14H\x00\x00\x00\x00ʞ\x9a8\x00\x00\x00\x00ˍG\xc8" + + "\x00\x00\x00\x00\xcc\u007f\u0378\x00\x00\x00\x00\xcdo\xcc\xc8\x00\x00\x00\x00\xcebR\xb8\x00\x00\x00\x00\xcfQ\x00H\x00\x00\x00\x00\xd0C\x868\x00\x00\x00\x00\xd123\xc8\x00\x00\x00\x00\xd2$\xb9\xb8\x00\x00\x00\x00" + + "\xd3\x13gH\x00\x00\x00\x00\xd4\x05\xed8\x00\x00\x00\x00\xd4\xf5\xecH\x00\x00\x00\x00\xd5\xe8r8\x00\x00\x00\x00\xd6\xd7\x1f\xc8\x00\x00\x00\x00\xd7ɥ\xb8\x00\x00\x00\x00ظSH\x00\x00\x00\x00٪\xd98" + + "\x00\x00\x00\x00ڙ\x86\xc8\x00\x00\x00\x00ی\f\xb8\x00\x00\x00\x00\xdc|\v\xc8\x00\x00\x00\x00\xddn\x91\xb8\x00\x00\x00\x00\xde]?H\x01\x02\x04\x03\x04\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02" + + "\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02" + + "\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02" + + "\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02" + + "\x05\x00\x0008\x00\x00\x00\x0008\x00\x04\x00\x0018\x00\b\x00\x00FP\x01\x0e\x00\x008@\x00\x12\x00\x00?H\x01\x16LMT\x00TMT\x00+0330\x00+05\x00+04\x00+" + + "0430\x00\n<+0330>-3:30<+0430>,J79/24,J263/24\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x17✳2" + + "\x04\x00\x002\x04\x00\x00\x06\x00\x1c\x00IsraelUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xffV\xb6\xc2\xfa\xff\xff\xff\xff\x9e0E\x88\xff\xff\xff\xff\xc8Y\xcf\x00\xff\xff\xff\xff\xc8\xfa\xa6\x00\xff\xff\xff\xff\xc98\x9c\x80" + + "\xff\xff\xff\xff\xcc\xe5\xeb\x80\xff\xff\xff\xffͬ\xfe\x00\xff\xff\xff\xff\xce\xc7\x1f\x00\xff\xff\xff\xffϏ\x83\x00\xff\xff\xff\xffЩ\xa4\x00\xff\xff\xff\xffф}\x00\xff\xff\xff\xffҊ׀\xff\xff\xff\xff" + + "\xd3e\xb0\x80\xff\xff\xff\xff\xd4l\v\x00\xff\xff\xff\xff\xd7Z0\x80\xff\xff\xff\xff\xd7\xdfX\x00\xff\xff\xff\xff\xd8/À\xff\xff\xff\xff\xd9\x1ec\x00\xff\xff\xff\xff\xda\x10\xf7\x00\xff\xff\xff\xff\xda\xeb\xd0\x00" + + "\xff\xff\xff\xff۴4\x00\xff\xff\xff\xffܹ=\x00\xff\xff\xff\xff\xdd\xe0\x8d\x00\xff\xff\xff\xff\u07b4\u0380\xff\xff\xff\xffߤ\xbf\x80\xff\xff\xff\xff\xe0\x8bv\x00\xff\xff\xff\xff\xe1V}\x00\xff\xff\xff\xff" + + "\xe2\xbef\x80\xff\xff\xff\xff\xe36_\x00\xff\xff\xff\xff\xe4\x9eH\x80\xff\xff\xff\xff\xe5\x16A\x00\xff\xff\xff\xff\xe6t\xf0\x00\xff\xff\xff\xff\xe7\x11Ҁ\xff\xff\xff\xff\xe8&\xad\x80\xff\xff\xff\xff\xe8\xe8z\x00" + + "\x00\x00\x00\x00\b|\x8b\xe0\x00\x00\x00\x00\b\xfd\xb0\xd0\x00\x00\x00\x00\t\xf6\xea`\x00\x00\x00\x00\n\xa63\xd0\x00\x00\x00\x00\x13\xe9\xfc`\x00\x00\x00\x00\x14![`\x00\x00\x00\x00\x1a\xfa\xc6`\x00\x00\x00\x00" + + "\x1b\x8en`\x00\x00\x00\x00\x1c\xbe\xf8\xe0\x00\x00\x00\x00\x1dw|\xd0\x00\x00\x00\x00\x1e\xcc\xff`\x00\x00\x00\x00\x1f`\x99P\x00\x00\x00\x00 \x82\xb1`\x00\x00\x00\x00!I\xb5\xd0\x00\x00\x00\x00\"^\x9e\xe0" + + "\x00\x00\x00\x00# ]P\x00\x00\x00\x00$Z0`\x00\x00\x00\x00%\x00?P\x00\x00\x00\x00&\v\xed\xe0\x00\x00\x00\x00&\xd6\xe6\xd0\x00\x00\x00\x00'\xeb\xcf\xe0\x00\x00\x00\x00(\xc0\x03P\x00\x00\x00\x00" + + ")\xd4\xec`\x00\x00\x00\x00*\xa9\x1f\xd0\x00\x00\x00\x00+\xbbe\xe0\x00\x00\x00\x00,\x89\x01\xd0\x00\x00\x00\x00-\x9bG\xe0\x00\x00\x00\x00._\xa9P\x00\x00\x00\x00/{)\xe0\x00\x00\x00\x000H\xc5\xd0" + + "\x00\x00\x00\x001H\x96\xe0\x00\x00\x00\x002\x83\x82p" + + "\x00\x00\x00\x00?|\x9f\xe0\x00\x00\x00\x00@s6p\x00\x00\x00\x00AP\xa4`\x00\x00\x00\x00BL\x8f\x00\x00\x00\x00\x00CHOp\x00\x00\x00\x00D,q\x00\x00\x00\x00\x00E\x1e\xf6\xf0\x00\x00\x00\x00" + + "F\fS\x00\x00\x00\x00\x00F\xecc\xf0\x00\x00\x00\x00G\xec5\x00\x00\x00\x00\x00H\xe7\xf5p\x00\x00\x00\x00I\xcc\x17\x00\x00\x00\x00\x00J\xbe\x9c\xf0\x00\x00\x00\x00K\xab\xf9\x00\x00\x00\x00\x00L\x8c\t\xf0" + + "\x00\x00\x00\x00M\x95\x15\x80\x00\x00\x00\x00N\x87\x9bp\x00\x00\x00\x00Ot\xf7\x80\x00\x00\x00\x00P^B\xf0\x00\x00\x00\x00QTـ\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x04\x02\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x00\x00!\x06\x00\x00\x00\x00 \xf8\x00\x04\x00\x00*0\x01\b\x00\x00\x1c \x00\f\x00\x008@\x01\x10LMT\x00JMT\x00ID" + + "T\x00IST\x00IDDT\x00\nIST-2IDT,M3.4.4/26,M10.5.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS%J\xd5\xebS\x01\x00" + + "\x00S\x01\x00\x00\a\x00\x1c\x00JamaicaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xffi\x87#~\xff\xff\xff\xff\x93\x0f\xb4\xfe\x00\x00\x00\x00\a\x8d\x19p\x00\x00\x00\x00\t\x10\xa4`\x00\x00\x00\x00\t\xad\x94\xf0\x00" + + "\x00\x00\x00\n\xf0\x86`\x00\x00\x00\x00\v\xe0\x85p\x00\x00\x00\x00\f٢\xe0\x00\x00\x00\x00\r\xc0gp\x00\x00\x00\x00\x0e\xb9\x84\xe0\x00\x00\x00\x00\x0f\xa9\x83\xf0\x00\x00\x00\x00\x10\x99f\xe0\x00\x00\x00\x00\x11" + + "\x89e\xf0\x00\x00\x00\x00\x12yH\xe0\x00\x00\x00\x00\x13iG\xf0\x00\x00\x00\x00\x14Y*\xe0\x00\x00\x00\x00\x15I)\xf0\x00\x00\x00\x00\x169\f\xe0\x00\x00\x00\x00\x17)\v\xf0\x00\x00\x00\x00\x18\")`\x00" + + "\x00\x00\x00\x19\b\xed\xf0\x00\x00\x00\x00\x1a\x02\v`\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\xff\xff\xb8\x02\x00\x00\xff\xff\xb8\x02\x00\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x01" + + "\fLMT\x00KMT\x00EST\x00EDT\x00\nEST5\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x02\xf4\xaeg\xd5\x00\x00\x00\xd5\x00\x00\x00\x05\x00\x1c\x00JapanUT" + + "\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x03\x00\x00\x00" + + "\f\xff\xff\xff\xffe¤p\xff\xff\xff\xff\xd7>\x02p\xff\xff\xff\xff\xd7\xedY\xf0\xff\xff\xff\xff\xd8\xf8\xfap\xff\xff\xff\xff\xd9\xcd;\xf0\xff\xff\xff\xff\xdb\a\x00\xf0\xff\xff\xff\xffۭ\x1d\xf0\xff\xff\xff" + + "\xff\xdc\xe6\xe2\xf0\xff\xff\xff\xff\u074c\xff\xf0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\x83\x03\x00\x00\x00\x00\x8c\xa0\x01\x04\x00\x00~\x90\x00\bLMT\x00JDT\x00JST\x00\nJST-9\nP" + + "K\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xf6\xe8]*\xdb\x00\x00\x00\xdb\x00\x00\x00\t\x00\x1c\x00KwajaleinUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00" + + "\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZi" + + "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff~6\x18 \xff\xff\xff\xff\xc1\xed5\xd0\xff\xff\xff" + + "\xff\xc9\xea\n`\xff\xff\xff\xff\xcfF\x81\xf0\xff\xff\xff\xff\xff\x86\x1bP\x00\x00\x00\x00,v\x0e@\x01\x02\x03\x01\x04\x05\x00\x00\x9c\xe0\x00\x00\x00\x00\x9a\xb0\x00\x04\x00\x00\x8c\xa0\x00\b\x00\x00~\x90\x00\f\xff" + + "\xffW@\x00\x10\x00\x00\xa8\xc0\x00\x14LMT\x00+11\x00+10\x00+09\x00-12\x00+12\x00\n<+12>-12\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS_" + + "\u007f2[\xaf\x01\x00\x00\xaf\x01\x00\x00\x05\x00\x1c\x00LibyaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x04\x00\x00\x00\x11\xff\xff\xff\xff\xa1\xf2\xc1$\xff\xff\xff\xffݻ\xb1\x10\xff\xff\xff\xff\xde#\xad`\xff\xff\xff\xff\xe1x\xd2\x10\xff\xff\xff\xff\xe1" + + "\xe7e\xe0\xff\xff\xff\xff\xe5/?p\xff\xff\xff\xff\xe5\xa9\xcc\xe0\xff\xff\xff\xff\xebN\xc6\xf0\x00\x00\x00\x00\x16\x92B`\x00\x00\x00\x00\x17\b\xf7p\x00\x00\x00\x00\x17\xfa+\xe0\x00\x00\x00\x00\x18\xea*\xf0\x00" + + "\x00\x00\x00\x19\xdb_`\x00\x00\x00\x00\x1a̯\xf0\x00\x00\x00\x00\x1b\xbd\xe4`\x00\x00\x00\x00\x1c\xb4z\xf0\x00\x00\x00\x00\x1d\x9f\x17\xe0\x00\x00\x00\x00\x1e\x93\vp\x00\x00\x00\x00\x1f\x82\xee`\x00\x00\x00\x00 " + + "pJp\x00\x00\x00\x00!a~\xe0\x00\x00\x00\x00\"R\xcfp\x00\x00\x00\x00#D\x03\xe0\x00\x00\x00\x00$4\x02\xf0\x00\x00\x00\x00%%7`\x00\x00\x00\x00&@\xb7\xf0\x00\x00\x00\x002N\xf1`\x00" + + "\x00\x00\x003D6p\x00\x00\x00\x0045j\xe0\x00\x00\x00\x00P\x9d\x99\x00\x00\x00\x00\x00QTـ\x00\x00\x00\x00Ri\xb4\x80\x02\x01\x02\x01\x02\x01\x02\x03\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x03\x02\x01\x03\x02\x01\x03\x00\x00\f\\\x00\x00\x00\x00\x1c \x01\x04\x00\x00\x0e\x10\x00\t\x00\x00\x1c \x00\rLMT\x00CEST\x00CET\x00EET\x00\nEET-2\nP" + + "K\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xfe\x9d\x1b\xc9m\x02\x00\x00m\x02\x00\x00\x03\x00\x1c\x00METUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00" + + "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x005\x00\x00\x00\x02\x00\x00\x00\t\xff\xff\xff\xff\x9b\f\x17`\xff\xff\xff\xff\x9b\xd5\xda\xf0\xff\xff\xff\xff\x9cٮ\x90\xff" + + "\xff\xff\xff\x9d\xa4\xb5\x90\xff\xff\xff\xff\x9e\xb9\x90\x90\xff\xff\xff\xff\x9f\x84\x97\x90\xff\xff\xff\xff\xc8\tq\x90\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xff\xcf" + + "\x924\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xff\xd2N@\x90\x00\x00\x00\x00\r\xa4c\x90\x00\x00\x00\x00\x0e\x8b\x1a\x10\x00\x00\x00\x00\x0f\x84E\x90\x00\x00\x00\x00\x10t6\x90\x00" + + "\x00\x00\x00\x11d'\x90\x00\x00\x00\x00\x12T\x18\x90\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17" + + "\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00" + + "\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#\x8f\xfa\xa0\x00\x00\x00\x00?\x9b\x8d\x10\x00\x00\x00\x00@oܠ\x00\x00\x00\x00A\x84\xa9\x90\x00\x00\x00\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b\x90\x00\x00" + + "\x00\x00D/\xa0\xa0\x00\x00\x00\x00EDm\x90\x00\x00\x00\x00F\x0f\x82\xa0\x00\x00\x00\x00G$O\x90\x00\x00\x00\x00G\xf8\x9f \x00\x00\x00\x00I\x041\x90\x00\x00\x00\x00I\u0601 \x00\x00\x00\x00J\xe4" + + "\x13\x90\x00\x00\x00\x00K\x9c\xb3\xa0\x01\x02\x01\x02\x03\x02\x04\x05\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\xff\xff\x92L\x00\x00\xff\xff\x9d\x90\x00\x04\xff\xff\x8f\x80" + + "\x00\b\xff\xff\x9d\x90\x01\f\xff\xff\x9d\x90\x01\x10\xff\xff\x9d\x90\x01\x14LMT\x00MST\x00PST\x00PDT\x00PWT\x00PPT\x00\nPST8PDT,M3.2.0," + + "M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xf5\x8d\x99\x92o\x00\x00\x00o\x00\x00\x00\x03\x00\x1c\x00MSTUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04" + + "\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" + + "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\xff\xff\x9d\x90\x00\x00MST\x00\nMST7\n" + + "PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xe6h\xcac\xb7\x03\x00\x00\xb7\x03\x00\x00\a\x00\x1c\x00MST7MDTUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00" + + "\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif" + + "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00X\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff\x9e\xa6:\x90\xff\xff\xff\xff\x9f\xbb\a\x80\xff\xff\xff\xff" + + "\xa0\x86\x1c\x90\xff\xff\xff\xff\xa1\x9a\xe9\x80\xff\xff\xff\xffˉ\f\x90\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff\xfa\xf8u\x10\xff\xff\xff\xff\xfb\xe8X\x00\xff\xff\xff\xff\xfc\xd8W\x10" + + "\xff\xff\xff\xff\xfd\xc8:\x00\xff\xff\xff\xff\xfe\xb89\x10\xff\xff\xff\xff\xff\xa8\x1c\x00\x00\x00\x00\x00\x00\x98\x1b\x10\x00\x00\x00\x00\x01\x87\xfe\x00\x00\x00\x00\x00\x02w\xfd\x10\x00\x00\x00\x00\x03q\x1a\x80\x00\x00\x00\x00" + + "\x04a\x19\x90\x00\x00\x00\x00\x05P\xfc\x80\x00\x00\x00\x00\x06@\xfb\x90\x00\x00\x00\x00\a0ހ\x00\x00\x00\x00\a\x8d5\x90\x00\x00\x00\x00\t\x10\xc0\x80\x00\x00\x00\x00\t\xad\xb1\x10\x00\x00\x00\x00\n\xf0\xa2\x80" + + "\x00\x00\x00\x00\vࡐ\x00\x00\x00\x00\fٿ\x00\x00\x00\x00\x00\r\xc0\x83\x90\x00\x00\x00\x00\x0e\xb9\xa1\x00\x00\x00\x00\x00\x0f\xa9\xa0\x10\x00\x00\x00\x00\x10\x99\x83\x00\x00\x00\x00\x00\x11\x89\x82\x10\x00\x00\x00\x00" + + "\x12ye\x00\x00\x00\x00\x00\x13id\x10\x00\x00\x00\x00\x14YG\x00\x00\x00\x00\x00\x15IF\x10\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17)(\x10\x00\x00\x00\x00\x18\"E\x80\x00\x00\x00\x00\x19\t\n\x10" + + "\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2&\x90\x00\x00\x00\x00\x1b\xe2\t\x80\x00\x00\x00\x00\x1c\xd2\b\x90\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1\xea\x90\x00\x00\x00\x00\x1f\xa1̀\x00\x00\x00\x00" + + " v\x1d\x10\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xff\x10\x00\x00\x00\x00#j\xcc\x00\x00\x00\x00\x00$5\xe1\x10\x00\x00\x00\x00%J\xae\x00\x00\x00\x00\x00&\x15\xc3\x10\x00\x00\x00\x00'*\x90\x00" + + "\x00\x00\x00\x00'\xfeߐ\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\xde\xc1\x90\x00\x00\x00\x00*\xeaT\x00\x00\x00\x00\x00+\xbe\xa3\x90\x00\x00\x00\x00,\xd3p\x80\x00\x00\x00\x00-\x9e\x85\x90\x00\x00\x00\x00" + + ".\xb3R\x80\x00\x00\x00\x00/~g\x90\x00\x00\x00\x000\x934\x80\x00\x00\x00\x001g\x84\x10\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003Gf\x10\x00\x00\x00\x004R\xf8\x80\x00\x00\x00\x005'H\x10" + + "\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe7\f\x10\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xc6\xee\x10\x00\x00\x00\x00;ۻ\x00\x00\x00\x00\x00" + + "<\xb0\n\x90\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8f\xec\x90\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@oΐ\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00BO\xb0\x90\x00\x00\x00\x00Cd}\x80" + + "\x00\x00\x00\x00D/\x92\x90\x00\x00\x00\x00ED_\x80\x00\x00\x00\x00E\xf3\xc5\x10\x01\x00\x01\x00\x02\x03\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01" + + "\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\xff\xff\x9d\x90\x00\x04\xff\xff" + + "\xab\xa0\x01\x00\xff\xff\xab\xa0\x01\b\xff\xff\xab\xa0\x01\fMDT\x00MST\x00MWT\x00MPT\x00\nMST7MDT,M3.2.0,M11.1.0\nPK\x03\x04" + + "\n\x00\x00\x00\x00\x00#\x82iSV\x80\x94@\x12\x04\x00\x00\x12\x04\x00\x00\x06\x00\x1c\x00NavajoUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00" + + "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00a\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff^\x04\f\xb0\xff\xff\xff\xff\x9e\xa6:\x90\xff\xff\xff\xff\x9f\xbb\a\x80\xff" + + "\xff\xff\xff\xa0\x86\x1c\x90\xff\xff\xff\xff\xa1\x9a\xe9\x80\xff\xff\xff\xff\xa2e\xfe\x90\xff\xff\xff\xff\xa3\x84\x06\x00\xff\xff\xff\xff\xa4E\xe0\x90\xff\xff\xff\xff\xa4\x8f\xa6\x80\xff\xff\xff\xffˉ\f\x90\xff\xff\xff\xff\xd2" + + "#\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff\xf7/v\x90\xff\xff\xff\xff\xf8(\x94\x00\xff\xff\xff\xff\xf9\x0fX\x90\xff\xff\xff\xff\xfa\bv\x00\xff\xff\xff\xff\xfa\xf8u\x10\xff\xff\xff\xff\xfb\xe8X\x00\xff" + + "\xff\xff\xff\xfc\xd8W\x10\xff\xff\xff\xff\xfd\xc8:\x00\xff\xff\xff\xff\xfe\xb89\x10\xff\xff\xff\xff\xff\xa8\x1c\x00\x00\x00\x00\x00\x00\x98\x1b\x10\x00\x00\x00\x00\x01\x87\xfe\x00\x00\x00\x00\x00\x02w\xfd\x10\x00\x00\x00\x00\x03" + + "q\x1a\x80\x00\x00\x00\x00\x04a\x19\x90\x00\x00\x00\x00\x05P\xfc\x80\x00\x00\x00\x00\x06@\xfb\x90\x00\x00\x00\x00\a0ހ\x00\x00\x00\x00\a\x8d5\x90\x00\x00\x00\x00\t\x10\xc0\x80\x00\x00\x00\x00\t\xad\xb1\x10\x00" + + "\x00\x00\x00\n\xf0\xa2\x80\x00\x00\x00\x00\vࡐ\x00\x00\x00\x00\fٿ\x00\x00\x00\x00\x00\r\xc0\x83\x90\x00\x00\x00\x00\x0e\xb9\xa1\x00\x00\x00\x00\x00\x0f\xa9\xa0\x10\x00\x00\x00\x00\x10\x99\x83\x00\x00\x00\x00\x00\x11" + + "\x89\x82\x10\x00\x00\x00\x00\x12ye\x00\x00\x00\x00\x00\x13id\x10\x00\x00\x00\x00\x14YG\x00\x00\x00\x00\x00\x15IF\x10\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17)(\x10\x00\x00\x00\x00\x18\"E\x80\x00" + + "\x00\x00\x00\x19\t\n\x10\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2&\x90\x00\x00\x00\x00\x1b\xe2\t\x80\x00\x00\x00\x00\x1c\xd2\b\x90\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1\xea\x90\x00\x00\x00\x00\x1f" + + "\xa1̀\x00\x00\x00\x00 v\x1d\x10\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xff\x10\x00\x00\x00\x00#j\xcc\x00\x00\x00\x00\x00$5\xe1\x10\x00\x00\x00\x00%J\xae\x00\x00\x00\x00\x00&\x15\xc3\x10\x00" + + "\x00\x00\x00'*\x90\x00\x00\x00\x00\x00'\xfeߐ\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\xde\xc1\x90\x00\x00\x00\x00*\xeaT\x00\x00\x00\x00\x00+\xbe\xa3\x90\x00\x00\x00\x00,\xd3p\x80\x00\x00\x00\x00-" + + "\x9e\x85\x90\x00\x00\x00\x00.\xb3R\x80\x00\x00\x00\x00/~g\x90\x00\x00\x00\x000\x934\x80\x00\x00\x00\x001g\x84\x10\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003Gf\x10\x00\x00\x00\x004R\xf8\x80\x00" + + "\x00\x00\x005'H\x10\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe7\f\x10\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xc6\xee\x10\x00\x00\x00\x00;" + + "ۻ\x00\x00\x00\x00\x00<\xb0\n\x90\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8f\xec\x90\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@oΐ\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00BO\xb0\x90\x00" + + "\x00\x00\x00Cd}\x80\x00\x00\x00\x00D/\x92\x90\x00\x00\x00\x00ED_\x80\x00\x00\x00\x00E\xf3\xc5\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\x9d\x94\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\f\xff\xff\xab\xa0\x01\x10LMT\x00MDT\x00MST\x00MWT\x00MPT\x00\nM" + + "ST7MDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSb\xb2\xaf\xf7\x13\x04\x00\x00\x13\x04\x00\x00\x02\x00\x1c\x00NZUT\t\x00\x03\x82" + + "\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x00\x00\x00\x06\x00\x00\x00\x13\xff\xff\xff" + + "\xffA\xb7L\xa8\xff\xff\xff\xff\xb0\xb4\xb2\xe8\xff\xff\xff\xff\xb1Q\x87X\xff\xff\xff\xff\xb2x\xe5h\xff\xff\xff\xff\xb3C\xe5`\xff\xff\xff\xff\xb4X\xc7h\xff\xff\xff\xff\xb5#\xc7`\xff\xff\xff\xff\xb68\xa9" + + "h\xff\xff\xff\xff\xb7\x03\xa9`\xff\xff\xff\xff\xb8\x18\x8bh\xff\xff\xff\xff\xb8\xec\xc5\xe0\xff\xff\xff\xff\xb9\xf8mh\xff\xff\xff\xff\xba̧\xe0\xff\xff\xff\xff\xbb\xd8Oh\xff\xff\xff\xff\xbc\xe3\xe8\xe0\xff\xff\xff" + + "\xff\xbd\xae\xf6\xe8\xff\xff\xff\xff\xbe\xc3\xca\xe0\xff\xff\xff\xff\xbf\x8e\xd8\xe8\xff\xff\xff\xff\xc0\xa3\xac\xe0\xff\xff\xff\xff\xc1n\xba\xe8\xff\xff\xff\xff\u0083\x8e\xe0\xff\xff\xff\xff\xc3N\x9c\xe8\xff\xff\xff\xff\xc4cp" + + "\xe0\xff\xff\xff\xff\xc5.~\xe8\xff\xff\xff\xff\xc6L\x8d`\xff\xff\xff\xff\xc7\x0e`\xe8\xff\xff\xff\xff\xc8,o`\xff\xff\xff\xff\xc8\xf7}h\xff\xff\xff\xff\xd2ښ@\x00\x00\x00\x00\t\x18\xfd\xe0\x00\x00\x00" + + "\x00\t\xac\xa5\xe0\x00\x00\x00\x00\n\xef\xa5`\x00\x00\x00\x00\v\x9e\xfc\xe0\x00\x00\x00\x00\f\xd8\xc1\xe0\x00\x00\x00\x00\r~\xde\xe0\x00\x00\x00\x00\x0e\xb8\xa3\xe0\x00\x00\x00\x00\x0f^\xc0\xe0\x00\x00\x00\x00\x10\x98\x85" + + "\xe0\x00\x00\x00\x00\x11>\xa2\xe0\x00\x00\x00\x00\x12xg\xe0\x00\x00\x00\x00\x13\x1e\x84\xe0\x00\x00\x00\x00\x14XI\xe0\x00\x00\x00\x00\x14\xfef\xe0\x00\x00\x00\x00\x168+\xe0\x00\x00\x00\x00\x16\xe7\x83`\x00\x00\x00" + + "\x00\x18!H`\x00\x00\x00\x00\x18\xc7e`\x00\x00\x00\x00\x1a\x01*`\x00\x00\x00\x00\x1a\xa7G`\x00\x00\x00\x00\x1b\xe1\f`\x00\x00\x00\x00\x1c\x87)`\x00\x00\x00\x00\x1d\xc0\xee`\x00\x00\x00\x00\x1eg\v" + + "`\x00\x00\x00\x00\x1f\xa0\xd0`\x00\x00\x00\x00 F\xed`\x00\x00\x00\x00!\x80\xb2`\x00\x00\x00\x00\"0\t\xe0\x00\x00\x00\x00#i\xce\xe0\x00\x00\x00\x00$\x0f\xeb\xe0\x00\x00\x00\x00%.\x01`\x00\x00\x00" + + "\x00&\x02B\xe0\x00\x00\x00\x00'\r\xe3`\x00\x00\x00\x00'\xe2$\xe0\x00\x00\x00\x00(\xed\xc5`\x00\x00\x00\x00)\xc2\x06\xe0\x00\x00\x00\x00*ͧ`\x00\x00\x00\x00+\xab#`\x00\x00\x00\x00,\xad\x89" + + "`\x00\x00\x00\x00-\x8b\x05`\x00\x00\x00\x00.\x8dk`\x00\x00\x00\x00/j\xe7`\x00\x00\x00\x000mM`\x00\x00\x00\x001J\xc9`\x00\x00\x00\x002Vi\xe0\x00\x00\x00\x003*\xab`\x00\x00\x00" + + "\x0046K\xe0\x00\x00\x00\x005\n\x8d`\x00\x00\x00\x006\x16-\xe0\x00\x00\x00\x006\xf3\xa9\xe0\x00\x00\x00\x007\xf6\x0f\xe0\x00\x00\x00\x008Ӌ\xe0\x00\x00\x00\x009\xd5\xf1\xe0\x00\x00\x00\x00:\xb3m" + + "\xe0\x00\x00\x00\x00;\xbf\x0e`\x00\x00\x00\x00<\x93O\xe0\x00\x00\x00\x00=\x9e\xf0`\x00\x00\x00\x00>s1\xe0\x00\x00\x00\x00?~\xd2`\x00\x00\x00\x00@\\N`\x00\x00\x00\x00A^\xb4`\x00\x00\x00" + + "\x00B<0`\x00\x00\x00\x00C>\x96`\x00\x00\x00\x00D\x1c\x12`\x00\x00\x00\x00E\x1ex`\x00\x00\x00\x00E\xfb\xf4`\x00\x00\x00\x00F\xfeZ`\x02\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05" + + "\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x00\x00\xa3\xd8\x00\x00\x00\x00\xaf\xc8\x01\x04\x00\x00\xa1\xb8\x00\t\x00\x00\xa8\xc0\x01\x04\x00\x00\xb6\xd0\x01\x0e\x00\x00\xa8\xc0\x00\x04LMT" + + "\x00NZST\x00NZMT\x00NZDT\x00\nNZST-12NZDT,M9.5.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x96" + + "\xc5FF(\x03\x00\x00(\x03\x00\x00\a\x00\x1c\x00NZ-CHATUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00E\x00\x00\x00\x04\x00\x00\x00\x16\xff\xff\xff\xffA\xb7D\x84\xff\xff\xff\xff\xd2ږ\xbc\x00\x00\x00\x00\t\x18\xfd\xe0\x00\x00\x00\x00\t\xac\xa5\xe0\x00\x00\x00" + + "\x00\n\xef\xa5`\x00\x00\x00\x00\v\x9e\xfc\xe0\x00\x00\x00\x00\f\xd8\xc1\xe0\x00\x00\x00\x00\r~\xde\xe0\x00\x00\x00\x00\x0e\xb8\xa3\xe0\x00\x00\x00\x00\x0f^\xc0\xe0\x00\x00\x00\x00\x10\x98\x85\xe0\x00\x00\x00\x00\x11>\xa2" + + "\xe0\x00\x00\x00\x00\x12xg\xe0\x00\x00\x00\x00\x13\x1e\x84\xe0\x00\x00\x00\x00\x14XI\xe0\x00\x00\x00\x00\x14\xfef\xe0\x00\x00\x00\x00\x168+\xe0\x00\x00\x00\x00\x16\xe7\x83`\x00\x00\x00\x00\x18!H`\x00\x00\x00" + + "\x00\x18\xc7e`\x00\x00\x00\x00\x1a\x01*`\x00\x00\x00\x00\x1a\xa7G`\x00\x00\x00\x00\x1b\xe1\f`\x00\x00\x00\x00\x1c\x87)`\x00\x00\x00\x00\x1d\xc0\xee`\x00\x00\x00\x00\x1eg\v`\x00\x00\x00\x00\x1f\xa0\xd0" + + "`\x00\x00\x00\x00 F\xed`\x00\x00\x00\x00!\x80\xb2`\x00\x00\x00\x00\"0\t\xe0\x00\x00\x00\x00#i\xce\xe0\x00\x00\x00\x00$\x0f\xeb\xe0\x00\x00\x00\x00%.\x01`\x00\x00\x00\x00&\x02B\xe0\x00\x00\x00" + + "\x00'\r\xe3`\x00\x00\x00\x00'\xe2$\xe0\x00\x00\x00\x00(\xed\xc5`\x00\x00\x00\x00)\xc2\x06\xe0\x00\x00\x00\x00*ͧ`\x00\x00\x00\x00+\xab#`\x00\x00\x00\x00,\xad\x89`\x00\x00\x00\x00-\x8b\x05" + + "`\x00\x00\x00\x00.\x8dk`\x00\x00\x00\x00/j\xe7`\x00\x00\x00\x000mM`\x00\x00\x00\x001J\xc9`\x00\x00\x00\x002Vi\xe0\x00\x00\x00\x003*\xab`\x00\x00\x00\x0046K\xe0\x00\x00\x00" + + "\x005\n\x8d`\x00\x00\x00\x006\x16-\xe0\x00\x00\x00\x006\xf3\xa9\xe0\x00\x00\x00\x007\xf6\x0f\xe0\x00\x00\x00\x008Ӌ\xe0\x00\x00\x00\x009\xd5\xf1\xe0\x00\x00\x00\x00:\xb3m\xe0\x00\x00\x00\x00;\xbf\x0e" + + "`\x00\x00\x00\x00<\x93O\xe0\x00\x00\x00\x00=\x9e\xf0`\x00\x00\x00\x00>s1\xe0\x00\x00\x00\x00?~\xd2`\x00\x00\x00\x00@\\N`\x00\x00\x00\x00A^\xb4`\x00\x00\x00\x00B<0`\x00\x00\x00" + + "\x00C>\x96`\x00\x00\x00\x00D\x1c\x12`\x00\x00\x00\x00E\x1ex`\x00\x00\x00\x00E\xfb\xf4`\x00\x00\x00\x00F\xfeZ`\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x00\x00\xab\xfc\x00\x00\x00\x00\xacD\x00\x04\x00\x00" + + "\xc1\\\x01\n\x00\x00\xb3L\x00\x10LMT\x00+1215\x00+1345\x00+1245\x00\n<+1245>-12:45<+1345>,M9.5.0" + + "/2:45,M4.1.0/3:45\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\x00\x1c\x00Pacific/UT\t\x00" + + "\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x91\xd60\f\x9a\x00\x00\x00\x9a\x00\x00\x00\f\x00\x1c\x00Pacifi" + + "c/NiueUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\a\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xfft\xe0p\xbe\xff\xff\xff\xff\xbb\x05CH\xff\xff\xff\xff\xbb!qX\xff\xff\xff\xffˉ=\xc8\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2aI8\xff\xff\xff" + - "\xffՍsH\x01\x02\x01\x03\x04\x01\x05\xff\xffl\x02\x00\x00\xff\xfflX\x00\x04\xff\xffzh\x01\b\xff\xffzh\x01\f\xff\xffzh\x01\x10\xff\xffs`\x00\x04LMT\x00HST\x00HDT\x00" + - "HWT\x00HPT\x00\nHST10\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xca\"\xb8i\xda\x00\x00\x00\xda\x00\x00\x00\x0e\x00\x1c\x00Pacific/MajuroU" + - "T\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x05\x00\x00" + - "\x00\x14\xff\xff\xff\xff~6\x14\x80\xff\xff\xff\xff\x98\x11\x95\xd0\xff\xff\xff\xff\xa09\xf9\xf0\xff\xff\xff\xff\xc1\xed5\xd0\xff\xff\xff\xff\xc9\xea\n`\xff\xff\xff\xff\xcf=Gp\xff\xff\xff\xff\xff\x86\x1bP\x01\x02" + - "\x01\x03\x02\x01\x04\x00\x00\xa0\x80\x00\x00\x00\x00\x9a\xb0\x00\x04\x00\x00~\x90\x00\b\x00\x00\x8c\xa0\x00\f\x00\x00\xa8\xc0\x00\x10LMT\x00+11\x00+09\x00+10\x00+12\x00\n<+12" + - ">-12\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rt\xca{e\x92\x00\x00\x00\x92\x00\x00\x00\x11\x00\x1c\x00Pacific/Pago_PagoUT\t\x00\x03\x15\xac\x0e" + - "`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" + + "\x02\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xffߡjL\xff\xff\xff\xff\xf5\xa6\xb8`\x01\x02\xff\xff`\xb4\x00\x00\xff\xff`\xa0\x00\x04\xff\xffeP\x00\nLMT\x00-1120\x00-11\x00\n" + + "<-11>11\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSt\xca{e\x92\x00\x00\x00\x92\x00\x00\x00\x0e\x00\x1c\x00Pacific/MidwayUT\t\x00\x03\x82\x0f\x8b" + + "a\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" + "\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\b\xff\xff\xff\xffn" + - "=\xc8\b\xff\xff\xff\xff\x91\x05\xfb\b\x01\x02\x00\x00\xb1x\x00\x00\xff\xff_\xf8\x00\x00\xff\xffeP\x00\x04LMT\x00SST\x00\nSST11\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R" + - "\x9e\u007f\xab\x95V\x01\x00\x00V\x01\x00\x00\r\x00\x1c\x00Pacific/EfateUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZi" + + "=\xc8\b\xff\xff\xff\xff\x91\x05\xfb\b\x01\x02\x00\x00\xb1x\x00\x00\xff\xff_\xf8\x00\x00\xff\xffeP\x00\x04LMT\x00SST\x00\nSST11\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS" + + "\x80\xf8vܔ\x00\x00\x00\x94\x00\x00\x00\r\x00\x1c\x00Pacific/PalauUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZi" + "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x92\xf5´\x00\x00\x00\x00\ay\x99@\x00\x00\x00\x00\a\xfa\xcc@\x00\x00\x00\x00" + - "\x19\xd2\xf7\xd0\x00\x00\x00\x00\x1a\xc2\xda\xc0\x00\x00\x00\x00\x1b\xb2\xd9\xd0\x00\x00\x00\x00\x1c\xa2\xbc\xc0\x00\x00\x00\x00\x1d\x9b\xf6P\x00\x00\x00\x00\x1e\x82\x9e\xc0\x00\x00\x00\x00\x1f{\xd8P\x00\x00\x00\x00 k\xbb@" + - "\x00\x00\x00\x00![\xbaP\x00\x00\x00\x00\"K\x9d@\x00\x00\x00\x00#;\x9cP\x00\x00\x00\x00$+\u007f@\x00\x00\x00\x00%\x1b~P\x00\x00\x00\x00&\va@\x00\x00\x00\x00&\xfb`P\x00\x00\x00\x00" + - "'\xebC@\x00\x00\x00\x00(\xe4|\xd0\x00\x00\x00\x00)\x81Q@\x00\x00\x00\x00*\xe9H\xd0\x00\x00\x00\x00+a3@\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00" + - "\x00\x9d\xcc\x00\x00\x00\x00\xa8\xc0\x01\x04\x00\x00\x9a\xb0\x00\bLMT\x00+12\x00+11\x00\n<+11>-11\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xc8=ku\xae\x00\x00" + - "\x00\xae\x00\x00\x00\x12\x00\x1c\x00Pacific/KiritimatiUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\b\xff\xff\xff\xff\x14\xe1\xcfl\xff\xff\xff\xff~66\xec\x01\x02\xff\xff,\x94\x00\x00\x00\x00~\x14" + + "\x00\x00\x00\x00~\x90\x00\x04LMT\x00+09\x00\n<+09>-9\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x97F\x91\xb3\xed\x00\x00\x00\xed\x00\x00\x00\x11\x00\x1c\x00Pacif" + + "ic/TongatapuUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xff\xd2E\x9c@\xff\xff\xff\xff\xef\x11\xe0\x10\x00\x00\x00\x007\xfbG\xd0\x00\x00\x00\x008\xd3}\xd0\x00\x00\x00\x00:\x04\bP\x00\x00\x00\x00:" + + "r\xb8@\x00\x00\x00\x00;\xe3\xeaP\x00\x00\x00\x00-13\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xec =\x89\xac\x00\x00\x00\xac" + + "\x00\x00\x00\x11\x00\x1c\x00Pacific/EnderburyUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff\xc3,ۀ\x00\x00\x00\x00\x12V\x04\xc0\x00\x00\x00\x00/\x059\xb0\x01\x02\x03\x00\x00\x00\x00\x00\x00" + + "\xff\xffW@\x00\x04\xff\xffeP\x00\b\x00\x00\xb6\xd0\x00\f-00\x00-12\x00-11\x00+13\x00\n<+13>-13\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x9e\u007f" + + "\xab\x95V\x01\x00\x00V\x01\x00\x00\r\x00\x1c\x00Pacific/EfateUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xff~7H\x80\x00\x00\x00\x00\x12U\xf2\x00\x00\x00\x00\x00/\x05+\xa0\x01\x02\x03\xff\xffl" + - "\x80\x00\x00\xff\xffj\x00\x00\x04\xff\xffs`\x00\n\x00\x00\xc4\xe0\x00\x0eLMT\x00-1040\x00-10\x00+14\x00\n<+14>-14\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1" + - "c9R\x8a|\xdcU\x99\x00\x00\x00\x99\x00\x00\x00\x0f\x00\x1c\x00Pacific/FakaofoUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03" + - "\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff~7U\x88\x00\x00\x00\x00N\xfd\x99\xb0\x01\x02\xff\xff_x\x00" + - "\x00\xff\xffeP\x00\x04\x00\x00\xb6\xd0\x00\bLMT\x00-11\x00+13\x00\n<+13>-13\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x96\xc5FF(\x03\x00\x00(\x03\x00" + - "\x00\x0f\x00\x1c\x00Pacific/ChathamUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00E\x00\x00\x00\x04\x00\x00\x00\x16\xff\xff\xff\xffA\xb7D\x84\xff\xff\xff\xff\xd2ږ\xbc\x00\x00\x00\x00\t\x18\xfd\xe0\x00\x00\x00\x00\t\xac\xa5\xe0\x00\x00\x00\x00\n" + - "\xef\xa5`\x00\x00\x00\x00\v\x9e\xfc\xe0\x00\x00\x00\x00\f\xd8\xc1\xe0\x00\x00\x00\x00\r~\xde\xe0\x00\x00\x00\x00\x0e\xb8\xa3\xe0\x00\x00\x00\x00\x0f^\xc0\xe0\x00\x00\x00\x00\x10\x98\x85\xe0\x00\x00\x00\x00\x11>\xa2\xe0\x00" + - "\x00\x00\x00\x12xg\xe0\x00\x00\x00\x00\x13\x1e\x84\xe0\x00\x00\x00\x00\x14XI\xe0\x00\x00\x00\x00\x14\xfef\xe0\x00\x00\x00\x00\x168+\xe0\x00\x00\x00\x00\x16\xe7\x83`\x00\x00\x00\x00\x18!H`\x00\x00\x00\x00\x18" + - "\xc7e`\x00\x00\x00\x00\x1a\x01*`\x00\x00\x00\x00\x1a\xa7G`\x00\x00\x00\x00\x1b\xe1\f`\x00\x00\x00\x00\x1c\x87)`\x00\x00\x00\x00\x1d\xc0\xee`\x00\x00\x00\x00\x1eg\v`\x00\x00\x00\x00\x1f\xa0\xd0`\x00" + - "\x00\x00\x00 F\xed`\x00\x00\x00\x00!\x80\xb2`\x00\x00\x00\x00\"0\t\xe0\x00\x00\x00\x00#i\xce\xe0\x00\x00\x00\x00$\x0f\xeb\xe0\x00\x00\x00\x00%.\x01`\x00\x00\x00\x00&\x02B\xe0\x00\x00\x00\x00'" + - "\r\xe3`\x00\x00\x00\x00'\xe2$\xe0\x00\x00\x00\x00(\xed\xc5`\x00\x00\x00\x00)\xc2\x06\xe0\x00\x00\x00\x00*ͧ`\x00\x00\x00\x00+\xab#`\x00\x00\x00\x00,\xad\x89`\x00\x00\x00\x00-\x8b\x05`\x00" + - "\x00\x00\x00.\x8dk`\x00\x00\x00\x00/j\xe7`\x00\x00\x00\x000mM`\x00\x00\x00\x001J\xc9`\x00\x00\x00\x002Vi\xe0\x00\x00\x00\x003*\xab`\x00\x00\x00\x0046K\xe0\x00\x00\x00\x005" + - "\n\x8d`\x00\x00\x00\x006\x16-\xe0\x00\x00\x00\x006\xf3\xa9\xe0\x00\x00\x00\x007\xf6\x0f\xe0\x00\x00\x00\x008Ӌ\xe0\x00\x00\x00\x009\xd5\xf1\xe0\x00\x00\x00\x00:\xb3m\xe0\x00\x00\x00\x00;\xbf\x0e`\x00" + - "\x00\x00\x00<\x93O\xe0\x00\x00\x00\x00=\x9e\xf0`\x00\x00\x00\x00>s1\xe0\x00\x00\x00\x00?~\xd2`\x00\x00\x00\x00@\\N`\x00\x00\x00\x00A^\xb4`\x00\x00\x00\x00B<0`\x00\x00\x00\x00C" + - ">\x96`\x00\x00\x00\x00D\x1c\x12`\x00\x00\x00\x00E\x1ex`\x00\x00\x00\x00E\xfb\xf4`\x00\x00\x00\x00F\xfeZ`\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x00\x00\xab\xfc\x00\x00\x00\x00\xacD\x00\x04\x00\x00\xc1\\" + - "\x01\n\x00\x00\xb3L\x00\x10LMT\x00+1215\x00+1345\x00+1245\x00\n<+1245>-12:45<+1345>,M9.5.0/2" + - ":45,M4.1.0/3:45\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xf6\xe8]*\xdb\x00\x00\x00\xdb\x00\x00\x00\x11\x00\x1c\x00Pacific/Kwajal" + - "einUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00" + - "\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff~6\x18 \xff\xff\xff\xff\xc1\xed5\xd0\xff\xff\xff\xff\xc9\xea\n`\xff\xff\xff\xff\xcfF\x81\xf0\xff\xff\xff\xff\xff\x86\x1bP\x00\x00\x00\x00,v\x0e@\x01\x02\x03\x01\x04\x05" + - "\x00\x00\x9c\xe0\x00\x00\x00\x00\x9a\xb0\x00\x04\x00\x00\x8c\xa0\x00\b\x00\x00~\x90\x00\f\xff\xffW@\x00\x10\x00\x00\xa8\xc0\x00\x14LMT\x00+11\x00+10\x00+09\x00-12\x00+12\x00" + - "\n<+12>-12\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rt\xca{e\x92\x00\x00\x00\x92\x00\x00\x00\x0e\x00\x1c\x00Pacific/MidwayUT\t\x00\x03\x15" + - "\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\b\xff\xff\xff" + - "\xffn=\xc8\b\xff\xff\xff\xff\x91\x05\xfb\b\x01\x02\x00\x00\xb1x\x00\x00\xff\xff_\xf8\x00\x00\xff\xffeP\x00\x04LMT\x00SST\x00\nSST11\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c" + - "9R1\xce_(\x86\x00\x00\x00\x86\x00\x00\x00\x0e\x00\x1c\x00Pacific/WallisUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00" + - "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff~6\b\xa8\x01\x00\x00\xacX\x00\x00\x00\x00\xa8\xc0\x00\x04LMT\x00" + - "+12\x00\n<+12>-12\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R4\xd0Yӣ\x01\x00\x00\xa3\x01\x00\x00\f\x00\x1c\x00Pacific/FijiUT\t\x00" + - "\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00\x03\x00\x00\x00\f\xff" + - "\xff\xff\xff\x9a\x13\xb1\xc0\x00\x00\x00\x006;\x17\xe0\x00\x00\x00\x006\xd7\xfa`\x00\x00\x00\x008$4`\x00\x00\x00\x008\xb7\xdc`\x00\x00\x00\x00K\x11,\xe0\x00\x00\x00\x00K\xae\x0f`\x00\x00\x00\x00L" + - "\xc2\xea`\x00\x00\x00\x00MrA\xe0\x00\x00\x00\x00N\xa2\xcc`\x00\x00\x00\x00O\x1a\xc4\xe0\x00\x00\x00\x00P\x82\xae`\x00\x00\x00\x00P\xfa\xa6\xe0\x00\x00\x00\x00Rk\xca\xe0\x00\x00\x00\x00R\xdaz\xd0\x00" + - "\x00\x00\x00TT\xe7`\x00\x00\x00\x00T\xbaj\xe0\x00\x00\x00\x00V4\xc9`\x00\x00\x00\x00V\x9aL\xe0\x00\x00\x00\x00X\x1d\xe5\xe0\x00\x00\x00\x00Xz.\xe0\x00\x00\x00\x00Y\xfd\xc7\xe0\x00\x00\x00\x00Z" + - "Z\x10\xe0\x00\x00\x00\x00[ݩ\xe0\x00\x00\x00\x00\\9\xf2\xe0\x00\x00\x00\x00]\xc6\xc6`\x00\x00\x00\x00^\x19\xd4\xe0\x00\x00\x00\x00_\xde\a`\x00\x00\x00\x00`\x02\xf1`\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\xa7\xc0\x00\x00\x00\x00\xb6\xd0\x01\x04\x00\x00\xa8\xc0\x00\bLMT\x00+13\x00+12\x00\n<+12>-12<" + - "+13>,M11.2.0,M1.2.3/99\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xe9\xdd\x1e\xee\f\x01\x00\x00\f\x01\x00\x00\f\x00\x1c\x00Pacific" + - "/ApiaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b" + - "\x00\x00\x00\a\x00\x00\x00\x1a\xff\xff\xff\xffn=\xc9\x00\xff\xff\xff\xff\x91\x05\xfc\x00\xff\xff\xff\xff\xdab\x048\x00\x00\x00\x00L\x9f'\xb0\x00\x00\x00\x00M\x97+\xe0\x00\x00\x00\x00N}\xe2`\x00\x00\x00\x00" + - "N\xfd\x8b\xa0\x00\x00\x00\x00Ow\r\xe0\x01\x02\x04\x03\x04\x03\x06\x05\x00\x00\xb0\x80\x00\x00\xff\xff_\x00\x00\x00\xff\xff^H\x00\x04\xff\xffs`\x01\n\xff\xffeP\x00\x0e\x00\x00\xb6\xd0\x00\x12\x00\x00\xc4\xe0" + - "\x01\x16LMT\x00-1130\x00-10\x00-11\x00+13\x00+14\x00\n<+13>-13<+14>,M9.5.0/3,M4.1.0/4" + - "\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xcc\xf39a\xc3\x00\x00\x00\xc3\x00\x00\x00\v\x00\x1c\x00Pacific/YapUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01" + - "\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00" + - "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\f\xff\xff\xff\xff\x14\xe1\xbf4\xff\xff\xff\xff~6&" + - "\xb4\xff\xff\xff\xff\x98\x11\xa3\xe0\xff\xff\xff\xff\xa09\xf9\xf0\xff\xff\xff\xff\xc9\xea\n`\xff\xff\xff\xff\xd2\x11\x0e\xf0\x01\x02\x03\x02\x03\x02\xff\xff<\xcc\x00\x00\x00\x00\x8eL\x00\x00\x00\x00\x8c\xa0\x00\x04\x00\x00~" + - "\x90\x00\bLMT\x00+10\x00+09\x00\n<+10>-10\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rn\x04\x19y\x9a\x00\x00\x00\x9a\x00\x00\x00\x14\x00\x1c\x00Pacif" + - "ic/Port_MoresbyUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff\xffV\xb6Z\b\xff\xff\xff\xffr\xed\xa4\x90\x01\x02\x00\x00\x89\xf8\x00\x00\x00\x00\x89\xf0\x00\x04\x00\x00\x8c\xa0\x00\tLMT\x00PM" + - "MT\x00+10\x00\n<+10>-10\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xeaK\x85v\xdd\x00\x00\x00\xdd\x00\x00\x00\x10\x00\x1c\x00Pacific/Honol" + - "uluUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x00" + - "\x00\x06\x00\x00\x00\x14\xff\xff\xff\xfft\xe0p\xbe\xff\xff\xff\xff\xbb\x05CH\xff\xff\xff\xff\xbb!qX\xff\xff\xff\xffˉ=\xc8\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2aI8\xff\xff\xff\xffՍ" + - "sH\x01\x02\x01\x03\x04\x01\x05\xff\xffl\x02\x00\x00\xff\xfflX\x00\x04\xff\xffzh\x01\b\xff\xffzh\x01\f\xff\xffzh\x01\x10\xff\xffs`\x00\x04LMT\x00HST\x00HDT\x00HWT" + - "\x00HPT\x00\nHST10\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\u07b54-\xd6\x00\x00\x00\xd6\x00\x00\x00\x0f\x00\x1c\x00Pacific/PohnpeiUT\t" + - "\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x05\x00\x00\x00\x10" + - "\xff\xff\xff\xff\x14\xe1\xb9,\xff\xff\xff\xff~6 \xac\xff\xff\xff\xff\x98\x11\x95\xd0\xff\xff\xff\xff\xa09\xf9\xf0\xff\xff\xff\xff\xc1\xed5\xd0\xff\xff\xff\xff\xc9\xea\n`\xff\xff\xff\xff\xd2\x11\x0e\xf0\x01\x02\x03\x02" + - "\x04\x03\x02\xff\xffB\xd4\x00\x00\x00\x00\x94T\x00\x00\x00\x00\x9a\xb0\x00\x04\x00\x00~\x90\x00\b\x00\x00\x8c\xa0\x00\fLMT\x00+11\x00+09\x00+10\x00\n<+11>-11\nP" + - "K\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xc23\xa0\xbc\x84\x00\x00\x00\x84\x00\x00\x00\x0f\x00\x1c\x00Pacific/GambierUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v" + - "\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00" + - "\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x94PH\x04\x01\xff\xff\x81|" + - "\x00\x00\xff\xff\x81p\x00\x04LMT\x00-09\x00\n<-09>9\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xe2;Z\xf7\xb7\x00\x00\x00\xb7\x00\x00\x00\r\x00\x1c\x00Pacifi" + - "c/NauruUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x04\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xff\xa3\xe7+\x04\xff\xff\xff\xff̐\xe9\xc8\xff\xff\xff\xff\xd2C'\xf0\x00\x00\x00\x00\x11!\xa8\xe8\x01\x02\x01\x03\x00\x00\x9c|\x00\x00\x00\x00\xa1\xb8\x00\x04\x00\x00" + - "~\x90\x00\n\x00\x00\xa8\xc0\x00\x0eLMT\x00+1130\x00+09\x00+12\x00\n<+12>-12\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x97n7\x1a\xf2\x00\x00\x00" + - "\xf2\x00\x00\x00\x0e\x00\x1c\x00Pacific/KosraeUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x92\xf5´\x00\x00\x00\x00\ay\x99@\x00\x00\x00\x00\a\xfa\xcc@\x00\x00\x00\x00\x19\xd2" + + "\xf7\xd0\x00\x00\x00\x00\x1a\xc2\xda\xc0\x00\x00\x00\x00\x1b\xb2\xd9\xd0\x00\x00\x00\x00\x1c\xa2\xbc\xc0\x00\x00\x00\x00\x1d\x9b\xf6P\x00\x00\x00\x00\x1e\x82\x9e\xc0\x00\x00\x00\x00\x1f{\xd8P\x00\x00\x00\x00 k\xbb@\x00\x00" + + "\x00\x00![\xbaP\x00\x00\x00\x00\"K\x9d@\x00\x00\x00\x00#;\x9cP\x00\x00\x00\x00$+\u007f@\x00\x00\x00\x00%\x1b~P\x00\x00\x00\x00&\va@\x00\x00\x00\x00&\xfb`P\x00\x00\x00\x00'\xeb" + + "C@\x00\x00\x00\x00(\xe4|\xd0\x00\x00\x00\x00)\x81Q@\x00\x00\x00\x00*\xe9H\xd0\x00\x00\x00\x00+a3@\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00\x9d" + + "\xcc\x00\x00\x00\x00\xa8\xc0\x01\x04\x00\x00\x9a\xb0\x00\bLMT\x00+12\x00+11\x00\n<+11>-11\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x8a|\xdcU\x99\x00\x00\x00\x99" + + "\x00\x00\x00\x0f\x00\x1c\x00Pacific/FakaofoUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xff\x14ᴴ\xff\xff\xff\xff~6\x1c4\xff\xff\xff\xff\x98\x11\x95\xd0\xff\xff\xff\xff\xa09\xf9\xf0\xff\xff\xff" + - "\xff\xc1\xed5\xd0\xff\xff\xff\xff\xc9\xea\n`\xff\xff\xff\xff\xd2\x11\x0e\xf0\xff\xff\xff\xff\xff\x86\x1bP\x00\x00\x00\x006\x8bg@\x01\x02\x03\x02\x04\x03\x02\x05\x02\xff\xffGL\x00\x00\x00\x00\x98\xcc\x00\x00\x00\x00" + - "\x9a\xb0\x00\x04\x00\x00~\x90\x00\b\x00\x00\x8c\xa0\x00\f\x00\x00\xa8\xc0\x00\x10LMT\x00+11\x00+09\x00+10\x00+12\x00\n<+11>-11\nPK\x03\x04\n\x00\x00\x00" + - "\x00\x00\xf1c9R\x85v\xf8\x8c\x87\x01\x00\x00\x87\x01\x00\x00\x11\x00\x1c\x00Pacific/RarotongaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03" + - "\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + - "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1b\x00\x00\x00\x04\x00\x00\x00\x14\xff\xff\xff\xff~7J\xc8\x00\x00\x00\x00\x10\xac\x1b(\x00\x00" + - "\x00\x00\x11?\xb5\x18\x00\x00\x00\x00\x12y\x81 \x00\x00\x00\x00\x13\x1f\x97\x18\x00\x00\x00\x00\x14Yc \x00\x00\x00\x00\x14\xffy\x18\x00\x00\x00\x00\x169E \x00\x00\x00\x00\x16蕘\x00\x00\x00\x00\x18\"" + - "a\xa0\x00\x00\x00\x00\x18\xc8w\x98\x00\x00\x00\x00\x1a\x02C\xa0\x00\x00\x00\x00\x1a\xa8Y\x98\x00\x00\x00\x00\x1b\xe2%\xa0\x00\x00\x00\x00\x1c\x88;\x98\x00\x00\x00\x00\x1d\xc2\a\xa0\x00\x00\x00\x00\x1eh\x1d\x98\x00\x00" + - "\x00\x00\x1f\xa1\xe9\xa0\x00\x00\x00\x00 G\xff\x98\x00\x00\x00\x00!\x81ˠ\x00\x00\x00\x00\"1\x1c\x18\x00\x00\x00\x00#j\xe8 \x00\x00\x00\x00$\x10\xfe\x18\x00\x00\x00\x00%J\xca \x00\x00\x00\x00%\xf0" + - "\xe0\x18\x00\x00\x00\x00'*\xac \x00\x00\x00\x00'\xd0\xc2\x18\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\xff\xffj8\x00\x00\xff\xfflX\x00\x04\xff\xffs" + - "`\x00\n\xff\xffzh\x01\x0eLMT\x00-1030\x00-10\x00-0930\x00\n<-10>10\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RD6\x83\xa1\x8b\x00\x00\x00" + - "\x8b\x00\x00\x00\x11\x00\x1c\x00Pacific/MarquesasUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff~7U\x88\x00\x00\x00\x00N\xfd\x99\xb0\x01\x02\xff\xff_x\x00\x00\xff\xffeP\x00\x04\x00\x00\xb6\xd0\x00" + + "\bLMT\x00-11\x00+13\x00\n<+13>-13\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xea\xc1\xdaυ\x00\x00\x00\x85\x00\x00\x00\x0e\x00\x1c\x00Pacific" + + "/TahitiUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x94PU\xb8\x01\xff\xffs\xc8\x00\x00\xff\xffs`\x00\x04LMT\x00-10\x00\n<-10>10\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82" + + "iS߃\xa0_\x86\x00\x00\x00\x86\x00\x00\x00\f\x00\x1c\x00Pacific/WakeUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZ" + + "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff~6\x18\xcc\x01\x00\x00\x9c4\x00\x00\x00\x00\xa8\xc0\x00\x04LMT\x00+1" + + "2\x00\n<+12>-12\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSt\xca{e\x92\x00\x00\x00\x92\x00\x00\x00\x11\x00\x1c\x00Pacific/Pago_PagoU" + + "T\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00" + + "\x00\b\xff\xff\xff\xffn=\xc8\b\xff\xff\xff\xff\x91\x05\xfb\b\x01\x02\x00\x00\xb1x\x00\x00\xff\xff_\xf8\x00\x00\xff\xffeP\x00\x04LMT\x00SST\x00\nSST11\nPK\x03\x04\n\x00\x00" + + "\x00\x00\x00#\x82iSa\vೆ\x00\x00\x00\x86\x00\x00\x00\x10\x00\x1c\x00Pacific/FunafutiUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E" + + "\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZ" + + "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff~6\f\xfc\x01\x00\x00\xa8\x04\x00\x00\x00\x00\xa8" + + "\xc0\x00\x04LMT\x00+12\x00\n<+12>-12\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS6\xb7S{\x86\x00\x00\x00\x86\x00\x00\x00\x0e\x00\x1c\x00Pacific/T" + + "arawaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" + + "\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff~6\x12\xcc\x01\x00\x00\xa24\x00\x00\x00\x00\xa8\xc0\x00\x04LMT\x00+12\x00\n<+12>-12\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82i" + + "S\xcc\xf39a\xc3\x00\x00\x00\xc3\x00\x00\x00\v\x00\x1c\x00Pacific/YapUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif" + + "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\f\xff\xff\xff\xff\x14\xe1\xbf4\xff\xff\xff\xff~6&\xb4\xff\xff\xff\xff\x98\x11\xa3\xe0\xff\xff\xff\xff\xa0" + + "9\xf9\xf0\xff\xff\xff\xff\xc9\xea\n`\xff\xff\xff\xff\xd2\x11\x0e\xf0\x01\x02\x03\x02\x03\x02\xff\xff<\xcc\x00\x00\x00\x00\x8eL\x00\x00\x00\x00\x8c\xa0\x00\x04\x00\x00~\x90\x00\bLMT\x00+10\x00+09" + + "\x00\n<+10>-10\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xb7\xef\x97\xc6\xc6\x00\x00\x00\xc6\x00\x00\x00\x0e\x00\x1c\x00Pacific/NoumeaUT\t\x00\x03" + + "\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x03\x00\x00\x00\f\xff\xff" + + "\xff\xff\x92\xf5\xc4t\x00\x00\x00\x00\x0e\xe6\xbaP\x00\x00\x00\x00\x0fV\xbb\xc0\x00\x00\x00\x00\x10ƜP\x00\x00\x00\x00\x117\xef@\x00\x00\x00\x002\xa0K\xf0\x00\x00\x00\x003\x18Dp\x02\x01\x02\x01\x02\x01" + + "\x02\x00\x00\x9c\f\x00\x00\x00\x00\xa8\xc0\x01\x04\x00\x00\x9a\xb0\x00\bLMT\x00+12\x00+11\x00\n<+11>-11\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSD6\x83\xa1\x8b" + + "\x00\x00\x00\x8b\x00\x00\x00\x11\x00\x1c\x00Pacific/MarquesasUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif" + + "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\n\xff\xff\xff\xff\x94PLH\x01\xff\xff}8\x00\x00\xff\xffzh\x00\x04LMT\x00-093" + + "0\x00\n<-0930>9:30\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSY5\x1a6\xf7\x00\x00\x00\xf7\x00\x00\x00\x0f\x00\x1c\x00Pacific/Norfolk" + + "UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x06\x00" + + "\x00\x00\x1e\xff\xff\xff\xff~6\x17\x88\xff\xff\xff\xff\xdcA\xf8\x80\x00\x00\x00\x00\t\x0f\xcah\x00\x00\x00\x00\t\xb5\xe7h\x00\x00\x00\x00V\x0f\xe6h\x00\x00\x00\x00]\x98\xaf\xf0\x01\x02\x03\x02\x04\x05\x00\x00\x9d" + + "x\x00\x00\x00\x00\x9d\x80\x00\x04\x00\x00\xa1\xb8\x00\n\x00\x00\xaf\xc8\x01\x10\x00\x00\x9a\xb0\x00\x16\x00\x00\xa8\xc0\x01\x1aLMT\x00+1112\x00+1130\x00+1230\x00+11\x00+" + + "12\x00\n<+11>-11<+12>,M10.1.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSY\xd2K|\x86\x00\x00\x00\x86\x00\x00" + + "\x00\x13\x00\x1c\x00Pacific/GuadalcanalUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x94O3\x8c\x01\x00\x00\x95\xf4\x00\x00\x00\x00\x9a\xb0\x00\x04LMT\x00+11\x00\n<+1" + + "1>-11\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xeaK\x85v\xdd\x00\x00\x00\xdd\x00\x00\x00\x10\x00\x1c\x00Pacific/JohnstonUT\t\x00\x03\x82\x0f\x8b" + + "a\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" + + "\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xfft" + + "\xe0p\xbe\xff\xff\xff\xff\xbb\x05CH\xff\xff\xff\xff\xbb!qX\xff\xff\xff\xffˉ=\xc8\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2aI8\xff\xff\xff\xffՍsH\x01\x02\x01\x03\x04\x01\x05\xff\xff" + + "l\x02\x00\x00\xff\xfflX\x00\x04\xff\xffzh\x01\b\xff\xffzh\x01\f\xff\xffzh\x01\x10\xff\xffs`\x00\x04LMT\x00HST\x00HDT\x00HWT\x00HPT\x00\nHST10" + + "\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\u07b54-\xd6\x00\x00\x00\xd6\x00\x00\x00\x0e\x00\x1c\x00Pacific/PonapeUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux" + + "\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00" + + "\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\x14\xe1\xb9,\xff\xff\xff\xff" + + "~6 \xac\xff\xff\xff\xff\x98\x11\x95\xd0\xff\xff\xff\xff\xa09\xf9\xf0\xff\xff\xff\xff\xc1\xed5\xd0\xff\xff\xff\xff\xc9\xea\n`\xff\xff\xff\xff\xd2\x11\x0e\xf0\x01\x02\x03\x02\x04\x03\x02\xff\xffB\xd4\x00\x00\x00\x00\x94" + + "T\x00\x00\x00\x00\x9a\xb0\x00\x04\x00\x00~\x90\x00\b\x00\x00\x8c\xa0\x00\fLMT\x00+11\x00+09\x00+10\x00\n<+11>-11\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82i" + + "S\xe2;Z\xf7\xb7\x00\x00\x00\xb7\x00\x00\x00\r\x00\x1c\x00Pacific/NauruUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZ" + + "if2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xff\xa3\xe7+\x04\xff\xff\xff\xff̐\xe9\xc8\xff\xff\xff\xff\xd2C'\xf0\x00\x00\x00" + + "\x00\x11!\xa8\xe8\x01\x02\x01\x03\x00\x00\x9c|\x00\x00\x00\x00\xa1\xb8\x00\x04\x00\x00~\x90\x00\n\x00\x00\xa8\xc0\x00\x0eLMT\x00+1130\x00+09\x00+12\x00\n<+12>-12" + + "\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSFI\xfe\x14^\x01\x00\x00^\x01\x00\x00\f\x00\x1c\x00Pacific/GuamUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00" + + "\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00" + + "\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15\x00\x00\x00\x06\x00\x00\x00\x15\xff\xff\xff\xff\x14\xe1\xc5\xcc\xff\xff\xff\xff~6" + + "-L\xff\xff\xff\xff\xcb7\x95\xe0\xff\xff\xff\xff\xd0.\x89\xf0\xff\xff\xff\xff\xec7\xbe\x00\xff\xff\xff\xff\xef6\xf8\xf0\xff\xff\xff\xff\xfb\x9b\x00\x00\xff\xff\xff\xff\xfe?'\x8c\xff\xff\xff\xff\xff\x01\x1e\x00\xff\xff" + + "\xff\xff\xff]X\xf0\x00\x00\x00\x00\x00\x97,\x00\x00\x00\x00\x00\x01Fup\x00\x00\x00\x00\x02w\x0e\x00\x00\x00\x00\x00\x03&Wp\x00\x00\x00\x00\ap\x97\x00\x00\x00\x00\x00\a\xcc\xd1\xf0\x00\x00\x00\x00\f\b" + + "\x91\x00\x00\x00\x00\x00\f|\x87,\x00\x00\x00\x00\r\xbf\x94\x80\x00\x00\x00\x00\x0ee\xa3p\x00\x00\x00\x00:C^`\x01\x02\x03\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x05\xff\xff64\x00" + + "\x00\x00\x00\x87\xb4\x00\x00\x00\x00\x8c\xa0\x00\x04\x00\x00~\x90\x00\b\x00\x00\x9a\xb0\x01\f\x00\x00\x8c\xa0\x00\x10LMT\x00GST\x00+09\x00GDT\x00ChST\x00\nChST-10" + + "\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSt\xca{e\x92\x00\x00\x00\x92\x00\x00\x00\r\x00\x1c\x00Pacific/SamoaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v" + + "\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00" + + "\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\b\xff\xff\xff\xffn=\xc8\b\xff\xff\xff\xff\x91" + + "\x05\xfb\b\x01\x02\x00\x00\xb1x\x00\x00\xff\xff_\xf8\x00\x00\xff\xffeP\x00\x04LMT\x00SST\x00\nSST11\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x81\xe3w\n\xaf\x00\x00\x00" + + "\xaf\x00\x00\x00\x11\x00\x1c\x00Pacific/GalapagosUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\n\xff\xff\xff\xff\x94PLH\x01\xff\xff}8\x00\x00\xff\xffzh\x00\x04LMT\x00-0930\x00\n" + - "<-0930>9:30\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R6\xb7S{\x86\x00\x00\x00\x86\x00\x00\x00\x0e\x00\x1c\x00Pacific/TarawaUT\t\x00" + - "\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff" + - "\xff\xff\xff~6\x12\xcc\x01\x00\x00\xa24\x00\x00\x00\x00\xa8\xc0\x00\x04LMT\x00+12\x00\n<+12>-12\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xcc\xf39a\xc3\x00\x00\x00" + - "\xc3\x00\x00\x00\f\x00\x1c\x00Pacific/TrukUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\f\xff\xff\xff\xff\x14\xe1\xbf4\xff\xff\xff\xff~6&\xb4\xff\xff\xff\xff\x98\x11\xa3\xe0\xff\xff\xff\xff\xa09\xf9\xf0\xff\xff\xff\xff\xc9" + - "\xea\n`\xff\xff\xff\xff\xd2\x11\x0e\xf0\x01\x02\x03\x02\x03\x02\xff\xff<\xcc\x00\x00\x00\x00\x8eL\x00\x00\x00\x00\x8c\xa0\x00\x04\x00\x00~\x90\x00\bLMT\x00+10\x00+09\x00\n<+10>-" + - "10\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x81\xeb\xb8m\xaf\x00\x00\x00\xaf\x00\x00\x00\f\x00\x1c\x00Pacific/NiueUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux" + - "\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00" + - "\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x14\xff\xff\xff\xff~7TL\xff\xff\xff\xff" + - "\xdcC5`\x00\x00\x00\x00\x10t\xca8\x01\x02\x03\xff\xff`\xb4\x00\x00\xff\xff`\xa0\x00\x04\xff\xff^H\x00\n\xff\xffeP\x00\x10LMT\x00-1120\x00-1130\x00-11\x00\n" + - "<-11>11\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rt\xca{e\x92\x00\x00\x00\x92\x00\x00\x00\r\x00\x1c\x00Pacific/SamoaUT\t\x00\x03\x15\xac\x0e`" + - "\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00" + - "\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\b\xff\xff\xff\xffn=" + - "\xc8\b\xff\xff\xff\xff\x91\x05\xfb\b\x01\x02\x00\x00\xb1x\x00\x00\xff\xff_\xf8\x00\x00\xff\xffeP\x00\x04LMT\x00SST\x00\nSST11\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RF" + - "I\xfe\x14^\x01\x00\x00^\x01\x00\x00\f\x00\x1c\x00Pacific/GuamUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\f\xff\xff\xff\xff\xb6\xa4L\x80\x00\x00\x00\x00\x1e\x18\xc4P\x00\x00\x00\x00+\x17\n\xe0\x00\x00\x00\x00+q\xf4P" + + "\x01\x03\x02\x03\xff\xff\xac\x00\x00\x00\xff\xff\xb9\xb0\x00\x04\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\bLMT\x00-05\x00-06\x00\n<-06>6\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82" + + "iS\xeaK\x85v\xdd\x00\x00\x00\xdd\x00\x00\x00\x10\x00\x1c\x00Pacific/HonoluluUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_" + + "\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xfft\xe0p\xbe\xff\xff\xff\xff\xbb\x05CH\xff\xff\xff\xff\xbb!q" + + "X\xff\xff\xff\xffˉ=\xc8\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2aI8\xff\xff\xff\xffՍsH\x01\x02\x01\x03\x04\x01\x05\xff\xffl\x02\x00\x00\xff\xfflX\x00\x04\xff\xffzh\x01\b\xff\xff" + + "zh\x01\f\xff\xffzh\x01\x10\xff\xffs`\x00\x04LMT\x00HST\x00HDT\x00HWT\x00HPT\x00\nHST10\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x97n7" + + "\x1a\xf2\x00\x00\x00\xf2\x00\x00\x00\x0e\x00\x1c\x00Pacific/KosraeUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15\x00\x00\x00\x06\x00\x00\x00\x15\xff\xff\xff\xff\x14\xe1\xc5\xcc\xff\xff\xff\xff~6-L\xff\xff\xff\xff\xcb7\x95\xe0\xff\xff\xff\xff\xd0." + - "\x89\xf0\xff\xff\xff\xff\xec7\xbe\x00\xff\xff\xff\xff\xef6\xf8\xf0\xff\xff\xff\xff\xfb\x9b\x00\x00\xff\xff\xff\xff\xfe?'\x8c\xff\xff\xff\xff\xff\x01\x1e\x00\xff\xff\xff\xff\xff]X\xf0\x00\x00\x00\x00\x00\x97,\x00\x00\x00" + - "\x00\x00\x01Fup\x00\x00\x00\x00\x02w\x0e\x00\x00\x00\x00\x00\x03&Wp\x00\x00\x00\x00\ap\x97\x00\x00\x00\x00\x00\a\xcc\xd1\xf0\x00\x00\x00\x00\f\b\x91\x00\x00\x00\x00\x00\f|\x87,\x00\x00\x00\x00\r\xbf" + - "\x94\x80\x00\x00\x00\x00\x0ee\xa3p\x00\x00\x00\x00:C^`\x01\x02\x03\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x05\xff\xff64\x00\x00\x00\x00\x87\xb4\x00\x00\x00\x00\x8c\xa0\x00\x04\x00\x00~" + - "\x90\x00\b\x00\x00\x9a\xb0\x01\f\x00\x00\x8c\xa0\x00\x10LMT\x00GST\x00+09\x00GDT\x00ChST\x00\nChST-10\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RF" + - "I\xfe\x14^\x01\x00\x00^\x01\x00\x00\x0e\x00\x1c\x00Pacific/SaipanUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZi" + - "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15\x00\x00\x00\x06\x00\x00\x00\x15\xff\xff\xff\xff\x14\xe1\xc5\xcc\xff\xff\xff\xff~6-L\xff\xff\xff\xff\xcb7\x95\xe0\xff\xff\xff\xff" + - "\xd0.\x89\xf0\xff\xff\xff\xff\xec7\xbe\x00\xff\xff\xff\xff\xef6\xf8\xf0\xff\xff\xff\xff\xfb\x9b\x00\x00\xff\xff\xff\xff\xfe?'\x8c\xff\xff\xff\xff\xff\x01\x1e\x00\xff\xff\xff\xff\xff]X\xf0\x00\x00\x00\x00\x00\x97,\x00" + - "\x00\x00\x00\x00\x01Fup\x00\x00\x00\x00\x02w\x0e\x00\x00\x00\x00\x00\x03&Wp\x00\x00\x00\x00\ap\x97\x00\x00\x00\x00\x00\a\xcc\xd1\xf0\x00\x00\x00\x00\f\b\x91\x00\x00\x00\x00\x00\f|\x87,\x00\x00\x00\x00" + - "\r\xbf\x94\x80\x00\x00\x00\x00\x0ee\xa3p\x00\x00\x00\x00:C^`\x01\x02\x03\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x05\xff\xff64\x00\x00\x00\x00\x87\xb4\x00\x00\x00\x00\x8c\xa0\x00\x04\x00" + - "\x00~\x90\x00\b\x00\x00\x9a\xb0\x01\f\x00\x00\x8c\xa0\x00\x10LMT\x00GST\x00+09\x00GDT\x00ChST\x00\nChST-10\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9" + - "R\x81\xe3w\n\xaf\x00\x00\x00\xaf\x00\x00\x00\x11\x00\x1c\x00Pacific/GalapagosUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03" + - "\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\f\xff\xff\xff\xff\xb6\xa4L\x80\x00\x00\x00\x00\x1e\x18\xc4P\x00\x00\x00\x00+\x17\n" + - "\xe0\x00\x00\x00\x00+q\xf4P\x01\x03\x02\x03\xff\xff\xac\x00\x00\x00\xff\xff\xb9\xb0\x00\x04\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\bLMT\x00-05\x00-06\x00\n<-06>6\nPK\x03" + - "\x04\n\x00\x00\x00\x00\x00\xf1c9R\x9a\xf2:F\xc9\x00\x00\x00\xc9\x00\x00\x00\x14\x00\x1c\x00Pacific/BougainvilleUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`" + - "ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00" + - "\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xffV\xb6R(\xff\xff" + - "\xff\xffr\xed\xa4\x90\xff\xff\xff\xff\xccC6`\xff\xff\xff\xff\xd2+l\xf0\x00\x00\x00\x00T\x9e׀\x01\x02\x03\x02\x04\x00\x00\x91\xd8\x00\x00\x00\x00\x89\xf0\x00\x04\x00\x00\x8c\xa0\x00\t\x00\x00~\x90\x00\r\x00" + - "\x00\x9a\xb0\x00\x11LMT\x00PMMT\x00+10\x00+09\x00+11\x00\n<+11>-11\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R߃\xa0_\x86\x00\x00\x00\x86\x00" + - "\x00\x00\f\x00\x1c\x00Pacific/WakeUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff~6\x18\xcc\x01\x00\x00\x9c4\x00\x00\x00\x00\xa8\xc0\x00\x04LMT\x00+12\x00\n<+12>-12\n" + - "PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RP:\xc0\x8c\xed\x00\x00\x00\xed\x00\x00\x00\x11\x00\x1c\x00Pacific/TongatapuUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`" + - "ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00" + - "\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xff~6\a\xb8\xff\xff" + - "\xff\xff\xc9sB\x90\x00\x00\x00\x007\xfbG\xd0\x00\x00\x00\x008\xd3}\xd0\x00\x00\x00\x00:\x04\bP\x00\x00\x00\x00:r\xb8@\x00\x00\x00\x00;\xe3\xeaP\x00\x00\x00\x00-13\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xcc\xf39a\xc3\x00\x00\x00\xc3\x00\x00\x00\r\x00\x1c\x00Pacific/ChuukUT\t\x00\x03" + - "\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\f\xff\xff" + - "\xff\xff\x14\xe1\xbf4\xff\xff\xff\xff~6&\xb4\xff\xff\xff\xff\x98\x11\xa3\xe0\xff\xff\xff\xff\xa09\xf9\xf0\xff\xff\xff\xff\xc9\xea\n`\xff\xff\xff\xff\xd2\x11\x0e\xf0\x01\x02\x03\x02\x03\x02\xff\xff<\xcc\x00\x00\x00\x00" + - "\x8eL\x00\x00\x00\x00\x8c\xa0\x00\x04\x00\x00~\x90\x00\bLMT\x00+10\x00+09\x00\n<+10>-10\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xea\xc1\xdaυ\x00\x00\x00" + - "\x85\x00\x00\x00\x0e\x00\x1c\x00Pacific/TahitiUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x94PU\xb8\x01\xff\xffs\xc8\x00\x00\xff\xffs`\x00\x04LMT\x00-10\x00\n<-10>" + - "10\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RY\xd2K|\x86\x00\x00\x00\x86\x00\x00\x00\x13\x00\x1c\x00Pacific/GuadalcanalUT\t\x00\x03\x15\xac\x0e" + - "`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" + - "\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x94" + - "O3\x8c\x01\x00\x00\x95\xf4\x00\x00\x00\x00\x9a\xb0\x00\x04LMT\x00+11\x00\n<+11>-11\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rb\xb2\xaf\xf7\x13\x04\x00\x00\x13\x04\x00\x00" + - "\x10\x00\x1c\x00Pacific/AucklandUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x00\x00\x00\x06\x00\x00\x00\x13\xff\xff\xff\xffA\xb7L\xa8\xff\xff\xff\xff\xb0\xb4\xb2\xe8\xff\xff\xff\xff\xb1Q\x87X\xff\xff\xff\xff\xb2x\xe5h\xff\xff\xff\xff\xb3" + - "C\xe5`\xff\xff\xff\xff\xb4X\xc7h\xff\xff\xff\xff\xb5#\xc7`\xff\xff\xff\xff\xb68\xa9h\xff\xff\xff\xff\xb7\x03\xa9`\xff\xff\xff\xff\xb8\x18\x8bh\xff\xff\xff\xff\xb8\xec\xc5\xe0\xff\xff\xff\xff\xb9\xf8mh\xff" + - "\xff\xff\xff\xba̧\xe0\xff\xff\xff\xff\xbb\xd8Oh\xff\xff\xff\xff\xbc\xe3\xe8\xe0\xff\xff\xff\xff\xbd\xae\xf6\xe8\xff\xff\xff\xff\xbe\xc3\xca\xe0\xff\xff\xff\xff\xbf\x8e\xd8\xe8\xff\xff\xff\xff\xc0\xa3\xac\xe0\xff\xff\xff\xff\xc1" + - "n\xba\xe8\xff\xff\xff\xff\u0083\x8e\xe0\xff\xff\xff\xff\xc3N\x9c\xe8\xff\xff\xff\xff\xc4cp\xe0\xff\xff\xff\xff\xc5.~\xe8\xff\xff\xff\xff\xc6L\x8d`\xff\xff\xff\xff\xc7\x0e`\xe8\xff\xff\xff\xff\xc8,o`\xff" + - "\xff\xff\xff\xc8\xf7}h\xff\xff\xff\xff\xd2ښ@\x00\x00\x00\x00\t\x18\xfd\xe0\x00\x00\x00\x00\t\xac\xa5\xe0\x00\x00\x00\x00\n\xef\xa5`\x00\x00\x00\x00\v\x9e\xfc\xe0\x00\x00\x00\x00\f\xd8\xc1\xe0\x00\x00\x00\x00\r" + - "~\xde\xe0\x00\x00\x00\x00\x0e\xb8\xa3\xe0\x00\x00\x00\x00\x0f^\xc0\xe0\x00\x00\x00\x00\x10\x98\x85\xe0\x00\x00\x00\x00\x11>\xa2\xe0\x00\x00\x00\x00\x12xg\xe0\x00\x00\x00\x00\x13\x1e\x84\xe0\x00\x00\x00\x00\x14XI\xe0\x00" + - "\x00\x00\x00\x14\xfef\xe0\x00\x00\x00\x00\x168+\xe0\x00\x00\x00\x00\x16\xe7\x83`\x00\x00\x00\x00\x18!H`\x00\x00\x00\x00\x18\xc7e`\x00\x00\x00\x00\x1a\x01*`\x00\x00\x00\x00\x1a\xa7G`\x00\x00\x00\x00\x1b" + - "\xe1\f`\x00\x00\x00\x00\x1c\x87)`\x00\x00\x00\x00\x1d\xc0\xee`\x00\x00\x00\x00\x1eg\v`\x00\x00\x00\x00\x1f\xa0\xd0`\x00\x00\x00\x00 F\xed`\x00\x00\x00\x00!\x80\xb2`\x00\x00\x00\x00\"0\t\xe0\x00" + - "\x00\x00\x00#i\xce\xe0\x00\x00\x00\x00$\x0f\xeb\xe0\x00\x00\x00\x00%.\x01`\x00\x00\x00\x00&\x02B\xe0\x00\x00\x00\x00'\r\xe3`\x00\x00\x00\x00'\xe2$\xe0\x00\x00\x00\x00(\xed\xc5`\x00\x00\x00\x00)" + - "\xc2\x06\xe0\x00\x00\x00\x00*ͧ`\x00\x00\x00\x00+\xab#`\x00\x00\x00\x00,\xad\x89`\x00\x00\x00\x00-\x8b\x05`\x00\x00\x00\x00.\x8dk`\x00\x00\x00\x00/j\xe7`\x00\x00\x00\x000mM`\x00" + - "\x00\x00\x001J\xc9`\x00\x00\x00\x002Vi\xe0\x00\x00\x00\x003*\xab`\x00\x00\x00\x0046K\xe0\x00\x00\x00\x005\n\x8d`\x00\x00\x00\x006\x16-\xe0\x00\x00\x00\x006\xf3\xa9\xe0\x00\x00\x00\x007" + - "\xf6\x0f\xe0\x00\x00\x00\x008Ӌ\xe0\x00\x00\x00\x009\xd5\xf1\xe0\x00\x00\x00\x00:\xb3m\xe0\x00\x00\x00\x00;\xbf\x0e`\x00\x00\x00\x00<\x93O\xe0\x00\x00\x00\x00=\x9e\xf0`\x00\x00\x00\x00>s1\xe0\x00" + - "\x00\x00\x00?~\xd2`\x00\x00\x00\x00@\\N`\x00\x00\x00\x00A^\xb4`\x00\x00\x00\x00B<0`\x00\x00\x00\x00C>\x96`\x00\x00\x00\x00D\x1c\x12`\x00\x00\x00\x00E\x1ex`\x00\x00\x00\x00E" + - "\xfb\xf4`\x00\x00\x00\x00F\xfeZ`\x02\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05" + - "\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x00\x00\xa3\xd8\x00\x00\x00\x00\xaf\xc8\x01\x04\x00" + - "\x00\xa1\xb8\x00\t\x00\x00\xa8\xc0\x01\x04\x00\x00\xb6\xd0\x01\x0e\x00\x00\xa8\xc0\x00\x04LMT\x00NZST\x00NZMT\x00NZDT\x00\nNZST-12NZDT,M9.5." + - "0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RY5\x1a6\xf7\x00\x00\x00\xf7\x00\x00\x00\x0f\x00\x1c\x00Pacific/NorfolkUT\t\x00" + - "\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x1e\xff" + - "\xff\xff\xff~6\x17\x88\xff\xff\xff\xff\xdcA\xf8\x80\x00\x00\x00\x00\t\x0f\xcah\x00\x00\x00\x00\t\xb5\xe7h\x00\x00\x00\x00V\x0f\xe6h\x00\x00\x00\x00]\x98\xaf\xf0\x01\x02\x03\x02\x04\x05\x00\x00\x9dx\x00\x00\x00" + - "\x00\x9d\x80\x00\x04\x00\x00\xa1\xb8\x00\n\x00\x00\xaf\xc8\x01\x10\x00\x00\x9a\xb0\x00\x16\x00\x00\xa8\xc0\x01\x1aLMT\x00+1112\x00+1130\x00+1230\x00+11\x00+12\x00\n" + - "<+11>-11<+12>,M10.1.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R>\xfe垛\x03\x00\x00\x9b\x03\x00\x00\x06\x00\x1c" + - "\x00PolandUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00R\x00\x00\x00\x06\x00\x00\x00\x1a\xff\xff\xff\xffV\xb6\xd0P\xff\xff\xff\xff\x99\xa8*\xd0\xff\xff\xff\xff\x9b\f\x17`\xff\xff\xff\xff\x9b\xd5\xda\xf0\xff\xff\xff\xff\x9cٮ\x90\xff\xff\xff\xff\x9d\xa4\xb5\x90\xff\xff" + - "\xff\xff\x9e\xb9\x90\x90\xff\xff\xff\xff\x9f\x84\x97\x90\xff\xff\xff\xff\xa0\x9a\xb6\x00\xff\xff\xff\xff\xa1e\xbd\x00\xff\xff\xff\xff\xa6}|`\xff\xff\xff\xff\xc8v\xde\x10\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ" + - "\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЄ\xba\x00\xff\xff\xff\xffѕ\x92p\xff\xff\xff\xffҊ\xbb`\xff\xff\xff\xff\xd3b\xffp\xff\xff\xff\xff\xd4K#\x90\xff\xff" + - "\xff\xff\xd5^\xad\x10\xff\xff\xff\xff\xd6)\xb4\x10\xff\xff\xff\xff\xd7,\x1a\x10\xff\xff\xff\xff\xd8\t\x96\x10\xff\xff\xff\xff\xd9\x02\xc1\x90\xff\xff\xff\xff\xd9\xe9x\x10\xff\xff\xff\xff\xe8T\xd2\x00\xff\xff\xff\xff\xe8\xf1" + - "\xb4\x80\xff\xff\xff\xff\xe9᥀\xff\xff\xff\xff\xeaі\x80\xff\xff\xff\xff\xec\x14\x96\x00\xff\xff\xff\xff캳\x00\xff\xff\xff\xff\xed\xaa\xa4\x00\xff\xff\xff\xff\ue695\x00\xff\xff\xff\xff\xef\xd4Z\x00\xff\xff" + - "\xff\xff\xf0zw\x00\xff\xff\xff\xff\xf1\xb4<\x00\xff\xff\xff\xff\xf2ZY\x00\xff\xff\xff\xff\xf3\x94\x1e\x00\xff\xff\xff\xff\xf4:;\x00\xff\xff\xff\xff\xf5}:\x80\xff\xff\xff\xff\xf6\x1a\x1d\x00\x00\x00\x00\x00\r\xa4" + - "U\x80\x00\x00\x00\x00\x0e\x8b\f\x00\x00\x00\x00\x00\x0f\x847\x80\x00\x00\x00\x00\x10t(\x80\x00\x00\x00\x00\x11d\x19\x80\x00\x00\x00\x00\x12T\n\x80\x00\x00\x00\x00\x13M6\x00\x00\x00\x00\x00\x143\xec\x80\x00\x00" + - "\x00\x00\x15#݀\x00\x00\x00\x00\x16\x13\u0380\x00\x00\x00\x00\x17\x03\xbf\x80\x00\x00\x00\x00\x17\xf3\xb0\x80\x00\x00\x00\x00\x18㡀\x00\x00\x00\x00\x19Ӓ\x80\x00\x00\x00\x00\x1aÃ\x80\x00\x00\x00\x00\x1b\xbc" + - "\xaf\x00\x00\x00\x00\x00\x1c\xac\xa0\x00\x00\x00\x00\x00\x1d\x9c\x91\x00\x00\x00\x00\x00\x1e\x8c\x82\x00\x00\x00\x00\x00\x1f|s\x00\x00\x00\x00\x00 ld\x00\x00\x00\x00\x00!\\U\x00\x00\x00\x00\x00\"LT\x10\x00\x00" + - "\x00\x00#-11\nPK\x03" + + "\x04\n\x00\x00\x00\x00\x00#\x82iS\xc23\xa0\xbc\x84\x00\x00\x00\x84\x00\x00\x00\x0f\x00\x1c\x00Pacific/GambierUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01" + + "\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00" + + "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff\xff\xff\x94PH\x04\x01\xff\xff\x81|\x00\x00" + + "\xff\xff\x81p\x00\x04LMT\x00-09\x00\n<-09>9\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xfa\x0fA\x05\x99\x00\x00\x00\x99\x00\x00\x00\x10\x00\x1c\x00Pacific/" + + "PitcairnUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x0e\xff\xff\xff\xff~7.\xf4\x00\x00\x00\x005DB\b\x01\x02\xff\xff\x86\f\x00\x00\xff\xff\x88x\x00\x04\xff\xff\x8f\x80\x00\nLMT\x00-0830\x00-08" + + "\x00\n<-08>8\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iScF/.\xac\x01\x00\x00\xac\x01\x00\x00\f\x00\x1c\x00Pacific/FijiUT\t\x00\x03\x82\x0f\x8ba" + + "\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00" + + "\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff\x9a\x13" + + "\xb1\xc0\x00\x00\x00\x006;\x17\xe0\x00\x00\x00\x006\xd7\xfa`\x00\x00\x00\x008$4`\x00\x00\x00\x008\xb7\xdc`\x00\x00\x00\x00K\x11,\xe0\x00\x00\x00\x00K\xae\x0f`\x00\x00\x00\x00L\xc2\xea`\x00\x00" + + "\x00\x00MrA\xe0\x00\x00\x00\x00N\xa2\xcc`\x00\x00\x00\x00O\x1a\xc4\xe0\x00\x00\x00\x00P\x82\xae`\x00\x00\x00\x00P\xfa\xa6\xe0\x00\x00\x00\x00Rk\xca\xe0\x00\x00\x00\x00R\xdaz\xd0\x00\x00\x00\x00TT" + + "\xe7`\x00\x00\x00\x00T\xbaj\xe0\x00\x00\x00\x00V4\xc9`\x00\x00\x00\x00V\x9aL\xe0\x00\x00\x00\x00X\x1d\xe5\xe0\x00\x00\x00\x00Xz.\xe0\x00\x00\x00\x00Y\xfd\xc7\xe0\x00\x00\x00\x00ZZ\x10\xe0\x00\x00" + + "\x00\x00[ݩ\xe0\x00\x00\x00\x00\\9\xf2\xe0\x00\x00\x00\x00]\xc6\xc6`\x00\x00\x00\x00^\x19\xd4\xe0\x00\x00\x00\x00_\xde\a`\x00\x00\x00\x00`\x02\xf1`\x00\x00\x00\x00co\xa6\xe0\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00\xa7\xc0\x00\x00\x00\x00\xb6\xd0\x01\x04\x00\x00\xa8\xc0\x00\bLMT\x00+13\x00+12\x00\n<+12>" + + "-12<+13>,M11.2.0,M1.2.3/99\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xec =\x89\xac\x00\x00\x00\xac\x00\x00\x00\x0e\x00\x1c\x00Pac" + + "ific/KantonUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff\xc3,ۀ\x00\x00\x00\x00\x12V\x04\xc0\x00\x00\x00\x00/\x059\xb0\x01\x02\x03\x00\x00\x00\x00\x00\x00\xff\xffW@\x00\x04\xff\xffeP\x00\b\x00" + + "\x00\xb6\xd0\x00\f-00\x00-12\x00-11\x00+13\x00\n<+13>-13\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\u07b54-\xd6\x00\x00\x00\xd6\x00\x00\x00\x0f\x00\x1c" + + "\x00Pacific/PohnpeiUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x05\x00\x00\x00\x10\xff\xff\xff\xff\x14\xe1\xb9,\xff\xff\xff\xff~6 \xac\xff\xff\xff\xff\x98\x11\x95\xd0\xff\xff\xff\xff\xa09\xf9\xf0\xff\xff\xff\xff\xc1\xed5\xd0\xff" + + "\xff\xff\xff\xc9\xea\n`\xff\xff\xff\xff\xd2\x11\x0e\xf0\x01\x02\x03\x02\x04\x03\x02\xff\xffB\xd4\x00\x00\x00\x00\x94T\x00\x00\x00\x00\x9a\xb0\x00\x04\x00\x00~\x90\x00\b\x00\x00\x8c\xa0\x00\fLMT\x00+11\x00" + + "+09\x00+10\x00\n<+11>-11\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x9a\xf2:F\xc9\x00\x00\x00\xc9\x00\x00\x00\x14\x00\x1c\x00Pacific/Boug" + + "ainvilleUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x05\x00\x00\x00\x05\x00\x00\x00\x15\xff\xff\xff\xffV\xb6R(\xff\xff\xff\xffr\xed\xa4\x90\xff\xff\xff\xff\xccC6`\xff\xff\xff\xff\xd2+l\xf0\x00\x00\x00\x00T\x9e׀\x01\x02\x03\x02\x04\x00\x00\x91\xd8" + + "\x00\x00\x00\x00\x89\xf0\x00\x04\x00\x00\x8c\xa0\x00\t\x00\x00~\x90\x00\r\x00\x00\x9a\xb0\x00\x11LMT\x00PMMT\x00+10\x00+09\x00+11\x00\n<+11>-11\nPK\x03" + + "\x04\n\x00\x00\x00\x00\x00#\x82iS\xca\"\xb8i\xda\x00\x00\x00\xda\x00\x00\x00\x0e\x00\x1c\x00Pacific/MajuroUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04" + + "\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" + + "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff~6\x14\x80\xff\xff\xff\xff\x98\x11\x95\xd0" + + "\xff\xff\xff\xff\xa09\xf9\xf0\xff\xff\xff\xff\xc1\xed5\xd0\xff\xff\xff\xff\xc9\xea\n`\xff\xff\xff\xff\xcf=Gp\xff\xff\xff\xff\xff\x86\x1bP\x01\x02\x01\x03\x02\x01\x04\x00\x00\xa0\x80\x00\x00\x00\x00\x9a\xb0\x00\x04\x00" + + "\x00~\x90\x00\b\x00\x00\x8c\xa0\x00\f\x00\x00\xa8\xc0\x00\x10LMT\x00+11\x00+09\x00+10\x00+12\x00\n<+12>-12\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82i" + + "Sb\xb2\xaf\xf7\x13\x04\x00\x00\x13\x04\x00\x00\x10\x00\x1c\x00Pacific/AucklandUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01" + "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00\x03\x00\x00\x00\f\xff\xff\xff\xff~6C)\xff\xff\xff\xff\xa0\x97\xa2\x80\xff\xff\xff\xff\xa1y\x04\xf0" + - "\xff\xff\xff\xff\xc8Y^\x80\xff\xff\xff\xff\xc9\t\xf9p\xff\xff\xff\xff\xc9ӽ\x00\xff\xff\xff\xff\xcb\x05\x8a\xf0\xff\xff\xff\xff\xcb|@\x00\xff\xff\xff\xff\xd2;>\xf0\xff\xff\xff\xffӋ{\x80\xff\xff\xff\xff" + - "\xd4B\xad\xf0\xff\xff\xff\xff\xd5E\"\x00\xff\xff\xff\xff\xd6L\xbf\xf0\xff\xff\xff\xff\xd7<\xbf\x00\xff\xff\xff\xff\xd8\x06fp\xff\xff\xff\xff\xd9\x1d\xf2\x80\xff\xff\xff\xff\xd9A|\xf0\x00\x00\x00\x00\x1e\xbaR " + - "\x00\x00\x00\x00\x1fi\x9b\x90\x00\x00\x00\x00 ~\x84\xa0\x00\x00\x00\x00!I}\x90\x00\x00\x00\x00\"g\xa1 \x00\x00\x00\x00#)_\x90\x00\x00\x00\x00$G\x83 \x00\x00\x00\x00%\x12|\x10\x00\x00\x00\x00" + - "&'e \x00\x00\x00\x00&\xf2^\x10\x00\x00\x00\x00(\aG \x00\x00\x00\x00(\xd2@\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00q" + - "\xd7\x00\x00\x00\x00~\x90\x01\x04\x00\x00p\x80\x00\bLMT\x00CDT\x00CST\x00\nCST-8\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9RŭV\xad\xb7\x03\x00\x00\xb7\x03\x00\x00" + - "\a\x00\x1c\x00PST8PDTUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x00\x00\x00\x06\x00\x00\x00\x13\xff\xff\xff\xffA\xb7L\xa8\xff\xff\xff\xff\xb0\xb4\xb2\xe8\xff\xff\xff\xff\xb1Q\x87X" + + "\xff\xff\xff\xff\xb2x\xe5h\xff\xff\xff\xff\xb3C\xe5`\xff\xff\xff\xff\xb4X\xc7h\xff\xff\xff\xff\xb5#\xc7`\xff\xff\xff\xff\xb68\xa9h\xff\xff\xff\xff\xb7\x03\xa9`\xff\xff\xff\xff\xb8\x18\x8bh\xff\xff\xff\xff" + + "\xb8\xec\xc5\xe0\xff\xff\xff\xff\xb9\xf8mh\xff\xff\xff\xff\xba̧\xe0\xff\xff\xff\xff\xbb\xd8Oh\xff\xff\xff\xff\xbc\xe3\xe8\xe0\xff\xff\xff\xff\xbd\xae\xf6\xe8\xff\xff\xff\xff\xbe\xc3\xca\xe0\xff\xff\xff\xff\xbf\x8e\xd8\xe8" + + "\xff\xff\xff\xff\xc0\xa3\xac\xe0\xff\xff\xff\xff\xc1n\xba\xe8\xff\xff\xff\xff\u0083\x8e\xe0\xff\xff\xff\xff\xc3N\x9c\xe8\xff\xff\xff\xff\xc4cp\xe0\xff\xff\xff\xff\xc5.~\xe8\xff\xff\xff\xff\xc6L\x8d`\xff\xff\xff\xff" + + "\xc7\x0e`\xe8\xff\xff\xff\xff\xc8,o`\xff\xff\xff\xff\xc8\xf7}h\xff\xff\xff\xff\xd2ښ@\x00\x00\x00\x00\t\x18\xfd\xe0\x00\x00\x00\x00\t\xac\xa5\xe0\x00\x00\x00\x00\n\xef\xa5`\x00\x00\x00\x00\v\x9e\xfc\xe0" + + "\x00\x00\x00\x00\f\xd8\xc1\xe0\x00\x00\x00\x00\r~\xde\xe0\x00\x00\x00\x00\x0e\xb8\xa3\xe0\x00\x00\x00\x00\x0f^\xc0\xe0\x00\x00\x00\x00\x10\x98\x85\xe0\x00\x00\x00\x00\x11>\xa2\xe0\x00\x00\x00\x00\x12xg\xe0\x00\x00\x00\x00" + + "\x13\x1e\x84\xe0\x00\x00\x00\x00\x14XI\xe0\x00\x00\x00\x00\x14\xfef\xe0\x00\x00\x00\x00\x168+\xe0\x00\x00\x00\x00\x16\xe7\x83`\x00\x00\x00\x00\x18!H`\x00\x00\x00\x00\x18\xc7e`\x00\x00\x00\x00\x1a\x01*`" + + "\x00\x00\x00\x00\x1a\xa7G`\x00\x00\x00\x00\x1b\xe1\f`\x00\x00\x00\x00\x1c\x87)`\x00\x00\x00\x00\x1d\xc0\xee`\x00\x00\x00\x00\x1eg\v`\x00\x00\x00\x00\x1f\xa0\xd0`\x00\x00\x00\x00 F\xed`\x00\x00\x00\x00" + + "!\x80\xb2`\x00\x00\x00\x00\"0\t\xe0\x00\x00\x00\x00#i\xce\xe0\x00\x00\x00\x00$\x0f\xeb\xe0\x00\x00\x00\x00%.\x01`\x00\x00\x00\x00&\x02B\xe0\x00\x00\x00\x00'\r\xe3`\x00\x00\x00\x00'\xe2$\xe0" + + "\x00\x00\x00\x00(\xed\xc5`\x00\x00\x00\x00)\xc2\x06\xe0\x00\x00\x00\x00*ͧ`\x00\x00\x00\x00+\xab#`\x00\x00\x00\x00,\xad\x89`\x00\x00\x00\x00-\x8b\x05`\x00\x00\x00\x00.\x8dk`\x00\x00\x00\x00" + + "/j\xe7`\x00\x00\x00\x000mM`\x00\x00\x00\x001J\xc9`\x00\x00\x00\x002Vi\xe0\x00\x00\x00\x003*\xab`\x00\x00\x00\x0046K\xe0\x00\x00\x00\x005\n\x8d`\x00\x00\x00\x006\x16-\xe0" + + "\x00\x00\x00\x006\xf3\xa9\xe0\x00\x00\x00\x007\xf6\x0f\xe0\x00\x00\x00\x008Ӌ\xe0\x00\x00\x00\x009\xd5\xf1\xe0\x00\x00\x00\x00:\xb3m\xe0\x00\x00\x00\x00;\xbf\x0e`\x00\x00\x00\x00<\x93O\xe0\x00\x00\x00\x00" + + "=\x9e\xf0`\x00\x00\x00\x00>s1\xe0\x00\x00\x00\x00?~\xd2`\x00\x00\x00\x00@\\N`\x00\x00\x00\x00A^\xb4`\x00\x00\x00\x00B<0`\x00\x00\x00\x00C>\x96`\x00\x00\x00\x00D\x1c\x12`" + + "\x00\x00\x00\x00E\x1ex`\x00\x00\x00\x00E\xfb\xf4`\x00\x00\x00\x00F\xfeZ`\x02\x01\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x05\x04\x05\x04\x05\x04\x05\x04" + + "\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04" + + "\x00\x00\xa3\xd8\x00\x00\x00\x00\xaf\xc8\x01\x04\x00\x00\xa1\xb8\x00\t\x00\x00\xa8\xc0\x01\x04\x00\x00\xb6\xd0\x01\x0e\x00\x00\xa8\xc0\x00\x04LMT\x00NZST\x00NZMT\x00NZDT\x00\nNZST" + + "-12NZDT,M9.5.0,M4.1.0/3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xf6\xe8]*\xdb\x00\x00\x00\xdb\x00\x00\x00\x11\x00\x1c\x00Pacifi" + + "c/KwajaleinUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00X\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff\x9e\xa6H\xa0\xff\xff\xff\xff\x9f\xbb\x15\x90\xff\xff\xff\xff\xa0\x86*\xa0\xff\xff\xff\xff\xa1\x9a\xf7\x90\xff\xff\xff\xffˉ\x1a\xa0\xff\xff\xff\xff\xd2#" + - "\xf4p\xff\xff\xff\xff\xd2a&\x10\xff\xff\xff\xff\xfa\xf8\x83 \xff\xff\xff\xff\xfb\xe8f\x10\xff\xff\xff\xff\xfc\xd8e \xff\xff\xff\xff\xfd\xc8H\x10\xff\xff\xff\xff\xfe\xb8G \xff\xff\xff\xff\xff\xa8*\x10\x00\x00" + - "\x00\x00\x00\x98) \x00\x00\x00\x00\x01\x88\f\x10\x00\x00\x00\x00\x02x\v \x00\x00\x00\x00\x03q(\x90\x00\x00\x00\x00\x04a'\xa0\x00\x00\x00\x00\x05Q\n\x90\x00\x00\x00\x00\x06A\t\xa0\x00\x00\x00\x00\a0" + - "\xec\x90\x00\x00\x00\x00\a\x8dC\xa0\x00\x00\x00\x00\t\x10ΐ\x00\x00\x00\x00\t\xad\xbf \x00\x00\x00\x00\n\xf0\xb0\x90\x00\x00\x00\x00\v\u0be0\x00\x00\x00\x00\f\xd9\xcd\x10\x00\x00\x00\x00\r\xc0\x91\xa0\x00\x00" + - "\x00\x00\x0e\xb9\xaf\x10\x00\x00\x00\x00\x0f\xa9\xae \x00\x00\x00\x00\x10\x99\x91\x10\x00\x00\x00\x00\x11\x89\x90 \x00\x00\x00\x00\x12ys\x10\x00\x00\x00\x00\x13ir \x00\x00\x00\x00\x14YU\x10\x00\x00\x00\x00\x15I" + - "T \x00\x00\x00\x00\x1697\x10\x00\x00\x00\x00\x17)6 \x00\x00\x00\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18 \x00\x00\x00\x00\x1a\x025\x90\x00\x00\x00\x00\x1a\xf24\xa0\x00\x00\x00\x00\x1b\xe2\x17\x90\x00\x00" + - "\x00\x00\x1c\xd2\x16\xa0\x00\x00\x00\x00\x1d\xc1\xf9\x90\x00\x00\x00\x00\x1e\xb1\xf8\xa0\x00\x00\x00\x00\x1f\xa1ې\x00\x00\x00\x00 v+ \x00\x00\x00\x00!\x81\xbd\x90\x00\x00\x00\x00\"V\r \x00\x00\x00\x00#j" + - "\xda\x10\x00\x00\x00\x00$5\xef \x00\x00\x00\x00%J\xbc\x10\x00\x00\x00\x00&\x15\xd1 \x00\x00\x00\x00'*\x9e\x10\x00\x00\x00\x00'\xfe\xed\xa0\x00\x00\x00\x00)\n\x80\x10\x00\x00\x00\x00)\xdeϠ\x00\x00" + - "\x00\x00*\xeab\x10\x00\x00\x00\x00+\xbe\xb1\xa0\x00\x00\x00\x00,\xd3~\x90\x00\x00\x00\x00-\x9e\x93\xa0\x00\x00\x00\x00.\xb3`\x90\x00\x00\x00\x00/~u\xa0\x00\x00\x00\x000\x93B\x90\x00\x00\x00\x001g" + - "\x92 \x00\x00\x00\x002s$\x90\x00\x00\x00\x003Gt \x00\x00\x00\x004S\x06\x90\x00\x00\x00\x005'V \x00\x00\x00\x0062\xe8\x90\x00\x00\x00\x007\a8 \x00\x00\x00\x008\x1c\x05\x10\x00\x00" + - "\x00\x008\xe7\x1a \x00\x00\x00\x009\xfb\xe7\x10\x00\x00\x00\x00:\xc6\xfc \x00\x00\x00\x00;\xdb\xc9\x10\x00\x00\x00\x00<\xb0\x18\xa0\x00\x00\x00\x00=\xbb\xab\x10\x00\x00\x00\x00>\x8f\xfa\xa0\x00\x00\x00\x00?\x9b" + - "\x8d\x10\x00\x00\x00\x00@oܠ\x00\x00\x00\x00A\x84\xa9\x90\x00\x00\x00\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b\x90\x00\x00\x00\x00D/\xa0\xa0\x00\x00\x00\x00EDm\x90\x00\x00\x00\x00E\xf3\xd3 \x01\x00" + - "\x01\x00\x02\x03\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01" + - "\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\xff\xff\x8f\x80\x00\x04\xff\xff\x9d\x90\x01\x00\xff\xff\x9d\x90\x01\b\xff\xff\x9d\x90\x01\fPDT\x00PST\x00PW" + - "T\x00PPT\x00\nPST8PDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xee\xf0BB\xff\x01\x00\x00\xff\x01\x00\x00\x03\x00\x1c\x00" + - "ROCUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00)\x00\x00" + - "\x00\x04\x00\x00\x00\x10\xff\xff\xff\xfft\xce\xf0\x18\xff\xff\xff\xff\xc3UI\x80\xff\xff\xff\xff\xd2TY\x80\xff\xff\xff\xffӋ{\x80\xff\xff\xff\xff\xd4B\xad\xf0\xff\xff\xff\xff\xd5E\"\x00\xff\xff\xff\xff\xd6L" + - "\xbf\xf0\xff\xff\xff\xff\xd7<\xbf\x00\xff\xff\xff\xff\xd8\x06fp\xff\xff\xff\xff\xd9\x1d\xf2\x80\xff\xff\xff\xff\xd9\xe7\x99\xf0\xff\xff\xff\xff\xda\xff&\x00\xff\xff\xff\xff\xdb\xc8\xcdp\xff\xff\xff\xff\xdc\xe0Y\x80\xff\xff" + - "\xff\xffݪ\x00\xf0\xff\xff\xff\xff\xders\x00\xff\xff\xff\xffߵdp\xff\xff\xff\xff\xe0|\x85\x00\xff\xff\xff\xffᖗ\xf0\xff\xff\xff\xff\xe2]\xb8\x80\xff\xff\xff\xff\xe3w\xcbp\xff\xff\xff\xff\xe4>" + - "\xec\x00\xff\xff\xff\xff\xe50 p\xff\xff\xff\xff\xe6!q\x00\xff\xff\xff\xff\xe7\x12\xa5p\xff\xff\xff\xff\xe8\x02\xa4\x80\xff\xff\xff\xff\xe8\xf3\xd8\xf0\xff\xff\xff\xff\xe9\xe3\xd8\x00\xff\xff\xff\xff\xea\xd5\fp\xff\xff" + - "\xff\xff\xeb\xc5\v\x80\xff\xff\xff\xff\xec\xb6?\xf0\xff\xff\xff\xff\xed\xf7\xfc\x00\xff\xff\xff\xff\xee\x98\xc4\xf0\xff\xff\xff\xff\xef\xd9/\x80\xff\xff\xff\xff\xf0y\xf8p\x00\x00\x00\x00\a\xfcV\x00\x00\x00\x00\x00\b\xed" + - "\x8ap\x00\x00\x00\x00\t݉\x80\x00\x00\x00\x00\nν\xf0\x00\x00\x00\x00\x11ۡ\x80\x00\x00\x00\x00\x12T\xddp\x01\x02\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03" + - "\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x00\x00q\xe8\x00\x00\x00\x00p\x80\x00\x04\x00\x00~\x90\x00\b\x00\x00~\x90\x01\fLMT\x00CST\x00JST\x00CDT\x00\nCST-" + - "8\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xc7X,Y\x9f\x01\x00\x00\x9f\x01\x00\x00\x03\x00\x1c\x00ROKUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8" + - "\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00\x06\x00\x00\x00\x10\xff\xff\xff\xff\x8b\xd7\xf0x\xff\xff\xff\xff\x92\xe6\x16\xf8\xff\xff\xff\xff\xd2C" + - "'\xf0\xff\xff\xff\xff\xd7e\x8fp\xff\xff\xff\xff\xd7\xee\x9d`\xff\xff\xff\xff\xd8\xf8\xfap\xff\xff\xff\xff\xd9\xcd-\xe0\xff\xff\xff\xff\xda\u05ca\xf0\xff\xff\xff\xffۭ\x0f\xe0\xff\xff\xff\xff\xdc\xe6\xe2\xf0\xff\xff" + - "\xff\xff\u074c\xf1\xe0\xff\xff\xff\xff\xe2O)\xf0\xff\xff\xff\xff\xe4k\xb7\xf8\xff\xff\xff\xff\xe5\x13\x18h\xff\xff\xff\xff\xe6b\x03x\xff\xff\xff\xff\xe7\x11L\xe8\xff\xff\xff\xff\xe8/px\xff\xff\xff\xff\xe8\xe7" + - "\xf4h\xff\xff\xff\xff\xea\x0fRx\xff\xff\xff\xff\xea\xc7\xd6h\xff\xff\xff\xff\xeb\xef4x\xff\xff\xff\xff째h\xff\xff\xff\xff\xed\xcf\x16x\xff\xff\xff\xff\ue1dah\xff\xff\xff\xff\xf05qx\x00\x00" + - "\x00\x00 \xa3`\x90\x00\x00\x00\x00!ng\x90\x00\x00\x00\x00\"\x83B\x90\x00\x00\x00\x00#NI\x90\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x01\x05\x01\x05\x01\x05\x01\x05\x01\x05\x01\x05\x01\x04\x03\x04\x03\x04\x00" + - "\x00w\b\x00\x00\x00\x00w\x88\x00\x04\x00\x00~\x90\x00\b\x00\x00\x8c\xa0\x01\f\x00\x00~\x90\x00\x04\x00\x00\x85\x98\x01\fLMT\x00KST\x00JST\x00KDT\x00\nKST-9\nPK" + - "\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x06\xaa>\xa8\x00\x01\x00\x00\x00\x01\x00\x00\t\x00\x1c\x00SingaporeUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00" + - "\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif" + - "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\x00\x00\x00\b\x00\x00\x00 \xff\xff\xff\xff~6S\xa3\xff\xff\xff\xff\x86\x83\x85\xa3\xff\xff\xff\xff" + - "\xbagN\x90\xff\xff\xff\xff\xc0\n\xe4`\xff\xff\xff\xffʳ\xe5`\xff\xff\xff\xffˑ_\b\xff\xff\xff\xff\xd2Hm\xf0\x00\x00\x00\x00\x16\x91\xf5\b\x01\x02\x03\x04\x05\x06\x05\a\x00\x00a]\x00\x00\x00\x00" + - "a]\x00\x04\x00\x00bp\x00\b\x00\x00g \x01\f\x00\x00g \x00\f\x00\x00ix\x00\x12\x00\x00~\x90\x00\x18\x00\x00p\x80\x00\x1cLMT\x00SMT\x00+07\x00+0720\x00+0" + - "730\x00+09\x00+08\x00\n<+08>-8\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\aW\x10Ѱ\x04\x00\x00\xb0\x04\x00\x00\x06\x00\x1c\x00TurkeyUT\t" + - "\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00s\x00\x00\x00\x06\x00\x00\x00\x19" + - "\xff\xff\xff\xffV\xb6\xc8\xd8\xff\xff\xff\xff\x90\x8b\xf5\x98\xff\xff\xff\xff\x9b\f\x17`\xff\xff\xff\xff\x9bվ\xd0\xff\xff\xff\xff\xa2ec\xe0\xff\xff\xff\xff\xa3{\x82P\xff\xff\xff\xff\xa4N\x80`\xff\xff\xff\xff" + - "\xa5?\xb4\xd0\xff\xff\xff\xff\xa6%'\xe0\xff\xff\xff\xff\xa7'\u007f\xd0\xff\xff\xff\xff\xaa((`\xff\xff\xff\xff\xaa\xe1\xfd\xd0\xff\xff\xff\xff\xab\xf9\x89\xe0\xff\xff\xff\xff\xac\xc31P\xff\xff\xff\xffȁ?\xe0" + - "\xff\xff\xff\xff\xc9\x01\x13P\xff\xff\xff\xff\xc9J\xf5`\xff\xff\xff\xff\xca\u0380P\xff\xff\xff\xff\xcbˮ`\xff\xff\xff\xff\xd2k\tP\xff\xff\xff\xffӢ9`\xff\xff\xff\xff\xd4C\x02P\xff\xff\xff\xff" + - "\xd5L\r\xe0\xff\xff\xff\xff\xd6){\xd0\xff\xff\xff\xff\xd7+\xef\xe0\xff\xff\xff\xff\xd8\t]\xd0\xff\xff\xff\xff\xd9\x02\x97`\xff\xff\xff\xff\xd9\xe9?\xd0\xff\xff\xff\xff\xda\xeb\xb3\xe0\xff\xff\xff\xff\xdb\xd2\\P" + - "\xff\xff\xff\xff\xdc\xd4\xd0`\xff\xff\xff\xffݲ>P\xff\xff\xff\xff\xf1\xf4\xb9`\xff\xff\xff\xff\xf4b\xefP\xff\xff\xff\xff\xf5h\x06`\xff\xff\xff\xff\xf6\x1f8\xd0\x00\x00\x00\x00\x06n\x93p\x00\x00\x00\x00" + - "\a9\x9ap\x00\x00\x00\x00\a\xfbu\x00\x00\x00\x00\x00\t\x19|p\x00\x00\x00\x00\t\xd0\xcb\x00\x00\x00\x00\x00\n\xf9^p\x00\x00\x00\x00\v\xb1\xfe\x80\x00\x00\x00\x00\f\xd9@p\x00\x00\x00\x00\r\xa4U\x80" + - "\x00\x00\x00\x00\x0e\xa6\xadp\x00\x00\x00\x00\x0f\x847\x80\x00\x00\x00\x00\x0f\xf8\x11P\x00\x00\x00\x00\x19\x89\xb0p\x00\x00\x00\x00\x19ܰ\xe0\x00\x00\x00\x00\x1b\xe6\xd0\xf0\x00\x00\x00\x00\x1c\xc6\xef\xf0\x00\x00\x00\x00" + - "\x1d\x9b1p\x00\x00\x00\x00\x1e\x8cs\xf0\x00\x00\x00\x00\x1f|d\xf0\x00\x00\x00\x00 lU\xf0\x00\x00\x00\x00!\\F\xf0\x00\x00\x00\x00\"L7\xf0\x00\x00\x00\x00#<(\xf0\x00\x00\x00\x00$,\x19\xf0" + - "\x00\x00\x00\x00%\x1c\n\xf0\x00\x00\x00\x00&\v\xfb\xf0\x00\x00\x00\x00'\x05'p\x00\x00\x00\x00'\xf5\x18p\x00\x00\x00\x00(\xe5\tp\x00\x00\x00\x00)\xd4\xfap\x00\x00\x00\x00*\xc4\xebp\x00\x00\x00\x00" + - "+\xb4\xdcp\x00\x00\x00\x00,\xa4\xcdp\x00\x00\x00\x00-\x8b\x83\xf0\x00\x00\x00\x00.\x84\xafp\x00\x00\x00\x00/t\xa0p\x00\x00\x00\x000d\x91p\x00\x00\x00\x001]\xbc\xf0\x00\x00\x00\x002r\x97\xf0" + - "\x00\x00\x00\x003=\x9e\xf0\x00\x00\x00\x004Ry\xf0\x00\x00\x00\x005\x1d\x80\xf0\x00\x00\x00\x0062[\xf0\x00\x00\x00\x006\xfdb\xf0\x00\x00\x00\x008\x1bxp\x00\x00\x00\x008\xddD\xf0\x00\x00\x00\x00" + - "9\xfbZp\x00\x00\x00\x00:\xbd&\xf0\x00\x00\x00\x00;\xdb\x86%p\x00\x00\x00\x00?\x9b\x00p\x00\x00\x00\x00@f\ap" + - "\x00\x00\x00\x00A\x84\x1c\xf0\x00\x00\x00\x00BE\xe9p\x00\x00\x00\x00Cc\xfe\xf0\x00\x00\x00\x00D%\xcbp\x00\x00\x00\x00EC\xe0\xf0\x00\x00\x00\x00F\x05ɐ\x00\x00\x00\x00G#\xdf\x10\x00\x00\x00\x00" + - "G\xee\xe6\x10\x00\x00\x00\x00I\x03\xc1\x10\x00\x00\x00\x00I\xce\xc8\x10\x00\x00\x00\x00J\xe3\xa3\x10\x00\x00\x00\x00K\xae\xaa\x10\x00\x00\x00\x00L̿\x90\x00\x00\x00\x00M\x8fݐ\x00\x00\x00\x00N\xac\xa1\x90" + - "\x00\x00\x00\x00Onn\x10\x00\x00\x00\x00P\x8c\x83\x90\x00\x00\x00\x00QW\x8a\x90\x00\x00\x00\x00Rle\x90\x00\x00\x00\x00S8\xbe\x10\x00\x00\x00\x00TLG\x90\x00\x00\x00\x00U\x17N\x90\x00\x00\x00\x00" + - "V>\x9e\x90\x00\x00\x00\x00V\xf70\x90\x00\x00\x00\x00W\xcf.P\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x04\x05\x04\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + - "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x04\x00\x00\x1b(\x00\x00\x00\x00\x1bh\x00\x04\x00\x00*0\x01\b\x00\x00\x1c \x00\r\x00\x00*0\x00\x11\x00\x008@\x01\x15LMT\x00IMT\x00E" + - "EST\x00EET\x00+03\x00+04\x00\n<+03>-3\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x9f.\xe4xo\x00\x00\x00o\x00\x00\x00\x03\x00\x1c\x00UCTUT" + - "\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" + - "\x04\x00\x00\x00\x00\x00\x00UTC\x00\nUTC0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x9f.\xe4xo\x00\x00\x00o\x00\x00\x00\t\x00\x1c\x00UniversalUT\t\x00" + - "\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00" + - "\x00\x00\x00\x00\x00UTC\x00\nUTC0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x1c\x00US/UT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e" + - "`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xf6\"\x12\xfe\x0e\x05\x00\x00\x0e\x05\x00\x00\n\x00\x1c\x00US/PacificUT\t\x00" + - "\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00}\x00\x00\x00\x05\x00\x00\x00\x14\xff" + - "\xff\xff\xff^\x04\x1a\xc0\xff\xff\xff\xff\x9e\xa6H\xa0\xff\xff\xff\xff\x9f\xbb\x15\x90\xff\xff\xff\xff\xa0\x86*\xa0\xff\xff\xff\xff\xa1\x9a\xf7\x90\xff\xff\xff\xffˉ\x1a\xa0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2" + - "a&\x10\xff\xff\xff\xff\xd6\xfet\\\xff\xff\xff\xff\u0600\xad\x90\xff\xff\xff\xff\xda\xfeÐ\xff\xff\xff\xff\xdb\xc0\x90\x10\xff\xff\xff\xff\xdcޥ\x90\xff\xff\xff\xffݩ\xac\x90\xff\xff\xff\xff\u07be\x87\x90\xff" + - "\xff\xff\xff߉\x8e\x90\xff\xff\xff\xff\xe0\x9ei\x90\xff\xff\xff\xff\xe1ip\x90\xff\xff\xff\xff\xe2~K\x90\xff\xff\xff\xff\xe3IR\x90\xff\xff\xff\xff\xe4^-\x90\xff\xff\xff\xff\xe5)4\x90\xff\xff\xff\xff\xe6" + - "GJ\x10\xff\xff\xff\xff\xe7\x12Q\x10\xff\xff\xff\xff\xe8',\x10\xff\xff\xff\xff\xe8\xf23\x10\xff\xff\xff\xff\xea\a\x0e\x10\xff\xff\xff\xff\xea\xd2\x15\x10\xff\xff\xff\xff\xeb\xe6\xf0\x10\xff\xff\xff\xff\xec\xb1\xf7\x10\xff" + - "\xff\xff\xff\xed\xc6\xd2\x10\xff\xff\xff\xff\xee\x91\xd9\x10\xff\xff\xff\xff\xef\xaf\xee\x90\xff\xff\xff\xff\xf0q\xbb\x10\xff\xff\xff\xff\xf1\x8fА\xff\xff\xff\xff\xf2\u007f\xc1\x90\xff\xff\xff\xff\xf3o\xb2\x90\xff\xff\xff\xff\xf4" + - "_\xa3\x90\xff\xff\xff\xff\xf5O\x94\x90\xff\xff\xff\xff\xf6?\x85\x90\xff\xff\xff\xff\xf7/v\x90\xff\xff\xff\xff\xf8(\xa2\x10\xff\xff\xff\xff\xf9\x0fX\x90\xff\xff\xff\xff\xfa\b\x84\x10\xff\xff\xff\xff\xfa\xf8\x83 \xff" + - "\xff\xff\xff\xfb\xe8f\x10\xff\xff\xff\xff\xfc\xd8e \xff\xff\xff\xff\xfd\xc8H\x10\xff\xff\xff\xff\xfe\xb8G \xff\xff\xff\xff\xff\xa8*\x10\x00\x00\x00\x00\x00\x98) \x00\x00\x00\x00\x01\x88\f\x10\x00\x00\x00\x00\x02" + - "x\v \x00\x00\x00\x00\x03q(\x90\x00\x00\x00\x00\x04a'\xa0\x00\x00\x00\x00\x05Q\n\x90\x00\x00\x00\x00\x06A\t\xa0\x00\x00\x00\x00\a0\xec\x90\x00\x00\x00\x00\a\x8dC\xa0\x00\x00\x00\x00\t\x10ΐ\x00" + - "\x00\x00\x00\t\xad\xbf \x00\x00\x00\x00\n\xf0\xb0\x90\x00\x00\x00\x00\v\u0be0\x00\x00\x00\x00\f\xd9\xcd\x10\x00\x00\x00\x00\r\xc0\x91\xa0\x00\x00\x00\x00\x0e\xb9\xaf\x10\x00\x00\x00\x00\x0f\xa9\xae \x00\x00\x00\x00\x10" + - "\x99\x91\x10\x00\x00\x00\x00\x11\x89\x90 \x00\x00\x00\x00\x12ys\x10\x00\x00\x00\x00\x13ir \x00\x00\x00\x00\x14YU\x10\x00\x00\x00\x00\x15IT \x00\x00\x00\x00\x1697\x10\x00\x00\x00\x00\x17)6 \x00" + - "\x00\x00\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18 \x00\x00\x00\x00\x1a\x025\x90\x00\x00\x00\x00\x1a\xf24\xa0\x00\x00\x00\x00\x1b\xe2\x17\x90\x00\x00\x00\x00\x1c\xd2\x16\xa0\x00\x00\x00\x00\x1d\xc1\xf9\x90\x00\x00\x00\x00\x1e" + - "\xb1\xf8\xa0\x00\x00\x00\x00\x1f\xa1ې\x00\x00\x00\x00 v+ \x00\x00\x00\x00!\x81\xbd\x90\x00\x00\x00\x00\"V\r \x00\x00\x00\x00#j\xda\x10\x00\x00\x00\x00$5\xef \x00\x00\x00\x00%J\xbc\x10\x00" + - "\x00\x00\x00&\x15\xd1 \x00\x00\x00\x00'*\x9e\x10\x00\x00\x00\x00'\xfe\xed\xa0\x00\x00\x00\x00)\n\x80\x10\x00\x00\x00\x00)\xdeϠ\x00\x00\x00\x00*\xeab\x10\x00\x00\x00\x00+\xbe\xb1\xa0\x00\x00\x00\x00," + - "\xd3~\x90\x00\x00\x00\x00-\x9e\x93\xa0\x00\x00\x00\x00.\xb3`\x90\x00\x00\x00\x00/~u\xa0\x00\x00\x00\x000\x93B\x90\x00\x00\x00\x001g\x92 \x00\x00\x00\x002s$\x90\x00\x00\x00\x003Gt \x00" + - "\x00\x00\x004S\x06\x90\x00\x00\x00\x005'V \x00\x00\x00\x0062\xe8\x90\x00\x00\x00\x007\a8 \x00\x00\x00\x008\x1c\x05\x10\x00\x00\x00\x008\xe7\x1a \x00\x00\x00\x009\xfb\xe7\x10\x00\x00\x00\x00:" + - "\xc6\xfc \x00\x00\x00\x00;\xdb\xc9\x10\x00\x00\x00\x00<\xb0\x18\xa0\x00\x00\x00\x00=\xbb\xab\x10\x00\x00\x00\x00>\x8f\xfa\xa0\x00\x00\x00\x00?\x9b\x8d\x10\x00\x00\x00\x00@oܠ\x00\x00\x00\x00A\x84\xa9\x90\x00" + - "\x00\x00\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b\x90\x00\x00\x00\x00D/\xa0\xa0\x00\x00\x00\x00EDm\x90\x00\x00\x00\x00E\xf3\xd3 \x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x00\x00\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff~6\x18 \xff\xff\xff\xff\xc1\xed5\xd0\xff\xff\xff\xff\xc9\xea\n`\xff\xff\xff\xff\xcfF\x81\xf0\xff\xff\xff\xff\xff\x86\x1bP\x00\x00\x00\x00,v" + + "\x0e@\x01\x02\x03\x01\x04\x05\x00\x00\x9c\xe0\x00\x00\x00\x00\x9a\xb0\x00\x04\x00\x00\x8c\xa0\x00\b\x00\x00~\x90\x00\f\xff\xffW@\x00\x10\x00\x00\xa8\xc0\x00\x14LMT\x00+11\x00+10\x00+09\x00" + + "-12\x00+12\x00\n<+12>-12\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSn\x04\x19y\x9a\x00\x00\x00\x9a\x00\x00\x00\x14\x00\x1c\x00Pacific/Port" + + "_MoresbyUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\r\xff\xff\xff\xffV\xb6Z\b\xff\xff\xff\xffr\xed\xa4\x90\x01\x02\x00\x00\x89\xf8\x00\x00\x00\x00\x89\xf0\x00\x04\x00\x00\x8c\xa0\x00\tLMT\x00PMMT\x00+10\x00" + + "\n<+10>-10\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xcc\xf39a\xc3\x00\x00\x00\xc3\x00\x00\x00\r\x00\x1c\x00Pacific/ChuukUT\t\x00\x03\x82\x0f" + + "\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\f\xff\xff\xff\xff" + + "\x14\xe1\xbf4\xff\xff\xff\xff~6&\xb4\xff\xff\xff\xff\x98\x11\xa3\xe0\xff\xff\xff\xff\xa09\xf9\xf0\xff\xff\xff\xff\xc9\xea\n`\xff\xff\xff\xff\xd2\x11\x0e\xf0\x01\x02\x03\x02\x03\x02\xff\xff<\xcc\x00\x00\x00\x00\x8eL" + + "\x00\x00\x00\x00\x8c\xa0\x00\x04\x00\x00~\x90\x00\bLMT\x00+10\x00+09\x00\n<+10>-10\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xcc\xf39a\xc3\x00\x00\x00\xc3\x00" + + "\x00\x00\f\x00\x1c\x00Pacific/TrukUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\f\xff\xff\xff\xff\x14\xe1\xbf4\xff\xff\xff\xff~6&\xb4\xff\xff\xff\xff\x98\x11\xa3\xe0\xff\xff\xff\xff\xa09\xf9\xf0\xff\xff\xff\xff\xc9\xea\n" + + "`\xff\xff\xff\xff\xd2\x11\x0e\xf0\x01\x02\x03\x02\x03\x02\xff\xff<\xcc\x00\x00\x00\x00\x8eL\x00\x00\x00\x00\x8c\xa0\x00\x04\x00\x00~\x90\x00\bLMT\x00+10\x00+09\x00\n<+10>-10" + + "\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xc8=ku\xae\x00\x00\x00\xae\x00\x00\x00\x12\x00\x1c\x00Pacific/KiritimatiUT\t\x00\x03\x82\x0f\x8ba\x82\x0f" + + "\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" + + "\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xff~7H\x80" + + "\x00\x00\x00\x00\x12U\xf2\x00\x00\x00\x00\x00/\x05+\xa0\x01\x02\x03\xff\xffl\x80\x00\x00\xff\xffj\x00\x00\x04\xff\xffs`\x00\n\x00\x00\xc4\xe0\x00\x0eLMT\x00-1040\x00-10\x00+14" + + "\x00\n<+14>-14\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS1\xce_(\x86\x00\x00\x00\x86\x00\x00\x00\x0e\x00\x1c\x00Pacific/WallisUT\t\x00\x03" + + "\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\b\xff\xff" + + "\xff\xff~6\b\xa8\x01\x00\x00\xacX\x00\x00\x00\x00\xa8\xc0\x00\x04LMT\x00+12\x00\n<+12>-12\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x96\xc5FF(\x03\x00\x00(" + + "\x03\x00\x00\x0f\x00\x1c\x00Pacific/ChathamUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00E\x00\x00\x00\x04\x00\x00\x00\x16\xff\xff\xff\xffA\xb7D\x84\xff\xff\xff\xff\xd2ږ\xbc\x00\x00\x00\x00\t\x18\xfd\xe0\x00\x00\x00\x00\t\xac\xa5\xe0\x00\x00\x00" + + "\x00\n\xef\xa5`\x00\x00\x00\x00\v\x9e\xfc\xe0\x00\x00\x00\x00\f\xd8\xc1\xe0\x00\x00\x00\x00\r~\xde\xe0\x00\x00\x00\x00\x0e\xb8\xa3\xe0\x00\x00\x00\x00\x0f^\xc0\xe0\x00\x00\x00\x00\x10\x98\x85\xe0\x00\x00\x00\x00\x11>\xa2" + + "\xe0\x00\x00\x00\x00\x12xg\xe0\x00\x00\x00\x00\x13\x1e\x84\xe0\x00\x00\x00\x00\x14XI\xe0\x00\x00\x00\x00\x14\xfef\xe0\x00\x00\x00\x00\x168+\xe0\x00\x00\x00\x00\x16\xe7\x83`\x00\x00\x00\x00\x18!H`\x00\x00\x00" + + "\x00\x18\xc7e`\x00\x00\x00\x00\x1a\x01*`\x00\x00\x00\x00\x1a\xa7G`\x00\x00\x00\x00\x1b\xe1\f`\x00\x00\x00\x00\x1c\x87)`\x00\x00\x00\x00\x1d\xc0\xee`\x00\x00\x00\x00\x1eg\v`\x00\x00\x00\x00\x1f\xa0\xd0" + + "`\x00\x00\x00\x00 F\xed`\x00\x00\x00\x00!\x80\xb2`\x00\x00\x00\x00\"0\t\xe0\x00\x00\x00\x00#i\xce\xe0\x00\x00\x00\x00$\x0f\xeb\xe0\x00\x00\x00\x00%.\x01`\x00\x00\x00\x00&\x02B\xe0\x00\x00\x00" + + "\x00'\r\xe3`\x00\x00\x00\x00'\xe2$\xe0\x00\x00\x00\x00(\xed\xc5`\x00\x00\x00\x00)\xc2\x06\xe0\x00\x00\x00\x00*ͧ`\x00\x00\x00\x00+\xab#`\x00\x00\x00\x00,\xad\x89`\x00\x00\x00\x00-\x8b\x05" + + "`\x00\x00\x00\x00.\x8dk`\x00\x00\x00\x00/j\xe7`\x00\x00\x00\x000mM`\x00\x00\x00\x001J\xc9`\x00\x00\x00\x002Vi\xe0\x00\x00\x00\x003*\xab`\x00\x00\x00\x0046K\xe0\x00\x00\x00" + + "\x005\n\x8d`\x00\x00\x00\x006\x16-\xe0\x00\x00\x00\x006\xf3\xa9\xe0\x00\x00\x00\x007\xf6\x0f\xe0\x00\x00\x00\x008Ӌ\xe0\x00\x00\x00\x009\xd5\xf1\xe0\x00\x00\x00\x00:\xb3m\xe0\x00\x00\x00\x00;\xbf\x0e" + + "`\x00\x00\x00\x00<\x93O\xe0\x00\x00\x00\x00=\x9e\xf0`\x00\x00\x00\x00>s1\xe0\x00\x00\x00\x00?~\xd2`\x00\x00\x00\x00@\\N`\x00\x00\x00\x00A^\xb4`\x00\x00\x00\x00B<0`\x00\x00\x00" + + "\x00C>\x96`\x00\x00\x00\x00D\x1c\x12`\x00\x00\x00\x00E\x1ex`\x00\x00\x00\x00E\xfb\xf4`\x00\x00\x00\x00F\xfeZ`\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x00\x00\xab\xfc\x00\x00\x00\x00\xacD\x00\x04\x00\x00" + + "\xc1\\\x01\n\x00\x00\xb3L\x00\x10LMT\x00+1215\x00+1345\x00+1245\x00\n<+1245>-12:45<+1345>,M9.5.0" + + "/2:45,M4.1.0/3:45\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSFI\xfe\x14^\x01\x00\x00^\x01\x00\x00\x0e\x00\x1c\x00Pacific/Saip" + + "anUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15\x00\x00\x00" + + "\x06\x00\x00\x00\x15\xff\xff\xff\xff\x14\xe1\xc5\xcc\xff\xff\xff\xff~6-L\xff\xff\xff\xff\xcb7\x95\xe0\xff\xff\xff\xff\xd0.\x89\xf0\xff\xff\xff\xff\xec7\xbe\x00\xff\xff\xff\xff\xef6\xf8\xf0\xff\xff\xff\xff\xfb\x9b\x00" + + "\x00\xff\xff\xff\xff\xfe?'\x8c\xff\xff\xff\xff\xff\x01\x1e\x00\xff\xff\xff\xff\xff]X\xf0\x00\x00\x00\x00\x00\x97,\x00\x00\x00\x00\x00\x01Fup\x00\x00\x00\x00\x02w\x0e\x00\x00\x00\x00\x00\x03&Wp\x00\x00\x00" + + "\x00\ap\x97\x00\x00\x00\x00\x00\a\xcc\xd1\xf0\x00\x00\x00\x00\f\b\x91\x00\x00\x00\x00\x00\f|\x87,\x00\x00\x00\x00\r\xbf\x94\x80\x00\x00\x00\x00\x0ee\xa3p\x00\x00\x00\x00:C^`\x01\x02\x03\x02\x04\x02\x04" + + "\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x04\x02\x05\xff\xff64\x00\x00\x00\x00\x87\xb4\x00\x00\x00\x00\x8c\xa0\x00\x04\x00\x00~\x90\x00\b\x00\x00\x9a\xb0\x01\f\x00\x00\x8c\xa0\x00\x10LMT\x00GST\x00+0" + + "9\x00GDT\x00ChST\x00\nChST-10\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xee\xd0\x1cYN\x04\x00\x00N\x04\x00\x00\x0e\x00\x1c\x00Pacific/Ea" + + "sterUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\x00" + + "\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xffi\x87B\b\xff\xff\xff\xff\xb9\xc7@\x88\xff\xff\xff\xff\xfd\xd1<@\xff\xff\xff\xff\xfe\x92\xfa\xb0\xff\xff\xff\xff\xff\xcc\xcd\xc0\x00\x00\x00\x00\x00rܰ\x00\x00\x00\x00\x01" + + "uP\xc0\x00\x00\x00\x00\x02@I\xb0\x00\x00\x00\x00\x03U2\xc0\x00\x00\x00\x00\x04 +\xb0\x00\x00\x00\x00\x05>O@\x00\x00\x00\x00\x06\x00\r\xb0\x00\x00\x00\x00\a\v\xbc@\x00\x00\x00\x00\a\xdf\xef\xb0\x00" + + "\x00\x00\x00\b\xfe\x13@\x00\x00\x00\x00\t\xbfѰ\x00\x00\x00\x00\n\xdd\xf5@\x00\x00\x00\x00\v\xa8\xee0\x00\x00\x00\x00\f\xbd\xd7@\x00\x00\x00\x00\r\x88\xd00\x00\x00\x00\x00\x0e\x9d\xb9@\x00\x00\x00\x00\x0f" + + "h\xb20\x00\x00\x00\x00\x10\x86\xd5\xc0\x00\x00\x00\x00\x11H\x940\x00\x00\x00\x00\x12f\xb7\xc0\x00\x00\x00\x00\x13(v0\x00\x00\x00\x00\x14F\x99\xc0\x00\x00\x00\x00\x15\x11\x92\xb0\x00\x00\x00\x00\x16&{\xc0\x00" + + "\x00\x00\x00\x16\xf1t\xb0\x00\x00\x00\x00\x18\x06]\xc0\x00\x00\x00\x00\x18\xd1V\xb0\x00\x00\x00\x00\x19\xe6?\xc0\x00\x00\x00\x00\x1a\xb18\xb0\x00\x00\x00\x00\x1b\xcf\\@\x00\x00\x00\x00\x1c\x91\x1a\xb0\x00\x00\x00\x00\x1d" + + "\xaf>@\x00\x00\x00\x00\x1ep\xfc\xb0\x00\x00\x00\x00\x1f\x8f @\x00\x00\x00\x00 \u007f\x030\x00\x00\x00\x00!o\x02@\x00\x00\x00\x00\"9\xfb0\x00\x00\x00\x00#N\xe4@\x00\x00\x00\x00$\x19\xdd0\x00" + + "\x00\x00\x00%8\x00\xc0\x00\x00\x00\x00%\xf9\xbf0\x00\x00\x00\x00&\xf2\xf8\xc0\x00\x00\x00\x00'١0\x00\x00\x00\x00(\xf7\xc4\xc0\x00\x00\x00\x00)½\xb0\x00\x00\x00\x00*צ\xc0\x00\x00\x00\x00+" + + "\xa2\x9f\xb0\x00\x00\x00\x00,\xb7\x88\xc0\x00\x00\x00\x00-\x82\x81\xb0\x00\x00\x00\x00.\x97j\xc0\x00\x00\x00\x00/bc\xb0\x00\x00\x00\x000\x80\x87@\x00\x00\x00\x001BE\xb0\x00\x00\x00\x002`i@\x00" + + "\x00\x00\x003=\xd70\x00\x00\x00\x004@K@\x00\x00\x00\x005\vD0\x00\x00\x00\x006\r\xb8@\x00\x00\x00\x007\x06հ\x00\x00\x00\x008\x00\x0f@\x00\x00\x00\x008\xcb\b0\x00\x00\x00\x009" + + "\xe9+\xc0\x00\x00\x00\x00:\xaa\xea0\x00\x00\x00\x00;\xc9\r\xc0\x00\x00\x00\x00<\x8a\xcc0\x00\x00\x00\x00=\xa8\xef\xc0\x00\x00\x00\x00>j\xae0\x00\x00\x00\x00?\x88\xd1\xc0\x00\x00\x00\x00@Sʰ\x00" + + "\x00\x00\x00Ah\xb3\xc0\x00\x00\x00\x00B3\xac\xb0\x00\x00\x00\x00CH\x95\xc0\x00\x00\x00\x00D\x13\x8e\xb0\x00\x00\x00\x00E1\xb2@\x00\x00\x00\x00E\xf3p\xb0\x00\x00\x00\x00G\x11\x94@\x00\x00\x00\x00G" + + "\xef\x020\x00\x00\x00\x00H\xf1v@\x00\x00\x00\x00I\xbco0\x00\x00\x00\x00J\xd1X@\x00\x00\x00\x00K\xb8\x00\xb0\x00\x00\x00\x00L\xb1:@\x00\x00\x00\x00M\xc6\a0\x00\x00\x00\x00NP\x82\xc0\x00" + + "\x00\x00\x00O\x9c\xae\xb0\x00\x00\x00\x00PB\xd9\xc0\x00\x00\x00\x00Q|\x90\xb0\x00\x00\x00\x00R+\xf6@\x00\x00\x00\x00S\\r\xb0\x00\x00\x00\x00T\v\xd8@\x00\x00\x00\x00W7\xe60\x00\x00\x00\x00W" + + "\xaf\xec\xc0\x00\x00\x00\x00Y\x17\xc80\x00\x00\x00\x00Y\x8f\xce\xc0\x00\x00\x00\x00Z\xf7\xaa0\x00\x00\x00\x00[o\xb0\xc0\x00\x00\x00\x00\\\xa9g\xb0\x01\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05" + + "\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\x05\x04\xff\xff\x99x\x00\x00\xff\xff\x99x\x00\x04\xff\xff\xab\xa0\x01\b\xff\xff\x9d\x90\x00\f\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01" + + "\x10LMT\x00EMT\x00-06\x00-07\x00-05\x00\n<-06>6<-05>,M9.1.6/22,M4.1.6/22\nPK\x03\x04\n\x00" + + "\x00\x00\x00\x00#\x82iS\xa8A\x15\xfe\x97\x01\x00\x00\x97\x01\x00\x00\f\x00\x1c\x00Pacific/ApiaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04" + + "S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1a\x00\x00\x00\a\x00\x00\x00\x1a\xff\xff\xff\xffn=\xc9\x00\xff\xff\xff\xff\x91\x05\xfc\x00\xff\xff\xff\xff\xda" + + "b\x048\x00\x00\x00\x00L\x9f'\xb0\x00\x00\x00\x00M\x97+\xe0\x00\x00\x00\x00N}\xe2`\x00\x00\x00\x00N\xfd\x8b\xa0\x00\x00\x00\x00Ow\r\xe0\x00\x00\x00\x00Pf\xfe\xe0\x00\x00\x00\x00Q`*`\x00" + + "\x00\x00\x00RF\xe0\xe0\x00\x00\x00\x00S@\f`\x00\x00\x00\x00T&\xc2\xe0\x00\x00\x00\x00U\x1f\xee`\x00\x00\x00\x00V\x06\xa4\xe0\x00\x00\x00\x00V\xff\xd0`\x00\x00\x00\x00W\xe6\x86\xe0\x00\x00\x00\x00X" + + "߲`\x00\x00\x00\x00Y\xc6h\xe0\x00\x00\x00\x00Z\xbf\x94`\x00\x00\x00\x00[\xaf\x85`\x00\x00\x00\x00\\\xa8\xb0\xe0\x00\x00\x00\x00]\x8fg`\x00\x00\x00\x00^\x88\x92\xe0\x00\x00\x00\x00_oI`\x00" + + "\x00\x00\x00`ht\xe0\x01\x02\x04\x03\x04\x03\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x00\x00\xb0\x80\x00\x00\xff\xff_\x00\x00\x00\xff\xff^H\x00\x04\xff\xffs`\x01\n\xff\xffe" + + "P\x00\x0e\x00\x00\xb6\xd0\x00\x12\x00\x00\xc4\xe0\x01\x16LMT\x00-1130\x00-10\x00-11\x00+13\x00+14\x00\n<+13>-13\nPK\x03\x04\n\x00\x00\x00\x00" + + "\x00#\x82iS\x1c\xe3\xa3S\x96\x01\x00\x00\x96\x01\x00\x00\x11\x00\x1c\x00Pacific/RarotongaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00" + + "\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZi" + + "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff|L\xdc\xc8\xff\xff\xff\xffߡ`\xc8\x00\x00\x00" + + "\x00\x10\xac\x1b(\x00\x00\x00\x00\x11?\xb5\x18\x00\x00\x00\x00\x12y\x81 \x00\x00\x00\x00\x13\x1f\x97\x18\x00\x00\x00\x00\x14Yc \x00\x00\x00\x00\x14\xffy\x18\x00\x00\x00\x00\x169E \x00\x00\x00\x00\x16\xe8\x95" + + "\x98\x00\x00\x00\x00\x18\"a\xa0\x00\x00\x00\x00\x18\xc8w\x98\x00\x00\x00\x00\x1a\x02C\xa0\x00\x00\x00\x00\x1a\xa8Y\x98\x00\x00\x00\x00\x1b\xe2%\xa0\x00\x00\x00\x00\x1c\x88;\x98\x00\x00\x00\x00\x1d\xc2\a\xa0\x00\x00\x00" + + "\x00\x1eh\x1d\x98\x00\x00\x00\x00\x1f\xa1\xe9\xa0\x00\x00\x00\x00 G\xff\x98\x00\x00\x00\x00!\x81ˠ\x00\x00\x00\x00\"1\x1c\x18\x00\x00\x00\x00#j\xe8 \x00\x00\x00\x00$\x10\xfe\x18\x00\x00\x00\x00%J\xca" + + " \x00\x00\x00\x00%\xf0\xe0\x18\x00\x00\x00\x00'*\xac \x00\x00\x00\x00'\xd0\xc2\x18\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x00\x00\xbb\xb8\x00\x00\xff" + + "\xffj8\x00\x00\xff\xfflX\x00\x04\xff\xffs`\x00\n\xff\xffzh\x01\x0eLMT\x00-1030\x00-10\x00-0930\x00\n<-10>10\nPK\x03\x04\n\x00\x00\x00" + + "\x00\x00#\x82iS>\xfe垛\x03\x00\x00\x9b\x03\x00\x00\x06\x00\x1c\x00PolandUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif" + + "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00R\x00\x00\x00\x06\x00\x00\x00\x1a\xff\xff\xff\xffV\xb6\xd0P\xff\xff\xff\xff\x99\xa8*\xd0\xff\xff\xff\xff\x9b\f\x17`\xff\xff\xff\xff\x9b" + + "\xd5\xda\xf0\xff\xff\xff\xff\x9cٮ\x90\xff\xff\xff\xff\x9d\xa4\xb5\x90\xff\xff\xff\xff\x9e\xb9\x90\x90\xff\xff\xff\xff\x9f\x84\x97\x90\xff\xff\xff\xff\xa0\x9a\xb6\x00\xff\xff\xff\xff\xa1e\xbd\x00\xff\xff\xff\xff\xa6}|`\xff" + + "\xff\xff\xff\xc8v\xde\x10\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЄ\xba\x00\xff\xff\xff\xffѕ\x92p\xff\xff\xff\xff\xd2" + + "\x8a\xbb`\xff\xff\xff\xff\xd3b\xffp\xff\xff\xff\xff\xd4K#\x90\xff\xff\xff\xff\xd5^\xad\x10\xff\xff\xff\xff\xd6)\xb4\x10\xff\xff\xff\xff\xd7,\x1a\x10\xff\xff\xff\xff\xd8\t\x96\x10\xff\xff\xff\xff\xd9\x02\xc1\x90\xff" + + "\xff\xff\xff\xd9\xe9x\x10\xff\xff\xff\xff\xe8T\xd2\x00\xff\xff\xff\xff\xe8\xf1\xb4\x80\xff\xff\xff\xff\xe9᥀\xff\xff\xff\xff\xeaі\x80\xff\xff\xff\xff\xec\x14\x96\x00\xff\xff\xff\xff캳\x00\xff\xff\xff\xff\xed" + + "\xaa\xa4\x00\xff\xff\xff\xff\ue695\x00\xff\xff\xff\xff\xef\xd4Z\x00\xff\xff\xff\xff\xf0zw\x00\xff\xff\xff\xff\xf1\xb4<\x00\xff\xff\xff\xff\xf2ZY\x00\xff\xff\xff\xff\xf3\x94\x1e\x00\xff\xff\xff\xff\xf4:;\x00\xff" + + "\xff\xff\xff\xf5}:\x80\xff\xff\xff\xff\xf6\x1a\x1d\x00\x00\x00\x00\x00\r\xa4U\x80\x00\x00\x00\x00\x0e\x8b\f\x00\x00\x00\x00\x00\x0f\x847\x80\x00\x00\x00\x00\x10t(\x80\x00\x00\x00\x00\x11d\x19\x80\x00\x00\x00\x00\x12" + + "T\n\x80\x00\x00\x00\x00\x13M6\x00\x00\x00\x00\x00\x143\xec\x80\x00\x00\x00\x00\x15#݀\x00\x00\x00\x00\x16\x13\u0380\x00\x00\x00\x00\x17\x03\xbf\x80\x00\x00\x00\x00\x17\xf3\xb0\x80\x00\x00\x00\x00\x18㡀\x00" + + "\x00\x00\x00\x19Ӓ\x80\x00\x00\x00\x00\x1aÃ\x80\x00\x00\x00\x00\x1b\xbc\xaf\x00\x00\x00\x00\x00\x1c\xac\xa0\x00\x00\x00\x00\x00\x1d\x9c\x91\x00\x00\x00\x00\x00\x1e\x8c\x82\x00\x00\x00\x00\x00\x1f|s\x00\x00\x00\x00\x00 " + + "ld\x00\x00\x00\x00\x00!\\U\x00\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#\xf0\xff\xff\xff\xffӋ{\x80\xff\xff\xff\xff\xd4B\xad\xf0\xff\xff\xff\xff\xd5E\"\x00\xff\xff\xff\xff\xd6L\xbf\xf0\xff" + + "\xff\xff\xff\xd7<\xbf\x00\xff\xff\xff\xff\xd8\x06fp\xff\xff\xff\xff\xd9\x1d\xf2\x80\xff\xff\xff\xff\xd9A|\xf0\x00\x00\x00\x00\x1e\xbaR \x00\x00\x00\x00\x1fi\x9b\x90\x00\x00\x00\x00 ~\x84\xa0\x00\x00\x00\x00!" + + "I}\x90\x00\x00\x00\x00\"g\xa1 \x00\x00\x00\x00#)_\x90\x00\x00\x00\x00$G\x83 \x00\x00\x00\x00%\x12|\x10\x00\x00\x00\x00&'e \x00\x00\x00\x00&\xf2^\x10\x00\x00\x00\x00(\aG \x00" + + "\x00\x00\x00(\xd2@\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x00q\xd7\x00\x00\x00\x00~\x90\x01\x04\x00\x00p\x80\x00\bLMT\x00CD" + + "T\x00CST\x00\nCST-8\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSŭV\xad\xb7\x03\x00\x00\xb7\x03\x00\x00\a\x00\x1c\x00PST8PDTUT\t\x00\x03\x82\x0f\x8ba\x82" + + "\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00" + + "\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00X\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff\x9e\xa6H" + + "\xa0\xff\xff\xff\xff\x9f\xbb\x15\x90\xff\xff\xff\xff\xa0\x86*\xa0\xff\xff\xff\xff\xa1\x9a\xf7\x90\xff\xff\xff\xffˉ\x1a\xa0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a&\x10\xff\xff\xff\xff\xfa\xf8\x83 \xff\xff\xff" + + "\xff\xfb\xe8f\x10\xff\xff\xff\xff\xfc\xd8e \xff\xff\xff\xff\xfd\xc8H\x10\xff\xff\xff\xff\xfe\xb8G \xff\xff\xff\xff\xff\xa8*\x10\x00\x00\x00\x00\x00\x98) \x00\x00\x00\x00\x01\x88\f\x10\x00\x00\x00\x00\x02x\v" + + " \x00\x00\x00\x00\x03q(\x90\x00\x00\x00\x00\x04a'\xa0\x00\x00\x00\x00\x05Q\n\x90\x00\x00\x00\x00\x06A\t\xa0\x00\x00\x00\x00\a0\xec\x90\x00\x00\x00\x00\a\x8dC\xa0\x00\x00\x00\x00\t\x10ΐ\x00\x00\x00" + + "\x00\t\xad\xbf \x00\x00\x00\x00\n\xf0\xb0\x90\x00\x00\x00\x00\v\u0be0\x00\x00\x00\x00\f\xd9\xcd\x10\x00\x00\x00\x00\r\xc0\x91\xa0\x00\x00\x00\x00\x0e\xb9\xaf\x10\x00\x00\x00\x00\x0f\xa9\xae \x00\x00\x00\x00\x10\x99\x91" + + "\x10\x00\x00\x00\x00\x11\x89\x90 \x00\x00\x00\x00\x12ys\x10\x00\x00\x00\x00\x13ir \x00\x00\x00\x00\x14YU\x10\x00\x00\x00\x00\x15IT \x00\x00\x00\x00\x1697\x10\x00\x00\x00\x00\x17)6 \x00\x00\x00" + + "\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18 \x00\x00\x00\x00\x1a\x025\x90\x00\x00\x00\x00\x1a\xf24\xa0\x00\x00\x00\x00\x1b\xe2\x17\x90\x00\x00\x00\x00\x1c\xd2\x16\xa0\x00\x00\x00\x00\x1d\xc1\xf9\x90\x00\x00\x00\x00\x1e\xb1\xf8" + + "\xa0\x00\x00\x00\x00\x1f\xa1ې\x00\x00\x00\x00 v+ \x00\x00\x00\x00!\x81\xbd\x90\x00\x00\x00\x00\"V\r \x00\x00\x00\x00#j\xda\x10\x00\x00\x00\x00$5\xef \x00\x00\x00\x00%J\xbc\x10\x00\x00\x00" + + "\x00&\x15\xd1 \x00\x00\x00\x00'*\x9e\x10\x00\x00\x00\x00'\xfe\xed\xa0\x00\x00\x00\x00)\n\x80\x10\x00\x00\x00\x00)\xdeϠ\x00\x00\x00\x00*\xeab\x10\x00\x00\x00\x00+\xbe\xb1\xa0\x00\x00\x00\x00,\xd3~" + + "\x90\x00\x00\x00\x00-\x9e\x93\xa0\x00\x00\x00\x00.\xb3`\x90\x00\x00\x00\x00/~u\xa0\x00\x00\x00\x000\x93B\x90\x00\x00\x00\x001g\x92 \x00\x00\x00\x002s$\x90\x00\x00\x00\x003Gt \x00\x00\x00" + + "\x004S\x06\x90\x00\x00\x00\x005'V \x00\x00\x00\x0062\xe8\x90\x00\x00\x00\x007\a8 \x00\x00\x00\x008\x1c\x05\x10\x00\x00\x00\x008\xe7\x1a \x00\x00\x00\x009\xfb\xe7\x10\x00\x00\x00\x00:\xc6\xfc" + + " \x00\x00\x00\x00;\xdb\xc9\x10\x00\x00\x00\x00<\xb0\x18\xa0\x00\x00\x00\x00=\xbb\xab\x10\x00\x00\x00\x00>\x8f\xfa\xa0\x00\x00\x00\x00?\x9b\x8d\x10\x00\x00\x00\x00@oܠ\x00\x00\x00\x00A\x84\xa9\x90\x00\x00\x00" + + "\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b\x90\x00\x00\x00\x00D/\xa0\xa0\x00\x00\x00\x00EDm\x90\x00\x00\x00\x00E\xf3\xd3 \x01\x00\x01\x00\x02\x03\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00" + + "\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00" + + "\x01\x00\x01\x00\x01\xff\xff\x8f\x80\x00\x04\xff\xff\x9d\x90\x01\x00\xff\xff\x9d\x90\x01\b\xff\xff\x9d\x90\x01\fPDT\x00PST\x00PWT\x00PPT\x00\nPST8PDT,M3.2.0" + + ",M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xee\xf0BB\xff\x01\x00\x00\xff\x01\x00\x00\x03\x00\x1c\x00ROCUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01" + + "\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00" + + "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00)\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xfft\xce\xf0\x18\xff\xff\xff\xff\xc3UI" + + "\x80\xff\xff\xff\xff\xd2TY\x80\xff\xff\xff\xffӋ{\x80\xff\xff\xff\xff\xd4B\xad\xf0\xff\xff\xff\xff\xd5E\"\x00\xff\xff\xff\xff\xd6L\xbf\xf0\xff\xff\xff\xff\xd7<\xbf\x00\xff\xff\xff\xff\xd8\x06fp\xff\xff\xff" + + "\xff\xd9\x1d\xf2\x80\xff\xff\xff\xff\xd9\xe7\x99\xf0\xff\xff\xff\xff\xda\xff&\x00\xff\xff\xff\xff\xdb\xc8\xcdp\xff\xff\xff\xff\xdc\xe0Y\x80\xff\xff\xff\xffݪ\x00\xf0\xff\xff\xff\xff\xders\x00\xff\xff\xff\xffߵd" + + "p\xff\xff\xff\xff\xe0|\x85\x00\xff\xff\xff\xffᖗ\xf0\xff\xff\xff\xff\xe2]\xb8\x80\xff\xff\xff\xff\xe3w\xcbp\xff\xff\xff\xff\xe4>\xec\x00\xff\xff\xff\xff\xe50 p\xff\xff\xff\xff\xe6!q\x00\xff\xff\xff" + + "\xff\xe7\x12\xa5p\xff\xff\xff\xff\xe8\x02\xa4\x80\xff\xff\xff\xff\xe8\xf3\xd8\xf0\xff\xff\xff\xff\xe9\xe3\xd8\x00\xff\xff\xff\xff\xea\xd5\fp\xff\xff\xff\xff\xeb\xc5\v\x80\xff\xff\xff\xff\xec\xb6?\xf0\xff\xff\xff\xff\xed\xf7\xfc" + + "\x00\xff\xff\xff\xff\xee\x98\xc4\xf0\xff\xff\xff\xff\xef\xd9/\x80\xff\xff\xff\xff\xf0y\xf8p\x00\x00\x00\x00\a\xfcV\x00\x00\x00\x00\x00\b\xed\x8ap\x00\x00\x00\x00\t݉\x80\x00\x00\x00\x00\nν\xf0\x00\x00\x00" + + "\x00\x11ۡ\x80\x00\x00\x00\x00\x12T\xddp\x01\x02\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x03\x01\x00\x00q\xe8\x00\x00" + + "\x00\x00p\x80\x00\x04\x00\x00~\x90\x00\b\x00\x00~\x90\x01\fLMT\x00CST\x00JST\x00CDT\x00\nCST-8\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xc7X,Y\x9f" + + "\x01\x00\x00\x9f\x01\x00\x00\x03\x00\x1c\x00ROKUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00\x06\x00\x00\x00\x10\xff\xff\xff\xff\x8b\xd7\xf0x\xff\xff\xff\xff\x92\xe6\x16\xf8\xff\xff\xff\xff\xd2C'\xf0\xff\xff\xff\xff\xd7e\x8fp\xff\xff\xff\xff\xd7\xee\x9d`\xff\xff\xff" + + "\xff\xd8\xf8\xfap\xff\xff\xff\xff\xd9\xcd-\xe0\xff\xff\xff\xff\xda\u05ca\xf0\xff\xff\xff\xffۭ\x0f\xe0\xff\xff\xff\xff\xdc\xe6\xe2\xf0\xff\xff\xff\xff\u074c\xf1\xe0\xff\xff\xff\xff\xe2O)\xf0\xff\xff\xff\xff\xe4k\xb7" + + "\xf8\xff\xff\xff\xff\xe5\x13\x18h\xff\xff\xff\xff\xe6b\x03x\xff\xff\xff\xff\xe7\x11L\xe8\xff\xff\xff\xff\xe8/px\xff\xff\xff\xff\xe8\xe7\xf4h\xff\xff\xff\xff\xea\x0fRx\xff\xff\xff\xff\xea\xc7\xd6h\xff\xff\xff" + + "\xff\xeb\xef4x\xff\xff\xff\xff째h\xff\xff\xff\xff\xed\xcf\x16x\xff\xff\xff\xff\ue1dah\xff\xff\xff\xff\xf05qx\x00\x00\x00\x00 \xa3`\x90\x00\x00\x00\x00!ng\x90\x00\x00\x00\x00\"\x83B" + + "\x90\x00\x00\x00\x00#NI\x90\x01\x02\x04\x03\x04\x03\x04\x03\x04\x03\x04\x01\x05\x01\x05\x01\x05\x01\x05\x01\x05\x01\x05\x01\x04\x03\x04\x03\x04\x00\x00w\b\x00\x00\x00\x00w\x88\x00\x04\x00\x00~\x90\x00\b\x00\x00\x8c\xa0" + + "\x01\f\x00\x00~\x90\x00\x04\x00\x00\x85\x98\x01\fLMT\x00KST\x00JST\x00KDT\x00\nKST-9\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x06\xaa>\xa8\x00\x01\x00\x00\x00" + + "\x01\x00\x00\t\x00\x1c\x00SingaporeUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\x00\x00\x00\b\x00\x00\x00 \xff\xff\xff\xff~6S\xa3\xff\xff\xff\xff\x86\x83\x85\xa3\xff\xff\xff\xff\xbagN\x90\xff\xff\xff\xff\xc0\n\xe4`\xff\xff\xff\xffʳ\xe5`\xff" + + "\xff\xff\xffˑ_\b\xff\xff\xff\xff\xd2Hm\xf0\x00\x00\x00\x00\x16\x91\xf5\b\x01\x02\x03\x04\x05\x06\x05\a\x00\x00a]\x00\x00\x00\x00a]\x00\x04\x00\x00bp\x00\b\x00\x00g \x01\f\x00\x00g \x00" + + "\f\x00\x00ix\x00\x12\x00\x00~\x90\x00\x18\x00\x00p\x80\x00\x1cLMT\x00SMT\x00+07\x00+0720\x00+0730\x00+09\x00+08\x00\n<+08>-8\n" + + "PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\aW\x10Ѱ\x04\x00\x00\xb0\x04\x00\x00\x06\x00\x1c\x00TurkeyUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04" + + "S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00s\x00\x00\x00\x06\x00\x00\x00\x19\xff\xff\xff\xffV\xb6\xc8\xd8\xff\xff\xff\xff\x90\x8b\xf5\x98\xff\xff\xff\xff\x9b" + + "\f\x17`\xff\xff\xff\xff\x9bվ\xd0\xff\xff\xff\xff\xa2ec\xe0\xff\xff\xff\xff\xa3{\x82P\xff\xff\xff\xff\xa4N\x80`\xff\xff\xff\xff\xa5?\xb4\xd0\xff\xff\xff\xff\xa6%'\xe0\xff\xff\xff\xff\xa7'\u007f\xd0\xff" + + "\xff\xff\xff\xaa((`\xff\xff\xff\xff\xaa\xe1\xfd\xd0\xff\xff\xff\xff\xab\xf9\x89\xe0\xff\xff\xff\xff\xac\xc31P\xff\xff\xff\xffȁ?\xe0\xff\xff\xff\xff\xc9\x01\x13P\xff\xff\xff\xff\xc9J\xf5`\xff\xff\xff\xff\xca" + + "\u0380P\xff\xff\xff\xff\xcbˮ`\xff\xff\xff\xff\xd2k\tP\xff\xff\xff\xffӢ9`\xff\xff\xff\xff\xd4C\x02P\xff\xff\xff\xff\xd5L\r\xe0\xff\xff\xff\xff\xd6){\xd0\xff\xff\xff\xff\xd7+\xef\xe0\xff" + + "\xff\xff\xff\xd8\t]\xd0\xff\xff\xff\xff\xd9\x02\x97`\xff\xff\xff\xff\xd9\xe9?\xd0\xff\xff\xff\xff\xda\xeb\xb3\xe0\xff\xff\xff\xff\xdb\xd2\\P\xff\xff\xff\xff\xdc\xd4\xd0`\xff\xff\xff\xffݲ>P\xff\xff\xff\xff\xf1" + + "\xf4\xb9`\xff\xff\xff\xff\xf4b\xefP\xff\xff\xff\xff\xf5h\x06`\xff\xff\xff\xff\xf6\x1f8\xd0\x00\x00\x00\x00\x06n\x93p\x00\x00\x00\x00\a9\x9ap\x00\x00\x00\x00\a\xfbu\x00\x00\x00\x00\x00\t\x19|p\x00" + + "\x00\x00\x00\t\xd0\xcb\x00\x00\x00\x00\x00\n\xf9^p\x00\x00\x00\x00\v\xb1\xfe\x80\x00\x00\x00\x00\f\xd9@p\x00\x00\x00\x00\r\xa4U\x80\x00\x00\x00\x00\x0e\xa6\xadp\x00\x00\x00\x00\x0f\x847\x80\x00\x00\x00\x00\x0f" + + "\xf8\x11P\x00\x00\x00\x00\x19\x89\xb0p\x00\x00\x00\x00\x19ܰ\xe0\x00\x00\x00\x00\x1b\xe6\xd0\xf0\x00\x00\x00\x00\x1c\xc6\xef\xf0\x00\x00\x00\x00\x1d\x9b1p\x00\x00\x00\x00\x1e\x8cs\xf0\x00\x00\x00\x00\x1f|d\xf0\x00" + + "\x00\x00\x00 lU\xf0\x00\x00\x00\x00!\\F\xf0\x00\x00\x00\x00\"L7\xf0\x00\x00\x00\x00#<(\xf0\x00\x00\x00\x00$,\x19\xf0\x00\x00\x00\x00%\x1c\n\xf0\x00\x00\x00\x00&\v\xfb\xf0\x00\x00\x00\x00'" + + "\x05'p\x00\x00\x00\x00'\xf5\x18p\x00\x00\x00\x00(\xe5\tp\x00\x00\x00\x00)\xd4\xfap\x00\x00\x00\x00*\xc4\xebp\x00\x00\x00\x00+\xb4\xdcp\x00\x00\x00\x00,\xa4\xcdp\x00\x00\x00\x00-\x8b\x83\xf0\x00" + + "\x00\x00\x00.\x84\xafp\x00\x00\x00\x00/t\xa0p\x00\x00\x00\x000d\x91p\x00\x00\x00\x001]\xbc\xf0\x00\x00\x00\x002r\x97\xf0\x00\x00\x00\x003=\x9e\xf0\x00\x00\x00\x004Ry\xf0\x00\x00\x00\x005" + + "\x1d\x80\xf0\x00\x00\x00\x0062[\xf0\x00\x00\x00\x006\xfdb\xf0\x00\x00\x00\x008\x1bxp\x00\x00\x00\x008\xddD\xf0\x00\x00\x00\x009\xfbZp\x00\x00\x00\x00:\xbd&\xf0\x00\x00\x00\x00;\xdb\x86%p\x00\x00\x00\x00?\x9b\x00p\x00\x00\x00\x00@f\ap\x00\x00\x00\x00A\x84\x1c\xf0\x00\x00\x00\x00BE\xe9p\x00\x00\x00\x00C" + + "c\xfe\xf0\x00\x00\x00\x00D%\xcbp\x00\x00\x00\x00EC\xe0\xf0\x00\x00\x00\x00F\x05ɐ\x00\x00\x00\x00G#\xdf\x10\x00\x00\x00\x00G\xee\xe6\x10\x00\x00\x00\x00I\x03\xc1\x10\x00\x00\x00\x00I\xce\xc8\x10\x00" + + "\x00\x00\x00J\xe3\xa3\x10\x00\x00\x00\x00K\xae\xaa\x10\x00\x00\x00\x00L̿\x90\x00\x00\x00\x00M\x8fݐ\x00\x00\x00\x00N\xac\xa1\x90\x00\x00\x00\x00Onn\x10\x00\x00\x00\x00P\x8c\x83\x90\x00\x00\x00\x00Q" + + "W\x8a\x90\x00\x00\x00\x00Rle\x90\x00\x00\x00\x00S8\xbe\x10\x00\x00\x00\x00TLG\x90\x00\x00\x00\x00U\x17N\x90\x00\x00\x00\x00V>\x9e\x90\x00\x00\x00\x00V\xf70\x90\x00\x00\x00\x00W\xcf.P\x01" + + "\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x04\x05\x04\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x04\x00\x00\x1b(\x00\x00" + + "\x00\x00\x1bh\x00\x04\x00\x00*0\x01\b\x00\x00\x1c \x00\r\x00\x00*0\x00\x11\x00\x008@\x01\x15LMT\x00IMT\x00EEST\x00EET\x00+03\x00+04\x00\n<+03" + + ">-3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x9f.\xe4xo\x00\x00\x00o\x00\x00\x00\x03\x00\x1c\x00UCTUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00" + + "\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif" + + "2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00UTC\x00\nUTC0\nPK\x03\x04" + + "\n\x00\x00\x00\x00\x00#\x82iS\x9f.\xe4xo\x00\x00\x00o\x00\x00\x00\t\x00\x1c\x00UniversalUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S" + + "_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00UTC\x00\nUTC0\nPK\x03\x04\n\x00" + + "\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x1c\x00US/UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x03\x04\n" + + "\x00\x00\x00\x00\x00#\x82iSV\x80\x94@\x12\x04\x00\x00\x12\x04\x00\x00\v\x00\x1c\x00US/MountainUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04" + + "S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00a\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff^\x04\f\xb0\xff\xff\xff\xff\x9e\xa6:\x90\xff\xff\xff\xff\x9f" + + "\xbb\a\x80\xff\xff\xff\xff\xa0\x86\x1c\x90\xff\xff\xff\xff\xa1\x9a\xe9\x80\xff\xff\xff\xff\xa2e\xfe\x90\xff\xff\xff\xff\xa3\x84\x06\x00\xff\xff\xff\xff\xa4E\xe0\x90\xff\xff\xff\xff\xa4\x8f\xa6\x80\xff\xff\xff\xffˉ\f\x90\xff" + + "\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff\xf7/v\x90\xff\xff\xff\xff\xf8(\x94\x00\xff\xff\xff\xff\xf9\x0fX\x90\xff\xff\xff\xff\xfa\bv\x00\xff\xff\xff\xff\xfa\xf8u\x10\xff\xff\xff\xff\xfb" + + "\xe8X\x00\xff\xff\xff\xff\xfc\xd8W\x10\xff\xff\xff\xff\xfd\xc8:\x00\xff\xff\xff\xff\xfe\xb89\x10\xff\xff\xff\xff\xff\xa8\x1c\x00\x00\x00\x00\x00\x00\x98\x1b\x10\x00\x00\x00\x00\x01\x87\xfe\x00\x00\x00\x00\x00\x02w\xfd\x10\x00" + + "\x00\x00\x00\x03q\x1a\x80\x00\x00\x00\x00\x04a\x19\x90\x00\x00\x00\x00\x05P\xfc\x80\x00\x00\x00\x00\x06@\xfb\x90\x00\x00\x00\x00\a0ހ\x00\x00\x00\x00\a\x8d5\x90\x00\x00\x00\x00\t\x10\xc0\x80\x00\x00\x00\x00\t" + + "\xad\xb1\x10\x00\x00\x00\x00\n\xf0\xa2\x80\x00\x00\x00\x00\vࡐ\x00\x00\x00\x00\fٿ\x00\x00\x00\x00\x00\r\xc0\x83\x90\x00\x00\x00\x00\x0e\xb9\xa1\x00\x00\x00\x00\x00\x0f\xa9\xa0\x10\x00\x00\x00\x00\x10\x99\x83\x00\x00" + + "\x00\x00\x00\x11\x89\x82\x10\x00\x00\x00\x00\x12ye\x00\x00\x00\x00\x00\x13id\x10\x00\x00\x00\x00\x14YG\x00\x00\x00\x00\x00\x15IF\x10\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17)(\x10\x00\x00\x00\x00\x18" + + "\"E\x80\x00\x00\x00\x00\x19\t\n\x10\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2&\x90\x00\x00\x00\x00\x1b\xe2\t\x80\x00\x00\x00\x00\x1c\xd2\b\x90\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1\xea\x90\x00" + + "\x00\x00\x00\x1f\xa1̀\x00\x00\x00\x00 v\x1d\x10\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xff\x10\x00\x00\x00\x00#j\xcc\x00\x00\x00\x00\x00$5\xe1\x10\x00\x00\x00\x00%J\xae\x00\x00\x00\x00\x00&" + + "\x15\xc3\x10\x00\x00\x00\x00'*\x90\x00\x00\x00\x00\x00'\xfeߐ\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\xde\xc1\x90\x00\x00\x00\x00*\xeaT\x00\x00\x00\x00\x00+\xbe\xa3\x90\x00\x00\x00\x00,\xd3p\x80\x00" + + "\x00\x00\x00-\x9e\x85\x90\x00\x00\x00\x00.\xb3R\x80\x00\x00\x00\x00/~g\x90\x00\x00\x00\x000\x934\x80\x00\x00\x00\x001g\x84\x10\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003Gf\x10\x00\x00\x00\x004" + + "R\xf8\x80\x00\x00\x00\x005'H\x10\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe7\f\x10\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xc6\xee\x10\x00" + + "\x00\x00\x00;ۻ\x00\x00\x00\x00\x00<\xb0\n\x90\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8f\xec\x90\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@oΐ\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00\x00B" + + "O\xb0\x90\x00\x00\x00\x00Cd}\x80\x00\x00\x00\x00D/\x92\x90\x00\x00\x00\x00ED_\x80\x00\x00\x00\x00E\xf3\xc5\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\x91&\x00\x00\xff\xff\x9d\x90\x01\x04\xff\xff\x8f\x80" + - "\x00\b\xff\xff\x9d\x90\x01\f\xff\xff\x9d\x90\x01\x10LMT\x00PDT\x00PST\x00PWT\x00PPT\x00\nPST8PDT,M3.2.0,M11.1.0\nPK" + - "\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x9bܩ=\xda\x06\x00\x00\xda\x06\x00\x00\n\x00\x1c\x00US/CentralUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00" + - "\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZi" + - "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaf\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff" + - "\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xff\xa2\xcbt\x00\xff\xff\xff\xff\xa3\x83\xf7\xf0\xff\xff\xff\xff\xa4EҀ\xff\xff\xff\xff\xa5c\xd9\xf0\xff\xff\xff\xff\xa6S\xd9" + - "\x00\xff\xff\xff\xff\xa7\x15\x97p\xff\xff\xff\xff\xa83\xbb\x00\xff\xff\xff\xff\xa8\xfe\xb3\xf0\xff\xff\xff\xff\xaa\x13\x9d\x00\xff\xff\xff\xff\xaaޕ\xf0\xff\xff\xff\xff\xab\xf3\u007f\x00\xff\xff\xff\xff\xac\xbew\xf0\xff\xff\xff" + - "\xff\xad\xd3a\x00\xff\xff\xff\xff\xae\x9eY\xf0\xff\xff\xff\xff\xaf\xb3C\x00\xff\xff\xff\xff\xb0~;\xf0\xff\xff\xff\xff\xb1\x9c_\x80\xff\xff\xff\xff\xb2gXp\xff\xff\xff\xff\xb3|A\x80\xff\xff\xff\xff\xb4G:" + - "p\xff\xff\xff\xff\xb5\\#\x80\xff\xff\xff\xff\xb6'\x1cp\xff\xff\xff\xff\xb7<\x05\x80\xff\xff\xff\xff\xb8\x06\xfep\xff\xff\xff\xff\xb9\x1b\xe7\x80\xff\xff\xff\xff\xb9\xe6\xe0p\xff\xff\xff\xff\xbb\x05\x04\x00\xff\xff\xff" + - "\xff\xbb\xc6\xc2p\xff\xff\xff\xff\xbc\xe4\xe6\x00\xff\xff\xff\xff\xbd\xaf\xde\xf0\xff\xff\xff\xff\xbe\xc4\xc8\x00\xff\xff\xff\xff\xbf\x8f\xc0\xf0\xff\xff\xff\xff\xc0Z\xd6\x00\xff\xff\xff\xff\xc1\xb0\x8fހ\x00\x00\x00" + - "\x00?\x9bp\xf0\x00\x00\x00\x00@o\xc0\x80\x00\x00\x00\x00A\x84\x8dp\x00\x00\x00\x00BO\xa2\x80\x00\x00\x00\x00Cdop\x00\x00\x00\x00D/\x84\x80\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7" + - "\x00\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x04\x05\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\x9d\x94\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\f\xff\xff\xab\xa0\x01\x10LMT\x00MDT\x00MST\x00MWT\x00MP" + + "T\x00\nMST7MDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS5\x11Q\x06\xd1\x03\x00\x00\xd1\x03\x00\x00\t\x00\x1c\x00US/A" + + "laskaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00T" + + "\x00\x00\x00\n\x00\x00\x00(\xff\xff\xff\xff?\xc2\xfd\xd1\xff\xff\xff\xff}\x87AH\xff\xff\xff\xffˉ6\xc0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2aB0\xff\xff\xff\xff\xfa\xd2G\xa0\xff\xff\xff\xff" + + "\xfe\xb8c@\xff\xff\xff\xff\xff\xa8F0\x00\x00\x00\x00\x00\x98E@\x00\x00\x00\x00\x01\x88(0\x00\x00\x00\x00\x02x'@\x00\x00\x00\x00\x03qD\xb0\x00\x00\x00\x00\x04aC\xc0\x00\x00\x00\x00\x05Q&\xb0" + + "\x00\x00\x00\x00\x06A%\xc0\x00\x00\x00\x00\a1\b\xb0\x00\x00\x00\x00\a\x8d_\xc0\x00\x00\x00\x00\t\x10\xea\xb0\x00\x00\x00\x00\t\xad\xdb@\x00\x00\x00\x00\n\xf0̰\x00\x00\x00\x00\v\xe0\xcb\xc0\x00\x00\x00\x00" + + "\f\xd9\xe90\x00\x00\x00\x00\r\xc0\xad\xc0\x00\x00\x00\x00\x0e\xb9\xcb0\x00\x00\x00\x00\x0f\xa9\xca@\x00\x00\x00\x00\x10\x99\xad0\x00\x00\x00\x00\x11\x89\xac@\x00\x00\x00\x00\x12y\x8f0\x00\x00\x00\x00\x13i\x8e@" + + "\x00\x00\x00\x00\x14Yq0\x00\x00\x00\x00\x15Ip@\x00\x00\x00\x00\x169S0\x00\x00\x00\x00\x17)R@\x00\x00\x00\x00\x18\"o\xb0\x00\x00\x00\x00\x19\t4@\x00\x00\x00\x00\x1a\x02Q\xb0\x00\x00\x00\x00" + + "\x1a+\x14\x10\x00\x00\x00\x00\x1a\xf2B\xb0\x00\x00\x00\x00\x1b\xe2%\xa0\x00\x00\x00\x00\x1c\xd2$\xb0\x00\x00\x00\x00\x1d\xc2\a\xa0\x00\x00\x00\x00\x1e\xb2\x06\xb0\x00\x00\x00\x00\x1f\xa1\xe9\xa0\x00\x00\x00\x00 v90" + + "\x00\x00\x00\x00!\x81ˠ\x00\x00\x00\x00\"V\x1b0\x00\x00\x00\x00#j\xe8 \x00\x00\x00\x00$5\xfd0\x00\x00\x00\x00%J\xca \x00\x00\x00\x00&\x15\xdf0\x00\x00\x00\x00'*\xac \x00\x00\x00\x00" + + "'\xfe\xfb\xb0\x00\x00\x00\x00)\n\x8e \x00\x00\x00\x00)\xdeݰ\x00\x00\x00\x00*\xeap \x00\x00\x00\x00+\xbe\xbf\xb0\x00\x00\x00\x00,ӌ\xa0\x00\x00\x00\x00-\x9e\xa1\xb0\x00\x00\x00\x00.\xb3n\xa0" + + "\x00\x00\x00\x00/~\x83\xb0\x00\x00\x00\x000\x93P\xa0\x00\x00\x00\x001g\xa00\x00\x00\x00\x002s2\xa0\x00\x00\x00\x003G\x820\x00\x00\x00\x004S\x14\xa0\x00\x00\x00\x005'd0\x00\x00\x00\x00" + + "62\xf6\xa0\x00\x00\x00\x007\aF0\x00\x00\x00\x008\x1c\x13 \x00\x00\x00\x008\xe7(0\x00\x00\x00\x009\xfb\xf5 \x00\x00\x00\x00:\xc7\n0\x00\x00\x00\x00;\xdb\xd7 \x00\x00\x00\x00<\xb0&\xb0" + + "\x00\x00\x00\x00=\xbb\xb9 \x00\x00\x00\x00>\x90\b\xb0\x00\x00\x00\x00?\x9b\x9b \x00\x00\x00\x00@o\xea\xb0\x00\x00\x00\x00A\x84\xb7\xa0\x00\x00\x00\x00BO̰\x00\x00\x00\x00Cd\x99\xa0\x00\x00\x00\x00" + + "D/\xae\xb0\x00\x00\x00\x00ED{\xa0\x00\x00\x00\x00E\xf3\xe10\x01\x02\x03\x04\x02\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\a\t\b\t\b" + + "\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\x00\x00\xc4\xf8\x00\x00\xff\xffsx\x00\x00\xff\xffs`" + + "\x00\x04\xff\xff\x81p\x01\b\xff\xff\x81p\x01\f\xff\xffs`\x00\x10\xff\xff\x81p\x01\x15\xff\xff\x81p\x00\x1a\xff\xff\x8f\x80\x01\x1e\xff\xff\x81p\x00#LMT\x00AST\x00AWT\x00APT\x00" + + "AHST\x00AHDT\x00YST\x00AKDT\x00AKST\x00\nAKST9AKDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00" + + "#\x82iSp\xb6{\xc9\x13\x02\x00\x00\x13\x02\x00\x00\x0f\x00\x1c\x00US/East-IndianaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S" + + "_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00&\x00\x00\x00\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba" + + "\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xff\xcaW\"\x80\xff\xff\xff\xff\xca\xd8Gp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff" + + "\xff\xff\xd3u\xf3\x00\xff\xff\xff\xff\xd4@\xeb\xf0\xff\xff\xff\xff\xd5U\xd5\x00\xff\xff\xff\xff\xd6 \xcd\xf0\xff\xff\xff\xff\xd75\xb7\x00\xff\xff\xff\xff\xd8\x00\xaf\xf0\xff\xff\xff\xff\xd9\x15\x99\x00\xff\xff\xff\xff\xd9\xe0" + + "\x91\xf0\xff\xff\xff\xff\xda\xfe\xb5\x80\xff\xff\xff\xff\xdb\xc0s\xf0\xff\xff\xff\xff\xdcޗ\x80\xff\xff\xff\xffݩ\x90p\xff\xff\xff\xff\u07bey\x80\xff\xff\xff\xff߉rp\xff\xff\xff\xff\xe0\x9e[\x80\xff\xff" + + "\xff\xff\xe1iTp\xff\xff\xff\xff\xe2~=\x80\xff\xff\xff\xff\xe3I6p\xff\xff\xff\xff\xe4^\x1f\x80\xff\xff\xff\xff\xe8\xf2\x16\xf0\xff\xff\xff\xff\xea\a\x00\x00\xff\xff\xff\xff\xfe\xb8\x1c\xf0\xff\xff\xff\xff\xff\xa7" + + "\xff\xe0\x00\x00\x00\x00\x00\x97\xfe\xf0\x00\x00\x00\x00\x01\x87\xe1\xe0\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05\x02\x05\x06\x05\x06\x05\x06\x05\x06\xff\xff\xaf:\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14\xff\xff\xc7\xc0" + + "\x01\x18LMT\x00CDT\x00CST\x00CWT\x00CPT\x00EST\x00EDT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00" + + "\x00\x00\x00\x00#\x82iS\xae,\xa44\xc9\x03\x00\x00\xc9\x03\x00\x00\v\x00\x1c\x00US/AleutianUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S" + + "_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00T\x00\x00\x00\n\x00\x00\x00!\xff\xff\xff\xff?\xc2\xfd\xd1\xff\xff\xff\xff}\x87Z^\xff\xff\xff\xffˉ" + + "D\xd0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2aP@\xff\xff\xff\xff\xfa\xd2U\xb0\xff\xff\xff\xff\xfe\xb8qP\xff\xff\xff\xff\xff\xa8T@\x00\x00\x00\x00\x00\x98SP\x00\x00\x00\x00\x01\x886@\x00\x00" + + "\x00\x00\x02x5P\x00\x00\x00\x00\x03qR\xc0\x00\x00\x00\x00\x04aQ\xd0\x00\x00\x00\x00\x05Q4\xc0\x00\x00\x00\x00\x06A3\xd0\x00\x00\x00\x00\a1\x16\xc0\x00\x00\x00\x00\a\x8dm\xd0\x00\x00\x00\x00\t\x10" + + "\xf8\xc0\x00\x00\x00\x00\t\xad\xe9P\x00\x00\x00\x00\n\xf0\xda\xc0\x00\x00\x00\x00\v\xe0\xd9\xd0\x00\x00\x00\x00\f\xd9\xf7@\x00\x00\x00\x00\r\xc0\xbb\xd0\x00\x00\x00\x00\x0e\xb9\xd9@\x00\x00\x00\x00\x0f\xa9\xd8P\x00\x00" + + "\x00\x00\x10\x99\xbb@\x00\x00\x00\x00\x11\x89\xbaP\x00\x00\x00\x00\x12y\x9d@\x00\x00\x00\x00\x13i\x9cP\x00\x00\x00\x00\x14Y\u007f@\x00\x00\x00\x00\x15I~P\x00\x00\x00\x00\x169a@\x00\x00\x00\x00\x17)" + + "`P\x00\x00\x00\x00\x18\"}\xc0\x00\x00\x00\x00\x19\tBP\x00\x00\x00\x00\x1a\x02_\xc0\x00\x00\x00\x00\x1a+\" \x00\x00\x00\x00\x1a\xf2P\xc0\x00\x00\x00\x00\x1b\xe23\xb0\x00\x00\x00\x00\x1c\xd22\xc0\x00\x00" + + "\x00\x00\x1d\xc2\x15\xb0\x00\x00\x00\x00\x1e\xb2\x14\xc0\x00\x00\x00\x00\x1f\xa1\xf7\xb0\x00\x00\x00\x00 vG@\x00\x00\x00\x00!\x81ٰ\x00\x00\x00\x00\"V)@\x00\x00\x00\x00#j\xf60\x00\x00\x00\x00$6" + + "\v@\x00\x00\x00\x00%J\xd80\x00\x00\x00\x00&\x15\xed@\x00\x00\x00\x00'*\xba0\x00\x00\x00\x00'\xff\t\xc0\x00\x00\x00\x00)\n\x9c0\x00\x00\x00\x00)\xde\xeb\xc0\x00\x00\x00\x00*\xea~0\x00\x00" + + "\x00\x00+\xbe\xcd\xc0\x00\x00\x00\x00,Ӛ\xb0\x00\x00\x00\x00-\x9e\xaf\xc0\x00\x00\x00\x00.\xb3|\xb0\x00\x00\x00\x00/~\x91\xc0\x00\x00\x00\x000\x93^\xb0\x00\x00\x00\x001g\xae@\x00\x00\x00\x002s" + + "@\xb0\x00\x00\x00\x003G\x90@\x00\x00\x00\x004S\"\xb0\x00\x00\x00\x005'r@\x00\x00\x00\x0063\x04\xb0\x00\x00\x00\x007\aT@\x00\x00\x00\x008\x1c!0\x00\x00\x00\x008\xe76@\x00\x00" + + "\x00\x009\xfc\x030\x00\x00\x00\x00:\xc7\x18@\x00\x00\x00\x00;\xdb\xe50\x00\x00\x00\x00<\xb04\xc0\x00\x00\x00\x00=\xbb\xc70\x00\x00\x00\x00>\x90\x16\xc0\x00\x00\x00\x00?\x9b\xa90\x00\x00\x00\x00@o" + + "\xf8\xc0\x00\x00\x00\x00A\x84Ű\x00\x00\x00\x00BO\xda\xc0\x00\x00\x00\x00Cd\xa7\xb0\x00\x00\x00\x00D/\xbc\xc0\x00\x00\x00\x00ED\x89\xb0\x00\x00\x00\x00E\xf3\xef@\x01\x02\x03\x04\x02\x05\x06\x05\x06\x05" + + "\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\a\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b" + + "\t\b\t\b\t\b\t\b\t\b\t\b\t\b\x00\x00\xab\xe2\x00\x00\xff\xffZb\x00\x00\xff\xffeP\x00\x04\xff\xffs`\x01\b\xff\xffs`\x01\f\xff\xffeP\x00\x10\xff\xffs`\x01\x14\xff\xffs`" + + "\x00\x18\xff\xff\x81p\x01\x1d\xff\xffs`\x00\x19LMT\x00NST\x00NWT\x00NPT\x00BST\x00BDT\x00AHST\x00HDT\x00\nHST10HDT,M3." + + "2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xeaK\x85v\xdd\x00\x00\x00\xdd\x00\x00\x00\t\x00\x1c\x00US/HawaiiUT\t\x00\x03\x82\x0f\x8ba" + + "\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00" + + "\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xfft\xe0" + + "p\xbe\xff\xff\xff\xff\xbb\x05CH\xff\xff\xff\xff\xbb!qX\xff\xff\xff\xffˉ=\xc8\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2aI8\xff\xff\xff\xffՍsH\x01\x02\x01\x03\x04\x01\x05\xff\xffl" + + "\x02\x00\x00\xff\xfflX\x00\x04\xff\xffzh\x01\b\xff\xffzh\x01\f\xff\xffzh\x01\x10\xff\xffs`\x00\x04LMT\x00HST\x00HDT\x00HWT\x00HPT\x00\nHST10\n" + + "PK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS3\x9aG\xc8\xd0\x06\x00\x00\xd0\x06\x00\x00\n\x00\x1c\x00US/EasternUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14" + + "E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00T" + + "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaf\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff^\x03\xf0\x90\xff\xff\xff\xff\x9e\xa6\x1ep\xff" + + "\xff\xff\xff\x9f\xba\xeb`\xff\xff\xff\xff\xa0\x86\x00p\xff\xff\xff\xff\xa1\x9a\xcd`\xff\xff\xff\xff\xa2e\xe2p\xff\xff\xff\xff\xa3\x83\xe9\xe0\xff\xff\xff\xff\xa4j\xaep\xff\xff\xff\xff\xa55\xa7`\xff\xff\xff\xff\xa6" + + "S\xca\xf0\xff\xff\xff\xff\xa7\x15\x89`\xff\xff\xff\xff\xa83\xac\xf0\xff\xff\xff\xff\xa8\xfe\xa5\xe0\xff\xff\xff\xff\xaa\x13\x8e\xf0\xff\xff\xff\xff\xaaއ\xe0\xff\xff\xff\xff\xab\xf3p\xf0\xff\xff\xff\xff\xac\xbei\xe0\xff" + + "\xff\xff\xff\xad\xd3R\xf0\xff\xff\xff\xff\xae\x9eK\xe0\xff\xff\xff\xff\xaf\xb34\xf0\xff\xff\xff\xff\xb0~-\xe0\xff\xff\xff\xff\xb1\x9cQp\xff\xff\xff\xff\xb2gJ`\xff\xff\xff\xff\xb3|3p\xff\xff\xff\xff\xb4" + + "G,`\xff\xff\xff\xff\xb5\\\x15p\xff\xff\xff\xff\xb6'\x0e`\xff\xff\xff\xff\xb7;\xf7p\xff\xff\xff\xff\xb8\x06\xf0`\xff\xff\xff\xff\xb9\x1b\xd9p\xff\xff\xff\xff\xb9\xe6\xd2`\xff\xff\xff\xff\xbb\x04\xf5\xf0\xff" + + "\xff\xff\xff\xbbƴ`\xff\xff\xff\xff\xbc\xe4\xd7\xf0\xff\xff\xff\xff\xbd\xaf\xd0\xe0\xff\xff\xff\xff\xbeĹ\xf0\xff\xff\xff\xff\xbf\x8f\xb2\xe0\xff\xff\xff\xff\xc0\xa4\x9b\xf0\xff\xff\xff\xff\xc1o\x94\xe0\xff\xff\xff\xff\xc2" + + "\x84}\xf0\xff\xff\xff\xff\xc3Ov\xe0\xff\xff\xff\xff\xc4d_\xf0\xff\xff\xff\xff\xc5/X\xe0\xff\xff\xff\xff\xc6M|p\xff\xff\xff\xff\xc7\x0f:\xe0\xff\xff\xff\xff\xc8-^p\xff\xff\xff\xff\xc8\xf8W`\xff" + + "\xff\xff\xff\xca\r@p\xff\xff\xff\xff\xca\xd89`\xff\xff\xff\xffˈ\xf0p\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xfb\xe0\xff\xff\xff\xff\xd3u\xe4\xf0\xff\xff\xff\xff\xd4@\xdd\xe0\xff\xff\xff\xff\xd5" + + "U\xc6\xf0\xff\xff\xff\xff\xd6 \xbf\xe0\xff\xff\xff\xff\xd75\xa8\xf0\xff\xff\xff\xff\xd8\x00\xa1\xe0\xff\xff\xff\xff\xd9\x15\x8a\xf0\xff\xff\xff\xff\xd9\xe0\x83\xe0\xff\xff\xff\xff\xda\xfe\xa7p\xff\xff\xff\xff\xdb\xc0e\xe0\xff" + + "\xff\xff\xff\xdcމp\xff\xff\xff\xffݩ\x82`\xff\xff\xff\xff\u07bekp\xff\xff\xff\xff߉d`\xff\xff\xff\xff\xe0\x9eMp\xff\xff\xff\xff\xe1iF`\xff\xff\xff\xff\xe2~/p\xff\xff\xff\xff\xe3" + + "I(`\xff\xff\xff\xff\xe4^\x11p\xff\xff\xff\xff\xe5W.\xe0\xff\xff\xff\xff\xe6G-\xf0\xff\xff\xff\xff\xe77\x10\xe0\xff\xff\xff\xff\xe8'\x0f\xf0\xff\xff\xff\xff\xe9\x16\xf2\xe0\xff\xff\xff\xff\xea\x06\xf1\xf0\xff" + + "\xff\xff\xff\xea\xf6\xd4\xe0\xff\xff\xff\xff\xeb\xe6\xd3\xf0\xff\xff\xff\xff\xecֶ\xe0\xff\xff\xff\xff\xedƵ\xf0\xff\xff\xff\xff\xee\xbf\xd3`\xff\xff\xff\xff\xef\xaf\xd2p\xff\xff\xff\xff\xf0\x9f\xb5`\xff\xff\xff\xff\xf1" + + "\x8f\xb4p\xff\xff\xff\xff\xf2\u007f\x97`\xff\xff\xff\xff\xf3o\x96p\xff\xff\xff\xff\xf4_y`\xff\xff\xff\xff\xf5Oxp\xff\xff\xff\xff\xf6?[`\xff\xff\xff\xff\xf7/Zp\xff\xff\xff\xff\xf8(w\xe0\xff" + + "\xff\xff\xff\xf9\x0f\x8f\xd0p\x00" + + "\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E" + + "\xf3\xa8\xf0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01" + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xad\xd4" + - "\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x00\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x01\x14LMT\x00CDT\x00CST\x00EST\x00CWT\x00CPT\x00\nCST" + - "6CDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R>\x14\xe7\x03\x83\x03\x00\x00\x83\x03\x00\x00\v\x00\x1c\x00US/Michiga" + - "nUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00P\x00\x00\x00\x06" + - "\x00\x00\x00\x18\xff\xff\xff\xff\x85\xbd\"[\xff\xff\xff\xff\x99<\x94\x00\xff\xff\xff\xffˈ\xf0p\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xfb\xe0\xff\xff\xff\xff\xd75\xa8\xf0\xff\xff\xff\xff\xd8\x00\xa1\xe0" + - "\xff\xff\xff\xff\xfb3\x90\x8c\xff\xff\xff\xff\xfb\xe8;\xe0\xff\xff\xff\xff\xfc\xd8:\xf0\xff\xff\xff\xff\xfd\xc8\x1d\xe0\x00\x00\x00\x00\x06@\xdfp\x00\x00\x00\x00\a0\xc2`\x00\x00\x00\x00\a\x8d\x19p\x00\x00\x00\x00" + - "\t\x10\xa4`\x00\x00\x00\x00\n\x00\xa3p\x00\x00\x00\x00\n\xf0\x86`\x00\x00\x00\x00\v\xe0\x85p\x00\x00\x00\x00\f٢\xe0\x00\x00\x00\x00\r\xc0gp\x00\x00\x00\x00\x0e\xb9\x84\xe0\x00\x00\x00\x00\x0f\xa9\x83\xf0" + - "\x00\x00\x00\x00\x10\x99f\xe0\x00\x00\x00\x00\x11\x89e\xf0\x00\x00\x00\x00\x12yH\xe0\x00\x00\x00\x00\x13iG\xf0\x00\x00\x00\x00\x14Y*\xe0\x00\x00\x00\x00\x15I)\xf0\x00\x00\x00\x00\x169\f\xe0\x00\x00\x00\x00" + - "\x17)\v\xf0\x00\x00\x00\x00\x18\")`\x00\x00\x00\x00\x19\b\xed\xf0\x00\x00\x00\x00\x1a\x02\v`\x00\x00\x00\x00\x1a\xf2\np\x00\x00\x00\x00\x1b\xe1\xed`\x00\x00\x00\x00\x1c\xd1\xecp\x00\x00\x00\x00\x1d\xc1\xcf`" + - "\x00\x00\x00\x00\x1e\xb1\xcep\x00\x00\x00\x00\x1f\xa1\xb1`\x00\x00\x00\x00 v\x00\xf0\x00\x00\x00\x00!\x81\x93`\x00\x00\x00\x00\"U\xe2\xf0\x00\x00\x00\x00#j\xaf\xe0\x00\x00\x00\x00$5\xc4\xf0\x00\x00\x00\x00" + - "%J\x91\xe0\x00\x00\x00\x00&\x15\xa6\xf0\x00\x00\x00\x00'*s\xe0\x00\x00\x00\x00'\xfe\xc3p\x00\x00\x00\x00)\nU\xe0\x00\x00\x00\x00)ޥp\x00\x00\x00\x00*\xea7\xe0\x00\x00\x00\x00+\xbe\x87p" + - "\x00\x00\x00\x00,\xd3T`\x00\x00\x00\x00-\x9eip\x00\x00\x00\x00.\xb36`\x00\x00\x00\x00/~Kp\x00\x00\x00\x000\x93\x18`\x00\x00\x00\x001gg\xf0\x00\x00\x00\x002r\xfa`\x00\x00\x00\x00" + - "3GI\xf0\x00\x00\x00\x004R\xdc`\x00\x00\x00\x005'+\xf0\x00\x00\x00\x0062\xbe`\x00\x00\x00\x007\a\r\xf0\x00\x00\x00\x008\x1b\xda\xe0\x00\x00\x00\x008\xe6\xef\xf0\x00\x00\x00\x009\xfb\xbc\xe0" + - "\x00\x00\x00\x00:\xc6\xd1\xf0\x00\x00\x00\x00;۞\xe0\x00\x00\x00\x00<\xaf\xeep\x00\x00\x00\x00=\xbb\x80\xe0\x00\x00\x00\x00>\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00" + - "A\x84\u007f`\x00\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x01\x02\x03\x04\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05" + - "\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05" + - "\x02\x05\x02\x05\xff\xff\xb2%\x00\x00\xff\xff\xab\xa0\x00\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x01\f\xff\xff\xc7\xc0\x01\x10\xff\xff\xc7\xc0\x01\x14LMT\x00CST\x00EST\x00EWT\x00EPT\x00" + - "EDT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\xae,\xa44\xc9\x03\x00\x00\xc9\x03\x00\x00\v\x00\x1c\x00US" + - "/AleutianUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00T\x00\x00\x00\n\x00\x00\x00!\xff\xff\xff\xff?\xc2\xfd\xd1\xff\xff\xff\xff}\x87Z^\xff\xff\xff\xffˉD\xd0\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2aP@\xff\xff\xff\xff\xfa\xd2U\xb0" + - "\xff\xff\xff\xff\xfe\xb8qP\xff\xff\xff\xff\xff\xa8T@\x00\x00\x00\x00\x00\x98SP\x00\x00\x00\x00\x01\x886@\x00\x00\x00\x00\x02x5P\x00\x00\x00\x00\x03qR\xc0\x00\x00\x00\x00\x04aQ\xd0\x00\x00\x00\x00" + - "\x05Q4\xc0\x00\x00\x00\x00\x06A3\xd0\x00\x00\x00\x00\a1\x16\xc0\x00\x00\x00\x00\a\x8dm\xd0\x00\x00\x00\x00\t\x10\xf8\xc0\x00\x00\x00\x00\t\xad\xe9P\x00\x00\x00\x00\n\xf0\xda\xc0\x00\x00\x00\x00\v\xe0\xd9\xd0" + - "\x00\x00\x00\x00\f\xd9\xf7@\x00\x00\x00\x00\r\xc0\xbb\xd0\x00\x00\x00\x00\x0e\xb9\xd9@\x00\x00\x00\x00\x0f\xa9\xd8P\x00\x00\x00\x00\x10\x99\xbb@\x00\x00\x00\x00\x11\x89\xbaP\x00\x00\x00\x00\x12y\x9d@\x00\x00\x00\x00" + - "\x13i\x9cP\x00\x00\x00\x00\x14Y\u007f@\x00\x00\x00\x00\x15I~P\x00\x00\x00\x00\x169a@\x00\x00\x00\x00\x17)`P\x00\x00\x00\x00\x18\"}\xc0\x00\x00\x00\x00\x19\tBP\x00\x00\x00\x00\x1a\x02_\xc0" + - "\x00\x00\x00\x00\x1a+\" \x00\x00\x00\x00\x1a\xf2P\xc0\x00\x00\x00\x00\x1b\xe23\xb0\x00\x00\x00\x00\x1c\xd22\xc0\x00\x00\x00\x00\x1d\xc2\x15\xb0\x00\x00\x00\x00\x1e\xb2\x14\xc0\x00\x00\x00\x00\x1f\xa1\xf7\xb0\x00\x00\x00\x00" + - " vG@\x00\x00\x00\x00!\x81ٰ\x00\x00\x00\x00\"V)@\x00\x00\x00\x00#j\xf60\x00\x00\x00\x00$6\v@\x00\x00\x00\x00%J\xd80\x00\x00\x00\x00&\x15\xed@\x00\x00\x00\x00'*\xba0" + - "\x00\x00\x00\x00'\xff\t\xc0\x00\x00\x00\x00)\n\x9c0\x00\x00\x00\x00)\xde\xeb\xc0\x00\x00\x00\x00*\xea~0\x00\x00\x00\x00+\xbe\xcd\xc0\x00\x00\x00\x00,Ӛ\xb0\x00\x00\x00\x00-\x9e\xaf\xc0\x00\x00\x00\x00" + - ".\xb3|\xb0\x00\x00\x00\x00/~\x91\xc0\x00\x00\x00\x000\x93^\xb0\x00\x00\x00\x001g\xae@\x00\x00\x00\x002s@\xb0\x00\x00\x00\x003G\x90@\x00\x00\x00\x004S\"\xb0\x00\x00\x00\x005'r@" + - "\x00\x00\x00\x0063\x04\xb0\x00\x00\x00\x007\aT@\x00\x00\x00\x008\x1c!0\x00\x00\x00\x008\xe76@\x00\x00\x00\x009\xfc\x030\x00\x00\x00\x00:\xc7\x18@\x00\x00\x00\x00;\xdb\xe50\x00\x00\x00\x00" + - "<\xb04\xc0\x00\x00\x00\x00=\xbb\xc70\x00\x00\x00\x00>\x90\x16\xc0\x00\x00\x00\x00?\x9b\xa90\x00\x00\x00\x00@o\xf8\xc0\x00\x00\x00\x00A\x84Ű\x00\x00\x00\x00BO\xda\xc0\x00\x00\x00\x00Cd\xa7\xb0" + - "\x00\x00\x00\x00D/\xbc\xc0\x00\x00\x00\x00ED\x89\xb0\x00\x00\x00\x00E\xf3\xef@\x01\x02\x03\x04\x02\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\a" + - "\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\x00\x00\xab\xe2\x00\x00\xff\xffZb\x00\x00" + - "\xff\xffeP\x00\x04\xff\xffs`\x01\b\xff\xffs`\x01\f\xff\xffeP\x00\x10\xff\xffs`\x01\x14\xff\xffs`\x00\x18\xff\xff\x81p\x01\x1d\xff\xffs`\x00\x19LMT\x00NST\x00NWT\x00" + - "NPT\x00BST\x00BDT\x00AHST\x00HDT\x00\nHST10HDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R" + - "$ \x873\xf8\x03\x00\x00\xf8\x03\x00\x00\x11\x00\x1c\x00US/Indiana-StarkeUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00" + - "\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00]\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p" + - "\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xd5U\xd5\x00\xff\xff\xff\xff\xd6 \xcd\xf0\xff\xff\xff\xff" + - "\xd75\xb7\x00\xff\xff\xff\xff\xd8\x00\xaf\xf0\xff\xff\xff\xff\xd9\x15\x99\x00\xff\xff\xff\xff\xd9\xe0\x91\xf0\xff\xff\xff\xff\xda\xfe\xb5\x80\xff\xff\xff\xff\xdb\xc0s\xf0\xff\xff\xff\xff\xdcޗ\x80\xff\xff\xff\xffݩ\x90p" + - "\xff\xff\xff\xff\u07bey\x80\xff\xff\xff\xff߉rp\xff\xff\xff\xff\xe0\x9e[\x80\xff\xff\xff\xff\xe1iTp\xff\xff\xff\xff\xe2~=\x80\xff\xff\xff\xff\xe3I6p\xff\xff\xff\xff\xe4^\x1f\x80\xff\xff\xff\xff" + - "\xe5W<\xf0\xff\xff\xff\xff\xe6G<\x00\xff\xff\xff\xff\xe77\x1e\xf0\xff\xff\xff\xff\xe8'\x1e\x00\xff\xff\xff\xff\xe8\xf2\x16\xf0\xff\xff\xff\xff\xea\a\x00\x00\xff\xff\xff\xff\xea\xd1\xf8\xf0\xff\xff\xff\xff\xeb\xe6\xe2\x00" + - "\xff\xff\xff\xff\xec\xd6\xc4\xf0\xff\xff\xff\xff\xed\xc6\xc4\x00\xff\xff\xff\xff\xee\xbf\xe1p\xff\xff\xff\xff\xef\xaf\xe0\x80\xff\xff\xff\xff\xf0\x9f\xc3p\xff\xff\xff\xff\xf1\x8f\u0080\xff\xff\xff\xff\xf4_\x87p\xff\xff\xff\xff" + - "\xfa\xf8g\x00\xff\xff\xff\xff\xfb\xe8I\xf0\xff\xff\xff\xff\xfc\xd8I\x00\xff\xff\xff\xff\xfd\xc8+\xf0\xff\xff\xff\xff\xfe\xb8+\x00\xff\xff\xff\xff\xff\xa8\r\xf0\x00\x00\x00\x00\x00\x98\r\x00\x00\x00\x00\x00\x01\x87\xef\xf0" + - "\x00\x00\x00\x00\x02w\xef\x00\x00\x00\x00\x00\x03q\fp\x00\x00\x00\x00\x04a\v\x80\x00\x00\x00\x00\x05P\xeep\x00\x00\x00\x00\x06@\xed\x80\x00\x00\x00\x00\a0\xd0p\x00\x00\x00\x00\a\x8d'\x80\x00\x00\x00\x00" + - "\t\x10\xb2p\x00\x00\x00\x00\t\xad\xa3\x00\x00\x00\x00\x00\n\xf0\x94p\x00\x00\x00\x00\v\xe0\x93\x80\x00\x00\x00\x00\fٰ\xf0\x00\x00\x00\x00\r\xc0u\x80\x00\x00\x00\x00\x0e\xb9\x92\xf0\x00\x00\x00\x00\x0f\xa9\x92\x00" + - "\x00\x00\x00\x00\x10\x99t\xf0\x00\x00\x00\x00\x11\x89t\x00\x00\x00\x00\x00\x12yV\xf0\x00\x00\x00\x00\x13iV\x00\x00\x00\x00\x00\x14Y8\xf0\x00\x00\x00\x00\x15I8\x00\x00\x00\x00\x00\x169\x1a\xf0\x00\x00\x00\x00" + - "\x17)\x1a\x00\x00\x00\x00\x00\x18\"7p\x00\x00\x00\x00\x19\b\xfc\x00\x00\x00\x00\x00\x1a\x02\x19p\x00\x00\x00\x00\x1a\xf2\x18\x80\x00\x00\x00\x00\x1b\xe1\xfbp\x00\x00\x00\x00\x1c\xd1\xfa\x80\x00\x00\x00\x00\x1d\xc1\xddp" + - "\x00\x00\x00\x00\x1e\xb1܀\x00\x00\x00\x00\x1f\xa1\xbfp\x00\x00\x00\x00 v\x0f\x00\x00\x00\x00\x00!\x81\xa1p\x00\x00\x00\x00\"U\xf1\x00\x00\x00\x00\x00#j\xbd\xf0\x00\x00\x00\x00$5\xd3\x00\x00\x00\x00\x00" + - "%J\x9f\xf0\x00\x00\x00\x00&\x15\xb5\x00\x00\x00\x00\x00'*\x81\xf0\x00\x00\x00\x00'\xfeр\x00\x00\x00\x00)\nc\xf0\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7\x00" + - "\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x05\x01\x02\x01\xff\xff\xae\xca\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9" + - "\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14LMT\x00CDT\x00CST\x00CWT\x00CPT\x00EST\x00\nCST6CDT,M3.2.0,M11.1.0\nPK\x03" + - "\x04\n\x00\x00\x00\x00\x00\xf1c9RV\x80\x94@\x12\x04\x00\x00\x12\x04\x00\x00\v\x00\x1c\x00US/MountainUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00" + - "\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZi" + - "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00a\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff^\x04\f\xb0\xff\xff\xff\xff\x9e\xa6:\x90\xff\xff\xff" + - "\xff\x9f\xbb\a\x80\xff\xff\xff\xff\xa0\x86\x1c\x90\xff\xff\xff\xff\xa1\x9a\xe9\x80\xff\xff\xff\xff\xa2e\xfe\x90\xff\xff\xff\xff\xa3\x84\x06\x00\xff\xff\xff\xff\xa4E\xe0\x90\xff\xff\xff\xff\xa4\x8f\xa6\x80\xff\xff\xff\xffˉ\f" + - "\x90\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\x18\x00\xff\xff\xff\xff\xf7/v\x90\xff\xff\xff\xff\xf8(\x94\x00\xff\xff\xff\xff\xf9\x0fX\x90\xff\xff\xff\xff\xfa\bv\x00\xff\xff\xff\xff\xfa\xf8u\x10\xff\xff\xff" + - "\xff\xfb\xe8X\x00\xff\xff\xff\xff\xfc\xd8W\x10\xff\xff\xff\xff\xfd\xc8:\x00\xff\xff\xff\xff\xfe\xb89\x10\xff\xff\xff\xff\xff\xa8\x1c\x00\x00\x00\x00\x00\x00\x98\x1b\x10\x00\x00\x00\x00\x01\x87\xfe\x00\x00\x00\x00\x00\x02w\xfd" + - "\x10\x00\x00\x00\x00\x03q\x1a\x80\x00\x00\x00\x00\x04a\x19\x90\x00\x00\x00\x00\x05P\xfc\x80\x00\x00\x00\x00\x06@\xfb\x90\x00\x00\x00\x00\a0ހ\x00\x00\x00\x00\a\x8d5\x90\x00\x00\x00\x00\t\x10\xc0\x80\x00\x00\x00" + - "\x00\t\xad\xb1\x10\x00\x00\x00\x00\n\xf0\xa2\x80\x00\x00\x00\x00\vࡐ\x00\x00\x00\x00\fٿ\x00\x00\x00\x00\x00\r\xc0\x83\x90\x00\x00\x00\x00\x0e\xb9\xa1\x00\x00\x00\x00\x00\x0f\xa9\xa0\x10\x00\x00\x00\x00\x10\x99\x83" + - "\x00\x00\x00\x00\x00\x11\x89\x82\x10\x00\x00\x00\x00\x12ye\x00\x00\x00\x00\x00\x13id\x10\x00\x00\x00\x00\x14YG\x00\x00\x00\x00\x00\x15IF\x10\x00\x00\x00\x00\x169)\x00\x00\x00\x00\x00\x17)(\x10\x00\x00\x00" + - "\x00\x18\"E\x80\x00\x00\x00\x00\x19\t\n\x10\x00\x00\x00\x00\x1a\x02'\x80\x00\x00\x00\x00\x1a\xf2&\x90\x00\x00\x00\x00\x1b\xe2\t\x80\x00\x00\x00\x00\x1c\xd2\b\x90\x00\x00\x00\x00\x1d\xc1\xeb\x80\x00\x00\x00\x00\x1e\xb1\xea" + - "\x90\x00\x00\x00\x00\x1f\xa1̀\x00\x00\x00\x00 v\x1d\x10\x00\x00\x00\x00!\x81\xaf\x80\x00\x00\x00\x00\"U\xff\x10\x00\x00\x00\x00#j\xcc\x00\x00\x00\x00\x00$5\xe1\x10\x00\x00\x00\x00%J\xae\x00\x00\x00\x00" + - "\x00&\x15\xc3\x10\x00\x00\x00\x00'*\x90\x00\x00\x00\x00\x00'\xfeߐ\x00\x00\x00\x00)\nr\x00\x00\x00\x00\x00)\xde\xc1\x90\x00\x00\x00\x00*\xeaT\x00\x00\x00\x00\x00+\xbe\xa3\x90\x00\x00\x00\x00,\xd3p" + - "\x80\x00\x00\x00\x00-\x9e\x85\x90\x00\x00\x00\x00.\xb3R\x80\x00\x00\x00\x00/~g\x90\x00\x00\x00\x000\x934\x80\x00\x00\x00\x001g\x84\x10\x00\x00\x00\x002s\x16\x80\x00\x00\x00\x003Gf\x10\x00\x00\x00" + - "\x004R\xf8\x80\x00\x00\x00\x005'H\x10\x00\x00\x00\x0062ڀ\x00\x00\x00\x007\a*\x10\x00\x00\x00\x008\x1b\xf7\x00\x00\x00\x00\x008\xe7\f\x10\x00\x00\x00\x009\xfb\xd9\x00\x00\x00\x00\x00:\xc6\xee" + - "\x10\x00\x00\x00\x00;ۻ\x00\x00\x00\x00\x00<\xb0\n\x90\x00\x00\x00\x00=\xbb\x9d\x00\x00\x00\x00\x00>\x8f\xec\x90\x00\x00\x00\x00?\x9b\u007f\x00\x00\x00\x00\x00@oΐ\x00\x00\x00\x00A\x84\x9b\x80\x00\x00\x00" + - "\x00BO\xb0\x90\x00\x00\x00\x00Cd}\x80\x00\x00\x00\x00D/\x92\x90\x00\x00\x00\x00ED_\x80\x00\x00\x00\x00E\xf3\xc5\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff" + + "\xba\x9e\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x01\f\xff\xff\xc7\xc0\x01\x10LMT\x00EDT\x00EST\x00EWT\x00EPT\x00\nEST5EDT,M3." + + "2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS>\x14\xe7\x03\x83\x03\x00\x00\x83\x03\x00\x00\v\x00\x1c\x00US/MichiganUT\t\x00\x03\x82\x0f" + + "\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00P\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff" + + "\x85\xbd\"[\xff\xff\xff\xff\x99<\x94\x00\xff\xff\xff\xffˈ\xf0p\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xfb\xe0\xff\xff\xff\xff\xd75\xa8\xf0\xff\xff\xff\xff\xd8\x00\xa1\xe0\xff\xff\xff\xff\xfb3\x90\x8c" + + "\xff\xff\xff\xff\xfb\xe8;\xe0\xff\xff\xff\xff\xfc\xd8:\xf0\xff\xff\xff\xff\xfd\xc8\x1d\xe0\x00\x00\x00\x00\x06@\xdfp\x00\x00\x00\x00\a0\xc2`\x00\x00\x00\x00\a\x8d\x19p\x00\x00\x00\x00\t\x10\xa4`\x00\x00\x00\x00" + + "\n\x00\xa3p\x00\x00\x00\x00\n\xf0\x86`\x00\x00\x00\x00\v\xe0\x85p\x00\x00\x00\x00\f٢\xe0\x00\x00\x00\x00\r\xc0gp\x00\x00\x00\x00\x0e\xb9\x84\xe0\x00\x00\x00\x00\x0f\xa9\x83\xf0\x00\x00\x00\x00\x10\x99f\xe0" + + "\x00\x00\x00\x00\x11\x89e\xf0\x00\x00\x00\x00\x12yH\xe0\x00\x00\x00\x00\x13iG\xf0\x00\x00\x00\x00\x14Y*\xe0\x00\x00\x00\x00\x15I)\xf0\x00\x00\x00\x00\x169\f\xe0\x00\x00\x00\x00\x17)\v\xf0\x00\x00\x00\x00" + + "\x18\")`\x00\x00\x00\x00\x19\b\xed\xf0\x00\x00\x00\x00\x1a\x02\v`\x00\x00\x00\x00\x1a\xf2\np\x00\x00\x00\x00\x1b\xe1\xed`\x00\x00\x00\x00\x1c\xd1\xecp\x00\x00\x00\x00\x1d\xc1\xcf`\x00\x00\x00\x00\x1e\xb1\xcep" + + "\x00\x00\x00\x00\x1f\xa1\xb1`\x00\x00\x00\x00 v\x00\xf0\x00\x00\x00\x00!\x81\x93`\x00\x00\x00\x00\"U\xe2\xf0\x00\x00\x00\x00#j\xaf\xe0\x00\x00\x00\x00$5\xc4\xf0\x00\x00\x00\x00%J\x91\xe0\x00\x00\x00\x00" + + "&\x15\xa6\xf0\x00\x00\x00\x00'*s\xe0\x00\x00\x00\x00'\xfe\xc3p\x00\x00\x00\x00)\nU\xe0\x00\x00\x00\x00)ޥp\x00\x00\x00\x00*\xea7\xe0\x00\x00\x00\x00+\xbe\x87p\x00\x00\x00\x00,\xd3T`" + + "\x00\x00\x00\x00-\x9eip\x00\x00\x00\x00.\xb36`\x00\x00\x00\x00/~Kp\x00\x00\x00\x000\x93\x18`\x00\x00\x00\x001gg\xf0\x00\x00\x00\x002r\xfa`\x00\x00\x00\x003GI\xf0\x00\x00\x00\x00" + + "4R\xdc`\x00\x00\x00\x005'+\xf0\x00\x00\x00\x0062\xbe`\x00\x00\x00\x007\a\r\xf0\x00\x00\x00\x008\x1b\xda\xe0\x00\x00\x00\x008\xe6\xef\xf0\x00\x00\x00\x009\xfb\xbc\xe0\x00\x00\x00\x00:\xc6\xd1\xf0" + + "\x00\x00\x00\x00;۞\xe0\x00\x00\x00\x00<\xaf\xeep\x00\x00\x00\x00=\xbb\x80\xe0\x00\x00\x00\x00>\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00\x00\x00\x00" + + "BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x01\x02\x03\x04\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05" + + "\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\x02\x05\xff\xff\xb2%" + + "\x00\x00\xff\xff\xab\xa0\x00\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x01\f\xff\xff\xc7\xc0\x01\x10\xff\xff\xc7\xc0\x01\x14LMT\x00CST\x00EST\x00EWT\x00EPT\x00EDT\x00\nEST" + + "5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\xf6\"\x12\xfe\x0e\x05\x00\x00\x0e\x05\x00\x00\n\x00\x1c\x00US/Pacific" + + "UT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00}\x00\x00\x00\x05\x00" + + "\x00\x00\x14\xff\xff\xff\xff^\x04\x1a\xc0\xff\xff\xff\xff\x9e\xa6H\xa0\xff\xff\xff\xff\x9f\xbb\x15\x90\xff\xff\xff\xff\xa0\x86*\xa0\xff\xff\xff\xff\xa1\x9a\xf7\x90\xff\xff\xff\xffˉ\x1a\xa0\xff\xff\xff\xff\xd2#\xf4p\xff" + + "\xff\xff\xff\xd2a&\x10\xff\xff\xff\xff\xd6\xfet\\\xff\xff\xff\xff\u0600\xad\x90\xff\xff\xff\xff\xda\xfeÐ\xff\xff\xff\xff\xdb\xc0\x90\x10\xff\xff\xff\xff\xdcޥ\x90\xff\xff\xff\xffݩ\xac\x90\xff\xff\xff\xff\xde" + + "\xbe\x87\x90\xff\xff\xff\xff߉\x8e\x90\xff\xff\xff\xff\xe0\x9ei\x90\xff\xff\xff\xff\xe1ip\x90\xff\xff\xff\xff\xe2~K\x90\xff\xff\xff\xff\xe3IR\x90\xff\xff\xff\xff\xe4^-\x90\xff\xff\xff\xff\xe5)4\x90\xff" + + "\xff\xff\xff\xe6GJ\x10\xff\xff\xff\xff\xe7\x12Q\x10\xff\xff\xff\xff\xe8',\x10\xff\xff\xff\xff\xe8\xf23\x10\xff\xff\xff\xff\xea\a\x0e\x10\xff\xff\xff\xff\xea\xd2\x15\x10\xff\xff\xff\xff\xeb\xe6\xf0\x10\xff\xff\xff\xff\xec" + + "\xb1\xf7\x10\xff\xff\xff\xff\xed\xc6\xd2\x10\xff\xff\xff\xff\xee\x91\xd9\x10\xff\xff\xff\xff\xef\xaf\xee\x90\xff\xff\xff\xff\xf0q\xbb\x10\xff\xff\xff\xff\xf1\x8fА\xff\xff\xff\xff\xf2\u007f\xc1\x90\xff\xff\xff\xff\xf3o\xb2\x90\xff" + + "\xff\xff\xff\xf4_\xa3\x90\xff\xff\xff\xff\xf5O\x94\x90\xff\xff\xff\xff\xf6?\x85\x90\xff\xff\xff\xff\xf7/v\x90\xff\xff\xff\xff\xf8(\xa2\x10\xff\xff\xff\xff\xf9\x0fX\x90\xff\xff\xff\xff\xfa\b\x84\x10\xff\xff\xff\xff\xfa" + + "\xf8\x83 \xff\xff\xff\xff\xfb\xe8f\x10\xff\xff\xff\xff\xfc\xd8e \xff\xff\xff\xff\xfd\xc8H\x10\xff\xff\xff\xff\xfe\xb8G \xff\xff\xff\xff\xff\xa8*\x10\x00\x00\x00\x00\x00\x98) \x00\x00\x00\x00\x01\x88\f\x10\x00" + + "\x00\x00\x00\x02x\v \x00\x00\x00\x00\x03q(\x90\x00\x00\x00\x00\x04a'\xa0\x00\x00\x00\x00\x05Q\n\x90\x00\x00\x00\x00\x06A\t\xa0\x00\x00\x00\x00\a0\xec\x90\x00\x00\x00\x00\a\x8dC\xa0\x00\x00\x00\x00\t" + + "\x10ΐ\x00\x00\x00\x00\t\xad\xbf \x00\x00\x00\x00\n\xf0\xb0\x90\x00\x00\x00\x00\v\u0be0\x00\x00\x00\x00\f\xd9\xcd\x10\x00\x00\x00\x00\r\xc0\x91\xa0\x00\x00\x00\x00\x0e\xb9\xaf\x10\x00\x00\x00\x00\x0f\xa9\xae \x00" + + "\x00\x00\x00\x10\x99\x91\x10\x00\x00\x00\x00\x11\x89\x90 \x00\x00\x00\x00\x12ys\x10\x00\x00\x00\x00\x13ir \x00\x00\x00\x00\x14YU\x10\x00\x00\x00\x00\x15IT \x00\x00\x00\x00\x1697\x10\x00\x00\x00\x00\x17" + + ")6 \x00\x00\x00\x00\x18\"S\x90\x00\x00\x00\x00\x19\t\x18 \x00\x00\x00\x00\x1a\x025\x90\x00\x00\x00\x00\x1a\xf24\xa0\x00\x00\x00\x00\x1b\xe2\x17\x90\x00\x00\x00\x00\x1c\xd2\x16\xa0\x00\x00\x00\x00\x1d\xc1\xf9\x90\x00" + + "\x00\x00\x00\x1e\xb1\xf8\xa0\x00\x00\x00\x00\x1f\xa1ې\x00\x00\x00\x00 v+ \x00\x00\x00\x00!\x81\xbd\x90\x00\x00\x00\x00\"V\r \x00\x00\x00\x00#j\xda\x10\x00\x00\x00\x00$5\xef \x00\x00\x00\x00%" + + "J\xbc\x10\x00\x00\x00\x00&\x15\xd1 \x00\x00\x00\x00'*\x9e\x10\x00\x00\x00\x00'\xfe\xed\xa0\x00\x00\x00\x00)\n\x80\x10\x00\x00\x00\x00)\xdeϠ\x00\x00\x00\x00*\xeab\x10\x00\x00\x00\x00+\xbe\xb1\xa0\x00" + + "\x00\x00\x00,\xd3~\x90\x00\x00\x00\x00-\x9e\x93\xa0\x00\x00\x00\x00.\xb3`\x90\x00\x00\x00\x00/~u\xa0\x00\x00\x00\x000\x93B\x90\x00\x00\x00\x001g\x92 \x00\x00\x00\x002s$\x90\x00\x00\x00\x003" + + "Gt \x00\x00\x00\x004S\x06\x90\x00\x00\x00\x005'V \x00\x00\x00\x0062\xe8\x90\x00\x00\x00\x007\a8 \x00\x00\x00\x008\x1c\x05\x10\x00\x00\x00\x008\xe7\x1a \x00\x00\x00\x009\xfb\xe7\x10\x00" + + "\x00\x00\x00:\xc6\xfc \x00\x00\x00\x00;\xdb\xc9\x10\x00\x00\x00\x00<\xb0\x18\xa0\x00\x00\x00\x00=\xbb\xab\x10\x00\x00\x00\x00>\x8f\xfa\xa0\x00\x00\x00\x00?\x9b\x8d\x10\x00\x00\x00\x00@oܠ\x00\x00\x00\x00A" + + "\x84\xa9\x90\x00\x00\x00\x00BO\xbe\xa0\x00\x00\x00\x00Cd\x8b\x90\x00\x00\x00\x00D/\xa0\xa0\x00\x00\x00\x00EDm\x90\x00\x00\x00\x00E\xf3\xd3 \x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\x9d\x94\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\f\xff\xff\xab\xa0\x01\x10LMT\x00MDT\x00MST\x00MWT\x00" + - "MPT\x00\nMST7MDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rø\xab\x9b\xf0\x00\x00\x00\xf0\x00\x00\x00\n\x00\x1c\x00US" + - "/ArizonaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\v\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff^\x04\f\xb0\xff\xff\xff\xff\x9e\xa6:\x90\xff\xff\xff\xff\x9f\xbb\a\x80\xff\xff\xff\xff\xa0\x86\x1c\x90\xff\xff\xff\xff\xa1\x9a\xe9\x80\xff\xff\xff\xffˉ\f\x90\xff" + - "\xff\xff\xff\xcf\x17\xdf\x1c\xff\xff\xff\xffϏ\xe5\xac\xff\xff\xff\xffЁ\x1a\x1c\xff\xff\xff\xff\xfa\xf8u\x10\xff\xff\xff\xff\xfb\xe8X\x00\x02\x01\x02\x01\x02\x03\x02\x03\x02\x01\x02\xff\xff\x96\xee\x00\x00\xff\xff\xab\xa0" + - "\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\fLMT\x00MDT\x00MST\x00MWT\x00\nMST7\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R3\x9aG\xc8\xd0\x06\x00\x00\xd0\x06" + - "\x00\x00\n\x00\x1c\x00US/EasternUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaf\x00\x00\x00\x05\x00\x00\x00\x14\xff\xff\xff\xff^\x03\xf0\x90\xff\xff\xff\xff\x9e\xa6\x1ep\xff\xff\xff\xff\x9f\xba\xeb`\xff\xff\xff\xff\xa0\x86\x00p\xff\xff\xff\xff\xa1\x9a\xcd`\xff" + - "\xff\xff\xff\xa2e\xe2p\xff\xff\xff\xff\xa3\x83\xe9\xe0\xff\xff\xff\xff\xa4j\xaep\xff\xff\xff\xff\xa55\xa7`\xff\xff\xff\xff\xa6S\xca\xf0\xff\xff\xff\xff\xa7\x15\x89`\xff\xff\xff\xff\xa83\xac\xf0\xff\xff\xff\xff\xa8" + - "\xfe\xa5\xe0\xff\xff\xff\xff\xaa\x13\x8e\xf0\xff\xff\xff\xff\xaaއ\xe0\xff\xff\xff\xff\xab\xf3p\xf0\xff\xff\xff\xff\xac\xbei\xe0\xff\xff\xff\xff\xad\xd3R\xf0\xff\xff\xff\xff\xae\x9eK\xe0\xff\xff\xff\xff\xaf\xb34\xf0\xff" + - "\xff\xff\xff\xb0~-\xe0\xff\xff\xff\xff\xb1\x9cQp\xff\xff\xff\xff\xb2gJ`\xff\xff\xff\xff\xb3|3p\xff\xff\xff\xff\xb4G,`\xff\xff\xff\xff\xb5\\\x15p\xff\xff\xff\xff\xb6'\x0e`\xff\xff\xff\xff\xb7" + - ";\xf7p\xff\xff\xff\xff\xb8\x06\xf0`\xff\xff\xff\xff\xb9\x1b\xd9p\xff\xff\xff\xff\xb9\xe6\xd2`\xff\xff\xff\xff\xbb\x04\xf5\xf0\xff\xff\xff\xff\xbbƴ`\xff\xff\xff\xff\xbc\xe4\xd7\xf0\xff\xff\xff\xff\xbd\xaf\xd0\xe0\xff" + - "\xff\xff\xff\xbeĹ\xf0\xff\xff\xff\xff\xbf\x8f\xb2\xe0\xff\xff\xff\xff\xc0\xa4\x9b\xf0\xff\xff\xff\xff\xc1o\x94\xe0\xff\xff\xff\xff\u0084}\xf0\xff\xff\xff\xff\xc3Ov\xe0\xff\xff\xff\xff\xc4d_\xf0\xff\xff\xff\xff\xc5" + - "/X\xe0\xff\xff\xff\xff\xc6M|p\xff\xff\xff\xff\xc7\x0f:\xe0\xff\xff\xff\xff\xc8-^p\xff\xff\xff\xff\xc8\xf8W`\xff\xff\xff\xff\xca\r@p\xff\xff\xff\xff\xca\xd89`\xff\xff\xff\xffˈ\xf0p\xff" + - "\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2`\xfb\xe0\xff\xff\xff\xff\xd3u\xe4\xf0\xff\xff\xff\xff\xd4@\xdd\xe0\xff\xff\xff\xff\xd5U\xc6\xf0\xff\xff\xff\xff\xd6 \xbf\xe0\xff\xff\xff\xff\xd75\xa8\xf0\xff\xff\xff\xff\xd8" + - "\x00\xa1\xe0\xff\xff\xff\xff\xd9\x15\x8a\xf0\xff\xff\xff\xff\xd9\xe0\x83\xe0\xff\xff\xff\xff\xda\xfe\xa7p\xff\xff\xff\xff\xdb\xc0e\xe0\xff\xff\xff\xff\xdcމp\xff\xff\xff\xffݩ\x82`\xff\xff\xff\xff\u07bekp\xff" + - "\xff\xff\xff߉d`\xff\xff\xff\xff\xe0\x9eMp\xff\xff\xff\xff\xe1iF`\xff\xff\xff\xff\xe2~/p\xff\xff\xff\xff\xe3I(`\xff\xff\xff\xff\xe4^\x11p\xff\xff\xff\xff\xe5W.\xe0\xff\xff\xff\xff\xe6" + - "G-\xf0\xff\xff\xff\xff\xe77\x10\xe0\xff\xff\xff\xff\xe8'\x0f\xf0\xff\xff\xff\xff\xe9\x16\xf2\xe0\xff\xff\xff\xff\xea\x06\xf1\xf0\xff\xff\xff\xff\xea\xf6\xd4\xe0\xff\xff\xff\xff\xeb\xe6\xd3\xf0\xff\xff\xff\xff\xecֶ\xe0\xff" + - "\xff\xff\xff\xedƵ\xf0\xff\xff\xff\xff\xee\xbf\xd3`\xff\xff\xff\xff\xef\xaf\xd2p\xff\xff\xff\xff\xf0\x9f\xb5`\xff\xff\xff\xff\xf1\x8f\xb4p\xff\xff\xff\xff\xf2\u007f\x97`\xff\xff\xff\xff\xf3o\x96p\xff\xff\xff\xff\xf4" + - "_y`\xff\xff\xff\xff\xf5Oxp\xff\xff\xff\xff\xf6?[`\xff\xff\xff\xff\xf7/Zp\xff\xff\xff\xff\xf8(w\xe0\xff\xff\xff\xff\xf9\x0f\x8f\xd0p\x00\x00\x00\x00?\x9bb\xe0\x00\x00\x00\x00@o\xb2p\x00\x00\x00\x00A\x84\u007f`\x00" + - "\x00\x00\x00BO\x94p\x00\x00\x00\x00Cda`\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\x91&\x00\x00\xff\xff\x9d\x90\x01\x04" + + "\xff\xff\x8f\x80\x00\b\xff\xff\x9d\x90\x01\f\xff\xff\x9d\x90\x01\x10LMT\x00PDT\x00PST\x00PWT\x00PPT\x00\nPST8PDT,M3.2.0,M11.1." + + "0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSt\xca{e\x92\x00\x00\x00\x92\x00\x00\x00\b\x00\x1c\x00US/SamoaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14" + + "E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00T" + + "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\b\xff\xff\xff\xffn=\xc8\b\xff\xff\xff\xff\x91\x05\xfb\b\x01" + + "\x02\x00\x00\xb1x\x00\x00\xff\xff_\xf8\x00\x00\xff\xffeP\x00\x04LMT\x00SST\x00\nSST11\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iSø\xab\x9b\xf0\x00\x00\x00\xf0\x00\x00\x00" + + "\n\x00\x1c\x00US/ArizonaUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\v\x00\x00\x00\x04\x00\x00\x00\x10\xff\xff\xff\xff^\x04\f\xb0\xff\xff\xff\xff\x9e\xa6:\x90\xff\xff\xff\xff\x9f\xbb\a\x80\xff\xff\xff\xff\xa0\x86\x1c\x90\xff\xff\xff\xff\xa1\x9a\xe9\x80\xff\xff\xff" + + "\xffˉ\f\x90\xff\xff\xff\xff\xcf\x17\xdf\x1c\xff\xff\xff\xffϏ\xe5\xac\xff\xff\xff\xffЁ\x1a\x1c\xff\xff\xff\xff\xfa\xf8u\x10\xff\xff\xff\xff\xfb\xe8X\x00\x02\x01\x02\x01\x02\x03\x02\x03\x02\x01\x02\xff\xff\x96\xee" + + "\x00\x00\xff\xff\xab\xa0\x01\x04\xff\xff\x9d\x90\x00\b\xff\xff\xab\xa0\x01\fLMT\x00MDT\x00MST\x00MWT\x00\nMST7\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x9bܩ=" + + "\xda\x06\x00\x00\xda\x06\x00\x00\n\x00\x1c\x00US/CentralUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaf\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff" + + "\xff\xa1\x9a\xdbp\xff\xff\xff\xff\xa2\xcbt\x00\xff\xff\xff\xff\xa3\x83\xf7\xf0\xff\xff\xff\xff\xa4EҀ\xff\xff\xff\xff\xa5c\xd9\xf0\xff\xff\xff\xff\xa6S\xd9\x00\xff\xff\xff\xff\xa7\x15\x97p\xff\xff\xff\xff\xa83\xbb" + + "\x00\xff\xff\xff\xff\xa8\xfe\xb3\xf0\xff\xff\xff\xff\xaa\x13\x9d\x00\xff\xff\xff\xff\xaaޕ\xf0\xff\xff\xff\xff\xab\xf3\u007f\x00\xff\xff\xff\xff\xac\xbew\xf0\xff\xff\xff\xff\xad\xd3a\x00\xff\xff\xff\xff\xae\x9eY\xf0\xff\xff\xff" + + "\xff\xaf\xb3C\x00\xff\xff\xff\xff\xb0~;\xf0\xff\xff\xff\xff\xb1\x9c_\x80\xff\xff\xff\xff\xb2gXp\xff\xff\xff\xff\xb3|A\x80\xff\xff\xff\xff\xb4G:p\xff\xff\xff\xff\xb5\\#\x80\xff\xff\xff\xff\xb6'\x1c" + + "p\xff\xff\xff\xff\xb7<\x05\x80\xff\xff\xff\xff\xb8\x06\xfep\xff\xff\xff\xff\xb9\x1b\xe7\x80\xff\xff\xff\xff\xb9\xe6\xe0p\xff\xff\xff\xff\xbb\x05\x04\x00\xff\xff\xff\xff\xbb\xc6\xc2p\xff\xff\xff\xff\xbc\xe4\xe6\x00\xff\xff\xff" + + "\xff\xbd\xaf\xde\xf0\xff\xff\xff\xff\xbe\xc4\xc8\x00\xff\xff\xff\xff\xbf\x8f\xc0\xf0\xff\xff\xff\xff\xc0Z\xd6\x00\xff\xff\xff\xff\xc1\xb0\x8fހ\x00\x00\x00\x00?\x9bp\xf0\x00\x00\x00\x00@o\xc0\x80\x00\x00\x00" + + "\x00A\x84\x8dp\x00\x00\x00\x00BO\xa2\x80\x00\x00\x00\x00Cdop\x00\x00\x00\x00D/\x84\x80\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7\x00\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x03\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x04\x05\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01" + - "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xba\x9e\x00\x00\xff\xff\xc7\xc0\x01\x04\xff\xff\xb9\xb0\x00\b\xff\xff\xc7\xc0\x01\f\xff\xff" + - "\xc7\xc0\x01\x10LMT\x00EDT\x00EST\x00EWT\x00EPT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c" + - "9R5\x11Q\x06\xd1\x03\x00\x00\xd1\x03\x00\x00\t\x00\x1c\x00US/AlaskaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00T\x00\x00\x00\n\x00\x00\x00(\xff\xff\xff\xff?\xc2\xfd\xd1\xff\xff\xff\xff}\x87AH\xff\xff\xff\xffˉ6\xc0\xff\xff\xff\xff\xd2#" + - "\xf4p\xff\xff\xff\xff\xd2aB0\xff\xff\xff\xff\xfa\xd2G\xa0\xff\xff\xff\xff\xfe\xb8c@\xff\xff\xff\xff\xff\xa8F0\x00\x00\x00\x00\x00\x98E@\x00\x00\x00\x00\x01\x88(0\x00\x00\x00\x00\x02x'@\x00\x00" + - "\x00\x00\x03qD\xb0\x00\x00\x00\x00\x04aC\xc0\x00\x00\x00\x00\x05Q&\xb0\x00\x00\x00\x00\x06A%\xc0\x00\x00\x00\x00\a1\b\xb0\x00\x00\x00\x00\a\x8d_\xc0\x00\x00\x00\x00\t\x10\xea\xb0\x00\x00\x00\x00\t\xad" + - "\xdb@\x00\x00\x00\x00\n\xf0̰\x00\x00\x00\x00\v\xe0\xcb\xc0\x00\x00\x00\x00\f\xd9\xe90\x00\x00\x00\x00\r\xc0\xad\xc0\x00\x00\x00\x00\x0e\xb9\xcb0\x00\x00\x00\x00\x0f\xa9\xca@\x00\x00\x00\x00\x10\x99\xad0\x00\x00" + - "\x00\x00\x11\x89\xac@\x00\x00\x00\x00\x12y\x8f0\x00\x00\x00\x00\x13i\x8e@\x00\x00\x00\x00\x14Yq0\x00\x00\x00\x00\x15Ip@\x00\x00\x00\x00\x169S0\x00\x00\x00\x00\x17)R@\x00\x00\x00\x00\x18\"" + - "o\xb0\x00\x00\x00\x00\x19\t4@\x00\x00\x00\x00\x1a\x02Q\xb0\x00\x00\x00\x00\x1a+\x14\x10\x00\x00\x00\x00\x1a\xf2B\xb0\x00\x00\x00\x00\x1b\xe2%\xa0\x00\x00\x00\x00\x1c\xd2$\xb0\x00\x00\x00\x00\x1d\xc2\a\xa0\x00\x00" + - "\x00\x00\x1e\xb2\x06\xb0\x00\x00\x00\x00\x1f\xa1\xe9\xa0\x00\x00\x00\x00 v90\x00\x00\x00\x00!\x81ˠ\x00\x00\x00\x00\"V\x1b0\x00\x00\x00\x00#j\xe8 \x00\x00\x00\x00$5\xfd0\x00\x00\x00\x00%J" + - "\xca \x00\x00\x00\x00&\x15\xdf0\x00\x00\x00\x00'*\xac \x00\x00\x00\x00'\xfe\xfb\xb0\x00\x00\x00\x00)\n\x8e \x00\x00\x00\x00)\xdeݰ\x00\x00\x00\x00*\xeap \x00\x00\x00\x00+\xbe\xbf\xb0\x00\x00" + - "\x00\x00,ӌ\xa0\x00\x00\x00\x00-\x9e\xa1\xb0\x00\x00\x00\x00.\xb3n\xa0\x00\x00\x00\x00/~\x83\xb0\x00\x00\x00\x000\x93P\xa0\x00\x00\x00\x001g\xa00\x00\x00\x00\x002s2\xa0\x00\x00\x00\x003G" + - "\x820\x00\x00\x00\x004S\x14\xa0\x00\x00\x00\x005'd0\x00\x00\x00\x0062\xf6\xa0\x00\x00\x00\x007\aF0\x00\x00\x00\x008\x1c\x13 \x00\x00\x00\x008\xe7(0\x00\x00\x00\x009\xfb\xf5 \x00\x00" + - "\x00\x00:\xc7\n0\x00\x00\x00\x00;\xdb\xd7 \x00\x00\x00\x00<\xb0&\xb0\x00\x00\x00\x00=\xbb\xb9 \x00\x00\x00\x00>\x90\b\xb0\x00\x00\x00\x00?\x9b\x9b \x00\x00\x00\x00@o\xea\xb0\x00\x00\x00\x00A\x84" + - "\xb7\xa0\x00\x00\x00\x00BO̰\x00\x00\x00\x00Cd\x99\xa0\x00\x00\x00\x00D/\xae\xb0\x00\x00\x00\x00ED{\xa0\x00\x00\x00\x00E\xf3\xe10\x01\x02\x03\x04\x02\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05" + - "\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\a\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b\t\b" + - "\t\b\t\b\t\b\x00\x00\xc4\xf8\x00\x00\xff\xffsx\x00\x00\xff\xffs`\x00\x04\xff\xff\x81p\x01\b\xff\xff\x81p\x01\f\xff\xffs`\x00\x10\xff\xff\x81p\x01\x15\xff\xff\x81p\x00\x1a\xff\xff\x8f\x80\x01\x1e" + - "\xff\xff\x81p\x00#LMT\x00AST\x00AWT\x00APT\x00AHST\x00AHDT\x00YST\x00AKDT\x00AKST\x00\nAKST9AKDT,M3." + - "2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rt\xca{e\x92\x00\x00\x00\x92\x00\x00\x00\b\x00\x1c\x00US/SamoaUT\t\x00\x03\x15\xac\x0e`\x15" + - "\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00" + - "\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\b\xff\xff\xff\xffn=\xc8" + - "\b\xff\xff\xff\xff\x91\x05\xfb\b\x01\x02\x00\x00\xb1x\x00\x00\xff\xff_\xf8\x00\x00\xff\xffeP\x00\x04LMT\x00SST\x00\nSST11\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9Rp\xb6" + - "{\xc9\x13\x02\x00\x00\x13\x02\x00\x00\x0f\x00\x1c\x00US/East-IndianaUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZi" + - "f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00&\x00\x00\x00\a\x00\x00\x00\x1c\xff\xff\xff\xff^\x03\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff" + - "\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xff\xcaW\"\x80\xff\xff\xff\xff\xca\xd8Gp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff\xff\xff\xd3u\xf3\x00" + - "\xff\xff\xff\xff\xd4@\xeb\xf0\xff\xff\xff\xff\xd5U\xd5\x00\xff\xff\xff\xff\xd6 \xcd\xf0\xff\xff\xff\xff\xd75\xb7\x00\xff\xff\xff\xff\xd8\x00\xaf\xf0\xff\xff\xff\xff\xd9\x15\x99\x00\xff\xff\xff\xff\xd9\xe0\x91\xf0\xff\xff\xff\xff" + - "\xda\xfe\xb5\x80\xff\xff\xff\xff\xdb\xc0s\xf0\xff\xff\xff\xff\xdcޗ\x80\xff\xff\xff\xffݩ\x90p\xff\xff\xff\xff\u07bey\x80\xff\xff\xff\xff߉rp\xff\xff\xff\xff\xe0\x9e[\x80\xff\xff\xff\xff\xe1iTp" + - "\xff\xff\xff\xff\xe2~=\x80\xff\xff\xff\xff\xe3I6p\xff\xff\xff\xff\xe4^\x1f\x80\xff\xff\xff\xff\xe8\xf2\x16\xf0\xff\xff\xff\xff\xea\a\x00\x00\xff\xff\xff\xff\xfe\xb8\x1c\xf0\xff\xff\xff\xff\xff\xa7\xff\xe0\x00\x00\x00\x00" + - "\x00\x97\xfe\xf0\x00\x00\x00\x00\x01\x87\xe1\xe0\x00\x00\x00\x00D/vp\x00\x00\x00\x00EDC`\x00\x00\x00\x00E\xf3\xa8\xf0\x02\x01\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02" + - "\x01\x02\x01\x02\x05\x02\x05\x06\x05\x06\x05\x06\x05\x06\xff\xff\xaf:\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14\xff\xff\xc7\xc0\x01\x18LMT\x00" + - "CDT\x00CST\x00CWT\x00CPT\x00EST\x00EDT\x00\nEST5EDT,M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c" + - "9R\xeaK\x85v\xdd\x00\x00\x00\xdd\x00\x00\x00\t\x00\x1c\x00US/HawaiiUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x06\x00\x00\x00\x14\xff\xff\xff\xfft\xe0p\xbe\xff\xff\xff\xff\xbb\x05CH\xff\xff\xff\xff\xbb!qX\xff\xff\xff\xffˉ" + - "=\xc8\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2aI8\xff\xff\xff\xffՍsH\x01\x02\x01\x03\x04\x01\x05\xff\xffl\x02\x00\x00\xff\xfflX\x00\x04\xff\xffzh\x01\b\xff\xffzh\x01\f\xff\xffz" + - "h\x01\x10\xff\xffs`\x00\x04LMT\x00HST\x00HDT\x00HWT\x00HPT\x00\nHST10\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R\x9f.\xe4xo\x00\x00\x00o\x00" + - "\x00\x00\x03\x00\x1c\x00UTCUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00UTC\x00\nUTC0\nPK\x03\x04\n\x00\x00\x00\x00\x00\xf1c9R2\x91B\xc0\xee\x01\x00\x00\xee\x01\x00\x00\x03\x00\x1c\x00WE" + - "TUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\x00\x00\x00\x02" + - "\x00\x00\x00\t\x00\x00\x00\x00\r\xa4c\x90\x00\x00\x00\x00\x0e\x8b\x1a\x10\x00\x00\x00\x00\x0f\x84E\x90\x00\x00\x00\x00\x10t6\x90\x00\x00\x00\x00\x11d'\x90\x00\x00\x00\x00\x12T\x18\x90\x00\x00\x00\x00\x13MD\x10" + - "\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00" + - "\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10" + - "\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#\xf2y\xff\xff\xff\xff\x9e*\xee\xf9\xff\xff\xff\xff\x9e\xf79i" + - "\xff\xff\xff\xff\x9f\x84W\xf9\xff\xff\xff\xff\xa0\xd8l\xe9\xff\xff\xff\xff\xa1\x009\x80\xff\xff\xff\xff\xa1<\xa6@\xff\xff\xff\xff\xa4\x10m\xc0\xff\xff\xff\xff\xa4=2\xb0\xff\xff\xff\xff\xa5\x15h\xb0\xff\xff\xff\xff" + - "\xa5=\x03\xc0\xff\xff\xff\xff\xa7\x1eEP\xff\xff\xff\xff\xb5\xa4\x19`\x00\x00\x00\x00\x15'\xa7\xd0\x00\x00\x00\x00\x16\x18\xdc@\x00\x00\x00\x00\x17\b\xdbP\x00\x00\x00\x00\x17\xfa\x0f\xc0\x00\x00\x00\x00\x18\xea\x0e\xd0" + - "\x00\x00\x00\x00\x19\xdbC@\x00\x00\x00\x00\x1a̓\xd0\x00\x00\x00\x00\x1b\xbc\xa0\xf0\x00\x00\x00\x00\x1c\xac\x91\xf0\x00\x00\x00\x00\x1d\x9c\x82\xf0\x00\x00\x00\x00\x1e\x8cs\xf0\x00\x00\x00\x00\x1f|d\xf0\x00\x00\x00\x00" + - " lU\xf0\x00\x00\x00\x00!\\F\xf0\x00\x00\x00\x00\"L7\xf0\x00\x00\x00\x00#<(\xf0\x00\x00\x00\x00$,\x19\xf0\x00\x00\x00\x00%\x1c\n\xf0\x00\x00\x00\x00&\v\xfb\xf0\x00\x00\x00\x00'\x05'p" + - "\x00\x00\x00\x00'\xf5\x18p\x00\x00\x00\x00(\xe5\x17\x80\x00\x00\x00\x00)x\xbf\x80\x00\x00\x00\x00)\xd4\xfap\x00\x00\x00\x00*\xc4\xebp\x00\x00\x00\x00+\xb4\xdcp\x00\x00\x00\x00,\xa4\xcdp\x00\x00\x00\x00" + - "-\x94\xbep\x00\x00\x00\x00.\x84\xafp\x00\x00\x00\x00/t\xa0p\x00\x00\x00\x000d\x91p\x00\x00\x00\x001]\xbc\xf0\x00\x00\x00\x002r\x97\xf0\x00\x00\x00\x003=\x9e\xf0\x00\x00\x00\x004Ry\xf0" + - "\x00\x00\x00\x005\x1d\x80\xf0\x00\x00\x00\x0062[\xf0\x00\x00\x00\x006\xfdb\xf0\x00\x00\x00\x008\x1bxp\x00\x00\x00\x008\xddD\xf0\x00\x00\x00\x009\xfbZp\x00\x00\x00\x00:\xbd&\xf0\x00\x00\x00\x00" + - ";\xdb\x86%p\x00\x00\x00\x00?\x9b\x00p\x00\x00\x00\x00@f\ap\x00\x00\x00\x00A\x84\x1c\xf0\x00\x00\x00\x00BE\xe9p" + - "\x00\x00\x00\x00Cc\xfe\xf0\x00\x00\x00\x00D%\xcbp\x00\x00\x00\x00EC\xe0\xf0\x00\x00\x00\x00F\x05\xadp\x00\x00\x00\x00G#\xc2\xf0\x00\x00\x00\x00G\xee\xc9\xf0\x00\x00\x00\x00I\x03\xa4\xf0\x00\x00\x00\x00" + - "IΫ\xf0\x00\x00\x00\x00J\xe3\x86\xf0\x00\x00\x00\x00K\xae\x8d\xf0\x00\x00\x00\x00Ḷp\x00\x00\x00\x00M\x8eo\xf0\x00\x00\x00\x00TL\x1d`\x01\x03\x02\x03\x04\x02\x04\x05\x06\x05\a\x05\x06\b\x06\x05" + - "\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\t\b\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06" + - "\n\x06\x00\x00#9\x00\x00\x00\x00#9\x00\x04\x00\x001\x87\x01\b\x00\x00#w\x00\x04\x00\x00?\x97\x01\f\x00\x008@\x01\x11\x00\x00*0\x00\x15\x00\x00FP\x01\x19\x00\x00\x1c \x00\x1d\x00\x00*0" + - "\x01!\x00\x008@\x00\x15LMT\x00MMT\x00MST\x00MDST\x00MSD\x00MSK\x00+05\x00EET\x00EEST\x00\nMSK-3\nPK\x03\x04\n\x00\x00" + - "\x00\x00\x00\xf1c9R\x9f.\xe4xo\x00\x00\x00o\x00\x00\x00\x04\x00\x1c\x00ZuluUT\t\x00\x03\x15\xac\x0e`\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00TZif2" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00UTC\x00\nUTC0\nPK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c" + - "9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xedA\x00\x00\x00\x00Africa/UT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8" + - "\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81A\x00\x00\x00Africa/Nair" + - "obiUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\x0f\x00\x18\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\xa4\x81H\x01\x00\x00Africa/FreetownUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00" + - "\x00\x00\x00\x00\xf1c9R\x9f\x1b\xeb\xdd2\x02\x00\x002\x02\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x13\x02\x00\x00Africa/CeutaUT\x05\x00\x03\x15\xac\x0e`u" + - "x\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x8b\x04\x00\x00" + - "Africa/AsmeraUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xa7\x1d\xb3c\xb4\x00\x00" + - "\x00\xb4\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x91\x05\x00\x00Africa/LuandaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00" + - "PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x14\xcf\x10n\xca\x01\x00\x00\xca\x01\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x8c\x06\x00\x00Africa/JubaUT\x05" + - "\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xcc\fTξ\x00\x00\x00\xbe\x00\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\xa4\x81\x9b\b\x00\x00Africa/JohannesburgUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00" + - "\x00\x00\xf1c9R \x1b\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xa6\t\x00\x00Africa/BujumburaUT\x05\x00\x03\x15\xac\x0e" + - "`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x12tnj\xfc\x04\x00\x00\xfc\x04\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81s\n" + - "\x00\x00Africa/CairoUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RV\xadD\xef\xca\x01" + - "\x00\x00\xca\x01\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xb5\x0f\x00\x00Africa/KhartoumUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8" + - "\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xcc\fTξ\x00\x00\x00\xbe\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xc8\x11\x00\x00Africa/Mbab" + - "aneUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R)\xae\x8eo&\a\x00\x00&\a\x00\x00\x0f\x00\x18\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xce\x12\x00\x00Africa/El_AaiunUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00" + - "\x00\x00\x00\x00\xf1c9R6\x99rU\xa4\x00\x00\x00\xa4\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81=\x1a\x00\x00Africa/MonroviaUT\x05\x00\x03\x15\xac" + - "\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R \x1b\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81*" + - "\x1b\x00\x00Africa/LusakaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xf1\b{\x87" + - "\x82\x00\x00\x00\x82\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xf4\x1b\x00\x00Africa/BamakoUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8" + - "\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xbd\x1c\x00\x00Africa/Niam" + - "eyUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R \x1b\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\r\x00\x18\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\xa4\x81\xb8\x1d\x00\x00Africa/KigaliUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00" + - "\x00\xf1c9R\xca>\xd5\xe0\x95\x00\x00\x00\x95\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x82\x1e\x00\x00Africa/BissauUT\x05\x00\x03\x15\xac\x0e`ux\v" + - "\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81^\x1f\x00\x00Af" + - "rica/KinshasaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xb4\x8d\x98ƿ\x00\x00" + - "\x00\xbf\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81[ \x00\x00Africa/Addis_AbabaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00" + - "\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x93\xf4\x94\v\xc1\x01\x00\x00\xc1\x01\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81f!\x00\x00Africa/Tu" + - "nisUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\r\x00\x18\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\xa4\x81m#\x00\x00Africa/BanjulUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00" + - "\x00\x00\xf1c9R\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x816$\x00\x00Africa/OuagadougouUT\x05\x00\x03\x15" + - "\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81" + - "\x04%\x00\x00Africa/LibrevilleUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9" + - "R\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x03&\x00\x00Africa/BrazzavilleUT\x05\x00\x03\x15\xac\x0e`ux" + - "\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x03'\x00\x00A" + - "frica/BanguiUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xf1\b{\x87\x82\x00\x00\x00" + - "\x82\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xfe'\x00\x00Africa/AbidjanUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00" + - "PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RÊ\x0e\xc0\xd6\x01\x00\x00\xd6\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xc8(\x00\x00Africa/Algiers" + - "UT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\xa4\x81\xe6*\x00\x00Africa/NouakchottUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00" + - "\x00\x00\x00\xf1c9R\xc1\n\x8a\x84\xad\x00\x00\x00\xad\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xb3+\x00\x00Africa/Sao_TomeUT\x05\x00\x03\x15\xac\x0e" + - "`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xa9," + - "\x00\x00Africa/Dar_es_SalaamUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c" + - "9R \x1b\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xb6-\x00\x00Africa/LubumbashiUT\x05\x00\x03\x15\xac\x0e`ux" + - "\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x84.\x00\x00A" + - "frica/KampalaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R \x1b\xb0_\x83\x00\x00" + - "\x00\x83\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x8b/\x00\x00Africa/BlantyreUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03" + - "\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81W0\x00\x00Africa/Malab" + - "oUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xaa\x81\t\x03\xa0\x00\x00\x00\xa0\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\xa4\x81R1\x00\x00Africa/NdjamenaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00" + - "\x00\x00\xf1c9R\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81;2\x00\x00Africa/TimbuktuUT\x05\x00\x03\x15\xac\x0e`" + - "ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R \x1b\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x063\x00" + - "\x00Africa/GaboroneUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rd\x01\x05\x89" + - "\u007f\a\x00\x00\u007f\a\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xd23\x00\x00Africa/CasablancaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03" + - "\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R \x1b\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x9c;\x00\x00Africa/" + - "MaputoUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\f\x00" + - "\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81f<\x00\x00Africa/LagosUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00" + - "\x00\x00\x00\x00\xf1c9R\xcc\fTξ\x00\x00\x00\xbe\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81`=\x00\x00Africa/MaseruUT\x05\x00\x03\x15\xac\x0e`" + - "ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81e>\x00" + - "\x00Africa/Porto-NovoUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xf1\b" + - "{\x87\x82\x00\x00\x00\x82\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81d?\x00\x00Africa/ConakryUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00" + - "\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81.@\x00\x00Africa/D" + - "oualaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\x10\x00\x18" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81)A\x00\x00Africa/MogadishuUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e" + - "\x03\n\x00\x00\x00\x00\x00\xf1c9R\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x812B\x00\x00Africa/DakarUT\x05\x00\x03\x15\xac" + - "\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R_\u007f2[\xaf\x01\x00\x00\xaf\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xfa" + - "B\x00\x00Africa/TripoliUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R \x1b\xb0" + - "_\x83\x00\x00\x00\x83\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xf1D\x00\x00Africa/HarareUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04" + - "\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xbbE\x00\x00Africa/Asm" + - "araUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rm)\xb8P~\x02\x00\x00~\x02\x00\x00\x0f\x00\x18\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xc1F\x00\x00Africa/WindhoekUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00" + - "\x00\x00\x00\x00\xf1c9R\xee\xc4h2\xbc\x02\x00\x00\xbc\x02\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x88I\x00\x00Africa/AccraUT\x05\x00\x03\x15\xac\x0e`u" + - "x\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x8aL\x00\x00" + - "Africa/LomeUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xb4\x8d\x98ƿ\x00\x00\x00\xbf" + - "\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81QM\x00\x00Africa/DjiboutiUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00" + - "PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xedAYN\x00\x00America/UT\x05\x00\x03\x15" + - "\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x82\x13z\xe2\xc2\x00\x00\x00\xc2\x00\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81" + - "\x9bN\x00\x00America/TegucigalpaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1" + - "c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xaaO\x00\x00America/St_KittsUT\x05\x00\x03\x15\xac\x0e`ux" + - "\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81vP\x00\x00A" + - "merica/Puerto_RicoUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xdf\b" + - "\x9c\x9f\xe7\x00\x00\x00\xe7\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81tQ\x00\x00America/BarbadosUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8" + - "\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x14\xc1r8\xe0\x00\x00\x00\xe0\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xa5R\x00\x00Americ" + - "a/AtikokanUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00" + - "\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xcfS\x00\x00America/DominicaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00" + - "PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xac\x8a\x83S\xd4\x00\x00\x00\xd4\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x9bT\x00\x00America/Guatem" + - "alaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x1e+}\x15\xb4\x02\x00\x00\xb4\x02\x00\x00\x14\x00\x18\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xbaU\x00\x00America/Rankin_InletUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01" + - "\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xbcX\x00\x00America/TortolaUT" + - "\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R<\xb9\x18\x87\xe4\x02\x00\x00\xe4\x02\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\xa4\x81\x87Y\x00\x00America/IqaluitUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1" + - "c9R\xd7\b\\\xc6&\x02\x00\x00&\x02\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xb4\\\x00\x00America/MiquelonUT\x05\x00\x03\x15\xac\x0e`ux" + - "\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xb4\x11Z\xde\xe4\x01\x00\x00\xe4\x01\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81$_\x00\x00A" + - "merica/FortalezaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xd6\xfe\xf3%" + - "\xb4\x02\x00\x00\xb4\x02\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81Sa\x00\x00America/ResoluteUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00" + - "\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81Qd\x00\x00America/" + - "St_ThomasUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xbf\x03u\xf3\xe4\x01\x00\x00\xe4\x01\x00" + - "\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x1ee\x00\x00America/RecifeUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01" + - "\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x19vv\xa0\x97\x00\x00\x00\x97\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81Jg\x00\x00America/CuracaoUT" + - "\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xa7\x17jҲ\x00\x00\x00\xb2\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\xa4\x81*h\x00\x00America/MartiniqueUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00" + - "\x00\x00\xf1c9R?\xc9\x1c\xd4\xc6\x03\x00\x00\xc6\x03\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81(i\x00\x00America/JuneauUT\x05\x00\x03\x15\xac\x0e`u" + - "x\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R.\xbe\x1a>\xe7\x03\x00\x00\xe7\x03\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x816m\x00\x00" + - "America/BoiseUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xaaʂA\xcd\x00\x00" + - "\x00\xcd\x00\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81dq\x00\x00America/Blanc-SablonUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03" + - "\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\u007f$*\xa0\xa6\x03\x00\x00\xa6\x03\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\u007fr\x00\x00America" + - "/CuiabaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xf7\xe9 y\xbd\x02\x00\x00\xbd\x02\x00\x00\x0e" + - "\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81mv\x00\x00America/InuvikUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e" + - "\x03\n\x00\x00\x00\x00\x00\xf1c9RU!\x12f\xd9\x02\x00\x00\xd9\x02\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81ry\x00\x00America/Yellowknife" + - "UT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00" + - "\x00\x00\x10\x00\xedA\x98|\x00\x00America/Indiana/UT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00" + - "\x00\x00\xf1c9R$ \x873\xf8\x03\x00\x00\xf8\x03\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xe2|\x00\x00America/Indiana/KnoxUT\x05\x00" + - "\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x01\xd8N\x8c\xab\x02\x00\x00\xab\x02\x00\x00\x1a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\xa4\x81(\x81\x00\x00America/Indiana/PetersburgUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02" + - "\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rp\xb6{\xc9\x13\x02\x00\x00\x13\x02\x00\x00\x1c\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81'\x84\x00\x00America/Indiana/In" + - "dianapolisUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RصK\xa6\n\x02\x00\x00\n\x02" + - "\x00\x00\x19\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x90\x86\x00\x00America/Indiana/Tell_CityUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04" + - "\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R \x17\x89}q\x01\x00\x00q\x01\x00\x00\x15\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xed\x88\x00\x00Ameri" + - "ca/Indiana/VevayUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RK-E\xfa" + - "d\x02\x00\x00d\x02\x00\x00\x17\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xad\x8a\x00\x00America/Indiana/WinamacUT\x05\x00\x03\x15\xac\x0e`ux" + - "\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RM/U\x9f7\x02\x00\x007\x02\x00\x00\x17\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81b\x8d\x00\x00A" + - "merica/Indiana/MarengoUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c" + - "9R\r\xedsp.\x02\x00\x00.\x02\x00\x00\x19\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xea\x8f\x00\x00America/Indiana/VincennesUT\x05" + - "\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rc)\xf6)\xb3\x00\x00\x00\xb3\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\xa4\x81k\x92\x00\x00America/BogotaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9" + - "R.\xf9\xc0\x1e\xd5\x05\x00\x00\xd5\x05\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81f\x93\x00\x00America/MonctonUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01" + - "\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x84\x99\x00\x00Amer" + - "ica/MarigotUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R挋\x92\xf6\x01\x00\x00\xf6" + - "\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81O\x9a\x00\x00America/MaceioUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00P" + - "K\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RԾ\xe7#\x95\x00\x00\x00\x95\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x8d\x9c\x00\x00America/PanamaU" + - "T\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xa2\x81\xbfyS\x02\x00\x00S\x02\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\xa4\x81j\x9d\x00\x00America/MetlakatlaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00" + - "\x00\x00\x00\xf1c9R\xfe\xe6\xf5J\x05\x04\x00\x00\x05\x04\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\t\xa0\x00\x00America/DawsonUT\x05\x00\x03\x15\xac\x0e`" + - "ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RR\xc8\xd9\xf6\xc4\x02\x00\x00\xc4\x02\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81V\xa4\x00" + - "\x00America/CatamarcaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rg\xca" + - "g\xe7\x82\x00\x00\x00\x82\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81e\xa7\x00\x00America/AntiguaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03" + - "\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xedA0\xa8\x00\x00America" + - "/Kentucky/UT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xdf\xe5\x8d\xc4\xda\x04\x00\x00\xda\x04" + - "\x00\x00\x1b\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81{\xa8\x00\x00America/Kentucky/LouisvilleUT\x05\x00\x03\x15\xac\x0e`ux\v\x00" + - "\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x03\x1a|J\xcc\x03\x00\x00\xcc\x03\x00\x00\x1b\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xaa\xad\x00\x00Ame" + - "rica/Kentucky/MonticelloUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00" + - "\xf1c9R$\r\x89l\xe4\x01\x00\x00\xe4\x01\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81˱\x00\x00America/OjinagaUT\x05\x00\x03\x15\xac\x0e`ux" + - "\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x19vv\xa0\x97\x00\x00\x00\x97\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xf8\xb3\x00\x00A" + - "merica/ArubaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x81{\xc1\x92\xbc\x03\x00\x00" + - "\xbc\x03\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81ִ\x00\x00America/SitkaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00P" + - "K\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rѱ\x86b\xee\x03\x00\x00\xee\x03\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81ٸ\x00\x00America/NassauU" + - "T\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x9d?\xdfڸ\x03\x00\x00\xb8\x03\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\xa4\x81\x0f\xbd\x00\x00America/Sao_PauloUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00" + - "\x00\x00\xf1c9Rg\xf5K\x89\xa2\x01\x00\x00\xa2\x01\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x12\xc1\x00\x00America/Rio_BrancoUT\x05\x00\x03\x15" + - "\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xb1݂x\xe8\x00\x00\x00\xe8\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81" + - "\x00\xc3\x00\x00America/Costa_RicaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c" + - "9R\x1b\x81-\xa9\x8a\x01\x00\x00\x8a\x01\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x814\xc4\x00\x00America/Porto_VelhoUT\x05\x00\x03\x15\xac\x0e`" + - "ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rp\xb6{\xc9\x13\x02\x00\x00\x13\x02\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\v\xc6\x00" + - "\x00America/IndianapolisUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9" + - "R\xb4T\xbd\xeb5\x02\x00\x005\x02\x00\x00\x16\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81l\xc8\x00\x00America/Port-au-PrinceUT\x05\x00\x03\x15\xac" + - "\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xea$\xc1\xbf\xb0\x00\x00\x00\xb0\x00\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xf1" + - "\xca\x00\x00America/El_SalvadorUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c" + - "9R\xae,\xa44\xc9\x03\x00\x00\xc9\x03\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xee\xcb\x00\x00America/AdakUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8" + - "\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R~\xb2\x0e\x19V\a\x00\x00V\a\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xfd\xcf\x00\x00Americ" + - "a/St_JohnsUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RJtZ\x8c\x01\x03\x00\x00\x01\x03" + - "\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x9d\xd7\x00\x00America/PangnirtungUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8" + - "\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RU\xactA\xb5\x01\x00\x00\xb5\x01\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xeb\xda\x00\x00America/Mat" + - "amorosUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rs\xb0\xeau\xb4\x01\x00\x00\xb4\x01\x00\x00\x10\x00" + - "\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xeb\xdc\x00\x00America/EirunepeUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02" + - "\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RV\x80\x94@\x12\x04\x00\x00\x12\x04\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xe9\xde\x00\x00America/ShiprockUT" + - "\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xe90T\x16\xd1\x01\x00\x00\xd1\x01\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\xa4\x81E\xe3\x00\x00America/GodthabUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1" + - "c9RU\r\xf7\xd3\xc7\x01\x00\x00\xc7\x01\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81_\xe5\x00\x00America/ThuleUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01" + - "\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xe5s\xb3\\'\x01\x00\x00'\x01\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81m\xe7\x00\x00Amer" + - "ica/ManaguaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RM\x94\xc7Kp\x03\x00\x00p" + - "\x03\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xdd\xe8\x00\x00America/Glace_BayUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03" + - "\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R⚵\xfb\x9e\x00\x00\x00\x9e\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x98\xec\x00\x00America/Cres" + - "tonUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RB\xa0=:\x1e\x01\x00\x00\x1e\x01\x00\x00\x12\x00\x18\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\xa4\x81\u007f\xed\x00\x00America/HermosilloUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e" + - "\x03\n\x00\x00\x00\x00\x00\xf1c9R\xd0v\x01\x8a\x01\x04\x00\x00\x01\x04\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xe9\xee\x00\x00America/Santa_Isabe" + - "lUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RP\x0f(\b=\x01\x00\x00=\x01\x00\x00\x15\x00\x18\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\xa4\x818\xf3\x00\x00America/Santo_DomingoUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02" + - "\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xc4\xf4\x00\x00America/St_Vincent" + - "UT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xd6\xe1Հ\x9c\x01\x00\x00\x9c\x01\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\xa4\x81\x92\xf5\x00\x00America/Mexico_CityUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n" + - "\x00\x00\x00\x00\x00\xf1c9R\x15\xc8\xcb\x00\xac\x00\x00\x00\xac\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81{\xf7\x00\x00America/GuyanaUT\x05\x00\x03\x15\xac" + - "\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00\x00\x00\x15\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81o" + - "\xf8\x00\x00America/Port_of_SpainUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00" + - "\xf1c9R>\x14\xe7\x03\x83\x03\x00\x00\x83\x03\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81@\xf9\x00\x00America/DetroitUT\x05\x00\x03\x15\xac\x0e`ux" + - "\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xedA\f\xfd\x00\x00A" + - "merica/Argentina/UT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RR\xc8\xd9" + - "\xf6\xc4\x02\x00\x00\xc4\x02\x00\x00\x1b\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81X\xfd\x00\x00America/Argentina/CatamarcaUT\x05\x00\x03\x15" + - "\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RR\xc8\xd9\xf6\xc4\x02\x00\x00\xc4\x02\x00\x00 \x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81" + - "q\x00\x01\x00America/Argentina/ComodRivadaviaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00" + - "PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x8b}\xb6\x1e\xc4\x02\x00\x00\xc4\x02\x00\x00\x19\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x8f\x03\x01\x00America/Argent" + - "ina/UshuaiaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RŒZ\x8c\xc4\x02\x00\x00\xc4" + - "\x02\x00\x00\x19\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xa6\x06\x01\x00America/Argentina/MendozaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01" + - "\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xe0\xbf\xf5\xe5\xc4\x02\x00\x00\xc4\x02\x00\x00\x1e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xbd\t\x01\x00Amer" + - "ica/Argentina/Buenos_AiresUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00" + - "\x00\x00\xf1c9Rm\aD\x0e\xcd\x02\x00\x00\xcd\x02\x00\x00\x1a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xd9\f\x01\x00America/Argentina/La_Rio" + - "jaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x8ep\xb4c\xc4\x02\x00\x00\xc4\x02\x00\x00\x1e\x00\x18\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\xa4\x81\xfa\x0f\x01\x00America/Argentina/Rio_GallegosUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00" + - "\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RutZ\x1a\xb2\x02\x00\x00\xb2\x02\x00\x00\x17\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x16\x13\x01\x00America/" + - "Argentina/JujuyUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xfcz=\xe1\xcd" + - "\x02\x00\x00\xcd\x02\x00\x00\x1a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x19\x16\x01\x00America/Argentina/San_JuanUT\x05\x00\x03\x15\xac\x0e`" + - "ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x1c\x80\xb9\\\xcd\x02\x00\x00\xcd\x02\x00\x00\x1a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81:\x19\x01" + - "\x00America/Argentina/San_LuisUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00" + - "\x00\x00\x00\xf1c9Rt*\x9b!\xb2\x02\x00\x00\xb2\x02\x00\x00\x17\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81[\x1c\x01\x00America/Argentina/Salta" + - "UT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RY\xd8֭\xd6\x02\x00\x00\xd6\x02\x00\x00\x19\x00\x18\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\xa4\x81^\x1f\x01\x00America/Argentina/TucumanUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00P" + - "K\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xef\xf0R\x8a\xc4\x02\x00\x00\xc4\x02\x00\x00\x19\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x87\"\x01\x00America/Argenti" + - "na/CordobaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xe3\xc9I\xd0U\x03\x00\x00U\x03" + - "\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x9e%\x01\x00America/Grand_TurkUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03" + - "\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R$ \x873\xf8\x03\x00\x00\xf8\x03\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81?)\x01\x00America/Knox" + - "_INUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x8f\x19Ԇ\x12\x02\x00\x00\x12\x02\x00\x00\x16\x00\x18\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x80-\x01\x00America/Bahia_BanderasUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00P" + - "K\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xe2/\x01\x00America/VirginU" + - "T\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xa1'\a\xbd\x97\x00\x00\x00\x97\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\xa4\x81\xac0\x01\x00America/CayenneUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00" + - "\xf1c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x8c1\x01\x00America/MontserratUT\x05\x00\x03\x15\xac\x0e" + - "`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R?_p\x99\x0e\x05\x00\x00\x0e\x05\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81Z2" + - "\x01\x00America/WinnipegUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rg\xca" + - "g\xe7\x82\x00\x00\x00\x82\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xb27\x01\x00America/AnguillaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8" + - "\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RŒZ\x8c\xc4\x02\x00\x00\xc4\x02\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81~8\x01\x00Americ" + - "a/MendozaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x04,2h\x99\x01\x00\x00\x99\x01\x00" + - "\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x8b;\x01\x00America/SantaremUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00P" + - "K\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81n=\x01\x00America/St_Luci" + - "aUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RԾ\xe7#\x95\x00\x00\x00\x95\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\xa4\x81:>\x01\x00America/CaymanUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00" + - "\x00\xf1c9Rp\x1b\xceRC\x03\x00\x00C\x03\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x17?\x01\x00America/NipigonUT\x05\x00\x03\x15\xac\x0e`u" + - "x\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RV\x80\x94@\x12\x04\x00\x00\x12\x04\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xa3B\x01\x00" + - "America/DenverUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R+\x10`ȫ\x02" + - "\x00\x00\xab\x02\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xfdF\x01\x00America/Dawson_CreekUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8" + - "\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xe90T\x16\xd1\x01\x00\x00\xd1\x01\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xf6I\x01\x00Americ" + - "a/NuukUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xf2\x04\xde\xdd\x11\x02\x00\x00\x11\x02\x00\x00\x0e\x00" + - "\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\rL\x01\x00America/CancunUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03" + - "\n\x00\x00\x00\x00\x00\xf1c9Rn\xab\xd5\xf9\xcf\x03\x00\x00\xcf\x03\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81fN\x01\x00America/NomeUT\x05\x00\x03\x15\xac\x0e" + - "`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R,\xdb~\xab\xb2\x03\x00\x00\xb2\x03\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81{R" + - "\x01\x00America/YakutatUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rg\xcag" + - "\xe7\x82\x00\x00\x00\x82\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81vV\x01\x00America/GrenadaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00" + - "\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xef\xf0R\x8a\xc4\x02\x00\x00\xc4\x02\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81AW\x01\x00America/" + - "RosarioUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xac\x8e\xee\x13\xbe\x00\x00\x00\xbe\x00\x00\x00\x0f" + - "\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81NZ\x01\x00America/CaracasUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02" + - "\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Ro_\x00v/\x01\x00\x00/\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81U[\x01\x00America/MeridaUT\x05\x00" + - "\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xe0\xbf\xf5\xe5\xc4\x02\x00\x00\xc4\x02\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\xa4\x81\xcc\\\x01\x00America/Buenos_AiresUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00" + - "\x00\x00\xf1c9R\x1b\vKdC\x03\x00\x00C\x03\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xde_\x01\x00America/Rainy_RiverUT\x05\x00\x03" + - "\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rø\xab\x9b\xf0\x00\x00\x00\xf0\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4" + - "\x81nc\x01\x00America/PhoenixUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R" + - "\xdf\xe5\x8d\xc4\xda\x04\x00\x00\xda\x04\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xa7d\x01\x00America/LouisvilleUT\x05\x00\x03\x15\xac\x0e`ux\v" + - "\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rk^2S\xb9\x04\x00\x00\xb9\x04\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xcdi\x01\x00Am" + - "erica/Punta_ArenasUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rg\xf5" + - "K\x89\xa2\x01\x00\x00\xa2\x01\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xd4n\x01\x00America/Porto_AcreUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01" + - "\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R3\x9aG\xc8\xd0\x06\x00\x00\xd0\x06\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xc2p\x01\x00Amer" + - "ica/New_YorkUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xad`\x12\xe9\xaa\x00\x00\x00" + - "\xaa\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xdcw\x01\x00America/La_PazUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00" + - "PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xb7-2f\xe4\x01\x00\x00\xe4\x01\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xcex\x01\x00America/Noronh" + - "aUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\xa4\x81\xfbz\x01\x00America/GuadeloupeUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n" + - "\x00\x00\x00\x00\x00\xf1c9R\x1e\xfbn۸\x03\x00\x00\xb8\x03\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xc9{\x01\x00America/Campo_GrandeU" + - "T\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R:\x9a1T\xdf\x01\x00\x00\xdf\x01\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\xa4\x81\xcf\u007f\x01\x00America/ScoresbysundUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n" + - "\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xedA\xfc\x81\x01\x00America/North_Dakota/" + - "UT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RH\xeam\xef\xde\x03\x00\x00\xde\x03\x00\x00\x1b\x00\x18\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\xa4\x81K\x82\x01\x00America/North_Dakota/CenterUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00" + - "\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RR\x1b\x8b(\xde\x03\x00\x00\xde\x03\x00\x00\x1e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81~\x86\x01\x00America/North" + - "_Dakota/New_SalemUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xb7.\xb6" + - "*\x13\x04\x00\x00\x13\x04\x00\x00\x1b\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xb4\x8a\x01\x00America/North_Dakota/BeulahUT\x05\x00\x03\x15" + - "\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x1d\xf7\a ,\x06\x00\x00,\x06\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81" + - "\x1c\x8f\x01\x00America/Goose_BayUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9" + - "Rp\xb6{\xc9\x13\x02\x00\x00\x13\x02\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x93\x95\x01\x00America/Fort_WayneUT\x05\x00\x03\x15\xac\x0e`ux" + - "\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R):\x17-\x88\x06\x00\x00\x88\x06\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xf2\x97\x01\x00A" + - "merica/HalifaxUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x1c\xd8\x19\x9dp\x01" + - "\x00\x00p\x01\x00\x00\x15\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81Þ\x01\x00America/Swift_CurrentUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04" + - "\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R[Sp\x90\x02\x05\x00\x00\x02\x05\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x82\xa0\x01\x00Ameri" + - "ca/SantiagoUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R8\xcdZ\x05o\x01\x00\x00o" + - "\x01\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81Υ\x01\x00America/MazatlanUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00" + - "\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rg\xcag\xe7\x82\x00\x00\x00\x82\x00\x00\x00\x15\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x87\xa7\x01\x00America/St_Ba" + - "rthelemyUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x89غ\xee\x15\x04\x00\x00\x15\x04\x00\x00" + - "\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81X\xa8\x01\x00America/BelizeUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02" + - "\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xcd\xc3v\xe3\xb3\x00\x00\x00\xb3\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xb5\xac\x01\x00America/GuayaquilU" + - "T\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xc0\x98\x00\b\xc9\x03\x00\x00\xc9\x03\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\xa4\x81\xb3\xad\x01\x00America/MontevideoUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00" + - "\x00\x00\x00\xf1c9R\xf6\"\x12\xfe\x0e\x05\x00\x00\x0e\x05\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81ȱ\x01\x00America/Los_AngelesUT\x05\x00" + - "\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\a\x1c\x9e\x9a]\x04\x00\x00]\x04\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\xa4\x81#\xb7\x01\x00America/HavanaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R" + - "8O:\xbf\x95\x03\x00\x00\x95\x03\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81Ȼ\x01\x00America/MenomineeUT\x05\x00\x03\x15\xac\x0e`ux\v\x00" + - "\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RutZ\x1a\xb2\x02\x00\x00\xb2\x02\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xa8\xbf\x01\x00Ame" + - "rica/JujuyUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xd0v\x01\x8a\x01\x04\x00\x00\x01\x04" + - "\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xa1\xc2\x01\x00America/TijuanaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00P" + - "K\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R{\a\a\xdc\xca\x03\x00\x00\xca\x03\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xeb\xc6\x01\x00America/Edmonto" + - "nUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xb4\x82s\x1dT\x01\x00\x00T\x01\x00\x00\x11\x00\x18\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\xa4\x81\xff\xca\x01\x00America/ChihuahuaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00" + - "\x00\x00\x00\x00\xf1c9R\x1d`̟\x00\x03\x00\x00\x00\x03\x00\x00\x15\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x9e\xcc\x01\x00America/Cambridge_BayU" + - "T\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xc1Ȇ\x90\x05\x04\x00\x00\x05\x04\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\xa4\x81\xed\xcf\x01\x00America/WhitehorseUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00" + - "\x00\x00\x00\xf1c9R\xf6@\rm\xa8\x05\x00\x00\xa8\x05\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81>\xd4\x01\x00America/Fort_NelsonUT\x05\x00" + - "\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xae,\xa44\xc9\x03\x00\x00\xc9\x03\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\xa4\x813\xda\x01\x00America/AtkaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Ra\xcb" + - "'\xe9\x9c\x01\x00\x00\x9c\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81B\xde\x01\x00America/ManausUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00" + - "\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xf1\xf9\x1dɻ\x00\x00\x00\xbb\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81&\xe0\x01\x00America/" + - "ParamariboUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xfe7\xa1\x87\x1b\x01\x00\x00\x1b\x01" + - "\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81-\xe1\x01\x00America/LimaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02" + - "\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rd\xa9y\x9at\x03\x00\x00t\x03\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x8e\xe2\x01\x00America/AsuncionUT" + - "\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x9bܩ=\xda\x06\x00\x00\xda\x06\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\xa4\x81L\xe6\x01\x00America/ChicagoUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1" + - "c9RMv\xa1\x0f%\x01\x00\x00%\x01\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81o\xed\x01\x00America/MonterreyUT\x05\x00\x03\x15\xac\x0e`u" + - "x\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x14\xc1r8\xe0\x00\x00\x00\xe0\x00\x00\x00\x15\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xdf\xee\x01\x00" + - "America/Coral_HarbourUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9" + - "R錴$q\x03\x00\x00q\x03\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x0e\xf0\x01\x00America/Thunder_BayUT\x05\x00\x03\x15\xac\x0e`u" + - "x\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xd0v\x01\x8a\x01\x04\x00\x00\x01\x04\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xcc\xf3\x01\x00" + - "America/EnsenadaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9ROKj\xc7" + - "\xaa\x02\x00\x00\xaa\x02\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x17\xf8\x01\x00America/BahiaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8" + - "\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rӿ\x92\xbc\xb5\x06\x00\x00\xb5\x06\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\b\xfb\x01\x00America/Mon" + - "trealUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R%J\xd5\xebS\x01\x00\x00S\x01\x00\x00\x0f\x00\x18" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\a\x02\x02\x00America/JamaicaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03" + - "\n\x00\x00\x00\x00\x00\xf1c9R5\x11Q\x06\xd1\x03\x00\x00\xd1\x03\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xa3\x03\x02\x00America/AnchorageUT\x05" + - "\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rk\xc2\rx\xbf\x01\x00\x00\xbf\x01\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\xa4\x81\xbf\a\x02\x00America/DanmarkshavnUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00" + - "\x00\x00\x00\xf1c9R\x19vv\xa0\x97\x00\x00\x00\x97\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xcc\t\x02\x00America/KralendijkUT\x05\x00\x03" + - "\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R<\x01V\rP\x02\x00\x00P\x02\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4" + - "\x81\xaf\n\x02\x00America/AraguainaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c" + - "9R\xef\xf0R\x8a\xc4\x02\x00\x00\xc4\x02\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81J\r\x02\x00America/CordobaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00" + - "\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\u0096dK~\x02\x00\x00~\x02\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81W\x10\x02\x00Ame" + - "rica/ReginaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x85-\xb9\xf8\x8a\x01\x00\x00\x8a" + - "\x01\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x1d\x13\x02\x00America/BelemUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK" + - "\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rӿ\x92\xbc\xb5\x06\x00\x00\xb5\x06\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xee\x14\x02\x00America/TorontoU" + - "T\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RU9#\xbe2\x05\x00\x002\x05\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\xa4\x81\xec\x1b\x02\x00America/VancouverUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00" + - "\x00\x00\xf1c9R\xf8Dz\x97\xae\x01\x00\x00\xae\x01\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81i!\x02\x00America/Boa_VistaUT\x05\x00\x03\x15\xac" + - "\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x19vv\xa0\x97\x00\x00\x00\x97\x00\x00\x00\x15\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81b" + - "#\x02\x00America/Lower_PrincesUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00" + - "\xf1c9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xedAH$\x02\x00Antarctica/UT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04" + - "\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xc2\v\xae\b\x85\x00\x00\x00\x85\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x8d$\x02\x00Antar" + - "ctica/VostokUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x95{\xf3\xa9w\x03\x00\x00" + - "w\x03\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81]%\x02\x00Antarctica/PalmerUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8" + - "\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R:\xc8P7\xb1\x00\x00\x00\xb1\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x1f)\x02\x00Antarctica/" + - "TrollUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rb\xb2\xaf\xf7\x13\x04\x00\x00\x13\x04\x00\x00\x12\x00\x18" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x1a*\x02\x00Antarctica/McMurdoUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01" + - "\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x95\xea\x06\xd3\xc5\x00\x00\x00\xc5\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81y.\x02\x00Antarctica/DavisU" + - "T\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\r\x0e\xf20\x85\x00\x00\x00\x85\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\xa4\x81\x88/\x02\x00Antarctica/SyowaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00" + - "\x00\xf1c9R\xc8\x14\xdcA\x98\x00\x00\x00\x98\x00\x00\x00\x19\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81W0\x02\x00Antarctica/DumontDUrville" + - "UT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xd7N\xab\x8b\x98\x00\x00\x00\x98\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\xa4\x81B1\x02\x00Antarctica/MawsonUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00" + - "\x00\x00\x00\xf1c9RƉ\xf71\x84\x00\x00\x00\x84\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81%2\x02\x00Antarctica/RotheraUT\x05\x00\x03" + - "\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xddzAh\xf3\x00\x00\x00\xf3\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4" + - "\x81\xf52\x02\x00Antarctica/CaseyUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9" + - "R\xb2\x84J]\xd0\x03\x00\x00\xd0\x03\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x8124\x02\x00Antarctica/MacquarieUT\x05\x00\x03\x15\xac\x0e`" + - "ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rb\xb2\xaf\xf7\x13\x04\x00\x00\x13\x04\x00\x00\x15\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81P8\x02" + - "\x00Antarctica/South_PoleUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c" + - "9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xedA\xb2<\x02\x00Arctic/UT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8" + - "\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xa5\x97\aĤ\x02\x00\x00\xa4\x02\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xf3<\x02\x00Arctic/Long" + - "yearbyenUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x05\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xedA\xe4?\x02\x00Asia/UT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1" + - "c9R[u\x99q\xf1\x02\x00\x00\xf1\x02\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81#@\x02\x00Asia/TomskUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03" + - "\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x81z&\x80k\x02\x00\x00k\x02\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81XC\x02\x00Asia/Ch" + - "oibalsanUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rj$\xcd\xf4\x9a\x00\x00\x00\x9a\x00\x00\x00" + - "\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\fF\x02\x00Asia/ThimbuUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n" + - "\x00\x00\x00\x00\x00\xf1c9R\x88\xf6C\x84\x98\x00\x00\x00\x98\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xebF\x02\x00Asia/VientianeUT\x05\x00\x03\x15\xac" + - "\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rʇ{_\xbb\x00\x00\x00\xbb\x00\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xcb" + - "G\x02\x00Asia/YangonUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R6j\\J\xcf\x04" + - "\x00\x00\xcf\x04\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xcbH\x02\x00Asia/HebronUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00P" + - "K\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R*\xe4@\xa9\x89\x01\x00\x00\x89\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xdfM\x02\x00Asia/ChongqingU" + - "T\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R'\xe2\\\xff\x9f\x00\x00\x00\x9f\x00\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\xa4\x81\xb0O\x02\x00Asia/KabulUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xda" + - "v\x19z\x98\x00\x00\x00\x98\x00\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x93P\x02\x00Asia/BahrainUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00" + - "\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xf9l\x03\x12\xf8\x02\x00\x00\xf8\x02\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81qQ\x02\x00Asia/Irku" + - "tskUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RO\xb0\x03\xe9\xe5\x02\x00\x00\xe5\x02\x00\x00\f\x00\x18\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xafT\x02\x00Asia/YakutskUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00" + - "\x00\xf1c9R.>[K\xab\x00\x00\x00\xab\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xdaW\x02\x00Asia/JayapuraUT\x05\x00\x03\x15\xac\x0e`ux\v" + - "\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RE\t\xfa-\a\x03\x00\x00\a\x03\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xccX\x02\x00As" + - "ia/Hong_KongUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RS\xa5\x81e\xf7\x00\x00\x00" + - "\xf7\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x1b\\\x02\x00Asia/PontianakUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00" + - "PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R;\u007fP\x8d\xd4\a\x00\x00\xd4\a\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81Z]\x02\x00Asia/TehranUT\x05" + - "\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rd%\x05\xd8\xe6\x02\x00\x00\xe6\x02\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\xa4\x81se\x02\x00Asia/VladivostokUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1" + - "c9R:\x11\xea\xa2\xe5\x02\x00\x00\xe5\x02\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xa3h\x02\x00Asia/OmskUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00" + - "\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xee\xf0BB\xff\x01\x00\x00\xff\x01\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xcbk\x02\x00Asia/Tai" + - "peiUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R?Y\xaf\x19\xe7\x00\x00\x00\xe7\x00\x00\x00\n\x00\x18\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x0fn\x02\x00Asia/DaccaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1" + - "c9R]S\xbb\x12\xac\x03\x00\x00\xac\x03\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81:o\x02\x00Asia/FamagustaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00" + - "\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xcfׇ\xe1\x85\x00\x00\x00\x85\x00\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81.s\x02\x00Asi" + - "a/RiyadhUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R*\xe4@\xa9\x89\x01\x00\x00\x89\x01\x00\x00" + - "\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xf8s\x02\x00Asia/ChungkingUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02" + - "\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xceG|\xea\x13\x03\x00\x00\x13\x03\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xc9u\x02\x00Asia/AmmanUT\x05\x00\x03\x15\xac\x0e" + - "`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R`\xc9\xd4\\\xbe\x00\x00\x00\xbe\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81 y" + - "\x02\x00Asia/MakassarUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x8bSnT\xa1" + - "\x00\x00\x00\xa1\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81%z\x02\x00Asia/KathmanduUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8" + - "\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R*\xe4@\xa9\x89\x01\x00\x00\x89\x01\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x0e{\x02\x00Asia/Shangh" + - "aiUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xd5ΜGp\x02\x00\x00p\x02\x00\x00\x0e\x00\x18\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\xa4\x81\xde|\x02\x00Asia/QyzylordaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00" + - "\x00\x00\xf1c9R\x17✳2\x04\x00\x002\x04\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x96\u007f\x02\x00Asia/Tel_AvivUT\x05\x00\x03\x15\xac\x0e`ux" + - "\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xb2\xe27Yn\x01\x00\x00n\x01\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x0f\x84\x02\x00A" + - "sia/TashkentUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xcfׇ\xe1\x85\x00\x00\x00" + - "\x85\x00\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81ą\x02\x00Asia/KuwaitUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01" + - "\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RB\x1d\xc6\x1b\x85\x00\x00\x00\x85\x00\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x8e\x86\x02\x00Asia/UrumqiUT\x05\x00\x03\x15" + - "\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Re\x1bb2w\x01\x00\x00w\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81" + - "X\x87\x02\x00Asia/AshkhabadUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xf0\x9c" + - "f>\xd7\x02\x00\x00\xd7\x02\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x17\x89\x02\x00Asia/KamchatkaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00" + - "\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x87\xbd\xedL\xf1\x02\x00\x00\xf1\x02\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x816\x8c\x02\x00Asia/Bar" + - "naulUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x8a\x9a\x90\xf7\xd6\x02\x00\x00\xd6\x02\x00\x00\x11\x00\x18\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81m\x8f\x02\x00Asia/NovokuznetskUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e" + - "\x03\n\x00\x00\x00\x00\x00\xf1c9R0]*\x1bj\x02\x00\x00j\x02\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x8e\x92\x02\x00Asia/BishkekUT\x05\x00\x03\x15\xac" + - "\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xa7f^]@\x01\x00\x00@\x01\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81>" + - "\x95\x02\x00Asia/KuchingUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x84)\r\xbd\xec" + - "\x00\x00\x00\xec\x00\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81Ė\x02\x00Asia/SaigonUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00" + - "PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x06\xaa>\xa8\x00\x01\x00\x00\x00\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xf5\x97\x02\x00Asia/Singapore" + - "UT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R)p\x1cX\xf1\x02\x00\x00\xf1\x02\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\xa4\x81=\x99\x02\x00Asia/NovosibirskUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00" + - "\x00\x00\xf1c9R?\xa7^\xfah\x02\x00\x00h\x02\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81x\x9c\x02\x00Asia/AtyrauUT\x05\x00\x03\x15\xac\x0e`ux\v\x00" + - "\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x88έ\xe2\xbd\x04\x00\x00\xbd\x04\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81%\x9f\x02\x00Asi" + - "a/GazaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RΒ\x1a\x8c\xaa\x00\x00\x00\xaa\x00\x00\x00\t\x00" + - "\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81%\xa4\x02\x00Asia/DiliUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00" + - "\x00\xf1c9R\xab\xcd\xdf\x05\xee\x02\x00\x00\xee\x02\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x12\xa5\x02\x00Asia/ChitaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04" + - "\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xb2\xb9\xf4\xb6R\x02\x00\x00R\x02\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81D\xa8\x02\x00Asia/" + - "Ulan_BatorUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rw\rD\an\x01\x00\x00n\x01" + - "\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81ߪ\x02\x00Asia/SamarkandUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK" + - "\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x03R\xda\xedU\x02\x00\x00U\x02\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x95\xac\x02\x00Asia/NicosiaUT\x05\x00" + - "\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xcfׇ\xe1\x85\x00\x00\x00\x85\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\xa4\x810\xaf\x02\x00Asia/AdenUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R?Y\xaf\x19\xe7" + - "\x00\x00\x00\xe7\x00\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xf8\xaf\x02\x00Asia/DhakaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00P" + - "K\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R)\x15II\xf3\x02\x00\x00\xf3\x02\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81#\xb1\x02\x00Asia/SakhalinUT" + - "\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RT\x81\x18G^\x02\x00\x00^\x02\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\xa4\x81]\xb4\x02\x00Asia/AqtauUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x8a\xc1" + - "\x1eB\xb7\x00\x00\x00\xb7\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xff\xb6\x02\x00Asia/PyongyangUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00" + - "\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x17✳2\x04\x00\x002\x04\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xfe\xb7\x02\x00Asia/Jer" + - "usalemUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R's\x96\x1en\x01\x00\x00n\x01\x00\x00\r\x00" + - "\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81x\xbc\x02\x00Asia/DushanbeUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n" + - "\x00\x00\x00\x00\x00\xf1c9R\\\x91\x87\xbb\xf7\x00\x00\x00\xf7\x00\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81-\xbe\x02\x00Asia/ColomboUT\x05\x00\x03\x15\xac\x0e`" + - "ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R9Y\xb7\xf1\n\x01\x00\x00\n\x01\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81j\xbf\x02" + - "\x00Asia/KarachiUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R恸\x1e\x00\x01\x00" + - "\x00\x00\x01\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xba\xc0\x02\x00Asia/Kuala_LumpurUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04" + - "\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Re\x1bb2w\x01\x00\x00w\x01\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x05\xc2\x02\x00Asia/Ashga" + - "batUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x9a\x1a\xdc\xca\xdc\x00\x00\x00\xdc\x00\x00\x00\f\x00\x18\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xc3\xc3\x02\x00Asia/KolkataUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00" + - "\x00\xf1c9RB\x1d\xc6\x1b\x85\x00\x00\x00\x85\x00\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xe5\xc4\x02\x00Asia/KashgarUT\x05\x00\x03\x15\xac\x0e`ux\v\x00" + - "\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xba\xa3b\xc1R\x02\x00\x00R\x02\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xb0\xc5\x02\x00Asi" + - "a/HovdUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x03\x87\xb3<\xe8\x02\x00\x00\xe8\x02\x00\x00\t\x00" + - "\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81E\xc8\x02\x00Asia/BakuUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00" + - "\x00\xf1c9R\x83g\x95M\a\x03\x00\x00\a\x03\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81p\xcb\x02\x00Asia/KhandygaUT\x05\x00\x03\x15\xac\x0e`ux\v" + - "\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x9a\xea\x18\xd4\xf8\x02\x00\x00\xf8\x02\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xbe\xce\x02\x00As" + - "ia/YekaterinburgUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rʇ{_" + - "\xbb\x00\x00\x00\xbb\x00\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x02\xd2\x02\x00Asia/RangoonUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03" + - "\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rǯ\xdf\x1c\xee\x00\x00\x00\xee\x00\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x03\xd3\x02\x00Asia/ManilaU" + - "T\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x1d?v\f\x17\x03\x00\x00\x17\x03\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\xa4\x816\xd4\x02\x00Asia/MacaoUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RS" + - "\xdd\\2a\x02\x00\x00a\x02\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x91\xd7\x02\x00Asia/AlmatyUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04" + - "\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RѾ\xa8\xc7u\x02\x00\x00u\x02\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x817\xda\x02\x00Asia/Tbili" + - "siUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x88\xf6C\x84\x98\x00\x00\x00\x98\x00\x00\x00\x0f\x00\x18\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\xa4\x81\xf2\xdc\x02\x00Asia/Phnom_PenhUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00" + - "\x00\x00\x00\xf1c9R\x1d?v\f\x17\x03\x00\x00\x17\x03\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xd3\xdd\x02\x00Asia/MacauUT\x05\x00\x03\x15\xac\x0e`ux\v\x00" + - "\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xe4_P\x18\xef\x02\x00\x00\xef\x02\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81.\xe1\x02\x00Asi" + - "a/MagadanUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xdav\x19z\x98\x00\x00\x00\x98\x00\x00" + - "\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81c\xe4\x02\x00Asia/QatarUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n" + - "\x00\x00\x00\x00\x00\xf1c9R\x9a\x1a\xdc\xca\xdc\x00\x00\x00\xdc\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81?\xe5\x02\x00Asia/CalcuttaUT\x05\x00\x03\x15\xac\x0e" + - "`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xb2\xb9\xf4\xb6R\x02\x00\x00R\x02\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81b\xe6" + - "\x02\x00Asia/UlaanbaatarUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xa4Z" + - "ߐ\xe6\x02\x00\x00\xe6\x02\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xfe\xe8\x02\x00Asia/SrednekolymskUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01" + - "\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xdb\xfa\xb5\xbeg\x02\x00\x00g\x02\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x810\xec\x02\x00Asia" + - "/AqtobeUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rw\x86\x8d^\x03\x03\x00\x00\x03\x03\x00\x00\r" + - "\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xdc\xee\x02\x00Asia/Ust-NeraUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03" + - "\n\x00\x00\x00\x00\x00\xf1c9RL\xe0\x91y\xe5\x02\x00\x00\xe5\x02\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81&\xf2\x02\x00Asia/KrasnoyarskUT\x05\x00" + - "\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xc7X,Y\x9f\x01\x00\x00\x9f\x01\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\xa4\x81U\xf5\x02\x00Asia/SeoulUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Ry\x19\xe0N" + - "\x9a\x00\x00\x00\x9a\x00\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x818\xf7\x02\x00Asia/BruneiUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00" + - "\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xd7e&uv\x02\x00\x00v\x02\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x17\xf8\x02\x00Asia/BaghdadU" + - "T\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R`\xc9\xd4\\\xbe\x00\x00\x00\xbe\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\xa4\x81\xd3\xfa\x02\x00Asia/Ujung_PandangUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00" + - "\x00\x00\x00\xf1c9RV\xe0\xe7!\xe7\x02\x00\x00\xe7\x02\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xdd\xfb\x02\x00Asia/AnadyrUT\x05\x00\x03\x15\xac\x0e`ux\v" + - "\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xed\x8c\xf1\x91\x85\x00\x00\x00\x85\x00\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\t\xff\x02\x00As" + - "ia/MuscatUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x84)\r\xbd\xec\x00\x00\x00\xec\x00\x00" + - "\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xd3\xff\x02\x00Asia/Ho_Chi_MinhUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00P" + - "K\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xef\\\xf4q\x17\x04\x00\x00\x17\x04\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\t\x01\x03\x00Asia/DamascusUT" + - "\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rj$\xcd\xf4\x9a\x00\x00\x00\x9a\x00\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\xa4\x81g\x05\x03\x00Asia/ThimphuUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R" + - "\x88\xf6C\x84\x98\x00\x00\x00\x98\x00\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81G\x06\x03\x00Asia/BangkokUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00" + - "\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x02\x95-\xad\xc4\x02\x00\x00\xc4\x02\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81%\a\x03\x00Asia/Yer" + - "evanUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x8bSnT\xa1\x00\x00\x00\xa1\x00\x00\x00\r\x00\x18\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81/\n\x03\x00Asia/KatmanduUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00" + - "\x00\x00\x00\xf1c9R&\xe9\xd1\xd8q\x02\x00\x00q\x02\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x17\v\x03\x00Asia/OralUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01" + - "\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x02\xf4\xaeg\xd5\x00\x00\x00\xd5\x00\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xcb\r\x03\x00Asia" + - "/TokyoUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\aW\x10Ѱ\x04\x00\x00\xb0\x04\x00\x00\r\x00" + - "\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xe4\x0e\x03\x00Asia/IstanbulUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n" + - "\x00\x00\x00\x00\x00\xf1c9R\xc7\x11\xe1[\xdc\x02\x00\x00\xdc\x02\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xdb\x13\x03\x00Asia/BeirutUT\x05\x00\x03\x15\xac\x0e`u" + - "x\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rb\xadű\xf8\x00\x00\x00\xf8\x00\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xfc\x16\x03\x00" + - "Asia/JakartaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xed\x8c\xf1\x91\x85\x00\x00\x00" + - "\x85\x00\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81:\x18\x03\x00Asia/DubaiUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02" + - "\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xa1\xfax\x98g\x02\x00\x00g\x02\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x03\x19\x03\x00Asia/QostanayUT\x05\x00\x03" + - "\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R*\xe4@\xa9\x89\x01\x00\x00\x89\x01\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4" + - "\x81\xb1\x1b\x03\x00Asia/HarbinUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xedA\u007f\x1d\x03\x00Atlantic/UT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00P" + - "K\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\u0097N\xad\xaf\x00\x00\x00\xaf\x00\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xc2\x1d\x03\x00Atlantic/Cape_V" + - "erdeUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xe7\xcf^\xb0\x15\x03\x00\x00\x15\x03\x00\x00\x10\x00\x18\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xbe\x1e\x03\x00Atlantic/StanleyUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03" + - "\n\x00\x00\x00\x00\x00\xf1c9R\x82\xfa Z\x9b\x05\x00\x00\x9b\x05\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x1d\"\x03\x00Atlantic/MadeiraUT\x05\x00" + - "\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rl&\x04\x99\x00\x04\x00\x00\x00\x04\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\xa4\x81\x02(\x03\x00Atlantic/BermudaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c" + - "9R\xaf|7\xb3\xde\x01\x00\x00\xde\x01\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81L,\x03\x00Atlantic/CanaryUT\x05\x00\x03\x15\xac\x0e`ux\v\x00" + - "\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xb7\x0e\xbdm\xb9\x01\x00\x00\xb9\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81s.\x03\x00Atl" + - "antic/FaroeUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rm\xbd\x10k\xf1\x02\x00\x00\xf1" + - "\x02\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81t0\x03\x00Atlantic/ReykjavikUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8" + - "\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xa5\x97\aĤ\x02\x00\x00\xa4\x02\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xb13\x03\x00Atlantic/Ja" + - "n_MayenUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\x12" + - "\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xa16\x03\x00Atlantic/St_HelenaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00P" + - "K\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x0f-\xadׄ\x00\x00\x00\x84\x00\x00\x00\x16\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81o7\x03\x00Atlantic/South_" + - "GeorgiaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xb7\x0e\xbdm\xb9\x01\x00\x00\xb9\x01\x00\x00\x0f" + - "\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81C8\x03\x00Atlantic/FaeroeUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02" + - "\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RW\x99\x9d\v\x9b\x05\x00\x00\x9b\x05\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81E:\x03\x00Atlantic/AzoresUT\x05" + - "\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10" + - "\x00\xedA)@\x03\x00Australia/UT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RX\xb9\x9a" + - "p\x88\x03\x00\x00\x88\x03\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81m@\x03\x00Australia/NSWUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04" + - "\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x8ff~ՙ\x03\x00\x00\x99\x03\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xfe垛\x03\x00\x00\x9b\x03\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81" + - "?\xbe\x04\x00Europe/WarsawUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rk\xa4," + - "\xb6?\x06\x00\x00?\x06\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81!\xc2\x04\x00Europe/LondonUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04" + - "\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rn\x81\xf4\xd7Z\x04\x00\x00Z\x04\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xa7\xc8\x04\x00Europe/Mon" + - "acoUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xa5\x97\aĤ\x02\x00\x00\xa4\x02\x00\x00\v\x00\x18\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\xa4\x81H\xcd\x04\x00Europe/OsloUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00" + - "\xf1c9R\xe1C\xf9\xa1\xde\x01\x00\x00\xde\x01\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x811\xd0\x04\x00Europe/PodgoricaUT\x05\x00\x03\x15\xac\x0e`u" + - "x\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\aW\x10Ѱ\x04\x00\x00\xb0\x04\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81Y\xd2\x04\x00" + - "Europe/IstanbulUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xab\x80c$q" + - "\x00\x00\x00q\x00\x00\x00\a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81R\xd7\x04\x00FactoryUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02" + - "\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rk\xa4,\xb6?\x06\x00\x00?\x06\x00\x00\x02\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x04\xd8\x04\x00GBUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8" + - "\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rk\xa4,\xb6?\x06\x00\x00?\x06\x00\x00\a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\u007f\xde\x04\x00GB-Eir" + - "eUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RP\xda\xfa\x03o\x00\x00\x00o\x00\x00\x00\x03\x00\x18\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\xa4\x81\xff\xe4\x04\x00GMTUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RP\xda\xfa\x03o\x00" + - "\x00\x00o\x00\x00\x00\x05\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xab\xe5\x04\x00GMT+0UT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n" + - "\x00\x00\x00\x00\x00\xf1c9RP\xda\xfa\x03o\x00\x00\x00o\x00\x00\x00\x05\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81Y\xe6\x04\x00GMT-0UT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8" + - "\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RP\xda\xfa\x03o\x00\x00\x00o\x00\x00\x00\x04\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\a\xe7\x04\x00GMT0UT" + - "\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RP\xda\xfa\x03o\x00\x00\x00o\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\xa4\x81\xb4\xe7\x04\x00GreenwichUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RE\t\xfa" + - "-\a\x03\x00\x00\a\x03\x00\x00\b\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81f\xe8\x04\x00HongkongUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00P" + - "K\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R=\xf7\xfawp\x00\x00\x00p\x00\x00\x00\x03\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xaf\xeb\x04\x00HSTUT\x05\x00\x03\x15\xac\x0e`ux\v" + - "\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rm\xbd\x10k\xf1\x02\x00\x00\xf1\x02\x00\x00\a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\\\xec\x04\x00Ic" + - "elandUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x18" + - "\x00\x00\x00\x00\x00\x00\x00\x10\x00\xedA\x8e\xef\x04\x00Indian/UT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c" + - "9R\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xcf\xef\x04\x00Indian/MayotteUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01" + - "\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xb8K\xabυ\x00\x00\x00\x85\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xd6\xf0\x04\x00Indi" + - "an/KerguelenUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xb9\xb2Z\xac\x98\x00\x00\x00" + - "\x98\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xa5\xf1\x04\x00Indian/MaldivesUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00" + - "\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Ry(\xb6\x8f\x85\x00\x00\x00\x85\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x86\xf2\x04\x00Indian/Reunio" + - "nUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x96\xed=\x98\xb3\x00\x00\x00\xb3\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\xa4\x81S\xf3\x04\x00Indian/MauritiusUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00" + - "\x00\x00\x00\xf1c9R\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81P\xf4\x04\x00Indian/AntananarivoUT\x05\x00" + - "\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Ra\x85jo\x85\x00\x00\x00\x85\x00\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\xa4\x81\\\xf5\x04\x00Indian/MaheUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xb4\x8d\x98" + - "ƿ\x00\x00\x00\xbf\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81&\xf6\x04\x00Indian/ComoroUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04" + - "\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R$l=҅\x00\x00\x00\x85\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81,\xf7\x04\x00Indian/Chr" + - "istmasUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rx\xb0W\x14\x98\x00\x00\x00\x98\x00\x00\x00\r\x00" + - "\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xfb\xf7\x04\x00Indian/ChagosUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n" + - "\x00\x00\x00\x00\x00\xf1c9RͲ\xfb\xf6\x8c\x00\x00\x00\x8c\x00\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xda\xf8\x04\x00Indian/CocosUT\x05\x00\x03\x15\xac\x0e`" + - "ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R;\u007fP\x8d\xd4\a\x00\x00\xd4\a\x00\x00\x04\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xac\xf9\x04" + - "\x00IranUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x17✳2\x04\x00\x002\x04\x00\x00\x06\x00\x18" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xbe\x01\x05\x00IsraelUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9" + - "R%J\xd5\xebS\x01\x00\x00S\x01\x00\x00\a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x810\x06\x05\x00JamaicaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03" + - "\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x02\xf4\xaeg\xd5\x00\x00\x00\xd5\x00\x00\x00\x05\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xc4\a\x05\x00JapanUT\x05\x00\x03\x15\xac" + - "\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xf6\xe8]*\xdb\x00\x00\x00\xdb\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xd8" + - "\b\x05\x00KwajaleinUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R_\u007f2[\xaf\x01\x00\x00" + - "\xaf\x01\x00\x00\x05\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xf6\t\x05\x00LibyaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00" + - "\x00\x00\x00\xf1c9R\xfe\x9d\x1b\xc9m\x02\x00\x00m\x02\x00\x00\x03\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xe4\v\x05\x00METUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04" + - "\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xedA\x8e\x0e\x05\x00Mexico/UT\x05" + - "\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xd6\xe1Հ\x9c\x01\x00\x00\x9c\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\xa4\x81\xcf\x0e\x05\x00Mexico/GeneralUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9" + - "R\xd0v\x01\x8a\x01\x04\x00\x00\x01\x04\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xb3\x10\x05\x00Mexico/BajaNorteUT\x05\x00\x03\x15\xac\x0e`ux\v\x00" + - "\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R8\xcdZ\x05o\x01\x00\x00o\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xfe\x14\x05\x00Mex" + - "ico/BajaSurUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xf5\x8d\x99\x92o\x00\x00\x00o" + - "\x00\x00\x00\x03\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xb5\x16\x05\x00MSTUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00" + - "\xf1c9R\xe6h\xcac\xb7\x03\x00\x00\xb7\x03\x00\x00\a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81a\x17\x05\x00MST7MDTUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00" + - "\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RV\x80\x94@\x12\x04\x00\x00\x12\x04\x00\x00\x06\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81Y\x1b\x05\x00NavajoUT\x05" + - "\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rb\xb2\xaf\xf7\x13\x04\x00\x00\x13\x04\x00\x00\x02\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\xa4\x81\xab\x1f\x05\x00NZUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x96\xc5FF(\x03\x00\x00(\x03\x00" + - "\x00\a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xfa#\x05\x00NZ-CHATUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00" + - "\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xedAc'\x05\x00Pacific/UT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8" + - "\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xee\xd0\x1cYN\x04\x00\x00N\x04\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xa5'\x05\x00Pacifi" + - "c/EasterUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xfa\x0fA\x05\x99\x00\x00\x00\x99\x00\x00\x00" + - "\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81;,\x05\x00Pacific/PitcairnUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK" + - "\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R3\x03\x1f\f\xac\x00\x00\x00\xac\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x1e-\x05\x00Pacific/Enderbur" + - "yUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Ra\vೆ\x00\x00\x00\x86\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00" + - "\x00\x00\x00\x00\x00\xa4\x81\x15.\x05\x00Pacific/FunafutiUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00" + - "\x00\x00\x00\xf1c9R\u07b54-\xd6\x00\x00\x00\xd6\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xe5.\x05\x00Pacific/PonapeUT\x05\x00\x03\x15\xac\x0e`" + - "ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xb7\xef\x97\xc6\xc6\x00\x00\x00\xc6\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x030\x05" + - "\x00Pacific/NoumeaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x80\xf8vܔ" + - "\x00\x00\x00\x94\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x111\x05\x00Pacific/PalauUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03" + - "\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xeaK\x85v\xdd\x00\x00\x00\xdd\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xec1\x05\x00Pacific/John" + - "stonUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xca\"\xb8i\xda\x00\x00\x00\xda\x00\x00\x00\x0e\x00\x18\x00" + - "\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x133\x05\x00Pacific/MajuroUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00" + - "\x00\x00\x00\x00\xf1c9Rt\xca{e\x92\x00\x00\x00\x92\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x8154\x05\x00Pacific/Pago_PagoUT\x05\x00\x03" + - "\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x9e\u007f\xab\x95V\x01\x00\x00V\x01\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4" + - "\x81\x125\x05\x00Pacific/EfateUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xc8=" + - "ku\xae\x00\x00\x00\xae\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xaf6\x05\x00Pacific/KiritimatiUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01" + - "\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x8a|\xdcU\x99\x00\x00\x00\x99\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xa97\x05\x00Paci" + - "fic/FakaofoUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x96\xc5FF(\x03\x00\x00(" + - "\x03\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x8b8\x05\x00Pacific/ChathamUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00" + - "PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xf6\xe8]*\xdb\x00\x00\x00\xdb\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xfc;\x05\x00Pacific/Kwajal" + - "einUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rt\xca{e\x92\x00\x00\x00\x92\x00\x00\x00\x0e\x00\x18\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\xa4\x81\"=\x05\x00Pacific/MidwayUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00" + - "\x00\x00\x00\xf1c9R1\xce_(\x86\x00\x00\x00\x86\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xfc=\x05\x00Pacific/WallisUT\x05\x00\x03\x15\xac\x0e`" + - "ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R4\xd0Yӣ\x01\x00\x00\xa3\x01\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xca>\x05" + - "\x00Pacific/FijiUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xe9\xdd\x1e\xee\f\x01\x00" + - "\x00\f\x01\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xb3@\x05\x00Pacific/ApiaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00P" + - "K\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xcc\xf39a\xc3\x00\x00\x00\xc3\x00\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x05B\x05\x00Pacific/YapUT\x05\x00" + - "\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rn\x04\x19y\x9a\x00\x00\x00\x9a\x00\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\xa4\x81\rC\x05\x00Pacific/Port_MoresbyUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00" + - "\x00\x00\xf1c9R\xeaK\x85v\xdd\x00\x00\x00\xdd\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xf5C\x05\x00Pacific/HonoluluUT\x05\x00\x03\x15\xac\x0e" + - "`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\u07b54-\xd6\x00\x00\x00\xd6\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x1cE" + - "\x05\x00Pacific/PohnpeiUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xc23\xa0" + - "\xbc\x84\x00\x00\x00\x84\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81;F\x05\x00Pacific/GambierUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00" + - "\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xe2;Z\xf7\xb7\x00\x00\x00\xb7\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\bG\x05\x00Pacific/" + - "NauruUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x97n7\x1a\xf2\x00\x00\x00\xf2\x00\x00\x00\x0e\x00\x18" + - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x06H\x05\x00Pacific/KosraeUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n" + - "\x00\x00\x00\x00\x00\xf1c9R\x85v\xf8\x8c\x87\x01\x00\x00\x87\x01\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81@I\x05\x00Pacific/RarotongaUT\x05\x00" + - "\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RD6\x83\xa1\x8b\x00\x00\x00\x8b\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\xa4\x81\x12K\x05\x00Pacific/MarquesasUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1" + - "c9R6\xb7S{\x86\x00\x00\x00\x86\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xe8K\x05\x00Pacific/TarawaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00" + - "\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xcc\xf39a\xc3\x00\x00\x00\xc3\x00\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xb6L\x05\x00Pac" + - "ific/TrukUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x81\xeb\xb8m\xaf\x00\x00\x00\xaf\x00\x00" + - "\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xbfM\x05\x00Pacific/NiueUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e" + - "\x03\n\x00\x00\x00\x00\x00\xf1c9Rt\xca{e\x92\x00\x00\x00\x92\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xb4N\x05\x00Pacific/SamoaUT\x05\x00\x03\x15" + - "\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RFI\xfe\x14^\x01\x00\x00^\x01\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81" + - "\x8dO\x05\x00Pacific/GuamUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RFI\xfe\x14" + - "^\x01\x00\x00^\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x811Q\x05\x00Pacific/SaipanUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04" + - "\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x81\xe3w\n\xaf\x00\x00\x00\xaf\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xd7R\x05\x00Pacific/Ga" + - "lapagosUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x9a\xf2:F\xc9\x00\x00\x00\xc9\x00\x00\x00\x14" + - "\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xd1S\x05\x00Pacific/BougainvilleUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00" + - "\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R߃\xa0_\x86\x00\x00\x00\x86\x00\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xe8T\x05\x00Pacific/WakeU" + - "T\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RP:\xc0\x8c\xed\x00\x00\x00\xed\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x00\xa4\x81\xb4U\x05\x00Pacific/TongatapuUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00" + - "\x00\x00\xf1c9R\xcc\xf39a\xc3\x00\x00\x00\xc3\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xecV\x05\x00Pacific/ChuukUT\x05\x00\x03\x15\xac\x0e`ux" + - "\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xea\xc1\xdaυ\x00\x00\x00\x85\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xf6W\x05\x00P" + - "acific/TahitiUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RY\xd2K|\x86\x00\x00" + - "\x00\x86\x00\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xc3X\x05\x00Pacific/GuadalcanalUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00" + - "\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rb\xb2\xaf\xf7\x13\x04\x00\x00\x13\x04\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x96Y\x05\x00Pacific/" + - "AucklandUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RY5\x1a6\xf7\x00\x00\x00\xf7\x00\x00\x00" + - "\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xf3]\x05\x00Pacific/NorfolkUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01" + - "\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R>\xfe垛\x03\x00\x00\x9b\x03\x00\x00\x06\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x813_\x05\x00PolandUT\x05\x00\x03\x15\xac\x0e`ux" + - "\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xfa\xd5\xd6М\x05\x00\x00\x9c\x05\x00\x00\b\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x0ec\x05\x00P" + - "ortugalUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R*\xe4@\xa9\x89\x01\x00\x00\x89\x01\x00\x00\x03" + - "\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xech\x05\x00PRCUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R" + - "ŭV\xad\xb7\x03\x00\x00\xb7\x03\x00\x00\a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xb2j\x05\x00PST8PDTUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00" + - "\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xee\xf0BB\xff\x01\x00\x00\xff\x01\x00\x00\x03\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xaan\x05\x00ROCUT\x05\x00\x03\x15\xac\x0e`u" + - "x\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xc7X,Y\x9f\x01\x00\x00\x9f\x01\x00\x00\x03\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xe6p\x05\x00" + - "ROKUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x06\xaa>\xa8\x00\x01\x00\x00\x00\x01\x00\x00\t\x00\x18\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xc2r\x05\x00SingaporeUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c" + - "9R\aW\x10Ѱ\x04\x00\x00\xb0\x04\x00\x00\x06\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x05t\x05\x00TurkeyUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03" + - "\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x9f.\xe4xo\x00\x00\x00o\x00\x00\x00\x03\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xf5x\x05\x00UCTUT\x05\x00\x03\x15\xac\x0e`" + - "ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x9f.\xe4xo\x00\x00\x00o\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xa1y\x05" + - "\x00UniversalUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + - "\x00\x00\x03\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xedASz\x05\x00US/UT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1" + - "c9R\xf6\"\x12\xfe\x0e\x05\x00\x00\x0e\x05\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x90z\x05\x00US/PacificUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03" + - "\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x9bܩ=\xda\x06\x00\x00\xda\x06\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xe2\u007f\x05\x00US/Cent" + - "ralUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R>\x14\xe7\x03\x83\x03\x00\x00\x83\x03\x00\x00\v\x00\x18\x00\x00" + - "\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x87\x05\x00US/MichiganUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00" + - "\xf1c9R\xae,\xa44\xc9\x03\x00\x00\xc9\x03\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81Ȋ\x05\x00US/AleutianUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04" + - "\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R$ \x873\xf8\x03\x00\x00\xf8\x03\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81֎\x05\x00US/In" + - "diana-StarkeUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9RV\x80\x94@\x12\x04\x00\x00" + - "\x12\x04\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x19\x93\x05\x00US/MountainUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01" + - "\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rø\xab\x9b\xf0\x00\x00\x00\xf0\x00\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81p\x97\x05\x00US/ArizonaUT\x05\x00\x03\x15\xac" + - "\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R3\x9aG\xc8\xd0\x06\x00\x00\xd0\x06\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xa4" + - "\x98\x05\x00US/EasternUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R5\x11Q\x06\xd1\x03\x00" + - "\x00\xd1\x03\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xb8\x9f\x05\x00US/AlaskaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02" + - "\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rt\xca{e\x92\x00\x00\x00\x92\x00\x00\x00\b\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81̣\x05\x00US/SamoaUT\x05\x00\x03\x15\xac\x0e`u" + - "x\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9Rp\xb6{\xc9\x13\x02\x00\x00\x13\x02\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xa0\xa4\x05\x00" + - "US/East-IndianaUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xeaK\x85v\xdd" + - "\x00\x00\x00\xdd\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xfc\xa6\x05\x00US/HawaiiUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK" + - "\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x9f.\xe4xo\x00\x00\x00o\x00\x00\x00\x03\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x1c\xa8\x05\x00UTCUT\x05\x00\x03\x15\xac\x0e`ux\v\x00" + - "\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R2\x91B\xc0\xee\x01\x00\x00\xee\x01\x00\x00\x03\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81Ȩ\x05\x00WET" + - "UT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\xe1\xc1\xeb\x05\x8c\x03\x00\x00\x8c\x03\x00\x00\x04\x00\x18\x00\x00\x00\x00\x00" + - "\x00\x00\x00\x00\xa4\x81\xf3\xaa\x05\x00W-SUUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xf1c9R\x9f.\xe4xo\x00" + - "\x00\x00o\x00\x00\x00\x04\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xbd\xae\x05\x00ZuluUT\x05\x00\x03\x15\xac\x0e`ux\v\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00PK\x05\x06\x00\x00\x00\x00" + - "f\x02f\x02\x96\xc9\x00\x00j\xaf\x05\x00\x00\x00" + "\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\xff\xff\xad\xd4\x00\x00\xff\xff\xb9\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff" + + "\xb9\xb0\x00\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x01\x14LMT\x00CDT\x00CST\x00EST\x00CWT\x00CPT\x00\nCST6CDT,M3.2.0,M11." + + "1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS$ \x873\xf8\x03\x00\x00\xf8\x03\x00\x00\x11\x00\x1c\x00US/Indiana-StarkeUT\t\x00\x03\x82\x0f\x8ba" + + "\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00" + + "\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00]\x00\x00\x00\x06\x00\x00\x00\x18\xff\xff\xff\xff^\x03" + + "\xfe\xa0\xff\xff\xff\xff\x9e\xa6,\x80\xff\xff\xff\xff\x9f\xba\xf9p\xff\xff\xff\xff\xa0\x86\x0e\x80\xff\xff\xff\xff\xa1\x9a\xdbp\xff\xff\xff\xffˈ\xfe\x80\xff\xff\xff\xff\xd2#\xf4p\xff\xff\xff\xff\xd2a\t\xf0\xff\xff" + + "\xff\xff\xd5U\xd5\x00\xff\xff\xff\xff\xd6 \xcd\xf0\xff\xff\xff\xff\xd75\xb7\x00\xff\xff\xff\xff\xd8\x00\xaf\xf0\xff\xff\xff\xff\xd9\x15\x99\x00\xff\xff\xff\xff\xd9\xe0\x91\xf0\xff\xff\xff\xff\xda\xfe\xb5\x80\xff\xff\xff\xff\xdb\xc0" + + "s\xf0\xff\xff\xff\xff\xdcޗ\x80\xff\xff\xff\xffݩ\x90p\xff\xff\xff\xff\u07bey\x80\xff\xff\xff\xff߉rp\xff\xff\xff\xff\xe0\x9e[\x80\xff\xff\xff\xff\xe1iTp\xff\xff\xff\xff\xe2~=\x80\xff\xff" + + "\xff\xff\xe3I6p\xff\xff\xff\xff\xe4^\x1f\x80\xff\xff\xff\xff\xe5W<\xf0\xff\xff\xff\xff\xe6G<\x00\xff\xff\xff\xff\xe77\x1e\xf0\xff\xff\xff\xff\xe8'\x1e\x00\xff\xff\xff\xff\xe8\xf2\x16\xf0\xff\xff\xff\xff\xea\a" + + "\x00\x00\xff\xff\xff\xff\xea\xd1\xf8\xf0\xff\xff\xff\xff\xeb\xe6\xe2\x00\xff\xff\xff\xff\xec\xd6\xc4\xf0\xff\xff\xff\xff\xed\xc6\xc4\x00\xff\xff\xff\xff\xee\xbf\xe1p\xff\xff\xff\xff\xef\xaf\xe0\x80\xff\xff\xff\xff\xf0\x9f\xc3p\xff\xff" + + "\xff\xff\xf1\x8f\u0080\xff\xff\xff\xff\xf4_\x87p\xff\xff\xff\xff\xfa\xf8g\x00\xff\xff\xff\xff\xfb\xe8I\xf0\xff\xff\xff\xff\xfc\xd8I\x00\xff\xff\xff\xff\xfd\xc8+\xf0\xff\xff\xff\xff\xfe\xb8+\x00\xff\xff\xff\xff\xff\xa8" + + "\r\xf0\x00\x00\x00\x00\x00\x98\r\x00\x00\x00\x00\x00\x01\x87\xef\xf0\x00\x00\x00\x00\x02w\xef\x00\x00\x00\x00\x00\x03q\fp\x00\x00\x00\x00\x04a\v\x80\x00\x00\x00\x00\x05P\xeep\x00\x00\x00\x00\x06@\xed\x80\x00\x00" + + "\x00\x00\a0\xd0p\x00\x00\x00\x00\a\x8d'\x80\x00\x00\x00\x00\t\x10\xb2p\x00\x00\x00\x00\t\xad\xa3\x00\x00\x00\x00\x00\n\xf0\x94p\x00\x00\x00\x00\v\xe0\x93\x80\x00\x00\x00\x00\fٰ\xf0\x00\x00\x00\x00\r\xc0" + + "u\x80\x00\x00\x00\x00\x0e\xb9\x92\xf0\x00\x00\x00\x00\x0f\xa9\x92\x00\x00\x00\x00\x00\x10\x99t\xf0\x00\x00\x00\x00\x11\x89t\x00\x00\x00\x00\x00\x12yV\xf0\x00\x00\x00\x00\x13iV\x00\x00\x00\x00\x00\x14Y8\xf0\x00\x00" + + "\x00\x00\x15I8\x00\x00\x00\x00\x00\x169\x1a\xf0\x00\x00\x00\x00\x17)\x1a\x00\x00\x00\x00\x00\x18\"7p\x00\x00\x00\x00\x19\b\xfc\x00\x00\x00\x00\x00\x1a\x02\x19p\x00\x00\x00\x00\x1a\xf2\x18\x80\x00\x00\x00\x00\x1b\xe1" + + "\xfbp\x00\x00\x00\x00\x1c\xd1\xfa\x80\x00\x00\x00\x00\x1d\xc1\xddp\x00\x00\x00\x00\x1e\xb1܀\x00\x00\x00\x00\x1f\xa1\xbfp\x00\x00\x00\x00 v\x0f\x00\x00\x00\x00\x00!\x81\xa1p\x00\x00\x00\x00\"U\xf1\x00\x00\x00" + + "\x00\x00#j\xbd\xf0\x00\x00\x00\x00$5\xd3\x00\x00\x00\x00\x00%J\x9f\xf0\x00\x00\x00\x00&\x15\xb5\x00\x00\x00\x00\x00'*\x81\xf0\x00\x00\x00\x00'\xfeр\x00\x00\x00\x00)\nc\xf0\x00\x00\x00\x00D/" + + "vp\x00\x00\x00\x00EDQp\x00\x00\x00\x00E\xf3\xb7\x00\x02\x01\x02\x01\x02\x03\x04\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x05\x02\x01\x02" + + "\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x05\x01\x02\x01\xff\xff\xae\xca\x00\x00\xff\xff\xb9" + + "\xb0\x01\x04\xff\xff\xab\xa0\x00\b\xff\xff\xb9\xb0\x01\f\xff\xff\xb9\xb0\x01\x10\xff\xff\xb9\xb0\x00\x14LMT\x00CDT\x00CST\x00CWT\x00CPT\x00EST\x00\nCST6CDT," + + "M3.2.0,M11.1.0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x9f.\xe4xo\x00\x00\x00o\x00\x00\x00\x03\x00\x1c\x00UTCUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8b" + + "aux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01" + + "\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00UTC" + + "\x00\nUTC0\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS2\x91B\xc0\xee\x01\x00\x00\xee\x01\x00\x00\x03\x00\x1c\x00WETUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14" + + "E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00T" + + "Zif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\x00\x00\x00\x02\x00\x00\x00\t\x00\x00\x00\x00\r\xa4c\x90\x00\x00\x00\x00\x0e\x8b\x1a\x10\x00" + + "\x00\x00\x00\x0f\x84E\x90\x00\x00\x00\x00\x10t6\x90\x00\x00\x00\x00\x11d'\x90\x00\x00\x00\x00\x12T\x18\x90\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16" + + "\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00" + + "\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#\xf2y\xff\xff\xff\xff\x9e*\xee\xf9\xff\xff\xff\xff\x9e\xf79i\xff\xff\xff\xff\x9f\x84W\xf9\xff\xff\xff\xff\xa0\xd8l\xe9\xff\xff\xff\xff\xa1" + + "\x009\x80\xff\xff\xff\xff\xa1<\xa6@\xff\xff\xff\xff\xa4\x10m\xc0\xff\xff\xff\xff\xa4=2\xb0\xff\xff\xff\xff\xa5\x15h\xb0\xff\xff\xff\xff\xa5=\x03\xc0\xff\xff\xff\xff\xa7\x1eEP\xff\xff\xff\xff\xb5\xa4\x19`\x00" + + "\x00\x00\x00\x15'\xa7\xd0\x00\x00\x00\x00\x16\x18\xdc@\x00\x00\x00\x00\x17\b\xdbP\x00\x00\x00\x00\x17\xfa\x0f\xc0\x00\x00\x00\x00\x18\xea\x0e\xd0\x00\x00\x00\x00\x19\xdbC@\x00\x00\x00\x00\x1a̓\xd0\x00\x00\x00\x00\x1b" + + "\xbc\xa0\xf0\x00\x00\x00\x00\x1c\xac\x91\xf0\x00\x00\x00\x00\x1d\x9c\x82\xf0\x00\x00\x00\x00\x1e\x8cs\xf0\x00\x00\x00\x00\x1f|d\xf0\x00\x00\x00\x00 lU\xf0\x00\x00\x00\x00!\\F\xf0\x00\x00\x00\x00\"L7\xf0\x00" + + "\x00\x00\x00#<(\xf0\x00\x00\x00\x00$,\x19\xf0\x00\x00\x00\x00%\x1c\n\xf0\x00\x00\x00\x00&\v\xfb\xf0\x00\x00\x00\x00'\x05'p\x00\x00\x00\x00'\xf5\x18p\x00\x00\x00\x00(\xe5\x17\x80\x00\x00\x00\x00)" + + "x\xbf\x80\x00\x00\x00\x00)\xd4\xfap\x00\x00\x00\x00*\xc4\xebp\x00\x00\x00\x00+\xb4\xdcp\x00\x00\x00\x00,\xa4\xcdp\x00\x00\x00\x00-\x94\xbep\x00\x00\x00\x00.\x84\xafp\x00\x00\x00\x00/t\xa0p\x00" + + "\x00\x00\x000d\x91p\x00\x00\x00\x001]\xbc\xf0\x00\x00\x00\x002r\x97\xf0\x00\x00\x00\x003=\x9e\xf0\x00\x00\x00\x004Ry\xf0\x00\x00\x00\x005\x1d\x80\xf0\x00\x00\x00\x0062[\xf0\x00\x00\x00\x006" + + "\xfdb\xf0\x00\x00\x00\x008\x1bxp\x00\x00\x00\x008\xddD\xf0\x00\x00\x00\x009\xfbZp\x00\x00\x00\x00:\xbd&\xf0\x00\x00\x00\x00;\xdb\x86%p\x00\x00\x00\x00?\x9b\x00p\x00\x00\x00\x00@f\ap\x00\x00\x00\x00A\x84\x1c\xf0\x00\x00\x00\x00BE\xe9p\x00\x00\x00\x00Cc\xfe\xf0\x00\x00\x00\x00D%\xcbp\x00\x00\x00\x00E" + + "C\xe0\xf0\x00\x00\x00\x00F\x05\xadp\x00\x00\x00\x00G#\xc2\xf0\x00\x00\x00\x00G\xee\xc9\xf0\x00\x00\x00\x00I\x03\xa4\xf0\x00\x00\x00\x00IΫ\xf0\x00\x00\x00\x00J\xe3\x86\xf0\x00\x00\x00\x00K\xae\x8d\xf0\x00" + + "\x00\x00\x00Ḷp\x00\x00\x00\x00M\x8eo\xf0\x00\x00\x00\x00TL\x1d`\x01\x03\x02\x03\x04\x02\x04\x05\x06\x05\a\x05\x06\b\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\t\b" + + "\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\x05\x06\n\x06\x00\x00#9\x00\x00\x00\x00#9\x00\x04\x00\x001\x87\x01\b\x00" + + "\x00#w\x00\x04\x00\x00?\x97\x01\f\x00\x008@\x01\x11\x00\x00*0\x00\x15\x00\x00FP\x01\x19\x00\x00\x1c \x00\x1d\x00\x00*0\x01!\x00\x008@\x00\x15LMT\x00MMT\x00MST\x00M" + + "DST\x00MSD\x00MSK\x00+05\x00EET\x00EEST\x00\nMSK-3\nPK\x03\x04\n\x00\x00\x00\x00\x00#\x82iS\x9f.\xe4xo\x00\x00\x00o\x00\x00\x00\x04\x00" + + "\x1c\x00ZuluUT\t\x00\x03\x82\x0f\x8ba\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00UTC\x00\nUTC0\nPK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x18\x00\x00\x00\x00" + + "\x00\x00\x00\x10\x00\xe8A\x00\x00\x00\x00Africa/UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS \x1b" + + "\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81A\x00\x00\x00Africa/GaboroneUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E" + + "\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\r\x01\x00\x00Africa/" + + "DakarUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xaa\x81\t\x03\xa0\x00\x00\x00\xa0\x00\x00\x00\x0f\x00\x18" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xd5\x01\x00\x00Africa/NdjamenaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03" + + "\n\x00\x00\x00\x00\x00#\x82iS\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xbe\x02\x00\x00Africa/AbidjanUT\x05\x00\x03\x82" + + "\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS \x1b\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81" + + "\x88\x03\x00\x00Africa/HarareUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xf1\b{" + + "\x87\x82\x00\x00\x00\x82\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81R\x04\x00\x00Africa/OuagadougouUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04" + + "\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSd\x01\x05\x89\u007f\a\x00\x00\u007f\a\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81 \x05\x00\x00Afric" + + "a/CasablancaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xb4\x8d\x98ƿ\x00\x00\x00" + + "\xbf\x00\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xea\f\x00\x00Africa/Dar_es_SalaamUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00" + + "\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xf7\r\x00\x00Africa/P" + + "orto-NovoUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00" + + "\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xf6\x0e\x00\x00Africa/KinshasaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK" + + "\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xf3\x0f\x00\x00Africa/Brazzavil" + + "leUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\x10\x00\x18\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\xa0\x81\xf3\x10\x00\x00Africa/MogadishuUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00" + + "\x00\x00\x00\x00#\x82iS\xc1\n\x8a\x84\xad\x00\x00\x00\xad\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xfc\x11\x00\x00Africa/Sao_TomeUT\x05\x00\x03\x82\x0f" + + "\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xcc\fTξ\x00\x00\x00\xbe\x00\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xf2" + + "\x12\x00\x00Africa/JohannesburgUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82" + + "iSm)\xb8P~\x02\x00\x00~\x02\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xfd\x13\x00\x00Africa/WindhoekUT\x05\x00\x03\x82\x0f\x8baux\v\x00" + + "\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xc4\x16\x00\x00Afr" + + "ica/NiameyUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00" + + "\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xbf\x17\x00\x00Africa/NairobiUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK" + + "\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS)\xae\x8eo&\a\x00\x00&\a\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xc6\x18\x00\x00Africa/El_AaiunU" + + "T\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS \x1b\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\xa0\x815 \x00\x00Africa/LusakaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82" + + "iS\x93\xf4\x94\v\xc1\x01\x00\x00\xc1\x01\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xff \x00\x00Africa/TunisUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14" + + "E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xcc\fTξ\x00\x00\x00\xbe\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x06#\x00\x00Africa" + + "/MaseruUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\v" + + "\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\v$\x00\x00Africa/LomeUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00" + + "\x00\x00\x00\x00#\x82iS\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xd2$\x00\x00Africa/DoualaUT\x05\x00\x03\x82\x0f\x8ba" + + "ux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS \x1b\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xcd%\x00" + + "\x00Africa/BujumburaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSV\xadD" + + "\xef\xca\x01\x00\x00\xca\x01\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x9a&\x00\x00Africa/KhartoumUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00" + + "\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xad(\x00\x00Africa/A" + + "smaraUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\x0e\x00\x18" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xb3)\x00\x00Africa/ConakryUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n" + + "\x00\x00\x00\x00\x00#\x82iSÊ\x0e\xc0\xd6\x01\x00\x00\xd6\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81}*\x00\x00Africa/AlgiersUT\x05\x00\x03\x82\x0f" + + "\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x9b" + + ",\x00\x00Africa/BanguiUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xa7\x1d\xb3c" + + "\xb4\x00\x00\x00\xb4\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x96-\x00\x00Africa/LibrevilleUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E" + + "\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x14\xcf\x10n\xca\x01\x00\x00\xca\x01\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x95.\x00\x00Africa/" + + "JubaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS6\x99rU\xa4\x00\x00\x00\xa4\x00\x00\x00\x0f\x00\x18\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xa40\x00\x00Africa/MonroviaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n" + + "\x00\x00\x00\x00\x00#\x82iS\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x911\x00\x00Africa/DjiboutiUT\x05\x00\x03\x82" + + "\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81" + + "\x992\x00\x00Africa/TimbuktuUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xa7" + + "\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81d3\x00\x00Africa/MalaboUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00" + + "\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81_4\x00\x00Africa/F" + + "reetownUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\r" + + "\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81*5\x00\x00Africa/BanjulUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03" + + "\n\x00\x00\x00\x00\x00#\x82iS \x1b\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xf35\x00\x00Africa/KigaliUT\x05\x00\x03\x82\x0f" + + "\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xca>\xd5\xe0\x95\x00\x00\x00\x95\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xbd" + + "6\x00\x00Africa/BissauUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xcc\fT\xce" + + "\xbe\x00\x00\x00\xbe\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x997\x00\x00Africa/MbabaneUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04" + + "S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x9f\x1b\xeb\xdd2\x02\x00\x002\x02\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x9f8\x00\x00Africa/Ceu" + + "taUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS \x1b\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\x0f\x00\x18\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\xa0\x81\x17;\x00\x00Africa/BlantyreUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00" + + "\x00\x00\x00#\x82iS \x1b\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xe3;\x00\x00Africa/MaputoUT\x05\x00\x03\x82\x0f\x8bau" + + "x\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xad<\x00\x00" + + "Africa/BamakoUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xa7\x1d\xb3c\xb4\x00\x00" + + "\x00\xb4\x00\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81v=\x00\x00Africa/LagosUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00P" + + "K\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81p>\x00\x00Africa/AsmeraUT" + + "\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\xa0\x81v?\x00\x00Africa/AccraUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS" + + "\xa7\x1d\xb3c\xb4\x00\x00\x00\xb4\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81>@\x00\x00Africa/LuandaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E" + + "\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS \x1b\xb0_\x83\x00\x00\x00\x83\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x819A\x00\x00Africa/" + + "LubumbashiUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00" + + "\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\aB\x00\x00Africa/Addis_AbabaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_" + + "\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x12tnj\xfc\x04\x00\x00\xfc\x04\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x12C\x00\x00Africa/Cairo" + + "UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS_\u007f2[\xaf\x01\x00\x00\xaf\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\xa0\x81TH\x00\x00Africa/TripoliUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00" + + "#\x82iS\xf1\b{\x87\x82\x00\x00\x00\x82\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81KJ\x00\x00Africa/NouakchottUT\x05\x00\x03\x82\x0f\x8ba" + + "ux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x18K\x00" + + "\x00Africa/KampalaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\b\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xe8A\x1fL\x00\x00America/UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01" + + "\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xd0v\x01\x8a\x01\x04\x00\x00\x01\x04\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81aL\x00\x00America/TijuanaUT" + + "\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\xa0\x81\xabP\x00\x00America/Blanc-SablonUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00" + + "\x00\x00\x00\x00#\x82iS\xb4\x82s\x1dT\x01\x00\x00T\x01\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xaaQ\x00\x00America/ChihuahuaUT\x05\x00\x03" + + "\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSԾ\xe7#\x95\x00\x00\x00\x95\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0" + + "\x81IS\x00\x00America/AtikokanUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82i" + + "S?_p\x99\x0e\x05\x00\x00\x0e\x05\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81(T\x00\x00America/WinnipegUT\x05\x00\x03\x82\x0f\x8baux\v\x00" + + "\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x80Y\x00\x00Ame" + + "rica/ArubaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSJtZ\x8c\x01\x03\x00\x00\x01\x03" + + "\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81xZ\x00\x00America/PangnirtungUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S" + + "_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xc6]\x00\x00America/Mon" + + "tserratUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x12" + + "\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xc3^\x00\x00America/KralendijkUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00P" + + "K\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xf6\"\x12\xfe\x0e\x05\x00\x00\x0e\x05\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xc0_\x00\x00America/Los_Ang" + + "elesUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x10\x00\x18\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x1be\x00\x00America/St_KittsUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03" + + "\n\x00\x00\x00\x00\x00#\x82iS\xbf\x03u\xf3\xe4\x01\x00\x00\xe4\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x16f\x00\x00America/RecifeUT\x05\x00\x03\x82" + + "\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xd6\xfe\xf3%\xb4\x02\x00\x00\xb4\x02\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81" + + "Bh\x00\x00America/ResoluteUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS" + + "R\xc8\xd9\xf6\xc4\x02\x00\x00\xc4\x02\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81@k\x00\x00America/CatamarcaUT\x05\x00\x03\x82\x0f\x8baux\v\x00" + + "\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xae,\xa44\xc9\x03\x00\x00\xc9\x03\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81On\x00\x00Ame" + + "rica/AtkaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS.\xbe\x1a>\xe7\x03\x00\x00\xe7\x03\x00" + + "\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81^r\x00\x00America/BoiseUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02" + + "\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xe8A\x8cv\x00\x00America/North_Dako" + + "ta/UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSR\x1b\x8b(\xde\x03\x00\x00\xde\x03\x00\x00\x1e\x00\x18\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xdbv\x00\x00America/North_Dakota/New_SalemUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E" + + "\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSH\xeam\xef\xde\x03\x00\x00\xde\x03\x00\x00\x1b\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x11{\x00\x00America" + + "/North_Dakota/CenterUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS" + + "\xb7.\xb6*\x13\x04\x00\x00\x13\x04\x00\x00\x1b\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81D\u007f\x00\x00America/North_Dakota/BeulahUT\x05" + + "\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSa\xcb'\xe9\x9c\x01\x00\x00\x9c\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\xa0\x81\xac\x83\x00\x00America/ManausUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82i" + + "Sq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x15\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x90\x85\x00\x00America/Port_of_SpainUT\x05\x00\x03\x82\x0f\x8b" + + "aux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSŒZ\x8c\xc4\x02\x00\x00\xc4\x02\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x90\x86" + + "\x00\x00America/MendozaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xac\x8a\x83" + + "S\xd4\x00\x00\x00\xd4\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x9d\x89\x00\x00America/GuatemalaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14" + + "E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSU!\x12f\xd9\x02\x00\x00\xd9\x02\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xbc\x8a\x00\x00Americ" + + "a/YellowknifeUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xe90T\x16\xd1\x01\x00" + + "\x00\xd1\x01\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xe2\x8d\x00\x00America/NuukUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00P" + + "K\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x15\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xf9\x8f\x00\x00America/St_Bart" + + "helemyUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS:\x9a1T\xdf\x01\x00\x00\xdf\x01\x00\x00\x14\x00" + + "\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xf9\x90\x00\x00America/ScoresbysundUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00" + + "PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x9d?\xdfڸ\x03\x00\x00\xb8\x03\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81&\x93\x00\x00America/Sao_Pa" + + "uloUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x82\x13z\xe2\xc2\x00\x00\x00\xc2\x00\x00\x00\x13\x00\x18\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\xa0\x81)\x97\x00\x00America/TegucigalpaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02" + + "\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSM\x94\xc7Kp\x03\x00\x00p\x03\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x818\x98\x00\x00America/Glace_BayU" + + "T\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x8f\x19Ԇ\x12\x02\x00\x00\x12\x02\x00\x00\x16\x00\x18\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\xa0\x81\xf3\x9b\x00\x00America/Bahia_BanderasUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e" + + "\x03\n\x00\x00\x00\x00\x00#\x82iS\xef\xf0R\x8a\xc4\x02\x00\x00\xc4\x02\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81U\x9e\x00\x00America/RosarioUT\x05\x00" + + "\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x81{\xc1\x92\xbc\x03\x00\x00\xbc\x03\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\xa0\x81b\xa1\x00\x00America/SitkaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS)" + + ":\x17-\x88\x06\x00\x00\x88\x06\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81e\xa5\x00\x00America/HalifaxUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14" + + "E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xc1Ȇ\x90\x05\x04\x00\x00\x05\x04\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x816\xac\x00\x00Americ" + + "a/WhitehorseUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xf8Dz\x97\xae\x01\x00\x00" + + "\xae\x01\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x87\xb0\x00\x00America/Boa_VistaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S" + + "_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSc)\xf6)\xb3\x00\x00\x00\xb3\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x80\xb2\x00\x00America/Bog" + + "otaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS8O:\xbf\x95\x03\x00\x00\x95\x03\x00\x00\x11\x00\x18\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\xa0\x81{\xb3\x00\x00America/MenomineeUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03" + + "\n\x00\x00\x00\x00\x00#\x82iS<\xb9\x18\x87\xe4\x02\x00\x00\xe4\x02\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81[\xb7\x00\x00America/IqaluitUT\x05\x00\x03" + + "\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xad`\x12\xe9\xaa\x00\x00\x00\xaa\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0" + + "\x81\x88\xba\x00\x00America/La_PazUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xae" + + ",\xa44\xc9\x03\x00\x00\xc9\x03\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81z\xbb\x00\x00America/AdakUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00" + + "\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xea$\xc1\xbf\xb0\x00\x00\x00\xb0\x00\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x89\xbf\x00\x00America/E" + + "l_SalvadorUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSԾ\xe7#\x95\x00\x00\x00\x95\x00" + + "\x00\x00\x15\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x86\xc0\x00\x00America/Coral_HarbourUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00" + + "\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xe8Aj\xc1\x00\x00America/K" + + "entucky/UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x03\x1a|J\xcc\x03\x00\x00\xcc\x03\x00\x00" + + "\x1b\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xb5\xc1\x00\x00America/Kentucky/MonticelloUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04" + + "\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xdf\xe5\x8d\xc4\xda\x04\x00\x00\xda\x04\x00\x00\x1b\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xd6\xc5\x00\x00Ameri" + + "ca/Kentucky/LouisvilleUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82" + + "iS3\x9aG\xc8\xd0\x06\x00\x00\xd0\x06\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x05\xcb\x00\x00America/New_YorkUT\x05\x00\x03\x82\x0f\x8baux\v" + + "\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSl=\xad\xbe\x16\x01\x00\x00\x16\x01\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x1f\xd2\x00\x00Am" + + "erica/BarbadosUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00" + + "\x00\x00\xb1\x00\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\u007f\xd3\x00\x00America/Puerto_RicoUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E" + + "\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81}\xd4\x00\x00America" + + "/AnguillaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS,\xdb~\xab\xb2\x03\x00\x00\xb2\x03\x00" + + "\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81x\xd5\x00\x00America/YakutatUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK" + + "\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSV\x80\x94@\x12\x04\x00\x00\x12\x04\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81s\xd9\x00\x00America/Shiprock" + + "UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00" + + "\x00\x00\x10\x00\xe8A\xcf\xdd\x00\x00America/Argentina/UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00" + + "\x00\x00\x00\x00#\x82iSR\xc8\xd9\xf6\xc4\x02\x00\x00\xc4\x02\x00\x00\x1b\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x1b\xde\x00\x00America/Argentina/Cata" + + "marcaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSR\xc8\xd9\xf6\xc4\x02\x00\x00\xc4\x02\x00\x00 \x00\x18" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x814\xe1\x00\x00America/Argentina/ComodRivadaviaUT\x05\x00\x03\x82\x0f\x8baux\v\x00" + + "\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSŒZ\x8c\xc4\x02\x00\x00\xc4\x02\x00\x00\x19\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81R\xe4\x00\x00Ame" + + "rica/Argentina/MendozaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82" + + "iS\x8b}\xb6\x1e\xc4\x02\x00\x00\xc4\x02\x00\x00\x19\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81i\xe7\x00\x00America/Argentina/UshuaiaUT\x05" + + "\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSm\aD\x0e\xcd\x02\x00\x00\xcd\x02\x00\x00\x1a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\xa0\x81\x80\xea\x00\x00America/Argentina/La_RiojaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01" + + "\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSutZ\x1a\xb2\x02\x00\x00\xb2\x02\x00\x00\x17\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xa1\xed\x00\x00America/Argentina" + + "/JujuyUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x1c\x80\xb9\\\xcd\x02\x00\x00\xcd\x02\x00\x00\x1a\x00" + + "\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xa4\xf0\x00\x00America/Argentina/San_LuisUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00" + + "\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xe0\xbf\xf5\xe5\xc4\x02\x00\x00\xc4\x02\x00\x00\x1e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xc5\xf3\x00\x00America/" + + "Argentina/Buenos_AiresUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82" + + "iS\x8ep\xb4c\xc4\x02\x00\x00\xc4\x02\x00\x00\x1e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xe1\xf6\x00\x00America/Argentina/Rio_Galleg" + + "osUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xfcz=\xe1\xcd\x02\x00\x00\xcd\x02\x00\x00\x1a\x00\x18\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\xa0\x81\xfd\xf9\x00\x00America/Argentina/San_JuanUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_" + + "\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xef\xf0R\x8a\xc4\x02\x00\x00\xc4\x02\x00\x00\x19\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x1e\xfd\x00\x00America/Arge" + + "ntina/CordobaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSY\xd8֭\xd6\x02\x00" + + "\x00\xd6\x02\x00\x00\x19\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x815\x00\x01\x00America/Argentina/TucumanUT\x05\x00\x03\x82\x0f\x8baux\v" + + "\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSt*\x9b!\xb2\x02\x00\x00\xb2\x02\x00\x00\x17\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81^\x03\x01\x00Am" + + "erica/Argentina/SaltaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82i" + + "Sp\xb6{\xc9\x13\x02\x00\x00\x13\x02\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81a\x06\x01\x00America/IndianapolisUT\x05\x00\x03\x82\x0f\x8ba" + + "ux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xc2\b\x01" + + "\x00America/DominicaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x9bܩ" + + "=\xda\x06\x00\x00\xda\x06\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xbd\t\x01\x00America/ChicagoUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00" + + "\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x1c\xd8\x19\x9dp\x01\x00\x00p\x01\x00\x00\x15\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xe0\x10\x01\x00America/" + + "Swift_CurrentUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x1e+}\x15\xb4\x02\x00" + + "\x00\xb4\x02\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x9f\x12\x01\x00America/Rankin_InletUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E" + + "\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSԾ\xe7#\x95\x00\x00\x00\x95\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xa1\x15\x01\x00America" + + "/PanamaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xe90T\x16\xd1\x01\x00\x00\xd1\x01\x00\x00\x0f" + + "\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81~\x16\x01\x00America/GodthabUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02" + + "\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x89غ\xee\x15\x04\x00\x00\x15\x04\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x98\x18\x01\x00America/BelizeUT\x05\x00" + + "\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xd7\b\\\xc6&\x02\x00\x00&\x02\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\xa0\x81\xf5\x1c\x01\x00America/MiquelonUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82" + + "iSB\xa0=:\x1e\x01\x00\x00\x1e\x01\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81e\x1f\x01\x00America/HermosilloUT\x05\x00\x03\x82\x0f\x8bau" + + "x\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS>\x14\xe7\x03\x83\x03\x00\x00\x83\x03\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xcf \x01\x00" + + "America/DetroitUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xb4\x11Z\xde\xe4" + + "\x01\x00\x00\xe4\x01\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x9b$\x01\x00America/FortalezaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00" + + "\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS$\r\x89l\xe4\x01\x00\x00\xe4\x01\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xca&\x01\x00America/" + + "OjinagaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS5\x11Q\x06\xd1\x03\x00\x00\xd1\x03\x00\x00\x11" + + "\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xf7(\x01\x00America/AnchorageUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK" + + "\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSU9#\xbe2\x05\x00\x002\x05\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x13-\x01\x00America/Vancouve" + + "rUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSg\xf5K\x89\xa2\x01\x00\x00\xa2\x01\x00\x00\x12\x00\x18\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\xa0\x81\x902\x01\x00America/Porto_AcreUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n" + + "\x00\x00\x00\x00\x00#\x82iSd\xa9y\x9at\x03\x00\x00t\x03\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81~4\x01\x00America/AsuncionUT\x05\x00\x03" + + "\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS?\xc9\x1c\xd4\xc6\x03\x00\x00\xc6\x03\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0" + + "\x81<8\x01\x00America/JuneauUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xf6" + + "@\rm\xa8\x05\x00\x00\xa8\x05\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81J<\x01\x00America/Fort_NelsonUT\x05\x00\x03\x82\x0f\x8baux\v" + + "\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x85-\xb9\xf8\x8a\x01\x00\x00\x8a\x01\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81?B\x01\x00Am" + + "erica/BelemUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSV\x80\x94@\x12\x04\x00\x00\x12" + + "\x04\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x10D\x01\x00America/DenverUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00P" + + "K\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSp\xb6{\xc9\x13\x02\x00\x00\x13\x02\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81jH\x01\x00America/Fort_Wa" + + "yneUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSg\xf5K\x89\xa2\x01\x00\x00\xa2\x01\x00\x00\x12\x00\x18\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xc9J\x01\x00America/Rio_BrancoUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e" + + "\x03\n\x00\x00\x00\x00\x00#\x82iS\x1e\xfbn۸\x03\x00\x00\xb8\x03\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xb7L\x01\x00America/Campo_Grand" + + "eUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS{\a\a\xdc\xca\x03\x00\x00\xca\x03\x00\x00\x10\x00\x18\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\xa0\x81\xbdP\x01\x00America/EdmontonUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00" + + "\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xd1T\x01\x00America/St_ThomasUT\x05\x00\x03\x82" + + "\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81" + + "\xcdU\x01\x00America/VirginUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSMv" + + "\xa1\x0f%\x01\x00\x00%\x01\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xc6V\x01\x00America/MonterreyUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04" + + "\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xb4T\xbd\xeb5\x02\x00\x005\x02\x00\x00\x16\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x816X\x01\x00Ameri" + + "ca/Port-au-PrinceUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x1b\x81-" + + "\xa9\x8a\x01\x00\x00\x8a\x01\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xbbZ\x01\x00America/Porto_VelhoUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01" + + "\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x92\\\x01\x00Amer" + + "ica/St_VincentUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xd0v\x01\x8a\x01\x04" + + "\x00\x00\x01\x04\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x8f]\x01\x00America/EnsenadaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04" + + "S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xb1݂x\xe8\x00\x00\x00\xe8\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xdaa\x01\x00America/Co" + + "sta_RicaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xa2\x81\xbfyS\x02\x00\x00S\x02\x00\x00" + + "\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x0ec\x01\x00America/MetlakatlaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00" + + "PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xade\x01\x00America/Curaca" + + "oUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xa7\x17jҲ\x00\x00\x00\xb2\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\xa0\x81\xa7f\x01\x00America/MartiniqueUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n" + + "\x00\x00\x00\x00\x00#\x82iS~\xb2\x0e\x19V\a\x00\x00V\a\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xa5g\x01\x00America/St_JohnsUT\x05\x00\x03" + + "\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSutZ\x1a\xb2\x02\x00\x00\xb2\x02\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0" + + "\x81Eo\x01\x00America/JujuyUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSP\x0f" + + "(\b=\x01\x00\x00=\x01\x00\x00\x15\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81>r\x01\x00America/Santo_DomingoUT\x05\x00\x03\x82\x0f\x8baux" + + "\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\u0096dK~\x02\x00\x00~\x02\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xcas\x01\x00A" + + "merica/ReginaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSp\x1b\xceRC\x03\x00" + + "\x00C\x03\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x90v\x01\x00America/NipigonUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_" + + "\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSo_\x00v/\x01\x00\x00/\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x1cz\x01\x00America/Meri" + + "daUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSn\xab\xd5\xf9\xcf\x03\x00\x00\xcf\x03\x00\x00\f\x00\x18\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\xa0\x81\x93{\x01\x00America/NomeUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00" + + "#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xe8A\xa8\u007f\x01\x00America/Indiana/UT\x05\x00\x03\x82\x0f\x8bau" + + "x\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSصK\xa6\n\x02\x00\x00\n\x02\x00\x00\x19\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xf2\u007f\x01\x00" + + "America/Indiana/Tell_CityUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00" + + "\x00#\x82iSp\xb6{\xc9\x13\x02\x00\x00\x13\x02\x00\x00\x1c\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81O\x82\x01\x00America/Indiana/Indianapo" + + "lisUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSM/U\x9f7\x02\x00\x007\x02\x00\x00\x17\x00\x18\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xb8\x84\x01\x00America/Indiana/MarengoUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00" + + "PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\r\xedsp.\x02\x00\x00.\x02\x00\x00\x19\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81@\x87\x01\x00America/Indian" + + "a/VincennesUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x01\xd8N\x8c\xab\x02\x00\x00\xab" + + "\x02\x00\x00\x1a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xc1\x89\x01\x00America/Indiana/PetersburgUT\x05\x00\x03\x82\x0f\x8baux\v\x00" + + "\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSK-E\xfad\x02\x00\x00d\x02\x00\x00\x17\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xc0\x8c\x01\x00Ame" + + "rica/Indiana/WinamacUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS" + + " \x17\x89}q\x01\x00\x00q\x01\x00\x00\x15\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81u\x8f\x01\x00America/Indiana/VevayUT\x05\x00\x03\x82\x0f\x8ba" + + "ux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS$ \x873\xf8\x03\x00\x00\xf8\x03\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x815\x91\x01" + + "\x00America/Indiana/KnoxUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82i" + + "SԾ\xe7#\x95\x00\x00\x00\x95\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81{\x95\x01\x00America/CaymanUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04" + + "\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS錴$q\x03\x00\x00q\x03\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81X\x96\x01\x00Ameri" + + "ca/Thunder_BayUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS8\xcdZ\x05o\x01" + + "\x00\x00o\x01\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x16\x9a\x01\x00America/MazatlanUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04" + + "S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xb7-2f\xe4\x01\x00\x00\xe4\x01\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81ϛ\x01\x00America/No" + + "ronhaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xe0\xbf\xf5\xe5\xc4\x02\x00\x00\xc4\x02\x00\x00\x14\x00\x18" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xfc\x9d\x01\x00America/Buenos_AiresUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00P" + + "K\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x0e\xa1\x01\x00America/Tortola" + + "UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xa1'\a\xbd\x97\x00\x00\x00\x97\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\xa0\x81\b\xa2\x01\x00America/CayenneUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00" + + "\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xe8\xa2\x01\x00America/St_LuciaUT\x05\x00\x03\x82\x0f\x8ba" + + "ux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSk\xc2\rx\xbf\x01\x00\x00\xbf\x01\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xe3\xa3\x01" + + "\x00America/DanmarkshavnUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82i" + + "S\xf1\xf9\x1dɻ\x00\x00\x00\xbb\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xf0\xa5\x01\x00America/ParamariboUT\x05\x00\x03\x82\x0f\x8baux" + + "\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xfe7\xa1\x87\x1b\x01\x00\x00\x1b\x01\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xf7\xa6\x01\x00A" + + "merica/LimaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xac\x8e\xee\x13\xbe\x00\x00\x00\xbe" + + "\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81X\xa8\x01\x00America/CaracasUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00" + + "PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSø\xab\x9b\xf0\x00\x00\x00\xf0\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81_\xa9\x01\x00America/Phoeni" + + "xUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS<\x01V\rP\x02\x00\x00P\x02\x00\x00\x11\x00\x18\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\xa0\x81\x98\xaa\x01\x00America/AraguainaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00" + + "\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x15\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x813\xad\x01\x00America/Lower_PrincesU" + + "T\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSk^2S\xb9\x04\x00\x00\xb9\x04\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\xa0\x813\xae\x01\x00America/Punta_ArenasUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n" + + "\x00\x00\x00\x00\x00#\x82iS\x1d`̟\x00\x03\x00\x00\x00\x03\x00\x00\x15\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81:\xb3\x01\x00America/Cambridge_Bay" + + "UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSӿ\x92\xbc\xb5\x06\x00\x00\xb5\x06\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\xa0\x81\x89\xb6\x01\x00America/MontrealUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00" + + "\x00\x00#\x82iS\x04,2h\x99\x01\x00\x00\x99\x01\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x88\xbd\x01\x00America/SantaremUT\x05\x00\x03\x82\x0f\x8b" + + "aux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xf2\x04\xde\xdd\x11\x02\x00\x00\x11\x02\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81k\xbf" + + "\x01\x00America/CancunUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSU\xactA" + + "\xb5\x01\x00\x00\xb5\x01\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xc4\xc1\x01\x00America/MatamorosUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E" + + "\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSs\xb0\xeau\xb4\x01\x00\x00\xb4\x01\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xc4\xc3\x01\x00America" + + "/EirunepeUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xd0v\x01\x8a\x01\x04\x00\x00\x01\x04\x00" + + "\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xc2\xc5\x01\x00America/Santa_IsabelUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S" + + "_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x11\xca\x01\x00America/Gre" + + "nadaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x0f\x00\x18\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\v\xcb\x01\x00America/MarigotUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n" + + "\x00\x00\x00\x00\x00#\x82iS\xf7\xe9 y\xbd\x02\x00\x00\xbd\x02\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x05\xcc\x01\x00America/InuvikUT\x05\x00\x03\x82\x0f" + + "\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xe5s\xb3\\'\x01\x00\x00'\x01\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\n" + + "\xcf\x01\x00America/ManaguaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xfe\xe6" + + "\xf5J\x05\x04\x00\x00\x05\x04\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81z\xd0\x01\x00America/DawsonUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00" + + "\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS.\xf9\xc0\x1e\xd5\x05\x00\x00\xd5\x05\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xc7\xd4\x01\x00America/" + + "MonctonUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS[Sp\x90\x02\x05\x00\x00\x02\x05\x00\x00\x10" + + "\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xe5\xda\x01\x00America/SantiagoUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01" + + "\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSø\xab\x9b\xf0\x00\x00\x00\xf0\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x811\xe0\x01\x00America/CrestonUT" + + "\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xef\xf0R\x8a\xc4\x02\x00\x00\xc4\x02\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\xa0\x81j\xe1\x01\x00America/CordobaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#" + + "\x82iS%J\xd5\xebS\x01\x00\x00S\x01\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81w\xe4\x01\x00America/JamaicaUT\x05\x00\x03\x82\x0f\x8baux\v" + + "\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS挋\x92\xf6\x01\x00\x00\xf6\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x13\xe6\x01\x00Am" + + "erica/MaceioUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS+\x10`ȫ\x02\x00\x00" + + "\xab\x02\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81Q\xe8\x01\x00America/Dawson_CreekUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00" + + "\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSӿ\x92\xbc\xb5\x06\x00\x00\xb5\x06\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81J\xeb\x01\x00America/" + + "TorontoUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xd6\xe1Հ\x9c\x01\x00\x00\x9c\x01\x00\x00\x13" + + "\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81H\xf2\x01\x00America/Mexico_CityUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00" + + "PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSӿ\x92\xbc\xb5\x06\x00\x00\xb5\x06\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x811\xf4\x01\x00America/Nassau" + + "UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\u007f$*\xa0\xa6\x03\x00\x00\xa6\x03\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\xa0\x81.\xfb\x01\x00America/CuiabaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00" + + "#\x82iSq\xc9*;\xb1\x00\x00\x00\xb1\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x1c\xff\x01\x00America/GuadeloupeUT\x05\x00\x03\x82\x0f\x8b" + + "aux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x1d\xf7\a ,\x06\x00\x00,\x06\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x19\x00" + + "\x02\x00America/Goose_BayUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xdf" + + "\xe5\x8d\xc4\xda\x04\x00\x00\xda\x04\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x90\x06\x02\x00America/LouisvilleUT\x05\x00\x03\x82\x0f\x8baux\v\x00" + + "\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x1b\vKdC\x03\x00\x00C\x03\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xb6\v\x02\x00Ame" + + "rica/Rainy_RiverUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xc0\x98\x00\b" + + "\xc9\x03\x00\x00\xc9\x03\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81F\x0f\x02\x00America/MontevideoUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14" + + "E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS$ \x873\xf8\x03\x00\x00\xf8\x03\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81[\x13\x02\x00Americ" + + "a/Knox_INUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xe3\xc9I\xd0U\x03\x00\x00U\x03\x00" + + "\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x9c\x17\x02\x00America/Grand_TurkUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01" + + "\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xcd\xc3v\xe3\xb3\x00\x00\x00\xb3\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81=\x1b\x02\x00America/Guaya" + + "quilUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x01\x05\xf3\x89\xb5\x00\x00\x00\xb5\x00\x00\x00\x0e\x00\x18\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81;\x1c\x02\x00America/GuyanaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00" + + "\x00\x00\x00\x00#\x82iS\a\x1c\x9e\x9a]\x04\x00\x00]\x04\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x818\x1d\x02\x00America/HavanaUT\x05\x00\x03\x82\x0f\x8b" + + "aux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSOKjǪ\x02\x00\x00\xaa\x02\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xdd!" + + "\x02\x00America/BahiaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSq\xc9*;\xb1" + + "\x00\x00\x00\xb1\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xce$\x02\x00America/AntiguaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04" + + "S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSU\r\xf7\xd3\xc7\x01\x00\x00\xc7\x01\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xc8%\x02\x00America/Th" + + "uleUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\v\x00\x18\x00\x00" + + "\x00\x00\x00\x00\x00\x10\x00\xe8A\xd6'\x02\x00Antarctica/UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00" + + "#\x82iS\xcfׇ\xe1\x85\x00\x00\x00\x85\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x1b(\x02\x00Antarctica/SyowaUT\x05\x00\x03\x82\x0f\x8bau" + + "x\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xc2\v\xae\b\x85\x00\x00\x00\x85\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xea(\x02\x00" + + "Antarctica/VostokUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x95\xea\x06" + + "\xd3\xc5\x00\x00\x00\xc5\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xba)\x02\x00Antarctica/DavisUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E" + + "\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSb\xb2\xaf\xf7\x13\x04\x00\x00\x13\x04\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xc9*\x02\x00Antarct" + + "ica/McMurdoUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x95{\xf3\xa9w\x03\x00\x00w" + + "\x03\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81(/\x02\x00Antarctica/PalmerUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_" + + "\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS:\xc8P7\xb1\x00\x00\x00\xb1\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xea2\x02\x00Antarctica/T" + + "rollUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSƉ\xf71\x84\x00\x00\x00\x84\x00\x00\x00\x12\x00\x18\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xe53\x02\x00Antarctica/RotheraUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02" + + "\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSn\x04\x19y\x9a\x00\x00\x00\x9a\x00\x00\x00\x19\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xb54\x02\x00Antarctica/DumontD" + + "UrvilleUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSb\xb2\xaf\xf7\x13\x04\x00\x00\x13\x04\x00\x00\x15" + + "\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xa25\x02\x00Antarctica/South_PoleUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_" + + "\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xb2\x84J]\xd0\x03\x00\x00\xd0\x03\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x04:\x02\x00Antarctica/M" + + "acquarieUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xd7N\xab\x8b\x98\x00\x00\x00\x98\x00\x00\x00" + + "\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\">\x02\x00Antarctica/MawsonUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00P" + + "K\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xddzAh\xf3\x00\x00\x00\xf3\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x05?\x02\x00Antarctica/Case" + + "yUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x18\x00\x00\x00\x00" + + "\x00\x00\x00\x10\x00\xe8AB@\x02\x00Arctic/UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xa5\x97" + + "\aĤ\x02\x00\x00\xa4\x02\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x83@\x02\x00Arctic/LongyearbyenUT\x05\x00\x03\x82\x0f\x8baux\v\x00" + + "\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xe8AtC\x02\x00Asi" + + "a/UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSѾ\xa8\xc7u\x02\x00\x00u\x02\x00\x00\f\x00\x18\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\xa0\x81\xb3C\x02\x00Asia/TbilisiUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00" + + "#\x82iS\xee\xf0BB\xff\x01\x00\x00\xff\x01\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81nF\x02\x00Asia/TaipeiUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04" + + "\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x9a\x1a\xdc\xca\xdc\x00\x00\x00\xdc\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xb2H\x02\x00Asia/" + + "CalcuttaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSS\xa5\x81e\xf7\x00\x00\x00\xf7\x00\x00\x00" + + "\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xd5I\x02\x00Asia/PontianakUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02" + + "\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xdb\xfa\xb5\xbeg\x02\x00\x00g\x02\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x14K\x02\x00Asia/AqtobeUT\x05\x00\x03\x82\x0f" + + "\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x9a\x1a\xdc\xca\xdc\x00\x00\x00\xdc\x00\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xc0" + + "M\x02\x00Asia/KolkataUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x87\xbd\xedL\xf1" + + "\x02\x00\x00\xf1\x02\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xe2N\x02\x00Asia/BarnaulUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01" + + "\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xa7f^]@\x01\x00\x00@\x01\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x19R\x02\x00Asia/KuchingU" + + "T\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSǯ\xdf\x1c\xee\x00\x00\x00\xee\x00\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\xa0\x81\x9fS\x02\x00Asia/ManilaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS" + + "?\xa7^\xfah\x02\x00\x00h\x02\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xd2T\x02\x00Asia/AtyrauUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00" + + "\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x1d?v\f\x17\x03\x00\x00\x17\x03\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\u007fW\x02\x00Asia/Maca" + + "oUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xdav\x19z\x98\x00\x00\x00\x98\x00\x00\x00\n\x00\x18\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\xa0\x81\xdaZ\x02\x00Asia/QatarUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82i" + + "S\xf9l\x03\x12\xf8\x02\x00\x00\xf8\x02\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xb6[\x02\x00Asia/IrkutskUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E" + + "\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xe8\xf0\xdeV\xe0\x04\x00\x00\xe0\x04\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xf4^\x02\x00Asia/He" + + "bronUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS]S\xbb\x12\xac\x03\x00\x00\xac\x03\x00\x00\x0e\x00\x18\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x19d\x02\x00Asia/FamagustaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00" + + "\x00\x00\x00\x00#\x82iS\x84)\r\xbd\xec\x00\x00\x00\xec\x00\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\rh\x02\x00Asia/SaigonUT\x05\x00\x03\x82\x0f\x8baux" + + "\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS*\xe4@\xa9\x89\x01\x00\x00\x89\x01\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81>i\x02\x00A" + + "sia/HarbinUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xba\xa3b\xc1R\x02\x00\x00R\x02" + + "\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\fk\x02\x00Asia/HovdUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n" + + "\x00\x00\x00\x00\x00#\x82iS\xa9z\xc8\x1f\xce\x04\x00\x00\xce\x04\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xa1m\x02\x00Asia/GazaUT\x05\x00\x03\x82\x0f\x8baux\v" + + "\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS:\x11\xea\xa2\xe5\x02\x00\x00\xe5\x02\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xb2r\x02\x00As" + + "ia/OmskUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS?Y\xaf\x19\xe7\x00\x00\x00\xe7\x00\x00\x00\n" + + "\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xdau\x02\x00Asia/DaccaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00" + + "\x00\x00\x00#\x82iSB\x1d\xc6\x1b\x85\x00\x00\x00\x85\x00\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x05w\x02\x00Asia/UrumqiUT\x05\x00\x03\x82\x0f\x8baux\v" + + "\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS?Y\xaf\x19\xe7\x00\x00\x00\xe7\x00\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xcfw\x02\x00As" + + "ia/DhakaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSE\t\xfa-\a\x03\x00\x00\a\x03\x00\x00" + + "\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xfax\x02\x00Asia/Hong_KongUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02" + + "\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\\\x91\x87\xbb\xf7\x00\x00\x00\xf7\x00\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81I|\x02\x00Asia/ColomboUT\x05\x00\x03\x82" + + "\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x88\xf6C\x84\x98\x00\x00\x00\x98\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81" + + "\x86}\x02\x00Asia/VientianeUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSB\x1d" + + "\xc6\x1b\x85\x00\x00\x00\x85\x00\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81f~\x02\x00Asia/KashgarUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04" + + "S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS)p\x1cX\xf1\x02\x00\x00\xf1\x02\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x811\u007f\x02\x00Asia/Novos" + + "ibirskUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xe4_P\x18\xef\x02\x00\x00\xef\x02\x00\x00\f\x00" + + "\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81l\x82\x02\x00Asia/MagadanUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00" + + "\x00\x00\x00\x00#\x82iS\x8bSnT\xa1\x00\x00\x00\xa1\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xa1\x85\x02\x00Asia/KathmanduUT\x05\x00\x03\x82\x0f\x8b" + + "aux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x88\xf6C\x84\x98\x00\x00\x00\x98\x00\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x8a\x86" + + "\x02\x00Asia/BangkokUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xcfׇ\xe1\x85\x00" + + "\x00\x00\x85\x00\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81h\x87\x02\x00Asia/RiyadhUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00P" + + "K\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSΒ\x1a\x8c\xaa\x00\x00\x00\xaa\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x812\x88\x02\x00Asia/DiliUT\x05\x00\x03\x82" + + "\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSL\xe0\x91y\xe5\x02\x00\x00\xe5\x02\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81" + + "\x1f\x89\x02\x00Asia/KrasnoyarskUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS" + + "\x83g\x95M\a\x03\x00\x00\a\x03\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81N\x8c\x02\x00Asia/KhandygaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E" + + "\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x81z&\x80k\x02\x00\x00k\x02\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x9c\x8f\x02\x00Asia/Ch" + + "oibalsanUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSw\x86\x8d^\x03\x03\x00\x00\x03\x03\x00\x00" + + "\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81P\x92\x02\x00Asia/Ust-NeraUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e" + + "\x03\n\x00\x00\x00\x00\x00#\x82iSe\x1bb2w\x01\x00\x00w\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x9a\x95\x02\x00Asia/AshkhabadUT\x05\x00\x03" + + "\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS'\xe2\\\xff\x9f\x00\x00\x00\x9f\x00\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0" + + "\x81Y\x97\x02\x00Asia/KabulUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xa1\xfax\x98g" + + "\x02\x00\x00g\x02\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81<\x98\x02\x00Asia/QostanayUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_" + + "\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xb2\xe27Yn\x01\x00\x00n\x01\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xea\x9a\x02\x00Asia/Tashken" + + "tUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS*\xe4@\xa9\x89\x01\x00\x00\x89\x01\x00\x00\r\x00\x18\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\xa0\x81\x9f\x9c\x02\x00Asia/ShanghaiUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00" + + "#\x82iS\xdav\x19z\x98\x00\x00\x00\x98\x00\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81o\x9e\x02\x00Asia/BahrainUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01" + + "\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSʇ{_\xbb\x00\x00\x00\xbb\x00\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81M\x9f\x02\x00Asia" + + "/RangoonUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS*\xe4@\xa9\x89\x01\x00\x00\x89\x01\x00\x00" + + "\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81N\xa0\x02\x00Asia/ChungkingUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02" + + "\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS;\u007fP\x8d\xd4\a\x00\x00\xd4\a\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x1f\xa2\x02\x00Asia/TehranUT\x05\x00\x03\x82\x0f" + + "\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\aW\x10Ѱ\x04\x00\x00\xb0\x04\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x818" + + "\xaa\x02\x00Asia/IstanbulUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xed\x8c\xf1\x91" + + "\x85\x00\x00\x00\x85\x00\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81/\xaf\x02\x00Asia/DubaiUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00" + + "PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSb\xadű\xf8\x00\x00\x00\xf8\x00\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xf8\xaf\x02\x00Asia/JakartaUT" + + "\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xed\x8c\xf1\x91\x85\x00\x00\x00\x85\x00\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\xa0\x816\xb1\x02\x00Asia/MuscatUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xef" + + "\\\xf4q\x17\x04\x00\x00\x17\x04\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x00\xb2\x02\x00Asia/DamascusUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00" + + "\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSO\xb0\x03\xe9\xe5\x02\x00\x00\xe5\x02\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81^\xb6\x02\x00Asia/Yak" + + "utskUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSj$\xcd\xf4\x9a\x00\x00\x00\x9a\x00\x00\x00\f\x00\x18\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x89\xb9\x02\x00Asia/ThimphuUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00" + + "\x00\x00#\x82iSw\rD\an\x01\x00\x00n\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81i\xba\x02\x00Asia/SamarkandUT\x05\x00\x03\x82\x0f\x8bau" + + "x\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSV\xe0\xe7!\xe7\x02\x00\x00\xe7\x02\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x1f\xbc\x02\x00" + + "Asia/AnadyrUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSd%\x05\xd8\xe6\x02\x00\x00\xe6" + + "\x02\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81K\xbf\x02\x00Asia/VladivostokUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01" + + "\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSj$\xcd\xf4\x9a\x00\x00\x00\x9a\x00\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81{\xc2\x02\x00Asia/ThimbuUT" + + "\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS恸\x1e\x00\x01\x00\x00\x00\x01\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\xa0\x81Z\xc3\x02\x00Asia/Kuala_LumpurUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00" + + "\x00#\x82iS\x06\xaa>\xa8\x00\x01\x00\x00\x00\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xa5\xc4\x02\x00Asia/SingaporeUT\x05\x00\x03\x82\x0f\x8baux" + + "\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS[u\x99q\xf1\x02\x00\x00\xf1\x02\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xed\xc5\x02\x00A" + + "sia/TomskUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSe\x1bb2w\x01\x00\x00w\x01\x00" + + "\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\"\xc9\x02\x00Asia/AshgabatUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02" + + "\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSʇ{_\xbb\x00\x00\x00\xbb\x00\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xe0\xca\x02\x00Asia/YangonUT\x05\x00\x03\x82\x0f" + + "\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x8a\xc1\x1eB\xb7\x00\x00\x00\xb7\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xe0" + + "\xcb\x02\x00Asia/PyongyangUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x9a\xea\x18" + + "\xd4\xf8\x02\x00\x00\xf8\x02\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xdf\xcc\x02\x00Asia/YekaterinburgUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04" + + "\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x02\xf4\xaeg\xd5\x00\x00\x00\xd5\x00\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81#\xd0\x02\x00Asia/" + + "TokyoUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xb2\xb9\xf4\xb6R\x02\x00\x00R\x02\x00\x00\x10\x00\x18" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81<\xd1\x02\x00Asia/UlaanbaatarUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e" + + "\x03\n\x00\x00\x00\x00\x00#\x82iS9Y\xb7\xf1\n\x01\x00\x00\n\x01\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xd8\xd3\x02\x00Asia/KarachiUT\x05\x00\x03\x82\x0f" + + "\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xab\xcd\xdf\x05\xee\x02\x00\x00\xee\x02\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81(" + + "\xd5\x02\x00Asia/ChitaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xf0\x9cf>\xd7\x02\x00" + + "\x00\xd7\x02\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81Z\xd8\x02\x00Asia/KamchatkaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01" + + "\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x03R\xda\xedU\x02\x00\x00U\x02\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81y\xdb\x02\x00Asia/NicosiaU" + + "T\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS`\xc9\xd4\\\xbe\x00\x00\x00\xbe\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\xa0\x81\x14\xde\x02\x00Asia/MakassarUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82" + + "iS0]*\x1bj\x02\x00\x00j\x02\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x19\xdf\x02\x00Asia/BishkekUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14" + + "E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xd5ΜGp\x02\x00\x00p\x02\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xc9\xe1\x02\x00Asia/Q" + + "yzylordaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x02\x95-\xad\xc4\x02\x00\x00\xc4\x02\x00\x00" + + "\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x81\xe4\x02\x00Asia/YerevanUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03" + + "\n\x00\x00\x00\x00\x00#\x82iS\xa4Zߐ\xe6\x02\x00\x00\xe6\x02\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x8b\xe7\x02\x00Asia/SrednekolymskUT" + + "\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xcfׇ\xe1\x85\x00\x00\x00\x85\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\xa0\x81\xbd\xea\x02\x00Asia/AdenUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS*\xe4@" + + "\xa9\x89\x01\x00\x00\x89\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x85\xeb\x02\x00Asia/ChongqingUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00" + + "\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xb2\xb9\xf4\xb6R\x02\x00\x00R\x02\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81V\xed\x02\x00Asia/Ulan" + + "_BatorUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x17✳2\x04\x00\x002\x04\x00\x00\x0e\x00" + + "\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xf1\xef\x02\x00Asia/JerusalemUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03" + + "\n\x00\x00\x00\x00\x00#\x82iS\xc7\x11\xe1[\xdc\x02\x00\x00\xdc\x02\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81k\xf4\x02\x00Asia/BeirutUT\x05\x00\x03\x82\x0f\x8ba" + + "ux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS`\xc9\xd4\\\xbe\x00\x00\x00\xbe\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x8c\xf7\x02" + + "\x00Asia/Ujung_PandangUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x9e" + + "\x88|`\x9a\x03\x00\x00\x9a\x03\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x96\xf8\x02\x00Asia/AmmanUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S" + + "_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xd7e&uv\x02\x00\x00v\x02\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81t\xfc\x02\x00Asia/Baghda" + + "dUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS.>[K\xab\x00\x00\x00\xab\x00\x00\x00\r\x00\x18\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\xa0\x810\xff\x02\x00Asia/JayapuraUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00" + + "#\x82iST\x81\x18G^\x02\x00\x00^\x02\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\"\x00\x03\x00Asia/AqtauUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14" + + "E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS)\x15II\xf3\x02\x00\x00\xf3\x02\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xc4\x02\x03\x00Asia/S" + + "akhalinUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x03\x87\xb3<\xe8\x02\x00\x00\xe8\x02\x00\x00\t" + + "\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xfe\x05\x03\x00Asia/BakuUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00" + + "\x00\x00#\x82iS&\xe9\xd1\xd8q\x02\x00\x00q\x02\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81)\t\x03\x00Asia/OralUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04" + + "\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x88\xf6C\x84\x98\x00\x00\x00\x98\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xdd\v\x03\x00Asia/" + + "Phnom_PenhUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS's\x96\x1en\x01\x00\x00n\x01" + + "\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xbe\f\x03\x00Asia/DushanbeUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01" + + "\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x84)\r\xbd\xec\x00\x00\x00\xec\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81s\x0e\x03\x00Asia/Ho_Chi_MinhU" + + "T\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xc7X,Y\x9f\x01\x00\x00\x9f\x01\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\xa0\x81\xa9\x0f\x03\x00Asia/SeoulUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x8b" + + "SnT\xa1\x00\x00\x00\xa1\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x8c\x11\x03\x00Asia/KatmanduUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00" + + "\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSS\xdd\\2a\x02\x00\x00a\x02\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81t\x12\x03\x00Asia/Alm" + + "atyUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSy\x19\xe0N\x9a\x00\x00\x00\x9a\x00\x00\x00\v\x00\x18\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x1a\x15\x03\x00Asia/BruneiUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00" + + "#\x82iS\x17✳2\x04\x00\x002\x04\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xf9\x15\x03\x00Asia/Tel_AvivUT\x05\x00\x03\x82\x0f\x8baux\v\x00" + + "\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x1d?v\f\x17\x03\x00\x00\x17\x03\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81r\x1a\x03\x00Asi" + + "a/MacauUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x8a\x9a\x90\xf7\xd6\x02\x00\x00\xd6\x02\x00\x00\x11" + + "\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xcd\x1d\x03\x00Asia/NovokuznetskUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK" + + "\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xcfׇ\xe1\x85\x00\x00\x00\x85\x00\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xee \x03\x00Asia/KuwaitUT\x05\x00\x03" + + "\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xe8" + + "A\xb8!\x03\x00Atlantic/UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSm\xbd\x10k\xf1\x02" + + "\x00\x00\xf1\x02\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xfb!\x03\x00Atlantic/ReykjavikUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00" + + "\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xb7\x0e\xbdm\xb9\x01\x00\x00\xb9\x01\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x818%\x03\x00Atlantic" + + "/FaeroeUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xe8\x8dY\x80\xad\x05\x00\x00\xad\x05\x00\x00\x0f" + + "\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81:'\x03\x00Atlantic/AzoresUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02" + + "\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\u0097N\xad\xaf\x00\x00\x00\xaf\x00\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x810-\x03\x00Atlantic/Cape_Verd" + + "eUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSl&\x04\x99\x00\x04\x00\x00\x00\x04\x00\x00\x10\x00\x18\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\xa0\x81,.\x03\x00Atlantic/BermudaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00" + + "\x00\x00\x00#\x82iS\xb7\x0e\xbdm\xb9\x01\x00\x00\xb9\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81v2\x03\x00Atlantic/FaroeUT\x05\x00\x03\x82\x0f\x8ba" + + "ux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS1)7\xad\xad\x05\x00\x00\xad\x05\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81w4\x03" + + "\x00Atlantic/MadeiraUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xa5\x97\a" + + "Ĥ\x02\x00\x00\xa4\x02\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81n:\x03\x00Atlantic/Jan_MayenUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04" + + "\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xe7\xcf^\xb0\x15\x03\x00\x00\x15\x03\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81^=\x03\x00Atlan" + + "tic/StanleyUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xf1\b{\x87\x82\x00\x00\x00\x82" + + "\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xbd@\x03\x00Atlantic/St_HelenaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S" + + "_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xaf|7\xb3\xde\x01\x00\x00\xde\x01\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x8bA\x03\x00Atlantic/Ca" + + "naryUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x0f-\xadׄ\x00\x00\x00\x84\x00\x00\x00\x16\x00\x18\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xb2C\x03\x00Atlantic/South_GeorgiaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00" + + "PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xe8A\x86D\x03\x00Australia/UT\x05\x00" + + "\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS?\x95\xbd\x12E\x01\x00\x00E\x01\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\xa0\x81\xcaD\x03\x00Australia/LindemanUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00" + + "#\x82iS3\xba\xde\xd3!\x01\x00\x00!\x01\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81[F\x03\x00Australia/QueenslandUT\x05\x00\x03\x82" + + "\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSϻ\xca\x1a2\x01\x00\x002\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81" + + "\xcaG\x03\x00Australia/WestUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xa2\xdc" + + "\xba\xca:\x01\x00\x00:\x01\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81DI\x03\x00Australia/EuclaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E" + + "\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x9b\xe1\xc1\xa9\x88\x03\x00\x00\x88\x03\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xc7J\x03\x00Austral" + + "ia/VictoriaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSX\xb9\x9ap\x88\x03\x00\x00\x88" + + "\x03\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x9bN\x03\x00Australia/SydneyUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01" + + "\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSE\xf2\xe6Z\xeb\x03\x00\x00\xeb\x03\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81mR\x03\x00Australia/Hob" + + "artUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS3\xba\xde\xd3!\x01\x00\x00!\x01\x00\x00\x12\x00\x18\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xa2V\x03\x00Australia/BrisbaneUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e" + + "\x03\n\x00\x00\x00\x00\x00#\x82iSo3\xdaR\xb4\x02\x00\x00\xb4\x02\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x0fX\x03\x00Australia/Lord_Howe" + + "UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSE\xf2\xe6Z\xeb\x03\x00\x00\xeb\x03\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\xa0\x81\x10[\x03\x00Australia/CurrieUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00" + + "\x00\x00#\x82iS\x8ff~ՙ\x03\x00\x00\x99\x03\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81E_\x03\x00Australia/SouthUT\x05\x00\x03\x82\x0f\x8ba" + + "ux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSX\xb9\x9ap\x88\x03\x00\x00\x88\x03\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81'c\x03" + + "\x00Australia/CanberraUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x8f" + + "f~ՙ\x03\x00\x00\x99\x03\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xfbf\x03\x00Australia/AdelaideUT\x05\x00\x03\x82\x0f\x8baux\v\x00" + + "\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xc8R\x1a\x1b\xea\x00\x00\x00\xea\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xe0j\x03\x00Aus" + + "tralia/NorthUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSϻ\xca\x1a2\x01\x00\x00" + + "2\x01\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x13l\x03\x00Australia/PerthUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01" + + "\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xbd\xca#\u007f\xad\x03\x00\x00\xad\x03\x00\x00\x15\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x8em\x03\x00Australia/Bro" + + "ken_HillUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSX\xb9\x9ap\x88\x03\x00\x00\x88\x03\x00\x00" + + "\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x8aq\x03\x00Australia/ACTUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e" + + "\x03\n\x00\x00\x00\x00\x00#\x82iS\xbd\xca#\u007f\xad\x03\x00\x00\xad\x03\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81Yu\x03\x00Australia/Yancowinn" + + "aUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xc8R\x1a\x1b\xea\x00\x00\x00\xea\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\xa0\x81Ty\x03\x00Australia/DarwinUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00" + + "\x00\x00\x00#\x82iSE\xf2\xe6Z\xeb\x03\x00\x00\xeb\x03\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x88z\x03\x00Australia/TasmaniaUT\x05\x00\x03" + + "\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x9b\xe1\xc1\xa9\x88\x03\x00\x00\x88\x03\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0" + + "\x81\xbf~\x03\x00Australia/MelbourneUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00" + + "#\x82iSo3\xdaR\xb4\x02\x00\x00\xb4\x02\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x94\x82\x03\x00Australia/LHIUT\x05\x00\x03\x82\x0f\x8baux\v\x00" + + "\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSX\xb9\x9ap\x88\x03\x00\x00\x88\x03\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x8f\x85\x03\x00Aus" + + "tralia/NSWUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xe8A^\x89\x03\x00Brazil/UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00" + + "\x00\x00\x00#\x82iSa\xcb'\xe9\x9c\x01\x00\x00\x9c\x01\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x9f\x89\x03\x00Brazil/WestUT\x05\x00\x03\x82\x0f\x8baux\v" + + "\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xb7-2f\xe4\x01\x00\x00\xe4\x01\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x80\x8b\x03\x00Br" + + "azil/DeNoronhaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSg\xf5K\x89\xa2\x01" + + "\x00\x00\xa2\x01\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xae\x8d\x03\x00Brazil/AcreUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00P" + + "K\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x9d?\xdfڸ\x03\x00\x00\xb8\x03\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x95\x8f\x03\x00Brazil/EastUT\x05\x00" + + "\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00" + + "\xe8A\x92\x93\x03\x00Canada/UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS{\a\a\xdc\xca\x03\x00" + + "\x00\xca\x03\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81ӓ\x03\x00Canada/MountainUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_" + + "\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS~\xb2\x0e\x19V\a\x00\x00V\a\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xe6\x97\x03\x00Canada/Newfo" + + "undlandUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS):\x17-\x88\x06\x00\x00\x88\x06\x00\x00\x0f" + + "\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x89\x9f\x03\x00Canada/AtlanticUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02" + + "\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xc1Ȇ\x90\x05\x04\x00\x00\x05\x04\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81Z\xa6\x03\x00Canada/YukonUT\x05\x00\x03\x82" + + "\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSӿ\x92\xbc\xb5\x06\x00\x00\xb5\x06\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81" + + "\xa5\xaa\x03\x00Canada/EasternUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSU9" + + "#\xbe2\x05\x00\x002\x05\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xa2\xb1\x03\x00Canada/PacificUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00" + + "\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS?_p\x99\x0e\x05\x00\x00\x0e\x05\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x1c\xb7\x03\x00Canada/C" + + "entralUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\u0096dK~\x02\x00\x00~\x02\x00\x00\x13\x00" + + "\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81r\xbc\x03\x00Canada/SaskatchewanUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00P" + + "K\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xe6\x9aM\xbem\x02\x00\x00m\x02\x00\x00\x03\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81=\xbf\x03\x00CETUT\x05\x00\x03\x82\x0f\x8baux\v" + + "\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xe8A\xe7\xc1\x03\x00Ch" + + "ile/UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS[Sp\x90\x02\x05\x00\x00\x02\x05\x00\x00\x11\x00\x18\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81'\xc2\x03\x00Chile/ContinentalUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e" + + "\x03\n\x00\x00\x00\x00\x00#\x82iS\xee\xd0\x1cYN\x04\x00\x00N\x04\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81t\xc7\x03\x00Chile/EasterIslandU" + + "T\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS<\x8b\x99\x1e\xb7\x03\x00\x00\xb7\x03\x00\x00\a\x00\x18\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\xa0\x81\x0e\xcc\x03\x00CST6CDTUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\a\x1c\x9e\x9a" + + "]\x04\x00\x00]\x04\x00\x00\x04\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x06\xd0\x03\x00CubaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03" + + "\n\x00\x00\x00\x00\x00#\x82iS`l\x8d~\xf1\x01\x00\x00\xf1\x01\x00\x00\x03\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xa1\xd4\x03\x00EETUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E" + + "\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x12tnj\xfc\x04\x00\x00\xfc\x04\x00\x00\x05\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xcf\xd6\x03\x00EgyptUT" + + "\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x9a\v\xf9/\xd8\x05\x00\x00\xd8\x05\x00\x00\x04\x00\x18\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\xa0\x81\n\xdc\x03\x00EireUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iStX\xbe\xe4o\x00\x00\x00" + + "o\x00\x00\x00\x03\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81 \xe2\x03\x00ESTUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00" + + "\x00#\x82iS\xe7/\xebT\xb7\x03\x00\x00\xb7\x03\x00\x00\a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xcc\xe2\x03\x00EST5EDTUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00" + + "\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xe8A\xc4\xe6\x03\x00Etc/UT\x05\x00" + + "\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xb2\xab\xd1Is\x00\x00\x00s\x00\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\xa0\x81\x02\xe7\x03\x00Etc/GMT-11UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xa9{\xa2q" + + "q\x00\x00\x00q\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xb9\xe7\x03\x00Etc/GMT+2UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00P" + + "K\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x9f.\xe4xo\x00\x00\x00o\x00\x00\x00\a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81m\xe8\x03\x00Etc/UCTUT\x05\x00\x03\x82\x0f\x8b" + + "aux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xf7\x1ac\xc3r\x00\x00\x00r\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x1d\xe9" + + "\x03\x00Etc/GMT-1UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSP\xda\xfa\x03o\x00\x00\x00o" + + "\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xd2\xe9\x03\x00Etc/GMT+0UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03" + + "\n\x00\x00\x00\x00\x00#\x82iS\"\xf8\x8f/q\x00\x00\x00q\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x84\xea\x03\x00Etc/GMT+8UT\x05\x00\x03\x82\x0f\x8baux" + + "\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xd4X\x9b\xf3q\x00\x00\x00q\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x818\xeb\x03\x00E" + + "tc/GMT+5UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x9f.\xe4xo\x00\x00\x00o\x00\x00\x00" + + "\b\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xec\xeb\x03\x00Etc/ZuluUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00" + + "\x00\x00#\x82iSJ0p-r\x00\x00\x00r\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x9d\xec\x03\x00Etc/GMT-7UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04" + + "\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xd0\xfaFDq\x00\x00\x00q\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81R\xed\x03\x00Etc/G" + + "MT+4UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xf7\x19s\x81s\x00\x00\x00s\x00\x00\x00\n\x00\x18\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x06\xee\x03\x00Etc/GMT-12UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00" + + "#\x82iS\x9f.\xe4xo\x00\x00\x00o\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xbd\xee\x03\x00Etc/UniversalUT\x05\x00\x03\x82\x0f\x8baux\v\x00" + + "\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x9c\xfcm\x99r\x00\x00\x00r\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81s\xef\x03\x00Etc" + + "/GMT-3UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSP\xda\xfa\x03o\x00\x00\x00o\x00\x00\x00\a\x00" + + "\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81(\xf0\x03\x00Etc/GMTUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#" + + "\x82iS\xfc\x19@\xb9r\x00\x00\x00r\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xd8\xf0\x03\x00Etc/GMT-9UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00" + + "\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xd9|\xbd7s\x00\x00\x00s\x00\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x8d\xf1\x03\x00Etc/GMT-" + + "10UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x84\x19\xb3\tq\x00\x00\x00q\x00\x00\x00\t\x00\x18\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\xa0\x81D\xf2\x03\x00Etc/GMT+9UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82i" + + "S!\xd6~wr\x00\x00\x00r\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xf8\xf2\x03\x00Etc/GMT-5UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04" + + "S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSj\xd5d\xb0r\x00\x00\x00r\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xad\xf3\x03\x00Etc/GMT-6U" + + "T\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x90`N\xe8s\x00\x00\x00s\x00\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\xa0\x81b\xf4\x03\x00Etc/GMT-13UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSP" + + "\xda\xfa\x03o\x00\x00\x00o\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x19\xf5\x03\x00Etc/GreenwichUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00" + + "\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS5\xb8\xe8\x86q\x00\x00\x00q\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xcf\xf5\x03\x00Etc/GMT+" + + "1UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSe\xcb\xe9Qq\x00\x00\x00q\x00\x00\x00\t\x00\x18\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\xa0\x81\x83\xf6\x03\x00Etc/GMT+3UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS" + + "\x9f.\xe4xo\x00\x00\x00o\x00\x00\x00\a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x817\xf7\x03\x00Etc/UTCUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01" + + "\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x8e\x1569r\x00\x00\x00r\x00\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xe7\xf7\x03\x00Etc/GMT+10UT\x05" + + "\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSP\xda\xfa\x03o\x00\x00\x00o\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\xa0\x81\x9d\xf8\x03\x00Etc/GMT-0UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x84+\x9a$" + + "q\x00\x00\x00q\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81O\xf9\x03\x00Etc/GMT+7UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00P" + + "K\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xe5\xf38cr\x00\x00\x00r\x00\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x03\xfa\x03\x00Etc/GMT+12UT\x05\x00\x03" + + "\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSH\x9b\xd1\x04q\x00\x00\x00q\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0" + + "\x81\xb9\xfa\x03\x00Etc/GMT+6UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xc5\x18\xb6\xfbr\x00" + + "\x00\x00r\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81m\xfb\x03\x00Etc/GMT-8UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01" + + "\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS)\xb9\xbe\x9dr\x00\x00\x00r\x00\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\"\xfc\x03\x00Etc/GMT+11UT\x05\x00\x03\x82\x0f" + + "\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS,{\xdc;s\x00\x00\x00s\x00\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xd8" + + "\xfc\x03\x00Etc/GMT-14UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSP\xda\xfa\x03o\x00\x00" + + "\x00o\x00\x00\x00\b\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x8f\xfd\x03\x00Etc/GMT0UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e" + + "\x03\n\x00\x00\x00\x00\x00#\x82iSk\x19\xfe垛\x03\x00\x00\x9b\x03\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81ـ\x04\x00E" + + "urope/WarsawUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSIo\x11{\xd3\x02\x00\x00" + + "\xd3\x02\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xbb\x84\x04\x00Europe/BratislavaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S" + + "_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xd9L\xf6\xf7\xf1\x01\x00\x00\xf1\x01\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81ه\x04\x00Europe/Stoc" + + "kholmUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSk\xa4,\xb6?\x06\x00\x00?\x06\x00\x00\x12\x00\x18" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x14\x8a\x04\x00Europe/Isle_of_ManUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01" + + "\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSk\xa4,\xb6?\x06\x00\x00?\x06\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x9f\x90\x04\x00Europe/GuernseyUT" + + "\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x03R\xda\xedU\x02\x00\x00U\x02\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\xa0\x81'\x97\x04\x00Europe/NicosiaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82" + + "iS\xc9\a\xa0\xe1/\x04\x00\x00/\x04\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81ę\x04\x00Europe/AmsterdamUT\x05\x00\x03\x82\x0f\x8baux\v" + + "\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSo\xbc\x831O\x04\x00\x00O\x04\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81=\x9e\x04\x00Eu" + + "rope/BrusselsUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xe1C\xf9\xa1\xde\x01\x00" + + "\x00\xde\x01\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81բ\x04\x00Europe/BelgradeUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_" + + "\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSZ\x05wג\x02\x00\x00\x92\x02\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xfc\xa4\x04\x00Europe/Vienn" + + "aUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xe1C\xf9\xa1\xde\x01\x00\x00\xde\x01\x00\x00\x0f\x00\x18\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\xa0\x81է\x04\x00Europe/SarajevoUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00" + + "\x00\x00#\x82iS\xcb*j\x8f\xaa\x02\x00\x00\xaa\x02\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xfc\xa9\x04\x00Europe/AthensUT\x05\x00\x03\x82\x0f\x8baux" + + "\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xc7\xf5\x94\xdaQ\x04\x00\x00Q\x04\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xed\xac\x04\x00E" + + "urope/ParisUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xe0\xfe\x83\xe5\xcd\x02\x00\x00\xcd" + + "\x02\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x84\xb1\x04\x00Europe/KirovUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01" + + "\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xea\xc48\xde\\\x02\x00\x00\\\x02\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x97\xb4\x04\x00Europe/TiraneUT\x05\x00" + + "\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xe1C\xf9\xa1\xde\x01\x00\x00\xde\x01\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\xa0\x81:\xb7\x04\x00Europe/PodgoricaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82" + + "iS\xe5\xc8X\xa7\xe1\x01\x00\x00\xe1\x01\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81b\xb9\x04\x00Europe/HelsinkiUT\x05\x00\x03\x82\x0f\x8baux\v\x00" + + "\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSk\xa4,\xb6?\x06\x00\x00?\x06\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x8c\xbb\x04\x00Eur" + + "ope/JerseyUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS&S\x03\t\xae\x05\x00\x00\xae\x05" + + "\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x12\xc2\x04\x00Europe/LisbonUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01" + + "\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS8I\xdeN%\x02\x00\x00%\x02\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\a\xc8\x04\x00Europe/KievUT\x05\x00\x03\x82" + + "\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSI\xb8\xbc\xd3\xf3\x02\x00\x00\xf3\x02\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81" + + "q\xca\x04\x00Europe/TiraspolUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSh" + + "\xa5J[\xa0\x03\x00\x00\xa0\x03\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xad\xcd\x04\x00Europe/MaltaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00" + + "\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x95\xb4\x9e\xe7\xb3\x03\x00\x00\xb3\x03\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x93\xd1\x04\x00Europe/Sa" + + "n_MarinoUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xe6Kf\xab\xfe\x02\x00\x00\xfe\x02\x00\x00" + + "\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x91\xd5\x04\x00Europe/BudapestUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01" + + "\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xa5\x97\aĤ\x02\x00\x00\xa4\x02\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xd8\xd8\x04\x00Europe/OsloUT\x05\x00\x03\x82" + + "\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xab\x80c$q\x00\x00\x00q\x00\x00\x00\a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81" + + "\xc1\xdb\x04\x00FactoryUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSk\xa4,\xb6?\x06\x00\x00?" + + "\x06\x00\x00\x02\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81s\xdc\x04\x00GBUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#" + + "\x82iSk\xa4,\xb6?\x06\x00\x00?\x06\x00\x00\a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xee\xe2\x04\x00GB-EireUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04" + + "S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSP\xda\xfa\x03o\x00\x00\x00o\x00\x00\x00\x03\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81n\xe9\x04\x00GMTUT\x05\x00\x03\x82\x0f" + + "\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSP\xda\xfa\x03o\x00\x00\x00o\x00\x00\x00\x05\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x1a" + + "\xea\x04\x00GMT+0UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSP\xda\xfa\x03o\x00\x00\x00o\x00\x00\x00" + + "\x05\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xc8\xea\x04\x00GMT-0UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#" + + "\x82iSP\xda\xfa\x03o\x00\x00\x00o\x00\x00\x00\x04\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81v\xeb\x04\x00GMT0UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01" + + "\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSP\xda\xfa\x03o\x00\x00\x00o\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81#\xec\x04\x00GreenwichUT\x05\x00" + + "\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSE\t\xfa-\a\x03\x00\x00\a\x03\x00\x00\b\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + "\xa0\x81\xd5\xec\x04\x00HongkongUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS=\xf7\xfawp\x00" + + "\x00\x00p\x00\x00\x00\x03\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x1e\xf0\x04\x00HSTUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00" + + "\x00\x00\x00#\x82iSm\xbd\x10k\xf1\x02\x00\x00\xf1\x02\x00\x00\a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xcb\xf0\x04\x00IcelandUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14" + + "E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xe8A\xfd\xf3\x04\x00Indian" + + "/UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSͲ\xfb\xf6\x8c\x00\x00\x00\x8c\x00\x00\x00\f\x00\x18\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\xa0\x81>\xf4\x04\x00Indian/CocosUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#" + + "\x82iS\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x10\xf5\x04\x00Indian/AntananarivoUT\x05\x00\x03\x82\x0f\x8b" + + "aux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSx\xb0W\x14\x98\x00\x00\x00\x98\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x1c\xf6" + + "\x04\x00Indian/ChagosUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xb4\x8d\x98ƿ" + + "\x00\x00\x00\xbf\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xfb\xf6\x04\x00Indian/MayotteUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S" + + "_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS$l=҅\x00\x00\x00\x85\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x02\xf8\x04\x00Indian/Chri" + + "stmasUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xb9\xb2Z\xac\x98\x00\x00\x00\x98\x00\x00\x00\x0f\x00\x18" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xd1\xf8\x04\x00Indian/MaldivesUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03" + + "\n\x00\x00\x00\x00\x00#\x82iS\xb4\x8d\x98ƿ\x00\x00\x00\xbf\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xb2\xf9\x04\x00Indian/ComoroUT\x05\x00\x03\x82\x0f" + + "\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x96\xed=\x98\xb3\x00\x00\x00\xb3\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xb8" + + "\xfa\x04\x00Indian/MauritiusUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSa" + + "\x85jo\x85\x00\x00\x00\x85\x00\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xb5\xfb\x04\x00Indian/MaheUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04" + + "S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xb8K\xabυ\x00\x00\x00\x85\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\u007f\xfc\x04\x00Indian/Ker" + + "guelenUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSy(\xb6\x8f\x85\x00\x00\x00\x85\x00\x00\x00\x0e\x00" + + "\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81N\xfd\x04\x00Indian/ReunionUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03" + + "\n\x00\x00\x00\x00\x00#\x82iS;\u007fP\x8d\xd4\a\x00\x00\xd4\a\x00\x00\x04\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x1b\xfe\x04\x00IranUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14" + + "E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x17✳2\x04\x00\x002\x04\x00\x00\x06\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81-\x06\x05\x00Israel" + + "UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS%J\xd5\xebS\x01\x00\x00S\x01\x00\x00\a\x00\x18\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\xa0\x81\x9f\n\x05\x00JamaicaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x02\xf4\xae" + + "g\xd5\x00\x00\x00\xd5\x00\x00\x00\x05\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x813\f\x05\x00JapanUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02" + + "\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xf6\xe8]*\xdb\x00\x00\x00\xdb\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81G\r\x05\x00KwajaleinUT\x05\x00\x03\x82\x0f\x8ba" + + "ux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS_\u007f2[\xaf\x01\x00\x00\xaf\x01\x00\x00\x05\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81e\x0e\x05" + + "\x00LibyaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xfe\x9d\x1b\xc9m\x02\x00\x00m\x02\x00\x00\x03\x00" + + "\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81S\x10\x05\x00METUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x00" + + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xe8A\xfd\x12\x05\x00Mexico/UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00" + + "PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xd6\xe1Հ\x9c\x01\x00\x00\x9c\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81>\x13\x05\x00Mexico/General" + + "UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS8\xcdZ\x05o\x01\x00\x00o\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\xa0\x81\"\x15\x05\x00Mexico/BajaSurUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00" + + "#\x82iS\xd0v\x01\x8a\x01\x04\x00\x00\x01\x04\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xd9\x16\x05\x00Mexico/BajaNorteUT\x05\x00\x03\x82\x0f\x8bau" + + "x\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xf5\x8d\x99\x92o\x00\x00\x00o\x00\x00\x00\x03\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81$\x1b\x05\x00" + + "MSTUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xe6h\xcac\xb7\x03\x00\x00\xb7\x03\x00\x00\a\x00\x18\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xd0\x1b\x05\x00MST7MDTUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS" + + "V\x80\x94@\x12\x04\x00\x00\x12\x04\x00\x00\x06\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xc8\x1f\x05\x00NavajoUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00" + + "PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSb\xb2\xaf\xf7\x13\x04\x00\x00\x13\x04\x00\x00\x02\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x1a$\x05\x00NZUT\x05\x00\x03\x82\x0f\x8baux\v" + + "\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x96\xc5FF(\x03\x00\x00(\x03\x00\x00\a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81i(\x05\x00NZ" + + "-CHATUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b\x00\x18" + + "\x00\x00\x00\x00\x00\x00\x00\x10\x00\xe8A\xd2+\x05\x00Pacific/UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#" + + "\x82iS\x91\xd60\f\x9a\x00\x00\x00\x9a\x00\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x14,\x05\x00Pacific/NiueUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04" + + "\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSt\xca{e\x92\x00\x00\x00\x92\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xf4,\x05\x00Pacif" + + "ic/MidwayUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x80\xf8vܔ\x00\x00\x00\x94\x00\x00" + + "\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xce-\x05\x00Pacific/PalauUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02" + + "\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x97F\x91\xb3\xed\x00\x00\x00\xed\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xa9.\x05\x00Pacific/TongatapuU" + + "T\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xec =\x89\xac\x00\x00\x00\xac\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\xa0\x81\xe1/\x05\x00Pacific/EnderburyUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00" + + "\x00\x00#\x82iS\x9e\u007f\xab\x95V\x01\x00\x00V\x01\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xd80\x05\x00Pacific/EfateUT\x05\x00\x03\x82\x0f\x8baux" + + "\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x8a|\xdcU\x99\x00\x00\x00\x99\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81u2\x05\x00P" + + "acific/FakaofoUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xea\xc1\xdaυ\x00" + + "\x00\x00\x85\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81W3\x05\x00Pacific/TahitiUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_" + + "\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS߃\xa0_\x86\x00\x00\x00\x86\x00\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81$4\x05\x00Pacific/Wake" + + "UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSt\xca{e\x92\x00\x00\x00\x92\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\xa0\x81\xf04\x05\x00Pacific/Pago_PagoUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00" + + "\x00\x00\x00#\x82iSa\vೆ\x00\x00\x00\x86\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xcd5\x05\x00Pacific/FunafutiUT\x05\x00\x03\x82\x0f" + + "\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS6\xb7S{\x86\x00\x00\x00\x86\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x9d" + + "6\x05\x00Pacific/TarawaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xcc\xf39" + + "a\xc3\x00\x00\x00\xc3\x00\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81k7\x05\x00Pacific/YapUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_" + + "\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xb7\xef\x97\xc6\xc6\x00\x00\x00\xc6\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81s8\x05\x00Pacific/Noum" + + "eaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSD6\x83\xa1\x8b\x00\x00\x00\x8b\x00\x00\x00\x11\x00\x18\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x00\xa0\x81\x819\x05\x00Pacific/MarquesasUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n" + + "\x00\x00\x00\x00\x00#\x82iSY5\x1a6\xf7\x00\x00\x00\xf7\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81W:\x05\x00Pacific/NorfolkUT\x05\x00\x03\x82" + + "\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSY\xd2K|\x86\x00\x00\x00\x86\x00\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81" + + "\x97;\x05\x00Pacific/GuadalcanalUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#" + + "\x82iS\xeaK\x85v\xdd\x00\x00\x00\xdd\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81j<\x05\x00Pacific/JohnstonUT\x05\x00\x03\x82\x0f\x8baux" + + "\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\u07b54-\xd6\x00\x00\x00\xd6\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x91=\x05\x00P" + + "acific/PonapeUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xe2;Z\xf7\xb7\x00\x00" + + "\x00\xb7\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xaf>\x05\x00Pacific/NauruUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00" + + "PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSFI\xfe\x14^\x01\x00\x00^\x01\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xad?\x05\x00Pacific/GuamUT" + + "\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSt\xca{e\x92\x00\x00\x00\x92\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\xa0\x81QA\x05\x00Pacific/SamoaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82i" + + "S\x81\xe3w\n\xaf\x00\x00\x00\xaf\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81*B\x05\x00Pacific/GalapagosUT\x05\x00\x03\x82\x0f\x8baux\v" + + "\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xeaK\x85v\xdd\x00\x00\x00\xdd\x00\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81$C\x05\x00Pa" + + "cific/HonoluluUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x97n7\x1a\xf2\x00" + + "\x00\x00\xf2\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81KD\x05\x00Pacific/KosraeUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_" + + "\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xc23\xa0\xbc\x84\x00\x00\x00\x84\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x85E\x05\x00Pacific/Gamb" + + "ierUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xfa\x0fA\x05\x99\x00\x00\x00\x99\x00\x00\x00\x10\x00\x18\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\xa0\x81RF\x05\x00Pacific/PitcairnUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n" + + "\x00\x00\x00\x00\x00#\x82iScF/.\xac\x01\x00\x00\xac\x01\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x815G\x05\x00Pacific/FijiUT\x05\x00\x03\x82\x0f\x8ba" + + "ux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xec =\x89\xac\x00\x00\x00\xac\x00\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81'I\x05" + + "\x00Pacific/KantonUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\u07b54-\xd6" + + "\x00\x00\x00\xd6\x00\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x1bJ\x05\x00Pacific/PohnpeiUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04" + + "S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x9a\xf2:F\xc9\x00\x00\x00\xc9\x00\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81:K\x05\x00Pacific/Bo" + + "ugainvilleUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xca\"\xb8i\xda\x00\x00\x00\xda\x00" + + "\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81QL\x05\x00Pacific/MajuroUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK" + + "\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSb\xb2\xaf\xf7\x13\x04\x00\x00\x13\x04\x00\x00\x10\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81sM\x05\x00Pacific/Auckland" + + "UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xf6\xe8]*\xdb\x00\x00\x00\xdb\x00\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\xa0\x81\xd0Q\x05\x00Pacific/KwajaleinUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00" + + "\x00\x00\x00#\x82iSn\x04\x19y\x9a\x00\x00\x00\x9a\x00\x00\x00\x14\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xf6R\x05\x00Pacific/Port_MoresbyUT\x05" + + "\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xcc\xf39a\xc3\x00\x00\x00\xc3\x00\x00\x00\r\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00" + + "\x00\xa0\x81\xdeS\x05\x00Pacific/ChuukUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS" + + "\xcc\xf39a\xc3\x00\x00\x00\xc3\x00\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xe8T\x05\x00Pacific/TrukUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00" + + "\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xc8=ku\xae\x00\x00\x00\xae\x00\x00\x00\x12\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xf1U\x05\x00Pacific/" + + "KiritimatiUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS1\xce_(\x86\x00\x00\x00\x86\x00" + + "\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xebV\x05\x00Pacific/WallisUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK" + + "\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x96\xc5FF(\x03\x00\x00(\x03\x00\x00\x0f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xb9W\x05\x00Pacific/ChathamU" + + "T\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSFI\xfe\x14^\x01\x00\x00^\x01\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\xa0\x81*[\x05\x00Pacific/SaipanUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#" + + "\x82iS\xee\xd0\x1cYN\x04\x00\x00N\x04\x00\x00\x0e\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xd0\\\x05\x00Pacific/EasterUT\x05\x00\x03\x82\x0f\x8baux\v\x00" + + "\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xa8A\x15\xfe\x97\x01\x00\x00\x97\x01\x00\x00\f\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81fa\x05\x00Pac" + + "ific/ApiaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x1c\xe3\xa3S\x96\x01\x00\x00\x96\x01\x00" + + "\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81Cc\x05\x00Pacific/RarotongaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00" + + "PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS>\xfe垛\x03\x00\x00\x9b\x03\x00\x00\x06\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81$e\x05\x00PolandUT\x05\x00\x03\x82\x0f\x8b" + + "aux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS&S\x03\t\xae\x05\x00\x00\xae\x05\x00\x00\b\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xffh" + + "\x05\x00PortugalUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS*\xe4@\xa9\x89\x01\x00\x00\x89\x01" + + "\x00\x00\x03\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xefn\x05\x00PRCUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#" + + "\x82iSŭV\xad\xb7\x03\x00\x00\xb7\x03\x00\x00\a\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xb5p\x05\x00PST8PDTUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04" + + "S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xee\xf0BB\xff\x01\x00\x00\xff\x01\x00\x00\x03\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xadt\x05\x00ROCUT\x05\x00\x03\x82\x0f" + + "\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xc7X,Y\x9f\x01\x00\x00\x9f\x01\x00\x00\x03\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xe9" + + "v\x05\x00ROKUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x06\xaa>\xa8\x00\x01\x00\x00\x00\x01\x00\x00\t\x00" + + "\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xc5x\x05\x00SingaporeUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00" + + "\x00#\x82iS\aW\x10Ѱ\x04\x00\x00\xb0\x04\x00\x00\x06\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\bz\x05\x00TurkeyUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00" + + "\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x9f.\xe4xo\x00\x00\x00o\x00\x00\x00\x03\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xf8~\x05\x00UCTUT\x05\x00\x03\x82" + + "\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x9f.\xe4xo\x00\x00\x00o\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81" + + "\xa4\u007f\x05\x00UniversalUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x00\x00\x00\x00\x00\x00\x00" + + "\x00\x00\x00\x00\x00\x03\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xe8AV\x80\x05\x00US/UT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00" + + "\x00\x00#\x82iSV\x80\x94@\x12\x04\x00\x00\x12\x04\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x93\x80\x05\x00US/MountainUT\x05\x00\x03\x82\x0f\x8baux\v\x00" + + "\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS5\x11Q\x06\xd1\x03\x00\x00\xd1\x03\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xea\x84\x05\x00US/" + + "AlaskaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSp\xb6{\xc9\x13\x02\x00\x00\x13\x02\x00\x00\x0f\x00" + + "\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xfe\x88\x05\x00US/East-IndianaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e" + + "\x03\n\x00\x00\x00\x00\x00#\x82iS\xae,\xa44\xc9\x03\x00\x00\xc9\x03\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81Z\x8b\x05\x00US/AleutianUT\x05\x00\x03\x82\x0f\x8b" + + "aux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xeaK\x85v\xdd\x00\x00\x00\xdd\x00\x00\x00\t\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81h\x8f" + + "\x05\x00US/HawaiiUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS3\x9aG\xc8\xd0\x06\x00\x00\xd0" + + "\x06\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x88\x90\x05\x00US/EasternUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e" + + "\x03\n\x00\x00\x00\x00\x00#\x82iS>\x14\xe7\x03\x83\x03\x00\x00\x83\x03\x00\x00\v\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x9c\x97\x05\x00US/MichiganUT\x05\x00\x03\x82\x0f\x8b" + + "aux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xf6\"\x12\xfe\x0e\x05\x00\x00\x0e\x05\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81d\x9b" + + "\x05\x00US/PacificUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iSt\xca{e\x92\x00\x00\x00" + + "\x92\x00\x00\x00\b\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xb6\xa0\x05\x00US/SamoaUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03" + + "\n\x00\x00\x00\x00\x00#\x82iSø\xab\x9b\xf0\x00\x00\x00\xf0\x00\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x8a\xa1\x05\x00US/ArizonaUT\x05\x00\x03\x82\x0f\x8bau" + + "x\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x9bܩ=\xda\x06\x00\x00\xda\x06\x00\x00\n\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xbe\xa2\x05\x00" + + "US/CentralUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS$ \x873\xf8\x03\x00\x00\xf8\x03" + + "\x00\x00\x11\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81ܩ\x05\x00US/Indiana-StarkeUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01" + + "\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x9f.\xe4xo\x00\x00\x00o\x00\x00\x00\x03\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\x1f\xae\x05\x00UTCUT\x05\x00\x03\x82\x0f\x8bau" + + "x\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS2\x91B\xc0\xee\x01\x00\x00\xee\x01\x00\x00\x03\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81ˮ\x05\x00" + + "WETUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\xe1\xc1\xeb\x05\x8c\x03\x00\x00\x8c\x03\x00\x00\x04\x00\x18\x00\x00" + + "\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xf6\xb0\x05\x00W-SUUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00#\x82iS\x9f.\xe4" + + "xo\x00\x00\x00o\x00\x00\x00\x04\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xc0\xb4\x05\x00ZuluUT\x05\x00\x03\x82\x0f\x8baux\v\x00\x01\x04\x14E\x00\x00\x04S_\x01\x00PK\x05\x06\x00" + + "\x00\x00\x00g\x02g\x02\xea\xc9\x00\x00m\xb5\x05\x00\x00\x00" -- GitLab From 1ec51087e57d242e5556210a426307984d9ef0b3 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Wed, 10 Nov 2021 19:51:34 +0100 Subject: [PATCH 2112/2500] cmd/link/internal/loadelf: better error message for ignored symbols Currently it's quite hard to debug these error messages about ignored symbols because there are only some numbers and no symbol name. Add symbol name. Before: 135029: sym#952: ignoring symbol in section 11 (type 0) After: 135029: sym#952 (_ZN11__sanitizer9SpinMutexC5Ev): ignoring symbol in section 11 (type 0) Change-Id: I7fec50b5798068c74827376613be529803838c5a Reviewed-on: https://go-review.googlesource.com/c/go/+/363034 Run-TryBot: Dmitry Vyukov TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Dmitry Vyukov --- src/cmd/link/internal/loadelf/ldelf.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/link/internal/loadelf/ldelf.go b/src/cmd/link/internal/loadelf/ldelf.go index b4f565a153..d05d8e3b4b 100644 --- a/src/cmd/link/internal/loadelf/ldelf.go +++ b/src/cmd/link/internal/loadelf/ldelf.go @@ -599,7 +599,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, if strings.HasPrefix(elfsym.name, ".LASF") { // gcc on s390x does this continue } - return errorf("%v: sym#%d: ignoring symbol in section %d (type %d)", elfsym.sym, i, elfsym.shndx, elfsym.type_) + return errorf("%v: sym#%d (%s): ignoring symbol in section %d (type %d)", elfsym.sym, i, elfsym.name, elfsym.shndx, elfsym.type_) } s := elfsym.sym -- GitLab From a01a6d6efea52802f455849cd52ef7f8d049033a Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Wed, 10 Nov 2021 01:04:12 +0100 Subject: [PATCH 2113/2500] net: add conversion from AddrPort to TCPAddr to complement existing inverse We already have various member functions of TCPAddr that return an AddrPort, but we don't have a helper function to go from a AddrPort to a TCPAddr. UDP has this, but it was left out of TCP. This commit adds the corresponding function. Updates #49298. Change-Id: I85732cf34f47c792fe13a6b4af64fd4b0e85d06a Reviewed-on: https://go-review.googlesource.com/c/go/+/362596 Trust: Jason A. Donenfeld Run-TryBot: Jason A. Donenfeld TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/net/tcpsock.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/net/tcpsock.go b/src/net/tcpsock.go index fddb018aab..6bad0e8f8b 100644 --- a/src/net/tcpsock.go +++ b/src/net/tcpsock.go @@ -96,6 +96,17 @@ func ResolveTCPAddr(network, address string) (*TCPAddr, error) { return addrs.forResolve(network, address).(*TCPAddr), nil } +// TCPAddrFromAddrPort returns addr as a TCPAddr. If addr.IsValid() is false, +// then the returned TCPAddr will contain a nil IP field, indicating an +// address family-agnostic unspecified address. +func TCPAddrFromAddrPort(addr netip.AddrPort) *TCPAddr { + return &TCPAddr{ + IP: addr.Addr().AsSlice(), + Zone: addr.Addr().Zone(), + Port: int(addr.Port()), + } +} + // TCPConn is an implementation of the Conn interface for TCP network // connections. type TCPConn struct { -- GitLab From e9ef931e0649563e800f0a284ad3606564a88b35 Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Mon, 8 Nov 2021 13:53:55 -0500 Subject: [PATCH 2114/2500] cmd/compile/internal/ssa: fix debug location gen issue with zero width ops Revamp the way that buildLocationLists() handles zero-width operations, to fix a couple of problems that result in bad debug locations. The problematic scenario in this specific bug is where you have a parameter arriving in a register X, then a spill of register X to memory as the first non-zero-width instruction in the function. Example: v68 = ArgIntReg {ctx+0} [1] : BX (ctx[unsafe.Pointer]) v67 = ArgIntReg {ctx+8} [2] : CX (ctx+8[unsafe.Pointer]) ... v281 = StoreReg v67 : ctx+8[unsafe.Pointer] The existing buildLocationLists implementation effectively buffers or bundles changes from zero-width instructions until it it sees a non-zero-width instruction, but doing that in this case winds up making it look as though the parameter is live into the function in memory, not in a register. The fix for this to separate out zero-width ops into two distinct categories: those that whose lifetimes begin at block start (ex: OpArg, Phi) and those whose effects are taking place at the nearest non-zero-width instruction (ex: OpSelect0). In this patch we now handle the first category of ops in an initial pre-pass for each block, and leave the second category for the main pass through the block. See the notes on the issue below for a more detailed explanation of the failure mode. Fixes #46845. Change-Id: I27488d4c041019d5a0b897b7cf53000f63aab1cf Reviewed-on: https://go-review.googlesource.com/c/go/+/362244 Trust: Than McIntosh Run-TryBot: Than McIntosh TryBot-Result: Go Bot Reviewed-by: David Chase --- src/cmd/compile/internal/ssa/debug.go | 89 +++++++++++++++++++-------- 1 file changed, 64 insertions(+), 25 deletions(-) diff --git a/src/cmd/compile/internal/ssa/debug.go b/src/cmd/compile/internal/ssa/debug.go index e78eb5c0e4..fed152efba 100644 --- a/src/cmd/compile/internal/ssa/debug.go +++ b/src/cmd/compile/internal/ssa/debug.go @@ -1120,54 +1120,93 @@ func (state *debugState) buildLocationLists(blockLocs []*BlockDebug) { v.Op == OpArgIntReg || v.Op == OpArgFloatReg } + blockPrologComplete := func(v *Value) bool { + if b.ID != state.f.Entry.ID { + return !opcodeTable[v.Op].zeroWidth + } else { + return v.Op == OpInitMem + } + } + + // Examine the prolog portion of the block to process special + // zero-width ops such as Arg, Phi, LoweredGetClosurePtr (etc) + // whose lifetimes begin at the block starting point. In an + // entry block, allow for the possibility that we may see Arg + // ops that appear _after_ other non-zero-width operations. + // Example: + // + // v33 = ArgIntReg {foo+0} [0] : AX (foo) + // v34 = ArgIntReg {bar+0} [0] : BX (bar) + // ... + // v77 = StoreReg v67 : ctx+8[unsafe.Pointer] + // v78 = StoreReg v68 : ctx[unsafe.Pointer] + // v79 = Arg <*uint8> {args} : args[*uint8] (args[*uint8]) + // v80 = Arg {args} [8] : args+8[int] (args+8[int]) + // ... + // v1 = InitMem + // + // We can stop scanning the initial portion of the block when + // we either see the InitMem op (for entry blocks) or the + // first non-zero-width op (for other blocks). + for idx := 0; idx < len(b.Values); idx++ { + v := b.Values[idx] + if blockPrologComplete(v) { + break + } + // Consider only "lifetime begins at block start" ops. + if !mustBeFirst(v) && v.Op != OpArg { + continue + } + slots := state.valueNames[v.ID] + reg, _ := state.f.getHome(v.ID).(*Register) + changed := state.processValue(v, slots, reg) // changed == added to state.changedVars + if changed { + for _, varID := range state.changedVars.contents() { + state.updateVar(VarID(varID), v.Block, BlockStart) + } + state.changedVars.clear() + } + } + + // Now examine the block again, handling things other than the + // "begins at block start" lifetimes. zeroWidthPending := false - blockPrologComplete := false // set to true at first non-zero-width op - apcChangedSize := 0 // size of changedVars for leading Args, Phi, ClosurePtr + prologComplete := false // expect to see values in pattern (apc)* (zerowidth|real)* for _, v := range b.Values { + if blockPrologComplete(v) { + prologComplete = true + } slots := state.valueNames[v.ID] reg, _ := state.f.getHome(v.ID).(*Register) changed := state.processValue(v, slots, reg) // changed == added to state.changedVars if opcodeTable[v.Op].zeroWidth { + if prologComplete && mustBeFirst(v) { + panic(fmt.Errorf("Unexpected placement of op '%s' appearing after non-pseudo-op at beginning of block %s in %s\n%s", v.LongString(), b, b.Func.Name, b.Func)) + } if changed { if mustBeFirst(v) || v.Op == OpArg { - // These ranges begin at true beginning of block, not after first instruction - if blockPrologComplete && mustBeFirst(v) { - panic(fmt.Errorf("Unexpected placement of op '%s' appearing after non-pseudo-op at beginning of block %s in %s\n%s", v.LongString(), b, b.Func.Name, b.Func)) - } - apcChangedSize = len(state.changedVars.contents()) - // Other zero-width ops must wait on a "real" op. - zeroWidthPending = true + // already taken care of above continue } + zeroWidthPending = true } continue } - if !changed && !zeroWidthPending { continue } - // Not zero-width; i.e., a "real" instruction. + // Not zero-width; i.e., a "real" instruction. zeroWidthPending = false - blockPrologComplete = true - for i, varID := range state.changedVars.contents() { - if i < apcChangedSize { // buffered true start-of-block changes - state.updateVar(VarID(varID), v.Block, BlockStart) - } else { - state.updateVar(VarID(varID), v.Block, v) - } + for _, varID := range state.changedVars.contents() { + state.updateVar(VarID(varID), v.Block, v) } state.changedVars.clear() - apcChangedSize = 0 } - for i, varID := range state.changedVars.contents() { - if i < apcChangedSize { // buffered true start-of-block changes - state.updateVar(VarID(varID), b, BlockStart) - } else { - state.updateVar(VarID(varID), b, BlockEnd) - } + for _, varID := range state.changedVars.contents() { + state.updateVar(VarID(varID), b, BlockEnd) } prevBlock = b -- GitLab From 79e03a9281ba03f9f79904f074e2e343f2140bdd Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Wed, 10 Nov 2021 10:44:00 -0500 Subject: [PATCH 2115/2500] cmd/compile: include register-resident output params in DWARF-gen During the register ABI work, a change was made in CL 302071 to "stackframe" to treat register-resident output parameter (PARAMOUT) variables that same as locals, which meant that if they were unused, we'd delete them from the "Dcl" slice. This has the effect of making them invisible to DWARF generation later on in the pipeline, meaning that we don't get DIEs for them in the debug info. This patch fixes the problem by capturing these params prior to optimization and then adding them back in for consideration when we're processing the params/locals of a function during DWARF generation. Fixes #48573. Change-Id: I2b32882911c18f91c3e3d009486517522d262685 Reviewed-on: https://go-review.googlesource.com/c/go/+/362618 Trust: Than McIntosh Run-TryBot: Than McIntosh TryBot-Result: Go Bot Reviewed-by: David Chase --- src/cmd/compile/internal/dwarfgen/dwarf.go | 13 + src/cmd/compile/internal/ssa/debug.go | 40 ++-- src/cmd/compile/internal/ssagen/ssa.go | 19 +- src/cmd/link/internal/ld/dwarf_test.go | 266 +++++++++++++++++---- 4 files changed, 268 insertions(+), 70 deletions(-) diff --git a/src/cmd/compile/internal/dwarfgen/dwarf.go b/src/cmd/compile/internal/dwarfgen/dwarf.go index 3007262db9..e249a52e57 100644 --- a/src/cmd/compile/internal/dwarfgen/dwarf.go +++ b/src/cmd/compile/internal/dwarfgen/dwarf.go @@ -150,6 +150,19 @@ func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []*ir dcl := apDecls if fnsym.WasInlined() { dcl = preInliningDcls(fnsym) + } else { + // The backend's stackframe pass prunes away entries from the + // fn's Dcl list, including PARAMOUT nodes that correspond to + // output params passed in registers. Add back in these + // entries here so that we can process them properly during + // DWARF-gen. See issue 48573 for more details. + debugInfo := fn.DebugInfo.(*ssa.FuncDebug) + for _, n := range debugInfo.RegOutputParams { + if n.Class != ir.PPARAMOUT || !n.IsOutputParamInRegisters() { + panic("invalid ir.Name on debugInfo.RegOutputParams list") + } + dcl = append(dcl, n) + } } // If optimization is enabled, the list above will typically be diff --git a/src/cmd/compile/internal/ssa/debug.go b/src/cmd/compile/internal/ssa/debug.go index fed152efba..aad59fa24e 100644 --- a/src/cmd/compile/internal/ssa/debug.go +++ b/src/cmd/compile/internal/ssa/debug.go @@ -34,6 +34,9 @@ type FuncDebug struct { VarSlots [][]SlotID // The location list data, indexed by VarID. Must be processed by PutLocationList. LocationLists [][]byte + // Register-resident output parameters for the function. This is filled in at + // SSA generation time. + RegOutputParams []*ir.Name // Filled in by the user. Translates Block and Value ID to PC. GetPC func(ID, ID) int64 @@ -548,10 +551,10 @@ func PopulateABIInRegArgOps(f *Func) { f.Entry.Values = append(newValues, f.Entry.Values...) } -// BuildFuncDebug returns debug information for f. +// BuildFuncDebug debug information for f, placing the results in "rval". // f must be fully processed, so that each Value is where it will be when // machine code is emitted. -func BuildFuncDebug(ctxt *obj.Link, f *Func, loggingEnabled bool, stackOffset func(LocalSlot) int32) *FuncDebug { +func BuildFuncDebug(ctxt *obj.Link, f *Func, loggingEnabled bool, stackOffset func(LocalSlot) int32, rval *FuncDebug) { if f.RegAlloc == nil { f.Fatalf("BuildFuncDebug on func %v that has not been fully processed", f) } @@ -661,12 +664,11 @@ func BuildFuncDebug(ctxt *obj.Link, f *Func, loggingEnabled bool, stackOffset fu blockLocs := state.liveness() state.buildLocationLists(blockLocs) - return &FuncDebug{ - Slots: state.slots, - VarSlots: state.varSlots, - Vars: state.vars, - LocationLists: state.lists, - } + // Populate "rval" with what we've computed. + rval.Slots = state.slots + rval.VarSlots = state.varSlots + rval.Vars = state.vars + rval.LocationLists = state.lists } // liveness walks the function in control flow order, calculating the start @@ -1593,7 +1595,7 @@ func isNamedRegParam(p abi.ABIParamAssignment) bool { return true } -// BuildFuncDebugNoOptimized constructs a FuncDebug object with +// BuildFuncDebugNoOptimized populates a FuncDebug object "rval" with // entries corresponding to the register-resident input parameters for // the function "f"; it is used when we are compiling without // optimization but the register ABI is enabled. For each reg param, @@ -1601,8 +1603,7 @@ func isNamedRegParam(p abi.ABIParamAssignment) bool { // the input register, and the second element holds the stack location // of the param (the assumption being that when optimization is off, // each input param reg will be spilled in the prolog. -func BuildFuncDebugNoOptimized(ctxt *obj.Link, f *Func, loggingEnabled bool, stackOffset func(LocalSlot) int32) *FuncDebug { - fd := FuncDebug{} +func BuildFuncDebugNoOptimized(ctxt *obj.Link, f *Func, loggingEnabled bool, stackOffset func(LocalSlot) int32, rval *FuncDebug) { pri := f.ABISelf.ABIAnalyzeFuncType(f.Type.FuncType()) @@ -1616,7 +1617,7 @@ func BuildFuncDebugNoOptimized(ctxt *obj.Link, f *Func, loggingEnabled bool, sta } } if numRegParams == 0 { - return &fd + return } state := debugState{f: f} @@ -1626,7 +1627,7 @@ func BuildFuncDebugNoOptimized(ctxt *obj.Link, f *Func, loggingEnabled bool, sta } // Allocate location lists. - fd.LocationLists = make([][]byte, numRegParams) + rval.LocationLists = make([][]byte, numRegParams) // Locate the value corresponding to the last spill of // an input register. @@ -1642,10 +1643,10 @@ func BuildFuncDebugNoOptimized(ctxt *obj.Link, f *Func, loggingEnabled bool, sta n := inp.Name.(*ir.Name) sl := LocalSlot{N: n, Type: inp.Type, Off: 0} - fd.Vars = append(fd.Vars, n) - fd.Slots = append(fd.Slots, sl) - slid := len(fd.VarSlots) - fd.VarSlots = append(fd.VarSlots, []SlotID{SlotID(slid)}) + rval.Vars = append(rval.Vars, n) + rval.Slots = append(rval.Slots, sl) + slid := len(rval.VarSlots) + rval.VarSlots = append(rval.VarSlots, []SlotID{SlotID(slid)}) if afterPrologVal == ID(-1) { // This can happen for degenerate functions with infinite @@ -1662,7 +1663,7 @@ func BuildFuncDebugNoOptimized(ctxt *obj.Link, f *Func, loggingEnabled bool, sta // Param is arriving in one or more registers. We need a 2-element // location expression for it. First entry in location list // will correspond to lifetime in input registers. - list, sizeIdx := setupLocList(ctxt, f, fd.LocationLists[pidx], + list, sizeIdx := setupLocList(ctxt, f, rval.LocationLists[pidx], BlockStart.ID, afterPrologVal) if list == nil { pidx++ @@ -1727,8 +1728,7 @@ func BuildFuncDebugNoOptimized(ctxt *obj.Link, f *Func, loggingEnabled bool, sta // fill in size ctxt.Arch.ByteOrder.PutUint16(list[sizeIdx:], uint16(len(list)-sizeIdx-2)) - fd.LocationLists[pidx] = list + rval.LocationLists[pidx] = list pidx++ } - return &fd } diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 0853242e6f..d6407af334 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -484,6 +484,19 @@ func buildssa(fn *ir.Func, worker int) *ssa.Func { var params *abi.ABIParamResultInfo params = s.f.ABISelf.ABIAnalyze(fn.Type(), true) + // The backend's stackframe pass prunes away entries from the fn's + // Dcl list, including PARAMOUT nodes that correspond to output + // params passed in registers. Walk the Dcl list and capture these + // nodes to a side list, so that we'll have them available during + // DWARF-gen later on. See issue 48573 for more details. + var debugInfo ssa.FuncDebug + for _, n := range fn.Dcl { + if n.Class == ir.PPARAMOUT && n.IsOutputParamInRegisters() { + debugInfo.RegOutputParams = append(debugInfo.RegOutputParams, n) + } + } + fn.DebugInfo = &debugInfo + // Generate addresses of local declarations s.decladdrs = map[*ir.Name]*ssa.Value{} for _, n := range fn.Dcl { @@ -7003,12 +7016,12 @@ func genssa(f *ssa.Func, pp *objw.Progs) { if base.Ctxt.Flag_locationlists { var debugInfo *ssa.FuncDebug + debugInfo = e.curfn.DebugInfo.(*ssa.FuncDebug) if e.curfn.ABI == obj.ABIInternal && base.Flag.N != 0 { - debugInfo = ssa.BuildFuncDebugNoOptimized(base.Ctxt, f, base.Debug.LocationLists > 1, StackOffset) + ssa.BuildFuncDebugNoOptimized(base.Ctxt, f, base.Debug.LocationLists > 1, StackOffset, debugInfo) } else { - debugInfo = ssa.BuildFuncDebug(base.Ctxt, f, base.Debug.LocationLists > 1, StackOffset) + ssa.BuildFuncDebug(base.Ctxt, f, base.Debug.LocationLists > 1, StackOffset, debugInfo) } - e.curfn.DebugInfo = debugInfo bstart := s.bstart idToIdx := make([]int, f.NumBlocks()) for i, b := range f.Blocks { diff --git a/src/cmd/link/internal/ld/dwarf_test.go b/src/cmd/link/internal/ld/dwarf_test.go index db9002491e..9a163488e6 100644 --- a/src/cmd/link/internal/ld/dwarf_test.go +++ b/src/cmd/link/internal/ld/dwarf_test.go @@ -1635,6 +1635,66 @@ func TestIssue42484(t *testing.T) { f.Close() } +// processParams examines the formal parameter children of subprogram +// DIE "die" using the explorer "ex" and returns a string that +// captures the name, order, and classification of the subprogram's +// input and output parameters. For example, for the go function +// +// func foo(i1 int, f1 float64) (string, bool) { +// +// this function would return a string something like +// +// i1:0:1 f1:1:1 ~r0:2:2 ~r1:3:2 +// +// where each chunk above is of the form NAME:ORDER:INOUTCLASSIFICATION +// +func processParams(die *dwarf.Entry, ex *examiner) string { + // Values in the returned map are of the form : + // where order is the order within the child DIE list of the + // param, and is an integer: + // + // -1: varparm attr not found + // 1: varparm found with value false + // 2: varparm found with value true + // + foundParams := make(map[string]string) + + // Walk ABCs's children looking for params. + abcIdx := ex.idxFromOffset(die.Offset) + childDies := ex.Children(abcIdx) + idx := 0 + for _, child := range childDies { + if child.Tag == dwarf.TagFormalParameter { + // NB: a setting of DW_AT_variable_parameter indicates + // that the param in question is an output parameter; we + // want to see this attribute set to TRUE for all Go + // return params. It would be OK to have it missing for + // input parameters, but for the moment we verify that the + // attr is present but set to false. + st := -1 + if vp, ok := child.Val(dwarf.AttrVarParam).(bool); ok { + if vp { + st = 2 + } else { + st = 1 + } + } + if name, ok := child.Val(dwarf.AttrName).(string); ok { + foundParams[name] = fmt.Sprintf("%d:%d", idx, st) + idx++ + } + } + } + + found := make([]string, 0, len(foundParams)) + for k, v := range foundParams { + found = append(found, fmt.Sprintf("%s:%s", k, v)) + } + sort.Strings(found) + + return fmt.Sprintf("%+v", found) +} + func TestOutputParamAbbrevAndAttr(t *testing.T) { testenv.MustHaveGoBuild(t) @@ -1694,56 +1754,15 @@ func main() { t.Fatalf("unexpected tag %v on main.ABC DIE", abcdie.Tag) } - // A setting of DW_AT_variable_parameter indicates that the - // param in question is an output parameter; we want to see this - // attribute set to TRUE for all Go return params. It would be - // OK to have it missing for input parameters, but for the moment - // we verify that the attr is present but set to false. - - // Values in this map are of the form : - // where order is the order within the child DIE list of the param, - // and is an integer: - // - // -1: varparm attr not found - // 1: varparm found with value false - // 2: varparm found with value true - // - foundParams := make(map[string]string) - - // Walk ABCs's children looking for params. - abcIdx := ex.idxFromOffset(abcdie.Offset) - childDies := ex.Children(abcIdx) - idx := 0 - for _, child := range childDies { - if child.Tag == dwarf.TagFormalParameter { - st := -1 - if vp, ok := child.Val(dwarf.AttrVarParam).(bool); ok { - if vp { - st = 2 - } else { - st = 1 - } - } - if name, ok := child.Val(dwarf.AttrName).(string); ok { - foundParams[name] = fmt.Sprintf("%d:%d", idx, st) - idx++ - } - } - } - - // Digest the result. - found := make([]string, 0, len(foundParams)) - for k, v := range foundParams { - found = append(found, fmt.Sprintf("%s:%s", k, v)) - } - sort.Strings(found) + // Call a helper to collect param info. + found := processParams(abcdie, &ex) // Make sure we see all of the expected params in the proper - // order, that they have the varparam attr, and the varparm is set - // for the returns. + // order, that they have the varparam attr, and the varparam is + // set for the returns. expected := "[c1:0:1 c2:1:1 c3:2:1 d1:3:1 d2:4:1 d3:5:1 d4:6:1 f1:7:1 f2:8:1 f3:9:1 g1:10:1 r1:11:2 r2:12:2 r3:13:2 r4:14:2 r5:15:2 r6:16:2]" - if fmt.Sprintf("%+v", found) != expected { - t.Errorf("param check failed, wanted %s got %s\n", + if found != expected { + t.Errorf("param check failed, wanted:\n%s\ngot:\n%s\n", expected, found) } } @@ -1849,3 +1868,156 @@ func main() { } } } + +func TestOptimizedOutParamHandling(t *testing.T) { + testenv.MustHaveGoBuild(t) + + if runtime.GOOS == "plan9" { + t.Skip("skipping on plan9; no DWARF symbol table in executables") + } + t.Parallel() + + // This test is intended to verify that the compiler emits DWARF + // DIE entries for all input and output parameters, and that: + // + // - attributes are set correctly for output params, + // - things appear in the proper order + // - things work properly for both register-resident + // params and params passed on the stack + // - things work for both referenced and unreferenced params + // - things work for named return values un-named return vals + // + // The scenarios below don't cover all possible permutations and + // combinations, but they hit a bunch of the high points. + + const prog = ` +package main + +// First testcase. All input params in registers, all params used. + +//go:noinline +func tc1(p1, p2 int, p3 string) (int, string) { + return p1 + p2, p3 + "foo" +} + +// Second testcase. Some params in registers, some on stack. + +//go:noinline +func tc2(p1 int, p2 [128]int, p3 string) (int, string, [128]int) { + return p1 + p2[p1], p3 + "foo", [128]int{p1} +} + +// Third testcase. Named return params. + +//go:noinline +func tc3(p1 int, p2 [128]int, p3 string) (r1 int, r2 bool, r3 string, r4 [128]int) { + if p1 == 101 { + r1 = p1 + p2[p1] + r2 = p3 == "foo" + r4 = [128]int{p1} + return + } else { + return p1 - p2[p1+3], false, "bar", [128]int{p1 + 2} + } +} + +// Fourth testcase. Some thing are used, some are unused. + +//go:noinline +func tc4(p1, p1un int, p2, p2un [128]int, p3, p3un string) (r1 int, r1un int, r2 bool, r3 string, r4, r4un [128]int) { + if p1 == 101 { + r1 = p1 + p2[p2[0]] + r2 = p3 == "foo" + r4 = [128]int{p1} + return + } else { + return p1, -1, true, "plex", [128]int{p1 + 2}, [128]int{-1} + } +} + +func main() { + { + r1, r2 := tc1(3, 4, "five") + println(r1, r2) + } + { + x := [128]int{9} + r1, r2, r3 := tc2(3, x, "five") + println(r1, r2, r3[0]) + } + { + x := [128]int{9} + r1, r2, r3, r4 := tc3(3, x, "five") + println(r1, r2, r3, r4[0]) + } + { + x := [128]int{3} + y := [128]int{7} + r1, r1u, r2, r3, r4, r4u := tc4(0, 1, x, y, "a", "b") + println(r1, r1u, r2, r3, r4[0], r4u[1]) + } + +} +` + dir := t.TempDir() + f := gobuild(t, dir, prog, DefaultOpt) + defer f.Close() + + d, err := f.DWARF() + if err != nil { + t.Fatalf("error reading DWARF: %v", err) + } + + rdr := d.Reader() + ex := examiner{} + if err := ex.populate(rdr); err != nil { + t.Fatalf("error reading DWARF: %v", err) + } + + testcases := []struct { + tag string + expected string + }{ + { + tag: "tc1", + expected: "[p1:0:1 p2:1:1 p3:2:1 ~r0:3:2 ~r1:4:2]", + }, + { + tag: "tc2", + expected: "[p1:0:1 p2:1:1 p3:2:1 ~r0:3:2 ~r1:4:2 ~r2:5:2]", + }, + { + tag: "tc3", + expected: "[p1:0:1 p2:1:1 p3:2:1 r1:3:2 r2:4:2 r3:5:2 r4:6:2]", + }, + { + tag: "tc4", + expected: "[p1:0:1 p1un:1:1 p2:2:1 p2un:3:1 p3:4:1 p3un:5:1 r1:6:2 r1un:7:2 r2:8:2 r3:9:2 r4:10:2 r4un:11:2]", + }, + } + + for _, tc := range testcases { + // Locate the proper DIE + which := fmt.Sprintf("main.%s", tc.tag) + tcs := ex.Named(which) + if len(tcs) == 0 { + t.Fatalf("unable to locate DIE for " + which) + } + if len(tcs) != 1 { + t.Fatalf("more than one " + which + " DIE") + } + die := tcs[0] + + // Vet the DIE + if die.Tag != dwarf.TagSubprogram { + t.Fatalf("unexpected tag %v on "+which+" DIE", die.Tag) + } + + // Examine params for this subprogram. + foundParams := processParams(die, &ex) + if foundParams != tc.expected { + t.Errorf("check failed for testcase %s -- wanted:\n%s\ngot:%s\n", + tc.tag, tc.expected, foundParams) + } + } +} -- GitLab From c49627e81b05f23f97544fc6bfae3347296b4a06 Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Wed, 10 Nov 2021 15:36:25 -0500 Subject: [PATCH 2116/2500] cmd/compile: use canonical stringslice/ representations in abiutils A chunk of code in abiutils was synthesizing the internals of a Go string type as "struct { unsafe.Pointer, uintptr }" instead of the more canonical representation "struct { *uint8, int }" used elsewhere in the compiler. The abiutils type was being pulled into the code during late call expansion, which resulted in two different entries in the SSA named value table for the same variable piece, each with different types; this then confused DWARF location list generation. This patch changes the abiutils synthesized type to be consistent with other parts of the back end, and makes a similar change for synthesized slice types (use "struct { *uint8, int, int }"). Fixes #47354. Change-Id: If789031cdc7abaf215bc75ee6eb863defbe530be Reviewed-on: https://go-review.googlesource.com/c/go/+/362715 Trust: Than McIntosh Run-TryBot: Than McIntosh TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/compile/internal/abi/abiutils.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/cmd/compile/internal/abi/abiutils.go b/src/cmd/compile/internal/abi/abiutils.go index 74c8707b29..529150a390 100644 --- a/src/cmd/compile/internal/abi/abiutils.go +++ b/src/cmd/compile/internal/abi/abiutils.go @@ -715,19 +715,20 @@ func setup() { synthOnce.Do(func() { fname := types.BuiltinPkg.Lookup nxp := src.NoXPos - unsp := types.Types[types.TUNSAFEPTR] - ui := types.Types[types.TUINTPTR] + bp := types.NewPtr(types.Types[types.TUINT8]) + it := types.Types[types.TINT] synthSlice = types.NewStruct(types.NoPkg, []*types.Field{ - types.NewField(nxp, fname("ptr"), unsp), - types.NewField(nxp, fname("len"), ui), - types.NewField(nxp, fname("cap"), ui), + types.NewField(nxp, fname("ptr"), bp), + types.NewField(nxp, fname("len"), it), + types.NewField(nxp, fname("cap"), it), }) types.CalcStructSize(synthSlice) synthString = types.NewStruct(types.NoPkg, []*types.Field{ - types.NewField(nxp, fname("data"), unsp), - types.NewField(nxp, fname("len"), ui), + types.NewField(nxp, fname("data"), bp), + types.NewField(nxp, fname("len"), it), }) types.CalcStructSize(synthString) + unsp := types.Types[types.TUNSAFEPTR] synthIface = types.NewStruct(types.NoPkg, []*types.Field{ types.NewField(nxp, fname("f1"), unsp), types.NewField(nxp, fname("f2"), unsp), -- GitLab From d76b1ac3e1919bd863e7e906202ae085cb20f595 Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Thu, 11 Nov 2021 07:06:24 -0500 Subject: [PATCH 2117/2500] net: skip new testpoint TestUDPIPVersionReadMsg on plan9 Skip TestUDPIPVersionReadMsg on plan9, since it does things not supported on that OS. Change-Id: Icd1716fb5ed4e8877e57acb8c851ec3be72e83e2 Reviewed-on: https://go-review.googlesource.com/c/go/+/363354 Reviewed-by: Jason A. Donenfeld Trust: Jason A. Donenfeld Trust: Than McIntosh Run-TryBot: Jason A. Donenfeld Run-TryBot: Than McIntosh TryBot-Result: Go Bot --- src/net/udpsock_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/net/udpsock_test.go b/src/net/udpsock_test.go index 01b8d39216..8ccdb365ab 100644 --- a/src/net/udpsock_test.go +++ b/src/net/udpsock_test.go @@ -605,6 +605,10 @@ func BenchmarkWriteToReadFromUDPAddrPort(b *testing.B) { } func TestUDPIPVersionReadMsg(t *testing.T) { + switch runtime.GOOS { + case "plan9": + t.Skipf("skipping on %v", runtime.GOOS) + } conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) if err != nil { t.Fatal(err) -- GitLab From 47b3ab5ede452a88c2da4c5eaf092b2d707d2ff4 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Wed, 10 Nov 2021 16:57:14 -0500 Subject: [PATCH 2118/2500] doc/go1.18: add a release note for 'go mod vendor -o' For #47327 Change-Id: I50418c0d017c4e90a2c13d26945ee639079e4e33 Reviewed-on: https://go-review.googlesource.com/c/go/+/363174 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Paschalis Tsilias Reviewed-by: Ian Lance Taylor --- doc/go1.18.html | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/go1.18.html b/doc/go1.18.html index 44c56444fc..bec9ada383 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -114,6 +114,15 @@ Do not send CLs removing the interior tags from such phrases. go mod download all.

+

+ The go mod vendor subcommand now + supports a -o flag to set the output directory. + (Other go commands still read from the vendor + directory at the module root when loading packages + with -mod=vendor, so the main use for this flag is for + third-party tools that need to collect package source code.) +

+

TODO: https://golang.org/cl/349595: cmd/go: add GOAMD64 environment variable

-- GitLab From 8c73f80400d04a320165f4c1e535524cc50e20b4 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 9 Nov 2021 19:50:47 -0500 Subject: [PATCH 2119/2500] runtime: bypass scheduler when doing traceback for goroutine profile When acquire a goroutine profile, we stop the world then acquire a stack trace for each goroutine. When cgo traceback is used, the traceback code may call the cgo traceback function using cgocall. As the world is stopped, cgocall will be blocked at exitsyscall, causing a deadlock. Bypass the scheduler (using asmcgocall) to fix this. Change-Id: Ic4e596adc3711310b6a983d73786d697ef15dd72 Reviewed-on: https://go-review.googlesource.com/c/go/+/362757 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: Ian Lance Taylor --- src/runtime/crash_cgo_test.go | 8 ++++ src/runtime/mprof.go | 6 ++- src/runtime/testdata/testprogcgo/gprof.go | 46 ++++++++++++++++++++++ src/runtime/testdata/testprogcgo/gprof_c.c | 29 ++++++++++++++ 4 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 src/runtime/testdata/testprogcgo/gprof.go create mode 100644 src/runtime/testdata/testprogcgo/gprof_c.c diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go index e6d1742a38..58c340f8ad 100644 --- a/src/runtime/crash_cgo_test.go +++ b/src/runtime/crash_cgo_test.go @@ -702,3 +702,11 @@ func TestNeedmDeadlock(t *testing.T) { t.Fatalf("want %s, got %s\n", want, output) } } + +func TestCgoTracebackGoroutineProfile(t *testing.T) { + output := runTestProg(t, "testprogcgo", "GoroutineProfile") + want := "OK\n" + if output != want { + t.Fatalf("want %s, got %s\n", want, output) + } +} diff --git a/src/runtime/mprof.go b/src/runtime/mprof.go index b4de8f53a9..569c17f0a7 100644 --- a/src/runtime/mprof.go +++ b/src/runtime/mprof.go @@ -805,7 +805,11 @@ func goroutineProfileWithLabels(p []StackRecord, labels []unsafe.Pointer) (n int // truncated profile than to crash the entire process. return } - saveg(^uintptr(0), ^uintptr(0), gp1, &r[0]) + // saveg calls gentraceback, which may call cgo traceback functions. + // The world is stopped, so it cannot use cgocall (which will be + // blocked at exitsyscall). Do it on the system stack so it won't + // call into the schedular (see traceback.go:cgoContextPCs). + systemstack(func() { saveg(^uintptr(0), ^uintptr(0), gp1, &r[0]) }) if labels != nil { lbl[0] = gp1.labels lbl = lbl[1:] diff --git a/src/runtime/testdata/testprogcgo/gprof.go b/src/runtime/testdata/testprogcgo/gprof.go new file mode 100644 index 0000000000..d453b4d0ce --- /dev/null +++ b/src/runtime/testdata/testprogcgo/gprof.go @@ -0,0 +1,46 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +// Test taking a goroutine profile with C traceback. + +/* +// Defined in gprof_c.c. +void CallGoSleep(void); +void gprofCgoTraceback(void* parg); +void gprofCgoContext(void* parg); +*/ +import "C" + +import ( + "fmt" + "io" + "runtime" + "runtime/pprof" + "time" + "unsafe" +) + +func init() { + register("GoroutineProfile", GoroutineProfile) +} + +func GoroutineProfile() { + runtime.SetCgoTraceback(0, unsafe.Pointer(C.gprofCgoTraceback), unsafe.Pointer(C.gprofCgoContext), nil) + + go C.CallGoSleep() + go C.CallGoSleep() + go C.CallGoSleep() + time.Sleep(1 * time.Second) + + prof := pprof.Lookup("goroutine") + prof.WriteTo(io.Discard, 1) + fmt.Println("OK") +} + +//export GoSleep +func GoSleep() { + time.Sleep(time.Hour) +} diff --git a/src/runtime/testdata/testprogcgo/gprof_c.c b/src/runtime/testdata/testprogcgo/gprof_c.c new file mode 100644 index 0000000000..6ddff445ad --- /dev/null +++ b/src/runtime/testdata/testprogcgo/gprof_c.c @@ -0,0 +1,29 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// The C definitions for gprof.go. That file uses //export so +// it can't put function definitions in the "C" import comment. + +#include +#include + +// Functions exported from Go. +extern void GoSleep(); + +struct cgoContextArg { + uintptr_t context; +}; + +void gprofCgoContext(void *arg) { + ((struct cgoContextArg*)arg)->context = 1; +} + +void gprofCgoTraceback(void *arg) { + // spend some time here so the P is more likely to be retaken. + for (volatile int i = 0; i < 123456789; i++); +} + +void CallGoSleep() { + GoSleep(); +} -- GitLab From 666fc173c02ff3004ac9ef867aa4eec7e243dde3 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Tue, 9 Nov 2021 22:35:50 +0000 Subject: [PATCH 2120/2500] doc/go1.18: document http.Transport.Dial* being used in js/wasm This PR adds a note into the Go 1.18 changelog for CL 330852. Updates #46923. Change-Id: I99150e9275ce23fcf3697d6a22ac216818223c74 GitHub-Last-Rev: b2772ce68bcd02af672c663760b635eab292afb7 GitHub-Pull-Request: golang/go#49258 Reviewed-on: https://go-review.googlesource.com/c/go/+/360297 Trust: Roland Shoemaker Reviewed-by: Dmitri Shuralyov --- doc/go1.18.html | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/go1.18.html b/doc/go1.18.html index bec9ada383..45f89b7be5 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -276,6 +276,12 @@ Do not send CLs removing the interior tags from such phrases.
net/http
+

+ On WebAssembly targets, the Dial, DialContext, + DialTLS and DialTLSContext method fields in + Transport + will now be correctly used, if specified, for making HTTP requests. +

TODO: https://golang.org/cl/338590: add Cookie.Valid method

-- GitLab From 73a4bbb0df36d85d1ab8cb12d220d1d56e4049ec Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 11 Nov 2021 15:29:38 +0700 Subject: [PATCH 2121/2500] cmd/compile: fix missing ddd when building call for function instantiation closure When building a call expression for function instantiation closure, if it's a variadic function, the CallExpr.IsDDD must be set for typecheck to work properly. Otherwise, there will be a mismatch between the arguments type and the function signature. Fixes #49516 Change-Id: I0af90ee3fcc3e6c8bba8b20e331e044cbce17985 Reviewed-on: https://go-review.googlesource.com/c/go/+/363314 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 1 + test/typeparam/issue49516.go | 26 +++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 test/typeparam/issue49516.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index cfbbee3ceb..c8c5d80cfc 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -515,6 +515,7 @@ func (g *genInst) buildClosure(outer *ir.Func, x ir.Node) ir.Node { // Build call itself. var innerCall ir.Node = ir.NewCallExpr(pos, ir.OCALL, target.Nname, args) + innerCall.(*ir.CallExpr).IsDDD = typ.IsVariadic() if len(formalResults) > 0 { innerCall = ir.NewReturnStmt(pos, []ir.Node{innerCall}) } diff --git a/test/typeparam/issue49516.go b/test/typeparam/issue49516.go new file mode 100644 index 0000000000..d6fab02463 --- /dev/null +++ b/test/typeparam/issue49516.go @@ -0,0 +1,26 @@ +// compile -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type Q[T any] struct { + s []T +} + +func (q *Q[T]) Push(v ...T) { + q.s = append(q.s, v...) +} + +func pushN(push func(*Q[int], ...int), n int) { + var q Q[int] + for i := 0; i < n; i++ { + push(&q, i) + } +} + +func f() { + pushN((*Q[int]).Push, 100) +} -- GitLab From 84277bfd07dad771b9978149bdaed8aa16ed8982 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 11 Nov 2021 12:52:45 -0500 Subject: [PATCH 2122/2500] runtime: fix C compilation error in TestCgoTracebackGoroutineProfile Use C89 declaration. Also fix indentation. Change-Id: Ib974eb32ac95610d0b0eca00ca3b139b388c73bd Reviewed-on: https://go-review.googlesource.com/c/go/+/363356 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/runtime/testdata/testprogcgo/gprof_c.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/runtime/testdata/testprogcgo/gprof_c.c b/src/runtime/testdata/testprogcgo/gprof_c.c index 6ddff445ad..5c7cd77022 100644 --- a/src/runtime/testdata/testprogcgo/gprof_c.c +++ b/src/runtime/testdata/testprogcgo/gprof_c.c @@ -21,9 +21,10 @@ void gprofCgoContext(void *arg) { void gprofCgoTraceback(void *arg) { // spend some time here so the P is more likely to be retaken. - for (volatile int i = 0; i < 123456789; i++); + volatile int i; + for (i = 0; i < 123456789; i++); } void CallGoSleep() { - GoSleep(); + GoSleep(); } -- GitLab From 8ce1a953fb125ab390e816540d7f6c304ee7e52b Mon Sep 17 00:00:00 2001 From: jiahua wang Date: Sat, 2 Oct 2021 22:50:31 +0800 Subject: [PATCH 2123/2500] io: add error check to TeeReader Example Change-Id: I0b94bdced47483c6412e9979ce2d103fbfc52afb Reviewed-on: https://go-review.googlesource.com/c/go/+/353729 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Carlos Amedee --- src/io/example_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/io/example_test.go b/src/io/example_test.go index f6d9fd575f..419e449982 100644 --- a/src/io/example_test.go +++ b/src/io/example_test.go @@ -142,7 +142,9 @@ func ExampleTeeReader() { r = io.TeeReader(r, os.Stdout) // Everything read from r will be copied to stdout. - io.ReadAll(r) + if _, err := io.ReadAll(r); err != nil { + log.Fatal(err) + } // Output: // some io.Reader stream to be read -- GitLab From f1935c52703e4482c5047b4b35276e965896df7c Mon Sep 17 00:00:00 2001 From: hasheddan Date: Thu, 11 Nov 2021 10:02:13 -0500 Subject: [PATCH 2124/2500] obj/riscv: fix link to risc-v dwarf register numbers The repository name and structure in the RISC-V GitHub org has been modified, rendering the existing link invalid. This updates to point at the new location of the RISC-V DWARF specification. Change occured in https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/208 Change-Id: I8ca4c390bee2d7ce20418cdd00e4945a426cf5f7 Reviewed-on: https://go-review.googlesource.com/c/go/+/363355 Reviewed-by: Brad Fitzpatrick Trust: Brad Fitzpatrick Trust: Than McIntosh --- src/cmd/internal/obj/riscv/cpu.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/internal/obj/riscv/cpu.go b/src/cmd/internal/obj/riscv/cpu.go index ed88f621d9..d9434e7415 100644 --- a/src/cmd/internal/obj/riscv/cpu.go +++ b/src/cmd/internal/obj/riscv/cpu.go @@ -183,7 +183,7 @@ const ( REGG = REG_G ) -// https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md#dwarf-register-numbers +// https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-dwarf.adoc#dwarf-register-numbers var RISCV64DWARFRegisters = map[int16]int16{ // Integer Registers. REG_X0: 0, -- GitLab From d60a4e69f16f5bc958094af206ac7e47f6bc8b04 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 11 Nov 2021 08:36:15 -0800 Subject: [PATCH 2125/2500] spec: fix a broken link Thanks for jtagcat@ for finding this. Change-Id: If7324808edbae19ec8bf503b04e0426f3fb3b47a Reviewed-on: https://go-review.googlesource.com/c/go/+/363394 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- doc/go1.17_spec.html | 2 +- doc/go_spec.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/go1.17_spec.html b/doc/go1.17_spec.html index 46eebb5713..0b374e7bfb 100644 --- a/doc/go1.17_spec.html +++ b/doc/go1.17_spec.html @@ -258,7 +258,7 @@ continue for import return var

The following character sequences represent operators -(including assignment operators) and punctuation: +(including assignment operators) and punctuation:

 +    &     +=    &=     &&    ==    !=    (    )
diff --git a/doc/go_spec.html b/doc/go_spec.html
index 46eebb5713..0b374e7bfb 100644
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -258,7 +258,7 @@ continue     for          import       return       var
 
 

The following character sequences represent operators -(including assignment operators) and punctuation: +(including assignment operators) and punctuation:

 +    &     +=    &=     &&    ==    !=    (    )
-- 
GitLab


From 48f1cde942959e2fc3c56973a2986c24d554c82c Mon Sep 17 00:00:00 2001
From: Pavel 
Date: Mon, 8 Nov 2021 14:29:16 +0000
Subject: [PATCH 2126/2500] database/sql: prevent closes slices from assigning
 to free conn

In function connectionCleanerRunLocked append to closing slice affects db.freeConns and vise versa. Sometimes valid connections are closed and some invalid not.

Change-Id: I5282f15be3e549533b7d994b17b2060db3c0e7da
GitHub-Last-Rev: b3eb3ab6f49c036519f777fc7189e9507010c166
GitHub-Pull-Request: golang/go#49429
Reviewed-on: https://go-review.googlesource.com/c/go/+/362214
Reviewed-by: Daniel Theophanes 
Reviewed-by: Ian Lance Taylor 
---
 src/database/sql/sql.go      |  2 +-
 src/database/sql/sql_test.go | 61 +++++++++++++++++++++++++++++-------
 2 files changed, 50 insertions(+), 13 deletions(-)

diff --git a/src/database/sql/sql.go b/src/database/sql/sql.go
index 5131c08b51..c5b4f50aa7 100644
--- a/src/database/sql/sql.go
+++ b/src/database/sql/sql.go
@@ -1115,7 +1115,7 @@ func (db *DB) connectionCleanerRunLocked(d time.Duration) (time.Duration, []*dri
 			c := db.freeConn[i]
 			if c.returnedAt.Before(idleSince) {
 				i++
-				closing = db.freeConn[:i]
+				closing = db.freeConn[:i:i]
 				db.freeConn = db.freeConn[i:]
 				idleClosing = int64(len(closing))
 				db.maxIdleTimeClosed += idleClosing
diff --git a/src/database/sql/sql_test.go b/src/database/sql/sql_test.go
index 889adc3164..b887b40d71 100644
--- a/src/database/sql/sql_test.go
+++ b/src/database/sql/sql_test.go
@@ -3910,6 +3910,10 @@ func testUseConns(t *testing.T, count int, tm time.Time, db *DB) time.Time {
 	conns := make([]*Conn, count)
 	ctx := context.Background()
 	for i := range conns {
+		tm = tm.Add(time.Nanosecond)
+		nowFunc = func() time.Time {
+			return tm
+		}
 		c, err := db.Conn(ctx)
 		if err != nil {
 			t.Error(err)
@@ -3917,12 +3921,12 @@ func testUseConns(t *testing.T, count int, tm time.Time, db *DB) time.Time {
 		conns[i] = c
 	}
 
-	for _, c := range conns {
+	for i := len(conns) - 1; i >= 0; i-- {
 		tm = tm.Add(time.Nanosecond)
 		nowFunc = func() time.Time {
 			return tm
 		}
-		if err := c.Close(); err != nil {
+		if err := conns[i].Close(); err != nil {
 			t.Error(err)
 		}
 	}
@@ -3934,18 +3938,46 @@ func TestMaxIdleTime(t *testing.T) {
 	usedConns := 5
 	reusedConns := 2
 	list := []struct {
-		wantMaxIdleTime time.Duration
-		wantNextCheck   time.Duration
-		wantIdleClosed  int64
-		timeOffset      time.Duration
+		wantMaxIdleTime   time.Duration
+		wantMaxLifetime   time.Duration
+		wantNextCheck     time.Duration
+		wantIdleClosed    int64
+		wantMaxIdleClosed int64
+		timeOffset        time.Duration
+		secondTimeOffset  time.Duration
 	}{
 		{
 			time.Millisecond,
+			0,
 			time.Millisecond - time.Nanosecond,
 			int64(usedConns - reusedConns),
+			int64(usedConns - reusedConns),
+			10 * time.Millisecond,
+			0,
+		},
+		{
+			// Want to close some connections via max idle time and one by max lifetime.
+			time.Millisecond,
+			// nowFunc() - MaxLifetime should be 1 * time.Nanosecond in connectionCleanerRunLocked.
+			// This guarantees that first opened connection is to be closed.
+			// Thus it is timeOffset + secondTimeOffset + 3 (+2 for Close while reusing conns and +1 for Conn).
+			10*time.Millisecond + 100*time.Nanosecond + 3*time.Nanosecond,
+			time.Nanosecond,
+			// Closed all not reused connections and extra one by max lifetime.
+			int64(usedConns - reusedConns + 1),
+			int64(usedConns - reusedConns),
 			10 * time.Millisecond,
+			// Add second offset because otherwise connections are expired via max lifetime in Close.
+			100 * time.Nanosecond,
 		},
-		{time.Hour, time.Second, 0, 10 * time.Millisecond},
+		{
+			time.Hour,
+			0,
+			time.Second,
+			0,
+			0,
+			10 * time.Millisecond,
+			0},
 	}
 	baseTime := time.Unix(0, 0)
 	defer func() {
@@ -3962,18 +3994,23 @@ func TestMaxIdleTime(t *testing.T) {
 			db.SetMaxOpenConns(usedConns)
 			db.SetMaxIdleConns(usedConns)
 			db.SetConnMaxIdleTime(item.wantMaxIdleTime)
-			db.SetConnMaxLifetime(0)
+			db.SetConnMaxLifetime(item.wantMaxLifetime)
 
 			preMaxIdleClosed := db.Stats().MaxIdleTimeClosed
 
 			// Busy usedConns.
-			tm := testUseConns(t, usedConns, baseTime, db)
+			testUseConns(t, usedConns, baseTime, db)
 
-			tm = baseTime.Add(item.timeOffset)
+			tm := baseTime.Add(item.timeOffset)
 
 			// Reuse connections which should never be considered idle
 			// and exercises the sorting for issue 39471.
-			testUseConns(t, reusedConns, tm, db)
+			tm = testUseConns(t, reusedConns, tm, db)
+
+			tm = tm.Add(item.secondTimeOffset)
+			nowFunc = func() time.Time {
+				return tm
+			}
 
 			db.mu.Lock()
 			nc, closing := db.connectionCleanerRunLocked(time.Second)
@@ -4001,7 +4038,7 @@ func TestMaxIdleTime(t *testing.T) {
 
 			st := db.Stats()
 			maxIdleClosed := st.MaxIdleTimeClosed - preMaxIdleClosed
-			if g, w := maxIdleClosed, item.wantIdleClosed; g != w {
+			if g, w := maxIdleClosed, item.wantMaxIdleClosed; g != w {
 				t.Errorf("got: %d; want %d max idle closed conns", g, w)
 			}
 		})
-- 
GitLab


From 3e94140465984ff6c8d658051d022e8eacf057c3 Mon Sep 17 00:00:00 2001
From: Michael Anthony Knyszek 
Date: Wed, 10 Nov 2021 22:03:28 +0000
Subject: [PATCH 2127/2500] runtime/debug: make TestFreeOSMemory more robust

FreeOSMemory relies on the function FreeOSMemory increasing HeapReleased
as opposed to the background scavenger, because it reads memory stats
*after* the free of a large allocation. However, before that even
happens, the background scavenger can swoop in and release all that
memory, making it appear as if FreeOSMemory didn't do anything.

This change modifies the test to just make sure that the large
allocation's memory is returned to the OS *somehow*, by the end of the
test. It doesn't really care which happens. It also increases the size
of that large allocation to increase the likelihood that the test isn't
relying 100% on the background scavenger, and that FreeOSMemory is doing
some of the work.

Fixes #49478.

Change-Id: Ief1d839753720ebb88cbb616c46302293ee2d19c
Reviewed-on: https://go-review.googlesource.com/c/go/+/363414
Reviewed-by: David Chase 
Trust: Michael Knyszek 
---
 src/runtime/debug/garbage_test.go | 65 ++++++++++++++++++++++++++-----
 1 file changed, 55 insertions(+), 10 deletions(-)

diff --git a/src/runtime/debug/garbage_test.go b/src/runtime/debug/garbage_test.go
index 69e769ecf2..c3501408dd 100644
--- a/src/runtime/debug/garbage_test.go
+++ b/src/runtime/debug/garbage_test.go
@@ -6,6 +6,7 @@ package debug_test
 
 import (
 	"internal/testenv"
+	"os"
 	"runtime"
 	. "runtime/debug"
 	"testing"
@@ -87,21 +88,65 @@ func TestReadGCStats(t *testing.T) {
 	}
 }
 
-var big = make([]byte, 1<<20)
+var big []byte
 
 func TestFreeOSMemory(t *testing.T) {
-	var ms1, ms2 runtime.MemStats
+	// Tests FreeOSMemory by making big susceptible to collection
+	// and checking that at least that much memory is returned to
+	// the OS after.
 
-	if big == nil {
-		t.Skip("test is not reliable when run multiple times")
-	}
-	big = nil
+	const bigBytes = 32 << 20
+	big = make([]byte, bigBytes)
+
+	// Make sure any in-progress GCs are complete.
 	runtime.GC()
-	runtime.ReadMemStats(&ms1)
+
+	var before runtime.MemStats
+	runtime.ReadMemStats(&before)
+
+	// Clear the last reference to the big allocation, making it
+	// susceptible to collection.
+	big = nil
+
+	// FreeOSMemory runs a GC cycle before releasing memory,
+	// so it's fine to skip a GC here.
+	//
+	// It's possible the background scavenger runs concurrently
+	// with this function and does most of the work for it.
+	// If that happens, it's OK. What we want is a test that fails
+	// often if FreeOSMemory does not work correctly, and a test
+	// that passes every time if it does.
 	FreeOSMemory()
-	runtime.ReadMemStats(&ms2)
-	if ms1.HeapReleased >= ms2.HeapReleased {
-		t.Errorf("released before=%d; released after=%d; did not go up", ms1.HeapReleased, ms2.HeapReleased)
+
+	var after runtime.MemStats
+	runtime.ReadMemStats(&after)
+
+	// Check to make sure that the big allocation (now freed)
+	// had its memory shift into HeapReleased as a result of that
+	// FreeOSMemory.
+	if after.HeapReleased <= before.HeapReleased {
+		t.Fatalf("no memory released: %d -> %d", before.HeapReleased, after.HeapReleased)
+	}
+
+	// Check to make sure bigBytes was released, plus some slack. Pages may get
+	// allocated in between the two measurements above for a variety for reasons,
+	// most commonly for GC work bufs. Since this can get fairly high, depending
+	// on scheduling and what GOMAXPROCS is, give a lot of slack up-front.
+	//
+	// Add a little more slack too if the page size is bigger than the runtime page size.
+	// "big" could end up unaligned on its ends, forcing the scavenger to skip at worst
+	// 2x pages.
+	slack := uint64(bigBytes / 2)
+	pageSize := uint64(os.Getpagesize())
+	if pageSize > 8<<10 {
+		slack += pageSize * 2
+	}
+	if slack > bigBytes {
+		// We basically already checked this.
+		return
+	}
+	if after.HeapReleased-before.HeapReleased < bigBytes-slack {
+		t.Fatalf("less than %d released: %d -> %d", bigBytes, before.HeapReleased, after.HeapReleased)
 	}
 }
 
-- 
GitLab


From 46b2fc05a2681a9dd3b606176e738d786b0c2176 Mon Sep 17 00:00:00 2001
From: Michael Anthony Knyszek 
Date: Thu, 11 Nov 2021 17:31:36 +0000
Subject: [PATCH 2128/2500] runtime: adjust TestPhysicalMemoryUtilization to
 handle large page sizes

Currently TestPhysicalMemoryUtilization can fail on systems with large
physical page sizes like 64 KiB because all the of the holes to be
scavenged are not aligned to the page size. The holes themselves are 64
KiB so this is actually quite likely.

Bump the size of the allocations for systems with larger physical page
sizes, and add additional slack to the threshold for unaligned pieces of
the holes that may be unaligned.

Fixes #49411.

Change-Id: Iafb35b8761dc9cdc53d3745c4771b1a64c5c97b5
Reviewed-on: https://go-review.googlesource.com/c/go/+/363415
Trust: Michael Knyszek 
Reviewed-by: David Chase 
---
 src/runtime/testdata/testprog/gc.go | 26 ++++++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/src/runtime/testdata/testprog/gc.go b/src/runtime/testdata/testprog/gc.go
index 6484c36139..7d371a6a89 100644
--- a/src/runtime/testdata/testprog/gc.go
+++ b/src/runtime/testdata/testprog/gc.go
@@ -140,13 +140,26 @@ func GCPhys() {
 	// returned to the OS.
 
 	const (
+		// The total amount of memory we're willing to allocate.
 		allocTotal = 32 << 20
-		allocChunk = 64 << 10
-		allocs     = allocTotal / allocChunk
 
 		// The page cache could hide 64 8-KiB pages from the scavenger today.
 		maxPageCache = (8 << 10) * 64
 	)
+
+	// How big the allocations are needs to depend on the page size.
+	// If the page size is too big and the allocations are too small,
+	// they might not be aligned to the physical page size, so the scavenger
+	// will gloss over them.
+	pageSize := os.Getpagesize()
+	var allocChunk int
+	if pageSize <= 8<<10 {
+		allocChunk = 64 << 10
+	} else {
+		allocChunk = 512 << 10
+	}
+	allocs := allocTotal / allocChunk
+
 	// Set GC percent just so this test is a little more consistent in the
 	// face of varying environments.
 	debug.SetGCPercent(100)
@@ -197,7 +210,7 @@ func GCPhys() {
 	//
 	// heapBacked also subtracts out maxPageCache bytes of memory because
 	// this is memory that may be hidden from the scavenger per-P. Since
-	// GOMAXPROCS=1 here, that's fine.
+	// GOMAXPROCS=1 here, subtracting it out once is fine.
 	var stats runtime.MemStats
 	runtime.ReadMemStats(&stats)
 	heapBacked := stats.HeapSys - stats.HeapReleased - maxPageCache
@@ -212,7 +225,12 @@ func GCPhys() {
 	overuse := (float64(heapBacked) - float64(stats.HeapAlloc)) / float64(stats.HeapAlloc)
 	// Check against our overuse threshold, which is what the scavenger always reserves
 	// to encourage allocation of memory that doesn't need to be faulted in.
-	const threshold = 0.1
+	//
+	// Add additional slack in case the page size is large and the scavenger
+	// can't reach that memory because it doesn't constitute a complete aligned
+	// physical page. Assume the worst case: a full physical page out of each
+	// allocation.
+	threshold := 0.1 + float64(pageSize)/float64(allocChunk)
 	if overuse <= threshold {
 		fmt.Println("OK")
 		return
-- 
GitLab


From eb68e3367bf8d55bb98eb002cef35455f5be3c5f Mon Sep 17 00:00:00 2001
From: cuiweixie 
Date: Thu, 11 Nov 2021 07:10:52 +0000
Subject: [PATCH 2129/2500] runtime: fix typo

Change filepath reference from cmd/internal/ld/symtab.go to
cmd/link/internal/ld/symtab.go.

Change-Id: Icb207a2e2c82d3976787d2d5cfb0f8005696f738
GitHub-Last-Rev: 428d99c6ca97db79b7d8cdf24843df3492a9aeb0
GitHub-Pull-Request: golang/go#49518
Reviewed-on: https://go-review.googlesource.com/c/go/+/363276
Reviewed-by: Ian Lance Taylor 
Trust: Brad Fitzpatrick 
---
 src/runtime/symtab.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go
index 3237a6b708..21dd95a397 100644
--- a/src/runtime/symtab.go
+++ b/src/runtime/symtab.go
@@ -408,7 +408,7 @@ type pcHeader struct {
 
 // moduledata records information about the layout of the executable
 // image. It is written by the linker. Any changes here must be
-// matched changes to the code in cmd/internal/ld/symtab.go:symtab.
+// matched changes to the code in cmd/link/internal/ld/symtab.go:symtab.
 // moduledata is stored in statically allocated non-pointer memory;
 // none of the pointers here are visible to the garbage collector.
 type moduledata struct {
-- 
GitLab


From c622d1d3f68369ec5f8ce9694fa27e7acb025004 Mon Sep 17 00:00:00 2001
From: Ian Lance Taylor 
Date: Wed, 10 Nov 2021 20:28:45 -0800
Subject: [PATCH 2130/2500] go/build: skip rune literals when looking for
 go:embed

Fixes #49514

Change-Id: Id687eead731ba49974f11d2e5b489f11eff7d07b
Reviewed-on: https://go-review.googlesource.com/c/go/+/363275
Trust: Ian Lance Taylor 
Run-TryBot: Ian Lance Taylor 
TryBot-Result: Go Bot 
Reviewed-by: Bryan C. Mills 
---
 src/embed/internal/embedtest/embed_test.go |  5 +++++
 src/go/build/read.go                       | 21 +++++++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/src/embed/internal/embedtest/embed_test.go b/src/embed/internal/embedtest/embed_test.go
index bfd94af69d..1337e421bd 100644
--- a/src/embed/internal/embedtest/embed_test.go
+++ b/src/embed/internal/embedtest/embed_test.go
@@ -60,6 +60,11 @@ func testDir(t *testing.T, f embed.FS, name string, expect ...string) {
 	}
 }
 
+// Tests for issue 49514.
+var _ = '"'
+var _ = '\''
+var _ = '🦆'
+
 func TestGlobal(t *testing.T) {
 	testFiles(t, global, "concurrency.txt", "Concurrency is not parallelism.\n")
 	testFiles(t, global, "testdata/hello.txt", "hello, world\n")
diff --git a/src/go/build/read.go b/src/go/build/read.go
index 6115ef810c..de5c33a4f8 100644
--- a/src/go/build/read.go
+++ b/src/go/build/read.go
@@ -240,6 +240,27 @@ func (r *importReader) findEmbed(first bool) bool {
 				}
 			}
 
+		case '\'':
+			startLine = false
+			for r.err == nil {
+				if r.eof {
+					r.syntaxError()
+				}
+				c = r.readByteNoBuf()
+				if c == '\\' {
+					r.readByteNoBuf()
+					if r.err != nil {
+						r.syntaxError()
+						return false
+					}
+					continue
+				}
+				if c == '\'' {
+					c = r.readByteNoBuf()
+					goto Reswitch
+				}
+			}
+
 		case '/':
 			c = r.readByteNoBuf()
 			switch c {
-- 
GitLab


From 10d3b1355184320f6d9623cb35e848e5af7c29ed Mon Sep 17 00:00:00 2001
From: Keith Randall 
Date: Thu, 11 Nov 2021 08:45:02 -0800
Subject: [PATCH 2131/2500] cmd/compile: ensure stenciled function bodies are
 nonempty

Our compiler gets confused between functions that were declared
with no body, and those which have a body but it is empty.

Ensure that when stenciling, we generate a nonempty body.

The particular test that causes this problem is in
cmd/compile/internal/gc/main.go:enqueueFunc. It thinks that if
a function has no body, then we need to generate ABI wrappers for
it, but not compile it.

Fixes #49524

Change-Id: Id962666a2098f60a2421484b6a776eafdc4f4a63
Reviewed-on: https://go-review.googlesource.com/c/go/+/363395
Trust: Keith Randall 
Trust: Dan Scales 
Run-TryBot: Keith Randall 
TryBot-Result: Go Bot 
Reviewed-by: Dan Scales 
---
 src/cmd/compile/internal/noder/stencil.go |  6 ++++++
 test/typeparam/issue49524.dir/a.go        |  8 ++++++++
 test/typeparam/issue49524.dir/main.go     | 11 +++++++++++
 test/typeparam/issue49524.go              |  7 +++++++
 4 files changed, 32 insertions(+)
 create mode 100644 test/typeparam/issue49524.dir/a.go
 create mode 100644 test/typeparam/issue49524.dir/main.go
 create mode 100644 test/typeparam/issue49524.go

diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go
index c8c5d80cfc..20197565f5 100644
--- a/src/cmd/compile/internal/noder/stencil.go
+++ b/src/cmd/compile/internal/noder/stencil.go
@@ -802,6 +802,12 @@ func (g *genInst) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes []*t
 
 	// Make sure name/type of newf is set before substituting the body.
 	newf.Body = subst.list(gf.Body)
+	if len(newf.Body) == 0 {
+		// Ensure the body is nonempty, for issue 49524.
+		// TODO: have some other way to detect the difference between
+		// a function declared with no body, vs. one with an empty body?
+		newf.Body = append(newf.Body, ir.NewBlockStmt(gf.Pos(), nil))
+	}
 
 	if len(subst.defnMap) > 0 {
 		base.Fatalf("defnMap is not empty")
diff --git a/test/typeparam/issue49524.dir/a.go b/test/typeparam/issue49524.dir/a.go
new file mode 100644
index 0000000000..f40075e953
--- /dev/null
+++ b/test/typeparam/issue49524.dir/a.go
@@ -0,0 +1,8 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+func F[T any]() {
+}
diff --git a/test/typeparam/issue49524.dir/main.go b/test/typeparam/issue49524.dir/main.go
new file mode 100644
index 0000000000..ef00c8a81c
--- /dev/null
+++ b/test/typeparam/issue49524.dir/main.go
@@ -0,0 +1,11 @@
+package main
+
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+import "a"
+
+func main() {
+	a.F[int]()
+}
diff --git a/test/typeparam/issue49524.go b/test/typeparam/issue49524.go
new file mode 100644
index 0000000000..76930e5e4f
--- /dev/null
+++ b/test/typeparam/issue49524.go
@@ -0,0 +1,7 @@
+// rundir -G=3
+
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
-- 
GitLab


From ccd41cc05e3ee2f0d0ded1d7faf9c1f43ce1037b Mon Sep 17 00:00:00 2001
From: Robert Griesemer 
Date: Thu, 11 Nov 2021 11:57:43 -0800
Subject: [PATCH 2132/2500] go/types, types2: document nil scope for imported
 and instantiated Func objects

Also, don't set the scope anymore when instantiating (substituting)
a signature.

Per discussion with rfindley.

Change-Id: I560d4571c7ff14b0df3e15fece634cb5f9f94a99
Reviewed-on: https://go-review.googlesource.com/c/go/+/363435
Trust: Robert Griesemer 
Run-TryBot: Robert Griesemer 
TryBot-Result: Go Bot 
Reviewed-by: Robert Findley 
---
 src/cmd/compile/internal/types2/object.go    | 2 ++
 src/cmd/compile/internal/types2/signature.go | 2 +-
 src/cmd/compile/internal/types2/subst.go     | 4 ++--
 src/go/types/object.go                       | 2 ++
 src/go/types/signature.go                    | 2 +-
 src/go/types/subst.go                        | 4 ++--
 6 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/src/cmd/compile/internal/types2/object.go b/src/cmd/compile/internal/types2/object.go
index d86c166c72..da3e1a2abc 100644
--- a/src/cmd/compile/internal/types2/object.go
+++ b/src/cmd/compile/internal/types2/object.go
@@ -389,6 +389,8 @@ func (obj *Func) FullName() string {
 }
 
 // Scope returns the scope of the function's body block.
+// The result is nil for imported or instantiated functions and methods
+// (but there is also no mechanism to get to an instantiated function).
 func (obj *Func) Scope() *Scope { return obj.typ.(*Signature).scope }
 
 // hasPtrRecv reports whether the receiver is of the form *T for the given method obj.
diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go
index 4541435587..b0b8ad49d9 100644
--- a/src/cmd/compile/internal/types2/signature.go
+++ b/src/cmd/compile/internal/types2/signature.go
@@ -18,7 +18,7 @@ type Signature struct {
 	// We then unpack the *Signature and use the scope for the literal body.
 	rparams  *TypeParamList // receiver type parameters from left to right, or nil
 	tparams  *TypeParamList // type parameters from left to right, or nil
-	scope    *Scope         // function scope, present for package-local signatures
+	scope    *Scope         // function scope for package-local and non-instantiated signatures; nil otherwise
 	recv     *Var           // nil if not a method
 	params   *Tuple         // (incoming) parameters from left to right; or nil
 	results  *Tuple         // (outgoing) results from left to right; or nil
diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go
index a4e46b2097..f46e895b12 100644
--- a/src/cmd/compile/internal/types2/subst.go
+++ b/src/cmd/compile/internal/types2/subst.go
@@ -115,8 +115,8 @@ func (subst *subster) typ(typ Type) Type {
 			return &Signature{
 				rparams: t.rparams,
 				// TODO(gri) why can't we nil out tparams here, rather than in instantiate?
-				tparams:  t.tparams,
-				scope:    t.scope,
+				tparams: t.tparams,
+				// instantiated signatures have a nil scope
 				recv:     recv,
 				params:   params,
 				results:  results,
diff --git a/src/go/types/object.go b/src/go/types/object.go
index e7a4425643..9309a529c4 100644
--- a/src/go/types/object.go
+++ b/src/go/types/object.go
@@ -343,6 +343,8 @@ func (obj *Func) FullName() string {
 }
 
 // Scope returns the scope of the function's body block.
+// The result is nil for imported or instantiated functions and methods
+// (but there is also no mechanism to get to an instantiated function).
 func (obj *Func) Scope() *Scope { return obj.typ.(*Signature).scope }
 
 // hasPtrRecv reports whether the receiver is of the form *T for the given method obj.
diff --git a/src/go/types/signature.go b/src/go/types/signature.go
index ad69c95d12..3e0a046afa 100644
--- a/src/go/types/signature.go
+++ b/src/go/types/signature.go
@@ -21,7 +21,7 @@ type Signature struct {
 	// We then unpack the *Signature and use the scope for the literal body.
 	rparams  *TypeParamList // receiver type parameters from left to right, or nil
 	tparams  *TypeParamList // type parameters from left to right, or nil
-	scope    *Scope         // function scope, present for package-local signatures
+	scope    *Scope         // function scope for package-local and non-instantiated signatures; nil otherwise
 	recv     *Var           // nil if not a method
 	params   *Tuple         // (incoming) parameters from left to right; or nil
 	results  *Tuple         // (outgoing) results from left to right; or nil
diff --git a/src/go/types/subst.go b/src/go/types/subst.go
index 1fac82fe8a..a05195150f 100644
--- a/src/go/types/subst.go
+++ b/src/go/types/subst.go
@@ -115,8 +115,8 @@ func (subst *subster) typ(typ Type) Type {
 			return &Signature{
 				rparams: t.rparams,
 				// TODO(rFindley) why can't we nil out tparams here, rather than in instantiate?
-				tparams:  t.tparams,
-				scope:    t.scope,
+				tparams: t.tparams,
+				// instantiated signatures have a nil scope
 				recv:     recv,
 				params:   params,
 				results:  results,
-- 
GitLab


From 9d89a5eb64f25ce0e7cc6086d44b6f327cbb302c Mon Sep 17 00:00:00 2001
From: Katie Hockman 
Date: Tue, 9 Nov 2021 17:13:36 -0500
Subject: [PATCH 2133/2500] all: update terminology for fuzzing

This change doesn't modify any functionality.
It also doesn't update all of the comments and
variable names of the internal code, but everything
user facing should be correct.

Updates #49185

Change-Id: Ia8b2c94b89ba45897c4085ea0c17a3d8896f7ec7
Reviewed-on: https://go-review.googlesource.com/c/go/+/362794
Trust: Katie Hockman 
Run-TryBot: Katie Hockman 
TryBot-Result: Go Bot 
Reviewed-by: Roland Shoemaker 
---
 src/cmd/go/alldocs.go                         |  31 ++--
 src/cmd/go/internal/test/test.go              |  43 +++---
 src/cmd/go/testdata/script/test_fuzz.txt      |  10 +-
 .../go/testdata/script/test_fuzz_match.txt    |   4 +-
 .../go/testdata/script/test_fuzz_multiple.txt |   2 +-
 .../script/test_fuzz_mutator_repeat.txt       |   2 +-
 .../testdata/script/test_fuzz_seed_corpus.txt |  22 +--
 src/go/doc/example.go                         |   6 +-
 src/internal/fuzz/fuzz.go                     |   4 +-
 src/testing/fuzz.go                           | 138 +++++++++---------
 src/testing/testing.go                        |  57 ++++----
 11 files changed, 160 insertions(+), 159 deletions(-)

diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go
index ff144f9847..dfb88ab78d 100644
--- a/src/cmd/go/alldocs.go
+++ b/src/cmd/go/alldocs.go
@@ -1547,7 +1547,7 @@
 // 'Go test' recompiles each package along with any files with names matching
 // the file pattern "*_test.go".
 // These additional files can contain test functions, benchmark functions, fuzz
-// targets and example functions. See 'go help testfunc' for more.
+// tests and example functions. See 'go help testfunc' for more.
 // Each listed package causes the execution of a separate test binary.
 // Files whose names begin with "_" (including "_test.go") or "." are ignored.
 //
@@ -2796,7 +2796,7 @@
 // 	    Run each test, benchmark, and fuzz seed n times (default 1).
 // 	    If -cpu is set, run n times for each GOMAXPROCS value.
 // 	    Examples are always run once. -count does not apply to
-// 	    fuzz targets matched by -fuzz.
+// 	    fuzz tests matched by -fuzz.
 //
 // 	-cover
 // 	    Enable coverage analysis.
@@ -2824,20 +2824,19 @@
 //
 // 	-cpu 1,2,4
 // 	    Specify a list of GOMAXPROCS values for which the tests, benchmarks or
-// 	    fuzz targets should be executed. The default is the current value
-// 	    of GOMAXPROCS. -cpu does not apply to fuzz targets matched by -fuzz.
+// 	    fuzz tests should be executed. The default is the current value
+// 	    of GOMAXPROCS. -cpu does not apply to fuzz tests matched by -fuzz.
 //
 // 	-failfast
 // 	    Do not start new tests after the first test failure.
 //
 // 	-fuzz regexp
-// 	    Run the fuzz target matching the regular expression. When specified,
+// 	    Run the fuzz test matching the regular expression. When specified,
 // 	    the command line argument must match exactly one package within the
-// 	    main module, and regexp must match exactly one fuzz target within
-// 	    that package. After tests, benchmarks, seed corpora of other fuzz
-// 	    targets, and examples have completed, the matching target will be
-// 	    fuzzed. See the Fuzzing section of the testing package documentation
-// 	    for details.
+// 	    main module, and regexp must match exactly one fuzz test within
+// 	    that package. Fuzzing will occur after tests, benchmarks, seed corpora
+// 	    of other fuzz tests, and examples have completed. See the Fuzzing
+// 	    section of the testing package documentation for details.
 //
 // 	-fuzztime t
 // 	    Run enough iterations of the fuzz test to take t, specified as a
@@ -2851,14 +2850,14 @@
 // 	    same information as the -v flag in a machine-readable format.
 //
 // 	-list regexp
-// 	    List tests, benchmarks, fuzz targets, or examples matching the regular
-// 	    expression. No tests, benchmarks, fuzz targets, or examples will be run.
+// 	    List tests, benchmarks, fuzz tests, or examples matching the regular
+// 	    expression. No tests, benchmarks, fuzz tests, or examples will be run.
 // 	    This will only list top-level tests. No subtest or subbenchmarks will be
 // 	    shown.
 //
 // 	-parallel n
 // 	    Allow parallel execution of test functions that call t.Parallel, and
-// 	    f.Fuzz functions that call t.Parallel when running the seed corpus.
+// 	    fuzz targets that call t.Parallel when running the seed corpus.
 // 	    The value of this flag is the maximum number of tests to run
 // 	    simultaneously.
 // 	    While fuzzing, the value of this flag is the maximum number of
@@ -2873,7 +2872,7 @@
 // 	    (see 'go help build').
 //
 // 	-run regexp
-// 	    Run only those tests, examples, and fuzz targets matching the regular
+// 	    Run only those tests, examples, and fuzz tests matching the regular
 // 	    expression. For tests, the regular expression is split by unbracketed
 // 	    slash (/) characters into a sequence of regular expressions, and each
 // 	    part of a test's identifier must match the corresponding element in
@@ -3047,7 +3046,7 @@
 //
 // 	func BenchmarkXxx(b *testing.B) { ... }
 //
-// A fuzz target is one named FuzzXxx and should have the signature,
+// A fuzz test is one named FuzzXxx and should have the signature,
 //
 // 	func FuzzXxx(f *testing.F) { ... }
 //
@@ -3090,7 +3089,7 @@
 //
 // The entire test file is presented as the example when it contains a single
 // example function, at least one other function, type, variable, or constant
-// declaration, and no fuzz targets or test or benchmark functions.
+// declaration, and no tests, benchmarks, or fuzz tests.
 //
 // See the documentation of the testing package for more information.
 //
diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go
index 7361c11786..73abca8927 100644
--- a/src/cmd/go/internal/test/test.go
+++ b/src/cmd/go/internal/test/test.go
@@ -65,7 +65,7 @@ followed by detailed output for each failed package.
 'Go test' recompiles each package along with any files with names matching
 the file pattern "*_test.go".
 These additional files can contain test functions, benchmark functions, fuzz
-targets and example functions. See 'go help testfunc' for more.
+tests and example functions. See 'go help testfunc' for more.
 Each listed package causes the execution of a separate test binary.
 Files whose names begin with "_" (including "_test.go") or "." are ignored.
 
@@ -214,7 +214,7 @@ control the execution of any test:
 	    Run each test, benchmark, and fuzz seed n times (default 1).
 	    If -cpu is set, run n times for each GOMAXPROCS value.
 	    Examples are always run once. -count does not apply to
-	    fuzz targets matched by -fuzz.
+	    fuzz tests matched by -fuzz.
 
 	-cover
 	    Enable coverage analysis.
@@ -242,20 +242,19 @@ control the execution of any test:
 
 	-cpu 1,2,4
 	    Specify a list of GOMAXPROCS values for which the tests, benchmarks or
-	    fuzz targets should be executed. The default is the current value
-	    of GOMAXPROCS. -cpu does not apply to fuzz targets matched by -fuzz.
+	    fuzz tests should be executed. The default is the current value
+	    of GOMAXPROCS. -cpu does not apply to fuzz tests matched by -fuzz.
 
 	-failfast
 	    Do not start new tests after the first test failure.
 
 	-fuzz regexp
-	    Run the fuzz target matching the regular expression. When specified,
+	    Run the fuzz test matching the regular expression. When specified,
 	    the command line argument must match exactly one package within the
-	    main module, and regexp must match exactly one fuzz target within
-	    that package. After tests, benchmarks, seed corpora of other fuzz
-	    targets, and examples have completed, the matching target will be
-	    fuzzed. See the Fuzzing section of the testing package documentation
-	    for details.
+	    main module, and regexp must match exactly one fuzz test within
+	    that package. Fuzzing will occur after tests, benchmarks, seed corpora
+	    of other fuzz tests, and examples have completed. See the Fuzzing
+	    section of the testing package documentation for details.
 
 	-fuzztime t
 	    Run enough iterations of the fuzz test to take t, specified as a
@@ -269,14 +268,14 @@ control the execution of any test:
 	    same information as the -v flag in a machine-readable format.
 
 	-list regexp
-	    List tests, benchmarks, fuzz targets, or examples matching the regular
-	    expression. No tests, benchmarks, fuzz targets, or examples will be run.
+	    List tests, benchmarks, fuzz tests, or examples matching the regular
+	    expression. No tests, benchmarks, fuzz tests, or examples will be run.
 	    This will only list top-level tests. No subtest or subbenchmarks will be
 	    shown.
 
 	-parallel n
 	    Allow parallel execution of test functions that call t.Parallel, and
-	    f.Fuzz functions that call t.Parallel when running the seed corpus.
+	    fuzz targets that call t.Parallel when running the seed corpus.
 	    The value of this flag is the maximum number of tests to run
 	    simultaneously.
 	    While fuzzing, the value of this flag is the maximum number of
@@ -291,7 +290,7 @@ control the execution of any test:
 	    (see 'go help build').
 
 	-run regexp
-	    Run only those tests, examples, and fuzz targets matching the regular
+	    Run only those tests, examples, and fuzz tests matching the regular
 	    expression. For tests, the regular expression is split by unbracketed
 	    slash (/) characters into a sequence of regular expressions, and each
 	    part of a test's identifier must match the corresponding element in
@@ -468,7 +467,7 @@ A benchmark function is one named BenchmarkXxx and should have the signature,
 
 	func BenchmarkXxx(b *testing.B) { ... }
 
-A fuzz target is one named FuzzXxx and should have the signature,
+A fuzz test is one named FuzzXxx and should have the signature,
 
 	func FuzzXxx(f *testing.F) { ... }
 
@@ -511,7 +510,7 @@ Here is another example where the ordering of the output is ignored:
 
 The entire test file is presented as the example when it contains a single
 example function, at least one other function, type, variable, or constant
-declaration, and no fuzz targets or test or benchmark functions.
+declaration, and no tests, benchmarks, or fuzz tests.
 
 See the documentation of the testing package for more information.
 `,
@@ -1196,8 +1195,8 @@ func declareCoverVars(p *load.Package, files ...string) map[string]*load.CoverVa
 }
 
 var noTestsToRun = []byte("\ntesting: warning: no tests to run\n")
-var noTargetsToFuzz = []byte("\ntesting: warning: no targets to fuzz\n")
-var tooManyTargetsToFuzz = []byte("\ntesting: warning: -fuzz matches more than one target, won't fuzz\n")
+var noFuzzTestsToFuzz = []byte("\ntesting: warning: no fuzz tests to fuzz\n")
+var tooManyFuzzTestsToFuzz = []byte("\ntesting: warning: -fuzz matches more than one fuzz test, won't fuzz\n")
 
 type runCache struct {
 	disableCache bool // cache should be disabled for this run
@@ -1399,11 +1398,11 @@ func (c *runCache) builderRunTest(b *work.Builder, ctx context.Context, a *work.
 		if bytes.HasPrefix(out, noTestsToRun[1:]) || bytes.Contains(out, noTestsToRun) {
 			norun = " [no tests to run]"
 		}
-		if bytes.HasPrefix(out, noTargetsToFuzz[1:]) || bytes.Contains(out, noTargetsToFuzz) {
-			norun = " [no targets to fuzz]"
+		if bytes.HasPrefix(out, noFuzzTestsToFuzz[1:]) || bytes.Contains(out, noFuzzTestsToFuzz) {
+			norun = " [no fuzz tests to fuzz]"
 		}
-		if bytes.HasPrefix(out, tooManyTargetsToFuzz[1:]) || bytes.Contains(out, tooManyTargetsToFuzz) {
-			norun = " [will not fuzz, -fuzz matches more than one target]"
+		if bytes.HasPrefix(out, tooManyFuzzTestsToFuzz[1:]) || bytes.Contains(out, tooManyFuzzTestsToFuzz) {
+			norun = "[-fuzz matches more than one fuzz test, won't fuzz]"
 		}
 		if len(out) > 0 && !bytes.HasSuffix(out, []byte("\n")) {
 			// Ensure that the output ends with a newline before the "ok"
diff --git a/src/cmd/go/testdata/script/test_fuzz.txt b/src/cmd/go/testdata/script/test_fuzz.txt
index 150491be04..3e048e00c5 100644
--- a/src/cmd/go/testdata/script/test_fuzz.txt
+++ b/src/cmd/go/testdata/script/test_fuzz.txt
@@ -60,34 +60,34 @@ stdout ok
 ! stdout ^ok
 ! stdout 'fatal here'
 stdout FAIL
-stdout 'f.Fuzz function'
+stdout 'fuzz target'
 
 # Test that f.Error within f.Fuzz panics
 ! go test error_fuzz_fn_fuzz_test.go
 ! stdout ^ok
 ! stdout 'error here'
 stdout FAIL
-stdout 'f.Fuzz function'
+stdout 'fuzz target'
 
 # Test that f.Fail within f.Fuzz panics
 ! go test fail_fuzz_fn_fuzz_test.go
 ! stdout ^ok
 stdout FAIL
-stdout 'f.Fuzz function'
+stdout 'fuzz target'
 
 # Test that f.Skip within f.Fuzz panics
 ! go test skip_fuzz_fn_fuzz_test.go
 ! stdout ^ok
 ! stdout 'skip here'
 stdout FAIL
-stdout 'f.Fuzz function'
+stdout 'fuzz target'
 
 # Test that f.Skipped within f.Fuzz panics
 ! go test skipped_fuzz_fn_fuzz_test.go
 ! stdout ^ok
 ! stdout 'f.Skipped is'
 stdout FAIL
-stdout 'f.Fuzz function'
+stdout 'fuzz target'
 stdout 't.Skipped is false'
 
 # Test that runtime.Goexit within the fuzz function is an error.
diff --git a/src/cmd/go/testdata/script/test_fuzz_match.txt b/src/cmd/go/testdata/script/test_fuzz_match.txt
index 0c0085f2c2..dbf987605f 100644
--- a/src/cmd/go/testdata/script/test_fuzz_match.txt
+++ b/src/cmd/go/testdata/script/test_fuzz_match.txt
@@ -14,7 +14,7 @@ stdout '^ok'
 go test -fuzz ThisWillNotMatch -fuzztime 1x standalone_fuzz_test.go
 ! stdout '^ok.*no tests to run'
 stdout '^ok'
-stdout 'no targets to fuzz'
+stdout 'no fuzz tests to fuzz'
 
 [short] stop
 
@@ -26,7 +26,7 @@ stdout '^ok'
 # Matches no fuzz targets.
 go test -run ThisWillNotMatch standalone_fuzz_test.go
 stdout '^ok.*no tests to run'
-! stdout 'no targets to fuzz'
+! stdout 'no fuzz tests to fuzz'
 
 -- standalone_fuzz_test.go --
 package standalone_fuzz
diff --git a/src/cmd/go/testdata/script/test_fuzz_multiple.txt b/src/cmd/go/testdata/script/test_fuzz_multiple.txt
index d96b2b6206..1ec4985613 100644
--- a/src/cmd/go/testdata/script/test_fuzz_multiple.txt
+++ b/src/cmd/go/testdata/script/test_fuzz_multiple.txt
@@ -18,7 +18,7 @@ go test -fuzz=. -fuzztime=1x ./one
 
 # With fuzzing enabled, at most one target in the same package may match.
 ! go test -fuzz=. ./two
-stdout '^testing: will not fuzz, -fuzz matches more than one target: \[FuzzOne FuzzTwo\]$'
+stdout '^testing: will not fuzz, -fuzz matches more than one fuzz test: \[FuzzOne FuzzTwo\]$'
 go test -fuzz=FuzzTwo -fuzztime=1x ./two
 
 -- go.mod --
diff --git a/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt b/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt
index 15d7cb6b32..60f5787464 100644
--- a/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt
+++ b/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt
@@ -13,7 +13,7 @@
 ! exists want
 ! go test -fuzz=. -parallel=1 -fuzztime=110x -fuzzminimizetime=10x -v
 stdout 'fuzzing process terminated unexpectedly'
-stdout 'Crash written to testdata'
+stdout 'Failing input written to testdata'
 
 # Run the fuzz target without fuzzing. The fuzz function is called with the
 # crashing input in testdata. The test passes if that input is identical to
diff --git a/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt b/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt
index 4be9a6e385..57c8a8ba65 100644
--- a/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt
+++ b/src/cmd/go/testdata/script/test_fuzz_seed_corpus.txt
@@ -6,7 +6,7 @@ env GOCACHE=$WORK/cache
 # and doesn't write anything to testdata/fuzz
 ! go test -fuzz=FuzzWithAdd -run=FuzzWithAdd -fuzztime=1x
 ! stdout ^ok
-! stdout 'Crash written to testdata[/\\]fuzz[/\\]FuzzWithAdd[/\\]'
+! stdout 'Failing input written to testdata[/\\]fuzz[/\\]FuzzWithAdd[/\\]'
 stdout FAIL
 
 # Test that fuzzing a target with a sucess in f.Add and a fuzztime of only
@@ -19,15 +19,15 @@ stdout ok
 # and doesn't write anything to testdata/fuzz
 ! go test -fuzz=FuzzWithTestdata -run=FuzzWithTestdata -fuzztime=1x
 ! stdout ^ok
-! stdout 'Crash written to testdata[/\\]fuzz[/\\]FuzzWithTestdata[/\\]'
-stdout 'found a crash while testing seed corpus entry: FuzzWithTestdata/1'
+! stdout 'Failing input written to testdata[/\\]fuzz[/\\]FuzzWithTestdata[/\\]'
+stdout 'failure while testing seed corpus entry: FuzzWithTestdata/1'
 stdout FAIL
 
 # Test that fuzzing a target with no seed corpus or cache finds a crash, prints
 # it, and write it to testdata
 ! go test -fuzz=FuzzWithNoCache -run=FuzzWithNoCache -fuzztime=1x
 ! stdout ^ok
-stdout 'Crash written to testdata[/\\]fuzz[/\\]FuzzWithNoCache[/\\]'
+stdout 'Failing input written to testdata[/\\]fuzz[/\\]FuzzWithNoCache[/\\]'
 stdout FAIL
 
 # Write a crashing input to the cache
@@ -38,7 +38,7 @@ cp cache-file $GOCACHE/fuzz/example.com/x/FuzzWithCache/1
 # and writes this as a "new" crash to testdata/fuzz
 ! go test -fuzz=FuzzWithCache -run=FuzzWithCache -fuzztime=1x
 ! stdout ^ok
-stdout 'Crash written to testdata[/\\]fuzz[/\\]FuzzWithCache[/\\]'
+stdout 'Failing input written to testdata[/\\]fuzz[/\\]FuzzWithCache[/\\]'
 stdout FAIL
 
 # Write a crashing input to the cache
@@ -52,7 +52,7 @@ cp cache-file-bytes $GOCACHE/fuzz/example.com/x/FuzzWithMinimizableCache/1
 stdout 'gathering baseline coverage'
 stdout 'got the minimum size!'
 stdout 'contains a non-zero byte of length 10'
-stdout 'Crash written to testdata[/\\]fuzz[/\\]FuzzWithMinimizableCache[/\\]'
+stdout 'Failing input written to testdata[/\\]fuzz[/\\]FuzzWithMinimizableCache[/\\]'
 stdout FAIL
 # Make sure this crash didn't come from fuzzing
 # (the log line that states fuzzing began shouldn't have printed)
@@ -70,7 +70,7 @@ go clean -fuzzcache
 # the crash and doesn't write anything to testdata/fuzz -fuzztime=1x
 ! go test -fuzz=FuzzWithAdd -run=None
 ! stdout ^ok
-! stdout 'Crash written to testdata[/\\]fuzz[/\\]FuzzWithAdd[/\\]'
+! stdout 'Failing input written to testdata[/\\]fuzz[/\\]FuzzWithAdd[/\\]'
 stdout FAIL
 
 # Test that fuzzing a target (with -run=None set) with a sucess in f.Add and a
@@ -83,7 +83,7 @@ stdout ok
 # testdata/fuzz prints the crash and doesn't write anything to testdata/fuzz
 ! go test -fuzz=FuzzWithTestdata -run=None -fuzztime=1x
 ! stdout ^ok
-! stdout 'Crash written to testdata[/\\]fuzz[/\\]FuzzWithTestdata[/\\]'
+! stdout 'Failing input written to testdata[/\\]fuzz[/\\]FuzzWithTestdata[/\\]'
 stdout FAIL
 
 # Write a crashing input to the cache
@@ -94,7 +94,7 @@ cp cache-file $GOCACHE/fuzz/example.com/x/FuzzRunNoneWithCache/1
 # prints the crash and writes this as a "new" crash to testdata/fuzz
 ! go test -fuzz=FuzzRunNoneWithCache -run=None -fuzztime=1x
 ! stdout ^ok
-stdout 'Crash written to testdata[/\\]fuzz[/\\]FuzzRunNoneWithCache[/\\]'
+stdout 'Failing input written to testdata[/\\]fuzz[/\\]FuzzRunNoneWithCache[/\\]'
 stdout FAIL
 
 # Clear the fuzz cache and make sure it's gone
@@ -109,14 +109,14 @@ go clean -fuzzcache
 go test -c
 ! exec ./x.test$GOEXE -test.fuzz=FuzzWithAdd -test.run=FuzzWithAdd -test.fuzztime=1x -test.fuzzcachedir=$WORK/cache
 ! stdout ^ok
-! stdout 'Crash written to testdata[/\\]fuzz[/\\]FuzzWithAdd[/\\]'
+! stdout 'Failing input written to testdata[/\\]fuzz[/\\]FuzzWithAdd[/\\]'
 stdout FAIL
 stderr warning
 
 go test -c
 ! exec ./x.test$GOEXE -test.fuzz=FuzzWithTestdata -test.run=FuzzWithTestdata -test.fuzztime=1x -test.fuzzcachedir=$WORK/cache
 ! stdout ^ok
-! stdout 'Crash written to testdata[/\\]fuzz[/\\]FuzzWithTestdata[/\\]'
+! stdout 'Failing input written to testdata[/\\]fuzz[/\\]FuzzWithTestdata[/\\]'
 stdout FAIL
 stderr warning
 
diff --git a/src/go/doc/example.go b/src/go/doc/example.go
index fbbd846354..0a880cdefb 100644
--- a/src/go/doc/example.go
+++ b/src/go/doc/example.go
@@ -44,13 +44,13 @@ type Example struct {
 //     identifiers from other packages (or predeclared identifiers, such as
 //     "int") and the test file does not include a dot import.
 //   - The entire test file is the example: the file contains exactly one
-//     example function, zero test, fuzz target, or benchmark function, and at
+//     example function, zero test, fuzz test, or benchmark function, and at
 //     least one top-level function, type, variable, or constant declaration
 //     other than the example function.
 func Examples(testFiles ...*ast.File) []*Example {
 	var list []*Example
 	for _, file := range testFiles {
-		hasTests := false // file contains tests, fuzz targets, or benchmarks
+		hasTests := false // file contains tests, fuzz test, or benchmarks
 		numDecl := 0      // number of non-import declarations in the file
 		var flist []*Example
 		for _, decl := range file.Decls {
@@ -133,7 +133,7 @@ func exampleOutput(b *ast.BlockStmt, comments []*ast.CommentGroup) (output strin
 	return "", false, false // no suitable comment found
 }
 
-// isTest tells whether name looks like a test, example, fuzz target, or
+// isTest tells whether name looks like a test, example, fuzz test, or
 // benchmark. It is a Test (say) if there is a character after Test that is not
 // a lower-case letter. (We don't want Testiness.)
 func isTest(name, prefix string) bool {
diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go
index 8bd40fe8bf..cb739232c7 100644
--- a/src/internal/fuzz/fuzz.go
+++ b/src/internal/fuzz/fuzz.go
@@ -232,7 +232,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err
 			if result.crasherMsg != "" {
 				if c.warmupRun() && result.entry.IsSeed {
 					target := filepath.Base(c.opts.CorpusDir)
-					fmt.Fprintf(c.opts.Log, "found a crash while testing seed corpus entry: %s/%s\n", target, testName(result.entry.Parent))
+					fmt.Fprintf(c.opts.Log, "failure while testing seed corpus entry: %s/%s\n", target, testName(result.entry.Parent))
 					stop(errors.New(result.crasherMsg))
 					break
 				}
@@ -246,7 +246,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err
 					// Send it back to a worker for minimization. Disable inputC so
 					// other workers don't continue fuzzing.
 					c.crashMinimizing = &result
-					fmt.Fprintf(c.opts.Log, "fuzz: minimizing %d-byte crash file\n", len(result.entry.Data))
+					fmt.Fprintf(c.opts.Log, "fuzz: minimizing %d-byte failing input file\n", len(result.entry.Data))
 					c.queueForMinimization(result, nil)
 				} else if !crashWritten {
 					// Found a crasher that's either minimized or not minimizable.
diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go
index 46c9d63df4..24a0080730 100644
--- a/src/testing/fuzz.go
+++ b/src/testing/fuzz.go
@@ -19,9 +19,9 @@ import (
 )
 
 func initFuzzFlags() {
-	matchFuzz = flag.String("test.fuzz", "", "run the fuzz target matching `regexp`")
+	matchFuzz = flag.String("test.fuzz", "", "run the fuzz test matching `regexp`")
 	flag.Var(&fuzzDuration, "test.fuzztime", "time to spend fuzzing; default is to run indefinitely")
-	flag.Var(&minimizeDuration, "test.fuzzminimizetime", "time to spend minimizing a value after finding a crash")
+	flag.Var(&minimizeDuration, "test.fuzzminimizetime", "time to spend minimizing a value after finding a failing input")
 	fuzzCacheDir = flag.String("test.fuzzcachedir", "", "directory where interesting fuzzing inputs are stored")
 	isFuzzWorker = flag.Bool("test.fuzzworker", false, "coordinate with the parent process to fuzz random values")
 }
@@ -33,34 +33,38 @@ var (
 	fuzzCacheDir     *string
 	isFuzzWorker     *bool
 
-	// corpusDir is the parent directory of the target's seed corpus within
+	// corpusDir is the parent directory of the fuzz test's seed corpus within
 	// the package.
 	corpusDir = "testdata/fuzz"
 )
 
-// fuzzWorkerExitCode is used as an exit code by fuzz worker processes after an internal error.
-// This distinguishes internal errors from uncontrolled panics and other crashes.
-// Keep in sync with internal/fuzz.workerExitCode.
+// fuzzWorkerExitCode is used as an exit code by fuzz worker processes after an
+// internal error. This distinguishes internal errors from uncontrolled panics
+// and other failiures. Keep in sync with internal/fuzz.workerExitCode.
 const fuzzWorkerExitCode = 70
 
-// InternalFuzzTarget is an internal type but exported because it is cross-package;
-// it is part of the implementation of the "go test" command.
+// InternalFuzzTarget is an internal type but exported because it is
+// cross-package; it is part of the implementation of the "go test" command.
 type InternalFuzzTarget struct {
 	Name string
 	Fn   func(f *F)
 }
 
-// F is a type passed to fuzz targets.
+// F is a type passed to fuzz tests.
 //
-// A fuzz target may add seed corpus entries using F.Add or by storing files in
-// the testdata/fuzz/ directory. The fuzz target must then
-// call F.Fuzz once to provide a fuzz function. See the testing package
-// documentation for an example, and see the F.Fuzz and F.Add method
-// documentation for details.
+// Fuzz tests run generated inputs against a provided fuzz target, which can
+// find and report potential bugs in the code being tested.
 //
-// *F methods can only be called before (*F).Fuzz. Once inside the function
-// passed to (*F).Fuzz, only (*T) methods can be used. The only *F methods that
-// are allowed in the (*F).Fuzz function are (*F).Failed and (*F).Name.
+// A fuzz test runs the seed corpus by default, which includes entries provided
+// by (*F).Add and entries in the testdata/fuzz/ directory. After
+// any necessary setup and calls to (*F).Add, the fuzz test must then call
+// (*F).Fuzz to provide the fuzz target. See the testing package documentation
+// for an example, and see the F.Fuzz and F.Add method documentation for
+// details.
+//
+// *F methods can only be called before (*F).Fuzz. Once the the test is
+// executing the fuzz target, only (*T) methods can be used. The only *F methods
+// that are allowed in the (*F).Fuzz function are (*F).Failed and (*F).Name.
 type F struct {
 	common
 	fuzzContext *fuzzContext
@@ -97,7 +101,7 @@ type corpusEntry = struct {
 // Helper may be called simultaneously from multiple goroutines.
 func (f *F) Helper() {
 	if f.inFuzzFn {
-		panic("testing: f.Helper was called inside the f.Fuzz function, use t.Helper instead")
+		panic("testing: f.Helper was called inside the fuzz target, use t.Helper instead")
 	}
 
 	// common.Helper is inlined here.
@@ -125,7 +129,7 @@ func (f *F) Fail() {
 	// (*F).Fail may be called by (*T).Fail, which we should allow. However, we
 	// shouldn't allow direct (*F).Fail calls from inside the (*F).Fuzz function.
 	if f.inFuzzFn {
-		panic("testing: f.Fail was called inside the f.Fuzz function, use t.Fail instead")
+		panic("testing: f.Fail was called inside the fuzz target, use t.Fail instead")
 	}
 	f.common.Helper()
 	f.common.Fail()
@@ -136,15 +140,15 @@ func (f *F) Skipped() bool {
 	// (*F).Skipped may be called by tRunner, which we should allow. However, we
 	// shouldn't allow direct (*F).Skipped calls from inside the (*F).Fuzz function.
 	if f.inFuzzFn {
-		panic("testing: f.Skipped was called inside the f.Fuzz function, use t.Skipped instead")
+		panic("testing: f.Skipped was called inside the fuzz target, use t.Skipped instead")
 	}
 	f.common.Helper()
 	return f.common.Skipped()
 }
 
-// Add will add the arguments to the seed corpus for the fuzz target. This will
-// be a no-op if called after or within the Fuzz function. The args must match
-// those in the Fuzz function.
+// Add will add the arguments to the seed corpus for the fuzz test. This will be
+// a no-op if called after or within the fuzz target, and args must match the
+// arguments for the fuzz target.
 func (f *F) Add(args ...interface{}) {
 	var values []interface{}
 	for i := range args {
@@ -220,7 +224,7 @@ func (f *F) Fuzz(ff interface{}) {
 		panic("testing: F.Fuzz must receive a function")
 	}
 	if fnType.NumIn() < 2 || fnType.In(0) != reflect.TypeOf((*T)(nil)) {
-		panic("testing: F.Fuzz function must receive at least two arguments, where the first argument is a *T")
+		panic("testing: fuzz target must receive at least two arguments, where the first argument is a *T")
 	}
 
 	// Save the types of the function to compare against the corpus.
@@ -354,7 +358,7 @@ func (f *F) Fuzz(ff interface{}) {
 			fmt.Fprintf(f.w, "%v\n", err)
 			if crashErr, ok := err.(fuzzCrashError); ok {
 				crashPath := crashErr.CrashPath()
-				fmt.Fprintf(f.w, "Crash written to %s\n", crashPath)
+				fmt.Fprintf(f.w, "Failing input written to %s\n", crashPath)
 				testName := filepath.Base(crashPath)
 				fmt.Fprintf(f.w, "To re-run:\ngo test -run=%s/%s\n", f.name, testName)
 			}
@@ -378,7 +382,7 @@ func (f *F) Fuzz(ff interface{}) {
 		}); err != nil {
 			// Internal errors are marked with f.Fail; user code may call this too, before F.Fuzz.
 			// The worker will exit with fuzzWorkerExitCode, indicating this is a failure
-			// (and 'go test' should exit non-zero) but a crasher should not be recorded.
+			// (and 'go test' should exit non-zero) but a failing input should not be recorded.
 			f.Errorf("communicating with fuzzing coordinator: %v", err)
 		}
 
@@ -415,7 +419,7 @@ func (f *F) report() {
 type fuzzResult struct {
 	N     int           // The number of iterations.
 	T     time.Duration // The total time taken.
-	Error error         // Error is the error from the crash
+	Error error         // Error is the error from the failing input
 }
 
 func (r fuzzResult) String() string {
@@ -427,7 +431,7 @@ func (r fuzzResult) String() string {
 	return s
 }
 
-// fuzzCrashError is satisfied by a crash detected within the fuzz function.
+// fuzzCrashError is satisfied by a failing input detected while fuzzing.
 // These errors are written to the seed corpus and can be re-run with 'go test'.
 // Errors within the fuzzing framework (like I/O errors between coordinator
 // and worker processes) don't satisfy this interface.
@@ -437,12 +441,12 @@ type fuzzCrashError interface {
 
 	// CrashPath returns the path of the subtest that corresponds to the saved
 	// crash input file in the seed corpus. The test can be re-run with go test
-	// -run=$target/$name $target is the fuzz target name, and $name is the
+	// -run=$test/$name $test is the fuzz test name, and $name is the
 	// filepath.Base of the string returned here.
 	CrashPath() string
 }
 
-// fuzzContext holds fields common to all fuzz targets.
+// fuzzContext holds fields common to all fuzz tests.
 type fuzzContext struct {
 	deps testDeps
 	mode fuzzMode
@@ -456,12 +460,12 @@ const (
 	fuzzWorker
 )
 
-// runFuzzTargets runs the fuzz targets matching the pattern for -run. This will
-// only run the f.Fuzz function for each seed corpus without using the fuzzing
-// engine to generate or mutate inputs.
-func runFuzzTargets(deps testDeps, fuzzTargets []InternalFuzzTarget, deadline time.Time) (ran, ok bool) {
+// runFuzzTests runs the fuzz tests matching the pattern for -run. This will
+// only run the (*F).Fuzz function for each seed corpus without using the
+// fuzzing engine to generate or mutate inputs.
+func runFuzzTests(deps testDeps, fuzzTests []InternalFuzzTarget, deadline time.Time) (ran, ok bool) {
 	ok = true
-	if len(fuzzTargets) == 0 || *isFuzzWorker {
+	if len(fuzzTests) == 0 || *isFuzzWorker {
 		return ran, ok
 	}
 	m := newMatcher(deps.MatchString, *match, "-test.run")
@@ -476,7 +480,7 @@ func runFuzzTargets(deps testDeps, fuzzTargets []InternalFuzzTarget, deadline ti
 	if Verbose() {
 		root.chatty = newChattyPrinter(root.w)
 	}
-	for _, ft := range fuzzTargets {
+	for _, ft := range fuzzTests {
 		if shouldFailFast() {
 			break
 		}
@@ -486,7 +490,7 @@ func runFuzzTargets(deps testDeps, fuzzTargets []InternalFuzzTarget, deadline ti
 		}
 		if mFuzz != nil {
 			if _, fuzzMatched, _ := mFuzz.fullName(nil, ft.Name); fuzzMatched {
-				// If this target will be fuzzed, then don't run the seed corpus
+				// If this will be fuzzed, then don't run the seed corpus
 				// right now. That will happen later.
 				continue
 			}
@@ -515,17 +519,14 @@ func runFuzzTargets(deps testDeps, fuzzTargets []InternalFuzzTarget, deadline ti
 	return root.ran, !root.Failed()
 }
 
-// runFuzzing runs the fuzz target matching the pattern for -fuzz. Only one such
-// fuzz target must match. This will run the fuzzing engine to generate and
-// mutate new inputs against the f.Fuzz function.
+// runFuzzing runs the fuzz test matching the pattern for -fuzz. Only one such
+// fuzz test must match. This will run the fuzzing engine to generate and
+// mutate new inputs against the fuzz target.
 //
 // If fuzzing is disabled (-test.fuzz is not set), runFuzzing
 // returns immediately.
-func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ok bool) {
-	// TODO(katiehockman,jayconrod): Should we do something special to make sure
-	// we don't print f.Log statements again with runFuzzing, since we already
-	// would have printed them when we ran runFuzzTargets (ie. seed corpus run)?
-	if len(fuzzTargets) == 0 || *matchFuzz == "" {
+func runFuzzing(deps testDeps, fuzzTests []InternalFuzzTarget) (ok bool) {
+	if len(fuzzTests) == 0 || *matchFuzz == "" {
 		return true
 	}
 	m := newMatcher(deps.MatchString, *matchFuzz, "-test.fuzz")
@@ -544,24 +545,24 @@ func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ok bool) {
 	if Verbose() && !*isFuzzWorker {
 		root.chatty = newChattyPrinter(root.w)
 	}
-	var target *InternalFuzzTarget
-	var targetName string
+	var fuzzTest *InternalFuzzTarget
+	var testName string
 	var matched []string
-	for i := range fuzzTargets {
-		name, ok, _ := tctx.match.fullName(nil, fuzzTargets[i].Name)
+	for i := range fuzzTests {
+		name, ok, _ := tctx.match.fullName(nil, fuzzTests[i].Name)
 		if !ok {
 			continue
 		}
 		matched = append(matched, name)
-		target = &fuzzTargets[i]
-		targetName = name
+		fuzzTest = &fuzzTests[i]
+		testName = name
 	}
 	if len(matched) == 0 {
-		fmt.Fprintln(os.Stderr, "testing: warning: no targets to fuzz")
+		fmt.Fprintln(os.Stderr, "testing: warning: no fuzz tests to fuzz")
 		return true
 	}
 	if len(matched) > 1 {
-		fmt.Fprintf(os.Stderr, "testing: will not fuzz, -fuzz matches more than one target: %v\n", matched)
+		fmt.Fprintf(os.Stderr, "testing: will not fuzz, -fuzz matches more than one fuzz test: %v\n", matched)
 		return false
 	}
 
@@ -569,7 +570,7 @@ func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ok bool) {
 		common: common{
 			signal:  make(chan bool),
 			barrier: nil, // T.Parallel has no effect when fuzzing.
-			name:    targetName,
+			name:    testName,
 			parent:  &root,
 			level:   root.level + 1,
 			chatty:  root.chatty,
@@ -582,31 +583,32 @@ func runFuzzing(deps testDeps, fuzzTargets []InternalFuzzTarget) (ok bool) {
 		// TODO(#48132): adjust this to work with test2json.
 		f.chatty.Updatef(f.name, "=== FUZZ  %s\n", f.name)
 	}
-	go fRunner(f, target.Fn)
+	go fRunner(f, fuzzTest.Fn)
 	<-f.signal
 	return !f.failed
 }
 
-// fRunner wraps a call to a fuzz target and ensures that cleanup functions are
+// fRunner wraps a call to a fuzz test and ensures that cleanup functions are
 // called and status flags are set. fRunner should be called in its own
 // goroutine. To wait for its completion, receive from f.signal.
 //
 // fRunner is analogous to tRunner, which wraps subtests started with T.Run.
-// Tests and fuzz targets work a little differently, so for now, these functions
-// aren't consolidated. In particular, because there are no F.Run and F.Parallel
-// methods, i.e., no fuzz sub-targets or parallel fuzz targets, a few
+// Unit tests and fuzz tests work a little differently, so for now, these
+// functions aren't consolidated. In particular, because there are no F.Run and
+// F.Parallel methods, i.e., no fuzz sub-tests or parallel fuzz tests, a few
 // simplifications are made. We also require that F.Fuzz, F.Skip, or F.Fail is
 // called.
 func fRunner(f *F, fn func(*F)) {
-	// When this goroutine is done, either because runtime.Goexit was called,
-	// a panic started, or fn returned normally, record the duration and send
-	// t.signal, indicating the fuzz target is done.
+	// When this goroutine is done, either because runtime.Goexit was called, a
+	// panic started, or fn returned normally, record the duration and send
+	// t.signal, indicating the fuzz test is done.
 	defer func() {
-		// Detect whether the fuzz target panicked or called runtime.Goexit without
-		// calling F.Fuzz, F.Fail, or F.Skip. If it did, panic (possibly replacing a
-		// nil panic value). Nothing should recover after fRunner unwinds, so this
-		// should crash the process and print stack. Unfortunately, recovering here
-		// adds stack frames, but the location of the original panic should still be
+		// Detect whether the fuzz test panicked or called runtime.Goexit
+		// without calling F.Fuzz, F.Fail, or F.Skip. If it did, panic (possibly
+		// replacing a nil panic value). Nothing should recover after fRunner
+		// unwinds, so this should crash the process and print stack.
+		// Unfortunately, recovering here adds stack frames, but the location of
+		// the original panic should still be
 		// clear.
 		if f.Failed() {
 			atomic.AddUint32(&numFailed, 1)
@@ -662,7 +664,7 @@ func fRunner(f *F, fn func(*F)) {
 
 		if len(f.sub) > 0 {
 			// Unblock inputs that called T.Parallel while running the seed corpus.
-			// This only affects fuzz targets run as normal tests.
+			// This only affects fuzz tests run as normal tests.
 			// While fuzzing, T.Parallel has no effect, so f.sub is empty, and this
 			// branch is not taken. f.barrier is nil in that case.
 			close(f.barrier)
diff --git a/src/testing/testing.go b/src/testing/testing.go
index 2ad2266e2d..3458b46d97 100644
--- a/src/testing/testing.go
+++ b/src/testing/testing.go
@@ -146,11 +146,9 @@
 // a function is called with randomly generated inputs to find bugs not
 // anticipated by unit tests.
 //
-// A fuzz target is a function that declares a set of "seed" inputs by calling
-// F.Add, then provides a fuzz function by calling F.Fuzz. A fuzz target has
-// the form:
-//
+// Functions of the form
 //     func FuzzXxx(*testing.F)
+// are considered fuzz tests.
 //
 // For example:
 //
@@ -170,35 +168,38 @@
 //       })
 //     }
 //
-// Seed inputs may be registered by calling F.Add or by storing files in the
-// directory testdata/fuzz/ (where  is the name of the fuzz target)
-// within the package containing the fuzz target. Seed inputs are optional, but
-// the fuzzing engine may find bugs more efficiently when provided with a set
-// of small seed inputs with good code coverage.
-//
-// The fuzz function provided to F.Fuzz must accept a *testing.T parameter,
-// followed by one or more parameters for random inputs. The types of arguments
-// passed to F.Add must be identical to the types of these parameters. The fuzz
-// function may signal that it's found a problem the same way tests do: by
-// calling T.Fail (or any method that calls it like T.Error or T.Fatal) or by
-// panicking.
+// A fuzz test maintains a seed corpus, or a set of inputs which are run by
+// default, and can seed input generation. Seed inputs may be registered by
+// calling (*F).Add or by storing files in the directory testdata/fuzz/
+// (where  is the name of the fuzz test) within the package containing
+// the fuzz test. Seed inputs are optional, but the fuzzing engine may find
+// bugs more efficiently when provided with a set of small seed inputs with good
+// code coverage. These seed inputs can also serve as regression tests for bugs
+// identified through fuzzing.
+//
+// The function passed to (*F).Fuzz within the fuzz test is considered the fuzz
+// target. A fuzz target must accept a *T parameter, followed by one or more
+// parameters for random inputs. The types of arguments passed to (*F).Add must
+// be identical to the types of these parameters. The fuzz target may signal
+// that it's found a problem the same way tests do: by calling T.Fail (or any
+// method that calls it like T.Error or T.Fatal) or by panicking.
 //
 // When fuzzing is enabled (by setting the -fuzz flag to a regular expression
-// that matches a specific fuzz target), the fuzz function is called with
-// arguments generated by repeatedly making random changes to the seed inputs.
-// On supported platforms, 'go test' compiles the test executable with fuzzing
+// that matches a specific fuzz test), the fuzz target is called with arguments
+// generated by repeatedly making random changes to the seed inputs. On
+// supported platforms, 'go test' compiles the test executable with fuzzing
 // coverage instrumentation. The fuzzing engine uses that instrumentation to
-// find and cache inputs that expand coverage, increasing the liklihood of
-// finding bugs. If the fuzz function finds a problem, the fuzzing engine writes
-// the inputs that caused the problem to a file in the directory
+// find and cache inputs that expand coverage, increasing the likelihood of
+// finding bugs. If the fuzz target fails for a given input, the fuzzing engine
+// writes the inputs that caused the failure to a file in the directory
 // testdata/fuzz/ within the package directory. This file later serves as
 // a seed input. If the file can't be written at that location (for example,
 // because the directory is read-only), the fuzzing engine writes the file to
 // the fuzz cache directory within the build cache instead.
 //
-// When fuzzing is disabled, the fuzz function is called with the seed inputs
+// When fuzzing is disabled, the fuzz target is called with the seed inputs
 // registered with F.Add and seed inputs from testdata/fuzz/. In this
-// mode, the fuzz target acts much like a regular test, with subtests started
+// mode, the fuzz test acts much like a regular test, with subtests started
 // with F.Fuzz instead of T.Run.
 //
 // TODO(#48255): write and link to documentation that will be helpful to users
@@ -217,7 +218,7 @@
 //     }
 //
 // The Skip method of *T can be used in a fuzz target if the input is invalid,
-// but should not be considered a crash. For example:
+// but should not be considered a failing input. For example:
 //
 //     func FuzzJSONMarshalling(f *testing.F) {
 //         f.Fuzz(func(t *testing.T, b []byte) {
@@ -500,7 +501,7 @@ type common struct {
 	cleanupName string               // Name of the cleanup function.
 	cleanupPc   []uintptr            // The stack trace at the point where Cleanup was called.
 	finished    bool                 // Test function has completed.
-	inFuzzFn    bool                 // Whether the fuzz function, if this is one, is running.
+	inFuzzFn    bool                 // Whether the fuzz target, if this is one, is running.
 
 	chatty     *chattyPrinter // A copy of chattyPrinter, if the chatty flag is set.
 	bench      bool           // Whether the current test is a benchmark.
@@ -558,7 +559,7 @@ func Verbose() bool {
 
 func (c *common) checkFuzzFn(name string) {
 	if c.inFuzzFn {
-		panic(fmt.Sprintf("testing: f.%s was called inside the f.Fuzz function, use t.%s instead", name, name))
+		panic(fmt.Sprintf("testing: f.%s was called inside the fuzz target, use t.%s instead", name, name))
 	}
 }
 
@@ -1687,7 +1688,7 @@ func (m *M) Run() (code int) {
 		deadline := m.startAlarm()
 		haveExamples = len(m.examples) > 0
 		testRan, testOk := runTests(m.deps.MatchString, m.tests, deadline)
-		fuzzTargetsRan, fuzzTargetsOk := runFuzzTargets(m.deps, m.fuzzTargets, deadline)
+		fuzzTargetsRan, fuzzTargetsOk := runFuzzTests(m.deps, m.fuzzTargets, deadline)
 		exampleRan, exampleOk := runExamples(m.deps.MatchString, m.examples)
 		m.stopAlarm()
 		if !testRan && !exampleRan && !fuzzTargetsRan && *matchBenchmarks == "" && *matchFuzz == "" {
-- 
GitLab


From c3c4a2bf6589f8c1e046149356fb5456b34a0df1 Mon Sep 17 00:00:00 2001
From: Pedro Lopez Mareque 
Date: Fri, 8 Oct 2021 07:01:35 +0200
Subject: [PATCH 2134/2500] math/bits: add examples for Add, Sub, Mul and Div

Change-Id: I2f3619aa827e18f356871511c20cf2c712f496b3
Reviewed-on: https://go-review.googlesource.com/c/go/+/353189
Run-TryBot: Ian Lance Taylor 
TryBot-Result: Go Bot 
Reviewed-by: Ian Lance Taylor 
Trust: Keith Randall 
---
 src/math/bits/example_math_test.go | 202 +++++++++++++++++++++++++++++
 1 file changed, 202 insertions(+)
 create mode 100644 src/math/bits/example_math_test.go

diff --git a/src/math/bits/example_math_test.go b/src/math/bits/example_math_test.go
new file mode 100644
index 0000000000..4bb466f85c
--- /dev/null
+++ b/src/math/bits/example_math_test.go
@@ -0,0 +1,202 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bits_test
+
+import (
+	"fmt"
+	"math/bits"
+)
+
+func ExampleAdd32() {
+	// First number is 33<<32 + 12
+	n1 := []uint32{33, 12}
+	// Second number is 21<<32 + 23
+	n2 := []uint32{21, 23}
+	// Add them together without producing carry.
+	d1, carry := bits.Add32(n1[1], n2[1], 0)
+	d0, _ := bits.Add32(n1[0], n2[0], carry)
+	nsum := []uint32{d0, d1}
+	fmt.Printf("%v + %v = %v (carry bit was %v)\n", n1, n2, nsum, carry)
+
+	// First number is 1<<32 + 2147483648
+	n1 = []uint32{1, 0x80000000}
+	// Second number is 1<<32 + 2147483648
+	n2 = []uint32{1, 0x80000000}
+	// Add them together producing carry.
+	d1, carry = bits.Add32(n1[1], n2[1], 0)
+	d0, _ = bits.Add32(n1[0], n2[0], carry)
+	nsum = []uint32{d0, d1}
+	fmt.Printf("%v + %v = %v (carry bit was %v)\n", n1, n2, nsum, carry)
+	// Output:
+	// [33 12] + [21 23] = [54 35] (carry bit was 0)
+	// [1 2147483648] + [1 2147483648] = [3 0] (carry bit was 1)
+}
+
+func ExampleAdd64() {
+	// First number is 33<<64 + 12
+	n1 := []uint64{33, 12}
+	// Second number is 21<<64 + 23
+	n2 := []uint64{21, 23}
+	// Add them together without producing carry.
+	d1, carry := bits.Add64(n1[1], n2[1], 0)
+	d0, _ := bits.Add64(n1[0], n2[0], carry)
+	nsum := []uint64{d0, d1}
+	fmt.Printf("%v + %v = %v (carry bit was %v)\n", n1, n2, nsum, carry)
+
+	// First number is 1<<64 + 9223372036854775808
+	n1 = []uint64{1, 0x8000000000000000}
+	// Second number is 1<<64 + 9223372036854775808
+	n2 = []uint64{1, 0x8000000000000000}
+	// Add them together producing carry.
+	d1, carry = bits.Add64(n1[1], n2[1], 0)
+	d0, _ = bits.Add64(n1[0], n2[0], carry)
+	nsum = []uint64{d0, d1}
+	fmt.Printf("%v + %v = %v (carry bit was %v)\n", n1, n2, nsum, carry)
+	// Output:
+	// [33 12] + [21 23] = [54 35] (carry bit was 0)
+	// [1 9223372036854775808] + [1 9223372036854775808] = [3 0] (carry bit was 1)
+}
+
+func ExampleSub32() {
+	// First number is 33<<32 + 23
+	n1 := []uint32{33, 23}
+	// Second number is 21<<32 + 12
+	n2 := []uint32{21, 12}
+	// Sub them together without producing carry.
+	d1, carry := bits.Sub32(n1[1], n2[1], 0)
+	d0, _ := bits.Sub32(n1[0], n2[0], carry)
+	nsum := []uint32{d0, d1}
+	fmt.Printf("%v - %v = %v (carry bit was %v)\n", n1, n2, nsum, carry)
+
+	// First number is 3<<32 + 2147483647
+	n1 = []uint32{3, 0x7fffffff}
+	// Second number is 1<<32 + 2147483648
+	n2 = []uint32{1, 0x80000000}
+	// Sub them together producing carry.
+	d1, carry = bits.Sub32(n1[1], n2[1], 0)
+	d0, _ = bits.Sub32(n1[0], n2[0], carry)
+	nsum = []uint32{d0, d1}
+	fmt.Printf("%v - %v = %v (carry bit was %v)\n", n1, n2, nsum, carry)
+	// Output:
+	// [33 23] - [21 12] = [12 11] (carry bit was 0)
+	// [3 2147483647] - [1 2147483648] = [1 4294967295] (carry bit was 1)
+}
+
+func ExampleSub64() {
+	// First number is 33<<64 + 23
+	n1 := []uint64{33, 23}
+	// Second number is 21<<64 + 12
+	n2 := []uint64{21, 12}
+	// Sub them together without producing carry.
+	d1, carry := bits.Sub64(n1[1], n2[1], 0)
+	d0, _ := bits.Sub64(n1[0], n2[0], carry)
+	nsum := []uint64{d0, d1}
+	fmt.Printf("%v - %v = %v (carry bit was %v)\n", n1, n2, nsum, carry)
+
+	// First number is 3<<64 + 9223372036854775807
+	n1 = []uint64{3, 0x7fffffffffffffff}
+	// Second number is 1<<64 + 9223372036854775808
+	n2 = []uint64{1, 0x8000000000000000}
+	// Sub them together producing carry.
+	d1, carry = bits.Sub64(n1[1], n2[1], 0)
+	d0, _ = bits.Sub64(n1[0], n2[0], carry)
+	nsum = []uint64{d0, d1}
+	fmt.Printf("%v - %v = %v (carry bit was %v)\n", n1, n2, nsum, carry)
+	// Output:
+	// [33 23] - [21 12] = [12 11] (carry bit was 0)
+	// [3 9223372036854775807] - [1 9223372036854775808] = [1 18446744073709551615] (carry bit was 1)
+}
+
+func ExampleMul32() {
+	// First number is 0<<32 + 12
+	n1 := []uint32{0, 12}
+	// Second number is 0<<32 + 12
+	n2 := []uint32{0, 12}
+	// Multiply them together without producing overflow.
+	hi, lo := bits.Mul32(n1[1], n2[1])
+	nsum := []uint32{hi, lo}
+	fmt.Printf("%v * %v = %v\n", n1[1], n2[1], nsum)
+
+	// First number is 0<<32 + 2147483648
+	n1 = []uint32{0, 0x80000000}
+	// Second number is 0<<32 + 2
+	n2 = []uint32{0, 2}
+	// Multiply them together producing overflow.
+	hi, lo = bits.Mul32(n1[1], n2[1])
+	nsum = []uint32{hi, lo}
+	fmt.Printf("%v * %v = %v\n", n1[1], n2[1], nsum)
+	// Output:
+	// 12 * 12 = [0 144]
+	// 2147483648 * 2 = [1 0]
+}
+
+func ExampleMul64() {
+	// First number is 0<<64 + 12
+	n1 := []uint64{0, 12}
+	// Second number is 0<<64 + 12
+	n2 := []uint64{0, 12}
+	// Multiply them together without producing overflow.
+	hi, lo := bits.Mul64(n1[1], n2[1])
+	nsum := []uint64{hi, lo}
+	fmt.Printf("%v * %v = %v\n", n1[1], n2[1], nsum)
+
+	// First number is 0<<64 + 9223372036854775808
+	n1 = []uint64{0, 0x8000000000000000}
+	// Second number is 0<<64 + 2
+	n2 = []uint64{0, 2}
+	// Multiply them together producing overflow.
+	hi, lo = bits.Mul64(n1[1], n2[1])
+	nsum = []uint64{hi, lo}
+	fmt.Printf("%v * %v = %v\n", n1[1], n2[1], nsum)
+	// Output:
+	// 12 * 12 = [0 144]
+	// 9223372036854775808 * 2 = [1 0]
+}
+
+func ExampleDiv32() {
+	// First number is 0<<32 + 6
+	n1 := []uint32{0, 6}
+	// Second number is 0<<32 + 3
+	n2 := []uint32{0, 3}
+	// Divide them together.
+	quo, rem := bits.Div32(n1[0], n1[1], n2[1])
+	nsum := []uint32{quo, rem}
+	fmt.Printf("[%v %v] / %v = %v\n", n1[0], n1[1], n2[1], nsum)
+
+	// First number is 2<<32 + 2147483648
+	n1 = []uint32{2, 0x80000000}
+	// Second number is 0<<32 + 2147483648
+	n2 = []uint32{0, 0x80000000}
+	// Divide them together.
+	quo, rem = bits.Div32(n1[0], n1[1], n2[1])
+	nsum = []uint32{quo, rem}
+	fmt.Printf("[%v %v] / %v = %v\n", n1[0], n1[1], n2[1], nsum)
+	// Output:
+	// [0 6] / 3 = [2 0]
+	// [2 2147483648] / 2147483648 = [5 0]
+}
+
+func ExampleDiv64() {
+	// First number is 0<<64 + 6
+	n1 := []uint64{0, 6}
+	// Second number is 0<<64 + 3
+	n2 := []uint64{0, 3}
+	// Divide them together.
+	quo, rem := bits.Div64(n1[0], n1[1], n2[1])
+	nsum := []uint64{quo, rem}
+	fmt.Printf("[%v %v] / %v = %v\n", n1[0], n1[1], n2[1], nsum)
+
+	// First number is 2<<64 + 9223372036854775808
+	n1 = []uint64{2, 0x8000000000000000}
+	// Second number is 0<<64 + 9223372036854775808
+	n2 = []uint64{0, 0x8000000000000000}
+	// Divide them together.
+	quo, rem = bits.Div64(n1[0], n1[1], n2[1])
+	nsum = []uint64{quo, rem}
+	fmt.Printf("[%v %v] / %v = %v\n", n1[0], n1[1], n2[1], nsum)
+	// Output:
+	// [0 6] / 3 = [2 0]
+	// [2 9223372036854775808] / 9223372036854775808 = [5 0]
+}
-- 
GitLab


From 7bed3c7975780cad3c0adcf548d8b2d324a09265 Mon Sep 17 00:00:00 2001
From: Mikhail Faraponov 
Date: Thu, 11 Nov 2021 21:45:45 +0000
Subject: [PATCH 2135/2500] net: use Done rather than comparing with
 context.Background

Fixes #49023

Change-Id: I3de70f8a25f4ba8a0fb8bb96581371e33fde2f7a
GitHub-Last-Rev: b7ec9405adc77ec513df344f2ad33801feb2d3ca
GitHub-Pull-Request: golang/go#49024
Reviewed-on: https://go-review.googlesource.com/c/go/+/356471
Reviewed-by: Ian Lance Taylor 
Trust: Damien Neil 
---
 src/net/fd_unix.go | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/net/fd_unix.go b/src/net/fd_unix.go
index 1bb029d370..4ded833bbf 100644
--- a/src/net/fd_unix.go
+++ b/src/net/fd_unix.go
@@ -91,12 +91,11 @@ func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (rsa sysc
 	}
 
 	// Start the "interrupter" goroutine, if this context might be canceled.
-	// (The background context cannot)
 	//
 	// The interrupter goroutine waits for the context to be done and
 	// interrupts the dial (by altering the fd's write deadline, which
 	// wakes up waitWrite).
-	if ctx != context.Background() {
+	if ctxDone := ctx.Done(); ctxDone != nil {
 		// Wait for the interrupter goroutine to exit before returning
 		// from connect.
 		done := make(chan struct{})
@@ -116,7 +115,7 @@ func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (rsa sysc
 		}()
 		go func() {
 			select {
-			case <-ctx.Done():
+			case <-ctxDone:
 				// Force the runtime's poller to immediately give up
 				// waiting for writability, unblocking waitWrite
 				// below.
-- 
GitLab


From e9f0381a807d1797e0b5969a29f4a3666a73c9e3 Mon Sep 17 00:00:00 2001
From: Cherry Mui 
Date: Thu, 11 Nov 2021 16:51:08 -0500
Subject: [PATCH 2136/2500] cmd/link: don't unmap output file at error exit

When the link exits on error it currently calls Out.Close, which
will munmap the output buffer and close the file. This may be
called in concurrent phase where other goroutines may be writing
to the output buffer. The munmap can race with the write, causing
it to write to unmapped memory and crash. This CL changes it to
just close the file without unmapping. We're exiting on error
anyway so no need to unmap.

Fixes #47816.

Change-Id: I0e89aca991bdada3d017b7d5c8efc29e46308c03
Reviewed-on: https://go-review.googlesource.com/c/go/+/363357
Trust: Cherry Mui 
Run-TryBot: Cherry Mui 
TryBot-Result: Go Bot 
Reviewed-by: Than McIntosh 
---
 src/cmd/link/internal/ld/lib.go    |  1 -
 src/cmd/link/internal/ld/outbuf.go | 14 ++++++++++++++
 src/cmd/link/internal/ld/sym.go    |  2 +-
 3 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index 91665b2ebb..9e13db7b71 100644
--- a/src/cmd/link/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -1103,7 +1103,6 @@ func hostlinksetup(ctxt *Link) {
 		*flagTmpdir = dir
 		ownTmpDir = true
 		AtExit(func() {
-			ctxt.Out.Close()
 			os.RemoveAll(*flagTmpdir)
 		})
 	}
diff --git a/src/cmd/link/internal/ld/outbuf.go b/src/cmd/link/internal/ld/outbuf.go
index 9d5e8854fe..1d21dce9c5 100644
--- a/src/cmd/link/internal/ld/outbuf.go
+++ b/src/cmd/link/internal/ld/outbuf.go
@@ -131,6 +131,20 @@ func (out *OutBuf) Close() error {
 	return nil
 }
 
+// ErrorClose closes the output file (if any).
+// It is supposed to be called only at exit on error, so it doesn't do
+// any clean up or buffer flushing, just closes the file.
+func (out *OutBuf) ErrorClose() {
+	if out.isView {
+		panic(viewCloseError)
+	}
+	if out.f == nil {
+		return
+	}
+	out.f.Close() // best effort, ignore error
+	out.f = nil
+}
+
 // isMmapped returns true if the OutBuf is mmaped.
 func (out *OutBuf) isMmapped() bool {
 	return len(out.buf) != 0
diff --git a/src/cmd/link/internal/ld/sym.go b/src/cmd/link/internal/ld/sym.go
index 72639962e2..d51a59ef46 100644
--- a/src/cmd/link/internal/ld/sym.go
+++ b/src/cmd/link/internal/ld/sym.go
@@ -60,7 +60,7 @@ func linknew(arch *sys.Arch) *Link {
 
 	AtExit(func() {
 		if nerrors > 0 {
-			ctxt.Out.Close()
+			ctxt.Out.ErrorClose()
 			mayberemoveoutfile()
 		}
 	})
-- 
GitLab


From 23adc139bf1c0c099dd075da076f5a1f3ac700d4 Mon Sep 17 00:00:00 2001
From: Cherry Mui 
Date: Thu, 11 Nov 2021 19:58:23 -0500
Subject: [PATCH 2137/2500] reflect: keep pointer in aggregate-typed args live
 in Call

When register ABI is used, reflect.Value.Call prepares the call
arguments in a memory representation of the argument registers.
It has special handling to keep the pointers in arguments live.
Currently, this handles pointer-typed arguments. But when an
argument is an aggregate-type that contains pointers and passed
in registers, it currently doesn't keep the pointers live. Do
so in this CL.

May fix #49363.

Change-Id: Ic6a0c5fdf9375ef02f7c03fbe9345e2e98c9353d
Reviewed-on: https://go-review.googlesource.com/c/go/+/363358
Trust: Cherry Mui 
Run-TryBot: Cherry Mui 
TryBot-Result: Go Bot 
Reviewed-by: Michael Knyszek 
---
 src/internal/abi/abi.go | 18 ++++++++++++++++++
 src/reflect/all_test.go | 23 +++++++++++++++++++++++
 src/reflect/value.go    | 19 ++++++++++++++++---
 3 files changed, 57 insertions(+), 3 deletions(-)

diff --git a/src/internal/abi/abi.go b/src/internal/abi/abi.go
index 46dc593bd7..b266a7ff78 100644
--- a/src/internal/abi/abi.go
+++ b/src/internal/abi/abi.go
@@ -44,6 +44,24 @@ type RegArgs struct {
 	ReturnIsPtr IntArgRegBitmap
 }
 
+func (r *RegArgs) Dump() {
+	print("Ints:")
+	for _, x := range r.Ints {
+		print(" ", x)
+	}
+	println()
+	print("Floats:")
+	for _, x := range r.Floats {
+		print(" ", x)
+	}
+	println()
+	print("Ptrs:")
+	for _, x := range r.Ptrs {
+		print(" ", x)
+	}
+	println()
+}
+
 // IntRegArgAddr returns a pointer inside of r.Ints[reg] that is appropriately
 // offset for an argument of size argSize.
 //
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go
index acc09962a0..8c51d8ec26 100644
--- a/src/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -6478,6 +6478,29 @@ func TestCallMethodJump(t *testing.T) {
 	*CallGC = false
 }
 
+func TestCallArgLive(t *testing.T) {
+	type T struct{ X, Y *string } // pointerful aggregate
+
+	F := func(t T) { *t.X = "ok" }
+
+	// In reflect.Value.Call, trigger a garbage collection in reflect.call
+	// between marshaling argument and the actual call.
+	*CallGC = true
+
+	x := new(string)
+	runtime.SetFinalizer(x, func(p *string) {
+		if *p != "ok" {
+			t.Errorf("x dead prematurely")
+		}
+	})
+	v := T{x, nil}
+
+	ValueOf(F).Call([]Value{ValueOf(v)})
+
+	// Stop garbage collecting during reflect.call.
+	*CallGC = false
+}
+
 func TestMakeFuncStackCopy(t *testing.T) {
 	target := func(in []Value) []Value {
 		runtime.GC()
diff --git a/src/reflect/value.go b/src/reflect/value.go
index ecf9dd7bc8..02354f2736 100644
--- a/src/reflect/value.go
+++ b/src/reflect/value.go
@@ -352,7 +352,7 @@ func (v Value) CallSlice(in []Value) []Value {
 	return v.call("CallSlice", in)
 }
 
-var callGC bool // for testing; see TestCallMethodJump
+var callGC bool // for testing; see TestCallMethodJump and TestCallArgLive
 
 const debugReflectCall = false
 
@@ -509,12 +509,16 @@ func (v Value) call(op string, in []Value) []Value {
 				// Copy values to "integer registers."
 				if v.flag&flagIndir != 0 {
 					offset := add(v.ptr, st.offset, "precomputed value offset")
-					intToReg(®Args, st.ireg, st.size, offset)
-				} else {
 					if st.kind == abiStepPointer {
 						// Duplicate this pointer in the pointer area of the
 						// register space. Otherwise, there's the potential for
 						// this to be the last reference to v.ptr.
+						regArgs.Ptrs[st.ireg] = *(*unsafe.Pointer)(offset)
+					}
+					intToReg(®Args, st.ireg, st.size, offset)
+				} else {
+					if st.kind == abiStepPointer {
+						// See the comment in abiStepPointer case above.
 						regArgs.Ptrs[st.ireg] = v.ptr
 					}
 					regArgs.Ints[st.ireg] = uintptr(v.ptr)
@@ -539,6 +543,15 @@ func (v Value) call(op string, in []Value) []Value {
 	// Mark pointers in registers for the return path.
 	regArgs.ReturnIsPtr = abi.outRegPtrs
 
+	if debugReflectCall {
+		regArgs.Dump()
+	}
+
+	// For testing; see TestCallArgLive.
+	if callGC {
+		runtime.GC()
+	}
+
 	// Call.
 	call(frametype, fn, stackArgs, uint32(frametype.size), uint32(abi.retOffset), uint32(frameSize), ®Args)
 
-- 
GitLab


From 95d06576702c54139796f3e24e2eec4b135b1a09 Mon Sep 17 00:00:00 2001
From: Michael Anthony Knyszek 
Date: Fri, 12 Nov 2021 05:04:32 +0000
Subject: [PATCH 2138/2500] test/recover4.go: use mprotect to create a hole
 instead of munmap

Currently the recover4 test, which recovers from a panic created from a
fault, generates a fault by creating a hole in a mapping. It does this
via munmap. However, it's possible the runtime can create a new mapping
that ends up in that hole, for example if the GC executes, causing the
test to fail.

In fact, this is the case now with a smaller minimum heap size.

Modify the test to use mprotect, and clean up the code a little while
we're here: define everything in terms of the length of original
mapping, deduplicate some constants and expressions, and have the test
recover properly even if recover() returns nil (right now it panics
because it fails to type assert nil as error).

Fixes #49381.

Change-Id: If399eca564466e5e8aeb2dc6f86a246d0fce7b5d
Reviewed-on: https://go-review.googlesource.com/c/go/+/363534
Trust: Michael Knyszek 
Run-TryBot: Michael Knyszek 
TryBot-Result: Go Bot 
Reviewed-by: Cherry Mui 
---
 test/recover4.go | 28 +++++++++++++++-------------
 1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/test/recover4.go b/test/recover4.go
index 67ed970ecb..7cab15a5a8 100644
--- a/test/recover4.go
+++ b/test/recover4.go
@@ -24,12 +24,13 @@ import (
 	"log"
 	"runtime/debug"
 	"syscall"
-	"unsafe"
 )
 
 func memcopy(dst, src []byte) (n int, err error) {
 	defer func() {
-		err = recover().(error)
+		if r, ok := recover().(error); ok {
+			err = r
+		}
 	}()
 
 	for i := 0; i < len(dst) && i < len(src); i++ {
@@ -52,22 +53,23 @@ func main() {
 		log.Fatalf("mmap: %v", err)
 	}
 
-	other := make([]byte, 16*size)
-
-	// Note: Cannot call syscall.Munmap, because Munmap checks
-	// that you are unmapping a whole region returned by Mmap.
-	// We are trying to unmap just a hole in the middle.
-	if _, _, err := syscall.Syscall(syscall.SYS_MUNMAP, uintptr(unsafe.Pointer(&data[8*size])), uintptr(4*size), 0); err != 0 {
-		log.Fatalf("munmap: %v", err)
+	// Create a hole in the mapping that's PROT_NONE.
+	// Note that we can't use munmap here because the Go runtime
+	// could create a mapping that ends up in this hole otherwise,
+	// invalidating the test.
+	hole := data[len(data)/2 : 3*(len(data)/4)]
+	if err := syscall.Mprotect(hole, syscall.PROT_NONE); err != nil {
+		log.Fatalf("mprotect: %v", err)
 	}
 
 	// Check that memcopy returns the actual amount copied
-	// before the fault (8*size - 5, the offset we skip in the argument).
-	n, err := memcopy(data[5:], other)
+	// before the fault.
+	const offset = 5
+	n, err := memcopy(data[offset:], make([]byte, len(data)))
 	if err == nil {
 		log.Fatal("no error from memcopy across memory hole")
 	}
-	if n != 8*size-5 {
-		log.Fatalf("memcopy returned %d, want %d", n, 8*size-5)
+	if expect := len(data)/2 - offset; n != expect {
+		log.Fatalf("memcopy returned %d, want %d", n, expect)
 	}
 }
-- 
GitLab


From 0c6a6cd4d8c19ca8892085a38477e5ff56b7cc2b Mon Sep 17 00:00:00 2001
From: Robert Findley 
Date: Tue, 9 Nov 2021 21:39:53 -0500
Subject: [PATCH 2139/2500] go/types: use Identical to verify type identity in
 the Context map

We don't have guarantees that our type hash is perfect, and in fact
fuzzing found cases where identical types hashed to different values. In
case non-identical types hash to the same value, we should ensure that
we de-duplicate using Identical.

Adjust the type map to keep a slice of distinct type identities, so that
we can guarantee that type identity is preserved by de-duplication.

To allow look-up of instances by their identity, before they are
actually instantiated, add a Context.lookup method that accepts origin
type and type arguments. Replace the multi-function typeForHash method
with an update method that requires its argument be non-nil.

Change-Id: I8fe6fb2955f508db608161b7285b02d0a2fa0e46
Reviewed-on: https://go-review.googlesource.com/c/go/+/362798
Trust: Robert Findley 
Run-TryBot: Robert Findley 
TryBot-Result: Go Bot 
Reviewed-by: Robert Griesemer 
---
 src/go/types/context.go     | 52 +++++++++++++++++++++++++++++--------
 src/go/types/instantiate.go |  4 +--
 src/go/types/named.go       |  2 +-
 src/go/types/predicates.go  | 17 ++++++++++++
 src/go/types/subst.go       |  2 +-
 src/go/types/typexpr.go     | 16 ++++++------
 6 files changed, 70 insertions(+), 23 deletions(-)

diff --git a/src/go/types/context.go b/src/go/types/context.go
index 7caf631b57..e89babcd70 100644
--- a/src/go/types/context.go
+++ b/src/go/types/context.go
@@ -6,6 +6,7 @@ package types
 
 import (
 	"bytes"
+	"fmt"
 	"strings"
 	"sync"
 )
@@ -17,15 +18,15 @@ import (
 // It is safe for concurrent use.
 type Context struct {
 	mu      sync.Mutex
-	typeMap map[string]*Named // type hash -> instance
-	nextID  int               // next unique ID
-	seen    map[*Named]int    // assigned unique IDs
+	typeMap map[string][]*Named // type hash -> instances
+	nextID  int                 // next unique ID
+	seen    map[*Named]int      // assigned unique IDs
 }
 
 // NewContext creates a new Context.
 func NewContext() *Context {
 	return &Context{
-		typeMap: make(map[string]*Named),
+		typeMap: make(map[string][]*Named),
 		seen:    make(map[*Named]int),
 	}
 }
@@ -57,17 +58,46 @@ func (ctxt *Context) typeHash(typ Type, targs []Type) string {
 	return strings.Replace(buf.String(), " ", "#", -1) // ReplaceAll is not available in Go1.4
 }
 
-// typeForHash returns the recorded type for the type hash h, if it exists.
-// If no type exists for h and n is non-nil, n is recorded for h.
-func (ctxt *Context) typeForHash(h string, n *Named) *Named {
+// lookup returns an existing instantiation of orig with targs, if it exists.
+// Otherwise, it returns nil.
+func (ctxt *Context) lookup(h string, orig *Named, targs []Type) *Named {
 	ctxt.mu.Lock()
 	defer ctxt.mu.Unlock()
-	if existing := ctxt.typeMap[h]; existing != nil {
-		return existing
+
+	for _, e := range ctxt.typeMap[h] {
+		if identicalInstance(orig, targs, e.orig, e.TypeArgs().list()) {
+			return e
+		}
+		if debug {
+			// Panic during development to surface any imperfections in our hash.
+			panic(fmt.Sprintf("non-identical instances: (orig: %s, targs: %v) and %s", orig, targs, e))
+		}
 	}
-	if n != nil {
-		ctxt.typeMap[h] = n
+
+	return nil
+}
+
+// update de-duplicates n against previously seen types with the hash h.  If an
+// identical type is found with the type hash h, the previously seen type is
+// returned. Otherwise, n is returned, and recorded in the Context for the hash
+// h.
+func (ctxt *Context) update(h string, n *Named) *Named {
+	assert(n != nil)
+
+	ctxt.mu.Lock()
+	defer ctxt.mu.Unlock()
+
+	for _, e := range ctxt.typeMap[h] {
+		if n == nil || Identical(n, e) {
+			return e
+		}
+		if debug {
+			// Panic during development to surface any imperfections in our hash.
+			panic(fmt.Sprintf("%s and %s are not identical", n, e))
+		}
 	}
+
+	ctxt.typeMap[h] = append(ctxt.typeMap[h], n)
 	return n
 }
 
diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go
index 8d8d281842..1077ad8160 100644
--- a/src/go/types/instantiate.go
+++ b/src/go/types/instantiate.go
@@ -60,7 +60,7 @@ func (check *Checker) instance(pos token.Pos, typ Type, targs []Type, ctxt *Cont
 			h = ctxt.typeHash(t, targs)
 			// typ may already have been instantiated with identical type arguments. In
 			// that case, re-use the existing instance.
-			if named := ctxt.typeForHash(h, nil); named != nil {
+			if named := ctxt.lookup(h, t, targs); named != nil {
 				return named
 			}
 		}
@@ -73,7 +73,7 @@ func (check *Checker) instance(pos token.Pos, typ Type, targs []Type, ctxt *Cont
 		if ctxt != nil {
 			// It's possible that we've lost a race to add named to the context.
 			// In this case, use whichever instance is recorded in the context.
-			named = ctxt.typeForHash(h, named)
+			named = ctxt.update(h, named)
 		}
 		return named
 
diff --git a/src/go/types/named.go b/src/go/types/named.go
index 393d40b127..12d87af084 100644
--- a/src/go/types/named.go
+++ b/src/go/types/named.go
@@ -255,7 +255,7 @@ func expandNamed(ctxt *Context, n *Named, instPos token.Pos) (tparams *TypeParam
 		ctxt = check.bestContext(ctxt)
 		h := ctxt.typeHash(n.orig, n.targs.list())
 		// ensure that an instance is recorded for h to avoid infinite recursion.
-		ctxt.typeForHash(h, n)
+		ctxt.update(h, n)
 
 		smap := makeSubstMap(n.orig.tparams.list(), n.targs.list())
 		underlying = n.check.subst(instPos, n.orig.underlying, smap, ctxt)
diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go
index e8689a12cc..e7f9d3b1db 100644
--- a/src/go/types/predicates.go
+++ b/src/go/types/predicates.go
@@ -375,6 +375,23 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
 	return false
 }
 
+// identicalInstance reports if two type instantiations are identical.
+// Instantiations are identical if their origin and type arguments are
+// identical.
+func identicalInstance(xorig Type, xargs []Type, yorig Type, yargs []Type) bool {
+	if len(xargs) != len(yargs) {
+		return false
+	}
+
+	for i, xa := range xargs {
+		if !Identical(xa, yargs[i]) {
+			return false
+		}
+	}
+
+	return Identical(xorig, yorig)
+}
+
 func identicalTParams(x, y []*TypeParam, cmpTags bool, p *ifacePair) bool {
 	if len(x) != len(y) {
 		return false
diff --git a/src/go/types/subst.go b/src/go/types/subst.go
index a05195150f..0e3eafdaf1 100644
--- a/src/go/types/subst.go
+++ b/src/go/types/subst.go
@@ -209,7 +209,7 @@ func (subst *subster) typ(typ Type) Type {
 		// before creating a new named type, check if we have this one already
 		h := subst.ctxt.typeHash(t.orig, newTArgs)
 		dump(">>> new type hash: %s", h)
-		if named := subst.ctxt.typeForHash(h, nil); named != nil {
+		if named := subst.ctxt.lookup(h, t.orig, newTArgs); named != nil {
 			dump(">>> found %s", named)
 			return named
 		}
diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go
index 12e0f968c2..17d07649ef 100644
--- a/src/go/types/typexpr.go
+++ b/src/go/types/typexpr.go
@@ -390,8 +390,8 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named
 		return gtyp // error already reported
 	}
 
-	origin, _ := gtyp.(*Named)
-	if origin == nil {
+	orig, _ := gtyp.(*Named)
+	if orig == nil {
 		panic(fmt.Sprintf("%v: cannot instantiate %v", x.Pos(), gtyp))
 	}
 
@@ -409,23 +409,23 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named
 	}
 
 	// create the instance
-	h := check.conf.Context.typeHash(origin, targs)
+	h := check.conf.Context.typeHash(orig, targs)
 	// targs may be incomplete, and require inference. In any case we should de-duplicate.
-	inst := check.conf.Context.typeForHash(h, nil)
+	inst := check.conf.Context.lookup(h, orig, targs)
 	// If inst is non-nil, we can't just return here. Inst may have been
 	// constructed via recursive substitution, in which case we wouldn't do the
 	// validation below. Ensure that the validation (and resulting errors) runs
 	// for each instantiated type in the source.
 	if inst == nil {
-		tname := NewTypeName(x.Pos(), origin.obj.pkg, origin.obj.name, nil)
-		inst = check.newNamed(tname, origin, nil, nil, nil) // underlying, methods and tparams are set when named is resolved
+		tname := NewTypeName(x.Pos(), orig.obj.pkg, orig.obj.name, nil)
+		inst = check.newNamed(tname, orig, nil, nil, nil) // underlying, methods and tparams are set when named is resolved
 		inst.targs = NewTypeList(targs)
-		inst = check.conf.Context.typeForHash(h, inst)
+		inst = check.conf.Context.update(h, inst)
 	}
 	def.setUnderlying(inst)
 
 	inst.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, []*Func) {
-		tparams := origin.TypeParams().list()
+		tparams := orig.TypeParams().list()
 
 		inferred := targs
 		if len(targs) < len(tparams) {
-- 
GitLab


From 2dbf37045c24c8ab6f93083adc8be9ccdb3e3603 Mon Sep 17 00:00:00 2001
From: Robert Findley 
Date: Tue, 9 Nov 2021 22:20:18 -0500
Subject: [PATCH 2140/2500] go/types: refactor the Context type map to accept
 arbitrary types

In preparation for storing *Signature types in Context, refactor the
type map to not depend on the *Named type API.

Change-Id: I0439d43aa4cc3a60a78f409a773a343a4fffd0fa
Reviewed-on: https://go-review.googlesource.com/c/go/+/362799
Trust: Robert Findley 
Run-TryBot: Robert Findley 
TryBot-Result: Go Bot 
Reviewed-by: Robert Griesemer 
---
 src/go/types/context.go     | 41 +++++++++++++++++++++++--------------
 src/go/types/instantiate.go | 24 +++++++++++-----------
 src/go/types/named.go       |  2 +-
 src/go/types/typexpr.go     |  4 ++--
 4 files changed, 41 insertions(+), 30 deletions(-)

diff --git a/src/go/types/context.go b/src/go/types/context.go
index e89babcd70..0c2b0958c1 100644
--- a/src/go/types/context.go
+++ b/src/go/types/context.go
@@ -18,15 +18,21 @@ import (
 // It is safe for concurrent use.
 type Context struct {
 	mu      sync.Mutex
-	typeMap map[string][]*Named // type hash -> instances
-	nextID  int                 // next unique ID
-	seen    map[*Named]int      // assigned unique IDs
+	typeMap map[string][]ctxtEntry // type hash -> instances entries
+	nextID  int                    // next unique ID
+	seen    map[*Named]int         // assigned unique IDs
+}
+
+type ctxtEntry struct {
+	orig     Type
+	targs    []Type
+	instance Type // = orig[targs]
 }
 
 // NewContext creates a new Context.
 func NewContext() *Context {
 	return &Context{
-		typeMap: make(map[string][]*Named),
+		typeMap: make(map[string][]ctxtEntry),
 		seen:    make(map[*Named]int),
 	}
 }
@@ -60,17 +66,17 @@ func (ctxt *Context) typeHash(typ Type, targs []Type) string {
 
 // lookup returns an existing instantiation of orig with targs, if it exists.
 // Otherwise, it returns nil.
-func (ctxt *Context) lookup(h string, orig *Named, targs []Type) *Named {
+func (ctxt *Context) lookup(h string, orig *Named, targs []Type) Type {
 	ctxt.mu.Lock()
 	defer ctxt.mu.Unlock()
 
 	for _, e := range ctxt.typeMap[h] {
-		if identicalInstance(orig, targs, e.orig, e.TypeArgs().list()) {
-			return e
+		if identicalInstance(orig, targs, e.orig, e.targs) {
+			return e.instance
 		}
 		if debug {
 			// Panic during development to surface any imperfections in our hash.
-			panic(fmt.Sprintf("non-identical instances: (orig: %s, targs: %v) and %s", orig, targs, e))
+			panic(fmt.Sprintf("non-identical instances: (orig: %s, targs: %v) and %s", orig, targs, e.instance))
 		}
 	}
 
@@ -81,24 +87,29 @@ func (ctxt *Context) lookup(h string, orig *Named, targs []Type) *Named {
 // identical type is found with the type hash h, the previously seen type is
 // returned. Otherwise, n is returned, and recorded in the Context for the hash
 // h.
-func (ctxt *Context) update(h string, n *Named) *Named {
-	assert(n != nil)
+func (ctxt *Context) update(h string, orig Type, targs []Type, inst Type) Type {
+	assert(inst != nil)
 
 	ctxt.mu.Lock()
 	defer ctxt.mu.Unlock()
 
 	for _, e := range ctxt.typeMap[h] {
-		if n == nil || Identical(n, e) {
-			return e
+		if inst == nil || Identical(inst, e.instance) {
+			return e.instance
 		}
 		if debug {
 			// Panic during development to surface any imperfections in our hash.
-			panic(fmt.Sprintf("%s and %s are not identical", n, e))
+			panic(fmt.Sprintf("%s and %s are not identical", inst, e.instance))
 		}
 	}
 
-	ctxt.typeMap[h] = append(ctxt.typeMap[h], n)
-	return n
+	ctxt.typeMap[h] = append(ctxt.typeMap[h], ctxtEntry{
+		orig:     orig,
+		targs:    targs,
+		instance: inst,
+	})
+
+	return inst
 }
 
 // idForType returns a unique ID for the pointer n.
diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go
index 1077ad8160..814d457de3 100644
--- a/src/go/types/instantiate.go
+++ b/src/go/types/instantiate.go
@@ -52,20 +52,20 @@ func Instantiate(ctxt *Context, typ Type, targs []Type, validate bool) (Type, er
 // instance creates a type or function instance using the given original type
 // typ and arguments targs. For Named types the resulting instance will be
 // unexpanded.
-func (check *Checker) instance(pos token.Pos, typ Type, targs []Type, ctxt *Context) Type {
-	switch t := typ.(type) {
+func (check *Checker) instance(pos token.Pos, orig Type, targs []Type, ctxt *Context) Type {
+	switch orig := orig.(type) {
 	case *Named:
 		var h string
 		if ctxt != nil {
-			h = ctxt.typeHash(t, targs)
+			h = ctxt.typeHash(orig, targs)
 			// typ may already have been instantiated with identical type arguments. In
 			// that case, re-use the existing instance.
-			if named := ctxt.lookup(h, t, targs); named != nil {
+			if named := ctxt.lookup(h, orig, targs); named != nil {
 				return named
 			}
 		}
-		tname := NewTypeName(pos, t.obj.pkg, t.obj.name, nil)
-		named := check.newNamed(tname, t, nil, nil, nil) // underlying, tparams, and methods are set when named is resolved
+		tname := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil)
+		named := check.newNamed(tname, orig, nil, nil, nil) // underlying, tparams, and methods are set when named is resolved
 		named.targs = NewTypeList(targs)
 		named.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, []*Func) {
 			return expandNamed(ctxt, n, pos)
@@ -73,23 +73,23 @@ func (check *Checker) instance(pos token.Pos, typ Type, targs []Type, ctxt *Cont
 		if ctxt != nil {
 			// It's possible that we've lost a race to add named to the context.
 			// In this case, use whichever instance is recorded in the context.
-			named = ctxt.update(h, named)
+			named = ctxt.update(h, orig, targs, named).(*Named)
 		}
 		return named
 
 	case *Signature:
-		tparams := t.TypeParams()
+		tparams := orig.TypeParams()
 		if !check.validateTArgLen(pos, tparams.Len(), len(targs)) {
 			return Typ[Invalid]
 		}
 		if tparams.Len() == 0 {
-			return typ // nothing to do (minor optimization)
+			return orig // nothing to do (minor optimization)
 		}
-		sig := check.subst(pos, typ, makeSubstMap(tparams.list(), targs), ctxt).(*Signature)
+		sig := check.subst(pos, orig, makeSubstMap(tparams.list(), targs), ctxt).(*Signature)
 		// If the signature doesn't use its type parameters, subst
 		// will not make a copy. In that case, make a copy now (so
 		// we can set tparams to nil w/o causing side-effects).
-		if sig == t {
+		if sig == orig {
 			copy := *sig
 			sig = ©
 		}
@@ -99,7 +99,7 @@ func (check *Checker) instance(pos token.Pos, typ Type, targs []Type, ctxt *Cont
 		return sig
 	}
 	// only types and functions can be generic
-	panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ))
+	panic(fmt.Sprintf("%v: cannot instantiate %v", pos, orig))
 }
 
 // validateTArgLen verifies that the length of targs and tparams matches,
diff --git a/src/go/types/named.go b/src/go/types/named.go
index 12d87af084..ed3c426a12 100644
--- a/src/go/types/named.go
+++ b/src/go/types/named.go
@@ -255,7 +255,7 @@ func expandNamed(ctxt *Context, n *Named, instPos token.Pos) (tparams *TypeParam
 		ctxt = check.bestContext(ctxt)
 		h := ctxt.typeHash(n.orig, n.targs.list())
 		// ensure that an instance is recorded for h to avoid infinite recursion.
-		ctxt.update(h, n)
+		ctxt.update(h, n.orig, n.TypeArgs().list(), n)
 
 		smap := makeSubstMap(n.orig.tparams.list(), n.targs.list())
 		underlying = n.check.subst(instPos, n.orig.underlying, smap, ctxt)
diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go
index 17d07649ef..048bc95e15 100644
--- a/src/go/types/typexpr.go
+++ b/src/go/types/typexpr.go
@@ -411,7 +411,7 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named
 	// create the instance
 	h := check.conf.Context.typeHash(orig, targs)
 	// targs may be incomplete, and require inference. In any case we should de-duplicate.
-	inst := check.conf.Context.lookup(h, orig, targs)
+	inst, _ := check.conf.Context.lookup(h, orig, targs).(*Named)
 	// If inst is non-nil, we can't just return here. Inst may have been
 	// constructed via recursive substitution, in which case we wouldn't do the
 	// validation below. Ensure that the validation (and resulting errors) runs
@@ -420,7 +420,7 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named
 		tname := NewTypeName(x.Pos(), orig.obj.pkg, orig.obj.name, nil)
 		inst = check.newNamed(tname, orig, nil, nil, nil) // underlying, methods and tparams are set when named is resolved
 		inst.targs = NewTypeList(targs)
-		inst = check.conf.Context.update(h, inst)
+		inst = check.conf.Context.update(h, orig, targs, inst).(*Named)
 	}
 	def.setUnderlying(inst)
 
-- 
GitLab


From ede97290edd6ca9291d44f8eba503fbd8b162ed4 Mon Sep 17 00:00:00 2001
From: Robert Findley 
Date: Tue, 9 Nov 2021 22:28:18 -0500
Subject: [PATCH 2141/2500] go/types: re-use type hashing logic in
 Context.typeHash

The special handling for *Named types is not necessary. The hash of an
instance is simply the hash of its type followed by its type argument
list.

Change-Id: I7aa58e73b81731c3cad3a2fd14124f63cfb685a7
Reviewed-on: https://go-review.googlesource.com/c/go/+/362800
Trust: Robert Findley 
Run-TryBot: Robert Findley 
TryBot-Result: Go Bot 
Reviewed-by: Robert Griesemer 
---
 src/go/types/context.go     | 26 ++++++++++----------------
 src/go/types/instantiate.go |  4 ++--
 2 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/src/go/types/context.go b/src/go/types/context.go
index 0c2b0958c1..1f102f0b8b 100644
--- a/src/go/types/context.go
+++ b/src/go/types/context.go
@@ -37,28 +37,22 @@ func NewContext() *Context {
 	}
 }
 
-// typeHash returns a string representation of typ, which can be used as an exact
-// type hash: types that are identical produce identical string representations.
-// If typ is a *Named type and targs is not empty, typ is printed as if it were
-// instantiated with targs. The result is guaranteed to not contain blanks (" ").
+// typeHash returns a string representation of typ instantiated with targs,
+// which can be used as an exact type hash: types that are identical produce
+// identical string representations. If targs is not empty, typ is printed as
+// if it were instantiated with targs. The result is guaranteed to not contain
+// blanks (" ").
 func (ctxt *Context) typeHash(typ Type, targs []Type) string {
 	assert(ctxt != nil)
 	assert(typ != nil)
 	var buf bytes.Buffer
 
 	h := newTypeHasher(&buf, ctxt)
-	// Caution: don't use asNamed here. TypeHash may be called for unexpanded
-	// types. We don't need anything other than name and type arguments below,
-	// which do not require expansion.
-	if named, _ := typ.(*Named); named != nil && len(targs) > 0 {
-		// Don't use WriteType because we need to use the provided targs
-		// and not any targs that might already be with the *Named type.
-		h.typePrefix(named)
-		h.typeName(named.obj)
+	h.typ(typ)
+	if len(targs) > 0 {
+		// TODO(rfindley): consider asserting on isGeneric(typ) here, if and when
+		// isGeneric handles *Signature types.
 		h.typeList(targs)
-	} else {
-		assert(targs == nil)
-		h.typ(typ)
 	}
 
 	return strings.Replace(buf.String(), " ", "#", -1) // ReplaceAll is not available in Go1.4
@@ -66,7 +60,7 @@ func (ctxt *Context) typeHash(typ Type, targs []Type) string {
 
 // lookup returns an existing instantiation of orig with targs, if it exists.
 // Otherwise, it returns nil.
-func (ctxt *Context) lookup(h string, orig *Named, targs []Type) Type {
+func (ctxt *Context) lookup(h string, orig Type, targs []Type) Type {
 	ctxt.mu.Lock()
 	defer ctxt.mu.Unlock()
 
diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go
index 814d457de3..62d9e18401 100644
--- a/src/go/types/instantiate.go
+++ b/src/go/types/instantiate.go
@@ -60,8 +60,8 @@ func (check *Checker) instance(pos token.Pos, orig Type, targs []Type, ctxt *Con
 			h = ctxt.typeHash(orig, targs)
 			// typ may already have been instantiated with identical type arguments. In
 			// that case, re-use the existing instance.
-			if named := ctxt.lookup(h, orig, targs); named != nil {
-				return named
+			if inst := ctxt.lookup(h, orig, targs); inst != nil {
+				return inst
 			}
 		}
 		tname := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil)
-- 
GitLab


From 8b66b3d49f931715c52b4ed71bc1dc935132c30f Mon Sep 17 00:00:00 2001
From: Robert Findley 
Date: Thu, 11 Nov 2021 19:07:28 -0500
Subject: [PATCH 2142/2500] cmd/compile/internal/types2: unexport
 Context.TypeHash

Context.TypeHash is not being used outside of the type checker, so
unexport it.

The TypeHash method is meant to hash instances, not arbitrary types, and
will soon be modified to differentiate origin types by pointer identity
(even if they are *Signature types).

Change-Id: Ia8d4a7c6350ce7f278b70630585efb0009fef63a
Reviewed-on: https://go-review.googlesource.com/c/go/+/363516
Trust: Robert Findley 
Run-TryBot: Robert Findley 
TryBot-Result: Go Bot 
Reviewed-by: Robert Griesemer 
---
 src/cmd/compile/internal/types2/context.go     | 4 ++--
 src/cmd/compile/internal/types2/instantiate.go | 2 +-
 src/cmd/compile/internal/types2/named.go       | 2 +-
 src/cmd/compile/internal/types2/subst.go       | 2 +-
 src/cmd/compile/internal/types2/typexpr.go     | 2 +-
 5 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/cmd/compile/internal/types2/context.go b/src/cmd/compile/internal/types2/context.go
index f6137eea43..9e9eb5bdf6 100644
--- a/src/cmd/compile/internal/types2/context.go
+++ b/src/cmd/compile/internal/types2/context.go
@@ -29,11 +29,11 @@ func NewContext() *Context {
 	}
 }
 
-// TypeHash returns a string representation of typ, which can be used as an exact
+// typeHash returns a string representation of typ, which can be used as an exact
 // type hash: types that are identical produce identical string representations.
 // If typ is a *Named type and targs is not empty, typ is printed as if it were
 // instantiated with targs. The result is guaranteed to not contain blanks (" ").
-func (ctxt *Context) TypeHash(typ Type, targs []Type) string {
+func (ctxt *Context) typeHash(typ Type, targs []Type) string {
 	assert(ctxt != nil)
 	assert(typ != nil)
 	var buf bytes.Buffer
diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go
index 44cf593ffb..f814619bb0 100644
--- a/src/cmd/compile/internal/types2/instantiate.go
+++ b/src/cmd/compile/internal/types2/instantiate.go
@@ -57,7 +57,7 @@ func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type, ctxt *Con
 	case *Named:
 		var h string
 		if ctxt != nil {
-			h = ctxt.TypeHash(t, targs)
+			h = ctxt.typeHash(t, targs)
 			// typ may already have been instantiated with identical type arguments. In
 			// that case, re-use the existing instance.
 			if named := ctxt.typeForHash(h, nil); named != nil {
diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go
index 6ebad8fbb5..e73a31d42e 100644
--- a/src/cmd/compile/internal/types2/named.go
+++ b/src/cmd/compile/internal/types2/named.go
@@ -251,7 +251,7 @@ func expandNamed(ctxt *Context, n *Named, instPos syntax.Pos) (tparams *TypePara
 	if n.orig.tparams.Len() == n.targs.Len() {
 		// We must always have a context, to avoid infinite recursion.
 		ctxt = check.bestContext(ctxt)
-		h := ctxt.TypeHash(n.orig, n.targs.list())
+		h := ctxt.typeHash(n.orig, n.targs.list())
 		// ensure that an instance is recorded for h to avoid infinite recursion.
 		ctxt.typeForHash(h, n)
 
diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go
index f46e895b12..5deb868a79 100644
--- a/src/cmd/compile/internal/types2/subst.go
+++ b/src/cmd/compile/internal/types2/subst.go
@@ -207,7 +207,7 @@ func (subst *subster) typ(typ Type) Type {
 		}
 
 		// before creating a new named type, check if we have this one already
-		h := subst.ctxt.TypeHash(t.orig, newTArgs)
+		h := subst.ctxt.typeHash(t.orig, newTArgs)
 		dump(">>> new type hash: %s", h)
 		if named := subst.ctxt.typeForHash(h, nil); named != nil {
 			dump(">>> found %s", named)
diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go
index a08e472703..82c029cfd6 100644
--- a/src/cmd/compile/internal/types2/typexpr.go
+++ b/src/cmd/compile/internal/types2/typexpr.go
@@ -431,7 +431,7 @@ func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def
 	}
 
 	// create the instance
-	h := check.conf.Context.TypeHash(origin, targs)
+	h := check.conf.Context.typeHash(origin, targs)
 	// targs may be incomplete, and require inference. In any case we should de-duplicate.
 	inst := check.conf.Context.typeForHash(h, nil)
 	// If inst is non-nil, we can't just return here. Inst may have been
-- 
GitLab


From 5d24203c394e6b64c42a9f69b990d94cb6c8aad4 Mon Sep 17 00:00:00 2001
From: Katie Hockman 
Date: Wed, 10 Nov 2021 16:22:08 -0500
Subject: [PATCH 2143/2500] internal/fuzz: set timeout for each exec of fuzz
 target

This change sets a timeout of 10 seconds on each
execution of the fuzz target, both during fuzzing
and during minimization. This is not currently
customizable by the user, but issue #48157 tracks
this work.

Deadlocks will be considered non-recoverable errors,
and as such, will not be minimizable.

Fixes #48591

Change-Id: Ic86e8e9e9a0255e7860f7cbf5654e832785d1cbc
Reviewed-on: https://go-review.googlesource.com/c/go/+/363134
Trust: Katie Hockman 
Run-TryBot: Katie Hockman 
TryBot-Result: Go Bot 
Reviewed-by: Bryan C. Mills 
---
 .../go/testdata/script/test_fuzz_minimize.txt |  2 +-
 .../script/test_fuzz_mutate_crash.txt         | 16 ++++++++-
 .../script/test_fuzz_mutator_repeat.txt       |  2 +-
 .../script/test_fuzz_non_crash_signal.txt     |  2 +-
 src/internal/fuzz/minimize_test.go            |  9 +++--
 src/internal/fuzz/worker.go                   | 36 ++++++++++++-------
 src/internal/fuzz/worker_test.go              |  3 +-
 7 files changed, 49 insertions(+), 21 deletions(-)

diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize.txt b/src/cmd/go/testdata/script/test_fuzz_minimize.txt
index 462fb9a963..a6dc3f1953 100644
--- a/src/cmd/go/testdata/script/test_fuzz_minimize.txt
+++ b/src/cmd/go/testdata/script/test_fuzz_minimize.txt
@@ -67,7 +67,7 @@ rm testdata
 ! go test -fuzz=FuzzMinimizerNonrecoverable -run=FuzzMinimizerNonrecoverable -fuzztime=10000x .
 ! stdout '^ok'
 ! stdout 'minimizing'
-stdout -count=1 'fuzzing process terminated unexpectedly: exit status 99'
+stdout -count=1 '^\s+fuzzing process hung or terminated unexpectedly: exit status 99'
 stdout FAIL
 
 # Check that re-running the value causes a crash.
diff --git a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt
index 4c4fa8e651..99bae1daf0 100644
--- a/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt
+++ b/src/cmd/go/testdata/script/test_fuzz_mutate_crash.txt
@@ -54,9 +54,14 @@ go run check_testdata.go FuzzWithFatalf
 
 ! go test -run=FuzzWithBadExit -fuzz=FuzzWithBadExit -fuzztime=100x -fuzzminimizetime=1000x
 stdout 'testdata[/\\]fuzz[/\\]FuzzWithBadExit[/\\]'
-stdout 'unexpectedly'
+stdout '^\s+fuzzing process hung or terminated unexpectedly: exit status'
 go run check_testdata.go FuzzWithBadExit
 
+! go test -run=FuzzDeadlock -fuzz=FuzzDeadlock -fuzztime=100x -fuzzminimizetime=0x
+stdout 'testdata[/\\]fuzz[/\\]FuzzDeadlock[/\\]'
+stdout '^\s+fuzzing process hung or terminated unexpectedly: exit status'
+go run check_testdata.go FuzzDeadlock
+
 # Running the fuzzer should find a crashing input quickly for fuzzing two types.
 ! go test -run=FuzzWithTwoTypes -fuzz=FuzzWithTwoTypes -fuzztime=100x -fuzzminimizetime=1000x
 stdout 'testdata[/\\]fuzz[/\\]FuzzWithTwoTypes[/\\]'
@@ -190,6 +195,15 @@ func FuzzWithBadExit(f *testing.F) {
 	})
 }
 
+func FuzzDeadlock(f *testing.F) {
+	f.Add(int(0))
+	f.Fuzz(func(t *testing.T, n int) {
+		if n != 0 {
+			select {}
+		}
+	})
+}
+
 func FuzzWithTwoTypes(f *testing.F) {
 	f.Fuzz(func(t *testing.T, a, b []byte) {
 		if len(a) > 0 && len(b) > 0 {
diff --git a/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt b/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt
index 60f5787464..3764dcb915 100644
--- a/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt
+++ b/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt
@@ -12,7 +12,7 @@
 # The fuzzing engine reconstructs the crashing input and saves it to testdata.
 ! exists want
 ! go test -fuzz=. -parallel=1 -fuzztime=110x -fuzzminimizetime=10x -v
-stdout 'fuzzing process terminated unexpectedly'
+stdout '^\s+fuzzing process hung or terminated unexpectedly: exit status'
 stdout 'Failing input written to testdata'
 
 # Run the fuzz target without fuzzing. The fuzz function is called with the
diff --git a/src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt b/src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt
index 31d54bcb70..1051292fcb 100644
--- a/src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt
+++ b/src/cmd/go/testdata/script/test_fuzz_non_crash_signal.txt
@@ -25,7 +25,7 @@ stdout 'fuzzing process terminated by unexpected signal; no crash will be record
 # We should save a crasher.
 ! go test -fuzz=FuzzCrash
 exists testdata/fuzz/FuzzCrash
-stdout 'fuzzing process terminated unexpectedly'
+stdout '^\s+fuzzing process hung or terminated unexpectedly: exit status'
 
 -- go.mod --
 module test
diff --git a/src/internal/fuzz/minimize_test.go b/src/internal/fuzz/minimize_test.go
index dc153d0de4..04d785ce40 100644
--- a/src/internal/fuzz/minimize_test.go
+++ b/src/internal/fuzz/minimize_test.go
@@ -13,6 +13,7 @@ import (
 	"fmt"
 	"reflect"
 	"testing"
+	"time"
 	"unicode"
 	"unicode/utf8"
 )
@@ -279,7 +280,9 @@ func TestMinimizeInput(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			t.Parallel()
 			ws := &workerServer{
-				fuzzFn: tc.fn,
+				fuzzFn: func(e CorpusEntry) (time.Duration, error) {
+					return time.Second, tc.fn(e)
+				},
 			}
 			count := int64(0)
 			vals := tc.input
@@ -304,8 +307,8 @@ func TestMinimizeInput(t *testing.T) {
 // input and a flaky failure occurs, that minimization was not indicated
 // to be successful, and the error isn't returned (since it's flaky).
 func TestMinimizeFlaky(t *testing.T) {
-	ws := &workerServer{fuzzFn: func(e CorpusEntry) error {
-		return errors.New("ohno")
+	ws := &workerServer{fuzzFn: func(e CorpusEntry) (time.Duration, error) {
+		return time.Second, errors.New("ohno")
 	}}
 	keepCoverage := make([]byte, len(coverageSnapshot))
 	count := int64(0)
diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go
index 02efa7f84a..48a3923112 100644
--- a/src/internal/fuzz/worker.go
+++ b/src/internal/fuzz/worker.go
@@ -142,7 +142,7 @@ func (w *worker) coordinate(ctx context.Context) error {
 			}
 			// Worker exited non-zero or was terminated by a non-interrupt
 			// signal (for example, SIGSEGV) while fuzzing.
-			return fmt.Errorf("fuzzing process terminated unexpectedly: %w", err)
+			return fmt.Errorf("fuzzing process hung or terminated unexpectedly: %w", err)
 			// TODO(jayconrod,katiehockman): if -keepfuzzing, restart worker.
 
 		case input := <-w.coordinator.inputC:
@@ -183,7 +183,7 @@ func (w *worker) coordinate(ctx context.Context) error {
 				// Unexpected termination. Set error message and fall through.
 				// We'll restart the worker on the next iteration.
 				// Don't attempt to minimize this since it crashed the worker.
-				resp.Err = fmt.Sprintf("fuzzing process terminated unexpectedly: %v", w.waitErr)
+				resp.Err = fmt.Sprintf("fuzzing process hung or terminated unexpectedly: %v", w.waitErr)
 				canMinimize = false
 			}
 			result := fuzzResult{
@@ -255,7 +255,7 @@ func (w *worker) minimize(ctx context.Context, input fuzzMinimizeInput) (min fuz
 				limit:        input.limit,
 			}, nil
 		}
-		return fuzzResult{}, fmt.Errorf("fuzzing process terminated unexpectedly while minimizing: %w", w.waitErr)
+		return fuzzResult{}, fmt.Errorf("fuzzing process hung or terminated unexpectedly while minimizing: %w", w.waitErr)
 	}
 
 	if input.crasherMsg != "" && resp.Err == "" {
@@ -471,8 +471,16 @@ func RunFuzzWorker(ctx context.Context, fn func(CorpusEntry) error) error {
 	}
 	srv := &workerServer{
 		workerComm: comm,
-		fuzzFn:     fn,
-		m:          newMutator(),
+		fuzzFn: func(e CorpusEntry) (time.Duration, error) {
+			timer := time.AfterFunc(10*time.Second, func() {
+				panic("deadlocked!") // this error message won't be printed
+			})
+			defer timer.Stop()
+			start := time.Now()
+			err := fn(e)
+			return time.Since(start), err
+		},
+		m: newMutator(),
 	}
 	return srv.serve(ctx)
 }
@@ -604,9 +612,12 @@ type workerServer struct {
 	// coverage is found.
 	coverageMask []byte
 
-	// fuzzFn runs the worker's fuzz function on the given input and returns
-	// an error if it finds a crasher (the process may also exit or crash).
-	fuzzFn func(CorpusEntry) error
+	// fuzzFn runs the worker's fuzz target on the given input and returns an
+	// error if it finds a crasher (the process may also exit or crash), and the
+	// time it took to run the input. It sets a deadline of 10 seconds, at which
+	// point it will panic with the assumption that the process is hanging or
+	// deadlocked.
+	fuzzFn func(CorpusEntry) (time.Duration, error)
 }
 
 // serve reads serialized RPC messages on fuzzIn. When serve receives a message,
@@ -699,9 +710,8 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo
 	}
 	fuzzOnce := func(entry CorpusEntry) (dur time.Duration, cov []byte, errMsg string) {
 		mem.header().count++
-		start := time.Now()
-		err := ws.fuzzFn(entry)
-		dur = time.Since(start)
+		var err error
+		dur, err = ws.fuzzFn(entry)
 		if err != nil {
 			errMsg = err.Error()
 			if errMsg == "" {
@@ -803,7 +813,7 @@ func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, c
 	// If not, then whatever caused us to think the value was interesting may
 	// have been a flake, and we can't minimize it.
 	*count++
-	retErr = ws.fuzzFn(CorpusEntry{Values: vals})
+	_, retErr = ws.fuzzFn(CorpusEntry{Values: vals})
 	if keepCoverage != nil {
 		if !hasCoverageBit(keepCoverage, coverageSnapshot) || retErr != nil {
 			return false, nil
@@ -870,7 +880,7 @@ func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, c
 			panic("impossible")
 		}
 		*count++
-		err := ws.fuzzFn(CorpusEntry{Values: vals})
+		_, err := ws.fuzzFn(CorpusEntry{Values: vals})
 		if err != nil {
 			retErr = err
 			if keepCoverage != nil {
diff --git a/src/internal/fuzz/worker_test.go b/src/internal/fuzz/worker_test.go
index c6f83fd08d..ed9722f43a 100644
--- a/src/internal/fuzz/worker_test.go
+++ b/src/internal/fuzz/worker_test.go
@@ -14,6 +14,7 @@ import (
 	"os/signal"
 	"reflect"
 	"testing"
+	"time"
 )
 
 var benchmarkWorkerFlag = flag.Bool("benchmarkworker", false, "")
@@ -36,7 +37,7 @@ func BenchmarkWorkerFuzzOverhead(b *testing.B) {
 	os.Setenv("GODEBUG", fmt.Sprintf("%s,fuzzseed=123", origEnv))
 
 	ws := &workerServer{
-		fuzzFn:     func(_ CorpusEntry) error { return nil },
+		fuzzFn:     func(_ CorpusEntry) (time.Duration, error) { return time.Second, nil },
 		workerComm: workerComm{memMu: make(chan *sharedMem, 1)},
 	}
 
-- 
GitLab


From b1b6d928bd4fb368f8ada0a554fc85405e7a3688 Mon Sep 17 00:00:00 2001
From: Cuong Manh Le 
Date: Fri, 12 Nov 2021 13:27:07 +0700
Subject: [PATCH 2144/2500] cmd/compile: fix missing transformEarlyCall for
 OXDOT in subster.node

Like OFUNCINST, in case of OXDOT call expression, the arguments need
to be transformed earlier, so any needed CONVIFACE nodes are exposed.

Fixes #49538

Change-Id: I275ddf6f53a9cadc8708e805941cdf7bdffabba9
Reviewed-on: https://go-review.googlesource.com/c/go/+/363554
Trust: Cuong Manh Le 
Trust: Dan Scales 
Run-TryBot: Cuong Manh Le 
TryBot-Result: Go Bot 
Reviewed-by: Dan Scales 
---
 src/cmd/compile/internal/noder/stencil.go | 12 ++++++++----
 test/typeparam/issue49538.go              | 23 +++++++++++++++++++++++
 2 files changed, 31 insertions(+), 4 deletions(-)
 create mode 100644 test/typeparam/issue49538.go

diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go
index 20197565f5..4f9f8107bc 100644
--- a/src/cmd/compile/internal/noder/stencil.go
+++ b/src/cmd/compile/internal/noder/stencil.go
@@ -1095,6 +1095,9 @@ func (subst *subster) node(n ir.Node) ir.Node {
 			case ir.OXDOT:
 				// This is the case of a bound call on a typeparam,
 				// which will be handled in the dictPass.
+				// As with OFUNCINST, we must transform the arguments of the call now,
+				// so any needed CONVIFACE nodes are exposed.
+				transformEarlyCall(call)
 
 			case ir.ODOTTYPE, ir.ODOTTYPE2:
 				// These are DOTTYPEs that could get transformed into
@@ -1229,14 +1232,15 @@ func (g *genInst) dictPass(info *instInfo) {
 				transformDot(mse, false)
 			}
 		case ir.OCALL:
-			op := m.(*ir.CallExpr).X.Op()
+			call := m.(*ir.CallExpr)
+			op := call.X.Op()
 			if op == ir.OMETHVALUE {
 				// Redo the transformation of OXDOT, now that we
 				// know the method value is being called.
-				m.(*ir.CallExpr).X.(*ir.SelectorExpr).SetOp(ir.OXDOT)
-				transformDot(m.(*ir.CallExpr).X.(*ir.SelectorExpr), true)
+				call.X.(*ir.SelectorExpr).SetOp(ir.OXDOT)
+				transformDot(call.X.(*ir.SelectorExpr), true)
 			}
-			transformCall(m.(*ir.CallExpr))
+			transformCall(call)
 
 		case ir.OCONVIFACE:
 			if m.Type().IsEmptyInterface() && m.(*ir.ConvExpr).X.Type().IsEmptyInterface() {
diff --git a/test/typeparam/issue49538.go b/test/typeparam/issue49538.go
new file mode 100644
index 0000000000..ac20a5423f
--- /dev/null
+++ b/test/typeparam/issue49538.go
@@ -0,0 +1,23 @@
+// compile -G=3
+
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type I interface {
+	M(interface{})
+}
+
+type a[T any] struct{}
+
+func (a[T]) M(interface{}) {}
+
+func f[T I](t *T) {
+	(*t).M(t)
+}
+
+func g() {
+	f(&a[int]{})
+}
-- 
GitLab


From ecd2e140ec54feca9afbda7726345e09cd380eea Mon Sep 17 00:00:00 2001
From: Michael Pratt 
Date: Fri, 12 Nov 2021 11:16:43 -0500
Subject: [PATCH 2145/2500] runtime: drop cgoTraceback call assumptions from
 CgoPprof tests

the CgoPprof tests currently assume that calls to their cgoTraceback
functions are primarily for generating pprof samples and exit early
after receiving two calls.

This is a fragile assumption, as cgoTraceback will be called for _any_
signal received, hence why the test already looks for 2 calls instead of
1.

Still, this has caused flaky failures in two cases:

* #37201, where async preemption signals add additional probability of
receiving non-profiling signals. This was resolved by disabling async
preemption.

* #49401, where some ITIMER_PROF SIGPROF signals are ignored in favor of
per-thread SIGPROF signals.

Rather than attempting to keep plugging holes, this CL drops the fragile
assumption from these tests. Now they simply unconditionally run for the
full 1s before exiting.

Fixes #49401

Change-Id: I16dc9d2f16c2fb511e9db93dd096a402121f86ac
Reviewed-on: https://go-review.googlesource.com/c/go/+/363634
Trust: Michael Pratt 
Run-TryBot: Michael Pratt 
TryBot-Result: Go Bot 
Reviewed-by: Bryan C. Mills 
Reviewed-by: Rhys Hiltner 
---
 src/runtime/crash_cgo_test.go                   |  5 -----
 src/runtime/testdata/testprogcgo/pprof.go       | 11 +----------
 src/runtime/testdata/testprogcgo/threadpprof.go | 14 +-------------
 3 files changed, 2 insertions(+), 28 deletions(-)

diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go
index 58c340f8ad..9a174fa549 100644
--- a/src/runtime/crash_cgo_test.go
+++ b/src/runtime/crash_cgo_test.go
@@ -302,12 +302,7 @@ func testCgoPprof(t *testing.T, buildArg, runArg, top, bottom string) {
 		t.Fatal(err)
 	}
 
-	// pprofCgoTraceback is called whenever CGO code is executing and a signal
-	// is received. Disable signal preemption to increase the likelihood at
-	// least one SIGPROF signal fired to capture a sample. See issue #37201.
 	cmd := testenv.CleanCmdEnv(exec.Command(exe, runArg))
-	cmd.Env = append(cmd.Env, "GODEBUG=asyncpreemptoff=1")
-
 	got, err := cmd.CombinedOutput()
 	if err != nil {
 		if testenv.Builder() == "linux-amd64-alpine" {
diff --git a/src/runtime/testdata/testprogcgo/pprof.go b/src/runtime/testdata/testprogcgo/pprof.go
index 3b73fa0bdd..8870d0c415 100644
--- a/src/runtime/testdata/testprogcgo/pprof.go
+++ b/src/runtime/testdata/testprogcgo/pprof.go
@@ -29,8 +29,6 @@ void cpuHog() {
 void cpuHog2() {
 }
 
-static int cpuHogCount;
-
 struct cgoTracebackArg {
 	uintptr_t  context;
 	uintptr_t  sigContext;
@@ -47,13 +45,6 @@ void pprofCgoTraceback(void* parg) {
 	arg->buf[0] = (uintptr_t)(cpuHog) + 0x10;
 	arg->buf[1] = (uintptr_t)(cpuHog2) + 0x4;
 	arg->buf[2] = 0;
-	++cpuHogCount;
-}
-
-// getCpuHogCount fetches the number of times we've seen cpuHog in the
-// traceback.
-int getCpuHogCount() {
-	return cpuHogCount;
 }
 */
 import "C"
@@ -86,7 +77,7 @@ func CgoPprof() {
 	}
 
 	t0 := time.Now()
-	for C.getCpuHogCount() < 2 && time.Since(t0) < time.Second {
+	for time.Since(t0) < time.Second {
 		C.cpuHog()
 	}
 
diff --git a/src/runtime/testdata/testprogcgo/threadpprof.go b/src/runtime/testdata/testprogcgo/threadpprof.go
index feb774ba59..4bc84d16d0 100644
--- a/src/runtime/testdata/testprogcgo/threadpprof.go
+++ b/src/runtime/testdata/testprogcgo/threadpprof.go
@@ -33,8 +33,6 @@ void cpuHogThread() {
 void cpuHogThread2() {
 }
 
-static int cpuHogThreadCount;
-
 struct cgoTracebackArg {
 	uintptr_t  context;
 	uintptr_t  sigContext;
@@ -49,13 +47,6 @@ void pprofCgoThreadTraceback(void* parg) {
 	arg->buf[0] = (uintptr_t)(cpuHogThread) + 0x10;
 	arg->buf[1] = (uintptr_t)(cpuHogThread2) + 0x4;
 	arg->buf[2] = 0;
-	__sync_add_and_fetch(&cpuHogThreadCount, 1);
-}
-
-// getCPUHogThreadCount fetches the number of times we've seen cpuHogThread
-// in the traceback.
-int getCPUHogThreadCount() {
-	return __sync_add_and_fetch(&cpuHogThreadCount, 0);
 }
 
 static void* cpuHogDriver(void* arg __attribute__ ((unused))) {
@@ -109,10 +100,7 @@ func pprofThread() {
 
 	C.runCPUHogThread()
 
-	t0 := time.Now()
-	for C.getCPUHogThreadCount() < 2 && time.Since(t0) < time.Second {
-		time.Sleep(100 * time.Millisecond)
-	}
+	time.Sleep(1*time.Second)
 
 	pprof.StopCPUProfile()
 
-- 
GitLab


From 95196512b6163dbeff2e7ce5cea65072305905f2 Mon Sep 17 00:00:00 2001
From: Michael Pratt 
Date: Wed, 10 Nov 2021 17:35:13 -0500
Subject: [PATCH 2146/2500] runtime/pprof: mark
 TestCPUProfileMultithreadMagnitude as flaky

The Linux kernel starting in 5.9 and fixed in 5.16 has a bug that can
break CPU timer signal delivery on new new threads if the timer
interrupt fires during handling of the clone system call.

Broken CPU timer signal deliver will skew CPU profile results and cause
this test to fail.

There is currently no known workaround, so mark the test as flaky on
builders with known broken kernels.

For #49065

Change-Id: I37ceb9ea244869b0aab5cd9a36b27ca2f7e5d315
Reviewed-on: https://go-review.googlesource.com/c/go/+/363214
Trust: Michael Pratt 
Run-TryBot: Michael Pratt 
TryBot-Result: Go Bot 
Reviewed-by: Bryan C. Mills 
Reviewed-by: Michael Knyszek 
---
 src/runtime/pprof/pprof_test.go       | 24 +++++++++++
 src/runtime/pprof/uname_linux_test.go | 61 +++++++++++++++++++++++++++
 src/runtime/pprof/uname_other_test.go | 15 +++++++
 3 files changed, 100 insertions(+)
 create mode 100644 src/runtime/pprof/uname_linux_test.go
 create mode 100644 src/runtime/pprof/uname_other_test.go

diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go
index 704c0c516d..d9be00d030 100644
--- a/src/runtime/pprof/pprof_test.go
+++ b/src/runtime/pprof/pprof_test.go
@@ -116,6 +116,30 @@ func TestCPUProfileMultithreadMagnitude(t *testing.T) {
 		t.Skip("issue 35057 is only confirmed on Linux")
 	}
 
+	// Linux [5.9,5.16) has a kernel bug that can break CPU timers on newly
+	// created threads, breaking our CPU accounting.
+	major, minor, patch, err := linuxKernelVersion()
+	if err != nil {
+		t.Errorf("Error determining kernel version: %v", err)
+	}
+	t.Logf("Running on Linux %d.%d.%d", major, minor, patch)
+	defer func() {
+		if t.Failed() {
+			t.Logf("Failure of this test may indicate that your system suffers from a known Linux kernel bug fixed on newer kernels. See https://golang.org/issue/49065.")
+		}
+	}()
+
+	// Disable on affected builders to avoid flakiness, but otherwise keep
+	// it enabled to potentially warn users that they are on a broken
+	// kernel.
+	if testenv.Builder() != "" && (runtime.GOARCH == "386" || runtime.GOARCH == "amd64") {
+		have59 := major > 5 || (major == 5 && minor >= 9)
+		have516 := major > 5 || (major == 5 && minor >= 16)
+		if have59 && !have516 {
+			testenv.SkipFlaky(t, 49065)
+		}
+	}
+
 	// Run a workload in a single goroutine, then run copies of the same
 	// workload in several goroutines. For both the serial and parallel cases,
 	// the CPU time the process measures with its own profiler should match the
diff --git a/src/runtime/pprof/uname_linux_test.go b/src/runtime/pprof/uname_linux_test.go
new file mode 100644
index 0000000000..8374c83f74
--- /dev/null
+++ b/src/runtime/pprof/uname_linux_test.go
@@ -0,0 +1,61 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build linux
+
+package pprof
+
+import (
+	"fmt"
+	"regexp"
+	"strconv"
+	"syscall"
+)
+
+var versionRe = regexp.MustCompile(`^(\d+)(?:\.(\d+)(?:\.(\d+))).*$`)
+
+func linuxKernelVersion() (major, minor, patch int, err error) {
+	var uname syscall.Utsname
+	if err := syscall.Uname(&uname); err != nil {
+		return 0, 0, 0, err
+	}
+
+	buf := make([]byte, 0, len(uname.Release))
+	for _, b := range uname.Release {
+		if b == 0 {
+			break
+		}
+		buf = append(buf, byte(b))
+	}
+	rl := string(buf)
+
+	m := versionRe.FindStringSubmatch(rl)
+	if m == nil {
+		return 0, 0, 0, fmt.Errorf("error matching version number in %q", rl)
+	}
+
+	v, err := strconv.ParseInt(m[1], 10, 64)
+	if err != nil {
+		return 0, 0, 0, fmt.Errorf("error parsing major version %q in %s: %w", m[1], rl, err)
+	}
+	major = int(v)
+
+	if len(m) >= 3 {
+		v, err := strconv.ParseInt(m[2], 10, 64)
+		if err != nil {
+			return 0, 0, 0, fmt.Errorf("error parsing minor version %q in %s: %w", m[2], rl, err)
+		}
+		minor = int(v)
+	}
+
+	if len(m) >= 4 {
+		v, err := strconv.ParseInt(m[3], 10, 64)
+		if err != nil {
+			return 0, 0, 0, fmt.Errorf("error parsing patch version %q in %s: %w", m[3], rl, err)
+		}
+		patch = int(v)
+	}
+
+	return
+}
diff --git a/src/runtime/pprof/uname_other_test.go b/src/runtime/pprof/uname_other_test.go
new file mode 100644
index 0000000000..327640755b
--- /dev/null
+++ b/src/runtime/pprof/uname_other_test.go
@@ -0,0 +1,15 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !linux
+
+package pprof
+
+import (
+	"errors"
+)
+
+func linuxKernelVersion() (major, minor, patch int, err error) {
+	return 0, 0, 0, errors.New("not running on linux")
+}
-- 
GitLab


From 76fbd6167364fb98e3ebe946cfc16b5b84d4240e Mon Sep 17 00:00:00 2001
From: Damien Neil 
Date: Mon, 8 Nov 2021 11:23:27 -0800
Subject: [PATCH 2147/2500] net/http: do not cancel request context on response
 body read

When sending a Request with a non-context deadline, we create a
context with a timeout. This context is canceled when closing the
response body, and also if a read from the response body returns
an error (including io.EOF).

Cancelling the context in Response.Body.Read interferes with the
HTTP/2 client cleaning up after a request is completed, and is
unnecessary: The user should always close the body, the impact
from not canceling the context is minor (the context timer leaks
until it fires).

Fixes #49366.

Change-Id: Ieaed866116916261d9079f71d8fea7a7b303b8fb
Reviewed-on: https://go-review.googlesource.com/c/go/+/361919
Trust: Damien Neil 
Run-TryBot: Damien Neil 
TryBot-Result: Go Bot 
Reviewed-by: Brad Fitzpatrick 
---
 src/net/http/client.go      |  1 -
 src/net/http/client_test.go | 27 +++++++++++++++++++++++++++
 2 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/src/net/http/client.go b/src/net/http/client.go
index 4d380c65db..22db96b267 100644
--- a/src/net/http/client.go
+++ b/src/net/http/client.go
@@ -965,7 +965,6 @@ func (b *cancelTimerBody) Read(p []byte) (n int, err error) {
 	if err == nil {
 		return n, nil
 	}
-	b.stop()
 	if err == io.EOF {
 		return n, err
 	}
diff --git a/src/net/http/client_test.go b/src/net/http/client_test.go
index fb6fbe7197..62bf9342f4 100644
--- a/src/net/http/client_test.go
+++ b/src/net/http/client_test.go
@@ -1368,6 +1368,33 @@ func TestClientTimeoutCancel(t *testing.T) {
 	}
 }
 
+func TestClientTimeoutDoesNotExpire_h1(t *testing.T) { testClientTimeoutDoesNotExpire(t, h1Mode) }
+func TestClientTimeoutDoesNotExpire_h2(t *testing.T) { testClientTimeoutDoesNotExpire(t, h2Mode) }
+
+// Issue 49366: if Client.Timeout is set but not hit, no error should be returned.
+func testClientTimeoutDoesNotExpire(t *testing.T, h2 bool) {
+	setParallel(t)
+	defer afterTest(t)
+
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Write([]byte("body"))
+	}))
+	defer cst.close()
+
+	cst.c.Timeout = 1 * time.Hour
+	req, _ := NewRequest("GET", cst.ts.URL, nil)
+	res, err := cst.c.Do(req)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if _, err = io.Copy(io.Discard, res.Body); err != nil {
+		t.Fatalf("io.Copy(io.Discard, res.Body) = %v, want nil", err)
+	}
+	if err = res.Body.Close(); err != nil {
+		t.Fatalf("res.Body.Close() = %v, want nil", err)
+	}
+}
+
 func TestClientRedirectEatsBody_h1(t *testing.T) { testClientRedirectEatsBody(t, h1Mode) }
 func TestClientRedirectEatsBody_h2(t *testing.T) { testClientRedirectEatsBody(t, h2Mode) }
 func testClientRedirectEatsBody(t *testing.T, h2 bool) {
-- 
GitLab


From 363459479014bde19e83d9fb6781310f63fb0b45 Mon Sep 17 00:00:00 2001
From: Michael Pratt 
Date: Wed, 10 Nov 2021 12:56:40 -0500
Subject: [PATCH 2148/2500] runtime: start ARM atomic kernel helper traceback
 in caller

Like the VDSO, we cannot directly traceback from the Linux kernel ARM
atomic/barrier helpers. However, unlike the VDSO, this functions are
extremely simple. Neither of the functions we use, kuser_cmpxchg and
kuser_memory_barrier, touch SP or LR.

We can use this to our advantage to read LR and simply start tracebacks
in the caller.

Fixes #49182

Change-Id: I890edbeb7c128938000fe7baf6f913c02a956edd
Reviewed-on: https://go-review.googlesource.com/c/go/+/362977
Trust: Michael Pratt 
Run-TryBot: Michael Pratt 
TryBot-Result: Go Bot 
Reviewed-by: Cherry Mui 
---
 src/runtime/traceback.go | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go
index 36627a6735..73bd0e11a9 100644
--- a/src/runtime/traceback.go
+++ b/src/runtime/traceback.go
@@ -96,6 +96,20 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
 		}
 	}
 
+	// runtime/internal/atomic functions call into kernel helpers on
+	// arm < 7. See runtime/internal/atomic/sys_linux_arm.s.
+	//
+	// Start in the caller's frame.
+	if GOARCH == "arm" && goarm < 7 && GOOS == "linux" && frame.pc&0xffff0000 == 0xffff0000 {
+		// Note that the calls are simple BL without pushing the return
+		// address, so we use LR directly.
+		//
+		// The kernel helpers are frameless leaf functions, so SP and
+		// LR are not touched.
+		frame.pc = frame.lr
+		frame.lr = 0
+	}
+
 	f := findfunc(frame.pc)
 	if !f.valid() {
 		if callback != nil || printing {
-- 
GitLab


From 9150c16bced33ca591a55fe4fb64817dd659b285 Mon Sep 17 00:00:00 2001
From: Robert Griesemer 
Date: Thu, 11 Nov 2021 16:02:35 -0800
Subject: [PATCH 2149/2500] cmd/compile/internal/types2: remove asTypeParam and
 simplify some code

Because we do not permit a stand-alone type parameter on the RHS of
a type declaration, the underlying type of a (Named) type cannot be
a type parameter. This allows us to simplify some code.

Specifically, when parsing union elements, we don't need to delay
a check for later, which allows further simplifications when computing
type sets.

Change-Id: I4047c609f87ebb194ea8c1bad630a70d255b20cf
Reviewed-on: https://go-review.googlesource.com/c/go/+/363438
Trust: Robert Griesemer 
Run-TryBot: Robert Griesemer 
TryBot-Result: Go Bot 
Reviewed-by: Robert Findley 
---
 src/cmd/compile/internal/importer/iimport.go    |  3 +--
 src/cmd/compile/internal/types2/builtins.go     |  6 +++---
 src/cmd/compile/internal/types2/call.go         |  2 +-
 .../compile/internal/types2/compilersupport.go  |  6 ------
 src/cmd/compile/internal/types2/conversions.go  |  6 +++---
 src/cmd/compile/internal/types2/decl.go         | 11 ++++++-----
 src/cmd/compile/internal/types2/expr.go         |  5 ++---
 src/cmd/compile/internal/types2/instantiate.go  |  8 ++++----
 src/cmd/compile/internal/types2/lookup.go       |  6 +-----
 src/cmd/compile/internal/types2/operand.go      |  6 +++---
 src/cmd/compile/internal/types2/predicates.go   |  2 +-
 src/cmd/compile/internal/types2/type.go         |  6 ------
 src/cmd/compile/internal/types2/typeset.go      |  8 --------
 src/cmd/compile/internal/types2/typexpr.go      |  2 +-
 src/cmd/compile/internal/types2/union.go        | 17 ++++++++---------
 15 files changed, 34 insertions(+), 60 deletions(-)

diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go
index d04ef5c34d..1aa3b7b6a8 100644
--- a/src/cmd/compile/internal/importer/iimport.go
+++ b/src/cmd/compile/internal/importer/iimport.go
@@ -706,8 +706,7 @@ func (r *importReader) tparamList() []*types2.TypeParam {
 	}
 	xs := make([]*types2.TypeParam, n)
 	for i := range xs {
-		typ := r.typ()
-		xs[i] = types2.AsTypeParam(typ)
+		xs[i] = r.typ().(*types2.TypeParam)
 	}
 	return xs
 }
diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go
index 2bc084038f..99fe440340 100644
--- a/src/cmd/compile/internal/types2/builtins.go
+++ b/src/cmd/compile/internal/types2/builtins.go
@@ -293,7 +293,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
 		// the argument types must be of floating-point type
 		// (applyTypeFunc never calls f with a type parameter)
 		f := func(typ Type) Type {
-			assert(asTypeParam(typ) == nil)
+			assert(!isTypeParam(typ))
 			if t, _ := under(typ).(*Basic); t != nil {
 				switch t.kind {
 				case Float32:
@@ -436,7 +436,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
 		// the argument must be of complex type
 		// (applyTypeFunc never calls f with a type parameter)
 		f := func(typ Type) Type {
-			assert(asTypeParam(typ) == nil)
+			assert(!isTypeParam(typ))
 			if t, _ := under(typ).(*Basic); t != nil {
 				switch t.kind {
 				case Complex64:
@@ -813,7 +813,7 @@ func hasVarSize(t Type) bool {
 // applyTypeFunc returns nil.
 // If x is not a type parameter, the result is f(x).
 func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type {
-	if tp := asTypeParam(x); tp != nil {
+	if tp, _ := x.(*TypeParam); tp != nil {
 		// Test if t satisfies the requirements for the argument
 		// type and collect possible result types at the same time.
 		var terms []*Term
diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go
index 0540feaa78..b778d54b32 100644
--- a/src/cmd/compile/internal/types2/call.go
+++ b/src/cmd/compile/internal/types2/call.go
@@ -528,7 +528,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) {
 			check.errorf(e.Sel, "cannot call pointer method %s on %s", sel, x.typ)
 		default:
 			var why string
-			if tpar := asTypeParam(x.typ); tpar != nil {
+			if tpar, _ := x.typ.(*TypeParam); tpar != nil {
 				// Type parameter bounds don't specify fields, so don't mention "field".
 				if tname := tpar.iface().obj; tname != nil {
 					why = check.sprintf("interface %s has no method %s", tname.name, sel)
diff --git a/src/cmd/compile/internal/types2/compilersupport.go b/src/cmd/compile/internal/types2/compilersupport.go
index 31112d4e41..b35e752b8f 100644
--- a/src/cmd/compile/internal/types2/compilersupport.go
+++ b/src/cmd/compile/internal/types2/compilersupport.go
@@ -19,12 +19,6 @@ func AsSignature(t Type) *Signature {
 	return u
 }
 
-// If t is a type parameter, AsTypeParam returns that type, otherwise it returns nil.
-func AsTypeParam(t Type) *TypeParam {
-	u, _ := t.Underlying().(*TypeParam)
-	return u
-}
-
 // If typ is a type parameter, structuralType returns the single underlying
 // type of all types in the corresponding type constraint if it exists, or
 // nil otherwise. If the type set contains only unrestricted and restricted
diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go
index 7f93e2467f..968ac4d39f 100644
--- a/src/cmd/compile/internal/types2/conversions.go
+++ b/src/cmd/compile/internal/types2/conversions.go
@@ -48,7 +48,7 @@ func (check *Checker) conversion(x *operand, T Type) {
 		// If T's type set is empty, or if it doesn't
 		// have specific types, constant x cannot be
 		// converted.
-		ok = under(T).(*TypeParam).underIs(func(u Type) bool {
+		ok = T.(*TypeParam).underIs(func(u Type) bool {
 			// t is nil if there are no specific type terms
 			if u == nil {
 				cause = check.sprintf("%s does not contain specific types", T)
@@ -194,8 +194,8 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool {
 	}
 
 	// optimization: if we don't have type parameters, we're done
-	Vp, _ := Vu.(*TypeParam)
-	Tp, _ := Tu.(*TypeParam)
+	Vp, _ := V.(*TypeParam)
+	Tp, _ := T.(*TypeParam)
 	if Vp == nil && Tp == nil {
 		return false
 	}
diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go
index 9b643fac99..bab90fbd9a 100644
--- a/src/cmd/compile/internal/types2/decl.go
+++ b/src/cmd/compile/internal/types2/decl.go
@@ -616,10 +616,11 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named
 	}
 
 	// Disallow a lone type parameter as the RHS of a type declaration (issue #45639).
-	// We can look directly at named.underlying because even if it is still a *Named
-	// type (underlying not fully resolved yet) it cannot become a type parameter due
-	// to this very restriction.
-	if tpar, _ := named.underlying.(*TypeParam); tpar != nil {
+	// We don't need this restriction anymore if we make the underlying type of a type
+	// parameter its constraint interface: if the RHS is a lone type parameter, we will
+	// use its underlying type (like we do for any RHS in a type declaration), and its
+	// underlying type is an interface and the type declaration is well defined.
+	if isTypeParam(rhs) {
 		check.error(tdecl.Type, "cannot use a type parameter as RHS in type declaration")
 		named.underlying = Typ[Invalid]
 	}
@@ -671,7 +672,7 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list []*syntax.Fiel
 
 	check.later(func() {
 		for i, bound := range bounds {
-			if _, ok := under(bound).(*TypeParam); ok {
+			if isTypeParam(bound) {
 				check.error(posers[i], "cannot use a type parameter as constraint")
 			}
 		}
diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go
index 0b3fe23e80..17096ee418 100644
--- a/src/cmd/compile/internal/types2/expr.go
+++ b/src/cmd/compile/internal/types2/expr.go
@@ -160,11 +160,10 @@ var op2str2 = [...]string{
 // If typ is a type parameter, underIs returns the result of typ.underIs(f).
 // Otherwise, underIs returns the result of f(under(typ)).
 func underIs(typ Type, f func(Type) bool) bool {
-	u := under(typ)
-	if tpar, _ := u.(*TypeParam); tpar != nil {
+	if tpar, _ := typ.(*TypeParam); tpar != nil {
 		return tpar.underIs(f)
 	}
-	return f(u)
+	return f(under(typ))
 }
 
 func (check *Checker) unary(x *operand, e *syntax.Operation) {
diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go
index f814619bb0..582d1e4763 100644
--- a/src/cmd/compile/internal/types2/instantiate.go
+++ b/src/cmd/compile/internal/types2/instantiate.go
@@ -143,7 +143,7 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap
 
 	// A type argument that is a type parameter with an empty type set satisfies any constraint.
 	// (The empty set is a subset of any set.)
-	if targ := asTypeParam(targ); targ != nil && targ.iface().typeSet().IsEmpty() {
+	if targ, _ := targ.(*TypeParam); targ != nil && targ.iface().typeSet().IsEmpty() {
 		return nil
 	}
 
@@ -172,7 +172,7 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap
 	// if iface is comparable, targ must be comparable
 	// TODO(gri) the error messages needs to be better, here
 	if iface.IsComparable() && !Comparable(targ) {
-		if tpar := asTypeParam(targ); tpar != nil && tpar.iface().typeSet().IsAll() {
+		if tpar, _ := targ.(*TypeParam); tpar != nil && tpar.iface().typeSet().IsAll() {
 			return errorf("%s has no constraints", targ)
 		}
 		return errorf("%s does not satisfy comparable", targ)
@@ -184,7 +184,7 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap
 		// If the type argument is a pointer to a type parameter, the type argument's
 		// method set is empty.
 		// TODO(gri) is this what we want? (spec question)
-		if base, isPtr := deref(targ); isPtr && asTypeParam(base) != nil {
+		if base, isPtr := deref(targ); isPtr && isTypeParam(base) {
 			return errorf("%s has no methods", targ)
 		}
 		if m, wrong := check.missingMethod(targ, iface, true); m != nil {
@@ -212,7 +212,7 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap
 	// If targ is itself a type parameter, each of its possible types must be in the set
 	// of iface types (i.e., the targ type set must be a subset of the iface type set).
 	// Type arguments with empty type sets were already excluded above.
-	if targ := asTypeParam(targ); targ != nil {
+	if targ, _ := targ.(*TypeParam); targ != nil {
 		targBound := targ.iface()
 		if !targBound.typeSet().subsetOf(iface.typeSet()) {
 			// TODO(gri) report which type is missing
diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go
index 0612400590..5da51a23ab 100644
--- a/src/cmd/compile/internal/types2/lookup.go
+++ b/src/cmd/compile/internal/types2/lookup.go
@@ -134,12 +134,8 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
 					continue // we can't have a matching field or interface method
 				}
 
-				// continue with underlying type, but only if it's not a type parameter
-				// TODO(gri) is this what we want to do for type parameters? (spec question)
+				// continue with underlying type
 				typ = named.under()
-				if asTypeParam(typ) != nil {
-					continue
-				}
 			}
 
 			tpar = nil
diff --git a/src/cmd/compile/internal/types2/operand.go b/src/cmd/compile/internal/types2/operand.go
index 2f85802701..762a7543a9 100644
--- a/src/cmd/compile/internal/types2/operand.go
+++ b/src/cmd/compile/internal/types2/operand.go
@@ -183,7 +183,7 @@ func operandString(x *operand, qf Qualifier) string {
 			}
 			buf.WriteString(intro)
 			WriteType(&buf, x.typ, qf)
-			if tpar := asTypeParam(x.typ); tpar != nil {
+			if tpar, _ := x.typ.(*TypeParam); tpar != nil {
 				buf.WriteString(" constrained by ")
 				WriteType(&buf, tpar.bound, qf) // do not compute interface type sets here
 			}
@@ -256,8 +256,8 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er
 
 	Vu := under(V)
 	Tu := under(T)
-	Vp, _ := Vu.(*TypeParam)
-	Tp, _ := Tu.(*TypeParam)
+	Vp, _ := V.(*TypeParam)
+	Tp, _ := T.(*TypeParam)
 
 	// x is an untyped value representable by a value of type T.
 	if isUntyped(Vu) {
diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go
index f1fd33c5de..5cb1c33814 100644
--- a/src/cmd/compile/internal/types2/predicates.go
+++ b/src/cmd/compile/internal/types2/predicates.go
@@ -90,7 +90,7 @@ func IsInterface(t Type) bool {
 
 // isTypeParam reports whether t is a type parameter.
 func isTypeParam(t Type) bool {
-	_, ok := under(t).(*TypeParam)
+	_, ok := t.(*TypeParam)
 	return ok
 }
 
diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go
index c8c0f36e5c..24d44442e9 100644
--- a/src/cmd/compile/internal/types2/type.go
+++ b/src/cmd/compile/internal/types2/type.go
@@ -88,9 +88,3 @@ func asNamed(t Type) *Named {
 	}
 	return e
 }
-
-// If t is a type parameter, asTypeParam returns that type, otherwise it returns nil.
-func asTypeParam(t Type) *TypeParam {
-	u, _ := under(t).(*TypeParam)
-	return u
-}
diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go
index c37a20e73e..882f387c3c 100644
--- a/src/cmd/compile/internal/types2/typeset.go
+++ b/src/cmd/compile/internal/types2/typeset.go
@@ -291,10 +291,6 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_
 				continue // ignore invalid unions
 			}
 			terms = tset.terms
-		case *TypeParam:
-			// Embedding stand-alone type parameters is not permitted.
-			// Union parsing reports a (delayed) error, so we can ignore this entry.
-			continue
 		default:
 			if u == Typ[Invalid] {
 				continue
@@ -372,10 +368,6 @@ func computeUnionTypeSet(check *Checker, pos syntax.Pos, utyp *Union) *_TypeSet
 		switch u := under(t.typ).(type) {
 		case *Interface:
 			terms = computeInterfaceTypeSet(check, pos, u).terms
-		case *TypeParam:
-			// A stand-alone type parameters is not permitted as union term.
-			// Union parsing reports a (delayed) error, so we can ignore this entry.
-			continue
 		default:
 			if t.typ == Typ[Invalid] {
 				continue
diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go
index 82c029cfd6..a2585179ee 100644
--- a/src/cmd/compile/internal/types2/typexpr.go
+++ b/src/cmd/compile/internal/types2/typexpr.go
@@ -356,7 +356,7 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) {
 		check.later(func() {
 			if !Comparable(typ.key) {
 				var why string
-				if asTypeParam(typ.key) != nil {
+				if isTypeParam(typ.key) {
 					why = " (missing comparable constraint)"
 				}
 				check.errorf(e.Key, "invalid map key type %s%s", typ.key, why)
diff --git a/src/cmd/compile/internal/types2/union.go b/src/cmd/compile/internal/types2/union.go
index 5379bde02c..2304b30280 100644
--- a/src/cmd/compile/internal/types2/union.go
+++ b/src/cmd/compile/internal/types2/union.go
@@ -115,15 +115,14 @@ func parseTilde(check *Checker, x syntax.Expr) (tilde bool, typ Type) {
 	}
 	typ = check.typ(x)
 	// Embedding stand-alone type parameters is not permitted (issue #47127).
-	// Do this check later because it requires computation of the underlying type (see also issue #46461).
-	// Note: If an underlying type cannot be a type parameter, the call to
-	//       under() will not be needed and then we don't need to delay this
-	//       check to later and could return Typ[Invalid] instead.
-	check.later(func() {
-		if _, ok := under(typ).(*TypeParam); ok {
-			check.error(x, "cannot embed a type parameter")
-		}
-	})
+	// We don't need this restriction anymore if we make the underlying type of a type
+	// parameter its constraint interface: if we embed a lone type parameter, we will
+	// simply use its underlying type (like we do for other named, embedded interfaces),
+	// and since the underlying type is an interface the embedding is well defined.
+	if isTypeParam(typ) {
+		check.error(x, "cannot embed a type parameter")
+		typ = Typ[Invalid]
+	}
 	return
 }
 
-- 
GitLab


From f9dcda3fd83e83fb29cc6b0f710faa49ba98a54b Mon Sep 17 00:00:00 2001
From: Robert Griesemer 
Date: Thu, 11 Nov 2021 16:32:16 -0800
Subject: [PATCH 2150/2500] cmd/compile/internal/types2: better error for type
 assertion/switch on type parameter value

Change-Id: I98751d0b2d8aefcf537b6d5200d0b52ffacf1105
Reviewed-on: https://go-review.googlesource.com/c/go/+/363439
Trust: Robert Griesemer 
Run-TryBot: Robert Griesemer 
Reviewed-by: Robert Findley 
---
 src/cmd/compile/internal/types2/expr.go               |  7 ++++++-
 src/cmd/compile/internal/types2/stmt.go               | 11 ++++++-----
 .../internal/types2/testdata/check/typeparams.go2     |  8 ++++----
 test/interface/explicit.go                            |  2 +-
 test/typeswitch3.go                                   |  4 ++--
 5 files changed, 19 insertions(+), 13 deletions(-)

diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go
index 17096ee418..25e2060100 100644
--- a/src/cmd/compile/internal/types2/expr.go
+++ b/src/cmd/compile/internal/types2/expr.go
@@ -1459,9 +1459,14 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
 		if x.mode == invalid {
 			goto Error
 		}
+		// TODO(gri) we may want to permit type assertions on type parameter values at some point
+		if isTypeParam(x.typ) {
+			check.errorf(x, invalidOp+"cannot use type assertion on type parameter value %s", x)
+			goto Error
+		}
 		xtyp, _ := under(x.typ).(*Interface)
 		if xtyp == nil {
-			check.errorf(x, "%s is not an interface type", x)
+			check.errorf(x, invalidOp+"%s is not an interface", x)
 			goto Error
 		}
 		// x.(type) expressions are encoded via TypeSwitchGuards
diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go
index f9c07e38cd..6869c87929 100644
--- a/src/cmd/compile/internal/types2/stmt.go
+++ b/src/cmd/compile/internal/types2/stmt.go
@@ -733,13 +733,14 @@ func (check *Checker) typeSwitchStmt(inner stmtContext, s *syntax.SwitchStmt, gu
 	if x.mode == invalid {
 		return
 	}
-	// Caution: We're not using asInterface here because we don't want
-	//          to switch on a suitably constrained type parameter (for
-	//          now).
-	// TODO(gri) Need to revisit this.
+	// TODO(gri) we may want to permit type switches on type parameter values at some point
+	if isTypeParam(x.typ) {
+		check.errorf(&x, "cannot use type switch on type parameter value %s", &x)
+		return
+	}
 	xtyp, _ := under(x.typ).(*Interface)
 	if xtyp == nil {
-		check.errorf(&x, "%s is not an interface type", &x)
+		check.errorf(&x, "%s is not an interface", &x)
 		return
 	}
 
diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2
index b1d02efdb5..03c3f9a0b5 100644
--- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2
+++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2
@@ -482,8 +482,8 @@ func (_ R2[X, Y]) m2(X) Y
 // type assertions and type switches over generic types lead to errors for now
 
 func _[T any](x T) {
-	_ = x /* ERROR not an interface */ .(int)
-	switch x /* ERROR not an interface */ .(type) {
+	_ = x /* ERROR cannot use type assertion */ .(int)
+	switch x /* ERROR cannot use type switch */ .(type) {
 	}
 
 	// work-around
@@ -494,8 +494,8 @@ func _[T any](x T) {
 }
 
 func _[T interface{~int}](x T) {
-	_ = x /* ERROR not an interface */ .(int)
-	switch x /* ERROR not an interface */ .(type) {
+	_ = x /* ERROR cannot use type assertion */ .(int)
+	switch x /* ERROR cannot use type switch */ .(type) {
 	}
 
 	// work-around
diff --git a/test/interface/explicit.go b/test/interface/explicit.go
index 1b7af6712b..f769f5878c 100644
--- a/test/interface/explicit.go
+++ b/test/interface/explicit.go
@@ -57,7 +57,7 @@ func main() {
 
 	// cannot type-assert non-interfaces
 	f := 2.0
-	_ = f.(int) // ERROR "non-interface type|only valid for interface types|not an interface type"
+	_ = f.(int) // ERROR "non-interface type|only valid for interface types|not an interface"
 
 }
 
diff --git a/test/typeswitch3.go b/test/typeswitch3.go
index a57889bc1d..2e144d81c0 100644
--- a/test/typeswitch3.go
+++ b/test/typeswitch3.go
@@ -42,7 +42,7 @@ func main() {
 
 func noninterface() {
 	var i int
-	switch i.(type) { // ERROR "cannot type switch on non-interface value|not an interface type"
+	switch i.(type) { // ERROR "cannot type switch on non-interface value|not an interface"
 	case string:
 	case int:
 	}
@@ -51,6 +51,6 @@ func noninterface() {
 		name string
 	}
 	var s S
-	switch s.(type) { // ERROR "cannot type switch on non-interface value|not an interface type"
+	switch s.(type) { // ERROR "cannot type switch on non-interface value|not an interface"
 	}
 }
-- 
GitLab


From 1cd600301ea2a0b13d5e158282200114dc9de3fd Mon Sep 17 00:00:00 2001
From: Michael Matloob 
Date: Thu, 28 Oct 2021 14:54:30 -0400
Subject: [PATCH 2151/2500] cmd/go: use workspace modules' go.sum files to
 check sums

By default, use workspace modules' go.sum files to check sums. Any
missing sums will still be written to go.work.sum

For #45713

Change-Id: I0f537602523dfec44d423c3c80c7ef396e1397b1
Reviewed-on: https://go-review.googlesource.com/c/go/+/359478
Trust: Michael Matloob 
Run-TryBot: Michael Matloob 
TryBot-Result: Go Bot 
Reviewed-by: Bryan C. Mills 
---
 src/cmd/go/internal/modfetch/fetch.go         | 79 ++++++++++++++++---
 src/cmd/go/internal/modload/init.go           |  6 +-
 src/cmd/go/testdata/script/work_sum.txt       |  5 +-
 .../go/testdata/script/work_sum_mismatch.txt  | 61 ++++++++++++++
 4 files changed, 134 insertions(+), 17 deletions(-)
 create mode 100644 src/cmd/go/testdata/script/work_sum_mismatch.txt

diff --git a/src/cmd/go/internal/modfetch/fetch.go b/src/cmd/go/internal/modfetch/fetch.go
index 408b2860ad..e246c1a04d 100644
--- a/src/cmd/go/internal/modfetch/fetch.go
+++ b/src/cmd/go/internal/modfetch/fetch.go
@@ -384,7 +384,8 @@ func RemoveAll(dir string) error {
 	return robustio.RemoveAll(dir)
 }
 
-var GoSumFile string // path to go.sum; set by package modload
+var GoSumFile string             // path to go.sum; set by package modload
+var WorkspaceGoSumFiles []string // path to module go.sums in workspace; set by package modload
 
 type modSum struct {
 	mod module.Version
@@ -393,10 +394,11 @@ type modSum struct {
 
 var goSum struct {
 	mu        sync.Mutex
-	m         map[module.Version][]string // content of go.sum file
-	status    map[modSum]modSumStatus     // state of sums in m
-	overwrite bool                        // if true, overwrite go.sum without incorporating its contents
-	enabled   bool                        // whether to use go.sum at all
+	m         map[module.Version][]string            // content of go.sum file
+	w         map[string]map[module.Version][]string // sum file in workspace -> content of that sum file
+	status    map[modSum]modSumStatus                // state of sums in m
+	overwrite bool                                   // if true, overwrite go.sum without incorporating its contents
+	enabled   bool                                   // whether to use go.sum at all
 }
 
 type modSumStatus struct {
@@ -417,23 +419,38 @@ func initGoSum() (bool, error) {
 
 	goSum.m = make(map[module.Version][]string)
 	goSum.status = make(map[modSum]modSumStatus)
+	goSum.w = make(map[string]map[module.Version][]string)
+
+	for _, f := range WorkspaceGoSumFiles {
+		goSum.w[f] = make(map[module.Version][]string)
+		_, err := readGoSumFile(goSum.w[f], f)
+		if err != nil {
+			return false, err
+		}
+	}
+
+	enabled, err := readGoSumFile(goSum.m, GoSumFile)
+	goSum.enabled = enabled
+	return enabled, err
+}
+
+func readGoSumFile(dst map[module.Version][]string, file string) (bool, error) {
 	var (
 		data []byte
 		err  error
 	)
-	if actualSumFile, ok := fsys.OverlayPath(GoSumFile); ok {
+	if actualSumFile, ok := fsys.OverlayPath(file); ok {
 		// Don't lock go.sum if it's part of the overlay.
 		// On Plan 9, locking requires chmod, and we don't want to modify any file
 		// in the overlay. See #44700.
 		data, err = os.ReadFile(actualSumFile)
 	} else {
-		data, err = lockedfile.Read(GoSumFile)
+		data, err = lockedfile.Read(file)
 	}
 	if err != nil && !os.IsNotExist(err) {
 		return false, err
 	}
-	goSum.enabled = true
-	readGoSum(goSum.m, GoSumFile, data)
+	readGoSum(dst, file, data)
 
 	return true, nil
 }
@@ -485,6 +502,16 @@ func HaveSum(mod module.Version) bool {
 	if err != nil || !inited {
 		return false
 	}
+	for _, goSums := range goSum.w {
+		for _, h := range goSums[mod] {
+			if !strings.HasPrefix(h, "h1:") {
+				continue
+			}
+			if !goSum.status[modSum{mod, h}].dirty {
+				return true
+			}
+		}
+	}
 	for _, h := range goSum.m[mod] {
 		if !strings.HasPrefix(h, "h1:") {
 			continue
@@ -602,15 +629,32 @@ func checkModSum(mod module.Version, h string) error {
 // If it finds a conflicting pair instead, it calls base.Fatalf.
 // goSum.mu must be locked.
 func haveModSumLocked(mod module.Version, h string) bool {
+	sumFileName := "go.sum"
+	if strings.HasSuffix(GoSumFile, "go.work.sum") {
+		sumFileName = "go.work.sum"
+	}
 	for _, vh := range goSum.m[mod] {
 		if h == vh {
 			return true
 		}
 		if strings.HasPrefix(vh, "h1:") {
-			base.Fatalf("verifying %s@%s: checksum mismatch\n\tdownloaded: %v\n\tgo.sum:     %v"+goSumMismatch, mod.Path, mod.Version, h, vh)
+			base.Fatalf("verifying %s@%s: checksum mismatch\n\tdownloaded: %v\n\t%s:     %v"+goSumMismatch, mod.Path, mod.Version, h, sumFileName, vh)
+		}
+	}
+	// Also check workspace sums.
+	foundMatch := false
+	// Check sums from all files in case there are conflicts between
+	// the files.
+	for goSumFile, goSums := range goSum.w {
+		for _, vh := range goSums[mod] {
+			if h == vh {
+				foundMatch = true
+			} else if strings.HasPrefix(vh, "h1:") {
+				base.Fatalf("verifying %s@%s: checksum mismatch\n\tdownloaded: %v\n\t%s:     %v"+goSumMismatch, mod.Path, mod.Version, h, goSumFile, vh)
+			}
 		}
 	}
-	return false
+	return foundMatch
 }
 
 // addModSumLocked adds the pair mod,h to go.sum.
@@ -749,7 +793,7 @@ Outer:
 			goSum.m = make(map[module.Version][]string, len(goSum.m))
 			readGoSum(goSum.m, GoSumFile, data)
 			for ms, st := range goSum.status {
-				if st.used {
+				if st.used && !sumInWorkspaceModulesLocked(ms.mod) {
 					addModSumLocked(ms.mod, ms.sum)
 				}
 			}
@@ -767,7 +811,7 @@ Outer:
 			sort.Strings(list)
 			for _, h := range list {
 				st := goSum.status[modSum{m, h}]
-				if !st.dirty || (st.used && keep[m]) {
+				if (!st.dirty || (st.used && keep[m])) && !sumInWorkspaceModulesLocked(m) {
 					fmt.Fprintf(&buf, "%s %s %s\n", m.Path, m.Version, h)
 				}
 			}
@@ -784,6 +828,15 @@ Outer:
 	return nil
 }
 
+func sumInWorkspaceModulesLocked(m module.Version) bool {
+	for _, goSums := range goSum.w {
+		if _, ok := goSums[m]; ok {
+			return true
+		}
+	}
+	return false
+}
+
 // TrimGoSum trims go.sum to contain only the modules needed for reproducible
 // builds.
 //
diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go
index a6e49c6c71..fcf6ce2620 100644
--- a/src/cmd/go/internal/modload/init.go
+++ b/src/cmd/go/internal/modload/init.go
@@ -624,8 +624,10 @@ func LoadModFile(ctx context.Context) *Requirements {
 		if err != nil {
 			base.Fatalf("reading go.work: %v", err)
 		}
-		_ = TODOWorkspaces("Support falling back to individual module go.sum " +
-			"files for sums not in the workspace sum file.")
+		for _, modRoot := range modRoots {
+			sumFile := strings.TrimSuffix(modFilePath(modRoot), ".mod") + ".sum"
+			modfetch.WorkspaceGoSumFiles = append(modfetch.WorkspaceGoSumFiles, sumFile)
+		}
 		modfetch.GoSumFile = workFilePath + ".sum"
 	} else if modRoots == nil {
 		// We're in module mode, but not inside a module.
diff --git a/src/cmd/go/testdata/script/work_sum.txt b/src/cmd/go/testdata/script/work_sum.txt
index 99f66a4003..20261e7cbd 100644
--- a/src/cmd/go/testdata/script/work_sum.txt
+++ b/src/cmd/go/testdata/script/work_sum.txt
@@ -8,8 +8,6 @@ golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekuf
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0=
 rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
-rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
-rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
 -- go.work --
 go 1.18
 
@@ -20,6 +18,9 @@ go 1.18
 module example.com/hi
 
 require "rsc.io/quote" v1.5.2
+-- go.sum --
+rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
 -- main.go --
 package main
 
diff --git a/src/cmd/go/testdata/script/work_sum_mismatch.txt b/src/cmd/go/testdata/script/work_sum_mismatch.txt
new file mode 100644
index 0000000000..42994ea5d5
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_sum_mismatch.txt
@@ -0,0 +1,61 @@
+# Test mismatched sums in go.sum files
+
+! go run ./a
+cmpenv stderr want-error
+
+-- want-error --
+verifying rsc.io/sampler@v1.3.0/go.mod: checksum mismatch
+	downloaded: h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+	$WORK${/}gopath${/}src${/}a${/}go.sum:     h1:U1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+
+SECURITY ERROR
+This download does NOT match an earlier download recorded in go.sum.
+The bits may have been replaced on the origin server, or an attacker may
+have intercepted the download attempt.
+
+For more information, see 'go help module-auth'.
+-- go.work --
+go 1.18
+
+directory ./a
+directory ./b
+-- a/go.mod --
+go 1.18
+
+module example.com/hi
+
+require "rsc.io/quote" v1.5.2
+-- a/go.sum --
+rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
+rsc.io/sampler v1.3.0/go.mod h1:U1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+-- a/main.go --
+package main
+
+import (
+	"fmt"
+	"rsc.io/quote"
+)
+
+func main() {
+	fmt.Println(quote.Hello())
+}
+-- b/go.mod --
+go 1.18
+
+module example.com/hi
+
+require "rsc.io/quote" v1.5.2
+-- b/go.sum --
+rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+-- b/main.go --
+package main
+
+import (
+	"fmt"
+	"rsc.io/quote"
+)
+
+func main() {
+	fmt.Println(quote.Hello())
+}
\ No newline at end of file
-- 
GitLab


From c8d6ee12d5eb1c64f2aff8a4d511f677a64e3aed Mon Sep 17 00:00:00 2001
From: Dan Scales 
Date: Wed, 10 Nov 2021 08:41:21 -0800
Subject: [PATCH 2152/2500] cmd/compile: match Go 1.17 compiler error messages
 more closely

When being used by the compiler, fix up types2 error messages to be more
like Go 1.17 compiler errors. In particular:

  - add information about which method is missing when a type is not
    assignable/convertible/etc. to an interface.

  - add information about any existing method which has the same name,
    but wrong type.

  - add extra hint in the case that the source or destination type is a
    pointer to an interface, rather than an interface.

  - add extra hint "need type assertion" in the case that the source is
    an interface that is implemented by the destination.

  - the following change in the CL stack also adds information about any
    existing method with a different name that only differs in case.

Include much of the new logic in a new common function
(*Checker).missingMethodReason().

types2 still adds a little more information in some cases then the Go
1.17 compiler. For example, it typically says "(value of type T)",
rather than "(type T)", where "value" could also be "constant",
"variable", etc.

I kept the types2 error messages almost all the same when types2 is not
used by the compiler. The only change (to reduce amount of compatibility
code) was to change "M method" phrasing in one case to "method M"
phrasing in one error message (which is the phrasing it uses in all
other cases). That is the reason that there are a few small changes in
types2/testdata/check/*.src.

Added new test test/fixedbugs/issue48471.go to test that the added
information is appearing correctly.

Also adjusted the pattern matching in a bunch of other
test/fixedbugs/*.go, now that types2 is producing error messages closer
to Go 1.17. Was able to remove a couple test files from the types2
exception list in run.go.

Updated #48471

Change-Id: I8af1eae6eb8a5541d8ea20b66f494e2e795e1956
Reviewed-on: https://go-review.googlesource.com/c/go/+/363436
Trust: Dan Scales 
Run-TryBot: Dan Scales 
TryBot-Result: Go Bot 
Reviewed-by: Robert Griesemer 
---
 .../compile/internal/types2/assignments.go    |  6 +-
 .../compile/internal/types2/conversions.go    | 16 ++++-
 src/cmd/compile/internal/types2/expr.go       | 21 +++----
 src/cmd/compile/internal/types2/lookup.go     | 58 +++++++++++++++++++
 src/cmd/compile/internal/types2/operand.go    | 39 ++++++++++---
 .../internal/types2/testdata/check/expr3.src  |  4 +-
 .../internal/types2/testdata/check/issues.src |  2 +-
 .../internal/types2/testdata/check/stmt0.src  |  2 +-
 .../types2/testdata/fixedbugs/issue49005.go   |  4 +-
 test/alias2.go                                | 10 ++--
 test/append1.go                               |  2 +-
 test/ddd1.go                                  |  2 +-
 test/fixedbugs/bug389.go                      |  2 +-
 test/fixedbugs/issue41247.go                  |  2 +-
 test/fixedbugs/issue48471.go                  | 41 +++++++++++++
 test/fixedbugs/issue6572.go                   |  2 +-
 test/fixedbugs/issue9521.go                   |  4 +-
 test/interface/explicit.go                    |  2 +-
 test/run.go                                   |  3 -
 19 files changed, 174 insertions(+), 48 deletions(-)
 create mode 100644 test/fixedbugs/issue48471.go

diff --git a/src/cmd/compile/internal/types2/assignments.go b/src/cmd/compile/internal/types2/assignments.go
index 609d7d0962..da7f7dfa5c 100644
--- a/src/cmd/compile/internal/types2/assignments.go
+++ b/src/cmd/compile/internal/types2/assignments.go
@@ -85,7 +85,11 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
 	reason := ""
 	if ok, _ := x.assignableTo(check, T, &reason); !ok {
 		if check.conf.CompilerErrorMessages {
-			check.errorf(x, "incompatible type: cannot use %s as %s value", x, T)
+			if reason != "" {
+				check.errorf(x, "cannot use %s as type %s in %s:\n\t%s", x, T, context, reason)
+			} else {
+				check.errorf(x, "cannot use %s as type %s in %s", x, T, context)
+			}
 		} else {
 			if reason != "" {
 				check.errorf(x, "cannot use %s as %s value in %s: %s", x, T, context, reason)
diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go
index 968ac4d39f..cc7b52099c 100644
--- a/src/cmd/compile/internal/types2/conversions.go
+++ b/src/cmd/compile/internal/types2/conversions.go
@@ -69,9 +69,19 @@ func (check *Checker) conversion(x *operand, T Type) {
 
 	if !ok {
 		var err error_
-		err.errorf(x, "cannot convert %s to %s", x, T)
-		if cause != "" {
-			err.errorf(nopos, cause)
+		if check.conf.CompilerErrorMessages {
+			if cause != "" {
+				// Add colon at end of line if we have a following cause.
+				err.errorf(x, "cannot convert %s to type %s:", x, T)
+				err.errorf(nopos, cause)
+			} else {
+				err.errorf(x, "cannot convert %s to type %s", x, T)
+			}
+		} else {
+			err.errorf(x, "cannot convert %s to %s", x, T)
+			if cause != "" {
+				err.errorf(nopos, cause)
+			}
 		}
 		check.report(&err)
 		x.mode = invalid
diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go
index 25e2060100..f86606375c 100644
--- a/src/cmd/compile/internal/types2/expr.go
+++ b/src/cmd/compile/internal/types2/expr.go
@@ -1626,25 +1626,20 @@ func (check *Checker) typeAssertion(e syntax.Expr, x *operand, xtyp *Interface,
 		return
 	}
 
-	var msg string
-	if wrongType != nil {
-		if Identical(method.typ, wrongType.typ) {
-			msg = fmt.Sprintf("%s method has pointer receiver", method.name)
-		} else {
-			msg = fmt.Sprintf("wrong type for method %s: have %s, want %s", method.name, wrongType.typ, method.typ)
-		}
-	} else {
-		msg = fmt.Sprintf("missing %s method", method.name)
-	}
-
 	var err error_
+	var msg string
 	if typeSwitch {
 		err.errorf(e.Pos(), "impossible type switch case: %s", e)
-		err.errorf(nopos, "%s cannot have dynamic type %s (%s)", x, T, msg)
+		msg = check.sprintf("%s cannot have dynamic type %s %s", x, T,
+			check.missingMethodReason(T, x.typ, method, wrongType))
+
 	} else {
 		err.errorf(e.Pos(), "impossible type assertion: %s", e)
-		err.errorf(nopos, "%s does not implement %s (%s)", T, x.typ, msg)
+		msg = check.sprintf("%s does not implement %s %s", T, x.typ,
+			check.missingMethodReason(T, x.typ, method, wrongType))
+
 	}
+	err.errorf(nopos, msg)
 	check.report(&err)
 }
 
diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go
index 5da51a23ab..a05a5d6397 100644
--- a/src/cmd/compile/internal/types2/lookup.go
+++ b/src/cmd/compile/internal/types2/lookup.go
@@ -6,6 +6,11 @@
 
 package types2
 
+import (
+	"fmt"
+	"strings"
+)
+
 // Internal use of LookupFieldOrMethod: If the obj result is a method
 // associated with a concrete (non-interface) type, the method's signature
 // may not be fully set up. Call Checker.objDecl(obj, nil) before accessing
@@ -401,6 +406,59 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
 	return
 }
 
+// missingMethodReason returns a string giving the detailed reason for a missing method m,
+// where m is missing from V, but required by T. It puts the reason in parentheses,
+// and may include more have/want info after that. If non-nil, wrongType is a relevant
+// method that matches in some way. It may have the correct name, but wrong type, or
+// it may have a pointer receiver.
+func (check *Checker) missingMethodReason(V, T Type, m, wrongType *Func) string {
+	var r string
+	var mname string
+	if check.conf.CompilerErrorMessages {
+		mname = m.Name() + " method"
+	} else {
+		mname = "method " + m.Name()
+	}
+	if wrongType != nil {
+		if Identical(m.typ, wrongType.typ) {
+			if m.Name() == wrongType.Name() {
+				r = fmt.Sprintf("(%s has pointer receiver)", mname)
+			} else {
+				r = fmt.Sprintf("(missing %s)\n\t\thave %s^^%s\n\t\twant %s^^%s",
+					mname, wrongType.Name(), wrongType.typ, m.Name(), m.typ)
+			}
+		} else {
+			if check.conf.CompilerErrorMessages {
+				r = fmt.Sprintf("(wrong type for %s)\n\t\thave %s^^%s\n\t\twant %s^^%s",
+					mname, wrongType.Name(), wrongType.typ, m.Name(), m.typ)
+			} else {
+				r = fmt.Sprintf("(wrong type for %s: have %s, want %s)",
+					mname, wrongType.typ, m.typ)
+			}
+		}
+		// This is a hack to print the function type without the leading
+		// 'func' keyword in the have/want printouts. We could change to have
+		// an extra formatting option for types2.Type that doesn't print out
+		// 'func'.
+		r = strings.Replace(r, "^^func", "", -1)
+	} else if IsInterface(T) {
+		if isInterfacePtr(V) {
+			r = fmt.Sprintf("(%s is pointer to interface, not interface)", V)
+		}
+	} else if isInterfacePtr(T) {
+		r = fmt.Sprintf("(%s is pointer to interface, not interface)", T)
+	}
+	if r == "" {
+		r = fmt.Sprintf("(missing %s)", mname)
+	}
+	return r
+}
+
+func isInterfacePtr(T Type) bool {
+	p, _ := under(T).(*Pointer)
+	return p != nil && IsInterface(p.base)
+}
+
 // assertableTo reports whether a value of type V can be asserted to have type T.
 // It returns (nil, false) as affirmative answer. Otherwise it returns a missing
 // method required by V and whether it is missing or just has the wrong type.
diff --git a/src/cmd/compile/internal/types2/operand.go b/src/cmd/compile/internal/types2/operand.go
index 762a7543a9..fee154a6bb 100644
--- a/src/cmd/compile/internal/types2/operand.go
+++ b/src/cmd/compile/internal/types2/operand.go
@@ -289,18 +289,21 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er
 
 	// T is an interface type and x implements T and T is not a type parameter
 	if Ti, ok := Tu.(*Interface); ok {
-		if m, wrongType := check.missingMethod(V, Ti, true); m != nil /* Implements(V, Ti) */ {
+		if m, wrongType := check.missingMethod(V, Ti, true); m != nil /* !Implements(V, Ti) */ {
 			if reason != nil {
-				// TODO(gri) the error messages here should follow the style in Checker.typeAssertion (factor!)
-				if wrongType != nil {
-					if Identical(m.typ, wrongType.typ) {
-						*reason = fmt.Sprintf("missing method %s (%s has pointer receiver)", m.name, m.name)
+				if check.conf.CompilerErrorMessages {
+					*reason = check.sprintf("%s does not implement %s %s", x.typ, T,
+						check.missingMethodReason(x.typ, T, m, wrongType))
+				} else {
+					if wrongType != nil {
+						if Identical(m.typ, wrongType.typ) {
+							*reason = fmt.Sprintf("missing method %s (%s has pointer receiver)", m.name, m.name)
+						} else {
+							*reason = fmt.Sprintf("wrong type for method %s (have %s, want %s)", m.Name(), wrongType.typ, m.typ)
+						}
 					} else {
-						*reason = fmt.Sprintf("wrong type for method %s (have %s, want %s)", m.Name(), wrongType.typ, m.typ)
+						*reason = "missing method " + m.Name()
 					}
-
-				} else {
-					*reason = "missing method " + m.Name()
 				}
 			}
 			return false, _InvalidIfaceAssign
@@ -308,6 +311,24 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er
 		return true, 0
 	}
 
+	// Provide extra detail in compiler error messages in some cases when T is
+	// not an interface.
+	if check != nil && check.conf.CompilerErrorMessages {
+		if isInterfacePtr(Tu) {
+			*reason = check.sprintf("%s does not implement %s (%s is pointer to interface, not interface)", x.typ, T, T)
+			return false, _InvalidIfaceAssign
+		}
+		if Vi, _ := Vu.(*Interface); Vi != nil {
+			if m, _ := check.missingMethod(T, Vi, true); m == nil {
+				// T implements Vi, so give hint about type assertion.
+				if reason != nil {
+					*reason = check.sprintf("need type assertion")
+				}
+				return false, _IncompatibleAssign
+			}
+		}
+	}
+
 	// x is a bidirectional channel value, T is a channel
 	// type, x's type V and T have identical element types,
 	// and at least one of V or T is not a named type.
diff --git a/src/cmd/compile/internal/types2/testdata/check/expr3.src b/src/cmd/compile/internal/types2/testdata/check/expr3.src
index df4cf6a840..d1e1dba9f4 100644
--- a/src/cmd/compile/internal/types2/testdata/check/expr3.src
+++ b/src/cmd/compile/internal/types2/testdata/check/expr3.src
@@ -459,9 +459,9 @@ func type_asserts() {
 
 	var t I
 	_ = t /* ERROR "use of .* outside type switch" */ .(type)
-	_ = t /* ERROR "m method has pointer receiver" */ .(T)
+	_ = t /* ERROR "method m has pointer receiver" */ .(T)
 	_ = t.(*T)
-	_ = t /* ERROR "missing m method" */ .(T1)
+	_ = t /* ERROR "missing method m" */ .(T1)
 	_ = t /* ERROR "wrong type for method m" */ .(T2)
 	_ = t /* STRICT "wrong type for method m" */ .(I2) // only an error in strict mode (issue 8561)
 
diff --git a/src/cmd/compile/internal/types2/testdata/check/issues.src b/src/cmd/compile/internal/types2/testdata/check/issues.src
index dfd51006b9..f4b6199b82 100644
--- a/src/cmd/compile/internal/types2/testdata/check/issues.src
+++ b/src/cmd/compile/internal/types2/testdata/check/issues.src
@@ -132,7 +132,7 @@ func issue10260() {
 
 	var x I1
 	x = T1 /* ERROR cannot use .*: missing method foo \(foo has pointer receiver\) */ {}
-	_ = x. /* ERROR impossible type assertion: x.\(T1\)\n\tT1 does not implement I1 \(foo method has pointer receiver\) */ (T1)
+	_ = x. /* ERROR impossible type assertion: x.\(T1\)\n\tT1 does not implement I1 \(method foo has pointer receiver\) */ (T1)
 
 	T1{}.foo /* ERROR cannot call pointer method foo on T1 */ ()
 	x.Foo /* ERROR "x.Foo undefined \(type I1 has no field or method Foo, but does have foo\)" */ ()
diff --git a/src/cmd/compile/internal/types2/testdata/check/stmt0.src b/src/cmd/compile/internal/types2/testdata/check/stmt0.src
index 5ec37b4ace..d744f2ba81 100644
--- a/src/cmd/compile/internal/types2/testdata/check/stmt0.src
+++ b/src/cmd/compile/internal/types2/testdata/check/stmt0.src
@@ -715,7 +715,7 @@ func typeswitches() {
 	var t I
 	switch t.(type) {
 	case T:
-	case T1 /* ERROR "missing m method" */ :
+	case T1 /* ERROR "missing method m" */ :
 	case T2 /* ERROR "wrong type for method m" */ :
 	case I2 /* STRICT "wrong type for method m" */ : // only an error in strict mode (issue 8561)
 	}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49005.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49005.go
index 6225e68488..f152e7f55c 100644
--- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49005.go
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49005.go
@@ -23,12 +23,12 @@ type T2 interface{ M() }
 
 func F2() T2
 
-var _ = F2(). /* ERROR impossible type assertion: F2\(\).\(\*X2\)\n\t\*X2 does not implement T2 \(missing M method\) */ (*X2)
+var _ = F2(). /* ERROR impossible type assertion: F2\(\).\(\*X2\)\n\t\*X2 does not implement T2 \(missing method M\) */ (*X2)
 
 type X2 struct{}
 
 func _() {
 	switch F2().(type) {
-	case * /* ERROR impossible type switch case: \*X2\n\tF2\(\) \(value of type T2\) cannot have dynamic type \*X2 \(missing M method\) */ X2:
+	case * /* ERROR impossible type switch case: \*X2\n\tF2\(\) \(value of type T2\) cannot have dynamic type \*X2 \(missing method M\) */ X2:
 	}
 }
diff --git a/test/alias2.go b/test/alias2.go
index d7b5dccb68..61c7551f79 100644
--- a/test/alias2.go
+++ b/test/alias2.go
@@ -46,8 +46,8 @@ var _ A0 = T0{}
 var _ T0 = A0{}
 
 // But aliases and original types cannot be used with new types based on them.
-var _ N0 = T0{} // ERROR "cannot use T0{} \(type T0\) as type N0 in assignment|incompatible type"
-var _ N0 = A0{} // ERROR "cannot use T0{} \(type T0\) as type N0 in assignment|incompatible type"
+var _ N0 = T0{} // ERROR "cannot use T0{} \(type T0\) as type N0 in assignment|cannot use T0{} \(value of type T0\) as type N0 in variable declaration"
+var _ N0 = A0{} // ERROR "cannot use T0{} \(type T0\) as type N0 in assignment|cannot use A0{} \(value of type T0\) as type N0 in variable declaration"
 
 var _ A5 = Value{}
 
@@ -82,10 +82,10 @@ func _() {
 	var _ A0 = T0{}
 	var _ T0 = A0{}
 
-	var _ N0 = T0{} // ERROR "cannot use T0{} \(type T0\) as type N0 in assignment|incompatible type"
-	var _ N0 = A0{} // ERROR "cannot use T0{} \(type T0\) as type N0 in assignment|incompatible type"
+	var _ N0 = T0{} // ERROR "cannot use T0{} \(type T0\) as type N0 in assignment|cannot use T0{} \(value of type T0\) as type N0 in variable declaration"
+	var _ N0 = A0{} // ERROR "cannot use T0{} \(type T0\) as type N0 in assignment|cannot use A0{} \(value of type T0\) as type N0 in variable declaration"
 
-	var _ A5 = Value{} // ERROR "cannot use reflect\.Value{} \(type reflect.Value\) as type A5 in assignment|incompatible type"
+	var _ A5 = Value{} // ERROR "cannot use reflect\.Value{} \(type reflect.Value\) as type A5 in assignment|cannot use Value{} \(value of type reflect.Value\) as type A5 in variable declaration"
 }
 
 // Invalid type alias declarations.
diff --git a/test/append1.go b/test/append1.go
index 9dab120b25..397be570d9 100644
--- a/test/append1.go
+++ b/test/append1.go
@@ -17,6 +17,6 @@ func main() {
 	_ = append(s...)       // ERROR "cannot use ... on first argument|not enough arguments in call to append"
 	_ = append(s, 2, s...) // ERROR "too many arguments to append|too many arguments in call to append"
 
-	_ = append(s, make([]int, 0))     // ERROR "cannot use make.* as type int in append|cannot use make.* as int value"
+	_ = append(s, make([]int, 0))     // ERROR "cannot use make.* as type int in append|cannot use make.* \(value of type \[\]int\) as type int in argument to append"
 	_ = append(s, make([]int, -1)...) // ERROR "negative len argument in make|index -1.* must not be negative"
 }
diff --git a/test/ddd1.go b/test/ddd1.go
index f7381b7c94..639b0bfdbd 100644
--- a/test/ddd1.go
+++ b/test/ddd1.go
@@ -19,7 +19,7 @@ var (
 	_ = sum(1.0, 2.0)
 	_ = sum(1.5)      // ERROR "1\.5 .untyped float constant. as int|integer"
 	_ = sum("hello")  // ERROR ".hello. (.untyped string constant. as int|.type untyped string. as type int)|incompatible"
-	_ = sum([]int{1}) // ERROR "\[\]int{...}.*as type int|incompatible"
+	_ = sum([]int{1}) // ERROR "\[\]int{.*}.*as type int"
 )
 
 func sum3(int, int, int) int { return 0 }
diff --git a/test/fixedbugs/bug389.go b/test/fixedbugs/bug389.go
index 167e64e72c..209be8e6f7 100644
--- a/test/fixedbugs/bug389.go
+++ b/test/fixedbugs/bug389.go
@@ -9,4 +9,4 @@ package foo
 
 func fn(a float32) {}
 
-var f func(arg int) = fn  // ERROR "cannot use fn .type func.float32.. as type func.int. in assignment|different parameter types|incompatible type"
+var f func(arg int) = fn // ERROR "cannot use fn .type func.float32.. as type func.int. in assignment|different parameter types|cannot use fn .*type func.*float32.. as type func.*int. in variable declaration"
diff --git a/test/fixedbugs/issue41247.go b/test/fixedbugs/issue41247.go
index c5e495ba93..05889a9ce8 100644
--- a/test/fixedbugs/issue41247.go
+++ b/test/fixedbugs/issue41247.go
@@ -7,5 +7,5 @@
 package p
 
 func f() [2]int {
-	return [...]int{2: 0} // ERROR "cannot use \[\.\.\.\]int{...} \(type \[3\]int\)|incompatible type"
+	return [...]int{2: 0} // ERROR "cannot use \[\.\.\.\]int{.*} \(.*type \[3\]int\)"
 }
diff --git a/test/fixedbugs/issue48471.go b/test/fixedbugs/issue48471.go
new file mode 100644
index 0000000000..0412d23b99
--- /dev/null
+++ b/test/fixedbugs/issue48471.go
@@ -0,0 +1,41 @@
+// errorcheck
+
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type I interface{ M(int) }
+
+type T struct{}
+
+type T2 struct{}
+
+func (*T2) m(int)
+
+type T3 struct{}
+
+func (*T3) M(string) {}
+
+type T4 struct{}
+
+func (*T4) M(int)
+
+func f(I)
+
+func g() {
+	f(new(T)) // ERROR "cannot use new\(T\) \(.*type \*T\) as type I in argument to f:\n\t\*T does not implement I \(missing M method\)"
+	var i I
+	i = new(T)    // ERROR "cannot use new\(T\) \(.*type \*T\) as type I in assignment:\n\t\*T does not implement I \(missing M method\)"
+	i = I(new(T)) // ERROR "cannot convert new\(T\) \(.*type \*T\) to type I:\n\t\*T does not implement I \(missing M method\)"
+	i = new(T2)   // ERROR "cannot use new\(T2\) \(.*type \*T2\) as type I in assignment:\n\t\*T2 does not implement I \(missing M method\)"
+	i = new(T3)   // ERROR "cannot use new\(T3\) \(.*type \*T3\) as type I in assignment:\n\t\*T3 does not implement I \(wrong type for M method\)\n\t\thave M\(string\)\n\t\twant M\(int\)"
+	i = T4{}      // ERROR "cannot use T4\{\} \(.*type T4\) as type I in assignment:\n\tT4 does not implement I \(M method has pointer receiver\)"
+	i = new(I)    // ERROR "cannot use new\(I\) \(.*type \*I\) as type I in assignment:\n\t\*I does not implement I \(\*I is pointer to interface, not interface\)"
+	_ = i.(*T2)   // ERROR "impossible type assertion: i.\(\*T2\)\n\t\*T2 does not implement I \(missing M method\)"
+	_ = i.(*T3)   // ERROR "impossible type assertion: i.\(\*T3\)\n\t\*T3 does not implement I \(wrong type for M method\)\n\t\thave M\(string\)\n\t\twant M\(int\)"
+	var t *T4
+	t = i // ERROR "cannot use i \(variable of type I\) as type \*T4 in assignment:\n\tneed type assertion"
+	_ = i
+}
diff --git a/test/fixedbugs/issue6572.go b/test/fixedbugs/issue6572.go
index 9f4d2de0e3..d69bf5aee2 100644
--- a/test/fixedbugs/issue6572.go
+++ b/test/fixedbugs/issue6572.go
@@ -17,6 +17,6 @@ func bar() (T, string, T) { // ERROR "undefined"
 func main() {
 	var x, y, z int
 	x, y = foo()
-	x, y, z = bar() // ERROR "cannot (use type|assign) string|incompatible type"
+	x, y, z = bar() // ERROR "cannot (use type|assign|use.*type) string|"
 	_, _, _ = x, y, z
 }
diff --git a/test/fixedbugs/issue9521.go b/test/fixedbugs/issue9521.go
index 1ad40bdfda..a029ec145e 100644
--- a/test/fixedbugs/issue9521.go
+++ b/test/fixedbugs/issue9521.go
@@ -13,6 +13,6 @@ func f() (_, _ []int)         { return }
 func g() (x []int, y float64) { return }
 
 func main() {
-	_ = append(f()) // ERROR "cannot use \[\]int value as type int in append|incompatible type"
-	_ = append(g()) // ERROR "cannot use float64 value as type int in append|incompatible type"
+	_ = append(f()) // ERROR "cannot use \[\]int value as type int in append|cannot use.*type \[\]int.*to append"
+	_ = append(g()) // ERROR "cannot use float64 value as type int in append|cannot use.*type float64.*to append"
 }
diff --git a/test/interface/explicit.go b/test/interface/explicit.go
index f769f5878c..e18d6843ec 100644
--- a/test/interface/explicit.go
+++ b/test/interface/explicit.go
@@ -38,7 +38,7 @@ var e E
 
 func main() {
 	e = t // ok
-	t = e // ERROR "need explicit|need type assertion|incompatible type"
+	t = e // ERROR "need explicit|need type assertion"
 
 	// neither of these can work,
 	// because i has an extra method
diff --git a/test/run.go b/test/run.go
index 942fd032f2..ad64304ec8 100644
--- a/test/run.go
+++ b/test/run.go
@@ -2125,14 +2125,11 @@ var types2Failures = setOf(
 	"shift1.go",       // issue #42989
 	"typecheck.go",    // invalid function is not causing errors when called
 
-	"interface/private.go", // types2 phrases errors differently (doesn't use non-spec "private" term)
-
 	"fixedbugs/bug176.go", // types2 reports all errors (pref: types2)
 	"fixedbugs/bug195.go", // types2 reports slightly different (but correct) bugs
 	"fixedbugs/bug228.go", // types2 doesn't run when there are syntax errors
 	"fixedbugs/bug231.go", // types2 bug? (same error reported twice)
 	"fixedbugs/bug255.go", // types2 reports extra errors
-	"fixedbugs/bug374.go", // types2 reports extra errors
 	"fixedbugs/bug388.go", // types2 not run due to syntax errors
 	"fixedbugs/bug412.go", // types2 produces a follow-on error
 
-- 
GitLab


From 429d1e01557f95bba29837f2190441696484fd41 Mon Sep 17 00:00:00 2001
From: Dan Scales 
Date: Thu, 11 Nov 2021 10:28:17 -0800
Subject: [PATCH 2153/2500] cmd/compile: add missing method info for method
 with correct name except for case

When being used by the compiler, augment the types2 missing method
message with extra info, if a method is missing, but a method with the
correct name except for case (i.e. equal via string.EqualFold()) is
present. In that case, print out the wanted method and the method that
is present (that has the wrong case).

In the 1.17 compiler, we don't do this case-folding check when assigning
an interface to an interface, so I didn't add that check, but we could
add that.

Fixes #48471

Change-Id: Ic54549c1f66297c9221d979d49c1daa719aa66cd
Reviewed-on: https://go-review.googlesource.com/c/go/+/363437
Trust: Dan Scales 
Run-TryBot: Dan Scales 
TryBot-Result: Go Bot 
Reviewed-by: Robert Griesemer 
---
 src/cmd/compile/internal/types2/lookup.go | 48 ++++++++++++++++++-----
 test/fixedbugs/issue48471.go              |  4 +-
 2 files changed, 40 insertions(+), 12 deletions(-)

diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go
index a05a5d6397..8ed5ca837a 100644
--- a/src/cmd/compile/internal/types2/lookup.go
+++ b/src/cmd/compile/internal/types2/lookup.go
@@ -52,7 +52,7 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
 	// not have found it for T (see also issue 8590).
 	if t := asNamed(T); t != nil {
 		if p, _ := safeUnderlying(t).(*Pointer); p != nil {
-			obj, index, indirect = lookupFieldOrMethod(p, false, pkg, name)
+			obj, index, indirect = lookupFieldOrMethod(p, false, false, pkg, name)
 			if _, ok := obj.(*Func); ok {
 				return nil, nil, false
 			}
@@ -60,7 +60,7 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
 		}
 	}
 
-	return lookupFieldOrMethod(T, addressable, pkg, name)
+	return lookupFieldOrMethod(T, addressable, false, pkg, name)
 }
 
 // TODO(gri) The named type consolidation and seen maps below must be
@@ -69,7 +69,9 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
 //           indirectly via different packages.)
 
 // lookupFieldOrMethod should only be called by LookupFieldOrMethod and missingMethod.
-func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) {
+// If checkFold is true, the lookup for methods will include looking for any method
+// which case-folds to the same as 'name' (used for giving helpful error messages).
+func lookupFieldOrMethod(T Type, addressable, checkFold bool, pkg *Package, name string) (obj Object, index []int, indirect bool) {
 	// WARNING: The code in this function is extremely subtle - do not modify casually!
 
 	if name == "_" {
@@ -127,7 +129,7 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
 				seen[named] = true
 
 				// look for a matching attached method
-				if i, m := lookupMethod(named.methods, pkg, name); m != nil {
+				if i, m := lookupMethodFold(named.methods, pkg, name, checkFold); m != nil {
 					// potential match
 					// caution: method may not have a proper signature yet
 					index = concat(e.index, i)
@@ -178,7 +180,7 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
 
 			case *Interface:
 				// look for a matching method
-				if i, m := t.typeSet().LookupMethod(pkg, name); m != nil {
+				if i, m := lookupMethodFold(t.typeSet().methods, pkg, name, checkFold); m != nil {
 					assert(m.typ != nil)
 					index = concat(e.index, i)
 					if obj != nil || e.multiples {
@@ -189,7 +191,7 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
 				}
 
 			case *TypeParam:
-				if i, m := t.iface().typeSet().LookupMethod(pkg, name); m != nil {
+				if i, m := lookupMethodFold(t.iface().typeSet().methods, pkg, name, checkFold); m != nil {
 					assert(m.typ != nil)
 					index = concat(e.index, i)
 					if obj != nil || e.multiples {
@@ -315,6 +317,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
 				if !static {
 					continue
 				}
+				// We don't do any case-fold check if V is an interface.
 				return m, f
 			}
 
@@ -345,13 +348,20 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
 
 	// A concrete type implements T if it implements all methods of T.
 	for _, m := range T.typeSet().methods {
-		// TODO(gri) should this be calling lookupFieldOrMethod instead (and why not)?
-		obj, _, _ := lookupFieldOrMethod(V, false, m.pkg, m.name)
+		// TODO(gri) should this be calling LookupFieldOrMethod instead (and why not)?
+		obj, _, _ := lookupFieldOrMethod(V, false, false, m.pkg, m.name)
 
 		// Check if *V implements this method of T.
 		if obj == nil {
 			ptr := NewPointer(V)
-			obj, _, _ = lookupFieldOrMethod(ptr, false, m.pkg, m.name)
+			obj, _, _ = lookupFieldOrMethod(ptr, false, false, m.pkg, m.name)
+			if obj != nil {
+				return m, obj.(*Func)
+			}
+			// If we didn't find the exact method (even with pointer
+			// receiver), look to see if there is a method that
+			// matches m.name with case-folding.
+			obj, _, _ := lookupFieldOrMethod(V, false, true, m.pkg, m.name)
 			if obj != nil {
 				return m, obj.(*Func)
 			}
@@ -410,7 +420,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
 // where m is missing from V, but required by T. It puts the reason in parentheses,
 // and may include more have/want info after that. If non-nil, wrongType is a relevant
 // method that matches in some way. It may have the correct name, but wrong type, or
-// it may have a pointer receiver.
+// it may have a pointer receiver, or it may have the correct name except wrong case.
 func (check *Checker) missingMethodReason(V, T Type, m, wrongType *Func) string {
 	var r string
 	var mname string
@@ -527,3 +537,21 @@ func lookupMethod(methods []*Func, pkg *Package, name string) (int, *Func) {
 	}
 	return -1, nil
 }
+
+// lookupMethodFold is like lookupMethod, but if checkFold is true, it matches a method
+// name if the names are equal with case folding.
+func lookupMethodFold(methods []*Func, pkg *Package, name string, checkFold bool) (int, *Func) {
+	if name != "_" {
+		for i, m := range methods {
+			if m.name != name && !(checkFold && strings.EqualFold(m.name, name)) {
+				continue
+			}
+			// Use m.name, since we've already checked that m.name and
+			// name are equal with folding.
+			if m.sameId(pkg, m.name) {
+				return i, m
+			}
+		}
+	}
+	return -1, nil
+}
diff --git a/test/fixedbugs/issue48471.go b/test/fixedbugs/issue48471.go
index 0412d23b99..2e00c87c6a 100644
--- a/test/fixedbugs/issue48471.go
+++ b/test/fixedbugs/issue48471.go
@@ -29,11 +29,11 @@ func g() {
 	var i I
 	i = new(T)    // ERROR "cannot use new\(T\) \(.*type \*T\) as type I in assignment:\n\t\*T does not implement I \(missing M method\)"
 	i = I(new(T)) // ERROR "cannot convert new\(T\) \(.*type \*T\) to type I:\n\t\*T does not implement I \(missing M method\)"
-	i = new(T2)   // ERROR "cannot use new\(T2\) \(.*type \*T2\) as type I in assignment:\n\t\*T2 does not implement I \(missing M method\)"
+	i = new(T2)   // ERROR "cannot use new\(T2\) \(.*type \*T2\) as type I in assignment:\n\t\*T2 does not implement I \(missing M method\)\n\t\thave m\(int\)\n\t\twant M\(int\)"
 	i = new(T3)   // ERROR "cannot use new\(T3\) \(.*type \*T3\) as type I in assignment:\n\t\*T3 does not implement I \(wrong type for M method\)\n\t\thave M\(string\)\n\t\twant M\(int\)"
 	i = T4{}      // ERROR "cannot use T4\{\} \(.*type T4\) as type I in assignment:\n\tT4 does not implement I \(M method has pointer receiver\)"
 	i = new(I)    // ERROR "cannot use new\(I\) \(.*type \*I\) as type I in assignment:\n\t\*I does not implement I \(\*I is pointer to interface, not interface\)"
-	_ = i.(*T2)   // ERROR "impossible type assertion: i.\(\*T2\)\n\t\*T2 does not implement I \(missing M method\)"
+	_ = i.(*T2)   // ERROR "impossible type assertion: i.\(\*T2\)\n\t\*T2 does not implement I \(missing M method\)\n\t\thave m\(int\)\n\t\twant M\(int\)"
 	_ = i.(*T3)   // ERROR "impossible type assertion: i.\(\*T3\)\n\t\*T3 does not implement I \(wrong type for M method\)\n\t\thave M\(string\)\n\t\twant M\(int\)"
 	var t *T4
 	t = i // ERROR "cannot use i \(variable of type I\) as type \*T4 in assignment:\n\tneed type assertion"
-- 
GitLab


From 3a4b95073a9fd7bca6e9fd80016275ef04bc1987 Mon Sep 17 00:00:00 2001
From: Robert Griesemer 
Date: Fri, 12 Nov 2021 13:23:45 -0800
Subject: [PATCH 2154/2500] cmd/compile/internal/types2: make sure we are safe
 for nil in underIs

Reviewed all uses of underIs (global function and method) and made
sure we are ok with a nil incoming argument (indicating a type set
with no specific types).

Added a couple of checks where we didn't have them (and somehow
didn't run into a problem yet).

Change-Id: Ifde45a3a80ddf2b1a19c83f79258ad8207dfb09f
Reviewed-on: https://go-review.googlesource.com/c/go/+/363658
Trust: Robert Griesemer 
Reviewed-by: Robert Findley 
---
 src/cmd/compile/internal/types2/expr.go       | 3 +++
 src/cmd/compile/internal/types2/predicates.go | 4 +++-
 src/cmd/compile/internal/types2/type.go       | 3 +++
 3 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go
index f86606375c..77e497b9cc 100644
--- a/src/cmd/compile/internal/types2/expr.go
+++ b/src/cmd/compile/internal/types2/expr.go
@@ -740,6 +740,9 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const
 	case *TypeParam:
 		// TODO(gri) review this code - doesn't look quite right
 		ok := u.underIs(func(t Type) bool {
+			if t == nil {
+				return false
+			}
 			target, _, _ := check.implicitTypeAndValue(x, t)
 			return target != nil
 		})
diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go
index 5cb1c33814..ab490372fc 100644
--- a/src/cmd/compile/internal/types2/predicates.go
+++ b/src/cmd/compile/internal/types2/predicates.go
@@ -147,7 +147,9 @@ func hasNil(t Type) bool {
 	case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan:
 		return true
 	case *TypeParam:
-		return u.underIs(hasNil)
+		return u.underIs(func(u Type) bool {
+			return u != nil && hasNil(u)
+		})
 	}
 	return false
 }
diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go
index 24d44442e9..ba260d2b7d 100644
--- a/src/cmd/compile/internal/types2/type.go
+++ b/src/cmd/compile/internal/types2/type.go
@@ -65,6 +65,9 @@ func match(x, y Type) Type {
 func structuralType(typ Type) Type {
 	var su Type
 	if underIs(typ, func(u Type) bool {
+		if u == nil {
+			return false
+		}
 		if su != nil {
 			u = match(su, u)
 			if u == nil {
-- 
GitLab


From fdee1b297438a64c553ecc7468a7647f5a070404 Mon Sep 17 00:00:00 2001
From: Michael Matloob 
Date: Thu, 28 Oct 2021 16:28:32 -0400
Subject: [PATCH 2155/2500] cmd/go: add go work use command

For #45713, #48257

Change-Id: I7e9248f22fe7ab33b151e07cc296d64c194154e2
Reviewed-on: https://go-review.googlesource.com/c/go/+/359534
Trust: Michael Matloob 
Run-TryBot: Michael Matloob 
TryBot-Result: Go Bot 
Reviewed-by: Bryan C. Mills 
---
 src/cmd/go/alldocs.go                   |  13 +++
 src/cmd/go/internal/workcmd/use.go      | 129 ++++++++++++++++++++++++
 src/cmd/go/internal/workcmd/work.go     |   1 +
 src/cmd/go/testdata/script/work_use.txt |  32 ++++++
 4 files changed, 175 insertions(+)
 create mode 100644 src/cmd/go/internal/workcmd/use.go
 create mode 100644 src/cmd/go/testdata/script/work_use.txt

diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go
index dfb88ab78d..a53ff7c66d 100644
--- a/src/cmd/go/alldocs.go
+++ b/src/cmd/go/alldocs.go
@@ -1388,6 +1388,7 @@
 // 	edit        edit go.work from tools or scripts
 // 	init        initialize workspace file
 // 	sync        sync workspace build list to modules
+// 	use         add modules to workspace file
 //
 // Use "go help work " for more information about a command.
 //
@@ -1488,6 +1489,18 @@
 // go work sync
 //
 //
+// Add modules to workspace file
+//
+// Usage:
+//
+// 	go work use [-r] [moddirs]
+//
+// Use provides a command-line interface for adding directories,
+// optionally recursively, to a go.work file.
+//
+// The -r flag searches recursively for modules in the argument directories.
+//
+//
 // Compile and run Go program
 //
 // Usage:
diff --git a/src/cmd/go/internal/workcmd/use.go b/src/cmd/go/internal/workcmd/use.go
new file mode 100644
index 0000000000..10c25da396
--- /dev/null
+++ b/src/cmd/go/internal/workcmd/use.go
@@ -0,0 +1,129 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// go work use
+
+package workcmd
+
+import (
+	"cmd/go/internal/base"
+	"cmd/go/internal/fsys"
+	"cmd/go/internal/lockedfile"
+	"cmd/go/internal/modload"
+	"context"
+	"io/fs"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+
+	"golang.org/x/mod/modfile"
+)
+
+var _ = modload.TODOWorkspaces("Add more documentation below. Though this is" +
+	"enough for those trying workspaces out, there should be more through" +
+	"documentation if the proposal is accepted and released.")
+
+var cmdUse = &base.Command{
+	UsageLine: "go work use [-r] [moddirs]",
+	Short:     "add modules to workspace file",
+	Long: `Use provides a command-line interface for adding directories,
+optionally recursively, to a go.work file.
+
+The -r flag searches recursively for modules in the argument directories.`,
+}
+
+var useR = cmdUse.Flag.Bool("r", false, "")
+
+func init() {
+	cmdUse.Run = runUse // break init cycle
+
+	base.AddModCommonFlags(&cmdUse.Flag)
+	base.AddWorkfileFlag(&cmdUse.Flag)
+}
+
+func runUse(ctx context.Context, cmd *base.Command, args []string) {
+	modload.InitWorkfile()
+
+	modload.ForceUseModules = true
+
+	var gowork string
+	modload.InitWorkfile()
+	gowork = modload.WorkFilePath()
+
+	data, err := lockedfile.Read(gowork)
+	if err != nil {
+		base.Fatalf("goX: %v", err)
+	}
+
+	workFile, err := modfile.ParseWork(gowork, data, nil)
+	if err != nil {
+		base.Fatalf("go: errors parsing %s:\n%s", base.ShortPath(gowork), err)
+	}
+
+	haveDirs := make(map[string]bool)
+	for _, dir := range workFile.Directory {
+		haveDirs[filepath.Join(filepath.Dir(gowork), filepath.FromSlash(dir.Path))] = true
+	}
+
+	addDirs := make(map[string]bool)
+	removeDirs := make(map[string]bool)
+	lookDir := func(dir string) {
+		absDir := filepath.Join(base.Cwd(), dir)
+		// If the path is absolute, keep it absolute. If it's relative,
+		// make it relative to the go.work file rather than the working directory.
+		if !filepath.IsAbs(dir) {
+			rel, err := filepath.Rel(filepath.Dir(gowork), absDir)
+			if err == nil {
+				dir = rel
+			}
+		}
+		fi, err := os.Stat(filepath.Join(dir, "go.mod"))
+		if err != nil {
+			if os.IsNotExist(err) {
+
+				if haveDirs[absDir] {
+					removeDirs[dir] = true
+				}
+				return
+			}
+			base.Errorf("go: %v", err)
+		}
+
+		if !fi.Mode().IsRegular() {
+			base.Errorf("go: %v is not regular", filepath.Join(dir, "go.mod"))
+		}
+
+		if !haveDirs[absDir] {
+			addDirs[dir] = true
+		}
+	}
+
+	for _, useDir := range args {
+		if *useR {
+			fsys.Walk(useDir, func(path string, info fs.FileInfo, err error) error {
+				if !info.IsDir() {
+					return nil
+				}
+				lookDir(path)
+				return nil
+			})
+			continue
+		}
+		lookDir(useDir)
+	}
+
+	for dir := range removeDirs {
+		workFile.DropDirectory(filepath.ToSlash(dir))
+	}
+	for dir := range addDirs {
+		workFile.AddDirectory(filepath.ToSlash(dir), "")
+	}
+	workFile.SortBlocks()
+	workFile.Cleanup() // clean file after edits
+	out := modfile.Format(workFile.Syntax)
+
+	if err := ioutil.WriteFile(gowork, out, 0666); err != nil {
+		base.Fatalf("go: %v", err)
+	}
+}
diff --git a/src/cmd/go/internal/workcmd/work.go b/src/cmd/go/internal/workcmd/work.go
index dc1164fb77..98d5a01de6 100644
--- a/src/cmd/go/internal/workcmd/work.go
+++ b/src/cmd/go/internal/workcmd/work.go
@@ -25,5 +25,6 @@ which workspaces are a part.
 		cmdEdit,
 		cmdInit,
 		cmdSync,
+		cmdUse,
 	},
 }
diff --git a/src/cmd/go/testdata/script/work_use.txt b/src/cmd/go/testdata/script/work_use.txt
new file mode 100644
index 0000000000..dddce0fe22
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_use.txt
@@ -0,0 +1,32 @@
+go work use -r foo
+cmp go.work go.want_work_r
+
+go work use other
+cmp go.work go.want_work_other
+-- go.work --
+go 1.18
+
+directory (
+	foo
+	foo/bar // doesn't exist
+)
+-- go.want_work_r --
+go 1.18
+
+directory (
+	foo
+	foo/bar/baz
+)
+-- go.want_work_other --
+go 1.18
+
+directory (
+	foo
+	foo/bar/baz
+	other
+)
+-- foo/go.mod --
+module foo
+-- foo/bar/baz/go.mod --
+module baz
+-- other/go.mod --
-- 
GitLab


From b69b2f63d65609b400b4a40ae01e4a48638f050f Mon Sep 17 00:00:00 2001
From: Damien Neil 
Date: Wed, 27 Oct 2021 14:03:24 -0700
Subject: [PATCH 2156/2500] net/http: do not send Transfer-Encoding: identity
 in responses

Server handlers may set a "Transfer-Encoding: identity" header on
responses to disable chunking, but this header should not be sent
on the wire.

Fixes #49194.

Change-Id: I46a9e3b8ff9d93edd7d1c34d264fc309fa322ad5
Reviewed-on: https://go-review.googlesource.com/c/go/+/359176
Trust: Damien Neil 
Run-TryBot: Damien Neil 
TryBot-Result: Go Bot 
Reviewed-by: Brad Fitzpatrick 
---
 src/net/http/clientserver_test.go | 34 +++++++++++++++++++++++++++++++
 src/net/http/server.go            |  7 ++++---
 2 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/src/net/http/clientserver_test.go b/src/net/http/clientserver_test.go
index 5e227181ac..125d63566b 100644
--- a/src/net/http/clientserver_test.go
+++ b/src/net/http/clientserver_test.go
@@ -1582,3 +1582,37 @@ func TestH12_WebSocketUpgrade(t *testing.T) {
 		},
 	}.run(t)
 }
+
+func TestIdentityTransferEncoding_h1(t *testing.T) { testIdentityTransferEncoding(t, h1Mode) }
+func TestIdentityTransferEncoding_h2(t *testing.T) { testIdentityTransferEncoding(t, h2Mode) }
+
+func testIdentityTransferEncoding(t *testing.T, h2 bool) {
+	setParallel(t)
+	defer afterTest(t)
+
+	const body = "body"
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
+		gotBody, _ := io.ReadAll(r.Body)
+		if got, want := string(gotBody), body; got != want {
+			t.Errorf("got request body = %q; want %q", got, want)
+		}
+		w.Header().Set("Transfer-Encoding", "identity")
+		w.WriteHeader(StatusOK)
+		w.(Flusher).Flush()
+		io.WriteString(w, body)
+	}))
+	defer cst.close()
+	req, _ := NewRequest("GET", cst.ts.URL, strings.NewReader(body))
+	res, err := cst.c.Do(req)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer res.Body.Close()
+	gotBody, err := io.ReadAll(res.Body)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if got, want := string(gotBody), body; got != want {
+		t.Errorf("got response body = %q; want %q", got, want)
+	}
+}
diff --git a/src/net/http/server.go b/src/net/http/server.go
index c4a2d57dd4..f0b0e86e91 100644
--- a/src/net/http/server.go
+++ b/src/net/http/server.go
@@ -1426,11 +1426,11 @@ func (cw *chunkWriter) writeHeader(p []byte) {
 		hasCL = false
 	}
 
-	if w.req.Method == "HEAD" || !bodyAllowedForStatus(code) {
-		// do nothing
-	} else if code == StatusNoContent {
+	if w.req.Method == "HEAD" || !bodyAllowedForStatus(code) || code == StatusNoContent {
+		// Response has no body.
 		delHeader("Transfer-Encoding")
 	} else if hasCL {
+		// Content-Length has been provided, so no chunking is to be done.
 		delHeader("Transfer-Encoding")
 	} else if w.req.ProtoAtLeast(1, 1) {
 		// HTTP/1.1 or greater: Transfer-Encoding has been set to identity, and no
@@ -1441,6 +1441,7 @@ func (cw *chunkWriter) writeHeader(p []byte) {
 		if hasTE && te == "identity" {
 			cw.chunking = false
 			w.closeAfterReply = true
+			delHeader("Transfer-Encoding")
 		} else {
 			// HTTP/1.1 or greater: use chunked transfer encoding
 			// to avoid closing the connection at EOF.
-- 
GitLab


From 39bc666430b3340c3de0e815cfc1fbfc7b2f7e99 Mon Sep 17 00:00:00 2001
From: Robert Griesemer 
Date: Tue, 26 Oct 2021 10:06:55 -0700
Subject: [PATCH 2157/2500] cmd/compile/internal/types2: underlying type of a
 type parameter is its constraint interface

Until now, the type checker operated with the definition that the
underlying type of a type parameter is itself. This leads to some
inconcistencies and caused us to disallow type declarations where
the RHS is a stand-alone type parameter.

This change implements an alernative definition: the underlying
type of a type parameter is the underlying type of its constraint;
i.e., the underlying type of a type parameter is always an interface
(because constraints must be interfaces). This matches the theory
closely and also resolves some inconsistencies. For example, we
don't need to prohibit stand-alone type parameters on the RHS of
a type declaration (though, for the sake of keeping the tests the
same, we still do in this CL). We also get a clear understanding of
what it would mean to use a type assertion or type switch on a type
parameter (still disabled with this CL). Finally, the declaration
of a type parameter now very closely matches the definition of an
ordinary type.

The main consequence is that the rules for assignment need to be
slightly modified: even though a type parameter is an interface,
we cannot simply assign to it per the rules for interfaces: the
type parameter's type is fixed for the instantiation and we need
to reflect that accordingly when checking for assignability.

This CL does not enable the new mode, it implements it in parallel
to the existing mode; the internal flag tparamIsIface is used to
switch between the modes.

The changes to the code are numerous, but straight-forward: when-
ever we deal with an underlying type that might be a type parameter
(or newly, an interface), we need to act slightly differently. For
the time being this leads to some code duplication because the code
supports both modes.

While some of the code for the new mode seems more complicated
(e.g., when we have an interface, the code checks that it is not
the underlying type of a type parameter), in reality many of the
extra checks are redundant and only present because of an abundance
of caution: interfaces with specific type sets are not permitted as
types for ordinary variables, and so even if we were to hit those
cases w/o excluding type parameters the behavior would be the same.

Runs all tests with tparamIsIface enabled and disabled.
Current setting: disabled.

Change-Id: I7bb6453f4fe2569d92face222058fb4e17b12f25
Reviewed-on: https://go-review.googlesource.com/c/go/+/359016
Trust: Robert Griesemer 
Run-TryBot: Robert Griesemer 
TryBot-Result: Go Bot 
Reviewed-by: Robert Findley 
---
 .../compile/internal/types2/assignments.go    |  2 +-
 src/cmd/compile/internal/types2/builtins.go   | 30 ++++++-
 src/cmd/compile/internal/types2/call.go       |  2 +-
 .../compile/internal/types2/conversions.go    | 16 ++--
 src/cmd/compile/internal/types2/expr.go       | 30 ++++++-
 src/cmd/compile/internal/types2/index.go      | 86 +++++++++++++++++++
 src/cmd/compile/internal/types2/lookup.go     |  6 +-
 src/cmd/compile/internal/types2/operand.go    |  9 +-
 src/cmd/compile/internal/types2/predicates.go | 27 ++++--
 src/cmd/compile/internal/types2/sizes.go      |  1 +
 src/cmd/compile/internal/types2/struct.go     |  9 +-
 src/cmd/compile/internal/types2/type.go       |  9 +-
 src/cmd/compile/internal/types2/typeparam.go  | 23 ++++-
 src/cmd/compile/internal/types2/typeset.go    |  4 +
 src/cmd/compile/internal/types2/typexpr.go    | 11 ++-
 15 files changed, 226 insertions(+), 39 deletions(-)

diff --git a/src/cmd/compile/internal/types2/assignments.go b/src/cmd/compile/internal/types2/assignments.go
index da7f7dfa5c..a3d32093d6 100644
--- a/src/cmd/compile/internal/types2/assignments.go
+++ b/src/cmd/compile/internal/types2/assignments.go
@@ -43,7 +43,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
 				x.mode = invalid
 				return
 			}
-		} else if T == nil || IsInterface(T) {
+		} else if T == nil || IsInterface(T) && !isTypeParam(T) {
 			target = Default(x.typ)
 		}
 		newType, val, code := check.implicitTypeAndValue(x, target)
diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go
index 99fe440340..c4b897e80f 100644
--- a/src/cmd/compile/internal/types2/builtins.go
+++ b/src/cmd/compile/internal/types2/builtins.go
@@ -178,7 +178,28 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
 				mode = value
 			}
 
+		case *Interface:
+			if tparamIsIface && isTypeParam(x.typ) {
+				if t.typeSet().underIs(func(t Type) bool {
+					switch t := arrayPtrDeref(t).(type) {
+					case *Basic:
+						if isString(t) && id == _Len {
+							return true
+						}
+					case *Array, *Slice, *Chan:
+						return true
+					case *Map:
+						if id == _Len {
+							return true
+						}
+					}
+					return false
+				}) {
+					mode = value
+				}
+			}
 		case *TypeParam:
+			assert(!tparamIsIface)
 			if t.underIs(func(t Type) bool {
 				switch t := arrayPtrDeref(t).(type) {
 				case *Basic:
@@ -788,16 +809,19 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
 
 // hasVarSize reports if the size of type t is variable due to type parameters.
 func hasVarSize(t Type) bool {
-	switch t := under(t).(type) {
+	switch u := under(t).(type) {
 	case *Array:
-		return hasVarSize(t.elem)
+		return hasVarSize(u.elem)
 	case *Struct:
-		for _, f := range t.fields {
+		for _, f := range u.fields {
 			if hasVarSize(f.typ) {
 				return true
 			}
 		}
+	case *Interface:
+		return isTypeParam(t)
 	case *TypeParam:
+		assert(!tparamIsIface)
 		return true
 	case *Named, *Union:
 		unreachable()
diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go
index b778d54b32..fef493b2ae 100644
--- a/src/cmd/compile/internal/types2/call.go
+++ b/src/cmd/compile/internal/types2/call.go
@@ -132,7 +132,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind {
 		case 1:
 			check.expr(x, call.ArgList[0])
 			if x.mode != invalid {
-				if t, _ := under(T).(*Interface); t != nil {
+				if t, _ := under(T).(*Interface); t != nil && !isTypeParam(T) {
 					if !t.IsMethodSet() {
 						check.errorf(call, "cannot use interface %s in conversion (contains specific type constraints or is comparable)", T)
 						break
diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go
index cc7b52099c..47f9ac0a5a 100644
--- a/src/cmd/compile/internal/types2/conversions.go
+++ b/src/cmd/compile/internal/types2/conversions.go
@@ -102,7 +102,7 @@ func (check *Checker) conversion(x *operand, T Type) {
 		//   (See also the TODO below.)
 		if x.typ == Typ[UntypedNil] {
 			// ok
-		} else if IsInterface(T) || constArg && !isConstType(T) {
+		} else if IsInterface(T) && !isTypeParam(T) || constArg && !isConstType(T) {
 			final = Default(x.typ)
 		} else if isInteger(x.typ) && allString(T) {
 			final = x.typ
@@ -133,19 +133,23 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool {
 		return true
 	}
 
-	// "V and T have identical underlying types if tags are ignored"
+	// "V and T have identical underlying types if tags are ignored
+	// and V and T are not type parameters"
 	V := x.typ
 	Vu := under(V)
 	Tu := under(T)
-	if IdenticalIgnoreTags(Vu, Tu) {
+	Vp, _ := V.(*TypeParam)
+	Tp, _ := T.(*TypeParam)
+	if IdenticalIgnoreTags(Vu, Tu) && Vp == nil && Tp == nil {
 		return true
 	}
 
 	// "V and T are unnamed pointer types and their pointer base types
-	// have identical underlying types if tags are ignored"
+	// have identical underlying types if tags are ignored
+	// and their pointer base types are not type parameters"
 	if V, ok := V.(*Pointer); ok {
 		if T, ok := T.(*Pointer); ok {
-			if IdenticalIgnoreTags(under(V.base), under(T.base)) {
+			if IdenticalIgnoreTags(under(V.base), under(T.base)) && !isTypeParam(V.base) && !isTypeParam(T.base) {
 				return true
 			}
 		}
@@ -204,8 +208,6 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool {
 	}
 
 	// optimization: if we don't have type parameters, we're done
-	Vp, _ := V.(*TypeParam)
-	Tp, _ := T.(*TypeParam)
 	if Vp == nil && Tp == nil {
 		return false
 	}
diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go
index 77e497b9cc..d72ee8c340 100644
--- a/src/cmd/compile/internal/types2/expr.go
+++ b/src/cmd/compile/internal/types2/expr.go
@@ -658,7 +658,11 @@ func (check *Checker) updateExprVal(x syntax.Expr, val constant.Value) {
 func (check *Checker) convertUntyped(x *operand, target Type) {
 	newType, val, code := check.implicitTypeAndValue(x, target)
 	if code != 0 {
-		check.invalidConversion(code, x, safeUnderlying(target))
+		t := target
+		if !tparamIsIface || !isTypeParam(target) {
+			t = safeUnderlying(target)
+		}
+		check.invalidConversion(code, x, t)
 		x.mode = invalid
 		return
 	}
@@ -739,6 +743,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const
 		}
 	case *TypeParam:
 		// TODO(gri) review this code - doesn't look quite right
+		assert(!tparamIsIface)
 		ok := u.underIs(func(t Type) bool {
 			if t == nil {
 				return false
@@ -750,6 +755,20 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const
 			return nil, nil, _InvalidUntypedConversion
 		}
 	case *Interface:
+		if tparamIsIface && isTypeParam(target) {
+			// TODO(gri) review this code - doesn't look quite right
+			ok := u.typeSet().underIs(func(t Type) bool {
+				if t == nil {
+					return false
+				}
+				target, _, _ := check.implicitTypeAndValue(x, t)
+				return target != nil
+			})
+			if !ok {
+				return nil, nil, _InvalidUntypedConversion
+			}
+			break
+		}
 		// Update operand types to the default type rather than the target
 		// (interface) type: values must have concrete dynamic types.
 		// Untyped nil was handled upfront.
@@ -989,8 +1008,9 @@ func (check *Checker) binary(x *operand, e syntax.Expr, lhs, rhs syntax.Expr, op
 		return
 	}
 
+	// TODO(gri) make canMix more efficient - called for each binary operation
 	canMix := func(x, y *operand) bool {
-		if IsInterface(x.typ) || IsInterface(y.typ) {
+		if IsInterface(x.typ) && !isTypeParam(x.typ) || IsInterface(y.typ) && !isTypeParam(y.typ) {
 			return true
 		}
 		if allBoolean(x.typ) != allBoolean(y.typ) {
@@ -1248,7 +1268,11 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
 		case hint != nil:
 			// no composite literal type present - use hint (element type of enclosing type)
 			typ = hint
-			base, _ = deref(under(typ)) // *T implies &T{}
+			base = typ
+			if !isTypeParam(typ) {
+				base = under(typ)
+			}
+			base, _ = deref(base) // *T implies &T{}
 
 		default:
 			// TODO(gri) provide better error messages depending on context
diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go
index 10fb57c321..97d153dfe4 100644
--- a/src/cmd/compile/internal/types2/index.go
+++ b/src/cmd/compile/internal/types2/index.go
@@ -99,8 +99,94 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo
 		x.expr = e
 		return false
 
+	case *Interface:
+		// Note: The body of this 'if' statement is the same as the body
+		//       of the case for type parameters below. If we keep both
+		//       these branches we should factor out the code.
+		if tparamIsIface && isTypeParam(x.typ) {
+			// TODO(gri) report detailed failure cause for better error messages
+			var key, elem Type // key != nil: we must have all maps
+			mode := variable   // non-maps result mode
+			// TODO(gri) factor out closure and use it for non-typeparam cases as well
+			if typ.typeSet().underIs(func(u Type) bool {
+				l := int64(-1) // valid if >= 0
+				var k, e Type  // k is only set for maps
+				switch t := u.(type) {
+				case *Basic:
+					if isString(t) {
+						e = universeByte
+						mode = value
+					}
+				case *Array:
+					l = t.len
+					e = t.elem
+					if x.mode != variable {
+						mode = value
+					}
+				case *Pointer:
+					if t, _ := under(t.base).(*Array); t != nil {
+						l = t.len
+						e = t.elem
+					}
+				case *Slice:
+					e = t.elem
+				case *Map:
+					k = t.key
+					e = t.elem
+				}
+				if e == nil {
+					return false
+				}
+				if elem == nil {
+					// first type
+					length = l
+					key, elem = k, e
+					return true
+				}
+				// all map keys must be identical (incl. all nil)
+				// (that is, we cannot mix maps with other types)
+				if !Identical(key, k) {
+					return false
+				}
+				// all element types must be identical
+				if !Identical(elem, e) {
+					return false
+				}
+				// track the minimal length for arrays, if any
+				if l >= 0 && l < length {
+					length = l
+				}
+				return true
+			}) {
+				// For maps, the index expression must be assignable to the map key type.
+				if key != nil {
+					index := check.singleIndex(e)
+					if index == nil {
+						x.mode = invalid
+						return false
+					}
+					var k operand
+					check.expr(&k, index)
+					check.assignment(&k, key, "map index")
+					// ok to continue even if indexing failed - map element type is known
+					x.mode = mapindex
+					x.typ = elem
+					x.expr = e
+					return false
+				}
+
+				// no maps
+				valid = true
+				x.mode = mode
+				x.typ = elem
+			}
+		}
 	case *TypeParam:
+		// Note: The body of this case is the same as the body of the 'if'
+		//       statement in the interface case above. If we keep both
+		//       these branches we should factor out the code.
 		// TODO(gri) report detailed failure cause for better error messages
+		assert(!tparamIsIface)
 		var key, elem Type // key != nil: we must have all maps
 		mode := variable   // non-maps result mode
 		// TODO(gri) factor out closure and use it for non-typeparam cases as well
diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go
index 8ed5ca837a..cf6c6c7111 100644
--- a/src/cmd/compile/internal/types2/lookup.go
+++ b/src/cmd/compile/internal/types2/lookup.go
@@ -451,11 +451,11 @@ func (check *Checker) missingMethodReason(V, T Type, m, wrongType *Func) string
 		// an extra formatting option for types2.Type that doesn't print out
 		// 'func'.
 		r = strings.Replace(r, "^^func", "", -1)
-	} else if IsInterface(T) {
+	} else if IsInterface(T) && !isTypeParam(T) {
 		if isInterfacePtr(V) {
 			r = fmt.Sprintf("(%s is pointer to interface, not interface)", V)
 		}
-	} else if isInterfacePtr(T) {
+	} else if isInterfacePtr(T) && !isTypeParam(T) {
 		r = fmt.Sprintf("(%s is pointer to interface, not interface)", T)
 	}
 	if r == "" {
@@ -466,7 +466,7 @@ func (check *Checker) missingMethodReason(V, T Type, m, wrongType *Func) string
 
 func isInterfacePtr(T Type) bool {
 	p, _ := under(T).(*Pointer)
-	return p != nil && IsInterface(p.base)
+	return p != nil && IsInterface(p.base) && !isTypeParam(p.base)
 }
 
 // assertableTo reports whether a value of type V can be asserted to have type T.
diff --git a/src/cmd/compile/internal/types2/operand.go b/src/cmd/compile/internal/types2/operand.go
index fee154a6bb..8a905f3fd0 100644
--- a/src/cmd/compile/internal/types2/operand.go
+++ b/src/cmd/compile/internal/types2/operand.go
@@ -282,13 +282,14 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er
 	// Vu is typed
 
 	// x's type V and T have identical underlying types
-	// and at least one of V or T is not a named type.
-	if Identical(Vu, Tu) && (!hasName(V) || !hasName(T)) {
+	// and at least one of V or T is not a named type
+	// and neither V nor T is a type parameter.
+	if Identical(Vu, Tu) && (!hasName(V) || !hasName(T)) && Vp == nil && Tp == nil {
 		return true, 0
 	}
 
 	// T is an interface type and x implements T and T is not a type parameter
-	if Ti, ok := Tu.(*Interface); ok {
+	if Ti, ok := Tu.(*Interface); ok && Tp == nil {
 		if m, wrongType := check.missingMethod(V, Ti, true); m != nil /* !Implements(V, Ti) */ {
 			if reason != nil {
 				if check.conf.CompilerErrorMessages {
@@ -318,7 +319,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er
 			*reason = check.sprintf("%s does not implement %s (%s is pointer to interface, not interface)", x.typ, T, T)
 			return false, _InvalidIfaceAssign
 		}
-		if Vi, _ := Vu.(*Interface); Vi != nil {
+		if Vi, _ := Vu.(*Interface); Vi != nil && Vp == nil {
 			if m, _ := check.missingMethod(T, Vi, true); m == nil {
 				// T implements Vi, so give hint about type assertion.
 				if reason != nil {
diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go
index ab490372fc..62db3861ed 100644
--- a/src/cmd/compile/internal/types2/predicates.go
+++ b/src/cmd/compile/internal/types2/predicates.go
@@ -47,13 +47,10 @@ func allNumericOrString(t Type) bool { return allBasic(t, IsNumeric|IsString) }
 // for all specific types of the type parameter's type set.
 // allBasic(t, info) is an optimized version of isBasic(structuralType(t), info).
 func allBasic(t Type, info BasicInfo) bool {
-	switch u := under(t).(type) {
-	case *Basic:
-		return u.info&info != 0
-	case *TypeParam:
-		return u.is(func(t *term) bool { return t != nil && isBasic(t.typ, info) })
+	if tpar, _ := t.(*TypeParam); tpar != nil {
+		return tpar.is(func(t *term) bool { return t != nil && isBasic(t.typ, info) })
 	}
-	return false
+	return isBasic(t, info)
 }
 
 // hasName reports whether t has a name. This includes
@@ -122,7 +119,7 @@ func comparable(T Type, seen map[Type]bool) bool {
 		// assume invalid types to be comparable
 		// to avoid follow-up errors
 		return t.kind != UntypedNil
-	case *Pointer, *Interface, *Chan:
+	case *Pointer, *Chan:
 		return true
 	case *Struct:
 		for _, f := range t.fields {
@@ -133,7 +130,13 @@ func comparable(T Type, seen map[Type]bool) bool {
 		return true
 	case *Array:
 		return comparable(t.elem, seen)
+	case *Interface:
+		if tparamIsIface && isTypeParam(T) {
+			return t.IsComparable()
+		}
+		return true
 	case *TypeParam:
+		assert(!tparamIsIface)
 		return t.iface().IsComparable()
 	}
 	return false
@@ -144,9 +147,17 @@ func hasNil(t Type) bool {
 	switch u := under(t).(type) {
 	case *Basic:
 		return u.kind == UnsafePointer
-	case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan:
+	case *Slice, *Pointer, *Signature, *Map, *Chan:
+		return true
+	case *Interface:
+		if tparamIsIface && isTypeParam(t) {
+			return u.typeSet().underIs(func(u Type) bool {
+				return u != nil && hasNil(u)
+			})
+		}
 		return true
 	case *TypeParam:
+		assert(!tparamIsIface)
 		return u.underIs(func(u Type) bool {
 			return u != nil && hasNil(u)
 		})
diff --git a/src/cmd/compile/internal/types2/sizes.go b/src/cmd/compile/internal/types2/sizes.go
index 609b6f585e..b23cec435d 100644
--- a/src/cmd/compile/internal/types2/sizes.go
+++ b/src/cmd/compile/internal/types2/sizes.go
@@ -67,6 +67,7 @@ func (s *StdSizes) Alignof(T Type) int64 {
 	case *Slice, *Interface:
 		// Multiword data structures are effectively structs
 		// in which each element has size WordSize.
+		assert(!tparamIsIface || !isTypeParam(T))
 		return s.WordSize
 	case *Basic:
 		// Strings are like slices and interfaces.
diff --git a/src/cmd/compile/internal/types2/struct.go b/src/cmd/compile/internal/types2/struct.go
index 8c39f5e3c4..3e271039d1 100644
--- a/src/cmd/compile/internal/types2/struct.go
+++ b/src/cmd/compile/internal/types2/struct.go
@@ -144,21 +144,26 @@ func (check *Checker) structType(styp *Struct, e *syntax.StructType) {
 			embeddedPos := pos
 			check.later(func() {
 				t, isPtr := deref(embeddedTyp)
-				switch t := under(t).(type) {
+				switch u := under(t).(type) {
 				case *Basic:
 					if t == Typ[Invalid] {
 						// error was reported before
 						return
 					}
 					// unsafe.Pointer is treated like a regular pointer
-					if t.kind == UnsafePointer {
+					if u.kind == UnsafePointer {
 						check.error(embeddedPos, "embedded field type cannot be unsafe.Pointer")
 					}
 				case *Pointer:
 					check.error(embeddedPos, "embedded field type cannot be a pointer")
 				case *TypeParam:
+					assert(!tparamIsIface)
 					check.error(embeddedPos, "embedded field type cannot be a (pointer to a) type parameter")
 				case *Interface:
+					if tparamIsIface && isTypeParam(t) {
+						check.error(embeddedPos, "embedded field type cannot be a (pointer to a) type parameter")
+						break
+					}
 					if isPtr {
 						check.error(embeddedPos, "embedded field type cannot be a pointer to an interface")
 					}
diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go
index ba260d2b7d..77dc7db896 100644
--- a/src/cmd/compile/internal/types2/type.go
+++ b/src/cmd/compile/internal/types2/type.go
@@ -21,8 +21,13 @@ type Type interface {
 // under must only be called when a type is known
 // to be fully set up.
 func under(t Type) Type {
-	if n := asNamed(t); n != nil {
-		return n.under()
+	switch t := t.(type) {
+	case *Named:
+		return t.under()
+	case *TypeParam:
+		if tparamIsIface {
+			return t.iface()
+		}
 	}
 	return t
 }
diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go
index 099bc429c3..e430319476 100644
--- a/src/cmd/compile/internal/types2/typeparam.go
+++ b/src/cmd/compile/internal/types2/typeparam.go
@@ -6,6 +6,12 @@ package types2
 
 import "sync/atomic"
 
+// If set, the underlying type of a type parameter is
+// is the underlying type of its type constraint, i.e.,
+// an interface. With that, a type parameter satisfies
+// isInterface.
+const tparamIsIface = false
+
 // Note: This is a uint32 rather than a uint64 because the
 // respective 64 bit atomic instructions are not available
 // on all platforms.
@@ -69,13 +75,21 @@ func (t *TypeParam) SetConstraint(bound Type) {
 	t.bound = bound
 }
 
-func (t *TypeParam) Underlying() Type { return t }
-func (t *TypeParam) String() string   { return TypeString(t, nil) }
+func (t *TypeParam) Underlying() Type {
+	if tparamIsIface {
+		return t.iface()
+	}
+	return t
+}
+
+func (t *TypeParam) String() string { return TypeString(t, nil) }
 
 // ----------------------------------------------------------------------------
 // Implementation
 
 // iface returns the constraint interface of t.
+// TODO(gri) If we make tparamIsIface the default, this should be renamed to under
+//           (similar to Named.under).
 func (t *TypeParam) iface() *Interface {
 	bound := t.bound
 
@@ -88,8 +102,13 @@ func (t *TypeParam) iface() *Interface {
 			return &emptyInterface
 		}
 	case *Interface:
+		if tparamIsIface && isTypeParam(bound) {
+			// error is reported in Checker.collectTypeParams
+			return &emptyInterface
+		}
 		ityp = u
 	case *TypeParam:
+		assert(!tparamIsIface)
 		// error is reported in Checker.collectTypeParams
 		return &emptyInterface
 	}
diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go
index 882f387c3c..54a8266838 100644
--- a/src/cmd/compile/internal/types2/typeset.go
+++ b/src/cmd/compile/internal/types2/typeset.go
@@ -268,6 +268,8 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_
 		var terms termlist
 		switch u := under(typ).(type) {
 		case *Interface:
+			// For now we don't permit type parameters as constraints.
+			assert(!isTypeParam(typ))
 			tset := computeInterfaceTypeSet(check, pos, u)
 			// If typ is local, an error was already reported where typ is specified/defined.
 			if check != nil && check.isImportedConstraint(typ) && !check.allowVersion(check.pkg, 1, 18) {
@@ -367,6 +369,8 @@ func computeUnionTypeSet(check *Checker, pos syntax.Pos, utyp *Union) *_TypeSet
 		var terms termlist
 		switch u := under(t.typ).(type) {
 		case *Interface:
+			// For now we don't permit type parameters as constraints.
+			assert(!isTypeParam(t.typ))
 			terms = computeInterfaceTypeSet(check, pos, u).terms
 		default:
 			if t.typ == Typ[Invalid] {
diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go
index a2585179ee..e22b1ff0a0 100644
--- a/src/cmd/compile/internal/types2/typexpr.go
+++ b/src/cmd/compile/internal/types2/typexpr.go
@@ -144,9 +144,14 @@ func (check *Checker) typ(e syntax.Expr) Type {
 func (check *Checker) varType(e syntax.Expr) Type {
 	typ := check.definedType(e, nil)
 
-	// We don't want to call under() (via toInterface) or complete interfaces while we
-	// are in the middle of type-checking parameter declarations that might belong to
-	// interface methods. Delay this check to the end of type-checking.
+	// If we have a type parameter there's nothing to do.
+	if isTypeParam(typ) {
+		return typ
+	}
+
+	// We don't want to call under() or complete interfaces while we are in
+	// the middle of type-checking parameter declarations that might belong
+	// to interface methods. Delay this check to the end of type-checking.
 	check.later(func() {
 		if t, _ := under(typ).(*Interface); t != nil {
 			pos := syntax.StartPos(e)
-- 
GitLab


From c09d854f0961a997ac41a740a6e8d1892b7e6ee0 Mon Sep 17 00:00:00 2001
From: Robert Griesemer 
Date: Wed, 10 Nov 2021 15:50:35 -0800
Subject: [PATCH 2158/2500] cmd/compile/internal/types2: set tparamsIsIface to
 true

This CL enables the mode in which the underlying type of
type parameters is the underlying type of their constraints.

Change-Id: Id3471578dab098695dbd1e0429356ebcc9c5e224
Reviewed-on: https://go-review.googlesource.com/c/go/+/363155
Trust: Robert Griesemer 
Run-TryBot: Robert Griesemer 
TryBot-Result: Go Bot 
Reviewed-by: Robert Findley 
---
 src/cmd/compile/internal/types2/typeparam.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go
index e430319476..5499d975a1 100644
--- a/src/cmd/compile/internal/types2/typeparam.go
+++ b/src/cmd/compile/internal/types2/typeparam.go
@@ -10,7 +10,7 @@ import "sync/atomic"
 // is the underlying type of its type constraint, i.e.,
 // an interface. With that, a type parameter satisfies
 // isInterface.
-const tparamIsIface = false
+const tparamIsIface = true
 
 // Note: This is a uint32 rather than a uint64 because the
 // respective 64 bit atomic instructions are not available
-- 
GitLab


From 56e55a388986ed9c770a21e9c58df38e021b577b Mon Sep 17 00:00:00 2001
From: Robert Griesemer 
Date: Thu, 11 Nov 2021 17:32:15 -0800
Subject: [PATCH 2159/2500] cmd/compile/internal/types2: remove a review
 comment in implicitTypeAndValue

Reviewed the code and simplified slightly. No semantic changes.

Change-Id: Ib785b912fbee97746324af87ac0c14a4bdb69477
Reviewed-on: https://go-review.googlesource.com/c/go/+/363440
Trust: Robert Griesemer 
Run-TryBot: Robert Griesemer 
Reviewed-by: Robert Findley 
---
 src/cmd/compile/internal/types2/expr.go | 24 ++++++++++--------------
 1 file changed, 10 insertions(+), 14 deletions(-)

diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go
index d72ee8c340..6faa54475b 100644
--- a/src/cmd/compile/internal/types2/expr.go
+++ b/src/cmd/compile/internal/types2/expr.go
@@ -742,29 +742,25 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const
 			return nil, nil, _InvalidUntypedConversion
 		}
 	case *TypeParam:
-		// TODO(gri) review this code - doesn't look quite right
 		assert(!tparamIsIface)
-		ok := u.underIs(func(t Type) bool {
-			if t == nil {
+		if !u.underIs(func(u Type) bool {
+			if u == nil {
 				return false
 			}
-			target, _, _ := check.implicitTypeAndValue(x, t)
-			return target != nil
-		})
-		if !ok {
+			t, _, _ := check.implicitTypeAndValue(x, u)
+			return t != nil
+		}) {
 			return nil, nil, _InvalidUntypedConversion
 		}
 	case *Interface:
 		if tparamIsIface && isTypeParam(target) {
-			// TODO(gri) review this code - doesn't look quite right
-			ok := u.typeSet().underIs(func(t Type) bool {
-				if t == nil {
+			if !u.typeSet().underIs(func(u Type) bool {
+				if u == nil {
 					return false
 				}
-				target, _, _ := check.implicitTypeAndValue(x, t)
-				return target != nil
-			})
-			if !ok {
+				t, _, _ := check.implicitTypeAndValue(x, u)
+				return t != nil
+			}) {
 				return nil, nil, _InvalidUntypedConversion
 			}
 			break
-- 
GitLab


From bc0b98eeffa64f155e7f2a2dc6b883a97c4d0580 Mon Sep 17 00:00:00 2001
From: Robert Griesemer 
Date: Thu, 11 Nov 2021 22:21:48 -0800
Subject: [PATCH 2160/2500] cmd/compile/internal/types2: remove asNamed

In the few remaining places where we use asNamed, if the argument
is indeed a *Named, we either don't need to look "inside" it, or
we call under() (which calls Named.underlying() which does resolve);
so there's no need for an implicit resolution (which was done by
asNamed). The only place where we do need to resolve is in lookup,
so added the explicit resolve call in that case.

Change-Id: Iff0a19fde7581e94149e89b9e48157c1981db105
Reviewed-on: https://go-review.googlesource.com/c/go/+/363441
Trust: Robert Griesemer 
Run-TryBot: Robert Griesemer 
TryBot-Result: Go Bot 
Reviewed-by: Robert Findley 
---
 src/cmd/compile/internal/types2/decl.go     |  2 +-
 src/cmd/compile/internal/types2/lookup.go   |  7 ++++---
 src/cmd/compile/internal/types2/type.go     |  9 ---------
 src/cmd/compile/internal/types2/unify.go    | 14 ++++++--------
 src/cmd/compile/internal/types2/universe.go |  2 +-
 5 files changed, 12 insertions(+), 22 deletions(-)

diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go
index bab90fbd9a..d58fac5dbb 100644
--- a/src/cmd/compile/internal/types2/decl.go
+++ b/src/cmd/compile/internal/types2/decl.go
@@ -727,7 +727,7 @@ func (check *Checker) collectMethods(obj *TypeName) {
 
 	// spec: "If the base type is a struct type, the non-blank method
 	// and field names must be distinct."
-	base := asNamed(obj.typ) // shouldn't fail but be conservative
+	base, _ := obj.typ.(*Named) // shouldn't fail but be conservative
 	if base != nil {
 		u := base.under()
 		if t, _ := u.(*Struct); t != nil {
diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go
index cf6c6c7111..fbfe3c81ff 100644
--- a/src/cmd/compile/internal/types2/lookup.go
+++ b/src/cmd/compile/internal/types2/lookup.go
@@ -50,8 +50,8 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
 	// Thus, if we have a named pointer type, proceed with the underlying
 	// pointer type but discard the result if it is a method since we would
 	// not have found it for T (see also issue 8590).
-	if t := asNamed(T); t != nil {
-		if p, _ := safeUnderlying(t).(*Pointer); p != nil {
+	if t, _ := T.(*Named); t != nil {
+		if p, _ := t.Underlying().(*Pointer); p != nil {
 			obj, index, indirect = lookupFieldOrMethod(p, false, false, pkg, name)
 			if _, ok := obj.(*Func); ok {
 				return nil, nil, false
@@ -114,7 +114,7 @@ func lookupFieldOrMethod(T Type, addressable, checkFold bool, pkg *Package, name
 
 			// If we have a named type, we may have associated methods.
 			// Look for those first.
-			if named := asNamed(typ); named != nil {
+			if named, _ := typ.(*Named); named != nil {
 				if seen[named] {
 					// We have seen this type before, at a more shallow depth
 					// (note that multiples of this type at the current depth
@@ -129,6 +129,7 @@ func lookupFieldOrMethod(T Type, addressable, checkFold bool, pkg *Package, name
 				seen[named] = true
 
 				// look for a matching attached method
+				named.resolve(nil)
 				if i, m := lookupMethodFold(named.methods, pkg, name, checkFold); m != nil {
 					// potential match
 					// caution: method may not have a proper signature yet
diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go
index 77dc7db896..3fea8d1776 100644
--- a/src/cmd/compile/internal/types2/type.go
+++ b/src/cmd/compile/internal/types2/type.go
@@ -87,12 +87,3 @@ func structuralType(typ Type) Type {
 	}
 	return nil
 }
-
-// If t is a defined type, asNamed returns that type (possibly after resolving it), otherwise it returns nil.
-func asNamed(t Type) *Named {
-	e, _ := t.(*Named)
-	if e != nil {
-		e.resolve(nil)
-	}
-	return e
-}
diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go
index 7f636c30d3..ccb6ee8709 100644
--- a/src/cmd/compile/internal/types2/unify.go
+++ b/src/cmd/compile/internal/types2/unify.go
@@ -235,14 +235,12 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool {
 		// If exact unification is known to fail because we attempt to
 		// match a type name against an unnamed type literal, consider
 		// the underlying type of the named type.
-		// (Subtle: We use hasName to include any type with a name (incl.
-		// basic types and type parameters. We use asNamed because we only
-		// want *Named types.)
-		switch {
-		case !hasName(x) && y != nil && asNamed(y) != nil:
-			return u.nify(x, under(y), p)
-		case x != nil && asNamed(x) != nil && !hasName(y):
-			return u.nify(under(x), y, p)
+		// (We use !hasName to exclude any type with a name, including
+		// basic types and type parameters; the rest are unamed types.)
+		if nx, _ := x.(*Named); nx != nil && !hasName(y) {
+			return u.nify(nx.under(), y, p)
+		} else if ny, _ := y.(*Named); ny != nil && !hasName(x) {
+			return u.nify(x, ny.under(), p)
 		}
 	}
 
diff --git a/src/cmd/compile/internal/types2/universe.go b/src/cmd/compile/internal/types2/universe.go
index 92fa32524c..fccab145f8 100644
--- a/src/cmd/compile/internal/types2/universe.go
+++ b/src/cmd/compile/internal/types2/universe.go
@@ -240,7 +240,7 @@ func def(obj Object) {
 		return // nothing to do
 	}
 	// fix Obj link for named types
-	if typ := asNamed(obj.Type()); typ != nil {
+	if typ, _ := obj.Type().(*Named); typ != nil {
 		typ.obj = obj.(*TypeName)
 	}
 	// exported identifiers go into package unsafe
-- 
GitLab


From 787708a6ff66092678cd4312358e90a5085eac89 Mon Sep 17 00:00:00 2001
From: Robert Griesemer 
Date: Fri, 12 Nov 2021 08:59:49 -0800
Subject: [PATCH 2161/2500] cmd/compile/internal/types2: remove tparamIsIface
 flag and corresponding dead code

Added/clarified some comments.

Change-Id: Ib08d3343ff08c23cc8880a27a0148d1ff077a80f
Reviewed-on: https://go-review.googlesource.com/c/go/+/363654
Trust: Robert Griesemer 
Run-TryBot: Robert Griesemer 
TryBot-Result: Go Bot 
Reviewed-by: Robert Findley 
---
 src/cmd/compile/internal/types2/builtins.go   | 27 +-----
 src/cmd/compile/internal/types2/decl.go       |  4 +
 src/cmd/compile/internal/types2/expr.go       | 15 +---
 src/cmd/compile/internal/types2/index.go      | 89 +------------------
 src/cmd/compile/internal/types2/predicates.go | 18 +---
 src/cmd/compile/internal/types2/sizes.go      |  7 +-
 src/cmd/compile/internal/types2/struct.go     |  5 +-
 src/cmd/compile/internal/types2/type.go       |  4 +-
 src/cmd/compile/internal/types2/typeparam.go  | 17 +---
 9 files changed, 24 insertions(+), 162 deletions(-)

diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go
index c4b897e80f..5b4ffd0dad 100644
--- a/src/cmd/compile/internal/types2/builtins.go
+++ b/src/cmd/compile/internal/types2/builtins.go
@@ -179,28 +179,10 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
 			}
 
 		case *Interface:
-			if tparamIsIface && isTypeParam(x.typ) {
-				if t.typeSet().underIs(func(t Type) bool {
-					switch t := arrayPtrDeref(t).(type) {
-					case *Basic:
-						if isString(t) && id == _Len {
-							return true
-						}
-					case *Array, *Slice, *Chan:
-						return true
-					case *Map:
-						if id == _Len {
-							return true
-						}
-					}
-					return false
-				}) {
-					mode = value
-				}
+			if !isTypeParam(x.typ) {
+				break
 			}
-		case *TypeParam:
-			assert(!tparamIsIface)
-			if t.underIs(func(t Type) bool {
+			if t.typeSet().underIs(func(t Type) bool {
 				switch t := arrayPtrDeref(t).(type) {
 				case *Basic:
 					if isString(t) && id == _Len {
@@ -820,9 +802,6 @@ func hasVarSize(t Type) bool {
 		}
 	case *Interface:
 		return isTypeParam(t)
-	case *TypeParam:
-		assert(!tparamIsIface)
-		return true
 	case *Named, *Union:
 		unreachable()
 	}
diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go
index d58fac5dbb..739fc163de 100644
--- a/src/cmd/compile/internal/types2/decl.go
+++ b/src/cmd/compile/internal/types2/decl.go
@@ -673,6 +673,10 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list []*syntax.Fiel
 	check.later(func() {
 		for i, bound := range bounds {
 			if isTypeParam(bound) {
+				// We may be able to allow this since it is now well-defined what
+				// the underlying type and thus type set of a type parameter is.
+				// But we may need some additional form of cycle detection within
+				// type parameter lists.
 				check.error(posers[i], "cannot use a type parameter as constraint")
 			}
 		}
diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go
index 6faa54475b..b700716b0c 100644
--- a/src/cmd/compile/internal/types2/expr.go
+++ b/src/cmd/compile/internal/types2/expr.go
@@ -659,7 +659,7 @@ func (check *Checker) convertUntyped(x *operand, target Type) {
 	newType, val, code := check.implicitTypeAndValue(x, target)
 	if code != 0 {
 		t := target
-		if !tparamIsIface || !isTypeParam(target) {
+		if !isTypeParam(target) {
 			t = safeUnderlying(target)
 		}
 		check.invalidConversion(code, x, t)
@@ -741,19 +741,8 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const
 		default:
 			return nil, nil, _InvalidUntypedConversion
 		}
-	case *TypeParam:
-		assert(!tparamIsIface)
-		if !u.underIs(func(u Type) bool {
-			if u == nil {
-				return false
-			}
-			t, _, _ := check.implicitTypeAndValue(x, u)
-			return t != nil
-		}) {
-			return nil, nil, _InvalidUntypedConversion
-		}
 	case *Interface:
-		if tparamIsIface && isTypeParam(target) {
+		if isTypeParam(target) {
 			if !u.typeSet().underIs(func(u Type) bool {
 				if u == nil {
 					return false
diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go
index 97d153dfe4..648c7abe6f 100644
--- a/src/cmd/compile/internal/types2/index.go
+++ b/src/cmd/compile/internal/types2/index.go
@@ -100,97 +100,14 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo
 		return false
 
 	case *Interface:
-		// Note: The body of this 'if' statement is the same as the body
-		//       of the case for type parameters below. If we keep both
-		//       these branches we should factor out the code.
-		if tparamIsIface && isTypeParam(x.typ) {
-			// TODO(gri) report detailed failure cause for better error messages
-			var key, elem Type // key != nil: we must have all maps
-			mode := variable   // non-maps result mode
-			// TODO(gri) factor out closure and use it for non-typeparam cases as well
-			if typ.typeSet().underIs(func(u Type) bool {
-				l := int64(-1) // valid if >= 0
-				var k, e Type  // k is only set for maps
-				switch t := u.(type) {
-				case *Basic:
-					if isString(t) {
-						e = universeByte
-						mode = value
-					}
-				case *Array:
-					l = t.len
-					e = t.elem
-					if x.mode != variable {
-						mode = value
-					}
-				case *Pointer:
-					if t, _ := under(t.base).(*Array); t != nil {
-						l = t.len
-						e = t.elem
-					}
-				case *Slice:
-					e = t.elem
-				case *Map:
-					k = t.key
-					e = t.elem
-				}
-				if e == nil {
-					return false
-				}
-				if elem == nil {
-					// first type
-					length = l
-					key, elem = k, e
-					return true
-				}
-				// all map keys must be identical (incl. all nil)
-				// (that is, we cannot mix maps with other types)
-				if !Identical(key, k) {
-					return false
-				}
-				// all element types must be identical
-				if !Identical(elem, e) {
-					return false
-				}
-				// track the minimal length for arrays, if any
-				if l >= 0 && l < length {
-					length = l
-				}
-				return true
-			}) {
-				// For maps, the index expression must be assignable to the map key type.
-				if key != nil {
-					index := check.singleIndex(e)
-					if index == nil {
-						x.mode = invalid
-						return false
-					}
-					var k operand
-					check.expr(&k, index)
-					check.assignment(&k, key, "map index")
-					// ok to continue even if indexing failed - map element type is known
-					x.mode = mapindex
-					x.typ = elem
-					x.expr = e
-					return false
-				}
-
-				// no maps
-				valid = true
-				x.mode = mode
-				x.typ = elem
-			}
+		if !isTypeParam(x.typ) {
+			break
 		}
-	case *TypeParam:
-		// Note: The body of this case is the same as the body of the 'if'
-		//       statement in the interface case above. If we keep both
-		//       these branches we should factor out the code.
 		// TODO(gri) report detailed failure cause for better error messages
-		assert(!tparamIsIface)
 		var key, elem Type // key != nil: we must have all maps
 		mode := variable   // non-maps result mode
 		// TODO(gri) factor out closure and use it for non-typeparam cases as well
-		if typ.underIs(func(u Type) bool {
+		if typ.typeSet().underIs(func(u Type) bool {
 			l := int64(-1) // valid if >= 0
 			var k, e Type  // k is only set for maps
 			switch t := u.(type) {
diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go
index 62db3861ed..8ba534ce77 100644
--- a/src/cmd/compile/internal/types2/predicates.go
+++ b/src/cmd/compile/internal/types2/predicates.go
@@ -131,13 +131,7 @@ func comparable(T Type, seen map[Type]bool) bool {
 	case *Array:
 		return comparable(t.elem, seen)
 	case *Interface:
-		if tparamIsIface && isTypeParam(T) {
-			return t.IsComparable()
-		}
-		return true
-	case *TypeParam:
-		assert(!tparamIsIface)
-		return t.iface().IsComparable()
+		return !isTypeParam(T) || t.IsComparable()
 	}
 	return false
 }
@@ -150,15 +144,7 @@ func hasNil(t Type) bool {
 	case *Slice, *Pointer, *Signature, *Map, *Chan:
 		return true
 	case *Interface:
-		if tparamIsIface && isTypeParam(t) {
-			return u.typeSet().underIs(func(u Type) bool {
-				return u != nil && hasNil(u)
-			})
-		}
-		return true
-	case *TypeParam:
-		assert(!tparamIsIface)
-		return u.underIs(func(u Type) bool {
+		return !isTypeParam(t) || u.typeSet().underIs(func(u Type) bool {
 			return u != nil && hasNil(u)
 		})
 	}
diff --git a/src/cmd/compile/internal/types2/sizes.go b/src/cmd/compile/internal/types2/sizes.go
index b23cec435d..6f981964be 100644
--- a/src/cmd/compile/internal/types2/sizes.go
+++ b/src/cmd/compile/internal/types2/sizes.go
@@ -67,7 +67,9 @@ func (s *StdSizes) Alignof(T Type) int64 {
 	case *Slice, *Interface:
 		// Multiword data structures are effectively structs
 		// in which each element has size WordSize.
-		assert(!tparamIsIface || !isTypeParam(T))
+		// Type parameters lead to variable sizes/alignments;
+		// StdSizes.Alignof won't be called for them.
+		assert(!isTypeParam(T))
 		return s.WordSize
 	case *Basic:
 		// Strings are like slices and interfaces.
@@ -152,6 +154,9 @@ func (s *StdSizes) Sizeof(T Type) int64 {
 		offsets := s.Offsetsof(t.fields)
 		return offsets[n-1] + s.Sizeof(t.fields[n-1].typ)
 	case *Interface:
+		// Type parameters lead to variable sizes/alignments;
+		// StdSizes.Sizeof won't be called for them.
+		assert(!isTypeParam(T))
 		return s.WordSize * 2
 	case *TypeParam, *Union:
 		unreachable()
diff --git a/src/cmd/compile/internal/types2/struct.go b/src/cmd/compile/internal/types2/struct.go
index 3e271039d1..31a3b1af5b 100644
--- a/src/cmd/compile/internal/types2/struct.go
+++ b/src/cmd/compile/internal/types2/struct.go
@@ -156,11 +156,8 @@ func (check *Checker) structType(styp *Struct, e *syntax.StructType) {
 					}
 				case *Pointer:
 					check.error(embeddedPos, "embedded field type cannot be a pointer")
-				case *TypeParam:
-					assert(!tparamIsIface)
-					check.error(embeddedPos, "embedded field type cannot be a (pointer to a) type parameter")
 				case *Interface:
-					if tparamIsIface && isTypeParam(t) {
+					if isTypeParam(t) {
 						check.error(embeddedPos, "embedded field type cannot be a (pointer to a) type parameter")
 						break
 					}
diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go
index 3fea8d1776..7fcb196c5a 100644
--- a/src/cmd/compile/internal/types2/type.go
+++ b/src/cmd/compile/internal/types2/type.go
@@ -25,9 +25,7 @@ func under(t Type) Type {
 	case *Named:
 		return t.under()
 	case *TypeParam:
-		if tparamIsIface {
-			return t.iface()
-		}
+		return t.iface()
 	}
 	return t
 }
diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go
index 5499d975a1..8dd04ff408 100644
--- a/src/cmd/compile/internal/types2/typeparam.go
+++ b/src/cmd/compile/internal/types2/typeparam.go
@@ -6,12 +6,6 @@ package types2
 
 import "sync/atomic"
 
-// If set, the underlying type of a type parameter is
-// is the underlying type of its type constraint, i.e.,
-// an interface. With that, a type parameter satisfies
-// isInterface.
-const tparamIsIface = true
-
 // Note: This is a uint32 rather than a uint64 because the
 // respective 64 bit atomic instructions are not available
 // on all platforms.
@@ -76,10 +70,7 @@ func (t *TypeParam) SetConstraint(bound Type) {
 }
 
 func (t *TypeParam) Underlying() Type {
-	if tparamIsIface {
-		return t.iface()
-	}
-	return t
+	return t.iface()
 }
 
 func (t *TypeParam) String() string { return TypeString(t, nil) }
@@ -102,15 +93,11 @@ func (t *TypeParam) iface() *Interface {
 			return &emptyInterface
 		}
 	case *Interface:
-		if tparamIsIface && isTypeParam(bound) {
+		if isTypeParam(bound) {
 			// error is reported in Checker.collectTypeParams
 			return &emptyInterface
 		}
 		ityp = u
-	case *TypeParam:
-		assert(!tparamIsIface)
-		// error is reported in Checker.collectTypeParams
-		return &emptyInterface
 	}
 
 	// If we don't have an interface, wrap constraint into an implicit interface.
-- 
GitLab


From bfbe5ac9ce58fb59aa38ef69dee4933f20aac039 Mon Sep 17 00:00:00 2001
From: Robert Findley 
Date: Tue, 9 Nov 2021 22:31:59 -0500
Subject: [PATCH 2162/2500] go/types: deduplicate signatures with the context

Extend the type checking context to allow de-duplicating *Signature
instances, in addition to *Named instances.

Naively we would deduplicate instances of different-but-identical origin
*Signature types. That may be OK, but it seems a bit strange to get the
same signature when instantiating two different functions. For now,
differentiate *Signature types by prepending a unique identifier for the
origin pointer, thus guaranteeing that instances de-duplicated if they
come from the exact same (pointer identical) origin type.

Updates #47103

Change-Id: I93cc3cacad195267fe0a5801f9c5a3b1e61eb907
Reviewed-on: https://go-review.googlesource.com/c/go/+/362801
Trust: Robert Findley 
Run-TryBot: Robert Findley 
TryBot-Result: Go Bot 
Reviewed-by: Robert Griesemer 
---
 src/go/types/api_test.go         |  14 ++--
 src/go/types/context.go          |  39 +++++-----
 src/go/types/instantiate.go      |  43 ++++++-----
 src/go/types/instantiate_test.go | 118 ++++++++++++++++++++++++-------
 src/go/types/named.go            |   2 +-
 src/go/types/subst.go            |   2 +-
 src/go/types/typestring.go       |   2 +-
 src/go/types/typexpr.go          |   2 +-
 8 files changed, 150 insertions(+), 72 deletions(-)

diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go
index 3e10be5985..c9127f366a 100644
--- a/src/go/types/api_test.go
+++ b/src/go/types/api_test.go
@@ -28,8 +28,12 @@ import (
 // If source begins with "package generic_" and type parameters are enabled,
 // generic code is permitted.
 func pkgFor(path, source string, info *Info) (*Package, error) {
-	fset := token.NewFileSet()
 	mode := modeForSource(source)
+	return pkgForMode(path, source, info, mode)
+}
+
+func pkgForMode(path, source string, info *Info, mode parser.Mode) (*Package, error) {
+	fset := token.NewFileSet()
 	f, err := parser.ParseFile(fset, path, source, mode)
 	if err != nil {
 		return nil, err
@@ -1938,8 +1942,8 @@ func f(x T) T { return foo.F(x) }
 
 func TestInstantiate(t *testing.T) {
 	// eventually we like more tests but this is a start
-	const src = genericPkg + "p; type T[P any] *T[P]"
-	pkg, err := pkgFor(".", src, nil)
+	const src = "package p; type T[P any] *T[P]"
+	pkg, err := pkgForMode(".", src, nil, 0)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -1976,8 +1980,8 @@ func TestInstantiateErrors(t *testing.T) {
 	}
 
 	for _, test := range tests {
-		src := genericPkg + "p; " + test.src
-		pkg, err := pkgFor(".", src, nil)
+		src := "package p; " + test.src
+		pkg, err := pkgForMode(".", src, nil, 0)
 		if err != nil {
 			t.Fatal(err)
 		}
diff --git a/src/go/types/context.go b/src/go/types/context.go
index 1f102f0b8b..ff4bf89f3c 100644
--- a/src/go/types/context.go
+++ b/src/go/types/context.go
@@ -7,6 +7,7 @@ package types
 import (
 	"bytes"
 	"fmt"
+	"strconv"
 	"strings"
 	"sync"
 )
@@ -17,10 +18,10 @@ import (
 //
 // It is safe for concurrent use.
 type Context struct {
-	mu      sync.Mutex
-	typeMap map[string][]ctxtEntry // type hash -> instances entries
-	nextID  int                    // next unique ID
-	seen    map[*Named]int         // assigned unique IDs
+	mu        sync.Mutex
+	typeMap   map[string][]ctxtEntry // type hash -> instances entries
+	nextID    int                    // next unique ID
+	originIDs map[Type]int           // origin type -> unique ID
 }
 
 type ctxtEntry struct {
@@ -32,23 +33,25 @@ type ctxtEntry struct {
 // NewContext creates a new Context.
 func NewContext() *Context {
 	return &Context{
-		typeMap: make(map[string][]ctxtEntry),
-		seen:    make(map[*Named]int),
+		typeMap:   make(map[string][]ctxtEntry),
+		originIDs: make(map[Type]int),
 	}
 }
 
-// typeHash returns a string representation of typ instantiated with targs,
-// which can be used as an exact type hash: types that are identical produce
-// identical string representations. If targs is not empty, typ is printed as
-// if it were instantiated with targs. The result is guaranteed to not contain
-// blanks (" ").
-func (ctxt *Context) typeHash(typ Type, targs []Type) string {
+// instanceHash returns a string representation of typ instantiated with targs.
+// The hash should be a perfect hash, though out of caution the type checker
+// does not assume this. The result is guaranteed to not contain blanks.
+func (ctxt *Context) instanceHash(orig Type, targs []Type) string {
 	assert(ctxt != nil)
-	assert(typ != nil)
+	assert(orig != nil)
 	var buf bytes.Buffer
 
 	h := newTypeHasher(&buf, ctxt)
-	h.typ(typ)
+	h.string(strconv.Itoa(ctxt.getID(orig)))
+	// Because we've already written the unique origin ID this call to h.typ is
+	// unnecessary, but we leave it for hash readability. It can be removed later
+	// if performance is an issue.
+	h.typ(orig)
 	if len(targs) > 0 {
 		// TODO(rfindley): consider asserting on isGeneric(typ) here, if and when
 		// isGeneric handles *Signature types.
@@ -106,14 +109,14 @@ func (ctxt *Context) update(h string, orig Type, targs []Type, inst Type) Type {
 	return inst
 }
 
-// idForType returns a unique ID for the pointer n.
-func (ctxt *Context) idForType(n *Named) int {
+// getID returns a unique ID for the type t.
+func (ctxt *Context) getID(t Type) int {
 	ctxt.mu.Lock()
 	defer ctxt.mu.Unlock()
-	id, ok := ctxt.seen[n]
+	id, ok := ctxt.originIDs[t]
 	if !ok {
 		id = ctxt.nextID
-		ctxt.seen[n] = id
+		ctxt.originIDs[t] = id
 		ctxt.nextID++
 	}
 	return id
diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go
index 62d9e18401..ec646e1a5c 100644
--- a/src/go/types/instantiate.go
+++ b/src/go/types/instantiate.go
@@ -52,30 +52,26 @@ func Instantiate(ctxt *Context, typ Type, targs []Type, validate bool) (Type, er
 // instance creates a type or function instance using the given original type
 // typ and arguments targs. For Named types the resulting instance will be
 // unexpanded.
-func (check *Checker) instance(pos token.Pos, orig Type, targs []Type, ctxt *Context) Type {
+func (check *Checker) instance(pos token.Pos, orig Type, targs []Type, ctxt *Context) (res Type) {
+	var h string
+	if ctxt != nil {
+		h = ctxt.instanceHash(orig, targs)
+		// typ may already have been instantiated with identical type arguments. In
+		// that case, re-use the existing instance.
+		if inst := ctxt.lookup(h, orig, targs); inst != nil {
+			return inst
+		}
+	}
+
 	switch orig := orig.(type) {
 	case *Named:
-		var h string
-		if ctxt != nil {
-			h = ctxt.typeHash(orig, targs)
-			// typ may already have been instantiated with identical type arguments. In
-			// that case, re-use the existing instance.
-			if inst := ctxt.lookup(h, orig, targs); inst != nil {
-				return inst
-			}
-		}
 		tname := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil)
 		named := check.newNamed(tname, orig, nil, nil, nil) // underlying, tparams, and methods are set when named is resolved
 		named.targs = NewTypeList(targs)
 		named.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, []*Func) {
 			return expandNamed(ctxt, n, pos)
 		}
-		if ctxt != nil {
-			// It's possible that we've lost a race to add named to the context.
-			// In this case, use whichever instance is recorded in the context.
-			named = ctxt.update(h, orig, targs, named).(*Named)
-		}
-		return named
+		res = named
 
 	case *Signature:
 		tparams := orig.TypeParams()
@@ -96,10 +92,19 @@ func (check *Checker) instance(pos token.Pos, orig Type, targs []Type, ctxt *Con
 		// After instantiating a generic signature, it is not generic
 		// anymore; we need to set tparams to nil.
 		sig.tparams = nil
-		return sig
+		res = sig
+	default:
+		// only types and functions can be generic
+		panic(fmt.Sprintf("%v: cannot instantiate %v", pos, orig))
+	}
+
+	if ctxt != nil {
+		// It's possible that we've lost a race to add named to the context.
+		// In this case, use whichever instance is recorded in the context.
+		res = ctxt.update(h, orig, targs, res)
 	}
-	// only types and functions can be generic
-	panic(fmt.Sprintf("%v: cannot instantiate %v", pos, orig))
+
+	return res
 }
 
 // validateTArgLen verifies that the length of targs and tparams matches,
diff --git a/src/go/types/instantiate_test.go b/src/go/types/instantiate_test.go
index 832c822224..a4ed581e35 100644
--- a/src/go/types/instantiate_test.go
+++ b/src/go/types/instantiate_test.go
@@ -11,40 +11,106 @@ import (
 )
 
 func TestInstantiateEquality(t *testing.T) {
-	const src = genericPkg + "p; type T[P any] int"
-
-	pkg, err := pkgFor(".", src, nil)
-	if err != nil {
-		t.Fatal(err)
+	tests := []struct {
+		src       string
+		name1     string
+		targs1    []Type
+		name2     string
+		targs2    []Type
+		wantEqual bool
+	}{
+		{
+			"package basictype; type T[P any] int",
+			"T", []Type{Typ[Int]},
+			"T", []Type{Typ[Int]},
+			true,
+		},
+		{
+			"package differenttypeargs; type T[P any] int",
+			"T", []Type{Typ[Int]},
+			"T", []Type{Typ[String]},
+			false,
+		},
+		{
+			"package typeslice; type T[P any] int",
+			"T", []Type{NewSlice(Typ[Int])},
+			"T", []Type{NewSlice(Typ[Int])},
+			true,
+		},
+		{
+			"package basicfunc; func F[P any]() {}",
+			"F", []Type{Typ[Int]},
+			"F", []Type{Typ[Int]},
+			true,
+		},
+		{
+			"package funcslice; func F[P any]() {}",
+			"F", []Type{NewSlice(Typ[Int])},
+			"F", []Type{NewSlice(Typ[Int])},
+			true,
+		},
+		{
+			"package funcwithparams; func F[P any](x string) float64 { return 0 }",
+			"F", []Type{Typ[Int]},
+			"F", []Type{Typ[Int]},
+			true,
+		},
+		{
+			"package differentfuncargs; func F[P any](x string) float64 { return 0 }",
+			"F", []Type{Typ[Int]},
+			"F", []Type{Typ[String]},
+			false,
+		},
+		{
+			"package funcequality; func F1[P any](x int) {}; func F2[Q any](x int) {}",
+			"F1", []Type{Typ[Int]},
+			"F2", []Type{Typ[Int]},
+			false,
+		},
+		{
+			"package funcsymmetry; func F1[P any](x P) {}; func F2[Q any](x Q) {}",
+			"F1", []Type{Typ[Int]},
+			"F2", []Type{Typ[Int]},
+			false,
+		},
 	}
 
-	T := pkg.Scope().Lookup("T").Type().(*Named)
+	for _, test := range tests {
+		pkg, err := pkgForMode(".", test.src, nil, 0)
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		t.Run(pkg.Name(), func(t *testing.T) {
+			ctxt := NewContext()
 
-	// Instantiating the same type twice should result in pointer-equivalent
-	// instances.
-	ctxt := NewContext()
-	res1, err := Instantiate(ctxt, T, []Type{Typ[Int]}, false)
-	if err != nil {
-		t.Fatal(err)
-	}
-	res2, err := Instantiate(ctxt, T, []Type{Typ[Int]}, false)
-	if err != nil {
-		t.Fatal(err)
-	}
+			T1 := pkg.Scope().Lookup(test.name1).Type()
+			res1, err := Instantiate(ctxt, T1, test.targs1, false)
+			if err != nil {
+				t.Fatal(err)
+			}
+
+			T2 := pkg.Scope().Lookup(test.name2).Type()
+			res2, err := Instantiate(ctxt, T2, test.targs2, false)
+			if err != nil {
+				t.Fatal(err)
+			}
 
-	if res1 != res2 {
-		t.Errorf("first instance (%s) not pointer-equivalent to second instance (%s)", res1, res2)
+			if gotEqual := res1 == res2; gotEqual != test.wantEqual {
+				t.Errorf("%s == %s: %t, want %t", res1, res2, gotEqual, test.wantEqual)
+			}
+		})
 	}
 }
 
 func TestInstantiateNonEquality(t *testing.T) {
-	const src = genericPkg + "p; type T[P any] int"
+	const src = "package p; type T[P any] int"
 
-	pkg1, err := pkgFor(".", src, nil)
+	pkg1, err := pkgForMode(".", src, nil, 0)
 	if err != nil {
 		t.Fatal(err)
 	}
-	pkg2, err := pkgFor(".", src, nil)
+	pkg2, err := pkgForMode(".", src, nil, 0)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -73,7 +139,7 @@ func TestInstantiateNonEquality(t *testing.T) {
 }
 
 func TestMethodInstantiation(t *testing.T) {
-	const prefix = genericPkg + `p
+	const prefix = `package p
 
 type T[P any] struct{}
 
@@ -95,7 +161,7 @@ var X T[int]
 
 	for _, test := range tests {
 		src := prefix + test.decl
-		pkg, err := pkgFor(".", src, nil)
+		pkg, err := pkgForMode(".", src, nil, 0)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -112,7 +178,7 @@ var X T[int]
 }
 
 func TestImmutableSignatures(t *testing.T) {
-	const src = genericPkg + `p
+	const src = `package p
 
 type T[P any] struct{}
 
@@ -120,7 +186,7 @@ func (T[P]) m() {}
 
 var _ T[int]
 `
-	pkg, err := pkgFor(".", src, nil)
+	pkg, err := pkgForMode(".", src, nil, 0)
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/src/go/types/named.go b/src/go/types/named.go
index ed3c426a12..06b6d4692b 100644
--- a/src/go/types/named.go
+++ b/src/go/types/named.go
@@ -253,7 +253,7 @@ func expandNamed(ctxt *Context, n *Named, instPos token.Pos) (tparams *TypeParam
 	if n.orig.tparams.Len() == n.targs.Len() {
 		// We must always have a context, to avoid infinite recursion.
 		ctxt = check.bestContext(ctxt)
-		h := ctxt.typeHash(n.orig, n.targs.list())
+		h := ctxt.instanceHash(n.orig, n.targs.list())
 		// ensure that an instance is recorded for h to avoid infinite recursion.
 		ctxt.update(h, n.orig, n.TypeArgs().list(), n)
 
diff --git a/src/go/types/subst.go b/src/go/types/subst.go
index 0e3eafdaf1..3ff81a06b6 100644
--- a/src/go/types/subst.go
+++ b/src/go/types/subst.go
@@ -207,7 +207,7 @@ func (subst *subster) typ(typ Type) Type {
 		}
 
 		// before creating a new named type, check if we have this one already
-		h := subst.ctxt.typeHash(t.orig, newTArgs)
+		h := subst.ctxt.instanceHash(t.orig, newTArgs)
 		dump(">>> new type hash: %s", h)
 		if named := subst.ctxt.lookup(h, t.orig, newTArgs); named != nil {
 			dump(">>> found %s", named)
diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go
index c448d25458..9192b0423b 100644
--- a/src/go/types/typestring.go
+++ b/src/go/types/typestring.go
@@ -291,7 +291,7 @@ func (w *typeWriter) typ(typ Type) {
 // nothing.
 func (w *typeWriter) typePrefix(t *Named) {
 	if w.ctxt != nil {
-		w.string(strconv.Itoa(w.ctxt.idForType(t)))
+		w.string(strconv.Itoa(w.ctxt.getID(t)))
 	}
 }
 
diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go
index 048bc95e15..09d1471985 100644
--- a/src/go/types/typexpr.go
+++ b/src/go/types/typexpr.go
@@ -409,7 +409,7 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named
 	}
 
 	// create the instance
-	h := check.conf.Context.typeHash(orig, targs)
+	h := check.conf.Context.instanceHash(orig, targs)
 	// targs may be incomplete, and require inference. In any case we should de-duplicate.
 	inst, _ := check.conf.Context.lookup(h, orig, targs).(*Named)
 	// If inst is non-nil, we can't just return here. Inst may have been
-- 
GitLab


From c97d6817a3a47ce7ec30f1eebae48def30b64ad8 Mon Sep 17 00:00:00 2001
From: Robert Findley 
Date: Wed, 10 Nov 2021 15:53:16 -0500
Subject: [PATCH 2163/2500] go/types: when type hashing, use placeholders for
 type parameters

Type parameter names don't matter for the purposes of generic type
identity, so mask them with numeric placeholders when hashing.

Change-Id: Iacb4c23abecdd733fc292ae13ecac6baa2c5524c
Reviewed-on: https://go-review.googlesource.com/c/go/+/363114
Trust: Robert Findley 
Run-TryBot: Robert Findley 
TryBot-Result: Go Bot 
Reviewed-by: Robert Griesemer 
---
 src/go/types/typestring.go | 53 +++++++++++++++++++++++---------------
 1 file changed, 32 insertions(+), 21 deletions(-)

diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go
index 9192b0423b..cb41abd2ac 100644
--- a/src/go/types/typestring.go
+++ b/src/go/types/typestring.go
@@ -8,6 +8,7 @@ package types
 
 import (
 	"bytes"
+	"fmt"
 	"go/token"
 	"strconv"
 	"unicode/utf8"
@@ -71,20 +72,21 @@ func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) {
 }
 
 type typeWriter struct {
-	buf   *bytes.Buffer
-	seen  map[Type]bool
-	qf    Qualifier
-	ctxt  *Context // if non-nil, we are type hashing
-	debug bool     // if true, write debug annotations
+	buf     *bytes.Buffer
+	seen    map[Type]bool
+	qf      Qualifier
+	ctxt    *Context       // if non-nil, we are type hashing
+	tparams *TypeParamList // local type parameters
+	debug   bool           // if true, write debug annotations
 }
 
 func newTypeWriter(buf *bytes.Buffer, qf Qualifier) *typeWriter {
-	return &typeWriter{buf, make(map[Type]bool), qf, nil, false}
+	return &typeWriter{buf, make(map[Type]bool), qf, nil, nil, false}
 }
 
 func newTypeHasher(buf *bytes.Buffer, ctxt *Context) *typeWriter {
 	assert(ctxt != nil)
-	return &typeWriter{buf, make(map[Type]bool), nil, ctxt, false}
+	return &typeWriter{buf, make(map[Type]bool), nil, ctxt, nil, false}
 }
 
 func (w *typeWriter) byte(b byte) {
@@ -259,8 +261,12 @@ func (w *typeWriter) typ(typ Type) {
 		}
 
 	case *Named:
-		w.typePrefix(t)
-		w.typeName(t.obj)
+		// If hashing, write a unique prefix for t to represent its identity, since
+		// named type identity is pointer identity.
+		if w.ctxt != nil {
+			w.string(strconv.Itoa(w.ctxt.getID(t)))
+		}
+		w.typeName(t.obj) // when hashing written for readability of the hash only
 		if t.targs != nil {
 			// instantiated type
 			w.typeList(t.targs.list())
@@ -274,9 +280,16 @@ func (w *typeWriter) typ(typ Type) {
 			w.error("unnamed type parameter")
 			break
 		}
-		w.string(t.obj.name)
-		if w.debug || w.ctxt != nil {
-			w.string(subscript(t.id))
+		if i := tparamIndex(w.tparams.list(), t); i >= 0 {
+			// The names of type parameters that are declared by the type being
+			// hashed are not part of the type identity. Replace them with a
+			// placeholder indicating their index.
+			w.string(fmt.Sprintf("$%d", i))
+		} else {
+			w.string(t.obj.name)
+			if w.debug || w.ctxt != nil {
+				w.string(subscript(t.id))
+			}
 		}
 
 	default:
@@ -286,15 +299,6 @@ func (w *typeWriter) typ(typ Type) {
 	}
 }
 
-// If w.ctxt is non-nil, typePrefix writes a unique prefix for the named type t
-// based on the types already observed by w.ctxt. If w.ctxt is nil, it does
-// nothing.
-func (w *typeWriter) typePrefix(t *Named) {
-	if w.ctxt != nil {
-		w.string(strconv.Itoa(w.ctxt.getID(t)))
-	}
-}
-
 func (w *typeWriter) typeList(list []Type) {
 	w.byte('[')
 	for i, typ := range list {
@@ -379,6 +383,13 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) {
 
 func (w *typeWriter) signature(sig *Signature) {
 	if sig.TypeParams().Len() != 0 {
+		if w.ctxt != nil {
+			assert(w.tparams == nil)
+			w.tparams = sig.TypeParams()
+			defer func() {
+				w.tparams = nil
+			}()
+		}
 		w.tParamList(sig.TypeParams().list())
 	}
 
-- 
GitLab


From 958f405371d942d988aef325b2103fa64028af45 Mon Sep 17 00:00:00 2001
From: Robert Findley 
Date: Wed, 10 Nov 2021 15:54:00 -0500
Subject: [PATCH 2164/2500] go/types: when type hashing, canonicalize
 interfaces

The interface type string preserves certain non-semantic attributes of
the type, such as embedded interfaces. We want the hash to represent the
interface identity, so hash the type set representation of the interface
instead.

Change-Id: I14081ac20b738c5fe11785e0846a9b4358594768
Reviewed-on: https://go-review.googlesource.com/c/go/+/363115
Trust: Robert Findley 
Run-TryBot: Robert Findley 
TryBot-Result: Go Bot 
Reviewed-by: Robert Griesemer 
---
 src/go/types/instantiate_test.go | 33 ++++++++++++++++
 src/go/types/typestring.go       | 66 ++++++++++++++++++++++++++------
 2 files changed, 87 insertions(+), 12 deletions(-)

diff --git a/src/go/types/instantiate_test.go b/src/go/types/instantiate_test.go
index a4ed581e35..281c8bbcad 100644
--- a/src/go/types/instantiate_test.go
+++ b/src/go/types/instantiate_test.go
@@ -5,12 +5,14 @@
 package types_test
 
 import (
+	"go/token"
 	. "go/types"
 	"strings"
 	"testing"
 )
 
 func TestInstantiateEquality(t *testing.T) {
+	emptySignature := NewSignatureType(nil, nil, nil, nil, nil, false)
 	tests := []struct {
 		src       string
 		name1     string
@@ -37,6 +39,37 @@ func TestInstantiateEquality(t *testing.T) {
 			"T", []Type{NewSlice(Typ[Int])},
 			true,
 		},
+		{
+			// interface{interface{...}} is equivalent to interface{...}
+			"package equivalentinterfaces; type T[P any] int",
+			"T", []Type{
+				NewInterfaceType([]*Func{NewFunc(token.NoPos, nil, "M", emptySignature)}, nil),
+			},
+			"T", []Type{
+				NewInterfaceType(
+					nil,
+					[]Type{
+						NewInterfaceType([]*Func{NewFunc(token.NoPos, nil, "M", emptySignature)}, nil),
+					},
+				),
+			},
+			true,
+		},
+		{
+			// int|string is equivalent to string|int
+			"package equivalenttypesets; type T[P any] int",
+			"T", []Type{
+				NewInterfaceType(nil, []Type{
+					NewUnion([]*Term{NewTerm(false, Typ[Int]), NewTerm(false, Typ[String])}),
+				}),
+			},
+			"T", []Type{
+				NewInterfaceType(nil, []Type{
+					NewUnion([]*Term{NewTerm(false, Typ[String]), NewTerm(false, Typ[Int])}),
+				}),
+			},
+			true,
+		},
 		{
 			"package basicfunc; func F[P any]() {}",
 			"F", []Type{Typ[Int]},
diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go
index cb41abd2ac..f33175f97e 100644
--- a/src/go/types/typestring.go
+++ b/src/go/types/typestring.go
@@ -10,7 +10,9 @@ import (
 	"bytes"
 	"fmt"
 	"go/token"
+	"sort"
 	"strconv"
+	"strings"
 	"unicode/utf8"
 )
 
@@ -211,20 +213,24 @@ func (w *typeWriter) typ(typ Type) {
 		}
 		w.string("interface{")
 		first := true
-		for _, m := range t.methods {
-			if !first {
-				w.byte(';')
+		if w.ctxt != nil {
+			w.typeSet(t.typeSet())
+		} else {
+			for _, m := range t.methods {
+				if !first {
+					w.byte(';')
+				}
+				first = false
+				w.string(m.name)
+				w.signature(m.typ.(*Signature))
 			}
-			first = false
-			w.string(m.name)
-			w.signature(m.typ.(*Signature))
-		}
-		for _, typ := range t.embeddeds {
-			if !first {
-				w.byte(';')
+			for _, typ := range t.embeddeds {
+				if !first {
+					w.byte(';')
+				}
+				first = false
+				w.typ(typ)
 			}
-			first = false
-			w.typ(typ)
 		}
 		w.byte('}')
 
@@ -299,6 +305,42 @@ func (w *typeWriter) typ(typ Type) {
 	}
 }
 
+// typeSet writes a canonical hash for an interface type set.
+func (w *typeWriter) typeSet(s *_TypeSet) {
+	assert(w.ctxt != nil)
+	first := true
+	for _, m := range s.methods {
+		if !first {
+			w.byte(';')
+		}
+		first = false
+		w.string(m.name)
+		w.signature(m.typ.(*Signature))
+	}
+	switch {
+	case s.terms.isAll():
+		// nothing to do
+	case s.terms.isEmpty():
+		w.string(s.terms.String())
+	default:
+		var termHashes []string
+		for _, term := range s.terms {
+			// terms are not canonically sorted, so we sort their hashes instead.
+			var buf bytes.Buffer
+			if term.tilde {
+				buf.WriteByte('~')
+			}
+			newTypeHasher(&buf, w.ctxt).typ(term.typ)
+			termHashes = append(termHashes, buf.String())
+		}
+		sort.Strings(termHashes)
+		if !first {
+			w.byte(';')
+		}
+		w.string(strings.Join(termHashes, "|"))
+	}
+}
+
 func (w *typeWriter) typeList(list []Type) {
 	w.byte('[')
 	for i, typ := range list {
-- 
GitLab


From 530e320b2a9ed08f2bba39507b877fd66352d7ca Mon Sep 17 00:00:00 2001
From: Robert Findley 
Date: Wed, 10 Nov 2021 16:52:17 -0500
Subject: [PATCH 2165/2500] go/types: don't set a Config.Context if none is
 provided

Users can re-use a type checking context by passing it via types.Config.
There is no need for us to expose the internal type checking context
when the config context is unset, and in fact doing so could lead to a
memory leak for users that re-use types.Config, expecting it to be small
and immutable.

Keep track of the Context on Checker instead, and zero it out at the end
of type checking.

Change-Id: Iff5b328a09cd0af76fcd4869f5f15352131b5986
Reviewed-on: https://go-review.googlesource.com/c/go/+/363175
Trust: Robert Findley 
Run-TryBot: Robert Findley 
TryBot-Result: Go Bot 
Reviewed-by: Robert Griesemer 
---
 src/go/types/call.go      | 2 +-
 src/go/types/check.go     | 8 +++-----
 src/go/types/decl.go      | 2 +-
 src/go/types/named.go     | 8 +++++---
 src/go/types/signature.go | 2 +-
 src/go/types/typexpr.go   | 9 +++++----
 6 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/src/go/types/call.go b/src/go/types/call.go
index 890a2c7c5a..da4b72a0c7 100644
--- a/src/go/types/call.go
+++ b/src/go/types/call.go
@@ -81,7 +81,7 @@ func (check *Checker) instantiateSignature(pos token.Pos, typ *Signature, targs
 		}()
 	}
 
-	inst := check.instance(pos, typ, targs, check.conf.Context).(*Signature)
+	inst := check.instance(pos, typ, targs, check.bestContext(nil)).(*Signature)
 	assert(len(posList) <= len(targs))
 	tparams := typ.TypeParams().list()
 	if i, err := check.verify(pos, tparams, targs); err != nil {
diff --git a/src/go/types/check.go b/src/go/types/check.go
index 93e6ffa761..ba7d26455f 100644
--- a/src/go/types/check.go
+++ b/src/go/types/check.go
@@ -105,6 +105,7 @@ type Checker struct {
 	// package information
 	// (initialized by NewChecker, valid for the life-time of checker)
 	conf *Config
+	ctxt *Context // context for de-duplicating instances
 	fset *token.FileSet
 	pkg  *Package
 	*Info
@@ -203,11 +204,6 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch
 		conf = new(Config)
 	}
 
-	// make sure we have a context
-	if conf.Context == nil {
-		conf.Context = NewContext()
-	}
-
 	// make sure we have an info struct
 	if info == nil {
 		info = new(Info)
@@ -220,6 +216,7 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch
 
 	return &Checker{
 		conf:    conf,
+		ctxt:    conf.Context,
 		fset:    fset,
 		pkg:     pkg,
 		Info:    info,
@@ -322,6 +319,7 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) {
 	check.seenPkgMap = nil
 	check.recvTParamMap = nil
 	check.defTypes = nil
+	check.ctxt = nil
 
 	// TODO(rFindley) There's more memory we should release at this point.
 
diff --git a/src/go/types/decl.go b/src/go/types/decl.go
index 64d5bd195e..6adace3484 100644
--- a/src/go/types/decl.go
+++ b/src/go/types/decl.go
@@ -68,7 +68,7 @@ func (check *Checker) objDecl(obj Object, def *Named) {
 	// Funcs with m.instRecv set have not yet be completed. Complete them now
 	// so that they have a type when objDecl exits.
 	if m, _ := obj.(*Func); m != nil && m.instRecv != nil {
-		check.completeMethod(check.conf.Context, m)
+		check.completeMethod(nil, m)
 	}
 
 	// Checking the declaration of obj means inferring its type
diff --git a/src/go/types/named.go b/src/go/types/named.go
index 06b6d4692b..82a053dd0d 100644
--- a/src/go/types/named.go
+++ b/src/go/types/named.go
@@ -222,15 +222,17 @@ func (n *Named) setUnderlying(typ Type) {
 
 // bestContext returns the best available context. In order of preference:
 // - the given ctxt, if non-nil
-// - check.Config.Context, if check is non-nil
+// - check.ctxt, if check is non-nil
 // - a new Context
 func (check *Checker) bestContext(ctxt *Context) *Context {
 	if ctxt != nil {
 		return ctxt
 	}
 	if check != nil {
-		assert(check.conf.Context != nil)
-		return check.conf.Context
+		if check.ctxt == nil {
+			check.ctxt = NewContext()
+		}
+		return check.ctxt
 	}
 	return NewContext()
 }
diff --git a/src/go/types/signature.go b/src/go/types/signature.go
index 3e0a046afa..698b89c462 100644
--- a/src/go/types/signature.go
+++ b/src/go/types/signature.go
@@ -211,7 +211,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
 			var err string
 			switch T := rtyp.(type) {
 			case *Named:
-				T.resolve(check.conf.Context)
+				T.resolve(check.bestContext(nil))
 				// The receiver type may be an instantiated type referred to
 				// by an alias (which cannot have receiver parameters for now).
 				if T.TypeArgs() != nil && sig.RecvTypeParams() == nil {
diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go
index 09d1471985..cff9917185 100644
--- a/src/go/types/typexpr.go
+++ b/src/go/types/typexpr.go
@@ -409,9 +409,10 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named
 	}
 
 	// create the instance
-	h := check.conf.Context.instanceHash(orig, targs)
+	ctxt := check.bestContext(nil)
+	h := ctxt.instanceHash(orig, targs)
 	// targs may be incomplete, and require inference. In any case we should de-duplicate.
-	inst, _ := check.conf.Context.lookup(h, orig, targs).(*Named)
+	inst, _ := ctxt.lookup(h, orig, targs).(*Named)
 	// If inst is non-nil, we can't just return here. Inst may have been
 	// constructed via recursive substitution, in which case we wouldn't do the
 	// validation below. Ensure that the validation (and resulting errors) runs
@@ -420,7 +421,7 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named
 		tname := NewTypeName(x.Pos(), orig.obj.pkg, orig.obj.name, nil)
 		inst = check.newNamed(tname, orig, nil, nil, nil) // underlying, methods and tparams are set when named is resolved
 		inst.targs = NewTypeList(targs)
-		inst = check.conf.Context.update(h, orig, targs, inst).(*Named)
+		inst = ctxt.update(h, orig, targs, inst).(*Named)
 	}
 	def.setUnderlying(inst)
 
@@ -446,7 +447,7 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named
 		// This is an instance from the source, not from recursive substitution,
 		// and so it must be resolved during type-checking so that we can report
 		// errors.
-		inst.resolve(check.conf.Context)
+		inst.resolve(ctxt)
 		// Since check is non-nil, we can still mutate inst. Unpinning the resolver
 		// frees some memory.
 		inst.resolver = nil
-- 
GitLab


From c893a85f21d0e5448c687254e50cc6936b36548e Mon Sep 17 00:00:00 2001
From: Robert Findley 
Date: Wed, 10 Nov 2021 16:58:45 -0500
Subject: [PATCH 2166/2500] go/types: rename types.context to types.environment

Now that we have a Context type the context (unexported) type is
particularly confusing. Rename it to environment.

Change-Id: I7d280439b8263d9ebfd561fc4d59c6d43c8d3e3f
Reviewed-on: https://go-review.googlesource.com/c/go/+/363176
Trust: Robert Findley 
Run-TryBot: Robert Findley 
TryBot-Result: Go Bot 
Reviewed-by: Robert Griesemer 
---
 src/go/types/check.go | 17 +++++++++--------
 src/go/types/decl.go  | 16 ++++++++--------
 src/go/types/stmt.go  | 10 +++++-----
 3 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/src/go/types/check.go b/src/go/types/check.go
index ba7d26455f..aef53b20de 100644
--- a/src/go/types/check.go
+++ b/src/go/types/check.go
@@ -41,8 +41,9 @@ type exprInfo struct {
 	val   constant.Value // constant value; or nil (if not a constant)
 }
 
-// A context represents the context within which an object is type-checked.
-type context struct {
+// An environment represents the environment within which an object is
+// type-checked.
+type environment struct {
 	decl          *declInfo              // package-level declaration whose init expression/function body is checked
 	scope         *Scope                 // top-most scope for lookups
 	pos           token.Pos              // if valid, identifiers are looked up as if at position pos (used by Eval)
@@ -55,9 +56,9 @@ type context struct {
 	hasCallOrRecv bool                   // set if an expression contains a function call or channel receive operation
 }
 
-// lookup looks up name in the current context and returns the matching object, or nil.
-func (ctxt *context) lookup(name string) Object {
-	_, obj := ctxt.scope.LookupParent(name, ctxt.pos)
+// lookup looks up name in the current environment and returns the matching object, or nil.
+func (env *environment) lookup(name string) Object {
+	_, obj := env.scope.LookupParent(name, env.pos)
 	return obj
 }
 
@@ -140,9 +141,9 @@ type Checker struct {
 	objPath  []Object              // path of object dependencies during type inference (for cycle reporting)
 	defTypes []*Named              // defined types created during type checking, for final validation.
 
-	// context within which the current object is type-checked
-	// (valid only for the duration of type-checking a specific object)
-	context
+	// environment within which the current object is type-checked (valid only
+	// for the duration of type-checking a specific object)
+	environment
 
 	// debugging
 	indent int // indentation for tracing
diff --git a/src/go/types/decl.go b/src/go/types/decl.go
index 6adace3484..7e89e7be3a 100644
--- a/src/go/types/decl.go
+++ b/src/go/types/decl.go
@@ -50,7 +50,7 @@ func pathString(path []Object) string {
 	return s
 }
 
-// objDecl type-checks the declaration of obj in its respective (file) context.
+// objDecl type-checks the declaration of obj in its respective (file) environment.
 // For the meaning of def, see Checker.definedType, in typexpr.go.
 func (check *Checker) objDecl(obj Object, def *Named) {
 	if trace && obj.Type() == nil {
@@ -177,11 +177,11 @@ func (check *Checker) objDecl(obj Object, def *Named) {
 		unreachable()
 	}
 
-	// save/restore current context and setup object context
-	defer func(ctxt context) {
-		check.context = ctxt
-	}(check.context)
-	check.context = context{
+	// save/restore current environment and set up object environment
+	defer func(env environment) {
+		check.environment = env
+	}(check.environment)
+	check.environment = environment{
 		scope: d.file,
 	}
 
@@ -239,7 +239,7 @@ loop:
 			// If we reach a generic type that is part of a cycle
 			// and we are in a type parameter list, we have a cycle
 			// through a type parameter list, which is invalid.
-			if check.context.inTParamList && isGeneric(obj.typ) {
+			if check.environment.inTParamList && isGeneric(obj.typ) {
 				tparCycle = true
 				break loop
 			}
@@ -697,7 +697,7 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list *ast.FieldList
 	// function closures may appear inside a type parameter list but they
 	// cannot be generic, and their bodies are processed in delayed and
 	// sequential fashion. Note that with each new declaration, we save
-	// the existing context and restore it when done; thus inTPList is
+	// the existing environment and restore it when done; thus inTPList is
 	// true exactly only when we are in a specific type parameter list.
 	assert(!check.inTParamList)
 	check.inTParamList = true
diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go
index 11032f44dd..c000d935d6 100644
--- a/src/go/types/stmt.go
+++ b/src/go/types/stmt.go
@@ -29,13 +29,13 @@ func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body
 	sig.scope.pos = body.Pos()
 	sig.scope.end = body.End()
 
-	// save/restore current context and setup function context
+	// save/restore current environment and set up function environment
 	// (and use 0 indentation at function start)
-	defer func(ctxt context, indent int) {
-		check.context = ctxt
+	defer func(env environment, indent int) {
+		check.environment = env
 		check.indent = indent
-	}(check.context, check.indent)
-	check.context = context{
+	}(check.environment, check.indent)
+	check.environment = environment{
 		decl:  decl,
 		scope: sig.scope,
 		iota:  iota,
-- 
GitLab


From 2fd720b78086eaa57559e38f6ad4fe51c09c3a17 Mon Sep 17 00:00:00 2001
From: Robert Findley 
Date: Fri, 12 Nov 2021 20:15:49 -0500
Subject: [PATCH 2167/2500] test: fix longtest failures on
 fixedbugs/issue48471.go

This test is failing with -G=0, so specify -G=3.

Change-Id: I4c74707d0a43f8191cb0b156204604458ba85136
Reviewed-on: https://go-review.googlesource.com/c/go/+/363699
Trust: Robert Findley 
Trust: Dan Scales 
Run-TryBot: Robert Findley 
TryBot-Result: Go Bot 
Reviewed-by: Dan Scales 
---
 test/fixedbugs/issue48471.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/fixedbugs/issue48471.go b/test/fixedbugs/issue48471.go
index 2e00c87c6a..88caeede15 100644
--- a/test/fixedbugs/issue48471.go
+++ b/test/fixedbugs/issue48471.go
@@ -1,4 +1,4 @@
-// errorcheck
+// errorcheck -G=3
 
 // Copyright 2021 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
-- 
GitLab


From e658c42ba460b91d5b6934829ddffa802d4ca524 Mon Sep 17 00:00:00 2001
From: Robert Findley 
Date: Thu, 11 Nov 2021 20:15:02 -0500
Subject: [PATCH 2168/2500] go/types: add a test for Context deduplication of
 hash collisions

Add a test that exercises the fall-back logic in Context to handle hash
collisions by de-duplicating using Identical.

This has to be a somewhat invasive test because we don't know any actual
cases of hash collisions.

Change-Id: Idf00f7a6ab8c7517ed0f91fdc42d54f5e736b1b9
Reviewed-on: https://go-review.googlesource.com/c/go/+/363517
Trust: Robert Findley 
Run-TryBot: Robert Findley 
TryBot-Result: Go Bot 
Reviewed-by: Robert Griesemer 
---
 src/go/types/context_test.go | 70 ++++++++++++++++++++++++++++++++++++
 src/go/types/types_test.go   |  8 -----
 2 files changed, 70 insertions(+), 8 deletions(-)
 create mode 100644 src/go/types/context_test.go
 delete mode 100644 src/go/types/types_test.go

diff --git a/src/go/types/context_test.go b/src/go/types/context_test.go
new file mode 100644
index 0000000000..ec30050202
--- /dev/null
+++ b/src/go/types/context_test.go
@@ -0,0 +1,70 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types
+
+import (
+	"go/token"
+	"testing"
+)
+
+func TestContextHashCollisions(t *testing.T) {
+	if debug {
+		t.Skip("hash collisions are expected, and would fail debug assertions")
+	}
+	// Unit test the de-duplication fall-back logic in Context.
+	//
+	// We can't test this via Instantiate because this is only a fall-back in
+	// case our hash is imperfect.
+	//
+	// These lookups and updates use reasonable looking types in an attempt to
+	// make them robust to internal type assertions, but could equally well use
+	// arbitrary types.
+
+	// Create some distinct origin types. nullaryP and nullaryQ have no
+	// parameters and are identical (but have different type parameter names).
+	// unaryP has a parameter.
+	var nullaryP, nullaryQ, unaryP Type
+	{
+		// type nullaryP = func[P any]()
+		tparam := NewTypeParam(NewTypeName(token.NoPos, nil, "P", nil), &emptyInterface)
+		nullaryP = NewSignatureType(nil, nil, []*TypeParam{tparam}, nil, nil, false)
+	}
+	{
+		// type nullaryQ = func[Q any]()
+		tparam := NewTypeParam(NewTypeName(token.NoPos, nil, "Q", nil), &emptyInterface)
+		nullaryQ = NewSignatureType(nil, nil, []*TypeParam{tparam}, nil, nil, false)
+	}
+	{
+		// type unaryP = func[P any](_ P)
+		tparam := NewTypeParam(NewTypeName(token.NoPos, nil, "P", nil), &emptyInterface)
+		params := NewTuple(NewVar(token.NoPos, nil, "_", tparam))
+		unaryP = NewSignatureType(nil, nil, []*TypeParam{tparam}, params, nil, false)
+	}
+
+	ctxt := NewContext()
+
+	// Update the context with an instantiation of nullaryP.
+	inst := NewSignatureType(nil, nil, nil, nil, nil, false)
+	if got := ctxt.update("", nullaryP, []Type{Typ[Int]}, inst); got != inst {
+		t.Error("bad")
+	}
+
+	// unaryP is not identical to nullaryP, so we should not get inst when
+	// instantiated with identical type arguments.
+	if got := ctxt.lookup("", unaryP, []Type{Typ[Int]}); got != nil {
+		t.Error("bad")
+	}
+
+	// nullaryQ is identical to nullaryP, so we *should* get inst when
+	// instantiated with identical type arguments.
+	if got := ctxt.lookup("", nullaryQ, []Type{Typ[Int]}); got != inst {
+		t.Error("bad")
+	}
+
+	// ...but verify we don't get inst with different type arguments.
+	if got := ctxt.lookup("", nullaryQ, []Type{Typ[String]}); got != nil {
+		t.Error("bad")
+	}
+}
diff --git a/src/go/types/types_test.go b/src/go/types/types_test.go
deleted file mode 100644
index f2358c6e19..0000000000
--- a/src/go/types/types_test.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package types
-
-// Debug is set if go/types is built with debug mode enabled.
-const Debug = debug
-- 
GitLab


From c78a267bd4ccdd8699a9dbe9bad3597bf3de47e9 Mon Sep 17 00:00:00 2001
From: Robert Findley 
Date: Fri, 12 Nov 2021 11:46:23 -0500
Subject: [PATCH 2169/2500] go/types: return an error from Instantiate on
 incorrect len(targs)

Instantiate already returns an error when validation fails. Panicking on
an incorrect number of type arguments means that callers must both
pre-validate the number of type arguments and handle resulting errors.
Returning an error rather than panicking allows eliminating
pre-validation at the call-site.

Also update the Instantiate docstring to correct some stale/inaccurate
information, and to clarify its behavior more precisely.

Updates #47916

Change-Id: I997ef30b3486760a90b0db4c3ea7111280d74a81
Reviewed-on: https://go-review.googlesource.com/c/go/+/363635
Trust: Robert Findley 
Run-TryBot: Robert Findley 
TryBot-Result: Go Bot 
Reviewed-by: Robert Griesemer 
---
 src/go/types/instantiate.go | 50 ++++++++++++++++++++++---------------
 1 file changed, 30 insertions(+), 20 deletions(-)

diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go
index ec646e1a5c..2d2d1718f4 100644
--- a/src/go/types/instantiate.go
+++ b/src/go/types/instantiate.go
@@ -13,40 +13,50 @@ import (
 	"go/token"
 )
 
-// Instantiate instantiates the type typ with the given type arguments targs.
-// typ must be a *Named or a *Signature type, and its number of type parameters
-// must match the number of provided type arguments. The result is a new,
-// instantiated (not parameterized) type of the same kind (either a *Named or a
-// *Signature). Any methods attached to a *Named are simply copied; they are
-// not instantiated.
+// Instantiate instantiates the type orig with the given type arguments targs.
+// orig must be a *Named or a *Signature type. If there is no error, the
+// resulting Type is a new, instantiated (not parameterized) type of the same
+// kind (either a *Named or a *Signature). Methods attached to a *Named type
+// are also instantiated, and associated with a new *Func that has the same
+// position as the original method, but nil function scope.
 //
-// If ctxt is non-nil, it may be used to de-dupe the instance against previous
-// instances with the same identity.
+// If ctxt is non-nil, it may be used to de-duplicate the instance against
+// previous instances with the same identity. As a special case, generic
+// *Signature origin types are only considered identical if they are pointer
+// equivalent, so that instantiating distinct (but possibly identical)
+// signatures will yield different instances.
 //
-// If verify is set and constraint satisfaction fails, the returned error may
-// wrap an *ArgumentError indicating which type argument did not satisfy its
-// corresponding type parameter constraint, and why.
+// If validate is set, Instantiate verifies that the number of type arguments
+// and parameters match, and that the type arguments satisfy their
+// corresponding type constraints. If verification fails, the resulting error
+// may wrap an *ArgumentError indicating which type argument did not satisfy
+// its corresponding type parameter constraint, and why.
 //
-// TODO(rfindley): change this function to also return an error if lengths of
-// tparams and targs do not match.
-func Instantiate(ctxt *Context, typ Type, targs []Type, validate bool) (Type, error) {
-	inst := (*Checker)(nil).instance(token.NoPos, typ, targs, ctxt)
-
-	var err error
+// If validate is not set, Instantiate does not verify the type argument count
+// or whether the type arguments satisfy their constraints. Instantiate is
+// guaranteed to not return an error, but may panic. Specifically, for
+// *Signature types, Instantiate will panic immediately if the type argument
+// count is incorrect; for *Named types, a panic may occur later inside the
+// *Named API.
+func Instantiate(ctxt *Context, orig Type, targs []Type, validate bool) (Type, error) {
 	if validate {
 		var tparams []*TypeParam
-		switch t := typ.(type) {
+		switch t := orig.(type) {
 		case *Named:
 			tparams = t.TypeParams().list()
 		case *Signature:
 			tparams = t.TypeParams().list()
 		}
+		if len(targs) != len(tparams) {
+			return nil, fmt.Errorf("got %d type arguments but %s has %d type parameters", len(targs), orig, len(tparams))
+		}
 		if i, err := (*Checker)(nil).verify(token.NoPos, tparams, targs); err != nil {
-			return inst, &ArgumentError{i, err}
+			return nil, &ArgumentError{i, err}
 		}
 	}
 
-	return inst, err
+	inst := (*Checker)(nil).instance(token.NoPos, orig, targs, ctxt)
+	return inst, nil
 }
 
 // instance creates a type or function instance using the given original type
-- 
GitLab


From c54605266b746dd4d81e3753b55910e5c8dde5f0 Mon Sep 17 00:00:00 2001
From: Michael Matloob 
Date: Fri, 29 Oct 2021 16:47:22 -0400
Subject: [PATCH 2170/2500] cmd/go: remove remaining uses of TODOWorkspaces

Most of them are fixed, but some of them have been rewritten to refer
to specific issues.

For #45713

Change-Id: Id24d9bd47afeac089835f7a26e7025332fb6119c
Reviewed-on: https://go-review.googlesource.com/c/go/+/359794
Trust: Michael Matloob 
Run-TryBot: Michael Matloob 
TryBot-Result: Go Bot 
Reviewed-by: Bryan C. Mills 
---
 src/cmd/go/internal/modcmd/download.go        | 27 ++++---
 src/cmd/go/internal/modload/init.go           | 75 ++++++++++++++-----
 src/cmd/go/internal/workcmd/edit.go           | 27 ++-----
 src/cmd/go/internal/workcmd/init.go           |  6 +-
 src/cmd/go/internal/workcmd/sync.go           | 17 ++++-
 src/cmd/go/internal/workcmd/use.go            | 28 ++-----
 .../script/work_why_download_graph.txt        | 59 +++++++++++++++
 7 files changed, 160 insertions(+), 79 deletions(-)
 create mode 100644 src/cmd/go/testdata/script/work_why_download_graph.txt

diff --git a/src/cmd/go/internal/modcmd/download.go b/src/cmd/go/internal/modcmd/download.go
index f252133762..6b8a010fd9 100644
--- a/src/cmd/go/internal/modcmd/download.go
+++ b/src/cmd/go/internal/modcmd/download.go
@@ -93,24 +93,27 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
 	modload.ExplicitWriteGoMod = true
 	haveExplicitArgs := len(args) > 0
 
-	if modload.HasModRoot() {
+	if modload.HasModRoot() || modload.WorkFilePath() != "" {
 		modload.LoadModFile(ctx) // to fill MainModules
 
-		if len(modload.MainModules.Versions()) != 1 {
-			panic(modload.TODOWorkspaces("Support workspace mode in go mod download"))
-		}
-		mainModule := modload.MainModules.Versions()[0]
-
 		if haveExplicitArgs {
-			targetAtUpgrade := mainModule.Path + "@upgrade"
-			targetAtPatch := mainModule.Path + "@patch"
-			for _, arg := range args {
-				switch arg {
-				case mainModule.Path, targetAtUpgrade, targetAtPatch:
-					os.Stderr.WriteString("go: skipping download of " + arg + " that resolves to the main module\n")
+			for _, mainModule := range modload.MainModules.Versions() {
+				targetAtUpgrade := mainModule.Path + "@upgrade"
+				targetAtPatch := mainModule.Path + "@patch"
+				for _, arg := range args {
+					switch arg {
+					case mainModule.Path, targetAtUpgrade, targetAtPatch:
+						os.Stderr.WriteString("go: skipping download of " + arg + " that resolves to the main module\n")
+					}
 				}
 			}
+		} else if modload.WorkFilePath() != "" {
+			// TODO(#44435): Think about what the correct query is to download the
+			// right set of modules. Also see code review comment at
+			// https://go-review.googlesource.com/c/go/+/359794/comments/ce946a80_6cf53992.
+			args = []string{"all"}
 		} else {
+			mainModule := modload.MainModules.Versions()[0]
 			modFile := modload.MainModules.ModFile(mainModule)
 			if modFile.Go == nil || semver.Compare("v"+modFile.Go.Version, modload.ExplicitIndirectVersionV) < 0 {
 				if len(modFile.Require) > 0 {
diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go
index fcf6ce2620..ab899fac1e 100644
--- a/src/cmd/go/internal/modload/init.go
+++ b/src/cmd/go/internal/modload/init.go
@@ -12,6 +12,7 @@ import (
 	"fmt"
 	"go/build"
 	"internal/lazyregexp"
+	"io/ioutil"
 	"os"
 	"path"
 	"path/filepath"
@@ -56,10 +57,6 @@ var (
 	ExplicitWriteGoMod bool
 )
 
-func TODOWorkspaces(s string) error {
-	return fmt.Errorf("need to support this for workspaces: %s", s)
-}
-
 // Variables set in Init.
 var (
 	initialized bool
@@ -417,9 +414,6 @@ func Init() {
 	// We're in module mode. Set any global variables that need to be set.
 	cfg.ModulesEnabled = true
 	setDefaultBuildMod()
-	_ = TODOWorkspaces("In workspace mode, mod will not be readonly for go mod download," +
-		"verify, graph, and why. Implement support for go mod download and add test cases" +
-		"to ensure verify, graph, and why work properly.")
 	list := filepath.SplitList(cfg.BuildContext.GOPATH)
 	if len(list) > 0 && list[0] != "" {
 		gopath = list[0]
@@ -562,13 +556,8 @@ func (goModDirtyError) Error() string {
 var errGoModDirty error = goModDirtyError{}
 
 func loadWorkFile(path string) (goVersion string, modRoots []string, replaces []*modfile.Replace, err error) {
-	_ = TODOWorkspaces("Clean up and write back the go.work file: add module paths for workspace modules.")
 	workDir := filepath.Dir(path)
-	workData, err := lockedfile.Read(path)
-	if err != nil {
-		return "", nil, nil, err
-	}
-	wf, err := modfile.ParseWork(path, workData, nil)
+	wf, err := ReadWorkFile(path)
 	if err != nil {
 		return "", nil, nil, err
 	}
@@ -581,15 +570,60 @@ func loadWorkFile(path string) (goVersion string, modRoots []string, replaces []
 		if !filepath.IsAbs(modRoot) {
 			modRoot = filepath.Join(workDir, modRoot)
 		}
+
 		if seen[modRoot] {
 			return "", nil, nil, fmt.Errorf("path %s appears multiple times in workspace", modRoot)
 		}
 		seen[modRoot] = true
 		modRoots = append(modRoots, modRoot)
 	}
+
 	return goVersion, modRoots, wf.Replace, nil
 }
 
+// ReadWorkFile reads and parses the go.work file at the given path.
+func ReadWorkFile(path string) (*modfile.WorkFile, error) {
+	workData, err := ioutil.ReadFile(path)
+	if err != nil {
+		return nil, err
+	}
+	wf, err := modfile.ParseWork(path, workData, nil)
+
+	return wf, nil
+}
+
+// WriteWorkFile cleans and writes out the go.work file to the given path.
+func WriteWorkFile(path string, wf *modfile.WorkFile) error {
+	wf.SortBlocks()
+	wf.Cleanup()
+	out := modfile.Format(wf.Syntax)
+
+	return ioutil.WriteFile(path, out, 0666)
+}
+
+// UpdateWorkFile updates comments on directory directives in the go.work
+// file to include the associated module path.
+func UpdateWorkFile(wf *modfile.WorkFile) {
+	missingModulePaths := map[string]string{} // module directory listed in file -> abspath modroot
+
+	for _, d := range wf.Directory {
+		modRoot := d.Path
+		if d.ModulePath == "" {
+			missingModulePaths[d.Path] = modRoot
+		}
+	}
+
+	// Clean up and annotate directories.
+	// TODO(matloob): update x/mod to actually add module paths.
+	for moddir, absmodroot := range missingModulePaths {
+		_, f, err := ReadModFile(filepath.Join(absmodroot, "go.mod"), nil)
+		if err != nil {
+			continue // Error will be reported if modules are loaded.
+		}
+		wf.AddDirectory(moddir, f.Module.Mod.Path)
+	}
+}
+
 // LoadModFile sets Target and, if there is a main module, parses the initial
 // build list from its go.mod file.
 //
@@ -651,7 +685,9 @@ func LoadModFile(ctx context.Context) *Requirements {
 		modfetch.GoSumFile = strings.TrimSuffix(modFilePath(modRoots[0]), ".mod") + ".sum"
 	}
 	if len(modRoots) == 0 {
-		_ = TODOWorkspaces("Instead of creating a fake module with an empty modroot, make MainModules.Len() == 0 mean that we're in module mode but not inside any module.")
+		// TODO(#49228): Instead of creating a fake module with an empty modroot,
+		// make MainModules.Len() == 0 mean that we're in module mode but not inside
+		// any module.
 		mainModule := module.Version{Path: "command-line-arguments"}
 		MainModules = makeMainModules([]module.Version{mainModule}, []string{""}, []*modfile.File{nil}, []*modFileIndex{nil}, "", nil)
 		goVersion := LatestGoVersion()
@@ -854,8 +890,8 @@ func CreateWorkFile(ctx context.Context, workFile string, modDirs []string) {
 		workF.AddDirectory(ToDirectoryPath(dir), f.Module.Mod.Path)
 	}
 
-	data := modfile.Format(workF.Syntax)
-	lockedfile.Write(workFile, bytes.NewReader(data), 0666)
+	UpdateWorkFile(workF)
+	WriteWorkFile(workFile, workF)
 }
 
 // fixVersion returns a modfile.VersionFixer implemented using the Query function.
@@ -1233,9 +1269,10 @@ func findWorkspaceFile(dir string) (root string) {
 			break
 		}
 		if d == cfg.GOROOT {
-			_ = TODOWorkspaces("If we end up checking in a go.work file to GOROOT/src," +
-				"remove this case.")
-			return "" // As a special case, don't cross GOROOT to find a go.work file.
+			// As a special case, don't cross GOROOT to find a go.work file.
+			// The standard library and commands built in go always use the vendored
+			// dependencies, so avoid using a most likely irrelevant go.work file.
+			return ""
 		}
 		dir = d
 	}
diff --git a/src/cmd/go/internal/workcmd/edit.go b/src/cmd/go/internal/workcmd/edit.go
index f4e630f43f..5158ac9b49 100644
--- a/src/cmd/go/internal/workcmd/edit.go
+++ b/src/cmd/go/internal/workcmd/edit.go
@@ -7,13 +7,10 @@
 package workcmd
 
 import (
-	"bytes"
 	"cmd/go/internal/base"
-	"cmd/go/internal/lockedfile"
 	"cmd/go/internal/modload"
 	"context"
 	"encoding/json"
-	"errors"
 	"fmt"
 	"os"
 	"path/filepath"
@@ -150,12 +147,7 @@ func runEditwork(ctx context.Context, cmd *base.Command, args []string) {
 		}
 	}
 
-	data, err := lockedfile.Read(gowork)
-	if err != nil {
-		base.Fatalf("go: %v", err)
-	}
-
-	workFile, err := modfile.ParseWork(gowork, data, nil)
+	workFile, err := modload.ReadWorkFile(gowork)
 	if err != nil {
 		base.Fatalf("go: errors parsing %s:\n%s", base.ShortPath(gowork), err)
 	}
@@ -171,6 +163,9 @@ func runEditwork(ctx context.Context, cmd *base.Command, args []string) {
 			edit(workFile)
 		}
 	}
+
+	modload.UpdateWorkFile(workFile)
+
 	workFile.SortBlocks()
 	workFile.Cleanup() // clean file after edits
 
@@ -179,22 +174,12 @@ func runEditwork(ctx context.Context, cmd *base.Command, args []string) {
 		return
 	}
 
-	out := modfile.Format(workFile.Syntax)
-
 	if *editPrint {
-		os.Stdout.Write(out)
+		os.Stdout.Write(modfile.Format(workFile.Syntax))
 		return
 	}
 
-	err = lockedfile.Transform(gowork, func(lockedData []byte) ([]byte, error) {
-		if !bytes.Equal(lockedData, data) {
-			return nil, errors.New("go.work changed during editing; not overwriting")
-		}
-		return out, nil
-	})
-	if err != nil {
-		base.Fatalf("go: %v", err)
-	}
+	modload.WriteWorkFile(gowork, workFile)
 }
 
 // flagEditworkDirectory implements the -directory flag.
diff --git a/src/cmd/go/internal/workcmd/init.go b/src/cmd/go/internal/workcmd/init.go
index 1342748023..fde1483efb 100644
--- a/src/cmd/go/internal/workcmd/init.go
+++ b/src/cmd/go/internal/workcmd/init.go
@@ -13,9 +13,9 @@ import (
 	"path/filepath"
 )
 
-var _ = modload.TODOWorkspaces("Add more documentation below. Though this is" +
-	"enough for those trying workspaces out, there should be more through" +
-	"documentation if the proposal is accepted and released.")
+// TODO(#49232) Add more documentation below. Though this is
+// enough for those trying workspaces out, there should be more through
+// documentation before Go 1.18 is released.
 
 var cmdInit = &base.Command{
 	UsageLine: "go work init [moddirs]",
diff --git a/src/cmd/go/internal/workcmd/sync.go b/src/cmd/go/internal/workcmd/sync.go
index 2723013bf8..6f35dc4ff3 100644
--- a/src/cmd/go/internal/workcmd/sync.go
+++ b/src/cmd/go/internal/workcmd/sync.go
@@ -15,9 +15,9 @@ import (
 	"golang.org/x/mod/module"
 )
 
-var _ = modload.TODOWorkspaces("Add more documentation below. Though this is" +
-	"enough for those trying workspaces out, there should be more through" +
-	"documentation if the proposal is accepted and released.")
+// TODO(#49232) Add more documentation below. Though this is
+// enough for those trying workspaces out, there should be more thorough
+// documentation before Go 1.18 is released.
 
 var cmdSync = &base.Command{
 	UsageLine: "go work sync [moddirs]",
@@ -71,6 +71,8 @@ func runSync(ctx context.Context, cmd *base.Command, args []string) {
 		mustSelectFor[m] = mustSelect
 	}
 
+	workFilePath := modload.WorkFilePath() // save go.work path because EnterModule clobbers it.
+
 	for _, m := range mms.Versions() {
 		// Use EnterModule to reset the global state in modload to be in
 		// single-module mode using the modroot of m.
@@ -98,4 +100,13 @@ func runSync(ctx context.Context, cmd *base.Command, args []string) {
 		}, "all")
 		modload.WriteGoMod(ctx)
 	}
+
+	wf, err := modload.ReadWorkFile(workFilePath)
+	if err != nil {
+		base.Fatalf("go: %v", err)
+	}
+	modload.UpdateWorkFile(wf)
+	if err := modload.WriteWorkFile(workFilePath, wf); err != nil {
+		base.Fatalf("go: %v", err)
+	}
 }
diff --git a/src/cmd/go/internal/workcmd/use.go b/src/cmd/go/internal/workcmd/use.go
index 10c25da396..b2218280e4 100644
--- a/src/cmd/go/internal/workcmd/use.go
+++ b/src/cmd/go/internal/workcmd/use.go
@@ -9,20 +9,16 @@ package workcmd
 import (
 	"cmd/go/internal/base"
 	"cmd/go/internal/fsys"
-	"cmd/go/internal/lockedfile"
 	"cmd/go/internal/modload"
 	"context"
 	"io/fs"
-	"io/ioutil"
 	"os"
 	"path/filepath"
-
-	"golang.org/x/mod/modfile"
 )
 
-var _ = modload.TODOWorkspaces("Add more documentation below. Though this is" +
-	"enough for those trying workspaces out, there should be more through" +
-	"documentation if the proposal is accepted and released.")
+// TODO(#49232) Add more documentation below. Though this is
+// enough for those trying workspaces out, there should be more thorough
+// documentation before Go 1.18 is released.
 
 var cmdUse = &base.Command{
 	UsageLine: "go work use [-r] [moddirs]",
@@ -51,14 +47,9 @@ func runUse(ctx context.Context, cmd *base.Command, args []string) {
 	modload.InitWorkfile()
 	gowork = modload.WorkFilePath()
 
-	data, err := lockedfile.Read(gowork)
-	if err != nil {
-		base.Fatalf("goX: %v", err)
-	}
-
-	workFile, err := modfile.ParseWork(gowork, data, nil)
+	workFile, err := modload.ReadWorkFile(gowork)
 	if err != nil {
-		base.Fatalf("go: errors parsing %s:\n%s", base.ShortPath(gowork), err)
+		base.Fatalf("go: %v", err)
 	}
 
 	haveDirs := make(map[string]bool)
@@ -119,11 +110,6 @@ func runUse(ctx context.Context, cmd *base.Command, args []string) {
 	for dir := range addDirs {
 		workFile.AddDirectory(filepath.ToSlash(dir), "")
 	}
-	workFile.SortBlocks()
-	workFile.Cleanup() // clean file after edits
-	out := modfile.Format(workFile.Syntax)
-
-	if err := ioutil.WriteFile(gowork, out, 0666); err != nil {
-		base.Fatalf("go: %v", err)
-	}
+	modload.UpdateWorkFile(workFile)
+	modload.WriteWorkFile(gowork, workFile)
 }
diff --git a/src/cmd/go/testdata/script/work_why_download_graph.txt b/src/cmd/go/testdata/script/work_why_download_graph.txt
new file mode 100644
index 0000000000..c03b4a7a62
--- /dev/null
+++ b/src/cmd/go/testdata/script/work_why_download_graph.txt
@@ -0,0 +1,59 @@
+# Test go mod download, why, and graph work in workspace mode.
+# TODO(bcmills): clarify the interaction with #44435
+
+go mod download rsc.io/quote
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.info
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.info
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.mod
+
+go mod download
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.info
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.info
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.mod
+
+go mod why rsc.io/quote
+stdout '# rsc.io/quote\nexample.com/a\nrsc.io/quote'
+
+go mod graph
+stdout 'example.com/a rsc.io/quote@v1.5.2\nexample.com/b example.com/c@v1.0.0\nrsc.io/quote@v1.5.2 rsc.io/sampler@v1.3.0\nrsc.io/sampler@v1.3.0 golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c'
+
+-- go.work --
+go 1.18
+
+directory (
+    ./a
+    ./b
+)
+-- a/go.mod --
+go 1.18
+
+module example.com/a
+
+require "rsc.io/quote" v1.5.2
+-- a/main.go --
+package main
+
+import (
+	"fmt"
+	"rsc.io/quote"
+)
+
+func main() {
+	fmt.Println(quote.Hello())
+}
+-- b/go.mod --
+go 1.18
+
+module example.com/b
+
+require example.com/c v1.0.0
+replace example.com/c => ../c
+-- c/go.mod --
+go 1.18
+
+module example.com/c
+
-- 
GitLab


From c2397905e027cdbab3a28d02813adcb82368422c Mon Sep 17 00:00:00 2001
From: Robert Griesemer 
Date: Fri, 12 Nov 2021 18:24:54 -0800
Subject: [PATCH 2171/2500] cmd/compile/internal/types2: simplify under() and
 fix a crash

The simplified version of under exposed a bug (by crashing):
When a pointer base is used before the pointer is fully set
up, the base is nil. Set the pointer base to Typ[Invalid]
when creating the pointer, and add an extra safety check
into deref. Reviewed all code that creates pointers.

The same error cannot happen with other types because
accessing parts of another type results in an expression
that is not a type, and thus these kids of cycles cannot
happen.

Change-Id: I8332a281a534c094cfbb3623a636960865813ff6
Reviewed-on: https://go-review.googlesource.com/c/go/+/363665
Trust: Robert Griesemer 
Reviewed-by: Robert Findley 
---
 src/cmd/compile/internal/types2/lookup.go                 | 7 +++++++
 src/cmd/compile/internal/types2/testdata/check/cycles.src | 1 +
 src/cmd/compile/internal/types2/type.go                   | 7 ++-----
 src/cmd/compile/internal/types2/typexpr.go                | 1 +
 4 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go
index fbfe3c81ff..b4035e16b3 100644
--- a/src/cmd/compile/internal/types2/lookup.go
+++ b/src/cmd/compile/internal/types2/lookup.go
@@ -491,6 +491,13 @@ func (check *Checker) assertableTo(V *Interface, T Type) (method, wrongType *Fun
 // Otherwise it returns (typ, false).
 func deref(typ Type) (Type, bool) {
 	if p, _ := typ.(*Pointer); p != nil {
+		// p.base should never be nil, but be conservative
+		if p.base == nil {
+			if debug {
+				panic("pointer with nil base type (possibly due to an invalid cyclic declaration)")
+			}
+			return Typ[Invalid], true
+		}
 		return p.base, true
 	}
 	return typ, false
diff --git a/src/cmd/compile/internal/types2/testdata/check/cycles.src b/src/cmd/compile/internal/types2/testdata/check/cycles.src
index b2ee8ecd5f..998f9f7da9 100644
--- a/src/cmd/compile/internal/types2/testdata/check/cycles.src
+++ b/src/cmd/compile/internal/types2/testdata/check/cycles.src
@@ -45,6 +45,7 @@ type (
 
 	// pointers
 	P0 *P0
+	PP *struct{ PP.f /* ERROR no field or method f */ }
 
 	// functions
 	F0 func(F0)
diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go
index 7fcb196c5a..af195c08a4 100644
--- a/src/cmd/compile/internal/types2/type.go
+++ b/src/cmd/compile/internal/types2/type.go
@@ -21,13 +21,10 @@ type Type interface {
 // under must only be called when a type is known
 // to be fully set up.
 func under(t Type) Type {
-	switch t := t.(type) {
-	case *Named:
+	if t, _ := t.(*Named); t != nil {
 		return t.under()
-	case *TypeParam:
-		return t.iface()
 	}
-	return t
+	return t.Underlying()
 }
 
 // If x and y are identical, match returns x.
diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go
index e22b1ff0a0..e077879b9d 100644
--- a/src/cmd/compile/internal/types2/typexpr.go
+++ b/src/cmd/compile/internal/types2/typexpr.go
@@ -315,6 +315,7 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) {
 	case *syntax.Operation:
 		if e.Op == syntax.Mul && e.Y == nil {
 			typ := new(Pointer)
+			typ.base = Typ[Invalid] // avoid nil base in invalid recursive type declaration
 			def.setUnderlying(typ)
 			typ.base = check.varType(e.X)
 			// If typ.base is invalid, it's unlikely that *base is particularly
-- 
GitLab


From dfa62c79de4f6f6ee2eb8cde340c21afc739c38d Mon Sep 17 00:00:00 2001
From: Keith Randall 
Date: Fri, 12 Nov 2021 15:48:01 -0800
Subject: [PATCH 2172/2500] doc: document GOAMD64 environment variable

Update #47694

Change-Id: I9c90bd251616cd4d10434bd3b6e6c30c5c819e24
Reviewed-on: https://go-review.googlesource.com/c/go/+/363661
Trust: Keith Randall 
Reviewed-by: Ian Lance Taylor 
---
 doc/go1.18.html | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/doc/go1.18.html b/doc/go1.18.html
index 45f89b7be5..e796215c78 100644
--- a/doc/go1.18.html
+++ b/doc/go1.18.html
@@ -40,6 +40,19 @@ Do not send CLs removing the interior tags from such phrases.
   FreeBSD 13.0+ will require a kernel with the COMPAT_FREEBSD12 option set (this is the default).
 

+

AMD64

+ +

+ Go 1.18 introduces the new GOAMD64 environment variable which selects + a version of the AMD64 architecture. Allowed values are v1, + v2, v3, or v4. Each higher level requires, + and takes advantage of, additional processor features. A detailed description of the + versions is here. +

+

+ The GOAMD64 environment variable defaults to v1. +

+

PPC64

@@ -123,10 +136,6 @@ Do not send CLs removing the interior tags from such phrases. third-party tools that need to collect package source code.)

-

- TODO: https://golang.org/cl/349595: cmd/go: add GOAMD64 environment variable -

-

gofmt

-- GitLab From 5337e53dfa3f5fde73b8f505ec3a91c628e8f648 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 12 Nov 2021 12:38:29 -0800 Subject: [PATCH 2173/2500] cmd/compile: ensure we replace package placeholder in type names We want package names exposed by reflect to be things like main.F[main.foo], not main.F["".foo]. Fixes #49547 Change-Id: I182411a75d56ce1f64fde847e5b9ee74ce44e00b Reviewed-on: https://go-review.googlesource.com/c/go/+/363656 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/types/fmt.go | 8 +++++++- test/typeparam/issue49547.go | 22 ++++++++++++++++++++++ test/typeparam/nested.out | 6 +++--- 3 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 test/typeparam/issue49547.go diff --git a/src/cmd/compile/internal/types/fmt.go b/src/cmd/compile/internal/types/fmt.go index 23fc4221e1..b20d2e2908 100644 --- a/src/cmd/compile/internal/types/fmt.go +++ b/src/cmd/compile/internal/types/fmt.go @@ -140,11 +140,17 @@ func sconv2(b *bytes.Buffer, s *Sym, verb rune, mode fmtMode) { } func symfmt(b *bytes.Buffer, s *Sym, verb rune, mode fmtMode) { + name := s.Name if q := pkgqual(s.Pkg, verb, mode); q != "" { b.WriteString(q) b.WriteByte('.') + if mode == fmtTypeIDName { + // If name is a generic instantiation, it might have local package placeholders + // in it. Replace those placeholders with the package name. See issue 49547. + name = strings.Replace(name, LocalPkg.Prefix, q, -1) + } } - b.WriteString(s.Name) + b.WriteString(name) } // pkgqual returns the qualifier that should be used for printing diff --git a/test/typeparam/issue49547.go b/test/typeparam/issue49547.go new file mode 100644 index 0000000000..99c124d7ab --- /dev/null +++ b/test/typeparam/issue49547.go @@ -0,0 +1,22 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "fmt" + +type foo int + +func main() { + want := "main.F[main.foo]" + got := fmt.Sprintf("%T", F[foo]{}) + if got != want { + fmt.Printf("want: %s, got: %s\n", want, got) + } +} + +type F[T any] struct { +} diff --git a/test/typeparam/nested.out b/test/typeparam/nested.out index 9110518248..37cb762e32 100644 --- a/test/typeparam/nested.out +++ b/test/typeparam/nested.out @@ -1,4 +1,4 @@ 0,3: main.T·2[int;int] -4,7: main.T·2[int;"".U·3[int;int]] -22,23: main.T·2["".Int;"".Int] -26,27: main.T·2["".Int;"".U·3["".Int;"".Int]] +4,7: main.T·2[int;main.U·3[int;int]] +22,23: main.T·2[main.Int;main.Int] +26,27: main.T·2[main.Int;main.U·3[main.Int;main.Int]] -- GitLab From ce4a2755956a42aa3211c121139a52c9a97a9aa0 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 12 Nov 2021 19:53:28 -0500 Subject: [PATCH 2174/2500] cmd/compile, runtime: mark R1 as clobbered for write barrier call If the call to gcWriteBarrier is via PLT, the PLT stub will clobber R1. Mark R1 clobbered. For #49386. Change-Id: I72df5bb3b8d10381fec5c567b15749aaf7d2ad70 Reviewed-on: https://go-review.googlesource.com/c/go/+/363698 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/cmd/compile/internal/ssa/gen/S390XOps.go | 5 +++-- src/cmd/compile/internal/ssa/opGen.go | 2 +- src/runtime/asm_s390x.s | 10 ++++------ 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/cmd/compile/internal/ssa/gen/S390XOps.go b/src/cmd/compile/internal/ssa/gen/S390XOps.go index cd7bad7acb..eef8a2557c 100644 --- a/src/cmd/compile/internal/ssa/gen/S390XOps.go +++ b/src/cmd/compile/internal/ssa/gen/S390XOps.go @@ -509,8 +509,9 @@ func init() { // LoweredWB invokes runtime.gcWriteBarrier. arg0=destptr, arg1=srcptr, arg2=mem, aux=runtime.gcWriteBarrier // It saves all GP registers if necessary, - // but clobbers R14 (LR) because it's a call. - {name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("R2"), buildReg("R3")}, clobbers: (callerSave &^ gpg) | buildReg("R14")}, clobberFlags: true, aux: "Sym", symEffect: "None"}, + // but clobbers R14 (LR) because it's a call, + // and also clobbers R1 as the PLT stub does. + {name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("R2"), buildReg("R3")}, clobbers: (callerSave &^ gpg) | buildReg("R14") | r1}, clobberFlags: true, aux: "Sym", symEffect: "None"}, // There are three of these functions so that they can have three different register inputs. // When we check 0 <= c <= cap (A), then 0 <= b <= c (B), then 0 <= a <= b (C), we want the diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 2038575b0c..81fe5d4c23 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -32779,7 +32779,7 @@ var opcodeTable = [...]opInfo{ {0, 4}, // R2 {1, 8}, // R3 }, - clobbers: 4294918144, // R14 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 + clobbers: 4294918146, // R1 R14 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 }, }, { diff --git a/src/runtime/asm_s390x.s b/src/runtime/asm_s390x.s index 5894fe5783..9159a67372 100644 --- a/src/runtime/asm_s390x.s +++ b/src/runtime/asm_s390x.s @@ -777,13 +777,12 @@ TEXT ·checkASM(SB),NOSPLIT,$0-1 // gcWriteBarrier does NOT follow the Go ABI. It takes two arguments: // - R2 is the destination of the write // - R3 is the value being written at R2. -// It clobbers R10 (the temp register). +// It clobbers R10 (the temp register) and R1 (used by PLT stub). // It does not clobber any other general-purpose registers, // but may clobber others (e.g., floating point registers). -TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$104 +TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$96 // Save the registers clobbered by the fast path. - MOVD R1, 96(R15) - MOVD R4, 104(R15) + MOVD R4, 96(R15) MOVD g_m(g), R1 MOVD m_p(R1), R1 // Increment wbBuf.next position. @@ -798,8 +797,7 @@ TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$104 // Is the buffer full? CMPBEQ R4, R1, flush ret: - MOVD 96(R15), R1 - MOVD 104(R15), R4 + MOVD 96(R15), R4 // Do the write. MOVD R3, (R2) RET -- GitLab From f986191325e9c8be606b5f4db69a33692728274b Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Thu, 11 Nov 2021 18:12:20 +0000 Subject: [PATCH 2175/2500] runtime: fix released bytes accumulation in bg scavenger Currently "released" is not accumulated bytes released. If the last attempt to scavenge ends up as 0, then the scavenger will go to sleep too soon. This is an artifact from the old code where scavenge would only be called into once. Change-Id: I85aa2261f1504a6fb5bf086daa029eecb0e09cf4 Reviewed-on: https://go-review.googlesource.com/c/go/+/363416 Trust: Michael Knyszek Reviewed-by: Michael Pratt Run-TryBot: Michael Knyszek TryBot-Result: Go Bot --- src/runtime/mgcscavenge.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/runtime/mgcscavenge.go b/src/runtime/mgcscavenge.go index 4a7f2465fd..286aa1bbae 100644 --- a/src/runtime/mgcscavenge.go +++ b/src/runtime/mgcscavenge.go @@ -326,8 +326,8 @@ func bgscavenge(c chan int) { // Accumulate the amount of time spent scavenging. start := nanotime() - released = mheap_.pages.scavenge(scavengeQuantum) - atomic.Xadduintptr(&mheap_.pages.scav.released, released) + r := mheap_.pages.scavenge(scavengeQuantum) + atomic.Xadduintptr(&mheap_.pages.scav.released, r) end := nanotime() // On some platforms we may see end >= start if the time it takes to scavenge @@ -339,10 +339,11 @@ func bgscavenge(c chan int) { // on timing. const approxCritNSPerPhysicalPage = 10e3 if end <= start { - crit += approxCritNSPerPhysicalPage * float64(released/physPageSize) + crit += approxCritNSPerPhysicalPage * float64(r/physPageSize) } else { crit += float64(end - start) } + released += r } if released == 0 { -- GitLab From 1dc9af5cdc6dabe4841afb4edf9dbf5124946ea0 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sat, 13 Nov 2021 16:17:52 -0800 Subject: [PATCH 2176/2500] cmd/compile: fix position info for implicit nodes due to generics The main fix is that we should call ir.SetPos() at the beginning of (*subster).node.edit function, since that is analogous to the ir.SetPos() at the beginning of typecheck.typecheck(). It ensures that transform functions can use base.Pos() with appropriate results, just like their corresponding tc*() functions do. A small fix is to make sure that the new nodes creates for dictionary references have the correct position based on the location of the function call. Another small fix is to the use of base.Pos when creating a new selector expression (including implicit XDOTs) for a method expression in buildClosure(). Also, I converted the final use of base.Pos in stencil.go to src.NoXPos, since the nodes created by AddImplicitDots will be checked for their type, but won't actually be used. I also needed to add an ir.SetPos() at the beginning of transformCall(), since transformCall() is called in the modify and dict passes, when we base.Pos is not being set for each node. This change fixes all the line numbering problems printed out from Alessandro's program, except for auto-generated functions (which I think are fine). Fixes #49523 Change-Id: I9836a497b7beba25ecafdde653a6c2036a3020d3 Reviewed-on: https://go-review.googlesource.com/c/go/+/363835 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 25 +++++++++++++-------- src/cmd/compile/internal/noder/transform.go | 3 +++ 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 4f9f8107bc..174006ab5e 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -500,7 +500,7 @@ func (g *genInst) buildClosure(outer *ir.Func, x ir.Node) ir.Node { // explicitly traverse any embedded fields in the receiver // argument in order to call the method instantiation. arg0 := formalParams[0].Nname.(ir.Node) - arg0 = typecheck.AddImplicitDots(ir.NewSelectorExpr(base.Pos, ir.OXDOT, arg0, x.(*ir.SelectorExpr).Sel)).X + arg0 = typecheck.AddImplicitDots(ir.NewSelectorExpr(x.Pos(), ir.OXDOT, arg0, x.(*ir.SelectorExpr).Sel)).X if valueMethod && arg0.Type().IsPtr() { // For handling the (*T).M case: if we have a pointer // receiver after following all the embedded fields, @@ -616,7 +616,7 @@ func (g *genInst) getDictOrSubdict(declInfo *instInfo, n ir.Node, nameNode *ir.N } } if !usingSubdict { - dict = g.getDictionaryValue(nameNode, targs, isMeth) + dict = g.getDictionaryValue(n.Pos(), nameNode, targs, isMeth) } return dict, usingSubdict } @@ -905,6 +905,10 @@ func (subst *subster) node(n ir.Node) ir.Node { // Use closure to capture all state needed by the ir.EditChildren argument. var edit func(ir.Node) ir.Node edit = func(x ir.Node) ir.Node { + // Analogous to ir.SetPos() at beginning of typecheck.typecheck() - + // allows using base.Pos during the transform functions, just like + // the tc*() functions. + ir.SetPos(x) switch x.Op() { case ir.OTYPE: return ir.TypeNode(subst.ts.Typ(x.Type())) @@ -1555,9 +1559,9 @@ func (g *genInst) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool if se.X.Type().IsShape() { // This is a method call enabled by a type bound. - // We need this extra check for type expressions, which - // don't add in the implicit XDOTs. - tmpse := ir.NewSelectorExpr(base.Pos, ir.OXDOT, se.X, se.Sel) + // We need this extra check for method expressions, + // which don't add in the implicit XDOTs. + tmpse := ir.NewSelectorExpr(src.NoXPos, ir.OXDOT, se.X, se.Sel) tmpse = typecheck.AddImplicitDots(tmpse) tparam := tmpse.X.Type() if !tparam.IsShape() { @@ -1725,7 +1729,7 @@ func (g *genInst) finalizeSyms() { g.dictSymsToFinalize = nil } -func (g *genInst) getDictionaryValue(gf *ir.Name, targs []*types.Type, isMeth bool) ir.Node { +func (g *genInst) getDictionaryValue(pos src.XPos, gf *ir.Name, targs []*types.Type, isMeth bool) ir.Node { sym := g.getDictionarySym(gf, targs, isMeth) // Make (or reuse) a node referencing the dictionary symbol. @@ -1733,15 +1737,18 @@ func (g *genInst) getDictionaryValue(gf *ir.Name, targs []*types.Type, isMeth bo if sym.Def != nil { n = sym.Def.(*ir.Name) } else { - n = typecheck.NewName(sym) + // We set the position of a static dictionary to be the position of + // one of its uses. + n = ir.NewNameAt(pos, sym) + n.Curfn = ir.CurFunc n.SetType(types.Types[types.TUINTPTR]) // should probably be [...]uintptr, but doesn't really matter n.SetTypecheck(1) n.Class = ir.PEXTERN sym.Def = n } - // Return the address of the dictionary. - np := typecheck.NodAddr(n) + // Return the address of the dictionary. Addr node gets position that was passed in. + np := typecheck.NodAddrAt(pos, n) // Note: treat dictionary pointers as uintptrs, so they aren't pointers // with respect to GC. That saves on stack scanning work, write barriers, etc. // We can get away with it because dictionaries are global variables. diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index 47e6397206..a673484821 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -133,6 +133,9 @@ func transformConvCall(n *ir.CallExpr) ir.Node { // (non-conversion, non-builtin part) of typecheck.tcCall. This code should work even // in the case of OCALL/OFUNCINST. func transformCall(n *ir.CallExpr) { + // Set base.Pos, since transformArgs below may need it, but transformCall + // is called in some passes that don't set base.Pos. + ir.SetPos(n) // n.Type() can be nil for calls with no return value assert(n.Typecheck() == 1) transformArgs(n) -- GitLab From 0e654100382f345ea555cfc1e1dd50853316b368 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sun, 14 Nov 2021 20:34:58 -0500 Subject: [PATCH 2177/2500] go/types: assign error codes to new errors for Go 1.18 During development, we used placeholder _Todo error codes for new errors related to generics. Add real error codes in these places. As a result, 9 new error codes are added for ~50 call sites. Change-Id: Ib57b4cd9f0a2e160971a3aeea18f9fe26fc0f835 Reviewed-on: https://go-review.googlesource.com/c/go/+/363874 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/assignments.go | 2 +- src/go/types/builtins.go | 2 +- src/go/types/call.go | 14 +++--- src/go/types/decl.go | 10 ++-- src/go/types/errorcodes.go | 84 +++++++++++++++++++++++++++++++++ src/go/types/errorcodes_test.go | 6 ++- src/go/types/expr.go | 8 ++-- src/go/types/infer.go | 14 ++++-- src/go/types/instantiate.go | 2 +- src/go/types/interface.go | 2 +- src/go/types/resolver.go | 6 +-- src/go/types/signature.go | 4 +- src/go/types/stmt.go | 2 +- src/go/types/struct.go | 9 ++-- src/go/types/typeset.go | 6 +-- src/go/types/typexpr.go | 10 ++-- src/go/types/union.go | 12 ++--- 17 files changed, 142 insertions(+), 51 deletions(-) diff --git a/src/go/types/assignments.go b/src/go/types/assignments.go index 923bd43b49..d77cf8f7fa 100644 --- a/src/go/types/assignments.go +++ b/src/go/types/assignments.go @@ -72,7 +72,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { // A generic (non-instantiated) function value cannot be assigned to a variable. if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 { - check.errorf(x, _Todo, "cannot use generic function %s without instantiation in %s", x, context) + check.errorf(x, _WrongTypeArgCount, "cannot use generic function %s without instantiation in %s", x, context) } // spec: "If a left-hand side is the blank identifier, any typed or diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 4d3ff26b14..c2d36e9711 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -370,7 +370,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b return false } if key != nil && !Identical(map_.key, key) { - check.invalidArg(x, _Todo, "maps of %s must have identical key types", x) + check.invalidArg(x, _InvalidDelete, "maps of %s must have identical key types", x) return false } key = map_.key diff --git a/src/go/types/call.go b/src/go/types/call.go index da4b72a0c7..927c9f2a44 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -18,7 +18,7 @@ import ( // The operand x must be the evaluation of inst.X and its type must be a signature. func (check *Checker) funcInst(x *operand, ix *typeparams.IndexExpr) { if !check.allowVersion(check.pkg, 1, 18) { - check.softErrorf(inNode(ix.Orig, ix.Lbrack), _Todo, "function instantiation requires go1.18 or later") + check.softErrorf(inNode(ix.Orig, ix.Lbrack), _UnsupportedFeature, "function instantiation requires go1.18 or later") } targs := check.typeList(ix.Indices) @@ -33,7 +33,7 @@ func (check *Checker) funcInst(x *operand, ix *typeparams.IndexExpr) { sig := x.typ.(*Signature) got, want := len(targs), sig.TypeParams().Len() if got > want { - check.errorf(ix.Indices[got-1], _Todo, "got %d type arguments but want %d", got, want) + check.errorf(ix.Indices[got-1], _WrongTypeArgCount, "got %d type arguments but want %d", got, want) x.mode = invalid x.expr = ix.Orig return @@ -90,7 +90,7 @@ func (check *Checker) instantiateSignature(pos token.Pos, typ *Signature, targs if i < len(posList) { pos = posList[i] } - check.softErrorf(atPos(pos), _Todo, err.Error()) + check.softErrorf(atPos(pos), _InvalidTypeArg, err.Error()) } else { check.mono.recordInstance(check.pkg, pos, tparams, targs, posList) } @@ -143,7 +143,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { } if t, _ := under(T).(*Interface); t != nil { if !t.IsMethodSet() { - check.errorf(call, _Todo, "cannot use interface %s in conversion (contains specific type constraints or is comparable)", T) + check.errorf(call, _MisplacedConstraintIface, "cannot use interface %s in conversion (contains specific type constraints or is comparable)", T) break } } @@ -198,7 +198,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { // check number of type arguments (got) vs number of type parameters (want) got, want := len(targs), sig.TypeParams().Len() if got > want { - check.errorf(ix.Indices[want], _Todo, "got %d type arguments but want %d", got, want) + check.errorf(ix.Indices[want], _WrongTypeArgCount, "got %d type arguments but want %d", got, want) check.use(call.Args...) x.mode = invalid x.expr = call @@ -370,9 +370,9 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type switch call.Fun.(type) { case *ast.IndexExpr, *ast.IndexListExpr: ix := typeparams.UnpackIndexExpr(call.Fun) - check.softErrorf(inNode(call.Fun, ix.Lbrack), _Todo, "function instantiation requires go1.18 or later") + check.softErrorf(inNode(call.Fun, ix.Lbrack), _UnsupportedFeature, "function instantiation requires go1.18 or later") default: - check.softErrorf(inNode(call, call.Lparen), _Todo, "implicit function instantiation requires go1.18 or later") + check.softErrorf(inNode(call, call.Lparen), _UnsupportedFeature, "implicit function instantiation requires go1.18 or later") } } // TODO(gri) provide position information for targs so we can feed diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 7e89e7be3a..e12961416e 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -623,7 +623,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { check.validType(obj.typ, nil) // If typ is local, an error was already reported where typ is specified/defined. if check.isImportedConstraint(rhs) && !check.allowVersion(check.pkg, 1, 18) { - check.errorf(tdecl.Type, _Todo, "using type constraint %s requires go1.18 or later", rhs) + check.errorf(tdecl.Type, _UnsupportedFeature, "using type constraint %s requires go1.18 or later", rhs) } }).describef(obj, "validType(%s)", obj.Name()) @@ -631,7 +631,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { if alias && tdecl.TypeParams.NumFields() != 0 { // The parser will ensure this but we may still get an invalid AST. // Complain and continue as regular type definition. - check.error(atPos(tdecl.Assign), _Todo, "generic type cannot be alias") + check.error(atPos(tdecl.Assign), _BadDecl, "generic type cannot be alias") alias = false } @@ -673,7 +673,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { // type (underlying not fully resolved yet) it cannot become a type parameter due // to this very restriction. if tpar, _ := named.underlying.(*TypeParam); tpar != nil { - check.error(tdecl.Type, _Todo, "cannot use a type parameter as RHS in type declaration") + check.error(tdecl.Type, _MisplacedTypeParam, "cannot use a type parameter as RHS in type declaration") named.underlying = Typ[Invalid] } } @@ -724,7 +724,7 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list *ast.FieldList check.later(func() { for i, bound := range bounds { if _, ok := under(bound).(*TypeParam); ok { - check.error(posns[i], _Todo, "cannot use a type parameter as constraint") + check.error(posns[i], _MisplacedTypeParam, "cannot use a type parameter as constraint") } } for _, tpar := range tparams { @@ -861,7 +861,7 @@ func (check *Checker) funcDecl(obj *Func, decl *declInfo) { obj.color_ = saved if fdecl.Type.TypeParams.NumFields() > 0 && fdecl.Body == nil { - check.softErrorf(fdecl.Name, _Todo, "parameterized function is missing function body") + check.softErrorf(fdecl.Name, _BadDecl, "parameterized function is missing function body") } // function body must be type-checked after global declarations diff --git a/src/go/types/errorcodes.go b/src/go/types/errorcodes.go index 88dd0fda2f..cbf00ba0b4 100644 --- a/src/go/types/errorcodes.go +++ b/src/go/types/errorcodes.go @@ -1301,6 +1301,54 @@ const ( // var _ = unsafe.Slice(&x, uint64(1) << 63) _InvalidUnsafeSlice + // All codes below were added in Go 1.18. + + // _UnsupportedFeature occurs when a language feature is used that is not + // supported at this Go version. + _UnsupportedFeature + + // _WrongTypeArgCount occurs when a type or function is instantiated with an + // incorrent number of type arguments, including when a generic type or + // function is used without instantiation. + // + // Errors inolving failed type inference are assigned other error codes. + // + // Example: + // type T[p any] int + // + // var _ T[int, string] + // + // Example: + // func f[T any]() {} + // + // var x = f + _WrongTypeArgCount + + // _CannotInferTypeArgs occurs when type or function type argument inference + // fails to infer all type arguments. + // + // Example: + // func f[T any]() {} + // + // func _() { + // f() + // } + // + // Example: + // type N[P, Q any] struct{} + // + // var _ N[int] + _CannotInferTypeArgs + + // _InvalidTypeArg occurs when a type argument does not satisfy its + // corresponding type parameter constraints. + // + // Example: + // type T[P ~int] struct{} + // + // var _ T[string] + _InvalidTypeArg // arguments? InferenceFailed + // _InvalidInstanceCycle occurs when an invalid cycle is detected // within the instantiation graph. // @@ -1308,6 +1356,42 @@ const ( // func f[T any]() { f[*T]() } _InvalidInstanceCycle + // _InvalidUnion occurs when an embedded union or approximation element is + // not valid. + // + // Example: + // type _ interface { + // ~int | interface{ m() } + // } + _InvalidUnion + + // _MisplacedConstraintIface occurs when a constraint-type interface is used + // outside of constraint position. + // + // Example: + // type I interface { ~int } + // + // var _ I + _MisplacedConstraintIface + + // _InvalidMethodTypeParams occurs when methods have type parameters. + // + // Example: + // type T int + // + // func (T) m[P any]() {} + _InvalidMethodTypeParams + + // _MisplacedTypeParam occurs when a type parameter is used in a place where + // it is not permitted. + // + // Example: + // type T[P any] P + // + // Example: + // type T[P any] struct{ *P } + _MisplacedTypeParam + // _Todo is a placeholder for error codes that have not been decided. // TODO(rFindley) remove this error code after deciding on errors for generics code. _Todo diff --git a/src/go/types/errorcodes_test.go b/src/go/types/errorcodes_test.go index 5da1cdadfc..629eac4912 100644 --- a/src/go/types/errorcodes_test.go +++ b/src/go/types/errorcodes_test.go @@ -171,8 +171,10 @@ func TestErrorCodeStyle(t *testing.T) { } } doc := spec.Doc.Text() - if !strings.HasPrefix(doc, name) { - t.Errorf("doc for %q does not start with identifier", name) + if doc == "" { + t.Errorf("%q is undocumented", name) + } else if !strings.HasPrefix(doc, name) { + t.Errorf("doc for %q does not start with the error code name", name) } lowerComment := strings.ToLower(strings.TrimPrefix(doc, name)) for _, bad := range forbiddenInComment { diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 138eb2f521..9d9eddfb95 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -186,7 +186,7 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr) { return false } if elem != nil && !Identical(ch.elem, elem) { - check.invalidOp(x, _Todo, "channels of %s must have the same element type", x) + check.invalidOp(x, _InvalidReceive, "channels of %s must have the same element type", x) return false } elem = ch.elem @@ -1116,7 +1116,7 @@ func (check *Checker) nonGeneric(x *operand) { } } if what != "" { - check.errorf(x.expr, _Todo, "cannot use generic %s %s without instantiation", what, x.expr) + check.errorf(x.expr, _WrongTypeArgCount, "cannot use generic %s %s without instantiation", what, x.expr) x.mode = invalid x.typ = Typ[Invalid] } @@ -1233,7 +1233,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { // Prevent crash if the struct referred to is not yet set up. // See analogous comment for *Array. if utyp.fields == nil { - check.error(e, _Todo, "illegal cycle in type declaration") + check.error(e, _InvalidDeclCycle, "illegal cycle in type declaration") goto Error } if len(e.Elts) == 0 { @@ -1472,7 +1472,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { return false } if base != nil && !Identical(p.base, base) { - check.invalidOp(x, _Todo, "pointers of %s must have identical base types", x) + check.invalidOp(x, _InvalidIndirection, "pointers of %s must have identical base types", x) return false } base = p.base diff --git a/src/go/types/infer.go b/src/go/types/infer.go index 41326a1be8..f4f9bfac8f 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -118,17 +118,21 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, } } if allFailed { - check.errorf(arg, _Todo, "%s %s of %s does not match %s (cannot infer %s)", kind, targ, arg.expr, tpar, typeParamsString(tparams)) + check.errorf(arg, _CannotInferTypeArgs, "%s %s of %s does not match %s (cannot infer %s)", kind, targ, arg.expr, tpar, typeParamsString(tparams)) return } } smap := makeSubstMap(tparams, targs) // TODO(rFindley): pass a positioner here, rather than arg.Pos(). inferred := check.subst(arg.Pos(), tpar, smap, nil) + // _CannotInferTypeArgs indicates a failure of inference, though the actual + // error may be better attributed to a user-provided type argument (hence + // _InvalidTypeArg). We can't differentiate these cases, so fall back on + // the more general _CannotInferTypeArgs. if inferred != tpar { - check.errorf(arg, _Todo, "%s %s of %s does not match inferred type %s for %s", kind, targ, arg.expr, inferred, tpar) + check.errorf(arg, _CannotInferTypeArgs, "%s %s of %s does not match inferred type %s for %s", kind, targ, arg.expr, inferred, tpar) } else { - check.errorf(arg, _Todo, "%s %s of %s does not match %s", kind, targ, arg.expr, tpar) + check.errorf(arg, _CannotInferTypeArgs, "%s %s of %s does not match %s", kind, targ, arg.expr, tpar) } } @@ -214,7 +218,7 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, // At least one type argument couldn't be inferred. assert(index >= 0 && targs[index] == nil) tpar := tparams[index] - check.errorf(posn, _Todo, "cannot infer %s (%v)", tpar.obj.name, tpar.obj.pos) + check.errorf(posn, _CannotInferTypeArgs, "cannot infer %s (%v)", tpar.obj.name, tpar.obj.pos) return nil } @@ -383,7 +387,7 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type, if !u.unify(tpar, sbound) { // TODO(gri) improve error message by providing the type arguments // which we know already - check.errorf(tpar.obj, _Todo, "%s does not match %s", tpar, sbound) + check.errorf(tpar.obj, _InvalidTypeArg, "%s does not match %s", tpar, sbound) return nil, 0 } } diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 2d2d1718f4..13d6e3114d 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -124,7 +124,7 @@ func (check *Checker) validateTArgLen(pos token.Pos, ntparams, ntargs int) bool if ntargs != ntparams { // TODO(gri) provide better error message if check != nil { - check.errorf(atPos(pos), _Todo, "got %d arguments but %d type parameters", ntargs, ntparams) + check.errorf(atPos(pos), _WrongTypeArgCount, "got %d arguments but %d type parameters", ntargs, ntparams) return false } panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, ntargs, ntparams)) diff --git a/src/go/types/interface.go b/src/go/types/interface.go index 78813e665b..ef65bc6b2b 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -181,7 +181,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d if ftyp, _ := f.Type.(*ast.FuncType); ftyp != nil && ftyp.TypeParams != nil { at = ftyp.TypeParams } - check.errorf(at, _Todo, "methods cannot have type parameters") + check.errorf(at, _InvalidMethodTypeParams, "methods cannot have type parameters") } // use named receiver type if available (for better error messages) diff --git a/src/go/types/resolver.go b/src/go/types/resolver.go index 5a82b4fd9c..7a2dcbffbb 100644 --- a/src/go/types/resolver.go +++ b/src/go/types/resolver.go @@ -382,7 +382,7 @@ func (check *Checker) collectObjects() { } case typeDecl: if d.spec.TypeParams.NumFields() != 0 && !check.allowVersion(pkg, 1, 18) { - check.softErrorf(d.spec.TypeParams.List[0], _Todo, "type parameters require go1.18 or later") + check.softErrorf(d.spec.TypeParams.List[0], _UnsupportedFeature, "type parameters require go1.18 or later") } obj := NewTypeName(d.spec.Name.Pos(), pkg, d.spec.Name.Name, nil) check.declarePkgObj(d.spec.Name, obj, &declInfo{file: fileScope, tdecl: d.spec}) @@ -440,7 +440,7 @@ func (check *Checker) collectObjects() { check.recordDef(d.decl.Name, obj) } if d.decl.Type.TypeParams.NumFields() != 0 && !check.allowVersion(pkg, 1, 18) && !hasTParamError { - check.softErrorf(d.decl.Type.TypeParams.List[0], _Todo, "type parameters require go1.18 or later") + check.softErrorf(d.decl.Type.TypeParams.List[0], _UnsupportedFeature, "type parameters require go1.18 or later") } info := &declInfo{file: fileScope, fdecl: d.decl} // Methods are not package-level objects but we still track them in the @@ -527,7 +527,7 @@ L: // unpack receiver type case nil: check.invalidAST(ix.Orig, "parameterized receiver contains nil parameters") default: - check.errorf(arg, _Todo, "receiver type parameter %s must be an identifier", arg) + check.errorf(arg, _BadDecl, "receiver type parameter %s must be an identifier", arg) } if par == nil { par = &ast.Ident{NamePos: arg.Pos(), Name: "_"} diff --git a/src/go/types/signature.go b/src/go/types/signature.go index 698b89c462..306d86c0b7 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -168,7 +168,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast // (A separate check is needed when type-checking interface method signatures because // they don't have a receiver specification.) if recvPar != nil { - check.errorf(ftyp.TypeParams, _Todo, "methods cannot have type parameters") + check.errorf(ftyp.TypeParams, _InvalidMethodTypeParams, "methods cannot have type parameters") } } @@ -215,7 +215,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast // The receiver type may be an instantiated type referred to // by an alias (which cannot have receiver parameters for now). if T.TypeArgs() != nil && sig.RecvTypeParams() == nil { - check.errorf(atPos(recv.pos), _Todo, "cannot define methods on instantiated type %s", recv.typ) + check.errorf(atPos(recv.pos), _InvalidRecv, "cannot define methods on instantiated type %s", recv.typ) break } // spec: "The type denoted by T is called the receiver base type; it must not diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index c000d935d6..2a3fb5f6f5 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -429,7 +429,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { return false } if elem != nil && !Identical(uch.elem, elem) { - check.invalidOp(inNode(s, s.Arrow), _Todo, "channels of %s must have the same element type", &ch) + check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "channels of %s must have the same element type", &ch) return false } elem = uch.elem diff --git a/src/go/types/struct.go b/src/go/types/struct.go index 60640ac578..84af8a3f48 100644 --- a/src/go/types/struct.go +++ b/src/go/types/struct.go @@ -124,9 +124,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) { pos := f.Type.Pos() name := embeddedFieldIdent(f.Type) if name == nil { - // TODO(rFindley): using invalidAST here causes test failures (all - // errors should have codes). Clean this up. - check.errorf(f.Type, _Todo, "invalid AST: embedded field type %s has no name", f.Type) + check.invalidAST(f.Type, "embedded field type %s has no name", f.Type) name = ast.NewIdent("_") name.NamePos = pos addInvalid(name, pos) @@ -158,7 +156,10 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) { case *Pointer: check.error(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a pointer") case *TypeParam: - check.error(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a (pointer to a) type parameter") + // This error code here is inconsistent with other error codes for + // invalid embedding, because this restriction may be relaxed in the + // future, and so it did not warrant a new error code. + check.error(embeddedPos, _MisplacedTypeParam, "embedded field type cannot be a (pointer to a) type parameter") case *Interface: if isPtr { check.error(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a pointer to an interface") diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index f8e76ed400..1e6b9dd390 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -269,7 +269,7 @@ func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_T tset := computeInterfaceTypeSet(check, pos, u) // If typ is local, an error was already reported where typ is specified/defined. if check != nil && check.isImportedConstraint(typ) && !check.allowVersion(check.pkg, 1, 18) { - check.errorf(atPos(pos), _Todo, "embedding constraint interface %s requires go1.18 or later", typ) + check.errorf(atPos(pos), _UnsupportedFeature, "embedding constraint interface %s requires go1.18 or later", typ) continue } if tset.comparable { @@ -281,7 +281,7 @@ func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_T terms = tset.terms case *Union: if check != nil && !check.allowVersion(check.pkg, 1, 18) { - check.errorf(atPos(pos), _Todo, "embedding interface element %s requires go1.18 or later", u) + check.errorf(atPos(pos), _InvalidIfaceEmbed, "embedding interface element %s requires go1.18 or later", u) continue } tset := computeUnionTypeSet(check, pos, u) @@ -385,7 +385,7 @@ func computeUnionTypeSet(check *Checker, pos token.Pos, utyp *Union) *_TypeSet { allTerms = allTerms.union(terms) if len(allTerms) > maxTermCount { if check != nil { - check.errorf(atPos(pos), _Todo, "cannot handle more than %d union terms (implementation limitation)", maxTermCount) + check.errorf(atPos(pos), _InvalidUnion, "cannot handle more than %d union terms (implementation limitation)", maxTermCount) } utyp.tset = &invalidTypeSet return utyp.tset diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index cff9917185..c89e69db7b 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -149,9 +149,9 @@ func (check *Checker) varType(e ast.Expr) Type { tset := computeInterfaceTypeSet(check, e.Pos(), t) // TODO(gri) is this the correct position? if !tset.IsMethodSet() { if tset.comparable { - check.softErrorf(e, _Todo, "interface is (or embeds) comparable") + check.softErrorf(e, _MisplacedConstraintIface, "interface is (or embeds) comparable") } else { - check.softErrorf(e, _Todo, "interface contains type constraints") + check.softErrorf(e, _MisplacedConstraintIface, "interface contains type constraints") } } } @@ -169,7 +169,7 @@ func (check *Checker) definedType(e ast.Expr, def *Named) Type { typ := check.typInternal(e, def) assert(isTyped(typ)) if isGeneric(typ) { - check.errorf(e, _Todo, "cannot use generic type %s without instantiation", typ) + check.errorf(e, _WrongTypeArgCount, "cannot use generic type %s without instantiation", typ) typ = Typ[Invalid] } check.recordTypeAndValue(e, typexpr, typ, nil) @@ -261,7 +261,7 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) { case *ast.IndexExpr, *ast.IndexListExpr: ix := typeparams.UnpackIndexExpr(e) if !check.allowVersion(check.pkg, 1, 18) { - check.softErrorf(inNode(e, ix.Lbrack), _Todo, "type instantiation requires go1.18 or later") + check.softErrorf(inNode(e, ix.Lbrack), _UnsupportedFeature, "type instantiation requires go1.18 or later") } return check.instantiatedType(ix.X, ix.Indices, def) @@ -459,7 +459,7 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named if i < len(posList) { pos = posList[i] } - check.softErrorf(atPos(pos), _Todo, err.Error()) + check.softErrorf(atPos(pos), _InvalidTypeArg, err.Error()) } else { check.mono.recordInstance(check.pkg, x.Pos(), inst.tparams.list(), inst.targs.list(), posList) } diff --git a/src/go/types/union.go b/src/go/types/union.go index c715839315..bb08174728 100644 --- a/src/go/types/union.go +++ b/src/go/types/union.go @@ -63,7 +63,7 @@ func parseUnion(check *Checker, tlist []ast.Expr) Type { return typ } if len(terms) >= maxTermCount { - check.errorf(x, _Todo, "cannot handle more than %d union terms (implementation limitation)", maxTermCount) + check.errorf(x, _InvalidUnion, "cannot handle more than %d union terms (implementation limitation)", maxTermCount) return Typ[Invalid] } terms = append(terms, NewTerm(tilde, typ)) @@ -82,12 +82,12 @@ func parseUnion(check *Checker, tlist []ast.Expr) Type { f, _ := u.(*Interface) if t.tilde { if f != nil { - check.errorf(tlist[i], _Todo, "invalid use of ~ (%s is an interface)", t.typ) + check.errorf(tlist[i], _InvalidUnion, "invalid use of ~ (%s is an interface)", t.typ) continue // don't report another error for t } if !Identical(u, t.typ) { - check.errorf(tlist[i], _Todo, "invalid use of ~ (underlying type of %s is %s)", t.typ, u) + check.errorf(tlist[i], _InvalidUnion, "invalid use of ~ (underlying type of %s is %s)", t.typ, u) continue // don't report another error for t } } @@ -96,14 +96,14 @@ func parseUnion(check *Checker, tlist []ast.Expr) Type { // in the beginning. Embedded interfaces with tilde are excluded above. If we reach // here, we must have at least two terms in the union. if f != nil && !f.typeSet().IsTypeSet() { - check.errorf(tlist[i], _Todo, "cannot use %s in union (interface contains methods)", t) + check.errorf(tlist[i], _InvalidUnion, "cannot use %s in union (interface contains methods)", t) continue // don't report another error for t } // Report overlapping (non-disjoint) terms such as // a|a, a|~a, ~a|~a, and ~a|A (where under(A) == a). if j := overlappingTerm(terms[:i], t); j >= 0 { - check.softErrorf(tlist[i], _Todo, "overlapping terms %s and %s", t, terms[j]) + check.softErrorf(tlist[i], _InvalidUnion, "overlapping terms %s and %s", t, terms[j]) } } }) @@ -124,7 +124,7 @@ func parseTilde(check *Checker, x ast.Expr) (tilde bool, typ Type) { // check to later and could return Typ[Invalid] instead. check.later(func() { if _, ok := under(typ).(*TypeParam); ok { - check.error(x, _Todo, "cannot embed a type parameter") + check.error(x, _MisplacedTypeParam, "cannot embed a type parameter") } }) return -- GitLab From b6342a02ad901e015e1c4eb9f862824029efb7b7 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 15 Nov 2021 10:49:54 -0500 Subject: [PATCH 2178/2500] go/types: return an error message from Checker.genericType The bare error message "%s is not a generic type" is probably never sufficient, so change the signature of genericType to instead return an message that may be formatted as additional context in errors. Along the way, refactor instantiatedType to have access to the entire index expression. Fixes #48827 Change-Id: I0c455c1ce46ac3f1ef2990c997da19e5fc6c4eae Reviewed-on: https://go-review.googlesource.com/c/go/+/363994 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/errorcodes.go | 13 +++-- src/go/types/signature.go | 2 +- .../types/testdata/fixedbugs/issue48827.go2 | 19 ++++++++ src/go/types/typexpr.go | 47 +++++++++++-------- 4 files changed, 56 insertions(+), 25 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue48827.go2 diff --git a/src/go/types/errorcodes.go b/src/go/types/errorcodes.go index cbf00ba0b4..b3796e8919 100644 --- a/src/go/types/errorcodes.go +++ b/src/go/types/errorcodes.go @@ -1307,6 +1307,15 @@ const ( // supported at this Go version. _UnsupportedFeature + // _NotAGenericType occurs when a non-generic type is used where a generic + // type is expected: in type or function instantiation. + // + // Example: + // type T int + // + // var _ T[int] + _NotAGenericType + // _WrongTypeArgCount occurs when a type or function is instantiated with an // incorrent number of type arguments, including when a generic type or // function is used without instantiation. @@ -1391,8 +1400,4 @@ const ( // Example: // type T[P any] struct{ *P } _MisplacedTypeParam - - // _Todo is a placeholder for error codes that have not been decided. - // TODO(rFindley) remove this error code after deciding on errors for generics code. - _Todo ) diff --git a/src/go/types/signature.go b/src/go/types/signature.go index 306d86c0b7..8f89e931fb 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -137,7 +137,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast // Also: Don't report an error via genericType since it will be reported // again when we type-check the signature. // TODO(gri) maybe the receiver should be marked as invalid instead? - if recv, _ := check.genericType(rname, false).(*Named); recv != nil { + if recv, _ := check.genericType(rname, nil).(*Named); recv != nil { recvTParams = recv.TypeParams().list() } } diff --git a/src/go/types/testdata/fixedbugs/issue48827.go2 b/src/go/types/testdata/fixedbugs/issue48827.go2 new file mode 100644 index 0000000000..aa1d12aaf5 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue48827.go2 @@ -0,0 +1,19 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type G[P any] int + +type ( + _ G[int] + _ G[G /* ERROR "cannot use.*without instantiation" */] + _ bool /* ERROR "invalid operation: bool\[int\] \(bool is not a generic type\)" */ [int] + _ bool /* ERROR "invalid operation: bool\[G\] \(bool is not a generic type\)" */[G] +) + +// The example from the issue. +func _() { + _ = &([10]bool /* ERROR "invalid operation.*bool is not a generic type" */ [1 /* ERROR "expected type" */ ]{}) +} diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index c89e69db7b..d80acbe7d6 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -176,13 +176,15 @@ func (check *Checker) definedType(e ast.Expr, def *Named) Type { return typ } -// genericType is like typ but the type must be an (uninstantiated) generic type. -func (check *Checker) genericType(e ast.Expr, reportErr bool) Type { +// genericType is like typ but the type must be an (uninstantiated) generic +// type. If reason is non-nil and the type expression was a valid type but not +// generic, reason will be populated with a message describing the error. +func (check *Checker) genericType(e ast.Expr, reason *string) Type { typ := check.typInternal(e, nil) assert(isTyped(typ)) if typ != Typ[Invalid] && !isGeneric(typ) { - if reportErr { - check.errorf(e, _Todo, "%s is not a generic type", typ) + if reason != nil { + *reason = check.sprintf("%s is not a generic type", typ) } typ = Typ[Invalid] } @@ -263,7 +265,7 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) { if !check.allowVersion(check.pkg, 1, 18) { check.softErrorf(inNode(e, ix.Lbrack), _UnsupportedFeature, "type instantiation requires go1.18 or later") } - return check.instantiatedType(ix.X, ix.Indices, def) + return check.instantiatedType(ix, def) case *ast.ParenExpr: // Generic types must be instantiated before they can be used in any form. @@ -374,29 +376,34 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) { return typ } -func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named) (res Type) { +func (check *Checker) instantiatedType(ix *typeparams.IndexExpr, def *Named) (res Type) { + pos := ix.X.Pos() if trace { - check.trace(x.Pos(), "-- instantiating %s with %s", x, targsx) + check.trace(pos, "-- instantiating %s with %s", ix.X, ix.Indices) check.indent++ defer func() { check.indent-- // Don't format the underlying here. It will always be nil. - check.trace(x.Pos(), "=> %s", res) + check.trace(pos, "=> %s", res) }() } - gtyp := check.genericType(x, true) + var reason string + gtyp := check.genericType(ix.X, &reason) + if reason != "" { + check.invalidOp(ix.Orig, _NotAGenericType, "%s (%s)", ix.Orig, reason) + } if gtyp == Typ[Invalid] { return gtyp // error already reported } orig, _ := gtyp.(*Named) if orig == nil { - panic(fmt.Sprintf("%v: cannot instantiate %v", x.Pos(), gtyp)) + panic(fmt.Sprintf("%v: cannot instantiate %v", ix.Pos(), gtyp)) } // evaluate arguments - targs := check.typeList(targsx) + targs := check.typeList(ix.Indices) if targs == nil { def.setUnderlying(Typ[Invalid]) // avoid later errors due to lazy instantiation return Typ[Invalid] @@ -404,7 +411,7 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named // determine argument positions posList := make([]token.Pos, len(targs)) - for i, arg := range targsx { + for i, arg := range ix.Indices { posList[i] = arg.Pos() } @@ -418,7 +425,7 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named // validation below. Ensure that the validation (and resulting errors) runs // for each instantiated type in the source. if inst == nil { - tname := NewTypeName(x.Pos(), orig.obj.pkg, orig.obj.name, nil) + tname := NewTypeName(ix.X.Pos(), orig.obj.pkg, orig.obj.name, nil) inst = check.newNamed(tname, orig, nil, nil, nil) // underlying, methods and tparams are set when named is resolved inst.targs = NewTypeList(targs) inst = ctxt.update(h, orig, targs, inst).(*Named) @@ -432,14 +439,14 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named if len(targs) < len(tparams) { // If inference fails, len(inferred) will be 0, and inst.underlying will // be set to Typ[Invalid] in expandNamed. - inferred = check.infer(x, tparams, targs, nil, nil) + inferred = check.infer(ix.Orig, tparams, targs, nil, nil) if len(inferred) > len(targs) { inst.targs = NewTypeList(inferred) } } - check.recordInstance(x, inferred, inst) - return expandNamed(ctxt, n, x.Pos()) + check.recordInstance(ix.Orig, inferred, inst) + return expandNamed(ctxt, n, pos) } // origin.tparams may not be set up, so we need to do expansion later. @@ -452,16 +459,16 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named // frees some memory. inst.resolver = nil - if check.validateTArgLen(x.Pos(), inst.tparams.Len(), inst.targs.Len()) { - if i, err := check.verify(x.Pos(), inst.tparams.list(), inst.targs.list()); err != nil { + if check.validateTArgLen(pos, inst.tparams.Len(), inst.targs.Len()) { + if i, err := check.verify(pos, inst.tparams.list(), inst.targs.list()); err != nil { // best position for error reporting - pos := x.Pos() + pos := ix.Pos() if i < len(posList) { pos = posList[i] } check.softErrorf(atPos(pos), _InvalidTypeArg, err.Error()) } else { - check.mono.recordInstance(check.pkg, x.Pos(), inst.tparams.list(), inst.targs.list(), posList) + check.mono.recordInstance(check.pkg, pos, inst.tparams.list(), inst.targs.list(), posList) } } -- GitLab From 92655582d0d3b739a1fc88c73cc49a24eb57f845 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 15 Nov 2021 11:47:55 -0500 Subject: [PATCH 2179/2500] cmd/compile/internal/types2: add a check for nil reason in assignableTo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A recent change to error message formatting was missing a nil check. Fixes #49592 Change-Id: Ic1843e0277ba75eec0e8e41fe34b59c323d7ea31 Reviewed-on: https://go-review.googlesource.com/c/go/+/364034 Trust: Robert Findley Trust: Dan Scales Trust: Daniel Martí Run-TryBot: Robert Findley Reviewed-by: Dan Scales TryBot-Result: Go Bot --- src/cmd/compile/internal/types2/operand.go | 4 +++- .../types2/testdata/fixedbugs/issue49592.go2 | 11 +++++++++++ src/go/types/testdata/fixedbugs/issue49592.go2 | 11 +++++++++++ test/fixedbugs/issue49592.go | 13 +++++++++++++ 4 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue49592.go2 create mode 100644 src/go/types/testdata/fixedbugs/issue49592.go2 create mode 100644 test/fixedbugs/issue49592.go diff --git a/src/cmd/compile/internal/types2/operand.go b/src/cmd/compile/internal/types2/operand.go index 8a905f3fd0..6581d80323 100644 --- a/src/cmd/compile/internal/types2/operand.go +++ b/src/cmd/compile/internal/types2/operand.go @@ -316,7 +316,9 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er // not an interface. if check != nil && check.conf.CompilerErrorMessages { if isInterfacePtr(Tu) { - *reason = check.sprintf("%s does not implement %s (%s is pointer to interface, not interface)", x.typ, T, T) + if reason != nil { + *reason = check.sprintf("%s does not implement %s (%s is pointer to interface, not interface)", x.typ, T, T) + } return false, _InvalidIfaceAssign } if Vi, _ := Vu.(*Interface); Vi != nil && Vp == nil { diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49592.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49592.go2 new file mode 100644 index 0000000000..846deaa89a --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49592.go2 @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func _() { + var x *interface{} + var y interface{} + _ = x == y +} diff --git a/src/go/types/testdata/fixedbugs/issue49592.go2 b/src/go/types/testdata/fixedbugs/issue49592.go2 new file mode 100644 index 0000000000..846deaa89a --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue49592.go2 @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func _() { + var x *interface{} + var y interface{} + _ = x == y +} diff --git a/test/fixedbugs/issue49592.go b/test/fixedbugs/issue49592.go new file mode 100644 index 0000000000..8b5612943a --- /dev/null +++ b/test/fixedbugs/issue49592.go @@ -0,0 +1,13 @@ +// compile + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func _() { + var x *interface{} + var y interface{} + _ = x == y +} -- GitLab From 560dc9712d4bc900b5ab32b518ba4de2a9bc588c Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Mon, 15 Nov 2021 10:01:43 -0800 Subject: [PATCH 2180/2500] cmd/compile: error when using internal type declarations in generic functions We hope to support this feature one day, but it doesn't work currently. Issue a nice error message instead of having the compiler crash. Update #47631 Change-Id: I0359411410acbaf9a5b9dbb988cd933de1bb8438 Reviewed-on: https://go-review.googlesource.com/c/go/+/364054 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stmt.go | 4 +++ test/run.go | 1 + test/typeparam/builtins.go | 13 +++++----- test/typeparam/issue47631.go | 34 ++++++++++++++++++++++++++ test/typeparam/typelist.go | 3 ++- 5 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 test/typeparam/issue47631.go diff --git a/src/cmd/compile/internal/noder/stmt.go b/src/cmd/compile/internal/noder/stmt.go index aedb09e21e..e329a59156 100644 --- a/src/cmd/compile/internal/noder/stmt.go +++ b/src/cmd/compile/internal/noder/stmt.go @@ -46,6 +46,10 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { n.SetTypecheck(1) return n case *syntax.DeclStmt: + if _, ok := stmt.DeclList[0].(*syntax.TypeDecl); ok && g.topFuncIsGeneric { + // TODO: remove this restriction. See issue 47631. + base.ErrorfAt(g.pos(stmt), "type declarations inside generic functions are not currently supported") + } n := ir.NewBlockStmt(g.pos(stmt), nil) g.decls(&n.List, stmt.DeclList) return n diff --git a/test/run.go b/test/run.go index ad64304ec8..bdc2f0a277 100644 --- a/test/run.go +++ b/test/run.go @@ -2186,6 +2186,7 @@ var unifiedFailures = setOf( "fixedbugs/issue42284.go", // prints "T(0) does not escape", but test expects "a.I(a.T(0)) does not escape" "fixedbugs/issue7921.go", // prints "… escapes to heap", but test expects "string(…) escapes to heap" "typeparam/issue48538.go", // assertion failure, interprets struct key as closure variable + "typeparam/issue47631.go", // unified IR can handle local type declarations ) func setOf(keys ...string) map[string]bool { diff --git a/test/typeparam/builtins.go b/test/typeparam/builtins.go index 844cdae8ab..73dda77e0e 100644 --- a/test/typeparam/builtins.go +++ b/test/typeparam/builtins.go @@ -69,24 +69,25 @@ func m1[ C1 interface{ chan int }, C2 interface{ chan int | chan string }, ]() { - type S0 []int _ = make([]int, 10) - _ = make(S0, 10) + _ = make(m1S0, 10) _ = make(S1, 10) _ = make(S1, 10, 20) - type M0 map[string]int _ = make(map[string]int) - _ = make(M0) + _ = make(m1M0) _ = make(M1) _ = make(M1, 10) - type C0 chan int _ = make(chan int) - _ = make(C0) + _ = make(m1C0) _ = make(C1) _ = make(C1, 10) } +// TODO: put these type declarations back inside m1 when issue 47631 is fixed. +type m1S0 []int +type m1M0 map[string]int +type m1C0 chan int // len/cap diff --git a/test/typeparam/issue47631.go b/test/typeparam/issue47631.go new file mode 100644 index 0000000000..7f7cfa6abb --- /dev/null +++ b/test/typeparam/issue47631.go @@ -0,0 +1,34 @@ +// errorcheck -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// TODO: one day we will support internal type declarations, at which time this test will be removed. + +package p + +func g[T any]() { + type U []T // ERROR "type declarations inside generic functions are not currently supported" + type V []int // ERROR "type declarations inside generic functions are not currently supported" +} + +type S[T any] struct { +} + +func (s S[T]) m() { + type U []T // ERROR "type declarations inside generic functions are not currently supported" + type V []int // ERROR "type declarations inside generic functions are not currently supported" +} + + +func f() { + type U []int // ok +} + +type X struct { +} + +func (x X) m() { + type U []int // ok +} diff --git a/test/typeparam/typelist.go b/test/typeparam/typelist.go index 8d6a228de5..34ea4b8aa9 100644 --- a/test/typeparam/typelist.go +++ b/test/typeparam/typelist.go @@ -26,11 +26,12 @@ func at[T interface{ ~[]E }, E any](x T, i int) E { // type is itself, its "operational type" is defined by the type list in // the tybe bound, if any. func _[T interface{ ~int }](x T) { - type myint int var _ int = int(x) var _ T = 42 var _ T = T(myint(42)) } +// TODO: put this type declaration back inside the above function when issue 47631 is fixed. +type myint int // Indexing a generic type which has a structural contraints to be an array. func _[T interface{ ~[10]int }](x T) { -- GitLab From 184ca3cf99864b4112997891b079d106751be25c Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sun, 14 Nov 2021 11:31:47 -0800 Subject: [PATCH 2181/2500] go/types, types2: copy implicit bit in interface substitution Change-Id: Idb02449ef1b06d5f47eeb4a4413e56e2cd5d0d96 Reviewed-on: https://go-review.googlesource.com/c/go/+/363836 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/subst.go | 2 +- src/go/types/subst.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 5deb868a79..ed1fbbf941 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -137,7 +137,7 @@ func (subst *subster) typ(typ Type) Type { methods, mcopied := subst.funcList(t.methods) embeddeds, ecopied := subst.typeList(t.embeddeds) if mcopied || ecopied { - iface := &Interface{methods: methods, embeddeds: embeddeds, complete: t.complete} + iface := &Interface{methods: methods, embeddeds: embeddeds, implicit: t.implicit, complete: t.complete} return iface } diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 3ff81a06b6..04eb3a6215 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -137,7 +137,7 @@ func (subst *subster) typ(typ Type) Type { methods, mcopied := subst.funcList(t.methods) embeddeds, ecopied := subst.typeList(t.embeddeds) if mcopied || ecopied { - iface := &Interface{methods: methods, embeddeds: embeddeds, complete: t.complete} + iface := &Interface{methods: methods, embeddeds: embeddeds, implicit: t.implicit, complete: t.complete} return iface } -- GitLab From 0a39e4a89d26d8375bb5877f736dcc0047894060 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sat, 13 Nov 2021 11:02:51 -0800 Subject: [PATCH 2182/2500] cmd/compile/internal/types2: optimize common case in structuralType Most of the time we don't have a type parameter. Avoid using a closure in that case. While at it, rename argument from typ to t (to match style in that file), and clarify the doc string. Change-Id: Ie62821073f60f353526263f8b380bad9f72d842e Reviewed-on: https://go-review.googlesource.com/c/go/+/363668 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/type.go | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index af195c08a4..39737d47a7 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -56,15 +56,20 @@ func match(x, y Type) Type { return nil } -// If typ is a type parameter, structuralType returns the single underlying -// type of all types in the corresponding type constraint if it exists, or -// nil otherwise. If the type set contains only unrestricted and restricted -// channel types (with identical element types), the single underlying type -// is the restricted channel type if the restrictions are always the same. -// If typ is not a type parameter, structuralType returns the underlying type. -func structuralType(typ Type) Type { +// If t is not a type parameter, structuralType returns the underlying type. +// If t is a type parameter, structuralType returns the single underlying +// type of all types in its type set if it exists, or nil otherwise. If the +// type set contains only unrestricted and restricted channel types (with +// identical element types), the single underlying type is the restricted +// channel type if the restrictions are always the same, or nil otherwise. +func structuralType(t Type) Type { + tpar, _ := t.(*TypeParam) + if tpar == nil { + return under(t) + } + var su Type - if underIs(typ, func(u Type) bool { + if tpar.underIs(func(u Type) bool { if u == nil { return false } -- GitLab From cfcd71790f0ca8c2ec1ae5989cd60ad1e83ee40c Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 12 Nov 2021 15:08:00 -0800 Subject: [PATCH 2183/2500] cmd/compile/internal/types2: allow slicing for operands with []byte|string type sets Fixes #49566. Change-Id: I80ff4ca661f82b0981d51e0997d5988a9b82f508 Reviewed-on: https://go-review.googlesource.com/c/go/+/363662 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/builtins.go | 23 ++---------- src/cmd/compile/internal/types2/index.go | 4 +- .../types2/testdata/check/typeparams.go2 | 4 ++ src/cmd/compile/internal/types2/type.go | 37 +++++++++++++++++++ 4 files changed, 47 insertions(+), 21 deletions(-) diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 5b4ffd0dad..53d834507a 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -337,26 +337,11 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( if y.mode == invalid { return } - // src, _ := structuralType(y.typ).(*Slice); but also accepts strings - var src *Slice - var elem Type // == src.elem if valid - if underIs(y.typ, func(u Type) bool { - switch u := u.(type) { - case *Basic: - if isString(u) && (elem == nil || Identical(elem, universeByte)) { - elem = universeByte - return true - } - case *Slice: - if elem == nil || Identical(elem, u.elem) { - elem = u.elem - return true - } - } - return false - }) { - src = NewSlice(elem) + src0 := structuralString(y.typ) + if src0 != nil && isString(src0) { + src0 = NewSlice(universeByte) } + src, _ := src0.(*Slice) if dst == nil || src == nil { check.errorf(x, invalidArg+"copy expects slice arguments; found %s and %s", x, &y) diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index 648c7abe6f..524d1957b5 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -213,7 +213,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { valid := false length := int64(-1) // valid if >= 0 - switch u := structuralType(x.typ).(type) { + switch u := structuralString(x.typ).(type) { case nil: check.errorf(x, invalidOp+"cannot slice %s: %s has no structural type", x, x.typ) x.mode = invalid @@ -232,7 +232,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { } // spec: "For untyped string operands the result // is a non-constant value of type string." - if u.kind == UntypedString { + if isUntyped(x.typ) { x.typ = Typ[String] } } diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 index 03c3f9a0b5..f77d09391b 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 @@ -136,6 +136,10 @@ type myByte2 []byte func _[T interface{ []byte | myByte1 | myByte2 }] (x T, i, j, k int) { var _ T = x[i:j:k] } func _[T interface{ []byte | myByte1 | []int }] (x T, i, j, k int) { var _ T = x[ /* ERROR no structural type */ i:j:k] } +func _[T interface{ []byte | myByte1 | myByte2 | string }] (x T, i, j, k int) { var _ T = x[i:j] } +func _[T interface{ []byte | myByte1 | myByte2 | string }] (x T, i, j, k int) { var _ T = x /* ERROR 3-index slice of string */ [i:j:k] } +func _[T interface{ []byte | myByte1 | []int | string }] (x T, i, j, k int) { var _ T = x[ /* ERROR no structural type */ i:j] } + // len/cap built-ins func _[T any](x T) { _ = len(x /* ERROR invalid argument */ ) } diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 39737d47a7..3ab738eb19 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -87,3 +87,40 @@ func structuralType(t Type) Type { } return nil } + +// structuralString is like structuralType but also considers []byte +// and strings as identical. In this case, if successful and we saw +// a string, the result is of type (possibly untyped) string. +func structuralString(t Type) Type { + tpar, _ := t.(*TypeParam) + if tpar == nil { + return under(t) // string or untyped string + } + + var su Type + hasString := false + if tpar.underIs(func(u Type) bool { + if u == nil { + return false + } + if isString(u) { + u = NewSlice(universeByte) + hasString = true + } + if su != nil { + u = match(su, u) + if u == nil { + return false + } + } + // su == nil || match(su, u) != nil + su = u + return true + }) { + if hasString { + return Typ[String] + } + return su + } + return nil +} -- GitLab From 0a54a6826ebd19e5947af57993399652c62801de Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sat, 13 Nov 2021 12:04:01 -0800 Subject: [PATCH 2184/2500] cmd/compile/internal/types2: move match function to end of file (cleanup) Change-Id: Ia09f7b1af0e84858fb73ab7e2592c5c3e983dc0e Reviewed-on: https://go-review.googlesource.com/c/go/+/363669 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/type.go | 58 ++++++++++++------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 3ab738eb19..9487ac5a84 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -27,35 +27,6 @@ func under(t Type) Type { return t.Underlying() } -// If x and y are identical, match returns x. -// If x and y are identical channels but for their direction -// and one of them is unrestricted, match returns the channel -// with the restricted direction. -// In all other cases, match returns nil. -func match(x, y Type) Type { - // Common case: we don't have channels. - if Identical(x, y) { - return x - } - - // We may have channels that differ in direction only. - if x, _ := x.(*Chan); x != nil { - if y, _ := y.(*Chan); y != nil && Identical(x.elem, y.elem) { - // We have channels that differ in direction only. - // If there's an unrestricted channel, select the restricted one. - switch { - case x.dir == SendRecv: - return y - case y.dir == SendRecv: - return x - } - } - } - - // types are different - return nil -} - // If t is not a type parameter, structuralType returns the underlying type. // If t is a type parameter, structuralType returns the single underlying // type of all types in its type set if it exists, or nil otherwise. If the @@ -124,3 +95,32 @@ func structuralString(t Type) Type { } return nil } + +// If x and y are identical, match returns x. +// If x and y are identical channels but for their direction +// and one of them is unrestricted, match returns the channel +// with the restricted direction. +// In all other cases, match returns nil. +func match(x, y Type) Type { + // Common case: we don't have channels. + if Identical(x, y) { + return x + } + + // We may have channels that differ in direction only. + if x, _ := x.(*Chan); x != nil { + if y, _ := y.(*Chan); y != nil && Identical(x.elem, y.elem) { + // We have channels that differ in direction only. + // If there's an unrestricted channel, select the restricted one. + switch { + case x.dir == SendRecv: + return y + case y.dir == SendRecv: + return x + } + } + } + + // types are different + return nil +} -- GitLab From 42fa03a88ca7767c1869e55b3144a9828d29b7b5 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sat, 13 Nov 2021 13:37:15 -0800 Subject: [PATCH 2185/2500] cmd/compile/internal/types2: better position for "3-index slice of string" error As a result, slightly narrow position tolerance for tests. Change-Id: I543dc2b7b9a7940b0684067d1961165b2b4812bb Reviewed-on: https://go-review.googlesource.com/c/go/+/363670 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/check_test.go | 2 +- src/cmd/compile/internal/types2/index.go | 6 +++++- src/cmd/compile/internal/types2/testdata/check/expr3.src | 4 ++-- .../compile/internal/types2/testdata/check/typeparams.go2 | 4 ++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/types2/check_test.go b/src/cmd/compile/internal/types2/check_test.go index d4c7b7b39b..ddaacd2443 100644 --- a/src/cmd/compile/internal/types2/check_test.go +++ b/src/cmd/compile/internal/types2/check_test.go @@ -277,7 +277,7 @@ func TestManual(t *testing.T) { // TODO(gri) go/types has extra TestLongConstants and TestIndexRepresentability tests -func TestCheck(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/check", 75, false) } // TODO(gri) narrow column tolerance +func TestCheck(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/check", 55, false) } // TODO(gri) narrow column tolerance func TestSpec(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/spec", 0, false) } func TestExamples(t *testing.T) { testDirFiles(t, "testdata/examples", 0, false) } func TestFixedbugs(t *testing.T) { testDirFiles(t, "testdata/fixedbugs", 0, false) } diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index 524d1957b5..c773ae8ad3 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -222,7 +222,11 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { case *Basic: if isString(u) { if e.Full { - check.error(x, invalidOp+"3-index slice of string") + at := e.Index[2] + if at == nil { + at = e // e.Index[2] should be present but be careful + } + check.error(at, invalidOp+"3-index slice of string") x.mode = invalid return } diff --git a/src/cmd/compile/internal/types2/testdata/check/expr3.src b/src/cmd/compile/internal/types2/testdata/check/expr3.src index d1e1dba9f4..523214461f 100644 --- a/src/cmd/compile/internal/types2/testdata/check/expr3.src +++ b/src/cmd/compile/internal/types2/testdata/check/expr3.src @@ -110,8 +110,8 @@ func indexes() { _ = t[- /* ERROR "negative" */ 1] _ = t[- /* ERROR "negative" */ 1 :] _ = t[: - /* ERROR "negative" */ 1] - _ = t /* ERROR "3-index slice of string" */ [1:2:3] - _ = "foo" /* ERROR "3-index slice of string" */ [1:2:3] + _ = t[1:2:3 /* ERROR "3-index slice of string" */ ] + _ = "foo"[1:2:3 /* ERROR "3-index slice of string" */ ] var t0 byte t0 = t[0] _ = t0 diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 index f77d09391b..d72cf078a7 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 @@ -129,7 +129,7 @@ func _[T interface{ ~[10]E }, E any] (x T, i, j, k int) { var _ []E = x[i:j:k] } func _[T interface{ ~[]byte }] (x T, i, j, k int) { var _ T = x[i:j] } func _[T interface{ ~[]byte }] (x T, i, j, k int) { var _ T = x[i:j:k] } func _[T interface{ ~string }] (x T, i, j, k int) { var _ T = x[i:j] } -func _[T interface{ ~string }] (x T, i, j, k int) { var _ T = x /* ERROR 3-index slice of string */ [i:j:k] } +func _[T interface{ ~string }] (x T, i, j, k int) { var _ T = x[i:j:k /* ERROR 3-index slice of string */ ] } type myByte1 []byte type myByte2 []byte @@ -137,7 +137,7 @@ func _[T interface{ []byte | myByte1 | myByte2 }] (x T, i, j, k int) { var _ T = func _[T interface{ []byte | myByte1 | []int }] (x T, i, j, k int) { var _ T = x[ /* ERROR no structural type */ i:j:k] } func _[T interface{ []byte | myByte1 | myByte2 | string }] (x T, i, j, k int) { var _ T = x[i:j] } -func _[T interface{ []byte | myByte1 | myByte2 | string }] (x T, i, j, k int) { var _ T = x /* ERROR 3-index slice of string */ [i:j:k] } +func _[T interface{ []byte | myByte1 | myByte2 | string }] (x T, i, j, k int) { var _ T = x[i:j:k /* ERROR 3-index slice of string */ ] } func _[T interface{ []byte | myByte1 | []int | string }] (x T, i, j, k int) { var _ T = x[ /* ERROR no structural type */ i:j] } // len/cap built-ins -- GitLab From fda92615040c831bdcd812fd20ddb0da9dcef70b Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sat, 13 Nov 2021 13:57:48 -0800 Subject: [PATCH 2186/2500] cmd/compile/internal/types2: better position for invalid slice indices error Report the error at the first place (which is to say, latest index) causing the error. Change-Id: I31cf0a4d243fc66cfab84b7fec98055f4eb60ddf Reviewed-on: https://go-review.googlesource.com/c/go/+/363671 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/index.go | 9 ++++++--- .../internal/types2/testdata/check/expr3.src | 18 +++++++++--------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index c773ae8ad3..4995d2d730 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -309,9 +309,12 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { L: for i, x := range ind[:len(ind)-1] { if x > 0 { - for _, y := range ind[i+1:] { - if y >= 0 && x > y { - check.errorf(e, "invalid slice indices: %d > %d", x, y) + for j, y := range ind[i+1:] { + if y >= 0 && y < x { + // The value y corresponds to the expression e.Index[i+1+j]. + // Because y >= 0, it must have been set from the expression + // when checking indices and thus e.Index[i+1+j] is not nil. + check.errorf(e.Index[i+1+j], "invalid slice indices: %d < %d", y, x) break L // only report one error, ok to continue } } diff --git a/src/cmd/compile/internal/types2/testdata/check/expr3.src b/src/cmd/compile/internal/types2/testdata/check/expr3.src index 523214461f..0d7bbae9f9 100644 --- a/src/cmd/compile/internal/types2/testdata/check/expr3.src +++ b/src/cmd/compile/internal/types2/testdata/check/expr3.src @@ -45,9 +45,9 @@ func indexes() { _ = a[:10:10] _ = a[:11 /* ERROR "index .* out of bounds" */ :10] _ = a[:10:11 /* ERROR "index .* out of bounds" */ ] - _ = a[10:0:10] /* ERROR "invalid slice indices" */ - _ = a[0:10:0] /* ERROR "invalid slice indices" */ - _ = a[10:0:0] /* ERROR "invalid slice indices" */ + _ = a[10:0 /* ERROR "invalid slice indices" */ :10] + _ = a[0:10:0 /* ERROR "invalid slice indices" */ ] + _ = a[10:0 /* ERROR "invalid slice indices" */:0] _ = &a /* ERROR "cannot take address" */ [:10] pa := &a @@ -63,9 +63,9 @@ func indexes() { _ = pa[:10:10] _ = pa[:11 /* ERROR "index .* out of bounds" */ :10] _ = pa[:10:11 /* ERROR "index .* out of bounds" */ ] - _ = pa[10:0:10] /* ERROR "invalid slice indices" */ - _ = pa[0:10:0] /* ERROR "invalid slice indices" */ - _ = pa[10:0:0] /* ERROR "invalid slice indices" */ + _ = pa[10:0 /* ERROR "invalid slice indices" */ :10] + _ = pa[0:10:0 /* ERROR "invalid slice indices" */ ] + _ = pa[10:0 /* ERROR "invalid slice indices" */ :0] _ = &pa /* ERROR "cannot take address" */ [:10] var b [0]int @@ -90,9 +90,9 @@ func indexes() { _ = s[1 /* ERROR "overflows" */ <<100 : 1 /* ERROR "overflows" */ <<100] _ = s[: /* ERROR "middle index required" */ : /* ERROR "final index required" */ ] _ = s[:10:10] - _ = s[10:0:10] /* ERROR "invalid slice indices" */ - _ = s[0:10:0] /* ERROR "invalid slice indices" */ - _ = s[10:0:0] /* ERROR "invalid slice indices" */ + _ = s[10:0 /* ERROR "invalid slice indices" */ :10] + _ = s[0:10:0 /* ERROR "invalid slice indices" */ ] + _ = s[10:0 /* ERROR "invalid slice indices" */ :0] _ = &s /* ERROR "cannot take address" */ [:10] var m map[string]int -- GitLab From e08aae2ee443ba8bb16b8ce9c5d3d8d4d3cfa82b Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sun, 14 Nov 2021 11:29:45 -0800 Subject: [PATCH 2187/2500] cmd/compile/internal/types2: implement Checker.implements Checker.implements implements the complete interface "implements" predicate. Use it instead of Checker.satisfies. This is mostly a refactoring of the code but the constraint types have already been instatiated with the respective type arguments as needed before calling "implements". Future CLs will address the various TODOs. Change-Id: If530cca36643a561282361348f1526157a7182de Reviewed-on: https://go-review.googlesource.com/c/go/+/363837 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- .../compile/internal/types2/instantiate.go | 121 ++++++++++-------- .../types2/testdata/fixedbugs/issue45920.go2 | 4 +- 2 files changed, 67 insertions(+), 58 deletions(-) diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 582d1e4763..a0f6885c51 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -119,112 +119,121 @@ func (check *Checker) validateTArgLen(pos syntax.Pos, ntparams, ntargs int) bool } func (check *Checker) verify(pos syntax.Pos, tparams []*TypeParam, targs []Type) (int, error) { + // TODO(rfindley): it would be great if users could pass in a qualifier here, + // rather than falling back to verbose qualification. Maybe this can be part + // of the shared context. + var qf Qualifier + if check != nil { + qf = check.qualifier + } + smap := makeSubstMap(tparams, targs) for i, tpar := range tparams { - // stop checking bounds after the first failure - if err := check.satisfies(pos, targs[i], tpar, smap); err != nil { + // The type parameter bound is parameterized with the same type parameters + // as the instantiated type; before we can use it for bounds checking we + // need to instantiate it with the type arguments with which we instantiated + // the parameterized type. + bound := check.subst(pos, tpar.bound, smap, nil) + if err := check.implements(targs[i], bound, qf); err != nil { return i, err } } return -1, nil } -// satisfies reports whether the type argument targ satisfies the constraint of type parameter -// parameter tpar (after any of its type parameters have been substituted through smap). -// A suitable error is reported if the result is false. -// TODO(gri) This should be a method of interfaces or type sets. -func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap substMap) error { - iface := tpar.iface() - - // Every type argument satisfies interface{}. - if iface.Empty() { +// implements checks if V implements T and reports an error if it doesn't. +// If a qualifier is provided, it is used in error formatting. +func (check *Checker) implements(V, T Type, qf Qualifier) error { + Vu := under(V) + Tu := under(T) + if Vu == Typ[Invalid] || Tu == Typ[Invalid] { return nil } - // A type argument that is a type parameter with an empty type set satisfies any constraint. - // (The empty set is a subset of any set.) - if targ, _ := targ.(*TypeParam); targ != nil && targ.iface().typeSet().IsEmpty() { - return nil + errorf := func(format string, args ...interface{}) error { + return errors.New(sprintf(qf, false, format, args...)) } - // TODO(rfindley): it would be great if users could pass in a qualifier here, - // rather than falling back to verbose qualification. Maybe this can be part - // of the shared context. - var qf Qualifier - if check != nil { - qf = check.qualifier + Ti, _ := Tu.(*Interface) + if Ti == nil { + return errorf("%s is not an interface", T) } - errorf := func(format string, args ...interface{}) error { - return errors.New(sprintf(qf, false, format, args...)) + + // Every type satisfies the empty interface. + if Ti.Empty() { + return nil } + // T is not the empty interface (i.e., the type set of T is restricted) - // No type argument with non-empty type set satisfies the empty type set. - if iface.typeSet().IsEmpty() { - return errorf("%s does not satisfy %s (constraint type set is empty)", targ, tpar.bound) + // An interface V with an empty type set satisfies any interface. + // (The empty set is a subset of any set.) + Vi, _ := Vu.(*Interface) + if Vi != nil && Vi.typeSet().IsEmpty() { + return nil } + // type set of V is not empty - // The type parameter bound is parameterized with the same type parameters - // as the instantiated type; before we can use it for bounds checking we - // need to instantiate it with the type arguments with which we instantiate - // the parameterized type. - iface = check.subst(pos, iface, smap, nil).(*Interface) + // No type with non-empty type set satisfies the empty type set. + // TODO(gri) should use "implements" rather than "satisfies" throughout + if Ti.typeSet().IsEmpty() { + return errorf("%s does not satisfy %s (constraint type set is empty)", V, T) + } - // if iface is comparable, targ must be comparable + // If T is comparable, V must be comparable. // TODO(gri) the error messages needs to be better, here - if iface.IsComparable() && !Comparable(targ) { - if tpar, _ := targ.(*TypeParam); tpar != nil && tpar.iface().typeSet().IsAll() { - return errorf("%s has no constraints", targ) + if Ti.IsComparable() && !Comparable(V) { + if Vi != nil && Vi.typeSet().IsAll() { + return errorf("%s has no constraints", V) } - return errorf("%s does not satisfy comparable", targ) + return errorf("%s does not satisfy comparable", V) } - // targ must implement iface (methods) + // V must implement T (methods) // - check only if we have methods - if iface.NumMethods() > 0 { + if Ti.NumMethods() > 0 { // If the type argument is a pointer to a type parameter, the type argument's // method set is empty. // TODO(gri) is this what we want? (spec question) - if base, isPtr := deref(targ); isPtr && isTypeParam(base) { - return errorf("%s has no methods", targ) + if base, isPtr := deref(V); isPtr && isTypeParam(base) { + return errorf("%s has no methods", V) } - if m, wrong := check.missingMethod(targ, iface, true); m != nil { + if m, wrong := check.missingMethod(V, Ti, true); m != nil { // TODO(gri) needs to print updated name to avoid major confusion in error message! // (print warning for now) // Old warning: - // check.softErrorf(pos, "%s does not satisfy %s (warning: name not updated) = %s (missing method %s)", targ, tpar.bound, iface, m) + // check.softErrorf(pos, "%s does not satisfy %s (warning: name not updated) = %s (missing method %s)", V, T, Ti, m) if wrong != nil { // TODO(gri) This can still report uninstantiated types which makes the error message // more difficult to read then necessary. return errorf("%s does not satisfy %s: wrong method signature\n\tgot %s\n\twant %s", - targ, tpar.bound, wrong, m, + V, T, wrong, m, ) } - return errorf("%s does not satisfy %s (missing method %s)", targ, tpar.bound, m.name) + return errorf("%s does not satisfy %s (missing method %s)", V, T, m.name) } } - // targ must also be in the set of types of iface, if any. + // V must also be in the set of types of T, if any. // Constraints with empty type sets were already excluded above. - if !iface.typeSet().hasTerms() { + if !Ti.typeSet().hasTerms() { return nil // nothing to do } - // If targ is itself a type parameter, each of its possible types must be in the set - // of iface types (i.e., the targ type set must be a subset of the iface type set). - // Type arguments with empty type sets were already excluded above. - if targ, _ := targ.(*TypeParam); targ != nil { - targBound := targ.iface() - if !targBound.typeSet().subsetOf(iface.typeSet()) { + // If V is itself an interface, each of its possible types must be in the set + // of T types (i.e., the V type set must be a subset of the T type set). + // Interfaces V with empty type sets were already excluded above. + if Vi != nil { + if !Vi.typeSet().subsetOf(Ti.typeSet()) { // TODO(gri) report which type is missing - return errorf("%s does not satisfy %s", targ, tpar.bound) + return errorf("%s does not satisfy %s", V, T) } return nil } - // Otherwise, targ's type must be included in the iface type set. - if !iface.typeSet().includes(targ) { + // Otherwise, V's type must be included in the iface type set. + if !Ti.typeSet().includes(V) { // TODO(gri) report which type is missing - return errorf("%s does not satisfy %s", targ, tpar.bound) + return errorf("%s does not satisfy %s", V, T) } return nil diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45920.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45920.go2 index ef9ca9fede..620bdb2e4e 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45920.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45920.go2 @@ -8,10 +8,10 @@ func f1[T any, C chan T | <-chan T](ch C) {} func _(ch chan int) { f1(ch) } func _(ch <-chan int) { f1(ch) } -func _(ch chan<- int) { f1( /* ERROR chan<- int does not satisfy chan T\|<-chan T */ ch) } +func _(ch chan<- int) { f1( /* ERROR chan<- int does not satisfy chan int\|<-chan int */ ch) } func f2[T any, C chan T | chan<- T](ch C) {} func _(ch chan int) { f2(ch) } -func _(ch <-chan int) { f2( /* ERROR <-chan int does not satisfy chan T\|chan<- T */ ch) } +func _(ch <-chan int) { f2( /* ERROR <-chan int does not satisfy chan int\|chan<- int */ ch) } func _(ch chan<- int) { f2(ch) } -- GitLab From c8d7c5fe0511569f19d4ebed29f11d96f50b3e07 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sun, 14 Nov 2021 20:45:40 -0800 Subject: [PATCH 2188/2500] cmd/compile/internal/types2: remove unneccesary tests in implements and lookup Because the underlying type of a type parameter is an interface, the questions whether *P for a type parameter P has methods or not is settled: P is also an interface pointers to interfaces don't have methods. This allows us to eliminate the now unneccesary test in "implements" and also allows us to remove a special case for type parameters in "lookupFieldOrMethod". Change-Id: I8b218f81584a8e42e75884089a44293365b700df Reviewed-on: https://go-review.googlesource.com/c/go/+/363838 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/instantiate.go | 6 ------ src/cmd/compile/internal/types2/lookup.go | 6 +----- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index a0f6885c51..13f0661611 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -191,12 +191,6 @@ func (check *Checker) implements(V, T Type, qf Qualifier) error { // V must implement T (methods) // - check only if we have methods if Ti.NumMethods() > 0 { - // If the type argument is a pointer to a type parameter, the type argument's - // method set is empty. - // TODO(gri) is this what we want? (spec question) - if base, isPtr := deref(V); isPtr && isTypeParam(base) { - return errorf("%s has no methods", V) - } if m, wrong := check.missingMethod(V, Ti, true); m != nil { // TODO(gri) needs to print updated name to avoid major confusion in error message! // (print warning for now) diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index b4035e16b3..4f50ea54b1 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -80,12 +80,8 @@ func lookupFieldOrMethod(T Type, addressable, checkFold bool, pkg *Package, name typ, isPtr := deref(T) - // *typ where typ is an interface or type parameter has no methods. + // *typ where typ is an interface has no methods. if isPtr { - // don't look at under(typ) here - was bug (issue #47747) - if _, ok := typ.(*TypeParam); ok { - return - } if _, ok := under(typ).(*Interface); ok { return } -- GitLab From 95e85e31089523447aadb7670715c4d3383cc4ee Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sun, 14 Nov 2021 21:13:27 -0800 Subject: [PATCH 2189/2500] cmd/compile/internal/types2: use "implements" rather than "satisfies" in error messages Type constraint satisfaction is interface implementation. Adjusted a few error messages. Change-Id: I4266af78e83131a76b1e3e44c847a21de760ac6e Reviewed-on: https://go-review.googlesource.com/c/go/+/363839 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- .../compile/internal/types2/instantiate.go | 21 +++++++------- .../internal/types2/testdata/check/issues.go2 | 6 ++-- .../types2/testdata/check/typeinst2.go2 | 28 +++++++++---------- .../types2/testdata/examples/inference.go2 | 2 +- .../types2/testdata/fixedbugs/issue39754.go2 | 4 +-- .../types2/testdata/fixedbugs/issue45920.go2 | 4 +-- .../types2/testdata/fixedbugs/issue47411.go2 | 10 +++---- src/constraints/constraints_test.go | 2 +- test/typeparam/mdempsky/8.dir/b.go | 2 +- test/typeparam/mincheck.dir/main.go | 4 +-- 10 files changed, 41 insertions(+), 42 deletions(-) diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 13f0661611..3834c6ba87 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -174,18 +174,17 @@ func (check *Checker) implements(V, T Type, qf Qualifier) error { // type set of V is not empty // No type with non-empty type set satisfies the empty type set. - // TODO(gri) should use "implements" rather than "satisfies" throughout if Ti.typeSet().IsEmpty() { - return errorf("%s does not satisfy %s (constraint type set is empty)", V, T) + return errorf("cannot implement %s (empty type set)", T) } // If T is comparable, V must be comparable. - // TODO(gri) the error messages needs to be better, here + // TODO(gri) the error messages could be better, here if Ti.IsComparable() && !Comparable(V) { - if Vi != nil && Vi.typeSet().IsAll() { - return errorf("%s has no constraints", V) + if Vi != nil && Vi.Empty() { + return errorf("empty interface %s does not implement %s", V, T) } - return errorf("%s does not satisfy comparable", V) + return errorf("%s does not implement comparable", V) } // V must implement T (methods) @@ -195,15 +194,15 @@ func (check *Checker) implements(V, T Type, qf Qualifier) error { // TODO(gri) needs to print updated name to avoid major confusion in error message! // (print warning for now) // Old warning: - // check.softErrorf(pos, "%s does not satisfy %s (warning: name not updated) = %s (missing method %s)", V, T, Ti, m) + // check.softErrorf(pos, "%s does not implement %s (warning: name not updated) = %s (missing method %s)", V, T, Ti, m) if wrong != nil { // TODO(gri) This can still report uninstantiated types which makes the error message // more difficult to read then necessary. - return errorf("%s does not satisfy %s: wrong method signature\n\tgot %s\n\twant %s", + return errorf("%s does not implement %s: wrong method signature\n\tgot %s\n\twant %s", V, T, wrong, m, ) } - return errorf("%s does not satisfy %s (missing method %s)", V, T, m.name) + return errorf("%s does not implement %s (missing method %s)", V, T, m.name) } } @@ -219,7 +218,7 @@ func (check *Checker) implements(V, T Type, qf Qualifier) error { if Vi != nil { if !Vi.typeSet().subsetOf(Ti.typeSet()) { // TODO(gri) report which type is missing - return errorf("%s does not satisfy %s", V, T) + return errorf("%s does not implement %s", V, T) } return nil } @@ -227,7 +226,7 @@ func (check *Checker) implements(V, T Type, qf Qualifier) error { // Otherwise, V's type must be included in the iface type set. if !Ti.typeSet().includes(V) { // TODO(gri) report which type is missing - return errorf("%s does not satisfy %s", V, T) + return errorf("%s does not implement %s", V, T) } return nil diff --git a/src/cmd/compile/internal/types2/testdata/check/issues.go2 b/src/cmd/compile/internal/types2/testdata/check/issues.go2 index 8608473135..76f9cc5010 100644 --- a/src/cmd/compile/internal/types2/testdata/check/issues.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/issues.go2 @@ -58,7 +58,7 @@ func _() { type T1[P interface{~uint}] struct{} func _[P any]() { - _ = T1[P /* ERROR P has no constraints */ ]{} + _ = T1[P /* ERROR empty interface P does not implement interface{~uint} */ ]{} } // This is the original (simplified) program causing the same issue. @@ -74,8 +74,8 @@ func (u T2[U]) Add1() U { return u.s + 1 } -func NewT2[U any]() T2[U /* ERROR U has no constraints */ ] { - return T2[U /* ERROR U has no constraints */ ]{} +func NewT2[U any]() T2[U /* ERROR empty interface U does not implement Unsigned */ ] { + return T2[U /* ERROR empty interface U does not implement Unsigned */ ]{} } func _() { diff --git a/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 b/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 index cd56c81bb9..4aaefb3424 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeinst2.go2 @@ -208,7 +208,7 @@ func f0[T I0]() {} var _ = f0[int] var _ = f0[bool] var _ = f0[string] -var _ = f0[float64 /* ERROR does not satisfy I0 */ ] +var _ = f0[float64 /* ERROR does not implement I0 */ ] type I01 interface { E0 @@ -217,9 +217,9 @@ type I01 interface { func f01[T I01]() {} var _ = f01[int] -var _ = f01[bool /* ERROR does not satisfy I0 */ ] +var _ = f01[bool /* ERROR does not implement I0 */ ] var _ = f01[string] -var _ = f01[float64 /* ERROR does not satisfy I0 */ ] +var _ = f01[float64 /* ERROR does not implement I0 */ ] type I012 interface { E0 @@ -228,10 +228,10 @@ type I012 interface { } func f012[T I012]() {} -var _ = f012[int /* ERROR does not satisfy I012.*type set is empty */ ] -var _ = f012[bool /* ERROR does not satisfy I012.*type set is empty */ ] -var _ = f012[string /* ERROR does not satisfy I012.*type set is empty */ ] -var _ = f012[float64 /* ERROR does not satisfy I012.*type set is empty */ ] +var _ = f012[int /* ERROR cannot implement I012.*empty type set */ ] +var _ = f012[bool /* ERROR cannot implement I012.*empty type set */ ] +var _ = f012[string /* ERROR cannot implement I012.*empty type set */ ] +var _ = f012[float64 /* ERROR cannot implement I012.*empty type set */ ] type I12 interface { E1 @@ -239,9 +239,9 @@ type I12 interface { } func f12[T I12]() {} -var _ = f12[int /* ERROR does not satisfy I12 */ ] -var _ = f12[bool /* ERROR does not satisfy I12 */ ] -var _ = f12[string /* ERROR does not satisfy I12 */ ] +var _ = f12[int /* ERROR does not implement I12 */ ] +var _ = f12[bool /* ERROR does not implement I12 */ ] +var _ = f12[string /* ERROR does not implement I12 */ ] var _ = f12[float64] type I0_ interface { @@ -251,9 +251,9 @@ type I0_ interface { func f0_[T I0_]() {} var _ = f0_[int] -var _ = f0_[bool /* ERROR does not satisfy I0_ */ ] -var _ = f0_[string /* ERROR does not satisfy I0_ */ ] -var _ = f0_[float64 /* ERROR does not satisfy I0_ */ ] +var _ = f0_[bool /* ERROR does not implement I0_ */ ] +var _ = f0_[string /* ERROR does not implement I0_ */ ] +var _ = f0_[float64 /* ERROR does not implement I0_ */ ] // Using a function instance as a type is an error. var _ f0 // ERROR not a type @@ -271,7 +271,7 @@ func gg[T any]() {} func hh[T ~int]() {} func _[T none]() { - _ = ff[int /* ERROR int does not satisfy none \(constraint type set is empty\) */ ] + _ = ff[int /* ERROR cannot implement none \(empty type set\) */ ] _ = ff[T] // pathological but ok because T's type set is empty, too _ = gg[int] _ = gg[T] diff --git a/src/cmd/compile/internal/types2/testdata/examples/inference.go2 b/src/cmd/compile/internal/types2/testdata/examples/inference.go2 index 4eb18eb239..0732f06a39 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/inference.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/inference.go2 @@ -97,7 +97,7 @@ func _() { // last. related2(1.2, []float64{}) related2(1.0, []int{}) - related2( /* ERROR does not satisfy */ float64(1.0), []int{}) // TODO(gri) fix error position + related2( /* ERROR does not implement */ float64(1.0), []int{}) // TODO(gri) fix error position } type List[P any] []P diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39754.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39754.go2 index f70b8d0ce0..a88f4cf2f1 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39754.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39754.go2 @@ -16,8 +16,8 @@ func f[V interface{}, A, B Box[V]]() {} func _() { f[int, Optional[int], Optional[int]]() - _ = f[int, Optional[int], Optional /* ERROR does not satisfy Box */ [string]] + _ = f[int, Optional[int], Optional /* ERROR does not implement Box */ [string]] // TODO(gri) Provide better position information here. // See TODO in call.go, Checker.arguments. - f[int, Optional[int], Optional[string]]( /* ERROR does not satisfy Box */ ) + f[int, Optional[int], Optional[string]]( /* ERROR does not implement Box */ ) } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45920.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45920.go2 index 620bdb2e4e..b113e104bc 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45920.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45920.go2 @@ -8,10 +8,10 @@ func f1[T any, C chan T | <-chan T](ch C) {} func _(ch chan int) { f1(ch) } func _(ch <-chan int) { f1(ch) } -func _(ch chan<- int) { f1( /* ERROR chan<- int does not satisfy chan int\|<-chan int */ ch) } +func _(ch chan<- int) { f1( /* ERROR chan<- int does not implement chan int\|<-chan int */ ch) } func f2[T any, C chan T | chan<- T](ch C) {} func _(ch chan int) { f2(ch) } -func _(ch <-chan int) { f2( /* ERROR <-chan int does not satisfy chan int\|chan<- int */ ch) } +func _(ch <-chan int) { f2( /* ERROR <-chan int does not implement chan int\|chan<- int */ ch) } func _(ch chan<- int) { f2(ch) } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go2 index ccf4bcf782..ce5db0a615 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go2 @@ -15,12 +15,12 @@ func _[P comparable, _ = f[int] _ = f[P] _ = f[Q] - _ = f[func( /* ERROR does not satisfy comparable */ )] - _ = f[R /* ERROR R has no constraints */ ] + _ = f[func( /* ERROR does not implement comparable */ )] + _ = f[R /* ERROR empty interface R does not implement comparable */ ] _ = g[int] - _ = g[P /* ERROR P does not satisfy interface{interface{comparable; ~int\|~string} */ ] + _ = g[P /* ERROR P does not implement interface{interface{comparable; ~int\|~string} */ ] _ = g[Q] - _ = g[func( /* ERROR does not satisfy comparable */ )] - _ = g[R /* ERROR R has no constraints */ ] + _ = g[func( /* ERROR does not implement comparable */ )] + _ = g[R /* ERROR empty interface R does not implement interface{interface{comparable; ~int\|~string} */ ] } diff --git a/src/constraints/constraints_test.go b/src/constraints/constraints_test.go index 538dc843cc..47d4cba52a 100644 --- a/src/constraints/constraints_test.go +++ b/src/constraints/constraints_test.go @@ -105,7 +105,7 @@ func TestFailure(t *testing.T) { t.Error("build succeeded, but expected to fail") } else if len(out) > 0 { t.Logf("%s", out) - const want = "does not satisfy" + const want = "does not implement" if !bytes.Contains(out, []byte(want)) { t.Errorf("output does not include %q", want) } diff --git a/test/typeparam/mdempsky/8.dir/b.go b/test/typeparam/mdempsky/8.dir/b.go index ef2637b894..84037bf763 100644 --- a/test/typeparam/mdempsky/8.dir/b.go +++ b/test/typeparam/mdempsky/8.dir/b.go @@ -7,5 +7,5 @@ package b import "./a" func init() { - a.F[func()]() // ERROR "does not satisfy comparable" + a.F[func()]() // ERROR "does not implement comparable" } diff --git a/test/typeparam/mincheck.dir/main.go b/test/typeparam/mincheck.dir/main.go index 9cf2c6bafd..63786de5e6 100644 --- a/test/typeparam/mincheck.dir/main.go +++ b/test/typeparam/mincheck.dir/main.go @@ -28,11 +28,11 @@ func main() { } const want2 = "ay" - if got := a.Min[string]("bb", "ay"); got != want2 { // ERROR "string does not satisfy" + if got := a.Min[string]("bb", "ay"); got != want2 { // ERROR "string does not implement" panic(fmt.Sprintf("got %d, want %d", got, want2)) } - if got := a.Min("bb", "ay"); got != want2 { // ERROR "string does not satisfy" + if got := a.Min("bb", "ay"); got != want2 { // ERROR "string does not implement" panic(fmt.Sprintf("got %d, want %d", got, want2)) } } -- GitLab From d15610128e63e299e39af02ea0e6be1afd38b1ff Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sat, 13 Nov 2021 16:16:53 -0800 Subject: [PATCH 2190/2500] cmd/compile/internal/types2: add test for imported constraints pre-1.18 But exclude the test when running unified build for now (the unified builder's importers are not yet updated to handle extended interfaces). Also, fix respective error position. Fixes #47967. Change-Id: I4e3d829b5c12001c024b9eefcc27f97b10c1d1e5 Reviewed-on: https://go-review.googlesource.com/c/go/+/363834 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley TryBot-Result: Go Bot --- src/cmd/compile/internal/types2/check_test.go | 17 +++++++++++++++++ src/cmd/compile/internal/types2/decl.go | 2 +- .../types2/testdata/fixedbugs/issue47818.go2 | 4 +++- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/types2/check_test.go b/src/cmd/compile/internal/types2/check_test.go index ddaacd2443..a5ecdf8b81 100644 --- a/src/cmd/compile/internal/types2/check_test.go +++ b/src/cmd/compile/internal/types2/check_test.go @@ -25,6 +25,7 @@ package types2_test import ( "cmd/compile/internal/syntax" "flag" + "internal/buildcfg" "internal/testenv" "os" "path/filepath" @@ -93,11 +94,27 @@ func asGoVersion(s string) string { return "" } +// excludedForUnifiedBuild lists files that cannot be tested +// when using the unified build's export data. +// TODO(gri) enable as soon as the unified build supports this. +var excludedForUnifiedBuild = map[string]bool{ + "issue47818.go2": true, +} + func testFiles(t *testing.T, filenames []string, colDelta uint, manual bool) { if len(filenames) == 0 { t.Fatal("no source files") } + if buildcfg.Experiment.Unified { + for _, f := range filenames { + if excludedForUnifiedBuild[filepath.Base(f)] { + t.Logf("%s cannot be tested with unified build - skipped", f) + return + } + } + } + var mode syntax.Mode if strings.HasSuffix(filenames[0], ".go2") || manual { mode |= syntax.AllowGenerics diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 739fc163de..91503f1fcd 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -570,7 +570,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named check.validType(obj.typ, nil) // If typ is local, an error was already reported where typ is specified/defined. if check.isImportedConstraint(rhs) && !check.allowVersion(check.pkg, 1, 18) { - check.versionErrorf(tdecl.Type.Pos(), "go1.18", "using type constraint %s", rhs) + check.versionErrorf(tdecl.Type, "go1.18", "using type constraint %s", rhs) } }).describef(obj, "validType(%s)", obj.Name()) diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2 index 166cc680db..2631118bae 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2 @@ -8,6 +8,8 @@ package go1_17 +import "constraints" + type T[P /* ERROR type parameters require go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ] struct{} // for init (and main, but we're not in package main) we should only get one error @@ -56,4 +58,4 @@ type ( _ = C2 ) -// TODO(gri) need test cases for imported constraint types (see also issue #47967) \ No newline at end of file +type Ordered constraints /* ERROR using type constraint constraints\.Ordered requires go1\.18 or later */ .Ordered -- GitLab From 9e13a8876fb531861cbb8e865e57431de9818c16 Mon Sep 17 00:00:00 2001 From: Alessandro Arzilli Date: Mon, 15 Nov 2021 09:42:28 +0100 Subject: [PATCH 2191/2500] debug/dwarf: better error message when reading absent debug_line_str When a DW_FORM_line_strp is used without a debug_line_str section a good error message (about the missing section) is generated but immediately overwritten by the underflow error generated by trying to read the non-existent section. Updates #49590 Change-Id: I1c431392123a86c78c95ef1f185ebd6f17f2476a Reviewed-on: https://go-review.googlesource.com/c/go/+/363894 Run-TryBot: Alessandro Arzilli Trust: David Chase Reviewed-by: Than McIntosh --- src/debug/dwarf/entry.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/debug/dwarf/entry.go b/src/debug/dwarf/entry.go index 9f5ac57080..25a3b5beec 100644 --- a/src/debug/dwarf/entry.go +++ b/src/debug/dwarf/entry.go @@ -641,6 +641,7 @@ func (b *buf) entry(cu *Entry, atab abbrevTable, ubase Offset, vers int) *Entry } else { if len(b.dwarf.lineStr) == 0 { b.error("DW_FORM_line_strp with no .debug_line_str section") + return nil } b1 = makeBuf(b.dwarf, b.format, "line_str", 0, b.dwarf.lineStr) } -- GitLab From 865689571d52fee0b4c910d54bd4ba1484ff2344 Mon Sep 17 00:00:00 2001 From: jiahua wang Date: Fri, 12 Nov 2021 10:15:21 +0800 Subject: [PATCH 2192/2500] doc/go1.18: add AppendRune doc For #47694 Change-Id: I39594c273aeb038702457587ee1c46e4b3920bb6 Reviewed-on: https://go-review.googlesource.com/c/go/+/363359 Reviewed-by: Ian Lance Taylor Reviewed-by: Dmitri Shuralyov Reviewed-by: Jeremy Faller Trust: Jeremy Faller --- doc/go1.18.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index e796215c78..e266889cad 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -441,7 +441,8 @@ Do not send CLs removing the interior tags from such phrases.

unicode/utf8

- TODO: https://golang.org/cl/345571: add AppendRune + The AppendRune function appends the UTF-8 new + encoding of a rune to a []byte.

-- GitLab From fdd67930a0f2fec891e4be9c2b62996eb8b06ce5 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sat, 13 Nov 2021 14:36:35 -0800 Subject: [PATCH 2193/2500] sync: in TryLock try to acquire mutex even if state is not 0 For #45435 Change-Id: I728accd9a53c1826243f52aa04dc2a0a1dfdaadf Reviewed-on: https://go-review.googlesource.com/c/go/+/363672 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Dmitry Vyukov --- src/sync/mutex.go | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/sync/mutex.go b/src/sync/mutex.go index 9dd04d9470..18b2cedba7 100644 --- a/src/sync/mutex.go +++ b/src/sync/mutex.go @@ -87,13 +87,22 @@ func (m *Mutex) Lock() { // and use of TryLock is often a sign of a deeper problem // in a particular use of mutexes. func (m *Mutex) TryLock() bool { - if atomic.CompareAndSwapInt32(&m.state, 0, mutexLocked) { - if race.Enabled { - race.Acquire(unsafe.Pointer(m)) - } - return true + old := m.state + if old&(mutexLocked|mutexStarving) != 0 { + return false + } + + // There may be a goroutine waiting for the mutex, but we are + // running now and can try to grab the mutex before that + // goroutine wakes up. + if !atomic.CompareAndSwapInt32(&m.state, old, old|mutexLocked) { + return false + } + + if race.Enabled { + race.Acquire(unsafe.Pointer(m)) } - return false + return true } func (m *Mutex) lockSlow() { -- GitLab From febbef593e8d77500d0e330db91a7be1a71d05e9 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Mon, 15 Nov 2021 14:42:42 -0800 Subject: [PATCH 2194/2500] doc: mention generics in release notes Also mention local types restriction. We probably want to say more at some point, this is just a placeholder to start. Update #47631 Change-Id: I828e451e1e8504d21cb55c7132e9cb330b160a54 Reviewed-on: https://go-review.googlesource.com/c/go/+/364134 Trust: Keith Randall Reviewed-by: Robert Griesemer --- doc/go1.18.html | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/doc/go1.18.html b/doc/go1.18.html index e266889cad..1ad651ffe8 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -29,6 +29,24 @@ Do not send CLs removing the interior tags from such phrases. TODO: complete this section

+

Generics

+ +

+Go 1.18 includes an implementation of generics as described +by the +proposal. +

+ +

+ The current generics implementation has the following limitations: +

    +
  • + The Go compiler cannot currently handle type declarations inside generic functions + or methods. We hope to provide support for this feature in Go 1.19. +
  • +
+

+

Ports

FreeBSD

-- GitLab From a52e4b9c7e8f5aae678596e0c198e67b3b2b1087 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 15 Nov 2021 14:56:33 -0800 Subject: [PATCH 2195/2500] cmd/compile/internal/types2: use Identical to verify type identity in the Context map This is a clean port of CL 362798 from go/types to types2, with an additional comment adjustment in types2 and go/types. Change-Id: Ifa3d11f512f794f8ae2b6aca50b625a4a44672de Reviewed-on: https://go-review.googlesource.com/c/go/+/364135 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/context.go | 52 +++++++++++++++---- .../compile/internal/types2/instantiate.go | 4 +- src/cmd/compile/internal/types2/named.go | 2 +- src/cmd/compile/internal/types2/predicates.go | 17 ++++++ src/cmd/compile/internal/types2/subst.go | 2 +- src/cmd/compile/internal/types2/typexpr.go | 18 +++---- src/go/types/typexpr.go | 2 +- 7 files changed, 72 insertions(+), 25 deletions(-) diff --git a/src/cmd/compile/internal/types2/context.go b/src/cmd/compile/internal/types2/context.go index 9e9eb5bdf6..8833b8097e 100644 --- a/src/cmd/compile/internal/types2/context.go +++ b/src/cmd/compile/internal/types2/context.go @@ -5,6 +5,7 @@ package types2 import ( "bytes" + "fmt" "strings" "sync" ) @@ -16,15 +17,15 @@ import ( // It is safe for concurrent use. type Context struct { mu sync.Mutex - typeMap map[string]*Named // type hash -> instance - nextID int // next unique ID - seen map[*Named]int // assigned unique IDs + typeMap map[string][]*Named // type hash -> instances + nextID int // next unique ID + seen map[*Named]int // assigned unique IDs } // NewContext creates a new Context. func NewContext() *Context { return &Context{ - typeMap: make(map[string]*Named), + typeMap: make(map[string][]*Named), seen: make(map[*Named]int), } } @@ -56,17 +57,46 @@ func (ctxt *Context) typeHash(typ Type, targs []Type) string { return strings.Replace(buf.String(), " ", "#", -1) // ReplaceAll is not available in Go1.4 } -// typeForHash returns the recorded type for the type hash h, if it exists. -// If no type exists for h and n is non-nil, n is recorded for h. -func (ctxt *Context) typeForHash(h string, n *Named) *Named { +// lookup returns an existing instantiation of orig with targs, if it exists. +// Otherwise, it returns nil. +func (ctxt *Context) lookup(h string, orig *Named, targs []Type) *Named { ctxt.mu.Lock() defer ctxt.mu.Unlock() - if existing := ctxt.typeMap[h]; existing != nil { - return existing + + for _, e := range ctxt.typeMap[h] { + if identicalInstance(orig, targs, e.orig, e.TypeArgs().list()) { + return e + } + if debug { + // Panic during development to surface any imperfections in our hash. + panic(fmt.Sprintf("non-identical instances: (orig: %s, targs: %v) and %s", orig, targs, e)) + } } - if n != nil { - ctxt.typeMap[h] = n + + return nil +} + +// update de-duplicates n against previously seen types with the hash h. If an +// identical type is found with the type hash h, the previously seen type is +// returned. Otherwise, n is returned, and recorded in the Context for the hash +// h. +func (ctxt *Context) update(h string, n *Named) *Named { + assert(n != nil) + + ctxt.mu.Lock() + defer ctxt.mu.Unlock() + + for _, e := range ctxt.typeMap[h] { + if n == nil || Identical(n, e) { + return e + } + if debug { + // Panic during development to surface any imperfections in our hash. + panic(fmt.Sprintf("%s and %s are not identical", n, e)) + } } + + ctxt.typeMap[h] = append(ctxt.typeMap[h], n) return n } diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 3834c6ba87..65ed25ddff 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -60,7 +60,7 @@ func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type, ctxt *Con h = ctxt.typeHash(t, targs) // typ may already have been instantiated with identical type arguments. In // that case, re-use the existing instance. - if named := ctxt.typeForHash(h, nil); named != nil { + if named := ctxt.lookup(h, t, targs); named != nil { return named } } @@ -73,7 +73,7 @@ func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type, ctxt *Con if ctxt != nil { // It's possible that we've lost a race to add named to the context. // In this case, use whichever instance is recorded in the context. - named = ctxt.typeForHash(h, named) + named = ctxt.update(h, named) } return named diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index e73a31d42e..78c6803d99 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -253,7 +253,7 @@ func expandNamed(ctxt *Context, n *Named, instPos syntax.Pos) (tparams *TypePara ctxt = check.bestContext(ctxt) h := ctxt.typeHash(n.orig, n.targs.list()) // ensure that an instance is recorded for h to avoid infinite recursion. - ctxt.typeForHash(h, n) + ctxt.update(h, n) smap := makeSubstMap(n.orig.tparams.list(), n.targs.list()) underlying = n.check.subst(instPos, n.orig.underlying, smap, ctxt) diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 8ba534ce77..e7834a0f9e 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -372,6 +372,23 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { return false } +// identicalInstance reports if two type instantiations are identical. +// Instantiations are identical if their origin and type arguments are +// identical. +func identicalInstance(xorig Type, xargs []Type, yorig Type, yargs []Type) bool { + if len(xargs) != len(yargs) { + return false + } + + for i, xa := range xargs { + if !Identical(xa, yargs[i]) { + return false + } + } + + return Identical(xorig, yorig) +} + func identicalTParams(x, y []*TypeParam, cmpTags bool, p *ifacePair) bool { if len(x) != len(y) { return false diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index ed1fbbf941..9b82f8889a 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -209,7 +209,7 @@ func (subst *subster) typ(typ Type) Type { // before creating a new named type, check if we have this one already h := subst.ctxt.typeHash(t.orig, newTArgs) dump(">>> new type hash: %s", h) - if named := subst.ctxt.typeForHash(h, nil); named != nil { + if named := subst.ctxt.lookup(h, t.orig, newTArgs); named != nil { dump(">>> found %s", named) return named } diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index e077879b9d..05481a9a64 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -418,8 +418,8 @@ func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def return gtyp // error already reported } - origin, _ := gtyp.(*Named) - if origin == nil { + orig, _ := gtyp.(*Named) + if orig == nil { panic(fmt.Sprintf("%v: cannot instantiate %v", x.Pos(), gtyp)) } @@ -437,23 +437,23 @@ func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def } // create the instance - h := check.conf.Context.typeHash(origin, targs) + h := check.conf.Context.typeHash(orig, targs) // targs may be incomplete, and require inference. In any case we should de-duplicate. - inst := check.conf.Context.typeForHash(h, nil) + inst := check.conf.Context.lookup(h, orig, targs) // If inst is non-nil, we can't just return here. Inst may have been // constructed via recursive substitution, in which case we wouldn't do the // validation below. Ensure that the validation (and resulting errors) runs // for each instantiated type in the source. if inst == nil { - tname := NewTypeName(x.Pos(), origin.obj.pkg, origin.obj.name, nil) - inst = check.newNamed(tname, origin, nil, nil, nil) // underlying, methods and tparams are set when named is resolved + tname := NewTypeName(x.Pos(), orig.obj.pkg, orig.obj.name, nil) + inst = check.newNamed(tname, orig, nil, nil, nil) // underlying, methods and tparams are set when named is resolved inst.targs = NewTypeList(targs) - inst = check.conf.Context.typeForHash(h, inst) + inst = check.conf.Context.update(h, inst) } def.setUnderlying(inst) inst.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, []*Func) { - tparams := origin.TypeParams().list() + tparams := orig.TypeParams().list() inferred := targs if len(targs) < len(tparams) { @@ -469,7 +469,7 @@ func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def return expandNamed(ctxt, n, x.Pos()) } - // origin.tparams may not be set up, so we need to do expansion later. + // orig.tparams may not be set up, so we need to do expansion later. check.later(func() { // This is an instance from the source, not from recursive substitution, // and so it must be resolved during type-checking so that we can report diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index d80acbe7d6..5828c2e7c3 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -449,7 +449,7 @@ func (check *Checker) instantiatedType(ix *typeparams.IndexExpr, def *Named) (re return expandNamed(ctxt, n, pos) } - // origin.tparams may not be set up, so we need to do expansion later. + // orig.tparams may not be set up, so we need to do expansion later. check.later(func() { // This is an instance from the source, not from recursive substitution, // and so it must be resolved during type-checking so that we can report -- GitLab From 313cae3861841e9c64bebe2c1aed8126cf6cc117 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 15 Nov 2021 15:21:42 -0800 Subject: [PATCH 2196/2500] cmd/compile/internal/types2: refactor the Context type map to accept arbitrary types This CL is a clean port of CL 362799 from go/types to types2. Change-Id: Id670aa4b1ca0b568a79bb6e4855747807dcf00f3 Reviewed-on: https://go-review.googlesource.com/c/go/+/364154 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/context.go | 42 ++++++++++++------- .../compile/internal/types2/instantiate.go | 25 ++++++----- src/cmd/compile/internal/types2/named.go | 2 +- src/cmd/compile/internal/types2/typexpr.go | 4 +- 4 files changed, 41 insertions(+), 32 deletions(-) diff --git a/src/cmd/compile/internal/types2/context.go b/src/cmd/compile/internal/types2/context.go index 8833b8097e..b6fd9822b2 100644 --- a/src/cmd/compile/internal/types2/context.go +++ b/src/cmd/compile/internal/types2/context.go @@ -17,15 +17,21 @@ import ( // It is safe for concurrent use. type Context struct { mu sync.Mutex - typeMap map[string][]*Named // type hash -> instances - nextID int // next unique ID - seen map[*Named]int // assigned unique IDs + typeMap map[string][]ctxtEntry // type hash -> instances entries + nextID int // next unique ID + seen map[*Named]int // assigned unique IDs +} + +type ctxtEntry struct { + orig Type + targs []Type + instance Type // = orig[targs] } // NewContext creates a new Context. func NewContext() *Context { return &Context{ - typeMap: make(map[string][]*Named), + typeMap: make(map[string][]ctxtEntry), seen: make(map[*Named]int), } } @@ -59,17 +65,17 @@ func (ctxt *Context) typeHash(typ Type, targs []Type) string { // lookup returns an existing instantiation of orig with targs, if it exists. // Otherwise, it returns nil. -func (ctxt *Context) lookup(h string, orig *Named, targs []Type) *Named { +func (ctxt *Context) lookup(h string, orig *Named, targs []Type) Type { ctxt.mu.Lock() defer ctxt.mu.Unlock() for _, e := range ctxt.typeMap[h] { - if identicalInstance(orig, targs, e.orig, e.TypeArgs().list()) { - return e + if identicalInstance(orig, targs, e.orig, e.targs) { + return e.instance } if debug { // Panic during development to surface any imperfections in our hash. - panic(fmt.Sprintf("non-identical instances: (orig: %s, targs: %v) and %s", orig, targs, e)) + panic(fmt.Sprintf("non-identical instances: (orig: %s, targs: %v) and %s", orig, targs, e.instance)) } } @@ -80,24 +86,28 @@ func (ctxt *Context) lookup(h string, orig *Named, targs []Type) *Named { // identical type is found with the type hash h, the previously seen type is // returned. Otherwise, n is returned, and recorded in the Context for the hash // h. -func (ctxt *Context) update(h string, n *Named) *Named { - assert(n != nil) - +func (ctxt *Context) update(h string, orig Type, targs []Type, inst Type) Type { + assert(inst != nil) ctxt.mu.Lock() defer ctxt.mu.Unlock() for _, e := range ctxt.typeMap[h] { - if n == nil || Identical(n, e) { - return e + if inst == nil || Identical(inst, e.instance) { + return e.instance } if debug { // Panic during development to surface any imperfections in our hash. - panic(fmt.Sprintf("%s and %s are not identical", n, e)) + panic(fmt.Sprintf("%s and %s are not identical", inst, e.instance)) } } - ctxt.typeMap[h] = append(ctxt.typeMap[h], n) - return n + ctxt.typeMap[h] = append(ctxt.typeMap[h], ctxtEntry{ + orig: orig, + targs: targs, + instance: inst, + }) + + return inst } // idForType returns a unique ID for the pointer n. diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 65ed25ddff..9408fa43d9 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -52,20 +52,20 @@ func Instantiate(ctxt *Context, typ Type, targs []Type, validate bool) (Type, er // instance creates a type or function instance using the given original type // typ and arguments targs. For Named types the resulting instance will be // unexpanded. -func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type, ctxt *Context) Type { - switch t := typ.(type) { +func (check *Checker) instance(pos syntax.Pos, orig Type, targs []Type, ctxt *Context) Type { + switch orig := orig.(type) { case *Named: var h string if ctxt != nil { - h = ctxt.typeHash(t, targs) + h = ctxt.typeHash(orig, targs) // typ may already have been instantiated with identical type arguments. In // that case, re-use the existing instance. - if named := ctxt.lookup(h, t, targs); named != nil { + if named := ctxt.lookup(h, orig, targs); named != nil { return named } } - tname := NewTypeName(pos, t.obj.pkg, t.obj.name, nil) - named := check.newNamed(tname, t, nil, nil, nil) // underlying, tparams, and methods are set when named is resolved + tname := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil) + named := check.newNamed(tname, orig, nil, nil, nil) // underlying, tparams, and methods are set when named is resolved named.targs = NewTypeList(targs) named.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, []*Func) { return expandNamed(ctxt, n, pos) @@ -73,23 +73,23 @@ func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type, ctxt *Con if ctxt != nil { // It's possible that we've lost a race to add named to the context. // In this case, use whichever instance is recorded in the context. - named = ctxt.update(h, named) + named = ctxt.update(h, orig, targs, named).(*Named) } return named case *Signature: - tparams := t.TypeParams() + tparams := orig.TypeParams() if !check.validateTArgLen(pos, tparams.Len(), len(targs)) { return Typ[Invalid] } if tparams.Len() == 0 { - return typ // nothing to do (minor optimization) + return orig // nothing to do (minor optimization) } - sig := check.subst(pos, typ, makeSubstMap(tparams.list(), targs), ctxt).(*Signature) + sig := check.subst(pos, orig, makeSubstMap(tparams.list(), targs), ctxt).(*Signature) // If the signature doesn't use its type parameters, subst // will not make a copy. In that case, make a copy now (so // we can set tparams to nil w/o causing side-effects). - if sig == t { + if sig == orig { copy := *sig sig = © } @@ -98,9 +98,8 @@ func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type, ctxt *Con sig.tparams = nil return sig } - // only types and functions can be generic - panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ)) + panic(fmt.Sprintf("%v: cannot instantiate %v", pos, orig)) } // validateTArgLen verifies that the length of targs and tparams matches, diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index 78c6803d99..e90c301a0d 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -253,7 +253,7 @@ func expandNamed(ctxt *Context, n *Named, instPos syntax.Pos) (tparams *TypePara ctxt = check.bestContext(ctxt) h := ctxt.typeHash(n.orig, n.targs.list()) // ensure that an instance is recorded for h to avoid infinite recursion. - ctxt.update(h, n) + ctxt.update(h, n.orig, n.TypeArgs().list(), n) smap := makeSubstMap(n.orig.tparams.list(), n.targs.list()) underlying = n.check.subst(instPos, n.orig.underlying, smap, ctxt) diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 05481a9a64..4ba21fa9a0 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -439,7 +439,7 @@ func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def // create the instance h := check.conf.Context.typeHash(orig, targs) // targs may be incomplete, and require inference. In any case we should de-duplicate. - inst := check.conf.Context.lookup(h, orig, targs) + inst, _ := check.conf.Context.lookup(h, orig, targs).(*Named) // If inst is non-nil, we can't just return here. Inst may have been // constructed via recursive substitution, in which case we wouldn't do the // validation below. Ensure that the validation (and resulting errors) runs @@ -448,7 +448,7 @@ func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def tname := NewTypeName(x.Pos(), orig.obj.pkg, orig.obj.name, nil) inst = check.newNamed(tname, orig, nil, nil, nil) // underlying, methods and tparams are set when named is resolved inst.targs = NewTypeList(targs) - inst = check.conf.Context.update(h, inst) + inst = check.conf.Context.update(h, orig, targs, inst).(*Named) } def.setUnderlying(inst) -- GitLab From 6b3f4d388fe5602172f45361f438edf54699b953 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 15 Nov 2021 15:28:12 -0800 Subject: [PATCH 2197/2500] cmd/compile/internal/types2: re-use type hashing logic in Context.typeHash This CL is clean port of CL 362800 from go/types to types2. Change-Id: I66443b5a82b3a9c2f608a0fe012fbb099db996f3 Reviewed-on: https://go-review.googlesource.com/c/go/+/364155 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/context.go | 26 +++++++------------ .../compile/internal/types2/instantiate.go | 4 +-- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/cmd/compile/internal/types2/context.go b/src/cmd/compile/internal/types2/context.go index b6fd9822b2..93a0cb8d40 100644 --- a/src/cmd/compile/internal/types2/context.go +++ b/src/cmd/compile/internal/types2/context.go @@ -36,28 +36,22 @@ func NewContext() *Context { } } -// typeHash returns a string representation of typ, which can be used as an exact -// type hash: types that are identical produce identical string representations. -// If typ is a *Named type and targs is not empty, typ is printed as if it were -// instantiated with targs. The result is guaranteed to not contain blanks (" "). +// typeHash returns a string representation of typ instantiated with targs, +// which can be used as an exact type hash: types that are identical produce +// identical string representations. If targs is not empty, typ is printed as +// if it were instantiated with targs. The result is guaranteed to not contain +// blanks (" "). func (ctxt *Context) typeHash(typ Type, targs []Type) string { assert(ctxt != nil) assert(typ != nil) var buf bytes.Buffer h := newTypeHasher(&buf, ctxt) - // Caution: don't use asNamed here. TypeHash may be called for unexpanded - // types. We don't need anything other than name and type arguments below, - // which do not require expansion. - if named, _ := typ.(*Named); named != nil && len(targs) > 0 { - // Don't use WriteType because we need to use the provided targs - // and not any targs that might already be with the *Named type. - h.typePrefix(named) - h.typeName(named.obj) + h.typ(typ) + if len(targs) > 0 { + // TODO(rfindley): consider asserting on isGeneric(typ) here, if and when + // isGeneric handles *Signature types. h.typeList(targs) - } else { - assert(targs == nil) - h.typ(typ) } return strings.Replace(buf.String(), " ", "#", -1) // ReplaceAll is not available in Go1.4 @@ -65,7 +59,7 @@ func (ctxt *Context) typeHash(typ Type, targs []Type) string { // lookup returns an existing instantiation of orig with targs, if it exists. // Otherwise, it returns nil. -func (ctxt *Context) lookup(h string, orig *Named, targs []Type) Type { +func (ctxt *Context) lookup(h string, orig Type, targs []Type) Type { ctxt.mu.Lock() defer ctxt.mu.Unlock() diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 9408fa43d9..299d63dc60 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -60,8 +60,8 @@ func (check *Checker) instance(pos syntax.Pos, orig Type, targs []Type, ctxt *Co h = ctxt.typeHash(orig, targs) // typ may already have been instantiated with identical type arguments. In // that case, re-use the existing instance. - if named := ctxt.lookup(h, orig, targs); named != nil { - return named + if inst := ctxt.lookup(h, orig, targs); inst != nil { + return inst } } tname := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil) -- GitLab From 6e481c0b36ca484a9fe4a1de25b6def06a26b988 Mon Sep 17 00:00:00 2001 From: Alberto Donizetti Date: Wed, 27 Oct 2021 17:37:09 +0200 Subject: [PATCH 2198/2500] cmd/go: don't try to print build info of non-Go binaries On a non-nil err, buildinfo.ReadFile will always return a nil *Buildinfo. In scanFile, we need to return early if that happens. Fixes #49181 Change-Id: I354348d206ab084804937c6f922eadb61435e7b5 Reviewed-on: https://go-review.googlesource.com/c/go/+/359154 Trust: Alberto Donizetti Run-TryBot: Alberto Donizetti Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/version/version.go | 1 + src/cmd/go/testdata/script/go_version.txt | 9 +++++++++ 2 files changed, 10 insertions(+) create mode 100644 src/cmd/go/testdata/script/go_version.txt diff --git a/src/cmd/go/internal/version/version.go b/src/cmd/go/internal/version/version.go index febc7c638a..52502e95c6 100644 --- a/src/cmd/go/internal/version/version.go +++ b/src/cmd/go/internal/version/version.go @@ -151,6 +151,7 @@ func scanFile(file string, info fs.FileInfo, mustPrint bool) { fmt.Fprintf(os.Stderr, "%s: %v\n", file, err) } } + return } fmt.Printf("%s: %s\n", file, bi.GoVersion) diff --git a/src/cmd/go/testdata/script/go_version.txt b/src/cmd/go/testdata/script/go_version.txt new file mode 100644 index 0000000000..1a787e1b18 --- /dev/null +++ b/src/cmd/go/testdata/script/go_version.txt @@ -0,0 +1,9 @@ +# test that go version doesn't panic on non-go binaries +# See Issue #49181 + +[exec:/bin/true] cp /bin/true true +[exec:C:\windows\system32\help.exe] cp C:\windows\system32\help.exe help.exe + +go version -m . +! stdout . +! stderr . -- GitLab From 9efb6493f498f8fdcc5d34d4df4d5e9c620f861b Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 15 Nov 2021 21:12:33 -0500 Subject: [PATCH 2199/2500] all: update vendored golang.org/x/tools Update the vendored x/tools to pick up the fix for #49597, using the following commands: go get -d golang.org/x/tools@4adea5033c5c6f39a900d4b963c4b496448b1655 go mod tidy go mod vendor Fixes #49597 Change-Id: Ib1bc43aacbdc707b605194012134f048a336e176 Reviewed-on: https://go-review.googlesource.com/c/go/+/363986 Trust: Robert Findley Run-TryBot: Dmitri Shuralyov Reviewed-by: Dmitri Shuralyov TryBot-Result: Go Bot --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 +- .../go/analysis/passes/composite/composite.go | 21 ++- .../x/tools/go/analysis/passes/shift/shift.go | 20 ++- .../analysis/passes/stringintconv/string.go | 37 +++-- .../x/tools/internal/typeparams/normalize.go | 132 ++++++++---------- src/cmd/vendor/modules.txt | 2 +- 7 files changed, 117 insertions(+), 101 deletions(-) diff --git a/src/cmd/go.mod b/src/cmd/go.mod index facc54cee1..014c854a73 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -8,7 +8,7 @@ require ( golang.org/x/mod v0.6.0-dev.0.20210913215816-37dd6891021a golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 - golang.org/x/tools v0.1.8-0.20211109164901-e9000123914f + golang.org/x/tools v0.1.8-0.20211116011028-4adea5033c5c ) require ( diff --git a/src/cmd/go.sum b/src/cmd/go.sum index f248d84e24..4f50e7c6c8 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -18,7 +18,7 @@ golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e h1:i6Vklmyu+fZMFYpum+sR4ZWAB golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/tools v0.1.8-0.20211109164901-e9000123914f h1:wwsTeyXackfHvwdCKtGcDlYwO78AwwW6OwUomSMB0aI= -golang.org/x/tools v0.1.8-0.20211109164901-e9000123914f/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.8-0.20211116011028-4adea5033c5c h1:EftGXIEk7/EwE5R+/azXJzSbzwNumuLeH9oupAN7YV0= +golang.org/x/tools v0.1.8-0.20211116011028-4adea5033c5c/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/composite/composite.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/composite/composite.go index 025952ed50..d3670aca97 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/composite/composite.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/composite/composite.go @@ -68,17 +68,26 @@ func run(pass *analysis.Pass) (interface{}, error) { // skip whitelisted types return } - terms, err := typeparams.StructuralTerms(typ) - if err != nil { - return // invalid type + var structuralTypes []types.Type + switch typ := typ.(type) { + case *typeparams.TypeParam: + terms, err := typeparams.StructuralTerms(typ) + if err != nil { + return // invalid type + } + for _, term := range terms { + structuralTypes = append(structuralTypes, term.Type()) + } + default: + structuralTypes = append(structuralTypes, typ) } - for _, term := range terms { - under := deref(term.Type().Underlying()) + for _, typ := range structuralTypes { + under := deref(typ.Underlying()) if _, ok := under.(*types.Struct); !ok { // skip non-struct composite literals continue } - if isLocalType(pass, term.Type()) { + if isLocalType(pass, typ) { // allow unkeyed locally defined composite literal continue } diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/shift/shift.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/shift/shift.go index 640de28e05..e968f27b40 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/shift/shift.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/shift/shift.go @@ -14,6 +14,7 @@ import ( "go/ast" "go/constant" "go/token" + "go/types" "math" "golang.org/x/tools/go/analysis" @@ -95,13 +96,22 @@ func checkLongShift(pass *analysis.Pass, node ast.Node, x, y ast.Expr) { if t == nil { return } - terms, err := typeparams.StructuralTerms(t) - if err != nil { - return // invalid type + var structuralTypes []types.Type + switch t := t.(type) { + case *typeparams.TypeParam: + terms, err := typeparams.StructuralTerms(t) + if err != nil { + return // invalid type + } + for _, term := range terms { + structuralTypes = append(structuralTypes, term.Type()) + } + default: + structuralTypes = append(structuralTypes, t) } sizes := make(map[int64]struct{}) - for _, term := range terms { - size := 8 * pass.TypesSizes.Sizeof(term.Type()) + for _, t := range structuralTypes { + size := 8 * pass.TypesSizes.Sizeof(t) sizes[size] = struct{}{} } minSize := int64(math.MaxInt64) diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go index 92fd375f23..e41de809de 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go @@ -110,17 +110,17 @@ func run(pass *analysis.Pass) (interface{}, error) { // First, find a type T0 in T that has an underlying type of string. T := tname.Type() - tterms, err := typeparams.StructuralTerms(T) + ttypes, err := structuralTypes(T) if err != nil { return // invalid type } var T0 types.Type // string type in the type set of T - for _, term := range tterms { - u, _ := term.Type().Underlying().(*types.Basic) + for _, tt := range ttypes { + u, _ := tt.Underlying().(*types.Basic) if u != nil && u.Kind() == types.String { - T0 = term.Type() + T0 = tt break } } @@ -133,21 +133,21 @@ func run(pass *analysis.Pass) (interface{}, error) { // Next, find a type V0 in V that has an underlying integral type that is // not byte or rune. V := pass.TypesInfo.TypeOf(arg) - vterms, err := typeparams.StructuralTerms(V) + vtypes, err := structuralTypes(V) if err != nil { return // invalid type } var V0 types.Type // integral type in the type set of V - for _, term := range vterms { - u, _ := term.Type().Underlying().(*types.Basic) + for _, vt := range vtypes { + u, _ := vt.Underlying().(*types.Basic) if u != nil && u.Info()&types.IsInteger != 0 { switch u.Kind() { case types.Byte, types.Rune, types.UntypedRune: continue } - V0 = term.Type() + V0 = vt break } } @@ -158,8 +158,8 @@ func run(pass *analysis.Pass) (interface{}, error) { } convertibleToRune := true // if true, we can suggest a fix - for _, term := range vterms { - if !types.ConvertibleTo(term.Type(), types.Typ[types.Rune]) { + for _, t := range vtypes { + if !types.ConvertibleTo(t, types.Typ[types.Rune]) { convertibleToRune = false break } @@ -200,3 +200,20 @@ func run(pass *analysis.Pass) (interface{}, error) { }) return nil, nil } + +func structuralTypes(t types.Type) ([]types.Type, error) { + var structuralTypes []types.Type + switch t := t.(type) { + case *typeparams.TypeParam: + terms, err := typeparams.StructuralTerms(t) + if err != nil { + return nil, err + } + for _, term := range terms { + structuralTypes = append(structuralTypes, term.Type()) + } + default: + structuralTypes = append(structuralTypes, t) + } + return structuralTypes, nil +} diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/normalize.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/normalize.go index 29373508e9..f41ec6ec0b 100644 --- a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/normalize.go +++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/normalize.go @@ -16,92 +16,72 @@ import ( const debug = false -// NormalizeInterface returns the normal form of the interface iface, or nil if iface -// has an empty type set (i.e. there are no types that satisfy iface). If the -// resulting interface is non-nil, it will be identical to iface. +var ErrEmptyTypeSet = errors.New("empty type set") + +// StructuralTerms returns a slice of terms representing the normalized +// structural type restrictions of a type parameter, if any. +// +// Structural type restrictions of a type parameter are created via +// non-interface types embedded in its constraint interface (directly, or via a +// chain of interface embeddings). For example, in the declaration `type T[P +// interface{~int; m()}] int`, the structural restriction of the type parameter +// P is ~int. +// +// With interface embedding and unions, the specification of structural type +// restrictions may be arbitrarily complex. For example, consider the +// following: +// +// type A interface{ ~string|~[]byte } +// +// type B interface{ int|string } +// +// type C interface { ~string|~int } +// +// type T[P interface{ A|B; C }] int // -// An error is returned if the interface type is invalid, or too complicated to -// reasonably normalize (for example, contains unions with more than a hundred -// terms). +// In this example, the structural type restriction of P is ~string|int: A|B +// expands to ~string|~[]byte|int|string, which reduces to ~string|~[]byte|int, +// which when intersected with C (~string|~int) yields ~string|int. // -// An interface is in normal form if and only if: -// - it has 0 or 1 embedded types. -// - its embedded type is either a types.Union or has a concrete -// (non-interface) underlying type -// - if the embedded type is a union, each term of the union has a concrete -// underlying type, and no terms may be removed without changing the type set -// of the interface -func NormalizeInterface(iface *types.Interface) (*types.Interface, error) { - var methods []*types.Func - for i := 0; i < iface.NumMethods(); i++ { - methods = append(methods, iface.Method(i)) +// StructuralTerms computes these expansions and reductions, producing a +// "normalized" form of the embeddings. A structural restriction is normalized +// if it is a single union containing no interface terms, and is minimal in the +// sense that removing any term changes the set of types satisfying the +// constraint. It is left as a proof for the reader that, modulo sorting, there +// is exactly one such normalized form. +// +// Because the minimal representation always takes this form, StructuralTerms +// returns a slice of tilde terms corresponding to the terms of the union in +// the normalized structural restriction. An error is returned if the +// constraint interface is invalid, exceeds complexity bounds, or has an empty +// type set. In the latter case, StructuralTerms returns ErrEmptyTypeSet. +// +// StructuralTerms makes no guarantees about the order of terms, except that it +// is deterministic. +func StructuralTerms(tparam *TypeParam) ([]*Term, error) { + constraint := tparam.Constraint() + if constraint == nil { + return nil, fmt.Errorf("%s has nil constraint", tparam) + } + iface, _ := constraint.Underlying().(*types.Interface) + if iface == nil { + return nil, fmt.Errorf("constraint is %T, not *types.Interface", constraint.Underlying()) } - var embeddeds []types.Type tset, err := computeTermSet(iface, make(map[types.Type]*termSet), 0) if err != nil { return nil, err } - switch { - case tset.terms.isEmpty(): - // Special case: as documented + if tset.terms.isEmpty() { + return nil, ErrEmptyTypeSet + } + if tset.terms.isAll() { return nil, nil - - case tset.terms.isAll(): - // No embeddeds. - - case len(tset.terms) == 1: - if !tset.terms[0].tilde { - embeddeds = append(embeddeds, tset.terms[0].typ) - break - } - fallthrough - default: - var terms []*Term - for _, term := range tset.terms { - terms = append(terms, NewTerm(term.tilde, term.typ)) - } - embeddeds = append(embeddeds, NewUnion(terms)) } - - return types.NewInterfaceType(methods, embeddeds), nil -} - -var ErrEmptyTypeSet = errors.New("empty type set") - -// StructuralTerms returns the normalized structural type restrictions of a -// type, if any. For types that are not type parameters, it returns term slice -// containing a single non-tilde term holding the given type. For type -// parameters, it returns the normalized term list of the type parameter's -// constraint. See NormalizeInterface for more information on the normal form -// of a constraint interface. -// -// StructuralTerms returns an error if the structural term list cannot be -// computed. If the type set of typ is empty, it returns ErrEmptyTypeSet. -func StructuralTerms(typ types.Type) ([]*Term, error) { - switch typ := typ.(type) { - case *TypeParam: - iface, _ := typ.Constraint().(*types.Interface) - if iface == nil { - return nil, fmt.Errorf("constraint is %T, not *types.Interface", typ) - } - tset, err := computeTermSet(iface, make(map[types.Type]*termSet), 0) - if err != nil { - return nil, err - } - if tset.terms.isEmpty() { - return nil, ErrEmptyTypeSet - } - if tset.terms.isAll() { - return nil, nil - } - var terms []*Term - for _, term := range tset.terms { - terms = append(terms, NewTerm(term.tilde, term.typ)) - } - return terms, nil - default: - return []*Term{NewTerm(false, typ)}, nil + var terms []*Term + for _, term := range tset.terms { + terms = append(terms, NewTerm(term.tilde, term.typ)) } + return terms, nil } // A termSet holds the normalized set of terms for a given type. diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 3806f7171c..82e04c1d33 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -51,7 +51,7 @@ golang.org/x/sys/windows # golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 ## explicit; go 1.17 golang.org/x/term -# golang.org/x/tools v0.1.8-0.20211109164901-e9000123914f +# golang.org/x/tools v0.1.8-0.20211116011028-4adea5033c5c ## explicit; go 1.17 golang.org/x/tools/cover golang.org/x/tools/go/analysis -- GitLab From bddb79f0faa11958ff473109398be684c088a6a9 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 15 Nov 2021 22:22:26 -0500 Subject: [PATCH 2200/2500] go/types: use type variables consistently in Checker.conversion This is a clean port of CL 362895 from types2 to go/types. Change-Id: Icd0631127c51aec80ce9450df2be71bf4b96b2df Reviewed-on: https://go-review.googlesource.com/c/go/+/363987 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/conversions.go | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go index 26bebd4ade..18d24e404c 100644 --- a/src/go/types/conversions.go +++ b/src/go/types/conversions.go @@ -139,39 +139,39 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { } // "V and T are both integer or floating point types" - if isIntegerOrFloat(V) && isIntegerOrFloat(T) { + if isIntegerOrFloat(Vu) && isIntegerOrFloat(Tu) { return true } // "V and T are both complex types" - if isComplex(V) && isComplex(T) { + if isComplex(Vu) && isComplex(Tu) { return true } // "V is an integer or a slice of bytes or runes and T is a string type" - if (isInteger(V) || isBytesOrRunes(Vu)) && isString(T) { + if (isInteger(Vu) || isBytesOrRunes(Vu)) && isString(Tu) { return true } // "V is a string and T is a slice of bytes or runes" - if isString(V) && isBytesOrRunes(Tu) { + if isString(Vu) && isBytesOrRunes(Tu) { return true } // package unsafe: // "any pointer or value of underlying type uintptr can be converted into a unsafe.Pointer" - if (isPointer(Vu) || isUintptr(Vu)) && isUnsafePointer(T) { + if (isPointer(Vu) || isUintptr(Vu)) && isUnsafePointer(Tu) { return true } // "and vice versa" - if isUnsafePointer(V) && (isPointer(Tu) || isUintptr(Tu)) { + if isUnsafePointer(Vu) && (isPointer(Tu) || isUintptr(Tu)) { return true } - // "V is a slice, T is a pointer-to-array type, + // "V a slice, T is a pointer-to-array type, // and the slice and array types have identical element types." - if s, _ := under(V).(*Slice); s != nil { - if p, _ := under(T).(*Pointer); p != nil { + if s, _ := Vu.(*Slice); s != nil { + if p, _ := Tu.(*Pointer); p != nil { if a, _ := under(p.Elem()).(*Array); a != nil { if Identical(s.Elem(), a.Elem()) { if check == nil || check.allowVersion(check.pkg, 1, 17) { @@ -249,20 +249,12 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { return false } -// Helper predicates for convertibleToImpl. The types provided to convertibleToImpl -// may be type parameters but they won't have specific type terms. Thus it is ok to -// use the toT convenience converters in the predicates below. - func isUintptr(typ Type) bool { t, _ := under(typ).(*Basic) return t != nil && t.kind == Uintptr } func isUnsafePointer(typ Type) bool { - // TODO(gri): Is this under(typ).(*Basic) instead of typ.(*Basic) correct? - // (The former calls under(), while the latter doesn't.) - // The spec does not say so, but gc claims it is. See also - // issue 6326. t, _ := under(typ).(*Basic) return t != nil && t.kind == UnsafePointer } -- GitLab From 67c15568156eb0c5607edc51a2b5d69876ba236d Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 15 Nov 2021 22:23:24 -0500 Subject: [PATCH 2201/2500] go/types: rename structure to structuralType This is a clean port of CL 362994 from types2 to go/types. Change-Id: I51b38c35ec3306274ef0355516e2d5557e7d8b46 Reviewed-on: https://go-review.googlesource.com/c/go/+/363988 Trust: Robert Findley Reviewed-by: Robert Griesemer Run-TryBot: Robert Findley TryBot-Result: Go Bot --- src/go/types/builtins.go | 22 +++++++++++----------- src/go/types/call.go | 2 +- src/go/types/expr.go | 2 +- src/go/types/index.go | 2 +- src/go/types/infer.go | 2 +- src/go/types/predicates.go | 4 ++-- src/go/types/stmt.go | 2 +- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index c2d36e9711..8d293a9af3 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -83,7 +83,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // of S and the respective parameter passing rules apply." S := x.typ var T Type - if s, _ := structure(S).(*Slice); s != nil { + if s, _ := structuralType(S).(*Slice); s != nil { T = s.elem } else { check.invalidArg(x, _InvalidAppend, "%s is not a slice", x) @@ -332,14 +332,14 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b case _Copy: // copy(x, y []T) int - dst, _ := structure(x.typ).(*Slice) + dst, _ := structuralType(x.typ).(*Slice) var y operand arg(&y, 1) if y.mode == invalid { return } - src, _ := structureString(y.typ).(*Slice) + src, _ := structuralString(y.typ).(*Slice) if dst == nil || src == nil { check.invalidArg(x, _InvalidCopy, "copy expects slice arguments; found %s and %s", x, &y) @@ -473,7 +473,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b } var min int // minimum number of arguments - switch structure(T).(type) { + switch structuralType(T).(type) { case *Slice: min = 2 case *Map, *Chan: @@ -776,11 +776,11 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b return true } -// If typ is a type parameter, structure returns the single underlying -// type of all types in the corresponding type constraint if it exists, -// or nil otherwise. If typ is not a type parameter, structure returns +// If typ is a type parameter, structuralType returns the single underlying +// type of all types in the corresponding type constraint if it exists, or +// nil otherwise. If typ is not a type parameter, structuralType returns // the underlying type. -func structure(typ Type) Type { +func structuralType(typ Type) Type { var su Type if underIs(typ, func(u Type) bool { if su != nil && !Identical(su, u) { @@ -795,10 +795,10 @@ func structure(typ Type) Type { return nil } -// structureString is like structure but also considers []byte and -// string as "identical". In this case, if successful, the result +// structuralString is like structuralType but also considers []byte +// and string as "identical". In this case, if successful, the result // is always []byte. -func structureString(typ Type) Type { +func structuralString(typ Type) Type { var su Type if underIs(typ, func(u Type) bool { if isString(u) { diff --git a/src/go/types/call.go b/src/go/types/call.go index 927c9f2a44..dfd7142094 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -175,7 +175,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { cgocall := x.mode == cgofunc // a type parameter may be "called" if all types have the same signature - sig, _ := structure(x.typ).(*Signature) + sig, _ := structuralType(x.typ).(*Signature) if sig == nil { check.invalidOp(x, _InvalidCall, "cannot call non-function %s", x) x.mode = invalid diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 9d9eddfb95..0edaf63db0 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -1228,7 +1228,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { goto Error } - switch utyp := structure(base).(type) { + switch utyp := structuralType(base).(type) { case *Struct: // Prevent crash if the struct referred to is not yet set up. // See analogous comment for *Array. diff --git a/src/go/types/index.go b/src/go/types/index.go index cd19f50627..534b445e9e 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -211,7 +211,7 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { valid := false length := int64(-1) // valid if >= 0 - switch u := structure(x.typ).(type) { + switch u := structuralType(x.typ).(type) { case nil: check.errorf(x, _NonSliceableOperand, "cannot slice %s: type set has no single underlying type", x) x.mode = invalid diff --git a/src/go/types/infer.go b/src/go/types/infer.go index f4f9bfac8f..909042219c 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -377,7 +377,7 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type, // If a constraint has a structural type, unify the corresponding type parameter with it. for _, tpar := range tparams { - sbound := structure(tpar) + sbound := structuralType(tpar) if sbound != nil { // If the structural type is the underlying type of a single // defined type in the constraint, use that defined type instead. diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index e7f9d3b1db..2d9b9c4c07 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -33,7 +33,7 @@ func isBasic(t Type, info BasicInfo) bool { // The allX predicates below report whether t is an X. // If t is a type parameter the result is true if isX is true // for all specified types of the type parameter's type set. -// allX is an optimized version of isX(structure(t)) (which +// allX is an optimized version of isX(structuralType(t)) (which // is the same as underIs(t, isX)). func allBoolean(typ Type) bool { return allBasic(typ, IsBoolean) } @@ -47,7 +47,7 @@ func allNumericOrString(typ Type) bool { return allBasic(typ, IsNumeric|IsString // allBasic reports whether under(t) is a basic type with the specified info. // If t is a type parameter, the result is true if isBasic(t, info) is true // for all specific types of the type parameter's type set. -// allBasic(t, info) is an optimized version of isBasic(structure(t), info). +// allBasic(t, info) is an optimized version of isBasic(structuralType(t), info). func allBasic(t Type, info BasicInfo) bool { switch u := under(t).(type) { case *Basic: diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index 2a3fb5f6f5..3d4a20f808 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -834,7 +834,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { if x.mode != invalid { // Ranging over a type parameter is permitted if it has a single underlying type. var cause string - u := structure(x.typ) + u := structuralType(x.typ) switch t := u.(type) { case nil: cause = "type set has no single underlying type" -- GitLab From 50dac3b410b9bc47dabc3f3c2afd21f7aecfb118 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 15 Nov 2021 22:27:19 -0500 Subject: [PATCH 2202/2500] go/types: move some functions into different files (cleanup) This is a clean port of CL 362995 from types2 to go/types. Change-Id: Iefc37b28178795ea944e0bc0ff91982251de2944 Reviewed-on: https://go-review.googlesource.com/c/go/+/363989 Trust: Robert Findley Reviewed-by: Robert Griesemer Run-TryBot: Robert Findley TryBot-Result: Go Bot --- src/go/types/builtins.go | 40 ------------------------------------ src/go/types/type.go | 44 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 41 insertions(+), 43 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 8d293a9af3..9b50403d7f 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -776,46 +776,6 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b return true } -// If typ is a type parameter, structuralType returns the single underlying -// type of all types in the corresponding type constraint if it exists, or -// nil otherwise. If typ is not a type parameter, structuralType returns -// the underlying type. -func structuralType(typ Type) Type { - var su Type - if underIs(typ, func(u Type) bool { - if su != nil && !Identical(su, u) { - return false - } - // su == nil || Identical(su, u) - su = u - return true - }) { - return su - } - return nil -} - -// structuralString is like structuralType but also considers []byte -// and string as "identical". In this case, if successful, the result -// is always []byte. -func structuralString(typ Type) Type { - var su Type - if underIs(typ, func(u Type) bool { - if isString(u) { - u = NewSlice(universeByte) - } - if su != nil && !Identical(su, u) { - return false - } - // su == nil || Identical(su, u) - su = u - return true - }) { - return su - } - return nil -} - // hasVarSize reports if the size of type t is variable due to type parameters. func hasVarSize(t Type) bool { switch t := under(t).(type) { diff --git a/src/go/types/type.go b/src/go/types/type.go index b1e2bda4cd..26a605444d 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -27,10 +27,47 @@ func under(t Type) Type { return t } -// If the argument to asNamed, or asTypeParam is of the respective type -// (possibly after resolving a *Named type), these methods return that type. -// Otherwise the result is nil. +// If typ is a type parameter, structuralType returns the single underlying +// type of all types in the corresponding type constraint if it exists, +// or nil otherwise. If typ is not a type parameter, structuralType returns +// the underlying type. +func structuralType(typ Type) Type { + var su Type + if underIs(typ, func(u Type) bool { + if su != nil && !Identical(su, u) { + return false + } + // su == nil || Identical(su, u) + su = u + return true + }) { + return su + } + return nil +} + +// structuralString is like structuralType but also considers []byte +// and string as "identical". In this case, if successful, the result +// is always []byte. +func structuralString(typ Type) Type { + var su Type + if underIs(typ, func(u Type) bool { + if isString(u) { + u = NewSlice(universeByte) + } + if su != nil && !Identical(su, u) { + return false + } + // su == nil || Identical(su, u) + su = u + return true + }) { + return su + } + return nil +} +// If t is a defined type, asNamed returns that type (possibly after resolving it), otherwise it returns nil. func asNamed(t Type) *Named { e, _ := t.(*Named) if e != nil { @@ -39,6 +76,7 @@ func asNamed(t Type) *Named { return e } +// If t is a type parameter, asTypeParam returns that type, otherwise it returns nil. func asTypeParam(t Type) *TypeParam { u, _ := under(t).(*TypeParam) return u -- GitLab From 46e98d489fda3bc1e36af92ee625b2fce3c1f88e Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 15 Nov 2021 22:33:22 -0500 Subject: [PATCH 2203/2500] go/types: refer to structural rather than single underlying type in errors This is a port of CL 362997 from types2 to go/types. Some error positions were adjusted in tests. Change-Id: I6a932aee1a8d9bcbf4cd8c16a95bbb41b5c7e13f Reviewed-on: https://go-review.googlesource.com/c/go/+/363990 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/builtins.go | 2 +- src/go/types/index.go | 2 +- src/go/types/stmt.go | 4 ++-- src/go/types/testdata/check/builtins.go2 | 6 +++--- src/go/types/testdata/check/typeparams.go2 | 12 ++++++------ 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 9b50403d7f..b767128367 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -479,7 +479,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b case *Map, *Chan: min = 1 case nil: - check.errorf(arg0, _InvalidMake, "cannot make %s; type set has no single underlying type", arg0) + check.errorf(arg0, _InvalidMake, "cannot make %s: no structural type", arg0) return default: check.invalidArg(arg0, _InvalidMake, "cannot make %s; type must be slice, map, or channel", arg0) diff --git a/src/go/types/index.go b/src/go/types/index.go index 534b445e9e..0284716277 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -213,7 +213,7 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { length := int64(-1) // valid if >= 0 switch u := structuralType(x.typ).(type) { case nil: - check.errorf(x, _NonSliceableOperand, "cannot slice %s: type set has no single underlying type", x) + check.invalidOp(x, _NonSliceableOperand, "cannot slice %s: %s has no structural type", x, x.typ) x.mode = invalid return diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index 3d4a20f808..e7514f19ae 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -832,12 +832,12 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { // determine key/value types var key, val Type if x.mode != invalid { - // Ranging over a type parameter is permitted if it has a single underlying type. + // Ranging over a type parameter is permitted if it has a structural type. var cause string u := structuralType(x.typ) switch t := u.(type) { case nil: - cause = "type set has no single underlying type" + cause = check.sprintf("%s has no structural type", x.typ) case *Chan: if s.Value != nil { check.softErrorf(s.Value, _InvalidIterVar, "range over %s permits only one iteration variable", &x) diff --git a/src/go/types/testdata/check/builtins.go2 b/src/go/types/testdata/check/builtins.go2 index 7cca6fd714..c1accff016 100644 --- a/src/go/types/testdata/check/builtins.go2 +++ b/src/go/types/testdata/check/builtins.go2 @@ -148,7 +148,7 @@ func _[ _ = make /* ERROR expects 2 or 3 arguments */ (S1) _ = make(S1, 10, 20) _ = make /* ERROR expects 2 or 3 arguments */ (S1, 10, 20, 30) - _ = make(S2 /* ERROR cannot make .* no single underlying type */ , 10) + _ = make(S2 /* ERROR cannot make S2: no structural type */ , 10) type M0 map[string]int _ = make(map[string]int) @@ -156,7 +156,7 @@ func _[ _ = make(M1) _ = make(M1, 10) _ = make/* ERROR expects 1 or 2 arguments */(M1, 10, 20) - _ = make(M2 /* ERROR cannot make .* no single underlying type */ ) + _ = make(M2 /* ERROR cannot make M2: no structural type */ ) type C0 chan int _ = make(chan int) @@ -164,7 +164,7 @@ func _[ _ = make(C1) _ = make(C1, 10) _ = make/* ERROR expects 1 or 2 arguments */(C1, 10, 20) - _ = make(C2 /* ERROR cannot make .* no single underlying type */ ) + _ = make(C2 /* ERROR cannot make C2: no structural type */ ) _ = make(C3) } diff --git a/src/go/types/testdata/check/typeparams.go2 b/src/go/types/testdata/check/typeparams.go2 index 09d478c4d7..6bf303af90 100644 --- a/src/go/types/testdata/check/typeparams.go2 +++ b/src/go/types/testdata/check/typeparams.go2 @@ -134,7 +134,7 @@ func _[T interface{ ~string }] (x T, i, j, k int) { var _ T = x /* ERROR 3-index type myByte1 []byte type myByte2 []byte func _[T interface{ []byte | myByte1 | myByte2 }] (x T, i, j, k int) { var _ T = x[i:j:k] } -func _[T interface{ []byte | myByte1 | []int }] (x T, i, j, k int) { var _ T = x /* ERROR no single underlying type */ [i:j:k] } +func _[T interface{ []byte | myByte1 | []int }] (x T, i, j, k int) { var _ T = x /* ERROR no structural type */ [i:j:k] } // len/cap built-ins @@ -210,7 +210,7 @@ func _[ for _, _ /* ERROR permits only one iteration variable */ = range c1 {} var c2 C2 - for range c2 /* ERROR cannot range over c2.*no single underlying type */ {} + for range c2 /* ERROR cannot range over c2.*no structural type */ {} var c3 C3 for range c3 /* ERROR receive from send-only channel */ {} @@ -226,7 +226,7 @@ func _[ for _, _ = range s1 {} var s2 S2 - for range s2 /* ERROR cannot range over s2.*no single underlying type */ {} + for range s2 /* ERROR cannot range over s2.*no structural type */ {} var a0 []int for range a0 {} @@ -239,7 +239,7 @@ func _[ for _, _ = range a1 {} var a2 A2 - for range a2 /* ERROR cannot range over a2.*no single underlying type */ {} + for range a2 /* ERROR cannot range over a2.*no structural type */ {} var p0 *[10]int for range p0 {} @@ -252,7 +252,7 @@ func _[ for _, _ = range p1 {} var p2 P2 - for range p2 /* ERROR cannot range over p2.*no single underlying type */ {} + for range p2 /* ERROR cannot range over p2.*no structural type */ {} var m0 map[string]int for range m0 {} @@ -265,7 +265,7 @@ func _[ for _, _ = range m1 {} var m2 M2 - for range m2 /* ERROR cannot range over m2.*no single underlying type */ {} + for range m2 /* ERROR cannot range over m2.*no structural type */ {} } // type inference checks -- GitLab From 289c930750fccac6aca578c675694b612532fd24 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 15 Nov 2021 22:42:41 -0500 Subject: [PATCH 2204/2500] go/types: slightly relax notion of structural type This is a port of CL 363075 from types2 to go/types, adjusted for the different error reporting API, and to adjust positions of error messages in tests. Change-Id: Ic6bfedf1152eff94bad20725b56e6ba804b2e3e8 Reviewed-on: https://go-review.googlesource.com/c/go/+/363991 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/expr.go | 35 ++++++------ src/go/types/stmt.go | 32 +++++------ src/go/types/testdata/check/typeparams.go2 | 2 +- .../types/testdata/fixedbugs/issue43671.go2 | 6 +- .../types/testdata/fixedbugs/issue45920.go2 | 17 ++++++ .../types/testdata/fixedbugs/issue47115.go2 | 4 +- src/go/types/type.go | 55 ++++++++++++++++--- 7 files changed, 98 insertions(+), 53 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue45920.go2 diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 0edaf63db0..6eeb431b73 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -174,29 +174,26 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr) { return case token.ARROW: - var elem Type - if !underIs(x.typ, func(u Type) bool { - ch, _ := u.(*Chan) - if ch == nil { - check.invalidOp(x, _InvalidReceive, "cannot receive from non-channel %s", x) - return false - } - if ch.dir == SendOnly { - check.invalidOp(x, _InvalidReceive, "cannot receive from send-only channel %s", x) - return false - } - if elem != nil && !Identical(ch.elem, elem) { - check.invalidOp(x, _InvalidReceive, "channels of %s must have the same element type", x) - return false - } - elem = ch.elem - return true - }) { + u := structuralType(x.typ) + if u == nil { + check.invalidOp(x, _InvalidReceive, "cannot receive from %s: no structural type", x) x.mode = invalid return } + ch, _ := u.(*Chan) + if ch == nil { + check.invalidOp(x, _InvalidReceive, "cannot receive from non-channel %s", x) + x.mode = invalid + return + } + if ch.dir == SendOnly { + check.invalidOp(x, _InvalidReceive, "cannot receive from send-only channel %s", x) + x.mode = invalid + return + } + x.mode = commaok - x.typ = elem + x.typ = ch.elem check.hasCallOrRecv = true return } diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index e7514f19ae..363ea35acf 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -417,27 +417,21 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { if ch.mode == invalid || val.mode == invalid { return } - var elem Type - if !underIs(ch.typ, func(u Type) bool { - uch, _ := u.(*Chan) - if uch == nil { - check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "cannot send to non-channel %s", &ch) - return false - } - if uch.dir == RecvOnly { - check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "cannot send to receive-only channel %s", &ch) - return false - } - if elem != nil && !Identical(uch.elem, elem) { - check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "channels of %s must have the same element type", &ch) - return false - } - elem = uch.elem - return true - }) { + u := structuralType(ch.typ) + if u == nil { + check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "cannot send to %s: no structural type", &ch) return } - check.assignment(&val, elem, "send") + uch, _ := u.(*Chan) + if uch == nil { + check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "cannot send to non-channel %s", &ch) + return + } + if uch.dir == RecvOnly { + check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "cannot send to receive-only channel %s", &ch) + return + } + check.assignment(&val, uch.elem, "send") case *ast.IncDecStmt: var op token.Token diff --git a/src/go/types/testdata/check/typeparams.go2 b/src/go/types/testdata/check/typeparams.go2 index 6bf303af90..9e2bffb539 100644 --- a/src/go/types/testdata/check/typeparams.go2 +++ b/src/go/types/testdata/check/typeparams.go2 @@ -210,7 +210,7 @@ func _[ for _, _ /* ERROR permits only one iteration variable */ = range c1 {} var c2 C2 - for range c2 /* ERROR cannot range over c2.*no structural type */ {} + for range c2 {} var c3 C3 for range c3 /* ERROR receive from send-only channel */ {} diff --git a/src/go/types/testdata/fixedbugs/issue43671.go2 b/src/go/types/testdata/fixedbugs/issue43671.go2 index 6cc3801cc9..46ac51ebdd 100644 --- a/src/go/types/testdata/fixedbugs/issue43671.go2 +++ b/src/go/types/testdata/fixedbugs/issue43671.go2 @@ -12,11 +12,11 @@ type C4 interface{ chan int | chan<- int } type C5[T any] interface{ ~chan T | <-chan T } func _[T any](ch T) { - <-ch // ERROR cannot receive from non-channel + <-ch // ERROR cannot receive from ch .* no structural type } func _[T C0](ch T) { - <-ch // ERROR cannot receive from non-channel + <-ch // ERROR cannot receive from non-channel ch } func _[T C1](ch T) { @@ -28,7 +28,7 @@ func _[T C2](ch T) { } func _[T C3](ch T) { - <-ch // ERROR channels of ch .* must have the same element type + <-ch // ERROR cannot receive from ch .* no structural type } func _[T C4](ch T) { diff --git a/src/go/types/testdata/fixedbugs/issue45920.go2 b/src/go/types/testdata/fixedbugs/issue45920.go2 new file mode 100644 index 0000000000..f659f3a0db --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue45920.go2 @@ -0,0 +1,17 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func f1[T any, C chan T | <-chan T](ch C) {} + +func _(ch chan int) { f1(ch) } +func _(ch <-chan int) { f1(ch) } +func _(ch chan<- int) { f1 /* ERROR chan<- int does not satisfy chan T\|<-chan T */ (ch) } + +func f2[T any, C chan T | chan<- T](ch C) {} + +func _(ch chan int) { f2(ch) } +func _(ch <-chan int) { f2 /* ERROR <-chan int does not satisfy chan T\|chan<- T */ (ch)} +func _(ch chan<- int) { f2(ch) } diff --git a/src/go/types/testdata/fixedbugs/issue47115.go2 b/src/go/types/testdata/fixedbugs/issue47115.go2 index 6694219b54..f71e06c9b2 100644 --- a/src/go/types/testdata/fixedbugs/issue47115.go2 +++ b/src/go/types/testdata/fixedbugs/issue47115.go2 @@ -12,7 +12,7 @@ type C4 interface{ chan int | chan<- int } type C5[T any] interface{ ~chan T | chan<- T } func _[T any](ch T) { - ch <- /* ERROR cannot send to non-channel */ 0 + ch <- /* ERROR cannot send to ch .* no structural type */ 0 } func _[T C0](ch T) { @@ -28,7 +28,7 @@ func _[T C2](ch T) { } func _[T C3](ch T) { - ch <- /* ERROR channels of ch .* must have the same element type */ 0 + ch <- /* ERROR cannot send to ch .* no structural type */ 0 } func _[T C4](ch T) { diff --git a/src/go/types/type.go b/src/go/types/type.go index 26a605444d..8f23fb530d 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -27,17 +27,51 @@ func under(t Type) Type { return t } +// If x and y are identical, match returns x. +// If x and y are identical channels but for their direction +// and one of them is unrestricted, match returns the channel +// with the restricted direction. +// In all other cases, match returns nil. +func match(x, y Type) Type { + // Common case: we don't have channels. + if Identical(x, y) { + return x + } + + // We may have channels that differ in direction only. + if x, _ := x.(*Chan); x != nil { + if y, _ := y.(*Chan); y != nil && Identical(x.elem, y.elem) { + // We have channels that differ in direction only. + // If there's an unrestricted channel, select the restricted one. + switch { + case x.dir == SendRecv: + return y + case y.dir == SendRecv: + return x + } + } + } + + // types are different + return nil +} + // If typ is a type parameter, structuralType returns the single underlying -// type of all types in the corresponding type constraint if it exists, -// or nil otherwise. If typ is not a type parameter, structuralType returns -// the underlying type. +// type of all types in the corresponding type constraint if it exists, or +// nil otherwise. If the type set contains only unrestricted and restricted +// channel types (with identical element types), the single underlying type +// is the restricted channel type if the restrictions are always the same. +// If typ is not a type parameter, structuralType returns the underlying type. func structuralType(typ Type) Type { var su Type if underIs(typ, func(u Type) bool { - if su != nil && !Identical(su, u) { - return false + if su != nil { + u = match(su, u) + if u == nil { + return false + } } - // su == nil || Identical(su, u) + // su == nil || match(su, u) != nil su = u return true }) { @@ -55,10 +89,13 @@ func structuralString(typ Type) Type { if isString(u) { u = NewSlice(universeByte) } - if su != nil && !Identical(su, u) { - return false + if su != nil { + u = match(su, u) + if u == nil { + return false + } } - // su == nil || Identical(su, u) + // su == nil || match(su, u) != nil su = u return true }) { -- GitLab From f041c7e3028545ba39c60d6e20ab9b74c01bbf33 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 15 Nov 2021 23:29:25 -0500 Subject: [PATCH 2205/2500] go/types: remove structuralString in favor of inlined code This is a clean port of CL 363154 from types2 to go/types. Change-Id: I26c18767041db096390e84ba9200ec69b66778d0 Reviewed-on: https://go-review.googlesource.com/c/go/+/364234 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/builtins.go | 21 ++++++++++++++++++++- src/go/types/type.go | 24 ------------------------ 2 files changed, 20 insertions(+), 25 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index b767128367..c1932232aa 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -339,7 +339,26 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b if y.mode == invalid { return } - src, _ := structuralString(y.typ).(*Slice) + // src, _ := structuralType(y.typ).(*Slice); but also accepts strings + var src *Slice + var elem Type // == src.elem if valid + if underIs(y.typ, func(u Type) bool { + switch u := u.(type) { + case *Basic: + if isString(u) && (elem == nil || Identical(elem, universeByte)) { + elem = universeByte + return true + } + case *Slice: + if elem == nil || Identical(elem, u.elem) { + elem = u.elem + return true + } + } + return false + }) { + src = NewSlice(elem) + } if dst == nil || src == nil { check.invalidArg(x, _InvalidCopy, "copy expects slice arguments; found %s and %s", x, &y) diff --git a/src/go/types/type.go b/src/go/types/type.go index 8f23fb530d..e26d8189d1 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -80,30 +80,6 @@ func structuralType(typ Type) Type { return nil } -// structuralString is like structuralType but also considers []byte -// and string as "identical". In this case, if successful, the result -// is always []byte. -func structuralString(typ Type) Type { - var su Type - if underIs(typ, func(u Type) bool { - if isString(u) { - u = NewSlice(universeByte) - } - if su != nil { - u = match(su, u) - if u == nil { - return false - } - } - // su == nil || match(su, u) != nil - su = u - return true - }) { - return su - } - return nil -} - // If t is a defined type, asNamed returns that type (possibly after resolving it), otherwise it returns nil. func asNamed(t Type) *Named { e, _ := t.(*Named) -- GitLab From 7c50ef6c8c4c827db45a3327cb950913cf9d489b Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 15 Nov 2021 23:39:22 -0500 Subject: [PATCH 2206/2500] go/types: remove asTypeParam and simplify some code This is a port of CL 363438 from types2 to go/types. Change-Id: I87c76d31b398b9ce406f96b0030ee458619b3dbe Reviewed-on: https://go-review.googlesource.com/c/go/+/364235 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/builtins.go | 6 +++--- src/go/types/call.go | 2 +- src/go/types/conversions.go | 6 +++--- src/go/types/decl.go | 11 ++++++----- src/go/types/expr.go | 5 ++--- src/go/types/instantiate.go | 8 ++++---- src/go/types/lookup.go | 8 +------- src/go/types/operand.go | 6 +++--- src/go/types/predicates.go | 2 +- src/go/types/type.go | 6 ------ src/go/types/typeset.go | 8 -------- src/go/types/typexpr.go | 2 +- src/go/types/union.go | 17 ++++++++--------- 13 files changed, 33 insertions(+), 54 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index c1932232aa..5418d66aeb 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -298,7 +298,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // the argument types must be of floating-point type // (applyTypeFunc never calls f with a type parameter) f := func(typ Type) Type { - assert(asTypeParam(typ) == nil) + assert(!isTypeParam(typ)) if t, _ := under(typ).(*Basic); t != nil { switch t.kind { case Float32: @@ -441,7 +441,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // the argument must be of complex type // (applyTypeFunc never calls f with a type parameter) f := func(typ Type) Type { - assert(asTypeParam(typ) == nil) + assert(!isTypeParam(typ)) if t, _ := under(typ).(*Basic); t != nil { switch t.kind { case Complex64: @@ -822,7 +822,7 @@ func hasVarSize(t Type) bool { // applyTypeFunc returns nil. // If x is not a type parameter, the result is f(x). func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { - if tp := asTypeParam(x); tp != nil { + if tp, _ := x.(*TypeParam); tp != nil { // Test if t satisfies the requirements for the argument // type and collect possible result types at the same time. var terms []*Term diff --git a/src/go/types/call.go b/src/go/types/call.go index dfd7142094..7cb6027f3b 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -531,7 +531,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { check.errorf(e.Sel, _InvalidMethodExpr, "cannot call pointer method %s on %s", sel, x.typ) default: var why string - if tpar := asTypeParam(x.typ); tpar != nil { + if tpar, _ := x.typ.(*TypeParam); tpar != nil { // Type parameter bounds don't specify fields, so don't mention "field". if tname := tpar.iface().obj; tname != nil { why = check.sprintf("interface %s has no method %s", tname.name, sel) diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go index 18d24e404c..eadc923f5e 100644 --- a/src/go/types/conversions.go +++ b/src/go/types/conversions.go @@ -47,7 +47,7 @@ func (check *Checker) conversion(x *operand, T Type) { // If T's type set is empty, or if it doesn't // have specific types, constant x cannot be // converted. - ok = under(T).(*TypeParam).underIs(func(u Type) bool { + ok = T.(*TypeParam).underIs(func(u Type) bool { // t is nil if there are no specific type terms if u == nil { cause = check.sprintf("%s does not contain specific types", T) @@ -186,8 +186,8 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { } // optimization: if we don't have type parameters, we're done - Vp, _ := Vu.(*TypeParam) - Tp, _ := Tu.(*TypeParam) + Vp, _ := V.(*TypeParam) + Tp, _ := T.(*TypeParam) if Vp == nil && Tp == nil { return false } diff --git a/src/go/types/decl.go b/src/go/types/decl.go index e12961416e..2108cf6b05 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -669,10 +669,11 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { } // Disallow a lone type parameter as the RHS of a type declaration (issue #45639). - // We can look directly at named.underlying because even if it is still a *Named - // type (underlying not fully resolved yet) it cannot become a type parameter due - // to this very restriction. - if tpar, _ := named.underlying.(*TypeParam); tpar != nil { + // We don't need this restriction anymore if we make the underlying type of a type + // parameter its constraint interface: if the RHS is a lone type parameter, we will + // use its underlying type (like we do for any RHS in a type declaration), and its + // underlying type is an interface and the type declaration is well defined. + if isTypeParam(rhs) { check.error(tdecl.Type, _MisplacedTypeParam, "cannot use a type parameter as RHS in type declaration") named.underlying = Typ[Invalid] } @@ -723,7 +724,7 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list *ast.FieldList check.later(func() { for i, bound := range bounds { - if _, ok := under(bound).(*TypeParam); ok { + if isTypeParam(bound) { check.error(posns[i], _MisplacedTypeParam, "cannot use a type parameter as constraint") } } diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 6eeb431b73..660c92de3b 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -147,11 +147,10 @@ var op2str2 = [...]string{ // If typ is a type parameter, underIs returns the result of typ.underIs(f). // Otherwise, underIs returns the result of f(under(typ)). func underIs(typ Type, f func(Type) bool) bool { - u := under(typ) - if tpar, _ := u.(*TypeParam); tpar != nil { + if tpar, _ := typ.(*TypeParam); tpar != nil { return tpar.underIs(f) } - return f(u) + return f(under(typ)) } // The unary expression e may be nil. It's passed in for better error messages only. diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 13d6e3114d..c9ce6f6ae1 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -157,7 +157,7 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap // A type argument that is a type parameter with an empty type set satisfies any constraint. // (The empty set is a subset of any set.) - if targ := asTypeParam(targ); targ != nil && targ.iface().typeSet().IsEmpty() { + if targ, _ := targ.(*TypeParam); targ != nil && targ.iface().typeSet().IsEmpty() { return nil } @@ -186,7 +186,7 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap // if iface is comparable, targ must be comparable // TODO(gri) the error messages needs to be better, here if iface.IsComparable() && !Comparable(targ) { - if tpar := asTypeParam(targ); tpar != nil && tpar.iface().typeSet().IsAll() { + if tpar, _ := targ.(*TypeParam); tpar != nil && tpar.iface().typeSet().IsAll() { return errorf("%s has no constraints", targ) } return errorf("%s does not satisfy comparable", targ) @@ -198,7 +198,7 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap // If the type argument is a pointer to a type parameter, the type argument's // method set is empty. // TODO(gri) is this what we want? (spec question) - if base, isPtr := deref(targ); isPtr && asTypeParam(base) != nil { + if base, isPtr := deref(targ); isPtr && isTypeParam(base) { return errorf("%s has no methods", targ) } if m, wrong := check.missingMethod(targ, iface, true); m != nil { @@ -227,7 +227,7 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap // If targ is itself a type parameter, each of its possible types must be in the set // of iface types (i.e., the targ type set must be a subset of the iface type set). // Type arguments with empty type sets were already excluded above. - if targ := asTypeParam(targ); targ != nil { + if targ, _ := targ.(*TypeParam); targ != nil { targBound := targ.iface() if !targBound.typeSet().subsetOf(iface.typeSet()) { // TODO(gri) report which type is missing diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index aae6fa206d..98af6bfcd7 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -134,14 +134,8 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o continue // we can't have a matching field or interface method } - // continue with underlying type, but only if it's not a type parameter - // TODO(gri) is this what we want to do for type parameters? (spec question) - // TODO(#45639) the error message produced as a result of skipping an - // underlying type parameter should be improved. + // continue with underlying type typ = named.under() - if asTypeParam(typ) != nil { - continue - } } tpar = nil diff --git a/src/go/types/operand.go b/src/go/types/operand.go index 8b76e939b6..6f902e9749 100644 --- a/src/go/types/operand.go +++ b/src/go/types/operand.go @@ -166,7 +166,7 @@ func operandString(x *operand, qf Qualifier) string { } buf.WriteString(intro) WriteType(&buf, x.typ, qf) - if tpar := asTypeParam(x.typ); tpar != nil { + if tpar, _ := x.typ.(*TypeParam); tpar != nil { buf.WriteString(" constrained by ") WriteType(&buf, tpar.bound, qf) // do not compute interface type sets here } @@ -241,8 +241,8 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er Vu := under(V) Tu := under(T) - Vp, _ := Vu.(*TypeParam) - Tp, _ := Tu.(*TypeParam) + Vp, _ := V.(*TypeParam) + Tp, _ := T.(*TypeParam) // x is an untyped value representable by a value of type T. if isUntyped(Vu) { diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 2d9b9c4c07..d0697b1ad7 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -92,7 +92,7 @@ func IsInterface(t Type) bool { // isTypeParam reports whether t is a type parameter. func isTypeParam(t Type) bool { - _, ok := under(t).(*TypeParam) + _, ok := t.(*TypeParam) return ok } diff --git a/src/go/types/type.go b/src/go/types/type.go index e26d8189d1..555eb9e8b9 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -88,9 +88,3 @@ func asNamed(t Type) *Named { } return e } - -// If t is a type parameter, asTypeParam returns that type, otherwise it returns nil. -func asTypeParam(t Type) *TypeParam { - u, _ := under(t).(*TypeParam) - return u -} diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index 1e6b9dd390..d0464aeaa0 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -289,10 +289,6 @@ func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_T continue // ignore invalid unions } terms = tset.terms - case *TypeParam: - // Embedding stand-alone type parameters is not permitted. - // Union parsing reports a (delayed) error, so we can ignore this entry. - continue default: if u == Typ[Invalid] { continue @@ -370,10 +366,6 @@ func computeUnionTypeSet(check *Checker, pos token.Pos, utyp *Union) *_TypeSet { switch u := under(t.typ).(type) { case *Interface: terms = computeInterfaceTypeSet(check, pos, u).terms - case *TypeParam: - // A stand-alone type parameters is not permitted as union term. - // Union parsing reports a (delayed) error, so we can ignore this entry. - continue default: if t.typ == Typ[Invalid] { continue diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 5828c2e7c3..89264ee9eb 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -337,7 +337,7 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) { check.later(func() { if !Comparable(typ.key) { var why string - if asTypeParam(typ.key) != nil { + if isTypeParam(typ.key) { why = " (missing comparable constraint)" } check.errorf(e.Key, _IncomparableMapKey, "incomparable map key type %s%s", typ.key, why) diff --git a/src/go/types/union.go b/src/go/types/union.go index bb08174728..2a65ca4d8e 100644 --- a/src/go/types/union.go +++ b/src/go/types/union.go @@ -118,15 +118,14 @@ func parseTilde(check *Checker, x ast.Expr) (tilde bool, typ Type) { } typ = check.typ(x) // Embedding stand-alone type parameters is not permitted (issue #47127). - // Do this check later because it requires computation of the underlying type (see also issue #46461). - // Note: If an underlying type cannot be a type parameter, the call to - // under() will not be needed and then we don't need to delay this - // check to later and could return Typ[Invalid] instead. - check.later(func() { - if _, ok := under(typ).(*TypeParam); ok { - check.error(x, _MisplacedTypeParam, "cannot embed a type parameter") - } - }) + // We don't need this restriction anymore if we make the underlying type of a type + // parameter its constraint interface: if we embed a lone type parameter, we will + // simply use its underlying type (like we do for other named, embedded interfaces), + // and since the underlying type is an interface the embedding is well defined. + if isTypeParam(typ) { + check.error(x, _MisplacedTypeParam, "cannot embed a type parameter") + typ = Typ[Invalid] + } return } -- GitLab From 7f4a946fa26f2ffdc14c354f2f1cc193ab5d0e90 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Tue, 16 Nov 2021 21:59:15 +0700 Subject: [PATCH 2207/2500] cmd/compile: prevent irgen crashing for empty local declaration stmt Updates #47631 Fixes #49611 Change-Id: Ib4a4466038e0d4a9aa9380d7909f29f7d15c6c69 Reviewed-on: https://go-review.googlesource.com/c/go/+/364314 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stmt.go | 8 +++++--- test/fixedbugs/issue49611.go | 11 +++++++++++ test/typeparam/issue49611.go | 11 +++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 test/fixedbugs/issue49611.go create mode 100644 test/typeparam/issue49611.go diff --git a/src/cmd/compile/internal/noder/stmt.go b/src/cmd/compile/internal/noder/stmt.go index e329a59156..1e996b95c4 100644 --- a/src/cmd/compile/internal/noder/stmt.go +++ b/src/cmd/compile/internal/noder/stmt.go @@ -46,9 +46,11 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { n.SetTypecheck(1) return n case *syntax.DeclStmt: - if _, ok := stmt.DeclList[0].(*syntax.TypeDecl); ok && g.topFuncIsGeneric { - // TODO: remove this restriction. See issue 47631. - base.ErrorfAt(g.pos(stmt), "type declarations inside generic functions are not currently supported") + if g.topFuncIsGeneric && len(stmt.DeclList) > 0 { + if _, ok := stmt.DeclList[0].(*syntax.TypeDecl); ok { + // TODO: remove this restriction. See issue 47631. + base.ErrorfAt(g.pos(stmt), "type declarations inside generic functions are not currently supported") + } } n := ir.NewBlockStmt(g.pos(stmt), nil) g.decls(&n.List, stmt.DeclList) diff --git a/test/fixedbugs/issue49611.go b/test/fixedbugs/issue49611.go new file mode 100644 index 0000000000..b40ad58649 --- /dev/null +++ b/test/fixedbugs/issue49611.go @@ -0,0 +1,11 @@ +// compile + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func f() { + var () +} diff --git a/test/typeparam/issue49611.go b/test/typeparam/issue49611.go new file mode 100644 index 0000000000..96c651e2b5 --- /dev/null +++ b/test/typeparam/issue49611.go @@ -0,0 +1,11 @@ +// compile -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func f[T any]() { + var () +} -- GitLab From 79d0013f53d4199b9f84d813221b71adf7eb1e4d Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 15 Nov 2021 09:42:03 -0500 Subject: [PATCH 2208/2500] go/types, types2: improve error messages referencing any Because any is an a alias, it is naively formatted as interface{} in error messages. This is a source of verbosity and potential confusion. We can improve the situation by looking for pointer equality with the any type. To avoid churn in the importers, do this all at once across the compiler, go/types, and go/internal/gcimporter. CL 364194 makes the corresponding change in x/tools/go/internal/gcimporter, allowing the x/tools trybots to pass. Fixes #49583 Change-Id: Ib59570937601308483f6273364cc59338f9b8b3b Reviewed-on: https://go-review.googlesource.com/c/go/+/363974 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/importer/support.go | 4 ++++ src/cmd/compile/internal/noder/types.go | 8 ++++++++ src/cmd/compile/internal/types2/api_test.go | 6 +++--- src/cmd/compile/internal/types2/object.go | 8 ++++++++ src/cmd/compile/internal/types2/object_test.go | 9 +++++---- .../internal/types2/testdata/fixedbugs/issue48008.go2 | 2 +- src/cmd/compile/internal/types2/typestring.go | 7 +++++++ src/cmd/compile/internal/types2/universe.go | 5 ++++- src/go/internal/gcimporter/support.go | 4 ++++ src/go/types/api_test.go | 6 +++--- src/go/types/object.go | 8 ++++++++ src/go/types/object_test.go | 9 +++++---- src/go/types/testdata/fixedbugs/issue48008.go2 | 2 +- src/go/types/typestring.go | 7 +++++++ src/go/types/universe.go | 5 ++++- 15 files changed, 72 insertions(+), 18 deletions(-) diff --git a/src/cmd/compile/internal/importer/support.go b/src/cmd/compile/internal/importer/support.go index 6ceb413601..9377d99779 100644 --- a/src/cmd/compile/internal/importer/support.go +++ b/src/cmd/compile/internal/importer/support.go @@ -118,10 +118,14 @@ var predeclared = []types2.Type{ types2.Typ[types2.Invalid], // only appears in packages with errors // used internally by gc; never used by this package or in .a files + // not to be confused with the universe any anyType{}, // comparable types2.Universe.Lookup("comparable").Type(), + + // any + types2.Universe.Lookup("any").Type(), } type anyType struct{} diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index f035e0da97..fa24ab1844 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -26,6 +26,8 @@ func (g *irgen) pkg(pkg *types2.Package) *types.Pkg { return types.NewPkg(pkg.Path(), pkg.Name()) } +var universeAny = types2.Universe.Lookup("any").Type() + // typ converts a types2.Type to a types.Type, including caching of previously // translated types. func (g *irgen) typ(typ types2.Type) *types.Type { @@ -53,6 +55,12 @@ func (g *irgen) typ(typ types2.Type) *types.Type { // constructed part of a recursive type. Should not be called from outside this // file (g.typ is the "external" entry point). func (g *irgen) typ1(typ types2.Type) *types.Type { + // See issue 49583: the type checker has trouble keeping track of aliases, + // but for such a common alias as any we can improve things by preserving a + // pointer identity that can be checked when formatting type strings. + if typ == universeAny { + return types.AnyType + } // Cache type2-to-type mappings. Important so that each defined generic // type (instantiated or not) has a single types.Type representation. // Also saves a lot of computation and memory by avoiding re-translating diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index a59c9a4eee..866ebb8684 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -319,16 +319,16 @@ func TestTypesInfo(t *testing.T) { {brokenPkg + `x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string]invalid type`}, // parameterized functions - {`package p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[T interface{}](T)`}, + {`package p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[T any](T)`}, {`package p1; func f[T any](T) {}; var _ = f[int]`, `f[int]`, `func(int)`}, {`package p2; func f[T any](T) {}; func _() { f(42) }`, `f`, `func(int)`}, {`package p3; func f[T any](T) {}; func _() { f[int](42) }`, `f[int]`, `func(int)`}, - {`package p4; func f[T any](T) {}; func _() { f[int](42) }`, `f`, `func[T interface{}](T)`}, + {`package p4; func f[T any](T) {}; func _() { f[int](42) }`, `f`, `func[T any](T)`}, {`package p5; func f[T any](T) {}; func _() { f(42) }`, `f(42)`, `()`}, // type parameters {`package t0; type t[] int; var _ t`, `t`, `t0.t`}, // t[] is a syntax error that is ignored in this test in favor of t - {`package t1; type t[P any] int; var _ t[int]`, `t`, `t1.t[P interface{}]`}, + {`package t1; type t[P any] int; var _ t[int]`, `t`, `t1.t[P any]`}, {`package t2; type t[P interface{}] int; var _ t[int]`, `t`, `t2.t[P interface{}]`}, {`package t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `t3.t[P, Q interface{}]`}, {brokenPkg + `t4; type t[P, Q interface{ m() }] int; var _ t[int, int]`, `t`, `broken_t4.t[P, Q interface{m()}]`}, diff --git a/src/cmd/compile/internal/types2/object.go b/src/cmd/compile/internal/types2/object.go index da3e1a2abc..c7c64ca9d5 100644 --- a/src/cmd/compile/internal/types2/object.go +++ b/src/cmd/compile/internal/types2/object.go @@ -528,6 +528,14 @@ func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) { } } + // Special handling for any: because WriteType will format 'any' as 'any', + // resulting in the object string `type any = any` rather than `type any = + // interface{}`. To avoid this, swap in a different empty interface. + if obj == universeAny { + assert(Identical(typ, &emptyInterface)) + typ = &emptyInterface + } + buf.WriteByte(' ') WriteType(buf, typ, qf) } diff --git a/src/cmd/compile/internal/types2/object_test.go b/src/cmd/compile/internal/types2/object_test.go index 93b3dfb44b..8f0303d4b2 100644 --- a/src/cmd/compile/internal/types2/object_test.go +++ b/src/cmd/compile/internal/types2/object_test.go @@ -101,8 +101,8 @@ var testObjects = []struct { {"type t struct{f int}", "t", "type p.t struct{f int}"}, {"type t func(int)", "t", "type p.t func(int)"}, - {"type t[P any] struct{f P}", "t", "type p.t[P interface{}] struct{f P}"}, - {"type t[P any] struct{f P}", "t.P", "type parameter P interface{}"}, + {"type t[P any] struct{f P}", "t", "type p.t[P any] struct{f P}"}, + {"type t[P any] struct{f P}", "t.P", "type parameter P any"}, {"type C interface{m()}; type t[P C] struct{}", "t.P", "type parameter P p.C"}, {"type t = struct{f int}", "t", "type p.t = struct{f int}"}, @@ -111,8 +111,9 @@ var testObjects = []struct { {"var v int", "v", "var p.v int"}, {"func f(int) string", "f", "func p.f(int) string"}, - {"func g[P any](x P){}", "g", "func p.g[P interface{}](x P)"}, + {"func g[P any](x P){}", "g", "func p.g[P any](x P)"}, {"func g[P interface{~int}](x P){}", "g.P", "type parameter P interface{~int}"}, + {"", "any", "type any = interface{}"}, } func TestObjectString(t *testing.T) { @@ -131,7 +132,7 @@ func TestObjectString(t *testing.T) { t.Errorf("%s: invalid object path %s", test.src, test.obj) continue } - obj := pkg.Scope().Lookup(names[0]) + _, obj := pkg.Scope().LookupParent(names[0], nopos) if obj == nil { t.Errorf("%s: %s not found", test.src, names[0]) continue diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48008.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48008.go2 index 5c9726875c..6c14c78e4c 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48008.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48008.go2 @@ -21,7 +21,7 @@ func _(x interface{}) { case map[T[int]] string: case chan T[int]: - case T /* ERROR cannot use generic type T\[P interface{}\] without instantiation */ : + case T /* ERROR cannot use generic type T\[P any\] without instantiation */ : case []T /* ERROR cannot use generic type */ : case [10]T /* ERROR cannot use generic type */ : case struct{T /* ERROR cannot use generic type */ }: diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index f151f47a5e..0c93a7e6e4 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -197,6 +197,13 @@ func (w *typeWriter) typ(typ Type) { } case *Interface: + if t == universeAny.Type() && w.ctxt == nil { + // When not hashing, we can try to improve type strings by writing "any" + // for a type that is pointer-identical to universeAny. This logic should + // be deprecated by more robust handling for aliases. + w.string("any") + break + } if t.implicit { if len(t.methods) == 0 && len(t.embeddeds) == 1 { w.typ(t.embeddeds[0]) diff --git a/src/cmd/compile/internal/types2/universe.go b/src/cmd/compile/internal/types2/universe.go index fccab145f8..c16ae3f63e 100644 --- a/src/cmd/compile/internal/types2/universe.go +++ b/src/cmd/compile/internal/types2/universe.go @@ -79,7 +79,10 @@ func defPredeclaredTypes() { } // type any = interface{} - def(NewTypeName(nopos, nil, "any", &emptyInterface)) + // Note: don't use &emptyInterface for the type of any. Using a unique + // pointer allows us to detect any and format it as "any" rather than + // interface{}, which clarifies user-facing error messages significantly. + def(NewTypeName(nopos, nil, "any", &Interface{complete: true, tset: &topTypeSet})) // type error interface{ Error() string } { diff --git a/src/go/internal/gcimporter/support.go b/src/go/internal/gcimporter/support.go index 5aef63ec1e..965e5d8838 100644 --- a/src/go/internal/gcimporter/support.go +++ b/src/go/internal/gcimporter/support.go @@ -134,10 +134,14 @@ var predeclared = []types.Type{ types.Typ[types.Invalid], // only appears in packages with errors // used internally by gc; never used by this package or in .a files + // not to be confused with the universe any anyType{}, // comparable types.Universe.Lookup("comparable").Type(), + + // any + types.Universe.Lookup("any").Type(), } type anyType struct{} diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index c9127f366a..d8ca8ad611 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -349,16 +349,16 @@ func TestTypesInfo(t *testing.T) { {broken + `x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string]invalid type`}, // parameterized functions - {genericPkg + `p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[T interface{}](T)`}, + {genericPkg + `p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[T any](T)`}, {genericPkg + `p1; func f[T any](T) {}; var _ = f[int]`, `f[int]`, `func(int)`}, {genericPkg + `p2; func f[T any](T) {}; func _() { f(42) }`, `f`, `func(int)`}, {genericPkg + `p3; func f[T any](T) {}; func _() { f[int](42) }`, `f[int]`, `func(int)`}, - {genericPkg + `p4; func f[T any](T) {}; func _() { f[int](42) }`, `f`, `func[T interface{}](T)`}, + {genericPkg + `p4; func f[T any](T) {}; func _() { f[int](42) }`, `f`, `func[T any](T)`}, {genericPkg + `p5; func f[T any](T) {}; func _() { f(42) }`, `f(42)`, `()`}, // type parameters {genericPkg + `t0; type t[] int; var _ t`, `t`, `generic_t0.t`}, // t[] is a syntax error that is ignored in this test in favor of t - {genericPkg + `t1; type t[P any] int; var _ t[int]`, `t`, `generic_t1.t[P interface{}]`}, + {genericPkg + `t1; type t[P any] int; var _ t[int]`, `t`, `generic_t1.t[P any]`}, {genericPkg + `t2; type t[P interface{}] int; var _ t[int]`, `t`, `generic_t2.t[P interface{}]`}, {genericPkg + `t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `generic_t3.t[P, Q interface{}]`}, diff --git a/src/go/types/object.go b/src/go/types/object.go index 9309a529c4..cf05384a87 100644 --- a/src/go/types/object.go +++ b/src/go/types/object.go @@ -482,6 +482,14 @@ func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) { } } + // Special handling for any: because WriteType will format 'any' as 'any', + // resulting in the object string `type any = any` rather than `type any = + // interface{}`. To avoid this, swap in a different empty interface. + if obj == universeAny { + assert(Identical(typ, &emptyInterface)) + typ = &emptyInterface + } + buf.WriteByte(' ') WriteType(buf, typ, qf) } diff --git a/src/go/types/object_test.go b/src/go/types/object_test.go index 46b92a4006..47c7fcd349 100644 --- a/src/go/types/object_test.go +++ b/src/go/types/object_test.go @@ -104,8 +104,8 @@ var testObjects = []struct { {"type t struct{f int}", "t", "type p.t struct{f int}"}, {"type t func(int)", "t", "type p.t func(int)"}, - {"type t[P any] struct{f P}", "t", "type p.t[P interface{}] struct{f P}"}, - {"type t[P any] struct{f P}", "t.P", "type parameter P interface{}"}, + {"type t[P any] struct{f P}", "t", "type p.t[P any] struct{f P}"}, + {"type t[P any] struct{f P}", "t.P", "type parameter P any"}, {"type C interface{m()}; type t[P C] struct{}", "t.P", "type parameter P p.C"}, {"type t = struct{f int}", "t", "type p.t = struct{f int}"}, @@ -114,8 +114,9 @@ var testObjects = []struct { {"var v int", "v", "var p.v int"}, {"func f(int) string", "f", "func p.f(int) string"}, - {"func g[P any](x P){}", "g", "func p.g[P interface{}](x P)"}, + {"func g[P any](x P){}", "g", "func p.g[P any](x P)"}, {"func g[P interface{~int}](x P){}", "g.P", "type parameter P interface{~int}"}, + {"", "any", "type any = interface{}"}, } func TestObjectString(t *testing.T) { @@ -134,7 +135,7 @@ func TestObjectString(t *testing.T) { t.Errorf("%s: invalid object path %s", test.src, test.obj) continue } - obj := pkg.Scope().Lookup(names[0]) + _, obj := pkg.Scope().LookupParent(names[0], token.NoPos) if obj == nil { t.Errorf("%s: %s not found", test.src, names[0]) continue diff --git a/src/go/types/testdata/fixedbugs/issue48008.go2 b/src/go/types/testdata/fixedbugs/issue48008.go2 index 5c9726875c..6c14c78e4c 100644 --- a/src/go/types/testdata/fixedbugs/issue48008.go2 +++ b/src/go/types/testdata/fixedbugs/issue48008.go2 @@ -21,7 +21,7 @@ func _(x interface{}) { case map[T[int]] string: case chan T[int]: - case T /* ERROR cannot use generic type T\[P interface{}\] without instantiation */ : + case T /* ERROR cannot use generic type T\[P any\] without instantiation */ : case []T /* ERROR cannot use generic type */ : case [10]T /* ERROR cannot use generic type */ : case struct{T /* ERROR cannot use generic type */ }: diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index f33175f97e..cf86f9f720 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -202,6 +202,13 @@ func (w *typeWriter) typ(typ Type) { } case *Interface: + if t == universeAny.Type() && w.ctxt == nil { + // When not hashing, we can try to improve type strings by writing "any" + // for a type that is pointer-identical to universeAny. This logic should + // be deprecated by more robust handling for aliases. + w.string("any") + break + } if t.implicit { if len(t.methods) == 0 && len(t.embeddeds) == 1 { w.typ(t.embeddeds[0]) diff --git a/src/go/types/universe.go b/src/go/types/universe.go index 519cf0b707..e30ab12bc3 100644 --- a/src/go/types/universe.go +++ b/src/go/types/universe.go @@ -80,7 +80,10 @@ func defPredeclaredTypes() { } // type any = interface{} - def(NewTypeName(token.NoPos, nil, "any", &emptyInterface)) + // Note: don't use &emptyInterface for the type of any. Using a unique + // pointer allows us to detect any and format it as "any" rather than + // interface{}, which clarifies user-facing error messages significantly. + def(NewTypeName(token.NoPos, nil, "any", &Interface{complete: true, tset: &topTypeSet})) // type error interface{ Error() string } { -- GitLab From 29ec902efc0ae53c4435097efdb738667466756c Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Tue, 16 Nov 2021 11:46:42 -0500 Subject: [PATCH 2209/2500] runtime: get tracking time only when needed casgstatus currently calls nanotime on every casgstatus when tracking, even though the time is only used in some cases. For goroutines making lots of transitions that aren't covered here, this can add a small overhead. Switch to calling nanotime only when necessary. Change-Id: I2617869332e8289ef33dd674d786e44dea09aaba Reviewed-on: https://go-review.googlesource.com/c/go/+/364375 Trust: Michael Pratt Run-TryBot: Michael Pratt Reviewed-by: Michael Knyszek TryBot-Result: Go Bot --- src/runtime/proc.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index bf5fa8e4fc..a238ea77f3 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -980,17 +980,18 @@ func casgstatus(gp *g, oldval, newval uint32) { gp.trackingSeq++ } if gp.tracking { - now := nanotime() if oldval == _Grunnable { // We transitioned out of runnable, so measure how much // time we spent in this state and add it to // runnableTime. + now := nanotime() gp.runnableTime += now - gp.runnableStamp gp.runnableStamp = 0 } if newval == _Grunnable { // We just transitioned into runnable, so record what // time that happened. + now := nanotime() gp.runnableStamp = now } else if newval == _Grunning { // We're transitioning into running, so turn off -- GitLab From 40effca7a13d11f3549a24a5d4b02e87c12fc6bb Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Mon, 15 Nov 2021 16:19:29 -0500 Subject: [PATCH 2210/2500] cmd: pull in golang.org/x/mod@3a5865c This change updates the cmd module's requirement on x/mod and vendors in the changes. This pulls in the following changes into our vendored copy of x/mod: golang.org/cl/351319: module: accept trailing slash in MatchPrefixPattern golang.org/cl/353749: semver: remove unused err field golang.org/cl/355630: x/mod: update requirement on x/crypto golang.org/cl/359412: modfile: rename directory directive to use Changes have been made in cmd/go renaming all uses of directory to use and fixing references to functions in x/mod/modfile to account for the changes in the last of thse CLs. For #45713 Change-Id: I9121d08f6e6b11838bca50e6cbd756baeeae867b Reviewed-on: https://go-review.googlesource.com/c/go/+/364114 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 +- src/cmd/go/alldocs.go | 8 +-- src/cmd/go/internal/modload/init.go | 8 +-- src/cmd/go/internal/workcmd/edit.go | 40 +++++++------- src/cmd/go/internal/workcmd/use.go | 6 +-- src/cmd/go/testdata/script/work.txt | 10 ++-- src/cmd/go/testdata/script/work_edit.txt | 52 +++++++++---------- src/cmd/go/testdata/script/work_env.txt | 2 +- src/cmd/go/testdata/script/work_prune.txt | 2 +- src/cmd/go/testdata/script/work_replace.txt | 2 +- .../testdata/script/work_replace_conflict.txt | 4 +- .../script/work_replace_conflict_override.txt | 4 +- src/cmd/go/testdata/script/work_sum.txt | 2 +- .../go/testdata/script/work_sum_mismatch.txt | 4 +- src/cmd/go/testdata/script/work_sync.txt | 2 +- .../work_sync_irrelevant_dependency.txt | 2 +- .../script/work_sync_relevant_dependency.txt | 2 +- src/cmd/go/testdata/script/work_use.txt | 6 +-- .../script/work_why_download_graph.txt | 2 +- .../vendor/golang.org/x/mod/modfile/rule.go | 4 +- .../vendor/golang.org/x/mod/modfile/work.go | 50 +++++++++--------- .../vendor/golang.org/x/mod/module/module.go | 2 + .../vendor/golang.org/x/mod/semver/semver.go | 10 ---- src/cmd/vendor/modules.txt | 2 +- 25 files changed, 112 insertions(+), 120 deletions(-) diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 014c854a73..75a93e6bd1 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/google/pprof v0.0.0-20211104044539-f987b9c94b31 golang.org/x/arch v0.0.0-20210923205945-b76863e36670 - golang.org/x/mod v0.6.0-dev.0.20210913215816-37dd6891021a + golang.org/x/mod v0.6.0-dev.0.20211102181907-3a5865c02020 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 golang.org/x/tools v0.1.8-0.20211116011028-4adea5033c5c diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 4f50e7c6c8..62619b8d01 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -9,8 +9,8 @@ golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VA golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa h1:idItI2DDfCokpg0N51B2VtiLdJ4vAuXC9fnCb2gACo4= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/mod v0.6.0-dev.0.20210913215816-37dd6891021a h1:gAiIC0JKDJwXAQFyqEYxROcAzeeh5ZTwWjKORCFuQxs= -golang.org/x/mod v0.6.0-dev.0.20210913215816-37dd6891021a/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20211102181907-3a5865c02020 h1:HjtpZuJcnSa+yHlL4Y5aypjDvbHkJne5FS8JRmKI2+I= +golang.org/x/mod v0.6.0-dev.0.20211102181907-3a5865c02020/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index a53ff7c66d..6805d56e2c 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -1411,8 +1411,8 @@ // rewrite the go.mod file. The only time this flag is needed is if no other // flags are specified, as in 'go mod editwork -fmt'. // -// The -directory=path and -dropdirectory=path flags -// add and drop a directory from the go.work files set of module directories. +// The -use=path and -dropuse=path flags +// add and drop a use directive from the go.work file's set of module directories. // // The -replace=old[@v]=new[@v] flag adds a replacement of the given // module path and version pair. If the @v in old@v is omitted, a @@ -1426,7 +1426,7 @@ // module path and version pair. If the @v is omitted, a replacement without // a version on the left side is dropped. // -// The -directory, -dropdirectory, -replace, and -dropreplace, +// The -use, -dropuse, -replace, and -dropreplace, // editing flags may be repeated, and the changes are applied in the order given. // // The -go=version flag sets the expected Go language version. @@ -1448,7 +1448,7 @@ // Replace []Replace // } // -// type Directory struct { +// type Use struct { // Path string // ModulePath string // } diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index ab899fac1e..8bb3875e37 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -565,7 +565,7 @@ func loadWorkFile(path string) (goVersion string, modRoots []string, replaces [] goVersion = wf.Go.Version } seen := map[string]bool{} - for _, d := range wf.Directory { + for _, d := range wf.Use { modRoot := d.Path if !filepath.IsAbs(modRoot) { modRoot = filepath.Join(workDir, modRoot) @@ -606,7 +606,7 @@ func WriteWorkFile(path string, wf *modfile.WorkFile) error { func UpdateWorkFile(wf *modfile.WorkFile) { missingModulePaths := map[string]string{} // module directory listed in file -> abspath modroot - for _, d := range wf.Directory { + for _, d := range wf.Use { modRoot := d.Path if d.ModulePath == "" { missingModulePaths[d.Path] = modRoot @@ -620,7 +620,7 @@ func UpdateWorkFile(wf *modfile.WorkFile) { if err != nil { continue // Error will be reported if modules are loaded. } - wf.AddDirectory(moddir, f.Module.Mod.Path) + wf.AddUse(moddir, f.Module.Mod.Path) } } @@ -887,7 +887,7 @@ func CreateWorkFile(ctx context.Context, workFile string, modDirs []string) { } base.Fatalf("go: error parsing go.mod in directory %s: %v", dir, err) } - workF.AddDirectory(ToDirectoryPath(dir), f.Module.Mod.Path) + workF.AddUse(ToDirectoryPath(dir), f.Module.Mod.Path) } UpdateWorkFile(workF) diff --git a/src/cmd/go/internal/workcmd/edit.go b/src/cmd/go/internal/workcmd/edit.go index 5158ac9b49..03a27f2bc6 100644 --- a/src/cmd/go/internal/workcmd/edit.go +++ b/src/cmd/go/internal/workcmd/edit.go @@ -37,8 +37,8 @@ This reformatting is also implied by any other modifications that use or rewrite the go.mod file. The only time this flag is needed is if no other flags are specified, as in 'go mod editwork -fmt'. -The -directory=path and -dropdirectory=path flags -add and drop a directory from the go.work files set of module directories. +The -use=path and -dropuse=path flags +add and drop a use directive from the go.work file's set of module directories. The -replace=old[@v]=new[@v] flag adds a replacement of the given module path and version pair. If the @v in old@v is omitted, a @@ -52,7 +52,7 @@ The -dropreplace=old[@v] flag drops a replacement of the given module path and version pair. If the @v is omitted, a replacement without a version on the left side is dropped. -The -directory, -dropdirectory, -replace, and -dropreplace, +The -use, -dropuse, -replace, and -dropreplace, editing flags may be repeated, and the changes are applied in the order given. The -go=version flag sets the expected Go language version. @@ -74,7 +74,7 @@ writing it back to go.mod. The JSON output corresponds to these Go types: Replace []Replace } - type Directory struct { + type Use struct { Path string ModulePath string } @@ -106,8 +106,8 @@ func (f flagFunc) Set(s string) error { f(s); return nil } func init() { cmdEdit.Run = runEditwork // break init cycle - cmdEdit.Flag.Var(flagFunc(flagEditworkDirectory), "directory", "") - cmdEdit.Flag.Var(flagFunc(flagEditworkDropDirectory), "dropdirectory", "") + cmdEdit.Flag.Var(flagFunc(flagEditworkUse), "use", "") + cmdEdit.Flag.Var(flagFunc(flagEditworkDropUse), "dropuse", "") cmdEdit.Flag.Var(flagFunc(flagEditworkReplace), "replace", "") cmdEdit.Flag.Var(flagFunc(flagEditworkDropReplace), "dropreplace", "") @@ -182,25 +182,25 @@ func runEditwork(ctx context.Context, cmd *base.Command, args []string) { modload.WriteWorkFile(gowork, workFile) } -// flagEditworkDirectory implements the -directory flag. -func flagEditworkDirectory(arg string) { +// flagEditworkUse implements the -use flag. +func flagEditworkUse(arg string) { workedits = append(workedits, func(f *modfile.WorkFile) { _, mf, err := modload.ReadModFile(filepath.Join(arg, "go.mod"), nil) modulePath := "" if err == nil { modulePath = mf.Module.Mod.Path } - f.AddDirectory(modload.ToDirectoryPath(arg), modulePath) - if err := f.AddDirectory(modload.ToDirectoryPath(arg), ""); err != nil { - base.Fatalf("go: -directory=%s: %v", arg, err) + f.AddUse(modload.ToDirectoryPath(arg), modulePath) + if err := f.AddUse(modload.ToDirectoryPath(arg), ""); err != nil { + base.Fatalf("go: -use=%s: %v", arg, err) } }) } -// flagEditworkDropDirectory implements the -dropdirectory flag. -func flagEditworkDropDirectory(arg string) { +// flagEditworkDropUse implements the -dropuse flag. +func flagEditworkDropUse(arg string) { workedits = append(workedits, func(f *modfile.WorkFile) { - if err := f.DropDirectory(modload.ToDirectoryPath(arg)); err != nil { + if err := f.DropUse(modload.ToDirectoryPath(arg)); err != nil { base.Fatalf("go: -dropdirectory=%s: %v", arg, err) } }) @@ -287,8 +287,8 @@ func editPrintJSON(workFile *modfile.WorkFile) { if workFile.Go != nil { f.Go = workFile.Go.Version } - for _, d := range workFile.Directory { - f.Directory = append(f.Directory, directoryJSON{DiskPath: d.Path, ModPath: d.ModulePath}) + for _, d := range workFile.Use { + f.Use = append(f.Use, useJSON{DiskPath: d.Path, ModPath: d.ModulePath}) } for _, r := range workFile.Replace { @@ -304,12 +304,12 @@ func editPrintJSON(workFile *modfile.WorkFile) { // workfileJSON is the -json output data structure. type workfileJSON struct { - Go string `json:",omitempty"` - Directory []directoryJSON - Replace []replaceJSON + Go string `json:",omitempty"` + Use []useJSON + Replace []replaceJSON } -type directoryJSON struct { +type useJSON struct { DiskPath string ModPath string `json:",omitempty"` } diff --git a/src/cmd/go/internal/workcmd/use.go b/src/cmd/go/internal/workcmd/use.go index b2218280e4..97c493685a 100644 --- a/src/cmd/go/internal/workcmd/use.go +++ b/src/cmd/go/internal/workcmd/use.go @@ -53,7 +53,7 @@ func runUse(ctx context.Context, cmd *base.Command, args []string) { } haveDirs := make(map[string]bool) - for _, dir := range workFile.Directory { + for _, dir := range workFile.Use { haveDirs[filepath.Join(filepath.Dir(gowork), filepath.FromSlash(dir.Path))] = true } @@ -105,10 +105,10 @@ func runUse(ctx context.Context, cmd *base.Command, args []string) { } for dir := range removeDirs { - workFile.DropDirectory(filepath.ToSlash(dir)) + workFile.DropUse(filepath.ToSlash(dir)) } for dir := range addDirs { - workFile.AddDirectory(filepath.ToSlash(dir), "") + workFile.AddUse(filepath.ToSlash(dir), "") } modload.UpdateWorkFile(workFile) modload.WriteWorkFile(gowork, workFile) diff --git a/src/cmd/go/testdata/script/work.txt b/src/cmd/go/testdata/script/work.txt index 68bd3ea08b..cbb3746a69 100644 --- a/src/cmd/go/testdata/script/work.txt +++ b/src/cmd/go/testdata/script/work.txt @@ -34,7 +34,7 @@ go list -mod=readonly all stderr '^go: -mod may only be set to readonly when in workspace mode' go list -mod=mod -workfile=off all -# Test that duplicates in the directory list return an error +# Test that duplicates in the use list return an error cp go.work go.work.backup cp go.work.dup go.work ! go run example.com/b @@ -59,7 +59,7 @@ go build -n -o foo foo.go -- go.work.dup -- go 1.18 -directory ( +use ( a b ../src/a @@ -67,14 +67,14 @@ directory ( -- go.work.want -- go 1.18 -directory ( +use ( ./a ./b ) -- go.work.d -- go 1.18 -directory ( +use ( a b d @@ -133,7 +133,7 @@ func main() { -- go.work.backwards -- go 1.18 -directory ( +use ( d b a diff --git a/src/cmd/go/testdata/script/work_edit.txt b/src/cmd/go/testdata/script/work_edit.txt index 060d1f0386..fd04bbda6e 100644 --- a/src/cmd/go/testdata/script/work_edit.txt +++ b/src/cmd/go/testdata/script/work_edit.txt @@ -3,31 +3,31 @@ go work init m cmp go.work go.work.want_initial -go work edit -directory n -cmp go.work go.work.want_directory_n +go work edit -use n +cmp go.work go.work.want_use_n go work edit -go 1.18 cmp go.work go.work.want_go_118 -go work edit -dropdirectory m -cmp go.work go.work.want_dropdirectory_m +go work edit -dropuse m +cmp go.work go.work.want_dropuse_m go work edit -replace=x.1@v1.3.0=y.1@v1.4.0 -replace='x.1@v1.4.0 = ../z' cmp go.work go.work.want_add_replaces -go work edit -directory n -directory ../a -directory /b -directory c -directory c -cmp go.work go.work.want_multidirectory +go work edit -use n -use ../a -use /b -use c -use c +cmp go.work go.work.want_multiuse -go work edit -dropdirectory /b -dropdirectory n -cmp go.work go.work.want_multidropdirectory +go work edit -dropuse /b -dropuse n +cmp go.work go.work.want_multidropuse go work edit -dropreplace='x.1@v1.4.0' cmp go.work go.work.want_dropreplace -go work edit -print -go 1.19 -directory b -dropdirectory c -replace 'x.1@v1.4.0 = ../z' -dropreplace x.1 -dropreplace x.1@v1.3.0 +go work edit -print -go 1.19 -use b -dropuse c -replace 'x.1@v1.4.0 = ../z' -dropreplace x.1 -dropreplace x.1@v1.3.0 cmp stdout go.work.want_print -go work edit -json -go 1.19 -directory b -dropdirectory c -replace 'x.1@v1.4.0 = ../z' -dropreplace x.1 -dropreplace x.1@v1.3.0 +go work edit -json -go 1.19 -use b -dropuse c -replace 'x.1@v1.4.0 = ../z' -dropreplace x.1 -dropreplace x.1@v1.3.0 cmp stdout go.work.want_json go work edit -print -fmt -workfile $GOPATH/src/unformatted @@ -40,38 +40,38 @@ go 1.18 -- go.work.want_initial -- go 1.18 -directory ./m --- go.work.want_directory_n -- +use ./m +-- go.work.want_use_n -- go 1.18 -directory ( +use ( ./m ./n ) -- go.work.want_go_118 -- go 1.18 -directory ( +use ( ./m ./n ) --- go.work.want_dropdirectory_m -- +-- go.work.want_dropuse_m -- go 1.18 -directory ./n +use ./n -- go.work.want_add_replaces -- go 1.18 -directory ./n +use ./n replace ( x.1 v1.3.0 => y.1 v1.4.0 x.1 v1.4.0 => ../z ) --- go.work.want_multidirectory -- +-- go.work.want_multiuse -- go 1.18 -directory ( +use ( ../a ./c ./n @@ -82,10 +82,10 @@ replace ( x.1 v1.3.0 => y.1 v1.4.0 x.1 v1.4.0 => ../z ) --- go.work.want_multidropdirectory -- +-- go.work.want_multidropuse -- go 1.18 -directory ( +use ( ../a ./c ) @@ -97,7 +97,7 @@ replace ( -- go.work.want_dropreplace -- go 1.18 -directory ( +use ( ../a ./c ) @@ -106,7 +106,7 @@ replace x.1 v1.3.0 => y.1 v1.4.0 -- go.work.want_print -- go 1.19 -directory ( +use ( ../a ./b ) @@ -115,7 +115,7 @@ replace x.1 v1.4.0 => ../z -- go.work.want_json -- { "Go": "1.19", - "Directory": [ + "Use": [ { "DiskPath": "../a" }, @@ -137,7 +137,7 @@ replace x.1 v1.4.0 => ../z } -- unformatted -- go 1.18 - directory ( + use ( a b c @@ -149,7 +149,7 @@ go 1.18 -- formatted -- go 1.18 -directory ( +use ( a b c diff --git a/src/cmd/go/testdata/script/work_env.txt b/src/cmd/go/testdata/script/work_env.txt index de67255696..ec3d3be3ed 100644 --- a/src/cmd/go/testdata/script/work_env.txt +++ b/src/cmd/go/testdata/script/work_env.txt @@ -19,6 +19,6 @@ stderr '^go: GOWORK cannot be modified$' -- go.work -- go 1.18 -directory a +use a -- a/go.mod -- module example.com/a diff --git a/src/cmd/go/testdata/script/work_prune.txt b/src/cmd/go/testdata/script/work_prune.txt index 00c3e10663..7e2ae4e6ce 100644 --- a/src/cmd/go/testdata/script/work_prune.txt +++ b/src/cmd/go/testdata/script/work_prune.txt @@ -19,7 +19,7 @@ stdout '^v1.1.0$' -- go.work -- go 1.18 -directory ( +use ( ./a ./p ) diff --git a/src/cmd/go/testdata/script/work_replace.txt b/src/cmd/go/testdata/script/work_replace.txt index 5a4cb0eebb..81268e5069 100644 --- a/src/cmd/go/testdata/script/work_replace.txt +++ b/src/cmd/go/testdata/script/work_replace.txt @@ -10,7 +10,7 @@ go list -m example.com/other stdout 'example.com/other v1.0.0 => ./other2' -- go.work -- -directory m +use m replace example.com/dep => ./dep replace example.com/other => ./other2 diff --git a/src/cmd/go/testdata/script/work_replace_conflict.txt b/src/cmd/go/testdata/script/work_replace_conflict.txt index f91b63cd86..e5677b21d7 100644 --- a/src/cmd/go/testdata/script/work_replace_conflict.txt +++ b/src/cmd/go/testdata/script/work_replace_conflict.txt @@ -9,8 +9,8 @@ stdout 'example.com/dep v1.0.0 => ./dep1' -- foo -- -- go.work -- -directory m -directory n +use m +use n -- m/go.mod -- module example.com/m diff --git a/src/cmd/go/testdata/script/work_replace_conflict_override.txt b/src/cmd/go/testdata/script/work_replace_conflict_override.txt index ebb517dd7c..c62084bee6 100644 --- a/src/cmd/go/testdata/script/work_replace_conflict_override.txt +++ b/src/cmd/go/testdata/script/work_replace_conflict_override.txt @@ -5,8 +5,8 @@ go list -m example.com/dep stdout 'example.com/dep v1.0.0 => ./dep3' -- go.work -- -directory m -directory n +use m +use n replace example.com/dep => ./dep3 -- m/go.mod -- module example.com/m diff --git a/src/cmd/go/testdata/script/work_sum.txt b/src/cmd/go/testdata/script/work_sum.txt index 20261e7cbd..19dbb90507 100644 --- a/src/cmd/go/testdata/script/work_sum.txt +++ b/src/cmd/go/testdata/script/work_sum.txt @@ -11,7 +11,7 @@ rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= -- go.work -- go 1.18 -directory . +use . -- go.mod -- go 1.18 diff --git a/src/cmd/go/testdata/script/work_sum_mismatch.txt b/src/cmd/go/testdata/script/work_sum_mismatch.txt index 42994ea5d5..9e9474304e 100644 --- a/src/cmd/go/testdata/script/work_sum_mismatch.txt +++ b/src/cmd/go/testdata/script/work_sum_mismatch.txt @@ -17,8 +17,8 @@ For more information, see 'go help module-auth'. -- go.work -- go 1.18 -directory ./a -directory ./b +use ./a +use ./b -- a/go.mod -- go 1.18 diff --git a/src/cmd/go/testdata/script/work_sync.txt b/src/cmd/go/testdata/script/work_sync.txt index 16ad8c8cfa..69167d4cc1 100644 --- a/src/cmd/go/testdata/script/work_sync.txt +++ b/src/cmd/go/testdata/script/work_sync.txt @@ -5,7 +5,7 @@ cmp b/go.mod b/want_go.mod -- go.work -- go 1.18 -directory ( +use ( ./a ./b ) diff --git a/src/cmd/go/testdata/script/work_sync_irrelevant_dependency.txt b/src/cmd/go/testdata/script/work_sync_irrelevant_dependency.txt index bbb8579b4f..072323d15d 100644 --- a/src/cmd/go/testdata/script/work_sync_irrelevant_dependency.txt +++ b/src/cmd/go/testdata/script/work_sync_irrelevant_dependency.txt @@ -11,7 +11,7 @@ cmp b/go.mod b/want_go.mod -- go.work -- go 1.18 -directory ( +use ( ./a ./b ) diff --git a/src/cmd/go/testdata/script/work_sync_relevant_dependency.txt b/src/cmd/go/testdata/script/work_sync_relevant_dependency.txt index e95ac26707..d7997027d9 100644 --- a/src/cmd/go/testdata/script/work_sync_relevant_dependency.txt +++ b/src/cmd/go/testdata/script/work_sync_relevant_dependency.txt @@ -11,7 +11,7 @@ cmp b/go.mod b/want_go.mod -- go.work -- go 1.18 -directory ( +use ( ./a ./b ) diff --git a/src/cmd/go/testdata/script/work_use.txt b/src/cmd/go/testdata/script/work_use.txt index dddce0fe22..f5ea89c900 100644 --- a/src/cmd/go/testdata/script/work_use.txt +++ b/src/cmd/go/testdata/script/work_use.txt @@ -6,21 +6,21 @@ cmp go.work go.want_work_other -- go.work -- go 1.18 -directory ( +use ( foo foo/bar // doesn't exist ) -- go.want_work_r -- go 1.18 -directory ( +use ( foo foo/bar/baz ) -- go.want_work_other -- go 1.18 -directory ( +use ( foo foo/bar/baz other diff --git a/src/cmd/go/testdata/script/work_why_download_graph.txt b/src/cmd/go/testdata/script/work_why_download_graph.txt index c03b4a7a62..7964c914a2 100644 --- a/src/cmd/go/testdata/script/work_why_download_graph.txt +++ b/src/cmd/go/testdata/script/work_why_download_graph.txt @@ -24,7 +24,7 @@ stdout 'example.com/a rsc.io/quote@v1.5.2\nexample.com/b example.com/c@v1.0.0\nr -- go.work -- go 1.18 -directory ( +use ( ./a ./b ) diff --git a/src/cmd/vendor/golang.org/x/mod/modfile/rule.go b/src/cmd/vendor/golang.org/x/mod/modfile/rule.go index 98211a450a..ed2f31aa70 100644 --- a/src/cmd/vendor/golang.org/x/mod/modfile/rule.go +++ b/src/cmd/vendor/golang.org/x/mod/modfile/rule.go @@ -609,7 +609,7 @@ func (f *WorkFile) add(errs *ErrorList, line *Line, verb string, args []string, f.Go = &Go{Syntax: line} f.Go.Version = args[0] - case "directory": + case "use": if len(args) != 1 { errorf("usage: %s local/dir", verb) return @@ -619,7 +619,7 @@ func (f *WorkFile) add(errs *ErrorList, line *Line, verb string, args []string, errorf("invalid quoted string: %v", err) return } - f.Directory = append(f.Directory, &Directory{ + f.Use = append(f.Use, &Use{ Path: s, Syntax: line, }) diff --git a/src/cmd/vendor/golang.org/x/mod/modfile/work.go b/src/cmd/vendor/golang.org/x/mod/modfile/work.go index b1fabff51b..0c0e521525 100644 --- a/src/cmd/vendor/golang.org/x/mod/modfile/work.go +++ b/src/cmd/vendor/golang.org/x/mod/modfile/work.go @@ -12,16 +12,16 @@ import ( // A WorkFile is the parsed, interpreted form of a go.work file. type WorkFile struct { - Go *Go - Directory []*Directory - Replace []*Replace + Go *Go + Use []*Use + Replace []*Replace Syntax *FileSyntax } -// A Directory is a single directory statement. -type Directory struct { - Path string // Directory path of module. +// A Use is a single directory statement. +type Use struct { + Path string // Use path of module. ModulePath string // Module path in the comment. Syntax *Line } @@ -67,7 +67,7 @@ func ParseWork(file string, data []byte, fix VersionFixer) (*WorkFile, error) { Err: fmt.Errorf("unknown block type: %s", strings.Join(x.Token, " ")), }) continue - case "directory", "replace": + case "use", "replace": for _, l := range x.Line { f.add(&errs, l, x.Token[0], l.Token, fix) } @@ -87,13 +87,13 @@ func ParseWork(file string, data []byte, fix VersionFixer) (*WorkFile, error) { // Cleanup cleans out all the cleared entries. func (f *WorkFile) Cleanup() { w := 0 - for _, r := range f.Directory { + for _, r := range f.Use { if r.Path != "" { - f.Directory[w] = r + f.Use[w] = r w++ } } - f.Directory = f.Directory[:w] + f.Use = f.Use[:w] w = 0 for _, r := range f.Replace { @@ -133,60 +133,60 @@ func (f *WorkFile) AddGoStmt(version string) error { return nil } -func (f *WorkFile) AddDirectory(diskPath, modulePath string) error { +func (f *WorkFile) AddUse(diskPath, modulePath string) error { need := true - for _, d := range f.Directory { + for _, d := range f.Use { if d.Path == diskPath { if need { d.ModulePath = modulePath - f.Syntax.updateLine(d.Syntax, "directory", AutoQuote(diskPath)) + f.Syntax.updateLine(d.Syntax, "use", AutoQuote(diskPath)) need = false } else { d.Syntax.markRemoved() - *d = Directory{} + *d = Use{} } } } if need { - f.AddNewDirectory(diskPath, modulePath) + f.AddNewUse(diskPath, modulePath) } return nil } -func (f *WorkFile) AddNewDirectory(diskPath, modulePath string) { - line := f.Syntax.addLine(nil, "directory", AutoQuote(diskPath)) - f.Directory = append(f.Directory, &Directory{Path: diskPath, ModulePath: modulePath, Syntax: line}) +func (f *WorkFile) AddNewUse(diskPath, modulePath string) { + line := f.Syntax.addLine(nil, "use", AutoQuote(diskPath)) + f.Use = append(f.Use, &Use{Path: diskPath, ModulePath: modulePath, Syntax: line}) } -func (f *WorkFile) SetDirectory(dirs []*Directory) { +func (f *WorkFile) SetUse(dirs []*Use) { need := make(map[string]string) for _, d := range dirs { need[d.Path] = d.ModulePath } - for _, d := range f.Directory { + for _, d := range f.Use { if modulePath, ok := need[d.Path]; ok { d.ModulePath = modulePath } else { d.Syntax.markRemoved() - *d = Directory{} + *d = Use{} } } // TODO(#45713): Add module path to comment. for diskPath, modulePath := range need { - f.AddNewDirectory(diskPath, modulePath) + f.AddNewUse(diskPath, modulePath) } f.SortBlocks() } -func (f *WorkFile) DropDirectory(path string) error { - for _, d := range f.Directory { +func (f *WorkFile) DropUse(path string) error { + for _, d := range f.Use { if d.Path == path { d.Syntax.markRemoved() - *d = Directory{} + *d = Use{} } } return nil diff --git a/src/cmd/vendor/golang.org/x/mod/module/module.go b/src/cmd/vendor/golang.org/x/mod/module/module.go index 89bd3ede27..355b5a4568 100644 --- a/src/cmd/vendor/golang.org/x/mod/module/module.go +++ b/src/cmd/vendor/golang.org/x/mod/module/module.go @@ -798,6 +798,7 @@ func unescapeString(escaped string) (string, bool) { // GOPRIVATE environment variable, as described by 'go help module-private'. // // It ignores any empty or malformed patterns in the list. +// Trailing slashes on patterns are ignored. func MatchPrefixPatterns(globs, target string) bool { for globs != "" { // Extract next non-empty glob in comma-separated list. @@ -807,6 +808,7 @@ func MatchPrefixPatterns(globs, target string) bool { } else { glob, globs = globs, "" } + glob = strings.TrimSuffix(glob, "/") if glob == "" { continue } diff --git a/src/cmd/vendor/golang.org/x/mod/semver/semver.go b/src/cmd/vendor/golang.org/x/mod/semver/semver.go index 7be398f80d..a30a22bf20 100644 --- a/src/cmd/vendor/golang.org/x/mod/semver/semver.go +++ b/src/cmd/vendor/golang.org/x/mod/semver/semver.go @@ -32,7 +32,6 @@ type parsed struct { short string prerelease string build string - err string } // IsValid reports whether v is a valid semantic version string. @@ -172,12 +171,10 @@ func Sort(list []string) { func parse(v string) (p parsed, ok bool) { if v == "" || v[0] != 'v' { - p.err = "missing v prefix" return } p.major, v, ok = parseInt(v[1:]) if !ok { - p.err = "bad major version" return } if v == "" { @@ -187,13 +184,11 @@ func parse(v string) (p parsed, ok bool) { return } if v[0] != '.' { - p.err = "bad minor prefix" ok = false return } p.minor, v, ok = parseInt(v[1:]) if !ok { - p.err = "bad minor version" return } if v == "" { @@ -202,31 +197,26 @@ func parse(v string) (p parsed, ok bool) { return } if v[0] != '.' { - p.err = "bad patch prefix" ok = false return } p.patch, v, ok = parseInt(v[1:]) if !ok { - p.err = "bad patch version" return } if len(v) > 0 && v[0] == '-' { p.prerelease, v, ok = parsePrerelease(v) if !ok { - p.err = "bad prerelease" return } } if len(v) > 0 && v[0] == '+' { p.build, v, ok = parseBuild(v) if !ok { - p.err = "bad build" return } } if v != "" { - p.err = "junk on end" ok = false return } diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 82e04c1d33..fd955a6932 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -28,7 +28,7 @@ golang.org/x/arch/x86/x86asm ## explicit; go 1.17 golang.org/x/crypto/ed25519 golang.org/x/crypto/ed25519/internal/edwards25519 -# golang.org/x/mod v0.6.0-dev.0.20210913215816-37dd6891021a +# golang.org/x/mod v0.6.0-dev.0.20211102181907-3a5865c02020 ## explicit; go 1.17 golang.org/x/mod/internal/lazyregexp golang.org/x/mod/modfile -- GitLab From 6c36c332fefdd433cfe6e6468a2542fc310e9f8a Mon Sep 17 00:00:00 2001 From: Alessandro Arzilli Date: Mon, 15 Nov 2021 10:14:04 +0100 Subject: [PATCH 2211/2500] debug/pe,debug/macho: add support for DWARF5 sections Adds the same logic used in debug/elf to load DWARF5 sections. Fixes #49590 Change-Id: Iee05b9927a6f521842b330eab8942ade3fc2bd86 Reviewed-on: https://go-review.googlesource.com/c/go/+/363895 Reviewed-by: Ian Lance Taylor Trust: Than McIntosh --- src/debug/macho/file.go | 14 +++++++++++--- src/debug/pe/file.go | 14 +++++++++++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/debug/macho/file.go b/src/debug/macho/file.go index 73cfce3c76..cdc500e476 100644 --- a/src/debug/macho/file.go +++ b/src/debug/macho/file.go @@ -650,10 +650,14 @@ func (f *File) DWARF() (*dwarf.Data, error) { return nil, err } - // Look for DWARF4 .debug_types sections. + // Look for DWARF4 .debug_types sections and DWARF5 sections. for i, s := range f.Sections { suffix := dwarfSuffix(s) - if suffix != "types" { + if suffix == "" { + continue + } + if _, ok := dat[suffix]; ok { + // Already handled. continue } @@ -662,7 +666,11 @@ func (f *File) DWARF() (*dwarf.Data, error) { return nil, err } - err = d.AddTypes(fmt.Sprintf("types-%d", i), b) + if suffix == "types" { + err = d.AddTypes(fmt.Sprintf("types-%d", i), b) + } else { + err = d.AddSection(".debug_"+suffix, b) + } if err != nil { return nil, err } diff --git a/src/debug/pe/file.go b/src/debug/pe/file.go index e50229e5a3..ab00a48f5c 100644 --- a/src/debug/pe/file.go +++ b/src/debug/pe/file.go @@ -272,10 +272,14 @@ func (f *File) DWARF() (*dwarf.Data, error) { return nil, err } - // Look for DWARF4 .debug_types sections. + // Look for DWARF4 .debug_types sections and DWARF5 sections. for i, s := range f.Sections { suffix := dwarfSuffix(s) - if suffix != "types" { + if suffix == "" { + continue + } + if _, ok := dat[suffix]; ok { + // Already handled. continue } @@ -284,7 +288,11 @@ func (f *File) DWARF() (*dwarf.Data, error) { return nil, err } - err = d.AddTypes(fmt.Sprintf("types-%d", i), b) + if suffix == "types" { + err = d.AddTypes(fmt.Sprintf("types-%d", i), b) + } else { + err = d.AddSection(".debug_"+suffix, b) + } if err != nil { return nil, err } -- GitLab From f6591839727e09cc5cb11d08b333fd2386e8aa1b Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Mon, 15 Nov 2021 13:50:39 -0500 Subject: [PATCH 2212/2500] os/exec: avoid NewFile on unknown FDs exec_test.go's init function uses os.NewFile(fd) + f.Stat as a portable mechanism to determine if an FD is in use. Unfortunately, the current use is racy: if an unused FD becomes used between NewFile and f.Close, then we will unintentionally close an FD we do not use. We cannot simply drop Close, as the finalizer will close the FD. We could hold all of the os.Files in a global for the lifetime of the process, but the need for such a hack is indicative of the larger problem: we should not create an os.File for an FD that we do not own. Instead, the new fdtest.Exists provides a helper that performs the equivalent of fstat(2) on each OS to determine if the FD is valid, without using os.File. We also reuse this helper on a variety of other tests that look at open FDs. Fixes #49533 Change-Id: I36e2bdb15f271ab01e55c18db6564271995a15af Reviewed-on: https://go-review.googlesource.com/c/go/+/364035 Trust: Michael Pratt Run-TryBot: Michael Pratt Reviewed-by: Bryan C. Mills --- src/go/build/deps_test.go | 3 + src/os/exec/exec_test.go | 132 +++--------------- src/os/exec/internal/fdtest/exists_js.go | 18 +++ src/os/exec/internal/fdtest/exists_plan9.go | 20 +++ src/os/exec/internal/fdtest/exists_test.go | 21 +++ src/os/exec/internal/fdtest/exists_unix.go | 19 +++ src/os/exec/internal/fdtest/exists_windows.go | 12 ++ src/os/exec/read3.go | 92 ++++++------ 8 files changed, 154 insertions(+), 163 deletions(-) create mode 100644 src/os/exec/internal/fdtest/exists_js.go create mode 100644 src/os/exec/internal/fdtest/exists_plan9.go create mode 100644 src/os/exec/internal/fdtest/exists_test.go create mode 100644 src/os/exec/internal/fdtest/exists_unix.go create mode 100644 src/os/exec/internal/fdtest/exists_windows.go diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 2f68cbcffc..7f25038d2d 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -545,6 +545,9 @@ var depsRules = ` NET, testing, math/rand < golang.org/x/net/nettest; + syscall + < os/exec/internal/fdtest; + FMT, container/heap, math/rand < internal/trace; ` diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go index 459ba39dff..6172c78dd4 100644 --- a/src/os/exec/exec_test.go +++ b/src/os/exec/exec_test.go @@ -21,7 +21,9 @@ import ( "net/http/httptest" "os" "os/exec" + "os/exec/internal/fdtest" "path/filepath" + "reflect" "runtime" "strconv" "strings" @@ -29,15 +31,10 @@ import ( "time" ) -// haveUnexpectedFDs is set at init time to report whether any -// file descriptors were open at program start. +// haveUnexpectedFDs is set at init time to report whether any file descriptors +// were open at program start. var haveUnexpectedFDs bool -// unfinalizedFiles holds files that should not be finalized, -// because that would close the associated file descriptor, -// which we don't want to do. -var unfinalizedFiles []*os.File - func init() { if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" { return @@ -49,21 +46,10 @@ func init() { if poll.IsPollDescriptor(fd) { continue } - // We have no good portable way to check whether an FD is open. - // We use NewFile to create a *os.File, which lets us - // know whether it is open, but then we have to cope with - // the finalizer on the *os.File. - f := os.NewFile(fd, "") - if _, err := f.Stat(); err != nil { - // Close the file to clear the finalizer. - // We expect the Close to fail. - f.Close() - } else { - fmt.Printf("fd %d open at test start\n", fd) + + if fdtest.Exists(fd) { haveUnexpectedFDs = true - // Use a global variable to avoid running - // the finalizer, which would close the FD. - unfinalizedFiles = append(unfinalizedFiles, f) + return } } } @@ -377,50 +363,21 @@ func TestStdinCloseRace(t *testing.T) { // Issue 5071 func TestPipeLookPathLeak(t *testing.T) { - // If we are reading from /proc/self/fd we (should) get an exact result. - tolerance := 0 - - // Reading /proc/self/fd is more reliable than calling lsof, so try that - // first. - numOpenFDs := func() (int, []byte, error) { - fds, err := os.ReadDir("/proc/self/fd") - if err != nil { - return 0, nil, err - } - return len(fds), nil, nil + if runtime.GOOS == "windows" { + t.Skip("we don't currently suppore counting open handles on windows") } - want, before, err := numOpenFDs() - if err != nil { - // We encountered a problem reading /proc/self/fd (we might be on - // a platform that doesn't have it). Fall back onto lsof. - t.Logf("using lsof because: %v", err) - numOpenFDs = func() (int, []byte, error) { - // Android's stock lsof does not obey the -p option, - // so extra filtering is needed. - // https://golang.org/issue/10206 - if runtime.GOOS == "android" { - // numOpenFDsAndroid handles errors itself and - // might skip or fail the test. - n, lsof := numOpenFDsAndroid(t) - return n, lsof, nil - } - lsof, err := exec.Command("lsof", "-b", "-n", "-p", strconv.Itoa(os.Getpid())).Output() - return bytes.Count(lsof, []byte("\n")), lsof, err - } - // lsof may see file descriptors associated with the fork itself, - // so we allow some extra margin if we have to use it. - // https://golang.org/issue/19243 - tolerance = 5 - - // Retry reading the number of open file descriptors. - want, before, err = numOpenFDs() - if err != nil { - t.Log(err) - t.Skipf("skipping test; error finding or running lsof") + openFDs := func() []uintptr { + var fds []uintptr + for i := uintptr(0); i < 100; i++ { + if fdtest.Exists(i) { + fds = append(fds, i) + } } + return fds } + want := openFDs() for i := 0; i < 6; i++ { cmd := exec.Command("something-that-does-not-exist-executable") cmd.StdoutPipe() @@ -430,59 +387,10 @@ func TestPipeLookPathLeak(t *testing.T) { t.Fatal("unexpected success") } } - got, after, err := numOpenFDs() - if err != nil { - // numOpenFDs has already succeeded once, it should work here. - t.Errorf("unexpected failure: %v", err) - } - if got-want > tolerance { - t.Errorf("number of open file descriptors changed: got %v, want %v", got, want) - if before != nil { - t.Errorf("before:\n%v\n", before) - } - if after != nil { - t.Errorf("after:\n%v\n", after) - } - } -} - -func numOpenFDsAndroid(t *testing.T) (n int, lsof []byte) { - raw, err := exec.Command("lsof").Output() - if err != nil { - t.Skip("skipping test; error finding or running lsof") - } - - // First find the PID column index by parsing the first line, and - // select lines containing pid in the column. - pid := []byte(strconv.Itoa(os.Getpid())) - pidCol := -1 - - s := bufio.NewScanner(bytes.NewReader(raw)) - for s.Scan() { - line := s.Bytes() - fields := bytes.Fields(line) - if pidCol < 0 { - for i, v := range fields { - if bytes.Equal(v, []byte("PID")) { - pidCol = i - break - } - } - lsof = append(lsof, line...) - continue - } - if bytes.Equal(fields[pidCol], pid) { - lsof = append(lsof, '\n') - lsof = append(lsof, line...) - } - } - if pidCol < 0 { - t.Fatal("error processing lsof output: unexpected header format") - } - if err := s.Err(); err != nil { - t.Fatalf("error processing lsof output: %v", err) + got := openFDs() + if !reflect.DeepEqual(got, want) { + t.Errorf("set of open file descriptors changed: got %v, want %v", got, want) } - return bytes.Count(lsof, []byte("\n")), lsof } func TestExtraFilesFDShuffle(t *testing.T) { diff --git a/src/os/exec/internal/fdtest/exists_js.go b/src/os/exec/internal/fdtest/exists_js.go new file mode 100644 index 0000000000..a7ce33c74f --- /dev/null +++ b/src/os/exec/internal/fdtest/exists_js.go @@ -0,0 +1,18 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build js + +package fdtest + +import ( + "syscall" +) + +// Exists returns true if fd is a valid file descriptor. +func Exists(fd uintptr) bool { + var s syscall.Stat_t + err := syscall.Fstat(int(fd), &s) + return err != syscall.EBADF +} diff --git a/src/os/exec/internal/fdtest/exists_plan9.go b/src/os/exec/internal/fdtest/exists_plan9.go new file mode 100644 index 0000000000..8886e06027 --- /dev/null +++ b/src/os/exec/internal/fdtest/exists_plan9.go @@ -0,0 +1,20 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build plan9 + +package fdtest + +import ( + "syscall" +) + +const errBadFd = syscall.ErrorString("fd out of range or not open") + +// Exists returns true if fd is a valid file descriptor. +func Exists(fd uintptr) bool { + var buf [1]byte + _, err := syscall.Fstat(int(fd), buf[:]) + return err != errBadFd +} diff --git a/src/os/exec/internal/fdtest/exists_test.go b/src/os/exec/internal/fdtest/exists_test.go new file mode 100644 index 0000000000..a02dddf7f7 --- /dev/null +++ b/src/os/exec/internal/fdtest/exists_test.go @@ -0,0 +1,21 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fdtest + +import ( + "os" + "runtime" + "testing" +) + +func TestExists(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("Exists not implemented for windows") + } + + if !Exists(os.Stdout.Fd()) { + t.Errorf("Exists(%d) got false want true", os.Stdout.Fd()) + } +} diff --git a/src/os/exec/internal/fdtest/exists_unix.go b/src/os/exec/internal/fdtest/exists_unix.go new file mode 100644 index 0000000000..49f264cebd --- /dev/null +++ b/src/os/exec/internal/fdtest/exists_unix.go @@ -0,0 +1,19 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris + +// Package fdtest provides test helpers for working with file descriptors across exec. +package fdtest + +import ( + "syscall" +) + +// Exists returns true if fd is a valid file descriptor. +func Exists(fd uintptr) bool { + var s syscall.Stat_t + err := syscall.Fstat(int(fd), &s) + return err != syscall.EBADF +} diff --git a/src/os/exec/internal/fdtest/exists_windows.go b/src/os/exec/internal/fdtest/exists_windows.go new file mode 100644 index 0000000000..72b8ccfd23 --- /dev/null +++ b/src/os/exec/internal/fdtest/exists_windows.go @@ -0,0 +1,12 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build windows + +package fdtest + +// Exists is not implemented on windows and panics. +func Exists(fd uintptr) bool { + panic("unimplemented") +} diff --git a/src/os/exec/read3.go b/src/os/exec/read3.go index 8aae5735c4..10cbfbd54a 100644 --- a/src/os/exec/read3.go +++ b/src/os/exec/read3.go @@ -18,12 +18,15 @@ import ( "io" "os" "os/exec" + "os/exec/internal/fdtest" "runtime" "strings" ) func main() { fd3 := os.NewFile(3, "fd3") + defer fd3.Close() + bs, err := io.ReadAll(fd3) if err != nil { fmt.Printf("ReadAll from fd 3: %v\n", err) @@ -37,65 +40,52 @@ func main() { // descriptor from parent == 3 // All descriptors 4 and up should be available, // except for any used by the network poller. - var files []*os.File - for wantfd := uintptr(4); wantfd <= 100; wantfd++ { - if poll.IsPollDescriptor(wantfd) { + for fd := uintptr(4); fd <= 100; fd++ { + if poll.IsPollDescriptor(fd) { continue } - f, err := os.Open(os.Args[0]) - if err != nil { - fmt.Printf("error opening file with expected fd %d: %v", wantfd, err) - os.Exit(1) + + if !fdtest.Exists(fd) { + continue } - if got := f.Fd(); got != wantfd { - fmt.Printf("leaked parent file. fd = %d; want %d\n", got, wantfd) - fdfile := fmt.Sprintf("/proc/self/fd/%d", wantfd) - link, err := os.Readlink(fdfile) - fmt.Printf("readlink(%q) = %q, %v\n", fdfile, link, err) - var args []string - switch runtime.GOOS { - case "plan9": - args = []string{fmt.Sprintf("/proc/%d/fd", os.Getpid())} - case "aix", "solaris", "illumos": - args = []string{fmt.Sprint(os.Getpid())} - default: - args = []string{"-p", fmt.Sprint(os.Getpid())} - } - // Determine which command to use to display open files. - ofcmd := "lsof" - switch runtime.GOOS { - case "dragonfly", "freebsd", "netbsd", "openbsd": - ofcmd = "fstat" - case "plan9": - ofcmd = "/bin/cat" - case "aix": - ofcmd = "procfiles" - case "solaris", "illumos": - ofcmd = "pfiles" - } + fmt.Printf("leaked parent file. fdtest.Exists(%d) got true want false\n", fd) + + fdfile := fmt.Sprintf("/proc/self/fd/%d", fd) + link, err := os.Readlink(fdfile) + fmt.Printf("readlink(%q) = %q, %v\n", fdfile, link, err) - cmd := exec.Command(ofcmd, args...) - out, err := cmd.CombinedOutput() - if err != nil { - fmt.Fprintf(os.Stderr, "%s failed: %v\n", strings.Join(cmd.Args, " "), err) - } - fmt.Printf("%s", out) - os.Exit(1) + var args []string + switch runtime.GOOS { + case "plan9": + args = []string{fmt.Sprintf("/proc/%d/fd", os.Getpid())} + case "aix", "solaris", "illumos": + args = []string{fmt.Sprint(os.Getpid())} + default: + args = []string{"-p", fmt.Sprint(os.Getpid())} } - files = append(files, f) - } - for _, f := range files { - f.Close() - } + // Determine which command to use to display open files. + ofcmd := "lsof" + switch runtime.GOOS { + case "dragonfly", "freebsd", "netbsd", "openbsd": + ofcmd = "fstat" + case "plan9": + ofcmd = "/bin/cat" + case "aix": + ofcmd = "procfiles" + case "solaris", "illumos": + ofcmd = "pfiles" + } - // Referring to fd3 here ensures that it is not - // garbage collected, and therefore closed, while - // executing the wantfd loop above. It doesn't matter - // what we do with fd3 as long as we refer to it; - // closing it is the easy choice. - fd3.Close() + cmd := exec.Command(ofcmd, args...) + out, err := cmd.CombinedOutput() + if err != nil { + fmt.Fprintf(os.Stderr, "%s failed: %v\n", strings.Join(cmd.Args, " "), err) + } + fmt.Printf("%s", out) + os.Exit(1) + } os.Stdout.Write(bs) } -- GitLab From 5e59d6ebd110a7c19770c7d996930ff379ba5726 Mon Sep 17 00:00:00 2001 From: jiahua wang Date: Wed, 22 Sep 2021 07:59:11 +0800 Subject: [PATCH 2213/2500] sort: improve sort documentation Fixes #48527 Change-Id: Ib5df0819cbcd5c2e4f03bda841871d237af96b19 Reviewed-on: https://go-review.googlesource.com/c/go/+/351336 Reviewed-by: Rob Pike Reviewed-by: Ian Lance Taylor --- src/sort/sort.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/sort/sort.go b/src/sort/sort.go index cbaa8c3aac..749310764a 100644 --- a/src/sort/sort.go +++ b/src/sort/sort.go @@ -223,7 +223,7 @@ func quickSort(data Interface, a, b, maxDepth int) { } } -// Sort sorts data. +// Sort sorts data in ascending order as determined by the Less method. // It makes one call to data.Len to determine n and O(n*log(n)) calls to // data.Less and data.Swap. The sort is not guaranteed to be stable. func Sort(data Interface) { @@ -370,7 +370,8 @@ func StringsAreSorted(x []string) bool { return IsSorted(StringSlice(x)) } // - Often "optimal" algorithms are optimal in the number of assignments // but Interface has only Swap as operation. -// Stable sorts data while keeping the original order of equal elements. +// Stable sorts data in ascending order as determined by the Less method, +// while keeping the original order of equal elements. // // It makes one call to data.Len to determine n, O(n*log(n)) calls to // data.Less and O(n*log(n)*log(n)) calls to data.Swap. -- GitLab From 01b6cf09fc9f272d9db3d30b4c93982f4911d120 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Mon, 15 Nov 2021 15:56:39 -0800 Subject: [PATCH 2214/2500] runtime: check GOAMD64 compatibility after setting up TLS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need TLS set up to be able to print an error without crashing. Fixes #49586 Update #45453 Change-Id: I97f0efcd716a8dca614e82ab73f2d855b7277599 Reviewed-on: https://go-review.googlesource.com/c/go/+/364174 Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Martin Möhrmann Trust: Martin Möhrmann Trust: Keith Randall --- src/runtime/asm_amd64.s | 136 +++++++++++++++++++--------------------- 1 file changed, 64 insertions(+), 72 deletions(-) diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index 0f0e5be21a..c08ae610fb 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -145,28 +145,14 @@ GLOBL bad_cpu_msg<>(SB), RODATA, $84 #endif -#ifdef GOAMD64_v1 -#define SKIP_GOAMD64_CHECK -#endif - -#ifndef GOAMD64_v1 -#ifndef GOAMD64_v2 -#ifndef GOAMD64_v3 -#ifndef GOAMD64_v4 -#define SKIP_GOAMD64_CHECK -#endif -#endif -#endif -#endif - TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0 // copy arguments forward on an even stack MOVQ DI, AX // argc MOVQ SI, BX // argv - SUBQ $(4*8+7), SP // 2args 2auto + SUBQ $(5*8), SP // 3args 2auto ANDQ $~15, SP - MOVQ AX, 16(SP) - MOVQ BX, 24(SP) + MOVQ AX, 24(SP) + MOVQ BX, 32(SP) // create istack out of the given (operating system) stack. // _cgo_init may update stackguard. @@ -181,23 +167,8 @@ TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0 MOVL $0, AX CPUID CMPL AX, $0 -#ifdef SKIP_GOAMD64_CHECK JE nocpuinfo -#else - JNE has_cpuinfo - -bad_cpu: // show that the program requires a certain microarchitecture level. - MOVQ $2, 0(SP) - MOVQ $bad_cpu_msg<>(SB), AX - MOVQ AX, 8(SP) - MOVQ $84, 16(SP) - CALL runtime·write(SB) - MOVQ $1, 0(SP) - CALL runtime·exit(SB) - CALL runtime·abort(SB) -#endif -has_cpuinfo: CMPL BX, $0x756E6547 // "Genu" JNE notintel CMPL DX, $0x49656E69 // "ineI" @@ -212,44 +183,6 @@ notintel: CPUID MOVL AX, runtime·processorVersionInfo(SB) -#ifdef NEED_FEATURES_CX - ANDL $NEED_FEATURES_CX, CX - CMPL CX, $NEED_FEATURES_CX - JNE bad_cpu -#endif - -#ifdef NEED_MAX_CPUID - MOVL $0x80000000, AX - CPUID - CMPL AX, $NEED_MAX_CPUID - JL bad_cpu -#endif - -#ifdef NEED_EXT_FEATURES_BX - MOVL $7, AX - MOVL $0, CX - CPUID - ANDL $NEED_EXT_FEATURES_BX, BX - CMPL BX, $NEED_EXT_FEATURES_BX - JNE bad_cpu -#endif - -#ifdef NEED_EXT_FEATURES_CX - MOVL $0x80000001, AX - CPUID - ANDL $NEED_EXT_FEATURES_CX, CX - CMPL CX, $NEED_EXT_FEATURES_CX - JNE bad_cpu -#endif - -#ifdef NEED_OS_SUPPORT_AX - XORL CX, CX - XGETBV - ANDL $NEED_OS_SUPPORT_AX, AX - CMPL AX, $NEED_OS_SUPPORT_AX - JNE bad_cpu -#endif - nocpuinfo: // if there is an _cgo_init, call it. MOVQ _cgo_init(SB), AX @@ -330,11 +263,59 @@ ok: MOVQ AX, g_m(CX) CLD // convention is D is always left cleared + + // Check GOAMD64 reqirements + // We need to do this after setting up TLS, so that + // we can report an error if there is a failure. See issue 49586. +#ifdef NEED_FEATURES_CX + MOVL $0, AX + CPUID + CMPL AX, $0 + JE bad_cpu + MOVL $1, AX + CPUID + ANDL $NEED_FEATURES_CX, CX + CMPL CX, $NEED_FEATURES_CX + JNE bad_cpu +#endif + +#ifdef NEED_MAX_CPUID + MOVL $0x80000000, AX + CPUID + CMPL AX, $NEED_MAX_CPUID + JL bad_cpu +#endif + +#ifdef NEED_EXT_FEATURES_BX + MOVL $7, AX + MOVL $0, CX + CPUID + ANDL $NEED_EXT_FEATURES_BX, BX + CMPL BX, $NEED_EXT_FEATURES_BX + JNE bad_cpu +#endif + +#ifdef NEED_EXT_FEATURES_CX + MOVL $0x80000001, AX + CPUID + ANDL $NEED_EXT_FEATURES_CX, CX + CMPL CX, $NEED_EXT_FEATURES_CX + JNE bad_cpu +#endif + +#ifdef NEED_OS_SUPPORT_AX + XORL CX, CX + XGETBV + ANDL $NEED_OS_SUPPORT_AX, AX + CMPL AX, $NEED_OS_SUPPORT_AX + JNE bad_cpu +#endif + CALL runtime·check(SB) - MOVL 16(SP), AX // copy argc + MOVL 24(SP), AX // copy argc MOVL AX, 0(SP) - MOVQ 24(SP), AX // copy argv + MOVQ 32(SP), AX // copy argv MOVQ AX, 8(SP) CALL runtime·args(SB) CALL runtime·osinit(SB) @@ -352,6 +333,17 @@ ok: CALL runtime·abort(SB) // mstart should never return RET +bad_cpu: // show that the program requires a certain microarchitecture level. + MOVQ $2, 0(SP) + MOVQ $bad_cpu_msg<>(SB), AX + MOVQ AX, 8(SP) + MOVQ $84, 16(SP) + CALL runtime·write(SB) + MOVQ $1, 0(SP) + CALL runtime·exit(SB) + CALL runtime·abort(SB) + RET + // Prevent dead-code elimination of debugCallV2, which is // intended to be called by debuggers. MOVQ $runtime·debugCallV2(SB), AX -- GitLab From a2b8231b91e8c4c9e95875b8063bf364f5b0db97 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 16 Nov 2021 13:01:57 -0800 Subject: [PATCH 2215/2500] runtime: remove defer test log spam This appears to be leftover debugging from CL 356011. Change-Id: Ieeda0b7e297e0cb943827b28644135e6cad12e3c Reviewed-on: https://go-review.googlesource.com/c/go/+/364555 Trust: Josh Bleecher Snyder Trust: Dan Scales Run-TryBot: Josh Bleecher Snyder Reviewed-by: Michael Pratt Reviewed-by: Dan Scales TryBot-Result: Go Bot --- src/runtime/defer_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/src/runtime/defer_test.go b/src/runtime/defer_test.go index 1d5745d60b..821db0ca12 100644 --- a/src/runtime/defer_test.go +++ b/src/runtime/defer_test.go @@ -467,7 +467,6 @@ func TestIssue43920(t *testing.T) { } func step(t *testing.T, steps *int, want int) { - println("step", want) *steps++ if *steps != want { t.Fatalf("have %v, want %v", *steps, want) -- GitLab From 3d7cb23e3d5e7880d582f1b0300064bd1138f3ee Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Tue, 16 Nov 2021 18:44:08 -0500 Subject: [PATCH 2216/2500] cmd/compile: emit definition of 'any' when compiling runtime Include the predefined type 'any' in the list of other important predefined types that are emitted when compiling the runtime package (uintptr, string, etc). Fixes #49619. Change-Id: I4a851ba2f302fbc3a425e65daa325c6bf83659da Reviewed-on: https://go-review.googlesource.com/c/go/+/364377 Trust: Than McIntosh Trust: Dan Scales Run-TryBot: Than McIntosh TryBot-Result: Go Bot Reviewed-by: Dan Scales --- .../compile/internal/reflectdata/reflect.go | 1 + test/fixedbugs/issue49619.go | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 test/fixedbugs/issue49619.go diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 4e20dbf29e..e22fabb410 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -1384,6 +1384,7 @@ func WriteBasicTypes() { } writeType(types.NewPtr(types.Types[types.TSTRING])) writeType(types.NewPtr(types.Types[types.TUNSAFEPTR])) + writeType(types.AnyType) // emit type structs for error and func(error) string. // The latter is the type of an auto-generated wrapper. diff --git a/test/fixedbugs/issue49619.go b/test/fixedbugs/issue49619.go new file mode 100644 index 0000000000..c9f3cbc4ad --- /dev/null +++ b/test/fixedbugs/issue49619.go @@ -0,0 +1,19 @@ +// build + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This testcase caused a linker crash in DWARF generation. + +package main + +//go:noinline +func f() any { + var a []any + return a[0] +} + +func main() { + f() +} -- GitLab From f384c707ac3dd946e3c895d0f4e154744048ef36 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 16 Nov 2021 17:02:11 -0800 Subject: [PATCH 2217/2500] cmd/compile/internal/types2: tweaks to ArgumentError to be more idiomatic This CL is a clean port of CL 351335 from go/types to types2. Updates #47916 Change-Id: Idc377fb71d480a51d5e93a348f3a880346011974 Reviewed-on: https://go-review.googlesource.com/c/go/+/364535 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/api.go | 13 +++++-------- src/cmd/compile/internal/types2/api_test.go | 11 ++++++++--- src/cmd/compile/internal/types2/instantiate.go | 6 +++--- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/cmd/compile/internal/types2/api.go b/src/cmd/compile/internal/types2/api.go index 83c4b02abf..367cb8f700 100644 --- a/src/cmd/compile/internal/types2/api.go +++ b/src/cmd/compile/internal/types2/api.go @@ -55,17 +55,14 @@ func (err Error) FullError() string { return fmt.Sprintf("%s: %s", err.Pos, err.Full) } -// An ArgumentError holds an error that is associated with an argument. +// An ArgumentError holds an error associated with an argument index. type ArgumentError struct { - index int - error + Index int + Err error } -// Index returns the positional index of the argument associated with the -// error. -func (e ArgumentError) Index() int { - return e.index -} +func (e *ArgumentError) Error() string { return e.Err.Error() } +func (e *ArgumentError) Unwrap() error { return e.Err } // An Importer resolves import paths to Packages. // diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index 866ebb8684..7ec1063843 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -7,6 +7,7 @@ package types2_test import ( "bytes" "cmd/compile/internal/syntax" + "errors" "fmt" "internal/testenv" "reflect" @@ -2002,9 +2003,13 @@ func TestInstantiateErrors(t *testing.T) { t.Fatalf("Instantiate(%v, %v) returned nil error, want non-nil", T, test.targs) } - gotAt := err.(ArgumentError).Index() - if gotAt != test.wantAt { - t.Errorf("Instantate(%v, %v): error at index %d, want index %d", T, test.targs, gotAt, test.wantAt) + var argErr *ArgumentError + if !errors.As(err, &argErr) { + t.Fatalf("Instantiate(%v, %v): error is not an *ArgumentError", T, test.targs) + } + + if argErr.Index != test.wantAt { + t.Errorf("Instantate(%v, %v): error at index %d, want index %d", T, test.targs, argErr.Index, test.wantAt) } } } diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 299d63dc60..09ca1b7c16 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -24,8 +24,8 @@ import ( // instances with the same identity. // // If verify is set and constraint satisfaction fails, the returned error may -// be of dynamic type ArgumentError indicating which type argument did not -// satisfy its corresponding type parameter constraint, and why. +// wrap an *ArgumentError indicating which type argument did not satisfy its +// corresponding type parameter constraint, and why. // // TODO(rfindley): change this function to also return an error if lengths of // tparams and targs do not match. @@ -42,7 +42,7 @@ func Instantiate(ctxt *Context, typ Type, targs []Type, validate bool) (Type, er tparams = t.TypeParams().list() } if i, err := (*Checker)(nil).verify(nopos, tparams, targs); err != nil { - return inst, ArgumentError{i, err} + return inst, &ArgumentError{i, err} } } -- GitLab From fceca2c0f1ff21e1b2b0bf9960b776bb08e58d86 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 16 Nov 2021 17:30:47 -0800 Subject: [PATCH 2218/2500] cmd/compile/internal/types2: add a test for argument error unwrapping This CL is a clean port of CL 351338 from go/types to types2. Change-Id: I7fd0e5a447bf51cb359e71731c2f9b95e3960da6 Reviewed-on: https://go-review.googlesource.com/c/go/+/364536 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/api_test.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index 7ec1063843..ca90e6b97d 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -2014,6 +2014,20 @@ func TestInstantiateErrors(t *testing.T) { } } +func TestArgumentErrorUnwrapping(t *testing.T) { + var err error = &ArgumentError{ + Index: 1, + Err: Error{Msg: "test"}, + } + var e Error + if !errors.As(err, &e) { + t.Fatalf("error %v does not wrap types.Error", err) + } + if e.Msg != "test" { + t.Errorf("e.Msg = %q, want %q", e.Msg, "test") + } +} + func TestInstanceIdentity(t *testing.T) { imports := make(testImporter) conf := Config{Importer: imports} -- GitLab From a17a21c190c3e3ea8e88af3e89ccb3c2f101c35b Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 16 Nov 2021 08:22:53 -0800 Subject: [PATCH 2219/2500] cmd/compile/internal/types2: deduplicate signatures with the context This CL is a mostly clean port of CL 362801 from go/types to types2. It deviates from go/types in some of the testing code because types2 already had made some of the changes. It also re-introduces some empty lines that got lost in earlier CLs. Change-Id: I0bebd68f0880fac61631a5d0c323a9f8ce853ac6 Reviewed-on: https://go-review.googlesource.com/c/go/+/364335 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/context.go | 41 ++++--- .../compile/internal/types2/instantiate.go | 43 +++---- .../internal/types2/instantiate_test.go | 107 +++++++++++++++--- src/cmd/compile/internal/types2/named.go | 2 +- src/cmd/compile/internal/types2/subst.go | 2 +- src/cmd/compile/internal/types2/typestring.go | 2 +- src/cmd/compile/internal/types2/typexpr.go | 2 +- 7 files changed, 140 insertions(+), 59 deletions(-) diff --git a/src/cmd/compile/internal/types2/context.go b/src/cmd/compile/internal/types2/context.go index 93a0cb8d40..7abea6b654 100644 --- a/src/cmd/compile/internal/types2/context.go +++ b/src/cmd/compile/internal/types2/context.go @@ -1,11 +1,13 @@ // Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. + package types2 import ( "bytes" "fmt" + "strconv" "strings" "sync" ) @@ -16,10 +18,10 @@ import ( // // It is safe for concurrent use. type Context struct { - mu sync.Mutex - typeMap map[string][]ctxtEntry // type hash -> instances entries - nextID int // next unique ID - seen map[*Named]int // assigned unique IDs + mu sync.Mutex + typeMap map[string][]ctxtEntry // type hash -> instances entries + nextID int // next unique ID + originIDs map[Type]int // origin type -> unique ID } type ctxtEntry struct { @@ -31,23 +33,25 @@ type ctxtEntry struct { // NewContext creates a new Context. func NewContext() *Context { return &Context{ - typeMap: make(map[string][]ctxtEntry), - seen: make(map[*Named]int), + typeMap: make(map[string][]ctxtEntry), + originIDs: make(map[Type]int), } } -// typeHash returns a string representation of typ instantiated with targs, -// which can be used as an exact type hash: types that are identical produce -// identical string representations. If targs is not empty, typ is printed as -// if it were instantiated with targs. The result is guaranteed to not contain -// blanks (" "). -func (ctxt *Context) typeHash(typ Type, targs []Type) string { +// instanceHash returns a string representation of typ instantiated with targs. +// The hash should be a perfect hash, though out of caution the type checker +// does not assume this. The result is guaranteed to not contain blanks. +func (ctxt *Context) instanceHash(orig Type, targs []Type) string { assert(ctxt != nil) - assert(typ != nil) + assert(orig != nil) var buf bytes.Buffer h := newTypeHasher(&buf, ctxt) - h.typ(typ) + h.string(strconv.Itoa(ctxt.getID(orig))) + // Because we've already written the unique origin ID this call to h.typ is + // unnecessary, but we leave it for hash readability. It can be removed later + // if performance is an issue. + h.typ(orig) if len(targs) > 0 { // TODO(rfindley): consider asserting on isGeneric(typ) here, if and when // isGeneric handles *Signature types. @@ -82,6 +86,7 @@ func (ctxt *Context) lookup(h string, orig Type, targs []Type) Type { // h. func (ctxt *Context) update(h string, orig Type, targs []Type, inst Type) Type { assert(inst != nil) + ctxt.mu.Lock() defer ctxt.mu.Unlock() @@ -104,14 +109,14 @@ func (ctxt *Context) update(h string, orig Type, targs []Type, inst Type) Type { return inst } -// idForType returns a unique ID for the pointer n. -func (ctxt *Context) idForType(n *Named) int { +// getID returns a unique ID for the type t. +func (ctxt *Context) getID(t Type) int { ctxt.mu.Lock() defer ctxt.mu.Unlock() - id, ok := ctxt.seen[n] + id, ok := ctxt.originIDs[t] if !ok { id = ctxt.nextID - ctxt.seen[n] = id + ctxt.originIDs[t] = id ctxt.nextID++ } return id diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 09ca1b7c16..35fcc7c040 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -52,30 +52,26 @@ func Instantiate(ctxt *Context, typ Type, targs []Type, validate bool) (Type, er // instance creates a type or function instance using the given original type // typ and arguments targs. For Named types the resulting instance will be // unexpanded. -func (check *Checker) instance(pos syntax.Pos, orig Type, targs []Type, ctxt *Context) Type { +func (check *Checker) instance(pos syntax.Pos, orig Type, targs []Type, ctxt *Context) (res Type) { + var h string + if ctxt != nil { + h = ctxt.instanceHash(orig, targs) + // typ may already have been instantiated with identical type arguments. In + // that case, re-use the existing instance. + if inst := ctxt.lookup(h, orig, targs); inst != nil { + return inst + } + } + switch orig := orig.(type) { case *Named: - var h string - if ctxt != nil { - h = ctxt.typeHash(orig, targs) - // typ may already have been instantiated with identical type arguments. In - // that case, re-use the existing instance. - if inst := ctxt.lookup(h, orig, targs); inst != nil { - return inst - } - } tname := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil) named := check.newNamed(tname, orig, nil, nil, nil) // underlying, tparams, and methods are set when named is resolved named.targs = NewTypeList(targs) named.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, []*Func) { return expandNamed(ctxt, n, pos) } - if ctxt != nil { - // It's possible that we've lost a race to add named to the context. - // In this case, use whichever instance is recorded in the context. - named = ctxt.update(h, orig, targs, named).(*Named) - } - return named + res = named case *Signature: tparams := orig.TypeParams() @@ -96,10 +92,19 @@ func (check *Checker) instance(pos syntax.Pos, orig Type, targs []Type, ctxt *Co // After instantiating a generic signature, it is not generic // anymore; we need to set tparams to nil. sig.tparams = nil - return sig + res = sig + default: + // only types and functions can be generic + panic(fmt.Sprintf("%v: cannot instantiate %v", pos, orig)) + } + + if ctxt != nil { + // It's possible that we've lost a race to add named to the context. + // In this case, use whichever instance is recorded in the context. + res = ctxt.update(h, orig, targs, res) } - // only types and functions can be generic - panic(fmt.Sprintf("%v: cannot instantiate %v", pos, orig)) + + return res } // validateTArgLen verifies that the length of targs and tparams matches, diff --git a/src/cmd/compile/internal/types2/instantiate_test.go b/src/cmd/compile/internal/types2/instantiate_test.go index 4f10dd929f..289fe98fd2 100644 --- a/src/cmd/compile/internal/types2/instantiate_test.go +++ b/src/cmd/compile/internal/types2/instantiate_test.go @@ -10,27 +10,98 @@ import ( ) func TestInstantiateEquality(t *testing.T) { - const src = "package p; type T[P any] int" - pkg, err := pkgFor(".", src, nil) - if err != nil { - t.Fatal(err) - } - T := pkg.Scope().Lookup("T").Type().(*Named) - // Instantiating the same type twice should result in pointer-equivalent - // instances. - ctxt := NewContext() - res1, err := Instantiate(ctxt, T, []Type{Typ[Int]}, false) - if err != nil { - t.Fatal(err) - } - res2, err := Instantiate(ctxt, T, []Type{Typ[Int]}, false) - if err != nil { - t.Fatal(err) + tests := []struct { + src string + name1 string + targs1 []Type + name2 string + targs2 []Type + wantEqual bool + }{ + { + "package basictype; type T[P any] int", + "T", []Type{Typ[Int]}, + "T", []Type{Typ[Int]}, + true, + }, + { + "package differenttypeargs; type T[P any] int", + "T", []Type{Typ[Int]}, + "T", []Type{Typ[String]}, + false, + }, + { + "package typeslice; type T[P any] int", + "T", []Type{NewSlice(Typ[Int])}, + "T", []Type{NewSlice(Typ[Int])}, + true, + }, + { + "package basicfunc; func F[P any]() {}", + "F", []Type{Typ[Int]}, + "F", []Type{Typ[Int]}, + true, + }, + { + "package funcslice; func F[P any]() {}", + "F", []Type{NewSlice(Typ[Int])}, + "F", []Type{NewSlice(Typ[Int])}, + true, + }, + { + "package funcwithparams; func F[P any](x string) float64 { return 0 }", + "F", []Type{Typ[Int]}, + "F", []Type{Typ[Int]}, + true, + }, + { + "package differentfuncargs; func F[P any](x string) float64 { return 0 }", + "F", []Type{Typ[Int]}, + "F", []Type{Typ[String]}, + false, + }, + { + "package funcequality; func F1[P any](x int) {}; func F2[Q any](x int) {}", + "F1", []Type{Typ[Int]}, + "F2", []Type{Typ[Int]}, + false, + }, + { + "package funcsymmetry; func F1[P any](x P) {}; func F2[Q any](x Q) {}", + "F1", []Type{Typ[Int]}, + "F2", []Type{Typ[Int]}, + false, + }, } - if res1 != res2 { - t.Errorf("first instance (%s) not pointer-equivalent to second instance (%s)", res1, res2) + + for _, test := range tests { + pkg, err := pkgFor(".", test.src, nil) + if err != nil { + t.Fatal(err) + } + + t.Run(pkg.Name(), func(t *testing.T) { + ctxt := NewContext() + + T1 := pkg.Scope().Lookup(test.name1).Type() + res1, err := Instantiate(ctxt, T1, test.targs1, false) + if err != nil { + t.Fatal(err) + } + + T2 := pkg.Scope().Lookup(test.name2).Type() + res2, err := Instantiate(ctxt, T2, test.targs2, false) + if err != nil { + t.Fatal(err) + } + + if gotEqual := res1 == res2; gotEqual != test.wantEqual { + t.Errorf("%s == %s: %t, want %t", res1, res2, gotEqual, test.wantEqual) + } + }) } } + func TestInstantiateNonEquality(t *testing.T) { const src = "package p; type T[P any] int" pkg1, err := pkgFor(".", src, nil) diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index e90c301a0d..a455489cd6 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -251,7 +251,7 @@ func expandNamed(ctxt *Context, n *Named, instPos syntax.Pos) (tparams *TypePara if n.orig.tparams.Len() == n.targs.Len() { // We must always have a context, to avoid infinite recursion. ctxt = check.bestContext(ctxt) - h := ctxt.typeHash(n.orig, n.targs.list()) + h := ctxt.instanceHash(n.orig, n.targs.list()) // ensure that an instance is recorded for h to avoid infinite recursion. ctxt.update(h, n.orig, n.TypeArgs().list(), n) diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 9b82f8889a..516f248127 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -207,7 +207,7 @@ func (subst *subster) typ(typ Type) Type { } // before creating a new named type, check if we have this one already - h := subst.ctxt.typeHash(t.orig, newTArgs) + h := subst.ctxt.instanceHash(t.orig, newTArgs) dump(">>> new type hash: %s", h) if named := subst.ctxt.lookup(h, t.orig, newTArgs); named != nil { dump(">>> found %s", named) diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 0c93a7e6e4..1857f58a4b 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -297,7 +297,7 @@ func (w *typeWriter) typ(typ Type) { // nothing. func (w *typeWriter) typePrefix(t *Named) { if w.ctxt != nil { - w.string(strconv.Itoa(w.ctxt.idForType(t))) + w.string(strconv.Itoa(w.ctxt.getID(t))) } } diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 4ba21fa9a0..0380c3461d 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -437,7 +437,7 @@ func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def } // create the instance - h := check.conf.Context.typeHash(orig, targs) + h := check.conf.Context.instanceHash(orig, targs) // targs may be incomplete, and require inference. In any case we should de-duplicate. inst, _ := check.conf.Context.lookup(h, orig, targs).(*Named) // If inst is non-nil, we can't just return here. Inst may have been -- GitLab From 489f58779ce073ef8f6b1505f80580211200ff60 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 16 Nov 2021 08:31:38 -0800 Subject: [PATCH 2220/2500] cmd/compile/internal/types2: when type hashing, use placeholders for type parameters This is a port of CL 363114 from go/types to types2 with a temporary work-around in tparamIndex to avoid a crash with the unified build and test/typeparam/setsimp.go. Change-Id: Id4805385f21c95b461911b246fb47ee278a84ac9 Reviewed-on: https://go-review.googlesource.com/c/go/+/364336 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/typestring.go | 55 +++++++++++-------- src/cmd/compile/internal/types2/unify.go | 7 +++ 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 1857f58a4b..ba3494d9d9 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -8,6 +8,7 @@ package types2 import ( "bytes" + "fmt" "strconv" "unicode/utf8" ) @@ -70,20 +71,21 @@ func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) { } type typeWriter struct { - buf *bytes.Buffer - seen map[Type]bool - qf Qualifier - ctxt *Context // if non-nil, we are type hashing - debug bool // if true, write debug annotations + buf *bytes.Buffer + seen map[Type]bool + qf Qualifier + ctxt *Context // if non-nil, we are type hashing + tparams *TypeParamList // local type parameters + debug bool // if true, write debug annotations } func newTypeWriter(buf *bytes.Buffer, qf Qualifier) *typeWriter { - return &typeWriter{buf, make(map[Type]bool), qf, nil, false} + return &typeWriter{buf, make(map[Type]bool), qf, nil, nil, false} } func newTypeHasher(buf *bytes.Buffer, ctxt *Context) *typeWriter { assert(ctxt != nil) - return &typeWriter{buf, make(map[Type]bool), nil, ctxt, false} + return &typeWriter{buf, make(map[Type]bool), nil, ctxt, nil, false} } func (w *typeWriter) byte(b byte) { @@ -265,12 +267,16 @@ func (w *typeWriter) typ(typ Type) { } case *Named: - w.typePrefix(t) - w.typeName(t.obj) + // If hashing, write a unique prefix for t to represent its identity, since + // named type identity is pointer identity. + if w.ctxt != nil { + w.string(strconv.Itoa(w.ctxt.getID(t))) + } + w.typeName(t.obj) // when hashing written for readability of the hash only if t.targs != nil { // instantiated type w.typeList(t.targs.list()) - } else if w.ctxt == nil && t.TypeParams().Len() != 0 { // For type hashing, don't need to format the TParams + } else if w.ctxt == nil && t.TypeParams().Len() != 0 { // For type hashing, don't need to format the TypeParams // parameterized type w.tParamList(t.TypeParams().list()) } @@ -280,9 +286,16 @@ func (w *typeWriter) typ(typ Type) { w.error("unnamed type parameter") break } - w.string(t.obj.name) - if w.debug || w.ctxt != nil { - w.string(subscript(t.id)) + if i := tparamIndex(w.tparams.list(), t); i >= 0 { + // The names of type parameters that are declared by the type being + // hashed are not part of the type identity. Replace them with a + // placeholder indicating their index. + w.string(fmt.Sprintf("$%d", i)) + } else { + w.string(t.obj.name) + if w.debug || w.ctxt != nil { + w.string(subscript(t.id)) + } } default: @@ -292,15 +305,6 @@ func (w *typeWriter) typ(typ Type) { } } -// If w.ctxt is non-nil, typePrefix writes a unique prefix for the named type t -// based on the types already observed by w.ctxt. If w.ctxt is nil, it does -// nothing. -func (w *typeWriter) typePrefix(t *Named) { - if w.ctxt != nil { - w.string(strconv.Itoa(w.ctxt.getID(t))) - } -} - func (w *typeWriter) typeList(list []Type) { w.byte('[') for i, typ := range list { @@ -385,6 +389,13 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) { func (w *typeWriter) signature(sig *Signature) { if sig.TypeParams().Len() != 0 { + if w.ctxt != nil { + assert(w.tparams == nil) + w.tparams = sig.TypeParams() + defer func() { + w.tparams = nil + }() + } w.tParamList(sig.TypeParams().list()) } diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index ccb6ee8709..651bba1a6b 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -9,6 +9,7 @@ package types2 import ( "bytes" "fmt" + "internal/buildcfg" ) // The unifier maintains two separate sets of type parameters x and y @@ -161,6 +162,12 @@ func (d *tparamsList) index(typ Type) int { // If tpar is a type parameter in list, tparamIndex returns the type parameter index. // Otherwise, the result is < 0. tpar must not be nil. func tparamIndex(list []*TypeParam, tpar *TypeParam) int { + // Temporary work-around for getting around a crash + // with unified build. + // TODO(gri) investigate and implement proper fix + if buildcfg.Experiment.Unified && tpar.index < 0 { + return -1 + } if i := tpar.index; i < len(list) && list[i] == tpar { return i } -- GitLab From 633d8c120b8f9c2ce4a0d079cd700a152a27dad6 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 16 Nov 2021 08:39:44 -0800 Subject: [PATCH 2221/2500] cmd/compile/internal/types2: when type hashing, canonicalize interfaces This CL is a clean port of CL 363115 from go/types to types2. Change-Id: Ic2bd9388c57ffa02e75ab136d952e3ab49eb9018 Reviewed-on: https://go-review.googlesource.com/c/go/+/364394 Trust: Robert Griesemer Reviewed-by: Robert Findley --- .../internal/types2/instantiate_test.go | 32 +++++++++ src/cmd/compile/internal/types2/typestring.go | 66 +++++++++++++++---- 2 files changed, 86 insertions(+), 12 deletions(-) diff --git a/src/cmd/compile/internal/types2/instantiate_test.go b/src/cmd/compile/internal/types2/instantiate_test.go index 289fe98fd2..591b467a2e 100644 --- a/src/cmd/compile/internal/types2/instantiate_test.go +++ b/src/cmd/compile/internal/types2/instantiate_test.go @@ -10,6 +10,7 @@ import ( ) func TestInstantiateEquality(t *testing.T) { + emptySignature := NewSignatureType(nil, nil, nil, nil, nil, false) tests := []struct { src string name1 string @@ -36,6 +37,37 @@ func TestInstantiateEquality(t *testing.T) { "T", []Type{NewSlice(Typ[Int])}, true, }, + { + // interface{interface{...}} is equivalent to interface{...} + "package equivalentinterfaces; type T[P any] int", + "T", []Type{ + NewInterfaceType([]*Func{NewFunc(nopos, nil, "M", emptySignature)}, nil), + }, + "T", []Type{ + NewInterfaceType( + nil, + []Type{ + NewInterfaceType([]*Func{NewFunc(nopos, nil, "M", emptySignature)}, nil), + }, + ), + }, + true, + }, + { + // int|string is equivalent to string|int + "package equivalenttypesets; type T[P any] int", + "T", []Type{ + NewInterfaceType(nil, []Type{ + NewUnion([]*Term{NewTerm(false, Typ[Int]), NewTerm(false, Typ[String])}), + }), + }, + "T", []Type{ + NewInterfaceType(nil, []Type{ + NewUnion([]*Term{NewTerm(false, Typ[String]), NewTerm(false, Typ[Int])}), + }), + }, + true, + }, { "package basicfunc; func F[P any]() {}", "F", []Type{Typ[Int]}, diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index ba3494d9d9..4d03eba657 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -9,7 +9,9 @@ package types2 import ( "bytes" "fmt" + "sort" "strconv" + "strings" "unicode/utf8" ) @@ -217,20 +219,24 @@ func (w *typeWriter) typ(typ Type) { } w.string("interface{") first := true - for _, m := range t.methods { - if !first { - w.byte(';') + if w.ctxt != nil { + w.typeSet(t.typeSet()) + } else { + for _, m := range t.methods { + if !first { + w.byte(';') + } + first = false + w.string(m.name) + w.signature(m.typ.(*Signature)) } - first = false - w.string(m.name) - w.signature(m.typ.(*Signature)) - } - for _, typ := range t.embeddeds { - if !first { - w.byte(';') + for _, typ := range t.embeddeds { + if !first { + w.byte(';') + } + first = false + w.typ(typ) } - first = false - w.typ(typ) } w.byte('}') @@ -305,6 +311,42 @@ func (w *typeWriter) typ(typ Type) { } } +// typeSet writes a canonical hash for an interface type set. +func (w *typeWriter) typeSet(s *_TypeSet) { + assert(w.ctxt != nil) + first := true + for _, m := range s.methods { + if !first { + w.byte(';') + } + first = false + w.string(m.name) + w.signature(m.typ.(*Signature)) + } + switch { + case s.terms.isAll(): + // nothing to do + case s.terms.isEmpty(): + w.string(s.terms.String()) + default: + var termHashes []string + for _, term := range s.terms { + // terms are not canonically sorted, so we sort their hashes instead. + var buf bytes.Buffer + if term.tilde { + buf.WriteByte('~') + } + newTypeHasher(&buf, w.ctxt).typ(term.typ) + termHashes = append(termHashes, buf.String()) + } + sort.Strings(termHashes) + if !first { + w.byte(';') + } + w.string(strings.Join(termHashes, "|")) + } +} + func (w *typeWriter) typeList(list []Type) { w.byte('[') for i, typ := range list { -- GitLab From 9c60a0968987ca3245b115a46d358d63b6b31b0f Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 16 Nov 2021 11:18:53 -0800 Subject: [PATCH 2222/2500] cmd/compile/internal/types2: don't set a Config.Context if none is provided This CL is a clean port of CL 363175 from go/types to types2. Change-Id: I149789be07c0ca7ddef7bfaa4ea9507778a63775 Reviewed-on: https://go-review.googlesource.com/c/go/+/364454 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/call.go | 2 +- src/cmd/compile/internal/types2/check.go | 8 +++----- src/cmd/compile/internal/types2/decl.go | 2 +- src/cmd/compile/internal/types2/named.go | 8 +++++--- src/cmd/compile/internal/types2/signature.go | 2 +- src/cmd/compile/internal/types2/typexpr.go | 9 +++++---- 6 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index fef493b2ae..4e2c2a2989 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -78,7 +78,7 @@ func (check *Checker) instantiateSignature(pos syntax.Pos, typ *Signature, targs }() } - inst := check.instance(pos, typ, targs, check.conf.Context).(*Signature) + inst := check.instance(pos, typ, targs, check.bestContext(nil)).(*Signature) assert(len(posList) <= len(targs)) tparams := typ.TypeParams().list() if i, err := check.verify(pos, tparams, targs); err != nil { diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go index 247bb5a649..faf4ccac0b 100644 --- a/src/cmd/compile/internal/types2/check.go +++ b/src/cmd/compile/internal/types2/check.go @@ -103,6 +103,7 @@ type Checker struct { // package information // (initialized by NewChecker, valid for the life-time of checker) conf *Config + ctxt *Context // context for de-duplicating instances pkg *Package *Info version version // accepted language version @@ -200,11 +201,6 @@ func NewChecker(conf *Config, pkg *Package, info *Info) *Checker { conf = new(Config) } - // make sure we have a context - if conf.Context == nil { - conf.Context = NewContext() - } - // make sure we have an info struct if info == nil { info = new(Info) @@ -217,6 +213,7 @@ func NewChecker(conf *Config, pkg *Package, info *Info) *Checker { return &Checker{ conf: conf, + ctxt: conf.Context, pkg: pkg, Info: info, version: version, @@ -333,6 +330,7 @@ func (check *Checker) checkFiles(files []*syntax.File) (err error) { check.seenPkgMap = nil check.recvTParamMap = nil check.defTypes = nil + check.ctxt = nil // TODO(gri) There's more memory we should release at this point. diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 91503f1fcd..e85abbb82f 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -69,7 +69,7 @@ func (check *Checker) objDecl(obj Object, def *Named) { // Funcs with m.instRecv set have not yet be completed. Complete them now // so that they have a type when objDecl exits. if m, _ := obj.(*Func); m != nil && m.instRecv != nil { - check.completeMethod(check.conf.Context, m) + check.completeMethod(nil, m) } // Checking the declaration of obj means inferring its type diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index a455489cd6..51ea27a6db 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -220,15 +220,17 @@ func (n *Named) setUnderlying(typ Type) { // bestContext returns the best available context. In order of preference: // - the given ctxt, if non-nil -// - check.Config.Context, if check is non-nil +// - check.ctxt, if check is non-nil // - a new Context func (check *Checker) bestContext(ctxt *Context) *Context { if ctxt != nil { return ctxt } if check != nil { - assert(check.conf.Context != nil) - return check.conf.Context + if check.ctxt == nil { + check.ctxt = NewContext() + } + return check.ctxt } return NewContext() } diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index b0b8ad49d9..06dcd9131a 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -216,7 +216,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] var err string switch T := rtyp.(type) { case *Named: - T.resolve(check.conf.Context) + T.resolve(check.bestContext(nil)) // The receiver type may be an instantiated type referred to // by an alias (which cannot have receiver parameters for now). if T.TypeArgs() != nil && sig.RecvTypeParams() == nil { diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 0380c3461d..862a31544a 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -437,9 +437,10 @@ func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def } // create the instance - h := check.conf.Context.instanceHash(orig, targs) + ctxt := check.bestContext(nil) + h := ctxt.instanceHash(orig, targs) // targs may be incomplete, and require inference. In any case we should de-duplicate. - inst, _ := check.conf.Context.lookup(h, orig, targs).(*Named) + inst, _ := ctxt.lookup(h, orig, targs).(*Named) // If inst is non-nil, we can't just return here. Inst may have been // constructed via recursive substitution, in which case we wouldn't do the // validation below. Ensure that the validation (and resulting errors) runs @@ -448,7 +449,7 @@ func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def tname := NewTypeName(x.Pos(), orig.obj.pkg, orig.obj.name, nil) inst = check.newNamed(tname, orig, nil, nil, nil) // underlying, methods and tparams are set when named is resolved inst.targs = NewTypeList(targs) - inst = check.conf.Context.update(h, orig, targs, inst).(*Named) + inst = ctxt.update(h, orig, targs, inst).(*Named) } def.setUnderlying(inst) @@ -474,7 +475,7 @@ func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def // This is an instance from the source, not from recursive substitution, // and so it must be resolved during type-checking so that we can report // errors. - inst.resolve(check.conf.Context) + inst.resolve(ctxt) // Since check is non-nil, we can still mutate inst. Unpinning the resolver // frees some memory. inst.resolver = nil -- GitLab From 1c13b58abaaeaaaa54a5471613c020fe78105016 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 16 Nov 2021 11:27:56 -0800 Subject: [PATCH 2223/2500] cmd/compile/internal/types2: rename types.context to types.environment This CL is a clean port of CL 363176 from go/types to types2. It also includes a minor adjustment to a field access in go/types to match types2 in that respect. Change-Id: If33fc7e68372b12d61d06b75dd9f7c0715b57bc1 Reviewed-on: https://go-review.googlesource.com/c/go/+/364474 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/check.go | 17 +++++++++-------- src/cmd/compile/internal/types2/decl.go | 14 +++++++------- src/cmd/compile/internal/types2/stmt.go | 10 +++++----- src/go/types/decl.go | 2 +- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go index faf4ccac0b..38fc25c74d 100644 --- a/src/cmd/compile/internal/types2/check.go +++ b/src/cmd/compile/internal/types2/check.go @@ -39,8 +39,9 @@ type exprInfo struct { val constant.Value // constant value; or nil (if not a constant) } -// A context represents the context within which an object is type-checked. -type context struct { +// An environment represents the environment within which an object is +// type-checked. +type environment struct { decl *declInfo // package-level declaration whose init expression/function body is checked scope *Scope // top-most scope for lookups pos syntax.Pos // if valid, identifiers are looked up as if at position pos (used by Eval) @@ -53,9 +54,9 @@ type context struct { hasCallOrRecv bool // set if an expression contains a function call or channel receive operation } -// lookup looks up name in the current context and returns the matching object, or nil. -func (ctxt *context) lookup(name string) Object { - _, obj := ctxt.scope.LookupParent(name, ctxt.pos) +// lookup looks up name in the current environment and returns the matching object, or nil. +func (env *environment) lookup(name string) Object { + _, obj := env.scope.LookupParent(name, env.pos) return obj } @@ -137,9 +138,9 @@ type Checker struct { objPath []Object // path of object dependencies during type inference (for cycle reporting) defTypes []*Named // defined types created during type checking, for final validation. - // context within which the current object is type-checked - // (valid only for the duration of type-checking a specific object) - context + // environment within which the current object is type-checked (valid only + // for the duration of type-checking a specific object) + environment // debugging indent int // indentation for tracing diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index e85abbb82f..4b79c59af3 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -51,7 +51,7 @@ func pathString(path []Object) string { return s } -// objDecl type-checks the declaration of obj in its respective (file) context. +// objDecl type-checks the declaration of obj in its respective (file) environment. // For the meaning of def, see Checker.definedType, in typexpr.go. func (check *Checker) objDecl(obj Object, def *Named) { if check.conf.Trace && obj.Type() == nil { @@ -178,11 +178,11 @@ func (check *Checker) objDecl(obj Object, def *Named) { unreachable() } - // save/restore current context and setup object context - defer func(ctxt context) { - check.context = ctxt - }(check.context) - check.context = context{ + // save/restore current environment and set up object environment + defer func(env environment) { + check.environment = env + }(check.environment) + check.environment = environment{ scope: d.file, } @@ -646,7 +646,7 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list []*syntax.Fiel // function closures may appear inside a type parameter list but they // cannot be generic, and their bodies are processed in delayed and // sequential fashion. Note that with each new declaration, we save - // the existing context and restore it when done; thus inTParamList + // the existing environment and restore it when done; thus inTParamList // is true exactly only when we are in a specific type parameter list. assert(!check.inTParamList) check.inTParamList = true diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index 6869c87929..44d9256c50 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -28,13 +28,13 @@ func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body sig.scope.pos = body.Pos() sig.scope.end = syntax.EndPos(body) - // save/restore current context and setup function context + // save/restore current environment and set up function environment // (and use 0 indentation at function start) - defer func(ctxt context, indent int) { - check.context = ctxt + defer func(env environment, indent int) { + check.environment = env check.indent = indent - }(check.context, check.indent) - check.context = context{ + }(check.environment, check.indent) + check.environment = environment{ decl: decl, scope: sig.scope, iota: iota, diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 2108cf6b05..4f28553aa6 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -239,7 +239,7 @@ loop: // If we reach a generic type that is part of a cycle // and we are in a type parameter list, we have a cycle // through a type parameter list, which is invalid. - if check.environment.inTParamList && isGeneric(obj.typ) { + if check.inTParamList && isGeneric(obj.typ) { tparCycle = true break loop } -- GitLab From 2f937d9bfcbb1e95c089a3af37677bacb185aedb Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 16 Nov 2021 11:36:09 -0800 Subject: [PATCH 2224/2500] cmd/compile/internal/types2: add a test for Context deduplication of hash collisions This CL is a clean port of CL 363517 from go/types to types2, with the exception that types_test.go was not removed because it's still needed to set a types2-specific test flag. Change-Id: I12177866537c0f95f3fa36fa0f4aa02016609ca9 Reviewed-on: https://go-review.googlesource.com/c/go/+/364494 Trust: Robert Griesemer Reviewed-by: Robert Findley --- .../compile/internal/types2/context_test.go | 69 +++++++++++++++++++ src/cmd/compile/internal/types2/types_test.go | 3 - 2 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 src/cmd/compile/internal/types2/context_test.go diff --git a/src/cmd/compile/internal/types2/context_test.go b/src/cmd/compile/internal/types2/context_test.go new file mode 100644 index 0000000000..aa649b1448 --- /dev/null +++ b/src/cmd/compile/internal/types2/context_test.go @@ -0,0 +1,69 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types2 + +import ( + "testing" +) + +func TestContextHashCollisions(t *testing.T) { + if debug { + t.Skip("hash collisions are expected, and would fail debug assertions") + } + // Unit test the de-duplication fall-back logic in Context. + // + // We can't test this via Instantiate because this is only a fall-back in + // case our hash is imperfect. + // + // These lookups and updates use reasonable looking types in an attempt to + // make them robust to internal type assertions, but could equally well use + // arbitrary types. + + // Create some distinct origin types. nullaryP and nullaryQ have no + // parameters and are identical (but have different type parameter names). + // unaryP has a parameter. + var nullaryP, nullaryQ, unaryP Type + { + // type nullaryP = func[P any]() + tparam := NewTypeParam(NewTypeName(nopos, nil, "P", nil), &emptyInterface) + nullaryP = NewSignatureType(nil, nil, []*TypeParam{tparam}, nil, nil, false) + } + { + // type nullaryQ = func[Q any]() + tparam := NewTypeParam(NewTypeName(nopos, nil, "Q", nil), &emptyInterface) + nullaryQ = NewSignatureType(nil, nil, []*TypeParam{tparam}, nil, nil, false) + } + { + // type unaryP = func[P any](_ P) + tparam := NewTypeParam(NewTypeName(nopos, nil, "P", nil), &emptyInterface) + params := NewTuple(NewVar(nopos, nil, "_", tparam)) + unaryP = NewSignatureType(nil, nil, []*TypeParam{tparam}, params, nil, false) + } + + ctxt := NewContext() + + // Update the context with an instantiation of nullaryP. + inst := NewSignatureType(nil, nil, nil, nil, nil, false) + if got := ctxt.update("", nullaryP, []Type{Typ[Int]}, inst); got != inst { + t.Error("bad") + } + + // unaryP is not identical to nullaryP, so we should not get inst when + // instantiated with identical type arguments. + if got := ctxt.lookup("", unaryP, []Type{Typ[Int]}); got != nil { + t.Error("bad") + } + + // nullaryQ is identical to nullaryP, so we *should* get inst when + // instantiated with identical type arguments. + if got := ctxt.lookup("", nullaryQ, []Type{Typ[Int]}); got != inst { + t.Error("bad") + } + + // ...but verify we don't get inst with different type arguments. + if got := ctxt.lookup("", nullaryQ, []Type{Typ[String]}); got != nil { + t.Error("bad") + } +} diff --git a/src/cmd/compile/internal/types2/types_test.go b/src/cmd/compile/internal/types2/types_test.go index 1525844f2d..11dca0b53d 100644 --- a/src/cmd/compile/internal/types2/types_test.go +++ b/src/cmd/compile/internal/types2/types_test.go @@ -7,6 +7,3 @@ package types2 func init() { acceptMethodTypeParams = true } - -// Debug is set if types2 is built with debug mode enabled. -const Debug = debug -- GitLab From 3c00a2839a8b577912f78d5fe1ba2d765d0f6c7c Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 16 Nov 2021 12:20:11 -0800 Subject: [PATCH 2225/2500] cmd/compile/internal/types2: return an error from Instantiate on incorrect len(targs) This CL is a clean port of CL 363635 from go/types to types2. Updates #47916 Change-Id: Ib46758435c31ad9a6a4a63f552503d5afa66b5c0 Reviewed-on: https://go-review.googlesource.com/c/go/+/364534 Trust: Robert Griesemer Reviewed-by: Robert Findley --- .../compile/internal/types2/instantiate.go | 50 +++++++++++-------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 35fcc7c040..3f5fc56f5d 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -13,40 +13,50 @@ import ( "fmt" ) -// Instantiate instantiates the type typ with the given type arguments targs. -// typ must be a *Named or a *Signature type, and its number of type parameters -// must match the number of provided type arguments. The result is a new, -// instantiated (not parameterized) type of the same kind (either a *Named or a -// *Signature). Any methods attached to a *Named are simply copied; they are -// not instantiated. +// Instantiate instantiates the type orig with the given type arguments targs. +// orig must be a *Named or a *Signature type. If there is no error, the +// resulting Type is a new, instantiated (not parameterized) type of the same +// kind (either a *Named or a *Signature). Methods attached to a *Named type +// are also instantiated, and associated with a new *Func that has the same +// position as the original method, but nil function scope. // -// If ctxt is non-nil, it may be used to de-dupe the instance against previous -// instances with the same identity. +// If ctxt is non-nil, it may be used to de-duplicate the instance against +// previous instances with the same identity. As a special case, generic +// *Signature origin types are only considered identical if they are pointer +// equivalent, so that instantiating distinct (but possibly identical) +// signatures will yield different instances. // -// If verify is set and constraint satisfaction fails, the returned error may -// wrap an *ArgumentError indicating which type argument did not satisfy its -// corresponding type parameter constraint, and why. +// If validate is set, Instantiate verifies that the number of type arguments +// and parameters match, and that the type arguments satisfy their +// corresponding type constraints. If verification fails, the resulting error +// may wrap an *ArgumentError indicating which type argument did not satisfy +// its corresponding type parameter constraint, and why. // -// TODO(rfindley): change this function to also return an error if lengths of -// tparams and targs do not match. -func Instantiate(ctxt *Context, typ Type, targs []Type, validate bool) (Type, error) { - inst := (*Checker)(nil).instance(nopos, typ, targs, ctxt) - - var err error +// If validate is not set, Instantiate does not verify the type argument count +// or whether the type arguments satisfy their constraints. Instantiate is +// guaranteed to not return an error, but may panic. Specifically, for +// *Signature types, Instantiate will panic immediately if the type argument +// count is incorrect; for *Named types, a panic may occur later inside the +// *Named API. +func Instantiate(ctxt *Context, orig Type, targs []Type, validate bool) (Type, error) { if validate { var tparams []*TypeParam - switch t := typ.(type) { + switch t := orig.(type) { case *Named: tparams = t.TypeParams().list() case *Signature: tparams = t.TypeParams().list() } + if len(targs) != len(tparams) { + return nil, fmt.Errorf("got %d type arguments but %s has %d type parameters", len(targs), orig, len(tparams)) + } if i, err := (*Checker)(nil).verify(nopos, tparams, targs); err != nil { - return inst, &ArgumentError{i, err} + return nil, &ArgumentError{i, err} } } - return inst, err + inst := (*Checker)(nil).instance(nopos, orig, targs, ctxt) + return inst, nil } // instance creates a type or function instance using the given original type -- GitLab From 03dd049d6efcbca6b829d7ed504ceea6318f2036 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 16 Nov 2021 17:51:58 -0800 Subject: [PATCH 2226/2500] go/types: make sure we are safe for nil in underIs This CL is a clean port CL 363658 from types2 to go/types. Change-Id: Ie2032f85a9cfca62161c2e629c78f1ecd8c6e4c0 Reviewed-on: https://go-review.googlesource.com/c/go/+/364537 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/go/types/expr.go | 3 +++ src/go/types/predicates.go | 4 +++- src/go/types/type.go | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 660c92de3b..ddb0149bf4 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -679,6 +679,9 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const case *TypeParam: // TODO(gri) review this code - doesn't look quite right ok := u.underIs(func(t Type) bool { + if t == nil { + return false + } target, _, _ := check.implicitTypeAndValue(x, t) return target != nil }) diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index d0697b1ad7..78ad6c4f23 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -149,7 +149,9 @@ func hasNil(t Type) bool { case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan: return true case *TypeParam: - return u.underIs(hasNil) + return u.underIs(func(u Type) bool { + return u != nil && hasNil(u) + }) } return false } diff --git a/src/go/types/type.go b/src/go/types/type.go index 555eb9e8b9..756bdcf0a5 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -65,6 +65,9 @@ func match(x, y Type) Type { func structuralType(typ Type) Type { var su Type if underIs(typ, func(u Type) bool { + if u == nil { + return false + } if su != nil { u = match(su, u) if u == nil { -- GitLab From 1d004fa2015d128acf6302fc74b95f6a36c35680 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 17 Nov 2021 10:17:31 +0700 Subject: [PATCH 2227/2500] cmd/compile: emit definition of 'any' only if generic enabled CL 364377 emitted definition of 'any' when compiling runtime. But 'any' is only available when generic enabled. Thus emitting its definition unconditionally causes the compiler crashes. Updates #49619 Change-Id: I0888ca1cbc7a7df300310a99a344f170636333f2 Reviewed-on: https://go-review.googlesource.com/c/go/+/364614 Trust: Cuong Manh Le Trust: Dan Scales Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/reflectdata/reflect.go | 4 +++- test/fixedbugs/issue49619.go | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index e22fabb410..f35baabbf9 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -1384,7 +1384,9 @@ func WriteBasicTypes() { } writeType(types.NewPtr(types.Types[types.TSTRING])) writeType(types.NewPtr(types.Types[types.TUNSAFEPTR])) - writeType(types.AnyType) + if base.Flag.G > 0 { + writeType(types.AnyType) + } // emit type structs for error and func(error) string. // The latter is the type of an auto-generated wrapper. diff --git a/test/fixedbugs/issue49619.go b/test/fixedbugs/issue49619.go index c9f3cbc4ad..f34dfac192 100644 --- a/test/fixedbugs/issue49619.go +++ b/test/fixedbugs/issue49619.go @@ -1,4 +1,4 @@ -// build +// build -gcflags=-G=3 // Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style -- GitLab From 4083a6f3776487e707d4c56c63b1d7dbabb01fb0 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 16 Nov 2021 11:24:22 -0500 Subject: [PATCH 2228/2500] go/types: better error for type assertion/switch on type parameter value This is a port of CL 363439 from types2 to go/types. Change-Id: Ic71871874345e1d0a4a42703e3673aadd11f2bfc Reviewed-on: https://go-review.googlesource.com/c/go/+/364378 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/expr.go | 5 +++++ src/go/types/stmt.go | 5 +++++ src/go/types/testdata/check/typeparams.go2 | 8 ++++---- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/go/types/expr.go b/src/go/types/expr.go index ddb0149bf4..5e66a4a4b5 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -1432,6 +1432,11 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { if x.mode == invalid { goto Error } + // TODO(gri) we may want to permit type assertions on type parameter values at some point + if isTypeParam(x.typ) { + check.invalidOp(x, _InvalidAssert, "cannot use type assertion on type parameter value %s", x) + goto Error + } xtyp, _ := under(x.typ).(*Interface) if xtyp == nil { check.invalidOp(x, _InvalidAssert, "%s is not an interface", x) diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index 363ea35acf..ee7d4e4cf1 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -685,6 +685,11 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { if x.mode == invalid { return } + // TODO(gri) we may want to permit type switches on type parameter values at some point + if isTypeParam(x.typ) { + check.errorf(&x, _InvalidTypeSwitch, "cannot use type switch on type parameter value %s", &x) + return + } xtyp, _ := under(x.typ).(*Interface) if xtyp == nil { check.errorf(&x, _InvalidTypeSwitch, "%s is not an interface", &x) diff --git a/src/go/types/testdata/check/typeparams.go2 b/src/go/types/testdata/check/typeparams.go2 index 9e2bffb539..fdbb7a2740 100644 --- a/src/go/types/testdata/check/typeparams.go2 +++ b/src/go/types/testdata/check/typeparams.go2 @@ -481,8 +481,8 @@ func (_ R2[X, Y]) m2(X) Y // type assertions and type switches over generic types lead to errors for now func _[T any](x T) { - _ = x /* ERROR not an interface */ .(int) - switch x /* ERROR not an interface */ .(type) { + _ = x /* ERROR cannot use type assertion */ .(int) + switch x /* ERROR cannot use type switch */ .(type) { } // work-around @@ -493,8 +493,8 @@ func _[T any](x T) { } func _[T interface{~int}](x T) { - _ = x /* ERROR not an interface */ .(int) - switch x /* ERROR not an interface */ .(type) { + _ = x /* ERROR cannot use type assertion */ .(int) + switch x /* ERROR cannot use type switch */ .(type) { } // work-around -- GitLab From 54b9cb80372f45b5e86c5246717c766fac6f1fe6 Mon Sep 17 00:00:00 2001 From: Patrik Nyblom Date: Tue, 16 Nov 2021 14:35:59 -0800 Subject: [PATCH 2229/2500] runtime: make sure to properly park before going to sleep in Windows ConsoleControlHandler This change avoids the program intermittently hanging on windows/arm64 after getting a signal for which the ConsoleControlHandler can not return. Fixes #49458 Change-Id: Ie28f0f437c7e0f9634b6b3e29dc6cdebd5d996f6 Reviewed-on: https://go-review.googlesource.com/c/go/+/364556 Trust: Patrik Nyblom Trust: Dan Scales Run-TryBot: Patrik Nyblom Run-TryBot: Cherry Mui Reviewed-by: Cherry Mui Reviewed-by: Michael Knyszek TryBot-Result: Go Bot --- src/runtime/os_windows.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go index 648239fb36..7ffb3a11b5 100644 --- a/src/runtime/os_windows.go +++ b/src/runtime/os_windows.go @@ -1194,8 +1194,10 @@ func ctrlHandler(_type uint32) uintptr { if sigsend(s) { if s == _SIGTERM { // Windows terminates the process after this handler returns. - // Block indefinitely to give signal handlers a chance to clean up. - stdcall1(_Sleep, uintptr(_INFINITE)) + // Block indefinitely to give signal handlers a chance to clean up, + // but make sure to be properly parked first, so the rest of the + // program can continue executing. + block() } return 1 } -- GitLab From ab75484d7130496ac9b204b0d418b1ec95bee2f8 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Mon, 15 Nov 2021 17:47:15 -0800 Subject: [PATCH 2230/2500] internal/fuzz: limit number of consecutive mutations This makes two changes: (1) mutator.mutate now only applies a single mutation to the input, and (2) in workerServer.fuzz if, after five mutations are applied to the input, no new coverage is found the input is reset to its initial state. This process is repeated until new coverage is found, or the fuzz call times out. This results in finding new coverage expanding inputs which have less divergence from the initial input they were mutated from, which makes traversing certain types of call graphs significantly more efficient. Fixes #49601 Fixes #48179 Fixes #47090 Change-Id: I74d18a56ca2669f20192951090b281f58ee0b5dc Reviewed-on: https://go-review.googlesource.com/c/go/+/364214 Trust: Roland Shoemaker Trust: Katie Hockman Run-TryBot: Roland Shoemaker TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/internal/fuzz/mutator.go | 39 ++++++++++++++---------------------- src/internal/fuzz/worker.go | 23 ++++++++++++++++++--- 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/src/internal/fuzz/mutator.go b/src/internal/fuzz/mutator.go index da7200dcbe..a3161c04ea 100644 --- a/src/internal/fuzz/mutator.go +++ b/src/internal/fuzz/mutator.go @@ -125,15 +125,13 @@ func (m *mutator) mutate(vals []interface{}, maxBytes int) { } func (m *mutator) mutateInt(v, maxValue int64) int64 { - numIters := 1 + m.r.exp2() var max int64 - for iter := 0; iter < numIters; iter++ { + for { max = 100 switch m.rand(2) { case 0: // Add a random number if v >= maxValue { - iter-- continue } if v > 0 && maxValue-v < max { @@ -141,10 +139,10 @@ func (m *mutator) mutateInt(v, maxValue int64) int64 { max = maxValue - v } v += int64(1 + m.rand(int(max))) + return v case 1: // Subtract a random number if v <= -maxValue { - iter-- continue } if v < 0 && maxValue+v < max { @@ -152,21 +150,19 @@ func (m *mutator) mutateInt(v, maxValue int64) int64 { max = maxValue + v } v -= int64(1 + m.rand(int(max))) + return v } } - return v } func (m *mutator) mutateUInt(v, maxValue uint64) uint64 { - numIters := 1 + m.r.exp2() var max uint64 - for iter := 0; iter < numIters; iter++ { + for { max = 100 switch m.rand(2) { case 0: // Add a random number if v >= maxValue { - iter-- continue } if v > 0 && maxValue-v < max { @@ -175,10 +171,10 @@ func (m *mutator) mutateUInt(v, maxValue uint64) uint64 { } v += uint64(1 + m.rand(int(max))) + return v case 1: // Subtract a random number if v <= 0 { - iter-- continue } if v < max { @@ -186,20 +182,18 @@ func (m *mutator) mutateUInt(v, maxValue uint64) uint64 { max = v } v -= uint64(1 + m.rand(int(max))) + return v } } - return v } func (m *mutator) mutateFloat(v, maxValue float64) float64 { - numIters := 1 + m.r.exp2() var max float64 - for iter := 0; iter < numIters; iter++ { + for { switch m.rand(4) { case 0: // Add a random number if v >= maxValue { - iter-- continue } max = 100 @@ -208,10 +202,10 @@ func (m *mutator) mutateFloat(v, maxValue float64) float64 { max = maxValue - v } v += float64(1 + m.rand(int(max))) + return v case 1: // Subtract a random number if v <= -maxValue { - iter-- continue } max = 100 @@ -220,11 +214,11 @@ func (m *mutator) mutateFloat(v, maxValue float64) float64 { max = maxValue + v } v -= float64(1 + m.rand(int(max))) + return v case 2: // Multiply by a random number absV := math.Abs(v) if v == 0 || absV >= maxValue { - iter-- continue } max = 10 @@ -233,16 +227,16 @@ func (m *mutator) mutateFloat(v, maxValue float64) float64 { max = maxValue / absV } v *= float64(1 + m.rand(int(max))) + return v case 3: // Divide by a random number if v == 0 { - iter-- continue } v /= float64(1 + m.rand(10)) + return v } } - return v } type byteSliceMutator func(*mutator, []byte) []byte @@ -279,15 +273,12 @@ func (m *mutator) mutateBytes(ptrB *[]byte) { *ptrB = b }() - numIters := 1 + m.r.exp2() - for iter := 0; iter < numIters; iter++ { + for { mut := byteSliceMutators[m.rand(len(byteSliceMutators))] - mutated := mut(m, b) - if mutated == nil { - iter-- - continue + if mutated := mut(m, b); mutated != nil { + b = mutated + return } - b = mutated } } diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 48a3923112..e7d824bea1 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -661,6 +661,17 @@ func (ws *workerServer) serve(ctx context.Context) error { } } +// chainedMutations is how many mutations are applied before the worker +// resets the input to it's original state. +// NOTE: this number was picked without much thought. It is low enough that +// it seems to create a significant diversity in mutated inputs. We may want +// to consider looking into this more closely once we have a proper performance +// testing framework. Another option is to randomly pick the number of chained +// mutations on each invocation of the workerServer.fuzz method (this appears to +// be what libFuzzer does, although there seems to be no documentation which +// explains why this choice was made.) +const chainedMutations = 5 + // fuzz runs the test function on random variations of the input value in shared // memory for a limited duration or number of iterations. // @@ -699,11 +710,13 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo return resp } - vals, err := unmarshalCorpusFile(mem.valueCopy()) + originalVals, err := unmarshalCorpusFile(mem.valueCopy()) if err != nil { resp.InternalErr = err.Error() return resp } + vals := make([]interface{}, len(originalVals)) + copy(vals, originalVals) shouldStop := func() bool { return args.Limit > 0 && mem.header().count >= args.Limit @@ -742,9 +755,13 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo select { case <-ctx.Done(): return resp - default: + if mem.header().count%chainedMutations == 0 { + copy(vals, originalVals) + ws.m.r.save(&mem.header().randState, &mem.header().randInc) + } ws.m.mutate(vals, cap(mem.valueRef())) + entry := CorpusEntry{Values: vals} dur, cov, errMsg := fuzzOnce(entry) if errMsg != "" { @@ -1094,7 +1111,7 @@ func (wc *workerClient) fuzz(ctx context.Context, entryIn CorpusEntry, args fuzz wc.m.r.restore(mem.header().randState, mem.header().randInc) if !args.Warmup { // Only mutate the valuesOut if fuzzing actually occurred. - for i := int64(0); i < resp.Count; i++ { + for i := int64(0); i < resp.Count%chainedMutations; i++ { wc.m.mutate(valuesOut, cap(mem.valueRef())) } } -- GitLab From 0555ea3ce997db6e6ef14ba9f55857f359b3fbf2 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 16 Nov 2021 22:18:02 -0800 Subject: [PATCH 2231/2500] runtime: don't serialize all builds in test Permit a test whose program is already built to run immediately, rather than waiting for another test to complete its build. For #44422 Change-Id: I2d1b35d055ee4c4251f4caef3b52dccc82b71a1b Reviewed-on: https://go-review.googlesource.com/c/go/+/364654 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Bryan C. Mills TryBot-Result: Go Bot --- src/runtime/crash_test.go | 61 +++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/src/runtime/crash_test.go b/src/runtime/crash_test.go index e0c0bac892..91a1a41ed5 100644 --- a/src/runtime/crash_test.go +++ b/src/runtime/crash_test.go @@ -6,6 +6,7 @@ package runtime_test import ( "bytes" + "errors" "flag" "fmt" "internal/testenv" @@ -34,12 +35,13 @@ func TestMain(m *testing.M) { var testprog struct { sync.Mutex dir string - target map[string]buildexe + target map[string]*buildexe } type buildexe struct { - exe string - err error + once sync.Once + exe string + err error } func runTestProg(t *testing.T, binary, name string, env ...string) string { @@ -108,13 +110,15 @@ func runBuiltTestProg(t *testing.T, exe, name string, env ...string) string { return b.String() } +var serializeBuild = make(chan bool, 2) + func buildTestProg(t *testing.T, binary string, flags ...string) (string, error) { if *flagQuick { t.Skip("-quick") } + testenv.MustHaveGoBuild(t) testprog.Lock() - defer testprog.Unlock() if testprog.dir == "" { dir, err := os.MkdirTemp("", "go-build") if err != nil { @@ -125,29 +129,48 @@ func buildTestProg(t *testing.T, binary string, flags ...string) (string, error) } if testprog.target == nil { - testprog.target = make(map[string]buildexe) + testprog.target = make(map[string]*buildexe) } name := binary if len(flags) > 0 { name += "_" + strings.Join(flags, "_") } target, ok := testprog.target[name] - if ok { - return target.exe, target.err - } - - exe := filepath.Join(testprog.dir, name+".exe") - cmd := exec.Command(testenv.GoToolPath(t), append([]string{"build", "-o", exe}, flags...)...) - cmd.Dir = "testdata/" + binary - out, err := testenv.CleanCmdEnv(cmd).CombinedOutput() - if err != nil { - target.err = fmt.Errorf("building %s %v: %v\n%s", binary, flags, err, out) + if !ok { + target = &buildexe{} testprog.target[name] = target - return "", target.err } - target.exe = exe - testprog.target[name] = target - return exe, nil + + dir := testprog.dir + + // Unlock testprog while actually building, so that other + // tests can look up executables that were already built. + testprog.Unlock() + + target.once.Do(func() { + // Only do two "go build"'s at a time, + // to keep load from getting too high. + serializeBuild <- true + defer func() { <-serializeBuild }() + + // Don't get confused if testenv.GoToolPath calls t.Skip. + target.err = errors.New("building test called t.Skip") + + exe := filepath.Join(dir, name+".exe") + + t.Logf("running go build -o %s %s", exe, strings.Join(flags, " ")) + cmd := exec.Command(testenv.GoToolPath(t), append([]string{"build", "-o", exe}, flags...)...) + cmd.Dir = "testdata/" + binary + out, err := testenv.CleanCmdEnv(cmd).CombinedOutput() + if err != nil { + target.err = fmt.Errorf("building %s %v: %v\n%s", binary, flags, err, out) + } else { + target.exe = exe + target.err = nil + } + }) + + return target.exe, target.err } func TestVDSO(t *testing.T) { -- GitLab From 17b7604ef62316c7ea69e6a07f90282edcf4c874 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 16 Nov 2021 19:17:31 -0500 Subject: [PATCH 2232/2500] go/types: match Go 1.17 compiler error messages more closely Introduce a new constant compilerErrorMessages, which is set to false for now, so that we can port types2 error handling more precisely. Use this to (partially) port CL 363436, excluding issue49005.go, which does not exist in go/types (it was added in a previous CL related to compiler error messages, that was not ported). I've also included the bugfix from CL 364034, so that go/types is not broken at this commit. In subsequent CLs I'll catch up with error handling locations in types2 that use compiler error messages. Change-Id: I13fd6c43d61b28e0a7a3b0ae8ba785fb8506fbb7 Reviewed-on: https://go-review.googlesource.com/c/go/+/364379 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/assignments.go | 14 +++++-- src/go/types/check.go | 4 ++ src/go/types/conversions.go | 15 +++++-- src/go/types/lookup.go | 58 +++++++++++++++++++++++++++ src/go/types/operand.go | 40 ++++++++++++++---- src/go/types/testdata/check/expr3.src | 2 +- 6 files changed, 118 insertions(+), 15 deletions(-) diff --git a/src/go/types/assignments.go b/src/go/types/assignments.go index d77cf8f7fa..8645834a6e 100644 --- a/src/go/types/assignments.go +++ b/src/go/types/assignments.go @@ -84,10 +84,18 @@ func (check *Checker) assignment(x *operand, T Type, context string) { reason := "" if ok, code := x.assignableTo(check, T, &reason); !ok { - if reason != "" { - check.errorf(x, code, "cannot use %s as %s value in %s: %s", x, T, context, reason) + if compilerErrorMessages { + if reason != "" { + check.errorf(x, code, "cannot use %s as type %s in %s:\n\t%s", x, T, context, reason) + } else { + check.errorf(x, code, "cannot use %s as type %s in %s", x, T, context) + } } else { - check.errorf(x, code, "cannot use %s as %s value in %s", x, T, context) + if reason != "" { + check.errorf(x, code, "cannot use %s as %s value in %s: %s", x, T, context, reason) + } else { + check.errorf(x, code, "cannot use %s as %s value in %s", x, T, context) + } } x.mode = invalid } diff --git a/src/go/types/check.go b/src/go/types/check.go index aef53b20de..38508c77a9 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -18,6 +18,10 @@ import ( const ( debug = false // leave on during development trace = false // turn on for detailed type resolution traces + + // TODO(rfindley): add compiler error message handling from types2, guarded + // behind this flag, so that we can keep the code in sync. + compilerErrorMessages = false // match compiler error messages ) // If forceStrict is set, the type-checker enforces additional diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go index eadc923f5e..530a29c5dd 100644 --- a/src/go/types/conversions.go +++ b/src/go/types/conversions.go @@ -68,10 +68,19 @@ func (check *Checker) conversion(x *operand, T Type) { if !ok { // TODO(rfindley): use types2-style error reporting here. - if cause != "" { - check.errorf(x, _InvalidConversion, "cannot convert %s to %s (%s)", x, T, cause) + if compilerErrorMessages { + if cause != "" { + // Add colon at end of line if we have a following cause. + check.errorf(x, _InvalidConversion, "cannot convert %s to type %s:\n\t%s", x, T, cause) + } else { + check.errorf(x, _InvalidConversion, "cannot convert %s to type %s", x, T) + } } else { - check.errorf(x, _InvalidConversion, "cannot convert %s to %s", x, T) + if cause != "" { + check.errorf(x, _InvalidConversion, "cannot convert %s to %s (%s)", x, T, cause) + } else { + check.errorf(x, _InvalidConversion, "cannot convert %s to %s", x, T) + } } x.mode = invalid return diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index 98af6bfcd7..be91d39f50 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -6,6 +6,11 @@ package types +import ( + "fmt" + "strings" +) + // Internal use of LookupFieldOrMethod: If the obj result is a method // associated with a concrete (non-interface) type, the method's signature // may not be fully set up. Call Checker.objDecl(obj, nil) before accessing @@ -382,6 +387,59 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, return } +// missingMethodReason returns a string giving the detailed reason for a missing method m, +// where m is missing from V, but required by T. It puts the reason in parentheses, +// and may include more have/want info after that. If non-nil, wrongType is a relevant +// method that matches in some way. It may have the correct name, but wrong type, or +// it may have a pointer receiver. +func (check *Checker) missingMethodReason(V, T Type, m, wrongType *Func) string { + var r string + var mname string + if compilerErrorMessages { + mname = m.Name() + " method" + } else { + mname = "method " + m.Name() + } + if wrongType != nil { + if Identical(m.typ, wrongType.typ) { + if m.Name() == wrongType.Name() { + r = fmt.Sprintf("(%s has pointer receiver)", mname) + } else { + r = fmt.Sprintf("(missing %s)\n\t\thave %s^^%s\n\t\twant %s^^%s", + mname, wrongType.Name(), wrongType.typ, m.Name(), m.typ) + } + } else { + if compilerErrorMessages { + r = fmt.Sprintf("(wrong type for %s)\n\t\thave %s^^%s\n\t\twant %s^^%s", + mname, wrongType.Name(), wrongType.typ, m.Name(), m.typ) + } else { + r = fmt.Sprintf("(wrong type for %s: have %s, want %s)", + mname, wrongType.typ, m.typ) + } + } + // This is a hack to print the function type without the leading + // 'func' keyword in the have/want printouts. We could change to have + // an extra formatting option for types2.Type that doesn't print out + // 'func'. + r = strings.Replace(r, "^^func", "", -1) + } else if IsInterface(T) { + if isInterfacePtr(V) { + r = fmt.Sprintf("(%s is pointer to interface, not interface)", V) + } + } else if isInterfacePtr(T) { + r = fmt.Sprintf("(%s is pointer to interface, not interface)", T) + } + if r == "" { + r = fmt.Sprintf("(missing %s)", mname) + } + return r +} + +func isInterfacePtr(T Type) bool { + p, _ := under(T).(*Pointer) + return p != nil && IsInterface(p.base) +} + // assertableTo reports whether a value of type V can be asserted to have type T. // It returns (nil, false) as affirmative answer. Otherwise it returns a missing // method required by V and whether it is missing or just has the wrong type. diff --git a/src/go/types/operand.go b/src/go/types/operand.go index 6f902e9749..e8b5d00de4 100644 --- a/src/go/types/operand.go +++ b/src/go/types/operand.go @@ -276,16 +276,20 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er if Ti, ok := Tu.(*Interface); ok { if m, wrongType := check.missingMethod(V, Ti, true); m != nil /* Implements(V, Ti) */ { if reason != nil { - // TODO(gri) the error messages here should follow the style in Checker.typeAssertion (factor!) - if wrongType != nil { - if Identical(m.typ, wrongType.typ) { - *reason = fmt.Sprintf("missing method %s (%s has pointer receiver)", m.name, m.name) + if compilerErrorMessages { + *reason = check.sprintf("%s does not implement %s %s", x.typ, T, + check.missingMethodReason(x.typ, T, m, wrongType)) + } else { + if wrongType != nil { + if Identical(m.typ, wrongType.typ) { + *reason = fmt.Sprintf("missing method %s (%s has pointer receiver)", m.name, m.name) + } else { + *reason = fmt.Sprintf("wrong type for method %s (have %s, want %s)", m.Name(), wrongType.typ, m.typ) + } + } else { - *reason = fmt.Sprintf("wrong type for method %s (have %s, want %s)", m.Name(), wrongType.typ, m.typ) + *reason = "missing method " + m.Name() } - - } else { - *reason = "missing method " + m.Name() } } return false, _InvalidIfaceAssign @@ -293,6 +297,26 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er return true, 0 } + // Provide extra detail in compiler error messages in some cases when T is + // not an interface. + if check != nil && compilerErrorMessages { + if isInterfacePtr(Tu) { + if reason != nil { + *reason = check.sprintf("%s does not implement %s (%s is pointer to interface, not interface)", x.typ, T, T) + } + return false, _InvalidIfaceAssign + } + if Vi, _ := Vu.(*Interface); Vi != nil { + if m, _ := check.missingMethod(T, Vi, true); m == nil { + // T implements Vi, so give hint about type assertion. + if reason != nil { + *reason = check.sprintf("need type assertion") + } + return false, _IncompatibleAssign + } + } + } + // x is a bidirectional channel value, T is a channel // type, x's type V and T have identical element types, // and at least one of V or T is not a named type. diff --git a/src/go/types/testdata/check/expr3.src b/src/go/types/testdata/check/expr3.src index 3ab367810f..0f15c15a55 100644 --- a/src/go/types/testdata/check/expr3.src +++ b/src/go/types/testdata/check/expr3.src @@ -458,7 +458,7 @@ func type_asserts() { var t I _ = t /* ERROR "use of .* outside type switch" */ .(type) - _ = t /* ERROR "missing method m" */ .(T) + _ = t /* ERROR "m has pointer receiver" */ .(T) _ = t.(*T) _ = t /* ERROR "missing method m" */ .(T1) _ = t /* ERROR "wrong type for method m" */ .(T2) -- GitLab From 9bdbed1d963a840d8c23640bbd20bd4cb9776859 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 17 Nov 2021 09:35:57 -0500 Subject: [PATCH 2233/2500] go/types, types2: complete methods on pointer receivers in missingMethod We were not calling objDecl on methods on pointer receivers in missingMethod. This may not have mattered before, but with lazy completion of instance methods it is necessary. Fixes #49579 Change-Id: Icddb1f3b16bef7d8017859734f9879a4f1cc18de Reviewed-on: https://go-review.googlesource.com/c/go/+/364714 Trust: Robert Findley Trust: Dan Scales Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/cmd/compile/internal/types2/lookup.go | 17 +++++++++++------ .../types2/testdata/fixedbugs/issue49579.go2 | 17 +++++++++++++++++ src/go/types/lookup.go | 7 +++++++ src/go/types/testdata/fixedbugs/issue49579.go2 | 17 +++++++++++++++++ 4 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue49579.go2 create mode 100644 src/go/types/testdata/fixedbugs/issue49579.go2 diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index 4f50ea54b1..ee764c7d14 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -71,6 +71,8 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o // lookupFieldOrMethod should only be called by LookupFieldOrMethod and missingMethod. // If checkFold is true, the lookup for methods will include looking for any method // which case-folds to the same as 'name' (used for giving helpful error messages). +// +// The resulting object may not be fully type-checked. func lookupFieldOrMethod(T Type, addressable, checkFold bool, pkg *Package, name string) (obj Object, index []int, indirect bool) { // WARNING: The code in this function is extremely subtle - do not modify casually! @@ -352,14 +354,17 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, if obj == nil { ptr := NewPointer(V) obj, _, _ = lookupFieldOrMethod(ptr, false, false, m.pkg, m.name) - if obj != nil { - return m, obj.(*Func) + if obj == nil { + // If we didn't find the exact method (even with pointer + // receiver), look to see if there is a method that + // matches m.name with case-folding. + obj, _, _ = lookupFieldOrMethod(V, false, true, m.pkg, m.name) } - // If we didn't find the exact method (even with pointer - // receiver), look to see if there is a method that - // matches m.name with case-folding. - obj, _, _ := lookupFieldOrMethod(V, false, true, m.pkg, m.name) if obj != nil { + // methods may not have a fully set up signature yet + if check != nil { + check.objDecl(obj, nil) + } return m, obj.(*Func) } } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49579.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49579.go2 new file mode 100644 index 0000000000..9e20ae5468 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49579.go2 @@ -0,0 +1,17 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type I[F any] interface { + Q(*F) +} + +func G[F any]() I[any] { + return g /* ERROR "missing method Q \(Q has pointer receiver\)" */ [F]{} +} + +type g[F any] struct{} + +func (*g[F]) Q(*any) {} diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index be91d39f50..6855ccdf27 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -69,6 +69,8 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o // indirectly via different packages.) // lookupFieldOrMethod should only be called by LookupFieldOrMethod and missingMethod. +// +// The resulting object may not be fully type-checked. func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) { // WARNING: The code in this function is extremely subtle - do not modify casually! @@ -346,7 +348,12 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, if obj == nil { ptr := NewPointer(V) obj, _, _ = lookupFieldOrMethod(ptr, false, m.pkg, m.name) + if obj != nil { + // methods may not have a fully set up signature yet + if check != nil { + check.objDecl(obj, nil) + } return m, obj.(*Func) } } diff --git a/src/go/types/testdata/fixedbugs/issue49579.go2 b/src/go/types/testdata/fixedbugs/issue49579.go2 new file mode 100644 index 0000000000..9e20ae5468 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue49579.go2 @@ -0,0 +1,17 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type I[F any] interface { + Q(*F) +} + +func G[F any]() I[any] { + return g /* ERROR "missing method Q \(Q has pointer receiver\)" */ [F]{} +} + +type g[F any] struct{} + +func (*g[F]) Q(*any) {} -- GitLab From 0981724eaeb9e3a4553473072c38cf11822bc7fd Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 17 Nov 2021 09:38:16 -0500 Subject: [PATCH 2234/2500] go/types: check for non-negative index in tparamIndex There are code paths (particularly error formatting or tracing) that call tparamIndex before the type parameter is bound. We cannot rely on the index being non-negative. Change-Id: Ibad91c691b4f319b0c7b465a750b679a8a7af6a1 Reviewed-on: https://go-review.googlesource.com/c/go/+/364715 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/cmd/compile/internal/types2/unify.go | 15 +++++++-------- src/go/types/unify.go | 10 ++++++++-- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index 651bba1a6b..f663beec38 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -9,7 +9,6 @@ package types2 import ( "bytes" "fmt" - "internal/buildcfg" ) // The unifier maintains two separate sets of type parameters x and y @@ -162,13 +161,13 @@ func (d *tparamsList) index(typ Type) int { // If tpar is a type parameter in list, tparamIndex returns the type parameter index. // Otherwise, the result is < 0. tpar must not be nil. func tparamIndex(list []*TypeParam, tpar *TypeParam) int { - // Temporary work-around for getting around a crash - // with unified build. - // TODO(gri) investigate and implement proper fix - if buildcfg.Experiment.Unified && tpar.index < 0 { - return -1 - } - if i := tpar.index; i < len(list) && list[i] == tpar { + // Once a type parameter is bound its index is >= 0. However, there are some + // code paths (namely tracing and type hashing) by which it is possible to + // arrive here with a type parameter that has not been bound, hence the check + // for 0 <= i below. + // TODO(rfindley): investigate a better approach for guarding against using + // unbound type parameters. + if i := tpar.index; 0 <= i && i < len(list) && list[i] == tpar { return i } return -1 diff --git a/src/go/types/unify.go b/src/go/types/unify.go index d3b86008ef..6cd653aee1 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -159,9 +159,15 @@ func (d *tparamsList) index(typ Type) int { } // If tpar is a type parameter in list, tparamIndex returns the type parameter index. -// Otherwise, the result is < 0. tpar must not be nil. +// Otherwise, the result is < 0. tpar must not be nil.j func tparamIndex(list []*TypeParam, tpar *TypeParam) int { - if i := tpar.index; i < len(list) && list[i] == tpar { + // Once a type parameter is bound its index is >= 0. However, there are some + // code paths (namely tracing and type hashing) by which it is possible to + // arrive here with a type parameter that has not been bound, hence the check + // for 0 <= i below. + // TODO(rfindley): investigate a better approach for guarding against using + // unbound type parameters. + if i := tpar.index; 0 <= i && i < len(list) && list[i] == tpar { return i } return -1 -- GitLab From aa34ea2f4c57ea2648286463ef3f891e49b64fa8 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 17 Nov 2021 09:40:11 -0800 Subject: [PATCH 2235/2500] runtime: don't run TestCheckPtr/TestCheckPtr2 in short mode Change-Id: I02c9bea1637c2694a76e7747cb8a2e3562301566 Reviewed-on: https://go-review.googlesource.com/c/go/+/364755 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/runtime/checkptr_test.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/runtime/checkptr_test.go b/src/runtime/checkptr_test.go index b3aea079c6..15011ec494 100644 --- a/src/runtime/checkptr_test.go +++ b/src/runtime/checkptr_test.go @@ -12,6 +12,12 @@ import ( ) func TestCheckPtr(t *testing.T) { + // This test requires rebuilding packages with -d=checkptr=1, + // so it's somewhat slow. + if testing.Short() { + t.Skip("skipping test in -short mode") + } + t.Parallel() testenv.MustHaveGoRun(t) @@ -57,6 +63,12 @@ func TestCheckPtr(t *testing.T) { } func TestCheckPtr2(t *testing.T) { + // This test requires rebuilding packages with -d=checkptr=2, + // so it's somewhat slow. + if testing.Short() { + t.Skip("skipping test in -short mode") + } + t.Parallel() testenv.MustHaveGoRun(t) -- GitLab From 88474d47ddeb5714a18923048beaa5dafa7196d5 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 17 Nov 2021 10:39:36 -0500 Subject: [PATCH 2236/2500] go/types: underlying type of a type parameter is its constraint interface This is a port of CL 359016 from types2 to go/types. Some of the code around untyped nil differed (because we have to treat untyped nil differently in go/types for historical reasons). Updates #47916 Change-Id: Ifc428ed977bf2f4f84cc831f1a3527156940d7b8 Reviewed-on: https://go-review.googlesource.com/c/go/+/364716 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/assignments.go | 2 +- src/go/types/builtins.go | 30 +++++++++++-- src/go/types/call.go | 2 +- src/go/types/conversions.go | 16 ++++--- src/go/types/expr.go | 34 +++++++++++++-- src/go/types/index.go | 86 +++++++++++++++++++++++++++++++++++++ src/go/types/lookup.go | 6 +-- src/go/types/operand.go | 9 ++-- src/go/types/predicates.go | 27 ++++++++---- src/go/types/sizes.go | 1 + src/go/types/struct.go | 9 +++- src/go/types/type.go | 9 +++- src/go/types/typeparam.go | 23 +++++++++- src/go/types/typeset.go | 4 ++ src/go/types/typexpr.go | 12 ++++-- 15 files changed, 231 insertions(+), 39 deletions(-) diff --git a/src/go/types/assignments.go b/src/go/types/assignments.go index 8645834a6e..7e6a230b48 100644 --- a/src/go/types/assignments.go +++ b/src/go/types/assignments.go @@ -37,7 +37,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { // bool, rune, int, float64, complex128 or string respectively, depending // on whether the value is a boolean, rune, integer, floating-point, // complex, or string constant." - if T == nil || IsInterface(T) { + if T == nil || IsInterface(T) && !isTypeParam(T) { if T == nil && x.typ == Typ[UntypedNil] { check.errorf(x, _UntypedNil, "use of untyped nil in %s", context) x.mode = invalid diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 5418d66aeb..5abfe8d35b 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -179,7 +179,28 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b mode = value } + case *Interface: + if tparamIsIface && isTypeParam(x.typ) { + if t.typeSet().underIs(func(t Type) bool { + switch t := arrayPtrDeref(t).(type) { + case *Basic: + if isString(t) && id == _Len { + return true + } + case *Array, *Slice, *Chan: + return true + case *Map: + if id == _Len { + return true + } + } + return false + }) { + mode = value + } + } case *TypeParam: + assert(!tparamIsIface) if t.underIs(func(t Type) bool { switch t := arrayPtrDeref(t).(type) { case *Basic: @@ -797,16 +818,19 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // hasVarSize reports if the size of type t is variable due to type parameters. func hasVarSize(t Type) bool { - switch t := under(t).(type) { + switch u := under(t).(type) { case *Array: - return hasVarSize(t.elem) + return hasVarSize(u.elem) case *Struct: - for _, f := range t.fields { + for _, f := range u.fields { if hasVarSize(f.typ) { return true } } + case *Interface: + return isTypeParam(t) case *TypeParam: + assert(!tparamIsIface) return true case *Named, *Union: unreachable() diff --git a/src/go/types/call.go b/src/go/types/call.go index 7cb6027f3b..940c0ff468 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -141,7 +141,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { check.errorf(call.Args[0], _BadDotDotDotSyntax, "invalid use of ... in conversion to %s", T) break } - if t, _ := under(T).(*Interface); t != nil { + if t, _ := under(T).(*Interface); t != nil && !isTypeParam(T) { if !t.IsMethodSet() { check.errorf(call, _MisplacedConstraintIface, "cannot use interface %s in conversion (contains specific type constraints or is comparable)", T) break diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go index 530a29c5dd..5995d5920f 100644 --- a/src/go/types/conversions.go +++ b/src/go/types/conversions.go @@ -98,7 +98,7 @@ func (check *Checker) conversion(x *operand, T Type) { // - Keep untyped nil for untyped nil arguments. // - For integer to string conversions, keep the argument type. // (See also the TODO below.) - if IsInterface(T) || constArg && !isConstType(T) || x.isNil() { + if IsInterface(T) && !isTypeParam(T) || constArg && !isConstType(T) || x.isNil() { final = Default(x.typ) // default type of untyped nil is untyped nil } else if isInteger(x.typ) && allString(T) { final = x.typ @@ -129,19 +129,23 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { return true } - // "V and T have identical underlying types if tags are ignored" + // "V and T have identical underlying types if tags are ignored + // and V and T are not type parameters" V := x.typ Vu := under(V) Tu := under(T) - if IdenticalIgnoreTags(Vu, Tu) { + Vp, _ := V.(*TypeParam) + Tp, _ := T.(*TypeParam) + if IdenticalIgnoreTags(Vu, Tu) && Vp == nil && Tp == nil { return true } // "V and T are unnamed pointer types and their pointer base types - // have identical underlying types if tags are ignored" + // have identical underlying types if tags are ignored + // and their pointer base types are not type parameters" if V, ok := V.(*Pointer); ok { if T, ok := T.(*Pointer); ok { - if IdenticalIgnoreTags(under(V.base), under(T.base)) { + if IdenticalIgnoreTags(under(V.base), under(T.base)) && !isTypeParam(V.base) && !isTypeParam(T.base) { return true } } @@ -195,8 +199,6 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { } // optimization: if we don't have type parameters, we're done - Vp, _ := V.(*TypeParam) - Tp, _ := T.(*TypeParam) if Vp == nil && Tp == nil { return false } diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 5e66a4a4b5..84eb59d1d0 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -598,7 +598,11 @@ func (check *Checker) updateExprVal(x ast.Expr, val constant.Value) { func (check *Checker) convertUntyped(x *operand, target Type) { newType, val, code := check.implicitTypeAndValue(x, target) if code != 0 { - check.invalidConversion(code, x, safeUnderlying(target)) + t := target + if !tparamIsIface || !isTypeParam(target) { + t = safeUnderlying(target) + } + check.invalidConversion(code, x, t) x.mode = invalid return } @@ -678,6 +682,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const } case *TypeParam: // TODO(gri) review this code - doesn't look quite right + assert(!tparamIsIface) ok := u.underIs(func(t Type) bool { if t == nil { return false @@ -693,6 +698,24 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const return Typ[UntypedNil], nil, 0 } case *Interface: + if tparamIsIface && isTypeParam(target) { + // TODO(gri) review this code - doesn't look quite right + ok := u.typeSet().underIs(func(t Type) bool { + if t == nil { + return false + } + target, _, _ := check.implicitTypeAndValue(x, t) + return target != nil + }) + if !ok { + return nil, nil, _InvalidUntypedConversion + } + // keep nil untyped (was bug #39755) + if x.isNil() { + return Typ[UntypedNil], nil, 0 + } + break + } // Values must have concrete dynamic types. If the value is nil, // keep it untyped (this is important for tools such as go vet which // need the dynamic type for argument checking of say, print @@ -961,8 +984,9 @@ func (check *Checker) binary(x *operand, e ast.Expr, lhs, rhs ast.Expr, op token return } + // TODO(gri) make canMix more efficient - called for each binary operation canMix := func(x, y *operand) bool { - if IsInterface(x.typ) || IsInterface(y.typ) { + if IsInterface(x.typ) && !isTypeParam(x.typ) || IsInterface(y.typ) && !isTypeParam(y.typ) { return true } if allBoolean(x.typ) != allBoolean(y.typ) { @@ -1219,7 +1243,11 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { case hint != nil: // no composite literal type present - use hint (element type of enclosing type) typ = hint - base, _ = deref(under(typ)) // *T implies &T{} + base = typ + if !isTypeParam(typ) { + base = under(typ) + } + base, _ = deref(base) // *T implies &T{} default: // TODO(gri) provide better error messages depending on context diff --git a/src/go/types/index.go b/src/go/types/index.go index 0284716277..2ff33814e5 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -100,8 +100,94 @@ func (check *Checker) indexExpr(x *operand, e *typeparams.IndexExpr) (isFuncInst x.expr = e.Orig return false + case *Interface: + // Note: The body of this 'if' statement is the same as the body + // of the case for type parameters below. If we keep both + // these branches we should factor out the code. + if tparamIsIface && isTypeParam(x.typ) { + // TODO(gri) report detailed failure cause for better error messages + var key, elem Type // key != nil: we must have all maps + mode := variable // non-maps result mode + // TODO(gri) factor out closure and use it for non-typeparam cases as well + if typ.typeSet().underIs(func(u Type) bool { + l := int64(-1) // valid if >= 0 + var k, e Type // k is only set for maps + switch t := u.(type) { + case *Basic: + if isString(t) { + e = universeByte + mode = value + } + case *Array: + l = t.len + e = t.elem + if x.mode != variable { + mode = value + } + case *Pointer: + if t, _ := under(t.base).(*Array); t != nil { + l = t.len + e = t.elem + } + case *Slice: + e = t.elem + case *Map: + k = t.key + e = t.elem + } + if e == nil { + return false + } + if elem == nil { + // first type + length = l + key, elem = k, e + return true + } + // all map keys must be identical (incl. all nil) + // (that is, we cannot mix maps with other types) + if !Identical(key, k) { + return false + } + // all element types must be identical + if !Identical(elem, e) { + return false + } + // track the minimal length for arrays, if any + if l >= 0 && l < length { + length = l + } + return true + }) { + // For maps, the index expression must be assignable to the map key type. + if key != nil { + index := check.singleIndex(e) + if index == nil { + x.mode = invalid + return false + } + var k operand + check.expr(&k, index) + check.assignment(&k, key, "map index") + // ok to continue even if indexing failed - map element type is known + x.mode = mapindex + x.typ = elem + x.expr = e + return false + } + + // no maps + valid = true + x.mode = mode + x.typ = elem + } + } case *TypeParam: + // Note: The body of this case is the same as the body of the 'if' + // statement in the interface case above. If we keep both + // these branches we should factor out the code. // TODO(gri) report detailed failure cause for better error messages + assert(!tparamIsIface) var key, elem Type // key != nil: we must have all maps mode := variable // non-maps result mode // TODO(gri) factor out closure and use it for non-typeparam cases as well diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index 6855ccdf27..16a9890199 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -429,11 +429,11 @@ func (check *Checker) missingMethodReason(V, T Type, m, wrongType *Func) string // an extra formatting option for types2.Type that doesn't print out // 'func'. r = strings.Replace(r, "^^func", "", -1) - } else if IsInterface(T) { + } else if IsInterface(T) && !isTypeParam(T) { if isInterfacePtr(V) { r = fmt.Sprintf("(%s is pointer to interface, not interface)", V) } - } else if isInterfacePtr(T) { + } else if isInterfacePtr(T) && !isTypeParam(T) { r = fmt.Sprintf("(%s is pointer to interface, not interface)", T) } if r == "" { @@ -444,7 +444,7 @@ func (check *Checker) missingMethodReason(V, T Type, m, wrongType *Func) string func isInterfacePtr(T Type) bool { p, _ := under(T).(*Pointer) - return p != nil && IsInterface(p.base) + return p != nil && IsInterface(p.base) && !isTypeParam(T) } // assertableTo reports whether a value of type V can be asserted to have type T. diff --git a/src/go/types/operand.go b/src/go/types/operand.go index e8b5d00de4..8cc5eda866 100644 --- a/src/go/types/operand.go +++ b/src/go/types/operand.go @@ -267,13 +267,14 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er // Vu is typed // x's type V and T have identical underlying types - // and at least one of V or T is not a named type. - if Identical(Vu, Tu) && (!hasName(V) || !hasName(T)) { + // and at least one of V or T is not a named type + // and neither V nor T is a type parameter. + if Identical(Vu, Tu) && (!hasName(V) || !hasName(T)) && Vp == nil && Tp == nil { return true, 0 } // T is an interface type and x implements T and T is not a type parameter - if Ti, ok := Tu.(*Interface); ok { + if Ti, ok := Tu.(*Interface); ok && Tp == nil { if m, wrongType := check.missingMethod(V, Ti, true); m != nil /* Implements(V, Ti) */ { if reason != nil { if compilerErrorMessages { @@ -306,7 +307,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er } return false, _InvalidIfaceAssign } - if Vi, _ := Vu.(*Interface); Vi != nil { + if Vi, _ := Vu.(*Interface); Vi != nil && Vp == nil { if m, _ := check.missingMethod(T, Vi, true); m == nil { // T implements Vi, so give hint about type assertion. if reason != nil { diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 78ad6c4f23..5204eb0c29 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -49,13 +49,10 @@ func allNumericOrString(typ Type) bool { return allBasic(typ, IsNumeric|IsString // for all specific types of the type parameter's type set. // allBasic(t, info) is an optimized version of isBasic(structuralType(t), info). func allBasic(t Type, info BasicInfo) bool { - switch u := under(t).(type) { - case *Basic: - return u.info&info != 0 - case *TypeParam: - return u.is(func(t *term) bool { return t != nil && isBasic(t.typ, info) }) + if tpar, _ := t.(*TypeParam); tpar != nil { + return tpar.is(func(t *term) bool { return t != nil && isBasic(t.typ, info) }) } - return false + return isBasic(t, info) } // hasName reports whether t has a name. This includes @@ -124,7 +121,7 @@ func comparable(T Type, seen map[Type]bool) bool { // assume invalid types to be comparable // to avoid follow-up errors return t.kind != UntypedNil - case *Pointer, *Interface, *Chan: + case *Pointer, *Chan: return true case *Struct: for _, f := range t.fields { @@ -135,7 +132,13 @@ func comparable(T Type, seen map[Type]bool) bool { return true case *Array: return comparable(t.elem, seen) + case *Interface: + if tparamIsIface && isTypeParam(T) { + return t.IsComparable() + } + return true case *TypeParam: + assert(!tparamIsIface) return t.iface().IsComparable() } return false @@ -146,9 +149,17 @@ func hasNil(t Type) bool { switch u := under(t).(type) { case *Basic: return u.kind == UnsafePointer - case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan: + case *Slice, *Pointer, *Signature, *Map, *Chan: + return true + case *Interface: + if tparamIsIface && isTypeParam(t) { + return u.typeSet().underIs(func(u Type) bool { + return u != nil && hasNil(u) + }) + } return true case *TypeParam: + assert(!tparamIsIface) return u.underIs(func(u Type) bool { return u != nil && hasNil(u) }) diff --git a/src/go/types/sizes.go b/src/go/types/sizes.go index 9a119138dd..a921525062 100644 --- a/src/go/types/sizes.go +++ b/src/go/types/sizes.go @@ -67,6 +67,7 @@ func (s *StdSizes) Alignof(T Type) int64 { case *Slice, *Interface: // Multiword data structures are effectively structs // in which each element has size WordSize. + assert(!tparamIsIface || !isTypeParam(T)) return s.WordSize case *Basic: // Strings are like slices and interfaces. diff --git a/src/go/types/struct.go b/src/go/types/struct.go index 84af8a3f48..53204dc381 100644 --- a/src/go/types/struct.go +++ b/src/go/types/struct.go @@ -143,24 +143,29 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) { check.later(func() { t, isPtr := deref(embeddedTyp) - switch t := under(t).(type) { + switch u := under(t).(type) { case *Basic: if t == Typ[Invalid] { // error was reported before return } // unsafe.Pointer is treated like a regular pointer - if t.kind == UnsafePointer { + if u.kind == UnsafePointer { check.error(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be unsafe.Pointer") } case *Pointer: check.error(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a pointer") case *TypeParam: + assert(!tparamIsIface) // This error code here is inconsistent with other error codes for // invalid embedding, because this restriction may be relaxed in the // future, and so it did not warrant a new error code. check.error(embeddedPos, _MisplacedTypeParam, "embedded field type cannot be a (pointer to a) type parameter") case *Interface: + if tparamIsIface && isTypeParam(t) { + check.error(embeddedPos, _MisplacedTypeParam, "embedded field type cannot be a (pointer to a) type parameter") + break + } if isPtr { check.error(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a pointer to an interface") } diff --git a/src/go/types/type.go b/src/go/types/type.go index 756bdcf0a5..dcf678a27a 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -21,8 +21,13 @@ type Type interface { // under must only be called when a type is known // to be fully set up. func under(t Type) Type { - if n := asNamed(t); n != nil { - return n.under() + switch t := t.(type) { + case *Named: + return t.under() + case *TypeParam: + if tparamIsIface { + return t.iface() + } } return t } diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index 731b746d05..084130fc74 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -9,6 +9,12 @@ import ( "sync/atomic" ) +// If set, the underlying type of a type parameter is +// is the underlying type of its type constraint, i.e., +// an interface. With that, a type parameter satisfies +// isInterface. +const tparamIsIface = false + // Note: This is a uint32 rather than a uint64 because the // respective 64 bit atomic instructions are not available // on all platforms. @@ -72,13 +78,21 @@ func (t *TypeParam) SetConstraint(bound Type) { t.bound = bound } -func (t *TypeParam) Underlying() Type { return t } -func (t *TypeParam) String() string { return TypeString(t, nil) } +func (t *TypeParam) Underlying() Type { + if tparamIsIface { + return t.iface() + } + return t +} + +func (t *TypeParam) String() string { return TypeString(t, nil) } // ---------------------------------------------------------------------------- // Implementation // iface returns the constraint interface of t. +// TODO(gri) If we make tparamIsIface the default, this should be renamed to under +// (similar to Named.under). func (t *TypeParam) iface() *Interface { bound := t.bound @@ -91,8 +105,13 @@ func (t *TypeParam) iface() *Interface { return &emptyInterface } case *Interface: + if tparamIsIface && isTypeParam(bound) { + // error is reported in Checker.collectTypeParams + return &emptyInterface + } ityp = u case *TypeParam: + assert(!tparamIsIface) // error is reported in Checker.collectTypeParams return &emptyInterface } diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index d0464aeaa0..d98080069c 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -266,6 +266,8 @@ func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_T var terms termlist switch u := under(typ).(type) { case *Interface: + // For now we don't permit type parameters as constraints. + assert(!isTypeParam(typ)) tset := computeInterfaceTypeSet(check, pos, u) // If typ is local, an error was already reported where typ is specified/defined. if check != nil && check.isImportedConstraint(typ) && !check.allowVersion(check.pkg, 1, 18) { @@ -365,6 +367,8 @@ func computeUnionTypeSet(check *Checker, pos token.Pos, utyp *Union) *_TypeSet { var terms termlist switch u := under(t.typ).(type) { case *Interface: + // For now we don't permit type parameters as constraints. + assert(!isTypeParam(t.typ)) terms = computeInterfaceTypeSet(check, pos, u).terms default: if t.typ == Typ[Invalid] { diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 89264ee9eb..c6ab7cd564 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -141,9 +141,15 @@ func (check *Checker) typ(e ast.Expr) Type { // constraint interface. func (check *Checker) varType(e ast.Expr) Type { typ := check.definedType(e, nil) - // We don't want to call under() (via toInterface) or complete interfaces while we - // are in the middle of type-checking parameter declarations that might belong to - // interface methods. Delay this check to the end of type-checking. + + // If we have a type parameter there's nothing to do. + if isTypeParam(typ) { + return typ + } + + // We don't want to call under() or complete interfaces while we are in + // the middle of type-checking parameter declarations that might belong + // to interface methods. Delay this check to the end of type-checking. check.later(func() { if t, _ := under(typ).(*Interface); t != nil { tset := computeInterfaceTypeSet(check, e.Pos(), t) // TODO(gri) is this the correct position? -- GitLab From 9a33945f2cc4b2108defdcdea80dc0ebe5af3c24 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 17 Nov 2021 10:42:13 -0500 Subject: [PATCH 2237/2500] go/types: set tparamsIsIface to true This is a port of CL 363155 from types2 to go/types. Change-Id: Ic24f8c88513599c8f4685f0b66d3782ac4e6831a Reviewed-on: https://go-review.googlesource.com/c/go/+/364717 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/typeparam.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index 084130fc74..f000d8f108 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -13,7 +13,7 @@ import ( // is the underlying type of its type constraint, i.e., // an interface. With that, a type parameter satisfies // isInterface. -const tparamIsIface = false +const tparamIsIface = true // Note: This is a uint32 rather than a uint64 because the // respective 64 bit atomic instructions are not available -- GitLab From a218365faeed6d62d3becabf0c8700f0e0b3a734 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Wed, 17 Nov 2021 13:03:13 -0800 Subject: [PATCH 2238/2500] cmd/go: skip broken fuzz test For #49047 Change-Id: If06ce033f7bfd23d640311f1be261afab8332028 Reviewed-on: https://go-review.googlesource.com/c/go/+/364758 Trust: Roland Shoemaker Run-TryBot: Roland Shoemaker Reviewed-by: Bryan C. Mills TryBot-Result: Go Bot --- src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt b/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt index 3764dcb915..5b1e26be24 100644 --- a/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt +++ b/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt @@ -1,3 +1,5 @@ +skip # https://golang.org/issue/49047 + # TODO(jayconrod): support shared memory on more platforms. [!darwin] [!linux] [!windows] skip -- GitLab From 0440fb833405a5c61ed0269af9c5897b03390bac Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 17 Nov 2021 11:07:44 -0800 Subject: [PATCH 2239/2500] runtime: make faketime more robust against GC When using faketime, only run the scavenger for one loop. It tries to run for 1 ms, but with faketime that calculation fails. Prohibit write barriers in the faketime write function, in case the GC wants to print something (e.g., with GODEBUG=gctrace=1). Fixes #49614 Change-Id: Iab5097fe78b6e0032ea8b493088264dfb25013c6 Reviewed-on: https://go-review.googlesource.com/c/go/+/364757 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Michael Knyszek TryBot-Result: Go Bot --- src/runtime/mgcscavenge.go | 5 +++++ src/runtime/time_fake.go | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/src/runtime/mgcscavenge.go b/src/runtime/mgcscavenge.go index 286aa1bbae..0399c2d21c 100644 --- a/src/runtime/mgcscavenge.go +++ b/src/runtime/mgcscavenge.go @@ -344,6 +344,11 @@ func bgscavenge(c chan int) { crit += float64(end - start) } released += r + + // When using fake time just do one loop. + if faketime != 0 { + break + } } if released == 0 { diff --git a/src/runtime/time_fake.go b/src/runtime/time_fake.go index 107f6be335..b5e0463588 100644 --- a/src/runtime/time_fake.go +++ b/src/runtime/time_fake.go @@ -41,6 +41,10 @@ func time_now() (sec int64, nsec int32, mono int64) { return faketime / 1e9, int32(faketime % 1e9), faketime } +// write is like the Unix write system call. +// We have to avoid write barriers to avoid potential deadlock +// on write calls. +//go:nowritebarrierrec func write(fd uintptr, p unsafe.Pointer, n int32) int32 { if !(fd == 1 || fd == 2) { // Do an ordinary write. -- GitLab From e3b48af57560e730a512d79f9d338aafac61f944 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 17 Nov 2021 18:56:46 -0500 Subject: [PATCH 2240/2500] go/types: remove a review comment in implicitTypeAndValue This is a clean port of CL 363440 from types2 to go/types. Change-Id: Ibbef41b5b599d5c88f7122670ab87aa5be512c0a Reviewed-on: https://go-review.googlesource.com/c/go/+/364894 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/expr.go | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 84eb59d1d0..0a3fa72c97 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -681,16 +681,14 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const return nil, nil, _InvalidUntypedConversion } case *TypeParam: - // TODO(gri) review this code - doesn't look quite right assert(!tparamIsIface) - ok := u.underIs(func(t Type) bool { - if t == nil { + if !u.underIs(func(u Type) bool { + if u == nil { return false } - target, _, _ := check.implicitTypeAndValue(x, t) - return target != nil - }) - if !ok { + t, _, _ := check.implicitTypeAndValue(x, u) + return t != nil + }) { return nil, nil, _InvalidUntypedConversion } // keep nil untyped (was bug #39755) @@ -699,15 +697,13 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const } case *Interface: if tparamIsIface && isTypeParam(target) { - // TODO(gri) review this code - doesn't look quite right - ok := u.typeSet().underIs(func(t Type) bool { - if t == nil { + if !u.typeSet().underIs(func(u Type) bool { + if u == nil { return false } - target, _, _ := check.implicitTypeAndValue(x, t) - return target != nil - }) - if !ok { + t, _, _ := check.implicitTypeAndValue(x, u) + return t != nil + }) { return nil, nil, _InvalidUntypedConversion } // keep nil untyped (was bug #39755) -- GitLab From 9115a7ba4a7e198befe26d69b740a34b495e1db5 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 17 Nov 2021 19:04:17 -0500 Subject: [PATCH 2241/2500] go/types: remove asNamed This is a port of CL 363441 from types2 to go/types, with an additional adjustment in methodset.go. Change-Id: Ia04dcfb70bb9f6af6f45175dee3334dba7b2768e Reviewed-on: https://go-review.googlesource.com/c/go/+/364895 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/decl.go | 2 +- src/go/types/lookup.go | 7 ++++--- src/go/types/methodset.go | 2 +- src/go/types/type.go | 9 --------- src/go/types/unify.go | 14 ++++++-------- src/go/types/universe.go | 2 +- 6 files changed, 13 insertions(+), 23 deletions(-) diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 4f28553aa6..600467620c 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -795,7 +795,7 @@ func (check *Checker) collectMethods(obj *TypeName) { // spec: "If the base type is a struct type, the non-blank method // and field names must be distinct." - base := asNamed(obj.typ) // shouldn't fail but be conservative + base, _ := obj.typ.(*Named) // shouldn't fail but be conservative if base != nil { u := base.under() if t, _ := u.(*Struct); t != nil { diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index 16a9890199..1462d30b30 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -50,8 +50,8 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o // Thus, if we have a named pointer type, proceed with the underlying // pointer type but discard the result if it is a method since we would // not have found it for T (see also issue 8590). - if t := asNamed(T); t != nil { - if p, _ := safeUnderlying(t).(*Pointer); p != nil { + if t, _ := T.(*Named); t != nil { + if p, _ := t.Underlying().(*Pointer); p != nil { obj, index, indirect = lookupFieldOrMethod(p, false, pkg, name) if _, ok := obj.(*Func); ok { return nil, nil, false @@ -114,7 +114,7 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o // If we have a named type, we may have associated methods. // Look for those first. - if named := asNamed(typ); named != nil { + if named, _ := typ.(*Named); named != nil { if seen[named] { // We have seen this type before, at a more shallow depth // (note that multiples of this type at the current depth @@ -129,6 +129,7 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o seen[named] = true // look for a matching attached method + named.resolve(nil) if i, m := lookupMethod(named.methods, pkg, name); m != nil { // potential match // caution: method may not have a proper signature yet diff --git a/src/go/types/methodset.go b/src/go/types/methodset.go index 89e4b57627..e17be7c41a 100644 --- a/src/go/types/methodset.go +++ b/src/go/types/methodset.go @@ -111,7 +111,7 @@ func NewMethodSet(T Type) *MethodSet { // If we have a named type, we may have associated methods. // Look for those first. - if named := asNamed(typ); named != nil { + if named, _ := typ.(*Named); named != nil { if seen[named] { // We have seen this type before, at a more shallow depth // (note that multiples of this type at the current depth diff --git a/src/go/types/type.go b/src/go/types/type.go index dcf678a27a..1d672135b8 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -87,12 +87,3 @@ func structuralType(typ Type) Type { } return nil } - -// If t is a defined type, asNamed returns that type (possibly after resolving it), otherwise it returns nil. -func asNamed(t Type) *Named { - e, _ := t.(*Named) - if e != nil { - e.resolve(nil) - } - return e -} diff --git a/src/go/types/unify.go b/src/go/types/unify.go index 6cd653aee1..5dcb35f6ec 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -241,14 +241,12 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { // If exact unification is known to fail because we attempt to // match a type name against an unnamed type literal, consider // the underlying type of the named type. - // (Subtle: We use hasName to include any type with a name (incl. - // basic types and type parameters. We use asNamed because we only - // want *Named types.) - switch { - case !hasName(x) && y != nil && asNamed(y) != nil: - return u.nify(x, under(y), p) - case x != nil && asNamed(x) != nil && !hasName(y): - return u.nify(under(x), y, p) + // (We use !hasName to exclude any type with a name, including + // basic types and type parameters; the rest are unamed types.) + if nx, _ := x.(*Named); nx != nil && !hasName(y) { + return u.nify(nx.under(), y, p) + } else if ny, _ := y.(*Named); ny != nil && !hasName(x) { + return u.nify(x, ny.under(), p) } } diff --git a/src/go/types/universe.go b/src/go/types/universe.go index e30ab12bc3..edda56fc0d 100644 --- a/src/go/types/universe.go +++ b/src/go/types/universe.go @@ -244,7 +244,7 @@ func def(obj Object) { return // nothing to do } // fix Obj link for named types - if typ := asNamed(obj.Type()); typ != nil { + if typ, _ := obj.Type().(*Named); typ != nil { typ.obj = obj.(*TypeName) } // exported identifiers go into package unsafe -- GitLab From b95bff0318150e0b2869079bf2c0068fb4bcb17c Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 17 Nov 2021 19:14:58 -0500 Subject: [PATCH 2242/2500] go/types: remove tparamIsIface flag and corresponding dead code This is a port of CL 363654 from types2 to go/types. Change-Id: I64041615ccc7f11f2e4ae395b063ec5141ccf2cf Reviewed-on: https://go-review.googlesource.com/c/go/+/364896 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/builtins.go | 27 ++---------- src/go/types/decl.go | 4 ++ src/go/types/expr.go | 19 +------- src/go/types/index.go | 89 ++------------------------------------ src/go/types/predicates.go | 18 +------- src/go/types/sizes.go | 7 ++- src/go/types/struct.go | 11 ++--- src/go/types/type.go | 4 +- src/go/types/typeparam.go | 17 +------- 9 files changed, 27 insertions(+), 169 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 5abfe8d35b..b547cddeb1 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -180,28 +180,10 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b } case *Interface: - if tparamIsIface && isTypeParam(x.typ) { - if t.typeSet().underIs(func(t Type) bool { - switch t := arrayPtrDeref(t).(type) { - case *Basic: - if isString(t) && id == _Len { - return true - } - case *Array, *Slice, *Chan: - return true - case *Map: - if id == _Len { - return true - } - } - return false - }) { - mode = value - } + if !isTypeParam(x.typ) { + break } - case *TypeParam: - assert(!tparamIsIface) - if t.underIs(func(t Type) bool { + if t.typeSet().underIs(func(t Type) bool { switch t := arrayPtrDeref(t).(type) { case *Basic: if isString(t) && id == _Len { @@ -829,9 +811,6 @@ func hasVarSize(t Type) bool { } case *Interface: return isTypeParam(t) - case *TypeParam: - assert(!tparamIsIface) - return true case *Named, *Union: unreachable() } diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 600467620c..c85087018c 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -725,6 +725,10 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list *ast.FieldList check.later(func() { for i, bound := range bounds { if isTypeParam(bound) { + // We may be able to allow this since it is now well-defined what + // the underlying type and thus type set of a type parameter is. + // But we may need some additional form of cycle detection within + // type parameter lists. check.error(posns[i], _MisplacedTypeParam, "cannot use a type parameter as constraint") } } diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 0a3fa72c97..e93a2bc7c8 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -599,7 +599,7 @@ func (check *Checker) convertUntyped(x *operand, target Type) { newType, val, code := check.implicitTypeAndValue(x, target) if code != 0 { t := target - if !tparamIsIface || !isTypeParam(target) { + if !isTypeParam(target) { t = safeUnderlying(target) } check.invalidConversion(code, x, t) @@ -680,23 +680,8 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const default: return nil, nil, _InvalidUntypedConversion } - case *TypeParam: - assert(!tparamIsIface) - if !u.underIs(func(u Type) bool { - if u == nil { - return false - } - t, _, _ := check.implicitTypeAndValue(x, u) - return t != nil - }) { - return nil, nil, _InvalidUntypedConversion - } - // keep nil untyped (was bug #39755) - if x.isNil() { - return Typ[UntypedNil], nil, 0 - } case *Interface: - if tparamIsIface && isTypeParam(target) { + if isTypeParam(target) { if !u.typeSet().underIs(func(u Type) bool { if u == nil { return false diff --git a/src/go/types/index.go b/src/go/types/index.go index 2ff33814e5..54398ad19b 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -101,97 +101,14 @@ func (check *Checker) indexExpr(x *operand, e *typeparams.IndexExpr) (isFuncInst return false case *Interface: - // Note: The body of this 'if' statement is the same as the body - // of the case for type parameters below. If we keep both - // these branches we should factor out the code. - if tparamIsIface && isTypeParam(x.typ) { - // TODO(gri) report detailed failure cause for better error messages - var key, elem Type // key != nil: we must have all maps - mode := variable // non-maps result mode - // TODO(gri) factor out closure and use it for non-typeparam cases as well - if typ.typeSet().underIs(func(u Type) bool { - l := int64(-1) // valid if >= 0 - var k, e Type // k is only set for maps - switch t := u.(type) { - case *Basic: - if isString(t) { - e = universeByte - mode = value - } - case *Array: - l = t.len - e = t.elem - if x.mode != variable { - mode = value - } - case *Pointer: - if t, _ := under(t.base).(*Array); t != nil { - l = t.len - e = t.elem - } - case *Slice: - e = t.elem - case *Map: - k = t.key - e = t.elem - } - if e == nil { - return false - } - if elem == nil { - // first type - length = l - key, elem = k, e - return true - } - // all map keys must be identical (incl. all nil) - // (that is, we cannot mix maps with other types) - if !Identical(key, k) { - return false - } - // all element types must be identical - if !Identical(elem, e) { - return false - } - // track the minimal length for arrays, if any - if l >= 0 && l < length { - length = l - } - return true - }) { - // For maps, the index expression must be assignable to the map key type. - if key != nil { - index := check.singleIndex(e) - if index == nil { - x.mode = invalid - return false - } - var k operand - check.expr(&k, index) - check.assignment(&k, key, "map index") - // ok to continue even if indexing failed - map element type is known - x.mode = mapindex - x.typ = elem - x.expr = e - return false - } - - // no maps - valid = true - x.mode = mode - x.typ = elem - } + if !isTypeParam(x.typ) { + break } - case *TypeParam: - // Note: The body of this case is the same as the body of the 'if' - // statement in the interface case above. If we keep both - // these branches we should factor out the code. // TODO(gri) report detailed failure cause for better error messages - assert(!tparamIsIface) var key, elem Type // key != nil: we must have all maps mode := variable // non-maps result mode // TODO(gri) factor out closure and use it for non-typeparam cases as well - if typ.underIs(func(u Type) bool { + if typ.typeSet().underIs(func(u Type) bool { l := int64(-1) // valid if >= 0 var k, e Type // k is only set for maps switch t := u.(type) { diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 5204eb0c29..229a616eac 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -133,13 +133,7 @@ func comparable(T Type, seen map[Type]bool) bool { case *Array: return comparable(t.elem, seen) case *Interface: - if tparamIsIface && isTypeParam(T) { - return t.IsComparable() - } - return true - case *TypeParam: - assert(!tparamIsIface) - return t.iface().IsComparable() + return !isTypeParam(T) || t.IsComparable() } return false } @@ -152,15 +146,7 @@ func hasNil(t Type) bool { case *Slice, *Pointer, *Signature, *Map, *Chan: return true case *Interface: - if tparamIsIface && isTypeParam(t) { - return u.typeSet().underIs(func(u Type) bool { - return u != nil && hasNil(u) - }) - } - return true - case *TypeParam: - assert(!tparamIsIface) - return u.underIs(func(u Type) bool { + return !isTypeParam(t) || u.typeSet().underIs(func(u Type) bool { return u != nil && hasNil(u) }) } diff --git a/src/go/types/sizes.go b/src/go/types/sizes.go index a921525062..dd4b78969f 100644 --- a/src/go/types/sizes.go +++ b/src/go/types/sizes.go @@ -67,7 +67,9 @@ func (s *StdSizes) Alignof(T Type) int64 { case *Slice, *Interface: // Multiword data structures are effectively structs // in which each element has size WordSize. - assert(!tparamIsIface || !isTypeParam(T)) + // Type parameters lead to variable sizes/alignments; + // StdSizes.Alignof won't be called for them. + assert(!isTypeParam(T)) return s.WordSize case *Basic: // Strings are like slices and interfaces. @@ -152,6 +154,9 @@ func (s *StdSizes) Sizeof(T Type) int64 { offsets := s.Offsetsof(t.fields) return offsets[n-1] + s.Sizeof(t.fields[n-1].typ) case *Interface: + // Type parameters lead to variable sizes/alignments; + // StdSizes.Sizeof won't be called for them. + assert(!isTypeParam(T)) return s.WordSize * 2 case *TypeParam, *Union: unreachable() diff --git a/src/go/types/struct.go b/src/go/types/struct.go index 53204dc381..d6c56341f0 100644 --- a/src/go/types/struct.go +++ b/src/go/types/struct.go @@ -155,14 +155,11 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) { } case *Pointer: check.error(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a pointer") - case *TypeParam: - assert(!tparamIsIface) - // This error code here is inconsistent with other error codes for - // invalid embedding, because this restriction may be relaxed in the - // future, and so it did not warrant a new error code. - check.error(embeddedPos, _MisplacedTypeParam, "embedded field type cannot be a (pointer to a) type parameter") case *Interface: - if tparamIsIface && isTypeParam(t) { + if isTypeParam(t) { + // The error code here is inconsistent with other error codes for + // invalid embedding, because this restriction may be relaxed in the + // future, and so it did not warrant a new error code. check.error(embeddedPos, _MisplacedTypeParam, "embedded field type cannot be a (pointer to a) type parameter") break } diff --git a/src/go/types/type.go b/src/go/types/type.go index 1d672135b8..97de5e49d1 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -25,9 +25,7 @@ func under(t Type) Type { case *Named: return t.under() case *TypeParam: - if tparamIsIface { - return t.iface() - } + return t.iface() } return t } diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index f000d8f108..7cce1f7e35 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -9,12 +9,6 @@ import ( "sync/atomic" ) -// If set, the underlying type of a type parameter is -// is the underlying type of its type constraint, i.e., -// an interface. With that, a type parameter satisfies -// isInterface. -const tparamIsIface = true - // Note: This is a uint32 rather than a uint64 because the // respective 64 bit atomic instructions are not available // on all platforms. @@ -79,10 +73,7 @@ func (t *TypeParam) SetConstraint(bound Type) { } func (t *TypeParam) Underlying() Type { - if tparamIsIface { - return t.iface() - } - return t + return t.iface() } func (t *TypeParam) String() string { return TypeString(t, nil) } @@ -105,15 +96,11 @@ func (t *TypeParam) iface() *Interface { return &emptyInterface } case *Interface: - if tparamIsIface && isTypeParam(bound) { + if isTypeParam(bound) { // error is reported in Checker.collectTypeParams return &emptyInterface } ityp = u - case *TypeParam: - assert(!tparamIsIface) - // error is reported in Checker.collectTypeParams - return &emptyInterface } // If we don't have an interface, wrap constraint into an implicit interface. -- GitLab From 2463b4fcafbd59998ea4c81b0fd91a697ad02c15 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 17 Nov 2021 19:20:52 -0500 Subject: [PATCH 2243/2500] go/types: simplify under() and fix a crash This is a port of CL 363665 from types2 to go/types. Change-Id: I20c4e20ab97f1e4de66a29095dc4a9b160810fe5 Reviewed-on: https://go-review.googlesource.com/c/go/+/364897 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/lookup.go | 7 +++++++ src/go/types/testdata/check/cycles.src | 1 + src/go/types/type.go | 7 ++----- src/go/types/typexpr.go | 1 + 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index 1462d30b30..e3c43a94f7 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -469,6 +469,13 @@ func (check *Checker) assertableTo(V *Interface, T Type) (method, wrongType *Fun // Otherwise it returns (typ, false). func deref(typ Type) (Type, bool) { if p, _ := typ.(*Pointer); p != nil { + // p.base should never be nil, but be conservative + if p.base == nil { + if debug { + panic("pointer with nil base type (possibly due to an invalid cyclic declaration)") + } + return Typ[Invalid], true + } return p.base, true } return typ, false diff --git a/src/go/types/testdata/check/cycles.src b/src/go/types/testdata/check/cycles.src index 218b4cad6a..27b6111822 100644 --- a/src/go/types/testdata/check/cycles.src +++ b/src/go/types/testdata/check/cycles.src @@ -45,6 +45,7 @@ type ( // pointers P0 *P0 + PP *struct{ PP.f /* ERROR no field or method f */ } // functions F0 func(F0) diff --git a/src/go/types/type.go b/src/go/types/type.go index 97de5e49d1..6611c25f25 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -21,13 +21,10 @@ type Type interface { // under must only be called when a type is known // to be fully set up. func under(t Type) Type { - switch t := t.(type) { - case *Named: + if t, _ := t.(*Named); t != nil { return t.under() - case *TypeParam: - return t.iface() } - return t + return t.Underlying() } // If x and y are identical, match returns x. diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index c6ab7cd564..5664d8175f 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -308,6 +308,7 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) { case *ast.StarExpr: typ := new(Pointer) + typ.base = Typ[Invalid] // avoid nil base in invalid recursive type declaration def.setUnderlying(typ) typ.base = check.varType(e.X) return typ -- GitLab From 353cb71ea29e02a41f77b7576d658de4515e264d Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 17 Nov 2021 19:22:22 -0500 Subject: [PATCH 2244/2500] go/types: optimize common case in structuralType This is a port of CL 363668 from types2 to go/types. Change-Id: Ic55acb2e27f57c33467cef2f687cd695e092ba6d Reviewed-on: https://go-review.googlesource.com/c/go/+/364898 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/type.go | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/go/types/type.go b/src/go/types/type.go index 6611c25f25..e283c65289 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -56,15 +56,20 @@ func match(x, y Type) Type { return nil } -// If typ is a type parameter, structuralType returns the single underlying -// type of all types in the corresponding type constraint if it exists, or -// nil otherwise. If the type set contains only unrestricted and restricted -// channel types (with identical element types), the single underlying type -// is the restricted channel type if the restrictions are always the same. -// If typ is not a type parameter, structuralType returns the underlying type. -func structuralType(typ Type) Type { +// If t is not a type parameter, structuralType returns the underlying type. +// If t is a type parameter, structuralType returns the single underlying +// type of all types in its type set if it exists, or nil otherwise. If the +// type set contains only unrestricted and restricted channel types (with +// identical element types), the single underlying type is the restricted +// channel type if the restrictions are always the same, or nil otherwise. +func structuralType(t Type) Type { + tpar, _ := t.(*TypeParam) + if tpar == nil { + return under(t) + } + var su Type - if underIs(typ, func(u Type) bool { + if tpar.underIs(func(u Type) bool { if u == nil { return false } -- GitLab From ce7e5013a68ef4572b9fa439b1402145ef710631 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 17 Nov 2021 19:26:37 -0500 Subject: [PATCH 2245/2500] go/types: allow slicing for operands with []byte|string type sets This is a port of CL 363662 from types2 to go/types. An error message was adjusted to be on the operand in test data. Change-Id: I4d2d69976f4f05e0d89ba1c6bf8b3e4cf1a82316 Reviewed-on: https://go-review.googlesource.com/c/go/+/364899 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/builtins.go | 23 +++----------- src/go/types/index.go | 4 +-- src/go/types/testdata/check/typeparams.go2 | 4 +++ src/go/types/type.go | 37 ++++++++++++++++++++++ 4 files changed, 47 insertions(+), 21 deletions(-) diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index b547cddeb1..daeed81ed8 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -342,26 +342,11 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b if y.mode == invalid { return } - // src, _ := structuralType(y.typ).(*Slice); but also accepts strings - var src *Slice - var elem Type // == src.elem if valid - if underIs(y.typ, func(u Type) bool { - switch u := u.(type) { - case *Basic: - if isString(u) && (elem == nil || Identical(elem, universeByte)) { - elem = universeByte - return true - } - case *Slice: - if elem == nil || Identical(elem, u.elem) { - elem = u.elem - return true - } - } - return false - }) { - src = NewSlice(elem) + src0 := structuralString(y.typ) + if src0 != nil && isString(src0) { + src0 = NewSlice(universeByte) } + src, _ := src0.(*Slice) if dst == nil || src == nil { check.invalidArg(x, _InvalidCopy, "copy expects slice arguments; found %s and %s", x, &y) diff --git a/src/go/types/index.go b/src/go/types/index.go index 54398ad19b..ace9ee06ab 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -214,7 +214,7 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { valid := false length := int64(-1) // valid if >= 0 - switch u := structuralType(x.typ).(type) { + switch u := structuralString(x.typ).(type) { case nil: check.invalidOp(x, _NonSliceableOperand, "cannot slice %s: %s has no structural type", x, x.typ) x.mode = invalid @@ -233,7 +233,7 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { } // spec: "For untyped string operands the result // is a non-constant value of type string." - if u.kind == UntypedString { + if isUntyped(x.typ) { x.typ = Typ[String] } } diff --git a/src/go/types/testdata/check/typeparams.go2 b/src/go/types/testdata/check/typeparams.go2 index fdbb7a2740..0d3b6ea527 100644 --- a/src/go/types/testdata/check/typeparams.go2 +++ b/src/go/types/testdata/check/typeparams.go2 @@ -136,6 +136,10 @@ type myByte2 []byte func _[T interface{ []byte | myByte1 | myByte2 }] (x T, i, j, k int) { var _ T = x[i:j:k] } func _[T interface{ []byte | myByte1 | []int }] (x T, i, j, k int) { var _ T = x /* ERROR no structural type */ [i:j:k] } +func _[T interface{ []byte | myByte1 | myByte2 | string }] (x T, i, j, k int) { var _ T = x[i:j] } +func _[T interface{ []byte | myByte1 | myByte2 | string }] (x T, i, j, k int) { var _ T = x /* ERROR 3-index slice of string */ [i:j:k] } +func _[T interface{ []byte | myByte1 | []int | string }] (x T, i, j, k int) { var _ T = x /* ERROR no structural type */ [i:j] } + // len/cap built-ins func _[T any](x T) { _ = len(x /* ERROR invalid argument */ ) } diff --git a/src/go/types/type.go b/src/go/types/type.go index e283c65289..099449c8b9 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -87,3 +87,40 @@ func structuralType(t Type) Type { } return nil } + +// structuralString is like structuralType but also considers []byte +// and strings as identical. In this case, if successful and we saw +// a string, the result is of type (possibly untyped) string. +func structuralString(t Type) Type { + tpar, _ := t.(*TypeParam) + if tpar == nil { + return under(t) // string or untyped string + } + + var su Type + hasString := false + if tpar.underIs(func(u Type) bool { + if u == nil { + return false + } + if isString(u) { + u = NewSlice(universeByte) + hasString = true + } + if su != nil { + u = match(su, u) + if u == nil { + return false + } + } + // su == nil || match(su, u) != nil + su = u + return true + }) { + if hasString { + return Typ[String] + } + return su + } + return nil +} -- GitLab From 3404ee3e86b9f4eab55d2451dcd9db5b4cd9ed4a Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 17 Nov 2021 19:29:13 -0500 Subject: [PATCH 2246/2500] go/types: move match function to end of file (cleanup) This is a port of CL 363669 from types2 to go/types. Change-Id: Id1f375ff5708dab528144e30ce16d24d6fdf7d00 Reviewed-on: https://go-review.googlesource.com/c/go/+/364900 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/type.go | 58 ++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/go/types/type.go b/src/go/types/type.go index 099449c8b9..3acb19c412 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -27,35 +27,6 @@ func under(t Type) Type { return t.Underlying() } -// If x and y are identical, match returns x. -// If x and y are identical channels but for their direction -// and one of them is unrestricted, match returns the channel -// with the restricted direction. -// In all other cases, match returns nil. -func match(x, y Type) Type { - // Common case: we don't have channels. - if Identical(x, y) { - return x - } - - // We may have channels that differ in direction only. - if x, _ := x.(*Chan); x != nil { - if y, _ := y.(*Chan); y != nil && Identical(x.elem, y.elem) { - // We have channels that differ in direction only. - // If there's an unrestricted channel, select the restricted one. - switch { - case x.dir == SendRecv: - return y - case y.dir == SendRecv: - return x - } - } - } - - // types are different - return nil -} - // If t is not a type parameter, structuralType returns the underlying type. // If t is a type parameter, structuralType returns the single underlying // type of all types in its type set if it exists, or nil otherwise. If the @@ -124,3 +95,32 @@ func structuralString(t Type) Type { } return nil } + +// If x and y are identical, match returns x. +// If x and y are identical channels but for their direction +// and one of them is unrestricted, match returns the channel +// with the restricted direction. +// In all other cases, match returns nil. +func match(x, y Type) Type { + // Common case: we don't have channels. + if Identical(x, y) { + return x + } + + // We may have channels that differ in direction only. + if x, _ := x.(*Chan); x != nil { + if y, _ := y.(*Chan); y != nil && Identical(x.elem, y.elem) { + // We have channels that differ in direction only. + // If there's an unrestricted channel, select the restricted one. + switch { + case x.dir == SendRecv: + return y + case y.dir == SendRecv: + return x + } + } + } + + // types are different + return nil +} -- GitLab From 72f0976ac45fcb7f3fd6d47a3ac5c96a78edd59d Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 17 Nov 2021 19:37:04 -0500 Subject: [PATCH 2247/2500] go/types: better position for "3-index slice of string" error This is a port of CL 363670 from types2 to go/types. Change-Id: I2ac3a5f86bb4eafddd2854e193083b2b737e29b6 Reviewed-on: https://go-review.googlesource.com/c/go/+/364901 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/index.go | 6 +++++- src/go/types/testdata/check/expr3.src | 4 ++-- src/go/types/testdata/check/typeparams.go2 | 4 ++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/go/types/index.go b/src/go/types/index.go index ace9ee06ab..6ea25bc764 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -223,7 +223,11 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { case *Basic: if isString(u) { if e.Slice3 { - check.invalidOp(x, _InvalidSliceExpr, "3-index slice of string") + at := e.Max + if at == nil { + at = e // e.Index[2] should be present but be careful + } + check.invalidOp(at, _InvalidSliceExpr, "3-index slice of string") x.mode = invalid return } diff --git a/src/go/types/testdata/check/expr3.src b/src/go/types/testdata/check/expr3.src index 0f15c15a55..a63542b843 100644 --- a/src/go/types/testdata/check/expr3.src +++ b/src/go/types/testdata/check/expr3.src @@ -109,8 +109,8 @@ func indexes() { _ = t[- /* ERROR "negative" */ 1] _ = t[- /* ERROR "negative" */ 1 :] _ = t[: - /* ERROR "negative" */ 1] - _ = t /* ERROR "3-index slice of string" */ [1:2:3] - _ = "foo" /* ERROR "3-index slice of string" */ [1:2:3] + _ = t[1:2:3 /* ERROR "3-index slice of string" */ ] + _ = "foo"[1:2:3 /* ERROR "3-index slice of string" */ ] var t0 byte t0 = t[0] _ = t0 diff --git a/src/go/types/testdata/check/typeparams.go2 b/src/go/types/testdata/check/typeparams.go2 index 0d3b6ea527..e3aca4ccb0 100644 --- a/src/go/types/testdata/check/typeparams.go2 +++ b/src/go/types/testdata/check/typeparams.go2 @@ -129,7 +129,7 @@ func _[T interface{ ~[10]E }, E any] (x T, i, j, k int) { var _ []E = x[i:j:k] } func _[T interface{ ~[]byte }] (x T, i, j, k int) { var _ T = x[i:j] } func _[T interface{ ~[]byte }] (x T, i, j, k int) { var _ T = x[i:j:k] } func _[T interface{ ~string }] (x T, i, j, k int) { var _ T = x[i:j] } -func _[T interface{ ~string }] (x T, i, j, k int) { var _ T = x /* ERROR 3-index slice of string */ [i:j:k] } +func _[T interface{ ~string }] (x T, i, j, k int) { var _ T = x[i:j:k /* ERROR 3-index slice of string */ ] } type myByte1 []byte type myByte2 []byte @@ -137,7 +137,7 @@ func _[T interface{ []byte | myByte1 | myByte2 }] (x T, i, j, k int) { var _ T = func _[T interface{ []byte | myByte1 | []int }] (x T, i, j, k int) { var _ T = x /* ERROR no structural type */ [i:j:k] } func _[T interface{ []byte | myByte1 | myByte2 | string }] (x T, i, j, k int) { var _ T = x[i:j] } -func _[T interface{ []byte | myByte1 | myByte2 | string }] (x T, i, j, k int) { var _ T = x /* ERROR 3-index slice of string */ [i:j:k] } +func _[T interface{ []byte | myByte1 | myByte2 | string }] (x T, i, j, k int) { var _ T = x[i:j:k /* ERROR 3-index slice of string */ ] } func _[T interface{ []byte | myByte1 | []int | string }] (x T, i, j, k int) { var _ T = x /* ERROR no structural type */ [i:j] } // len/cap built-ins -- GitLab From f1cc5294290b33889d48a3185b3c3711531881e0 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 17 Nov 2021 19:45:49 -0500 Subject: [PATCH 2248/2500] go/types: better position for invalid slice indices error This is a port of CL 363671 from types2 to go/types. Also adjust the error message to match types2 ("invalid" vs "swapped"). Change-Id: I662a73c915814fea14bfcb1ebde0fbf39589f022 Reviewed-on: https://go-review.googlesource.com/c/go/+/364902 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/index.go | 10 +++++++--- src/go/types/testdata/check/expr3.src | 20 ++++++++++---------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/go/types/index.go b/src/go/types/index.go index 6ea25bc764..db4732c8e0 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -310,9 +310,13 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { L: for i, x := range ind[:len(ind)-1] { if x > 0 { - for _, y := range ind[i+1:] { - if y >= 0 && x > y { - check.errorf(inNode(e, e.Rbrack), _SwappedSliceIndices, "swapped slice indices: %d > %d", x, y) + for j, y := range ind[i+1:] { + if y >= 0 && y < x { + // The value y corresponds to the expression e.Index[i+1+j]. + // Because y >= 0, it must have been set from the expression + // when checking indices and thus e.Index[i+1+j] is not nil. + at := []ast.Expr{e.Low, e.High, e.Max}[i+1+j] + check.errorf(at, _SwappedSliceIndices, "invalid slice indices: %d < %d", y, x) break L // only report one error, ok to continue } } diff --git a/src/go/types/testdata/check/expr3.src b/src/go/types/testdata/check/expr3.src index a63542b843..5117a0373b 100644 --- a/src/go/types/testdata/check/expr3.src +++ b/src/go/types/testdata/check/expr3.src @@ -44,9 +44,9 @@ func indexes() { _ = a[:10:10] _ = a[:11 /* ERROR "index .* out of bounds" */ :10] _ = a[:10:11 /* ERROR "index .* out of bounds" */ ] - _ = a[10:0:10] /* ERROR swapped slice indices" */ - _ = a[0:10:0] /* ERROR "swapped slice indices" */ - _ = a[10:0:0] /* ERROR "swapped slice indices" */ + _ = a[10:0 /* ERROR "invalid slice indices" */ :10] + _ = a[0:10:0 /* ERROR "invalid slice indices" */ ] + _ = a[10:0 /* ERROR "invalid slice indices" */:0] _ = &a /* ERROR "cannot take address" */ [:10] pa := &a @@ -62,9 +62,9 @@ func indexes() { _ = pa[:10:10] _ = pa[:11 /* ERROR "index .* out of bounds" */ :10] _ = pa[:10:11 /* ERROR "index .* out of bounds" */ ] - _ = pa[10:0:10] /* ERROR "swapped slice indices" */ - _ = pa[0:10:0] /* ERROR "swapped slice indices" */ - _ = pa[10:0:0] /* ERROR "swapped slice indices" */ + _ = pa[10:0 /* ERROR "invalid slice indices" */ :10] + _ = pa[0:10:0 /* ERROR "invalid slice indices" */ ] + _ = pa[10:0 /* ERROR "invalid slice indices" */ :0] _ = &pa /* ERROR "cannot take address" */ [:10] var b [0]int @@ -82,16 +82,16 @@ func indexes() { _ = s[: - /* ERROR "negative" */ 1] _ = s[0] _ = s[1:2] - _ = s[2:1] /* ERROR "swapped slice indices" */ + _ = s[2:1 /* ERROR "invalid slice indices" */ ] _ = s[2:] _ = s[: 1 /* ERROR "overflows" */ <<100] _ = s[1 /* ERROR "overflows" */ <<100 :] _ = s[1 /* ERROR "overflows" */ <<100 : 1 /* ERROR "overflows" */ <<100] _ = s[: /* ERROR "2nd index required" */ : /* ERROR "3rd index required" */ ] _ = s[:10:10] - _ = s[10:0:10] /* ERROR "swapped slice indices" */ - _ = s[0:10:0] /* ERROR "swapped slice indices" */ - _ = s[10:0:0] /* ERROR "swapped slice indices" */ + _ = s[10:0 /* ERROR "invalid slice indices" */ :10] + _ = s[0:10:0 /* ERROR "invalid slice indices" */ ] + _ = s[10:0 /* ERROR "invalid slice indices" */ :0] _ = &s /* ERROR "cannot take address" */ [:10] var m map[string]int -- GitLab From d8f7a64519695f037cce8696c5c3b7216fd4a680 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Wed, 17 Nov 2021 16:12:43 -0800 Subject: [PATCH 2249/2500] test: make issue8606b test more robust Use actual unmapped memory instead of small integers to make pointers that will fault when accessed. Fixes #49562 Change-Id: I2c60c97cf80494dd962a07d10cfeaff6a00f4f8e Reviewed-on: https://go-review.googlesource.com/c/go/+/364914 Trust: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- test/fixedbugs/issue8606b.go | 37 +++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/test/fixedbugs/issue8606b.go b/test/fixedbugs/issue8606b.go index 448ea566f0..41b9a3d00e 100644 --- a/test/fixedbugs/issue8606b.go +++ b/test/fixedbugs/issue8606b.go @@ -1,4 +1,5 @@ // run +// +build linux darwin // Copyright 2020 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style @@ -20,20 +21,10 @@ package main import ( "fmt" "reflect" + "syscall" "unsafe" ) -func bad1() string { - s := "foo" - (*reflect.StringHeader)(unsafe.Pointer(&s)).Data = 1 // write bad value to data ptr - return s -} -func bad2() string { - s := "foo" - (*reflect.StringHeader)(unsafe.Pointer(&s)).Data = 2 // write bad value to data ptr - return s -} - type SI struct { s string i int @@ -45,15 +36,31 @@ type SS struct { } func main() { + bad1 := "foo" + bad2 := "foo" + + p := syscall.Getpagesize() + b, err := syscall.Mmap(-1, 0, p, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANON|syscall.MAP_PRIVATE) + if err != nil { + panic(err) + } + err = syscall.Mprotect(b, syscall.PROT_NONE) + if err != nil { + panic(err) + } + // write inaccessible pointers as the data fields of bad1 and bad2. + (*reflect.StringHeader)(unsafe.Pointer(&bad1)).Data = uintptr(unsafe.Pointer(&b[0])) + (*reflect.StringHeader)(unsafe.Pointer(&bad2)).Data = uintptr(unsafe.Pointer(&b[1])) + for _, test := range []struct { a, b interface{} }{ - {SI{s: bad1(), i: 1}, SI{s: bad2(), i: 2}}, - {SS{s: bad1(), t: "a"}, SS{s: bad2(), t: "aa"}}, - {SS{s: "a", t: bad1()}, SS{s: "b", t: bad2()}}, + {SI{s: bad1, i: 1}, SI{s: bad2, i: 2}}, + {SS{s: bad1, t: "a"}, SS{s: bad2, t: "aa"}}, + {SS{s: "a", t: bad1}, SS{s: "b", t: bad2}}, // This one would panic because the length of both strings match, and we check // the body of the bad strings before the body of the good strings. - //{SS{s: bad1(), t: "a"}, SS{s: bad2(), t: "b"}}, + //{SS{s: bad1, t: "a"}, SS{s: bad2, t: "b"}}, } { if test.a == test.b { panic(fmt.Sprintf("values %#v and %#v should not be equal", test.a, test.b)) -- GitLab From f6647f2e3bc0b803a67c97a7d5d8733cefbd5d5b Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 10 Nov 2021 09:44:58 -0800 Subject: [PATCH 2250/2500] spec: generalize method sets and interface types to type sets This is the first of several CLs that update the existing Go 1.17 spec for type parameters. This CL updates the section on method sets and interface types. It also adds "any", "comparable" to the list of predeclared identifiers. Change-Id: I0ce25dc02791c33150c0d949528512610faf3eab Reviewed-on: https://go-review.googlesource.com/c/go/+/362999 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Ian Lance Taylor --- doc/go_spec.html | 245 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 207 insertions(+), 38 deletions(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index 0b374e7bfb..63bc6a546e 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,9 +1,18 @@ +

Draft Go 1.18 Specification - Work in Progress

+ +

+ +For the pre-Go1.18 spec see +The Go Programming Language Specification. + +

+

Introduction

@@ -266,7 +275,7 @@ The following character sequences represent operators * ^ *= ^= <- > >= { } / << /= <<= ++ = := , ; % >> %= >>= -- ! ... . : - &^ &^= + &^ &^= ~

Integer literals

@@ -829,27 +838,41 @@ The underlying type of []B1, B3, and B4 i

Method sets

+

-A type has a (possibly empty) method set associated with it. -The method set of an interface type is its interface. -The method set of any other type T consists of all +The method set of a type determines the methods that can be +called on an operand of that type. +Every type has a (possibly empty) method set associated with it: +

+ +
    +
  • The method set of a defined type T consists of all methods declared with receiver type T. -The method set of the corresponding pointer type *T -is the set of all methods declared with receiver *T or T -(that is, it also contains the method set of T). -Further rules apply to structs containing embedded fields, as described -in the section on struct types. +
  • + +
  • +The method set of a pointer *T +to a defined type *T +(where T is neither a pointer nor an interface) +is the set of all methods declared with receiver *T or T. +
  • + +
  • The method set of an interface type is the intersection +of the method sets of each type in the interface's type set +(the resulting method set is usually just the set of declared methods in the interface). +
  • +
+ +

+Further rules apply to structs (and pointer to structs) containing embedded fields, +as described in the section on struct types. Any other type has an empty method set. -In a method set, each method must have a -unique -non-blank method name.

-The method set of a type determines the interfaces that the -type implements -and the methods that can be called -using a receiver of that type. +In a method set, each method must have a +unique +non-blank method name.

Boolean types

@@ -1236,23 +1259,33 @@ func(n int) func(p *T)

Interface types

-An interface type specifies a method set called its interface. -A variable of interface type can store a value of any type with a method set -that is any superset of the interface. Such a type is said to -implement the interface. +An interface type defines a type set. +A variable of interface type can store a value of any type that is in the type +set of the interface. Such a type is said to implement the interface. The value of an uninitialized variable of interface type is nil.

-InterfaceType      = "interface" "{" { ( MethodSpec | InterfaceTypeName ) ";" } "}" .
-MethodSpec         = MethodName Signature .
-MethodName         = identifier .
-InterfaceTypeName  = TypeName .
+InterfaceType  = "interface" "{" { InterfaceElem ";" } "}" .
+InterfaceElem  = MethodElem | TypeElem .
+MethodElem     = MethodName Signature .
+MethodName     = identifier .
+TypeElem       = TypeTerm { "|" TypeTerm } .
+TypeTerm       = [ "~" ] Type .
 

-An interface type may specify methods explicitly through method specifications, -or it may embed methods of other interfaces through interface type names. +An interface type is specified by a list of interface elements. +An interface element is either a method or a type element, +where a type element is a union of one or more type terms. +A type term is either a single type or a single underlying type. +

+ +

+In its most basic form an interface specifies a (possibly empty) list of methods. +The type set defined by such an interface is the set of types which implement all of +those methods, and the corresponding method set consists +exactly of the methods specified by the interface.

@@ -1297,15 +1330,19 @@ then the File interface is implemented by both S1 and
 

-A type implements any interface comprising any subset of its methods -and may therefore implement several distinct interfaces. For -instance, all types implement the empty interface: +Every type that is a member of the type set of an interface implements that interface. +Any given type may implement several distinct interfaces. +For instance, all types implement the empty interface which stands for the set of all types:

 interface{}
 
+

+For convenience, the predeclared type any is an alias for the empty interface. +

+

Similarly, consider this interface specification, which appears within a type declaration @@ -1334,12 +1371,16 @@ as the File interface.

-An interface T may use a (possibly qualified) interface type -name E in place of a method specification. This is called +In a slightly more general form +an interface T may use a (possibly qualified) interface type +name E as an interface element. This is called embedding interface E in T. -The method set of T is the union -of the method sets of T’s explicitly declared methods and of -T’s embedded interfaces. +The type set of T is the intersection of the type sets +defined by T's explicitly declared methods and the type sets +of T’s embedded interfaces. +In other words, the type set of T is the set of all types that implement all the +explicitly declared methods of T and also all the methods of +E.

@@ -1361,8 +1402,7 @@ type ReadWriter interface {
 

-A union of method sets contains the (exported and non-exported) -methods of each method set exactly once, and methods with the +When embedding interfaces, methods with the same names must have identical signatures.

@@ -1374,6 +1414,134 @@ type ReadCloser interface { }
+

+Finally, in their most general form, an interface element may be an arbitrary type +T, a type term of the form ~T, or a union of type terms +T1 | T2 | … Tn. +Together with method specifications, these elements enable the precise +definition of an interface's type set as follows: +

+ +
    +
  • The type set of the empty interface is the set of all types. +
  • + +
  • The type set of a non-empty interface is the intersection of the type sets + of its interface elements. +
  • + +
  • The type set of a method specification is the set of types + whose method sets include that method. +
  • + +
  • The type set of a non-interface type is the set consisting + of just that type. +
  • + +
  • The type set of a term of the form ~T + is the set of types whose underlying type is T. +
  • + +
  • The type set of a union of terms T1 | T2 | … Tn + is the union of the type sets of the terms. +
  • +
+ +
+// An interface representing only the type int.
+interface {
+	int
+}
+
+// An interface representing all types with underlying type int.
+interface {
+	~int
+}
+
+// An interface representing all types with underlying type int which implement the String method.
+interface {
+	~int
+	String() string
+}
+
+// An interface representing an empty type set: there is no type that is both an int and a string.
+interface {
+	int
+	string
+}
+
+ +

+In a term of the form ~T, the underlying type of T +must be itself, and T cannot be an interface. +

+ +
+type MyInt int
+
+interface {
+	~[]byte  // the underlying type of []byte is itself
+	~MyInt   // illegal: the underlying type of MyInt is not MyInt
+	~error   // illegal: error is an interface
+}
+
+ +

+Union expressions denote unions of type sets: +

+ +
+// The Floats interface represents all floating-point types
+// (including any named types whose underlying types are
+// either float32 or float64).
+type Floats interface {
+	~float32 | ~float64
+}
+
+ +

+In a union expression, a term cannot be a type parameter, and the type sets of all +non-interface terms must be pairwise disjoint (the pairwise intersection of the type sets must be empty). +Given a type parameter P: +

+ +
+interface {
+	P                 // illegal: the term P is a type parameter
+	int | P           // illegal: the term P is a type parameter
+	~int | MyInt      // illegal: the type sets for ~int and MyInt are not disjoint (~int includes MyInt)
+	float32 | Floats  // overlapping type sets but Floats is an interface
+}
+
+ +

+Implementation restriction: +A union expression with more than one term cannot contain interface types +with non-empty method sets. +

+ +

+Interfaces that contain union or tilde terms (not just methods) may only be used +as type constraints, or as elements of other interfaces used as constraints. They +cannot be the types of values or variables, or components of other, non-interface types. +

+ +
+var x Floats                     // illegal: Floats is restricted by float32 and float64
+
+var x interface{} = Floats(nil)  // illegal
+
+type Floatish struct {
+	f Floats                 // illegal
+}
+
+ + +

An interface type T may not embed itself or any interface type that embeds T, recursively. @@ -1872,7 +2040,8 @@ The following identifiers are implicitly declared in the

 Types:
-	bool byte complex64 complex128 error float32 float64
+	any bool byte comparable
+	complex64 complex128 error float32 float64
 	int int8 int16 int32 int64 rune string
 	uint uint8 uint16 uint32 uint64 uintptr
 
-- 
GitLab


From 14c3f749bebafe10d60cf5a9b1f4ae6663ff862a Mon Sep 17 00:00:00 2001
From: Than McIntosh 
Date: Fri, 12 Nov 2021 13:20:07 -0500
Subject: [PATCH 2251/2500] cmd/link: relocate dwarf examiner helper to
 separate package

The linker DWARF test includes an "examiner" helper type (with
associated methods) that is used to help linker DWARF tests read DWARF
info in a higher level and more structured way than just raw
debug/dwarf operations. This patch extracts out "examiner" and
relocates it to a separate package, so that it can be used in other
package tests as well, if need be.

Change-Id: Iec66061e2719ee698c12d8fa17b11698442b336d
Reviewed-on: https://go-review.googlesource.com/c/go/+/364036
Trust: Than McIntosh 
Run-TryBot: Than McIntosh 
TryBot-Result: Go Bot 
Reviewed-by: David Chase 
Reviewed-by: Cherry Mui 
---
 src/cmd/link/internal/dwtest/dwtest.go | 197 ++++++++++++++++++
 src/cmd/link/internal/ld/dwarf_test.go | 266 ++++---------------------
 2 files changed, 241 insertions(+), 222 deletions(-)
 create mode 100644 src/cmd/link/internal/dwtest/dwtest.go

diff --git a/src/cmd/link/internal/dwtest/dwtest.go b/src/cmd/link/internal/dwtest/dwtest.go
new file mode 100644
index 0000000000..c68edf4187
--- /dev/null
+++ b/src/cmd/link/internal/dwtest/dwtest.go
@@ -0,0 +1,197 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package dwtest
+
+import (
+	"debug/dwarf"
+	"errors"
+	"fmt"
+	"os"
+)
+
+// Helper type for supporting queries on DIEs within a DWARF
+// .debug_info section. Invoke the populate() method below passing in
+// a dwarf.Reader, which will read in all DIEs and keep track of
+// parent/child relationships. Queries can then be made to ask for
+// DIEs by name or by offset. This will hopefully reduce boilerplate
+// for future test writing.
+
+type Examiner struct {
+	dies        []*dwarf.Entry
+	idxByOffset map[dwarf.Offset]int
+	kids        map[int][]int
+	parent      map[int]int
+	byname      map[string][]int
+}
+
+// Populate the Examiner using the DIEs read from rdr.
+func (ex *Examiner) Populate(rdr *dwarf.Reader) error {
+	ex.idxByOffset = make(map[dwarf.Offset]int)
+	ex.kids = make(map[int][]int)
+	ex.parent = make(map[int]int)
+	ex.byname = make(map[string][]int)
+	var nesting []int
+	for entry, err := rdr.Next(); entry != nil; entry, err = rdr.Next() {
+		if err != nil {
+			return err
+		}
+		if entry.Tag == 0 {
+			// terminator
+			if len(nesting) == 0 {
+				return errors.New("nesting stack underflow")
+			}
+			nesting = nesting[:len(nesting)-1]
+			continue
+		}
+		idx := len(ex.dies)
+		ex.dies = append(ex.dies, entry)
+		if _, found := ex.idxByOffset[entry.Offset]; found {
+			return errors.New("DIE clash on offset")
+		}
+		ex.idxByOffset[entry.Offset] = idx
+		if name, ok := entry.Val(dwarf.AttrName).(string); ok {
+			ex.byname[name] = append(ex.byname[name], idx)
+		}
+		if len(nesting) > 0 {
+			parent := nesting[len(nesting)-1]
+			ex.kids[parent] = append(ex.kids[parent], idx)
+			ex.parent[idx] = parent
+		}
+		if entry.Children {
+			nesting = append(nesting, idx)
+		}
+	}
+	if len(nesting) > 0 {
+		return errors.New("unterminated child sequence")
+	}
+	return nil
+}
+
+func (e *Examiner) DIEs() []*dwarf.Entry {
+	return e.dies
+}
+
+func indent(ilevel int) {
+	for i := 0; i < ilevel; i++ {
+		fmt.Printf("  ")
+	}
+}
+
+// For debugging new tests
+func (ex *Examiner) DumpEntry(idx int, dumpKids bool, ilevel int) {
+	if idx >= len(ex.dies) {
+		fmt.Fprintf(os.Stderr, "DumpEntry: bad DIE %d: index out of range\n", idx)
+		return
+	}
+	entry := ex.dies[idx]
+	indent(ilevel)
+	fmt.Printf("0x%x: %v\n", idx, entry.Tag)
+	for _, f := range entry.Field {
+		indent(ilevel)
+		fmt.Printf("at=%v val=0x%x\n", f.Attr, f.Val)
+	}
+	if dumpKids {
+		ksl := ex.kids[idx]
+		for _, k := range ksl {
+			ex.DumpEntry(k, true, ilevel+2)
+		}
+	}
+}
+
+// Given a DIE offset, return the previously read dwarf.Entry, or nil
+func (ex *Examiner) EntryFromOffset(off dwarf.Offset) *dwarf.Entry {
+	if idx, found := ex.idxByOffset[off]; found && idx != -1 {
+		return ex.entryFromIdx(idx)
+	}
+	return nil
+}
+
+// Return the ID that Examiner uses to refer to the DIE at offset off
+func (ex *Examiner) IdxFromOffset(off dwarf.Offset) int {
+	if idx, found := ex.idxByOffset[off]; found {
+		return idx
+	}
+	return -1
+}
+
+// Return the dwarf.Entry pointer for the DIE with id 'idx'
+func (ex *Examiner) entryFromIdx(idx int) *dwarf.Entry {
+	if idx >= len(ex.dies) || idx < 0 {
+		return nil
+	}
+	return ex.dies[idx]
+}
+
+// Returns a list of child entries for a die with ID 'idx'
+func (ex *Examiner) Children(idx int) []*dwarf.Entry {
+	sl := ex.kids[idx]
+	ret := make([]*dwarf.Entry, len(sl))
+	for i, k := range sl {
+		ret[i] = ex.entryFromIdx(k)
+	}
+	return ret
+}
+
+// Returns parent DIE for DIE 'idx', or nil if the DIE is top level
+func (ex *Examiner) Parent(idx int) *dwarf.Entry {
+	p, found := ex.parent[idx]
+	if !found {
+		return nil
+	}
+	return ex.entryFromIdx(p)
+}
+
+// ParentCU returns the enclosing compilation unit DIE for the DIE
+// with a given index, or nil if for some reason we can't establish a
+// parent.
+func (ex *Examiner) ParentCU(idx int) *dwarf.Entry {
+	for {
+		parentDie := ex.Parent(idx)
+		if parentDie == nil {
+			return nil
+		}
+		if parentDie.Tag == dwarf.TagCompileUnit {
+			return parentDie
+		}
+		idx = ex.IdxFromOffset(parentDie.Offset)
+	}
+}
+
+// FileRef takes a given DIE by index and a numeric file reference
+// (presumably from a decl_file or call_file attribute), looks up the
+// reference in the .debug_line file table, and returns the proper
+// string for it. We need to know which DIE is making the reference
+// so as to find the right compilation unit.
+func (ex *Examiner) FileRef(dw *dwarf.Data, dieIdx int, fileRef int64) (string, error) {
+
+	// Find the parent compilation unit DIE for the specified DIE.
+	cuDie := ex.ParentCU(dieIdx)
+	if cuDie == nil {
+		return "", fmt.Errorf("no parent CU DIE for DIE with idx %d?", dieIdx)
+	}
+	// Construct a line reader and then use it to get the file string.
+	lr, lrerr := dw.LineReader(cuDie)
+	if lrerr != nil {
+		return "", fmt.Errorf("d.LineReader: %v", lrerr)
+	}
+	files := lr.Files()
+	if fileRef < 0 || int(fileRef) > len(files)-1 {
+		return "", fmt.Errorf("Examiner.FileRef: malformed file reference %d", fileRef)
+	}
+	return files[fileRef].Name, nil
+}
+
+// Return a list of all DIEs with name 'name'. When searching for DIEs
+// by name, keep in mind that the returned results will include child
+// DIEs such as params/variables. For example, asking for all DIEs named
+// "p" for even a small program will give you 400-500 entries.
+func (ex *Examiner) Named(name string) []*dwarf.Entry {
+	sl := ex.byname[name]
+	ret := make([]*dwarf.Entry, len(sl))
+	for i, k := range sl {
+		ret[i] = ex.entryFromIdx(k)
+	}
+	return ret
+}
diff --git a/src/cmd/link/internal/ld/dwarf_test.go b/src/cmd/link/internal/ld/dwarf_test.go
index 9a163488e6..2f9bf25d10 100644
--- a/src/cmd/link/internal/ld/dwarf_test.go
+++ b/src/cmd/link/internal/ld/dwarf_test.go
@@ -7,9 +7,9 @@ package ld
 import (
 	intdwarf "cmd/internal/dwarf"
 	objfilepkg "cmd/internal/objfile" // renamed to avoid conflict with objfile function
+	"cmd/link/internal/dwtest"
 	"debug/dwarf"
 	"debug/pe"
-	"errors"
 	"fmt"
 	"internal/buildcfg"
 	"internal/testenv"
@@ -352,8 +352,8 @@ func varDeclCoordsAndSubrogramDeclFile(t *testing.T, testpoint string, expectFil
 	}
 
 	rdr := d.Reader()
-	ex := examiner{}
-	if err := ex.populate(rdr); err != nil {
+	ex := dwtest.Examiner{}
+	if err := ex.Populate(rdr); err != nil {
 		t.Fatalf("error reading DWARF: %v", err)
 	}
 
@@ -373,7 +373,7 @@ func varDeclCoordsAndSubrogramDeclFile(t *testing.T, testpoint string, expectFil
 	}
 
 	// Walk main's children and select variable "i".
-	mainIdx := ex.idxFromOffset(maindie.Offset)
+	mainIdx := ex.IdxFromOffset(maindie.Offset)
 	childDies := ex.Children(mainIdx)
 	var iEntry *dwarf.Entry
 	for _, child := range childDies {
@@ -396,7 +396,10 @@ func varDeclCoordsAndSubrogramDeclFile(t *testing.T, testpoint string, expectFil
 	if !fileIdxOK {
 		t.Errorf("missing or invalid DW_AT_decl_file for main")
 	}
-	file := ex.FileRef(t, d, mainIdx, fileIdx)
+	file, err := ex.FileRef(d, mainIdx, fileIdx)
+	if err != nil {
+		t.Fatalf("FileRef: %v", err)
+	}
 	base := filepath.Base(file)
 	if base != expectFile {
 		t.Errorf("DW_AT_decl_file for main is %v, want %v", base, expectFile)
@@ -424,191 +427,6 @@ func TestVarDeclCoordsWithLineDirective(t *testing.T) {
 		"foobar.go", 202, "//line /foobar.go:200")
 }
 
-// Helper class for supporting queries on DIEs within a DWARF .debug_info
-// section. Invoke the populate() method below passing in a dwarf.Reader,
-// which will read in all DIEs and keep track of parent/child
-// relationships. Queries can then be made to ask for DIEs by name or
-// by offset. This will hopefully reduce boilerplate for future test
-// writing.
-
-type examiner struct {
-	dies        []*dwarf.Entry
-	idxByOffset map[dwarf.Offset]int
-	kids        map[int][]int
-	parent      map[int]int
-	byname      map[string][]int
-}
-
-// Populate the examiner using the DIEs read from rdr.
-func (ex *examiner) populate(rdr *dwarf.Reader) error {
-	ex.idxByOffset = make(map[dwarf.Offset]int)
-	ex.kids = make(map[int][]int)
-	ex.parent = make(map[int]int)
-	ex.byname = make(map[string][]int)
-	var nesting []int
-	for entry, err := rdr.Next(); entry != nil; entry, err = rdr.Next() {
-		if err != nil {
-			return err
-		}
-		if entry.Tag == 0 {
-			// terminator
-			if len(nesting) == 0 {
-				return errors.New("nesting stack underflow")
-			}
-			nesting = nesting[:len(nesting)-1]
-			continue
-		}
-		idx := len(ex.dies)
-		ex.dies = append(ex.dies, entry)
-		if _, found := ex.idxByOffset[entry.Offset]; found {
-			return errors.New("DIE clash on offset")
-		}
-		ex.idxByOffset[entry.Offset] = idx
-		if name, ok := entry.Val(dwarf.AttrName).(string); ok {
-			ex.byname[name] = append(ex.byname[name], idx)
-		}
-		if len(nesting) > 0 {
-			parent := nesting[len(nesting)-1]
-			ex.kids[parent] = append(ex.kids[parent], idx)
-			ex.parent[idx] = parent
-		}
-		if entry.Children {
-			nesting = append(nesting, idx)
-		}
-	}
-	if len(nesting) > 0 {
-		return errors.New("unterminated child sequence")
-	}
-	return nil
-}
-
-func indent(ilevel int) {
-	for i := 0; i < ilevel; i++ {
-		fmt.Printf("  ")
-	}
-}
-
-// For debugging new tests
-func (ex *examiner) dumpEntry(idx int, dumpKids bool, ilevel int) error {
-	if idx >= len(ex.dies) {
-		msg := fmt.Sprintf("bad DIE %d: index out of range\n", idx)
-		return errors.New(msg)
-	}
-	entry := ex.dies[idx]
-	indent(ilevel)
-	fmt.Printf("0x%x: %v\n", idx, entry.Tag)
-	for _, f := range entry.Field {
-		indent(ilevel)
-		fmt.Printf("at=%v val=0x%x\n", f.Attr, f.Val)
-	}
-	if dumpKids {
-		ksl := ex.kids[idx]
-		for _, k := range ksl {
-			ex.dumpEntry(k, true, ilevel+2)
-		}
-	}
-	return nil
-}
-
-// Given a DIE offset, return the previously read dwarf.Entry, or nil
-func (ex *examiner) entryFromOffset(off dwarf.Offset) *dwarf.Entry {
-	if idx, found := ex.idxByOffset[off]; found && idx != -1 {
-		return ex.entryFromIdx(idx)
-	}
-	return nil
-}
-
-// Return the ID that examiner uses to refer to the DIE at offset off
-func (ex *examiner) idxFromOffset(off dwarf.Offset) int {
-	if idx, found := ex.idxByOffset[off]; found {
-		return idx
-	}
-	return -1
-}
-
-// Return the dwarf.Entry pointer for the DIE with id 'idx'
-func (ex *examiner) entryFromIdx(idx int) *dwarf.Entry {
-	if idx >= len(ex.dies) || idx < 0 {
-		return nil
-	}
-	return ex.dies[idx]
-}
-
-// Returns a list of child entries for a die with ID 'idx'
-func (ex *examiner) Children(idx int) []*dwarf.Entry {
-	sl := ex.kids[idx]
-	ret := make([]*dwarf.Entry, len(sl))
-	for i, k := range sl {
-		ret[i] = ex.entryFromIdx(k)
-	}
-	return ret
-}
-
-// Returns parent DIE for DIE 'idx', or nil if the DIE is top level
-func (ex *examiner) Parent(idx int) *dwarf.Entry {
-	p, found := ex.parent[idx]
-	if !found {
-		return nil
-	}
-	return ex.entryFromIdx(p)
-}
-
-// ParentCU returns the enclosing compilation unit DIE for the DIE
-// with a given index, or nil if for some reason we can't establish a
-// parent.
-func (ex *examiner) ParentCU(idx int) *dwarf.Entry {
-	for {
-		parentDie := ex.Parent(idx)
-		if parentDie == nil {
-			return nil
-		}
-		if parentDie.Tag == dwarf.TagCompileUnit {
-			return parentDie
-		}
-		idx = ex.idxFromOffset(parentDie.Offset)
-	}
-}
-
-// FileRef takes a given DIE by index and a numeric file reference
-// (presumably from a decl_file or call_file attribute), looks up the
-// reference in the .debug_line file table, and returns the proper
-// string for it. We need to know which DIE is making the reference
-// so as find the right compilation unit.
-func (ex *examiner) FileRef(t *testing.T, dw *dwarf.Data, dieIdx int, fileRef int64) string {
-
-	// Find the parent compilation unit DIE for the specified DIE.
-	cuDie := ex.ParentCU(dieIdx)
-	if cuDie == nil {
-		t.Fatalf("no parent CU DIE for DIE with idx %d?", dieIdx)
-		return ""
-	}
-	// Construct a line reader and then use it to get the file string.
-	lr, lrerr := dw.LineReader(cuDie)
-	if lrerr != nil {
-		t.Fatal("d.LineReader: ", lrerr)
-		return ""
-	}
-	files := lr.Files()
-	if fileRef < 0 || int(fileRef) > len(files)-1 {
-		t.Fatalf("examiner.FileRef: malformed file reference %d", fileRef)
-		return ""
-	}
-	return files[fileRef].Name
-}
-
-// Return a list of all DIEs with name 'name'. When searching for DIEs
-// by name, keep in mind that the returned results will include child
-// DIEs such as params/variables. For example, asking for all DIEs named
-// "p" for even a small program will give you 400-500 entries.
-func (ex *examiner) Named(name string) []*dwarf.Entry {
-	sl := ex.byname[name]
-	ret := make([]*dwarf.Entry, len(sl))
-	for i, k := range sl {
-		ret[i] = ex.entryFromIdx(k)
-	}
-	return ret
-}
-
 func TestInlinedRoutineRecords(t *testing.T) {
 	testenv.MustHaveGoBuild(t)
 
@@ -656,8 +474,8 @@ func main() {
 	expectedInl := []string{"main.cand"}
 
 	rdr := d.Reader()
-	ex := examiner{}
-	if err := ex.populate(rdr); err != nil {
+	ex := dwtest.Examiner{}
+	if err := ex.Populate(rdr); err != nil {
 		t.Fatalf("error reading DWARF: %v", err)
 	}
 
@@ -677,7 +495,7 @@ func main() {
 	}
 
 	// Walk main's children and pick out the inlined subroutines
-	mainIdx := ex.idxFromOffset(maindie.Offset)
+	mainIdx := ex.IdxFromOffset(maindie.Offset)
 	childDies := ex.Children(mainIdx)
 	exCount := 0
 	for _, child := range childDies {
@@ -687,7 +505,7 @@ func main() {
 			if !originOK {
 				t.Fatalf("no abstract origin attr for inlined subroutine at offset %v", child.Offset)
 			}
-			originDIE := ex.entryFromOffset(ooff)
+			originDIE := ex.EntryFromOffset(ooff)
 			if originDIE == nil {
 				t.Fatalf("can't locate origin DIE at off %v", ooff)
 			}
@@ -696,7 +514,7 @@ func main() {
 			// to see child variables there, even if (perhaps due to
 			// optimization) there are no references to them from the
 			// inlined subroutine DIE.
-			absFcnIdx := ex.idxFromOffset(ooff)
+			absFcnIdx := ex.IdxFromOffset(ooff)
 			absFcnChildDies := ex.Children(absFcnIdx)
 			if len(absFcnChildDies) != 2 {
 				t.Fatalf("expected abstract function: expected 2 children, got %d children", len(absFcnChildDies))
@@ -735,7 +553,11 @@ func main() {
 			if !cfOK {
 				t.Fatalf("no call_file attr for inlined subroutine at offset %v", child.Offset)
 			}
-			file := ex.FileRef(t, d, mainIdx, cf)
+			file, err := ex.FileRef(d, mainIdx, cf)
+			if err != nil {
+				t.Errorf("FileRef: %v", err)
+				continue
+			}
 			base := filepath.Base(file)
 			if base != "test.go" {
 				t.Errorf("bad call_file attribute, found '%s', want '%s'",
@@ -747,7 +569,7 @@ func main() {
 			// Walk the child variables of the inlined routine. Each
 			// of them should have a distinct abstract origin-- if two
 			// vars point to the same origin things are definitely broken.
-			inlIdx := ex.idxFromOffset(child.Offset)
+			inlIdx := ex.IdxFromOffset(child.Offset)
 			inlChildDies := ex.Children(inlIdx)
 			for _, k := range inlChildDies {
 				ooff, originOK := k.Val(dwarf.AttrAbstractOrigin).(dwarf.Offset)
@@ -780,15 +602,15 @@ func abstractOriginSanity(t *testing.T, pkgDir string, flags string) {
 		t.Fatalf("error reading DWARF: %v", err)
 	}
 	rdr := d.Reader()
-	ex := examiner{}
-	if err := ex.populate(rdr); err != nil {
+	ex := dwtest.Examiner{}
+	if err := ex.Populate(rdr); err != nil {
 		t.Fatalf("error reading DWARF: %v", err)
 	}
 
 	// Make a pass through all DIEs looking for abstract origin
 	// references.
 	abscount := 0
-	for i, die := range ex.dies {
+	for i, die := range ex.DIEs() {
 		// Does it have an abstract origin?
 		ooff, originOK := die.Val(dwarf.AttrAbstractOrigin).(dwarf.Offset)
 		if !originOK {
@@ -797,9 +619,9 @@ func abstractOriginSanity(t *testing.T, pkgDir string, flags string) {
 
 		// All abstract origin references should be resolvable.
 		abscount += 1
-		originDIE := ex.entryFromOffset(ooff)
+		originDIE := ex.EntryFromOffset(ooff)
 		if originDIE == nil {
-			ex.dumpEntry(i, false, 0)
+			ex.DumpEntry(i, false, 0)
 			t.Fatalf("unresolved abstract origin ref in DIE at offset 0x%x\n", die.Offset)
 		}
 
@@ -807,7 +629,7 @@ func abstractOriginSanity(t *testing.T, pkgDir string, flags string) {
 		// K2, ... KN}. If X has an abstract origin of A, then for
 		// each KJ, the abstract origin of KJ should be a child of A.
 		// Note that this same rule doesn't hold for non-variable DIEs.
-		pidx := ex.idxFromOffset(die.Offset)
+		pidx := ex.IdxFromOffset(die.Offset)
 		if pidx < 0 {
 			t.Fatalf("can't locate DIE id")
 		}
@@ -821,15 +643,15 @@ func abstractOriginSanity(t *testing.T, pkgDir string, flags string) {
 			if !originOK {
 				continue
 			}
-			childOriginDIE := ex.entryFromOffset(kooff)
+			childOriginDIE := ex.EntryFromOffset(kooff)
 			if childOriginDIE == nil {
-				ex.dumpEntry(i, false, 0)
+				ex.DumpEntry(i, false, 0)
 				t.Fatalf("unresolved abstract origin ref in DIE at offset %x", kid.Offset)
 			}
-			coidx := ex.idxFromOffset(childOriginDIE.Offset)
+			coidx := ex.IdxFromOffset(childOriginDIE.Offset)
 			childOriginParent := ex.Parent(coidx)
 			if childOriginParent != originDIE {
-				ex.dumpEntry(i, false, 0)
+				ex.DumpEntry(i, false, 0)
 				t.Fatalf("unexpected parent of abstract origin DIE at offset %v", childOriginDIE.Offset)
 			}
 		}
@@ -977,8 +799,8 @@ func main() {
 	}
 
 	rdr := d.Reader()
-	ex := examiner{}
-	if err := ex.populate(rdr); err != nil {
+	ex := dwtest.Examiner{}
+	if err := ex.Populate(rdr); err != nil {
 		t.Fatalf("error reading DWARF: %v", err)
 	}
 	dies := ex.Named("*main.X")
@@ -1501,8 +1323,8 @@ func TestIssue39757(t *testing.T) {
 		t.Fatalf("error parsing DWARF: %v", err)
 	}
 	rdr := dw.Reader()
-	ex := examiner{}
-	if err := ex.populate(rdr); err != nil {
+	ex := dwtest.Examiner{}
+	if err := ex.Populate(rdr); err != nil {
 		t.Fatalf("error reading DWARF: %v", err)
 	}
 
@@ -1521,7 +1343,7 @@ func TestIssue39757(t *testing.T) {
 	highpc := maindie.Val(dwarf.AttrHighpc).(uint64)
 
 	// Now read the line table for the 'main' compilation unit.
-	mainIdx := ex.idxFromOffset(maindie.Offset)
+	mainIdx := ex.IdxFromOffset(maindie.Offset)
 	cuentry := ex.Parent(mainIdx)
 	if cuentry == nil {
 		t.Fatalf("main.main DIE appears orphaned")
@@ -1648,7 +1470,7 @@ func TestIssue42484(t *testing.T) {
 //
 // where each chunk above is of the form NAME:ORDER:INOUTCLASSIFICATION
 //
-func processParams(die *dwarf.Entry, ex *examiner) string {
+func processParams(die *dwarf.Entry, ex *dwtest.Examiner) string {
 	// Values in the returned map are of the form :
 	// where order is the order within the child DIE list of the
 	// param, and  is an integer:
@@ -1659,9 +1481,9 @@ func processParams(die *dwarf.Entry, ex *examiner) string {
 	//
 	foundParams := make(map[string]string)
 
-	// Walk ABCs's children looking for params.
-	abcIdx := ex.idxFromOffset(die.Offset)
-	childDies := ex.Children(abcIdx)
+	// Walk the subprogram DIE's children looking for params.
+	pIdx := ex.IdxFromOffset(die.Offset)
+	childDies := ex.Children(pIdx)
 	idx := 0
 	for _, child := range childDies {
 		if child.Tag == dwarf.TagFormalParameter {
@@ -1734,8 +1556,8 @@ func main() {
 	}
 
 	rdr := d.Reader()
-	ex := examiner{}
-	if err := ex.populate(rdr); err != nil {
+	ex := dwtest.Examiner{}
+	if err := ex.Populate(rdr); err != nil {
 		t.Fatalf("error reading DWARF: %v", err)
 	}
 
@@ -1854,8 +1676,8 @@ func main() {
 	}
 
 	rdr.Seek(0)
-	ex := examiner{}
-	if err := ex.populate(rdr); err != nil {
+	ex := dwtest.Examiner{}
+	if err := ex.Populate(rdr); err != nil {
 		t.Fatalf("error reading DWARF: %v", err)
 	}
 	for _, typeName := range []string{"main.CustomInt", "map[int]main.CustomInt"} {
@@ -1969,8 +1791,8 @@ func main() {
 	}
 
 	rdr := d.Reader()
-	ex := examiner{}
-	if err := ex.populate(rdr); err != nil {
+	ex := dwtest.Examiner{}
+	if err := ex.Populate(rdr); err != nil {
 		t.Fatalf("error reading DWARF: %v", err)
 	}
 
-- 
GitLab


From 9ea939be600df12fe51b201112cc12e741acef00 Mon Sep 17 00:00:00 2001
From: Robert Findley 
Date: Wed, 17 Nov 2021 20:01:16 -0500
Subject: [PATCH 2252/2500] go/types: implement Checker.implements

This is a port of CL 363837 from types2 to go/types. As usual, test
error messages had to be repositioned on the operand.

Change-Id: I2b53fae7aa30f9147f8d05f75b0ab252338320bb
Reviewed-on: https://go-review.googlesource.com/c/go/+/364934
Trust: Robert Findley 
Run-TryBot: Robert Findley 
TryBot-Result: Go Bot 
Reviewed-by: Robert Griesemer 
---
 src/go/types/instantiate.go                   | 121 ++++++++++--------
 .../types/testdata/fixedbugs/issue45920.go2   |   4 +-
 2 files changed, 67 insertions(+), 58 deletions(-)

diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go
index c9ce6f6ae1..737340d086 100644
--- a/src/go/types/instantiate.go
+++ b/src/go/types/instantiate.go
@@ -133,113 +133,122 @@ func (check *Checker) validateTArgLen(pos token.Pos, ntparams, ntargs int) bool
 }
 
 func (check *Checker) verify(pos token.Pos, tparams []*TypeParam, targs []Type) (int, error) {
+	// TODO(rfindley): it would be great if users could pass in a qualifier here,
+	// rather than falling back to verbose qualification. Maybe this can be part
+	// of the shared context.
+	var qf Qualifier
+	if check != nil {
+		qf = check.qualifier
+	}
+
 	smap := makeSubstMap(tparams, targs)
 	for i, tpar := range tparams {
-		// stop checking bounds after the first failure
-		if err := check.satisfies(pos, targs[i], tpar, smap); err != nil {
+		// The type parameter bound is parameterized with the same type parameters
+		// as the instantiated type; before we can use it for bounds checking we
+		// need to instantiate it with the type arguments with which we instantiated
+		// the parameterized type.
+		bound := check.subst(pos, tpar.bound, smap, nil)
+		if err := check.implements(targs[i], bound, qf); err != nil {
 			return i, err
 		}
 	}
 	return -1, nil
 }
 
-// satisfies reports whether the type argument targ satisfies the constraint of type parameter
-// parameter tpar (after any of its type parameters have been substituted through smap).
-// A suitable error is reported if the result is false.
-// TODO(gri) This should be a method of interfaces or type sets.
-func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap substMap) error {
-	iface := tpar.iface()
-
-	// Every type argument satisfies interface{}.
-	if iface.Empty() {
+// implements checks if V implements T and reports an error if it doesn't.
+// If a qualifier is provided, it is used in error formatting.
+func (check *Checker) implements(V, T Type, qf Qualifier) error {
+	Vu := under(V)
+	Tu := under(T)
+	if Vu == Typ[Invalid] || Tu == Typ[Invalid] {
 		return nil
 	}
 
-	// A type argument that is a type parameter with an empty type set satisfies any constraint.
-	// (The empty set is a subset of any set.)
-	if targ, _ := targ.(*TypeParam); targ != nil && targ.iface().typeSet().IsEmpty() {
-		return nil
+	errorf := func(format string, args ...interface{}) error {
+		return errors.New(sprintf(nil, qf, false, format, args...))
 	}
 
-	// TODO(rfindley): it would be great if users could pass in a qualifier here,
-	// rather than falling back to verbose qualification. Maybe this can be part
-	// of the shared context.
-	var qf Qualifier
-	if check != nil {
-		qf = check.qualifier
+	Ti, _ := Tu.(*Interface)
+	if Ti == nil {
+		return errorf("%s is not an interface", T)
 	}
-	errorf := func(format string, args ...interface{}) error {
-		return errors.New(sprintf(nil, qf, false, format, args...))
+
+	// Every type satisfies the empty interface.
+	if Ti.Empty() {
+		return nil
 	}
+	// T is not the empty interface (i.e., the type set of T is restricted)
 
-	// No type argument with non-empty type set satisfies the empty type set.
-	if iface.typeSet().IsEmpty() {
-		return errorf("%s does not satisfy %s (constraint type set is empty)", targ, tpar.bound)
+	// An interface V with an empty type set satisfies any interface.
+	// (The empty set is a subset of any set.)
+	Vi, _ := Vu.(*Interface)
+	if Vi != nil && Vi.typeSet().IsEmpty() {
+		return nil
 	}
+	// type set of V is not empty
 
-	// The type parameter bound is parameterized with the same type parameters
-	// as the instantiated type; before we can use it for bounds checking we
-	// need to instantiate it with the type arguments with which we instantiate
-	// the parameterized type.
-	iface = check.subst(pos, iface, smap, nil).(*Interface)
+	// No type with non-empty type set satisfies the empty type set.
+	// TODO(gri) should use "implements" rather than "satisfies" throughout
+	if Ti.typeSet().IsEmpty() {
+		return errorf("%s does not satisfy %s (constraint type set is empty)", V, T)
+	}
 
-	// if iface is comparable, targ must be comparable
+	// If T is comparable, V must be comparable.
 	// TODO(gri) the error messages needs to be better, here
-	if iface.IsComparable() && !Comparable(targ) {
-		if tpar, _ := targ.(*TypeParam); tpar != nil && tpar.iface().typeSet().IsAll() {
-			return errorf("%s has no constraints", targ)
+	if Ti.IsComparable() && !Comparable(V) {
+		if Vi != nil && Vi.typeSet().IsAll() {
+			return errorf("%s has no constraints", V)
 		}
-		return errorf("%s does not satisfy comparable", targ)
+		return errorf("%s does not satisfy comparable", V)
 	}
 
-	// targ must implement iface (methods)
+	// V must implement T (methods)
 	// - check only if we have methods
-	if iface.NumMethods() > 0 {
+	if Ti.NumMethods() > 0 {
 		// If the type argument is a pointer to a type parameter, the type argument's
 		// method set is empty.
 		// TODO(gri) is this what we want? (spec question)
-		if base, isPtr := deref(targ); isPtr && isTypeParam(base) {
-			return errorf("%s has no methods", targ)
+		if base, isPtr := deref(V); isPtr && isTypeParam(base) {
+			return errorf("%s has no methods", V)
 		}
-		if m, wrong := check.missingMethod(targ, iface, true); m != nil {
+		if m, wrong := check.missingMethod(V, Ti, true); m != nil {
 			// TODO(gri) needs to print updated name to avoid major confusion in error message!
 			//           (print warning for now)
 			// Old warning:
-			// check.softErrorf(pos, "%s does not satisfy %s (warning: name not updated) = %s (missing method %s)", targ, tpar.bound, iface, m)
+			// check.softErrorf(pos, "%s does not satisfy %s (warning: name not updated) = %s (missing method %s)", V, T, Ti, m)
 			if wrong != nil {
 				// TODO(gri) This can still report uninstantiated types which makes the error message
 				//           more difficult to read then necessary.
 				// TODO(rFindley) should this use parentheses rather than ':' for qualification?
 				return errorf("%s does not satisfy %s: wrong method signature\n\tgot  %s\n\twant %s",
-					targ, tpar.bound, wrong, m,
+					V, T, wrong, m,
 				)
 			}
-			return errorf("%s does not satisfy %s (missing method %s)", targ, tpar.bound, m.name)
+			return errorf("%s does not satisfy %s (missing method %s)", V, T, m.name)
 		}
 	}
 
-	// targ must also be in the set of types of iface, if any.
+	// V must also be in the set of types of T, if any.
 	// Constraints with empty type sets were already excluded above.
-	if !iface.typeSet().hasTerms() {
+	if !Ti.typeSet().hasTerms() {
 		return nil // nothing to do
 	}
 
-	// If targ is itself a type parameter, each of its possible types must be in the set
-	// of iface types (i.e., the targ type set must be a subset of the iface type set).
-	// Type arguments with empty type sets were already excluded above.
-	if targ, _ := targ.(*TypeParam); targ != nil {
-		targBound := targ.iface()
-		if !targBound.typeSet().subsetOf(iface.typeSet()) {
+	// If V is itself an interface, each of its possible types must be in the set
+	// of T types (i.e., the V type set must be a subset of the T type set).
+	// Interfaces V with empty type sets were already excluded above.
+	if Vi != nil {
+		if !Vi.typeSet().subsetOf(Ti.typeSet()) {
 			// TODO(gri) report which type is missing
-			return errorf("%s does not satisfy %s", targ, tpar.bound)
+			return errorf("%s does not satisfy %s", V, T)
 		}
 		return nil
 	}
 
-	// Otherwise, targ's type must be included in the iface type set.
-	if !iface.typeSet().includes(targ) {
+	// Otherwise, V's type must be included in the iface type set.
+	if !Ti.typeSet().includes(V) {
 		// TODO(gri) report which type is missing
-		return errorf("%s does not satisfy %s", targ, tpar.bound)
+		return errorf("%s does not satisfy %s", V, T)
 	}
 
 	return nil
diff --git a/src/go/types/testdata/fixedbugs/issue45920.go2 b/src/go/types/testdata/fixedbugs/issue45920.go2
index f659f3a0db..60a9e83fa9 100644
--- a/src/go/types/testdata/fixedbugs/issue45920.go2
+++ b/src/go/types/testdata/fixedbugs/issue45920.go2
@@ -8,10 +8,10 @@ func f1[T any, C chan T | <-chan T](ch C) {}
 
 func _(ch chan int)   { f1(ch) }
 func _(ch <-chan int) { f1(ch) }
-func _(ch chan<- int) { f1 /* ERROR chan<- int does not satisfy chan T\|<-chan T */ (ch) }
+func _(ch chan<- int) { f1 /* ERROR chan<- int does not satisfy chan int\|<-chan int */ (ch) }
 
 func f2[T any, C chan T | chan<- T](ch C) {}
 
 func _(ch chan int)   { f2(ch) }
-func _(ch <-chan int) { f2 /* ERROR <-chan int does not satisfy chan T\|chan<- T */ (ch)}
+func _(ch <-chan int) { f2 /* ERROR <-chan int does not satisfy chan int\|chan<- int */ (ch) }
 func _(ch chan<- int) { f2(ch) }
-- 
GitLab


From 5d5f2b1e201fe9f3b641109ccd91b3ceae4cf460 Mon Sep 17 00:00:00 2001
From: Robert Findley 
Date: Wed, 17 Nov 2021 20:04:14 -0500
Subject: [PATCH 2253/2500] go/types: remove unneccesary tests in implements
 and lookup

This is a port of CL 363838 from types2 to go/types.

Change-Id: I03f4da86ea38209a73f567cc5d84e7afd08883ac
Reviewed-on: https://go-review.googlesource.com/c/go/+/364935
Trust: Robert Findley 
Run-TryBot: Robert Findley 
TryBot-Result: Go Bot 
Reviewed-by: Robert Griesemer 
---
 src/go/types/instantiate.go | 6 ------
 src/go/types/lookup.go      | 6 +-----
 2 files changed, 1 insertion(+), 11 deletions(-)

diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go
index 737340d086..63b4a1ea4a 100644
--- a/src/go/types/instantiate.go
+++ b/src/go/types/instantiate.go
@@ -205,12 +205,6 @@ func (check *Checker) implements(V, T Type, qf Qualifier) error {
 	// V must implement T (methods)
 	// - check only if we have methods
 	if Ti.NumMethods() > 0 {
-		// If the type argument is a pointer to a type parameter, the type argument's
-		// method set is empty.
-		// TODO(gri) is this what we want? (spec question)
-		if base, isPtr := deref(V); isPtr && isTypeParam(base) {
-			return errorf("%s has no methods", V)
-		}
 		if m, wrong := check.missingMethod(V, Ti, true); m != nil {
 			// TODO(gri) needs to print updated name to avoid major confusion in error message!
 			//           (print warning for now)
diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go
index e3c43a94f7..c787601a06 100644
--- a/src/go/types/lookup.go
+++ b/src/go/types/lookup.go
@@ -80,12 +80,8 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
 
 	typ, isPtr := deref(T)
 
-	// *typ where typ is an interface or type parameter has no methods.
+	// *typ where typ is an interface has no methods.
 	if isPtr {
-		// don't look at under(typ) here - was bug (issue #47747)
-		if _, ok := typ.(*TypeParam); ok {
-			return
-		}
 		if _, ok := under(typ).(*Interface); ok {
 			return
 		}
-- 
GitLab


From 8d6c4e07fdd4a81c466450b51cda71a1bfab41fc Mon Sep 17 00:00:00 2001
From: Robert Findley 
Date: Wed, 17 Nov 2021 20:17:55 -0500
Subject: [PATCH 2254/2500] go/types: use "implements" rather than "satisfies"
 in error messages

This is a port of CL 363839 from types2 to go/types.

Change-Id: I9efe412a6a602fd55170d1ee89c8e1513037c926
Reviewed-on: https://go-review.googlesource.com/c/go/+/364936
Trust: Robert Findley 
Run-TryBot: Robert Findley 
TryBot-Result: Go Bot 
Reviewed-by: Robert Griesemer 
---
 src/go/types/instantiate.go                   | 21 +++++++-------
 src/go/types/testdata/check/issues.go2        |  6 ++--
 src/go/types/testdata/check/typeinst2.go2     | 28 +++++++++----------
 src/go/types/testdata/examples/inference.go2  |  2 +-
 .../types/testdata/fixedbugs/issue39754.go2   |  4 +--
 .../types/testdata/fixedbugs/issue45920.go2   |  4 +--
 .../types/testdata/fixedbugs/issue47411.go2   | 10 +++----
 7 files changed, 37 insertions(+), 38 deletions(-)

diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go
index 63b4a1ea4a..011fb8e540 100644
--- a/src/go/types/instantiate.go
+++ b/src/go/types/instantiate.go
@@ -188,18 +188,17 @@ func (check *Checker) implements(V, T Type, qf Qualifier) error {
 	// type set of V is not empty
 
 	// No type with non-empty type set satisfies the empty type set.
-	// TODO(gri) should use "implements" rather than "satisfies" throughout
 	if Ti.typeSet().IsEmpty() {
-		return errorf("%s does not satisfy %s (constraint type set is empty)", V, T)
+		return errorf("cannot implement %s (empty type set)", T)
 	}
 
 	// If T is comparable, V must be comparable.
-	// TODO(gri) the error messages needs to be better, here
+	// TODO(gri) the error messages could be better, here
 	if Ti.IsComparable() && !Comparable(V) {
-		if Vi != nil && Vi.typeSet().IsAll() {
-			return errorf("%s has no constraints", V)
+		if Vi != nil && Vi.Empty() {
+			return errorf("empty interface %s does not implement %s", V, T)
 		}
-		return errorf("%s does not satisfy comparable", V)
+		return errorf("%s does not implement comparable", V)
 	}
 
 	// V must implement T (methods)
@@ -209,16 +208,16 @@ func (check *Checker) implements(V, T Type, qf Qualifier) error {
 			// TODO(gri) needs to print updated name to avoid major confusion in error message!
 			//           (print warning for now)
 			// Old warning:
-			// check.softErrorf(pos, "%s does not satisfy %s (warning: name not updated) = %s (missing method %s)", V, T, Ti, m)
+			// check.softErrorf(pos, "%s does not implement %s (warning: name not updated) = %s (missing method %s)", V, T, Ti, m)
 			if wrong != nil {
 				// TODO(gri) This can still report uninstantiated types which makes the error message
 				//           more difficult to read then necessary.
 				// TODO(rFindley) should this use parentheses rather than ':' for qualification?
-				return errorf("%s does not satisfy %s: wrong method signature\n\tgot  %s\n\twant %s",
+				return errorf("%s does not implement %s: wrong method signature\n\tgot  %s\n\twant %s",
 					V, T, wrong, m,
 				)
 			}
-			return errorf("%s does not satisfy %s (missing method %s)", V, T, m.name)
+			return errorf("%s does not implement %s (missing method %s)", V, T, m.name)
 		}
 	}
 
@@ -234,7 +233,7 @@ func (check *Checker) implements(V, T Type, qf Qualifier) error {
 	if Vi != nil {
 		if !Vi.typeSet().subsetOf(Ti.typeSet()) {
 			// TODO(gri) report which type is missing
-			return errorf("%s does not satisfy %s", V, T)
+			return errorf("%s does not implement %s", V, T)
 		}
 		return nil
 	}
@@ -242,7 +241,7 @@ func (check *Checker) implements(V, T Type, qf Qualifier) error {
 	// Otherwise, V's type must be included in the iface type set.
 	if !Ti.typeSet().includes(V) {
 		// TODO(gri) report which type is missing
-		return errorf("%s does not satisfy %s", V, T)
+		return errorf("%s does not implement %s", V, T)
 	}
 
 	return nil
diff --git a/src/go/types/testdata/check/issues.go2 b/src/go/types/testdata/check/issues.go2
index b7bba5d3b1..fdb49d55f2 100644
--- a/src/go/types/testdata/check/issues.go2
+++ b/src/go/types/testdata/check/issues.go2
@@ -59,7 +59,7 @@ func _() {
 type T1[P interface{~uint}] struct{}
 
 func _[P any]() {
-    _ = T1[P /* ERROR P has no constraints */ ]{}
+    _ = T1[P /* ERROR empty interface P does not implement interface{~uint} */ ]{}
 }
 
 // This is the original (simplified) program causing the same issue.
@@ -75,8 +75,8 @@ func (u T2[U]) Add1() U {
     return u.s + 1
 }
 
-func NewT2[U any]() T2[U /* ERROR U has no constraints */ ] {
-    return T2[U /* ERROR U has no constraints */ ]{}
+func NewT2[U any]() T2[U /* ERROR empty interface U does not implement Unsigned */ ] {
+    return T2[U /* ERROR empty interface U does not implement Unsigned */ ]{}
 }
 
 func _() {
diff --git a/src/go/types/testdata/check/typeinst2.go2 b/src/go/types/testdata/check/typeinst2.go2
index f07c42a1da..1c3eb21b22 100644
--- a/src/go/types/testdata/check/typeinst2.go2
+++ b/src/go/types/testdata/check/typeinst2.go2
@@ -208,7 +208,7 @@ func f0[T I0]() {}
 var _ = f0[int]
 var _ = f0[bool]
 var _ = f0[string]
-var _ = f0[float64 /* ERROR does not satisfy I0 */ ]
+var _ = f0[float64 /* ERROR does not implement I0 */ ]
 
 type I01 interface {
 	E0
@@ -217,9 +217,9 @@ type I01 interface {
 
 func f01[T I01]() {}
 var _ = f01[int]
-var _ = f01[bool /* ERROR does not satisfy I0 */ ]
+var _ = f01[bool /* ERROR does not implement I0 */ ]
 var _ = f01[string]
-var _ = f01[float64 /* ERROR does not satisfy I0 */ ]
+var _ = f01[float64 /* ERROR does not implement I0 */ ]
 
 type I012 interface {
 	E0
@@ -228,10 +228,10 @@ type I012 interface {
 }
 
 func f012[T I012]() {}
-var _ = f012[int /* ERROR does not satisfy I012.*type set is empty */ ]
-var _ = f012[bool /* ERROR does not satisfy I012.*type set is empty */ ]
-var _ = f012[string /* ERROR does not satisfy I012.*type set is empty */ ]
-var _ = f012[float64 /* ERROR does not satisfy I012.*type set is empty */ ]
+var _ = f012[int /* ERROR cannot implement I012.*empty type set */ ]
+var _ = f012[bool /* ERROR cannot implement I012.*empty type set */ ]
+var _ = f012[string /* ERROR cannot implement I012.*empty type set */ ]
+var _ = f012[float64 /* ERROR cannot implement I012.*empty type set */ ]
 
 type I12 interface {
 	E1
@@ -239,9 +239,9 @@ type I12 interface {
 }
 
 func f12[T I12]() {}
-var _ = f12[int /* ERROR does not satisfy I12 */ ]
-var _ = f12[bool /* ERROR does not satisfy I12 */ ]
-var _ = f12[string /* ERROR does not satisfy I12 */ ]
+var _ = f12[int /* ERROR does not implement I12 */ ]
+var _ = f12[bool /* ERROR does not implement I12 */ ]
+var _ = f12[string /* ERROR does not implement I12 */ ]
 var _ = f12[float64]
 
 type I0_ interface {
@@ -251,9 +251,9 @@ type I0_ interface {
 
 func f0_[T I0_]() {}
 var _ = f0_[int]
-var _ = f0_[bool /* ERROR does not satisfy I0_ */ ]
-var _ = f0_[string /* ERROR does not satisfy I0_ */ ]
-var _ = f0_[float64 /* ERROR does not satisfy I0_ */ ]
+var _ = f0_[bool /* ERROR does not implement I0_ */ ]
+var _ = f0_[string /* ERROR does not implement I0_ */ ]
+var _ = f0_[float64 /* ERROR does not implement I0_ */ ]
 
 // Using a function instance as a type is an error.
 var _ f0 // ERROR not a type
@@ -271,7 +271,7 @@ func gg[T any]() {}
 func hh[T ~int]() {}
 
 func _[T none]() {
-        _ = ff[int /* ERROR int does not satisfy none \(constraint type set is empty\) */ ]
+        _ = ff[int /* ERROR cannot implement none \(empty type set\) */ ]
         _ = ff[T]  // pathological but ok because T's type set is empty, too
         _ = gg[int]
         _ = gg[T]
diff --git a/src/go/types/testdata/examples/inference.go2 b/src/go/types/testdata/examples/inference.go2
index 73246b0137..ffa30ee2cb 100644
--- a/src/go/types/testdata/examples/inference.go2
+++ b/src/go/types/testdata/examples/inference.go2
@@ -97,7 +97,7 @@ func _() {
 	// last.
 	related2(1.2, []float64{})
 	related2(1.0, []int{})
-	related2 /* ERROR does not satisfy */ (float64(1.0), []int{})
+	related2 /* ERROR does not implement */ (float64(1.0), []int{}) // TODO(gri) fix error position
 }
 
 type List[P any] []P
diff --git a/src/go/types/testdata/fixedbugs/issue39754.go2 b/src/go/types/testdata/fixedbugs/issue39754.go2
index 4b4420d997..cecbc88043 100644
--- a/src/go/types/testdata/fixedbugs/issue39754.go2
+++ b/src/go/types/testdata/fixedbugs/issue39754.go2
@@ -16,9 +16,9 @@ func f[V interface{}, A, B Box[V]]() {}
 
 func _() {
 	f[int, Optional[int], Optional[int]]()
-	_ = f[int, Optional[int], Optional /* ERROR does not satisfy Box */ [string]]
+	_ = f[int, Optional[int], Optional /* ERROR does not implement Box */ [string]]
 	// TODO(gri) Provide better position information here.
 	//           See TODO in call.go, Checker.arguments.
 	// TODO(rFindley) Reconcile this error position with types2.
-	f /* ERROR does not satisfy Box */ [int, Optional[int], Optional[string]]()
+	f /* ERROR does not implement Box */ [int, Optional[int], Optional[string]]()
 }
diff --git a/src/go/types/testdata/fixedbugs/issue45920.go2 b/src/go/types/testdata/fixedbugs/issue45920.go2
index 60a9e83fa9..a0e2d0c970 100644
--- a/src/go/types/testdata/fixedbugs/issue45920.go2
+++ b/src/go/types/testdata/fixedbugs/issue45920.go2
@@ -8,10 +8,10 @@ func f1[T any, C chan T | <-chan T](ch C) {}
 
 func _(ch chan int)   { f1(ch) }
 func _(ch <-chan int) { f1(ch) }
-func _(ch chan<- int) { f1 /* ERROR chan<- int does not satisfy chan int\|<-chan int */ (ch) }
+func _(ch chan<- int) { f1 /* ERROR chan<- int does not implement chan int\|<-chan int */ (ch) }
 
 func f2[T any, C chan T | chan<- T](ch C) {}
 
 func _(ch chan int)   { f2(ch) }
-func _(ch <-chan int) { f2 /* ERROR <-chan int does not satisfy chan int\|chan<- int */ (ch) }
+func _(ch <-chan int) { f2 /* ERROR <-chan int does not implement chan int\|chan<- int */ (ch) }
 func _(ch chan<- int) { f2(ch) }
diff --git a/src/go/types/testdata/fixedbugs/issue47411.go2 b/src/go/types/testdata/fixedbugs/issue47411.go2
index fde704bb41..d6c34be8db 100644
--- a/src/go/types/testdata/fixedbugs/issue47411.go2
+++ b/src/go/types/testdata/fixedbugs/issue47411.go2
@@ -15,12 +15,12 @@ func _[P comparable,
         _ = f[int]
         _ = f[P]
         _ = f[Q]
-        _ = f[func /* ERROR does not satisfy comparable */ ()]
-        _ = f[R /* ERROR R has no constraints */ ]
+        _ = f[func /* ERROR does not implement comparable */ ()]
+        _ = f[R /* ERROR empty interface R does not implement comparable */ ]
 
         _ = g[int]
-	_ = g[P /* ERROR P does not satisfy interface{interface{comparable; ~int\|~string} */ ]
+        _ = g[P /* ERROR P does not implement interface{interface{comparable; ~int\|~string} */ ]
         _ = g[Q]
-        _ = g[func /* ERROR does not satisfy comparable */()]
-        _ = g[R /* ERROR R has no constraints */ ]
+        _ = g[func /* ERROR does not implement comparable */ ()]
+        _ = g[R /* ERROR empty interface R does not implement interface{interface{comparable; ~int\|~string} */ ]
 }
-- 
GitLab


From feb330dcdd86146f5c9b4e09d30e19fc920f78f4 Mon Sep 17 00:00:00 2001
From: Robert Findley 
Date: Wed, 17 Nov 2021 20:22:32 -0500
Subject: [PATCH 2255/2500] go/types: add test for imported constraints
 pre-1.18

This is a port of CL 363834 from types2 to go/types.

Change-Id: I32583ead4bce626e0761f4c327678050404a15c9
Reviewed-on: https://go-review.googlesource.com/c/go/+/364937
Trust: Robert Findley 
Run-TryBot: Robert Findley 
TryBot-Result: Go Bot 
Reviewed-by: Robert Griesemer 
---
 src/go/types/check_test.go                     | 17 +++++++++++++++++
 src/go/types/testdata/fixedbugs/issue47818.go2 |  4 +++-
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/src/go/types/check_test.go b/src/go/types/check_test.go
index 75b26e34bd..2f80d9b7b6 100644
--- a/src/go/types/check_test.go
+++ b/src/go/types/check_test.go
@@ -31,6 +31,7 @@ import (
 	"go/parser"
 	"go/scanner"
 	"go/token"
+	"internal/buildcfg"
 	"internal/testenv"
 	"os"
 	"path/filepath"
@@ -199,11 +200,27 @@ func asGoVersion(s string) string {
 	return ""
 }
 
+// excludedForUnifiedBuild lists files that cannot be tested
+// when using the unified build's export data.
+// TODO(gri) enable as soon as the unified build supports this.
+var excludedForUnifiedBuild = map[string]bool{
+	"issue47818.go2": true,
+}
+
 func testFiles(t *testing.T, sizes Sizes, filenames []string, srcs [][]byte, manual bool, imp Importer) {
 	if len(filenames) == 0 {
 		t.Fatal("no source files")
 	}
 
+	if buildcfg.Experiment.Unified {
+		for _, f := range filenames {
+			if excludedForUnifiedBuild[filepath.Base(f)] {
+				t.Logf("%s cannot be tested with unified build - skipped", f)
+				return
+			}
+		}
+	}
+
 	if strings.HasSuffix(filenames[0], ".go1") {
 		// TODO(rfindley): re-enable this test by using GoVersion.
 		t.Skip("type params are enabled")
diff --git a/src/go/types/testdata/fixedbugs/issue47818.go2 b/src/go/types/testdata/fixedbugs/issue47818.go2
index e3e5a99637..2631118bae 100644
--- a/src/go/types/testdata/fixedbugs/issue47818.go2
+++ b/src/go/types/testdata/fixedbugs/issue47818.go2
@@ -8,6 +8,8 @@
 
 package go1_17
 
+import "constraints"
+
 type T[P /* ERROR type parameters require go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ] struct{}
 
 // for init (and main, but we're not in package main) we should only get one error
@@ -56,4 +58,4 @@ type (
 	_ = C2
 )
 
-// TODO(gri) need test cases for imported constraint types (see also issue #47967)
+type Ordered constraints /* ERROR using type constraint constraints\.Ordered requires go1\.18 or later */ .Ordered
-- 
GitLab


From c4aae23d6426442402b3de0e5f7de1ef8da3842a Mon Sep 17 00:00:00 2001
From: Mikhail Faraponov <11322032+moredure@users.noreply.github.com>
Date: Tue, 16 Nov 2021 19:41:43 +0000
Subject: [PATCH 2256/2500] net: optimize ctxDone usage

Change-Id: I6db6fcf0ebe36da77af062114b5264405f15fee8
GitHub-Last-Rev: 80a97262bb220bb3958c94016eadf385cdf915e8
GitHub-Pull-Request: golang/go#49620
Reviewed-on: https://go-review.googlesource.com/c/go/+/364514
Run-TryBot: Ian Lance Taylor 
TryBot-Result: Go Bot 
Reviewed-by: Ian Lance Taylor 
Reviewed-by: Damien Neil 
Trust: Damien Neil 
---
 src/net/fd_unix.go | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/net/fd_unix.go b/src/net/fd_unix.go
index 4ded833bbf..aaa7a1c185 100644
--- a/src/net/fd_unix.go
+++ b/src/net/fd_unix.go
@@ -95,7 +95,8 @@ func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (rsa sysc
 	// The interrupter goroutine waits for the context to be done and
 	// interrupts the dial (by altering the fd's write deadline, which
 	// wakes up waitWrite).
-	if ctxDone := ctx.Done(); ctxDone != nil {
+	ctxDone := ctx.Done()
+	if ctxDone != nil {
 		// Wait for the interrupter goroutine to exit before returning
 		// from connect.
 		done := make(chan struct{})
@@ -139,7 +140,7 @@ func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (rsa sysc
 		// details.
 		if err := fd.pfd.WaitWrite(); err != nil {
 			select {
-			case <-ctx.Done():
+			case <-ctxDone:
 				return nil, mapErr(ctx.Err())
 			default:
 			}
-- 
GitLab


From 24898d6948e1651aab909a5abccbfde64dc359cd Mon Sep 17 00:00:00 2001
From: Robert Griesemer 
Date: Thu, 18 Nov 2021 10:02:08 -0800
Subject: [PATCH 2257/2500] spec: various clarifications/fixes for method sets
 and interfaces

- fixed a typo in the method set section
- express in the syntax that ~T denotes an underlying type
- be more precise when talking about types vs type terms
- refer to "unions" rather than "union expressions"
- make it clear in the spec title that this is WIP

Change-Id: I9b2c4b1f77bc50dd574ed6893bedd40529c320fc
Reviewed-on: https://go-review.googlesource.com/c/go/+/365154
Trust: Robert Griesemer 
Reviewed-by: Ian Lance Taylor 
---
 doc/go_spec.html | 39 ++++++++++++++++++++-------------------
 1 file changed, 20 insertions(+), 19 deletions(-)

diff --git a/doc/go_spec.html b/doc/go_spec.html
index 63bc6a546e..7c53a1eb91 100644
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,16 +1,14 @@
 
 
-

Draft Go 1.18 Specification - Work in Progress

+

Earlier version

- -For the pre-Go1.18 spec see +For the pre-Go1.18 specification without generics support see The Go Programming Language Specification. -

Introduction

@@ -852,7 +850,7 @@ Every type has a (possibly empty) method set associated with it:
  • The method set of a pointer *T -to a defined type *T +to a defined type T (where T is neither a pointer nor an interface) is the set of all methods declared with receiver *T or T.
  • @@ -1271,7 +1269,8 @@ InterfaceElem = MethodElem | TypeElem . MethodElem = MethodName Signature . MethodName = identifier . TypeElem = TypeTerm { "|" TypeTerm } . -TypeTerm = [ "~" ] Type . +TypeTerm = Type | UnderlyingType . +UnderlyingType = "~" Type .

    @@ -1415,9 +1414,9 @@ type ReadCloser interface {

    -Finally, in their most general form, an interface element may be an arbitrary type -T, a type term of the form ~T, or a union of type terms -T1 | T2 | … Tn. +Finally, in their most general form, an interface element may also be an arbitrary type term +T, or a term of the form ~T specifying the underlying type T, +or a union of terms t1|t2|…|tn. Together with method specifications, these elements enable the precise definition of an interface's type set as follows:

    @@ -1434,7 +1433,7 @@ definition of an interface's type set as follows: whose method sets include that method. -
  • The type set of a non-interface type is the set consisting +
  • The type set of a non-interface type term is the set consisting of just that type.
  • @@ -1442,7 +1441,8 @@ definition of an interface's type set as follows: is the set of types whose underlying type is T. -
  • The type set of a union of terms T1 | T2 | … Tn +
  • The type set of a union of terms + t1|t2|…|tn is the union of the type sets of the terms.
  • @@ -1487,7 +1487,7 @@ interface {

    -Union expressions denote unions of type sets: +Union elements denote unions of type sets:

    @@ -1500,7 +1500,7 @@ type Floats interface {
     

    -In a union expression, a term cannot be a type parameter, and the type sets of all +In a union, a term cannot be a type parameter, and the type sets of all non-interface terms must be pairwise disjoint (the pairwise intersection of the type sets must be empty). Given a type parameter P:

    @@ -1516,14 +1516,15 @@ interface {

    Implementation restriction: -A union expression with more than one term cannot contain interface types +A union with more than one term cannot contain interface types with non-empty method sets.

    -Interfaces that contain union or tilde terms (not just methods) may only be used -as type constraints, or as elements of other interfaces used as constraints. They -cannot be the types of values or variables, or components of other, non-interface types. +Interfaces that contain non-interface types, terms of the form ~T, +or unions may only be used as type constraints, or as elements of other interfaces used +as constraints. They cannot be the types of values or variables, or components of other, +non-interface types.

    -- 
    GitLab
    
    
    From 2375b6edf376f97d0d8e3978fa3211788bc9b4dd Mon Sep 17 00:00:00 2001
    From: Ian Lance Taylor 
    Date: Thu, 18 Nov 2021 12:14:24 -0800
    Subject: [PATCH 2258/2500] cmd/go/internal/test: add dep from test pkg build
     to real pkg build
    
    If we have to build a test package, and if the full set of packages
    being tested imports the regular package somewhere, then make building
    the test package depend on building the regular package.  That way if
    the regular package fails to build we only report the error once.
    
    Fixes #44624
    
    Change-Id: Ic7d66d8fec9c4688d369153a4b21194989f8def3
    Reviewed-on: https://go-review.googlesource.com/c/go/+/365215
    Trust: Ian Lance Taylor 
    Run-TryBot: Ian Lance Taylor 
    TryBot-Result: Go Bot 
    Reviewed-by: Bryan C. Mills 
    ---
     src/cmd/go/internal/test/test.go              | 25 +++++++++++++++++--
     .../go/testdata/script/build_single_error.txt | 18 +++++++++++++
     2 files changed, 41 insertions(+), 2 deletions(-)
     create mode 100644 src/cmd/go/testdata/script/build_single_error.txt
    
    diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go
    index 73abca8927..b7bbcb4513 100644
    --- a/src/cmd/go/internal/test/test.go
    +++ b/src/cmd/go/internal/test/test.go
    @@ -890,6 +890,17 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) {
     		}
     	}
     
    +	// Collect all the packages imported by the packages being tested.
    +	allImports := make(map[*load.Package]bool)
    +	for _, p := range pkgs {
    +		if p.Error != nil && p.Error.IsImportCycle {
    +			continue
    +		}
    +		for _, p1 := range p.Internal.Imports {
    +			allImports[p1] = true
    +		}
    +	}
    +
     	// Prepare build + run + print actions for all packages being tested.
     	for _, p := range pkgs {
     		// sync/atomic import is inserted by the cover tool. See #18486
    @@ -897,7 +908,7 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) {
     			ensureImport(p, "sync/atomic")
     		}
     
    -		buildTest, runTest, printTest, err := builderTest(&b, ctx, pkgOpts, p)
    +		buildTest, runTest, printTest, err := builderTest(&b, ctx, pkgOpts, p, allImports[p])
     		if err != nil {
     			str := err.Error()
     			str = strings.TrimPrefix(str, "\n")
    @@ -964,7 +975,7 @@ var windowsBadWords = []string{
     	"update",
     }
     
    -func builderTest(b *work.Builder, ctx context.Context, pkgOpts load.PackageOpts, p *load.Package) (buildAction, runAction, printAction *work.Action, err error) {
    +func builderTest(b *work.Builder, ctx context.Context, pkgOpts load.PackageOpts, p *load.Package, imported bool) (buildAction, runAction, printAction *work.Action, err error) {
     	if len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 {
     		build := b.CompileAction(work.ModeBuild, work.ModeBuild, p)
     		run := &work.Action{Mode: "test run", Package: p, Deps: []*work.Action{build}}
    @@ -992,6 +1003,16 @@ func builderTest(b *work.Builder, ctx context.Context, pkgOpts load.PackageOpts,
     		return nil, nil, nil, err
     	}
     
    +	// If imported is true then this package is imported by some
    +	// package being tested. Make building the test version of the
    +	// package depend on building the non-test version, so that we
    +	// only report build errors once. Issue #44624.
    +	if imported && ptest != p {
    +		buildTest := b.CompileAction(work.ModeBuild, work.ModeBuild, ptest)
    +		buildP := b.CompileAction(work.ModeBuild, work.ModeBuild, p)
    +		buildTest.Deps = append(buildTest.Deps, buildP)
    +	}
    +
     	// Use last element of import path, not package name.
     	// They differ when package name is "main".
     	// But if the import path is "command-line-arguments",
    diff --git a/src/cmd/go/testdata/script/build_single_error.txt b/src/cmd/go/testdata/script/build_single_error.txt
    new file mode 100644
    index 0000000000..241cdb954b
    --- /dev/null
    +++ b/src/cmd/go/testdata/script/build_single_error.txt
    @@ -0,0 +1,18 @@
    +# go test ./... with a bad package should report the error once (#44624).
    +! go test ./...
    +stderr -count=1 undefined
    +
    +-- go.mod --
    +module example.com
    +
    +go 1.18
    +-- a/a.go --
    +package a
    +
    +import "example.com/b"
    +-- b/b.go --
    +package b
    +
    +var X = Y
    +-- b/b_test.go --
    +package b
    -- 
    GitLab
    
    
    From e8cda0a6c925668972ada40602ada08468fa90dc Mon Sep 17 00:00:00 2001
    From: Dan Scales 
    Date: Thu, 18 Nov 2021 10:52:35 -0800
    Subject: [PATCH 2259/2500] cmd/compile: don't run ComputeAddrTaken on imported
     generic functions
    
    It causes a crash because of the unexpected XDOT operation. It's not
    needed, since we will run ComputeAddrTaken() on function instantiations
    after stenciling. And it's not always correct, since we may not be able
    to distinguish between a array and a slice, if a type is dependent on a
    type param.
    
    However, we do need to call ComputeAddrTaken on instantiations created
    during inlining, since that is after the main ComputeAddrTaken pass.
    
    Fixes #49659
    
    Change-Id: I0bb610cf11f14e4aa9068f6ca2a012337b069c79
    Reviewed-on: https://go-review.googlesource.com/c/go/+/365214
    Trust: Dan Scales 
    Run-TryBot: Dan Scales 
    TryBot-Result: Go Bot 
    Reviewed-by: Keith Randall 
    ---
     src/cmd/compile/internal/ir/node.go        |  2 +-
     src/cmd/compile/internal/noder/stencil.go  |  7 ++++++
     src/cmd/compile/internal/typecheck/func.go |  7 +++++-
     test/typeparam/issue49659.dir/a.go         | 13 ++++++++++
     test/typeparam/issue49659.dir/b.go         | 15 ++++++++++++
     test/typeparam/issue49659.go               |  7 ++++++
     test/typeparam/issue49659b.go              | 28 ++++++++++++++++++++++
     7 files changed, 77 insertions(+), 2 deletions(-)
     create mode 100644 test/typeparam/issue49659.dir/a.go
     create mode 100644 test/typeparam/issue49659.dir/b.go
     create mode 100644 test/typeparam/issue49659.go
     create mode 100644 test/typeparam/issue49659b.go
    
    diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go
    index 8784f9ef99..4fdee5010b 100644
    --- a/src/cmd/compile/internal/ir/node.go
    +++ b/src/cmd/compile/internal/ir/node.go
    @@ -584,7 +584,7 @@ func OuterValue(n Node) Node {
     	for {
     		switch nn := n; nn.Op() {
     		case OXDOT:
    -			base.FatalfAt(n.Pos(), "OXDOT in walk: %v", n)
    +			base.FatalfAt(n.Pos(), "OXDOT in OuterValue: %v", n)
     		case ODOT:
     			nn := nn.(*SelectorExpr)
     			n = nn.X
    diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go
    index 174006ab5e..004db54c3b 100644
    --- a/src/cmd/compile/internal/noder/stencil.go
    +++ b/src/cmd/compile/internal/noder/stencil.go
    @@ -109,6 +109,13 @@ func (g *genInst) buildInstantiations(preinliningMainScan bool) {
     		// main round of inlining)
     		for _, fun := range g.newInsts {
     			inline.InlineCalls(fun.(*ir.Func))
    +			// New instantiations created during inlining should run
    +			// ComputeAddrTaken directly, since we are past the main pass
    +			// that did ComputeAddrTaken(). We could instead do this
    +			// incrementally during stenciling (for all instantiations,
    +			// including main ones before inlining), since we have the
    +			// type information.
    +			typecheck.ComputeAddrtaken(fun.(*ir.Func).Body)
     		}
     	}
     	assert(l == len(g.newInsts))
    diff --git a/src/cmd/compile/internal/typecheck/func.go b/src/cmd/compile/internal/typecheck/func.go
    index 7dec65c1d6..57b15b7a2b 100644
    --- a/src/cmd/compile/internal/typecheck/func.go
    +++ b/src/cmd/compile/internal/typecheck/func.go
    @@ -160,7 +160,12 @@ func ImportedBody(fn *ir.Func) {
     	IncrementalAddrtaken = false
     	defer func() {
     		if DirtyAddrtaken {
    -			ComputeAddrtaken(fn.Inl.Body) // compute addrtaken marks once types are available
    +			// We do ComputeAddrTaken on function instantiations, but not
    +			// generic functions (since we may not yet know if x in &x[i]
    +			// is an array or a slice).
    +			if !fn.Type().HasTParam() {
    +				ComputeAddrtaken(fn.Inl.Body) // compute addrtaken marks once types are available
    +			}
     			DirtyAddrtaken = false
     		}
     		IncrementalAddrtaken = true
    diff --git a/test/typeparam/issue49659.dir/a.go b/test/typeparam/issue49659.dir/a.go
    new file mode 100644
    index 0000000000..718bc0c5fc
    --- /dev/null
    +++ b/test/typeparam/issue49659.dir/a.go
    @@ -0,0 +1,13 @@
    +// Copyright 2021 The Go Authors. All rights reserved.
    +// Use of this source code is governed by a BSD-style
    +// license that can be found in the LICENSE file.
    +
    +package a
    +
    +type A[T any] struct {
    +	a int
    +}
    +
    +func (a A[T]) F() {
    +	_ = &a.a
    +}
    diff --git a/test/typeparam/issue49659.dir/b.go b/test/typeparam/issue49659.dir/b.go
    new file mode 100644
    index 0000000000..1f37153769
    --- /dev/null
    +++ b/test/typeparam/issue49659.dir/b.go
    @@ -0,0 +1,15 @@
    +// Copyright 2021 The Go Authors. All rights reserved.
    +// Use of this source code is governed by a BSD-style
    +// license that can be found in the LICENSE file.
    +
    +package b
    +
    +import "a"
    +
    +type B[T any] struct {
    +	v a.A[T]
    +}
    +
    +func (b B[T]) F() {
    +	b.v.F()
    +}
    diff --git a/test/typeparam/issue49659.go b/test/typeparam/issue49659.go
    new file mode 100644
    index 0000000000..87b4ff46c1
    --- /dev/null
    +++ b/test/typeparam/issue49659.go
    @@ -0,0 +1,7 @@
    +// compiledir -G=3
    +
    +// Copyright 2021 The Go Authors. All rights reserved.
    +// Use of this source code is governed by a BSD-style
    +// license that can be found in the LICENSE file.
    +
    +package ignored
    diff --git a/test/typeparam/issue49659b.go b/test/typeparam/issue49659b.go
    new file mode 100644
    index 0000000000..a9a14af77d
    --- /dev/null
    +++ b/test/typeparam/issue49659b.go
    @@ -0,0 +1,28 @@
    +// run -gcflags=-G=3
    +
    +// Copyright 2021 The Go Authors. All rights reserved.
    +// Use of this source code is governed by a BSD-style
    +// license that can be found in the LICENSE file.
    +
    +// Testing that AddrTaken logic doesn't cause problems for function instantiations
    +
    +package main
    +
    +type A[T interface{ []int | [5]int }] struct {
    +	val T
    +}
    +
    +//go:noinline
    +func (a A[T]) F() {
    +	_ = &a.val[2]
    +}
    +
    +func main() {
    +	var x A[[]int]
    +	x.val = make([]int, 4)
    +	_ = &x.val[3]
    +	x.F()
    +	var y A[[5]int]
    +	_ = &y.val[3]
    +	y.F()
    +}
    -- 
    GitLab
    
    
    From a94409660dbf05c1cdc2013aa2c7aa2489fe5c1c Mon Sep 17 00:00:00 2001
    From: Roland Shoemaker 
    Date: Thu, 18 Nov 2021 13:30:55 -0800
    Subject: [PATCH 2260/2500] internal/fuzz: compute correct number of mutations
    
    When reconstructing inputs, we miscalculated the number of mutations
    that needed to be applied. If the count%chainedMutation == 0 we would
    apply 0 mutations, when we should actually be applying chainedMutation
    mutations, due to how count is incremented.
    
    Fixes #49047
    
    Change-Id: I76773bff0afd6dfd40deafc317be095da995ecc5
    Reviewed-on: https://go-review.googlesource.com/c/go/+/365294
    Trust: Roland Shoemaker 
    Trust: Katie Hockman 
    Run-TryBot: Roland Shoemaker 
    Run-TryBot: Katie Hockman 
    Reviewed-by: Bryan C. Mills 
    Reviewed-by: Katie Hockman 
    TryBot-Result: Go Bot 
    ---
     src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt | 2 --
     src/internal/fuzz/worker.go                             | 3 ++-
     2 files changed, 2 insertions(+), 3 deletions(-)
    
    diff --git a/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt b/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt
    index 5b1e26be24..3764dcb915 100644
    --- a/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt
    +++ b/src/cmd/go/testdata/script/test_fuzz_mutator_repeat.txt
    @@ -1,5 +1,3 @@
    -skip  # https://golang.org/issue/49047
    -
     # TODO(jayconrod): support shared memory on more platforms.
     [!darwin] [!linux] [!windows] skip
     
    diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go
    index e7d824bea1..5be49d28f9 100644
    --- a/src/internal/fuzz/worker.go
    +++ b/src/internal/fuzz/worker.go
    @@ -1111,7 +1111,8 @@ func (wc *workerClient) fuzz(ctx context.Context, entryIn CorpusEntry, args fuzz
     		wc.m.r.restore(mem.header().randState, mem.header().randInc)
     		if !args.Warmup {
     			// Only mutate the valuesOut if fuzzing actually occurred.
    -			for i := int64(0); i < resp.Count%chainedMutations; i++ {
    +			numMutations := ((resp.Count - 1) % chainedMutations) + 1
    +			for i := int64(0); i < numMutations; i++ {
     				wc.m.mutate(valuesOut, cap(mem.valueRef()))
     			}
     		}
    -- 
    GitLab
    
    
    From 80cb59c0c15d2391f7b8d2571121f8213df70f7b Mon Sep 17 00:00:00 2001
    From: Roland Shoemaker 
    Date: Thu, 18 Nov 2021 11:40:48 -0800
    Subject: [PATCH 2261/2500] internal/fuzz: fix chunk swap mutator
    
    When swapping two chunks of bytes in a slice, don't pick chunks which
    extend beyond the end of the slice. Also don't pick chunks which
    intersect with each other.
    
    Fixes #49047
    
    Change-Id: I070eb1888d05ae849ec6122d01c40c45e602019f
    Reviewed-on: https://go-review.googlesource.com/c/go/+/365175
    Trust: Roland Shoemaker 
    Trust: Bryan C. Mills 
    Trust: Katie Hockman 
    Run-TryBot: Roland Shoemaker 
    TryBot-Result: Go Bot 
    Reviewed-by: Bryan C. Mills 
    Reviewed-by: Katie Hockman 
    ---
     src/internal/fuzz/mutators_byteslice.go      | 14 +++++++++++++-
     src/internal/fuzz/mutators_byteslice_test.go | 19 +++++++++++++------
     2 files changed, 26 insertions(+), 7 deletions(-)
    
    diff --git a/src/internal/fuzz/mutators_byteslice.go b/src/internal/fuzz/mutators_byteslice.go
    index 7c96b5920e..d9dab1df9f 100644
    --- a/src/internal/fuzz/mutators_byteslice.go
    +++ b/src/internal/fuzz/mutators_byteslice.go
    @@ -284,7 +284,19 @@ func byteSliceSwapBytes(m *mutator, b []byte) []byte {
     	for dst == src {
     		dst = m.rand(len(b))
     	}
    -	n := m.chooseLen(len(b) - src - 1)
    +	// Choose the random length as len(b) - max(src, dst)
    +	// so that we don't attempt to swap a chunk that extends
    +	// beyond the end of the slice
    +	max := dst
    +	if src > max {
    +		max = src
    +	}
    +	n := m.chooseLen(len(b) - max - 1)
    +	// Check that neither chunk intersect, so that we don't end up
    +	// duplicating parts of the input, rather than swapping them
    +	if src > dst && dst+n >= src || dst > src && src+n >= dst {
    +		return nil
    +	}
     	// Use the end of the slice as scratch space to avoid doing an
     	// allocation. If the slice is too small abort and try something
     	// else.
    diff --git a/src/internal/fuzz/mutators_byteslice_test.go b/src/internal/fuzz/mutators_byteslice_test.go
    index 50a39a9a5b..7886967881 100644
    --- a/src/internal/fuzz/mutators_byteslice_test.go
    +++ b/src/internal/fuzz/mutators_byteslice_test.go
    @@ -10,30 +10,31 @@ import (
     )
     
     type mockRand struct {
    +	values  []int
     	counter int
     	b       bool
     }
     
     func (mr *mockRand) uint32() uint32 {
    -	c := mr.counter
    +	c := mr.values[mr.counter]
     	mr.counter++
     	return uint32(c)
     }
     
     func (mr *mockRand) intn(n int) int {
    -	c := mr.counter
    +	c := mr.values[mr.counter]
     	mr.counter++
     	return c % n
     }
     
     func (mr *mockRand) uint32n(n uint32) uint32 {
    -	c := mr.counter
    +	c := mr.values[mr.counter]
     	mr.counter++
     	return uint32(c) % n
     }
     
     func (mr *mockRand) exp2() int {
    -	c := mr.counter
    +	c := mr.values[mr.counter]
     	mr.counter++
     	return c
     }
    @@ -56,6 +57,7 @@ func TestByteSliceMutators(t *testing.T) {
     	for _, tc := range []struct {
     		name     string
     		mutator  func(*mutator, []byte) []byte
    +		randVals []int
     		input    []byte
     		expected []byte
     	}{
    @@ -164,12 +166,17 @@ func TestByteSliceMutators(t *testing.T) {
     		{
     			name:     "byteSliceSwapBytes",
     			mutator:  byteSliceSwapBytes,
    +			randVals: []int{0, 2, 0, 2},
     			input:    append(make([]byte, 0, 9), []byte{1, 2, 3, 4}...),
    -			expected: []byte{2, 1, 3, 4},
    +			expected: []byte{3, 2, 1, 4},
     		},
     	} {
     		t.Run(tc.name, func(t *testing.T) {
    -			m := &mutator{r: &mockRand{}}
    +			r := &mockRand{values: []int{0, 1, 2, 3, 4, 5}}
    +			if tc.randVals != nil {
    +				r.values = tc.randVals
    +			}
    +			m := &mutator{r: r}
     			b := tc.mutator(m, tc.input)
     			if !bytes.Equal(b, tc.expected) {
     				t.Errorf("got %x, want %x", b, tc.expected)
    -- 
    GitLab
    
    
    From ac0da79a676c852fee4939b79baf97224cd0b334 Mon Sep 17 00:00:00 2001
    From: "Bryan C. Mills" 
    Date: Fri, 19 Nov 2021 12:51:25 -0500
    Subject: [PATCH 2262/2500] cmd/go: temporarily skip
     TestScript/test_fuzz_minimize
    
    This test is failing on the longtest builders.
    Adding a skip temporarily until it can be diagnosed and fixed.
    
    For #49685
    
    Change-Id: I0ceaf009f5029d1ad6f667f7cfee1f1605737bf3
    Reviewed-on: https://go-review.googlesource.com/c/go/+/365315
    Trust: Bryan C. Mills 
    Run-TryBot: Bryan C. Mills 
    TryBot-Result: Go Bot 
    Reviewed-by: Roland Shoemaker 
    ---
     src/cmd/go/testdata/script/test_fuzz_minimize.txt | 2 ++
     1 file changed, 2 insertions(+)
    
    diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize.txt b/src/cmd/go/testdata/script/test_fuzz_minimize.txt
    index a6dc3f1953..b591e90d16 100644
    --- a/src/cmd/go/testdata/script/test_fuzz_minimize.txt
    +++ b/src/cmd/go/testdata/script/test_fuzz_minimize.txt
    @@ -1,3 +1,5 @@
    +skip # flaky: https://golang.org/issue/49685
    +
     [!fuzz] skip
     [short] skip
     
    -- 
    GitLab
    
    
    From 0f75a9ecdf3f320a22e52d9493b879c4a6ddc536 Mon Sep 17 00:00:00 2001
    From: Jeremy Faller 
    Date: Fri, 19 Nov 2021 13:56:24 -0500
    Subject: [PATCH 2263/2500] [go] doc: add new bufio functionality
    
    cl/345570
    cl/345569
    
    Updates: #47694
    Change-Id: I170af16d5fc9f022d3d29ed0772cfc3d02b8bbcf
    Reviewed-on: https://go-review.googlesource.com/c/go/+/365317
    Trust: Jeremy Faller 
    Run-TryBot: Jeremy Faller 
    Reviewed-by: Joe Tsai 
    ---
     doc/go1.18.html | 10 ++++++++--
     1 file changed, 8 insertions(+), 2 deletions(-)
    
    diff --git a/doc/go1.18.html b/doc/go1.18.html
    index 1ad651ffe8..3018ed1b4a 100644
    --- a/doc/go1.18.html
    +++ b/doc/go1.18.html
    @@ -236,11 +236,17 @@ proposal.
     
    bufio

    - TODO: https://golang.org/cl/345569: add Writer.AvailableBuffer + The new Writer.AvailableBuffer + method returns an empty buffer with a possibly non-empty capacity for use + with append-like APIs. After appending, the buffer can be provided to a + succeeding Write call and possibly avoid any copying.

    - TODO: https://golang.org/cl/345570: make Reader.Reset and Writer.Reset work on the zero value + The methods Reader.Reset and + Writer.Reset + now use the default buffer size when called on objects with a + nil buffer.

    -- GitLab From aec5c2eed6e4342270ca778a29b50487f7922f83 Mon Sep 17 00:00:00 2001 From: Jeremy Faller Date: Fri, 19 Nov 2021 15:11:22 -0500 Subject: [PATCH 2264/2500] [go] doc: document speedups to Trim[|Left|Right] CL: #332771 Updates: #47694 Change-Id: I8c729084b7a8745ec73f87ef3c469edbd596ddb4 Reviewed-on: https://go-review.googlesource.com/c/go/+/365318 Trust: Jeremy Faller Run-TryBot: Jeremy Faller Reviewed-by: Joe Tsai --- doc/go1.18.html | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 3018ed1b4a..cc5c542746 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -254,7 +254,8 @@ proposal.
    bytes

    - TODO: https://golang.org/cl/332771: avoid allocations in Trim/TrimLeft/TrimRight + bytes.Trim and related + functions, have had their most common use cases optimized.

    @@ -394,7 +395,8 @@ proposal.

    - TODO: https://golang.org/cl/332771: avoid allocations in Trim/TrimLeft/TrimRight + strings.Trim and related functions + functions, have had their most common use cases optimized.

    -- GitLab From ba9f0f6665273ab5202d829ae4aa0c5fa2cebb32 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 12 Nov 2021 13:10:30 -0500 Subject: [PATCH 2265/2500] doc/go1.18: mention register ABI on ARM64 and PPC64 For #47694. Change-Id: Ide378f4a34587027c3d84fed2126c5b9bd8f7287 Reviewed-on: https://go-review.googlesource.com/c/go/+/363694 Trust: Cherry Mui Reviewed-by: Jeremy Faller --- doc/go1.18.html | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index cc5c542746..61bb8dbbcb 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -71,12 +71,6 @@ proposal. The GOAMD64 environment variable defaults to v1.

    -

    PPC64

    - -

    - TODO: https://golang.org/cl/353969: internal/buildcfg: enable register ABI for PPC64 -

    -

    RISC-V

    @@ -170,6 +164,25 @@ proposal.

    Compiler

    +

    + Go 1.17 implemented a new way of passing + function arguments and results using registers instead of the stack + on 64-bit x86 architecture on selected operating systems. + Go 1.18 expands the supported platforms to include 64-bit ARM (GOARCH=arm64), + big- and little-endian 64-bit PowerPC (GOARCH=ppc64, ppc64le), + as well as 64-bit x86 architecture (GOARCH=amd64) + on all operating systems. + On 64-bit ARM and 64-bit PowerPC systems, benchmarking shows + performance improvements of 10% or more. +

    + +

    + As mentioned in the Go 1.17 release notes, + this change does not affect the functionality of any safe Go code and + is designed to have no impact on most assembly code. See the + Go 1.17 release notes for more details. +

    +

    TODO: https://golang.org/cl/298611: cmd/compile: add -asan option

    -- GitLab From 6027b2183d9a63a11f92d392fd2296e7b88402fc Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Tue, 16 Nov 2021 12:33:03 -0800 Subject: [PATCH 2266/2500] crypto/x509/internal/macos: use APIs available on ios Use SecCertificateCopyData instead of SecItemExport, which is only available on macOS. Updates #49616 Change-Id: Ieda33894930d23c6dab6112ee18120f8a440083b Reviewed-on: https://go-review.googlesource.com/c/go/+/364554 Trust: Roland Shoemaker Run-TryBot: Roland Shoemaker Reviewed-by: Bryan C. Mills Reviewed-by: Filippo Valsorda --- src/crypto/x509/internal/macos/security.go | 27 +++++++++++----------- src/crypto/x509/internal/macos/security.s | 4 ++-- src/crypto/x509/root_darwin.go | 7 ++---- 3 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/crypto/x509/internal/macos/security.go b/src/crypto/x509/internal/macos/security.go index 661844a805..ef64bda49f 100644 --- a/src/crypto/x509/internal/macos/security.go +++ b/src/crypto/x509/internal/macos/security.go @@ -92,20 +92,6 @@ func SecTrustSettingsCopyCertificates(domain SecTrustSettingsDomain) (certArray } func x509_SecTrustSettingsCopyCertificates_trampoline() -const kSecFormatX509Cert int32 = 9 - -//go:cgo_import_dynamic x509_SecItemExport SecItemExport "/System/Library/Frameworks/Security.framework/Versions/A/Security" - -func SecItemExport(cert CFRef) (data CFRef, err error) { - ret := syscall(abi.FuncPCABI0(x509_SecItemExport_trampoline), uintptr(cert), uintptr(kSecFormatX509Cert), - 0 /* flags */, 0 /* keyParams */, uintptr(unsafe.Pointer(&data)), 0) - if ret != 0 { - return 0, OSStatus{"SecItemExport", int32(ret)} - } - return data, nil -} -func x509_SecItemExport_trampoline() - const errSecItemNotFound = -25300 //go:cgo_import_dynamic x509_SecTrustSettingsCopyTrustSettings SecTrustSettingsCopyTrustSettings "/System/Library/Frameworks/Security.framework/Versions/A/Security" @@ -233,3 +219,16 @@ func SecTrustGetCertificateAtIndex(trustObj CFRef, i int) CFRef { return CFRef(ret) } func x509_SecTrustGetCertificateAtIndex_trampoline() + +//go:cgo_import_dynamic x509_SecCertificateCopyData SecCertificateCopyData "/System/Library/Frameworks/Security.framework/Versions/A/Security" + +func SecCertificateCopyData(cert CFRef) ([]byte, error) { + ret := syscall(abi.FuncPCABI0(x509_SecCertificateCopyData_trampoline), uintptr(cert), 0, 0, 0, 0, 0) + if ret == 0 { + return nil, errors.New("x509: invalid certificate object") + } + b := CFDataToSlice(CFRef(ret)) + CFRelease(CFRef(ret)) + return b, nil +} +func x509_SecCertificateCopyData_trampoline() diff --git a/src/crypto/x509/internal/macos/security.s b/src/crypto/x509/internal/macos/security.s index cdef63f9f9..36f814f3cd 100644 --- a/src/crypto/x509/internal/macos/security.s +++ b/src/crypto/x509/internal/macos/security.s @@ -11,8 +11,6 @@ TEXT ·x509_SecTrustSettingsCopyCertificates_trampoline(SB),NOSPLIT,$0-0 JMP x509_SecTrustSettingsCopyCertificates(SB) -TEXT ·x509_SecItemExport_trampoline(SB),NOSPLIT,$0-0 - JMP x509_SecItemExport(SB) TEXT ·x509_SecTrustSettingsCopyTrustSettings_trampoline(SB),NOSPLIT,$0-0 JMP x509_SecTrustSettingsCopyTrustSettings(SB) TEXT ·x509_SecPolicyCopyProperties_trampoline(SB),NOSPLIT,$0-0 @@ -35,3 +33,5 @@ TEXT ·x509_SecTrustGetCertificateCount_trampoline(SB),NOSPLIT,$0-0 JMP x509_SecTrustGetCertificateCount(SB) TEXT ·x509_SecTrustGetCertificateAtIndex_trampoline(SB),NOSPLIT,$0-0 JMP x509_SecTrustGetCertificateAtIndex(SB) +TEXT ·x509_SecCertificateCopyData_trampoline(SB),NOSPLIT,$0-0 + JMP x509_SecCertificateCopyData(SB) diff --git a/src/crypto/x509/root_darwin.go b/src/crypto/x509/root_darwin.go index a7ff1e78bb..1ef9c0f71e 100644 --- a/src/crypto/x509/root_darwin.go +++ b/src/crypto/x509/root_darwin.go @@ -96,14 +96,11 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate // exportCertificate returns a *Certificate for a SecCertificateRef. func exportCertificate(cert macOS.CFRef) (*Certificate, error) { - data, err := macOS.SecItemExport(cert) + data, err := macOS.SecCertificateCopyData(cert) if err != nil { return nil, err } - defer macOS.CFRelease(data) - der := macOS.CFDataToSlice(data) - - return ParseCertificate(der) + return ParseCertificate(data) } func loadSystemRoots() (*CertPool, error) { -- GitLab From 5e774b0f5c9e9d5a0dab94620d2e0030226148c2 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 18 Nov 2021 16:07:13 -0500 Subject: [PATCH 2267/2500] net: simplify deadline fluctuation tests These tests were checking for fairly narrow timing windows, but were running in parallel and heavily dependent on timer and goroutine scheduling. This change eliminates unnecessary goroutines, runs the tests sequentially (dramatically shortening the timeouts to reduce the penalty of doing so), and uses timestamp comparison instead of background timers to hopefully gain some robustness from monotonic timestamps. Many of the other tests from this package would benefit from similar simplifications, which we can apply if and when we notice flaky failures or want to improve the latency of running the test. Fixes #36108 Change-Id: I17d8af7d2eefb1ec14fe0d9d891142a39599a562 Reviewed-on: https://go-review.googlesource.com/c/go/+/365334 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills Reviewed-by: Ian Lance Taylor TryBot-Result: Go Bot --- src/net/mockserver_test.go | 71 --------------- src/net/timeout_test.go | 178 +++++++++++++++++++++++++++++-------- 2 files changed, 141 insertions(+), 108 deletions(-) diff --git a/src/net/mockserver_test.go b/src/net/mockserver_test.go index 43b11a7218..70ecc69f66 100644 --- a/src/net/mockserver_test.go +++ b/src/net/mockserver_test.go @@ -11,7 +11,6 @@ import ( "fmt" "os" "sync" - "testing" "time" ) @@ -287,54 +286,6 @@ func transceiver(c Conn, wb []byte, ch chan<- error) { } } -func timeoutReceiver(c Conn, d, min, max time.Duration, ch chan<- error) { - var err error - defer func() { ch <- err }() - - t0 := time.Now() - if err = c.SetReadDeadline(time.Now().Add(d)); err != nil { - return - } - b := make([]byte, 256) - var n int - n, err = c.Read(b) - t1 := time.Now() - if n != 0 || err == nil || !err.(Error).Timeout() { - err = fmt.Errorf("Read did not return (0, timeout): (%d, %v)", n, err) - return - } - if dt := t1.Sub(t0); min > dt || dt > max && !testing.Short() { - err = fmt.Errorf("Read took %s; expected %s", dt, d) - return - } -} - -func timeoutTransmitter(c Conn, d, min, max time.Duration, ch chan<- error) { - var err error - defer func() { ch <- err }() - - t0 := time.Now() - if err = c.SetWriteDeadline(time.Now().Add(d)); err != nil { - return - } - var n int - for { - n, err = c.Write([]byte("TIMEOUT TRANSMITTER")) - if err != nil { - break - } - } - t1 := time.Now() - if err == nil || !err.(Error).Timeout() { - err = fmt.Errorf("Write did not return (any, timeout): (%d, %v)", n, err) - return - } - if dt := t1.Sub(t0); min > dt || dt > max && !testing.Short() { - err = fmt.Errorf("Write took %s; expected %s", dt, d) - return - } -} - func newLocalPacketListener(network string) (PacketConn, error) { switch network { case "udp": @@ -504,25 +455,3 @@ func packetTransceiver(c PacketConn, wb []byte, dst Addr, ch chan<- error) { ch <- fmt.Errorf("read %d; want %d", n, len(wb)) } } - -func timeoutPacketReceiver(c PacketConn, d, min, max time.Duration, ch chan<- error) { - var err error - defer func() { ch <- err }() - - t0 := time.Now() - if err = c.SetReadDeadline(time.Now().Add(d)); err != nil { - return - } - b := make([]byte, 256) - var n int - n, _, err = c.ReadFrom(b) - t1 := time.Now() - if n != 0 || err == nil || !err.(Error).Timeout() { - err = fmt.Errorf("ReadFrom did not return (0, timeout): (%d, %v)", n, err) - return - } - if dt := t1.Sub(t0); min > dt || dt > max && !testing.Short() { - err = fmt.Errorf("ReadFrom took %s; expected %s", dt, d) - return - } -} diff --git a/src/net/timeout_test.go b/src/net/timeout_test.go index 82069b347a..d345bf85ac 100644 --- a/src/net/timeout_test.go +++ b/src/net/timeout_test.go @@ -643,9 +643,24 @@ func TestWriteToTimeout(t *testing.T) { } } -func TestReadTimeoutFluctuation(t *testing.T) { - t.Parallel() +const ( + // minDynamicTimeout is the minimum timeout to attempt for + // tests that automatically increase timeouts until success. + // + // Lower values may allow tests to succeed more quickly if the value is close + // to the true minimum, but may require more iterations (and waste more time + // and CPU power on failed attempts) if the timeout is too low. + minDynamicTimeout = 1 * time.Millisecond + + // maxDynamicTimeout is the maximum timeout to attempt for + // tests that automatically increase timeouts until succeess. + // + // This should be a strict upper bound on the latency of the timeout: if a + // test would increase the timeout beyond this value, the test fails. + maxDynamicTimeout = 1 * time.Second +) +func TestReadTimeoutFluctuation(t *testing.T) { ln, err := newLocalListener("tcp") if err != nil { t.Fatal(err) @@ -658,27 +673,52 @@ func TestReadTimeoutFluctuation(t *testing.T) { } defer c.Close() - max := time.NewTimer(time.Second) - defer max.Stop() - ch := make(chan error) - go timeoutReceiver(c, 100*time.Millisecond, 50*time.Millisecond, 250*time.Millisecond, ch) + d := minDynamicTimeout + b := make([]byte, 256) + for { + t.Logf("SetReadDeadline(+%v)", d) + t0 := time.Now() + deadline := t0.Add(d) + if err = c.SetReadDeadline(deadline); err != nil { + t.Fatalf("SetReadDeadline(%v): %v", deadline, err) + } + var n int + n, err = c.Read(b) + t1 := time.Now() - select { - case <-max.C: - t.Fatal("Read took over 1s; expected 0.1s") - case err := <-ch: + if n != 0 || err == nil || !err.(Error).Timeout() { + t.Errorf("Read did not return (0, timeout): (%d, %v)", n, err) + } if perr := parseReadError(err); perr != nil { t.Error(perr) } if !isDeadlineExceeded(err) { - t.Fatal(err) + t.Errorf("Read error is not DeadlineExceeded: %v", err) + } + + actual := t1.Sub(t0) + if t1.Before(deadline) { + t.Errorf("Read took %s; expected at least %s", actual, d) } + if t.Failed() { + return + } + if actual > d*11/10 { + if actual > maxDynamicTimeout || d > maxDynamicTimeout/2 { + t.Fatalf("Read took %s; expected %v", actual, d) + } + // Maybe this machine is too slow to reliably schedule goroutines within + // the requested duration. Increase the timeout and try again. + t.Logf("Read took %s (expected %s); trying with longer timeout", actual, d) + d *= 2 + continue + } + + break } } func TestReadFromTimeoutFluctuation(t *testing.T) { - t.Parallel() - c1, err := newLocalPacketListener("udp") if err != nil { t.Fatal(err) @@ -691,27 +731,52 @@ func TestReadFromTimeoutFluctuation(t *testing.T) { } defer c2.Close() - max := time.NewTimer(time.Second) - defer max.Stop() - ch := make(chan error) - go timeoutPacketReceiver(c2.(PacketConn), 100*time.Millisecond, 50*time.Millisecond, 250*time.Millisecond, ch) + d := minDynamicTimeout + b := make([]byte, 256) + for { + t.Logf("SetReadDeadline(+%v)", d) + t0 := time.Now() + deadline := t0.Add(d) + if err = c2.SetReadDeadline(deadline); err != nil { + t.Fatalf("SetReadDeadline(%v): %v", deadline, err) + } + var n int + n, _, err = c2.(PacketConn).ReadFrom(b) + t1 := time.Now() - select { - case <-max.C: - t.Fatal("ReadFrom took over 1s; expected 0.1s") - case err := <-ch: + if n != 0 || err == nil || !err.(Error).Timeout() { + t.Errorf("ReadFrom did not return (0, timeout): (%d, %v)", n, err) + } if perr := parseReadError(err); perr != nil { t.Error(perr) } if !isDeadlineExceeded(err) { - t.Fatal(err) + t.Errorf("ReadFrom error is not DeadlineExceeded: %v", err) } + + actual := t1.Sub(t0) + if t1.Before(deadline) { + t.Errorf("ReadFrom took %s; expected at least %s", actual, d) + } + if t.Failed() { + return + } + if actual > d*11/10 { + if actual > maxDynamicTimeout || d > maxDynamicTimeout/2 { + t.Fatalf("ReadFrom took %s; expected %s", actual, d) + } + // Maybe this machine is too slow to reliably schedule goroutines within + // the requested duration. Increase the timeout and try again. + t.Logf("ReadFrom took %s (expected %s); trying with longer timeout", actual, d) + d *= 2 + continue + } + + break } } func TestWriteTimeoutFluctuation(t *testing.T) { - t.Parallel() - switch runtime.GOOS { case "plan9": t.Skipf("not supported on %s", runtime.GOOS) @@ -729,25 +794,64 @@ func TestWriteTimeoutFluctuation(t *testing.T) { } defer c.Close() - d := time.Second - if iOS() { - d = 3 * time.Second // see golang.org/issue/10775 - } - max := time.NewTimer(d) - defer max.Stop() - ch := make(chan error) - go timeoutTransmitter(c, 100*time.Millisecond, 50*time.Millisecond, 250*time.Millisecond, ch) + d := minDynamicTimeout + for { + t.Logf("SetWriteDeadline(+%v)", d) + t0 := time.Now() + deadline := t0.Add(d) + if err = c.SetWriteDeadline(deadline); err != nil { + t.Fatalf("SetWriteDeadline(%v): %v", deadline, err) + } + var n int64 + for { + var dn int + dn, err = c.Write([]byte("TIMEOUT TRANSMITTER")) + n += int64(dn) + if err != nil { + break + } + } + t1 := time.Now() - select { - case <-max.C: - t.Fatalf("Write took over %v; expected 0.1s", d) - case err := <-ch: + if err == nil || !err.(Error).Timeout() { + t.Fatalf("Write did not return (any, timeout): (%d, %v)", n, err) + } if perr := parseWriteError(err); perr != nil { t.Error(perr) } if !isDeadlineExceeded(err) { - t.Fatal(err) + t.Errorf("Write error is not DeadlineExceeded: %v", err) } + + actual := t1.Sub(t0) + if t1.Before(deadline) { + t.Errorf("Write took %s; expected at least %s", actual, d) + } + if t.Failed() { + return + } + if actual > d*11/10 { + if n > 0 { + // SetWriteDeadline specifies a time “after which I/O operations fail + // instead of blocking”. However, the kernel's send buffer is not yet + // full, we may be able to write some arbitrary (but finite) number of + // bytes to it without blocking. + t.Logf("Wrote %d bytes into send buffer; retrying until buffer is full", n) + if d <= maxDynamicTimeout/2 { + d *= 2 + } + } else if actual > maxDynamicTimeout || d > maxDynamicTimeout/2 { + t.Fatalf("Write took %s; expected %s", actual, d) + } else { + // Maybe this machine is too slow to reliably schedule goroutines within + // the requested duration. Increase the timeout and try again. + t.Logf("Write took %s (expected %s); trying with longer timeout", actual, d) + d *= 2 + } + continue + } + + break } } -- GitLab From b31dda8a2ad833ea5ec3c807119372b27cc0e782 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 18 Nov 2021 13:43:04 -0800 Subject: [PATCH 2268/2500] cmd/compile: handle `any` as alias like `byte` and `rune` `types.Types[types.TINTER]` is already used for `interface{}`, so we can conveniently just extend the existing logic that substitutes `byte` and `rune` with `uint8` and `int32` to also substitute `any`. Fixes #49665. Change-Id: I1ab1954699934150aab899b35037d5611c8ca47e Reviewed-on: https://go-review.googlesource.com/c/go/+/365354 Trust: Matthew Dempsky Trust: Dan Scales Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Dan Scales --- .../compile/internal/reflectdata/reflect.go | 5 +++-- src/cmd/compile/internal/types/fmt.go | 4 ++-- src/cmd/compile/internal/types/identity.go | 2 ++ src/cmd/compile/internal/types/type.go | 13 ++++++++++--- src/cmd/compile/internal/types/universe.go | 14 +++++++++----- test/fixedbugs/issue49665.go | 18 ++++++++++++++++++ test/fixedbugs/issue49665.out | 2 ++ 7 files changed, 46 insertions(+), 12 deletions(-) create mode 100644 test/fixedbugs/issue49665.go create mode 100644 test/fixedbugs/issue49665.out diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index f35baabbf9..142b289dae 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -924,11 +924,12 @@ func hashMightPanic(t *types.Type) bool { } } -// formalType replaces byte and rune aliases with real types. +// formalType replaces predeclared aliases with real types. // They've been separate internally to make error messages // better, but we have to merge them in the reflect tables. func formalType(t *types.Type) *types.Type { - if t == types.ByteType || t == types.RuneType { + switch t { + case types.AnyType, types.ByteType, types.RuneType: return types.Types[t.Kind()] } return t diff --git a/src/cmd/compile/internal/types/fmt.go b/src/cmd/compile/internal/types/fmt.go index b20d2e2908..3198a1f53c 100644 --- a/src/cmd/compile/internal/types/fmt.go +++ b/src/cmd/compile/internal/types/fmt.go @@ -328,8 +328,8 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type return } - if t == ByteType || t == RuneType { - // in %-T mode collapse rune and byte with their originals. + if t == AnyType || t == ByteType || t == RuneType { + // in %-T mode collapse predeclared aliases with their originals. switch mode { case fmtTypeIDName, fmtTypeID: t = Types[t.Kind()] diff --git a/src/cmd/compile/internal/types/identity.go b/src/cmd/compile/internal/types/identity.go index dce7d29143..89343b8419 100644 --- a/src/cmd/compile/internal/types/identity.go +++ b/src/cmd/compile/internal/types/identity.go @@ -58,6 +58,8 @@ func identical(t1, t2 *Type, flags int, assumedEqual map[typePair]struct{}) bool return (t1 == Types[TUINT8] || t1 == ByteType) && (t2 == Types[TUINT8] || t2 == ByteType) case TINT32: return (t1 == Types[TINT32] || t1 == RuneType) && (t2 == Types[TINT32] || t2 == RuneType) + case TINTER: + return (t1 == Types[TINTER] || t1 == AnyType) && (t2 == Types[TINTER] || t2 == AnyType) default: return false } diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 6288df30d6..b1194fa196 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -106,12 +106,16 @@ const ( // It also stores pointers to several special types: // - Types[TANY] is the placeholder "any" type recognized by SubstArgTypes. // - Types[TBLANK] represents the blank variable's type. +// - Types[TINTER] is the canonical "interface{}" type. // - Types[TNIL] represents the predeclared "nil" value's type. // - Types[TUNSAFEPTR] is package unsafe's Pointer type. var Types [NTYPE]*Type var ( - // Predeclared alias types. Kept separate for better error messages. + // Predeclared alias types. These are actually created as distinct + // defined types for better error messages, but are then specially + // treated as identical to their respective underlying types. + AnyType *Type ByteType *Type RuneType *Type @@ -119,8 +123,6 @@ var ( ErrorType *Type // Predeclared comparable interface type. ComparableType *Type - // Predeclared any interface type. - AnyType *Type // Types to represent untyped string and boolean constants. UntypedString = newType(TSTRING) @@ -1207,6 +1209,11 @@ func (t *Type) cmp(x *Type) Cmp { if (t == Types[RuneType.kind] || t == RuneType) && (x == Types[RuneType.kind] || x == RuneType) { return CMPeq } + + case TINTER: + if (t == Types[AnyType.kind] || t == AnyType) && (x == Types[AnyType.kind] || x == AnyType) { + return CMPeq + } } } diff --git a/src/cmd/compile/internal/types/universe.go b/src/cmd/compile/internal/types/universe.go index 13f62a3ab2..f845614e13 100644 --- a/src/cmd/compile/internal/types/universe.go +++ b/src/cmd/compile/internal/types/universe.go @@ -59,6 +59,7 @@ func InitTypes(defTypeName func(sym *Sym, typ *Type) Object) { Types[TANY] = newType(TANY) Types[TINTER] = NewInterface(LocalPkg, nil, false) + CheckSize(Types[TINTER]) defBasic := func(kind Kind, pkg *Pkg, name string) *Type { typ := newType(kind) @@ -108,11 +109,14 @@ func InitTypes(defTypeName func(sym *Sym, typ *Type) Object) { ResumeCheckSize() // any type (interface) - if base.Flag.G > 0 { - DeferCheckSize() - AnyType = defBasic(TFORW, BuiltinPkg, "any") - AnyType.SetUnderlying(NewInterface(NoPkg, []*Field{}, false)) - ResumeCheckSize() + DeferCheckSize() + AnyType = defBasic(TFORW, BuiltinPkg, "any") + AnyType.SetUnderlying(NewInterface(NoPkg, []*Field{}, false)) + ResumeCheckSize() + + if base.Flag.G == 0 { + ComparableType.Sym().Def = nil + AnyType.Sym().Def = nil } Types[TUNSAFEPTR] = defBasic(TUNSAFEPTR, UnsafePkg, "Pointer") diff --git a/test/fixedbugs/issue49665.go b/test/fixedbugs/issue49665.go new file mode 100644 index 0000000000..c6c22a1b4e --- /dev/null +++ b/test/fixedbugs/issue49665.go @@ -0,0 +1,18 @@ +// run + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "fmt" + +var x any +var y interface{} + +var _ = &x == &y // assert x and y have identical types + +func main() { + fmt.Printf("%T\n%T\n", &x, &y) +} diff --git a/test/fixedbugs/issue49665.out b/test/fixedbugs/issue49665.out new file mode 100644 index 0000000000..bd06d717cf --- /dev/null +++ b/test/fixedbugs/issue49665.out @@ -0,0 +1,2 @@ +*interface {} +*interface {} -- GitLab From 57aba325c8c34f3354abc24fca7bc9627949a1c8 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 19 Nov 2021 16:36:03 -0500 Subject: [PATCH 2269/2500] cmd/link: exit early when -d is used on libc platforms On platforms where we use libc for syscalls, we dynamically link with libc and therefore dynamic linking cannot be disabled. Exit early when -d is specified. Update #42459. Change-Id: I05abfe111df723b5ee512ceafef734e3804dd0a8 Reviewed-on: https://go-review.googlesource.com/c/go/+/365658 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/link/internal/ld/main.go | 4 ++++ src/cmd/link/internal/ld/target.go | 10 ++++++++++ src/cmd/link/internal/ld/xcoff.go | 4 ---- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go index a1d86965e4..26f9db8ec4 100644 --- a/src/cmd/link/internal/ld/main.go +++ b/src/cmd/link/internal/ld/main.go @@ -172,6 +172,10 @@ func Main(arch *sys.Arch, theArch Arch) { usage() } + if *FlagD && ctxt.UsesLibc() { + Exitf("dynamic linking required on %s; -d flag cannot be used", buildcfg.GOOS) + } + checkStrictDups = *FlagStrictDups if !buildcfg.Experiment.RegabiWrappers { diff --git a/src/cmd/link/internal/ld/target.go b/src/cmd/link/internal/ld/target.go index f68de8fff1..58d45d1504 100644 --- a/src/cmd/link/internal/ld/target.go +++ b/src/cmd/link/internal/ld/target.go @@ -185,3 +185,13 @@ func (t *Target) mustSetHeadType() { func (t *Target) IsBigEndian() bool { return t.Arch.ByteOrder == binary.BigEndian } + +func (t *Target) UsesLibc() bool { + t.mustSetHeadType() + switch t.HeadType { + case objabi.Haix, objabi.Hdarwin, objabi.Hopenbsd, objabi.Hsolaris, objabi.Hwindows: + // platforms where we use libc for syscalls. + return true + } + return false +} diff --git a/src/cmd/link/internal/ld/xcoff.go b/src/cmd/link/internal/ld/xcoff.go index aba6138c83..aaddf19d16 100644 --- a/src/cmd/link/internal/ld/xcoff.go +++ b/src/cmd/link/internal/ld/xcoff.go @@ -1290,10 +1290,6 @@ func Xcoffadddynrel(target *Target, ldr *loader.Loader, syms *ArchSyms, s loader } func (ctxt *Link) doxcoff() { - if *FlagD { - // All XCOFF files have dynamic symbols because of the syscalls. - Exitf("-d is not available on AIX") - } ldr := ctxt.loader // TOC -- GitLab From d2f4c935f2e247dd9949094c8a4f3ab8df2ba3a0 Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Wed, 17 Nov 2021 12:54:22 -0500 Subject: [PATCH 2270/2500] runtime/cgo: add example of Handle with void* parameter Fixes #49633 Change-Id: I12ca350f7dd6bfc8753a4a169f29b89ef219b035 Reviewed-on: https://go-review.googlesource.com/c/go/+/364774 Reviewed-by: Ian Lance Taylor Reviewed-by: Bryan C. Mills Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Trust: Bryan C. Mills --- misc/cgo/test/cgo_test.go | 1 + misc/cgo/test/test.go | 5 +++++ misc/cgo/test/testx.go | 25 +++++++++++++++++++++++++ src/runtime/cgo/handle.go | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+) diff --git a/misc/cgo/test/cgo_test.go b/misc/cgo/test/cgo_test.go index fe99e251e9..774277e10d 100644 --- a/misc/cgo/test/cgo_test.go +++ b/misc/cgo/test/cgo_test.go @@ -61,6 +61,7 @@ func Test32579(t *testing.T) { test32579(t) } func Test31891(t *testing.T) { test31891(t) } func Test42018(t *testing.T) { test42018(t) } func Test45451(t *testing.T) { test45451(t) } +func Test49633(t *testing.T) { test49633(t) } func TestAlign(t *testing.T) { testAlign(t) } func TestAtol(t *testing.T) { testAtol(t) } func TestBlocking(t *testing.T) { testBlocking(t) } diff --git a/misc/cgo/test/test.go b/misc/cgo/test/test.go index 3b8f548b13..dd81f770a2 100644 --- a/misc/cgo/test/test.go +++ b/misc/cgo/test/test.go @@ -915,6 +915,11 @@ void issue40494(enum Enum40494 e, union Union40494* up) {} // Issue 45451, bad handling of go:notinheap types. typedef struct issue45451Undefined issue45451; + +// Issue 49633, example of cgo.Handle with void*. +extern void GoFunc49633(void*); +void cfunc49633(void *context) { GoFunc49633(context); } + */ import "C" diff --git a/misc/cgo/test/testx.go b/misc/cgo/test/testx.go index 823c3e13d2..a61b47c41d 100644 --- a/misc/cgo/test/testx.go +++ b/misc/cgo/test/testx.go @@ -113,6 +113,8 @@ typedef struct { int i; } Issue38408, *PIssue38408; +extern void GoFunc49633(void *context); +extern void cfunc49633(void*); // definition is in test.go */ import "C" @@ -554,3 +556,26 @@ func GoFunc37033(handle C.uintptr_t) { // A typedef pointer can be used as the element type. // No runtime test; just make sure it compiles. var _ C.PIssue38408 = &C.Issue38408{i: 1} + +// issue 49633, example use of cgo.Handle with void* + +type data49633 struct { + msg string +} + +//export GoFunc49633 +func GoFunc49633(context unsafe.Pointer) { + h := *(*cgo.Handle)(context) + v := h.Value().(*data49633) + v.msg = "hello" +} + +func test49633(t *testing.T) { + v := &data49633{} + h := cgo.NewHandle(v) + defer h.Delete() + C.cfunc49633(unsafe.Pointer(&h)) + if v.msg != "hello" { + t.Errorf("msg = %q, want 'hello'", v.msg) + } +} diff --git a/src/runtime/cgo/handle.go b/src/runtime/cgo/handle.go index 720acca802..726f0a396d 100644 --- a/src/runtime/cgo/handle.go +++ b/src/runtime/cgo/handle.go @@ -59,6 +59,41 @@ import ( // void myprint(uintptr_t handle) { // MyGoPrint(handle); // } +// +// Some C functions accept a void* argument that points to an arbitrary +// data value supplied by the caller. It is not safe to coerce a cgo.Handle +// (an integer) to a Go unsafe.Pointer, but instead we can pass the address +// of the cgo.Handle to the void* parameter, as in this variant of the +// previous example: +// +// package main +// +// /* +// extern void MyGoPrint(void *context); +// static inline void myprint(void *context) { +// MyGoPrint(context); +// } +// */ +// import "C" +// import ( +// "runtime/cgo" +// "unsafe" +// ) +// +// //export MyGoPrint +// func MyGoPrint(context unsafe.Pointer) { +// h := *(*cgo.Handle)(context) +// val := h.Value().(string) +// println(val) +// h.Delete() +// } +// +// func main() { +// val := "hello Go" +// h := cgo.NewHandle(val) +// C.myprint(unsafe.Pointer(&h)) +// // Output: hello Go +// } type Handle uintptr // NewHandle returns a handle for a given value. -- GitLab From be18cd51dec6ac460949e96231dd05becc2cbcf7 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Fri, 19 Nov 2021 12:13:04 -0800 Subject: [PATCH 2271/2500] cmd/compile: ensure generic function is loaded when it needs to be re-exported In the case where we need to re-export a generic function/method from another package in the export data of the current package, make sure it is loaded before trying to write it out. Fixed #49667 Change-Id: I177754bb762689f34cf5c8ad246d43f1cdbbf195 Reviewed-on: https://go-review.googlesource.com/c/go/+/365837 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/typecheck/iexport.go | 6 ++++++ test/typeparam/issue49667.dir/a.go | 12 ++++++++++++ test/typeparam/issue49667.dir/b.go | 11 +++++++++++ test/typeparam/issue49667.dir/main.go | 11 +++++++++++ test/typeparam/issue49667.go | 7 +++++++ 5 files changed, 47 insertions(+) create mode 100644 test/typeparam/issue49667.dir/a.go create mode 100644 test/typeparam/issue49667.dir/b.go create mode 100644 test/typeparam/issue49667.dir/main.go create mode 100644 test/typeparam/issue49667.go diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index bf12ba803b..9bd1f626fe 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -1418,6 +1418,12 @@ func (w *exportWriter) funcExt(n *ir.Name) { w.uint64(1 + uint64(n.Func.Inl.Cost)) w.bool(n.Func.Inl.CanDelayResults) if n.Func.ExportInline() || n.Type().HasTParam() { + if n.Type().HasTParam() { + // If this generic function/method is from another + // package, but we didn't use for instantiation in + // this package, we may not yet have imported it. + ImportedBody(n.Func) + } w.p.doInline(n) } diff --git a/test/typeparam/issue49667.dir/a.go b/test/typeparam/issue49667.dir/a.go new file mode 100644 index 0000000000..3b1889f699 --- /dev/null +++ b/test/typeparam/issue49667.dir/a.go @@ -0,0 +1,12 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type A[T any] struct { +} + +func (a A[T]) F() { + _ = a +} diff --git a/test/typeparam/issue49667.dir/b.go b/test/typeparam/issue49667.dir/b.go new file mode 100644 index 0000000000..e7f781e4af --- /dev/null +++ b/test/typeparam/issue49667.dir/b.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package b + +import "a" + +type B[T any] struct { + _ a.A[T] +} diff --git a/test/typeparam/issue49667.dir/main.go b/test/typeparam/issue49667.dir/main.go new file mode 100644 index 0000000000..fccefe023f --- /dev/null +++ b/test/typeparam/issue49667.dir/main.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "b" + +func main() { + var _ b.B[int] +} diff --git a/test/typeparam/issue49667.go b/test/typeparam/issue49667.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/issue49667.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From 91abe4be0e8f3329bd891838fc047d83a5762c61 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Fri, 19 Nov 2021 17:52:41 -0800 Subject: [PATCH 2272/2500] test: fix -G=0 mode for longtest builder For -G=3 for test using 'any'. Change-Id: Ia37ee944a38be4f4330e62ad187f10f2d42e41bd Reviewed-on: https://go-review.googlesource.com/c/go/+/365839 Trust: Dan Scales Run-TryBot: Dan Scales Reviewed-by: Cuong Manh Le --- test/fixedbugs/issue49665.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fixedbugs/issue49665.go b/test/fixedbugs/issue49665.go index c6c22a1b4e..4a6593c454 100644 --- a/test/fixedbugs/issue49665.go +++ b/test/fixedbugs/issue49665.go @@ -1,4 +1,4 @@ -// run +// run -gcflags=-G=3 // Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style -- GitLab From 0c3b4a358ad6813d6aad111d0d0c45dce84cbeec Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 18 Nov 2021 12:16:39 -0800 Subject: [PATCH 2273/2500] spec: add type parameter lists Change-Id: I29e9188a0fa1326c2755a9b86aeb47feaa8019be Reviewed-on: https://go-review.googlesource.com/c/go/+/365274 Trust: Robert Griesemer Reviewed-by: Ian Lance Taylor --- doc/go_spec.html | 195 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 175 insertions(+), 20 deletions(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index 7c53a1eb91..0ce6a3ca18 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,6 +1,6 @@ @@ -849,8 +849,7 @@ Every type has a (possibly empty) method set associated with it:
  • -The method set of a pointer *T -to a defined type T +The method set of a pointer to a defined type T (where T is neither a pointer nor an interface) is the set of all methods declared with receiver *T or T.
  • @@ -2246,12 +2245,12 @@ type (

    A type definition creates a new, distinct type with the same -underlying type and operations as the given type, -and binds an identifier to it. +underlying type and operations as the given type +and binds an identifier, the type name, to it.

    -TypeDef = identifier Type .
    +TypeDef = identifier [ TypeParameters ] Type .
     

    @@ -2328,6 +2327,130 @@ func (tz TimeZone) String() string { }

    +

    +If the type definition specifies type parameters, +the type name denotes a parameterized type. +Parameterized types must be instantiated when they +are used. +

    + +
    +type List[T any] struct {
    +	next  *List[T]
    +	value T
    +}
    +
    +type Tree[T constraints.Ordered] struct {
    +	left, right *Tree[T]
    +	value       T
    +}
    +
    + +

    +The given type cannot be a type parameter in a type definition. +

    + +
    +type T[P any] P    // illegal: P is a type parameter
    +
    +func f[T any]() {
    +	type L T   // illegal: T is a type parameter declared by the enclosing function
    +}
    +
    + +

    +A parameterized type may also have methods associated with it. In this case, +the method receivers must declare the same number of type parameters as +present in the parameterized type definition. +

    + +
    +// The method Len returns the number of elements in the linked list l.
    +func (l *List[T]) Len() int  { … }
    +
    + +

    Type parameter lists

    + +

    +A type parameter list declares the type parameters +in a type-parameterized function or type declaration. +The type parameter list looks like an ordinary function parameter list +except that the type parameter names must all be present and the list is enclosed +in square brackets rather than parentheses. +

    + +
    +TypeParameters  = "[" TypeParamList [ "," ] "]" .
    +TypeParamList   = TypeParamDecl { "," TypeParamDecl } .
    +TypeParamDecl   = IdentifierList TypeConstraint .
    +
    + +

    +Each identifier declares a type parameter. +All non-blank names in the list must be unique. +Each type parameter is a new and different named type. +

    + +
    +[P any]
    +[S interface{ ~[]byte|string }]
    +[S ~[]E, E any]
    +[P Constraint[int]]
    +[_ any]
    +
    + +

    +Just as each ordinary function parameter has a parameter type, each type parameter +has a corresponding (meta-)type which is called its +type constraint. +

    + +

    +A parsing ambiguity arises when the type parameter list for a parameterized type +declares a single type parameter with a type constraint of the form *C +or (C): +

    + +
    +type T[P *C] …
    +type T[P (C)] …
    +
    + +

    +In these rare cases, the type parameter declaration is indistinguishable from +the expressions P*C or P(C) and the type declaration +is parsed as an array type declaration. +To resolve the ambiguity, embed the constraint in an interface: +

    + +
    +type T[P interface{*C}] …
    +
    + +

    Type constraints

    + +

    +A type constraint is an interface that determines the +set of permissible type arguments for the respective type parameter and controls the +operations supported by values of that type parameter. +

    + +
    +TypeConstraint = TypeElem .
    +
    + +

    +If the constraint is an interface literal containing exactly one embedded type element +interface{E}, in a type parameter list the enclosing interface{ … } +may be omitted for convenience: +

    + +
    +[T *P]                             // = [T interface{*P}]
    +[T ~int]                           // = [T interface{~int}]
    +[T int|string]                     // = [T interface{int|string}]
    +type Constraint ~int               // illegal: ~int is not inside a type parameter list
    +

    Variable declarations

    @@ -2437,13 +2560,19 @@ they can be used to declare local temporary variables.

    Function declarations

    + +

    A function declaration binds an identifier, the function name, to a function.

    -FunctionDecl = "func" FunctionName Signature [ FunctionBody ] .
    +FunctionDecl = "func" FunctionName [ TypeParameters ] Signature [ FunctionBody ] .
     FunctionName = identifier .
     FunctionBody = Block .
     
    @@ -2466,18 +2595,28 @@ func IndexRune(s string, r rune) int {

    -A function declaration may omit the body. Such a declaration provides the -signature for a function implemented outside Go, such as an assembly routine. +If the function declaration specifies type parameters, +the function name denotes a type-parameterized function. +Type-parameterized functions must be instantiated when they +are used.

    -func min(x int, y int) int {
    +func min[T constraints.Ordered](x, y T) T {
     	if x < y {
     		return x
     	}
     	return y
     }
    +
    +

    +A function declaration without type parameters may omit the body. +Such a declaration provides the signature for a function implemented outside Go, +such as an assembly routine. +

    + +
     func flushICache(begin, end uintptr)  // implemented externally
     
    @@ -2498,9 +2637,10 @@ Receiver = Parameters . The receiver is specified via an extra parameter section preceding the method name. That parameter section must declare a single non-variadic parameter, the receiver. Its type must be a defined type T or a -pointer to a defined type T. T is called the receiver -base type. A receiver base type cannot be a pointer or interface type and -it must be defined in the same package as the method. +pointer to a defined type T, possibly followed by a list of type parameter +names [P1, P2, …] enclosed in square brackets. +T is called the receiver base type. A receiver base type cannot be +a pointer or interface type and it must be defined in the same package as the method. The method is said to be bound to its receiver base type and the method name is visible only within selectors for type T or *T. @@ -2542,18 +2682,32 @@ to the base type Point.

    -The type of a method is the type of a function with the receiver as first -argument. For instance, the method Scale has type +If the receiver base type is a parameterized type, the +receiver specification must declare corresponding type parameters for the method +to use. This makes the receiver type parameters available to the method.

    -
    -func(p *Point, factor float64)
    -
    -

    -However, a function declared this way is not a method. +Syntactically, this type parameter declaration looks like an +instantiation of the receiver base type, except that +the type arguments are the type parameters being declared, one for each type parameter +of the receiver base type. +The type parameter names do not need to match their corresponding parameter names in the +receiver base type definition, and all non-blank parameter names must be unique in the +receiver parameter section and the method signature. +The receiver type parameter constraints are implied by the receiver base type definition: +corresponding type parameters have corresponding constraints.

    +
    +type Pair[A, B any] struct {
    +	a A
    +	b B
    +}
    +
    +func (p Pair[A, B]) Swap() Pair[A, B]  { return Pair[A, B]{p.b, p.a} }
    +func (p Pair[First, _]) First() First  { return p.a }
    +

    Expressions

    @@ -2823,6 +2977,7 @@ noteFrequency := map[string]float32{

    A function literal represents an anonymous function. +Function literals cannot declare type parameters.

    -- 
    GitLab
    
    
    From a287c4aa38c9c71f823a0c366871f7f4452a602c Mon Sep 17 00:00:00 2001
    From: Robert Griesemer 
    Date: Thu, 18 Nov 2021 15:33:19 -0800
    Subject: [PATCH 2274/2500] spec: add type parameter types
    
    - add section on type parameters
    - added two sections on the scope of type parameters
    - expanded general section on types accordingly
    - introduced the notion of a named type which will
      help in simplifying various rules (subsequent CLs)
    
    Change-Id: I49c1ed7d6d4f951d751f0a3ca5dfb637e49829f2
    Reviewed-on: https://go-review.googlesource.com/c/go/+/365414
    Trust: Robert Griesemer 
    Reviewed-by: Ian Lance Taylor 
    ---
     doc/go_spec.html | 62 +++++++++++++++++++++++++++++++++++++++++-------
     1 file changed, 53 insertions(+), 9 deletions(-)
    
    diff --git a/doc/go_spec.html b/doc/go_spec.html
    index 0ce6a3ca18..2120985b3b 100644
    --- a/doc/go_spec.html
    +++ b/doc/go_spec.html
    @@ -787,32 +787,46 @@ If a variable has not yet been assigned a value, its value is the
     
     

    A type determines a set of values together with operations and methods specific -to those values. A type may be denoted by a type name, if it has one, -or specified using a type literal, which composes a type from existing types. +to those values. A type may be denoted by a type name, if it has one, which must be +followed by type arguments if the type is parameterized. +A type may also be specified using a type literal, which composes a type +from existing types.

    -Type      = TypeName | TypeLit | "(" Type ")" .
    +Type      = TypeName [ TypeArgs ] | TypeLit | "(" Type ")" .
     TypeName  = identifier | QualifiedIdent .
    +TypeArgs  = "[" TypeList [ "," ] "]" .
    +TypeList  = Type { "," Type } .
     TypeLit   = ArrayType | StructType | PointerType | FunctionType | InterfaceType |
     	    SliceType | MapType | ChannelType .
     

    The language predeclares certain type names. -Others are introduced with type declarations. +Others are introduced with type declarations +or type parameter lists. Composite types—array, struct, pointer, function, interface, slice, map, and channel types—may be constructed using type literals.

    +

    +Predeclared types, defined types, and type parameters are called named types. +An alias denotes a named type if the type given in the alias declaration is a named type. +

    + +

    Underlying types

    +

    Each type T has an underlying type: If T is one of the predeclared boolean, numeric, or string types, or a type literal, -the corresponding underlying -type is T itself. Otherwise, T's underlying type -is the underlying type of the type to which T refers in its -type declaration. +the corresponding underlying type is T itself. +Otherwise, T's underlying type is the underlying type of the +type to which T refers in its type +declaration. Accordingly, the underlying type of a type parameter is the +underlying type of its type constraint, which +is always an interface.

    @@ -827,12 +841,15 @@ type (
     	B3 []B1
     	B4 B3
     )
    +
    +func f[P any](x P) { … }
     

    The underlying type of string, A1, A2, B1, and B2 is string. The underlying type of []B1, B3, and B4 is []B1. +The underlying type of P is interface{}.

    Method sets

    @@ -1706,6 +1723,25 @@ and a second goroutine receives them, the values are received in the order sent.

    +

    Type parameters

    + +

    +A type parameter is an (unqualified) type name declared in the +type parameter list of a +function declaration or +type definition; or in the receiver specification +of a method declaration that is associated +with a parameterized type. +A type parameter acts as a place holder for an (as of yet) unknown type in the declaration; +the type parameter is replaced with a type argument upon +instantiation of the parameterized function or type. +

    + +

    +The properties of a type parameter are determined by its +type constraint. +

    +

    Properties of types and values

    Type identity

    @@ -1983,6 +2019,15 @@ Go is lexically scoped using blocks:
  • The scope of an identifier denoting a method receiver, function parameter, or result variable is the function body.
  • +
  • The scope of an identifier denoting a type parameter of a type-parameterized function + or declared by a method receiver is the function body and all parameter lists of the + function. +
  • + +
  • The scope of an identifier denoting a type parameter of a parameterized type + begins after the name of the parameterized type and ends at the end + of the TypeSpec.
  • +
  • The scope of a constant or variable identifier declared inside a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl for short variable declarations) @@ -5384,7 +5429,6 @@ TypeSwitchStmt = "switch" [ SimpleStmt ";" ] TypeSwitchGuard "{" { TypeCaseClau TypeSwitchGuard = [ identifier ":=" ] PrimaryExpr "." "(" "type" ")" . TypeCaseClause = TypeSwitchCase ":" StatementList . TypeSwitchCase = "case" TypeList | "default" . -TypeList = Type { "," Type } .
  • -- GitLab From e30ebaab0bd5d95178f77cf40998ab14a0341d17 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 18 Nov 2021 17:52:24 -0800 Subject: [PATCH 2275/2500] spec: add section on the structure of interfaces This change introduces the notion of a structural interface and its corresponding structural type. Change-Id: Ib5442dfd04cb5950b4467428cae51849f8922272 Reviewed-on: https://go-review.googlesource.com/c/go/+/365474 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Ian Lance Taylor --- doc/go_spec.html | 66 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 4 deletions(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index 2120985b3b..bf589f0ae6 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1269,7 +1269,6 @@ func(int, int, float64) (float64, *[]int) func(n int) func(p *T) -

    Interface types

    @@ -1655,8 +1654,8 @@ ChannelType = ( "chan" | "chan" "<-" | "<-" "chan" ) ElementType .

    The optional <- operator specifies the channel direction, -send or receive. If no direction is given, the channel is -bidirectional. +send or receive. If a direction is given, the channel is directional, +otherwise it is bidirectional. A channel may be constrained only to send or only to receive by assignment or explicit conversion. @@ -1836,7 +1835,6 @@ created by distinct type definitions; are different because B0 is different from []string.

    -

    Assignability

    @@ -1928,6 +1926,66 @@ x T x is not representable by a value of T because 1e1000 float64 1e1000 overflows to IEEE +Inf after rounding +

    Structural interfaces

    + +

    +An interface T is called structural if one of the following +conditions is satisfied: +

    + +
      +
    1. +There is a single type U which is the underlying type +of all types in the type set of T; or +
    2. +
    3. +the type set of T contains only channel types +with identical element type E, and all directional channels have the same +direction. +
    4. +
    + +

    +A structural interface has a structural type which is, depending on the +condition that is satisfied, either: +

    + +
      +
    1. +the type U; or +
    2. +
    3. +the type chan E if T contains only bidirectional +channels, or the type chan<- E or <-chan E +depending on the direction of the directional channels present. +
    4. +
    + +

    +Examples of structural interfaces with their structural types: +

    + +
    +type Celsius float32
    +type Kelvin  float32
    +
    +interface{ int }                          // int
    +interface{ Celsius|Kelvin }               // float32
    +interface{ ~chan int }                    // chan int
    +interface{ ~chan int|~chan<- int }        // chan<- int
    +interface{ ~[]*data; String() string }    // []*data
    +
    + +

    +Examples of non-structural interfaces: +

    + +
    +interface{}                               // no single underlying type
    +interface{ Celsius|float64 }              // no single underlying type
    +interface{ chan int | chan<- string }     // channels have different element types
    +interface{ <-chan int | chan<- int }      // directional channels have different directions
    +

    Blocks

    -- GitLab From ffb6c798281f1a3ec54421a11573cec7d517d117 Mon Sep 17 00:00:00 2001 From: zhouguangyuan Date: Sun, 21 Nov 2021 21:06:27 +0800 Subject: [PATCH 2276/2500] go/types,types2: use allInteger to check type for shifted operand Fixes: #49705 Change-Id: I35a1c5f29b57f3facc5e89d33a8dec88e0ff4afa Reviewed-on: https://go-review.googlesource.com/c/go/+/365895 Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Griesemer Trust: Emmanuel Odeke --- src/cmd/compile/internal/types2/check_test.go | 1 + src/cmd/compile/internal/types2/expr.go | 2 +- .../internal/types2/testdata/fixedbugs/issue49705.go2 | 11 +++++++++++ src/go/types/check_test.go | 1 + src/go/types/expr.go | 2 +- src/go/types/testdata/fixedbugs/issue49705.go2 | 11 +++++++++++ 6 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue49705.go2 create mode 100644 src/go/types/testdata/fixedbugs/issue49705.go2 diff --git a/src/cmd/compile/internal/types2/check_test.go b/src/cmd/compile/internal/types2/check_test.go index a5ecdf8b81..f13679d1e3 100644 --- a/src/cmd/compile/internal/types2/check_test.go +++ b/src/cmd/compile/internal/types2/check_test.go @@ -99,6 +99,7 @@ func asGoVersion(s string) string { // TODO(gri) enable as soon as the unified build supports this. var excludedForUnifiedBuild = map[string]bool{ "issue47818.go2": true, + "issue49705.go2": true, } func testFiles(t *testing.T, filenames []string, colDelta uint, manual bool) { diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index b700716b0c..5961f32f37 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -625,7 +625,7 @@ func (check *Checker) updateExprType(x syntax.Expr, typ Type, final bool) { // If x is the lhs of a shift, its final type must be integer. // We already know from the shift check that it is representable // as an integer if it is a constant. - if !isInteger(typ) { + if !allInteger(typ) { check.errorf(x, invalidOp+"shifted operand %s (type %s) must be integer", x, typ) return } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49705.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49705.go2 new file mode 100644 index 0000000000..2b991b8722 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49705.go2 @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +import "constraints" + +func shl[I constraints.Integer](n int) I { + return 1 << n +} diff --git a/src/go/types/check_test.go b/src/go/types/check_test.go index 2f80d9b7b6..a3be47e371 100644 --- a/src/go/types/check_test.go +++ b/src/go/types/check_test.go @@ -205,6 +205,7 @@ func asGoVersion(s string) string { // TODO(gri) enable as soon as the unified build supports this. var excludedForUnifiedBuild = map[string]bool{ "issue47818.go2": true, + "issue49705.go2": true, } func testFiles(t *testing.T, sizes Sizes, filenames []string, srcs [][]byte, manual bool, imp Importer) { diff --git a/src/go/types/expr.go b/src/go/types/expr.go index e93a2bc7c8..c49865aec6 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -565,7 +565,7 @@ func (check *Checker) updateExprType(x ast.Expr, typ Type, final bool) { // If x is the lhs of a shift, its final type must be integer. // We already know from the shift check that it is representable // as an integer if it is a constant. - if !isInteger(typ) { + if !allInteger(typ) { check.invalidOp(x, _InvalidShiftOperand, "shifted operand %s (type %s) must be integer", x, typ) return } diff --git a/src/go/types/testdata/fixedbugs/issue49705.go2 b/src/go/types/testdata/fixedbugs/issue49705.go2 new file mode 100644 index 0000000000..2b991b8722 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue49705.go2 @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +import "constraints" + +func shl[I constraints.Integer](n int) I { + return 1 << n +} -- GitLab From b2aa1380d9ad9a46eb98cd2e1ad71fcbccdc2bd1 Mon Sep 17 00:00:00 2001 From: zhouguangyuan Date: Sat, 20 Nov 2021 01:49:32 +0800 Subject: [PATCH 2277/2500] A+C: add Zhou Guangyuan (individual CLA) Change-Id: I34b966b2f3de93a1d086be3dea5ebc6c60cf1eec Reviewed-on: https://go-review.googlesource.com/c/go/+/365754 Reviewed-by: Ian Lance Taylor Reviewed-by: Emmanuel Odeke --- AUTHORS | 1 + CONTRIBUTORS | 1 + 2 files changed, 2 insertions(+) diff --git a/AUTHORS b/AUTHORS index 8d7e196732..6f304f3672 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1479,6 +1479,7 @@ Zemanta d.o.o. Zev Goldstein Zheng Dayu Zhongtao Chen +Zhou Guangyuan Zhou Peng Ziad Hatahet Zizhao Zhang diff --git a/CONTRIBUTORS b/CONTRIBUTORS index a548cb0e2f..7f74b0ce5b 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -2746,6 +2746,7 @@ Zhengyu He Zhongpeng Lin Zhongtao Chen Zhongwei Yao +Zhou Guangyuan Zhou Peng Ziad Hatahet Ziheng Liu -- GitLab From e73c6c8808da281186a4d8f7107e34e9f7a4a9ee Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Thu, 18 Nov 2021 14:48:26 -0500 Subject: [PATCH 2278/2500] cmd/go: fix go work sync when there are zero workspace modules go work sync panics when there are no workspace modules. This is because the code that set the pruning mode only did so with modules present. This change changes pruningForGoVersion to properly return workspace pruning in workspace mode to prevent that. Another weird scenario can happen when there are no workspace modules, but the command-line-arguments module is created by default. Check for that when iterating over the workspace modules to avoid trying to find the nonexistant go.mod file for that modules. Fixes #49591 Change-Id: Iee8bc92a8aaf9c440f88fe4f9ca908a8d461cd36 Reviewed-on: https://go-review.googlesource.com/c/go/+/365234 Trust: Michael Matloob Trust: Bryan C. Mills Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/modload/modfile.go | 3 +++ src/cmd/go/internal/workcmd/sync.go | 7 +++++++ .../go/testdata/script/work_sync_missing_module.txt | 12 ++++++++++++ 3 files changed, 22 insertions(+) create mode 100644 src/cmd/go/testdata/script/work_sync_missing_module.txt diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index 40e6ed787d..7cc2272ea0 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -124,6 +124,9 @@ const ( ) func pruningForGoVersion(goVersion string) modPruning { + if inWorkspaceMode() { + return workspace + } if semver.Compare("v"+goVersion, ExplicitIndirectVersionV) < 0 { // The go.mod file does not duplicate relevant information about transitive // dependencies, so they cannot be pruned out. diff --git a/src/cmd/go/internal/workcmd/sync.go b/src/cmd/go/internal/workcmd/sync.go index 6f35dc4ff3..5f33e057f6 100644 --- a/src/cmd/go/internal/workcmd/sync.go +++ b/src/cmd/go/internal/workcmd/sync.go @@ -74,6 +74,13 @@ func runSync(ctx context.Context, cmd *base.Command, args []string) { workFilePath := modload.WorkFilePath() // save go.work path because EnterModule clobbers it. for _, m := range mms.Versions() { + if mms.ModRoot(m) == "" && m.Path == "command-line-arguments" { + // This is not a real module. + // TODO(#49228): Remove this special case once the special + // command-line-arguments module is gone. + continue + } + // Use EnterModule to reset the global state in modload to be in // single-module mode using the modroot of m. modload.EnterModule(ctx, mms.ModRoot(m)) diff --git a/src/cmd/go/testdata/script/work_sync_missing_module.txt b/src/cmd/go/testdata/script/work_sync_missing_module.txt new file mode 100644 index 0000000000..0018c733ee --- /dev/null +++ b/src/cmd/go/testdata/script/work_sync_missing_module.txt @@ -0,0 +1,12 @@ +# Ensure go work sync works without any modules in go.work. +go work sync + +# Ensure go work sync works even without a go.mod file. +rm go.mod +go work sync + +-- go.work -- +go 1.18 +-- go.mod -- +go 1.18 +module foo -- GitLab From 6275b54a2a58a1a1bed7f2cc3bc92eca5affb8ff Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 22 Nov 2021 14:37:19 +0000 Subject: [PATCH 2279/2500] Revert "cmd/go: temporarily skip TestScript/test_fuzz_minimize" This reverts CL 365315. Reason for revert: test may have been fixed by intervening changes. Change-Id: I110948d53a789527edf471f1637eadbd98a1fc5a Reviewed-on: https://go-review.googlesource.com/c/go/+/366074 Trust: Bryan C. Mills Trust: Katie Hockman Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/cmd/go/testdata/script/test_fuzz_minimize.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize.txt b/src/cmd/go/testdata/script/test_fuzz_minimize.txt index b591e90d16..a6dc3f1953 100644 --- a/src/cmd/go/testdata/script/test_fuzz_minimize.txt +++ b/src/cmd/go/testdata/script/test_fuzz_minimize.txt @@ -1,5 +1,3 @@ -skip # flaky: https://golang.org/issue/49685 - [!fuzz] skip [short] skip -- GitLab From cd0bf3896677583074d33af0b9e538f237db5394 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Fri, 19 Nov 2021 16:09:52 -0500 Subject: [PATCH 2280/2500] cmd/go: report a helpful error when there are no modules in workspace The current error message that no go.mod files were found is not helpful, especially when a go.mod file exists in the current directory. Fixes #49594 Change-Id: I750475ce8654eeb3e0a2857d5a2de1a9c6ede415 Reviewed-on: https://go-review.googlesource.com/c/go/+/365319 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/alldocs.go | 12 +++++++++++- src/cmd/go/internal/modload/init.go | 3 +++ src/cmd/go/internal/workcmd/work.go | 12 +++++++++++- .../go/testdata/script/work_build_no_modules.txt | 13 +++++++++++++ 4 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 src/cmd/go/testdata/script/work_build_no_modules.txt diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 6805d56e2c..296f8f8c6a 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -1371,7 +1371,7 @@ // // Workspace maintenance // -// Go workspace provides access to operations on worskpaces. +// Go workspace provides access to operations on workspaces. // // Note that support for workspaces is built into many other commands, // not just 'go work'. @@ -1379,6 +1379,16 @@ // See 'go help modules' for information about Go's module system of // which workspaces are a part. // +// A workspace is specified by a go.work file that specifies a set of +// module directories with the "use" directive. These modules are used +// as root modules by the go command for builds and related operations. +// A workspace that does not specify modules to be used cannot be used +// to do builds from local code. +// +// To determine whether the go command is operating in workspace mode, +// use the "go env GOWORK" command. This will specify the workspace +// file being used. +// // Usage: // // go work [arguments] diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 8bb3875e37..30fe446e43 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -525,6 +525,9 @@ func die() { if cfg.Getenv("GO111MODULE") == "off" { base.Fatalf("go: modules disabled by GO111MODULE=off; see 'go help modules'") } + if inWorkspaceMode() { + base.Fatalf("go: no modules were found in the current workspace; see 'go help work'") + } if dir, name := findAltConfig(base.Cwd()); dir != "" { rel, err := filepath.Rel(base.Cwd(), dir) if err != nil { diff --git a/src/cmd/go/internal/workcmd/work.go b/src/cmd/go/internal/workcmd/work.go index 98d5a01de6..a79eebe649 100644 --- a/src/cmd/go/internal/workcmd/work.go +++ b/src/cmd/go/internal/workcmd/work.go @@ -12,13 +12,23 @@ import ( var CmdWork = &base.Command{ UsageLine: "go work", Short: "workspace maintenance", - Long: `Go workspace provides access to operations on worskpaces. + Long: `Go workspace provides access to operations on workspaces. Note that support for workspaces is built into many other commands, not just 'go work'. See 'go help modules' for information about Go's module system of which workspaces are a part. + +A workspace is specified by a go.work file that specifies a set of +module directories with the "use" directive. These modules are used +as root modules by the go command for builds and related operations. +A workspace that does not specify modules to be used cannot be used +to do builds from local code. + +To determine whether the go command is operating in workspace mode, +use the "go env GOWORK" command. This will specify the workspace +file being used. `, Commands: []*base.Command{ diff --git a/src/cmd/go/testdata/script/work_build_no_modules.txt b/src/cmd/go/testdata/script/work_build_no_modules.txt new file mode 100644 index 0000000000..c9859b437e --- /dev/null +++ b/src/cmd/go/testdata/script/work_build_no_modules.txt @@ -0,0 +1,13 @@ +! go build . +stderr 'go: no modules were found in the current workspace; see ''go help work''' + +-- go.work -- +go 1.18 +-- go.mod -- +go 1.18 + +module foo +-- foo.go -- +package main + +func main() {} \ No newline at end of file -- GitLab From 9e94cc3666cc5ff6ecf5930fb5da48ba62ad8080 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 22 Nov 2021 09:50:47 -0500 Subject: [PATCH 2281/2500] misc/cgo/test: remove unnecessary forward declaration This test otherwise fails to build on windows/arm64 as of CL 364774 due to a warning (promoted to an error) about a mismatched dllexport attribute. Fortunately, it seems not to need the forward-declared function in this file anyway. Updates #49633 Updates #49721 Change-Id: Ia4698b85077d0718a55d2cc667a7950f1d8e50ab Reviewed-on: https://go-review.googlesource.com/c/go/+/366075 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- misc/cgo/test/testx.go | 1 - 1 file changed, 1 deletion(-) diff --git a/misc/cgo/test/testx.go b/misc/cgo/test/testx.go index a61b47c41d..8ec84a8b22 100644 --- a/misc/cgo/test/testx.go +++ b/misc/cgo/test/testx.go @@ -113,7 +113,6 @@ typedef struct { int i; } Issue38408, *PIssue38408; -extern void GoFunc49633(void *context); extern void cfunc49633(void*); // definition is in test.go */ import "C" -- GitLab From 2d7ae3fbd86d4b5471ac4044ece208b29cd0ef74 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 22 Nov 2021 10:21:19 -0500 Subject: [PATCH 2282/2500] net: diagnose unexpected nils in TestUnixAndUnixpacketServer For #34611 Change-Id: I31894d58498b2c290ecceccfc004bc817f8969c9 Reviewed-on: https://go-review.googlesource.com/c/go/+/366114 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills Reviewed-by: Ian Lance Taylor --- src/net/server_test.go | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/net/server_test.go b/src/net/server_test.go index 5192c1e0af..33d33b0337 100644 --- a/src/net/server_test.go +++ b/src/net/server_test.go @@ -7,7 +7,9 @@ package net import ( + "fmt" "os" + "reflect" "testing" ) @@ -187,7 +189,34 @@ func TestUnixAndUnixpacketServer(t *testing.T) { } t.Fatal(err) } - defer os.Remove(c.LocalAddr().String()) + + // We really just want to defer os.Remove(c.LocalAddr().String()) here, + // but sometimes that panics due to a nil dereference on the + // solaris-amd64-oraclerel builder (https://golang.org/issue/34611). + // The source of the nil panic is not obvious because there are many + // nillable types involved, so we will temporarily inspect all of them to + // try to get a better idea of what is happening on that platform. + checkNils := func() { + if c == nil { + panic("Dial returned a nil Conn") + } + if rc := reflect.ValueOf(c); rc.Kind() == reflect.Pointer && rc.IsNil() { + panic(fmt.Sprintf("Dial returned a nil %T", c)) + } + addr := c.LocalAddr() + if addr == nil { + panic(fmt.Sprintf("(%T).LocalAddr returned a nil Addr", c)) + } + if raddr := reflect.ValueOf(addr); raddr.Kind() == reflect.Pointer && raddr.IsNil() { + panic(fmt.Sprintf("(%T).LocalAddr returned a nil %T", c, addr)) + } + } + defer func() { + checkNils() + os.Remove(c.LocalAddr().String()) + }() + checkNils() + defer c.Close() trchs = append(trchs, make(chan error, 1)) go transceiver(c, []byte("UNIX AND UNIXPACKET SERVER TEST"), trchs[i]) -- GitLab From 5a3d871831c9febebe513863a26ecc6da1c9c4f3 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 22 Nov 2021 12:20:26 -0500 Subject: [PATCH 2283/2500] net: allow more generous slop in Fluctuation tests It appears that at least the OpenBSD kernel gets sloppier the longer the timeout we give it, up to an observed overhead of around 25%. Let's give it a little more than that (33%) in the comparison, and also increase the growth curve to match the actual observed times instead of exponential initial growth. Fixes #36108 Change-Id: Id3e54559b7c45b7c8bc0ca07dce74ca60e77e7ed Reviewed-on: https://go-review.googlesource.com/c/go/+/366176 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/net/timeout_test.go | 61 +++++++++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 15 deletions(-) diff --git a/src/net/timeout_test.go b/src/net/timeout_test.go index d345bf85ac..515aa07ec3 100644 --- a/src/net/timeout_test.go +++ b/src/net/timeout_test.go @@ -655,11 +655,37 @@ const ( // maxDynamicTimeout is the maximum timeout to attempt for // tests that automatically increase timeouts until succeess. // - // This should be a strict upper bound on the latency of the timeout: if a - // test would increase the timeout beyond this value, the test fails. - maxDynamicTimeout = 1 * time.Second + // This should be a strict upper bound on the latency required to hit a + // timeout accurately, even on a slow or heavily-loaded machine. If a test + // would increase the timeout beyond this value, the test fails. + maxDynamicTimeout = 4 * time.Second ) +// timeoutUpperBound returns the maximum time that we expect a timeout of +// duration d to take to return the caller. +func timeoutUpperBound(d time.Duration) time.Duration { + // In https://storage.googleapis.com/go-build-log/1e637cd3/openbsd-amd64-68_3585d3e7.log, + // we observed that an openbsd-amd64-68 builder took 636ms for a 512ms timeout + // (24.2% overhead). + return d * 4 / 3 +} + +// nextTimeout returns the next timeout to try after an operation took the given +// actual duration with a timeout shorter than that duration. +func nextTimeout(actual time.Duration) (next time.Duration, ok bool) { + if actual >= maxDynamicTimeout { + return maxDynamicTimeout, false + } + // Since the previous attempt took actual, we can't expect to beat that + // duration by any significant margin. Try the next attempt with an arbitrary + // factor above that, so that our growth curve is at least exponential. + next = actual * 5 / 4 + if next > maxDynamicTimeout { + return maxDynamicTimeout, true + } + return next, true +} + func TestReadTimeoutFluctuation(t *testing.T) { ln, err := newLocalListener("tcp") if err != nil { @@ -703,14 +729,15 @@ func TestReadTimeoutFluctuation(t *testing.T) { if t.Failed() { return } - if actual > d*11/10 { - if actual > maxDynamicTimeout || d > maxDynamicTimeout/2 { - t.Fatalf("Read took %s; expected %v", actual, d) + if want := timeoutUpperBound(d); actual > want { + next, ok := nextTimeout(actual) + if !ok { + t.Fatalf("Read took %s; expected at most %v", actual, want) } // Maybe this machine is too slow to reliably schedule goroutines within // the requested duration. Increase the timeout and try again. t.Logf("Read took %s (expected %s); trying with longer timeout", actual, d) - d *= 2 + d = next continue } @@ -761,14 +788,15 @@ func TestReadFromTimeoutFluctuation(t *testing.T) { if t.Failed() { return } - if actual > d*11/10 { - if actual > maxDynamicTimeout || d > maxDynamicTimeout/2 { - t.Fatalf("ReadFrom took %s; expected %s", actual, d) + if want := timeoutUpperBound(d); actual > want { + next, ok := nextTimeout(actual) + if !ok { + t.Fatalf("ReadFrom took %s; expected at most %s", actual, want) } // Maybe this machine is too slow to reliably schedule goroutines within // the requested duration. Increase the timeout and try again. t.Logf("ReadFrom took %s (expected %s); trying with longer timeout", actual, d) - d *= 2 + d = next continue } @@ -830,7 +858,7 @@ func TestWriteTimeoutFluctuation(t *testing.T) { if t.Failed() { return } - if actual > d*11/10 { + if want := timeoutUpperBound(d); actual > want { if n > 0 { // SetWriteDeadline specifies a time “after which I/O operations fail // instead of blocking”. However, the kernel's send buffer is not yet @@ -838,15 +866,18 @@ func TestWriteTimeoutFluctuation(t *testing.T) { // bytes to it without blocking. t.Logf("Wrote %d bytes into send buffer; retrying until buffer is full", n) if d <= maxDynamicTimeout/2 { + // We don't know how long the actual write loop would have taken if + // the buffer were full, so just guess and double the duration so that + // the next attempt can make twice as much progress toward filling it. d *= 2 } - } else if actual > maxDynamicTimeout || d > maxDynamicTimeout/2 { - t.Fatalf("Write took %s; expected %s", actual, d) + } else if next, ok := nextTimeout(actual); !ok { + t.Fatalf("Write took %s; expected at most %s", actual, want) } else { // Maybe this machine is too slow to reliably schedule goroutines within // the requested duration. Increase the timeout and try again. t.Logf("Write took %s (expected %s); trying with longer timeout", actual, d) - d *= 2 + d = next } continue } -- GitLab From 81031300a7139cfb59f704bcbb97e333590aacd0 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sun, 21 Nov 2021 16:19:26 -0800 Subject: [PATCH 2284/2500] misc/cgo/testcshared: skip TestGo2C2Go on Windows For #27019 Fixes #49457 Change-Id: I398abb7b555196ced34a6dd04b68195bf8bbdd38 Reviewed-on: https://go-review.googlesource.com/c/go/+/365994 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Emmanuel Odeke Reviewed-by: Cherry Mui Reviewed-by: Patrik Nyblom --- misc/cgo/testcshared/cshared_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/misc/cgo/testcshared/cshared_test.go b/misc/cgo/testcshared/cshared_test.go index 84b92d502f..13ec8761e8 100644 --- a/misc/cgo/testcshared/cshared_test.go +++ b/misc/cgo/testcshared/cshared_test.go @@ -781,10 +781,10 @@ func copyFile(t *testing.T, dst, src string) { func TestGo2C2Go(t *testing.T) { switch GOOS { - case "darwin", "ios": - // Darwin shared libraries don't support the multiple + case "darwin", "ios", "windows": + // Non-ELF shared libraries don't support the multiple // copies of the runtime package implied by this test. - t.Skip("linking c-shared into Go programs not supported on Darwin; issue 29061") + t.Skipf("linking c-shared into Go programs not supported on %s; issue 29061, 49457", GOOS) case "android": t.Skip("test fails on android; issue 29087") } -- GitLab From 8f559bcb4666b2358c227aa1bd3a82f3b806d45a Mon Sep 17 00:00:00 2001 From: Bharath Kumar Uppala Date: Sun, 21 Nov 2021 02:15:39 +0530 Subject: [PATCH 2285/2500] testing: mention that TB also covers the new type F Fixes #48146 Change-Id: I7c667a7915db81558514bc9fada6898c565eb0fd Reviewed-on: https://go-review.googlesource.com/c/go/+/365894 Reviewed-by: Emmanuel Odeke Reviewed-by: Katie Hockman Run-TryBot: Emmanuel Odeke TryBot-Result: Go Bot Trust: Katie Hockman Trust: Ian Lance Taylor --- src/testing/testing.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/testing/testing.go b/src/testing/testing.go index 3458b46d97..e4b7aa30e5 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -740,7 +740,7 @@ func fmtDuration(d time.Duration) string { return fmt.Sprintf("%.2fs", d.Seconds()) } -// TB is the interface common to T and B. +// TB is the interface common to T, B, and F. type TB interface { Cleanup(func()) Error(args ...interface{}) -- GitLab From 189b4a2f428be7264db76e5275c96d98b847383b Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 22 Nov 2021 14:01:26 -0500 Subject: [PATCH 2286/2500] cmd/go: forward the MallocNanoZone variable to script tests For #49138 Fixes #49723 Change-Id: Ia93130fdc042a1e2107be95cccd7e7eeaa909a87 Reviewed-on: https://go-review.googlesource.com/c/go/+/366254 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills Reviewed-by: Ian Lance Taylor --- src/cmd/go/script_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go index 98c1b68ed9..101195fc9d 100644 --- a/src/cmd/go/script_test.go +++ b/src/cmd/go/script_test.go @@ -146,6 +146,7 @@ var extraEnvKeys = []string{ "GO_TESTING_GOTOOLS", // for gccgo testing "GCCGO", // for gccgo testing "GCCGOTOOLDIR", // for gccgo testing + "MallocNanoZone", // Needed to work around an apparent kernel bug in macOS 12; see https://golang.org/issue/49138. } // setup sets up the test execution temporary directory and environment. -- GitLab From 773f43b35638092f9c0dc56f4a468dce2eb3a8ef Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 22 Nov 2021 12:47:53 -0500 Subject: [PATCH 2287/2500] go/types, types2: substitute for type parameters in signatures when comparing type identity Generic signatures should be considered identical modulo type parameter renaming. Update Identical to reflect this, by substituting type parameters. Fixes #49722 Change-Id: I33743768c72d8aa59c29bf72fcbabc5974f0b805 Reviewed-on: https://go-review.googlesource.com/c/go/+/366178 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/cmd/compile/internal/types2/api_test.go | 50 +++++++++++++ src/cmd/compile/internal/types2/predicates.go | 72 ++++++++++++------- src/go/types/api_test.go | 50 +++++++++++++ src/go/types/predicates.go | 72 ++++++++++++------- 4 files changed, 196 insertions(+), 48 deletions(-) diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index ca90e6b97d..9436a4ed97 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -1675,6 +1675,56 @@ func TestAssignableTo(t *testing.T) { } } +func TestIdentical(t *testing.T) { + // For each test, we compare the types of objects X and Y in the source. + tests := []struct { + src string + want bool + }{ + // Basic types. + {"var X int; var Y int", true}, + {"var X int; var Y string", false}, + + // TODO: add more tests for complex types. + + // Named types. + {"type X int; type Y int", false}, + + // Aliases. + {"type X = int; type Y = int", true}, + + // Functions. + {`func X(int) string { return "" }; func Y(int) string { return "" }`, true}, + {`func X() string { return "" }; func Y(int) string { return "" }`, false}, + {`func X(int) string { return "" }; func Y(int) {}`, false}, + + // Generic functions. Type parameters should be considered identical modulo + // renaming. See also issue #49722. + {`func X[P ~int](){}; func Y[Q ~int]() {}`, true}, + {`func X[P1 any, P2 ~*P1](){}; func Y[Q1 any, Q2 ~*Q1]() {}`, true}, + {`func X[P1 any, P2 ~[]P1](){}; func Y[Q1 any, Q2 ~*Q1]() {}`, false}, + {`func X[P ~int](P){}; func Y[Q ~int](Q) {}`, true}, + {`func X[P ~string](P){}; func Y[Q ~int](Q) {}`, false}, + {`func X[P ~int]([]P){}; func Y[Q ~int]([]Q) {}`, true}, + } + + for _, test := range tests { + pkg, err := pkgFor("test", "package p;"+test.src, nil) + if err != nil { + t.Errorf("%s: incorrect test case: %s", test.src, err) + continue + } + X := pkg.Scope().Lookup("X") + Y := pkg.Scope().Lookup("Y") + if X == nil || Y == nil { + t.Fatal("test must declare both X and Y") + } + if got := Identical(X.Type(), Y.Type()); got != test.want { + t.Errorf("Identical(%s, %s) = %t, want %t", X.Type(), Y.Type(), got, test.want) + } + } +} + func TestIdentical_issue15173(t *testing.T) { // Identical should allow nil arguments and be symmetric. for _, test := range []struct { diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index e7834a0f9e..cf2993f68b 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -235,19 +235,56 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { } case *Signature: - // Two function types are identical if they have the same number of parameters - // and result values, corresponding parameter and result types are identical, - // and either both functions are variadic or neither is. Parameter and result - // names are not required to match. - // Generic functions must also have matching type parameter lists, but for the - // parameter names. - if y, ok := y.(*Signature); ok { - return x.variadic == y.variadic && - identicalTParams(x.TypeParams().list(), y.TypeParams().list(), cmpTags, p) && - identical(x.params, y.params, cmpTags, p) && - identical(x.results, y.results, cmpTags, p) + y, _ := y.(*Signature) + if y == nil { + return false + } + + // Two function types are identical if they have the same number of + // parameters and result values, corresponding parameter and result types + // are identical, and either both functions are variadic or neither is. + // Parameter and result names are not required to match, and type + // parameters are considered identical modulo renaming. + + if x.TypeParams().Len() != y.TypeParams().Len() { + return false + } + + // In the case of generic signatures, we will substitute in yparams and + // yresults. + yparams := y.params + yresults := y.results + + if x.TypeParams().Len() > 0 { + // We must ignore type parameter names when comparing x and y. The + // easiest way to do this is to substitute x's type parameters for y's. + xtparams := x.TypeParams().list() + ytparams := y.TypeParams().list() + + var targs []Type + for i := range xtparams { + targs = append(targs, x.TypeParams().At(i)) + } + smap := makeSubstMap(ytparams, targs) + + var check *Checker // ok to call subst on a nil *Checker + + // Constraints must be pair-wise identical, after substitution. + for i, xtparam := range xtparams { + ybound := check.subst(nopos, ytparams[i].bound, smap, nil) + if !identical(xtparam.bound, ybound, cmpTags, p) { + return false + } + } + + yparams = check.subst(nopos, y.params, smap, nil).(*Tuple) + yresults = check.subst(nopos, y.results, smap, nil).(*Tuple) } + return x.variadic == y.variadic && + identical(x.params, yparams, cmpTags, p) && + identical(x.results, yresults, cmpTags, p) + case *Union: if y, _ := y.(*Union); y != nil { xset := computeUnionTypeSet(nil, nopos, x) @@ -389,19 +426,6 @@ func identicalInstance(xorig Type, xargs []Type, yorig Type, yargs []Type) bool return Identical(xorig, yorig) } -func identicalTParams(x, y []*TypeParam, cmpTags bool, p *ifacePair) bool { - if len(x) != len(y) { - return false - } - for i, x := range x { - y := y[i] - if !identical(x.bound, y.bound, cmpTags, p) { - return false - } - } - return true -} - // Default returns the default "typed" type for an "untyped" type; // it returns the incoming type for all other types. The default type // for untyped nil is untyped nil. diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index d8ca8ad611..c8fda5521a 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -1661,6 +1661,56 @@ func TestAssignableTo(t *testing.T) { } } +func TestIdentical(t *testing.T) { + // For each test, we compare the types of objects X and Y in the source. + tests := []struct { + src string + want bool + }{ + // Basic types. + {"var X int; var Y int", true}, + {"var X int; var Y string", false}, + + // TODO: add more tests for complex types. + + // Named types. + {"type X int; type Y int", false}, + + // Aliases. + {"type X = int; type Y = int", true}, + + // Functions. + {`func X(int) string { return "" }; func Y(int) string { return "" }`, true}, + {`func X() string { return "" }; func Y(int) string { return "" }`, false}, + {`func X(int) string { return "" }; func Y(int) {}`, false}, + + // Generic functions. Type parameters should be considered identical modulo + // renaming. See also issue #49722. + {`func X[P ~int](){}; func Y[Q ~int]() {}`, true}, + {`func X[P1 any, P2 ~*P1](){}; func Y[Q1 any, Q2 ~*Q1]() {}`, true}, + {`func X[P1 any, P2 ~[]P1](){}; func Y[Q1 any, Q2 ~*Q1]() {}`, false}, + {`func X[P ~int](P){}; func Y[Q ~int](Q) {}`, true}, + {`func X[P ~string](P){}; func Y[Q ~int](Q) {}`, false}, + {`func X[P ~int]([]P){}; func Y[Q ~int]([]Q) {}`, true}, + } + + for _, test := range tests { + pkg, err := pkgForMode("test", "package p;"+test.src, nil, 0) + if err != nil { + t.Errorf("%s: incorrect test case: %s", test.src, err) + continue + } + X := pkg.Scope().Lookup("X") + Y := pkg.Scope().Lookup("Y") + if X == nil || Y == nil { + t.Fatal("test must declare both X and Y") + } + if got := Identical(X.Type(), Y.Type()); got != test.want { + t.Errorf("Identical(%s, %s) = %t, want %t", X.Type(), Y.Type(), got, test.want) + } + } +} + func TestIdentical_issue15173(t *testing.T) { // Identical should allow nil arguments and be symmetric. for _, test := range []struct { diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 229a616eac..22ccdd7744 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -237,19 +237,56 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { } case *Signature: - // Two function types are identical if they have the same number of parameters - // and result values, corresponding parameter and result types are identical, - // and either both functions are variadic or neither is. Parameter and result - // names are not required to match. - // Generic functions must also have matching type parameter lists, but for the - // parameter names. - if y, ok := y.(*Signature); ok { - return x.variadic == y.variadic && - identicalTParams(x.TypeParams().list(), y.TypeParams().list(), cmpTags, p) && - identical(x.params, y.params, cmpTags, p) && - identical(x.results, y.results, cmpTags, p) + y, _ := y.(*Signature) + if y == nil { + return false + } + + // Two function types are identical if they have the same number of + // parameters and result values, corresponding parameter and result types + // are identical, and either both functions are variadic or neither is. + // Parameter and result names are not required to match, and type + // parameters are considered identical modulo renaming. + + if x.TypeParams().Len() != y.TypeParams().Len() { + return false + } + + // In the case of generic signatures, we will substitute in yparams and + // yresults. + yparams := y.params + yresults := y.results + + if x.TypeParams().Len() > 0 { + // We must ignore type parameter names when comparing x and y. The + // easiest way to do this is to substitute x's type parameters for y's. + xtparams := x.TypeParams().list() + ytparams := y.TypeParams().list() + + var targs []Type + for i := range xtparams { + targs = append(targs, x.TypeParams().At(i)) + } + smap := makeSubstMap(ytparams, targs) + + var check *Checker // ok to call subst on a nil *Checker + + // Constraints must be pair-wise identical, after substitution. + for i, xtparam := range xtparams { + ybound := check.subst(token.NoPos, ytparams[i].bound, smap, nil) + if !identical(xtparam.bound, ybound, cmpTags, p) { + return false + } + } + + yparams = check.subst(token.NoPos, y.params, smap, nil).(*Tuple) + yresults = check.subst(token.NoPos, y.results, smap, nil).(*Tuple) } + return x.variadic == y.variadic && + identical(x.params, yparams, cmpTags, p) && + identical(x.results, yresults, cmpTags, p) + case *Union: if y, _ := y.(*Union); y != nil { xset := computeUnionTypeSet(nil, token.NoPos, x) @@ -391,19 +428,6 @@ func identicalInstance(xorig Type, xargs []Type, yorig Type, yargs []Type) bool return Identical(xorig, yorig) } -func identicalTParams(x, y []*TypeParam, cmpTags bool, p *ifacePair) bool { - if len(x) != len(y) { - return false - } - for i, x := range x { - y := y[i] - if !identical(x.bound, y.bound, cmpTags, p) { - return false - } - } - return true -} - // Default returns the default "typed" type for an "untyped" type; // it returns the incoming type for all other types. The default type // for untyped nil is untyped nil. -- GitLab From 17aa21279965f5d088606639c17aa60208a34b7d Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 22 Nov 2021 14:30:40 -0500 Subject: [PATCH 2288/2500] runtime: in TestSpuriousWakeupsNeverHangSemasleep, wait for the runtime to register handlers According to https://man7.org/linux/man-pages/man7/signal.7.html, the default behavior of SIGIO is to terminate the program. The Go runtime changes that behavior with its own signal handler, so the program will terminate if we send the signal before the runtime has finished setting up. Fixes #49727 Change-Id: I65db66f5176831c8d7454eebc0138d825c68e100 Reviewed-on: https://go-review.googlesource.com/c/go/+/366255 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills Reviewed-by: Ian Lance Taylor --- src/runtime/semasleep_test.go | 41 +++++++++++++++++++------- src/runtime/testdata/testprog/sleep.go | 7 ++++- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/runtime/semasleep_test.go b/src/runtime/semasleep_test.go index cf4ef18208..bc73140a2a 100644 --- a/src/runtime/semasleep_test.go +++ b/src/runtime/semasleep_test.go @@ -7,6 +7,7 @@ package runtime_test import ( + "io" "os/exec" "syscall" "testing" @@ -28,6 +29,10 @@ func TestSpuriousWakeupsNeverHangSemasleep(t *testing.T) { start := time.Now() cmd := exec.Command(exe, "After1") + stdout, err := cmd.StdoutPipe() + if err != nil { + t.Fatalf("StdoutPipe: %v", err) + } if err := cmd.Start(); err != nil { t.Fatalf("Failed to start command: %v", err) } @@ -36,27 +41,43 @@ func TestSpuriousWakeupsNeverHangSemasleep(t *testing.T) { doneCh <- cmd.Wait() }() + // Wait for After1 to close its stdout so that we know the runtime's SIGIO + // handler is registered. + b, err := io.ReadAll(stdout) + if len(b) > 0 { + t.Logf("read from testprog stdout: %s", b) + } + if err != nil { + t.Fatalf("error reading from testprog: %v", err) + } + // With the repro running, we can continuously send to it - // a non-terminal signal such as SIGIO, to spuriously - // wakeup pthread_cond_timedwait_relative_np. - unfixedTimer := time.NewTimer(2 * time.Second) + // a signal that the runtime considers non-terminal, + // such as SIGIO, to spuriously wake up + // pthread_cond_timedwait_relative_np. + ticker := time.NewTicker(200 * time.Millisecond) + defer ticker.Stop() for { select { - case <-time.After(200 * time.Millisecond): + case now := <-ticker.C: + if now.Sub(start) > 2*time.Second { + t.Error("Program failed to return on time and has to be killed, issue #27520 still exists") + cmd.Process.Signal(syscall.SIGKILL) + <-doneCh + return + } + // Send the pesky signal that toggles spinning // indefinitely if #27520 is not fixed. cmd.Process.Signal(syscall.SIGIO) - case <-unfixedTimer.C: - t.Error("Program failed to return on time and has to be killed, issue #27520 still exists") - cmd.Process.Signal(syscall.SIGKILL) - return - case err := <-doneCh: if err != nil { t.Fatalf("The program returned but unfortunately with an error: %v", err) } - if time.Since(start) < 100*time.Millisecond { + if time.Since(start) < 1*time.Second { + // The program was supposed to sleep for a full (monotonic) second; + // it should not return before that has elapsed. t.Fatalf("The program stopped too quickly.") } return diff --git a/src/runtime/testdata/testprog/sleep.go b/src/runtime/testdata/testprog/sleep.go index 86e2f6cfe6..b230e60181 100644 --- a/src/runtime/testdata/testprog/sleep.go +++ b/src/runtime/testdata/testprog/sleep.go @@ -4,7 +4,10 @@ package main -import "time" +import ( + "os" + "time" +) // for golang.org/issue/27250 @@ -13,5 +16,7 @@ func init() { } func After1() { + os.Stdout.WriteString("ready\n") + os.Stdout.Close() <-time.After(1 * time.Second) } -- GitLab From f13fcd9e6839978b883016a50a4e61d4ba843335 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 22 Nov 2021 14:37:41 -0500 Subject: [PATCH 2289/2500] runtime: execute TestSpuriousWakeupsNeverHangSemasleep in parallel This test spends most of its time sleeping and waiting on a subprocess to sleep. It seems like a prime candidate to run in parallel, although we may need to relax its hard-coded 2s timeout on the sleep(1) subprocess. For #48770 Change-Id: I4e839739fe82446615f9894c1904c87e5f3cf386 Reviewed-on: https://go-review.googlesource.com/c/go/+/366256 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills Reviewed-by: Emmanuel Odeke Reviewed-by: Ian Lance Taylor TryBot-Result: Go Bot --- src/runtime/semasleep_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/runtime/semasleep_test.go b/src/runtime/semasleep_test.go index bc73140a2a..0057b0729e 100644 --- a/src/runtime/semasleep_test.go +++ b/src/runtime/semasleep_test.go @@ -21,6 +21,7 @@ func TestSpuriousWakeupsNeverHangSemasleep(t *testing.T) { if *flagQuick { t.Skip("-quick") } + t.Parallel() // Waits for a program to sleep for 1s. exe, err := buildTestProg(t, "testprog") if err != nil { -- GitLab From 100d7ea50dbe601164f428f5e4203be7727093f9 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Mon, 22 Nov 2021 15:37:29 -0500 Subject: [PATCH 2290/2500] cmd/go: correct an inaccuracy in the 'go help work' docs Change-Id: If2c6586b5ad212214b8041f8768fe7d26b877207 Reviewed-on: https://go-review.googlesource.com/c/go/+/366314 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/alldocs.go | 2 +- src/cmd/go/internal/workcmd/work.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 296f8f8c6a..12b64d309c 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -1383,7 +1383,7 @@ // module directories with the "use" directive. These modules are used // as root modules by the go command for builds and related operations. // A workspace that does not specify modules to be used cannot be used -// to do builds from local code. +// to do builds from local modules. // // To determine whether the go command is operating in workspace mode, // use the "go env GOWORK" command. This will specify the workspace diff --git a/src/cmd/go/internal/workcmd/work.go b/src/cmd/go/internal/workcmd/work.go index a79eebe649..3ddbfbe772 100644 --- a/src/cmd/go/internal/workcmd/work.go +++ b/src/cmd/go/internal/workcmd/work.go @@ -24,7 +24,7 @@ A workspace is specified by a go.work file that specifies a set of module directories with the "use" directive. These modules are used as root modules by the go command for builds and related operations. A workspace that does not specify modules to be used cannot be used -to do builds from local code. +to do builds from local modules. To determine whether the go command is operating in workspace mode, use the "go env GOWORK" command. This will specify the workspace -- GitLab From 11972353a67456d776cf891a9e46873e8a1fe630 Mon Sep 17 00:00:00 2001 From: Ryan Leung Date: Mon, 22 Nov 2021 02:41:07 +0000 Subject: [PATCH 2291/2500] cmd/go: allow a package that ends with _test having an internal test package Fixes #45477 Change-Id: I2f1ed281515ec40d31fd07ce9f4901777691bfa7 GitHub-Last-Rev: 7894d9400c95b8d84efe88f401fa75c3dd01921a GitHub-Pull-Request: golang/go#49673 Reviewed-on: https://go-review.googlesource.com/c/go/+/365534 Trust: Heschi Kreinick Reviewed-by: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot --- src/cmd/go/testdata/script/test_issue45477.txt | 12 ++++++++++++ src/go/build/build.go | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 src/cmd/go/testdata/script/test_issue45477.txt diff --git a/src/cmd/go/testdata/script/test_issue45477.txt b/src/cmd/go/testdata/script/test_issue45477.txt new file mode 100644 index 0000000000..f435b6a6f4 --- /dev/null +++ b/src/cmd/go/testdata/script/test_issue45477.txt @@ -0,0 +1,12 @@ +[short] skip # links and runs a test binary + +go test -v . + +-- go.mod -- +module example.com/pkg_test + +-- pkg.go -- +package pkg_test + +-- pkg_test.go -- +package pkg_test diff --git a/src/go/build/build.go b/src/go/build/build.go index eb47ffe285..6f7260b78f 100644 --- a/src/go/build/build.go +++ b/src/go/build/build.go @@ -894,7 +894,7 @@ Found: isTest := strings.HasSuffix(name, "_test.go") isXTest := false - if isTest && strings.HasSuffix(pkg, "_test") { + if isTest && strings.HasSuffix(pkg, "_test") && p.Name != pkg { isXTest = true pkg = pkg[:len(pkg)-len("_test")] } -- GitLab From 7fbe2f4cc877a02465f36e10e7547e03bcb6e1af Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 22 Nov 2021 12:21:12 -0800 Subject: [PATCH 2292/2500] doc/go1.18: document compiler change for "declared but not used" errors Fixes #49214. For #47694. Change-Id: Iba68ed17bfd81890309b6a6732087f87a03e1350 Reviewed-on: https://go-review.googlesource.com/c/go/+/366274 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- doc/go1.18.html | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/doc/go1.18.html b/doc/go1.18.html index 61bb8dbbcb..5f94aa86c4 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -29,6 +29,20 @@ Do not send CLs removing the interior tags from such phrases. TODO: complete this section

    +

    Bug fixes

    + +

    + The Go 1.18 compiler now correctly reports declared but not used errors + for variables that are set inside a function literal but are never used. Before Go 1.18, + the compiler did not report an error in such cases. This fixes long-outstanding compiler + issue #8560. As a result of this change, + (possibly incorrect) programs may not compile anymore. The necessary fix is + straightforward: fix the program if it was in fact incorrect, or use the offending + variable, for instance by assigning it to the blank identifier _. + Since go vet always pointed out this error, the number of affected + programs is likely very small. +

    +

    Generics

    -- GitLab From 7456b948532e752c0ea0ac98e56e6898271f4dcd Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 22 Nov 2021 12:33:11 -0800 Subject: [PATCH 2293/2500] doc/go1.18: document new overflow error for some untyped arguments to print/ln Fixes #49216. For #47694. Change-Id: Ib129d790c382ddcc9677d87db4ca827b7159856a Reviewed-on: https://go-review.googlesource.com/c/go/+/366275 Trust: Robert Griesemer Reviewed-by: Ian Lance Taylor --- doc/go1.18.html | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/doc/go1.18.html b/doc/go1.18.html index 5f94aa86c4..4175063edd 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -43,6 +43,19 @@ Do not send CLs removing the interior tags from such phrases. programs is likely very small.

    +

    + The Go 1.18 compiler now reports an overflow when passing a rune constant expression + such as '1' << 32 as an argument to the predeclared functions + print and println, consistent with the behavior of + user-defined functions. Before Go 1.18, the compiler did not report an error + in such cases but silently accepted such constant arguments if they fit into an + int64. As a result of this change, (possibly incorrect) programs + may not compile anymore. The necessary fix is straightforward: fix the program if it + was in fact incorrect, or explicitly convert the offending argument to the correct type. + Since go vet always pointed out this error, the number of affected + programs is likely very small. +

    +

    Generics

    -- GitLab From 0244343088e074c5f92b42a9812521f711a69410 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 22 Nov 2021 11:43:46 -0800 Subject: [PATCH 2294/2500] spec: fix Swap example (correctly swap type arguments and parameters) Thanks to @danscales for noticing the mistake. Change-Id: I547ee80a78419765b82d39d7b34dc8d3bf962c35 Reviewed-on: https://go-review.googlesource.com/c/go/+/366215 Trust: Robert Griesemer Reviewed-by: Ian Lance Taylor Reviewed-by: Dan Scales --- doc/go_spec.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index bf589f0ae6..ecd2f084c9 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,6 +1,6 @@ @@ -2808,7 +2808,7 @@ type Pair[A, B any] struct { b B } -func (p Pair[A, B]) Swap() Pair[A, B] { return Pair[A, B]{p.b, p.a} } +func (p Pair[A, B]) Swap() Pair[B, A] { return Pair[B, A]{p.b, p.a} } func (p Pair[First, _]) First() First { return p.a } -- GitLab From 9678f794149d07857cbf2a518bfc7aec532fb732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Thu, 18 Nov 2021 22:58:17 +0000 Subject: [PATCH 2295/2500] cmd/go: work out VCS information once per repository MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need VCS status information for each main package we load. If two main packages are under the same VCS repository, we can reuse that information to avoid duplicating work. For instance, the kubernetes holds 51 main packages in its root module, meaning that "go list ./..." repeated the same git calls 51 times. Instead, use a global par.Cache to deduplicate that work. Below are the numbers on kubernetes 5eb584d1cb6917, via "benchcmd -n 8 KubernetesListPackages go list ./...": name old time/op new time/op delta KubernetesListPackages 8.91s ± 0% 3.33s ± 1% -62.61% (p=0.000 n=7+8) name old user-time/op new user-time/op delta KubernetesListPackages 11.2s ± 1% 8.1s ± 2% -27.50% (p=0.000 n=7+8) name old sys-time/op new sys-time/op delta KubernetesListPackages 8.02s ± 0% 1.67s ± 6% -79.21% (p=0.001 n=6+8) name old peak-RSS-bytes new peak-RSS-bytes delta KubernetesListPackages 127MB ± 2% 123MB ± 7% ~ (p=0.328 n=8+8) Fixes #49582. Change-Id: Ib7ef5dc7a35c83a11e209441f5d6f3b8da068259 Reviewed-on: https://go-review.googlesource.com/c/go/+/365394 Trust: Daniel Martí Trust: Dominik Honnef Run-TryBot: Bryan C. Mills Reviewed-by: Bryan C. Mills TryBot-Result: Go Bot --- src/cmd/go/internal/load/pkg.go | 17 +++++++++++++++-- .../testdata/script/version_buildvcs_git.txt | 19 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index 360d265de6..41afa42f0f 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -2203,6 +2203,10 @@ func (p *Package) collectDeps() { } } +// vcsStatusCache maps repository directories (string) +// to their VCS information (vcsStatusError). +var vcsStatusCache par.Cache + // setBuildInfo gathers build information, formats it as a string to be // embedded in the binary, then sets p.Internal.BuildInfo to that string. // setBuildInfo should only be called on a main package with no errors. @@ -2365,11 +2369,20 @@ func (p *Package) setBuildInfo() { return } - st, err := vcsCmd.Status(vcsCmd, repoDir) - if err != nil { + type vcsStatusError struct { + Status vcs.Status + Err error + } + cached := vcsStatusCache.Do(repoDir, func() interface{} { + st, err := vcsCmd.Status(vcsCmd, repoDir) + return vcsStatusError{st, err} + }).(vcsStatusError) + if err := cached.Err; err != nil { setVCSError(err) return } + st := cached.Status + if st.Revision != "" { appendSetting(vcsCmd.Cmd+"revision", st.Revision) } diff --git a/src/cmd/go/testdata/script/version_buildvcs_git.txt b/src/cmd/go/testdata/script/version_buildvcs_git.txt index 3d56c6d8b4..72cbe28285 100644 --- a/src/cmd/go/testdata/script/version_buildvcs_git.txt +++ b/src/cmd/go/testdata/script/version_buildvcs_git.txt @@ -16,6 +16,7 @@ rm $GOBIN/a$GOEXE # If there is a repository, but it can't be used for some reason, # there should be an error. It should hint about -buildvcs=false. +# Also ensure that multiple errors are collected by "go list -e". cd .. mkdir .git env PATH=$WORK${/}fakebin${:}$oldpath @@ -24,6 +25,10 @@ chmod 0755 $WORK/fakebin/git cd a ! go install stderr '^error obtaining VCS status: exit status 1\n\tUse -buildvcs=false to disable VCS stamping.$' +go list -e -f '{{.ImportPath}}: {{.Error}}' ./... +stdout -count=1 '^example\.com/a: error obtaining VCS status' +stdout -count=1 '^example\.com/a/library: ' +stdout -count=1 '^example\.com/a/othermain: error obtaining VCS status' cd .. env PATH=$oldpath rm .git @@ -99,6 +104,14 @@ go version -m $GOBIN/d$GOEXE exec git checkout go.mod rm $GOBIN/d$GOEXE +# If we're loading multiple main packages, +# but they share the same VCS repository, +# we only need to execute VCS status commands once. +go list -x ./... +stdout -count=3 '^example.com' +stderr -count=1 '^git status' +stderr -count=1 '^git show' + -- $WORK/fakebin/git -- #!/bin/sh exit 1 @@ -114,6 +127,12 @@ go 1.18 -- repo/a/a.go -- package main +func main() {} +-- repo/a/library/f.go -- +package library +-- repo/a/othermain/f.go -- +package main + func main() {} -- repo/b/go.mod -- module example.com/b -- GitLab From 83bfed916b97d51646b4bdc95e0e0fd7798b754f Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 22 Nov 2021 13:53:21 -0800 Subject: [PATCH 2296/2500] cmd/compile/internal/types2: print "nil" rather than "untyped nil" When we have a typed nil, we already say so; thus it is sufficient to use "nil" in all the other cases. This is closer to (1.17) compiler behavior. In cases where the 1.17 compiler prints "untyped nil" (e.g., wrong uses of "copy"), we already print a different message. We can do better in those cases as well; will be addressed in a separate CL (see #49735). Fixes #48852. Change-Id: I9a7a72e0f99185b00f80040c5510a693b1ea80f6 Reviewed-on: https://go-review.googlesource.com/c/go/+/366276 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/assignments.go | 3 --- src/cmd/compile/internal/types2/operand.go | 2 +- .../internal/types2/testdata/check/stmt0.src | 6 +++--- .../types2/testdata/fixedbugs/issue49296.go2 | 2 +- .../types2/testdata/spec/assignability.go2 | 18 +++++++++--------- test/fixedbugs/issue6004.go | 9 ++++----- test/fixedbugs/issue6402.go | 2 +- test/fixedbugs/issue7223.go | 11 ++++++----- 8 files changed, 25 insertions(+), 28 deletions(-) diff --git a/src/cmd/compile/internal/types2/assignments.go b/src/cmd/compile/internal/types2/assignments.go index a3d32093d6..ac4f7b88a4 100644 --- a/src/cmd/compile/internal/types2/assignments.go +++ b/src/cmd/compile/internal/types2/assignments.go @@ -220,9 +220,6 @@ func (check *Checker) assignVar(lhs syntax.Expr, x *operand) Type { return nil case variable, mapindex: // ok - case nilvalue: - check.error(&z, "cannot assign to nil") // default would print "untyped nil" - return nil default: if sel, ok := z.expr.(*syntax.SelectorExpr); ok { var op operand diff --git a/src/cmd/compile/internal/types2/operand.go b/src/cmd/compile/internal/types2/operand.go index 6581d80323..f6bd0291ec 100644 --- a/src/cmd/compile/internal/types2/operand.go +++ b/src/cmd/compile/internal/types2/operand.go @@ -116,7 +116,7 @@ func operandString(x *operand, qf Qualifier) string { case nil, Typ[Invalid]: return "nil (with invalid type)" case Typ[UntypedNil]: - return "untyped nil" + return "nil" default: return fmt.Sprintf("nil (of type %s)", TypeString(x.typ, qf)) } diff --git a/src/cmd/compile/internal/types2/testdata/check/stmt0.src b/src/cmd/compile/internal/types2/testdata/check/stmt0.src index d744f2ba81..353444f068 100644 --- a/src/cmd/compile/internal/types2/testdata/check/stmt0.src +++ b/src/cmd/compile/internal/types2/testdata/check/stmt0.src @@ -69,10 +69,10 @@ func assignments1() { // test cases for issue 5800 var ( - _ int = nil /* ERROR "untyped nil" */ - _ [10]int = nil /* ERROR "untyped nil" */ + _ int = nil /* ERROR "nil" */ + _ [10]int = nil /* ERROR "nil" */ _ []byte = nil - _ struct{} = nil /* ERROR "untyped nil" */ + _ struct{} = nil /* ERROR "nil" */ _ func() = nil _ map[int]string = nil _ chan int = nil diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49296.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49296.go2 index 8f52acc8a4..eaa8e4dc7d 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49296.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49296.go2 @@ -9,7 +9,7 @@ func _[ T1 []int, T2 ~float64 | ~complex128 | chan int, ]() { - _ = T0(nil /* ERROR cannot convert untyped nil to T0 */ ) + _ = T0(nil /* ERROR cannot convert nil to T0 */ ) _ = T1(1 /* ERROR cannot convert 1 .* to T1 */ ) _ = T2(2 /* ERROR cannot convert 2 .* to T2 */ ) } diff --git a/src/cmd/compile/internal/types2/testdata/spec/assignability.go2 b/src/cmd/compile/internal/types2/testdata/spec/assignability.go2 index fb28358bbb..507fe6d021 100644 --- a/src/cmd/compile/internal/types2/testdata/spec/assignability.go2 +++ b/src/cmd/compile/internal/types2/testdata/spec/assignability.go2 @@ -153,28 +153,28 @@ func _[ // "x is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type" func _[TP Interface](X TP) { - b = nil // ERROR cannot use untyped nil - a = nil // ERROR cannot use untyped nil + b = nil // ERROR cannot use nil + a = nil // ERROR cannot use nil l = nil - s = nil // ERROR cannot use untyped nil + s = nil // ERROR cannot use nil p = nil f = nil i = nil m = nil c = nil - d = nil // ERROR cannot use untyped nil + d = nil // ERROR cannot use nil - B = nil // ERROR cannot use untyped nil - A = nil // ERROR cannot use untyped nil + B = nil // ERROR cannot use nil + A = nil // ERROR cannot use nil L = nil - S = nil // ERROR cannot use untyped nil + S = nil // ERROR cannot use nil P = nil F = nil I = nil M = nil C = nil - D = nil // ERROR cannot use untyped nil - X = nil // ERROR cannot use untyped nil + D = nil // ERROR cannot use nil + X = nil // ERROR cannot use nil } // "x is an untyped constant representable by a value of type T" diff --git a/test/fixedbugs/issue6004.go b/test/fixedbugs/issue6004.go index 2b3dcd923d..99d6ab85ea 100644 --- a/test/fixedbugs/issue6004.go +++ b/test/fixedbugs/issue6004.go @@ -7,9 +7,8 @@ package main func main() { - _ = nil // ERROR "use of untyped nil" - _, _ = nil, 1 // ERROR "use of untyped nil" - _, _ = 1, nil // ERROR "use of untyped nil" - _ = append(nil, 1, 2, 3) // ERROR "untyped nil" + _ = nil // ERROR "use of untyped nil" + _, _ = nil, 1 // ERROR "use of untyped nil" + _, _ = 1, nil // ERROR "use of untyped nil" + _ = append(nil, 1, 2, 3) // ERROR "untyped nil|nil" } - diff --git a/test/fixedbugs/issue6402.go b/test/fixedbugs/issue6402.go index 39cb9ac3f0..9977027d18 100644 --- a/test/fixedbugs/issue6402.go +++ b/test/fixedbugs/issue6402.go @@ -9,5 +9,5 @@ package p func f() uintptr { - return nil // ERROR "cannot use nil as type uintptr in return argument|incompatible type|cannot use untyped nil" + return nil // ERROR "cannot use nil as type uintptr in return argument|incompatible type|cannot use nil" } diff --git a/test/fixedbugs/issue7223.go b/test/fixedbugs/issue7223.go index c78de287ff..129e20f497 100644 --- a/test/fixedbugs/issue7223.go +++ b/test/fixedbugs/issue7223.go @@ -7,14 +7,15 @@ package main var bits1 uint = 10 + const bits2 uint = 10 func main() { _ = make([]byte, 1< Date: Tue, 23 Nov 2021 14:30:56 +0000 Subject: [PATCH 2297/2500] runtime: ensure no GC is running in TestParallelRWMutexReaders Currently this test makes it clear that it's unsafe for a GC to run, otherwise a deadlock could occur, so it calls SetGCPercent(-1). However, a GC may be actively in progress, and SetGCPercent is not going to end any in-progress GC. Call runtime.GC to block until at least the current GC is over. Updates #49680. Change-Id: Ibdc7d378e8cf7e05270910e92effcad8c6874e59 Reviewed-on: https://go-review.googlesource.com/c/go/+/366534 Trust: Michael Knyszek Run-TryBot: Michael Knyszek Reviewed-by: Than McIntosh Reviewed-by: Cherry Mui --- src/runtime/rwmutex_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/runtime/rwmutex_test.go b/src/runtime/rwmutex_test.go index 291a32ea5e..33ddd7d1d5 100644 --- a/src/runtime/rwmutex_test.go +++ b/src/runtime/rwmutex_test.go @@ -55,6 +55,9 @@ func TestParallelRWMutexReaders(t *testing.T) { // since the goroutines can't be stopped/preempted. // Disable GC for this test (see issue #10958). defer debug.SetGCPercent(debug.SetGCPercent(-1)) + // Finish any in-progress GCs and get ourselves to a clean slate. + GC() + doTestParallelReaders(1) doTestParallelReaders(3) doTestParallelReaders(4) -- GitLab From b90c6b99b3fbe60f4782c3e3b85f0ba9bbcf5f50 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Tue, 23 Nov 2021 10:54:49 -0500 Subject: [PATCH 2298/2500] misc/reboot: skip TestRepeatBootstrap on short builders This test is slow and resource-intensive, and will rarely catch failures. It is important to run sometimes, but probably a waste of time on smaller (and especially reverse) builders. Rather than hard-coding a list of small builders, only run it on the longtest builders. Fixes #35233 Fixes #30892 Fixes #49753 Change-Id: I25a9702e1f541246ea200fd7c79414ca5f69edae Reviewed-on: https://go-review.googlesource.com/c/go/+/366538 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills Reviewed-by: Ian Lance Taylor --- misc/reboot/reboot_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/misc/reboot/reboot_test.go b/misc/reboot/reboot_test.go index 6bafc608b5..ef164d3232 100644 --- a/misc/reboot/reboot_test.go +++ b/misc/reboot/reboot_test.go @@ -15,6 +15,10 @@ import ( ) func TestRepeatBootstrap(t *testing.T) { + if testing.Short() { + t.Skipf("skipping test that rebuilds the entire toolchain") + } + goroot, err := os.MkdirTemp("", "reboot-goroot") if err != nil { t.Fatal(err) -- GitLab From 00045b76e50d98db354aa185bcbd60a6f62499ac Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Tue, 23 Nov 2021 10:39:07 -0500 Subject: [PATCH 2299/2500] runtime: skip TestCgoCallbackGC on darwin-amd64-10_14 builder This test occasionally fails due to a real bug on this platform. Due to the age of the platform and the rarity of the failure, we do not believe that the bug is worth working around. Fixes #43926 Change-Id: Ia227c5afe81fc21b6630813228f976cc3a54013c Reviewed-on: https://go-review.googlesource.com/c/go/+/366537 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills Reviewed-by: Cherry Mui TryBot-Result: Go Bot --- src/runtime/crash_cgo_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go index 9a174fa549..45ee6d6905 100644 --- a/src/runtime/crash_cgo_test.go +++ b/src/runtime/crash_cgo_test.go @@ -64,6 +64,10 @@ func TestCgoCallbackGC(t *testing.T) { t.Skip("too slow for mips64x builders") } } + if testenv.Builder() == "darwin-amd64-10_14" { + // TODO(#23011): When the 10.14 builders are gone, remove this skip. + t.Skip("skipping due to platform bug on macOS 10.14; see https://golang.org/issue/43926") + } got := runTestProg(t, "testprogcgo", "CgoCallbackGC") want := "OK\n" if got != want { -- GitLab From 0f64c21d90c7017df4f199a5852d60d4b474c03c Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 19 Nov 2021 13:28:49 -0800 Subject: [PATCH 2300/2500] cmd/compile: special packages must not have any path separators We want to distinguish special compiler-generated package paths, like go.shape, from user paths, like go.opentelemetry.io/otel/semconv. The former have no slash in them. Writing a test for this seems hard, as the dependency we'd need to add would be non-hermetic. (Or it would need a new tricky run.go mode.) This CL does fix the example in the issue. Fixes #49606 Change-Id: I38f1b970b6dd31e0617763a27ff227e3afee74d5 Reviewed-on: https://go-review.googlesource.com/c/go/+/365834 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/types/pkg.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/types/pkg.go b/src/cmd/compile/internal/types/pkg.go index fe42049cee..0b822a450c 100644 --- a/src/cmd/compile/internal/types/pkg.go +++ b/src/cmd/compile/internal/types/pkg.go @@ -49,7 +49,7 @@ func NewPkg(path, name string) *Pkg { p := new(Pkg) p.Path = path p.Name = name - if strings.HasPrefix(path, "go.") { + if strings.HasPrefix(path, "go.") && !strings.Contains(path, "/") { // Special compiler-internal packages don't need to be escaped. // This particularly helps with the go.shape package. p.Prefix = path -- GitLab From e3eaedb5cf623d0836533573db4140749da42768 Mon Sep 17 00:00:00 2001 From: Chaoqun Han Date: Tue, 23 Nov 2021 22:05:40 +0800 Subject: [PATCH 2301/2500] os/signal: reset SIGURG in TestSignal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Accepting SIGURG signals could cause SIGURG to take up the entire channel buffer. Enhance the stability of test cases by: 1. Stop accepting the SIGURG signal by adding ‘Reset(sys call.SIGURG)’ 2. Close the c1 chan by adding ‘defer Stop(c1)’ (Another bug, NOT this bug) Fixes #49724 Change-Id: I909a9993f0f6dd109c15e48a861683b87dfc4ab3 Reviewed-on: https://go-review.googlesource.com/c/go/+/366514 Reviewed-by: Ian Lance Taylor Reviewed-by: Bryan C. Mills Trust: Bryan C. Mills --- src/os/signal/signal_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/os/signal/signal_test.go b/src/os/signal/signal_test.go index 3e85d936f8..e6fb24c6a8 100644 --- a/src/os/signal/signal_test.go +++ b/src/os/signal/signal_test.go @@ -136,6 +136,9 @@ func TestSignal(t *testing.T) { // Using 10 is arbitrary. c1 := make(chan os.Signal, 10) Notify(c1) + // Stop relaying the SIGURG signals. See #49724 + Reset(syscall.SIGURG) + defer Stop(c1) // Send this process a SIGWINCH t.Logf("sigwinch...") -- GitLab From 1ac45e026b2cbae91e3495e2cc6e93b6d505b4f4 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 23 Nov 2021 12:25:10 -0800 Subject: [PATCH 2302/2500] runtime: run the right test in TestCgoExternalThreadSignal The code was accidentally repeating the TestCgoExternalThreadSIGPROF test. While we're here remove an obsolete skip on ppc64/linux. Change-Id: Icdc4032a67aa80fbcfcd7c5c7ab8a6f23f321e2e Reviewed-on: https://go-review.googlesource.com/c/go/+/366755 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/runtime/crash_cgo_test.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go index 45ee6d6905..bfb260a143 100644 --- a/src/runtime/crash_cgo_test.go +++ b/src/runtime/crash_cgo_test.go @@ -94,11 +94,6 @@ func TestCgoExternalThreadSIGPROF(t *testing.T) { case "plan9", "windows": t.Skipf("no pthreads on %s", runtime.GOOS) } - if runtime.GOARCH == "ppc64" && runtime.GOOS == "linux" { - // TODO(austin) External linking not implemented on - // linux/ppc64 (issue #8912) - t.Skipf("no external linking on ppc64") - } exe, err := buildTestProg(t, "testprogcgo", "-tags=threadprof") if err != nil { @@ -128,7 +123,7 @@ func TestCgoExternalThreadSignal(t *testing.T) { t.Fatal(err) } - got, err := testenv.CleanCmdEnv(exec.Command(exe, "CgoExternalThreadSIGPROF")).CombinedOutput() + got, err := testenv.CleanCmdEnv(exec.Command(exe, "CgoExternalThreadSignal")).CombinedOutput() if err != nil { t.Fatalf("exit status: %v\n%s", err, got) } -- GitLab From 47db3bb443774c0b0df2cab188aa3d76b361dca2 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 23 Nov 2021 16:30:17 -0800 Subject: [PATCH 2303/2500] runtime: skip TestTimePprof if nanotime calls libc Fixes #43118 Change-Id: I499bf335904e2b72a2a8876d0368fff5e69aa7fa Reviewed-on: https://go-review.googlesource.com/c/go/+/366759 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Bryan C. Mills TryBot-Result: Go Bot --- src/runtime/crash_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/runtime/crash_test.go b/src/runtime/crash_test.go index 91a1a41ed5..1c28e47ac3 100644 --- a/src/runtime/crash_test.go +++ b/src/runtime/crash_test.go @@ -714,6 +714,13 @@ func TestBadTraceback(t *testing.T) { } func TestTimePprof(t *testing.T) { + // This test is unreliable on any system in which nanotime + // calls into libc. + switch runtime.GOOS { + case "aix", "darwin", "openbsd", "solaris": + t.Skipf("skipping on %s because nanotime calls libc", runtime.GOOS) + } + // Pass GOTRACEBACK for issue #41120 to try to get more // information on timeout. fn := runTestProg(t, "testprog", "TimeProf", "GOTRACEBACK=crash") -- GitLab From 465b4028082339bb7aa64ed6e30aef4c0b0413b4 Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Tue, 23 Nov 2021 08:19:45 -0500 Subject: [PATCH 2304/2500] cmd/compile/internal/inline: revise closure inl position fix This patch revises the fix for issue 46234, fixing a bug that was accidentally introduced by CL 320913. When inlining a chunk of code with a closure expression, we want to avoid updating the source positions in the function being closed over, but we do want to update the position for the ClosureExpr itself (since it is part of the function we are inlining). CL 320913 unintentionally did away with the closure expr source position update; here we restore it again. Updates #46234. Fixes #49171. Change-Id: Iaa51bc498e374b9e5a46fa0acd7db520edbbbfca Reviewed-on: https://go-review.googlesource.com/c/go/+/366494 Trust: Than McIntosh Trust: Dan Scales Reviewed-by: Dan Scales --- src/cmd/compile/internal/inline/inl.go | 15 ++++++++++----- test/closure3.dir/main.go | 8 ++++---- test/inline.go | 4 ++-- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index 47b895f7e3..716a7fbcd9 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -1108,11 +1108,15 @@ func (subst *inlsubst) clovar(n *ir.Name) *ir.Name { // closure does the necessary substitions for a ClosureExpr n and returns the new // closure node. func (subst *inlsubst) closure(n *ir.ClosureExpr) ir.Node { - // Prior to the subst edit, set a flag in the inlsubst to - // indicated that we don't want to update the source positions in - // the new closure. If we do this, it will appear that the closure - // itself has things inlined into it, which is not the case. See - // issue #46234 for more details. + // Prior to the subst edit, set a flag in the inlsubst to indicate + // that we don't want to update the source positions in the new + // closure function. If we do this, it will appear that the + // closure itself has things inlined into it, which is not the + // case. See issue #46234 for more details. At the same time, we + // do want to update the position in the new ClosureExpr (which is + // part of the function we're working on). See #49171 for an + // example of what happens if we miss that update. + newClosurePos := subst.updatedPos(n.Pos()) defer func(prev bool) { subst.noPosUpdate = prev }(subst.noPosUpdate) subst.noPosUpdate = true @@ -1175,6 +1179,7 @@ func (subst *inlsubst) closure(n *ir.ClosureExpr) ir.Node { // Actually create the named function for the closure, now that // the closure is inlined in a specific function. newclo := newfn.OClosure + newclo.SetPos(newClosurePos) newclo.SetInit(subst.list(n.Init())) return typecheck.Expr(newclo) } diff --git a/test/closure3.dir/main.go b/test/closure3.dir/main.go index 662a2e967b..7ef0a47595 100644 --- a/test/closure3.dir/main.go +++ b/test/closure3.dir/main.go @@ -94,10 +94,10 @@ func main() { return x + 2 } y, sink = func() (func(int) int, int) { // ERROR "can inline main.func12" - return func(x int) int { // ERROR "func literal does not escape" "can inline main.func12" + return func(x int) int { // ERROR "can inline main.func12" return x + 1 }, 42 - }() // ERROR "inlining call to main.func12" + }() // ERROR "func literal does not escape" "inlining call to main.func12" if y(40) != 41 { ppanic("y(40) != 41") } @@ -109,10 +109,10 @@ func main() { return x + 2 } y, sink = func() (func(int) int, int) { // ERROR "can inline main.func13.2" - return func(x int) int { // ERROR "func literal does not escape" "can inline main.func13.2" + return func(x int) int { // ERROR "can inline main.func13.2" return x + 1 }, 42 - }() // ERROR "inlining call to main.func13.2" + }() // ERROR "func literal does not escape" "inlining call to main.func13.2" if y(40) != 41 { ppanic("y(40) != 41") } diff --git a/test/inline.go b/test/inline.go index d0ebe84aa5..2780e10b19 100644 --- a/test/inline.go +++ b/test/inline.go @@ -92,9 +92,9 @@ func o() int { foo := func() int { return 1 } // ERROR "can inline o.func1" "func literal does not escape" func(x int) { // ERROR "can inline o.func2" if x > 10 { - foo = func() int { return 2 } // ERROR "func literal does not escape" "can inline o.func2" + foo = func() int { return 2 } // ERROR "can inline o.func2" } - }(11) // ERROR "inlining call to o.func2" + }(11) // ERROR "func literal does not escape" "inlining call to o.func2" return foo() } -- GitLab From 14f2b2a4c55b707828be2890b8c750cb849203f6 Mon Sep 17 00:00:00 2001 From: zhouguangyuan Date: Mon, 22 Nov 2021 23:39:52 +0800 Subject: [PATCH 2305/2500] cmd/internal/obj/x86: modify the threshold of assert loop for span6 Fixes: #49716 Change-Id: I7ed73f874c2ee1ee3f31c9c4428ed484167ca803 Reviewed-on: https://go-review.googlesource.com/c/go/+/366094 Reviewed-by: Cherry Mui Trust: Heschi Kreinick --- src/cmd/internal/obj/x86/asm6.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go index 6555756fd3..a508e484e4 100644 --- a/src/cmd/internal/obj/x86/asm6.go +++ b/src/cmd/internal/obj/x86/asm6.go @@ -2174,7 +2174,7 @@ func span6(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { } n++ - if n > 20 { + if n > 1000 { ctxt.Diag("span must be looping") log.Fatalf("loop") } -- GitLab From b38ab0ac5f78ac03a38052018ff629c03e36b864 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 23 Nov 2021 18:03:47 -0500 Subject: [PATCH 2306/2500] cmd/internal/objfile, debug/gosym: use the address of runtime.text as textStart Tools like objdump uses the pcln table to find the line number of a given PC. For a PIE binary, at least in some cases such as on macOS 12 with ld64-711, the table contains unrelocated address, which does not match the address in the symbol table, causing the lookup to fail. In Go 1.18 the pcln table is essentually position independent, except the start PC. Instead of reading the static content from the table, use the PC of runtime.text from the symbol table. While here, change the type of textStart to uint64. What matters here is the word size of the target program, not the host, so it shouldn't be uintptr. Fixes #49700. Change-Id: I517d79be7ba02dd4dd0275e75a11a136b08d76cd Reviewed-on: https://go-review.googlesource.com/c/go/+/366695 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/internal/objfile/objfile.go | 9 +++++++++ src/debug/gosym/pclntab.go | 8 ++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/cmd/internal/objfile/objfile.go b/src/cmd/internal/objfile/objfile.go index dcfd158ec2..d890a0b756 100644 --- a/src/cmd/internal/objfile/objfile.go +++ b/src/cmd/internal/objfile/objfile.go @@ -152,6 +152,15 @@ func (e *Entry) PCLineTable() (Liner, error) { if err != nil { return nil, err } + syms, err := e.raw.symbols() + if err == nil { + for _, s := range syms { + if s.Name == "runtime.text" { + textStart = s.Addr + break + } + } + } return gosym.NewTable(symtab, gosym.NewLineTable(pclntab, textStart)) } diff --git a/src/debug/gosym/pclntab.go b/src/debug/gosym/pclntab.go index a687c406b2..d9ae8b73a9 100644 --- a/src/debug/gosym/pclntab.go +++ b/src/debug/gosym/pclntab.go @@ -54,7 +54,7 @@ type LineTable struct { binary binary.ByteOrder quantum uint32 ptrsize uint32 - textStart uintptr // address of runtime.text symbol (1.18+) + textStart uint64 // address of runtime.text symbol (1.18+) funcnametab []byte cutab []byte funcdata []byte @@ -249,7 +249,7 @@ func (t *LineTable) parsePclnTab() { case ver118: t.nfunctab = uint32(offset(0)) t.nfiletab = uint32(offset(1)) - t.textStart = uintptr(offset(2)) + t.textStart = t.PC // use the start PC instead of reading from the table, which may be unrelocated t.funcnametab = data(3) t.cutab = data(4) t.filetab = data(5) @@ -402,7 +402,7 @@ func (f funcTab) Count() int { func (f funcTab) pc(i int) uint64 { u := f.uint(f.functab[2*i*f.sz:]) if f.version >= ver118 { - u += uint64(f.textStart) + u += f.textStart } return u } @@ -444,7 +444,7 @@ func (f *funcData) entryPC() uint64 { if f.t.version >= ver118 { // TODO: support multiple text sections. // See runtime/symtab.go:(*moduledata).textAddr. - return uint64(f.t.binary.Uint32(f.data)) + uint64(f.t.textStart) + return uint64(f.t.binary.Uint32(f.data)) + f.t.textStart } return f.t.uintptr(f.data) } -- GitLab From e883005d2ae5c9de0f3a072af53968da299bb8a8 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Wed, 24 Nov 2021 11:05:51 -0500 Subject: [PATCH 2307/2500] doc/go1.18: document that iOS 12 or newer is required For #47694. Updates #49616. Updates #48076. Change-Id: I570564c3a54d3cd9cfc9b8267df9fbee3363b650 Reviewed-on: https://go-review.googlesource.com/c/go/+/366914 Trust: Dmitri Shuralyov Reviewed-by: Cherry Mui --- doc/go1.18.html | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/go1.18.html b/doc/go1.18.html index 4175063edd..c6c338984c 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -105,6 +105,14 @@ proposal. now supports the c-archive and c-shared build modes.

    +

    iOS

    + +

    + On iOS (the ios/arm64 port) + and iOS simulator running on AMD64-based macOS (the ios/amd64 port), + Go 1.18 now requires iOS 12 or later; support for previous versions has been discontinued. +

    +

    Tools

    Go command

    -- GitLab From 4da06e7b00ae9965ec7d2f6f131266e44f966754 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Fri, 19 Nov 2021 16:09:52 -0500 Subject: [PATCH 2308/2500] cmd/go: fix bug in using the workfile flag with tests Tests do custom flag processing so we must process the workfile flag after that happens. Also fix an issue where errors weren't handled properly when the workfile wasn't absolute (the go command should just exit), and where a parse error was just dropped. Fixes #48576 Change-Id: I3a94d8d3a515114b2c4cc0e73f63447df2fc6bc9 Reviewed-on: https://go-review.googlesource.com/c/go/+/366174 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/modload/init.go | 5 ++--- src/cmd/go/internal/test/test.go | 2 +- src/cmd/go/testdata/script/work_workfile.txt | 21 ++++++++++++++++++++ 3 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 src/cmd/go/testdata/script/work_workfile.txt diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 30fe446e43..943547e71b 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -294,7 +294,7 @@ func InitWorkfile() { workFilePath = findWorkspaceFile(base.Cwd()) default: if !filepath.IsAbs(cfg.WorkFile) { - base.Errorf("the path provided to -workfile must be an absolute path") + base.Fatalf("the path provided to -workfile must be an absolute path") } workFilePath = cfg.WorkFile } @@ -590,9 +590,8 @@ func ReadWorkFile(path string) (*modfile.WorkFile, error) { if err != nil { return nil, err } - wf, err := modfile.ParseWork(path, workData, nil) - return wf, nil + return modfile.ParseWork(path, workData, nil) } // WriteWorkFile cleans and writes out the go.work file to the given path. diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index b7bbcb4513..7ea9d4f1f1 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -619,8 +619,8 @@ var defaultVetFlags = []string{ } func runTest(ctx context.Context, cmd *base.Command, args []string) { - modload.InitWorkfile() pkgArgs, testArgs = testFlags(args) + modload.InitWorkfile() // The test command does custom flag processing; initialize workspaces after that. if cfg.DebugTrace != "" { var close func() error diff --git a/src/cmd/go/testdata/script/work_workfile.txt b/src/cmd/go/testdata/script/work_workfile.txt new file mode 100644 index 0000000000..b62918147e --- /dev/null +++ b/src/cmd/go/testdata/script/work_workfile.txt @@ -0,0 +1,21 @@ +! go list -workfile=stop.work a # require absolute path +! stderr panic +! go list -workfile=doesnotexist a +! stderr panic + +go list -n -workfile=$GOPATH/src/stop.work a +go build -n -workfile=$GOPATH/src/stop.work a +go test -n -workfile=$GOPATH/src/stop.work a + +-- stop.work -- +go 1.18 + +use ./a +-- a/a.go -- +package a +-- a/a_test.go -- +package a +-- a/go.mod -- +module a + +go 1.18 \ No newline at end of file -- GitLab From 5d8c49a5a13d922c24dc30675d64f0c49b676535 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 23 Nov 2021 12:02:40 -0800 Subject: [PATCH 2309/2500] spec: add definition of "specific types" of an interface The notion of specific types will be used to define rules for assignability, convertability, etc. when type parameters are involved. Change-Id: Ic5c134261e2a9fe05cdf25efd342f052458ab5c8 Reviewed-on: https://go-review.googlesource.com/c/go/+/366754 Trust: Robert Griesemer Reviewed-by: Ian Lance Taylor --- doc/go_spec.html | 64 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index ecd2f084c9..176e1a755d 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,6 +1,6 @@ @@ -1290,8 +1290,8 @@ UnderlyingType = "~" Type .

    An interface type is specified by a list of interface elements. -An interface element is either a method or a type element, -where a type element is a union of one or more type terms. +An interface element is either a method or a type element, +where a type element is a union of one or more type terms. A type term is either a single type or a single underlying type.

    @@ -1926,7 +1926,60 @@ x T x is not representable by a value of T because 1e1000 float64 1e1000 overflows to IEEE +Inf after rounding -

    Structural interfaces

    +

    Structure of interfaces

    + +

    +An interface specification which contains type elements +that are not interface types defines a (possibly empty) set of specific types. +Loosely speaking, these are the types T that appear in the +interface definition in terms of the form T, ~T, +or in unions of such terms. +

    + +

    +More precisely, for a given interface, the set of specific types is defined as follows: +

    + +
      +
    • The set of specific types of the empty interface is the empty set. +
    • + +
    • The set of specific types of a non-empty interface is the intersection + of the specific types of its interface elements. +
    • + +
    • The set of specific types of a method specification is the empty set. +
    • + +
    • The set of specific types of a non-interface type term T + or ~T is the set consisting of the type T. +
    • + +
    • The set of specific types of a union of terms + t1|t2|…|tn + is the union of the specific types of the terms. +
    • +
    + +

    +If the set of specific types is empty, the interface has no specific types. +

    + +

    +Examples of interfaces with their specific types: +

    + +
    +type Celsius float32
    +type Kelvin  float32
    +
    +interface{}                    // no specific types
    +interface{ int }               // int
    +interface{ ~string }           // string
    +interface{ int|~string }       // int, string
    +interface{ Celsius|Kelvin }    // Celsius, Kelvin
    +interface{ int; string }       // no specific types (intersection is empty)
    +

    An interface T is called structural if one of the following @@ -1966,9 +2019,6 @@ Examples of structural interfaces with their structural types:

    -type Celsius float32
    -type Kelvin  float32
    -
     interface{ int }                          // int
     interface{ Celsius|Kelvin }               // float32
     interface{ ~chan int }                    // chan int
    -- 
    GitLab
    
    
    From 003e7faf53a3e7d0e280871447c60922bff89bcf Mon Sep 17 00:00:00 2001
    From: Robert Griesemer 
    Date: Sat, 20 Nov 2021 13:29:02 -0800
    Subject: [PATCH 2310/2500] spec: adjust representability rules for type
     parameters
    
    Change-Id: I4423a059527066c4418c195911f8184dfd3f5a15
    Reviewed-on: https://go-review.googlesource.com/c/go/+/365914
    Trust: Robert Griesemer 
    Reviewed-by: Ian Lance Taylor 
    ---
     doc/go_spec.html | 10 +++++++++-
     1 file changed, 9 insertions(+), 1 deletion(-)
    
    diff --git a/doc/go_spec.html b/doc/go_spec.html
    index 176e1a755d..186600f015 100644
    --- a/doc/go_spec.html
    +++ b/doc/go_spec.html
    @@ -1876,7 +1876,9 @@ by a value of type T.
     
     

    A constant x is representable -by a value of type T if one of the following conditions applies: +by a value of type T, +where T is not a type parameter, +if one of the following conditions applies:

      @@ -1899,6 +1901,12 @@ are representable by values of T's component type (float32
    +

    +If T is a type parameter with specific types, +x is representable by a value of type T if x is representable +by a value of each specific type of T. +

    +
     x                   T           x is representable by a value of T because
     
    -- 
    GitLab
    
    
    From 939480033aa2c09f1b511a1928c0b465f41a45da Mon Sep 17 00:00:00 2001
    From: Robert Griesemer 
    Date: Thu, 18 Nov 2021 16:11:10 -0800
    Subject: [PATCH 2311/2500] spec: adjust assignability rules for type
     parameters
    
    Change-Id: I3c4d8bdb5e92ee7fdca9593fb043f94f467755e8
    Reviewed-on: https://go-review.googlesource.com/c/go/+/365434
    Trust: Robert Griesemer 
    Reviewed-by: Ian Lance Taylor 
    ---
     doc/go_spec.html | 40 ++++++++++++++++++++++++++++++++--------
     1 file changed, 32 insertions(+), 8 deletions(-)
    
    diff --git a/doc/go_spec.html b/doc/go_spec.html
    index 186600f015..904132adf0 100644
    --- a/doc/go_spec.html
    +++ b/doc/go_spec.html
    @@ -1848,21 +1848,22 @@ A value x is assignable to a variable
     
  • x's type V and T have identical -underlying types and at least one of V -or T is not a defined type. +underlying types and at least one of V +or T is not a named type.
  • -T is an interface type and -x implements T. +x's type V and T are channel types with +identical element types, V is a bidirectional channel, +and at least one of V or T is not a named type.
  • -x is a bidirectional channel value, T is a channel type, -x's type V and T have identical element types, -and at least one of V or T is not a defined type. +T is an interface type, but not a type parameter, and +x implements T.
  • x is the predeclared identifier nil and T -is a pointer, function, slice, map, channel, or interface type. +is a pointer, function, slice, map, channel, or interface type, +but not a type parameter.
  • x is an untyped constant @@ -1871,6 +1872,29 @@ by a value of type T.
  • +

    +Additionally, if x's type V or T are type parameters +with specific types, x +is assignable to a variable of type T if one of the following conditions applies: +

    + +
      +
    • +x is the predeclared identifier nil, T is +a type parameter, and x is assignable to each specific type of +T. +
    • +
    • +V is not a named type, T is +a type parameter, and x is assignable to each specific type of +T. +
    • +
    • +V is a type parameter and T is not a named type, +and values of each specific type of V are assignable +to T. +
    • +

    Representability

    -- GitLab From ce2a20af467c8dfa10874abc4b45af413e2b1954 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sat, 20 Nov 2021 13:17:27 -0800 Subject: [PATCH 2312/2500] spec: adjust conversion rules for type parameters Change-Id: I7bfddf4be0d1d95419f312bb349ae2e16b74b795 Reviewed-on: https://go-review.googlesource.com/c/go/+/365915 Trust: Robert Griesemer Reviewed-by: Ian Lance Taylor --- doc/go_spec.html | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index 904132adf0..d8e6bb7b8e 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -4633,7 +4633,9 @@ as for non-constant x.

    -Converting a constant yields a typed constant as result. +Converting a constant to a type that is not a type parameter +yields a typed constant. +Converting a constant to a type parameter yields a non-constant value of that type.

    @@ -4669,7 +4671,7 @@ in any of these cases:
     	
  • ignoring struct tags (see below), x's type and T are pointer types - that are not defined types, + that are not named types, and their pointer base types have identical underlying types.
  • @@ -4692,6 +4694,28 @@ in any of these cases:
  • +

    +Additionally, if T or x's type V are type +parameters with specific types, x +can also be converted to type T if one of the following conditions applies: +

    + +
      +
    • +Both V and T are type parameters and a value of each +specific type of V can be converted to each specific type +of T. +
    • +
    • +Only V is a type parameter and a value of each +specific type of V can be converted to T. +
    • +
    • +Only T is a type parameter and x can can be converted to each +specific type of T. +
    • +
    +

    Struct tags are ignored when comparing struct types for identity for the purpose of conversion: -- GitLab From a3b8f627c258f34325d2284ce636f8d4fb103331 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sat, 20 Nov 2021 14:35:02 -0800 Subject: [PATCH 2313/2500] spec: add section on instantiation Change-Id: I2770da87b4c977b51dfa046f2f08283917675e1c Reviewed-on: https://go-review.googlesource.com/c/go/+/365916 Trust: Robert Griesemer Trust: Dan Scales Reviewed-by: Ian Lance Taylor Reviewed-by: Dan Scales --- doc/go_spec.html | 90 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 2 deletions(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index d8e6bb7b8e..6f30ed7b91 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -2913,13 +2913,19 @@ non-blank identifier denoting a or a parenthesized expression.

    +

    +An operand name denoting a type-parameterized function +may be followed by a list of type arguments; the +resulting operand is an instantiated function. +

    +

    The blank identifier may appear as an operand only on the left-hand side of an assignment.

    -Operand     = Literal | OperandName | "(" Expression ")" .
    +Operand     = Literal | OperandName [ TypeArgs ] | "(" Expression ")" .
     Literal     = BasicLit | CompositeLit | FunctionLit .
     BasicLit    = int_lit | float_lit | imaginary_lit | rune_lit | string_lit .
     OperandName = identifier | QualifiedIdent .
    @@ -2928,7 +2934,7 @@ OperandName = identifier | QualifiedIdent .
     

    Qualified identifiers

    -A qualified identifier is an identifier qualified with a package name prefix. +A qualified identifier is an identifier qualified with a package name prefix. Both the package name and the identifier must not be blank.

    @@ -3962,6 +3968,11 @@ var pt *Point pt.Scale(3.5) // method call with receiver pt
    +

    +If f denotes a parameterized function, it must be +instantiated before it can be called. +

    +

    In a function call, the function value and arguments are evaluated in the usual order. @@ -4073,6 +4084,81 @@ within Greeting, who will have the same value as +

    Instantiations

    + +

    +A parameterized function or type is instantiated by substituting type arguments +for the type parameters. +Instantiation proceeds in two phases: +

    + +
      +
    1. +Each type argument is substituted for its corresponding type parameter in the parameterized +declaration. +This substitution happens across the entire function or type declaration, +including the type parameter list itself and any types in that list. +
    2. + +
    3. +After substitution, each type argument must implement +the constraint (instantiated, if necessary) +of the corresponding type parameter. Otherwise instantiation fails. +
    4. +
    + +

    +Instantiating a type results in a new non-parameterized named type; +instantiating a function produces a new non-parameterized function. +

    + +
    +type parameter list    type arguments    after substitution
    +
    +[P any]                int               [int any]
    +[S ~[]E, E any]        []int, int        [[]int ~[]int, int any]
    +[P io.Writer]          string            [string io.Writer]         // illegal: string doesn't implement io.Writer
    +
    + +

    +Type arguments may be provided explicitly, or they may be partially or completely +inferred. +A partially provided type argument list cannot be empty; there must be at least the +first argument. +

    + +
    +type T[P1 ~int, P2 ~[]P1] struct{ … }
    +
    +T[]            // illegal: at least the first type argument must be present, even if it could be inferred
    +T[int]         // argument for P1 explicitly provided, argument for P2 inferred
    +T[int, []int]  // both arguments explicitly provided
    +
    + +

    +A partial type argument list specifies a prefix of the full list of type arguments, leaving +the remaining arguments to be inferred. Loosely speaking, type arguments may be omitted from +"right to left". +

    + +

    +Parameterized types, and parameterized functions that are not called, +require a type argument list for instantiation; if the list is partial, all +remaining type arguments must be inferrable. +Calls to parameterized functions may provide a (possibly partial) type +argument list, or may omit it entirely if the omitted type arguments are +inferrable from the ordinary (non-type) function arguments. +

    + +
    +func min[T constraints.Ordered](x, y T) T { … }
    +
    +f := min                   // illegal: min must be instantiated when used without being called
    +minInt := min[int]         // minInt has type func(x, y int) int
    +a := minInt(2, 3)          // a has value 2 of type int
    +b := min[float64](2.0, 3)  // b has value 2.0 of type float64
    +c := min(b, -1)            // c has value -1.0 of type float64
    +

    Operators

    -- GitLab From 6ea17aa52c5f66c1fd72b74c36f8036e17ddde34 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 23 Nov 2021 18:11:07 -0800 Subject: [PATCH 2314/2500] spec: adjust type identity rules for type parameters Change-Id: I5ffc7f26236487070447eaa0f6b14d1fab44c3c7 Reviewed-on: https://go-review.googlesource.com/c/go/+/366794 Trust: Robert Griesemer Reviewed-by: Ian Lance Taylor --- doc/go_spec.html | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index 6f30ed7b91..0fc5b4590f 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1750,7 +1750,7 @@ Two types are either identical or different.

    -A defined type is always different from any other type. +A named type is always different from any other type. Otherwise, two types are identical if their underlying type literals are structurally equivalent; that is, they have the same literal structure and corresponding components have identical types. In detail: @@ -1775,15 +1775,17 @@ components have identical types. In detail: identical, and either both functions are variadic or neither is. Parameter and result names are not required to match. -

  • Two interface types are identical if they have the same set of methods - with the same names and identical function types. - Non-exported method names from different - packages are always different. The order of the methods is irrelevant.
  • +
  • Two interface types are identical if they define the same type set. +
  • Two map types are identical if they have identical key and element types.
  • Two channel types are identical if they have identical element types and the same direction.
  • + +
  • Two instantiated types are identical if + their defined types and all type arguments are identical. +
  • @@ -1798,18 +1800,18 @@ type ( A3 = int A4 = func(A3, float64) *A0 A5 = func(x int, _ float64) *[]string -) -type ( B0 A0 B1 []string B2 struct{ a, b int } B3 struct{ a, c int } B4 func(int, float64) *B0 B5 func(x int, y float64) *A1 -) -type C0 = B0 + C0 = B0 + D0[P1, P2 any] struct{ x P1; y P2 } + E0 = D0[int, string] +)

    @@ -1823,6 +1825,7 @@ A3 and int A4, func(int, float64) *[]string, and A5 B0 and C0 +D0[int, string] and E0 []int and []int struct{ a, b *T5 } and struct{ a, b *T5 } func(x int, y float64) *[]string, func(int, float64) (result *[]string), and A5 @@ -1832,7 +1835,13 @@ func(x int, y float64) *[]string, func(int, float64) (result *[]string), and A5 B0 and B1 are different because they are new types created by distinct type definitions; func(int, float64) *B0 and func(x int, y float64) *[]string -are different because B0 is different from []string. +are different because B0 is different from []string; +and P1 and P2 are different because they are different +type parameters. +D0[int, string] and struct{ x int; y string } are +different because the former is an instantiated +defined type while the latter is a type literal +(but they are still assignable).

    Assignability

    -- GitLab From 696515ee396566ba02da145cf71fe5913d65b9a6 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 23 Nov 2021 20:56:33 -0800 Subject: [PATCH 2315/2500] spec: type assertions and switches don't operate on type parameters Change-Id: I11111b3617673be94508128489aed6488d518537 Reviewed-on: https://go-review.googlesource.com/c/go/+/366834 Trust: Robert Griesemer Reviewed-by: Ian Lance Taylor --- doc/go_spec.html | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index 0fc5b4590f..b8e6aceee9 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -3884,8 +3884,9 @@ If the indices are out of range at run time, a run-ti

    Type assertions

    -For an expression x of interface type -and a type T, the primary expression +For an expression x of interface type, +but not a type parameter, and a type T, +the primary expression

    @@ -5677,7 +5678,8 @@ switch x.(type) {
     

    Cases then match actual types T against the dynamic type of the expression x. As with type assertions, x must be of -interface type, and each non-interface type +interface type, but not a +type parameter, and each non-interface type T listed in a case must implement the type of x. The types listed in the cases of a type switch must all be different. -- GitLab From 9e7600d3fccf1920028bc808c755198db73482c0 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 22 Nov 2021 16:04:17 -0800 Subject: [PATCH 2316/2500] go/types: print "nil" rather than "untyped nil" This is a port of CL 366276 from types2 to go/types with minor adjustments due to the slightly different handling of nil in go/types. It uses some more detailed error strings in stmt0.src; the same changes are made to the corresponding types2 file. For #48852. Change-Id: I2cdf258799bcbe2d12bbadaf67b8b4504b356bd0 Reviewed-on: https://go-review.googlesource.com/c/go/+/366277 Trust: Robert Griesemer Reviewed-by: Robert Findley --- .../internal/types2/testdata/check/stmt0.src | 6 +++--- src/go/types/operand.go | 5 +++++ src/go/types/testdata/check/stmt0.src | 6 +++--- src/go/types/testdata/fixedbugs/issue49296.go2 | 2 +- src/go/types/testdata/spec/assignability.go2 | 18 +++++++++--------- 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/cmd/compile/internal/types2/testdata/check/stmt0.src b/src/cmd/compile/internal/types2/testdata/check/stmt0.src index 353444f068..8171c57d8b 100644 --- a/src/cmd/compile/internal/types2/testdata/check/stmt0.src +++ b/src/cmd/compile/internal/types2/testdata/check/stmt0.src @@ -69,10 +69,10 @@ func assignments1() { // test cases for issue 5800 var ( - _ int = nil /* ERROR "nil" */ - _ [10]int = nil /* ERROR "nil" */ + _ int = nil /* ERROR "cannot use nil as int value in variable declaration" */ + _ [10]int = nil /* ERROR "cannot use nil as \[10\]int value in variable declaration" */ _ []byte = nil - _ struct{} = nil /* ERROR "nil" */ + _ struct{} = nil /* ERROR "cannot use nil as struct{} value in variable declaration" */ _ func() = nil _ map[int]string = nil _ chan int = nil diff --git a/src/go/types/operand.go b/src/go/types/operand.go index 8cc5eda866..c35b1650be 100644 --- a/src/go/types/operand.go +++ b/src/go/types/operand.go @@ -105,6 +105,11 @@ func (x *operand) Pos() token.Pos { // cgofunc ( of type ) // func operandString(x *operand, qf Qualifier) string { + // special-case nil + if x.mode == value && x.typ == Typ[UntypedNil] { + return "nil" + } + var buf bytes.Buffer var expr string diff --git a/src/go/types/testdata/check/stmt0.src b/src/go/types/testdata/check/stmt0.src index 15df37703c..2cce0b59b2 100644 --- a/src/go/types/testdata/check/stmt0.src +++ b/src/go/types/testdata/check/stmt0.src @@ -69,10 +69,10 @@ func assignments1() { // test cases for issue 5800 var ( - _ int = nil /* ERROR "untyped nil value" */ - _ [10]int = nil /* ERROR "untyped nil value" */ + _ int = nil /* ERROR "cannot use nil as int value in variable declaration" */ + _ [10]int = nil /* ERROR "cannot use nil as \[10\]int value in variable declaration" */ _ []byte = nil - _ struct{} = nil /* ERROR "untyped nil value" */ + _ struct{} = nil /* ERROR "cannot use nil as struct{} value in variable declaration" */ _ func() = nil _ map[int]string = nil _ chan int = nil diff --git a/src/go/types/testdata/fixedbugs/issue49296.go2 b/src/go/types/testdata/fixedbugs/issue49296.go2 index 8c6d0b678d..0ad71ef4b2 100644 --- a/src/go/types/testdata/fixedbugs/issue49296.go2 +++ b/src/go/types/testdata/fixedbugs/issue49296.go2 @@ -10,7 +10,7 @@ func _[ T2 ~float64 | ~complex128 | chan int, ]() { // TODO(rfindley): the types2 error here is clearer. - _ = T0(nil /* ERROR cannot convert nil \(untyped nil value\) to T0 */ ) + _ = T0(nil /* ERROR cannot convert nil to T0 */ ) _ = T1(1 /* ERROR cannot convert 1 .* to T1 */ ) _ = T2(2 /* ERROR cannot convert 2 .* to T2 */ ) } diff --git a/src/go/types/testdata/spec/assignability.go2 b/src/go/types/testdata/spec/assignability.go2 index a6e71aac81..d5f6ab4419 100644 --- a/src/go/types/testdata/spec/assignability.go2 +++ b/src/go/types/testdata/spec/assignability.go2 @@ -155,28 +155,28 @@ func _[ // TODO(rfindley) error messages about untyped nil diverge from types2 here. // Consider aligning them. func _[TP Interface](X TP) { - b = nil // ERROR cannot use.*untyped nil - a = nil // ERROR cannot use.*untyped nil + b = nil // ERROR cannot use nil + a = nil // ERROR cannot use nil l = nil - s = nil // ERROR cannot use.*untyped nil + s = nil // ERROR cannot use nil p = nil f = nil i = nil m = nil c = nil - d = nil // ERROR cannot use.*untyped nil + d = nil // ERROR cannot use nil - B = nil // ERROR cannot use.*untyped nil - A = nil // ERROR cannot use.*untyped nil + B = nil // ERROR cannot use nil + A = nil // ERROR cannot use nil L = nil - S = nil // ERROR cannot use.*untyped nil + S = nil // ERROR cannot use nil P = nil F = nil I = nil M = nil C = nil - D = nil // ERROR cannot use.*untyped nil - X = nil // ERROR cannot use.*untyped nil + D = nil // ERROR cannot use nil + X = nil // ERROR cannot use nil } // "x is an untyped constant representable by a value of type T" -- GitLab From c25bf0d959c299e5fa5392ae6f835570ed6d111f Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 17 Nov 2021 15:23:12 -0800 Subject: [PATCH 2317/2500] cmd/compile/internal/types2: report types for mismatched call and return statements Thanks to emmanuel@orijtech.com who wrote the initial version of this change (CL 354490). This change is following CL 354490 in idea but also contains various simplifications, slightly improved printing of signature/type patterns, adjustments for types2, and some fine-tuning of error positions. Also adjusted several ERROR regexp patterns. Fixes #48834. Fixes #48835. Change-Id: I31cf20c81753b1dc84836dbe83a39030ceb9db23 Reviewed-on: https://go-review.googlesource.com/c/go/+/364874 Trust: Robert Griesemer Reviewed-by: Robert Findley Reviewed-by: Emmanuel Odeke --- .../compile/internal/types2/assignments.go | 81 +++++++++++++++++-- src/cmd/compile/internal/types2/call.go | 25 ++++-- src/cmd/compile/internal/types2/decl.go | 2 +- src/cmd/compile/internal/types2/stmt.go | 2 +- .../types2/testdata/check/builtins.src | 2 +- .../internal/types2/testdata/check/errors.src | 28 ++++--- .../internal/types2/testdata/check/expr3.src | 14 ++-- .../internal/types2/testdata/check/stmt0.src | 16 ++-- .../types2/testdata/check/typeparams.go2 | 2 +- .../types2/testdata/check/vardecl.src | 2 +- test/fixedbugs/bug326.go | 2 +- test/fixedbugs/issue4215.go | 20 ++--- test/fixedbugs/issue46957.go | 2 +- test/fixedbugs/issue48834.go | 24 ++++++ test/fixedbugs/issue48835.go | 25 ++++++ 15 files changed, 190 insertions(+), 57 deletions(-) create mode 100644 test/fixedbugs/issue48834.go create mode 100644 test/fixedbugs/issue48835.go diff --git a/src/cmd/compile/internal/types2/assignments.go b/src/cmd/compile/internal/types2/assignments.go index ac4f7b88a4..0a85d8eb39 100644 --- a/src/cmd/compile/internal/types2/assignments.go +++ b/src/cmd/compile/internal/types2/assignments.go @@ -9,6 +9,7 @@ package types2 import ( "cmd/compile/internal/syntax" "fmt" + "strings" ) // assignment reports whether x can be assigned to a variable of type T, @@ -241,6 +242,58 @@ func (check *Checker) assignVar(lhs syntax.Expr, x *operand) Type { return x.typ } +// operandTypes returns the list of types for the given operands. +func operandTypes(list []*operand) (res []Type) { + for _, x := range list { + res = append(res, x.typ) + } + return res +} + +// varTypes returns the list of types for the given variables. +func varTypes(list []*Var) (res []Type) { + for _, x := range list { + res = append(res, x.typ) + } + return res +} + +// typesSummary returns a string of the form "(t1, t2, ...)" where the +// ti's are user-friendly string representations for the given types. +// If variadic is set and the last type is a slice, its string is of +// the form "...E" where E is the slice's element type. +func (check *Checker) typesSummary(list []Type, variadic bool) string { + var res []string + for i, t := range list { + var s string + switch { + case t == nil: + fallthrough // should not happend but be cautious + case t == Typ[Invalid]: + s = "" + case isUntyped(t): + if isNumeric(t) { + // Do not imply a specific type requirement: + // "have number, want float64" is better than + // "have untyped int, want float64" or + // "have int, want float64". + s = "number" + } else { + // If we don't have a number, omit the "untyped" qualifier + // for compactness. + s = strings.Replace(t.(*Basic).name, "untyped ", "", -1) + } + case variadic && i == len(list)-1: + s = check.sprintf("...%s", t.(*Slice).elem) + } + if s == "" { + s = check.sprintf("%s", t) + } + res = append(res, s) + } + return "(" + strings.Join(res, ", ") + ")" +} + func (check *Checker) assignError(rhs []syntax.Expr, nvars, nvals int) { measure := func(x int, unit string) string { s := fmt.Sprintf("%d %s", x, unit) @@ -263,10 +316,10 @@ func (check *Checker) assignError(rhs []syntax.Expr, nvars, nvals int) { check.errorf(rhs0, "assignment mismatch: %s but %s", vars, vals) } -// If returnPos is valid, initVars is called to type-check the assignment of -// return expressions, and returnPos is the position of the return statement. -func (check *Checker) initVars(lhs []*Var, orig_rhs []syntax.Expr, returnPos syntax.Pos) { - rhs, commaOk := check.exprList(orig_rhs, len(lhs) == 2 && !returnPos.IsKnown()) +// If returnStmt != nil, initVars is called to type-check the assignment +// of return expressions, and returnStmt is the the return statement. +func (check *Checker) initVars(lhs []*Var, orig_rhs []syntax.Expr, returnStmt syntax.Stmt) { + rhs, commaOk := check.exprList(orig_rhs, len(lhs) == 2 && returnStmt == nil) if len(lhs) != len(rhs) { // invalidate lhs @@ -282,8 +335,20 @@ func (check *Checker) initVars(lhs []*Var, orig_rhs []syntax.Expr, returnPos syn return } } - if returnPos.IsKnown() { - check.errorf(returnPos, "wrong number of return values (want %d, got %d)", len(lhs), len(rhs)) + if returnStmt != nil { + var at poser = returnStmt + qualifier := "not enough" + if len(rhs) > len(lhs) { + at = rhs[len(lhs)].expr // report at first extra value + qualifier = "too many" + } else if len(rhs) > 0 { + at = rhs[len(rhs)-1].expr // report at last value + } + var err error_ + err.errorf(at, "%s return values", qualifier) + err.errorf(nopos, "have %s", check.typesSummary(operandTypes(rhs), false)) + err.errorf(nopos, "want %s", check.typesSummary(varTypes(lhs), false)) + check.report(&err) return } if check.conf.CompilerErrorMessages { @@ -295,7 +360,7 @@ func (check *Checker) initVars(lhs []*Var, orig_rhs []syntax.Expr, returnPos syn } context := "assignment" - if returnPos.IsKnown() { + if returnStmt != nil { context = "return statement" } @@ -449,7 +514,7 @@ func (check *Checker) shortVarDecl(pos syntax.Pos, lhs, rhs []syntax.Expr) { } } - check.initVars(lhsVars, rhs, nopos) + check.initVars(lhsVars, rhs, nil) // process function literals in rhs expressions before scope changes check.processDelayed(top) diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 4e2c2a2989..91e2a8f783 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -350,12 +350,25 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T } // check argument count - switch { - case nargs < npars: - check.errorf(call, "not enough arguments in call to %s", call.Fun) - return - case nargs > npars: - check.errorf(args[npars], "too many arguments in call to %s", call.Fun) // report at first extra argument + if nargs != npars { + var at poser = call + qualifier := "not enough" + if nargs > npars { + at = args[npars].expr // report at first extra argument + qualifier = "too many" + } else if nargs > 0 { + at = args[nargs-1].expr // report at last argument + } + // take care of empty parameter lists represented by nil tuples + var params []*Var + if sig.params != nil { + params = sig.params.vars + } + var err error_ + err.errorf(at, "%s arguments in call to %s", qualifier, call.Fun) + err.errorf(nopos, "have %s", check.typesSummary(operandTypes(args), false)) + err.errorf(nopos, "want %s", check.typesSummary(varTypes(params), sig.variadic)) + check.report(&err) return } diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 4b79c59af3..a4bc3969c0 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -549,7 +549,7 @@ func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init syntax.Expr) { } } - check.initVars(lhs, []syntax.Expr{init}, nopos) + check.initVars(lhs, []syntax.Expr{init}, nil) } // isImportedConstraint reports whether typ is an imported type constraint. diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index 44d9256c50..ab64882c02 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -493,7 +493,7 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) { } } else { // return has results or result parameters are unnamed - check.initVars(res.vars, results, s.Pos()) + check.initVars(res.vars, results, s) } } else if len(results) > 0 { check.error(results[0], "no result values expected") diff --git a/src/cmd/compile/internal/types2/testdata/check/builtins.src b/src/cmd/compile/internal/types2/testdata/check/builtins.src index 17e4068d65..de27f5c632 100644 --- a/src/cmd/compile/internal/types2/testdata/check/builtins.src +++ b/src/cmd/compile/internal/types2/testdata/check/builtins.src @@ -25,7 +25,7 @@ func append1() { _ = append(s, b) _ = append(s, x /* ERROR cannot use x */ ) _ = append(s, s /* ERROR cannot use s */ ) - _ = append(s... ) /* ERROR not enough arguments */ + _ = append(s /* ERROR not enough arguments */ ...) _ = append(s, b, s /* ERROR too many arguments */ ... ) _ = append(s, 1, 2, 3) _ = append(s, 1, 2, 3, x /* ERROR cannot use x */ , 5, 6, 6) diff --git a/src/cmd/compile/internal/types2/testdata/check/errors.src b/src/cmd/compile/internal/types2/testdata/check/errors.src index ff929217c4..5f09197bde 100644 --- a/src/cmd/compile/internal/types2/testdata/check/errors.src +++ b/src/cmd/compile/internal/types2/testdata/check/errors.src @@ -8,32 +8,38 @@ package errors // (matching messages are regular expressions, hence the \'s). func f(x int, m map[string]int) { // no values - _ = f /* ERROR "f\(0, m\) \(no value\) used as value" */ (0, m) + _ = f /* ERROR f\(0, m\) \(no value\) used as value */ (0, m) // built-ins - _ = println /* ERROR "println \(built-in\) must be called" */ + _ = println // ERROR println \(built-in\) must be called // types - _ = complex128 /* ERROR "complex128 \(type\) is not an expression" */ + _ = complex128 // ERROR complex128 \(type\) is not an expression // constants const c1 = 991 const c2 float32 = 0.5 - 0 /* ERROR "0 \(untyped int constant\) is not used" */ - c1 /* ERROR "c1 \(untyped int constant 991\) is not used" */ - c2 /* ERROR "c2 \(constant 0.5 of type float32\) is not used" */ - c1 /* ERROR "c1 \+ c2 \(constant 991.5 of type float32\) is not used" */ + c2 + const c3 = "foo" + 0 // ERROR 0 \(untyped int constant\) is not used + 0.5 // ERROR 0.5 \(untyped float constant\) is not used + "foo" // ERROR "foo" \(untyped string constant\) is not used + c1 // ERROR c1 \(untyped int constant 991\) is not used + c2 // ERROR c2 \(constant 0.5 of type float32\) is not used + c1 /* ERROR c1 \+ c2 \(constant 991.5 of type float32\) is not used */ + c2 + c3 // ERROR c3 \(untyped string constant "foo"\) is not used // variables - x /* ERROR "x \(variable of type int\) is not used" */ + x // ERROR x \(variable of type int\) is not used // values - x /* ERROR "x != x \(untyped bool value\) is not used" */ != x - x /* ERROR "x \+ x \(value of type int\) is not used" */ + x + nil // ERROR nil is not used + (*int)(nil) // ERROR \(\*int\)\(nil\) \(value of type \*int\) is not used + x /* ERROR x != x \(untyped bool value\) is not used */ != x + x /* ERROR x \+ x \(value of type int\) is not used */ + x // value, ok's const s = "foo" - m /* ERROR "m\[s\] \(map index expression of type int\) is not used" */ [s] + m /* ERROR m\[s\] \(map index expression of type int\) is not used */ [s] } // Valid ERROR comments can have a variety of forms. diff --git a/src/cmd/compile/internal/types2/testdata/check/expr3.src b/src/cmd/compile/internal/types2/testdata/check/expr3.src index 0d7bbae9f9..646319e4c4 100644 --- a/src/cmd/compile/internal/types2/testdata/check/expr3.src +++ b/src/cmd/compile/internal/types2/testdata/check/expr3.src @@ -494,23 +494,23 @@ func _calls() { f1(0) f1(x) f1(10.0) - f1() /* ERROR "not enough arguments" */ - f1(x, y /* ERROR "too many arguments" */ ) + f1 /* ERROR "not enough arguments in call to f1\n\thave \(\)\n\twant \(int\)" */ () + f1(x, y /* ERROR "too many arguments in call to f1\n\thave \(int, float32\)\n\twant \(int\)" */ ) f1(s /* ERROR "cannot use .* in argument" */ ) f1(x ... /* ERROR "cannot use ..." */ ) f1(g0 /* ERROR "used as value" */ ()) f1(g1()) - f1(g2 /* ERROR "too many arguments" */ ()) + f1(g2 /* ERROR "too many arguments in call to f1\n\thave \(float32, string\)\n\twant \(int\)" */ ()) - f2() /* ERROR "not enough arguments" */ - f2(3.14) /* ERROR "not enough arguments" */ + f2 /* ERROR "not enough arguments in call to f2\n\thave \(\)\n\twant \(float32, string\)" */ () + f2(3.14 /* ERROR "not enough arguments in call to f2\n\thave \(number\)\n\twant \(float32, string\)" */ ) f2(3.14, "foo") f2(x /* ERROR "cannot use .* in argument" */ , "foo") f2(g0 /* ERROR "used as value" */ ()) - f2(g1()) /* ERROR "not enough arguments" */ + f2(g1 /* ERROR "not enough arguments in call to f2\n\thave \(int\)\n\twant \(float32, string\)" */ ()) f2(g2()) - fs() /* ERROR "not enough arguments" */ + fs /* ERROR "not enough arguments" */ () fs(g0 /* ERROR "used as value" */ ()) fs(g1 /* ERROR "cannot use .* in argument" */ ()) fs(g2 /* ERROR "too many arguments" */ ()) diff --git a/src/cmd/compile/internal/types2/testdata/check/stmt0.src b/src/cmd/compile/internal/types2/testdata/check/stmt0.src index 8171c57d8b..8b18d676ac 100644 --- a/src/cmd/compile/internal/types2/testdata/check/stmt0.src +++ b/src/cmd/compile/internal/types2/testdata/check/stmt0.src @@ -29,10 +29,10 @@ func assignments0() (int, int) { a, b, c = <- /* ERROR "cannot assign [1-9]+ values to [1-9]+ variables" */ ch - return /* ERROR "wrong number of return values" */ - return /* ERROR "wrong number of return values" */ 1 + return /* ERROR "not enough return values\n\thave \(\)\n\twant \(int, int\)" */ + return 1 /* ERROR "not enough return values\n\thave \(number\)\n\twant \(int, int\)" */ return 1, 2 - return /* ERROR "wrong number of return values" */ 1, 2, 3 + return 1, 2, 3 /* ERROR "too many return values\n\thave \(number, number, number\)\n\twant \(int, int\)" */ } func assignments1() { @@ -81,12 +81,12 @@ func assignments1() { // test cases for issue 5500 _ = func() (int, bool) { var m map[int]int - return /* ERROR "wrong number of return values" */ m[0] + return m /* ERROR "not enough return values" */ [0] } g := func(int, bool){} var m map[int]int - g(m[0]) /* ERROR "not enough arguments" */ + g(m /* ERROR "not enough arguments" */ [0]) // assignments to _ _ = nil /* ERROR "use of untyped nil" */ @@ -380,15 +380,15 @@ func returns0() { func returns1(x float64) (int, *float64) { return 0, &x - return /* ERROR wrong number of return values */ + return /* ERROR not enough return values */ return "foo" /* ERROR "cannot .* in return statement" */, x /* ERROR "cannot use .* in return statement" */ - return /* ERROR wrong number of return values */ 0, &x, 1 + return 0, &x, 1 /* ERROR too many return values */ } func returns2() (a, b int) { return return 1, "foo" /* ERROR cannot use .* in return statement */ - return /* ERROR wrong number of return values */ 1, 2, 3 + return 1, 2, 3 /* ERROR too many return values */ { type a int return 1, 2 diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 index d72cf078a7..007157ea0f 100644 --- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 +++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 @@ -312,7 +312,7 @@ var _ = f7(1.2, 3 /* ERROR does not match */ ) func f8[A, B any](A, B, ...B) int { panic(0) } -var _ = f8(1) /* ERROR not enough arguments */ +var _ = f8(1 /* ERROR not enough arguments */ ) var _ = f8(1, 2.3) var _ = f8(1, 2.3, 3.4, 4.5) var _ = f8(1, 2.3, 3.4, 4 /* ERROR does not match */ ) diff --git a/src/cmd/compile/internal/types2/testdata/check/vardecl.src b/src/cmd/compile/internal/types2/testdata/check/vardecl.src index 9e48cdf847..827b9b9d69 100644 --- a/src/cmd/compile/internal/types2/testdata/check/vardecl.src +++ b/src/cmd/compile/internal/types2/testdata/check/vardecl.src @@ -183,7 +183,7 @@ func _() { func _() int { var x, y int - return /* ERROR wrong number of return values */ x, y + return x, y /* ERROR too many return values */ } // Short variable declarations must declare at least one new non-blank variable. diff --git a/test/fixedbugs/bug326.go b/test/fixedbugs/bug326.go index dfd8be8005..74e06f39d7 100644 --- a/test/fixedbugs/bug326.go +++ b/test/fixedbugs/bug326.go @@ -19,7 +19,7 @@ func h() (_ int, _ error) { } func i() (int, error) { - return // ERROR "not enough arguments to return|wrong number of return values" + return // ERROR "not enough return values|not enough arguments to return" } func f1() (_ int, err error) { diff --git a/test/fixedbugs/issue4215.go b/test/fixedbugs/issue4215.go index 7201591f3f..b6ece4bf21 100644 --- a/test/fixedbugs/issue4215.go +++ b/test/fixedbugs/issue4215.go @@ -7,7 +7,7 @@ package main func foo() (int, int) { - return 2.3 // ERROR "not enough arguments to return\n\thave \(number\)\n\twant \(int, int\)|not enough arguments to return|wrong number of return values" + return 2.3 // ERROR "not enough return values\n\thave \(number\)\n\twant \(int, int\)|not enough arguments to return" } func foo2() { @@ -16,19 +16,19 @@ func foo2() { func foo3(v int) (a, b, c, d int) { if v >= 0 { - return 1 // ERROR "not enough arguments to return\n\thave \(number\)\n\twant \(int, int, int, int\)|not enough arguments to return|wrong number of return values" + return 1 // ERROR "not enough return values\n\thave \(number\)\n\twant \(int, int, int, int\)|not enough arguments to return" } - return 2, 3 // ERROR "not enough arguments to return\n\thave \(number, number\)\n\twant \(int, int, int, int\)|not enough arguments to return|wrong number of return values" + return 2, 3 // ERROR "not enough return values\n\thave \(number, number\)\n\twant \(int, int, int, int\)|not enough arguments to return" } func foo4(name string) (string, int) { switch name { case "cow": - return "moo" // ERROR "not enough arguments to return\n\thave \(string\)\n\twant \(string, int\)|not enough arguments to return|wrong number of return values" + return "moo" // ERROR "not enough return values\n\thave \(string\)\n\twant \(string, int\)|not enough arguments to return" case "dog": - return "dog", 10, true // ERROR "too many arguments to return\n\thave \(string, number, bool\)\n\twant \(string, int\)|too many values in return statement|wrong number of return values" + return "dog", 10, true // ERROR "too many return values\n\thave \(string, number, bool\)\n\twant \(string, int\)|too many arguments to return" case "fish": - return "" // ERROR "not enough arguments to return\n\thave \(string\)\n\twant \(string, int\)|not enough arguments to return|wrong number of return values" + return "" // ERROR "not enough return values\n\thave \(string\)\n\twant \(string, int\)|not enough arguments to return" default: return "lizard", 10 } @@ -40,14 +40,14 @@ type U float64 func foo5() (S, T, U) { if false { - return "" // ERROR "not enough arguments to return\n\thave \(string\)\n\twant \(S, T, U\)|not enough arguments to return|wrong number of return values" + return "" // ERROR "not enough return values\n\thave \(string\)\n\twant \(S, T, U\)|not enough arguments to return" } else { ptr := new(T) - return ptr // ERROR "not enough arguments to return\n\thave \(\*T\)\n\twant \(S, T, U\)|not enough arguments to return|wrong number of return values" + return ptr // ERROR "not enough return values\n\thave \(\*T\)\n\twant \(S, T, U\)|not enough arguments to return" } - return new(S), 12.34, 1 + 0i, 'r', true // ERROR "too many arguments to return\n\thave \(\*S, number, number, number, bool\)\n\twant \(S, T, U\)|too many values in return statement|wrong number of return values" + return new(S), 12.34, 1 + 0i, 'r', true // ERROR "too many return values\n\thave \(\*S, number, number, number, bool\)\n\twant \(S, T, U\)|too many arguments to return" } func foo6() (T, string) { - return "T", true, true // ERROR "too many arguments to return\n\thave \(string, bool, bool\)\n\twant \(T, string\)|too many values in return statement|wrong number of return values" + return "T", true, true // ERROR "too many return values\n\thave \(string, bool, bool\)\n\twant \(T, string\)|too many arguments to return" } diff --git a/test/fixedbugs/issue46957.go b/test/fixedbugs/issue46957.go index f3ed3c3def..6c1c0fe0c2 100644 --- a/test/fixedbugs/issue46957.go +++ b/test/fixedbugs/issue46957.go @@ -9,5 +9,5 @@ package main func f(a int, b ...int) {} func main() { - f(nil...) // ERROR "not enough arguments in call to f$" + f(nil...) // ERROR "not enough arguments in call to f\n\thave \(nil\)\n\twant \(int, \[\]int\)|not enough arguments" } diff --git a/test/fixedbugs/issue48834.go b/test/fixedbugs/issue48834.go new file mode 100644 index 0000000000..cf97d132c3 --- /dev/null +++ b/test/fixedbugs/issue48834.go @@ -0,0 +1,24 @@ +// errorcheck + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func _() (int, error) { + return 1 // ERROR "not enough (arguments to return|return values)\n\thave \(number\)\n\twant \(int, error\)" +} + +func _() (int, error) { + var x int + return x // ERROR "not enough (arguments to return|return values)\n\thave \(int\)\n\twant \(int, error\)" +} + +func _() int { + return 1, 2 // ERROR "too many (arguments to return|return values)\n\thave \(number, number\)\n\twant \(int\)" +} + +func _() { + return 1 // ERROR "too many arguments to return\n\thave \(number\)\n\twant \(\)|no result values expected" +} diff --git a/test/fixedbugs/issue48835.go b/test/fixedbugs/issue48835.go new file mode 100644 index 0000000000..c000f8357d --- /dev/null +++ b/test/fixedbugs/issue48835.go @@ -0,0 +1,25 @@ +// errorcheck + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func f0() +func f1(_ int) +func f2(_, _ int) +func f2ddd(_, _ int, _ ...int) + +func f() { + var x int + f0(1) // ERROR "too many arguments in call to f0\n\thave \(number\)\n\twant \(\)" + f0(x) // ERROR "too many arguments in call to f0\n\thave \(int\)\n\twant \(\)" + f1() // ERROR "not enough arguments in call to f1\n\thave \(\)\n\twant \(int\)" + f1(1, 2) // ERROR "too many arguments in call to f1\n\thave \(number, number\)\n\twant \(int\)" + f2(1) // ERROR "not enough arguments in call to f2\n\thave \(number\)\n\twant \(int, int\)" + f2(1, "foo", true) // ERROR "too many arguments in call to f2\n\thave \(number, string, bool\)\n\twant \(int, int\)" + f2ddd(1) // ERROR "not enough arguments in call to f2ddd\n\thave \(number\)\n\twant \(int, int, \.\.\.int\)" + f2ddd(1, 2) + f2ddd(1, 2, 3) +} -- GitLab From 67dd9ee92c454ded14f117e2d958db9ee56e8b02 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 22 Nov 2021 19:02:56 -0800 Subject: [PATCH 2318/2500] cmd/compile/internal/types2: produce empty type set for invalid ~T If ~T is not permitted because the underlying type of T is not the same as T, there is no type that satisfies ~T. Besides reporting an error, also ensure that the corresponding type set is empty. For #49739. Change-Id: I127f75f170902e7989f7fe7b352dabda9f72e2a5 Reviewed-on: https://go-review.googlesource.com/c/go/+/366278 Trust: Robert Griesemer Reviewed-by: Robert Findley --- .../types2/testdata/fixedbugs/issue49739.go2 | 23 +++++++++++++++++++ src/cmd/compile/internal/types2/typeset.go | 16 ++++++++----- 2 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue49739.go2 diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49739.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49739.go2 new file mode 100644 index 0000000000..46b1e71a3b --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49739.go2 @@ -0,0 +1,23 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Verify that we get an empty type set (not just an error) +// when using an invalid ~A. + +package p + +type A int +type C interface { + ~ /* ERROR invalid use of ~ */ A +} + +func f[_ C]() {} +func g[_ interface{ C }]() {} +func h[_ C | int]() {} + +func _() { + _ = f[int /* ERROR cannot implement C \(empty type set\) */] + _ = g[int /* ERROR cannot implement interface{C} \(empty type set\) */] + _ = h[int] +} diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index 54a8266838..a55e9d1d63 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -367,14 +367,18 @@ func computeUnionTypeSet(check *Checker, pos syntax.Pos, utyp *Union) *_TypeSet var allTerms termlist for _, t := range utyp.terms { var terms termlist - switch u := under(t.typ).(type) { - case *Interface: + u := under(t.typ) + if ui, _ := u.(*Interface); ui != nil { // For now we don't permit type parameters as constraints. assert(!isTypeParam(t.typ)) - terms = computeInterfaceTypeSet(check, pos, u).terms - default: - if t.typ == Typ[Invalid] { - continue + terms = computeInterfaceTypeSet(check, pos, ui).terms + } else if t.typ == Typ[Invalid] { + continue + } else { + if t.tilde && !Identical(t.typ, u) { + // There is no underlying type which is t.typ. + // The corresponding type set is empty. + t = nil // ∅ term } terms = termlist{(*term)(t)} } -- GitLab From 5527d7ff7935d8a58a693be5d1ec4a5312f0f07d Mon Sep 17 00:00:00 2001 From: jiahua wang Date: Tue, 16 Nov 2021 15:36:37 +0800 Subject: [PATCH 2319/2500] doc/go1.18: add Clone doc For #47694 Change-Id: I3b135f6ff199d7a9746726b131fbe7dd97a8e95e Reviewed-on: https://go-review.googlesource.com/c/go/+/364254 Reviewed-by: Dmitri Shuralyov Trust: Heschi Kreinick --- doc/go1.18.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index c6c338984c..6d813dce2e 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -439,7 +439,9 @@ proposal.

    strings

    - TODO: https://golang.org/cl/345849: add Clone function + The new Clone function copies the input + string without the returned cloned string referencing + the input string's memory.

    -- GitLab From 7e5331ac445045a70256eeeef5b7aad43886c9ec Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 24 Nov 2021 15:37:21 +0100 Subject: [PATCH 2320/2500] runtime: skip TestTimePprof on illumos On illumos nanotime calls libc, like on the other systems for which TestTimePprof is skipped. For #43118 Change-Id: I370d3f098a261185920cb1e3e3402d16200e301a Reviewed-on: https://go-review.googlesource.com/c/go/+/366737 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/runtime/crash_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/crash_test.go b/src/runtime/crash_test.go index 1c28e47ac3..ec4db99d78 100644 --- a/src/runtime/crash_test.go +++ b/src/runtime/crash_test.go @@ -717,7 +717,7 @@ func TestTimePprof(t *testing.T) { // This test is unreliable on any system in which nanotime // calls into libc. switch runtime.GOOS { - case "aix", "darwin", "openbsd", "solaris": + case "aix", "darwin", "illumos", "openbsd", "solaris": t.Skipf("skipping on %s because nanotime calls libc", runtime.GOOS) } -- GitLab From 8cdfe408bbd608c5129036e40f346d526049ffc4 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 23 Nov 2021 13:54:02 -0800 Subject: [PATCH 2321/2500] cmd/compile/internal/types2: better error position for instantiation failure - Thread type argument expressions (rather than posLists) through various type-checker functions so we can provide a better error position. - Adjust signatures that expect a syntax.Pos to accept a poser instead to avoid gratuituous conversions from expressions to positions. - Rename targsx to xlist so we use xlist consistently for expression lists. First step in providing a better error message for the issue below. For #49179. Change-Id: I8fc685a2ee4f5640f4abd35568ba32bcb34e9e84 Reviewed-on: https://go-review.googlesource.com/c/go/+/366757 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/builtins.go | 2 +- src/cmd/compile/internal/types2/call.go | 32 ++++++++----------- src/cmd/compile/internal/types2/mono.go | 6 ++-- .../types2/testdata/fixedbugs/issue39754.go2 | 4 +-- .../types2/testdata/fixedbugs/issue49179.go2 | 19 +++++++++++ src/cmd/compile/internal/types2/typexpr.go | 20 ++++-------- 6 files changed, 44 insertions(+), 39 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue49179.go2 diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 53d834507a..fcf02a6975 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -129,7 +129,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( arg(&x, i) xlist = append(xlist, &x) } - check.arguments(call, sig, nil, xlist) // discard result (we know the result type) + check.arguments(call, sig, nil, xlist, nil) // discard result (we know the result type) // ok to continue even if check.arguments reported errors x.mode = value diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 91e2a8f783..ed8b67c607 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -50,14 +50,8 @@ func (check *Checker) funcInst(x *operand, inst *syntax.IndexExpr) { } assert(got == want) - // determine argument positions (for error reporting) - poslist := make([]syntax.Pos, len(xlist)) - for i, x := range xlist { - poslist[i] = syntax.StartPos(x) - } - // instantiate function signature - res := check.instantiateSignature(x.Pos(), sig, targs, poslist) + res := check.instantiateSignature(x.Pos(), sig, targs, xlist) assert(res.TypeParams().Len() == 0) // signature is not generic anymore check.recordInstance(inst.X, targs, res) x.typ = res @@ -65,7 +59,7 @@ func (check *Checker) funcInst(x *operand, inst *syntax.IndexExpr) { x.expr = inst } -func (check *Checker) instantiateSignature(pos syntax.Pos, typ *Signature, targs []Type, posList []syntax.Pos) (res *Signature) { +func (check *Checker) instantiateSignature(pos syntax.Pos, typ *Signature, targs []Type, xlist []syntax.Expr) (res *Signature) { assert(check != nil) assert(len(targs) == typ.TypeParams().Len()) @@ -79,17 +73,17 @@ func (check *Checker) instantiateSignature(pos syntax.Pos, typ *Signature, targs } inst := check.instance(pos, typ, targs, check.bestContext(nil)).(*Signature) - assert(len(posList) <= len(targs)) + assert(len(xlist) <= len(targs)) tparams := typ.TypeParams().list() if i, err := check.verify(pos, tparams, targs); err != nil { // best position for error reporting pos := pos - if i < len(posList) { - pos = posList[i] + if i < len(xlist) { + pos = syntax.StartPos(xlist[i]) } - check.softErrorf(pos, err.Error()) + check.softErrorf(pos, "%s", err) } else { - check.mono.recordInstance(check.pkg, pos, tparams, targs, posList) + check.mono.recordInstance(check.pkg, pos, tparams, targs, xlist) } return inst @@ -179,9 +173,10 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { } // evaluate type arguments, if any + var xlist []syntax.Expr var targs []Type if inst != nil { - xlist := unpackExpr(inst.Index) + xlist = unpackExpr(inst.Index) targs = check.typeList(xlist) if targs == nil { check.use(call.ArgList...) @@ -205,7 +200,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { // evaluate arguments args, _ := check.exprList(call.ArgList, false) isGeneric := sig.TypeParams().Len() > 0 - sig = check.arguments(call, sig, targs, args) + sig = check.arguments(call, sig, targs, args, xlist) if isGeneric && sig.TypeParams().Len() == 0 { // update the recorded type of call.Fun to its instantiated type @@ -279,7 +274,8 @@ func (check *Checker) exprList(elist []syntax.Expr, allowCommaOk bool) (xlist [] return } -func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []Type, args []*operand) (rsig *Signature) { +// xlist is the list of type argument expressions supplied in the source code. +func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []Type, args []*operand, xlist []syntax.Expr) (rsig *Signature) { rsig = sig // TODO(gri) try to eliminate this extra verification loop @@ -381,15 +377,13 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T check.versionErrorf(call.Pos(), "go1.18", "implicit function instantiation") } } - // TODO(gri) provide position information for targs so we can feed - // it to the instantiate call for better error reporting targs := check.infer(call.Pos(), sig.TypeParams().list(), targs, sigParams, args) if targs == nil { return // error already reported } // compute result signature - rsig = check.instantiateSignature(call.Pos(), sig, targs, nil) + rsig = check.instantiateSignature(call.Pos(), sig, targs, xlist) assert(rsig.TypeParams().Len() == 0) // signature is not generic anymore check.recordInstance(call.Fun, targs, rsig) diff --git a/src/cmd/compile/internal/types2/mono.go b/src/cmd/compile/internal/types2/mono.go index 39c4d4fbef..7bd79f4282 100644 --- a/src/cmd/compile/internal/types2/mono.go +++ b/src/cmd/compile/internal/types2/mono.go @@ -168,11 +168,11 @@ func (w *monoGraph) recordCanon(mpar, tpar *TypeParam) { // recordInstance records that the given type parameters were // instantiated with the corresponding type arguments. -func (w *monoGraph) recordInstance(pkg *Package, pos syntax.Pos, tparams []*TypeParam, targs []Type, posList []syntax.Pos) { +func (w *monoGraph) recordInstance(pkg *Package, pos syntax.Pos, tparams []*TypeParam, targs []Type, xlist []syntax.Expr) { for i, tpar := range tparams { pos := pos - if i < len(posList) { - pos = posList[i] + if i < len(xlist) { + pos = syntax.StartPos(xlist[i]) } w.assign(pkg, pos, tpar, targs[i]) } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39754.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39754.go2 index a88f4cf2f1..9edd239d7d 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39754.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue39754.go2 @@ -17,7 +17,5 @@ func f[V interface{}, A, B Box[V]]() {} func _() { f[int, Optional[int], Optional[int]]() _ = f[int, Optional[int], Optional /* ERROR does not implement Box */ [string]] - // TODO(gri) Provide better position information here. - // See TODO in call.go, Checker.arguments. - f[int, Optional[int], Optional[string]]( /* ERROR does not implement Box */ ) + _ = f[int, Optional[int], Optional /* ERROR Optional.* does not implement Box.* */ [string]] } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49179.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49179.go2 new file mode 100644 index 0000000000..7cba52aa25 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49179.go2 @@ -0,0 +1,19 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type SliceConstraint[T any] interface { + []T +} + +func Map[S SliceConstraint[E], E any](s S, f func(E) E) S { + return s +} + +type MySlice []int + +func f(s MySlice) { + Map[MySlice /* ERROR MySlice does not implement SliceConstraint\[int\] */, int](s, nil) +} diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 862a31544a..56a7dcd203 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -402,9 +402,9 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) { return typ } -func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def *Named) (res Type) { +func (check *Checker) instantiatedType(x syntax.Expr, xlist []syntax.Expr, def *Named) (res Type) { if check.conf.Trace { - check.trace(x.Pos(), "-- instantiating %s with %s", x, targsx) + check.trace(x.Pos(), "-- instantiating %s with %s", x, xlist) check.indent++ defer func() { check.indent-- @@ -424,18 +424,12 @@ func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def } // evaluate arguments - targs := check.typeList(targsx) + targs := check.typeList(xlist) if targs == nil { def.setUnderlying(Typ[Invalid]) // avoid later errors due to lazy instantiation return Typ[Invalid] } - // determine argument positions - posList := make([]syntax.Pos, len(targs)) - for i, arg := range targsx { - posList[i] = arg.Pos() - } - // create the instance ctxt := check.bestContext(nil) h := ctxt.instanceHash(orig, targs) @@ -484,12 +478,12 @@ func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def if i, err := check.verify(x.Pos(), inst.tparams.list(), inst.targs.list()); err != nil { // best position for error reporting pos := x.Pos() - if i < len(posList) { - pos = posList[i] + if i < len(xlist) { + pos = syntax.StartPos(xlist[i]) } - check.softErrorf(pos, err.Error()) + check.softErrorf(pos, "%s", err) } else { - check.mono.recordInstance(check.pkg, x.Pos(), inst.tparams.list(), inst.targs.list(), posList) + check.mono.recordInstance(check.pkg, x.Pos(), inst.tparams.list(), inst.targs.list(), xlist) } } -- GitLab From b77f5f9667c6e5c2081d94163dd7d11c03fa2b8e Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 23 Nov 2021 15:55:11 -0800 Subject: [PATCH 2322/2500] cmd/compile/internal/types2: better error message for missing ~ in constraint If a constraint could be satisfied if one of its type elements had a ~, provide this information in the error message. Fixes #49179. Change-Id: I59f1a855a0646ad7254a978420b0334f1f52ec22 Reviewed-on: https://go-review.googlesource.com/c/go/+/366758 Trust: Robert Griesemer Reviewed-by: Robert Findley --- .../compile/internal/types2/instantiate.go | 25 ++++++++++++++++--- .../types2/testdata/fixedbugs/issue49179.go2 | 20 ++++++++++++++- src/cmd/compile/internal/types2/typeset.go | 2 ++ 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 3f5fc56f5d..f9423dd70e 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -238,9 +238,28 @@ func (check *Checker) implements(V, T Type, qf Qualifier) error { } // Otherwise, V's type must be included in the iface type set. - if !Ti.typeSet().includes(V) { - // TODO(gri) report which type is missing - return errorf("%s does not implement %s", V, T) + var alt Type + if Ti.typeSet().is(func(t *term) bool { + if !t.includes(V) { + // If V ∉ t.typ but V ∈ ~t.typ then remember this type + // so we can suggest it as an alternative in the error + // message. + if alt == nil && !t.tilde && Identical(t.typ, under(t.typ)) { + tt := *t + tt.tilde = true + if tt.includes(V) { + alt = t.typ + } + } + return true + } + return false + }) { + if alt != nil { + return errorf("%s does not implement %s (possibly missing ~ for %s in constraint %s)", V, T, alt, T) + } else { + return errorf("%s does not implement %s", V, T) + } } return nil diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49179.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49179.go2 index 7cba52aa25..75bea18072 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49179.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49179.go2 @@ -4,6 +4,24 @@ package p +func f1[P int | string]() {} +func f2[P ~int | string | float64]() {} +func f3[P int](x P) {} + +type myInt int +type myFloat float64 + +func _() { + _ = f1[int] + _ = f1[myInt /* ERROR possibly missing ~ for int in constraint int\|string */] + _ = f2[myInt] + _ = f2[myFloat /* ERROR possibly missing ~ for float64 in constraint int\|string|float64 */] + var x myInt + f3( /* ERROR myInt does not implement int \(possibly missing ~ for int in constraint int\) */ x) +} + +// test case from the issue + type SliceConstraint[T any] interface { []T } @@ -15,5 +33,5 @@ func Map[S SliceConstraint[E], E any](s S, f func(E) E) S { type MySlice []int func f(s MySlice) { - Map[MySlice /* ERROR MySlice does not implement SliceConstraint\[int\] */, int](s, nil) + Map[MySlice /* ERROR MySlice does not implement SliceConstraint\[int\] \(possibly missing ~ for \[\]int in constraint SliceConstraint\[int\]\) */, int](s, nil) } diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index a55e9d1d63..eaf614da64 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -108,6 +108,8 @@ func (s *_TypeSet) hasTerms() bool { return !s.terms.isEmpty() && !s.terms.isAll func (s *_TypeSet) singleType() Type { return s.terms.singleType() } // includes reports whether t ∈ s. +// TODO(gri) This function is not used anywhere anymore. Remove once we +// are clear that we don't need it elsewhere in the future. func (s *_TypeSet) includes(t Type) bool { return s.terms.includes(t) } // subsetOf reports whether s1 ⊆ s2. -- GitLab From b2a5a3771f5efdb499da215298c7bcc2f493b4f1 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 24 Nov 2021 10:35:21 -0500 Subject: [PATCH 2323/2500] cmd/dist: add buildtag parsing test Forgot to 'git add' this test written as part of CL 359314. For #41184. Change-Id: I2ebd48fd62a2053c8b16e5a8c48c1e11d1b86d5b Reviewed-on: https://go-review.googlesource.com/c/go/+/366894 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/cmd/dist/buildtag_test.go | 43 +++++++++++++++++++++++++++++++++++ src/cmd/go/go_test.go | 6 ++--- 2 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 src/cmd/dist/buildtag_test.go diff --git a/src/cmd/dist/buildtag_test.go b/src/cmd/dist/buildtag_test.go new file mode 100644 index 0000000000..f64abfd1f1 --- /dev/null +++ b/src/cmd/dist/buildtag_test.go @@ -0,0 +1,43 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + "reflect" + "testing" +) + +var buildParserTests = []struct { + x string + matched bool + err error +}{ + {"gc", true, nil}, + {"gccgo", false, nil}, + {"!gc", false, nil}, + {"gc && gccgo", false, nil}, + {"gc || gccgo", true, nil}, + {"gc || (gccgo && !gccgo)", true, nil}, + {"gc && (gccgo || !gccgo)", true, nil}, + {"!(gc && (gccgo || !gccgo))", false, nil}, + {"gccgo || gc", true, nil}, + {"!(!(!(gccgo || gc)))", false, nil}, + {"compiler_bootstrap", false, nil}, + {"cmd_go_bootstrap", true, nil}, + {"syntax(error", false, fmt.Errorf("parsing //go:build line: unexpected (")}, + {"(gc", false, fmt.Errorf("parsing //go:build line: missing )")}, + {"gc gc", false, fmt.Errorf("parsing //go:build line: unexpected tag")}, + {"(gc))", false, fmt.Errorf("parsing //go:build line: unexpected )")}, +} + +func TestBuildParser(t *testing.T) { + for _, tt := range buildParserTests { + matched, err := matchexpr(tt.x) + if matched != tt.matched || !reflect.DeepEqual(err, tt.err) { + t.Errorf("matchexpr(%q) = %v, %v; want %v, %v", tt.x, matched, err, tt.matched, tt.err) + } + } +} diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index d8bed1dac0..170c882df9 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -1128,11 +1128,11 @@ func TestGoListTest(t *testing.T) { tg.grepStdoutNot(`^testing \[sort.test\]$`, "unexpected test copy of testing") tg.grepStdoutNot(`^testing$`, "unexpected real copy of testing") - tg.run("list", "-test", "cmd/dist", "cmd/doc") - tg.grepStdout(`^cmd/dist$`, "missing cmd/dist") + tg.run("list", "-test", "cmd/buildid", "cmd/doc") + tg.grepStdout(`^cmd/buildid$`, "missing cmd/buildid") tg.grepStdout(`^cmd/doc$`, "missing cmd/doc") tg.grepStdout(`^cmd/doc\.test$`, "missing cmd/doc test") - tg.grepStdoutNot(`^cmd/dist\.test$`, "unexpected cmd/dist test") + tg.grepStdoutNot(`^cmd/buildid\.test$`, "unexpected cmd/buildid test") tg.grepStdoutNot(`^testing`, "unexpected testing") tg.run("list", "-test", "runtime/cgo") -- GitLab From c58243aa8a510a0f467715da71a3053a04365038 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Tue, 23 Nov 2021 20:04:24 +0100 Subject: [PATCH 2324/2500] runtime: support non-cooperative preemption on windows/arm This adds support for injecting asynchronous preemption calls on windows/arm. This code follows sigctxt.pushCall for POSIX OSes on arm, except we subtract 1 from IP, just as in CL 273727. Updates #10958. Updates #24543. Updates #49759. Change-Id: Id0c2aed28662f50631b8c8cede3b4e6f088dafea Reviewed-on: https://go-review.googlesource.com/c/go/+/366734 Trust: Jason A. Donenfeld Reviewed-by: Austin Clements Reviewed-by: Patrik Nyblom Reviewed-by: Cherry Mui --- src/runtime/os_windows.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go index 7ffb3a11b5..a85971c6a9 100644 --- a/src/runtime/os_windows.go +++ b/src/runtime/os_windows.go @@ -1306,7 +1306,7 @@ func setThreadCPUProfiler(hz int32) { atomic.Store((*uint32)(unsafe.Pointer(&getg().m.profilehz)), uint32(hz)) } -const preemptMSupported = GOARCH == "386" || GOARCH == "amd64" +const preemptMSupported = GOARCH != "arm64" // suspendLock protects simultaneous SuspendThread operations from // suspending each other. @@ -1399,8 +1399,20 @@ func preemptM(mp *m) { *(*uintptr)(unsafe.Pointer(sp)) = newpc c.set_sp(sp) c.set_ip(targetPC) - } + case "arm": + // Push LR. The injected call is responsible + // for restoring LR. gentraceback is aware of + // this extra slot. See sigctxt.pushCall in + // signal_arm.go, which is similar except we + // subtract 1 from IP here. + sp := c.sp() + sp -= goarch.PtrSize + c.set_sp(sp) + *(*uint32)(unsafe.Pointer(sp)) = uint32(c.lr()) + c.set_lr(newpc - 1) + c.set_ip(targetPC) + } stdcall2(_SetThreadContext, thread, uintptr(unsafe.Pointer(c))) } } -- GitLab From f7e34e705c533cca0970f1c6d1eafc2666a6a947 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Tue, 23 Nov 2021 20:57:24 +0100 Subject: [PATCH 2325/2500] runtime: support non-cooperative preemption on windows/arm64 This adds support for injecting asynchronous preemption calls on windows/arm64. This code exactly follows sigctxt.pushCall for POSIX OSes on arm64. Fixes #49759. Change-Id: Id35ff6bc105c1db9d7ed2918d3ecab0e4e9a9431 Reviewed-on: https://go-review.googlesource.com/c/go/+/366735 Trust: Jason A. Donenfeld Run-TryBot: Jason A. Donenfeld TryBot-Result: Go Bot Reviewed-by: Cherry Mui Reviewed-by: Austin Clements Reviewed-by: Patrik Nyblom --- src/runtime/os_windows.go | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go index a85971c6a9..15953ffa0c 100644 --- a/src/runtime/os_windows.go +++ b/src/runtime/os_windows.go @@ -1306,18 +1306,13 @@ func setThreadCPUProfiler(hz int32) { atomic.Store((*uint32)(unsafe.Pointer(&getg().m.profilehz)), uint32(hz)) } -const preemptMSupported = GOARCH != "arm64" +const preemptMSupported = true // suspendLock protects simultaneous SuspendThread operations from // suspending each other. var suspendLock mutex func preemptM(mp *m) { - if !preemptMSupported { - // TODO: Implement call injection - return - } - if mp == getg().m { throw("self-preempt") } @@ -1412,6 +1407,17 @@ func preemptM(mp *m) { *(*uint32)(unsafe.Pointer(sp)) = uint32(c.lr()) c.set_lr(newpc - 1) c.set_ip(targetPC) + + case "arm64": + // Push LR. The injected call is responsible + // for restoring LR. gentraceback is aware of + // this extra slot. See sigctxt.pushCall in + // signal_arm64.go. + sp := c.sp() - 16 // SP needs 16-byte alignment + c.set_sp(sp) + *(*uint64)(unsafe.Pointer(sp)) = uint64(c.lr()) + c.set_lr(newpc) + c.set_ip(targetPC) } stdcall2(_SetThreadContext, thread, uintptr(unsafe.Pointer(c))) } -- GitLab From 45bae64015975a4d7ede597a55397545571d8bc5 Mon Sep 17 00:00:00 2001 From: Chaoqun Han Date: Thu, 25 Nov 2021 09:41:06 +0800 Subject: [PATCH 2326/2500] A+C: add Chaoqun Han (individual CLA) Change-Id: Id4aa067ef84510a31992d7d32cc697dd8b8342f1 Reviewed-on: https://go-review.googlesource.com/c/go/+/367035 Reviewed-by: Meng Zhuo Reviewed-by: Ian Lance Taylor Trust: Meng Zhuo Run-TryBot: Meng Zhuo TryBot-Result: Go Bot --- AUTHORS | 1 + CONTRIBUTORS | 1 + 2 files changed, 2 insertions(+) diff --git a/AUTHORS b/AUTHORS index 6f304f3672..43dded948d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -262,6 +262,7 @@ Casey Callendrello Casey Marshall Cezar Sá Espinola ChaiShushan +Chaoqun Han Charles Fenwick Elliott Charles L. Dorian Charles Lee diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 7f74b0ce5b..8018f9518a 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -475,6 +475,7 @@ ChaiShushan Changkun Ou Channing Kimble-Brown Chao Xu +Chaoqun Han Charles Fenwick Elliott Charles Kenney Charles L. Dorian -- GitLab From a0506bdf7c9741974c54d9dac55517025ba2572d Mon Sep 17 00:00:00 2001 From: sivchari Date: Fri, 26 Nov 2021 07:45:44 +0000 Subject: [PATCH 2327/2500] test/fixedbugs: fix go directive of issue16008.go This change modifies issue16008.go I fixed // go:noinline to //go:noinline Change-Id: Ic133eec51f0a7c4acf8cb22d25473ca08f1e916c GitHub-Last-Rev: dd1868f2ca1f9ca7e2d6d1bfc15c601649896fdd GitHub-Pull-Request: golang/go#49801 Reviewed-on: https://go-review.googlesource.com/c/go/+/367174 Reviewed-by: Alberto Donizetti Reviewed-by: Emmanuel Odeke Trust: Alberto Donizetti Run-TryBot: Alberto Donizetti TryBot-Result: Go Bot --- test/fixedbugs/issue16008.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fixedbugs/issue16008.go b/test/fixedbugs/issue16008.go index 45457cdb7f..b88e2351b7 100644 --- a/test/fixedbugs/issue16008.go +++ b/test/fixedbugs/issue16008.go @@ -37,7 +37,7 @@ type Node struct { type MemoryStore struct { } -// go:noinline +//go:noinline func setupNodes(n int) (s *MemoryStore, nodeIDs []string) { return } -- GitLab From 77038044ca7b11fce7eb11f3e6115ed753c2c2bd Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Thu, 25 Nov 2021 13:05:58 +0100 Subject: [PATCH 2328/2500] doc/go1.18: document non-cooperative preemption on windows/arm{,64} For #47694. Updates #49759. Change-Id: I7accd81b8ea6c31e4a2b5e155cf93fe9c447813b Reviewed-on: https://go-review.googlesource.com/c/go/+/367095 Trust: Jason A. Donenfeld Reviewed-by: Emmanuel Odeke --- doc/go1.18.html | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 6d813dce2e..c9c70267f1 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -193,8 +193,11 @@ proposal.

    Runtime

    -

    - TODO: complete this section, or delete if not needed +

    + The

    windows/arm
    and
    windows/arm64
    ports now support + non-cooperative preemption, bringing that capability to all four Windows + ports, which should hopefully address subtle bugs encountered when calling + into Win32 functions that block for extended periods of time.

    Compiler

    -- GitLab From bf88adadac9bbb1b190ba7af1010373823dabb06 Mon Sep 17 00:00:00 2001 From: Roi Martin Date: Thu, 25 Nov 2021 13:47:39 +0100 Subject: [PATCH 2329/2500] cmd/doc: fix "builtin" package parsing As stated in the code, "The builtin package needs special treatment: its symbols are lower case but we want to see them, always". Thus, cmd/doc forces the -u flag if the package being queried is called "builtin". However, this happens after having already parsed the package. This CL forces the -u flag just after parsing the command arguments and before parsing any package. Fixes #49796. Change-Id: If690a900c7cfd1700feecb9529bd4344c3c249d1 Reviewed-on: https://go-review.googlesource.com/c/go/+/367134 Reviewed-by: Rob Pike Run-TryBot: Rob Pike TryBot-Result: Go Bot Trust: Emmanuel Odeke --- src/cmd/doc/main.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/cmd/doc/main.go b/src/cmd/doc/main.go index 0499c40369..dee5d7bbcd 100644 --- a/src/cmd/doc/main.go +++ b/src/cmd/doc/main.go @@ -110,6 +110,13 @@ func do(writer io.Writer, flagSet *flag.FlagSet, args []string) (err error) { if buildPackage == nil { return fmt.Errorf("no such package: %s", userPath) } + + // The builtin package needs special treatment: its symbols are lower + // case but we want to see them, always. + if buildPackage.ImportPath == "builtin" { + unexported = true + } + symbol, method = parseSymbol(sym) pkg := parsePackage(writer, buildPackage, userPath) paths = append(paths, pkg.prettyPath()) @@ -128,12 +135,6 @@ func do(writer io.Writer, flagSet *flag.FlagSet, args []string) (err error) { panic(e) }() - // The builtin package needs special treatment: its symbols are lower - // case but we want to see them, always. - if pkg.build.ImportPath == "builtin" { - unexported = true - } - // We have a package. if showAll && symbol == "" { pkg.allDoc() -- GitLab From 1d47a1184a4718a34ab1df4d9bf05a284aba4c70 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 26 Nov 2021 07:36:09 -0800 Subject: [PATCH 2330/2500] bufio: mention that panic at slicing means underlying reader is broken Fixes #49795 Change-Id: I2b4fd14f0ed36b643522559bebf5ce52b1d7b304 Reviewed-on: https://go-review.googlesource.com/c/go/+/367214 Trust: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/bufio/bufio.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bufio/bufio.go b/src/bufio/bufio.go index 9ea058db3e..7483946fc0 100644 --- a/src/bufio/bufio.go +++ b/src/bufio/bufio.go @@ -244,6 +244,8 @@ func (b *Reader) Read(p []byte) (n int, err error) { } // copy as much as we can + // Note: if the slice panics here, it is probably because + // the underlying reader returned a bad count. See issue 49795. n = copy(p, b.buf[b.r:b.w]) b.r += n b.lastByte = int(b.buf[b.r-1]) -- GitLab From fad67f8a5342f4bc309f26f0ae021ce9d21724e6 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Thu, 25 Nov 2021 12:22:36 +0100 Subject: [PATCH 2331/2500] cmd/go/internal: gofmt after CL 355010 Change-Id: I25902cc4e7a3d2a78b467825b723cd72b310e2a3 Reviewed-on: https://go-review.googlesource.com/c/go/+/367094 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Emmanuel Odeke --- src/cmd/go/internal/generate/generate.go | 2 +- src/cmd/go/internal/get/get.go | 2 +- src/cmd/go/internal/list/list.go | 2 +- src/cmd/go/internal/load/test.go | 2 +- src/cmd/go/internal/modload/query.go | 2 +- src/cmd/go/internal/run/run.go | 2 +- src/cmd/go/internal/vcs/vcs.go | 2 +- src/cmd/go/internal/work/buildid.go | 2 +- src/cmd/go/internal/work/gccgo.go | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/cmd/go/internal/generate/generate.go b/src/cmd/go/internal/generate/generate.go index a3873d1138..4c17f42930 100644 --- a/src/cmd/go/internal/generate/generate.go +++ b/src/cmd/go/internal/generate/generate.go @@ -25,8 +25,8 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/load" "cmd/go/internal/modload" - "cmd/go/internal/work" "cmd/go/internal/str" + "cmd/go/internal/work" ) var CmdGenerate = &base.Command{ diff --git a/src/cmd/go/internal/get/get.go b/src/cmd/go/internal/get/get.go index f46313dcff..8cf8fe6645 100644 --- a/src/cmd/go/internal/get/get.go +++ b/src/cmd/go/internal/get/get.go @@ -17,10 +17,10 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/load" "cmd/go/internal/search" + "cmd/go/internal/str" "cmd/go/internal/vcs" "cmd/go/internal/web" "cmd/go/internal/work" - "cmd/go/internal/str" "golang.org/x/mod/module" ) diff --git a/src/cmd/go/internal/list/list.go b/src/cmd/go/internal/list/list.go index 8c85ddcf21..5ecd384787 100644 --- a/src/cmd/go/internal/list/list.go +++ b/src/cmd/go/internal/list/list.go @@ -23,8 +23,8 @@ import ( "cmd/go/internal/load" "cmd/go/internal/modinfo" "cmd/go/internal/modload" - "cmd/go/internal/work" "cmd/go/internal/str" + "cmd/go/internal/work" ) var CmdList = &base.Command{ diff --git a/src/cmd/go/internal/load/test.go b/src/cmd/go/internal/load/test.go index 8a18dfbe93..6122428c9c 100644 --- a/src/cmd/go/internal/load/test.go +++ b/src/cmd/go/internal/load/test.go @@ -22,8 +22,8 @@ import ( "unicode/utf8" "cmd/go/internal/fsys" - "cmd/go/internal/trace" "cmd/go/internal/str" + "cmd/go/internal/trace" ) var TestMainDeps = []string{ diff --git a/src/cmd/go/internal/modload/query.go b/src/cmd/go/internal/modload/query.go index 1eb484de9d..33808ea109 100644 --- a/src/cmd/go/internal/modload/query.go +++ b/src/cmd/go/internal/modload/query.go @@ -21,8 +21,8 @@ import ( "cmd/go/internal/imports" "cmd/go/internal/modfetch" "cmd/go/internal/search" - "cmd/go/internal/trace" "cmd/go/internal/str" + "cmd/go/internal/trace" "golang.org/x/mod/module" "golang.org/x/mod/semver" diff --git a/src/cmd/go/internal/run/run.go b/src/cmd/go/internal/run/run.go index 03895d27eb..878cee367e 100644 --- a/src/cmd/go/internal/run/run.go +++ b/src/cmd/go/internal/run/run.go @@ -18,8 +18,8 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/load" "cmd/go/internal/modload" - "cmd/go/internal/work" "cmd/go/internal/str" + "cmd/go/internal/work" ) var CmdRun = &base.Command{ diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go index b2ce80325a..77a75fd51c 100644 --- a/src/cmd/go/internal/vcs/vcs.go +++ b/src/cmd/go/internal/vcs/vcs.go @@ -26,8 +26,8 @@ import ( "cmd/go/internal/base" "cmd/go/internal/cfg" "cmd/go/internal/search" - "cmd/go/internal/web" "cmd/go/internal/str" + "cmd/go/internal/web" "golang.org/x/mod/module" ) diff --git a/src/cmd/go/internal/work/buildid.go b/src/cmd/go/internal/work/buildid.go index d4f2a716d7..4e9189a363 100644 --- a/src/cmd/go/internal/work/buildid.go +++ b/src/cmd/go/internal/work/buildid.go @@ -15,8 +15,8 @@ import ( "cmd/go/internal/cache" "cmd/go/internal/cfg" "cmd/go/internal/fsys" - "cmd/internal/buildid" "cmd/go/internal/str" + "cmd/internal/buildid" ) // Build IDs diff --git a/src/cmd/go/internal/work/gccgo.go b/src/cmd/go/internal/work/gccgo.go index 60181b99e4..1499536932 100644 --- a/src/cmd/go/internal/work/gccgo.go +++ b/src/cmd/go/internal/work/gccgo.go @@ -16,8 +16,8 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/fsys" "cmd/go/internal/load" - "cmd/internal/pkgpath" "cmd/go/internal/str" + "cmd/internal/pkgpath" ) // The Gccgo toolchain. -- GitLab From a142d6587cb6a7ac59ebf49120167c96bdc3bcf6 Mon Sep 17 00:00:00 2001 From: Carlo Alberto Ferraris Date: Mon, 22 Nov 2021 01:26:48 +0000 Subject: [PATCH 2332/2500] doc: go1.18 release notes for CLs 323318/332771 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updates #47694 Change-Id: Ib76737996a701906117e096eb6d05b388576a874 GitHub-Last-Rev: 05b96499651bb4e90617460a72f1df9f2c8615f3 GitHub-Pull-Request: golang/go#49588 Reviewed-on: https://go-review.googlesource.com/c/go/+/363840 Reviewed-by: Dmitri Shuralyov Trust: Daniel Martí --- doc/go1.18.html | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index c9c70267f1..1788e97663 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -304,9 +304,10 @@ proposal.
    bytes
    -

    - bytes.Trim and related - functions, have had their most common use cases optimized. +

    + Trim, TrimLeft, + and TrimRight are now allocation free and, especially for + small ASCII cutsets, up to 10 times faster.

    @@ -447,9 +448,10 @@ proposal. the input string's memory.

    -

    - strings.Trim and related functions - functions, have had their most common use cases optimized. +

    + Trim, TrimLeft, + and TrimRight are now allocation free and, especially for + small ASCII cutsets, up to 10 times faster.

    -- GitLab From 7e1260f62b7447c36d9f3ff95365d761592323c4 Mon Sep 17 00:00:00 2001 From: sivchari Date: Sat, 27 Nov 2021 23:02:16 +0000 Subject: [PATCH 2333/2500] testing: simplify fuzzResult.String to avoid unnecessarily using fmt.Sprintf Change-Id: I16b6bfb6b0f02672c894b20845aa14d8dd1979b4 GitHub-Last-Rev: 75ab90123a8a5ad42e96795b756d3a9e898aaa06 GitHub-Pull-Request: golang/go#49819 Reviewed-on: https://go-review.googlesource.com/c/go/+/367314 Reviewed-by: Emmanuel Odeke Reviewed-by: Ian Lance Taylor Run-TryBot: Emmanuel Odeke TryBot-Result: Go Bot --- src/testing/fuzz.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 24a0080730..19ff39947b 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -423,12 +423,10 @@ type fuzzResult struct { } func (r fuzzResult) String() string { - s := "" if r.Error == nil { - return s + return "" } - s = fmt.Sprintf("%s", r.Error.Error()) - return s + return r.Error.Error() } // fuzzCrashError is satisfied by a failing input detected while fuzzing. -- GitLab From 9f2a075df905d873e3e426b2f549c327d228ac26 Mon Sep 17 00:00:00 2001 From: tangxi666 Date: Sat, 27 Nov 2021 05:20:05 +0000 Subject: [PATCH 2334/2500] cmd/go: fix a typo in mod_lazy_new_import.txt x/y -> a/y Change-Id: If24970623731098bb72345b8f4c8518b563bbec8 GitHub-Last-Rev: 8a35dddbc155d97f03c08c06d945596584bc2e6d GitHub-Pull-Request: golang/go#49813 Reviewed-on: https://go-review.googlesource.com/c/go/+/367202 Reviewed-by: Ian Lance Taylor Reviewed-by: Emmanuel Odeke Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot --- src/cmd/go/testdata/script/mod_lazy_new_import.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/go/testdata/script/mod_lazy_new_import.txt b/src/cmd/go/testdata/script/mod_lazy_new_import.txt index 4272a52de1..520d8459cc 100644 --- a/src/cmd/go/testdata/script/mod_lazy_new_import.txt +++ b/src/cmd/go/testdata/script/mod_lazy_new_import.txt @@ -7,7 +7,7 @@ # \ # ---- a/y (new) ---- c # -# Where a/x and x/y are disjoint packages, but both contained in module a. +# Where a/x and a/y are disjoint packages, but both contained in module a. # # The module dependency graph initially looks like: # -- GitLab From 0fa53e41f122b1661d0678a6d36d71b7b5ad031d Mon Sep 17 00:00:00 2001 From: syumai Date: Sat, 27 Nov 2021 11:16:57 +0000 Subject: [PATCH 2335/2500] spec: fix link for instantiations This change corrects the link `Instantiantions` to `Instantiations` in the spec. Change-Id: Ib0ed03420ae401d20af1ea723c5487018b2f462d GitHub-Last-Rev: b84316c818b4aba022362fd09fac0d2b85da1a81 GitHub-Pull-Request: golang/go#49816 Reviewed-on: https://go-review.googlesource.com/c/go/+/367274 Reviewed-by: Ian Lance Taylor Reviewed-by: Emmanuel Odeke --- doc/go_spec.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index b8e6aceee9..4700548cb2 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -2883,7 +2883,7 @@ to use. This makes the receiver type parameters available to the method.

    Syntactically, this type parameter declaration looks like an -instantiation of the receiver base type, except that +instantiation of the receiver base type, except that the type arguments are the type parameters being declared, one for each type parameter of the receiver base type. The type parameter names do not need to match their corresponding parameter names in the -- GitLab From 78af02e8b5c5c9d3c6d5026fd72f57026a14952a Mon Sep 17 00:00:00 2001 From: Bharath Kumar Uppala Date: Thu, 25 Nov 2021 10:09:47 +0530 Subject: [PATCH 2336/2500] A+C: add Bharath Kumar Uppala (individual CLA) Change-Id: I4943e943892bd29bca2afafddb62f3060bc153e9 Reviewed-on: https://go-review.googlesource.com/c/go/+/367074 Reviewed-by: Ian Lance Taylor Reviewed-by: Meng Zhuo --- AUTHORS | 1 + CONTRIBUTORS | 1 + 2 files changed, 2 insertions(+) diff --git a/AUTHORS b/AUTHORS index 43dded948d..1a4a57bae7 100644 --- a/AUTHORS +++ b/AUTHORS @@ -209,6 +209,7 @@ Benjamin Hsieh Benny Siegert Benoit Sigoure Berengar Lehr +Bharath Kumar Uppala Bill Zissimopoulos Billie Harold Cleek Bjorn Tillenius diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 8018f9518a..e2e102f610 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -368,6 +368,7 @@ Benny Siegert Benoit Sigoure Berengar Lehr Berkant Ipek <41230766+0xbkt@users.noreply.github.com> +Bharath Kumar Uppala Bharath Thiruveedula Bhavin Gandhi Bill Neubauer -- GitLab From 1ea4d3b91164fb08b7022958b6cd8e290f12e017 Mon Sep 17 00:00:00 2001 From: Meng Zhuo Date: Tue, 30 Mar 2021 19:58:35 +0800 Subject: [PATCH 2337/2500] cmd/link: merge note sections into one segment The ld from binutils merges note sections into one PT_NOTE segment. We should do that for consistency with binutils. Change-Id: I45703525c720972d49c36c4f10ac47d1628b5698 Reviewed-on: https://go-review.googlesource.com/c/go/+/265957 Trust: Meng Zhuo Trust: Emmanuel Odeke Run-TryBot: Meng Zhuo TryBot-Result: Go Bot Reviewed-by: Cherry Mui --- src/cmd/link/elf_test.go | 55 +++++++++++++++++++++++++++++++++ src/cmd/link/internal/ld/elf.go | 39 ++++++++++------------- 2 files changed, 71 insertions(+), 23 deletions(-) diff --git a/src/cmd/link/elf_test.go b/src/cmd/link/elf_test.go index 012c0b5169..760d9ea60d 100644 --- a/src/cmd/link/elf_test.go +++ b/src/cmd/link/elf_test.go @@ -201,6 +201,61 @@ func TestMinusRSymsWithSameName(t *testing.T) { } } +func TestMergeNoteSections(t *testing.T) { + testenv.MustHaveGoBuild(t) + expected := 1 + + switch runtime.GOOS { + case "linux", "freebsd", "dragonfly": + case "openbsd", "netbsd": + // These OSes require independent segment + expected = 2 + default: + t.Skip("We should only test on elf output.") + } + t.Parallel() + + goFile := filepath.Join(t.TempDir(), "notes.go") + if err := ioutil.WriteFile(goFile, []byte(goSource), 0444); err != nil { + t.Fatal(err) + } + outFile := filepath.Join(t.TempDir(), "notes.exe") + goTool := testenv.GoToolPath(t) + // sha1sum of "gopher" + id := "0xf4e8cd51ce8bae2996dc3b74639cdeaa1f7fee5f" + cmd := exec.Command(goTool, "build", "-o", outFile, "-ldflags", + "-B "+id, goFile) + cmd.Dir = t.TempDir() + if out, err := cmd.CombinedOutput(); err != nil { + t.Logf("%s", out) + t.Fatal(err) + } + + ef, err := elf.Open(outFile) + if err != nil { + t.Fatalf("open elf file failed:%v", err) + } + defer ef.Close() + sec := ef.Section(".note.gnu.build-id") + if sec == nil { + t.Fatalf("can't find gnu build id") + } + + sec = ef.Section(".note.go.buildid") + if sec == nil { + t.Fatalf("can't find go build id") + } + cnt := 0 + for _, ph := range ef.Progs { + if ph.Type == elf.PT_NOTE { + cnt += 1 + } + } + if cnt != expected { + t.Fatalf("want %d PT_NOTE segment, got %d", expected, cnt) + } +} + const pieSourceTemplate = ` package main diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go index fb75c761a1..4a143dfcaa 100644 --- a/src/cmd/link/internal/ld/elf.go +++ b/src/cmd/link/internal/ld/elf.go @@ -1682,13 +1682,18 @@ func asmbElf(ctxt *Link) { var pph *ElfPhdr var pnote *ElfPhdr + getpnote := func() *ElfPhdr { + if pnote == nil { + pnote = newElfPhdr() + pnote.Type = elf.PT_NOTE + pnote.Flags = elf.PF_R + } + return pnote + } if *flagRace && ctxt.IsNetbsd() { sh := elfshname(".note.netbsd.pax") resoff -= int64(elfnetbsdpax(sh, uint64(startva), uint64(resoff))) - pnote = newElfPhdr() - pnote.Type = elf.PT_NOTE - pnote.Flags = elf.PF_R - phsh(pnote, sh) + phsh(getpnote(), sh) } if ctxt.LinkMode == LinkExternal { /* skip program headers */ @@ -1787,7 +1792,6 @@ func asmbElf(ctxt *Link) { phsh(ph, sh) } - pnote = nil if ctxt.HeadType == objabi.Hnetbsd || ctxt.HeadType == objabi.Hopenbsd { var sh *ElfShdr switch ctxt.HeadType { @@ -1799,34 +1803,23 @@ func asmbElf(ctxt *Link) { sh = elfshname(".note.openbsd.ident") resoff -= int64(elfopenbsdsig(sh, uint64(startva), uint64(resoff))) } - - pnote = newElfPhdr() - pnote.Type = elf.PT_NOTE - pnote.Flags = elf.PF_R - phsh(pnote, sh) + // netbsd and openbsd require ident in an independent segment. + pnotei := newElfPhdr() + pnotei.Type = elf.PT_NOTE + pnotei.Flags = elf.PF_R + phsh(pnotei, sh) } if len(buildinfo) > 0 { sh := elfshname(".note.gnu.build-id") resoff -= int64(elfbuildinfo(sh, uint64(startva), uint64(resoff))) - - if pnote == nil { - pnote = newElfPhdr() - pnote.Type = elf.PT_NOTE - pnote.Flags = elf.PF_R - } - - phsh(pnote, sh) + phsh(getpnote(), sh) } if *flagBuildid != "" { sh := elfshname(".note.go.buildid") resoff -= int64(elfgobuildid(sh, uint64(startva), uint64(resoff))) - - pnote := newElfPhdr() - pnote.Type = elf.PT_NOTE - pnote.Flags = elf.PF_R - phsh(pnote, sh) + phsh(getpnote(), sh) } // Additions to the reserved area must be above this line. -- GitLab From a59ab29bf2164730e3e6d5439c6ec4b1e46adcc4 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Mon, 29 Nov 2021 11:05:41 -0500 Subject: [PATCH 2338/2500] doc/go1.18: use instead of

     for target
     specification
    
    For #47694.
    
    Signed-off-by: Jason A. Donenfeld 
    Change-Id: I38c2fd9b57fbbacf220a2bc679f67e2dfdcc7cb1
    Reviewed-on: https://go-review.googlesource.com/c/go/+/367514
    Reviewed-by: Dmitri Shuralyov 
    ---
     doc/go1.18.html | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/doc/go1.18.html b/doc/go1.18.html
    index 1788e97663..022541b83d 100644
    --- a/doc/go1.18.html
    +++ b/doc/go1.18.html
    @@ -194,7 +194,7 @@ proposal.
     

    Runtime

    - The

    windows/arm
    and
    windows/arm64
    ports now support + The windows/arm and windows/arm64 ports now support non-cooperative preemption, bringing that capability to all four Windows ports, which should hopefully address subtle bugs encountered when calling into Win32 functions that block for extended periods of time. -- GitLab From 4325c37d6789aff6f24b05526080b011dda86477 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 23 Nov 2021 12:34:04 -0800 Subject: [PATCH 2339/2500] vendor: update golang.org/x/net to tip This brings in a fix for OpenBSD that lets it correctly gather network interface information. For #42064 Change-Id: Ib88fd2f494bb2ee86fd2725d8375b2df1404c4ca Reviewed-on: https://go-review.googlesource.com/c/go/+/366756 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Dmitri Shuralyov Reviewed-by: Damien Neil Reviewed-by: Bryan C. Mills TryBot-Result: Go Bot --- src/go.mod | 2 +- src/go.sum | 4 +- src/net/http/h2_bundle.go | 76 ++++++++++++------- src/vendor/golang.org/x/net/lif/address.go | 1 + src/vendor/golang.org/x/net/lif/binary.go | 1 + src/vendor/golang.org/x/net/lif/lif.go | 1 + src/vendor/golang.org/x/net/lif/link.go | 1 + src/vendor/golang.org/x/net/lif/sys.go | 1 + src/vendor/golang.org/x/net/lif/syscall.go | 1 + src/vendor/golang.org/x/net/route/syscall.go | 26 ++----- .../x/net/route/syscall_go1_12_darwin.go | 13 ---- src/vendor/modules.txt | 2 +- 12 files changed, 63 insertions(+), 66 deletions(-) delete mode 100644 src/vendor/golang.org/x/net/route/syscall_go1_12_darwin.go diff --git a/src/go.mod b/src/go.mod index b8c4d5c16b..d26e4960b3 100644 --- a/src/go.mod +++ b/src/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa - golang.org/x/net v0.0.0-20211108170745-6635138e15ea + golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 ) require ( diff --git a/src/go.sum b/src/go.sum index ff1288f81d..fddc4fbe93 100644 --- a/src/go.sum +++ b/src/go.sum @@ -1,7 +1,7 @@ golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa h1:idItI2DDfCokpg0N51B2VtiLdJ4vAuXC9fnCb2gACo4= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/net v0.0.0-20211108170745-6635138e15ea h1:FosBMXtOc8Tp9Hbo4ltl1WJSrTVewZU8MPnTPY2HdH8= -golang.org/x/net v0.0.0-20211108170745-6635138e15ea/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 h1:0qxwC5n+ttVOINCBeRHO0nq9X7uy8SDsPoi5OaCdIEI= +golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e h1:i6Vklmyu+fZMFYpum+sR4ZWABGW7MyIxfJZXYvcnbns= golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 h1:GLw7MR8AfAG2GmGcmVgObFOHXYypgGjnGno25RDwn3Y= diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go index 23a4d15326..8d19c42b5a 100644 --- a/src/net/http/h2_bundle.go +++ b/src/net/http/h2_bundle.go @@ -7830,36 +7830,49 @@ func (cc *http2ClientConn) RoundTrip(req *Request) (*Response, error) { } } + handleResponseHeaders := func() (*Response, error) { + res := cs.res + if res.StatusCode > 299 { + // On error or status code 3xx, 4xx, 5xx, etc abort any + // ongoing write, assuming that the server doesn't care + // about our request body. If the server replied with 1xx or + // 2xx, however, then assume the server DOES potentially + // want our body (e.g. full-duplex streaming: + // golang.org/issue/13444). If it turns out the server + // doesn't, they'll RST_STREAM us soon enough. This is a + // heuristic to avoid adding knobs to Transport. Hopefully + // we can keep it. + cs.abortRequestBodyWrite() + } + res.Request = req + res.TLS = cc.tlsState + if res.Body == http2noBody && http2actualContentLength(req) == 0 { + // If there isn't a request or response body still being + // written, then wait for the stream to be closed before + // RoundTrip returns. + if err := waitDone(); err != nil { + return nil, err + } + } + return res, nil + } + for { select { case <-cs.respHeaderRecv: - res := cs.res - if res.StatusCode > 299 { - // On error or status code 3xx, 4xx, 5xx, etc abort any - // ongoing write, assuming that the server doesn't care - // about our request body. If the server replied with 1xx or - // 2xx, however, then assume the server DOES potentially - // want our body (e.g. full-duplex streaming: - // golang.org/issue/13444). If it turns out the server - // doesn't, they'll RST_STREAM us soon enough. This is a - // heuristic to avoid adding knobs to Transport. Hopefully - // we can keep it. - cs.abortRequestBodyWrite() - } - res.Request = req - res.TLS = cc.tlsState - if res.Body == http2noBody && http2actualContentLength(req) == 0 { - // If there isn't a request or response body still being - // written, then wait for the stream to be closed before - // RoundTrip returns. - if err := waitDone(); err != nil { - return nil, err - } - } - return res, nil + return handleResponseHeaders() case <-cs.abort: - waitDone() - return nil, cs.abortErr + select { + case <-cs.respHeaderRecv: + // If both cs.respHeaderRecv and cs.abort are signaling, + // pick respHeaderRecv. The server probably wrote the + // response and immediately reset the stream. + // golang.org/issue/49645 + return handleResponseHeaders() + default: + waitDone() + return nil, cs.abortErr + } case <-ctx.Done(): err := ctx.Err() cs.abortStream(err) @@ -7919,6 +7932,9 @@ func (cs *http2clientStream) writeRequest(req *Request) (err error) { return err } cc.addStreamLocked(cs) // assigns stream ID + if http2isConnectionCloseRequest(req) { + cc.doNotReuse = true + } cc.mu.Unlock() // TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere? @@ -8016,6 +8032,7 @@ func (cs *http2clientStream) writeRequest(req *Request) (err error) { case <-respHeaderTimer: return http2errTimeout case <-respHeaderRecv: + respHeaderRecv = nil respHeaderTimer = nil // keep waiting for END_STREAM case <-cs.abort: return cs.abortErr @@ -9019,7 +9036,7 @@ func (rl *http2clientConnReadLoop) handleResponse(cs *http2clientStream, f *http cs.bytesRemain = res.ContentLength res.Body = http2transportResponseBody{cs} - if cs.requestedGzip && res.Header.Get("Content-Encoding") == "gzip" { + if cs.requestedGzip && http2asciiEqualFold(res.Header.Get("Content-Encoding"), "gzip") { res.Header.Del("Content-Encoding") res.Header.Del("Content-Length") res.ContentLength = -1 @@ -9158,7 +9175,10 @@ func (b http2transportResponseBody) Close() error { select { case <-cs.donec: case <-cs.ctx.Done(): - return cs.ctx.Err() + // See golang/go#49366: The net/http package can cancel the + // request context after the response body is fully read. + // Don't treat this as an error. + return nil case <-cs.reqCancel: return http2errRequestCanceled } diff --git a/src/vendor/golang.org/x/net/lif/address.go b/src/vendor/golang.org/x/net/lif/address.go index afb957fd8e..34b6432d6e 100644 --- a/src/vendor/golang.org/x/net/lif/address.go +++ b/src/vendor/golang.org/x/net/lif/address.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build solaris // +build solaris package lif diff --git a/src/vendor/golang.org/x/net/lif/binary.go b/src/vendor/golang.org/x/net/lif/binary.go index 738a94f422..f31ca3ad07 100644 --- a/src/vendor/golang.org/x/net/lif/binary.go +++ b/src/vendor/golang.org/x/net/lif/binary.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build solaris // +build solaris package lif diff --git a/src/vendor/golang.org/x/net/lif/lif.go b/src/vendor/golang.org/x/net/lif/lif.go index 6e81f81f1c..95c7d25846 100644 --- a/src/vendor/golang.org/x/net/lif/lif.go +++ b/src/vendor/golang.org/x/net/lif/lif.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build solaris // +build solaris // Package lif provides basic functions for the manipulation of diff --git a/src/vendor/golang.org/x/net/lif/link.go b/src/vendor/golang.org/x/net/lif/link.go index 913a53e118..f1af1306ca 100644 --- a/src/vendor/golang.org/x/net/lif/link.go +++ b/src/vendor/golang.org/x/net/lif/link.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build solaris // +build solaris package lif diff --git a/src/vendor/golang.org/x/net/lif/sys.go b/src/vendor/golang.org/x/net/lif/sys.go index c896041b7b..d0b532d9dc 100644 --- a/src/vendor/golang.org/x/net/lif/sys.go +++ b/src/vendor/golang.org/x/net/lif/sys.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build solaris // +build solaris package lif diff --git a/src/vendor/golang.org/x/net/lif/syscall.go b/src/vendor/golang.org/x/net/lif/syscall.go index aadab2e14b..8d03b4aa92 100644 --- a/src/vendor/golang.org/x/net/lif/syscall.go +++ b/src/vendor/golang.org/x/net/lif/syscall.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build solaris // +build solaris package lif diff --git a/src/vendor/golang.org/x/net/route/syscall.go b/src/vendor/golang.org/x/net/route/syscall.go index 97166dd3c4..68d37c9621 100644 --- a/src/vendor/golang.org/x/net/route/syscall.go +++ b/src/vendor/golang.org/x/net/route/syscall.go @@ -2,28 +2,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build dragonfly || freebsd || netbsd || openbsd -// +build dragonfly freebsd netbsd openbsd +//go:build darwin || dragonfly || freebsd || netbsd || openbsd +// +build darwin dragonfly freebsd netbsd openbsd package route -import ( - "syscall" - "unsafe" -) +import _ "unsafe" // for linkname -var zero uintptr - -func sysctl(mib []int32, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error { - var p unsafe.Pointer - if len(mib) > 0 { - p = unsafe.Pointer(&mib[0]) - } else { - p = unsafe.Pointer(&zero) - } - _, _, errno := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(p), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), newlen) - if errno != 0 { - return error(errno) - } - return nil -} +//go:linkname sysctl syscall.sysctl +func sysctl(mib []int32, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error diff --git a/src/vendor/golang.org/x/net/route/syscall_go1_12_darwin.go b/src/vendor/golang.org/x/net/route/syscall_go1_12_darwin.go deleted file mode 100644 index 7a13e4fd90..0000000000 --- a/src/vendor/golang.org/x/net/route/syscall_go1_12_darwin.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.12 -// +build go1.12 - -package route - -import _ "unsafe" // for linkname - -//go:linkname sysctl syscall.sysctl -func sysctl(mib []int32, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index 004b599288..2650806683 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -9,7 +9,7 @@ golang.org/x/crypto/curve25519/internal/field golang.org/x/crypto/hkdf golang.org/x/crypto/internal/poly1305 golang.org/x/crypto/internal/subtle -# golang.org/x/net v0.0.0-20211108170745-6635138e15ea +# golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 ## explicit; go 1.17 golang.org/x/net/dns/dnsmessage golang.org/x/net/http/httpguts -- GitLab From 37a5d720d4c4ebf3fd0c8a089a3bde347d72c01a Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sun, 28 Nov 2021 14:17:11 -0800 Subject: [PATCH 2340/2500] spec: corrections to various sections - fix definition of "specific types" and add more examples - state that a parameterized function must be instantiated when used as a function value - remove duplicate word ("can can" -> "can") Thanks to @danscales for finding these. Change-Id: Ideb41efc35a3e67694d3bc97e462454feae37c44 Reviewed-on: https://go-review.googlesource.com/c/go/+/367394 Trust: Robert Griesemer Trust: Dan Scales Reviewed-by: Ian Lance Taylor Reviewed-by: Dan Scales --- doc/go_spec.html | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index 4700548cb2..11f44d896d 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,6 +1,6 @@ @@ -1971,39 +1971,38 @@ x T x is not representable by a value of T because

    An interface specification which contains type elements -that are not interface types defines a (possibly empty) set of specific types. +defines a (possibly empty) set of specific types. Loosely speaking, these are the types T that appear in the interface definition in terms of the form T, ~T, or in unions of such terms.

    -More precisely, for a given interface, the set of specific types is defined as follows: +More precisely, for a given interface, the set 𝑆 of specific types is defined as follows:

      -
    • The set of specific types of the empty interface is the empty set. +
    • For an interface with no type elements, 𝑆 is the empty set.
    • -
    • The set of specific types of a non-empty interface is the intersection - of the specific types of its interface elements. +
    • For an interface with type elements, 𝑆 is the intersection + of the specific types of its type elements.
    • -
    • The set of specific types of a method specification is the empty set. +
    • For a non-interface type term T + or ~T, 𝑆 is the set consisting of the type T.
    • -
    • The set of specific types of a non-interface type term T - or ~T is the set consisting of the type T. -
    • - -
    • The set of specific types of a union of terms - t1|t2|…|tn - is the union of the specific types of the terms. +
    • For a union of terms + t1|t2|…|tn, + 𝑆 is the union of the specific types of the terms.

    -If the set of specific types is empty, the interface has no specific types. +If 𝑆 is empty, the interface has no specific types. +An interface may have specific types even if its type set +is empty.

    @@ -2019,6 +2018,8 @@ interface{ int } // int interface{ ~string } // string interface{ int|~string } // int, string interface{ Celsius|Kelvin } // Celsius, Kelvin +interface{ int; m() } // int (but type set is empty because int has no method m) +interface{ int; any } // no specific types (intersection is empty) interface{ int; string } // no specific types (intersection is empty)

    @@ -3980,7 +3981,8 @@ pt.Scale(3.5) // method call with receiver pt

    If f denotes a parameterized function, it must be -instantiated before it can be called. +instantiated before it can be called +or used as a function value.

    @@ -4807,7 +4809,7 @@ Only V is a type parameter and a value of each specific type of V can be converted to T.

  • -Only T is a type parameter and x can can be converted to each +Only T is a type parameter and x can be converted to each specific type of T.
  • -- GitLab From 68da368a4ed0f6f47e841d75aaed0faf1dcf425c Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 23 Nov 2021 20:24:40 -0800 Subject: [PATCH 2341/2500] spec: rules for index expressions, len, cap, with type parameter types We want to support some special cases for index expressions, len, and cap on operands of type parameters (such as indexing a value constrained by byte slices and strings), hence the extra rules. Change-Id: I4a07dc7e64bb47361b021d606c52eae1784d5430 Reviewed-on: https://go-review.googlesource.com/c/go/+/366814 Trust: Robert Griesemer Trust: Dan Scales Reviewed-by: Dan Scales --- doc/go_spec.html | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index 11f44d896d..8643d94476 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -2269,7 +2269,6 @@ An identifier is exported if both: All other identifiers are not exported.

    -

    Uniqueness of identifiers

    @@ -3715,6 +3714,26 @@ For a of map type M: for the element type of M +

    +For a of type parameter type P: +

    +
      +
    • P must have specific types.
    • +
    • The index expression a[x] must be valid for values + of all specific types of P.
    • +
    • The element types of all specific types of P must be identical. + In this context, the element type of a string type is byte.
    • +
    • If there is a map type among the specific types of P, + all specific types must be map types, and the respective key types + must be all identical.
    • +
    • a[x] is the array, slice, or string element at index x, + or the map element with key x of the type argument + that P is instantiated with, and the type of a[x] is + the type of the (identical) element types.
    • +
    • a[x] may not be assigned to if the specific types of P + include string types. +
    +

    Otherwise a[x] is illegal.

    @@ -6468,12 +6487,24 @@ len(s) string type string length in bytes []T slice length map[K]T map length (number of defined keys) chan T number of elements queued in channel buffer + type parameter see below cap(s) [n]T, *[n]T array length (== n) []T slice capacity chan T channel buffer capacity + type parameter see below
    +

    +If the argument type is a type parameter P, +P must have specific types, and +the call len(e) (or cap(e) respectively) must be valid for +each specific type of P. +The result is the length (or capacity, respectively) of the argument whose type +corresponds to the type argument with which P was +instantiated. +

    +

    The capacity of a slice is the number of elements for which there is space allocated in the underlying array. -- GitLab From 61ff5019687c125910c48c22d672a9b6985ee61e Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sun, 28 Nov 2021 15:25:09 -0800 Subject: [PATCH 2342/2500] spec: adjust section on package unsafe for type parameters Change-Id: I562d4648756e710020ee491f3801896563a89baa Reviewed-on: https://go-review.googlesource.com/c/go/+/367395 Trust: Robert Griesemer Trust: Dan Scales Reviewed-by: Ian Lance Taylor --- doc/go_spec.html | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index 8643d94476..2832b0739d 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -642,7 +642,7 @@ an identifier denoting a constant, a constant expression, a conversion with a result that is a constant, or the result value of some built-in functions such as -unsafe.Sizeof applied to any value, +unsafe.Sizeof applied to certain values, cap or len applied to some expressions, real and imag applied to a complex constant @@ -7446,8 +7446,14 @@ uintptr(unsafe.Pointer(&x)) % unsafe.Alignof(x) == 0

    -Calls to Alignof, Offsetof, and -Sizeof are compile-time constant expressions of type uintptr. +A (variable of) type T has variable size if T +is a type parameter, or if it is an array or struct type containing elements +or fields of variable size. Otherwise the size is constant. +Calls to Alignof, Offsetof, and Sizeof +are compile-time constant expressions of +type uintptr if their arguments (or the struct s in +the selector expression s.f for Offsetof) are types +of constant size.

    -- GitLab From f598e2962d3a358b59faa68471b6ed378fc68806 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 22 Nov 2021 15:33:01 -0500 Subject: [PATCH 2343/2500] runtime: fix preemption sensitivity in TestTinyAllocIssue37262 TestTinyAllocIssue37262 assumes that all of its allocations will come from the same tiny allocator (that is, the same P), and that nothing else will allocate from that tiny allocator while it's running. It can fail incorrectly if these assumptions aren't met. Fix this potential test flakiness by disabling preemption during this test. As far as I know, this has never happened on the builders. It was found by mayMoreStackPreempt. Change-Id: I59f993e0bdbf46a9add842d0e278415422c3f804 Reviewed-on: https://go-review.googlesource.com/c/go/+/366994 Trust: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Reviewed-by: Michael Knyszek --- src/runtime/export_test.go | 9 +++++++++ src/runtime/malloc_test.go | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index b2e64f14ad..ef601f770c 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -1307,3 +1307,12 @@ func escape(x interface{}) interface{} { escapeSink = nil return x } + +// Acquirem blocks preemption. +func Acquirem() { + acquirem() +} + +func Releasem() { + releasem(getg().m) +} diff --git a/src/runtime/malloc_test.go b/src/runtime/malloc_test.go index e028554b23..757f945393 100644 --- a/src/runtime/malloc_test.go +++ b/src/runtime/malloc_test.go @@ -198,6 +198,10 @@ func TestTinyAllocIssue37262(t *testing.T) { runtime.GC() runtime.GC() + // Disable preemption so we stay on one P's tiny allocator and + // nothing else allocates from it. + runtime.Acquirem() + // Make 1-byte allocations until we get a fresh tiny slot. aligned := false for i := 0; i < 16; i++ { @@ -208,6 +212,7 @@ func TestTinyAllocIssue37262(t *testing.T) { } } if !aligned { + runtime.Releasem() t.Fatal("unable to get a fresh tiny slot") } @@ -229,6 +234,8 @@ func TestTinyAllocIssue37262(t *testing.T) { tinyByteSink = nil tinyUint32Sink = nil tinyObj12Sink = nil + + runtime.Releasem() } func TestPageCacheLeak(t *testing.T) { -- GitLab From 1970e3e3b7b6c42676acc22071ced887ac68b520 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 24 Nov 2021 16:18:57 -0800 Subject: [PATCH 2344/2500] go/types: restore original assignment error messages This is the missing portion of the port of CL 351669 from types2 to go/types, now that we have a local flag to control for compiler error messages. Mostly a clean port but for adjustments to error reporting which requires error codes in go/types. Prerequisite for port of CL 364874. Change-Id: I5fc8c83003e4396351f42e9adb08f4ebc8a05653 Reviewed-on: https://go-review.googlesource.com/c/go/+/367195 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/go/types/assignments.go | 35 +++++++++++++++++++++++++++++++++-- src/go/types/expr.go | 6 +++++- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/go/types/assignments.go b/src/go/types/assignments.go index 7e6a230b48..8e9724e911 100644 --- a/src/go/types/assignments.go +++ b/src/go/types/assignments.go @@ -7,6 +7,7 @@ package types import ( + "fmt" "go/ast" "go/token" ) @@ -237,6 +238,28 @@ func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type { return x.typ } +func (check *Checker) assignError(rhs []ast.Expr, nvars, nvals int) { + measure := func(x int, unit string) string { + s := fmt.Sprintf("%d %s", x, unit) + if x != 1 { + s += "s" + } + return s + } + + vars := measure(nvars, "variable") + vals := measure(nvals, "value") + rhs0 := rhs[0] + + if len(rhs) == 1 { + if call, _ := unparen(rhs0).(*ast.CallExpr); call != nil { + check.errorf(rhs0, _WrongAssignCount, "assignment mismatch: %s but %s returns %s", vars, call.Fun, vals) + return + } + } + check.errorf(rhs0, _WrongAssignCount, "assignment mismatch: %s but %s", vars, vals) +} + // If returnPos is valid, initVars is called to type-check the assignment of // return expressions, and returnPos is the position of the return statement. func (check *Checker) initVars(lhs []*Var, origRHS []ast.Expr, returnPos token.Pos) { @@ -260,7 +283,11 @@ func (check *Checker) initVars(lhs []*Var, origRHS []ast.Expr, returnPos token.P check.errorf(atPos(returnPos), _WrongResultCount, "wrong number of return values (want %d, got %d)", len(lhs), len(rhs)) return } - check.errorf(rhs[0], _WrongAssignCount, "cannot initialize %d variables with %d values", len(lhs), len(rhs)) + if compilerErrorMessages { + check.assignError(origRHS, len(lhs), len(rhs)) + } else { + check.errorf(rhs[0], _WrongAssignCount, "cannot initialize %d variables with %d values", len(lhs), len(rhs)) + } return } @@ -294,7 +321,11 @@ func (check *Checker) assignVars(lhs, origRHS []ast.Expr) { return } } - check.errorf(rhs[0], _WrongAssignCount, "cannot assign %d values to %d variables", len(rhs), len(lhs)) + if compilerErrorMessages { + check.assignError(origRHS, len(lhs), len(rhs)) + } else { + check.errorf(rhs[0], _WrongAssignCount, "cannot assign %d values to %d variables", len(rhs), len(lhs)) + } return } diff --git a/src/go/types/expr.go b/src/go/types/expr.go index c49865aec6..dd18abaf13 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -1657,7 +1657,11 @@ func (check *Checker) singleValue(x *operand) { // tuple types are never named - no need for underlying type below if t, ok := x.typ.(*Tuple); ok { assert(t.Len() != 1) - check.errorf(x, _TooManyValues, "%d-valued %s where single value is expected", t.Len(), x) + if compilerErrorMessages { + check.errorf(x, _TooManyValues, "multiple-value %s in single-value context", x) + } else { + check.errorf(x, _TooManyValues, "%d-valued %s where single value is expected", t.Len(), x) + } x.mode = invalid } } -- GitLab From 2f6d3820501b34ce530be8193789659c18db0867 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 24 Nov 2021 16:48:00 -0800 Subject: [PATCH 2345/2500] go/types: report types for mismatched call and return statements This is a port of CL 364874 from types2 to go/types with various adjustments: - the error position for "not enough arguments" in calls is the closing ) rather than the position of the last provided argument - the ERROR comments in tests are positioned accordingly - the reg. expression for matching error strings accepts newlines for the . pattern (added s flag) For #48834. For #48835. Change-Id: I64362ecf605bcf9d89b8dc121432e0131bd5da1b Reviewed-on: https://go-review.googlesource.com/c/go/+/367196 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/go/types/assignments.go | 82 ++++++++++++++++++++++--- src/go/types/call.go | 25 ++++++-- src/go/types/check_test.go | 2 +- src/go/types/decl.go | 2 +- src/go/types/stmt.go | 2 +- src/go/types/testdata/check/errors.src | 28 +++++---- src/go/types/testdata/check/expr3.src | 12 ++-- src/go/types/testdata/check/stmt0.src | 14 ++--- src/go/types/testdata/check/vardecl.src | 2 +- 9 files changed, 126 insertions(+), 43 deletions(-) diff --git a/src/go/types/assignments.go b/src/go/types/assignments.go index 8e9724e911..a556e5e017 100644 --- a/src/go/types/assignments.go +++ b/src/go/types/assignments.go @@ -9,7 +9,7 @@ package types import ( "fmt" "go/ast" - "go/token" + "strings" ) // assignment reports whether x can be assigned to a variable of type T, @@ -238,6 +238,58 @@ func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type { return x.typ } +// operandTypes returns the list of types for the given operands. +func operandTypes(list []*operand) (res []Type) { + for _, x := range list { + res = append(res, x.typ) + } + return res +} + +// varTypes returns the list of types for the given variables. +func varTypes(list []*Var) (res []Type) { + for _, x := range list { + res = append(res, x.typ) + } + return res +} + +// typesSummary returns a string of the form "(t1, t2, ...)" where the +// ti's are user-friendly string representations for the given types. +// If variadic is set and the last type is a slice, its string is of +// the form "...E" where E is the slice's element type. +func (check *Checker) typesSummary(list []Type, variadic bool) string { + var res []string + for i, t := range list { + var s string + switch { + case t == nil: + fallthrough // should not happend but be cautious + case t == Typ[Invalid]: + s = "" + case isUntyped(t): + if isNumeric(t) { + // Do not imply a specific type requirement: + // "have number, want float64" is better than + // "have untyped int, want float64" or + // "have int, want float64". + s = "number" + } else { + // If we don't have a number, omit the "untyped" qualifier + // for compactness. + s = strings.Replace(t.(*Basic).name, "untyped ", "", -1) + } + case variadic && i == len(list)-1: + s = check.sprintf("...%s", t.(*Slice).elem) + } + if s == "" { + s = check.sprintf("%s", t) + } + res = append(res, s) + } + return "(" + strings.Join(res, ", ") + ")" +} + func (check *Checker) assignError(rhs []ast.Expr, nvars, nvals int) { measure := func(x int, unit string) string { s := fmt.Sprintf("%d %s", x, unit) @@ -260,10 +312,10 @@ func (check *Checker) assignError(rhs []ast.Expr, nvars, nvals int) { check.errorf(rhs0, _WrongAssignCount, "assignment mismatch: %s but %s", vars, vals) } -// If returnPos is valid, initVars is called to type-check the assignment of -// return expressions, and returnPos is the position of the return statement. -func (check *Checker) initVars(lhs []*Var, origRHS []ast.Expr, returnPos token.Pos) { - rhs, commaOk := check.exprList(origRHS, len(lhs) == 2 && !returnPos.IsValid()) +// If returnStmt != nil, initVars is called to type-check the assignment +// of return expressions, and returnStmt is the the return statement. +func (check *Checker) initVars(lhs []*Var, origRHS []ast.Expr, returnStmt ast.Stmt) { + rhs, commaOk := check.exprList(origRHS, len(lhs) == 2 && returnStmt == nil) if len(lhs) != len(rhs) { // invalidate lhs @@ -279,8 +331,20 @@ func (check *Checker) initVars(lhs []*Var, origRHS []ast.Expr, returnPos token.P return } } - if returnPos.IsValid() { - check.errorf(atPos(returnPos), _WrongResultCount, "wrong number of return values (want %d, got %d)", len(lhs), len(rhs)) + if returnStmt != nil { + var at positioner = returnStmt + qualifier := "not enough" + if len(rhs) > len(lhs) { + at = rhs[len(lhs)].expr // report at first extra value + qualifier = "too many" + } else if len(rhs) > 0 { + at = rhs[len(rhs)-1].expr // report at last value + } + check.errorf(at, _WrongResultCount, "%s return values\n\thave %s\n\twant %s", + qualifier, + check.typesSummary(operandTypes(rhs), false), + check.typesSummary(varTypes(lhs), false), + ) return } if compilerErrorMessages { @@ -292,7 +356,7 @@ func (check *Checker) initVars(lhs []*Var, origRHS []ast.Expr, returnPos token.P } context := "assignment" - if returnPos.IsValid() { + if returnStmt != nil { context = "return statement" } @@ -404,7 +468,7 @@ func (check *Checker) shortVarDecl(pos positioner, lhs, rhs []ast.Expr) { } } - check.initVars(lhsVars, rhs, token.NoPos) + check.initVars(lhsVars, rhs, nil) // process function literals in rhs expressions before scope changes check.processDelayed(top) diff --git a/src/go/types/call.go b/src/go/types/call.go index 940c0ff468..280ed05d1b 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -355,12 +355,25 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type } // check argument count - switch { - case nargs < npars: - check.errorf(inNode(call, call.Rparen), _WrongArgCount, "not enough arguments in call to %s", call.Fun) - return - case nargs > npars: - check.errorf(args[npars], _WrongArgCount, "too many arguments in call to %s", call.Fun) // report at first extra argument + if nargs != npars { + var at positioner = call + qualifier := "not enough" + if nargs > npars { + at = args[npars].expr // report at first extra argument + qualifier = "too many" + } else { + at = atPos(call.Rparen) // report at closing ) + } + // take care of empty parameter lists represented by nil tuples + var params []*Var + if sig.params != nil { + params = sig.params.vars + } + check.errorf(at, _WrongArgCount, "%s arguments in call to %s\n\thave %s\n\twant %s", + qualifier, call.Fun, + check.typesSummary(operandTypes(args), false), + check.typesSummary(varTypes(params), sig.variadic), + ) return } diff --git a/src/go/types/check_test.go b/src/go/types/check_test.go index a3be47e371..e296d13be9 100644 --- a/src/go/types/check_test.go +++ b/src/go/types/check_test.go @@ -51,7 +51,7 @@ var ( var fset = token.NewFileSet() // Positioned errors are of the form filename:line:column: message . -var posMsgRx = regexp.MustCompile(`^(.*:[0-9]+:[0-9]+): *(.*)`) +var posMsgRx = regexp.MustCompile(`^(.*:[0-9]+:[0-9]+): *(?s)(.*)`) // splitError splits an error's error message into a position string // and the actual error message. If there's no position information, diff --git a/src/go/types/decl.go b/src/go/types/decl.go index c85087018c..2c51329be9 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -602,7 +602,7 @@ func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init ast.Expr) { } } - check.initVars(lhs, []ast.Expr{init}, token.NoPos) + check.initVars(lhs, []ast.Expr{init}, nil) } // isImportedConstraint reports whether typ is an imported type constraint. diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index ee7d4e4cf1..06c9d3175d 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -519,7 +519,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { } } else { // return has results or result parameters are unnamed - check.initVars(res.vars, s.Results, s.Return) + check.initVars(res.vars, s.Results, s) } } else if len(s.Results) > 0 { check.error(s.Results[0], _WrongResultCount, "no result values expected") diff --git a/src/go/types/testdata/check/errors.src b/src/go/types/testdata/check/errors.src index ff929217c4..7cdc5fb5ff 100644 --- a/src/go/types/testdata/check/errors.src +++ b/src/go/types/testdata/check/errors.src @@ -8,32 +8,38 @@ package errors // (matching messages are regular expressions, hence the \'s). func f(x int, m map[string]int) { // no values - _ = f /* ERROR "f\(0, m\) \(no value\) used as value" */ (0, m) + _ = f /* ERROR f\(0, m\) \(no value\) used as value */ (0, m) // built-ins - _ = println /* ERROR "println \(built-in\) must be called" */ + _ = println // ERROR println \(built-in\) must be called // types - _ = complex128 /* ERROR "complex128 \(type\) is not an expression" */ + _ = complex128 // ERROR complex128 \(type\) is not an expression // constants const c1 = 991 const c2 float32 = 0.5 - 0 /* ERROR "0 \(untyped int constant\) is not used" */ - c1 /* ERROR "c1 \(untyped int constant 991\) is not used" */ - c2 /* ERROR "c2 \(constant 0.5 of type float32\) is not used" */ - c1 /* ERROR "c1 \+ c2 \(constant 991.5 of type float32\) is not used" */ + c2 + const c3 = "foo" + 0 // ERROR 0 \(untyped int constant\) is not used + 0.5 // ERROR 0.5 \(untyped float constant\) is not used + "foo" // ERROR "foo" \(untyped string constant\) is not used + c1 // ERROR c1 \(untyped int constant 991\) is not used + c2 // ERROR c2 \(constant 0.5 of type float32\) is not used + c1 /* ERROR c1 \+ c2 \(constant 991.5 of type float32\) is not used */ + c2 + c3 // ERROR c3 \(untyped string constant "foo"\) is not used // variables - x /* ERROR "x \(variable of type int\) is not used" */ + x // ERROR x \(variable of type int\) is not used // values - x /* ERROR "x != x \(untyped bool value\) is not used" */ != x - x /* ERROR "x \+ x \(value of type int\) is not used" */ + x + nil // ERROR nil is not used + ( /* ERROR \(\*int\)\(nil\) \(value of type \*int\) is not used */ *int)(nil) + x /* ERROR x != x \(untyped bool value\) is not used */ != x + x /* ERROR x \+ x \(value of type int\) is not used */ + x // value, ok's const s = "foo" - m /* ERROR "m\[s\] \(map index expression of type int\) is not used" */ [s] + m /* ERROR m\[s\] \(map index expression of type int\) is not used */ [s] } // Valid ERROR comments can have a variety of forms. diff --git a/src/go/types/testdata/check/expr3.src b/src/go/types/testdata/check/expr3.src index 5117a0373b..b8f96dc611 100644 --- a/src/go/types/testdata/check/expr3.src +++ b/src/go/types/testdata/check/expr3.src @@ -493,20 +493,20 @@ func _calls() { f1(0) f1(x) f1(10.0) - f1() /* ERROR "not enough arguments" */ - f1(x, y /* ERROR "too many arguments" */ ) + f1() /* ERROR "not enough arguments in call to f1\n\thave \(\)\n\twant \(int\)" */ + f1(x, y /* ERROR "too many arguments in call to f1\n\thave \(int, float32\)\n\twant \(int\)" */ ) f1(s /* ERROR "cannot use .* in argument" */ ) f1(x ... /* ERROR "cannot use ..." */ ) f1(g0 /* ERROR "used as value" */ ()) f1(g1()) - f1(g2 /* ERROR "too many arguments" */ ()) + f1(g2 /* ERROR "too many arguments in call to f1\n\thave \(float32, string\)\n\twant \(int\)" */ ()) - f2() /* ERROR "not enough arguments" */ - f2(3.14) /* ERROR "not enough arguments" */ + f2() /* ERROR "not enough arguments in call to f2\n\thave \(\)\n\twant \(float32, string\)" */ + f2(3.14) /* ERROR "not enough arguments in call to f2\n\thave \(number\)\n\twant \(float32, string\)" */ f2(3.14, "foo") f2(x /* ERROR "cannot use .* in argument" */ , "foo") f2(g0 /* ERROR "used as value" */ ()) - f2(g1()) /* ERROR "not enough arguments" */ + f2(g1()) /* ERROR "not enough arguments in call to f2\n\thave \(int\)\n\twant \(float32, string\)" */ f2(g2()) fs() /* ERROR "not enough arguments" */ diff --git a/src/go/types/testdata/check/stmt0.src b/src/go/types/testdata/check/stmt0.src index 2cce0b59b2..c7a718de70 100644 --- a/src/go/types/testdata/check/stmt0.src +++ b/src/go/types/testdata/check/stmt0.src @@ -29,10 +29,10 @@ func assignments0() (int, int) { a, b, c = <- /* ERROR "cannot assign [1-9]+ values to [1-9]+ variables" */ ch - return /* ERROR "wrong number of return values" */ - return /* ERROR "wrong number of return values" */ 1 + return /* ERROR "not enough return values\n\thave \(\)\n\twant \(int, int\)" */ + return 1 /* ERROR "not enough return values\n\thave \(number\)\n\twant \(int, int\)" */ return 1, 2 - return /* ERROR "wrong number of return values" */ 1, 2, 3 + return 1, 2, 3 /* ERROR "too many return values\n\thave \(number, number, number\)\n\twant \(int, int\)" */ } func assignments1() { @@ -81,7 +81,7 @@ func assignments1() { // test cases for issue 5500 _ = func() (int, bool) { var m map[int]int - return /* ERROR "wrong number of return values" */ m[0] + return m /* ERROR "not enough return values" */ [0] } g := func(int, bool){} @@ -380,15 +380,15 @@ func returns0() { func returns1(x float64) (int, *float64) { return 0, &x - return /* ERROR wrong number of return values */ + return /* ERROR not enough return values */ return "foo" /* ERROR "cannot .* in return statement" */, x /* ERROR "cannot use .* in return statement" */ - return /* ERROR wrong number of return values */ 0, &x, 1 + return 0, &x, 1 /* ERROR too many return values */ } func returns2() (a, b int) { return return 1, "foo" /* ERROR cannot use .* in return statement */ - return /* ERROR wrong number of return values */ 1, 2, 3 + return 1, 2, 3 /* ERROR too many return values */ { type a int return 1, 2 diff --git a/src/go/types/testdata/check/vardecl.src b/src/go/types/testdata/check/vardecl.src index 54f5ef1e10..787f7878f1 100644 --- a/src/go/types/testdata/check/vardecl.src +++ b/src/go/types/testdata/check/vardecl.src @@ -175,7 +175,7 @@ func _() { func _() int { var x, y int - return /* ERROR wrong number of return values */ x, y + return x, y /* ERROR too many return values */ } // Short variable declarations must declare at least one new non-blank variable. -- GitLab From 1ab677a797ab5cdb5c0248b2d63b753820e6ed49 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 26 Nov 2021 12:43:06 -0800 Subject: [PATCH 2346/2500] go/types: produce empty type set for invalid ~T This is a clean port of CL 366278 from types2 to go/types. For #49739. Change-Id: I2e2cb739c02fcc07e012499c7b65b13b057875ea Reviewed-on: https://go-review.googlesource.com/c/go/+/367197 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- .../types/testdata/fixedbugs/issue49739.go2 | 23 +++++++++++++++++++ src/go/types/typeset.go | 16 ++++++++----- 2 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue49739.go2 diff --git a/src/go/types/testdata/fixedbugs/issue49739.go2 b/src/go/types/testdata/fixedbugs/issue49739.go2 new file mode 100644 index 0000000000..46b1e71a3b --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue49739.go2 @@ -0,0 +1,23 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Verify that we get an empty type set (not just an error) +// when using an invalid ~A. + +package p + +type A int +type C interface { + ~ /* ERROR invalid use of ~ */ A +} + +func f[_ C]() {} +func g[_ interface{ C }]() {} +func h[_ C | int]() {} + +func _() { + _ = f[int /* ERROR cannot implement C \(empty type set\) */] + _ = g[int /* ERROR cannot implement interface{C} \(empty type set\) */] + _ = h[int] +} diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index d98080069c..2928368735 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -365,14 +365,18 @@ func computeUnionTypeSet(check *Checker, pos token.Pos, utyp *Union) *_TypeSet { var allTerms termlist for _, t := range utyp.terms { var terms termlist - switch u := under(t.typ).(type) { - case *Interface: + u := under(t.typ) + if ui, _ := u.(*Interface); ui != nil { // For now we don't permit type parameters as constraints. assert(!isTypeParam(t.typ)) - terms = computeInterfaceTypeSet(check, pos, u).terms - default: - if t.typ == Typ[Invalid] { - continue + terms = computeInterfaceTypeSet(check, pos, ui).terms + } else if t.typ == Typ[Invalid] { + continue + } else { + if t.tilde && !Identical(t.typ, u) { + // There is no underlying type which is t.typ. + // The corresponding type set is empty. + t = nil // ∅ term } terms = termlist{(*term)(t)} } -- GitLab From bc32dd1b69b0629a54cfe50626e42eb4b75eb017 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 26 Nov 2021 13:14:01 -0800 Subject: [PATCH 2347/2500] go/types: better error position for instantiation failure This is a port of CL 366757 from types2 to go/types, adjusted for the different handling of index expressions in go/types. For #49179. Change-Id: Ic859eb09683134d055e28c8e0cb1f3814a87dc5c Reviewed-on: https://go-review.googlesource.com/c/go/+/367198 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/go/types/builtins.go | 2 +- src/go/types/call.go | 39 ++++++++----------- src/go/types/mono.go | 7 ++-- src/go/types/testdata/check/issues.go2 | 2 +- .../types/testdata/fixedbugs/issue39754.go2 | 5 +-- .../types/testdata/fixedbugs/issue49179.go2 | 19 +++++++++ src/go/types/typexpr.go | 13 ++----- 7 files changed, 45 insertions(+), 42 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue49179.go2 diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index daeed81ed8..828220f257 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -130,7 +130,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b arg(&x, i) xlist = append(xlist, &x) } - check.arguments(call, sig, nil, xlist) // discard result (we know the result type) + check.arguments(call, sig, nil, xlist, nil) // discard result (we know the result type) // ok to continue even if check.arguments reported errors x.mode = value diff --git a/src/go/types/call.go b/src/go/types/call.go index 280ed05d1b..4156d56d9f 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -51,16 +51,8 @@ func (check *Checker) funcInst(x *operand, ix *typeparams.IndexExpr) { } assert(got == want) - // determine argument positions (for error reporting) - // TODO(rFindley) use a positioner here? instantiate would need to be - // updated accordingly. - poslist := make([]token.Pos, len(ix.Indices)) - for i, x := range ix.Indices { - poslist[i] = x.Pos() - } - // instantiate function signature - res := check.instantiateSignature(x.Pos(), sig, targs, poslist) + res := check.instantiateSignature(x.Pos(), sig, targs, ix.Indices) assert(res.TypeParams().Len() == 0) // signature is not generic anymore check.recordInstance(ix.Orig, targs, res) x.typ = res @@ -68,7 +60,7 @@ func (check *Checker) funcInst(x *operand, ix *typeparams.IndexExpr) { x.expr = ix.Orig } -func (check *Checker) instantiateSignature(pos token.Pos, typ *Signature, targs []Type, posList []token.Pos) (res *Signature) { +func (check *Checker) instantiateSignature(pos token.Pos, typ *Signature, targs []Type, xlist []ast.Expr) (res *Signature) { assert(check != nil) assert(len(targs) == typ.TypeParams().Len()) @@ -82,17 +74,17 @@ func (check *Checker) instantiateSignature(pos token.Pos, typ *Signature, targs } inst := check.instance(pos, typ, targs, check.bestContext(nil)).(*Signature) - assert(len(posList) <= len(targs)) + assert(len(xlist) <= len(targs)) tparams := typ.TypeParams().list() if i, err := check.verify(pos, tparams, targs); err != nil { // best position for error reporting pos := pos - if i < len(posList) { - pos = posList[i] + if i < len(xlist) { + pos = xlist[i].Pos() } - check.softErrorf(atPos(pos), _InvalidTypeArg, err.Error()) + check.softErrorf(atPos(pos), _InvalidTypeArg, "%s", err) } else { - check.mono.recordInstance(check.pkg, pos, tparams, targs, posList) + check.mono.recordInstance(check.pkg, pos, tparams, targs, xlist) } return inst @@ -184,21 +176,23 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { } // evaluate type arguments, if any + var xlist []ast.Expr var targs []Type if ix != nil { - targs = check.typeList(ix.Indices) + xlist = ix.Indices + targs = check.typeList(xlist) if targs == nil { check.use(call.Args...) x.mode = invalid x.expr = call return statement } - assert(len(targs) == len(ix.Indices)) + assert(len(targs) == len(xlist)) // check number of type arguments (got) vs number of type parameters (want) got, want := len(targs), sig.TypeParams().Len() if got > want { - check.errorf(ix.Indices[want], _WrongTypeArgCount, "got %d type arguments but want %d", got, want) + check.errorf(xlist[want], _WrongTypeArgCount, "got %d type arguments but want %d", got, want) check.use(call.Args...) x.mode = invalid x.expr = call @@ -209,7 +203,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { // evaluate arguments args, _ := check.exprList(call.Args, false) isGeneric := sig.TypeParams().Len() > 0 - sig = check.arguments(call, sig, targs, args) + sig = check.arguments(call, sig, targs, args, xlist) if isGeneric && sig.TypeParams().Len() == 0 { // Update the recorded type of call.Fun to its instantiated type. @@ -286,7 +280,8 @@ func (check *Checker) exprList(elist []ast.Expr, allowCommaOk bool) (xlist []*op return } -func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type, args []*operand) (rsig *Signature) { +// xlist is the list of type argument expressions supplied in the source code. +func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type, args []*operand, xlist []ast.Expr) (rsig *Signature) { rsig = sig // TODO(gri) try to eliminate this extra verification loop @@ -388,15 +383,13 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type check.softErrorf(inNode(call, call.Lparen), _UnsupportedFeature, "implicit function instantiation requires go1.18 or later") } } - // TODO(gri) provide position information for targs so we can feed - // it to the instantiate call for better error reporting targs := check.infer(call, sig.TypeParams().list(), targs, sigParams, args) if targs == nil { return // error already reported } // compute result signature - rsig = check.instantiateSignature(call.Pos(), sig, targs, nil) + rsig = check.instantiateSignature(call.Pos(), sig, targs, xlist) assert(rsig.TypeParams().Len() == 0) // signature is not generic anymore check.recordInstance(call.Fun, targs, rsig) diff --git a/src/go/types/mono.go b/src/go/types/mono.go index d4d884393b..84e1e971b6 100644 --- a/src/go/types/mono.go +++ b/src/go/types/mono.go @@ -5,6 +5,7 @@ package types import ( + "go/ast" "go/token" ) @@ -166,11 +167,11 @@ func (w *monoGraph) recordCanon(mpar, tpar *TypeParam) { // recordInstance records that the given type parameters were // instantiated with the corresponding type arguments. -func (w *monoGraph) recordInstance(pkg *Package, pos token.Pos, tparams []*TypeParam, targs []Type, posList []token.Pos) { +func (w *monoGraph) recordInstance(pkg *Package, pos token.Pos, tparams []*TypeParam, targs []Type, xlist []ast.Expr) { for i, tpar := range tparams { pos := pos - if i < len(posList) { - pos = posList[i] + if i < len(xlist) { + pos = xlist[i].Pos() } w.assign(pkg, pos, tpar, targs[i]) } diff --git a/src/go/types/testdata/check/issues.go2 b/src/go/types/testdata/check/issues.go2 index fdb49d55f2..ac8ef789e5 100644 --- a/src/go/types/testdata/check/issues.go2 +++ b/src/go/types/testdata/check/issues.go2 @@ -48,7 +48,7 @@ func (*T) m2() func _() { // TODO(rFindley) this error should be positioned on the 'T'. - f2 /* ERROR wrong method signature */ [T]() + f2[T /* ERROR wrong method signature */ ]() f2[*T]() } diff --git a/src/go/types/testdata/fixedbugs/issue39754.go2 b/src/go/types/testdata/fixedbugs/issue39754.go2 index cecbc88043..9edd239d7d 100644 --- a/src/go/types/testdata/fixedbugs/issue39754.go2 +++ b/src/go/types/testdata/fixedbugs/issue39754.go2 @@ -17,8 +17,5 @@ func f[V interface{}, A, B Box[V]]() {} func _() { f[int, Optional[int], Optional[int]]() _ = f[int, Optional[int], Optional /* ERROR does not implement Box */ [string]] - // TODO(gri) Provide better position information here. - // See TODO in call.go, Checker.arguments. - // TODO(rFindley) Reconcile this error position with types2. - f /* ERROR does not implement Box */ [int, Optional[int], Optional[string]]() + _ = f[int, Optional[int], Optional /* ERROR Optional.* does not implement Box.* */ [string]] } diff --git a/src/go/types/testdata/fixedbugs/issue49179.go2 b/src/go/types/testdata/fixedbugs/issue49179.go2 new file mode 100644 index 0000000000..7cba52aa25 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue49179.go2 @@ -0,0 +1,19 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type SliceConstraint[T any] interface { + []T +} + +func Map[S SliceConstraint[E], E any](s S, f func(E) E) S { + return s +} + +type MySlice []int + +func f(s MySlice) { + Map[MySlice /* ERROR MySlice does not implement SliceConstraint\[int\] */, int](s, nil) +} diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 5664d8175f..0a74a875bc 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -11,7 +11,6 @@ import ( "go/ast" "go/constant" "go/internal/typeparams" - "go/token" "strings" ) @@ -416,12 +415,6 @@ func (check *Checker) instantiatedType(ix *typeparams.IndexExpr, def *Named) (re return Typ[Invalid] } - // determine argument positions - posList := make([]token.Pos, len(targs)) - for i, arg := range ix.Indices { - posList[i] = arg.Pos() - } - // create the instance ctxt := check.bestContext(nil) h := ctxt.instanceHash(orig, targs) @@ -470,12 +463,12 @@ func (check *Checker) instantiatedType(ix *typeparams.IndexExpr, def *Named) (re if i, err := check.verify(pos, inst.tparams.list(), inst.targs.list()); err != nil { // best position for error reporting pos := ix.Pos() - if i < len(posList) { - pos = posList[i] + if i < len(ix.Indices) { + pos = ix.Indices[i].Pos() } check.softErrorf(atPos(pos), _InvalidTypeArg, err.Error()) } else { - check.mono.recordInstance(check.pkg, pos, inst.tparams.list(), inst.targs.list(), posList) + check.mono.recordInstance(check.pkg, pos, inst.tparams.list(), inst.targs.list(), ix.Indices) } } -- GitLab From ebd0b778c92c4dfc71195ef83d71116957e173ad Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 26 Nov 2021 13:27:12 -0800 Subject: [PATCH 2348/2500] go/types: better error message for missing ~ in constraint This is a port of CL 366758 from types2 to go/types. For #49179. Change-Id: I7e1c6ffb392d5c535cf901004b7acbe8c3be9b0f Reviewed-on: https://go-review.googlesource.com/c/go/+/367199 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/go/types/instantiate.go | 25 ++++++++++++++++--- .../types/testdata/fixedbugs/issue49179.go2 | 20 ++++++++++++++- src/go/types/typeset.go | 2 ++ 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 011fb8e540..597a6da624 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -239,9 +239,28 @@ func (check *Checker) implements(V, T Type, qf Qualifier) error { } // Otherwise, V's type must be included in the iface type set. - if !Ti.typeSet().includes(V) { - // TODO(gri) report which type is missing - return errorf("%s does not implement %s", V, T) + var alt Type + if Ti.typeSet().is(func(t *term) bool { + if !t.includes(V) { + // If V ∉ t.typ but V ∈ ~t.typ then remember this type + // so we can suggest it as an alternative in the error + // message. + if alt == nil && !t.tilde && Identical(t.typ, under(t.typ)) { + tt := *t + tt.tilde = true + if tt.includes(V) { + alt = t.typ + } + } + return true + } + return false + }) { + if alt != nil { + return errorf("%s does not implement %s (possibly missing ~ for %s in constraint %s)", V, T, alt, T) + } else { + return errorf("%s does not implement %s", V, T) + } } return nil diff --git a/src/go/types/testdata/fixedbugs/issue49179.go2 b/src/go/types/testdata/fixedbugs/issue49179.go2 index 7cba52aa25..d4c8a897c6 100644 --- a/src/go/types/testdata/fixedbugs/issue49179.go2 +++ b/src/go/types/testdata/fixedbugs/issue49179.go2 @@ -4,6 +4,24 @@ package p +func f1[P int | string]() {} +func f2[P ~int | string | float64]() {} +func f3[P int](x P) {} + +type myInt int +type myFloat float64 + +func _() { + _ = f1[int] + _ = f1[myInt /* ERROR possibly missing ~ for int in constraint int\|string */] + _ = f2[myInt] + _ = f2[myFloat /* ERROR possibly missing ~ for float64 in constraint int\|string|float64 */] + var x myInt + f3 /* ERROR myInt does not implement int \(possibly missing ~ for int in constraint int\) */ (x) +} + +// test case from the issue + type SliceConstraint[T any] interface { []T } @@ -15,5 +33,5 @@ func Map[S SliceConstraint[E], E any](s S, f func(E) E) S { type MySlice []int func f(s MySlice) { - Map[MySlice /* ERROR MySlice does not implement SliceConstraint\[int\] */, int](s, nil) + Map[MySlice /* ERROR MySlice does not implement SliceConstraint\[int\] \(possibly missing ~ for \[\]int in constraint SliceConstraint\[int\]\) */, int](s, nil) } diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index 2928368735..d39483f254 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -106,6 +106,8 @@ func (s *_TypeSet) hasTerms() bool { return !s.terms.isEmpty() && !s.terms.isAll func (s *_TypeSet) singleType() Type { return s.terms.singleType() } // includes reports whether t ∈ s. +// TODO(gri) This function is not used anywhere anymore. Remove once we +// are clear that we don't need it elsewhere in the future. func (s *_TypeSet) includes(t Type) bool { return s.terms.includes(t) } // subsetOf reports whether s1 ⊆ s2. -- GitLab From c402d64f37f819b0f2d9949c6895e342191d11d6 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 29 Nov 2021 12:21:46 -0500 Subject: [PATCH 2349/2500] go/types: consider structural restrictions in Implements Fixes #49786 Change-Id: I4559d013399deda48bcb97aef3427ecf87a3ef26 Reviewed-on: https://go-review.googlesource.com/c/go/+/367515 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/api.go | 12 ++- src/cmd/compile/internal/types2/api_test.go | 103 +++++++++++++++++++ src/go/types/api.go | 12 ++- src/go/types/api_test.go | 104 ++++++++++++++++++++ 4 files changed, 227 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/types2/api.go b/src/cmd/compile/internal/types2/api.go index 367cb8f700..4ea3989c39 100644 --- a/src/cmd/compile/internal/types2/api.go +++ b/src/cmd/compile/internal/types2/api.go @@ -440,8 +440,16 @@ func ConvertibleTo(V, T Type) bool { // Implements reports whether type V implements interface T. func Implements(V Type, T *Interface) bool { - f, _ := MissingMethod(V, T, true) - return f == nil + if T.Empty() { + // All types (even Typ[Invalid]) implement the empty interface. + return true + } + // Checker.implements suppresses errors for invalid types, so we need special + // handling here. + if V.Underlying() == Typ[Invalid] { + return false + } + return (*Checker)(nil).implements(V, T, nil) == nil } // Identical reports whether x and y are identical types. diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index 9436a4ed97..4227397df9 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -2102,3 +2102,106 @@ func TestInstanceIdentity(t *testing.T) { t.Errorf("mismatching types: a.A: %s, b.B: %s", a.Type(), b.Type()) } } + +func TestImplements(t *testing.T) { + const src = ` +package p + +type EmptyIface interface{} + +type I interface { + m() +} + +type C interface { + m() + ~int +} + +type Integer interface{ + int8 | int16 | int32 | int64 +} + +type EmptyTypeSet interface{ + Integer + ~string +} + +type N1 int +func (N1) m() {} + +type N2 int +func (*N2) m() {} + +type N3 int +func (N3) m(int) {} + +type N4 string +func (N4) m() + +type Bad Bad // invalid type +` + + f, err := parseSrc("p.go", src) + if err != nil { + t.Fatal(err) + } + conf := Config{Error: func(error) {}} + pkg, _ := conf.Check(f.PkgName.Value, []*syntax.File{f}, nil) + + scope := pkg.Scope() + var ( + EmptyIface = scope.Lookup("EmptyIface").Type().Underlying().(*Interface) + I = scope.Lookup("I").Type().(*Named) + II = I.Underlying().(*Interface) + C = scope.Lookup("C").Type().(*Named) + CI = C.Underlying().(*Interface) + Integer = scope.Lookup("Integer").Type().Underlying().(*Interface) + EmptyTypeSet = scope.Lookup("EmptyTypeSet").Type().Underlying().(*Interface) + N1 = scope.Lookup("N1").Type() + N1p = NewPointer(N1) + N2 = scope.Lookup("N2").Type() + N2p = NewPointer(N2) + N3 = scope.Lookup("N3").Type() + N4 = scope.Lookup("N4").Type() + Bad = scope.Lookup("Bad").Type() + ) + + tests := []struct { + t Type + i *Interface + want bool + }{ + {I, II, true}, + {I, CI, false}, + {C, II, true}, + {C, CI, true}, + {Typ[Int8], Integer, true}, + {Typ[Int64], Integer, true}, + {Typ[String], Integer, false}, + {EmptyTypeSet, II, true}, + {EmptyTypeSet, EmptyTypeSet, true}, + {Typ[Int], EmptyTypeSet, false}, + {N1, II, true}, + {N1, CI, true}, + {N1p, II, true}, + {N1p, CI, false}, + {N2, II, false}, + {N2, CI, false}, + {N2p, II, true}, + {N2p, CI, false}, + {N3, II, false}, + {N3, CI, false}, + {N4, II, true}, + {N4, CI, false}, + {Bad, II, false}, + {Bad, CI, false}, + {Bad, EmptyIface, true}, + } + + for _, test := range tests { + if got := Implements(test.t, test.i); got != test.want { + t.Errorf("Implements(%s, %s) = %t, want %t", test.t, test.i, got, test.want) + } + } +} diff --git a/src/go/types/api.go b/src/go/types/api.go index c115d07b41..51d58c49aa 100644 --- a/src/go/types/api.go +++ b/src/go/types/api.go @@ -436,8 +436,16 @@ func ConvertibleTo(V, T Type) bool { // Implements reports whether type V implements interface T. func Implements(V Type, T *Interface) bool { - f, _ := MissingMethod(V, T, true) - return f == nil + if T.Empty() { + // All types (even Typ[Invalid]) implement the empty interface. + return true + } + // Checker.implements suppresses errors for invalid types, so we need special + // handling here. + if V.Underlying() == Typ[Invalid] { + return false + } + return (*Checker)(nil).implements(V, T, nil) == nil } // Identical reports whether x and y are identical types. diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index c8fda5521a..7b7baa7604 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -2093,3 +2093,107 @@ func TestInstanceIdentity(t *testing.T) { t.Errorf("mismatching types: a.A: %s, b.B: %s", a.Type(), b.Type()) } } + +func TestImplements(t *testing.T) { + const src = ` +package p + +type EmptyIface interface{} + +type I interface { + m() +} + +type C interface { + m() + ~int +} + +type Integer interface{ + int8 | int16 | int32 | int64 +} + +type EmptyTypeSet interface{ + Integer + ~string +} + +type N1 int +func (N1) m() {} + +type N2 int +func (*N2) m() {} + +type N3 int +func (N3) m(int) {} + +type N4 string +func (N4) m() + +type Bad Bad // invalid type +` + + fset := token.NewFileSet() + f, err := parser.ParseFile(fset, "p.go", src, 0) + if err != nil { + t.Fatal(err) + } + conf := Config{Error: func(error) {}} + pkg, _ := conf.Check(f.Name.Name, fset, []*ast.File{f}, nil) + + scope := pkg.Scope() + var ( + EmptyIface = scope.Lookup("EmptyIface").Type().Underlying().(*Interface) + I = scope.Lookup("I").Type().(*Named) + II = I.Underlying().(*Interface) + C = scope.Lookup("C").Type().(*Named) + CI = C.Underlying().(*Interface) + Integer = scope.Lookup("Integer").Type().Underlying().(*Interface) + EmptyTypeSet = scope.Lookup("EmptyTypeSet").Type().Underlying().(*Interface) + N1 = scope.Lookup("N1").Type() + N1p = NewPointer(N1) + N2 = scope.Lookup("N2").Type() + N2p = NewPointer(N2) + N3 = scope.Lookup("N3").Type() + N4 = scope.Lookup("N4").Type() + Bad = scope.Lookup("Bad").Type() + ) + + tests := []struct { + t Type + i *Interface + want bool + }{ + {I, II, true}, + {I, CI, false}, + {C, II, true}, + {C, CI, true}, + {Typ[Int8], Integer, true}, + {Typ[Int64], Integer, true}, + {Typ[String], Integer, false}, + {EmptyTypeSet, II, true}, + {EmptyTypeSet, EmptyTypeSet, true}, + {Typ[Int], EmptyTypeSet, false}, + {N1, II, true}, + {N1, CI, true}, + {N1p, II, true}, + {N1p, CI, false}, + {N2, II, false}, + {N2, CI, false}, + {N2p, II, true}, + {N2p, CI, false}, + {N3, II, false}, + {N3, CI, false}, + {N4, II, true}, + {N4, CI, false}, + {Bad, II, false}, + {Bad, CI, false}, + {Bad, EmptyIface, true}, + } + + for _, test := range tests { + if got := Implements(test.t, test.i); got != test.want { + t.Errorf("Implements(%s, %s) = %t, want %t", test.t, test.i, got, test.want) + } + } +} -- GitLab From 186f375ecfdd0f9eae109464a93bb0ba8c993f45 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 29 Nov 2021 14:52:54 -0500 Subject: [PATCH 2350/2500] go/types: ensure that constructed type parameters are immutable TypeParam.iface may mutate TypeParam.bound in the event that the type parameter bound is not an interface. Ensure that iface() is called before the type-checking pass returns, and before NewTypeParam or TypeParam.SetConstraint exits. Fixes #49788 Change-Id: I72279acf5f0223161671c04887bc2c3df4158927 Reviewed-on: https://go-review.googlesource.com/c/go/+/367614 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/typeparam.go | 17 ++++++++++++++++- src/go/types/typeparam.go | 18 ++++++++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index 8dd04ff408..e32063a0af 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -21,7 +21,7 @@ type TypeParam struct { id uint64 // unique id, for debugging only obj *TypeName // corresponding type name index int // type parameter index in source order, starting at 0 - bound Type // any type, but eventually an *Interface for correct programs (see TypeParam.iface) + bound Type // any type, but underlying is eventually *Interface for correct programs (see TypeParam.iface) } // Obj returns the type name for the type parameter t. @@ -47,6 +47,15 @@ func (check *Checker) newTypeParam(obj *TypeName, constraint Type) *TypeParam { if obj.typ == nil { obj.typ = typ } + // iface may mutate typ.bound, so we must ensure that iface() is called + // at least once before the resulting TypeParam escapes. + if check != nil { + check.later(func() { + typ.iface() + }) + } else if constraint != nil { + typ.iface() + } return typ } @@ -62,11 +71,17 @@ func (t *TypeParam) Constraint() Type { } // SetConstraint sets the type constraint for t. +// +// SetConstraint should not be called concurrently, but once SetConstraint +// returns the receiver t is safe for concurrent use. func (t *TypeParam) SetConstraint(bound Type) { if bound == nil { panic("nil constraint") } t.bound = bound + // iface may mutate t.bound (if bound is not an interface), so ensure that + // this is done before returning. + t.iface() } func (t *TypeParam) Underlying() Type { diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index 7cce1f7e35..03ba9be55c 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -24,7 +24,7 @@ type TypeParam struct { id uint64 // unique id, for debugging only obj *TypeName // corresponding type name index int // type parameter index in source order, starting at 0 - bound Type // any type, but eventually an *Interface for correct programs (see TypeParam.iface) + bound Type // any type, but underlying is eventually *Interface for correct programs (see TypeParam.iface) } // NewTypeParam returns a new TypeParam. Type parameters may be set on a Named @@ -47,6 +47,15 @@ func (check *Checker) newTypeParam(obj *TypeName, constraint Type) *TypeParam { if obj.typ == nil { obj.typ = typ } + // iface may mutate typ.bound, so we must ensure that iface() is called + // at least once before the resulting TypeParam escapes. + if check != nil { + check.later(func() { + typ.iface() + }) + } else if constraint != nil { + typ.iface() + } return typ } @@ -65,11 +74,17 @@ func (t *TypeParam) Constraint() Type { } // SetConstraint sets the type constraint for t. +// +// SetConstraint should not be called concurrently, but once SetConstraint +// returns the receiver t is safe for concurrent use. func (t *TypeParam) SetConstraint(bound Type) { if bound == nil { panic("nil constraint") } t.bound = bound + // iface may mutate t.bound (if bound is not an interface), so ensure that + // this is done before returning. + t.iface() } func (t *TypeParam) Underlying() Type { @@ -104,7 +119,6 @@ func (t *TypeParam) iface() *Interface { } // If we don't have an interface, wrap constraint into an implicit interface. - // TODO(gri) mark it as implicit - see comment in Checker.bound if ityp == nil { ityp = NewInterfaceType(nil, []Type{bound}) ityp.implicit = true -- GitLab From 3ca57c7fb8bfc9b8b633f71a7aaa9de5fe76f63d Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 29 Nov 2021 17:39:19 -0500 Subject: [PATCH 2351/2500] go/types, types2: handle case of no specific target types in conversion Avoid a panic by handling the case of no specific target type in a type parameter to type parameter conversions. Fixes #49864 Change-Id: I117dd80cc9d47c8c1e168f1caf0f281726270c84 Reviewed-on: https://go-review.googlesource.com/c/go/+/367616 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Go Bot --- src/cmd/compile/internal/types2/conversions.go | 3 +++ .../internal/types2/testdata/fixedbugs/issue49864.go2 | 9 +++++++++ src/go/types/conversions.go | 3 +++ src/go/types/testdata/fixedbugs/issue49864.go2 | 9 +++++++++ 4 files changed, 24 insertions(+) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue49864.go2 create mode 100644 src/go/types/testdata/fixedbugs/issue49864.go2 diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go index 47f9ac0a5a..253868cf93 100644 --- a/src/cmd/compile/internal/types2/conversions.go +++ b/src/cmd/compile/internal/types2/conversions.go @@ -233,6 +233,9 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { } x.typ = V.typ return Tp.is(func(T *term) bool { + if T == nil { + return false // no specific types + } if !x.convertibleTo(check, T.typ, cause) { errorf("cannot convert %s (in %s) to %s (in %s)", V.typ, Vp, T.typ, Tp) return false diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49864.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49864.go2 new file mode 100644 index 0000000000..0437e74a64 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49864.go2 @@ -0,0 +1,9 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func _[P ~int, Q any](p P) { + _ = Q(p /* ERROR cannot convert */ ) +} diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go index 5995d5920f..fb3771635d 100644 --- a/src/go/types/conversions.go +++ b/src/go/types/conversions.go @@ -224,6 +224,9 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { } x.typ = V.typ return Tp.is(func(T *term) bool { + if T == nil { + return false // no specific types + } if !x.convertibleTo(check, T.typ, cause) { errorf("cannot convert %s (in %s) to %s (in %s)", V.typ, Vp, T.typ, Tp) return false diff --git a/src/go/types/testdata/fixedbugs/issue49864.go2 b/src/go/types/testdata/fixedbugs/issue49864.go2 new file mode 100644 index 0000000000..0437e74a64 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue49864.go2 @@ -0,0 +1,9 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func _[P ~int, Q any](p P) { + _ = Q(p /* ERROR cannot convert */ ) +} -- GitLab From f90a42b41080cf5a289f151f2166d0d0a795e836 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 29 Nov 2021 12:04:42 -0800 Subject: [PATCH 2352/2500] cmd/compile: change iexportVersionGeneric to 2 Don't expect/allow generics-related info in iexportVersion 1, now that we increased the export version to 2. Fixes #49853 Change-Id: I9bacee7f8e7cb9bb3b02a00084fad77edd220121 Reviewed-on: https://go-review.googlesource.com/c/go/+/367634 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Robert Findley Reviewed-by: Heschi Kreinick --- src/cmd/compile/internal/importer/iimport.go | 2 +- src/cmd/compile/internal/typecheck/iexport.go | 2 +- src/go/internal/gcimporter/iimport.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index 1aa3b7b6a8..23d6ca350e 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -45,7 +45,7 @@ func (r *intReader) uint64() uint64 { const ( iexportVersionGo1_11 = 0 iexportVersionPosCol = 1 - iexportVersionGenerics = 1 // probably change to 2 before release + iexportVersionGenerics = 2 iexportVersionGo1_18 = 2 iexportVersionCurrent = 2 diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go index 9bd1f626fe..7ebabe7314 100644 --- a/src/cmd/compile/internal/typecheck/iexport.go +++ b/src/cmd/compile/internal/typecheck/iexport.go @@ -261,7 +261,7 @@ import ( const ( iexportVersionGo1_11 = 0 iexportVersionPosCol = 1 - iexportVersionGenerics = 1 // probably change to 2 before release + iexportVersionGenerics = 2 iexportVersionGo1_18 = 2 iexportVersionCurrent = 2 diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go index 49ea64392a..d7fc3ee7a9 100644 --- a/src/go/internal/gcimporter/iimport.go +++ b/src/go/internal/gcimporter/iimport.go @@ -46,7 +46,7 @@ func (r *intReader) uint64() uint64 { const ( iexportVersionGo1_11 = 0 iexportVersionPosCol = 1 - iexportVersionGenerics = 1 // probably change to 2 before release + iexportVersionGenerics = 2 iexportVersionGo1_18 = 2 iexportVersionCurrent = 2 -- GitLab From f463b20789c89f0d22e56663a34e57a942f945cf Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Mon, 29 Nov 2021 15:07:04 -0500 Subject: [PATCH 2353/2500] runtime: keep //go:cgo_unsafe_args arguments alive to prevent GC When syscall's DLL.FindProc calls into syscall_getprocaddress with a byte slice pointer, we need to keep those bytes alive. Otherwise the GC will collect the allocation, and we wind up calling `GetProcAddress` on garbage, which showed up as various flakes in the builders. It turns out that this problem extends to many uses of //go:cgo_unsafe_args throughout, on all platforms. So this patch fixes the issue by keeping non-integer pointer arguments alive through their invocation in //go:cgo_unsafe_args functions. Fixes #49731. Change-Id: I93e4fbc2e8e210cb3fc53149708758bb33f2f9c7 Reviewed-on: https://go-review.googlesource.com/c/go/+/367654 Trust: Jason A. Donenfeld Run-TryBot: Jason A. Donenfeld Reviewed-by: Matthew Dempsky Reviewed-by: Ian Lance Taylor Reviewed-by: Patrik Nyblom TryBot-Result: Go Bot --- src/runtime/sys_darwin.go | 94 +++++++++++++++++++++++++++------ src/runtime/sys_darwin_arm64.go | 4 +- src/runtime/sys_openbsd.go | 22 ++++++-- src/runtime/sys_openbsd1.go | 5 +- src/runtime/sys_openbsd2.go | 36 +++++++++++-- src/runtime/syscall_solaris.go | 2 + src/runtime/syscall_windows.go | 4 ++ 7 files changed, 138 insertions(+), 29 deletions(-) diff --git a/src/runtime/sys_darwin.go b/src/runtime/sys_darwin.go index 9af4cf18f8..80dd1a0378 100644 --- a/src/runtime/sys_darwin.go +++ b/src/runtime/sys_darwin.go @@ -105,28 +105,38 @@ func syscallNoErr() //go:nosplit //go:cgo_unsafe_args func pthread_attr_init(attr *pthreadattr) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_attr_init_trampoline)), unsafe.Pointer(&attr)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_attr_init_trampoline)), unsafe.Pointer(&attr)) + KeepAlive(attr) + return ret } func pthread_attr_init_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_attr_getstacksize(attr *pthreadattr, size *uintptr) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_attr_getstacksize_trampoline)), unsafe.Pointer(&attr)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_attr_getstacksize_trampoline)), unsafe.Pointer(&attr)) + KeepAlive(attr) + KeepAlive(size) + return ret } func pthread_attr_getstacksize_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_attr_setdetachstate(attr *pthreadattr, state int) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_attr_setdetachstate_trampoline)), unsafe.Pointer(&attr)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_attr_setdetachstate_trampoline)), unsafe.Pointer(&attr)) + KeepAlive(attr) + return ret } func pthread_attr_setdetachstate_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_create(attr *pthreadattr, start uintptr, arg unsafe.Pointer) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_create_trampoline)), unsafe.Pointer(&attr)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_create_trampoline)), unsafe.Pointer(&attr)) + KeepAlive(attr) + KeepAlive(arg) // Just for consistency. Arg of course needs to be kept alive for the start function. + return ret } func pthread_create_trampoline() @@ -175,6 +185,7 @@ func mmap_trampoline() //go:cgo_unsafe_args func munmap(addr unsafe.Pointer, n uintptr) { libcCall(unsafe.Pointer(abi.FuncPCABI0(munmap_trampoline)), unsafe.Pointer(&addr)) + KeepAlive(addr) // Just for consistency. Hopefully addr is not a Go address. } func munmap_trampoline() @@ -182,6 +193,7 @@ func munmap_trampoline() //go:cgo_unsafe_args func madvise(addr unsafe.Pointer, n uintptr, flags int32) { libcCall(unsafe.Pointer(abi.FuncPCABI0(madvise_trampoline)), unsafe.Pointer(&addr)) + KeepAlive(addr) // Just for consistency. Hopefully addr is not a Go address. } func madvise_trampoline() @@ -189,13 +201,16 @@ func madvise_trampoline() //go:cgo_unsafe_args func mlock(addr unsafe.Pointer, n uintptr) { libcCall(unsafe.Pointer(abi.FuncPCABI0(mlock_trampoline)), unsafe.Pointer(&addr)) + KeepAlive(addr) // Just for consistency. Hopefully addr is not a Go address. } func mlock_trampoline() //go:nosplit //go:cgo_unsafe_args func read(fd int32, p unsafe.Pointer, n int32) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(read_trampoline)), unsafe.Pointer(&fd)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(read_trampoline)), unsafe.Pointer(&fd)) + KeepAlive(p) + return ret } func read_trampoline() @@ -239,14 +254,18 @@ func usleep_no_g(usec uint32) { //go:nosplit //go:cgo_unsafe_args func write1(fd uintptr, p unsafe.Pointer, n int32) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(write_trampoline)), unsafe.Pointer(&fd)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(write_trampoline)), unsafe.Pointer(&fd)) + KeepAlive(p) + return ret } func write_trampoline() //go:nosplit //go:cgo_unsafe_args func open(name *byte, mode, perm int32) (ret int32) { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(open_trampoline)), unsafe.Pointer(&name)) + ret = libcCall(unsafe.Pointer(abi.FuncPCABI0(open_trampoline)), unsafe.Pointer(&name)) + KeepAlive(name) + return } func open_trampoline() @@ -285,6 +304,8 @@ func walltime_trampoline() //go:cgo_unsafe_args func sigaction(sig uint32, new *usigactiont, old *usigactiont) { libcCall(unsafe.Pointer(abi.FuncPCABI0(sigaction_trampoline)), unsafe.Pointer(&sig)) + KeepAlive(new) + KeepAlive(old) } func sigaction_trampoline() @@ -292,6 +313,8 @@ func sigaction_trampoline() //go:cgo_unsafe_args func sigprocmask(how uint32, new *sigset, old *sigset) { libcCall(unsafe.Pointer(abi.FuncPCABI0(sigprocmask_trampoline)), unsafe.Pointer(&how)) + KeepAlive(new) + KeepAlive(old) } func sigprocmask_trampoline() @@ -306,6 +329,8 @@ func sigaltstack(new *stackt, old *stackt) { new.ss_size = 32768 } libcCall(unsafe.Pointer(abi.FuncPCABI0(sigaltstack_trampoline)), unsafe.Pointer(&new)) + KeepAlive(new) + KeepAlive(old) } func sigaltstack_trampoline() @@ -320,20 +345,32 @@ func raiseproc_trampoline() //go:cgo_unsafe_args func setitimer(mode int32, new, old *itimerval) { libcCall(unsafe.Pointer(abi.FuncPCABI0(setitimer_trampoline)), unsafe.Pointer(&mode)) + KeepAlive(new) + KeepAlive(old) } func setitimer_trampoline() //go:nosplit //go:cgo_unsafe_args func sysctl(mib *uint32, miblen uint32, oldp *byte, oldlenp *uintptr, newp *byte, newlen uintptr) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(sysctl_trampoline)), unsafe.Pointer(&mib)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(sysctl_trampoline)), unsafe.Pointer(&mib)) + KeepAlive(mib) + KeepAlive(oldp) + KeepAlive(oldlenp) + KeepAlive(newp) + return ret } func sysctl_trampoline() //go:nosplit //go:cgo_unsafe_args func sysctlbyname(name *byte, oldp *byte, oldlenp *uintptr, newp *byte, newlen uintptr) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(sysctlbyname_trampoline)), unsafe.Pointer(&name)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(sysctlbyname_trampoline)), unsafe.Pointer(&name)) + KeepAlive(name) + KeepAlive(oldp) + KeepAlive(oldlenp) + KeepAlive(newp) + return ret } func sysctlbyname_trampoline() @@ -355,56 +392,79 @@ func kqueue_trampoline() //go:nosplit //go:cgo_unsafe_args func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(kevent_trampoline)), unsafe.Pointer(&kq)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(kevent_trampoline)), unsafe.Pointer(&kq)) + KeepAlive(ch) + KeepAlive(ev) + KeepAlive(ts) + return ret } func kevent_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_mutex_init(m *pthreadmutex, attr *pthreadmutexattr) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_mutex_init_trampoline)), unsafe.Pointer(&m)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_mutex_init_trampoline)), unsafe.Pointer(&m)) + KeepAlive(m) + KeepAlive(attr) + return ret } func pthread_mutex_init_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_mutex_lock(m *pthreadmutex) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_mutex_lock_trampoline)), unsafe.Pointer(&m)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_mutex_lock_trampoline)), unsafe.Pointer(&m)) + KeepAlive(m) + return ret } func pthread_mutex_lock_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_mutex_unlock(m *pthreadmutex) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_mutex_unlock_trampoline)), unsafe.Pointer(&m)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_mutex_unlock_trampoline)), unsafe.Pointer(&m)) + KeepAlive(m) + return ret } func pthread_mutex_unlock_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_cond_init(c *pthreadcond, attr *pthreadcondattr) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_cond_init_trampoline)), unsafe.Pointer(&c)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_cond_init_trampoline)), unsafe.Pointer(&c)) + KeepAlive(c) + KeepAlive(attr) + return ret } func pthread_cond_init_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_cond_wait(c *pthreadcond, m *pthreadmutex) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_cond_wait_trampoline)), unsafe.Pointer(&c)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_cond_wait_trampoline)), unsafe.Pointer(&c)) + KeepAlive(c) + KeepAlive(m) + return ret } func pthread_cond_wait_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_cond_timedwait_relative_np(c *pthreadcond, m *pthreadmutex, t *timespec) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_cond_timedwait_relative_np_trampoline)), unsafe.Pointer(&c)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_cond_timedwait_relative_np_trampoline)), unsafe.Pointer(&c)) + KeepAlive(c) + KeepAlive(m) + KeepAlive(t) + return ret } func pthread_cond_timedwait_relative_np_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_cond_signal(c *pthreadcond) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_cond_signal_trampoline)), unsafe.Pointer(&c)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_cond_signal_trampoline)), unsafe.Pointer(&c)) + KeepAlive(c) + return ret } func pthread_cond_signal_trampoline() diff --git a/src/runtime/sys_darwin_arm64.go b/src/runtime/sys_darwin_arm64.go index e6d4c1be48..6170f4fdda 100644 --- a/src/runtime/sys_darwin_arm64.go +++ b/src/runtime/sys_darwin_arm64.go @@ -15,7 +15,9 @@ import ( //go:nosplit //go:cgo_unsafe_args func g0_pthread_key_create(k *pthreadkey, destructor uintptr) int32 { - return asmcgocall(unsafe.Pointer(abi.FuncPCABI0(pthread_key_create_trampoline)), unsafe.Pointer(&k)) + ret := asmcgocall(unsafe.Pointer(abi.FuncPCABI0(pthread_key_create_trampoline)), unsafe.Pointer(&k)) + KeepAlive(k) + return ret } func pthread_key_create_trampoline() diff --git a/src/runtime/sys_openbsd.go b/src/runtime/sys_openbsd.go index 9f3a25fcf8..c4b8489612 100644 --- a/src/runtime/sys_openbsd.go +++ b/src/runtime/sys_openbsd.go @@ -17,35 +17,47 @@ import ( //go:nosplit //go:cgo_unsafe_args func pthread_attr_init(attr *pthreadattr) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_attr_init_trampoline)), unsafe.Pointer(&attr)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_attr_init_trampoline)), unsafe.Pointer(&attr)) + KeepAlive(attr) + return ret } func pthread_attr_init_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_attr_destroy(attr *pthreadattr) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_attr_destroy_trampoline)), unsafe.Pointer(&attr)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_attr_destroy_trampoline)), unsafe.Pointer(&attr)) + KeepAlive(attr) + return ret } func pthread_attr_destroy_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_attr_getstacksize(attr *pthreadattr, size *uintptr) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_attr_getstacksize_trampoline)), unsafe.Pointer(&attr)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_attr_getstacksize_trampoline)), unsafe.Pointer(&attr)) + KeepAlive(attr) + KeepAlive(size) + return ret } func pthread_attr_getstacksize_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_attr_setdetachstate(attr *pthreadattr, state int) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_attr_setdetachstate_trampoline)), unsafe.Pointer(&attr)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_attr_setdetachstate_trampoline)), unsafe.Pointer(&attr)) + KeepAlive(attr) + return ret } func pthread_attr_setdetachstate_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_create(attr *pthreadattr, start uintptr, arg unsafe.Pointer) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_create_trampoline)), unsafe.Pointer(&attr)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(pthread_create_trampoline)), unsafe.Pointer(&attr)) + KeepAlive(attr) + KeepAlive(arg) // Just for consistency. Arg of course needs to be kept alive for the start function. + return ret } func pthread_create_trampoline() diff --git a/src/runtime/sys_openbsd1.go b/src/runtime/sys_openbsd1.go index 4b80f60226..d852e3c58a 100644 --- a/src/runtime/sys_openbsd1.go +++ b/src/runtime/sys_openbsd1.go @@ -14,7 +14,10 @@ import ( //go:nosplit //go:cgo_unsafe_args func thrsleep(ident uintptr, clock_id int32, tsp *timespec, lock uintptr, abort *uint32) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(thrsleep_trampoline)), unsafe.Pointer(&ident)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(thrsleep_trampoline)), unsafe.Pointer(&ident)) + KeepAlive(tsp) + KeepAlive(abort) + return ret } func thrsleep_trampoline() diff --git a/src/runtime/sys_openbsd2.go b/src/runtime/sys_openbsd2.go index c936fbb494..a7786fe65a 100644 --- a/src/runtime/sys_openbsd2.go +++ b/src/runtime/sys_openbsd2.go @@ -56,6 +56,7 @@ func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) (un ret2 int }{addr, n, prot, flags, fd, off, nil, 0} libcCall(unsafe.Pointer(abi.FuncPCABI0(mmap_trampoline)), unsafe.Pointer(&args)) + KeepAlive(addr) // Just for consistency. Hopefully addr is not a Go address. return args.ret1, args.ret2 } func mmap_trampoline() @@ -64,6 +65,7 @@ func mmap_trampoline() //go:cgo_unsafe_args func munmap(addr unsafe.Pointer, n uintptr) { libcCall(unsafe.Pointer(abi.FuncPCABI0(munmap_trampoline)), unsafe.Pointer(&addr)) + KeepAlive(addr) // Just for consistency. Hopefully addr is not a Go address. } func munmap_trampoline() @@ -71,13 +73,16 @@ func munmap_trampoline() //go:cgo_unsafe_args func madvise(addr unsafe.Pointer, n uintptr, flags int32) { libcCall(unsafe.Pointer(abi.FuncPCABI0(madvise_trampoline)), unsafe.Pointer(&addr)) + KeepAlive(addr) // Just for consistency. Hopefully addr is not a Go address. } func madvise_trampoline() //go:nosplit //go:cgo_unsafe_args func open(name *byte, mode, perm int32) (ret int32) { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(open_trampoline)), unsafe.Pointer(&name)) + ret = libcCall(unsafe.Pointer(abi.FuncPCABI0(open_trampoline)), unsafe.Pointer(&name)) + KeepAlive(name) + return } func open_trampoline() @@ -91,14 +96,18 @@ func close_trampoline() //go:nosplit //go:cgo_unsafe_args func read(fd int32, p unsafe.Pointer, n int32) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(read_trampoline)), unsafe.Pointer(&fd)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(read_trampoline)), unsafe.Pointer(&fd)) + KeepAlive(p) + return ret } func read_trampoline() //go:nosplit //go:cgo_unsafe_args func write1(fd uintptr, p unsafe.Pointer, n int32) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(write_trampoline)), unsafe.Pointer(&fd)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(write_trampoline)), unsafe.Pointer(&fd)) + KeepAlive(p) + return ret } func write_trampoline() @@ -121,6 +130,8 @@ func pipe2_trampoline() //go:cgo_unsafe_args func setitimer(mode int32, new, old *itimerval) { libcCall(unsafe.Pointer(abi.FuncPCABI0(setitimer_trampoline)), unsafe.Pointer(&mode)) + KeepAlive(new) + KeepAlive(old) } func setitimer_trampoline() @@ -140,7 +151,12 @@ func usleep_no_g(usec uint32) { //go:nosplit //go:cgo_unsafe_args func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(sysctl_trampoline)), unsafe.Pointer(&mib)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(sysctl_trampoline)), unsafe.Pointer(&mib)) + KeepAlive(mib) + KeepAlive(out) + KeepAlive(size) + KeepAlive(dst) + return ret } func sysctl_trampoline() @@ -184,7 +200,11 @@ func kqueue_trampoline() //go:nosplit //go:cgo_unsafe_args func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32 { - return libcCall(unsafe.Pointer(abi.FuncPCABI0(kevent_trampoline)), unsafe.Pointer(&kq)) + ret := libcCall(unsafe.Pointer(abi.FuncPCABI0(kevent_trampoline)), unsafe.Pointer(&kq)) + KeepAlive(ch) + KeepAlive(ev) + KeepAlive(ts) + return ret } func kevent_trampoline() @@ -192,6 +212,8 @@ func kevent_trampoline() //go:cgo_unsafe_args func sigaction(sig uint32, new *sigactiont, old *sigactiont) { libcCall(unsafe.Pointer(abi.FuncPCABI0(sigaction_trampoline)), unsafe.Pointer(&sig)) + KeepAlive(new) + KeepAlive(old) } func sigaction_trampoline() @@ -201,6 +223,8 @@ func sigprocmask(how uint32, new *sigset, old *sigset) { // sigprocmask is called from sigsave, which is called from needm. // As such, we have to be able to run with no g here. asmcgocall_no_g(unsafe.Pointer(abi.FuncPCABI0(sigprocmask_trampoline)), unsafe.Pointer(&how)) + KeepAlive(new) + KeepAlive(old) } func sigprocmask_trampoline() @@ -208,6 +232,8 @@ func sigprocmask_trampoline() //go:cgo_unsafe_args func sigaltstack(new *stackt, old *stackt) { libcCall(unsafe.Pointer(abi.FuncPCABI0(sigaltstack_trampoline)), unsafe.Pointer(&new)) + KeepAlive(new) + KeepAlive(old) } func sigaltstack_trampoline() diff --git a/src/runtime/syscall_solaris.go b/src/runtime/syscall_solaris.go index 15be8e1c61..e270e271c0 100644 --- a/src/runtime/syscall_solaris.go +++ b/src/runtime/syscall_solaris.go @@ -312,6 +312,8 @@ func syscall_wait4(pid uintptr, wstatus *uint32, options uintptr, rusage unsafe. entersyscallblock() asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&call)) exitsyscall() + KeepAlive(wstatus) + KeepAlive(rusage) return int(call.r1), call.err } diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go index da181f2a8d..e76b403ade 100644 --- a/src/runtime/syscall_windows.go +++ b/src/runtime/syscall_windows.go @@ -422,6 +422,8 @@ func syscall_loadsystemlibrary(filename *uint16, absoluteFilepath *uint16) (hand } cgocall(asmstdcallAddr, unsafe.Pointer(c)) + KeepAlive(filename) + KeepAlive(absoluteFilepath) handle = c.r1 if handle == 0 { err = c.err @@ -441,6 +443,7 @@ func syscall_loadlibrary(filename *uint16) (handle, err uintptr) { c.n = 1 c.args = uintptr(noescape(unsafe.Pointer(&filename))) cgocall(asmstdcallAddr, unsafe.Pointer(c)) + KeepAlive(filename) handle = c.r1 if handle == 0 { err = c.err @@ -459,6 +462,7 @@ func syscall_getprocaddress(handle uintptr, procname *byte) (outhandle, err uint c.n = 2 c.args = uintptr(noescape(unsafe.Pointer(&handle))) cgocall(asmstdcallAddr, unsafe.Pointer(c)) + KeepAlive(procname) outhandle = c.r1 if outhandle == 0 { err = c.err -- GitLab From 18934e11ba6ef2b2f21f091ddf4ab6814dcf1959 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 29 Nov 2021 15:17:36 -0500 Subject: [PATCH 2354/2500] net/http: eliminate arbitrary timeout in TestClientWriteShutdown This test occasionally hangs on the darwin-arm64-11_0-toothrot builder. When it does, it fails with the unhelpful error message "timeout" instead of a useful goroutine dump. This change eliminates the use of an arbitrary timeout channel, so that if (and probably when) the test hangs again we will get more useful logs to diagnose the root cause. For #49860 Change-Id: I23f6f1c81209f0b2dbe565e1dfb26b1b2eff0187 Reviewed-on: https://go-review.googlesource.com/c/go/+/367615 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Damien Neil --- src/net/http/serve_test.go | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index 1156b187ae..82c1a6716f 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -3075,22 +3075,14 @@ func TestClientWriteShutdown(t *testing.T) { if err != nil { t.Fatalf("CloseWrite: %v", err) } - donec := make(chan bool) - go func() { - defer close(donec) - bs, err := io.ReadAll(conn) - if err != nil { - t.Errorf("ReadAll: %v", err) - } - got := string(bs) - if got != "" { - t.Errorf("read %q from server; want nothing", got) - } - }() - select { - case <-donec: - case <-time.After(10 * time.Second): - t.Fatalf("timeout") + + bs, err := io.ReadAll(conn) + if err != nil { + t.Errorf("ReadAll: %v", err) + } + got := string(bs) + if got != "" { + t.Errorf("read %q from server; want nothing", got) } } -- GitLab From 682435dd9991040073ae12021fac164b41376502 Mon Sep 17 00:00:00 2001 From: "Paul E. Murphy" Date: Fri, 19 Nov 2021 16:33:42 -0600 Subject: [PATCH 2355/2500] misc/cgo/test: reduce likeliness of hang in Test9400 If a GC triggers while spinning in RewindAndSetgid, it may result in this test hanging. Avoid it by disabling the collector before entering the uninterruptable ASM conditional wait. Fixes #49695 Change-Id: Ie0a03653481fb746f862469361b7840f4bfa8b67 Reviewed-on: https://go-review.googlesource.com/c/go/+/365836 Run-TryBot: Paul Murphy TryBot-Result: Go Bot Trust: Michael Knyszek Reviewed-by: Ian Lance Taylor --- misc/cgo/test/testdata/issue9400_linux.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/misc/cgo/test/testdata/issue9400_linux.go b/misc/cgo/test/testdata/issue9400_linux.go index e94a9bb45f..f521b1f49a 100644 --- a/misc/cgo/test/testdata/issue9400_linux.go +++ b/misc/cgo/test/testdata/issue9400_linux.go @@ -15,6 +15,7 @@ import "C" import ( "runtime" + "runtime/debug" "sync/atomic" "testing" @@ -46,6 +47,10 @@ func test9400(t *testing.T) { big[i] = pattern } + // Disable GC for the duration of the test. + // This avoids a potential GC deadlock when spinning in uninterruptable ASM below #49695. + defer debug.SetGCPercent(debug.SetGCPercent(-1)) + // Temporarily rewind the stack and trigger SIGSETXID issue9400.RewindAndSetgid() -- GitLab From 931d80ec17374e52dbc5f9f63120f8deb80b355d Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 25 Oct 2021 16:02:07 -0400 Subject: [PATCH 2356/2500] cmd/go: adjust BuildInfo.Settings Make Settings more closely align with command-line flags and environment variables. - Change command-line flags to begin with - - Change syntax of build lines to use Key=Value instead of KeyValue. - Change CGO_ENABLED to 0/1, matching environment variable, instead of false/true. - Add GOOS and GOARCH. These are technically redundant, in that they can be extracted from the binary in other ways most of the time, but not always: GOOS=ios and GOOS=darwin may produce binaries that are difficult to tell apart. In any case, it's a lot easier to have them directly in the settings list than derive them from other parts of the binary. - Add GOEXPERIMENT. These could be inferred from the tags list, but the experiments are being removed from the tags list. - Change the tags list to match the -tags command-line argument. - Add msan and race, echoing the -msan and -race arguments (always 'true' when present, omitted when false). - Add GO$GOARCH when set. Change-Id: Icb59ef4faa5c22407eadd94147b7e53cf4344ce6 Reviewed-on: https://go-review.googlesource.com/c/go/+/358539 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/cfg/cfg.go | 4 +- src/cmd/go/internal/load/pkg.go | 53 ++++++++++++++----- src/cmd/go/internal/work/init.go | 2 +- .../script/version_build_settings.txt | 28 +++++----- .../testdata/script/version_buildvcs_git.txt | 27 +++++----- .../testdata/script/version_buildvcs_hg.txt | 16 +++--- src/debug/buildinfo/buildinfo_test.go | 4 +- src/runtime/debug/mod.go | 24 +++++---- 8 files changed, 97 insertions(+), 61 deletions(-) diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go index 351c3ee6a5..5b84d8be92 100644 --- a/src/cmd/go/internal/cfg/cfg.go +++ b/src/cmd/go/internal/cfg/cfg.go @@ -63,6 +63,8 @@ var ( // GoPathError is set when GOPATH is not set. it contains an // explanation why GOPATH is unset. GoPathError string + + GOEXPERIMENT = envOr("GOEXPERIMENT", buildcfg.DefaultGOEXPERIMENT) ) func defaultContext() build.Context { @@ -89,7 +91,7 @@ func defaultContext() build.Context { // The experiments flags are based on GOARCH, so they may // need to change. TODO: This should be cleaned up. - buildcfg.UpdateExperiments(ctxt.GOOS, ctxt.GOARCH, envOr("GOEXPERIMENT", buildcfg.DefaultGOEXPERIMENT)) + buildcfg.UpdateExperiments(ctxt.GOOS, ctxt.GOARCH, GOEXPERIMENT) ctxt.ToolTags = nil for _, exp := range buildcfg.EnabledExperiments() { ctxt.ToolTags = append(ctxt.ToolTags, "goexperiment."+exp) diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index 41afa42f0f..589bf9e729 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -2285,33 +2285,57 @@ func (p *Package) setBuildInfo() { Deps: deps, } appendSetting := func(key, value string) { + value = strings.ReplaceAll(value, "\n", " ") // make value safe info.Settings = append(info.Settings, debug.BuildSetting{Key: key, Value: value}) } // Add command-line flags relevant to the build. // This is informational, not an exhaustive list. + // Please keep the list sorted. if cfg.BuildBuildinfo && !p.Standard { - appendSetting("compiler", cfg.BuildContext.Compiler) - if BuildAsmflags.present { - appendSetting("asmflags", BuildAsmflags.String()) + if cfg.BuildASan { + appendSetting("-asan", "true") } - if BuildGcflags.present && cfg.BuildContext.Compiler == "gc" { - appendSetting("gcflags", BuildGcflags.String()) + if BuildAsmflags.present { + appendSetting("-asmflags", BuildAsmflags.String()) } + appendSetting("-compiler", cfg.BuildContext.Compiler) if BuildGccgoflags.present && cfg.BuildContext.Compiler == "gccgo" { - appendSetting("gccgoflags", BuildGccgoflags.String()) + appendSetting("-gccgoflags", BuildGccgoflags.String()) + } + if BuildGcflags.present && cfg.BuildContext.Compiler == "gc" { + appendSetting("-gcflags", BuildGcflags.String()) } if BuildLdflags.present { - appendSetting("ldflags", BuildLdflags.String()) + appendSetting("-ldflags", BuildLdflags.String()) + } + if cfg.BuildMSan { + appendSetting("-msan", "true") } - tags := append(cfg.BuildContext.BuildTags, cfg.BuildContext.ToolTags...) - appendSetting("tags", strings.Join(tags, ",")) - appendSetting("CGO_ENABLED", strconv.FormatBool(cfg.BuildContext.CgoEnabled)) + if cfg.BuildRace { + appendSetting("-race", "true") + } + if tags := cfg.BuildContext.BuildTags; len(tags) > 0 { + appendSetting("-tags", strings.Join(tags, ",")) + } + cgo := "0" + if cfg.BuildContext.CgoEnabled { + cgo = "1" + } + appendSetting("CGO_ENABLED", cgo) if cfg.BuildContext.CgoEnabled { - for _, name := range []string{"CGO_CPPFLAGS", "CGO_CFLAGS", "CGO_CXXFLAGS", "CGO_LDFLAGS"} { + for _, name := range []string{"CGO_CFLAGS", "CGO_CPPFLAGS", "CGO_CXXFLAGS", "CGO_LDFLAGS"} { appendSetting(name, cfg.Getenv(name)) } } + appendSetting("GOARCH", cfg.BuildContext.GOARCH) + if cfg.GOEXPERIMENT != "" { + appendSetting("GOEXPERIMENT", cfg.GOEXPERIMENT) + } + appendSetting("GOOS", cfg.BuildContext.GOOS) + if key, val := cfg.GetArchEnv(); key != "" && val != "" { + appendSetting(key, val) + } } // Add VCS status if all conditions are true: @@ -2383,14 +2407,15 @@ func (p *Package) setBuildInfo() { } st := cached.Status + appendSetting("vcs", vcsCmd.Cmd) if st.Revision != "" { - appendSetting(vcsCmd.Cmd+"revision", st.Revision) + appendSetting("vcs.revision", st.Revision) } if !st.CommitTime.IsZero() { stamp := st.CommitTime.UTC().Format(time.RFC3339Nano) - appendSetting(vcsCmd.Cmd+"committime", stamp) + appendSetting("vcs.time", stamp) } - appendSetting(vcsCmd.Cmd+"uncommitted", strconv.FormatBool(st.Uncommitted)) + appendSetting("vcs.modified", strconv.FormatBool(st.Uncommitted)) } text, err := info.MarshalText() diff --git a/src/cmd/go/internal/work/init.go b/src/cmd/go/internal/work/init.go index dc368de1c1..26192ecaed 100644 --- a/src/cmd/go/internal/work/init.go +++ b/src/cmd/go/internal/work/init.go @@ -138,7 +138,7 @@ func instrumentInit() { cfg.BuildContext.InstallSuffix += "_" } cfg.BuildContext.InstallSuffix += mode - cfg.BuildContext.BuildTags = append(cfg.BuildContext.BuildTags, mode) + cfg.BuildContext.ToolTags = append(cfg.BuildContext.ToolTags, mode) } func buildModeInit() { diff --git a/src/cmd/go/testdata/script/version_build_settings.txt b/src/cmd/go/testdata/script/version_build_settings.txt index 1ced285ac3..dc9e67681e 100644 --- a/src/cmd/go/testdata/script/version_build_settings.txt +++ b/src/cmd/go/testdata/script/version_build_settings.txt @@ -3,22 +3,25 @@ # Compiler name is always added. go build go version -m m$GOEXE -stdout '^\tbuild\tcompiler\tgc$' +stdout '^\tbuild\t-compiler=gc$' +stdout '^\tbuild\tGOOS=' +stdout '^\tbuild\tGOARCH=' +[amd64] stdout '^\tbuild\tGOAMD64=' ! stdout asmflags|gcflags|ldflags|gccgoflags # Toolchain flags are added if present. # The raw flags are included, with package patterns if specified. go build -asmflags=example.com/m=-D=FOO=bar go version -m m$GOEXE -stdout '^\tbuild\tasmflags\texample\.com/m=-D=FOO=bar$' +stdout '^\tbuild\t-asmflags=example\.com/m=-D=FOO=bar$' go build -gcflags=example.com/m=-N go version -m m$GOEXE -stdout '^\tbuild\tgcflags\texample\.com/m=-N$' +stdout '^\tbuild\t-gcflags=example\.com/m=-N$' go build -ldflags=example.com/m=-w go version -m m$GOEXE -stdout '^\tbuild\tldflags\texample\.com/m=-w$' +stdout '^\tbuild\t-ldflags=example\.com/m=-w$' # gccgoflags are not added when gc is used, and vice versa. # TODO: test gccgo. @@ -30,10 +33,11 @@ go version -m m$GOEXE # "race" is included with build tags but not "cgo". go build -tags=a,b go version -m m$GOEXE -stdout '^\tbuild\ttags\ta,b(,goexperiment\.[a-z0-9]+)*$' +stdout '^\tbuild\t-tags=a,b$' [race] go build -race [race] go version -m m$GOEXE -[race] stdout '^\tbuild\ttags\t.*race.*$' +[race] ! stdout '^\tbuild\t-tags=' +[race] stdout '^\tbuild\t-race=true$' # CGO flags are separate settings. # CGO_ENABLED is always present. @@ -41,7 +45,7 @@ stdout '^\tbuild\ttags\ta,b(,goexperiment\.[a-z0-9]+)*$' env CGO_ENABLED=0 go build go version -m m$GOEXE -stdout '^\tbuild\tCGO_ENABLED\tfalse$' +stdout '^\tbuild\tCGO_ENABLED=0$' ! stdout CGO_CPPFLAGS|CGO_CFLAGS|CGO_CXXFLAGS|CGO_LDFLAGS [cgo] env CGO_ENABLED=1 [cgo] env CGO_CPPFLAGS=-DFROM_CPPFLAGS=1 @@ -50,11 +54,11 @@ stdout '^\tbuild\tCGO_ENABLED\tfalse$' [cgo] env CGO_LDFLAGS=-L/extra/dir/does/not/exist [cgo] go build [cgo] go version -m m$GOEXE -[cgo] stdout '^\tbuild\tCGO_ENABLED\ttrue$' -[cgo] stdout '^\tbuild\tCGO_CPPFLAGS\t-DFROM_CPPFLAGS=1$' -[cgo] stdout '^\tbuild\tCGO_CFLAGS\t-DFROM_CFLAGS=1$' -[cgo] stdout '^\tbuild\tCGO_CXXFLAGS\t-DFROM_CXXFLAGS=1$' -[cgo] stdout '^\tbuild\tCGO_LDFLAGS\t-L/extra/dir/does/not/exist$' +[cgo] stdout '^\tbuild\tCGO_ENABLED=1$' +[cgo] stdout '^\tbuild\tCGO_CPPFLAGS=-DFROM_CPPFLAGS=1$' +[cgo] stdout '^\tbuild\tCGO_CFLAGS=-DFROM_CFLAGS=1$' +[cgo] stdout '^\tbuild\tCGO_CXXFLAGS=-DFROM_CXXFLAGS=1$' +[cgo] stdout '^\tbuild\tCGO_LDFLAGS=-L/extra/dir/does/not/exist$' -- go.mod -- module example.com/m diff --git a/src/cmd/go/testdata/script/version_buildvcs_git.txt b/src/cmd/go/testdata/script/version_buildvcs_git.txt index 72cbe28285..86d1de06df 100644 --- a/src/cmd/go/testdata/script/version_buildvcs_git.txt +++ b/src/cmd/go/testdata/script/version_buildvcs_git.txt @@ -11,7 +11,7 @@ cd repo/a # If there's no local repository, there's no VCS info. go install go version -m $GOBIN/a$GOEXE -! stdout gitrevision +! stdout vcs.revision rm $GOBIN/a$GOEXE # If there is a repository, but it can't be used for some reason, @@ -40,9 +40,10 @@ exec git config user.name 'J.R. Gopher' cd a go install go version -m $GOBIN/a$GOEXE -! stdout gitrevision -! stdout gitcommittime -stdout '^\tbuild\tgituncommitted\ttrue$' +stdout '^\tbuild\tvcs=git$' +stdout '^\tbuild\tvcs.modified=true$' +! stdout vcs.revision +! stdout vcs.time rm $GOBIN/a$GOEXE # Revision and commit time are tagged for repositories with commits. @@ -50,22 +51,22 @@ exec git add -A exec git commit -m 'initial commit' go install go version -m $GOBIN/a$GOEXE -stdout '^\tbuild\tgitrevision\t' -stdout '^\tbuild\tgitcommittime\t' -stdout '^\tbuild\tgituncommitted\tfalse$' +stdout '^\tbuild\tvcs.revision=' +stdout '^\tbuild\tvcs.time=' +stdout '^\tbuild\tvcs.modified=false$' rm $GOBIN/a$GOEXE # Building with -buildvcs=false suppresses the info. go install -buildvcs=false go version -m $GOBIN/a$GOEXE -! stdout gitrevision +! stdout vcs.revision rm $GOBIN/a$GOEXE # An untracked file is shown as uncommitted, even if it isn't part of the build. cp ../../outside/empty.txt . go install go version -m $GOBIN/a$GOEXE -stdout '^\tbuild\tgituncommitted\ttrue$' +stdout '^\tbuild\tvcs.modified=true$' rm empty.txt rm $GOBIN/a$GOEXE @@ -73,7 +74,7 @@ rm $GOBIN/a$GOEXE cp ../../outside/empty.txt ../README go install go version -m $GOBIN/a$GOEXE -stdout '^\tbuild\tgituncommitted\ttrue$' +stdout '^\tbuild\tvcs.modified=true$' exec git checkout ../README rm $GOBIN/a$GOEXE @@ -81,14 +82,14 @@ rm $GOBIN/a$GOEXE # there should be no VCS info. go install example.com/cmd/a@v1.0.0 go version -m $GOBIN/a$GOEXE -! stdout gitrevision +! stdout vcs.revision rm $GOBIN/a$GOEXE go mod edit -require=example.com/c@v0.0.0 go mod edit -replace=example.com/c@v0.0.0=../../outside/c go install example.com/c go version -m $GOBIN/c$GOEXE -! stdout gitrevision +! stdout vcs.revision rm $GOBIN/c$GOEXE exec git checkout go.mod @@ -100,7 +101,7 @@ go mod edit -require=example.com/d@v0.0.0 go mod edit -replace=example.com/d@v0.0.0=../../outside/d go install example.com/d go version -m $GOBIN/d$GOEXE -! stdout gitrevision +! stdout vcs.revision exec git checkout go.mod rm $GOBIN/d$GOEXE diff --git a/src/cmd/go/testdata/script/version_buildvcs_hg.txt b/src/cmd/go/testdata/script/version_buildvcs_hg.txt index df4938742d..fbbd886102 100644 --- a/src/cmd/go/testdata/script/version_buildvcs_hg.txt +++ b/src/cmd/go/testdata/script/version_buildvcs_hg.txt @@ -34,9 +34,9 @@ exec hg init cd a go install go version -m $GOBIN/a$GOEXE -! stdout hgrevision -! stdout hgcommittime -stdout '^\tbuild\thguncommitted\ttrue$' +! stdout vcs.revision +! stdout vcs.time +stdout '^\tbuild\tvcs.modified=true$' cd .. # Revision and commit time are tagged for repositories with commits. @@ -45,9 +45,9 @@ exec hg commit -m 'initial commit' cd a go install go version -m $GOBIN/a$GOEXE -stdout '^\tbuild\thgrevision\t' -stdout '^\tbuild\thgcommittime\t' -stdout '^\tbuild\thguncommitted\tfalse$' +stdout '^\tbuild\tvcs.revision=' +stdout '^\tbuild\tvcs.time=' +stdout '^\tbuild\tvcs.modified=false$' rm $GOBIN/a$GOEXE # Building with -buildvcs=false suppresses the info. @@ -60,7 +60,7 @@ rm $GOBIN/a$GOEXE cp ../../outside/empty.txt . go install go version -m $GOBIN/a$GOEXE -stdout '^\tbuild\thguncommitted\ttrue$' +stdout '^\tbuild\tvcs.modified=true$' rm empty.txt rm $GOBIN/a$GOEXE @@ -68,7 +68,7 @@ rm $GOBIN/a$GOEXE cp ../../outside/empty.txt ../README go install go version -m $GOBIN/a$GOEXE -stdout '^\tbuild\thguncommitted\ttrue$' +stdout '^\tbuild\tvcs.modified=true$' exec hg revert ../README rm $GOBIN/a$GOEXE diff --git a/src/debug/buildinfo/buildinfo_test.go b/src/debug/buildinfo/buildinfo_test.go index 44d78a6be0..fd31caf135 100644 --- a/src/debug/buildinfo/buildinfo_test.go +++ b/src/debug/buildinfo/buildinfo_test.go @@ -124,7 +124,7 @@ func TestReadFile(t *testing.T) { // build lines are included. got = goVersionRe.ReplaceAllString(got, "go\tGOVERSION\n") got = buildRe.ReplaceAllStringFunc(got, func(match string) string { - if strings.HasPrefix(match, "build\tcompiler\t") { + if strings.HasPrefix(match, "build\t-compiler=") { return match } return "" @@ -163,7 +163,7 @@ func TestReadFile(t *testing.T) { want: "go\tGOVERSION\n" + "path\texample.com/m\n" + "mod\texample.com/m\t(devel)\t\n" + - "build\tcompiler\tgc\n", + "build\t-compiler=gc\n", }, { name: "invalid_modules", diff --git a/src/runtime/debug/mod.go b/src/runtime/debug/mod.go index 14b99f5735..14a496a8eb 100644 --- a/src/runtime/debug/mod.go +++ b/src/runtime/debug/mod.go @@ -57,8 +57,9 @@ type Module struct { // BuildSetting describes a setting that may be used to understand how the // binary was built. For example, VCS commit and dirty status is stored here. type BuildSetting struct { - // Key and Value describe the build setting. They must not contain tabs - // or newlines. + // Key and Value describe the build setting. + // Key must not contain an equals sign, space, tab, or newline. + // Value must not contain newlines ('\n'). Key, Value string } @@ -97,10 +98,13 @@ func (bi *BuildInfo) MarshalText() ([]byte, error) { formatMod("dep", *dep) } for _, s := range bi.Settings { - if strings.ContainsAny(s.Key, "\n\t") || strings.ContainsAny(s.Value, "\n\t") { - return nil, fmt.Errorf("build setting %q contains tab or newline", s.Key) + if strings.ContainsAny(s.Key, "= \t\n") { + return nil, fmt.Errorf("invalid build setting key %q", s.Key) } - fmt.Fprintf(buf, "build\t%s\t%s\n", s.Key, s.Value) + if strings.Contains(s.Value, "\n") { + return nil, fmt.Errorf("invalid build setting value for key %q: contains newline", s.Value) + } + fmt.Fprintf(buf, "build\t%s=%s\n", s.Key, s.Value) } return buf.Bytes(), nil @@ -185,14 +189,14 @@ func (bi *BuildInfo) UnmarshalText(data []byte) (err error) { } last = nil case bytes.HasPrefix(line, buildLine): - elem := bytes.Split(line[len(buildLine):], tab) - if len(elem) != 2 { - return fmt.Errorf("expected 2 columns for build setting; got %d", len(elem)) + key, val, ok := strings.Cut(string(line[len(buildLine):]), "=") + if !ok { + return fmt.Errorf("invalid build line") } - if len(elem[0]) == 0 { + if key == "" { return fmt.Errorf("empty key") } - bi.Settings = append(bi.Settings, BuildSetting{Key: string(elem[0]), Value: string(elem[1])}) + bi.Settings = append(bi.Settings, BuildSetting{Key: key, Value: val}) } lineNum++ } -- GitLab From 5f63f168daa9644bcc723077e9e2e1796639f6bb Mon Sep 17 00:00:00 2001 From: Chaoqun Han Date: Thu, 25 Nov 2021 21:16:28 +0800 Subject: [PATCH 2357/2500] runtime: add invalidptr=0 for TestGcZombieReporting pointers in zombies slice may cross-span, add invalidptr=0 for avoiding the badPointer check Fixes #49613 Change-Id: Ifb1931922170e87e799e2e6081dc85dab3890205 Reviewed-on: https://go-review.googlesource.com/c/go/+/367044 Trust: Emmanuel Odeke Run-TryBot: Emmanuel Odeke TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills Reviewed-by: Emmanuel Odeke --- src/runtime/gc_test.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/runtime/gc_test.go b/src/runtime/gc_test.go index 7b979afd55..d81cb3a3d5 100644 --- a/src/runtime/gc_test.go +++ b/src/runtime/gc_test.go @@ -196,7 +196,10 @@ func TestPeriodicGC(t *testing.T) { func TestGcZombieReporting(t *testing.T) { // This test is somewhat sensitive to how the allocator works. - got := runTestProg(t, "testprog", "GCZombie") + // Pointers in zombies slice may cross-span, thus we + // add invalidptr=0 for avoiding the badPointer check. + // See issue https://golang.org/issues/49613/ + got := runTestProg(t, "testprog", "GCZombie", "GODEBUG=invalidptr=0") want := "found pointer to free object" if !strings.Contains(got, want) { t.Fatalf("expected %q in output, but got %q", want, got) -- GitLab From 7ccbcc90560468937f02609a43cb39a6e13ff797 Mon Sep 17 00:00:00 2001 From: "Paul E. Murphy" Date: Fri, 19 Nov 2021 16:33:42 -0600 Subject: [PATCH 2358/2500] misc/cgo/test: further reduce likeliness of hang in Test9400 As suggested by #49680, a GC could be in-progress when we disable GC. Force a GC after we pause to ensure we don't hang in this case. For #49695 Change-Id: I4fc4c06ef2ac174217c3dcf7d58c7669226e2d24 Reviewed-on: https://go-review.googlesource.com/c/go/+/367874 Run-TryBot: Paul Murphy TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Paul Murphy --- misc/cgo/test/testdata/issue9400_linux.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/misc/cgo/test/testdata/issue9400_linux.go b/misc/cgo/test/testdata/issue9400_linux.go index f521b1f49a..47f224dc4f 100644 --- a/misc/cgo/test/testdata/issue9400_linux.go +++ b/misc/cgo/test/testdata/issue9400_linux.go @@ -50,6 +50,8 @@ func test9400(t *testing.T) { // Disable GC for the duration of the test. // This avoids a potential GC deadlock when spinning in uninterruptable ASM below #49695. defer debug.SetGCPercent(debug.SetGCPercent(-1)) + // And finish any pending GC after we pause, if any. + runtime.GC() // Temporarily rewind the stack and trigger SIGSETXID issue9400.RewindAndSetgid() -- GitLab From a412b5f0d803b261b8075289bf41599490f237cc Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Tue, 30 Nov 2021 23:21:39 +0100 Subject: [PATCH 2359/2500] runtime: skip TestSignalIgnoreSIGTRAP on all OpenBSD builders TestSignalIgnoreSIGTRAP is flaky on OpenBSD and the cause is suspected to be a kernel bug. This test is currently only skipped on the previous OpenBSD 6.2 and 6.4 builders for #17496. In the meantime the OpenBSD builders were upgraded to more recent OpenBSD versions (currently 6.8 and 7.0). It seems the issue is still present in these OpenBSD versions and there is no obvious workaround in Go. Thus, skip the flaky test on OpenBSD in general. Updates #17496 Updates #49725 Change-Id: I3577d287dcfaad7a81679db2e71540854fce065a Reviewed-on: https://go-review.googlesource.com/c/go/+/367115 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Emmanuel Odeke Reviewed-by: Bryan C. Mills --- src/runtime/crash_unix_test.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/runtime/crash_unix_test.go b/src/runtime/crash_unix_test.go index 0930a1b365..b93a760276 100644 --- a/src/runtime/crash_unix_test.go +++ b/src/runtime/crash_unix_test.go @@ -14,7 +14,6 @@ import ( "os/exec" "runtime" "runtime/debug" - "strings" "sync" "syscall" "testing" @@ -250,9 +249,7 @@ func TestSignalExitStatus(t *testing.T) { func TestSignalIgnoreSIGTRAP(t *testing.T) { if runtime.GOOS == "openbsd" { - if bn := testenv.Builder(); strings.HasSuffix(bn, "-62") || strings.HasSuffix(bn, "-64") { - testenv.SkipFlaky(t, 17496) - } + testenv.SkipFlaky(t, 49725) } output := runTestProg(t, "testprognet", "SignalIgnoreSIGTRAP") -- GitLab From 0e1d553b4d98b71799b86b0ba9bc338de29b7dfe Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Tue, 30 Nov 2021 16:58:36 +0700 Subject: [PATCH 2360/2500] cmd/compile: fix identical to recognize any and interface{} Currently, identical handles any and interface{} by checking against Types[TINTER]. This is not always true, since when two generated interface{} types may not use the same *Type instance. Instead, we must check whether Type is empty interface or not. Fixes #49875 Change-Id: I28fe4fc0100041a01bb03da795cfe8232b515fc4 Reviewed-on: https://go-review.googlesource.com/c/go/+/367754 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Keith Randall Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/types/identity.go | 3 ++- src/cmd/compile/internal/types/type.go | 3 ++- test/typeparam/issue49875.go | 14 ++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 test/typeparam/issue49875.go diff --git a/src/cmd/compile/internal/types/identity.go b/src/cmd/compile/internal/types/identity.go index 89343b8419..f99e50a1c3 100644 --- a/src/cmd/compile/internal/types/identity.go +++ b/src/cmd/compile/internal/types/identity.go @@ -59,7 +59,8 @@ func identical(t1, t2 *Type, flags int, assumedEqual map[typePair]struct{}) bool case TINT32: return (t1 == Types[TINT32] || t1 == RuneType) && (t2 == Types[TINT32] || t2 == RuneType) case TINTER: - return (t1 == Types[TINTER] || t1 == AnyType) && (t2 == Types[TINTER] || t2 == AnyType) + // Make sure named any type matches any empty interface. + return t1 == AnyType && t2.IsEmptyInterface() || t2 == AnyType && t1.IsEmptyInterface() default: return false } diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index b1194fa196..7d22e2da23 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -1211,7 +1211,8 @@ func (t *Type) cmp(x *Type) Cmp { } case TINTER: - if (t == Types[AnyType.kind] || t == AnyType) && (x == Types[AnyType.kind] || x == AnyType) { + // Make sure named any type matches any empty interface. + if t == AnyType && x.IsEmptyInterface() || x == AnyType && t.IsEmptyInterface() { return CMPeq } } diff --git a/test/typeparam/issue49875.go b/test/typeparam/issue49875.go new file mode 100644 index 0000000000..aece7deab1 --- /dev/null +++ b/test/typeparam/issue49875.go @@ -0,0 +1,14 @@ +// compile -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func f(args ...interface{}) {} + +func g() { + var args []any + f(args...) +} -- GitLab From ab7905540bf83b85cdbd6574e54319126df9dae8 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 29 Nov 2021 14:26:44 -0500 Subject: [PATCH 2361/2500] cmd/go/internal/modload: fix up main-module checks from CL 334932 Some critical Version == "" checks were missing in mvs.go, causing mvs.Req to fail to retain requirements provided by older versions of main modules. A few checks also ought to be rotated to put the less expensive string-equality checks before the more expensive map lookups. Fixes #48511 Change-Id: Ib8de9d49a6413660792c003866bfcf9ab7f82ee2 Reviewed-on: https://go-review.googlesource.com/c/go/+/368136 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Russ Cox --- src/cmd/go/internal/modget/get.go | 2 +- src/cmd/go/internal/modload/buildlist.go | 2 +- src/cmd/go/internal/modload/edit.go | 4 +- src/cmd/go/internal/modload/load.go | 2 +- src/cmd/go/internal/modload/mvs.go | 6 +- .../go/testdata/script/mod_get_issue48511.txt | 68 +++++++++++++++++++ 6 files changed, 76 insertions(+), 8 deletions(-) create mode 100644 src/cmd/go/testdata/script/mod_get_issue48511.txt diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index 2c48c3c444..893cc92e39 100644 --- a/src/cmd/go/internal/modget/get.go +++ b/src/cmd/go/internal/modget/get.go @@ -1124,7 +1124,7 @@ func (r *resolver) loadPackages(ctx context.Context, patterns []string, findPack } opts.AllowPackage = func(ctx context.Context, path string, m module.Version) error { - if m.Path == "" || m.Version == "" && modload.MainModules.Contains(m.Path) { + if m.Path == "" || m.Version == "" { // Packages in the standard library and main modules are already at their // latest (and only) available versions. return nil diff --git a/src/cmd/go/internal/modload/buildlist.go b/src/cmd/go/internal/modload/buildlist.go index f4c1311af5..4ce71fef5b 100644 --- a/src/cmd/go/internal/modload/buildlist.go +++ b/src/cmd/go/internal/modload/buildlist.go @@ -45,7 +45,7 @@ type Requirements struct { pruning modPruning // rootModules is the set of root modules of the graph, sorted and capped to - // length. It may contain duplicates, and may contain multiple versions for a + // length. It may contain duplicates, and may contain multiple versions for a // given module path. The root modules of the groph are the set of main // modules in workspace mode, and the main module's direct requirements // outside workspace mode. diff --git a/src/cmd/go/internal/modload/edit.go b/src/cmd/go/internal/modload/edit.go index 023983caed..0f37e3b2e9 100644 --- a/src/cmd/go/internal/modload/edit.go +++ b/src/cmd/go/internal/modload/edit.go @@ -76,7 +76,7 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel // requirements. var rootPaths []string for _, m := range mustSelect { - if !MainModules.Contains(m.Path) && m.Version != "none" { + if m.Version != "none" && !MainModules.Contains(m.Path) { rootPaths = append(rootPaths, m.Path) } } @@ -370,7 +370,7 @@ func selectPotentiallyImportedModules(ctx context.Context, limiter *versionLimit if err != nil { return nil, false, err } - initial = mg.BuildList()[1:] + initial = mg.BuildList()[MainModules.Len():] } else { initial = rs.rootModules } diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index 27bbfb7832..5e7075da4e 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -1091,7 +1091,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader { break } if changed { - // Don't resolve missing imports until the module graph have stabilized. + // Don't resolve missing imports until the module graph has stabilized. // If the roots are still changing, they may turn out to specify a // requirement on the missing package(s), and we would rather use a // version specified by a new root than add a new dependency on an diff --git a/src/cmd/go/internal/modload/mvs.go b/src/cmd/go/internal/modload/mvs.go index 40224d534b..588bcf4bdc 100644 --- a/src/cmd/go/internal/modload/mvs.go +++ b/src/cmd/go/internal/modload/mvs.go @@ -42,7 +42,7 @@ type mvsReqs struct { } func (r *mvsReqs) Required(mod module.Version) ([]module.Version, error) { - if MainModules.Contains(mod.Path) { + if mod.Version == "" && MainModules.Contains(mod.Path) { // Use the build list as it existed when r was constructed, not the current // global build list. return r.roots, nil @@ -108,12 +108,12 @@ func versions(ctx context.Context, path string, allowed AllowedFunc) ([]string, // previousVersion returns the tagged version of m.Path immediately prior to // m.Version, or version "none" if no prior version is tagged. // -// Since the version of Target is not found in the version list, +// Since the version of a main module is not found in the version list, // it has no previous version. func previousVersion(m module.Version) (module.Version, error) { // TODO(golang.org/issue/38714): thread tracing context through MVS. - if MainModules.Contains(m.Path) { + if m.Version == "" && MainModules.Contains(m.Path) { return module.Version{Path: m.Path, Version: "none"}, nil } diff --git a/src/cmd/go/testdata/script/mod_get_issue48511.txt b/src/cmd/go/testdata/script/mod_get_issue48511.txt new file mode 100644 index 0000000000..0ba486d35b --- /dev/null +++ b/src/cmd/go/testdata/script/mod_get_issue48511.txt @@ -0,0 +1,68 @@ +# Regression test for https://golang.org/issue/48511: +# requirement minimization was accidentally replacing previous +# versions of the main module, causing dependencies to be +# spuriously dropping during requirement minimization and +# leading to an infinite loop. + +cp go.mod go.mod.orig +go mod tidy +cmp go.mod go.mod.orig + +go get -u=patch ./... +cmp go.mod go.mod.want + +-- go.mod -- +module example.net/m + +go 1.16 + +replace ( + example.net/a v0.1.0 => ./a + example.net/b v0.1.0 => ./b + example.net/b v0.1.1 => ./b + example.net/m v0.1.0 => ./m1 +) + +require example.net/a v0.1.0 +-- go.mod.want -- +module example.net/m + +go 1.16 + +replace ( + example.net/a v0.1.0 => ./a + example.net/b v0.1.0 => ./b + example.net/b v0.1.1 => ./b + example.net/m v0.1.0 => ./m1 +) + +require ( + example.net/a v0.1.0 + example.net/b v0.1.1 // indirect +) +-- m.go -- +package m + +import "example.net/a" +-- m1/go.mod -- +module example.net/m + +go 1.16 + +require example.net/b v0.1.0 +-- a/go.mod -- +module example.net/a + +go 1.16 + +require example.net/m v0.1.0 +-- a/a.go -- +package a + +import "example.net/b" +-- b/go.mod -- +module example.net/b + +go 1.16 +-- b/b.go -- +package b -- GitLab From 029dfbcc83123cb62e52f2aaedc46397815e3fa6 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 30 Nov 2021 17:30:57 -0500 Subject: [PATCH 2362/2500] net: do not use sendfile on iOS Apparently, on the iOS builder sendfile causes a SIGSYS signal (instead of returning ENOSYS). Disabling it for now so we can make progress on iOS. We can revisit if sendfile is actually broken on iOS and whether it is beneficial. Updates #49616. Change-Id: I3883fad0ce35e3f0aa352301eb499a1afa0225a1 Reviewed-on: https://go-review.googlesource.com/c/go/+/368054 Trust: Cherry Mui Reviewed-by: Emmanuel Odeke Reviewed-by: Michael Knyszek Reviewed-by: Changkun Ou Reviewed-by: Roland Shoemaker --- src/net/sendfile_stub.go | 2 +- src/net/sendfile_unix_alt.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/net/sendfile_stub.go b/src/net/sendfile_stub.go index 4ddae852e1..7428da3127 100644 --- a/src/net/sendfile_stub.go +++ b/src/net/sendfile_stub.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build aix || (js && wasm) || netbsd || openbsd +//go:build aix || (js && wasm) || netbsd || openbsd || ios package net diff --git a/src/net/sendfile_unix_alt.go b/src/net/sendfile_unix_alt.go index 8845a981f5..f99af92bc8 100644 --- a/src/net/sendfile_unix_alt.go +++ b/src/net/sendfile_unix_alt.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build darwin || dragonfly || freebsd || solaris +//go:build (darwin && !ios) || dragonfly || freebsd || solaris package net -- GitLab From 2c5d2083e41371aa4f5aab9e86921002c1f9b504 Mon Sep 17 00:00:00 2001 From: Rhys Hiltner Date: Mon, 29 Nov 2021 16:48:34 -0800 Subject: [PATCH 2363/2500] runtime: fix riscv64 sigaction mask field offset The Linux kernel for riscv64 does not include an sa_restorer field on its sigaction struct, and expects sa_mask to come immediately after the sa_flags field. Arrange the fields of the sigaction struct that are known to the kernel so they appear at the correct byte offsets, and so they agree with the output of "go tool cgo -godefs". Follow the example set by the mips/mipsle port to leave the sa_restorer field in place, but at an offset where it won't hurt anything. Fixes #49709 Change-Id: I9bb0d7dbd7439d07e3a204461c7d790f33fd4977 Reviewed-on: https://go-review.googlesource.com/c/go/+/367635 Run-TryBot: Rhys Hiltner Reviewed-by: Cherry Mui Reviewed-by: Joel Sing Trust: Ian Lance Taylor --- src/runtime/defs_linux_riscv64.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/runtime/defs_linux_riscv64.go b/src/runtime/defs_linux_riscv64.go index 332720a8c8..747e26bc4b 100644 --- a/src/runtime/defs_linux_riscv64.go +++ b/src/runtime/defs_linux_riscv64.go @@ -122,10 +122,12 @@ func (tv *timeval) set_usec(x int32) { } type sigactiont struct { - sa_handler uintptr - sa_flags uint64 + sa_handler uintptr + sa_flags uint64 + sa_mask uint64 + // Linux on riscv64 does not have the sa_restorer field, but the setsig + // function references it (for x86). Not much harm to include it at the end. sa_restorer uintptr - sa_mask uint64 } type siginfoFields struct { -- GitLab From 8ebb8c9ecba4069cc4defffffbbcdde0ba22ced1 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Tue, 30 Nov 2021 16:10:47 -0500 Subject: [PATCH 2364/2500] runtime: give the subprocess more time in TestSpuriousWakeupsNeverHangSemasleep Issue #27250 reproduced readily enough to keep the subprocess hung indefinitely when it occurred, so the timeout does not need to be short to maintain test fidelity. On the other hand, on heavily loaded systems it might take a while for the kernel to actually start the subprocess, and it might also take a while for control flow to return to the test after the subprocess exits. We can reduce noise from this test in two ways: 1. Measure the timeout from closer to when the subprocess actually starts sleeping, instead of when we started creating the subprocess. 2. Use a longer timeout, since it doesn't actually need to be short. Fixes #38921 Updates #27250 Change-Id: I01c11ae82d0cdc6e7def2da6544b4d07201b35e8 Reviewed-on: https://go-review.googlesource.com/c/go/+/367849 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/runtime/semasleep_test.go | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/runtime/semasleep_test.go b/src/runtime/semasleep_test.go index 0057b0729e..d56733c0cf 100644 --- a/src/runtime/semasleep_test.go +++ b/src/runtime/semasleep_test.go @@ -28,19 +28,24 @@ func TestSpuriousWakeupsNeverHangSemasleep(t *testing.T) { t.Fatal(err) } - start := time.Now() cmd := exec.Command(exe, "After1") stdout, err := cmd.StdoutPipe() if err != nil { t.Fatalf("StdoutPipe: %v", err) } + beforeStart := time.Now() if err := cmd.Start(); err != nil { t.Fatalf("Failed to start command: %v", err) } doneCh := make(chan error, 1) go func() { doneCh <- cmd.Wait() + close(doneCh) }() + t.Cleanup(func() { + cmd.Process.Kill() + <-doneCh + }) // Wait for After1 to close its stdout so that we know the runtime's SIGIO // handler is registered. @@ -52,6 +57,19 @@ func TestSpuriousWakeupsNeverHangSemasleep(t *testing.T) { t.Fatalf("error reading from testprog: %v", err) } + // Wait for an arbitrary timeout longer than one second. The subprocess itself + // attempts to sleep for one second, but if the machine running the test is + // heavily loaded that subprocess may not schedule very quickly even if the + // bug remains fixed. (This is fine, because if the bug really is unfixed we + // can keep the process hung indefinitely, as long as we signal it often + // enough.) + timeout := 10 * time.Second + + // The subprocess begins sleeping for 1s after it writes to stdout, so measure + // the timeout from here (not from when we started creating the process). + // That should reduce noise from process startup overhead. + ready := time.Now() + // With the repro running, we can continuously send to it // a signal that the runtime considers non-terminal, // such as SIGIO, to spuriously wake up @@ -61,10 +79,11 @@ func TestSpuriousWakeupsNeverHangSemasleep(t *testing.T) { for { select { case now := <-ticker.C: - if now.Sub(start) > 2*time.Second { + if now.Sub(ready) > timeout { t.Error("Program failed to return on time and has to be killed, issue #27520 still exists") - cmd.Process.Signal(syscall.SIGKILL) - <-doneCh + // Send SIGQUIT to get a goroutine dump. + // Stop sending SIGIO so that the program can clean up and actually terminate. + cmd.Process.Signal(syscall.SIGQUIT) return } @@ -76,7 +95,7 @@ func TestSpuriousWakeupsNeverHangSemasleep(t *testing.T) { if err != nil { t.Fatalf("The program returned but unfortunately with an error: %v", err) } - if time.Since(start) < 1*time.Second { + if time.Since(beforeStart) < 1*time.Second { // The program was supposed to sleep for a full (monotonic) second; // it should not return before that has elapsed. t.Fatalf("The program stopped too quickly.") -- GitLab From 08ecdf7c2e9e9ecc4e2d7c6d9438faeed2338140 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Wed, 1 Dec 2021 08:56:19 -0500 Subject: [PATCH 2365/2500] runtime: fix racy allgs access on weak memory architectures Currently, markroot is very clever about accessing the allgs slice to find stack roots. Unfortunately, on weak memory architectures, it's a little too clever and can sometimes read a nil g, causing a fatal panic. Specifically, gcMarkRootPrepare snapshots the length of allgs during STW and then markroot accesses allgs up to this length during concurrent marking. During concurrent marking, allgadd can append to allgs *without synchronizing with markroot*, but the argument is that the markroot access should be safe because allgs only grows monotonically and existing entries in allgs never change. This reasoning is insufficient on weak memory architectures. Suppose thread 1 calls allgadd during concurrent marking and that allgs is already at capacity. On thread 1, append will allocate a new slice that initially consists of all nils, then copy the old backing store to the new slice (write A), then allgadd will publish the new slice to the allgs global (write B). Meanwhile, on thread 2, markroot reads the allgs slice base pointer (read A), computes an offset from that base pointer, and reads the value at that offset (read B). On a weak memory machine, thread 2 can observe write B *before* write A. If the order of events from thread 2's perspective is write B, read A, read B, write A, then markroot on thread 2 will read a nil g and then panic. Fix this by taking a snapshot of the allgs slice header in gcMarkRootPrepare while the world is stopped and using that snapshot as the list of stack roots in markroot. This eliminates all read/write concurrency around the access in markroot. Alternatively, we could make markroot use the atomicAllGs API to atomically access the allgs list, but in my opinion it's much less subtle to just eliminate all of the interesting concurrency around the allgs access. Fixes #49686. Fixes #48845. Fixes #43824. (These are all just different paths to the same ultimate issue.) Change-Id: I472b4934a637bbe88c8a080a280aa30212acf984 Reviewed-on: https://go-review.googlesource.com/c/go/+/368134 Trust: Austin Clements Trust: Bryan C. Mills Run-TryBot: Austin Clements TryBot-Result: Go Bot Reviewed-by: Michael Knyszek Reviewed-by: Cherry Mui --- src/runtime/mgc.go | 14 ++++++++++++++ src/runtime/mgcmark.go | 14 ++++++-------- src/runtime/proc.go | 14 ++++++++++++++ 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go index d75893dc43..8c8f7d936b 100644 --- a/src/runtime/mgc.go +++ b/src/runtime/mgc.go @@ -320,11 +320,20 @@ var work struct { nwait uint32 // Number of roots of various root types. Set by gcMarkRootPrepare. + // + // nStackRoots == len(stackRoots), but we have nStackRoots for + // consistency. nDataRoots, nBSSRoots, nSpanRoots, nStackRoots int // Base indexes of each root type. Set by gcMarkRootPrepare. baseData, baseBSS, baseSpans, baseStacks, baseEnd uint32 + // stackRoots is a snapshot of all of the Gs that existed + // before the beginning of concurrent marking. The backing + // store of this must not be modified because it might be + // shared with allgs. + stackRoots []*g + // Each type of GC state transition is protected by a lock. // Since multiple threads can simultaneously detect the state // transition condition, any thread that detects a transition @@ -1368,6 +1377,11 @@ func gcMark(startTime int64) { throw("work.full != 0") } + // Drop allg snapshot. allgs may have grown, in which case + // this is the only reference to the old backing store and + // there's no need to keep it around. + work.stackRoots = nil + // Clear out buffers and double-check that all gcWork caches // are empty. This should be ensured by gcMarkDone before we // enter mark termination. diff --git a/src/runtime/mgcmark.go b/src/runtime/mgcmark.go index a5129bd1ee..a15c62cc49 100644 --- a/src/runtime/mgcmark.go +++ b/src/runtime/mgcmark.go @@ -102,7 +102,8 @@ func gcMarkRootPrepare() { // ignore them because they begin life without any roots, so // there's nothing to scan, and any roots they create during // the concurrent phase will be caught by the write barrier. - work.nStackRoots = int(atomic.Loaduintptr(&allglen)) + work.stackRoots = allGsSnapshot() + work.nStackRoots = len(work.stackRoots) work.markrootNext = 0 work.markrootJobs = uint32(fixedRootCount + work.nDataRoots + work.nBSSRoots + work.nSpanRoots + work.nStackRoots) @@ -194,15 +195,12 @@ func markroot(gcw *gcWork, i uint32, flushBgCredit bool) int64 { default: // the rest is scanning goroutine stacks workCounter = &gcController.stackScanWork - var gp *g - if work.baseStacks <= i && i < work.baseEnd { - // N.B. Atomic read of allglen in gcMarkRootPrepare - // acts as a barrier to ensure that allgs must be large - // enough to contain all relevant Gs. - gp = allgs[i-work.baseStacks] - } else { + if i < work.baseStacks || work.baseEnd <= i { + printlock() + print("runtime: markroot index ", i, " not in stack roots range [", work.baseStacks, ", ", work.baseEnd, ")\n") throw("markroot: bad index") } + gp := work.stackRoots[i-work.baseStacks] // remember when we've first observed the G blocked // needed only to output in traceback diff --git a/src/runtime/proc.go b/src/runtime/proc.go index a238ea77f3..f375b67981 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -547,6 +547,20 @@ func allgadd(gp *g) { unlock(&allglock) } +// allGsSnapshot returns a snapshot of the slice of all Gs. +// +// The world must be stopped or allglock must be held. +func allGsSnapshot() []*g { + assertWorldStoppedOrLockHeld(&allglock) + + // Because the world is stopped or allglock is held, allgadd + // cannot happen concurrently with this. allgs grows + // monotonically and existing entries never change, so we can + // simply return a copy of the slice header. For added safety, + // we trim everything past len because that can still change. + return allgs[:len(allgs):len(allgs)] +} + // atomicAllG returns &allgs[0] and len(allgs) for use with atomicAllGIndex. func atomicAllG() (**g, uintptr) { length := atomic.Loaduintptr(&allglen) -- GitLab From 6c4bf8fb8a2216a09d22ae0c87a04b7865f794c8 Mon Sep 17 00:00:00 2001 From: Baokun Lee Date: Wed, 1 Dec 2021 17:48:55 +0800 Subject: [PATCH 2366/2500] cmd/go/internal/modfetch: remove legacy code ReadFileRevs function is no longer used. Change-Id: Ibac6319dca4cf8010195e7c2fb502655494fb728 Reviewed-on: https://go-review.googlesource.com/c/go/+/367756 Run-TryBot: Baokun Lee Reviewed-by: Bryan C. Mills TryBot-Result: Go Bot Trust: Baokun Lee --- .../go/internal/modfetch/codehost/codehost.go | 15 -- src/cmd/go/internal/modfetch/codehost/git.go | 134 ------------------ src/cmd/go/internal/modfetch/codehost/vcs.go | 13 -- 3 files changed, 162 deletions(-) diff --git a/src/cmd/go/internal/modfetch/codehost/codehost.go b/src/cmd/go/internal/modfetch/codehost/codehost.go index 378fbae34f..5063f8616a 100644 --- a/src/cmd/go/internal/modfetch/codehost/codehost.go +++ b/src/cmd/go/internal/modfetch/codehost/codehost.go @@ -55,21 +55,6 @@ type Repo interface { // os.IsNotExist(err) returns true. ReadFile(rev, file string, maxSize int64) (data []byte, err error) - // ReadFileRevs reads a single file at multiple versions. - // It should refuse to read more than maxSize bytes. - // The result is a map from each requested rev strings - // to the associated FileRev. The map must have a non-nil - // entry for every requested rev (unless ReadFileRevs returned an error). - // A file simply being missing or even corrupted in revs[i] - // should be reported only in files[revs[i]].Err, not in the error result - // from ReadFileRevs. - // The overall call should return an error (and no map) only - // in the case of a problem with obtaining the data, such as - // a network failure. - // Implementations may assume that revs only contain tags, - // not direct commit hashes. - ReadFileRevs(revs []string, file string, maxSize int64) (files map[string]*FileRev, err error) - // ReadZip downloads a zip file for the subdir subdirectory // of the given revision to a new file in a given temporary directory. // It should refuse to read more than maxSize bytes. diff --git a/src/cmd/go/internal/modfetch/codehost/git.go b/src/cmd/go/internal/modfetch/codehost/git.go index a782de56ff..2a5255f115 100644 --- a/src/cmd/go/internal/modfetch/codehost/git.go +++ b/src/cmd/go/internal/modfetch/codehost/git.go @@ -523,140 +523,6 @@ func (r *gitRepo) ReadFile(rev, file string, maxSize int64) ([]byte, error) { return out, nil } -func (r *gitRepo) ReadFileRevs(revs []string, file string, maxSize int64) (map[string]*FileRev, error) { - // Create space to hold results. - files := make(map[string]*FileRev) - for _, rev := range revs { - f := &FileRev{Rev: rev} - files[rev] = f - } - - // Collect locally-known revs. - need, err := r.readFileRevs(revs, file, files) - if err != nil { - return nil, err - } - if len(need) == 0 { - return files, nil - } - - // Build list of known remote refs that might help. - var redo []string - refs, err := r.loadRefs() - if err != nil { - return nil, err - } - for _, tag := range need { - if refs["refs/tags/"+tag] != "" { - redo = append(redo, tag) - } - } - if len(redo) == 0 { - return files, nil - } - - // Protect r.fetchLevel and the "fetch more and more" sequence. - // See stat method above. - unlock, err := r.mu.Lock() - if err != nil { - return nil, err - } - defer unlock() - - if err := r.fetchRefsLocked(); err != nil { - return nil, err - } - - if _, err := r.readFileRevs(redo, file, files); err != nil { - return nil, err - } - - return files, nil -} - -func (r *gitRepo) readFileRevs(tags []string, file string, fileMap map[string]*FileRev) (missing []string, err error) { - var stdin bytes.Buffer - for _, tag := range tags { - fmt.Fprintf(&stdin, "refs/tags/%s\n", tag) - fmt.Fprintf(&stdin, "refs/tags/%s:%s\n", tag, file) - } - - data, err := RunWithStdin(r.dir, &stdin, "git", "cat-file", "--batch") - if err != nil { - return nil, err - } - - next := func() (typ string, body []byte, ok bool) { - var line string - i := bytes.IndexByte(data, '\n') - if i < 0 { - return "", nil, false - } - line, data = string(bytes.TrimSpace(data[:i])), data[i+1:] - if strings.HasSuffix(line, " missing") { - return "missing", nil, true - } - f := strings.Fields(line) - if len(f) != 3 { - return "", nil, false - } - n, err := strconv.Atoi(f[2]) - if err != nil || n > len(data) { - return "", nil, false - } - body, data = data[:n], data[n:] - if len(data) > 0 && data[0] == '\r' { - data = data[1:] - } - if len(data) > 0 && data[0] == '\n' { - data = data[1:] - } - return f[1], body, true - } - - badGit := func() ([]string, error) { - return nil, fmt.Errorf("malformed output from git cat-file --batch") - } - - for _, tag := range tags { - commitType, _, ok := next() - if !ok { - return badGit() - } - fileType, fileData, ok := next() - if !ok { - return badGit() - } - f := fileMap[tag] - f.Data = nil - f.Err = nil - switch commitType { - default: - f.Err = fmt.Errorf("unexpected non-commit type %q for rev %s", commitType, tag) - - case "missing": - // Note: f.Err must not satisfy os.IsNotExist. That's reserved for the file not existing in a valid commit. - f.Err = fmt.Errorf("no such rev %s", tag) - missing = append(missing, tag) - - case "tag", "commit": - switch fileType { - default: - f.Err = &fs.PathError{Path: tag + ":" + file, Op: "read", Err: fmt.Errorf("unexpected non-blob type %q", fileType)} - case "missing": - f.Err = &fs.PathError{Path: tag + ":" + file, Op: "read", Err: fs.ErrNotExist} - case "blob": - f.Data = fileData - } - } - } - if len(bytes.TrimSpace(data)) != 0 { - return badGit() - } - - return missing, nil -} - func (r *gitRepo) RecentTag(rev, prefix string, allowed func(string) bool) (tag string, err error) { info, err := r.Stat(rev) if err != nil { diff --git a/src/cmd/go/internal/modfetch/codehost/vcs.go b/src/cmd/go/internal/modfetch/codehost/vcs.go index c2cca084e3..c8449ccdcc 100644 --- a/src/cmd/go/internal/modfetch/codehost/vcs.go +++ b/src/cmd/go/internal/modfetch/codehost/vcs.go @@ -382,19 +382,6 @@ func (r *vcsRepo) ReadFile(rev, file string, maxSize int64) ([]byte, error) { return out, nil } -func (r *vcsRepo) ReadFileRevs(revs []string, file string, maxSize int64) (map[string]*FileRev, error) { - // We don't technically need to lock here since we're returning an error - // uncondititonally, but doing so anyway will help to avoid baking in - // lock-inversion bugs. - unlock, err := r.mu.Lock() - if err != nil { - return nil, err - } - defer unlock() - - return nil, vcsErrorf("ReadFileRevs not implemented") -} - func (r *vcsRepo) RecentTag(rev, prefix string, allowed func(string) bool) (tag string, err error) { // We don't technically need to lock here since we're returning an error // uncondititonally, but doing so anyway will help to avoid baking in -- GitLab From 0103fd2b8b3e57ead47a65501eb5ce5f444e0077 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 30 Nov 2021 17:48:51 -0500 Subject: [PATCH 2367/2500] gcimporters: allow reusing empty interfaces on the RHS of type decls We guard against caching or reusing interfaces on the RHS of a type declaration, because for such interfaces the base type is used as the interface method receiver type. However, we don't need to do this for empty interfaces. By refining our guard, we can allow importing the predeclared 'any' type on the RHS of a type declaration. Update tests to add more coverage for importing generic export data. Some accomodation had to be made for the unified builder, which does not yet fully support generics in export data. Fixes #49888 Change-Id: I51f329de464fc7309f95991b839ab55868c2924f Reviewed-on: https://go-review.googlesource.com/c/go/+/367851 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- .../internal/importer/gcimporter_test.go | 41 +++++++++++-------- src/cmd/compile/internal/importer/iimport.go | 22 +++++++++- .../internal/importer/testdata/exports.go | 19 +++++---- .../internal/importer/testdata/generics.go | 29 +++++++++++++ src/go/internal/gcimporter/gcimporter_test.go | 40 ++++++++++-------- src/go/internal/gcimporter/iimport.go | 22 +++++++++- .../internal/gcimporter/testdata/exports.go | 19 +++++---- .../internal/gcimporter/testdata/generics.go | 29 +++++++++++++ 8 files changed, 165 insertions(+), 56 deletions(-) create mode 100644 src/cmd/compile/internal/importer/testdata/generics.go create mode 100644 src/go/internal/gcimporter/testdata/generics.go diff --git a/src/cmd/compile/internal/importer/gcimporter_test.go b/src/cmd/compile/internal/importer/gcimporter_test.go index 44c5e06cd6..e097507f69 100644 --- a/src/cmd/compile/internal/importer/gcimporter_test.go +++ b/src/cmd/compile/internal/importer/gcimporter_test.go @@ -8,6 +8,7 @@ import ( "bytes" "cmd/compile/internal/types2" "fmt" + "internal/goexperiment" "internal/testenv" "os" "os/exec" @@ -107,25 +108,29 @@ func TestImportTestdata(t *testing.T) { t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) } - tmpdir := mktmpdir(t) - defer os.RemoveAll(tmpdir) + testfiles := map[string][]string{ + "exports.go": {"go/ast", "go/token"}, + } + if !goexperiment.Unified { + testfiles["generics.go"] = nil + } - compile(t, "testdata", "exports.go", filepath.Join(tmpdir, "testdata")) - - if pkg := testPath(t, "./testdata/exports", tmpdir); pkg != nil { - // The package's Imports list must include all packages - // explicitly imported by exports.go, plus all packages - // referenced indirectly via exported objects in exports.go. - // With the textual export format, the list may also include - // additional packages that are not strictly required for - // import processing alone (they are exported to err "on - // the safe side"). - // TODO(gri) update the want list to be precise, now that - // the textual export data is gone. - got := fmt.Sprint(pkg.Imports()) - for _, want := range []string{"go/ast", "go/token"} { - if !strings.Contains(got, want) { - t.Errorf(`Package("exports").Imports() = %s, does not contain %s`, got, want) + for testfile, wantImports := range testfiles { + tmpdir := mktmpdir(t) + defer os.RemoveAll(tmpdir) + + compile(t, "testdata", testfile, filepath.Join(tmpdir, "testdata")) + path := "./testdata/" + strings.TrimSuffix(testfile, ".go") + + if pkg := testPath(t, path, tmpdir); pkg != nil { + // The package's Imports list must include all packages + // explicitly imported by testfile, plus all packages + // referenced indirectly via exported objects in testfile. + got := fmt.Sprint(pkg.Imports()) + for _, want := range wantImports { + if !strings.Contains(got, want) { + t.Errorf(`Package("exports").Imports() = %s, does not contain %s`, got, want) + } } } } diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index 23d6ca350e..7c51d3b16f 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -259,7 +259,7 @@ func (p *iimporter) posBaseAt(off uint64) *syntax.PosBase { } func (p *iimporter) typAt(off uint64, base *types2.Named) types2.Type { - if t, ok := p.typCache[off]; ok && (base == nil || !isInterface(t)) { + if t, ok := p.typCache[off]; ok && canReuse(base, t) { return t } @@ -274,12 +274,30 @@ func (p *iimporter) typAt(off uint64, base *types2.Named) types2.Type { r.declReader = *strings.NewReader(p.declData[off-predeclReserved:]) t := r.doType(base) - if base == nil || !isInterface(t) { + if canReuse(base, t) { p.typCache[off] = t } return t } +// canReuse reports whether the type rhs on the RHS of the declaration for def +// may be re-used. +// +// Specifically, if def is non-nil and rhs is an interface type with methods, it +// may not be re-used because we have a convention of setting the receiver type +// for interface methods to def. +func canReuse(def *types2.Named, rhs types2.Type) bool { + if def == nil { + return true + } + iface, _ := rhs.(*types2.Interface) + if iface == nil { + return true + } + // Don't use iface.Empty() here as iface may not be complete. + return iface.NumEmbeddeds() == 0 && iface.NumExplicitMethods() == 0 +} + type importReader struct { p *iimporter declReader strings.Reader diff --git a/src/cmd/compile/internal/importer/testdata/exports.go b/src/cmd/compile/internal/importer/testdata/exports.go index 8ba3242102..91598c03e3 100644 --- a/src/cmd/compile/internal/importer/testdata/exports.go +++ b/src/cmd/compile/internal/importer/testdata/exports.go @@ -15,14 +15,17 @@ const init1 = 0 func init() {} const ( - C0 int = 0 - C1 = 3.14159265 - C2 = 2.718281828i - C3 = -123.456e-789 - C4 = +123.456e+789 - C5 = 1234i - C6 = "foo\n" - C7 = `bar\n` + C0 int = 0 + C1 = 3.14159265 + C2 = 2.718281828i + C3 = -123.456e-789 + C4 = +123.456e+789 + C5 = 1234i + C6 = "foo\n" + C7 = `bar\n` + C8 = 42 + C9 int = 42 + C10 float64 = 42 ) type ( diff --git a/src/cmd/compile/internal/importer/testdata/generics.go b/src/cmd/compile/internal/importer/testdata/generics.go new file mode 100644 index 0000000000..00bf04000f --- /dev/null +++ b/src/cmd/compile/internal/importer/testdata/generics.go @@ -0,0 +1,29 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file is used to generate an object file which +// serves as test file for gcimporter_test.go. + +package generics + +type Any any + +var x any + +type T[A, B any] struct { + Left A + Right B +} + +var X T[int, string] = T[int, string]{1, "hi"} + +func ToInt[P interface{ ~int }](p P) int { return int(p) } + +var IntID = ToInt[int] + +type G[C comparable] int + +func ImplicitFunc[T ~int]() {} + +type ImplicitType[T ~int] int diff --git a/src/go/internal/gcimporter/gcimporter_test.go b/src/go/internal/gcimporter/gcimporter_test.go index 3a9ed79df6..c0f4e3934b 100644 --- a/src/go/internal/gcimporter/gcimporter_test.go +++ b/src/go/internal/gcimporter/gcimporter_test.go @@ -118,25 +118,29 @@ func TestImportTestdata(t *testing.T) { t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) } - tmpdir := mktmpdir(t) - defer os.RemoveAll(tmpdir) + testfiles := map[string][]string{ + "exports.go": {"go/ast", "go/token"}, + } + if !goexperiment.Unified { + testfiles["generics.go"] = nil + } - compile(t, "testdata", "exports.go", filepath.Join(tmpdir, "testdata")) - - if pkg := testPath(t, "./testdata/exports", tmpdir); pkg != nil { - // The package's Imports list must include all packages - // explicitly imported by exports.go, plus all packages - // referenced indirectly via exported objects in exports.go. - // With the textual export format, the list may also include - // additional packages that are not strictly required for - // import processing alone (they are exported to err "on - // the safe side"). - // TODO(gri) update the want list to be precise, now that - // the textual export data is gone. - got := fmt.Sprint(pkg.Imports()) - for _, want := range []string{"go/ast", "go/token"} { - if !strings.Contains(got, want) { - t.Errorf(`Package("exports").Imports() = %s, does not contain %s`, got, want) + for testfile, wantImports := range testfiles { + tmpdir := mktmpdir(t) + defer os.RemoveAll(tmpdir) + + compile(t, "testdata", testfile, filepath.Join(tmpdir, "testdata")) + path := "./testdata/" + strings.TrimSuffix(testfile, ".go") + + if pkg := testPath(t, path, tmpdir); pkg != nil { + // The package's Imports list must include all packages + // explicitly imported by testfile, plus all packages + // referenced indirectly via exported objects in testfile. + got := fmt.Sprint(pkg.Imports()) + for _, want := range wantImports { + if !strings.Contains(got, want) { + t.Errorf(`Package("exports").Imports() = %s, does not contain %s`, got, want) + } } } } diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go index d7fc3ee7a9..c5b89aa042 100644 --- a/src/go/internal/gcimporter/iimport.go +++ b/src/go/internal/gcimporter/iimport.go @@ -255,7 +255,7 @@ func (p *iimporter) pkgAt(off uint64) *types.Package { } func (p *iimporter) typAt(off uint64, base *types.Named) types.Type { - if t, ok := p.typCache[off]; ok && (base == nil || !isInterface(t)) { + if t, ok := p.typCache[off]; ok && canReuse(base, t) { return t } @@ -267,12 +267,30 @@ func (p *iimporter) typAt(off uint64, base *types.Named) types.Type { r.declReader.Reset(p.declData[off-predeclReserved:]) t := r.doType(base) - if base == nil || !isInterface(t) { + if canReuse(base, t) { p.typCache[off] = t } return t } +// canReuse reports whether the type rhs on the RHS of the declaration for def +// may be re-used. +// +// Specifically, if def is non-nil and rhs is an interface type with methods, it +// may not be re-used because we have a convention of setting the receiver type +// for interface methods to def. +func canReuse(def *types.Named, rhs types.Type) bool { + if def == nil { + return true + } + iface, _ := rhs.(*types.Interface) + if iface == nil { + return true + } + // Don't use iface.Empty() here as iface may not be complete. + return iface.NumEmbeddeds() == 0 && iface.NumExplicitMethods() == 0 +} + type importReader struct { p *iimporter declReader bytes.Reader diff --git a/src/go/internal/gcimporter/testdata/exports.go b/src/go/internal/gcimporter/testdata/exports.go index 8ba3242102..91598c03e3 100644 --- a/src/go/internal/gcimporter/testdata/exports.go +++ b/src/go/internal/gcimporter/testdata/exports.go @@ -15,14 +15,17 @@ const init1 = 0 func init() {} const ( - C0 int = 0 - C1 = 3.14159265 - C2 = 2.718281828i - C3 = -123.456e-789 - C4 = +123.456e+789 - C5 = 1234i - C6 = "foo\n" - C7 = `bar\n` + C0 int = 0 + C1 = 3.14159265 + C2 = 2.718281828i + C3 = -123.456e-789 + C4 = +123.456e+789 + C5 = 1234i + C6 = "foo\n" + C7 = `bar\n` + C8 = 42 + C9 int = 42 + C10 float64 = 42 ) type ( diff --git a/src/go/internal/gcimporter/testdata/generics.go b/src/go/internal/gcimporter/testdata/generics.go new file mode 100644 index 0000000000..00bf04000f --- /dev/null +++ b/src/go/internal/gcimporter/testdata/generics.go @@ -0,0 +1,29 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file is used to generate an object file which +// serves as test file for gcimporter_test.go. + +package generics + +type Any any + +var x any + +type T[A, B any] struct { + Left A + Right B +} + +var X T[int, string] = T[int, string]{1, "hi"} + +func ToInt[P interface{ ~int }](p P) int { return int(p) } + +var IntID = ToInt[int] + +type G[C comparable] int + +func ImplicitFunc[T ~int]() {} + +type ImplicitType[T ~int] int -- GitLab From c3a7fb207409a77b2ad644fe777db04d7df8e08c Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 1 Dec 2021 11:39:51 -0500 Subject: [PATCH 2368/2500] doc/go1.18: mention stack trace change For #47694. Change-Id: I06cac88d5328c8c0e38212ad801d70bc36cdfc6f Reviewed-on: https://go-review.googlesource.com/c/go/+/368234 Trust: Cherry Mui Reviewed-by: Austin Clements --- doc/go1.18.html | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 022541b83d..d9da160ab5 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -221,12 +221,15 @@ proposal. Go 1.17 release notes for more details.

    -

    - TODO: https://golang.org/cl/298611: cmd/compile: add -asan option +

    + Go 1.17 generally improved the formatting of arguments in stack traces, + but could print inaccurate values for arguments passed in registers. + This is improved in Go 1.18 by printing a question mark (?) + after each value that may be inaccurate.

    -

    - TODO: https://golang.org/cl/352057: cmd/compile, runtime: track argument stack slot liveness +

    + TODO: https://golang.org/cl/298611: cmd/compile: add -asan option

    Linker

    -- GitLab From 00dbcb33f8c20ce51de558cbc9de811b1ba0f70c Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Wed, 1 Dec 2021 14:15:08 -0500 Subject: [PATCH 2369/2500] os/exec: in TestContextCancel, dump goroutines on failure If this test fails, we want to know exactly what the os/exec goroutines are doing. Panicking gives us a goroutine dump, whereas t.Fatal does not. While we're here, use exponential backoff instead of a hard-coded 1ms sleep. We want to give the OS enough time to actually terminate the subprocess. For #42061 Change-Id: I3d50a71ac314853c68a935218e7f97ce18b08b5b Reviewed-on: https://go-review.googlesource.com/c/go/+/368317 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/os/exec/exec_test.go | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go index 6172c78dd4..81de018e09 100644 --- a/src/os/exec/exec_test.go +++ b/src/os/exec/exec_test.go @@ -954,6 +954,10 @@ func TestContext(t *testing.T) { } func TestContextCancel(t *testing.T) { + // To reduce noise in the final goroutine dump, + // let other parallel tests complete if possible. + t.Parallel() + ctx, cancel := context.WithCancel(context.Background()) defer cancel() c := helperCommandContext(t, ctx, "cat") @@ -978,14 +982,25 @@ func TestContextCancel(t *testing.T) { // Calling cancel should have killed the process, so writes // should now fail. Give the process a little while to die. start := time.Now() + delay := 1 * time.Millisecond for { if _, err := io.WriteString(stdin, "echo"); err != nil { break } + if time.Since(start) > time.Minute { - t.Fatal("canceling context did not stop program") + // Panic instead of calling t.Fatal so that we get a goroutine dump. + // We want to know exactly what the os/exec goroutines got stuck on. + panic("canceling context did not stop program") + } + + // Back off exponentially (up to 1-second sleeps) to give the OS time to + // terminate the process. + delay *= 2 + if delay > 1*time.Second { + delay = 1 * time.Second } - time.Sleep(time.Millisecond) + time.Sleep(delay) } if err := c.Wait(); err == nil { -- GitLab From 1b2930d70c8bad5ecae08275e56e228e0f424b02 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Wed, 1 Dec 2021 11:04:39 -0500 Subject: [PATCH 2370/2500] net: remove arbitrary deadlines in PacketConn tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When TestPacketConn was added (in CL 6501057) it included arbitrary 100ms deadlines. Those deadlines were arbitrarily increased to 500ms in CL 4922. If the test is actually provoking a deadlock, allowing it to deadlock will give us a more useful goroutine dump. Otherwise, the deadlines don't seem all that useful — they appear to increase code coverage, but have no effect on the test in the typical case, and can only cause flakes on particularly-slow machines. For #43627 Change-Id: I83de5217c54c743b83adddf51d4f6f2bd5b91732 Reviewed-on: https://go-review.googlesource.com/c/go/+/368215 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/net/packetconn_test.go | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/net/packetconn_test.go b/src/net/packetconn_test.go index b3b1715655..487912efab 100644 --- a/src/net/packetconn_test.go +++ b/src/net/packetconn_test.go @@ -12,7 +12,6 @@ package net import ( "os" "testing" - "time" ) // The full stack test cases for IPConn have been moved to the @@ -60,9 +59,6 @@ func TestPacketConn(t *testing.T) { } defer closer(c1, tt.net, tt.addr1, tt.addr2) c1.LocalAddr() - c1.SetDeadline(time.Now().Add(500 * time.Millisecond)) - c1.SetReadDeadline(time.Now().Add(500 * time.Millisecond)) - c1.SetWriteDeadline(time.Now().Add(500 * time.Millisecond)) c2, err := ListenPacket(tt.net, tt.addr2) if err != nil { @@ -70,9 +66,6 @@ func TestPacketConn(t *testing.T) { } defer closer(c2, tt.net, tt.addr1, tt.addr2) c2.LocalAddr() - c2.SetDeadline(time.Now().Add(500 * time.Millisecond)) - c2.SetReadDeadline(time.Now().Add(500 * time.Millisecond)) - c2.SetWriteDeadline(time.Now().Add(500 * time.Millisecond)) rb2 := make([]byte, 128) if _, err := c1.WriteTo(wb, c2.LocalAddr()); err != nil { @@ -115,9 +108,6 @@ func TestConnAndPacketConn(t *testing.T) { } defer closer(c1, tt.net, tt.addr1, tt.addr2) c1.LocalAddr() - c1.SetDeadline(time.Now().Add(500 * time.Millisecond)) - c1.SetReadDeadline(time.Now().Add(500 * time.Millisecond)) - c1.SetWriteDeadline(time.Now().Add(500 * time.Millisecond)) c2, err := Dial(tt.net, c1.LocalAddr().String()) if err != nil { @@ -126,9 +116,6 @@ func TestConnAndPacketConn(t *testing.T) { defer c2.Close() c2.LocalAddr() c2.RemoteAddr() - c2.SetDeadline(time.Now().Add(500 * time.Millisecond)) - c2.SetReadDeadline(time.Now().Add(500 * time.Millisecond)) - c2.SetWriteDeadline(time.Now().Add(500 * time.Millisecond)) if _, err := c2.Write(wb); err != nil { t.Fatal(err) -- GitLab From d34051bf16d86a88e6c5764aa076219069702045 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 1 Dec 2021 10:53:17 -0800 Subject: [PATCH 2371/2500] cmd/compile: fix case where g.curDecl should be saved/restored When we set g.curDecl for the type params created during fillinMethods for an instantiated type, we need to save/restore its value, because fillinMethods() may be called while processing a typeDecl. We want the value of g.curDecl to continue to be correct for type params created in the typeDecl. Because of ordering issues, not restoring g.curDecl happens to cause problems (which don't always show up visibly) exactly when a type param is not actually used in a type declaration. Cleared g.curDecl to "" at the later points in typeDecl() and funcDecl(). This allows adding asserts that g.curDecl is always empty ("") when we set it in typeDecl() and funcDecl(), and always non-empty when we use it in typ0(). Fixes #49893 Change-Id: Ic2fb1df791585bd257f2b86ffaae0453c31705c5 Reviewed-on: https://go-review.googlesource.com/c/go/+/368454 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/noder/decl.go | 6 ++++++ src/cmd/compile/internal/noder/types.go | 7 ++++++- test/typeparam/issue49893.dir/a.go | 15 +++++++++++++++ test/typeparam/issue49893.dir/b.go | 15 +++++++++++++++ test/typeparam/issue49893.dir/main.go | 15 +++++++++++++++ test/typeparam/issue49893.go | 7 +++++++ 6 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 test/typeparam/issue49893.dir/a.go create mode 100644 test/typeparam/issue49893.dir/b.go create mode 100644 test/typeparam/issue49893.dir/main.go create mode 100644 test/typeparam/issue49893.go diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go index 0143fd3d45..027c8598fd 100644 --- a/src/cmd/compile/internal/noder/decl.go +++ b/src/cmd/compile/internal/noder/decl.go @@ -86,6 +86,7 @@ func (g *irgen) constDecl(out *ir.Nodes, decl *syntax.ConstDecl) { } func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) { + assert(g.curDecl == "") // Set g.curDecl to the function name, as context for the type params declared // during types2-to-types1 translation if this is a generic function. g.curDecl = decl.Name.Value @@ -133,6 +134,7 @@ func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) { } haveEmbed := g.haveEmbed + g.curDecl = "" g.later(func() { defer func(b bool) { g.haveEmbed = b }(g.haveEmbed) @@ -158,6 +160,7 @@ func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) { } func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) { + assert(g.curDecl == "") // Set g.curDecl to the type name, as context for the type params declared // during types2-to-types1 translation if this is a generic type. g.curDecl = decl.Name.Value @@ -167,6 +170,7 @@ func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) { assert(name.Alias()) // should be set by irgen.obj out.Append(ir.NewDecl(g.pos(decl), ir.ODCLTYPE, name)) + g.curDecl = "" return } @@ -219,6 +223,7 @@ func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) { } types.ResumeCheckSize() + g.curDecl = "" if otyp, ok := otyp.(*types2.Named); ok && otyp.NumMethods() != 0 { methods := make([]*types.Field, otyp.NumMethods()) for i := range methods { @@ -229,6 +234,7 @@ func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) { meth := g.obj(m) methods[i] = types.NewField(meth.Pos(), g.selector(m), meth.Type()) methods[i].Nname = meth + g.curDecl = "" } ntyp.Methods().Set(methods) } diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go index fa24ab1844..4f6d828720 100644 --- a/src/cmd/compile/internal/noder/types.go +++ b/src/cmd/compile/internal/noder/types.go @@ -229,6 +229,7 @@ func (g *irgen) typ0(typ types2.Type) *types.Type { pkg := g.tpkg(typ) // Create the unique types1 name for a type param, using its context with a // function, type, or method declaration. + assert(g.curDecl != "") nm := g.curDecl + "." + typ.Obj().Name() sym := pkg.Lookup(nm) if sym.Def != nil { @@ -331,11 +332,15 @@ func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) { tparams := make([]*types.Type, rparams.Len()) // Set g.curDecl to be the method context, so type // params in the receiver of the method that we are - // translating gets the right unique name. + // translating gets the right unique name. We could + // be in a top-level typeDecl, so save and restore + // the current contents of g.curDecl. + savedCurDecl := g.curDecl g.curDecl = typ.Obj().Name() + "." + m.Name() for i := range tparams { tparams[i] = g.typ1(rparams.At(i)) } + g.curDecl = savedCurDecl assert(len(tparams) == len(targs)) ts := typecheck.Tsubster{ Tparams: tparams, diff --git a/test/typeparam/issue49893.dir/a.go b/test/typeparam/issue49893.dir/a.go new file mode 100644 index 0000000000..bc810cd3dd --- /dev/null +++ b/test/typeparam/issue49893.dir/a.go @@ -0,0 +1,15 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type Option[T any] interface { + ToSeq() Seq[T] +} + +type Seq[T any] []T + +func (r Seq[T]) Find(p func(v T) bool) Option[T] { + panic("") +} diff --git a/test/typeparam/issue49893.dir/b.go b/test/typeparam/issue49893.dir/b.go new file mode 100644 index 0000000000..b36f6bddf0 --- /dev/null +++ b/test/typeparam/issue49893.dir/b.go @@ -0,0 +1,15 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package b + +import "a" + +type Ap1[A, B any] struct { + opt a.Option[A] +} + +type Ap2[A, B any] struct { + opt a.Option[A] +} diff --git a/test/typeparam/issue49893.dir/main.go b/test/typeparam/issue49893.dir/main.go new file mode 100644 index 0000000000..8b5b3bdad7 --- /dev/null +++ b/test/typeparam/issue49893.dir/main.go @@ -0,0 +1,15 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "b" + "fmt" +) + +func main() { + opt := b.Ap1[string, string]{} + fmt.Println(opt) +} diff --git a/test/typeparam/issue49893.go b/test/typeparam/issue49893.go new file mode 100644 index 0000000000..87b4ff46c1 --- /dev/null +++ b/test/typeparam/issue49893.go @@ -0,0 +1,7 @@ +// compiledir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From 28ec0fdeb500b4d0ab5c0ac07cba2f5ebc12ae32 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Wed, 1 Dec 2021 13:41:45 -0500 Subject: [PATCH 2372/2500] runtime: print errno on clock_gettime failure on OpenBSD For #49532. Change-Id: I5afc64c987f0519903128550a7dac3a0f5e592cf Reviewed-on: https://go-review.googlesource.com/c/go/+/368334 Trust: Austin Clements Run-TryBot: Austin Clements Reviewed-by: Joel Sing Reviewed-by: Cherry Mui --- src/runtime/sys_openbsd2.go | 16 ++++++++++++++-- src/runtime/sys_openbsd_386.s | 7 +++++-- src/runtime/sys_openbsd_amd64.s | 7 +++++-- src/runtime/sys_openbsd_arm.s | 8 +++++--- src/runtime/sys_openbsd_arm64.s | 8 +++++--- 5 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/runtime/sys_openbsd2.go b/src/runtime/sys_openbsd2.go index a7786fe65a..4d50b4f6b1 100644 --- a/src/runtime/sys_openbsd2.go +++ b/src/runtime/sys_openbsd2.go @@ -174,7 +174,13 @@ func nanotime1() int64 { clock_id int32 tp unsafe.Pointer }{_CLOCK_MONOTONIC, unsafe.Pointer(&ts)} - libcCall(unsafe.Pointer(abi.FuncPCABI0(clock_gettime_trampoline)), unsafe.Pointer(&args)) + if errno := libcCall(unsafe.Pointer(abi.FuncPCABI0(clock_gettime_trampoline)), unsafe.Pointer(&args)); errno < 0 { + // Avoid growing the nosplit stack. + systemstack(func() { + println("runtime: errno", -errno) + throw("clock_gettime failed") + }) + } return ts.tv_sec*1e9 + int64(ts.tv_nsec) } func clock_gettime_trampoline() @@ -186,7 +192,13 @@ func walltime() (int64, int32) { clock_id int32 tp unsafe.Pointer }{_CLOCK_REALTIME, unsafe.Pointer(&ts)} - libcCall(unsafe.Pointer(abi.FuncPCABI0(clock_gettime_trampoline)), unsafe.Pointer(&args)) + if errno := libcCall(unsafe.Pointer(abi.FuncPCABI0(clock_gettime_trampoline)), unsafe.Pointer(&args)); errno < 0 { + // Avoid growing the nosplit stack. + systemstack(func() { + println("runtime: errno", -errno) + throw("clock_gettime failed") + }) + } return ts.tv_sec, int32(ts.tv_nsec) } diff --git a/src/runtime/sys_openbsd_386.s b/src/runtime/sys_openbsd_386.s index 7830b61b7d..890b96b673 100644 --- a/src/runtime/sys_openbsd_386.s +++ b/src/runtime/sys_openbsd_386.s @@ -520,8 +520,11 @@ TEXT runtime·clock_gettime_trampoline(SB),NOSPLIT,$0 MOVL BX, 4(SP) // arg 2 - clock_id CALL libc_clock_gettime(SB) CMPL AX, $-1 - JNE 2(PC) - MOVL $0xf1, 0xf1 // crash on failure + JNE noerr + CALL libc_errno(SB) + MOVL (AX), AX + NEGL AX // caller expects negative errno +noerr: MOVL BP, SP POPL BP RET diff --git a/src/runtime/sys_openbsd_amd64.s b/src/runtime/sys_openbsd_amd64.s index fc89ee6cbb..fc6d5dc387 100644 --- a/src/runtime/sys_openbsd_amd64.s +++ b/src/runtime/sys_openbsd_amd64.s @@ -369,8 +369,11 @@ TEXT runtime·clock_gettime_trampoline(SB),NOSPLIT,$0 MOVL 0(DI), DI // arg 1 clock_id CALL libc_clock_gettime(SB) TESTL AX, AX - JEQ 2(PC) - MOVL $0xf1, 0xf1 // crash + JEQ noerr + CALL libc_errno(SB) + MOVL (AX), AX // errno + NEGL AX // caller expects negative errno value +noerr: POPQ BP RET diff --git a/src/runtime/sys_openbsd_arm.s b/src/runtime/sys_openbsd_arm.s index 143fcf0518..a9cb1fbafe 100644 --- a/src/runtime/sys_openbsd_arm.s +++ b/src/runtime/sys_openbsd_arm.s @@ -407,9 +407,11 @@ TEXT runtime·clock_gettime_trampoline(SB),NOSPLIT,$0 MOVW 0(R0), R0 // arg 1 clock_id BL libc_clock_gettime(SB) CMP $-1, R0 - BNE 3(PC) - MOVW $0, R8 // crash on failure - MOVW R8, (R8) + BNE noerr + BL libc_errno(SB) + MOVW (R0), R0 // errno + RSB.CS $0, R0 // caller expects negative errno +noerr: MOVW R9, R13 RET diff --git a/src/runtime/sys_openbsd_arm64.s b/src/runtime/sys_openbsd_arm64.s index 9b4acc90a5..3fa7e1ede2 100644 --- a/src/runtime/sys_openbsd_arm64.s +++ b/src/runtime/sys_openbsd_arm64.s @@ -359,9 +359,11 @@ TEXT runtime·clock_gettime_trampoline(SB),NOSPLIT,$0 MOVD 0(R0), R0 // arg 1 - clock_id CALL libc_clock_gettime(SB) CMP $-1, R0 - BNE 3(PC) - MOVD $0, R0 // crash on failure - MOVD R0, (R0) + BNE noerr + CALL libc_errno(SB) + MOVW (R0), R0 // errno + NEG R0, R0 // caller expects negative errno value +noerr: RET TEXT runtime·fcntl_trampoline(SB),NOSPLIT,$0 -- GitLab From 36be0beb05043e8ef3b8d108e9f8977b5eac0c87 Mon Sep 17 00:00:00 2001 From: Changkun Ou Date: Thu, 2 Dec 2021 16:01:09 +0100 Subject: [PATCH 2373/2500] misc/ios: bump min version For #48076 Change-Id: I5edaa43af82c3478555c309a001a3d1b16de3d64 Reviewed-on: https://go-review.googlesource.com/c/go/+/368615 Run-TryBot: Cherry Mui Reviewed-by: Cherry Mui Reviewed-by: Dmitri Shuralyov Reviewed-by: Roland Shoemaker TryBot-Result: Gopher Robot --- misc/ios/clangwrap.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc/ios/clangwrap.sh b/misc/ios/clangwrap.sh index dca3fcc904..8f7b439315 100755 --- a/misc/ios/clangwrap.sh +++ b/misc/ios/clangwrap.sh @@ -17,4 +17,4 @@ export IPHONEOS_DEPLOYMENT_TARGET=5.1 # cmd/cgo doesn't support llvm-gcc-4.2, so we have to use clang. CLANG=`xcrun --sdk $SDK --find clang` -exec "$CLANG" -arch $CLANGARCH -isysroot "$SDK_PATH" -m${PLATFORM}-version-min=10.0 "$@" +exec "$CLANG" -arch $CLANGARCH -isysroot "$SDK_PATH" -m${PLATFORM}-version-min=12.0 "$@" -- GitLab From c5c1955077cb94736b0f311b3a02419d166f45ac Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Wed, 1 Dec 2021 15:26:31 +0000 Subject: [PATCH 2374/2500] runtime: break out new minimum heap size into a goexperiment The new minimum heap of 512 KiB has been the cause of some build slowdown (~1%) and microbenchmark slowdown (usually ~0%, up to ~50%) because of two reasons: 1. Applications with lots of small short-lived processes execute many more GC cycles. 2. Applications with heaps <4 MiB GC up to 8x more often. In many ways these consequences are inevitable given how GOGC works, however we need to investigate more as to whether the apparent slowdowns are indeed unavoidable or if the GC has issues scaling down, which it's too late for for this release. Given that this release is already huge, it's OK to push this back. We'll take a closer look at it next cycle, so place block it behind a new goexperiment to allow users and ourselves to easily experiment with it. Fixes #49744. Updates #44167. Change-Id: Ibad51f7873de7517490c89802f3c593834e77ff0 Reviewed-on: https://go-review.googlesource.com/c/go/+/368137 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Gopher Robot Reviewed-by: Austin Clements Reviewed-by: David Chase --- src/internal/goexperiment/exp_heapminimum512kib_off.go | 9 +++++++++ src/internal/goexperiment/exp_heapminimum512kib_on.go | 9 +++++++++ src/internal/goexperiment/flags.go | 7 +++++++ src/runtime/mgcpacer.go | 4 ++-- 4 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 src/internal/goexperiment/exp_heapminimum512kib_off.go create mode 100644 src/internal/goexperiment/exp_heapminimum512kib_on.go diff --git a/src/internal/goexperiment/exp_heapminimum512kib_off.go b/src/internal/goexperiment/exp_heapminimum512kib_off.go new file mode 100644 index 0000000000..09da431b40 --- /dev/null +++ b/src/internal/goexperiment/exp_heapminimum512kib_off.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.heapminimum512kib +// +build !goexperiment.heapminimum512kib + +package goexperiment + +const HeapMinimum512KiB = false +const HeapMinimum512KiBInt = 0 diff --git a/src/internal/goexperiment/exp_heapminimum512kib_on.go b/src/internal/goexperiment/exp_heapminimum512kib_on.go new file mode 100644 index 0000000000..bab684b5e6 --- /dev/null +++ b/src/internal/goexperiment/exp_heapminimum512kib_on.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.heapminimum512kib +// +build goexperiment.heapminimum512kib + +package goexperiment + +const HeapMinimum512KiB = true +const HeapMinimum512KiBInt = 1 diff --git a/src/internal/goexperiment/flags.go b/src/internal/goexperiment/flags.go index 3bf19222e1..6d935edc2b 100644 --- a/src/internal/goexperiment/flags.go +++ b/src/internal/goexperiment/flags.go @@ -89,4 +89,11 @@ type Flags struct { // Details regarding the new pacer may be found at // https://golang.org/design/44167-gc-pacer-redesign PacerRedesign bool + + // HeapMinimum512KiB reduces the minimum heap size to 512 KiB. + // + // This was originally reduced as part of PacerRedesign, but + // has been broken out to its own experiment that is disabled + // by default. + HeapMinimum512KiB bool } diff --git a/src/runtime/mgcpacer.go b/src/runtime/mgcpacer.go index 868666036c..6df8af45a8 100644 --- a/src/runtime/mgcpacer.go +++ b/src/runtime/mgcpacer.go @@ -53,8 +53,8 @@ const ( gcOverAssistWork = 64 << 10 // defaultHeapMinimum is the value of heapMinimum for GOGC==100. - defaultHeapMinimum = goexperiment.PacerRedesignInt*(512<<10) + - (1-goexperiment.PacerRedesignInt)*(4<<20) + defaultHeapMinimum = (goexperiment.HeapMinimum512KiBInt)*(512<<10) + + (1-goexperiment.HeapMinimum512KiBInt)*(4<<20) // scannableStackSizeSlack is the bytes of stack space allocated or freed // that can accumulate on a P before updating gcController.stackSize. -- GitLab From 469f030dcaad765b3a40b2e0a88f4000357e61be Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Thu, 2 Dec 2021 12:36:28 -0500 Subject: [PATCH 2375/2500] all: update vendored golang.org/x/tools Update the vendored x/tools to pick up CL 364678, which updates vet analyzers following a change to the underlying of type parameters. This also pulls in significant changes to the typeutil package to support new constructs in typeutil.Map, but this is not used by vet. The following commands were used: go get -d golang.org/x/tools@e212aff8fd146c44ddb0167c1dfbd5531d6c9213 go mod tidy go mod vendor Fixes #49855 Change-Id: I3ffc59f3693710c83b81d390999aeabc8043723b Reviewed-on: https://go-review.googlesource.com/c/go/+/368774 Trust: Robert Findley Reviewed-by: Dmitri Shuralyov Reviewed-by: Robert Griesemer Run-TryBot: Dmitri Shuralyov TryBot-Result: Gopher Robot --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 +- .../tools/go/analysis/passes/printf/printf.go | 8 +- .../tools/go/analysis/passes/printf/types.go | 6 +- .../x/tools/go/types/typeutil/map.go | 138 +++++++++++++++++- .../x/tools/internal/typeparams/common.go | 7 + .../x/tools/internal/typeparams/normalize.go | 38 ++++- .../internal/typeparams/typeparams_go117.go | 1 + src/cmd/vendor/modules.txt | 2 +- 9 files changed, 187 insertions(+), 19 deletions(-) diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 75a93e6bd1..833c7d7b1f 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -8,7 +8,7 @@ require ( golang.org/x/mod v0.6.0-dev.0.20211102181907-3a5865c02020 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 - golang.org/x/tools v0.1.8-0.20211116011028-4adea5033c5c + golang.org/x/tools v0.1.8-0.20211202032535-e212aff8fd14 ) require ( diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 62619b8d01..0d39656a1d 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -18,7 +18,7 @@ golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e h1:i6Vklmyu+fZMFYpum+sR4ZWAB golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/tools v0.1.8-0.20211116011028-4adea5033c5c h1:EftGXIEk7/EwE5R+/azXJzSbzwNumuLeH9oupAN7YV0= -golang.org/x/tools v0.1.8-0.20211116011028-4adea5033c5c/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.8-0.20211202032535-e212aff8fd14 h1:KPFD5zp3T4bZL/kdosp4tGDJ6DKwUmYSWM0twy7w/bg= +golang.org/x/tools v0.1.8-0.20211202032535-e212aff8fd14/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go index 0206073578..dee37d78ae 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go @@ -25,6 +25,7 @@ import ( "golang.org/x/tools/go/analysis/passes/internal/analysisutil" "golang.org/x/tools/go/ast/inspector" "golang.org/x/tools/go/types/typeutil" + "golang.org/x/tools/internal/typeparams" ) func init() { @@ -520,7 +521,12 @@ func printfNameAndKind(pass *analysis.Pass, call *ast.CallExpr) (fn *types.Func, func isFormatter(typ types.Type) bool { // If the type is an interface, the value it holds might satisfy fmt.Formatter. if _, ok := typ.Underlying().(*types.Interface); ok { - return true + // Don't assume type parameters could be formatters. With the greater + // expressiveness of constraint interface syntax we expect more type safety + // when using type parameters. + if !typeparams.IsTypeParam(typ) { + return true + } } obj, _, _ := types.LookupFieldOrMethod(typ, false, nil, "Format") fn, ok := obj.(*types.Func) diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/types.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/types.go index 81bf36e1ee..270e917c80 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/types.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/types.go @@ -178,10 +178,12 @@ func (m *argMatcher) match(typ types.Type, topLevel bool) bool { return true } + if typeparams.IsTypeParam(typ.Elem()) { + return true // We don't know whether the logic below applies. Give up. + } + under := typ.Elem().Underlying() switch under.(type) { - case *typeparams.TypeParam: - return true // We don't know whether the logic below applies. Give up. case *types.Struct: // see below case *types.Array: // see below case *types.Slice: // see below diff --git a/src/cmd/vendor/golang.org/x/tools/go/types/typeutil/map.go b/src/cmd/vendor/golang.org/x/tools/go/types/typeutil/map.go index c7f7545006..490ee904a6 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/types/typeutil/map.go +++ b/src/cmd/vendor/golang.org/x/tools/go/types/typeutil/map.go @@ -11,6 +11,8 @@ import ( "fmt" "go/types" "reflect" + + "golang.org/x/tools/internal/typeparams" ) // Map is a hash-table-based mapping from types (types.Type) to @@ -211,11 +213,29 @@ func (m *Map) KeysString() string { // Call MakeHasher to create a Hasher. type Hasher struct { memo map[types.Type]uint32 + + // ptrMap records pointer identity. + ptrMap map[interface{}]uint32 + + // sigTParams holds type parameters from the signature being hashed. + // Signatures are considered identical modulo renaming of type parameters, so + // within the scope of a signature type the identity of the signature's type + // parameters is just their index. + // + // Since the language does not currently support referring to uninstantiated + // generic types or functions, and instantiated signatures do not have type + // parameter lists, we should never encounter a second non-empty type + // parameter list when hashing a generic signature. + sigTParams *typeparams.TypeParamList } // MakeHasher returns a new Hasher instance. func MakeHasher() Hasher { - return Hasher{make(map[types.Type]uint32)} + return Hasher{ + memo: make(map[types.Type]uint32), + ptrMap: make(map[interface{}]uint32), + sigTParams: nil, + } } // Hash computes a hash value for the given type t such that @@ -273,17 +293,62 @@ func (h Hasher) hashFor(t types.Type) uint32 { if t.Variadic() { hash *= 8863 } + + // Use a separate hasher for types inside of the signature, where type + // parameter identity is modified to be (index, constraint). We must use a + // new memo for this hasher as type identity may be affected by this + // masking. For example, in func[T any](*T), the identity of *T depends on + // whether we are mapping the argument in isolation, or recursively as part + // of hashing the signature. + // + // We should never encounter a generic signature while hashing another + // generic signature, but defensively set sigTParams only if h.mask is + // unset. + tparams := typeparams.ForSignature(t) + if h.sigTParams == nil && tparams.Len() != 0 { + h = Hasher{ + // There may be something more efficient than discarding the existing + // memo, but it would require detecting whether types are 'tainted' by + // references to type parameters. + memo: make(map[types.Type]uint32), + // Re-using ptrMap ensures that pointer identity is preserved in this + // hasher. + ptrMap: h.ptrMap, + sigTParams: tparams, + } + } + + for i := 0; i < tparams.Len(); i++ { + tparam := tparams.At(i) + hash += 7 * h.Hash(tparam.Constraint()) + } + return hash + 3*h.hashTuple(t.Params()) + 5*h.hashTuple(t.Results()) + case *typeparams.Union: + return h.hashUnion(t) + case *types.Interface: + // Interfaces are identical if they have the same set of methods, with + // identical names and types, and they have the same set of type + // restrictions. See go/types.identical for more details. var hash uint32 = 9103 + + // Hash methods. for i, n := 0, t.NumMethods(); i < n; i++ { - // See go/types.identicalMethods for rationale. // Method order is not significant. // Ignore m.Pkg(). m := t.Method(i) hash += 3*hashString(m.Name()) + 5*h.Hash(m.Type()) } + + // Hash type restrictions. + terms, err := typeparams.InterfaceTermSet(t) + // if err != nil t has invalid type restrictions. + if err == nil { + hash += h.hashTermSet(terms) + } + return hash case *types.Map: @@ -293,13 +358,22 @@ func (h Hasher) hashFor(t types.Type) uint32 { return 9127 + 2*uint32(t.Dir()) + 3*h.Hash(t.Elem()) case *types.Named: - // Not safe with a copying GC; objects may move. - return uint32(reflect.ValueOf(t.Obj()).Pointer()) + hash := h.hashPtr(t.Obj()) + targs := typeparams.NamedTypeArgs(t) + for i := 0; i < targs.Len(); i++ { + targ := targs.At(i) + hash += 2 * h.Hash(targ) + } + return hash + + case *typeparams.TypeParam: + return h.hashTypeParam(t) case *types.Tuple: return h.hashTuple(t) } - panic(t) + + panic(fmt.Sprintf("%T: %v", t, t)) } func (h Hasher) hashTuple(tuple *types.Tuple) uint32 { @@ -311,3 +385,57 @@ func (h Hasher) hashTuple(tuple *types.Tuple) uint32 { } return hash } + +func (h Hasher) hashUnion(t *typeparams.Union) uint32 { + // Hash type restrictions. + terms, err := typeparams.UnionTermSet(t) + // if err != nil t has invalid type restrictions. Fall back on a non-zero + // hash. + if err != nil { + return 9151 + } + return h.hashTermSet(terms) +} + +func (h Hasher) hashTermSet(terms []*typeparams.Term) uint32 { + var hash uint32 = 9157 + 2*uint32(len(terms)) + for _, term := range terms { + // term order is not significant. + termHash := h.Hash(term.Type()) + if term.Tilde() { + termHash *= 9161 + } + hash += 3 * termHash + } + return hash +} + +// hashTypeParam returns a hash of the type parameter t, with a hash value +// depending on whether t is contained in h.sigTParams. +// +// If h.sigTParams is set and contains t, then we are in the process of hashing +// a signature, and the hash value of t must depend only on t's index and +// constraint: signatures are considered identical modulo type parameter +// renaming. +// +// Otherwise the hash of t depends only on t's pointer identity. +func (h Hasher) hashTypeParam(t *typeparams.TypeParam) uint32 { + if h.sigTParams != nil { + i := t.Index() + if i >= 0 && i < h.sigTParams.Len() && t == h.sigTParams.At(i) { + return 9173 + 2*h.Hash(t.Constraint()) + 3*uint32(i) + } + } + return h.hashPtr(t.Obj()) +} + +// hashPtr hashes the pointer identity of ptr. It uses h.ptrMap to ensure that +// pointers values are not dependent on the GC. +func (h Hasher) hashPtr(ptr interface{}) uint32 { + if hash, ok := h.ptrMap[ptr]; ok { + return hash + } + hash := uint32(reflect.ValueOf(ptr).Pointer()) + h.ptrMap[ptr] = hash + return hash +} diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/common.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/common.go index 9fc6b4beb8..961d036fdb 100644 --- a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/common.go +++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/common.go @@ -13,6 +13,7 @@ package typeparams import ( "go/ast" "go/token" + "go/types" ) // A IndexExprData holds data from both ast.IndexExpr and the new @@ -23,3 +24,9 @@ type IndexExprData struct { Indices []ast.Expr // index expressions Rbrack token.Pos // position of "]" } + +// IsTypeParam reports whether t is a type parameter. +func IsTypeParam(t types.Type) bool { + _, ok := t.(*TypeParam) + return ok +} diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/normalize.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/normalize.go index f41ec6ec0b..090f142a5f 100644 --- a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/normalize.go +++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/normalize.go @@ -23,9 +23,9 @@ var ErrEmptyTypeSet = errors.New("empty type set") // // Structural type restrictions of a type parameter are created via // non-interface types embedded in its constraint interface (directly, or via a -// chain of interface embeddings). For example, in the declaration `type T[P -// interface{~int; m()}] int`, the structural restriction of the type parameter -// P is ~int. +// chain of interface embeddings). For example, in the declaration +// type T[P interface{~int; m()}] int +// the structural restriction of the type parameter P is ~int. // // With interface embedding and unions, the specification of structural type // restrictions may be arbitrarily complex. For example, consider the @@ -67,7 +67,31 @@ func StructuralTerms(tparam *TypeParam) ([]*Term, error) { if iface == nil { return nil, fmt.Errorf("constraint is %T, not *types.Interface", constraint.Underlying()) } - tset, err := computeTermSet(iface, make(map[types.Type]*termSet), 0) + return InterfaceTermSet(iface) +} + +// InterfaceTermSet computes the normalized terms for a constraint interface, +// returning an error if the term set cannot be computed or is empty. In the +// latter case, the error will be ErrEmptyTypeSet. +// +// See the documentation of StructuralTerms for more information on +// normalization. +func InterfaceTermSet(iface *types.Interface) ([]*Term, error) { + return computeTermSet(iface) +} + +// UnionTermSet computes the normalized terms for a union, returning an error +// if the term set cannot be computed or is empty. In the latter case, the +// error will be ErrEmptyTypeSet. +// +// See the documentation of StructuralTerms for more information on +// normalization. +func UnionTermSet(union *Union) ([]*Term, error) { + return computeTermSet(union) +} + +func computeTermSet(typ types.Type) ([]*Term, error) { + tset, err := computeTermSetInternal(typ, make(map[types.Type]*termSet), 0) if err != nil { return nil, err } @@ -98,7 +122,7 @@ func indentf(depth int, format string, args ...interface{}) { fmt.Fprintf(os.Stderr, strings.Repeat(".", depth)+format+"\n", args...) } -func computeTermSet(t types.Type, seen map[types.Type]*termSet, depth int) (res *termSet, err error) { +func computeTermSetInternal(t types.Type, seen map[types.Type]*termSet, depth int) (res *termSet, err error) { if t == nil { panic("nil type") } @@ -139,7 +163,7 @@ func computeTermSet(t types.Type, seen map[types.Type]*termSet, depth int) (res if _, ok := embedded.Underlying().(*TypeParam); ok { return nil, fmt.Errorf("invalid embedded type %T", embedded) } - tset2, err := computeTermSet(embedded, seen, depth+1) + tset2, err := computeTermSetInternal(embedded, seen, depth+1) if err != nil { return nil, err } @@ -153,7 +177,7 @@ func computeTermSet(t types.Type, seen map[types.Type]*termSet, depth int) (res var terms termlist switch t.Type().Underlying().(type) { case *types.Interface: - tset2, err := computeTermSet(t.Type(), seen, depth+1) + tset2, err := computeTermSetInternal(t.Type(), seen, depth+1) if err != nil { return nil, err } diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go index 6ad3a43a2c..e509daf7be 100644 --- a/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go +++ b/src/cmd/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go @@ -75,6 +75,7 @@ func ForFuncType(*ast.FuncType) *ast.FieldList { // this Go version. Its methods panic on use. type TypeParam struct{ types.Type } +func (*TypeParam) Index() int { unsupported(); return 0 } func (*TypeParam) Constraint() types.Type { unsupported(); return nil } func (*TypeParam) Obj() *types.TypeName { unsupported(); return nil } diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index fd955a6932..0c107cd5ea 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -51,7 +51,7 @@ golang.org/x/sys/windows # golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 ## explicit; go 1.17 golang.org/x/term -# golang.org/x/tools v0.1.8-0.20211116011028-4adea5033c5c +# golang.org/x/tools v0.1.8-0.20211202032535-e212aff8fd14 ## explicit; go 1.17 golang.org/x/tools/cover golang.org/x/tools/go/analysis -- GitLab From 3c6295d272d09e6c7be912510e4b62afc0ef8ffc Mon Sep 17 00:00:00 2001 From: Jeremy Faller Date: Fri, 19 Nov 2021 16:51:47 -0500 Subject: [PATCH 2376/2500] doc/go1.18: add short-circuit evaluation for text/template This description is based on https://golang.org/cl/321490. Updates #47694 Change-Id: I48656cd487d2fccf0b0d3390f350f1bc6f2b0080 Reviewed-on: https://go-review.googlesource.com/c/go/+/365738 Trust: Jeremy Faller Trust: Dmitri Shuralyov Run-TryBot: Jeremy Faller TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor Reviewed-by: Dmitri Shuralyov --- doc/go1.18.html | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index d9da160ab5..74d0e0c23e 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -290,7 +290,7 @@ proposal.
    bufio

    - The new Writer.AvailableBuffer + The new Writer.AvailableBuffer method returns an empty buffer with a possibly non-empty capacity for use with append-like APIs. After appending, the buffer can be provided to a succeeding Write call and possibly avoid any copying. @@ -517,7 +517,11 @@ proposal.

    text/template

    - TODO: https://golang.org/cl/321490: implement short-circuit and, or + The and function no longer always evaluates all arguments; it + stops evaluating arguments after the first argument that evaluates to + false. Similarly, the or function now stops evaluating + arguments after the first argument that evaluates to true. This makes a + difference if any of the arguments is a function call.

    -- GitLab From bbe1be5c19f04816f5f9162c2be75351480c92a0 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 29 Nov 2021 11:45:17 -0800 Subject: [PATCH 2377/2500] cmd/compile: report channel size errors correctly for -G=3 First, we need to set base.Pos in varDecl() and typeDecl(), so it will be correct if we need to report type size errors while converting types. Changed error calls in types/sizes.go to use Errorf, not ErrorfAt, since we want to use base.Pos (which will set from t.Pos(), if that is available). Second, we need to add an extra call CalcSize(t1.Elem()) in the TCHANARGS case of CalcSize(). We can use CalcSize() rather than CheckSize(), since we know the top-level recursive type will have been calculated by the time we process the fake TCHANARGS type. In -G=0 mode, the size of the channel element has often been calculated because of some other processing (but not in the case of #49767). But in -G=3 mode, we just calculate sizes during the single noder2 pass, so we are more likely to have not gotten to calculating the size of the element yet, depending on the order of processing of the deferredTypeStack. Fixes the tests fixedbugs/issue{42058a,42058b}.go that were disabled for -G=3 mode. Had to add exceptions in stdlib_test.go for go/types and types2, because the types2 typechecker does not know about type size limits. Fixes #49814 Fixes #49771 Updates #49767 Change-Id: I77d058e8ceff68a58c4c386a8cf46799c54b04c3 Reviewed-on: https://go-review.googlesource.com/c/go/+/367955 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Gopher Robot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/decl.go | 4 ++++ src/cmd/compile/internal/types/size.go | 15 ++++++++++----- src/cmd/compile/internal/types2/stdlib_test.go | 2 ++ src/go/types/stdlib_test.go | 2 ++ test/fixedbugs/issue49767.go | 12 ++++++++++++ test/fixedbugs/issue49814.go | 14 ++++++++++++++ test/run.go | 15 ++++++++------- 7 files changed, 52 insertions(+), 12 deletions(-) create mode 100644 test/fixedbugs/issue49767.go create mode 100644 test/fixedbugs/issue49814.go diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go index 027c8598fd..b7fd95e2e8 100644 --- a/src/cmd/compile/internal/noder/decl.go +++ b/src/cmd/compile/internal/noder/decl.go @@ -160,6 +160,8 @@ func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) { } func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) { + // Set the position for any error messages we might print (e.g. too large types). + base.Pos = g.pos(decl) assert(g.curDecl == "") // Set g.curDecl to the type name, as context for the type params declared // during types2-to-types1 translation if this is a generic type. @@ -244,6 +246,8 @@ func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) { func (g *irgen) varDecl(out *ir.Nodes, decl *syntax.VarDecl) { pos := g.pos(decl) + // Set the position for any error messages we might print (e.g. too large types). + base.Pos = pos names := make([]*ir.Name, len(decl.NameList)) for i, name := range decl.NameList { names[i], _ = g.def(name) diff --git a/src/cmd/compile/internal/types/size.go b/src/cmd/compile/internal/types/size.go index 0f3db06c1d..fb6accdc64 100644 --- a/src/cmd/compile/internal/types/size.go +++ b/src/cmd/compile/internal/types/size.go @@ -450,16 +450,21 @@ func CalcSize(t *Type) { CheckSize(t.Elem()) - // make fake type to check later to - // trigger channel argument check. + // Make fake type to trigger channel element size check after + // any top-level recursive type has been completed. t1 := NewChanArgs(t) CheckSize(t1) case TCHANARGS: t1 := t.ChanArgs() CalcSize(t1) // just in case + // Make sure size of t1.Elem() is calculated at this point. We can + // use CalcSize() here rather than CheckSize(), because the top-level + // (possibly recursive) type will have been calculated before the fake + // chanargs is handled. + CalcSize(t1.Elem()) if t1.Elem().width >= 1<<16 { - base.ErrorfAt(typePos(t1), "channel element type too large (>64kB)") + base.Errorf("channel element type too large (>64kB)") } w = 1 // anything will do @@ -492,7 +497,7 @@ func CalcSize(t *Type) { if t.Elem().width != 0 { cap := (uint64(MaxWidth) - 1) / uint64(t.Elem().width) if uint64(t.NumElem()) > cap { - base.ErrorfAt(typePos(t), "type %L larger than address space", t) + base.Errorf("type %L larger than address space", t) } } w = t.NumElem() * t.Elem().width @@ -539,7 +544,7 @@ func CalcSize(t *Type) { } if PtrSize == 4 && w != int64(int32(w)) { - base.ErrorfAt(typePos(t), "type %v too large", t) + base.Errorf("type %v too large", t) } t.width = w diff --git a/src/cmd/compile/internal/types2/stdlib_test.go b/src/cmd/compile/internal/types2/stdlib_test.go index 9c22f01673..5ac01ac253 100644 --- a/src/cmd/compile/internal/types2/stdlib_test.go +++ b/src/cmd/compile/internal/types2/stdlib_test.go @@ -194,6 +194,8 @@ func TestStdFixed(t *testing.T) { "issue42058b.go", // types2 does not have constraints on channel element size "issue48097.go", // go/types doesn't check validity of //go:xxx directives, and non-init bodyless function "issue48230.go", // go/types doesn't check validity of //go:xxx directives + "issue49767.go", // go/types does not have constraints on channel element size + "issue49814.go", // go/types does not have constraints on array size ) } diff --git a/src/go/types/stdlib_test.go b/src/go/types/stdlib_test.go index b0d7fdd3d9..c56e0ba428 100644 --- a/src/go/types/stdlib_test.go +++ b/src/go/types/stdlib_test.go @@ -196,6 +196,8 @@ func TestStdFixed(t *testing.T) { "issue42058b.go", // go/types does not have constraints on channel element size "issue48097.go", // go/types doesn't check validity of //go:xxx directives, and non-init bodyless function "issue48230.go", // go/types doesn't check validity of //go:xxx directives + "issue49767.go", // go/types does not have constraints on channel element size + "issue49814.go", // go/types does not have constraints on array size ) } diff --git a/test/fixedbugs/issue49767.go b/test/fixedbugs/issue49767.go new file mode 100644 index 0000000000..e25081dc93 --- /dev/null +++ b/test/fixedbugs/issue49767.go @@ -0,0 +1,12 @@ +// errorcheck + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func main() { + ch := make(chan struct{ v [65536]byte }) // ERROR "channel element type too large" + close(ch) +} diff --git a/test/fixedbugs/issue49814.go b/test/fixedbugs/issue49814.go new file mode 100644 index 0000000000..fd487d8ccb --- /dev/null +++ b/test/fixedbugs/issue49814.go @@ -0,0 +1,14 @@ +// errorcheck -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +// "must be integer" error is for 32-bit architectures +type V [1 << 50]byte // ERROR "larger than address space|must be integer" + +var X [1 << 50]byte // ERROR "larger than address space|must be integer" + +func main() {} diff --git a/test/run.go b/test/run.go index bdc2f0a277..c6e82891da 100644 --- a/test/run.go +++ b/test/run.go @@ -2153,8 +2153,6 @@ var types2Failures = setOf( "fixedbugs/issue28268.go", // types2 reports follow-on errors "fixedbugs/issue31053.go", // types2 reports "unknown field" instead of "cannot refer to unexported field" "fixedbugs/issue33460.go", // types2 reports alternative positions in separate error - "fixedbugs/issue42058a.go", // types2 doesn't report "channel element type too large" - "fixedbugs/issue42058b.go", // types2 doesn't report "channel element type too large" "fixedbugs/issue4232.go", // types2 reports (correct) extra errors "fixedbugs/issue4452.go", // types2 reports (correct) extra errors "fixedbugs/issue4510.go", // types2 reports different (but ok) line numbers @@ -2171,7 +2169,6 @@ var types2Failures32Bit = setOf( "printbig.go", // large untyped int passed to print (32-bit) "fixedbugs/bug114.go", // large untyped int passed to println (32-bit) "fixedbugs/issue23305.go", // large untyped int passed to println (32-bit) - "fixedbugs/bug385_32.go", // types2 doesn't produce missing error "type .* too large" (32-bit specific) ) var g3Failures = setOf( @@ -2183,10 +2180,14 @@ var unifiedFailures = setOf( "escape4.go", // unified IR can inline f5 and f6; test doesn't expect this "inline.go", // unified IR reports function literal diagnostics on different lines than -d=inlfuncswithclosures - "fixedbugs/issue42284.go", // prints "T(0) does not escape", but test expects "a.I(a.T(0)) does not escape" - "fixedbugs/issue7921.go", // prints "… escapes to heap", but test expects "string(…) escapes to heap" - "typeparam/issue48538.go", // assertion failure, interprets struct key as closure variable - "typeparam/issue47631.go", // unified IR can handle local type declarations + "fixedbugs/issue42284.go", // prints "T(0) does not escape", but test expects "a.I(a.T(0)) does not escape" + "fixedbugs/issue7921.go", // prints "… escapes to heap", but test expects "string(…) escapes to heap" + "typeparam/issue48538.go", // assertion failure, interprets struct key as closure variable + "typeparam/issue47631.go", // unified IR can handle local type declarations + "fixedbugs/issue42058a.go", // unified IR doesn't report channel element too large + "fixedbugs/issue42058b.go", // unified IR doesn't report channel element too large + "fixedbugs/issue49767.go", // unified IR doesn't report channel element too large + "fixedbugs/issue49814.go", // unified IR doesn't report array type too large ) func setOf(keys ...string) map[string]bool { -- GitLab From d514411625bdd437c7d1997b92685bb03bfbf2a8 Mon Sep 17 00:00:00 2001 From: Jeremy Faller Date: Wed, 1 Dec 2021 12:44:04 -0500 Subject: [PATCH 2378/2500] doc/go1.18: add information on new pacer. This is based off Michael's notes. Updates #47694 Change-Id: I6e7944f85b776e8481829a2fafd177a49557c6ca Reviewed-on: https://go-review.googlesource.com/c/go/+/368156 Trust: Jeremy Faller Run-TryBot: Jeremy Faller TryBot-Result: Gopher Robot Reviewed-by: Michael Knyszek --- doc/go1.18.html | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/doc/go1.18.html b/doc/go1.18.html index 74d0e0c23e..285b44946e 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -200,6 +200,21 @@ proposal. into Win32 functions that block for extended periods of time.

    +

    + The garbage collector now includes non-heap sources of garbage collector work + (e.g., stack scanning) when determining how frequently to run. As a result, + garbage collector overhead is more predictable when these sources are + significant. For most applications these changes will be negligible; however, + some Go applications may now use less memory and spend more time on garbage + collection, or vice versa, than before. The intended workaround is to tweak + GOGC where necessary. +

    + +

    + The runtime now returns memory to the operating system more efficiently and has + been tuned to work more aggressively as a result. +

    +

    Compiler

    -- GitLab From d3bf627bc1e1a4959ecff797754e4a636aa6be1c Mon Sep 17 00:00:00 2001 From: Jeremy Faller Date: Wed, 1 Dec 2021 13:41:10 -0500 Subject: [PATCH 2379/2500] doc/go1.18: add constraints package documentation Updates #47694 Change-Id: I3239023dad194c317e271e6093eff2cfbed1a4b9 Reviewed-on: https://go-review.googlesource.com/c/go/+/368314 Trust: Jeremy Faller Run-TryBot: Jeremy Faller TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor --- doc/go1.18.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 285b44946e..6c246b8b7b 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -258,7 +258,9 @@ proposal.

    New constraints package

    - TODO: https://golang.org/cl/349709: constraints: new package + The new constraints package + defines a set of useful constraints that can be used with type parameters of + generic functions.

    New net/netip package

    -- GitLab From 94e22fa03eb5eb678689e05b8e309cd23f874698 Mon Sep 17 00:00:00 2001 From: Jeremy Faller Date: Wed, 1 Dec 2021 13:48:22 -0500 Subject: [PATCH 2380/2500] doc/go1.18: add Conn.NetConn documentation to crypto/tls section Updates #47694 Change-Id: Iead44baa8b2a06ecf7b92d343ed9117f0fc0793e Reviewed-on: https://go-review.googlesource.com/c/go/+/368315 Trust: Jeremy Faller Trust: Katie Hockman Run-TryBot: Jeremy Faller TryBot-Result: Gopher Robot Reviewed-by: Katie Hockman Reviewed-by: Ian Lance Taylor Reviewed-by: Agniva De Sarker --- doc/go1.18.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 6c246b8b7b..31aa17209f 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -341,7 +341,9 @@ proposal.
    crypto/tls

    - TODO: https://golang.org/cl/325250: add Conn.NetConn method + The new Conn.NetConn + method allows access to the underlying + net.Conn.

    -- GitLab From 25f06cb71f06406bd38de0a37967edc6ec8ca120 Mon Sep 17 00:00:00 2001 From: Jeremy Faller Date: Wed, 1 Dec 2021 13:56:53 -0500 Subject: [PATCH 2381/2500] doc/go1.18: add deprecation note for net.Error.Temporary Updates #47694 Change-Id: Ia25ad49f688efa3d60d83290095648711704b478 Reviewed-on: https://go-review.googlesource.com/c/go/+/368316 Trust: Jeremy Faller Run-TryBot: Jeremy Faller TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor --- doc/go1.18.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 31aa17209f..fb4d03151e 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -377,7 +377,7 @@ proposal.
    net

    - TODO: https://golang.org/cl/340261: deprecate (net.Error).Temporary + net.Error.Temporary has been deprecated.

    -- GitLab From c8c89d20ce206969ea48819af3ef0309299f9f6c Mon Sep 17 00:00:00 2001 From: Jeremy Faller Date: Wed, 1 Dec 2021 16:27:55 -0500 Subject: [PATCH 2382/2500] doc/go1.18: add docs on Cookie.Valid Updates #47694 Change-Id: Ibf3e25fbccf82e4abd7bd76b2ea6ceb4b05d4664 Reviewed-on: https://go-review.googlesource.com/c/go/+/368357 Trust: Jeremy Faller Run-TryBot: Jeremy Faller TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor --- doc/go1.18.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index fb4d03151e..a142115c22 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -390,8 +390,11 @@ proposal. Transport will now be correctly used, if specified, for making HTTP requests.

    +

    - TODO: https://golang.org/cl/338590: add Cookie.Valid method + The new + Cookie.Valid + method reports whether the cookie is valid.

    -- GitLab From bcb98f126bc3a12a63333069b669cb8aaf251b89 Mon Sep 17 00:00:00 2001 From: Jeremy Faller Date: Wed, 1 Dec 2021 16:33:33 -0500 Subject: [PATCH 2383/2500] doc/go1.18: add docs on User.GroupIds Cobbled up some release notes from: https://go-review.googlesource.com/c/go/+/330753/ Updates #47694 Change-Id: I249e4b96b7d51185b07c11a734505677e9e36315 Reviewed-on: https://go-review.googlesource.com/c/go/+/368358 Trust: Jeremy Faller Run-TryBot: Jeremy Faller Reviewed-by: Kirill Kolyshkin Reviewed-by: Ian Lance Taylor TryBot-Result: Gopher Robot --- doc/go1.18.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index a142115c22..b02bac13ba 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -402,7 +402,8 @@ proposal.
    os/user

    - TODO: https://golang.org/cl/330753: implement go native GroupIds + User.GroupIds. + now uses a Go native implementation when cgo is not available.

    -- GitLab From f9b2733e3a8b4911b932671b0bd9fc4190cf59aa Mon Sep 17 00:00:00 2001 From: Jeremy Faller Date: Wed, 1 Dec 2021 16:43:47 -0500 Subject: [PATCH 2384/2500] doc/go1.18: add docs on MapIter.Reset From: https://go-review.googlesource.com/c/go/+/321891 Updates #47694 Change-Id: I2cdd5d9f3da62a5690cd2ef921ed48957c602d64 Reviewed-on: https://go-review.googlesource.com/c/go/+/368360 Trust: Jeremy Faller Run-TryBot: Jeremy Faller TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor --- doc/go1.18.html | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index b02bac13ba..193ee16fb6 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -433,7 +433,13 @@ proposal.

    - TODO: https://golang.org/cl/321891: add MapIter.Reset + The new + MapIter.Reset + method changes its receiver to iterate over a + different map. The use of + MapIter.Reset + allows allocation-free iteration + over many maps.

    -- GitLab From e533b5793f43ed44f1562a10d974cb3bc3688226 Mon Sep 17 00:00:00 2001 From: Jeremy Faller Date: Wed, 1 Dec 2021 16:55:37 -0500 Subject: [PATCH 2385/2500] doc/go1.18: add docs on new reflect.Value methods From: https://go-review.googlesource.com/c/go/+/352131/ Updates #47694 Change-Id: I7c7811c49900049f5ef7fc906fe25d2ffd73c7b9 Reviewed-on: https://go-review.googlesource.com/c/go/+/368363 Trust: Jeremy Faller Run-TryBot: Jeremy Faller Reviewed-by: Keith Randall Reviewed-by: Fabio Falzoi Reviewed-by: Ian Lance Taylor TryBot-Result: Gopher Robot --- doc/go1.18.html | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 193ee16fb6..5692a068ab 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -447,7 +447,15 @@ proposal.

    - TODO: https://golang.org/cl/352131: add Value.{CanInt, CanUint, CanFloat, CanComplex} + A number of methods ( + Value.CanInt, + Value.CanUint, + Value.CanFloat, + Value.CanComplex + ) + have been added to + Value + to test if a conversion is safe.

    -- GitLab From 48e4284e551fceee7a45c11af791813782ca7e82 Mon Sep 17 00:00:00 2001 From: Jeremy Faller Date: Wed, 1 Dec 2021 17:03:15 -0500 Subject: [PATCH 2386/2500] doc/go1.18: add docs on FieldByIndexErr From: https://go-review.googlesource.com/c/go/+/357962/ Updates #47694 Change-Id: I2d43dcbd28c03457b55eada26e87f7710a113b0c Reviewed-on: https://go-review.googlesource.com/c/go/+/368364 Trust: Jeremy Faller Run-TryBot: Jeremy Faller TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor --- doc/go1.18.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 5692a068ab..8f0fc1fb71 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -459,7 +459,10 @@ proposal.

    - TODO: https://golang.org/cl/357962: add FieldByIndexErr + Value.FieldByIndexErr + has been added to avoid the panic that occurs in + Value.FieldByIndex + when stepping through a nil pointer to an embedded struct.

    -- GitLab From 06dbf6121ad77e9ea3288df99bfe4e94f8776f38 Mon Sep 17 00:00:00 2001 From: Jeremy Faller Date: Thu, 2 Dec 2021 13:18:33 -0500 Subject: [PATCH 2387/2500] doc/go1.18: remove some TODOs for changes we aren't mentioning Updates #47694 Change-Id: I8fdbded4aaf974425ee317a1cdd940a5ac88c0b3 Reviewed-on: https://go-review.googlesource.com/c/go/+/368794 Trust: Jeremy Faller Run-TryBot: Jeremy Faller TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor --- doc/go1.18.html | 8 -------- 1 file changed, 8 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 8f0fc1fb71..8dc6a88ef3 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -428,10 +428,6 @@ proposal. to eliminate the need to perform uintptr to unsafe.Pointer conversions at the callsite (as unsafe.Pointer rules require).

    -

    - TODO: https://golang.org/cl/321889: allocate hiter as part of MapIter -

    -

    The new MapIter.Reset @@ -442,10 +438,6 @@ proposal. over many maps.

    -

    - TODO: https://golang.org/cl/345486: optimize for maps with string keys -

    -

    A number of methods ( Value.CanInt, -- GitLab From fd4b391849dcd3ac0e90d3a86b0ee7df00b9b269 Mon Sep 17 00:00:00 2001 From: Shang Jian Ding Date: Tue, 5 Oct 2021 19:52:20 -0500 Subject: [PATCH 2388/2500] crypto/x509: fix comments on certDirectories CL 205237 allowed SSL_CERT_DIR to be a colon delimited list of directories. In the case that SSL_CERT_DIR is unset, the change also made certDirectories to all be loaded rather than stopping after successfully reading at least one file from a directory. This update fixes code comments on the certDirectories package level variables to reflect current behavior. Fixes #48808 Change-Id: Id92f875545272fc6205d9955d03ea7bf844f15eb Reviewed-on: https://go-review.googlesource.com/c/go/+/354140 Reviewed-by: Emmanuel Odeke Reviewed-by: Katie Hockman Run-TryBot: Emmanuel Odeke TryBot-Result: Gopher Robot Trust: Katie Hockman --- src/crypto/x509/root_aix.go | 3 +-- src/crypto/x509/root_bsd.go | 3 +-- src/crypto/x509/root_js.go | 3 +-- src/crypto/x509/root_linux.go | 3 +-- src/crypto/x509/root_solaris.go | 3 +-- 5 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/crypto/x509/root_aix.go b/src/crypto/x509/root_aix.go index 4d50a13473..99b7463a2a 100644 --- a/src/crypto/x509/root_aix.go +++ b/src/crypto/x509/root_aix.go @@ -9,8 +9,7 @@ var certFiles = []string{ "/var/ssl/certs/ca-bundle.crt", } -// Possible directories with certificate files; stop after successfully -// reading at least one file from a directory. +// Possible directories with certificate files; all will be read. var certDirectories = []string{ "/var/ssl/certs", } diff --git a/src/crypto/x509/root_bsd.go b/src/crypto/x509/root_bsd.go index 8ac205faa9..a76aef8659 100644 --- a/src/crypto/x509/root_bsd.go +++ b/src/crypto/x509/root_bsd.go @@ -14,8 +14,7 @@ var certFiles = []string{ "/etc/openssl/certs/ca-certificates.crt", // NetBSD } -// Possible directories with certificate files; stop after successfully -// reading at least one file from a directory. +// Possible directories with certificate files; all will be read. var certDirectories = []string{ "/etc/ssl/certs", // FreeBSD 12.2+ "/usr/local/share/certs", // FreeBSD diff --git a/src/crypto/x509/root_js.go b/src/crypto/x509/root_js.go index 9593038517..7b3f1e486f 100644 --- a/src/crypto/x509/root_js.go +++ b/src/crypto/x509/root_js.go @@ -9,6 +9,5 @@ package x509 // Possible certificate files; stop after finding one. var certFiles = []string{} -// Possible directories with certificate files; stop after successfully -// reading at least one file from a directory. +// Possible directories with certificate files; all will be read. var certDirectories = []string{} diff --git a/src/crypto/x509/root_linux.go b/src/crypto/x509/root_linux.go index ad6ce5cae7..e32989b999 100644 --- a/src/crypto/x509/root_linux.go +++ b/src/crypto/x509/root_linux.go @@ -14,8 +14,7 @@ var certFiles = []string{ "/etc/ssl/cert.pem", // Alpine Linux } -// Possible directories with certificate files; stop after successfully -// reading at least one file from a directory. +// Possible directories with certificate files; all will be read. var certDirectories = []string{ "/etc/ssl/certs", // SLES10/SLES11, https://golang.org/issue/12139 "/etc/pki/tls/certs", // Fedora/RHEL diff --git a/src/crypto/x509/root_solaris.go b/src/crypto/x509/root_solaris.go index 97c19139e3..617f26961f 100644 --- a/src/crypto/x509/root_solaris.go +++ b/src/crypto/x509/root_solaris.go @@ -11,8 +11,7 @@ var certFiles = []string{ "/etc/ssl/cacert.pem", // OmniOS } -// Possible directories with certificate files; stop after successfully -// reading at least one file from a directory. +// Possible directories with certificate files; all will be read. var certDirectories = []string{ "/etc/certs/CA", } -- GitLab From 8835343280029eaf86e0612d600ae7af5c68b092 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 2 Dec 2021 11:39:38 -0800 Subject: [PATCH 2389/2500] doc/go1.18: mention new -asan option For #44853 For #47694 Change-Id: Ia76246218b1361d8bdf510bbfc5178c83cdd3eec Reviewed-on: https://go-review.googlesource.com/c/go/+/368834 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gopher Robot Reviewed-by: Jeremy Faller Reviewed-by: Cherry Mui --- doc/go1.18.html | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 8dc6a88ef3..2ea8e08423 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -183,6 +183,13 @@ proposal. third-party tools that need to collect package source code.)

    +

    + The go build command and related commands + now support an -asan flag that enables interoperation + with C (or C++) code compiled with the address sanitizer (C compiler + option -fsanitize=address). +

    +

    gofmt

    @@ -244,13 +251,15 @@ proposal.

    - TODO: https://golang.org/cl/298611: cmd/compile: add -asan option + The new compiler -asan option supports the + new go command -asan option.

    Linker

    - TODO: https://golang.org/cl/298610: cmd/link: add -asan option + The new linker -asan option supports the + new go command -asan option.

    Core library

    -- GitLab From 5f6552018d1ec920c3ca3d459691528f48363c3c Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 30 Nov 2021 18:58:53 -0500 Subject: [PATCH 2390/2500] runtime/race: rebuild darwin syso to work around macOS 12 malloc reserved address On macOS 12 a new malloc implementation (nano) is used by default, and apparently it reserves address range 0x600000000000-0x600020000000, which conflicts with the address range that TSAN uses for Go. Work around the issue by changing the address range slightly. The actual change is made on LLVM at https://reviews.llvm.org/D114825 . This CL includes syso's built with the patch applied. Fixes #49138. Change-Id: I7b367d6e042b0db39a691c71601c98e4f8728a70 Reviewed-on: https://go-review.googlesource.com/c/go/+/367916 Trust: Cherry Mui Reviewed-by: Austin Clements --- src/runtime/race/README | 4 ++-- src/runtime/race/race_darwin_amd64.syso | Bin 451280 -> 455944 bytes src/runtime/race/race_darwin_arm64.syso | Bin 438936 -> 438560 bytes 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/runtime/race/README b/src/runtime/race/README index 3b188a0361..d3c55182ef 100644 --- a/src/runtime/race/README +++ b/src/runtime/race/README @@ -4,12 +4,12 @@ the LLVM project (https://github.com/llvm/llvm-project/tree/main/compiler-rt). To update the .syso files use golang.org/x/build/cmd/racebuild. -race_darwin_amd64.syso built with LLVM 89f7ccea6f6488c443655880229c54db1f180153 and Go f62d3202bf9dbb3a00ad2a2c63ff4fa4188c5d3b. +race_darwin_amd64.syso built with LLVM 89f7ccea6f6488c443655880229c54db1f180153 with https://reviews.llvm.org/D114825 applied and Go 7ccbcc90560468937f02609a43cb39a6e13ff797. race_freebsd_amd64.syso built with LLVM 89f7ccea6f6488c443655880229c54db1f180153 and Go f62d3202bf9dbb3a00ad2a2c63ff4fa4188c5d3b. race_linux_amd64.syso built with LLVM 89f7ccea6f6488c443655880229c54db1f180153 and Go f62d3202bf9dbb3a00ad2a2c63ff4fa4188c5d3b. race_linux_ppc64le.syso built with LLVM 89f7ccea6f6488c443655880229c54db1f180153 and Go f62d3202bf9dbb3a00ad2a2c63ff4fa4188c5d3b. race_netbsd_amd64.syso built with LLVM 89f7ccea6f6488c443655880229c54db1f180153 and Go f62d3202bf9dbb3a00ad2a2c63ff4fa4188c5d3b. race_windows_amd64.syso built with LLVM 89f7ccea6f6488c443655880229c54db1f180153 and Go f62d3202bf9dbb3a00ad2a2c63ff4fa4188c5d3b. race_linux_arm64.syso built with LLVM 89f7ccea6f6488c443655880229c54db1f180153 and Go f62d3202bf9dbb3a00ad2a2c63ff4fa4188c5d3b. -race_darwin_arm64.syso built with LLVM 00da38ce2d36c07f12c287dc515d37bb7bc410e9 and Go fe70a3a0fd31441bcbb9932ecab11a6083cf2119. +race_darwin_arm64.syso built with LLVM 00da38ce2d36c07f12c287dc515d37bb7bc410e9 with https://reviews.llvm.org/D114825 applied and Go 7ccbcc90560468937f02609a43cb39a6e13ff797. race_openbsd_amd64.syso built with LLVM fcf6ae2f070eba73074b6ec8d8281e54d29dbeeb and Go 8f2db14cd35bbd674cb2988a508306de6655e425. diff --git a/src/runtime/race/race_darwin_amd64.syso b/src/runtime/race/race_darwin_amd64.syso index 3f95ecc8eef955f005a017f3820ae1f3556f9826..6fbe140026f0a8391d3dfb4581d37a16dacbd375 100644 GIT binary patch literal 455944 zcmX^A>+L^w1_nlE1_lO31_lOJ1_p)?AdUh97)UZOFl2!EU>+uMV(N0Rpa2V)Vo<07 znZUrn&H%w&5MhS+_>$C$5-5j(fgwIV#5E!W!H2P&xFH6C%mc9u8dw=(gcukYSQr{$ zYCv>+d`@ObYEfd2p&5vaVO{{#90RD^6ZlyeK<0rJGcYjl!5C0FK0c|q7|I4w@$oK> zA&wvx1Uo?ebwO+qM1X;Tfep@rgdGx>AwE7Ou_O^8f^J>|AH+2i5+G_O2tnK@Ak2p0 zHjs+=_~hb}qRhN>5C=>63FJe}I~oU3pim6qLwF1fOfUwNj*m~y&&|!xgK`^ z60bXuG(v+CtOb--zziq>GB2+f5y9x@-8c(zj|9|^7Z+I=K+FbVHU@vF8ORi-d8p~- z!v%(nh~E?l$e_eQIDRUIk+MDK%x*LFTu|W_Ai9Tz`)JGkO5n*V<<<1joB?HK16f7qk*vuEdj&*tMC9<7%g_kry6 z;dlMy(fX~Vz6%`7EeA>+HZZn9*(E$4y|y6pUVw-O+yDRn|7R$bfC}ydaltajSV2ri z2*m)E_UOFl)A`G%^CMV^N9zIp7EpoXvD5Lu>pfN*aB{oZWhWzcudv|NlOn|G`d1OFxF+z(Jb^OH`2XZT-*RvWk&`!K3px!e>6+?ms*& zPw=;%WMp9Q?EL1@eE5gweoz?wuV-NJI1VZ<7(k&e0`p#posZ@3vbvWW85kG{1qFZ0 zG6n_)AIsnTZI2ij7+&%*;?_fKocUP(F1PULyy0>1g@Q*fFDQgOx=jv(+^E=j>)<322g|_;ALU(=r!dK;9&6RyakR@aA@K33n}h0 z#O^LBguD2m?kaHtx#_i?N3SiagTV0#jc2gq4jW$bfF*?Q9-TMAf?yYeB*1AND(}&G z6Ri970gqnWy;&e{ioUL8Vc0iQnt=fEZ&zlOCPtJ-%P} zVf^j`$^y@rOQaFTr%mABCc@nz!r}4%pvV7nr5`<-|1ImUr0x_67LO7T`nh&ygSe`At`V!RO^XdHP(fsg%M{nT+kIqjX2Vb#z{6FN; z{4b%H#qj^@N{`NW9?j1lcr+h-;BoLBYi}K+1OK-F&Ci)VzF+fT{Ac)|Ux3A$U%fW!hoVh$j&0FYP$NUQ)PmH-kf@MwPD z;L&`HrF6x&L(C-sKD|B`0v^33)&ee_pBf$|G#q+x;1%n?LoWQ=4mmbIVD>!tfYtCn zB6#@a8TbWU>^|@d@Yp%>3%Xc-aO4-{vGiy@uHb3;qx7+-mHnV!+_p z>8|0^U7{l3+xpF;mz6t%g~5m4<%7rZqgdkiu*d%cjtw<>j0_&Vxs0XnJbG&x;qmLy z`j)?C2B>6f{;NXE^0hFpCOkvo}F(zJMZ(i&i?)XKd6u~@Mu0_5$zb` z7z=82#2)tSd=6@l9Ai;oIOd|l2qKt31T%@Ph~e5FrR6gg}Hah!6o0q98&HM2Le32@oL(BBVfsG>DJ^5wajc4n)X<2n7(K z2qKg~gffT#yIB>)QUej{AVLE~Xo3hW5TOksbU=hIh|mKO`V64585~+Zo&S(Si@)W@ zKS($!cy_uW7sk;ku)-K4vx348ULI?M%41M|^+e9EzM%XHDUU(<)vK3B8}u9Ky?hD3ISn3S?JsjqAd|04j6A@?ZwMK<0%P$h;^8 z@`ab&)G3hR?P-1i7h48Ud1{MVAlrfqWLvZX*%n+N+oBc7w%`KU7F&TlA59(O}7kNI03{QCc&$TC^Zv-6&3=bM)&e*OOs51+8$0ME{U z1WoYiEam{Un46D)x>kqb^_@rOkIsXf7r!0k=Wl5Q)s(H5_*?WraoFqi-?8(8WAg)c zkIv&B%|F?TY9XiSx9XiUH96HLG9XiTc96HKb9XiU{96HL` zJwUz6=7Sui*L^`{vIuxu9^h{S zb!j}3&v|s7^Emj7!-MmjN9RY6gAWBfI6p$f6hLDCPjy~A_>$%SL67E#>?LI$-*0+! z9*4FUJvz%dJUY!invV;3{6ARw!K3+CK~WIG1u*%}atV*lasiLdat)8pas`i0P{*g- zz@xL=!=tm@!K1T0!lSc1z@xJ~!=tl2!K1Uh!lSbs+@SNZJYKZpFgTEY6%?;~{RLrq z+5|^P{CFHc3~FknO>k_ekpt!AXvWen9=+AbEvwu7EhV6UZ~m=NB;wi2BL~XJ#U7mp zJs5BLSbi+aFod?9Js9tMfEzT-B?7Sa612e#ZBOZt-Jbdcih|CYkoHvI1JBM2o(EsB zdj3D)(fli+7*~5LjFErarRGPFR`WIFCaWWj+f$C;4ltL1qqp-GQd5e5+o$Gd%pTwG zf!kvr96>E+P&51kzaWnVsJ-m*|5)i`56jd1ttJhaceAbWt$?5egtefM1hE<)u9%1H%Yw%p7x3F#t7d3_*kuh%g2bCLqETM3{jH za}Z$xA}m3K6^O6~5jG&g7DU*A2zv&PP8)E?6*LxzXdGEE@V7`YF))BSu^bE~IiSX* zfXBfX%pN-#K)`^3p_`|%^(24G7f|l$29Hv?8h(THCpu3zKK}pzzy0@v3=9ko{H+ck zHJvv-4!-2_=2CXMckG}*BFz>HmK<%uf_0>I( zyA^=k;Cb8))U9XmJnjY_tn@tY1|IizJm!|c;M1L=qTt*5#HZJ`FN%f1m*3?%v^e0G zXK-w&k-=Rah=Be5TcJqCvzJH4!}0`wvpCoTpfbVJ@(h172O|RmmU2M?UO(_}6X8Kr z@6hsL4@&s}k_T1qJn-tB2VTANpj7V{Up9fQ2ZbMxPj}4;4&T=QCH0Mu|MN32U~u?T?5>fA z43v0wx)r=U%f!IoYWVHtQBX+XEw`G$B^zo#5To3h04lF+K+O#s)aHf_xVd42*4(fG zH#cn1nj1FY=7tTn=EeeI$}1aid1Zs6yb^$xSDu}22B1*W@Mt~Y!|(b7nx+ty54gSJ z*ia*nJAI+lH}W2qCyJr>Qq4i{m9U_h=be>Q}6mO;Kpw# zz`>vjDcM*WJPtl!?e<{=m277X4;+Rl<52}=TaSYeSUi|n&O_!GLW2W3|Dxt(kIuuL z8t`1~aoibPRpN_GB20WNS z;~&hR@egJ&7c~CC3>yDn2919(vonCEL_BOkCY7Fjt?AL*3}SlpdJA}1p77vzKLHBy z?-x9JOBe+_nxB2}=)4aeOZM!P_vn-b1qDpRqr3UUKhX388)V>{5j@6?=ntTbS9?G_ z%fR3Ij|-&dKU9xLFKa;(3xh`|xUTi+g-|das(n!Fdu{!aSRf$N$4ECrjUXv>x#2 z^lBu!rR_{`QNY8oZZ95X?CO;xzwe+6S(w`F%e7^}5LY_vm#IWc0K=P%P}# z>mtSI(OY8pAEdl#DrjWC^QLF>!v~(djt@LL4|yJZ#p>JZ#0Z}Mv0`LkaO`zr4hA=gq_yv7r8Jze9U1UFi1TXLl_-H-=i-JfO*$W=c#~eJG zj~?)BKEzad{N)=^*mvIdXny{{qqqElXXgiaXXGEKGxGK&wn{w@G=~4S`6;9~^3L!r zzW|FS$SMIReoYsU12lbPLBsf(3LsGfu&9C)zow5YXdqt`G?1?u02Xxsi-LyoH9Tr?%=kfovNAqvS`nOKUT%;Ho z_P=0|VDMlDXEl#r(F1WT3_hLT!1)bKbRInTQXsAQhams-1N>7Cr8WO#;h%m`;UdSu z4sg~3D@tqrAzY;D(QDediiN@B_;FCS0!w(b9w_1U=mx9owlw_q|3ZT;cy$PLRH0iJ zTnP1=Zc1Ze*l(f0z+iX@qOtR^M=vXA9?PSXxvLfA$PQ|spz>E6RQ_s%%3p0z`Kt{oe~)r_H2wvdQF;bCRSWfDiIfM_s_q>it30~d{|k6@ zHY>0(FnD(NgGyVE)|33L=4=cM9^Kqvwi}4OkKx1r|MwX{1?zl}Dxc086$hVAYlvyh zKbVVDJbI^rN=1)eTbp?-4B!IM@BqYnaNQpJK^|vNU|?|E2~xb9Lx6$7aTfyz1B2&o z7SPO~0Rw~M9*`ne!~d>^Z(oNX%A^UNoo_vMF#P%d-yGx+#)BS=hdmj;d+cQR_y4~% zSm=}|<7tl_KbRR9PJjwg#v7iDXFPT?vM?~L0L2KXPtpb|a(bITy#N2-!}0@vb2}qw z%Ch(a!YAHdy;JNT*fTJA_Im&D=(X*h3r>E92YfnxR0MoFuljVxs6d+aKHV`Y9G;!8 ze7b#91Q4F{fP2`t^=(P0S1-?6ke9rAS=M_rKX~BPD`M}VdC0f(ho|NVAIn4htx+tX zkiFrn`NFgLzz5HZZ#|oz{_*L2=%e}4qw(M$b_NEIgD;sp558dbu{_A%3ZAa-ZTR;VAgWB0=17<=6{ znoqE=;4d*e#;OjII>rjJjo}z8XiXHuF;*>zpf-fkfl!e0vlDC&yu8_#-lq#MFMWl43Igf?gBXw91;C}2p4oWgO<#BbTfE%w(a-_T7m<08YBjfF)%jl5Mh*HU?|arnAB^_j2u>ovJu>W zh6U_*Sf>m&ec62QhgUC8zlY{Q&&C6wlI^vcXX61-@!+9(+_SgG9>jbtJocdtgb|qt~_sA}&6Gg<;>?zo`L9=jg&;j229M*ce?ZIKK&cLrpgwr~?*Q2jb#nIx4+a5- z)^8=z9=*1oLs=N0S#UEWT!9Znfq+M^?Mq|@4YuHZehDNL`M3QBTikgN-05NKW_`lI zzyRs38Q$*R05PR>*Xt7=y|&hF-~@HA7cJqWO#t_U5fKKCFUJtjoY8mB&VNuhd9)rV z72FT%bb+me_v<|Vd$gY5ZxsXOWN^6(YGru!+HCabJmm5HmWSeXP$Sfr@w-S=kTtkT2sum``>4WG_u9-8+&dPUiTLG=`*$J=tCB-N)=6;x=v zR)9nrBV6IVAQXi*kQi+K!31j4+MWplw@G|De|dD?^zD3LcmOgb5CdAU01iha{$WT+ z_1gAKfqD`wFagnj4)EyK2i1WckUq+1P;i4I7!-&;y($|#o1Z-J1TC3k04@E7j(H~k z|L>vrqWLkq$HB*19-N1LIA5oE@aG*)<1aW6>d3FbqvFV~5uzf%uW^(A*sZ(#VX{>Z zm>JUe%Wiz;uXE=BDP!P2cB&(dKkY;s|LxOh{MQerwH_$phq)bAesx~=058=9j}ZMo z>e;F1(fQKj;7hHBhwL854=^0~|KH>C1CQ?)JUU-_D1P!#JoNqOe|ZK5{+7+4#DDOu zQR7n(-y`!V0|OHybTB@Nfx(0GpiigGMUVf7J-b;{K>fnj1)zpxr;Lhcw+m>E*#Z7m zZBR$D+eJkHEPo0l4_dJT;KK@R>ymE9`i7~2W@NAFfe$u z{^M_D1y#kC*Z7-tK;sAywGE669<3MnTev~3)#IQ#jN#?~fB*mcbbj~f6j1?3lSj9R z3c~v@^`JIF3}9ekfLaT(rt_$W;a!i`tNg7XSNd39keei>%ag1`+%%@1QLN+bI3#Slc(hrs5PK& z^UEp{t>JI_@aO-3uveb{f!c8oBm%L+Q}Lj$We>!HCOMEl4uT~~^oJbC)gXU}!u-Jl z5`owODnF6^@$t|9|1URzQUy%@xR2s_L~!;&%mBqhOE)yLaDXyPD`LMf|Q!DEL1A%V|lf>09sT)5e`Jn-W0gsvsm$!n73B6>5FK-(m&I{m`;&f^}2_dQy#m+JahUN2I_YJM>n$YDt@ z?}AF6)&r$0UWb8}Y8`y5)%+AC$DKvWad*Kv?k&hv4Y2>-mMVaZkw#eIft1Ud8bG-k zT5gsYgTfEuE+dc$a!^f>I0mO@h@(sLEvj=XICiM$>asebhAJmJ~-#k2FD zCwv6M1GM_251gMbBg$vbZaoitHI!%PTTjKWo{C3dHPm%b?XnwObAT!&^t#H2^9D2x zGB7B3aNhLlfog2=|oxcTCOnG+8f$H2&IcRx~QI9L$^H4nY z{V=G~=5M(SDr^qEHfnqf;(KHs236w70psA&$@9Up+0Ej|>l)u~J>S;16(!!iGRr-h zA3yNG(rWQhe1YP#Hwd5cYjE>x1S5It`gP*GWdKSEC)A{eE$p8QU2_&HRo{HZ+6_3Lb&nSdxujC(94d|3^H# zT^T^7L+frv1_s~GR0hv(R}Qd1252Os+ZEERVTN!Z1xf6`|NnhEAAwWSeQ@)}7qxZc zV|Wd%b<@tmz~BL@)9#ZE9|ifm3p7jzX_i5J&ffxR7kEHD zd>>S?f#Ul%XkjfzhV|)IQSt1&jg%4Lf%8%p?4%FAouJ5ow%0)Iv(BTwosWDBpMslw z;7Juo`wY~Uvpmb+d>z!%gb0CM1Zw>GcK$}#;oEu4xAO{r>yy9#|G#_;QjOMl^XYu< zWB3eO0)eaqH3jM;L4o8B(t&KG2gtlL z{4HIea5?S_X*t(|IK-Ii1~tu%qwka5|G`um0T{_gRF`KF<@4qwy*7e|Ns9Il-EFQ3rO3H zkasPwK|KkL9#8>!jK3-FCn)7y0ednC)ZPFMEO>$#*lpJP`Tze*Ur;?xjwdUBK|NXU z3)IrT!QYw=Vqmw*2h_v^?U{qNWjs2ejqekXb}=8QVU4KETW>%-2+ij$pji-j`R~sR z@^31~%kOAjLu!r7fy`^Y0nLA{w|@Tr|2hrS%s%+a$fNU^kK#E`%PkimcC&$;4G&3= zR%mGhwY!z$2WXrh?rzjpKiJ&}ds4wMkOpn6=YbpRou7R=;Z>za=e?KPzk^!z@MHz8 zJenV}V@*~*miK)+VR^Y}4yZB&ZI_%3PQ)+xTf0CESfC$ANyPb}MEoB$etkMm5=_MZ zd^^wZH!TMF1!UDMP%wi!i4#E#m{q8WxD1q(rhuJ-$g|*~4xD+`@*00r^LJ2+1r<}^ zL|gJ5l#*WXw`PMF5Su&|5Bb9TqQT$)|9`1Vu8)rVfTq~pKcMz(0x=-=fD#9CcX9fU z|Nmbe0=3{^^2dD?uX|eVIS)xSeV|m+`T`L*EuiHt@Ot_icqlHJ~@8;#IAk*|NmvfR}yo%Z|9q$aA zI{!o#jJ}pPLAyYp`2&=U^*~8M6A|zzNkJZzjCp)o4}jZx3ZS@$#%(KP$|qamrOYR= z{XT}*!L3G6x`uic;%}r_J>;W!%F}WR;aCNYuf7xj)d=X7^;xk0Qzc%W`vA4}J=of# zptNUszeoe>6G+JpE>4R@JP?ui8I)c;euG90!JcXXwHtgolOp0GRP_9<>?feHG z%>l(DVl)R-z=Ma3_?x1B!EEvAR5|=I=L7O^4$^!Qc*$e8JZLder#y}^2+uvB6?mX2 z2T#R2o{C2xqY))B9_S+x(9i&l-f$j-u771h1sb;jwcc7m#Vg9Z5G$zt1RaazZw2iKLkz`&=7l^u zzY;Sqqzdcx9sn^w9T*0NmqP!+lR%($00Uxh@uerII_>=G3F*dy3LOXw(xHWn^zyf^ z0T&S0LBrln5FLn-cBBaj&`c7MlR%&%2Ryn1I(`Q}-Q&^u?j^W_N9){!=Dt8>BLf4- zU7!&IP}K$2zXcR#$6Zvwol}th-JoIN&V!x@Uurpmn(m!9VBJJt&4Wmt!<*pF;Y%M& zkhh8yd|OYJ;;KX@fb4+J-Yo&~z>^LEpfVla6^7<|Jk4rw_-TSPfu=^lH3F>iL@C>v zLBm=vr9d?(siuR56u>R^E#SHqYczo-L|%fH#39;sgx${HbOGFR`_JEc9K?V+T=A%< z1)G8dER_ zHBvhddK%vJY`s{j;%j-a2-G2l*1n*A24c>sc;8Dwa2|y>QZ$dlQ!#v+5@ZC(U7$t@ zu2g&qlrdoQB^sc(hs>9#gC;d#m7fPVoWT*w-!ucHqccWD;^h@kBN0)#Y92#!0@Boo zET}TYYLxFkz+H|bti%O5RcB+K8mM3 z6c59OcGrXQ(LM$c0M)1%Wi;mpXfX}0Vt;yc^4tK;ZNTS4d^%72bYjkjcy_+=fSc;s zc@w0^r_%yb3A%?u}W>0G>90Z0mab|G$so52VQgTr&mW+Ka%<2k86{ zLNgzpiZ?wK4?@}+{4Jo3fS9#7QV=+Jb@H5m%zR{ljBdSMk>uT*1MfM@1$&^(X_=LeromKR7v{oob7 zNJIU%K`w@M+=M}uEVNI51JqpSRoCo1k8qgV?wct68 zR0a>&jE*tbbI=(b(2fcZSXbH$91o9uJ3o2!qRr)iYHP@(Cb+i#$KToy8d(MnUF(CU zHlQsM4zLN|Jv+bRoWAhse1{bEf#AS}hAed26urgb+xY-C1iuaB8O#6hu=MRb!rx?y zQUgG`RFKlHSqjwWodJpswAKgKDT}k9Gyw9_8&D8I2ggCRSLdIX55V;s>N*&#h6IB2 zf(!wj9_RrbxrZ9E0yY_;qJnj5=cOVzI6fgw96*XAP@s1n_vw5L4v6pktuMj0T=(s~ z=Gl3NzeyS`2;j9Ze=}&^`^%M}`2a{O5EQzd$G}FRPuYN7401Z?s7nvnVO*VeUfu$E zo}hMlP&k9Me*-aKXLxnqc?nwV0ohrj<=Fg)9dziz!I$9WIh{Nzo|>oN6_4llTi_Pl zD<9N21~ug_Avfh9!$*)vZrTBgHrSNiJJ2LeXEMi2eQ<>gANciv6d<71BZ2vZZ?O4< zwu_)z1netpi;g@jufbC-f0Hz5IKT4jBLOFYkgK3Te7^9`o#c>7n?} zxAUE+<(8|UkyCK#cBDubTHd`h2Mt$%0|m6?2E$s?ko=332WNpMWK=DT}NU)F*rwBQ*6YnR5u@;WGPlzls|q4jD|ashbk8Zxk6 z8s^iPDgbW@IDGs6|K)dxO^^}d(tKabpYRe4T6{NLB^SPdI>s2QtF^ zk-rsm^o^(GMUcZL`*vPK)(J`~r$A|dzv(|HU<*)sM;_WXh;T*f9{nuRL3R*YKMAFZ zmv#TE@aeFY*ZG@2fKpp$ti;PpUy$v@?p+_tf5@IKQb4sD zI+6?x{$;2moNGUW%!k!5;DY-VxZs|078K}^f}6hyG_?#K`K<-3hY!1A>ls2*m;xvw zTfddU`iGz#4J$dCO#UFoSwW+@uffKGodHq@&iUY22j%=GHqc_t&Qyt)M?RyB$AUJC zc76gKj?{V3)$jl~|09MR(~#Dudo;fRZ=q?4kp}I)x`sU9XfwgH`S}CSX8ZsAEw*6k zFCN|I9U5FO>G0*`^po5vPEgt{up?De86+H&(UwCwus3`Ea{FGu~ zfVOHuqnVJV5@>n`yg$H56|6M#0JtlH+*tSNRJjQ`(373NMVm^M~C@<1ah>nZGU`v=Hw$Y?b}#H2&Ks z()h2ROlv(^qUibmm`C$pMvvay|NJct>xfDqFvmPJLOx&cNW?E$`cUyR^cy zlijyFp2HWkQ%V3dao!y-0Oo+s`t|LOm+)=9U9!;wbX4+v55wco{yC^&+j^eARUOox zg@g>Kfogf4zqtW4RDJNZzGL%aW*_Sq6%CKh>-%oW z3*t`5x}Cq^=J_wIE?fv|7NDBA8>@+{LET2^3ED5`fje5aJPy9nYJSA-q4}v&zz4kQ zUDpHLhW5Dp3L3(Y;6(Vb=`P5^)=T`YS3vEa))*BI$N|m}{YD<0J}MGEowq#Tqca|g zr#!krTNf;+faj0+n`eP${yf0Vx0~=mSMw40UR!$Knt!wyN5w*YJDKK z-vfztf=n_(x7Z7A=T14X=ZH4(=Q;3y>|oj~uh-y)5^D%V7RyP$+>T1QbuL zUZ9!I47eNadBCTSJQV+VSZ;x8iiY_Ptm!CNDEVvz3^cz0?FHwedHD zmWX)b$mmZ&0|TJ_)}RDOawaM&^Ju+PS_lrU(ky5o5s`74Knr(YTS7H}0tkD|y8Q>u z$Hu5|AjRy>fB*mcLdw)qPR~wvftSm{oyZ%Wh6kV?uVG;DY&}t$0Oc~UFnC&?C^9Et zU9lM0A5g1W`#=-IIiRuzYtR+9yv`>&%s|#VLJS54m>JljQhlg{hzYRApsWk2JW7Q? zr+Pz78Ps=Ufd{it6b`{)Qen<#pf#xHyhCopv$Q>^q z{{T(C5m^FzTAqMgP-F-S3mvenrK&hw2QPz~9{&0N-@B9L{mUY7Pxy>)Z$9YkHD7+0 z_a4oEIry8TIYHZerU9?gH*%U8S%1D*fS%?@6u4Vq{50L^=NcDks%0L`d=0E>gp zYXR|ofO(+GAGBr9xAQ6JIFA*cofkp94r5SV25F*!n;#eXTa`dnK12vyUtZ*I4gw8g z9eknR{D9fR+68ou#VP(K@I26QSJ1oz!^==`>*H)1fBq4V&JYy=&(7PPoj+YVkKwT7 zBd9HcY6*C|9FirDogaKU&---VMnoKFm$^V1fBpl0jhFn*?4SlpDyV&c(=VVIXAe|s zz+;j~*7$Uu;%|Bc%HzjfRDOVb^YRLahttepP@4hO%ydwYp_|zNGUd373aD$t@UjTh z>}hpTu^{BFR`3E#Wb?tk=5MM7jpl=U*q|{aXzB(a43!x}!0XYVgl^_}G zKPc_OGTeukGeF}M2)p2$5Rih7zZtxA9b^|M6kChI4GK`!0Pn6mgf+bRn>#@!!!?1% zZ(bV{)KmiV71*ZVzyJSF@qHNV5XmfbI16@aS|0w=Fz7|N3-ZhPE(t)t7*Z zuY8b}Zg5V%1-d;#!Kd@R3%JRV1#Y7p^uQ=ON{i64+9gmxA!Q3f;oQ6olx4bIR3Jqb zXrULpVEX|oyg(&c%d21i|9dtcm3V0hatJ7R2$);C2E|?AOj0xhG6+v}R%+S?Y9)a> zSx7N}JzarUco5+({#F4{2?p9b1TqsdJQGpe&EEuCj1E!>O*GhTZw3WA!gfSy0QNVy z@N5MgfA{h!ETQm&*XyC!Ra6KGQ;>2T0p)Eu3$oz=4{`9*BU$X)k2-?&UIA<|N?E z(rOgPfPH; zr}#CF_;jX#&cgcT+IbMGHNQbQ8O<6{YX_+%uHf2v!l&~(!Y0sh#2nz^8wpU^@)V>V zhc7_eN)g=y5702v8IW>h`IVvu!#{+p9|DU zfh=})>HG*@b#@LusN(S*x+(|712_W%I?nSAGS1`M`k24 zi=FqN%Wa8u0a|!%0vEC0_*++kx^5tA!5i$cTiXh1xPUgzknV9bYyW|Zrf>YMUqNFX zAZy=%h90dSPay|#7iefl5H%8z1^}*k z!iQBrCo6!HwQuWV^cV)E^p?|*JPXOqpvIYJrz^)xO;o$l%!W1r`62Ow8h)*yM$_vG z9KBIkUzxv|2NJqynj1mmKGp;^gARr8ZGDWUxdc3%lcK@_X{f=+fASqXJO4l%XsT_q zm>EFJExJ=wI1o7>(l}!V8-OwRTk4FGQTUq|gNDP9b2@s+fyv^%C4IfZm21Oxt zGGtLMXdzvOZ|mdIWTcQnN*_(%KpRcmkR;I}5IW{&0U8|w1q80d0dl=Bq;v-j6}bw$ zl>G%7tiTMSK-3^=S_hs6gC}0>_IH95q1ew4J`m@n8F)~d)EtF~PH^}aML?sa^;@Yg zD6~9~0t7j5qv~eb!ekiH}Is2s;*mdN!?V-nEW^ubpe9xGkqppr-q4em!1>m*^Dj8BdUThlAo@)&o*>WV zf%gX>&*wSr0G(z8nbL!uR|eY806EWVbpHj?P7$K_Ux4msfgLjD;MsZ3qw_N8p1{t3 z98>s{APFwvehIG94j8Zwi|yiGkElhZvVl| zuz8o&yHLX05Gu?Q6yK{~*xODz)de{wdPU4&Z)4 zj4p#C|MnIY&{33Wj-4*LJdO=}R3`mnU|=XQfnNAw02)@Y@U(VOF(~Er>3j~g&_%@p zG|k2Vy)PCtvT5;})A06dONjdJ5)};(P4Ibhorj>8&l=u_9Us|xpoFL2J*CI*kr z>mHrw;1}+~?%RDM06i1F8+6JZgGcjW4rox9YI*dQsBj>HxkQD-1C+K9m*h4d5rFI> zGW_=X3BLH$fLg+M(c|DNq-z5_dUYmv9DKy&aquOxN3TgQs6XY=YtsQb7NFOqgT;g2 z^|(i;i;9GYUlW4$s~;@O31epbJBL-FQG61Pl+n z)<<>`1L){=&rUxM*Up?afennHYX?1=kFt1J=cq{VH*+vCFt~K*GPt(BEqMXDIS@KH z?9rX0!tq)fG#}sV!RXo9Cjh$EqjO1{1c+{ZTe8*h`%%aRF4Bw)Anp8}pyj8ooo^f) zpMWkv@acTuaqtC~XLrkS(8UKXoevuyg7%qt^zw9i9DK;?(QCuu(w)O$06X;Bv%3vs ziH9v{-B4-A2F5n#mIEcApob)|&YQjv6^`BWWf%k)K)q%KuU?S`LzMfgx>>qF`v?xc z=kn~{^B-h&=h4Qe5Sw$>GI$((%GxQT@7UQ6GNU`D>yJn0eGg>S_Zpu;RGVz`IQWdU zlf~Sz6JlZW!G9jjKM$17@nk&V+X;59Pv>dJV~h+iw}V3MC1_IvA__pKxBUNa@7e9f z0r47tYv#ZI|2HtUxiUcf2RRPax7&@wv3olUD0V^nt^9gVjJ3pYp=+S&c11U#&^x77G2A7_aY%C1>c%(q*mBLC-SbYa6zreTY z8hCbIha4b<^@;^6!vp;C479#qK}H31h%E=`>~7HQswD&u*5xonI#}1S^Oy&;aPLMv zS$7_&XWxu@vM!o(&?YRcW;x-}*$g^E7cSX+!~hgwagOn^hdp|2k9-72SGpzo zv7_)Sv?hdt?md?9=&S*iY9%THplX$)yB$>Ezh>P5IeQpjffkG8EoIN`q!0d+}b6aZS(Ti~^u}kMqP^hAxObpHjurMw701i`O zbT>oqvkUgh|BG^%#FE_;3Zt)^`O422aNO9=$v>yn0!7cz~``Zhr8j62_+Oc~ZD9wTEQE;Gn^x9suLq56{(mn$x2hYxbhPP2K4DbZqC>fF=d*s0GkpsI&4(uK|4EL~sS_1gp(*|;n z5BO3d$jy=PybW$og2NJ#0KxmggFU+WJwOYH#6d%zo&P-`jUJ!g%@-IXKo{9JgJ@7~ z1ltzv**#qXwC4hJ{NG^)28QnDD-040-wrXB@_BS#^l1LYSnBo?bkwCsuh)Oq?w08? zpqtFWtHZfGy7&CPz#zcj(s>M8l^%S?*~wz=(g`-ir4w{@A!A7jG=96M^n)~ebYAl~ z_>Rk?d&_5#=FaPl&%xF3!RMTvEOwofLH0X#xAcRZ1>W|@)p;DD2Ch%U4q}Z*^TB_m zi#(6FgEW9b)$te`1JvUi7~7gT7&t)nFONs>ZV(fiNy0h6Cmw><{B<|;FmRxH+4&`C z76#&Fm+3q{VE^)Xbl3dmfOwW4bcew+7Kmp-+F_oJMx>AKkbWMBXL&rjOFnaeeG1n2 zoCWMtkUqz5mwpb&5s*A!Z$cG7bb$N_QU&(oI#1}Lx?^BJG5GXuR$veS$0~?Mi&bzF z3lyuMzEF3w3WETu7Xw~`{0{MA%XCot65>m6tb#7*gLo7)husTrAh~pc4T5>L2$B5K zCOCFa=?57D@iI7mLB@c64K~GQzsJGntYDvmTmy<@up`mpxEG=h6whG&pfCWb2ZzBd z&*SYNO|W=|HKf_4V zq;uO5-T~bY2)a+oqxp?MbG-}$e`^b`&K3)Ocw+IRXW#(@01dq;^)8M(e=EDiFo`?ySo=D>{P=bbZNWh5}bS5On zKM&+S$t{G7q4^)py%z_sdp$Zo8GZxD2()|%cMNlcc8{T9{t6uC7d<*Zd3OFqoL~Vx z7#}n&;M4gIGB)G56Es2t4kypfW1iiy4B-8Wu?)~1Cg>Y7K{I2D&yhAP_JHiddl-h- zah9Lpbk|%f!%*r2jb2~nR0hXx*970rB}YNg>f4#h;n^Dtk6IVvqV~TZ2P9^p2lyWL zfnMzJGW|d3f}+=_M#Br-HwQ=Y2hY*)0^d8rSW30@1<8u=HU{c`1qnzYm*B{1dd^#Iw5>)I;*=HhBrUN#&7ab6o*bskvu&8@RUa zmOx&2b=srbqrk)RCVx9<_`;(zqTsa%vIPvD-SaLmFfhQ1;C#dXKArzyw+hy%2sn1T zad>vlIReVmo|Y{tpwWtQuKx!-J0WbxZWomV$LW3!-a{_EwS6~vGWnZW%iM`(!v?pNJ50be)q z!i0rkALs&4&(0fQvq9sZkC{Q^pCQ_4T`rGa+i4IfUy#&S9puhEB1GWzhXLrO@6O+# z0a#EM&+wZ^=PARJ9^ejWoMSvVnLw*u{+11(QWJ7d38*;s=)7lm$<^=xYH18j1s=@@ z1VBSq93GvZMWDxBRKOi%wA&m#x*Nb%cc%+z(6jjfs4oK^AcOVRAr*XYn1x3-J1F6B z_;mg=Jo!IB16n_#r~|3#{P#b=12p*4c?c3#Fs~d&_?}-LavlVzKWfo=*5TVx0sdAt zMo{vAUZw^r`aL=?dP4iE@Fsvy=Qp3uU#Nce=seu`l%0`*p@gg3S!X4fCEo2U<7nLm z>I#+0eDG*?=J@w=DFXuo=Zj8f9fVxT6SUA00F82JfJQkC&}tIUjSh&wlJM+qg9VlX z%nazgXq~q_nh$}(%cB=Gl-&6aTv>vG4D1dx)!pnKo$vk!cz}=Nh6kAixCIppy6g_r z6k@;;&~7Ku0S5N2#&@d34@F4KL5mW6=L^S9HyxPc zpovES6cQSs6htsM+HnMjPv<9iaKxwxfYL0U!ES z8=eGB7jQ$GCE(lwCQ!>$56{jk;GI&Qo&Oy7f|@R!J}NBV4myur9>1t;*K0>56H1>oIdpb23H2GAkKki|gB z|NeU@-f-!B3OWJ*;8QIR&Z9n@XF;oZj$++*#UCbnt{Sw^u_k$o#DLdyu$4(y=9nhH{{||e1%7G>l z1UwEtF!1DNQSpSVrThP%-&658j^><4=UwE&A9T_N?9>r`uTYOBoV8InVoa z+PnZ2?J~_j{+DRNa;%GEbB&4yLurCXudT;Da6w!Dj+tR!w;%(<%N3ye?vi~}G{9Z& zB`gdKj@{sl?%3&~BIDW32AU#Kc&!3W$_+c-gRW;P5pn$Pq5`^P%%POivC#*@bnUKD z(Qsw_>)M&4qT$;5zeEb;7@f_GA3Xp2sBpC0=5JX8S`-3W2=3TiC&N&h=-Zp4QsLPf zm*CmWh8zed9J~DzJUd&!do7{W9DghL$Oy>gV6e&#bVV6bZ{roXlmr{j-vZj21JBcH zpb8#ZzC!b(1gLld--gWrD%&kUWfaoP6}S+G7w8H|Wt2vDj0($l(2#>di5BS20)bLx zXaIRYiY?FH5YS8$JIF{0Sc%nn_uyNW=BJDho%~Y{qw4YLd<4(iB`OeIj-4<52N*bT zyoLo~N$yL~5niBh3qS;zr!t>ow_Ac|XU{QEl@AZFLm*ER5n!-TYQ6RE|9?b$l~%j9 z{x2U(y(gQhY0TV+5k$!>SZiS?lSeLTC} zA!m=S1DyuZdBU^TAN8zy4@2~`>P?uSr}S5X&eBjk;A44!zcnAU@ECf^OY(0}*XgA^ zXx8J~OHc5skME$h){q@rppweL6XYLoVF^CP$G7tY(vnc5Lro5Q7{2ys{mkDAx;NCr z@-lz(MDV`CgFX<8TjW41b^#4@B%w`@MOYE&@Dtrj=*Nfa!{fK9bvKs$&fV=Lm=mu%?Isi=(U}F6I@uW zc*)GLuSO8L>F3dFTL+Px4U%jZMBGCMnOB3{P({0ok@6Bm%Py zb;Um7VC7kV|Nnov1r%`L;XI)eaL=NP)YakIqwrvEh*aK}Nf<&DWXk#|gp2pK2oddb?lpI!$# ztr}cKy@VVTeh_>&>3onPNa<2)?Ae*m@p3L`xt--n{?>({6Ex<5!V`2mtsm&L@LMps z3XmM+P(f%8FBSE$yj)!53koq%ky5e=GX70`qPbjD2s%2b^?zw5=y>21_+7RDCDu-?0WP04g@V!Ut_fjzr%j?AjumX4%XhSG?_7*&% z47pJWQJP>miPyvOdQkyrLN42<^+0JFJf3irAWh|RAq-&X?$&zT=4QfRJOiKdd*v2I>v?>v(p{sDRrjpxX=G zp}hfiPsn+6;LgBN+?@d*#jhTUM`2ACP(4GS$pUEwFfc6eOOdjIULf<2i^S(>eF`TsIYXtKKPoY z`7zS0EaIVsIEq7x;}?BU0|15Y7<@2&!$P|e>0J{KQ*fn}vNlFZ(EhEcF3hl_dje8-sQOdvty#(6YS+D!)MP z2ASfcc*Do?hDYZ;{#MY!XpiG=kQVYwP~(=MQL(Tf0PP7vG75AiiN|p_NIQ8V*eD{K zpFWnSeLy!PUFL5BU$PBqsDUoc^8wxF(+aW<)=)d{1HLZs45aas1?sZ@1IrU>6KH{8 z=RL?VQ{ZFIzJbr8xWV807NxE01HPREYRx533m5D#;u|a1_?!H|i|&tst#JaeTQBgp zT7p{*;6sqWO*znU#ZYVHK?92F1HU{HW(X9;MhK4eMl%d_AU?k@XSUIdxi@($D{1)cEYV|f$o zqF*2Z&>1g2mY4Wj=Yx6{X5i*5MEV>^S{odY(9BpW<70Um)P_aQgr7irML=V>kcK7^ z{U1njFA4_TmeKmZ)Em^Ab%VE(P?C6)0;mnE2{9ULR26GOqKUudD=5oBO1M&WkIp;+ zcnNm|)Has~4*uD|UMhi0(F?E`R0mA}L5giq%P&LXth^-@V6%k#xK z5D$Q(ydTtd1zp1e^5? zd#U;jv|(Kyl!ibjfI-H)L8IO5h9|*;++YH_UJj!@D}xyG{_BC+iUkFMZ+9(du^i^W zw#fp|=4bGGJsIKmdj10)XpJ(k?ZJuEigo1I;B!Q6$BL#R+Oe*9nz5kj2Wi^E5pXk!-J@b+=f?py}Ym{(^mgGaXmyvYi=dIQ{KJ%aP9@7KtEZsa4xw}Gk+jDy1= zRWbM^WyJV(gD2-1pH7t<4K*q<436FI8ZP`EA6zs)ICi>gl%_czcL&wO{~f{W7s5Sz z<12i7Qxg#OdMf*Zmoj*E_JEf%cy{{2*2?p@s)3sIy(KCN$m``5JRsx7KAq1!I&XnH z<C6F*>VhV(I$cy8K!dwD$BQ*QyIWzcUjvvyknv8` z_NxMPc-Z2D=YM|=m=n;)TB&6>w85$X9&3FMYp}Y2SL&e-w?bBYzXZ+Pc!G`xuVuh_ zKKL(0Ja{Oc@=!bkKPen^>$~ScjFZAqQUIu3>Cp)tafP%iK{cUgryh7cI;dR<+Ry0; zDRucpq>AA>*aKphy9YmwJF2kD&2VPp~=Qku;>SyYt?bd%)R|ze$~mfq{(i zQelusK}}WAJ-uMt7(pVirYgp02l%i}{$|jXqhySi9tSlXLAHSo9QFYj}Pe!w6J&LZ%r( zDNFIEXXgQ5#S7k+JhEWcf1tT#QX|s zV)8e`$4kpWZA?7lrAT%`$4kY)CyM8Kcy_u5_;!{$z?YKgfJU%8FZ)_v;BR>d9xrtR z&BlPnOY=Bh-UrQ`Sl;Asef<0X|Cd+64a`gYt=~b-O&L%F8YH(1BnRHZ4!VmSJPIcY z8igzNfo0K>O)o+B5kV3&^omqMnF2ImdeOJ_0Cd0| zZlOW^&I>AmAVnc)z%)+)UKDbHJo_1Rh)w4KPs10UtshE7JuNR37s1<`B_s}*dRkrp z`wnyrE@U{Epzj<&4NqGf%D_FBi?A{QGR!FWk{9edQ2Ud=1u|d?9WwxR%01vw1sgC0 zbt=nfN#JQl5LvGKy6RF1Ev>Yr?NwQBK*=B(gX!HoAV@IR>9hzo}l(;4s!bw zrG04u9xF9b@$CGArD-`4d`S@=*E=eutgJGj{F)yNMocYqY!ONykn$(py~u|j8sI$r}HJ2MH9z7yLD8+ ztx6pgM5~ewZB+y~hoLWW_2|Ues@xB%*@$aZ9)PThxB*%bfOSaJ4LlH9%Hi1P2WCNr zL`$Q5d+P!~lk6x>OdiNko@Zwdcqq@a(?` zw=oYxW|Dk6Pw}^ahBIEag0d-c3lZdCNV^+0n|~W@#5Mlre2`jbGm`;SzZ`dhj8%RH zwYBgYQVR3+R3t+{hhumicY=&kE(93@9tHyqazHx~;Gu!@NJ9hn!9xS@JuI*KbRGtI zqvH7npH_zjY&s0c-jl_kc{NfEzuaBjKSVd_AD?N(+!m^VMY7Hf-`3bhFI23HnSMc~<4RoZ_w=)E3q>~-o z0zK?wc@SiH3%E52n*9bX)NVZqYFi!ww>uBfxj z<<;UEpHAd#`v5e?30fo$YV#a?Ph4j4?L1YK4xO=&2aO0u!BY^94AKM|NCBPq2uiO6 zA{0FC3HI%CP&o}LBTLnNJF5gdyP;*|2hg}D=-L{PZ=hi#3Tg#j@PK<)806hz_{2Th zv^~KLa~0&va;Pu!LB7l)=u6N!Ij@}|K}pD$pg~06&Qql#FB!mXQPAW)*w@0K!Vu!o zQcmB_N{N?DprctjkNX(@2TkHjg1Qf7NJTH`_@kHL?mv7UAK7>3kP1B5L1UKJLB1;k zP30GYrt*=lfkE#8LNa9&Xr%MCD`Hd>JqLkT%Rpuaz~iGJuZg`>1vgGXX&2;`Dv6io z-#}MK`~Y7BY;)+P#y8MW6rdI+14F=ncbO8V2+(eAu`S?5Sg#HC`u>ySp zlKN+x!RmM6SKsX}(|VwU{r`zhcNwrX>mk~jLE84BSOeNm5rCn-9-=-NyL!-mT*&!0 z|9l`#Rm0nkdq7K-)4=;r4G(96`4X!}JGqn*Tr48P4JX-6iR9 z9I~9w19}NVlAv1_uWI<|zye4F8XLbe1c4^tx-T;4iV?0os!Q_TMoU zc7|gv?2I6S2}Cf12o?~*3L@A*1ZZFH0S*sajeiUbrDs90&<|pI^p;zASbp^2cmL?2 z`Ol;I*mIBOXCFK|kApoKak%p%=vQ}#LVEh1LU@SOBop$z$!W~I(D9LY<%$l zzdeITukE#sV3pjPm>KphgQ*#E{uO}uLSrLA|32FQ_OJ9tWd8HKjb%TFBXm8D1~e&keuWIcb9r>PoVdUszyLil2&o!hi>R|ssECTH+2A}l; z_YY|EIKM})Bcn$rd$)@UPbX-DHu#_jzF~it!A!gX4p585xGc*l}9M!6B;i3 z+mlp$Tc7Z^Sb`4u0iB=n!L#$P2V!9?s3!$(N@{sD{sbM*Q6l1@c*E1u<*Y_A7wAkg z4Tr6aubB+rdV-evp{f*utK@*GbnJFzaIt()T-;9?b_i zK>1C;!`eqhqDTwP6wl^kp#Ev;q1TeADvPhdq?W@%O4+g7m!yWJH$EH8NQyI=6^3|A=Q2A?GM z4P1<(GND2_DkQ}ie+y{v8j+}dd($-x-$L38;P~_G7E$r&HuO-u=VAG&nBB9}L zcvv0+1?hA6;cW2UwPQDnila3ff9pa<(C#1~6&6QpKNkMhNsJ5(NEtLlMa}Xef2%mC zYYNV#pp(J68GIC9cv`!0@V7gG`sHz8Bm5*hT2GdA`gDU%eqr$FJOMg{tMe2j)p;Cz z#OcXAcL z>l#qsA3h1?*v;l~@PQU+EjZ^f(9#tS$8Iyv?vigBC_-$Goh&Mj-DNC}oh2$Pkd+Le zykz;iL=Bov?stpqf*f+i1#u}Pe|R!a`2ljPM=#4EkAu&&Jd`;+I6r!Ha)361NqqR< z0IGdof-YGA6;UB7WR+3SP%KmQw009HllJNS?$h}XykY2w0(@8voNzz~xI)j@16>ac zDzm`DFdznaQ0KUd3g`&u{~pjo@xViktp`dxJ$vIcJUgF*+S{P?&f(E5?4$S!DRFav z$|-?jZqPY&9<2vTZ@w0VpYa45uWUXHPV01x6^YlNXi_0qNSy>F z7(^k(a|#sQKFXS&oJV~+H65GlBp6EgJerZh>2MlolvjnJFuU-N*KLE{~?^i#pH z(@nyWf4hr{N}6M*n+%w#24c#+OaU#n>9yUs3|u2CEC)3&K~C8h!31qigWL0=;0_J6 zJt*M`x={2x>_{gU{_WW+zO8Rd6!^D0t9kT#FnL^j>2dG@n}_BJkLCjoK9(Pf1YUk- zVPG&k;A8oLzxf3V14Ei?>s$VoTt)^4{_WXno}F(z4?bb@wS2?h+y^>+2fXpARDC}< zT{DCC3&YEWZg#MZNcupBIC^&S`*yza)qLdH{L6vA`86v8gKKw8I}5b!>eC52@0QC4 z+H!U6yy*z3k$pN(f~sWCUJ(wjUKY^CTLzC#78T#tOC_lu-Nh0f%{D3uMN(e9EZ00N zFYve7voJ7t^|D;@usp`!Yy|Suf3IGax1gHdtCt6~=9j@k^927k9=i@6EBtBHkFFpIR9~{`;YT$9ED$uz_ z-QJ*bkiWHqg@K{lTLCOF9kd@468z#gf*%^(j@>TpES=5@9^Jek-+O=u)VMsldoF@v zO%+sudmMbg>CtP$=+Rj%;qdJ^e~As~bUPOY29o-R5cj`U_voDtVtVwJFba5Be)8aV z|Ky>0%;Wn-kKPhK0Z=CqT=9BzJ4-;a1Gv9^+*yT@!Eq1BO=->5Dh&Ls_MnOYax=?; zk{X}R6CRo`KrZ!RJOJ+CJmmE16#>Vnhvr3(#)Du>558pfVSMS)%X7l3x8#KYw1eu^ zYxBaR^M#M*36KFEj2}ESFL-{x;MH5g0Ctc^XO4=1Pv=!1(1~|o*ZFkEfKDxa1v)!Y zz@xibqVoqgi^>ZA54n!SUcD^WJuH8e zNqd00XWy@S^_IK^JISZ>F4!TSov-<~d#m+2GNyGptAPS-7o;_Is+(s5I4M|zj=k)Z znSc~{C2ElN2)>*S>d8TKI%vcdbjWJ!fl^WEdN3bGL=6wxcIolovyL4-vc*5J`&zk+eW#5B%_CMIf;F zK#dWd3D6{V2Q-xW{onupX)c|`DriSh_;iMVjup%SozY;U;?ey4fk$ut1CP!Z9tU5r zdi+1&*m=kibQf3i--Kco!;`PGeKaq4_U3RD7@mZ+=lKO#`1l2U_yqU`U3e$(3;OUb z;1_V=Qvit>fW$U{#14SO96(|LAh8P|u?HZr1dvz(NbCbhjKQP%WrIiafj_0oL5Wb; zqxqnK=l5Gk;RDk2fnR`!k6+M*>jS?a50^*tK?TqMhf1G%SlXz76SGfuhzbXPiw;l^FmM+=D@(fu#cCSfx)NqA~>}p{DN7ZWu!INt1$4l908TOoxeT0-6gug)oJq& zM*fy{j0_B*qIfH4k4on^k6vd94^Y9`>7!!N?XA%1qvF87Jy<2JGepG<$7zeN^1K zxjTJS6uP}xI(<}Be0o7Qk92!;cyt#Ffcje+pbY~C9>*P^4I@zT$>4FE8C3D|3pj&X zF0ZXYzRBj`4`cmc&CI|r=nOjJ6?O`&N3RR$CO8)r4^XQr0HhzphyXE;yQqNfYzB7; zJ-~kV=#)_bNkeUOQNh{_^Xaxx@ooLj-_j1AZFvNmO7?)IH}DbXpb?S)k8TdnP97DH z<^$k8>j56tE-Del;-LNpXyTZ|$2vttpjgwl^?&K9*Y=>k2hN_*X+^h%8=GvqvFC) zA_&@O0Xitg4b~I!Ks~wKqu2J*Tu^9=YRqS5*k{Phz+ebJ-Woc-6yVWa&H*~R<={&# z$N&O=%X9_?1{ePA?kb?2bj_Ba!~r=G0@Oh1{NSm0z~kUMgXV|!;IV;gr99x41hWUT zzr<@ZpKgB%XnFd{v0G%K53G^|53E3&@8FiBC-an#pvuXkm**68$`#c7Qx^2$JOpa{ zD!X$)H$k)1Gk9iZ#-ZFPHrqE9xp)~70L7g!kkh&P)~saGLr@CzLs!-yk+TfPNPU3BrSj@%@30< zW_2}u`%7dZce3L0?v0%CxNmhp{IdG_XMfX^X9E1yCAKj?UsM|UX$xV7hY z%>(ODhez{KaJTRDYcWJ`5VS-ZD!$nh8sx4mZ%Z;kJ-}`^+I9RqlqEel4|{Yj5KPYXMczASs3qU16 ziys&)f0UR&<#b?220M21d3L*;(?Im0`L`E?deHiy9<&Fux5Voxa93FIC%D-1xeV%l z`zqI*)9~ax?$cRw8FVtMWBg%IHw!w%fpa7fTvQ@=vV9bPpp=##;L;M@{3fc(xWnUa)Y%!_wuvMv;aGXdNf2I&n;O#mt5W4sT#YnjwOm zcZNC)06uK16JUW9Fy1BbSttp?=8XleA9IXdR z#Q3)d6P%rLfu5h`2pW$F08Iq++D@3p%wTxHqx0+kYo5)u3JfJSKE1YG)0i22dR1G% zlxZnQ$!$pg#iRAMPvk86&z!Q8%HwS#QE7tM<16cj#aoinxayjJEdXMAmpp3*X;0|ic*%^U{q1-`~pgYIm zvwy%8v6_P@V${ol6o#>?gD8ml0RHX%Dxkv-WcauHgL?d>dLG^Wpx%C|L$^Pu zr(YTju9kO9VFpdb)J|n)*moavYXS5U4v${jxe%#RkkkWIsV0b2K1k{zs#H2eDh(v{ z2uTV#LpU%H?LG;Jad)R+y6^8~u+y)Cq|n^=2qJYJB!%X_;}EH1ASvAL1Ep7Rub@P* z+gX8sd$1bHlqoc>AycQQ4fjn3;JDrmq6D2eq7Q@n8y=lM!1D+ZpjKq_FZnVdk6s=z z56gpPwI01ZpwWb~5?8}ZzMY`a15d^apkdzT=gcJ%(Dtbl|27^mrw$$g&;N%!{+};> z@7er=nZF6t)drgnmv`dd<|D@F)Zrt*2xc;Ym`q?MGl$H0|3TNz6ON#Z4V!<0`k((_XZdO#H2jYofeictEOz_?K6V29 zf-DyNf<6`k`~og^pzfy~sQYQ501`6*iGjMGcA)O3g#$<|03-(Le%gV$pB4!qu>z0g z_YI!S2mh3=@NGR%qUX_kT)^}D4TObh6F|B^{ZBi7K^F^9|I@;w`M84T{{y8@Jwe+# z5C8lBAGv%AfJB}cqA%Bapo9n1pPPCh^0487NYKiXJrltRNN6%fuV8{lw?7ADT0qP4 zLrIE9x4!^_8`}Bd;0w0qXZE1HWqG2Mr}G1(EO(c9ZPs}Jl+mC~|3lp@6H$l9z{6sl z-@v0q%q`%NGLK%C4<6kdNJkwjomkhCc?9wx_jo)4&IfW}io zK@A2+X!-gLbPjT_t?oon5&QodxQ^v-0WD(n>D5)62rgq4z?7{ZNX^^V(VZtfx`SaO z=jXe5cEKk@L5&TRI?RK)=NF<56F_o{;vvxK(+3>?U-S5Xlz+RkiihRVVhxYhw~(Uy zYv;>@FWEpFEbT!V)be6!C#Y6@!0f^7Eb)4aN3X3L$TcASP$w?}O|SOq7EfSi@aWae zod9yVZQKNA23Nx;uj7!@8wKt^_(}`rY|sBkK+g8GJW{OX+xo<#^PMNZ%U74qhX-G> zxpY2gegJd$1SE&=?l$fYX7TBE<^ZiX1I;VJ_ttnS{_yB_7JzKs(DG3H;nB&W;?ZlH zIRO+ipm1tFf>b{tB_fYxcL|UG2RcC$*Zln33)L(?)P{I;2f~_}$GSx}!J8RKT~yH2 zh9~os58w#u4CmnA?x_M9+CS*g{L^6vXq?4^-{~ND?y1vV;BcuK|Mox?Py&C(=3#lQ zSly%BQv%#&odMBz$fNleT;Cz^3^+)i2jr50!_e{$Ix%PYqfEf#;Byv_UdTjUHw*h= z!vlxYCLrVmQRH3NIY0`)?GwoQtN$JcpRxG#f-mdvWc=pQE${LFut%pnu5&3M`%OVz ze8oGSibo))pp?YmJptt)blQf2LBWUfgI6cZL(gt^3r}lzgHj$?mjoo@(`f)2H}ULr zw?JNm1yk~R7Q8kt&e(Hb9lz70CQXRse4b1)u$K65ey%^GtgN}9a0Pi9NjktSs`WqZ` zw_x<>bazNQ?(V_Jc+B04@fbS;QhLNFUwnGg7(vUrK;w3x?jyJl4P83t*?e5Ur_;ix zGl9b+*_*?o@h51FJbyD2=*He|VUJ!DPmf;P*q{3#4weaC{x2wOkEB(3T*0DFcZU67NSgLKr!_Y z*eI~6hrvt?Q(1{Jbrm~u2y6ix1vYgrn2BL38&Rf)pqNTHT-k{-^&cCuTT8(X1iQ5c z%*1dj2T`W3KruBNY!uj3hy@s?auQ`~5Q?ew2va-2Obk=Gh%)sLD{=^wfQQw1sp1pYzSS$dqP4sL&BH+`h;L(|ZTITejSP%&|6>LE)n2BM5 z0;UC>8W^TppqT0fHVSO2KbVPODyY&21;ai>QHjOWN1(zRUXrPRjRKph3ua=NszH=n zdr(Ye0~-Z4l^e{&FjWVOsTLR^V1{Cd!P;{ z+^zj!qrj$41~V~Cb--dOW-jPJF|`A16xh@*FcZU64=ko)y4489)Nrs-U{f=}Obk;& zwLW?-z%&)SBM2S>zF?!krY3@!7^Zp=<<>UPBpKY)WUx_SQ}e-0R8z5;=+jw%T(T5f zAkrzs2(W2Y*i1uh>0_+?Aj+p#RlgZ@Rktc= zfFIQOWn_S~{8&LFBObl1s-OwCPF7I+Fzq<29!L`-NF4(MNTo+7s|f=G!!cHC1_lPk zr&;7>}`nt`}hRIL?{^Hh_`A zqnFie9w_6m7BDa{q#b8114|rZtpw4>SV4DjF?bwj1#MjbiFh1m1zlYOWkR-|Fn|=) zfP@$r7>=`oHh_T|ylKZ-mw{{r*>N4>yA5CkTR=(~85q-!vw}7%GBO-z-2)N=IlY&4 z9YiT8QqqpIo`aaM7uwcl^yt(Dtt|EE)CC=?r2z)!!B_NRr3K-DQfR3=P zfFqjRf4FW?N;DLG@h6!HE+TETD-h@Y(AM zpi@6vKs($)mm(na7#;vyICOpXeY5Gwc8YwT3f%BM0@nwzP%0_6aYJ+*%qAe>#RI_!L28s zUeg~SS<3Pm~H|odJ7tLF@lcAgIBG0n`n4+ zhiGv4bbj~jya64F_WXauBN?;;viYclr{$4aGf-G^cy!lj2zYd}?*eU-@Bm#i!QsKb zuLtZJkJgi=o*uot-F3_iEeA>$`*gm1J+H&`2DGzm1G=F!^* z%BLQd$BUgkdfOrFW5wo%2O$3E-^Rn%!NbnK&4-P#!-pNTUXYEc!-t&-B*NU`!_Mr{ ze1OHn7NoKC(qVo9Hhuv=0e(StenEc$egQWHegQuNenEEyenEc&egQWJegVG#enEE! zenI~LegU@xegVG%enIyHenI~Net|YnsPPN*fv*1H7ii@KbR-bc7TC_fnT5xboURxU^|#6*bn9jv^{{xfyyX;!FDiDuph)boHhY8o{nQ{ z8LVb2y;7WEY zn2B0td-mpG=_*3@>EP-cw4qpV5o{{hg8N`5h6Px9H=UU67XuViUxAGRoBAHi#4r_0 zmj+8e=9VOKVA#!s2Zk${iD4?Xehj8tTTo2Z2O9-;t0kC;VX7i5@{#&6n5OEXnCb*J z3T&zmn2BMk5>ck!kU$OrFR)QyQ$xW_3{#bfGPMcC)F7}?U{gcDObk=8^yE-_xELKJ zMHCB^!KQ*O&;c_sEWp;O!)(x>7Do;YBvTc!n~JTYgc)(AD5hG2jRL#X7RtCD14?8*ZnF+F*O-sY7&@<;Z{qcLO>S9)E2N& zV7In`nHZ*85oPLeQREPa1RDi5H4)6jFx8qUQwvc{-3m4eZ0Zp(6T?&+qD+-WG4&|e zD6pv~z)TENv2|-PJN8FKKnq55R5(BlL;*yHY!BE_u=$6;Obqi~h;ntR2yzJj0~-Z4 zm0=dB{6#g@w>J$-w;82yz!?5wL9qbhRjH!LklC-Vg8V8iU;m zHq{Kw#4t60C{rU)OkD~#3T*0fFcZVn5TZaC7^X%LW$GFsNK!XU{hyRMVfnw?ugsJ^tCWfgMSWHEaJ^p6UxkreCCmU=O*sUdCCWfh% zM49@AA2|ea!A5~itpqbMOsyiy)M+TDdVq}ro9YB+qMN!7)Xl(RFlKAS7R6veuxVg} zMZio9gTeb|d%?TJka`1HTD?#Bki)?SY#P{LXD}1PU{H^UC>M957~BUo4Q%jKFcZUI z@F_dQxY!8A;N{?9Ah5xk!AuN;LESYhF2+n~H+hkR;ttp}u)+7hObmlTcaUKi3|gkk z;nB%~(MqjGF?}Q0NU-Urz)TF&!N+`Jh6kpzl~4@!0uT0q4Gsr0F$@Ncm0&pA2TM2W zBoA_UB!Nu>8=L@UVi*kS5MwbIv-T`NF?b@_G_b*w!AuN;LBpL`48{x!aTJ4l!KQ%? zo(g7S7z~=bC(7V`+{i((5^NgS;EiA=hQXj=PofM?MKQP?Y#P{Lh~qH~1|54$l)*eG z2J?e<0(F8776UUe3Bq6oXm7rhyIS z0W&cS1`V}fxEN>l`-8GF;x8hgS+ScA8lJ{5-3Lphw;09XRN0cQJhryBSH$m>Nh7!qS(gCAly z_!_Y;Ho;}^1MCKaE?gzb#kWzGV%!9q26pj%FcTvvK+`is8Qg?o@Ds3UV1r+SnHUCx zPg*A?xoM&p{1j{&K7+wm0TE;H1(Y=ze-H*Uf%aNr^g`Bw5A7tz;Bpj$e<2M13ua;j z1$d&C7=z_d3}y#A6C4!0U?zsacZp4IM^Tnx`~W)>Z16uY6T@K8aXmz(iX0S!kzCA; z-Nm4JK%xv5MlqNfY#P|b5IZnj3>uXu%HUln>oNX={g2OJ$UG%l#fP(gia{}*1>tNQ zX$~}_LX@*Xdx8<&rw<5ce*rTw!UHrbN|eE?P*!LB1e*p94@R)#F${i1Y?=#1F<1m_ z8rWcQFcZUI&=eq1F8;xY+;sVbaPfCA6T@K8Obr%;F&nh=Q4Br-HVy3JlVB!>!JwID zECyq?0l*g+z{i;;f=vS(JQvKwF!(32VGKIU0g);ugG~b)JRQu$F!&d-27}fSAPimv zHVtg>N-z`6;KpOWaTtug7{nf7=mxM!U_+09nW%<(blyijT>zA#L6hhA6TowpT(#KN zgfMute&cUh&A`9_TIV0^(fmfhv-2A0a6kcf0e(#u6_3tx0od7(h6gmx4Q{s9vn#l*jp&m;rDjH=V#&5;XaVs z#;4cxB}n!*V$RmH+Z@|;xM%Zm4iC%2H4hNe;Si^xtgitNM}W=|0ME{Y=9oKMR6v6t z$6QqE84y$Du~i5sRdX=Zm3VeO^XXN+5)Yaqx9tPTz6I^E)lQq>(ar3Em>vJ`+xY=L zJATw7*_p!wJUM=}))1@^X=>c3^V|Ob(A2n(N$7Zua}|D zgo9iOo(Tu}0n1EyXB;?H?Wshc32%G@Y9e`d{%Sc;V#u%QqGG_W2|5`;GejkTUo%D} zfnPI4rGQ^^4LBh9HMgjM##Z<>_o#qJEIPr*XoaYNk4KR3>2y(1@agnXft@@F4MT8m zqVoZ0nG&Qw)S?2e&^lXGz`f=jpc4)ZKzXdQMFrA9p8}>0|NC@a163jnsNMw`Sjyqi zcm(8l$aFtsK0W}ZuJr(DHzj!G2i|Tau7QL zNpDnx?Q_s1b!kkuEvSkFyW#%@k8YTWCF{UEsF@{ez&xm_C9A+ZsJSI8z&wy?pfl5! z{l5S;yJQL2R7B$CmuEmqkKp<8v(5D~3?=-aBNVzB96Mb(UV;vH0iV6_4Rq}T;_~Tk zebDuqo%)btShTR+ilBJeL-FwUqo4!t`CFJk^%rPpfq?;Zp%%ui2%Lx;wiJ9o$CB~f z0BtL`@U(VOF(~DQ?Hvb;!S_eFs91omy5jKcj%Dc9hMpYb(R`f4@SEW!kItK}h6h{? zPlCM-3X43?&ZD3cwPYAdqkTHxdNd!c@a-*8NdVnk>Veo6t$4z*+eanAv$F+!jxqcq zR2PsJdO>#-{QnO*vauWa;)L%Wov*-Fb!&g{Yc+5pzGB>fbOC@_*lz>^ROpqY=D8`03(AZ=UvcE7)QZ3Veo7CGVp7J zB3*>B;0F^!8h_c1&yM_ccrU^LU)Ky;IMeN;!qVx%fpqCFj@>QDC)VHffZg$1;)i#4 z3nBs?!1ow5yQo^DU`GBr6{LbHc2vk@>au3*s>-^2lAXh7%@UT3=-=h2f|Noa4K~^G+={)9R z_zrr;2J9jQa9M|B%r*YzQiL(BEFgy*cLfzI3@<^a5SHX!p){9`IB=;cdAGT!ip9gDw~VUq+@4 z@)x)<4?cJueE$-nR0UrV;GuZR6M73Oe{(Y^j9V}9x2FI7|No@~$R)&R1l>|~iN6(e zmio)bpn!sDI*hz;|1#(>HpO3_mUAE%5}1NEAGclroy-I}&d3v#wl0D$G^p^fJjLJo z1a!&5ZBR&ocqc(T8Bj1<{^D<)4bmhAk^`R;pbNi46LkN(CFlZ86KG-tCE(T*rK*qv zL%;!mI4wo-z9%fqnm|G2(GAU{R-lEfow*z@gFtZrvjct^$2I;YH;@GA8V*|!1Ch#G zPw=;DfrP-Cj6hz-enkf89)y>WyPQC0Zs>Y^M>hTz=;khv@fSf1RO9!7ga{cw^Y{P% zuc5adpqU*9ItB}5b|{E}YBuPyV0cjBy8c2Id`(9V^g0O86}S%YqLvY4X6JE8QBtaa z6bqKui|st1MaTlsNo1hX)B}4atqAY{Wzeah8d84bFm z0F(LgLsM>355w%ZgqnT@KR2n&Rl_)R-oI(Ky5upi46C>kcZ{I=!gp< zitItRLs)^lW(xNjjx^ik^Y{P%*L*&f2f=YB@iOu|=$eNY%@3G;I&+RPy!8D3|3CKj zsQ{>b>e0;rI>q^=9qg!Y3LB`bprRF$^=Q*T^&p~!non5^)eYnaB3h^(uqLWUr;ZBY zCMq-bCh7x%O;p}@L^e@D>&~I;wRu!L21y(B9a1B0@U~Hpf=U^}ZB)>;7tm%ar~(FE z|CIttEzmYt;eKOmq(V&(Gw1NS*QCEVj#NS2*?VdrdqptBc`yz}X zxs3|mRRGD>Fn^mP8Ap5@bpc41<#qmM(B)n)AAoqc8ksjilAuOrIH*#63*zBY3U2U% zl*)sYf?KD!l!6L6P~W2IGN|Dd1TOZ7sC}u?_UtF8?dc2BL~7gfJE$26Z+rekv^{x1 zrZIz3DX8uF5flV2VBRnO)_)i%}BHcTpmaQ)PPF`F%ZcO)b>O) zSn;$ybwM7&+4f`tnF=!gC#a!`YWy>h5V)0r$M}P|+n%kU<{`-J8W023>`aglA+ufZ zv^_Pz2EdvrXl+jul(r|nwwN2J*+xc-GZoh21oa82+2Z7Zw8cO}2H@62EH4)uK$>PHS6_ne-GVeCF*>Ie)*z*1v@^kFH#nA%Q|09%E6{bgM7A@n z5$#M+LG1w>0RfMncEUU(26CYZ#54RYpru|f!7H-BolDGiCe%YDw=UNqXJvTn@-j)S z%Ph3k~`nqbO8-Gf{*8|s6q@ldiBa|@MwMv8*p3< zYR&y{>HG*969L_m!g&xn=I8)w(49pdbL8gN2!;(g5;fMi8gzL4x(`T0vEZY6Px*9y zbld^jQ|Smk{{`xk<3tQacHTwqYJqN5g`Bm+-=YDkSP#B7YJ3bDV)n>9jCrT(aTc&m z&_Uk>pU&SN&4(+%_vPXr^!4m?Q9)dp3qJ7~cf0z%N9QfDJ>4!UERNtC)cnaGWlf~U zD64PhS+I+IJ72zRL2k&M245TqxzzUcRL}p%eLHPbpjZE)590fD{zVUa$M45Mfz96n z>Rfvsd~f8~_#7nQnRy%|^nJj$*&g-iHU>>2w$25es@19O(Ot{|<|~7u4|LLX>o@*Z zaDNtbjRI)GarfW<|9v}8dGvatjJ$pa4Pk)nWncggXddTpoe44nBE$e1dA-ix90ST} zt;c*jFY>n(feI36t2XT~c;wX`;(ySr5#%BypKc!&j+ci2Ayy*VrjTKHkVTyzd<+?88q`6DHgUnmT<32th8V-& z0v>if?hF}&eFbXa;5X|$0|Nt^SrcGp%>!va?hF}#od~)Zv-5)|=r*e62S_6Vo|-54 zJNiL-EH8k((R2oMf;s5iz_w|i!OFcLDbUe%FSJnffv&IU*angW4Gh_X>;h{#3esc% z;^NYD1EL9R*?Ca&1+4EmNZ$bv7neTBi0^g&CQ#SJ1FQ)=;=2ue`!UFCMjo9XJmBY` zc_{wywrl}kfz96xYKwb7BMP+Y;^l9UE5KG6d31h4*7eKNatc&e2FM?+=lEOW|Nj5~ z5OMfQXLQeUC#`PRN=;cM0WpAPfN(f-~3IG zxeaKJ0}ZJ9bY^qBYz4I^A;x=vjrRZ!~ogB-vn;b!oukzQXQyx z5pGYj1IX2&S$4>AK}

    uLIqU8-&GJ{wDCSE6BB5 zL8%5}<|+`AkeRLE+jGIgr6no>o}Dq^+jD(7;Wg|_3y9Mo86Q4q3eK$;imhSkXg#RY zwh%lH3QB!ijwl(#Q}aZH9W>VJK?iY``Mxgq1ZP1bkIwJV`9IJSC&lC5mV3Y{u6PN= z>{37Qa4FQ=l%)Y7aAUPt05moy=F^!i06OCsR0OvKfv*3ZifFll{0AwpTHlwNgL+TV z1X5VBl@BzjgC;6oE(fJzaOh){6%}$I^AdbJFM@JzneOXQn9j`q|Np;shk6w`;S?Ex zRJR@|)$(aQ2AVMV-~rAV;>$enMYzx+ywtyV*U#CzEo#TtcM= zY&NJ`gH(OAX~24RyMxZ*Q{nK1Trh#B1>20X1)D&53w8}1TdjNyxPu2)0X;AWp;HE;WI)9r;_q?b2DGo+0-9QegpUr4$pG7pjaB#Skrn_25JNJ?zjK{ zA?sgJ=I1p$JI{f~PenYt*&Mt5I6m+nphdzww(fJyA7!S0561FPW4rCF=T3kd3bDr=x&H`HW%;4BuE5lHl?c1AH z;n|y;0A7KCv`*xNW4AA8#q3$of^g8f4EUqKEl;2B8Wjc4#^Vy8JxQJK zA@>7=W5xr8*X^Ui18R;6fRd4K>$eit51#-1I6y)YogM<9HNT*XSUO`FNL$4kMcVkP zD|itr(zRfReL5it=_ROb2Ip)Ax5^+gujhCWh>=&wF>=a7@enLVKrKNJyfNa_sdB;d z|8dW5Gf*GC6|{81x6{tEy9_d{stOvt>n;QJ_W4`EcXxD`Nq|(gfEoax*@Ip`^kLQi z(8&VOXlLtj{?=KbI0Lx^bkrjQXdzT{EGX->9`oru&EJv;YDqxbq@jQR|93U~|56*` zeUHw|(5SoxI?zzyr2%LPuJb0+N>bE;)gQP9R>A9AThDI+a2jo&QL8JuVXtKdOWkXdseWkESQXgy?qRdCp1a6vI zUI$yY7u4PW50Qe$Ro8*I;N}OUE=17>A6GpBide8F@VM$$yyL1zL0O%@IRfM&Xgm?o zeue7Fgy`aLjRQ3+@wZ>ELM*BSIS!HnTkjJdSA|*xYT<+1uP;C?K^*N@pU%@oL^fd{ z#)8LH;aN_Jk%7UtvyS6s3%E%Ny5${Z0F=L}0we)y5$1y!kQQMIhzX7oaAO9o=7reP zY!7lZj&W6RJYNMh2tg*F0WlyZ9|SQ8nLGz~`xTsaKxS?Mr5cEtD?v;`X10LaueBbY zouvW3ouv-&!ciaMA|FFgc1Ishweo-_pBkorl(V{Q&i| zIcVS!&uA*dy`a%lP_(v!M^iU~G70vQ1vHv^p(w$p^E5apbit#kV4Y~Asfc!Zkr7CB z>wkiysbHt@HyMKpIf&m%d3-zTBz!tgzf6O)Iia2+G@1%F2|St#b{cpz^$w&N>(hC< zq!MK6OJT5)*drV?nhJ^{e50u#d7?&B!LH$NiUv1ke>6W}_U*Je_HqiOG1~&#Foimv z3UAMfdUmsUg4(kl{0BKaK@HmdRBF(+f$B6!g+VjauknE4VZSRU|L547Q>-YVi%WlG>=nH`q#iqZT^Y3i1W^!B#|_eFAB))dN($ zqYt*CD1{ETf(&jt2O6RTw`jqw4lK=9_+aZJP#Y5eU@N5TZ-x%Gf-GnyzOf1)Y;6Ns zL{wvS8B$}F1>_U_gRM~K!3SFfKo-%svAPD_{>0K)T>z2*HUFlA7?9>)4~Pkl2t19| zbV7~QU!Z0n$mEY82E^oNASNM`K`q+X*cSnS2IavE3+{kgs1P&3TeJw7xdvBbH3Z@! zXd4H%XcgR{yig1pV+AK4aAOsHj1`fZ&x6NUeL7F$A7cead@*Q@)u;1xso%?N(9kI6 z7%QlaLs~Oc3Dob#+Dt74HB--^HB-O)82t=TB&oAM6hPCeUD#ODDWpdLGm)oq&CO z71SODjjy(I@UQy-9$?)=rS@nus6wQEdvwqZumngD7(KpUeW(8j11#QUQoter@; z>;R6i?g6zoz=NgW5!SUJF1XEsrKvjfMp*BSj<7;U(yxG;gP=z1X%GX_z&rqAf+HJG zb9gpAM_BbBF2deu9WEoRo}i}dFdtz}g|s-K5lNL1Rw1yF12)1s8OM56`1qg5?V^I?EK~~* z@Jd$DS*YFG-OfCnE-E6P-8w2Bt#3h#SS66B{JnZ*R-hgQ;Gy`!rSm0dxf=8+0PL$+ z`8BvnJqqADs18GJkv{Y3`~*I()u;0%mX)kW!Hx#4o77RkbE+)TqEqCRtU(~#h-{YD zsK_vs=6Uw!R`~YT5IX)9^(27zAZt*YrX`@&tj9pBS$#VH`+%;Tg&YHm$^#t@0BW9c zbcd*jKvR@&>s#=mR$uZD3&&@>!u)7485hy2B@b3xi+o318+IM|n& z###QRrJ%7^#L(+B5EtCQ!8i0u&Y=O&#jPM860=?ayoH;;8NRrcj6(y?^0$KazYuq5 z0DN&P`k?`+o3qXmySNqNe(>T}c#Z?DC->>BrvIS?eXDQhS$vzbNR527%~{om(*pEC&DuF=3kQf@-wJUrXniXsx&~Z4SSz1T7?h-M@jlo&en5{o(;@@QQnMb9;0L3wU&X_~606QP8vV*vsRvHt%1L zPSD*8h*jzY_HKE0zV}qT?x}bj*65u~Qls~wS0~R8&`vFEd$$xIEnZg(pKfc9Zf60H zP8Su}QddZmw-UOcMS+3At5;?RQj-_5%GIUwCsLCabgT~p19+M18PLY9BcPpGq1c5} zw?2Zbz}?t=j?&mg=7HC^dUW%sfSO4Hu*Brs`XAif1)Yr*%RtuNEfSl%puJn5)~-i) zi3*1&xVbCg(R>88xeM8{^%6AY4jYJlxftBugUCReyLjS=;^yuVSaWv{_<#Xrc;yS) zSpvQb2Xsc(N#y446mWC*Czj^!b7%vc3*=y zsEu88v+yl?oe$CuYwS(}agZ9j50Q6rK^MJ(e1Uz@D?&B$kSyq2rj&VA zUWGvx;aK$Q+j*YYMl8hrsEt@qKJw{I=6Jatyp9#iqSwVB2~bmW7Kj09YW9PeIGdUf zdz!QGEP4e6dDAOU+Yn^(Ll6UE@-+~XkjWcyH)3CadORRA?}Hc+Gp~S{gv?wIUi6v@ z-l65$8H?DV$iqF0c6F&Die0^kIA(JLqbAd6nXfre+%t8eFd ztV=|3FM5TZ-34l~CQJBso`2a5Zn46=Lj0mvu+xwiz4~^Z2OTVsEb-C;Y$Rex7TJHG zMXwb+`LA;L<$h3GRS(u!<(Fsh*zxbqt{G(^Mgkt4?gIQ8tf%{# z82AO*5A(}|oDR8`4tyouXV1?6F5TkY?krBdJVK2R|Ns9l-^uS{d9j%7{{hENcNQP; zs%lxrgN~j4ERM~O>|I+g@wenMF)%ppaA06y@YTHFYx#k{4Yb+P7jz0`2@3;*XY)UW zA{Fmm7b^*`ULIr6WjoDrj0_Cky(~tay)Nt$9+o%w+k6-q7z|H(be{M4e%*)hyHDpQ zkLE|rC5qm?B~}tB_igcSW8v;#;q&-^(BuE9(vP6N4Sy3i3&=nhE9tZe{M$shJ3=`A z@^1^_X6y*z_y=Mzb%b#I2QipCL^wQ}53+b#o-4ij@(MEpgJbhA!(vtcULPw7kIoxD znio8p4>)*Q9^`MH1Ui+j*F6I4K+p-ihL>DAFMhx2)oUWO-yYPG(ERSv{E)ds8th7F zc=B&!5$<3S^Z0+rRkl?@^5nyX6$eg{0Cw% zb+`!r2QipCSOh(q53zVyUMs!&5_A)vOXs2HM;|( zBg2y~7lB(qA3d5MKJe&ud;mEsnbqU}@y=h(kC;80e zAXWm1^#Q~x;1^`!^JsqA0BYEmt^nO8ChGD12FQFzenA#akLH5{9{&%NzVo!az~2gL zNcb=w_SHP**;_8L3mkTx|G`Zu&*py)MUs#ta=@qazendiu((I(VaMiY_TZHF3$%qF zl=8$qd);9Pueidy*Tqi4!}4%(p5Xz|H67ot`7nNin8aKn#t-)IHXdfj4j*>VC5xaG z_8xS>2Y=H_(3xf^^8DL;m>EGTB|$7E5K9Wg0_&FcXg8vFt-!U`Z!1F)zCSkwa~>HrcA0E83@(!T*#k9|(`H+Ig|AVEEJS~s$w}8$BczG7oveUfo-P;0AEr#D< z>0N-um|wuh7?d;&Ch!aT7=Y4;G03&Xprm220VD=WAI2cJ8iSIC!3B^QD18`%Txwjv zFX&?MfnSivz@zycD1H0^rH@M`dZ1!M!{hrcM4AMJ55hjEo?{9g{|}Wu^|AcO-@4=X z|NoGiBGJ!R2>^{f-|*=C&>havozK(lFW}KxqjI6UTm)f!+Jw%_ogpe)IzM%u>%3_A z5j5)1`A+ep;YH8R3!uilOSgbaw+D+)r;o}G#+#14Q@ARYWL@{^3{iP-@DO|FN5)Sc zov#glDqeK%HQ_M)39{iw?;69f?Z;mnJj&B~k@2eGO~sep1stHkfD?u{L7nXnjQ@J~ z7~U>WP&s&9knw%zOT&wbKMgN-7w~`-9bmlIJICgUU8AXWtljdMtWnv(_}lQJOYa;>#;I<99SP7%B@qapL)A$AwWTP~e9T?|huUUV@$*RAu8j9x6n}Mlm~{H6bT~4eaWQ=5*1JS$ za^Z}>AosX3{&DI2?P7S_Me(tV;cd_m$ct_d3rEJYou}M-TeSO}E0;MQJRs=G_`s#} zv5Vnv7sbOahQGTVY#bR6cOL9?QCZ{GJ4afPV~Z!mU58ydZ@U;C1{-(Sr#nYwhb!ZI zx86P0Nvd++91k961vv<6<6#%W+m4K1+bT;SFqdcYbo|EKynE%J>=Nh7-RpKgZ$*mu?@G9#_WmAV)kq z`%n?9Bd&B_>I|s@Bd(NLwAVE21mvVAXnUE%1?*7!nO05tKl=3 z&d)B2pcv`SQCZ^1_}Zy=j&zrgR`0>XA})-F9S!d}G9GvDonz-@`Rl*q!NV+$jJF*- z@3|Tta|KELaqr!u*7&Wk-SOaYZdb(-raI$y}3JI52`<8$#b7g!CPP(Af=E`^- z6a*{J-}8oA22QS^1PAup7Ul%+-QOG!9ush7{0Ge#hMz$}GX)eh1$*}Ib3AxN+?DYQ z$jgQxFFQgKz_Gg78pyVN2IZ#i8kGl*jQ`zwTdaSnFMQ>A@Bp_f;|-XVhd~p$2OJsC zx%F-_ZZ&v+1!C_put#pYKXGc*%>ScE=78$Fi-!lVMP&-(tpb}(K9xr6hB;f3BU1{Y&nS`Qu*Wjx0mqcQW@G&9 z!uYE51jL5kJpvD&>HIr*oQv^3vyaLQu=zg>Z}j$Xh&VGYK6sFy@h5YMN(a>VA1=K; z1`7o_{2UJ+6m?`g$sD7y0^-FJh9`QbNHo<2e?NGL&4uw4bB)Rzuq78<3{UiKu`vB) zwfEpLE*Hj+E+ApXYn&epFZA|s?7nne%Z1rTrKj@(bBM|okcA(=U*J3e@_Y-&#LI23 z4;~Qp=+063z<8GND6@~s4`ve;(AenWt9>3qm}@Y_NDk~rViC;Tln;I2c6%72&6hoDjN=3neZ`W~I9 zd^8^&V_-Puz{qgSfr;Um12e-h2Ns574y+8v9M~9+Ij}Q;#^pVl4{?-U2Q|{n4KE#I z5nupyCM++OetE49Ht&ZA<3SJ0gJqH)y){yjj?GVgI5r>QcWi$0!Kd>XxGC(o2h?B& zx0=CMg8u`H8lLn3xz)3`MCC{4C(c9P4)K@7d9;2jsqpOeQTg8djNPO8Cwq~ZN9RW$ z&4(V%2RZoV8HjT4L9lzjmFOFuJjTMo0P37so-6(GTHd4i*$&Q;l|SC%aV+~DDZ2rYBex1fbRJg@aT;JUE6&h9CRL? z&*2@PZWiz~0f$F7FDN8Ex;Z_pdsINCm2!GC9syYw4ZU-F0@Bs(;QkJ&{D97nt=~%c zn*Z?^t9Tq|2iX^K*rV6>=0he1k6zKgZX%ldn*9p2e!C1-;PHnM= zJvx6IzJ1L<0b<@!k8b7_j3tko|8kbUCC+W1C%itvFVFD7qnZ65l7#^t&Grl>kkEa4 z9~|fHZVrKxe|MUL#tfkH&IKS99><+MpmYF~P5{xzoHH1rk(@i>B}f$EoC%bg7XWg~KG4NY zVE05I*#*u|gycPryBmO<!p&Du7BXn>rsw~|4K`d1rC$vHr%mwa{NeHcxMPD26GQ1|kKXwI9+o$Y(mk60 zGnTk`YX0`d!Ag(6RR?syM6VN5LlvXG2fxdO zm(pMX+Z`{N7z_`9b1FE{z^ucdK+ORk9tpZF7BuX1$m9Qk1{-mZe@>=NXt3d9@aXkq zEdA!w>-pcu@>EfzNApj{5_=EL6Rw5_JUf5;^@^|?o`jVTj-UZfD-pg@E|32QJuOd` zzI!d``Tv0D|HGb^2g)wLmNxwVTGOZVy2tGUayqbqt~6O zp&sOP*W-shI)9)fUr4IT&oG5hqY_Pk(X@aeT}f5F7yYWU6Ytw%S@OOI{|kN-zKI$s!G^7#JE zqnqWTM>mH@udU7tCWd{_LD!LV-h$ifD&W;^V*s|>r}H^n7;YQL9#o?Yd^-Qb)q%9v z7(kXx;?(cid`!T@@+*H+93&}bJ_m&exF&Fnag240bBvD#r%9h)RdG#Fh?~l5fKu%Yk1X6JOwFfwTBT5yI?otDf?obDhZeI(Z zZdV1LZeI;VNJ2c|;Mwi#f$Ra$xy&BjIybsq8CnmNY-;|&Sb7!N$WRZD?$Q86z;~A> zfZQqI(QEr!9Ue@t`8;}U-yrxN-L(Z^54`R;4!RTlKj_}J!(jKKWjF?u?B~M3;1~w# zd;C5IYC<08IM&R;z`?-a@a;H%i8ZJZ3Tj<)fCx?y!383?K?Dzo-~|zUAc7y#k+5Z8 z;9w{{^IFZL7iZD_KJzY zqqA9pfrG)Lceerq2g9*u1qK1AyP^#bAm!I%EzBSV498lS6+tE(YhhM`(#lX;1xl+z zX*DRV4x+&wAc(uSyw>#S1zY6N+id`{9G}xwKn{X9T?5AKWqt4x>~sSL0S1rb%@#0; zJMx8s030|Tf#<LlvVxX7@@uk!TJijvtf1>8eL6R1Ks;0cbNcb-1qkL01aks{*@0j- zAea>h<_ZM!0D`##!Q232_U^vGAi!{}`2vFkBoXkpfEpx*2ht`SYheb-f#UxnNcpiA z=1WleGL*gorLRKiYf$<+h(?ZokH*~~+d=y&jyGQc*#!>Y<{L0(FRSQdaQr@CkYFea zffRUghdp}1F7xQ^egFz4e5nSzsrw(nP4#Fz4D$9qa71<9hgtzHOu_jX)E+z54$5Z? z-wyMaxFTl;Q2T|X{vybj(zD=X4`O=sdJA~KTz|s@DZ6@fLVAJ6n^{1a1`;gbq5{P1 zWxetY>;X_7_UPRW%DBgxB|yOoE=eK{55UX&V=c@eX;6Ggf{Z%W!Yl=)rJ=M8l$M3k za!^_xL?g!+*x?{+JbJq|2<2B9kaIw;Jr2&|pd8`R%W42|I4B2u9B&3?TaW~}F$&2) zDC;jHI)5Ygpj}h~p!aZsjsoo!{hjGPQG%i2ARi>cFFym{8~O{JE4_Qy=z)&&_UIK|uEflMVdy>%4F(4A z3G5K{9?)ZV{CoH4acD3wqFb>8R4aH~e&BKN1@BGM=4?_zmPsTT1y)DY@Ad|n}_E0?Rsd>N5*rWA!i5_U3peEADPxFue z{4D|?8=7tFL57xadw#$F!G{sN(sDoOczQ$+3_6GanvU({==M?J>Ga_6IPL)IrZF6M z0F`(Q#~r|(uwxD-3?9cF!2K7G;|}2d%rOT8kXQxC7LVf%;57ye3=GE`Km`O?u$LEP zlt(9r$MFVGn;0y3yaBqtj=|%21E`FHih>HigYuwh=myYu27d^vc0LmWe;BI?h!O+~ zdK_;6-5dnfaREew(iPMnpurFym4H%ykLDv0NCSS5(Cmg3^1ZeRGRzD4B(OrslGOF5sCwjYe!#%M;Mn*RR8#Ude`H`_=)CFy%A7tb5kB21DgmJBFb~kZ1rEKg zj2@lsprG(*JPry5aFJxY1H=T4HEClq4EvVB6d~W2JR07h(8nL% z&1b>kJ^L)-@Q#2e?LCVc-jMb*Xe{3Yn%7&up_Zq|pyjDYuiJl*)?=lf(AB>R3=BSu zpS^l{HhA>1%m6Q^0k7exG5qiG{ho*7cMrv59-9Bk1b2bji^vTFC>t~^+9$&d8R-NU z3HKuH43i=GgT;QH3~>S=InoxjP% zux|!0s4lz-_O?f_?JkJaC6LriUTBu_=(Sx05x)--pM|RB%S})l=AKXICungDF{=|? zXB~!(hXnX`9`x)y;n8^!GN9gTyX-co^9xoCCJ==ks67TMuff8g6Hi+}mnQpkGx&n8 zjClyEG>#wo|NsAggq8^nHNuPx9-z^mub$loh6lhyITJxjTQ8OJzs~jSF5vKNJ^;Eo zq@>p4_;FP2X%iZ1>_GbK8B4!ZZI50TF~(?6dh-#4cS=2aZCy@*BV@iH zGsC_~It&c2g*|$0^&x_DL4wnCP^&ZtaQcMYJi}1J0gGjiUT~oA12x$of!7OakT8G+ zU~SPZ@Z^KxftHgcGKc_d_z4;$JIue$o6+O{;g*x7?>t%$c=UQO`t*u|DiTkAms8MS zGrR;IZ#&*#BM1rc&mO%|?|piU{`**7^x|t{AIpoy zdcLjS>NG*FD>n4}e+*$-+5{*5Z7zoYoI6~^{(1gC=h^&^vHp$IF&Cl#42ZyX`e*pf zxAmI`zyAlXUKgQ%9+t<-cX;%=2!dJbJe&V9f$leA@Z|UT=GW^Y_8%no-_!CyF+WKC ze~;c0!~Y(Z$BLSLJ3n|fKX~BT>+ry{^RVZ^*Q~z1-i+X+@5ji%;MnWT$iMAC^8-fD z@0UFp4|^Ox21>vD0xpst_yu?*o%jWLgq`>WU4%hP_#`jz3;0MraN-yA5eAVi!WTT6 zj~(!6K77El`7l%IiI#4| zRP(V1prvrVag6-iZZ|(>_V|9ygYll>ZA5VK%Y)XZNrJ2uaN^fw5q9F&^br;Sxev6! zOwz!KU(-cc0W4|&5(O8IN8ULr|bGfdZ1rtJg&gv{;RaU(ki=gD+@R9Xn`2 z-S_Jr&FAGk7_WPF{sZ5Vi!nbJ0M2in2M@j!NNfHf$Upr6|CB>%%|BWAryo?f$Z@a( zoa?}f(wct=7pZyln(`P$cjnOT1!6YF`lsN3s%L-|`Gdp&%bvSbzYZd@C{y|+#1qO!W%?2PIsBApmtbt%E zAea(R<~{}%SRK%L1D5c?{pkRY?!FWM7#Kivcp}ibIdzZDePFRpbMUNQ?on{Dw&NNT z!@i&5D07WL5UB=`)Gs6{cz-vb!4@>S%TU6zpM`;e0XlsG3qP)M{~+^@KEb|%zr^qut2#*P7%QZY#i|M6X+bD$2&Ds|bU~B{ zq?&|wIX${JXfR4JM1Y+L8mK-34#1OFnHcsNOMMS#Wm6$-89=$Cp7K{uGD>zC;JdQhnMratI^M@}%{flD| zX@+AhDwZHE$68dZptLoVwt>>NP}&YkgAN@A>2rYcL3d(+_@JZPK(sSd+yzRzLTNWB z?GB>BQQM*datg>duzsFL?;Nn$KClFIAjhM34>$x6bNUdCKHWVkAdQ~QKbiQOK|>(E ztta_gSwY*+dTsN0;lb$By#;J4=)g8JkM21tp#BtSFhJ9%^E=E`@Hl`UXo3Ph4&d?q z_6H9}aBU7xEDRpjEh?ax;%|KdvZ(P0C?b*i&W^i4{`2W=Q33VOUkf8j>1E7YZSp_j1v;pC)M{fxyqepKDCzFrmwIV?u%S%Pt9+qcIyzWrFMa&+Z=R7*U`dD5nzUt9i0`}tv4v$`&OCHuGKfv;@ zJUXv>Sf1r?i3Ly4@SFs>3=$rs`M>j}kL6YVrm+A2|GyOc|Np6481N*f9R)BcMHLFw>fkdb~XO4^~h1+6oARrmRF= zq?sA^f$v@Hgm+=S3W25ArI;D^U1b6lny}Rlu%2A6trQnCgGc8rkItLEogZM9_uB5+ z2QF`IxG+YMK4XD%>&5F(lZd z`Hcp+d}C4ZIPRhXs=pXKnr*>m@wYUBO8IV9P-PEpYw9wB9QMSs^O;X?jf#Td?bjkO z_krf+nvW=eHf3mgbc2TmotkSD1sF=6`Y=B9==4!h@ag>S(+OF^<^eJE^-1uyXb;f- zql=*S256&nZ_)qG3(XIhK^r!T*$lrK-hOT6p?L_zK=Q9gx6Mc9cma>@nvWb%S^!E* zfavC9EFPAhN^gMLOiCWTJRc1&A#{WKC*39&nd1b&OY$z1egxNEpvk{;Obng(IuF6( zytzh2fT6^~r`MG2JQIWAZFu{`1H4#^fcx;B?0V8iSf7$-wa15Rp{# z*|8>7L5P-#>=;QEvK|Dq{sXi=(zElQPj|Y3k9N9-PbX*yo5?5nhgYx7Ur-W43?_FT z2F<*C9(=>>oBYHTv^G+hk%7Ulm*pu)ooDk8g(4xZUKVyx{0n&XvM_sC9xrA$Joyr| z#K5QXpa*ytQ{e-T&QBf(U$J`pKLm^8gkl!MZ?7}JF^q_z3H$;q=KKOa<^ueJEXMqT zpp7X4F6N-#f;nhAim?Jn4AfUJ2lW-qLEBM`9YA8Bo`N~3r(h1+j$)hu5-Wi0M>z!E zk8+?S$OAOb{{05RI?#R{7jsY(-<)62#TeAYH}+^grr`1aK1N^8%ktZ^)6D>! z*&Sm*v-pQ6fWkkxVgDph)mNei9Z72aR-)n2?QG#;?QBrW11mH@B0il4;2D}uXN%XI zu7>|#n}S3=x{EbDG(UJ8e8Jp#2-+ldHT-XQ5|W%-50tRDbXRbIQXs2Gv$Mqym(CxM z*`blOTs6Ryq?Y;$9g(@hEnKyI`z_39y>rK)qiFN z22W)+kIq9L2Ve0*J4jufpc$Zl2cdmokIT=#UsL?#(JM2_vp3{Ehi9kDeNc&H_zmiF z$1b-B#}1eK8jk<_K>qvS`5!dZ0A5=R%7%!<0xo|&l8?i@4jMWGd)SuFv`I(H*bh(d};Gp?SmO;16cQw;rwE9Qdam_2@OxaNG-;Q}Wb&>uUJT zqwyVx6an-`AVE-D<&KbZKNK&@iWZXOkvUWb2P-8=^&^Ja!`q1BNGbRwVM z^__?1+44w_|EIg5eWd#y2cNTeFn%|@RgWu`8hvlgv3&Tq=o%}AJJTyO+sCjmW zs0jQ&;n8h!$g9)jkYlHd3WrCtjS52vx5vSsEZ{P|lLMAdA?s}pdv@Lgtz2q;^uVLH z=mBUa*}?a$plz7HL1P`D0TC9%x3AMZH1B)&mV7KQd<#w=`~og|6Zi#u^cL_7vS{!N z`e=ZLJM=bygbwfvx@dq3Fbz-vrUx31(R%)<=Mv=4*dV`arqf&Ob3*ESS~fzHg?>@4C+_9sEB}ikUrh! zzOCQ*JEt%(FuXKmWMDufR;YfK8f}kWS7w-gWk=A}K@7)TR7601dWinYh?id(7#R5F z8Jd4H)o6HtCcO+_xEekIS?S0>>4;;miwYy?oJpv9jhCQB@UDhWK<0poK!`Yh$2taN zC!|e4nw;phS>f6I{DDvB2k2GUkN^MoP&@%Xi_)o==b;DWJW9}v9^`nB1_lNX&I^wG z8tjhz8vX+O8W;GFUA*hsa=?S%^rqb`W&+`k^%b+lSNmuOCQjJy0Un?V}>ndBTJ7sOD+@ z)?QG`Im5}o;Q9ZUPp3I#3%M3Ji5!3=kp~{%FMy80K{}Q4oQL8u$M47fgXVo(KhnF9L=JyOdI(a^L{y*y3%?@gOwt}vq z_U+X7>~`k>^RqyEgS*`Yz#JY3M*_rYaRQAnYaH?H{O8(v*tPSNXRp76N9S=L!}lKh zK;65KF*5 zKF{BL5!A>>GSR2=I)Bp!(5+&}-NF3<@EJg!I1B`@MnE+Xe8mg8fk6-hL0OaGr7Jk- zj(Hq>r`7z7-KX;dxGiGkteVbGv2E+b6PjX-tIwLfsPoIqwB1NBOAnH7j`7T7uF z2Imqwt??MNqJ{PVQjat<^g#NYe_q^Ole1;sV3e4r5V1liJwOaCc| zelAcHw6dsxT+n(5baIOjSR1Gbh0WS)5N!`Z-ovmKbj#q&OQ3W_$l51RXM?S^16ey8 zu1(kD`@M#T%pRBDp`>|a9~K#Sw05!|hXKtIwk`uHZ)H*8Z=Lh||9{WUL!Jj;VYBl( z*v{s1&;jhAIV}%xP~flv*-!jUlYagG54Nil%mCR{4`P8$FakAe_raRE9*UnlET^1@ z*cJ8b|NqxH^(79P>!3>c3hd~Fx5b_J?ei@(6d=HOK_W+;HdI!(WKdznU zTsx10yBGW#s_ouP3_hLDT|0lcc7A+$8hmgLxR`}xIY=>98h{d=#dRJ?Wdlk;G{=An z30RR18pQDJ%op(Nc83(}*+2jPe`x^n0`~k>k%D3ove88=!TG(Y>h%IhaDihGd(Hw6 z?O`Nw(5>k&--9v@I97;?S3}SsAt>B6zzk5h%l!wXAp+^P160|50o#QcnjR>gEGj49 zpW-l3WuykkNDXW_)y{wcD7xC|p(d0I{Z7p=w8r~#(& zfWP$!D9k>AiauOPw`n10ze{Jn#LJ`LLoTrgtqO`$kX>Jt0ts28*U=F7;RrbtJ;;S2 zL>GpyJYa=IlkuPb|6Mv?fG>O3IsQ@(y!LQNi7k z1$E;kko<}0>3IG>?h84T64U^}Y|Z}nP`vJ;c--;(aZr<$zXepTdmemmCl)tSfcdqn9PX!}2hH6Xd8sPy?Ic3j}qxAK6? zb5ILa05opT^HKup07TOm;tY_roi}_8KX|nM;BN)F*#|T}0J`blXSUU)ED8w{ep1Q)oz~BM$)H{&x5az->b<(4k#RKfAQ=t0d zxGSWUx)Dy#0Q!?_zEh(I&rwc9BKqK06|88&g|}lxWN^q-yhU=>%0kRm)`I| zYLk5Mv}`#8X_I(^P5?Uq$-j_R04V?SyPk0Eyy@C<5)noo{I175I8S)A9_DWaoeKF< z59ET*8y?_0if%$sXeF3$87<5#j2=?{dO}^P)%VX?}3S@MR^E!Jrg?FdNCylSp>-6HqHs7GySB zB8B8Bcn)Y@_51(-*99KnSkd+Peiz(+ev6(Si~K+nuAVpp4jvVysvgi#!sVH!c5qJ{ zT87OBH>yiHUK)d1$uL*ITJfk!S{9@P)EW}`jR@}zXa`Uhgc4(C6Mc^6BW`vmRAu4aZ!y+=Uq_i z^F)y*Qc(iRMjn@6pehY?>AVX%rW1Qn;?VLIQK}PBlz{FOfd?h%$aoKMD1t)}G*9kh zd9^4M;t3<@&?u;mP=sf|VslvVp=4v6MfMp`!UT`d;0U{>Rp4fPsl>|@UqNTp-}iu> zRgb8!k3+%_l7kr-8Hy@hI`4t%$>T+uuXEu=@qKVn{2mm32&H~5o%cLi|ChR9bvG!^ z;T24&52WUpWRT5lN1PXvTo55!U1WJI;2iW7; z>nY(0P2DUE9-Wsx3_pA9MGVcp=5Gb<$MCWI%-=i0~a8l`J2IuR}P}P6k+gekXgqaAq~|&5U2B+=fQVcj-X?Jzz4l*H9utc1P!d- z2CeF~yv^UF#l*ni(s|JnG=};BG-4lA^J}9cL;)8xS#o( zZ2p0g+(l2z)BH_xpjN3i*gjnPK;xmHz-c-OZi_C1uHw;xF#sG;?8 z9k>O05!?dZjc96J_OP4-9TEfGq6v#pkAn~O!LfSqv4IEYX^+-h{H^*R@8*M&R42rk zy$EBjdRVT38e{nH|9>=NUU(dQYT&_n)}!?mf2+~o|NmcVfQ`B8aqz8?2byc%LmI;_ zfB*jnCtA=%mLvbR6R^pw)>Hhgn?ViJC!lnL*D3!&JppKs3hE;ir+`lBemNIzjIQT* zQ1i?4@;e{P+eOa4t=~%R(0p>k10EotLIx5JXdZxsLlbB{Bs@O{gYt7{A;(K~a7O~9 zPuKJNZE$nzH8`TB|NQ^&3+n6&fkwsgIQkQ)Er{3K7eFoGW8iij7K=cmtYC}se&Y$@ zK(H+rz*_S;1d%O3EKwW7?IdSE43Y;Xo04-WE*)o=VsK?-hykq7p~^aIoY>@4^2 z=nN0=>GXF%l%UWC8o2mteO;>MV|lwc)B_{8Bg&;(P~!|#=y>ADWy{1l}?JX^sJvN{qRyl0DKUi(8F zq3a3meR*Df3zD|-ZGBs6ipw3P(hxmH9w-jyZ@LO97`q|0WGu)5hF?8f-o>df4a6D@Zop)=*#)fr}YzmD`@NF%MMU!2}w-gLI_*{frm~G z6;*k57D~J{0JmH(dmMbNg;MN$Xr8X%2iY0y0%{nZE|Pie39((*1DxSKF24pzn}9Yo z>tl68sf0%-IOjo}3(jx+O`su&PEec0v(x0@%Z=av|A(y~1g(d139bpFoL&BK-5Byzi2tY-?9TVLSXrZ zzpWb7`sjQCS|z~v0JIN=^*?A;AbW`xcs&MqX!N)%I8;2LLwcUaUBM3a1g~Q`S$f;U z7Sw{{Zvxfg$fMOR3=H`6`*xNpcpi5J@44_i?g~D)%k#La1*pO4+ga-1dE6Cz2$|<` zSMVWZp2uAypmGVG$6Y~*g2D5+D|o}S=W$o?hH2lrLA$*@kGFzT2&lDuycMiWzl{7`PsX zU77THfk&_HqzT{m?XUKquZ;4{n!3_umHm zcb6z(Yw%}p0B=3})CZ2Ax$~G9_DvN)-UI+s-|a5ZdZ2{=|A|g_3D7x-4e9LlV6EFB zT9ZIp=c8yvPVXMw>>k!^r92*>Wt>hI6$R*m zQ;+T)CqReg^afjioX}gMBJe*z0em;y!3PE&+|1B{l>h(vJroambb5PufM)^YP__#o zpC1RB{{vkIea)lulV|52&)zmrwTfKXg62LuZ!|w({ z1G&2wghAg4$dMpK5t<9t90s9EA;A_<|-0 zLt*0X4#0*hPNebQKApyY{UB%+n};LRb_Nf$3z$DbiWJA4pgA#c z!P5AcosofoGeYNs$A1sdDo~`M)WeAR2qGp8zavi?f{Xuy7?XyOfdufR;X#j1k)NQO zgu7iCKnvJf`#@!RXD)+hw<~0=n*^xq)$Iyd>joOd^6YknEQ*i;4J>qC0?!pfnk=Bf zkIrKrhVP*BN#L=HfBdbbpvH>jHU4H}P}>MHXyVg(>E$g@Yq+yUg#$Ex+!>-G01gb$ zY#;}Ccg9P5s1=Yl6UcbT*agVo&f^}2?>$<-^S6T5_xV`f_vyUE-{b)9GJuxYU|VMa zohbqxxA^h|$Wfiwp(QNHY>3k#p#!p^^&CIAs`CIjU5tqVR1-s*Or5`8eg(Uokai(Z zg9W6W1EL+=$nfa=^>QUhd#~-&E^uLRZ59*5J~=_;!oaihpy$DtT8^M0l+G8h**9O! zgOvi133px3?>E66;Fl1;7isyno&+sT0_igX-Nk~`@jUNsxd-C;rVEe=g~TrCc0te1 zT#lEZ+vYqw55Vk!UWEv5K@`vxs*vcwSpVQ@IR&iJqw`l$Jgi;$avzepore%v+e7ga zvIad*XoK`+16TuOZ5*0Iu7KKqKAo3}l{`ChKv&|rAWg?~UIhgJgGcA9m&Lz9n_)qP z4a3WH5F3_tN{t~&hrbEDrVr}f&SM^E%ag$V;BN*kUVJ?TDPd9}HG&q*dP0hqQZdiY zTmg9TviH~j|1al*7rq_zG<@mV`mt2s*Yc)M=cS_S@F2(G)F#l4gs(RsqTfgJIA)~# zTHY+u_369>8WvZDcneRynE@Jcgp_?H0w9yYrBA7#kLCU1OwZ0-2~df~0UmHU2Agcx zJceW|XaK_lG&lw-sfyG=%a4>`9zly)NPst~g2nt;MVbB;2+Tn(O`gOqJZQ^|*5 z2?v~lKZ5%4ow*V(Ykz{exS;bO!SxKdRR!+vAlg$N&2Kz9&w@Jpo!`N20q~9-(DB5e zeH%WVFCi6`D|DXwsGQr6M0Z{(FO} zFb~9F)8Pi&L{R5|zXddb2Wu{Xn;f8Jpd~62KH$~Ny(KCJ$Sn>7q!tGUQj0?XW(2gw z(RtUS`6#H-;o14br}LRd=d1q#4rpq+*^dw6I@+9LpaYw1-45H>|@W~R`kZnchHd80r0AXmIEbQ zJ-V|6z$3Zb+CJUM3SeCbM?yAk`e%56x*`ui^(3TW0&XoG1sw?nZkjZ6!D6%o$QqtR>{-R88QcwrI00$DAyN|vXVTL5=sXM$?w_EFv$sUW0TJLO zDh?^#EUhzbqf4<7$JK&N$rwnBo!4eU#g&il|Eb0C8t%jU5}B51tbv0)#y zRha~CRkne6jGo+ey_0` zXz~ktYf{AV7}!>ZmkUA5MZUeP2UUcKQsDnlUr@hQ4_eQmFDUcueCMfn%~SCh>?UYX z(-1U$(D)S8i}T1l3SLeIY5PE0hJKwkA3gtrj(zuNJ>c8uyL z+UM2-{H-8u9^KB6W??X>1=i~=fzq(@!DthfgYpxoWn>CU>yS2~Z|Ad@BA_kl-(CuV zZ@+yGj;WVmBN0tZ2Lxa_hQp=QIAM5ReOCl^I4I3tno;->eUsX9KO3 z!f+?ZHw=)C8t3?1L2H4*4M5Q9f7o~y$f4XITM&-wJO=V3s$OkSAc6d-0P-w!Obn#= z5Ty0@yaC+$>pH=Ny7Stj*Y*rVYVQOlhJ6Vr4MUI4qtNAGzKC|AkLFRNng+TS$HNj7 z9z|N96*#J}nx^wOa!3BXr{x|!NyfzHi8|3*(wC9-U4nI z7EAhe=6QH_x&?T4#yR+Oeuw0xEuaPy6g*tedZ3ikr!!mN<#H4U>O+lt zf+MJ4>!|sgnEwC&|9UTB#}(=Nc0L0)|KLXAa@=}Qpg_tvaPtpR@RSOASY9vA^y$o& z0Ojj&!p%QurbKQ2AXw+G!j_z_g?x*DDYHvFXjCCQ15_FDuEy};W8{|CDu^58<+r3Lb3}whrD(JLl+n8!_QM|O5 ziDBP)NyMnBN3X3TL~030>H?A!Z2kyx-Vx+vBye~__p5t=?|*^~dND9~D1Jn124Oa@ zO*}h~L&jeXAZu{!O1*r$(*;~QAE^Gf2c35L-NW)ksTAxq3!l!%uSJpCS+99v2lagL z{O`{JG6Ooc3ff2xJzdnE0d(;AMaa2{cTY1h?DJ!Qo}~qHzXvQK9CwEdS3vIQf$z6P z=|5<6p7!b1_w4o+@a)c&05vl-K}XX4;BWZ>>gXT*#|&PHo~z&qn%X%JnzA|ggW1RO z1AjAkiy`P}7tnB{1ZdZ-0{BqnUX})rgD;qNgN9l>_+4-KSbp~8ce>}%Yjc+Y)ZYCD zo#XNBJOaKsBo|~+x2u3>^M8dRF|S@83s1{4{LP?MUEaMsHXfEIifcg!^PKYde#wLJ zs)u$CX!-dskIsAG8-fM+x5;ogcF6F6?wtC63Uq$oUuKWa&-_iCjNtvZ{M$r096LmK z__u{{FgkXG@Gyc{Odu8$h{X(IL62fMUwZK+XrrT7ug*tMpYY`;a2^27B0liwt$YAF z>kE2!>nHG4y8j`EP-J^_UiZ-a4!RQ+bY7hSzkrW{0O(R%6GwhQ9~009ZUfK>6b9hy zTTK+eqM$9@2B0%248Yg7nmB+(1Na483_zz)7=W*DHAw)ALeHT%&QiJnv<^xGat_5U zP<(^bgEoCbjQ-%rFUVs8If3F3=zO~K{H+JTUEf*(XnWbWGgZL5SLX}JgPy%CcRV{? z6}mykVRwgs27^mfB#ycMU^wRbli`@_FNR~TzZs6X{$V)g`j_FD>pzBLuKyW8TiH9W zfh#1BPS+nD5ugsE22zI+Q9>cl-*_~?@$l(9>e1<=q5(=T9G;zDp(~_8ZPw)DKA8_d z?O5O5J)jfz86npidGa4@0drR{^0zJrH*8*@oYc^8kZ%`gbj0KGBhW$Gkm+XL|0fks zc+BwWHEHngcKNR0Yx#n|{TBxVgJ*981L$B^%NP7@uQ)(i@})=PLxu%3pnlprFUO` z_vc={HsGU84BvvvY-k`IK8F9+H^=7xjQlN2L1W;({{NdFGVTER$g%l9Q%Sl{=PwV< zQ(ys5d>>;u%y7)*FzEiV!=U@e4ukF=JIn$S1KmG%7sS`6e~a0vWA?Agt}f|0+){@?%qpc6e_5`72N5yu?|K)Xsn zJ=aTyx54)KcAod{4*AUC(s|6W`3E$xz&&6ee)n^p%|DsTlsuaMF?#U3AM@ztIRxHC zQosT#I9U#Z*8eppvoJ6i{`c+tIl-fw<(Ee%%Wu&6pO)W?KDcxq1&v-C_$a;tZ6?^C7qhKFQy*2vh_&|5PZ}F+AYY?V{rFQXE`%g663iKqqWWIpERymVfF& zg@d4V%9=-C_A!AMHE?@c9sz487Vz$6;qkD%QO0g~;N?wlsd)mj;-LWf=$?zs4?)K> zflAFwuS-G4rfFV7J6{R;{%aNyQ0XTEDnErm<)<*XkP`uypCX|0Qy5f!3WLi}5pek_ z0xCa+LFK0~xcn3Wm!Bd99?jspufgT#$r3Zq-VzZ3kKPbr0grDC89)x$%C#6XLRiFVPOQZK-Y(}Fo9U0>%&=?A=if=EWL<4&f%gW;M>b{ z#HaHyIHQ4+DI&>%$3c90MSeRSV|mTsbj;;7Bba0Ylgwa}1x&JnNj5Oa&fwYW%jjYG zlfPvXXd(U!7tI&{53FD;F#(yt0an8aCb_^QH<;uBle}P(4@~ld%wh7ed|QHicCNew z!!efA498qfgUYMZpz`W8sJuE2Dz8q1%B$0$^6E6GygCgkuTF!?tJ9$J>NKdlIt?nX zPJ_y;)1dO|G^o5f$mC&pzH|kw{RYZJpv#z!gGvd|`6T}jcv!wD`{DWjxTocH{FI0~%y=6!7R| z?9AiJo*dA|AiACKPrKai0f zCXfFIJ5PX)h-m)HQ*2~-^5s-;UU>*wl!K#%!QTv;^)&qUQVP_??>y?EdDieGQhE|# zImIvFa|(3c)oFe~pVOe+atf4NPJzz5It@B5<}@g;oC4*QQ=s#%PJ@n%IStAwr$9O7 z6zIIG)1dQWP8WE9ZhdGz$^xnn4wUG5^zxhqmnz?Hz`~nfz=aExKe+e>UARH{gWIF| zAmqF&Ps^YDtt)uK~!tNY}-K z+-m@GFVc1KAom&|+C?is?V>Dby9g0F;PbhRLGCq1x?>)6KG&hrr?0I%dTkZ+!Ci-q z^-K)=CW$~B(p@6l9U>fEA>51|AsmcdA>2$IAskFyA>7OzAso=g;+fK$p!$HLJAlw$9eoe=>ky#Dhdxi zWAR|TX87O7@}vj9(?1W(<3%=xCt+IoT`qcPUMSH5t;y%`==Kx%f7YX0QlR;IaMuvD%o}uh z1FZ80IvgE5f!cZOm_r7mPq(#acf5mVx4Q@EBn8bop3Q%L@V9&b)glM~Fnj(#;@RyV z;L&;3L-Vc&XoVT5$MAr^`8sHjuM?D$pnZg$;H1Uxdcw!@p(nr78H~CLTv35mueHAA zZz% z6kOq%g0clthrtwF;h7>b#(Yr5Ky(-wQ2Gm|p#Fl7DFdv-@CbB9X)9<$tY>$<1H8kK z@8I3*@|3}|)7=AP8}MWer)TH?=6VH& z5>PV%)V>FwU-w`IM=2-tFv-{c$5>Ptj=89SDhw4+g`onfFjPPlh6<>{PytmKDxeBO z1yo_EfGP|XP=%oasxVYQ6^06^!cYNK7%Kb>9-Ysj{_x0TQDHbW%i1Fulm;_Tg3iSR z-K5;v9l#*K;Mv{(0<)Xg94vI)MFqT^(D1EKZw_d-t3*WsUY>b& zyQpY*cKfIx?!`M>tmxQnqvFxc^1`FLz{02V6*wV-YN^%(CFdZ`V~AO46F~X}K>8)% z*V3IWmWAjyd4Z<)(o4|oJy3T*#)m-q3qblSko3zz^n>l!Kr`dqYdfd`;PejC?*P(| zxEAj$fAeEdR|M<_3^$zf=sfHLS!Zha))BnM6}h~HTv@vnbeC93So2@bayw$1`u~r5 zHtz-LV<_46`Y5cv0S6tD)cn`0K&7mLM>j(^Lnn)h2k2y3kcb3mWs|^u&}Cg7%#f*2 z=xx{^JpcEC%-z7qzYTKlbjyJfA;SZ&^$bA=y@PFNIZ*n}rxP+`0qtJ?ZvFs5g&Z+nX8SdSqcG6T?0hQN$1w*mOhyfzD6-?a^J2 z(&m7TBzqhOokYd}ooa{%-+v1l-}CJJN5t%yya((oY53fj=W);+Bm8CoP=5?1e@1|| zShc8vdPbc!DhALAH;?WeDD#d!Ix7ByDvxAW22aZ) z{Jn*s1^$zNdEc}7|DTfCo(KOkff|I}D?r1To}Di}HE;TWE;{j8Spu ztWlBaEKyPD3{g=5RYw6Bohu*9pPtZum4`>K4XD;<05ueSJCFHvo(2bkXXh=C&cnW- z!)Xh^l~xmH2nJv6U- zfG(?$MGig(22lOfA;Jx=z0Q?>^l1Li%-{4IeAXPezXp{D*IpeV+>pwvBZM1LcXfoo zjvYN!di5pfcoLt^i;&t1`HWS^&I^v)*c5o?{uy|L0-QoXOLZYjHyd`m zV31&djCFZ5-(UcpgS*B9)M|Rb>cjZLrQ2nOf@7}(WAhKDqAjki2lzWcTdcw3057;z z89vA}7@mABj<9e7C}A}IWDsCrC~@)V6=C#f{Kdc^z`)*IzD{ zZX6|C9^Gc36)m4$AMof76Yyw02D+{JrT72;|3PWnr}H~_F(29uY96q#0xvcN^*cI*;dTp(e!P@VxLYu6e04iUb>t&EHyXm|PUB(TX+g4`p z_D}HWY&j1~Q$D@r2@Q}nC8e6+ixFT8Y)w==ATuf8;rv?=Yr%u}afc1Ry?z7_Z<6fu z=yc~G-%fD-PH+2A>K6;o&g&kXCMuxKIK55iD{MfwV|aG!sDK8SIzZ(ibTAFFzIO+B zeJ^CSKm#KKG)j{H{r6CO;nMjVwD0KPV=WKP!ycTUL5qD4V_)pcA10gmpAob{nb4YF z{+1?Cgrh9?_2?E+f$t(fTJr1Jd9>R>2E3~UbZ>>Db&Cqz^(`j1vDj< zqM`vg2iQf0;OhGp6&%a&eLx-6L!iZQ4*c6dcTs>=;ahz0{O`*Fa{;ZaMy&ex04*Ww zJOqwI5AY&?=oX;Z!@j+>0nj930!t!Wph=`eg#(^MK=-JCY6StDNd$65Dm?7@TNi`Y z+X;b|j3c%bLlOv%bl}CqN4>2pUxa8qx$A1=_lg zWE5z-GJFkn0m!Ic+lpv#4Zc2`iD93E5b|Ps#7Ys!;M9d33(xZ#oEC+61x& zbaH`5>j(bU^&k%We{_;cxN+ttVAz$cHcK&7s&_S45Bw7IW#~bh{`hWh`$6&?>{?=O{2E-1JPE>z@))YwL7DQHkL5v7a%$NPI&}cl zFa#xH%a{DECqM%4Ksnd)5P$1(&~ZO3V86Wc07-+6gncOmP72W6St{dWdA7L7rxQ6> zf)3w%30`##4oR)%=j;R$o{#0(qF|rSgFcJX%kbI)efYd?@g755@2BWZk3y zT4$vO$vs#jsTef-$=?EU1-SXrdZ1L@vojX4%K!Yg|Nmcp_=OS_E}&yPFM!rLf=iuJ zQINl~K~4gffhGH1f`)7%wi4-~1dwisheAOf3c%qZe~{J25TmhshzqoGNbn`-7*n6l z1E4AY7Hv?K1KAnC-vVA`1lnM6-=p<R!JDH&fxq$RbC^Iiw|= z@XZ3}i^4$tsz9IC1EoGtS0iW1ra7R6c;MY92VX(b>_H#JgT9tiAgchu?iGGn_7}W9 z0d(9!ti;R6umAspw#_kncE%iKcvw*$v*e z2D%Z@g@J)M{cs%&;QjX@!2#fHonfAxf4bcZS`U;sKz899-hM5C=$wMapFI8_?mXyW zdAeB6v%5zH)EoEcwz=ui`oH9v9}m9d==^l>mB7Jw5+2?9 z9^G?6#h*tvc$YcoI8@Dhp3VRM@V9`@q47NUkID1@F^}%Ops4Wd{O_rG->373$3f7@ z*ayf}-k_}u9GxX9BAp>B5}iIOG9H){I3GRvoz8(q%oLCZ#lU4Hc$vX}{uXe})(zhF z4qogf1z+q1%5~7iUi{7dph1+AkZG_p4f;8(Ose<;?j}vr^DlKN5DUa zj)MPa!{3M~NyEIqwDo^UdFN054$yE7Xw;Uw@ez2~>VQu#_~Zw}|7hb^$2}VVgU7F& zJbF#UJsSUkMth1aJ-balcr-uzS8^9&9ltz-r5|GW>htS^u;D9@&JU4?4G$Pziagx; z(WBSac|ExNIJX{i_{g#I1bp~N2BIu`J@W7oihZCy9@3WQ37sF1c>MAVC_EPir1Ovi zJUhR+wtnMp0UeADE+ae@k3p&x&(8m@hEEJ{^UE`McI(^+kN>@}X@0=y(Obg`xqK5m z4SJxY22_cFuF}i|?c^x^=+mj_@&B-I=Nli(&!vYA|NC^lKz6PJ19&3$IOz7x)&r%V zKy$*P;9LovYk19Wc;K~!tKr-IpvhR!U>{iam;(ocPp1ZCi7mYM=h18X$sZh!jtiL> z_VoxOx5A8o~?n*?}5he zDA5mz5AXpw&2KDxJJ0)c9`)=z>(O}`wEDaA&wd9`c?(;W>(Tihbe3Z0KhR3%;|>bo zxh`lc!Q;3Cw6X>209( z0Wy4`adgOfV$cK&=(Z9_d_e0HKJWyKV@C)dWQGOAf=sc1Sn%Zm7hhgu056q$?9u6H z@Dh9>Rwwbx13>OUu20NB%LB~NmIs)Dmj{?3&AB-83%Zzrmj{?3&ANa^!OH{85c4kh z*Att8)(7yI!IlR+_OLt)3O)YTJ)pjRcZG)GH=oYK;N0rdS*+pR%ks>l)7b!4k(~4B z^tJ$1Kn9?peGQLp(AsU#stljbiXV`}hm2G~JJ=jM*&$r;nWKy!JVE2$;M-kv8y+(6 z04;{S{J^o(T>zp=|Jwx>M#m0!5zm8f4ICSuGP-u;LrOKzPIn8>&V0~bwi1?O4jhbV z<5!sNrE4CYpFKMNf^M4bb}aDd_5{tNm&kSpb9fy5$!z$|qub_#r8s{}0BDl*|1l5C zb473VgYtnPEYEm$9{1@^WdPj~Rsfn!ukh?V>Zy6vv-$52{uaV!Iu*C zfUoHVo!z2&4ZJWEv^?eofAbS?hdD$=0Mv?-z|zEe>B;YO79vne}@Zvxy%R1av5%<_7y~)e;fFgL(pm&@HK~^#WLV~4k2r0JT1?aUU>;R zq1~&O<&|fri%P{y(CN#d17^WjJUTvrblh1z{vYdvtgin7nS4wG9SElR0kpc_g#om_ z9(KQ@izx%YpbvPp4B~=EQ_ut?c&!ZLf=5%(1f(e_D%T*X1n(*q7kE-~m}M1BrT< z?h+LqP!8yJ=5Xv}_vm(30Hycl>H;Q5{weMP9>K?{Q6 zsSZ?9|3A(TxoQ=(cS6FW*GJnBG@V@Q(d(nZ=+PT&;9+^HIN$J+XXgt~%?lo#|1c+% z8ThyP2pe?pfG;%tf3Ea{XY&tc{wC1gM_73Wkq4f z2M1oV{yWIO?IdWW^7orq?S~YH2TPxLSYGFEo&WFu|6?v1jG*OF65Y-;0gL8=h1^b$Pe6M|W_9N4IkVa_RIJ zR9+nX%M9Kr?49A+dB#)o3ivu#Xrc57S}1XVuF>-V)$6zmrnAV)%%Pq=23{*$3mS6l zc8>4_t(OIL`xHPqrx`Ta;@!)m2Ckc1LCp}%x|zeL^N|O1ua5|5`~ceDL#dy^`+a!9 zYu3T*BOE(Kh^U`EEzgv~>*rS4C(?H8jv7}ef>=?KP9fJGQJYem~t?21B8I)e% zfYK|d0u}J=jiC7d>qP#{SQ+V9;H~M66*U+=By^SK#qcQ1=Ve;sdRQ_zYSM(fpGUbZ|@a z-T&xo0YMk*3VY$bfY%jt0k2;#3;3#S&;d>@pyn9tE^VIQpf-SjS1%8Phvm&OcEd~H zt3`b}4?(KsD&%d9A3@bzGk6>0|JOMln&*)B!tl#O+FREA0zTHD{RI~Mf<6|Y-iI}4 ze}Oeu=3oJl&uLY>NWewV2U=7+|U;(OiEebrE-#2(PANvE^ zUvLt1pZ0M9kMB1TMGCmSwFa&CvgQ|bu>h_2vHb`^5X&wf}2Y8ixC*77D^FWszgLax^9)K)4 zJ^@Opu={Pn=_4dKzyrF_pTC6(R4I3UGduuZj1MZCJeqCgL0w<|mRq28xeaw34E!yi z9zgSde*Wg?;8B(99?8c&dcpe*e7aQ*I(G4>H2lmfRok2gUV&zK0D28_%WeJ^(A~C< z{M%$itYnNldV?5CUU_!Qfrf^Z(k6KH7K09SgAG1|E^WvFmBy{NOP@dtEh-J&Tm)Xr z<^kEyV0Zu#ffHJ8mk5B&=CP6y^yu|uEP3}@!xOx^tVGVE`4|WEwsG)q?h)7}+2BDF z!vnD4CeUtYk6zn0Tku$mn?Do7zAVt~^}-&#wuKPEkNr#x`=TU~2cRJJ3tIaLGHwJe z*tdcXaqIl<3OX<0TZyPow!xArms<{$ta9Yv#$sc|V(!sf&sg#fH0I&koo{fAH60YG zF5SGKvdp#hB!AyY&;&hXVW8o+*E}BokNH@h<8Of++-LK_iof&?I5s;^z}J(t8~}$m zi-;AAI5;lfy*|6?F>48Nn53=cGY%XoCx7;%8cIXIx90y?Tlpj6DK+f~8y|1n?7 zWBkpF{{H_D^4;q`Nc@5pbP9QN7lSfHiw_fnA>^Fb5C5G7Kts$Pof5v?`4%s;L36~t zw$)bPtYGcK#IUaxCDnWM+Qva7@AY7034VD7(Dm zKx`KabAOrG6g&5Ae6hf|~2S9{)j8t*oA%2VZM=@b5k0xRVJ~&|H4#X?c*p zO$@Y#44h&-FFycX71pc-N(Y_aeLBy91HrS~O~A98&!abh(X%s5z@wMNp-Z?!)UBS#9AqSbef>}C34zhFwvv!0WWbF!O>j*i>))ma&5ps~dE107r zb zfkxRqx=Su_pjP+}44#%I|4ZUMK)WaZm414C!0^E9M8mhQwx8$CdajD0Q$Y+wZKt!DY~-%;R$M>E*Cf1tV=Hq_qQ4G!X+lbIOyfo?Ma z+l+Lcut(z?2~dFy$xomej?NYp0ni|Hw<)M#b!^xN-gU&^!XXUW!0^YhVc$p4P7eN- zK=2Ag9~BSJ?i`f>=+aWq0%FA%ph24e56}*F2G9;~Pv#gE2akiVnLxLwLvGIV=oOIw zE%Sg}LhW(zC1{KiT>5)le(upZM+MY7@aeTNcH9dZxb$GW4(T|<$1^=IKlNq&>tXr9 zhu`U!kL7zGe)so|4f|e$+~(8y19Z@U1%Jy0Rt5%0#C!4|Y%5?8U;v$fa1!iea5eAI z-8cbsVsCfn3=pMxuq4yt;7=Bh<^vptpw1R(sRF3I3+mx%_;mjEvHV}G=+pV$r}LeU z<=Zk956jQR+Ar@hq3%ET===>=Q+@~JPs`8zO(2JO{6FLYTJC6hs%Vu@=MwNR<_FJa zu+#qebgP2G-0-a#XEwV0hUMTH|>8wHVk!(D@MHbObshLiR7@ zj0jT7lh&jBEvA3||930t~*Lr(e!v1kLd9aClgrMTAJPpjWRCF9WD6#%_4> zC1`KGPv=R~D@8(cgVKUpaOJ|L7?D2{~F$z_G*o7lbL{*x~&f z!c=hV@csi~YB+Xy|AjCO96P-Kc^rIY;n)%U|AQwq$@oC3BA;$ZaS3v!0BAbn;0wFv z2me5+bt>p?S#U#>-{pkke$WO$7k-zY9<7&L_&tAu%3X#Jpb7v|+xm2`0aq{lt?r;A zqPq>$3IL5KyL)!`f$DzH2L9I~h~S^#(R@(CJ|M&7CHv*6-$}@1;;?a4O z!09`l;B?dZ-2-uKs^UG68zMl(Y;TK-1*8oJF%G(_u6v3KNZO;j2OKgkod`F$aDmPh zg2gy^-oIhTD^TqYDxVGbTbwyS_3{?5AG@c3{orx%5wpkce|L7xC<`$X0JS1OvREaO4tH+Y4;Sc zL%|kx&QXCHA4`()YcPx#fUeAdBvcRngRP*79@J8i0WE-oo^H_HSOIFHbays@D9wYQ ztf|4@3c4NGr!z+-;DbjqSl>VBesROMkhT+ieaC8$sr)UV>#0CZO)KJ?5FX9DL3$ZV zwt@B(J3y`i`F|8HJpc7N!`rXr;q7H`z=G=|P^JLYN7Me0TpvMOL%!WDDj<)0cDJa2 zeD2wK$XD}_=fPjBpvBOd2SHV{1ZW)Iz^6M$MZ>4tMQaqzVPC`l=R(sSoWkAp8Q zJUV++Ks%Q}8%_?s;_&F4q5`@r08*9-fMh{S9(+3Ac^rHv0XeEv!KbrDg#&ag5BTI# z4d2c;o(JC;_;kMaIQZVexAU~;!Pgw1YU1E40Z?6c@TCOE9MHMa5Uv7<`-1_LIZk>U ze5nEAf^MLJ$QppSpwNeK!7c>dSOY5G6+q`(NIc+gVPOI3e(d@G5U5N~@abOA!63i@ zI&Db;q%Oi!^NdgD1CN70Siu*JgU+M?c?~rF>(e<$1+?JEqjQf6sHFl55YVMDAYYvT zPjhWi0o|JeYbt>kM0xPL{_wH9?$bF%1$5w@C%@A#kAu%yL1uua6G4RxC@m*|+|A$# znuUMD-|`XEX6jxIj``+43jEDI;0_|l#Sx%U0*RNPofC$)UrX}KL(}77k8W@V0HwF% zq^CEJgFjh4nh!`AUIHz&5O^(xr~n|Xb_MY5loLQJ(7Ov>cv^ld75A`?_)se7W1aD% zl-tAFqC^qWzV@*$_)&Vw)ADQSQ4ed0(gPp|3wT%;d??+D+K_r$jc7>0vhPb5R?rb^ z0TPDaUW-A@gS3hjd_cQA)Ift7-Bm9GA~V6qx(ICl z&(fnl)>-JGm@a(+v z@({SS=A+8s37UIwQHdxP^X~OgWdJq&c|ePUN>n7kn-_?f2h2h=*Fdc_0UuM)sej0) zc$k6)%1yz?Rw13@VG3%qnSzh4LOR966f{_F3O=?9;}nm1pw$U#h<2Ol2Yvw`@M$3~ z=x2C51Wy8%s7RE=LE3Mi)g7A0K=Y`e^|M0!+gx}V96Jz8I^KbnbQBpP#6c`ZkP1c+ ziwVSH0+pC6VuA|14v*(99T_h`Tu_16;qem0 z1Qm829lXbfcinFb~jJ$~SNzd34@~ z`I(5B!#Ut!#yqYATzEsw>&^k)5%3JS%+M9en-XG4~P%*lEZf z&}BKt+zmit;A{Cjj<>kJ4K@DxN;PG})^8v~P6;e

    f$^^b=&0i6mEbWY#81^ZNAtg)jc%LI| zzm7-e@8&ughSCt9-p!z>gN_1&dM(Oq-F~1mAHXMh`}Eeq&V1l+-43z|bgGRZ{AxAO zf@j##5C45SVO!rpM{qNi)}Zb2sZrrbYu*iVFGGo>N8@qOZlCVWphU#KeKP3QVo3Tw z-V71~B@K_`;N$@Ky*Q*V`y$t#P|36}W zGyo}4H`jxvl+(d8LEnA4)xgWPK&7>3=ReQAAiw+vk2lDufVNI|%BVnhzMnIqj%T-viiM}Oi;6)hFKkc%EauZ`0UGxP4c=S4&i3qG2MQ@)WgXZa z^)=8v>NzSL;O*=1jq0Fnr`Qkj02k?yle>Jo)e)|0%>tc@a{ILz*kaJwfrf|X2akg< zm^%+aC$|l6!-}`o10~Ge5g-qguz5DSs95}P?3@Rx(jc=;@SPPf&-iw$zl3i4F8vR> z0SG*Qhe+c5t=*s$2+6};9TJQZ3=IeQc7rC6JuW}?NiOGrUAx)(trY1BSkT&9$Q7_2 zy>9pp}B)dm*oSbn1f(E!YqxXiT#6F!-pI%PT=;6n_h7@iYG0bv%xMYd6VKx-sakN}hQ-iJ(0N>j|I^@(<8O`s z|NsBXa!{f9?WGv#ptWAxHIm>W?*mPQ`*eN;o7H&`dey;yd(c$}^$^8d zB$*iYEn|e9(CX1^J0}}#$ntEEA?yqcNC!S4f>w8kE;PI-NN@nhzt=6X?bQv_cfoCIKJE1KCFm^_`EhvTx@yP?-hGcS@-F z&ZB!XB$KiK50HRrf|b@@XcpC|aC8?}w0nuI?`VOoo1hwqt70AISmjD0%p8$_P&(3om-QXM6N&`JRuXuu2#{2ZvOZap` zc1VI&PO^797kGBMGWfPWDdG0$ZU#lCXD5paXhk5GM>qI&>7$ecM*Rp=!g*C&Lf?dJvzU7cK-M2&6j}P>+IPL z?l5??9`NYYQ7I|(?A{N`q#oV3XFr(Nda}gU^fj^fgS8XC|<1Kxs}FA5F@p;)wt^60e< zfk>r>GcoL2gcLR&y|$J}Qj1j)y#kM3+rwe-kxXz%di2_ILsY*HV`A91Kozau`%VPx z05^~=%T=KT5^Q}8c)b-gooa#>Q}mXD&eDSz+&vosC=6#8}^^X$9=-pYoY_B{TBcd>Wgbm?|2aJ0Npmh92p3Xbh=n-icz7qVTt-3vUM ze=wHT9d|DPt?=^cOjmH}tgisa#kc|4in<3)ULzx)%S*f9g>oka@aySzMctUiaHB2WW48Y|^Um5w_XFf)KA@|Zn3@Ba@FcUDw zLGuYl(9WvXEf8rIkWOg5;?WH@K>$1=b`P9Vj)OPpftC;XbbbdP_W%p@LLqRVi$q}t zdKg5i9u&B8Y77joi$V7vK?IM5Ffr^?fQ6?=udOCToEIdn1XAqg(Q7LL5iAV_l`tUN z_h}+&`6dXq`ezUm!#*8V28P$d9=)~?A%dzPOI1-~6f*t~D!*Zy!F?bH%X&hx2Y>4# zP#|<(_C<<2$8Prm(A0FfXLmm+ow^$SH@x&($>X>ixC-{{{EkQq;PMzWzhQZy#K5E5 zvfQP-5?D`2V#qBz!;> z*8k(32R$v%7b|&mcY{3b)vfc>qxEgcGw=xGGspi|TMm?5>(1qP%?dUG=16R%V<5z- zUqFQu@}L~7d;wWY2 zD}Hc@Fe!pk3b+MlFAmM-$Pt8oA3SJ9k^nTE_*+5S79cAeLG^g&2hgHh4z%^Tu-e_F z+quBi@&SJvXyo0a8+;!bXqcbFr(5TQFX(`H7SNK^=Gp>=l4wWBF(aU?Tf@M>;L5+v zwFI;PxD`^jxq?bOX8u;t6;Y1IT|qa)fNlqeq_A#R2GEpdcM0g|JP+|rtaD6)e{SPo`t}b9MwLb0)P6V))K19KP0q{YHkP`W|G$Q72`om-XHOn#Q z5=PJwJ>bJ$!RHmhit1xLVDD#widdA$?6qADkum_q!ADpig9<8$c)1@F!@kepxPjf* z3(vox$xLttR&4wQ%6P>l(DTYYx_5%6PCBo7bRL3dVJC=zUb3J8eAFmVhe+AW!lS?k zGYTNV-vT=D)uY=3 ze5zRMeDFem0u4~D2M#+>XA%~4-Q3`y(+fr`a6Ni$3m{ToeVG{cMIzNs5fE`3ka#qD znzx2XdisO>3aWee#Ug2yg~Z zzcrPSf#H~|0RyfbJJ+Ia%V};lpYGx=)C)PY7Dw;$fNm(L+Rlipu<33^LzY1@S4k``2f>v&}w34&>=Ji`#@42 zn#Vdna{l~wkiR4qRM}STv|6(k)dD#vM#a^%fuH7!vctB^ZAAHZ_ z(QWhFrSn+hv;UxVvj?BCbh4Pcbb@uebRO_%{>4}l4BFq(9n#0+(Rt0|;5#0VZj;ZQ z*BhThbUbJ2WU=d<46@F#+og{KGzNU|9Z%;V%P^- z1PD$O9=*29A>!H~aYhLS2G35+=~D;L1f>ATEDs#_c?NrQl5wBJH!Qk9VGA*A|5HAe$BLeS<|6|!p%dk6y?B&5zhUnt!kt*@9NqYMww% zFC>&dmrD4M%AZ4}Um^~BG(QBDKm4Hb=c7mSL4J?shaWtkTb#hL`;Y}3yDYAtngvuw z?#otzHiW_H1u<8|?H;)g2q^ z7z;`j92@GGib^FN8|s+zONAU8>R6IXxg8toSoQf^nn5eGL^q20JP7A|NVh9{(2V`1<=(6kg?s~8Wjb{J)pn_ z2N^uX4PYS-F2NdWR5U7n7Lz6Za{A^vS% zj2{0FwVW({2O7u(jpy;ZoOvzk(fJy*xAF-;cwplt=)4falRlk4;O(OZ3kJ|O($epq zy`leoG#`3cUi9F1K4o|bwE0UaZGt0cA9Bm>68?@Df&bvn{KeAO9-XI-xiI}_Fg!WI zvB8F)0kqMw^ef2N32^g#I^TI{o-1Vsx!}@k9Usk?9{&#-UILjX)^fW<0&HIAc@M_x zplz|G&pkR{dvtz!&Fs=1Rz{G&jX_CJ12lH5>C^cf*4G1{>lx^ju3 zgxmA`-48yD;BBl9EpI(K@0K$Ac7BKM+Afhm^bQOhnHYRJe?bQuKm+CqpvC0iQQqDj z@brr#Xaxz259rjtli(EBa-bv}w9-<+1G==^r`rTPXsz$j9izel+MBHkYVCAFIwQ?L z{+GBQoaXWU_6H9}S#UMccm!0)Aomp^TM#^YZTC1JI}B_u!qo}hObi~Ni)(KBc7Av* zj*xKo2I+d`)A`c3^8wsbwlDuPGI;cgW`f#GZ3f6Ad5E+Fs;>iJt>e}MB}|c^`Qr5u zo%w>GQ3aH}tRVFs-R=s=>tVXsyZ9_lluGXc4M*|IgBn-T{M%T>`M2?idHg?QaiZj{ z;U$X`{F4v$x(NM0YKX{5o%f^K;8d@P2F_eJdV)(6LP= z?_QtjJm}a^!wcGw4H|^>>1Ks&JU>uUV))jh8@k2_wjbNTLcUbSr`N;)?BfY7w?X@{ zWyBq=WT5-I!Mm)F7Hc_n$-h20!K1szfWrrR(-mk3gfeLPIK&Ew%A#vfUqihK8h!Wa zPBd_Y?!K;z@azs{aO{$I?L1-l4SDS_DEz>C(2w!AfXNvs!w7nT*2{bTnVg`msw<8B==t%(LUeHE-ckrRm z;81Y^ZAX7%`0ceI*nOb&%$CRaTQooeHr+O#h>HIYj?fMH@BjV(4|0sF;S?m$1$G@}(|5y(W;&`AGg}ceIjW2NkR(?_Mh-avXGjKBy>xtm$ky zP$~+t5aN6O=E8sf|APW*24w84(-1Q92Wr4ccy^b8cB6me1&waNj#%{RHvZuF-wj-8 z`*bV3H2C-bKeBy@{1tG_J%gb;o}=|Pe;??eH_!nm;FCVVXGe9LcX1hB0`2KPTuxK!p)Pok?D1b&5 zNHnV|CGWQh*{HXeOPE6^R0y}67fZ$Y;&SspGn zcI@(Hc)cIt8L<7}z5G7#-8`jo5F7s=_OLu$bk^_y>Qu;K&|ZC?PJ<1Mub)B2b3y$< z_{FatT(2XfY?;cXw#t!b`?Z(obR`s<*hx0(+tcv>DURs-#u6lkuI6ksTM;lX$l zw3UOy2ehRgvbPBAlGo=@r%@680(a=563Bu_kK^tEpqYJs4OY#Wj12q&{t^5F(?R7A zf5-`b4OtbCVAyGXLH`J(bzmOH!80P@n&h~91=xU)3;bc1`31pxVT&svSIvOtAU!(W zC18zp=(@_|?m8d?4nx8d-fzL_zLhhuxNiwakPhyHoZfBW(aG=A=`L{G9o#B}c0!;N z}X2flPSD6oMhXkAn!JiFV#lj@zI z#wR4tc|exAc=QH??t1}g7x*8b;L+_Y;BoMQfd@CU$4*cHgO-7LC?53a^!9)pW*LW6 z!=-`m6FdeUc3}8+n7_mo`7jnxc|p>8AO;2whSIaIH9dO4y?>8hZvhX>6CV8TCqQ$R z-!FLdmM{u{hG1Yb_Q%2F5un)iINr>`09uCzTA#!k!UbwgGz&0rFnEAQ5I7i)fyWOR zz>Ah54G+NEhsRo&LH&1zV=c^*ApOT$n5Ce!G?bQs(y~xm4ob^|Xwcx1hb;rh;ak8C z2Mtqr^mc22tcJP$hX<0|!403|;K2&0!xccyfAByB>juzhPiM0RXbt-DW&@~1G@`#7 z4C-Vae8CLezG%R}(9P3mc)Rsvi3K>lcb-uF|Np=J_k*CDgg}>sfp$f5d35)j2YFK! zw2Tt6!{`BPw-2L1>&eoy9-TL$4@0&;@_2OfoCmdxbyPv!4UdBlSUezCzWirk@KBav z^k_cJ?$P}Chezj4us^_h4R3=fu>IgsM?{$h8GnQoNEM(R?wx-4fG%JJO%xfpwqD|IoeJKx7Ner!0y=u$rPD=)1$^!Z=sb*8Py~Ui zZs-CP{?=)X3=D?I~(}cZqE=YTKN!K5bPSDC< zE|2aOaAN5E-uN7n!=a;)G8Ua+t3acQ9?d@wlrHdOJmK33b~0#S5$1YOf4Z|5>=Dpb zILFSOR?vP`R;QM-+S1^`@8@_$5h)@hJZ(!=XnLSp5x@aXvAV<6; zc7yKgBd(xB>p{0jS0Hs-L0(NVybW%|86NQIu2JCt4McwMohM`3qvLeSO&Q z+e@dv$gO2ieH;Kfe#!C^e~SWWA_z1qW(4YSLaysF0JRoAc^rJj?92xegM=~@a(+k(|PN)vgg4U z%>KP1O^|zEUJE1QY=T#>NE1lP$MRH3l4Cdcf|=TGuH&GkKManYT&*Wd?jV$>P3Sz= z_zYB5mmX_9S!oQuD8U|lTm3uG*!y=-25Ec=f>7KLiU&gRLMT26#SftbAe114 z5`s{|5K06>i9#qb2qg}oBp{R|gpz_#(hy1pLdilXIS3^Wp%fsLB7{7EJN(VyeLMS~5r4OP!I>70?m(IFvpCrB6cXQ&9Rei1uhcz*9Qwb>Kb*(5-vW8@RE!ur&@eV9?tPa*RiBcK}E= zta*9^+&taFc;Wx=|De`2ILUb&Kd|HP@BhbIm_ca^(;a$C>7if8c2jV0lHb z3%o209-Ymg00B3NA@@c7f@BLu#F*hvC(sZA*bFd%C{QMV`p3bZo!3EArmg==_&l5c zeJ_(TJOG(ugYHO!>c?-5M9lW9t)La8~I>1iES(H%SJ<#JjA#GakUK%v|M zTA|l@!-ez13jUIO@CuAJaNjW)d?_0{=+rzG8}VcV>sr>&fw8}ki(<-5C>>I#DNk6!%N3l1R227A{R=(yjB2p z{XBbF1YSaiAG!$9T|Og1$NO1~ZRd+o0#*G++Ij zkzwBkY2-Em)W6{I%HRM;NC^bG_ybhjfmYHWdjoVD8^jyXFe$C|=yj2W28Q7QXiI^A z>H&|&-wX^44ZSR&1MHK*6FbQ+{LTjq|9f=a+XY%hx06W#)YySc^mu@#Zk*s#H!>cb zH$fd)$bo*0H$4u%6!Ea;1@&c$Eg?gVptUU^uez8adlj6%yE$C>w;lKB6`f@W8g9Ao z(+S;;-fMg1HzU%{J46bc5a7}4{@8hB2d_Zc`4i+?dP?AwkK zh-ni%I>E)`VOakI5fYH`K1g}Qh*RF71699AudUuMMh3$J-~uRZLIBjjQeW4W1En6G zogY0qe?Sd|Ch1Nd70^Mzzd)(_pl9a+XsQOS|9=X0_;irN1!Rz8AGG567jlrm+z(Fw zptOGcFsQXR!Lgx64rE9)W9b)Y65qh+*v5|Bi-a~0A#q>}sVBa9bV6=@2X*TpbpyD6 z6pY-v1ns}>JmK;GV1o@iL+Ka8OKB4tY{VGA6O`Y4dY%6JSRN>5F+31`7_`2pl+~m2 zNAzJ2&5MQyJUf588lLp)72!9$gosU0`Nh9YM%YS5tQ0gG20H!v-D^pNg0u;q{||cp zKkR9Fvg}awVV}+m(MY3*p#F#lq~`!1k87x52YKItvGgnCyzJKhC7NCQ;F)1jkIr8> z=7Sv=J@{RYqffuNFfc&1%D}>#f8R;a)y3#oYXwl30*9a37WUB+X?Q~AQns5f#>c2pf)fWj?rj+Tbd_--f{5!J$UK` zG=1NCyObSXQk!1>4od&eAx!~T7U(tsWeuJmpbP~L55n`v^6oPIyL!Ai*rLSO*#y6nNW}cmwKuaY%f0Na0 z01tiPZ83mmy?sDq=iS~CpnF}LLHor$@HHVo%c@YC5Z%ra9^KX+jK{l+1vHO=4xa3N@^`D_cwTsE4^J2?^(iN|zd@K)^FgtcIc>X`o z<;dvq|6t33(uuE`Jv&c09%FzkeLHd=>|cwoj12pnWuX2=lun@Z!M~5+fq&mM%Tp!B zpmyjFhn8<8JpB6#7(M4f|;V`)55ka^IQ9gk-s(1cCDm*~ufy#5xdU4OrYo3tV z$8LM*i7B4FE-EsP$6ZvwgRq{*T~t6xfC0n+mEjDY$5~WBMa~NTk|f7tE-Eq%AW{}g z%7ICFFsT406~Uwum{bOnDqvC-OsauNbug&`CN;sN7MRp#c+Kx|+yQK>2V|)r$SNI> zFlg_di;4lv&D}042B0ZKSLz4^C7k%(t6k38sf(qhoqJ>yLu%b#T#pt1k+9^bEf zFy8k7-MRCO8N8N3gug?C!{h%!577Nk9?k!m`I~g$_kTI^Zv)Fa@^1^_XY2^!U<9+6 zIzl*@z%1sD5DxI6Q6843OE13s1ZpdH-t=gG_`st#@PTLN1^5+Fzd%<+{eKC%9us2y z1CQoo4?GUOW9zE=B&za%vp`$n6o;=F=q{iW6qik$DFkojyYpVe8-%17(gpr zK3<-Ok|DC*{#y4N83A3;kM8mfrL@?hHwK=TRFJ4AAzqYv(zi&clwK z=RG?Af|H+1XRSmRbBC);mosCBt8AAuQ-`ZumosyRt9+L;ONXmMmosaJt74ZkTZgMs zmos~Zt8$k!M~ACQmosOFt7?}sSBI-wmos;Vt9q9+Plu~UmosmNt7exoUx%w!motBd ztF}u=sSZ+`8B%_N-2ezW6yg>`J1{U=uKhROkpnk_UpUy`voj+YW zU-)$MsDPah4v6EfpyC14*DjIt==OH-=+yM+%ys}RSMPK-aBcZtD)CwYEYg{60iL7+ z1*L1t{}L`A%VdFK7N5>!0f-9`8(O>FEnf2?%0$q7OzVLXehkIo;Uz5{qD(}VGc$H5mO9@ebjz60bWob&IITfC6)K(6iYfAC<0 zw8jzkBf`rAbXV0HpI(1P{wW81_+8JxW;HzEYIxFd2dL!q z1r29|=IcP`NuTuXJnPsM%Fysjs}!li@%(>uBctH~NB(VKsgn0Cm-t%}L0h-F>eygo#!&j%@X`d(qW%AeK&zJ+7)n2R^j7`%u>4od z>S}oVHK%XqXK=gS+vE5#P-g<VZ6735j3#Dz~8bRv_#1AGk?oE&~5fU9-3EuI={IZ{`c>du`|3hfq$Efn4?vU zC_^b1cv#?K>D$*6JpUi}_hr{(*y%P*_`gC^WAxf-5)sSldaIPjWj10&J| zOUrHkDTi84@=ra$apCoIL=aE#=={OIPuzij-#N>RC4y-aS}uXA;{b4Ve6jQ+I3Xgn zKwx9x@ctfn|8p<6PYqrr3tK7B1@7X4D|0!7b!ihI{fWc;+q@Y){vU2ZtS|L}TrT6u z?{doH_;FBh8eRhRpZ*_jun~l`Nj`h@M!omxE&A_cd6B>64g&)Ne;a6*7w9g`K2Ws^ zz6MjqqqjuxKj;9;Hqb$wUcDtk|2-@}@;BEpf~Sf>V?Gx=dSe9s`*eN--;juuTqp2v zW3hDVU=jBK1@XDk4<60GnTzreK7h&dZ*#F^bn0*s2OXMd$pm6Cfy9_WEM|}9<1C<4 zFE73}_OZNJtmoVMtxgl&5>hYxr*A7&~&@e;Jn05o#d{QQAOZ}|hy&JXa0z&}t!;Py+FrjIb_hAK(W!JCo>PW+lK!U|wf z&>dBhpo2Fh1HhsVV9@}OTR{hJN)~`c6TqSc9?h>o_f#R(|Az%Y`!*9;9vpbV`tJb$ zwhxf%A9Oz`%>SA$!XKRYHF-b-a|#~+kCi_5wEV~4V)yU=|CiH1N1sAU1;=j(8B1h5 zdR+`b0mTFgJSMMR7co%Nfr($xh3Nz6!k8BJfB*l3+G5S;H=8y5-7k{wu4UL0_`P`0GR_>*)9Oi zvoAo^9H@h=0GfFhz_Ohn9n?dvL0{Q!F*)Tn^;l<0#N zkw}0x$f){sf{F>S!Kg!d+@9a>eehufFB=A}mTEp?0O>%3hTD5>cU}V30-{z@Obk0g ztBUrm(Si1d5FPA0vY@5bpL{w$`gZ<6bg=6nTK|FeaH4mx84&%QZ=Rk1p@V1qt@)rq zlU{J;jufT%%VjZ8eMMY(eCQu&HVaZLBT561evkjh8*0F30t7LF>c^;$KD|kd-~#$K zxPS)TJOiq4`#=X2fo}u_7toC00y>--beBSj5F@yN_GE?>(3d?lfBSSk1DDO1_YY97 zeEw64D4(Bz%4g8w%`Bi3xc(o3b-F?2vm&T`7WwD-|BPqzA87f^$l!7O5U7^&fn34{ zSKm;>1&a9~#?mjIptIL34|(uA9rA2`$5_m6c;MwsP(*VEFVEn_zm12_v4h7Pv@rSq>C*R* z4w@}!eU0TOAAYA#sPO|=@5H~&hmX;*!^fNv%wz&FnZQhD5R=)X`4|i6r0BCRLC4yH zb`Lf`d*IPq_W(2{cknf<$N$5Qoi`ktA255sZV;^U(FC2VhTJ}I;@4o|cjDLZ;TLe^ z7X)?H1byrUocJ|d_!Ypy;KPwYy){7}djqhz16Vu&bYHnW_!e{f0I+xhSR8ynvOV}7 zb9?B0f`|W<&H$|;cLH_Od@Mh?bbjV{y4CPFq2cg@1Fu>C9fs8zw?Xx*h711(Cw>hc zey|1L8_w-LnvW}Z{6Ad!(8KZrf9qt>B5CkORHU97sLFlf!SDacvzJB4!}1t^`!i6P z-pe8g=G^@I|G#JRA9%(41zzzof+}8NP{qsW(OUwpc=?-F{r&&nxAOt6$``Z?!4a+U zHT(vut3cHSQFW~YQe6wWml?E|9d}&|n!SKzG2C@6xc@=V`u2ee$@T3Y{+2w@#V^Ny z|Nn3J4P4bKfp*Mmg6dj%o%fC+#O zFarsQ!vs7)<1VcSO4vL)???ZC5DmM3awB6Kyk*Wm<-lRkwUhr#96=_w zdck)t?f@+|dM)MAD+&sl9iU0F*E}A*qM$(80otA4dC;TN%H!Ze7O&0{Mvni;dwK$3 zryaDOEaikwMu8`-B2I&fSy7RPj12pHWkEA;nA>Sx7(nM~dNjY$@aX)FZ8l*a==vfs z0j}Y}Eej9Z|NlX=37{ofpym<>hzp%fV1Rb8Aqru$2@H%3NLw$n!5wMPIV3wlI+3 zPi+XMAPJ(0h zp9q!-1_qSjUl#@pJ~W9S`lsQJVc_8)pWdwhKCQ2yhm?WFo-ccLe(?lt{eq0Bv>qt& z^RT>89Pi0^2YJTVv+)m(8DF2yXNH${Iw4K>dMX};j<0IId>x3nvc~d8(L!>~_UJt5 z*~#wPna<(cSuWtwc>>8$4P=`0q2G?n4! zDTM?(cAoJB9cA*_v-3Z4xE=KA{9$;>+3nr1Ku^(B_r{C9a?_gv_{iUId+gejFT%f_E7i_MJj1R6wIZ zy|zz}fn{YuvZs+{du=W6f@bGXPMm^_zkyu~naBaxr{M9n-~bQM1m}O)Bog*zSdc3@ z`CIRSPEP49Vg3(l2Y$cpsdx``ORqTCWJs~qc^J9~!{hsHAI0CODGYSBGUj>(NIe8u zumFlvSJ)B8pk9uZ!&XLkNQU}!et?fV`Y?hPK*Pozi!42QZ6j|(3q`P7z=TUT{9NK* z+qsHN44@;CK>Zxg&KuBt4m-;V68OEgp`uJ!7cfBX>qeyE4U8xy0A&0boWTRY2Jv#4tS{^T54`~q~ zjTb|Dn7y{WmDqy44pxBYXjGcnN`G2F48Z6p8Oboj~`gVc{L}BL9YkTqlINUvXFvA@w zyE%Z`qo67L5?#;=#MW;ms-U$<&~yZH1@s={nLIYFFph#SKh(DiV^ z9-W`}gEpQZCW<>HjyG_Cn&=D+45+hvp!CrB-S8VE7{T>dut(=*$bLrf9%7Gf&{kms zk6v5(>!2F&7BnS-&r|g1WQNUV!uubc9}m9dYJ3J>Ym<3w4Jbh|yPOw*x7S<^4}kT; z&P()cKEUMJ_ye@yr^MH*JLI?kXuY7bhvlbo9*^EGh7C*%9+n@=yrASn%y)JcR? z*ftG&(kba&|?|x8v2c7H$qEQxsbvJ_& zJE)Tt>e1Z|$__5wDUE+TKoh87DaXb?j0^${#p$r{VJ?yYU5o9}4GN!}Ym5voosXd5 z16noa(h2SUL8gX%k{5&W5V*N1z`)#NbUyUx zwGG$@PIzChGBP;sU|tm1R zHxVA4S3NtwgKnr5fCUOuk&F5Tdi2U^~D6_k8lL4(J)yPU(bJ6yn{ z+m*w^@OkLj?yziMS`|Y~ug_1t1z+ zZt--36*m84ELB2s%_Q(W8DRf_)*OOdl*P=z(EN{yzsG|a6gZ$uN;`8@B)VN0Kz)OQ zFS$Th0D`KMvjUKvW|;@T`2cdQuZxOfl`gM1+`3C%@xU#Mf!p%}WRFj;iuMM^HWuxc110cV zHNd{~NOsZY@M!+QQ8Lq|vqVM3qqjzzqxC?YK4@8dw~vZMH>Xc;jkb)d;Ww}sK;yrT zmi`|~R6PG5^K3pY;%RxT=G|*$n7oU%Ie%-w|NsAAg07DTg{?(5gQKPUmr_B`&hKDZ zBakfk;FZoA6$8gk_b=T{j-Bp5x?NOM96R0rfJ(`3HjmEl{{U5bS z016YAIUB%*Tx?~j7cd-rI5 z;{gg&0Zd<2?%-vAB2TJ!s={_jk z52Yu7XwcRY(0+CShSDvd0kh^#CIJSI-pw;X8)_{-c<{S_@X);H(Ri#4H2U29>;t%{ z1qGV`sF4oZ7Rcq%Eu!MnU2+OmoPe{rZ?B3TXeBd?9;6m~4%X<{T%*UqQ0MB|>!Qcu z(c9g_B*0*J$rW@M3*`JZ&;LieO9VtZO9TZxx=RFDJi2QHcsx351UWo9O$0rX4Lq6; ziFjImt-1D^+12nZxFm9Ieaqjs1mxh}W{`oP++g5p_}_6Cc-p8lMn&Sa3^cqP|DSgS zEwwrC+WFPB^&5X*4if`|Yj5d)P!{ObX>jRYvKnMY_mMW z3Mgn7%)fJ^5CXxVxKROWg1+HivdgS+KG zi4o|S_Rbg;ht3ie9#9NhfP)5xgqwxG^(q4cgVV7V zu%(QS%{APhTa>_?M|xYpu6FJ9XY@?I?$IkU$)$72nARq+^((v z`8yzoAhD=`YDm}46CS<6DjvO?LEb3w1LX)%d$ILE=Rrq)my`cbdL*Ch&imofnf1h@ zm#4G4ryCR;9-Urqy8S+Qbb5X1_WRT6^{1P!lMA$>s`-$DNAocePs;n7#NR%cHA8C zK$I;)w}n85CwDV9|M*`j zf;5rc$?Vt-R@58F=-4?GtUURqW2ehq4#$Ri4u%q5&u%s!NS*6)mj``BqSyA$W^iFD zb(WD~pQt?YV53K`?S60~Yv^z1hG=(T-y1|B#6y;(}w zAj6XgWuo992Djs%Bb35AH{cL1@$pRV2M1;A$-4cX-C+W~h5tQ!OTKe-o=5m#LT~(k zOP5<5C0riO$A0`jU;qB~WY2Dv^B$dSj{m{hAy#|z+Lmtu2lB!*j11s|VI0BzqJ38I zU_ond2f)WqVeV!sk^mns19o@88PGcW4%sWuw=+W&h;E_BL;`U2*dY#vh z-COtH(&Z;d3ETg3^`Bo0d33W}^yqZ?$??Avq~5Wct@Gf)mt3CRG3QZgA5bIHaVsON zoyh^a@a(^fHp_7rZO{xC1ElU~TMz1KxwgD5;qip@zQCoiXYYPc7Ynv(!x1(R0iB_R zv>=WT}X$n)X(Gp0e;9y)R6JiQdZB-gReC_ z`1hW01RwD0dHJEI7&^lyC@WhqpMkdFuFy@YsMrKH+0j=J$T?08X^e|{h<~eBAzZ1Tt zeIi8a2uNxHXnER6*!kZcy|yI~$?YJ?B@lhSohKkp>9q}m$nFNof^JjtfSQVkJ8=5w z^uR^+#w#leV`)Sqc=>&@V`gvf0xb!{I19UpYTaO(e3!dqtoe$cP~q4 zcS{?jymori?fAi?)9FjMTK*{A{W>1SOoS8CCU~^| z@BHD&?{a{!`LN;}(}G>c+Q7y4VbFPJZX69eKs<&Lj$;jA256BYZ2bjz)5*X6pr#eL z-3Uq_zMaQl$D4uoX z?)T~4%p(9gm&u!_0XkW$ifKBjnTh-M8~6v_N<*>Cr1%e1eeyAq88K zKk~OEgFFM8 z&qi!X?g4K}2D=wFYu(N1Vci4X-i)yo8PeVcrBBb!Yp^qMbsFsTOVu0d84F4k8|s;g zN~Ig>ne$6U8|qn-OZmY^Lp9Wcj>Me@K2f3hALC9&HUar!DYEeFYoK4j12Jf({iaqpMRSOvy})3_&CM)2z959GBSYHKZl{n zzm@?R3rf$g^})UcaiO-9%<^nL23pCm?*Jm>c)<5vg9iCL;2Y~e`as3f>lgg{jQRHk zGxG2AW^&=*=gjQFzt5Y6f1fie|GsKA{(aHxoiQo`oi!>Poh+d3eSeR@8z*1~AW}bi ze^mlJ(&llTjR7<|(kY_i0XgTz<2cCu3>z51hfwB%){23q49|LYe)Z|}QQ`1`%q;k# zULp$G01w#|?P+<>hu`_LZ+9yArZrQKZWa}vZVS*!43JZFA!BRc7DXJWrb0SJ_x=YT zMsT48TKwBJ?>!J>^!zR0Q@P=OMA}9PGu`mO zYc3dj1L*oh38XHEXLl?EXyW~L$um%Y)uUSzWZ^B)F;vhC(m|Ov7d{=q?eYEY2M@?m z#D)i6Z$vC0o&6cqru*g7`4i==UfUI*EF`-3Gb8#AO@!8j&*0XvN9Rq?&KIwdCKlYm z60bZuUwU@lc)bc#K2fv&MCxyO9Crhi`wXC}_!56hF=zk*+5rQt%OI2}K~r(xJUVq$ zJUSuQ_JR}4E6_6b&ZD3K4M_jd@-Ba~8feLMH)yf6<ga-QZospg~d8`!V=i z>cIK#pvU)%K8!zMmt>fFFn;jS1Ras>!a&;oVI!pT=|T5nC?VgEA&PQ82CV(#+gYO` z;M4ibL-Q4Xn?A_jmiPJFT|f-bW?{y6F3=OFL79fXWk1Nlj7LESU9?{O_y0dk7VJ?E z%NP93pfL|m%N%GxctBGqSRNV>pe-}-fZ%TdwWGm>JE-9T8if9S(Sz|NEHErQ7(aMu zzJQm_Rqn(ec>fL*Exjcw9V;0a3Q6DzYdSe#Q7EvEI(0XGQX7DvMmPbp^zH|UNsn>SVKIlRcP-<-X2wuo> z#Pj&k`~Uy{ho=|kh8jIZ2H#$g|FEp+1GiqmkpUVa1Dy;2YC^QX0fi^{WB`5!*vS9_ z&}KD6AtX`Zf zuk{dhCpi8M-?m&T5km+%Hq_|A(wh(CQ;*JyJZwSx9?JVXK)VE6L9K#r z7L^VGa4)B&l#zh}v>y8V1y9BoyFjfI&*mQr{7tVw;oV!n=wbP;SjeN-gu}D9MupMC z@;iSM=yFk?&O;u}j~;mRRw1oQ@4N@vn*&*se*1NSN9T7B&HIM8A@f0w`~ogAjG+C# zGJ^bqE)tCVf<6+0U{OV|s3AyH5hQ8|7Ig%R27*K#L85_R(L}IlAxJb4Bw7gBF?5`z zbRK9yfv(5*dl36TwRrP+kcBKZAU!sSZOR_ahr!!~?s!^WC@J@7KE>GiPV<_J<};7Z z>)?g{?|n2uS8p?yNFjwU=)Qyw839oI{|E0!`_Eitg(>gIzb!_Du_H!+5zJ!hh!Fr~ zwiprSju-)EkLE)x9+nqNFHZ0QRfC{2wc30^DX5!8o~t8QeFK1@}$FA>ER>f01(ozdQr1<^&aB4S)at$5w!4{Qdv`WjzZ6 zgKw{|f_JZro&snF!NI5Vg~!1ctf0$eeL7Ep<#1k?XN&{lbm|HnGNHa~^!$@m6J|L;9CzZ-soq(@NdH320@9}`geHvpx7 z1918`0jGZxQ2I9jrGEo(`Zocme-lvp2kq4GF#xB36L9)B0i}NfQ2IA0^k{z90NUjU zO8;+5bUnV`h1dtmeK^zqF$ItRM@tdu-=*^(QU>s0{13|jlJM{a-R~hnoAl2Lx*~-I zlKy)g8KD{A0DqeRSVly}gYklA^G}5$Q4ebu6^G&qk6sfl&)yPKMIXy=Wm&KdI$pgs z`U<|Smr6u@I(Zy7PMw8E=RZ%&pZu*Cz|-9h44|q(5fRh}K&v;Hc~l&ax$r8Yls0Cd z(#8;6+GvAI8&z;=BM&ZZBq61ZKHBL#p!p|AtLd~)=T+a%JK&apZ|7sr&R3qDH$i34 zpWoQapeMio|A+1h^yt=6fv3NQ8d*^F77aT81^IXlaC7Q5f6HW0uLX3%hAim7Fa~gY zsteYhy5Rx3Q@a|aJ#`Os>k6Vh#lOvml>xIoWdj4le|F(6mNC!pJwd|UtXw}SSwy?hL+Ry*H$fOd4j&e-r{;Ilt}o%35pL?D!A|{fW-~K;@~932j0KM1Kz*I695(mCn`Sh{w*Hx z{wk#W-Ugo|zn}{bc>flUNAp1i zkN<~2`?rqrw+4Rw|KIT#iw*;578r8gA99NxG!TWYEmh2Jc=9FW*r0p(Lk7NrFAcQ+ zmzRNGz=sz(c=!cectIPGc~JrfBnsMq%!?8>y7482&0zvbFL(6N#Kkw!F1Vqk*}{4F~` zY7rL z5Q7e{A2Gr&9fFN6d-U4&P6r#z`xs-q0(|}?Xdx`D4WbJw6*R!5f)cn?kO7wpV&GCi z08}cJav2_guAV)NSmfJ!fPczCP}_qC+GH$T5^~gYO)8F{1}$Yc9l8(7`;* zK^e07H@FwZBj;gxg1;Gjq;2Ox576N}ANkuRg9dm{dUT>4(1X4o7IYpDAKH06MSci3 z!Q??z3m^Qv9zOVaJ$$I=^?>jA28|wqNBqI=HN1U{MFMde0qiWF!Uv$L{@{C7kN?Lz ze}S50&Ho^^RE~${bhYF#(V7w?OSPP;c1(z1! z^LbkI{{R2~atXLPa$x`u#CcfiB)Sm`H^&JQRHq#YOnKod-m;Zl!Y z+tdwcL$ebc8jgK;X!vJXF66O8n4y7zgMo>m^P|V*7b@UGT_%9$DLuOVB|zsZ?P5@4 zU|}8{8lRAZ1}Ct-`WkzsJ-q?AbF4!6X+zBgC$0e zT_N_27MDvjJ$l`l5!r15SRMa18Fr8V2OvsWEH0P6^!R_G|uUhlYPvwrvJ9TRKKxAJ z(higuL4$*gFFh^K7MB{Hd?^Gn7K?RTK}|&L)|rE?ONLmd1Xc$fHwkzExiFR$)Ia(N zYUMQlN+?b>y!7%k*!M5v!Kz<+fX^kvT9)xQgAOn-{Pq&GIolJ-1B_q~Kxgtjz#ial zz5#0FoqRbLo~*_yt_VC-4jSh%W$bhZg}gn?yhdmWXcv2_67d;v(S2 zlnCg+5^>NmD&h~oqTr^K2eu_!Y9hLnE!1ze0l?loS( zF9v{LqSO|H1zlCa_ zIY^T^+&YhDP&e^V=~EBOvnAP};jizPJQ!brMwy$RF_)lJfDR0f{M%x989HQO2iCp! zX#T}qWa8Z$V!;Xyk8Lqre>-G2__xJy{p*O~U<5J#cf@co@o$si>WG1zRd=@Z>M<4# z2G9R)5{}(|9IYq$`#l&L7+!7$H+1l&lVTP_P_G*jn1#rJ3AUfs;VDSB@MHn|hqUm7 zgk@cUZ#NrgtkLk>YoxJ5ka?hfvgNrFe~(_9GS67f-c1K@T1gcYcDyhpF;O1P?C+Y3G5#w+JD(84tl z&@B>k6`&)_ApZsUB>Qvtww|m@^yy}I=@J7S9EN;9hv)ypzLuwJoxOWmqCLB94!Br} zm%iQs8W45qya>6^j-P)U51SPa738ey*PEMdl|c>6I_M(1HG<9O@uK1_h|lQRVMXX85+Nxt`I*%Wy-ld_!nOWh0moD7mv>Oh6Z?0-Y&U<*)fIp7d<;qcqIFCcr^Y5 z9Rge|>(kBe(aYlL*=cgnx6|byhi7NVK><*1bmst{Td@FQ=IJG%+y~OK&qxueya3%V zgSbKwJU z(aU;k5y;c-8fl2~l1!>3KD;OA#xmPh9YX=p-3?9hWO}2w} zx`IjqkK^s2laHWGP{Rs#leFX#5=xvKZZf*x1)O@@hw4s`Tk%2Mo zcspo;BO}A{cF-DXkZzA&)?SEGP!OjbZwDw!3YH&o$WV3P2SG-OAMgPdqCGs zfTTedfvf!XCm`uwRzHX_pfizxUi&%gPPRQz8aH;H~V&KzT zBlh3Z@;m?Z1N?2`pv_{Pf4cZvPV%>KF*7ju_2wA;O@j|F@ymn8M^zXbeyWy+@$chk z{#j5G*8DSxzZG<1rmy8c{^mVQ3=EL76+vdK12s2$SwWEs+h5Va=lTB_Sm{L27~(b# zP)Fos>GPLOpc~OAICk*8lwgD=AkX6mz`GB6eN-GltyR$YY3Fs19N7K{N(m+>Q z9DHT(aqx!{N`da?tZ=Mf2)S&Z)kLCxDN~ zp;+0~@a;>`xdD#H*i=C~**cHBj0De5Uh`}|!t~M?2&0WAIiEba&v4+M*UaOM}_(E$r5f`tn`o8LmFVWvBL zJIY+*!^SNYqR7iLvd&5d~{$|j5 zSsvZO9=#@>9=*14^FgJM%_omu+h{Pe<`d{f=}+Kt-Wjwz5L5>3L)ZnkfYGND#pGgr zgsEm=qrj%xf|;nMLYhY)+nc~%@0^EOgQQJ(Er{xWkN?N{x3Tl@JJB2Xz4;ew(fj6~ z3MH>>v`d_9bW0sQ{vU^IE8yQ}-s^Uu`3Gm2o#7=9@J@sO|Nqy!wjQYC@PHg)cNlaC z%J-X~bsw#lJor5i9tP_Mmpw4u<%c}}A2+<@xpUS`FpzwW(p>}17wt3e{Lp;hg2(^k z%|Ez`r}$W&^62Fe0__ljt_SwucRuC8zwg@)&@odUnjbtY50; zTqU|5$)`MeZ9^Nu0pWQ76cAjXruR}MXvqd2&%^0|0UO;?37_70Mo0j>7KN}u-g(Ul z-3QS5+mU}CcW>YYSHnxqzc|Z-kUS;zL3%-z8h(sBnWB|3dr93)+!1Loi4$F@v;2l=~PnCW& zJb)v|+Pn1D~NGp-9T3mq*M4w9^B8^kOfM0O-)kHqfcSu7;OR>6Nm{uUr~%1#ANntKE&cS+Hqh2B&`d%f=t3cn=3fesB`zM#znFG{ zQlSUG&ncf?7moiPy*6T=mOnu20c-?3dVTo*dszPDZvxF1cy?ZZ94QD|Cv+ZE2Z8cr z=TFDxhm7ELH))`$NX_#;y&(c0e0pQVK6o5I_yKu66=-~(8#Ld?4VuvM;R2B?T%b{O zZqU@Q4>xEC$%hL>x^O-4Xg+wrqxty1(i0xd2l;(lPnL*#Fka*raNz?Twa537U(ko+ zBfp>v$3xH>7uDuR@*e*WAyN;&JOlqWAF+QOJ_7$d{+|LJo?ZX$uxIBb&*n!DJbSAi zcy|8uJou8;^Z!BD&J&R2_#ZT>@c(tZujWC+|DgFd7CU|cA3Mad8h!y6JJ95todM`T ze$eog1!ySE4m9;<2bxKMp8O9|2by@Z15I-yo%`?EeDF`{3Q*G21Dz-7`TYjM!65rw z>_FpFb|Aw+vk4ZUvm-tKA1Hn5X?cmi#SS!^uphKH_xM533Ovx6=&dh6yC;AB`~N>} zf=d^_Ys<+JHC1v=Z?(c)z3$Ja6l%fa$4 zT|Vrf!`EC}PL>`9ZFE7C2jzDa!;|p+k}mw)SomG6Solf>L6@q6hs7*UmA(LJ<(~}C zC-CwS(S8LP;lR*f!^Qww7+?C$@GZz}l1EOPvAoUS3~I!CT7KYf_6Fs{)&u-~mq7|a2cJrL^op=~ zT3+A>@6Gh=6=CqO{KVf@4cZWF_}{nlr|0*Jo{R@Ur(S_hKZUG6bmHG8V&~i;VgWt_ z{WK^){$%EFsskC?TVu-%mUrq1vH$DDzb(X$5ybolW-@`8|G`XVrw$Q&&*tMSpxuCH zUplgamL7Tk2fI@q)ba!EnNni~EuZ_TP$ccu%fkm+GS$osZf^Tn{RfvEUl~E08!vUf z{(hP9vS;UIUrmtDJ(~~z^FVPgkC-#8`~bW6H#2|JNzfq{y)j_-@`yQg_y~jC>jN%8 zghB500T&>`Aou!!3J@M)Q2F6&d9n2D%N~$sP*8TTFff1|-3D4b1!}B=*U*6uKk#V& z!L$onihvF~7iIA2^^yPY(JRB|X?e3))VG(1!J{|E=)XtjAs@@r{7t99U6X^L#mD?}vK{qY6aj`HkfKqxNBgh4vuROnB@?^Z^2`e2KYrlZeE5Oq!Pl&gz0r)2Git%-tlxGuJPE6>o%jV<_?-9!eE0-F?R>ropmsjr z0w+)zs{j@^0E=$`iyr`sJAlOlz~UFc;t#;$31IO8u=odOenB2S&*qm6p3R3@N@qBN z))_c@f)-#L#&&Wpl6zeEJ~;6U@bH1m;Q*V%;R#-Uak%s$Xsvt;BNGF|OP@dg|NDUa z>f3qW6S4l1Uw}o9U%*FB02C2&6F~DHatrtcT;xDSwj6l9gxm(O=mC%@sL+-Jua}U! z02X}!5(O38a^Uq6a-fQcM-H_55|n>S7l7_l(C}zJEa3V5HfX#Rq#RUU%Yp2Z0IQY& zExh#nf4KCqFX-L?&_VYv-9bma!mpX}{C>@o@tUjQZLeMtIeq~bfd`<2V?TKJ%1D3~ zdwu{d`vf^e-~dP*v~Eh`0!R$xWPt@BG0+Mti47nzkmm#%Kw_Y^SP~OJVxTZ@@N7QD zQaaD``)zR0hj{cxeCRxcZS4zq4ed=2#`B(?pL{iuCQCs61J%q@p!Ccm#V^Ps&oAgA z|G}gA@B`3ln8!YrCrZjY4?(M4aQy+UZyk{<+_$eopbMQq`*$RL7*B)33{-#1eFO!$ z1c-Ezc<5{SsYKOR^P}hggNQl@bYFoF-#_OLAC7;X|4({0|75IxbIir+KZ8fF3+sQ- z&>D1WF0{V~x?;2QC&GXRO9qc#PsY;kpslBuN~A#bl^v+25^(8ovHTC}QCt2hed*D8 z{g?~?e}==L@!w$2Ti6FmMObZV#(6JYQKZ5RCL+3Upb0jfek^^9+?mjJl& z=MO8x7lF#DUMB(2;^HD1uU;Q90Z`kiEtv^)?zoRQqzM=bny9?w*y|q>`4GQH z^FwCPY1^Rw$~GCX4jFOq^4pW8A3d9YG4nThvw&KE;E^i+Z9HNfJmR2WX6*0*-3H+! z#?;{>&IA%+?(h)@uf6rOyij`er3kp(zQo_c%>r74?erh)SU#|05AgSW29>4YiqWf= zhYjq`yNn=r^00&Jn+xFj=5}w?e;>_T9?gd!)eK4n?EpR>T+XS3N8a=QVGqdp;2;-I z2fNsX0U-}+ugZbitMcIXsvM}jDi3b2%7NOe^30%e!q@Uf>DiZ2AkA%Iph6l{G5UfS zy-@<5;1L>W(4p;@d|OX?@cUix>17f3>WvW-@U*;9Ea=r6BQD^<_{qca7Jt)c&`40{ z4M=k};DKi+xPk!>6M*WMw_wlxf0+Rqv}$_+vI11Y-3J%?QU8594??V453XH)K$^&& z{5~gqdVN3@3$$MI>jlk|#PESMfa|q-kV%k1AkSV;l=AwPWAh_O)uIEo#YEhL@e`S8KPv>P1Sgm){vH2mhC%EE$ z3Yu8H{n7_)+-VQcunQ==AAHT)>kVJQciDsSG^h@7U;tGg;M#*<+W<^vVAe4zF*KWO@vA2iX-2P$a!K<#6G(EKewbiLkTmeLiD-wrdE z*n-xjIW{~@aBMjE!12IKR>yw_9r?H21Ygi`8&ci~xbT6(i;rK>g&)*j=7+4+I}Bi~BGh28A@F{s1`;)c=!z=xcepMAfJB zppWKB59A7je_IIOzm5?8e;)r&g0_OxzjFeeyblQietCvq=&8h)N~9s_X&Vn4=nU!( z9%g8d|E)*o1&>}EX3zo;__ni>4AAIF9B4%eXuH`(*mg5Z572hA3kV;QwBL*mb$^aW z=MB(Jt%yxG?@+ejfu%zo!-73KKYD`aCO}gKKA@`uX0m|B`bGGCdfnMUgV@c_e)x1= z@@Rha!|;Fy=<0`c;7Z^me+%R&haaH9C|}E4zWnaDz?a4Iuz4~b_OZO_!|!wxGC0m$ z4qE8g`SYbGsF4X?mG{S^*YOXiyL9k16Zp1%eyoa|p z`M2w^r}5`qP2*3vl*XTUi+_6#I}?(?r8NHcPty3)9;fjaJ(fu0Pr8%F|M~{VoHYKl zLuvd)k3fPK()eFr1ZibSvGSsOc zm)(Y%_z32ZD*%Rlqy``lCb%%2}~&)_qEe#$+EH2&8Q z)A(OM`plmnaxWl_|24>$5FH6={I8FIbrgVt29)DL8}CY&gC?+bJbGR3fmRM7^2cZX z{D2RjF#61&53&su6AGZkL(f1~qXrtNK#=z8HMxh-KEZ>V&7=7khll00qAwnnzxbQ7 zKtW`AiN6grh2^Pv(TDN8NArIc{w62TfI#O@kLHJv@PQ=WV;%?JF@Y9seQtgXNxD8D zb(;6Up>$xvXZ|`7CTPTh5-Ss#i8YNs&xMHvDWx(|lv0oV<8Ms_-I3FJyTpTkdkNTC z*P!miol?{I^WeU@l*UgmnR;0MERpeGJcS5w5B_~z9-JpU{vYzRyj1!Tw7_r5foR9L zSWv!#=5^5hXsvre*JLn*wr7Eo+X2v;h}Pi$|Np<9>CtP;odq6A7h1{4utspqMNVpLHi4yy}698U7?Jgy{=4# zCmkDp>GDrG=)v#u!mZ0ilhL);&V#x?xZE0KEbfe5Y%E}aKqGNlF$wTxP&T8`af9?icr%K1GyFM2Zj z2{a$#aO@O&&Ewha$KlZ%$l=);#^KR?l&RaW%a_6Mf5Xoz2mUF?Js96N{H!XGZ?MlP zm2x$_-B8b%g9@KwyX!u{u-zv+(z|eAu zzm)~F2d?3lZV4ACO!?cSSQr>O4}QN1au~ns38av@;K}TU6f$lc9=!pOkm+XdXg%Q3 zD|+=HX!(uHA;Y(=-%1?1BwB8lSb??xNg&@~KEcQGc`<*7JXiwM+3N%)sNO6_%df>e z{M%v#7(F^)wcIYf(fQ*04ah6^Y(ZM$5CMyq!lK8Q**UKl-xc@Bjau2Q@Fg<^s1Tnh*XfdF*5P ztVj%``{QdBkEmz2pMVGBMM&xa1^!-8 z$%mYVx&>dZ1jX5ZRsL4cVUaDj`CCD=@}M2a5_?xf(`TzeIgX+r@py3HAMb^IYHIuqaxvB`H;UEbY;#<(5ZmUzcl#UK^t;WobvJ{=(u}$ z$nb;w3Q`EV`VTF1IA4l@LkEBN<3;(tQFbBQPL@7bKIbSP-5(?g8CYck-Qt;Z>TORyA7d;NXwD06mf%zQSmYpD* z!CrM_JPz{c^k1MOwOz;EL8}EAj=5(rdL*9$AKusp z%81R!H99YF{#e0ZlH7W!B-W$X@qhCpc8}&C>_xVqj*#XFczWvf8v+`;85 zN_)YAf17^>sF%mz`VG9^{;Nl?y8vi&w}xluGta#YN}y$3pp|4bDh993K=l(S+jBS_ zV=-U=RS_U%up+2DwGR)@-IGH z%uPz3zr`0+Q+zwdQ7R8UM8ib|ye#%5=ulB)=Q}WfP8vVvqQVF| zGK>jCFoOsd5P^J_*fCIpu(`itCz>X!}4r#zTrua&igK%&otkG%iBvnjE_7tUx6>5 z6iS}OEXrDksUmpJt!53dZx6mc|bRGxqq63XLnS%D4nt~?0A=~Hp1zb!) z1A3;Q0X^vEIgl7=0LTLc@5J~8UBp4-KjM&69xs5#@6PeJ#DKaHr$Ku}n~zu^4fi89dA7|%UoUUF zCKg<1gv|qWFH}IYrU$?!3g~H|726g)Q#x{>K0 z^t{keP|;4{yim|Q5_Fx=WypD@vzrfeUZ`hhm;h+WU6*i&2xC_; zV@C)hV^=U!M+hTRS1@x&2qSY>FiS@WBTH8>YextpYgaH^M+hTZS1@}=2qSw}Fh@rS zBS%*-XGaJlXIC&+M+hTVS1@-+2qSk_Fi%GaBTrW_Z$}6tZ&xs1M+hTdS1^A^2qS-2 zus}x$qd-@%U`Gg}U{|nEM+l=(SFmtL2%~UUut-M;qexeSFm_T z2%~scutY})qeNG*WJd_2WLL0MM+l=-SFm(P2%~gYuuMk?qfA$@Y)1&AY*(;cM+l=_ zSFn6X2%|h?PX+kQ(;e%pbSMap_P{sucat~&A0r0j5^=Pn@IOi}j?E9ets&vpb zgX$m9{$8Z?!3<6xkf!u!&rVqS01e%H5J(@O^*N~NV;yJ#X(z7q0ZJPO!D-_lByAjo zq>Y1+v~duUHV#74#z9EhILM9^<}T~N9*o|O8RnW0sThzHMws(JB>h2>m|^~IE!fmx zkSubTL;JTL(1uU*0RfLr_Rey6%Lcl;;<$SOXf5P1_YzQB2i(T-IPMO*zmnmYy8%e7 z0wnKoyd9jK85kH4tHBTR%QL_)oZ5|dM z9^LGb|3SkJf5X8c%rKLYVV@342&YYe#13d_2ju>o=KbKc`=GKG-2Mx2;os(7;@f(l zRN1B5y#TaYuGARQB9Cqd4$zjRUfT%}%kIr!WY}i|whWx5J$h}+5HdSKcZTk>RfV=R z5dk)#p}vHngsr*0fU%VQxO)LeokutO{{#VO`aJGl06KKjqqAJ0GrR)4UCKeiqx0PV z2axrB$K4A+p7H1`*YM~J7wGUWX$GBu&f?PPUIS6B-~&<(Yrn(OvjI{<1>2|r_CIL; z0@B3q^yhKu1a0y;E&=w@ac6K&@Hp-aP4UgJ6z_4o861e9_Wto^*tUr7Y7UQs&zU`X zO_^sfGC&XC_2_H{9f#m?ycxWq0-^)7s2-Aunn4>QpiIaN1OtP|@n-n0h~v$m?GPXZ z(V!y@To@Q$f;dRw>CxQ}(g+$IR`uux@2BwSo&a*GN9S~qIiN*he4xpjPOw7Ix-yUB z?J#4JBp~4nn!g8M2h?0I!BCRm+4-m2y`c3#i5qAFxbwT=?bqT6+d=n}{6E}z(8Ka{ zv8rcxj|#}IKHWMueOup_JoN$XCi>?1|9Z=TQZC1C7nOq77hOR&3%-E2LqIou*oT5s z?>A66|5XR0d;q({zT3Y5+5@Dg$eO#m%Kusp=y44Oyv=$5$%+Wqv}$1+=^^l5W-0Yl0C zW6lN);C)@7GXxC}fX?G%Z#h}w2P)t|XY#Q#wwx?61eI`L9;k@Z02Ogy9%dQ0pM)|l z5md&Np_g%H;4%)De~z&;9CK%6IOfj8aLk>V;g~xM!!dVOhGXt*49DEr89bVgbAaZ4 zO0R>=(n6hodo6|gG)GYR=F|Bdo)W<68nhEI7#vMkW-&7Cd!vKg^n}c>fa?3^Iu3>s zM~}|m9^LJrY~^vh4V2(PIRlgg^gX(}LHWv~b0bLDqjNKu_y2%LCpZ^&d-Hf$o+#IX zSH(~Totr@!6TFubMP=DFpKh>}XLldOz;2L2kJgi=+#bgfSr~k=7|1=2-F^ig%|BTn zrx7?FcLNtBj>p^#7#xp-Z;b~z6?$hwfQDnYo5cSEj-752-QEKKPg)-2ZvszEbT@-? zwkN9Rq&&L2L7CSF;yItr%^)7AMiYjzeL6RT@;%HSAT!`T?X|ra2oB$_si5%yP;Ii$ zT@6}FgUdrmee5wK5?bDPbhCFmaDX_F@b~EE-|_!HKZCL(&tY)=?a|E+9=-d(f6#-c z@gYdA@h6BZVFC|8BtR_OG?kHIC+NB}=%r`dVYVXYKG670FDnB}0|VOrO6Yzq56{l? zkbDR#3|K(tH5;DvZGFq%!q3XU(0Yl#g`Jgwp_c`81}cMT&nEZjpet%aR3thtf)-de z|6}y%EKw0CWih<;+S^0(oZ+Pjj+r@E8K%Cx7~T2);Cl(f_nH4eoXi6t5+ug~Vi^9w zB5U}=qxle%hvl`>-Jqdm36IXt9tU45fLtc$nCSyG_0+*v5{9QTPl1eqm}+TP2Vd}a`l#@9o^N~(3OB>!zTGB&Je!~W^XSe|5hw}s>HPRw0G1y;x;a5M zICeYo7`v$O*n)JFzp^Y8D1B-fDN_2t5UF(niXV^ekb@GQ)*(k3N{@g>XDyGGzIpi& zGz`-jqoQE=*0WpY&$q*jr53MM!14ci0w(-_6sAhZ12l1clF_5{#s^RSjXZx!WSjqT zmYwqG{0*)%LARO16qj6n{TQ^-x4T3|0^*YdAIr}r(H@;QUkk#=YoPvd#o`~((2|0s zqe$s(&=j~lEd62n$Fo!B&r4pgpMH28e8B^0#eZ<+KiJa3z|g?p`2T?C{}vTcx^is% z0TSVFwqRmlIQT%^k@J9S>jC~2FYt1m6cr1f&Kea5{*DOH%F_Km{{R2a4qElotMc7f z@sDTo5e1KKUeI7R{CfG5B{E*UB8s3bBElY>Cq8)aZxjV7D82S_8Myo4qM`vh<=bEb zV;gudvgJStXy+`b1ONva`2Ijf21oF%=Dz&yUp#tscdub&c&!hP50B%lpj--44myy# z^BuHd;R#xD)(JU?zY}r;J%-B;!(6rt)n&(6|NsC0A3R`Z;L{CqV0Vs+g%9IW4weQ6 zmrh5HZWk3ERR)F+|2rMQ_nJv`I)bMn6gnM6K(Qj=)5~%cVbg*5UzKsV8vcK20IC|BkH7F$Jnq?B{s1&63ppLN^Fs3j&|x>A?E>Fk z=Xz)!0`G4Ft(P=q0ImE5ji9&~f);cdYJf$-=b3>AQ4B5k1$_)Xz@p$2h`_@rh7lmq z46rEp1S0T2ieUx6V2>fFz2*Tv0`btF(%Ilj`w*xxhP-(I9Nu8v81_TXxHwSy@FnQ3 zHkZzW9=)~`R)I^>-K#()DJW6xt47?PU|R%{-MEU8VP7pcAsmElcysAI2r4K4*L(EZ zdP9`W0x1I>Mh#99&Rrq43{D*(mJ%QqXi2=KB!~rC5pO94Vljhcr9mrdeJy{Kp7-dK z^yu{Y3%-WR0aOJtA7fwyEl+4hxjPA59&~>4===xWU1xX_T+RAJmTnnKYZ=4hD;|vJJs8hvE%f9;cOnCY0(|N+<-~$$qZb6UkLJm;%$l(FHh@e{pbOjnC zhesz!R1kD!9n_c-ke~>o;U$mG>uD1_dP{^DJ$hq=n0zeH6$$!So-We$u)JRC`Enuy z14G&b(45D?2Q1wzjNs$Pp0il9SQdfTf^~lPu{>RT8MNRSrr;jPch)S1AO*icC-Yif zFY)y__=p9n$fMgt(4#vBbhlj$$g?IY9^EF49^Ek@CxL}Q@**mzF7@dA4iNBYJ|Gc!*zgjxzqo7`I7DtOVr1C&7@Qd|f(vJlUfXVn)P9f@=wL;# zIIO(tbw|GOenK#4It`Qwns5B?bm!5)2@q$n1VbH2#pWfgHzMYq$i(t`iO&ernrcKNFOl+usDeH5eMx|aS;QNK4Jl2 zaS-Vv4%(UGA_gLT#0tRTAhJgs)E)9{eg)bu@uzeOXn$cT+WJ%+_IrY^qWXWZ^ucQv zk6v3FS8!PG>jYP&j0_C>EYuMLzFjPG9WL?$T`qEr9WL^MT`qD=9WL@hT`qFW9WL_1 z9?geYJS}gO-T<|WSv@*^t_ye^Zx;ZU?&ud}J1`*TI|E!h&p9^#WaMuH?f&uYJnGqb z27FQ7ca$SsN+f+cYXy$Ga)5@NK#es428Lp-my;M681~D;D}2bkE0`*aa(yk|@V9|3 ziSn_0T^8@z>!b3)!}4ZXXy+}^ym0HKQg84K39SBevHVnQ>Cs)x;bD2K$iT<)UkOj= z_5X)DLqTQpUjZM>$Hkf+-Nqi4_sWDkEI*d4R z;THh!>;;Xvd-b{;7x3!!IS&?U2A%r@x*_`R3QovaC@fP z^(RLDxGvc76gKVeZlVlc$))@Z{@a zAI)oCy;IJEa)jYYBr646PJvdnp8_ptKQF*9=yP6yU%=%QX!ZLk(8Blgph?2>4j?hm zD*02O1@h+uKcNsGxcqet3kF9w=r(ydpKfv2UXTBv-OG;6KbT5|9l-|=8XkBFiN$Eg zxWm4hCt#wl`O+r%fVPwzWAe59P?G1_&2tEJV5;VKkMH+AG(URqJDvCLmigq}T?0Cw z;g*NyCy(#9JTyOh@H^e|?fmRvdAf+%v-7ZbH_I(h%Tn_rXlK3V2M>OygC3nfK_+~^ z>7n`EgWu_=hvo6&$)3G#jGoP4+e#;a_CK~{fu{VsSq_2cYeCj}YJTwU=K18q?{pm9 zDL$45J^7uEfjof-RM2?wx5NDWEu4%D49A!mjyW?j9CK!3IOYsuvoIWUW@R|$%*Jrc znVsR7GY7*lXHJG=&Rh(~oVgi}IrA_abLM3@=FG=%%$c9zn6m)GF=s)BW6nYh$DD;3 zjya1k9CH?BIOZ(IaLiep;h3`o!!c(`hGWiB49A?M8IC#2FdTE1WjN+6$8gM9p5d6Y z0>d$9MTTR}N({%Gl^KpXt1ujMR%JNmtj2K6S)JjSvj)R4XHAA<&RPt|oV6K_IqNVS zbJk@z=B&qX%vqlSH1v4P*^uFwvk}8FXJdwA&L#}UoJ|>yIh!#Yb2eu<=4`=m%-NFR zn6nkbF=uOrW6m}V$DC~$jyc;g9CNm3@Hp~=kbdPI1l*Z-jK_2{nWFoYaG=FwfPfM6OxnWGUvaRk6JHBx=( z*m=$qHqMQFKaDP^U;y3Uf^t6%=y;%(si1jx(B(9ep1nT04B&${>p^W}(7DJjeJo#= zm4KFOobvdNd?X~&o_Wyu`k3cI@;BLl+DM@C3v>=Lc)mH2P4KKm_N1*Wl zQSf+xC}>3or~nrLABZdp9*z(Nt?3W|ZR!yKABZdp9*z(Nt?Cc}ZR-&LABZdp9*z(N zt?Li~ZR`<%9te7zrF6anXj7BBNAn?p&etd#dq0EEB|=)O4=I271zbcy`$>I78TbWV z1VBqZ1i;1m|6`?(JS@-hxAy$|{~vrdCa6aUzF*1}w9poeZJR!j0+i`yW7El|Pz|_GpcMgVQ z?wkzA+_@NzxpOldbLU|==FZD-%$<+nm^(iM=s2`v?t%=*+=Up9xeGHKa~EMa<}S)` z%w3G(n7cT`F?R`uWA2g+$K0hDj=4)S9CMdpIOZ>CsGaPeQVL0Zl%5cnGjp3NPI>Rw{4TfXxnheL>wHS`MYcm{k*I_v3uFG)DU60|I zyFPfj`>D{G8}U^V>sq+&T!1#g5j9ECBrdyD~4n4)(pqo zZ5WQZ+cF$;w_`ZwZqER!RoxvtKy7(gsrUoAR0M};1X9-%9KYc3?zV>(bRON+5(uUS zlnE~Wz#$B(b4G6cLu|c+eCQr%JSf<+^PdMij6J*EG(cl!cAnjF531>J-VxrY9#@fX!BtUAIsmR*FBHBfmcaDcE-WWk7Mo`3`lW2A;6<~Kd4Q~P%7oo zydRtfN(DSRw}ZqyI;VpKKncfI(*jiLihiqMWZ3sd9eGw1;WkkF7vvwukl+B1Zg+)d z3kLp{6wt_Z=NGUS-6cRCGwR}SwBk`I)dF`kkhQxoFn~^_Qw8ne-Nqx}XvHG}UX=C9 zx3^9LyaK%SWQix@ELbkke(qx)mgkC1JiA#wSO}DU0ADlOc^U3s(D|?Y+hi;ptz>LG zdg~cW-n~BK*~$L$AgEYAei+nTKz0FxV?&J$$fwcZ`_HP876O8f-7f*@0v)?A;@Qh1 z<6(KCxER#%10A{luq*>qwV)lhF913}pQl3ve2xn2{w4k<9YzL*G;scc$%Cp69(Z-a z1FueakgAi@r59g*0@r3YAxi)QAAk<cj?Aogkfy;{iIa zV1eVe1I#7npo4KbQSYPp1gTEI`a$&vj}6KRIUfIyfzF#g&EE>TKmv4w0O(|N@Msm} zvQW=%Hwjo366Y8Xnz?T^1;w1GO)VqCKGd0egnt8??HQmmfngBky!e!(-w!^N)^nAB z4({v~?VgA^h878t>H$e%jG@^;BA@L1hfXF=q#cW6lW-$DA`5U<(>Nx?NNZJUW}f2W@tPwlsD7 zfM&0{L5FdAbb{BScpPsA6;+@?agXE8V52}e1boeV++oQ5?t{ra9-ZbM-EANzgNj0? z{|}G~V^H}?P#$z(a|6hqIP?>c5BBJu4-UT8+a;o)^)lVeph?mI4Ug_<4$z#yJLK94 z5q{m~p!<{AAeWTGPEfuNatA|qHKaAxdVqiG0q_}&(9j3@2Qq&TmWl+e#|!r8W(6%j zXs}2ub=jP_6EuqD(JOkUj1h7kTFdPcL;h_t99A-dpnb9>?-6Rg`hxCP200s9-ta*5 z;SG$@hdsJMqhAag7~7aZj)eE|Acx*U9BKh;e6oHPf+|IEKi%@0XsBX+oRc*9hB`r#{k&!gIR_i&9>rTmWfBRtvr}z zZg}9Z2jtvzk4}pXj35pu8sHpI*#PH&4vvO%K&w3=9E5*7AUD{TsC!s~W3$BA!_pRH zM2VA!r7cK%NuYWxn!;_B9KbgxCUS0zg553?SYREP(u(-#|eGqYwQI0!7 zL^3_!P)82;}FF#ugwV%QO4zznKqJuN?#UiCQ6Dgz2~1_p)=jE8+XuYoV6>J57U zI(YNoOIDBn2OT?4Lk^kx1)AnQ`8w0PH{?WtPv?CP&GWGHKU}y##yF>*v!{gDrMg^1;J$mP;fR2)MHGB(c?;URe^EpAO z4YKsP+rp!_MFn&&7-$QMPv<|M&PO{zdD644WOf+|8pYT%b=pi=m_ zybi?`J|M?=F!rc`tOj`s6p>g1N!Vj2I6FBofCrMGi{L;p!vI=qhaT zwyCp61-v4TfBivFuz|#U`PYB-1RWU7z>oq@R!QiA2wJ&ETp)tlN3iiTs)e67uJ8l7 z3lx4JTS30W8Gf8TmM{35vOz;L-LO#e>D;0MT6$WFBlISNb09eM!1i?ZsDN85(9i>m zb+^Dmv;`80olt?}kTl3309vN`ACv{bZtI-`&H$jS3Cc`9y=%Z(&=tJChfsKdu8rxu z1WiU^3q@TD?vYP3872```SHDGW1@ULH^0tsjE zS}jnMPuPcl{SQyjdG+Ab^KvS-i9e54(4`ch)SJScTe^WaM^kM2F-sP{Pd zp39?qjS46ycpQAo<wAkLF0;(85d`R(KqEg|}8KP3))9Ip;0ouNo09r#A0V%7%!QAPh65!LB zqv8O%?AHQx&bt9bmI0gzK?~48ixE9Kb5tat5}-1m(?vx9$_1Br;PovwDjvsOR6Iaw z&ZAe;>Af4%!B&!U3{~4V*>zxBGxJyQr`od?3Ji0+L)jpanrUr-!wV zNzmR4>Z_E#)oZ2rOMA$ii{`$Z3KA5acE;n8>mqy`+G=>9|Jqq~owyhpF?T4ivGFv((M z*mp`BW$Y0nypFSjq6D!%oRInG?m_3Hv=>3wcX)PQ@c?bT_zz1-pj-%PgzX1)8^Gb$ z>7pXj{DZNM)z$FZYf}_)1<34k^ADz4859W>SHo}3KNubP=O6QI{>F@ubKDE^QuB}h z{4Mf~3=ExzJCB1c0p)mMkN~6`4&s8(1nG zR6;<~4^(HVFIZ?Fg99{ggLZs*cAI;2KJw`G0WDU1?%Vmpr`tzG0BQ(-3uq?KvGe|J zP;hkK1?vaPxpe-9x%f2~SQczaCnQ{4psOcAhkyx8aO$qvA_Lat`Ttz$N2Ex!hD2g1 z=-T+kBcP~8DwiQ~@Oq6$Z;pya=Y5aPcVIIbQdA87Hl(OHd4WgeZ711Qp(e{hv?dw|y7 zaxj!gy>@{zORYgNrKSg82&6Ut;4IQ{Xn9+r4lXbDgLcz_4QoA6nhqMx1230laM;bj zz~JD)?{ot!3A4$wlifq}hG!?6NAnR0@U%rNXjFH-JUI7E7O6VBQgs~uv`bZ zNbpEL;n8bb1(EjyX{txswgW4FTMv|Qfv(tTJy4zKB6Ledw<%!Zy zhdWPrblM#91eI9^;PQHePl_IMcVIZ??#OV=-HG9tyEEvrDu!e3t_;WA-58F!yE7bf z_h2~Y?#Xb>-HYLvyEnrzcOQmh?!FAi-2E7ix%)F5a}QuR<{rp!%sq(Vn0qk8G4~LL zWA330$K1mhj=6_391ig4_74Dc7uh1fvFg!ldk;LpB-)sQv84>le#(GmTTm`y0NpMK z9v}o~8888DOYyHi*v$)S<``b``2G>~Iu8d1vTyBuELfYu9uMLL;}J41cq4E2aJ#2?O3Z#WCA;4g8a zbkP}T039U?QRgpE+Hat7K2OkGH2g|LP(j!N?v{cb?bzwc;CS2>>~7EFu3&e29(M)1 z+wr(7*x{bNt{{g8IUaKrU~oL!sh zvLHeZM94F|=0}TA*vUGe6aX5}W&pK#1a^bEn)^Tm*u|h)Rl&pdKR*KlfBSY&W2~`8 zMFPYv7XhnBSK3{pBH+Pz94rhvU*IR_N2K!wKpH(X55kVWwesj~F<|)c|35r_3Dg&4 z@4p2dae6q7zaBix=b|ET4AlJub+|iQAR{2hA%i_2kAucb!5gSLTU0>HpgnrGsDQSZ z!uH94j)%+yZJ_HdQHcQ!13@HHR4iW0d4M*7LuQbDI^V0rsQvln8Cq_a%;DcABLJSi z0-Yy=EDJgx&_yMO0do9py^D$iC~gBlCC_mel?V{+`0W@^NzgGDl^D$fMUqrNHC31Gtz%OLsn< zk9|6ygIaJ7;3VeR4T=X)@eMjL(z9Df#iv*0fM0LT(;Xh&Q@|k)8tVX!Q+3Y)k48Io zxf*o1sPOxALK?tMoiR@@bhW5_VPIfz>Tr2_rK?2+bf_PQeYLAaPeUiHXxaI@RHXv8w(#Q$ifniwJ=ip8W zN(eDDAOB-`p!q+0x$aKT!I%7te-gt0}!AxXif0= zf82$C8@nUuhCavd%|BR+-hyuEd*RsdL%XEVvEhd*n#dR{K-{3)z|Vemf-W? z-*;f2J}Ad(9`msLSbox{H-_WF>qF4}d7Zxyp~v4A4!R9&C+NtuUfV?i;H0o30+bZ= zKqH^cu%rN)ufZ}t460)|KrK^`Ufae9kbZ07!m z{N~Yl%ct`rSOhBl54z1AWTSvb^AQDTQ7{2ILJw~rfy>JV+vlJFDk=8p<^|R6;B#AQ z*+4UVzo82{z=j*1oX}vy4Y|r0pc)E#_KR)kC&fVLAM9gSTTYQe}O7C zdU*#b$^5oUDkZ~@(z<08xiVljclm_aO% z+gUs;FP2_>`Hh8vVdsC)WQOKNuzSG`#>QX&{(~CK7eP1bfZQzW(aXZ^X?dK#8FZ11 zM=vW_i{)YdX3!NnhTp)+K=Zl><0r=*Ag!L77r?F;;NQk#?AXC#?(zQ^=z7NwpaZM; zn<`n5+zXcH-{xWra<4ffhy`-5Imo@nAorSs*Kl}Pek{HC(jMd@&@DN(pxb;b@AJ2r zfJB;qD)2W6fUe3p;L&>0hu{BzcP|UON3RIChvkK00nc6*eow|5o|Xsrn_htez4IjG zCN{?hpljU@zGC(1bz<~r{*l1n47!BQ@c&Ctbnv%b0G(0+3ys4dPV-MD@TMtnedWRL zbI^nFg5xew)O%_kg51zn0afS0@AJ{K*Tww5N3RXHhvkoAQIB31j!qpq{9Qx&SRi!;XMBzbM5>H+NK3=Qv3!TCc69me+C9m&CA}sCi0$)w|zR#`)GcL zUg-*2Br5z7bO?hmBfp@J7$d)+ix`OSB76}n`Vb`g5F~ohqxlf%ibETAVjF8-C*#U@_(w@G%D6SH@xvx(~}7w1CDKbl|2j__{K41+XY+35_x6$W7w_ z&{bpR4q#ExA{t}Rp_|6w>&na%z@i0^qau#8lr8|Tr#1CxJ|@t4LM4Ia!GRa7{|@kP z`_cTI+2i|tegPL_&=MSDu#w=~%giBXMH~mMroG7D@(gr;PWhkz|9hPnp;tMB_QD)8 z{O{4rV$Cn$!U(#ZhVg@EuZcbA_zKVsHHM(O%NRj-mob9wE;9t(U1oRyq!x5{86)WK zGDFbaWrm=;%NRj-moZKN=>^?gW(c}o8ggIGJdf}9!OpiwaryCKx-|)OS+x}C+Bpf(&2bVRJVEys{XYb{H0~sSi!A7L@Q3nf7j7`{Z*$@P=h)$b zxFF{3OVFBW@Kv-w4gd2CfPCp=4UQjsQ0Ur&;>Q{kKi1&*u?NSGJt%&xLGfb^jvsq) z{Mduy#~Ktr*5LTD2gi?nfk*TE2JjWN3qV`NRY1#~J-^@J7jUr##fCK~HtfN%VGq0g z^Rb8J$CA*OOTf3`90FBIpxw%n9*n2>1zdzdx8Z;iyr7Rb_%=21hrX7FO4NKb4-(`JPVI*_GSz2QjX>d4hGO6e(2+k9#H)r-5ub?7@htSpZW709Mbp;4)}fMuXk5K zv5^5f|Iy6=n%)H24{pBwuV(;RiG`0ezSI0h0yHNr;L&;2v-7)W=imLH)tTUm7QEo$ zuuJDpkIRo8_kdb-oi9BvKk>1A?8)zT$H(%455M~ZU&g24rV^;?_JAJF4w+jAZ7vlA z?LPJgUG4o2+QtCSQ+aki0FNWw^XdEqwhC0Dwccc4U_fXUhn)Y=Eu!MlYuoORm}uyB zQQ-hP>VZe+U61c~Jrs|6SnH_pH-WY$dw>_7F*GnRcxb*OX0F+z^S$Avok8H$FOa>m z9^gqm@OrfWXCY0OP7SbyZ+#e_A{+?v+c7^-#}V!~(AWsbPl!bWAdj^)g4(SAPkXf9 z0N<=Gfz(U&=(S~G11B$LQ1a^4XJB|;=Fw|=%MZ!JAu1dm-8`Uh_~r)=OV7?1@ZhvP z!V1=}>(9uruO6h|%%j(KJw)(0$WRvp28P#)9=)~(NTJwk+XGP&0Mgf~k31WMdjCiT zcvt;*PjJYBQh^WX_$|-~4?A>Z+qd;?35Vx#S5O*Y0Hr1aP}^n-cr4?G$Hf;OJ42zs zL-C+b=MN9f6COK_p}?c_n1|vykAp9mJQPoWE{^Iv=yC8RiwEODj~)C_;GuZJa}OgF z`0%fP;Cb+kg=epe_K zRKUaI$6ZuZK(0ORqM`sApX{~N8N< z0?!u13^P3GY5A^H>E$%gSt;Q5C-|f+P|rZZqt`^!v$K@J)AC(OrDO9SM*jA6kVCpd zR4lxDO^kdL|9N!2@=^Tdq4{Y)$VDFf&cA%RT~r)=ERXX~Kg1QH!e64`V|l#H8gy1m ziHZj31`(bA|Npj*1Fs!q&s5H$_DO6od}o@B>Dl?h zxAP%9L5Yqapw|26RBTEO=2cntQu_R0KRN&y|#c{A1z6_z4t3o##NIrFpHG z$?zNKTzUr&%YXdS4|Bz+@R#U%SpI{?dYL1rFA}1n;n4Dpzts_R+fE>|@u2b$5?)47 z9mV_}okj>HX%jq{eN-UDqQf>&kbzD5{_p?)*X)J|KuJymR4!^gniZ7FKtWY1?8985 zA_2~utp`dbzl;J+w)EN-1u`;#BLYl7_nQPD7nA>pDJHR$kJ=C)YuzjuBojzsKomYEABv3N!E`L{Xo@ox*_ z?+j5%=yXwu==4zu=qynI*A|^QDi)nFDh4i{IVu`1ohd2`E}*NCTtF3^3+VJO7tkqM zy`n!nK>j}tYLOIl`>5o&bi1fzz~T+H5CHoJJ-r(q0PVPz^yu~b@6q@ZG?-q_18K8u zU<3sSy88WA46s9j!R8T@LqYdsgDMbEc@G{>@$CHO+4&z@#DO*`i6EMGp!*7;iwk?5 z|9i9^=5Ga^iRantBLCmx`)v=!!>Cq*<_j7y*6A7k_vpO03pBR6lL@T>RiXnQx|i|j zy!pX{{~#~Obsmg2Jr2GU@v!CvC7)t#a6=oiR;HVy`6o}Qmf-=2m`AVeHXr1&%cIve zSqN1?l+6Rw{<`ne`3<&86C7TM^c3LH>;B)P^*Dd)IZz|4^Q%X1+<%YOd;G1JL5o2; z|M~RR*fRKZ{`cs-1}-7N4Yqk;xg#E}hfCaj7$1WhnRh)q-}-7kEz$G=P4GfiGJ#u) z;B)GmZ9(g-7)rQ3zu*1f!>9}Lt1shoPsVq?n%_$WUfcR~K85p3^g+`eTA-VtK{Fmc zosg-u<{$q{^5DV7?fL!w2Omc8@&%917ocQEx4^QCX+gV*8+iKAeNUp}2bQKmrBA!a>y z!!revHi7i?R$4)RT602AYqsz}!LdV~F z2b4y8W0?PgF2Dr!Y+i#jh$Cw_3SEQl@%^rk;$LENsRy`M0?DRA=t1X1RM17BEF0hO1as1xY?-Ta@aKH`{*3i91K;PS*H`S&pw8(!#olf%tFm}}lN)Tr<> zl&~8@CTkmNRQMQ5xWF6f!S*!NsPKaXKr>cg0q}}wfoSmhG0=Ur9*u86eS6Q&Z-(EX z&IK1IQy3T+I*)pEK7%eLG`tO7I(*yX`(+RA7?lM67SJMekLKV1`CCBu$-%O4>$g&r z0v@(m!K2shzenpa{?^Ih#045^{C>|v@t9|)nc;22|KN~;Y~Aa8;cAHJ0(P|;wbg(~ii0G14ME4^9|Vos zcpg6hqQK$e(QA9o4LJ$$%R|>&26%R!1CL5Lc3uG0pBBx3|Cg#DCwcH8o(z~3lTYVA zNO}h?bAL^|KEwZTouCxu3!TmY)t1da{+FtQ9qa-sD{Kp#7#R$2gWBt#d^&$ZJp@ar z;J5~@es_$I1?}Gjmk*91!SFbToa_L}{E*c&pcWI@c+ftJ<1Q+oZD#*Hj=QKp?=5gq z2?5n9$6ZunKs0D6LISS!ObMX%3*@YLI0jm0am+;}7i2&lh{y*orSbq<3G2RqTm@fR z6X4Maxs1(mJ7dd%k^o=JXXQnp{$qeg=i}F+kn$2z1cANRa-c*9JeUC*#__N`Sn?RO zKc^71V$AX&e>><{A0Nwy~>dZ zJy22Y*zM2K`19PaxBvKCRxvOzH2ysQ>+Qc%XV30<4d3oGkN+p&^;fqyiwEP)W@}0Q zmL$-$LZ`bzZ@_=hS^KA34|HCrzyC7z|9_~%LsqjpcDnO8cDu9Kf*e=kVGD8>e=BGY0_fWF*VYIZ zLi?*Q_c8Lf+yO7P$8g_K&`fXhVHwZPcny!v8{HhOC;3}IXLp0k@8+M zZ*~c`Tq=?F=sah5AZ@GF}wsigWiDwG^J^Iiod<)|Ns9DHUc@N?;2_Z7&A+sH`E9) zC6zvCs1aaJF1^`MBfyeVda0pCfHkr7bVH2*TVCmrh8h9(^wPZzH3A&*rP~^61UQRI z*EiG%aFvv~iJ;@x!2erY>i05I+jaXYO+50rBIYe3mX}UJxIgg*seRSi7A0K>ReQ zJX@DDKZu_N<+FD=3xN1}P(DYOvml6{59M=qISYaKpu2P&J6u$_x}1eU{6eTacbBsW zh!2{S1j+MsIg5h$#ZYv9$c@k^n6{vDu&Y%jB!prH&7)b3yjSdexX z%Xlze^Xx3+00-)3aG)B1!cxGaH`oHifCMV2uJr6g3shE6MnwcFJD7_IRBk9A7O0?m zYeAlX1uAHd4u}s6RB@1LDI16|}7p#D@i{B2+&tP?ey3SfDCH z`LIA$f%0L2stV=90#yylhXv{_)Ihxenzujj667nx11}FTF)-`^h0;sVqB;m`9Y_q+ zI(!K_Q5rl&^l}zR4Ah?nAGojs%xVLPf!5N#1f6xi1Iz-&_zqC(0X!EAVS!TN4$!jm zm!MW5gax_~VF&2EiI;5*3=9yK8OS`)vg+5RJ3!P+(7{nVKwIlyr+}%KA|Mr@r6jL| zcYvsupvmtY+zbp1ubsfu%TJ694B$I|UmJp{mk&V#pbq|Pg&iR35J8?9uDO@c~?(J04?EVQ>WBkO?B0z-(qP$pR)>!6X})WM}YfJ_5Pl<~V59LeKDk z<1rQ%2GC)%mIq5ezm^4EaO2s_V&Y@@piID{`4~Uwyh|VGb}o-(XB*E>Hx0uBj?MKP zO#D+1fX=A)=ys8i@a%LG@a(RW@M!(d-?9Ld0J_;hop=do(;Xz|*&U`}coKAAyVPqv z=#d_9u@V_b`v`P)OUvyNz783F@TQYfrEfvUPcWVbE&R|t*ZBc-7cGB_GHB)i6iOx_ zM&}98L3E54z{`$*uooG7Fn;vVya=j)iCS-bkfRiI-w$MV8~MhOvUG4&o9d0I$UG9R8 z9d4$MUG74T9d2fhUGBn;9d721UG5@|9c~tmUGAce9d4G6UG8Fz9d1^RUGCzJ9d6c+ zUG5T&9d0&`UG9>O9d5RcUG7qj9d34xUGCD39d7oHUG6fD9c~VeUGB1u9d3?}UG8#@ z9d1sJUGDOZ9d6E$QBTlt7HBU7=>7rQlctQ2YtcaI*P-FRK4>Q%ti1&4{joRLgT)LF z97dj>YJ&;7b*`b z*g$;HnaUs<)UO87pbHj2H0UUD5Dn_3gJ@880@0w83P3byauGyN2bl-n>yuuoaX?8*5ZJKpPdxg*-Z+qbuyTQNgmkAq|vZt9OEQ zA#HE4hHr0xFM=kjyg2|VZ%9e6p#2R;!TTEoKpi{q_68Oe&;%TK4*=u<0Z?Zd6eyr& zh!vn|Tn%stv>Ygj2F=4&fTra%UL&ozPMd%uA ziXd`i%gGX1{%t(Mi2H8$x`O5)byPfB-z9?(W4tITLNC) z4mu>PL=~wU45}ua;bU*y9^Y?&@L&Y3ykLM%27(3-tsyD6RMe&OgGb{LP(lagnOI1d z7wk*e=ufXLiy>%e477$FWp%)^r=a94s%D610C$21==?JW3HW_op!>oYz!z3>gR&t= zz8iTH97O)WpXMLz<$NA9kk)O34yuwhVnkNVFV6s8j)FAFfy4yY=a8X0cyhwn-w9cb zD&g7r4K!g`q5|ngwjL;z1B{Vqkq>|ANiy{D&|N>;nY1^+2f@n&Bl%NM>Jr z3^sczn%N$`w%Z{xD-9SK_W6Qsg^!ZLgBNrj*&7Lnm7vlR>@I@-iG`S~h-N3)Kj86G z5AY^(P-yH2nd;FA*~j70`3%g5*}~&tDWg)V48FPr8dOXWqmS9429-yz?TbfXkN(wX zWY`yu!#n))nByzp)ytsE+%Ps+3c&Ig_K|qT13tYh4W5=a_`$akg31(FVk?m~ybaUb z&ER3}q9RZl1s>@GC${by6&{~X&?;!KPeH4QN;o_$Z}3k!{2HOESkIrl0LJ}$zMfl|z zz~_T>UItyk1G@S_^Hxy`XeD_!yNBh6QX#Ki7GuzwnHwJbt|vS?`Cs#R_3{||Fdp!* zJXjj$(HRc9I=(~;G#CP!9)l$$P>~soy~u=+gRb@HJT;y|xFnLFE9b2=ztY29ylZ_*fgG2!(|QI1mtFj?_L0aP2(n(s{J= zH0VAi@B+I(;D~kXJl1-kqLRNA)Gh#x<+p+s7d8L=&)<55fq}uX`S1S{dBkZJE}iee z$4-Ft!p>$uWGj!(!_B{$YXqTXV6XH4=HJYnhwI;iE4qK6d!N8ML7gzjY7ocffB#EG z!GhfepexLD85yAEU-R$(CG1d>K+a%?9t8n*69>$4P?ZD@cKAId(3ud>nGRrc5k~O0 zfEFwvEbn{|UMvk!^&U)t4Cim<{{R2~OI5VtL>C4INcqxRqQbKa)Qbk|03`=r&}`0O za2^zhhD=0t8^F$5lm=d1u7!@9vO0bpP2H+wN zX2D~RUR!gJ1(0+EQ_3&T(EOhXRByt^S0Us7(EBeXJUhR8bjN#mfX+si1f43VO*EC~iJ7<%f{ovz{7{DjH#;v1jtYzfa^R~L^?XNm4?14rdt1rO$I4cG2c z6;H-@`wbWv7~nHdpqY-&;~wB?4a1YJ;Iq44`%XYHtysdNJKMms*DU~KqNj2m*f`(r zJPl9Aw>XV^1vL(`LBzA$-2l2J9W>$IDh;~Tt25rgvoqcTGCU#m25^H1v@=Tpw8E1Gw8B%u6S_*V^+1UPXk{O$;lkk2d?W*@o$Ui^ z_<@%734pp2ETHa$1ZZwc3lYg4j6NzH-L(upo!=nq_k590p)6ernvoLlX#OcvboHBy ziUecHIZ(pk=oV;x^sn(3XcnY&Pjdwid+D~9761SLpAgUpx|@Na@jn{_17p1bI7c-9 zXD?9!O|d68AN$q(kGy`ATB$I zs|_AwZ2rewa<};(N2wurcoBSzOVdqorFlr5kzwC?69$IY8Xmp2xe&o?Ai*mjL1B+x z+X#qY4oL8X38+zv*}R0+|2z60Tl9gD$Me+elwT1`(-V=~RWj!xH^t3$4-v%B?2L}f1GCt5iDEN4D$c2=i z-Jk(EK9Al2M$gVL(DiEvK$r0y>VTp?K}vs%sqN-J0McKK~fk8x@SWq*MTH4 z4|Mm1$Zi73A|L1usjtz?FIw}Vhr@ducL$B=Gay}$3SO=4aoim;Uw_;kRNI5(EkH%2 z$8mSiK2i`LI>YY{K2E{oxO)OrJ_AaFP9JCRINlB#{elR!gXZF)Oz>b9sIWcW4m#5g zDhfJ40?GspT|k+j<8Yx&&~`{D6C5QF6F{d;LPbHRBS4v;<1?X5&{3#RCTL$Gl*s^U z8A40|ZFh!>g4Vc0nV@4Op-j+8lTapTo(RfJK$sALULLX27;M@U`8OA z0SM*<1hWIdY(OwUTScKR16R@z_ijKaSb<Mu3LuyP2&M;u>40Eb zAea>hW&whkfnX*emyKrq282p~S*fDrwFV7@>wA0U`F5KIYh z0|lIiV3+%P9B=19h%z9UkORuVYAq0=1_-7Gf|-F}CLov*2xb6+IRU}!KrkB+%nAe( z+=YVr7$Ld>!CZh~K0q*UAea{r%o7ME2WY_s#9Rgh^9Mq~2L#gqp+Ez{R6sB#5X=Y! zGXTN#KrkH;%mxIr0>LamFf$O$6$s`61ak(0IRU}EfMA|LFb^P@;AJKd&;LM(en2o^ zAeavjOa;(l6o@tn1XBRPONNU_L-FZy=Z#5KIBkQXGh390(=@g82iX)&e1FfM9AMmaFcT2W2n2Hmf;j=f>_9LZ5X=JzCV2fC#OWIlqAL*07YOD91oH-hc>%!` z01q^S+a(+bCTRT)w2$)xq1FPSzyQJ2Krj^$%mf580>KPGFg*~=4g|9S!K^?q3lPi= z2<8d|a{+=m1Hrt3U|v8lPav2F5KIQp?ixs-{y>O+Krmk*m>LMR3J9hIf+>Jt1|XOo z2&MyqX@Ou?AeaRRW(IuxOfnaVxFh3xeFA&TJ2<8n0 zQ$h%oM!;!D0Kw!yFc}a`2L#gs!8AZHH4w}U1Tz7_j6g605X=b(W(R`VfM8Z2m^%>6 z4G8861akp``2fMZfnZ)hFi#+u9H6-wNZMgQFn=Hvd_XV_5DGL9Oa%l}0>O+xFar=w z4+PTz!E8V31oHrbxdXxcfna_>Fkc{;4-iZR z5qR2>KrjUmOb!Io1Hp7aFf9;F0|c`G!OTD~6A;V@1ak(0IRU}!KrkB+%mWDK4g_-p zg1G|0e1Tv-KrnA0m=_RC0q{YJ;5@{EU@{<>KM-my5TXVMrUrtkfM6ydm=OqO0D|d( zV0Ivw4G3lhf?0rIZa^?sAeajf%ozyg4FvN7f_VbLJb+*_h{4mt4}|Ck1oH)gsew?d zfM7}>m;wl90D|d(U^*a}76@hqf?0rIW+0de2<8F=a|VJr0m1A*Fi#+u2N2912<8R^ z^8ONMVBSD5CBQdrg42!wg2{nkG9Z`^2&M&sX@FpAAeb2lW&(m4fnWw8m=h4p z4g|9S!K^?qcOaM>5X=<_<^lxs0fKo0!MuQAo_9LZ5X=e$vjD-|fMBjbFc%=0GZ4%h2<8O@^8|u<0KsIChKIus zgy;tZ^96#bfl#Y}U`imE0tjXRg6V-^Iv|)92xbL>S%6?>AeadV<^lwB27);O!R$aV zPav2F5X>D2<^}}w1A_Si!F+&V-as%VpqK4>9B&suFgXxR1_aXq!L&dy4G>HX1TzD{ zOh7Or5X=Asa{_|dfnYWum=y@-4g_-pg1G|0T!3IcKrnA0m=_St69^^;c&$IA{6#Q- zAQXH+Fbxn2G!RS$1XBXRj6g605KIpQ(*eP3Krky1%mM^61HoK@U@kx~XCRmp5X=h* z<_QGz0D`##!Tf<>en2o^AeavjOa(c3ev?2j1rSUQ1k(e-bU-jI5KIFEvjD-&Krj;! z%m@T?27);O!R$aV8xYI`2<8q1a|4380>ONNU_L-FZy=Z#5KIB^9pT`#!+~HjAecW8 zYAq0=1_-7Gf~kODCLov*2xb6+>49K&AeapZW(9&-fM9MwFjpX$3lPj12<8n0^8$i- z0>M0hV1h1P0;LF#XcmWJJ%oGqz2?SFB!3;n!JrGO>1k(b+tUxde z5X=k&GXcR|fMCu*Fef0G9SG(L1oHrbxdXx6fM9+=Fkc{;4-m{72&RN0D8#_wAb?LLX27;M@U`8OA0SM*<1hWIdY(Ow85X>D2<^}|F1%kN%!F+&V z-as%fAebi*Ob#V@I4~fXKM)E&AeaUS1sVvZ0)i=lU`8OA0SKlCg6V)@HXxW42xb9- znSo%gKrj~|m@^Q}2?*u|1oH%fc>uxOfnfeXFh3xeFA&TJ2&RHEJj^5zOaTOw1Htq_ zFdYy~3k1^u!7M;9GZ4%K1TzA`oPl6YKrlNHOwdKaAZL0UZ$E$#-GN|kKrmMzm@g2_ z2MFd31oHxdDF8k?7MzDT5KIOH^9Mq$1wzyS!PG!76%fn>1TzA`3_vhF5X=q)vjM@Z zKrjms%nbme_2?X;1g1H01+<;(yKrmk* zm=6%l8wjR^8Ypps!%P6dO+x zFar=w4+PTz!E8V31oHrbxdXxcfna_>Fkc{; z51>q>CB)G47CpM-B^q{50-Y#QqT|zDuK+qvQp2O$*}}ux*`Soi1G)hVB;wO);n946 z!=uyL;x(r$=z3+4s7H6PhKJ?{kAp9mI}brmzIQeJ20H|<^*{-WOLqYW$Xr&BW@n2Z zE}b91hyEcs2E4z;quX7gyP@YF1N6Lk#Q9d|JwRu-T>@|0^5A#90OB&9D3(X;TVDN} zfdO=l(og6vt(Ty?%)n=t{_p_Zf$^WSNZPa4{l6#Z5Kqt^DbHRX@&BMx#J}GFoeSRh zpMimip>m_=4qipl9!n1H3E@o{a}M1UMLcI*<8u{sgZ# z_UJt9+5DfgxaMUuXjq4T?}c8kf1vZoFTVp{Mtu2s^E2k}*A;(&PT=chndZ@ans+yk8t9x6M~_~|{~n#p9^Edd1w6WA zPD}7hFnD*ns0ny7wh7!|U;x=&#N+w@yr<%Q{?;at6To}OI6#|EKnEj$Pd~f|+Cd3j zv)*!`gw>;)`}I=8+aS%whhLusouK#~y6Y3-sa{)6$f2FlzZn?z%>-@lLR@*)Ys&+X z4ExQ%;JCw#fq`Kk=)4#Ys12Z7fPaB^gRK0;z_8Dgfq}sXand4ezZ_yePJl;m=6{dY zm;9}uMa-U^XTTe7**zdTIrv*=F)}cCc3$=9^V)+Ey#&YhPQnzA9(UR-SJ?& z>|^=5SQ(KZF8%>sdj#4@>(luVmMB0gw!!=6AbT}oNgH&K78l5hZZVHuum2vc2l-n; zOTImNO_)HNQWf8OYX0$P{qMu?^4yd0i)ZT_{#IR(`qnf2t(J@o4BovwIv$n>`I{U; zqMZjk8E^Q2&Y|-KU#j)gL-VRnXRd%prz?X;XDnzJKYxoCBLl+*M#r``2PPJVmIEa` zp1u1(OmOIXcJ~P|urPQu{si4Yz~5{I+Ht_Y_pnEAAfspJG_YK!uY_lJ7>7rv&MC)Z zZ4#jMx1Rso6c|_-JiGf0K)M-kdUk?Yp54oG~D~ zBSG71AyQ94Qh5weYdv~x8GnKk9O$ybeN~`aV~~?;4@A=^aB>BO=|0e4J~*rq`>zn? z%^A?W+@0V9SexrO7$Aq+c=m2*xB*JY-yyrRz`DVicqS7AgHN{uhc750O$O~rYW~4o zrtZ<}t>D!gazMbt@)UpD8U_XiuU?(qG_QGdUiA2W z(TDM%NAolG5>bA629NHV3j!XUHJ24YC$0TISNhJQ`6oMn6Xw{gegT&s z0{j9#KNR={U4AR@3;O&9-Q@Da03_xB5_15Ff$nkn5dacP0Es1l#0o%q3-|?ket@=y z@C&y5hR{8~L7PHAce;2qANx}}7gQpudK?5@xN~y?zkrJc$UX~@ebylRtPMbSym65{ONJqd0dKVN^=TA@o@~=PT!FX^7g98JD;ic~%n}0YI+d(R~ z)&r%^9?ie(idc8qfr|2879o#Lw+|kjem^{VMXrLDLV#yML8+%H?LYV^y!ikB|L*{8 z!GRf3vKO4je%Tf8dcD{1_Ddbel1OLlgX>?U^4PQUyl3ZE z&`CI*XFU!+W%KFXq7N!8HZZoefEg_ZK*9Lkv-1i#41GEu`SdQ)_5hVK-8~Sx^<=4> zN9TR;Z3G{EJAZ%`wj3yN_XOQS(t5JQ$)mePI{>Ujz@u{tgxPwjl*i+Ei*^JkltCfz z|Dz5wAwwm9-zViCUz_8B|rJ6$c$D{ELXv3dx=TQ&P z9(vGuew}Fd5QDbY_;eluI})6!8<|0M&Oygrp!oG{{%Z=lEJC2f*0cGqKsl#x=PS>H zk62!-`u2u?@aepW8r7h?N0=O&A2IvzufOQYc*wW)5`T*~Gw6zMaFjcK|J3}$VJ9fg zJoueXc(k4bIgi1E-xZX2>>T%i;@*ef>A?;L1_1`cOP=39d3?X++dD@P#NWW^Yk8Bu zc^7D}V`q+vgy+GhTzhwm3ReCx}25v#o$lZ+eWDd>gWh9^PwokwRFhfinCIRPKbNBpfh zprqXG%>la`z4au2s|!dB~ft{euN-rJ$gYtchih@sPh>C_!Cy$Cxr;7@QN9Q}x zO&}8BNCur@I2Tl}c87vWS`~o}j6R^#WPQ4MRD8NY+PY&@6kdXF8*hEf-vVkNxElU{ ztqBib?BR9X$MP?K3-}D~)^8=;e%(2L48TE_2xfxA>m4Y(>>%M~4{kC*!^;F7Uipyl z;`8YCxdsZZYgmH|Yz>y+%7F$~E+}Zwf(z^;l;8s0ZUPM;6BXnTDyjGA28oD)(>^qS zUM7JIZT(ha;{mB0XM?gSiX|lisA2P(7o4bI@#E3y&4GNhcaI7v_mygZPA6gnU84wZ za-bdo4pCQf0~~*@hL>CopS-;F=l_3?UfY@v;8Nh&2bA_GSfNL+t^7x@?C}o_4Est^ z+6IW^pN4$i2CV-71HEr^KPcbr0}&7-K^6T{aJ%HVN29X@NW$^^anNz1{H>rfxO_T) zdmMZ%0_tBJe4)?Z3JM~h&c7Z9-zs=^v%CSFz3c4TyGDh9fd$+OYyq=c4wP`fF4Bf6 z6Zhyf75NCd0a5@|S%9tg>|}Z4c+8c7q46>3R4o_&Z7dSLtp`dYT{=u8Kz5=YsR2s0 zppsG&5=Ne&P%uIX1&?0aKkvaov=bbF3=9k$`#@(~dUV2%iLr#}P6z3B2bZ&8w;%!# ze11RZJYo+}X%`Jn))zgRf0^+&XM;KCK(_#P{_*KN?Q!rimrt*ayhpc>JO?N*7x368&olR z96tuDt=T=B4-0_qg={;g@$5Y5+4&cA*5JVhTpry%>=K~J@`Dsymq86(NI~!28)FLUl$tVtt4`2SwBWv5 zC$~p;$zcJHZlA*v{1R;5-7cmAo{X*FxNJRHD*3V$)N<~8;G_A&v)kv80_ei8mPD{v zC1}8azvV9|a7u1KqO{J z`&#C>M`z4I0nlkF|Id}a_h|mh&fk;;a?-&k%wD}FV9lPIU%Y#3L?R}5be9}I;n7)g z5L8|tzW`!MfW&TqSPCH40}x9C#Cic@8Gu+HKr9Oo>j#MC;L&Yz9K`Sd4Yhb$9xq+- z60{T9W5*v*h5i43y^rD#kKTemppNOm_e`J*qyIKPW%g+P$5YI1`2Qtn1OOBmpm6fh zJm%FqM-1GC?tJH=`OgsP_-#=8`S%2V0iWLs_yt{l3h)d1{8Zo-6>_BGN@e8_Gf~>bxfHdEamOcU92ixlS@Be>aO)JmFqo9tLN9T2LTk;g>2s6;& z2BaMbJ~at;4wd2}WVm(GU=Uy3x?a4?ig zc=qlC4V3vnPxJ?u2$R5h`a4X_v-7Bj^|cfM%ewpFnLG*Z9XiF9X`yAU=~w{4>J>(#oXb;%I;dq$} z@*gC~JR6Te#umT%bUp&762sdsK}S;ifNt)2@W7+D;DJZyCy#@#SUvt9>bwZ*N;dyX zC}uId^tuRim#*eD!%K+xb>tUd5dq!NDNN`+ zfJGg^q5&XLP(NKb04$mS7A*jYf_m!01s=_>8a$ehv6LW zfVz+#&A&`b0vdh^l=*u!ANl|q?m-zII0$NgfbQevUw_eq@sLO7g~-Dm-R+>P1g=Y4 zKbFdSw4Nx{_s~4%!R#mC0Uo%HJZyN$(DUV)T{%2rSKA_S8bUFr-uk~Q1Go*YA1|8}N9)`Wh-+C6@;=KkMLGAqQsd;Pz zV_Q3D%n~$w>Cw9z#01;m+3hFc(H+d;(amzo$MOSzE4b~^-3%JH1dWR}ZwDFF>+s*B z6D;P{?Q-acM<>fEk8Wp>rV}2W9umiz!DE^p|C==!Kx3M293Gm@pm9x4O?LrLO?Qc7 z%^(XIe7o&HQww^Y-Ep9i)e==7&^26;QzJpAyQN`0><=;l;n8bb1PO{Q&tUPk`OqU+h$F@yzj${3_vzgZ@*h$dbNF;Z>JH!Teo#H<-|DcGTV5#I=+XJ{^%{>}+XIjzQSUxuVAyvY zX#jWyMEoU495jFliI!g52@r86Pz-~bgua~*U{a+>Ql=<9B9QyR@c}+=uk{;$%WqK6 z1T-f6&!gL4z{Bz*e>eCIrTg|uiKk~&%o}lCJz~>jhC!Jn1g2sPctp9s{zwfDd z9CRPzGtg-Af9PR>o}EWLyX8PRY0JfOjw|K~vU-G65Ora$oeWMT6B+d{Y* z9XmpJ7(py15Q_=KVg|98J(>@)fUdo{2)-%612mlZ@PS8f;R8s6lNHq9`~@nfAT`go z*BKs~*A2h%%QNr`Al<)i0=nPZ1a!YQ(*5fu;QPHzK%>G)_ph6P@AozVjSC~)zitA) z-`fOs|N0+LeRHWq19bhm$M;*H_(8dG-2{Bcw+ZCN^+TW=*H7@bUjO(1zh}1`=nPOj z-|jpP-`2OF^ONuUK(F%wl@IBN^1&17*1b+O-_AP3a3kmpsQHi+JpVmmVAuz`?%;K- zN3U%cM3Ctz1H(QwaE}NwJmJx6YkLQ!*o7Am3$BCW9dvu1XXgz>0pZjGE+7tF$5KFm z8rKW~umhSp%Q-wc!v#A0C0sh(C4E~@di1hx?qOi?LJC5D!#|fv%eIUS%<%Rmj_?V$&%s@e~m5&{+0tJ1s(31;Nkbz*@g#Rr-O$^ zUnhW1?RgyuKFa2G5cu$w*WTb0NnX2v@2Plg3qDxlwHf%dh1dGv^8sFKfH%#*Rs>%; z@mdPJ_xZIjcth}O9`F{{*R0@uogTe4>{5t3B{+Y6JIG&>1se8D-U%9Az`RPr0_{SA zW9$sa+!+~;xic{wb7y8a=FY-!%$=3tm^&N8F?V(bkLKeXpgtYwzJ!w{e1-?$_ahuE z{StB5qxsnnk6spY56d5AA7R%=fD5XK!;te+iFXQO^0GI`+FqC+xUwj~Sptk|!OA zMp{&W=-+rWz5$)_<=J@!yd(hmI>>^27@5cv}AP>^xF@!Igj8BS*_GWqD4$ETCKM88lCDo>;-*((R+d!`})j6g)LQcpiMf z44$_H6$>7{H9P_yy)G&O;7dW?dGwZi5%945?7{E;*@N*Is1eb8OaOGR2{`e9P3q23 z;c)4E=*oD;q2+B!{c8os&M#mwkTtHYPx$*lr+Xn(#Ddl{^oE?_Fg*EM6gh?&JpP|- zKJdS|!lT*d6hoh&|V&6Gw}S+{`#S#=1JGiGmab}OX3_s&B}7nd9}#amoE0` zbveUfcy+)Exv-WRL{rqQ?as3m&+Le$A%wV{M$Z*kDKN9{pZ4P+@ZtD zvs>Kb{~^y#amW8hJpP|-Jy25S(R`4Jf7{`GpriI)3xm_YWAhOvkLH8_Jeq$p)`fzM z)aBnMbEe@pSLbnlpMMSv_mPbP$)9~KfC%9UAd%ht+hWfAz@g>!T-c$gp!35a8KX4W zrSpMD;}KB)K@7Sa_ULu|;ngd0^vD1I|3R@0s*jJk@CYy*bKwyL5keqB7(|GG2vHCr z1|q~6K!qSExq4V0Dn0%3=HLI2QU-L<<9(DGv)6X*Jv4!>=mLAt1&*T&d_WOE3J;|6 zq4|vkc*+x0J|Kkww z2L6_{pvG~p=)`-VLJfTS!@ddN**Dm|*S7tjo_``4kD{|gg#)kC6YnxG7{1*Paul>7 z?9mB1gWIw5C^S?{v^;u6?e8K&6r|dt^FGXBM{WPxGcfS?Ujzko@>j238)NX?x{Kxq zh(9#$GBCJw!ft@=JnF*uwec@R4|obN`6#GLWQ2s3<~w8$y#R-oPj`t52P8=OdqD%h z9>>A+r-;F&U+r6ufPJ1 z$JiOVm_0jhfTkwvKu<1P@aPRX`oYg%=m@?j1>A`NjbyNTbl(4e0k#~_$MSQDhD+yLP`DvArjy~V1a6P- zcRzSQuCPYRQPwUh2BrLvdw=1xd|=;u^x8T!f}&V-%QOateavhA4zL zq{GjES^=*-I$xqRq(MW`9=)QKXYe*C92h|DDMxt!E*7(Y2f8Q_8k2gVOQnwe^4q9smiV^`L&ALymaF zC{-7vquT}R$99EqL%OkDA>63F*sFxPe`<&ni?{m+Pjrt?f?^b-_tsJe_8QA6XrjY% zpJ`}tfJf(V!?&+FAnp18N1Ok0mTP{VfC(F{8A>0#mOze92gsERAQ{lW8*|Hn(tY3& zXwcoj;Qk>vJ%a^j~Ey@7(nAkAR1B%LB@|9yZc!fI2b@{Cu~8Z&)w5G7&sU_ z8h;HdH zVTCmQ=+PU+=)!oabBa0WR7j7`TcEX9ObiUA&s;i>fzCF!XYe@qjLV~UHv?!9z`@6y z9=%hTL24o4+dIdOk%fVwa~8<#-Z^$m5YC_f|9j`yF+({2z#JA3N6Mq|5a`@MkLKen zrH79 z%AKRZg2AJgb-@i#0_I%`qWE1-c=U=cnFuOgv39b+?a?lN!vnp6vl@O0mxu9hyX4c$ zS_Vo@$s!Yc7!Un_1n#%{^s>6&U|{Gx#V^m$a*4m?HK>uaO@!UaN`wJ)?QF@bhM$%E zEsq&Movjl77DjNd%dkZJC1~EG;imzA3+QgMhM$J~t)igYAQ?feieATLm!$HvZajsl=Zj*=_F(4>bHNuD5UaX;{+M@H36S zMdSbf|1Uw8v4M^7=oL-9&cFcIf3k$1e;W@w_Pram%F=2UPnSewJ)3Db)Zg^XL_oyw1RY@ZyA)lO+Nu<{KV3e2k581LNVe z36uZ*|Nr+tZmf$#?kpDZW&i*G2Zd*_N9Tvvya)$){6E0Ije~#R#onmz&A(ZT-Z%eJ z0L7nniD1J|-BJmk-T+2Na3|`uD1;4)tk;~5VE=e_9&+U0$JHBn!PW3~^DoYFf6tw> zW`cpFPv?c#LKFD+c`$nXKhSxq`Ot;tUtGm{zLuxGdqt!@dSxbg9zP74{`TZ|zU{%k z@8m8}YuiKfl!xWz@)JJ2F_ITvAN1G>QUSU-%C+@C9jB+|X-|Hq)2{`5I&XP=zvc1& zpl|DK4}Q;69^K&_om^cKEw@YfJbG<+UWL#9w%q2Qav&Ohe;F))fNp9R-Fp>JW`NxI z=h5xX;n8UTiVtx9fa&)D8xYoq#{fk6P4)JOM=wjXSFei&V%)jp0;mSV(I)9-aR9eV z!a>a;l<{Y@b_u9MNJP6N3*0UNhsWS+kDNUPD)U5j&cjA@LG6(p5J3ZwAXe${RKi=>Gbj2P6XfWf@!ACs!+oTilwnurO?NNSkdz6Lf_UQAo@b)Moh{26d z@cPeS$l?H>-tD070JhFYcQ>r>0a^m%(LEW|Q-Jq9)}h9&NB3rE-(&t+MBK8#Yiy|e zeuf4n258*68XoXy-VHL8!I6K;0nmPogAZ9fdPO>2I**Y?b5c+x<`5IAW-`bRXWZI_csKn4FwbUE3sIpho_Y`vH z3)CNKIZ)!nzm0|4ibc?)*AvvglY=RiJH@~-q2)k{5{kS>udU!I)PDGDUe9hfj^m&O zVGIsi8NuChfoR9L*u!b?{y4b1;Cm8JcLCDh7{>iG52Own%Sm`~5AUFXN?!)l{uL*_ z00XN>Eq@MyIyjKYbl7^HBcS;MV%PI*0_i{am=(4BkvI%Wt?1>Cp8%)?h3p~n=w;#d zv^-Mm3R?Ndc*4W-aIux)0Z{tl-zLKB*dfBgzb%9rv_6Lgv_6L!G_c76TA#xV8rft4 zuSW%4aeMJ4sP6J;KKKAKz{Cn#5_+Ne0kcQ*&xB$Y!;`P`Jv0v)o?JfQVC+zueo0I(={eGU(3eGYd5NVEVf3SOVX zQ{d73vcaSI5O{sg0nqxKgP^5}VE+iXaD&E!xxvc8>vMQKnhz>?{6A3on9#T^@yl{J z_JT`-bWl$R+^7aE%lW(qESL=vL@VT$?LaQ%5K9y|w}7G!qo7%x0X9i{3$&m?j6$QP zC-C?`YI^b~B|U*gVnHoM)bw=X0LW43>B&vN_U-^jip*Z*_RGL8IFs3~?}M27>^GDr8i4P48TN_C1u#0OP~L0Y-!6k-`IXZUreAW)6%dXdYMr z1JUk*nG2)A+L7D~6Nk}*O&%0?APjaF76RsO7!6i}LZJcvPVN;Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!n zMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nhHD5M-V0era0yBe zSAUNBYcvE#Ltr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!n zMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ON zU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU z1O`(G*xNJcGU(~2=a&>G=IJFD6fkILWaed-q^4+UDk$12Xc%ZRXlRsVg19yc8XDQY zi4`H4DV}-GIr+)injp!d)Y9VAlz2@|1zTGM4Gj&AQZo}xsGx$4jY76_PPS8KNwKDa zogIP$(wS0RqHC9uSyWOPA8in;2eAcgNVaEQSz=CRN(jhehGdXkw$Ti##i}_ur3?%@ z46zC&nJKoarTVI+3OR|zCGm;Lg|=Wx4UOW=s#LgZ48TrI0vS+@CRmb~gheDXr2<_v zzd%z{0pxkGpPfKvSy^R+InMc|c_m;gz~0ccgZKfY80riL4UIBQO$9pz4GoZ6Vih1E zV;ju?V&?Cm1h>GDwJfTRw^VGr7Gm*>*f~}>oF9U z78Dev78l2-7M3RF#21$&CTABj1Vcp?5*3OPlT#InQVa5nN)$5F6v|W8%Tg5*bBaQEGCDLTPbgdMd~>5Iw2I z3W<3s5H@nu!_6wrOwUWqi7(A7PE1RMIioByKL?U}z^*8+%u7~)DAWZhE2&h_NYzW% zQ^-xs$;nUF&{RlH%*jzmE6UGRNQ5d>$Vkjf$w@6j1W{s1er{%RJSf?~g9yw~NJ=d! zPfg8JfT#dFxF9DnGfyEmH8;PgQXw%pIkmVrwOEfKEx#x^HNH5tFg_WSt-&T1GkB&c z6sMNxD1aORF{2oqlvC5vQj<$E%Ro_BoLX24iqFKHoJxh{{Ji4K;*!+75(N#YVVXJ$ zMXBkDMJYL{#o*v8&qxG?W@?c_Vsc3-SX*&HYI0^;W@?HaLqSnyUP*jXYF=h~9zy_# zqmY|elAMv6qM!s3RRSmaVpzoMF=Qm>l*H%f#ite($Qd0}!bBh^*K@0^@pnyUKnzoWs)AEZ_!6^%rU_t4#1my1A z#Joy{++ujbEy-6%202eb37QU}uG0khBtI=PCp8`t*6^?_NG;0DPss#DY^6eZQD#Xh zEH(;?z#0@v@)f{#fpqIJq~(+rXFv@BIoA!uS18U%Ovx{Y=}aw4Evi(AP{;+vBuGBK zxH2~>KPR&)wFpTMTudQ3F*zf(SOHld#F_CqnYo!I@wrJ1L8--=DWHgiNGO0MK*8ke z1ae_wX0AeFiJoT~xCkgH$_J$+aQv6%rWPyYf zjLe)Ah2)~t#FErvg}l^qXxt+;4!{izSepREQ2><&3VDgSsd@~V>3N`*OJ-h4YEg1( zK}mj5aXc(#F?fO{K|W7`R8e5>6+y^mKVX56|z|hP_y(HiZc?6Qd8m! zN{Zr<9KjG$l$e|itD}li(^894^O92)l0iuuRQP7*Ddc1(C2MPg$_%Ih;JU0lH8C4x znjS-OYI1&FN_8-$b*`|aCt;C8B%%2=j11*Xs8vJ zB$lMc>p(Mae11_%YEgVqYEEJWsQUr!Ph^MYLBa@ZI!XFL{TFbnTR|Z@Eip4EH3d|d z6s3ZSP;h$~RH`Ru$8s?!D5w@|XmWu<9K^IzO;OM`s8Fq{;9{`F09*{=jzNB&e(qKZ zE{-9N3PFy}u1G?zjxIj_&fZ)M?)gRer6rkpsS2to;AS4Qk*1oWP@a*Qld6!BpOXSg zSCGV@nqtMpz{LO#G?0$+#9{?lv7J*1HXt=c0hENSxFB63P;)3hIk6H^&f1A1ej4 zw5*Vvn5U4JU!stkn^*uXg%nCanOZ?ZwLo9B05j<_xch@cUJC?Zb*MsVUP@{ahUsNS z3K|8ODGI77nhGH0S|C3|`fA|*Ca7zM?xM_Mh2qlUg4Dc})D%!?fg1#+1#pA(6r4fL zQMAT@9v6dKerX=aDutB95=bXXqZrfqRtmY9#l@*$g{c(FC`vQ#DXFc+TYaBKvoERX_HcFfR)FM3D+SeJP-at7 zEml&{0OvRz1uz9JYl1)_>5^Zbr;%EapPZqikPS|o0f|K=!I@R5nlNW%q!j7eft5fU z1ol;OX;D#XUP(Np9|%*LSDKSkP*MaALr`$&fm%$U6bu=?fa(VgJHY$wSjIoV+Cgni zUAvNuB5Y=Zod8l{NSrK4DRxuA7BFaNz+Db;DXjONnV%P*Tv7qniy;OZ!pY0eOT{eu zVf`5-Z3^nD#p+mU313j(0+LvfR2PFYgRN?crWF^1Y6>_qi$Td3JYs`2XhCT;9+z}R zYGQ!`c(4Y!Xan_4!QD`BNe3QBf%!{Aqqqo^N3N{G9w;+|qR~K;!Nb!p#0u0#t;{b~NXgGrFHuMa4O}HA<(HO# zdJM&>kUn&=0!T$}VkKyF0Op4LqWIjz%J?F12Pz(vYitd<7~rj@ko^1{2G^h<{~#*` zH+Z7}RPAuVgjI{7#S^Hxpjr$mkigNRsgP6&YAWZaDX11JXn;HN3d#8?saBw>1(fm) z6x7rdlu98@{gQleeWrx)eQ>C+uVYXoxZG1vEoRWrCpc=Ibl!Z(3OA>S9L9R(n z0gaa$8Gwc!lk;iV;l)u+^9mffNZE8X8Hd=?ba}?x`i9l{(2`Vn3 z6%r&XX=tS8r6_1C7-|xuJ}9*~wWusL7(8;|3myOpO3X`7g#|jKaa2-N32GaGf-tcF z8U^6M*HZ{cEy_qN07t%hQK~{|F-T!4WL!YE3?7Y$*exi^2X_)ceIDq5MS5a^9w-iz z!K0-LpyD?*HAMkB$d*&7r{L)19~9#0=dQ=a0B@Q@Ive>#m?8=q1sRpapwSd)>qV16 z88mWhrQqUXWd&~3dFEx7Xn@(w4D3(57AB^E+G46Hx^|!z zb!J{RUe(Z&BO^5#i#kWpz#N9xbred9DhUPwTrX+}fWr@w)ipHo%kxsKKx^_tXLHb7|#~?%-vJdbXuK=ohP@M=)hoBN$Bik?EGer|K z!Mi|4z#(Z~wO9{?s!AE46toO>P6ULHip=PTso=cQXI zs3xOAJv}`xhT@Wx{L&H-m0DE95R{sj;+C0{8j|l+nwFMY#Gs)8ZgJ$mGh0$=TAHpM zs7?YEV+f{mz-FVn!>=TTFk}CsS7H8G@K!=RE03m5F4nm zpbF|MfEdv50hR7ZTzFSO-Bumc4gg6bi!qdf21;@>^FTH!6qgib=A|=$+Bl#l0l1)q zw7m5gK!$>J+oa|elvLU=Ac{*+h$-Y3faWNm!!@8*p%tXgRR9$V8XC~r2sBp)E5bmw z6l-cSB$k%sGw3n6xVkxp`h+kPC*~#RmoaE)fGTer(7X|-(E#ZV!rF0}dC57YDX9!# zo54f2DAt3@?exqtXcA$7s*cZ0i%+e{EG{V~PM?BCW|~4Kc$TKPq*#*yJ~Ry<5-){J zlYs`7K;3q@f+EPE6{H$gD25HdC=`LlgL6|s%>>YBtwLF55ojVo0o45k&u4&SK;vcl zIUw_LK%I5a7@8hKYDGzE5olTlVMlyHVo3%AIMtWrE5H;eAQb2+c%~_UBMUr|tx%Gm zp92}lE>2A>O3qMF0VP&&;sga4l12tll~5iJa+VRuC2$Xe#X;lSAW#P` ztV1CwGcU2I5+n{c7czPR>7^GdXuwT}xCuNsmjtSvLBm^V3OPAtxw>$@MKA+1ixo=q z5@GoZH2hwaSpW`-_=2L;w9E>I;F6-u0?WcR|=Xx0FRb~ zW|1MmS*(zqT2KN`kEx(BPq5>`W99lOsR)i9Lr#7=IK~;m!Lv{~`RU+^1SOcbUO{Gx zlAZ!+L?1jsmzV>YM1afzDnV)hC9u0eoYbNssA|~we`c`)Tmo!cYDH>1Xb79Z7c^s- zp9db#201^qA~m@b+|&Zi&g6l5UHL_z1`H%hz;=Mf)$&plkd%Uq0%Z-b%QX_g2@>IY zm}OvZXhOVO0-A0p&dE=Q`WZBmgeX^_bL%Cbxdf0RPy$a(Ny!A2$RK+lQ|`H`iQq|X zg`9lwbdw%KS!z*IesN|=B|{jDr2v_3&;ZR%6ldn7=9TCufF>jo6_PSbKt6`prK4b^ zt)L5;ErW9H@^%zdI~QH!DH<%kv=Z*o_@iuK_T%zo=!oI zL7uL`Am=8Q)H;-8tHr^f)|$AdF>d}0ZxGALp2%qz>!PE`QOD1c=^orBCgg+$QoGibsU zHgBz`;E`Ainy-OOA}eI3K~09(YzrQ1(*e!BWu_^_$LAC$=EbMvgC!wWqRjk3=V?I& zFC_02DP$xTDw6wafSkD zHX}7L1r%+N?k&h~2B7jOzqCX*KTQ`BOrR-W(ByS-X>M*}Q6-YeDVfFKW(;_88>AUh zY(f-frh*eLazcYh!%J1LHt3X0d~RX^bY2|fUT_DhxEMOeqL7yb zgXPm0oIz#10)(TGSdK+D5Aqr3z zg9oOIQqw^T3W`8AQ7TLY#0xMf(9i@-22xVwW?l$0JUm!Em<>Vt*tig5 zM{#C)W=;+sk9hj{3=w~n6eSkm@kmIJW55vcNm@ZF9*?*MxDIN6fU1D4ofl6uF8bYcTP#e7)TO&P&QqbbW%=E;ZlH!uYF~N7Hh_j$$psUE*14Jad7!>NWN~AP9z$|YYGP45WULN692yT=l~N3vF=g-p z4aP%fIYCRhKs_q(I+m)`qI})7%pA}}FJw>>3p2s)<~I=BDNrr$uDAX29cRnsnB*|v6X^GVorHtWpPa&XbDpd zsOt-A;iaZ0CRfH6fJ{qF0X3IXpo=s?bBYDv1(o2HLeLePIhjdCiAA9LHzzYMJ2gcC zyn-?(GYM*ff{~t)o~a%KxEBIiXc1qMQyib3S_1CUAvN9OQ6%&jGE#GpD{0W^g+fYd zadJ^6q<62!016?*P%?P*7+j4(me+t<8Xy(A;E81LQaz2-3Q%7i)OdhI4=7X>e3Puf zwPYf=w$n{ZOa>_c*#}OKDGIsy#W|JWG*SW?5d_-;>cSQ?WF!`)#1|D8Bi!MUSd^j= z6da7S*eeN~hV%0CbV1RqqmZZo8re=S0!+dgjntd z8fPd5TL4-+39f@66)~*Yk(mZ|A7o59vlujm16umWP@JDug6dSzxI5S+sMX)uoF_Rk2ei%%yx1)G?ntudGJ-Fm80hbb>&IH6Ph0;9G>U&stf>&&&D)4&XFgPM_8tN^W~Kx;yh^K%O_ zb5a#bGILWw{Sc@-;!`q<7(zg4umrT2KQ*}ow8$A$;=>IFIieWe`2~-6fGvg&2d89$ z)_Ug`Rq8RMmFDDt%X!dJ{o;be7*G1{Y|D6C|Jj5&^Xe6r4cI_P|RsbrjIG*cyVI3C#f|`3jK11E^MoLR{w^9HHu!f<5 zj){?`m4cogs5O^TS`c57pPiZqnjT3n$pCr305s&3S(d5;U2qESdV}heMC1`-g~XiV zd`Pz(w1pr8w5bF#J)rYByb5{3|@ho28z;@(t?~!NX-Ch zs(^A3WKf`3Pr6kaii!OQ3uWszu5nOCLc)-XQ%7VEuXu44?=|E{O+GdFhZ*Em#vB zGI$0Fc8EM;Fa=bafC|ro)S{e91yEJ0TasD?opeHKr52YI6_*r&90x9y!QBSvh)a19 zXc)Dq7!(qqz%4E*0%y(QlA`3qV$j5)LRx7ac%KZoa7@btZE^uE<_C{S6(cu>LDm%H z5ob*SXe2NNWMgu1K_1)=P=FJ#q9h-^1EhfJ7qC}ANwB!2s3bp|6tfGGiqH&4H5wjF zAcdqDoSa)gRJbJP7Ql@qCcJY}i3{%>(59a}aCql|*rdd1UP>u(jt40u$@R$@#3jn) zj3OOyQpqUFE6ve?CD5Yej3VOg%T3KCDi$E>;O1gak)WKI3|h?wGZT{Q6N^DxQ6QNW zVva_Ep^idLPMkgg?I6=)(Pueby{ zGXb84(a=P141hF(je?GyVC)DjNG@h@NrlzusS3HEeJceysZjOMA}}*AJttM6IKQ+g z8PrOH*8Q1z3MiZJApJGaWJIch2B<3ro?rm)g#%5DB86~+n@yYpR(8a_I?x}g8Z9l0BAPEI{qaM=s(1R{{fXrzIgO@*mXBglOFFgiO z(=i^_WCShY1rIZULK%{wLGlWQX3)F}UV090QGu5~f`_p{ZB5Xq8F+_Yaw51F2%5Zr z7!99ZKr<5DzX!K$odZI_gJ;FyrKsSIGa&5>8K8POuUJn3(kF$@%!2~PKUg6GoagiM z%R!An(3(2PlJj`bWGKR_lA_G?bkGXd^28$0_BYT}P@V#4aXKiK>VgzQCt1M_5%>f% zxLuJ1TJWxro0yWy0P5?-gF4aiskx;&piGmO58Z(Xntcj!4GvN8_w$JauN(vwK%k5O z>yhRr7C^ENXf*{yJ3M2hC@6t;xhsK||0EWJ_OpPO?;3&@X+d_7!`84Fg2qW~Y!oz1 z3_!aVKs%uzvsvIRp=qGt$W1IMwo*{lh&Ir*jMdV#*Qlz=$=;1`Q2G4GqvxZzgETJ!n0x zfkI7%swQZ?saA4n5ojrmda*jn3Qon0#In@*^30Ty3@kd~8~i~Q zgVsHPXwcdm1`Umz)V%bP4A|-((CQ}WYAK{HVLWIJa&dfKX)ahDY(*j{h@hRukjjEo z(25|?QX^2*fRZqh0ma}R2B;qmT89Ku1X-H|k4a3mpoK`FWmljfhJwVRV(?CXMaVe? zs0M&#!LyH0#}tF~WrE^WK|=%C~LUAUjh)m2&%`XLwttRGVmZd7B!!{j(hqP0n3xRbMQb4O| zK_O5A-YfuiC3Jl}WFHJD5H+$x^Rn~u%kv=TE+B7w0Ii6F3}=JRQ2^}&OD?I(;ZE?XHy3bRfI5tzAw=*JGSL2Fi1)a_O1$zj z^KdEvt$)u%^$={&i-txKWHT?4pO80_5C}A=kHCS3oJio}kdQ<3lZFPW07Mb8ewWll zNXkP~2#$1Qg~+i+NG+P7pq5BHIPSpd7*dpiHn4#ghJ%)|YiI<6rjcAy3-U|+K#S(B zKr4hpi&GK%13@JXD2sv%6R>LVjvwDd$Oacsl1WJ|D9L~=nl}Om6?lgxNE;|;gEt02 za&l2gd`5nLc04FRzzg$1yA=>3h_$+q7BYNXtq5tES857)u|9Zri-Lw~PELxB0*KV) zf^ND~Pyp{-GB7l&s?as4Pz5tILAySn`_@6*IkKHVBV9!$m7r}M3fWFvp#3P|?S`OT zPhc&?>jjTb6q9FfVnG4eT5{YB9_;{CbyX<}rFof!rKt*@F2y=fFTqC7Q&YGgISHx~ zyrlu62vkCG>EZ>TA_^Q;N~L+Aah_Dr@Oo+r(iRF04X``nOTg!{fKo7cR|!NgDZiv7 zKNk_P8XD=TB}L#l2n}N$1+}6aPz4E3pz(ge?x`iNd1aYJ`FZeN_o*r1=@C7J0PuLd zLT+MqszPyTQK~|GJg6}l4{AGr8ols+|Byu~IhjepmBl5gxnKpEiQr=oG&J=1ZgX&wjA2c+yH2i~u3o`RS z%h|Ow)$$7x3riuV$|R=4D@bTz5AKkG7oL_B<)r3ml%*CGgMtLKTSvnfY=su+yc@9b z>UyA+%b*ctz5HV6fIoOeHE7ccSOp}PgO^GxfQoET{>@L*2um$04hHSA(`0alY_I^0 zW|brsXM;!N^%Pt|M`VCD&2TZeW#*;0Kqf*VTS9_CCokwIfQPcd^F0c-3aSNM3=mlb z&{Ps=$#`03iH-tzqNlhdK0UD@9@2pUsnt;c6%_f&$)yFEsVU&WbEp}i@Qpd((Vj$D zW3dRb0VTf(eu@rc5Dm1z95m#Pa0jV&>L}!;mdAtKQn`U$KHMXrGROp;=B&g@OV@QDOx{QBnm%QE~-CQ3?oWG87eO zG882hFccLRFeoq-Suhk?G87paFccXYG87paF%%gZGZYz`FccY@GT5jZ7)2msT^I)s z1EvH<+c5+{j|9mDpCkb4QCo2_fcKb!O5Can@G^YWVoe25Bh)nyyt)pd796HUsl|{6 z6L=w`mZmOfCo@>YKod5!s#_njltNlQXayZ;rv)c?+d63H z1OqgVK;tK%DKCU_JuZfTa2E!*09OW2A0GzL(lG{5pO(QXG?)RjY>6S%&)d&G+z+(S z&(F~Z)WZU|F+e*$J&Qy0!1Y8bctbllP{0+7Bjlv2U{EoDQxP=0Kt&*^OA9G3v=pEn zN<$M(Xg2`V2TlbY5R{h>E^A@>K*cW(ykS`vEprHtmsVGW7t6RWJAvKaRL5Un3 z3ZUvHxI8lrbfimBCTK8$0m4lLA0P$ZKhK~Fo{&^60L_9zmREzf1u+D`&cFdj0)h+b znKFQ;gAko3D=r3jM@j*FFoOqZdLQf_kl#U3rJ!0>3huiWAX+|PE8QW-wv;6nfr^&= zG{{mSgzA*kk>Tjlb@#m&Qze|FW~afEf5N-1y<0R zN?X+e@F5bmkTR-RK^J^1MLfI>piux7(p1n=$cEI?zL3GYOwj%}1`Q33T&R-xTulXi zg>2u{l0=9?P}YNG4kUw6)HtW+A0`gZ ziVgHUiygt1Yk&uPiVcwjkh~A=#=+L)TOr0i@?b~aDI^v{4_-=v?AO6|ECqaM1iLnH zJ6n^B0ogZ2B{_N^&t!no1b73TIeY*EzVX^hA*B?4v{|? zTntcB175J77z~_7S7K@5`fmP`9&Zpu;ps_sosDz%LK7MCF0s?Gr1w1{6YHE_=fr6q;&{hOvBd{@uhGtP}v5rDEs4woxo7QI_ZXfKK*usw_zb zH9A21L&2#QbhxQsX)f%{Gl-KwgO>!|k&{_m0=8Nav^J^|9JruZG0=n^%m6;T3bcC+ zJOKh4Pf#z0C0Ov;Zm_e7pk7K4}=1MH8)XP8|Oa#g{ zKA<&8pxyjb%r~H77uIjcO)Q8{N=?@RFE9W%g5r@%C}fr3h==Dxe2U=hDO96CZF2aL zMBv^l)N*h}K#>KPNFZ5AvlH1F1vs6Gyg46~jWSB}vO&oK>0A$RiwqR4&}hpq0I92H1m{DWJRv z%H(! z2JQe&Essx5EJ#ewEU5%J41Pip$Qsay1~{5Pon?e7$kOJ##2iqX4Fj*EBV6i$&k+D; zNTfQO$kWCQH8l}A1~QafkxAld_RaH=PC(=(_I52_Um!P7f%o*4t236@aIgD%WuNK7iu z&nYcQjR()>fhHvoa=Dp#nYoEM;8_{SB#wfO0%%ytCpC}3u>iE(*AKE;6Excc+T02~ zgodFYzZg92WCL2yV+TF6j=|PewU`02mmahl9(EcnXvRDrbPiupi6ZEXG}RPaTgaFz zX#Es;WDeAK1UDAqVS{oE(2=BqqWqN7&MVQPc?-BG^`X~oC@0immHs73R+B_l$w!PmYH9~kZEjT#sKN5 zK&cFd#G>3XGcaimA&VhYHi$AaVJONhPA)Su0Z%x9hG}4ZALyU}Xsb0+vjp1xMC!|f z+Zd3*C@L`oH3(DlQb5N*K`RCD0A^8%5md$qTBjOlB8?y*MlChLlbhh9m*6Lxs1}0` zynzmDq9_2jEI^3~dEgUV)~bP&gQhUy=L*0K1}(A#pHEZ*E1N(k5W$YRLGqX?X#66z zs0h-r*95iL;PYvaL${%mR!D6=Rm3qzps|lqE!C=0O+5t{&~%g@mV>6!i}K4sjXzLr z1?nFJlR&%S^TFF1te~e@88GDKGk|B|7z`OIQ;QiubL+4` z#xx-_uLOGP0n7l^6i_rmyatLb4Gmb)1ghkra){_d%p8NxL5I&AmxB5rpb;ZbgC11a zK}$akn2J(Rp$|0;RCIuH4ydPV!~ouFQJh%@A6&w8HS(4lPH>`(pnJA} zaM23R&nck!8&KHx1D z%J+cMFLp!x`3p+Ffztn>^b;rz<9~zlKSJsM|Ns97tsDR^9{^36LCu9xRtkBk#h}gE zpmXsvL0d#XOPE1Nnt;!m)lmR1@XE|f*W+RUx2qT+b9)SsVut~=3M@4x9<={IJ|{B? zetZ?ke2~jwn3aKn0mNowU|?VeNiu>61_nn)1_mx37A6P}K_);&IGM1^7k~_7U|@*g zVqjp9;Df40=)b@RVVg5BFfegonqMFQk>A9KUEV+lBHzHqz`!DaX}*FaMBX3dFKp&R zV6bV~4mNQed~d7v7?Sjq^p zA5*@d79u|t6h9o8<_pw8F*{@Kt1F@Gu8d`$l(wBnanXoJWrfZ|64OZsldFW=CCUw%U; zME)trd@S+5pc^9p8SH+{@L$jakymE~#SdouUg(9$GvknF00le)1A`cj@O8;2Or-VIVgBd=6DNOSN_JSpF$~)|X$SZ>=Ecv4VDqjK0xmfb=hXWvu3=Ana zxB-z@1E+t?^5Fnf-Vvk>OZW=h1W7P3fU_Z%`oZ89 zM1B&O!gT)y0`dj7!5SI7K@=AI4eo*@7#Qrq6sGwF_rMYi$3WqS&3z9c@}Tws3zqbG z;SoeWlM{RW>+l95Uj(i{^+2%z5rC2hK0z4ZY8;FE89)UO0|SFExc3oK#|&QsA&C3} zaQTDj{tGe?`8XW%2B3nKfq`Ks4*3s;5dBp+@R@I%i!?e1gN|zNFGc6d_X{6VFJW{Q1cv{{~ZX(FM!H}+P4f?>{plwG2Z}3`OPpH zA|C*%f3TEq4bvd1cekF8-O}K3=9mbKq6T5 ze}Ky8fsDc8zJvuJ2?hpS@)s6DGuIt9$buJ@gD=I;m^RpP>&;gC#-;&59uahmY)nOA@ZPZ1UC0IK;^@6xeqE2=>}q& z@30DDKBSq2DbKJPA`dE_u%%xCs65W}4VBji*MBA$>7!r+#C*`W4GXsXyAdM)3*0}( ztUnYsL*(nh@|gACf-O*a9OZ|?R){>V_F({2o)MS%+aUVuKt98gekbgN$S>vwmCu;% zZ-=80`K@4iO#d-lgvhS|m+$N#Tfi|5BR1TG$X@~FZ!G=W33nm#>>vt@`xe{-NiZ<1 z2N{S(KHxq?ekTrjfd>$I$S?+G`f-5Dn}GCV$v+FA@}Tw~69=aM9Uel=_XdxDV9GCe z0g-A3p;&?Z$j4*3fN+pzOK82Mi(dyx{P`EPpOQ zt29tGiY%v$EST^cFOaVNw$-n>}M#j=UxB!)J0@wdy5W^r| z2a^flhAjg_D#-oV{9g~z0_uNbYd;w@K;(acC@l6HG=n4o0K;;{7q@M@iikE@G z4(wXY_*H0yn12>5k2!wz0V)rwU$K=BAKD=LLG?4X{QaOEA`dD*6tIjBKInkR<8ogE zxZ}*gkO6idru#oY<)d-*Ujn)y=7ZYL*v1DMx*_ssz~P5w{-hTo51JohV8INZ4Sf*# zO*q_lpdTW?9>@4n!6b-0xc!4A{v9SmSV zPYYH+FCGE{HsMm@4Z52|0V#ovKF5cz)~_hZq2U@t@-G>nfeeLmO^kq3<*VUssF z0Fn0vjlW_k{~Dn3pkaKh?mGz4zXRkx2F&uO;Sfar36A(HI1G_@#!{~eC{ zbHiJRyfCPI#8SR8e1^zJf(kG!^~Zvr5c#*P*ym>^{D;Vc#+R|x&jAb|hchsoV_{(6 z#mNmxcWZ<5)gS@^A`z{5P9%25N!1;R6ZF;_#{X{^v?jLKP>tgWFYd&@v}%>C-?3BCiHY=2-eK32G2|Q2zm2{qaB@ zA`c#4#^SyW8W8y=Q21bpUk5FSJZSs|TmO23HbfpWjEtE+8+0M^-@x??bg&g1R}i8> z4^` zH`qY*tAN~(#s3eW@-{fkSFnZX2UXwL$`=EuJZSwJw(|P}R34oFvDiPs4q`s8^6LOp zUJvAcEaA7o5u$%S$N&lGU?*5DgedTU$lHP9p8>OeIN%A92bHhb@}GehL>^c9kw8Gc z04k4b{I-FB{068zF8dD7$T*^Ws9!eVc;dj3S0r>y|@(BdwH$de<{Wk>x%=X^~e~9}+!S2N@UlhO# z6Brn9g^xlIM87r;{RvQcTCPe>D5G8>*e%O!;l3-v+0|ywU{~7Wi z@}Ox(Z1Zyh1rT}A`~w3P^FKi4!TonEHzr|L6 zKIntUgZ9^8YkwL{fXIW^w=iI_e*#ngA1v#O6{bSuajoxs0F?)g?_&!e2hhYH0|NuD@q-6Y`5QRK&kh`i*bg3t z$C5t-PC?{B_G2qQ0?tC@FM$1rSw1S9gUG9Z`@eP=<$J&-h`cE{{4w=UxD1g8%@1O; z-{C4m9^6dFQhqkvfXHtHkDp+UA3A^wRt5$+kTNX(Pq+h;U|{$H@*lSH?=D0>13W&4 znSUS*JPm=RfBNAOL>{z03tRp1;R!_kBaZU(!&8Vnczq_8`d8r@ zL|zmeKhVVnV822LhgT5!Paq1*{xpYoAPEKr@H8hD_iq3XyfT2dDPdcGCh!rW|2>ZM z$?zE>4_Y6JO}_(F9=v`9i~kb7LiGOtc?X;PH;B9j4*3O8dGPuxEc!1%<#GAn;U~m= zT=E-!L*zlrz_6u{34bB-pk*-F+CLlqL*#LpufPO~SjhMzHy1J9#+P59t)u@z#S18kVHhL_>a(7}BM;isx&x0qXwCErJo0lG7#L>Ykq51L z>%b#_hk=2i0+0M31_p)&jCq4xyJ`E>614lj!7rugK_8zug);^YgW^ldAz`y{qXAKhr zg9PJmaC!vo=LKnJaN-kigt(U(G!+bT?-eEn1_P+N5VU{;ne&B-fuVp2Vh(8EFE(>P z{c+IHCI<^d9cceAOq~;-gcF~FBcBGyrK~;haPnaW?L&sB2d&owtA`RGdvll>7*=pW z4rJdjLLOufXss0{(;1UBcDMtG#)_d>3$X#n#85nLr)q(drgA|hBuQ#j=3^Obt_JH?8lb|0I z-#Tmz3@h9r`r+{nGJ}Bu9Bw{H^5Ff{AURC;x$rH(o}PNx7#JjyA?8Eo8$kv@FeqHt zAjuOGu6NiN7-m4t!xgTe@Mi%PYAFzV!TVT1R-%5#1lrQ8C=TM9b^!vv^4@IG#kMr`2{fSDda;l6~Ofnh@`#C?!)V2}Y23<{Sc z>0;YRF;b6kS zz|fEZaSwF+2&#TZJ_8rNgl6QR0EKf72Lr>8Oo%?vesZvbAmty(k>Ii(GK33$E-g~t-m+WZ2DyP(^tk=z9eI&c*P)(%pCg_D7yfk^eB@M8fD?iNDK2Qk40 zK?zWNt8g(ee1Mt<-scXIgM=TX-Ui3F11P?GVJ-og8^guGa08FIHCzk~C!q4An7f6G zfnh@tZuef{VqjPRl_$kq9&QGPj$(+p=8p$@P2$yI1rhSLGhBq&A^~h z3NatLZ5AaS10YEeWGVwl{Tyxvh96M%p!F$W3AlaWe2@Uk2O#xlKf!AOuqH@(F2jS62k-v}$-(VMYOi5wAArIuhKGS+M>E8H@c95F=m)uP z4i5u^Mju2!^cWS831AE|e-Dy8_W0!^6PfF#}>g`1}D}`mwY}LGH8RWnfsb z2%;Y{zldmuf#hR&85nlpk+0!pU^oGl2gM)AdQg1=qCxuS@G>ymz#$J(zlWEB;RRG4 zynY*`5uPs{A@vcoT?8`k4KD*j#$t$jA?FpKx|fHKfx%)4Zh0L(1_q9$5P9%^G?0DJ zauyUHK70%e5>R>QvR%}A0Z+XG(%-|!z!0$ps@CBfhb0BxS@G~$Ntb^zSpOXO6hbBrG-I>OJuFku@+KjfSRM7)B`f5Oke@L@Yd9=e>0=x_z48x;Wt zh6TGI`oZhKLH>hcP(9`%z`*bUDi1oR0W1XxH+Ve;GABoXfx%-B#GIpGMF;|9PLBWs z!w;xDc)SfHjm4ZTpq|iPh&hmTBM|?B>U)rXuLv+O7(nI0=Q@DQ!3AQ&WXBFMln0grr$AOph!Jn|)i3=A8f^5AvRAfu7`cT)rz7!3A7{D)0` z3rIgy9x|_h@IT0XR|FXt9zf+m>smm@!!Stx3&{Kf5c47DPC)d7)PUqggcukCpz`o` zGf0vFGHzia#K3R>Di5Cbfy#j>Q22)kF)#=mgqROLw*n+VLikS+VqjQs2%;a}{sWl- zwSS8c1B1a~h&*Io7Agsqzk(!>Uax`5%`ZsuX#Hc1{uwAdRD>BA4nXY#t#e1%1_=)r z(B7yc5chz#!J^Bj2s1Ezfa-_LGa^)g!mCA?fx!W)AAC*+NSes-0_i^@%)n4^7Ggj6 z91raJ-T6K+VKnGL{$mkgVAya8q942t7o;DGLGmgh3=9)4L*&8h96@qO<-Q9@KUCfq zHqeFXeo)bgF|GrOj}{RIh6C>)=7Y`&0U6KW4IUT5=)Zv6vqgk~A>chky%<Opyq(~pMg!mbhkU-0qp%%8&L*^hz}5VK+YdwU|?|P1Me6H zxidzTfq~;AL>@9fg~(?h`)foQ7*;^#!RL>F9Dr#*)^G#q-vcuL55#=%`6MLj|0Bx4 zpuzSBJe~$Vzl22nHew76D+D0=!RMQhsJ}*xf#HP|L_hfa6I}YS)YoADi!m@%s6zCE z&qpCq{~s|1h7fT~09 z_kzq(kz!zIfXYMm(LwwH8}ERPTl+{cFzkS;11$#x+Xp2;_T)%0Fsy*eWAjfBl7960 z3XuLaNcyqKpOIoVk_XL)!sJ2iMv!_QX@vXH!vQ3(BaLuBHvK-* z3=Air_CwAafrJyt9+3VV0`fgb^62>yq<;+o`7=oJ@NrCNJq^^A`6n9(ESIB zXC4^_1`en^=)4|~yV3JI$Q% z>2Z!M1A|2wL>@i9K=$vEWnj>N%7f1zg6c=JA8R;+^#1|5zZ_ydsro_TXd}nK&`|-= z589sxvL2LPVC4d6J`SWVMUH{t15_Pydkk3}D7<^*7#J)nA?Bg`7i7*FIR*v|s61pn zA_KUdKsV=#90S7vs5)%z@h@@=3>%>GkaLqz^QnkDLO*B@80;@-yo20f0+O$SxD#}4 z5?CHf`iYTeV34STs6$VOAph3LGca&K<-z+aK?Wg}S99bU7(Afz==wqK*dx!tU;&i} zoxcRqjvoFXd!EQMFie1|gPg;J>R%QG28IhzdC)#HusKNXP*DIK5C!oEWSt;b1(*Pt z@1nrK@BykHG$#+1K+>P0z`!t}9-<%COaax`Aax-9EeZ?_4N!S(<>nG3dGv4qrQ;(C z3=9QO{or$)Kn7#BKiv5iFk|$8K;g)u$iR@$0&yRB9UN3YEM39sHyuR=h8a+G*vcgz zMFxfrs62Z51^F{ak%6HCDi7*1f~TS|FX6=?}D80Hgm4(%+)Yz_4K& z#D4HOTe$RN89xNg&m2)^U@%w&(GNa{3%h=lv=7qvM;SEU3DE~yGXT;CDnB6U2{PV^ zGS~^7=QUAbU9egO65!Ru5&@m{0Kz_0^q4*2{qkVTl`2-1U*Zb0tbqsqW=Vmrhi=;aZ} z{5v4?q4MDK$8edCW&Q?azKj|JL&iaf`H=PBAOj#6V~U>S%%LFEP5pCEHm z)EF2V4nfR;x7!^d>sdhMMT;5(LjhDCUVq>zFSdX>4~HS7!(XOR9W>I@7EEfr09(9#h|-5L!B28o*x z^KhvHx%-L+149B-9r)Zfkj2>CjbmOBM!IMOr7UoDyp3K;_Zx2l;Q076U^ER33Ex4aj;>Iwz(c0F~>1v=|sHUPAl_ zUY`px06CptS3Genz#;RDoM$hj|=`3t13Mw@|w18NQ~bs&E( z(Pm&!fT{zZgNN=;NPUO1eene3o;MKpg3rmrr60>UA;^9e9R`Mgj}ZOfbM$cO$5Ec8 z=rAxG_zckxK4*^v{h;t(qQk(T@C~9L-hTj@0iEwTqQk%-0F{TVc7{qq<)45u4^$q# z{sF}Ui!KAhhp!Oxag~Rl^rEB7z#suN2ecmnYzrj+!Pmi{x0gWfPtj#yDEJOBA9Btg z0|SE#AE;LaUgy!G%fRpeDi7W#4l)>SF6ul!C_c7;3Z0)2^PtBgV9(cB;sfO0FS-m2 z7k)$ZgZ71htV1uCLH?D|V_=B*3sDC;9}ujLK>h%^FGP=l!Qmf7ANbrrkVa&Eko4-# zcYy_^O$t&53a=@83=A6t|AOZwAm<7q!V4t7MUR2u0aPBnTmZ>m(PLn^0F_6dX9mfC z(PLm}5Q3NwAI}6?4oxp2`V0&Qpz_%Co9Htz6bM7~L(VlsEC2Nw7#g7R@OdRjd}1x9 zTl5(i0z@F@fzLSvxdk)4u(oGG@p%N~UQvjC@IFM4ek}Fp8+`_b3^9m0@Og+Jb&h-j zE_@20rU8h@0E%}J0|tf%P<7DlPpIh&yxt3SeIH1lj{yTig%rem@OgX+J(j)b$uLFzir(r~{qX2(||jexUX=cxfHT zJzGHTQG}?2ulpg=-{ACb$iVObsvmN$AtL>P%oj0YU@%aEn2%@v9%sKK#E606fHFis zy7{1@xWtHoK|lo}4?6b|$)6bG5+L_3F=Al&096k;2L<6?kaA?AV3fdrce z4-Z)R3E52mGVcq>e`*l**wzP#7&9;!K;=Q_M&dIM6mKrZ3=9v{A?AV3kp!zpi#L$H zImQeOD>NbM(8C2J-($?c@B=E3-md}4uR)Rr`5SBx(zxUqV+IBeEr|J`^CrRaXypLN zoG&2%LDkuU6(IpV0Zx4k38NDZ2$1|5QwD|^IOIX;@C-=5DMUZ$JWjAqNc@BR3h$49F=b%b09A)RuK}`0 z#EgM~!5m@^+#S$#29h^1V_;~2%A>~*DEvaq7#Iqm^5AnjK@Pzd{u{8*i%cJR8BP#$Am=wRFfhbH#x+3p#F#TM?10LH_P2x0fvyh$ z*;8ZAz>wh#(GTx`K;jEj-h<-{q;3hwJuVP+@O}=OdqDZKK;P8bKAp7rFFfh!3%0te#LzH8naQ%bie)zgBv~UHPqhiUxpx_1x zSNM1yQhso;WMEhTl?SPZIsr_9_$f&8@byz*S;+da7E1<(15o|&^azy)#p@DF28Ihz zdC)njU@5peK`kn9(*P_C^4Aqh28IF;hcDej6(W1`RKWe#rSuP|XaG^U`9h7#Jd;^3Y={!Si*HauAjt z5&P$QtQZ(>_(04<9!~(d859m{K<@E{$b-&f1=|KMS77Er>UmH(bjON;;RRGZ_}u2?fL1VH7{^9?9{d_mF=J)Q*| zFUaj)PHv%^mqfMmo>Hw3>r{*@Oil)hd|;3-oHX0e*n4v38;}52XPnjJUw#% z17tpr9RouKR2}F%U6AphdJ~dg5&bYo4g<@A*HO9HF)#?kL(E4Xp8=(#6j0>?l?R=} z3)Trw=cxG>6pm9s>JuR5!PgN%;{znW#g2jD1Jpe9aYInPzhcM0@Bk_gI`;|HKEnB4 z#GZj+0n~nDux11S3MUhL28IJrdC9$WfZW6!`40hJGenhT>q;c~{Ffnf$7`8W0q3^$Q8(@T|UwC?Q;lnZy0@9!2$iT256QUn_oCoT73S>OYg%8Jk z(h^4ohJaj%e(*WVAO~aGkF_2H#oH4{28IK95dHA}48*^ncmp>cKI1abx>T(H(xI?fCX9#Hl0{df@d@NfjV zKg5}VA)pxIe)RqkNWR3Gfx!VP4>?yFv2GmX{wdB33=g34pmU``&O#4Iko)&IGcc?u zf!G5&UmB(kQm%ulCUDe(g+cNA#+iZPL@7i)_`GS53}*a-`idCyiXeCCxG*rhD2M3B z6|NwALR=Ua1S%lvz~@q9w+Cx_1?ivS!oaYh3Zfr;ZZ&rO?tBxlk1t$tVPH7W4$%*9 z_q+3fZ|Vbu{}+(^Iw11!`Fm*n0`jMbD+7Z7R33D$HOPAO@CTV=t8B zF{HeYab;jQ0hNdEQ-Rt8(qDrlk3J3slAnVl4=)Fy=7Yj%k1GSi3#j?v^Rq#6nDL1< zoI&RQab;kLm?O3=A)z@@V6-@bnH!hc0dm3;~lM=77#21L+5a z7o^<)UYFzmTbBf?KTF&g7z8Fm)Pv652CGMQH+X!c0MwL$H#I=+UE{{U&@ly~4?a(W z6rN|?7#May<&oQQuzKf>8w0})s62e!18g~DzblVB1B1pii22ZC%dnTzSmupE;pOAb zz|b)hq91ggH`r(_I=zG)UgW zgMmR|KE!_bxH(7?YJP|Z149B-9)3;>R304v9t;c(Pqw#P3y?V?o(v2IYasHV zbI-x%K->pS_iap|{Ac6Iz;I&&L>>72bC5!aI!JpQ;t!nbG-^B<7%H|y^rN@;LE${d zlYt=vDvzx_xW|)$Ap$B7U$+KYJGJ`r+f*ATyxn^~88FFmyoWLFcoBrO@hOkU1@03=9tYAm+fwbD{Yf6dy~x z7#I?u@}P5?ahY?*i-93yKg1mPxFA?Dq&$A(#lWxvDi12Rz*10qKmB-fa z(D6p-2cPE-G60%xK>B^W85m|9fY@&bk^^BR^K(GvL*=oJm-T?m$0NT6$$a#A5Rm<6 zycrl?K=q@qQv}JsL6VmOxeW<}s`Ffjapnh)FN2U7yl?}H?dZ9RLA z4+BHTK}h&uYZvwSFfdd=<>B+bPzyli#u^_6h80lx9;i5?oI%%9D%5V_ji!eMT;*3!vm;1=qMVnIZy%=u1kCw7%o8N;p-QWDFNw!f@D8>IRh%kSo{$7gU{IqX~b5JVdP&~i!V_>j= z>W80HjTXbuT7&y-1*1yJ|f#C;KKlr`@kVa_v1B%BpAoI^d^uyPYK*AZ4jv@6C&h{Wr00TqC z1&DsgeFTVn0tyG600st+OAvX`eFPxuq3OLDJO~EOZy^B;3<{Sa>cICBfD}UA3G!!2 z00Tq76^J~xaGDapz~BIthqu$9`a%BO62QPP;VMKw_}&7j`H=P|yg!c9pI<=sUx(;N z?>~avClbiO;DAToB#?o@04fh3uZOx1q(1~nKjdBnL^y)vO9B}f5^g~32j7bTbw8+` z3JT{bfeZ`_ZbIad*G)qDb;$UdDQ28N0|5cSCZ2I&L2+b4*Dp#v(9tDXj_D+yv? zm~aUc1_$k2*3pSUKNfuRB_4?lMb zY7fYtXM!0Ren921m5*?3vV7LL5hu5!2=IewoFnHXDgfq7E<`creU;&lK z)_%$fVPMdJ%3~XU>_L);pSywVebt=1akiwBzeev8{lv19a(c2NAbjlM3T8|5n2bB*X zedzfTWR6J~1H*6|4?QfaF8M7#J=<<*~JQO2QZz4nXCxh4U07^RdZq31eVb z0M(Dp{3~G$3=^R8aDO7Dqc33$3=MeXMZy^v3ZU}X>^BK#U`W6t9}>>M5CE0O=Dw0} z1_lQ_@>9YY7!2^pZwY5$P=LzA;|Xbe>k0w=Uy$@;bDu~A1A_q6e60QlZIXk^W78iJ z!NBkVnohClFNt7acmS2hHZC>=NgkX2EfEY17ohsFwU@6%Ffbf|%42iimk0)i4N!S( z=8Hr!Ff70$ZxYGCFad`=D4&N!GB7ki8g!!2BYq0S?$j}|AJV=RRU~qT^ z@ekyl71Z`nOB4e`15_Scd@KRk2bIT`UXCEiqnEoN`=3NHFeE_r!^0EmACNptGy_8b zR33C@HB<^rf#g-985kx&0Li;VGca6u4e=jnYXDdyQhAdS&A{*gDv!;7ElB#& z$3H;kFNtPg_yE<9KHmwFKZ0aFn)AT(vrmxB$LjwW28IJr^WpV2*b|U`mr4u+!v?54 z`uScnb+H@VyTp8E88Llz*mxBHlukXxYr9Gh6s`PmS8$o)B}={hEsfkERNL>@lQ=)woDk85HX7*0UtK|>T^qh0vG zLz|#*odYr-Di69p2P_YFC#a_i?h1f~LGC>RvhO>@KJ;=C2_<`&(iDO_`0F}o!KNo@|kFA|of+UY^{mK+1`{CncNcm|Cl76^6 z*fWsydL@p5VFJ{B=<=ZS^(Bshp#drnzBdS@7qfiEIu8cYZxYYIknkT8KG5qgu+J0V zSl?I@&%nUI{13dp0e&7BlK-Z}GcW`|<h&uFq26BH$A_GGKR33Ei64)HLJHYiL{M=TMc`bl05vpKD2!wAb0a5F)+M< znghD83CZ1#dOuE8A(;;upK|0g056?EIyf2>K1-4q7#w&Z`q1k?kh_m0F)$cFV0ZwP2j4pd zl7oi}e0<8C?*oqY&mi-qAm(GUe+$Tbs64v;Apc!SW?;AgmB&_}e@SLwH~^K$R{n~l z;MZ@Gg3ynxJP1i)VAudPA6t8;B!z)t0aPAcKPbIUNnv1^0F{TYLxPN#fDXF`j}L+T zxhDm5ejFs6;OAgM_tk;q@1!s=NJvBEA@_5E`@`UUcOdycDGUr1P>)B zFM9lf(|;NRLjzPEey<2-`o~!gPXU=P2QeSi)dV{ct-J!ccMr(DP<8P2J80@a;qoMn zf#CyG9eQ~UaxY6d1H%KTJop|nkcF7;#o8VKneUR$z_368;$HOjEJ!{joq<6>5x0Cx zIs-!kR32NrFG*)$D8L~Pa{rNZ(0vsU^TGF|;c`EY^MhG37#IYUAo|hIsRV_yN(KYN z2B7gW(fgvCe zq7J=%3aZbhWHK-~K;=RA&VlW~QJ;b1Ka+vsLlDF~NbL;ihd|nc@cIU8egoOZlEuK_ z5DL+c9KR6#nC(fEECvRF2#9*{y>%c5V&)gD_JQ16lEuKV0IDB+uN`*%?tCAZQPzNf zl!5eb$zoub5CgFveD57df=K&8{`~^d9}CfswjUFty#TULB^$K98KNG1Pabyru$B)X z`%*yqlOXy*_vnGNL)(>D?VFO#z_0+S9(=DJNCT1n1EsGk*$fN~sSx`h_wGT`1IQRq zI{lK(z>tszkq6zo2NH+62b7<|?Oc$%WpWr8R-{AJVeWTFO&6f{olgz}14kxAJ^Va8 zc)Gts)(FZ@*3aS0NB!_{)Ar~SKx~C7DdqMs_lf%Fukq1!+Isyi)4ryHB zO%4Nt22>t=Umr*TX1KcZ9l#t{0Hp(+T+n%d5c9$J`C-?O^&AFJ_~hh*)?Y&OgYRPl z=_e3Ap!iyn3%bY*q7Qlh1FT*K<#|wioylcju&98j1KkG*G9DVQ80idT?w?!+h98v> z^~mR0BAW{eSCu>l27xMwI^^?EK=YL#d6zr}1_P*k7h1s&l26HFVE9lC(GR{y5acju zyny6e@)#H{)Ij9n>rRm5m*g=pJb=n$>mMCK(hpxZ0M!o)_a{jDi4Av_%JB|t*?cc2j8~{4R26R` zEa-s9V~dXxkoiz~`1wc#@&VZY1q=))x*+C)?>htq6cPHK6fiJ+=z-`XHr!0OSr}Lu z7({iUv>G=H!z)GxT`?%1pPPk2hLJ(`I~NOsIs=33OD-0MUPcDlyId>`Cd>@F)3{g| z$`}}Qd$?E_9xyWKwsWyCd}3tKZQ_EMTMd=ZgYwg%bR?7xg3+8T3_lqebUipB`V=`? z7&bF7$cl5aFqAMe=yE{$M>rtzd!h6;4v2e~LHYAJAntAFfVj7k1LEFX4v2fzI3Vto z;efbToCD%sA*g6h&|t-^h+rH2uih~ zRhI^(fw(uF1>)WaC|{a|g~6PWL6;Az?j17=!wW_R-RH~@eXp1x@^_ga z{0&SH`6W<(HXN36wI3vXUI~gJFU&{z_ ze;Oks9Ag+E;SfP{kx1H>I4|1*Qr+4KL*;B3K=dpBf#?_f1JVEQH$?x{-w^#%enZ52p>*4CW^g_& zgYxr#GlTPK_-|%#KK1;~49=&vznQ`L^xH3Ha6WzW3*wIFznH=K^wBSfxwoP6=b-%K zPEeukKz z0Of~5X+J2f@fl*i43y9JnHijKet&}a|Jx^s{L@bmbEkcT_^bINM7;1LL_F>zB;A;P zgru8~AD9{PnHhAae1ORJLg}^-koYKr^7B7H;v@V6BtASpK;pyp10+7ay@$ldoA(g+ zJbw>~k4Ntz=H7}4%F~rzF}tQU|^8l{f3z# zfq_AH8LHP-9m>GUEGU%GTfyBSo8;HADp!~0|nHdBb7-ZkQhKN6T4YB|B zYi0&FW(M8MuOZ=e6e{2U8e(4dYlwMCP;n!uxENGD7gYTAD~S3{uOR9dzk=8|=M}`h zzE=?Y+Fn8Ii+TkK55rfG@YHz)2~TyXdIhMsG*ny+D$WlT=Yoo}LdE~RgqZX5CB&RB zFCq56g^Is`ia&;m-+_u>hl*c1WG7@&w`@-p3I8pFV=vf9(;3e;!Jocm%P32b90@5ybvgk09Z+^bsVS z7C_}^Le1%c@>`*FIg~Dd(h-lq?w0j>1aY_BBZ#|CJ%G6LzypXo7CwOFx9JZc`K<%W zk9YuauP0QU6O^`wit9o7>QGt%DlP`)^FwJ4sQAD85c|GE>96-7`Qpeuh&@~HLFCs# z>E-tz;W8b{pKuQnE}c;I^-%E&C|w8@PlWQLptKK^c7@Uw_aNb-bq^9Qa`zzNGW9OR zJpp$i?s2>eagP<0Hogmq552pP_|SxkOG9Z9C>?bNqTl-tM86A^w!Fj4aFdZiR~<^T z-eG32XJpX5e+xqQ-(qGEVPw#~coRZzyUENT#K@q#=q59R10#d3(M^cC$~PhA%0TIz zHz4jVxB-z*xB-!mgwjDbAnx|P0SQkxsJQ(NNO;QMU}m_@$e_!9gPEa%kwMq&D#RS+ zs}OT!ptLAdoDItVe+44{;R-XuEk*|2#>)_WrI#V%c~CkXDjovm`$B0qsJJ@$R_(}L2p9f0+x(F#R zUR;Ef4+o%h%teU*tu8?5&~wZT<%|rvPUj%%WX?hC;XMa&4;z%;aF&^&64bvr3vr*@ zS%^CGvk-L#P}=znB;FfNF*B5b%mvX547x_AAnLTCv9bJ!7?j=tr8h$9#ZY<>C3^zmKCu&!bhYI;#C=PSL&WDo>1j~$W+=Y~N|!>#)1dr# zC>?Pe;=bVH5cl~(#Z8Vw;;Z=>GlL@|gRaCeh&yye^%5R6#4N&o7C_e{EhfHH; zSi{Jmdwwd!o&!@M_UwextD*D~C_N2I_e1Hhsmu&63=Fa_rZ6+qF*E4Sn!?QB%)lVq z3+3lcVP^1WX0UaHinmT?X0T#r(EU0ILYGfsX6RyI&<&r&%rJ+6LHF-O2>;1M2!AS+ zzBmCAZl@+d+;?CCxV@OWc>*(oAv1&S+zHGK^~?;qMNoB_P<8Q8b>UET4p4P`6POw7 zm>G20ConTOGBfD@?uYPSK;x2b6?En=whVpfwv}!M;Todbslvn({knm=M z(w}-D;dZ|V(oWse15vlWhnXRQnL&4I52XI@>w$z{J(OPnRcGG=agRX{#66l&S_vvH z2IccZ>95_)4DQSfx-Yt!8H5=abdPsK^zZJ5=-&dR`=ROzpz?`O@hB)A3>9~W@*SYG z3{)R4)co&V5c6MmLCk*wrT2G1+%c~UQhvE2o8FcS;LhQTL$;{xyz#!Y$32{deR6H9>r*uN>4T17~J0bSD zbwc7zz7rB35}lCr!qo{$FaJ6q>7~7cnIV>uK{o+Pt8_rxmF?}!3|kl(bmO3OZW|=u z$F@PuYhz}3%*dcC+y-%HNh?I(wiadvM+OGjc`eKg7R(H~87&a;-%Swl$4wCN6-^NF zN%hPOlNlIvZR;SkP8~CYB{PFAAC&%G&CJls$e^}je z4?@K^LHVnp^c<*oFO=T~rK_qS;gnwm2?xC@i2uGQ6 zi2XY&Ao0Dr0+QbImDcoQ2J3hMEo+8e+EkL zgVNif^qg{teHrDDd=^&@$!GphzD7ASg9|f*u5dXs!$(F2-4A7u{CgitpM%mn%a|D) zm>G1-%a|F$m>G0apmZ2WoPj~ttBjdp0V9L1Wf{bsMrDxxk1UigRtE8(U>U@JJWz2~ zs5k>u{C6ot|CdroxIZn0gy*?ZNce4m@>iEa(&^k%NV@HV@*7Jb{`D<|gs*)m#NVc+ z5Px$+`7BWW*Aj^Qvl56shf5&k zhsqa}K-`&B0&!r*B;P+Of{0%!f`}g}f{0Hqg0#QF ziy-0PSp;#HQxPP*Y>Ob_WdRj8go^7x#nqwWf<=&UV}Y9gtq@}0^FoMyw+bQQv%C-z zKJA5&@To0?gijun9|2Wo0#&C5m1iqtX0T;u&^=KANrxK>Ans%@faJ?h`4IX=K1BQ) zlz#@w-v#AwfbthY`O~5N4k*74N|!*zQ=$B5DBlOlcY^Ybp?pm!Ee{nJfb!X({Qr3n z_kD%Zuk#@8yaVN5g7ObT`8%QfRZ#u{D1Rc9-wx$BK>1}*emayN3+4Mk`7ThtDU`1b z<*Ptx(L6}{@S@67qp7b?cz? z@-$`!9ZqY~l-7faD?<5FP+A}!QvQFBgOtn9;+PpGFfiyIj$;N@6}s!=Aofg$%C~{U z85nfSpyK&Zx;h48Z*~kseF~H|h=KS|Du$WCmVrTbS2Qz2Cj*17GL+sM1<|)I3Zid0 zlwJ@8@#h36zcUI_?lwWy7emE!pmb^!#2=1P5Pw)jLCQIuD2V+EQIK*~F_M{~hk-%& zegreaT1E!lL*bD2#rAM!hDb&R-3d^>OE{!mv^)&b{;Gk}r$Qm^k6obW>96 zGXyX*=;lJjlc98A5G4J%2SLKmDhLvO#!y-(2$J491DF}EF)+xM2QV{)Ff-UD2QV`P zGc(wR1whidRRBc4b^t`b3X~QMU}o6Lz@WLFsu=y4#nTA(ojzx51a0As*B|^JQj; zVrI~F^<`#AWM;s{1`Y}z`mZ;{ofo|!`ShSS zGeapegYHIeNdI?{H>4bC^k!x#WMe_3SN-<>%S+Y{Qm9<;otOxv|l!RGBb!U zFvza*gruigo)CXbhSEJy@fs+<6iVlLLgG0SDjx|I4}#K$o{(_V@?>VPW?+yN^@Nmv zpFJS$ndcr5d-i!SGfZM+(B0?(3Gca3@m3FrzH$$UIf)*S{&0{7Bpq5p&EbQpFK~yB zPeEy6cSw7S#~qR%f4f2WZ`>gK+fe=)D1SGUzY)rx1m$-_`I%7uCs$^MT4n~_bFPqj z!Oaz7uDvV7Tn#AykPAfJJQs*M4i|_zMi+>>PtFj2lQTqJoHIn-O(%%>B`1iw!%%*b z6GWYz6GYu)M`i{kP`}v`lFo{u{5}U}24w~YSx+c!4y8ezACUM9dx-o6D7^zpFNV_7 zp>!XVZiUh{P`VgO$3SU+DD4ELO`)^~l$M6lf>4?rO8>QkxZ^W~&V6MENq@KOAnD>V zls;m|%pd_upLWa)k_-&Jiy-{mNp{Q(*31mLjdqaoslpC2u2pOYNgug(%nTD58FZ8F zm>H}X7-VChd>=bVeP?3_8ILuCm?x_Zr4=Fe$couP=6OMbagq!SvY%`r_H4FgX7FKV z&|PN>nXg=7%M6~cTny#Uv4xo11LbGiLj2DaO4U7!B5m3Ghl+S7n39lbk5c5Am=~q?|@mo;-Whi|HD!v!W-v*`EL&XB3^0C%uvk0pqpdN%uvd} zpc@0FTMZ%Zur!3IXEcDQ|E3S2Uqk7O`Vf6P^dahUbs_Ff(1o}=5=yseL&VFpA>#Q^ zIs+;m0p$lmX?Li&Ih1bzrDtkE^7$k!NIuVk^51Jh%)g@vG5;!*o~i*6@792bw?OGy zsCWUCp9!TesxvdxGBW5MREOx>q7Kow7D_LJicf>``=N9PRJ;<(FM`t9Q1Lh@KO9OQ zS7T;a$H<_&NrjnVJtKo|kqV?7&QO7fM?v{dl_BDXl_B{m6Uq-zhRiQ`LirDrAnv`U z1aa?qD7_ylz8=b70i_p0#V11fT~OLhk(pr@BSWqogqBr-(y~xm3`+AuX%(l@0c?b9RDkaXHE1!<4^OF`5-NI}$FLg^Qh5b>Lm5b;Y; zno$x`zO0sj_J~<*$X(%b?=Zp!|L)-2oM^ zgz}4^bT(8x4$2RQ(L&4&s~8z{D+M9;=LkaVPleKPf{=b`q#$G*B?v0+EeNTb#KfPvL>I*SvTj?I~v-W(G?J23-RvpP2`;9;bpE zVs9}wWPBr!8)9BMR6GeP9t#x@gNg@2#eJaSuG|p!m_hmaP+Ad6OF?O2sD3`Eeom

    Oiyh()DOQNNysQvD81j~98%ig>VPcSAWY7(N!^9BEz#!`Y6*q;_LQwk8YbJ&-OboVPUqjTtehpE7 z?lr`o{jVYR?10i6Uo(NKGTq6qnZWC#e!gG=uSYuif(g7{X&aOdc>$4Ed;!sa>p6s8 z52Zt(wB~ar@Vd$0&mi)Tp!AMs5cjNm260cvGl+XCpz?)K+88RX0_Dp>X|ZQa;B}B} zQ2zg?OyG5pFP<`i*FoNT$^>2qdG09_cpc;#D1R}Op8b>wyuP#VDa2hVPnj5e7#MV4 zK4D_`&%mI&_X!htedx9)OyKpQ%c1=2ClGU!ptQ>qh`tApA?96s3^DICl-~E43A7$G zck5#&@H|cPV~G9|D4p{dqMz$A#Q(n@LG*uy(oY^SF|1)=ki83~&q3*kM-cTMP<4(_ z+UgM#gC7Hft|^qS_lOC+o>lV^#C=Loap^~p@DhQl=ZA`acnGoYC6vAer7u5(n0xLa z#C==uLgH`3T}b@RhVmyu`EF3YBb2WL1#`Anta(1#!3C zEr`A5w;=A8y9v=RaucFI?*@dQc>}^%yuk!srzdd(l75Au{Kwas!2Q*g*CFvR>pCPH zyRSpcZ-LUa*CFXE7s^k&4zV{Lsy-Ad?gypqq2fkRzBZJWxeiH>Tu}S|U4x`YlPgT% z`TF~pA?}%c8RDLl^ANu3c?kc~87A<0w|}RZ7(nxYSE2NT(~$JkeH!BKr>7w1Ej|U& zpLPnO-{Ta-e-@`8>I|W@7F1jc$`^*x-%dj8yK#~U)TPipbCLhKgT-(r1rB;%6_EzYVH>^)X0z&pih5|HNaE@QynM@lOzx_JXRjfvVGi zs$)9_ao?At5cLO+Lfkp+D8ygoN14Fuz6*{*+?jS1Vqe5jhm7mE&kf~2J`7Q}{V)@FU3uVPh&vq)L)7U* zX*np(d6)^*mDas;hzUH-)OiTvzLG*MiD3^TgY3owObkmI8Dy6qfaKqd0}%V84lsfHu|WqQ;UI7T5)QBTL*(y3 z>9hMF?mMs#V$V(}y$LG52+E%grKdo}TcP|qC|wQ}&w}!kp|tuwCWfty47!W=GBIpp zWYC?m7vi35DE)a4q}+PB2V(!VJ>YskcH16^yB0#lXF+KTsCq*vUk<9C7b?yM75}~) zV$PG@5c6;ChM2z>Dn5TV#Qc7!cn6ejgo>9y`MFR!4JsZ9YEply3^9KkQ;+ zILXMMyLK1E{$;x$_D|adaaSQ!JPRrw1r>LPirYfPrJ>?%J0RiqdK-k^v<*_8{ND=k z$NQ}i^It&eOIsoK?uGJKZH3soWGfTH3DEipsC*<;{>T=Hyu%iVKFci-^VV;Mh%;}7 z*z30mB5uA3BK~G0#GiXMLc~{Ygosbt2r;JvDxM7$ci#wcuL)FK7fQe004Xo-Z-AI{ zV*^Cp2`K*{lrG)?F*g&+58D8-Pjv&teZlJ?@}BD<=9sOA$g8bq0?()XTL&rspRR+L ze{CH^-FYZ|VjZNs*#YHmTn8y%7p;SoUsKjW@?pn1Ncj~9HOC*S-UCWILe0^I^3|Z` zNJ7l%<%62T1U2XWT8RHIuZ6g0-&#n%DPGIO@Rf-{HV(=chVnnJVPY_2V32*b2I7zF zYaseAKtC$$pF)-+ETm><2)hdX2i&sJ1-wM?i0@bI!3Q}+IL&cx0gqXKzB@=@U zGlTA=l@N1#S2BV3^K`6)m{+nAVtx{oAH5P{e&9+-Iq3t{=ML591XX9b5)w|@E5YF= zD+A^8tc3XI#tMl2r&d7fwF4_4?wbbX_e1#&P<|SeAGU&t;UQ?<&97J4 zzs69$4wP1cii<+|d{FxPawY~BMh4x-%OUQ&v>f8z9m^r^m<6RXmP6cYu^i%Fb|`&s z8N|Nx%OLijfYQsBLDZKmgQ(A32Jv6gGKjfePS{q7>Lur?JObh}H46-tFA?<=s zb0GAaIZWXB$NNzJ4JiNI9Ekb@5IT3|97uS~nga=s$xymy4mA9s{L(p)@Xv#)kB5p! zKxxN0ka#hk1Bn;)IgogHJDZ6i7c`GDn~6c6nL&5SY)HJY&W6OxtyvJdXF9~)QBXQ$ zI>i0%P`)vg{x}6<&*Lc&d#+7^Vc|B5c=u_h*INgpTWngjYyE#2#NLJ+}{1{!QzHh`04Y)YU-w zrBFH#DxL!6$3p3_K1lg%-3KWLh58`v%C)@^zDF;_Jj-5)`9@G$yB88q(onugFC?Cr zdm-WUwFeSTFMA;Iak>ZM&Lce#b9VMX^36&pe^C!ae@hP}o}P3=;%7IM?(T+|XWIp7 zFB)}0`iVMSkandyl&{bQsdxFI{3o4|c)H&SiKkng5c@B8Li}|E%HIp6w{=4NwGzso z-wAQo^iC!QBL;@tW++_+RaXpEm)yz3V93BA8w85)fkn&Tb15$qSbU?~arVdE?`MDj!zuFE7r(^99`}afX9qkbJ zZElCSZyi*;t{vjftaeC!n*bGeg_>vG4l!Q`%Ky;@@%PgGVV^6N4fHgKjmHFVzY$PqY% z7N~iDnj!XmZHCzQz8PZQ(`JZ!ZbQYdHbd;Y08uY{6iV-e$jkOLL&7nz84^xD&5&?% zZH9z{T{9${%$gzTn7oy)747&sUhWM@?~F>GgI(Cvou%d43f zxEUC7PggN9%wl4YT~q~8msSPIe}5{O7`&Jmbk9~o#CKLg)N@rbF??rYusvA8#IT8p zL3cHj{$CF9=i_on__{&)T2Ovk8N?o^GKhIfWe{`t${_Z2l!C)ov=~aiD1q=VL+R-y zObnYD8FV>Im>3o_FzE6WL&|5SVu-z;iXi=z(?t;Z*M&?B;tUM3PYRhBL>U-lPZmPN z-J#<53Lx^=3n20*p!}T$5Ou{+ekzpag3{mfA^P4!>4*6c{T2C;_|D9SxF-ophd|}+ zpz``qaSbS~m=8(Ef>1tJJ|rFg$b*>kF%QCjl?O@pPxB!Dz73VX0+rvL2PrSt=0U=9 zVIHI&YtCb02msAP=0V1reW3cCp!%($`VI5I;g_obHAe_)4inUzXE{s^`HT#@M{*$X ztDOU>?--!;rfkS~U}-kQ{*Y{ly6ssIb$w9UJqr>}=2;N`89-_EEQorZOh`WemH}x; z9Dvew84!Ji84!J0P&yeZ9tq_KL20#gNc#6rgV5?}5d9Kq5dDHsnhPraI~5}S1xmk7 zg{XfF<==tQSE1r3p!|bSdRHnFc%9~wRER%HQkcN&FuhZl7!EQp=$fTK(!X*F#9Xly zh<*G}ngc5SI~gMW1xmk7hN!;_Up!}UsdJ|N91(d%KO3#9d_d@w?P`W-D z;%OLkx-0=!ZKTd+U;~JEI9!j4`Vq!Q9+Mk{T@!u4vx>l%s9h5GIiswT4 zX;3;IDjo#odqZiLB#67TlOXv+1u8C^1j!E~NlXlf7#MW7CPLg@mk4oRULwTZ=}eL?(uP3=Fy!i4b=SLDexs<^Lo=%=wxCG4~~u{|HLohKiqo@{dC4eNgfB zQ2q)iJqaq_3gy>9>8u1u`5l=6@vjY(HcWu{TMMdAIRWBtu>^>}r^G}2Z5I!5pI$t~ zz3Na}0V*yG@JN{{WO;5eIQkXdJ{IO{h8srO)-%0-5(8c@5E?`xlPd! zd#j;z2~<24%8!H6;ZSj3DBlfA+e5{TpnPp8tr88f_f!cA4AM*ty8FW*>Q;wA)cpvB)FTH& zA@1533bAh$lwJ%Kp9$qpg3|R+@f;{W6-pb2Lfpj}3TdA(LFscL5O*#Jf!N;@0 zgo#0li9t6XDjp3LUmgr`e?62g4Tkt5JQz~{sRTpnksE;!doDuhMS&1|ssbVQWCcR( z2@izCZ%`nlf8!en@uyoL#NU=sz7dpG4rBtakG&HBX%}A#fV7hjL;1@CAnvOQfcV!l zfC;?s*&%=lyzf~c021E6{2}gm;SX`gT7M?+e&}s}5O=SK(hYtPcSra^)O+|r)I0e> z!bck_E)EsH<_mH6NneOR4ngT=Ux>LiP}<&?iQyX)gY07;Ch&ThW+)x(15xJ#rTKjz z>Na~r)J^n;q>Bb`CWilv47wHGOblEM47yp~Obks-47&E-5c`e1A@*xSX%(orD3s3! zrP;k9{kz9rkpA5rFNpa|q4Y#3-Q)#H=M_+Xo);4XD-(lmm=`3xy}g*g>pGpim_X}1 zb8SJ5a3%&_BQGX~1SSSuc`qi03?>HM+nx~hS3Dv7YACk4iU${Ik$HKF3NQ1L<+NWEq5 z0!gnPP7w1Logm^59U*k1BSbs^N*hCIaYrVGlS~Y{?2b$fe;FBc-#b9!Ylj0we1!u< zd;(NF$N^%GwF47F0~3R;GL$dlz{H>r>ZjO4+_BvrB0t|AqJD-wBt8S}ApAC4h=2KP zApT{yf%x~gHN?Nqts&wMtRdo8pyGwr5dSb(L+!DIn77apB5nocFSCG%A2Wy0Tg)Np zVYWFWJxw%+nA-)V70n^~%giA1nPw3ABq$vX759enU7)lrR9p|rSBKIHP;p@>p9f02 zm@+Y}U}VreX#%llmkGq4%}{y`RD3R!KMhJ(n?S;&1jVp){8^6GI*ogYHEwh`fg;ME<-6gpSsL$S+ZY@NLx~>NcuC_ zGEs)euT+G{|5AX^+Z7<-&lnhVr^qoeSTQl^^2tt7;rd6E!&r$cEaNhXF>Oboibk`Vtsl7R5fNzA?_39g{Wueg{a@n12JbQ4@7)A4@BIZ2NLdvP;q6b_-k%R_}t@$gwJ&- zeE}+d49edRrPo8n=R^53pmaYsr2Z`DhQxa=NSuj5H-a1DZeMOlestxAn8;gqUN`0ZBje*qInonHY4f*dh7YlpT^ERM;W)=6^Pb zIVag5`u4Ly^3@us_(C>_{WIAh_7_0a1+qcfXFhC@aIgpI1D*2-rP-kR|FbeN@G~*! zer9E2ILgGJ`w&W>XJuko$;hC4oE2jKL{>;X)PVBESeY0!KZ$3sQP}Qb;l>s6?iGhhho`E5^2tv!oGcYkIFfho5L-@J= z5L%Xz0pg$U{~5vSOFuwqfq#tPb!UJ6GJ@9)O#K6)pZtP|2mWLPk6-%#fbf@pX9SN! zYJFz}x5Ms!gQ!pW3X$LOg%P}tb=?<;J|@ME{ou5c48g!cxyk7a{Ek^MA233AnKM~gM_ouMM(N* zJqzLM9f$bi%u$GV>Olw{cMu}qvj@U&*aJ~_eJ6xpyb}`s>^m62<;(N!U|RO-c1Cdd zau&kRJqn>^1-C=;|L<*(^xwPf4BjX53g@vWT;_g&^@vN;*aecAnx4&r59{~lp~WiK=NtX z21vMNL)FJX)rCT7zYP$7+d=u}8zBBRfT~x7ic3LhVW>D8l>dJ{#Qq=a8NuuPFRq7# z!*Qtip7o3j8Vn4w?duuA>rsoK;{Vn#g7*V_Ujqrxmun#5d2pSTJVPN!CZ!(aB$Do8x-hSFQ0^javr3`)<3(lelRJCv@4(q&LO14<`B z>1Ze&vWk&GjDbPc1!}MLDn^Dl&^*E_M(}!b*;S0-ead317#Y%-8Fas|WCZV1|Fn`3 zd`{Nmm5^||yb|KSV=E#4+YhC8K*d)>`AeX5&Pqn`dQ*j!jNo;1Vk;TJ>yWvi@^@A+ zg3pP&u!51n9+cizK+N5~f)TuLdD99;(0Vl4Nl<>yQbzE84jU+Kwv-XP-bNG3SAy~- zmNJ6Z=deNO+#gFI?tZxhV*Vp2eFaLNh0@2CK+@@cDF5kVM(}w6=N3cC$CHa8>EO^} zh&hWFGcxcoFv!k<%1?*NcR}Tw7enkVgYxsCbOuyB4$2RQ(g9F$XDHtWO3N>Xl)D!f zLFhA!AnrN7h!MPw?$9ELdp0j(1dqeDErOK8HH#qSa4wV|3Dp+@)#ne@=K$6BZ6QS8 zn}ra4ccJ`K3nBhEun=O;PAI(;Dn1p;?}O4_3mL)d|DzT_^aU({=<|fqrciNJC|?dr z-3JSyl+=^9>iQRs5n2A=9mYGzaMiU>Oanflryj9 zLduOZb0PV5#au}Ju@Fk9%w+_R`?1Vr1dsduodYSy-_L=R8xQ9|(*MOdkaA<$97s6L znF9%@UMN3q4kNhT=|6{&VJQ=XuKOHD25%+?UGq7Ra!G9t#9iW0@!zu{>L1O9$e)=F zk>5NU;?8;~KY2DJT#n6x$gi3O;j7PL1dqe8Ld9Rsgov-72~oFT1|x$S1B2{LC_M>E zcR=aJ8IbU;ngLOt4;4>^(os;_A4~%^m8Vh<6Dr>XkohqW~h8ElrDqP`B2&#s?G$;mw@sGp?tSV5PPg9LF{Rm2+0o#6CvWZ6CvV)AexCm zmt`WPJ@k13gnkUAFGK0WPHzi~gr zUL7cXu@BO2YlPB5eGql5eGqm3dLi_qUWoWrDE}Ok-USt31?4Y>(sQ8V{ZM`fl+J>R zM?v|)P}&D7ZV%;KKVcF?g;4p$-HZ$>3=F!N z-H`CP-UZ4ANc>D233@P}&SiHBf3>_A(%)$-o1F@IYI#Qez_5c6NAL(E^40x^G20>s>1@eq0~lwJU(f5$=0e;Wre|8g9}{QYqd z^X20p<}=1Y%nyo%nEy2rV*c|`h`CQgAoL9=eHuz@hCs}h4uP1@7y>c>Z7{@q-(ZOO z`oR$M8-pO`JNQG)kMf3?8{q|^y`i)nl%C}YF~7$XVt$b)#QZoT5&H)6#;_ zvQU~AN>^(_%uUgRm>Zx8F?Xc~#N2KTh`IOGA?9|gK+FwMfS4C551~DvbiW)VUnt8# z!huH)V(t%Fh`BptA?7ZUg_v6>3o(~p3S#aCQHXgPMIiJNDE&qlVs4`_#M~@lh`C|H z5Oc+ZA?AV>MS|AF-4%kED=)+d-d`Xt1SvEsA7alWen#*<;btgZ z300o}RUZiz_lMG+Ptyo}&|>gRYF!TZ!VK*g6r>3XPqDO5fjD((ZN)u8e+Q2Bp6 z5OY66>9af#^AGbt%wGx>p9Q5$pz>Kzc^{~_Bb1hg$_ql}KXXIOe*vWraYM}C!3{Bg z7F4_+N@qglYhJyg5|O8Y_OU7+%6P;qG}{gnfv|1}51{IeVo z^AADkIZ*jYQ27$5cqWu~hRRz)<)xwG0#N!DJH-44>=5%0u|v$?4y7kT<=dh1nNaaK zC~X0i*MrInK*d?1^nEsn`B&K>=5J?%n7;-}w?XA=pz?80@n9&e3zb)f%Ckbnf3ZT$ zxxxxD{}e04{54SVg;2U0Dqjed4~B|+KxrkYyaZJK7YoGP_fYyI3&i~WED-Y-LdB;+ z=>n*H8dTl`DsBs7C3F^Vc&&%%2DqZ-deaQ28*ZyaiNT7fQ23 z<^M84^xtQKn12OIuVaFkzXU4Z1{JS{(xFg!Z>YR3R9p#4|6zpa|HKF}{|Y0-{F6|6 zF;spgRK6N2UI3-Npz;n-c_pa0IF$a#05ShL1H}B33=s48LFvg*`A(>OHdH(TN?SqY z4WRNuP;quB{qR2nxcs~Rp8;I{?flOGo{w1vr8}VVbx`>PsCX!p)`!ZgLgm?^;(z`@ z%(?atV*Z(b5cAhT#TP^ATBv+6R6YVK?hB>Wq4Kg&c_yg%_rDPHFaCv?fBY}R{54SV zg;2U0Dqjed4}*$(Lutjo3=E%`7;L4W>I9(bzW#xj{|ZVU`2(?M*B^*I^P%EXpmZKo zJ_Rc82^F`4(!x-APN@95-w^X3L+QQ0A?9!X4KaTPRJ<2Tr$gmqq4G{padRjw2$g4t z%D?#qG5;Zy-u(+={>EPr^QS?@yP2H zg3@2ULCk;k4PyTJZxHj3K4{MJcBp&~R6G$%TSMgyq4Hu-ac(I6^b5rN+g~8&ANT?>e=C&k zhsw7?<+GsT@le_lDz6Wf7lDd%Lg~k!A?Dxw3^9M-XNdWmp>*eG28Q=c47N>Bbrn!` zu~7LSD6R3Cf#CxagRLS|oj6q8i%$^q?|p)pzwRRgc;0K}M+We`%A$`D`({GvNgo-& z^Te%CejSu9|H!}qx{odRBLjGT!4xX~{R70D^B*AQoPg3Bq2jBc{KX#_!1Hds9~i*% zlFc6&!0q4?D4hjW9|%?N1r>LI(pFG;W2n3aR9yZ81E?LGD+!@xg`wv2LTPp={op;s z-s@0$`+Ej(JJ}7&w}sO3?->|U85wj%-ZLe+LP_ukRq?R|=w;8FangLHw%* z<@3ISn9mNS8KCk%-$KNnL+OW5`WBQv4y6x3>78#O=B|VCmqF>-PFZGXB9z_-rME-r4R0X+TnXjRfYKA8;+;@_J(RA1(ghGYH~tMY9ln92S5>G!IVk<( zHN^b4Q2O+1NIV{V4T;B9Q1SUtx)Lg%50wvrihDw7WvIL)RQ}&9i20wP^x0Ps^AEp* zn7;xlJ{L-tL*;X!@cPOn0l^2J~|9J^9|09$>{SspS!Iu#8mqEp6L+Mhed^S`* z04nYZrRAaWqEPu?FCgZ>htelsK+NC&0%HCWsQ64MT@01agv$Ft#hszFEL2_?D*xj- z#Qe8V`uKB*`Fo#3%wGf*pAMySpF_&IG^n~5s5(ceycv|{c@8P}S)uBFKZBU};2Ffe zt5ACVGl+dlq4Hf&@p>p736=MU%9}vNHK8;!RQ~5vi23)PLd?GmrPn@%n7~5&c25X;PnMg4b^3Z2AKR@cfh91BksX_aXe~`w)Hzl=g+vW>EUbJ&3v$_aN#PLg`shx&=zx zK-KNL3sIka7gFBD+=b{1h0+^uL(0KbP`cwb19*K?+-->Zz}pb@UQpT@DsBel>qBV` zsJJwgF9M}`q2dfs{?A(w^Y-0>n7glphJD zRc}H3B?qOy-h}YqLFuDVdLNXoy9sfZ3zW8n(q>Rv5lVl)0STW?HyFU<@$+vmfXCw* zZa~6$?R5r*vrG)SA=e@N_tzlwglh~87ePytq5S5n5OM9R3=HR(7<5lvfzS)DK=i9$ zfym#x4AHmlG6Ta?CI;Qq%MfwD%MkkoE;BG(U}Dg{dmBrpmaQxwuI8$7a;ciIS&cXk5Jn7Jj7hB^AK~Dp|lKC zoFB^PfYOXm@h|5f>fb`?XXha1+=TKkLFv;_@qJMKb|_tcmH|9}{rn8Xe;3a%FnBOA z=pKXe{m($;kDZ3l8c=%vDTw;EQxNraP`>R+h&cO6i1_~#5dMr4ka#FR0dZgY35dHB zpmf)9h&sFDkZ>`F(z3@P;d$d2gx+)vV$Skokob%~2GJLJ6hgm00tw&wMkmWH$@0Sx^X43e=(9Ww(f9Na#JrqC5cO(Mdiz0$_>%(=e_TBP@y9tR zEqQ``yl*AC>^>FVvo%}h&e|4Am(U8X$hz}2b9kUrN8Zk#DmXX zh(4#i5PjBAS_3LB0p$xqX*Q@nvpo=ZDDGhZuOr>J8^T|)8)Dwf-4OF8LFo#pcqWve z1f?CJ;zm%uHk1~GiZem^zjr~*11&BCt@n=D0x9o9H$!N<%?#l6+KQVY?)bBb0le<= z#wG^vdd72`AnnZ+n;`PdQ2BVMydPBFV-o{-ADbamUUm}$c-`jdjSziC8yUdsT7{wf z#~UE&tZpp>c%A9@l@RxQTLGc(tbn*{{|boy*()IKDq8_@SI!EEyPTo&@=*C-%OUbF zmqX+qFNdVRGs_|RcPxjv>&`NWd$uiunBTq(;-05V85lyD7<3;jWnkcAV$c;^3~}F* z`4D%lng^lV=0VJ_mtkTBWCGo13Gv6uK8U(HC>_-YafekO#2w;&5cB@`Le#zJg}7@+FGT-b zsCYh<_U?t~*Y1Vrf8GPpf4&Eze@72Qe`^m!e->2S2};ZNK=l9ZhUov?4bgw68>0VQ zH$?x5ZUzQzCI;P!-H`Zf>V||vHIy!ail;;Q2~au`D((a2yFzLGZU*o=?7v-*@@{z- z#2qucAmRPJ6Jq~|P6qHg=yOp1!cGPT3nm8L$(@k&QPBy>--(?N{ehhj{YN_>{#e@q zF{iA9fnh5XgKlyMM4v|oB>x$9K=dhgK=e&*hv=(qhv;)_XJF7{V$d~ihv<`NX8`Ya zVQh!!``8B2m)Zu==i3I+C)UQm(89!^`?eL5p02e*)E{ewsPAuusIO^-sJDfxQ-i7# zgQ~mV0#SFS1)^?#3ncs}wLrqZ8%npdFo5?3Btq4Nw?N`8qZv}qbTmQef+mPLlNurX z@ESqVHZk19)BD?0N?9`sj)E4B++AO;CO^R9*(k7lO(&L-`l#ApSdA$G~9D z#Gt#i4iXM4>LB(lgwp+WkaSg42T3=vbqoxKS2#9D~GAy9q3P}&lzUk0k5y%u8c;TniJdukx&Z>fQpKLsk@ zRRb}<2+H@Wfz;#ot0CdOr5a-2(rSo%=Rs+fYDoO4R6%IgDhBZWg!L5+;B#c=R6x>O zPX#2sHB~^|ky*h2USH2t!2qgyb$^yKfY)^&E{F89g31{fJee4DP0Jzr70V&|-bvC z>;{pqc7f2}oFVjOXNbCWwh(n9)(~3T93ubN6hgl=hR`RVbgMDMed~-Mw2=|SoP2$V zekL7=`b%06`DiUj{Df&i@?oGBB!0Z0;+9&Faan1oIKLKnoK%)oivhf!;jbn{{d-LY z1}O%H+~=AM4AKk?vUfBg@>ihpyP@J6q3Q~u@;Oj>bxlbAR?vjxZ$T*kqXq-RDJBNp zR~nFXaaRLk-!&+`TLV(Atkqy(_{YegyHtaLVKNhg?p&z&R1Jvx`=IJ;H6ZDx1S*~j z6_0_6`$B0a4F>Rj9xDw7@O~Z>4F>SOB}ENLJ9oc2#GD=K4B++tE1~?k>X7`}uMWwt zX;ATabq0nl3=F#A>Jaxjs53A)Gc)K~sxvU`0qv7gXJFuAV33tphxk)S9pX=JD9s2J z|EdNNe+Q+Xt3lM?g7Pmz=`&FA{ZRf6D7_IXz68pj3#F$)#e1OqRw!+x#sFGRnk%aY z2}cpAIIkK5c)!FSRY*8|RfYKbjw;08hgBivSQAvfOqBt=-aiSdE()s73My}?3MtPd zq5O|35c^)JK>Yhq1!CV#6>$2?y{y6j-WPCO1!DgJ6$a404A~tj4B-768=>?nD7_d; z&w!XVu7%RYP&x-n$3f``C>;o;y;K;$`vR<>_8O}&fcFLHsW5=|1*oe);#on3 z0lYszQiTD$Kj5n}19*SH2W1BE{(y(d5OueeA@O)o8RFklP})Tq5)L|0zJxN^|FTI+ z5OHrMh)2|r&2h&z}SAoa%^d5HK^ zc?R%4glX~&;C%=^@(kd82o3TOb1I?gvgINA(28LiJ23-!QI!35@Z=@N(`xSOU=`GR>;Qb2Aq5K6<{xoR@@P3632%TFm z%>cf4p-LL!zG7*JKXRlQ!0X~uq!}3a85m?^r6KiCm^1_E2oza=X~?{i2UMSfGy?-K z14FI>l;)9!)H8pi7#RLAGU$Ghg5=j%QjmJLMhX&cc~X%2FAz#QOF{JMNkQUQMGE3B zSt!j575^&<5&s6IUrI87_h0r%Lh4ytNe1w`UVTZ3J*?so`nV_qc>j92C`3M06e7M< z1VYz|K+N?Lfyi4x#UBep!ex~(#Jy7mAnL#HF@W!>ddLUiZ-VmYL;0t9AmUSaAm+a2 zg77zTLHNB~5cA?WA+#JP#5`_Jh&pR_2+hI{Q6J3;;j6Gh_#asy`sT4f^mVg9Iz5GVWvs*N?fInHfM!5Or5V<>y1iXEH{%v={U?~f;UT*hN-u}X2Qxw1 zy|zpY;PWW8A@aGZObiSnj10O`OptIAW`g*i8)AMg3q*hJKSqeZzc51NUonF1&3(cM zvG+bB#9ddQ^a+T(>>;T9UPg$!HbLnwMu@#NQ1eP4`f_t2`f}5u_QgWwgQ4QSQ1d(> z>Sb-Av>`-Z_6GwbeXM|#YitXkbO8ec!&L?bz61uaJJ=$ibN~YbgC_$6p9cd2g9ifx zp92E}gF6EQp9KR0gBt?_p8*2{gDV3Ap9TX1=-diE1qKGtxfOf@Q2h)H44`{|`2?6D z=5j!3P@-XFU|{fYL9Z^aCh;14>_j(x7zH#K6FJfRTZrk%5741tSAP6$1m` z0!9XgN(KhL4n_us8U_Zw21W*kY6b?r3`Pcq22i{*GBDJG;*pVop$-&}j0_C5pm<|s zV6bIm;8S2^V6b6i;NxIqVA##Xz{kMIz_5#nf$s$a1A`nR1K$G%1_pIT2EH2%3=G@z`$^gk%14C{w^{y@MSPCFq~(Eq{B;$41Az;c!3d; z?rfMK>CT=BlI|RtAnDGDi2CcXdfiJ<50pt}n2Pmxor9qcw zF)}c)J+OetAAr&epmYP2PJq%5P+9>>GeGGF=1~1mdI6MffYJ$2+5t){KxxpWSYZ3j zp!%Wo0w~=8r4yjE1C&;P(x6KK!1_(0`l0j!DBS?16QHyMlvaS!pu^C?`c0tvq4WYM z-2kN%ptJ*&R)Er=!_L9_jiLIX^a3c|0HqV4v;&k@fYPAD*TMRYp!%Wo0w~=8r4yjE z1C&;P(x5}4!TJrM`l0j!DBS?16QHyMlvaS!phKj=`VFA^q4WYM-2kN%ptJ*&R)Er= zL#Dy{^`ZKq^a3c|0HqV4v;&k@fYP8tsKNU6p!%Wo0w~=8r4yjE1C&;P(x5}H!TNQf z`l0j!DBS?16QHyMlvaS!pu!rgUk9omN-u!Y4Ny7(N;^Pl1t<+FR2Pmxor9qo5!TMF9`l0j!DBS?16QHyMlvaS!pv{qB z{VGuXPpfsp|2ohI-@sD3ED07^GN=>#b40Hqb6 zG-&V)tX~qUA4)HP(hX2L0ZKbSX$2?^8mt2Amw@Vr(hHz;1C&mH(hg8s0ZM}gxxo6x zq57fp0w~=8r4yjE1C&;P(x5>XuzoS9eki>FN;g311SstQr4^twXfOq=UlghzN-u!Y z4Ny7(N;^Pl1t<*~`~mA1f$E3S3!roZlum%s4p3SFN`nSz!1{%u`l0j!DBS?16QHyM zlvaS!purrlej%uSD7^qmH$dqGDD42H6`(X|Pz0=B5UL+aFM!ewP&xrhJ3wg#C=D7c z0qYll>W9(`pmYP2PJq%5P+9>>g9cH+`uU;yq4WYM-2kN%ptJ*&R)Er=K^3rmKB#^u zy#Pu#K*s;$htdn6bOV%5 zfYJ_7S^-Lf24BJYxuN=@^a3c|0HqV4v;&k@fYPAF0bu=HQ2kJP0hDfl(g{%70ZJ=C zY0zK~SU)FJKa^eor5m7h0+e=u(h5)-G#LZd&jHmBr58Zy1}L2Xr5&KO0+a?Vk^t*x zhw6vY3!roZlum%s4p3SFN`nR&!1~#s`l0j!DBS?16QHyMlvaS!pg|k3epaY{D7^qm zH$dqGDD42H6`(X|lMPru3sgUpUI3*VpmYM1c7W0fP#QFN1lG?C)eof?KQ{qkQ2!Z3gZjxJ8q^;K(V%`X zhz9k4L39Em#C!)R4eIBD#6g`x5Dn_rg6IPb5Ott_D~J#3pMq%6cnF9FjeCG-(D(+3 z290Zg=o)Tjh86}E2A;3X3<01($!1{SV=-W8;9~(PVK~msz`(}{(go%+tewEXz{kwM z&@fdEEU=**!f%A~cY`|R%nS?;t#V-b|4{h}yOx3Zpmhfz{WGBa-8LZe85j(jnZWXb zlOg6g)Ubj1H!2`}fo%}`nEN5>1LPp;A41&|099`cwci8ESC4||cc_J!ccm4=Pk`EA z3RT|#mDd9eJ}@&dELaM$FA~Ow`foO9@PV0up#rKuoeAO|gDz&Udry@>%rAh-zl8E9 zv_Qgx7i1m_1H%Gn_)dY^e*h})UJB8#0o9)}5yDr1@uB`PfVy{ABt+f<$}eDqxM#yn zMzDJpYe3{Pp!y$}K;#Sdfu$K_K!YzV3=ADm_n1KW0{W2n_X&fjSKxv8Z#^{pBB17d z0u9hVP&Z&cMK602&-(WMH_E4@nO!AoDmF7`|M9=&u097Y75w zPbhybEIy$2eFdd276yhFQ2&QO{nr7Ne+V+4nSo&uSeGcYi$ zZi9sP@v{*7CQ3of+WkAs212FmXOrDqNX1}7+A z05k~5!NA}N<$sz4(H{Wi8$sn0pnSmu1_pjc28IRKA@OZ&3E>-n23i>y7?_hF{0+At z@^!foegGdN{Ut&58$jiap?rbI5cNJ#^$Cw4{Fr=*eurlezOfX9UjWs=F&@HS0M)-v z0LlkBl7WFCZW03nKN|ys#}r6-A5DSC2SD|Qr$hJ?osPvQ{%f*=Tgi7teHU?s%-=tKy=;4p+=2X*fQ(1ZnO?2#KH z-vAn*W?*2r2Mb>)AJh*7c})RY{_40v)Gq){bTBY5^h}2MS7Iu}zroP(5ip0iC%qV= zJ^*T;0hDh5<%8y3LFP|@@^>ph)E7Yc)q)WI1}J|r50q~PF+U7yzXsI)e|Zr315kNA zsJsGH-f=2Ket|Va|Mw{nz5tZZqz&O0tb>G?Wjll)U$|m0tkmCqwl!e1^!|L**Tyd~>LL!dHm=V>5{P2~hpqPM7=IF{~v&cZ=O6v-T}&=1U0Y04x*mP9U>2E zAA-VbAuojgAPOR13FR{cL-?)G@qf2a0C_zGJgtvkLHG?&{#Gpr ze*%=>%L?IdfbxT@AmvX4w7l&ohsb|`h7UK?zYMD(?u(Ix$Qw+D@cX7i_#av!{2r)( z4B8;>k&1=LAAr`6juRpFDM0PhhnnxO8WKM1!1;}VVZkhjd2Bim{Q}VRvpfjGzpw$K zeqRQNe}LhGEX2OW(DY~!2ho3%1tibF5D*XHgZg8j@^V2GgkL*>fq|ccf#CzReqIb! zuK=0|WME+6hKARKM2LC;ABcGiq9Obn(EK3)O@C(4{1uP_kyq-1sArIYxKG*?!WT$} z$V)@>g9Fq(7oh25LO4YJ2Q>T=q#*j;p#DpM+ULv+G4BJE|0o;6H;{zr=Y*yQgL#nf zI_e3L50HSE*9;BM2@@dvXMqs;3DEfGgU08DHxTpMq4_ldnttq|;d24XPlfUiK=~(O z`2m`K4WZ^gfb#D_>x%_Y^>;w&kBx!B0h&Jcc03i{PV>IqW=OPs5D|= z_#+D87Z^kIcc?-52~hrPXnh#~<+l|<<)Ptg1x*hDeh~fop!Gc{Te{+< z+mi*L1q2KX49}tb4_y%Z|HHxu%CCgE2kJi)X!>-3^0nh3?hiNx(eDn8uMePwCJYP= zR?zfo0FBQosC)yoJl|sg(VtKT39s$?5PkuaZw{^B4jh4){{+e}fYx{4q3Lr1v^-i3 z4etUdpATA}G(h=#p!yF$%X2Yk`U!xBrytb67ohP`2@QYHVFjQV2!@7d!Y7D(?pr|I z3p#8RB;N_;FZc5;8{~v(rkAuoj_zzLv25lcOK-=G@(D)31rr&>1_a;E& zdn&lRKEU8`6B2$C!S&+-hJ-s1J{LH@9AGd24frrHFj$y?+z^$ZLLpnOhf`^EvvzXDAk22g$|to(wScU=x--T{UOGa%-D2dAF{3~t?wM5<|RS- z4L*?Y<%PDtE;5c|_SK>lN3aL|JI_bRk~Izb!4-{B0AZ_tJC#q}Wk4bcAAZE*kh z0K$d|833nm#o1p3A!aWFI0$hF^U^s9b z!ha4ek1nJ^_=aHn7#IXV1EmZM4BMggQvuZcv(WnfLNP?W6tumh0S&Kpg%I~#fYxs- zpygu&G(Ua-=Pw3^3DEM&5SHGd^^+w(ME?V5`EvzYzX+&6?3)hl&pDJp!Z#h7o&vHU z{8#l5{RYJl{%WXy0(c?%??c0PUa1K*t*#p!M@fX!>D*_CKmX`I(V{;RCdM-w!R16`=i%Zdm^{6yn|u(Ef1& zv_GR!3Gp98HAG$wnjae`L- z4_-s~DbV!$U@3&J4Ncz%py8_xtzSMYgUF{FLj4Doe+*TB0m`ojkCz-^2sjG~-(|KS z^#>RNEbf z+d<3g4bb-Eb!dBI1Jr-X;QY_PzyQt9tkCj20h+(Uq2av%8b77b@Dcze3I+y-`Oxr6 zfVM}~q4`B&D#U$eu=)eq9=C(G{~kd5KMSGm{QylLp!FFbqd!39onhrMR6i56Jh%XL z|0HO8Tmh>8LMNnrmY56~kD3P^Us(_janDLvdj#sA0%-XW&G1(HJ=%ln z6GjGx1&bl_A>i_xfx!W^u#|y;p|u9$9|mauAp;tp4c!p)i=pFp6F>_qLF2bj`xAN~ z^1RUgwgS{WZLstSbx#^}yrco@{&&#w!~o<;1_p+$Q2#kV<##~aw*}Dh?mD!5+wc|= zeu1F=C>sNV0kph-3oY*#WJ27t8=9XJp!xZa3n;t}FkFC+KZSzF?+!3rFoBpi(-k6b z03Cng2b*_*;R9$vH3I{~BdGiX4#@aa98~@RH2uwkn%}?%k^cxTe-AJus6pJL1(kPr z2jOpk%0GaP-}pn#clZgBUk7!cfCz-23e}(R0K)$WuCEU;Z1@l1-vXC!2N({37H~5# zFfc*Ke;YsxxfvK3rb6TM0yI9CL+gJADE~Ng{KWxUUMkpt!h?a~0%2tNTDe@f8&ya5`22chlF0BC*70JXmX+TUmfjc0?BCba%r-2gF90cze& zXnIqCmM?tJ^cVomA77#7Clo=#1GL`?oV3N+s6Vg=!Vd$FpD=(I|AK0qIH-REHbUgZp!^NHA$(A^3$p(MbbR+8w0yb% zb=#t8Yuq*RDL?FKHCQ|PaIkv7eLkPL*2gtT7KMuy4L_Izn~i8egUX? zRZxBbln>gkz|VMqVZvodc(H@~vj-R)u0r_LP=3HE2wxUlpD-{y04)?}U|`q@jjsjJ z@whqA@~r?GUop`5*w6=Y|8i*iqCgN7$qWo%!2Nv&h6T|2_c1j51EA%}6lizyv>K!Cj!v^dI*dUO)oys`g(x?#C}z%eg$ZILJumh03DwT zg}N^QT7C#Y`$rd`?SZY(@vH|XknmxJ);AaWA?9a5>zf78@dhcV{~zc>!Xp-1pEMkT z@S~ya!w=B#TLX1p1FXD-w%;~D+w&gK_+(fKv2P;OJr2Citw?Oqzgz#IS;kN;_fPjI4;U9FqLjkn0fPsPG5;XiACP37CL)(W6Q2sh- z|49I9o*;DmdI40v3hKTE<`DnbLHpYepyQj%VeQjx5c8Kp)hq0T@Z*{w?)?DTz{0@5 zz)=U`F90p1U|?XF1|1J{cnDGd8`>T_0NTg^TEh?RUwv2#2_GY9{s3*#1Bq+^)vt^U z3<-@O9s|S7Mu_3YO^&dbBJ{TAnoIFfcGULHQq` zd|^le_a_(_41^%^tkCv*LLkI_ zi(vIxD1^Tm+8)^83*lb^kH0W5OaN^VVqjoc3mq?c0F_sS@%hEOfpCv~CvUUR%)kJ0kfb#c3>(>j={Ivwy zK6{`H36I&({)hu~{_!?6KRQ6|tA_FAA?nSb_0I&T{7h*641n^TpyL$PQ2$?82noL_(EiQ>=y;PhG(R&$LiFoG!&6~4gf9k--vDU(KL)M;FFbLI-a^aQ06mEN){-Kj|zPd z|38PSUjXGZLFG3<`E#M=X92Xn&V}+7p!{@b`uhOopMtg*4nX;)VEF?K0nqVyC1`$2 zXa)I}f#E$gy*_}pAA+Fa+W@VE z{Kw$&YX*h`Q1$1b`ESA}i2oB|d}wFfi~!^QQt-zbG_6T!5CRr=a6) z2D2dM=|bCo8_FQ|Pl2Y#2GGV)1_p*D(DvPjQi%LbXnS)5)IB*+^8%pq=b_=T0XlyD z9NfP;z~BI#U+Mz)pAIlwfb!L$?d1SLfuR68ADjfu{|%sx!JuJKaC?M-A>cej zzZi6UuHYVo?*}bEFF@PdD$w$o;TA-`9hx2%K;@5t^8*9J1*p6xw0t&z^8KOZMFF(@ zGk}J70d#&a5jtKr0XlyO+Mff8zX#Cy7!_!FvH&Xo5~`j7+CM%HHGczCJ_Vef7#I#f z`FYUsgA2lt_LUv9eb@kP&t3qp2V-DpfR49;_Pc=W|4;={e-PTAJa8T2e-$X-;TnWr z3*}$93gMrG#>WF_{r?m?9@PM?AA_Lo0j+BX=}3pVAG9AE#E*uJx7-Es7#I#i$IlF) z{I^hf255Z!1kIPQA7IFUt|#^e%@463VDNzQi=ccCC|?cA*MRaFq5KXg{}(8~u^(V) zI0tEv-vXr<_5%zrp#1-!`3QCf1_dbJ0MtHZXJEJiT~9k1G(NNM>t{Wo?RNuceR?w-BEO*p629F~_XI%e8}jrnh^CDN+9Ne&Q$`rub~vezXCPS0CYeE0|SE?RR4uQNcp-8>fQny2>&CLZy*HW z?}xhAKpnzg4>eDr2*UpfOKL_#WK*Q?+=pX~o_%zf!2WbEKC6q4!ZSNI9)fYhPJJ5MoAopy5hKDj# zJ^)(3_khBije$V|I$pgMn*Jw1>nm}ndnR~+T*JW70oA_&nttRx!24bxk_-$Cx7<~{t`6v-=WDrLE|@~sjrPhwJ#q{eM|(Z zyaSs0X^{QbaQ9tA<3sml!{yt;P|a%%N9C_W3y*d*_jJxcRlgR^yh~{Id!ebfN3)M5 z3e`MS$bNLVdqK<0k>l$#n*Sxx?5jcx-*=FGP;m3C(cEK%7QXMZP~F3Y79L(`?(ae4 z%c6ysJ{n&FvTqCS9s@N0u0XSo5zT#yX#NGA+lL%JNoej#NAoXqzZl&98))V^p}Frn znmjX_fArDvn>3pJJ!tBeq4C|LQNz0y&HwY!(${3P_&tDTo*BE=IL41TB1@ zp`|Y=wD>7PbKhMw`yLHE8DPqs7-%H1*rw9yIqe#K%YZ85+jN7boUrmSk3?78#mn=9Q!t%bF(tSpu_VQR)#40F!OPtGnqQTG@o_KO|6AQq~GO;Q2 zF)L0j$;r%h1xq5uMsZ?ZN>YABe12YhUVcet8pIN4kXiVamZVk$rB;bWag&kr==vKC^a;Lq$)@PbxJHwwQx*H0qb`qpwQ6BF(t(%H4&R?xC_jJQgidm zQlVy{gqooVBnpF4(=&@piYkpP-7@o1AY#t>c_pb8B~F$8#hxxc`N`R-DcFoKa&a-V zbS_FwEJ^jrPtQzF%zBmr_;|ly_tX-{qVzH>dBFl6CB>QP zkksp%8Q@(OfJL#fL2zbOs&h_aaWOb)B$nhC85{ZJCnx5BQ;DZvaJ&&#H6R%i#{gp^ zS65e8Lj#x8L{QQKrQv{J=`mKmBuJOvAr#Nt##gW%K>h`&=@b1Rdwu8ZZCi3RXj1I34tfnUCVfp20#XkKn&fpcO`PEulWwyR%oys;6cj)0OP$D*Rd zN>Is@nG8~8WC)IV$CQ+!)Z*gcg2d$1u*}qQ^!NppS|)IdLE4L5vHK=CGd(Xc2O8go zW-g_Pe;RriqM3cFh@{PR$ip%%!P zp2X0A-CRQh|2#;hN4S8H(FFAv8NhRYR(@t)daB2xO@8%czmzMaa;ZbbliKyHNskLy) zECw}xob!uPLB&;Sk!PA;YI16Eabgj6KN&z;9H7>cp?OehenDy;0WC(xpw?VwVoqjN zYCuk6Nm_nUu4`gZP9-$VpkYCzG9N?pq|(fsl=$TQyyDE_lGMCpG=mIH5%xhEL|B5< z&=gdVXC?<1WafbtS%6wA!8!TmsID?Jg!nhOBr!SL*e?|(jgmyoK}Bp)dKs!#L_#s~ zEJ-ag@k^~JfvP~!ZDX-!T#9#{rGqAs0QVa4+JQDL#a#Afzi&Nv1^GoyKmZG}VBDl1m090LO z=I23+U_&z$F@#oBoyH)a_@_a9Rcw+8YT;vZ5~?~wqcmu}4vJK$?_l9zj8YYt`{xCv zf;s`%OvNlB@hZ23SV0lJQNf z2rW)6!m1jtJB$oHi$jV^Q{6yem6?~0Y7t(oh9;iHko4e~3@RF-j)MlYkr60mLW(zV zk3TuJpd`Nt7C0!LHAF5wO+eWuzo?`boE~tf2gPDQVo`Bwk&z*IxB(>Kl3JWxlvx1o zsG~W?0^t~!%Dlwf%w)&By!?_xY-*7l4sr@KSHm0v^PUOVTHnNy2_nDhxw%ib3NEpbP@F5zPpn{KS;h6i7jCnw*oGh{GU|38}@!o_T5crp~yOS-KS^ z=BDCTW8soml89dkM&ua>mL?V@=9OgTr3T~|VD*RzsKpadln=_&zKJ;0KvF-rDu$@Z zi7zhCEJ@DL1CJW%VT>YEfQlPFQMDaV8$MzKO~C#f~|d>3OLssA^$p3#k}^H`yT7DpUocabpRt z7CmzdaG!N7rz@^X}p%B!F#H9=|*pZfBlno6mXmFZ>+n}K8 zAu$DF8B`uM>luT)C7F5YVC7~gDp5?rBV`eknwSD|ClNN7AgMz!A6Wve{6b6HptK1Z zVoe2=yV$LCPlb*z1gGYtL6tylGc@wg17!|K^$L|k4HH9M~1kiHjr-Yn{V~P)(2|p_&X0K*bGYkO1mds0_B&SW#+DYGQFJ zR3YAA2K7L|<1vs-iW)-ZzWI6iCHZ-o$$p7>`5~FPFe6cvS>Tg2GzHhVPMLX$MU{Su z*iA45HPApFOf4?Psm46C0Mxl5pv>4M6RRT)vDJ=-#-JL>ttdYi>_}*Mp?J;^qoV^F zrAUs4_jck-^NJJGu-j<>O1h9nn4xKLc4k3*c}8YQYB6ZQ5Na9T$gzO5*OEY{W7Zx- zYsIKW%s`2=JO%0mXhO1pjf0wn=9OpW!DLZF1LSwu92lro7hjo~nuArPp(%VUCq1>K zAQP)1kUK(gONGFt(4A-*nwMEvnu<_>;z}%W1~&;+A!g^!&UKotV~F;321x=(nkWTM>iT)wjgR< z3(w-*%a?{AvH?cA) z6+FD`l$e~IUX))7o#sN#azZeg-wET~bR@lS}f8;3`q=N2+<@Dqxm_ zhT+2!5jvsbmXJvG%`brKKrs_qgoB&)(B86dB0??H6m#Fyl0;;26f+DBk-E0nt$}x0 z;nGl(5vdCgt0ba&v&U}j*Z5p*S{;Eawg3hJkT*2REQ z4!RsPa~cw#Iblj+u0qY6XtIdlbAidAcp69WVONYTbHYr8xdtrQCrmr4jm9XQL1&mEr~&ZIi6)N7oM;kwGAB$Ws{P2B6Q%-YIV^Lci6doB zm<)=UI5H*WJKzM2PcZzI8ql}G1M5;%n7pt#U#wk z2~!3$12c_aSc8;CpmLD4Gx>SYRbLG8iJ++;hIr^&t@Ql(V$gIxLwq`DY^M`()5NPoY+G;x304r#g6SQuvv?$dvF9pXu&= z3|Y;UnV0SwU}TB3$`Irk@H(%=qV&?-)Vz{nxL;Br(>3w=knwwvMQDKvZB~QA6ErRF zoeWtA=xUi)nj4>-n3DrG48EcyDSCU+uS^^3`hWL`?bQm)pvX&6;AxPwa);hu>7Bt2TiQJ6T z#FW$`hWM1y0*3ek$Vvdvnl?}}OwLYBNhylY!zNRlS(S<+1JRn90v0SS&Ph!zV2FoO z@$tE(pcOzM7lD@Lf#{^F)S`Tb_>#op?D)*Qw0w})k~88#Yw3~_i&LRu@lohOk8P~P z)zBDCA5!XrtxkiE&oacrSD_(13|a;Oa#TriVqScDetc$nUVc$(d~s!7a(ohKjR8YE zC<8LYr{ok@=7LfLYSKem5d&H~30ic8O%FUl-Q1uq1|=0lU9(mY>qc7d-vfhdEPz81MDrtukx#TlU0A1E?DCQ11z zmEg6k=Dseb@y;O;7-|d+Kr)blE*vURD+3y@0Ry$yz@7!KR|G8_!@9;1yc!NXgytD+ z9PbKBJ}6#?Ew=^D{iZq_L3{@71Gr{pR%Yeq=Hk&{h(`lzaDYZhL4~k;VgYE0Fshjr z;L&8r++RRZK4{T0XaP5x&6u?(bWO20%#Em4S~!)arKJ{umT4y@XMzRV^gRe(E4m->->wrQ#wQ%1GgGv3}`J^3LdLb0^P{KB|onOGzk}syZ{OslPF3J z&3vI1Gidh0KQE`!6{-vx;+DRN1rSrvBn-_wi(M-UQj<$kQy^VKm;zJ_=)KC!0-Q2n z8PX7afhp8?sBVM@f?qy#B?43#G!PI;6D97Pv93sMTsy8$TMVVh} zY6>K<-4G_CIMv7i8Em#GxaL7~0_JKaa0?z(7=acopsR-TUp(``tE8Zz zfNf&|a&|N{1kaZRr4}S+7GX`D$f}KupsEv7{ENW(FBIG=CaBR6()R_WP$G4h2SKNJ z2>QSXsxr7FzbKWkODvICXO%_JTMNY9} zSz=}mX!#*5l2H{Kdlo|?I5Q~+TF`=%5q8y}Ayi1B1TDDE&+{lvPX$fg`R1p9HkyEA z7}b1Om_pnHQd=C7?;niSctaXj(Wu1%!F>wg`WZFz`xu&nmbs*Xm!=}sIM{c?KPfg3BV$yyTqHlvFdf{G!~%5>QhHGpQOH zB5TNXB|&i}DT)KUlSxsYM2cci1ernn3|Sxu&X@#DFaZ^&NVCoXScB6Nq{=5hFCALV zfhV7_Dh1U`i75yJ!L8jC?12taTbznshe29}pwSI1DZvnt$csyg@{$WGT?3K>ysgkdqS+@>)u10VqFU3j@R4)ZF;Y z;&@OG9G4mt&*$Z&f>zmM3ne2X=fsjk&@^sAMrJa2`Vm|s<1!aIA_iKWZi-JK!2*`J zjbNrOMTwvt0)D|J@fHE8Mc|!fuHYSEn3pl;q7YUASokNEBxdG8XCJ|{@}SL8SQbUPy1JHOX`KXw#6yilsRWHo zax38jRiL3S&}daLXz@R25G2?DrU~W_qoCAcP?HSo0@ut+uuYhqPf%>dLz=GOov^5$ zF>|dbDN0N(0Tp3hxdp)muGpOBV{8KHz`!QapgjoG9U%~tQT&84)(qaqfJLD(Xl~vo zzuYIaEHwveda7?`9(buBXcW^Gq6xMf0q!Btjv1I7s@2%`3m7A<6m~3u>O;{+a1SQD zzmy7T?1944oCFSz(oNx!N7ye60*TIARoIkK`TPQX$rK~#0Rv_#52#SvLqF&YC|le z7ltMQ`2}DTzzb|)`k>B$^%TMVK15>?x!;HEYAo3bwAL6jN(&h`fd(CFFqnJhB^QBK zu!ZE8B<6s^1iLbqR3elSP7-DT`30ppi6yC^zAR|73HC$*%Ao{{;$S1t_?KU>QM{os zCr?F&)(q@D2$7q^#8B63`Mp ztZFRXO7oIk^Gb>!BadjqNGMTd4DH3a=j10Pf~yJiP4_6u&A}^Xk;_p?u%Wi4k+m3E zc;*$S7L`B>aYPbx%P#`?4HUlk+y`yCdxFQnT|q}7fLeyQtuwTQwDlnxKog6^Xfi?e zktfz6DX^c=QY>2GmtTbFm!ZTg>IxEPBhYqY&?qZtRvZ+Gs4l%skRF?$LsWHYOv;}lpsps1l~3}2Y-4DPLC zi5hH0oGEyaC^aD2GY>ps3v~`koFb;RK?P74c(sXNzH>=_k!O~xc@ShDKZzPa-6S%# zCX;I?q(KU5h@dT9F*NW@0WHJ`0F7;tZ925XGBk6`1Py{CHu<@dYb2x`K&tA=HVIrl zP|F~c>Kwn5kk`6_3u({}PS3pJlA==ZAt?dL&~yU}JVY`EZCHUyqNYZy6EC2aD|B1G zp)su8MKKf2};Wf~;;VL3bl$?dMLATL8^>lorQ z^OH+*K(n6U)^mJvMs|E!VrC9vR9rZA%Y>kG!Hb)!VnJ|Z~@7Hr%ZD} z$D+h1rKW*qO(9DZ7~=hdg9|eAK+8}egRN+)6Vpmki{e3R%+MsD#z15chJXx0xDBP{ z4>ABT+g=RXK$V(Uk^!EI2c0-UWNBppS&;3PSX=_?`Q&DS^}*5(WY8J9`WO=JsC6Qm zddQGA#Op*ThZrAFlnU}E5$essW8eY##U+rjmE>$9G?_s(6{V7(2jUONnp`|qpeA9o zLn=UXk#3-5jAcQWYnE$P79^R#`)sEUNv8?LeTp zf6#zNCN^hU!e_LLGt)sGfAA117L|A_I?IC6;*5AuVs#Dj#-`cD#Ueem1RQ^^5P7Iy zd|(IlKw4q2>0XE$SVs_1^Bbq9mOu?a^Deld2(G)_u`9v8_zT>%gxH2^Afg2WUIqfS z6w^hPpw%d#U5a^7C1}P#`~~Vpf(|n>G=i)jhloOTK!d{24Bkuudj>Qj4$i}s(L@ zZWd=|GGOlDL2(owofsQJQqXE3tTvm1_W=0iyQHQTIDxh^VfTp(e5K4_TKJ2?Qf4iSqpK%3@3Qw1r|E#z+CL-%q6u!XA`s7iy3NkT_FKxbM7 zBnRXMo5W++Vg%Mwl%EUI241rjfL);>c%(WcAF9r~EEk7DL^Na;gU|DG#cm*yV<8!M8(hF?DcC3;TPRuh7o_HaeG%ZD3~IHTfH;sjT<~lU zHcdu`pr$?i9E8*q|I(6z(h^rlEWnB%jAhsspp(?V=afJcqGUp(bztE2qEN$7)zElG z7cxWtuZ1!!sqo3qV4i=i$KD$UCSt$D?!3NddATA2kJA;ju-M5;>8$uCaD zrpD44Bm+u8*klbsXWn>#³P9#`7#xZkoLEE4P%D#rCE-t9&C1SG=w#Ysga<(O8 zD;Go|%p0g1?VOFEPQoE=2$lvdX@(r38V~9MK^KM>B$i~rm%vt}CYORwMF@b1qPIs3 zAamTIp`I?FDc1mRkXH01xOmpsyBg;fr(+i6K1L>xy^!Fc%rwvtl3zZwluimr&IFaz zhQ{&nWr^`QnZ+gXC5c!Ju?!3LgXni9R*R3J8M?i$NmwmQEJ`*hO3X{i&y7ziO=E}$ z^^x=Q(h&X4;?$fphWONq)a0^Mc&iS)gcao7C}ZRkY~vFl>v`gnixP`7Kr5+BQe8nM z90ibD2az#NjBT9gh_3lRlJX?ziAsU(uci79A8$RUxOp9|V;5T9C+ zoPnYbuE^LZp0FY_6Z|G%7!TS)fVrT*EEl|Jzc?o|1?($C8Uydx0Hwy{?0C>@CPW%E zU8UF_i9 z9Hp5l4DrwwK3JdtB!IF%Beev&M9v`mm5wDR596f&pj=ojqi zTAZ9%kQ$s?SelxboLUU(LqQI}b`8Ly)6g8$9(BvCNKHXZn}XKZfJ#5qy%0ubaHZfa z4E}j;i6x0S;H4q1xj6J#fb@W8u~Sos*M)TrE9l5*T=p26x}+xO7bTXYLVFar6dDx`1{^Bz00C=r#hwJv7dIM#mO4QE0_p-f zRYI3I5~te`bRZ`}w`&$w=UIaM0x}(Rf^2Rks2zfto_!1vX#sqQ5@-<(R?ni$To{@r zrl72?cFoOA0yRD`Z7@XD2s-^6bT9>YDXp^+9(`t@bG<=LxsZIwiaAg>5{vmr=T{n< zLdH!%zV~)m zL-O&d1s&T9k01j?d}24*5R{U9Q;Ule(^LKPU_AtE$=D(&u^j9QxIwUT6WZMhPAviD z3oPTISfd=<$e$@VUBN9t?Py|IRg70X+M;6O)n>X9uQrJUwcwsFMxP$t0JQa4SVlYz zEj$v7L8D5baxODJ4?J{>J&Z92>p}YnAkl;^l0oMN7iAXsf{*vZqYRs?jKPryD!0Ic z8rU6V>RAlR3&Ef*#)&2QMXuQDJ){-67MaDM>pPNDp$egC4!+LJ*d;Z`wK54aSA)h+ zg1~)J(4+uF0aUZ0Ib?AhWaJK9QD8~5xw*M0x?pR{z~^TA7eS`<9P=P&&0#jA(R3R^ z=L{g)uv&-PHqSIyZ~+dp4b@?=SwYAOBIu#sptOe4ut(Kn1eJs60j)YBpbsT060t2F z93imq#u!$zbWDLAHIxbQHj4SERXTj_Hpou~zTl(@nz(Qc$iSl4$OPKfge>NP#55$1 z!RiZ&y|P*A@ebX+CG zxsZg3HIZZ{p=dRP?l>Ys2TBP07#cZ(Z|Z>@?CKf-UdLaVk&y&7A4N6jJ`)r0B$gv+ z*#Tk}%fQ72b{-qpwdO7^U}dh@Oo0TPQ+_^pHY5Pz4-|V0O~4b6;8|4A8Lgnj7sz6M zpw&}8nTD=DnMMY#uEqhSC6JX}U~P~_J2rDc?uX3yJAoHjATKMx?FDcWMsXj=9LOd( zh&jXr1lSa4`oLT$hm;Wlyg}(3T9?A+p|J##5oq5MbQMj05$dU<5alr2Ag6_aM}%Ba zWiT=%=yn}&AiAP&sgT$kJjLhR9BZjDwNu_CN5EW=XMYIAT5JlFw8$j9%48qUSwgbz869Hb@K7@{1-_t@wDk(ag^8hNHTgNMSvwPFx- znirgUP>e$F=@}aYmFB@RA!xrU{E8b;>I5CI;Re|sfY}sq4JdQP>Rfa?jEq5DB}j)5 znlj;rCxOd13Jf`Nv>2iRGV&Kx*lU~?0m8B5SAOq6vkSgpik0Ax)YXoM16 zpdwBKLr!>7{@S`&lKm-ussA-?oQhH)qZQRwLv zn|X#fQUSC^1y{(BRt?tRHZlQ~obX-dkhUYZa04yC49E>Oz>=7ZK*Ldxkb{_?U*MRR z;*?)flAr6Egi90R&ZFYYbkGzUXlbi!WptDuQo&10PNb35B&k1QwF~~$}ONQ*dQLXvk)}>mY4&Yc2;q53<~%3i+7C(3HAeL zOITS8?Yn^&XIi?XCY7dx4jFL`a03m&R=FapMXX%Jr4S|Xj6mlKgO?;hPUnKPD_jHI z%0MfVz!!ExEI`p`Xr2r?CpEq-wJ0gS7<3a9*cm9Qe2k32yD>m5ocR3GlKA{I&_$j3 zMU@aEq5ktRG|kD+OV7$Jh_A>miqB5PkS<27-;Yl&sX)QGN+XPEX5xnvmq8&}O z8RQz8VA#E?km4HBxdHnO?pX6|q@frj1tQiB=oUWE(u0)za)=2i0b%A?0y-)WlqAcrNP}lSg5d|(A*Wz$$_+satw56_ zE}5wW)tW;l0Etm*0=k5hu#rASh=obuyaAqijn6H`;xj`NNKXc`3<0YWA0x#2B(QPd ztdjS#>ECsYM2u&Pxb|vVRThPg1 zNYW^wYiL}Wmz|dnxaPk-1MQlKFUUzu zPR+>A0bM(V>^2`m)8vv0+|owI$W0XtQ_vy<(b0kwVg%G%fY)b%?zuvClA$4V3>MK& zKqOVts&~+pgd8P4b ziNz)HprcG7%AgT#Xygf>)k;l)4D3QG1W@{gIKdEFt$=sNg6@C{K+hd0eL5_=8E9x3 z@*-Pe{DOSaRbl;=WsP! zL1B&PYoS;JIxQP~(GfX%&7k&z&&4Cd0MJYw*mAG|P`{92j-eqXdLbQraDUZ2F}X0l zC>45e1J=Fsc*7FeDCinga3yF+kx`)2J`lk~1p`6eL>x*;ncFO({zQ&K5}gPeK7n<% zz)@jn2|2fGEEQ$?H(fgj*6hUr^K^v06qR_}9I6tiqK<1ta%yTy zY6>3vja*#7>m*V^0R@SA9)R?BRc%A6F? zs5TZ^!sp?bx)9RU^8H;58A|X2JhGc6=1NO2I(y$tF-{1byJa90ts)ZPE2)%M&O|uzkJYC z8)TLdx1pfqpPvlcfe$?h6{*Qfz&W6nayab#RHC&Rnz|R|mqXTAKynyK$ATx`>pJTIdXc8+7jj0p%7%sw1#W9yvl`2jhU6z65MHgxr1|l3x(uj7up> zX<}rU489Hbbid$u&|RhAbDqFXgbg)8)q_v%Ax1rVGar1S8^~SI2@_cJA8aew zk5Gr9YlJuvHqS!5Hn2+xYeQt-B5c_?vl1C9fG8gY5+m zUt?Rc1`aJ09Y#nC;Q~ra;=?mbG9YUTAT9x$hv^TrG6Gy7VKcnAB)^~}BegugC?^H7 znXM?kpdd2^5-6xHF~+JGt6Gez#V|V*GIR{O0u|FCKE{Y?WoVl+AGCxkvjj4h40R7Q zQ~H>JcBQ341yLO7V`!2dUjjOX5j?7dRgIwqY}o+l4tr<<#B`IP3Fx47@R^99SrhEG znL$dY%)E5i3@+Fpm_t!V9-#dyunH7cgKq0IgbsjW+YOC5J%`;41E?9OTc<(E7jr{3 z*aWCM4GqB^703`9q;myp%79n#fz_h87#}}36m1O3o#wSB1(fk81FN!QcsVhFWG#+9H zPIX3x#g(~9`8kOxR8K6i5EpY%}y8{k?s45GP zD)@*liV}=s5^diD*f#u%GF^#K1X>5RG1nM63r7a#a)XX`0^fjV#J~UmEI7;X literal 451280 zcmX^A>+L^w1_nlE1_lO31_lNe1_p))AdUh97)UZOFl2!EU>+vn(7GHV2-3*Fz_1~k z70hR6U|;}YE-;UQAwIq&wW0*dVF2+%Tq8mdd>E_$C)6?)h+8(~vofd(fgRQWQv;&o z<8v}gQi~FE49!4XhWL0?^Cm#eF@PF3;V(1TZ(zj?3=DiQ29%DEPbw~kvO!dQyo+Oq zBZvjT2cZ7CAhrl1z`(%324_LS4vEVUAD@y~l86w&Fz*kPcAMg%FIiLilF|cIzVX!!h(<>^YV%j5sYr0!(OO+pyoLog!uOZBO8Mi#0V4;(>&Dpb=VIv zZx2+L!(oVdP%Z`qGB39vF}WnZG_O1}FC{+S#|1^v0f>1CmQc|nEDRw39$;o;I1TYE z)a4NQ`1sU}__U(L+*BAJ)qM#+A?5`XLF5zuLd=8k7#O%27&2gN5Us+%z#sr(utRbT z$TA5A1_lWsHikZC28JJAYz#N1gY_{4fYdQCFoZ+#Lna0W3uXp}FsL{w)ZsKR(BqeH z0c#s*zTp9|3*heYIPMM(7LViZ93TgJ90!#u3?7|74)e>qFff2sr=`Kwqw_J$>-=E& z&G3>(=kb>y<0d$UJB9^&bbj{i{BL-`v-$sb{&pco1_saO;~XBXmmK$jEcM}c{p8Vl zyCkIxT(;RTlsar+Yy-1f4wUeC^xA@qdI2IDZ2$lN|DT~$0xGx<#0AS7V+Ao8Aru2t z+N1NHPvg;L&-*^_SQr>QI%8Bg_`?tIYr3cifCvQ;Vc^r5 zq9WkYTcRScA5Wf6H`E1_qyA-Gz}X3_jf@Dje|i=+W(>V&K{7CgIav zqaxwk`ro6MwF0Dy-{ptl|Fj7noqs)gYZ)CIZ1fpQKOx-N`gSKMq42lN0;kl!3ZOK} zz~A(T0p!4!9?cIQKtx(zF)%QA_J-*H_prQBF6_}8qVeC;@;XGa?JP)nZ|H;0YX{%4 z{y*mM?HKcZkhvu$y`>MpLe0;ZJ-**F{Le2BZr?ca3$WNb@(cLb3-AlFSnvz_SO|DD zA6M}Bf2{PeNAs_QqD+s@S02re9(ZW}^5`wGDDdp9u`hu8mtVkr0>6O&0)9ca3H*Y7 z3-|@xH}DJiAK({s+rTgAcYt5O{Q|#${{wzOw+sA&eh>Hs+&}OO@be40ec%`5^Jsq8 z;L-fP!K3+5L+KU|%d;Mxr}$f@FfcH{@_Xky&1)XLwf{XduRDA@#$F-^5@>$L?(zK| zxIA|3;t}uQ5%Bnb2;}0A9?k#Ri^4rRUwUX>^yn=SVE60|5obp#ue+jtcEtVciu%5%;ev>VHSv|1PNxIgjRJ93IVwI6RsU{wO`- z(fRTi3kQQ|r<;aHcZ`aHN9%1*ewVw3|B=jx#&3g-Hbd!W!*7O{z-i6{9=)?sqxUZ; zzB-Yk_cchQH$)pLdOa*JL!K;q<-ZWV6o;G@Ug~>-KXH#%|?q|kKP*V z0wn*?JAP%+;jVHPSLojK6*1YEKp7b>2eZ#+Bi@we{!{r~?CK zQllc^*?A9KKD{=h97ITf z2uTnj1tO$Dgbav~1rc%}LLNjYfCxnpp#&n7L4*p3Pz4ccAVM8PXn+V!5TOMkv_XUp zh|mQQdLTj{L>PbwLl9vEB8)+V35YNS5oRF597I@v2ul!Q1tP3Lgbj$W1rc^2!kz(K zW`m1spU!{Cfy>|Wl$n76sc_B#70z!xdRcD=voQGZySxCEh%TVA7Fs^n=rS;renif} z{4Hpi7u10TrA0*9{0>q!>mp@dPs^*&%zF`6=Cwr6yh!QUkzc^YmH|{i+hS(nN8l`+ zftH0mduwb9VC5&h^RGNw{&no~5oJK+;1A#&90m$CL;)?zj;PNm$-l=~G*Aj>k6u=W zAQlD>ewQ1d*ag>jILl}Lmbs`!GZTo5QZ#=6M<9-(`7&4%OVMnB8M{dFJ6b*yU;jem z7kA;@dhgf&|Da6H;n94=Bib>>F&5N|h&_x*UyfnH0iK=z2o|G0oy8oW7H{(rP*3DA zyuH);gY&`)e*P9v*U6*x5`T*`BdDZy`tNFZ^4lSHkIo+@ik%mlAF#U`p5&KzVDRZY z>Cj=q@6+qa=wo@J^n*vQ3qPZ0^AC3ZCQgt}%~PoTVTTR_hmHb9hmHa!hmHbfhmHak zhmHbPhmHa^hmHbvP|wJt`OuHj>n~4%%9_p#p3M(_`1SIz`&gdmZ{7w{q#XY-GOq983_LphJUlx696UPxB0M_%0z5kXGCVr{59mLz2Of!uOEER`v17$ zH-~S>nM+I^d+Q&71)85Tdwjod_zkIjYz8WR%|OMk0l%P+fq+NzF$ItR$6@VbpUz*9 z_VFi=-Wr1f&)yO<CC;^PlE5&)#}?!&nt8 z0%;i|l`oE6JYtCA7ur4s1rwt96{A-B*y$LH1p}nx2G1{`_=I)O96WkiR90}5N`u=) zEGnRG7E*`nr9C49!!Z_cV}cP>pEH37W)Q&wB3MBL8;D>B5gZ_b6GU)<2yPI;10r}q z1Rsdt2N5Hx0p!tXqvFwPqOu<}o(E|Fxf*`+fc9EdSs55WYz~H!d{8kd;BoK;vj@22 z$zZ_1(9P25YWS`70DsFLP`9|77u0ifHT;I$zFx_|z~I2&YQ)08(0Qow(SK$JhJ!D- zRR90yXYlB5IjF$E!Qjy=GRfoMBi3#g0fW{9rDtERV_{%0yuH5yltp1ZBG1laj>o|R z+Md02kdC?Iakm7JjgH6NQo!^vw+sf)<8B2Yj^}YV@Gzw3aW_y0pTVa)M@7N6^{r2@ zt)v$VgD=0!dvN>Mv-6H;Z;T3~b3=_P14Aiv@a;ah7v|gggukU7T4?-H;BR^ka?vH9 z&WDgf;|8SAP(>;<6#jc!e&ui52QD;1RM1Kd1IOMP71Uw_)Lt_Mx7SQD3k+y`&8PDb zT7hAT)Lx@zd2t4*ym$sGFML$~duUz+_oP)_I-hA?gBBR@@l40A7*U1}8Bk#l>QI01 zX#UAw6b1?+M1euA_L|c%76nj)%>a}ZH9T4m`0%@e21$_9n`h@A&)ynPeA=iZx5vS8 z*^LyJpnkIVr@*g8U zYe4Y{85vQ*5uaGbM^K}aYU3lY_*4MJCuk5%gI~i%MZl3?(9Pl{sNm>4-1rzY@OkhB zkLv&b%nUx=H3vC74nAgaHT>q=`Nxy-4u4A{0|NuLq5?DqM_y3@a*cpzr<;ez4)Eab ze+C9mWfm3BPPYI@{_QUEJdT}i369-0@{nT4v(v4>r}KkH^AQJl3lh=(^Emj9*<%N& zL;{zXJR1xTw4N-nGCTlnFMK};Dj-X>I!{3h$Cq4<4t#J3$im>!35_8L1>?zr?DXh_ zRC*qr5N@yRTCfh7=uxm6J-Q)d^Nq(}Fi0?XbiVWGyakp36a3pRY-DWyC0H(a@P$D0 zFG2n(hnjz|@J~OeaIpg%2~brBntuovse1I9rq5+z@Hl?_-~a!RX&cb22CoOCA<=DV z`0f9N23zn1G$fyUbnAkh+G|=C$-=PTLIKpC2b&2Rx9?>I&BS?hGIzCt9M|E@ajaPY zv`oOGcejKB1H^{!8}@A!pk6JJ z@_^dey#r*YM>qR_0gujR1vUl-&+a}@dhlpH$=?d%dvtSy+4^h@3?BO#KK%cGA5>d) z&I76P=`{A~EK!kwnAZG*xk$mIcRDDyfhNCtZTTj$Fzf?y4G%!P+Iin|7Yk@Y(SU)$ z6Vl34V1Ovu%^|?R;JBNCgMq}6SrJ#thaKJnCi;c@XT!WSNjM}0t3FfTnC z4}uaPl4n2$^SxZh1oMw)=Npe541fOrHwWe8&O;uI*E|{jd+cEN_y4~%Sm>Z9<7rRE zQy#r8!aqD1FMBec_2}&fC36qU6Z~yHfB*k)umvaX5+3jx4a09>?|}*a?I)Ula)D;( zB+3Pve{z+|9DE_bzx_b-556M7{h*nBurgRV+HI-2-3Jo5zO4uNTemVXFo1>> zK}ujnEx7bN&I($40WuBTv4s>{$5~}SVaEU}vq6h!7<=6{noqE=;4d*e#;OjII>rjJ zjo}!pCWNO2p|l~C4upafkey(A;N{2$4MqvbL})W){=Y;V?2pca9=*0_y;&Fx4|JXb zi+~CY1CQe_Di$E)b{>>x0L^%puse45b^HSjh(k)l?j0En0t`OAE-D6w-*$nTT43Fs zhv8PP04eb3_RRp7Pm!Rp(dMHP9-Z&O3So5XZT{93Ai3TW6$3+P9nc-3VgNU12FM(^ ztDx-@7ZpeY<+zKA1IV3l2SZ(CcoJTlb$dfxa2*s2z1avCbT`ic33W4gcDC&Rc@5?? zNDLlhU~JeS!YIMOP@)QUGB~V2g#$N{mAP&A}n*esv|HGcmb_}J54G(0v^4#hmaLD*n+zk zC6K`6-}W1<+3;k`0e)BBCkzY>ohKk;Y#zO~%9h}0z1@J8P7vd>;AS^cdmj{Ej^Ot2 zchAm$PzQk;?}Gb5?L@F$u;Q@Su!{u?z|f3|_r98$CJ?frg0{uX{8< zf8fjb-K&>pC%A^|En)ocp?J+h^PfkrsD~R1q?Bqoz~6Ec)R+K`Mk9|ndGyLOg6c`o zFjV7X28RFteR`KP{s;BY8lQl;u-0#hDb%T+mPg7eJuDA<@H^e`>3rs)dC#L)^qDKD z#)hILYv*M6(CW@2v@ilRiQ5={+fRWrk<-lLyeTw+03V zXx}vX|9=m~7aq-z**y+E*7D#y?7?|D&4WMhF#oXwp^p3-JSvX-8X+nI{2Dj;kKMY< zA0}&kiJ2jdzwE|mNB%lD4*p{Y82FE!>PX{HJCVkJ`*a%r^@FVkO88+8hn8lZyTDB- z(3I%^qn@35p!v9iFSVK(+X2d59+w|@{6FE@`PNtQs;A=7G{^5p|I72YfSQD! zJHeX&Gc$OCQz}CPBZKE|P<~*j0ZpL3^f>s^sPW-{c?JfL%##cZOpG4j8Bm4<1_lq# zQ+}N`uRQ)A_UyJ%@o4?e-wIl%;Mpmo0u7x8P^-8`g##=HN;IC`H7WvN9;ko^@gzXJ z7R~?v|9kfOs7QEp{_`-r=hJ$Rzcm50li{hmYEA|@4dnFipz!4Ywbft>fB7h0^0b@+R#+SgHh=5i|Nmb;2Kl!0m&d_Z zMxKhld@ZM30~uB91y*tD&;S1~4}w*I!VAs5Vk@ws1duUvU{MU>dBUSO2owaMm~Z%l zNPi`N{{IKZt=ixJ|3PXYaVr7$mu|yDW=C)f%=7XikJjU*_CA*9%B(!U-}klrRc7P? z^V2`i&P&MtZxRDVbgz#J2PlVta!-l$OBHl6&(2Hyt$bilNxobRau?V#YJWqML&@*||3Nhe z$h-^?yYq*~!57frKL!f^qJWqFU#?GI1mjxaIx+SDye^Y7~b+}y;Umf*;~lyVfm@p2^>+gK&{G7N#D+2 zFN?s2Vaa|zo!2}x&s7+K;w#t3@>E%dr{$>kb((p+C<)a8P1)Pxin^Zu>1GI1~mG|ChHwGvctasZq=#^RgdQRADPnd^#_AXr6-m=p2%dKn_Ou z2<(>PjSwGA0_8z)M1Ud=-ACujls&%R^0d5!(?>!7phY^&AEg`~osuu@fBydu3Q2Gw zUn=PdF5rvpz|k`Y5Km1C@s!owqy=zS3%b#O~R7!c+4?g$>Ao#h|Q|=V5uV zB=B{*2Q1_N_qE&u$@p9#MSd^OKr(KL3&`%nKR|Ya%msM~oH0Eh8B-Nxnu6!|8$OnY z$|O8s2^nM@I3e>lfy%z-r_7$6GH+g1|M>qO)SgDP4?LRRNO*K!_U!!V+4;kBFSt$x zRsY~6+@R5MPw>i3aP11IKS5O^qMn6_f$CI9Evx_@G6Ge@G7JnJ5c5D4JZM$)OmLR> zQ4#R%Ht_s^%(v6PrxP^9017MA8sE3`i>KlnPsJl?j^B@fYWyppGUVVpBge*Ppc>sX z^BA~B=ez)IyD%^)cyQkI>g0Lg+3jHAY3*Q8>f_US+_&?HPv=?B&hNgRkl_Xoh;L*V z7<@ZF`*i-p>buUDphg$m?I069Iwe4h9y~i8EPT5Sd|SU&WI-!v1qKGcUX>0|JIYt_ ztLMRoTAqqOeK}wHa$ZdHVF00ks|v@V8b&c@iMG7A26wAg#wkK8B}!T5s{U+Jdsn|6?AOpZJ@Z zSwOAFAN(ypK~*!f_4pQ4X_Mre92~ykyx`NR0&>1bHyg-3tuw$1`8>MaIKcdGpcw0R z699A8K{ybXn}7=0UeIzIxWjEgW2Ae)B?zch{{M)Ndj2PpF1JLe???rbQmA1=5HT1hpAE zk9%~Ms0jFW9`)%w3rW|I^qRnc)Jefv_`CoOO$#7-(jL_vcA$18y#M3z{~*}60nCuZ z(rN|rtpI579^u<794j2O?5E56bEq-T0z649vHSo!L;51Crvkq@6Urc zpfz6LZk$i&d5?qdwVI!^dvu=m(EQEcF#)XW0)Oijc5X8fye-}*u3Q&s#WdD3H<0pU1d652zARZq5 zAZPouUf^%l0$BvouLx%RHOdV1;-?=|Qy}KX$El0j1x_mpn zLj?<=Y9aYG86H}oh9!91(&O@TpVkYd8XlIPKuzV_9+vk(O=WEEX<`D^W{~cl3uv(9 z0DtRMP+IHce94K+Wd7Dapw=uX?|cR^zJqMwZ+i}6V-M{!pir3(YSw_|(Ok;kdgmLc zcmIjM?J|e~HSaix4OWj9DMbM|=A$!~dzzwI|DO+ka@J%|l< z8(I+aH(&Yw|NqMsxTEar*Z==f+|S?k2qXkG`5K4~H5r^yz-4Gr)XTka3AEtgZw&#t z2Gy~SAR(xcrXV)d$j(C^$R)GXcSIa|b{2r*&;zBJ3hthJbbj`LRf?r?9=*k&?m2(+ zM9_#bsC^Ry2~UsCdoOuG(c1al15vubH1fB0fdU1l88mU~1Jc|N)BNvc4_GrOyP+4V z=R7q3@ppixb-_gnXssEzP<{k55>#w~76`t)0^)T-3K_HtBji6Q-Cf{s-2fUXaYd`E z&v_htr`7z7-LvzIr{)*_4v-?SMV~+>f=Yi-ICxloCSKkK31hcN17Z`ZO$v~w(BchL&fEee-g_RF-*J{Rv;O@5@7WD$Lzhp0MG5Gbxg!HkcPZOJd)K|HWSF)UJtSOf~d)-|BG-Ux34krmhLe!+)dTvQ}{ zI-i5)g|dA*IbVMHfFpwWTbF~<7s%Q3K#g&5MDw>n27<7J4#=%dTp(wHdNAE?pmbDf z46-8jBghI^9Q%0uKMcxY&CQTZ?%DZ=zaT-~!0}*3Y191@a1Li!C^}9Rr0bXelYEU3c)65o$ZIxY(x^ zq7$4e^WpU_#41<|+_UqvC#VI!4(yc+{H+gR_J9@~gWGi5LH2+)binKZ7ro#%N^veY zb$}LPyuA1eREqrY?EF*W1r9UNvKDaK0L3>_zVqz-1I^x^-*5X^-ou%_cmMeR-?8}_ zvwtVgmzR9+!N!-kfXqINVm5O7L=}{$6~G4H2Mv6I0@ug`>|$_b!QZ6$3u3BYC(pN+ zE${#TN6bee<{v@p@jScb!Q(6PxW`v+ctSe1pp_z@Xs6 z`N6A`<)LS{yM?E^K3Ch)<^hWMIkN0yaAaT7?Hw@_H6{JpjnP!JeJ}JiFz< zE|tUQQpn)~V3!^TyVRUWmpXWLvi$UHcC+{anc9U-QN7-e7%#+_PfUk;6nQ=ovcmQ8 zf3#UdJX44y&mDR|MuI?1WkPd@o{C?Q<_UmA!9v9(Z_lY z`gPj81ciLJh>Az+rP3_WRH0{g2&m0_iNAFfXaKuA1T@5Rsk9CxE&<+^02TP#Fqch=B0fOHh67(RtOw@UBnm-O^ki%d16g z9-S8u8 zn{NaPROHYGc?2ppeR-L_SOOSJMMF-Xp12v35F(Cjd2)Mu#UN1Sp-hyRR zC6F!8KrTA?!U$vwa)68d|NsB>NsuUP`kQJl+YM^_fQlQC^FSpKWa8=&cuWiCI9?yi ztHo-dNu^a_aYP86@XINLjn+4J7{dN^G5Rn(0tU9m+HT;&qsj=)-QW@{(z2wKK}pT6VyfmpNIx6y+Nxy zAmun{Rs%AxqW~XXm0@6jt`GrL5un+pQqage5fe|oif51}o>qa11kxs+oWK)L$9y}_ zcy@mE?Ys^d41i3TfhV4RL1&>rRc7ZqgvWe4ANqEFK$~vz?3VCoy1FvM}CcP*qjWkKE*w;WDW8dp@}6=#hadr2h$wC9|TQ` zya%-y@ilsoW|q7#PLASIXa-4VrBMbt6GLC5^#3-(LdMa5wzq(|U=& zH61h#XZec1c`s<>A6g4>lk9TvG7Suub6)Vk;$CHt`;gr04dTPx+rbK2QsoZnYVo(Y zV!C%D%)RWO3=4IyEF=oR^F*-xbPb%Jd^?X%gTQXV?({5fV4$`{0h>x8l=q&!~<)? z@cCj;pAF{o!{8;!ho$K{0FXsL8%5*2P4{TuZuK2zTfw-{9C37 zNerMN10Th6o|ap{ePf@_Yy3^wprq6J$+Op=175;7gS^^#&7;%M6OwOzJ8$u~Oa(g` zn)phEd@NrT+jv4xD12D~mIS#0Tj*6-gM%O#q{#ATNytl25DUBaZ-IJIFk=OfvY zG%sH9H?e`FzTfq*e9zzZ3myXKq1k*NG(`gH;6Q=^!jycN#K_FR5}9j3g+!+y zG$wsIuYn`80_;^Bkr@q^BoLWqAVuKF)B&-udbtU-GXkDQSm5eFUPFn@m!RP)Xb9c~ zv9TK0d5J1gX0%AkVfaE@KzTt1~ z`Hm5jSf>h(`50dFX}wqK;$!)aziA~RFMD(zgJeW-b_Qp}N1)}KonR#}ZALzp?~0>* zIt5?afeU^_jDX7UicGMn3qZ{=%ZnvdFQg zFE4?3@L_v&$ACs6K-s_Z)62u~0uB^why?kLn9>DQaC>%sf+jxx)ch+4^$aQKx3#h7L@#M zeFlw(lWFK>aHk%{Pz8{o?%;_UScq$aq9Oz&o(r}NCY}xojpja3JFHXir7&0z$RWsa zF&QLl`3@Y!M_|zb$`>y|NgdQ0h76aZr}BJofn@md_a~V5kWB@RAoxH{1)Bqk4bZqD zbVd`sQU+TOUJBf4_%aLZ36MiU(Xb0L3-t(MToGuf$HVd$Xs8FI0xhNRH(mev|9|HP zaPQdU_{&(h>#!K50IuPGfqL0sqmYZKCeU;b!kp`${{Kfk-wD*Q@BHLycmQ-pQ|Cd@ zydDGcekH_suSfHn3=hx}%Ilt;Upzsl_J*h=c(lIdZ|Ri;?H2(p)&uRw@$1#u;o1E3 zfoF3q!+-vk0!dJ7UkEe`+K~ccL#9GOP5b|cJUfLD;~%ICKRr4x`zYQ3c_hEL~zkLKs>{4M?*psgVnJUT;E zB0$4MoyR;m&$+gMj{NxG%D?S_Pv>Kg=Fg0vvkpBx4?fZNG(6)14o8np7ZnG74b|fL z%nYDKz@0TJ0WYVq!}gDQw0`4nZD(g-c=??jXQwNJXLl%M%nmeN>e(F% z8a9GV4SIHmf(B{$TNZ$J4TFYlk3&~xf`&F)&-1rBfogT|hK%$4&G$hK^n1`dH!ZUR3n;W{{R2~vI^Y%z3yR%Zab(%f@`%w z)!Jka8rnYY3K=Oi0vA14j93q9(!o3cI-|@3$ph~}CHHYx$dL0Ra6N|@j5_TBnim6| zt>t0)5p>R}2Y(A_Pv=We_XQk3h$IAFT=tp2;~2<|aMjO1y&CX{ac7K*2d3)ZD5?cO zy%KTonmMeh6+xi{H`@`US|9FY&~T`a;(brcJ*Plr2Y>T)P`|bH5r3;J$PvyUz2LD? zG=;?xJ|IP(K@9*oWJT9}6z_RjZULKC8~|2S&C0;=@+Zj6SWWT(E1Cl`3A9!kIh?0} zDhXIrfk%vyB0&YzEr+EdanK4$BuQV0PDl(nfSUuL7y^|>j<6AIkMFlVEpI}5x&N6N zz;RWk;bVEeOxdIJqL1RkQfWxwqj{dc2{b+q&mN#Ps-B&$94~KxTSCOy!{4?Yv=Ynm zJb&9dh&CU^hy1OJAZ+M72};bggErJ`0#y~@U<7#uHe=}lS}Af5?0)_>9?;5Lkh!2G zxDbEvw|)neUtoPk9-YW>RFwP@wEPd^Pmr1TgNMKEGk6EddH%Lnpw0|9nD|@oLD<-w zeHbhiqvGMx>7t_J+3Dor*%=hz+nMFy(|O&e^D=lWf?q@R@+@Z9xF={0F1*zB?7Ri` zm`k^diq1=Yus<;JYpD`6yBE74rytO4HaKSNz>WaL45+pQPbhz`@b|F%2-?A);0d>^ zB=sdI8$dz>E!K;EUQXQ!*c%QmnbV83_Ps92zsxTPwP0Ps<oh3)LMj=s=Otd6fy)oD=OGm+q^3bcyfw0~!F5Nc ztHjIy@caVvwFT7I1{L-oUt5%fzpjPHH*(H^#CPILdr;|t@N$4B$Xw868xUO}FT?X; zHz-s=em#dPl96rTZ+Z;M?%h5r4xXJZXBl3HfX+7u9XP4w!}$R;LVf@`Lhj4p$gdF! z8zOgYIZ(>XA9g2=zw9t*+iDaC|FPS!ZL6o#_-~&``NE_510$$4 zV&Qr4slKP-S&!b@ACPT7%)Y%g$31#^T0!SPfRdz#M=#4!Py-F5-T}10f?q>-<1}Ul z&(1q9SAq|IVNvk_?NI==qd^B$1$cI{AZ=aH0kuD%%dYraLCa7;i?AR=xFG!=oj*N$ zLqL09L37`ohdhi!R02Ff8`mI>GH~kp#or1_%pR7XJUY+wH?IKIa|d7OH$PzZuy#?g z04;To;BSfoRlQ)Vj)Ppx@X`|`08am%-$4y|h|!*m9-xI(4B$P!t)F14SWfXb-vlLX zBy;(jgg~WSw~GqcQ=mp$ca4g{OF2-%12^}ehp`XH$$=>5e&lb3^}-<2^hoBy4B~J4 z04iJHGwYBB3@E>X+>6s($m*Vp{LSEY3|4bN^V*2Xp}9C7x~d_U;Ov~e~|67K_vrL?ad9K<_!3>d7M7wZw4)0K=xM4TyUc^1hfYgx+u8? zG&AuMGy#a*m4dFN7c^Sd`T`Pcts;N_{|C)~g1dU)F&lW;@;8I#@@UK+I!@5L8pg6(<$(*7Rm^;8;1;@zCQjj?ywUAU;8qjj7#0PuYha`MZ6a2L* zXsH}{>+5kyEASI2cN9;A$45&6IPKS{7=TJP@On>mu2Y<^(P=%OCCe+*z|zC0;(LrQP%PVlOJLcK>6{7+M_!dGC&{-a!=`GH4FMO^D26--<;N&tTgXqnwh(1{Y@Sn=(|sS`ZDf~*rXBl@xe)RXT_Q3=4K z6ST<(#ZFPs@IV3^1NbHgd^%-8!HR6B5lAO^89KIZCVz7x$T^@f1JHJkmnIquRt+})g&LVq7;xxM?s2EVkQby0>PpeG+Ka~{$fGn39$4R z0OFwN=7;Ep#48hs19kzZF92#WGI(5m?)m+ukL7t-Y=XK2p#A&c{xZ_A0%~_a4&+Q& zrUGr`_2_iwc!?Mjz->N%8)zB^d}0XrxD2p8{H-ORatZ7-v~E9tb0lau0kkR_k{rgpFw|fAcJm zdQgG}H#R(>BMF|JQJ@BhZ|4Fs=*V+DJlV=ZG>o9+qLtc zN9(y#eUDy$(8)E$Zm5X^G6>_$;o5n^v-2m|%$I*ry4S9qe;k{ifDTXa)qGH4;A8o) z#O-w*B&5+|qIfab0H4-JuAL`JgI-F3iyByG+7Yw|o5Az)6VLBAd@YZZS$SCgD>DTd zr0k;-P^t}L9R%$NL5=~}&J$oW`J2vyG94($Kt6&L(4~qVoz4Q#0vgE&{4JTF9PAJF z2S#yODgz4(W8|2r4VVX%&=cDD?Oh(3Vw%$3c}* zsfb6XvjmclUsiy!8(P$(#Cr&`Uy*e3H(dt%+F9bI3D^wm-cR^ukR+kj4g`v8tN(A}N)eLBBE_K3uRC+s|WZCAczX7K10UH_7qVIQawWq1;HMkDHc zA7nl+B-pp}m}lpC&(15IUp+d1gQNEY|3UESo6SGCi}*pi2q1^$fo+AJb_a5ufJf(j z(776qd^&&nc7FJO!K2sKQx9}fok!=r&R0I24}Cj-_(HGr1Z&1QpD5wedDs)=K~NtQ zG^zO4@Gbu~h$9{_HveEO6#`#NhB!_;2h{6z1ucRs74qq=Q_%y9elm zz)oKdm+qQY9+%F)jZZ-*nY(oUIQW9cw>#%3gU7+AEYOqf{xdLmC?59gjL~ICbL?(W z0UbY@=Gf_?%VT)kv0;zOq<;(y3?;dsVLT3o5*<*V%EHsyMa7_$7jb+xc+|>Ag#&s= zD5$Gw@tPH)7Idbthvo;+l@^_cp!b~`-i94?*?ORaxjTXbYCM}~vx|zw568|JT@KHK z@0cAMK}!l8pgj!(1_rlIn+>STOF&18gYO5s07?ZQlW{+NzUeGw6N3TtXhvhYoUY8CQ4}RCKqjbm+o8!S5Ws%8>FDyMMVNKRLC#S z;P@Rh&gsD43YudCsp&LeVqkFXeB;>obUrxvg3GhJAZXJEthBa zn)e{*c=X!r_c-{RwbRFz!Lf5b*v#G#ga4kL(;)hMHvH*457l_;;43cA?kU$%G|E^x zc0%0JeC(e`^S=Y7?LM8Sk1;bqUFy;6!RXo92QtmIb4i;769dBrMo?(A?g0(+fi@09 z>nl)r{r_+82|5P`8VI1V`VEYrK@g5M_Lc+CgF$_}{Wu)Er?Y^fubV~1ua~96^Z!W< z|9ke@7Z70bKc|NbCymKOUKT3kTIUUK8F82J3+>V zZ1~f85pqc_=$<4V&u*Ll9tR(?bh7X}c0%lgd2}9V%!A_?XztyO1L99V4%g0{HUW^E zb5tZenvb%0Sm&q+@Hedo4M{K=9#8?Dd#{01V|w)3Mmzx*s6W3kGwkD$0-aEcT%f}1 zM@W7E-}Y+Y*$G)1@z3xr>UsViork|2<}b12muDdD{C3ds{iSDKL(cI>Bsdur(22zy zKAklx0z{ml%z=D{vSa5lSYh6cdWbT(<%#7GWi;iW+i5`uB7+Z$1~I_L+k+V3(FG6# z+{p)>mCRvy33OKSdlzVSf*#mhYUa~hD*@Zt=+gPYqq`Thn98G@<)BArGw8Tvn50MZ z5d%=f#5u;tf{r*n_y`;=m0D;g%);6up`gM~0yGuF0X}$V2k3}tkJkSsY~AgkBHjaX zX0J#0KG4C>{M$}~o$1ket@BjpL2y0Nc@*wp#_7Z};*A|3IgFKPicY1%B(dQW50ieUEu`f=^QR=ym(= z(fWbE6*SWC$#}=Jmt~%JFV8a2VegRRd}|E;dwjp=q4?cH5p)JZ8P_gQYXKZ@p560T zKrK!6?OwhCYH1{qmX^knYN6w?_R0Sk7+|L;dq55?ckJE{PG{hY`eH!W{ei>Gqu2Ji zKJw|ju<{jj|2pV?x!b5WKX`T?2Zz7oF&25y-5&Db`#>fF=d*s0GkpsI&4(uK|4EKO9*uw9gHjsOK!1vuiZaM^IAH;rba9|>}M?mQ> z7<4ILH$V6!csEf05z^@K>D_#RL4sieV_P$b2G!ZHeaxQS(iW$T>cJLjSNB5S`7eJN$!RMTv zEOsuPU=v(A4|p{HV&rcr1@&i}5B{6r(HqF<*$KAIv3p9t3h17)YmLvqb^i5(@3}m> z_xy&K^Nh2T#k_Me$RSXx9lKll6+jw}K{Xsl*C1jJvDc&d;6IP%pZ`iHI38nTK{bmIWs{eo!8 zP5`GDh)2ci3U|H=a(MQ}k{iGO{XjRX3V<32 z;FH7;`#^75cp3j6vY&J`{J?n;)VafwKSslk*69zNZ;{GNNPhvEfh9aaFAU%M z^wy{dpw^$AFFm`bg4%^X-6p4eTfgzQoMd2NaBQwCU@A5C>}~_yZ|2c00X>lmR2D0q z_UQH~@UXne-wxT?5K-`20Nx((?4EZ4bly4gs110@PpN?6f5fHdpktvOyWKcEJLen$ z<$F)d78OvJx}59(0nbhd+p*h4CBd`11)`wSMJ2fmcC)~d5G>;oNX z<=J@yY^F!AZQ?a%&^Vf;99kpZqu16AA|(Wp`l^H4BZRl_VfBjvq(1a$y;LG$_zhI^ z-3N{1fqOG?j`84R0j-qzTR_L{AeGjJms|}GKniP*&U;8DH8k2inhywoMngc0pCv$j z0!VkEw?st)F`VO~qT$iq0IJ$SBP|>r-OUF;tz*z)2ADDM`@cMU!z_GyZBz_Tf?_N{ z15t58E~M~)s|3q?cyxk10|_#ikD%jG;PegZ-&k~>_2|6d3GU=Ld^;+@-wHa8xQjQ5 zfq?y^i{NtH7L?FI6(31li7~z+q{QK{t_yctF z8R)8tgHN?QIFI^p-UZF$9EC10<#OcL2!hSz@Q2BU=0cCf#(gOYf6F!S6l#tN2U5O( zgaNED`0N83VE+hCP@bJfyIoX7RKdAJ(6QTBC++(|cE(aR&V!DfzB-^p(Jci!hpbb| zv)fg`kQvAI@*p)|^)*Y@)TW>9IX^^loiU$-Cw!^`^| z3=E#hz8c`Z+#L=EhHkJP$4*xnk8UQ1E0bcg#(RmeX&qD%Hij=5GctBcKpabflw^e#{z5>}(8s*s=8-UcW={)G6%+>9b z;L+K02viMHV7}uvMtJ@4mVtqxJ4Z#tvGbi{<1+@(5%|!o2hHpfpk>M6YmGTTwSfhw zBy=$R@6mY~dQWNR&E}^9ojEEZpwUwYq+(IQqq`B7{WVIhT{=G;d?DL%pv2IllSc&_ z6G+uVZ;Fb9Pv>io=ED}?ViI)IQRl7y0UEDC=cB9mAj!M7eskcTf*5Rrbx50QR74o~ zryg|S-}Vv74A;&N{{svhIo^46i>Q3?{O`-*+WMb=>H*i5Z>4oD2TH5DSix1xfsz84 zvxxP4w~Gpzm*I7#2Fxr(8P;2(BJn=}tq$~ncR^wgdw_<4A!oh#bpCpI4z&02|8bvA zJJ2=vkfVN3x4QXs{zguKrxBapKpS_V$p^HF1Cq^ZK&y#BH$dRN)aas5r_N1}|3^K$ z!5i;dL9IH^PA$*wAjkqU&^e)=-9eBAW}sb?p4~y9Ieq??8qk`}UM~sIIah}7eL#E9 zvOvwx{|7uQkMlPNfDTSjyyatgi@!Axw6p|zJclcY4LZ0TRC;xqsQ7kXg%nbd!)_WF z8GJimd32kofbL1>cnLZc6v+l~R_OI$^sqe7-wZkz-v?qv3+ULim-j%EJfKZ+5a)od zGXjn4gB62rPlqaQwE%BKa{>=Oztjdb0TG%&nF6lq0BC_P#D>;y;HBG6;8E3=FX2lj zKx;2NI$wJne67{|7_{!hQ}YIY2RF#~pp*H%K~Azf&fn$)X58d&0ZmmQt-`{tUl*po z7i1Age+!s#lfMOI(91Fq54->YyMA|={%fF>j3E7I!Hk>yEis_QCi_7=Jo;l{`WZkL zf%JnHm|5QBZvh>U|MDehi9{##6s^msX%e)a=%$C|9Pp`H{LLFd%@NQwvEbw0B0<4G zoJR0D3?Pl2fB*k~sQ}h^88nmtN)M2gmY^y|@wi9l1s}y59+rFVfs#jYx(8@`!d=h- z(62!Wk{H{H-NE&U5Xh!&ph&m8$=?cEPxn(#tx@yr_2Pi%P0&^gk50{(F}Q5tZ}kI7fuhe93z9cIJ6_bcO}^bcQ*2fVNb81{W=$ z=_GmsS^0g4baIWpn|Rq z+}s9b4DjCj!=PoUofka8r?{cH6}(T`%W@C+sJ~)2573>XlR+EyT|h-puPy%xa2rSF z1~bFH8bRc4qerjpr{iErevo9lAmXY^AIsaNfuK|n23|h~ayeS4mXesxwt)&dNRbcP z0+uE45_BIEDAPd#PYhZ-7P~?MujKYi&~`sa3}Fkkig0jil}S>NE0rx7hkiSHTCG|AY1nKt~Vt zwqoxhsrj}(LF*!|z}-c9;M@7$6SN}x;Bzfc&f~tE_d)j{9mml{a!Megi*y@YU&Nqv zk>Fin571hsTRxpH!Q}(N{?RKBto4*}Za59vd^ zacq7f(D+mUbYL-Lw%oJ%m;h+S0TJDZ#=ns62S$?`sTW~`qwi1y?>m48qC6lS2e}WP zjjkM^X`Gj!#w18DXj~K4&A@1&yS6@o^d1f(Ofi5si+}0?xM5I_mt?gZC{2TSu3JV0 zG#-N4Pl9%mXwgr&0#2(wosVAb0hL()kN9+|`E)*n-iV3bPk4%w>TvfCK>G3Y4m>(# zUV8pNj@&!&?X-foKyddCKvyn$LV5>2hW{~o2Nt0ACA48325OE#n^0aLHmK$XW!z2^ z71%a)#K;PGSGtJ`XlFXScL1{i)ck{1PFQ*e;9aDh*I|mmr82B50X}pc>K<&p1DGb1 z-oZRjLlLS8Pw&8|^Dp$WQrMZsplu`IngO)w1Kfz<0Tm0DFZo+ufVPVL12;xMZ`B9oGgylsbabDO~Wz=;?XeW0cZ{1B|x zTcDHekC!QfTl_~s2l{~2fZE_7kHFjc4B!n~NbP*kd73_*mMlNw~!C0LvOD1X~AkRaG@47aTY?>4DJZOKDV&g^{mQXOm)G#i6j z@)?XCmhX!lVQn+e2?U_fN`c#eEfH6^f_h-}pdMJ2hvmzXsMp1ylcEp4g*wNx^MWt9 zPYFp^T)wRbN&{b}{{R2q*YZZGJIDgahE6PACN7#KL4y#mX0~rol!c@?x(kpmP=<&d5iqy#OMhc=}HAfEEh^!_NI(yuPgmJUd^NM!a0|7aV~gjyK54 zTj2XyU~!1tk_IW!0EHzeyMh|i(x5dI;BMVTq@>T^6!;f(WyBL^|4y4nFT1{i788Kx zD;dD^6QJ1%F3@xbWLXAmW&-0rRnU9{k0)r?MTv@lXXhX2DZ`*~a>yt=xUG#e9q}JD z9nlObM}50(RD4_i^LI3Xx>cZ^DGboVwKjkc*8(+#7(jQiLWc*F3C~HO9(utaCi@@+ z+TwQPuX9nsdGRRd!a(27s~D3K9-W^dK?@q>1>Jez16}m*(RmBJtVBiyysSh<#S?Us z4tV~7&6CLHwTI$WMDrT7X$v$&gmRIo59bT$xfu)$4X{RacbrDIiwaN6fePVX=l_nK zZW_(M8Ns77rFpM89FMz!SFJi8cas5KX6M)pntLw|@$Idv@a@e}N$^w_QGrZDcTRy$ zLx-qvkTM1E-ly{yxJd_VUzRyG*J&`6=EK^lut90iCRA`sQvi8H9!E>lv%5tFJ_-*r z2|gqZpM)z>kpR_?4F3ZxK6w834eK;z-y*$>E6XXg!%<|D`>;;;=9 z9=kxH4qE&6QWsRN{6Fs7X`_ND5zw2vzdaN`BL>4k8;qf;o#0@&59dYDGJFA#P7%mB zcqr%`HvU#n8ROZRi#Utz9;ovUITnb&6||iUeij=isGZR3i#!qzx}yS8((yNgcHBZr zJO0*tpeh;Kc(?=_L+pGGP6J5o+g+fETkzR*@SG1h`3Nya4QlFOZRdJ}_FY5UxsahQ z{#KmrTpLgY1Uuske6|w82Au8OU!d549l!>+Rnw)4{zsAgpERX zfEhQT?c6F558Q|VRq>em;qBaXP+I`h1Oc5{30j~6Y3Bxjgz@Nyw{uxQ7J>Bt290}z z2K&J6T+pq$@GAB)C<%hwxt^AD{(z#0A6!0z8?Tt{TukNAcJ5M8ixkq%g^zZ_+PR*V zd+vZthPHDjfQ~B$upnkef*WgYtU zVaN^D1CWO54aep>8LXqfZr}whprtH+U=~snHGtG6DhKi^6%P0+6^tfo5u}Nljn+!! z05wq+JV5u^cY;Xp1H9(!IqI6T7)S7e z@z}#y+NPje(>?zm_3hMA@#(}K@jjhzJ&-2=K(mC{+omA>XhX4_H$iJyJUT^?2Vp_8 zNXUb*;Jdyc0}1@Ci@>c^=n@SnP{ocq2n#wg71l7d0uAFq$1g$C+^{PmKxZTRbUw#E z_KGF9zl0pp10A@4UTX;(Sw&u?;fB;ag^UN_X`Y&astefYn z-aP#WZj~PAZ~F>nz=mO;gLtsj4_85{5ZXLlL%4a0sT|rooeyeALYk+rVOY>6JMa<= zPs=@TKy5o{^K>>w^AwAzkYQLGkg2H6Q_#(E;5Mf&C>6sJf&!$H<8QSCwH=_%QzOvr zqM%{eub@^TEc#!-n}wh%keKl-a->n@|BYOmU3FqBcy?^C4=(6m29H z6eHk~Sa{NcHcXR{M`BSMrbr=(+}J@Ga0i)dxd+-20bQ>LUE@~D2_A`sHcTO96yb&` zhL`Y-#A4(_$l3zrX>5v4O9qX8Hwcvug-xMqIgGQA5v!|78J^`*aLT{lFu!PeCKGuU^W11D#HTw4dg` zyG#k=;Q)_b+vQ8ZOKGaNFf;7iB7nTk26?|SLVY-3g*fA|cD!K?~sF`%RjEbJlBro0!eIAAI>Ys+aD9 zHNcV^JV2*#bh3T${Lc?LVFtW~8ML_rG%C-)5YTD<|4?T*i^p+y=yrd1@PbPZ=xtSv z{|?AAFz`2TVPs(Fyy)0@!m;te|Nr(3K9&a|r~m#x=FwTM;L+=@u@f{FyMn*O6*+#6 zvG6k-bKz$M5lkS08APyv2v!im1|mTFiVt#lH2&21$G}i}26Eea<8ctrGJS>0kHy!%-|9`~c z&W|3wwlNFAS*c_pGsC{6pj~AYI)T7td4kB9&l3m8g068THcK!l!>7zIoEp3$6 zV5SQz(0mFx=^^6qJ_hh!r{iEJLp{~L0PLyx3$S`B6CyhgB#Y!J2GIEj9^K9otp`fv zK^wRZzB2IW{N8yCY%=sf!{g2}ps#+`yXC|M z(Dv(t&pADMbu2tOLFXFv_E`L3WMJrS0aMLC7)!)JTlu7z7#Mmh{(s=#Xj%H|<6gNJ-Wfc20F^dm%+8O zrj^6<|1nR?Yy7Qjpk4;tv)wT&Ec~sYlly(Kd6)xs)(FI(5Lf#5y7aO@{D@NCLe8(L zWq_Yw!_2?{I==?V@y|KIXV|nreG5Ls1{8p>Lu^1gKwJMkyZ8Koc=sVE_#hjI%^on{ zPH}{K7c?p0+3CyR*csCb+V3oZyxE}FcHLZX!e*Jz%&>1FBXY%uo*pg0C)9ic?KJlNiN)DJx&u$Tw&Wk>lFN?DvL#GNJo!2}LzGG{A z_W%EX=H^HC9+t;Sc|c9z2h5(#?h>z!!HL&H^Mhx1xkNWh8}uX(*g*^jUvPC^@&IKa z<~_&20oluP-J_eq^wy|IK$3oQjS6U2EvVS_0p(B78Zi!E&?ZZt-W(MP*nYL{5)}ndrqJ-{ zb>r}`Jm}GR+=Ji!r-$ZukN@XAI)8yr#^T@goViHFqua~_beoG=F`H+nnZs5_&*ozs zufZF1;rSJ`ZM5}Li509o_2?GxP`u@7DF)Ib=CGB~qdR~DEE2|1%{3KDqK7?uX%QdOLU8Dg2m5u zNKtq26&Fa)b50NDJ=Y-d13KdAftH7|qzC6=k4{O4Z$}wREF8PRHw_%o07Vc7XwR=i z>$eg`5Ac1Z2CySLK-+x5RXKv~70w7rfkM05vWN8D3t&AWm zIs-U7n~yQU64q8w!V-WFmoDj7>@kg-5@tx90HG_g-U?Vd;!%3pla^mYXe9jq~HNLuB7too1Pu>+H2wtnlfSi{8MG7M z7j&eYmXG2y56*L*on;)3-JuMg-62;sd=wvfaGnC?UC-`P2FFe_h<*jfPCpjV28V<1 z*&3gNGvPCP56k7AcEdRZ>K?1uONlyr-^eL%adU?(54d3O6USf1c-eF|#c9ek+( zX{sn#p5kx41QG(@s=(Ix5NzrLP}UAp^RT>F8qs;c;~=QGb(45qzYCI`e|57=@aP7g zONm_6euEaZhd|-r(aZAPs}f(MU}D8REi zI8`BeA9iRKI75PRCb$D|+(ktKl>0n-p{dHF*+zwdzXfzSf#Ge?Zg+5b0ow1#0m^>@ z9=!n^9+np&neULt|5KgU4!&dlf6U?AG3F9|D5v=uv&Z*)Na@eByXLNjkK%KWP7Bap z+vWot9{-P(zVvARB~fJ0FAs`vko+T$P65yEkh=z;xCdpd?vT3{5H?uc0m7E>Xg~v$nQlyuGiu6(*P{|A`&HW@^8zYMGFj9(fA7w>P&LcjZijeasTALXd7}6Y@ z>r@y@s=?<49(nbB9qZc7HX{dASFlv3Xd2g4`nJ z(G5Q8UkO^)cr+ddC;iTQVB0*pg+UfVZ7TZj(P`|`?K7Fhweyr?<0DWd;?jBU;5#n< z?HBmB9|WZh15jJz;Bz)mX{Gtoqxq);fAeil1_o%C!>4=B2e1XbETB7V7(iMyJS=~K z4#!jAZ~4#2z~I}RFX7Q^13EC40hALAz-3+MUk}ZrperGp|0?h|f#w!K9MDmB4<3LF z5#VnLXJlY->4fHHpH3eY3D3@to(CUt`ZC@G^=3FcdUdXXvtPH13dB^+qdtspT@4R- zTE6t@_EC{2m-5gq0m(h%^kKZ`(d%;Uzo+F<{Pg%rD@=%izo};KM86#4qT= z`@xA{(1(}7v-zL`D5u`{Z2pl@R1Wt%%)$o`d^Jx%E%9Nz;n|zRSm51TqFKN%;5LC@ zz;6M+pz8#FLEi=Z0&W}l1^f>13%YLL7xX>AFW`28U%>AHzo6>{enH;{`~q$t_yzd* z1zkVz3;Hs6G{0@|Xnxn=*?gd(bTi0W0Z=Q9!?W`MI8;iqy?aYo*->m}VE55H4pIsY z$m2-<>vH?q;rg@7?N^8EuP(RW9j?E--2Qa9{^@f2+u{1R%k5u>>%T6y{~fOXyVyEh z89bVgadhCJyf|a-E$C}XCTSTgYkrCr@O=o z{*nlfgO4~p7%v(g0DBPLUO&bH8meLh6QJ=bM$mW_BWS#e5j0-K2pX?q1o`U#hlefL zTW4Q_4m$_A=H(+$ff0UyUyy-c&_RG-&_RJ;(7}LT(7}OU&>?_d&>?|e(4l}|umLoX z#4p$Y8ad(@Yyb@v@e6{-hWG^=K!ZX2g5c2~e!&LNa1Xy=1897QU$6l*xWg~lAi&7L zz%SUK0HF*Z6lmivzhFZEgqHxJK=*cl?1S(?S4M&CgYY&$DA4X{kbMx|0|@m2RG9Rp ztAVZzh7{VMG0Zf_Ljgv$X?K_USf90VVFaR78>k%5oq z1<)GfgHJg<8jpek3tl#9f;L+)doW)0IQW3mhw+9-ug(jPUY84?6NEkZ-H-Ze9s;F5 zPsT%@n!h~1U-o6Z?9zGT;0u=j2Uf6qbbc){fN`52uzP&J;nDdO(qHg^E_?Dg?g|=A zVesh974Z0fp!B(C^X~#5(9y!6gKjnWn?Paj!*~uuJ@m#*59mrOkK?Y;o~0|eW9f0+ z6*|D^3LRi{g$^*fLI)UKp#zMr&;dqQ=m4WDbb!$nI>6`(8DIpJAC_PFn~I@B9Gu4; zz8&W;i3D9Mq~Ozel)ohuya?eDGpJQ#;BoLFr-$Y#_<2po7#NN@Fftr-U}8Atz|3&W zfra6i11rNZ2R4Rd4$ySkeCS8%bR6y*wv8EKh)pZU!CU0}2lV4{)_}%|r8_ zN3YFSP(k1M@8CNYaBGR(qw`pazQ@5w%>Pdve8uwrQ1c^pkMFlUI*;+oGk6?#12@k+ zj)TvF^yn=U@c4hI^o2+B{{sFd&^}z${DrRmxEr(s<_2xZWnkAn}`Jem(UcxayR z=sXB+O6&lIcQ=8845<)<6=1LfA`cyW#pTgGpesO`yFD_8|#RV$AxIpOwJl+nV#(7Ji1fnvDD5H#`MYir*HZcaV`ZP{*S zMr_$mbL}iwK^v3s=(QDqD1Xt#%&?CUNx4U_?blAQNsmBMOsG<~AW}C$Qp~7Q`yo>lXP9GHq zkAp8kYFvDJvpGDvy+Iv(0njPT0U#4RFs5dhL45;$0cTKOW{L{9FEbZJ2|9D|Z@&cI zt_nGY-J=(@owULUZQ}v&GIr~zytV~pXn1|^13Fd?)E3k5=;rY3~3Z2d@Am4a^x-Q*}9^IZCo}IoN zpb_-6<{Fh0h7u9bh)@D_NW`b}JH$(<7kYT~+U{%zryc%IW`=!+%*cbjAm<{^7lUp& z0WDkr7eEZ4ju(8K*Q2`}Hh2LUyC|va4hIbk9|FzSHGgAZU^w^+bhInzB#wjc44NO> zdstqB^&UMyV}Zudg7A|EXpq)qnh)gUq0UdxHq|@uAmAfTPv$Am-U!brk8VL9#Y-NX zhdeq3J-XdFd=zi^aGvn!bm#EsE*F4|hG;<@RDy6&aV9Ms}CTE5L=!o6#!*vP`U*Ts3(Ft&&Sz7x%MS!QxLNEz^ep7w-iFhk2?=G zKLiakm8pSrdsu#gB^pm=a)%tcIYEPLmIq7az@rP`AuTQFm|KaYhvE%SOP4bm#r)v@ z=W!Pm5m1BfwK13r-hqUwLj8QO53J?JvMT?Z9E^`Oux0Jv;wFx2l1v*lsqD zUQl%w%mLYxp=EizB%tv>C?}M7c=URM?*9@%NSQ*VbYW-oJ9hJVcDtO@fQ26a_G0ib zoGxS-&V$)o;&q6}!3SDCioYPmqGPw1uX4>b4NuPFKAo1}gCh^a#_2$pjS)HB;-mP( z1G4o9H1wt{2r<0dTP3aaWJ$T>oOSn7~4|-VoT-PX)^XT?N zpXB6)$rdvk9yq*#@i6p!?qJ9~1nlMna6<-E-h*QiT+Ac<3tC^$dBLO8=dgx{rL#gg z+y6tLDJhg$5@%vpAGk0etv?6=pC$U&qt{lqftkVZ!2iphoi{w2YZVwu?0tG|)f<=@ ze0o(C!IY^GNXczb|E%@4Pvjb=>Mypoi9MUIjv(Aif)5i#h%^1 z9FSIuf=93IoqCWJuoXkGpxBLd{Qn?rg2!=paGB`=UoQln3*r}W2etb4Nr78^$3c{! zJI7%{>eqo3hOur3QN*a92T~Zux*SA7)CY9?gVKJf#KD&WrG_5e;NhfF=Wg&wQfXMk zVgBtWJ$h}U>cDlsd_6P6zWbmHgbWXWYetV=TYHFH#0X*k9 zn-Nqko%Cq_CC}dmI`G)l@FZwzvH8IR{ua<_A0E9fV*f$s^IQHX;`8Wr5&!RD`GLO~ zw1*Xw~x=gEUFS^pn2Jn-!xbBTGc*8?!O`608%_nY7mF?jo!Ux0;;U%-b=fM1Y> zonO$09W*hm;PL-p=~K_%vxmG@i*X;4pz-z+(Zw zpyLF7LC*#J0uCGa1w0P$3p#G#7xX;9FW_*2U%=x5zo6pKuU-_C>lEud|koflj*Px$mY{rA;8v4Xus1I&kv1%XN+ zxci;Dc=((;c=$d49|R2peei7l!Cn;Sqj}1&*M*NPYUVsl{megYqwU<;Dr{ z8i)@iNgm*(88B{e=ZAwY*qWc&gU3`YPn7a>egHKkJ;19iphf#Zk8XE~Zk7(%*aBj3 zwDTLN9Q9zH0vRIhW%=aM&4E;YDxNqz0n-N1CD+qs z+WJ<53LnS+*SeiSjd1>!C7?A=y}B;d;3CcrOxfy#RJ{cazqG!E6mefc#~>Yi1*>UZ zf_pdc_O%DIvjltz$^~$pi)deiZmwcxV1Tx-!Al%q?d$WPCK=MvUxz?t=zqum*F63o z?RHk--+scw@+@Th4z$z`EDS*<2MaVzd>9Xc6o7g-Cp;|Amy1D-C}nmv zJOG*=JNTakRE~P|vig=YGr-GJj~$Fq;L+*Mc+8!X@t8Xo!!dVmhGXtL49DFCUVvJD zy{r=D%nTl#?h?@E%5is<4q*m{?XC})002K3Upk{*14~MdG zna@I$`5!ot!>0jiCdm8@C>xjgtVEeV0mb|RsF@)11E6eN=CcuHz5$B)&QLQ!<|{(k zxXfoK%KQuL$l)UmH4|k1-!e#A!eu@OQRWw*n9qe|{!0Spa}s5~0E+p-NalYgU_KX7 z=5GMcAH&i=1Csgo2$;`Jl=%TD<|`nX&kkkd3V$A=%>TfO9KT`MX$-*AA|q=S~kfA;MBcZ?O(250o>1()|8$5~lGLC(OyaEz57#PaB6 zWzGRLidjJeO~+W}L4wCv!J|*dSQQx<7#NSSDuD!#g9SlNVvkkL-pmy^yR(+84 zF;>uwE#q-81racZ=msytaaPbu22eNQ7%S*bY{p}( z;Qf3ay{s(|i$F^pj1O&`IkI#~~DG ze7%>|1!4jyLeq}3g6_j*WboVr?aDCvbgF_j{`qvOf>w7QV+CCm#c-Szw0Z&(6wg7P zKgJ453yjBD!Gny)SYLtt(#!e*5=Edz7ROn?fCNEHvU+n=ICg;9(RLv!X{@jGk{mvLs#=S9(MzG!{F!k9dpwG zY0?F00(Zq6kGp~UVvfh$EEqjI-5fkSk2oH4^8i`m2_n20K{uivcToZLwHV-2cpwHS zSu?j5F?1TSb^8V6{H4+nVlIb;C>C`ceZZBU3ZcyxpA5$|>Z-7A)&0-hlRXNzWA zWl(6=b0Ou3PLNXY(uLOB{4L;fLONN%=S(B?86NQ5E6mWqz`?-809uW}@mdx(9tfG3 zh1wdUA^}=TpwK14+;Oqt;CKFQADjOfmg{)@KLAtDzwM+a|KhX7$3gx;R_O8nK=VJN zqWdkEN>}4_CwLauMMc4}p^k;2lqb#cxEm`2D8xA!x>#Q`Ffeeif)1VTW;J18VCV!7 zRzUmVB?;Z8pzP54tt1SzNAv(QgW+4~pn0<`IB(S%d-TeJ!pEoA*8Ko819bhpF=)60 zvf$d||51-*aIW%bKFr}^d9>!iaaPdiEl5{`EjXi=a3S{Ecy_xPH2>fzmIlo+H~(NR zmiA~o0xIO-dj-HZT$>g#GrR`%lnRPK!%g781QVd~(%!cJpd4p;ygc5cw;jShRvv74 z05X5u#lzOY!`|h?#@OM*&e-L{#?;}%&eY|@#@yk<&fMk0#?s-#&eG+>#@gY-&f4X} z#@6A(&er9_#@^w>&JG$C@vsGDs?u$T`32bc1^fi~1=;xp{RQ|1+!Xi){0#U7-4*x+ z{SEj9+#L7?`~vs|-5vM^{R8*~+!FW&{0jI5-4pl){R{X7+Q7@G1o|M$sM^6i!G17L zpbZrE`~rQT5{F-~9n2H#2lE8lz)P$I`XEcJ+QB@*elSm<4OC?C3-p09IKN;!m?zi| z;(@k&yD)(FzaDpnF4==kIXFWyQ!n^7x_wAlhdCNN`hheahE)GFzmb3s*@7YzsdbJv z{DD$g@;85$MQ*5HZG?1LK^5kHC>v{q>DilyrTYrmG>fax(Sc&sSE%tIt1dvY+UAJ>oZ}xKLf>lL#UY` z_X|MTxXf3Cm9(I=1I~RuSi*+`#e6HMnIQ8ep=?~{D-mV>3Tfo=0As; z2{Qi@l#R=LY~3@=q$G=C{!gfxAoCwU*|^L%Bq}QQN+O4kG&J}@<}*UsxXdT6`xlF1 zz97_0komA|jmv!Ex_^HqkloLKWd17x;bTcu_{>EyUkb^5Lg8aYl=-$O=D&uz85BNe zpln>>V@;I#cg2yz#|6p#a!@ud^KFPSzZS)OJE)l;_p3nJxXj1a{l*-gkQE2ri6@ke)qLOHG%Ou`ltKw(c+dmID&$PZ zjL$01-aH>HUcn5s7ox~sX@Qyv@=6wzjnyljy?LM`g3wwWSjOx+P|SY~H4|k1B`6!0 z`5{EPUjxPbkY+^vYz1ZGGCzVS^G}E%htFQ9nIQKsg0gX$A48P+87StfwIJNj17+hf zKLLyR=#>Kaa!CGWW)w>%Lk$LbA|J}eWl16tmhd+(7Df)FwNNub=1+vOahab)l=;pm z=1+i{2{OMJ%Eo1W2B!J=+p9N(kiC)tH6CP@1C))+ssc=_u;hmd6!V**W`fKwgtBp& zUxCGZ^!Vm)mOwE-4r(UId^;!`m-&@MnZH92Iea3aW`fK&gR*g%UqzJp5h&(MK+Oc1 z&kki{H6MI;^xFn3R$#Wnz6v0F;Q=%ogRD3PWn;C%vv(cnBr2k;n1o^lE7av6E1nau z0@V8?$_jlHD}0fx(1)^d`2uuu7ExB5;YSXr#8yPvWCvyAvI5jy#$p9#a?M1sq6um& zD4;T-Y+P1=mLy?V0otJ_;L*u}(Y9wqu_py;Hpm_mC>xhOpbM=!6f4+~taw4d3eZq5QC0|{SRsjI#V-O@fQFHYvSK|CazMR?8Vibxb5J&}xBv}N z6J>=DiWON%zVLyvaajQx{wB(bm)yv{NQD{;@`WRmjmwI?pg}(9fEC^mh&B`}U@iw) zp-aFD(7+moFK}jYITU-Wp=N{Zk%6*tc?C2lfMJghmdblK%Ce!IP-8(>%!0CUSpgax z#9{?z=7>PC;t$kVkQLXVY+P1=_K*@~#aEQYLr>^;r6=GBF8I)B-q*wtu%Yi6gWTIGc5$bY~FE&Hj zxB}`LvA$qKvEmriSdbMfp=?}MTqo9w#VE^(c0-K?SuqdF#$^R)(v7HqazL?SFVt9& z74xBNTvps9))#kC78Sw5A7sTe0#<-8xhAG8tU|Hk0MuBJ6^o&4T)wzXtS`h-tk?)O z7G%YAC>xg*cZjuO3(7j8?NDPuRuC!%?-FZ8Ac_^RR0Oi35o#SSUx4nPA}U3_Ls?C< z5Na&QiZ&=4mldGNVWO<)MzLZt)L4)e6;L)VD?sx`L|LJMVnrv^SdbO4_5v;|o?wd$ zoVDu#l(j`wNcO-Q4Y=$9O-&Hxl~@!jl8~%$hq7^50h*2{$_miADTskVn9D(-L<38i>*t>jbg<~sIed`)kf{&sMIq+_x^hH+Il3w*HtuE zb1>AE`1G2nc=YO)B!G7>RV091{KVDpZQ2BnZf39U8U+E5ZuVUulYBbA{SV;q;NRz? zQt#1vvNXQsfJf&`k6zYxS7rtee%BLV4JHa+-60Ab;FTi2ogbi{IqH$@%;DL5M8ebZ zXw5PtS6V|{S*q*Ncmy;EhPoW2&IO#P*2FV2?AxaR+8GJi+X*%`*rV|csQ2U9`K#qX zi6OtHi;4lirjLpPzh;O^0KaC8N&>%Tib?^$<{EHF@M~^S0S$ujYwl424I_ch!qe~p zulE6+is#W8q5?hwg~Ov8y!OSTTiT;@jtZm?2TGnTDv*9-iwd|B?QBs2jZ7SGQQ5-4 zzyMk}cf3UfG#mn2g5l9S1|76Ph*_na9*svp?v6eT7Kg9@3xEYn>wyxc z{}(*E!E5zA;5^VGChR>D<+CQqPp4Yr{5Wela<-L{}=8Ehk%K;EC{0bcKM z7IEY>__Ea!e$c^E-3*SMt{g8dL6y%g&@x2O@rItD16lqb_3YG90VRQhFF}{6H6P>y z9g4)@aruGA{}UdauRW0O+XCISgS24@{pKwX&J$2s@D8Sr9-TZlKqo?5fKI(IDCPBm z-P76aqGAEx#N?u4;n^L_06Hw0qgxwxo?P>B4#RJTms|}&ClGpc-UR#Cv-7BL>)Vnd z=q+9GplhL;k5+(AiB9kYEv7=8HK2IHvD-%_!Lzdkd_M`+J7oosFYFS4U)c5Cqw^Km zx^C?co{g>?|Nj5~-Ga_6?1ta@i*p+q{7hsI#k;U8eoOrD?n6VwqJu{# z&kN6H7Zr;i9w;@&VOU(gd;_{m2pX}kS9tzE=G$oky73Kkcu4a@cGLvr)A`v0DUMDf zu5w!o@){&<{%2-@hHwKTg9qpUSq6q0(Bv)X)L*o_y+F5KGl1`T<^1T=X>-%_|51v5OI*;yH36N;Zdhi)jpi5`(`53IP~R{6FMjd5ynW6O>^T4|`Z1=5K8QDTQ8@Q~|nV2I}XRp!>KyI^p_31)xW-7bEBx zv*t38VGsjaa{vGT{}Q}N9-$b#<{75A38A<(3bfA?ddA&LUl0eO39^G6Y6IxPMGuG# zt)NSmVF%{DP69dCbLl76Ib{&u|koHZWPyuOQ3A!!^tlbf$eHKW(^S;Ny_gc-*ku3MnJkQ?& zwiBe=0Ccw&NVhtO(fps8zby`=TLN@h6;8`R=i+#PwCjK@0clr;TV4jzE&}3q-t;{9 z(g>6-;5Pt+?z!o_;i-7Q+p-5-D)2XNWB?trd4Rvwk&%JnWh~g!L}_e;X#`yu`BDWG z9-a3*4!$!2HLf7(7}Q}=yzbF?%R}*yr{$h6pp;RZ4mu&A)f{wX)qC*ra3X9gcK2;P zz~5^7_y7NwyFi*O5Ae5wYQdMF>%BZdJS|WF!qST@h+}z(zZG;z73@Ab&?Qx1rQbkD zlR%GQeEAZ@>AdN2@TG3ULuUAeK_0D#ON~4%ua)U~e!l^_El3q~m<9OW_It<~_?)-p z7I2l%-=qjiy}iC1@EoTDTIJlS`LYeC75uH>OJ_kbm<2j93v3mCTO5cDj(sDKP8`-X zTY^FmTxcL%zXP-w+w<}RaN@WEy4nn6^l1>|`+ZN#AN+0mLF~>O9$=r`MBI<uGt3 zzil$;`10l-%w-ubK`GA@k|8`hZ+XBogs0*sP`oN0@VA@-&Je}mi@{=EhJXqW%LAoB zKAoB`kKzoDQX@~xOC+R`zn}~YErdCJI&%eH7J&PmqsOU$%lg5AiYnA^_s!$d^f=GQ;vfssGCqaA}Jz_DRhW zd?4?Ft~7^KH>Dh)(6j+xL=5w>j0d=?DfWVRn7DM>;HcmwOQFmT$`1>Y%sT3t-*~^f^Ak2urgBGtgwhCzsUq!3OP-zJEBzqjt9+i_?2g_39Gx65`$3IOc-Nnd)+%WD0Xl#R zIuDA()~Yag@9Jf6htjk27I@$ld63n&+uX6+ouku5g~zwsM#Z=Fe?W|~ZjB$3}Mf4Ip6tBXDIr&@UK!XwoUmG<({x8qK z;E{Qlfq{t;>W>5l1|QBB9>-b0HbEQcSw5Y=J(>?!`1a2dHS-Z5Q~m*6p7V~^HvrDZ;y+8*7-9H42( zR`8q-Xb!RU8-FWkI1Y41E=Z7-#6f6!3>wV<4+)>=Zw6K49uOOv1VHMb zdxKvxg9d0iKj0YMWdpgR^%#Gv8;D_foxjZ%G_naEp5+6Lkm`ZBIJJX^y+PVnf%*?1 z?F&JpBVg?ygI-PoadB#Q0a*&tE(RL;18L_4jp%{3gDwPn`47~r!>K(Qrd=LpyBNqi zu=aeAnUzBdBhHi?qZiQV0V3lZY z=Wjjm^Z$PjkjdMB{{Qa@HF-5i5Olig3nS2d2Jl)Kd0;o{Wh+<}$hR1#ZUS{XK&Gw) zB~GZRb3uY&SKx7P1!7#c1T?N210L7)>4ewBFZq7{|L@y*8D5N(DtPo}F?v|OFZP3F z?lYicNINxsJ8!+z0673h?f{K=9^-EX&jW%SI~6p{2^#TCc?n7`o}HgOv7}MY&JW;8 z4`?#w^=&=i+j*-r0$lX?wjL;LeeDklHOM3Yaze52u)JPo3<=~iZHOA2LE+nZi@)j9 zKZsu;1#_vSPiM9Ov|t9ww=n(q|Nmt?D80gpJlLr3dC;gYs8lXK{qiWtU%0{`#sgHi zECQtvP#A!Qf5D@^887=lVnpRSUXRw3pfHGe=?E%KK$#9yC{r&SUj2oH1E?D6E|vh* zUfe#A2>$==|9?bUkOz+dUoQ@XBn40)HJyi~hL=~rfx1}OOZkdKkJe)#)vXIbz6ON^ zXzLC*BywN&g2cc#`eH;Ea*4(30Z9spFReg@446|A0vdmg0y`2*Rsn^Y5hz)JriP&9 z#|OxS%13Br51#mfPpI%W-TMO?4Svq-*QxXSCF8gM{}JnZ(8q%@+SmM^-RzL-u{mB& z1Qo;ZtW8D(J04^Jr13$U2DWFnI|t|_7!JZM>}K38>;wv1*z4%n!j=csS%b8N4IX#) z9MC3qAEZr*+{8XN9Gcj3LB$2AY=f2JxSQBTAf?cTN*W|MhI12}oxhEeCN?{ytxjwc zTNKoy0+szdfBygXZ2rN{-xdLCBmc$Ih~V$Q*~Dh&ZyO3tZ28}GX=3jHHB+D|cMXU= zQkvNNLG5Hvs@jIs#9jpwB-q4m0jt8&Zs2dFWfPm1)=g~ovLVyNW~5aU8#G!wG@97| zz^zy4s7)!pCiWGwn%L}RRA^#Hf*pw^t5Dj+X84AEy@iHn=Q;5B^>@$CzmCndG7Kdm zp51JY-F_S&_z!Y8cKQjt+z4tSBek(}89YF1gmW2)T_ao%GJxnd_D{$fVOI-JYgdC( zA@CWH@Q$-*x2pwc<3{rV(2b22p51be-EQCkY|u?{0>0g;48E;TDk>49*gm}`Gd!E0 zp^Rcb04)GQ8pVbzC!FJbL7_uLm$U><={VdfPw$msg5-Mv=eFk zw@;_>Uq1*Me>n(h_;!Mihy*!+XBRLG;ZL`4C%CK`0}rh;eVaS6~CGSIQ2|9mj%&OejFenfldzr&^mAMtr@Wlph&^Cgk zE`tnhgLW2pc9#i&MzdQ%C9Y?88E6QBzoiSb%AnUz!lU!6kKtdR*0cPr;QOaRL)%yR zo6SL)4?12PkJRoCh6I5JD7_+$OnG$2s7Smt0SzpJ+VTIvL*=0K0UzQn0i`yGfz6;b z$uF;fY(OYR8R7=r0}L6(;BWE*4NxD4+#3B7bo~f;!~0as!iFXeh$hfR z2!@xxL8HFNV?dy(0?-}>@B(ILkUK!*K+YfrsI6iJ8q)@k5_5xEz}g`3&aWN^-)c2K zWk*b2cxayG?@$Lxf^;tijsAdigBL6}|7GTH11&mx*$om0k0e3XFT?BxuV01_aQ^{~ z4_aR3Z~F{lfY&cag6w_*;^ML!Jj(~NTMA?c$ZkOp18jE@NH-IR3$`2g`1W5=ETNBY zgX{*4;^G?^hiZh6Z!ZE3H7kIE1K()TRgiVi@oo0s|Np;y2Z}Xf+z1`t)&p4sp3MLa zwF!WDpaDzJ*msLOC{4qXiV!H(g38wgpawUz@jV5^1~tB)gL*m8E6rct0`+~sqqAtE zxkQg|gUdq5(q+$HKMr{QgN$!mzN|p80aChy*B2k-Z_NbBfnqNK#Q1*K)A9v>TL_2^ zb`r+0o2TU-h;_~SpaE{k(q&lXk81Q%P#YSQtmc3i&}ASKKx~}N@1vjyDvExY1y+UK z*j1oZ33Bm55CiJssUS8X7Z-qsxNAK;J4*w6J4+qF)ih)t(X;c_%dbBmW1X;K0q6L( zC1`wG8NF)?%UhnBCny}>h9pzO__oLY|Np5nz738!&|quRSIGD_v~(_&^zEz@fR@f6 z`IeX8|Nnm(1xl~*&=7-`rufFUk;8zp@ojJhFGh@SyMRg)P^P2C_%1Q3$j5C;g=6VT#_5%?EGy*p%KnPpGNpxP(ucqd?$j~Bc~C*2-K1W zC99br2DB003t|&&gr|d5!5SB+ZF`zE!avcv5l-v~IJD^nUt}@>jqqo*YJ?Lz0zUAK z@W(_q!gqq3!X!4ri5dWhrUaagaC@-LuzW(rM))&OBOH9+4a)iw9PMw=_;))8|GE$0 z0q{+r<})Sj?*@=KoRFkZrTih8-wf}tj%xu05~{7p|!pTtnr-- zX?a2#-v@?vttUiIJ1e}d;N3hMX zd_u*>_X|kl8*&~Zq4u{Jbo|=`++G3?fNuk}pDAg8w}1?wRRer54S*j7wS)(t1#Ski zcd)j=5d+|mG=v>V}V#5cmDks9ItkRTWdjc|I7fd2qBwn43> z_aFvh1pEPrOL8N8h>U*dwPAz7W)s1|_Q*AO^G%-UDJ2Y=ozQ zRlyn;bZUfuq;(^F2#tV0rBx$*=!}3rBDxX21KboQu@O#{5pX-O&9Hnz#YXtkub?I1 z4yfmsSRk$c{^QtP#sN9>qD0)Yo6oU3jHmO%2mXzMok#gy-o3mCYD6Qo!gW-@>%fUW zD|#8o08(4wptGQ@T~rK8#eF)TcYgNigfBAdyazteq_adt2fid6q#C>?oTt-8MFg}W zMFDo;T{ZHWaGe>Rh%=hOC!2f#Ek7n=O}HzAN9n>_&+aw1aZ-Q7Aew4Uf zte)^AJAD*C!&Zg!x5R>MLvM(CfG#NmFBbRUynt90UZWzzP+IBPn_J=ATLU@U#7FUi zPv>XMvrSyF9&TcQSQ%cTV&K_$474)br}Mv0=Qr4a*{D3v&U*;AbeE{;bbbIe&Lz5Q zR75`TZ?x<@%0J}*=sa)GB5_}imIM5*?}#|<#Z&Q~r{b|R$M47f%a>$htPlrz8j|cF zE5tuQPD1hNE>Tgi{OZU*#SL^TfCb8O@#mmqg>*6s$gwZ&!Hw1DkoNjCaC`l^XXjPl z&hL($kQ)qKI=}gL{sSGGQuhDlp`-74cbTv8X3~0!zJ^m)} z3C+-UkTfJ@d^$r^IKaW<(;cG1@zR3Gb>#8?|Nkd?9eDsKWMKyzJEPiwa~(M!L=$8k zIU|Te>viOyUdsDoNs2SE(PC^~q@ z9Ki;>0>}=~x?XV*18g^V2@B}pdO~AmSkFlTEuSG$BYYkC3eb{ng6qhU&q=xZi^z54 zU^hb7k(+?5fv+P+JtsvK)G37}70?ml;B!*)K#g{2!c79PK@Iq~;C1A#kOcAozG$1= zb>z@iG5DLEviB9@YaPHCdbQgU!mfLB37k4o``6wRQe}e&Cg9QOq9Ooo(w8#$wthq1=4ms-v-vq} znGx@D4)!ISe0Xq)E|=r&J&M}CcP;@1=KjPVK4rA z^W~7nd>E+t)9Vk}8u}ExH56B4UK><|LEA*2-FM*qT&RtCD_B$eIsQ$d2`G(uh+>?Z zLLrTLcgVSi@Wwnu6M@FOJEX0~2#Oix#yn_~E#Xa}xJKh)x=}ZUqBrJY>(S90^9bF@ zjrnt+mJq1bbri%vjK*&RagiGH2;FD-JK&o_(Hrxy(RgAS^Wasd)YueCTw@+G!<-Ik zWw+iWwlNQOBi6>e7^rCv-xLaI%tMn3yfF{HE(Drz(?BgFL}MPBKqzm_gZH?>Hid$Y zW`*WF$fi)mmsD=dL#%_GdWf$vUk+-KgOXJqhyiWPCxO^F8}s1(X+_a5ZNREPWe!yu z^H3K<8uO{pO`)~un?jExwd6rL9OtG`MbM^DP4t#LEO+4E6gn73 zm%%Oh-Jq6y0w}$LTJqq~AZAl2au{IW6gpT(OB3k46&^SC#KQeiY+@udjZW>`KUvn3DCbg)gK&zSu?RldL64Qj}P*P|bI z7x;H)*No%tB4r^)0{j}Rw{w{o_yyTv_me_y9qqjA+4uo|I0ge ziaB=su~;4|X8V88vD1$Qbg|gMSF((!96Q5UIuABKwC8Vm$jrdtxZ43V;HP=o)ABZd z+a6Ghvh_B9OC2i%gW)BQ=HCkZO?-?XHt0sE=7$gXTmCaJFmxVkerE60TVp2S)$3#Z z-|&)$<@s_!55{|*y*_5*K9)cEn?c8m`1CqIaOpgF@Fna2gNEO}9b_)C0$c6XTVtrv z8~otlE7t#qnjbNHe7|M*jbEO@kzatt+>u|v$6SD4(8c@%zaWpfNAocSkN<~CAA2_c zNGPfV`J?&K0}stlV3Rx;KYI4=;RB6Rdi9pr6{LXxy#K>5;5LC@z;6M+p!)=VLH`B( z0&W}l1^f>13%YOM7xX{CFW`28U%>AHzo7dCenI~S`~q$t_yzd*1>HaJ3-Wt3zi;qp ze%Ij9e5j#xi>KvHpUzYKEh#Jv44wBhule*k|M%3q;PCAjdx;t}JW9+YI`3;m+W9*h?}dtKP%y?TAD*!krh7`g&~ zb_D$F3jEa(@T)8EcSpeQuE0MX0e`vz|8@lY?F#(Y5%8}o@P9|Z|1QA}0Z<>vqxm3* zNAuwyrAJ<#W(HkOcbmWEGa~~7IB*+e~T(i zp;vE+p@c{CM|&T}pN9WEEKim5diMH-gX56_rf46?Fvp!>QuCx^^TPzs=7SGhI!{8P z_dh6ly}|Z^jMLCO*ZeG@`PhSl?^ypIYktP;@%^6Re^Bfo?RN&nw>>Dn?LqNv1&VJg zkLKeF9{-Pl;`?VpQ6<?ARq@-yve>@&CBT|AUbDFNy$1{130*5PSA6ub++`K5PtcX|B<(K20L|3I{Cm)Cy~E!V{bqU0e7;1GvL^ACs8&AyEHeKc=- z_LfP2qur+ya;>mO^KXYD2}rg%;M4itr}H1UljGTWy!o*`_+HD2pk#3plG#5pFfbUN z1YOzH{NMq93+VPp&)zTzuig^t|Ar?$EI*a=dG&@Ei+h5G^p1d!X7PT|c@7-QhL;?^ z9b+!B>@7x#^-J*kZb9)a4vKGa0Y`p87cmJ(enB5G4UgtS;3$9K(fl)^C=D{(_P|5) zqF3)0BS_W`u`1w~XW$obn!qpMwSZsHZ34fb-vWLCrw#l9UI+LE-8S$G`W@gGaJs-R z;PrrC(Cq@hpx*<20jCfA0$lupZXfss`5<{26vqb}O1F4e9`@)w$lo#r6u-ALPkHnf z|M$>5_w5jSiDu_5%~Q>f*gd}A0w-8_dE(f`!tdDO!YASJ{~)MLdhgNvkG&|=L-Vv( zuZtllA6v4gA*F9h@-yVdXH@%9#&ZNbK~rfpDh=KK94_7NJl*aB-T5LQ4RH5@t~%xb z-Ew@Q^L%HG%8|~O9-TfaJ30@6#5Q!EFudTRc);+4N9S3_ACBF8Ajuz&-Ek})oiZxD zJ&YAgvaTOI$nL^;(53T$;RVGLh8H|KulI(?GI)00=v^Zaw*B~vgGYH7&vu>wb?Z3{ zFDSl%G90_Zz!tyg6%p^g0>T@putM3&t>TMBt zcW&>&g9pSIe{}vbe5H8E@RehCnLuZW$`i(qy**s(`D?x&Jjl*?u=9}NFU3=azZ|>E zL^?}Ut}uS>U8ALStlb^rlv9R>6ki!0a_o+i=!{WW!+5{*o=b0!m9U$^3de&71sxe* zcD^z^<)V1X@RVbBolIwq${fZYF1>S@7^k}Zbv$@j%$4!9OXms07cPo73|}~QhbeT1 zs61f2*xSQ#V@5+JI6Q8;blz|=JfV2P#qfk{cb$q$XN}4o7skK6EgI{;yL2Bsz{7Z= z^OTF>EyY7FhPNEM<1{*BR34V|SiTXO7Aj zN5#d9(U}{Gw94wnZo$erFRLxlHi1F$Ad@M zT^aAVblx<)=%V=0@SUJoqu~<7$+Cb_s{JzyhlGJfc7VRYE+ zaNytpP8Y@pP{VJ!7(R4mJnPoGMl&!fPR;S)Q9eh;qb{8<4G)66a1b=^^23qwGsxCe z$G5$7Ja||H)zne?T_J3g}F5NCF zPh1%fgKR$W`|@*4n_VHcK0EtR5sR%Zj2C)a7_YILAI7lOr`tzm0o2#+yjQ6_@cLk@yFu#e=w|f>8??kp7v>z5FK)d{w3HI(<~klcBH+k)q!W|{ zTnrz%FkW=&UBks=@$|3b!K31?j89!U9~vHXF?{LKEusQVXfChzEdkjCj&e{!bTPc? z!g!#!g>mKid)_d+Kq=7hpey4a*Un#{U`g=a4N8Gv+dygD#qeQw2`ImP1$nt(&;EUA zHo7p!sN4WW^s&0x8tC?cjuToq78i*scezosS(2FFP6@cIoy}nc>2C(zSOD_m7%I@{R|O z3c&NJ;Y-F>F1>REQ^VFAab^7Dc<`{eE92|VgWoT@aDoB|6fiDInqOQPFE}1N!UoQr zFF}&vEZRGTar%EPXHbOoI37I2<;wWTrSr!33oe`&Tnrz$^{&xat~_Nm$k|sM4<6-r zWxVRr`2ZyS!o~1{TkjkR%LSAFI5OUGJa||X99b7Yk~droUpV!)C>)NAPIYBGbnpNh zIBmTAevuOtFHXHZf|Jhh^gA+sJ$R4{RIA+jeu?vx;UTBqIa;+}-v5WDgoB6q8Bcc} z`hJP?mfrkGTvZzQF+jL>iZ=Z&O?T`dRv(M>sI80?K$AWc(M~@ z-XRymLoU5NTo0b<{Bt~bkjs(rAmeWrNWh#lJlMNOQpA~Y@xkN#E{x}0m|awEfTTEo zx)`2x>Yc;5P>{pV2XtvVsA4*C@UST3Z)O*jCoY{QzhC6MY523Zhq0+H`1`?wY>YQu zn0-{fbpH5$f%Amn4X55U9HyVF_8vUS#dsEUgy9RunOKZi@FJ5Q&(Kxe*)Pv-}Z<|6_~>r;^1AE5rBV@Pm-N9SkH&VSw9 z%@6H;daEUlxo}G~c=QG`dUl@iZ2n^J+5Cr{zkM^P@7L=hEaB4mi1X05L;UAc7(k|+oRV-QqraKVe>QV=NX79=+v^9+n?V zKX~-ISTK4t|6=EF0$r)%srd!eJVCVAk1;SDb6{jR=D@^o%z>HVm;(#LF$Y$LV-9Q# z#~j!hKWsc`&%#_`}A7RUcb9Gjo8dw#zI>R)*rcK{Czdw_08W?=B>brA6Uf28z< zNAs@&{wB~sG^+d1)gO0|U;s6Fk2`<|r9F;2Xh8W2P}%}Y8$f9fC=Kd0F?bwzh=B3~ zpmYY5PJq%CP`Ut2H@|2Ad9|tJ|NsAvdq8G@oAw@^_hGGg!%H5ZDD&*~QTfq%juR9B z{QNCVAV-1*J3)62dG?m5d^h|LjyGkGUKc3|P>2}*=a*;j==^nzMS#Jhw~Eoz@((z^ z1QyE5hMnd4a$AEyzj#Pl9?1uz0d`Y(DY>M_fVn z1EGgMBEEhO-uSw}500;H=3XAq#Uu=!+#TKl;6acM??4dE+u~Lf0 za^`jHaAWOq=5y?DW9xF}ckFOu?{XG!>~Q1gau#&#aO3Q97IN%x~Q1hau#*$aO3TA7IW-y~0nn zP$A9XV+}E@l-r~62*|Q%$GF2_C5OSu7g64j$`9!L*!r!6ulXN;v5LoWc97d64tw<4 z-rUQ?;L$7k_aqa;K5H%p23NxaVEa6JZTCT>m`*V4BsN+v-vMM_8;}=W?sQq zdI+3UW0CFq;L!-WF6=*SeAT1bo}mO1y3cllqrBq;6T`kXF3=bWEYgwO3r!=(+&LHy zgZzWe57-Z?Hw?cSUIK>%v>H0*z`+m+Rv+xq`McBDqqiEeQ1ZAlxLP>woB~RD$DA`5 zJdQgF-UT*E{k29FoN1gS%E52fY>cr+j9*tZ0hfFscJ4dP) zx`Qi9c=!^K2f5#)dpBqZ$fNat3A-U=C9OwybpaYb0*&v0#@9gO3xN0>hTo#WK^A=& zGF}JfAcY?|{d=_j=WnqD-C@>k?+aq) zg4!+JvY=*z$MHj;o8Wvw!|R6`7#Kj~!woe;j0_&VL5!teJdPg+NrOy;kKZ^p)L4V$ z>p}9GzlsVyTK_wON;n4J&Wk11{=Ga*hPRR3%fF39+L3=7kEG?nQX!B3hdnHR7rlBd z1S`)y{~rJyR(brj2HY_xOJorF$+4kE7-S#FJ)VpgeLGJ%@^52m{-IYY>d3#%iLv>I zekr$S^C2dF`36u@^Xa_g*zND&+wCr42pU@ir)pnFFtxt__y0d6YkTzCb{u75FgyU} zLIN3_UJVa`19u;&f@uB5-?9nBIDP;W4q*9)8g`I#92iT#dK^Cp5(Whi!o3YOd?0yG zki6!JqC{7afhRpXf0kJI_42U0f&vG*J?zH6O+?O_f18M;i{+(KF3FaI`oaA2@_G#_X3===dq zKZxxecvAJiA>r zJS|-fAVJ~NYnsi*%;3{&Tg=AH;L)q=%Ek;za`5!w)2(vD@PJ3J?d2m(kUGY(p+-f7 z!K0T|7p#L<0Yve;9`xz_=gIH-&7<|U2fxb)PtXc%!vh}Br7e!#CMt#pn*TAD@_F>y zin1|7%zDk^(Q7LK<9T-1s91n~0$QE}a%Z=%frsWnkApv%JuFZ2H|2vCTXefR7~b}@ zboJnGISESoy`~mNm_R<@0((UD1}ifIBK|zOb#8RKGPE8jaRnVIUyn#c9^IiH9^It@ zAQ8x-`tH&Mh#OrzdTk3?VQzFnj$e>!=%{yhsewm#sDnqhuZ2&ytAbCruLel=KiCJa zMLl|L?OWK=xP|#A5}X-M$ruw>>Nm^0%Zyih!8IV81o8f@3Ed z>kfw1WZ z!K3pQ%sm2L-8Keb4#-20m_f4{)hGjyI!LH{cDo9Ab=Md`DmRcgR{fsM#{@hqzw$T5 z{r~^pqt~|cAjps4%Gxo;G1f88F+LVjhD zSa1MnqVyOWgJ*9YhvTs}4h9Ye28VCQ`AZxP4@_`8=EBCo03tcTBo~FnIRv zQ(ypD)~3K90ChvE;Q^HN<9Muv4Wx(x#83no17aw_7|Jk)3XGu&W2nIx>L3QFBMo)u z8Z>vRfGmf&Qv=HM=w+RF6zom|1_1`o<82mD3D4tg4p64!@iq?x(+A4*=mp;p;n4}9 zb{vprU;y=6Jvv!I{qEzeJPZsB|Nq-F>;PAYy|SQ61gZWy#v;LR%tZp!-;eFL6VjVxVDLE3 zT7wWRfik;oL5}k{_?+3J*L3A)CI(pZtdkYgr{NDjz^}=A090dZvV!_7{F64KQZ!z6%Tj435XzE-*+y z5)gk2=z2>;{|%H{Kx)A0=ORcSNaPZXaT&(A0%Kf-F|NTF*Fg;A^yAsx26Bw!@wO`< zYe4~VyzK^*>Cwwuun&}U`W`SyFnHL4ZciyQgXG<~!zdX9t8P{!uxYoDXZyfZB)0nnBr)!SKMh!~7-ApzMRFUr6e|f{ZCW`;gIEcr&>805N-6Zyf{`*3F=d>~Xvq zlzTx*9Mn00Uv zd;qk~@+LT3Jd$twWPS$SkM7@Vqvz2LHlw>kf>DB@`5+%S&O9zZ1Ml#A1lHi)yGD})Rc^q$e0HPtHpj9#;p2zV9&^0blCg`$qD3b$JyFt`~ zR$@R!e}HI+=m!MT0HIa`!BjvnB@oOA1Tz4^^gu8j5KPcbEg)MwjyF^wL<}oPl6YKrk;Lm?sd-0|@301oH=i`2oRvfnYvBFhLv3pzf6bjU7M&N&vy+KrlTJ zOa}zh0>LyuFbfdO32Vg3>K|HUWFjdd}*!=qalY)b3fQjz_jIue|NKpQhU!4jT~_q}>sY}qv!7(Kq<^-w(O z)A`v$^L3fAN9)@XJx|MbC7K?f{S%OJvgRNE`C9})gZs_4^&oRgxIMn#{@}p~GMQmN zCBuM#>(OjS_TIe z#F25J{^;iPu=Y_2DCPHPJ`w>MmV`7PA)|vHkkLqwUfa~K;3j70EsxHdo}Dis!QE^7 zX(f2fr~NBv%*OzE%m>>41=T+uoyMKP9G%`gE}hN-;C2nk_0KUEW>9;E8PuL(MrqH$ zMthnO3~I)B9B)PxE6s=iZ$^|{&4`k#85H1< z7-vX=Sj!T6ON4!Ky5@H%Y*!_R~Q%=e7aLqB7C}YR02S& z13W@r5Em8k8P(eT9^zCp{t;hVJ#YxtT#WHUjsIKmgyAM^mvjl#-;)^Dgq z?lF%}@RWr|uiJl*)(@qgNGC-we)j6++2GO3GQ*?!;RBE62M;`YYYhK;e81;4VioZffZNNzaG#&`7(9D<OY9=o{a1Yfpz7}j41@a;V4*?GdF^J3>GkIsJ{ zy|!svK*oUef(ftz@bLpkctF-mf;O(Sd;%9o48EW%$2dV%>hWWsQAwEjjtwb!TfuE-kJfJ``C#Lb+y@==h3Rjou>xtY2aRW1eg}1)7|Jw}%3ILT zt{wk287s@vrGlVUrIz1|Uh{9`F>3y4TjJ^29l+t)e1OBF^-}55*G{1MU5NAG?d66V zBar!JAoE+lm2mKHGiv^4TOx$4^Ym*D&|bY>7bZqnGP?=eCp0KlMHMT@H77GkW|#+;Xz?jYsPNkKO=ApI)#+Pkxt+(4k^} zd4`4>E|7mg;}u>8c|wjC@}`JnS3WXXeK2ics{F*G>PW+la+yWlWhrx?oAA2bKTyTGG2Myh~c zzZt<}^2wuj#8MMsxwB~P*-opPLn*Y8XW-n3bJgxb=`7yi4 z_uJ6+Oc#rlQwIw_C}sUWT>25T5}>FSH2tdi&#O0vpWUN3#EKm$J$5<$>~Q|s<@Bq= z`B#_I?+)kRT~2>God0w={q1o6+vW7H!}(vA)Bg_V|6NQS%pT2$IXs#Vadc7o&ep9WH$TJpP~aX#U4o|IX)V{W4EQ@x5)nwBEa);==MR&1CL(Q&)b+7_FE``Hb#I=_vk$A z(aQ>H+cG|UQ z!RaZ$qr2|}sHxF$e&{_i8 zJM-w?pus4?0CsJFN3ZSMx!~~ZTF=C=&sY*vtbu(Ci4QQ-V@4!&{wKhr*F?n-ny9*2 zR3ae>2wtB+xQOsUwC_9`-+;Q-a5pe`bhfB~de|Plws9}uWiQyi&K4C5Mh1rCEh?Z+ zJgENhINqX?0Pp{{sMtW+$6HifpiGb678OwMeg#LV2->omm!Q0L3?j{NtVP8Wq~%zP ziWijjhSEMz+80XuL21ywVURxXIKr_Ol|ZO?5R?vv(jib9bOkL)eHfG<4x+(v+oA$a z1;<-dV0{jc-Z@~geIPf&>I9G8J>U>PtOS85^68!e)(ARksKB%N7ZZO|CAirQvcRXe z2fX40CH-}xj<VOD=O1n|t(%T=wYIIlYq;)B@-{ z@6mbfv&T{}&!h9YN9Q{P@4Zjwxz8R;Jz5WxuJ`2%-Di=O{a^0&MK>F#X- zJA_}J!Mm5`q(`sFVX!$qoyR>o?;*^&k7|cc=dsToOASvVyWgX?gp<*uH-wYP$MT#< z=ZRt|50Hu7E{8chdTqXWSiAh@C}IW`;GG{prLB}luL;OopFz@>JgiF~(uX`cFL+p< zC~@=X&GoNB0^PaJRqpZHX#)5!E}e{^lS5 zOKLrkMuP5s@L+@#gOI}5qnp9Q8dCO@`g=4U0ToL~BPSlcw(s76OGG8mu*iMTL?~!s zmx~H?4z<_z97O)XXC{VySD8R1CTyt;*afhzO|R{{#~?R*biVTFeCgSF10vgNTRj78 zzQ7acu*>Uxu=X)%JrK;5D?pPk9^JkfpcPQc9=)*=u;QV6Ehu@wc%3i6RcI`z!=(r@ z`R08lhJ9~z5OpKW{LKF^m>D2NKe&7cR{}`&)iG93X$zW00?j*ust|CAPM~}b3HE4y zqW~`8SX4ZYyQqL_Fb1D)RgeL`txxz{wlgv?_;$OfD1d6h7Hv?o^sP^?iHc8ejf#Zf zZFqhG9cn1hT%#etP@?E*d4s>r71Wevd;uD{mq6Ov1vU#bYutQP!N>A&(Q(k2i2!)< z3g|Lbk8Tzf&))F=h9@1r9cSJPaz=@=OXt7lXUv8tk=IvwblaR@&KCgfcCtJNY7hQm zF0w=l507q<6Wu`qjITVpOHOcfmkBUl^XLvaA<&&A!1xu!l3>mf@Mu2B;$!)<2(sp> z^Poqs?Xnf1i0^#Yc?uHe-7+dZy{1P%qUiI}ue%EbJT2dsReE#_cyxPkfToQh^XMM` zkNQ~tExPT|t)l`O_|ym8PtE~K{HmyCt>d0hF*o^U0vZA^r-S?7TlQ zG3)~+YuK@i9=*1IUV^0z5K=FFJAXjj-fMe$Dp|h%l7Zp1AtH%$KLq&{wEGTa zWN`*Wi|#{c5;r^v%Oap2B0N2T)*m^BI);GO;CXh(8F*^PX+V1BOg_m!yn1c^g5nN7 zdh6MF)U&%z!{gvMru0Htx|3B)UUUSeM$b{yD z55OBin;$ZJe7_0W&g;Mc+Rh8!%?sM?XUgEnFX&?`0NK!cu=EjlLvM!1!AHy&m8zsdIS{m(DiA)op~DGy)I7~JUiViyn9{# zf*1y%v<4m<1T_{xwHX5gD1L)IJHL5${x`hs*sy;RXqkISH0Tg|WzTMR3r}lzgHj%! zPDqOqB;wO)02;0I>~yzy%>ohtEjjbh1l>8z+<6FEaTwk8F$q;x&BW#7F;Q>&T3wrh1e1+tE=#mCc z&^cM2oh&M@oh2$9zO8RPJ74p+gfM}2j{oPMdXRtHMUP${VUNb2Ak+7O2oHXzj~@HM zA^iWpyocd;55`~MJbV1$4^U(8_#rT*dCBk_WRv-9Q1$f<)ZzsfFFl~Tt@S_u)I%=( z+YWj4nlO7b{sS4j3q*jum(D}r0|pGgeLKWl z5)V`O$)i`q*rV|mlJ)MdJbTx?7Wnc1KjXiH&zN_C4AA@p){Hovzy&lBRTOVkH)_so4~&H;CH|3*(-9{hw(Ugp62*b zP}q5B{`CNzIIQ{AqqoMOz@vAISiuj_fy@ku@{h9f3yy;Kv!4Q$f7!5Lxa7fj*`x6{ z$Zh*Uga^O-Z_i$v-yWJDJ-&lvz>#qLD461Rf9=6|)#Kn(W)IDm9*iG6dZ*ZdVgbGU zl2WA@4@&Fbne7mP_pr`yjX4qHJ}uv zPxGh8!JjN8O8-xQ);bD!bekOV>NGjz2x_x?G~1{!l(2(ZL7<69)M*=#kKpyMM{+x) zbUOep-Maaq2k(MbZYrMgfS>dQD_%guR*IiIdRZ=bfX7ilC80+*3nP5JGo-&k~>_5e+(m8d9ymJCnlW?=9HuPSC}U|?|M-*&)}e;cT`=Hb!&i4nA+Tf*bu z1AUK!4-Gsx5BeBh1nuS);MY)nuF1skl8Fm6;2xr);raiVPp3JqbIN=>zax$v_EbFY zsdzli@%wSmL1m!Efak$?Mvjfo{>w8kcxE00hY7-;oF_o%H7j^^^85g8%h2%nf5>q+ zr~+{5c<6Zfv2W)a-)FJ=Wl%v$~xUOD&Tf%t3Bv6 zi|!f~36O@CPA<^ggO7@YPv<`$!*9?@m>LEKkJe-St)`$>Fr*Ry9f{l)W75K=(JG**O~kps#`Ufkb>Hy z+eXC&ly*VeF?nA80H5vr&%^KffQbqL~qN3Ys|+XgU## zZzhAr2rw;n-TE zBH-D1jlWe0iuPP}#%8-ewJ?V0`e z|Noaim>3v5QKFlY+o?Qk-a`D9IzbX)A^}H z;$MyFF1u3d!hwJ8~C(iXfO3;1=t{b zQD2b^Nms9{d^!n6g)ky2hLD372S`Sdv-tw`$Ud$1-Wu-Be|P6I>r+QnaxP=Q!? z7|H`%hbzm?11l=`@ae1%@aar%a-rpLSPmw6_w_`)cy|%hl4LcL5Mhe z8hqxRYv%>6Ecp)FH~?2) z=StO}H7+<14|-UhE4D%j#Nx#-uYrb*J3$4b7Py>#2@kYW6&~O~yI3Cm60~~9xATYR z!584-6Y0Fsb6%EPj)OyPDLCX@LAx&ot7_`;+42S>58;~r+nE?g5(BjR-(NI7DDs`)nySUoe6deCae<1Q*D zph>yce(36%YE(QxYqKEcgLjQKUu5X?Q85A8=PLQcvH1z(YjIb@Cm=IGRVH$O+Nayx zxAhx;2WTfgv~{Hb8cWbw0lJdKr}G0eAwK^9-$U_4=ga1Y>`uKr4?PY()bijw=+Sw? zhx39f_#EMbj{F*~pzBzC1^6{C@E^N)x0IPb>>o^owD>A~-EAS9Lw}MZ9MLkX!5q>D`d5O-mpd+mzyW=`$gIjr^&N&0bixWUzgr@Wcc;)i=|9>CF zAI*>0dwE_Vyy?OD0jD?F`NKq6PAAXk)pp&id5#i4g(1?cw ze84L9FsO+v0?l-wahCtbeLA777*GSS`5@m8P+WRke&F%{gm32`PsJ;qibv8MzaIg0 z9YCioc@5zp>W(25uSR(4QRqB~RotYRCe)!iK`0phgigT@2E7nfZ1G5qS& zdX>Mm3p8(Gd6&O=5~%TX@Rfe^BWC_>haLI1ee~#MDe!3i!02Ilh`;FzXe0vKVF0yQ zJvwVtI6!kjEZ{m5)Fog6o!G(gQW~^dsq=!5;Rm1A3m}K_w}MidkL3;i=1x!t1!l=< zNB(UuJ$iXEJ(@oxEXn8N#4A25FflN6egv7> z#0F~6Sia^q}9zszGzHa_GsCI$-9bAHfw&Pgd zu$_wq#cyxvb_;ltwcr+hDsjp9gXDd@<*?Kq?; zX32mTrSHHkZ9|vN-!C_SeT20TtVnPRGFY-s7nPrAyuYJ=WqU&pP*x? zK?Bqtuv)ED4HSO4Q*eP>iSsTEsjGCDAZC7G@J+0HyNz&vd6*KTFsBy zK~3C)FF>`Qhvs4a4$we3D5c%yZvt=lw!F#T4r=>=JA|;*hOLe$)*~X&_*?ryV;#E@ z#V<$`S`(-!59G?XUqJ-`EJ-4jCq@1q-*0Ub3b>!FJbmZ3vgk9Cra-fu*KTMWen28~czwGd5 z{Y|ewdqf%@!vj?#((`}>&X&sq;@W>(F|{;HZU+iFERnOS9inO3*ghf zJ1$;+>f5d9+xoUN&$H9ew>uLwqsHF~T1xEOohjhk`j)@74?L=!DdF4twq%-Tucw4h z=W7qc&pxe>`CCDg^FEfJ`J25#gL((w>N_?+WrhswU-0N<2>_K!o|Z@Xo1#D^0<;SB z1CMvW%>d0ig3ag#)k1JHPB`*!yW!Ex6A5Z$dRm_4Zw8t1(hxjg3fBxeZv(6uG)d=) zqWOYHFHay$a}(%(56|O{;DswMbx~aa8ZZMJ0@}ETY6yx8nn3Mm&*P4ujwZv)+u-4p z_nrseYdM0>%LZQt2I@0iHJ}#lBk*_yF5355si7@=?46 z8!zN<1}*5~-v-lt!Q+0!7Vd*L0GEiWBIu_0#OKfO1AQBr&oHv~Zl~Rz3qmY&mNTtcBG918q?8QiGyl<@5a*OjFlpg>Ogf$V)EU$hE>izn3qL-P)^0>;&(yEs#Am_r92)av(B0;WS@*U)QSQ0_X zy+u~w^5}1w5l$N) z{5d=5&WX;O9?cKgOT>48YG4n|6F!zd_?zE?MjIFpdukr{*un7O|9@~0_I87qpp%Z8 z&w_^gdVA#mzyJRqEC3oXh8_~30GgD~X9t}e)coLwhczo`Loa_bc(e+X5E&RA{QvI( zE?64C#<-n5BbOe{$5=f6 zAM$8Es^DRHx%7%>^A8^Wrgh-4kcUhj2OqI|bbbd9ha<*+eL77(cpP^T0G)Qj0Ahd} zP#^{<3K)DkOFk%oc+k@+Tm+z}<+%ue_pX5C9YFHXQz={opojjs2!K!h1IZ_VBQ$Y++OfYyf9~bZdpCNmmzp3E=|Nk#RXC)yP9+x7WF5uaD#HSOyBH6RI1{6)t zA9!4R>#-9N+An=NK_?Zkc=Vba_vrlnS|x3QN3S!7Pp2{LfB>|8CE%TImY<7mf=-0G z;raawXk+3Tk6xYgpv4xR-|u)TzVYpR>Zy4bv}o7R)ACM<4tOIee5E>n3#efVU%kr* z$`s#keDGidZK`De8GGNS6Qa810Dnsqs0nQO26T!ve>13q<<-lw7qm|Zoah)2`E)+? z_E-TZ2|xLQg%w@MH4<1yFLZ zyjFS>bZrHH(_&EJbMO(XC*u{vlaTWSeL77zJdeBZfa4#;0LMRw0gHbQ1rQG${~!i9 z{y_{_{Bt;fc;NU4F~IQ;V!+~`BLTz%$3KVxj(-pX692tZIKZn?Knr0lU-38Pfcg=r z>zzD$ZMieS>z5DgWMbGSEx^F=+8eatGXpGm8YCzK5;Ox3cq3Le8-jPvf@;-Hj+Z!thUoeXwwHryMwJcmT8*8)81_yyWIL79OA*z5YQL4|_Bp08fi^fUma&-I=1{(OaSd zzmgR+lWySA-Jrk*TH)uSBH-EGb^w%pI$cyGU}kjhIKd#m0J6R}*aD=T<9~pHN4K+p z$H4~%9^A~(dDZ{_`8^a5dUSewKyFBl18;9ZxE~SU9?fqgI!}9oR*Qe~?EK@|+Xiki z9DKp!Vf*j@e_sCf`JfHQH<}+XLZ<5+`M33`fU>bi>q-9B8LSMTGs(aLjL>C)73t6^ z76s6j1)B}vZPAc5FOXSK&?TzPPuV>VKGpKzJPI26ISLy3;n(2Da!0R=3J3qO1F-R) z6KVXnPp9!;KiGPp#KZAe3)o@?k8bb=bkHHUkg~-QJYntA`OK&DBe-m7d<>dZFEioEpr zf7AnV(QA=Mr@ja5qE}E8)}tG8p8EL{VZ2JHp)=sfOm9C|lrBAO}ut)Lx$V5QLzlRSgs0{S z{*Gf{<@Y^0kMlQO1kFBLp5$-21JVjwE9j6ZA4`bVUYOQzAg%Qv9zLyqkZi32 z^&UXB3W0`;azH%rEwx6VSV9^bJ@0L~=Lo2~3U(_yNHOSqYEPJA*us2J(^&DRw`C7P z@hwnj!b1Hukv4!1sey<8S|m-7_5WaNzN5IQ7;Ft_?wHy!_n9 z@;<1;bJN%Ie3=m>bg}speA7MHpYouP>h>;1d<3&L)li+Hxx-}a-+5#~aJTC~nqZKJ7 zeDs7yE`Kw4Y^F0u#ly3+L?ytpvqr@MoM*2>a%|_Tm(t*Q!VeyXFML`rl=^|E>Q92x z=LgW@FwmwSB%@DwTeg7HP0`Aii$SFTXjww9?bkSPrS>e3iD93dAfm|viD6KFg5<*r z9?%qvkB{ZS5~bI!5LvJtlJpSQ8}P3>F6^StKXfKvHZ`B`5@gUKhc5W6N9V2o0S*|dz}MX0 z0=JmJ9nXdx??C6BmPj?%%KR^p`0ffiO~Rp6xX~BP*ueOj%kaQ!Hp2t2nG6qrI;LAe zC0b{S3Wra3s(?>-seiPozBpZzVFld49o=YICfD1jWDQyJC+{3Au0-nCqd__arksThjpDn z$DApEDtQfXRKtt|ow<7Oy%A)679zKLDjoyxRs{tL$ULxBIE(=I<{`%?fr}`}frNw; z%VE%ffPvvR{%zp!ZhpWBIv!jI6w?8Sm@ZKXfVuU9$A51QP-Ddabgn;a7aZnxZD`bf z@c7>WI>{KcV^{!YhT%6D3l_+)u{%Kl*$E0T#o(y)>}^MH2dn@64?1K3sqxE<-1znE z2Jc?3NJBJ!{d!Gycs4(K01b2SV#gPr&Cl6A4?frO<86J|Brfh>Zo|Yn@FhbR*%lt(2fDPls@gDcsT9*VbF>` z(8RF^WHS;23j=i3Vhsa>$HBKojZYz6>7!V>(mFRi{~!14*7In6TN>@#Y3JFU$Ke5* zCS3+zua_qPlBn_Q&XWL%wt(h3J$wB?soux%zenqL{#MW#CLWg8`I{jP98jUh@KOyt zBMCW8{ACKL2I+hO8boaUP+IC?d7)@3#D_+pec_NC1@;iUmgaBz2WneogLS@#SXEjK zwuT?n+&JzA9=Lg#jI4ma6Z8ukU1@{sk!;H7OIou_>?5A%0` z&P@T`iPQvI76>}!um#lgeOV1^O2K2or}H;-O#tXTMa>)h9VH-n(1{OsK^1`IP5u^; z{+FOh1BmxP)?sSvgK3)!)3zAYUhN0*kZk+m0bO^{dCo)g7=OnSn6^`(b{42{4JsU7 z?g8;2L(?Ejkt(U5@D@rFc;gi;%=F#PS*99+4xL>9Ua_PaBc&rEQfAsA2+ZQdX@p-=&>_3ffZ?~Oo%|L|oI9*Q?SEnEJ8dMrijU+xB} z>a|@H0&YmA%t1SJ1GKonqt~_`rJV^1B~Y4%bWlPDi(imw||-f;SM)(O09NAaf)$g<}k&w<)boiCv~puxokQc4G%AqHw@ z($cBPpq6{Dp9Hj21T8nRd}#unTZP36uZQJ@Vl|&m%a<}>afEZu`Dh-iFavp}2o!SO zud`u(!k)9fftM~=zPti%T!PF2B`xGI)&iYxY55)0u!Mv$)+E&g>OH!2{s3=9usQa! z<>&wZX%jp;KY%uYgPMr0pi8C?f}53y@g>OlYTrQTUmkY`7rDos!DHvgon=5vZ#<4W zgU?7i?hGCuKkf`_Z!v(j4798URUnPWBv=?2(wcYA0ks87#5}q;gO*Hqbbj(U_{spb z!{6gLcp(KyiN|rIlXaad4uTIG1|KWSAHsU?9V6(l;pZSq5G+=5$ z3_glKaW%pq&ACo+3kflQQ=$X9s3=E!@CrZ71x|0Q5Iv=S1w+C%_`|e?RqErfY z6qj%3^Vgz~F>$a-uX$lN6@r^+pdDS%`3KMiaUQ+4T#LXS6p3VRM^S5|{7ODIP@7YoS zRg;>BLB}hA7E?5^uNDW)ieo(zDn9zmMigk6sgg!%Lo)U(0!X7+-?VUjbbo=+PVSpz|X5WEI12-wraD zSUUFlKXB1J2^K;ewgQ^xA#mP`NAs_Qq72X$nC3?hP>x)Ig(u>?0cxDLa=@qa5afP! zm(HJ>7hN<@diJ{i_t3oHqj}=nLG}_wm@sIR?)y!Cd4?_-amS7rQ3j9yhdlltEdAio z{DZwH%v1BaujYBrUKdezk6s^fc0_s675K9w;AdChua1CUU4g$l0)BS|{^3;vs3?FsI1;Zpy?SLnfR!9`{=sm}`6t6M=U)uRoPRSMbN<6{%=s_F zG3S2_$DIE&fCln9uYnVXN2l`-hYrvb^brlj5*YCLk|^od!l#o(#k2DaDESG1=I$Zw zYtZ4jh+{@NeN;F+de;bojy&7}+KL6b7q11(UBOu52f6SH-hU_ad=-ywSB4dgr3XQ| z_23KCvs9W7@;QRne|mzhclhXW@Fnm6lZq!iX882#H28J9yjAeE{K4Ozzyewu&;Z`s zWch=?Er117R{Zp6dDtAgRT=D#dOC61jh9Gf378-8=KJX(_G(d+W^hv7F5%R}W{ z9=$HFet1|OEDP}HeCMNi%%itbz@s-xz_IhCBPauPz5r!YdGPrj?jQIC`1u8$Kky53 zdo&+c0MB7JANW)H#I^N6i9E)94$DW6PL@v||BrcCzAO6RtN0HzOC#aadDW}e<*k5k z>yr{rr!Jqj8jc-2Dxg#P8y|!G@6v4naykdJ&j*TP#zW91#{d8Fi23Jkom-$e?}IOF zJr(~p|6nYUZ9Pz$2^!>3@axq1@wy1?Ab5O(B|xVzXn<}KIQWyvHVf?!{h&9P&wKLnj-)m`oRMlVo>nuE>RJ9Eed9Pg3jCk3-Gsq7I%WX zfpw^7*4*}O{SR8Y#ZV&R)hqKCR6m1CSXi&zv(rt$vy;uWvkr8~7k>-rL<7T19?icM z_?tlc9YD(gKr37x@V9_AJ$d$)$ovN#5b~j%&!e|Q;=iZm7ydTTk`RyH;0K-8558yp zf86k!!?)wiB__Sq55WB9=gc18?}HAn0+*+b`~oZ{j{E{XCIV;&z8o)o3@%PHK}UN* zic|36EndAPY6bB4LzJhKo!@e(p>&If>iqz!O>5Cd3cZm zQYIe$QF_F+yN<)L`9BkX6DWImcD``z_5bJD&F0a~asqPvN;Bes7E@53YFMwNn003BZSgT<%w zXoJEqxED7vqvW*C_8Z(euH&QK6o^`GJp>8g-lk$ z?gj%jpDaAUt%?&7Obq)bi9k=&O+y{OlmIm|LAMTqHX3_CPk#cR^4-D&x|ceG(Wl$m zvpe6xvpd|wv-7H_=3CE$f0;d-|NiH1Q35w6j{0_|2l#Y8h91@AWBHoD8MMU419Z$1 zto5)H+Il$QWBJmP-{~yqTo%yzn`c2`2uk4KGS0K}7`O=mx-`YJyWRn`*hcdOq>m3u z<)DMxK&=I&#slbX1knEJ|DZE@psj~*pw`1jaO(lQBL%(nVCdNEqw+xWC2H$IfW;hk zOdE?C=#(}y=($D*p~*Y}rPW{tIj9Yhx~bP%0G*%Y()m#HqUKA_UKbTmYr#YF#kYg( zB}!0XNMixAz6RW0kP(A67e0cU3*nxcS3EV}c=o!8L7NNY=Z^y%koLk6aC@QN0p46F zcku2NdFR;~?g1({IXruLj(K+a2Y@&NpjJW%sQnP`(c$!?Bk3pPkOP4ZuU`E>kovb(c$$M!ZPUa`sZ=*g++(cf3*2#wDfBMIXKRvTNad%8g{<{k4f`6HrFdK zl<*lIczG6d_U3_?$3TtSUKbUC6&$5p(Arkub-*#u2_MH?R0J80xu^(%2w@N*0wP2~ zgcyhr2N9r4*;FJ!EGZBn4I*Sfge-`V0}=8J9=(Y6lt(7W@Kdv_J(7J?Bs?-tf{xV$ z-P_*T9RRvAt-JpPXoUi3C4e>P?6Gb&-_GS=q2n%)p=!goKD{|A2599QsBy0WIwuuz z@#NWJ6~}HH6_0L~7arXO7CxP?z}X3O9`}DxqrBwwOVA0cxXlv)nI{3QFFh>J7Aru^ zGkJk&*7=v93v{4n@yj!S+*1J3UxB1w5uzXL9t})0PQSK;8jv;tq~8IgA93I0S^j1f z(1EyMKVfsjX;2G;1A4xl;oDuH5m3kxdlNxd$NBWG1W_e1kX9Nv0O9QeGVe?FY_4Ts zC_MzZu(_0>bO$J%b9i(!bTfbpI#8P#BxC?8_Y`0~%f{oN>)SwM_K>v%A3Xp2GHhVv z-}V6%rz8y|+r{bd|xjp!y$tUr%>6O0&ZQI?~{AoEc=tacA%#B7vlAZOJ0NG<`h(84 z=+ov~0MFJE6@c8%W zE@gm)cX#Oz7!$N=F4>g z8F~FIcx>qbs}JJ~w{Djm3XZ)FjG!iD6KHjlYwH1UhX&LFV}M*#=+b#W_5c6>^)8kN z_*)YhLFY#uIQT-`zrQ%~e6}K_!^DK$BGPvyBnS3v?_Qsukd2ACF$!NXUuxPv(Nwu`z(I9b#Y*U;z6C zeEO~>M7{$g4?1rhEaTB@%WMzMNW0t625J%E1IiB`otK;IWf)5Rq0>{KAyH-aZvO<2 zPRIs&pWgBW^r<@m$ieuqIa(7H56Dm*XpRwjxhyQ7Ag3o}`+{-V=h5lTL7|x>Z#8TR=M`{-1E{bklIy%E;f^4sz>pH}DX2bCnDO ze`_h|P}APJ3ZLGr1f+D?dC)_dtJ^8TqqFA_XcEMu(~HBS^D=sF08eCdAkQLm!1Kd< zpUz+4!1Cz4^^y-ogcj^PnX&Y*`2gXz&cY zHUzdv)}!+>tkiK)L0Kp3(cKJN7=pP@)~EB6NAn>I2mWnmLFF~a{{Rb*&RZWm|NC*k zoRCc`yP+0(fKTl|1W632Ck%Q1KjPD=2HMU5KY|oo8-Zs3{+|Gi<{(YVAY}{CfU+lK z;^#jzgC}He?jh)~#>R(`nfsIAnS0Kk9-SgD!2>mHpl)$1=u92(oV^HdY^Y+Jm4FCJIp671`E!On>f5-kiPg8+0lcbUvR4Xwmz1u%~@Gf4vL<&zD~J>_iBufTuIRdvuDZcyxXSt3)dGI`4VF zOHa^7ke58*>3Fz1K-to>*NYLka-^(B5!RsI@tP+-CWbzeNPJR>1_sgP)!Un$LioAmGt?)!Nhp5=A^ zwzz+w9b7m0TR;ZA3;^+v^uz4;=sfMA`I^7O9j0F#w9yfypAR&(2(mv0WIqFlhom2| zS^;8zEKL6`(2OET|3y$#f|e~5f%G2+@j8z~rjU=K7UP`c~_|^!tmK15y`o2f!Vel^PJ?}s^7N>(o zVp`>X{{R2-HMng~gl)y{;Dzm=rKT^pfmRP#-h`g7a1yjr7{t2^T0II&G#9|4xA|MQ zgATKXW`Nb8{f;1|OCd_ZU6GeFzzH67P$Fn97QT-Ycv!Amvn^0%!7v0=&LAo6A% z(19S}1W^?AvKg!j+XGfclqz`kW-)qLzAyF%Z7u?pXb(XRv`$OU z&f72Vp=AR!$R6(OC6JrBOda4%@;Q1OPB<(_+> zI4$P#Z9Pz0^wI^ioWb%&N&D+Gk6v3VV{k*h(3y#0pMwzcMi$Jd@E|=IT?dt8ka8b% zYD}GgC#2l>?7Yq2^5X0N|1Tkh1GE?|6@wO`#jcPbDmncUbO1EOE!axGig0kiOa}!d zD1m^^(D1N)S(5S+)R6>bUhu*bj8ek`QEC)(fo9YrUTTAiIm?@+elLT;r8F$fz;Y28 z-oF7_7Y|;K0j}*J>oGol0UeM6^RW!1rYrV=c$mKxbOIh|dB!QQGLR#%`a25jZ_w$7 z-~=%dRDM~$EJ=R}YV><{9`ppSVmgkTE#AWu1UQpJ5=8V%V~`^)Z@d^^ngP8!=5AI(DBlbc!S4%LIm~}fBv>qr?F?>6r z^QA}kWbg`+Zktn}m7|^72inE=73GFY z=zJNy`;VaY9iYpF1Ux&hgFEGENSzUsPC2}jd>hM}TBNQ>j0%TG<6+P$8gSSA9;`Ql z%JXPGA^^Qd1T=tx8s6XwYdo6YXmoz=ym{~?N9V1BuLKUhlkn))_vqdWDz!YiTS4Ov zo}I@%HUE1a{Lkds{Qp0HOEP#)<+xAxT2PeucE0h{{Ns7>50kIuAO2?0I5GI}#m*8H zna&Uug-#z874Ke_C7=ZwNK-67J^7u^gQi#nJbG<nb;;? z;NxGkn1KNu4&l=I61rZa^uLGZH6P7$pcxnim@s4t2DDy-MclE21!?}}AA3=_r{+~( z&9hXUe>wW2^awP@pi?kDom)XE$-9?jpGPM+HG!tR1w4Cs`aC*&LFuR4M@0p+a-+LM zMdmfPS1-$csKSnjKOG)_I|BYWbQFN5SdbTGpv4cUFhVKc3@^c^sB=1hfX6N^fAF`~ zf(F?-e>xs~DeigjA&=oDpI-2~b;EC7y*zx-LCj(s&u*3z9?cK_m59Q|n=C6hN~Ary z89;Xheg-WfX#58nz64K#mmYr2;n5ucTD2k(37XSv>I9cQyj|Fa^&G)BZN@{Ctm|ZA z*aymC;8GSTy@9U0IE=)1==cEgB0T?sILQ75m!IJL8~~YYGCbf4nlU}Zz`y`rN9}6( z#8dGYWRZ{I?FpXUI`_e2z%Oi?A253K*04fvF6ulA9_gM5YS(nTg8b{*naknR`LYBw z0t>ev)FkK@@aW6{o#^V(d7<>3Pp2Yeae;5=o1z7V|3SxS>HBoPfXx4aW^g-?gSNG{ z9w_|;+B6^r_A+!V|22oJ;oH~Du7+>-gXUo21;H@~4hEl24M^dRJZ;RV1rFlWY9@w# zJ;KNhCy0HJ@Bm%MbLpwqbFHiG&cy|oK&IEhgU*ndoL)#-ktxWF`kRe?abf9?;AHc>czR zeHK6-ON>mg;!!6yV7QUU|JvEPe z9{kVjYx%r56g1hz;SDNR4!&SQs(~JQ@;jY@)j*)CfdQTjKr3llj)1z9-L)FNogYEB zICA)EUMv;$>^$}oRR4JOiahY>3^jNOx}L-Ek|+3XYS3as!%Lv;tKhq-?}2hruit+k z&5MvlgC3S2%6UN3tDsBUKqn@6_6DLZ8Z>n5^?Tr=30X%7TJr?Dp)G9!y#7I3-Ey$> zDR^~Dwom6N57_D!AJElAw7Z|p*YY6JdclvN`sbo&ZyBWix#rn<15^dcxO75fAXQM8 zjChBP0Cf8Q6X?2XpU%TYp`M!8d^N9m^p*%fR{+4u+pfT$9bw@0f??qGf??qGf??qG zf??qGf??qGf?=Tbf?^)c$Ds57p!=#p3pBcGHQ@En2airy4On!6D<6+uo)aFOz80Wm zP70tK7bQBPesom*gbZIp=Kn$GQb6YaK`hApKZpgH{|B+a^Z(!hZ;KAE|B%&RMyjBJ zxlU#X4}3f%vkNG-gN|Q;Ez;frnhEx}{GiiW0HRL+`-SEQj2+G*o(JC=I5s?Gbm_G8t}ERzMbzpHP3;U^;*8;Z^gzI)m*=o&XAd}uxO9V(Ot*`Q#A`l} zUXhnzRbWA~7vz8kk3bpHvD=@clf$#yU%{i(gTt}8zJQ5;ii3b>=MlsI6FfTqdi2&Z zIyThk8!(i9gr{;3(5h9?0iB@q^j86LCk1G|;!6+k9eH;cKu2Db*y=;pD}v^SSpR$W z)*E1zx>d z>_C@ogXi-R{R#I8{DS^S_iegw;1~2qx^L6{0>7X?;=WDy5B!4s9?kC?JeuD%cr-)S zE1vb}JOybQcD@4@$F=`GG_N~+JH}q34iad7#_sX`9wsyw2KE+)s--@d-aA`nIq<-yP|$}#Qp4w`qdHlt1IevN8InOs6QQXf4ZXncEtVd ziu%_P_pdAJe@EQ^E~ySV4{&)7y07!#kJ2N@STq}&aXb2Z^30J=w1WJXt#?BhfimXihxJ2%UTAsg7KyY zztd^ZwUZvbHmK#IXXkNniUn<324%YlpUw|Hpv8!Dk$T9W>)MctL{JIo32v0UgfvP# zEx&`-BK`yyiJ%SxMv-U-X_TO@MMOyt@bb}-Uy#Kdv@p>eUP40F-y)Tep1nTiv@0R! zg6=GYG(KL!nW}?>u{5#9;*_ zJpGefK7!jP-8Cu^(DKo@vqmMtvsdIksN_ok_4+(}d5(K_`lw`p+9d*@5|iUKmuGLt zT?VicSh;wZlD3Lxx4VExC$ncayGN%p$1!IC2FLDt32^4|=yV3Hhe0}=9drMKgl8vs z=NDRj0q2!Vkp6>5x5)(`OEdnK3*h{6$iwnf5oUe?wI|^D#Y6KnXqyitzkrSq2IrR? zP=0yq0c~r5@(ZLL!J`6d)#J-9pq2&^`Q-)pR%%e5nTeEVK*LB#c?MMMgGQB**6$+a z8PGy0j67onYDSF*Hz+(b!Py1UpwL9*7UcE;_WS}~dQHvz0&7p; z$}cV|pe4PK3)+<8u zC%DC|4C)_uTl;h;bNGS>X_mWTB#v#`y#s^$kt(k4LvPw6^i-wD#_0`3@@d!I{Og zm*u!er?bFoMUQS~kmyS$Mg|6$l9!+xsbL)FV=T`ZoR7IYX9SZ>V3HY3vVcieFv$ic z*%?4v0vLTPKk&DJM%NsB!x&vOA9?or{rh%^vBbioo7w4@%L5Ju5XlK9xxgehnB)PI zykL?KO!9*bWb(0mSdt8G|9W(DA7eSlaLnZ(BZy!E5zHWh1w^od2sRMG&Hz&Ba*zYW z;RF#}Ac7l2@PG(j5Wxo`_!&H!4={OJ9xGjhww#||9(?~hczD&b6LQ)k=qw%2=6{T! z^&HK&|AQJ|D2tU14}b_|0p|()0^SSw1!4UW=MDS< z-Us*vVf_*33;Y7!5BLRP{SoI6`~uwkf=K<5*9{)c$H4oiE_!rc1MQy*F$L|PGGO=6 z{0M4oBH0J(Peg$G6A|G4L(W93|Wd%nmCwM0Yi^^;NV=OA59TcDxrvgfGDxegn0!nczpcJP9 zN^vUeASIyWrUFWCDxl=10!nTwpyZ|kN^UBkFDOxgQw?aT2>23t{ua;)h#uXZ3Se>Yyx0N9 zhB^)g{ua=e1(4N+lq*q-On3%aJ6 z!SDc5cssQG=WkgKzRk*tf14b*oqWvle#vvtkaFwo5`DDz@#rmv99#rlBH4PNG{>V` z+N1S$=@Z8;9u>m_{M$}8|12sE^Zb8gQ;|n6FKA56@BnQ5ujNvSh$H_t5f%PzhMxbA zc>F(T`Kjd9YYoqCGf>X@Rs!iG_JWUv^y&Nsn<0pEj0X>eBk@5qGM5CwL+6u}nHctE zNis0J7WU}1-3t*60-a|OC5bYJfVTh42Quyto*8-11lqXp%>y*MauL+H?F>;7@a^_h z@NGTG-?ASf+ib_c-?|yXZm7#(;BQ&R#J~WKfioaI=rO>e()=T@)EKl!3=#vPpx|%? zZEplEq+nnGhd=20VE%2E{M(p3{vY)Cf5`H9$#aixH}GZ-4##7z84RAukSq53;y?ps zo!@=CT^Yc^{ojRu+eOcAnIHVym>n$-fkz-6I?k2KK>NcEE#FFH9r?GJu<&owVfOfc z!17(mYtS-%%j-2KUV<7njtw=o8Vvj`pu-S+dtFo*T@Amz=7Gf*$P&=~L_VG0JPtl% z_2{-S;@`&3zwM^wjnY`3UJ)Y?&_#rx#u3CnEhkH4__y)%Z({~o^8c{q!IC$xO%Uy4 zpU$VgpmVM-dvwl$%kAGzq#;lyJ`5}vs>gB|28H^%fs*xkpky8 zP&=oA$5pqJXD_E!_-9U7Dy6&T2$vj-_8?YSy=u>jE4nyfKCg9&YJr6 zu2BJPQUhWBZ10xv-ePYh3bHvdp4ss^2ccmQ+) zeMy05ug3%ES@Yl<3fN239D55M9DD~pd>%9$YIq6R{~pbU6g>VPEB)@#_!Bh1RwVAz zc@Q*Y?4fxPG#~8Ic#z@$|No`mJuMG-bRI0_H$3oK6sdlNy7-6Tfe)UDz0w@;#tC>; zlYBfl9)r`F81~&~gzc3Emsg1R^Jsii0a`5D4Zb44w_8QUr*nx)0ayrJTRJxE2X8>- zZ_yHBU~p{M{}HrRioZnwv=gH@KER_Fv{%;O!>2nx0JKOy0=iP^|NnX)#TOo(%pRa3 zjsbK!f(LWHgU7+QOrZP=J(P^`g-_=@kAv^DK!e7N?>r7dF8c-_L;>E^<#G9u2jd~g zRVKO(51BnLKl5b#=3)84gWu@`=+Nv6AIncZ{O+F|8}`43xNIY+%Iu6$NdPS?%7CZE z_5#oj)yCr>Y6WA7m*H(h{XypZyJt813dYhy9-TQV1)$wr6&?p)TR`_adUQ8V03XfW zIRiv#9xMs*=)C7~@EQ1ohzj_j5DXrQzdSfUc^v%70@||=s>2-^Ji04>cyw!cSpM?h zcmD-GoyPs0hvj?zrhlL^@BcCIz6i^6Mb|t!V^jh@cs7EL5B?9e8g=t1$iF_l3qe$g zKX^%P+5~d*ALy_L@OlGJ{*5v!r8|5eRfTVN2gt9U-3=hWLgKCSppWLsk^)d&9Dvu? zp1p;jd6y7PW`bjx{IzVhIAf8}HO*^}S>o(Jf@ASuvs)e$WcG&X=CuJ3;;g9S7c>qhjHq`I5gC z+@tC|{4ySt>X7pSC~trl{4g*uGJvuI|E`Ay#cH5^6s-*W3=E*=VdphI28NeM!K!etYdIeS10={nwKJbbuPsv~qGpDsf|rea zpaUBpv3N3G^zG~bMTt-6iI?9Q(e)mSK+^l4M+J6)NVkg0OItn$&^;XB-X*An0u95Q z@@#(efWPG;co?SqzlY{Kk6syb(A3rq&?MjUCM(c3tQ*aM5!2@ZLLJV|~0%9i1c>=$nH_}X& z^9FuFZ={(l=L`IT-iVnj=*cgjUL$NK%g6GfPv<567SOs}@R3EJQ5cZFu0e-1)u5uy z581&J0PysQxjq3jKYHC$^F7ky1f=pBH2zP{`UKEPaEfJ+sAmkYkFZyoo7c67V&d%kM; z$>758^2)P!K1#Er9mHF~SmI{*7E<4nS>AbcGlR-^&+hgEpfbGm0LXm>B|4tn{g75h zA&225P<`!UnfIfV)5Fq^za^EG0es9=^Dzkz%R@y^Jt6xjnHd;9cr-Hq`~Uwxcz~cq z1+<=rU$aF8G~xxK!IQO`Eh?ZfLC@qi(Edq}%mbhuTb|uwkN^a&EpI-^2d*7GE~soQ7CpEJ?6^5aLkpF;g~BE!!cK8hGVWQ498qq z8IHNKF&uMcX8-xl1}pn~Mg~y8UjU7X^{!C?)9_=M_kdR%ctFF#qq_yl zcTw>GaX^byK~qWro(G>Wd+Y*Tb;ZsAI)LvHPWz_ML)hojy98_>^6AOF5G!G)Jo|Jn z0bA+Qy+s9Nn-3(maJOgPBDH7!a@K2qo0rH>$Xy`Y< z1In}T?R?+~Vnc_Nx*ID%IitI?0YqsY^nmQX`v0GSzXjA*237wCuTa?|X2*_c-{I)uZ`m;)RFhtx|Ch z>w*uZf*#ftKT5fMtPS{Ew3!$f(k6IV2mB}%@vyvK%I{%qP|D?FUGRawg&$Or{y*vg zy3xtzqCySO`Qi%b4W`@R(gm_cb0Vmv0}#}njE99^`G-hbpA4wWtH!)_UrrdDr9M zUseyxtNhK)plkpdt@i1>3}2prt+6HHaqu}SsIeu0C|5x1Y4pL3t(%_RJ3+zZ)A=5|#fxpp`K?;MUO#MC%B&)fTgLWZ>AFqw>H-^XkF3tpATTKV|m#eiwK9 z=qR*(lnAQIVJm)eFxp416Zi#vk=jSD8~6o%k=jSD7x)Ez5$z+_5B!3@3?9vI5lekG z`&i!e>Ac0?0@`m0KBdV;^P*>Oi3)V>CTNj_3``u-M#9oC^6}KX;;VTD(J&&nF$6lS z$)ocqJYAfIH-=t#bT)(13h3-T3Gj`5pvKT-P{f0pECS%hP&X*8g04L8_5mIH2x>Ng zZx!e02zb!p@eoqO3Uqipg0LhyJRU<>3LPF#AS{gzkEalpL5IgPkkJMm9?wCx20(;4 zIs#sFc)Wyg1UfukL0A$U9AAuNLq4{!@jgIX;#esCS`(LD#;YH-{G zx@HkHBrggQ0@vNGw;`gg{4P(SyXJi$w;gzP`$7)60qyVcY(6RhyEe_IcMr7Y`|r~E z%maEz2)F_Qb)h4`%c`b;ZS?7G0axZe(1wXm=YLTCD}YtXp51&N-BZA=2#``pv!Msv zYyc^RSKZuDr$JZqgR;%RSNa~H-YNq_Pjl!^sw$b!N9;!%nq{A z;kA*6bsxBW0LuU6DjrZzz!sxJ$_$wK5Q9OkQ#|c)@TGp^L#P!T9@g_frWQ$fSkD6) zSI&=aQtupa=zxw0=q^#IfQCzrN(Ss8ULuZ_fg1tV4QdMB2eV*N;L-XPsm)!&1yb=I ztiq#vj|#|vpe=K-%N9J2w}8dKQ%J{Kz^yY7`#7Wt3u1z_fts<%+I*}b!$_q<9*svp zLrh46QxLljzAyk?gznL6oAiT`!J}7{(~F5=pSLJzd>l0D1yR*&>jIJeV~>7(4WhjR znt$UDKftfaqT&HM;|T1iUJ(_;lMq9|hi;XqKqdt|I*&s|K?~?w|Chjh+I&O;GJgh| z+(Q|!gGMm;$~N}Sat_!5#>d?u$5^|AFK9gGUczw9-GIU4xI1{6p~rD|(3(F6kK^s2 z<}=t;$KAn~Iv#Hawduejy{w>3EFPWg9>?23jeoG<@pe%E0LlcVY$y}djz0)K&AJ`b zR_7044VVHx%{mf934#SZj<1 zgir5gP}D&OM?qzbGF!J_f=6cyczdr;Zyme0O!l(?WLor8_>INl5r0;Lm=y-t|#@i#QetbeRX9A^Q~^g1@zsDR?bvv(cH zYre`lDvsSQDha-wYruC<_;%)i)`-QZU_=M5qpmzv4c)nfg=aX z22H{He*$MPJ7y+^eU3;O%%j&<)QJgl=ovWWg8PTCyhi`rVAK!J4b~tEDK|hW5cqf@ zWWFT?Yod?9NdU z03}xm&@n~_9~pUYp89{lv+>^naE;)`!7l*1Q%BgPvpAvCImP3+Gq|qtIF5RU0e|x< zCI*JigN~gi92+0}|8LLW13I^R8xsQqzb20gzov_dfMc&4qemzBas-dw-JrT^2Z(U^ zcAUS&jbFn>MSx#}M+KJOkFkK(wlIU1x-f&5x-f&eprtO%prtO%prtO%?4T7>93Hly zk*(6RuZ8z9{DV$P!Oe5&+zgWKT;21Jfq`GJc?Ov3Uh$8C0d@PIXZId(6Vap7UBjc( z9h8Y2JUZPCU}rdKKvS{@{DM?awi5UsAb`->egJed580a!@*$N>K8k-4#gZXtvI5_sT<~HEG;s-v za?o~u@P>bX-(JW_mXET1w|jz5=bq!B@b~Gh$0(S<^@IlUsbd=OQ^)@MbmFNekTlh( zXrwtd?@@u&6w=U|!n1n|xH*knRe(|@tgZmDVU-1l4JuMWwS^q?LaTz&cD8jPm%7Al?A1|gYS(TA(yjxW*!HZrjYZzKtsEn2fd&bS#z}v zLurg}?>J6#z-$BuJ*bc1h-0j;qF zt@Pva=mr;ho}Fwyo&Q0J5?r4`s;6Gt9k0RZu)r9jFM?9PLdtvSer5^Z&f|`qXF4x~ zrmF=!IzihkK@Q_@wFgbJ_vXU;#va|Rpxgx7jO66ey%&_rJi7ZqT?dcOUNEoqWGT1D z@m5e#0dA{-nnF-L|4aB>I#X15d^`WRbeD6yw&^bAaOo~BaJ2l!-|P-PgcTwSD%v|; z3tT$C{|{vV9lF!q3Ti)ib=rLJX#LOM0$MQT+WFlPe7VYY(Ds;aR}NRp$H^T-v^W7R_JK%==rA$tTc`>;F%^`reLA6+SN7VzcnQ|a2U4&|6*SiY zmpY3iwOAF=#P{g6&C!OB8-hy`k6zpP5Y;oZnHcshP(@xH=+SH21d)6Xl3cC|t@M!l zm!S3-Qi@gc=`EH(%+kyTg(;ldc>}4LqyaJcfdQJ|L8%d`d_$zi0N>7Ij-BT{JFj$p zMkK}3G#}(-_#b@mM(0hJZr1`w%Nu3M9*`vB(QR`A)W^?u>2@#h1YO-&cig=IbX$o} zXS#w*XMF`Y#=iXz03~UNGod**7M6p`UVuYf58cHcy|&R1sjpg04Erq9puyzPYwHXV zw*iS;siB3f8btC0C~U3O7#Mak!j57<_kVBzXocB-&u-}P%YQ&i?|RGO0qxlh?xlk! z=v#h+QuqH8o}FN!&YP~??x2w1Z~G1!-|cP(Wf+fcnG@jE0bs@5&IO=*JbXdtBDaE? z|DN6b;CceIxKEjpfx)3GyTs%FNzYD*Ft|+r53;89L@E1m=K|22CU{-_{r>?14lQp> zg60|Ucx=K}DU9P9uD(5n3V{{_HUXbx||vV!|PIyUfZ1z!C*}$hJ6Z1F|-gOK1&1C z9R?`|9r)2}+XWG30GXkw2FiXQm%y@24n(#^orz(ejw*DOZ8$`51IPwdl(x|alUo8$wiOWZzbv;mT?-Tip_Ne z3? z*Y<@usMLUsYi^xC>Zq~bwR_Tr!<1TqdBcu4VqDBnOMfuNN< z9FCn|5G5*qD@X^Z9pKXW05q#9;0ij@03N=u)`3g6bAhYn1O7J9jT|1`&7jl*uAzLo zbx!z#CZ|9b(l|EP7BG}VJ3=bE<{u1>{8NvWxViFgb1m_0J;2|3AGF4|+Z9wqGV`~B zHU~N$cLirv&*QF;NLz=$#Rzm7UazgdV{rVO0OdU7_`$3_pFIMrY*1xl z*vF;@s?&W`Am{pf^xB?;NFGvQV%W!lk{dmGZP!2~`9YF4;3^N|lwR9ONHVsn3=BI# zWgA$My!7D&G0*EWBf~yd)bybak+KI#x#3J7;P!n8cs~TF4)_DwNeXF#LDr|2fDVL# zruLhz-7YGS!XC6R2-H=9Bm-z^585!?TwTCWVg@O#eLDaB4=`x1E?_RT##taghh_WM z($KgCH6v6&1p+u+Ub7r?E@6b1(J_wjoe90RE)T&m^aoV9qQqsdttLe3FleK~M_9wc zqt{jtBF+U8{|t^ASLpI>$aBVF$jGqI8#VlwL!|bDqdhNJT>hfU*sgddMVKw$>KEUG9{KKK>_-g@=<`aysxjdRrFuevXaAo%B^Tz`(G}9@H?>Jk)vY`#sQ(v}5cgh912>8U~%m zzu#|u&JMW_4-p<7o%fEh7&3VD#xa5xfqd}j^)Y1hX#T}slnk@VL-Q6w{V_&{V~!xq z#Bj`!ncg? zO|J5T+}HdJa^uM{*L((e)!GDpx^GZ*U?5Cl7@GK;>O9Xy;ew?+uJ?%?u123@ryrcszP{gP33) zp50*_9<7)7Th=fzFmyMwFmNz@JH%MZ>d|@ewV_9^*MHAWKMvP!muWmMoyQxW|K|tY z;&JTYJ06d2lh2@KvYjk;E}dX~E}aKFntw5tq;`^z01daO@806Y0Fx z_za{SbTu1~N4L#ykAu%xI$6v+Cxa{nS>xF4(kIY)465w-!S@JdBIXb~Kt_8s|NK|F z?85GX@ME$3dfP4DkD0$-AEi za%x01+D2K>D2vj%dd?9xHkRn$HBcXFCl#12{a6 zJ3yy&9l$fc9>*O7Kw){zA%oE)`Bd{yNB(BeX^0-Z6&jt_IRAl4w~}m7N(3bspI*oR zpxa*AOO!mC4`?($VmJH-T0iR1`TZD+1%pR#IirW=r_v7|y)_n$o}f!o{Xm;pCmdsE zIOfjCaLk>F;g~x!!!dUjhGXum49DEr7>>EKGk7!~2OVezDzD@`4!&ge=w&(YVR^h* z(4*JnEJ{%Yj_c1iz;UfD$;7ZPTLsjn1{KHPQUTgN1J^H*0nx@cpur}{kvEPF_6+Yf>Iq2 zi>diXQK=G$#oYWOzf=OmVrl-7T*?Pxu{QtE=WhuGO^^1LfM&-agLbV4N=5m%yQtWx zGJIfQuw`gqVBl}jXJ%l4TEgF=1lCfcVu9?Y6cr25>J1OD6Fnf;TSB+8f|D;I{u^pI zKtbZbSo+nYH}t=Un}5plw}CqM zhTq_)_=$i9{Vgwm2G;o9e|dJ^_UMh_|8Mxs)AEi_=k0Pn&)yoF|DeNjnqPs65X%c5 z{B9RKnh&8J1LX-YU0NPp*HkMEZ~EbsBV-`jux|NsA*_kB8VgLiAgueH=*;p5lv z;S&Izr(*&-Psap$o(}9j%Sw;V_a5KxgHE0OehIwe!Tq|&_e;=206lwaOh8BM@PV$l z1l^aa;WmL^!w<1PTf=PwzlI-Tf3}9(1%3@b#Qtmzw-5Xpd?@>~-$Bod^0hqZ(|N2! z8+69}_X{4DM?Lu6k9vH+fZU(&65(^~5HSIrlxq2*^rQ1J77+%=E*2HTZ!HH(K=)yE z90J7{ynN%|cB%Q7z6Za{$F4v|kN*c-E|tFV=nZ4^IDQZ`z&F9Mp@t6>p`MJTUp!jB zdGfnl0iAy4qxs0g@{+p@PSu(BK0RdI^T7;nE&^%yjINP z*u`Sv(VNHEa-j4DXs(y>oZ~STGX|(tkoGi+eUOBP;$Fvw8a9x792iT#cxs+CJn8xW zY>BLAuLzsrNl^ZG?2_Scxn08DA;SgU+V!&Ntq0>l$73vf3=UfvJvx8CW_LWsqQYSK z7BpsU49aN^ppk4%pU&q#&~;ADKmJ3PY&P41ZnI-3;r9G~_k$0kE~tD0^%$9bJO4p1 z=q!;ybVH&$g2)Eer9j6gO2_+R4U0e6ze_uC&l7{NCidNdvZ6)nhvxsYzJN3ZQ` z5o9+(GB8}SUmhe0x}df5rf=tm*OCaolz^ptI$!y8zVz*U0MXcM%XkG8`l8c74W~8( z+ zs6s?RyA1yyvpiVxihmnu8@uH}@EtDTIYWM@gW&UEkjmTUHxizmf1&HMJi6T!z{3@e z$6Qo07<`j`R5(Bz$NO?Y4gGEw71yp<2E+fZ{M#;jcI*7$-{#5y+pg`>akEqo*1u>u zS)%O7zs-l0fqz>JD+6eQ^39T0piS16=WC9FZd`c@+NB3#I5yPSfHrP}c0z)>$&lj# zK<5a8rY|@=dqWvr4gbFuL`mNuXMh$j2>5jV1GR5Fx@`>jx9L0bZ@X=Iw=~$N*Teu6 z44qe@^^0rE?GkAh{%!L7+hQ3&GXIY{THY>s@md2KAE2SV8Uyf7ZpdH+Xyv~jXkjpT z^=9WS(DgNz=Zo50yFmvxfhNacTiXR7VddI-vM#{4TSUdNE0)1G`Jmxj7yfOxJ-cmQ z@o!^ygzn((xLGO*%6}~IH27IXj#83$7YWV-<575<7 z4K+HTpaPE}bi1f1fChhBz?T|ymZ)&}_SP~QzJ1LOnxE>51>Y$t04mfW8@LU?spGQc z#Zo_L@c4B8g2&fw(0+G${%u^~z&T`jy5!AkHAH>o(Tx!}pt)vWkRu?@F6u!F8IWr{ zy4^UCl9H?8f7jNN{Cx)Cgai*I(3s)2--h2jyLCQ+Qj_Iza60X{S*nCwUbmbqk%xs> z2qZmS1f{2AK9b3nU6kq!hnZF!zSA9+en30j zT~ri2J8wcmsOzZ(b`Q!WT1eWx-B>hU^5x z1Fyvl54;vKJn)*&@W5*>&>j*FpH71fps9Y;!{R^_h=}uYAoK6vJUjpUcDsY}Q;9p| zzDv-F-w69bC(QH}DI%NAPR#mS!_D z@P{1a*AT4+vBD1V3%W;m90$)1L6jpc=yb1u=mgIwfpmeCgE_F?6MQkL45$$UTRaL~ zOM2WLbSoREOXb1dp|lK?mW9%CP+A^DgVq>&*n-?sy5%(&*kRyI zavVG|0(F%Fs5=MhlJv4>L0qK)+SGNt*#Ig5x;qzg9!oH2Q|ZAM%+O7T1`G_{ERBY@ zTMv|!8Q$iXXXre*l7WH2p;V*sA!rfJ!53Vr|NrwdcyzZM2l>OJm#5R?;6v7K7Y>8g z1Em*VJ2XB7jSwAt!K3>BKQn{J!G|n{w>_A7j+dxGmlA^3=qodNG#_C1*bUlj_y0d5 zgNGvMSWB=+JUVYgA4bF%bjTFmUqC9K8{dFtM8O+gUov}uY9a;(u=~4R4KKO2oaAo- zU4!P+Ytrq}+Yj;#A zoi|GT!N~{V9>>n3j*U-|gTkkK4>&0NdsEgjcpiMh>TRi`&fns}#K7R(?V@hbdZ2`> z^I#+B1U!e51CHHnmN!agf@&2=-f(Tb#NXNiS}oN12Xt?=fJ>*3ii}IAi%N(ixHAJP zaUDMR@E_DbSs&~OI((9$R0wnpZ;46-ByWLQ@DZNfZJ+@$(2W)1zPtnE z(?5GX{(C|OtX#XNv_ZzrE~tXM<+ZH>D>a}AqnvXXjdkvGV$ncP+$XX5p_{X@a%4d6%rX3g@ku+h&i~FhyblH z>5ft10Btn$@aP7)fdN!xc%l{=C%ijd%spJXT~tC`x_wk+K;b6f)A`)7GuptV^J3#k z1_p+P&Kn;b`8V?Mx9nzOU~p|Y3ECZ`0qQU*@V8$5`~N@a+KSt*hEG5n{F}kcFd>o5 z-&zXNVE6=7|KLt9-jI_PAFz5_>adr9)-JOffQ+(0GOFajOHJ^}jJJIm|Geh(>Ada3 z_`|dF2q@9CfYuy&bp8bgpbIFyV7h)lR zCUwyKuZLr2Pa9}}799ETIPmQ)VdrpdIZ%>rcpJR#1hUnW50auC_k&hDfZJbW?;o{; z>>u^z-)L95>vb4>^Do;9#u5)uQ40w#a?S5%1MP43>3rbP2wwe;)ED>dt%iE-Et1#x z`CC9|<3MgM0qv^SB5sfI=LxU5eL8Q0Q-Npa?f*wTL0e<@L2jNmFWve&816Op6^tdW zhHoh{yc={b%U<8kJ1-Uf|NoyhA=tC?f+y&BNgmMP9B2j+bPk>;y!7|%{OAc8H#PJ) z_=4G|^N@$;C+}X9Zr@&>W=C+tyi5($sc1g@$A=NLv7Xtp*QNW9NAs~ip2rV?nroh* z>(TDLmi0XNg4w&5rTMim(s+_rugNs8UX}?ymgh?HyE#D9mRa3=kbC4iIbLgao^E^$ zO5g`yay34L)RaBvA*oenw#UK8tR9RalHER%2CXMcHiHy{YuA;nCo7JEOOFPRUR&A2 z;2{gvYm5y0c1s~UT1TFK8~!%*rPuz|4+%z?}|fe&~98`oe93MGb82@lAQhJ7F| zSO&7AjS)gIfYzFL^n#5*oc{)DpLz5)a|m!S90QXK$C^0>I2ag?HFH5IZV1H#p?Dz_ zAB5tEPy!H25JCw-C}9XC0-;19lo*5(hfop_N)kdzK`3bmB?F;kA(R}1l7~!dX9)!{dQ68P(fbr;T2Kf`xinWFH zmq~2DvM`jMeQgKYP$v&5U-$)C4)Y7T92Ni(3LwG&L^yzm01%M?A_~B#64`===WEV_ zn$s){486?`3@i*Q_)AJWjvr|F^#4D&JUrIIe1Mk)+^#(cr4K>r!%+GNls*cjk3s3< zQ2GRvJ_)5yLFv;V+N1dZPwA}Jf*!rQLDuhU;Dt_Gc^p5m@XzhyO0ng@t-}&1?V?!Q09S^+TW3?eC%ctA<2k2O|Rs~S| zvH2K>NAuwypw(+N@NDcraV~~ra!1gG>kObl!OmN-#riM7F1rNos{aE|UV>ZexNM}l zn>>2KTb3YB^FX)@R{pde08h?=rVt(DL1pKWz2E}!?FB}LeWlXSgaljq2N|#Q?7ZmN z`2lnsogj3c$?%fr_YXdnCyMxe`PZND={)Drc?#^$0K{PR?hBydC7;eiKAn(#s^C}! zwf}-W8sC5x-g|cbYB^A12-=Zjz_00};=r#Nq7uNb8KaWGubHA!z^@6pJBMF$iwbD5 zDZl0($d2hw9~BMIaTf}p9*P90J1qd}JaBk)gVG@b=xo)_IpA%*pkr%2Iw5;`J$fN$ zrGWULasT5jDxhO2L9O=VE#QM{K>b$G2`-@BzToDKPvoY=k2{@_fuZvt z=gn^i`T1LVK%G?3v0ROy+PpUyG^Ki&-J|nhiH2#FaLqu(){>`M=y_rhvfRzvt0;2((}JxDzO389a`I zR&+3U^acrd{y$dw!lU_j0e=%H!=Sp)15N#LCvb<#qZ6n|66|NsBNS@OX3*htszHknb9DAMrgKx+MPc!to$bqkoRy^$4&F2Xowm#*d zdC0@^R&6fy5FF6bToFW(>e+eRrxV=N@a%Q}@6-CDG}5cr#rnVJ_xqlT$31#Yl|gR0 z1YaN02^tDN=)?Havy;yQawrREI*=c9`*Y{N|CeC)Y992kyjdgX!FbrSGY(N8OyPvC z$OQY$qt|xPPH+iv>?|Y0z75jI?Ih@Y2YCD;IKUBFLjQ$j!`9oV`za55bRq{xX`M%} zi!3xSpbaSgsRuk7K`YK1__rPCWocz#U`Pf}(j~j_J0CFozYDb1awn4jr~!Bqw(8IW zGz;ehpM{h0=)C#Cga0689E0(u$HA8(9@e~|K3uUSr~w9!Q}E`B6&%QZ1$(%g!L-t0_x~QPKT5@5Rifn&4}PcP(5eu;qdIN} zI1KlnVPx319W4wQJRq?PUr&Mv3&?(bNZHMZQ{JHioI2q09=*1eXF$mmTqLJW2mo~e zI)6bYM@zk2TMm@E9%luelMd>`K@)c;j|ylFJXoV|=LMh6i!gsL+zxj9eURe?WRMep zN3U(+8RS3#w}0U2|M+20GZ-{qEeA3onz8f?G>LCubZlcsUeyF`H-oM0wgnXzKA?M5 zZh-|53xUAq2SaD4VeP+$8h()Ro}l#&knRd7J0jwzp+*cOAH-Pt)$o9a=EWj6SJ1iH zmr7g>5BT-+u)BhfFGZ+#EEFF z{zF|}j2{0FwVW({A_X7=nn;CPII z0bJ}p-vkbZuoH|7`-5Ji%8{dUpQt?1tZV0J(^&>8Zx6>wo z?)R|p=;jCA%w+)@?coHu71GuM?J9FoF@PRk1zI&>02*{ZgFL_P*?HHqH&t}k#gP^o$cnNesGWf1(fIFU z`HvrbzK3To`fY;xUij8iNAQ zUeFD)u=)mZN~=4?_YHblBJLY>0o^YMxmoL?1L(p*Rj>%?@MzGDgNX7R=^V0Sr5`<- zf3g>agTe@W-Jk%wXK#o&J5u@s-48+s1GaPePU^wQi$Z*VA ziQ$;DGQ%-v6^3KZstm`R)fkRBt1}#P)?hg1tjTc9S&QMAvo^zPHqZc$Aj2_d9fsF3 z;0z0Q5BLZbXIL8a=ynDr!4fHt?rKn~_2~2lC)%4H$DP4x_Vsyi^^M5y(Dtlr=Q*Fw z!;YX`3V*>xq)TV5L>F_1t4xk8Vzn){`Xy9+rh1<)1b%dRP_;l)ZY* zWOxA5o`p9EWIQ^5fLiL1AtS~g9tU5Dcv!Q7Tk4RNYO4>Swk|G29^dbO@L+_r zei8OV!Yd@$19UCPW<~~v20I4+mUWDvPQw9L!~Y(w|4W4Ux3T;5f|l;aIr2|A?!)hT z+_UrZ21f8QlU8sE%0Z-5iyi-9%Eu~+{ozJ zdBNlOF;Ghz8Xt}gHO8QNuMD(46xxVDE`J+p#6i-a_Jph9B@fMOMUJlEC8NHbw@S=h z4KMlksu&xdgtuS$x9RYM*6Z+Cz9(-Xe{ixj_rkCcEDza|T} z6ThYpH}v|dW2KKhn*S#hWrFrzH9vpgp?Tk{w}iXEqc=thv^W|%9uB*|O4Druzoy>; zegWwHRhn)a_%;0w@C!iiuhMk8z_01|fM38Fe1Dau+XsG4KFD3Vpp(dtHE(6xFB*fYTAUzy+;X z>~vA#0d-XE{@{22u>-sf;Rjev^8;p&?>7wp zBbT528Z6@c8b0FS{RsA;{Rs8~9?i!UJpLa5<*$DUMU|kz3()ZA2@lYwfMXu~?#Do^ z<_8ZvG=F&Zme?0~^wx-jvK)9ng8Kx14gUrFf^HM|1^pKAYq)RV*YH2UFX*;`U(oLW zzlQq-ehvQz{DN*5_yzqQ@N2k#;Md^i7j*l;F9^+VpgXJ&G?Z@f1?9H`CEB3D*Y6iS zEzf!KyPxy;ei7OIT`~fW9WtPWz#f(d!TS-!8GJe~K+*?jJumn^PRRZwa7hVj`Nu=L z_5Uw;bhCn*bRaQrBr(uXEJ(~8Nena`3ldXC5(724Kw|t5F-VId?*9WQ<1oKGcz(#E zn-$bx1gZ4$=)4cM7Suli30T4eK*PWw0S%Y{XdD!$^rgukkJ*S_A+R2=s$nU60qKH{4KLV=f^=NZNUvA(Ba6C`CgySgC!-P zp?y%B1hf^2p~Q9j#`4LE|OOZ!|nQfBW>7sBr89U*XXS*#P0u zYYI|tcmTY~0W$msTC>FQnjhXCIK}{4W6!^hqxmOSsSv1p_x80cQuwu;EaBtd2JZfY zRD5`S4pjbefQv5BT4VuGlLl0D!3K~(MVBmcs}8Y?qWOphct`_YDiyo~l}hmK5nvB_ z^xFPi1orDB&{iE|?VFqijfyys%bK4U%v31$A^NVNaf1lp$|DLUP z`CGv?F=RD0$m>|C8eZBN1RI<`{@M_(=Kx#} zwo!fLAb?b69-YiSoz)yZoy7u>VhK6^VC{Ry&NH5%qc%Q!cK%09mw0p@1dSN{@c8}_ zw2rg&KxwQ;Z#E;E0*}rY2nB&Yn!n-6j}KH`e!uX+gAtS^89e?Uc5QhA9tFJz+eOrJ zpu`3gnBbN590@<&RvnEN3ZRLEy!Iva0s|` zb3i8}JbG>Qels!{zBN4H*?9vpBn(#K&;dQK1s3*C-ys_VZvR5=mqzplH!y;8JiI*x zNk7o@X3lwbUV(-z=meClpjD2L!W}#p^%um)Iu`{`>EN^hIo`y_@<&OTujO<8)*1!| z25>xrUG3R<#JBUQ=l8o{_jz=__R)M?7UOIAy*S*L@wpGG z{7wfDnG4BEPs`&Top(!DL+Vd>*BlX!>$ZSW8rT^K0;PS4Y&p(|M_3L?nMmb5sJsA| zmmZC8K=brI-QZ1mzTLSDKAme+K!d|zn>$@p0*-l&ptG(nDj}e{@wkgh z42bsVbx}!J!BHxRHWv9h;Fya_0_Z~7L=ce#B9cKw3W!Jr5osVI9Ykb+h)fWX1tPLR zL=K3^1rd25BA>yd*EIMgBg1}B^BsEDxo77w(1K$Lkn74&F40*V4q z=>#e2!6A=G4TjGd8Fqn8-3cNL5BMS)_Pb_-OELfFjOg<$pwxomA4tjAdZ2{q|AWIA z^(*2G>n^qqcaCH20-#pR@pc0c1!`0sZ`VLD6%b4b7_)ajhzXvXf~7WO`{8F~)5?6) zI~y4p_D^7%z+`v{?f`iC5$w_V8PtT)*auPp8!!Mxj|67)6#UKq8+{lN0UMq&GVB8B z+X*7T#Tz7wdTlLdfg|7?Xj>*)8wL~uaQhv@K$QXLK2cC2(E>Sz=++cyo*&6IN>4!v z4x=@-ekRx@E|@L>^^ZaR-w#?s4;s3MIKETjcmoHh;mg3l02xh1j<3!SphNhNgF_P1 zzP}7e+dsX47HM|0g^TKH&1uyykK69aHA9=6wtF9T^X} zbRGaX!G!^`-wS*m(>HJ%dp9WkgO2h5(I}JN-OZqk0P3+wcyxDz(!5J|O5-2!05(|a zb&OB)Vo<&THz5TW_`ye#r#XH<@}IfX)T7t5XFVgsevnU~1z2}CNOk9_gTLetz7k_R zb?_ILNAf9;PM6aHF5O_096|RLcQ%8RIX3=bWDsB|HiN|mbCHB6JT@}dgJQ#_^AR{U zKy&aeozQL?_yniJE}aiOdTpDhgVT!gdPatQJLEv;Eif<$K-NisW)UH>r`9nt?Ar*J zh240C)V_gKAkA+gz)d>Pjq;$oj2vJtV=7Ye=ynCA6aH-{UAn=E4b;V12XZ5vqXO~>hmYltQaP9r%=}FPEDQ{u-R7Wm!Rr_qUcLbxft%b9O1K{2vn@cY zl)=l%9J|??fBY{M1sBnfy4|sp&9NJ-wl|Q`v2!|DSMp8APM7-}jtw;`91JCV9^I}C z9-Z(13xGs<9J|{=ia;kxDj_+d8+4ij#4jGbwo5?{Nd}$v(9PEg-3f5;B^T(R#U5j3 z(A<29iUsHnP7Tj)mooz3jes7Rr@+Y`ykx_Lg9RjLV0hc`0EnS5!Lb|Uq;8-4Je@u& zKE9oQ9XpSM&fH~YU^w`K%eOn_h=6bAcaRC*y*efv7@gZ#OhC!f19m+a=+;f|WET?- zkLDj7r2;tD>*K%+Z85tQEynAJ~d33v|7<4mOy37?Qpef(xck| zToQP8`yAoe1u9HH(-J8jmM=m1ecM4$8J84UYUkYpSe6Ba}2r}I$h=pU<5>t ziiRiTyglTQ*vJT48>s*~OtT5JqR8G`gqt;o;$cE+vj7Jf!gigJU-z*zYe^ zL;VhJ|AH>p1C0X&c>F)?nGDV&ATulv^Y=LZ{r?~2S%nphpuL-Bsu>Fk!45eFMf^L@Z=L4Mo;x?a)&x?a)& z+H!Y*td~6A0BYhxls14z$ia=g2GHJZs3@pS3T1*$w}Uc4hkHYrpiT~y30e&UWr9x7 zfHFbDE>I?DoePu+T8j&1g5w8bF{tYc75xFCA)=tAIUt?~D+74Q_ym8`A<+5j-7YEu z-3%yYBskf5bmtrt@XdS=D%kvbQ*;?NFgmrl=z`7~nB`}C?b zICZaC3|3}&)~$QZ;t5Ow3{KrGi{~&2Fo1erUfnH=r!WaHfK2fy6?go9;$=T00|Ur) zNac0I9&K=XzlElhp|*`5Zf7bQAh9DKnA4V{{U059V;c*9%YhOjkU9s@ z#djK@oBJGmI$cx@KzT#~96=zx3Lps$P>;yL2UPC6SmyAv@VA0?gC1)ETg}*9!_UD0 zxo-|^o?mYd*k4|~EnrW1CSP#;f54+xWK!pv$vsQ~j4qvPCQo1rVC*hY3FzE1c@9$m zBWPQqhezj@$y1mD7#)u@fEtAOI(S_3-P+v~#5(QLs`m+6^&&I7cGw>w0I!=qQE z%OlfAMFJA9CHy=togcv`?84jQ-E{(;RRSK}b{^e%93Gun93Gukp8t<~BwK*u(xds9 zh^OWMnwyS{=U)r%1i9k12!!Hw?fedAfy3e$6Lh@Cwe`Pi=Rf{_6;SF#DX>jxOKsJkTNm4j;>xrFt;!%tb<;-KC%&@glHduu6xPxBM-j_4NOp zSzdxp5%p+22^lPPXn9*=fvI;rLT|S>3s^PiRF>n;ETBcHVE1)8bGWuVDGBmS?ghIJ z+(ugrI?<0A)H)LZ-xLHHf9hm*>;@|WH_oPlm4h2+cR3szK&P(rdUmt?&$#+`d^naGVBwTM;;FaoqrCIdoffX;jN?ED4`CZ-}Ka0ql8pfq=PEk%u-IsuPvXK*Xm z6Q+~7ND$J(JqlI}w(Y++OKAo|fhg2yk6zmo2t}|SRyQbYOYA+N?c&yxb-JG2Wda_Z zr(pGsCCjxEE|34GJX$Z+e}2vH+0Am^vyL;4q%Y$bdi|Id3gAN%3a`oI3eYXOgLmWv*pZ2vn!8XUXXKzq?aZU2KW zxIDXKjth8Xz651=pI#Mh$E}Q@qD>prK!%n2|6R0Mj=N}sCa4%7rF7eRP~XnAc~hS{|QnXAY28JP*EL0xdCZ2W^fhO$VK4`~Lv6 zlxjUu;^M)-_d>51qa%1_r03;_o|Xss+dvt^5!}G*xafKLfv4qxA~}y<+i#%L4thnS zLBl#rK@}gg=>^uQlDFHe~9-MhYJbL@UMS5?T3V8jFOXmT8*W>?B_#~g` zcKqSd>GZ_Am!-42r43XUcyv0w>300!(dqQ1+wo7Q)1Pj}PA1T50!Zzu;Ar`yboc9c z6f=?M7d%@36Kno)C(z6e0~QN*9c$}gVqjoAoHoIu+mFNWK*LTDpP_{7SR(Rl(o zUI02DxAW(Ia8nO7<8%l-P=Xl00HqIK&}~$w!9fI?8*2Xfzl3K4BWUPH%A=F}wJ2yL zhz~3cYRW*D&p^@{=&VSL^2QN7K5-3l@}W<+GH5|QiwbfghmC7>S9ADu{)1;a&_Qhw zb0LEOp!s6Z{yfk$Q8zRHHV%*GpN#yi>p`WoGspiEppI-4Xa*JRIG^MnKGxv%TBYpJ ztpMHC9L@j#m+<*mg2zcpiXaMmH}eQEFnIKO^E5!`PL(`*Mavd~hFHPFkKk1npuyDd zzR(*lUQ2rPipDJjo$)CEI^Wl)^Sf{753q6IOT|IcLXcU`PG=6#aGkbKC)iGSkyQmb z%6QIwMuvUb44@JlR2P9w@aUE00!^89LT;M`$Ce=|QG0ZPwmE^-z(#5jlAv_}orl1Z zU;^BKfJ84MeqsCJsIqRI!Yy#%IriQj@OC(`i*as!L%1K5K0Q0H!4Ai?gPn~DI~r4$ zf15k_WK0$QZSLTMF{Sypxr5Ke6yo3J&I-O&8+2q=9CJ|t-N2>71{%<3XMnB;^GN=E%*BS45$t}Da^{*h z4K*sP3?=M_kdgO>8WlE%5-#u_Kd`EX8Wnbi5(RL?fdyWRfL#U3R$O2KaJB+3qyZOw z$mIp3{)X?b0B=wQHD;mvKqfTQFoSAB(Ebk(+qwJ<4E)V!KzBHF+ktW&$~G9s?mCWM z(5gh{a#ql|5i8hk$K!4spy3PtZOqL-ic5n%dc7GPwiSEyih`2o1kn2QIR0&h{M)QN z{vQP0-te#FHUG8)Ahqfqz0QoAiamOHK}sR@VaufwOa5&F{M!sY{vYu8f6($%$s5n+ zV>}+cqDy8X=N^yFn_&B23xQk!GT=1_hy^OCK;wakO&t9DjQRHkGxG2AW^&=*=gjQF zzt5Y6f1fie|GsKA{(aHxoiQo`oi!>Poh+bTMmOhz+A(0W!33yyLZl}|djNFbfp6z| zpU%UeBW*fER0P16AJwREc*2&kLiZFxx!@v^zXh~#2)20x^;SRd1P^!zichDF%4>d5 zed7YVJ&Ey~r{z5#e&^4=-KpUFlgvN^4+1{j7QU_jOCZNlLguHz$594=sxH`cC-QhiYBz@F;^b(-OxLps|0@aWbAS##5)^FHiOV^E=644)(6_xOJIg9qdUPs0PRHy9pxy#_H+(hlB<23vmi z0Qnru9IzB**21&%1=w#My|zCaK-o;R542AWb^Zilsv%VCE04~Xo}D*dgVq~?$}eix zuPEtP1AL_kXf2%QaW~M~9)`_~;A=srfsWgSG;=}SaRty~5*hH6u}3GYqQ41|f$gdH zQ4uh_ZTJm5`+ExP>&~N{IVv*EfB*BhxPcGFc>r2w*6E_cVR#$fzV@+v%-<{y+71tD z$6J0b=JV|Q{_-3H1GK;C(W@g3N}UQGmM=Uz-}>;ozwotu>f8C;m*43xcy|S;8R~0U z$5G6Wv|Uv2je~1$Tm1>Uk4>^ z#>1dJOsx<8{r?Y@1ow(8Z}2yN1C2ae#zA}wTcZS$1zmdGYr_aic$$Yg|8ZUeoqx^W z0vgfsusqD)0y<^1^B!nVSMYxi%|nK7A-gy{7!P*d*E|k7+5au5yz%IK2RY9_kI}>O zJ!rpn4fH(!deD`ynlC*x4)e(0me)M<-;9dN)HSGt`5Iw_mG34*X}i z4hmn;0otf%{d;!C32bKU0Nuf*ff!T;jfu{!1?R2Y8H^13Kxc$|fDWhq0ZxM+y|(ob z*?f?!qXKBs;wS8UT7G#3r2NqM1~ee&(fJeBSg_>Z#@PHrztoU_nq`MgHxG`r8%xuOsSTSLFYWsQ+D(9a50B*`O;bKEpQ7!^rYwb_^$s!RgZ^vuZsqlW#HNC3cg!P0lX|4wA&1nLOXp_96(E? z!RJ(hR#CgC2zd576o52yc=kH5gBTW&iAfFE_>m+3Hu2_PRvj07JO7n9g3p7Mapd3T z#_0L~So067()X`*P|{n=CCI^kB|@&CMiGNEc!P;=FKB;@FXKO-&W}EtKRtR~cp0F< z-<}29)ZCq-65!kU*;n&7f6GtMZk-Mh6>#UYex&*;c6 z;A1c7$S>$(!w6baZX*a;Q+~AczGw4~1pX$_VF=*9-{50;zO=!|@|r|G8-X z^VIz1tN9CD^QpnaAX^yW@!ut4@7N(?1FrOsm45I9U1bvmZsq>+(fsAvTVlfwTD#8< z?ay_&|Lk!4+2#JL!|hj>`|l37-(Bv1I^6zrx&Q5O``hLIufy$Mm;3(?xBp%29c&)p zGk-u=MjZN4dIVhFH~s`=R{rJ+b_URR9gjY!?1Bk4vNJGvHvd%s?NDLhZ+Z_Z1Db18 z92g)1E%z8eQ`9apj2_l5DhB1E-n}e3K8!bfEDt~wG=pk=kLDT`35bpoUGLr!89`7Z zU%>DZ$bLtD0TuyJL@8O|&Z3TOYo_DW{45Lfud(G?3&)Ge`-v{MJ zr25CPOGcnWM!@6$A&>vZq5E^feL7!wXkPH@H8Jwh{O1W;Apml{1<3#8?ms>7qx6Um z<4X@%OzmWaL>~jJ@!$s9m8Jq}KG-<&Z*x%rHy{kbOmGuI4a@{LBBa4ga5F*x%mg(g zN?gJD$*1!$XhIp(o&eVgtp`e2L45;t(5)PhW(2qq0WKa5nK9dHc0gg! z5s0AmL`eI8d>DUwblwD)cOkqC9*w`iDZ3psU+3BR614asz@zi7kLF+gmaE`0j|E!h z9S1j=ivN3be)7@$<xVb;454nf7L56mt`XQ2FLzdAzj2!}1V+%XDx#aDvgJ^LXbi&0j8>zdSVm`Dp$F zwT$GTB9O+>1jjBGd&dqINO^V$bbi4<_M#|{&buC(e|-g=Z9JaN-AN6bmpDoKbYaOmId~0yDuGMI6io zXB1F{3{RinYdIj(ZlJ^8&~izMP=hstPj59Ne=GCf|NmctHsGS}p90liy|s*v4K_N^ z{r})>2fmG_2C3-{I%pr%^nUNr{QLob3uw&Dvo}NsrRnWyd4<1i6DY1Qn%=tTO>a;+ zECMQrMKD|5kHIbP1hkenXgyN_qWFbw&!VWg{nw-OC*(pnQ1cq8xvc@>LsAsDI6(A| z9lK0x=gS5rU2K?7aWl2r2-c?*NM$o_x6)RKi0P!bUR;Px`ik`c9zScFD8(zXE^LI|c>@ z(7@$S5AabNpj%$OdrRz)j@q#J?*qDR{V1r-*Bg#@qm#K~Z~X&ss~2`{6TE)|%6Dd< zd}jvAcR0@5_=R@fh8bvcBqThjd)~%*&`dVCzw6TZPxG2*um67!P55~m|1_^b8mp-7 z9WhvY2kE?xpV0m}=)4Uvl>8UA&f^2}R=ihe8 zlYjArVo{GyBuyUw4>tcZDtdHy0%AM}K}#>Bwj+goDG;A;2;*^C2kHL((%-fe+&;&)yKx0)&3*jW>B(-hq!dxpY3#JmuM2q5>OnQU!~^ z>OgpUa_o}f!>Ip!I-hxf2b>t$JsD4W_xkX%!`w^Bc#}`(Ls0(n?M|2Q1uc~K?R1y$ z?ami)?g~+5Y`Nsqd62&aw2+X0+o|TCN+q1lKh^nLLG2IEULO@E&rW{{XZ~$9s*KM3 z+e%cK99q8dPdUUt^|0l?604TmC1xPsg3b&<*-!4-Sq@6fIi?JtMO0w*9-SX8|CX?O z{6E%myYzm`CH~e1Rt5$i&4V8QPx7}gF)}dt_m=1|8A8UBdt*V3DLn@M7SP%$56jaY zop*~~g0CCEQcrkv-hBzW#t`gcQ2z{(bJ##Rr$_+g4aY7}{{npZ+Yi{(FEPY37Ovmt>i$df?j}EvOn_cP0?cX?7U|97I}Qo1LA%i z2L2Xa(4+_v?q>$6!(rDRP<4lpL*zhk19Kj@%7cvU{s!f~OVBnSe+y{%&#N~?mBF*O zM3fPF#FR&G3G07P%WwQ`XThyZ^dqKhy?bkPgnDBi9DL3C|8VnTW{>Z;(avY(7jQ8L z6x1Kp9j);Q=sFfJbHcM)t?$j z09N}Um4A+1GMM!rDAd5?(@gB1j90vSLsU6o?j^UsfAB}?5s%K7p#10g-(BM6cDxZe z6)7S=p++R=etWOp5>o~r#&@XE_=Ugi7}jVs^X{$D6U2x{@c01f@%IfBe}%B{7zFVr zg3*3KiN9;!y&YeCQMn$H3r-TWS%$Nmep94N7Xtyu!^ zii}0t0vBJ0(O&ZCHSMf}H5htLrz5dr5p3JeByfl0`ff&seRCB+tA#`uphqo&S`hI1 z3*6ob4)B47iLXz$yh|6KPp=y^JbZd>>b<*Ve)Df*cCCC-l-X z!vmgs;Jy|{T6XN&9WUV7?Jm(J!rXDO;ox`vZ6866V_lE`2h!l~Hdr2EJ7ebApkvJLg3dev z-H_zCjS<{c1XYgw0f4&w?n*cs|4sw)*N4Kwl zN4Kj)mkc9vYCsPkP=DcS@o|q%6qWGsxs5Y?_yt`BK!X&4p#4M|pg{_Ev_T3__#lNY z(jdia1;=fSt}XvdCAvdYKr51NR55~fYJk=gLR{|B@d0vw8kQ~fZ&rem4#ogPWgIvw z@qzXYp{_px6$gm);MsY?BiWzBqwyzbe@n59PdC3uFN>#Vr^!LzPM3omo}D2F1wdKZ zo#Qa*92Z51xrtSb4Eu}}LFEicA2_PO^%Lm)MfmxOkPGPG=Pp9J{re6GK?^32PG*e# zxyRTUVOIhka~A;J+ZG41vD01Rn7abQF?U6VW9~|f$J~_}j=QUXGa|IK?R3{T=5D}n z%-xXjxVs4`yB>45U_9n-$#Bfwit(7cHN!D?8^+`Apk?n2$J|{Q`88PMe={)f3%Yw8 zcL#4WI_@3=GVz#u0^>3FM8;$8Ng%gmfR3c`=wv3AgkP{w2Jpza^Tv3Ah#Iw%(A zK+FbpH;%W1hSNa%mJX*O^`AY!$M}5p?ED8^OzYci58C{y;M1ET`romO4V0BtK~tEP zZ}{6}7#SFRdUZkJ4N8zm<U#g`p{QE#-!zC`wKa%)cFMrPad?+2*p0o za7FSDkIeh&X=!PoTy*f2y~n}dN{p9#MWlO0CVjuv8zNxPA;QyqoD+0jT=RdS&Ku?b^k_XK6yykx){_;&uhl@tBl4HW|AQbU0$naV3LUOsWz9eT)x7|@ z@io^mR|Zv&|3^JL&w<0Igwx0JDSy+CfB*l3G)aLrC;C{|s3?FB;zU~oGd&8N!@0^C z8TPd(B5x7_`xRPWgX$wto`j9Xf$A@?JakE-XY(-upH2gh&IpcU4gw55y|(Y77#Vyz zD3QKWsh!Qk6sf`k6zo|WsD4I9{hR7J$h}IL)quk_;XHt=C9}Z;PKq#lMfg^HlRG#^ztVB_BFZHUCs72lYKK6g}qOcCh(}ZixV7Z$tAB z?NUCE|Hof*di+1`2;M=$zt6na?SdzGAIbm!|LYAeHUHo&5Ayhb-0+g;u30m|KoWZ9 z9JqY+vApEbDL%E$5)%)g%e&X+v+_nn0L_XNbhTo*j~-7oR)15ZJAo@hRB!ErMq$j?VTTECTW zxwhQ);CKD)(P;+_0(e+^v|jSy_qYH#nI04v2S9-leHe7aK(B3OI5bOHiN9qM zs5I(z`fqsP+acx>8^_Lzj?E95T@5c89zacRzMYr-dPU?x#>!iM^yGIrdYJ>k*o&dk5hpBZGJ>p_p^<18M{hyIivKAbiI?7k99&}H`xpseS@zm0|8g?}3l zpR45w_=%}6UyD2P?>p$ozwZRfCFwo~L5T@@JS5n|@;g81SOo@;)=T_-@0dUZ4QR%e zzX?=P7@qX(ynuXOsEZhQtnfz>pGU8Y_}dU|2;KNd^-$Uk9Jw}H1_jC`M}489`yKsxb%}}^AC3ZCeT_x z(60Pm7tnd3K71(S^N~M0BEaj>BEaj>BEaj>BEaj>BEaj>BEaj>B0%fWB*43`n?dW* zK<-#7lKH~p9dR^H5gYMdCy9pYoz%bf{>61(6frBqt z{vU7!$EpV?(m#0g`iOn-?7Zyx{jz8C?|-{N+e{t#{crciNPRl^ngup8rb8u0c>m$>19 zmP;kUE?s;c|Bo3SaOK~2(1m~7C0EM}9-SXuI!={XfC>P(ddPhOf*$`5x>#N+{rFl6 zB#Shj)fK`HI)=IBQt3|ceH@VdtBNE4^0|U`MS)ffSzau9a@di7+d)VEZK!$J36zK7 z_8XoATL|ZScAoU?^<;Evu;ByEcOL*9H6w}So(9Bx&V`~+h~AxN=TT41tDrL-FTB)e zV_*QC$ESJBrL8l4)f?h~Ph0_LpK`*4D!s!CPpckU3aQeV6$mP)t zTE_Ic!L#`=_-NsazMYr(TSQnH7&=e8Xx{eiJmsr-3sh9dg89(0VuDkbh@5kWh=k|= z!=Qu?UT?5&y3%>VHT4|1PNxd5>oBS~Cuh=7T>EHfTA2U_3GPO^uVR_%QheuxRr`W{>YTLB%_4 z{uEligW^jb9AEN~_&NxRuYU~&aF#w$*^Zy`Zy&!*+1TzDJujUs|%_CmD zJOlG`_&Qot1IqzN96CWxIZ0{f4buSc0~T|iu>0Q`L8SP ze@Ep1F1Zd#4{+IjjKj0}2q^vzf@T&#nQ1Q*0|O`$+qQs2j)RVh`0sK2FsMlM(LC+Z z{QIv5zuzsN-WW+H&*t9>{7nL&Ri&M`Ai0ehRMz)K{PR4145Y*J_;C>Bt9jnD`Tt+f z<43?ee*fn_nvXpge|zM{72)t;`~|n?u?OR456jE^ZJR-p?#=)I`ttjK z_v(!?d<5w?v4Re6=il|1wMfp1U%-X$p%cG=58p>;enB4&5b474&=K4d0F^mu9=Lr` z1M<9&YEl0trdLH7@c1&5$RiQO-FG#@(P z(R}=XXY+Az5r3J#r5@DR)V%2N|6tmLt`NR|jvXN!|2+Pm1TDa=e+R8aLqUNA3Tq!w zQP%wTFVx?j{Qh@+dP9U6Jv9$OG72|1Y@xXXbVi{EC~TYm{)GlCB1E4;Le!%->z{|_ zQ4hwi9+t1mr9FCM#Q%95KMD$VAI+y=;k*28pz{hmoBx7B^{;1dj5wo*=3$TK!w)<= z?|UA6&+2OU!~+qyX7@pXYxW)#xCS87#o)f<9#A(6Gy;_ZG6%)|B~px@n#Vxd%2)H5 zPjA(GpU&SNnuo#e`|PXv+>`M?^yG9$enEcFNZ$w8$?A@vWt;?2z~I!y!`E`MgvYsqhr{##K~KwzMQ=PA4>}!V;b#D~(p@19aCm*^(|Hgy z*blDmK7%^Ljv>JwohLjjFY-4p1VuThdFuhnzO4uN`%=J_)+Nv89}1B6t*hZB-_C=e zHQ10!%L80#UGlK}UBnA+b%1It&=8DIZ{S0h&P(9R2~uMj^ah~TRp9a*USIJGvLLr_ z50yUkYzEE0`F0)x^6Mf0+c=0#AI zr3K+Z>nuL6(5?p^pg6pqHaQzhtuD>F|^;aaQ{(_c&hd4Z&LF;W_f+uxBhp(RjS6NQ~!JQFD zSZr+siw6BSJPFB|pm7bulfK|4F0_#WYS8`zZIAg4>X3l)9Vo&;>)?HQqwc$O-UL@t zkg7|+*Xur*i>R|4K>K5`_D2qa;_G)pQ8u)`1h+1H@WmHpl@_Rx;cI!yr}HF#%T7?G z6~zwfka+#`)I14_GS%io?3$-w%M}pgPvGSW{Gb-&|3jeu2q?BHK}XGLp7Q7o!QLMs zeSeH+Gq^vZzzn)vLLL@BVxSfWN-^(&sH}W@VmPeXz!|T=S@h*#2HllLNvkZ zE6sDB&Hs?f<9nd`=KC$5-Wu_L9=#%bo|f0krC{|5DBpm31D`xBZ}GQ*8Z{uzzWn~z z{Ch(LK7sQn%YRU_2h^;L@awH%|KQad!}bBiwtu@orL!Zy|20RDu7j^wU~NuU@Ps-% zKky4MJMs&%gND&On~#6+Xg>S_)bxDe+5F3(C=cc+NL7vGd(U1U2_}!`haY@2KYI2C zfGfFP8F3HBPoUg}R6g5AC?7I@^su}MGN=tSUJZ?-d%nFf!XLrelI8zFSHu6HCZ(%SZ;JSP zP)>gD+5GPx_>dw;e*bg5K3pFUzGV4-5RzYAL7P|@Ao0PX;@Ny$z_a-XG(rxRKKE?? zZBP^nvIpuCkPkh2eYhAQ(eTrw`OtgNYII06kQVNzN;E(fjpj*E8v_)B@bm#{Z*+w4 z!`cZoQC1}m2XY<1!e!VPwK9Wb20dTS4SK$u8}xiRH}FJ|$8k6C)Q`t;w*avH$K9ak%ef^$`Ox#_+#u)6HNR^B zc@BIZFQ~l%?jZ+*Z#4xEB7&wxd@T?1w;yImjlbxDL>hn6p)~%4lWF{kC)4=z zFT!LVf@DrP?gyQL`g@>+?mC*yCQ&f6aUQQE7WXFd4$dH?s|eCc8N zxtP<(@~}s5G-J_o56f%(&03(~Z$829(fr|u2jd0L&O@FDUonF&ZEgO=!ruhindiA1 z6gmI@|F`#5ybM|A1)54Z=-He7r}O2(mrSspwDZ9i%>NHGKj3LT@aNzQCJ>X^VMY(|_jA7rFPDKR@Q40FvKWK-a%KdCdY+?9u#}rzq2>^M(g#yv*lb0ZRGwnLj^p z!e{>c$OWJI^Ak6G=FiVO01NNW{P~3!KJ({SK1kz#{Uwe6^`|uc*MHOaU;qBhpYQnL zGk-p38vpBKY5cFxLweT-K9sJ<7M8b4M7(-U?t#YVJh=J5WrpRoqA#GW%1vFMLdWtD ze>3QcaZk;QK8)u*n*X!#H-R?HdvyNrXnyd=qw}9f^RqwvEq;s);EAV;9=-m5K*w+# ze9L5b+XI}q{nPmKnE1DQp{MK{Y5YZxLCFl9HVz}DjhiqTaN0Nx3cuZ;#0|<0(69sT zzy{@O&@>^q<`QO0^q{wz~Iw)64cUW0Jkr| z{>ACg@v&S9>^}Z|Cwo~MdR-hZK<-QHIMs0I0{^y4&A+&c9z&+I zz*nm2m74Hx^JZ-Rsa2}&nJn(n{7a*p-=p)QC$qmmZxDxLr}%3g&u)JXkKRBI&(3fT zko_**jQrcUn}1e;*41viau+FUNs@%F)+MhHqW?w|#VM{#V66<)CBpFD^&^Nrzqdx4n04{;TW2 zzwNF|mr7I#t843l3efJsFOFM^oBtK_w|-z@U~u4g>Bw=~qgN)%k$>Nn-l7%F{}jp# zJbFbvL801t-6L6Ky9eX1|BpPA`9UkW6q|o)_;#M-ZwDPy;n8`@lQ~?V*OSAsli#CT z=%qVo(;mnjt=^0b49!0^Ji2pKAnHM9!g_Xx3wSV|YCZ^6-{qsC{&Fr814HvKRsPlh z76t~_mfQTT?x2;qprbW?JJ0!8egK=n-^}vw|NmnQsxM{#{r?YErT`kNOy>7Mu?Ae8 zcAoHLc85CaC1}kD#PN{x4^WiHfJVoVeen|11_2v?5Y*>^7!UUFXVB;-ipg&o7#Lbk z^0!V0oqyf@SC@Y(DD*kYL6-`*ZeV6$=sfuSCMXX0T~9z$2-qZ9P?_I(0qjO_LU{=} z-UKPFbPIxg4GtjCrZN;qM}qYu1^vrlXt;wl@wb9j3B%$E)Zjx4cdo7w74?^ypb^4u zcMgwU4-U^xfAIAVpe)4SJnPT@|6L3nj4wC+`TyS&MM;i|hDWymXp@wIkL8DAfny8? zU=CVJno_bZmB_U0Nx2YKgMwf4``VhXo8CYbV7jvYzbR$4l9$# z|HChp;C2Q;vQ4*vN9#9_Ue-U8L5ts9K6HtJ=2Q4vm_avUwjSW`038JbzRVahUhHCd zfWH@X{5EJ0vw@H0_hR-Aaj<*3LfD`)C%0dM#-dSjXSX0IuwM&#c87C#^m>7V1SHZe z1kUXS4*XM&f%9&J1OJrc%|A;wa+NS`6ma0*_8)XI6x5HP^DgZ(!2ed}Tqw}06b2%)zo(3f|(9$)qms}VaKtAB_5C{7PwCB9DM#TW(lZTy$ zzTdLESXE&LG9S471c#wV=P8fxw>&~V!cns!G?8jLR>X0!i-9Ip*Z zdi?FvKx4}Pk3mx$12~2|LD%b8fci?Xg|fZ256hryVZl|9N3ZP!@co{mrl4golaxWT z)3C!G!FhGc0sd_#JbG<2Aqt=6WRcx1elfJ3(w%eTaTv80P$a;~UUMAJ9}PXlEAqa#4?NX^+l1DlgXi@TLKCaRH zh#hpCh695~=Lb*+*`v3B(Zli+=sY49c4+q$v{=kT^CPJFifBI^V_-Puz{qgSfr;Um z12e-h2Ns574y+8v9M~9+Ie_}72OyJSkp8Jh^TQt=y(S#sWeK3V!Q=nQ&hrP~v;05q z@a;HziDvU7)b8m757bM@J$fA={ZkK|{Zo`n%jtgpIcNccXm*6ZHHn3R0elm>0jL`9bx~1he!v0R zlq=xT>khdA!gC*k5_Cxw%LLE=pgW&k8Jd46lzisjcB1(wSBZA>PtJ}*zMbz&9!_Yv zRHEU?zb%~6^Z)VYUtFc{U)z8pR1cP(H*xv4zV+>VU#j|=spC+~CCI(JB_iO_9Tx`B zc`LS{^K|M#_m48Z_qF`X-%`d5YMm(icK+dS$$}h-05{K(f18gA_=4MVK~Mh0=Zd*K z|DW--d|LX=~X#lYVL+WG}5d72+RfQYn!5+-P48ffJZXcbBc z$A3@DuMo*LaBbT8+M~DdLFe~_?^(gQmKnSdw!{Ry>Ci>kwyxGI@qDSX7 zkIuXNEug4%>3pvF-9_`gXKx5-+uPM1bdCBEa)65uo`O z==vhi{0nIQ8Ppck0PTPRwN^MltMp;#=GUl59COjvVD#yH;n-l$;M<$e=)>>wf`94( z-`2M!94!a+L#!pKgAaE;i6AoJ+3!+b(!^^IYWL#t7QAA_to9==|W)ad<+@ZP589 z68zgVL5qCK%9RK8iMn{dH!`es0j~VhlP6nbraZ=(LJD5iQsnsL2w{=b{+&DW_S+5 z>-G}>oqz4w=_cUW&E|3NA#0a#hX_YkFk?pu2V++-Q%48~Q&%u^M+gUVS1?OQ2nS17 zFl$E$2WwX_TSo{7TURi9M+gUdS1?CM2nR=3FlR>y2WM9>S4Rj3S6481M+gUZS1?aU z2nSDBFmFc)2X9v}Uq=WBUso`HM+gUhSFk`w2!}vduwX|BhhSH*P)7)dP*<>UM+k>- zSFlJ&2!}{luxLjJhiF%@SVstlSXZ!kM+k>_SFl7!2!}*huw+LFhh$f>SFlV+2!~8puxv*Nhiq4{Tt^6pTvxDsM+k>JWHU`1=xo0$jo=V^-Gz3B_a2D& zdyqJ&O#(jd7#v!lBk>`Uk3f=WXLx&be(>pbSManvP{!$T@Bym_v%3JeUX0KMTjZa| z$guB+3g}EXNK~MuH>~M_8Jr$KJ8co^0kkR~cX|K~kV00~qNImskW)gvK@LYd4;^=U z0HuW!;Iwc8k`_)t(!vQyS~vko3nw6H;RGZtfQBUD=cE@vY;EsE3*!igcsEEKBaE#f zl64?Sv@k~QZ+JjA{xlyD@aSakEa&hz4rv-fcP|}x2als4b1z{4ZP)NP?hYNVhczhS zTO~Ze`z#n3j>Gp+fX+t^K()Z5*S2399FYcgj12qaRgpUYp!N;={hOfp^z8iSc+Aa! z!K3vXe~TVy>*fK({0k3T%gGWC#||GhgDxL7#+H*M+8~Z$mk%3L%gGWI5XY#?hmE=A zWQi<@W9-p7oKgP&#%n^i{7>+qIGaPedVL0Z<%5cn)jp3LhsC^7w zOnUvbGUR+dlZzgfAB)AjdTR^}JbFz~&*XGG=9bR@%dOz{PPcnO^9jc0AIzm9$K4A+ zqo?pF?PmY40NOJ2P7@qKY}t$q`*hGE2pYSL3=9m1!R9sZ2k)BUpLzho4{+h%=3e64 zdZ1LIY{|`X--$HDAoW;nn&jxH8tdvMYlCf1~U;s^{L#iL7 z`lX@1grS73xxRq0l>NAS0W$+=G?M*)f&g^9^tgKg=)`G{&T@s$@CtCt$3eoQ^W6Uj zko||p-3vgT@#rkq@aPN|=JUvrgUY{}VL8 z;Q`*e(P`Wn%+cx1G;(IpY2?i8AT9@p z-~<$OM@E7zKi&+E0+7#-H-i^tgPG3YiLmZ!4v&M+ znLT<<4`nhkK%00Toz0-bW;~8JgXVIfhJaSZK$)NsbSM+Fy$Q+$?SFzYL9HPWGx{)O z`3|!GK#pez`HvmsKX#D+*g^hd2l5|IDcLH=Wh`!Avt<34qd?tYMKK+9}T zmgswQgZEE)bWZ^J)1z}b$k86HmrA)kj)V76fgA-|Db@+rbvO-tAGIUsx?a!%*v{{s zoqrs`$L*DbId;3K6u26`ZH1ngW&w^rm(G`--BVP+!P6~s3bZRw2z=GWH^=|iTMm>8 zfwejQKk8_C6jVtt6rJ_xya8`CfvUuHYT*1+1*)mO>Yx^I49)ct3?)vWtYLV-we>)W znMe0@kY$GdA?eYho8=ei3|>JG%L0W`?rx8Q=94VVKUqq7J^mkeu{;h642Ghc;40A- zVv!)GMTqzSFQJ0?|GFpW66imm9kv-BpbK_DN7efFmZ(VhKre6y`>pjriJE734>$-6 zFL`v!Tm%IIkB?=xMk!l!bpb=E1n8LfLq$(~I={m`{t^`O$D9oqK zIa%V~;lpg;*yY0xDxkGGe3%VE98dwR+~LD)1mb`SXqgTlX1wLIN3Rbv!SdO02dIGd z)I0zhoiqFoI(1Fgqt{2m0K^B4T>M9bk4NV}NcmjH=wbN_T0VoO*Nc$K=U)i*L02{P+Lo(;lZ}23Bg4KoI%o}QM1KO@-u>NN2fE@4v?kSqq`fFbv-&af`mOfH-mZq54;wJu{$?|GBmi&>(L1|quZMYym519xU?q=xzoja!*VTfeI@hh=+VS zH-mT{AP+&=KAoFEr2))CATwY!pGU8)4`@GRuV`)sBf~yN2INfX(QErh2^{pN(ij=` zxvPQ3TtF2gxE_MEM?7Xkf{xg70aq^F4jdp3WW3v>n}5gu|NIQfjy&M~03bf7Lixad z(2++KB=i4(E$C9yV#dP(od-efABbh&K$dL>TLzK_TgERB+PcZW(g3PlA?Blu_h@)_ zegWMz$$Sj7;rM`W>l6N#^DK}-y5lSi481H@L9t=lv&nsW=Vilh-wrXBC^=^8s7!r% zF}m~J!FLjd?=ruEIGG1Pq~QnfK`Wpe);K(xe>0W@cV6@WEpW>D!U3&6Gh=^%RCeA2 zX}*W5IWv|4r<_OgQ2`Io5cNLK&g-2A55D9zJeYYBtlURM1+>J3-?8(YW8*VW5IGti z^XrxQ?$yom9W)myVEERf`N2QX5QGGO3#gt09TI==g@Q}xFVLlL5{7T#?LWuv0v_WM z6_v(+AcM*sJi7}794)_>ntL34r(pR3JP=W;g~-32-8CO1JgsfMl!}77R?I>fZAowiflc0X}2T%Tu+$AE-e>v+; z`*hw0$ERoK?f*w#U-E5z>(lwyr`tzGprqW#I!8sKq`;%|g~!1c3Z1WfJ6|BT$Fcdx z@@uIDvUjwR+CSL*vlD#PDyn}R55D8s4NjQO{0HZ3WMF7u_8W_$v-!9J zB7A+iSwXW-9^I^<0cPLU10^!vy&@JKmWRrPeL4?(@ZjGl3Q|yd?Iox`=Fusm;?sG1 z17jO2186?)KnV|Y=PM)t8~=kwDnUm$Gcx${yMOoTRsCGc$ne?-)*kaX&I-z_AkCly z=)U`OLbl+8*Y$Vuf*j$|33ieXhRY7aT(%3z0 zP6D326&fC$uRHI09DK^$d9V2yv&X?_%pRIwLH#9u0f!I#0vzC#^@98!%?A{~CqFkI zeNg(uqxF(c=Lzue6}SWQ|D=cJK~NnCsu9&e49xYXj$JZLjvX-!65!#NL#6LMnt!qv zg?7I3IQWR!L-UYVZwZ6ESFeizJ0yQ}MS#z%i}=+M_p2-7cSqdsu82P!aeulZ{&vLu z?TYx<5%;ev;(tfn|1OCRIq*`FX3!8nX#J^gr-pAQGicO`15{^m9AjX7&FtH$?b8Wb z(SW>tx)XH4eMvRAl%8MB$gr;(G>y3flx)H2#G}_X3?e%fBwGvK8gl@41r4~^HG{~v zg5*IH8=jpvz*^D955V_n{eq@J&;g>?JUS178#fUDg3IIJ09V8RKE2?pV9@k?_saY; zeEV7smOe2{kIxhSANA;FUcp$(2fmH#BqJzOaF>XJijE6lH~l~Q`YyEm_56R_6O;)A z7)qBwt259t4|w?px+0gC0laq}R6jF#bc=9!G(Y<1(FvjtaCq2)0;%-HVW@fN^G)6C z)@=NfK%F;8c>!-PdNjWg@a+8SdE6D0hZsDMyMnSUhz8ll06H^}r2({_Fr|dU2YN{a zI8;m`>*X<0x#-}qz1*8i${S2DmYQ0_h2+6m{e7k)G zJez+q@i#SrR<3sYGC&4ozyS_#5BYS0eFW!wbl&smjr;F$@ipi|hJ(*pJPtl%=@zlH z7BMWg^k6*i!FbN2Tg;=|4Lm8r;n69g0`BI8b9i)yad>pHd33X=fUeZ!@Bq!5b+UW3 z-Y#9``Tu~g<%!Zs;6;-l2f*zEWw3(}SUf;W1`0Vqle6mGIDryf+?n$H7M|pmYp&myMuDcZ?v1 z2PnkBXA5@QFnV;yfE)o92FZiMpa$f&8j!FEqmSh|kIqm0P4S>hgZ`i7Zx#Cw9vl{c zH}?<2(l=;)#-sDIXXig(#P}-iiwafw&lSumSR&hHD_=_d((qV|D!y$x9%~C6Hle*qw%uq6bmG z2KaQl3xIB~fSe#-l4*F-rxR&?n@_I@m*>S-zLpot0(`ppeL63I(u$*{38QDP6C-3x zztag1%Twi74G;KO9t0m%Qm*W2d7{kPU@aT1CL|%^xPA||DiGTMI%{7rlij&J7&$o_TEPA;F`Z~>2A zmuvrB4NrPn9x4ZIV!zJsVR?+d4Ri*r=T7L_O?gkni+;T#XCM6k|KFwa0(c`kWCygp zOXr8?2MNsw9)JZQyW3q6`yZV^8-PH2x8wwz_yt|$L8Onof+u*(>VeV+;7vezo(CT? z`)c0w?VVx`DuumzUF1MV(7G@%@C!Ih;1}>%;K(oNG{F(FZPj4|zktU9kjMs*$N_!< zhYS1y9uGhw7eFEpptU+k0JPbYBXnYr*Q#>2qDc z<9NFOxVUFvKuX(JMZuAu6UE4|&q5v4O#-c+_JA%!fRyjx`VlDl?h@!J9R(m)@}gJnLRmN&}WT`YeUJ9%~&aClfAE3)*ld{)BOdA&D?(Xlg> z!?UyGuYhN_hOgxZpU%TYp#Io@5wNd9^BEcTd8mVyOMV0=U5LlwCpfuu{`Bazy#!I* z5y{A~FAf|8pwUH$`d-^D5LqrHqhQSpSb6Eu`N5^zodYz#q3Ni3z@^ijqeR}L*X6hX zXbZUmgGaZ>36IW@^8z0K4}#W0f%eOR2YVtQW~+j1o}`X*{sUyV;Q>$Z&6%KmpP*^- z|Bm4Ba{P9HvDDbJo6)n|lf$F)yNBj^&>D7rr}JRWanO+_{7%O`EDw4}{%?NH=(r2y zH;>LAj?F)qN-`nw>kYpB_LGO^A&Bxrp4}op!K-aAdT4&~;CH&{VR^xm-|3fkx6efm zP%Wf+0%FSvh{_Khnin7{FMvuU&=f1b^KsASLrlJwhderu7tIA#=oB z$JiN;xic~xb7x{W=FZG;%$2Vy?31a}Q zKoE2n;1_gP;1_f^fGdNR2k7+&czn9Mn!^xs2ERvlwE}`^0A+qV%+KEfDwB^fGaPef zWH{!`#Bj_R#AabQ=FG})%$behm@_-WF=q~jW6qom$DFwsjyZEP9CPMjIOfdDaLk#H z;g~Z&!!c(8hGWix49A>>7>+p$GaPdkVL0Y2%5cnCjNzEGIKwe#35H|Nk_^Y3r5KJm zOEVmEmSH&NEX#1rS&reDvpmBwX9b31&Wa4joRt`kIV&?9b5>zE=B&za%vp`$n6o;= zF=q{iW6qik$DFkojyY>H9COxTIOeR&aLiec;h3{N186+*n6n|nF=r!&W6s75$DBp7>+sHG8}WZV>sq)&+u9fcCod` zanQ^HB(R+Y_ywI6_ywH}JdQhSfZ`+?F&+dd|3ZQtJI{G`UI({~{urW+H$v|Z(}vz3 z1}Qs0>(+Z2L5HYAPL~Ds9Ssqu%YyEa@#rnlh8?Kx(OUw#IqV*PGiZp;qZj>PS(Dyc zl=Gaw!TSsR0xZV-0zSr|#TCfs$sPxt*8d}dGo~%KEM{kKS>Uk}06Zi%Ekk(hY zZQvL1Lt07Z&3dfbf3(-29IXYepbx$WNZI>XkG_TsHx&O zPqvFkxPu3@qziQA*(ZUV4C!lNDh1=nWA@y+14p+&_&1_fMn1{nIFL|1=8R zKaB$SPou#7Qz=;g^blkT+7ZzGVV-T>)zJCi z{MK6yIqKh|+uEb`e+lc0XaE2IH~i+&c|RJgDGkxSgOqomdUb@CcLd5gSbr8AzTMW) zg3F`3S^~k;fHFsmGe~h3eHedn77d**3-;{%=h7JN+O>z`@I-W9}IY$o&J4=KbJ<4of9Hn)idt z#!`Nd&g~#EkIv~J0dQ-`iyPc%(+OZ?*!M>rc{o1}4B+ht_;?1m1qxbEuh4A4z~52> zS${79@|g+$HUaRGct`$iCMvHbkjG>Bw~26ogn7Vs9hY*pTq=F@(iD8&f4PJ&s4w;( zG{_m@+s*IVC8J^pI;8lr;YrVKmXrM31Y9gHfty|~9rsG*!0lDgsqQUrLEW8gCZO#g zG9sYKw0kAb!3Pf>EII~uJ|cWULomIypc@2qKtaopT4y?lP0#z73me2T`4}%tNV^kQXj_5T8wEf`7FTi2~T8?LeSz|o* z0G)u4>4REhfbQ=Cb$%e@Nz^>Q+7s#gaTiei;Mt2*VSq(oCy*oJzl%o%QDJ-pR~X@- zQF~~G;n^D^f^xnW1@(m!q{48QKsn^sUE(zdsC%vD*~x|&Kk?|bZQ}r^;UG{NMx7`2 z=(Vkh0ZVR3LGDfS%QH0FGn6obvw%B9yD+A9&_ty4)Ep8<`{ zoSM zO#dH%dY?$`F@o~l>>k|>pg_iJgI`4zr!O#tDZMGiZpL)RY7#n;D2Q*&7G zMS}bv?9t5&T2aKmO|bb_Vrhg&Zz1F6M2}uu$OsF=2F8}#{4F)035IQQ{M$gcig^4# zZh5%m8UMCJ%|8-LwLJbG+?43i%L>wv2HGzm!@o_Cf13elP4E8$mY+)A7#;wv6M|rm zZt#wl4UBEfAh*NZ44rU+xF2!D71*7}m>ED(1*uOU(SxWT(fPq(BRo0}zvcpmCzxw^ z;DZPMMzF;t)*hBON?$^q0k^*MzDMUVuv(}~_G!b8AMLgU9k~paLz<@Kg{p%z;1TXa zZ_h)*8{uB)+@i;ER?yHSC^v$A0FPh(ZQ$7)&}NQONI9Gw#)1%o|9L&=2Xto6%rp!>H4!VO3at8NnC68Y4)aYwT zk6!S6?P~##URKb8wb$$(z2LL+JvuEmFdjy@KQ!3G5_~yPiMEF&IHF2)JuGcOb3`RZ z9+tKs%_Zg@mbMBE3=AbUh6i4L1`TNUf_-K9_O+QuFE42LVlODUyw>pO1y9j}&P!u> zE#=Y63(~(ARJ6Y4@#y6R8L}5Nzq@4?eUIbbcoI@B_{F9?91oJ74-hyzSL%!sXi=^MT#)n-A#dOrPGEi~qfQ zLr!q`fR3O6^|cTFXYxtD?|JYst7r4!2k?^(zk!aRu>dKRIQX2k`8aAH8=T(w1ze0k z_q7=D3$hsU3;Gxecr+gaZ(eu`KHac-7ue;mJd!VY><1-*|NsBXdnjH9FVX`YpcZ0S z;N2^8!lSoDt^$1DH>|%6J3k86--aD}2XyWzg6}b*N!kFKq*T<0EL-Rx01knBiQqF$@_mw$3z~?`C9A}jQr8Wizh7F9- zvEcdzeZL!e{@~{ZH+bRcA6-2-cOaF=knt7Jf;NxFHyWU%)d^Xu=FvGtWdW$3>)fIO zUi;IzM+LMz$pge;U{C;!n6{`WfF}|D`}A%BGktoOs7Qbe>0P4&+8FB5J4ZzXtmG}U z{d>FxEWime88T+wZQ;?|q5^7fgDy$h2};;Lo!@*qA9;4Z@a((^&X}zSO2j<6A=Vk5 zd~JcqKiw@Vpqa4l9u?4aOP-9!JsHo!RC+MCKwQ%a(YX<{SWegjbf`Q-gE9jHXmM6k zHfSmi;u4S610LWthzte{3?+O%{Of;sbhfB~+8eKJF>Y}HOM@;OgsYK6Rs+!oyYZoO z4mf;3x6rnzfNDoVAqG(iYKWl5Cso4F30L@eFhX4C!Puh$vYVKYWN?6nWFj~uLGj1n z(RvaZk_ik9C2}BRK%VyCUw_b}vquHAt_&1vAhFj0$f0)7qZ494H`F0u9Z+`b$r3J@ z_Sa~E4KWf_sxg3U1I3vq|N5gKTR?2kc27`RHGGR6@IGis6%z2ECIq4u3Qo6({IF&|=9cMBvw`Pa8V(o82*;5a1Lfu@^4 zCu8=m0cQbFkpLlt9*CFu*Y8n*L>9#Ftp|L%A)#C%?8CqQ12oYafX)ZL^V-g%^DlC^f%SluAr~~B zop(wFF_d|9zW3x`f83|L2OP1U2VZjebVJG%&x0?xJi2?p#R%jK7%q?QIgm&=_?pY} z;9D+_gYUUK55D8_04wDMElTs~76q-d@;La4%cFY>cr~&|=N1*v^eTuCDe6m9Dm*$v zR0=>V7&AbfN~Q+b%TqF2560h z0_dy{38)09r08@}5%B3u0WDWyQSmtLqT&HcARfJ-y_8jpagEBFWisCsl^U}&%fD=Xmvw^R(jf$K-4_791qZQ%#+Sn0Lh7zFB%m#7GUZs*}Z?73<^P~rl11^@OF%|C_sn?W~JH~(bj zZ(GB_z`*+FKWJfVi3$h*_7fhxqPxMS)Tjs;LigM!p8y3g$7@!PZczWK`KLp%HRy~0 z0ni>p4v<}JP}5yh*!Z{msBj#7Ai#N|6P$oNtYcInO4&S`k0d}hri1Q(_zt>SQ}nt$ zXf2m6Xet@x1F#_;y|y_J*`I-o4Eu_~vVySIxJR$8A4K*WNVWtl3u;n<^`=dLZ8tJ@ z7XY_EK;s{to!>l~|Nk#xF}(d+a5JMX=$-kDi zh8~Tebp{Rm+Ya=yv@$R-Bs+p4IN62Y`2aYoAnkj^`e3jiQhNoRkFGud7REC`-7yCS zbUwO%bUuc8V2>f(gD#J8{c!USMi0pYpkv#)T~snWpw|$?$7j*?qw@*52SeVY*S7a7 zIPx`Z7#a4R(ncA)oq(?XI6EjN5c6w<>_^v+&PQoKf?8spomV_Nzaw3N)y)8^Wk5y! ze$f0kI6OODRAgKYzk!ZpG({0ra0IWQZvMekD}y4T0_v*F0Ubs1!L#`s6O!CvNAUf$ z&AWyc>KunE>c= zG7g{4=RVy$Dp2_ngU-7U&v)JjYX*yVzD9B_NEi}$FJFTDEff15iaXeXE&?7neX z*nQ(7u=~cjq4$mRPdNa+jv3(|aQX*TDiV+lQJsImH?)E7M*%Onng=gvJCB3?`Hb`Q-Po}HkILIONV6bo8#miQ4|R>)c~ zGVCkUVPJSI4BE_rBv_8J!^$HWba;#oL|zo6sUB%74Zl1CH2lH+pl$}xn4KzkVH<}9 zs5S>X*Q3|=^#`!6(I5jR!EC(-5sU;0PD8O3UwQA*YdaUB(bAleVc&jKjT6xOx8Q~q zq|gGl=b`mkH$(FerXru_e~hK>K9Ks~vs(bPW68p!+sXs76d80>oTf+fArA0l7IZw( z(x`;z|3Q$b<-wwluQ@$Btvo?RoB?FNChhm{`3Hb@3$cRz1lnHO{~jE+?x4^>+2;iI zFIX8;cm_1vg3=K~DayV8a6ENGdS3kN4|el{S^$QZJidR7gajyjJi!pMqY%!ANF(w? zsz)~qc*QcPig96J*a2#=A+^6?=bRn~6|@W<$3eqZ44%h9WhrQr4g+|8F$9#MJUl!9 zLoey_?KT6oLmeC&>LnQXTR=snC+HsZ)&u-4;5w&U-lLc0fKRW=VWj!fUT2vV{P?FE zN&+ZdBJ)}nTtLCY1MR#V&x+(ktM6dxYFE-Df$I7$W4{Pa5Dn2U-8 z==2jw5FrI3q(OuXh>!&lav(w;L=bg$3#g9Z@ag;qcASrOiHbuh5A5s=&@sVaaY+6H ztxo`RJDHC=D}d@<(4rx*bB{ZNQZ2)AXRt3kdYuJU@RvAIx@HPA$&YfR5$gN_xcmpN z&xDSjd4k5SK$Bgazd`*U4QPSm0V*RP9b&pV|202a?194CU>~T@1$GCh9x(v*^aMby zG?0+T@fPsd9Y_giWDeXm>V%G@^=^Umf1zy~(1DeupiNA@E-E?A4|qTZNq~CxpiVNV zYSH=hQkRK=0V(}J~`<`nUsVJf8tg+Nbk7sA7lIpx~KDPs>7>pjE*j@f%$&Dx6U9n_Vp`Tu}C{t`-&0jUOO2x4T+Yc%b5U zx>{6tq3pX|Eh?bp{5~1vH3#zpF(BbQ24R{h+Hw1$1OOi2bmuMMVgz_fc1i ziZGP@*uA6V?-QTS=N{0Ot4}v5Cw0ew#uD!PK)0fSPS@G`7j$@Dj*0;2s40EWg|il* zUDc`{pzUAxK*^Y)`N#i~SdV7gdQjm|!i{v{EK-)VhGfZ7eaztmk6v4M8&LOO^n@!T z!@l>R#UUqQXX}A&@PMD^lWq)Z?SPKu@4V^R`2r%_Yy0InxN7b+W@Ok0x`g)iK8*GW zsJ?@&4{{R#?-7R7XL6AG%w~ktXTM?fnHxBxfSaq3_EhunKZYlp|Ff4H?YIt_G+q3o zSi>XvxCdkc%%hv-U^hqePsUPVa2st0s8!Km8xM|hrp^=4^Nfxk1XUE^_E19&KPXN; z8B4!G0P-g&V3BxCbW(EXSPn|~;jvw89_J_))X^8o06 zOhL$c@a7-dr9zr%UJk z=HnNd|8o@`1KZ@-dD`*&ZNu9httZp=|No!H@A)&$k>B&SYwM*ne*gPvopK)h`#3zB zf9mnKg4V=N@c4g#f1g3;N4Wn!f{x6E`p=`+ep~EB#MCp$lUzX7@`;2YFe|I+w9Pq?<8 zOyl=IpVr9*8*u`ifAR#J=PGm<8TK`RN3%ffU09Axg2>i_WShaVdaw=}tbNh^27P=G z)I{O{HOD-9Z9{cH$p_nrV5zkSd^FDwRLg=#^VmS6c`RV-`M0~Muz*JM*dRlA?%+W^ z$T%LPpLOIh*zF7;*X`Ct99iJeYr7I6^-Y_RVc#CG!$A%Ln+qo3`yra&SR8jz;Q=2z z3hCH@CfGtiLzq4)Jo`XHh+qw!2U|~;a)GK58PMI@puXXDZBQxJ2|0udtO#=62dFhJ z02=h`{0%Z1lwv^@7mrVGjS2_2Tk6yK3#{Iw*G2`j4)>N%CuGwHSQfO74$`&*uPJFh zA^^+a4h+x{TKM=FXnfJ5^LK;ob8sHE^XTRUT}%LK6k9=eh{D%rKbh2S{tcqniOV zdUef`?L9tghwZjibv;FPtd_ENK+4(euAU|&`{KE1_lO%W(m-7y#kPZpuM&;z{Wt-cDtwufL->$ zqw}uE_q!g7M?I`_R5z)lUYjcJ&#_|c#ytMeUxEfMEXWaFBPEkFFJpF zf=`eHB@57`P624!8auRS4qA)L4(*9Dn6jDCTOxl0Ca?n3j;&z0np(C3=I6Oa-e<#tZjbWMI{B4+>X1b z=zzL!NJUqPN&%=0%>bpg6i{k2@agqY(E7L zpfb6@r`ts(!?V|f1CjtcjXW*SmXvxl+o&+`x0-|8(H)|q;MHrQ<)iq_qw~Cv;&Ttp z@8C_F9{g^-(OpUD>!)mg`{&!JCDxG z#ljFyryX+r&Ug?M90i*gJv+~~T=MPw$KU$m-~azFL2YJ_)^Gf+pvh5?5^#tig%@c1 zFWi^Z3onn(m#_H|=>r^Ipx{XZg_VL=uZWh9;v9xI`Mb;zv|Q-=Yb#{)K&jo*$fNT&C_F%%P9vo7@L={)$pCq`z+oFGNE}+e zfy0F5|Ns9!ogX}!k5nK{@qucb6rbJ{6$6jn7!@7Rv@!`P$fxtCZ|4Kpni5djQAABU zps)}|k53A;PoY_@<8tYg8CDVA;AG2oxeSLZTF~x z$}_MI@K95CfPhc0=?+y;8^-hySQ1{Ff`+2H10+0pP1jV15SaK~WOn(QA4EMG4e}2_C(syRb=Qc=VbsMUem*isJ18k6zO@ z6eUnYD?EBl3$aK{08h&Innq%i124VkHFZRh1KSB{?8G?6ImUwEBtSQoz5BsnbQJ#)W^I6Qc|NHZLX@{%t|bF8te~SX}tG6|uVTZ>wT+;op|T?!vz< zi-Uh#6es_-EH3_SRowjBig@_9dGYdZbK>LQ7R28fqLR?*q7u>RqY}_rq5@tc09qo@ z8KYw0(wU>8;nJC+qTte5qaxwbS)wA~0y;p!1$10QuV{rbC{{qH>=uC5B7nT#?W0ly ziM+-mAZH^L0-y{EFK^M)Kj>h)|0R+hy?*~a8h?T=94hC5w5c{Qf&vI#{eCM31_p3& zLE8UB-^uN^#*?{ zXhhAk*G2xn$M@SFiieS{{LR3?fOT@*@c%AQKV~NrtZf5n?}7^pbNDESwMXa84<7sn zc|mol2jfkTgD*uqta(8JS|sn$Yy092bag-2X<(w8!|*`!Po7e7NSoZF*H&H~xk&Tq z6>U%gACCn&whyccQNAP6SAYk2TZCt?+kc z=Ni}y&(7nnhHpW~+tqruzW43?TjJou_!k@`uRS{N`e^HGz*e?EXc@6l^}{VLds9FP^D!6Br=9jSfP*&(v0gHPv2c=q&R{D_=ARXloaJzpY+2PE(`3=cH_ae4x*KB2sVE5=1J*LOV;L~fPvJZ5|Fr~3j;#{^oY~e1N>7CL>`_H09F8Y8dL~W93#pD@K{0T@8;i3^%2Kh zRCqz-<9r~3A97!oNAmAuE;hW-d8ot9znN>^G}Nf@GL*0zLTb&18Wlc<60ZFqhk)&A zs8Qhu34q4-zyh716-EM}Jpv94p^jm}9*u86eQVFoZ-%h_e4R&||NiH1=>-)Qy(TKq zF>>(QoZBAXFMDvus3h>WOaVzZ|NhV4vK+*M4(GOhLoL6Ld31tLrt;`@`|r{Ep)|mw z*Twk1$M<_4ipM-V%?xiF{s#vN=$JSLSHqKzumRxaAOAi0T@HIR9sxNo+A$711AqS_ zINu+aWn|dLZOFjz8Wi)Z6_Ml5qt|vPMAdbWDn3Kx&YVZD?Hq{Y0+1xHAp-++sLk{E z0npeCIE-N9LE!uYx}WhJcv!%r_5Th~!0rSs0ONN#(fs$nW9JLx1zOkZfhaS$Y6LI>Jq~Po$q`)Klyb21gr1>M;r&ZtcZoq z4};wYn?D0rjG&WE{-NaWHQ;ruU?V^+jN>jU6(E0l9EVJ=fa|*BE-En~2CQQQnvcoA zHF=oj>C=%7H$hvlrGn}P%( zgA?G8X*p1O_%$==#4u|}c$K=ibbyusmP2aPXvyQqLK%M$RgJW(nJ zI^+vFy3=x?^wH~0V6#D^Z=xQ(wkqerNq3?&Bf~ypP|}qKoegYxqD#(eN+^>1spp=R9LzTcpN)R zR5-dbSh@>1Tom6m{$*oeV5~O-mpsjX*-PS^|MKv+uH|B2Xg>C<`5!xf^ENI9hW(k~ zd5G`)%`3P-xB7i^?6%qd+PLvA4+8^ZiCW`db_NDU{?;;(Qc#iA{ExXrwD}(ge`_yD z2-J#u&AJ~nxaQbdqr%hp>)fxm|4M`!f1UsJ_8)(1H)uGb`G5lW{B#-6aS0k8orhlY zLc^=Oh{c2PQ@0W5I497ZQO*CPOJ8?IaX5Cws0egLae`>Ut|%@LEz}jo4Wfm+qIf{G zNLLguh!*XN;seoQT~YiXTD&Vt07Of4MG1mv$*w3N5G~aeB@CjayP`xuv`kl&D2SHr ziV_3Sa$P~f^>uduiwEO{Zh_`sJSD=dmrCEi1Wg_y>Icv^7(bO< z?UHJ_U83i~cntYG5B_bhoB!&2@Vor$ievQnf2`$p=^M})4{YGe!hU%`Crse&|ArbP zP-nIbJfHKAhrg*Bv^2i?*cZ@k$e{D0w&_?k|IH~a=iioN#n}8evosgPVru@IRGJK8 zF*pBBE{z1SSU~FhK`hqhzlo);AQoHm-@H<55R1L}Z+fXAh{e(TH@;LI#NurJTU06w zVsSP9Eh!at*viPiEyjww`L|w)B&0t9a<=7n{MIk~pv;6tfNILu(yL`F8GlU>9 z(Cn9Ehd)!7FZT{mo&<^A1O;%1KXaEa4|qcyNDMRz?bzYZ(&ftw-ZTdi+Xzv|+U3i) z19WXONNg@djIGO;e+OvaAV>_Lktf9@_{5%5KWEhkGX9XtGax_m`< zfVy}sCrdOPJN$XOe8qO~LDWk+cKGvk`HJrV?O1F%S;Fbq;m^MVG^X#_Yr_t{v=DS? z=_$@%-wyHfx6A;SHa`UTTh=f!Fzf_r0!f1|Vz>l3H^!6kc;~V2_nM!vgHBjv@aVkm zc#OrK!J{{v(Zlju>3h%K8hb|2p{D#zpgS00Hh5@W1eebQPF(?=^WxEb5OjaGHcDdf zKu!%F%%KXNoner)kPIryLmi-L!2^~SBthpejHU$&(gJu3UNa~yfEJiwNeh~&X#q5< zfHysWc4Cm79$wdZ9DK>_(aUn)!}55sphvICS#auXeg^G9C%fu+cDiYRt{>oF0_}%5 zDgml9k1BM#GC*z)3X|{vUAO1N#J~V6ql&@hk7sw7#Or*5=G$O3U&904f`_2u1=>t$ z0rj2Wmb`of>Q_Lv$$EDCDHwhOO|HlymDgP|1}(QsxI1Kwz{h8w1KoFTW8~3!!b9^z z=U>jF4&RRQ^S2~|rc*3G^0$@xO=W2gBPA-;T1E=zB1J>O8Ocz48^EZJnm({!pzETigpAw&6Ut{x{5OMwiAD;~J z&oTxEhEA&Zrzp+?>K9M|knW$?avld?Fnjd!9QUw14^D4KQPLZzqULezbTe@5a#0a* z>~J#yF$5hu+)P0XA;%6kGY~`AvBS+A#1L`paI*k0L>)WaEI|x0#|}3u5JTLt!_6AR zkZ|m9vjH(A9Xs4?K@2I!4mUdxL)x*!%^t*%aqMt&05N18JKP*W3^~URHzyE7-m$~Y z88WVk(!#f`J`8Sd{}g0o*muQ*fdRBJ+%^p&xEmyR9wZ1_`W*-ntO5z1FhTBTLfRi5 zy|#P;jF1shQ2W|}f7|iqANruB@Zj!|@gs&{hYqSTAHd;tGyZ5wrz% zFF_^LF^Dw7u@)6jbqu0G?I;l44bp$CMWqKygGLKL;(btlKa>Xb-a+D^R12a(i~B(| zs4oVhLBj|jdMZ>ss9g@?gEobM`+yvX^_HL&Z5-gm%plJ|_P!l=Q2`wp0ajW8>Mm-4 z1ES?XNvTJtjEZM(j0&SqZ;na@sMDwcO5TX@{pO+)z*1uA0XlBPk$)SH3ja0%%ZsHN zpw*F`x6&rGoGdZr2i@6d;PL;E$NvMCA5qs!`hXV9LH1&_94OuBYWV-P42VzynW*8> z&7>EZ258jF5ax64Rxkkj^P6 zMIa?zu)h%_rvf~XLDgFxoi}|uq2+$B?c4+4)NRBAT~>!Qayr2SbUuiK1mZloZuV{l z@C{Aepfn4T?`A+=j}DeU@Td6)dpV!S45W2shdp{(jd&SBr)eRT*Wl$BNcz#|6F|j3 z1Cn}ldC+iG^BW1z&TpUzx)K%0$Uy6XQdv-<0ADi50bN|%dY}|^GaP91#$o9ACOCY$ z1w49f&7~O`UW;M~J4!=B3^F?aR*srpJV2{NdP|_|cEAc+50r{SmzDhgU+-b*qQb#H z1$1J(#9^Q010KD$y8FT5%?9fB>l=Z}2(Ug#{s)=Y`C~t*35_`N1KoTvH1kW8Kgu;1iGbRKgd+r;v&#J!C(Qf_gfE?@_1OvsFW&ufL1g?J;Mkw`<5hzXP)l`ds7hP znQ&CkAf*>*0Sd3bz~ld*v*RJND?Z)eISb!zdmqp}-Oyzc9$1h4^R>! zv@i?mYVfvAyY3nl7N5><9-X(q!r*x%4iC#4{8J9UhHTgJNoMeD{=rx3W_Y{X2E6o` z0i+46+{d~`g`-p*ywwxBn9HNrmKEZ|5H3cBeXor`n}8vwH-NQx^x8h%0}g>8ko*@T z28NxWJ_}e9QJ$ga7mv;#@Dccfpu_h;Lz5?ac|c_~V(;id!~cetcEaZ`j)8L_I6gf( zFYE#hc!G}P?SzPfG6Xz)JvuLd&ISGM0hNTTKf4TC#oz7D;nR7@L-STqqDMEokL8C_ zA+KH*W6;UiH$3=VPk40lzvl7kOll{kc zgG0xUlaXPcgE1oXJbG={K%_iDQm)3Jt~YceF?7Vb*Y+73B;TWzl*JH@9PAh+C2V{c z98yT>4^dwSxOSd(={(wb8g!;VctzPCa9lZd9&>H|#^13LGzASV9!U&0QW9Xb3Onr{qXrwR#q^x8gV2Mv)!H<`X>GQ17VM&SL` z2=ky5FQB@Vtvg1A=e07}@NNTe;RG{~&!g9N639SEiU5zW3m~1J+x(viRPVvdOGNyF zN>1=j-5M1EkM4L6kJj7#Eoz{SMsu|Q1AmJ&BLl-XcMTT)R?xD2SbFJpR%reqSrXCw zgOR`WDQGadJ6*%E`3aNf#Wz0P*%F?;t}Y&(&JvE@xeBh`r79lE*#;iW*&3dV@AiYX z8Np|0JUS19t^>L60iGgo1)t^c+INBvvT?-{p1p1XAmco`vkg3z^Atcv`F7`Ncrw1l zW85pSagY_Lp535BoI%wScz2?_XSctDN2jD`XS{>Q{{ydOK&1gv`Ui=7cE($P$BsNZ z-3>si5+LF8-&=sc^$%#R7HF&o)X?YzU2WkGz4@X$U&FEUtz+|37T?Y{o(JDBH9uwY zxQOOV@Jh_@9^EF8J26~3A37pV4FNgT^EhZg3G7q>kW+m+4ShSy!A|7`F?>7A5pMHs zeOn>|YMgO+TDl7qb3&M%?gF6N6{%T;c1Eh6_6h0XB4`hKT zXhxy+6$1kUO8&_J%{GB+m*Xxf5unyTs8J7|3_9+j;scsvgSMBuYZ*Wd`vA~N#t8UI zMh?(QMjvpt?mTFCp!H;FDd?cY0MIhG2+%UO6i~CD12j$K10DYd%@0L*H2;(-QvK$l z!odhST*pNvpj)8%(LcykLMcyk1rK|PHl%#=VDwQ5=&oe|AF1@qr}H7oDK((xH$%y4 z*eONLM>3F74Y>Xc0Np6|pP}(Tcy7c1oGqIFvzPcZ|K}+UfXs^&$L@g4iF_yy_DDVk zZ9{jnG`?1A{12WLQD_9+aK%_E4<3F6&4}g7B{EG>G7SCPs#RXkAxC{Q#-YLHDVE?y~mS(f`<@4}?6wr*VMp%sBXh z4Lq*~8Z|~-uA&Gk260}l0vdOQoEnF6xr!v@0MR;7SDM(%j6vJoPI~mReDdh6b~ilf zVfmw+%cHmEle>rI?=oY40cL(d27Uq13F$7M1o#C&$E3S_Qs5VGHsBX@`DCyYv*(_OCsT8O0V+3jZGY3*iE$^%;>2omw>wD4#? zz~R~HX7QQ@B;eUyrUAOH;ouAA&O^|%-wbaXo&@J)(0*R#?g-FebqT9yvzx^a(0!($ zZLFa26OV3piSCA;f3WrZAoqZ$zdbw8dvsm^&w2jvXgvUKO?dFTUhwF=;KTT%SRT4_g?7r`sdMk%;WOA=4Z^{HrD0m|Id3U9{1>VnfAe>`9Gsa^Ns(Ya47d^{$a-7 zJR3YVf7J8fQ!f8r6+Q269zD=Fs10Zo)3cLB#j`u+jD%;m%NYTF2?p)g}Kkun{zqAtNVpyL}(A{*P20HY<6vNvs2TIO)cJrvbUhdIr%fbRqwPq}g z4EtuHUr=eofVSM?8Z%h60!Z~N&`iz_GtlrR)M$@hTNj9eVo(X>3Aqjp7XB#t4^ck^ zcyyli1TDJw@6%iQ-?Q}{e=F#uMbB<_(6%a%)`R@5b3uF0dVN^`dvqT1_+mIuZxutF+YtJv}ETA=!mjg9?&H_FZDoWRVS!H0a>L2ZOXbDJ^@u) z(9QDV9=%@w!FF1Kl=qr2d31jFQT*5s&+p0(7fu?nJeJY>B`{I84EgOmA}P}5p-su zV_Ule6AMGjff63i-u)mZIEQ$4_X{wvFnBcn1Z^hZZ#DxtiGS~5kKRB=&(7&!xlUgR zPtbiWojRu+kF`rMurM%q{%==cU}5m=?l%DGX1wXy31)eAPqzRGSf29WcR%IX*$?7* z{%<+%01^eAV#^pI;K3Ln;dl(}90s4x2aw_oei@BNuPrkqy{tUMz_2fjfq~&AXcW(* z*H-W!bdD12bdO%!Tac8H4N5Ah3=9mf3p{#lk3s|+K!VvI!Dx?O+YJ!G2_V57kf57K zukCDz;6jjKE;wJnOVb93)DnFuL@-wszA$kR~y3 z$^``~*s-AU2B~~G13sbTt7qqb&*oatb+^Ajk=(nT;RfiEp6}oViVwjW!3hU+hNwrk z2M1_hN6U651_scvpr9kJK7w-7H;>L!9?g&b@V9`bI6Ql66+C)lPH-50^RT>MF67x; zb5_EmH$uR}@;84Q=xjcpUdKN!oyQKoWBPy0@V~>iW6UMSy^((ozGnJ=xcM=&$M@Ty z33~?yegT&s0{j9#KNKAK1zrAvNT0t39?i#DJpLapedyWzgQqCnqw}0c^Rqu5n*Tg| z=llf?&wBLk`2ia3oxm^PK7n7re*wRs^8|iD?*;q|oj>pka(gttZt!RZ-KlZxL+KXKT{@lD_*+0X?}DaR zJbDBFduV=g_;#GVL=z;?{G8q6`+b!B@6jFeLBO*!=Bol|KIi}O(s$s?=~F<#rTNLT zx8^HoLC^;eSbxf+JMM%>XZ#6|?zjsco$(huy5nwmbjIKC=#G2f(HZ~1qdV?}M`!#C zkM6h+9-Z+YJi6n4cyz}9@aUHF=#=+pKJMVre9Xb4`OuHjEuNje44wy{aCvu!s7q{S z^k}_Q!Us7z9d@Tw2hz>jp1s>8SU_vXj(`0B|Nm~#6tUwDP&2GZt~+5tLd$netlkIg?EJo()Zc(fkyxe0rB?dw@%s9thofvQ!DYPWqis=SSbpA7F(Y z2SFquU;2@3D8C~ z4a2vf+R;Zv!K2gXje*DiqaMwF4IIHc*Z5mOt-aT};9DCz-+}fwK}O#_x@}Zi4nQ1S z?9m;{@Y)AHUIJ>xaQk(ayfFZkg|E}0Owj3u-Jqh;r}IOJy+`v;Gydjy&|wyx=RFTT z=kn^+vG?j0u?J-Ch+LU|AVi2!HiC4 z$juubo!%UV2R#2D^=$rY0P%g3At*C|7Q}(}TnTts`>06pH(dao$pyOn0yNy?YWViG zA5s!|=?AK94!m>+xeauPS||88h7jni1#-Amf%dv7cyx=s4nQprTMv{Vg>?TR}}GaN+q@!Lys? z4QN`z*|&F%3IhWR1L%1D7BCBRPCe{~TbMF&k6zQ`KN%SIgHD}+j(mD{vb=FT=E}g( z`1n6R1A`0yHWmrr)&r#>E*&NkAUnZh=g7t4#UJ3XVFY;`v;!4U&VweCAd-b3NhQ#V z4N!*XfZb{A(QEq=qCg&`z#Y`af%NA<$r&-8fKz;u^6dQM+j^3}B^s25 z!KFbSxa>U(Dxmy(ZFIc5eRM$O1*jHa2OTWiA_dA+y&jC7o&3I?CC3%KyIphyJT+TX zz(oSuw&KnZ6#?&F7aho0qi63P6-eEE3{iLQ2G!l*W8k4x_YP3i?a}-XQD3_Wcr?T7 zYtZfkjQaW`vGw&~P<6rYaulP!_W$6~8IG;KKH$;G?g6f^k9jm62i0;O&HteFHF)6C zqZ_N4L*m36E}eBD=2nf zb9;2Y@X`F?+3j;k0o=X@EsgZ)tON}j@V9{OmG`uK2ipG1?|u~2?Eb;R-xLPQ$=^WT zujU7T_*=kba&M&oSm7rRe)p@My)myOAPsOOkMEZ}dTl`cdj^lr(;k|?Js4kk_J&;2 z@Bkgj4_cB7*7wbW-~Fpc^RYjjpANoa`hUpqKj=jMaL}D~-!FkC^uJ&Cu>1wuOUmzl zi{Jg1$HB+U9=#&3J$qw>EO!0=|Np<{FR;euN6a4IZyEldz%StP8+2a(Z+=0Sp91`X zK0iShsIz$dKUDg}qZzb7w++;|>3rn@vf!J?_iG-OAlHBL=nXMt0C6D=dyn2ZKS2$8 z570H~y&}Ind-n*<0L?g2v3>7jdBCUhScyOAR?Y7hAfER8e$B`7lMlc9Cm+oZ9=#zS z1w0wwc^-Vm?AdGb&9k?}NCUMz@aVSl=(GYI2ME6V_5X>|x4xQIo{dLAy(;kBfe&bc z;}q(MJb2a(y!7H8s2L*Q)9C{`L_q{HUF6d(qT&NOAOKWSdUP|tTmwGs2-3apwdMT^ z+FJ`QqrrqnudVoJaHdH7j9Dpwor@^H!2Q7x(1wun9-WsxJO6k#*K;tG)Oj3y%;wv> zMF!H~b!=+^vp^2;>HH41#>sKloY( zdj1?p4Ah_n(I92uLwYZKA%{%tH=9?d^Y9ruG; z+a=M>KLq&OAAlC*9(=&!*?Ii6C%7l^2z0v^N_7B9J>6h;diJ_Qwp+enVqoxT{lVY* z1;pt5=%e}5gV|BQ^ZR{I#pBR>)MHcxd@Y~*bpG|^cYgyn91^>oN5OZXRfB3JPr1Ge$b=&;RF5_&>>!66Q6nVJAL=;tugy=c*)c9Z#kc5 zZ;9!DAIoq2&7gA&z-k_O@;hDkXg>6y^ZLQ}tpAT2eslPCoVmo;r}Ll3_iH|#Pd&b0 z^{{-$@BVK8eNf5r9;~YQIkU(2`-b13^B<1<0xV{r`_s$>Km!D(437MQKBn+XK^}mw zP%HE4{O|Gox=-gLP&sIM-Gkr#I*8T$=z#~g6K-1I*;`^(fN~#*`viVL{{{R4ZWP?V zdBUUfREafcUg7%%&+pegzhCjSeD2Hd{@h3N0Vo<7FZwWkLP^hEQXP`un|%&>{6A6p z5xP#Mo`J#B@))Q|El}?0)A_*zoNh&qfs&dbW>S;$=w>-)cnQ>3VF6vR2P$_sU`O!0 zuJh>K2TIZ&jmIDZx{y;^UZ;U_g)74J!ywa5F-=$U=w>;LY&z(8=X)^YL45`p4@jo* zXgmzE!2@v=jH}^W$o^WCLsFU#eDLT5cN%v=#tR;KbY2AaAs>K73l4fPUhwQZ{?ZLp z?Dg87dadX&)IF_UST0chRMy>?Z|{oV^2U{R>hBy3Ybp zsKCZwK;>aDcwp>1sG93$2G!j@tsnVYK{vsAY98Cb*wzdhxdaVjdi3rFF(DbI+fTxy zJD9_xo8^>`vj0=(Fqpw>UKHw!=sbslt;HSNYe?A zP7jG=&ESzukN?dY;E_!?4iC*{(CDV8rn`Wrrn|&3u-y#4-FBe)2|ds5IMDcNi7F_8 zBQ3T|!@9TxywMJ{v_u_pL~P~AGA9NsgYFhCBx!yev_;QHr_XXk(4-tC|O1@#TUL$k>B zjW1-B7}N(j$=?FHd)u?yox|{?;>4B!PNh9^M_KQxaQ@fn`(y(kV;5@}xa&^(B|AL$tAW^&xO zmLv9)fYx)r0_`8T4%8?CL7jtcKLHQRoBZw0pz63AvTCpOKl09E&(7mMonQ$_ zCH{lI)sTsS!K>HB`aiVV?lnz(2fD=C2YQ6BXXg>mZaMf_p?x4XL2G8va(twk`3|U+ z-CM#8u8+Tf>tmMx9+sc^+YW(c0?=w67?{DPp1O9g#Q;FT@( zzEaRwFT7?oDS+H?4GSNB0oZ+8)T&?k!P~Ywk7-`>=&gX?Z>Wny4>9ShnL z4iPj234(f=o}JJW-+OIy9y35T(m_gwZdh00{5?=H?bG?nr}HI}@|elsbp7!jMln4B zcHeeqIfqAQxIl-$giD9Jq;Km$e+7ww_S$uX%X9@YJAzkyfW$z1?K;9`y8>ApA$#pE@wb5X z+I57>bp^6ILiXBS;%@=%wd)9%?+RpdgzUAu#NPs1f7KDL&=tt;2-$0Q2~zZQge!Ih zayWt)leAnasq6?>>I&p^gzUAuRFc^duG|&K>H63?= z3R$mSA9kr-AeN8jq0S4OCsy$Dw}7fqPf#PjWfcPh!!A&1fFBUV@Z$o}Fa2C(*Iu1wvZD9hiGr&6zgPJ?G;B6DIvJaGljNv&*@q^D4s)Nt{d0L~HjZ)4;LQ0oDy zdz9rlmmM2EGdBO_D&cem-5qKS z>O{64DCKCm#NTQT+T_l^?L_lWIsRsAW(Ee=mIM4#4=Y@D={VK!iP7++3&*WeVUKQc zNYC5yQ!(2yCS8yJ>@HnfR4hQFpc*$oTgKq=>(TsMj=y;=Xu20X1=A^V$KyX}u&?x~ zEC03^E}btlZ}9hZf_jO`mpyuQuJ|PX@akpx%fP_E!1-bY2Y)N*RwmCqpshQgs~CM1 zpYyi_LX?9vU+|dWqxiss@q$M$%MqX6k}Co}mLGih-9LZ^dOS6+`Shx&fVxeLUtBsL z9DKp@|G)}%kIq*m`Y>+u19p$^H#|CDLD#n(cLMFKW$=JrD9{@u;PL-J=?l;1KLs#9 z@;8A_eevqe`O7fD15N#LC(sR<3?9cpi^oB;p-#{v9GnzDUh+8ZWC5i?t5-qlJfM8g za4U!pUH9h%UiRm4+zEUNp~rD2@KNI)$DJym>LFWvnqM_|Sia(K0__KXZR2Qpx5OM2 zEH@xGZ>CKEjdve&Wn?(!%EWNYm6_p~D+|LhS5}5&u51j)TtON5DCBm?YoM5Ji344( z*mAPO*3t5=Bfsz6&RZV;Pa(ILJeqB;FqEcxbhCR{ekf);#$e#_pZ)(q@SIBPC6CTS z^><%;qG`s|uL{-A+j?oUK?&1lg$@aHW3Ihs>b&5}akEswqg&hqkDKJkVeZIvJUvM9rgD^wv{Q0R`Ih&9H9*sM&V_+{p(!(YBwFfuTOz zBl(2~_%x4R8x2RWq8%WWnlC((KX~+t?tKa>t~w!GGCB`4zHa;t)@SUI{M(~DM}@qA0w7Ss3ml9f{he2Rpdo@19x*B$HQ}Hzz!w_gPZ$^=Hi4~!PH%a1 z9tQgcZ2Bvh>0r0;_pSs5^6{gfQWQ14HPmQ>76aunmVWi=Rs|I;pw2Uk3Z&-@JJ?`@K9xl|&_=skVC;A7uBpxZT|%P>(+gNDml$Ea|WK(^%|H9J5piV}E>0_99N z@Htx+nCEOMb%3&==)}1U4EvmApaqUcudTx)C>tE;V8Wx<_Defh^_uex4EvC;=0S|3 z=v@Y7O7POFpGXb#-4Kldmob_np!OGfe^VN{zo`t$Ezr}^THm7fH;?*sg2T+S*Y&?o z>kIx?LGWnvV`i^j7w!L^-|u=V9`)!oeS06$=X?+LhiB(;-)=SV>gisVv!E0QULKaj z2w4&KLxH~ubZQ~!*zZFg;ESR`2MKug)|~lo_|4PuKdA3nbN;`l)z_Yi;rU21CMywBWo4_yVhqOM-Z3Dlc-vPw>Ft-c* zf_{kgVQwGz1^GOhL3clc)`uNz0Id(Z-~qb-*|XQjgx#|@#2kF(GirYAiu~CT^|LGT zS4Y&ZuE^gVQNOz)|8zwC>5BZ@5%sq#@?S^Pzplvt9Z~C+lv46XM;w$oMkLqz z3!vl*8}@^bL-DkNjbC^HBe_lp1s_Fg`1Umiq`v=uwD~V*z2xT!nD8|RzdWQD+hEO5 zdJS@=ed#$+7X*CyHF!J%Qs0IIdxDM$1C1XtFmQm^7PNyHkWvsbU**`{&%(gL(0Y=; z6*NHX**%?ufrG)L@fYa4c>b1ojL7GcD|mKq7XV53+Ma*Fz_1gf#&HK|k{Y^C3o5@K zWDB$a_wDWnndsYj%JbkOF3|M9DK;>(L05afsKK| zxi?0b*}2z8n8~@fMwpRbo}qIW!>|AUJG&VE{QuuMi{an@|D8t7$5=q-aWF76A7*Jj z$kKeArTOTe(ksUs82*8dreR=k(_(f`8vZP=D-4F@Ha3dw=sU!;<9YUupcUpv@m(!_we}A-9)7=7Em#=HG^99;kCy zSrXa&tE5!$CFn#qknz6^_`ydHHvcl@Z#@Qfb{OMkL#WB1@llX@pc`zknpaX{)BLNF zzZEpH0CrO)R41amYq?$GjHdSu|F(n8KT1j?J$n5Z9k!Qv^n%857$Eu6q2+&x5dSty z{%uTc zRqdM@J8pmuZDct3@BjaY|8e6I9P%Al^o0KZ{~tO0A^mfAjs^>c5>Dt&q}S|FhDWcc z|1?Mm_8nG`B0BA0{{(yPfZYY-(fR2$v&a8K{QH*xlzt5QwRCXM0K7671H&@Z|*Q|yo zJv%RVp7?&lqxB^C?iqg1i;nyr2V7fE^7|k1==SI6WOVG3Zn<3o+B6z{2NV$COw@9l zf64(+%(yTxz{0N^bZBc5SPj+@4%qmv2k3r`PJ<1M(DNK&`az3%dPN^j0a=2>0C0JZ ztvv%e2@2fa0F9p;lhU41gtliqdRd~qdR;USZ5qkz*xEF80v^z@3y)qF2XMP43#nZL zYWITLH3uQH-Cw{NRHWXsH|7esZF3*gwh6iZ-_!C6f7>;XY$v!0lOVIRtLsobc#8R}wM!+c)zrfEyrxuOPQ?Iw69LR~Z=gp|x*p&R}of z%s&oEuaIr@@b-;P4cPdD$1&SC*wQbx+vBlUu%%r;P}&`Bk3;us46XL~yR+Z~<$DP^ zz21Zf27(09(reF2?CJIW5v=L8rV?zt;8D!=+BwCV@F{oIGE{oH>Q(S8;HIS*XN zKpS)WK@Dqc?PnfvV;SClHpkk2X2IQlZayUN|77XMy`YhO)W$Q5M{fwD0b0u$K0n@B zb)nPiL1)wlNVB>5kONAa`N8pq51>l~Ks)}3Xfr$DX)p7G+RHr9_A(1G?PXj#2)38+ zT!y!o5itOch6&*E3VHnns6zu9Lc-U7ssOEOM(aQQ#2NpW5%JH08UGDT4AA)ZY~By* zKQZt_x=lWy6+sVKJ$gktJ$nln`88M{h%hklYw*4lVE{EwA?+iN<1PZw0e=?($dLMR z7Xj#)yNf`;L3suSet{5y2>y@@{9zaQ1w#ZPJdU>rfYy$J$1aYy2!J+>LD((=6%Y+m z1VF73m>viZWEE%%kKwqB0Cw>4VE>OP=+z)pIUoV2xH7mRb zPilzB1}8O0e*&D|LLEbbA#;Y{^%2p?<5i$BTG**Z1lLCdLfUsssB0u_&qC@)$ocWG zH4@}=!G<1<+Ooc&OcJUZHcJP>hH!~h8g|DCZ0B#d{^oAI-gOVqb`a!XNq7O8Z+$;L_ z6mtDq2@(7V5=5(Cbq-;#U;Foh3NVcI6Ea2M`gP-8%=$IhrHjp_;{eMAaNp3Azg-`c zWP5o-KvXhIqX*-O{|`WY^$i9dy|SRQLr}xd@MOyY$R0fYZA|>zxWOY5hb>Q(JbPIO zniJ>^W89Dj)d?COfT+I%9>G9W4|2t9uq#B$qda`JKF@cJ8WK4?7&T97@47-Ccs+WaGxzom|WfuZ?F z34iMxP*1HljB!H=%rr#$g_{Rj%7)#%)DrXNA4ZVjlMP1j!4OFO)N-IChJPC)|2Eig z$c>UW5ND*8s(bXhF>Xrr=mp)I464#x7#LbEmFVzq6X4$_2|BUy|3S-JC2u@>ZHqxg z8hrRf4Ajf+4jL+CfDEUAE<*16_y0fW*z+s@|NkEjciPCiwUgWPIoySP6~*1GUH)u(cm< zf}5kz^_8H*m!UJEzO7GC=ev&hbb_ZyJ$qeL{`<5(;BP$#Dnk!GX7%cIQU34w{f?*N z5szNeKcH^ZC7({n^r>g(ao8fugAZ6say*)U$d}1@^!hOW_q06E-wtZddG`9S|M##w z&EF0>4A!IhFuPCZPmkt<>|Mb>I|6@p1^?;@{M8lwyCd*-SMZ;Xz&~BVe>(#Ib_M_I z2>jO-{J$gcf0uBFphxpz4#=Dj()vLo*!n?D@LVN){UCn}s2_$rUx~Da(9X9r4Q0;9 z<3Z=SgYQ`X9|JGF1)a7~@BqvQ?bH5#&+rnYea0`qBFrz~BMfezh=bZE;sPGchd`$n zls@)o{+YnvlnUDZ3SKcO4!Vg`7_EKcG=X2hYXQHY;{<*|&jtJfP8;|IybkaSI&R<> z^gO^X;B;4m6Z*dHEZ(8M)W? z0^|%${lmz$_il)wF-Q=t_Riadz4pGi6_fxmYVWu#aP9qhD@N@Nz0VDOew7=!y(&z~ zcqAjJ&OP{;1$BP4_YkDLiaNjQCg5@K0SkXiBvM256KEUiH&CtvH&h>kw-ki1fE%jU z!3|Y*$lxPrVYmlm@X@2U=t1Xq@ZK52+u$8GR-MPOjXQ$tX9DAm9?kzo#~U%{Q}rMx znf4w)PN9+z!HFP2v=n+~JN6W+zZsN5G3HbEq=Qpv;AV^z3hBS2^{1#ZUVa;Oy!_>U zY-to_yc~372Y(CU@$&!VkC*?)mTo}}W_bUIK>7vuu+lw7$IDUb2HU)y-~@IS)PVsl zb9xP0Umgh&ya*CROTRo@v8Uhs4Or9fpA@k16E|R_Uk1?OMD)a<{w-*#8b*VLX&6{Q zGpY;>AQ~nPqX(NjsD}u`V0VECP^${sP48TN_C1sf=fnI7qrvh>;X!KL zz|4Ws1kD30K)4U44@QHfk=z3lhtWe#9u#*V40bmb0_HCm4OW8We=r{pVX>A4Eb9)X z!JJWIGz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0q zLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$( zGz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!n zMniz6Apkivlz}0n7_#r5T+8YUA^ImlY4Dk?kH?bllGsQE{IVV3kTN5N%lv-Mxni8+6sbFiXprN6mQEFzQ2^CbZu~Eo& z&dGMlEGgDhu(LyOKsr;3OLXm0GK)$oBs0ZUwNziVR3Rs^xFkL?xzH9Ysi9GvS(OTRjRDw+NgxA?(F98p zldy_OlbnEGw&QFvmH+G_M3~1=t(9b`U>+6hocCprKKwsi|P6 zprHYBORNGUWNf1uK+K%f#NyQW;*$KL)OfIuQuI|*6u@SI_{FxWDbXNr#p=Tt45@jE zNja(UiFtYXC5a`O`FX_*u3#aBl*+us+{|PJBq<$*{F02+qVmk*RE3g^)JlcKqEv;v zeBJzlVm*f9(t?7b)Z*g!)WXulocQ9B#N_N^hG3|uLZU)ZVsffNQEEYcQHerknnHQ1 zdReMMVop(NVoIe#erZWTX^BE&9@qvHwdI*586fKviW75F6~N|V*p`@*0| z`9%szsd>p6xrs&DnR)4&aC1sBK>m);NlnZyW(a}=3Pel+ET)iHqL5mVSz-^fI3=~X zq$s~K9+X~EQ(#)aqNT~8h*QWRNGs%)mZVm|^@4d2r$epE%uCKMDoRZ*Q7A1= zOiu-Q2BIgmSRpYl1;R#-dbnA|ndy0nIq{`=#ffRDFlUry=I20C57-sOm3heu5QVxR zWhIpg8mW5edJ4ITIXU^s8k!2pi8(n6X+`mSzMBu zSE8T+HB3`Sp(r&yu_z@cwHO?HZ53KUStK+{%IYFd6#DmZ0< z5-ccvmVn%yo0wOrkXsB-xFz`t$sp$`C_&R9)ODI5pX8@y=A_0$!Wtfy1*t`u`6-#8 zh^zEpr4}LSfr}|5Cnjg47Aqj@gE%ujCo?y*BtAEZAt<#tGX)fp z5D5ja1Spt%oj@*3%*<6tEYb5!0~Y}WMfsqV1djjG+|*))Tu|sibn1Xq=?2($HpaF`Xl+>is^mJ(9QJR;RnU@YSuq-hry(lv;g~2&LucRnHr&ysp zBNbFSD+ECl`R9c}m1t-x6s4Ac%dC>3(o}`~B89ZXoZ?hHhKx*5Wl$`5t0J1}JJkDW#w&wJbBgv=|mqunY&zMMbH(skuq1MX4zY1*t^}5F_;z z6aw;#i!+mQQWeS)b4o$wOi`*rw1J+Ud90oS)IzXBYz-6=b3rv>F(^Wejl9uq(Nj=x zO-#;E$V;s#ff%Ncl3$vXlUfXl5~yZSK?I2?cyXYkP+9;o62&reNTNit(Zm;vg&`TK z3Mr{+iKRI(D>I7~j1)8sjVv(Sr>Vz~nI8`-1QC&wlUkOV19B5cIHM>(FS80>jqNi9lFEhxz^DvpPxECx@oB*^C}kSYr7y<%u3l9Qu=tPO5fUVdI?UU5lLX>Mv> zNoq=bZhlH>PHHiOCz2fs#TogfIVlSHc{!B|DXAr(S`kvulxL*o!SW)wvO+dX0cw^W zLvco8QEEzjK}k_Ok|P*GiV~BvVRckdYFcVhYF=`xLNX|6g9_iwJcXRhq-1SvP?-TW z09==qrzU2DOw(g1PEF3wONmcOO-un*?2twktkNydNCg$;pqv1%;6VikNL6YIs5pb^ zfz}hn3GYCP;8%US{u=a1qIb&4NWdkh=Z6`swoQE1{JDR6DSoHqum66v{I) zb5a#D@^ex^=?an;5^E4Fhg!3LzJD1efX6&IvS1ZocDCnuKV z7lBfAN`5&*ZfZ#)C~<<>i3J6zDGEqJ;Pj!PTA-_1pb2WVK$)Oe1+|(%u?p(JfwDoW zZ)&bnYPyCdB-B$StWaE9T#%ZVl9~bvEpUUN zv;c09o`N%|If~X8(Booo%P-9XS*4JYSOV!pX%u5R-%24jv$!}FtT45rAT_xpH3ib3 z1iLMxNY^g2I6kc?H5Js7fMy18D*zlNC13^MA~qgWVHC$F=B30#idaxYLi?K<8psMk zH4}=YB19J19#EzMclwJ`lTp+bgKDPa(xT$b{5)7ZgThTi15F0j*ToUj&K|DL-U^WX zXr-W949aXus>MnQ8sHqKqX4GBWlaz$Bwg~$^E6Tm@{==k6tcl-Ga#|3BsjAwRTJin zjFci>JFpUngTTH@E-flb%`1tA^aEi^^Gb7a3QCH=VF(HiJy44Yl!76n7f}76VF!4h z9n1I!SUae#scTn~QH0HGuoFNk42hEkDaCFo*a8L(4Y0W&SVI+* zOyhA$XQU<;D1gUlkV`dCw-nq11s8JQArzRGG&G8fKnWC-UNusRA)_$GRnTE8aIvqU zp_Nix5)Uc?VUYld-^`Q>1vQ0ix17ZE;L1FhDF&Jhpj73YlUQ8r2BC8 zO)NkNX=r4FM}d43(=$Pu!9_@cu3avK&j3yMs>N2I)(_aEqN2n~g@VMQ#N5=9)S_aA z{Ib-dw4D5MD@f}?K?_{CDrl%yr6_1As8*$Df=WbCftZvEY7i8q7K7VEpoRjdh6O8+ zFX2MA3)GX#Po{}2P`{@#XlOvABQ+&HH7_MzK^GQXsVVWW9H(GstDsQ~%4ML;1&tAK znc`U-kYAo!X`uaKsMS_bw1=V5(4UJ+@`3kB`t3bK8B)=pv zCm!UQ)D+NAsgVI_)G;|fH#a{oJ}oCPy;wt2*A66)=o_novs`d~T1ilGu@9)n>{^kW znwpZD0;-#m5km3Rq7@!!@WB^-@84*a4prN6Wl$x%fs^Fel0!sPrMTvQ(If+G? zC6%C(5?U8QvXX{IYF>(hwt}H1G3tX-i&KlrQiH*R2EO32pP&mO_REbj#q;h=|>SqI_`w0My-qj#Z>5 z7U+TEFc~~hssJi^Q&UqEpyO*fm3j(}PX0k5o__9nTnzA5Ii#PFUxX>5piz)fSqvIT zfi_$;8I(bTwpI!*E>>3H_MB&4W{C#45u>4znG&C#3aUXtO=Qq`I#`9KCN_g1EyEJf zh%acs99%8gfKm*yJ|xRvnbR{xA+Z=Vo~HnA^l)J~$O$~G?MPpyJdL1+a2ZQ0C%jWT9(^#2=(+Np!}x*E`q^bDAi&sP+Wm@ zrxrzn%*#&$o0VDw?&ie8S{v#y2I`uc3<@DdrFqGTC8;S4oT|lKoSeF#;zz?7(m+)R z1C6eM8VjnRZUTq_4IfbHj>Luc64Y(gLG1vLG_n{&DQJu&H!}}plR|MxQD$B`16)CI zDyaEUl3xTGO-#+tVF0y$K#c`(5ejLJ>oI_=1DR`+np;p(X~%#lNI_w#kY50rxPXq~ zfZB^zklI)QR9t9iKc1RAVx1KConsmYL7T9VJ8$Kc}X<{0V|!cd%;mz-b5prHY( z)@?wONucHgq>l(|;brC}=ai|P4=T~qGs~cfhXJZOJ~J&owIZ{)q?kB; z3L2Sd3Yp-ko8ppUO$PXQHGG`B6f$=P8f^mg<>3m7AR}3j3R=CdIg`~{9#G*=&INV&wkP4*hUaX)2Hyz?8@Q7U! zsNM#Rd8H}j`?07NsSYB<4_J5!e7o zPQ&y@E-1c|DKQ>mf<9=hL5~44s~4Y{pInlI7!+k5IC=~@ z`RU*oX9x#RP37dLgJ&0%VB&fOnJG$o3ZP+r@T^^84rFElGBKzGsT-8Q?gnvEi;AGC zVUq%x#R_lf|0g@E@TP~BBBY)i>Y~K4B^n}tCD<$qSV~{GU$*h zydVS*z`I2HxWs$<1-k}?#QS(U1vv(Jx(0)sn^=~gnW9htYNqC;gGyk~3?^tkq9`>_ zPr(H`bCX%DP*PNys>c9nenY3G?K~vJ8SygGj?mRj@YbJWYIVVgYor9OPbb z*Q&S}I`N{An^*wKKt-tvpn;_PBG8DZ1}F_en(JVLAPEu71l72e3i+Ubf(9haJWz}k z>nMQc$RH}g6JHA80tMnOO+5y1Jja9O(-@pVWxWD~qmWpX4xU~rhL?85sp(~islVjX z;*$Jaa8;^atPt$!9_;EK21_9dP#1$otBX?8L8}akKs8Y+Oa;UXFe%WW1xyA~Qsm_1 zmxC&rB2YGfw*DcWf$2dp4y*|>GFDm)T1)_1gaJxGpebgB%o0sK1z4e7oSB|fT8zgd zPNBhYw+v!`Bqrq-mEiG)qf=1GQ1C}_W_o5$4jzwq`uGeHf0Ps@7U1znNRVT|5b;S` zK`I`PxCOWlYJY&Lfbw`yK@blrwBn)l3WG~(K~XBWkEsXhZh{IUq zn^js2S|XAI?!uHnm;Hg;d7yEq#2knjnR)5(x*RsNhFIPO6M@#bnfZC3Q2@w_#}qw= zI8hmV>G>xGmsOcTl?vG8)N{oS&0l#NZ4f zGpkae?ZRR!1&zd<^2EyGnmo|DrW#P!7u3Q_O;1d&j4uG0mY4!+E~h|OZh|Hn3&5)^ z!OMrB%Q$l~lZq0HK=p4%>wqFF~FQ2{jOon8c*H-rwx zf+DfFAhA3Tbr!cgBQrSzwA=}?1`agNPz<&Jw4f4P2SF-gShFKD4eUP1Xme&UXmSU% z9+06pKdl7Ssh|;gut`w0c?!O?aVpsVpfn1#2<|A*l!!ucX%ci*By=ICK4^_ka$*i> z@fmmpTw-Pps4-gvo-tAI3-$3)&`3!IO?rc(3c9WqvbY4Y>p(y*2iXG7!H`Z(Nk(EGk`F*# z&WdKprwMIX$pw6kPB9TmIzud44U2tWm@n`K&bzrlOzfn z`9%uQ#&sIZIhdY?bOtm*87i?L9=d3f!L0{%&=?3( zi@zupvIx8+KR&-0vK*-lG!InF;162f1PK~YpTW#T7t}ig`wBEO366Sj$y)+0B|x1C zh*=7yd7vfvuBw)b-E=bA}a}+c{Yfv+Daxx*S znTj>_6#P=t6G7{2VSQ{+H&Y=cA8c4+NeO5G3e=i~dIrO0JuZgi#5_>71q!ERP&c6% zv^J_F7gT*f>mY2#C8j9ogR-A~Zel^PK4`&EuAYK#esM`oC8$t=E!l<@AMoCCu^vM* zXpS{8Jr!gFIGA7p3YmFn`9-_#=$pkF`&o8RfV@NB_$pM%1p!NI31&PV2@M%s3ko`HS zC8^+nI?!5Yu)H;B!6IzzBRjPyFEs~LKPG}YipECZq*aiUSON-}Vo0cfa%NI0d}K2P zx+EIZcLOcm2jx#_Uk|o08d(Yy5}7SZ(dZITml;P0*81BB+DRHplM{3rl)Gc8ZMc65T}8LG4&8*(easipt0Ea zG|+%#F*ML2Vkxj;wM_6D<>YMeqAB!51Rg?xkF&;?fihoZPAb$SkZqv#W#H5d?(T74&rZz)O`N2c zWPrS102*@2EKAjau0jQOy+L(KBJv2aLSjyFKBQX?+E!Pk zh@dMA!Hdtp&0=V@=qUuJBC=2ssLX>#5oBZ{wMZ`m(g4ax1<|>nbc$$;=_!O3rz$`v zO+W=~dTI%LRWm57CYIb2sXkQ4(h0rE4C>lV6XOM{jNV^Q=B~ZQw)gtAP z^^l+;Z;*Zkuzo!S22cbfm&AjpymZK@7OaU589ajoJ47Bam;x$IK!s;PYEe$50;nq0 zElDkcPDdfNQj1H9ic5+>jsus<;BEtS#HG9lG>lqQ36Q*e0;cOzUmq-zOQ1)2!SD=vY~On|3hG&Ip010aoHqo89a7~4b(l8YH! zQeicEszNSkGfP2EDpWnR2+Yh&&q-A%&Mz%W2DQ?lb$@1_0?Lj&NPi798Ih`>0qTl@ zCm6sR3ReCZ?n^fckpzpiXprYHn!` zDAVNSL$@V@W}iY_gF_Vj{d^+9YYIUH5GW(SdZf9D1(2)*T1^4b4$oLA3QC}@?@FMB zL5annO)lVty@sIWTaaz#u+?pbpm7o#8wCv$1JITR(Do?EY!-N*Xc{OuauZ96trS!> zq78H{W3@ExHL7ZIay0F$Q*=soDs&=htrb)YtQAzFbz>1qV)SCPH0_J66;zYCKpSB} zEltoOBWSZ)!A`+|K|@1PLjyF_n+aNn4_aw!pionzkdvBL5}#FCTms&`stH<&s+C+? z1X@a?UaXF?wo@@9u`D&dJTs*v1B*`hu78llpcPRd8niZtK|>=aH7~s+1Gc&cwC)MI zjtZ&Y7Y|yUTpXWQnhRD3TdN2PB50>Eq_Q9tv?2(!)Cd$cpd^fBKry(70qQ-1)**ou zLDnY0V-iy>Xdx14K^AC;p&+rS7`**o5ps9|ssUhG@a!YhF~uN#nV@)8(9l3OIUc@* z9kfulBoS0F+S0HEdlL+1udY{(7>S+oCYE0YidHbZv}y;9g8X%KpSMNAR}v_yr^2LP@D-WA`|mc z^GiWvtBE<8WvL43u$@TYA?;M?5@8*M6wo?bPzaQOcMyPG30*l4*&G83M2+mwyzIRE z@;u0449L47Kx^e7!`Yz26+oNAl1nOd?O?72g$Js?JR!$AfR;OhmVcL}f=BQZQ$X4w zszFAA9gQRdG8nw%5VWW)4>WQPT4(~&!=RyIpkR*@E6(8Ej42B6Ek@v|fW{Rp;6eUH zxD&kU%>^76pbjHw2ob!547BMO;yo^~60iKsJe&$ZE8{a!Jp|hbqoGj*+2M=iC*<8F z1Og4}BXFQ0Cla_gB;?Tiq@jT-08xaj-z7B>lJd|Lf+HPSA#$t{Qj2CNs3j5)jyrHV zh7_fsU2Whc5afa1>Uv^(gw=e;N3!yoLp2ApOK%R9S;f+@REJdJ_dvcVihl> zg$y58D?(c4m6`%x#t+{2qM)Iglar#O03tQHpgZvt6u{e=3=GYxDs&AhRKW~Q(0&l; zW_Hj{}O zT~&%gX@`L9HkUR6)WM zXuMyrduoYmURh>Qeja=)ergJMdPGkl06bo=keisDs!&{7l&TOP4{A)tgW3+DMlbv@ z0LY@0oXn))%HopLT(E-7MDSS%8k%|_Kc(iCfwm1JyDSxAEwT_OKY&(%`hcrnP>Kd+ zgrw3mP`dz})WOTgLG>-%4;mU;8ven-1(|uEh3;CKYWW3;g{6?AW)jok6(qE<2Y1N8 z3r|ama#Hg&%2JDpK|uoA$D?5kwn7VZ2oBhIbv@9UX3z+-UVbrjz#qKU8nm4StOAnD z!HcLBKt(nv|K_J@gryc02ZOfWX)-uNwqAfnvq}<+v%w?sdJ3+fb2C8OX}B2NGV@Yg zAQPdG%_6~|;}~=lz(d*K`5pyZ1=RvB28gTzXetS`m^>}BL`MNU(NkO!pPpC{59z>w z)aodJ3X1&XD7k{6CbGu7!(+aEEtL`8Hx-I7>W!H z8Hx;z7>W#y8Hx-|7>W!{8EjMyj3SV+E{ubR0aF5_?HB@}=Y-^fj~4*-sI9mdz#C6N zC2my(c!9oZv8Dp35$c);UR{S!3l7tw)M7}33A~U|OH&uLy%{WGpb4AbONH%dK-pIY zU+9_&3Yw}4l>KFiCGdG0Q2N%;K-y7OnwOhcpag2%8z2`DD4V%JnGKY8p=BUwpck|( zL;-YC19?_KIERhAzCTOTaYeY~PU#e*Zst$BOg9v%~kPMF4%c)VEnhq+@^-}Xd%@LQ<+yZFq z_<|P`LJo9+%(Z|bN+B&Dw1N(_2ZIy5mmRdHf&m&wpz#yXlovv|9v4GExC?_@fGdNi zj}HTA=@S2M~7@)nNp2eYg;CdnzyvrRN zDBz045psN0FsK;7sR$Zgpdt{|rG*q1S_;q(rJ;!?v>O2G1E+#c4a&<0m$fi`pkf}x zjt7f^meM0O;e!j>qEv9nT~L%-5}%w{Tw()?E;|j-q)EIcR4qs|{Ja80R|<4U2zVD` zUOr_1Vt8UExWoX@wWNXu^1%n`Ky`rjJ3>@~(>|m;fwl`l%M3uhK2X!R!on=x%mk$X z!Kv0U$QO@7&`<=(R1_tk)h*zqkQzyuphON11yFSpT%MT*I_IS*6Ev8>0O2NrPn801 zs%KCIpVOpT0Gb7bEUyM{7-9&39gG8x1OykA z;O;kgKPGtOCqGXCoT)%(V!-90TObrv3#_0smA0w{;FBe6A!Sstf-d;1igq35xlkqXxta?43faD?C5aG)psWYW97qPCsBuos$pPmJ z&tixs-_%?UNO@HNN*d7e4^)An%WD)s^9I6c&UqyuCqPt!jD~DQLX@(4diq5rIr`v( zpCEhKGZ-{962a$_fsZqR9bBTJ2069|bR=PEW)Y~Vr3o5G0iOfN0NO5F0yP!f_(C=p zd>#SF*iuA~$vw5ir#MNYG&4m<0aRjuwt*^Y6dUMy7CVA1*8mUp6dNK5AbB6!jf1Vp zw?d44lX1}_P^ zBPX-C1Z=e;Xl+y_IB-F+VxS2-vH^Ue6=?Sucmf18o}gX~OR(Sr-(Uw8LA{i!kOPfum~TMEF09{>n^+K^l$x#s zUSI%j1jQqjP{=C55f9IY_!Pn0Q>aFP+T`$aiom^BsO8{{fFcVnkwCJLW+$>U3UE3V zdD}iH8)cN{WrLCf(up7778xj7q0yFK1X^3?8bHm}0lS{|RASdf^USyBmd82s2GkTswY z4RADpI?D)EkfqIei8-J&8wOrSN4V4hpD+NC(2RLL=y1NG5=GF#X{srsLP0nDNj zBdClKv`#h9L>fUrj9O}fCpW=|GQrP0Q7r}?g##VdL{R{4S%4A~^1vs!tW^Uk2TftZ zPaJ?53|eFfKDnp_RyKjoCW0M;gXA$)(D+4aQ4yqLuL)|g!RON;Cvih3t&rM$s)z%S zKw}@JTB=p0ntBQ@py?<*EJskK7v-0O8h@bL3e;tSmZqvzV4d&~fW-+U2Y}XdCV_Ut z=YzL3SV7OXGGNHdX8_N_F&HvbrWP}R=GI|>jA=qkAMtg09&E}wgq%VJ-njJ z4oOS`wc|83N5pyk)b^xGJPX*!)SVDI3rZJ4=}IVF52ah7bPtrC45ep6>Dbi}bMm2d zB9tzH(veUa#?OZG)1Y(+*fk6c5l}h+jgCR%`#|{~Q2PJ>|Nryy^HRYx<6r_bB?OgZ zU|_IP$V)8-?K=jY1D^@n{Qz2>3p%X>e735N0(k9GW?s4;7X!G-zyO)HVu0i*2G9bh z)RcJ8*7o?E%p~}kO$_>_#YOr#nMwL7l{qO8`xx067?_wKY#0d&9T;Y1U|;~T*%%lY z*kKA7Aq;ay1_mx37Bt-q3;|G)Z@A<^1~M=(sBtkcFh~eMRYS}Kkqvwxl7Yb-LP1qS zI3Q9%07Nn{9LHh)2SKPj$k8Hv80H&DLgYgs6o&Z|pzzW|k=hQt32st}C{ka)t-|3D2QF9Wh461@-s7^x3o zd=mn>j|;jetm2Y6co<0nmA^KxL@q@+w37!!7B!2AnD?~!%zk=dPLIlHo z4#g08T<-e-mB;12f)a@SA_#>MejlLnAc|9j4a5F|Qiw(`Q20w=hTnxUh&(9$aq(d4 zHzww%Z!hsRKADZ#Y8?@q=FKC0vUj>_&%nU287z-kz8=^K(XRrb zFyi+E0eOX85RKXp3PXPY0r>`~{Bj)n4R%8$Bp@-5Y5rb_{8!NI5cvR*{aEt1!3~If0l0j^bicqIhaB#*^?AMQgWCO{}qC_z|Ia>4@$!yiOpF@M4%kOTvREri0*zu_@N;u((c+3*Y^ zzYRiR=udb7kthen4;J@7_ym!c1vS1TG(f2YA^;^7enJ?AAPS576QJ^ua-jT;nLZAP zLmUpuhS=(#1riYX0&w|+*}fBygvc|1C<$mT0=Wf>1*AX{3=GFXd=?oD_dkHj=Yiz0 z_&-1zqJJeQe6Zvn1~rKMS{(8l3?TAh;PMUA{{l7;`A8h{1?~{}Qm{N`{`(LFk*~rb zUl0e8FUKMOArm5BgG0UmRPiw|FdPKSW9Bc1Mu`4hIOG+2A@Yw{vA4ejCPU;^K?88?*~>5?mj?RQ1Su+d4+`#{m^DC zhW!Bq^sC*QT@_EBDi2giK`Hn4ru7b#)z#*@&4kE7sqOkZsU_D5J zfx#18zG3!%7HomYf574X1zREV&}@hiJ`CIO%O~uB$oGQG$Kt;aP-87LGWE`gE) z#~|iI$6qk)KLC|CW&-t(Fw1|2lMwyaK@^t$+k;ae2?hpGHw#<)B;hnf9z2?dC4MGA zax3`Alwj{NiC0!028j`ID$9f-U$SRT`V0xux)f}EiGpB*Fo3_e2S=R#Zt zA)#RlqAq-e$O}R!4EYbBfgJ`0hGihdSn|(;?+}d}amXk9fXHj$ke>jR2e)sqnEwGP zKZ${Xfr$gt{}X;f%zpwJu)@-Qn7{}L5<5@=mB1{2K5#?iZ6U^B_}_pRBF}@v{SHw1 z9XR9_pjG-FkTDXN?TZJ{E?XWr{X-Q)%mR}EVjztS4EsP77XJxIf+QFij6ms20*iiV zlS~I>8kY3i0F{T1TVnYC0#tq*$Qmr}pCAvCU|@g_F=FUvP=Ls1fb7Q-zXb&3A3)^~ zf+7Hm|2F7C%y+?IK7$@a-VBGl15`c}hx`VpJTCVu=tIm04KrYCUvGfQ9|S4G7Jfz` z2?mC(IP7l#6>Olk4UY6V!33iJ9RsNR!yF%(U<#49!eRae0`daTA{kfzuK`?fF)(O? z(=TTF-e3o@Uk98%G4t;OM~J)(4tWJvh&(9zvDF_2PD$y?+ZQSH5+aXle&PXC9#{V+pbDxV zWIq=FG1Nfhap^CB%5#DAV{v~&Eq?tUpz_dR2#oaMP!G{B2%#|K6B;2BpK$bF5}G0M zNjSp)15_SY{io0Z(eH{w{|2c1OC0hGS|R#hfm|*Dt*jtw!Q_N4h&-A@Z(_p!T^Ogaa}QiXW_k2pxj( zLAeCNf|3GjAo5p06qfS&!#a=z0|R)N9Eap9!%KLtbGcMBWmI zd;?VeB_pW*!E9e`*bLFH38JvL@4;4(1Oo$Tn3anMv;D)c9U>2^zp$l`13Mt{&}ldf z_dD!_$b-iRu-IR)3nFiT!+#5)@}Tx369;De9@q`h{~x3uOZ*%FcWf9KK4-B z!y?~s0U{3_Mg*w>xde_4Ej%vA?{FI;p9`X})V~|< zf+QFiaQTnn9z>oOT)$(sUj-gQ3a1l?RRdV++56PZ0g!^ou2a6+T1cAA{x(u*eJifym<;|F{5^2bB-l`fmk)A^P8d zBn2?TKj9xleiJBtVd?)XFn|JXSRwMtApKa(ci@1?vw?AQhr>uih&(v{u%tf+s61%>1jq`QHW+;YJTS(<0B-+d z(a&HEF&`8>*z^lP<-I}ii$#Be2}D1x_SpfbJg)xL0aJ*6T=O3R<`8-C`~{Z!_W@Ks z4dP*p@C&ej=syH)#aIAo9>&T1ttrcKoSfLp!x}$`5&P2&}mvw zD1-IEiB^dI%OC+P>(f3!<#F|I651g8LE~@O;wPaUA|C=OKe2?*fewiLYaI3Kfli1# zczy^=|HYvjA`e>rj?Mo8P6Sn!22T*xX`-PhaGyEBPA@hVatCDpz?=7`43C`vtS)We-9{qVY7cD zL|z_5VbQO!1th`1Z~^2$Ec!n{<>f#zD*>I%hNuOT0y`o4jX>_hqCa34M1BuQ9$WnE zfyjRZxgVSSeu(^Lux*&*8yBGR9$@!jjxQ@5f#}b`F@7=OC`3LTEHYJcLP?tlf3s8A}@cJ{%{>g*e5d9lL;fp1I zeYgve$F)Ax;2uOCod2-sH@FXx2d}TfB3}TN2hZ^c8g7;l9FfcGy1u-yI2rvrpuyagcWMBZT zHwNJbw%?#Fq@du1BseGuk^}W=3-HK;+I$IkXKsUJT#!AWsoDY|h<@mPU9dfl z5ce{JmMVbU3z`z@fT{z<0mvE{2AT7PiGksSFvJ|tzFx2#ntM$^alp*LP#_9b2O8f1 zDTJtlxYv=-z=f}%nXQMl7aUk1Jq!#CAY(dy!0JE-f#g9|w}LFh9?19s0|P@4A9%+yXguW(GXsMG zR35rN6&zkpd=gH43XXglj(i5qtUX|-gW`vWg@IuMR6TgVFvuco@iPH4en9T=0o6`w z5cj~!6_CF`#(?~tgCq}akHOr7lHR7UFfdf8L(BmU+k*7NFvwq9SQr>Gpz_dhSC~0i z{q=-}fnkOQ#60LeWN7{K8MauZA*ynh-bht2#2*wfP-HUoD@q~uf-^fvKNN$) z5 z3W$3^`@})oLHQn@zrf{W0;rsXm*}8yuHj%{_)rPa2iiXl)91)10dgd`=m+^{2?qm1 zMioRIXdgLD9mIS`J`ESXfM#eYgTm(u2LrR3=9c15OvV~=HPM(R<4864aj{ZoD2*%pz6@e zH;_3~I2jmDK;@y^^T6gH*UKP(?BQf!P^g302c2I+QU?k`aM2ESE=c_wP6mbrM5+h5 zQ-+IyL7^UEK6HKpY!-+B#k&m`1A_om9=yLDBmoacCvg4Z!sh^rca-|Ego}ZJqXDBf4|vRd!^Obx04h(4dsVm@7;ZE|+>0Jxp#0;)&A@O1Di7X=4+;lt z`3FmW2E|JYHv>aPGsJw*K7EjOMEU|HZq#_(!p*>7(E?Eqop(km_rdug0hS*?=05?c zZ-uA_?c)cV4|gA`dQiNJ@Gvk)v_aHE_mzRQfC!L(O?Vg>G@$a}eg7Z{xOwpU6l*&U zq`w4Y{$z;x;Bx^;&<}Fo7LfjV5d9!NNIMLJ%)f#p4?b4_BuRq%M0gn(I#xi;2cJ8D zOMgK#dNUQ=ZwldMVBpvc(GSYcAngq9kaii!y(PR13=(+cr|>c`Xh7wm>vkC!{1E!L z@G>x1;E)H!_Z40S1`nt_^jrd1xqwl=f!xEw$G~s`svf>V%@JXr3P^q{#6Qq;3c%?N z=q!C+uV96gK{Y&^57;fx7(p=$ za^D}2`R5?=;Qciq3y5?dDBf*AjgLzZ{rMohNEnpvV+0r&0-*As^BKU>kZ?n3@3#mr zFs!%?F$a1a23RSG0GYEyfPul|3Pc_}4hNFJV$KWHyKivi}Uo{kI_UpmYNghhdQX8zBY;1E@TBybUJF z09l{KBh0|y0F{THr-8TJv=L@txByk3fMgbk39>Inn1MmyHpD%U<%=L02nNa52s1D+ zK;@ywL_s8>{iiv?3=9cSdFc5aM28nByzdAzFf4cqu^)WC2gr2H{O!(nfC;1E1i4Q} zgn^;q6+}Pu7!8mKU<{JC0m;9H$V1o1f!zly_hUpD7#2X~!RLd3bYj{MYT#hhqo8_h zjtB$80nR_*@kh}4At3F@?IPrU49GoaL>L$XxFG7qz={zBC_TJEl85fMXJGIFk3Yf7 zBT%@Bh%zwDfSLnccMSFyS~_*-JAm151=$lK%D@o84RHtfToRBo9Qg#?`5rKW!Un_z zxwl4?fq{Vsq7HgK3D_QxJjfk$L>U+Ypz`4JNk9@rh95}(9Z?2`17Z;K!RMEds9#2m zfx$o#q91&|35oh+#26R?bRhb{=bw7!p+hG5TF)(a!g6IdI zpF*O38F2=N555rn;PX{T)E^_xz+eyw(GNax#2FY0QXu-l=d<9_kE8u?2Q+9> z0MQRVzl8+-p!6vt!NAZ^4bcxe{tl!ahC%7v21y=t{tH+RtzHJjLy80ggGVF89Pl|X zAcfe{u?I#m!~iM>mPjx#Sad@4L(hr9SuTUzbwz@Kp`#a~9(kO{kx#;%?*d~pXrLJ6 zzdsTT3=g2{u#K7z$0%X$-r;`k9>?I1H%S9@->nS3=5$0ko7Z=_6jI?K<=A^ zWIs0fJ)lVGgZLA?J`<$T3sGO+kz`;Hz#$I`r$3Sm3<^+r@cIpqezf=lxkE*YfguB` z4!zw0GRH-Vfgu7a4_#*rF2`Ww9@QW zS%ah>x?T^a9o+9agQOpu{2M6-h6bqlAp5|Yk@`72(g=C*d?-i(Qu|3q8sUEQZ~&R- zBaLuBHvKu$3=A8f_Jf*wAmc&pc@PcK-$Out4U#-4>OuNo7^MFU0r@vb^5FA&K$?;K z#{)8?ACjKX{RfI?9T^6O4^a1m&hr6jN7ToVK}C=eAu(L@k!4_Lm=3WAynhvB2{b%G{)~}jV3;ri zA`d=)2r7@}PZvHM^C@#=85kDKh3E&b&xh&>gfZUHZjt)}SBFDhMu@IsT-Y!E^ z2lDS4IR=IRs5*52g3LK1$H3qKm4}{}gf-s2$T2XyfU3jRE*Ft!V7LL5hmU_j%L$M@ zCh`dV&~ufr+7lzsz#y;~;xFhi72xoP#b1p)1B1a*h&*~a1o?N4JOhIQR30>!4hlZx z@?wuX149B-9$i1kop5w4+l^>exks@FaxR|e9jZdWti;`cfJkG7!43mII1WzFm$Yj_z!vx z6xe;R@&H!9`6x0l9Du6BRxafzGB9j_%A==WkUx4985kBooUF34`prf+R1CBnM)G(!&=ddFZ)VsNn<|SHoHVm?$$ayx0t}AG$6J zWHcCq><>|9V361Xkw>qmLH3s*$%D_`0_ns|kD#Rm82w_9{w>N33@i3S%m<&#g-bt{ z@l;TJe^F*&*l`M?AAD{XcKs-M0c5X^3IoG}%Mg9g^Sp=-H<11uP@=g3(GNZEizNMP zR2Uc@K=nh<10zZQ8x;nIfSVBeq34AWtsfMxI;so|7ohsV>%BnX<_#{!!0k^TRR)F! zPowoaDdkbugA&n?4cK8|)v2uS}Mi22yYVM>tX zq351~^E<3Og|)Bds4*}YyoHzpZ_h)^eNefvM~#6&0V)sPp8#?vyxc-v-vaXY8#M-o z4N&#yw5Df+fiQf=&z~{Ds)L{z;Ea3>UXNm>`!;HTW{m^sWFwzG| z-5!v8q3WRLqhVF|M1z4r;~&I4TPykg2KJN{eyK#h{52$kE{tF(jgq{Zn z4u6m_pzzJnWMD9W%0thCgUf@$yGN6OApj~5Jr52n52?Rl=^0XWgZ;0`z%T)-9+$sB z=04G6V7LKQ2RbJX%tz7#J*gApQWK8wb)rWc-2r8KT9&aDoq_AHAId zk}uI>VAuhbhpyWP`x9ghNPdbI149HqL_fB6(iSZS1`nt_w*K7}ko%$X==OvB_eG0= zK?5q!1yg|OKdkjXsQxt3W?=XM)ekzi1mtc|K7qs&WZeU(y#$FVuq?QK$kAqC*dT!2 zU!eHx(Pm&+0F{THmxnbyZ_#F8*g-%Y$e(w#85k}=)sZ^C2huMCN<1PE_kz#Y19=5A zoN$(hF**zkA0#09!RPPc(vPD&o1??P@IV@(AACL^3Hm|l=#CBp!vQ&net5qEWCnDd z<{upfh7C}8Z0Sfwmw{mcR35$l0mYY%E(5~^s64*%Fh!SvVFy$l_#8lx8?c2VmT&;2 zwgX{rIH*F@gU=HLsVCAOpzz88>DPehhtEG^sXwOZF)*Cags6j_ zI|wcx;Q0$r`y7;Rujnx_cxXfPgU=<3jjVBLO@b|xrZuYk;l%7e~L1j|F>75n->0|tf)2Z(vla}3xa;1H%ufI?%a`UBDD?m&or2o#82vaPNQ?wsMKk~c*$UczybBq`m0-*9MVHpiM9pDLHkok9v7#I%t zV>cfZE`N*|7z6?!^6+*5#GhEl9dwKt7(PJNqq`Smo{upDgF_(1Jm`6oIKvs_z8Yf& z27@4odiXda$n((k2y;N@LFJ+6Q{pra6mMrh=7m7a1D#h1HVWb&c)Wq^{bJ0(z!3&f z2R*kEY%WMWNM6K*fgu7akKRuL$(ta_gZvHB2TJ##Obl{IhzSEj22?-vTuY2}4Kk<3 zgn?lKR2_W13D_{mdXqUO3=A8f@}Tnz!BWuvA1Hn7F=1e62#5FseEua!0cQGe=WD>e zzTuAv1A{>fL_fB5b~2_63=U9vZ0%4RQ-pqydqCF1Fo+*x%D@l+)ek;j6C{c0KCI;f zNdFvD28Ijq5ck2?DHEw5RIc3t=}&;@2cORgvLBKjaF&Olco8vUV9-c}=$j4FgM>ly zCT0u_D{#nz;~%6y38Ei#?k89~q@D-)72Hn*nNwrNz_0pBjQ`7-7V3?DKf=7Y}< zh3W^TbCA4^IRk@1HbfpiZjLk_6l2c7Pym%jUbhI-Ut`X|;E)H=4`0^?^&co4=a@4v z1VH6M=ZAu9Y@R=7*^y%%z?KB*jXzNix>Ub;| z7#a#7=D^n*LedMo`~aylv0z}xD1xYi=SwtopmHI`f`P%H7@`hzz5&?%@brsX?|}T# zW5K|{Py$g8FAtE`pRKWAU{HX{W1F`*W5K{60F}o!{{9BZd~Eu8EEyO+K;4T?zm6pX z!vm;1HvK-93=9{b@}T4N!2X32Aphl9GB6x~%ER}CLCZ5xxb|2g+z&c06|5C4TtVh+ zv1DNIfcg`9t{u4ihNY`3mJAFhpzw(ULK;i^FZdRScCSTK+FZ70}Ij!&8ML7aIt1!kf?^pL(hQ)#|NaGK~3kNa;e0c zfuRDb9(pb;l6u1HP`6k!Fx-IZhu2#mH$nS-SF9NrUO?rc=gKlLWPpPSJPz^2nt_3% z2I5}y@mWwfiP#|ILFdkbjfUr2M1K>~Vg$>A&GoTiU^q|i1H9rwV7=1CP9j9cX_E zL_c~wfzpSG9Rq^~R6qD!UXbAg@)5}WId%*TAE5f+0HvcX4h#$)T@d$!&JX~* z4U!K)=?I<=?l>?oEP$$mp1%YxXJPsEj{^h42BItK}iQ}57ZqXc^gLt zh67Oj=<|6X`4}X5`20B75XgG-8b<~Og>HyHpy%^|%NOs zKj^$?koAc28`7QyxpRsW1B1nMh&nv$ud(JEkUdwN7#My)^+V5v28S#9{Nf)c28IVS zAoiRCI|f03;!nnzfnmZ-h&=R~ZMXuEybY2(dOZqqM+}lY^n6PUcYw;J7H0;A9Z-9q z=TL*yLBbU^9e~W;;>^Hs1F9ZgjzRK0DE)&gL6H0II5RLjm<4e^djAMy&L3w6h6_-6 zDlQBR8M7hgK+mxTyAL@$LH_V@VPJ5W15pP$&l((9aCd>KD6rGO!k~Dr zabaLcmMTbaoK}qJ`$u~ z#g&1fV-dt2@HyGo^}F+Jz&_59;>y5qV*^A#yc}Ti-~(Mv35ur{R|W=)jSzWwIfB$L zSb`)EI!7C1J$k+YnRCXKfk9z2#2k6BA_M`Fe}g2CTpof{f#iAI7#Iwo`a$6f5{F@s zyp9_Kg9B6^zP|{n02EF>ZVU_sPv%?hFhMpz6Wre}nuAcMrV0 z!@5of6kajz3=9eTA@;%N5pp5zIgosfI|IW6s62eV2vYqr$DM&;15_S*%_YbMU=ZAx2u(=OQx(3DXA9n_Z1&1K|LFbEuv|~$GDjp0B9fu+6pw~Hrm4XP6 zKU_Q*7(9+ZbI?5OEYD4?QOnqymgV`dd607&4&p^T47A0wll0gMr}% zR34tsp-MpVM?4r9B#uGM2cL5el0&lpi3bA%$4Q7hyxk5`1MM%dcrq|}K;_}%l~8$5 zJ4?lrfuRB_4?ZUyBv%jKHw0;CLE3RB>!m>Mit%J%cyJzKZvaRS5(cHm8czlWfeR3M z(D~|M>3EpAj(i%h!&#v2T;s{WFyR_RJ@nd2uoe&jGVhEh1B1a0h&=Q>cBK4=ntwp) z=MQM{+Fgix@cHZ@gRrF^9P1ryycif9oI%lpyp#cr%MG%9@{#67heVjjt>y`!RPTn zkpRuNDZUI09#DCBKLRQbDqmWB85lC4^2qDtA@vfXzl%Ko2=ezHUj~K)P<_zz_Zb+N zJi!SKWbPeb1_ptT5O;yk-v`+VX^%n5E$I0)$mW95g@_*m!-`K3eb96Hv8D?fKL&;m zpCRht{cUKw1?0XMKL&;ePp#UlmE9RimVE?W`(vR+6P<)^9XJ80`>IdIf0Md*W-=HQA z(r^HHe3m7Efx+W9#GlCLX`z>EIsps}4Syi&(EAf0|M>(kFcd)L;pfpHrH33)CHNP+ zeo(sW31DFO0M!q@4*?_Hf#P*b00YB{e-Lxv3y zw0;w!4tzc+$U^XX7z0pJ0P(=_x+Iu^A%h2^4!-{dEDIS|K0-kL2?2SQ5d7w=AjyN= z4YnF7UR^>M7%HId1LaS!JX*Mb(nn4R1H%NUI{0`SQu)vm!obh~l?UH<0Wt_`4@m!- z5C#STUPw5=f*+&=ghBFWLKqkr@W{UjVPNT2GmTF)(C6 z<*}I`5(Zko3$Y(PocInd<-(jC7glb z22>q<-Uh4~l0Q?z85mwb<*~JsT9EW(i;pGY3=Air`mxC$31?u~0hPyQ{*!P9h80kG zxIdBd9ZLiQ!wfv~DiI6}9Z-2}_PazdFjU}?Pl;e)$biaYb6-mY149HJ`6Uqy3?6vo zk3=vqSU~0B=b*ZShu6U6=Mw_@St1eovAItrl7T@3YCcx~M=~%-K;^ONPl;q;;DE|w z)87)w!0-c_o}u@QfZGG0Bm_!dOOWKT=|2+5!0-a9A6q;7NhBh_U~?Z!6a&KvsD5nb zt3)v{?7$=M62-u<0*5>(zo$eoFwB6;gYSs}c??^A$1#4o1mr$(NIu2p{v#mw;gNp= zavvUfmS_fs8F=JXq8S)Epz_Wjw$Vi*`^ zK;_}

    |$JVi*{1K;_}>XC(QM7zPFjNr?a8<9$f=TuBTAg9cO{oByUD=?5(l1sjbN zK3ifK7%ZUr(dS)3?!SU$K34xDnUB@~u?!3xQ1jvSJlGMC^4uhrf#C<#|LFTmLFpj` zNgjS<3B3IYP7ejJp*@g$TVfd)UPwX03w%!o$S!ER1eAZ4#4<2MNJHeo_xwQRA?XV~ z4vn+Ed=ksR;2{suj~*VNdX6QIfx!YQ54tA^WIU*zLvNSs#4#`!C_u~sO^t)qK?#sK zK5+~T0Z@79eL~>&J#u{sQdbhkz!0GXF$Z~^AH9B_6UV^t0jdsu{)r2p1IS8HIPZyL zU{Fwom;)czg@iN4I(JYwzX7=qsvfnJy1IUfg zap@yS`r+#=;rReDul^>Hfk8kA;!fy&Qs8z5BwXO-2-a~EP&(8}Vqh@Ph3E&}HwAVA znmr)@gd{OA{D7)M&u5_YQIf>K@B%6i-*<#9ec_mQ*pkG+AfXR&2e$CKlElEk0hNcZ zZ$U~wUqJ5DgXo9%r=jv7e~KhCF#LeZ!_P$m_sbFcR6yy>CYgc30csE0IFuuwf;-;^ zMo`#;PKSW3_sB_RU@$O%*bBYy3Mu?y=@K%k0}7`($qWn&pz6W*Ux5M~Gn~L@T476< zcaj+x5{w}Bq1Tfj^Zz6>Fa$v5yI=(YrukUY11O$tQWzK(*h0*Q_bWhdg!U6-QWzK} zK;>b^L#4s(@|qL|h6boSJRYD5K<=A^BoDs73nYi>KJXe+to~17VAx;}aUZsR>K~B% zq4Mx_0R0f6ysJt>%AB+NpPYeP5HAwogl^b(X85jzn=3{Fo z?MY=|NPxj$OdJE;r|0Z@7PIx5Jx3~19Ye4P|a8Uw=$s5C*09A*cUP1Y7O&SBk z2B^V_+z7gt!Ymd_eMl(ij*Lpz`qZy1<4)+IceR3=9oW zd2IE#4U#mlU!5Xc=Z=?n}OP7rsZ$1^A&EJt1JKGdkUE|W1_lSHI`DmOps+ww2Xe1T1_MI|R2{bRJtTvH zAp$B7z84N^4q82fwfz7xe@X@egM=%@z3A;>ko=Ym28Ir(Jp5cEXnPqXeGJ{;#Rhh#D^bhts>kG!r5WDF>r zOEMW4G~6Nb$oHV2r;9n63=9iAAnLIBV^1an!vs9?cQP3m8t};f$z)(Cz#}h{#lVn& zN8Tojfgu2od`uQ-ee?*#bDvui4b+*dk#SkAdtR6<=~xM z28IvG5Pi`54;dJke}dP|fb9PRl23)mgYG{B8H?^OkU1)O3=AjIAnMTfse$6tC69sO z22>t;-66L0gmrx+NPkNn14Bg?#C-5Qi6Dnyiytig0Z{lH$zxzxkq6Naz9$f*pFsG4 z{h!Ccpil_W2U-dR(gsS$uyPpGatE2OlFz{40aXXOXA!0jlHL&OGaxN@uq?QJ86 z*!oF-ko3dXBS7_o{4GI?$iVQT17a@to=A|piO?rg#J~{H4bewz{CEFkW@u($(5?B&%)rXPAX*Bg^L{cj z{9t6zjf3*Te=;*@Ffzyn{A6Z$%gCVX{gau2k%>Xq4JvOBHOC0b*M`!vP+AO1|NFtr zpw7S``{4&O!z@My*(X1k8624zbe+C4GjK35=vsV-xI^$eGs6J}23hv+%nXgp47xwQ zLHMV?LEO9N8${h!D823*#J%&N{OR8y?w#-r;@<9W5cjr01>)X6pCS6c zeulXB-Dikk9>l-SN{{ly{exe z_A!2fxcB=B{X7-SXSF*EovFvwnh%go@*z#v=xmYKnafk9T`Ei;2R1B2|1 zH_QxP3=FdK-Y_%xGcd?zzk&EO<_*NWP$=#91`=L&P`>#aNO&2%frOX#8%TJmLFMJ4 z<_JOg+)(=OYlykup!B`hknpsAzB_zC_yo9Jf_!1I6+h0P$YXy{F_7Y-$ z;Y&z3BtX?4e$LFm#K0iB2TD(W4l%FgIYeF2bBMX|&zTwQ85v~Fo-;GNXJF9fehx8@ z4XWVFE={}d8_f1W_(ze4GEPaxrU56Zv(1QLE1ov71QLD)Paxr!@&poo=N>`ad*l(s9Sa{p!f*N` zNceR?`O%Lc_V_^6xk72XM-cbwLHX*BAnsLo1aYtQBZzy&pz{1sbC{s~-wz@7zJ=1y zp!B(i5ceK<2yyS0hYG2MUS(!*W?+y#3#AWVh3MaWl^Jwa zs4VYQW`V9@=31;YPu1rl%fp!_vgm>D>k7<8vyfrMMj z6-apaLB(~hFf%waGuTQ%`EM>m(&MAc5OrIj{AHJ!88jIfWamT0r(TA*tLHK^LohRg zZp&qe`DIXfo68V;g`xVnpyCfMLCimY31Z%fOAveZU4odmQGwY934iaAnESQS!RY51_s@` zXTj;E_tIHNI2=0*NiUnA@(a&0Gc03d(Cs@53FoG>5c{mpGBemRGwAx9hVZpdL+qD< z@FeLn@U|HCPW|6ZSh`0p81{{AV5IhUaP(@=UZl->rV=bZw(TXw=J zh`U=(LEL@n1jL;OPC)Eicmk3yr=Ni2(+(&<_yoir7pOX0C@p#d;xGT>%nSz^8FY1_ z^ygy`^-qpL%)JYxuR+C6LivZF^lqs5Mks$3lwJ%Kp9$qpg3{ZLLh?_`QHVXIM;GFeLsy9fri;Td4SbD18G;pMuhdp>*|OW(IFY2Hn`h%nZ*M z8Fa;<{C|fae3gUD3<``4x>pZCXqyAf3_gquy8HJ-+_7Ol#Qv2~+HF6?oqzX1i z@f%S7MJRn}H#5U?Mh0EGT@ZPrT@ZcRP+A2lE(qmwL1|{F_?Mj!^>3l{_MMRQyBf-$ zy%XX;vz^Qgml+v!)ps&8R5LQja_xlJ_j?CK{}(9zb_b+r1h89K!U7@WI@i$u_=HA@`vG*F3ZrH-i(8kE18@>hN zUTLU09;iGkl;+wDiD$!&%nZ$p47xuyK+Jow0b<@mD18emej3U@0;Tst#WzFwYoPQ} zsQ3&heKxs`VJz+h>pI_H8GfZS; z(0#j(nPCYdgY4aPkaTu-9mGG!)P}&hHt_S6-LurL|5O+wggSbNs zD$Wm8&j98BTnn-1*;+_^d8}n-@MUDsy}t(Hj>~Hx@@LjS+>y72nc*k{gKp{?W(H0M z23eam%nS)k47!t6L)_Q28lt`$N|!*zQ=$AgC>;(J_k!}Bp>*#mW`>=N47&BJAm$aV zf|!>Lr9ZBOh(B5h5x)(k&qC>APbU8DFJ2Qi>D3o5YjG19N1A}h&GG>OA3=Fz|mqPeYmO}Vb zq4et|kZ^ml1meD1OTg{Y+_OuV8SI!DboVY{X6RvN(47NSHyNs~6RNHes;&U4&SeQR zgEupSt{Ifpg3@wO{o+vld{BMNOPCpMF)--caWOMPJ~M-^$YMymur7x9``;o6 z{e2N6Jf1`O4;Dev(al8=^=F{sN1^mSsQ5-Ge-)ITy$Djz^e%$bGmVQN^^DFUW(HRV z23>wA{e2-bg99^z?$L$J3<3-cxr-J;?3ug};+`HT-MSD`&NV>gi=pByEnsE{VP??vSisC6$iSeh4pk=&l^221@8?6*U7imy|HyoZ`Fo-CHmLY2D1R}O zu7~O?m=7^O9IDP6D(?cN<)P~S&4ZL9Kj%T>@%=oAJnW2i2L3iD3NdBHX z8=}r*HZ#LVMh0Ey*%159W<%Vg4&^IAX(1@h4W<9if~fxnrCn!1+JA{NnHk&}7-ZXK zKAo7Ax{?+La{`#rR3=0?-bQevA&=V&!Gq^D`=;lJ{kNptwXZ_3! zF3b$N*ZU#mSzkZI{&pzc&<}BUA(Wp5r9+^!FO+udhlHP5KO|h9_Ce?lD1EvY5q@}3+Znc^g`@Q>xIOBL@y-2Y4$?$+m{}Q{damG>aIfRb5Qa9Q2q`my|D+9zSi_W z>Z#>W@tIJ15|l3Qf!O2T1Icf;J&^pS2jz42Ff#-)Gw6QqW@cbuV$i+N4avXzq4YW^ zJ+qsc!IzmqH@usfA(@#$*9A(ObwkP#t!`$9wTuk9Qr!^u3wJ~MeSf5aQoN= zarc`ph`XOd<@aw=`)b|}B93*tZLE=V|n1w4hb(~sJLu9Bzz>G^1@JgKBzn^)co&l5c^)VLF~KT1__^~ZIJM3 zZ-azSZ5t$f@}T@ks5&F4IyI;~TN^Wj7pR@k3Q2cMTOscJ-U7*gkD&C87Kr#UD1Q%> zzY5A<0Oe1F^4p>O3MfAhN~b`@L!o?cDBlLkH-hq&p?paw%?}l4fbzdJL)`Pe8RE{T zQ2I7h{0x+T2+H3K<*$VDXF>TBp!`NCzZ}Xhfb!Fz{BS7W7s|JT@=c(8RVZH?$`^ss ztj&=0_pb@!-pfspbb18J-wUPJH9_LBp$QU?Sxu01lG+4GCkaq>Vol5pam)<5e;Og} zN3KQ)|5XEof2$tC-&GIcGuA`w`&0+9|233;QU`I@T`2!Nls*BacR}gRPV`kXQ$e?QhRi_6PSE>WIPi6ntLi~HK7UJJIwGj7At%bO=z80dc zpcZ0I1XSJ+D(?i9XRL*!^G!9(3|7nxy0SG8{|eMV%;AL6zp5eQiLa|6)bH zt0Ciw=c^&(iHD)|&T2^hT3pS{P{Pch+f~iXP{z!lTV2h}P{7Qfn+4@tRYT&*v>M`m zooa}^qSefxq^kSB3K9=bsvza~{VIt2&R0Ryoq*B@q2gPh{IyWJy^5J(E(3#Z3P_%r zK{o&@Zczm(ht)vh3=FzrP;q`J%>fnvQ3<2Hhnk%nZ928FZtHA@VZCkoMD*B1rq7r3hl~)j|mW zSRuq6>k63}(is_a1)<{Xg^+&TtOAI?zU4#cgZU8s=K0JFjtmU4x=>m@pP3<=nL$@6 zpP3;Rl#Za{!cdwqACi8)OhO4sK?;-v!0Ps(Lx zux4h^jfCp=fr`6AX=|vs4wSD7rNyDN0F?fk!^}{~%%J-=hnb<2nL+nL4x}ADHHVpD z0V9KMZw@m<5i^5sD^y-62NJJLIgozlr)*{he`W^VN7>8_LCg%gm$I1|szLQjHYA=l zW-~LiF*E4S&Sqw4WoFQA&t_)GVrI~-%!b5EK{hi(4l{#pL^d-+Ix~Z=MK&`-9y5ck zd^R&fE;EC!U^X*D1~Y>$LpC!*CNqQXgDePrIt!wIS{9@o)&`~PpmZ@*J{n4UWif+{ z&^6CuW=LUX&=t>OW{3cltC`FU9n1{6A2XR5!a?&4nam7n%nZ5*q4WwUJqb$JWOTp#juC&Vck6 z1v8i#Dwr8`Su!C0`;rc!AEiUW=VCfDLp;b|>5z8mrgTWYT$2tdmpjrS<#J{^q+Q~i z&deahz#wat4spL$I>i0TP+A5m&I9GMLg{~L5cTiUAnKn(=?7_$^l&bXnZbd9L3U>v zq@0_O25E=1K-ER3F*D3(WY7%)nFH#_LB-Xe`XoT=nHg*u)0i1R{nt;ako0&p6=Ke+ zREWJisgUs_Rw%tC1=3Dhn*zy~y-%wuHGZHZ=PuxDV9t%dT7qL~?(7#Vc4q9OHP48%U!z-Y+4uM^ZB zu4rb4NM;6I)@aB)){w#2t^J{9RGZ3oq{4hf$~C>;b9cZTw9ptLDeTpP+)fzlVk zAm$wkgP6B93}W6oDD40hH-z%FptK}ZoFB^PfYOXm@lT-;b6!K~Goj23`xqH?l|vxo znYO_Y`}Be#>eQk1nILGr4W+k1={_hO5D1ZXh0<0~`lCNY{H8xMLjwbY?iqh(h9(9E z-91qHlP|>HMjwc}GANx5r2~B+>UF&!?o#lAxJwdBU-5*9AMu2U?}gIapyJD*{P|G2 z4Juv<*C%{B0f(^A~$S%%20LPrE_H54u6bcR}gRQ1N9@{(LAc z=*G;@#mJz`1C{^d3eoo!O22c3n0Ft_zX7E$LdB0m`3Io1fh#k^Zbk-OC8)e8RGbe= ze{y1G*u%)6d)Nt5-tKgQs9z1`n?h+uCrG|o>j+Ud%@H!r-wEaCIzrr);0SSVB$N(- ziaS90mQdOVDy{_OOGD{4duE2^j10MT5Lz|`O27&3S!WwWR>U5y=O>>C&DRYSU zVJMww1__5KGl;mNDMX!+DTL1rrCFfjKTIIvAEES26NvgQD8Cs>dznDo$7Bquv>9}N z7(vv%G=k`V1f{QlF7jk%uq}qt2~c$bPj7wJRHo2m~nuMbM^)q{v{(1VDtgwl)jApOj_dXVvsX;ATgJxF~NpvTOxgONeE zP6tx1NoYaL;n0GZ!w99_H6ZOSeGO&?TLuPQK@CXz^|3l+-Hg9F#2zno$hd>6Iz+!6 zRNN9OZUPn8g^FuH#g(DrGU^cf`JsFcDE(axBK|@RV(vpIeM=2u?^QL3y%(V3eQL}M z)(i}~GgKhzi&Y@}a0Q4tUJ4L#XDH3j4iW#)1`+=OrT?)&#NV+%#GgaygHU=al zW>8^d&~0R4W=LXSkWGY&heBy1C@sUn%)rRZU@Hn$&ka@ol^GJgADAKbJ!FR1cMD2$ zGDFtwTw#K&>zNOw%b6hY;K2k@|ArAluY%HEP+FD|vL5mY12cm>1B2`#28g;D3=nts zF+kj%&H%AL94a3GrTL)Z|Nk?A*D3#i(jWgbf!8TNgz|6wX9BNNKKP#ryl!<1RDAw_ zCh)rBiT|0v>yBIhGlAC~$3yvHP@4Te6GJ4ZzWv9KN>)!Dj;{J6|@#ViE;aT<@Vt+oAPJq(UKbgSkF8C)CINeS94&irwhwv+) z{5&W>8p;oY@_C?qCMbXQH;Dde-yr%0zCidKUm*M+pCSCupCSBpQ2r7qf5vBszbAi& zgh%fuh`%~MLHt$s2_jzp3F5E$A0XyU{{S(s6UwiL@{6JTJSgAr0~2^%p2i0z@VYo< zDF5AiCU8G?(R)a|_P&S2OWk{@eNejKJtVy*K>3mHA?^r*s<(xTn?Y%PsJJ|oF9D^0 zy@RCZH}4?!J$MI6&&F?=!1M0U-$2~c^9CZn=Ou)n{1U=n`h*F*uI%z-Ch+>J6;L|i zF(iFPKZdw_>qCfnMGqnR)gD6hb3TOl@8<)Ex=&F0^#h3bZ7BZ=l-~9LV&9YpOyGI? z&Ie53dH##{A@*;+4-ubsp9$RmPrDCM|M(t6KK&jOc)lw59wa}y+=JvtT`2$7U5I(R z??Uv?xeIaE)Vq-I?Yj$cS3Oj`0!kO&g~Uf9lph6E?*`@DL-_`GA>plb7vg`hyO8jH zbO++@TX!JxXYN4c_uPTVPrU)nQ=bIscj|0vytn0NLT6L>xU?pqN4v|CKz@;Cby z6N424gRJi@h`Hvsn854LFW!W>_rOhv_3P>7;n#m1;=fv`cnOrBbe##jo;4aO9(Wz%K8NcNcW7N_VmQgj zAgg$tiD45XgRJ;vknCEsGT+hfVUxwJj2Nh?B(wirc7kUxm zUNxw=*hPqYKVE={zq$ai=hg*?_;INCUa0tNsCfDXCWZ%$47w8MA>sD?EQG#(8se_w zry=GXfYPf@L(HEF=eYjvXc<;JtrXc z>7Iayi=BXoUpfx)=aSVq3cAnrJM z1fuQ`l-_*=QvR%l@|PTel)qDtK+3iDBanPpeFRdj`9aOGhpM-L(uPoTWTAX9s5zVv zb9(G=Mb%!DODfuuH0~0fYtRIxm4COyQ#Kd3$T8DoK;*WiY zAo{jL=?#Y<{+I*hPdxOg7a*zqUzK;1Iq#S*4fC;>AYtsQH@Vc$}2O#C? ztOHC8yBQdCryhWq*LMJ7Px}FgyECEsOriSt4nXRUZ~GzU9oi2uuW3IMgC{eCZux$Q zxkdY#!2A4i_e0E!*bgz^4a&FQ4>8|#Kcsv#fa=qR>QjTNlid#qC;t85aFb<#@;~f@ z*uQfh#QwGWAobhgeGvCmLizbnegc&52IU*?V`6yE$e^pY58^JBeGqrb?t{cDFO<&) zrGM;&$bW>=clRl)oj3MC=-qoD_N>_h zF?T7HZr%e?9{^Qn1Lbo<`M-BV{P|@!#Ga>6{^s3~blJ5VVs7G8}iCWcDTy6#;Nb9U@v0iy-okwLY$xbE)GX@6PZYaMB zN@qgp2q^6irDdTsCzSrW17hw&D18=6OKoRj&|qMY<=M`}@PvUu_scej|DJAx`1>A| zzP=3-e#fEw1KS|sw-c&%9kZ>*91_@WgZA=VR%nZ5;+n5+^m>G20 zKzv39-FKTI?T+J6`ru|J@cif&D1R}OF5Cz)H+dt(+|Z4X{1&hglHa^HLfq{Dl{bQ_ zSBCPZZeRkhv#rzUCSTJ#RH6d?v1j*wY22 zFRX%;Q^!_8#5b;jly_@ZLDVmTiqD49Q=sBqP<}I%wp;~i|D9P0DYsHrLiC5NgqZ6O zr9DWBD>B1``H`-kA_Ow+pJS8LF;$854ss1A}Z5gw73G#>8O6z>w<% zrHz*{F&Hv1$ZA6Em4fOMhSFTim>3K|`^1()=toN-?!LPe;_e$uA@07olnK0E?--Q7 zb19^}-U3y>9;$v7RDRl0NVs(@g~UT8l%KN{Qm&aTg_M6XOCjZ$&{9Y_#th{@T>=TG zYfB*ZpNG;XmO$KhcnQRP`=H`|OCbKNS^}y63ZUYlOCaWZFM*hE1Lbosf%x~`Vu*P! z7em7T&SHptR~JLVUtNyq0FGBGHE_PZ~Hq)Ul~5dFdnA^O=CLiGP%0MY+_ z0TaVZ&^nU^ObqM{47&RkK>W330Yu$eC_N2A=T2C_#2^P+m%o6CfsKJdwqgMj0}BI# zY{3F124)6^+{^_`pnbu)$qSemx=rF9|lvg%NIC5U~p z;!v7@0mPp_=0og%G9O~^o%s-Zug-_qdwxE|-lI_Y-B9tZ^C9+bfT)*U3Z-X4}^K^*&4oqia;9y{o-8`L%;Rq9h z?lLHU;&dhkZqUB>X-o_&m>6UOra{zkOoQaF^;4M`BA6I-yQV_K^QS`8ADF_#z{1R6 zn>d9D)Kt>-h0+TqL;Tq?84{jcQ2x6~5Pr}kh&_6fAm;H+f|$cH31VO2L~yu@rbFqA z6CnKKPAd5uz`U=cU>Q(9A4fBQ8&F0(oe|igUEaL zLTJ4n2(8l1#30PTAiKQ_V*ZLQh`xnTdU6*;z6~m04izte(wSY5bQcNb2X#TxogI{K z4&@tkLDH#q7sP#vPG+T&Fh4ilK?d*0BTNc8>AhQ-v()iB(y>5A?-HE_}QISh`nc8A>vb8A>q;5 z3bCgSN|&}m;?u7MlCRBLAoVr_l-}12(YK`;qHisfUIrDP3FS|M(os#2bXwmCp?w=6 z`t2Ga`pu!V0aRQO%9n!D!ccKeD4z*R|89Vo^R5A6&T}aJpn(az5BgLC#2+d3OyK>` zdi6{U=RoWJ>LKZrxgMhbTOCCIdno;)4kCU7%D)JuPeH}^LiyXE^m?fH0w{kbl%50? z?|||fp>!2gJQvDOgVOPJ5O)jILEQVW7UGVJwGj86g3^bf;@hD7^-y|6Efd291_s?} zwGjW6LDi*0#aj!>2W(LB|22?w`K^YD;XDI_ z?(`anyAx|5?hdShxZ4X#J440IpnQEOtx?0oa2gaZH4t}yt%m4-Rt?dAA4=bVil2e< zk3#8vQ1SIp{t76)5Gp@}!>*sBOtF9oG} zpfoF#{#OoB_pTgb?sF)89ZFw-(kG$n_CxtQp!6yzy%!gVspXLH zomd8OZ(b{jg%y|!`Uz9-f--PlnLFv;aka#*)0x943L&bMM)vt!~ zmq6*cQ1J;+ekYV}f{N!u`590;5h@-6<@-WulM;ykgo`2mJ6i;C-+>~CyLUqAO+^rO zWknEmwna<~#!L*lB1KG~Gs<+o6hi9t`-PBp!tO#yI@(wWsaIwdGBIc}G3Yi!)#X9e z?I?iMAB_bNdkYI7_GUrpWTvKM&{qP1#@5qO^vnLKp>%W}#2>bKka~|h4^n?z%z@Z*3QEt;f!I@& z1F2L&2k|A)`aqvptNuf6L>x8nQTbA^-wmX-MSgdpPdbH zUwSsgzh>D?;C;Qi*-YSly$sn*;C;Q9vmoKVHw)sPm01w?9L|Kedk>WE&4jo+B@?2~ zKNF(PEfW$x`cQExsQA?kh`Uc@K>TqKN;hXf%&mda_8CkJ%*+h3kJFhL7?>Gso1t`Y zIz*ihl;%%|sN0+dQ8y_Knl93q7^Dh+*slwv z)u7^HP(DADW=Mndv+k!t%v}Mcr$FhJR7k(8DixB>i=g5esZ0#QObogKsgUq?O=SYF zi?mH;0w%iFM{$jQkWPDnHY4P zptMj56T?(S23_71CWcBT2Ho$;koYs zbR|?g2g*-{(sKit7`8Gp==KLd%xemOm{$#@S)lY^e~9=ue~7y0Q2qlbz1<%YJ{zF? z1^$rmY4L~jb5i^ubf7O2gAN0OtcfoZgEnYAvk#oT#ZC}&^r7@o zM<#|ECI(#-M~Hl}Jw*P$9fa<%gUBDTf$&9aAnKy6ApCol5IV*ZQvOV{fXJUQgNWNf z>F=fx@wcWBci%FFxO+QPd@WRb7F4{^6yokGQ%JaHn?k}p1xh=bLekkw6Now2Od$2m zQ4@&0OQ7OyCJ_DQCJ_AvP&yc@&cuX?;WGn+?h#`q1`klVX$(DpE;Cn*J5H2VPeo# zQG?Wjyiod=DumCf%ES=G#Gv~^1!B$-6^MHlszAmcrmH~e^&F_Y2UK1aDlY<+XH|jJ zqwka<`fn;j{PRNz5)KcQAmV3~AmXPLA@1Lx2(hkJ~RQ!cJBz!N)L)7n+hp2CohlEF|JS05wpmaJ^JQm6igVMfGaa$7$wSibPdSLY-^oGp-7`5zzIz}Csqea>@{Mv#3?-oRLu4W8Bw3b;p@4}&H$s+) zp_qw5S5p>}PgP_g>0MYBQontYftbHj24e4e8Hl}epyCr{Aoh03KAY2Hlg=Obpu?8FY6*gi28P`IqD%~O3=FaxA$-|cQ2qo6Ker1)%W{f9%zr5i(H|+y#PE}m zL6=zwLU#&6+*2qB@y|g4NI8`v08zh$52F7IFT`E1cp>h345d%-GBM;cG3f4t((8Dc z7>bw}bW3<4={JrSV!j10Bp!`;A@QgQHBSa=jwqDogNidk`M-D|_FdqCr2mspdKnL- zz1a%o*FotZsQ4ppi2Xk}A?|+72{Gphl)ecSKLh0-h0^t$kn+HQ4U+#?ut3H=XR|=^ zPa6v)|5UR;(tR-tB%Cr?An7lJ1>#>%7D)PYWPzkVYp6O^sCg1l^O&LLePV{V_a-w$ z|0QNfJ~_?|X&3HchUAl_%#e0bC6u4U3~2{hF+=i;J~JeowU{B{EXEAUFE5!O=1zvv zl~6huO6xH}{Kv-xDc2a7Am!RoMu@xCFhcZqL-`Z_GcthA*KPjK2wt~Z1Eux+&EhqX}tGAKPCs=pt~?|{;c zQ1KEdKNm_zo`A%Q_X$XN+n<2Mi{uGL@H*>v$06=`d>q2R0p*`R&In#7YjT{C;Q;8o ztYeJed4O5R7{UF!Nyiw${kz6vjNtxR`7uU@PG$z(lw%P8g&%{M8vvypjxmDAm5q)u zg2$7^jzPlr?@@@lZ&3REQAjx4hw^V6g@nV!qm1D7iD!;N%-;)@-v*`EL&fJp`O~0u z!BIx=I>yYSkZ_1T3JC}QqmXbgItuZ(HdH-7l+O<3|2o3RpvAx-d-Vt-1L%C^lSd%# zRX)TB-v2Fph!K3Am(W2*@OmHKgAnuB4nov@IRLSL#{ou$a?t+T1CVf?egNW+?gJ2Y zEl|4V03$;bBZF?i0Z8~{9)N^<;sHhmQ3eLtC@38arG22ZE0nf_(&kWF4NA*EX;CQ6 z4y75P^soI8^FQxrWDsFskbS%#V(+>Aj11YJdDQ)k;PulR_A`R_<*wY%$WRR0PraWJ zyidDnKO=ZQZ1H|b_$Kd%_%Ccf#DD%!+5;+X4dt6a=|B4z!RshD>|+G4`&zb-5xl;3 z);@^-{C$kz^UIR=F*5jo&bNVzd+cKb@7HzS#|T+N9#uOnrJ(*Jieg4c6= z+6@tZ4dp-F%?Mt9av4JB9^MUc_mCi1_=R5OZEY>4#A9 zD^UJfD7|4Pq&!Z9(lI+B?g`(?2wo2s1Xbs}lMy_ACbkn&KJ)B^l+S;6K=?0rK=eJ? z0nvAV2gLphJ0SYnpz3ONK=kE8`F=Yf?sb8xw}sMXP;oUVUmi-|-p&YK&;D*3MBkHb z5PR-I>1$B&V^IEnC|$h`qHp3>Mux4Re%n?^da>FH(LZ$y#JsjG5Pm(BuGj*Jw+tvh zaSNn;iP{1wUu?EO@~gxaNPQv*rLSye1dr2|Y-R+H)8%f4l;`oAA>~ToW=Ohs+zcsK zgf~ONk#jR7e12_$@GotGP285ts(7<8Ynhmd7L#JrCyAm%?`0nv96%3lZNFNe|#pma7=UlLSZEL1!M$~S}3a!^_l zD$fDse_IZ*@6vLJeW#)H5hy)rImBHZP<72v@hT|46v|JA@|~c3YbdP;71xCF1)wx1 zlxBj`ZD6I^og`xE7#gKUKhSJ`P85#aDGUysY>EDYW{M(Bl`ETJONIsvm2x4zHlnz`3 zX{TLW2%!rXLe!-!gs6*!(vDDZ6DVI7N=re-xuASzDE(&v#GLmFAm+S)(x;%}yP*8d zP+yOA?42H`H*smc|Ie93Il_#+*}A9F%d#L zKxx5Vi26sJkaqF>R!Dnzb_;~=fYQZKdTTQycwB0EGb4Cjr?(l>PpN2T1h03w-2~~+ z>}`USKP*jP~=PHMo|E3IL zzEK&({E#Au`Fwd0a|LoCG&7X`oCDzp=0MDM&ViV(nFBFjBnM)Cc{arS$ZUxDE3zQw zpHG9B-fSCU^9%BCWc!>Gx@euQaq9Nw< zghR~b3xm*%Q2JvigdY$JG2bZ^V!lQw#C+jUi1}q95c4BKAm%R*hM0fWA7XyHH^iJy zF9=-&rE{S4IZufB2RtF>FY|<$KhYCn{ud93`PV!k=Bs%?%nxvZn9uD1F_+ICLjSgd z&@Z5Lj2*;$S38Kg26hm0du<`+=G#KdJz@hf_pJrQ+!ZDeb5JW4F)gk7- zQG=L!O$}o1CN+q;LdpQ_Ik$)n^2tH@!vJ|BJ z*e%5fUKg1o1t~9hpyKROkaFsmB&3}B45iOXLey=Ogp}hmq2eh}Iu=U%K;>Pbd^<@< zJ4qd?pGlGtys!1M1cZJm0Wt5g1jN2GQ1L@hdJj~76I6Z?RD7ZYBWQoEY`g>{Ji?$f zy96V6Kkrs?h(DH!L(H8ArKgKCGSo6M=w?9qF;Ln{oRI;vpV~m25xlRJ6Ds~!45I(K z7)1W87({*{934ZA(Zxp z$~!{krJ&+`Q2K=kME^Yzi2m&&5c5|<=~k$GHB>$XD((TLm7wwxQ2CF-5dBY~^e$nD z`5S~G=66EHYoT;FRNfaVuLc#Dg3@1vAo^bkLG&LMf|$P@N>7B!w?pLln14_ZV*V_scpsF`fXc@~<;|hu+EAJmD*symqW_8j#QYObdXWIc z{25UBLa2Bul(vV;n?mLJpyEtW`VK!t|0RBi`K$RM=Ff-Hl~DP7sJsVM+y+XELFIX% z@=y67`foz%&3q8^SMov3Z-R=KLFoXfyc<+r9x5&jrQh;G^grf>=-1j~;9;kdOR6G(&8$;zaq4G>n@o!uZb1rZ}%s<8jF@HW(d@_{Ig~}&G z9DH$lbApmYFK-VG`* z4;2@N(r?)y`X94F^zUJVn7;u^cR}SFpz@JWabGB{4waXM%Kv1A=zj~PkF!F|-^&Uy ze%LFmM6DnQ{rNg1}zEF8hsJJYY{>})||CSM=|0E;C{Jl_mI#j+FDxV1zkA>34 zjEoGwnHX$!pz4&M>i#i6%=rYR&oDsjIm7_5XC7315|mDY%11!uO`zf$P?`xU|KmRc zxIVt}p8-6daso;(`p*EauV+BzOQ7NzP}&J9ZvmATfr@iL=|}${`fvP$n7`#8#QYUd zx(O;@0hJGdihDq5C8)dvRQ}6fi2fH)`p{p9`8)nX%%1`k?|{-tQ27X`ya`lX14=VN z<$wHv=)dv@V*UvzJ?{?#!#^el+v$HG_Vhy4WkTg+p|m+vUKc9Q2^IhQ8)Dw|-w^$0 ze?#n92^F6UrOTo6xlnmesJJbZ7Kh67Lgionf|z?3N^k!KF@NnZi20pR@meSy4wd(X z%46u|{DheE=qJRSeLo@gY=Y7qKN%SQGBMaTLe-T+)pBO5cOh*P--TD18h{AAr(3q4Y8+Js(QXfSTJ2<+nlUdMI51r3;~S7L-ng z(y>rF3~G)al zAA-_5p!6mvz4|lg*b)ZO#ZdlCC_M>EcSGqGC|wJs%b;`)lum`xaZow}N(VyS=LY55 zLum^rZ3v~cptK5B7gNG#JrPGdhthy{+UquQmA+)ly-*7TSDbUq2ioS`tb*d z{+k~l=5PG~F@GhLZidQNLghoD;+{}i87eOcmH+x4qW>k7KKveH{?7Lh^QS_^JE3$k zR6Y_aZweLHgwo7V`Je9~`mer&n12#VFMbCxe)%4k%?hZxJg7P^sJtDN7I_P)M|h#?n4#+Kzk!%{8A`8x1F>)M z8;E`NQ1N0Y?F*H6hRVxB#f72t+t(2Nk6%Od?|%(3e>0Tsg~~TW<>R5^!BAQkDz6Nc z|Njc2|1*?6`wC+I;a3pz=R?IOL+M-o*Af19)A*p=S_%6QFd{Gq8EG z2~d6zlz;pw19)9Z-BXCYOi=!^ClLO8C_Mv8H$Z8lClGzF9z)bUhSGPS^bsgs{}`f9 z7D}Id1SxlRJ%Z@l45hC=fRv}_p!Avt4B&kcjSm zzAuz^gNj>1`9@G$8!9db<%>h&AmZIOAoi!+U|_h*#GtEl0}`G} zHz4knhSCqOL)3>r>2ud0>h@oQsM`Uh7hQw+OY$1T9ehyw+f@kvJd|E|6=GliRY>@D zK}Qg4U{g0if2IiiBQ@NDsBno8$s!VmmvOI zbBTc=jEO;aE|d@2ya?LI`}izG{K{E~y6dMPblWM2csZ0WaS9U7zfMB@@#-YRACIB5 z*hz@K!zUpA-UFqVo`8hUv*QqY|8a;pTaH8GE9*E!pA?ina10WD+{Yl|6OKZ{J??{NrAT_$w%Ve=h@g zp5J9JM4uH@+!#vhK*eRCd{HRPxf^2t$6XBIbyt16ApG)O5OXqiLF`F{((X`k3nCKc)!=f4G{fjHZXwa-x@bS%>B8Z0lcp8 z`g#a|*?LGi%Uc6+SL6zayE2zU=z!%AcNs5-sOMV_G56&%h`a7DgV?)m8AN{KGKhQ* zR6ZIiAG!>Z?(CrQn#&;W3RntpkM2^4{y$3~?(tZ{z>v(upzE-NfkB3eLAPNc#C?@> zA?|9L1EDkKK-}j&2clnn4#fW7vmx#}G8-aZ1EoD@L*x}_L)^~X@{u)3Z?J2Gl176Zf%E@Yf0@8cX+i!;$deS#C@CE7{Kcm zCqVg$Z43-x_@{bE{c^n?qHbe71A`nBgKj;P zUs?~*r%=xTUYGm64x;X99YlOe9Ynme4l)i@P{#mX-u{Wz4Vy_xhpFC7v94i043S!>dDv0@4q5Sn#ka{|? z3KG8hRS^3Wsv!1BLTT4ZNc`DVKxpX-2JrbQ;^hqBb5B^xA?fFR86^EYDudW}ri=l+ zp1rt?0kVF&i~+oU+M*27uQ^uAz!1*Fpu4gZqJK&$M1MjlB%Y&78Nln+-AWAjIqXgo< zrV@yKStXEs_Ouv6A1a2p&$yTYyq^AR5ky=$A5zZB+ObtrvF4U#X4n1xWnQP+$PB%b%#g0A81$rN97Qm!GP@0A80L236N45AkodJjB1D@?d|; z?vR6sFP4LdcgjJ;pUOhSFUUf~x5+}p)1l(gP;pnN_;(pdJiL{GxNDXSq#kL8ir2_6 zfYi;Iq0ABb1N}2(@?*E=NMBRC52JpK7Q_>9J zb^j}&{3X&142huqmeLS+bW1aU&y{SJW&oexUk%k?0+r8|W&p1rPnBk1;AdcvjgyAd zC*jfzpd%4v1Ed+i`=LCc`W&Sh71t z&C0^S@Qjf`_b)R<{2Ma^1L)kpBT)VZX3#Q!hTN6l>y{aE7c(<}&;6STmG6g&cQQlT zKP?dTvXxLe7a}j44wX-02Kz@g97_8$L)_&AHP0GKn=nJ%r2^%DVuH92bc{ae974$P z=?u9SnIP^t4wc^vK31I}cRLfrJ)6MCgfPf1htjhl^0LlMkanyw69f2ML_Q|4yK*_0 z7#I{l;lT(Ahi{A!d*6Y#J22!vX9U;pxepm3_Fjj|pM{DaXN1^$2%=tgJCt4xk(XTx zm0!RJwoi5{l6%r79=n* zm@zW&%}8KiFk)ojD{x?7cm#5X12}xxBA|4D0|P@C$XyN$451)*IWRDUFfj00I502- zGcfQOI502-f!yi906K4iPr-o!blwD?1XRBU1H?Q9D9ymYz~I8b!1sd@Tt4%CfYL9Z z^aCh;14>_j(kGzw0Vur#5`SzPp!5nT4UJ#68BqQNC=H5dRt5&P1}MJ*N*6%s3@Dud zr6Ztp0F?HC(hgAC0!kY|X$3||I7u)-_!2k)@ z3k;BOJOQN-K&yU|_h($iUaYz`$^e zk%6y*fq~&MD4rP@816AL@MSPCFx+8e;7ed&V7Sl7z!$;5z;Kt5fzN?~fx(N3fzN`0 zfx(xFfzN<}fx(}Nfe#dq0Za^hpm_9VV&IctU|{fLV&D^CU|{fJV&HSIWB_@QO#w=S zE_VQB$~lFM!ew zP&xrhJ3wg#C=EJ12yDL=R6mqn0HqtCbOMxifYJ(38no#ctX~tVA4)HP(hX2L0ZKbS zX$2_F0Hq&jK=niE1yH&HN+&>R2Pmxor9qow!S<^|^+V|eP`Uw1CqQWjD6IgcL5Bf= z^@IBV3=C`sp!5PL-2kN%ptJ*&R)Er=&52 z-2)YFN;g311SstQr4^twXwwx~zcN%mlwJU(8=!Ooly-p93Q!ufnFFj}3927T zFM!ewP&xrhJ3wg#C=J@=0oJbw)eof?KsNs4htdn6bOV%5 zfYJ_7S^-LfE{O%}mxt)-MUw52Y7C z=>{mB0HqzEv;vd{4Vr=VOF;EQ=><@_0ZJ!8X$L5+0Hr~LZ(#l6Q2kJP0hDfl(g{%7 z0ZJ=CY0zL7SicxlKa^eor5m7h0+e=u(h5)-G)M;4FACKUr58Zy1}L2Xr5&KO0+a>~ z&VcocK=niE1yH&HN+&>R2Pmxor9p!(VEw{S{ZM)Vlx~312~gSrN-IEV&>#_5zYtVE zlwJU(8=!Ooly-p93Q!s}m;=@?2-Odz7eMI-D4hVM9iX%Vlm-p@fb|PN^+V|eP`Uw1 zCqQWjD6IgcL4zt_{rph{mB0HqzEv;vd{O{#$Pb3pY&=><@_0ZJ!8X$L5+0Hr~T8o>J5q57fp0w~=8r4yjE z1C&;P(xAZwuzohEeki>FN;g311SstQr4^twXfOt>pB1VfN-u!Y4Ny7(N;^Pl1t<;L zWB}IB0@V+t7eMI-D4hVM9iX%Vlm-nJf%P*(^+V|eP`Uw1CqQWjD6IgcL6=5=^)o^B zL+J%jx&cZjKxqdktpKG#harLWGeY%4X;A+fBo69FgJ@8H8AOBn#UL8g4+hbo&LD^e z^=m;isQ(J0LH$(_4eFPIXi)zXM1%UBAR5%a1ks>z0uX&AlYxPc#em_!A7+pcg9SGO z10N$u6`0E)3>sVkNwunh1)9qk82CV80Oj}9K==nr@`+IW*=%6`>T(Ew!cvHRnV`WMMh1ok(0~>L1A{x%Jr|(r*`W5H zfbwM{A^H#GK+Lmhf$$%!gt*58s-7ViBA-_ak^cde2OZDL$H>4iVIIiS3=DINA@U!f z@_V3s0jPf;RDr^ef#HD-3)ubXQ1cz2@=_%b{VSmQPeI+k0LqVox_1NAy&EDR>UTi- zpz#xsdkj7@g3Vv04v~KW)&JZW5}pD3z|suwDmhtu zXm~t;#!n2?{}Ryj!&nXRkHS<)eCxpYP}0$1-c>WD+@Fz$icwi36=K-#Wx27gCCTC0+ilZ7#K8cA^LYUL)^mwwZ8xs z-%!4LJw#p*$_LF?g7Sk1l)n-hJ_^wEy9yMZ%nS?#P<}ErJS(95iBS6*p!`CRe>oT! zPC(t)0gWGBXne_~L;Tlp4iY~vp!z$Y`gel{4;dL45-vgHe?ay3EQa{610>JEz>okn z|2ZhUKx5I+{Hdx5@!ub4{2mACXJ=qwfU1834G)W^<=_PO22_49GcX*;W(D)xV1SnN$c6GZLizbnK4@JSD7_a$`Aebtlc4-rP`=V0Ncgls`6^Jp z7byR7FfjB$-TMKQemNKzCPDdSp!C4Oz%Ucaj{uct91IK#p!^w7`3+D$dprXJKO+Of zg7=X0X=MT7JA8ofegA#81)zNW zJcxb;P=&?7z|buT;a`C2UmgeH7yO0l7l7~uBq8=4nZUrn&&I%Tq8Sq3yOSaE3!wUa z(;)nWe-QnFDiFTHPjGTzIHdsL7eMV#4uS9)S|RC^M+Cx808OZX#zw^<{D6Fj{AwKt zf5CpJ`OxtBa1+9R&kvDTh=Qo!$OYklxCW7b3Ju={P=2f&L_PpopG3Gq_!rzD`aeyC z_;*GN#J`@<@CgWp$XgXb)K7?n@R_0f0w_OT86tlH%D*8G;ctNQ-$29n1C-Cg1Cjp_ z1Tk+9)czGv`!D7~nkZTwijQAk@4bb?#S_t7Y zfCl0j7#LcUK>Py?1#ckwi_IYXgbxrtBRG8?U`V(R;fq7%3!wZ+sQw4HA@Xie`44v? zd|jx#!9587l_|u01E_vRsQd(|eS4wu6Fx%Jw?WezLmq^$3FRk1)88a$_!L0-8~s7% zGcW`|(^DoieI-ak^y_vrFz~Z5Fc?7VlbKVX>LJ0;@G=&}Kfqvc8lrv!n9slvumPe# z5Ne*l8VG++Do8y8!-4e>{${9qKCFZAvu&aB3nAtm%ZBh7Dj@t0sCzfug{c3}0g-pu z3E>w&&2v}*QEwImk)MzO;e+PsLGiB;2H}^BLF6w$!%Gy(XMl#!MQHlpU0|P^iAB6t_%75qy;WI$>@6m+t1)%(1RtVn!%2%s|ls`A1%j z>V5%pi2XXy{N+#&k?-h$s8_Ip$SavZ_#bK^@;!nOz5vuci=pWw0BZj`X!r$KK=eyO z{TBeW&zTvb{{fW0H4DOb(1Vzt2u%+Qwm`y57Ro z0al3oQfPjC08MZ9(C`U>rl(XW-vP>3gof7zDBnK-;=TlEdVUJ6FBG8i>p|&{je+3+ zG<_&{LDI_(X#LX-W#l{96F6pM#^J_CfnsN1)-Y&<61j2Q>W# zK>LT&pzVzSX!?x|hUjNl3Q@n>3c`QT4dK6phS!5Q2ww%7e+@tjJQx@lD!D=G4=^;` zgvgsg%~x0fiJukV`iOzy0cb%30|UcvYmj;d2GDpGs5}aR=Kl+z1s)6x4E?GQ`2$cs zhZ2Op0m_er)`t(E;mHe44JT zzz_jde}E6oh8vYI(koW=3GlTpe0F56tXm|&3L*$>CL-aH7K=>1& z{0~A9{%$CL0hF%<_5TK_{#2N}Bt(5Lw0#f&ZGQ(t<1+!8e#4;YogoLJeh#?2KEQBc zKZLIV&L0OD4CX+>%ib8|z5@&k)8Oz`NyE;)dHycFR~E(7C`OG0Lvd>_yFZE1j{opBtZ4ELdz2YV~G1)!R@UB3>%>8 zcdOzgGzZ&cp2P)#P>dT zkbf8$4tPM^cL&-Yec%b_Lv;qN4f`2rIl{*8sErvsI-d6uTHjs(Ef{2AU|<7>Hv_{1X#H>z+J0exmgkG0<;#ZE z5cA$c+dB==`uI82zX!@8_CEmSXGR7F0cia!4lRETp#6)F(Ee#c5k$Qr)IA%Z{g>b6 z5dUoeEx=@8V3-chZww3zmP6Ff$b`sWD1`8Hp?m?Td<(SxodE4G{Dt;66rlF=K-0GX zv_Eni+P*yi?T@s8+TWn@GwArmNoae+02<#-(D*Wd#uo>)e<1)3ugTE*X##Y-f(bf4 zaRHkCnxXB13DEMe8rt5u0Gc>pU|`6C_OA<8Lc)6q3NAr5yU(rsQv?cAo6(zknlBt%HM>lSAg5bM?=eRf%y>o&O+N86QKUP0xoYE7#2YDw-U6zp8&1jwV>gz z0F5sXXm~Y%78WuvFieGpR|2#>S`W=X4xoj?ptXb0`UJFS9TdK<(Dq*gwEwdY>RtzE zdU*~@k5GBgdJ0ha`2Z?^wG`sN4N&)QfVN)}pzUQdP=AGufnf%8ytNQI-sAxF-v(%V zBmnB46R`2LWsvyX25m1GK*uX|pz;P)knoFu@&(c${9x$#nFCaRs}aO~3wj~)Lg4lS z1H%W<0#Q)=7n&Xwpy^QvRKGAXFgWZ2)f5a2(a`cGfeE5Nq8d{FG(h_gt>T{OJ+6y?B7ZKp$crA2fem04-Q&U|=u=+joG0VHHIFlrzM9 zgD(*N5%75L0fr4O5Pld`{=zi~zZohY03E-nhT5O-2qNDIb)SPFgg+6gKj8#~FAL>2 zyoB(L!1?t6gTWPue||v2I{~ynoq>U26Er>zpz*a1+8#)N#;-0YJVEn$(Dt1=w11@l z?VojlrUGeG`lU?_mb-&b(>Ffb%Q<8M2({b>NLf7zk-7eM

    csC;hLjiO=?hCZMYJkR95Hvm>tb(Zj4{h&0kb;y4HQ@1}0}LOa?XOg5 zf3E>rKW~G^#|CJ6?Si%!8=&RaOKAJW0ovYK2W?M$fR>*<(E4QqwEtcRFp!Jc#Vu=4+q4g1H^B}0cDuRa31uuyC)zJFp1GGIK2yIU?K>PP6q3#ucmd7Wd z?L7skdTD5UPk_oZLEX~;ozGxM0r`i4;RAF$C#cg4Wj!Q2thE|Ed6Lo*r~On*qvy0CitOFvPrR(Dvm6=y<0Dw7q}e z48%R$p!ytC{(&}LFfcG2X@IzAf;>e3?HUOG184&W0|Uc54+ww4Pl$ddLkNF^E=0W= zR6bw{#D6oO`Fq1Mi27zweapzeZ~*H6|IqTT0JIQ=fq`K;G<{uI1W{iE4UYp*{%dIZ z*#PDL?}6B_09|h|tr5aM0Gb$LU|=w6g77aKhPdZ4BZS{@55i}FstK@CJ+ z37Vck>oGwhRnYlG2GE8k1_lOCD1X6LNO%Z9%f|)K_%njW_XOztfjKli6@V7*FfcHH z&K&@!UvEhKOs$33f58XBe*;eM3m6XEftddd+JBzF2$2tk#b+nTbqox=(Dds7P2Y;p z{*izrMEwzHdic-`Q6B@XPagJM~7_{X8+0|Aif zcZNQ2`-g$ygCIn{4BDO#$bqK;Dg^@G-Tfm|#J4c`Z+ zAn^-2rv*H|108SP1ezaYJis9E6k1+`^V0zaf#(pu1+@QB0Bz4ELF4-ZG=7Ys>DfRM zWE%s+VkqAMT3+Qq`5&P9H4Yjd8=(2Y5*ps1{ZSwju0qoi-02e~lH|o)w6Pq&G!qepZMCxt4*U6&ju&Wpw!2Gc-ZV+Xqnh8$j)U08P(=(EQi{ZEvlF=7$fU4ZWcGXK4E00QFxw zG<_93hghHv9bZX+=4a4;5m5OV0OhZM+J69AUNl16FR&G%-=OsoXkQ}8#BykV;{vq( z8wS-6+FuEhFNKEJ2B?1}p!s>hcS!u)28|c6F)&Pkj&Fe0i-X+r0P5ba(DAkcXnAG? zE&m&!{Q1!J0}Try=GjB}AE5jwD4zkUo*7y`UV!=+bS@Rhz6K~i51Rf0p!%Of+Y1U% zz9uw(eP{&vj)CDDG<{BhwioiD=`#RYUl&8;r=S#~z6zQi3Z_8Pqd!c37KDEd+Fna& zgz#U1$Fmt25}@jjLi5`NZisw1l-~etKSV>**8$K5QqcT>9i%)vFd3p=2Acj2$|3H# z2u%+P>mcFh1#Rz5m;_Nj8=C$MS|RE|&0bJ=J(viQUjudT2dI0Bq2@V2<=;TVV*zwL zn+4oII=~GeK|*{m_kuVK3=Hj1_k#B2f`nY4<$D5jz1Tdk zdl(o5p!w4T+8;SE9}<2q!QsDvfdT4XIjDObW<%tkLeoEJe;dgBZm9hap!GKkH2e=h z`8&b$8w?B&u7OlDFg$|h{{>GW{AzG}f`MTIv;yse=6BGcQXmz_!0ihLh6`6fJO+lB z(Dw9(#}NK9Xn8r|K7_9gEsqaC`AeYgNr3XtLi0xh)IK+8ee?k;zZ_aVT!5B$=Fsr| z0A1g730j_fmN>8P<{ebULM+i6@bd`f%eZ8p!`zk_yGfS zJZn9)zkdMQemw?W55~Z7K@VcTAhdp30G)48hxQ*Q+=YZk7qmYka0kMF4CODl4dGis z%@=^Smv=zNmoGr;!$_!mK-PX? ze8q#-ld&9NFo=URm^Xsb7s~+#0Vw|llz$->BHsh$e}MASq5J@-`UFsal;r?}2UOkx zR9~_jVAufVr%q#F;AdxG=zy-bW(KuK*%=rdp!}bp@gbH23=^R0ABIB8n+4GIW%r@u zV+Wx84Qdei576FnXCaduNY)I z1H&O1f$A@agYY*%-CN)e;XjA+1EeARWl;BQ03Ce5z`(E+YMw(Q zME*UL{~;5?p9IzaAqc`h2jw%ULHIpT^8{=l{5Gh26rlaHNtzJ%9)Px2ro!Z*?HfL* z{~W3y{uP0SUx5^auLm7}D}b&C-2^LdRUz^&(D<4F?eE1x`2nB<6hP~_p?m}A_{CRf z`BMNbZ-t=lZ>WQq2RbJNlpZ!f$1@n9_CJ7ZA7GG!@EFN^WE%qmFVsB~ zJR$r#n0{z_DR&3&|A9z?#!t}rplNML%t4f7LH2z^IG{5mLQwVph3xN!%SWN{|G1&5 z|B5F68jXJwO?`0$s{S%G_0Hj_@@8o2=R)>>!`*iSjn9t8&kaR2FDDF@zZES!`q12S zX*#O1M6)jhO}!eLeZSEBqXXFw5BCpf*$Z-fy+l(lk7nN`wD5h$fa+dXH1|lN zh40}^RP};r;bDm8{$ez~3R-xXq47b}X2||ANAvG`H2YqlnXiH7-&i#Do@nYfp!pZN z-whtV_tDIAg6x}v%l|`@=R)&OJ6ir?LbHD|n)CHH&3(&?Q0=oui~l=l=}QqUek#%2_XN%UWVGVyiDxsQIx|BbI!?6&NeQFSz+mt znpd0}oRgU3n3I#A?3|dKk?NWS(TS24jEsE~3&M*sOA?cEQr$9hQbY0~PIe6_%gw~1 z!O$3HOCrTaabjLdQhr5zeqMZDeo1B;#1d$bS@@Qg zq*er{mKZyxq_|clRWihvtuf(9p;+ zCB-E*5u0kb3(SI2bMwnmp=P0knxP3K3WHM9GmA@#Dvd1NGV@X(V$S(_C8-r9PL=+} zo-RK5$=RtX*o-i8aWS-XE=o--N%hH3&rD9tfoKP-1?PwO+{A+T;*7+U{Bnl)c)wux z)Dp*{^fD}Y!2%v7#hK}l)a#lV;9VAgMX|9#aAsAib53G$F*s=?mgE;18~NlXC+2`t ziKkz1yb)G4AQ=O%`(LnDX|h-t35MCvl|%FoP$>LJn|m(-HP1cUT$K6b7D?TQetwp zt6y-uu@R<@fRZA|qN2n~P|1^-3{que2#$Hjl$4^>;^N?f#N^bl%+zx9_yv_(CUA>E z+KXMW`zAOuJufi_8sCOyE~U932Sf5nY7q`y=&@}WT#{H+0*i!7knIK#UPxs@Dt4Q3 zq%^Qepd5(95NNT3RH~&FrNXU%%R+32ddt#34`wXZK)`egrVgAYLlSxlv7WT_&m&bw zaB2xCUx4aYNcn)>Ef)THsLD`FKuk|!Xuxi+p@DxMB$pvvK*(r|)mdZ%81ZI)U!l&DcG)#0gY~JEf*)=D}SB4MIy$qX1mR z8ydLflon^WWEPcFx?**?duj=&m~byj%qz`FEXstdgPLV%4mKeeT(LmwdMpMR83(79 zz_Yx6X^DRt9>qqUh}wjZS__xVVo+sQb26(^19B2e((;RPT@#CPDxqNp4GSWb`52lfm1gFo#3$$H z6=xQgq~;}~8DwaRun*D#!4jl~rl68DGdZ{*GY_oD0@OSR&dD!Fb(NtZ#J|BMiOJc< zeyK2Nlq6~nZ4RJnMI;mx&yv(46Tj4o5~vCk-G&CimAOgzpx`M2wbIKHb23vBOHzIF zQ%ZAEeKLz-y1bzwh1uA$bWbgTxD%TNrjALVUIVsJFa!I`CAA>G#3L~;B`4Lgv^X_B zIlnXyZYio;ErLr63PAN!W_}*D2sSiB5kqK2)oBd!iGLczSH&iope8joC!wk{G)jY3 zq@YNJ`VJNj#wb;Rxqn_zDyY?s%~Z@H60dSgNdEFoEGWp#OZQ2v%r7l5CB<|+icOvK zbMlKat5P8`R*dE;gOH-cex7PxZRNPZbK)DB|&KuQ%#;ENM15oCGv}vF|MNw`9lJ`xl z2+J%gDNW3QwtldxGyxT-i4~#6sYO^-<8_CTp=WVOQE93hD6BH`(orqKtJToNvlx;d z9FsvsBh+!wfHpD$rA$ci2JT`frxujt7r_Dt#j}RUrKbrf+vFFO6obV=NGkajDEp%*{-8%*)F!NyMfW$>AWUKyx+BAu#Wm zfUWgSEJ@BtO~I|s& zB^72oYH%8*rX0G$VZS6H`)CAO*Q;a!zU@4ue1@ zq!t%@=B4GEI^$Ai=~k4On~GnJg-c>dB7P+pk!KuOnpl*WSCW~R8jxRr%_AluMTuA? z3{5~yp@5=%P-geVr3R8Mz;!e(HRvTFD7^dO39kJ- za|?2?yA9qv^-Zh{N-ZfZ%JVDD!K&66QlfZd<{{d&&WWH>3co%>q#6hu_>S1kH#CKp zGoW$3w* zc!L?#(Ety-Kr$(62$}ol=jE5==Vd1QCFbRaWah$*L{VmePtwp7T(LT3<|P(Y`XypF z!4T9A19>pDxEQAz^UwlNABKQ3W0y>nI);kpn*83Wq2dU0@5r?!fLu1D20`$ zK+S=s1`F6Ap;>5Nd1f9=7R5^-55OjfKrOKN%FNUptSSvn;o~mpsU-!OSQUZX5sF(X z1TKZ{M9a{;%)-)CgaQ;-VhMP-NvH}jJ7R`L;7$y9ekT>Hqp=NLg9;oM$fOWOK_+J&2NBOzu+-fLW)g5V=<8a3|Kw7(XavnQFU5)76)e}7GbyC z5Vf#}&ZU70WVm{0R6r{a$YdLe0+bLoGK5UUfSZhv<}XMwHiJ?0VGCqX_tGshFS9rU z-7$u!eQ(g9Aeusgh8y_j;nQN|;$ma~DMJG?DvOb3Wv~=}My9@rl}V}Kp zpm|Mf4m1l&b*)HE#wKM5$pPRR%n+1coJ)&}Qu9gzu&Xu(&*J(91o?-!I)`905L9>s z1qWl3vIJ{(4E70v%0fK>Nwh9TP*K!?z*fq`l|l_LG=d~&NJ>VRMPxF#42l&vG6QzS zSaJYdAs9o%mT9TSvl3xT@iE2Mm^$Ax2vm7*J9+rsE2^F`5 zM5=Fo0bB=)nb0B}+%|{yY<&|EYN4i>`=*v8B8#J#VQ7fd4aIH^yn6|khMJ5>U2qu` zvvH&@xMHX=C}YTQNfeWi(g>u_0#^nz12c_aC_zdi=yK3(Xh?iEgeisDkD3k9WDx=7 z0+T`U9*%&*t{7W3gqaF+4Q4iksX(z8e>Q|^ffU!967Ia4;WkZ+_6f<#TLzr5a>9A}F6Gt%vH5+18 zg2;w2X{gDF)CG4rirF|)7hEya7}RVCvjfE>%xnl#1~UUQjbK=Vlt!R(kR>GfdCbVa zC#Iwn#phv@DbB1)MUjDM%}fCcmKNuvrWP>7L#g=q+)~g&7?6uVtJ6SqQdMeEK0|y- zVsUnSW?ou8$ZN?N@t`GTNr}a&P_g(Z^q|K!wBc%KjHVAM^}!ZtL5EWr;^B+25FQ3C zP5?Qoq&P7zK0QA^Gd(ZAC^f#gGA}tk2{iN15D&_L4Dl&B#g)0B6oH!bkk+YymJov0 z9${03=#@jl1GGvHi(v-fRYU$opj;YIM!+EOYDw3CvH)+aD$U>n0lBHU;B|92l_FeM zTv?o4lH(fSotYI-7LbeGXd^?o(Gc}Xph>1w(E3r_nhZ_gn#zkZOH#q>;jsD8B&amc z7o1(->p>vOprx-xZi;DqMq+UWXiWx+jE_lDeo7^HNvFB5i)p-bNCbu&Lj#ZuWLye| zO4Q20+&MotDKjrM1wOV7S>^>AQb1p{2aj*jOS!90(q!x9v6hzQ52-q0Kr zWqzrtDUiT+Lzsx-R3ihB3yR88Q=olfu-T^Ing`7Zm}`u{EqG921X@aft{T#R@yr9S zU4n)Jw)OSM+0oDtJiQf^T9BAogf(>{t2Q!%s!mMtF9PSkP;jf5phiPT-xriZiPT{p z1f7u~=mR6D%HWdxqEx~zu|!txm|R$zNrWzQVig*iK^7@E=jRod=7LA+ae4qXSr{P~ zImM1;iJ3W|MS-wLMpbO=SqzEb%%mJ>K?_bs*j0lDOCgC8wC*@R&!aRw6*SZ4o1X&O zZvl>BRP$kB3UL!iZE;Axe=t_#4QX6OqZS7Qm+OP;XVlE^V`vIme3AxUFp5;;VBZu1 zsZ&wH17l%>X)tUa6|@k_GsQIvn=VAVE;lt7v?wm1EEAhLl%`@)az+uT*@RUkiixNS zp~aS=DI@{<<-->>g9=gPVQkl2tY#w?$E1}MmF6Xb3Sg`X5xb>8P41k`ylimOGZ~B5 zjEsUylZs0+OG-;XokGy$URYvIDWt86O@pBYNDX8eWRYiHa!zSVs+n7UQEp-hs40V) zR1FQ0HRQUIpg5Bh#R1;Qq$p1!MKLIX%piV-EZYNTOadmDfC^KjN#X#k!D$In<&&S6 z4z1?EbH!Mdg6gHj6oi4`)@};+KnJNUPDQW7Agw~s=mwUQV2DWM#U({~$pw|J0m%X0 zSRIX`G>3SlpfpRgso(^K!vRL1Np9HcD##`>>@Gzb=rc6P$%zMfEv2*olpnB#fnjcH zZhU5OJg5hbOAU(W^Kw!_Yu~Yjl97>fVo4%s!nPnIGZ{S52(FQFnF}2e1Fac1#ix*9 z0ZZI|C{vfBM9{i@zhIMii-6Q3a9_<8yfF$h6I01fv!K+p%$yuh8-NH)k*4ZFJ0EjF zu~rsr7>_ODP$MN7tTq{!TF{C`@GeJqAIz;RH#aFDH`g`T0K4(Ni3QM=qL6wT)c*;> z<`7fg!~#$hB6cNuCkH?j!YTj@|D=+{%sl8kBY6HD)G@}gRMFMdwG2z^Bp@UnY9vY} zXk?OG2_L8e4Sj(|tBOHO@$i2!t8v4Vk;ifbOmn+ zMfHrCYeh*>VsZ(n2=mG<2rh8N<}@E;6G#UJHeCkoLF5-9@4bMSjN&JZv1ah@0xSxR zL9_5a`Q<*TWvMw((^Gvj^S~?nK%;F;niW1K}r^=F4 ztf~#Mj9wU;1mqWhO#m-@h3SJj1J+Xn_xliyMdW@Tva7LVE6@sH&?qfr+yokQsKH?F znU`DyT5uMUUy_&u3KQ(gTvCZpMmR~B1>_f$<|LM+g8H(cEg;wv1t^CSEQ*7TK;vJ2 z!A9|h#-JDg7wn*Q!B8Kd1tVzvHY5}w83ZZ~UPlYbvmW4qaL|&nki>LUL%{nI{FAa$ zlS@D=?oidBgs52u*AyK4|;i6FgAv z3OY6b)O^HkouMV9LjchLS_D9hCKF^Id14*60{aOi5)94JO33^oMCT19`cW5@I2(bs z-hzf=K_@GKVj4B}Fvmd%>Oh$(cQz#1d_p=9qv_zGa)|l9;DnCpek0?M#B@;NMUQe+ zZz85xVQCng7O?hGQA5)hzS!Cs+@;47HQ35QQ}9SqYCy7Q9(Y(6>Kv3fMa+GJN-0P# z^UHTG$uIKEay1Wv?0F|qBd9M$rq*O~?S!;iL9G?El`Mt^o++ReJprHrFtSaD7HfuP zZkeEwa>V{TS8|O6$Gss^dw^_{z~uwA3__{%@jD55=^MBt2W`Ie%quP_Dg_@X5|9i{ zH?Y7%BxBHC6R0F=YQ#D_18Uwv=Y0%~VU05<&}Jz}Sqy6t!5TlHpe3%JgJd%lCm0%| zG%{Uti82k6{IDD}f#h~qSL|Mf*#};?20b&z*$AW-GX2L8pP8Rrk^`DX1vkgzlQXj8 z(-Jdt5Yw#1nd!NS#n~VwpbZfW@uhj7aT|ts*a!|t20RCw3p#EjJ}ET~Gz|+`^S}`A z9~@kenFm_I3K_jcQ=OPrl3ElGTAqd`0W}69gD?bS5W;OJT?vo@i0S)c&_1cu#F7l~ z+&<_e2O>*01ISu#x5VNSP**B93#<>8&LE@M(1pv8B!XIhqN#_Bkwd&rgmQ@S0Y#}G ze-feI96YEVkY8K^8LUapCPI@LL{m{J33?#@fGp?5V+Cq*M>~rGG`Z;pO7d7%h`DCD zW@SNw8owEat^q`t0gEnZ+<-@KosC?fHei)Cgvp}XkJt_bT1)^MA<4w%OiTC_d2wbs zXe0qVW{X87-b&H3ptLw69+X&JgS@e6c5$&tPb~q*pDRQj>K7l_0XUEr8*Kgh zV<7$l^-DpA1Q{AZmYzdIp*o;JVQ2<#(tte!8e#|MVN??_H!^?{2yqGxp*EtLXbGE5 zg{*;y0xkY=4JgY56-?j)GA%O?#KBk{15Z1!byA>30@zd{#*%UqQ_3=nK~pdgbuhm} z&vpTwHi9jiqAE6m1RvxC5yHxi!RZcE*x)XmAQqs83+SkZqLSd!B+wf8)MC&%A;|&W z!G`g{#_^e%*mNNLS)P~)-U^c$fK8#1A!HY;V^MMjsFCbkPzr8BV^fQ?+$W{9z{nM= z8Y}}Vpi(QqI~kiZv8gt64ZxuqF#%It0-dSBYAV9>#U(}f6k;iwuq0o^+ziCpyi(92 zA*?o=f;R#9<-4S&7C3?SGhz3M5yIl)%-n*URM6OUNj_-w)H^u@z1tbUL2AjlV*J1?LQk0(y(gt426@Xo#A$R~g zBp<5IyDS%nLPRuV7K2Z_bH#2Tl4BuV98etrs^yH}EATP8Kgq5*3_~g{K|5T)X(`w! z9$P3`_!p$+fqfC+oeXNHn}9fwsa^0S5H?Ll;9ddz(1O$y|I(6z(h^rlEWip8jMdo| zpmWB+hl)THqULXeqruBap@yNVq47j7Wc~=Nk;*eqIW8MHbNY8Nnrqc`1oSDQ-B_8No|@(2Nf@XPbEzLtPwHnwJM! z3X4q@VmcMHU<)*Gh}G?g2ujY$FHXg##?l!i14=>IWDP+F)Odgom_eFlgt!QnXrN6k z$Y=nn6h?XipBaeQkO)zYnqW*li$TN9sgTMkH3gfqj9gscM{0s{fSHR6+Ez1AJ~T9S zaX~#65Sx9lMfAClBOD={vLFg!K1AIz=WGOZ5)NrYurz4NGUTMtcuhJEsRnq1w4yJu#j}Rq)i}2}9kWFCF*1SdY6Oo$ zrh!I({PLm2ZBjsTCaB0YG>(riON`ISEG~&JNyK7^WmvEuM87MsT6_%6(Cu|i!fIJ! zQL;%Iz!fiYx#!1kr`Wq61+!XmGs*VJoO<6Au%EFM@!sk1orNFG@|% z1aBY!t=UgSSw4<>P-HrDf)U5C1BPPtPyPF9jXRfus|(Rtf6Q#H8Z|(GmKhp=j(dO}2LUdGq16MpOm_ukyyAG!juD6wRLy8EHB3n?Ndz6>T967-2T21( zsi1U+;KSq5%p^W7wIn$sJ~0K0tg#V3Su>OPocu)W+E64wLtpS{fF#F)WVirGHXex& z*+GIRI?_{1iVIScGt)9bdeDk{V^hc!rlVi5r)zO?VnJ$fYGG+=UUF(NsD}eN_SrQ6 zi%vsxP&?Btvm!MGF-rPa3*y}j0FoC-XT^+2MVB(ut0O@x_no78W8*9KBf{#&wMglHJ7#V^b0k$7C zVgtOfB^z+4zyk!V%@unRKwryf1X|eu@e8PH=Tr$@(MX(bL(r+12;Ht(Se<7H@(ajx z&@ryLnV@C~W_tE9M5G1q5l5gkGgv)~G6!L3nwWyJl-e~nHwn}h!L-2;RU_!kYtV@k z;FYtW0d<`E%s{7EgIabW`H%&2pza|S^N|jbG&F^bYJhz0U!Ip*1m64)Vx>6egBHJG z^BHJwziVC@F4I9P9ieBVSb%9rK>{jLaO<-0$xn9!odN|qy$mwrj??_ioK)9}%;FO8 z=ngjjA-TY?0CXZ=Jb1qxP6Kli)4>icGBivB6;6=-aX6HtjIDtBR9MrJk#TTFerZmM zZ$9K${L-S-kbF=#nix}|%jvLq4biF(MqgQZir=!&J>)k;1;0vJFzSx z#;YD}4KeX*GhK;Sn?!XTB4l*JKt|+i1+T7e+ z6kV_-WZ=Uq{fi(IZjO17li)BL(rCI3p(FYbZCI_tZJTGBE4ToM*@o&c*qj|?EfDl% zZBSZ6Y1pIcF@nlL^nlh65zvQ{6^Ymd4~`I6cw>w*Svsb`&JfCkcpJrh)G8gmR2$?c z17C2`1WhZr24rB-Yh(g#YeJUgKw=sa$KduH7A@e045D>~MFn!1Y6(f^pjtJ+I~k%F z>QQ(S0iBo!i!7{314WyWVJN5@4?0W|;#^3=#F|JllTfr8LN^!@p#vp^eGH8p!S~ZZ zPFHme0599G%*aTBnvbFybc=@xc#6ppv?u^E$7JB*0y}68>{@dd7qBu{Y^E5RfG7RH zGnk-bP(h0%kj4B!tDJl?4PAXQjSO5}jRQ(cAS#V`l5qYYvXG2R550*!sl1#L*lJir^2dZ9HXYz`QkXF!{fpsQW-i%?JegeZsE z207#lJpAK|Dua>TKsUyK1JM<=vx&Tx2h|J<|2#11TMTNFx=1pVYq968|mg5flFK18M~mt=#pR~ERg`72LX+ggNu5% z{32KzBp?^NdZadnp5^WV4xMdA#koc!T3Z!D!fLzdW6l}i4pF0fk zr7tp!Lm6d4&sf;ZGsKY!pcN{(K87@Eum-o038>_R?-++P48esPXzgP_Zm`N6=$Y{rprL9N?kJpvas5Lw8JhX2XxdBXdx9= zmEh&UNUm|rO9{y-hPorzAReX(w&VAZsJsp zGI9rBdImWv60~>-hb4Hm8M+2w*M@w659rJ>`0Y$?0cF7k@t|FTpsBXR9MBZAii=}V zxTjydYeYz}A2?gW%35g047@JV(j_&iG#zwch--iwXneKG6`S zjtFwn7OY+28sJt2T22JMgA!r^iata0WXS2J@nxw+N%_T~yOzMtKvCsmWDMRk0czpI z=a-hm=cj@0p3E<*gcu3+pO2wwPJUi`R&GIjMSf9yb}EK+F=Cm0d~!(zif&`L0Giz< zSQ?7pMb8lJXsXR17rg|-t_p<|*N~nI*k^FZnr9=8vmhxzF%Z-}f-Db4S$&MN?*X;~ z-2_Xp>7cneaGTSRG~I><&XvhIso>a!=qGl?1*l$wciXVK%+LU~uob#x2+~P{ge)|q zV29#B`k~-~evrXvTb?qLk^(^Y+<}%Eq~w=FOh5?;GshCpv3H;(S%yU#JgpH7KZFiB z1!Gfg2wEKln)z_aOeLt+95TB{j8YTOy_$rL^f5xLCIaUT@Vsh#ZYdU@8Ja+PGLR() zSe5t~Ar=*ZjRR-3WYDFjFf&8K;5`|%t|mBUVUcA7Sz884_K@TPEp{N2z(L^7D#~sv zh?8LkKsV;X&acH{L~a0T56r^F1!^7GB`A^ZV^NZk3U02T!Kl;G5KgfTGxVf3I4O+lBgg7<$zlDKPb zu3vCGEFq)%6{TAZuI}N(mDoIJ?&}6=%VPS(2Xt#00QDL$z2{?O1ZwuB78es%Yh+ZCks1KH9|v?pAmW}GNc6*eY6w~)iCh~Z z?X(8l4^;>|I2U@U8z_6?Qt6utK8qT39zMu$&y*aiIpk^D#6{E~&sRZDfqxRKYL>Eiw=tEl43oK)nTcEf(k| zDP$)Z8bSwH5$yz&f*ZVT4Hl*-{>B`f1off8Z4Sr~A68vHhL*?;prFL$)R6oFh{34- zGc*U?1X7V#8lRR}ToMmDmK3548qtPEp71HF)D+0LE~G*LrC*2>458HucmpeFR3HF7 zccAp?Py&V+0%bS1)U6dz)pu0-^Njp749i5IokiR?ljv=9jJP7d-$t2dAjR0lZ_ zv>hMQ%P7wBF){$>?3DOi(4ADECOY`$DzMckDvdxhe`s5|QCda0xsVt`(dA=g3Qn)! zwnlDZWqc9%2CDcx(BcEICC~`=F|Ayc1v*Rv5lmDt5adn7nST^{)6f#?Pvj^h(TT7T z4OssN92JI^kP~vDhcG}wmKp{d8G9raL(@wNc!my|iXp`+dOpGKICIe5#-R0)l`xaA z>xO1#&_!ICd7#TmK^t2^%_mU41D*5$9(aP}NYs+V(6SibbAxaF#ir261ii%%Is_cN z_Yz!Ipc-pr3|Y0}m3T)rr@#P$i)S`E+G{ZP>`rc?&o7#0UBB`fEK{1(C#A)hZwE&+IQ;}H$32&%QOm&7v;L#Jm ze9-I{Wa1CEp`hfSpA6cM4n1cSsTE4VIiSXCIP7>*qO}>Cx)%wi`mOd=AMk2yn)w z6s0sVGE4^F0S#FJ8K07$R|2}?4xC{^!qAd1mU&UIJ5fwTpKdiYLApM*6m;M^D52vr z3Yy*_BW{rMaUcVQ;8wF=a6IVdPVg~GU?;*xf1v8Y=iLya9=+uaJ}?dBF6bNvtVIsC z73@c-!_YNCoCurxAYL2TrG&L1GH(&K?3`JN7DLcI*9d2$MGazm2j~U}lpypmG(&E! z`sL@PLgZ15Ffs@z%FInHs)R4u056&Y2N9}5BgpPVB9t1M!w058mp9`u5P6UbK8j^% z=7_p%8d{E_PF`WU&d?BP^bw0UeT z#3ePaI5jvYF$o-wpp`*pkaL$@eR9oAO^wZ5eR53@`_^U%Cv&?Se&dKsEYz%Btb%8FAD=56lNXlSjT`eP$xZ};8}TOTZx#ogj(rXRFqf=+J-@6 ziw)uDx`4)D@{>W^FsU54=&8WS#l@AuCtk0(q)5-u!VfHBRCEf`QY(d(I+nImN3 zOd|tx429-q7(!-d2)%Hoi6It+rU-?m4DpDg4$MrDd63HrQ{zFRImIQ3B`ThN{w}T{ mZW<~Vg@@rK6S!@r2&OTDX=)5tU~G*4m<7-&P~bcCj2HlrTrgAs diff --git a/src/runtime/race/race_darwin_arm64.syso b/src/runtime/race/race_darwin_arm64.syso index f6eaa62ae3a88744f0f79d1ed6e9645909d1110c..207099eb1d0808327960892de7712c7845d42337 100644 GIT binary patch literal 438560 zcmX^A>+L@t1_nk31_;5*z`(GAnSp^p0VKk}Aj!bMAOYe-xEQ2H%_6Ya38qEgbgC$<{6rSxD4^}sO~#37ovLu zSeAjIV<9sGvKf3(aTpaJpPZjpjPNkJc?I(z<{f})uvo;*0P-)Ci$TT5ClwbXiN?pf zIEFYP2_!*WQy@MMF31LFLE;vP%Mc%*l30?65J5N3U_Qis4G9o6KNdm4&mxkQ0o|`4 z74h-O#U(|VdFdbymiXQ9A7UOyJVZeSGsL|R9s`EoLE)F1o1X`hM|WRAB_!SLKngU7 z4Guu`6r;U|aHEsexJp=oVIl`(Lr^>e z!$%Rurdf`x3|qt)7$%%xa#d72brP4&=7Qji2-aL$SiqA21}T_hs>g@9x)5A zddw`c3Z(u48^ab2jv1FS=5GJw!G7&ihws}@94!n#(A^F)hme~@85kz4AkiNn_4xd; z0*5~s85kxgGB8X;_6x}GAa{cNoAC4h)(6bOU_XN53O$|_1Q@n_W@cE0?)Q|w_#g8b zI9?wVWC;1f%($waiQy+BBf}PCzjZJ%m}LA*xvas;u*HmlK?Gzcp|BBQV3^PW4Vw%$ zh<*-EhAp8)>L)dvK<<0N$gnlzU&3Wh28Icmj0_XCD>Ht8!bqEuVM|tB$mQ(JEQ`|& z3?>>-aSjfKElinN7WNDbBCzzr;n@(>!LXo+k%6Nd6xPV;0u-ji_#NbLd~w`?7RThc z-Gdq8c1b*L2c>tA|3PjBr4eMmfbu6OKf}`117?v`kC}y6A*%uT7o-LjHZZjybs)1} z{{JrylVf6FnBc^~Ffp;XIY^mf#--%B+dnz8U;EVT`}Pw^?SE&ci+}Q&SN=+8S@|QL zb>+8kwv}J}*;oFp=2-cKnPC+JXG0Ju-9qh~0!pj$EetR5>bLT8khK5Ohm^oHuFpG9` zvN~99Wn-Aw!Ok!-^Z$R-1#Aoxk=^%|m0`<%C5Del3=AP4^VAp^L_qrF88}`a0*i@u z*E4gxhRMq@Fo^7DVuY*bXJ8On@vLf6=kuybTn!8pvzr+vCa~78P2xSY#(~v-trKt4 z8cjyVkBR^PhwNwKc%8t+5VD`E_EQ5RLr5kwM>iJ(M|bz<+DY7u+^1K3s-2|J>hQ;* zmEljeBE!aoP(2427(z0$Gb}hWG%Pq+879tW=6K!s|3BEh@)@QU4&n?yUvfkIZ#{zi z5B9q}!_OD|4nIBWIW&JWJN&F?7I}Sui6I0%9e!nISOrUmyV)3ihB7n!L{59ZaiqO3 z%+jlVF^jHR@di>Z|E=~|`NiLT<+pIRl|SNLSN=+OS@|d5dF6j+riq}u2r6&4GBHg2 z!7RK=oPlA&cP563|Ct#q|Fbh#{^w?}{Ljx|`Cpj9^1nEP<$q}g%m4BWmj9I*EdQ%B zSpL^$u>7yjVENye!ScU3gXMo~2Fw5U43__$87%+1Gg$ujX0ZJ4&tUmKn8EUYID_T? zXa>vw@eG##lNl`kr!!do&t|avpU+_VznH=De>sEY|7r%y|Md)(|C<>s|F<(({_ke6 z{NK-D`F}El<^Smnmj7onSpJ{SVEKPBgXRC_43_^_Gg$s#&tUm~GlS*-?F^RxcQaW2 z-_Kx)D_?ee|Gx#4XFz$76DbewV(OeF$@}MU)4`xI2pvGs+ zJP6VQ%7dOrc@R`4Ao8H41p`tZ{5697FP~v)!2r#J9Q7QUKbakV+B1v1UhwQcMjiy! z53oEqla1l02s6XaAIu`FzA#I!GXMWy{EPp-m4B-lSAyyc^!$sgcQPBpPf$Jgx7u;# z7ym=xHYx`Lla@TM!>0!f3?YkH7`D7%W?022%3$Hd!tn9n|NkKh3=AS(A8IFYFmQFt zGcvsHWM&A_tZ|sEsmQrX(~)zPW+Ue+Z&rqjub3HD)gNU1sLaF=lJ(c+vNtQk#GI$K zleh$Ux)pdi{CF7{C%$9mS+#)CZtVg_`?U)g8P+afWL&$Jk!j*NMTU=#|Nn>7GxEF! zwR=5P8&||La=bqL|9=RmY(Vy(2t&i93?`9o4ps-tDQpZASN#8P+JII!O<`r&GGB?| z<6{Pf5Rh6#eh}%FXB2*&39g?SF3B=5h|EW;lRBPNP2y}|n3&bXF!41r$0`Tb`n68H zht?>t+OJjOZCaBJt&`?6alCe5VhEYfRr@J{ks$=6w&PRnq)aC6ZY~Dy?rcVm)97^) z3j>2lW)@O?#0062E6x0-DwsP13EAYl%!@0l6bK44~8 z>&U<$GSth*|A!eY{~u?t{C}Fk^8a}T%m0@dEdO6;u>60U!Sero2Fw4C87%)lXR!SL zn!)n_dj`w@pBXIwe`m1#|C_<`|9=L{2h0pVL2Ww@Mo8Po0oL}BclhbS&9LPKyTi{H zOblCIa6A0u`0IF?<73?X$Zho7K6!4xKjiSmpLAEz;OfZJOqm_)&88PwJSrDgPXRw*Z>odrtEAhn>h zyoiM%go8n}`#uxLYbP+f;gSslgGlFJ&&!&wwUam)IlDzz9e$cHGi;fv>oAD{i#tJm zMvfK+gj-?mW+pN0WZ-nz3G!cp6~oUI z1_lvfhK5T?INElgd~}LHJ_5DvK=}yNwu9v(PqXq#b@{h%x+pz<$6sp{dyh)c^fk?Y8oZzw63x;VvuxA7%u%tu+21(mq#a=8jX0 z3?>}R4M7}?3yL^J8iKq_8HBPJKbU9zb-(Q8TRVx1fvejqGvi0Ls>7r#P0ra~h7LPl z{rhhU8sh+!#~FV;FLQv>Sw_Z>Oi=m~R)JiVkytc zQ0T}A%A=rh9fzL}l|f@T4VOUuvIp!AKS5>v|7Heo+<@GG%tszu`pnF@3KVW2bD0E~jim5GV73A_hjzZpio+WNZs0&tbzLB=5^m*v!Zf z!U!ERQebER#qX2{43PE>#BPV53XBdr8KHH?4<_MmVFrc?8B7kAE0`Hft};3Ngz0Bs zZwX=osbgT60*epO_zwpI!%q&`h9C~+1w|{eGAuY07%VxMT7u+3{Y~bUAO;4G?)gRv zJLd}t{G2Z)@N+(&z)!{oNSXorL$V==lW9SbNT%iwhNGx;3B;a;OY^fJeOLK~5+6bR z+WAZjKS6HPU}P{sHiIEE^9Kim!%t9M2uf!SLd-vzl^uRA)@In+%;fOXS%+ckkNb=( zMU)wSPG@3()tfuzc^L{pbqj~gflHhWO+hb}8CJs5IVe1(7#c1~Ff?3}W@xx1!q9Mu zo1x^A|376gb96^Bb9QSsG+g2o zJ@84Mk@NK-0fvwaWrmCLj54nuaWaIIJ+_|+NmmYFcPBG4gk&&EbaON^Tzsj-aPh@* zhLzu#89;d(o}OUt{ldhsrSn_eWe$cTmoykTx;b7}Ps(DH==NgdIPKNQaFLUl^EA(& z_8?70p6+-?&esQJ8A39cMNV@(w4d1d&+)S6$GSX~I;JFzl^RI)puxX&3>1~7AXzZ8PF?I#YmO=Du%a^hRvWln}8mpBxcT5c$R|vI^uz=HLHAelm-#%1{QiL1bPZ`t(19gRv>71QZwGF=$A*g4_)a*NHFg zGl0gYu!iZ+5C6Ale#aT66TxB1(t!w55s>>OPjfOh1%cWqn*Wi)RZsyXTp8Z|2hD_m z;}JHt_HcV6xEzC~0m}{s29pK`NWKB3RS*W}e@%u$P&xABzT?Uh3=AQPpm_KbaGArF zK}g<`p>Qz+L&yVYeg>JvzzE3?jEvxV0c8FtFoa<7yRW%vmi!{=mVv6N?Iwv=aOwv^{&wv^{(wv-oSwv-oT zwv?A-wglM+&bz9Ra*Q!E6I2FHf!N`&^8^Ef3CMm>`xZGbe*e$3vYdfo3p2CBP9_Eh z5#=AvK_GL4c^iU+nHCf=WETH;vKTT(pak_FNS-6J_y@D8!_Q^~2 z<^TUCf2+M#e)0EQ`7PXI<&SvxmA}&6R{qI%UHShoWE?3|iQys_!;wp#oSfatj2x#q zxJ6EL{%H^5Wnd5iNX>cJl z4Wf%H&T9=~fy@t0L6=MX--J`H5s%zLwdNpZsF}@m4wEs=J=h30_iy!na6QZbNy8vF zO!?0Y>PIrJ{Nm5F@^3XWSe}E?VJEnK0-0Z$0_u}=Fgg6>l!wFvXJ+OOdsc?R(@YE@ zu($_>nJA;f&&6gAKb5%|wr)m>->pp!J3;MEP`vHuVkqQhWC%evk0Ud42WM?V5JN4e zG)N7oP1nif@RN(9A&84dS2rjvWd3_`0@P*)^#w#38iLFi8iMw#F%+&~U1`lq3|>Ne5p>TT96+> zdG-aGT4T_B9;95g^nm7RP+A7X0muvn!TC~utDRSV@poGJE!=VCe`ZK~9X+1W(w4~o zX2y#@;+a-{3uj*W#h+#6-)h#Cpt&p1_z!3tbpeyZ&jtpDtqYhTZH)z>`ksa1qC5k~ ztA!j4A)tJq!71GRikaaw2P0P(C_hYP67JUI6b08knv4wHnyd^LH5s|O6d5^A!_q#e z%mc;Y12zV;jDLte1t<(xLhB=uy#6u~R;R zVUy-FGJMQg>M+UcZ_#B3PKRF&jGn)^4i;R_K3H(sq0zglft4X-HJiiF97eHIy@Fwr z_A@ek%w6g*spoIelSyPs?o6F(MC9S~x%^{T< zKTfbQOkBz2@Y9oGDQ>J ze0o;+7M)&$~8MlnPFmvFr|@N>cc|Ki$=9H;69 z!#**xfW}vgE}vqDs7?6%KV&}_!_S#WY92D9s%iN2KV&~2!_P@*b}nRQ2ssTk=fQ{n zA^X`FeztC+rL%tAGFB;>E$R*{W|IU|B%k__1l9P7(}#is9E&=e+cL6`t4o>)M&n{-wql(#b-|Ei~8*r z3=AT#KmXsNy)*anD`u|KUaF^OWqtm?)$?=xc3gUsKK&2TVqg$C{R~x~*R%gyHJ{hphZvzwPb+|Ki<$QT@U7_y5+He{lQb@z4Ju_d#YO<)eiR3?bPt zH~#(~0-AS5cb7IZ1K3^Sc+v{fzyBdGztwL8h3{%c29$K5#mKOgld%G4I#B-lKV&7J z!%s~nhAr@X3!WDN0_d=2f6|OrScC7P_8#{brkY)(s*o>%WIG8oMIDezoGbfpxH+fcS{K!;tUJ2^s zH-h?N&~-Z*at=SmS{Z(1$brW=esZw=*bb>@MZ3+Q_3SDxNIh%H7`Q2u&Ee-MCWoKi zjH2MO@c=(V$SF1izd?W@sK z!LaoN6T{DwYz{v&wHdaaMh>4INHBzS zAl1ViOd4ICX!S5B!;4Fx@BxJdha$s8P*{Mhwkl&E$`0xLtvX>hwk zlwiAqfrTODG`P(ndJ5d;;A99n4Q_Kl_zYaAVacFET3BXkBEoW|4kRo!wIE^1sg1wQ z0m>8JAO3IkUg|KZo{{tQ%lH37xDOUw_BvQ_xt@_LJMsPhkh%Z=i-Xj4zelLkL{qo$ z-T#ouP<5x@A=G8QLpAT=+y5b*P<7l$>Q=t}AHoT>*Pf9pTk-Axka}o)XU#XHHqkev zHqqDrAt#|~c#zbr{EE~j`uacQ0JKf?G78cbdKtyA^Ci>JYzw`Jg0zKRL_yj@pZ`JH zd-(ij3T@}Dg!c77?L0Ath9C=uhM@ausO`LKYz%@cm>})E9Z>b8w)4ao8YZ1oLT%?+ zgmTShQf8RQfuo(rv6#UU*>5YDzWrbs#__flR4*aby^I13A*+R}te$uALP2;n~Ve+!oo!xlXxd63=~A%>9E zNB(blCB(2r86=0JPjKk<|B#oj>$gwE*Uo$MKcw?e{q`OLYE~Ys-`-3>4d;RS?NuN( zP``rQngU9npZ{+;#m}$>)JKE0MPdE~h12U3kZ^JZ`30&MCJzcH?Guo2vPY5!nSDeM z5{6nr&@jXi4odI;hj_lP-`)>$8xA!|@BfFaJW{{CjeweyhwHc35>TUgsD671s9*8` zwLRZ;|Nqv^`?%ZlP4^)EC+=-%`nLYxnz7`zuH?-^{v|Se{1I!-1-)6M)fbT{l!Ek zh7fILNZIu8{QnS8``D9{Ve1JlhM(qtQO7?RL1Ph6wTibOYF~0d)YgO4Lh}VE-7jHg z2wDC2{}wJ5hApo_Webip?eyn=$jMLj+a7_`An8wGW(eW_`+v(RW`-@#Kyo%pzzXWWdMhlI!F$Of0_RN z5Al3izYV?5e1w%D#G9RAixwNh7SOl|uKp_%D7@d*Z_{UB5FxeC-2C)^2&mtL+-Fu~ zgVb4GjQIP^D<9WybB6Yr6*w3|PJrsHKmWx^b;IKqm~H^2%PjC%7k)QzKCj$}mxsf#K(VBZp54 zpz#W%{_P4Tjjokw{o76g{eKZ?|Nn2b%gQhQ&MUu#JFWZ?@3`_;`cd%sGHhJ9jES@R zB(yJdGKyj6NwmI@Ikdm<659R;^%o=<8iFht8iM4}#)T!=83aLd5}GnRln-}EE?2uhfiGI4gVgof$LD2AOY(ZbXW8m1?qVFU_O zacCdxKUyE`I~#)_Xr31orZ=GKNexqRhK5Nm(feSLg!^DCpkcZqiecvortd$t{l`7N z1qxRWo*&!4Ff*+Jg)?Nl2{NzqjhSPW8AsS=^!XgnJPvG52R5IR!BVkZgO?#>6?ptf z>{JeP-p6OD!z57NPk_$*oZw*ySp^=G!mTC)qy{`rB?cbX0?iG8%+O|GfRAyUWM&9i z#ayu+Hr}Ag$mPY!#$YDFz#xJ=w*(sFA$D#FG{!^9ywU@9(&m*qc@gtUEBPVwO5ph= zK8K&20{F*xKyyaam{;QdT)!O_K3uhm9F!F>-mW`u*Qz+W-IJ zr_jV-{rYbLYRALMp^9NTKh*_ogZMz_r$BQ`I-maI9J_Y<_&)^HKZ1>SJ3{B6xY!uB zg65~%L2W4L99AM!P75T*#_$u=KZNOPgvxn=F56t(7sAsZ6&3j|3l0f7({v)8Mf%` z%)R`Ynfr9M>X}*Gj0{_~|K?xLHm#kM&BWcE?dtGT2RyFH^E#Q80X#35$p)DhGysJS z+FaABr~kL&vh&cB{~@5c1#h%|%Bjb=^*nm?KLoUPMjLI8Y1Jd#dJd5=zXXc+oWDhv zL35j+HM2fHai_7QAOAyMf&2_h3k(b)Zx|W2yk=n70&*iMVF_9b2b#aiWPr?H-T(Jr zT!)bZJhq+4$Pm&6YV-Za?H1;r|3g6QiM2OoT?Um+;Iv7Bdz!yN=8RT?=9-}Sq>&NQ z{^i2c{sr|HKyySJLGA~I%ip5QU7&ozz!3795i&mn3Y%__xkz)FT#O7j(~0t@|M0n? z*(A;lIdNd08&XgwJRd;H+>nO=>RiYVW{y=mxWYDr=7b<~AQIp?5NvgI2WQ3h3|ZJ* zkp#GoJs<{~D}wSRU~@$f{zFcN5KtMjniEk6dvY>_XmO&}!JXU;W-g$;u%Pj0Ve;L$ zg1ch7hcv>CxY`phq!8}LrKSU<2Hc*2_+=qC#4p+02)}T0Glab2LiLL$FN0YST6>}a zG!F!xGm-%3l>|Q6ybzQR8rK8Q3qkk{f(#*`K0+xIq>r#bg&|}Gfj$Cgj*WvIGRMZL zg_sx8gw6|r=7T_e#ZDc}Ikp2*p^lz{UjG&hLAOU3|m(7 zGHfXZ^;6LLK`wj@A+L}A-?EC2VT&%v4^VkfABu&aA>{Ot|68*78Mde($${z;ko*#U zh7j)~|F>`nFlQ(x{pHUYHKk{2?+yZ7&Z@zZE?KwjH%_sf#D zLHd8M(dK`$w&K>)v<1@tJB>EC=CuX4o+PySBGCNUw7>twN$H<~`nn*$a)Rc7*cg5u z{`+6N8*QG9YX@#OC~b%Mbv4>tqSiLtdYraG{MwBcK3sUhM`;W3b7P=#71q~%$ixux z<|FQMg6ZS`koBOxE+fY&m>xzZhLAPiaqBts?SBY(t_su-WaN77!pIP^hKXSdXbwRb znvcN!RFK`w3|n3^F>C?tX(lCJoIgV5<}#Teb8~Ve#_Qs55dEA`{r-Ou{cg})3%K9? z7q=gs-~JB)&F8`T>W)m1zWORWdYC`|4|xg-OQgPf3L`_v8777;rx_Wxfc7jR_v2Yu z7(#Mb8Mb7zFl^BzF^@V!=a7*5@rH z6gKHT6T`=8%N!Ev3s@u z{cp18|9^3io2UN%zZDe5`3Ig#la8im zi2y_oD6N-%{J-V70K*p0npr~nK1T73_RfdaGeYcBDmBsu`q;y z)PdZi_!`ol#iiDX8KIW()&CGsyBn9Bg0mZUqJgfaJlO+ z2SdoC#VjkIWHao1y`5p@8)k-|@AfmU{BWFk<-_SrE1xqnuX?2q$+ru*7`DF9c3tVo z%JB0sGyAHK+%7AhWIOD9qwlctt+nII_v}t9pE^6Q1i6#r|9^3idqC{35B_fv*^zts zxyqGU?GOHg-Q@V-e+c`Z{L9ZxYA2;Lv3Eararh~+#9`8Z29eiE_aWy{!StKnN9aF( z52C;E9&Y`M?*0!EU|EC(>q2K)uL_gyl-1?Pn{|^EA9~2I+`dPtY0}6|`+zdZ6 zn^;z6LDzwS=8(TKbF2d8rSHr<;Qh}a|2~}VwDQAo=aujFJFa}o?eOyrvp6_!z3O*e z`GQ$=6)4OeF^jA^4DKg$o)Y<6bXi_7?2{rBL&y{shOHb2@-M&M?yypxk@xkZ#gH(5 zrSI?)WZoNQho2y`L3V)bQs!U?0mTIz*YKNVVTA6Gj* zOC4HnKV)DCX*a_xAC+(a5Am$j|FQY+e{m-U&hBIe&eNWa3=``a89sV4cFw9-VECBq z$`Hc!F?f8V8XfJLF6K8iPbbU}~6vNI=wDm!_#(>QU?9tdx=K3IPdo;{Lxn@67Vwm_s2(q`4 zk)h!dGxQ7v&|cgZix@0BpzDJ=q8N69_Gp00;fK(=>xH(%PsYFh#ozU_u6(%aZq@{y7El)=BE z%OJlbg8U}Ju=V}H{LB9txn3{+`ai^;m*MB?|Nq57e!BSMKip55KmLaV{HWhP5$Y!c zCIK&lFaJ&Ug4#%biY_ns{eLSceB~MV!F$s|?v`f~%x3ufKja!z4Fi%I(B5?YLj{-R znfS9GeEc7B@&AAEji2kc!@@^^NzlvS^ZUHxkpC6YxOp<33d<|Ofs?ES4Qt;(JSgpaA|2Wk) zKmQ*BTK9C}B}DCnm$=m`Kl>lz^8deh!AFQ%gO9k?9)9var1AfMaa?XZ^zDDhe@5m3qk40pOsOki$f&8-Y#s82O|Ne`=U}S~2^+02LB`geEUmVQ8EYHaJ8svVE zJ3(%I%*qe~a_?hiRDXc{r^?Fk6ExR~tiFVWVapdr?k-SYADbSKSzrFVGM2ZhC{PDr?A2VD)VG_c^u$826;bi#v_TPVTkeguPNJ+RfpNE9Y%fI=T zHBDNTod5k72gMyIoUz3%C>%lY3yRytObj8qybM3R z{{0unrxs)$NWCc|q&)h-z_4`!ma?e%$o~-CO1&Ru|Ne_J`!a0d_!vBi3))uU5$u}9 z!EoWyE8&h=-3$yty{rzC{6fMm3p5B%sm;|bWL3JRku7=c=960MrP+bkFBRNii>PS#s4XGm`d{AA@ z@Tcgq0t*AYt^$qKZG_glh9cTvljusABl_KSY5Qbao-fDHVaR zN%I*PKC&!vn4}0YkHg_t1B3rBnA!zD{)Z@VLe$zr>uLpF1RuGs)?mb5SNDVKYK~J1 z(7O5{H$zB+0IVG2e%%bJlXw|^u7cLB2Yw*xUr=2g_@jP%1GKFn$ROw?2(7C@?p^r% z|5i}=+C%GVkh|@f7_uLHg4ER@HH=7VKy@|$fr88SO#Imgpmp_v&yYG9q}Py%!AlTY zR||eYwKou2S3h9nI3@U}=rSl?Ky~#*c3Az&{TftPw}QqI7!m$eWM&9ifTRYsu0~SF z!Vsdsi7*SfuKutw>+%C;rd5s{4wD3!7+)XZW(X}b2WZ%ZD%O7C!4F@h6 zGBLge&CxP^`M;%*pJB^9P`dz&nj`!SAq_A8Z!r{L*y4plO^X0SNW;hfTRsXfYyqwL z#Z?c3#>@UQa)HOoRPfcAEDRwab)bC4`2K&0Bp$V(@iLfN$0z?o`0%I&jhDgHGQRmA z!u#>}+pBQx`= z=ggd|Ky4Czc2FJ2zUl=FsGJvE^$64sVP;tcDj#1nv#xr}%&_X6xx-J8UqEY#6rTRy z@?dA~<&VsQrw!E(%-Z;FTf z|Nj?%a1&K;;Z2BM#hbYGKEC=tRLvQQzn0l zF5837DPm#>xx&n__2og(xHRkQm(1*N|1oob&P!)q^_Uqo96({9!OHLx)HZs#G3)Xv z4u?qwj9jmeFf)X}^qa7O#)MGy!NSh~I$wvYjt1@L1BLg0M#fh#yFuo@VP;tcGXoR{ zpz*0}kbj_Vp2CFN&M)xvas_XC`2uP`F^Rlhd#4hn_WQnZd+h_L-S^6=>cEvL1n96$2x~mPZVrH3yKh z-x(AcCW7wXdjdV<3Up@fLuTPspnJYR=e~pPVF8`9hJNPfLa7Gu*{`rOWkGj>{D@~> ziF_{z=&W|gS%nM}H5gy)kk@4>Y-V5x0pEkcz%WIDLE*}GW|mdoz-M?dt%98q3U&X_ z7YqzrKxel;WENTVh*@;iV`i~cPngA5fzA*AcAs(Om+K6mJ7rMLeg>`O0-ZmK?R?B{ z%q*)w;qjFjVi)Kvc+i<)mJA%-P&>hA<2Q0(KO6rSyTi{P%u=g3`W=3(U|`t#fLVOi zLuLtZzm0?0;U@9NiL}4m&yidtT=7t)28DE8_>JzQZJOLC)?I`y3{{ z0G(sc?6C8N6hozkwu2=HGlNNooWoC0AGA{nH21~%8glL!)-!dLFZwD&RB=}`^As{TMzyJFaD63c@?Nn07@sI^zk3< zEMMfi0Yn)cVCT7m!xuD`1PyPLy9XY!JN#Ur#4r)u*M+7>~^JhV0=AbkCKxytz zKI6(?=}arp)1C*?of26LOx<389WQ%*tefP`$l2Y)&~S-|;n*i1@LB2{ue%t#XGt(} zcE4h0_!-YA@tTtlwDtyew*lzfVaS=gq70nfVhm0bEdw|vY8o(1e96r4Q<}LUNSbj$ zk&H+~5Dx=`$jdSYAud+X-8{mpvU(YQWN>nHb8<551my(@VTOsI`|RYIIbSnzGlYmU zJM1j~|KCKOnPDe81A_=BE5pPrCyt4kT#P?GI61ndI2m?^|NCz;o%MtHcCH_0zseYd zJpQ|b(^Lm&elxTBho`#3Bn3s8+2RHcJ3;vtl>Rfg9Dm9)GJS0P`#%I^?~0}u;5$1L zz-QS(&eaC(56$Fq{JEOVVW$>1XSYvf#*W^lqv1_lvO`3AfH0;Wdf|NpI^v(rIm#Dn&zi}E%EiGt5hFa7aE8Qb~krQq|^n?Y-* zm>E`KJ3k#{4(z;a(ag*rpV?t&r8BGrnF%^)9aPSO@-ytbbkKR)j~N-ZZUdjE4T-lE zp!3orOMY-(pC6QwrTOClGejJ@EP<6F=;4cePBeOX@d8wyursV|U|`q+n#*I($OK&z z3_e31bOt!+Om0{>C}fuYc*4vu@gaDf9S1l)fzG|=$b^K$Vn&9op!g6;1fBB^DMLZ^ z8Ypjo!W&zeg4eBR=>WZ+LJrplSi%)#FD=6oR_}xS46+O4M^G7wTz@0q+X6~|!k{|u z^86r?jEo;8%nVyf`5bb|F!RD|tvq)efw^TzA zH`9V59i%$uEVz!zhSV`P%P+6W)Z5X+#<24hGtVjxR)&wD^1Ysq30$_%XJW7fotFq| ztHSCySonhOWB|z_hi#&e^G|U2vO4?(wG~1BgyaXr{nsGB!r~fU{{KbXgMeN>amYCA ze8IwC`k0w<)i>~YCy4el$ZSx#30mjN3Qgw?%#iz>Pslm!1l^%s@`!QbS7xzQEBM@Y zfX`-K>M&^qA4fN*C}{lx*er0{2(&gD>Nk|O5$LWs#zcXMpmG}2J_4o93?=aWMc}&u zu$5_`bn^NCe{tM?VH$FN0rg`*;SGvET#1l?nEg3oOS zsIJmn>M-d9G=4kTP~&(ZC#Vbs$2pET76bQpU~vq){{gv<1>Fw-I@kU`^o{^fT!ZS( zX#~z4vVfkE!wEfK9&|>IBtt`x6+=UiJ=(cLmh23IpneVLj2tPbdgL>5Kw$m9(Tig_AICBg`OF~^@V)i0{!2%aqb2&8LmbTCe}Lu>K>h=*FBpw~#QhMX@y~b> zTR(p^|3l7T#&+)5P|yE_%KZ#Z22)U51>7cp-VMc(nF;P6IdehUGRXY`WOZVhnLkcQ zIqZDF$zXD#$YJLRHU<-M@cnWO6F_&VqP?4^+>A z;vU*IvV6hHU;>M0NSzKDvjnxlVD&nv-iNCH$>GQ_@dY!(&(HrEVfRe^gx@E|XnzfK zCo89*^G}W&pnh$}kC%%XR)W%om}Enc7`X3U_M_<$!$feqQWSEZFUXCc_GJfBI}D_U zA+ro}*P$vz9Z1b1W`rbev^w+{c7obDFm(_9{SSe<2@$T>352V>!%t9{g4$rBl8EsP^e|NhwaFOm zuOYhwq=zB1lt7pw?v(|N^}z0y#TBlL*%9ID!HycPq=YBv{&-k;CNeODz`~2<@Igv< zAphbEBW&poq=(!vdcn*HZig*mVA%4AnFE~nK<#5teuMEr?ElT6J62g%{z_+E`6Hff z<+pJ5m0$chR{pK#T=|umdDVC5xH>35Co>qBgYHOUW&qvq$g=8)E`teZ+@X?*qx%J$ z!^M~X=U#gGfB&bK(g!|CF)&O3-L>(83v?g4!_O65uycvTyDgyiYP^Ept6|LwxmSaW z8FWvEG~{d~R)!ERb_8F6jUj}K8^Lb?@%a(_2W$)>GOP>}Ye4s27(0AApv4f17$NvxyW{01! zauU>ke9SD4(gy;~g@DS46-=C2pfvpoT1LRq^b0+PouE5DVE2)L(%VZeho2k=Iaf)) zb(jRYU&TS3@EKZ}?9Sl(RbI$}@A)$XjhAXd%OB9ZzzZ#hogB;zrs(y^Lc^w@M+^)i zkF^?hCd)9GYJlcXLn}IZfC!`M#>fb@;jWXmM zc6M+vm~=2ZSaSUN55MyrTwifB{QP{G2~l4?Mlws@;U}oR(g2sMj4P)yzA!6gR4@mH z0rFVLBjh^EnPDQVeBCC*61<;@x#+9-d?}oIBptx+2kChN8s}xSzjlI2R0}zbRxmS| z&t_&Y1-ajYnSpHgqq_lI&w}btQ1~(0Uqh`wJy(A5_gMKY+8VH-q}wQqc2#vEBRD0loKaCR9CgKO5#3P#aW}8T-9&pfu~L zhSpYU&7!r9@f_e?KSaO%wYM8S#s4+c88xD(EHysq8WB_Ff>f+ zV1Ds~7qljlfdPEqEPRYizX_#1hn`Or4H08#pgudHaKd$V5w_9$J7%d> z$Y-E~?!{XTUSp@Z3UqhYFJ`_~KbiSg9XJa)mlRnosE#;|q}K85{}6d@hMyV#P|u_X ztpnob1g+bHn0fH@{}6e0hMzJ2AZ`7pP}&!CPAK%88PNGSPq-LDPV+Eqfw{qpn_){5 z=&TqdH7z_0A>AkcZ+XSTum!Y+8g>piNPi12LrC}8|65-1GHl5Lxd~YxA45p@@&8+1 z@iA<%0?8q*$MS}r6{^J=IH{hI=XDYbLkQdr91L4Q`;n2)21QrDh?ybe)sg>OL2FL& zse1%EbK}JSt??i~;jv$di6KPm(EqKWpm|&Nz)hff6y_d=ga1Q7XOFyuiYp%cA2J`b z_8-jWc>Unu{}64^+AJ`i^Yz31|3eo3|1S=@^9*JN^4)x1&^zBiYc-MGj(m?`G8;n( zs7-N_jbSSXJHtaa#?IKVgS(^zd?Xn`$0?6;HLF$px z)e$C!kku@RG^@qTutkwT{4QcZn0bncVJql`13zR5OfC!6T(bV0&3ra{mPHX#unM`4a|*4Ga{{f816nfyx)TP}#}SA2aS{Xw_i;EGzFd0A#JLJ|Pa9G3N{y3L(uW zf!fQU{lqB!4T)8cKCP;wRuQ@YJd;#rqNHZ`@ z$Y6H(`H+l0$Dv0^<7CbZ6Jg^OON3a0(cAfOwa~r>OzjDzF}17A3g%mxUzojMaI29yGz85@n`fKD&L9Z# z2dr%iQ;)4}>q$cU-zJx9c9Sy0#10(o|Bl5BmgsHR4CWU3Ar6V zT>J?dW8V#GqaxMSpt1PVY>0NrgX{l8z~?w3sR8Z3c#Whc@%sOe|6Gte1d-eEp!=(} zIS^(&y!t=nKO4i(wIDl@>w7MSkk{M{;CrTHL2Vi&xh0^pu&?~z!o|a|Wg(J2P`Lh>;;g>+JunpgW;p^|8a5{~^*yZI8q=|3g-Q(;}#i&hZ+wKeZL9?X7tF ze+X#*9_Xw*QrmFKYz!fwIa|yF)f7>jb3Dt9Sx;o7d?$q^ zG-`V}>oipFX*_yQLE74{kD%#20@Zs2kKV(OwstvETiXs4*GTF0AOk~4H+YXTq@M^n z13?88FG%SO)aHE6%&-O2)&%u?Ky5i#+Xs7utf`cW+XoMJAu+B6T{X`|No1F+MCF6 zO-$PubT%2Nu7LSH0pxx@ho7CSkaiL1JWP=Nptdk5?0b;HK7oZH1mt#D8yM8~1)b6I zhM8dtsP700dtBiT>aVV1V%Q2gPb&wl&HEbKrU%`{2Gft+=6(F`e+V0Lo?>7KdBMl< z6LcmEsIB{=O7q8tzo4@VA#(vuNOJ+8v47A!0EiwAZD9sE(%Ql+l@V>>m8y`ou%-%T zTbNM;(iYaz8Jull(3}ozZWPoO2DJsnSs5mlgVzo^{N&_-jORFL{$w&@)td05-@^i@dPbPY%j zPn%PTgtlqcW#ZbVT-S+fo36Tm+BQ9K9<^->x;J(iQrmRFh5sR-b~>zWu<#tD?MhC& z2)%8Z^zXlT_8HVR;wxzTav`4f<)KrMwrTcxG`;5_?MsjwLG2Z6?S?~VA?>>C6KHym zL-iiV-8MaR46|(-1&V8=bPH-94W+gzGXeJx*0$+MXxkLjCI#)G2A#jX3aMRsfQ2Ch zeD^L|9tO3mwLxndm>9OmgZd13@+qiY4H{=}{{LSbH1>?#uI7T?4}1{R-$OD3xsAFQ zM;rAlbUYT+Mmy-7Br8FeZ7fjw;6OSb`^9i)*Lz(dkQ=j zD-K_8atb^a3*m#tVo!m`Vj+CcSnMhASS*B(J{G%x$oA(8Hpm@Qptj}-CWfD&`vx@C zAonY+RDs;D1X^#R&By_Emm{?OnT6K=ygvYAv7otH)b%E!DCESwS>toOK0gtQXoQ-R8tN@jJ8dsuz5San={mwfh)tQqcG>-ZcZ_s~&;YN-!`? zf$rY}k6EtJa@a{uo0J2(z60bZ!q)J6x5m&QQV!^TQM z`-VX23bghE*IEf_hK5O*Xm=soWD*`L<$$h{;D~0}>B0Q_MYlk+VwL=%4 zhqNkA4^O%`Y3q2hy zG-(K8`OzE%QvaBlLn|f30i+joU8P9_Sbn(si$lU;=L-e~6Hxz*$;P4b0W;{HB*+;K z^?VFJk;5OfcLUe?E}*kGkoWhzWM7`8|1WyX$mf88&i3$2}$$HdotE;HxH zdR2!>?{Ai0KAow*V=eqF7haUJWMFOtoh1V@TZ5HhB1o)*i?dsdlVK;R=eZ~vp`B6H z%y{ufJk!c=;fOO`!aW=+zY8*KfutwKRiJd~!Q$|f^KaH=tsl)nptF-fWkn_*XSY_b z(+^O;BA$`sbrSk1iem+ncxPl8+9|I#p2)e!`Bz+l7pnX^3*`Rf;Tz}mz zbBa1lTJ7gh8PCX_4Lbj66`#XTPhQS$(A_Yr`5b7r#RjzJNU(IgN`e)6*S(mfe!27B&J0CEE_8KrudBN=P^92*bmWoA?vx~GC9e#q= zWpOh*{H$l>dJXaq7c;|8P&jBRg48hle8uhX6BKTsFp>bRKmYfCD`@T!*-Vgl$KU^3 zGnpKA+B1r0gYM190G&nj*X^<S6yRb zFqdOs5TPWDkj*Y*WH1B8O@^OFH;1Uh&kQz(pNUcqI~OuAm?YVO$}Gq^7m)JGb>$a- z#GY)>K1ERd1Uj1lJ*}anF%O5z73>UKGKD~4#qnCHv13+}5W~+-=ow9*vv@%D1!%4Z znGF)d7gri=pfg+=g36)s1zJO>&FJtmdnx2T7EpY>W`e{QC?2(18GgKEM~$=ZN(>V< zu*4ZiJmc^Gt)TLYfzjdb0w#vPV$9I6;^ROGD@P{Gu;PWDcLeee=sY*%eUPB@3_xKA znqx*bADbF*_&S5mW@1|T#h-cQ-)feXpP~CAL3M(MheIVO%{B=+{ETPdcnt|t;Z+Zz z`&U76+X>EloY{%I3?Z3p4m-QpKm9AktRLN~4wF1pxw|v@7=Gp`G3@NI za;VJlVyNu3bEwSqW2nqwbNJc(H|w(AkLI9y2ENygVhkaDOb$EGhlX7~6B@QThmGN9 z50k^r9zLG#9#My%{YxD-=d&^V1gXhmV%XWk=CCt|jbZ2cziyY$i8@UB&&UfdH#}6i zyE%CIxjv#v?hFmv%*n{`GlS3JC&x$jiJkmS$NgoYL}H?{GC^R z3wK)i-+pGlPv`rxvvQ%0?>3 zL16|f$FnIY$C1mZ4k?G7p#5#=;RMPX8D0*R9{>NFfX-pl1l3_HJzgIK?b(I8KaF-eKj_n8K~*nsfpB< z)XdEK@k-5M(ydRmmnA>eUf#ybu%(;N;is;;#Ontf3?VwIT-|<*5~uZ4`MS?BN_OWn z@^=3R?Q?1L`}LTeA!I)z<3}b=h7cZxhD)G5C!eJlwlw=WR3^(XY;ERq_{l8Gu(esq zVdr9522)UfNQ039T-Ji}4JQ`=fYgA_oLs@g@N)$h=$t`^ot;Xc{acW;W$@*9235}P z20n(LpuW%p22k6t;gWoY2By~F^c)b$TZd8{z&0)(h5f;{+eh!rytPFx3ehihMa0iw3pg3W!%-r#qgTYk1Qga7r z4g%I!xxwEM1WNy)GqXDU94a|E876W(t-8#?>Uo-jk#V9tqwwp+3=AQL3=ATmzCVZ$ zI^zPA&Q35eYz3`{XJ8bE=O>Uja{80x1f6x|@Kf_Yq&@`uIkWtSrnaj{qZwCq@;Ur`Y0U7mQ^{fH%WQ_7O`s}jS+X-W(e8=4N-JYa6Mk*{R{?=J?m=Ngz8{({8u z)p-p~4K|>98dN_2uV-HQT^zKRph4)nGsDgYiy?i6|MiS3zpyj>{I1Nf^MNu%>^r-| z&+kkOTYhjm{Cpwp@RPIE;Rh!(!_ODe3_oAWL)rjLj0_FZm&2hZq<_%Kw4e zoFXvuzk}`&Kr*-d@Bgh2)E)kU+`oY7fb9XM2HO|69V%BaFqk~dcG&soKB&zu3_d3k z*V*70@t%g-cjRJm`04yN>#_#8t;UfJx;L1`!=bXCf#tOlCqszmQin<2e+w>Wi7*K9 z_&8M7GxB7E_7idQIQ#_dqvPRm_<5GUA!s!t_v!A+>>WG|3=?`79e(CQ&s^lskp<^(#geW}AFt-l4AGesDLxP2h~OOV^Rpl$=Xk=(u|s7>M( z8aBy;kz*C8Kg_}5@RPIQz@?Y`4?b}&b=b_w!SEB*CP5G1g(=XqPoN#o!NjlyS3ACg z$zdnwU(~ibXir-vAEd1gx_bwdRzdYYt~Mp8Z3b@7GICPfp3P)Jv}ZY)P}{Sh{DR!? zSjfN-0_yK}vVq0`II|V_8A3p5D}#w)XBoVo1UYX9t3MeKeG<_40LA|Jn{^rF7JEjH z?1fBVx1o%IfX;;ItkTAW%CV z6ds^{EUq^E2_}Xu)1Ym5a2i|cFzGZC=nN!C`vX_s^_mjH#0)HLdXV@Eq`qqc6T{!B z%nW9oN)DRzYO^EPNB^A}CxY??2LmDvYxzL>o1n2DO&&-Z2F0xw546ukK^g^>8K5z2 zP&)#&&KJaf&^})ZO;@cEl{*`ARnTl+_IP>Y~< z6=+-w)K&+}^E$%iL2{t{ryUx0St~SbGZ!PnPf-5|mL9a1I&9`=RWr3FwL@8shE zr!VfmZkM@49VX@YIaGqi0zhRcC`>?orz~EsZcure!-rO$l2Dd{+~Lj0@H5lPq4Fg& zg9#@?!zEDL3D$1~-7lBN=kU|lQTO!O%G@1%j1E87|8>9oKD2hyIY$2ObD7yc)~Y&8 zI;+aty~bCkyO+`7=h~$XlX@8$ermEZOw92D#UsyaP<^Ib>vma3ltC!Z&!KWZBVV@T z-~S=Gd=5W9f$A`DKi6?3?2LW7q=mm(mpNHLV;zuuuEByjW(msYoIIHMTmw|DBaMlI z(g3x1 zpPT{?KS5;==o~cA+z)8%5>&2cAdNp|K>Nm!u{!+o3)s$%hn-yytFsgs?5}kQIsD9E z0*|d-n!bo(B4p1b!$eS@(~_BCB50m$D-*-S`%DZUHJE42dRbNWIGUGlI$Lq)c{)cq1IsEL@a?pIWm|-R89C?^sAhp=Wxnbv7$^U_zvju9eF)%Rv zWoW=ZM#0d~U<1nA^w!7h;ZVuU$gq{!$DtB*9yc?O!%t@>hONvB4m%$+F_?nf1oJcO zY>|i2xZB!{F}URv@yIzM$qhy~A*XXtn;$f$0~%9F@&mP5k<#uzM7)FQE@H-}kmu5r zm>9OiD=>U~4C+TRFhTm1p!PPH&G_0A%x<{k$-r@%i-DtCgMp))ThzhATa>{<6WTuq z#aTQ9<3~_F2lWp@<*>(-s!5s+3=_E;KzAN+tWsdDU#rA>XpIA_{aPp9rZw4&kiNP+ zBhzb!fB!?`Ich&W`13#HH8aO5j}NtzG#R+Nxfr;+vl%%~E3`WNacE`uldZ_G5j6e) z(v$G#e+cN@22j{=fX>q9arnsr?FWIvN}iRW@Burd9)p!V=;=xktu4<1E%WRd8M7Oh z8A8BqR&X81n9ab<5CWP*)(~M3;)2%4ptdq6w5<$kGlScUWR8C_EOnR!3P*H1K@9D$}j%xEB{t=ti)R0c{x;q#tyDAF-!#Q zt$~$yD_9szK=Yut_#1+xr5b{ynHChm%0BQo37^AHFJ~?A9Mx+k)cL9G%xcVesih8+ zkjqKX+$pFZZ_mu}+KG`N#GaYqBM0-eSz7gOmo>#1gu0>Qst5o459#7_`1uZLoDo!Z zg7i||jeoN)Q|iW!WezL3{$^bUwVk#9W?crI58Y$tp!r&zY2_gV<`QI6G#ubM|1L!`Ei5wCPJ2@E~ero$VRLV1Q zXLB(#glO?X+KZq(HEA+3OjO9s_yJPOz|e3BL}RE0ue)WK$RWtk&A{pa?N>t7VjoXt zSOqbIVWNm2V>f91D(H-FQ3i&epfkP|m>EI{o$=kt1UauRQ^|QHsLc#&hr-&d8FCIk zMOqntWXOTqw21i%o%V?bvGNI=gElSfe43!Ej4Ezid41d96)DIXeITRRvYA7@WaZF&SF!8GMTGkXT1V*VUsK5OiNDYhM)`u&ezNcmfh zG_z+UVVVtTXF2>l0Wv!QVfG?r(#)ROglYBe}w_%!z?C(Qjq?tG45T<$GofsyHBl%lNghVqh zVVa3--XcNL%$xoQ)4Ua+G>KH7G4YdVCKGt=21;ECPUlEwCh?GHrV^%^=w-+uP7=*j z!!#4Q3~^#7&Ae$^nC5MDVwfn3RCa*wEC;pKKy3q9djPVok6|LHt-z&=+BSf-f#7Y9 z07Sk9?Y$($Eab6h{sX$}j$s zEB{tYtpwdM`jr{7eiG8=2HjKX@bkrThM$n~jbWk%LqpIFCI(B;{+|0z43>~Gm0_X= z!-7j13~jAHotvYEr^wyb?;is7uNWqP+H5D& z7=GSZ#8~D(Yag()tUbWyy!HV*>)Hcs4r?E< zGp#+q=D79&JM-Ef&Wx7-7qeLY?`E?6|D4$pmQG%^GyL@8Xb5_x&baf(b0*6N>~3oh zu(7Ot!0xj402|ZV2kg#k53n(=eaP&w_8=46+K0@ZYY#H9uYJJozV-kc>)HqGu4@ml zF|U2V?zHv*8^c;o6$VRA0fry2_B3a0LlCC`!%lGm?P!Sy43^>w3_n5bX9;Ng`M);9 zPSD&iEG;ocG=bN)KLDLW)(pD04>A|~0L+HmANVuddFA(d=9MSZz4tiyb`q5RN_F(B@2c_pClR{d|H{6VPXH0q3|UGLkJgW?E)*q z#24}mKVjl47#KoMDV>}Z&nWRq@&Er2P0(EvV7npfIKL`8uY{>R`R{+oPw>7zh6$XE zpmA~ruv@_W1*lsxgd8k07#K|JgBU96m0)+vF-+vV>txAw)zQ+EkyDHFDx)Q+p9@M? z8jK7(H5kGBKTSj#7$&S>00@?S2nGrso4YTuwFeo33b~A8-?r;U&aSOWBf^i~~KtmAd43x+J zn=F%A7`DnYFciKJnmOyGu)|MHM$v99Rfm-?k{MUN0*`@1!Wrb=7upRwwSN=cD2A)rY`4LurB}%kltnC1W9TbD>B`A9eh~{8mnW)LY zGEts^^R<$J$1i6lh7bi7hqX#Pj%yiM7}hfJFs@Z#aayay6kMMp)f-HwNUPVTW9zdpFig0{1Z}?} z)$2;fNi-WvyBq9YBr}_ikZ2~B_BML^BpQrq~@781?I($4_LJCd17n@BTr zCYClldOxFSJ&9%>!wgg8eg@N8(#)HIrB8s~ze-v~nwc}P^b64aeP}s}WOas zn)eFRJajiMT129m?=a0ojvJ)~q?tG46Q+6K@(n3XHq9l`Of3B?^!R=>i$pVpF#9g( z?sS?#nwhh(^w}VDN)A6Iof#%dW+3`9NmEHQ+X&OW$mTtoM51|4Sj)AHbdFc84Q8tNYCSfrXDIAkBNi%Oo6Q+6KxIwDd4yBQ3<|Irr(d#v( z6w=I`xd_ut^zx`Fkwi0>VVa3t9x=s}X5NfLnC5}=H&R$8#gJy^%tx4JqWk+$B#CA| z!!#4w-%jBqn)eFRJajiM3L(+VcbH}(yHP2KMDspjnuqSjCVvvm{Dx^JvKyIvNi%N- z6EjAchMsSdyht=t3DZpUG27desWMlVeB(A~&H z;@tU6KTI=`-PlCp-1*EPO!Ls)_{fSxe}`e3iR{KC66elmMq!$V?#4r=B)TyU(@bPH zI*~YcJ~Ii^JajiMG9b~7X_#gryHSb6x$~J>nC79ov5CaF^O<>=W+J-FS%9dGaPq^U&K=N;0IS#~G6_ z%|x#onn;`{pRowjO!RTaN2Jb`FT*qwd7Lqc)Oqq%nC79o@eqk~BL} ze2{2_<4VxEX~=V#j5UlaLGwiD^O+fZ3_oGwp!v*K=<}J(pz}>2^K6Mqj&L&w&1aTI zF|NdRz8c3GXG_i{PL>*s99kSpm@GL=9CpIyGC}iM|CvGOuOQBg1I-tL_HdnG!kpIx ziNoeKA#;tO`67mi!VC-(ikTQDo~SB?&TB&Eg}1UXOgyouVds7(j@O`h&G}5Av!9$- ze(`r&`7PXW<$q?#-nswGEEj*JbFcgn&$IGdIPc0Y{(LL{R`Wy8u7jL`0G|5{XZZPl zKJK~D3@*rAs5jDF==a5#dwf8C1kJ;O(hdhB+MMWO2E?4`{3gq0X2_hVhVYD8;Je#k zbE5H>bD|kssB@w(!ZGJQL3bJct@dB}#ouq`w{YK;KjM8>{z~^=`Jb7En0e1B|C<>u z{;g(Q`H-1m)r)3^iJ&_a9yNo;qakZMK=X?Kn;F1n{jJ^)-V+WAyAw=^Gbmmlu{oF# z;u=V74C*=b?e->Op6obZ{~3+`zyf0y?Yd8*Dwx#rZ)}3>@I~ z10 z&~OQSUI0Tw5Gw;Dz78-mYysWb4!S@51QUZP=x*|#%)+ZQknRf9z;ah$qXy`#4@lm4 z2;M{Aa0wLlFW6yslS{68#0r{IoZA_{1Q=5Tda; z>+;M0?UOVVPt4L_*67mwjd~7vXr;!F6Ko6>O zbMRlOk#}DY=zQVRKmTt9?M04fzS5xTo_1{dTmdl6QK zi6u-7Kj#}cd}`oi2+8k zmz6)_omc)!cUt);-*F{u4edILibF7{3V8TcBuygLkMV(I;iXbomUDv-vqSBVmnklDgF{;Xqa?T>EtZX`7fHL z9$j3l4MFCiT(cj6&YTj0tmOdZZRGpdUo2vzZKtVE#)4oe9MR+2@Zd-mu*_ z54!W7(0!B0{sW!w`jXkAYdk{pj613|r!P89r)q zGlV1}oktAH*Pt_rSwQ!r-~A6(ke_}kH5N#dJhi6Rn&WM6t6<=KZl(^{^08W5YU}M zuzPSGUj84l`2T-#YTSd<^Y6d->WirN(P&+S+(+~90`B{0m@Yu>!C8F;P45+`-phFO zUWVL*v-&KW-m_4>XYlAfgLw~53n;FU(mQDX=W68pSbqEuQAJ93pfs1l#1O*G0!f!E znHa$L(<7gkj(%P}XrFEu6T{Yr|Nq19X=I?_p2o*NQSWKgA>aql8RY1G0NwKq^MfW4 zegLg&2KiwFnRhihe?h&++~L>%5YQdgFR|Q*1G@VWR+c;fotuLc{;)g^a=$k;4nXcF z_D&p7ISx8QjMO`EoUxoo4!XDT3-mm4(49CRL3iRDX1s{&tYj>0-JkodnXh)RG5lOl zLR+_i`fXjXJ80F`O(d$I%hv#Fzgef5<`gB z-=fQ}R0lyjmyO{ks1GsP&TR;?A)}qEKty|Rw4KW^WiYpMLHBim+OD9x*g);rRY-S< zgW9>}pn8Xq;}j_Gg6`S@<=s2)LH$+GS!u}rN4^X3Fj~8{0pxZ*ho7+fb3kPS z=pIKamSL!ls1@$*T=W>I_v>!4H zuL7O_|Cm_>@12mKJ0Ks3FoY1g12Vo+;|FLQ`~?$(>9$A2-{tsFi_lm&;x0#!`)4sR z>_om_5tJ5?+p!K}v>C5G{jq%;=>7&!I*Dgw_?W=x`K#mW|B#OV|HYBx{@}a+A)tP0 z_dCRxw8xkKAqAjurw@=Z>DTWOav7ihhg74Pq4*YJ#_Kl-bsC@kha`i_gLe=!yphfS z_&+2MWIj~x^;?9#j1T`qvZ3wO;dU?LE9lrEK7V05(+A(3masE@{@@vJ2AxgMrQ8t2 z#k`@`WLwTMeaB{vcEv%=u)6I z9pt`=oy!2t5g?DF!{!ITW9ZO%5AYZ|R6T4A9dz#!sC)pO_l3)ESjW(F zNsBYk73~d*I`X`JmkU26fP`~10`?mXh3_p9(^n=uRb1-bpywJW4 zw70(znm5*i)WP}{j6APhI2b}s|AvfrcXBX*&-K$nl4s#$2eR?g4u+i|r8 zlUW%;Cj9>|zWOMdzN7!QavsI4PwB}25E)S0`v|JORfqp??L3TI-=ahR!EK1w2T}E9 z9sIx5^B``0Ne3YP1LS))LG3=|Gzn_6o@Qj&dh&JqcF=v6o-7PoLHAjH`}Gl4AkefS>&YR`l2!|WuoJr6pM|Ad;uN>E!0bidFR658?#)NIRV zIjjVg%^2 zZNkxZJi`=X*Tdjy>yEbL8!jQQ_32p5V2RvEL2t*SjHxn%#)Kg4c<`7z(wHT9%%7cM zE9YfM+kG0Sy$hW?0L?9c#tgLB8MbI?O}M-B!SeNZr|>UM~%~u{~?*D+PAylQKR(Zf5^!b z?c1#x7(`Zq+Ez&8`UKl)tPCNbzLh2$q;F*c8q+_9Hnx83|5napxZ9vgM8_s4q~>`xj^xal&(N+V36N4f3|N2jdi2M zA0tBuXe=0C+t=ye|B#n|AZ=e#!&LeA{}52$05nby>Ki=#`(GS6Kfv6k`Ja5ZasD9B zZO-2i?Q&!{f!gI>ptOUhU7q=+eH$puPBKB-mJKjK+dehX(^`Nf}Y<=<-dmFVk1I=LKng6{Y15MtQ5i-AGp z8#B`?_*s5<);>QVqD{V%z}ja~=-TJ0Ob$QiV2rPecALMfp2Ybvc+x7g@pTL6_&Vr} z`7A~WlE&9xu{r$oW|RQ0O=@e;Wf=+l^Q=d*dc40L1XAIm>7P(1l=2A0A16p2U*k1sn4(#wuS~W zwl22nF|#Pj*!nkShEyH>G{$Lhf#euZOoCCVX zJd+J{cQklixg}_?N1_hW*m^Q}p8;f@IlseC$wYyP511uZJ!A&0H5Uip%ZAQh!SrXx zGzNw(CzTi`g2u@-8DISXrB9F_kjLB;$R2ZdU-`w~ZRNLc*OfowT~_`|cV77?-)ZH4 zX2|*a+E~WiUwru=(u_V{4jpqx9`|1H88YtO^&UE2jx^?e;?w_-GBh(9-$2IPy^+S; zJ3jsoiTnRw{MB2C8LN@T)mMD@ACd_gkB7>6Bgvh3|34%RI);mHE%Z=a12C&WZ7LF4X{MEDD1{W?3tPX{K35Ke}MAbVAYLeRQ=(A~o?g&Dwmhh7Rh z?0n7c0J>{SFoV(I=Zk;;w`wso1Z6?jzr*5Ck<4}Mnz~%GUve}2R8nM^s3C}bt^P}H zho2e?G2`+jJ7hh3C$t@oJ{JG-V*7Sb84enYe*wD78%-T-EZ*~C`?mjF3_m-d?K1SS z_|6OM+y3)0{A@zg4;zc;Jm0?UKO4i(GH9Mz3{nSeYk;R3$pFRaK12h&N43fvuJ_3!Q6Ehayd4lj*{L15m$KpZlaZ1MG zz0t>O4kL$qytuOcEZsRlU zhqUp_l_2RCwD;pXXdD=6EE#z${w0^gPtaIAXkE-}kUFHa0vhuk>0|MrHRGVMcpXNL zQ{8`yE`#Q3<_m^>TFA%{qRq&##mlsIQWg_eH_F@*149UCEFN?Z=}V@DZJ>4A)BgS! z*V&kLnRjE>qXqn0ZcjtDc_44O-vB(6Akw9gm^o z@St_z^+dM&LF4cpY7Q$o7+?PA;9~f>lY}<^0cy7Si_pj6q3!*bfk^Fr$T<8+ZtrVC z+xstdA?^K@dV{aM&q#TD{|82Up9^!X_-K2-=<-Nu?>~dKT}IpckbRw?wJ2hPe81{Q zZttUv2SUf}LG689WA-bdZTxOfyBN!u{Yz*YzZKdCKp(TugtqZ3q4{JPNFB7@1{!C_ zH)en8EbcLTt+Uw2>|dRx&X_%DJq@8Td(e6sLSy!z^)%#;*@OCEpfP(;A58P#e{nCg zvG-F){%>80XYBpZVMu%a)M3=Icdx_$w`$_)2RK33)^r_2)yH-4|JIiW@U-WlYip3( z^PqLq$Y~BXEOmt)#Zw7emMELGAWlBHQgR7#K`IXO)1*>l~zT zfHr2IKw!*%0d&k>2W`y$0NR*+0@|4U0U?GELSh|SqW{!XF|v9HOU;a zKS0DDTyn?k8!2tWH~j&pNsM;95a!t?v}(t5V;Q$U@#TL=6WW+NBXr#UG}734$LIec zS^xiwXFKj1Y^q?_y zV#e*ck;d&)k@O>v+r!q#gU0Q_Yvhsa0FB$PMjE#d0+~VKxP2xOuFY==eRT-H&Vhz7yKk?*g@tv5en?*3^UA`k*!S$Y#UV++t`roOs6Xm7wGIS!m<;uMYg*dJ@n0{Ua>vasJ^LBOeUo_g8VaZK#jm zgZ9EAufL(j_9PwlLol4FtB_}1Mk zh(XrfuMt39ckciivqv@uZ7#q;1Tuy{6MB|-gBEG)?m=PBX^0rde`yL?d!K0xS&QRo z!mt%_u8qj5N6gsQ-h;vy6pzzkYwyJg$02AOzeCPp=Lr@D)8E_-;Pms0S#;G`W|>ux zwfG|7wfLP(4nH-QI!uDC#qUH~i~omNausMjzM~;!>+ydw%dGkXwp(h|FJ|dgzquWD z?)mq-1Jvd}p~Ntelc8Y}cs&`D!%tCGhKW;|7=G?If}GvH0_hC%6-*jkD{-7*4oa7x zGt5EhvYuHg8?=r$!->K2Z#Dk4`rV-M`lSw&K>N;M=i`9RwjpMnJ?Ly3T9A9il|j%ml3}MOW5Z4_g#|&}3JWfAJDmAM&2fKFS_GX-0=myblhNTP zw)12NpUV!~Du-Cx-jU>J3EI;LUKbtdu#N-%B;#g~?`#V>e`KRW}`8h=cGgV*ve#PmC8&j#$=`rLp2#XmAjulm3& zwdy^y=&EgbT3}lZ0X#5`3zX0zMV1=I7168AW8nRCy9MnceGKZ0sA;cT1 zrt>6Z&cO@X52*pEh4w>0Zt?=170SgBvijHmE$Ds#ox=k7pzE!+$tua802 z|DWV$2m$Slg`M#Nnu~y$4LVEz^-+jA&{_K6bH&ljS^_#t{|H3QOCE+0d5{~Sa}r%> z>#i4l`5yu@8{MrdzqD^pK-ve4tPi91(#`;M`yV`K>NJkY+~hmd&; z3?ZHS+P6C~Fo<;SYu`5I|9^21J^TNE@soSow=MerU;OoZ%y30ME9TX^|65PKL#z!# zb`RLiZ~upAf!2-hM%yE>`~TLLyKw7c+67s|#JvkuU)Rq6TQhg!*4MNHvM1s6c2s>{ z+y8IX+>TqH)3*O19m`l&P6zKvfZSEJ5j1Cklr9|^8A47oLGsH=wuWu!aR|yM3qX3% z(uWE&Lx?sj1J?AJ$;=R1-qPaCrRwKlq-Nl|S3JgXd>J;lao76I*y_g63V&_FO13GK8##rV(^E zu4HZ4uF1e40_)>pGZVD$!i9+;U$$@K zXJ8P4-Dd&YtKrSauvL>0vR4DyERa6s7Z87UGBj)lot*?)`}Oh9fAJT53_suh`7i#T z8TX!Ta37Mz;pcDkJ|vgJPtL!;PYie;lFQ*Is4m9nL*m%WF_im|31svkUm76#kS9$b zeMnCuNFP$um`;62b_Q_zA-4~yXh7vYB)h}UJ^y~6Ak>F^AkGj%W*_o3sBN5)G}?z8 zHhoBT(3n`mrQy_v{IlF)r3P}J8QO>BB(i@sRQr$IMEY+y_aF1H^dCWeIna7BP=D?q z3q!~$4hF3K$Ii3u+nYe`QlxeE3t1RKxHuu|HP1r&hv}fc5^R2og#mmQj22XlC#Vm} z$M7=&H1~vLjw47NRL#m$kp3ZP|2Akm1H2yvsl5rBs{-96f!-Da-7OIXavz%7Bisxj zUMK!<0o|(xJ68xab_Z&2fy`>*VF>9u{(nn47QLW5CbW+IN4aAHy`8n_8}|O+OSXpX z8HD-)Obj8JhugQu5mLv<5R!SQeR~KYbqow4D-S^Stgk%KzHQF`|KcDTbQjvo{q5UU zf%?r@+SAB)OAzW;B(pJufab$avf&;_c=GqZ_^Lgqdrq|W{NKvC2X}u>X*Z;QsI?na z->O~zw|3&`S1#HK=^wt@fvPWS$N#OKJ8;{Vv>mg5xC?C_3e-OY-3JCrE15X@hbuvP z(9#^JKZKD!nHjc{(=U7p?H6kPf%FTtD2+cN`h{g6KOyH&Murf);lRc4GZUl-EgY6G zVfO2^hzJL4{lS&c{$LgX{}bvDCVznRi(V4ZA2h?!AI!$lAIxNJ*se}Qe~^WVA*7p$ zVJm1(n3R5C=PT0tfse8D0~!88`hoxc{1*q^i_F02@Rxyu;V*=Jz?Olb!4`Dy_P6l8 zE5G=I?(Ak-`GuKj)n{hLRbN4KhAIx4T#O>zUWE)oTnr35;~6=!L1zJj#!y$XG3@O6 z7Yn+df*Zu<5OtWO!NFj{$AmA=q|ew9)>ORl^8xg=3)rpWEAbzOk|kI z#VFG4#VFeCmB=tLn@ObGo{{^tgJJNm6Pyeo^O+bwDhYzmX}L6=fk8z6AwyvYGeZa$ zRQ>8C#)&yh9H)C287Iaw^1Mzk4F1)@#1JBXkfE@Xmm!3Uq2bayX0BCS91TI|x|Q?a=D*C!v+$PY=}1AiWCT{)a68|6d&6{ofoaj+#6g zPMQzc8Gc$8%?i3%u(!yYQIo5Wk&{cez(MmgBexbeBR6+8BQG~!|CAuVx4Vk68Tq)g zQ@e$;89BN87`3_d8M(RMG4g5oGs&CkToT_D{TB+#;?=slwV_j}uZ;rEPu+y#vKTo)PnxeS;D zv`e@aBJ}~@o}GKIzrc5H-g-oVgtxTd^OBn>U)Lh&&k2A1y zKV@L$c2{W%VlP@-w3LCJdud9m@HPff?p7u?i`Ui{mB> z7c+@*motfS-C!~Wn|Fl~;y!b)?x5?Zmq6U-HAT3b$&3r+#u-dv5ce@c+!y|JM$mP$ zy%6^qVY*L@3F5x(+)Y8>kM6?lJ_d;U%Db9^rh6>F>Ao${@H4+KC&*l6H%|AJGDF-a zUO7Lg{MR0w?z;vJzw3Ku2ASI|!RfxwQ1@N`)e!VO4R`p7K;8F!Lu1hPS^IFh?<+L? zw$E(}3SYefr~Axc;ioV+sN7~NPWJ^fL&8tIeoD~yx%+X3-xR3(%%dBEzQ0`qcONKj zr!xtA{a_N~l3*70x(ZHz65J6JJA)#YZY%Jl|KeJbOEu$#+HbxVzYfPeEEeyikEevAZpFhnH3Qk>71m;Jy2)8isa!+P3 z)hcG<^?J@A!u^~ZcJ5>b7Vahe^MaoI z-CqP^C%ZHYCo?c`r!eShwJLCllY&+Y1GCp# zMv!}0xZj`b590s2wrDLQKioa*8I`r(GYWVuU|`_pXW-{%xHBiH;V7uSW#E1v32Hy^ zaz9`+&|+ZV^#a%bj11fjNgY8730sP?85y{Lc!AqGjDppdf% z*9B$)aJy&)BM0|eMoI3qy1l}gjGWw>jJ(`Aj6B?@7`eC=85k!zF))5Sxaofg=={eF zRYuJmO(x9;%#5r4R=chI;_tfhTe!>0AMwsBf2BLE{FCpv^8aDRiJEJq?RZcd{S*_2Ry?o6rvnTO zA>SAow#bVzSX^Uc_;~RD{}52S{uEd3BrZm-ZqS{fpgUDG7=^nTQW++m;F1;Muw@Wr zRX6$Gz2|h7GCubsUHGr(`Pbqfcsmglo&30GjeLxL+t|Hb7>Fl7l7>IVqg&Q z`dB+jn~|%#o{{tQNd|@x4v<}m3==(U874Bmh1ip!=Ag+{C>xx`#IQ5ViP4g)mNhub z4Mg(>XL&JNa@2|jXZSH%W`;5B#OfX{hn<~F43?Q(4m&k#If6Uc7%Vfz94b4x7%VgO z94tHe7%V~SS389uG+2!ogJq_iLuIEFgJq_jgJq{2gJq_W!_H162n|-F#$cJL=1|$G z#bBA~=U~~X2R3(SrxAn(t1$!HQQ2w5V3`@`VA*NMU|FA~0qN5vGJ*S2=>4Pr%*+@6 zR&%d>#LT$rA*esh06vTOCkNoaGCH%OzdqK3Y{1k zLgX13euCr~7#JonFfdGHVqloy#K15y(Y-NO2?WE4MCiLAm>#jFfoLH`qCl{4MC<14MFqO7z$S~FoaBD zV-N(bfA0AIe=F!*S5O$h#6V}cmZGg|bNu%|1Ubi2%j5t5kYE4*i)%16Oahq! zG8c5Gs0RbX77!afjt&Mi27&H#fW;vwp5+x7EJ13K*?+6|uVi3q2m+l0%mj^ZnEc=B zgJAc;+z)amV++F$kQ?i*7=G6OV_8{m#PG9z5u+t2k0Setfq_AU9DVXD7H7x0+=o z0|&zv5eA2!SJ)Z0h%zut5N2SQP|O5c&&(jw#pm#|+sR?)Yi-7rFVq=Ug3JTCa|)Bg zPZM^AEgfPGKRe|dexCgIf6FQ+ho4>l{%_%BXt?x-nRk_TX0F9rR)&eI|Nl4TV`#Ya znwf8ve`cP=IaY>=>;L~ZJG5Wta%M^R@Hef5@G?%>1h~Ss5;Ri#k|n zvNB9O{r|tI7Ndh@{7#0#g+Kp?Xt6q2YI8D7jNi*pn90~V>%{;6;;?l6x7uap7k}rK z-@=_%{&!}a2ufe*VxY9pz{;>Ck(FT!Xx!~3GuJAPj4aUj*2ES6|C@3%G+ffi$hOF4 zWte#4|9{gAR)&k9auejodZ-^k<6mBk+^0cmc^Ejmdo!~w^fIz7_A~N<{Rq-4&&Un; zBgh~2j9jl_etf{pvxe>`${+EpE5C)at^DH8zVdH1$4XG1gM|SoZZnu1cFJ2a6fR(62+@#W zFh!AD=Cl&zp9MS&ArcG?mqZvCCQM;sm?+7>Fu{_UVWJcR!-ObihKbS)3=^uE876|( z9M559mS?;vb zTiD^}>&=WSU#w2vox6< zcD_^wm2D6|Du_ee0J0x+pCT;%{H^v_`NiLT<+pIRl|SNLSN=+OS@|d5dF6j+CU9Ay z0jl>I7$#^iGVBE9IT%K6AAs^2hg3rl2lIj=Q3j4~4wi->4yFY~VxYZF&Adh;3>@9^ zEesa(nHVhPc^p15FoM<_HC)P6Vwh+TAJcaNxBoz4$H=%K2$Zhovw`*%fZBTu6X!2t zSP3?laY0c66G!)bs96qBvp88Af;br$6lF4TcH=YiK9ZUD7cr~^-Ftdph~ejbF@~S8 z`~jMq;b3H#*ujKoUpBBY{N?zuUkG$ATSF40Z8^UPQs*`_wc9i_b=Y)pIqYQkSbLd~ zfnkCoxJ?LY>oxc>`~=m_4NRS7=D7omr0|lL@>3Pxv|f+|S0a6VmQw zn7Dr#!%F$TOdmNx_x&(1h`_=dqz2~q{fj_pM`RTvw7m+dBhlMx7-@hR;$~2Mi!wM( zgt_qnsQhMVxCC$OGeY8;g@Hi?WG*iIIY8z?;~SQC;PK5&TzsRaq4|8E@>zHlx?lbu zX1e$*oo(fhc=naw!Z}uc@#kFmx0(xFk3ho20n+EtXZZP*q4koe!h%nt4re}nW@h*a zYx_T#%`nlC4HDda?zIGnkZpkzK9R4#EaJN%SXZU~ZOUQoo5S-FG5l0lG@ zu^~uN@x-i0vmt4ULt()s4u>C3@mfx>dl;ALY+b+%aWexm!_O0-`7cKCZVpC< z?w8CAr$re#yQVOSz6RZix}S;RV~do-uLX<@A)vDRAv2^-kY`~qRA2|CLr`9I__>0C zVap3|b=V16LFTt==zJOt;`~^l!aQpHA zgQff*cJSSz@*Rls0HjCWgW;$AAMTYPvp{`7h5&}YFP1xOV&LWQV{ABOqadT;$I)=$ z(hL3vpBQ;L{1{{w`Y|+g*~tIlS@}XAvmf}7i6P`~wb#lo{+=tpg?p_05%0e8SGwEE z|A!%W$AIhs)rnui8CSjtW>^U;LqTB=W5d!yqF@_JKLVr%xsA-o!0?lahf$M7fMF*? z0wnJ1q2)d0*jIgFW?S_ge1{ans-MZOD>=b;NO5+1g7iBu{A5sIng}Z2L1QT#2j&OKi!gxt z_TaG;(D(-D(fL8El9(oPGIDl<+J2giU9&V8IZkt=GF*g>Z-hrPXomPRu8d4(S_w*H z$Zgdh@s2Bhr5^?Nt6;%kfu!@%u)!TR$YuH$ zX2w;Zx*gOOS-^x^RxAM3jVufobtyRW;m_D$koNc$koNj$N(PSTEx&0gj^0o`X;FJQIV8UrI|mj1gLrBWLf=TlkgkLiIH@2XUwu|3aD&jV1)GR|1&dQ{9Dbu^6_NG zl@Gf??EnT)KL+d;kbV$GF3Ujt1MCc2K;tSMYz$jKeZj1(OmJWI)c^mcT#ODsy;vEx z*t0TxOn~g?xd>|KarHX<=we~m0_q?8X69Ic`n_lW|2ORc_o2C8bN>Gy0+Y+j$^rK! z6aW1W0jaBJT+z*!UNuoZ^j< z%ifF*mi1p53J?DKAL78s*^OFuHe5pGqmA!PZbdKGk;4VdhSdQNC!wl^g&8QUIT#%* zI~W*Du-V1P&;%~WU}F}b@*O6Y!Q^1+!N_0&3S%w?h6!Gb3==tI8H7OnVo%1-SstluY#gZ9y6GjVihgY|H~2JMppg{=_-gNQw&@M|SjsD2iP5KT^o zi?5hDR%vHuS>!Nrb$36M2aO|K1eu@n|9^-a1A|CBBjZQVnir56pnjV7)2c~2jSLfc z85kz4Wn`H6j+uK^18e=-Cf-A97O>i{UBuh8<{TsA$Hf2tLqPj&K<$rs&e~57Obj6) zwca0VC+RTqb>}kib)RG8K8?Pv2sAzjYGccPl(#?*Z;)9I|Nn>RWM*6BWNCxPH-7*B zFAnPCfXDY37^ZO8FbK)}G88UmWC($^>lGLpKy}L$21bT0kC4Ws85kXQGJ?yrgDV^u zzfYeE#c?(FofV77|@ywyXV9CMM5+t9YVZp)N62!p3 z(LLWtVds1yfuHlm1b)uv6Zpy40MQR>10ws4M z@;IpN0df@h0)<>3Nyo25F6AdgS9CiFmtTp z?BV?J64XCk$goqsmV2dqD8o-sdzX`u#ZsP;*;1aB*;1a9*;1aD*-~DR*-~DV*-~DT z*%D+Y#5{+eoT?2$oXiV~7&9|LV;Z1wWRyI-P^}r9-$DKY`5Qzt)HqCrx%q!H!$r^- z^+RP)8?FIdEnxW4Z?jnbzt3X%|1pc@|K}{0|6j9M{(sM6 z`TsME<^S(2mj8dVSpNSH!W=9A`-ALZn#d>sO;^n<6CWxwfyM%+yl{8;`O@Fvr#&ab zM<*7Bke4D1Tan^x$`^NspI;amwtV(>__>*pVGAft!q(n_`UnrC(fbI(D1C$%>oMEp zin0tLf2*Tbe({f7`7JzR<&XIAm4EWXR{lTC2CgGP_rq~>HUxqCl3uI~6XO{dtey&&Kp8cNH;pcru{@08C{SR5I$UPe*w}A10?E~!w z+Xbx-YZvhzuwAd{@bi5!!_SA@Y-=CrH`pFzbXoqeY zLrCAx`pf4y876}GhZz|{_A~OlZe(Hzx&8mYc&{S&?6s^8KhHzMY(FFa>$8SEvyk;P z{revR3)2gV+_MGP9De?16nK5suy+>7EQO!{LwXdsXRlM_p4|ZTS3|4A+9uuuw*7d* zxL=XsXCouy+9qfiH$cPq4b*>Uu!J#aY<@o@*XzeW{)epo|6g1fX>6^GwIS$xGt)#+ z9~?9`2x>2a#%(zm#kx5K<1M%p<1M%i<1Kg`<1Kgt<1P3S<1P3L<1GXl<1GXy##=Bf zjJIIi7;nLJFy4asV!Q>*!*~nUkMS0uI{c|J`^v|{Y%3pfv#$Ke%(C*mGxN%~)=Vp3 z8#Ata(9AUPr8dJ#P+ocj?JGa=clZfv|E*+V2m$3Mup2JU+hMQCP?S&pz;znuLmnrVE#~?*9xzfIBFY$7-~4ALG=R&gXa1mb}~$q zXJoLH-^ly}RNjK{|7OOEU;J5C{;g(R`TsxD%K!54@w}f0*ci4vTns9+8K%6DclddN znPH1CLqpI@afhE;tqwoD1RZt;GYWHaurhoEtu+R@^D{GQxPkO>FoEWo8ZN=wYA?hc zesWZn{NU7dSji#iu=C|=hLw=9V5q-A@h9)_6SM|*@xT8eU&NthrZo046V%3m_zyO& zf?8(&t#)1c#ouM+|7OT~2=uUPG-?h4-C+SUgPi#P5x-~Uw{XUlU;LR?g8BuZHVo$i zrV&l2SDq&n;0SM%|UnSf!eL0ae*!-&TdWy$Qo*IQSey8#>M~thk)+w z;Cxy&sSC9BxPbw@?l^(9er*zHoiwZcS|{G7HJ~-ep!OnYT{mdV@IP1Wr-Z-%L%0|? zySte|{bcw+Q|0dr&$>zQYQ%9^e`qgWw7# zho8vn0bpXF^#I$ktOo$CA0Tvw5xIBRc0@tWFY1V5*a^DB_HQ+2oO&oM2;x*&aEa65 z%qIpFjoF}b1eSL=l_70Kj?7H(*e$572^w2v`0INar0!4tu9d&i8CU*@XIl9!oOvaz z>;diZ2kq$qtxE!>3vm%poQt29{Odf~o`K<`2K&reFXbD8G(|gSaWJxcG;5qW>xXg2 zERftU_W4q`*{02M;6R-Nk7i`plJFTd&oyu{{A^%i_&J-4VdpmnhOKtsbrB7hkj2f| z8MeISljsKJMNmFG%_P~K%_!Ba!z|U!tI!ZMpONKbk74huY(}2bulcyUvjNpDu#tQ+eo~2T(o&<*C2nLG_F*A9D~&C+Dl>f+$#?B)cG`($Q<>o}+p2dFQ5aefdVsC;H%DCA(caOs6`$E^Jf427Bu4=!m6&Yxw- z$g!$}fg#9~p&dkAU1^sm)IQ6d{Sp<2$Ex9m;frLIhM1mlvD<_ zVI)?4XJ%aWlbLVTFJ{42f0&uT?EsKEkb0P2kU1dp9x=K(J>s)x+ttFAd& zcW-5q&VCTf5VBv1q0pO=A>@P{!$b~7u~YJj3?G>o8A56p8iJ%5LGzFfKQowrZ2SEG zzxaM3s9HW$wJ{70L9;>YikKaKaxnea_5!4qi=j{(WG)**?H~2|QomK&r9g8kCm4Qg zyZ8UUxC}!>kTq1V$M65!J2}L6sZ&0JVc_%a<})&U%vtI%$$``1R|BKxuUpI& z+cWqWLbTXHXDLdZ$`K5k1XAO()L|0njHLvqIu4K;Zit$C!LUyXoD3ma{0M#`3quG< zy*3NOR_~<_lfY{WnHfS>F;{H&JX~tF$B|Ckr&S9UW{-RpI@;BxlCg3At#-c{he zKI{%Za~P#g^$Lbf+Rw=FF?XrMq@KS;mm4@i^FW@zU}_mY{}0jThNuPIp9`9=*XBp? zAFwfmfX+!2XJ+{MA9Q{oC*gAv9V<0{c(5}}e5G(lN|V{)=Sg1Bc^V8qHQ610p5$lP zstGz8{;r0KJ<4`p^NNP_0_#cvau;6k$BWJe5tN$T~{{I(0{jq*KENs0PxxKnx z{x|6a^#?zp+I#B7f0Lg7|HU77NfOS&1D};9&VY1Qngq(d_So_!N3x?OsErJ|BmEt_jrcZZdreBA#3zc_NdD6%nx&Y=UfPrm*CFaA;+dQP3T!_L>j4nJZ3hpF@U_kSyB z?F49VJLsP0Y)0PKDS`|kJi-iH-Y|1%fyShp1sOu7fcyi!3mOy#pfU|szJba*kiH|r z3?V+R{=@Y>7G?P!o@WUA zltmaq3_$k%&A*&&T04oGnY%mN)#0ZOxQyU=t;7bJ`xAVn$iooQ4>BKzIwq((Z1y@n z{vXl+I->x3o*Nf4>OI;{tPne}>2195Kcoq>ovnIi z7U)bVdq%-mjG(*5afC1PvHv08ndMeJW@cLTfLU*IgS;;Xj&`!Bxc+J6)`XkYuk737A8SO14-<8Z^{ga1R8 z|NAfg2JKAktiuq!iiiJ)fbLBP?XO0UW99?@Lj*zgUP80?5=8IAi@5Do-uFKQcHa`b zY+zytS;Gt~KbT)*i<8A{3?ZO!Kn@p>|3P6@3`$ebJO;{#EX)icI;;#^kkx|p!t%2+ zGed|XC_m!}n?t|DxWv4yP=MabPBf5OD?u5n{@ZwTui~K z@T3Az`&-L52q2UQ?)35sT-(>3l|Kh9A#9#gXZ!+UQ=zNZb zOQ5l@EGEuwPiUJPbY}M}c7~tm=XTpb&vx$o57`p~I@?*Ap&_VV9rax2YIX*}4rYg+ zpmUu;;Q~_+YmYYm`yWEgm>0IQj;#y1W+y2#Ow0hE?<|bccF#z1w9EjV@67J-6a5Ub z4(1m>djJ0y_eQE47}*&@)^Iay^*We;c{LM55UAhk!_W}aBRGFnHzW5d&|LYUkN-o~ zGBAkvFmiy?NFy6VNcZ2O%iKKp^)3GJKSZ9J;b$}Go>i#chpY@Coqvlid-5=B^*ES+ zc_q|NFNTI7FTweg4^uOybK}b3=AUPP&J@52WlG};bRCn18$>3)IH{72nj+nD@A}I z1f>4V%l}(mGK17{zHSy^2=PKw$0EcKqVodO{syVxd95tO5Mm2b18rAiGeO$lp#D9m zA93jO|B(Gm429eb7cRXP?w$pT4;_XFmyqJ)l_MuZNI%HkILt^Q!i2h^%2^*y4lKM%HFx*h(lIK<#I59AWU7gCPW5_HZ$5B+yy{CWbR8E zQpkNKpmAQ1IuDQ<4v3m~!LUyWYz!eQc@TWi_$}xRMJ*PFty)VRCV}>$pJZkTS;<_n z{ltNS%bEuZE^{z)dUdccn1RM`Pac4b=_)jORXqTW^Rj@(g4uAiUp;<-#(zO-8<-eE zR&hYog4(DJAiX>Yz5)wF2xu=5hvFfrl_0;fF>GDN!0;2~zf5k1tt&YkerB>WYz4WU zlM}KJ8RYI&KmWts?fLV6i004w?Wdsb_GIMrI{ELv$r0$7Z1*47m@LO@%|HJ`KyI^V z%+zmW#`x~LA^Y{M{kAnr5?HM_;6@UK^dHnysc-NQu?XWNawV_Y`{%H(Z_#B?*n`?YtGOX#3t0>dLGu|H3enSK(vSZk+d<<2jBMbx zJg5x>I@6O2I$nuOpY!+sA^SNPe(nH`xk2@U+CUk9i!OWcK*p&vp?0FTffj%LAF`hZ zvNjjly`VNwHz9jL^*0N{Pf+_7G^ccCL)K-`y$>pU3?Zup7`D7-=FkGQ?VR}-LK;D5 zUT(~~3{nFMYmhn?0fvz5kN@H7lm!? zsCgi>T!a}yPQOE#l`PB18y{pq9Ula>f$A9;3b`0ATzVzkH479Uu(k)ZjCj?^ z#Sk(R^#wNpJ9Iab*-a=dDM@gLlVgpY%v`32Ml0-1r&FAtyo4@m>L<6!<}Txr4i zDIzVbW@6Zaa!&yh!&X9efXX>sZUnWJK=~Pzf0wZ^`~;oj+x-yrE(orN{|Vah@IKOb zAX+#u-G{W5KJ}2?_KR6%ai$_oxfcp5<4g=;7|H1Y0OJ;^G+R*YF z)D{AzV-F^VEjZI8BN1f>D?>;Ibe;hge&}@os4cV%RtF%JsZSW7WiK;m&mE{N=K!zm z1dZu|+_nPbHl#eJ0WBl&j?*vvOE$fbKJclN%>jI_fD;dB zEm+eeEe4TpPw-wbj@OI08A42D7$&a#1S+2)`wT&Q_7^cTglI7|T;gIl^a->FiGx$5 zo8x8mq}SfTo46UdyFu;nMO+LanqTWKYl6fX8YaE|fBO?BBWJfJBR6;-S`rsS$jX0? zmo-1ueM$iJ7a1BZar1I@7uPbZtgmHU=_LqRSDgI+e~2{$g9vEf`~kH6PzRV8euDPf z!`vYGvU<{re~y*D|iuVixZPtyu<{ z?ag^$R`yDU+1&sCZ#CoR=zhV>a9V;iNkuRUzNJZKLlXg?iD4{VK|11p2ceI|+5ptFXA>ls$c*E6n^ zXl9rw&n))3`9J7v7R){&?A#^T+A`Q0&4tWOLBinmMyUH`4l*~PtUvrh=H5wMYpXaK z8iMK>1U{A+bj<3wG(U(rBg2B3m0>F=?R|rtp?h(DkT?TJH>myk!id50F|)`j73dy> z|3(a!pfzd|tPB%(Ffsg;H+J|0YBzHrjdgM`YjkmFpcF&HBu{13JM^qmk;ffH zQN|rtK*t?lK-b#6h+^2O!TjsTn*aaBam68QeH=W#7!Y@(g4c>L6J9F1bFg*j;4cL!*_X*6WbBWE^Y(#>l`_v zAz{A}G`20_uoHAY?E_|}RS%h&S3%1F(0&&Y4hgV&Lkd4CY@p3T(d>;;{WCQpd1%}MbA4!iud$AmTatJ#7e8|i& z5u_J1R-eh`@RQ>p=PHi34wEv}Kx_LTXY7E^*8#bWP&x;#1O3L#u*!qQ;o{5xb1%L8 zzyH%q=>wlYU zlbK`HOs=rapz~q~&1;P<^Enw% z=AsU8Lgu1wLFb|#@GyjUAeGP9=AuHOb5Wek4nH%6AahWlb$6X23|l$59e!pCGi>GL zclZg~!vv}WVCyLv6d5KyWENZXh*@+Mte#MX))g-l8iF#IIJh`<9Cm6ja%gerFzn<| z0G%lXxg!@>83RfapgDp!KmNnlk#+t+tRqwW@jv7~bPVM67ufg)=j+Zd|3k9A)Nkj8 zh9`Iq>(_sidC)ayZ@wX!_YKLsZ~sG1L)G{osd@SJKYU$U<5%dqwDYycuXc<$ScdYYsbu zU8B9H_{sPULf${=q%^SY@3){SzO)l5$CS`_+9pHI0F_il21oXaJQln9m60?Dy6{0s+=6G8NW@)~H2$qOXM&+sz@B)2i^GS|ke%h`-vuUps{ zLf)`5YE8bk(4HFad#HL&-Nmiv(VhPxCzi3SyaAqXft(xl2(+FCX%5zrks;*GPu%H= z>F58D_t3Zp$2$W<$Qwq6Ew33Ewt(D2O1Lfl{XYa;4npTQ_JZccpmVdJF^#UjMVGz) z<95s9pZ`NXLEQo>+bDGpXubth91r3{Skh#!)u$SuTSzL?^IMc-8Pl)mU%76dGq2<2_=!~F0`K&9k zofGt(nR(S$aDNwaW(Mf&I8fUgRG)zM6oJ}XkC{cm{SH=WeUiY)um#i(xX!>}enQV- zC+K|3>x>R&U^b(JIr9DM*v_T-lkbW+o95#Dpc*EQZfHGb2|Bax1v7&Ql>Za7U-*SE z!_Uu`nOAx+JN$&4i3)8GaXb73wTC+79e%!C%(N2ZZVAbTAPJ@gMGTo0Kd!^tL5dDP zA2u^ge8eoi3e*+?sRPM_+j*ci5}MpeS@?b#iwtH4lM`~_bJ7eSFfoLH{CGnC1K8gj zj7&x+^cZ%6+BhCe4CYWbTY}c>DrzujIsCjW~KOZ%N+zL5A1h!x7A-B^?kXmI}`ubgTIdQqeB#>H=8rXhK zbafy-pmU2s=7Z7&s1FNbgTeq``u)T1@Kb?_Vas>Wz7a^<8xm)lh_Q%=%AhkRq4A~; ziZ{sFh%b~7?WPCPsC%2R?db%$1$3_s=!`QCM$o=MNSo^cH{@J9P#y!h8I~?quwk~X zUp)OE(qZgixk3!mp6)PaumrW|J-A`*Y0+-8m(`QLGjpuk&K0&flg;7hDJIYym^gU; ztb?^;dk+`GmQ!pHF;Kk?Iy3SV7lMC)k0Im~AA%2>=LD5W-bib`UV`p^V?k>tvon~1 z)|pB$Gz3{e*RIckwvk|Mo&?ZZ7bw#kX>ma|w#6WxNK7!hRY-n!fUW6rWGi*Hx z+7l(lu=OOL!_SrC3|r?LGgzMc2VQ3t#POKjoDJIM?f!~r^J;$mAHww&we9Kk@4pG? zUNulScK<|D`}2PYH?(bB&&ZX%@W=m<=TI}VKO@v}e*Pcw>JzG&tA0b)h=I(^{*I*f zJF1zD-~NYOf|}|55uxtohyNj`(AvmcKmVIF!qg)9>E#zxGZVl357`S<*NxQP*ZlH7 z1lD%~&3i8V{6A##|Nr8kw0-0s;!IcAm>crGXl(6rM;%1F9K8?kI3M+F8c_Mw2_5_B zjAqygDi1r+#y_l}ZFf&-x&*b|LFpB=7fK$j{SHctpmG~D_7n|O4@<|Ou_sWz1GU}3 z<)Csy5Et`;BF)UK9h#O5f|{lb7bO@PCUK&TJ6UFO%~n!on5ZEP+E0eL-c4gMgC(d; z>VS@abVM`k^kDw+!~g$(@wdz}tF(~X?x1@R|1k5e>Uo7|Ge)@ll z76-!?El^t=tu3Fz!4Ts8szRLvTotl({%HHNX9aj zm1W>IJ!Eh9ain(iLeO1)e~T`kLTb~a+Y9pF;Di?9dVKY(e?+8|AF#M7bC;g6MPVN7l7Oi%?qG#1GV#yfcDNXGi(9f)d-sNg7x#T z`C;*={~;i=;{N>?$JZY~*ZcSbq(5+?O7n;RzyIP-n3+~RW@ZGB8-Ut>(Du9tXiV~@ zGE?psf6#dWEa0<4L1$VrJY&~q;9>YHFTn6qUV~w$ybi<8Miz!GCJ6!)GprmdLF2NC zvmACN**R8%#;ZYfd3_xxY)tZRh8@G-1f>JEptCI@=U6Jj&$VO%pKH0uFF~onHsh5; zJkh{w6dXwPBD^^ka}&kNEmwsavL0rKT^IGz|W+B z`Q;!d2Q>f9 zsEBWTYd=zI|~1_qG`eu?fMd<;K9 zzsFGlIpr!-2a8O|9WCHrF`~h8{~`0aYd3O|eU_EK(pgvjh-X{*Eu4Mj7k`eGf2%oHg3bm2?X&p>KJ%4v)gNYtRS}>w z3KSq`6iX^t%m&@fp~3v(M+PT@`O1I3m!W<4pIp#39YFF#<0>}v*<)u8YP<(mic3_s-=7%Vw>#Jd?7B)a#rF<9>BVzAuL$6&c%h{1Bd z7=z`0DF(~^atxOL*%%5zXAZt(W4O4=j$vZ_M0tz&h4L2h8|5wH56WA_UzE3qe<*Je z|54r|zLf!V?&Zga|Ne($GCAx7h1Yjx(N&sk3??7N9e#q&I|Q9G1j>gXw-mEM=4iov z-f!$?^=b@-uscf_K<9@tG+Yv8Xt)GgTkw*-K?oFPU3FZuwLp7mSsi}9X6DqgXJshN zZk<1?UXkJBVkU-=oR77a*D~>R`!Mo!?`Pt9?PTct>oFrk29 zy1>ZW&A?W_mWj_{?FJ?gn_(>zALH7!jEocCD>8g!gx-M!I)f8*w*kogpf(74S>HGb za$Y59-va3D-`hO~X6Doaopa&M$l3jkS$q{}e|uJC^$*X#wU;A4I!prjbpZoI z$V(Om(;ZdDKfW=Gt^(cZ&B-Ww+UBqG1%l4Rq|h!QtZYa|NGd_ewsQZhJ-sOM6xZOM6ZROM6}hOM5{EOM6iUOM6KMOM6)c%T9KN ziC^U%e%doiz6SN#GMQvfYqBy-T*W8T?PW`RdIq`uJG1C2P`HE6A>(9dm;^G%o>BPq z$^ZXDs@WMP)-wyf?)>yWM4Ev?#N&C@q?b($6G7z|=x$or-LML*_G^`Ro7QB*&h%vF zc)j4q|B!g@+D{4JA@|sNe6F2zl8L+f6==L4%N@4y%p9*7zW)zd|Np=EPkx7=#S9Ev zLF*Y-a5HQHx$O(L!_Nk^dt=Hzfyx3%n8L~e*x5Lfxfphau`+CV!6eo#&%p6|5%^vK zvF`s&9Irw5Jwf72>@?`ioEKQ)N{WF&A|1>Aupk4WN|Qx!SC*col!NJ%VB2*7ek>l3qwdJlfzHV$c!JL zb6|ZK9d`OMI_w0UZIjK&FmXR4L*ZNI?pga8IbXkEVgQ|)dl4j`C&<$c+IxG(aQ-aN zc^1q}3?W{O4m;x+846!9chAyfgUKtSmfbk7o~KKNVhx$=v@$I5Tv?kj)9yRH0{?z-|% zKIoh>$XV*x&fr$$VAukh#|Pc}1~O{_J7^6V!z$3YFvkK$%c)EbKX)j(tmI^rIBgGY zLumYUo-D@7Fmb1r!%r(_321&7!_$Tkdwt!gW7Y#K=atQ3X4tYq$>Ap`uY=kUolH{Q zT#QoP^O4#R@u0lU3|gPoa7mMaL4<=}tb2tTavK74Hj(6M&>3Uc+7Jtr5N(JKKC$jC zN-Qfo`NX?dYBBs2Zj}Fl>%4Q%=g{-c2($;{nK@sB(hw*wEdZ^XXXaex32hH_<7f|n z^nltB7om46V_VM$Yqxho$MiWfGc7t9Ky7x0Rh$YAJ2M#=Oh9WhN*NeLKy6x1F336x zQASSCI<|?Rb4vf$L(eH?X0ZIv&S3eUo5AuwKZE6eVFt_p;tZDmr5P;$%QIO1S7xyM zug+lkUz@@5zdnQIe`5yA|K<#q|E(D;|JyTIg6?#KwZmR8JN)Eym>J|*yu9cYcf(HZ z+J+#nTJG5#nw+y&fX*ntJ3nYT6G!)BCWoJg`53l>?!zfza`^d$iQ(seeukeNNcZw6 zF*1ZSFgfhxsI2(GDC_X^Q8J{B54soUz`y@nR2djVK>9n>9Km=1WhvjfzY0hKr4K96Wa5NJLDz0U($ z6AK=1V|3X0f|+6G3x0>6Ul%j11oy+lAo0Y&$k`2EzvG(auq;=VJI- z&&2Svo(pncBJw$u$ojzTGw>V-;+#oXTNm5B1Oo%=yadP&(7Xz=`S{M~Qj%xb0=g6E z1(U;1?;9!%9$o;b348$>5Ud z&hTdVDRoeO2Pi+SU~1SY&&=_f3$)%zOrkrH%i-q(kU0ztQ>xe;e*PAA_*uNzVG_-Vo{e7fVG(`0!@nb%5x|HJ!>sO>tL*BzjC9XG>I zhOc#(L1hN4-Usy=O_&+BWVk#0oUg?2(V3AU5!t_E;(Xok z_kYNIuG&uyf1v%lPXzjROq{PD{Qe&T+6&;x(Gc{KpW!EHF7$9tg>97Db1h9V`rj@|+BXpmEL=t{>*0@~ZQX z_hn7Rl1ZTT&>XA`6XjVQJ~A*dgm5u(cE>Zid{hFh!>-Qy;q|lr6T|=iA>N#zGxu1s z8yLXtm7iVz|8E7YKX6QBnCQgm@beaQOdS-z*Z=<)2i;8x8sh==v&x`p6*hj;@algE z=x#_*xdgkPvg7~%t*~+lCI%~)JUAMHUVzRH0nfQggYz1;@&FVT*vf(j!l-4z17=8m zC3GH!b1mjQ9SemTf>@X!_hU6zV9GNJLB?m$%S7b4B6KqgP})H-q7JwgDyh|=fD!Ii<42ai{od}We!;m@EIdqf%%(5DmCHr&78&z zTVeCfoTd!m`Q}bz$b9oj7KSaL`95#xTD?YdhLF|P3|n6?Yp#-K4g3U}uLIrvCd0rW zlJ%>7n-}z4MbI8y2S(3dCzu#Q&i?-|&V@zp1tUYqDbP70KQZ-jFfxG81oZmZz6~_D z%>DEKR*>1CJsvB6{0{-GV*risg2rG$XM)4l1VPsrO#!#(WEw#C2^xaJhm+Z1r#vHP z_CZbt(0I~MGggL)WlRh|S28*LTm_n6KghMp{H?>J`$i6*K9=WH14pKMZX%S!OUYn5r-^h^zpwtNLIL zqB$6uj8^C|>;%;daCOWKCM&cYc4{y)n8Mm~;I&fRptVv=usN8Y4$51Z6TAjX6=EM~Z5HTW z5>R^+)Sf2P7vJVYd^|HE-QfUQD+C&&1ljijOFSdT$BQrjO%H(fAuu#t;)Jd<;KZ`W z0^1q`(78G`IL_AbfUXgaA!Ch!G(*FrOtduyHkrt4gE7|_bS!4DrOP!NG=|~v|K$nLT|A&MxWVox(40F) zJHZ2Wzs3u8P#G}%;uAE^1)3v9u0KHag*H3G)|bqhtL#|=KRKNFA5slk|G>y`3SP%B zGlX~}sX2K1e+X!uNX)cz(vM_{nb0ExeJoP{1J{!Z&0La>?OM1|JvI(RQy1oOn ze_n-)A>=eS!(Tm!u#th>p9{3-!^#6bH z7hrjg*9r&!hp7JhFAkGe-2Xph`Tzgor_t5{doeO>1;r<5&nvQ@kkJI`_c67hw9yrNAJG>A)qnk*E`Vk z?ttpufk*Fl%ylaF{-UNy(0Yq*MnsxC@Z*07sQyGwV=hb#A+MPkwya`e*aAA&9XY%( z(f|YKymf}Hk3eT{fa8SowZb=uAIOOV=3kI?ESb=CEbRo`|KJ~{`$20(K<)>v6(Qt) z&^^mtOblB$fzIecJ7?h(G|e=E(j`**Mou%$U;c-H`nIt2mjH4QN>;$cO;Xv6Zbr5{+J?O3qqRhdf7kLc@X#e2}CI%C5+quAD z=L<&A+4i8l=Zvew7#c2t;sJDr_I)Rf*P!v*m3|IC6)MYqB>exs1=J32V6wlqqR3$< zsILj@gMJG?40a<%9f-DWlG461P5P$Hj2DsbYXS9{JD3?v@%7o!-LVjSuQaqhkJfJ& zh4$M)>r7yMcThhbnU8$8#(!o;@LgS?{yb=$7u(zqXwE>C!QtnQMW8W13GkR7sK2Q3 z*9kJe;|H7H0gd?)F~9Q-b-WKWuLPdoaU*elhg+@xeSEO&mqqhfX4qd zhS<6~P@k35GI%r`Aoorp&sV|fWNhQn#LP`m)2#o@pfzSpD}SXkuly0uvhrIv>&h?w zY%Bj(v#&%x&-pj_4jRT)KbaX;F>s*f6VN&w`9Dl6m{hK3SIjHTK5B*CxWc~k$#;4 znJ1Hk>F&tIOyD^qO@7X9PkDx) zzxf@0iZ{ytIPt6K@(U)0ouIKX4n~RY7iPQ)iSspRZDBoVzUl{LzA6(sU!~2= z)7^t*Jt9aC!;k+V+wh(d0%^~I=ItP3UG6Kj89BgfRX}0f#pSRw`>*q4p32N0J&d5b zi7Q)yk0AuIK8gFa^Z)-L3~Z=r3e;W%?GyZ^4RVP7c&rmuf|L zUFsrUNcyP+t()SP=zd{`+~y##F4YQ=c20oSr7E$nJjo~7{nClyr)Z=6j}9(}ohz6a zc6JCk{9M7t@Ux@HVJB!l4m2OO!im8Wbe~!WlUO&$Q3p#<{kY=)f71hO3==_hH)uW$ zlwQJ^7`EJ3g4_)aR(p_PB50k|BW8w>jzgfmd}7_8xdTw&AJoq4Jj5^&bl)@==dqC@B?sL_C zTJQ_9=Iq3$+DVy=BHfw?876Xp&K|?E?hK^w!O#C8CqQ$!B&^YW@CmX;cfm(Up6GmNoPvl!6UX@lH4o0(zD2|b6O z_0VOcu?`EQN8uMFZ4n#iT8xmjgP^eT z`s+NIyE5|!s6AfKDE#^W2Q0q1Am!g6j&IO?(jY(RF))ZwJH98^F{}iQzjrt>Sk9+n z{DRhFfZ~?{y3UT6_yv_UXTamT4nG-JGVBEPV?gaO5KT-wb|meSL2iR$TW>*W8yCI* z_?ek`73iK$*g0hN3=AK`S(;`spsg9Z4qEeywtkceeD+<#r3G9JKNm1D{OtHtdwDw- z!%huWhAk)gM7re}IKgX*IT<**?HR>hdqVHg1f7QnxW?T4&mGi-s$ak4XP z=~QyCT*<~@B5%u3$i%@A0vZQ{$TLhdy_o?z$InuJCu1S#+>@1T3=>cDHUz=OL+WK2 zia_HDpt$i7b+D*s|373JlfzFlMusg1l|bh(h^~T-gEcTSY`w9LkO3sg9XTJ@O^^N{T85gk{XN*TNo8V zbIy?S6hY=A_lqIt2sT_o76X+b=wk+ry3HtOwPDC>qsoKM^Tc%r4=Bvc86AFp7h~80 z8n1(e_d^DTEub}IptH6*85p)?F*)q?Vg#=TzC`GLm#jsOmZ$#x2gi+)C}`Y$ z-+mT!cMe0tB_8mduMXg`nQT^uiJ&t=L2E5~E3<#BV|1{TXXMKUwGs6g8iL+4bFBIg zvWI~om8W?%)K zI|sS^#Aq20+9&k+e+a0aea+hTR>|-L1FTW3lts_WQKIH(VPG9@BoDc2P349bC`i4 zM1$SoC+IvtSlS2mF*KYZ_Y`q3zT7dBiQ#90oWsvh@R%MXzrpr9KGa9eA22gu@{MTu z2Ucfs^f;`1`I&K3X6V#U9JMEBv;1|r4BF4;!38RR7{TY_g4SgxvoLG~oj;qw!f>&k zf#Vfu&gBI&^D59f@JxXNw_Y%Fo`&t61MTnR+my^g<)bR7sF3Z=7yjQ1;Z<*$Iac*C zI{ds3x^Eh^pGT2l;#yXQkDxp5p<~fOLJSNd;?TADpfvuSjY04PlfzF?+o|I>yV-xF zy@ed0G@-&Vn}gHgCukjg1_Q$u(7GoM#s@n-Te!r^FaDA%|5i)E*HMAS$Y0E7_$kA{FadNg7Rr8-B+$Ga!z$2O ztkMje-I=hxCXAfjT9OWyUfc{OSE`#m} z(b=4J*=uL+WnG4bpjC>eX02o5?morH)vdof_wriB^Rw17@pQjskbMVYjGWz|y{({d$lzcw2f39~2qFjG*Q4pM(u0u`yq}Ka zughe4R)&upt@CGTDl$yeT3f#|o>Am=mr>WOdPb?&-p$>!K<9}lgYvE;!$b~N2JrsS z-_nrvGnxzylTI?d{Lu-zyO$5Lhr=4S&K|n1=^-ma2(lYw7&*H;k{woZg7(gFFobCR zb(tK`%J9*BsS|6P7^MA;F=sx^wY>+b_k=J6w#9sXSzZEoh zh+MWeGcbg}(jzFn!_sXN6N88uLqkv(x5LkHMv2oe|G7*CwYfoe#%geKV%b+N_WFcT z$E;V%Oe-1Q)}ZVYFlS}h0t)y4N(>(#gZBZ5cXKg{cgr(C#($le7()ItF@Ag$0BNI7 zW?~S*=SB{OhDo5aBqNy^L?i^ox@WM1&n*xE)yZ0n65XJChe6}Spu6qC=?rZTI%pic zff+Hr@qk%;m4tv;cSAD6O3=Bs90DBO9o!5*MVRF+I{tZF<`4$a0hc+HL3G09&VLb? zIgRBlIGjQJjLRIsAiCf(M>2@6xXe*3Zz0tzZ{hLZ<1)u&5FK!tV=;)1xXiH`L?>M4 zI1HjQE^}N4(FK<|9)swL%N(EOEnxnGc!@&+IP`-NsDn~^a%wO<1`~;n0|B}t&r=}yrL{QnOnFz^4 zpmlUwjPX0-8O5?e<)Bt${Ev7>(bu4T%NmT3y^5eR4Rp2|sGbL<50JUP7#T!hY|xo) z513ijK9Fy){a??vGK0BcrzdESdo8%W{0UnB^7?=Kq%6f#vosmCx;S__yFvStIWjYU zaQ>~m3|h~}$T)x2_rr`6e>5{rd~}#`;^StD+jZqbcZZ)ZCPT~s>3zU| z0H>bc>8>lmdm{KC<)%2aOa;XO2S5Crzn`4^5P5KVhnA}jYz!eBe_avfDlG0BA#v}( z$`GQ(82@8FGuLa-xtZFaxM${m{g8nnM4Qp!XFW6b>qZcp)#0Z-GdFmi03<#iq~`Dc z5N%eF8m`w4%-+8e|NajFr5(_m4kKtU5qO^$r2UAki~*f-3flJu+FJq&C(u4NkUzoo z>??LN(4IHg9{!(5W&BH~mp?##D9{`-7qpx=hnDj%p?g#s!RxR=?RN)wxJWW`c56V( z`UXx=S?`J{>m3;;evpRrWqKMR<@y13hLB!x*zkhGrmr#nM?5nhIBY;|h&ENkaAn|%;-q#Mye&Dd_ZH)gR&&2zhP}qR-F(__@8NvG`!S}DD zhfl@_)bIg?BW(ZRPiPpx>V^Z~QTGpm!Wg-3fQ37(Zm@4;*a-5w7ql*82CXY(Xb1v@ zk2bf%&m2aH)17}^Cxh-51KsKK+L&=A_WFS9wTEHHtQXo$D;Zu^qtplQ_#J+}V+P%? z;PCUlB4kdGlYy_Bi;)jrCxFfxxzEV>u}K+HCuo4eLzJuA0(8bC0|TP0=Z4G);wtNZ zFf*)DKq>1bR=qgvv{FKZqgw$~-U~bYYov%E#te~-&t!XP@}GM6%lj=0Qa45AY*b2)?P zjLTfX@)n%Q@)n?aMxa^Vf&)}XO$O1BdWPd4q@LmU2dQT`{z2*)j(?DPhT~twWze|; zpt|M-)5{;Adgg_?+e$9*U6c$TyBHdRt}}H>f#!ED7&~Tx>TcvU5#ark(hOUX&-z4H z!vQ+$Q;Ljzlfj@nKp1vPurT}tx8*n>Z8`KjuE@&}@&Z(@LibE2t2z99WbE+siMabp zP}vJwM+M3^$yyFSADKJ+d@|hwMLbi@;U~z=T%d6(rUgYDnOQ%yK>K8T9ey%aX8i!| z#nMUvo%g`?x*4=aF$2QZU}OjZna>2>zXvh{Iczw59e!qNIs62f1u{otslz1A6v+Ae zj~N(3G&3OV4hB?nKxV?`l|l6dtnLGqhoHKJgAuW37HlU6QhCn+J;yT`eUBXE9M%Ww zsAq#d@JHqU_hS z3_Im7Fj~sjFs+n7z+fr=hkYd|&B}K$?1bn8-T%PwQ{DsAPh*(C!07OoA%Nj8=o~f% zUJgIThEp~QG79js*g$8q$^YSA$sn`PkD;N7iC${DpSi=a(wPBrry~Oc z>iAgW5k#DW&cFK+&$#kiIMYhxGw?KI9Cm{CTY=W7buclQmNYR<1fBD?g3oOS=)Mn7 zd9?z%uMD&=3e+zI^>;yI7Z1U0TaOnmAgHI6tLcfHj zE*tc50Q(CkH2J%`)RE69$K$TR0fDfX*iXjs1i6#Z6;k_zBtvr@+Y&0$S_y5_<1Cwmp6E zl^Q=f2yXKxFW!%vS(;QLZ6 zG?*Dowz4_=?2vQ#Y0Aj3rBe!0FM!(H511kG0+JJLW%$t{$MCaJ40N9i<7uW&=gYA4 z1Ix>xGwnDy9Cm`vk?E9k_^GMLaIsU4;b+DyhMm~%)A-*EUrQV`^&e!n;kOR86ObV(V)-DB|Uki#S(D}8n`UQ60 z8S)vnlA!aE(Ds*EC34MnQf8Rw0Y1Z41bl`hEG#;b94$Q-GgzYBJ;D6*2Po`8cWHwB zIqUy_apXBLaNcBP*ecA?04=i|esU@|1aUGiC=$uc+#$-qFku1OU1gy8Ne&ijCp&O?5+}ohPhN}+;QQEKF*BT2 zVC3rJVC3pzWMlx}AGV00AqZ6Ve(`r)30gbPz`!7a%mjKjA#)JR=hj1}4h;SX9AH^NO*S)=UD0eMmTiW>`Gq%7}EPmFVj*OS~L@axgGXY!GAk z*}=pNE<-_k{Xz489iTg)K{0}n&U3ND99$mQV6U#NSVLFHgZn!``fnjTPj z2yzps-T~D)rAG0*16D4cfYv!2%+Pctzz_oJW1`m~kaG$kcLIUJ2dA*Rj&)ip<5JT7M7Pqy7ZiX8`2^P+2>ZiL+Z1x{p^gnqj9V zGwNMw)ZE7lFKa>LFTVT^E~7jgelmz6#%4k0&Hu-=az3a&yX0sIOOGd57)(Ka0-d!#6?)eG z0#3qb?Ss-cC|#dmVlc&*p277zG)*hwNTcX!8st`xn?QA1Mi!*K3(D8vJPjES`-!~A z9dvhEV^+owaNg!c%G*$TLHmcW<)y|dhn)+d?XjkR4&b)fd^?7p^jTx_=w$(N9}ZXB7Bn{sa#J!F=nhVn zRo|JJR{daxtmzj4y9?4j)QETZ`GSdIi$XH!{5FT5n#l}5UotXm0iE%x5zp|Gfr(*@ z7>C2o`)mw`ip+?49$2|{a7#-N=v)OBh6W*!Kkd^Qe!}!R{QJMvtk_|v2Dih``%E0! zp!xL^pmSD>LH8ko?jR9^++XAG@ROm^><8$aK^3rCmh2{0h7jfghn>o745k|D9xIty z873+_GyJq?WPT008&QRoVWNsV!%xs!=Z9C8%xd!N6c5S_A4+!tN3j2HOv7D}(MV!PnNs7Z2!i524`#3KMiW#;q+l z&+A^er3LRidE?d=aQ%V4jsj#4Y|R5G-kTXg@y@UcIj)P{Kw%DvchJ}nXg${#|3g^! zS0bk|^z{CPnRyk+j${^)9W1LrX&#ieKyzZqY5oPMjl#+>@r4(|&&SLXT2G1`cFt#z z$nFH)BkBi=^W+~7m>IUP6gcdh&%#jH$iff;nseePVAv@p!0=O~0vcDm4nH3Tm*ugQ!*uI2=T?U$QfVboe>^6s=7D5z4`^WpR0KQ%ZRwyeD5 zXbH+s9bODSI~f^FL348}iWqi+&T0Xz832_Tp!OW-%>8;$7;-R#;8FwHTgy=?F9h0i z0J;ySgP|b^WEN=6KiE7*Q2G#s=Ly*OCul4Nv~G7r7wl|4NP8UCzd#R1mw2Ql zNCLb@6LtJz;Sn5ha-<~)v<3&=9K~fVuz3xX@h!)r_~Y>4(Uu_4-e^#M`H#Lo7goRW zLdHeKGBbZ1Hgov77@W?TR$WN~mFJNBbE3#$=L;qV6VRE^C;cGvKA<%Rpf-L3Xsnmf z0dzLn7H?69pY@EwuR&|KybB$6zW(>$M3k9fYrH7K&#%l}t3Ln#FAghzwlXkmS-|D6 z6EwF96Jua#5JFDxusysO;W4ijUZ#9zX7~w{2l*3((ep4U|2nfUYz3{e1&slL_VXa8 zTd@Ba8B9QH#z5`?ukUi!0H47N@~?Si#gFp;|F?kVy+LEn3z+P$Edbr0R^+hrE9Bfa zA<$afFI)~gL1hid4In=u`vtbH73Nl0or0Wx9x^knQm%2BoW#grqEW*ZEdQ6W5OfX& z=v*CG-xD@=4!SEATYbs+q6r>07ieYaTO;X)OWQsbbln zyN_4+IsD|PO#b1)%&>*I&|xPt3xi3$07Kyd7KRXJQHP(-pm91;(A`xctB}XWNDjNx zIKu7>YS^KNx#Ahz?LWseEkP~N{D7`65lJ8D%nw)^ft7#YwJ;aw2Qg-3?f~tB2l)p* z91pWW%6wQjqNZ^~ID*PDP&k6xCRf=Qwt&NzgP{;~KHdI943=M*8Mc7>fh!L&Ozg_a zuvo>wV4{_&0UG0)2-+(FS_ia}iKAQLAj3q^-e*llj?-F<3|jHL4xbnp8A47nGHe0q zwMWvk@c;i1(EfalkF}E^`!g6`cY^L8w`G_J8xz~V50>u9Z-X%I!5(jpd+^6w)Cary2bGa*1cgJZqhMljNxmSVO6$k(Q z51G%#0A5FWpNYW|WPS#U`Or2emm{b@xh0FuVP|I$$3$-Ch9GXn1w}j}4MDn<89Ubf zb-#Qrw06=uCcf@-nb|+qt2#`2U&}N5RHpupT(Et-VEaJh>+`u7!S>ZNf!6&Z!W=Y? z{Dhfd73a z2S{F%mEj`i|NmP-VF~jWBLl-vCJu(3@_!gtg62m-aSSSVLFewrvoIDaF+;|i85V%{ z05NFE^E!M|U}OksVqh=D<$rBZ8Ou14 zkpXfq$qQ|VpYnh0KXx!PguGOD_-X&w{^JU8zCcy;QrY3B0wYH^7eiB!7bC}MZ$<{K zdR~W54;UCiRxvVcftMMq4j*AA$^4d3=F0(PCHa`_=*T|*fI#oD>@W52s4Dh z>{1YB2m!5m{BO)`8zzo!(47~a%nTu*J8eLEvJAUsc`@>we$B+wt;xvKtt0ASkpsE&2^`1& zvotJT89V&UVr1Cj&FEnHnvuZ-v{v^GGuNtYSq7o{y$pq&jGeQ(WgRTK|NjS_Au0kg z8&scw>Z2xJh+Uww0zvvf>qUK7J7=wAW4QR5nR8XHtb@hd|Nl+TvN2rjVdOdux|^fd zuy>X(Bf}PuIewWr7JQ5hCV81U7NEOy_A~Ol2GwzIn0Z%$`Z*vq^_e;rub4$wd5bz& zTw`Onc>4c;Q!QBsi&voVVQ9D%#>lYcG|2p{EQ>b`3?@36S{6RgeNV5Lc~*h;I=x~R zTLoID1X?%sgMGf#ea(DvE`P6o4w#-R2sq@MYr?C|poBg2-@>JC3QGlK3PLELW!au?_vVwgP; zcL}4o>u+`N$}j#wE5C&YuKW=nu<}p7|H}W&tl)J&JWs18fzm~;Vb`p+Ppc-qYhswl z&%iL@JtM=!2dwpLAMqYqbAZ);?IGT#HEW^w*T^&Sygu;me~3J1?Wcsd|3h>cdAi>* z@pOaC$v5np_5Ne+q<%*J(>xz*CoO1o_;a9@;m>E4*NKC{!BU$6v`>yZ8+6|sCkw+wEf$7}p!No+PS6kq?PCS)XX6I%$CGE| z&IX+Y$6(qK1+k|g2t?zXPXW!9NH8-@6lZq$X(r(CQ=XZ{l4CLGEM$hlUT(-fLC_vV zQ2U1qbfzo=!vxU!UQPxFOVGFhXbmW6e)9nvLr6|#)(_BLHhV^1@ctUm-jH|9obbJD z>#*!)1BKlyC#`Ppg%04m)V-KN<0%YPf5voTBrtv>{ejs;%_K-sM@^QUxVq^$e$>d=94isPTeSeUArXa{*4ze4j z_VB;|A)qh;g+-YZWM3a>y^J<9LkK7wK>PYYX1!tN&_aX*&uayChLGIKEb#tDdq(8_ zjhx{9ji9lk^*Hu7g3<|SZy{)pAZQ<9F$04LC~UkII#_10Fqpg&a`>sm!mve(q2UrJ zOkQv~{FD@xLfYp?TzEvWGfa$UMh_1u=)ONlcr4&xFbCNOQ;QNF(0z{J@L)#`j~C1w z@O_T3w4uO(nl?aVWyGWn&_2f(PFmd@3mq(9Ff*9E0G+GC4B7+RaA_AC!$iz|j+!X@ zK0)aLG(V4?9w7TZVf!2*{#9UPFbA0r9tUIQcn#VM4vJsczE9A(C!qa{pg01Rv7j+l zP`!t3&*Mxcho8v%9ut@xe*Ue-Kj((+tUmb#jFy}n4m&|@&eiOob|Eu(-#lpi0yLfn zN{8GG4nI9m@*?MJ(3*Z&UIguR1=Tx{@J8$_?Zc55PdaHq_LZ_Qn4ARdD`f`VkJ4~y z1{=df(4FS!`)onw5+wggfcM#g@*ny>TS%Vb1m{0cn+TNu(D&UoFfy2f?1QNVr8m(1 zIOyY7ztWF_=QApq7{L4Keqfoe;}CH8=>cBn1?dZb#&ALB(}DIz$ulsBfW|sNZQ_TJ zF^nn6T%h?m$Ue?YE{2~Ryv*GznIyVFdpNcJdR*pWWw6xx8*rJ66GTT`=Hdm>375G9 zL3GAtE>RF&aG6Vz!BX>Y#bwYQPS6=Zpfi59HbKthImFBmGK0(ECnvLLx2B-OPR;-S zO)~l%R`i^51lgCm z_~-u+^g0E$rxJPm2-kQlHTHDMvoQRW|HB4ervh5*$DqORm$Bg}ck?p#F~CHVSH zW?l|IMVZBZj18?e@->_*8EhE-GAJCdWsp(wV~|INtE(V=509|7# z4n5oc26(OCkC%%X;Oda)|C1hp*2co-GZ`j==7K=y>10CB@#lE!FeyU~G^Y=_M;NwN z5_$Xr)L(;*U5GGnbc-@LP2A4}+WQ3QbAj6Y^;xj79Vc*m98{-)@(3d%we_K9f$~1cEYLn^PR0dAnM|DB@V*=)#9Yw$Cd|zFNM_Do z#IO={W(>$q zF@7-5`s;q#%eQtC7Xw$fS7yeKY*mLzS(==)y$l_8zWVpy6g0M;@z?V*himO5j*N^S zD;OEJWa>Ih(tKNU88pVmvDaY|hb+TH;jOik9)sp385pKO+=b|GgU*;l7XyvQ{Xfin z@lQVI%3tYRD}TguulyFyv+|2S@5;Z`d@G+?Gwgg4&ae}7-raw7hM%Cd@8ED`T2Lg# zz|s9!pW$Z)k{=%}W?CtpnYlxnxgkgz2j2(V*a6A5#XJq>LkeML_H1^@qj68k@xvvM5hPa$LCUSB+ z{`6*d*y+W|+3h9BFwv(nV@K~__seTTYbWV4^LDSztp3rb>M-eCt?2C4nR+{X*co<$ z=2BlX^Q@9*WZc;J?|+B}Xl*4oWQ;4GnZXidKWH5R#C*n|9-JKAKa?GQN^mml1cjBb zBE!TN;gGpMkUKzY4PbY0Ens2@0qwB`o#TKk4qD%evbUDW;U{SS6zH5|Q2QUex0cD_ zCusi^=q@GD9C!xPiytQ#7|b6q%dCQhv*YLgA%zSKA|N|JafhrIG{3asAG;aI9@w5Y z(7AD-H~^hR@xt0+rv?v$$qQ-FUW{XxK_%m}OQ? z=41RZ-4c zq}~Csk;~4{QKGX^%1@A=811it`VpYDi5v$xSHa3pP*{QXz;qik?Brx-Gy;Vq7pRp)q@4NC_ zxX;QT@!l(crF*UXlkd6m|6yiu-xrj=R)FRW85%BiDl<$3tvS^C`{D#>Odx>?d~aBg z3FsaU&^ZDO3?ZQL2T)o7-C^9p?(oy&|NpHZeI`&npmAeRn(RSpBb)?sJ}0?9S7Fog7ct-H+2+z`aexS)tn zq#+38FVMLIpfMwmngnKskYq-Ooz5%_ruvKyJM9@6cIGoO?EJvUB=nz=p^!n!p$e4m z{h5B4y)R`D`taBNvVdRhBmoA2Zh@@aAMZh9;f{Q>KQKD{6krtS{=mra^Sz-1ihhNE z|3e=C|1S=zdmb|~g4R8uj0Y?XZ^k*_yf6&6+{2LOpvTNC;JI1!_8Ma-LLaQY6J}tT zkiq0&35qMwT0~I(1nuzxl|3AdFTwK;4QPAwLFzde8BAg3GeXyGfy@Avw;4a(Ked^#X-IXxvVNk--ua{-E;e1vA*q;PeH` z;~K2@=y9NIkx^b^=FQ1GyD)CztRl z7DmXtLjxPb76t`|iOB8;E&TJ!%9%U0%k5qF9^fZ*h6N9RiJx9L3ai{ zYG#lA$?FBQ(X;VgyE)E8V zm7I(Wr|lU{JCbOsw}ZIl9|{k04xhm{#aigtt2pM0R_YfVOm5cGTs^9Lx+Kru?0 z1`=ataM%g+=L2TY8XA#RPoVuPSX_YS+(7XRa)Ui1!)s21&RL-SI-s-yvjb*^VmWG9 zf%GvjLgt}CY|y%T(0!>7*yl@u^dpzQAU-xVATb6;21}4U%sx;#3d%E}`~s5aWOT6X zWMVK+VPY@^)y1H3B9J&Jd>-;Mt$e`Dxbg)zM!60S5188>n^4`3WY-i>SfR!{!zxf; zBr_`my#C_k|No|-G-$%;@DpTzXVXgyQC5bF8nO&R84L_2pfn3I1C&OtF@ffJAY+^d zxEywZ*4aK{hMaW=DzoM@Vb1%5?0Ut_v5GSTV&BUD|4q3W8ZK#OWLtp7`at$)vNBu* z-46vCCk3S|P0|z}4NCnQNh+k!x|Ekw1GO z149VtOgno<-q)b*WL-~SNMIv0?6AUT+OK=w1RGF$|SgZ4FY zGB{Xjg7!o)G+cVc%&G|Nl)vZD^1gpf)xGOUEpbUXVUc zs6P7!&1?>aj#->C4i+H)BHIgNgXU4bg|n>u;?KJBZ#BHnVX48182|ZS&$RNtG-#fe zVIpG#q;3QCCFK9|L*~WBLG!%)ka_WDR5dS!q4T^A4fyB983n-Y7|`4&QS;*b4Yn_Y zA#=UZy7K3ICWen3j8kU4@Ml;FFYB5?<5LV%Kx)zJm@mT6xj=F3bAh0FOIRMjJ{O1> z|Ay@|0j;M4&B1}(fR_GI@(TL=8>mkF;t$!g$im~e5`4ZJGeZby%@nAX$z{;=%bT$!azAuA?!Q=@u^D5Bz zn+BtUYsXbAt;& zXEB1#x!lTF2s#TMG~S-c!7vdtU-;txe^ZT*@fI3?!DWaD$Xo{o(Aq@?%N7=fi5W5u z7AyWh@(aiv^BGXfLYTi7c0ktka4;OO)RbWmwrAwXhUa}*2BFu?Tp)L^0-fs$YBTW2 z9_X}6K=1R!_OBC3|kuHK;teBKS6t{U;g{Qb-ohAPtZDP(3$@$Kxh85;y&|# z8Y|??f6#mqNUb~r$Lm9&_7el>tbfthnP7IqCD2`J$Y=3`&M5|+#n0KmFcEZCI%qwT z18e;$dhg2hdJ5rbuY8G~hg6@z7c z9fM_k6N6=a8-rzi7lUPeAA@E6BnHd+X$+S2vluMv=P_8;FJiE)U&dfrzly=K9w~0> zk>Vx;DQ+^LaRWMY6m-W>rX0ghP~6l*;|7!mVf$lH(-`ZjFU%~fKzpn}^K78>bybRC zCur{KL=l4}Xx-3>G6qY~nxPX_43?nvLMQ4NEJ169PBbxCg4PM0Xk)PKkaDm*(Zyid zA?ILuqL0C{L&?GN#3TmG4mAhM6Vn(hJG2}uPt0Pl?9g+tJTZ^Kvct&1^28zr%MLRK z%M;5OEIX_mEKjUruYr3ZU?m&LHl;Vd4&!2EHuy> zanM=E;610z;;Wv*)-Hn17+_%d$pJcVKnYYIG5l;$0`K{n2uk-?85lrq50Qo@X2@CZ zQVc)0GBB8QaDnO<;nz+K3?Y-bKPEgOR~R0o=b~Sj8#oU}0a$SolVKz7#KG!z@t#f56Nj1X9n# z&=3S_*Lbit1a-1B1ij^D*uuxq5cHavcNJ)@PcEZ_<^Ging`hhJxfmLPKxZ81$~stp z#2Wtp56R_WFxfwmp%ApTM~A_|k_W_J$xsM7m-Zbq_bLGf1`*KOBM=*O{xWDy?HO4I zi}@=Vz-9UyX6{uW{UGzX85l(P7#c3Y#6aaOm@Ugt1X?H33$k}2MBiIxo>lJ{7`Du3 zE1IltTM<*uwYJ-3&Y1oCWa6JhK5UpnFSUCYzz}G z{{L^<$G~6?T3e;f*deu=k--uaj`}PNTV68?bZ4`I%wl}~kePc`!`J^IUW^PuAhy<5 zc5~34B0=yvC8pD$dLDF^gFb^`w@XH{MQUcU#e4=C_X@8aqRzpanSf<10y6}L1_TgX8@f+afXpY3ntFVaKKVS zhCvu~M>r@hz->(Exzb!R2P`~g8HD5+xxjTBD1Cs!4?;u6*FbDo`6$f5FrkQ=PVCd2a67H958^-H3QX~pfzrpY@M?}_rJi` z>9I0gv}Y84-N4Qe@{*Au1awyEYc__EctyyaGTMwB;BW@*S?UCxk%2Hiae zYUdjJw;ZW?AGgadme;l(+B#^#NEJKIZ&~+_xIf$oLV| z9{`yFO26Jut0w6*GEC%UV3@F$kzpbzEjO^%uWjNzv}OUT{n|ymO>53U*LH#0`=B;t zJZJ4EP(1}w>;18Ik`5zZcP?lhGb8uuhE|6^3tAceoP)0E0`(a(m^ixSKgwGmm*pU{ zKxc;QWM*6BWNCx@EWiK%7YE&sg?uNL{U7^}E5YYPGpzbw&%E-#GQ-aYhe7x8K;i_v zjuf_@RUXuChpuNuQ}a?9R8G=hJ*#koEx7N%$Y2R_%L8f9oE*c>hnpeo^al(KCZKu9 zuffhM_cJkkY>{&K1sWgcV_*;gsRi}*KxN;9fB(U2`H}mN!mJDzk@bPX9@ZxZ=>f0r zgN_G)%W3esLlKm66EdEIxX%i9ht(5iM$p(5N*i8rT5Aw9be%A)EdCPCxbj6X{(drg z+aH#PVC#@UZUyxu!$oi!W#oMAVAwfJgqdMW0u#d)c?HOt zRc=OxZcsir3C;%~HplBsCWa7D`sHBc?gsU5JqooDZDN?n$G|Y*93#WT1FZFH4)glMNqLNXr@24WPD0NgAiWQM z{SP_&|Gzja+#uoP@bd&S=o}=-`WVo>Eliw)8EKs-qy06QxCaw<@ebs5p-}Zqj1E5! zf$r{LhO8Hbg^2@${52RGxjcl~p#gRi19*QbOsoTJFJx~pOboQQ0+jZU-R%K(2SObq zqr=aIU^fV_g4wBnWe>r6xEI?{N z{a?^L{1<=0F|aeZj=g#mOMn4Y~&hR6i_WhKx-yFoVuR7JJS75447?;Sx^$ z%nYjfd(e0*=-g>ge+rbI7BDfGp|4wnt;<5spN%^a z`4e4kA(GrTwDBXbJ&-sQ0p)AtbMHXwwL$&_jrHL>ldO@AAtZx|p&K-x@`9P+v@s(` z*8&EHt*~$aonHnL7iARbg0u~USApjaxKPs;$S&~w0eIenVFIX}Jc(2;YBGNQp~)x= z@29;0&tpQ`#UOvcFepEO@*gLI!_KeE8CQNjk2xnapN(N7XgnYJ91mEYgoPi>JW#(8 z#D?`Fv84?~@Eydc`3sf?S&-*P7(`wl0F5UxiM@7YW(a|W5omniJ2S)S9ZX`cLG9`J zOv2#&IE6{9`yrEPHz;jjGw&<2#H#sB46hyk{SU#FR$$?QJ{Ak|69{85R|KR7w%34x zLH-)3oB?52{SPYlL25wj2tem_g8Dlg3JjJUOf5n3pm82%(6}W>cRioL&w4R|pY=il zKkJPYcEZN8LG>=IKBc9(uyUUvs3C|UXh9LkudsO-*xaQf6Qm6z64VeR611QQG!M=g z)DXlNw4ewSKA>_P)UJj2*Wu?0&|D{I%^D-a#Fv2$lU}af|A~X~CHyWf^f^h;7&EEu zQ_wsS%zdEp8I%_nGBRud*KjF%(go^cg}6Y4mSFayI+c@CzX z$Z-k|M{r-80X+W<3J1^}G^h-Ph9&r3Q_y&&1_$WONr#{4b>M@i4EhO741ep9=0IU% z=o&R#!5lss-JtVLG*uXcxB7KPHX;kx}0@kdJxx_rA058IlL7Vxuij6g5u;` zIO9rKyny-+pgB}fng{LW1fdQWWr-0O+_{T4JpNXN6W8*X_j#@6^73Va%88{h!o?v4TTw$aDHcRvO z{}9l=d03eUYY#eJZw_K%g0%Gx*Evi^mruNgkpJ%tTFc75@>e>?${+EZE5C(vt^DH8 zz4C80&q~l8(x9~cz?k8u6a&Kq4`#?Y{?3dHA)tFdL3IEJr_;_?%*1N9|N@QHLY@G|T?$>jvza{<~53UgPo48&jH_(iIV?|{ZiI2j7Pr5Hj!YlH6F zX}I*?pJ8VPv%^mC+S<_CNuP}!er7Upc58Av{Nzw|nA9!W5cKjo)5;gZ3_m$kxo2|- zGE95{TKnt7F!9BE=9QrHa6oDDg+IeikY12_P#UslX0V*Y&M@%=R}*-h>wIR8*QbOT zLQe3>baMteYHIw2th)q_iAZod{4`f}nDjG=dp5`{4d^;s(0Z{4%#xt~`4o`3Uz50J zujq5wA+N|#_~6g~kT3ZRJ3;$;PBVhmO*CBMsCAf}$?UN6RTB5?Xh(*LS%*RQfN*Am z)_PB2W0+VS%rFtOuGkxT?xhGrL(qICj_k%?kaI9WdO_T=(jTHt`Ucw zAa#yE|A&C$XeATFPLSGHb=&KxV?yO#(l|&ezORtH5@1 zG8B5UK<*=e+x^~oo1+X_2QY zw{#Y>!_JqhG22I=xCW)0;{X4}VQf%%!|Vse`NIGI#mO}nq<`Z7|Kgx-S!~r~X6aRbt9@2}@%LW&E!=D6 zk9g0OztTNc{>gV=`QMotbQg*UI1HiXDJ=Yu%K}inj?WBGdCy#nS*|tSY)0&HZ)Upq zC!b~IuXNUxKjPU|ehX(``Nf}O<=<+~m5HYzX3GT2Q3Hz}F3$Pw!`H2$~?;5M;;zS(j_c z&Jg&WS#;HYCWgXZA%>8zYz%=b*w)V$VdU$c!{o5@H?zp9Du0I^pz|;~g&cOiv}V}( zLYm>{d~OCq&>CA~2AS>*H80B-fB&0yK-Y}J(he`D!_R5z4wG(}3C!kb{s>;{3Mz9R zFiWg@D-7PRJLTba$CV(rfZPOf8_c~YKzdj~dswBi9a$MdGSs*x3NkWSo-`AftGgpvdXM$^^4QOqPE@Q*ao_5ywVWXw!VEK}nLo17!!2~q!shz+uu_w48h(~Kdkq!e- zcP~>z5TAcT5TDk9qIgDzkNk{XQWF~EcN8$n|9H=;JNtcR-j4i6`5*m^@jLPv8GiO3 zjNg&Z$*{BE)p18YFT+ld8?zfhaf z#$eXL<^Zan1v}Unc7oQrGqW>n{SG?c4CDqpdYjoCb~b~~!(?a(0_g?06LiM18EBsq zH>CZO#KsWPz~rzK)Q14g{lWU>Ah$L!G3?~vcG?N5PdT}nc5Nu-eu*lbmx_@@q7l*coPG|L|7a0;Um;>9d!A`$GFEd4kF26E2j@W zK`N)6880H=aR55Y4iu-Lb!{g=VZg~yh_k(kHm^_$x~r27)ZP?*{g4UV#@q=yw+j@H zpmj*-@d%B>LQp&;vLMuh+WDY(0oDKLdO&CQbb#E&%3ug8A69WW?eqlQ17UJl_gsL|A&Cuvn$SNc7x7#%V1>q zxq{0Hl%4`taDn=1kbQpN!kt#)98-D@jvpb|nXTByJwSaq*mxp(pAK|KHQ0atsBQKP zsNWR08A4WaIsDY-blRE4%23D+nm=J>2-NY_?(Xe%*a7krsP3v~WhnFlokat>YyPYj z*gqYN3_mqEA^y?eWZDTble3m9xYJLw+nm$kr-Ukl5U8FLjbAa_jG-ZDMbkHM*$-;# zgVH)EorB~#;yGq>vO4V4WMvTK{L7#TDmy`Y8bN)!sZ1Q**z`4v1^ny~3i!$L*Xc57 z-O~zIh7d+(2JoI+CeTE7LU+T${DEss2tBV+WA84ynXtXX$_xxUL1&JhW@89>!OX11so-Fl$qbpJ z)=FTQ*c}Y1JGB|OyL*@#f_VKKf_SwS6oKZY`4~H;@*CrK_%q7?ILE3p`&?%34!=hE zA9;-NJNy_Ke&!vF-{Hr}urtrqafcr-11KIRdNqRDSDfH_M-p~_7lro3!v^S8U zAqZ6Gfa((k7Kfi43SO3=^|SH{T+sEu4VOT2p!Eizb@dLAwe%v$Ak+QPuFWf}v6IY^v?!C_|y6T{BQ3=CWLvoUN0t+y*>0-c>ChH^d~$Szc~ zA!FpAF-Bnqho7K265BWhXj}ng4`h8W;?5ROS^|wbV2qJ7Ghh4`&bji7KiA5?)sXvH zK=~bnU$`^;1g)E7W^}NuXJPmVx+f1jW(c}Rg_R)?bnZbjD`+1I!xWAhhsls}aM(TI zptU<3uR|F-W+iYz>L^gzmcbS9Q=U=u^#Nw6J_hg@v1JEiQxItXaE1}XL{3Ifx&oaw z$T0Ecbx6MkR^Ncup@Gg-f$?GIO@Z{6FmZH)_Bnw1{)&+JnUcW80InZF`!!3s1b)5% z?H6PKneFfsv~C}CKNaZAr@z(SE5G=At^5}5x$-|VWN#jNUPxqZ2!fp_3kqY{xC|&Q zFhR!Or+~(+IvJaSKz)4VwHQpS3>QJ_Kzjs0dS56z>;%;rFn@fW%rNo6WQK{2Jdn8< zkU7Y6^dS8YCo@b0nE_hw0z0b_WEOZVw3*@J-)hE{u>Bs7q3d@+V|mDXJy6HKm{vi{ zdrQb3M97&|j-a`I7RY&6p!K929FX&{8bM?FJRmiUg`ja74gtt{SfI8ChX_aGg$t&X0ZHX&M?uGp&{tMJ%i=cQ^pqHzBdEI6p&f+ zJPd`||Nn=)Fn0jwU(ot8keM&6A$-vIKbUV1;e)~x#0QyyJdXt%k3(PQ4Qg|M#%~!x z=cY3>Ttbc`(0Wk$QoE0f*cn2mGC}g_3TXcgxz1|fa@fhi!XOB0bFj>GtOA{F13Igx zgNtEjF$=>M(E18nbgm6H zb)Y-2xzN-#7%@x)&85Q99W4KV+8Lm5fVt!I@Bdptdy_$K0+k)0`V{%x64<(JP&ove zQ_Wy%u*_s@u*~9Wu*~Lbu*?x^u*?-}u*{Qcu*{chuzY9Fyz-4X)5=%+jPNt4UZ{iH z6yQA$pf>!Ue5RGy+VS=b3_s%;7=G3>F#JprVA%4LnRV4yX3$yWh&#bS=aIwaLKE0Q zbD^TIB@Cv{y2;M4MVf(OLNznP#5qh3KdYD=e$HoR_~;@HJ6}s?)k9{;UUN`8`hYNe zEElvsamx#4DYSJip!0R5L3^TtK;Z@2>sJ9Tzr{iK3I#o4hK#3y%wphY2>Hbf*{^Y* ziQy*`GY5E&ENH*6A|prl1BAUBAAs(h0*^s5be~`X&BHQ$WDyMgmH6*}hzn>94^%D3 z@A}K2@>9Za>Z~*W|BJ)so*;9#5I@iS@qa6*pJU0)FcIW;bbo{98$f%_k^RlU!w{0e z3|^Co!_Sg9{S4Y`2nq|3pA*=L_cN$W2HiKt!HDT+PsMgnpu7w^3ms%P zsLaq{X4pA}39>h#mZ4s}a`?F&X+9a0UqO4+Ky@`ELjy{_X%Jut z0kv~P7#c1~@-l3h&m{Vqi5D{F4jNwutt$lGo36ybAkz7({xax3#+OZV|&OaAf^#qz;(B%(;CDj#=$WGrK<7g_Gs5pXPhe&+eX$z#%+Z5P z3?ZVRd+(VJd%QFhU&IFg44VUgRGQiLH29>!9EDT$IGc&9L?Q6+k5(C?F4QkK-|I8~v=h{4Y z46+ZphE^SN#;FGjLkQ^HSNNH*Xlh={L(&HNnXsVwd(av?_&Gw*Ghsn%m_TL4Zbk-? z{Y;D>ne;$)c*CU{Mg|f5d*YgcUZ^wtye7f0rJPBu`^K}XNhi5#C*Ar~J1L`yVdBfh zOe_B|OP&77+7R@GSsJ_#t3%Ae0yLJLq0V5E$?RZh|B|7QfeF+n=3E6*1KV@eA?IKr z{}Qs!9<-hh)Sd_3PnN~bFwq;jw+VD+XbCe%cQcdp=@U%M-5i_@6XjVQKEC+#KZKc? zVap47@ZMW+->ZR%A><{q^(rk!k#5lXZDvLW&|KL>dq$DhPJ9d@nd}S`xfz+eL2I`U z@iK&f#v?cwxw<_WrMtBlMNWg-irkPhRyQvG|3Bo3y2H=;49u@Rbr?cG_DE(bTV${> zOoWJYyw22O2m!^zeI>|RanKx&JfryQMWFk47@4~{7(ww3>Z1$4=469}w!~=QoTp;*tUeNwGd1yZ2fc8Z| z{WMr#1T-JZ0qu)`_X$J$BA`A5tS_?Q)Bli%&Y-hv7^XOU`j3%E7JmF6a-M-f1h$U~ zwAL3?&S-$#)XFgNm9)dp*US>DVEd>TSnby`q3olQce+Wp;3ucK`pn05E-~VsP zVB+r1Vif82Vw64&y7Lb-j^548-ObSI@W-K*;ZHVn&H4*wsa5xxq+Tn0{~xmP|9^4V znt9NfwV?f6o=>YLaknx|%xPzs_?DS-6>PnH0;~PnB&4%YLF5@t(OO#N%M-? zdX+b$NO#W1+DToE4x4hBIlDpoYxx*CyU&5{O=9FZ4LcK66Y7?FMxNJ=@BW8Wf#w4l z9X1t$=Jl|o`xX3yC*2=nLrwQiY{aMgP7z4@6Glt-D}^BG9#qCqJ3T)5ib#(QUoq3; z!!Q3sv>6ygC`ktlKPgWKjNkr;Y=fqQwUGN=E`2@k4Bl4&S~IJ_!w^!;z#t;b&@kyM zIL``$%l=|$*`I)=jtS;r*isLzV^%N;L+Ti2(7D*c-TRq1UMDd_%8+0N29XudswQ;tt?G1?E-p!*>?AZ;NAv2M_P zXV}z$>R8bDLMQY*K9GMwYnbO}nOcC_&FE(;|4R2?`6u5Gey%cTza~sC$n6ll#umtN zdEhUo?FKr30dmeWs1FC)CkE?#ocQy9%L``I{t9R>6-@qfIO9t6^;#2BM~%be3^oCjGkjobnZSD#7*~PX9vN9B7AqJSOhD^k;u%C3&^|>Hij+pq4^+#Nu(RJzZY~CG3Y!IP+JRho(3pgDkI&S1slr**#k;X z^O4dosJ;T#7ah;4CV}#cHzQ|v0&D%+BwmNL+zcQ#!`dWX#<7?zD<}=Z_WgqNg8U|*VS=*X1+-`K z1vA4c&^m3-%mfQiTL-jP(4K(-Yz}B0A!tk+BoCrtd*PvJ;O7f=@K_K$oIqivp~4U- ze-t!+$Pkjr)NqMYV8JI&#si-`86JGnP(3k=0lH5Q6z3o_IaC~1g4#XY2U;#^GaUNF z-SFTOPiCgY{Fe-cK8j~%^)PaGwaj$*1)7fn?epj4VfYC;GZv&5`@9%r>_#HSaV00S zc=szdhKbq?4M92wS}y4@9Qwr5@Zb|De0&)>x^wv;`(kx7Gc5LhWhl(}|375^SB8(E z{eiiPXJ_qa5@Qzc2F1gvtWxm(DxmhdCM&~7 zP*{Iu=2*25EggZ|?d*_tJE$$Vf=RragP8+dt}X)IDaRz*4QhKifyQhZ8ZLpxV`2Fc zmYzUnfb0g%OM}|YpuQ+5?Sb|ufzlMH9Dceu$XJuN{GeXLM6hW^l(0=!md=PnLIZ%24 zsROA2ok@)`_!$;7a@SywAK=HCNs{)+9!RJFWN`TWhXgq?E9W}3m z=7}l<8MeqPL)y?B%wpXfjN;&SzC8oSYbOrSxt9{)`tK1tr2ea7U=RVt!6`0=iLaTs zxx8&_5ooS}q2W>_mhuYZ ze^8it;gJhqU=WdKX8iaFw4N7~51@R|`d3gmfZ9W#w8-(iYSJkt@ouk9hKa~&Q5#1Y zC(q3Bx`CA;M4r3$6X-4|kpDS8*G^iHmH9^jt&CHE&M(64XeHhb1{R1Nps{v*c8D-A zh#=>CP~EHvT4N7dN5;$nPDAz?78V(N4nINrcR}ep12k{O%21fa$Pl8-z#xKC4^&+@ z3uNsPXl&&*v&gC(Q3ngq`H7%13e*RQXXJPdT8rRU%R5^yGw;WFMhDCJjQrW4^bYD5 zyl3WK^#OEVsvJWR=&bY)q7D`pL1%|B34-Ss-v9qE?osP7i3@bjt}54T2GAN-(4Fgy zpmSC1uPtC?Fh}+yD1S3EHtehqU?>FDaTzQOf{-~vhKU*r8FrdfD*r$qlfku)!BM0o zsD%kSH^$Mh6SOW>8|q)sc@D3c8L|48iKIu03!8gE_7n10Eo|HrG{+@&pyiSo!=X=N4G%tbs5!0#olz72lA$nz zks)NY(y3YXjAE}qd;CG=S0^6>_zWA6Jm|~>&|0!p3`l!585pL3;t&)soRIS}3)eDW zp5FyJM~ah?VJF61aWmt^U+Ii1f5bDbMBZZrT0;*S=K|I7pgIjS_YJZGv`$w8e5Mj; ze;fnooav7oj8kWQQAVxnr?P zILk{0Q2J&Nf#naFIOtv>F6EQ6;u$4hfzq-jbpI!8uC-Lj5pKrGfB!>%LdV--VUWYX z5CZdaSsdsrA;|u|Z{f}>f5bbj{FUwq-|P3^nd#!Mbe5Gr;#pUI3ujyT#h-oU-)fGP zpz&^4IDp2xv7X1qFd;}@!QmrIL&vO#j~OODI?ON;G*A07KKv>^Ek)V6_z52$T(3N0)$l^j=s&K)*oVK9H8 z@30d+Ec6`o|gxmsR~Xbpm6yt?eOz61H)EO`v5t-K;n=)VNm-Kpf&(B9blbn z0p*Lo)gCLq_`9$C7Vft4N4)FGU+FF@|2sq4r@Il`%N{ z1eIHvDqOP_6&Y44aWeb_`=)SHR#2hAL1Y~S8 z0XzqY*k24X6EruS1aTc;sO0Ei zv;^(FW_6hXWt<%xH#*92E>dIe$RH64bxLwWb=BM_};^USlE;y2G2P8#LZ$%F1wYKNI8Y zm(%ADJ<9xcEJpVdBd!hKVm%GpzjC#4z!f6XV3+XL^EepIK8B z!`J}2Yk0yomWCkE++l|pgT-fN&Q+lKiI?j0rJDH}LTVWpM7U%bgfiI}CdN-?Crmt-s9iH)%2#BNw+vql`4)K?cFK ztPB@lFmZSD)iPM}t1t+H&b-rLWw`i&nQPU5PliH{fB!>Pv4YkKGkomffVz(ZH0CU_ zicgfmf{WwFHqe~#A$Eq4ciav?FEEOn)?;Xxbe@s-v^*34Yd)j?S)ls;J|pAD!=UyG z6aQ;|qyAa_O#I#NITpHbj-gW-f(57`}lDljl~GcfRi&iQ?Z^^MKA7eZefU3KR!lm^t8a4eG~$=2=#J_;1R|#9#(G*AO(u4T(p@ zx*tU*P~C@rZ83VCt!RjGZ{!rzx*OC7hU{l$WPy|)u=FnC$S_gFhhe3>0|WT%y{$|P z6GeF#ekOB4%Be#vkhw$9oe8i!2+PwM3Y@dKbQxBH_I82Ftqd;k_yoAW46_GhHn_|I znU7>H=qwk|{upA-MX&eK!vMK#1hp|h{d~~bZ=9+Of%c*dh0Xu}hsZZF6oSrO0i9a| zsw+VKa`~+cg|C>qq_{;IX34K*DAZu=lFAZonB~oQz%uh7L!iAXLm>y~Tsww_OS!TP zLZCG8`Z?n!Z{x|Iw2dEsdc)cfq{qqGeeP%dWzamwNyGWK*2+3eUI!Z2KFDyfmy!3h zJtObylN0CP@)JE^aaNW==-feu!26mEh0gyV`x`)g3DBBEE`|@6yta1U;%4|T31pV0 zVfQR~MutKM#!m2gkntKIHbV&LK1Ou^JBGFdxj@ev|Y zmO<#%bH+_x#*;s389)B?nzbS50WkRfnC)bEZA3|kZ!7=9AtcTgBD{P%w==*+rD;C-?O zEae#)!E2L2{&iwu_z0TQfsN%PLC?qn@j>OBmgoVCct*x-2F8Y2FPJ%3!PJB5M35Q~ ztpr{_n0|K5YYKj*~|w5xgH8)SvWZ;5g02z|jrbql12i3uqo0 zH2&tn!tn7ms7;swIqwd1M+9hXmp$}+BaoZoq35}P%mj@gdpxO{q}jkQk*fhRX059C;`?XF;b4K!vOs^UK{SS%fsQt9yH)!sNW0l8;+DV!WxX<1L=}GwWKjh;7 z|Kgks4wjxw3?{I#HZ2j*8Zgal(3&1l9|&|uBIt}T&{|7S|8G8{W;Upv0`&nw;R_m@ z>-_iM6yyh3TsWb{1?XIU&{!r&JuE&zFj2PwWDnP> z1+4XJ7x5li1FP#{XL^C|WnA#{e@H#(zQ(WrL*6lSt;&MhbC!{_o0oyN`y3+|#<^Y~ zeGk6>519u#n++PKptu0J8|020P+yLP;UegamzUtPkQ**BF*0n?%E+`h#lT>~m8l6n z(-o8kL1h*wt;uI`#V&LqKXJmMNk`2@s1+f`lgYM4;g?%;ygUBOZhAp1pbGI2^GePxpvtsJ^WJTzI z2_46H&8)R5n~|xThk*+{oq_imiZL*VyySwoX*CyUJpjilkUzOHG%d71^SYpP4ozpi z3=ATkj1aZlj0_=M9FR1YlbK}Ulc@wcv+p9P+ytdD`3y}9&^a!kFtKNZjKzWcBMjQl z3_8aRwBD4V;Sy*MtQKfax`AP$P6KF8nhWQgG-xjuX#CBd6EgnxmYHjn*2mgO+6=ti zJPf?uYZ7J3-UT9(E2mbTI?_WhroB%aUiWJ1C7;i;JKsuF*D;T4bZvS3I{%c#$S`f zA!Qo}19La048ufFxN?51odimko}3IJ%A5>aUNbAK@?qre<^|mm%EZP<^R{re5*ibKQcaH z$Y*)Nkk9;tA)oCDLq6*hhJ5xX4EY~e584PWB zmMQofE)(!K1B(mri!W2)pR!DW-*B0NzrZpD|6?*6{90r-`Yn~&;+HJ5-A_?wo1c@+ zCco!0Tm2YhHv45eGJItG`#;1P%~E2w|N@fviFrt<&)A)qxAOsotcZx|XT z^)ND=?%{OUq{GP5J^vvC_}oHJJt_mbo93_cWsu%=FKZ|H@bYzo!Uq%6XZGcpVP9Ap;wCCDuBLw5Im zM!wge`ns#t;fFUP_bSkR$)Ghlpfm3mgVy3Pa=y-FX9&q+;5-ew$1L8F;bSrzLkMV1 z2*@oUHzmk&`1!o8nWV|c(+#@w3g#wIoFT{81`6XV85&$BnPq;- z;P_hN=LC+gMc_OBK=Fp`Z&2KT{H-P0V3EzpwF-3q%EJHuL+TkBKElpkLvMR4Mz#d8 zC>*#18fOHp&Ht0nxbjyz)5;(5%qzczBhF)g%*?RTNsVEPJp)5wuNp%LXnYQI_mKt* zL!ih3jc(9>vT*2_fdn(dL`jy0AZezCAQ`rXAkY~WQOpbzLE{LZ`&nMFL&oG^urvGw z-Ma*u0|Kq*lb^~^2pT8PkYg};$qrg;D)PGd-~SNMdiWR2qN})N9V}LIF-)xA%20Sp zY}zbc#*SGlv$8C74l)GJS7j(X0hyZ%0^N(dO4h-GqgGs+gHey0;~+zz|3QX8P#yVS zlc5ltUUxEp&-Mn*|A5Ynd&SJTDt;$JA!r@cDpm)}_>~OcJIdE`GE98M?C{f15mX;D z{Pbc3-?JdX#n2%1o|$*mJ5dLV`!5*_*9-Q~0+my5L1)u$WGn>j;dsmHV7Y%IW8quz z`BEEx)?WtQ&&SKq5Cl566{P2*_&7bifkiN6=ZF zT1-F81Q__W6p|PNVO$SZb-pP+MR;u%F=gXTUs89BW{;i<{WPzah628l2F z|34&>k--wA7Sz{$#SWQ|2KAwg8HKq)=`8L4e{uV14227M8A2xTGMIwWB4~Z>q1XRI zR`o z7#)6^FffQr;6gP6bao@mK9C<|KxdC4>o3FfIWr>MBFq2@ zYwrL5#X)`m`748!A*7QHw7!uOTz`P>@&U=g{l^R%>vdcC#ou-1w{Vx0KjNKN{z`XR z`6u6TC2VgDtn31nRZt8buYt|~G?ujlfzEh@se_3>EW#LL0_%gC0opHvmk%0mf}JG@ zYSaB^X219+UuxywYU!1anVD9B_Ar9ffW}`z_{DjKpAVJ6bJtT|oClpe;8MS?rH^%L4n3iI2JHk#K->lQ8`U#lnusv{UzfyVen92h2o>IZR$mP_Ug2R{99W|#aR-a9%#y2Kh%uOyGB9l2%D^B3O55OiLY1KqbRMOABSRr* zuNEkO|6~?jB@aEf63p&pC`@Ex2m#&C06Mo4Jf|n`06(`<9wg7m5CYmO0_wMb`sb^d zIJ>=A9V|h8>{b8&o9<-d>;|b@@cVzrekRG+pfh5BF-xv`$t<}_>ufirj7G0Ia)c`)n;x#j*jmgQ-5R}8@@DsGI8Prz? z&HaG=B+F0)TCWcp=kBY_{&7At*Wy2;MmDG(S;52$UJnQ=XFdM^HwD#M{R|AIps_&E znrP5i1*rT4?binN@4El~53vWGm(9o!QU;le2i*Y(9uq18tp{Y{?G|MPm22FqKdHiPB=dHS2I}tuV=9Q-^^h7zn#JIe>a2W|9%F`|C1Rk z|4(PI{6Cw)^8b7W%m0fREdMWOu>8N8!Serl2Fw4O87%*AXR!Rgo5Aw`eg;d>`08(F zPA!he%pWhf8Ggnvi=J*^2d#ZathIl@&+t>`-Ty7~l^H&Q&Ki(ska`WOXE+#Sz-vI9 zAnk!moQ$H~T8vVsLHAyuuiK9Q|6hDQGwS-qj^|aAIElFT0dz*xgO~q9=5yD60-f&! zT3gxi8UMWxAUzH*{)d3hNyj!<_b1;OK3|8P2Nh?w!0$$cl{e6RpD5)Q2XsDvHFWHk zi^1WiwuplTXv_+fwn2MzPcbos_*7>8=w)=UtY_rS2F)FS=1JZ%Gp+)SS=@)7zrIe? z!J;43#$n_KuUYs28Xs`b1m7DE8sB}%K3@t{K7rQ%fy%}Q%$!^x8djEZ^nmW+cD)Qb z69Ck9fz8E(#wQb4AY~+IT?=UaC8!K+2Aw6r%54ta0l)0PGzWz)h2TM*t2Fpw_ z2TM*-2Fpw-2TM*#2Fpx22TRa>;hCT_Iusc!Gu0d{IaL`fGqoHnIW-w9GxZ!SIdvH< zGmRW9ISm;sGtC?$q1@*KzDFUFzl2sVAv^tfzeXFhH0hz0R~I?KkO?(`&Q*UAajzi^vB@{ zx-62hw;z z{XRxZl(B;Xhn*ai@sy0lMcEB7jcm8HO8=X@T9LeRN4==L$OI{XBk=Z#_C3W$B6e1b0L zxS}N}nE}!kLw73K(`W3NZX+ zssP;;?C_I`7j*wH^D2=2V84LmMHoQsk)O;L7%e$C9CmszFqp8^K-CL^)U$%sgVW3b z2FN)>9T0g&QHWizxCgZd!0j6zMokt0hMf!vkTRgYh+!wF{z+(Rw@GN~umP>rV)$5l znGt#?B=n5ZDG7cIKf&slSl1>PHQ1uJaX@?bIb%R`lAwDO8CEeQIQ-;taQMlU$nf(N z1H%^3Iz-M`$USzj@p}1GhM&md=;uXqNI2}wU}i7@ufr*D*r~z9VDg!nX%%ShT^xEZ z2k1Po|4tgOL3PebKZl=YmE}Lm{)6_fimd{jo7li)f31Om!F)xL!%omV5a@nm(4ITw zJ@UBDdUl)-I^VzH66}luuzNsv92Yq3e8I?I!s+Ai6I`|{GE4;RvjmOVC@?zwZ213w z3zvYyPtaIDX#R(*z+q>6rEC#s-7F|A!u*esmeA}&o{wcVarl|c&af4<78`WN4QOAf za000P23hZZqR3(A30BZ~6AhP6`9a+U?gMhX28|DeRc8K}_W%Eu(_)}Lr08pqyG|E5 z?0o(2zsdbW43=M*A#0aT9%7i-m4&@bI7y&P0O=*QOt`;~(GrrD5O+#~(h_>uD9&qz z*TJwft-;~2a|I(PO)#wD2ypmm@4)aAwC^=D%HgM?Bg4Pyy zfbTy;l9W^NL_Q0!_ImEhC)Ra z@LgOx=O2RPz4=|>`;>lih&ucP*Q=m=xuu}zW=S#Z%oGBj?Gp$(GxG88{~;N14nOBR zG5pj3m8WSAKTRANewL&`-5dwHZwTSek{}+4JJH0^!>RFPOHd26Jc6AS%~0bo8Fq&d zs2pP8bO5gv0!Exqk_lR~pR?(yUrt)D<`_=+%o&MQ7_AChh)Md)bRu%xiU4#*XY- zPU-AKZ!Zw-Rm&-z#mMEwp~x_?o|yyOPw+7H@)ED*lz!pIAS7iQ?$r@h^+V!k{U^{l z7Auq(CawgpU6EJ?8t(wz{nfzCu!W1qVW$_PxR+P0NO0Ew|E6354m;x+#j-*D4lWT8 zn=gCezyBdzJPtosGl9wg?$@Amc|h|Jpz(PJDTWa5kF}S1K<5hyI{f6$%>DryGXaff zGl0i)d0#L7^FQPS1B1xB?TjlyV|{a~s(#ckGMIzP8ql~Mi2sLy!MuanVN)lcRQD@p znN=EpU!90&lz9!RpX=2a3PI}wLG=|({hoj9X1~B~ZibI7!V$mTZFgMxke4CE8uXcd?Gq1%Rer7Q``~;-3}APF_Uhwv+l#;dLtZi?+y>fn1Fp;e{SN_|14`qd zF_b6i4l7@)JFV1U1)YH@+^xaN@RNmuVdo1y9w81MhMjMe9ar)wFlly!=A;uCCT21- zbZaIuOkBkz-3?m5tk4+xYXt*j{uXpj7buO}g4ZiHT;gPuKF!6*(CwATFmVMF2l5>) z;CWhWP+tPIE$K52%AAPr_v z+Z=PfC2}9`F*BzY1KJsXiTn*gECP^oqS56R@`LuWv8;mC_01IwLg;D^@!i9XCc?upgW8}cdAceVweccw-f7`Tt0%%3K0dJg;-VmBLkYJx3Vz^c2pJr zc)`G6&dKPosf$mz8`P)u{QLSuJtN0!(7B@fk@7T5{R(KFMqlRyN=uM6Vhj_tGBbX7 z{j8q^iZ889jUS-$Po6R1BdFgAYKwp{=qv(F25|kD4H^#ziQ(EuBwxb-9vg%CjiaF< zh(lmOQAbwB55|d%8$tV5K=nDO>;dh`0gXR_{0|yK+RxPoOgh zL1hwXjVnkG?2Nf&E{C5S^%B9H^#Z|M^&G+3Ob$PDSQsYea54PM7G&6h%UICVF{uuE@#*> zSbk@6_-X$8|CWqCP=DFwGN`|t!OIZx19Y$O@BiR)^cI26?0}x5x8T?RkW7ICw_Y%F zo<5;;VwOB3^XrwokhAlSD4m=I+KayUC+OZ0$l5u0zsv-Zb~3pfe%f;~d`#wqtdRq) zCj*5KsGJ4O;s4OMAqbRDVfh zI9_Xl$9Eila=)#)teu&?qn?p5+sm+HRX z=CVd+#tzW>Gtk(gh9EO&Z1E>UBEv*bzYvt?7{T`wK+fkwcb}sTsCE7q z7z7x=W7_o$3?DsMnr4C4gmct7Op<41`3O4iz~e*hL5o@dyummG=AqT$^aT80M|jFv;Z0_0Ig94sR!MS z$N98s5*GvGMC}I9JQnAw1n~aNLu(vb?bbT=+OPFuWSj`P0}NF5faXX+X(67&;nRXY z|3g6QQM4Huy0aZY_s?*gc4&3@lhDfW2UZUxgVyiyFm*F?g6?);`3VXy^e|fZ9CY3Z z$0`;DNO)j7+vf{2>#F@M423V*8A5(AL(UTV&ddb9e;3rJ0<|X;m>qsLAf54}z|8RT zDi;Iztilsq3_I)D9Kid${#K)=N!U3o^-L14U$QcU{0Gth{)c2Zf!5=QzwZ3^KjbBs z!z9mt|F?qLH};Go*^mDI4|&A~Y9}(hZvG3J&ld&Hp`Z5C>;|>NPI58q%;IGD`5$x# z3nN3wD{z}q{Iw?N{xn9e*Drtn5Bbi_waSarVN%!M|64%gn;7Bp5)>}NtDZ26gZFAb zW){J$8{f19xj_33xb;gw^)s$w;c(aq8uMBSI$wo>IUAJLKzqsM6&VVfLHWahVIud( z+RIst4BbAUGxk5!UiJm8<8lP;NdxU^hr~4~uP zUWdU_-hjbU-h{zY-h#nW-Uhs{!cyLa!BXCX!BXCb!BRee!BRei!BReg!BRek!BRef z!BRej!BReh!BRel!BW0}!BW12!BW10!BW14!BW0~!BW13!BW11!BW15!BTz#gQffw z221%F43_e97%b%%Fj&ejVX%~6!C)!BhQU&P1B0df76wcC9SoN8dl)Q1gig7}Hr9w)}^l z1prbDItu`D*SC1LJfj%OUElwa_WXn9yI(wm%=w%ma7M;|CXUyjbs7J;YCnPM4N&{| z#i!ayCz)`sHwO71wEr5m=O1JSXnmY~hPlOpOAISFOM&(VBJQq%jRPX5H~AKZAE34@ zsC|k&c1@}p1_j7?YXTE!jG1A}&;S3YgUke_Wth33b_b|z0Hs}dhLK%1fXhpyG6BR# z4s+0W3@GeCag)G@$omOm2sWr30F|>Ny&Qn0FHjgFmj}q=$bDCEIm>_u#|$xtpBzjK zTT1vGesZ!m1c?T6&Tasmrw4AYGE8Y;L#S=wLa?Vig6t^+jqlWh%N@iRFUT$O3mCy? zQgal5&+FXEQR473gMncyBM09~kUV-jM3Dh?JRaH290H(m7>AuFxEV}9^8+A1fXc50 zeU3jCfW}}L94tGT94tY1T`Mv|_Q`_Q0)WnM=E%sj=*ohup9Zaa0`2z!o$UuY(*o4C z$YOH%+0EntE>B_exS;(S4wacdco;x?&$+WfZCcP72cZ7fe$bi%28Iycj2w%;tQ^of z_=)=&`LaRgg644-FoDWo)UW`ZJ=ehmI*ZJ~5_b070km><8XLnF&^czH^ZG$*5#_8{ zH)yR-CTRYVq2ZD$(pg}ju>epxdjeX{b`dCNL1%4%&MLkSDrcD>X9J!1R6D5?PdN)} zgQ3S2`rJup7Gw_!Xx$OW4oEp{W|6?h@DtMab_VyoHP{g6*Ef-He!V6eqz?{ipTW+r z2i+?HDr1qy6%vvhz-t^bSr{f}g66q-nY$Sn87x<_IaqSCGFYzUa)^dI>)^dI>)^dI>!wvd(g*U(8GdCeNvP@AM8AP(AW)VUJzS;L5~CE`~q7K zAbNmtBB)FNwYx+G7=AL=Li$egnHVkSH!)hyUj&+;5e2vV6POOzg7QT}Q;*I3I=+=1 zd7$&&MOLBvpI-JL*9V}vO^pJFpB@YhTR``of#Myxd?Qyacuu60ICF_rE1Ut|e-1hy z8#-46x#PK*&EaS9|NmRDxf^uG4gT};A^Yw@XL5t;M9_Irpt*0*xF4wgLpBpOF9cHq zn;U|K5onAX)b9b`LEH*CzZB%HLW% z4MDK+N6(b=h+w-rV!(AP#ytc z)bt7J=YiH_G+Y9mZwlJWy5Qf76Y`7V~&Jd!@$kpA)%iVphk#XXAMy_sqM*i0e4E=tA_VLCuG8TfyC%|h2L24YCCh9jb zOgzw9xAstP{n`ht_G=&UHmy0w$T)E=BO`chor{TK3+Nn6(0p7sFL!r#BjZHSJ|Trx zhCg144B&lGpmq5$InW+Q9mu(+U^#h4$XUOja07)EC>%j-P~0Q)L1O=%*)IOc7hd@* zU1a5tc+r*L!o^m8@fTnDw_0N5V{YD+57_xY^N5$E7#c2dFdVt`VmiZ56UK%hY4CaS z4nINl_X}pnoiF(vcNQ~obVo6BcE3;$TB*Uv(G5}yDknJp=3Hjtbp8d}!}vv>aVO}$ z%7=?tCO&FrnfT-}^TemcEEAtyW}dhhx}Uh=?|+jQ(;a>y>jmvymSJF+&;dK2J(=Mr zN3HPe7wHUOH^9z-Z(wEsjlXT-s1ct1K$&MHXx$}D?m<1zN{~Eceg)*8V_^T7GByOE z`(p|dHh<(@X5e)A#mK}E@|9$NK=eBN`yVoc+2Q96q%lH}n-~Ncw)_B{lV2}9`$as% zPmmiy>rFTu&fs+8HLPyTy3E8G2@Y%0-3ZYO3hSB74nJ?Axp4sx=v;G#Ro_8##vpe_ zL);0PtKnd13IfHq4VJLniq)N|mzg--!S4J+a#%w2g53Fl$>AsR9o-L@7=Ai%Fo5G< zvtDdASG~yW*XBMevumYh^VEpWUi;VUa`s=Z%kQndSDyRpb=eEV{_AyF^RL%sj=x@) z1sE762rw~B?D^|;S+JoYNKjxwkpPomx1f{5N`Ze~mmf0wu6)4Gx$>hk$I2JR>?=8B z4qW14XbO6x%(n8qI_pY~hBKEq9nM^Osm!wSoi_7I4u%t#I2n#zda2B`@~uAOO4ytN zI4`L)tbD-k2f7Pl%HQgUm0$eBSAGi*TlphCbmgz~kd=S(gIE4{W&@AQ!_qJ)jr@;i z_z6lgVL1u=K2h1E=u)7Rk_qaXgcKBJ(!1&SmFXo&Zz7UoBo`xw`^2B|>L z;X;>FT;B>`Lj&?VtX%}^Q-b)MHVi`cnvnAxS1>jNf!Lrq9nL=imo;q}gzPOD3Y{4k zLOK{5f-q@6U%mSSm1({a@nFYew^b#xf zA9`jg>|E0q#*jLKfpPvV&0K`0xN&S3$FYYF0}HCzwpYx)gmjuLFbP^cR_&aW>DK1gkRJ%{Dj}jqs{=jzp1d7 zfguERmY^jAXg?Z*2wYy9VW&I?Lt!@q=sXj+ZOy`9=l~LjmKP6x{Wk@d5zHd+ds-GSGQh=@ zpn4gQ#6a!_`_~y#rYvA!Fai4&YUbhp|HU6TgZ40VfbY6dU}P|T$mH43{*xWK;!!WGjvbi-?+j^^YKZb_eht z+IUWeLIn-SDg{P|U!Z#kbQm3eazoEs1Ft~@pV8S6q*s~y<31xdcrF^W{|R)rFKAx? z$PS%I-5;RxjhhiNcQ?}KD&!d$E#+AlE#)~FE#-L_E#(CmE#*ZRE#)N`E#+kxE#(y$ zE#*}hE#);BE#-9>E#(auE#*xZE#)m3E#++(E#(~;E#+MpE#*BJE#-X}E#(6kE#*TP zE#)H^E#+e%W8};l4nLh47`8&|B9yT}}u(F;DGrLFa{2x>xQ2GiYxwq8x{{)8O|hg7=F;&d~hd%m}XE zK<-0sw}JQ|_hu+D>;%nmB-AlzW;iiStY>5RDbMTh2{gVz={zzh?2y}jApfI_{bvS^ z0SK-9l`g#UN4&_&Z{eaVzxa!-{97%)5;oS05;y&jHXg|B9ZC#4=Zi7?Y^Y<<>~Lb3 z2)gqZwsSWZLsO6!BgbiPMh2~VUWZSh_RcCshAr?t2doa@u@g|c z3IBaL3=_a>;+mUnUWkM4PiC+L(VU?EuR7n#7tTx*Uvz`^5;ISPwUZw3FqphhW}GN? zkYS=YXG4%5Xs_mFM$7;8tl;~B{wFi+{6Cq|^8a*3%m1?(E&tDFwEVxA(enRtM$7-J z87=>>XSDpknbGq9c1FwpyBRJ2?`O39f0)to|8Yjk|EC!(|DR{HykEz#@;(>HUc{Y9 zpz-z-JPcbvXCX_diq95RX1w^Y*x~1+bcdfme>?1)b;!XIc89Pev+Rx+pPel^oMkOu ze0R3w2$r>Y@!Q#wBU#qs#eZi@j$&Dh7tAh}9L=&8FW6lyIVQ_myx?}R>*Z*5U>pMer#b>YTi~ixw=wNBj$epeD^?wLxEZLKlVIpW84>XSK@b`ZR7ur3L z^Z)-B|03@2^9v)x7R33jsCUoT%1g#4`zU-`v9Y~{D`(3L;p zLstGu4_^5vKWOEDW=MY?R<6S8~#jtZe7o=PQ=WVpS zI=_j*a()|w<@_!N%lUl_mh&euSk9luU^#ylgXR2r43_g3F<8!D#$Y*r6@%scb%?w@ ze-ncxXp9bYwp@o41HxV@ho2e0|8HrK1BI`{&rUgppD+LY-#TB3;U{P>7N`zDpF83Z zUPg4?c;_yymU3L9?* z^^ZVd2pT&<9%E-_Ww;0$!%$)bjTxh^(_OfsH7Etz<^-J^NA7u$=w~8=#*smD$vz~U ziP+1?*-gxuh@dhSWHzWxjO#o|55~?}8Vn4T%nS{d^*b0oDzY<#aI!E=1nC9MX@ky> zb7%D;Wj-EdmH?{^HVTFtbfzI6dTg`?sMn=q-SOXJ-DQw&c zbS4D2ziQ1e@sTm4|M@`Pq4I^aLnXFxtVSk=5C+?V&7eDIVdraL>titPK=d)t{hzLbgXLuXk5VA34C5X?2P&c zkntXHn-Wy+fbjpr3>UxngU%3VLTW!W2)*EE*!j?yVd5iYhKaDg8K@lvT8s0DS!C5? zW=MMqbPfkd9(F(917?Sxu)O~NFl0OlqzBYqg_e_+pm}T%9~5`6HWo+@bWVM;D8p7z z*#`>?kQ+hk+cUDVz-OO<&bqLG~yzd~^n_ zxm>T6z~}HWOaPr_UC+b?b_2+Nr~l8NL;Wm|B5mAA-*p5X{O z3oz&Z|BzVFy`zi_At(RO4+5>n)&PwMfXh*aiJ4hhU_GGv7j%{+Ob;kNK=X{C_7CWO zFHji@@;~Tq`&a+x2l;^f$jJB+bY>vP{e}z-BA~O1yq{K0%57qpsK?0By`GV$`vGhH z+DE(&YY$|uu{qDk)BUiMVeMny2HPG+#)+Wyv!FArLFZwD=Ji1HXb;#RXF7U+teup@ z#MiCM$k)A=kppqAV=KcS(3y^)HNFN63?iVpI?%a}eNU?<aGNt-w~l zR*BDHEko8?8$l-CZpAK!waR=Awrd#~C*Eh|eGRe~v`+!FHwkpcBf}TSnS7u#9(z85 z?iR}ZqsPeGeIQcy$64x&Np3&3an>q6^1PSBnmhCX|8hor+# z&PIoyoS?n*iYyaB?Og^3hCGIbMjMb?P#+PLhd^T%u)g1e-42^TaxfZnmo>I~tiLit z?yCl^5e1ETLdP7YfX4GU6t2wzt!>v-ygUn(ri2?iXUQ{gzLsq0oMp}|-u=IxX(i}f zG7n~louGaHiy0U~zN3{tj~6pce9{aWV-sHm+QSVhS3quUU}e|}({~uuK2UaA`2uqH zHaJW{YC!FH4#jJ;UNQ@xmSE)UdLiua6Lg2lWANRM7cMa}N}LAm5oBU$2y*6X3SvoE z6T}K##|FCJ7Ieo72Rp;X6`=7X)oZgv86~@6c7ojc70s=nwl~a;$nz!*tPEQ+*cdL# zGjO~DjkCe#Exv`juKW@2vhr8D^Getp2CPhjr5DFfsN*{5@`{{oSogAk{QpwfY30jg z#+BdE?xsLDqwxcFJ3wZjt3CJ;Rqg-7pmT^=SN=+8TlpiNedV`sj+I~hIamIz=34m` zx~Bq^7Bmt2dQ}u7XZJ64&>aB{ zK_It#{$e)=?c;>`aVic!da^N?aj+r$_?1XMGJ^JCp!rXpo#EpO4u+6ZOj6z6jN)Bd zjN)BhjNGqZ8F$SBo#U2(Nk15AYD6x0U*wSl=ne%5AL3F;5M)OJ}3s;fb90jg6$b95lL7&8iYe^zJs`Qp!i zlUqpTH8kx{0hNs$44|@t;WVyt0<_N&R&Ju_7xerIDpS$N(9zp65PyTpJTdTEy9_CZ zpB$W^eiP^nGlq#Tl^Ir|uXzHUV*zqASS>HATKKpHGm?3NM5qzPt_HR?3RK>K>_o8} zRM#*d+=xo?r*j`^ea)Ef{Lb1!C*c*vm4cOjTJaUP6S^t=mJ18SdP$v0rRR#g3nJO!G6MV;RQwIM-gY=G`> z@?dbV^ki|c^x|-^^yYD}^bv5d^c8Wi^pkL~^p|n43{Y^e3{-Kjbk=aNbkT9JbTx3W zbTe_VbhmJ@bh2@-n`;W_9JT+@ zJB~nQ9IVdo&$V-ImfGoETH>&8M--G z87{tLW;iXv$k_#|2SDd~CV|?444Cae(0W5qUk5aQ#>vRA1=gq3Wc>0&lToA_H2)-&BSKMX!M8&+q4)Iu@54GZGK+Jc~X2emI* zpkq@1n;9>n-&+Rr=RtPR`IL;S%vl&N+B1m1V&q^50fkQ~6GJyB-Gc6V1DVah!LS81 zXZxRt;T5Re^MXmN8`NGFX5{QDXA*l2TCWQ#M;}7>i-Oh`EC9EkA>#@w7(iz{iJyjr zi3a0~A1j!|x=Wcvx+thSIOEDM>7;u8_kYZ*yZNkXWg}f#Zr1k|f!)Z}Q(Jn|@7Fh+(yG&TZ z20D%b%DbLSxbrUP?m@J;odWVZXx){(A>U?v7LQ2qtYRYB4_=!`Sa8QC1KL1$Kj z#_?ch=fcMGu$c+!H^Rdcv=)W6A?PzRWIsPl9JDSD6xN_IG+2Izu6Gdum5b1Dp8{G_ z3tFQAD<45}P<0q`*xH?-bw)hQ3?cu`87%)>Ggy8xXP5}Oqw&8zgXPpy#ulKw1_}pI zIWEt`P?-Jyf5;1S2k_WB1GF4^VGZFc!1(qMK4{Dxq!(ny-)hu)3RJ%TXJ)?mEu3@Z z7k{pmf2+B{V~e0QGO%$%P+0)#gM-Q~(E1OMS+F%?qKxxz?Pp`yn83mi63WW3g;1JO zWMv3h!GtLH85udd5}82ro(-2k;pNN#I`ctf6>|Uo0dvEwzt!F=zxaEt{1)!H@;@^( zY~B|o-!m$;1@S@dNJ9~KR05X=lUNuUCV|`zOAD|#PK3zA&y<77L)A_JmG7u`QbNXB zKxe+i!`J*ZNrBQnXswAdQ$rA_kEP7e5cHH8Ql5g!cFwUJGMK^if%fOUWQLqo2r>tBj}_=HbA^c^zmorf z)|W!U8f4ZBcUb!jQ67N$ps;=}tX~TXe@{k)nJci&IVq~Pf!D6X;susg7}eXbu2EuC z1*b8jGz6I&L*L5{%0mpGbA4DC47nvCZG&r(^MkhC-Cy)Qa(>YEyZehkbzTRP!%hZP zhQJ0UhMgzGf0%>wAOm=AYzn9>2bII1y8u9b0r4CD{om4|}lp&;3$zi7!D??zH62ne=Mux&%@c9*D z*`T%b@{Ho(^V4vek;+iW`0szne9*a9LJm7Y>lIcoIqd9UW7xTZ&tYc=7sJj4Z4R0s z_cib_>;$<2^Z&llM2pZ`NvG(qONRunNz>=0x42|Bx4i_u}{D+UIW_*}?Y_FAkC zJ3-^-AaT&yZlJN&m8=Y=pgZif6df$PoER*%R2?k4+!!piG#xCvycjICbR8_a{1_~? z3>_@Hf*35dOdTw{!Wb;IEFCPnq8Kc-Y#l7S;utKo933pXk{B$tTpcXC(ikkYJRK~% zvKTD2d>t&i@)#_&0v#;7iWn@lLLDr-$`~xQA{{Kdsu(OaV;w9z>liFSZt-MfFa?bl zbsS=_1ckrGm;YuHL3e4fI_%_NUX!(JmR4pq=x(Tqr~dyp z%>v!YW61CkbT%DGUA8I1MbH=vnfbzyCveBpod0 z?_?}I_y;N{>tMNmE@PqNpZ_5}iVl|ZYZ(h4g6sy_r|Mw2|0H8!;_v?=d^DiNWK7xyF$wUDIEXy3$2s_hjo`GBSUv46T{C{a*(u?$;R-rLXu(2N+XAzs~#~- z1Ka9UwM4gXIb>2g?;8HaCOi3OxtQ z6CgG}gXIb%2g?^AwlIU`3Nr^w4t@p`4siy{6;=+G8X&ebgXIc42TKnSTb{vkg_DD2 z28gZ9V7bE0!LkFyR%ftW;pJet0>sv4uw3EiV0i+>)@QI>5#(U`0>n0Euv`)5V96oC zV8UU}V7Vg7!BPXnwq~$g5$9m(0b<)TSaL8m1T`Rs10Se7c?hJ^zMQaFIv&~N~UAv7GSq38G6K_thAo7Bt zAqaGb8HkPs*~{1v1Uj3EgRvnf9Aq!#ZWs{_#)hC^kiCozL7=`FXs*~FWIrQh9eM_1 zLy$MfUg+K*(B1`ikiCozL7??ipnVR`AbS}bf0toRnR1=xWMt5?=XLl5I*Uz%6ZQTpP@aE5Z9m(g`I)sL2z19O z)XzU)em=oMdq0Ej0Ro+&3%bt&bY{{)=)JYb_k5wB>)pZUurtGmVP^-ZthvNs+2Q73 znQ@K5vct>4GUFD5Wrv@GWyU=Q%Z?xi%Zx`1mK|XZmKo0&EIXncEHhp)Sa!rYSZ2Iq zuPjxqeDD{=N~(~;W0n;CY3_H;d{7t#c+9|W&g^+#|2GFkp_XR`d?&1Ct% zpULw7WG2i1)0r&)&t|gxKcC6+|6(S~|I3*y|F34U{J);b^8aQg%m3S%EdTFjvi!fF z$r3bo`d^yi=YwXXHI&j0KjCXA#gW!fqN#Z)OrtfF{0+9?Iabh}I>MkfaZ}KX<*Y0J zyEFWJ;LJ4fAv5DdP~H?{Xb5UxW-!^t#xN1o=0uiDU}G?QvDncv7P(P|);Mj3N@kq+_?XkG(Uhe7)M z3&H!)#8&;S4p{lc-+$$|aKDv*@_kqScV+?i6G8q&wm0$5fAC!>ugZla)u>*_@rm*}6 z+jjx-H)tO}NFLM={fs#;4PK8UN1@nH zNb9zQ89qz`najxV0X!A~@*9W`@;l5PQ2!RR4+J(w2wR&)DD2SvcF-HuZ=i7^SQ`2U z8cT(yBdp^H> z=-M;T*azsYHF*Z%*Pq4bOF`@VDJ%>PJLg+46e=<^gn;xuV1}Hh0MZW%6VSa_kUWBv z-EN!EQfn!`-5NPZUWEQ$yVtiZBVNkn)fdM?m2nrj>8N%Rub%LBx z$9P2^Ff*vjYC!IT@F8b;g4_w=L)KkBV3u5kJeKz(-f88pbkH7N*!~sB+#1L{ z(6}qeOb{DHgUojL@jnFSwg=4Os}!N-5{L~_1F|pi`~Q%G|No1_%P(VwiO_U91yrws z+K`AbYLMNK@))Ea8+qsefeE&DfcqFLYKrUmE?SQ6zupOW~zaH>A>_k>er1?U~ zdO&00pn3z8AF-Vm3oEZgRUCe9WnkE{f(v{`*_Mt)4wf1$0%p^r99GU0bNFe(?R43K z-SIL58)QE|Y&;t@hxUkBY}I3CkyTHaC04=qn1bebt-KSB0`+T|;_7=AjiF@&s8a@Z-K%1{V86A^Sy zJ!t)6hnT}pF;>UR+xZ-Rz7S%ZxPp)2=gLJ+D_`lkXoC7*DDqCo@=hx`7`eJc89BRm zFmZQd`bBirBWBQj2%vFuu~ko@^Mf$ItoZdG!!MWq{})I0!%hYPvkWfKo*S{(ptVJ1 zT%fbiu%DxgJf94S+XkV5-e*OMn?Ppc54vul(ZA zvGQ*<=St8y51?}45o&l7vT&$A!`vFeuDbX50e=uK5Ay1 z_;@oTWUX8T*yoc9wq|9NMs8E@)0~BVRj0kf;eS?=s=7P>Tm*-_D1fBl`I?s3^6GI57 zeF)MADjPvG10!V29aKMn`Dk|y9Gr!HOh0ip_A&j3Gf~@5uyh8x$L(d|oJ*X?H-5^L zIsWNn;h#?&wI^q@{B;ALm**h{8P^Am^@G+mCbKYXOcG-V$$*|$4>}_mbiO_)?qKKE zYcVtgc_>28uICiPJU7ot4AkZUwE-aWljwKDf%Y6_C~(dm>G#8BHaS>wHZoXdwmDdG zwlY{|b~#vbb~0FI_BmK`_A*#zPI9p1oXB9AInBY6b1H*n<}3$G&Y29Bne!YhIp;E1 zW-fBD(FR-w_BPlsG%&7ZXlS)z zXlS!xU|?Cx(9mVW(9mte(7?8qp`qV~!Lh-Xfq`=^10&a3h6e7n42?W%85sE1GBEP5 zWoQss%g`vemVrTdEd!&-T80MEwG547YZ(|M)-o_ku4QPDTFcNVy_SJNb}a*=+**bP z`Lzt3jkXM|jkXLTjkXK|jkXN3jkXMujkXLLjkXLbjkXMijkXNBjkXLnjkXLHjkXM~ zjkXMqjkXK{jkXLvjkXMtjkXM-jkXLajkXL4jkXNAjkXM#jkXLGjkXLWjkXMpjkXN6 zjkXLujkXLOjkXL^8*LdTHrg^QXtZUR(`d`EveA}dX`?N}mPT8K4UM)8dmC*Tb~f5F zoM^OVIMQg#aIw*r;cTNV!<|N3h8vBx3{M+v86Gy;GJI&XWq8wQ%kZ<&mf>roEdxuF zEdxW7Edy_pEdythErUdpErUptErVi{ErV>6ErU*zErUjrErV&3ErVf`ErUaoErU&y zErVy1ErV;5Ekj6?Eki()EkkUREkk6JEkj0=EkjC^Ekj|GEkkaTEkjL{Eki|vSnD?WXrI!$(CV9lP$xRCR>JsO|}es zn`{}*G}$toXtHIv+GNXcvB{R~4Y|C)9*_Po+vn|7eW?P20&9)3Ln{63>G}|(KX|`oxY_Vnd z+ic6g(_+iO(PGOW+G5Kf*ka3|&|=FV(_+h@*<#C}+G5LK(qhYC&|=GA+hWUL*<#D! z(PGQs(qhXH*ka4z+hWTQ(_+gI(PGPx+G5L)*ka32&|=Gw(_+g|*<#C3+G5Ml(qhZd z&|=Hb+hWVm*<#Buqs5kCN{cPS!WLVGxh=K~Yg%j>RJC+A@f?+A^rL+A=7#+A`?2+A?Ui+A>(Q+A^55+A=t{+A`R- z+A{dG+A?^w+A@T;+A;*T+A<`x+A_qn+A?Ie+A^fJ+A@^1+AtO+A?&s z+A_4X+A>URwPomSwPl#oYRfRA)s|stt1ZLAR$GP*t+otnT5TD2w%RgmZM9`M(rU|a zpw*V)Y^yE9$yQs28?CksS6Xcu9=6&t+-s~=3@UB542EsC47zQ$3^r}H3>Iy+46bdq z432HK3;}Jn3_fkP43TZN454kd3@L543<+(v47qK#44G}V3>9s*3?*&042^BJ47F{x z3_WeO3>|H@3{%@|878*bGAwAbWth`u%doP|mSJg|EyI>JTZRp7whVjQY#Da8*)p7H zvt>BaX3KD~&6eS8n=QkgHd}@pZMF%t zL%S^lZ@Vo6XS*$fM7u46NV_eAV!JJaY`ZOkPP;9GM!PM8X}c|hVY@AZL%S`5O}j0F zXS*$fYr8E&NV_dVK)WqNY`ZN(WVDBmbBY4ENHi7Sle#Pu(I8jVMn_y!9A$k*kQ}Cw!@ZTPlqkTjt*OfqaC&k z2Rm#TE_B#3oawM-xY=RLaJ9ph;Yo)r!-Ec6hPNHI3@IW%%1+ z%fQoV%fQiT%OKim%OKck%b?I{%OKNf%b?k5%b?n6%V5%J%V5xH%V67S%V61Q%iz&z z%iz*!%MjRU%i!B-%MjCP%Mj6N%aGb>%aGV<%TUm1%aGG)%TU>A%TU^B%h1wk%h1qi z%h20t%h1_r%P^zUmSIY#EyKc2TZXxvwhU`JZ5dW{+A?hIv}M@XY0Ge+)0SaRr!B+D zPFsefowf{DI&B#)blNi9?X+dM*=fu0qSKb)NvAEt$4*;@x1F{Oe>!a$estP`>T+0n zS(wM+r^luFK^a*Y79F5-uLK-^X2?1GGy&bQCR&@l*3`?6b6PZAUzz43>QIqko#i{3=KiZd=4ImpPd)y z2Qg%3g8LkxeY#)#nOB1L>VocBh-YB<=p-_KRy+gqYS5lg*cjNO^9(D|$ALioBGCLR zs7>;cnQ2wM8pB7>T}_#63>WK}IKgXuGntq`cg9?N#VmYUlaZ^dzRBTZ1}j4dsJ-vS zu%HNZ7s(?Qh7c{m1GiSQHw0xfa-G&uJw1z;p+RW1;%TYZ%-ULBU+XS=iPl}}Vs+ST z&&d7Ci?wT(mm|YPZCi$k*?(Ow+cUC!bZ+dP#mvgErTzxPN6=nbO%3L5Ek=i*T6 zJXjenYA`bV)NW*$m{6JVBZHT#n}ad_2LofnPYuw17N*%jS{a!?JQz8;H8M1Rfcycv zyA{+wVPLeJ$SK$q)XA`*h>?-A8#a~-Qq#=95CYmy$IQs^3e?Ym-Ms_b!wicrP+UPV zO50CS7&LF)a0#27qi{pe5jO1YO+`+GzL)GwDVJzea&_-#VtNhQe+x@DUvFck8_=9SXbcOa26Ue?XzeU0 z3>I*J)^Ibd>SS{GsRdfw!^rT;kqfl9nWH<0QR3AZCZ5yvj1sTjF!#)w#>m}$pGo2s zBNs!+eI~9~ja&>Nhnd8?>lrv+KjvZxS;E8t9!JjLW(c{##CcluKEp~5W`>_zxf!;A z)`xU3EGU}J#L@lW5XVH&cmzko3k%R(o&$7^*<&V$pY;k3AC>DAad>!lXc z$__q`ZqS|8pftplnF+pIlPgp62WZTRgHf~_HkS@&^Fi(w{C|i8d`=CvwUD6kQ`mY) zSQ>-RC2=(bX+qY%fYTZ%T%j1uhpAi0(-0(&qz)#Y$P3=rh`COkw;>2LuYqpgLSE3g z8>CN;E_aX@NBY%AJ(C1O9}_5jPXLd>qpu%C-scM%U(f*UD+Zm*$}l^q5fq=y!mB{z z*^i-Ty@2)tE3h$adBNuJ^8`1;7J1NKcV>o=lT8d0xjxoj_GT38&TeFw_{NE0q8Fn$ z_?{+E+$A*n{Ni9@2;ux#JL!}Y(?grI;=&$KMeT}DA1fAXnX@yc7XQ& zX@l>Z66^MAWSGdw$ay-OQM?;;pIA<-!w;WUh998&=bUgDv6T?T)o@&^<258O)ww9nHNnqkh#)e5;ObtQY3>`r{91THd*&BlTm>Pok z6(DPG3>+CI8vb><{891ZEQNngml@d{CJDMQ&X#v$_!wX~aaJMc1u1(b#zI4*o>}%x z3?B`}=FhVK#qiP4sCSmaulmajj`k}JKh<6~bYhq&&m{Qzg5msG0*nklLHAmL(mn^H zz{L1Q-j4@9{|||G-3pnYvs@j1 zYGpF~^kQJxYM%=pi zBEv*ZrrANWm^izCCqvdtfX-*W#>CSN(xb$|5K>lc`eQ2_!^HiE7{KR^gXFmw7(}x8 z9DaH*GW^Wo1K+Ja5p*U7XzkrrC5DOnnb!3A2doh?8e!gmAnCMZN@xzmsvs;rf{)Yl%!%t8-?8WTx)02_2 z+mo5$X9okrR?zykjO@}M8hoHV7Y&!>Ss8w2WtaZYW@VVj&C2kTlb5qwi<9AJJ)^|y z#^3)#GTA`wF@~R+zy5E{P=c(Byz>9Q_#1Z6*>IroNAXpUxE(FCa3&R$W zUqR&p=pHI`znhgn#mnLHDOM1bxJk|B%~C5)2KOe6XllsE3+IL3JW}xdWQB2Av-PDsw<> z6DCH7pA1Y3f*6?=fa@YqeUre#u;m0F=qy2(i6{6Ne$MxE_yk(p-|;WyvIi@}*6IHe zE-$Dm{{bpT8kiWiZewBsms=;AAngmtyeMR^FH9W+Bg0lk28IcW44`!cO+m0ZMUWW_ zs?5P=-DhI3?5GR5%#x8|!NSb2RX9V#0u(>k>I3xp)KLx9@6G>0;C%^Lz3-?3TEhwP zC%XQJ(DDrwW~h6~m{uh*Gi<59#qd#yg&_n~H-qjW28ENDhH&=_X0cVAy$(M-L1D%O z%2%AP6F3<{K=*c>WMcT)sU_U4!OPJtD#!qDhj(Rx+u^4>vNV6d)_;6M+n)$?GovV~ zztG*SCs^{}538J_OIxLgvvyavP!TcWm_wtX_eoVM_&vl^lN^FUvDZzLqeY zIg3Msxtp2S;b$|nY<v@?aPM_f8=w=pl_{q%4u%&{9;b#OZ!xnjEhL4At8A37~ z7$$OluDuMp3)9Wk>j;eqxUao&>q6~wUaU# z7${11yomZgVr1~G+g3j zlsKKi!_f^|_jrm=65Iy!uFU+w4QY3Q?~Db7DF>s(X;3-K!7w{$A-D}GvI?|r2U}SL zYIlRyzM!Wy}g}GBd3Ltq~EI zVCw$Ngu5;DqR$6(XZMzqQli~jnGQd@m>7PVWP;l_;5Cl(nHYYakP__{3FHOO;lE&l z^fz#~c~IMKisGnw4%_;KZ_F&KzB7Z|%n05Kox~0~n>iemHvXktwqRt~n(;68GDmIg zB+wn*pmMH*fniH#UC3pQ%uI_F3=F0XOqLU2>mm~b5ba@586?jj{`zNA!z@Vt0L}l4 zuX+qUQvwu54onPNESVU#*ef%91l>!P!6exYy5Eb5gCXPulVmq&ec4KO&^pV8OPb6a zr%y3)bZ4O6X%9ZL^9K{ioe7t_sxrW3a26B9jb53V7F52?+-AY#wV_)!VG4;6f`kO*i!2qdi{&PY=P<>%*B zlR*8WECTnk*)wyze(>#oh&^}hrvqRAhk){^#^>5enM~Z>r2jP_Xm$AG(8};9 zTajTSsGkGUY}6GMK=`wb&T8fWq_@D}xCKRP6~ShAp6UD1VjVBk0U>1_#g> z+Cgv|ghRm{JT79-$oL9$o(*Vx1k`rXV&FLK#R+M9zF_7!t-#391=|ZN?+7_NlHqO5 zWtbSJBf~|_zfPCA6dHm&6;IC6`s;L=gVkY@gDS^tm>P7yE>s2Ibp`L6gVGBWqx9_= zrBTBKG{*NWoM|O&oDZ}P7c{nG&&c#j5xgHC($50zmjI1Xh%s<>2QzS-K7eCvB$*Gq zr|zdlW%3VDUOLFe5OM@GUc$igI*FYjq=SXwBB(sosLc40^`Z8%MyA$}6>JVaIWn_; zF!M6}ysyMyd19I4O3)d2pf*$n8)$7K$LW(o3_m+TV=0Urr#rbAes=OX`~=nc#=z0d;Q?U_GjMc++teuSN<=&1 z1oWQxm23__wOSp1bTe_i?qOm+4LZlp+pu}od?v2f$p+oCKNCeT_9ho3BrEZ{LT&>boD3?i>VXClvM5PAKQ0knr1GCpX}$ovYl{+xl4xf`}t z22`Fy>JyAJC{WVrLkUQDp@$=*BzAE{Nzhmmq)tWGvkmrc33%)SdyAtDH}( zCV~2ytD)mu4y^TSop=weNno{Ko5b6+riYR7BWSM@XnbqI@Bbn4oVA}Ce*F&t?cD^A zkumXfuV&)u?qTFS?a=D*C!v+$PY<-r2kBw>^*`hUmVQ~IOGA(ZmT}01E|_r*@+Szx z@)zigj2H0?pnHzM=?Wx=o-Pv6&ccAr$$-*;JPX50CJu(5%n1yZEGeM7zd>QgFmXQv z!$%Ir)>)vt1~u6jOfs_=EIC;nEIC2!JO)cnP6x}EtPCcZMGTglybhKpLF_UHOHM%t z%atH@6@w+GsDouEh+W5E$tmeznF(SyF<5fSI#_yw*li4!oQe*Xnjm%;gC(ab_^wZr z%svK7PE7~Pmn;k>nUfeSIdvT@PlDLf7%Vvr9V}OZ*s~ZcIZYibJ3;Ju43?ah4wji9 z_96yL4qFFH4;BWKjAf90kf42dpfLzJP`%Co84CpM^OFL#GZ-LY58Br!2HIE00NICk zf}tS@v?m?3e@_6^mS$`KpDO^`uLl~}1ntuUjq7AU_u+x|<$>0-gZAUW_Thob0??kc zOeT(Qg-p=c5$aw%(ArSYctK_s!$kO5>CpXn5155lAzG~2ZSI~I>1JF4iP%jpgW%+EQ zhtxYT6go;Wgn;;<`4=~F22&>nhOKSl45srd7zz)GGlYQlFwJLRD15;_Uy7TNjVp_h zLHGs(Lr^&*gGmGaGamT*ug)WF-rq9 zRzHzLkzwLmM#1iEMTUv-4E(PjF*B@M^zVPjO<4vZduGn;l}rpFevBO6@0A%QzGvj% zKF7$frN=K}-o?myI{u@>rvspKc9j_>Ixuo{Ycle7gT^oG8985PHg?X^WaK&xYVU9$ zrEgF^`pL|>>Ls(JmIgONpgl7~A;-n}QLmI4CVD9{TnuMoFym%x2mE7&mLPr)E5pPdCWfD%{{I)} zW@!lGVT0UJ2{LCLE5pQ>%)G1avod^q%g7MoTbcQzmyuzsE-S;uJ|>5s_Zfv>ANuz{ z1at;(Cu6tNNk#_HUDn`vuudk1pYQ+w7uR5A2;^iI*Yad!FbB=)*@N^jFodjPZ3xmr zQxCFJgXM?$ORk2XS8NSI`^ts&?I zGlv$)-~6l$7eV9NFPQmPf!qpGpY;EKNPlIOGz%6E_XnN}(=F_?ht1C?PCpmK=W z!BU)oVZwJNhKZoM0(90bBF_u2Vl;xZzvOM$3UiqmLO|ywKNffRDPq(R1S+dQ@}T_# zAT#A1*a}~>Fob~iTfPtnowE-a#}onIq0#{#%LLgCG6QtC3S6&%L*Z!-hLCOG`oAGa zvc_RDsILyPr;~}nTd~$*GRhf6(D`lC!wTK|?br%)7#Ttmm_)l9nMA!oX2Z&|A5OWW(P|TMg|kqZ~>L+kb7a|1sn>qL3imv-7Q|@ zFnI-&c(*1q#LZur8Ga(d6EZjY{g6WUe<6p$EPjTN1x(`IpzvvA5=V2lIJdl@L!lQR zs1MU{X=PRhc%S;o|Nl)vYsJkN9e#r9t&>eJEyO`<8e|!SG8h<4K>cNq+d*+F!3;XD zQvy7P#J~;Og9aHN0m*~f<@cEwEJ1r&pD>HA%3xtI0nL+w*r0k_gVDkAF*E0?70e7K zpgma0p!4`aZ zFAHc~0(56Kw9WvZ^8^-SV3@L>Nf>$_9O`*(pnGkg>Y;aPh@kA9{afw6@{7OQN@C7C zUf9tL9`lEp_XSkH29ws-gtbLMVGqLC`XmdvG5aJZxC!@38o3!lIzH82=3qpeB_+bh z*#&F6fZ8hP{SwgKCLSMaFKe(eYytI2PBU?I?`Psh>60`uLi!}2HaV!S1l31a`Xu17 zQ&5``)NcUw8O}5@Onl4CxvGJ+er*#{zX5djFs$DII=>{I)8SLX-~S<}m^iyvGjW2> zgNOGQIH3InV){A^82x zU6rzz1C)22|D{17LFjdC31o8 zc31!}??GqwfaV23_kX+)pD(2oDi-{zz9Gn$wQJTo#kxtS7&%tuGjgo@z*xUYP=&vn z@mBfeM~w1D0!%#I?-_ZxAG0zDHZd}B3$QT=z87Q=RAyq>sl>#zQy@cehdvYA&TK)3 ziJ-gS9{&9wvY(Ofbpsu`&EyP^I|;JXg-dU;=6@c(XE0>}F#4 z*~P`x?ZL^g6V&G5`s;q#E3|gfs;sOZ9I6hJIBu3-_Q=fG0Wt?v-z)z69|9_CA!8tz z?fML8SZXpX2zt31bA1#jJW<=`jH?(~9Dai8UXUE9j#>b^BNOA?cThh8t!<99_Zl?6 z$pM;EV05qq)hD2P&ms5lF-(+aWGDpPQ$kMrA9Vf`7lVW4OJ=TB-ZL2k>wOstL3gge z?lSLXU=Zlb%(hs|$=AJrQT`eS3&TX%{eGbFgZZ)yMG5Q-Av~fE7P+Dh7V{Z-!DlGM zKV>XzU}p%4zsOh!I^!t*C_^D=A17$eDgGcsVFL?82uQ4vlOY6~nGGCR%)H20n83ym z0x}zPrk^FKe~ZOEpfgC(-2?Jx{8`4r943gp34i{F#Lr|bZ20*<1T?-5asw4AC>U`e~2t-9G-yzd@cxR+y&$}&>5s4_c(&~G$XkMWJUsL4U(vX z1?Vnzdqy5exLjl`1l^h0$=48sZYSuB8+1ECYd}GEfyN6p7#J)cFmtQ|@sZQm3ueYu zpf)h5zr@LSz)}n8-W~f!hCJ#ml zb(-;jW!6E4z<5NPeaEf6IkolCh;Cx&I&=7OEdwE*+Tj|=yI@qZli5rhLF)VFa!90FyuK&&^RqI?Nkq> zcIpEz9PLzwCcN!b1qM9rR9}(cSN|I!?Nm*)cB%k>H{-h+!tGQc21q;AhykOW3L5w3 z7U1gE^@X-meM=DSR940v;5I6&19+~5>)-q!a2wTEgp4+-=VdQnXd6}6VG_sN8q(XS z3{63J+o;Zr7s-i34NgQ~;{h3c4KaoZL17FFioksih6zCq3=4{2eO+)LhLPbTsLug9 zPnDCgZnNgg>dRgX4MAS4^QA!T&ICq>zps}&Y)a(i@Z)YcaOpMwgHK7k9DdBt*!6iB zIJ@VwGW?wXmu+Q(Cd1#B#-lbZGKzjJGK>6L8e47V*K)3Gux0q$qIkd-F0R;MJD-!` zXEQIu-}!C=XbgZ_Ui@Q4m+7IFW>wY;q zw06?!tZYa>q?T)T29^6E@;nZo5(F4RM(@+6?S0zv35=HVDU6o#8H|?lIgFO_1&o&R zC5)Ex6^xehHH?<>4UCrZEsU1(9gLRpJ&cy}6BsS!r!ZQ|&tSBapTlS=zktzFehH(c z{0c@(`8AA|@*5Z}<+m_e%I{#bl;6W>DSv>`QvL{|rThs-OZhX5mhu-EE#F~!)Phbz+?$(yMp(jGcd1Z zU|?Fyz`(ecfq`KyOb%P!o`_}6y@QChs3U03{aYRB<6B?rE~C%AV;ko}pL@qQ&PB|4 z6s2?T#EzkX=HBBu>pu;}xp(CLCTMN~G>-Am9yDGJnPXf4I(y09!4kB$N`sMMrz&WU zn#sXZ{v<;o=sXnpsf>l7yGk?J7$(B{*`V=f24;p3&{#95pA9>I5i~!It`0Q!hOX{2 zT7MAKS4Qs(cCb18^aP#7!pN`_bk+*GJgUE#Rzb&D$m%O1n>Eb)y7D`?IM zwEo2bI(I_+cseO_0HE@#>nFQ8Xip7BACb;$fw0wA6wSxHt06rNysa77`50D*5kDV; zEgeuahQ>$c7#i>B7#g^ZiFR%oz31l+$}@lgsWeDahcJj_U|@t$3?Tl$JG*9-g%}CI z=mYW$3=Rwo4Cv;=G>taiFta-1qBQm8ku>SC8;TznhJ`x3K|BQ3>q3GnINu>f`&%6 zZ(>DAW{PK?Gw5yuO^{?!YH4w5O1!3~f~~EBhK7blshNo;R8YajMj_idC)+8rq*znI z&JMu==}aju(X~s-EGnstk2Z+agV+K#B-=BuEHNiDB?M$KLo&!N+h_*WV%40SQU(Sc zhFFD?%oJPIQhn7@g`C9VlK8~rLR+w;hDLE_RVv&y24E*9fea`{6D&zg!XlEHQh_d- zU!bX}0P;N8&rTq-tgN!Z9OwMfyb`b#U~lN!LHqzx40Q&BhDMpDrh=V_KAi&Nu^OY)0SDkK)AD&*zs<`)#}F%*{; z6cnWv7ssa-mL}%J7ndX^XBRUBLq!!56+m}mC={g@d8wDkSEBuEVHQ z$S*A^C@oP)%mdqiqP9GpGwY>oGta9-ma2Ud#|u zT9j9;ke`+YzTE>NlbM&UkeXMLS(KVnsi09>oSIgeqmY(gq>z-FmzT`Bv2q?3ScpX#1e(nip&ywn8hin#U(}gmGPkTl9~e30v0Vz21T4g zewsp}0z_H?e5D9nFPH~$I@GGnyyX0%qSWLPh0@~0^i+^%AbL`Z6%zAOAZ+BQhnoet zpCrCCuQ)L+73Pex%={ck>H)i=xH2zU0isYBq^zV;K_gW!T~8r5F()TKSwm9+biIiJ z=yDTeER0*8u zi(wJ3$B>bjQxcz_7oS>GlwZW)T9H|zkeF7ITBMMcSyWsC%}J>#3SfCXhQtz3dWkR2 zNlh(?&n;#M1~EWa&*Xwa2AZ~#Qq%H_Qo$(;lwd*WvjpVs+{C;}h1_Cz!Y#>HNCr7i zK?#};p{~;e`6NFrGbc4364vmrEJ!WN%umS#MQo))c~NFbDl9e%iohBaO7a!Jc7b&3 zF{I^`7H2>W0Xf$V#8)WJNKDBuhv`f$OD(EYh)~D{#Uw~RzPK_sDL*H(Dzykn4_r(k zIWajSwO9dJAHInJJ)%gh(iWB|yRC>jZLPVrH&FVu_w-8o0zM zD9Q(=Byjwf=B5@a%`3^wQHYNR)t2!^sl}zasT!IJnZ@Ajk(#2Q0g9iL)TGk%bZFsG znwOWEmku(pEHNj&C^IjG!8t##q$oe9SfM;46;wJa1VI$}=Y>I)XlN=FrIvuptdgSA zRE7K^g|x(+;#56`j7(5vQ5g@aT^IsVi*%vM1S+lo64wFw9%4fVC~80{rJyLaEHl5f z7#2~m3lywPpZQ&4bCOwLfqORXq@7^aYtUz(JYS`3O3sAf<> z1c@kkaiF76S^zQ<#WHh9qC~RM#21T&AsML(DXD3Rr8zJwGm90B6f_KtEHK=ssmG9+ z9}g-75s{OVT9%pvauY~6qbNTwvkF{bDrDvsGiK&Q2nZDq@b&io|B)Hn1f*+sM^TML9?78B{MZ1 zT-wB^AfNDiZJyV{Mng`2^;K~ZwECr}pdJM%GiAAX?@dYJC@kowf2q{WT&W6@63Pq`D zsYR)I$*Bs-prj2dd^7VDax#;WwY5QI2Gjs>T~?l&m<=*bkD)jP{9GM{xkCwV0xhSL@|Scf`WpwYMz2>nu2Puf~qe=2>2$l;KaPl z5>SC^rGRJ@fO9A)Zc#F(f<|s>afw0_EZb^w5oZQ8GoWfWiq+%-^#v*mQlSl6U(hvZ zA(aKG(AGM*AzT8H2Q`7=@`z?KqyZ40lb@KPp;laySdtpA1I@hg`9&$IMe#+cIf)gZ z?gz9#ksX=`2_vxSBFe#LS%36i{JOlnN?B!R=vCsh*r2%f+Cepjxb< z$ps2=5YtLEMM2x3Lba-bi@_EHa502C2KjmVxmzi?IEFYX1UWjpA_=)Vy7>4zdvh_k z=NILdmSpCoDyXJ_n|aVinrezdc}8YVszOG7P6{YpK@x*%iWL_F7XvuZKsw43ixptS zc1|VOfYcNPP!h7@f^>;M&7u6{#FG3XP>N2;FK5V2ElC6=PB1&Mpdd9x0Z9m)J~UJd zbX5y9L9G@j6BMhURx>D8K|MH7Hc0hN&2>sm*U*H7dP+)>f;PBv0d<9t6}jf6ASr@% z0zt+ps43KGXqcIR`hbQ8nhLrKh9J}2977y^tQ64FvO;oVoI`ml6*tVnGoJ?Qd#mAS(pbOem6y5LskA#D?sw2m4a$9D6=W47Aq-efODLV0+<4qH9??|bjdHz z(?~7IPtMR$$Ofm)fW)Gb;LNI2O_(z>Qi^o#z)Bzv0{betw5TXGuOuGQ+k+|1E6vF% zC@BJmAt*TXKrJRv3WkhcK=p%$9pHU-EaM+w?Vz@%u3bq+5jL~IP5`MeBu*Bj6uYTl z3m7ys;4X)_6xMss%+HHYE~xK5^HU)LnVs$LFgfFOX0ZFV# zs*Ayy!B#az(~65hH3b}*;N%M)vB4U&ptKr~OFAPpu|NSlSc6=&f%>N4ZYa2<1COJ? z{H38$Tm(v`phT;YQVbc2DXxN!U4hGf4Gpc7;*xk!F$jwZNF-;bR4Aw^WV_`grUzH% z!AvpGWB?^C=bXgiVnQ^nc0yTlaCKVMWRw@)E7A5AUmZTOHE994@7NzCnms>%a7z$e85>`P&wJJqHOF^|N zMH5skf=b1tR8Xs+D76^eC<1kUK-DZ*d3*^MvR$C=Tz)c5Y=Qbcl|e%T8Xc)A@u_(! z@d~=I=t@nAhh;kjJ6i>fVo+8CF6AG%lpq#`%55;Qshb3=Yn zd~RZ8d=a<<6%WcawuW2`@K#euetr&vYfzAXkd=ZPyiowEcDP`|s>RUa3DjIrErt|G z;AqiQNU8)imGjdSRErffz#Vyo# z2^tz2NvY`ystWF@C7_h=UX++unv+cwc;K0{Y2uLl;NGt$HzIsurLTNEb zVJT!>K(`DYjfmJSD9Q(S5mxm=;R+1 z;_2tE#|6L37uwm#FTxa2&?v~LEC!9HKwB@G49cL9TPp<@7b`1pqs}ugvqS^jlF`t} zOo>lV1y!SKKx^_qi zLi$G}#~?%-vJdbXuK=ohP@M=)hoBN$Bik?EGX+ZwyFf<3A!%NZnYBDO+)6?T(C@x7! zEh++0`K2WcL8*x;Zkai$A^A?FX=$lN3>qM#Q{r>rSud$HElt-BR6~IZH3kh0Q~?EW zKFdw4fM{U|a18Naa4bvA%mL*_1#p23?p3K4TY+K@q&u}J8f0F68rZDVB5=Aq+I&25LH}f_e@h1~jxlWjzuX z-f>X3RR^^SK+?!!45gr9libWakWC83B}JKe=?tJ252%3vE;b?Ua6JZ)p&;EhsksFu zm39n>!V}bDQ^+p>%~(JOZ$NECD@YBj04gFhG@x}8Xyy!7pn+^D*3@K3EG@}r&|`3M zb#n~$31KKs%uCKMW6;n5RpmCIStL*s0@68zwdykSl56vBF z1j7JT9iN#NpIVVwTvAM&J_U`;G=)s?oK0~_u_gn2pc+0vUJ98s0}V5QI`MD?MUWvZ zNTsY$3>%J7C<2WRgD#BER{)LODwJgwfu;|Yg0UABi&jFd21M0eiM%45e zQY%VQi}FBoaPX1w_=3ce3m5FFDOb)%dB7sE-A_^01X>wf=5TvGAkgl0SZ?IP?!~i@&Tk_2I={MrXoO7#HD%V znRzLok@#d#l>qWJ+$J3bSY)Rq7MCcb6(#1T>K5dK2M2YN5<%T`i1ySX&}0BuJTEav z0nwK&EdtM8p<0xdSdy4SiA7)oAUO@w8@ZtPN~Xkkhza_jK?Xer$aG$OW`1%>4q~_! zJiZB$QUFUS6oKa1ic5<17$Dl?lk@XRQY%WpQvnRVi4_WYrJ&ga@Yp$MP8kxM#R}P} z1tsA0mePzVc+luJ zgD+?@F+UGH)D7}WYDH>tDYz8|nz+dWb;$CIKy4dH{D3V44Y}o|C?F{X83oEGU~gz7 zf>S5LD=^Eze$s?Epae7%QJj;X4h;a%AQPgHflj-ZfTkHhia@D7F(oAvR6K+1fy~C| zrY3^tyA^Ws!81{M3}vZBN%_T@C6x?eFqQ&jCPD)=ZBd+=lbTneqX3$#NK{D5ECKl# zVwaABk+y;^WFieBq6y2Gsd;4#;m}E}l6-}t)ZF|s=)fwxR0I#hyF~i9#C!S$y9R~C z`*=D9IR<&U27{cNSeBoeqEG;8r{<-Dieu0`CTLcoC^b({!38>hlUb}#QdF9%#{e1Z zhfcynmpwq|j6jp{(Dr#|ex4o!h#wEm>G6prpqinC!85NcKRZo*uYZ29M^V_g_I-9BL)V5NKw}FM<@U$wi69 z8493@j?}~yP_#jMz97FDfC{Vp(h}YLG+jtAfo6k2^V-Fwxw(l&l}IM1WEO+lG~jt} zkY-333Q?Gu3QoAl2@N6*FJi&kptCjcxrqhPDRYo}!F{XZV(9dXLT+LKC<7IxDu70k z@{2&@o*JMu2x+f_4T2;@FcVb$Rx0F!0ty*1W$h{fJ+yMyEOF} z!0{XpmQQ1F1{M4Y5RO7(Q95{%sTf}L6{n_`AtnHmON&eLbHVkhda**Vr+cugdl)Q* zC_r5d92&q~?4fcZc zqD0WBOG!R7MB=q= zp$TeaW)_1i2UTNmTfoEapmrBzIFcbbKPSJ4!5KtmR;5DQg~e718i_gOiIv4Qd7#xz zHK2YlsD+oBo|s%2UjQ;KF$L6iPJyo91Wh*JcI0rh8#88Q-!QsRq>ixKYdNGwWG z2nr5HS_hT{PQ!WmdAguz)=@}Q01bMl7lCFEp`)>&NGvW$EYCxo%Pr5yOwIr;dP1y( z0}VP9gDn6ps|43Ukct@A?8r<5yALwloLLN--2tr%WGK#0D?xQCXh#!Tf-h~H z3idxJjY2JgI|?)>qEK9#1YH{mUCyZwTIrLVm;+jZ23`l3n3)4=%oc&COceY=eS8!& zQc^)v-=L_1uC9eFF@Y>T0u5bY&a-Gj*T;ce0*ayZ{M2HFq*PEt2P6avAV{o1GZw_P zDIis#Nv=fjVovC45Rl73wt#amq*GIpk(h_%15p37A|6x{CWE_?;Ql9Q!JucF0wOKs zf)yb7I0sZjfEKwWf))*fCiy{`7Q7x1>VN1giGoIckpi@Fod$Cbrl%pD0ZmYbN-T(n zE}dj>tpF{r1kG!K$~@4tCRCYVqaIxHmViqMP-g;SmO^PBXkk7qJi&`OQx*J!brh0H zOTal2GPIUfk_rk5Sa5&~lCs1c1r5;h+{~PuOvsw1Vof~-ztr?Z&}v&)ha1$*R7lAO z8DpX(#w_(KxytiDe$B+z~WKB#@1=#=&CYXRiW?ou;Q7$;? zz-zmd(p=D*nZy#%giv}>Vy;4QMrlb(et8~vxDb?zk@UlssX@(1ELMP4QlRA`$@#ej znK`KnC7HRYpneF{9q}odMGPUJG*|*!=bxHf0$TqJD)He4gB(!|@BD&?D8Lp&$A(if zLCe7Niz@XP(n@o3z~ww>6@PI-Vsa{co>Kv2e@<#iDtOcmwBi{oZ>^97S~3S&7MYz| zl$V+Vsvi?U9Ytd!aMCKsNh|?{Ofe)>Kshrh6+Xbrp!@PqOvw6BL{IRVn* zXlVa3J~_WA734z(7ifnQB%lBi0ksMgoZ!yWQ9##XYY1{CGzXOAD?kPhpjs6Y6%5Tn zv_Ug?soJM~a}^3;0~H`6u;6+qvlwZ35fT!RNCKDO#o)!cX`nQeQd*Fc38@)C zO%+fMf(!~2>nXTaB<2?6q*^JcySTc92E>Q>d%OBsDWv7+>n0@@>4MhZtHU!OsOew; z8u3a@&W;DW7qr4QH?f4l4P1Uer&T}&5p;bacnKP~SqzO9J%!*@L>4Lnm3h!8f{aY0 z7U^X`8bBGTAUYS6P7!S}J%!NXR0Ze^3aEfhPc4CsU_zDaG34dPgA!4E0cdv!$c4}* zGAJ5AgJ+Og0!X_IO+bZbL26M>r2?ob)h$Uag3dr8wNi^qii%5$K#l{K%HVDTbi}2+2sDgZ zR1ESOC~%8Qiol~E#U(|_iN&BfMTNA|Jn$A8aN(Gi3EKYxTIUZQlPX4T41=sG$Rp00 z0?T5-kh4~9YHn^SxaEe( z!HEjc%nMHN5EUAl*xd_mXo7pJnRz8enM5QSNWWYk-zwB|NMN8=9JzLfFva)VvfeLWZWKCg&G{mc)bFy5QC^++dg#yd72q8b>e4%u5H? z)R5M3acWK)xQPrIBmfN$>4Lhm;BkG>L{u>YXv`e6UX8)OEVZa8GX*kRQ&5x-ZtQ|& zK^1dJX)$Qd15{vvy5S0G;GT419%QDA0o*ADO{9X$TeutH${}4#uqx0*NM3OXbY=oP z4Wprn-WULB1RDh%JHgm2T991K;F1cf(Nh(2L0ei1a#Eq{p+#V3UV2WdLUDd+Q8K8N z2Ce%u^Au3_Ba~ zZ5buGIq}K)WzcoT4DP9UpdCS}3Lpsuc%vTD_Rxc_e}GJI27}i^fM*!s4KF$f1A%VEpg3_;^0HZ}?xCI+C5 z4WLa@kl8HoZqYPQaO5VI6k92%YD638TE=Q=+G|wRQv}N)LJX37Fa8& zM(f5Rl*H)8XldFPTPvt0bAh(Qf?ArObw$u-wSt|30fUByqJ{=&s5cX|8XvUO)Aez5JN#?Q8D-s07b|V2B-#r zWx=zLP{$O5^kstLRY5}o+2nZm8g|f1-I7F5!Dwp>+g<|ZLpN`N0ufYkloo@Q=R^0B zfEBo9=4BRVfOa&2;sJ7?0(h)L6S{^rCA9>!3l_A3PD2BSPH-B8n6Ie`UCAE=o^~v% zWB~0Nv4V`Of%2kisX}oksEAC=OU*9@jjbl;WR|5Wq{H?jfrqqHp=*S76jDG7Z9ySW z0^Uaeb|rM_JY-z)HOGGxKmN z040K*jjSj3?A(ORdrP<3Z;3Og{7$qo-V~YP%pto&r?&lAUO%D61>|1 zq6kz%ap~d(pdtz!RZ69KpmCm5(C~U{3exTh4Gpk6;!D6swt!MFc*6-qFe$&JBtI7s zu^JlbsU=0=IS3779R;gX;G>|d_1Tz84qeZfEvBxJ4xC9$hgXo$!XDfq1Fu3YDauLB(x#-qT*oC20Tp$XUN_Q&}ddkVsSQj zL|#w96?A$AXze!_gIi`^iVNga8^~^vV9=oqItt*SZ18-Kf~|sT0T%;ARsl4X1X@j= zmRX{s0G{Y6E{RW1EQp76U_feh6hH+x*MksvG4tTUD5!P5Ng6vJn zFM=Pi0~tgEtu_Y@xg*>`s+~Ftd8y^`AorBzLLC9B$v_*3VB1o15|dM*!@@}E9KTZ` zDGs#FxhOLkyg)I`7o5-_nFou}&<+{0ma<$V`!qB>iyc85wNg_wAf5*eVHSZ8WWn6N z1!JgSg#RSuMt?U z5m>JgSg#RSuaQM8XahcmyVD97a*7y=3m9xv4U8g?u`Y~*hXGRpqwN?1pa+)Zg3mbs zb?U9S7{EJVL4|%*1$bM4YO$sQs2%K@2VUTZPz#RMqSRtYn+?2{QcF`8w9gtWVxS3| zVoZhYqd?i)248ra3W}Sm3Y0x=i6!uis0^%S zl?*-&0yLlvURzj{30b8Jp3u-xg;vU-YNk}v3RENMfW|TM@*!mmVn3-yacVlKO3_Qr z1GR_(!d)2L0$dq9eS8=|OU)QSeP9Ns&|n78GAD*mKW{((a6iz(KtD$xP>&4UCIM|8 z^(+p}1J^65;Jxu+AAl<&N64X9!JuLTry{85K&@O*7Z_5!XemHDpoS)z&~5{$&zuT6 zYbY-tTsFh>fvN=%J02_wT8EF=x(_axi&DWQeL+!bNqll*afuBmZ0$5alPvL?P_-b< z@KX*DT`$nlBH(S0dHIkHkKu`#;1UKr+K>tw_y-@q1JwcAAPG?kPNcHQ&E(FR>OdoPHH4&f>IN-R-OEdb4$LY8BL_Y^S%z>d=aM*@Ni>d7*IrjHPvEh{bt zc*jcte8z(ZXgL7bJs`h>qDn!vsubMUEkLxCz*f3LPJk&(ECQ7S`Du`)M+ns^smVE@ zqfEe>i>*|vO3{v;&;S)3kON*ohZtCKF+e*Z3~A7ADFe94sGwR3Wn`o#f=*CSEoDH- z%}Jmkz{H|TO$P9aT5xwAynz!uQk0*k06ta%bdm;K9=d-*LAAgNT7}uF7J$#Au!R&T z#R|IM6E5Q6Z3c}3sF0?DmO?h9R`-Pr_GN;$(lKagXyihb#OG=%=qqIVrj{f^6oRrI zEOQ_kgrdedH75t0FFcDOntW4pH6Vpc0Vrue3oB5Chc2&C0L>c+r#a`9fSdqP2{Ib8 zj|ovE>gnkhmE`DykBfqAde30c&`1QIY6d<81$Nwth8pCsAJ9RDrI|&brkN&a+y#7k zAOmQBZ3)y=aAOVGT<|FdAY)4rJuLUs5})EEjnd2%9R*N{0opgJs8MX7=UMCswp;@| zI8B0^Q!8Uj)m8pdnPystw2%eQ=!&9drd-2@!zrUx$rUrlx>Bq^GA3 zUq%oQ8b;2~LlS^ihWSMxDX{HePva<=i&Bd<71TiM389TGXfgx!UBT5CCDqz2=Af}Z_$Y>+ zo<4qOKmr16Zv{L(hiYn);(>yqOwiT^VuX-Gzt` z&|rIRVgcA}gHTv;lABmy6b(8sLRBFfWVTT(C{dQ@`+yD!bE+&!^-TnwoC=C4$Y=&A zxM0VpL7W5{>?G)poXp}9u+@s7wN#bhzy-yMfhO#X2k<#qpsi=%2@}xxgL*M6!Ge#8 zgB^1O^-`)rB4|%uUU6D#kwOya6c0U;(kEo`S7K46UIyZfBT%;S0j*&I9SlIld;=9WU9@+dfSVt6bA_7zq ztkn)mv*01@0LYF-&tl)qyi^U;3N0CIYdk0w!#5*mfIXO*0?Lb^Or94HRRtE$OHBmz z2q9vyQMC-v2`Au~!Kwyi3POp3wgQv`YUNbjLKP4G*dn48hYuaGn_hoC%gt%!4lEWJpXZ&d(_=NsR~3{(&Yj5OTSh zd6~J1IpA3w$fS>gjRI&G$|p6C!Lb0eJlGGi(-Sm11lk!3J02DI+S4tnezgRQM< zF#}`+K4{fE>_A)4%z8fPD8Hf-MbI&8swuX%kg-|NIxFx99;kx{ZY0FR2JaZ4BTfZH z`6;EzC7>ay%=|nC4GoZZYEFD^Vpcxr$OUi$Fa$LnFr>g4JU=b1I2CkUkfDK|Y6=5r z_$j_P6|_$PHc1hRq<)P@K3)D5}MvGjpKBpC}5zEecQ~LLMLm zm$7Of<)Eof_+bPvgF%Zi!ABgGz{(`hAx5y%a*#(7K!XgaMMaR_woZAhZ z+(K&WsUl8F0u4}DNt7lT8gSxfpx+|02U{Z zln+|>nFQKGpAX*tU@BL?uEjN;5P_y`cDtC6?nfU+@42teZ+Qx|B|0Nt|%go{*geog_+^MJ}EaM=p( zw}5I6P~ieTNd$C24m41}{T&b=)B@JfC^a?$4HSXSM#_dBB$NU^U0xG9ECMo&0c?o^ z*cQ-%_V5ZWJ0vj))PB>{WY8}yF4E7*Owv!O%t;whXa0|RcIbpa2-K+&P&xpOjzQ!5 zK=~d}no{b`9A*YNW(M6mbC?<87#VzSKxo@5bC?;}85n#nKxo@DbC?+>vM}hLn8VBv z%gEq!1VY>Hn8VC)l$pV23xu}aFo&6;orOVn%^YTinJf&tE9NjWs53D5EP>Fr3!wH* znZwMmor%F`0))2hnZwMG$H?H*0ikVc<}fpCV`A{BfY7!j5OJRZ2yN>#hnc~Efnf=V zW@cdU@qqF{G&2K(t<4-}h6Vz1Zc8Av?Sfg5aGNs=5^ghQLBeecgtnakwXbCsB-|Px zv~A5SNVru%Xxp4wkZ{X@(6%WMai0VTZEG_N5^f+G6mAw!K8OZ|o6amqxPfR;xM@K7 zAQ}{IGP5Az<}(u#ZVodc;bsG&Z6#(x!cAl*B-}Wld=?08du0YB+>XqEgxdiKZM$a% zB;0mDXxl9_AmO%Q1|;0pKxo?qGa%tM2SVG5y>qm<|ayo9U2nvw+aHBGVz^CNLcmZY)qf1BABSGL4zx0W*W{ifPOY zmzfxRmOyCRoN3Gq{VWW+8Pk{oNrrza~>4@oNB~ZFQzV;#UJg+p0`~#IM2>Nc_q`Xj_3Pkoe_+(6$^?Ao0sG z1romuQy}sCXEKv zAn_Xk<%d9M+aLW9e}3tQ#LtI*W`@H|3_folwC#mHW`=W23_fQdwC##Mh&?@h5cM5> z%nXN^7<^hFv~5ZsGs7Kb2A>27ZR^p;%+STmpexb`u}1)^kEah}4+n&{z0m_P_e2lG z+#@{@a}Pjh+XX!kbLT*4+m;@PxdA=F)SW$$c<1Q>$F~m$gtldY+V`Uy67OFiwC#s(NW8y+(6$e{A@P0( zLfhVei2GcD(6$@8A@L5PLGiu@$_LS)cwf*BiFXhUiuXBCK8Oaz`-E;tydUU-gxi)b zNW5==(6&8Yka+Ltg2a0blwSd%Z9Tf6;nu~>(9Ou;V*{aWExI87FoDpv22gb>UCaz! zj0`>s5ZYD-BJU#sp>0K=>NvWX89Esmd{`i~EhzFq_3NKbu(`G?IwAJX=!C@A6bNlQ zp%W5cJrLTqqZ1NeEuE0~YJkwTC7qD?DuB?oIh~OB%IJi|S4t-&z7im`Z4A`DfKEt! z`9Nq}4~TnwTp+ZqMJFV_Odzza0YuzK2SVF&bVA|_M1$gs15Zd-mJ0!ktv_s{YriNWUrgtlGM3Mp?v^id`Tp9N4ph(5~1U|Ry^ zgXq&t3_b-=K8QZe#9(Ux<%8%`Obk9cP(Fx0#l&Fyq6K0;h(5{0;PV8^2hk^)7;M)- z`5^iP6NAqRC?7XU+INV>{_ zs>^7GlvgPb+SZ^65|0W^5OZXjAmx<=gtq{g$Z3P-3?&WEOLKB`p&pVC)<9_6j(SKwXsL(fg9<3W1VY=o z)It(6%P^kZ@J0hlHyFgtnEbhlHyHgtir_hlHy@JtSOtAhaz* zJtSQJ)PZT+A9WD(KGZQYTx4YMc>|$sU(`X&djg?t57a@z1w@0wWe=1OqCw%Zp$-x* zAQ}`dYoL4(4GNb9b&zoBsbgkvV`0#3sAFb$!N9NtM1$1VK=~jVq&}yPnZbgAVF`!^ z*_Q$3gJ_U_M{1cF)Yuqwx70E-a4<9IuBl~aFkoizSplJKm()ViV+Vxq(*mJwQ)-zR z7O^nsI@Ch)l|?Nx!vQ7+9}@^|%L5f>sAXo@$Hd_Crv^;heyD-?A4G%P`=W-K;VmnJ z?t>agJYT3`X4nsEM?h%XH8l`>dTJo{wA4WCX@JnSAy9b-sD1;8J|7(jZ7Ttl|56Rn z|Dqb~4xc9w+V(~@GeZU=gU=NRZF`{_;yw@!a^D#!A4G$~^GG$sy)&vI>1#?gBz;Y& zW@gyS#Ng8dp=~>=nHg@gGU&EI)iprX)l@Sx>;d%~A+&7?RK5TzpHt1uu$zg&Cj&y; zraKS{GUR-K(6JSj%nVOh z8FYOrAmSbnI+mdV5_&|kQ>`2eA9XOuzw{icMO!G(dr=LLkeJy8Pj z-;NT9|F%GA+YKcU|E+=0wkt{?{##N4@!tXnZ9Am|;=c(H+P0?zk}f(*AnBr|1X8{> zKxo?X@$DE!ty`5+n;ehZ4B;a3a^FNtDE`6>dTZNC&j%GVD?kn;5jl>Y!i+ioa= zgxi85W`-@GdJ#g~&M0DLm<{TGL1^0vP<1Uu%nX~E7%pkd;%b}tq(-r#{)v!t|^3+TN#BAcSaOK;x`0B z+XfUu;@1a4+j9|Z_)D^m#Zw*-W? z6@jW_DP(3?&&1%v0HJOF6hPGdfY7#Y3YZzzF){eOfY7#2AmTm`Ahhj~0!TcAXiz*K zfbu~!D4w?zK;juhgW`DulnUNAH0W);-5d+VA^&?HpKra*${svWJBURCYzaI4X8YY z(6#~Dkofk2(6%<&%nVH|47xhm5PKA|nHi=tG5E+pXj_SFW`?Ou3_c^jy$AQqcA?c8CWl3jd$Yo*B{gKAZ zAi=`m^94fNUP*)0gBQ{u?m3VKiKjgf+IB}8#64RewCxJ0x;bf(@R|XkZKtF`!fOJA zwv9-G)L$VGI+i635>Fzj5V|0lnL&|-K{p{8qAmtP$Lb_Q+#!?9%&?S+!AAl@+lnMJ zGb~|Z@DYH}wtJG88I)NVbmt^N{1=l1(dUx{alZ$IwslE@xXS@T+cqRZ((#T2W(EZo z2HlDTh`yWzW`;#f3_ckU+BPKtl3x-av~3JjolgQY!$MH~4WVsa5+L=01BAA1^_=J;qpXj>JiI*9~khWViM388HTAo4yu5Zaa@ftg_*sC^a>rfq-3 zL)`TRLfgKGXJ(iS>YqVq+XoPFpF0rR_Ch=}!yHh14MN+VfQb7XfzY-G;vxBMPdua? z*%1#ZN47v{+ZFN5496H5e3n3H+XWDPK64_@~4%Gw87}=*Gk`GdQv^_(VWx zTc0>cKK6)XW|+mq;Nt?JZ7t#;`Pc+P+pdX)q>CA`kof3{WoDSk#Ng8bp>11YA>~p7 zgto1Lsw;?vq{AEtZJQAbiSHB$ZJPj97ZMA}w*e5^)(0Z*;{l;j}51PmL6Akv4?UZO{P}J%6L^CsR zGcfpcKxo^XXl90=pmZM$@n=LZWZWhMLfZxeL(-EEgtqm7sDAypI8d zw$*{ElL>~5+ekoYTM>x7j{t2=&Gc!zNV(>Wt zp>6j-#C>)^XxkWnW`+r%avnn4viLJI^fNK|9PwjjP+?=xZGqAme#{KtSQ&CsAatyU zA4HuCgtlGd%gpeAl|femN^kICW-wxA(4FDK%;3Vzp!>ud!aw5;;m3GG;xodVnV}Cf zP6459J-i|PeisOBYvaw#aGjMwSHYW^L6wa`_m3Au-w!W{zAq5k_JtQj-xCOJd&di+ zZ;uy5-yAPyhNr9yx>LNE8D6k5=ypK)6;QeWDxL!6+dyd@C@lk}d7$=lcri2dGBNnD zKxo?^o)G)qcrr7Tg8b{r%rKdmLHCF!#NG{_koMvVD1U(`#2r(h{0vWKh8wI5x+b2? z3><6>x(1$*_*d|Rw9jN9w5^0EB>qJpw5@yT%RT?iCQ)b_rD73^!(mHcs5Zbl_YHp1y#61~MeK8RAJ`oVwHUy&HCjdg*YC!dgfb3^s z&=qinre9ZPhE^s99}Wm@`^NG%tTw*BA&sW0BRK=i$EVPW)*#}^RV_Kq{eA2%Sh?G$H7 zdYJ&BV_Tdd`3XdW@>2tp528W&sl*wQpFlJyKNUdvAR3gPQk)_A>4Ot90~-s2?iDD# z#)+As5!9c7(6&pQApQLSCuW8iQ2QN9Z*YW^-%A`J?pgq$V`Chd8M;^)bR!&@85)=v zd_o|!?FI*kISCHT4E3P!g3z`)4$KVqSQ&Ib*hA!V>>=_Q5Zczl9wPt84kEw9hMB>d znL&4hHH2Pb&CGD0l|i=$O50d6Gw6fbn-&oH9t&oMyQ~bl1{RR`P_STTsAFRAk%7>* z5*Cp75P{IP92U$BwV-kuLfbMx#C`slgVou7FlT0{0nOJzXxkSMai1p;+V+AuB>p#; zL&9YZgpSQIhlFzgl-7aL8_b~LXa-Tg07A#+m_f$5Gt8J7szLn(2yGi+21(}*W{`64 zk0~U5|1gEL3%{5`+Cv{8wCx*Hh`;ZcGBZ>$G5Fko(6(1h!T#~N0HJNqK-KLrWoD=Z z^yTp{4p#s#uh0wNhAmTnVAhd0TDa2h4rjYW^#uQTi89@0u5ZYG2 zl$qf*D}(MI6J~}PEDX9wOd#dz7AU<0N_UtrGdyQy(6upPX7~fD*P*nC38Wt2F=1x# z2KASWnHi2UGWdLf(6%3pA>(iljF}nAnHYTTKxo@5#*p~AU*o3W+(-XA3$i^79)uN8jK*}Qey-OmkJ|@|4JaVZ2?q12P&Uo1PQkk z2yN?O1o1zJ2KmRv2;zSb4f4MQln9SoTnNd)!r_Afq`cl>05JzdgUne2<%4LDISZirKs3mlIZ!@` z2AMMfYEFUyq#r0_07(x#29W&20ikVK3?S(MG>HLP-}Ofyk`8`AXxlIP5cv=KkaY4! zACeAUKxo?|`jGUrLLcG}5Dj*ZKE(ZV^qCnz?w?Sko4f94@nOeP`(L-wv~aZ!_1Hd8rO!p=~9g;ygOc z42ht2B80a6qYd%T2W@7C1W-K=p=}>P#jj{HGsJ`X4G`M)2vmFzl-{7t%n--K;Ijro z+b)2LPtj&(h-G5%nE;_}TcF|<+RO|wObk9H5ZX2aDxLtPL$sM0qCw;D5ZcxSDsBU% zO`x=fHZwyM$bS&pRst$60Hs;9nHeHMc;vHJd3}H+RJ}nU1wgM_%0Hss3m>EKu z7<>{Sv~37f+y_cKXfZQ{fXYn>ZEFA(*MQOrTFeZ=p!OPswiVH0W(Wd}FG6Tr7O1*E zn#>G=pmYnNZNF$j%J~nP%nSjbc!ton7c?RD!~soa1}`QCpFI%Tc84aUp4bARZ5L=l z%9#dDNI6%d2`T3)G$G|&352%Q(PU=$!OEb^q6r!AV1UrEHX0Cd1`UY#A9XMt8=(#n zmx1teBp`I`0yT)cCa5tp_=EC4gtqNagSe{&LfbZ|LHt#t#?0Wy#Nbl_p>0c``cu@H z8GJ$E4WVsgAo_eFAhc}=RDXaPGlLHkgO3k{wzYwZTc|NJc!TDjA+)Ul)LaEMNO;LW zXj=)0c|IZ#+ExInjzNu?!4otNstTrUf2cy-{{=$Z9#Lgx2xMW#ORNmKDvA*IDnMvk5k+Q(00xF7AR6Qk0Vp3tyD~A@ zGJy26FzEhJfUI)>(V+VE3zQF{LG|kg1!e|bHU`}*3d{`rYz(?b6qp$}*%)*;K=~~S zko?e~0ExdE1!e{pCI+7h2yGjqz|0`a#-Qt=08Z~YE)Y7_KmpS3)=_|jtAYYEgDEIq zLugwG1xUDxKxkV5s5%w}W(H?axdx$a|Hwns{eaN6SL7k>+zSvo_JBMysLQ6iK%SXF zhK)hDN1mC%2{b+pp>0bb>T(JobZm+|#61!6%nXj8dK5z220+aB@qy5`9kLL0HL}bM z4j}(RXxkE5hs?fA>r5{4w0{c z(6J@r%nU3n47v3Qgg|IpA2DVI7SO&02;av8$_LRlOboUTVvusjMhp@k24awMMh8OMYKTGN zR|P`bDu^+I^L>Q~GeaFSgHH*Bwv7;BX86U*kP`x-V|_%J8Gf@eZNCUZ z(%lDPW`e zDNs53wgLQ*^yCAfZ9Vvz86?;kbS?Oq z85BVA!_Ukh#Kxejzz>=K;Ngdi2fg8gj2~Tq(tG%r8NPt}cYMqYl57mR3-}=8@pJf? z83frFbUXMU;gbWUBlsZU5x~dH@DsF-iw`osWWxt3r%d=D?GFwculW zkpAxx9%cp;P`?dA+fLzOX0Tyl(Cy)Y#AgK$GlMax-vXg+6L=uz#6W1<03L`vJ`g(A zf(J6LuffC2u#16V35W*e6BQ^QM1%5)3=gE=F2VyTmpGvOAKVcB8*YgF11Nt7H^jXw zxS1IYLG45cZR^1enXh$$(6%g4eGE{2U$`LV+~8tnP-bJ$je+tbxFGiUK=}qx`5l}P z^;B*MnbV9mmy%frUZU;rB5fY7!qQ1K6} zkapi22yJ_T6|(;03@gOFAR6SJ6Hq>g2DxVolnAk_#Ng8dp=~?9LDaQCXxj#; zx{_~93_76kSO{&K1CjU1fY7!HP;~(ib9{Utw5(F!26ZO&(ixfu}JHU+9K z z<|D-36A;>#;Ug16BnyM?i4PEZ%?Bp%I<6HE+SUg``*=WTTZIoy;Qc@s-b2)#fzY-) z-ZO#Mfo*{Bebzu|+Xe3-?wIkOiGiPi!DkADww>^viGi1a!KVj8+qOW}mAq$S&;+Fm z2yL4Kk@v}f(6%X1brJ8G7&JiR4G`Kk03z?>1EFn~yk%l=VPWuD0HJMt-ZFvrubaGO zVo(RISA@{E3U8S}TmE!qAnJT1AhazDg!W;8(6&e3Ffnj2Ff0MlAaf5u`5@Ybg~8V6 z4J2F+yn=+w9tdr_;}yjJD_$`%sDavF5ZZRZD@gjA1EFmLUP1JGK-Js4Vq#DQ%|AeB zTN8*n9|H(&tMC$HuE01rhv1b8hp6j-$osTFXxj#eyiW~;w%zfJ30&S!c?JpRo@Y!9 z5sVBz9T3_!2P(hgDa5=rPnj52F*5k9fY7!}o{3j4P_Q7L_IX50NF{psn`9Nsf3y&e@ zoPp4`YoO|uJci`k1rXYH&SOY^oB^S2OCB*Xgt9Q`W;|kI5MW`@-SLnKd``rchfLu8 z>l+?2F(`xPPaw4Il7~#-b0ro)XxljtA?}&*kcmMFR1QOE+m442_q0H0+XW9G<$uXN zCWbH;23?7J5PdxNm>4!OGWc*nXj_(h5Pb{~+V;&|NH`YUWdiRj3b@Mz-q+&;p<`X{ zGBGGJG3c5=_&Ej;I#%E=6L|j@hz7Nbc%Xa`4QlUj+=cj)A?h{W1t``vNNe1S9H>1r?l3V(f!2{hXj_XrObn7t z47zJ>L+F4TObimBc>)M+YjcB%L7a)f#{xpzez*<^_b1nx7{oy1=MdWV&UJ{pZa`?; z6IUSNUUCMaKI04%gD7Y`4MN){oPns1fzY-kr=jXjGcmL?F!-cEXxoI-P<0U6*5ou3 zg9xZRgwVD+r2{>^L`N8cFQRy@cyO^5ZZRZDJF*5tPDAGAav}EQxJ0}K+N;$fzY-Ury%L705Y3WdffY1EN9sbp@0UqCxp}&QT`txiKIb)IXR3<%4KY z|Dfk66ZqVilA}xvDhv!uKr~2Q2$T<^LHqzHA4G%nxg3R*a}GzD7Gcj<3##JG-?Uchz;BzA;Kxo^J!%X0HdjW?b_JU}z zJy5>EVJ7f=h7ObuqCxhm9ERAt=MW^GHymPO-~yFD5ZZRdAxQi!fzY-S4lyx=GBfz} zKxo^VLre?{7#Nm-XpndXln;FObi^L_6~%$U9%sO zzL)HWr0)d~+I9j|yaU4bX@StT9#C-?2;av6LfcN*2QjB-AHF3WTr zpE(fPHe?s1JoDKFX@7!f(7tF7C?7-{Ff-VS>|z3s+wR!O1RiGx(V+CV1O-C#*)?k+FWiAw!N_i zlD@7$Xxk$Y+UEd-w%xJ@lHNcxD7|ff@G z0|_q&sD2O)GS3Fe2hkw&450c!G{`(1C?7zj1U<9q_fzY;~ z&6uF`*#4}7#MhHm5clj@1#w5uDu_EuRzcj6unOW15Djui43rO|LGB1x1#t(62D!rr z$_LRP`yEz6+@-Jz;tm-IZOgF=l5SWawC$dikaBXzN=UqKSjoh|04hfzw5`iZh&ydo zGJ((UGFiz4J~zeyLfi7JgtX^C^nXzQ1j^@F$;9xVk-_%K3Wz+2{>RAR^8m^R(f=43 zY*(y+^z&_2K`XZQHSwi6MZ6!KVd6+tw_F)?Z5@?(=}qu`){`{^wcB1U~PBWho?nmMnpU zf6o$#dkj0SktN;jY>$4bAKX^cBTNkK0i^Y)fHWLVKYXFh=(Sgvm8c=l- ziy`A}A`seE03z?h1EFm>pz1)Ixn6!0HJMp7DCER4hU`A zvjAdV#{wpXuZ#>nEfCr^X92{#2&jC>0w#tpj0`>j5ZcxTDz5>RS6RTs@R^apM*%|H z{+SQa{{uqX-kA?^&xQF+3~v}2e9k~<+Y|F4?l}UXZTCRcZJ5u*@QIPZXAOk5T>+8z zSpuPL7eLibna{-Vk&(e?0))2hfyn!GKxo?*sJfE*Obj1D`vM@eZ4N}9&Mi}!7@jjS z_-ugCwmne!4hU@Ij&lnked?2)~$5e>FT_Cir4OE@MR3?U}pmB8wZL0y1 z_fdh+wjZWI>Z1o!m>8ZgGWgtq(6&paK-{xn3KPR)Mh2fb5Zbn73dFq)5ZX3o3dG+t zCPUOunasrS2$aqsv~9&?i24!;ZJRI|GVkFq8Pa}JnGErd$YgMP#YX@_+wx3?_=f{R z+pIj(A|SM_ z1=JlN8ssh$C?7^#TSIOJuwkd4o;cK z#2~=HumnWUVP)`{0Of<|Ijjt}1yFT1P;n3qQfC3>gJ_UCiHS@Mw-_0GL?E=Sz(ghn z(0k|wC$OG zNIiCSB7!h10^76#oPeGq?s>0@HJ z2WmG!XxkTkko0(`kBQ+f=p1ASZF{8;k{&NWXxlSTbqD&G8167K`0RnuwmTs5K3gEP z?UX(yhPTWNx($60e}ia{ziXg;5DoHoK_4WXKs3nTIZ!@`2KhUr58_W7DE*@s5)Ny6 zA?}^i%fxV-k-=vMgtnd13vurR2yL4IRqxUZ2{(schEK>8=!g} zLff9`hSX;z-H?7^0F>70hWJaNn~C8%XnqAk+e&mp{3QaRZF#zx7_NcN(S*{V&Ft40 z8En^dF@e`Pfaoir`5q{LMHdsp6-EZzIb9Hcf@qNZ3@9H&gXDX3io7?yx&kbDP} z528WxHC>Q$21JA8E1-N34U*4+*yED{p>18dm>8}yGWa+^Xj_>sCh&S95Dn5V0p){e zkbaIX$h-xJ2FbHP`5+o3|D}_OL4$!|35W*Ce}M8qG)VqIClhG@_!1BelD`AxgJ_Wa znNG;K4u}THpMdf~G)R6%CnWqpG)R65ln^o!Vg4)fb>5AR1&}KqC|Qd=iUBNP8=zfeE~BU8Vuj4qH+Wp^wx-m(-Xxkk%koMn}8YYJGp!O?-wp~yI(LbYxiQxhx zgU=KQZ9Aa`qQ3`1+jcjx0p_D(g# z+#3+u_DVG*U0|bed5O@qbD+#QzBp+BT#bQV;l4GclZFWbpBT(6$y(`%NIUtx7c$!&y+j5JKC^ zR72ABi7H6CUIL|Cs+bsT7#Nm-XpnmvpnMPwa*s_Vr2no{3F+UfR5F3K!ulvcXj_>| zNP8W$SspZ={igyfZ+oKxk}j`QK+@%f3MPg#pn3{I+n%U^g!hgLCWh0D3_e>RwC#op zNO-S-(6%coAmP2Ff{Ec2BZJQZ2yHu|0utUm5Zbn*f{EcIBZE%`lrDkLwi!_UDHTi% zCqVr$2yGit!NhQ!k-;YfLfg7PXded%ZEI1%#IT2v!N&wb+bTe49~lU3D^kJ4a0t}D zhtRe>Q2+cXX9Ax;^#elNekq6e=L3YceNoQDZ~)ZKhSE16wC#yO-J>5DiKf9_5gBnLs(DJ;hTFX=i~B832!4mVw1>ACy7j z`9c{J!(mYTLulI*Wsq<=0-703Gw4>7FoD+N`jkLu+kz4%&^{cW90+Zj0ilLHZUHL&672`%Ec@gijAdolggZwrzl_gVH`V z#gOo+fXFWa(IE3npnMPwGCu*z2hkw;7$_e^gX9CC=0a&7A1EJ6+bR@8(&v>TNcz4| z1WDg#ikKMoGBWs_fY7!FiXiE74}`YeQ3NUXwm@jxo+5BQ_UR~sZ^KZMy^_@3R0x+s=Win^3^Su#=I& zrw2mYc0lBPS|GG-15{l}0TaUx(D*5Yw#|Xa`(!|9TZ4Sadc!w)5LzIQiNTST!G{Mz z+rG$!^b0^V$p25Ed=L%t|CwASh9m}tB_JA9&YyttK{TkGZ^&h0_{hSb8v)e^qCw^a zK=~jVWR6EJI2?UkAhazDR31cwJNgo5G^Lfh`i zgrwV&OeTg9Q20V<+YG4ql?+HYUVzZHYce421koV(tbp=CG{`+OG9dO(fzYun8IW)V z(V%c`fbu~!C|p@Gm>9M*GWdWFli1G4U^^q7iD4V4Jqw|2JJKQPt|lEa|4{*Kg)(5K2B^^BP;o|_IZEYa(J{Az#RspI`A{{b6 zBLbmq1t9W1JP_K}C5?$88noURba(|bgYJ|RNPBfc3KK&+C|yHn+lmzEcrAps^#C1e z!OWl=0XoEjnL+nT5)*?4Bf}C94GPx_P(FwTg=;_(6T<@rh9w{xB<}$_+=7`w_d_BR z!vzM0B_J9k{szhi(I9G`RjLH?Nn<%4LD ze>&nJ?Mx62O7|^LK8OaT`-*r-|0X7$iQy+RgRW0JWF446JjDMx@k|U`7#VytAhfMQ zJjDMp5ZYEG9+I8}Aha#$kP^_nXdoKoohW2 z6AK>q@QHxXwgIt_@eY$%NICH!2GVcZ1EpJHAnQbQVj%O%AR1)829yt?LFV(sFfnWf z&2vL&Tb3Azc^jf3=Ji17fM`g1a*2kl+jW4@wl>j_^ke~{ZB?Qn`fZ{h^}9wCq<{S; z5<(w|gqX7s9y!4Z8tVHCLTbBrk`3?};)&{ChCxVG#4k$h$w502eL+pJ6p>1D;GlAF1UkHbUlTJ8fojmAJ zmrP~`-6vs?a{U2>w!IMs@z0qsCWdv43_d3ywC#~Fh`9$KwCx_Kx(#7W3~NF2qY&D5 z1w`Iw352#?097|7jEP|lXx<7!+x9@@eL5htZ3|RgNf;!23Lvy?4n*E3147%TK-I;B zLBb~jLfeKw6qJAhfLnMBYaPLfZ;J)v<&^{0llQGZ5N# z4OIVvV90)oIS|@*21K9F6bNlQ0jjPg7_y(D0Ycl>K;(TYAhc}>R9#9iB)k(Kv~3JT z-X{V=+lD~Zc?3hk+XX_~IzZ%oY#_9)MKB~BWr88$b0Y{6o>zjH7*;Sc_*{U{wkLuh z;dul?+a3slgv*v7NIY$T(6(!WAmOqCLfg&>g0v531VQXc34(;b4phHF5G4F%AhfLn zM4yicgtircs$&U)gg@wTq-Bf@wtoU4_WXd*wqF977?MEcKp-UiA3$i^1A$O?214Bl zp>5Yd^!coS(6&8+5cgRGLfpp@2&unW0wLi6I(%s{y(6$ExAm*-t(h&g=^GyOE?lgeVwlYxj1Ok{CmM}8-@IYu=4v0BEED+k3 z0jlnUKNG`Z&^#)Hwte9bvG)mtw!PsG*>7_NLfc+|i2Iy@(6$HsA?arigtpxQ5%<{w zp=~$#L;SbGACi8SKxo?q5P6?D5ZZQvKNG`3P`Lr2Z95?1J}nU1wgGBRi9aNq3Lvy? z4n*E3147%T_(Q_U#UGLm8~h;Q6yXPPhmRiJCypIBewv~aZ6Y+!iO8`RK@<8N$I3Tnw3sl_?Ux>TEKxo?!z7TugKxo?+z7TiU z_(I(4;tO%F1w_4%352#afT;J;fzY-RP<=d5eQ$gq>FtFNq`maShlybxX#EF-w!Ps4 zG53NG6T@6a2A?w!+V+GG#63qKwCw??x(z;%a99JOZC60#eU?CI+XYZ{Q+${hW`pW8 z2yNQ~k@x9<(6%j5brn8L46_&+d`cj+Z2?5yCkH~?W>@CcL-qCxG#4IWGkhgcYNCwM^21JNM!TA=31K*d2cs2wW-5w~UW zfVA`GxI^3<;SRA^#~tF%8*UK)pKxPhm;vhVLTK9qZcGf*LG$+z+I9z2-3B)%22%zG zpEVHLc7+=xoR&an+Zj-G9d1kvCJYQdEfCta0V3~H1EFmd+?W`qf##JVw5^C6B)s0Z zLi`7!LH>K-3JI?}u1pLESr~NpK;=O+NPYuUz6UA}qCx)efQZ{_xI+B<#|1)vfzY-e zTp-~MqCw&P2FeG~pzyxo0%EMGSMEnhewmskoNe>#1ko~+0 zj*$JVG7#DpbjTOzUWW?~kaW1g0pf2E4f6LIC?7d;_o>S+IEdS6T=ixdl5q0 zF0hA$Uxhuy91smMC&wP5FT)-Z-yTqT5Dk*Ifyzrj#X&U4J`sqx?H4;p_`R@$gx?bg zZTr9u5`K3ewCxN#CWc9%@e>Gb+hGTB2Z)}_%HY!i<%8(CtPHjRc98v_J`g%q1VZNs zKw;};A^y{`h3wzefY7!owh;d*KxkVTs5${#NV&!Xp=~)J@;)pO z+7@(J80dcUFE&gJ6F}>IAhhip8;E%?AhhitYe@Q-U=3N%+XJCvTdbk(hSCvG+QS-B zUOGVe7S>D*Ygia`Wvn6TPQV&G->?KkgW{D3$_LS)_++tWVz>fYk7UKfz|P8``^Jii zfgf~EkrhP$5-2|f%8#*PV&GzB&~<^*I#x^!Ml1}vEKvC?mXQ3s!4jf>jU}WU?}74j zAhd0W1;jr$%pvMi%pv~ffzn^hAob`65DjW4L1^0tW{`1)I}qB|#SCJP1BA9!fY3fN z5Zd;QDa70xrV#V4fM`&=7(&|~F@>0S07Bd9m_p3cfY7!)5ZZ^ul!>8$l|lE12@}H- z76#o5CJ_D+D1VCy6GJa(J{&^Zt}tO@=mD*pfY7!rCJ=LLOqdwdLFe>C`8g&`4A(&G znoS_#AOV%I)1Z>T@8pZGs_0eGG)Q^)Q5l+Y=FoVy8t5ZGY3N3&VZ`x(1nb{wm@jx28g^*4TQF>fT}Cdg^a`IKxo?x zh`dh2roKr~3c1j+}|Ao&O_$T%#B2FVA24)0)Q(B;sAjNgK2kT?sJ528W(mS{r8XF)Vb zegTvZqCxTHDYwCw^7NIcDf z(6%$6>N+$a@zesLZ5tr+J~a^9HbsMpp_!3EH$a1lp%t_)8$#PEXh8f0qFX@iEht|` zgNdPqk-_$dIz-w5^URBwRHhw5@9 zi2GQSA@WOl0Wr@5LfdLU^|MGYG4wGr=X3cLfj8JgkdiWgYE|rNIUh62&BCSqCx5M1e6b=LFsaj2&7%R147%T zh%hniV`0#BfvN-1Abk!{K8ObCGl8i0F@VsvFN7ifydew;_bU+E_JS}ZoX$XKTOVO2 zhCtB$AHtAuw}8;LEKu<;LJ;u}5ZZQu029Mn76#oVypVc5ffpig!V8JNCp-{)uke89 zOMEUsXxlS95PMHRXxkM$5dA4U5d9WB5dBxUA>tFbA>t|A5OD!+NIwijgZg1SP(FwT z^}|@WA^nXfT#)bu(V%d80Of;dP&i%Tf`sn{2yNTL#l-L#)Q;wY*yjRO528W(9iV&= z4bpGG1(}c4fzYukTo8AGXpp-;a6-(vzzJ~&hz6N+2FeG~AanL`Ld@9#p<`EYLd*ft zAaj;L`5+qPzXm8DM1$mOpnMPwl9%CRVgRMHKO7KyK{UwTA5cDs2HE?D1LFS|5Zcy) z0}}r-91wT!U<1>(F>H|Vv|)po2ckjdSwQ(98f2ah8^k;f2yJ_U72=K+tPp)58l-Ot zlnBW2ckjx1fYBn4bsN~QSSrVL=WQcVS%K#H7t;Hz5+tq zE@6SBw*?T|b`DhC1Qtj?rw2mYc0lBPS|GG-15{lF3#5D~fzY-EERgac2SVGXK-ERC zK+1;@2yGhxk@xX|(6%Zpkp7Jf3#42SVS$v(KbXPc?DK{hQcr>g{NIrPO1kv||iHU)il|gq46Qumv0HJL;m>~8nV1$%EHjGRRJfL9g8P`(F*wiRH2n8(2Yarc}5jNo-3FCet-o&SuW^dj2zl&nfEo&j>!(uI4`@Lp^9+C4{yu`OgSG*RB9U+d4qZ_p$lU$gqut zL09EJBlujgJ^vUPLRc7dSNwyxqXbGP{9|M|&%&T<@Q;z<91DZ)pT7|L43y6J%Lr~q z-1r00cLhS*s{DbtZ^Lg!@OgJGzZn@Gf!fEvpyIz68T=R+d}cuDhF^>f{tOI0H4xgi z0xDhtr3)am?TVie^QQcSm=o{=LZA2!5&!ZH5)N;^F*4LKGWfiJ(6&#$LBinygtpcA z2J!ctuMmBpO`V{1IDfu?{b4Kfg%RBUfAAS%e$Hozx(A;i=HK|l$WRL!Z-CIY7d|mE z)PTlsA++t1PmBy4tPHv{pmfV8Mh0$H2HlWPjF5Wa6WAUf3kYp112vcD6C?OsFb)W9 z%kl~0ZqO!A(7e@)kBs1c^?{EN_cwfmm=o|3;ywi^Uj{0cEK*Q}hBY57q;yEOK z3!XEA$45e*L)_`{9FqS)G${YMK=~jVl>cm?`V^isg4aKBJZA*&y93c6^(;_6hz6EvBY3=J%`--DIW*@PBX}I314@86XO?bixUdPn~p<`R1@*o=I?}jIg;Pq-C8eG3Z`87`%LFe+= zsyu;&0|(T676@&7{q$X$WRU%H-^x*GPfc2OF(GbH@6__?%aZ?y8)qXuiS#Dy8xkW*W6-cFa?db-C|_W zU|`TKxdrjR!7Ye8bs)4YXp<%=Kdre5QTO8pMBSDf5Oo_Mv~9}`NH|&CfY`5dgOQ;O zw9W%U+p64v*slPgZDnpi%v*7tkwKD`K{wz!q@MA)4$*IOoe{jB$O1y!np}tIH-ON# zI@cM&=Ur)BX9S;jr2?UCC9X4q&&?Bo(6$`c85v3$8GKkEv@K|}8#@Do&!1~x^K3s{ zV`L}+jq^ch+ZPaVpC=I7cF8qH@IJ-~*BBW<>xw`$IKH6#o@?NAZCi7V5qxeIhz6y@ z3Md~$gW7pH*BHU)W_`KJ2tL>J!&OG`xu#E`{09))HsvZK_&jM44KgPI$_LRPbM9P( zq}K~4AauhKNPO5Ffy9Regtp~40*Q|kJHg_%dv-$kJ0SccJ0SXMAbcO4tq^gItq^lr zp!|$2U~!)m2yOddGo)TU0i`!=hSaNTAhhiYsQ3~ny#PYnmTZEQ8wr~r<>8f$5OXg; zXxpBR5chaM_&zQW+E!vC#NAUiFoMq^?b*NxKF72JLfg7P#cd#b9}5U=E3<(Sd{6a( z^$`0&i<3b2C!bjdNnd-`LDJU_2yMG%9XLJsY=F?VYt}*1*NSzJ^tA*++s;@ANncYS zv~9;aM)3Gr3xu|9fav$BfzY-o>mca{M1#^z0+bJ;LHRsn9VFd=Xi$6yK=~jV6yGlE zAn8V89V7Uh$RBGN8HzynIYMaLCuXov{WQe-PSs0@S>g zHH_f%fg2#SZ4Jaep9%5}^W@N}=Wbl~*p>2Cs zGlK8Y>wwU<4l5bK=V{tN=vaf5kaPi}LE)_f<%4KYcq^=gqze!YN*6LvK8OaT3xSo8 zbn#^c#9bd&FfwF;$}tFSdu0V9_#T%ND;UA|w|J~z1m7#}0#)y@f{`JUk-^6XLfaaw zfVfWwLdX7D&d4CZ#-Mv=IV2rjSq_Px6U!Mv`*wYfKxo?o%OT;u2SVHKSkB1sotZ&* z#d2```YeIawh7A_86+7Pd}1K9ZNzd&dIZrR|A#>NAR6R#&>=y#LGwLfh&rX9V9z0ir?rG@yJC4brEwoRNVCwBHl77zor~SjGt2$E*8d z86)_91`rJj?#t1&&SY;U_g9vCm3qsp| zS;`2$NB#qZj(xI}k>MF=|LRgk24MyUpBoU`_QX;~@ck7wOTqEB1Vn@Ot6D($AUcDQ z!8T_JBlz6R3e0-5P2UD2yJVy2-5y|vJgT)SP1p!LPqd;x;GXwg3qzI0-u>cY-OCYrE45+%E1&rWzBOMUhwgn>Z(*U7uLl!WC&$FI0 zA7bv5`4Dp_Kxo^Z`4DqEAhc}_R9(S*h`Bis+BO3s?~?+dZ7t?Q%x##*$lwpUpK2Z? zUxmzL1fORe0HJM7<}rfLyB3)Tsh0%iLEHgaR0TfwZZ5dqvHdX@;*Kv6+V;a-NIHHq z7gFE6fY7#g=0fV58xY!d&0I)1y8=STmds^jhytY(2yL4%7g8R8XwbTX7$_e^gVq&j z%w+_hTde}2V-@B?+EqMrA@vD}2BmKfC?7M%?RG7 zV*{aWO`zfzW-)^2Ne|3oWQYW`D|z%mPx4nT|5B0%TP z&4i?b3o{uRfc{ z%!Iht2SVGrK*g`jU}QMQ%HVSWLff900V%&$%wS}21eHG!+IGeaM)10k2~hbGDD5$W zks*kY!N&zc+d9l(WC#S+>k!)3Vg@5a0BGMbgtj%9!3e&uR0l%aia^cfftvSbI>i1v zPhqxhm5k{u6=n-%NwJ^U(h-u2yMG$8pON>5ZZPQ zXwey{9R{IoE1>#HrZF;jgYp@Kw#}FZad!%Ywhe)*(}B`FP{{8@=ZQo2~ zWbgou|3PTmCsP?2+(F}75Zd<6R7M6jP&*bv+g_Q<$lwZE{{f+G&rD@xaA9QdIRT+< zk4%O5;{b%VT{9Kp{}odi8Js}r07BbNfQt7_g`|%T2yHuO3PgR!6h;OIMh2f22yJ_2 zGPr%S1Vn@K{g%lPbu%V2GT4LGM?q-Y2~c$)8dM$>OoohC#Y~3upM0RS4V2b_(lSt* z2TBJ_Vq}=c!k}vdr6r*Bmx+*a>cm7ydAegFBZD1iKMI7l-7pbSp00t=wj~oG{XPyT zeP9Aa-;YpY3kn(T=gpQrk&j?-*)X~ofUJq2$&&Xf}8jpw2 zwgvr+43?n$2cc~fAo_A*Aav}MK1K!$Mh4x8K1jL50_A_`h47~|LgZ_pv_=CXgE=FE zj|zmgm1$sPFk@u!k$}*)E9$}Zfo%zt4uH}MP$7dD#7}E zdLXoINF^j4KB$1mdO7gRvRf0RSSx0FM~H$Z6HmU4)^4wTOWRd=EcqV5QUww+N1 zQTL{V5j+ogr-Tu_4t7Tgq#XdFLG}3-C?7hmQf;BhCP1rXX+qXaVU$WsC_|3xvF zw%t(#83!pTg76mISiO%y7DRkYCPcg-6C$1ip=}*9A@VOWz~Z(iG9c<&Abg(&2yGjZ z0a3Ri4H927(jf6wk_L${5Dkj20w^CugW@Y84H9255Zd-hDkQ#6q=N19SpuPLOHv^5 zWsm|ExBZg{$ptab5cNl5AmR-% z5b=;0sCX2_KU<<8{+SR3@ehaw`KJfU2hkw^G(ZL+n3c1rcwtf`~_0LB!u!Lc~{CLc}X9A>txX@e39Z@g)`zaS3yX zKRC=G{&->r@dt`!9$??ClW;i~B@~L+t$^1`%H) z1`%%%gNRE&#jl7$#8-$y#5;r`=_ErK;!Y3^a%T#Z528Wtj1Y#nGXz50st7~e$sr6e z?~M?|ohyXEeA^%V5O==dfw*T04_Mr%fCpkP2UPqBH$;2}H$>ck8>0RV7exF37essx z2gIE<91wScXplQApnMPwa%T<)#GM%s+SY;t;!YV3h@{JB%p-wlkh}qu528WxD(sBl zdrd(!NL~TT2hkvT5q3uKy{I4>BrgEvgJ_UE3p->y0Yro38K8U+4U+%C#>i00%%J;) zjS+lbCx{05;{%irqCx(6!3Oashz7|&f$~8#Nd68R#GfDLM1$n#K=~jVB;Uct2tE%ggALN2Pho@fVQ#4n%|0oq_T}H0U0hEi8=Sdw4cL zXxj!BM(}+@AR3fT3ZQ%t4dUlO`5+pUZbDcX89?_6-C>4=_XTD~@O@clAhhiXW=MD+ zfzY-Gm>C(QSQvDtFf%fkfc7;)XxkoUMh0U>2A>WHZJWW&2);Kffte9}Z&nP1wsm1< zWH17)ABWJkHq49+hKvk877*H21geh*qTYuCLfd{|Vq`D?&D%g|+ZRlX4EmsT{Seyr z2ouD zapwUDZM%Yz5p0<%Ffu5D#$6z^Z39$a1w_41352$dVPIrXU}W%#fY7!f42%r&Aa_G( zTOFuA6^MEt1qf}+!NABM2U?c^p=}u$7#U!22k zXJC*4jhjGd+YSF27^Fe&hS0VhP<;&$^*%Ka+BW4s1A`Q3oC8AJ#{6eskOa9KLfcwE z^%+3a`{+PuTao_^3=*LIJrLTK=RX63IOzNm2yOf1AH?p9v7!w&E`X10N%UPYHy!E%?j8zzcFWgtqm8>T`jp_i=#Gwi!oK-BxpfzY-se;7bb44(!FZCmq)0aQi%R6uCk5U4&Mhv5ZX2YsxJbf-X{b?+uHnQ0A(E?3kYp%@|%I- zKLdl00fe^Yf$C#{sP_R~qV<=F!S=;328MqO3_edFwC#gm3=Drk^%I1)-SG?J&J7?w z6NAqh2yHv%7X!l|1_qxA5Zboq7X!#hpAHCZn*!Ar15xi20ikUjelaloVqoyGfzY-V zzZe*PGBEg3< z4_hF#?VO(s4Br?Sd}css+bKU87`}qs4WVrdp!zZ(>U~lmw5`ui28J&T3_czZ+ScVK z1H)$q1|J6qZ7T!SCjwFLBLJaofBaxz_{6~A^94fNe)z$_@Db#02yJ`j2gIF6en8xL z07BcY_`$&Nfq}ti352#?@PmQjJp+T!90+Y&0o7LkQSXxjp>0EcFfhDhVDJfm(6&B5 z7#QAy+zp{^RiOH0AnJW2AhazgFyDaIe|=|Qc*DS8`{O$U!)uVcA++t4?+|yM`3`aC z2?%Yw;X4DvE6~1p2yMIKI|IW@kh>wYZ39$a1w_41352$d`OW}p$NNM;XxotQ3=Gdf z?uO8|I#7Ko5cNI^5ZadGI|IWr1_mD%2yF|B^rs+qe`8>H%D`ZI;~T`C7rsHp!ymh>V0Y;v~9{a28Krr3_b}E+BW7J1H(fG z2A>EBZEFJ6rvp*%qXD691->zW&SUf8fzY-b-xwI~gWL_FZJ&IFxbx0eh&yjUXxjr{ z85r&{F!=0&(6&3iGBDg_VDQ-jp=~EX^>skh`?Nr4+nlcq40jk9d@>-kZOT^$hT9-_ zLugwYs6G>jdLIJ_Z7cDWf#DVdgO3P=wiWowz;Kg+!G{Mz+rIe%ap#jS5O+R+(6%SO zFfiO;VDLEtp=}R*VPLopayNvwodMN10ixcg2SVGHd|_a?#=ziH0HJMjzA!Lc1-TnS z+qyvY*+A6$SU_l7g)a;YR~Q(4WFWMy#1{sJ%OH0{Xxk5;85m}=GUU90(6KK*L)`t~ zGsN9@Ahhj~&kPKg7#MsGKxo@NpBWe~GBEh;fY7#6p!#|s>U}yOv~9s>2GBWrJ~vk=mqTa^>Lfa~QW?(o6ayNvwmH5oSa2Dil2yOe}6U3b_K0)01 z1VY=M`NY6*hJnH71cbId@`-`rG|1f$+I9g{-wcR)pD7U9w&oK9!zs``t`OR`nsJ{O339|s6+tMQ2ev`^GW1wz{@d}3fY4sthyw*B)F;?6H0A@2MDp>1z` zWMDYPz~FNQLfc;W$iQ$EvTL4k-GY3N3wtQq@IKsf-(*U7uYd$hC90s`? zLfb|_^#wrG`}ja;Ta%9r42MAV7=*Uf0jXnP@X>(Kwk#hR7^bo^H32yJ`g0|V$>L!T=U+V;W+28R70cSC5~6;OQ(AnJYQKxo^R4-5?ZK<U}&Qw5`Dh28KNh3_dy#+E(KO1H*0x1|Jm&Z3`;w!S@cohq&_# zgtoo&o&mJ}%I5}zw!QM6fng^DgUV1|#XxpCm3=BIM7<@V)v~A0K z28Qh*cSC5~7^uDwhU}_!61d&) zj)7qdsQ!h}wh!JhFl+|38z8jpj&~4uZg>ar-x>&QJLMe%!zNJu3!!a$-Z3z21i2eR z+onME#X!{iL_la;hj$DN8$j&_2yJWej)7r4$lVayRs^b#2cq7G147$=c+0@B4pjd_ zXxkTW85q`r+zp{^54?rAbH`hVJGVe++c|F;7}kK=4G`LP%3B78)gX66Xxkj9z7&Xh zp9BbP>+zO>VHE>|j|+shb$H9buoC2M2yH9zmVsdgD?^S5gpL(}n!^Fn@52J2ZQs0M zU|7Mx;PV1P+dg^2z_6Tw!RG;lwmt9$>h3pCcSC5~Id2#kmVw+2p>3zUVPIGaayNvw z&4KDmfvERMfY7!cZ$O7dGx)ebXj_Lj3=E4w?uO8|GEjXY5cNI+5Zd;~YX*izpmqa< zw*By$fngyiydkvhiPsQ!9(WCL=N<@cyW}+kXk5i-0fe@l^O}KSKFHk=+O`C$F9)LD zCj&y;2E1lqml;%Z8Kgl zfcG7wKxo^D7Yqzl3=B&^G-!M(1j+}|pz*1I7vOZT1Vn?zzigo9>bzh8kFRM!Xj_#R z4B+uK1qf{`0M!SgLHc;0`Z!)NfXCNZAhhj|=MeKjG)UbSC?7ft zw5`Mw28I?;I}1YF3Or$8Xa==wA++tA#}Iu_9z*m!fY7!l9y2gBf!ehY+V;R>28KpZ zyB0#*&VlNi0#WZX0YckWJZ1pxbMYyG(6$AS85rsr7<_Udw5#ZL1ESt%3WT<;c?8aXJ{1t!w&W25LnWx3fY7!9P<*IOZw*Af&k6`_JK+HX zLmmTzPY;B)?RdbzkPC7*gtkq9>WhG=_X&Z}wl)tK7;-@Q2SVGLJYZnR2DuwT+wwes z)IS^$I+g`$&Y$~GcSC5~2lp8mvOw)D2yJ`gJ_AE0$lVaycEf#0`(h1*j$Lsd;*SLo z{XTObv~A0M2GIU0p9TnRTXUa*Asy7Nh0wMUP<;Uq^*%lj+ScSg14A0f-4NPV=RN~N zDk!`mv@Hu%-=BL>cSC5~2lp5lQb6v8(6%@3F)$>9+zp{^x7>rca}7kj&k6`_JK-J! zXkVjG4}`YuxW~Yd2nufqZJPkq7XeZ469S=aZSFCE<^_E$AhfN?JqCt&kh>wYtpHRX z2SmLO3xu|PbC-c34%F^~(6&$RGBCt~+FcOZcF$diJGb10_-_M*ww-a8fguLe4uH_M z6YerFM1#@^gtpCr>PvyB_ep@zwjOsG7@|PsEQGdoxXZv032JviXj=)WJ^_e&A07y8 z`{fP;Xn%*#2MBHZ<_-fxILO@)+V;d9h&vD5fw*%IgtlFBhk+psG%p6BZRgx!UW2gtiU1!@v*%YIi|sTaP;o48b6GLugwSs6H8pdLIc0Z3`Nt2m+1Q z+-6`10*y1>W?%>ewHG0@?SAhd17ZAkqS z0-dr_{^J&ezH^HKyzl)6gtol`6~6$b&p>F~6}K3``>0cHF@Vnr zNPy6`Cbt+M`}c1$fcMj7+=Q5y0-+qPVX$QN8^U~mQ1GZ5O=2Q&x+8t;S9whyjB)SbBo zQFj7D+iti939mH}+I9s*o$Zoq3=Gbo^Z=o4r(9!Ta02xgAhfLoM4gWbgtk3#6=MDo z2yI((6;iLKTxDP|1J&CQ+BW7Yq+XAJ(6%O57#O@k`42+dYFuFe?{5bU@_^6fyUf5~ z3u=!;XxlfJA^KlHXxk^3A@7&b(V12O;2X$FQK(0LK3A@Wlov~9y_i2H3$Gcc61GU$Q^ z-$3c|$0-KT{hmHwAhhj=Q;>A|2147;IR!Ci286Z+4aPaLGWh&C2^P0qaT1blXPkuO zk0}t^cEU-BIXw{Cw%{Zr934(V{9^*8Uz~vOuR!TNCm`%ZF>PC?{fx1+n#``+jAU}-*!M~+bs}z zpA8V&b`4bBg5!|r!+O`HF?^6MxZFP<_fcHIJ zIR*|tpFPJI7~Zom=x%`WQy{dh%`u3&A4ehdg(DC;<_JVz1cbJ=IReqI0pa_oKxo?; zhau{64nyQ4p!@&`Z7Xval3sosf`r$bLktX-p!yX;+der23D*Y@+Lq%G#5@)VZ9Cy0 zB;Ep`w8cS)c{&Fn>F>k=i25TC+V;qP2>$?twk_EYiD#Mp3=9^a{sDxx71<9-r!V$F z(#xKG5cwSt+IGc0h`l~g+GHOjKj`d(*srh;V(y;35dA58A@(LfXxlG)Ao>?TX@@-! zc^e3Ao3k4d9x=Ni={W*I+lK6hghv2`w%xIdfuRd@|IIFl{s|D;RskyhXD3Ab2ZXlu zfY3fJ5Zab!C&Ya(c0lZVu!8}-ukH?nw!N_fV&4@AZF>T$ZqE*IzujjCgtpxRk@wjE zp>1dEfTR-vsCo{Fc|I%<+Li&L&gai|u=%zhwnOZHvK?aX0|;$<2O{rt147##*bXt5 zXFJ4SFSbG23oEuk_)8$PZO1lq&X7=*Sh*ao)GCkH~?hCtQ1K;(TKAhfLw zMBc{&Lfa}p)d@i4eRv?WEeAy2hXq30zS#<~_s&*`y*D7V?Uk(%doMs}+ltK$;PYfU zHbB}zE*l{3m)HRD&yw{J@r3mdag+5B@e}J9z~_)HSO*brSjPZ9rv*fV)`QhR`5>B^ zfx$Ls9Rv70lMDzQo3IYt&R+teLE|DiP;+>o`am?u91bWSM1#!vu@+*^7YH5uWG%!T z5DhZt0hAA-LE|fT)-r(47vHlM;yw@!GIs}*528Wlu35_fK1XH+gtm=X3-Q;FH4NZ$ zh3>3@@GDk>Y1RFLGHS-7~CIX>tD;7b*D`pYIT|X9p zY1<787#RM5&cRy1z_68tK{sR`B>WO)L&8sHHdvj{n^}->s+a{4H<<+yXMu|M%!Gtr z%1ns3%S=f4foPEX3}!;Y2SkJX^<@S`-3chYUXpsLadLjNVfzY-ly^wh1>4n(yrU#-QM1%Cdfbu~!NdJu-4J(y zXplK~pnMPwGUq}!#9wD1v~5c_#9bg7ls*EwA@0)XW&oX|IqMoA@Oxv#MU|^79Wzb#F!NBlQ#?nny*`24g35ZZPRMBZlygtpxR zRkxyrfk6+nz6L_uE@)w3&;|8ZA+&8x3j@PtRtDXa7D#)Erv>6~5DoG-XiywPuW5#e zgJ_WdS2TmusclO$B-|RB8Nlb4#X$KH5ZczHnStRx3xh6CGo&0i(F9RHrwNk(6`COR zDQFN~05pZz1UA>_Pb0)W5Dl{LLnB1|4TQFBX@rD#K_kSx90+Y|)5yRO!^)t`(+IV% z0U|%A0cu|Zq#gndzJu*+fSCKI9%^4bm~Z<5Li@ad(6%l0Q2Xj3=H)8f2aXln$lr01S$2JksA9T3{Kr5ci+ z8z8i8O*I4fd`u6BJ|Bl_NPYp)p!{M3<%4KYezB-#UlgtmQ93DF0l zLHh1M`5+pkZ%-ve--1fWyz87w2JpEeGb$Ot=ZZ{$(6$pQ85q);8FULE=KAD7XxoHJ z2Jm?!5|s?#bIn958Nlb7aX|Sj5Zd-b1w`G73W&NT6%chZp!_Ki+BTyC60RW?3=H=` z=OQf`<)Xj_8{NPOr(Xj_pANO|z59Fm`3lru0SGc)KODTjo|0SIloq#R=2 zjB<#1Qy{eMgmQ>^JrLTqpd4ae2Gl$sh<+cBat4M}W(HjyC|?6Y+x{qnnER#-V(tqF zZTqAQV(tS7ZF`~&V(x}Ah&$($LEM>B261NwR6YSJ?*bKfD1+Fm0_7_}Xj`5#NdN0Z zDI^}}ltSFmQ_8@g4H_qb(6%k55O*{{Xxkqpkn~ppr9(;>z~@XV6f=PD$puY9f%APa zBp?1Mg5*~a4a!d+iXh@|Ahhj^B8dB+Kxo?&MGOp}a|L~h7{KSYxfC&g&uw#n(6%Z? zkn!Xbg$xWISQvB{6hh1g(V+Z02g(Q0Ap0g1LhS2-(6%9kkn|c*$iOg>g+bS+kbyx9 zG#(70ZDk6<5pb1)^2%&8^6hOjr4TQE`Q2_DpgaQVJ09FRwh5|@<)Iez4m;#9VBOtV`0mvNC zJa;}s-3th9yC)w~{@%%hl*=>nAo5cnv~5NnME*lAB>Y-(8NlZ!3Zy{V$r&*ankNRL z|3oxI{}BjnJ0lvRzab2w?u|c0e~%A@-{B3RJv<=#Sv(;6L4&KH{n}UDA^M-VLF5;> zLFDH^Xxjoeh&%^W{)j6?{s4rwo#G0S*KvjDf8hd=e*&Rxcep_0PuN5Jx4;(S9tCTN z`a4z-^*122?HVhH`Zwkf`4#36`6UqAw!$1DKf??nA7TcP4}j3NDrOM*HKq{z3Jf9k zWf(x{9Xb$wB{~p&1rXZSMF*nKMH?ay%532APc5)I+Y4F{`3x@oJv71kd|V*3tprqljVi=l4$2VsG$=sS+bBTPTR>=A9tDVbCUTH`VIT)7$93c& z<+uifw&jt7taIUzV_;ANt<#0jwjX36>p|W?Xxk^U4B&Gw@5nMRs4_74+%O&w!I?5z);A_pnE|El8=wbK+5L> z5ZZQ+3?v`#fY7!xWWejEmw;$ceK`fn2hpJVa)Jy4gB9pL2pRDD#3davkp4jnlnS|;l;anlZz@Q8o?}E^_Au^D73xLY|$S^P{fyyliZEFCPmw?hdG7R8zxM+%&te0D%++bs}zpA8V&b`4bB0x3xQYz~CB zodJ>enF670CqUJ;fN0RTJA}5afynz*Kxo?%kT^4gZiW;jU8F#0+XRTbPYi^%jex2P zkYWG@xsMNow)KF>`?x@8+cT03;PaeLKxo?|l8|(8K$3w$8nnI!LfdYUWB{MfIYSZ> zUsEI@@zWp)iJu%vNV~uRDsLgl06vdV1FB8|s*VLJ4?0{C)Gm1<0Wt541jODG5)2Gd zp!G5k+IEiw#NI6uko>*@Lffv9U;v-nI0vdfLV^Kgq)!NhwhfQ~*KbQeG$@{ZpnMPw zif0!nA4G%X9iV&=4U)H!U;v-jXd%G>KCjUPLfaZZ)q!YGdeedOK{P16X-I(Q`~Gr-;tUM7EDXAD#KGxO_l`JtUGWkS4Kn`*ln@C*=VU=RbX2Y}GF2I7!#)Pc~pbHpI(W{5%5 zO@Yw16=D!|B@o&cWJo_~y_+aR-46(DdqWhW?h1sqbr6M^XCunMAPSn#gwVDM5P2UN z2yOd71nhsG8zPYQK8ObScZUeHT?mz*A;JJYcQQr<(%u5mpmQf9pnMPwI(ITagaLf+ zq>Bgx1L)jI2MBFz12xA4Y7dA8*<%3ZgJ@8=%7`$4&!?1t(6Kxs4B+!ASwtAX=Tm|V z6=q^m(V+B}1LcEgkbDM|528WxD#8p5i&+?SC4?dEJrM|P%OebF zr{58R#K##Su)Rw_G{~G2P(FwTnbQL0gJ_U^1C$SYaq0320KJOhz6PgJ_Vyj<7(?-@yVguY&~=uLUgNeu_^HgtpCK zfs{`v5ZX3|g@K^~G@ro2z`z2EZwPJc!vbzU_;^5QTL-8*4T!vt3WT=hVPRlkV_;YU zqCxKBfbu~!$Xy^qUobQ1zF}ryaNuKD0-{0oynymSGz$ZR?G9#${aYZk?GgyR1Vn?( zT>#~SXpp%xn8E3I36%EfVP;_1!_1)D0#WDF0HJLwpz5HsPYE-m|5^Z%Ujm{*=I229 zAR1(T1e6b=LGmF`K8Oa%2QV`*fc#|u^#_Os`AY}N2hkvZ{b7Rm>j#9keF34DfM}4p zPoR7d4Knu*6U1Lo+UEij#9t>M>U@qsXxlwdbx_)82NT3!TOjgFKs3nw4NyLa2AMwx z$_LRP`590?hz7|wK+T2HJ~dE2l(wya+Ec;=iFXhUGN%B_2hkvNVxW8w4U&(5@ZqGny z+Y^kC@IL~fZ4W@`B_JAP&K@WqM1#!P!Uzd}DDAU?5fc6jAnJVPKxo@3P<2q+X96Q6 z{CgnsOF%Tp{0=A|M1#yPf$~8#NWK8d2hkw;6sWmS+9v_Zhtjq&Pf)4odr+V1R_r5s3T}5DjwI0Vp3tgUnw8<%4LD{0b-^M1$n# zK+T2Hpy@%7JD1FWh}(uRK+3-v3JeS{m>BpbC@?TQXJX*XU|?XVWoF=uU|?W)z{J28 zz`($8pNWCbgMoqJ9uotf0|NuYT_y%T3kC*;J4_6G1`G@gx0x9DG#D5dZZR?NDKIdA z?oZ^CU|?WqVPxPFU|?Xl0lo@~fx(T5flq*$f#C@g10M%71H)60I5Pu7GZO!P-kY~^I&9PP-AA`1EqUaW(GbDMh1pw z%nW=Aj0_AKvkFfcG& zWoF<5rP~uA_b@OpTxMqA+rhxVa316y1_p*276v|0x+`K~;G4j}z);G zz}LXQz)-@%z*hlEcPtEi1q=)f6)cc+SjNJ@m%zZlP{{&GkL4_o^!JzrlK!5tK+@j} z7D)Pg$pT4#Pgoeh>F+rUB>g>QVc=tDTEV!6k)7!P;}J%7rYnp$7}=TrFg7r;GwoqI zz{JjUh3N(pJJScIFHG!A9n3w<>`Zf*7cjFkongMf%+7R#`2;gN(+!q8EbL4lSiZ2Z zGtFR~!^+OIfprTjJJS)?6Rhk^KUn{;vNNq=+rY-obcO8(8#~h*whwIVObzTU?CeZi z*mtnAGreGc!_LmMgkuE}y zzM;*|^h5iPHWSkqogX^vOjC4c=rS>_(c7TM&U8laf*w253H>wr>`VvrkLWWo9WXdz zz|OSAV21${(;9;f224yF47V7vGhH#bVZhFG#^8bhJJS)v6Nc=yJJS@?8K&$^J52YOvNLTk z-D1klbi?$HDLc~z(<`P-Odm|Ym@+Xk=&eUPiW5LdJ!s3htJJT179~MkZQ!Hm# zvNIj9JYvbtw8L_bB|Fmzt20*YOdG7XShF+Tu)br>#Pr7cgEc!-i%o|OJJSlAH8xC4 zI~?{nFfknoIuXRgv>;?j2ouwv(1tK3rVkNcBAA#i7G0k|yIOh=~JJX3rjAtH!%zezb z;4vs|KVdxbgprZy$y3HRPZ^m&^a~LE=P6^uGe&l%j@OJmuNm2y8eTKDfan)*8Q;8R zWM_KtmhlOQp7Ne?#(PF~rk?kV6W)W|{hsj%h`;3n`ZGuFmCw3$i(#K6XS?LiJfUlC)0{fCU&MdolFZr^np&M zBOrQ5C(|AfeW#P@0f@fR$#kQWiHYe)7t^0ECJv@2T}&^!n3$L@^fF!PW#VAk)5~A^9kCm{Zd<4kXk zgUmn9bmKS^6Vr~{OnYuKF)?-AVd}ZV#KH9CHq#Ff|IZz!hPzB0OfT**y}850&UE87 z)1B8$>`WJ4GhG4EJ#UyMykTNzYI(!d0iqAQVLAe$cf4WR1ERmYVfq20-@IY^0HPnf zXL|A;WX^l0J0QB{15?KbCU&Mj@0l7v^p1~AdpPTpU+H8OcTB`P5BBk?;F#dZy1Un+qIdK& z?*Y*p`kA+Y=qvrqH$e26e&!1x`a?hS7ZClTpZQHcGZRzCMCP7}%`WcYn0uCi{J)I31w=1d#=HVV z&soO207M^H#(V@s?^wpX2Sndl#{2+8Us=X{14PeR&b(kb$e+uZXMpG(%bE9p=nc!6 zw}9v?%b9P0=rhZiFM#L|%bCA`=oibG-z;ZlV%o5RdCLk=ysTn=vICHOk z4lz$%*6Cy8}pNG%#>~NVW;^qR?ab^{^q!r}2X=z|vy*uV zh@P>Nc@Bu~*~L6z7c)E4hn>t{K>Qawncslu2fLV`fW(jNVm<+)_v~Um0HQbSX5O+J z6#l!JXMpIQ-OLj}bju#*jy<4sznl3Di2q|`X0(nL9xApF_+IAo{~$<}V=n%3=nCF1#3CEeI90!#H$C!VB_-~Fee*n=B zjx#?2i61%6d;&!8InI0lL~l63yam*LoN|JB28ixC!8`#(KRChs1VrCB!F&fq&pFAw z;3OzroMfH>q92@PesY$XiD|`I<~3)T*_pPSVcu~Dl%7vB-#88O-)ZJGAiC!?^8^t6 z;1u(dQ=oi!iuuGTW=5tRrPl3FHSMHfan(|nctjbW?{Z@lKIX_<_93F zPMl{xa~>4L7nnOh4c-+OnAd>l1s9l?fanhwn7>?LW@37Bf%yf9Kj$Lzf{P%hUSyte zk(q^g!6oJ;mzY;vVrFN$bBXx@h`w@(`38voaEbW~h;F#d+;SO|%C0akxWdfA^yUil zhbtiUSC}7w_$RJ1pSjA+&a~qy^BxdA=PL685IyB8^9(S3jd{j3Q0!f0{sZEFxXSzm zM8CMk{01a`<{I+_5Pjqt^9c~W=Q{I&>!8@X&b$Of&$!M!2SiV}!93*#DE6*1{{Zpd zTxb3Oq95E~egYCda)bE|hX?f}s*ZZf|C$v?Qs`~*zjVtxV=KXQxt1c=^qi}?VE-g29H$8C^#x0&aF=n1!( zr-0~=JIp=%pXAfC(oE)JOicU=gc2K;&+}iKLF7O zo--c-(L0_q?*Y>^P;Uy?sUNCjG^OE@hh~DsudCMzMmV3oK14Q?{Vx9n^TV6AFyav@8ubAI}_zzw&KLOD< zUNheTiSK#Md;mmmdCj~7M6Yqs=YZ%5pP8qC=#DSUJzqfa{F(U!i2vj>^9vAt z;|ud0kocZ2%m+a9mM_dZK=hig%p1Of^5IwJDImJzD{~KsZurLB@(q*^zcRl7@$Y

    fU=l;5E6{KfnO#DDXP`2&c4@|*bu zNc_Za<})Drz;EUwAbQIm<{f`P;rWMo4v3!chj|K!?)b~x^A{AJf0#dj_)q>YzW~uU z{xaVIiSPN#d;mmm`OCZmM6dbByx|`xJpVCI0nr`*n0r9AfE0g1n9V)+2# zUua^v0-{eev77`ZT3Sw4XH zPg+@Cfap7IEDu292ijPUfao1R;lEDhZ(OiUlTSiW?zurS~0VtLTT@&u%0LpRHoZWeZ? z72ParK=gucmL=UREX;FySQhlKEa_okXS&kEasx!4>0!Ch!vY%nU|G=1!o;+qmt_rz z-qOpm14JL_WjO+(&-Aif0MR#kS?+-754|j3Ky*VNOG_UM6Vrq~mMI{5K_AN!5WS&~ zWebQt(8qEFME{t;@@E1I6VsDrEH9R^Ffq04XX)6_!o+mu8q0-iEKE!f-m*M-%fiHT zp_TPYD=QPzl)0=k=CU#|^=xIGu$7gG>BAY;FK1Ypm>Mp!wp?Td>0`Zcjg^UM%S+ZB zFIkzGj=W_(@fM{1GwX!UtV~Qx8rW7eurV^tXkc5?z{Uik=QOafFfW+Twq!oriur6z zOh4wa{h7zc$n<6&+mCr{Od$HhJT?~QJM-8c%wu~pkByz_%Y3#U^Fbqp^VvRt=m`th zrYvA%XX;qM)&ruCEMPkUqW3IdI{=~|EMR*AqHio|$g6vt%*0Y+8ooUHxwiO`y z!)mrKAo|5>wl^U9!D_ZAAo|8?wmTsD!fLiFAo|2=wlg65z-qQ5Ao|G~wij#I*qJ`8 zVfzB2SFB}Qvz86i^J7~AqGzmSn**Z%tYd3f5Aydqwjb+2{$9uS0YpDp$Myn5-&x1@ z07M_zz;*&Oj=E<9+W`>0Wdqv|5WQvt+XfK5WFy;(jcn{pXEw22*aY(b7PgixY)njN zHnUyW%*M`iU^Ckh5WQnF+a3_TU^Cki5Itin+nlXz>`Z&MvK;`^+t?0lV`FEUu$^tn zc93~H*e>i~V`Q4LgKf!9kbkzbec8^&!hB&n+m-EXH@1Ufbtl^&kW|Mmww_&VEX*r* zv#r_9wqZ9L6Vr!XY+rVwN7rWWs zfYjgE&2|UGzp#hx3P}FVKDH10*w~q#>|=WYq9^QUo3bAiOZ(Y+!1O`3o`WFY9%O3) z(Q6K}Z2-|r4zjHP(Ps{^T{r|9eLl=~<1iaL(}g2!SB|i;Go3iXb_PU$IKuV?M87z~ z_69`v9A%qu6qFi{vUPyyB}ds-faohn*=~U8<7_vMgF@vv+XWEaaDuJn1RFckkK=5A zK>Rny**<{i6DQctfW&v4VA}(tUz}ij1EP1FV%u|yjh*SnX|_A3*;trAoM!uSn(fDF zHg={RXV~_f0VR+#Y)e4&hO=y2&a$yHtvJiJ21K7Z%XR@oA34i*0z~gQ$9CWx8xzxs zb8Kfo^pf*zE6#(0`W)MXb09CDW4i&OkDO;a0TSPHp6vjbzQA_i0vikSnhR_jF0gI6 z07`Qg**;ukV`7?fiEY6pP~N!2w&4;R3-g{!YzHo}9RUd~xX!lZIvYFFjO%Q3Ky=4- zwjL1OaFea&CMW=Iu>AoI@b9?Ewg<%DaFcBdh+cA&ZN*JCCZ;Jj*=B(FH*T`s0nrz3 zvRwg*|GCN5a0?V6x7f~r=mWRdj)3S7x7fbi0y*h6+k)F5U)^SV0HVL#X8UoQjfv^P z9kwfX*w~pK++lkHqFe5=b=+lRXZmx8tpP;uxXZQ&L~ppuwgp5lxy!cVF325s*=B(F zJ07s@c>qdC57~MivN16odBk?&5y;%fY*!wGg5WvZhUaWdOiy00y?DXK#I&P>eNP8F z6VroL>`zv)Gco;G!~SOtJ3CX)TJ{NR+1Z)itY!ZIqMxi~e*vOf*0Fc2V`pdjvzEO9 zMDJL~z6V5aSjWBvL@!y#zG59a6VsG+>@z_86&u*sY+z?+TCjnA$p&^NrVSg}w`^o* zVp_9>eZv-ZcBUI!+3##+XJ@*wmHi5cUa*aQ$u@R&rWxDV=WJtVV%oBueaCioCZ?Y4 z>=U-Lb1?nb#{LH^zMFl=ZqPK#UiLS8+1Z&M>}7wlmz{~}!#?&e``9^{dQP%WILXe$ z)N+o!;~YCX(~)!RCqVRrE9_6Mfb6}(eg{N1TxD;$%FfR8;|lv95P!~9_5~pRl&kDB zuCg;Rop`{0<^jn3hwM)tg7iIPzXPKGJY;Wp#Lmw2@82& znV5DwVc!GdUwO)Y<0(5k)0wC27oM^+G5vYT-tY?K?zil3-h#}1%l-sJ|M|k+@D=2a zf9!w$v9mLM_{aX`A3GD%i~sCz{)6oO&wd9)Z)oM%(#pZk^rD^PO*;oW)0Ga68yy_% zOlLYcE`aDS9UMPE^qUTj4B5XEFy9(}5`*N2YLa zFs+%wv0(}a6VrpK98ac#rnqKuT$u@)Ic_Wm zxpO(kh2aa;k>54LbT*}}ojbYlz0oh=+pOf6eE zI<|5!Fxo1s6d6xWI7%M7Lbz=(xzi&h+O3M+1mna*<;Nh@Nwi zW5GoZCZ-z~Iqrb?2QG0Oxx~TF^xzW56A;~UnWN(}2NTnR%N$ECbFectT;*uF%E83c zaGj&&I>`UmIp%=qBiA`jfapEfISzp6C)YV%fap8dIUa!MH@7%G+yYG~-r{%xqFZir zble8H=N3l;h+cA=V+DwwbDLuUh(2(e;|Pe}ahqcgh<Qmb~QH z@Dh}SUUIAe(JNkYta$~B;@2EUUW20MHOH0L9864e-f%2<0}_A3aRfx)dCT$OEy(=0 z93Mb*&o_<<-#A#9d%kl__|7rqI|n<{ho2l@eu7f_PmVVry5|?igkPZ4{EMRlM6dY8 zu?9ph_{Fj07Y7s5mERmUesi!h9r?|1;x`8eQ_pXX2_SmHAC4)1IGC8G{NoofCapB7GbrUh-BOWHWunP#+c&H>R|+BkQ#aWXMIY2$nWqGz;o&S~dl zVw%&#xuA!WovEdlv!j=jo#{^xX9I{{)62O5L@(*(Tmhnw^m3j6(R+G15A<>}FDAbP?~&M7lF*_k?Ka`u4eH8VLkfaoPNIah$_Gc!3afaoJLIZuG- z2QxXJfaoo=ICsqAWM^74i*o~r{xX~M$81h^rZ=-WKY-{7b2z8W0hv38vj;@4n8UdS zL@$`bxdcR?n8SGnL?4*Lc?3j%n8*2L9w$4~i+P-HKy=T1&I$8D;WMAJ14J*G&$$9b z&zaA;07UPZ&v^huZ<)`z14Lh$&v^qxpPA2j0Ytx<&-npFKbg<@0z~&L;GD1kWZnYK zjs=`dOdA$(ZUOP1EaZH#kdvM1&O*)yAo|Zj&W1&t>`WULb8cD8$p) z7IQuU@f((Kwk+XfXZo?2^ACtWX9?#55P!-N&KV$j!&1&IOF{aUa;^c<7nX8fS<1=8 zbYv;#2@wCtGR_mrIN6!@EaN-?q8}{dd;+3xEaSWbq8pZTwk!vkzl`$_h(BjJ=K>Ia z%5u&b%Q=~t&MfD=0OG${&iMgEKUvQC0z`ML;Otq!$1!3|3lP6&HRpuY zpm1Bw*#V+gtma$;q8F^@Tmqu^tl>PchLfFX%NoudAo|7{&O0Fb!WzyiAo{}^&MzSP z#Tw2xAbP@D&M9j_>0&Ks4~Sl~mU9D$Ub2>R1&BVemh%jVKCqVa$XZaiujPCK;(uAs z`C~mOeXZyG0HP;s;GD7nWX=Z89uU1^1LqnLy*?Bir&ny`;^%05s$@8etp;?LQ~xd24B?C0#*53*-J=L`^iVL#`U z{hUlpI}UK}Il#%z^xy#J6A*pl0OuVLedYk?g#)1S;{fL$5P!x&&N&A;nV5PGa!vrz zD-Lq5ImpS*bl@Q85fHuOAm<(sedG}5i9?)BOkWOh{s7Y_IDeerWM}F*$vNR9$o_Mj zGtPnd=Qt;T=mY0CkAUbM=Q#I(=o{xa?||qF=Qyu`=pW}e|A6QZ=QzKd<78r*a-MU> zc}^y#h6|i67eM9CMb0Z1IhmMNT;yDHk&}aI%0Bwcy6PGzT zm^!X;_FMzG{|@JbJD_xQoAbqOkh%w)Umk$+_XEy1AiC!v=Y)r#boG$414OTQ$hihY zFL=ng1VkTs$aw-p?|I0107QRy$oU0CcRb?kc?2qdA8{@K(MKL}o&eD&o^qaf3QF%! zIS)Jq<>zOd51w(dGktl+`2$3EJm>6r4$9ZhIk$l5C(k)wfapKZIU8PZvNO$i!8r#+ zZ+OAE1w7aj`Rf z>ErqVqL=h@t>_1t+t0NCMBnM>dH|xY^mE++(I@)3&h&FJG41H*+5_VEOyHU@fs38# z$V9Fa6SC7aq3n2Q*B(4`A`p+b;hRIw^Oj9Ov%>dCSCUczu(RU_u zJpj=kCUboO(JfQBI;L%bJQBOv<46s|WQ`o|QmKOnkeDp$``E_S9F zQ@Q4V=oM4B)_~|a)3_E)<6>u;GL35nh<-Ai>&0}Cd!}<;0MQp_a9x?f#m@9#2Gt+doI@j5WQtC*A5VUV=mVn5Pe}T*A)=`VJ_Df5WQeN*OK`l_4Bz7fan+V zx!%m@Vq&^5pX&;UKVbpalm%SuOm7x)eOSoF#Pnbx*AoyuWf9kmMWA?G#I*-RPgu+~ zWib~!)1Ad!4;FJVF|Am_wPpzyJJXgWTsuJYpCw!kOF{9ugzE>0|6&Q(n`WcYxOzbJpQT(4%Rv5I%JpF>7ZcN$Wn4c%;uDs0 zOj{Ydvxci-Ey&(YTs@mW;+wdhfao`yxjt+LnX`p!#TJk~Teud0=o@>u z?(6}n-^dO-A={ahPB^pgEt zD?s#_{ahD7^pX8sCqVRq16)fEaIrI8IKXuUM7JE|>Np6B??YTu4uQ-$#MN_%i;3yP zA+9qZ{*yyoFF^F4qg)NgK;e9p>&H=0dOOB71H|t+#x(&%Z#l-b14OSm#j{XyaGL81i2iVz z>&s~_7Unf)xHg>O+H!`Ao$1aQt_L9c${DU3Ao|N0t{)(J$62mDXF*0>>j;Rxa+B)@Nc_)Du7+EnP`SzV z1H^xElj{wLKJtL;!~>8y54aA1=qC@jUV!L354awH=ogQ;-aG=u`bVx6A3^T>$h81O zpZLgi21FnD$aUl+D7Sp#y7CF+zfW9GK=hQ)Tr)m%u`~62=9&Pa8$NTjeCA?e`tXVC z3rPON7p^m3K<0hrTJV*No$1O~t{Wiw$ak(2-$A9=cdk9(x!9T3{N&p3lZ&0{$xp5q zAbQC!t`)zy*qILe<~s5lRI2^v+VL9{o`1P|{({8+aUJ;wT4?&8tK&ZxJJW*yTuVUo zl1A>EpftqBrz$ZvoLQecT;=+)PX_db!{9ax*gB>E(XW%gqF$AM|pw zGcD=mUeU|V!n~%RdqY3>mVRz_raKe3A57q8VO}zYd&Ly)HB-3RnI25xegdLzOyRx* zqBl(C-ZGV&gK5rG?gdjpzMslH0Yrb9%KZaG-o1`^kE4cBUKax$l7JGaI-sY~W^R+OdIq z4~U+!lY7QaP-ySu-TJiUIOCJImNx;6gNB5lvCU@Ky=S(?g^(s_MPVL0MRQ>bFTr>3r=${ z0nr_2xqHrn?>`WIPb6`YJIalZi3 zQ~q(!_y_XeKkf-2`amPkkwzYNrX7tudqDJ=W}XYpJnT$Int4uu=qJrQFF^F2W}XKi zx}}AuqlJf^=}$9H1BhPG!m|WK&uHP91EP<#@SFhAds=u7wD2%7wRG}ybn>t>E$HM~ z0-{fJ@|@}9VPfj&;_2z)VP{&=#j^%P|LNjs=;mQ(+R)9j1w^0d<~h^N!^HHao96?F zp3%cIr-z4~siTLd2Sjh_;n@MApY-s&0MU1PcpiZ0A3Z#OKy*hhPfsroJJXC_o;e_T zMK8}95WS<9XAg+J)64S!M1Se!`2nIk`gnT!c-Wcd^zkeJ(Qo>AKJ@W$Fuj?;^I-xH zJJXWsJS(Py!etuIiD^76%x7lsT$sUgWd;vB)0Y`MKS1<>nLI~k@~|*>%;M>p#WP_R zNcAk96CireES>`(`oS!oCm{O9ES@_c`p+z$hS?w^X7T)(#lysOWj4`V`q@jO|^!_IVL8P6RM{bL!= z9}xXv8P69GJ!d)3g5^ByOjDNg%mC3>mh;>I(Px(PTmaDxD|lK~@US!eSkChY#DBA# z=L3jdvVvy?NPNx;o&_s-SeUP@;JLAa=gtZq4yF?;c+P;NzO3N+0ixHe;n}bT6g+Eq zR;=M+Vmh&g=M0E{Wev{_5dCBg&xS{@eWKkIlJ*7LNi=V4*Kvw`Qq z2A(Gyc$k=;Y~p#biHC{l#x|Zi+j!WSUTouevyF#^`NuY%Kiha3w)3zvZQ0JV14OUc z&a(kTf7s6R1w_Bt&hrLD-`URdU^@>J)0yo&7eM?4yLguD0(oy2&mR!|VHeLA5PfAI z&y9Vcz}?4l0YrD~=jqwc!@~SwAJ3P4JU{mFurOcP&vRuz&yD>&>`V;@cv=pCOxe%# z2gILqfM)@SKji?=i~~F@%tsFJoH)R91|;<30MDNTJWNaz4)IJm1WNOVc$R?ZBZqiS zfapJmc^Zy@j6BNIauno%<2)CRgHp+Ho)aMY!Ev4^Ao|Bioc7W)f zvpf^d@~|_toaN~N(Lc`c{5iwJ!8GF>&zy5S987=C^E6!G;b3aG#M5#KWX~m@A0T?q zWu60S}Ot{0t&h+6n&zIYv^mm)*4v0Q;o96>GR@~|`AxykbYL?5`xa|A@sxyiEt zL^s^zX#vqsZt%Rg!NbmU;s(zd5WVCE&k7LTaf7D^M8CPt^Wi!VJJW^hJXb*Un(I6p zK=g#`JX1jQmuoyfu7TvQ@mvAXORn*(0MQNCcv?X8ovS<#u7b+Kt2}!^^o*-Kb3k;< zRh|wI{oo4ElPf&zOna{I901XCuJ9}X(G#xlOaak9F7x~Wh0mMIJRd;xjJrH@?t;po z`#f{*gVOYUo;M)+$9n>D78N4IRT=-Jm>iVqVGKCc>tmpyyjW*8syv8Jaa(w zj@LYUK=g*!JX=8Yjn_PPK=g&zJXb*Uhu1t`K=hM0JTKnxurM!p%d_My&x*G^EX-@( z^K5v}v*kSxJJXx@JRd;xllMF?Ky=Foo{kToyzri<0YuOFz_S2EPx-(z14O_0$MfbN zC@nScK4{=&XS&kFd!vb$g?T|U?~-QT70tX%Oe

    *R=97F@0#`{nEzE&eYJ(+tSX< z!aSj!cS<|&jCNjjra$ex4IRAfOkdi0e}MQe+Iio!^D;5rXy?5H;@|1ueE^bw)4}@z zL_g`|ebLFw#B`yP_ev)(J5xs&Z%-F56VsPY-X9?TjV|6hUA*i}7rJ<_fao3FynDKN zLA4$477%@Ch|T3(Q_v8E||p2&NO8b z?+g&#F^RWl5-(^@k@pWszGVt;#}r;BrYBQ*UrYss-c;TnQ+b(~j!fe{F%1+K(|B)8 z6GFB8+B?Ys>;K=$wA-Lnf6OS^clfanvuc+Y_7H@kR0 zfaoW?cwd0%j@`UHyFm$OH*X7wKC*}R#2#KIrY(DTcYx>{dwB2c0ma^a-WB_K*_r0- z=Uo7zx9sQL0iw_B=e+=;kL>3?0ivJm=Y0X9@9gJ&0HXiw=WRFu3cvllKS2B`2Y6?I z_&o=BCxGY;2Y9!D=oJTe*MR5~2YAnb=mQ6MkAUbG2YBCr=m!UQpMdBSM|jU10fqAs z-XkD-#xdSG$9UP9CLH6Pa*UUS`OY!k2gi7yfS6a#@ZLDXd*=)&RL}CxISW#CmUjw> z-gB1s0EpglmUqWlP})Ar`vb&(a*p@KIZ)`G=iPH2l%~(~ZUNDE&htJ1(O1s%-T=`* z&h!2O(I3w9egV-FF7i&f2+AuLd3!+ghKsygK=g`>ylX)8oNK%bu7Oh9HQpH@`o=Zh zJJ)zY%er_kfcPypcsp)@^6GWo1`s{vF7J%Hpjf@jI{`#D+~;k%4@xEXc>ml3`QtwC z6cB&Kecm-7dcl3(CHHxmm^M7*-SQ9=IuCh|fan(wdEbEO2M>9lfar!tye*GF<~-#6 z1L7}u#JdERsRc^82AQ=an90MpNSXFTI&Vp{W@cf)gD zcBVbgc@Kc-D=&C&yx?VLI`e|}0*HR|g7*W6e)59%1&D5V$=mW0R0_Q0-2tN4yyV>g zq8Gg6UGkEbiD|-1-YFpdie4`p-|^hF>6G{o>v6ig0fp9I-VJ|2q4k&d z0Em9`m-hpRe)5<11&Chok9WyGP%8h&I|oGf{NtVQ4^$TXN+XJFE zH1TZ#(My{6Ry6T3F->XWn*pM~H1qvv=3{4?(ZV;Ug^!)-NgLmbHa>QyIqiH4+WFX- zKD6_F0nvBb`5u7iEA4zYK=h6dzC9g$pmidAH$e1?PQEprApMg%$+t}5>zKmF&h%$8Ujv996lzd z2XpwI%mMj-E?>u7J|?C!bNMdJ1%=amz7O+3{#(j7VJROI(~4z$YnFlHcNyOv5Pe}e z-<9Qj>`W(?^PK_FFP8JY0nrbZ^F0C4f0pw#tl(p3+OUFe3y5B^f^Q9op0k2)!3sVm zrk)ji6F~eaEBR)u1i61D-vJQ)U?txZ5WQy=-+@)2_+7*IVhtZV(~`A(E7pSSU&ps+ z9Ul|Zi}ieO*7LD5{aDZU2Sh*E!1rVWA3M{H4SaV%^p6dEe?aty4SZifbk9b<2^&HF z-^h0aMDN(hw+BS8*~qtHBPiTA@+|=I_iW-junFYfEqrUXfb84Cw+BSO*uwV)L_gTV z_XI>YY~^d&3bKC--yaZv%2vJ^ApVK1d}l!PfvtQ;K=hWad^@)CF)=OK%C`cGa>v}LM&kUH6ZiZ85lM|54-0Pr2!F*Yi26vVye>4n zS3%9UT>+72;fJU%Ukc$%L-}i=?y2B~$RB{JuZQwaK-G6c`DRf2&p^WmbZ!SI{k^#Y zNrWCy{fD6OeGaPrrVGS;&$STylc4Fv&J+@U3Ohlu#lWBs4S)VXi28ZZ@K=WNHK6+Y zpyBfn%Kr@YPXjc(PD1&=py7EF%6~lvV*dmvzX|HUD^T~YTLh8+2<88Rx?hM9;vPFt zc!ADHnFERMN>F$s@$W*@mp14W9tH-6CaC?B{UG}PEQgps1uAa_wSOg)p9HmkH4we4}bq~W_i2J@l5cAWa?vsM@^P%o@ zfbv&D-4_JqUxk(zJy8BnXnC{{%9n+@?;Dh#3w0kC3&g%nQ1>}P`HE2Yg+uuqQ1_jJ z@};5fyAI_mL*4fm%8!M*kDC=@ekas@I#B*vsQYZ7{EM?8;XMV)SA@E6F_fPMb>D3$ z|0*>9zlQRUuYu_2W`o#wYbAs)59L2v2H`tH`RY*j1w;8BQ1=~z@)M!%y8z|4Lft38 z4l)1g42XFuP`(t@eF;#0C)9npP<}PkeLF!1=P@ua^g-Qs5Xzqhbzc=H#QfXP`mPho z|FZyM-$^K66zaZfP`(S)eeaY#lzP?IB07B z@=v57@`iIE;jIDnPZ`ub#!$WlG(P@9)t`i_kA>Rz1FC)@l>Y>po_9grrwR4X5h#B# z)IVmj5c|8J{_%(M=R)(_QYe2GG{0?y^6x{_v%effKR47riBP^i)W6f9{9tH&t%mYv zK;8Er%D)Ru&m!^=^TMI-i-q#-pzbS%@&lpn+YRMMLfv-)%AX8%-&-huKQzBFDnQJC z3{B6@P(C}}N37VdLp?p@T`({GwCgYu6+ z^V=dQ{|q$0ZGiFxq3-($AT< zzZmMiT2+YqQlakahVm<*?sHXx$TvXU7X;-Wg_Z}r>Ja&7(EK3{<^PA~kE>9=9@KqL zp!_LN_ss_#K+3?ta2Q%%t%dT9pzcf8gqW`abzeP{Zw__eODNwS>b{>)ekjy^+FB6( zv!L#?f$}#)-IomIKZ54pdMMum>b@^femT^Azo7hQp!N+r1B0SA#QYne@{OH=!4%4W z4JzN*85k;|{Lj$#-2^CK9_qeTP`)43ee0q8bg28zK=})y?z;u$|ACe#0Xh)-wW01y zg7TL_-S->HpAK~&uP#LWDyaK%^&tFBQ1`V!`S+mZ$!{p17wSF^eTaHBsQdJw{A{TE zf}s4}Q1>YqK-7Po0x4fDpnL;p`*R|cFAl0N*cljRLHY7f_evT<^s7VNs|MvKLfxAO z<@Z9}+X&_FftG)dq5P}R^5q+pF9mh4lo7=IEU0_6q5LP%^5r*_e;Qi;@ft(a--DJf z!BGBfX!(*2<%>eyw+PC2gt~7llwSaK-%lui3e)TS3g<0Ck@Yl+OTl-()D?73#i4Q2rKZ`S$|KUj}vGcPM`+)P1(r z5c3a0%fA39pAG811yH^^)O{p7m29>`|3=AGn`6Q_N2T*<-)cp^j?ZsZG`x!t7Z!<73 z`~m4_XJC+n^522GvCyzYm(;&O`ZT(EKF|9UnRlP2Vg~el0Y9e?r}} z9a?L(u%U8S0*A(Dc0r%I}BjpXCiPuMrymx1jtl(DHg4)O=-V{9b|bZD8RGZ%2$KNH(41Nc)KCvx65GsY6zbb zn*I!-?hS;xCl1QL3k|PVUJiZC$naWXJ;BtZBUQ2)3=)h~jkhkwBk`5>r!3}Ybt z?a=V#kB0EYpy6{IIv#2T_1|wOe+1`HP|Exk1MZFG0;q zhw=@e;ky>fR|Lf$69Yp6G`{1Y`G*yno)$y%k35VI&A;i;@y*rH{9Og*e}uZ%2O3}6 z(C}-4@+Uycw=k%B&RR%#-hhUuZzrVvH67|-i8@I7)kuVtZ-u=K44|a3W*%fbt-S`q z-w5TqK+SItf`soYX!@7~HE$*~zC~go^1Gn%X8`42hQ_}Gl+OeW?<6Q6bZ<6jJTn6t zUJ;=5&dk8@0m>JI#`iI(|Fod-{TIsr0JVQ6l%EC-{{pCfUMRl;$`6Oe=W1y9eSqfA z2B`crD8B>BZ-VkCK>2=9_nSh)<1sXSxuN#-pL; zNkio~LesMalph4GKf|H^X@klifri&AsC`$Ud>Lr_{65q@J)rnwXJAl;x_3TQ-X6*q zfy(cJs*i_;$4;pIH=*V4Qz-ucw7lno&L4p8LkErbltJ~cgQ{1BrpKvJ^$t)z=ss?c z`d{{t@X-c^2PmmS)3-A;{0*Vu69bLEFepD28viq(@m~Pa&&0s60LniFO`j{F`FS2R ze@ue%W1!`2K9rvV&Cg9x{{3Red>99`{Op8=mu@)3z00BX6PGZAF9!8*8I+#`nonb6 zV3+_MAHU)R$?tcd@;1#7^BJJ#|Apq~r%?G*(D=3&g_ti2P0tgd<*xwL{YoMb`IDgX z19X=O)I15Oe_WyRJJcce@j&GlLG$ZAsQfW#{`n8(*FnQ?Ig}p=3U6ix1_5aNh(XIs z1*rS>K;2&g<-dTY_lMB8v(7)d_nUGtPBhS(D}$qVG#Ex zK>1nF@XLVm&qK@W3aI(wp!C4Zz+eD1|2nk%UICRChUzbX>X(70kJV6lTd4m}LHS|O z@cIJfS3$!|1v)?Z25SB@Xnn^I^=~Uwz5p6NFQEKpsC#+DA@RorHNO(dzW^;i9ijY> z(EN}H<#$8vQ-ks?q3)Rr<DLd;(Zb?+~z{61*@<%Y@!L*3^L@6p?r3z|AL_WcL9+6-v{L{g8FAZl)n|~p8Zh%UZ{KSL;1&` z<#8x<{M#B@-!wz{3{dx^K>13b{Kd||FagRpf||bs%HI#oZw}D$_ZiUo=O9!*2WtOL zDE~OLzBviy2Z8(xx{C*zzj8qSVPard0WE)@LCYTv==iz<)I3)x-v?@+FO**mHNP0j zpAU6kE0o_4jla{-{@@B|{M>``{h|8Vpz8;=fc($Gz)%2nA7cijeWg$Vs$>`#u0!MV zH&p*wko(yg7?wlJtJ@&|u`@8FL;1GQ_zZyZbD-fJ4&^_9hVKO^zZ>LVB>SfnLhPSY z4Y7Y3)c!_jefAL=ztf?71*rKup?rR*`U%kb_cFBn*M!!;GEn!mL)TyALBq=!%5R5; zmphby0UAG%Q2lYR`WYI2Tp;(eGcZ&@<;|e+)eq&TLc@Crl-~)BuS-yV5~#dpVPMz= z4S!*%|2SMB`7IM#Urm6nXDNjGClPA@eQ5c+5z0RcEg$(o7iKXqFjPX_Uk;Vu3@yJW zLHWJV`Zx~SUn+t6uMWy@huSw8%5Q<1w;IZ?(Sp=B9Z>h30Hr5p28IBre=?xqT?cJ1 zZw`U9?*kGc{{^`d79D;+_NLi$L97 zhL522M63)93`r3C9HI5GA5?uCwEiiF@*APycg+)`{uwkrilFU@uh9BoH&p!{X#MaG z%6|{79~_|izeDSTG$`K?>Yv$A{!*y>S)l#Nuh8%kgYs8G?bC$vt)T9efbwTU?bn0y z*Fo(!hVr*T?YDsPe?!ZATPR-!8lFy2zA4oI?ofUt)O|is{uZeF0-^kO(EJw$<;OzZ z8x7_AL*17Mb}KLz9!UtE1`TZsQcDK`7KcQZH4mZLfy9;%0B}w zj}AilMo{-1hw?8#%g={Uej?PpXQBK<(DL>Plz$akem;ltr$G6Cpy_iCv^wRc{@ibJu2Piz485k0v<;QO+NO>^)4KL!j>a3DtiNTK>uSLc(h+wES~~@=rj^r+6s;D71X4g!2DG z^K(CxuMG{)Gf;jM)V&{|{9n-ZeKVlt<#j*Ec!dbG|8p1`UhdHGNDiob3!wZuX#F7# z<%dK4w+!0fJqk^a< z`R6&*ePPi2A_sNPQBe9}XJBxH@|mIO!2)XDB&d7dK>1?O@XLqt)uHD9f%4^`;WG`& zuY~&VG?c#`>b@wbeG{SKRReWz3)DUDq5j(o4X+tc`8Uw?u?fm&g}Uz)l6aJEFNd0M3FZHVmM4->em^w57DLBN zv!V5qGn9WH8edDG{HM_L`w+@+g~tC?DBm5_K4D>CmQVj zxd7!afToALP(B;9{(J`I%R}8K2yO55fb3&pVAud{@3TS8p9Gbk4o$xkp!^@u^fU*` z=Z3oP5|l3twf`TKza5mGklHuTKzQ3Z@y)@&P*4eJ9|b|nubI&C ziz%S^<78mi0WF`sLG39P28L(Q@Ji`}lvi({{2!q9DGLL`XDI(nKScf)lrL2e;d4RD zw|CI+IRYI&5`wz#I+QO3O|R#n7E<^d8(D1nq9_~Z=+R*g-9Lg7hn*SEc zSB0AY8Oqm%=C5B+emXS#8KL#lWN3O~hw^vFGcfQoGBB*!2^sI6XbIux?1J#uCPMfQ zpbJfaoM@E!6X>IIHL_;aNod={wr z(NO& zxVg?Ct_0!7K<&2;gYYf%Ang}9Q3!v7FoYi?0pT}@LHJC15WWHEB1#4Z23BbJM1U@= zWME);EC7)gV1cN&;D+!mmO}hvV+G+~Spwm&l85j^pzHhJx%Ni#%#E>wOGl>aaZV&08bh`b|I{!1H#zZEK< z1GP^CD&H{;B0mF~-W)_Ad}}Db1DgKYpyAU4<%a}<>|Pv z*%%mRK+DGulOXCrm$-vMWG*;89bh;Ex-go7fguIVXJBAygy_$Jn)jj>!k?c8(eDGg zc$I;H0dx;NsQj2v50O7)2a$i{4srjP90)%|7Q)wtx>sZ^M1314ME*c0gr5TSpNStt z{mo#AJO@97?=K7C8$i=jr#OT!0SymzDBl6fH-YB=9nT=*sA zg#X7I!e1Z;aUWAJgkQ4(Qr;!yL-;;T5cwErd1KHG;S2ghM0CUjYrTnNa_VfG)IU zU|={V36WpY0&%bR6bRp<6v8)y`X|Q`;=Us>5cwt0{-k3c#J&coeLNNrd4o2H{uCVu zUk93gGN9=tW-TQAre}cU4=`ML1yNrEO^-Z*5dK9LkURr}K@fy5!4Bbj_(J%vK=HxC zz_0?^-k1$l|HKO-&kPM8nGgtniVsA8j30!b1`Urr(De5p79!6Q4w3I~hwxQiLim-Y z5dNM}2){uH!vEj{;ctPahX|EL*i$75JbHOG`@F0>;H<=5c51jAo3y5^kNPTpEFQ? zER??k%J+qamj^Vxeu9<{bD(@1X#6gKs&4_MHx34d1<>@M)d@)-Goba)LTGxESOW2n zaR9_UJD~OZb3O>a23kL}L(^LWbbs0oXm~T|L;M>*8KV9MbbntZw7ro4O|QnG5cvXV z_%PW(_zz4V`g@?^rvSPzn}LBLzz-sC;R%sv0N1w%7y=q0{8!-mg@J*k3KE_>!SxXX z!O(jJBF*Lj)p#1Al`=&ts zcMq!G1j@e(t?z0!K=dz#`sWI?eEtoMzcpSE_uYWX_dv^YDMN_=C7|&wY5?JzK>53& z>F>ZwsQJ+JT>!2B5~1zi8ff_>Dg)7<0OhlRVLxvanCGYi249%c&>r^ z_X{*Wu0zAW2Ff>whUbfO5ck+Z>-UQD5dL#$`D$_r!WV+d|G5a^S3>=71698Vs@@0M z-gp94-vDio?}Wyu12jE1LDRniG<|&r=kEgyGC2_cbb{;00}N~OApFzd^5y_TL?Oif zX(k~59$>f=4Uzv~58^X0=s@eoerR}CK=boSsQe3PduE9fMEw(J{o@b~;WJExm>&x* zKU|>oxgn^$VPs&q11;|kg322<1_lRcdulH<|Lu7X(XS3}&m3T=35K}OR1ReR0frnX zKN(tout3Y#7-)U-=L-C$zi?f%4CAK-`-FRqqJpmq7W?!R|f4Pypo@gXI|*BB1W! zho;9Tk0ItigO=|Cb`X9!v_BF6weOY!$UX)J1t|X&H2gO}^Z(9bNcmm^E$Yfn$e7-{X#?bV!n0jf%Y#-q5VA< zXn(8~+J0YC28rLtVEYa*+$e|eQ@9}d8TujStpV3}2N(|IL*!RM(??DrgkJ_OFAgwV zh=uScLi@i0(DLOrw0-nN0V1CWt*#KRt{?s05`C|u7?*$(q{tJQj?>N#Rd_ida7!nQPU#f-J ze$pp!IbZH2p9@`yK*u+}LF2y#njSwv+Y57`<>Mu2`{+ywB!04>{qY~w5PmKweAyTn8ldH6 zEY$s9+9C3ul@R-CPC@v5(DZz!2g1J!EuT3&Anxyk>fg`{kv|Hpe>I@;z0mw20p&Y@ z`)>yr5|SYLS-}0%0}MCPAbd0M_`?B)jBE(s0UBNg$q;@4v^`V;4KI0UdDih6Vm}A8 zz10HcXG6y)I-u%TK+9_hSBQCy(EPju>c41kdBDK%2AaR~q3tanXnwPXhIb7#ehxw7 zdkzbzWMg3Pgoc*_w7t3-TEEKpL+o1stxr6l_16lhdo!T@BW`H=OM#{rFKGFk1C?J3 zO^*gp{ntt%@pS;|{$OzZ%)pQWZBN^R`ZF913>DDv-v`j~mky}^*unKZ1H%lce{Mm? z+Z-w&;mHdfAIpG_XV^jIGvp!u$%677cp&^+(DGIWs{f8L#C<(x5cy1Sdx3!=W+5cJ zra{wV2Q)o4g6bDW28Jz*Ao81_OKQ#dVK2O8gNq5d_1$|u3v zv(WZbG_?E+I0JG2K2ZOagMncJv_7~9tq+!{LENJN9j~l`=I_0(pzu4uFb6u`)d?Q& zJHYTq8)9A*czp5z!xiXw)n{;f@&JRwBZ&NBsQiOj5c8eD_8nm02!Qb8q2}M10pY&} z*S7~4JnA8Q0jPeTE(l)@s(womgue-@USkr3e;XQJB7G41|3l-)0T$lS`aK64UnZdN zU}Rue0&TC=LHlba(Eiv&kUR$i!whJ6O@+3X_CVA7o=i~qFffEb!=DYBKc_&$KO0(J z2|(-9IBdY=z9U%>$4 z{~a0-{Tk5r>zfh?-(nUdJkB;l_!?6nd=F^;y)qfX&w;AfSP0?kgU3r482-$K@XewA zO_&PdzlX{{m=EFCLF-=)sCgOC@VWza&nZxQgpq+E0xI7I<$r<7N5JZ<#SrsmL+hg* zQ1x@5?)QO~2kW5jO@Ye4h1MTBQ1gyM`7KcXH?aE-Fz{qR!YdVAz8qkfkO|@6gz{?= zApB}uNO+wohqz}lG`<+1<85rv`ZECZv%wU7$|2N?NJp+RRv_9Pq z4gV9+^l1le?>&K*KW5PKKLpxd`3-K*GccGy%g>uo`8UfU=I?{@TcGL12U`E;K<)2` z>X(7G7xbX=Jkb7+FVuY*(EMKm9dDijt>2xY<5x0&A^yvU)*m*LAogE^)^`klAo4BH z_WK1j2wx6bKd3<4->lH~-yLZ9i9zd^1JLp^2iiXSvkantDl|StmO<>3hq|W%I{)w( zT>dgJ?17H&h(Y`FBGCGf4>}+8qzqzSDLDNeU{Gj*#P=C!{{3lyu(DvaG=y)a%w7qs=Bg8#Ip!%4Rfx%!4gzwe> zvHt)IM89|qgr9O7A|DPN|6{lV;YS)li>f3OGXBU zDNz46)ACzyi z9isjfxc$h$@MR6eKMy+~_OB?1$mc`zUxpBbe^D1AzhFK@{Q@Yz1v>uv3Yz}+K;zF6 z8s96R^8t3y^mL&gqQ4BHavkS zcnEFp9D%0q1JLrvVl_mb59;3!w;=kppzU=Z=zPgMX#I8oTA%)arq3zR@zPN6cnbrA z1H?FnQgD5|fZ+kC;9y{2*aq$YhFpi3Zw=+|DS~KFhL(>h?GXN6X!#ZZE#JOD`=ctq zA^JhhOi=oCQG&!DD>Qx;L?QfV(C`+JhVTQS`8PlT!Us)bgY+wWf|$n&9Y6R0<=4UL zS7`pKh1O3tvJm|x(Dv~h==|awXnYh%Lga0r{0s>Qe*rXq9+86ZnW6Kg6;S>$X#aNy zG(D_@mIn#}5cP|p{@=3z;@%!ue+4?8!~)IFAN(QV_YPYAte6Vn&xPh+7ijtyhSn!@ zZbRfRL-lWf#{Vp6`<@3jegvL>Wnf5v^1Y$scPpUfizKxEeF6=?8fblU0$M+Rh5CO2 zw0w$y`u_@4-VPey4I&W#PJ{MGA3)nDE1~t(1zm`|3N-y{KMa1`cR@5?Wj{9D$a{0?_$oFQ|SSsQL@g z@bQ8AHy`TWDbV!71L{8@txpSq+GhbxU+mEN|0&S+M?G}>WC4`F5h{OV0>uA;P`(XR zJ_pM8fbzMZ<)aEz{ViyF>f$chdt2neFCk&PeIdHL?J|dEHr&g$%4f1GN^n&K7=1o4XQsF7-AwId`D=0o&Z(9 z0-FCGyodPT3d+9#ZBN{WrZ)~~`H&6GpD!{Y<`qNDb0~(m#{}B`doc@Q-gIbxLI$e- z6ErYi)R@c5Aqk++1J*8}ATg8NGc7%ZUkM_-`)Gf@5% zX#K??4Y5xQTwg6<*kK0Y&jziBVq{>Dfc6JwL&tMOAkqxSq5TmFC?7P;3@X26p!_G$ z@c`I~vxQLi3P9zrK;sYE9AWT;miIBx^3;!(iz&pw zQmA`#dLiL!1FipVKppfBYX1vp{T&DmuRBn_1GM~Ja}r`+Cba!-11*1=!0ihL1{Uai zuQIfK_2&>o{aJ8(gMoqL1cV;}ZC~eHgYb7i%g>xk5PlytJuHFpKSJGO0_7V(%jbg2 z5cQLx`Q;8&ekZj3ngT8V`k>*x0XqM844U61p#9}j(EKU_?f-T{%SRQcydRV=1C=*~ zmPa;F`E$_zz6X?l20DJQ0XqL>2A#jX0d3D#LFe1{JcOiAR%m@?0-Zlt3GGh`K>I5^ zQ2vB-5dWq^`7BWWL1=s!K5uaO0|!)oAC#W~ z<)?$nL(T&X2~hR!p!$>Z0K*9=e-CKA5GMlz1C+lU)E_}wKg3SgVx+@GYVs_QjY$`1w$N0y~6%4(i@NG7$bgsCfcK z5IzUYya)(i3aUTE0m2W1@_mFL{4G%P&S*gR^P&1Zp#8O%S`hc_fwo`PLFHAT?VUns zdu>4}#DC>b|89Zyr?)}v3xKZwTm>HQV_>)fE#KC9K+Nxe_WzDS`CnQf=G8;_Q=sD+ z5m5V5pyjO<)cs2;A?kyn_0I(8_(liRehWE>{4ywCM-{?f4Gq5=(Dv>UsCg#P{__tQ zAKKn)gsL}z)_04c?&*PshY?i%477gd0@(+eZ-I_iAAzPn&^kGg3#NkP85tNn>_I#R zhUrlK1<>^Kz=MGS5;G9_*=YQ|%&77QwNUx$VW|AgnyCC#H1qt>^t+((ozT?xM53B^ z9?ksh2vm80H1!M`sPfim{48};`Kf6B2}5(=lyFq_Jld%I=V5njpn~CXznRQvp*0mek2%C{o{mYzZIH%BAR>*n)^SXg|8Nx z{cq6Jv!S{7XcVe@ZllSsLrYH~X!a?fsqaTKuM|zaXfdjN$!Otw5-mNop!xp-ntirt z{7q=;m!i4f7|lJQX!ggVnYR!v{HCGtbJ5J3iIzT0(abAdjOzbpH2ys_|DQ&4KSO+c zl%Jtte0*_YUS>&VRceu;d1hWoYEfQdPJD4*K~ZL2Nt$awa&CZkauudxv!K+1{Gt+9 z9I^pW?O6318F)f13Qo>1NKFYYDay=CH%lxiNX<(@m}nLsUs9ZyXJ{HyoS5gFk(!+C zmYA873RaOBY#3iziRmmuLmUb-ixW#qKpGJKjV}UwAwIRJD8DGaxHLC6v8a+Ez97Fi zvm(B@AhA3zJ}omRH9j%9Br`v+I6ft{xTGi_RYhV+NfAN<;^6p#qWoke!6-kdPkanb zd{cAtiz^U_m;Q%hU}{DR{R4MQ@DQWH~xOA<>`U2}7DL9T@BF%PcHOAbpcGV#pI z#I7DiIm|HUoc!c$<6@W2r*MPFzOe`7cT2bOu>0j*W;*+18otlEp2qPC4LrdqP)WnihpZxU9wqqHga`!bu~0_NlgSLEl?T`2sVz- z#b%kIImA=2Fi9*=54;GK+B9U?p7Rc7InSd^aXo10hwk2O$y7#aBG z`xp2o7KG;ICKfm+=Hw(LCTF|)1;-m3Vd@AdDRL|-N~{ExJekQLRYr#3n0HJ`DM~Fa z4lYPcP7TXUEk}=EP^o1Cw-}_o*cH2Pf-}?e5_6#OZD{6FnhSC;B%h=f;m~F7oS&PN znU|UZw*ulfY$+8a151U(dDGR%1eA4>OG*=Saw?%#q^5uj$Ll2}v%OB0o# zz%YRDLMjVVv73P-;e$;A6$m&CftG?ug=|_;D%=XVEW~zbC|mmH!HmTkCzwvb)Pd7v zNWM!U){~b0d8FzHPAvgtQ&2SzDXy@)#lk-iRT*l5jOj@X4cN^!H1N-ZWO{@P2pLUK zkC6d9_h;p2=EawQD}3yMXcSbM=T?-O>XDzHUF;g*4G9EPC(u3j8@s2LIDwiJPO0gc zd2m-jgU}MxMgg}t3=Q0JN{cgGGK)$oU9q~{J+%Z>YPlCB=9T6o7G=WKLCrEW2b&NK zuIHdl4=e^583(79K=W>Xk$-84e;OXeMxKbujgVRkm&{^N2y(r51Un`K2bO z78fTLVfT{(q{RVhEg6~zrREo;<`K|hWDIJ}WhUliR;32yB$lM*7v;Jp7Ufhz!wec0 zL@M(!G*2qc%t?t)&d)2(EG|jSOGY!u&=g@Gq(OuwNDWOv1$kz2a6x7sSdj&&wGy0@ zUykZ3LqmvvgG&;VvyJ^yVbUl`)ErdA7NwV=YDFXz6VH;=A``#ViV~;_6y1gf!Iim5 z`Jmt_0(BP35_2+B5=&Bj^HWN5QhhRuVY# zeAPU-t%tP*;R@-0KwJk4bYqly$J{?JC>7M>fG9%sDrR|%SGgr5Gy5hM6lCV5`y^K8 zmzJ24Vmcnhrq1~}`9+yksgUGR3=Kh;rwl@h5|dK{5{pV;GN?W=bk5Js&CheoNlY&` zGz?BHaY;=}EX{$dhMHqaNP&?lMy8F=%Lg_3u-j{aNSE%ZC7`SdQ|FE9Kx5Q4mjNgz zLfUgspQ0!?0?GR(R)l31ff_{6mLFD?pk|YAVnt|iY7th|c->)S=vf?6RGR7r3aiY# zbX1G*YBe$FS9B&1r&f-6{B~e4J|-zg~STSoXoORNJ)cT zpQ(FliC<}MQfiTZnsY!Xc14IjF|?bSUj&Uhw6urK!=|pFAtI=HXv7$rhb0z)It}1_ z2`)4Yje=6kQj3aH{fkmkVaB5dr%`%pNqkCWPD*@63U(ESAvwjM!3$6Zf!c^_1Zr(y znw*oGh}|S3pZvs>)D%edf=8Vp$g0%hV$Zy^d{bv!##y=*CFZ8$S7YIlSdxfe2}Ud% z2bLxlCFYf6=A{PY7hv_V38)zJGCe;H76{!s5ldkTHnOv z{9?zP%=Em}6jZga1cp?Wz#EB>x)rJd(VVgb*NvXJ1v%K=25%|*CRPTemXsFd`IY8i zRcj0>Z#**d5Y21nL{J%qU!NgT{RA$t9I=~kXbLZdKqH>X*%sgwhfB33ICp_tW1)GV z4hSxV<_LwLW-Bgbh~bsA{Gx1VU_pb^6x`|s)e(s)5X+$QX!#G^5z5R<2P-#2QHf#_ z9x02U)Wj5!JBhHt1W6r=`N$Gzg&11e2Bl5Vpl&Lt@WpPWdn$B9BRDlD4XOlco1u|^ z9w>7_>R6~8YM2;;k=GzQf+ZbkXIU`Im33&nGW7+ovSxJYt5ynhv6npd2dhTTpBP|}68#0*V~ zvoj0g%QG@dQj0-Dlu*m?Mveuf(Ut@<9kcczS}R7qU3 z6jx%2Gq_2p3Nd?lhDPAt5qQ!p6|1AM%?E(WDi_F18+J`b2H>I|l(9XFL-TSnb2CeD zs02+KftuCefowvGO+X_`kd6{qJ-X4bvISA=T6h)*XCxM3x7^SerJjIJOoGaCxO!+* zKGA zCS?f80pQBd5R_k>ON)w9^GX7+t2PEtiTefw`G>eVhhQ@hRCojh2V;}61Z#E-_6dT@ zLOlUVv@S+aQPhCIRzbj(LJcr9f+S~1N=BDOWHPu6iWN9A19rt&asXT*%rzL3$8Z%W z_9Bl=A~j`;z^6}N;$s&9S)TnCDo&>|e% ztcP})eG?ICp{AJorj{fki=&ufh}><(ZVkLU3YUhOj7VK@85FZ|q%OE(s4*xb;c!V5 zlaSH~q`L!G1~UUQji4(r1!r`0QBXexv;qf|a?s_VnbVN?%n4Hpa}{dlM3Y4Xp9@R| z#nU)~54&P)nG|&CXSRjVKOLY;>esZwJ_6RnG+_CVg_pF#Hs|5 zIbqUJlM$&49-Js<<49d_#ZY5VGbhXr6q7JBCrla449qlwVGU9mfyzNv>*VJ_*OxKG zCxRxM7~-L;!_xEPi$Mzr7~<1G<6Z?Nuq9`pi9-;t6g^m&Fhd8HUWvO-xUP3n4Ab z%Fl}juK|R+JFPS?IX<-_vxFfYO5t272b#%(`3k&{4!lebA`0~rgj1YaQUq?mgO_!| zn7IW-`JgI^As)O|h9Mrju!aE?Y#__gy>9^<9SbN*El4a%b;~abhO8;e%u9C-FtS8i z;|TH~c(qw#QF>`^YF~Mdrp2*Vh&gxe5qu7W?peg zVopwcE_gIKJ~1yP9<(weJ_9sskLmT|)RHvNgb@QwLtbfad{us4YB5{{$}34OPAvfi z7ejnWaypcm6R%fXQUr1-c&#Fc0a_Uu4~Y`cT1r@Sf`*qNQJRsOn37t=5T8<7zz|;m zS#bbbI|mBI$aT4@Aw5oq}z zLwr(IYEeEzd`V()c6?@DT0Y2s$rxS_$ahUG{iPO;%aD&rVlB_!PdY* z$7C7e;cMLx-UThT06DFsI596iJwHA(Jukl~HNLnqFF8I5w32}#9+c@A;!|>pD|10v z3vER#Vz>~rLKC#K3!5rL{~Qt;phb{a3^M>P%JMG)<;;LG0tTh#CKpt?29yPOV^wJe z9}>t-%>^$@#HkeFy5h>>_!_I!i|QgPXf(jrGl2_;?`tn0@qYt zlv$DrUT%oZhbBR#dA{I017F_)Q3fq>Epk&#<1-SAGeB!hP-J{elJZk3!7FCXeO*lB zokJop)EF9oWFUiEI8>rm05o1{25O^$JqunH30j_pbtNTu%^i5y%rn?H-W8O5P`nOX z)C-#QO?5Vc_zc?acg@VK%*xHp#iPLxj|SA>0F8`-3SRfb0?6f7%7FlHm>W^8v~Vg-OG_;REdozW&IY%1(KSGm2CO?^XyBV)mI`qP z$d%xnhM@*L;{k4*fqjn>gy_1Aj3K6hmt}kAW`Y)CgFQ=FtDzZGD`@2dSU+Js#->m` zpjF_=*7+BKr*Vih25vRT7|@Eb6g*a=1iF!dOMYGnXi_a0d6^Y7CQ+0cn)yO2W6+F+ ze_l?dD^wXY#4UXj3m~STNf?@W7Q0pyq$Zc7ra-!bFa@X<(0eVL1vq8EGNd8;GFGVX zP~8X*1iyUf5(KC+XdobxCRzkqLWkJ%i(sBd(_smUI7EcwRBvbwiZZ{{)D%cyyCF9f0=Df7$l1}* z5Ijc~lvXn4m^ONPicULW$I29t54%A?O1msLJ4y z{GwFCF0n*b?wDLynn{E%b7B=5nnBh~VSkHCY%T7dgd_Wr>+Nphb?b zNJdp`>{$$n;LM~PXh923M%Yz@hD{-f611#4KhL8yJry)v=bN7b+Rg%wVN~;BVG3~* zNNsUQzJD-Q;|*zCMWYr61b0J#>u1!=?_+2RTHlfeUI2?!<6z%&1F2I{!UJPTglRBr zG8VMf$}`0^3!5%PyDm317qsp!pez%cI+UhjQF2BRsM&;7C5nlt3Zcc8p(!K*`sKqH zX@gd-BM)f1=3+G)vHm8lq^LA68B_pcRfyPx25NHWWaedqo1V#7yk=w+T$)r|l37w( z0_yaEW(dO)b4np?RcsmzEkJ4@%Q}lZ^OAE)Q&P>`@{4j4OF&H-%%o~)h^!&kl?26^ zq$m#XP9{Zp5-Ey75o8AOGh}5TIAanp!30#8BF!`hU=2=7kSd@2ymV+a2cB@osuWZ& zC8i(@1h;lmum?IwZE-4k9R_I?f<`p3qy$4mA}=l}$^& zNK?TH3Wozw)@4EV=wWv$(%_zUrByeU3~1PfU35@gWaF8Y=<#o16=ZwX$Ht zcx(}e8YvL9$+*;l7Da+Lk;406Ze_W-NddXJuE7S_jrUC~fG$Rb)YG8;PY^bTnEECb zfT9qw>C-zo0HP390a*Aal_X~7L1!GnGx4C9!Ll0C)z!5OOY0;cBpzxcN+oDyl3NKM zrUH$BfySzeL0b$!gCM~MFikLb7zL#kgPLSu7r16tf^EX=e1c*t9@2CL@3%$ujG1di zNl{{Q38)D3$}I>kaK+{{A7c|p2L?8A2JJzh?mK~)jN&JZ@n!IC2`mbYLG$rG`Q_j> z`%u$UeKYgG%L759l&%m>uq6m^4}tdOz~oS^#mVOR7hhF z9KLYD{36g0MKM;B%|H=Wl$l%tY4wHV`zBUE`zTQLXp3-Aib+G$@B z6Tk~*VfvuXfb|r?{XRrv5xL)o>}o983be==G)4;5qD9uSMNd}YryfvN zCRk<%8-WJO{DO_*4UIuj1+D==OOK&WLkn-vT5?EmLvj*S8oX*3lDR#=_QY$1v1 zsD^;|NcbmZr6!kv*7spmW9e3!m+YEXQUn>IL>q5HiBn@}cMmeL00{%s7Bq@-bMSIn zw~5V)P*U|MxYH- zpn+V_WIHJOQPT$IC<;LxD0A!1h9sL$NC#pp9z6C8G2a)Q`Z3*aWE_&14ocDJi3Qc0 zh)G#cIi6Vs9SXtP$3@9uhQ{#q-p=3w0W6VX@B z7Y1I$;+OASl3(PRT+@c&32XcLacj&&W0% zmafg*GC||)h~0{=f|j_-50cGLoM32- z(nNL5CCW5N^22fp2$I`fT|r)kOb9Z>XXYoD5=K^E^VphKxv^gs^u_Plt8M?)m$kNIHvd-Hr zvA6`(xysD~>w~2o$hbCiQ8OgkQEO8)^^j3>h}Vfw4lzEUC>7*SBGj9MhuH)2i%THG zH_6#VXflInDoQ0m55ymkrM`HqKuyAEr)_|yJKaFZ7|S{_*DTkpEJ#q}H^b01fCw{S z(FKhg@OZAXkt@^&tg?nMSycNG%LYKp3qWHgnb@3Z37<4C&P)f5Er3UHv8Xh1aj{5G zEdfV?D?}dZ93R-BL69aGY*HAa2G(6fRNltvsU=VY&|C~|C4#FTckD{AFAD>AKq0oF z8i;6wfR~CuEyZ+^C1}M8Xb)o^R0*0f5PyL>o1lZ042>Ww%ORpr9nhdKG=sM^z@7n( zn}f3sEVCFiuL4mA^E>na8qkp_*m4@GVk1cKL5?{gtlSu!?m*=Q?g9p4 z0cyB_&XXuA2`)_nEpbmR1|4RS9N-;n7$0mLpP7kG2g0A_iJ9P?E|~$?6dD;qHnlny zC1-%zuFeIe;FfJ>CIjZ)9u!C6(Fy7Tpr}PUbtk2?z{nMwOAN7$vw(`M0PkdM9>k{F z&@}*uYQ%g@aS3$d2CJ!vU@I;u!lw{Rxr8O*Bc^H~*5;Lh)(l~_*%Z7xz%Sn=HMPJA zw9yH>PmB;27iZ=cjSwy!8Z7i1@RSy%wb7EFbP;KA^ae5g9_ zvRoVr5pkGV3|{2tirqjY$3i+hpxOmgKN`W;^<#8~l3j5ahEzy{_RWA3Vz5y>wjj3f zFG$S;`y#+Q8PsYw0dXMH#NY`fY?_P=K}~!384IZ?{-q@ar6sPAD1?<=7^}N2Ku5xX z4_tvLM9q~5M}wE4LJdPzL*q$f$Xpaw$Au?mmbm2?K_|qpI?f~*w1(0xzsNT;CnvKQ zs~S_7n&8yr{Ja$GiY%aOJ%URT^HLIvQrvK;GlEw%pxGmA&NlNbhPpVYG%pXdY!;g; z#MCTk@fTP@k!bpbTQy~$%BO$6$)0wGfF=)g)6;hR^reO1pk&6rbuvAdSF>`T2+xG^_ zzJ{hQE~p1TVzUpnc0U(#NGD{67(^k=8>svDoQ8%a#w1)NhD;-M6@l?QSfxB&^>gbwGY=f@|Otmx4~`K+*|Xd<6ApVp4H_PH9Ohc!f74 zzDjZ+ONK$c{k+6nkfGocPe3hw$l7$MC}g7q%ptj;)%I{pz)>1s1X|k&7Xu9*pa~&| zL~?#EX!(D9YDIDeiaxj^W21P&ip)&#n}A_FXyHHR`unn6@EZH#oXiwZ2q0xK@U{w2 zYD~_K2Teahq(Q@f;E|N{(!`<^xS!MW<5TlcxX6px!BWMD?c?BW6s4Id4DrwgG+3Yj zB!IFBBDDm%IVC;~VRlg}C|(hKc(9q7#HXc}Bxl4YreKjZHo_-sW)h#1pNL%>iUcTf z;l75%enB!^03;ia#E0y=KxEDI)RN+Y)a1;xOpqS5!pXH4w3= zH8zFJ4?6k5ZJ%Lr3I-)e)-Vm2rdnVU>|@r5LAnO4UmOzVgcCeIIS>&y9r$# ztO7LgO)P-)e<6(kT)~Ys;0(bBoj@Z2mm`b}L5=|1j~cN7-q?~2I8@*P0@mh=Jqe&M z6f^=Y8-Vx))KPM(gf15(PPZZG2u*};*DS2gvjq7CWIE`~*WAoZtcrXL5orN@2oY#O z3Rcge4AC2!CZ?dQQ+CbGO#)?1%p7Bgsu6TvH|Sso@Um2ABRu-dKqqm7+AJaYkkx0P z{t_1Rkxra6G=+>VfPC#=o|jq#-eV79r8wtH(?QD!p{JKvfN4lU z0xD8)>$334Pj>^I(*!zw3^GfN)BMbwRM(2k;u7#E3pW2DxxlahbfR56ct;ve19KA7 z!454lG)w~(PLN~raVSR_sQ`5{uqG2DM`#-ek1Av6I6!b^aZY|ZcB708 zz>56yQhhS>QbY3bsRbRh3y&ZJM0{d5*$|YHd{c{y6Vp@u^B}b#c9j-EiREBdz@=g3 zCbVA>oLU0P7g$COu|_$z@i9|yx`JDP+M~jZd9(aHgdl+L5X@l0}L!t>=Sp_=jwHdk+E}-Blt28XHdt>CqEsU_He|xsb?`L>jZ;#?qnk%@x zhuMbeFxYGvWK9nA)NWAHM0F2}@kUTNh#t^79s>GMaxM|O&{6!3G2CM5m;yW5Cllf> z6!TGA0PtngAU_%Sf>SbRHo!F?1B+fG6KK;Evd9Gz(~vj@H~+9`0k?Y)jWH}Lkc(hT zNUi`?!U5jN5XI0)h9?ow5qPl3!kRQtv>6$Of_mVf(;*?wg(OU@i6k=#MXMonvkwtE zP(s+p&hxWJA-1H0DT#RaU) z6`LuLfOE>v2Tw5sK>UGXkD&>8HV-^C2|5=Qv?u{t%n!7x$S2d#)hE-)z}3|_ptJxVLeFD*@$?hh9IT6iJ*7e51f{Lj#22t^sbO zn`ZfT0{a4Rcw#jYNu zaSd7-32icCSB)GrrjQjIsYQ^MFgSR?i2|G{pn{;{9EZ&o&~gOS^9_dF%mxlGLu_$q z3JTByP!lqsC^ap!0*^}gOjvPAQE>^_S;5%NL{^E|l7l7hA!cqt)8)kl;4M|y4K)r) z%`E^efCnGvPK+~)QbA+oxK*O9mIAj!A=S5k8YFKPy9VTf)?8roCBBpfx|j~B`{C+} zn!d;|4rK_381oEqqylK=0^=BU`b3ypn)7n z$U)4{FL2CDamp_#$uBYs?Rbk*bmmt$E^yy@D<6gj(I5|ImJ+41{=h~jE1e+0-d|! zkyxCOTId?&4U&l`umFvgfqIHKRig~LA<8E3VTzztG&n55tIg0g0J}EigKa?P zZ^3V2atkO6Hi!r9o&(KTCFX$UJyl#BgTg)i;$0&`g8jgm9@c<@c9OuW11()rlSQ8sPZu~25$!dH6`NnOH1PO)8cc%8wnvsLj7l)Tv7oMK+|o4 zrBMZ5ybDnc)$U_xo{dy$KpOs-jsZ2AAk6McVjid5^Or?kHI@NSY2jl09&mI-Pi)@AfSX4?D!T)FAY3u4l)>RV@_sLQUK_N zInV@FN`5)S1eBODb1VTJ$_7d#Wmu%aa|FTgFAyZ|< zC^Z3Hut|iGCXj|XWPUui6zrjpFnF^EttSKyd}zuuG=eNHf;Jp5!!iimmqOWm12!IR zICPgM>{wJtqJU<1==ekc9CSP(=;~C^ zK~PB2C}C!3T$-1imk+v?7j%>!!~hf(M&Q{w$TbB>w=_W`5?KW7C=|VhmarBpvN~|c zBDHIYG728>#>$@O_L7lfbtc#DiM9@yVd; zi9t(5vBa^DkrAkUm0Da(Sgny!Nk(b_=pGi(rFe+@Od!U>d};_<`G#B#A#KJ52QO41 z>?UUD)ncHeflH-tD)``H(BbJI!#z`SAp7NTsP{24ha9p9UNQt)=N?~>lbD>Ek)H#) zM+n&wK8B{rB^8*`Xu*l-lRyd=4C7GMTY%T+fNms0w#(2EI&z1oV$n;(;CNW5poS?% zQ3L93f~#xD$PiXtK8BXaZHJ)5YcmpBm z2A%-)gbQAk3Y}JQ#j;`?8sUaCunc)EA~D7z-?ivUz#|~DQQ{TrE^43Y70a+xo#HJ&+uUT9O!A z7Q?$v@I9f}6dIYJx94FyNU^H62+mI{2`VlIA28xtk(`>Eg4Ev!mo6v{F>-MM&t0d2 zTnh<*hMV9cXAEqvljrfTr zsd)B1gSIMz&hiK;O3W)xOD%#Z1-TMWg<}ZXgpvc9{RN->0XlIDG-HN5BMdeJmIR;; z7-#VA5>P1uOYV>k9o1v+DQGPjO-W!t4@mpgEU6TOWXGzHGhT!4X;BwGijD*xe zhpOG6E6WKew;)oTp#i9M3hDC^FcNl%2dH65P$}4BA^8OX&bXAKW>CXq@U_5@MRoBh z`FSOvd(FTZCL|0k31gWU11CHb6Vd0}3{8+O$}9yPkPS-cxQv3PcgVOC=zslx~>s?nhn^AurUy*dhiJ&#HdGaYl9EC0=Wx1at~{RgKY)-5$Z5>jSwfo2Kd8rV26eElb0*W$o z6N@V0llI_sSl}Q+RcHj+0Y-#UL-XLoJjga4(0#r*3`8DBf)5lKnmMAb#D$h)s8cqW zt}`@58n46RO&=qq#hE!d`N`lmIk@!?Q4LKFi25F>ca6R22X+Kho1uwIYF=?_a86

    %nIoCaW&Z&=oFqQth3 zp$UAl2T~`YXFsqgxClnkXlUVCjB$t!s6K;Tw1Y7sK*(T}yk=+&wii5Ti)|SZIJ8i7 z7$GfA3Meg!56>*gfJ|;fTmm)^(;sMM1h_)NW_WQ)enCk_YI%N9P6}kJP*HqAL1qdh zP*7cBj8!pKwHQ^4VRk5FXccq|B&I_QEnrj1pzF1vX#$Hf6VOr4;KSHJ19(tZLbIxm zAxd8x+LORE1av!~A#^kj+crteNgC{C7(mTH-BSrlE0{Yi!6rc6X$ZOI9Wtl{=}y4f z4d7)=V6`YAk30@)3ND7QMUPobcDLZ#8149|Z>7NDDW;&V&mA;#cTXJlAhnVXcKlUbEo6c6oLPfDfDBN)fM%D$w|aoX0jkOZqzcr+0~cZ_N-&BYl+`M^u3+2nE6OBB z5h!YiFe?dS7FvOWZ3#7KAt-nh4zv&pRI*yYPHh71wSnyF_XLFq>c|{c^O2^)p-m{z z5l}^?#hGQPpc58BH6l`JTLfwtxDqr8(yAiYB&3p0?o!)qYr+txarI7)em5xP4iJ(h`a%pU_A^a=~P#Kq>4B9D2<-kQx1x79|prL%w zJz09DmX-{VE3@=W5KLnP(+I&dL@*I76AQQj#t5bnf@z3gB3NeTa9ySdrU`;+j9?le zn1%=@f@NlgFblynK`@OGOd|x-5Wz&SOikftnIM?P2&NH&X^3DVSY{@0156Q269m&3 z!8AfJ4G~NP%gh*I7J_MlU>YNsMhK=Mf{9?686nIYJZ;Rcu)z?r59rU`;+j9?len1%?ZB|}b0Zh-|X>6%)?nI;IPF@kA?U>YKr z2$rb@!Tr3_vhV5KLnP(+I&dL}J1XFf)KNO%P0D1k(t?G(<2h z!0FW-kzV0U6H7SL7{N3`Fbxq*1k2O{p$ow@LNE;xOa#l!9Ind*!8ArNjSx&j1QWqB zGlLsoieQ=`n8paE5rS!mU?Nzirf{=N5KLnP(+I&dL@*I7GZVN0rU<49f@zFk8X=g5 z2quDMW{fZk!8AcIjS);E1k(_~M6k?^5N08mCJ3f6f@y?c8X}komYE^KECka8!8ArN zjSx&jBqrPdGXpr&1i>^$FpUsQLj=iU>YHqh6pBtWoC>p3&Au&FpUvRBLveB!9=jk zj1Xoam?j9OF@kA?U>YKr2$q>4!Yl;S1i>^$FpUsQLnJ2L05bzP(-grpK`@OGOd|x- z5WzG9Cv#IoGKVuwEa6OJ1k(t?G(<2FEK>`(E)xXP7{N3`Fbxq*1k21EZh$F*X@X!H zBbY`ArXhlfV40aA%tA0t5KLnP(+I&dL@<$A2(wJ#OcMmt7{N3`Fbxq*1k20>Zh$F* zX^dbRA((~;CW2*Vj4%MfG(j+p5lkZl(-6T#u*{4QW+9j+2&OTDX@p=JBA5u4sUh4f z69m&3!8AfJ4Uw2|U1kPwrYVAHf?ygWm_`VuA%bZNPS7TZ1Py1JSi+gc2&NH&X^3DV zSf&YKr2$q>S!T^$FpUsQLj)7SGBJUhWsG1NA((~;CW2*V4A*6f zV45J9#t5bnf@z3gB3Ncd2(u7O69m&3!8AfJ4G~NP%hV8VmI;Dsj9?len1)D9xGpmT zIMWotG(j+p5lkZl(-6Tl0jFtWM4E;(O)TL|V+7L(!8AlL5iC;+xGoa}(-^@tLNE;x zOa#l!9BzOqf@y+a8Y7rS2&N%|iC~$U!Ob#3FpUvRBLveB!9-%2!VNG*Fij9lV+7L( z!8AlL5iBzkxLGC$rZIwPgkTyXmYNs zMhK=Mf{9?68Nv-PMKDbeOk)Jo2*ET&V!{nDGk`Nq5lj;V(-^@tLNE;xOk@1#8-fl{ z2H!<*1WxTn3^~pLo`!~&@kWSr4`-TK!kNYhrV)Z^h+raErWSBrCJ3f6f@y?c8X}ko zmYF%+08<3h1i>^$FpUsQLj)7SGBtynWrAQDBbY`ArXhlf#4?2&V2WUxAehDorV)Z^ zh+raEW+rg6Ob|?C1k(t?G(<2FEHh)c0j3D134&>iU>YHqh6pBtWoCph3&Au&FpUvR zBLveB!9=jk3=w7_m?j9OF@kA`#DwcIGk`Nq5lj;V(-^@tL@*(V*btJ4jV_Sn<#iYC~AMH?f2>jS);E1k(_~M6gUP;JQo@Ok)Jo2*ET&FcB;> zbGQMf2&M^wX^dbRA((~;CW2*Z1~r%tA0t5KLnP(+I&dL}tPgotXi`ECka8!8ArNjSx&jBqq2VH(5T_&0s7;0~pK5!UU?$(iqAxG=Z^95ljTj)B>){1i>^$ zFpUsQLj)7SGBbx8V2WUxAehDorV)Z^h+raEre<)nOb|?C1k(t?G(<3wSf+3TOc6{I z1k)J7G(s>95ljTj%miT;f@y+a8Y7rS2&N%|iC~!-Bg{fDO%P0D1k(t?G(<2FEHfj7 zSqP>Hf@zFk8X=g52quDMW{5Bg!8AcIjS);E1k(_S2{*vZ0M0Z;Fij9lV+7L(!89~5 HV1NPu%V!%~ literal 438936 zcmX^A>+L@t1_nk31_;5*z`(GAnSp^p0VKk}Aj!bMAOYe-xEN$c%_6Ya38)&5Bo;8A zoq>S?ggL=H28Q_flGKV4D2D;W4{?nMLGWQLjkyqmK;|(qFfd$5WnoB>V_;xlVQ7G< z0nzdCIhiG?MTt2UAReZ9aC0Ei3?CLSGeAs+2tZs3VS`Axd4^^nE<=1gs{1}b-L(NM z%fPT>Au|KA8GKN27!@C%oS#>W@G!c03+6#wa{#I#V-Yh0$iGl71{EKlR9uWC8XxcC z7~+T!aDaw;f%rVQARC+oiCZKtLwtNnVo4%G1l_!Z`4IOtBtX5CtokkwcFG!|$N*%gxQtgQy0@FRFhxR6^3-4x~VX z*Z|Q1PS6l0m;{-J8Xu_UeTaj&2bR`%B(Z?gOF|?ogFn~=RKf_9FQ9pbfq|O=f*Ba} z7#J7?7#J9CM6)tTI70j-!N9=qVGb*U1{(uI!GBf;jm;3%0Z=19GBGfK@FOM$hRduB z453hQQm6yW@z)4p28M=9AT{!}3@hb18GeG;FwDTv5CmdBU}jv!$k1?!iJ{>V0|SG| zxA46yzxXq*{9DbmQeK5&<4FdF5Rf^4tDRPU@poMLE&T8bkiM_XjH`qd7$(LuFnr`- zYzPuzY?_tG%CJR@fnmZ4CI`#?*34I5Ffo{NFfdHuU}Tu6$Hq&t zyBHWu7#J8PFfcGoWME*J0@B05$Y2T+V`OL$0*Qmn(O_r@I>E#MHWOr?JR^f8Ox;6f z(N&L_g;zah7Fh*SufWc*MT29;rHr}TKY6fU`_$q4_7g`7!w+=#gUlhuU7`#O6IPJn zACMk={#k*;Ka30v6BHR3CL;R@6b2yog8Z%U^Z(Wd%)(&5g5nK5&Kd+5wtQx0ScM)2 zDSh!j<}+}-Rup0g`NGV&s-B7ACnF=n7G(deU}7-I_?L1ygOy>61p|W!$WCIyNQ8l5 zLI*UAI@lm)cyKao2`9mf6-*A6q=Xm9oi7*}wr2cGxXj7GFhP@%VWM_r#t%?fX)`ix z$*K#voSm6vahid_L<1_W!NIVFDKpE$fq_8;mVP)q8-h9*78EfuaCC#h966nU!j{-D z0Qn!E`#aF$n;iFhFhkrgiO2n*JOBy3u)I599xOe}5=Qs$U(DS7VpPtNSuJ~jKk{RC3`-Ff?3xDeUmmlb_+|OLm8!_KXZ4rI|Zt zi83@y`oqkzDuY?Ho0HYSaw{9d#13|biJAZZn=W8un27AYtIP~r_BSznOk!XN0huSt zz#szBC(pp~`Vd%5w7Z^}<26j4mw`cK#jEN`na&Ioxf~cKcE7Hkq|jQw)}hsYt!5*` zM6X7MiP?<|9~1xo582Pe@%jJ*Lr7+Jh6QJah6M*J!^HW_9IqSy{|DP8pJ8g@AkOgf zB{#(F)qWGcf!NWoGz^ z9PhuG8Gd4m^DoTOt9~(yu6pqSQa1jr_E`DF-+kq`aJQ8|;$2t%N_ScLC*OJHe`ltN zpgaI7^FZ~~H716MKbVDAfzr}Ce`yBG z|MCo$|CJdm|En`t{?}%({IAbo`QMnq^1nHQ<$r4i%m4Namj9g@EdRSRSpN5Bu>9}O zVEI3o!Sa7NgXRBd2Fw5P43__s87%*&Gg$u5X0ZI9&tUn#n8EUYIfLc@Y6i>y^$eE( zn;9(sw=-D&?`E+4-_KzAe=>vR|LF{t|7SB;{-4ia`F}Bk<^Sajmj72XSpHwnVEKPD zgXRD243__QGg$uL&tM747b~#jiHz_6w}8?sDE)IHrT<$@owFnv8YcZ_=2+#yED28k zmh21@Goa~TfgLsd-(+UkV&9CK{z3W>>0h!t9xeTAysn<)2~Gdmc+$T;GbH_cBBg&& zUP7dQOA7|1^#5y!xLrQO(t-h+{yFM7G=DNX{Imz9|5yJp(m$w7gr$E;28N#^%nUz& zFpI4E!YsKe^8bJFFaG;h{;g(Q2`VSi^A56JVFreuptAjMwd2Y!{)fQrH4X+QEqPvt zPY)OvLY!C_w!C0wSj8yHVBy5V@bTdP{~@vr3?g11YA10paCOTwGQ8GgW(d)&ahR;B z$hk_>k#m)1Bj+k_R)&kOm>E{pA7uD=n2{kQ>#xgYZ&rqhIWOxbaS8BrEAVpo@is6_ ze8$&5@v=i^P3nxK4xGD0jWi#J&|sCM&Z|);BvU(5)T7| zNC&9wb%K<=ubDYk;VOGs7#Kt{vyjSNCP=v}pJ8Hw9ESf7GhX}_&a(20KkLfB)od%l z^%H}HIjCNGz|6Sz0W-r|M+OFwpu_-wc-j|1(%VU}pFUYJYGrLh5G+ zSp6*T@Y92vVap44ho3K)7`D9NcKFHh*YPsP$GSE&c;2;yX1 zP{bwD5R_BOAat7bgL(H~_siM7wUf9Rxx2G7Gk^4`I!x-;<(i#s=&wUJ=?bS05)T#4ky`AGRRL5Sh!3u%X+8Db1S zAFv;=O=xPi0rivqR=chI;_tfhTe!>0|A!gD^}og+M4IEu%-nH`k->z6xgm&yaX}HM zNJEf!DT7cJ;|KGszwVd4d}}9hF>rNzWoG=yR&|(^rO7$l%g|xxtAGDZLH%M-8J6+a z^D+l0els$DWP;*Vkh2>kj$F2($2F+D7KX<2d@F{Z^Z&7|oNvVNbN(VmOZ2kaftkT1 zf#rues1E0>;SSbR6cOTLV3^>=$S@I9c7fW8@~jRY8JHMCxEVRS>ls}>K4N4D@vhAN zk^Qs&6T|=iAvv55JLfYpWP{4!Y(|Hl-T(h@{q+C8ctRq>#6(VqpP+U>%s@Xq1cA~Ra|MIY6J`c2bTy1Z4Pg2I%?uYo^%OK8TgtOC6go13@&;%uz~SdZ zWl*2L;S#9L{(#-#C#a15-^>7x8;~22`N-oDpP3m~fx-=BE)yfePlkK*QTh*{_9Mr= z`9bnL4xd16>6gr+tL#M?Ky7Jo9mfr7k27&}gVLHjBj;<5#?DzUnN3%L@+F5O!$iin zHIp7Ni-P;sQ<)gx<-$}xP<;v!=eRjPXhl}Wj|?V;pP;-7>enInpFr{c|1hZE!@BZU zI@`)0@$4(Vg>$U@;?KGAZ#CCSklQ&J9V|Ia7|g#jGprK6I6nv?1{ovaWMr@e^=D!6 ztHsFh6T}DgZ#f^bfci%8F%wW5_5hMQLFon*KcH{`(I=Q3esan-1aUGiC}Lpb?1qe$ zK*mWx@*Fk{Lh`;0h0Tl%A&k&*2L*-(P~1;>zyN6@Kz+uyekUz|Z+&0zc>T3H)SifTSm|KO`H1IGGj{iDYX2U^t3e zzC-M3xHLZt(r=PqC;@JB%x7Zw338(bBZCRD84Q`3KR6g1euC;JP#SCyV*bgj?C`T$ zhhb|olfzGCU52ec?lZ0wQD*o#orwWfm+h42Whexd_Z%_@E^#t61-(>eSP9DmpzxGp zXt*T7&~Qnbq2ZDUL&GI*hK@_z3`aiw@h{o*NBY30=?smR#2Jo#5@u)$5@l!%5@BEv z0k!R3gqLl4!FJ$NF%w63H8V%I1hY){%joh=nal@1ZDr!@{?5eN&C$?wiR0(}PcQ!e z|CGVZ(H+Ii*{#{oaEVj&z$Z{zJ|w^plA+9SQJzue^&?J(kg~`26Cvr!0qpK%Muw0K zMu~2YMuv+ol^8C*SkAEW8#4na-^0@r%)MWj7`AkNtGmp>aO9E(BS$yK%j!v4j1t{m zj2x%E8W}EfGIO5h`O_Yx$;i_k&&c_Dp&Ua<2D8X%j)(RWJO4Re*8EsE$&;D$wB|?o ziOPSSF0=e~zFg11^7qDRZhj1`91(h&! zbR&l=$lcIzo%rHD187_WYncB0@PCWucbs855gev09f&X$1-W1HG$&(I5U708{Erl_ zf(j_%%JA+#Xl4Z*kFYVBhua&$WiiyPmY}ktgMq=MfdP_tKKDZRMYQ*OmVd zL&iull^8B^F&w$%$;sKR%*b(?gInY@=b!c<(3ln|?}5@Js9eZk#D5ly? zsCpz%bFy>f}2ejnq?FaAs`|5h`D= zDCA~j2thWFBQtXcXKh0eLoKH?NDWwy1CpkM89BQ_ZIR4>@h3VNKx5*ZCszLdZz{yV zAR@}p5M;*C5EO6Ed==DI1nJFSa`^cIT)&I1+RDZtD6h&;=<)x52uM8R|NpHS|Kd+{ z{QJMP>>tMoP~YbPxV^?O1vah>%HQBTx{>(@vO7TjT0pQ1(QHw!O7@g`I3>r3^cY08Z!m;NjsStLO^{c5yL67 z4l;=#*#l`4IxsVsePaT*H$`CO3O02NObliqJHUB>lcDf114GD{XvUSF!%^Eqf2&GLusjH5Px+I-Yvr$W#+B&d3~Hx&aQxT~3Tsd}YH~7m zo4%}`#Q8CJk`_nUWlu)VRc4HVn>bkF}$8(eoGA!Gg=#2MaDcGiJuAxq;K+ z*8)b*Uof=}ETB0vrd6xCAnNA}hJ9*aVF+2xhu|x)GK7e;GE6LIV)*%DQ`Y5||Jx^N zD4v-0f=Q!GVyVNV|3(gqsAM)b=e{qhB z^MfjxIJz~W9d>fCG6-r!Gwjr0ZrJImupo#_VZkLXhBKd}G&yI3${WxB@h3c48Mb=- zhmGDI#_;px|Nr9J zj2x%x1;aiua)HJYi!Ptyg{W=#@jqlg7sJm(NNOH(qN-W&{eQ@QK8ByW|Nj?9wsRpT zL&#~UISk+ahwNu#__^-?e{pGsh9DcXa?pbrRt`$9s%A%&gCKEGIq2~pQVz!ahm?b$ z@{wby!z4)C#^EQIazhXo^MWGH%&Z-nmJEWLrl2~rVUnlf$yqO%HCJhxdUSEIHUwE` za?MUsW|){E45_<8b4sxKC?ml)@3h7 zp4U&<8A4Wn{lCSFgJH{RB)ROrMPT_Q91J1Z@BVM$;$+xTh($hylObgF+y7fmaWZVl zMv@1a?ZU+n;{E3TmQ`E~TM|HWfAcSUnbuCqV&dxda&`Erz0_e+JR|q(q>ukYIzQHL z4+h0K4mFED{twZ7RlnVffEv%2_1i(?rdoK+S^2zvJ1BjDw|3gZZSXP3@^g!(ZTzMTdPJ^7@LGAU^jF5ce z`1F4WsLar0Vc5EYi{a;|fB(g`kkZW(MurgX|NpmeF)?iUh9_KTVMXc?T^Pl|A*WMnT=EqEM#B^$%eV{_x}(%PEHj5m*48Qfx>q+BLhl0&|+lR%E?%PGaV>@{U5TD&*7&g6T=pGxx)l0Q@j`%w%|-Z zpgD`r_1mNv7(_tj7y~my$O=A&pL3DI7MAZ?7#KphnHaXbVqn-pjvJXj{14$|b(plG zO7lnSzyIR6>clV1%&S1_Z$Nb-sJs?u;OJ)JW!UnKnQ0ZMjFMz!m{!zTwRh7gV4sP)hZCg)8Wl@>oTm7G_C#uFMreLv_rlMFeBpJJ^HKQiRN<0(Hi z*nez?)WxFRX3)BL6&Iu~Hf0Rll*#7s^E9|F7A3AOW?=|94X%qtPl4*z1^f&lr@?hC zgzq505ONw^*FyLY1Qj{FF79&Z4=H9i1y3E z_y0rYK-({8-XqjxzDKBGeE&aWGE|KYlA4q65N({qcmG4WU}}CK%sKfTVNT-r{~_0) zYI?pS)M$Q3m~-&k|B$o)|BJtfg0zudL^14q!Gybwbdm$nMhanI5W%NU4BECj`7izi zCojX+6aOG>t1<%mklSP@#S!+M0hOmnW${BLhLCJENPWTh;(rJz{d+nwY(2ro@Y5cx z+)h+t2+@YBb$I?iF4at0a)xlpt|XoALy-Z+#Qmw+5FB zWV9(QBDrQWDKkvuz|p4USj=FF?0%5Fpf)8eJze@oeERj|Mx>_h zFaHhxHa>EEpr@zMA@2Svr1lV~AHgEP5Tbqe|CTHPhAq$0 zr>kN?yKKk1yY05u1(=*2BGS6lvXJ-G$9zDJuO{(Zd}RbSTT|64urgm2O&RR0p&FHK}(2+?MSl=X^x|A&Cu z*PfgVTTgH?{8ayoI%dPj%n))Ks@CxwMD0rsh}uGsT4>$?<^Ltj3?Zxk{@=pI!m#Bv zC{N)?(@uZ>hn)OWzwHr74U+y8W`+>%zyG(KVrJO#3?zp`|DxajLp*=fZ@UX>@BBgy zvsFL;Z|(evJFJ=C{|`Cx|G)U@pQ!r0e*WL8iAUezFaJXhg4~4EUR%h>5R%OV4aaZ) zL(D+=4_TgxAtW0bc8%Zuhxmi!k^Bn^FKt!^aCoVMF@s#&zJSv(EH{`SQ$dR z*%`KIu|f6(;OZwcfx`P;{Wg6D1`$&G=FLz4hk*KB$bEA~Hb`55P~Uvz z2SdmSK8BwY|NIvx)eVn9ZDI8B0cPUd!1=s>n-SCv3~UfL9Q}hBdx4edEuiriW`-@V z7{U8wL||hxaCy-B9TtWyub3FNfZ~BvKRDlpj31n+()>AP3{ zh-X~+Eu3lP7k}oJf2&#G^B$mac`;UoiDC>4KTja_k54dZbcrr?m~`LB;nM;phL96z z{o@YsID;w9aRw3SIK$s+mz7`qomYMfcUt))-f`ux^rPT$ZqRr~ITJ@Wv@InFYMZ0? zy(FN0D9-7?$O^5^&H*0>mRx0t)Mf{XgWBvI&~acX3deyh6S-z9 zDKkvez|m&cKx?yu>;<*iVeVi1AA6jD$AK6eeuBm;L>X|8SAf=s5i?$aFYL>hIJ!?j z`@JWk7-UO7!~P|7F7gGm{|X9wZ2cwB+!VI{5=a~r_Aj9QrJt1cmtqO`m!SR% z1o;bOFDUF`?%(tu_jnvAFPz}{vHc4((<)G0K*q)(^HkrMIaZl*gl$Hjp90NG!RDx7 z^HUux728+vGK8#RbNK1aD0V6bI*;YE)L{~+j7WgaV`YHUaN$>@0aC*UQ3IM|X=Gst z0h!^=!m!nQsl%jtM$XqSnHfUj83R7O6rV5E#ayu+G(YCa$mx~I#$YbNz#szRgXWMx z^JND}m@i8J&5eP_n#924c?Upz@c12spFqT183PAH2)?;8PEN#JnI<>G)>q7;t2}uf zf4t;`vU?qWfcmYt+AE-SdZ76*AEY_6m%k9>K#fRqW^0h<%si3i%pU%P%$e0Q27G!Y zK3~fFQ~h@Cg9Vqf7`eQ>{;-?({r@ix3g6eD@cmQ|4qq=uZm+E0?B)}YUb^T&D zpG3wy+({NhAKe60&ogqI@`297f#%NEeEW}cjQh~n{~?<}a~9C~I7d!MTH)ql*c#8s z@N*5Q4Fr`-gwDfh@i1%!&8;m$l52$O^M>kMI0VLc@Xfn{=D)NzW?kmmm~}auk?VB} z8$-w&c7`pl*%-Fig2EWu&I08tP}{VHogqZ~&HpX0*crCOgW7Ru@+uq*A*Wyc-_pgw zuq6bG{1Fa@knUIiw`g%PYzYE|>)-s#*`~FVvYEKMvt1p2>VWet&+DYm|3lnC_Ty;F zIeq>gVh@T>9Qu_${|_-|U=ZnHWZ0s!GxzdqX71D3s%K_#Gcs(|#-S&fl>t0|n+cku zhK}EzMw=V+dh&lOuJ&Ql8YCD(PJ!!m2w#y4Qcl0-MAYe>oQOJIixW|&bMi2l zyMp$sGCBP85Fy{~9y}G>Ib?`%yEMY>xY{utAT>z-apZyc2UPFC+9)fz5&rSwM)*gQ zkHI_)t&Q>kG{*&=N0b2Pr3bvQc|-`G0W|IiZihhl3j`QKKy7Ahb9|tAMDQG+6y_Ws zXdaP+9WsyDDUF!(S}6-^dx(MCA(=8zcCX`)ld{CkCoT}hvU=`Xzn%PuXqzQ|{2u~plYr{o?&tsE?ODy||H189PkGTN5p+(E2WgIR zCDQz%0=Q2jk$5$@Lfig5SA zFaJXhBenaq9wOYx^`70F6{?@-3qt?O&j|Y+KmQNe{Qti=%>LJp5%#b8%5E-=Z1xj` z*{8m+o691}Wg*GE`pj-FPr_WLC(>MI0D(D4iQ`5dnQDbD3g@cI^>Rn+LgF ztH=!_rW@Hcn)$`ywUJ+8hyjF&^Yb8K!Fr=|GM@5DZZWV^Dp!rEYP+bqL z3lpLGv{fMbc!xl{7CJtHb?(w>h|gVaCt>dLBo`w6q@bmrg<=dLXKvw6KaXzy4+%j^ zKa66K^mAGQk`B%y%}XkZLBVyBctm0$X!VQ{hgUW;Yd@TG7A=wB1Z^`0k*usb; z2dbMu@=N#`LbMP3-@+xpu;u^X|Khm%S53G7htz@W#?hxsy8S-{v<3v1ey7|2L-Ig< zJ|urV;bjQ%;b++5&Bw5%0%SJS-7vR3;bREtKKy@+7eB)mDJ*Vp0l6JC*UHbZg&&K& ziU32%>x2KdbO|tQ;RS^$j=tlfXa7T*K=$MCThp`uA)vWaTz*S>_CEwvXOPmz0`*rx zYg5`_&-3nHjdcW@6X^IwOOWcyay+naj*%g3M+9`SV|# z6#a|8LG*J%^&5i94@QntFh7FA#pf?>KRUnt9|D^HgpDmIGC{@`R^idZ{P};#Q&3n! z!zG20A><4b!@O7g&&+i3S32{`AMq?JzlF1|{Nm5H@^3Z!%H-<|TR?k$IXIcRxnEXK%3yT( zDbLEValti)5YW5^Xr9C4+K=s^^9Dfs-#IsCU4Hey9lYOxlTowF1hn?n(BaboSB4PI zpGB87WjVXK7|vYM3e4Z^SZVUZhr{910w;zL@ZKH9z)kZR7z%X-yJm4RT)6Z_xO3K2 z28N(*tPYc2G4rfixsq#D9-G6@0!D|Q{7jsuJ_?3SdjGfRvON>SN5N$dlOAw7{8C`@ z`}LN&V!HkI~_$A3MX=Oh$&Ed8`gU{Wux6=5adwJjc$kHILWfCm$EX zRwovQiODPs9~mqdLcBN}CS`s5zjZGog9ykU20#D9{c-Zg{}7NrK8Vkk%KuRh_Q!ih z0Wbc4?B@Ib{}%_jQSi_It)OtVXX1Ok^7sD`kX!#V3S>L}{vQHbCjnAZ_#2^y^Y{M{ zzC#6<|1KN2VA$dbat~D8g_9vhSXdXs;Nf0NCI68AVenQxh;R=r`CT=jUpz|6hs zBQwXUhs-Rio-#A7ddAGW>I5U_De=EWm*oY+K7rQwm@_kMJ#jGqvOJ^c>&MJ&s~$14 zu6n}ExatM7;HuZm46EKS3#@v}%)hGX>;Di#1_qH68?!DWt7B*6dac6D5Q47$It#;= zc4mexDj+?7^DlFl)=tV`;^^jZb@+K2RL(JSzXq+90>vq^dFbXeGBJdJ_S&I~UuR_4 za(!p+<>$=or=P1_pXH8}K92v*zx>>!c2YVMd-rn}ho9F$X`4a(HE1sms4UB4VAz_; z$?)^czyIRs;Q#Pi0(ES4o!{f{hThtgB zL{6jiSI#U2&5QHAPWl7MQ|S6Z=EKZ5$ixs*{{O%DbSB*PkQy$@Z~ljX%630ShOHpG zIC&U;qPqcRe|;(9_X&Mh2983fj*FN|O&6 z7(!kl`2|)^F@x5%R+{~=|My=!vyovUXe~u1W9O_A1%{8!t_&euAA=`(L)#dkg59&W zu?279Vz_YWm2lUrZU%;+HEa%(dOy`p@?+rbKBUMnF%dK-xt?+5LvDtjpnU(8nQ7HG zX698RX}!^7X0cU|m_@;5*h6KzeuCCef%c|z{)g=6@A~^+{Pl7MaM}2HJLAgC zC~V~;*Q#I4JmB*2@pi|RZD&#T}bOvg&0>j068HSH1%^5;K?L7l< zdru5!d+#fA#dZ!}h7f&ldru5!d+!7fLx?`Oy(e}GRL3u1X9&>;xA!1?P&-55U(sc} z?Y%>g_TIT)?BMk<>kk!N7J#<*6n^~=F#xys#0a+c4*d8ZVgPRMiJbzq_dx4m48ZL@ z2p_Z_Mvu|qC#b$OV`TWL$LjF&90$YJ_spED-tjvASjP!v_d5Q_`}Tj!1xAP;7IHI$ zfc!8)5Y}Geex3Xk)YfD8x$^&iagbcW4@5hV6R91z{(Jp)kbgk!!1JHk&38iEfq_VE zJkWX=kbgn#zy+WFhg^oL+4u|54g{@-fwco0KK>6m_y4~*tR48_Q~mZ0ham01^&i;H zLHn~{?Ld7{JMd7!Ww8D4+0Cbd+D?pOr$BAML}rE%P+MQ06X7qX@Bc&mK@ptV}CFluClgwY2ib&H{41ll`&pONboBRj;b^K1-TaJ5B}U;Gcz zV_*;gsds$!KLpfvJc*=ylwQ7nPJr{W_C#XNZ8@$qaXi6G#D5}Kw|e9*Ai}-w8YX1oaWV z|0}v&&djjo`rrJ^-_2?#l{1NVe|K~Ec>~m5VUl>=eB*xzXiVq?TKnlFDBKu1Uo-vw zA405s3fKOJ=y5vy1hsw4I2nF&{Rg#u#Nchghm6oVoCVYdAkNQ+{{9aEt?dT+7Ze_E zg&lq-vM_{%gVqu=v#&xA1DOAD`Iq@3#J?y1=3mw{t(}y~#M!Os>hSZ_QinSF#C4Q$NqxDs9*Ap8C3Ujulml+yXp%w zAGi(%>3hd4vg$3f_^Q{;QmbAui-G$rpz{$QF-xp^%iBB@lVlZ1rCQ_4GjLjU}`~Uj3{tI)Y=O`&T~=VMespqwdgZC{5;Rj zuvLSR;U}oQah{W5t3Id0Pk#=Et)R9<{SB9dNL>u_*McAa;r{ac@jnFQuLt7ur9OVI2m8yAiNWjQXLfT?KMUmM#^3+9g2LIJ zfggOH3&`#EObpqey7=n<|KcDu4}T%lfX;K_KTvSlo{2vjR2N?W)x`_}pFWDums0p# zzrEpL!DT@PL9dM;AoVTG{=&~l_P=L02d#rZ_Ln0wL&ySlhOO@p=3oBL$o;zM`~Q%3 z1_lvyH4l)~Fn|9aV$aF&bKC#_;>hYiV=WAzwhh#*=CA)lKy~&ikh+aomp?Ewt#agW zm;_3*hD?mFpKvpTH1INP3FKkek_EC8iy9VCxPSh?rH~gg2J;b%nj^dnAqt=VZ!zR! z*wT-~t`20GjJCaT_#Hz0Z!-oUL_`Rf0Wz5o7; ze`Mxc^?;do6{xN9gqdsALuQ^;&zLz^J!fWG^@W*v)k{W>Q)Zy?Xu+^gpgQ{+GsD)G z2lFq3>HvFiJ4IyGBWCthFPYg^yHGf>O9lp!m!L6p z4u?sg`)fezO+jOg%nTvO`aotP>n&qt*kTHub9sqYN52Ba10&aK(Ec@$o&OnGUctG>YqLU;(!$rj`Ionv)lMp967AmV z=J4|y=zI(&vDb%B{Rj8K@);PmYH%|A+zhgVk>ivpQn-P_Y$`LuR*-$fgd3=>13Cu? z7H$Se;T6gT8jFF1J1opW=EB0x02*em(8fMrgU3F(Uq1r3Ygkqh3Nz4tMR|~4nAuis z1&{yWw)5-G+{+)B1x^d7U7Zzx6lUmU%U4ial1cQn^1=V$eri9sy~MWa1h~C~+k8-3 z5(K#gnjS%MVGnIDfx@i=P%$xj4%Z z8or=0qm5X~Cg*McLo_ONe;ob$U;J;i`^qo=ZY#fqyRQ5Z@3Qh&y7S8a%#gD$(dW%n z7{KTHiHz=tbNC6`lLgwB209;dbU)nupt2FX9}afDJ@hO{%M2z4v(L=Tt3dnUAoI=) zs~8v=wmf10%_~FBerHf*mQ@ysic@8kH+%mS{PLFZtB&WZ<}gAQ>U!$i)%@f}*M41!#LxjR<> z|8Huq%TUvllrgkn3x@*6YDDp0t9#*{(lhJwz02aPLRGQiK02A`1+YD>c0fP6;& zFLsBYKbWOfar8U{E?DuV9+0;fN4ID^KPU~!2ZslNoY;t|$X%w-|%dM9lz> zi7)vXerg&pOnk}C@Kc((AxN5WL6M9IWN$O*o&!!+hKaA3g;#m@GW_u11f>gxouD&2 zzY8%;1l=L_pNaFe6E{Q14vXF%bW!R7cBZN~Jgejx882_cnuz z@h9kf;{8kvmLR)9p!Z>*--7{Os{_3UBY_drmk>s|2jemm z!_P0*8CIHr^6bU=LCskiJ3w>gpn2g;C(wEKu)8sg(eB28oV5(s|L^}+(Anvrv*khO zTZ!^E1c`#rPcQxPL>b%p>80TF)0nPK8X@H#BWSz!^%43aD9L!TtW8I zGAv>31(2ISc7gl|Doc^;edPOIKy{=rsE)imKS(4a;|J*OuTnmTpQg;<^D`zKKs$H) z0O&kO=(*dVIUUeiwv|jG-CUd^-5i{p-JUP2Cvm*2o&-B@8+0DG0wY%!=uB=#Muyj* zyTcZN@+$+wloBC_pJ4mMh_kPe8FatRkxS&-2P&I0^kDZJIQ)dg73i*#L?(xw$alO5FF0EHt6ql7I9_oG15hNTDS4kYmX3!w8aA@vQ&ZqS-P9tK^?=%Gpgr_3 zd(rP?0mU(>e6L5llLd6|EGc#-2r>Tzr4v{h0oe)iKXN)@W^nk)%nr#*p!3+bF**F? zkb>Mba|LvkHR#;;fAJh0|F}3#{r_*839f@6`7MLb>8A%1!M)7_&P31hp?geud--#C^*k|H9%MUO)Ur+=YN%MsdhE z?9^aoFn!F-xau1-!z!r#KS6E+nGI@dgVutwLeu&IX2_kvC*&M*K7@)Qk zD1Bxqf!p9GG&vdIcLQK+TY=IHsNIL#PoQ-fL(@;7J`pJVLGcOdzx>H(T=^@VX(f6; z1{8lB?4bCAtltH-WyPWQ-Gbr}RR4j-BvhgC2g+-pdIfYI&on07=kb8n8K9rXV_#|d zqeISNC+M#3(npLFLHFOB;B(sns>eX_egYcroouLa54y_-madT7(1^Gf1Ft1PiF>4b zA&~E7`w{QF@>jak%0Kyz@H^T-W&aFN`x1H%Jx4UdP7btl=p~_N&1gc;`O)~#3BUJ3 zilHIMngR9R3k~==KT@lr*b(QwgTz7O8XC}ZeypMA{D8s~bl&?*CgRU}H&5l7{YZ&n z;tL_rnn4lp-RiJDQb&@b<%>lOmK+d21%mtpvJ=#QgSmYMq|JB$_v0~40Nu&X%D^B3693M|F!8^W#_L0@ z3?V1|9DZ6=mj9^w|9^`|vBOSzPKH87Murd%Z-<|pj1E6dmpV*hwsiPe&mj6bgOwpf z)Dki_6`JkvlY`j-JhlUxs|JVIea0F7;d(+5)9x9JgR zT+ZPqhbZKpV30dOZQu?pZAEmw;5M@=L?1}cBW8wGptdu5T!8!v>N9}aTj=d9(E46w zE(LR_zbsF1GMGFDuccuGpW_B;=@e;$(K%DbL864O-`q&2I(_3?d$k99kWE3_Fq4FZlOA1nM?Km|rI%%;g<^ zg2Eegh8}WX13kQzLG4FI`)kFg}Ql@1EJO z%*?Am`&D3LK*EEKT(Ycc31u(=rEkz(PcPUUF24Lf_tMM%`#-&uKJZD3 zfnfsZ4v-Vv3?Z3J4nI4&e{2VhrEqYHcT2pio}}?Hc+xAbu*)8d9IH5312<){IsD{d zcKF#1JuhPc8$$>WJA%)^&Je=Gjo^dUeev)k_y^b-LabRCCRQ^s{LI{p*i)Fvtl4F= z)L~LR=spiEhLFtPsCx=SDs6s%_9AjJJN#U!&9Ie&nc*iVyTeaSU52fk+zvlA^%%Bt z@;m(OWM$a$fmvkLduGX1@0g`lf$q-%-A|=x$q)iMpQ+1^Ve1QK%~kTOfuDXc^R4>H z%)jajv%o6QehPVhhM%B4oIO9=xAiP_m^7b}>osWqd_t$guLDdBA;^ z_=lCnp!p+Ed9#9vGYgalUO~$nSRQzx$FLK0uK?_h6i}Lc$>s2q;~?iM>9-D(IMD7) zkpZneFn0LFAdY#zM+Q6SUKpDnFXX`Y9U3+;GK6SC%QMhC$_p)rogB;zrs#FmLc^vY z2_^=S$65_Lm7N((H9+%Dau9cc`bMBR3XnfvLhmOA-CKErfx+a3p2N-#h7aZ-nuC$a z2;`SPS`Irqn8mnXXff=RW?+~whk?Q5zn%klKEn-krj;DT4L`vBSK(El{wpZmBKKdR zWdgX3kSLEdZqW?As}odj3B$%MKy6FN{91;b!%h!w29peC2g{B>|KWGjgX=(HhM%7= zGb8FiWyXo1`>R3q(F=8lpWr%BoZ+Vis63Wt_&JsFg;^=1f;q_F$mQ}QUjbh<7TwKc7jP%>!lLIM6JK^C%jl0E^7VdJ^`BZ zoX^Zq_>z6T6bB=x)(U0@bC91hm>DSY6S}+LMnWK03H{#yzSop1xWi2*7gVOtpVL7=dqZ<5>$TwDn_!oADpX9_JDBeJE=<)CWR#5zb?n8y8 zQBv;##20_yw3Os%i7WnIa69}2rAbXzhKrehA$zev=kS31=L|Z>3h8VYn=g9x9;B%qyxQ&UKA*5^X|E*D=^_uK~n?QX> zWP2U<{0~vYA;-Aqe@HB7eJxlY$7^JL3VZ*Du!7d^f#o<~C+_+m;sm-k0PVa?FX-KQ zpmn#n&R0!lV+aAYeO7WXY~^5Q_z79Om6H03gsA&yk zFX-OWm(cirNM>Av*4BgKcO?VERt|24pP)8w=DPn|yg+wlAf0Ci8awgE<=21zLqPpb z*c}Ama)OB=B%76C3vwC--9-S}D~+5^(DM{1e<17eVrJM1T4T@6jA|D0y`5UnJ1rhE zGT=;uhu{AX0j)`ag%`3N4nO{ffc$+D6bAeZKau4Okj}{gxf@h3fx^NEM_7RF(bEOh zNgJ~+gUUK&v$7d^U$cPD5@KQ4lFh`hMVWy?1a==PdN_dA|AAs7=Ftd>FR%L$iKZFxUc>-$VbMQ0#{Ql>^I47&aB#vs$A7B3b7ysYPbn#C< z%gSHrtSf)Sv#tCV&c5=CKgY_y)toCqeL>KgI9Oj0)bEpI;OO>X!QSuV;AQ~d1%84H zc22BVxA{xRoy(`7_dHs#LhgBd4Zi15;uNSq^?;QjKDG| zL-0ZULTPBfF9WGhlEJLe1!@C=`h5&4*!q1MKS1ZNg63sFXN`i^wY_9>`1w+eVJoPg zlc~zE^(E-eWEO@ku)KdzAJW(3GC}n9K>fS_e31T~_pkPC*`U5ABj;;S8Q}o!-<<)K zpFc6>K>a&VUhc*s$G`~b7iuHPfzDv@{9AOn^9Q#6of!CR9$5eG8#BYImkJF*u>RdC zwEo=*wEi7v%?#*%9Z>&H983RB8rr{e5X9`?aWH(j^n!_Fl}4rY577LtJS&4CXxs|a zu1D{ioq+buKs2at26hK@&iMKx#)&_eg;#O#yX}DWy*T(W=Zqaik=pLgNPRDESl>%x z73lm7Q2QFx&N?9kj-Lq~%np_-I2lYN7#Jom;oI#fj*D zbuv3x+A}f~g6>-Y^}$XsGnga$gBU-6;sv?y2=8x!!jciSzr_X`W5+U<`nTG1*LYmzDpUA?x4q^$BF4eWXt4oNEVk&J}bv7$>xU1hV%fH^WX) z9KPfR_1z(BYF{vOt^$p>%d0XJa{T`v(!mVrBX#_bKLKiAYcVtgb^S-}BY83tKliFx z$Tb_Z9#Tn>VWNg0W*-UEKYGdT@Ka+U>V4ZF`$2spm|x7H_Oq6@$dguP#hrlbLbHVFPI&Eg3=VI zf71y)YoZC%XF%%LfZHfs3?bS)3|n4tF>HwkwZG8hk8m@DXkYlhMT>`FOFdfu1>C>k zVF=;A@_!2#FT<93*v#i;2zh<>{}xbRDHkM4w?=YtFkA>H6TSdcLc&>0?}GnA0q%Pvd|A+MPkwyc7l4T(1mfaZmm7`B4WV}!+- z!Z(N?$cY2yU;jhEZ5;-NtuMG3ejY(<`=h)6!N30@=@gbL2mCs z3VYC*^&q!{&YlFd&p~Z+&|UU#m>IT!?pp_)%ZV%RDKRmGtoraDe0F6HT08tT)ZL(Y zIhcNAH$Q&&KLlKtf%6dOYf#(!1s}uD34bAN?-x~?KYIUy&RJvx&(|~|&DVhDXFzi` zAbPmA%@gGDx6MI!fWzA6o=T9m`AG#t+Z+_{p!iPIhKvEO(jS~{bL6=fP}>~TE){2G zm{<;4Z_MEElam87w<7V@VbTkvyYOBxX>@_w-v5mpK7sC{K)=t5gV}KtxZSPguya3? zWRa*SXl!0I`-B$5PS6=R91IOYCqQ#1(Dixv+Sr+B>+=|q$H+l#L(o1Q&>RPrb~bd* z)v|+`!Q_ON!%h!o22<#K31r@x8#K?sgqY_b(9TA0qr%(DvJO8VIwR&cPQcoxNb3S$ zFgaLa%t=saKfX3HXg|Sddl-Lv7<3i@XuSuq{enyuhOMx6Fz9SPSUv~cR|9GXzd~x` zGTi?kvJuqYVdMahA;8A=x%d!m<;HuEcJL>pcJM)HJJ<`U9n5$a(hh$1@4q-`T-@#d z@M;e)1+`Jo+Pf`i?P27xOHg|k)E@4>0%;E~!lHi(=+2!RkoGXB{{U;>fabWp7G2tUrA{XzdBD`d${W|aqVHPv#9N1hcl?{;lwllL-IlWIdEOh@mk^R z|BzOs_ORkJc38>Va)ch9Vo7$c@ngr9yBJl3aL#7Y7eWT%_V`-8#!%a&^S1( zP0T<+oA~ih)Hd-mI<<*6{{JsdPMbJ+0Ncb}WVVS9<7g9aLTVGQ|4V2*8gzyV>KZ%r zv1rg5QP3JB%&}@F2Eyc<(v5JY|rw7tlv@Cgdqz_{$k*9Iok{)O&W5d`g5LEnQT z4IK~8gpLPiK*xhYXZ*@Q$Adxreoz>L#V{Za6tBg#(!aM2eo%W?MKl0&fqo7&~-zE{0|!c zg_)s`G`0)BGZ(4dd*I&xkkv@-UeKMppgPtINsZ&Z{~`Ce7=C_0YWITL$DlTJ7gGE9 z;GO>=pgYT+{QECXYM6t<8svY_8YNJeBai#iGR#5y#6W2VG~SyD9q(NUYIBg$zU96O zY2Plxq94@0eGP5j9>pRLYTurQwr{6^4yAV(N_RwL}dxt<}5$Fy)*xc|?YTts| z6rg*9PjE5(d^H5yx1hEVXgxNlEkw&PUuw2*Pw+AP+y-smg6`$n{P({&Xnzz3D}y12 z48u+*28IyO9uxF6NC(AG*C>&zr-OmPgoBkK5M&oNdmf5o+C!?IAMtxuehX(@`Nf}U z<=<-Nm7sk@usuPX9FX$>L>M`{LFW{7{)4QI?f3^-8w;xI#TXib%+cz5(EeFSeJ{4^ z8XKa%2Z@8~`;LF{CqUD`gLeQE&dB%W3(0W0Tzcg4F1UUp4eljdz zm?+QV@JWG@A%x?={2+M|1`E)B{)7Mjhk*7HA)h(GaddtV_a;)Kb@q4EJU=&mZrIVtsgsOL<8_7dURFAq8k2YG+mOJ+tbt-tPaWO3@;>gVUp{eRHNm7-wTjMkPM9u$>J3(g#X|XaCg7!6d@-vul|BdgcXXMOo zWMBvZofX#o|G#Mt1A|DsJ@eI<%-pL$Y7hSVAM%i$VJB#eT%6J2Cn!COvNLP}omJHd zI$w#M;pb)kh9C=uh9DWKh9DWH1x29sT%fa+I++-Lc5rcYOLH>pjACb)2wD>n&n)^H zblz|#lhkSJ>dYOWbCW=4O2E#r_y#&-?q58|4IF0|f%fX3#yGnOa)#1d@YxkL@Utth zonHhyL#cxaaefiVPoVY9=8O*D{f;l0Iab*-GJX8a?ywVdPBYAHU!mt~to#?xu>$3M z4N>^nN+9=v&UotL;_UVkWSGb!)eywPw4lhhGGoWOzwVdMh1O1b$HdotE;HxHdR2!> z?{Ai0KAow*V=ergC0>-Xo?z|-o%IAVTZ5HhB1o)*i?dsplVK;Jvjx!eq@oep*>cT{ z7k|Vvt^5{_IBzN3!=ZA!Aj1|&T7!&Tc(6G9+}P( zehqZ4R}%w62`K;iu1E_scz@ zwUe?LdAecYpPiZW!%Nj+QkE)Lx2LaWw*PtCtsm$TTw`xmo8V z?C`Umk?S?cKU~ZVKSALjq0BH*QxT+&;pZ!Eho7LZ1IdHd0D<;aAe*`3@BghZ{~uyx z2+3q~*va+R?J@^a7&tOAgn+`pgO{V5i_zhyR%qB}E=Go*-OcQu2J;b)?h!_I{a3?@l-pmGdywhW{Ub6xqx-(}^uaOahv zeZlbks94e%O4{;ps9eF$uq9In6h0iUl^Q!{B?&S7>||gF0nJ%~&Hw?`A?R$77``~t zU;~|<)DTn-ji*;k4nMUS9e#q=K7#KEVqge)%>;=jQ2c4NGW-Cose;85C_R5yVweb8 zCj^=sM~*9yc*fuVTS4U_1Ea&=1xyTo#h9UC#m9jXR*p=VVa3b9AOfmGL4E_>Lxa3$ z85VY+`E+FSv8e&I3I02S&P!uj`Nf}k<=<+Sm7k&edO`JshlfMu3nqpwO+pSo;~6+! zL&8*e)kEl>Y*5^Gg7X|__Cj7rngg8=WY5Tzt;ov|!dVMRe_4JGl_0T&91J0ud=5V~ zcsaTQLHA%vIqcN=i`XmH`PcojW@zmsPDW06U8I$n^`l$WVUnjRcXuWq!_OQghMhfD z4wX4x43)ih4wbon43#--4nLd!W?k0%(HvCI!1tO_oFSx-$zkXD(6GyALc=!aurd7X zVRG2n!^hLzBkJ(8f2qUfd^U!kAT@bR3_E++9CqfgG3-45*X{B-QHM$Y8F|6wg@-D4 zHwQ0YHz>SM@izo{G4h|*tjyYhug>I9^{!dos0}2om`-Di1W23BPjigfaB^Bv+%0F z)h;W)_&cxs7Vfn2zcXn69V`t&>K{;E_{Q#TN9cN*t}Tou!)hE!;e8m(T}6yz@-=b4?aQo3;hzB8f-x6DU*p| zX9t_Z&I~q&omzk0E^CT9Ov*+o$3bBRE61}bD91r%FIQ;TW-UgBpB+*TJ3;#@(ZdOp zM>4z|Dn0)HHvyfIsQIHg$bO~AYf#$;=Kf4Bho73EVUz3`IbJjV`yT>|Z_dAtJMCE+ z3PI;Og4m$;6PVAy5aP+u5XAYH5qyp$NG-Osk)h| z|Nmp`@nH0B2vUKzmH*`LT8ZtP3gmnZD*I-5IaFFOGHmJabExFxWSGeDwCXYktLJGB zM#hQqjKZ%MGcbhwV_*;gjqic@N%9OKp!E+H>W^eF zGHeCypXHQ-^h+2RIlE!y1V|oaA50&ppR$69;ink0^y&Ldj31d48A4WYadb;^g3ecR z_^J6HQVwu1a(2Va1D&S&P(i9W(c;hSvJE3tH{h_B1j~T-(Sn@mwRr z$Hf2tL*_GczgA>r0H5F8?B`Hp$6 zblBOc#IO?-F8Im}235}P20n(L;64@$Xx(?iCHV{uP#_OchR^l4C8C7-Ef;l;`@F&@btE(VT?nm5ZYb2D;wXFG!AxLwO4FTQ43(g@44}1sT8vVsxm3Bjxj)xl zc3|Z0_PJdSaXTZ&L>_*hZZBS*ZXO4a`8=<^8hd7WGIO2=m2H}g+*s{t;B)xd!OWl~ z&+G6B)D{#2oy+;T_A&>r^l9WiDHkZ+@`!cIGcvq>$p8+|NgS$Dr#N^eP~6?==TND^ z${^U`$509K1E`D#`H{IYbH`&222;sO%^hM=4MAc|3yN;=Hw1NfIaGqqro)$KK<};$YyI$mxLG z=Vmy~VaqTP7DwoQ?^;8bFBR0&$;q% zHP=cGP`i+e!35NfdBM!EinG`8hvr{MKNeIDAK+vN$>aj{sTo&w@;Ur`Y0U7mQ^{fH z%WQ_7O441x=2jc|S_bfX zFHk$Kfr;TSNE}}s*U;2p13L@ne?9Zc@8S$U#TgoezB@DQe6SeONBCdQxbh1-$UcUh z50oKd-`O30erICX@`Kyq=L>0vpPa1@KRB5ge!h@q`1w*EQs*;)#%Giv`#oOrL&Od- zFocx<`wwbsioneO{{O!?vbp7d|8E8D!w2;Z7cd>LJ;2mp`{K4kEIU75Xuhk;>2 z52M4+T<96dJ&e5FyiyH8yi5yQ?3M&hpjj_6D`vL&GLzGIFl+WMufs z$>Q*ntKq<=!<~H11R>#->l0Zx7ags zWP{H81ho~B$2>sik96{Jc58|{`~Og&dQHF*f(71>xLqia# z?*|GGd~J5n7{fGZn;o3SmO4y2%>+8n3sRTk>a$)`Vweb;<3w-6gTz5&46r_B0u#gE zsmu&!ok|Xx^lGDHYnyX0Akwgw52T+78k5xIf%G#$ajV5cc^?Z@W`Ne&tYlya0j*;O zu^+V0mjdNY1%`$o5DgoL2Gu#73=TU%_oHz2I{fhYn|0ZqktbXGM{`h%pm!Ch?E-3# zgXMW0;qo9kQ2x^n4Z92*n*sHQVCg}7sl#S&M%3|MSXuz3@lHMtaQfo@>vow-)L~MN zpF<@mzCdLuC`>?or7T{qZcure!-rO$l2Dd{+~Lj0@H5lPq4Fg&g9#@?!zEDL3D!>q zodJ@^=kU{)k@xi3%G@1%j1E87|8>9oKD2hyIY$2ObD7yc)~Y&8I;+aty~bCkyO+`7 z=h~$XlX@8$ermEZOw92D#UsyaP<^Ib>vma3ltC!Z&!KWZBVV@T-~S=Gd=5W9f$A`D zzt(Xj=!|8^cn2NQ!r!dRoGcDIVfkEx1$B%Pl+QVNF!Q+vs9Z-H0|li4bakM7&HznI zur!5yelsY|fc7SX)*6BGKWt13(!WPN2N{+YL30K#n3=RVeU!SDMHzl_3OM`(l|7&{ z{Xp|Tps`9&xtf7A?vw%T3q!`}@Xs}1JC_%BuLP{lQed#Z)*F-*MA#PCsrdB&`lRb@Y3s57ht`7wdX{@OJ*hKV3E?lW<` ze*Eu$NC%t4&rU4|%~y*VR=z~KV+5oY+qgFDtTp*RkaOWc?KK7lhQACA_{Ss|8X9as zd7Iw)m^~aSnHd?jGW$4Gg3iBZ=5hGx%*3#jS;1lFVlBNU0 zL@o!0iLaSCRw=aBuXSj(Ukke9+pCdbVm5RU( z%+qFR)w^BR6lW0XhK_+A{PRBqH2(DtX)F*_?t%1D-Hm^r5pj%5xjx&CHd2DN*& z|7KkVoj2EG=AijnooVGOWyY0n%o$d~(k;jzf2%!Ke(`r-`7PXS<&SvRmA}$mR{qI% zUise{(%0mWXaL=9Gm%4rVJ9bp!%r<=he~-yu52!5h7c`YNLw$Pk>j*iWj4|CdZ0d_ zrl&)th9t*nc}B*MptT$vhMluOb7dURJ{V~Kqqe6*WxXU9IKON1I{f6Qb(ow1)x*Wn z5X52FH48Mq!MT88B`B@SGeG)ppmrDsBdD*!@cJZZ9Oq5VWzf8_CL_Z{h0Kf}Ahn=% zw;&orEqHA%!$b~2hHeH{2WWq=;SxwKw!8K~bw0!lhKVAAjNPC$t)O+uVhp&?ykEeC zxemF533R5R>5oj5d#@nl02y))KSf#@eq_jj+M|fMg&*;bD}SXQT>)|%==_v&CXVhG zQ4XN^5_}N_8VhaM>8Y?Fh)ZF?B`$_DpCq8`VmYDfVmXl3#Y!?j?r8$8DS)kw1>NHX zSt}#C$`Wa9EJz%*R%S5Wxd$2t1jVs7qr*-eMu(k{xgCay^BEZm-!OO0n$O7a`UJGz z$Yy1@2vXxK$lVP(=WDg${8{yk46hG^=eNP>rtk$b=)P-?(;R{UlB2dEh(iFf27`l;Og)q%TcH<*k63r9CG!Na4 zPSzxvDTQe!vKtRskZ7J9rg`XYR5BycOeIV+k=?k+m_+l`FwH}EBagErlt@9C37Ufh?cX7`JeoNP(@bRZn&e1x{3_{wkL5-Y#>ORoG| zEwvJK$M08W$T~4WUdz0=vF<3&%RECKf3=1x4 zFdX=FeG%iz`(g|~xfB|LP9-r^YA_tQq`~mu(+MZ$A2&WRSl)MH*m*;U(Gp}n1LFbP z15GV95VphL19}X9LG8E`hZrhvbTL|LGAsy!h2_b0Y%A}7VyL|TiqZ0Z6O$#w69)eS zOe||T3!8#YE@RkvBZ#pQ)-F34#qjfGGl$X1T?{*KR54cGKLqM~F-!op*-oZ0{JgP< zvGV0%hD|4xcz>MCWB7T$iP=({q2ZFY!huhxo%nvh>^xn?@blC!hMfo4+}1u|=U97y z&3)|ycFwg2*j(2>U}s-@fX!v?19rBx2iTm}K452Adw|V(?E`k!wFlT7);?foT6=)a zaqRff><`!;&}*=LpnbshfK-F+ z1N{TG2jm)TABZ2YJ;2sr%c;U($tl3_1J)krtZfM56kymXPM{qw@qocnT!G;ysQoPg zZGZpQX4nauGlr!_#)u~H`uGQ+{d>)z`!gYZvj<={B-2c#d(#{ z64ZwVrAZA&hMgLW4m&}2GmA1XOjyALzLU=cbp8e`d_ZI5AaT$**=a_G5HaYzIugtb z6G3;7PGMr0$WdMP1EdEwCl4BD=2+aY6Ex1O{r`W+ekNGo$-&ZtmBHlyeDwbwepL9 zP$5YxBC*56@Zm~f2= z+V(|i6DS=g(QGVjcCdSq%xpSBqM2CQ>ga8kM+ZqWa|V_+`gXK-pwoU5&1}PLw;{I! z5A7k*ye>@h(A}uCi$pW~FwI1EO)&dG#g7F1sv~4W-4tW z&CHot+W+W%l&1A0nt2Q}Op*I2OlwIqZw8kB1bW{rX%%T^&cxEEK==2d)lopU?-i%L}=7GyMq%_$ymqatM^v%%Y`_U{C%@o4y z_n^DeX$EO#&cf2)gUnSq{FHQNm?)Wn=m#ZDCDCjnO!p$2_h=G{<~d<856z8E6G${O z2#c9Wem>Mont3ymFwK*2MjaL$_5A}nSijXN#sAkn-gO!Lt5BvTuSX0~CPiJT{! znn^QnMi-`e=xO~?18HW?T!d*REUkmi2IoKuQ>Ho+%|3)_Hn?6xGBc@~G&5&C!ZdTI z6KbA3R6(Md&oIqI&XZ1Mq?tGK6{dOMctY~`qGHm_oW;a65xt#^UKTMGl4zz97Bi9Z zc~c%~=FN1%G!H$WKguT2%p@#kB86j8CTZr)Xu>oP95+by+MzTO&76d3CVIW5ltP-B zGZ$f+iC!KxC6Z|7GE6g(%Oj?E(#)H22-7@p{zeMRq!`l7ocRdTOmu%AiX_p@XP9Op z``am;MDt!@nuqSjMIj`b`3}=eWH%}Wk!ap0O!Ls)*yK;5ncpzYM0O*SFKOn@U}DB7 z)6nxxk{5|)Dq)(5o+b~ulV;{jCrmTZ!%~UFdH0!am}Vk}4#}1vKyO7oOhoYglQhS8y{Jb=r%qUFr(A{{*lteeiVVa5TMkf;I z-Df6YnuqSjMFu3gF%8p9WH&02IPX3)3)4JwH#U(t?>;jR(@bPHGLbm%KC=kZJajiE zkvQKzvkcQrWH&w{b&kCX(>!!HIw_JE*L9d?BD?VrsdMa2nC79ksgz_$bK{Ijm}a8a z4NWA@vCmk9X(swO<0De%*_UCOi9F7jMCu&-Dopdx-FS$^dG;CWFwI1EqZ6rf?1wPT z1J|)gW8aH-NQ>|3k1)+dpJQj@BGJrem}Vl+u{V)A$Nmb_JoGvCM@Vz*#LQ7ld53AH zDAJrq5))~D2JKtIHrEc?#{=s>!sePDBF(ikvN3G=&kQ=V1aSr%XpSAU{tz@D#K3aE z_5pK)Eoh&d*nyTyW(0R*cxn+&tdz|%m|)O<5=Tt$+^VI zQiG90i(?6sC5MT_PS~6#XkH85f1r6o(EhFyObi(Fn;>!6{3c}15j1baFj1I+VL~wz z!^9I+rO^3J$lUN&Hin5O7B%eL&&2T>G`~5Y33LvW^U5#&PAk8KJFbMe@jo-m#b4>% zD}TiEto#sMXsreZBih{PVg|(A==>(j#mo#_L35)T!ZT)p@6dzIjmBfnjb?D6&W*kZ$D9KN z-52|}+JEI2f4`OA!hKi%i1%6fE8TnLe`XeNd_m_i!E1G3X%cz<^M5nL#lO{zD<3j5 zta{PRFcEYX?jz8>-VBiSA)xui|IG|wv;J1^2k#dLh204z2GG9j2_W_hBsK>#LRtJzn6VP;+hI>QmPM+I~~8feZQbpA;P7sJl2 z3=ATm^P9fG*2G+#A0)-V0bZjn!3s_nKRJ-j73W~q=n`M*FbQ;bp*-kpanQYpzl$z& z$Z~XZGMu@@8JNHM1bCgg`43#{)WupM>(r+)IsClAj~%?qmB#=BIsvZ zgU(oo?3qA4PaGr;+B2bnbe^~-+Iixcq?{+7O87i+sGkBsVF9uibOs8{&s_iii;FWr z&VxkW^8vcI72^z2HpMR z^|$D<7t*=q3{U@uY(Y8$9i}D=NloJu$lX6mpgZo7?&o9VW(Zl0eD}{|$lX6;pnZi5 z4VP~JL%aJ&73E{2e99)>OPybK>TxfwzdvE0YP!ov`fed|A1jVBL7$OX_D=V)iFAK_sL(Y^;! z!^z7K@(xK2=nkMIybK}SHz4vac^N|Xg5;@mPI}i>;?7Cex=GwQ>8CEC-UIaDBI-Rr zjFW-7yT1_6BksJOG{L11d++@-@i)-q1JzxnCZn22Z{Pxu5I9|1ID> zzf25Ukne@%Vq(||y0iWuBSQ#sJR;whsf^=ppj*(h(?R!TUI*O`L|PmBC#YT9!N%|t zR98^a#%`dzjSY4St=ia*q_wfZZo$>YUcvQaJ14`DOPZWw-R7YCk{{Bb*^D=M zNVKov?FLnb5Ky~;OLGvkuh|%Wg4$rC?Q6)r?Vxrp==^@r*w8?>uenFt*Pmc*XD_7t zgFx-;HJ~ydR)2Fs@=_L(8szph=uQq$Ulw#HuOk=eOl`y+oQ!Dg>pLT%ea*=blFh}i zH5yC1+6C1Axb=TaEa;vmXuS(6r?MG&Uc2xxgsi&ve+%dwWYC?}JR7qvgTzyK8A49o z_`f9&6eoD_TooU;H0ZMy2+1 zHK_f39<3dF9@>sQho>ET7Sew1y7YgG*3R6^ubH_|XQ`f=#dQg)_aYv>7a(oUuG46G zp?4G=JcUQ^NzC>$s1E?E%V75mbs@DoLHB5a?lwnnKdUe?gsf&_*h*}>`4LjPnVR>? z%l!Ki_zN44bb-TN>+v~_`-Yv3quH~&jQPvuzU-1H!hoI;&K3wLw0b(+MpuvJ3G6$!Y*qva;@TGIB`jf z;lU?!My^$$@m|mwj-b0aeFVcMyKA(}{W6n~CNx7_nle8HgTw1{B{R9n?ImPDi(}z*~RIgyzr2UKxAAOfPO!8t4oaDgh{j2M5(Pfa@1&p4*JlGjR zPH{Q>^kx)41*+Q~2r-15;zRHmnHfTSSOX{NGCa66pON=B7GCWft`^CaUL zIbUnAGKBCkFo^i@Gi*V=S9AeCL&#|^ho2y~gZh;Yf(#+Z_lhn6-9gF9FcEZ@5$DFN z%dh^oPx4eeIg67~vkP=yki4P8CkG9N5RRXa@mMZ~Gncpm^EZc9YQpao)zn1XE6S}lgrMJ7Z(nH!8Xw;If{DR&+au!d;Y?H~G@G?@(7EBzv3i1c zSaKlr`4iBGJXY_?gBYtXz%o`3>N7*ex>3jKLE@mXZqOZ+u)YN79?FjY|4l*h4I1yJ z#3;eW`>5AEB7 zL2b~#`IoazYbRwhad&6CI{egG>M#j(<`~n*{~;%jwQu*rqXuLS=dt$fpm|1I?af0U z{)cEDY2R+az#!uN7PVh;>dpVHE8nzl$E7!!l_4Y+RCgRg)yH+{|JIiWaqD9`_&-Dj zEHj5%kzotA`))yJCZGJ=z72F%{Y$2XZJ;|yJCMS+hmrU75(b74ZYG8; z^LZiXw}S3->V~@S4KvT_Zq?JXxIuk2hKB9f>^S`4e+Vb5!z9q1riDcIH$ZnMoKSOE z32LW-?tnT$VPE3_C4G%7hn1i*5~H8-GH?>2pK)fipRv?o5~=-+mDBG^k zbNci@#FMpQdpIcWaP=KN{SVPR(Z1aekD5mx|A%BAZ{O~U$F4&k|A%xQZQpJKx`!6p zMtjA~b=phy^ejSc$j7VU!|W;*mAyaopp zuH0ySkgkLOw`St$gESq0^d-9YquIIt|JIjy`Vvh0F#8f8|Na+;<)MWPkUq2*Bg0nD zpY7X0cl4t7A6h_baF`gj;%lEP{rews@(+3KbLQXwL%@9)21p;~*k9E74p1Kg6hE5( z+qZ+}VqkLypm`3E+d$*}_}u37?|;ZkXy0KKBkCLn$XtAV2jy?%_Z>XHv~Lq*U=Ude z?K@0H>pP@??)hb4*h*@jq4^`C&rnC8&j4F5558NF$>C=w7wGQh_zrJIPHyhMJRNKP z|2ORtV%T|^fkEUOGt(;gd6Gn~od>O(caUQU;Xs?KSV3UjyeM?t{8T1~pL3vd6(_i1 za}}bH^)erWC#^!8tFVC1RY2CJOPnHhuHpp;L&z)eT!jR|xrz>UhLBg_xe5tzUE(0Z z5b_EQNB#1H~mHxJ=62s4EIW|mro zYwf($Qin<4wewmGAsT35ZdPgagM%HicK#Q$^eRtn#QOP6T~J>_96V>CsRw2EI{xU? zM(hVc%vp%7ddw_}GH3A(v|oYA;U{PxMFkTB)_oM9v~YkQGcDLxnuF&oI+z(uuRmg( z_=8z^6$jE@2M*|7hfFrm9l_xJ4VIvNM~qsy=PV=>1tvaVmRR+W8MNm?9K7cNoxkE= zdn~)iP3tdYtgSwLyFPnH5y+-<~6)uBjzA)yuKWi2GQ4;Bkw2BWI^mF&}U!}Aw_Q{2SP8X-GHnY-A?5Bjgv_88zl@3B2o+u zK{jaP?4Y?f$T+*yswkv896;irIS$x*DVzTsCy>W?L3`vtXIFA5Hw1ApFDTN?%-W%8 z$snj{%5ag3p#eN!2wHEeY3k9%#o7>LmC7~SNtt1y2k3lMX5m%nYx+GFGgyN1Ury|KcD&An!*2xsw?8gW8km>%9iT53K+HQ*~bjseT}4&I6jh z!0Y|YeUt(ybS51fchA)wi&v4 zoR`|S{RiDGk7Uk5s5#kCb389X%;|vkRkk6m5o2dy5P6BT2jexn!_N#xho6x2#<>b~ zf4saZL*a{m|3g6Hp!@>bhmr9&{shOr|68;EQkG{lb-8B0#IqOU)pCcGp#3l!3mGh5 zBH{#`cRWCDU}d=I0S$LYv_1?dyt^2AU#oC2gk*n#jCE&nF@!7tjYlK(XF%#eeHT#Q z#2Y%l@sf)n#2%M<+zcV!$DrnMGlb}a`iR)f1I5Eph`N{D3?UjIbvXJwO7H)NfZU<^ zzI}TPjy?@Y9yD+Ah>0PD^Kkq2AW%BPVjf6cJR|q(M~n<1oCn*tdk`{@fgwcmK>Kz( z1_lw&1MS;D<-X_s_H9}J|BGktZ{Jq<|G#+lE7U&5tC#<`o_vYBU-Rh2{}3$(29eWy zQT2K4{l8UnFK&HKdm!^F-n&uto!a$(>&jiY^&Q#?=?lHyiK;Ja=l`vqJ8|nv+JU(? z>>#wS0h(`AWQ6o*LF=YK;hOoVefvu;ho7MFhZkH7KR1K=O<3X{w8sB5bbbZ2#vgRA z8fbn2+jzgzUr5}a{N29o<^TWU+-P$wU4Q;>&BQau!u;!h$Zb%XMw(**_2EGKC_rvL z`Kx`q5-6=e-3dzTETDC4%nVyV@}PZ6o=glOk{~r$(i12x9fG=X<+t{2p!+;Qdp|&W zk@q4H>Ng$!0@*jw3A&%0kKrdse;TO&gFgSlzz_m+yC+M-cF;ODSpO5G2QXsEl4fM?MzGzpt;Cxf(#5Ipm`aPn_=@X-Jtn0M(p!2&hP(+urM%) zWHK~td%?%>(;8_Vm<5r2EYLlA9a;`6Ise9=&}QW7=Kjlb0@T0i0ww*c zBFOvsPY~g~ml|kxW zo%p{6G=GClKWLAR_HoD_9prtzp#3?ZeNG_#UB@8%ba1tqn?69=%$aNr+mk_Yj%A(* zWDcyqlzF6mdnCxcSlYKBb)a@4sK1nXsC_$VeXTY=^B5RHIuAnTl~x{X-=j0=F~V?b#aj^~UIXp30r~6XkM`}Lb4OrvHy}BXIA{(Bw&w%1&I(r=cm(Z}WJ2edNS()74BD5% z-V6~ zBaO~Wot%X{mpeKy&38 zfk7lk5Owd=0kpkS3Bss*rw#}+g#6)V_zBuOH51FdBQnsvQwrMH_D)fGxj+uP+Wo1#0)%pry2w> z(*$VmREHesz699bDG~7AsZJ(`pPEY@Cc*Yjb)xN^I!NK(sqOzD=^Zo4z%{~nanNawYI))qK)I{Z@j z{6C}sw4NP{oWrO8A-U*#s$N0&RJ}s%sp9zfKg17omg*bKJyi-H{)Z%h%tw-g?WuBj z{~vtTPzPlHk6=eM!%k4z>_FRFf^Sb1DSFZOR3Ym{w^IVTpM~>({0Y#WDvtk?CD|i5cKMRU#;RsydP!Ei)D~Sc38<)Ng^H zFh$=}1=_<;jXP?{^@9z{JvEqq=pe!m|Ns3Lmt<%NvPRq6#=#8Rt0TF}5-A=);-I}c z9MHRVq@jD;$n}F|BG+ssWrm3wIO0KLF@q&?9DwWv?Q4UjBTmqsD$t!Ok>GZ{phhIa zP7OxXyNTd?s+h6wse+vm2b#MAtU=e@zyBJZgJsXciK zvIcMp()vD-d7w2<-ca*Ed#XU^&h;Uw0qv;**_j1Zqj>?c@2VcU1`u?P1Sd3Zz`~M*zb)fU! z0`RDVnFrca<%YDD5ZzuTsCk_GA?Hef%;tWLx|Xi%)&H%TuMlhT(9LLi`9DOLfk6bM zR~u~))v7)Jw|4Hqt#{FG$ofB!-qmRPsI+$f-^z)!1`yp|rCpG7wn2Ki(e_ex?fAbn za|dpFo3{TCnXbgLvQrCmrxm1)x)-|s543(1c1|5=?HS1Ym1ujZ)`QeS(;6tgL3@-y z>R{*8f%YgNpHqkK_N2eic>LYI?bZMP;vl_*_EMpnfp0Gr$UIzosX%hw&~xiR?nGV> zh;9dHFBM2VY%djvO=!I+x*6zusX%5VVObCOkdYz88+w)TwBPlA>rm`>5wqV4 zRPTfOU8_LtWi0!xK=PW<^DCw!^`k)ZTA+S}H$SxR2JMf5_FKW`zCin}K;t!8P&J*< zzE%^ouLU|IWjOY=>_FiJYyX1wn=$gd2A%H>3QI0dhOMA|Nyz)9ojCcoMdg- z9uJCh=>8~-zSIXu8{G47`}R;g>Xe}BK>Mw{@%5!(>JC8800+5&&^{k@wW;N~k9|AhF8m2!RZI9Kf-T$|q#M8fegw($} zwG;I&Bd?wRw`wBouR^!mX$NNi>M)KyOCZ0kMB87L&B*f_v}XwQ~DNOddv{wk0eIiNle+SwGu^rv2aYTpLx z|AEW^oe>T?J0cQf7E*tz1=^niodXU!zZ|5Nlz!AxV;J)gt!wU+MSumFp-NLH!@7@X=M1A`2T+h$oz#I3?ZO0Oa3TB;UXr65H3d1 zZtp~fiK~(rC+0A5obF*{oCuot2ARErks*YOqanzLk>hk1XU(Ly%v`J9F$=FczV$%B!jdvy}S#4IMRZXZzxi=0di3l3I> ziSmq$9~=Mw4=HBi?4H8Jd3s?I!^8*7qN|uV8iGK34(2m4etgWp5YqIlY7$8NA+s>} zyt&WJ46CMyIZT?u3Jn)VhL9CW3==b%M7lxqcTUUToT7yslluKbnGwDLzh^U81GEGxhGv#$JG&9;(5#Zi+- z!%6c2JHt=QqFF&V3-%UyGiq}6GIDaQX5`l5X5{A9EpX7xX5{7O>z@+j_jXrNHX|Q* zc51h9HX|o@AEP#xJ|j2RJ4QY&e?}SZcZ_`8=U+_=dM~lJ=o}+I_qo76;d6}K-1>}q zTm_7LT>MP@T2>5>niCkMxcQm*xeKKGf&^NY6uoB@;C^r0FZ`a7kGp_TpX(wcKbHZM zfR-U61GfQ_0QbeaGlMpo?-QCb*dTW%GYWFQW>n@ zT<011wI(tMa_ckka~m$06m)UL{-XDcg52*l`-ML;vT~niG~`;wAjox$fnQ6%!bS5j zBQtk00~TIZPgxX*$8GcTw)V`CAB z4GPc8jO^TcOvYS~8HBmg82Gf5EnGEI8CbcOGO%$U>zpD4qL|o_iH|h&w-@G59 zE}&I-GlLlSQYK@r<4nR_-$Cj`+%>;2h;UC~66d~N*b!uYeoGOEJ;iQ{@DwIt?(0k@ zTop_rT;j~)T3Z=JxwkTjbDOg?22D3xSp;Hl)tV~2l}UtqJCiWi3?^f)?@SU})0oA$ zuQ7>php%Y~x_)?H5r};)Z<_EmCQ4UZ#t70R|S(9Slw1ei2K67&Ir10 zwin_)BTV;+F+tq7ox3UM`_Wyv-NyiNUwKzk&~%RlINi4e8h+*%<^-9G?8fQ7Qf7$z z#4G0qmH*m<(|y;V;dgz{%ph}{B{<#p8S1|4zZ!zRr{NAi5vcpVZ)gnKK5HLN_kD$i z-}bppLE)=c;B=oEEc_Ja29?`v#p%9aW=Qyn*G~!hK6gLP@S6g4pLujc(D%1%(A+2N z^@B-_OM+S0>nb??NpMF@>67_<`Yq&;xQ277-5O)LDE|}lbF|c zCK0c%V7G{KPiJfo+P-H$B&^gRX>B@_uouWZuzWDxV{Xv(>07Y6rx+SW=3i$9U9Vn= z)jhEA5zpxiD!&emKQ#B0Lfs?YH$CY4_3c>Q1BKyfYm*)bZ*W*D`>jaZmjOP3{B(PZ6*hm-`<1O zJ+S;IKEFRG{L5mj?g@qFz3peZf~HU1f#ROEjAGo|n2fcqF^PDA*wZ{(g3Ma?6@l1m zGkb;CGKzAyFbH#RW;D?%W)k%Ru|I#B9~7Lrq6oxpiD(gSVc_L{&LF})nZZ=6n2Fcx zIfF3w=aQD7$wga>KPYEiXw7&?%7SNj@ zEWpIheU^cjn~h0D>lg#O*IGt4?lg<;ptRL%ia>0Ldjz-{7+AQMFsf^{FbH^o*e;W1 z2DLogSOj7-L^KF9Fz|9GGq7{BFc@gHFz|XMgVguW3wrW*e-VhC?9wcp%)r1sfmwh% zg+W)Vg@M6KfQf}$Wmk7l%Z3d_AU4E3%-nAodAa$S6tvzmGJCBB)w?JAgZRI$EdsG& z?pe>kz`cM`S&M-|!0SCD12@B+IYA9aLG>*I_xngt`+*nS26(_|pvAzz>y^#Oz}=A4 z5u}i?r3l2%b_KOt_`z+8LPlLJLneMNP@BTgq$x=7;7UmQ0vtZv+_}uW+=5K{T82#A zUTYZzxdSis2Nk{o#g`yA%srqs&U!{|t@n%qUSPJ{ydeMO+lxT#bCIC74==YjGdK5n zMgy()j3D>$bLWT83VI*4v?!aApBv&HKJN3(0^9|Rx>^EEd|sfo&rNgAvS6S)K$ zf>vc|T9}DCT)HpE@G*m#Aq3Qp1+{ZeF>z?c^E!Mwz`zjljgeuCyeNakH8zHi2mk*M z;bveEImJ~wiHnh|JD!o_^-BhZ5DiA*ZiZBbi6^*Zg*a>(1Q|JNCV|@AVjK-Y5155l zJw$4UgYI?9Wa0p~olhw-T=Zt-)T)Qt1v+QL9@;Jj*#&Czdwr~(1UiQgbbsVY28Iw0 zkX?xk6FqDhCNjQ-*ps2=pvhGz8=S?&urtev(UPl{H8{%+MDqq`c`;gY)QSdY_%T{$ zhB55K>K-nKot;b!mYG}*J2h)Lf;-t5EHlL%Dm%FtEHm{SEIauaEJ5oBJB1)LSdAEi zWu}}%Wv3K_Wu~2jWv3j2Wu}nB&Q2u=4OXMZV411rP}!-)V43OXVA-h$Hg{*I5rhV- zF$3FC*=faKnHlF`*=fgMS)T>%(0NeP-s1f2+AyK4NBE^$^rAWB{MH{gVT9 z4s1B&{B2O*@_{g-Z~1_|!S;bO!$eTLJYZ&+_z=cscUbu%+~Fr|oe${zWP3&q@Vdpn z)!r-rGc$wJ6i6Q^Z6V{w%#2zK85m6LZ5Rrj7#Tq0EI&c=3=9kt7#J8PGBGeraAIJX znCRXZ#KHjC`;9Kw=-wFggb~t5qqcd>3=Th?85p)=bJIf)gqw&}hnlY#R)NlX%lsFA z0(3rR#y`jyx)1|{hzLVNkSTO+3FtgZP}qUiphC{*6J{~;i8(7KTY(Ag|6m_=5-{Ksx4!U}PZ#{d5zKmY$12iwKT zaFGMaE)E8VpB@YhTR`@r$Kk<%#vo>fhD)$GmSFwwUi=o$wDOBT z^UA-~EGro}7`BKoIQ+cA&ag$4fnkC$1H*)3CWeWe3=AS&d=5Xmog8+))@EG!LY-kH z$UKlcr!YDEG+}4h(jn&Xvs2FD=gEKnx2$4v_}TUE{}x_`hD&dlc~@y?=31;}Wta%M z6O)gj;nHhnzE%F2c^2nb878j(|KIdHE5pV4jQp>enHfUvvod^iU}6a2VQ9FtmXYr? zNWDHIPxpt+Jd420JPUay!EDgHDoAfVBj0Ps|Nlc+85l%*SQ#dQ?ws!Y_df)b&R;U~ zgU-Uf=q>7Cp~=cH5wu@ci_yU{ekViW!k_;`v{)T1wK*9k#_we)%w+7Gb>jbjaag+k zTkW#)i@)>AZ{bcW|2s2+%1jY-F;H4)U}e~n$jYz zOBxy37TK%}6HkEd;ALgF2r5@WeyoT35i~yJ#mIdcq?U()v%5Dl+d?lR+hRW>AJ~r| zz4DCQa6f|lVb93*8s^6b%si_YSQsv9h&WgOyFi;?5>eZH>OOq>iMl9gpYw3r=s#j-j z8$*aVL&GHrhK5U;f1M})tZ4{>xew+ZF$RVS*O(Y4a#dFR@M3iMDZ$P#k(>MEtjvd; zvpFg=e}L-PSBn`|{$xh1nabdD_{or2{sUweXlxNgXF%*c4YG%e`{XQ7B>gYIdd0x* z2I=Ks6z^tWg}5J^{_jo<6XlsXUnl?m9|DVmzttWqzxcba{1)!E@<+Vu%3tX&EC1v> zul(=K1WvCYKf?Sb$-pqdl9^$m6a&MAC}xI<(hLj}s+k!k$}liYn1d7-us8y>@gQ!5 z+{tl34&pXYSY#}70)^#idH&AVP9Oeb4#v(| zC)pf+LdpzCT%7==D^`ZWhkp?MdG;T?UKXBS(BlKJa{Gd!OeW55bh|+5f`hFgh=XxK5vZ?lpNZr3 z2^@CbN3!$&B8HXs`51oQ7h?E%UyR`=EM3Cf)B)O00ctZcI{a;5WBAMQW4{pSK9`0h zNPBgD5u~1OXll1@UiwXBLl+(MQ}S4(td34WB3WG&l{Ln*ESe6*j`a% z_<3K8;U@<_Bz!?`W?*Dk%fQ)S3sQIAjo~MU7(}jwiKDxLslj$W7sF3*+%Q4HXFoK2 z6ky~2QVl_zOxVNcgrCFD{cH?7A#G`fiTjr^td#%D^bvI4IjCL8Ap@}sPR52H zMa2`d9?gcNRSty(mpB;Cd@4~gpN-3GkXlgL#mLwSo|^)(LE)PbWt9+>%{ zvIMmEhEt&-NW;|Q^h=h8N#eDfVD~UEJN#^5VA#5V8RBLJW`>_9Kyy`$;@upK4Bao8 z8BU8ba&}E&5`CS?#1OKdiQ!|5l*2CuCQvyhy6PcxUz$7%gW&>pP#FX3M>1@A!7Oqb zmX5)9EirO*!|qyQkVb98!^78+VIl_u!%txjhMn>p3_s;17_a0!d zl>fsHzVleV15qY{^vHWK{FML0y%J;=sPD=U!0`9Qa)(U}yc~Xv4X11rWEA{38V+1~ z!T;bBBQJ*^gUmudhK4R1`9C}>U+81@UqSb4|E=~~`NiLJ<+pH;l|SO$SN=+OTlxPm z6TCkQvI|t7e+g$?`68HMC9G}*#RZHFOB;!TZ76*lhT`6HfjC30K+8#D8&$IMJx z9VeJqfx_|Ch1w5eq|zJ!3#&6Dvc= zXJ+K@P-5XXV}LGmIDpm|pC z7!atu;5<4%h?9}CdsPzCL{OVlv$1QI1|!F5j#P$=uyL92Xa>y?f5w%O$xJIj?Hc4Z z^pAMQmA}%Dg8O{vVZG3#A&BKiGdOQNX6DpN32^|8C!vff95jKX`O&b!9X81I!WU-7 zRiJSKP`hdY6Kc7!09607FkF;p;CS^AT+bc3)X5~=&BZC)&B4jp?fJ5L635HxNt%od z-I}Zn7hf?moK|4u>f&JJ>SAPMcnuntTg1>1gj^K6S9XQftkS!=J)@H8DQlNO8QmY z+!*wjS$Gu-!x`|Ih_JAMl{b!?8-rLJu*)Sv^@76jGiJFp1yrsvFha%~{xdUP{9Dbu z^6_NGl@Gf?Z3zZYKMCv>kbV$GF3Ujt18fXiK;u0t*crBf`lwl1nczP3ssH~?xfmUO zda*KWv1euYn83^sqRq;15!4>$>UH?h#lo-!)Nl9A%&`FV$It%%Z`uRy+jGC>{Qn=^ zrw7U9W#xeTxQYM%hk(?9)`Woi@ji^4-8~=UE#`k^C~W)-QqLd)G8Z&14C*8MWJ3DW zXa4^;1@)mpeM4_X2g~}e421{({SR?qg)J8Y!vrrzhKU@q z3__rOx+i1jEDu=+3(%TzCI$u(kQ&gKxjiGp$4s`)Sz4JHpmKO3I4;0r3c{}${`?Pl z$;c2A&&u%eGz&vWd?Uk0Wk!Y&ZAOmnY*vPg^^C%=J3)K3nIL?7M()>4Obj8QFa@1A zZOuo1+DgLdm0%gu5DzPcn-QY2s9o8YV*o}l(#?*E6`aF4*&m$ z=wxPF{(7_cB4D#1tV~Qa2kkdHK90vB5ASMP#Jp!5|fy61K4FifJ4h05F4yKkM z`3wyU4(6611_qAq`9=ym=L-q^oG&Kub3UKIPsRp_eoz|@*>4;-=LcypaC9>>I{ZA$ zz_1lG#+=N^uoaXqLG1;Qo6yr>;{PVxJ{ zP&)Hf60}9tEIqgQBeC3gkP-3EH^nA8iZarGw%GqoZ;sKWyYQV)fsob zXl9uR>U;m6&hRsXLBd?VmSH969;^R{SuFn_XR-W$n#J<}c^1q6msu?TUuUuWf1Abf z|9uwA|BqQL|37E3{QsK8^8b4l%m1HQEdPIJvHbs=#q$4u5aw9<-ydWT(?muAXqszg znfOqd2{hg_<%PS$&zJrVKkYdgJ}zQm2=NqU*oqXNQ@*%6{0w1Y*z(!i;ioVY!xm6_ zg{^@Dwf_@j(cAyRINSd()?>D}6D1i!{#Hk={Nf+E@>_Vs${+FJEC1w&t^9wO4P5_$ z?jYpmYzP9)hj_6vOpIsbeEoohAq2GUZw)KM#h$;8m-`gCXP;wr__L900mcT~x6C}N*8Kjz^~V4I;##Z>A3Y;hK8X2pY@y1aWYK&&&c)qFatx#eMYX=&5R5o`x$v&J2EkZ-2DGvyjPKX z_F7hlpC1&tXA7`7{M^qd@cOM`&n%GIL;wDVz{2zbRQ^As!0WSyy|X}ODE#~%(xb>d zdz~Wp>;|a68d@FJHt`;??Z*?w{fZ1f8#x)*HbBF;0m)x)iXDEQ!4k%x`GEb5T(6aX z{tsFG|G&5}(im|WYeUfYW+sd=Vh%>JZcf2?3ogZY3vR=B3m(UK3*NwZ3%Hpai4MJD{j!Z1gQT88FMUVW0?5D-{B{C&FJI*U^A{MF-|-S z8JnI0%bQHlInsmH4dC`5xC{f0g@MPlAoHhB$PhP(jW(FrO zWIRhGGxJBYnZr*|9W@!eb{4Wec1n{2c+MQ;E>M{PDm!6wis*h&oYxAkzc^|ef*5Kz zq(OBF2!rMuA$CIRf{n~SKxHoogVwGhuUGwF&$RNtG-MtdRQ9gmWY_{~M}g)_J=j2V zR1KFz85%Bu#_B=y2V2<~CQfOBj9(=&GK8E2ovXqq(yb-vuv6>*f0LK;3_l+jW?gWinfyQHSm&eHKL11e@(Br1js5uDKZiB>u!%uS34r+gmVHL*` zr0!GHl62InxOeuNiU1fqr&mG+z!%TMi5iTNpSTc9#76zXhZgbZ!pFEaZF!YTLlpdf?IzYxDew-?Q>tIOEDM z{viJ`L&iTZ&JO~O1$RV2&hqGpV%XWignE{TDD*s;mC*GJE0ESRh%qz-nWL>|SiuB4 z$3$$^HKg?nAaT%oh858D4BMgW89;fCobzPNLb+xiQev2RLI_m8V&2hxViAKS)L(%h ze}U`;jSaxu|F_zCPjP*@Pesj%P@C&QUf3@RG4L1hpuUvMfz z+MFDjnc(qVP`eg1{>t#z_cBNww(%y=zIV_*jjzm%t2ksFeu|5L;#>SQ$6x2k_6!Uk zIaxbqy^?PT@)GTurOC+hF|4s;)(_*(Ss=NaY|~~raG=iBM=~;OQTU9SpBlIrel{>M z{G7?fu=5)O!&Y_hT8@TG$l_rv3|nA%>@esKRXz!D9y`q>(fyi_yIY=t`?Z6i=dTyg zy!MJuqT9=nVIsE!arq5A?gyIJX5=`{#lYG9nopuTlMyq|l`=4F>ELqsDOzdvqm#>F zrv@iOAu|g@NEegCPp`;~AKVNK6LJ|HcIGiU?Bro!n9#$>F!4SkL*YASNPA@k6GO;a zR)&ip`F=s(?){8>uiqNZp9N|+fXaz%Mu(mCj0}aZnR{k=F>=3FU}OmC=5qL{$;uFz z6PfuVr&8lbCl|xcVg`mS9)DdXXD~7R#5MNFaS@c)SM2aqSP;Zf%Q>5q!Qm%p&))0* z?US+;PtDR~)anAC(ZvfYU(Q@&$jk)STlmt8g5rr;ptSP888p|&hSTY%9No zv#N^%%;5P-kXn!)klx44GOHdiORajxEV=3-v-ql~ z%)+a#IazmaWs=Tb5Xlg-Ux}g6n~@>pgdD>}4o0z4@`?-}nHU*DY8V=Vq!~eTm<~TX zn15^o)u;P~plbP0)y6P11kGlEsMTQlvF*kG|Kj_(plaC=YX7LumjbP+l2+}I0?mP( zVED1^?*ISdptGPr=O}^1G=Bfzev(71+v;WYB+ie)lTL9l2z9Z`8f&iPTBXGpxM@BU zL!qW%*DNi@fK8yVixljf#mVmQ)0^4hXBMO6DIdYGNua%|^BEaF<}7uX2dKdcm+y3pg1< zy!a9PMi$7O@ZKy8TfLV$OaiT2dY7cz+ zAL7joQ9EBS?9%}@h7fOl1V4eDAw-;&VWK!Q!_OC+vM#?+I5F!5lSY^DQin`h><&LQc^J07W|mr&$?FKp zV-Pmz9KCn{x9Bo*oLcj@=<7Ji*wo6IPFKtIExOEzR&V<8S;44;F^4pzzE5%K<+7!3eakmXYIB&flWTpft0P ziy@>(fMKiV!TihijLff_a1I28 z^HY6?osXLxR)WeaP`QPE=9NDvOrU!;VQN6;Wi#@=cHw6Tc_YBESpx44)gXK#V*iD%?_?F615M78JO z`Trp~|Ne_><8WIOGp5@V@Ba^p|My=UmbQ`I{pjxh5ETXn5o~gY@BR<*`2SxVR$d_M zYd-xy6PP{}7db|HX5zqT2iV3PkV1E4b}leBgh`+<*VYpD;780*!-z zWaeA-fthjDduG;EC}jjAL&zCsNEz{%nPrtdBg^Zj%>1h!G7GGF$1J$&0W%XyJ7UrI z{~_Qq3z|pJ)q>1Gjvr7yV_{|pS;KT(<*yLrdP=3qnpjh z#1L}&FPZVX{eOrjH{`xh4{nB^p`f&kR1O~m&5<0;zwE=zuoYx)J%Mlm-Ct^mRCa*; z?ZV6en#0<3VIg3N=LIm`?p%Ak8aapYH}Ke)qUArnJL_uv2GIZO;#?I1PHGq3+2 z;>qvuGn0{Fs|P>BPi*c+j@#P5|HX9}IZpNdExHVfOHez5k%b{d>tOz6UnYhv*`~FV z(95hQM$mjH;kaF}>VF6*JV9X6&$lt_GR*BgjC`*_ccjA7GRQn+ zKkza$fXiplUUJYpk_ZEX2rjj285y>K?sf&=4EmC$xWcm zJCmhi`w3o#5H5B|`xRH4w*#aG+UCWj#sj1VsU4ii3TX#xvm)BTCqZ+Q&~|VZ3!)v| z$)*9sGceA%vUAc5nkLLkKst9ZaartiZw$!p)CpBQIcK2$5oCm{`Tc@Y7>6 z;;ds2W{oasP#JCP@X3LlA;jZ%(Pa)mi+=8_40Noh^MCw_m+TB%JD_I|gU-A0Mk-$y@-l?@2r+E+I+%ZXH4{S+sBh-O z&=AxkIDb|*BljxM{BP5@{~?bU7({#+IZlDf7DZl$5Rm`ZK=rMG>hoo22wE#Rf7TjC zo>idsO7mApe_|Er{AZ}%MjnQc&c8*MUkWj7^*ES+c_mb@7ehmkm*D(ao{XHUKx2o@ zUm$wt{r@kH?B0Xi3?Vwg_}!cQ@qdUsJHyY;|Nq5dXBvUV{azxSAKSqU8yn*U?Lh$V z_2KycKLjKWYFl^wk3Zq@@BdcNoLJX?NFRaR@iEOpuGue9&W^<#BYVm2@DtRoe#z|c z6B@VRvtvQ-0F9Nw;t$l$^@i5@pt|h|4?{=}Kd4UU1h<`;c^N{=85l%hYC!P>Qg?)p zA%q9qW`?MH%*PM{YLmg#fz*K8$$yJ3>%92CzMNAGEHqkelJcrPspUvp{J~hvC5`q%`)*k&_{$ zAC$(R^=}Rnq`mA5Z7&~sL)Z+)NB=|W7#Ku6|K?xTG_9QkS|6?H>hKff4$yfiO;9s9 z87^FUDclKmhc?55OWA_+XJs;Su8L>meC7Dye@HGU{BZci32FvDza-xM9}>gBAhL#u zVT%t^dsmx@Ve5V-2E5?_Y72Ygu=_Cwq#oenV%W;T&hYahs7-q7KZ+f%Z~iA}2dJHl z%Z^9aA!p=*^XT>eTRfre&s04*EAu+UY`o!j?SBY*_=Cn+K(}S1(hv0Pc#s47{N-Qh0z-Q!w)*a*CdkdQ9LM~4d85u%yKzAeHDgPFI`5$5c zN)t$V;0Y5$NDeDfzGG$x0gdZuJ7Fc|Kik6H_G4thj4K_{LBK~E5Ob0 z)9oK>nF|LXd>HuP$iqrRh5@L4q;?p9&dBBB zclh~=nPCg89y`bksf#?B7`EU{v!FSACWbX$x~yYyLR?_rEv?i^I=V3=Tg%8QD&03x-Y71dV?&GJFK(Sp`mqUkQvJ zzn(EyY}epn2wBPE@KcMC?Uc7**ra+!hL52BF=(6?G(HPb_kx=tWF-eg4d`5I&{*e6 z9t0mW?g~=x#lo;v3)F4{?M(-dPXv4dorBuRT(SM+fr85#j2vDkSQxncxP#~+}!6PVrW_`{PMvQHW8hoAoue)s`8TMII7+4-X$ z><3LoF0YmU*v$_>$5OTbz{XNJUZ4E^KLq4Xdq%G8#NYozUPIM%|3;|M{QW<~<6yyM zdq$4zgTMZVJc70hLF3b>KG$zQbpSFx-T9l{eAfT};`Y#SQ_e3)_Wxoxp95Ma1B$c1 zMVCQw!pP1LvYHz*&XC2x5Hz2Gp%6W-9{T=2WIL!2&Bz8GKW}7%^b@#wAo{YQ`e0=Q zsGSHZ-w%Vwh#7uvL9_E9D?^AkR4*<&o4@=I+0Vl8a}j8q4Qj6=e-=fPMJdiQ! zOsKsu_k!wdP+Kt>G@c4wORKdp>++cmS(ia)ovZLMgsc`|*z%g0LkrZ7b>?FT0o`{4 zQv;ea0I36wC%*phAFd8Go(LLmhN%OoSt7^~lKmc`=CB|`NIA%#NcOo1L&E9xyZ>8W zfbHaXoh-}{QVdcDJx`yD0Wzis$~z!89s2w~q@IDHkc;8MrB}jTvq13yYm-3Bj#rIb z3?VZ?@d0fYa5JEeKPC}j#>1EYLpqSoghY3T5)o!3KK~DHTWb8xzszA;JBb6dFV5BB zC&(|LJ+Pp49U#BJ=EXpM(PDUT3DmClVB}b3&&ctL@!9{7GzJC{&=?}F_?+xlVhjo}Q(}#IO})2fpwEm4EQDJhbozwV^oOLGpKSmC zi*r9jyGP)`e}Z---bWfQM6;vm9;6NR`Yx)uS$7GW>v#vZxkZdh=jn*n%tV5R>l}-a^_)$oU?<&kt%NE#raYdz3I_fRwA* z%%C+^pt79fHLQ&Ua@z`!+mP~t2DFU8mlr@~1TOy^e*Qn?1dGF@WfdCWbp-#L887~b zXIl9!oO$IJf0mVht65hv@-b}r%*?b3w1$dsyx4O$-ptV_y zT-~o38YaE|fBTacBX>6_T`Ga(|2bdI;(+WG@%mbKnVXlhySSENWqmEaVFU%aPKx>C5*D)H=8HwE#5*Y_}h z_ws<&Kz;?S^$bT{hlp+-`X0qU`MXyBN@rY&p1$fC1U_;!Gz66xbj<3wG(U(rBg5h` z55rban)?PjYxd&&AaMo`(4MED7e)-0kC{bQsX+G*{5N8-1g-M|-G#RU6n9ADrX0)~ zU6M;3CdnH+d};u#VMH4@HLJAz0n*FyGH?=jES2HICniSDRiOPbp#7-mVfQQDapj-< zV=F*?>le`VYcHZ0cD_Jcza|A8ll1%#IgiH!IwlF)ca7~nG!OU~9qN5(AaT$bod@(D zt{CV&TwpgZb%5s|F6D+GF6ISAnweQUG%XnfHBA{VaxpYa@>D!I>m{@1Dos<5E-u!F zAnQynr2EiBQRcl@K<`6?`YRCRFOa>UF*%s~H$c`4qwITd|$aK-UP`Lpz#pY zw2mBKptV&ynK-&Np!er#L^JHvK)X9{D90PrUx6Thp~u@g(0ICp!_E~93?`uYz=zDt ztDtLRLHS*TLjt@O(~v`gVdo<7zI@P{LB~y?y}Y2cW9WJNp->a*8gL1RouIo-IanDA zL1s8GFob~gf%ffj{B)Rv%N#`!G;VtzIcd$78)MSD1ABfMF0+|U~(+Z+N z=LNye3IdfC;Q9%6_Lw8X#2275H`*ED`(_?42CcVlxWvF{f9-|1!%q%D=btaw8Gdry zm><-UmGR>RH^Wc(IyyKF}FGVE5rU0~wYdKx;I=F*B_4U~#zk^8egRFaPiV^iul3C(!vKpgPfmhatq6 zhrt|_c5g6obaNOxSaujNn1cKB#tfDxm>hm`aKr9v73sEoSv~0&Gsmh~Tw$9*=bUJR z=iH>g>&!sw$3SbAKz(}9I0k5)*$d{1?H+;*AzI)$Hz^!r4W7R^Kx)8qZc^ZW@&j&$ z5H0Zh8ic=)8QyL|tfN9&XSRx|VmsGCXg{8n!5p*)3B(7jn*yyf1MR)h2G6faf#+Qg zurq{cbA#r^Ap8fM3?bV52z~<>Lx?mh!^GQ63_mlF%KHpv$lXBopm{RTSwLvzy=kS* z4-e3KGSE6QUWTn2%nUy@*&Tj*@`LVUl?0E2aPmRfpmk*Y3|r-m87yBgIs9Z$WSIDn zS!~rKX3)&Kvd z#LTt%AgvpF`5m#gtnvH*5YYNVP+wmA3vB#^^Yuyam;hwGTGr=!a5#h3t9kumHwUe| z0?mu)eESbyuXge)!py|4|3g4$O@Y+(d_}0y{EC?4I|v%DK$_!Q{jPpH_d&>dHLdUL z=7rGl8qj*VSMQMQ|Hf_(8V}%rmbVSfA8c0UA4i-Y4>q6OtxZ^Dt}$-N)Ds9&h0Qr(Z@c zh7i!*7N>X^w%W5Z{A@&$Q{;l^dkxjsfHb!TTDyikw?@p}jIgz9p!u~d=o&n5zFq1t z=_QlHPh#tC@VYg2e3Ul=JY1SaWZp^yO1-hFJwDysa z>vanoL&zI;(A~%kTWmpNC(wI7Kxqv$Ce*^t5R(1;|CU$m3|lNgV?1c`DjWEdA60-7HK^=WuEW?hEqKf=Kfa{B52En1umTaee6orcbzf!2M2=Fbj&`XAyBvL8Bz zgb~M|{)gCu;utzUgs#8o)Bg}qy6Is=U4I3-Cjr(EMc0$e$`Ar713>qCXs|Q<{P*v_ zIQIk8@rNHH*oaNk4Ia~F@EJCJ?L+Gyh@tM1^|bLjT}kef;@D^G&w zejsN--Ta3*Cl1z*XH-G0Q(<`sG`0cCL$7||&O=N;{)aq=rVmh=kPS*33=AP}7#X&_ zW?H*Im%CdCkbMfS; z{PTr4!_N+Rho3K`8GeHNAR*ZhB*Ck;2@L6ew3d{^4ApfpV{s0aG4n`)U6M76gLG7pxCI)k;yDh=z zs%bEUfZg1TXfHk#cKG>#8ItF)h1YBb1`*JirYHWgn}N#qlhC%I_*;ibw}l*jV$%ci z3v9n5M`q>^W>bfs&5jIP|FARs6iWo%7Xq;lT^)y{!%huH1``G`$Ub{eoP+jmfzA+P zXkb{&(7?Esp@C^FLj&_#29*X|h69~854ahAo&fE6U|`rO&jJZ=&|NH`v%_QCR}7IH<1*TE_u8J9ZYdulfRX zwy!EEEE%SN&in=K>j0Sp+gJIh8RS>Uc_pxYXb-uaR)W+jL(_1=@1o0z%N-_x)PmH& z_MW1v1L*;cjeyJtr8!VP9>fNPA*lU^E06qPclepW#IWT%Xx|GoO@q>cqC8?;=Akm^ z>`h1-ey9#g50LW+Utqbj{(&^=9x816O+jvg#R2GyJoL8W18&GUejqo4`~XXTE7(x` z3ZQ;M$D{ut9mWop8itU*L5DGeC8&?`0^TLv z^$iZNGK8FF1GW9d3GP8jU||S3%>_{lYBw^lF@&7vL+}@{F@%V+GE6LGV)(gY6JmYc z3MP#%sih8+_8U2TTEM{&vI1=%ibQa)bH`V&Hzm zN**Y?*YSrYH^bKX#tfG0Aa~9MW!z^sfBp}0ZFfWHBcOI3v@H+1haIF3w2tvU8^h1V z|No1>V@8+@k_V-+Zazp`A7uUlG&PDGkaoQ`v|SHUGv)t(agZN*|Nj>Um31~~WnBh* zTn@FY1Brvmx(w*JTn)6W1LZl;o)k@H;@kBWxm>fElo=*+2xH$<%CVTi5>!4x;~)?e z2OxVv<8rWY4*CCITo>A=2kpfH`E4~L*J~GchLANJ3|m&SGi-4NwX2cZ?I1Pawmk2m$ribV2PtJnEX+A?nmX`2Mw=tedWdL~qx+}n0i^B!`aWvgKMSe9fT8Cer0vg* zrl;#3ZhIEp{U1`M#IiCI-1dj;^?re+?XNfwapnQ~n4RN%>}N_j>Y(-)KzlVnc@@?! z2F1y#Z@Ba7qp$zLXMTXvA9C6Q-BCwuzX3gt7XSDk0%}8@WMJ5Of(sf)pz)Zi|FW zz|n!R)NmUWO&A|&%nd*S6+bOr@RKkPI(=MosBFETTBuJCT3VU zR)WTp6K6T>OtN#V1dYLi+9~yQoUk$1zZrH6e-o4r*n-Z^gq)M92tPNI34CtmBEJNs z2HT8R4wWw$7)%n29CjwXa{!z5h@D|A$h=4F4r}ZGv8~L|V)&cTbkv4HM$wN!W|3b) zQ>zW=yp3cl$4X{KhONo394Z$xg4VOUfX_>RsqB;s8;eEH3yN0F@UubCV zBRuA#o;imcCa`l7mG^+h_$Pqo29ev@pgB5d8k=%}kzq^nzknZqPd+5zp$Rb*rcfwkX1GmEVPjkkg1U}r;dFffR~*ekHLyRrBuI(3uG*nPj@T7-hQegU%%}^!%mF#1PW?x_T0qBg4eg1kNRy&&>H6R2G58 zY$Et2x_|I7`~;1=gU%??VwCFkVw668nu)U;-1iW5u*ihmbpt-9ct< zNpycpVqAHGPqO=k5W`RTW_b(w$?_KRi{&lkH_KbdAC|X}zbtPd|5)Ba{xx zMY}jy8-i+*IA(Y7JMIu+WHkKg&bU&6jUi;d6T?RiriP%7rjA+SA8Rjz&S?jQC#cK? zg$pR{%QG-o%Cj(7a`1?BGcbsE@8@E$+|S2gxnGFEa=#dZ<$fs!%l&c;mh;&d3KuXk zgmkhoTwGT{TjS}<5cmaZww4uI9VHlGV3^Jb24*w zYc6!KJjujh3G(|NW=<{8oPISkXLnY0)eq0VwU>iGI!pq&yMcirE9s<2GP?R;JhsUdJ*V6YOHx#{Phc?j#&?snN~v1fJdA; z1j^5qptDJv89pXK&$E9c?C?{DfkDKclc5l_zI8q`!^c+?FH2|PA0h$v%z{k=3m04^RD9x&o1H)F(+J_7dhAorX874NM-78b} z36$3$^CGak20N2xG8e~)S12o1X)-BH{`dSmr28Ef} zY0!C4E1-Ajg3fT#WMu${*<>zE$ zBg4e~j0}ZunY(B0XXJeSf(g7Y_aaC>Pmre@v@iaQ;rv;k^COs<7(%=l9d^buG8DdI z?w+N|$n`pbks+ju%i(7>8$+N^WcClAN{t`gTnsy3usi(hU;wR8bD0d@N5#nSb1DPq z{6s`Ng33b<(0xhJJ~+O+IY8wvD6Xwe6;HbM^#4}l|Nq5Lyn>`N(Aih`?*0Ycx3J** z|B$U%)`T=pf}A&t?R+9fPKGU@xq8suaiDZ}fCIF?403-J#{x#nsZ0((cPP265y)eTy|#RRQmJ)w0hp|ii@k?L3uezEQqYRGl0M7I~C&t{3v7!L z%gRnZ@$Qvc3_pb%<$vHhBM7u-7u&tcu=Z&ubPSv`Gt;7z0n|2SSjDN}urrf^!34B+ zVlD%N2&mo0$pu;CAj$|{qc#zAKIs2?==q?`43_`d87%*EGg$uTXR!P)%wYLnoWb(H zG=t@Tc?Qe>$_$qO)fp`RYcp8>*JrT&Z_Hr%-<-knzcqv9e|rW?(4B6e`VJJoFPI&E zayrZm@+@9n^oqM-CwFZ_kXJ4DYz|G%*(*TnweHRjn$E=0{g}z&=VE?_t)RPNN|+pe zeqmzx`JbQRX9v<9FG`FIAq`9pJ2@&VelW^9{Ct!QX~%-@f;sT-{}xpS1`&|{4mC&k zy)dBjfk1i~D=U5=tAFtC{}#|a>k#$saP=s5h+^8o1GmEkuICXO#9i3z0M+&2euF3^ zyd|J*drs(hI|nqMg2vk=v5dEa&N+d!?Il-PB8|6$#6fL)P<{uEw@V?9K`}b)e8J4H z^98@d&##LaR)XypgV@i&$k`2E#{xRf_&@X>H>evFq2uib7#PezX$90?1f5|FipPfk z?B<}hIEW24j}u}ZS7zo8(3veE=A;X>X7we8-Itj4`F>Sa61@ny+#6P z-3J516j)jY*#+riAkNgo*M5B@3+~%bc){fG6S?0An(KKi&#)CVmk08fG`^lGee%iAGrSpode%z>d({gB zd)IRWOC6NA;Jzqt!Sztyg7c%i1t?#yU~1SY&&=`q6$eAeW-*EGL@o#L`I(@!QN`u3 z^S7|W&*H@%D>)g3PumMJY;5=oTKn%bS%#HiVx_;sPZMV0(;feuCd)I*yiWS_KZFBo zJ5J_xhjGU&&>Ap?uXUF}@eOM~fZA~(EDT#R+#P<-Z-Sf`d6G$_n~PBd-Y)~41K0VA z$bK0UC%AnEJHJkgQ5alL;OdJdxFhO`6I?RgWs5mhzT|fJd6J8>JJX-xCumKkCr3lj zOMZr*pgF7G%nm=Z*%?B_7#c2FFf;^7%0ljlk%Hd01sXE}-EjsAS5O_!#l{dK!q9Mu zmw`dVF_B@S6DK5mVRLU&Kxc)5)|q8iT7d66W1le#bZ#i<{E-!6V%?y1+AN9=J3Cky z1Ro|dOjKfM2$JVyD17|)f5;Q|ALgJoXy+gA%bJQMlR$Hb9IOlzA<7DD5;$a9{^cSCTzfy%^D|pPDg<*>pBL~Kr;9eu4JAo&n9*{KS+4^+iwq z|1aK+MGka--7(Ny0FvCvAE3SbMVC8&{NDJz|{romqI*3qH3UAp1di{RK3yXR@K@Ek|8YUl*F+LF+O= zdq_a}og0?l#aBIou5$sk0YK}JUobgXo?u}x1&vLB+5w<`7|4I1e)vkHbuK56=F?9= z=hH#{JHUst=Czh$FLLGO&!b( zCZO=~U}i9dwdKI;j<`YVj+kI`5I-U3Y(v&qBh$pKn>Bn({(gS6gz5p3;| ztiw;x8j{DL@L;sRhHbnV6gC;mXzQLRw4Z~);U|YG#BR`5pK z)51bA;?n|3{CxRux)-#c0MEK!;;WwXF&UZV$kz#hoalpL)O|{3M9i1pl}C;MaIAXTS4Iu znj-_1b)b5Vmf;T?&jYQQ0qqgUgw9{+K>aZXv@aKFy#{ElMhX{02saPImQ!2|TjG$` zbAaTIa5IE>AN{{Yi-%#026UY&=*&-0y6$4+eZ7Q-Aw>J+|1Dg+3|ri>nBBt55W;=< z|CU$03|quN@m_^OCeWTwhQ0qoq!}1QV0^{B|3gIn{}+D& zmgji=VDJAB?tlNqVe$`m{|^DB^V6U;z|g(4p#AnlLDr6R zvP0I6oca4-eDzM$wI5nL|AWnWxC61j9erM&X~+K%IR*xi)qBwN?t$vvjYse9{~`P! zy<5@rZiVXIf=BNb%ylG3{$j2ncl1DA69Ot9L2X3Pxr3ng*D6Ltxp(0E{}51ptphzX z2$tSlm>5D{Gc#;i#l)~hmO#8FF@VlvXV?n5I|dd{3|}GsBqyF8L)VXh_PB%AkEHws z?Q!Qg1#%n6AE0^BZX`cE_y;))7PfBzoSzsW?gy>UAmn~0CW!k%=RXk86RFR1PTxxEL;?VvS}pmS_tXZ(WBH(SEU z5b}nZVGB1j?7d8DCxOx+dj3=bx%>V9Eub?fL1%g*uX}k7b@xI>h7g#36- z7tnageJ73Apt0nYehxnsD$9N({QtiN)JJGwvcI;X$YCd_FAVD=!|w1v@8^ToU{SL# zPm{hgGvh_%J3ByQ3?0l2rjRgUScPp&0o@&-b7Eofj6SX)3LRGft@D75Er7-ukom~> zWc+7_>{kbkH+=m6UmV+<5@TWjzyqxKnd_TAZTrd#$PAMypbPl-Uu`fNW{F+ zH`Fme(0mnm-pGvx^G4ia-7CCEm^X4mj0bjbiFI#T#IdrIOT2rfAHz@KgYr9Y%^QK{ z`aov|G_XL%(6PCMM23lpoDM%h_JGz8fX3=T>|_GtWXu%|LQj|(w9xYk zY^>}7v)n3>IiUGM5DmiU_sS@;FqoLuID7(~n+1w1aqxXi4VPwAmHprlX1FNN?DC0$ zamFlATO2gr4!WP%fdzC98OJKnnk5TXhMz0`|KDoP$nX=C*FpX1`%I#*8UOtc0r}+x zvoQGliwDdQ^&quhKzHRZFie@x#PAaob|7`2H4C6S#2A=R_h!f|FjxvRfc6Mu-v5H` z?}LS?buV&R1)JkTo=X7D4|oj0HE5tdEve<@Xjn8{g6(}lp5KC%wUo|f(ZbCC%%FQ` zm{$HuXI}Xuo@M2?aMqPy{MlCit!7{O8|iFm(49p;z<0witYY9m%|D=hIr4v)R)W@{ zS}{BPj9Kiol9N#eygopIgCXR1Fyl(l8UblmhKa%Q4nIqnWKMVd1Fgf8e%*v~9iH^- z4A7hpXkP6j>itGPnHg4XVPV+fAr6`I0jDfgYw;Y!5#_xGzjSxxVy2a#wI7=NoZX)C3_pJd zJFXOOl>Y%5Lwv!+uoE;6$H6Gk{eq3*=ZRgpmyH=3f-;m&%z7cju=B*f{L3$xHMBSw z8H8R0F<72BRB-u47-+s;bk##<$h^k`IfkEK_!xeI?gE3X-E&|0#ouk^w{X{$KjK|h z{z`XV`6u6L<$q?#8REFtO@hu0Vq689KLgD{XsEic)Mn%WuWbSOyNk&ER-7oBr>v;leFs%^regd=xQ;B`$Nj}N$mre{nMH}URbZ|NBT*1V!vqQ+? z=L$B4pB+UGJ3;eqpz|eHI5Aj?F*Ho-U=r)*IO<>ts?$JY8VA@ICW7i^*xV*;JrwAE zX0Y0W3==_Xq8>4W#sc@lHUm!l{&Sx&r9mK2*6G8KbjsO3L$Y+>Y zEZ}4K*-_`PbA=Ma&W>rf{zZ1+72oWMZ61%=#mT zKmS8+|Nk$JI}I|f0;L&n`djLXlK!$l>#Gpy?yuV8 zNq2KGN_X!^S_7O3U7xg?z#8Csr1eP}{NmjwjF8ixWVaWi)alhY)+Zg%L!>{@y1%Q7 zSXZv(ljuHa#_&_5QT|5;m&4Bv(D@ro4nI5C7=F%oVz5k*g2Z(LAE>Q^JC2EsFD*un z*PwfwLFI+lU+2l(m6<<4ZBEb~;tx1sam58GD@NlAe5W+FxB{J12HxxJ#9%p}K-_@l z9~f6M>;$#585kh#d1BgKBW)i9a$5=8x&vyp$A43fSp^I$pKo+%D4*D zp9J;)64^oL4l+#8WOVq+$qMnf_JK_KTkZGVfW=4iB2bDnk z=0#V*#!woV8Ma#=?V43?VDn7$$o0H3Y%zjR%>_z!1VE>RbOb+lkImN~>@eFT65Nu8Nd|8H~ z2Y>#DfZ`)p)WKptBQH2kN~Iir!pw+oWVD2>=ROO%H-@3%5)b%ZQ3voiK{hMHM9?|& zpgU!HE3<#BV|1{TXXMLv{Qo~hkD(#xJu}Cu{~&u97(&ix*ERJ?pF?@gXMfijcm}JRUkXx zFiWkHhsJ$|sDnkXsDp(()cv4+Rvx0_-3+V_KSASgp!Qk-fYGHpmT*Ag5EK6thx^ki*s4I z7X6vI7HdK6PDXxkSiJxLU;L$$CV1b6=7;|#FNGX_zI^|G3uuiYC`?{)fx<(A%L-rcle1a= zx?BeBUDDtJl|PK&aV$`|kj%oc(TR&8B!h+FVm$-LE6|>s7tGA7K;=M&z=2zwq7Iil zKxc+1o}2~RoA;8FAq2E{%0=n*Ihh-R zG88yxXEHfhaxyYlX0kb0a_DTW-2*Yaw;-dW~w<@a;h>|W@j!8t|8X?qQ}8O8|>@( z9vU~GlyT_#5=|O{o-jkg4PCC$1Y#z7z5kV&c@?Ps0Id__5N!zJU|LWl#=y~i;vZ!H z+sS{B{ckIn8O)FHIs7~V+UHQ`@CmdZ4K(Kf+VjrE+z7Jy*)?3V zwKKDK)H8~J%OFtPa)QKFxMpXwI{bXYEWGM1GsmhvMu(sG8M$9OfcCN|GE7{{3fZsq z7PJ09>@;AGgI4gsoyedN>(%v%2-S43Ep~5kngVW*X2?mBO zptU=kf8$Z|2Wb5`w9OI(@+W9t%L(XSSZr+!(3Kg@RVrLsuwpM24k zztY84{)iV}`7K;xvqAGi468UV&JU7g z;Ox$X?YCg$?ADTWuw2E#V3KvuW##K%4wJIA7=C6eIsAO%9lR-k5ww5~=2dOn8*Y;Oc;FA6kV zq!~H8Ym^;Uaxu!h_WbKI`2ZtB2scB+r51PSMFyNdEIN&JL^89)N8-yzFDAq zzaN9n!DD5Z*y9MQ!#Q7r!X@63VPgX~LkMWyUnaN1PYXtw(;WX@Cd)I5y?(^b5b{!* z;V1Sr=VGr<75NuB~bG}w&0iCVQATm9?VS9P#k8P3QJPTe22p%(PW?%?`l|!Jq3O%mpF@fR= zs-BghuoF!^D4ap-h+uI(iHSj^Ls+akgB`rTT?ADBYca}ngYNqEV&p!}&47KZ6Ljx* z0yARV0d!|Lhk#gjf-=L(m+}rjIR!YoGr1XliZIGsbpG?W%qa+>11@tag6N3LoQ5De z;WDQqh|ajo83>{aE^{V==!(mnh4L0sjq(&CrX#~d zP+6^+$S{$EmEmIo6GMm=WBiVIM)B;#|Nld@8smS&Gm5@u{Qo~hgAsQb3bF^e+|*`b z5J49MogMaonPu$*`3Bqn^=vC)=OTmdpa-of1+9yCjpGh_j?By-oPTRC+cPqJd??&8 z>&Icni9eeeCq6pNIPq~a<3!Lr4=7E6;`I@~`%2jPUkB_N%ozkw$Jc&=&Yghnit9874kvmIAjyz;^U| z!0m9bfs}=w&@!4MGtdvVEaJ0!S;c6 zgYAQ6rimc8KX7K8_z=qe#w@++N51RIhwctPUrdIW0n+mQjxI8n@>w|y)gT?1FbH7et_W9-b_kW0YWBiZ(jNGpug7)-4&TPY4mT91c zRV*Weh!mDHG(dF*q%M(K6@|1$6C{pYmzY885>Q$JwG&|R#Lvjt{Xr2_p9sA6{OdaT z*KOyOjw}oz@r?`{8~7MPv{)G?zT|ZHsm&;GI^(bFWYAqCNgNCzFAp=U#9lvez4kEd znDs)NX(hwUYIyzdUYgJN$gl#jxe2w8KwO8SuZ6;p1Co&Q(lops|~V zOYgWHema8ACI$6Dofsy9;sn$e>}iD5UrN9KhxCHugclqqec(9Z1IG!dy*Hnk4;&|b ztPVf#Gx34vZb0Jl%zWTD0g2CN=6#*O><5mM-p2SJ_nCN6Aig9(nU}gBJ z30fn}z~9Zq$PcgYK>h&jv3d!*_rZ~2BB46(KO#8>w`;Ai-` zfDx(g;dl7?Vztvs4iS!S2StXJFNGa`a*A+vdvY@Tlwg#z-~`nnf*=}H|A1&v{R5&w z^$&;!)juE_RR4fzQ2irk(fPmPvUH=IMb>|h%UlydbiiegVUq4l%qGKa6jPsYluADT-Y zCTXQO`~=;l*UZQeqLl$*Yk=;tZf2Uu1l^;H5q`c7KQpx)euB&bnWM4PVUlJF1%p4FKc3umpj)T?LpmH8k#(~Oj221&k%s;?(Lcow!C5Q&$2mGjh0gac!_UD1dOCe$F@DtSU1>KLp z$ic7^bQY1k1jA1G0*0OP7Z@$&YnWEbA7HSQ|HHl#6d&>(3_BtEKz9-_{FL{A)cXvK z4u2T}82*CJ*<#@3@MCN^WuqXY06%LBboQ3~AMTY5G7J3}8oF%c|M0A�`|_rKbCt zI~*&W86bBRqQ`0D5yU=n(D`OR;u%+d3uju1e8!oEjKfaQz9Z1OstzUw(~>5piJ)_y zR`9v)0Nq0Y%8M(Yd#ONseL(wbAF_hSL4TsJYlQ5V1dYdwfZL*Q^~~7SXLdPOt^}RQ zkSH)Q@sPvLq&~+=P`auA#|<8b0L5uS5X0Yurc*Yccm>5F=-U-Jh$_YBk?1KIQP&wtZb;67i&CD5H>_{QA9X^O*Prw1o!O)TRo69$K$U!Z4n zfaV84^W4*!Fz;;EpVnwTbjXBGkPR|B7)veaP` zY`}r}Jf4T7u_mMusgM91c4{XRUO~ zIsDXAWVqNV$M7>_7Q;?L^9`W(bLqeTTfc(B|Kj|h8K85sA$xEHLFeYTms$ijy#_R&d00_TZK6qpyivxPflgXSrQ_d znL9)o7$z)0yQd2@f62kZa8aIt;}xi#-C@Nb2)dUnOHR1kYiIst4aF0)JQz8;L1#dL z>MBo0hHfr~E0eew9()4bMfQrB;j{uHR~H8(R~I8A1Ni=|MGOr=pmO?)zvD{K8g2## z1`%XFsN9344OpF$cmh$*z~n&r7=)4cMuXO!Ldre|@ZM|C{#Ga-BW;87EcMC;$oYP- zx(8M!X#V|g`sV+CaeU`jm@+v06b02W84f==I2|T(oGhNi$Ea))d@bg9kBBB1hmfLV1}eMP&o>67y2DYkU9%;rwu5*!qu}egkV!oY`O&1SD+~Z=N$~F6u62nB$S&E?g2(%s#xg3452z8GpdN~S8YZcIPbi#kky;}=S8iGLg z6S4eg2A@Omn3+>6B?R*&W82H)=;PTAF;U|MAqR$L++x&k_ zE9Zmi#!HTtuyp!@g~1e*{y}@kL1`bfM)f81&Nt9raZ%`Acm+=EX&;p4PY_7!;I;!a zy)*Jd)2}jU9YX`;&M)|x7Kro?axchTp!zT)3(}Sb<$F+`hn3BoNckRgS6E|K#t(4b z=XLlA&-+k&LHl07`3BA2#wv%M3!!bjrhg9LcHVqDhM)CbpmlPXXCwW|cU%cO9|@Fh zLHZT{{Wtvriua52gJur!J$A4#Bee}-jdK4WW*Z`7F@q((d+b2*1xx$A|No1l&yj-G zMlqW>{5;IWu=N`=)2i>xkoj)W1jt$$P#IUwz_10hR`vxG!_P7h+Y7WVf#D};{ZfaM z!_N#R&^hd)tI+2cL2Uu_yn@_s1l^tb3(NhMpm|%6o07RecUrQn`p(R>3bxK&1ne$I zn^Ys-;pYn`hAj%op!3okerhH&{Co*&cY@kb@eDs1m>9N*aX9R}&&FV=$c&h;f#utS zTUvrZXBDt8GzfwGX`jyU6Fesq&+yaX-~X*<#SS|)xE*%hXX40S1gc}$7z8zn8Fqr& zkKnr{811iV_&fY$s5JZGz`?LZ1+11OyNQ({gt@?Br!pIZsfN18N@iAuiOS9lKkXTr zUxV%nRAFV9sN&85zQeVVogqZS-r*-FE5k%hd(c>3Ll9>H!%hhihMyc93_ry$Fj|7z z(H;y8CZaWqoT4(mf{}6b8 zBf1-r{f3_2zc4ee0@;zw0hhnHfS}_<`a)`NsohhAk`w4m;;SL*C}7wrCcyAhqyidOyvT7ydLBXd z+rs0J@In`VcpQH?GoEM(f}Kx=(vL84`1zO}bgmjC-wT8D7v%gRP~LvQ&aefPCpw%! z;UKEj0uBe!?3e5eAsv1WKSe8(e}r-{Y*}37u(O_nq3|FhLr4cG?6?@Vti0rC3D)by z@UxSV!4x!)x1xw)C+Hj$P&*KG?lCA0gU)iVXJIHj$i@(YOATnhC#UjG*)(3cm9QlqXeCUj;oJk<$*kT;h?I zAbAD`(EXn%>+=>K!4W4%T7rbJs6TkLB?z>S7h8T&T-E|x7lLAk<5AT3{g1xq6f&O! zKQm7(GxNt`Gl!qbte|wxwCYL{s62<{pA$t6J2RLWOhg$PE}isq_z9ZViWg=0`IVV# zm8K$O?i4h)uLU_rY>T(3!_Rs~;n$!wX5NJkJ753%Z!-1Y|1F=H!E-8LcS8L#1r+um z_ErXlEep6Dc7o<(VPXsn4MNCu1Z!jGfdVJ9f>fX4V>dO+dPZ07Lu@!$Vj@cAF+NA&subT%f-Wk<^; zEDT#&iXC>&=V2&RWQF8qj$($L^5P6XLGub6tf0Isu?n1r8SSru;@}~(1bB=PxZED1f46zz<@FS&iJw^ z2-Yt_&-0*oc4mXL+dz2%wATg{&!8{@x%)9QQh5yuXIOd7#;^rco^~)Xn1IVpNlxbb1+}w9Rw0kCksNlXafIC&)UZPjbH_6+K`qcUk1nTp2GJ%&mrF#F1D$69 zOC!j0ouGArj2W3bKzqeO{y`7N!)%c99u|(MX&e!bnQROpE1+roDjUNVaQJdC6ehAW zgzP`WVEKiaVGF2lxbhIg#ICFii&YE^CR&*qpz*Sa@{EihL2HCoGI4Y(9Auct$DGm;E%V)JuN}b(0D@*SJ0YR(B3%?X2`l&VFr$FF$SlJpnQ7r zUp&W&e_R}={{J@xoq-MNTY&u0!RGMu1tY_jQ)~`9JB=77YFB3L$ocDexyQG5(weNC zAGx{?lh(eix!jehyW=z)!_HUC+^fK2k^laO%x7cx393)-Gcj0#?8y8V&yj&*2ei$} zw2q0d`&?%BkM*h!lit_z z%s!Q=zatlHCokB}g&;e*7{PYdGlAA5Bf=guCjEq&VHM}i`9YctoZZTd4nOM|7+!V6GJ2FQ33Mw(}6hObpdzApvV#{rE4q3=B+ z?p$U_8y#KmWd?>V2{`sGA)n=s+-KtEaM)ST$xsM7OCOXcI5`}CX8m=%oXyG*$n&xG z@>^zZt+gL(FY9II{Ls(L{h^ccCnzjo{$gZc_{qe1R5r~P01 zk1Igy0+>;RRQ;PrLf4Ym)&8*E=FgVrQ4SbkM@`1ws6GzJfz>$A*YVle3d?Zes2Pzc(;(!u6n zDSwc$5Ofw%2bTkQZxd)8KnI_LrTkvTLeLtr4j~6i`Ci6C&^%v<7)YFRi_;F39KIq#9JUNX@`?_H4Wi(&c}w}d4224!3?ZQPkN>S1em-bM3JYtb z@G?gVFElkTjj0=654aE5g4SfdFouNFcVma2Kdd2ZEWqiUfnkCsBf~_{o@`KB29g*x>p>uzFLHVL4@aJ^`y5>pfzY*uk#GMW}SOk zJ&B)zVZwVxhKUba>(?%5wO3`I!^Kz39IJd}9W37b|8IJRjp1T8Bj;(*I`$mHo>@MO3|m0<>SktJ@G>%(_-1Nb zfY!i)?vVl2k*}F~R)P9SAT{xs+7>UFMOSHwI#^s|W4H(kPfl3}im{?;Dse{6ZqQow|4a;)-=p1D{%2zN zctpzK7wB9aNIy*s-2RtmVK4;EmxJ;JXe}WJBg2*#%wne@?Ky^tT7TnDcrkKxYyIUu zvHJgi(+CCz^RLVztDx$4g6>R%vVXn^X8^4|f%jiQ>Hg7UhKY|4gZj#%t5_Nq1hGQf zeFvBs%pMwp+R2c5>Wi|&&k!btEuYmLehM>z?h_GN1s;=QV3-1OBk2BQm^~0T3gdL+ z-|FC%U;KksehUv=`6E7H<)3{2mH(Mp!E170W}v$jR3F3SJ_j?deBsZq64c*?iG7P_ zT=^mz)qm(^W1?Ui%Gex8F9V|k_#6vRxsI-$Q3Gv%l>lU~GY5l%r8Wa-PabzR=sq$| z7KVvhEDRGtd*?vqyN0NPg*SNb95;CHpFAUXHt6g!2Gfoxh&>HKAR6D?320tKf|+5W zIJ3h~GXaO6^2{uj9E(Bc2s0Gsax;MUB!c!kg4#4(3=Nk+=|LN`rgyd9a{Q&KovuET5@88j70PUOOgzuYMhh^W~hyVY@UpZ-Ydo6UZT*bm*0y-Ps zi`n6)7YpdVf`&`G*%&6uFfdF2-RUfevY${B944Ur^M+Y^mAx!O5omvYCUid`$PJ*q zq>w#>T(6rL8A4VvIaq@3UgUu9FNCCh1wjULkex8Kp!ydS9-we2lY;CY1g*ExW@ZQh zg~4kk2hf?ymT#Cjv=Cvy^ICzOAtbjl3%rlgo{v8O(1f>zs z9!Ah!M9_Z4QU(SQSh!@dFqpg&a`>sm!mve(0TL#lyV)c~rI7X$5*HqjdyLS-LkhaT z5E32>I2g=9_QBMmga>p#B{)3TQN!Z}GY5P>B`jSeaG<6O&{!8S=>oK$@`aODH^)K; z%NNWHCNDr|i!g)s+BRI;#l|oZb3dgf%KlPNdH~Jcqo)VR{!-X}N{D|I7#Yk#=7Yzx zm^og9&VU4^71;h#(0Uip{zy<9aWF#mR)W?sV%u9elgZ&Hw*8f$`#b(tO&>$EALy9|g}(R5CIAQ~<5_1+5)HAGZ|%p9uoqs|^~z z0gcIm&QJuE<)AZYwl+b|i~-$;)(JWrol&$~OVDAb*8l$|FWDKu>tH}_U{HMkI@jj& z|Nr9X<13)D6?BKa{2w;(It|b|IR*`ezl;q>!RzEe_lhdYD8bi0GV^lyDatJNV{B-( zk+0!g$za3qmqFoxErX1bAA`(dKL&*cTTuHR+g+#hwhJ`=30t4Y%)s!Ig@fUzyaB^b z(3((aKCtv)LA33mV&FBTFPIsAKI~=$hY6@Hfxgy*L(usr_#EvU;5BkTKzE(M^drx4 zCp`kKErrd?F-!!_X@Jf`&V-)z&hge^Qid96-WqbxDr~JGa(^7u?|}8iMHo1`MH!qX z?q>q+=YjMcKyBChEZA6u6S!Ro8gt8VVwkv}iR1N(rjA)JnT=P0)@^~-$AZQlVCiB% z8)z;H)K6fTxPKADO0YeQ3yKmzZCR)tpu7OG1GER3lW{>&CKG2jysyFtu@AI20CayN z2jhaG46t5~*P#0vUotD8*b7RF^O5YFzldQa=nNH*dyvPjKxqZmcl7wLIqwyMLVEKSbY zUWN`kU;X=U3L0b1`0II@!?ku2M@Ghv6^sm9GIbp$X}+zw4BB_avDaY|hb+TH;jOik z9y3GQau9bR`kSEh2+_qr<5K^dnJ@my=UDkGopa@nc&?S-!ns#|@#k6jx0-k54`ycY zxk>-k8Gdqs_JD)j&a|Ki6qgxDegp3@Vs_Zc$p#t!=V9RNmSS!Ql44v?#LFPn&3R*f zkRAhPw~RgBjG0lFnBA`#?=wyWwFy9J|GT!s&u>l~6JKyS{(Q*ovJ&L}51@Ml7#X%c zkOs|%Lh7>*?apAiN9v&U1Py?pP%_b>lYk;zA$F^i7juxRCZX&p(-;QR1PpbM9SyRjNp6@ z^20l3;Z>k`g82iqwu$2)=PFRXf4SOWrG_fQ&!@t!nxK0rLG3UQ8>If-X2+Fpr5%2P z;`z1_!%j~|Mk9^?@g4Gv(%GOsx#oY4j*kETO)D7~M82sr`~>aeZTSCR9CUugivRz` zSFtmg{9@)>^^=)p6)Zj&g&9IJkmBP9GdFll|Dm?S&j;$zelRm?eEk58BXB$ZlxJl6 z2wE2k8n@~E7thgwGCl_x4*-`D+>SrH*&KFqadUQi1#(Q}VQvWG0i|D&h9JMnj2-9y zx?g@DT03by6My&n%$y$=R2?P>)bY-KooTS64^%F&GF*Jk%(qIOk#S?=KhR!Gj&2Ta z$XMNcCI(9mZb$HX2rg%iiJaVwKRq}(x}`W7c0OU2T*V>M5cI;2W45p&!^9^H3}zs= zg74&FV%Q41lM8gVa|U#ee>|IN(ce%@sz-2MUeJwRrI_P)aWlkt}wr++&Cu+zjp=l=f} z2d%vWrK#Ni|HYp$Gp&keV0`Vs#Sp^G&9FrSTF!AZ9J|EH$laa6z}U_47gDZsF>-fz zFfhJ8$;c4mE68v$i-D!v>#yTwua9+;UYFNxdj0?CCvQgXZY@EEi#!YslU_3Ot^)1n zVFc~xVPFvH`Qv!G=VRTZZbt5I9fpP=kX!=`LrBlpy34%G4MDt&3ySze8iGLWCeRoR z=Xx%F)OF|BHj_ zv&W2#ptVHcF$LIs?ZR-}cc(85!!7qPq&es@GYfd!1EVhR?z<#KFMP4N@=9%3vwa$zUnZ%U~%l$Y3ci%3vuk z$zUlj%U~(5$Y3e2%3vw4$zUn3%U~&Q$Y3dN%3vvP$zUmO%U~(*$Y3e&%3vw)$zUn( z%U~%V$Y3cS%3vuU$zUlT%U~&=$Y3d-%3vv<$zUm;%U~&A$Y3d7%3vv9$zUm8%U~(r z$Y3eo%3vwq$zUnp%U~%#k-<`aDubo`Oa@E&xeS&Zir_JlDG5x>;C0lXaas+ z%M#JnVzQi=>BJ1)o6FJIiD+*fWCE|HhJ>Z%L{86!piYJbMe?GMyQL5Q{~sd4z%Zc! zZ9RSi=qwv0_MaI}mJ>77*nc92=YQxqUZ5}s#UJQA7!Vs&r@deXyBVCuKz4#Ka$6E~ zHx>hEtXYL&<4Q)*y0?Z)=aJ+8hW(YA>V3;V%%CH5r2j~PD=?$a@UwS)%BfWv#3%OrPcohpHWK916 z8^aa`1%`>pegNe|NLUe0`=EUiE6DHzNDn?gtia(1Mh1oniVO@B(ft9+Yalm+@=L?d z|64)rPf)zV@+7P*d6?H6q|7nnQu5sGpPbpReQNf7`w65@qvp`;4hDv;jx~(4A2Bn7 z$_x?EUJB5@JCM1cbn~#AVI`=~12Yq(4}@W9?IAP6D$qTYptjDVW`>ENJ}XEblrCXs zy8UNny!geRY31K)=9L^Z2WOvPX4q;{!!Y{+Gidyi37noldO+oX0~5oR4klsnJP#;e zT>+2P3aFfnw4*0{Z7W;iXv$k_#pUr>0!_KR{bh;(N#F@W2;pmsdy{58)b$PJ`~!&IaEtDB7LD2I?!K&R3$x8H^807mj79W3$Nqhn;~08XE=W z*#l_h&;ih$!q9y|pglIoeiCKm>;kpxL3uBUp&`hbp(%(ZVGVp-T%Ltt;{qngo-#-&{F+j%SL1Fd; z+Gj&o4~rAfycQ_FL2j{UWO&VK&^e2f5&QhDVmWGcdb?uEsCsPWIR3e;}T%*p_-bvOy0n_-w>!szf*6tq^Fp&te1hx)%`tIiKh^ z#eGKp?1c;rA)vGE>=}7qgT@U(ZF`WtpfTMZ@OVG>YtMiGLqO|FK<0tuVD16g&%nxX z5hQ*9oMs&?H5ozo(luOq#muluQvnUCRT3KwWS3CnBH7%nWI!1flx+zHRuo!Hm;Fm^%2VRiKb&{zgi8y>liW?*I5 z@|YQv=N&9FSQt#6Ff*?LjXQwGNFFnDg3eww0r~MUGeZa`D4pjr6go07gk-WfSlZ_@ z7J}}$1)WKl!Q2o8n!{TFI-e0Vf47yf5Oj7qXiPklgJB|QUhl>K|E3xr<1IA){x=2H zz6TD)~{l)tVashdZcj8Knm9kXt;vT4h5ZUpDD-i6BMrX&~OFiAJ~2p)bzo+>I*Z= zD$t%J&{}g)+PEskuoE;lbfSpC612|dL>Yr6XpPN@Dh5l?`kE7U43?m^H7A-FEJ5pP zPP8#tc1Sr`p6Ft*?2vP?JkiHs*`efMd14ZSWrv!B<%wwwmK|CSmM3O0Sa#?+Se}^2 zVA)~hV0mH@gJp-AgXM{343-^M4wffYF<5rkIar=p$6$GR6Xu#W^tJNem|0hShq@iq z1_bSM0rlZOW@!lGgJVDgTcch!4l9`M=(P&xcg*1_WbN(OK_ z3@S_b85%CVW9C`4UzVW=wASJ*$h?UV`S%PATkbRRzdmB=@awE#|13~>!^hBYDgXcf zt#6t6R-I#K*s`CI!4hY+J2Jqao07JtiP`U7dnQ>J;3&Y2UObj7{3=NkWG7BvX*%&4s`2XLupMk*y zbPi+=W0%w#Mg~hBhK8UGEDT%tm;}4!nHXOmWM#O>$H)-$o_)U52l4q*d`x^=9E|*2 z=NTD-G#UB1^uDp1OM>^%G+c6GU_SkrnQ;|peYXJvLw9OMibY#yip72gHgH=IRNvS$ zv4Gox_x}GE2f2@dg<&Gd?eYvv;I`n6|Nq7L85)9){QochfSExE6t|%9#0EwP`#vKB zI6ie4IkaG6oD2snHDnlsL3dVz)&YathR}1NxnvGlc*-&e$un|+>miVNu(m8Ly@AAF z<)JVG!-QfcPM!GX#CBCk->zMq2UtjOl%I2nR^)uJsCS^dB{3gfaU=}@eNV~ zs^dUs2WGN$&O%wo#>#Nfo>BO90xLtvOGbu}cvgmwry=L5eFWWCqRq(Boef^+Cj7dS zi6JDL3BtE$Pb3|3=?@77$&S`WSIDlnR`_ObX^+g>@?(cX`psGX#P5UEBF8Z5S`3yi<~UTnzP^FIdi6q$af&w|FQqb$qnhl|F36W`Cpmg=Yzwbds?7t zH9>16VQV$zL2YH|T1_-HFQq|c8V%NJ3OCq-+v|)BmZ14A(3;H``V2cCZU*hGW|;DT zfx!ec$M`kadF6g4hL0^$4!;gCGlcLlFo=NEgZfvX^6A09|KRoN$o)29R)&kn`ao@F z&^|g)-x#C^``R-RoMjtiYz1*&5$uklC(MkX{vArYS#erx5HoZ=EUfJO63)2tMKJ!p zDtdbxmKR{_Z9(n^_4OcTGEC&m%mSsaiJ(4OCmX{>a9U&JeC=S^IZK3@VM_w&?u7u>9` z6j0J2DDNVtN$wZblX9FO>lJ+sJ7=wZSv`r5fnmZqMuv$8TI<&~wA!yd*T^stn#MnZ z+M@Cd+^-$}{ttQZ|GzlQuModE{5-+T0AK3?nk$8gb1);VA!M|_1{3!{UR#JH-oc2e zo{7=n=ONG?7T~cs;Z-nyI55axgRzmzBA6W-U^g*<=LunA9bkKfQN%!N|3T>m+1(ys zcOcX;GCKTR2zCR)eg!o9A$DMn&Bik_6h07#jkPocJz!$ka*zqMX9Kc!0aWLAG9isG zF*^LrLgRz(o`sJ;F*^Kw1@7BJ*ZeX%{9FavAI{Ja1nUcc=IUR9?kEJ^w+lU!+l!$A zeCBr+Lqia#%mtm*r@+YYlOs^8n~{~_rvod4ASfI`{$OTw_?Zl9$3Vx8U}Zk6U-NJ! zVx9)H-~Ed}%gVpitSdqNO5}dNBEtgkK4?(6!TC4fawjvx)|cWAKQ;dbTwck*u=PPR z!$f2?uztQ4!vg&Md`A-3nIrY{LHj$g_3Jqq9W3oN845w;FQBnp7=OY4{~@6DY@l`u zXbmt(4XD2ey65$aztc+4ctHw$O)qG?7_$BXRAxN@k9~sT8FZ!;XiYD^^|G!jzxcbX zgzaqy#RI4vM^4`#6ptVbG6OdD_alDKO62=o!&w+E#xsb&N(7G^GlTbx!}^R8pguUW z!_Nnd3|r(G#9o8$HNMIu+6^j4Kx3w$F<@s7)G^Z+OblI|3}W4&b9g{y{sLym7!Lz8 z!%vVI%+NbDaq4GgSk(~5uoBd^2Bl-z*!Z__$CbGDryksnI$ns{$3gUg4}WhH(a)J6HFu!+j9hk*@kzw{>W`?cT*%&6m z#9x5K?=sAO%*?R$1e3^V(0M43{O$0Q6Fi@wu?oV+T>A|ggMY{jI=cjt&K58+n4z!H zgRR9v&$o>`5&0HfZXuG~H?(mWP+bOfy9g-1e+y?`iOBPi{X3xXGrVVWf%d^OF?56G zD?t4cV@8gy1q=*Zq2^8jo#O=(7hx3Xg7{H*6?kl(3pJgA#^z!93RHGtj?D{W^p`+; z5kY+|(AiNSzku=uC~t8xIPCngoN?vn^VsHFKxcqK^5nO0XL!DZg&W8mC% z+~%FnBn-}@Q<%iMA2Nw{gTfD+d0&|&R?TN(cT_}^Fj#UhwFJq7#$K2~%|0q z)(Z*ztT$5F2^%K{)z8@KdTN^ss}~r88iE*t78HT}3Yt3x&2zx!2N#0&M=&$45(#Pu z5(!#R1e$YZ3~C5s3|deG3Lj9p4{EcM$f=tUX@YST zgA?kx@4^fWKjk@?b|S|$ID8@dRlswJq+qEfaWkkc>%Ov6*T6AYai(fu>kPB04wMh z5EJ-$pUI`L1AJE}xUI1hw9g$B9-uKRQ2e6rnE}mjf%cC=)^I`M7F5r|;&+=-!cLHx zN-PW^_thAR7BDh|oM2-RTw$aD7C-ste+X!=H!O@{?Lx=v%|R?okTxGYFELCDa$tbx zr70k@PyFK-ywAi?$gy#n6h|$W@QQO9-3*)zKauTN`SX7WXb-^QI)};V_9R|I*z?~R zw0@O+<*#&(l|SM+SAGlUTKUDFd*$D1o|V6tA$QM$$_Y^Yw1Nq;e*iRY016vW{lUTM zwDYktjvzivZg52y>6J3_}RWFW`7as<&@}#ymI~ z3O^e={Cq9R5F*3SaOuB4!%h#-I$hA(+ECE?1kP?vPKTcyst%L7MH_-%-e+3*LYUzv zhbs4M4nc;AUzAx_g4SaHTFkuCoS`8IRDXif=L>(3n;m|F^nlWmJu`#l9Cn6@C%Bq+ zg2w*mGjqJo5@rZF!6(zrnd_*j0bTP78XuA1bogni>M&_%68CJ4|M48=|2a88ec}!V z29pQOlA!+i6p*=FlDKDg^fl~|S7a!B@aKQX?|g=x@~jMns~H(Wq!}76c``ffT$RK< zJJ^w7V%8zheHfhCpmD5fc7}zO&S7ykSolEKa(*uew|rBu%1q(xnCZoVb(A_-t(6WV-p+QKUfk7k#bhk6eZZ@dh zTnsyZX*>M%UE{U_H!~6YO+A?0`TC5sQb0rc_l9UL1hUx`(;4=NoMZT zUVoh~zhvh0&b}}`i2KXZB2QIrX)k7noiA5owxeL_rS$)QaTxoTJjCyycwYGbzql5e zW`gvC&XE10?eG(nzaL72%6^BP8B7dj9ia3q?C?{gmSZ-k&#A%40V?Bng3j~<<;h3P zVyi&+h5W7dS^34^d*!!qua!UIJy-rp_gMKS-+kqOXJ*iyA0n`PhEkp)fID<88nu6!WR@KZsB z3$d0DwC@$vZej(U$?gK4^9JY5K*+fV8lW{mDO~V1eH@I8r#W77!q@XX1l?%>Ne4SQ z|GHn+46U8?N*=V%g|pk3)8VIxs>38u_)YWUm<@`vlSpSLbb|A#7&xDT%mJzE@Z*@x z+3T#PGVFA4 zZM5NLY}lz8$T0Cg6ZdQG|Nlck;}hZx4MCu?1$4H;e>R4~)glZbk_-(&eSr-@d`t_9 zG#L20LG#!BObtO3L>q!^7$ECpE!i0YzcY)j+RwyL$Scec@}Dj4i!0dpXG<{h zbxSil?EJ+nu`1Z#VFw4h!%t3Ohn+9I8Fqs1WvS<8Fk}F&-DZ&P=2Z2vJo)#(DVHkO z#Ek!tHTy5+LG3w?ZeC7@pM~lUlg!KnW}o;M&vEA;v+Oc%&;@Qo?+!HZqWS} zpz@3>8?;VXi_u{x=>EmiOwj#;><&M>_4sG&mu_^_ubD{}3q#1`)VDK?Lk!bl8buPb0*hdXOEQ4m*+U0EGi+%{9m#P+rhb-~z83 z2Bpit)m|&V_C7vC#IvkK9_#ClJ_oh`BpDbcfcLC$G88&9GK7Hc)rPfCzAa{4`Q<*t%9m*6P6e04&t^8z zIt+=|pfl>g`gs`&L3dAbfbOzDQ@@>!!K{PL0aQl|cCaz*)M8)|VPV*^dkjK_I;#_kr&FHUsTx;)b++lGqqR8bECX{RUXPF5y{kQ^?DpR4^e zyR#J;CVH_l1orxBb+6@g*twsPBO5g4nXSlh5mbI?{r?{VYD29!r`ZiU%PfPD;pYl2 zCs0}nT)_qEv$?GN;_tljTe#Cooa0Z=!Eqx5JDU{S*a)a!2OEb(@85y$l?MCIAGNKX z0rlGhHinRuTn<0AIh}T9u`(2LgXT|I83J{DwYz(J9d>~H)WEC#6KFGOglkla@KMMclv2|n{hh)6jx;s0@Zb2qgH_H#FhWzIaZ+TC4#IS z1gUuu#W9M5Py-W3H*CHPrWeNB@N1O+k;fRn!;g{SXWqg19e$h) zJM&x}clhx#fZ}_i7xbPpP<;WKI1h-Whf8DI7HplObd84$!;29e#rD8wzFYn3cfguoE=C z2PzjcxB`C4Gm5@mzzo#~T?5_0*c4R4#L=B$#4wSQ5tPm#^K_sx`Q>$nm9TmWw8jK< z{t1i^%3rXx6QF$xAig3buBIe#F+l8PVhAba68QPT9kh-PWUj+c(As;D`#@t2f2+M$ ze)0EO`7PXY<$q?#9z0MOqUX0n)&}@lt*~(#P`Y4(&e?#*y*e42f-;#nyOGyoFtIXR z1gV3KXS`5$*a`9%%nzR@GfaFinPFlh4`l8KWDfE?KS=+>$qW-gW`Ne=fY!V~-3MCV zEdpBy3fr&o7`pBjlm?OaYM_pvF~QEk0iPEII=2OMh7;(#C=M3Hc~Kl3i1VU2ctGbu zF@n#F;t)Wb7sVk05@#p`tu?V{VJOr%&=ADIIA6-1gQ3vVp&>|-u|tZ(tRV>GXOO!= zX`umn{+B!lL*W@_hLHc}43__`87#k;GfV{Swft|-U^(@au?4tI!@w{FlE8|43Ip?!QikHG)^H5J=YaB zhKxLphrTWw)II^tPccH~i!UL^4QSj(zSQpHA$Eq4sZ5Z(iK~uk;Bwf>!NMR28fRpg z=~(5!0@^FlAk@Ldu(OzjVGC&OkNjE2LeM$*p#9cad<{X6JjF0E9&}a==qwje2McXc z2a9+{?rhLmG1%0B&Ku%FQ`ca`FcCC|3rlmbJOgT*fWioL1`o&`pMU?~3Oc(Q#0Hfa zp!yg23=r7*YET&jn#;{#YOu^?Yp~4XYOu`aYp~1_YOu@|Yp~3dYOu_gYp{H0&%E-D zIn&Bl`i$`Nm0qZW+aaK|I|bC%|C7(O5?g!Uo`KW`R0IabjG>eN`lr9hOfZ_x^9t^%$`vtS~Y0zClnv5LXn$UYjL1RU*{12V$0MEl!fzQ5| z0Nw2q1lrRD3RjSs3G56Zzrky;8!r84V)*IA%mLo}x{}G^ry?Uq_XC9e8$svoya2c7 z8Mqqo-@oJwYN&3|oqs9DZH~ug5^0 zTTfs^_n$Bp|3Sh7l)pgbEzEtO{DrMg@h9I2sbA3$1aiZbfB(U5nEVfPwlb<4Kx?O= zZB+1j(ihCar$Kh1hx1eL{TvNJp#8Kk^}mZ5SH8$+Ksn#)GxW?WSa}T!cNiO%-f^uv zqIErv?R*@24u+pfd<v~jTL7{XUH%|g zUUJnF=z8n_hgmNE$>&}9E1hrUk9hu--@*k}e(@Jv`L|jKyj}=2ZVTFX3OfG-TyN}! zob{N2bk<`A(pirgNM}7}Af5G?0X^#xbiVLIX5{;(8BAYvqn`B$>Jy1FG)&515(V}B zEVr^TOkDB*zv%)t(0a>;OQ3bbAisg?%2ES{E&HMS4nXQbX%ci7MhBB+cpYfV;A zIn;2egb{IuK1}ZdJ%%lyy$u;?dmH}$XIlARp5f<%#UT5j>pSH^d!g( zm4`g^?9P`Ag`o5cT8{=&16xa#Dequm{}QsM8?;{w)K6N$z+lqF#xT)46SCh3w6A|Q z6K8iav&iX_Ow8SyoD37~SsgyU`13!6nVDe=C@eG>8NhA&1}27(7tAKBI2fh7Q;{X3c zp2$1=oX^1gnp2)3kxOPai>jOXkhaCI= zU!418^`tCDhfO_h3=?%-@vohhXXJj}@a2EVod5sDKeILjf$oI_)z>e?Kxs*Q)e9cX zv;;yBaNN*+j@3Ztc^lU$Ir z1Uj3F+Hw5gDqsc0=1c8?ZXp){%--bCt>|2^fO>VdqH4oKZi4d&q{^)1>}Ah8&|vWe>2m?ztxXW@MFEfa;JbYz!0Q8AQP04jOZ6WCObczD`esg<;El zXnMQcv)h5y zVJ#N}h-LuSsi1piL3_7BWf&+O!S)w|(lsb8$Y+?Ktj~7@ulZzH1zL~FnVDb#zVnlX zVWK?)1K1CsHBg{2JdiwyhK-ZJ;{OFZxE~7lA1KT;R2Tx~k1`Z;FfxQ>GBsS{6j<ya)cUQ|yhhL!abI@L3P9BDzKcMFWVIRi_?bU6#B%a{7@+Ff*Hy1m@L~VwKAe{p( zmvk5oed1|&@JTl_!(#tehQbpJ3?ci!GJH&6WC+PsJUeSYBhRZwHii&iMvm@WKFHoY znA(&7{)hbf|6e?VnPH14L&K$SOcLFow#BKeQVY-?Sx{R}la=8kD4f4CbF5m37Wbew z-Bwmen-0`QSivOG{Q`RK-y+aGPfViSpgI|JuMVipkp=J5f}9Pc2u%YZGeCArL(>7M zeRT?&4!XcJYC7O&U=V3!VAu-lYlGqkU)-I{%CLZyAIN1-X_Vv26Ko6in|F>t(g;$R5TV36qk&&2Wi5j&&}9RX@< zfbMVNVwkv^iL)EDhfViD%OzcgL!WpX9()4r^#irDviKN&W@SS5LHo%v2zkjmOuGM) zp-|)h|Bx=lQ?ue3d0!p)_dmpg1#)IBD1E%jssN`Ckh@{&1DCrcII*~!6_g)2UNf;E z+`S0A=C0wAIhHg6@;@ldH1NpjLDLV%>*`6Tm_)n1JQ*f>Gjet(wAQcHX5j2jU`0(w zptd}yoeWp+ieEkGjCJHR_cANPLKC)bgc(vV*=JZ-WblE{DFmmh4A2-iD??!xBSVNT z1A_=oJy3PsERb~tpnmIXW|37nq7D|Iv&%qbAEf=u@ftMe=vT`-TQ4*3$9YBv%lVA_ z*`RcGj+J5JduHxcADDSo$;&YmfzAy6AnIUo5wtI#Nf10P2s(?{qt;;(7wGIsRj%0# zp!I4Dka=Rz9Pt8126JRTg7OtJW5dq+0ER+PnV!MIAPB2NH5M}LG^tenf!^1}HDBo{ z(h}6d1RcxfXxIr_f2IxfFKEB@Yi35Q{^eq32%)xrL3?r@GBd48V2}szqk{R73A9!K z&5w$e%0ED3T%d9tR)4|T0myzro|}P<-GIid#SXMwGGjRONvz?)rw%p8m7wz<;$MQ! z^JfTIt#oQuJ)_tw&^!^S-00+E0G|&5k_YW+2CWkTt(66}lVEe0$YyZ<`ycWXe0D#> z1Ww4=b%kpg7(&qJb3pruIT=B7OQ>fC{cmQx_#>WaCGs8w&>C9MxH_nw1eL9z^%S6V z0Ggiyjh{oP?F04(TQi1+An^k&m&_RseG+eY z@Ts(paV4lt2kNiBWB{di1`*Ib3!risCJwqc_=f%gYT4#Q9R24>KmOqVni4t(Np;QIlI zBZi3_6%0Q)e?Y<#l#l-8Gq3!W&ax6cKY{WRL=U8{c_9wE$CjxZH11-`%5ZT%6XWZb z)8|XEbUIWiGBJd3iZGag&Wr+$6+yxeF*gf3zZO01{7QFO`6u6bB`ghr;>?plq+64h z;UZ|A*LP)xi9Zf8O#IozF!9%!o}gQ2))YlEHUxq0W7x*h5Cj@C>kwnG_{_|?YCezC^Dr5^qM4;qiQT=DzA370H`P$sA!G?k(7AZVQc;{ov9ISEV*A@ZG!g$H>+`-()t z_eXXxJ6LisBIc?==7P?F0GZ2T=}-k~OBZu7Oa$>k_B{UcKLm8v0H~}5oeQDE&@c%! z{_~odcNM6u#ZhB5o9l1=Wsbi|lerkVxIG%BrTGpr2(D#ixcGvJyPL0;!IEEvK@fDF zl?E%r#Rtq>tNwd36mtCgAF>KOX2;kQu6@2}Ofgxl9lR&os7sJGlAn`VaiS|qauOBlpgj{%8J&A)+pc|z3m0`~; zP+P|9W%VR4Mqco^9%x+aEwlEj|BSq^UmJGc0-eF1{jz!zXlxap-O+$;*=8ykFGXMV<2c78)ii0oA z9Ps#F{NaB{5_oP2^NvMDL)1IeQ0sb7UlY=&VPt`n9k8@6;>a*j#D`&}yaVJ+tgTE8 z6GeF#ekOB4%BVvukU0;~nd-3o2g}bH3Y@dKbQxBH_HuyAtPC!2{~g>fh1ml#8(iLi z%tta8bXEgsE`?Zg(c25??HuHC5!5CDotXhThlx{_A<$lwp|JV?{}A~`hC&BWxXUsK zf$9wTtqg@+3=Kk{eySH^w-mQX!z}r=422quT~b-14YRx%4_Ia%WC*lZWhmqToioMI za48qm|6pa9`1(2HCU4`(pR|o1e|p2(5TwV+*?sP3{bhSb?$;*`=igc@>oB>Gk@xgk zM$YcF2SI0A@V#C+asDko(E}D|Wf_Fd9b^c+ugOs8{13AJ8Pv`PtwG{q_;AT5JIT<)z%jHX$OU?)D5d_-6m6KL&3M2v z>mWm5yedPX251f+>VI^<`*CuC{SG?&;uMnKeHnSdevfD5d%bGn{9Agmn0^O^{XzzY zt)TgQ(3)OuhK8U<28J!5{;8&5!z@kETskAeM^1(hmo&F_fx`u4j~6st6gGB&!{reJ zsQq%lQl60!yp9p%eXX)XqiZqV9(^z$A- zV{Mv@450q*$Jd~CWCr9+E71MxpmiPg&@)XyZt{3hJxSAn@Yz`Mj7+Z^{{0Vm^#8v& zCxe5fCliASbluk_EfLVV4b5!OcqOP0^oE&h)qGioBG9@hQ2%c}qh>a!&H(iRL169-xOp&EF7KC!jX}YAp|sb2T~6UOUD2IL*QWvI=>luw-P8kG@)lOg7yx9@(Rd2 zu8d3zE=C3uP`@OeffGD7@sgQo6=?4V>|8{9MyA)GJ^tw8pu5t17&uRZ#_{SIdBA7K zfcE-5Vqpl8XJz>K`Y*V=0M9FFGjMc+(p(ZdLkKqmXLmLuM|V9VUXv~R)}e76z<=$y%op!q3KI~U|G?VtZcKzd*P_#dK^k!|6Vscn(N$}kah zCeD0Vy#N0%p2-Mthc>9rVPNR?;$*m}&B1UnH#5h=_p7``4=ck(koung|3TyT-SHpg zEs(#wm+bA)hKr!{7hrd=F)=c1(aOlQIK{wV!j-8BKA#X2=b*VXP~6IAYFdEO8z^mP zWI*NKegUBLIhAp0;Gou(7!Q(+-{j8Y!HIek6WCisbLHFZnt;%L(>gHkKLXTJQJ|56L zc`MlC)G1Dyyj$O2zkuHu;neY!m2z* z-fk|?eQ=CiulZXWX1!(P?Y_^*`}(Y5@2qvK3={9OGJNa+j}ykX{E1xi~zf1NM)vNB9u_qJ|Q4liFf!xIL7#wQH^jWg;7W#29q|F1Jfd(q`yIUQ8WHEBB0^K1A zDw{xO6gM+7gn;HjJee6nvKcr}^DuCC&*x zduHBM1|R2J7&10kdNB&DI>#uu3N+{co)Z!trx>|b?Puh94YD&+w86rQk#iNOj9B;| zR0cA9gq^d4-VRcXYzbmfIB*HnUjeO&{FBeP@>e?3${+E}E5C&!&aHjS%&_v13d0tA z28KdjRfZ7In2In%Ly!gwL!ih3jc(AmP&i{lkOTw61kk;Gk}M5D(o79OQv8s9*&Jqu ziJ&!_FW4dDsi6I7#cT|Mpg9T9yuJKXhCGAr9c=O9Did{u_R6Og&7pm)rit5(Z8Sa8&e zOLH*ladRAG2+Tjo5C}S>?7t>MAvitkWB{Lg3K};Doy`Xd_xha-g`oYzt63c^>sK;> z*TAmj1jW0<&pbs?xz6x2n-P3QwFoyugAgcA-ibO`+<(bfxL&Y-7AXI{WpuFIzmc&J zH1GG86~cZiK3{6X&-%-t^8$Gp8iGJ+9i-=@_&7 zbifkiN6;9IHq#F?0S108g(Sv6`38o<4i1Kpi3|(^joAqnhFpx@3QY3Xav2y*LFPT= zV+eW0?C{fD5#(lupH7SpKg$>xMC{Ko7AlG|g!GFrn1aj&%~N%P&QeunDAW`MjjJ>S zfy6mPJEB1PeH0lczF}tg>BZ>q6SN17hq-H(Hxq+NAESdM9}{HX+FN#qpP)YKen!Yz zt#ynHmY{gkWo4N7mYw0JCumN9kvqGIfgz+XGt1%?Gv}&x|Nfi4V&?P)ot^iJ5!83( z@O}l_XUNFu4GJ4gR)#{*KIM3jng9QXL^3j1g5*K{z*p>$IW|Gng2-g*hSV-s%5;@ek~%c7wvuo>Anr()0fz&@oy|W6)icsPVef z{vbo)Q}Ovyp!)#r6B!Gii_e#`zsgwnm}#~Yi!6f>%pGhD;CrP+K=BGo7ha4FaQ&e8 zbqeje1=8d8xBfCrpED!E&B6?j@D}_3UmO$$Airm@GK6%pfyN3r!R0OJ9s`gZEPNn! ziQCFA{;n&(g}bc$5%0Y6SGv>6KlzR;Ve5-wWf7?Cfnsof7&adNu&5;nRA#``!NeQO zQ2XyNd8iqnHOF9caPdL?dDz)cpgR9QGyBCq`BE$YR!gsZ%*?b3v>ybd1~T^P@bkra z$h~_Y^In|C++P4{GykoQUil|KYUO`scJMj}kXl%MKIresb_VUS#y-}^yucB>hU}mu zsLW?v1saPJabTGE&6!~$=-dMdhn7ng3pS7ymoD?}MgN*Nfou4Z5m0p($E*{{k_2s%qlzLB92wB8+*$A2=5u9AnIIR<9; zG885_PR;dPWCJ(3z>AbPf{hXJ9Y|p9T7op%7I5gWCF_ zy>g&_0BGJ36kag94*vNc@{U;)bk=_m$Q=KF|4qI?{2ye`$dwJMgCZFiM6R-e$~A7# z{Yu#jxEMmFF-Vw$+BOfG8PdHiPB=dHS2I}tuV=9Q-^^h7zn#JIe>a2W|9%F` z|C1Rk|4(PI{6Cw)^8b7W%m0fREdMWOu>8N8!Serl2Fw4O87%*AXR!Rgo5Aw`eg;d> z*w$}mPA!heOz@qHG0dW;8`weXKN0IqAMi8$w0Zk~%lu}BkDxug@(fb1L2D8?7-Ycf zpqwCe|0Pb)eVL3>r$Og`qpw?x`2SzL<27;TUxUu+Xn6TQdnN4w~S5YLV}> zfQ=cz$|lI(NY~5Yy^%biGgcvImVwp*C$lhYRN^6FZzOc>sEgvsS)lcyAia>ePRP14 zjJ=Vfg!e{f3OQJE3Nlz`iaA(viZWPcN;z0^N-|hx$~jna$}(7Hg7!!&GFWD+IaqS4 zGFWD6IaqRPGFWEnIaqS)GFWCBIaqQUGFWDsIaqRIaqR9GFWEXIaqSqGFWCh zIaqQ!GFWE1IaqSKGFWDMIaqRfGFWE%IaqS~GFWB?IaqQAGFWDYIaqRrGFWCtIaqQ= zGFWEDIaqSWGFWCNIaqQgGFWD&IaqS0GFWD2IaqRLGFWEjIaqS$GFWC7IaqQQGFWDo zIaqR*GFWC-IaqR5GFWETIaqSmg3k0t><5I^W3aSB%e|kVz8#Bz!_WB)jITRE=QVLS z{A3Vi?grI|=%~l)u1eDPP01QvLvgrTicEm7u*@@*R-*ICQ<}?rvOy(I$e& z7sxzD@VR=Bb!VIh7$$0EWPsQFXk}`E?}(9SWCWjO3%Zv{;UL3APL75kO-7E>T8s=@ z@w^V7K<)CApu1HMF-){a(gW&Wg67*aKw|+6pgWxyAn6HurxU0hRKJhW5;@E{3LJKF zFftf{_Q-+8h&w>{r-J-10@;fSI#U*OhAg@t6_=s<5fnb)`4U(dbvWz2l2 ze}U#7KxsY$>L<`0B8;34KSBNhr~3kios0quKba~(XAn93Wa0(gkIK9XWIxz1AbAmn zpG+JKKbbEuT7vfBdN44Uu+%`+3xd?Mg4Ki5%mK(fP|)Yn}ntg8_?P&hL5$EVe5rpd)^ZK7=D7)F|n>qFlw-c zwChpIED_Ea(0nfF3|EF#3<(ZDxf~pRawRhSJjKAU1vDnd84J6Q39{c>K9%7ovN-zr zs~i#zJ2RLWOu%bZ3LJK7Ffo{XhMrdjIzIN7LG2F-PF6*%mSuaqqUt+#`es}TQV zq$M=_kmn3&a%EDeIoMhtY z##bhQ^paX8+~3D&2}w(cHB6xMB+C>a7{gCb28ONm5VJ0V)HN45?5r1HC{$!&2$^5Ruyg()NZy;@1->8TCx@uRPf&Y@ zfzke2hZOWI87YRHnL^<6E&@U4syzm+Lx^+uIp2xlrv|7zO>_8Z;>hr`Bn|53IMDqW zi2PL&!~=0BnmBqmHJ)q~2b-j|^WbiWTI{X*u&VeON~>n%adObg)W8bazQ zhKZaF4MCg&3yK&RIl=7-d}~QSgoEG%@#ipVibqigYJXY_|JI)bPpM5jWp;k=z4XA!js@V1PoKE*%<`E`u?$- zfyyEn|NCEdGmyH@|Nle2{r@liTHN91b!LVw|CxkegZieRy_hh6F)%Z1;UMTQZiK%+ z)?Nn90ebN|{Orui`~f;^{~*Y3ptIJPIlz5nQ2lGp%zcd&bLQejRKLHwR z2ZiH_e~@qltwjcfBWOJxEUkjpHXz@X`-Gd}=PRW9az8WkfcM0_VHRHXgxld~y|cqd z4Tc3l8O2!|9^3i+d=a`F#mw=jRE-qv|k#e9^?cLyuOPZkb_ogMl-LL58{ zJ3(u%L=~7c<%OYZ%@Y_Vb}~tIgZh>$nHfSnm>Ie`5<%m5BCj=}YqmKVrA~7(GIV<- zGED4X;y}Jb0XDx1b|Yy2{Y!p_pP3AxyK+E#20{H9{C#DQ^6E*Qp!=s5fX1kC@3#cy zl>>kNhur=DU;HsMrxpX+SyqYs4M8jdkn>d04F4@>($)!^Ce><`=elSjC+z8rF z0V*3o;R@R40SXV$INp9Hmye*ca676>e~A68{{$MxJHZ7$17+toc7~sz{Z24_*O(lB zn*IO3^%H3Boy*~;JtxCQWlqT2DNtV!WG1Lg0F^Ha91J0#dDzvg3>UNiI$q`xPZ$e(@Muxl1b-J^g1L-O9%T;|Kn z+p!)h4|3~j!|qw2u{_Xz6Nbz;Hd$|LE`!|7kon4nA#;t*1Lgy^44JEJUNLj80?k=A z|Nb8W+LNL93v{m~Xl*LynZ&Sm5o9dKv$P-hc>8O1?`F8ep_={ zJ2QJnJtJebmtn`OWR;Ft@r=x`SN!`Q0*bQ^Murg3xEbiKri?c=mo+joc7WDsfyQw) z1VMYC9ey$-GE4;ZCqelaa)%&}K7|da41|oKV1$J=r0io5U;xim)H5)A^k8Y41zJbV zQR^^Co|WYzsPEwMq4qN9UKr4xanL?)PSAPZJWSo7Hcb*}T`wa;x27ZLtVzb#p!=sl zW0;^jF0?>(hajaOp!rGz>pM%a`;8?|?0P!2PGdaF6 zv##3D!ch29c>r1q#>-F$TGIeZC)^)vFK00_bo)3mOw9UFd)XJd zHp-ikyE~hap*!0Vblw2x>qU(|zZQem_LtU80?omL?*8p%aezvx5=h~alQ>~ zjRmO90vcNZo#zWmYaEQ6r@44IyS+eZjgh&VlZO+W9<^H?et5Ss`~daMLE}@PG=}c4 zho2y0nw%UCJMBSdoPp0s0JQ@eE`jF#K=lxJW!4WJ2JX|@jEt|l4ZCOYR3`k;W#Bp8 z!^rr0jbYC$&{{YL!v^sBXHZ?${O>>b9%E4d1!O0zTn5*xJPw~6I2b}e=d;zbF<91f zF<92~F<90MF<91%F<911F<92iF<90sF<92CF<91XF<92?F<90cF<91{F<91HF<92y zF<90+F<92SF<91nF<937F<90IF<91zF<90|F<92eF<90oF<928F<91TF<92;F<4T1 z&nD=8&H8N&mi4b4bJ(euDUDWjoRteGID@SR8&r%0h-I2|`G0DFnNoZ#4YL z4S(dYM<1&Lm7$=qsc+1Tt3cy*;tUOwPB4js=Q}}TbfB|i9-y6TP!8&kLid=1)PnYy zgVtGaFo<`{Gm5>=1kFb{~J#2kKdFfnW?;dA)O$=(no8pt`jfe8@@4QxnkE(CkZBgp{oXzU~-(_&Q?WIZ)#jT>nH z4Cvf4(0L4?_DU9$!_U=B4wj&@3O2tF+Uwv@nfZf<0krp39$$?nkiHXget_+L7d^l@5i}3Tz`(FpRDj_pV=YAOd?rTA`Av+L^A~~Ub0Ft@ zComnb1*Q9jrXHL5b$ly3@<8z`vI;#;>17WrJ%Gw1&|IiSfx}M^&{?sJ_Sf*$8>FZO z&!LnOXD+d7g)zE?XaZ<| za=k1=5om8MXe_`-)WM>jkq5j+3A9#Ji>CqQ{9Di%BKojmj6L#UW51`yBHW9 zz~@SV+NZF%2c-*;9LOD@xd!=-%s)Wk0uqCr8}7)!0PXvt&JlvlR)LN!fYgJ`0NweJ z37S)50G+`LIt$$4=Sy(iir{CW@n3?*jgZuX<{Uuj0^|-D?{eC)P9ag2&uIW7eR%Z@d&4E`sjA)@J1D&R*zf2|cfIVmx%e638F&jF9t8 zLE+T>vU-v)c)u;(?G=wO_lokzpd}j_dbOz4IBlUxUWoKx=D3=77Q* zWCkdWAoD?D|C!k?{>c|w`72#`<&SugmEXceSAOvqTlu$IeB~p4o|O;Sc~^qY2?Nck za4;OX^rD~PrzvAY5NPbplG))WD384O?6C9Ye}|n@m^iwNnK-*&s0XgpVC3iqsRf0x zCTK0j-<-?xybK=?F*1aFI-1)SurX`_ zodx`&PIUH*XojC+3=Nk+?h~#Tp3T8<2JAiy#)cqX(A+CD46iY9bZ^DtK1dj5UY0)! z3Bw;mxDh=JLE%@yz_3NEUTik#J_pzxte|jYV1k6BSdG|h(4I$_94Ku6$20r{sag5| zzc@@BOuGPf$q2aQYSK-gP|!1lpf5{{5yx4qq~|JSDHz^ zEH4Z3?{_l%D_So)+kx5PC-U9AAa^COF>K+ek(td|BR%_#w)aY}zh0NK|9M^R`RjGL z_n+70bN{?9um9(Dnd7h5WdR0;2?9(E6E**OT^4L;2oe-nP$a-4*e&Sfuu|Zk*X0Mv z4nIFMbF6%j?(p-0Kf}+L$JtlDux9wlA#>moCqq-vOJ%l|@9bGuayXp1#K~~x(o1EQ zm2b?MS8_0%xWvhD?9xkR$T{q=adB`SQ)gKDfZZ2#Hv5#n)!{3@_=m0h79P6tM|{Z2 zU+KXs|Kta){Ljn=o(q75JE-me`Rz1le<`?Jbg%@iacf|J+)E0|`;h$3bn%Nn+sePy z?6C6^!FT<=&}aAwI;#+LR}85Bc)`M8%E8eP^nx3F_ZN8V{$Vo1#7E8y6G3w(ur<*P ztPCcgx`^4vVN$&Z!^cOUy}>*TA3NC?LOTA>58`0p;C={NS76H^1X^zm^XG$P$e0Ur zjl<-}+@SO189y>HGlYP|LHiLNSwrMsC_7ZXly|7quoW-{xeIh>;7fhPeHNfSL7=f* z&>aa6m^rlmRzvPrg59a~m>YDb6yrzdzyCvE^(V{?j2l|v_tt^@fFZxWHAn?|W)`}f z;`&zj`W;x?3e;W&nZs$rAOyNw9dxhi3dV*Y5F51TgtI2#vb`lkp)&(RNC#s>P)1e8 z56GOb!%qc9j#J2OCYYI^Gq^$f8bEazvOK7r4?0T#WFM%n1qv5Xork-)fPS-=OnWpmGyb2ZP$+ApD}9;V0})j0frrJLOpz3Ue74 zLO|#3@i8!nz~!_Vc7pEZ$Yx*&v4GwI8qClT1ee!`=&d+5c@|6zlpaB6v4X}VKbiVRTVox`XtyHK7!_EUesgmr&8ns z%{7az`db~c@{51)%5UL8D}TfXuKbf9u=2k%E4Z9`@tAQUDF1`(N$lziViZ^bzhnBr z@BbkW9y3mKgtj|DZFP{l9YEsHa^k_S|EA!wfmvh~Y_018Mh3W;5>zh(k{HO{VE;Np z%8~^P3?^W|Ld^u7`TM{bv~Q&&2&7hlk-_vKlf%zP$qW-8gZD&0#GDG^w42%pW z-EKRk?B=lMe3;pan4HD8Q1t(GwFpo z!_P-hHH=XAiZL_@y@kvJ!tYy$0bY|HBYTJO$_}I%(2wDdLJ7XKP zwi@FG5`4t?{yJSG+7VJD+#Gd4aAV^&Tx;Kt-CG0-&MplL`pmo1YY@mBV z7*~PjXhGov!l1bZ5Y1u3AOzYc25M99XL9-ox>u!)k--#n9wdklb{|v?*nKqtm*rI% z3PI~Q!WbFMKxIM#H0%yAL-%6-jk^pwUxt%mMUW_C=PZytAPgFB<6sayoxubegG9_F z!0v`d&-;n}t=RW3_M?^wpgId(Z{q~Sx>s2IEC7vJFgW~dU}V?=>xaYif!qgU!|J1l zld#*LI2qM`XjucUlVN%rXP~M9#SgS?0KU^6RMvp{agcM496)=8cgAxv6e?&qRw*z# z{94G!5Te8A@ROT?VFKtpGjJaQd~Rk#kX~i(kNb?=;JI$l-u-w+Uhp~ZAUkv-b$@`& z=4OPf8JA}OpS@-&&%t0R&%7ITal=Icqp)D{!8eg-ENAwJM-^hRu<~ zXyki<<}*Oz9&{c7@)-o6`Uhe@c#Qrhs2t=-aIjp##$W;(Z`5F8*iype@RO4hGPeL4 zXP=_P2tJ$5ffaoJCVZZ_qljVR{5pn}^Q9Pe&gWwIDbMTh3AEpGei4J^{4xg1`Be;- z^XnKa=QlA}&TnI|oZrP@Ilqs=a{eR+%lXq7Ea%T+u$(`S!E*j02Fv-&7%bUio|b$q!^-)a7%ahO3$QX=?2uwW*em7mGvoLFEe&#@de7l!ryRr2m;e56ov+03 z6SPmEo{QlpXfJ4e9m7fx8&tnBGC=AR@Ot$m(E4bGDWEpQ3uT6#|HT=8KB#BVe8J2x z5j21PpPk`n27`n-$PJ+JCrbBrK41pzXNT-H0M$XT_9g1wYKVQ_NPD~C`;S2J21*|w zH)kj@?5r1K_?b}0pb5G^y`Bvc_Mq_>O4l}k!V0;)3JL>sF?{0_pf)h5t$>oo`XTL7 zklQ)xH0H_3D6oH@SSOY|A%m)-G%o5GNa}Hde)Wy)fs;NPiEK| z&cv|g|71qX|I-;Q|IcQ${6C-3^8aE+%m2$6E&s1(wEVxG(enRhM$7-(87=?sX0-gj zpV9LFVMfdU#~CgEpJufDf1VMXx9`_6tdy^3SSim9@;Blx9Z>o6f|Fqj=&WZcRms_* z%8VBur91q5SnTlg_iu-ta}GIJg3ee4<%4Ku*&Q!FJ6n1<%UZnn?riB1ENk)Nx3i^3 zvaH36|IU^k#j+MJm|ZMAnq@6su)A1#OqR8H!R=z{u~^pP1;2}>$7WfJ7s4)<9*1Qu zUWmI`dR&&Zcp>d#>G4?B;)T46rN?JkixF}TePzP}DME(ShDF$YkX!0HiL`{ST(LlE+~04z^_CgUD3PA-7wGe9 z90Cl1^0Ewtpfi?UN;L#&s-BR_WMD7{_4z?z0f{4qi5fREet^dNL48DUyBs>s1G*y> z)b|Ie1@-+vG-x~sc@BY@mEmGN55q^$xxDCcw{SyiPztn74LY-qlCvdqMH^R;A^fed{SaPW{1jb`IM-xrXN6 zK=h~3{h|nxUxnGp_tw&9oBH#%K_F!OyVsp)te6N6HKnVSP|gdkeHy z33RvQV`fOZ>mgJgcK6x?W{01!JpcbNWDPe+52$?(EhjBOYb8K@P~5@B{y=h|v+|t< z7`8&&WN>$a_C{o6Wr5G71Dyp3%J1H+3>RT#g-&LM#To_%6HwhN@8|%&L!_L6K?KBJ zzz6EqD#zA@QsXAG>)OLO^p-%!~{n*-TvBp#ESJ z2SW&Wz6yLsr0{D_4#=4*X$%Y^r~c0m@?zvT4KgE%l_3Pg2d#PTU}Fe*1(gGt=L|NF z|e>w5TeP*1y&C_Gc+?R+k*3}yhSGTEJ@HAhdKZMhZuwI zVFc|x`#(Pjw6+zr4-FLNpgGUXtSqn|P`ky8mEj^x4@e%=t^&;$_Bb+3^nO`ADc1>f z))@CH(0m-|>_O0c9O&%9bI|!X(EUw33=NlF|DPX}%gAvWq-X8R>PdQx9Nqa$Jlzji z9o8PmTw`;dk*E71YlAIFFX(JI(B4PT*_@#BB=x%dSE$Ndm5CMaF|@Y(cvd2Xz#xw%S2Fnlfi)@kD;N_2Ba3$--P5NP@0E~VLjOGun8mwqe1t}V!K=R zD>L&d(D)H(Z7OJ-6gqwZp1bEzxHbzsm#BDo7AUTS8#`yoGjP6^Z0MY2&Me;jzn*C& zXpYc>*4(!DY;CncK!paVin;tJ_nE0d_G)5=B3e;u-XB-FYQ!?gQp`SbA~%)EWf3a{wj|@)yXjFOwNp zen-1U0;UG0xA8-35NKa3y0{`|8)!X<2uvJgCX5Z!d+;Ob*wlY!=8J#w*;f8aXJ7dv zo?|8QUFV>?gduB`8CGd99JusCp8+)1v8A4g;b#~F!jHk`mL3c|x1er1%xHKDj*8Ci1ho7K6z9}O|_g8)B z9uXb}vj!dp)BoBGKmYqP?EEdxu(JU?H_bTlku&4O$Ht5kpCmI(d>Ra?-#~3I&>0w@ z^?@7=7cTu*W?c!o*C^rd{}9kPz)NMo#CSf=qyfV(QYqB z$u4e2$*ychuGg=PL3_(YUcZ?>U#f>uT|8*=U!Z-)Fn@vi@*w|!?zaQQEy(^C+73U38HKw)>ofdx`1{}F4pR9GP2=G4 zdXO26j0~rl7#f1G<$KWnOT>5@>RKC6-a*OR%<36_yv_=V&MHf8Bz{E zIXFRMQw$R{85t(NRAyL-zIF<9js{3CSS>HAT2TKHB!{9#kO(!R*wsMd0^~l(oC%7# zpt^$r;ZCe}%VIYd#T-Q<)TrW8gT-B%xYQzru`YHs;4n4BBWH?T4phE_!X2#N61y6( zoGl(XM?7+_*yT{{^~A0QY_BgKxj;N}q1fe6?2W{(25fIE9=Sw3a;ezmQ0&dbt_Eyx zE*`l;JaVPjh#gU{k%>BZq->CNL{=_BA^=_}%3=_lb}=`Z788KB@`8K~l5>8#;k>7wIc>1yC$ z>1N_!>2Bd*>15+z`J9`5J=O%{fW_J5f_g6>TOwH-lcYlHFyXgmW}Zi2)e*dhHrm>5#~N(6PR z2yz}Cs2p0rW9);Y(khb#;s9ZU?Mdx|f1$UYdk@IV`gyJ zS#JP2+X`eStZ(=&{4jXV7rDF#sYmC-!Wb0Spf(~4bnNDTGb6@*VjNKa9)#{MHwT3` zgZL{(PKFTB*m)TfLpP{w1>MI6vde*;VGC%k_CFKDD+gwVkQYp%-JmwFFe7JIIg{vX z(7i99wEd77axXh*%rOCc=OLuu4Y_+t9Oszh2`16*QYMjZ5k}G1pt=@x_Wx&Q(N)Oe zpm`lrCWb8{ObpO_t|055L3S;`7~d4ZX%}QJ!FA;qf0vct!kt(Ch<92EyLSw!gn%!JaHA}d443Z#01k&&}2kqI=%*l-CHUd{}l{W&75 zko)=%m>XvOtw!`+{xdU!*FeGI6BbvDN^MxznH*|CB_aK3$hise@HK%=QlNaWfQey?GE+m)Q|Q{eKv=_LOtw-)b(TaaCBo;qdc?J1AVCbLGVh zJOA5*=E}J=UpO;D=F0Wa=E|EHE&sPOTK?~5wEW-CXi4&XA!x4gKjX>=&Wsab>0|*j zgUNg*Venf07wQfxL1RsgEDRyYYC!E5P@3iV&u$K?6OiQ=Ffy3I^nv#Mon(TXsR%OX z1T*L!3E|fY6GMI_gU=0W2m%Fj_(E-|D;{aN>Xvi%CIm6~!|pv~-pS^$)1FZ*djaU48%FVL&>hiJ#TeHP!_E#i&^V}AwgM|C-o&#(XZoyYVwl(=#_$t#=D8N5!_HSM z45on$3?f+F!OBqBAcET+d;b3y2c3P&xxGWmo|T~xbnmEErMwUaBbWDUX0BD)oD78z z|NjpGoed7UPZ(sU1}j6LJtIRQh`r|jf3P1{|Nk$(q6pPpU91cy@wp6zAbnb_4m&j& zxw=8_&HDe}RF#22L`%`Zvdf9VQcKmrvdfLZQcKgpvdfFXQcKstvdfRbQp?c6vMY$e zQp?oAvMY?iQp?i8vMY+gQp?uCvMY|kQp?f7vMY(fQp?rBvMY_jQp?l9vMY0QZv@Uva^l>yr=dhCxZzmE9jg)&TjDd zvmrwvXnZ>3|NkxAoDMrV8M(W47#%Ei7#U1J^Bvrb+}%C03_|nwg6?$gnw2B#VA1pc zzbPmWf#n$*E`jbx&}8kJrInct9`io+|G#M#=>950hL4N?{0{-C%Qj`W2pYqJoLR;F z`o-`6Av&2^7V|eUg6-E~t^>8{^&hKO_Z2b2>1T4qvV7b4Sv5@iK z|BxO*2TPE?g@2)Pq7Ih(TNw)#|Nal@k#w+}zmu^LbnZJ?pR9xB{<(~Wj(`4#^e8%5 z&aY)Gdo<^Ge5g^9oahxBMVSkAx5SjY&K>(K?7!%*1x>wgGnO%ceyptI;Z z4l!7Q@`lIr|7Kd?JktwPiTEG#MGXGnp8Et`Y+AxwtKLuv}r} zVEF>X7G|(qVdh}T!Ovi#AI{}Eyc{f7fY{m$mMi=mEKh*g`V5vUf*dSgfY`EI9-iOf<|HELTK1 zSZaXS)(n;_;v6hJKx}&kOAe-npa$e{kOHMaPDD7!LGlqO9BxW5Y*}gKuyfTT21qzC zpoIe)QaFIvuy6peVc`H`!@>c?hJ^z=QaFIvuy6peVc`H`!@>c?hJ^!&4GRYl8x{^A zHY^-Ckir4PhK2(;458sr4ZXkK21DtKh=9&VHi6Rl3=ATmGn5UW zbT$Kn2bIl<5n1e!+!(eVrnA}<&kf z85_WN&4Tu1ID_nGYzP9C11CUxG(h$q!PdiJ&>WGy^s zJr=%mv{%?Q?92ewd0db=DGt_#Akdwl8jKyYR%B)T$lzl53A(R7gNI=YEWd*G(}L=s zjAf21LFada$}8@SEQ@YN1{3Z~#64u7auRe$52#*+)!&&y4nI5p{oe}G!vLQD+mUogCRtN6ZNh!P@aE5Z9nUw`5APt4>RbjNwA-H!2EoIh4y|1)qS9IhLP`A z1H~Egooe8-^lcd?GQO<=x1~Gy9Cl_HG3@LBl{J?bEIZsBEHkb#Sax_hSZ3T}u#Aw-3=3tq@#%S45&%w|^@|$7du|;p<@X}Q{yVc={FBeS@>@9H$}j%>EB{sttOU)m zg3j;-wXab6+v!N{@68N5LHqt5)C*~X)(wK!s`{h1znLumw=-G(?`E?6-_K zjg4U7P(P7D4$s=ZbdcXbb1|U09WrhK+HV0G3;bIhu=0z)|H^OSek=dv z`>y=&%mVJeg8Yo^21d|*HsE##sC@zH$9*Pay&q`(0RyiC_-sKC8+4Br_`U&ML^=kE zgVywb(m99?RwD>mHwQ`|u(4Q$n;GD}?yx)pQqRE9AOxa87?fu~G-yl%wr>TL7eM0_ zps^EB+&VBan0^7R7X|MDf`sn@Mg~*ZSOjeU2q^D>&M^S#0rizXW6q(2*VhwL1KU#v z>Vqag$8tgYn80_OF?^T=>c>IGY7qPESZW+5!~6*A*Bx|&^y@(GK{9g{%uIadgYLft ztsQ~w<0E7~y4{Ul5W8XfLXqsBxPV%ILRyz4%%%2<5#dW^er4TF2c0(Z#6UaF%5Rmo^*x@Smz=*7`j=0)?c2_ zApCkIXpDgwvc@2Rfx!fHS0iXo)B|>houE01M@Zu{p!)#j8H8Vd7N0K#t^cR6Ff{C( zZ^2OL$jlG|())lJaxMf&KPXIIfbQ)B&mkf5J81kJ*BBc}4|*Is#E}r<{LocXQ2ED<3qDxQdejR9-Q@2CYrVWD@BHh2Kl&&RLuc4B+)0$xI^MDvT`Mpfg%QW91wy3_nen z7`6z5=MzxNOwbwYpnObBnTekN(Zk?j2JY}_%xnYiF@)JgPB{q*E6~{9uXM(hKjN8I zqK@&guKLc*vg!vj^D5AI`d4Pe{=1)`^RiifnEzy9FqLO#FjQn`2>H*(V8{qMKaGvS z5Oh}z@|Y`ZA0{YmfYJdhUxCWVdOn82*P!|snjSOQ7y?0JpmWthYwAGt2WZa#Y;6^& z9Ro7Mo}IxEl-@vWP+1Au3knNAkQm5aptTa9HB=xz$bAq#WS*&>jlmGYhm^+;m?c*s zk3E9sc7COU%11_UT?NXcAag+GfyRbmY!D4H+u_Im5SZIQXY4CN%P0^Vqy}VP;`jd{ z2SMvmni($st!7*aTKfr2vr|CzEvS8o7)J-$4O!a>(hu?@q)u|!xsm~V-#E%zG?4p{ z%UgJPX$)GM3>miv*#X-7{ea(LC$d^1%@;z}0~)Uf)ghp~iESJYG=>fuFBesD__>vV zVap0G@R@8|IuYcCMZGg&X8jG`IAk++=_ugB%z5Ja&Lwd!_TQ| z4nINmgU*9p!Nu?sw03TVlEY5UR+xZ-Rz7S%ZxPp)2 z=Za-cD_`lkXoA}LDDqCo@=hx?8M(SZ>%ev}ad%_-MRe68W{FkI;IVzNRZpRFoiM+w z`1K#dFPHxR7f1HPP6h$93@(SCpz|@E7#KpzxIlYQT~>bacV77|+-c>Hc*m8nGl*g9 zeL?vP61NRP1HJEx6gPp+-Jx_Z7$~j6?z{%=14HJ6(kuvr&IR}u&c5=CKgY_y)toCq z=T(5t?0mq=uoW~W@gkpL=l}n#D>IlHf?k9(?1ZePaQF%8TR%)@ocO4japL36j1!+I zgVysw+VP;Ve9#=+3T6h=uWRN9U46H{2y`|csND`)Zwy+0h)+MLT?n3ADrEQw8q|m++kKOEnKB#@|uya3~XEtbTkdwz@r@bsgq2u5GA)xU)kevzOeaW6HzxaEs{1)!M z@_#dAj9(+hVbV#4h9FLb1x4}8L?TMCxWKxhBGESz(R^Z3S3nKH*e zoh%%*~?&=ImyA2b0ULf z<}?RO&Z!KRnX?=$IcG9hX3lf4vs$Y`0#=4i>u%4nI%t$ z$Y_}<=4i<&%4nG>kYo*f2COu4QOwwP9#zvteLhSrR5LnC5D7cn^L3k|#qsUr@2GO+)jbdvV z7$nv*FiNgvXpmaV&?vo@fkAdH1Ebtph6eey44jR&46Kc|3?hxT3<8a|46=>343dqu z3>uBL3@VMb42F%i47!cB3^t9n3>J;H46co~433Sq3;~U{3_gvv43Ukt455v-3@MGa z3<-_447rWA44I9#3>A&G3?+@W42_Mp47H863_Xpu3>}TO3{x9z874N`GAwAcWth`w z%doQ1mSJh5EyI>ZTZRpdwhVh4Z5ehp+A^GIv}HKbXv=W1(U#$CqbGMs3#Ww_d8%W$#Dmf=B@EyJBA zTZWfSwhT|3Y#F{Z*)n`+vSs+&WXtfg$(Dhm*_MH&*_J`D*_MH~*_J`3*_J_~*_J`I z*_J`E*_Oee*_J`4*_Oew*_Oey*_Oej*_Oef*_Oe#*_Oex*_I)q*_I)s*_I)(*_I); z*_I)v*_I)r*_NTS*_NTO*_NT9*_NTE*_NTR*_NTT*_L5Svn|7fW?P22&9)3Pn{63Z zG}|&PX|`q9*lf$Nw%L|pPqQt3%TU^4%h1wd%h1qb%h20m%h1_k%P^zGmSIYZEyKbVTZXwU zwhU`pY#COx*fMNwv1QoUV#{!##g<`Di!H;+7F&j+Ew&6-T5K6EwAeD-ZLwvz*<#D^ zqQ#csNsBGR#}-?Lw=K2|e_CuAeze#!u(sMVFt*w<2(;QV@U+@8NVeKCh_>1?sI=NL zD74x#=(gH2XtvriShU(Qn6%n5IJVj{*tXg-__W$Gc(mFwgtpo;1h(2TB(&Nx#I)Kn zWVYHeq_)~Jl(gD16tvnh)VA6(RJPhObhO$sw6xkXOl-Af=xw!SnA2*@Fr(F$VQH%^ z!@^cuh7GN@3~O3#8FseXGHh+NWjNAm%W$C8mf>uxEyKxHTZS90whUKVZ5bZ6+A`d2 zwPkqIYRmAV)t2FFt1ZLFR$B&!Hd}^2t+ouDZMF=oZMF;|ZMF;oZMF=uZMF=OZMF;= zZMF<5ZMF=CZMF=$ZMFmNr|44Q;jzd)sUocDC6voM^LUIMQazaIwvn;cS~N!<{x;h8u0R3{Tr^ z86LLTGJI&WWq8wO%kZrgEdxutEdxWlEdy`6Edyt}ErUe6ErUqAErVjaErV>k zErU+GErUk8ErV&hErVgZErUb5ErU(FErVyfErV;jEkj7VEki)NEkkU(Ekk6xEkj1T zEkjDXEkj|uEkka*EkjMaEki}SEkkR&Ekk3wEyIL%TZW!?TZWnKwhU9-Z5fud+cGR@ zw`Ew{Zp*N;-IifTyDh_(c3Xyn?Y0bi+ie-nwA(VAXt!m!+HT8mvE7#8LAx!(opxJ> zm+iI;Pup!7zO>sid}z02_}gyF@Uz{PfuqBgfu+NiL9oM?fw#k!L8il&L88N!LAAq{ zL9xS@!JxyIL8rr(!Lq}a!L-Ac!KK5N!J)&J!MDSf!L!4bA)>>UA*92WA+f`jA-2Po zA*aKZA)~{Vp|r!6p|Hc2p`pW;p{B!@p|iu5p|!)7VM>QB!-Ni7hPfTK3^O}y8CG=I zGA!w^W!TtZ%dob?mSInaEyIouTZW?@whRY5Y#A9A#B?6hV0+hNPV(`n1V(P_&d+G)!m*lEk4&}qvc(`n0~ z*=ft5+G)#R(rL?J&}qwH+iA;S*=ft*(P_)z(rL>O*lEk)+iA-X(`m~P(P_(&+G)#> z*lEj9&}qw%(`n04*=fsA+G)$s(rL@k&}qxi+iAukPuLjPqw@?a(Z_*6{URsOTr4xgs+Y`6tLoJlK7#h3X0kC{tY_kU z)yT;ZlF7sbx^L&=D`w%-pniOPlfy?3R)!GJer+#?1x29!M2A=yLbL=A-0~82xa7^r za8XC~^sF9Mhe^B)4MM9GPfNXK*4FZotlMnQ$o;B|wP%)>Bf~{)TZW0*e_bxyGqQYi zZtR}5n2lje{SAhXPN4my8qA>eGe2K3Gi>o-Ww@xp$naCUkzry&WyX&TUaoEq#`qr$ zj150EKznhRW(R3yWd87Afu#%T64F}((zTL4QpUvFck8(#(n5zrVGNDb&dYS3C=kbfU=fX={R zSk=ko@KX!44v3NA)j}@NK4y;Y97c(*GfX_E>lr0pylGY6DshARuoGV} zG5loaXZYE{=I~RZQu)V!B?ikET;O$W6JKyK{CuJ2w335SwEKk+=-y3^*BXr-vtEGK z7Vt@SgYNzYr6;b;%pagNOqvBKQq`t_bty3 zYGmT*e!wie3N)_$7}tpmiRg`9I`)w6wu@ zb%}L*HGvwmG2xhuJQI=72zTE@Tb} zROUkFLy)K9$yr)|oi1~*I!y9b<(SPa4$2oDK^&Z?rQ{hI3qfTNhhgU|c}9kh z9HR4Q$^T^dc#^##NW!pl76;P;kh)nsk=(QIGx5A;5@rbbDh!$zZMXzFx1v)^yxTI7 zVIn8f?4VgpoZW91L)KJ)&dR>V1S*qxUMF!dglwxc{Q-0eCtCblh?%&7ovFY#skPZfhEj7%bddT6Y1OtNzh^@@* z@bd+;%qnFjNPXWVzz{NBi@EzHlf%zUW`->qpuHtb3_o8rF--KR%=qES%h|2T82>|o zvEk=SE{C69%nm<289BQ>nHhd^@PYP)HC&QsWdPMT6S-I!esc11cH3|={ETOmc-{E> ze@G@9XkLKfXXdZ}TQigxSAz1~mH+?6-{>>0gp5gwuX-fx0GcnFa)6V;1muo4`i?6> z;R3o}HaIK;nVaQ`|mF_?hd@Bnm| zGH8z-tHaNiEDT#8KK}nNF2T@nDF{;DOhK=A@U@E;>Y?UU%=_1vR)Nm9fUUh^Vs!Y) zz_cKUk!bPVj-w?{b-Vf{)?nd_RXz3qku8|D{~cU}e}k{a?c61y$ug zK;_8-CWfusn3%w2*~x$L94G!k+8LP)3?`tu9aJ~N)G{zKY=zxv&A`wU1f6f60yd}0 z9BkfwCI-unx{%8(85tHV%nVzFGc+tfaRi(D{ub`I5_T6GM!2Y<`n~yI2)sW5tN$HU zKx;lBenr>+5L(WG+>Bf=gVq2X;$+xTe~aN`6Bk1WsGfer%(w~^R$>~$-7lEMR&n+^ z{P1LA*aEu88B||3fX;bhWte!9iQ#9bmTyD(%)KfeS`P*~GF$}Je+)_oW-2I%btwP-P)jgMnBhH)@fvz*u}_o`Vmw{_C4ru!=*1iD294q?Bm)3uew$T)jR& zPBAcS(av=E+0Df8(F^w1gOpAz{Ie{ zl8Ir9eKW(y$DlqtlVtaOCXUxk91I~Rm?XPF>&`%DP=VSYn#>%hPcdC?3(JM34f{Tg4qysAcf{kGdQ)Z@x83Tg|x|?8Q z1juU&Kxqf$KMujBAW)wa)OP`;HIQGy>+}DmTwVbVBZS>rpz))+kjo&uPcb0uKEVvJ zTb6-A1eckhekAB_b&c26lR)>xo^rx}_oqEG$7_Wj|3h~E|1S<&KLSbTBCB9yA)t0A zHgS+WpgIkkpF!he7-bnRYFYyAan<;fa`^-k!&Z$y375GlAmQ!>+M`zk@%t-A1{0XL z78}DBP@eO-M##fBsy?&gp z8ks@kQXHqfI3aDs7t9=|6&N|XVEb<69UtF&m}^-LDH( z!S{E;`_-VhhGNw6Um7(`Kx1{^!kJdW#_K?9Ye8kRJtNbrg&d%98^}Gepgj?wF$OUP z&hB6aj?)M5jBOw131r%F>rKqctF^~3>@8{wlS{0 zF1UVTVb}s1^97x2wTjK*C#VkVVd8$>%fx(oJ|pkz9K+^W^O?9`CmZz40!$o^W z=2xI~Dh!Ow-LUmApmLg+I^v-OB<#?`lu;79xS}Lz3<*+)qU%|R)@B8@chJ{XCUSx5 zNXAv5^;yguAipxc?%-kwA#}!wBNyg54Y2k%s2qp2zd`X<#^mr5G-d}XZ{-^qJ|;6U zgsf!Z=mymt`{e^s;&qsC-@Rgk#L85p~RnlYv156sH`FoTpbYadw|% z;sl?c2&#ub>+3+{L?FA%*&Ke}XJYvH1irUGY!zs{15}29)*&Wf)e3S+;tVD0u zfZ8DQ`5s$tn9d&#t5$(JU*c=KdF6CJmRx)ug z{A5mGuw+SLu!NY)FmXQv!$%Ir)>)wQtu@&gOfs_=EIC;nEIC2!JO)cnP6x}EtPCcZ zMGTglybhKpLF_UHOHM%t%atH@6@w+GsDouEh+W5E$tmeznF(SyF<5fSI#_yw*li4! zoQe*Xnjm%;gC(b`gC!@3-N#_bsp(+(l7+z}a}t9kr>=wLNf3J)gC(b-gXKyPdlrKw zr>TQwCx|_d!IIO`!7>xXUc_L@Ve4S&!NOpYu?(`G5wxEU)D8ii`v)omWI+4o7#e~= z^>qdVB;}{_O=}s^-fX_Ms?ZXoQwR0I8g7~2O??7`Hp#65Bv4;%kemc

    CAbY+tg4&Xzs~DkbKzRptt_Y}{ ze*xa31saoMn8^7z{)8s0!$r=&Tqjoj{|~;G2V0$kut#JSx;&_@2T8Y}@s6gTm!LCf z)Je+|sOQ}>tpd&Gf%+A&HaTR@3DU3RsBxGKs?#5+&zFMrn_>GZKzASgO2@qW=qoe( zs&CA!t3dNJpgudyz2NYuXZTsK!B7ZV+g423V)=Sy)jvTWH1S5WH9dl_lbpHgYKta3EFST z$Y2Q)1GObU`>8-@5rFaos7&l*;P&of;Ntd{b(oa%vG($NWrm5b92q7GF#MSWy3bku zAoIrs!VDpS9EWEqbTQ9QpBE!UZ2Ikj~m<3lY`u9KNrYwVy zJu_$aNhXGncghSC&oOdv_cL;MzhmUnTE{P8p3TU4y8ffXCj};kkk_Cyf*Cow-!N;h z(q!cA&gA9n2F(q4Hg?X^WaQ}vwQE3o?qK^8LHX(@Gv_LMc80=kL57f*%#vCP%o5z! zm>A4JX9B!ZW|#;bmsDi9$i>zGK37D7odJCIfuANT41e{s+r(ih4M6FGP}yFqil+$;@2JZzwO69y44(0RCw zT-pj;3?aOgSwDE07`FB@IsDwuDEwOK|Njs@My~GrtPCIf7`vs`F)~ekQO6@ zB}fd^_UHtizrw;Gn8EzRd_NOI;Y+TDpjT`SL7sx0QXqeT!h*+PVGu7{L(mIm4lPjG z#K6KJ$j8cX5i~yif|+ksFC#-pJ)`hzr~m&${3K!8=cOF`JfZY57 z%e_~iyNl58y!w@nxbv!>ku&?ir~e_Hj2x#yZt?)lYl<>hfck$2|Njr^1^43{gg}1o z{K0N^1~Og)@4th}6etF_;h}7b<#Cg?i9*aBt6fpvw^A3>*?GJ#M zDZEPFfvvEciy;KG*Ybrp=)M((35pC16Ggyxr*y!_CPDUt%mLl00@E)q;83`lgCS%U zcz&@VNV3LZat4!RH^{C|CI)ZCT8GIfXC*=B%1sX|bnmxgEA(Mx2uWZP?QUce^#+*@ zGna!wlpA!fm%Jle;c8Y)w@G4g8^}N4GL6~6(t{B_TtM{z=N2`)klT27KNWSd4*T z%6=wcr1R?_{Q*$@jJXF4_nC5}oVUENqZvG=59@P)(h3Me-S+bfsIDgQytw~Z&iGr1 zrGIjQi2g|N$w8_7AANgRPIk@v-(Yt@QSs4W1b211DGBNDrXJXo!&B-tkbUz(v zPuPA&zSp3=%-kwm-MXO;lR)=&tO+gK+{?(t?Z?V6F_)2HXEr0p#8=FGtL`%jfaj54 zsf!!QXK3xv2o*EVU}M;+#mX=-i;dyuf-21);CXE(29qu(ho9c83==`^qb@G4ZVyg| zouIY_*I)O`UZJ&D_^HXTAPD{3c~G39w$B+?F|s)P1oeABat9a~%#hb|z}n)U(aw{HtowtE zy~EU?n#%-U$HKwrUnRC^AS%xCe`Jz0c z4i>qh4i@tndBJBS#6M*$1kLfqUt}yiz`+m_e-v`ol@9}hNc=&D!Uh(I7-+p9HZvPI z7(y`2yvSIXz{U^)G8=Tpm?fz1i^V;lJL=K(g8UhOma#C031Tnk&W8AzjD-z9|A%Np z&4Jv#$S~1fmZ1o=ca#%6AK+kN&j>m90W`*L&%gja`vWvq0`l7fMu>Yr`?`_+0Wt%0 zw>`*=98r)NJdkj?$XEzEzps<8Aqb=%*-p^e7$EiDVD%6?LFocy7ierigMq;kbp9@g zkDNAMFf*Z)GS%zAuMIv}2b2T82VT z#%`%T(T-WC84p-y9b^cMSB0blP(LGAmO<$CbH+{H#*;s38$bR8x+@3NM)%|7>OS|g z{&GAc_v=%J^KY${b(q}8$a{J%BUks@gA5nr8TnqXnmGR!pX>pPv$70A=MFLi-bcC{ z2xK|CSVb3gkR))gNja{?2SU}_Q3_FDx9V|C9Fqk|< z%Qy8*kTWP?vy-em!s76gkrA?P0X^(NbKju#W#GOtN*fWhhn|Q&c{3x%nZOUR zv==zI36EzU1hp5~M7lxsKgn$dRt~Vf(RKsF1SbZDiL@Hu9Bm(tjB#vA+HW36?Y9S< zINEOvO?caH3JiGKZ@wbIul_ee+Hbl@?Kc4|?KdF?jP@I7Y?xbst6SF>+J5sbLA2jk z8Fzr&ZmbUAwXt0P<_Ce>ZoVR9wB0-}d-+1!Zn_SWINsKf-gaYX!ryjtX1s_zzX}?U zCbpfe!HH;RKj6j@Pk7qdVhj_4!Wb45f!o^*6M`HV78JqybKv$nBg02fdmD6?C?{jx zX3dw?m%SJog1lJgOM&izPGEHS`+B*{!U;m7=pU7v@6vwJ=( z!_WDD*;Y1aGW>06JZjS-qv+Qnv&gTdvDIdNE$7MxTZX?aiU(}r;))Hn^EnxQHuEz4 zoiE7nbG|0S&iT3wJG0pwe)?*1bN4bb?9^;zn&`#KAZX7h_WI$U{~?@j`hz?f78J>6 zXzs{>w$DNLc!Ab-E~wH5x6ipm8iF{O7)(H8e>toS6ML8#es*(lcV|G`=-hwZFK36= zPFkIn4QZp-a?Q@5avNQq$Kg|g07J;={nxa;|5`qQ(NaEz(NaEx(NaE#(NeyE(NeyI z(NeyG(NeyK(NeyF(NeyJ(NeyH(NeyL(NcZ_qow>5Moak_jF$3q7%k-&Fj~qlVYHNA z!DuPJhS5@f1EZz<7Dh|?9gLRpdl)U{4=`HFA7QkVKf!1ze}>Ug{sN<={1rw^`5TOu z@^=_5Wj-V6oKXwL1Uz#ejMz~K+t?_ zCYrhfj0_>@>WCQ^0PR8Y1f2`Q$gmUJ*aC9j5UGDcR^JENtP#-9{7I#LCV1T^V*Z8v zzF;FK=GvAOoP_&=iJS}}9j~fMFLz#6UtYn)umyc>3us^HNhgMhtDG1nDzw(Gb!fF; ztJ%mf5wypN1G=UKG>`X^S#;GYF$W7RQ3lXF$H$Sjeue6F$GaNRPkIwgi?hB{sxXnR%1~4F%25IUL29XR5j1Y01-^0Xk@&#Zjpfn4VhEeG9a9=|d zfb0fg2#Vj|NsC0ixQJl z89+pQNqzx?l|o)>aY<^5LQ-kELS~*qNk*zdabj+&LPb1I;j6*@I@yD0egjMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$( zGz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!n zMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ON zU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU z1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhl}jE2By2#lx@u(xN> zWzf@4&o3!X%+pIQC}7ag$jr+uNlnqzR8X{4&@j+s(9kH!1aWN?G&Hh(6DvY8Q#|vW zL3bNyf+UMlON&!e;x#oDY;6@ZG&D3y%}g|*f(kY^3fay%*-n`y#hMCsb_fngXG(F2 zu3buIQAuTdv_Y&M#1^n2*`9f2i8+}mAs~wxl0kOaMl+}utLEgCGBD^c#440zrr4^M z>Z_J2f+JYrDG>S8;QsJ&K06Q@WWI!>RU`b*U7Lm-93Utx@0!>W?kmtdE zb^@7YWt9!)IOmtr=G(c{NRe*$yZ8QUjnUk7W zoEl$Tl3$b>5B5=tzG{jB*enpg*j6>gK$0D^-A+ab`AunGyzo1x;p}4f5peVJtI6k$o zG%+W>xFj(-yO<#uDyopE0JerZWTX^BE& z9@qvHwdI*58HoEcz~*AumY9+PvOAS37Um;e*8w$Hj{)NF_@vVGVup~?qP${-{IoRi z?H&-B%)E4k)Vz|+qSTy91&z|;)U?tZg|z%4g{0KH&EKW%+E-A{dj0dHc)D)N&uxM#ADB=|I(-aaFAkqrp zD@EXX!90l5p;l$)CFd6vr6!jsloltZr-D2K(UV%NkeHVOVIxO9+$_lbB=Mzr#ffRD zFlUry=I20C57-sOm3heu5QVxRWhIpg8mW5edJ4ITIXU^s8k!2A>rE6umzyXgLKP}x zB<7{$q!uB9D6u3zH#0dNlx*NZ1m-9trIwVZrsgR?RDc~^kdv61r;wYPn_pC^keHmD zT3no3tjCa+UzD60Uz}PPpA5>@U=xcOJku14Q%iId5_58(W)y>ya%x&yYH~?t87K;i zQwvK$@tK&DQ>l=gpI4k&T#}ksqM!jaOjAdpC^bE?C?zMg7#w`%8Hu3KOf6DKOfD$} zYb!2DP0mcqOij^aC@9LzD~V4^&C5*BV+a6o6mk2 zC;4faIjQlGu!e_aL26NEeo7`NVk;HOi!w`6VX;wA1lFKXlCJ=^3#40*AuXr0I0I@3 z$hmGHzCv+EVoH8FOlN9YYEh*^ghDPTCPDJ?#g(~9`8k$;{0xiO)@92udx^OaVnCL_z^90SYExCy)yhGjkOZOY}U`z$H#WQ9dXof#bh4 zH?>$H7ZiFBojM>Dc?u!HiFpd;nK?NMU>~9SK#!rgB)KwNJPPl1099Z z0+5j?mYG8mC6bLMzE~^_$w*a5Nli;E&4F2&S*&2BpkZiaf#E()J%-Hucu*mTh@70% zveX=qn?S-DMfrJ|Rp0_sAv3oiClho}RHcHaze0XNY7tnxSWm$~L02I!Ujbc%p@ObL zQEFmwKBSt)X|M)36YAQ5>Q_x81zm;oocyH391Qb7)kaPZn&k{BnW^#M(k4DFzbKo* zB{LOT_~e%6lw?BFNooqHhRX)k=Aiqnk~1=MQWTPlQWHy3ixu)x%b{_P)Hnb)Fko#0 z5Jv%28Ytu?=BDZ~WTxkVS}vJ+C8&&^LM%}Fh0@I;Vs48^I*`FSbvu*<(7jVf5BTb_{$D#}4Q z0bId@3Jz%XpP8os(*vz1iWw9X6cm(I^AuFm6jXy1RDBsjz&DWvC+20AfC^MA1w^9& zoI^ozi;^)FG;&LeOB9k|*;bQ_I5VJ`0ad$EtR@$zFHl*K3T@E(g04XesVqo^w${N7 z;Sz{Es0j?0M>LZm4S@KZ{KOOuwc?V*lGJz|Xy%R2FG@)*iZ4pdNvr^MKcM}I?9e<& z7=cYENk6Fn0&aCHC`6|vX6B@(fC`hMR8SELZV!V>_2leWE(Qe!)nW}zE>MVrm{zJO z3fcx0s#O(S47M16iy_=G$j{Ty-Acj5F~m_J$kEvqNyydF#mC>-n~T9czbL=7Br`8n zK{W;3%!4-4R8thnGct2h6*BU3Qb6enk{DD|thgAs7{GxB(ovpRtN<&vb1K0Gq^2l< zl8_Y_q)P;94&^5&mgEcN4sL8@&^VsOhZ%>!Abkdjye=|pK1V>;hTAvd$Q zI2EigwW1(38Fcp`$iu~8w`COR+GQ5Urxm59f?5*L%m8i$fTN@YtN>iZ#)B%1;`qe8 zlz2!H3yMf+e^WyPSs|!qLXlL2$RgVV$~53ke^F{OirQjO&6HePRGgWg2a9J=xM^sh z$-w%$IAYq_!`0ba0g@lB6jX~rnN3NxSV=(xoa1y9z!bQw2?B+rOMZEtMruKRa)ypV zHaKktBo>tfXI74;WI!}ziP1+s0jo% zsi-KiQlTKRC^0v+B(q5H=txb8Pt8k-SI~t;S87T; zEZZsA*(zuhgR&YZhe2ZmT(Ec+2jrKh7Wt=zl;>+C=47Vlf!cbY%nXV~15E}GPrnc= zP#d)}zf>V5KTo|xAsIAqm6()YS_0}Z6sJP^(8UTM6}gF(pwR)C8}f_da}z7$i@+VI zcu=mfHRNJ|x0*uo^K%$ngM$2ntQ6efjRH`$!vzyoEru3Ppyq;VF{D5OM~kLHQYEOV zoS&wkTCAV}?#L@7=clAvfvOfz!EKPQslnip17Gj} zP*7rCdMYf?A&sMwqDoNP2o!{g1<)t}2fm&{Kx$D&VgWev)r(RUN{c}XOCjR|x@GWa zM8s}EQ9ihn0P6EV2Q1PP3-my7m<%2*RR9&gsi`Rn&_TAGN<9TfC;y-jPd|4(F8E!( z(9TAF5vGWOMnOhpF=#Xe+IrDsPzH_MS}C}=SXqG^b)I>dB^uzCjD|*LN_=`Ms2T;e zlR<;(U=^C0*bIg=4@*G9zMxTaaNT4BN-@a#kSv2`PR|sD#A48(o&vb#!-e4>C-B&k zPkwT?hH8P1LOH0N4JynPpe=4&)f9Z16pB*8&4IF1P{PkC(Y1r>gS8Ps?(<7623?x0 zi5VOS+o9uQV1MGZFfj$x7E?{pwF9-NGxM_Xs)m*v8L7!w)H#9%<}kdjqfk;*NiYcD zdQn3F9DazbuAz}%o|g)59Ds5PQY3-n8(~m!YKa0^IVdP|akRA1wL?M>(mx_O1|iyz zeSpt+1yJ3C>O^ol1eMqt*?#$+DOh6I1u_B-N%N}3dLUF)$^fOHWw3K1sC>^aNX-L} zELbTpC}==NOTc9+tV|9_EXe@%mrL^V6>{?P(ybI!lTo3bo*oxNaY;&QQ4xsBFD+pR zN=;00%gjj)$#*JEOG_WJ zV~7WXV_9Nm4k$M&fD2@BuS&Jp3KVl7-Kj;yfzdj)S_bI;d3u zl13I|CoI@~1?jd)%`GUYv|~UNo}d<+ zLVf{g#sWHc18O5$L26(HP!XY_0j--rGiR^@4P;BPrY1vTX-PhV9)pXkn`5X?2t#pV zUUGgJgN6pEDz^d6B7vF^kj^2jRhOBUoKu>T$^f<*Jb;U0J*X5<&n$x`7zU{7_{_BU z)QZgFl49cYDQIM-DP)4@Y>G>YH5uRo)$jrGQpltkXqXAqiH9pFf(&6nDrJRY*l>(O z5omN6bYXnH0%+`3p)9iqG_9Zj>I{QtH$cq^(CC?d4#>P5P}dzaqNc}?T2Yc(ln0uF zgO7~I7bKQsFo08iNxlM1fdax2dJ3Lt3gE~Bk83NGgv=Kh0HXCoSd>;UAW#Nn1Pwa3Z;38u>1uYj4#S800%{UK~ZX2 zW(7lVNl|72XxKOtJUWt=SpkU+P`E09!mJpS4cT2TU?3SjU}tWd}+1%8=kJR>)2*C;_L(RL}@0 z*zw?zbN!T51V@h{CqEq=;|$^8IjNldbnvu-5=>mLATvctPXRQ(51y_|%z;cPKxPD$ zic3=ROG}i%?gnvEi;9%Md8ITDtQ<7ErvsZAfS3%aG?XA#r&grKgGRR*d_j|m`FY@> zZjfJ6D^in7!L2aR#7!QkLzZ6zYTH2K2W%l|$Sp5L0ZA#yC{R8DdqX1;oH`L+fmsIj zlP1IgC7_vz;+*_+XaIl)nGl5xblSZHG|d1~1WN6RDJhwt;u&NQWHvrGH4!}Dt&o!s zo{7?9C`&C$$}i3=sbmO)u@oRP5gMRri{i|j)VvZM1<+hYqC!$;3CPC~yL1$cv=wwA z6KN0;O<2ZE%`0OFhfZRZ;XDw z1e%10w$C&3^Yj=%{CIFqk54QC)eI#Jo_S^Y*{KR383nKmsNay8r;rGmm17eco^uWb3cr+Ki{|d_DP%A-(Kr>5z5u|8ME=nxUPykJIq$Z|- zq7BmX1^LYYR9NMgmgwfE=|X}DG#d<>*Dfy2%}p$-L^3%gvl!f_0ndAbG(*Zzh{DWN zaKc4SXb@?55ewD^ovn$_O)P*;nSVr@ zsNh$Ca1;`Y(!rBV#qgr9I5oWtF#(udT3nK!3$9nyixq-B-Gg1-!(b^y0qSD#m~~NV zI%usy5vW>9g{gpe0VV|+wSdV$N{XDE{BlsOQv}Ke(B?nHGcY|U#(_0KhQ>;ZK}!mX z@^irn2sF{GkXfRsrvNL#i!;-cN{jJ$#3?iw?v_F9kHn<>q7ppbaC8a^84CU=&P>nD z$-(0hPamHl;*XM|!~#4X2?=rx7$QDND@euT5w`%>LG2Gv6;K`zDhT31g;qSYUSV)a zEhtI_cPsTkJxowxgjA0~TDcIl@sLu&))3q_g4QljDJ@$=NYw&ruot8kC4xp>O7fv0 z60c=zq{mPSTDO>)o|scoT#}fa4XQ}ME3`_BK?_B4!2Ow$RA{FFv?>NP5S5q%F(WfC z9bT8iro9o1ykH`T+8osJhpc-{(PK!?Nlh$@hYaI^M@r*CYha2&lc@|opmBQW1Sn{= z7pQv$UgA=fT9mJwmYD;Z1BQ$jg2qra{QQGlgI$BdTs4s^(A?DA;?xoiO;95h;wYwn0kqpWCIr&8l&LA?gDizu;EVfe6NX#iutSqj{1FdeV0ri7HExgq9 z#N^8O0+4BmDWJA<3UvJ@Xu7cgyw(yFT(HHQIhjdCiAA9LHzzYMJ2gcCytpzaGYM*f zf{~t)o~a%KxJv?BgArenQyib3S_1ChA+_Ve3PufwPYf=w$n{Z zOa>_c*#}OKDGIsy#W|JWjzI}zun=qus6SiGkdauF5?@qYjBtlXVo{1hP;fBPIg z8qUkl(*;GdjzXdWXwW;o2sC>L9gPJ=VsSxYc^>LqZh1y#at3J86JjMCXwab;YyoIl zCAbcPRK&1mM`jw>eURbi%wo{&4ro;%Lvemu393^;L-Jsgplb6Jd}-rUu>V166lxLN zQJ^^yh2qjA=-No=a!!5FN}uG!9MBRp@H)7}%p6c-wg^0BqTmu^_HZ0jUB_awUQn zb3#{xfLso;1)PH+otl!2#5^P)fcl>m@t~408QhHo_dh`k20hah5NRP7tN_W!IiMl} zw8$+Hv}hPK$q&l3;Prq||3ha<6g2XS6rhdkG?;TRJq_s$Xo50SVnIA~=_G?|1!#FC zXkH6c=7FX)p)y4}3W>#udAgth5u_G>Q7U99cu9VIelcWGQWsF=YYw8#k(G@w3% znTal_cLw$qXlfE1_281X1YAmhIuj7H6iV|z3-e*&30};Zs^A~2qmWcu0?v_;p|!M< zR8UC3f&*NTlqKdUXn>aIX6EE%Le?}DYw9WZrKTr>R@=fl+@NlzLP|c^u*8xQ&}bB> zH4F6&hRu3h49SUkplS;gPRXEdLNRECR7ozV`heC!*o;d|QP2lvKmFXqf?|EpvY}i( z1>gMQlAKCVp#odD4J$t2z2#y(hGftrYhrpT$OdpQ!2}dC^V0H*a=}RlUfZRV=7QGD zB$j|Cgwl%=a}|m+N=s7m%k#j)g`iZ7q#w3S4QfVWu>!P`0xcIw&d)8#%t=)!$;?d! z^+TZUh)>BZVh91H!4l9q|J39X(E4Xki4Qjzq zC>k4qlU6}aVhJc@iXou_%9%;2@L|pr=)!1F-wm{YACy0#eLXD836K^?L;IKU$@xX8 zARjWgKs%fu0R@ld6nkJS&=aWI2AWD(K161IHVgiwVAWKal9aGQ@NKsj;LQZ}Oc=WnRyVW zfyOlT5ChZknR%dr+4wZj=wvZ8&>>&Jqq?crXyk7tsa>^`A)q$=>1$VtcbxI<%We9esLSjyFKBQX?+Fg(V z+HV4xt55(Nr~ny(1=mBF#Yn@8kdS~x61W5}1~1M{1Eryq(t?~!NX-Chs(^A3WKf`3 zPrNG}7@0Ln-O z(Yc^>ifD`JDTEfMDnMsYKm}}iY6)xv6RKQ~Aum53l!)RBK)XXgE`&CbLD2vjJcG;< zK-y&>FM;wks1_-QtcnDUe}nWZfc5JsFn}T;xg;J$<)uSLwO~zj$lw_y*dg+W!4yzw z0xCQUQj2mb6+l&~Zb@npbOs8km0DaWs z1Rnh;E-6Y*EC$UfDx{U>fw$0r3&*rf(Eb!KCu|IO9hfyA?9cl80sh#80jeF zX(~XvsGvSfO0hy7bafMSoE6l9NCeFoD-;-l{a0XwoV9XOb8}O{EjL6CPE>$qUT}hk zsL;^F?p|<16Wn9X%quC%BqGs3`sMl{Ulde=DDZRxM0as!G7*V0v4n7v*8;UK;bBeK z(A2yX!iE;7=A~#6GBhPMIll5UOKp@hO~~0Q*+Y5 zO=QR*0cdzg7u1~vkL!abqKX+nW9FdsY7G8msYOMZDUjKkf}(tIV;3X~s+dbki$QZ9 zpaKij4Od75_oNf^ATwPI;7&1UA{AWT!rcg04(VEgRe>f#@`_8KGZWxx7!6JI#sEko z*eK}O3C3p8g5+WbmsD7do~n=w+R{>xlL}Q2Edn$1(sNQ3it|g0l0mIBXx*Qgr+~6A z57J))O-7_DXn?w6;0XrsHaXD5NOEopsF4M26M^RVL9IfN5UA}5=?XV0D&?BtVf!gSOCd7prsWM z?eL71qM!uY0IvjE3zS$4+Uf#c*=q<|zXjP`4qM)42pT7`u~E=4F#v6B0Bw?j%w~ai zi>85sBR8?6*h)cFBicaMGFD5|UZbieCr8u1Iz^{cr$Q&9)>=Wez*<2yS~nJrY7&J5#H8em&y_ulZ_@Je>1`0Jb3OT81CGlCM z#Uc#3Pi#ruF63bHK%QI6-GO*}`@BIf^3|a&QqCpFF7&J6; zQuESFGGI%6KuevVOQ(>!gz=!|$;I(`rMX~ru*Hg?AcA%pLn;eWLCb?c>yAKC14_b3 z1{8yP7@&SMXi*YK5oDnfJSH*Kf>tGg)?k5#7zz@Liou5fC_;`fKs5j?3!Z(1I;I$; zFB2563K|;7Cdb3qu!C0WmL!4-Mq69h_7X53x_J{6h@gt2v>3EJAG((WtiUZZFS9rU zw4(_W50C>Dz+)Yn&^5FvsU@IYu%H!m8X7osg3}559V#OJ}r!hqV zzR?IA70|eX1w6>V2zP>)z`20q0@Psy4IzTplYzD#L%hcYR^pYPnTJyWXlZ;Vs)u0P zVKg*~Ap3lg{Di#6gg~G{eFP3PznvT99Aj2U<^W1zJ2DTAYg5ItVIh zKv@)An1EG-Hv{=5LiWCZl1xf!K}iN|J-rb)sKA>yLE1n$8@y)-l9P){;xqE|v*SSl z0$#HZ+Q@(qK`i5iw2-fPNUlcS{b8=F26hNdV7j!?Kf&zF`lYyaG zRfVoWg({e#3EB_>-O>))>5=UO8tE!3sRZr#P{?-T0&P_R??eP`hyrUNUN3ljqL@5; z6AKE!){^69@Ms69s;f#-D9y_(EKODLbSc(>dI>gqo|?i1$w^R^;N1=oMW7OjOBXKy z6;a@*QYy^@jq{{}hSyV5kakySXn@@jUjja|1(brp8%`jCN%<}^Qx%F!i&7Qh z<3Wwdcu?B`)aZpD2>@A?l9QPfTv=R_nhREtnFu}+K|@myWS6BvtVI?A z zNql-@K|G`b15&G_04gZ*laoseGE-B)gXd5)Lg9OMz@t5hu*PB$WN%7-5&VE1$RHYM zwK-_W9pMgA?bK1oOD&HFxu+}_>IhIx2HHRb+m@1(n4Ah77Dh_v_?-$#aiDF^MVZOq z1&U$5;DiRrJXnl|cF2&ml;tAXr=j6l>1P!Vkq%TN(*2qKI?gfWOP0THGk!VE;1g9r-{VF@A( zAzHwC48fWV!MY5=+6=+^48a-=!8#4WS`EQ^jlg=1z5Cs~gpnYo~pMi8iWne9(y%4=H01`$;v5Q`13Jie73Ss6`YI?!w>} z;L70X325`EXK`pAxL!#G z?~Moh09+9{LJqwO1{E7P6+t}*YUP5uz>wlaO99#eH8jzLb{jx_=2XyGLwWh&vKgii zR4stm@nBKVI()>|eQ?2ClnO5C3yM-p;*%4LOKd=4Yo`I4WQo^=ss(9=pK^fcdV!7> z0dITE%ZF@u3{T7imoVVbhE&kNKlu0^s1DEuNr*~tLWPt+&~_wfSpuk+2x>}KSeV6| znV=LnIMq4^`QlLs8oB_PilPLx8V0;{QX?r7lp?{Q0IHsX%QMqJr^6Iwf(9QLAlyXo zSybS&oj}D_Vu^xk0ch3~vK$+{r-&f{cAO445)fQaPnH2ReT3+2S#dGIJ6;OlGafuZ z%K^ad0r?#iRSK$ArQp790ivY@w$dGP0!&$A5vUxVSqWnAs@Uar0lQiJ+(ESq%ss&ciD$G{30DK;WEu=sxR?r2Xa1jr0 zGiVe*g)|kk6tW?;x-Vp~FB7ztjzL31BNwV9K37vgUm@E!wImUu5R~;`nFGln6gAGN zIXU2b;aLpP0L%{i|G;Pfx$7 zBu5{7Toh!}dj^AsMk4rBGw>lOu;WfN)F6lbfDSS&%`5^n%``#dF5uGx89@7MOQ5EL z8*9ksf=@938C#0zVY#Q4_!K8;lxC*rD1b@~(7sVcjbZ~m&tgZgDY$sg6hf=U>1GmdHxfqarQ&f_p2l7k?C{2KO z--4WWWoZ9ul@gX?7Ipexu)hyZ;5I&7peH3jS;Jw1K+GJ<%}Fmiq# zk^ru zCqZ}QWEPiztyToBrK$u6E+|$EG+}2vfX~4KZ9M}|n1IF~)Qe#W7JN(`?3g2{mr@lH zL3{G@iqley6p}!vc<7OoJ|T<05{oMJG7x7RfwGMcXbltSU;rxS8&I(e>u2O97Q`o| zrt5$gB!C-1@kk{UvPy8o!}B3NMez0%s!^Z@H2icUaBmlCIXEMr$bw5GkSwH)i0q64 zoK8jF=MTz88KrsIpyYsbL$@)*C+-Zo&y?q1NHDgTd7MS1MQIGKES?#9=r@4frss^2GJgnGgv*L zJElQxcu=ii2%Zjt^UN6FOt6Gv9&{lmLt;{KeokpgYCL%M4>XB^kju@?%gjy80ng$< zCVdoa6hOmJKB;*Ojs>9Q!G4gPo}k$w(9T%sc{U6M`NiOADjU%HA3NyrcMP_+s>KYD zjrgF|^RR<$K{M?6pdLs zCYOMQsxtHQ7&J6M;;A|Dxrtf%praSS3BeH5gusvjXY~BEwBl6Iu|b9gda5Z5pkb)^ z;#AOn!Q}Y#Qqbb_q|}VWvdsJ7%GX_Xc1xjTwBo^hCnSn`j2w4oFvO$!Y2}4n4 zadMfN33!46G^_*b`#^i}pncj%%@W8;LQq>C)N2E+*#x&SAc0X-VhCywrsk!9PLzUH z3g7|Hq7oyhj1ja>HPA%r?juGyHNlgi;8UF7hoq<$gU-%@4uhg70Jkhai3xe26kOJ- zfs})$JmH5Dzzha0$^;*ER01oTK!+K@PR&6cQ2-4#q!txHdf}R&78`v24RU@rbdn3H z&8LbuF$pwKQL3d{RjR3{-~yVy(!+9QReDi=IjHdms;xj>CTMA@S_Re#4*^)5KymynF`mtQ~_PLuG0)186QD7RZ<;WagDXk4%6Wpqc`TMu^uy zv8AB_E1E!+JX8)5eTbQ6(2?r!ndVYZ9|SbK18UHN3Oi`&rvXz@3M%xWrh$qMP|gAM zbd4CmdozkN%itqHn65_Nq65m#C?NoiYfN3B(F1hP77#94!TC7_G~WX%o4{o(xc>sG zK|qBJ_(T!VK{?Ps0rz`Ad{9eRL!;E#2sB^>IwL6?dZ17W_>_4~=0Fb1$C3Se76 z2iwCdy6lj|Bv3m}Qe-IS)G5DN-(6&eBFf-&aGWZ;T(6(FVFf(jrV({4jp>5Yd#C=vkXxoZ8%nSw$3`;;X zGXsN936u|_nHd;tGv+WeG%zqM0nsKb3_dAPK8QA9VX%#u!_07-l|gsIY-WaqEDX9! zW-~KvVPf!E0HJLwW-~KHF*Ep-%w}egW@FIJfbvryw5`c(h(A30 zgtir#4GA}a+2HW<;epV$46`BO_GcEDw*4^+5^i5+LBj3BEJ(P$fzY-uWqK( zn#_cRn*oHj)tLziH;tK)a8rTMwh}YJ;pHO&p=||bLc)z_CM4WAWgxWL5VGX+B1mP}=4U}Rue0;10|G58cf`5^i{6N9Y}lnjCA1Xi)sxOo7BNhz7;41(Xk>LGi0I1romdLibXfY7!pdLia6fzY-+y%2LldLi-d(hG@q2MBFz(+i1r3kYp%(hG@qgI-9y z>p*B*g$_LS)c%RV&iFXhUiuWl{K8Oazdq)o>-k)?s z!tF*kB;Kz;Xxk0lka%Cy4T<*!Q2rbUZJW~#3AdPTNVr8nXxor(NVo++Xj`9dNVs`) zL&D7kLfcw&L&D7jLfaa2L*iGb8xn3B-H>oofzY-JQ2Ru>A>k$fp>27(A>qaWp>6+k zLBj0^gtq2GRv~5Bsq0{9;y*ed<=z(v zZM&xflAd>TFf*KHV({4lp>12*A>|&3KFY-4(*Wgz=%Y*wwjoeHh(5){;1dAlgXmLC z47LJLK8QZa#NfjN<%8&xOboUs+92kG=o3r~K1ZN@5PgD)!L|p=2hqow7<@XQd=Pz{ ziNV$a$_LTMm>7IapnMR0jETWkrj40Fk%3_eh?Zw!@R5M>L9{#*gYAP>NH|?-g@n@u z2yJ_ym6-u#-W~{TyQ7tv0p$NJ5Zbn-6%t+zt;`HZm>7I&Ahc~vE2NxvXoaLR8>l*q zR!BKw0-w5?1tBwt8CXj_qHNWKtghU5z#2yM&I49ORNn!vQ}k0ywFzcfMe#fK(HzIX$n zZC^A&?7Pzh$rm>uwC$B9NV>lOp>2;eLGr}`2yMFuBJQ&TLfdvULGlHN2IY$uC?72H{ zA^xywgoK*~gtj$lgoK*`gtpabgoK+$BP85ZAhfMSBRIT#L?E=SKqDmFcp4$$#?i>k zaFB_?hXq30GC=M7(ZI}bk&(gY3xu})&;YUT4TQGc(*Ow<5Df~K9Z)`q28GL-21vMo zXi&JUfbu~!C|u?=K*FV?ftkUXg+aHbftle21H%#!4N_kL<%4LD`iur<1`7s;B_JAP zUka2DqCxf@sApzSXJgRaP|wW3&di{@qMn&SpP9jD352#?P!CCu4G_Lh4TQFhsb^+b z%)+2+Q4h&i2KCGg2bdUqbRe`X3sn3^9W%o|CI+7`5Zd-d9mM}28sy#wb<7O!SQ&J0 z)Is9;L>)83eo*-Up>0>xLG0Ekyr= zT8Mk@Kxo?wwag3|j0`?!Ahhj?T8R5VG{}8NpnMPw3eP>Y5cf`~g`|g`T1a~6sAXo@ z%f#T*0-WKxo^NGKl{QAhc~x8N`1XWf1?RKxo^DGKl{|Ahc~j z86@5KltI#sM;WC2b%D^f4p93{${^*h0fe^IDT9>18W7r6rVLX4N6cSz{rI7Mh07Bb-D1nr} zZ%QEL?*l0R4urN{QvwOMIVH>to0%AVW+Mo>P1(6$K>d7l^vZ5shq7f`~?uz`ue#|J{&dO+lTTp+aV zf?`Oy7Eugwr$;d)eqA86twS*+er+JMtwk{;eocxY@oNB~ZB>dP@v8u#ZDpY5i4-$4 ztY>2I5rELPJjD=yb3kZY7O1)}Ma&HAK>bn(ZTqGOqV5HRw!Krt%&->J|AEl9S0Lg( z7a+9liXuongJ@7ZFM;wwG$@{D6hYz{M1$ga3X~6`LGj#C1c~Plg^=)=QwRx}AG1EovynHhF7 zGw7blgU}oDm>G65Gw3eJV`g~H%%E$N2eC&dkC|Z+6N8Tigtk@5gZM`QLfc-*h4{ZG z7oxr)mziN2C_O@G+lpLfhAE)(8$#O_fYh@v=;q`?(nUrtGs9|7x`fcSF}aX*5dooX zJ#v{DnnCqtE;EBX3xn>SY=}K;vLW`YfY7!}vLW^?fY7#cpz3n;sZk4wm{^4 z8X&Z7Nj5V>6AOc`NfyLhjVxw{RZI*%DiGRMA&Z$|C1_j(Lfc9})$wF8Gpt}@@Zo^a zwk%nYaAAPZwm&i<=Do;dW?0U|;PV7R+djyIsJjE9Z5L!h%84nN%nZvw`5QvpHe^D= zRVR~~ArCY@lgZ2=%EI6y1EFpIWI)V+lL3jJ7ZBR^Ne0CH2N2r!4piNR3`lsLfzY-m zG9ck~1VY;$$bi&q4H=O7s|G^H>SRE|-zFVGPf2BFkYi!cZApcwYk<(P0jUu8IHWQ& zEMa2sv4POG7OBh(i$V1#gtont!pxw+!l1h)1>(P)6o|f<6o@|}Ahc~r3dDT@5ZZQ1 zG9*3UNMdG?Wns{r1EQH3bSES+Gc06c@acijwjD{3a-ao5+crSe6(lh;ECA&X2yL5@ z1gRHNAhc})R9!?8GsApPdjUe*20+a5@qy5`9#C~QNz4rMm>7I4AhfLsMBc{$Lffh& zF*D3%V(?Lb(6%xVaUTf?ZOfCy%rFO(ejv0h3q;(90Yck;Nn~c24JzLtwC$Tjh`(My zXxk@=koxceh|j{HdnXZ6j@*FIwr3KV8ICbB_?&>ywnsqfm>7HxKxkVLkbY(c-I@eu z25lAw-I4@m20Io8p8^PNo00&@p9u-f3^SP+d}1K9Z9oDffBHaZ+XwNG_`4F%%rJwA z!RG>mwmlOMDUVJ-Xxk%DbvxoA>2M2#w%rg9iRU#C+I9t0-JEzxzMTP~ZKpuweI`I? z+n#uc|2yI#7KS1TZtG zvN7n+fzk~D%naXI8FFeMbZkNZL|qJowmss{%nW@fm_%Ao7x&CI~b#-Qur4T*mXZ%F&h1VY;ycthe>2SVFwcthNy;tgq^ zDL`mj5pPJo5P;COJW%skyqOugnHYQ+AhhitFNk?RAhhilFNnP_yqFofK=mGkwtWDR z_qhY1ZFhJ<+Fu|V)c)E6<%4KY`)h?4r2Pe=LG7<4P(FwTwZCR~LE2viUd#-oObogT zP+Gu?nc)^IgYE}Uh&!HmGBb2CG59=y(6)CxA@02ap>3}~)t&HUX6OL*pCPpE0f@ZM z9tdr_!xK_JPVj`(dp!_3w#5??KQ&M~#S@Zld^{oJ0|uVV4F5s>LQhD$U&Ip;s?P?Z-p2w$+nPYs`xroITMnqcFYXZcJaK1c zXaj{Ogtooo4sp*72yJ@>s_uk4#63qKwCw?iyw4s8Z9Bys;+_t7h2aWf*LEJsTjhW#iD}!#08#6-_6N66$ zgtpCbV`gY%V(`g;(6$P0kZ==lgXBXV2yM&Z1_?J72yM#%b5x|Lfr8J zLfbxZg`~p;u8{OH2SUfTxI*$1hz8}S1}GmygYr{}DGZM(z;(%%noVP=S7VbIlq(i@y1<@XY2h`Sa*=-3!% zW`=GS2Hgl}W`=qu2A>cJZM((^Vor<`GeaGye*>XyHJq3k?z1xJzHx-eXE;LSQy{dh zi6cb*hXX`@iybqA6*GhG8e0gxz?PZe0V{)U3zXhs#mu0?!k}wm1(DaVVrIC<%Ak9| z5)v;PESVWJ=b#>>qPT zId{VxGCqFAoSC5t)c%6dwmZz3!S&u6sJa4kNV?B4hqRY6%pvWi6bNmbU=9h70CQ%B zN>KkFLfd+nL&C!aLfbk()ft#GGgN@aEg`h621MRR1wz|Om@_k!gYqMUwiSSg`|v<$ z+c#zq_ir(Sl#3h8Am!o`D1QNjwrw$EW_ZKOpj%+Z%rFxak7khaRs%{)KKq$&pf7(cz9s~iN7ZhI`)bQ zBtL>^P<}jM0?EH18kB$cK=~jVlz+EC)q`k|`VCM%hz8}~B_@#YY%qa@XN?IYJVT)T z04U!D%6EX!wk8nwJSQ^UDz0mIo@%0;PZGGBczyG5CCe z(6%phA^yFi%gm6%#NcxSLff8!iXYHrW=ICLiy^e_2B`QFU1o+PP&*hx+fIRs_dw|e zU1o+v(D)>Twk?2)r|2>>B!KE|2yGhz75C6(W{78E@Nt3AwiZxv9bIOIIMBE#gtnD| zii<#L4qax3SSAJ^76@(oLkHrYH#*D=F-#0TFCet-9jN#P9cG4TCI+7~5Zd+tRD1`N zUZcaz5CtkXAhhiqsQ45p-2i#wgph}3@9C=!^{u?YHvYkTOX*n3zW9d zVP*&i#UF&W)qsjCKxq*jW`;1(_&kKRWr2$S(T4c%i#9WZGbq16XxleX@dw(>456TL z0SIk-0V;k1O7GETW(Z+o@Yw;OZP!4>mq6(m+RO~WObk9#Ahc}@XkDG)k# zhbBb4L=z%j0HI^gXh6h!G$7&~5IR;s1L7_Q4Q2*ECI+8B>R{UThdRVvUm&#Y2X%qTc5Mgtk4R&dlHq8YhI%wtFDrK06?^?G~uH8`PN@ zyg=m%gtnan6`!Hb%-{)%CkSoZq0Y?U0h-^1(6$W_b9`zbw5<=w{h;x8sD1-=W(GG< zyAnd%%BX|KV|*AuG%JJd5jBXv4yZ9RxP$UPgtlFw22r;_jhVrZg+aFis;)&1VqOD; zwk?3F%Yo3g4r-8k;fpFW!&O!W-3nD^hAXTLx;d)M3@)Jb1EFnGR3YIW0iqcgd_o|! zZGb8y+X+3PXUCs4N+!hxXj9+8=wqvuMdQ_bx>wz2w-4X0-{0wuz~VH zvN47v=;%nSl-47wkbm>Ia(7Z{gAnjES2yOdE7Sdk* z0ikWb$U@9}BFoHR3mV6P(6)DEA>-FKAhhijSx9&;kp+ii&H@M>+aU{Smw{+dyQ~Gu z2hpH*S%oa59S5R8{w;y>K{Uv}8M2Ue;EI-5x<^hEJe+P>`8{fsH{o1xmX>X$>eX0WmK}1VYEY5rCAhF9etwWY`#Vp9nza zBd!QQ>WKpa%nTB247z(j>OkXl0+4jK0z%s^5rD++0tjt8M}V0@6678MW(Gwz2Hh3` zW(HwUJPAPNJrV>U<2?=nkntfEC@mns% z4nXNO{E+Zi!q3d`3pB684;eq2zz->>I`|>&y99nnKUIaFnIVFKVF`!^m46CQK8OaD ze;@dm8LU_sbRY0R((x5OW(G4*I{-r4p5cS|^8|#pJpxs?gO8cP6jU!kXxj}Cd7m{9 z+I9sWB;725s-M9JsW+!UXxj-8bv`{1+BSv{67LZZIyQihnZXb=FV6?54`uiu{aX<} zW(H$WdmcjDKH+6%uw-G-y~7KM&l9}N3`U@N5eRL&ffr)V8VGH>fEQxV90(oT!3!DB zui#~7*ag~O#mme9$|ogIK8ObA6JAKaJcSoh9@+3h+@r(G%wPcOS3zjoBRr6K*aHyS zb^;GXUk?vNUjvk%!Nbg;!p5NcgBv3Mh8rUP0Ls4t<)47^_dxkep!@|;eh-vi!3{N! z3u4|EE{J(Ap!_Rb5cwD=KLRT61Lb=_Xj>Dgx;vbZ_RkFn9Xo}SnZbjBVF`!^rK1T@ zK8OaTqaIF3`fq`XgJ_Vt1}GmygVfn@Lh4%(4U)Hj@m*3GB=atPBiGKs3ml9w;9~gUqRc@bz(IEK( zc4mf0p#CB|q+Uv4hs+Bnuro6}0mTnHBwxiq`5+pUuOir)87x>BbOYF#8T3KzY6xxX z0Tnl4hqMO`AhfLrJ7gV>0MvdE4RQ|;lnXxk}F5O*suLEI_8#LS@2z~I9Jp=~*sAoUXqgtmRa$jlJQ!l1i@ z5u$ztBSifY2yMH75u$z$gtm2Hgsjg9V1TH1U|?p@1=Twc+SY;rqTU2T+kW`Z1n%!V zfzmgi^bROJ;Xf02U3JJmh&m4_Z3Cr6{z2qV{DH`?_`}2?1?s>3VPcR0?RSLI2Yxew z*O6rWhNw6B1yQd7rDdQr%P)w&7e68De10&2_cy!zU}Df=V(@W*(6%-|n85p+Eg-aQ z&3A~pobOBwTA*0Ycl_K-HOiVPXKSmok9RwmJ}b9}Ng?+wz%-A&iAV_rOOchH%ih(MJeB=OYt% z{Z|HrwiSTTK0FZG_Q?k(@IIrO4-j<~5ZX570~2`tSPX>k69J)ZeLg_K!Q}%J13v?U zj{}6ZwfVrrz{|kkV*#OU4WQ~2J}@z8FfsVZKxkVDh`f&ogtircs$==U#GuZ^;KKl+ zZU4N7nD+xh+lstrVsK<(@DYH}wrAckf%mH)c*n$`2I@CKXxox^OyK>UIqx9qGa$6B z4}|vdfY7!q@0b`k7#Nm-Xpp%KP(FxuWMQync?$`b1+O9DG6zE2&Ug*+f5&Sk22~~o zpB4yh+wdBa4r?H^t;TDJeg&v{k=INNDohMM0ub7k2cpi0147&WcnLB04Txr7@Oc5D zZJ)e^nEL=i+unJ}1RmEr@)DA-d0sMs$ITwRfat&Qf(cv>o`KM|Ctg7GAA!)e1yFSf z5P6>%2yGhyk@pFK(6$qvGlA=eoac~mPI=D65W&dclK`P@U7+$4oJcHO<0ikV6pz1Q7F)^%UWbjFW(6$K>d7l^vZOZ{w_v0xO!(z}rDhO@+;VHzt zHxSx(!&8X=HJ&mt++b$VRe1_=hsaYV25klg9{~t$%L7sG!vUdf|2$!0n9a(N^8-T1 z9)Qp}dmwb|jwcXvHavmk^ED9KcEuA&K3@W%Z5Ke*O?d*z=Mx~bZ4X4=rvpOUwm{XD zJb~o%0tjuJ1CjU1fY7!nP<1g+Ao)B3LfeKw72N3mp z9xyQ|f#y#jwC$D$5dUm|(6(zHFoDn2Sn+@fyx)Jx111JV(D)UEww>{S349L66bNnm z6gtj$+%IiSoHSRDm$b#loA+)UmR9*%uFL8&7K?XFh1EFmNKX^TKT=21(Go9)z|n zxXr{M!Nj1u=N5$Cah-_)wC{EcgtlFBorysl6fY3kHsU%Y+a1S^KQSWk&i9wW!!N&nY+uEFisJDR7wmxSe>Kx88F|;!<_}D;bTZ^+0 zbtVwnmgg)Jg9sCY4+n&{WjV{lAPlN+Ahhj`GfWKonHh91oMB@41M(+?w%u}ui9v{o z!Dj=6wq0|Ei9rxFe+i*&d(JR{_ltEvXxoZ2Obl~a8FES>bZi0C+zg0$J}D5|HsB1@ z-Dj8>1VHUd2yJU|2I_7IZEJ7_lKxhlVgm1ztU1L5KA!?aXD~AOR6zM4I)jnHw%`;K zct4{Igtk3$5|VBYKJy zhS0W8PB1Zm`YR70wC#x#Obq;>aTN${yXOQG10N{=LTKBT6Oiy}fY7!PCm`V*Z~_v} zJ`md0ifzQtY(V%`-4wMg~ zLH(?R<4oZ5b6k!yF{m&wECJCVbtcCl<&(j2CI(*6JRpR&Wq_&!(I9nyjzRQ+Xpnga zjxjNOW@6B-IL5@VjF~|<TME_Q+P9U!#rpQBLyN14FmQ*WSr5DhZ_1(Xk> zLFQjL3Nb(DD8zjkN0}ISKyCI)UM2A=>3ZR>HA34DHr3xu|{Im!fH2gw07 z7es^YIRbIViz5(sJc05-G|1jFMtk2yGj11QLHf5Zcz_2opmv zGlP!_gtk>V!o;uuG+qhe`zS#9AUc?t!FIx7h`B9?A?7wfXxo~@5OXUav~9>?h`9j} z+ScJP#9R;!vd;#}2hkvNEeZ&GZF}b+ zBz<2w2ua@;AhhiPsQ3;D-)9Siwyl7Qmq7SF1rXZyzyXLkdk#R%*#V(#|Llj9%Rlx* z;_u6TCI)uUx?c!w`(i&NeLsQFwh#70+<9j|69XG){RxD&owFZe{*?U?^Cv)P+X$$5 z2!!tw0HJLi_Cf5m*$1)LVjmL&E2!Rr(6&1JAoglNXxkZkA?8om3o*Y3Lfghb#Umhm zpAZOb%d;0!zOn3uw#)Z2f%l<~BFZiu@oc0>B7B@o)SU^k@wlmnq{ z6QJrsAo4x|5ZcxUBJbk?p>1F6g0yc!c0s}gv`HK^uLGh%?kLy+5trEk2`>;05}&dS zQqPKPV*;;#{;(B7AJ_`X-+Q()F|dHjaR_bOvK3;F$5x1WAGScu1JNM!-az>v8sy&- zTOj`2v4x3&88jaNp=~#8frS4W2yMFps&2*>CI%+ZdJ70`I{_l^(*vPxGqyn7>#~Ij zynn@H3ln%<@R!XHcVE~H5#O`e@kn;2hlz#w1 z+oo)Sm}|2MVvfcph(9DYLDG>3gtisf1n~zCgtq0_1W89Mn;_{3w3#`Uk-_%MMo2pP z0HJLkKxm&k5ZZRbMo2mV(V%c#1LcEgP&h8w2uU|F8zKJlfzmoqbs!p~PXo#a(I9;? zP<=l(K>YJ!14RFx4G@1#*Z>KSiVcwdUBLz>21Zan0z%vRY=F26M1#!tfbu~!$b6d( z5O;}efaD7h4aye+P(FwTmmFf5ZZRbdPuplW<4bQmaJ!DU;won zA+)WjKgL85w;3tb??VK=gk`2HP7@K8XIu z$l!AY$_LT^7#VEmtb>dfD6E5olgK)VeJoJ=%UTHk##$!uy6h!unZWasCTk(-A4G$~ z#{kL)(V+0*S<3`IALGj!i2e_2ApU%_hKWI!nL+o+8i;?ktYKpK%gErf0Ycj@S;GWA zkD~@k7p!4o_`}HHlLMh`GuA-TW6T;R@VI>hgtiS?!vr3;4}j3NK5HQDMvXO)_MZxb zj^$YciT6LNA@+Y*&BXANk-_H;gtmRKnu*~DBZJQ!2yJ^|HKaXx2148JSPhA95DoJ8 z7APM?gZ#Z=HN?L?tC<*5SQvadAhd1EY976zXN2yI)j8dBbStcJMH1wzM4tcLiX zV>J`_JQC2RYS4LIb5=p(r(_jGJ^@O5tb~Mz!%9g1)&@e`TC9YWrzQ~E)&QzbWhJD4 zs{o;GWgzlC5)j%}1gef@CAeSf1KKp*$;e>)X9dK(9}wF1%L<6SZ&pD1w=W>H?GuQ+ z&jSc;J7)zGLo5q}F2@QchBy`m-5<*#>1_v;)>#gzPc@b^F??ra@KJ%#wmi!r?Jf=o zZTn;y#J(%bm>9k>GWcA8(6(omLCT>M5Zcyf8N@t~WlRiT85w+BAhfN{GKhH+PlPri?VqI(`4>we`kyRiV))F+;PU`N+a7?*?}5;^3zkCMGi50g!y85hp9v7! zwr45CJsl9*wgIZHWGNHFCq@RJ0tjuJ1CjU1fY7!nP<0VYnHWAYGWdi*XxjjYypIor zw)KFjvslW+@PU!R#{@##8bIWIbRe|tg(XZ3g)9uZ6P7^y)3bz$;XNaRPX~myEm;Eb zZwORAUGztZBHzO#Osm;5ISZ7 zr2cs`9}-Rv=0n2i4urP7F&`36S0J?Qn)wiSu9(ln@S2gqX9g3E2yJ_2E`)yqLfihC197** z943aBpmB2uZL2Z|qVCFUNO-Q9&BX8mG+zjzZKuqJ$T!S}*jqE3iQze@UkagZBcSpj z5ZYE_HY7Y`W-~E7V`T7=fY7!gvmxOj0HJMf%!1TQCuT7*JY{6?IRc?=56pt--!hAd z;R&eRgwVEYW0#9L&`~m=}Zg)3=B&^ z^jua39~~$kM9*bqu;qcOyD<%-4n%|0U4imJG)Uc+X-o{aK&7#_1S=_q7YJ>eG8N*E z1PE;#GZj(~dQ63cH;4v>x5-pU{D5ds{1`y_AQ}`u8c_8h8l+wY$_LS)_>q{(1m17_ zWeTKy_F)RdpC_RFBT)VhD1Qrtww(bLpD=}qp_7F{w`U5(A01Pe816AL__RQ1+nOnm zd{QuliQz7&Jp-X_Gp0cDNeYCvO@OKknZm?yhmpZ207BdPK;(TqAhfN<6efn(%nZ65 zQy~5Z(I9`bK=~jVjm~LH_;%<%4LDzwbouxH$Z4xACNdBgO3M{kZ_fl1Svm6Aha#VBuM&TfzY-OCPKmkM1#WP4wMg~LE&*> zA|yOOG$=gIK=~jV6dngALh@Rgl0u#e^Mh2f55ZZRi1c<*TKxo^J2}}&v7#VyTpmYs{w$+%x1YUmu zqOXA3MNq!V1SWmk(mTPYRR|qCxT@{Y;?!?Mpy3NPhs7528Wx4*igE5)ciN zw}J9OG)SJO9}<2b8YIsF<%4LD{FgpR_M1$n-^g+T8M1$mSK=~jVB!8q2 z5`G{WB!2+P2hkw;HGPoqTLGbME1>cqI-QZhrv%Ce(dmo~wikMt7(n7@Ahhj~UM7ZG z(774CkaV=57m`2bKxo?;y^wS?1wz|S=!N8uo?b})=z!3+HNBAhQ30WCOQ7au^fEDA z2F*i4XxjvcIX*EE+E%9*54&Td<3FF`A7oF2hpH>#M2AOM>l$y z7(_t(?R%IQuCp@ePUvA`xWvfd(*vPxJ9;4b$D{|6e*~cPlx|4)f@sh<{{$!>L}xHE z*k0*^^vfU>N$fBNIjOnL}KMT}+5Dl^qbT|d*ym}A~vhPPb z#6A!WQvU_Y2hkw=BHEc4Kc(?hHiU=LCedJpz&UIRK$;Tbdx_0uE6122GH3tplNLH6ZGIR3Nmi zLK7ri%QQjKwFHE=nDwn_yp0Q@O=Q~gJ@9rUTK7cFNg+(?*%9yM1#WjNFyYj zu4sh#e@P?Q-#!ZjNOPZA>F1 zU2`--()E)D2z{i1iNS_}VF`!^x#s|s528Wtsi}wb?{n%Q{r{AD$T)BUgtm>ThqTvi zAbcMS2yH6@5@%u16{v@#OP+crhBJ%|J{%C*mZcsNk6-GT7*2!s^+9OcH+7JBd;y_t zpVUFZ`#~KO!zs`>2!yshQwQhQhJ&DZ zgwVDHH4yjY)Ii*m0OiL(Xj_dMNcgKjXj>7ey#h6mbjDM|#IPTfP9e1IpK3@t`vIYC zA5=r~(UfXP`Ib=4#9+$EpzBZ#alcJ9#2kxiCWd{W@el}Ys{zsPqXMCAC90VinwS}M zS*ju7^QH>ie(-q#p>3a3LBi(>om?#l*nIz@U2pLN5W)pm;k2<%4KYyd9}xV%WjV zpu44t3A9ewX9I+`T~oyb+9%|*0z%s^fzV4pG{~FY%hwNfo3#D1gW>0ns4ybD(?>4KhCj$_LRP`2Z*%M1$mApyonp z9|tHOO555%?XiIRA4G%9F@f?yG{_toC?7ERR^Vg9Lgc#XakX7 z0-{0YTR{0B8f3l#ln-ZiNT4L!N&(e+sZ)Y zK{Uub2`C>#gVb{rF)<{8`hi7|bqNOwA$$-Gs#kUtGBJE&VbEOy6$jBE@s>h}J3utZ z+=@c5`+Qy$Ffq($WypB~p<^EuK-7U~kbQRw!0K!>3YZw8SQ&I3p!9-#CWcT@xI$># zDfy6etdq~g5W>jdqXD696`@~@QxXS=S$13DO z{0X8#^{EV$528W-Tae4dupQ(c2yJVU%fzsak-^6RLfdlWGBHH6Fz6QKFfn*BGw7OR zL)wQ1*-Q-Wj0`?H5ZYEE8!|pB0-y444}`5+pkuLi0QM1%BIK=~jVBrlV}#BhLt zVF`!^$xA@_AQ~k9CLPlM2GJn-7f?Qk2FX{XL-JQfIuk=NsGkU-Z4=TV`7j1T+Xg`O zfoPC9K2Sc02ASglHOC?y(#|)5(6$B;{XRMn+EybSQje>oL)!TY5ZYEG9a3HjKxkXg zp(KZy8GQbvfyHfqq(RyNU(z7)^C69iVJm1p4?^2MfvEF&0HJL+q(RzYAR6S}HBdf? z2Dx`Z8l>F@qCx3q4wMg~LFr~f8l=BalE%dFotZ&5B@MDp$pdP?OBxfy7SOs%2yJTt zvDe20Lfh)3LDGu`gtp~@+7F^Z?%{y)K{Uuce^Mdt0ns4${DAU7G{`+~QX%dE9l8P< zHwMw5afCl9ko*FoLE{T1DUk660|;%akpdZC;7Nhx!yUc<59g_@M=fIK-ndb%3 zAp1dwwSd=GB!kNn+b2m(44XmyLI`bpCkbL+M-s%m6ez8c1W8XaNsx7?5)j%}Bngt9 z1R%8SpG1g$kwi#+3OeM)fSEz}NCKo^J0}5R&V&RehK-0kpMBL1wz|4K-ELfd|cgQ)uep>5y9LCkv+$HXun6iyJ@_6|he=LUqfy#iHt0z@+~_#A=I zwg({cK6@av?T$Fe`u7EKkZ}4F%LHEkej%2LAsy5XjfIq(8z8jpidcyKb7Gko)`7+$ zA++t3Scp3(Kxo?@sJez&CWf_)3_djw+O`5B?^6PyZ4034Qev4H)`0rE5ZX2dBJUFc zp>0E;>Re(W;o|_IZEYa(J{Az#)�fCl(Su8W7r61tRaG0HJMVpy~ubG-y30gtp~? z$osHBXj{->J)mT!7HFXCU%ECm^)#k!Waoh=!D(bE26TR)gXh zLfcM=2A7jQJrLTqC7OvLgPB2BA{r7tFQOpsxf2BmpBoU`_DU4ky*?KpwCx$Fx&u*= z@Yw^QZFfNAeYQYo+YM1n3@OYEx(lKp;WGz9+txt!7eqn!N#sCi+YE?4pA-mfn*dc8 z5(U{O5dfiWeIW8a9uV5r1**;>3KEVc5ZcxNBJZOEp=~vw>Lj8d@gf4DZ3Q6mK0FZG zmLm!hj&C9%;jFrGr}P0VhV(|od6N{>4DI;9Z+)`!XW9a2146bK;(T&Ahc~p7!$)n zP&)}i+a^H7ePSTAZ3NUD9}vyJ;Nt0n<Qpe1oD*&QF=s*+X|>TIl)W}vq9&HLTK9*h<=|02yGh!RTmJ<#4rmq z4hf-cJs|QvE)d$*0jkafL^Ck>7(i%S9f-V-286a{f%@Ac2;yIhASQ;Hj0`>|5Zcxt z2;yHI2yOc#5E4E+0wLQP*s6D#FAJYGr;1AK)1EFnO{2~1-5DjVQ<%)+4S12qpsgUoY)ns>zyVh@N0wR11{f$g!~;|FQy_4q;j+2F^-Fay*c zfzY-UeoPG0LG3vRZCe0Um*L06V9LPYlLDb_6Z|0I5d)!Z1EA_0{FoR_K>K7Mw5

    nhthlybtBZJQ#2yMH?2NGUAJ`jI^XpsLJe8B$jsqtZA zIK;xB8v~UG(IEK%sJsqT97KcsuK^LaJ>m_qcLtQ60HJMrydmKYqCw%^0p){ePo73!!aSctXN|352$t;K>9&mqo`DGQOqZ2^rs# zf$}9Fv@M4x#Q!W1+IEWvBt8l}AmTX?+Sb4W5-(HSA^UWD+#&l^J0P@eiaQhdo(Bte zNIH~ohxi*rgZwQ5<%4LDzd76?{$_#Dwmfc33{ybk(h%AfbeJ6|f820|m;<6g=A3bb z=sV#GiSHFqc@Pbfp97VzfQo}?kbNZ(aoZ4ANcefULc-4lLfbmHLc-4mLfiguVPcpB z+7Ak$ZC|)R+ySEJu`>8Pf$~B0JXQwV4K9#Icyv^HiXG5DhZ#gEPduHxN4ZhBG9eo^WPjSkA(rd&HTEfro)XcaJk9z7{w`{58QD zvLCkxLfdvYL;TeOp=}$W>PkQ~1A|WigtpCr$ophKXxkWPCWZ-&3_cMM+BO6t?h^o^ zZGD^}>wP7hA?s;HAapDb)SVxkAntttrLQE?jJbwv@ z2F2q9C?7gKmuz69Wh6Tx%yL1_4$ET^*=?4JiMGBgDK1j!X>PtPHv* zp!5buCI)>L2Hg@zNIJHGsuOU8awh&dJz+IEf& zM1292cCdk%X9J;aIUuwT3xu|PU=5MKV$H-*2=c!*6T?zaI79hUp!^nVCWc;6y$qpk zE3BCqdO+nogtiTVn&V^5#GnBhSA_CyteF_DgT~pdApUz{1(CmF1+n*r6(l`wv4rp! zKxkVYOGx-_v4Hq{g9Q^qAE^9-(6$RKApV{Mp>12B>KY*OJ~a^9wg4jUlLMh`Su7y# zNHB-kr(+HYuODU*dV?86+yhEaF@^9aKxo?*Q%L%4fY7lqrjUFTVhY(W69A!YeM}+i zu{|KP?Ew>r`5Yz?^$aGE_27Su!L;oUV~F}M5Zd;GF+|-HW5{~&2N2r!4n*GP286b~ z0#$d!7_uJx0ED*P1CjUH0ikWTK-H}=hO7r)0ikV|K;(TEKxo??MobI=EDX99MiBco zjF=eOK=l-awpB2Kln*ix+ExOpj>8Bt4#@(cZ9#`wf&0~lVD+{)3?cD&#Sk(+djUe* z?lFYK;|>UIJHrq%zPiT%GX4poLHT zgX9IEd=L$i|DXqnrw4kFc)A0jZExs-!`Z4>k${sGY~pm7%{KSqy zk2ZwYfdq5jfZ-8i!xqF~|5DhYSg*GHSXJ|v}#VHWlc7iq}JbNIt zZ3#%6g+bRw85bdIG4ME;LD zM1BsGzM%$@&rySji>N`=)u=-FGEllf1yaAus6gaflp*pWP z9U1^SH|CEV_`Da}4{{K7Pvn>w_!t;`9zbZ@I}mxF8xY#ILJrd2ErHOsI&zTkpCSvf zpGB65VIK>F?iU$IyYzw#q`e5DLFw`glnGFUKq#e5lLfdA@Ffr_BVbJw}ssqs= zeJ)Twhz9AifT;H|fzY;Zq#^FVBMk}n8xY#|iZmpgEN z#Ip!g{DKHXe1Zr>JVFGbUIZ$BMHnK!KnT+B0@0v;*BmGxM1%TWQ-mP>ixMG7_=0Fq zI2AzoAQ}`-DMFC&O@Pq0GD1uYUqJCA2yw>+L5O}34bp!G$_LRP{d)u<^P4*$bnFH} zh`T^E$Xz8+a{{3HKs3l4A1EJ0gUqpk=+Ci$(6Jg&b3io692F=ZM1%YXI_v>7e+;5Q z@_z&%_JU}T{1hl3M1$lfK=~jVB;O$bNrxE%5dVQ_kh@Z#d=L$CSA+m0d_o|!?E-#C zI%wgCgpUj#n6^E@3kmN9yb$w1G|0R;P(FwTnKywKVqOn~w$+J4@BP&2yHuq2aFvHxq*_1B1^82yOd@8=~$7gtmPG5@%-6y~7PDKW;#1+bi7Qa>M5W zgtk2aRkw#5Qhw}!(6(D3@;)0Nv~34Br2o^v4JkJ&xFO|s2sb#KeLT1!^%#f-`PT)? z2hkw^+HgbqKQp)>>L+k9G4Qc6=q7MM%B2_xZ7ahCF@FLlq+HVBWMbe2-Mh^J>HkdO zfaJ3n4v0BA91wLZP(J8z0noYVH`pQaS0J?Q9CnDgQ`jNyE`W&pa($I8TT9<;vzN}E9G3oMX! zhXV^ly$yu6{lX0KZwxaed_FKSF+65r&^^NharY4>CWbmj2A=~E+I9~U#N9g}w57@|%&N7Brs-p>1P+ zGcweG`uh;tR^vA#11Bqkt_+ms_|3?`13DM^7bCbHIq(Z&-yR5UyWkhZ+zG!J!RLYX zKxo^JUyR`M{#qckZ4O8rw6E|N#QlGMLd?1F6XL!FQ2rbUZQJt`Vs67vMuuw8xFm$O zt@sHsw**4l7C_ad{A6UP0{II<+r~iTeIg*Vt-w!4@VM)lAB+r@pnF~+wC#Z(5b=^9 z5dSrNgVJ)a@rr0{_ed=8t$2S|Jhd|(8RpS*bwQTO0I zBWOM35)ci_e|MmK5Dm(ISKdSPZFtWJUKcgvJtKJE8;Ay}p91BBXps7j_l%(Rkv=UD z+P369BwQk(_JzD>1dqpfyk`WD$Jo4Q1eZrT?-{}410qm9%X^4_Uc6%jmqT~nF@nco z7QBP_E8`u+{TA;a@h<}93%p|l&$GXI3z1*&7UJ%Xw-9%OXpp;W-a_120ikVepz0N% z^p7_X{a4;V^nqxQz9VlK!Rx9HK3U~!cKMt=T>Bj~_+giMWq#qLqZL9MN67Lo-AmQ}kImEpyo*+NS|R+eSQw_zy&b{1*b{gJ_U{TpmOG>j0r+|2%@Y@697d zhH^#*pBE6?_Q@lN`yN1O+bvLaOCa(-3m~-Z9EiNn3<~qfkD^c z5yU@l9zxvt0z%uac?j`W#6yU>Jr5x6*zkanp$s%01fgwLJb<`k352$-cmOfa5DiLy zAMP@O&w*;W%LqQlwBarz_#D#`D8B$g+kUyj2tHRDM1#`t2PhvzgUl(o2}yrG7a;VV zGmvneat0F46Ckv$&lyNKHynh>TO5SQn?PvWHwPf{AND}ZvDpKWw}8;LTXr*o>%lot zx@9*bxE^eP(6%*D@d_wi0-cxb2%Wi?T(!g_mu2}h!;R;Ta%p- z_w3oh2tHSI%MM2HxuhE)v~3MkyadAcDS*(nHai%>^B6C-L+lIL4zXWjJ0v|xY=@*L z5eRK7upN?~cp$Vb$9711V%ZK!PoPDQ;B#5FLDJI)2yOdh8zXp~-vbD3duJQOoEs3@ zcEdJE`T)_O^sxrY2hpJPv0xh{J%DIXyv~90K{O~{Cv1bHkCbhU;ByOIwlOjkf!4`E zXj=oQxXw04hCQ1_Xvcx-LVA{zgr-*?FOiM3$`#a6oA&fLTK9= zTNuIT0#AX^wiBT0TDCBP&kt^Z(6%)Yd7lahZCkR15qvIW$QDR^ifmy7pHH)3Gb2MT z$b1NGJ7Y5=Lk=T@&lCu4+p(Dud=Fm>gtoQW$Ot}H(gH%qDr|(LGY}05Zy6{bM1#Ux zU?U`*foM=VM({l`J2o(a?^n0j zzzDvt+ytuLU;`sVCTM*xgtk@K0CArTgpPf)o{>S2jY0R!dPurFvK|soJJvIT_S^bw zfzY-a)H-cjP;Oso&uq5JJv(eABYC|w*|@v(IEe(tY>6+!N9Nt zM1$lLpnMPwk~dh-$RNqU;G+YfZ8g?2GJw|of@qL>6(}D>gVf7F%?HsSc?l>VM1$l- z)-y7&g4S)UX9S-=#si^k|EyyK--3#j&!S`mIS;q+4 zzpJ}v9V7Vu2oMd5uN_c6hz7;ihINqeTe6OkL7suZX90w^owE)SelsAn?G&iGj&+O- zatsVUEfCta0V3~H1EFnQ)-i(5n-N$CX@7ud(D?{FP(FyB%gSKOvW^jae)5mCj0_?S z3_f2VwC#ztjNtq2k3i_y9cvjGp0hIOZdl96Ak4tvvj#%j&RNR{zF)&-EyNxW4ce#b z0Of<|3`PdqmNksv^C%l2v~9r}M({q>6bRoZ0YclxK*dAWFoO312S8|B8wl-V0ikVm z)4w+E!pSBl!Lv&?3SP(7f6zNIv?pijg51H2(~tZEvh%1m8;rqCx553X~6`LFwVb zDoFd}3{?M#Rg4TtpmR(hwC$c%5Pxh~#mJBdYG*-c+ZC%I?py+)Z5Ke*Oz&ugwaGxgQ|3?Truk=86-cIEMo+plU)FzZ9|qZg3r-5Sq8CRWf`PCQ-IL6GRq+L zOF(E_k!6r{DX)zA4G%JHFzv#1fPfP0-<9amO|QB3QM8&&{9Z$P6o;c(V+A#uoPMk zErqm)d7yj{4Jy|_iycAr(3vHW_&u=%l5X}u`8y!A?UW^u`k-S8BZDt1gKonTMuyLz zeJ4vG^=ZlyMur&B_yL5r^?}OkK=o-rXj>7edX6QG4AG1XJ}eO0_QhgI_&kBou`3oc zg7@JpfzY;d7DM9EWHBRnAC3Wpw$*@&uUW(hp0Ay=h>;-@G~WoJZ6_>(=!<~xeL^6# z?TLkubZ}rHBpvL5(6$Q}LefFcLPmyQ&^~GiZQHPrks%y3jsl@=D;6>`gn{}i5ZX3j zA;i5g5ZX3mA;jJ{3n1=&0ikUlEP#kdEMR0f&&uEv0HJL?7BDh^)~7fufRtkjP+9;= zKbQ{@KLDk-%x7fqXJqi%0HJNy%x7c>0G;;)p>3DUXJiNhtp|qCwsYn)G6aIc1wz|S zna>EmH+2Gpwrzpv^J#$4wgpgoJfO73e2DuLpnL&{y*@k;+LmKJBZD6(J|VO%XcK`i zXnb-WBZDt!d=j)s5>zfjXxk6-7#X}l`(Gfm?TdMg3|@>3K2IRD?Spv`_uYZewpZps z{J&)$BZDKz-w@h%3RJvj9>je$P<{xM_JN8!K=~r`7#Tbn8GHmFv@H+Bd>;-7ZObx` zk--DB9~na1K9~!!_s(2K26sjVpBoU`_RL&}eMg}3E1-1ETt)^r(7ZN;wk?^<$lwYp z=OMIh&Rj+Y7ts1m2yL4(7vj$Z2yJTuHOF8sBZCvDeFvd!C7|LWb0Pj0fY7!ob0F>$ zn8V26z{udk1EFn0W`o-`OF%TJJ!3N)qE2BpBZEEYd^8AcD*;spqCw@sk6DoMu_v=2 z{kSVo`UsTX0;QKg=_ye9#!N7eyhP0o3q1Ep&SZJW~u8L!}Jfs7*@X@=Af2OzX< zMKdHGGnydsDoqf11qf~Xq!A*&q!A*Y&Ovs2El(N59Un>{@@q;U@+%;;ZB7Y9UI!}wq8K9o1VY;`DTc^r z6hri@K*W6%Ahhk1B8dEr0*F6P6hQpBqyXYi5DoI@0w^CugZw$A0OHRH5ZYFy0OC)M z0*L)A5ZX2)58}@y*${u4WJ28WCIh1G1%$R;kO6VWgmj3!PdY^2147&Kq(kJ-q(S66 z(jf9J5Zcxy4Ip!XW-s34{0()R+M8iwuMK z=T9ia-yj;~&kvyx@i!3KwjmVa&y-Mz`3Vr(_DnFupFDvOf6noPxFf_5qAmbJ+j96p z-1)-?BEQ84BEJDb+m`r1bo8gGbvfj30I4n*8X147%r@q)q{_L@a_%p*A;!h9_@@EQ^528W-jIf6IGXz50zOaJ$^Nbb5{1Xt` z*2EIx&n;#UfA*L_-05KgQO98dv0uO#B7VjQB0j+gA|7G{5f^}pUoeD-&oG3DhZsWC zi$KL~^dbI`(TBJnM1$Nf0p){eko$S`A@1jZ(6)2*AntF_gP8Y42jcDnI$*wSh8D#A z1{x51->8Gdeb%T$+_ORrBA%iK5!X1b~Lfly+3N=p@;!Yh1-!?@E;?4v75PK{5A?i%{A@(}(LB#*?Lc|a7Ld08m zA>s~DaR#XP3@(T}E4U!;1koUOmO%L+8syFlE{Ho*AhfLs7sQLH>Ba0r4k@2Fc%n@2IQAnkAu2yN@a z0cqz-a6sCrA`m+E2Ro#nvWA_JVJc|f7=*T6!p;c3zh?o2ww=Sy$S{S0!Dj}9wylBc zt6*njn9RW7Qv#uFbJ)S-Fg_U&+BSk6VqXY^j#Xf11m9NzqJxizK!KVR2+t#o$G8lu}_Ym4Pf|U_`&r$#@Blw;r z9|&!0!pg{C1Ui2NLfh)FGBOx~=D{GeEellN9~Owd9}wF10ShC80cd^$LfhV8VPwz; z^;aOY?G_e@eQO}V+d{A!NSO(3+k6ZXxjv+z6gkVpAZObYs13G zpu@=EV*#OUO;{Kiv_bBM(6&5KeJl|5J`51r_60K|gBEBU0z%t9U}j{{1i2eR+wNh8 zxN{3L#D5zgwCxOLM$q{wK2spH?F42<26d3TA+&7W6gtqlzVq{QYWbpBT(6%m2j12N1 zcSC4f8K^!HhqG&u3%(j zkO7^q4xw!qFfuYogWL_FZ7ZPq3Lxrzav-#A2qPnd6zDu+2yN@b$jBfGayNvw)qv_# zfT;J8fzY-rjEoEtpm84vZTp9TkwF}EUIv7=y}|%-=NSfwJ5NAp+YJni3}T@10SIlo zf`O4i6y$CQZQBCXR|8S+QvsoE6Brm7L>L)-Vj#3_1Op?3FzEbq2yJTs)u#bb@1p{t zZFv|N8H7Ol{UEe03j-sAAjsVi+V;VJ25`Q;@t*;lZ?8aT+dcmo7z9B3lp(b3mj4V4 z{Gf3(2yNQ~)z<=1@6!OGZ8QEeFz|u)i$iGJg#Qenrh!ikgtoPT>NA0;_c4Ibwi5pt z76m4V_@I}xf?>; z&VcHh08#JL1EFn8{xL9cfX3M%v~A8m1_pM}I2(kvb%E-$fvESffY7!I{}>q9K;vN$ z+E(Hp0|P6_-4NRL%U_5)-~5HR^96*qz3`U-RAl&^fzY-m{xUEygXWDOwCw_@z8Mhp zK2spHZOvZ>1}0EB3!!aG{xUEyg4_+EZ3CeCJRs_QTp+Zq&R+%w22eQ*p>0+EGBEsS zVDM3Z(6)d6K-~G|55%1xAhhj`KMV~2K=l!Xw!QF&f#EM`e>{Y?T>;g%0HWS!4urOC z0nwoI7a+84%^wEPJx)Fq5ZX2bs?P@`54tB1LfabrVPN+*|%;T`DyUI=Y#^NWGuEy&#v+ExUr zj|ZaOhXX>}e)!42@P>iG=M99meesil;WfzJ5Zd<0Pl!AB{Dio32ZXj=@RNbz6$69M z90+YY<0k{dOOU%Ev~2-YUj{_IPYQ&#_4&yFn*aClfY7!sKN%RFgWL_FZDpYPL?G&Y z1R%8Sj~@&S&p`9q5Zd;`4+e&(Aa_G(+Y>(^?mX}V;?6w~+IGng22gw3X90w^o%4f% z;W4N^2%&8&p!y0R>V0w`v~9=_28KtVb}59m_4&cT@DOy)1%$R$f$EcisP~b8(6*q& z`GA4J=g)Tr(E1+RAKw`m?t|P7p>3~xhq&|1cZfSrKxo?y-x(P0f#%~OwC#%T3=DS} z7<`sMXxj#;z6ywXpArad8}prk;SK|XPXvUv4f)Q%a2w=q2yLqa)u#ec@1p>rZ8^R( zFx+Bb@L_?_wxCRO6Xfo13=B6J7;Nu+gShj`H;6kgKxo??-xwHfFfjORfzY-azA-Rd z2e}(U+jcDgJ{^d99}Ng?EAWkh z;R@)y4G3+^@r{AuGRWN!+V;U$28LOz3^{iobnK0<5O-hr3UT)t2yMIND+9wN1_qxE z5ZZRlR|bZQpnd~{wrzpxtAVKZsesV7311mN>#=-dAhd17R|bajp!+o;w5Gobn=K-By6Kxo^N&kPJlK>Ok$v~A9328P2RcSC4f52!u|h-TevbZU}9A;u8aCJ(1552yJ@+ zqz>e62yHt9L^Ct!PJpQQ>4DI;C7&1=_JQ0Dp>1;xHA++tE4-j{L`2ca}2MBF@;{yZ37Et{Qp=~dGU|`q`YBxY= z+Z9lK3n1!!=0IrMmJbXJn?Ut1gto2uz`(E(|YgWL_FZDXMNLLlmW0wA=l#d`*ZRSXP1CJ@@z;5`Gw zN|3uDv@OSb28Nle3^^2EKF)%Cxxf?>;w!C9tSPF7Cgtm==>I;FW_X&W|wifRg7?yzC z4WVrf-Z3yN2DuwT+wws5u|U-OfEpd(_Rd=dhDD%u1BAAH@RosLAt<~dwC#?!5O;2P z3-R9?2yHv%Edyv=#b*M9w(WV#z%U==ZU}9g0@W7-QSTE0p=}-BGBC^ooqGeJZ7tq1 zFw6zH8$#O(K=pAz)cdeNXxle$7#QX-F!;QH(6&$BFfhyp?H_{BwtL<%FidA<$k_p* zW4FA4xO>eTh`U!nXxj;I7#L=O+GP;hw&M*0!%WaRJ_v1_@P>h51}j5O41|u2fSMBk z(eL8}p=~9g;sOx94-bU4ZFtQ9UJqaMngP7NxZ*Vf!wk@P6@<1efXe4U*5x$=c-^bWYXCz-U+W5 zz~gH@5Zbom6$5xYtp!5cW4rzJpW+lW^T;Pw3>5Zcz`6$3*R1H%#!4H}8lj+jgh4b&-=CKd zcmH_F03Kia0-Sr~kF zK>1*rg~4{gO9t>b9Eb+_YXX!HqCxzMmki)>HwmaXhz5!CK=~jV++ldeE+utgtnD<&H%puTLePe{&~j0&;=ULgwVDho-r_Vg4)>-+IGh? z2Jram76@&-;28sW|HK>!Z9Cx^BpvlY=-7m3&~*5W0X*Iq0HJMtocnS%R7f&JK@dQHKo_Wf^(89pra{@x!9(l^Z&ML;SY_qTXi-gtqN@%)n3v zDz_oDZOdZ@hEkBbA+&7*R9^%{y-x^)wzYZ8z)%9}r$T63lgA7U#i0H*gtp~@>SKYZ z_W^a@!1c`|28JR~eFLFwA3S1UC;Wo`aH-xqof$HOdsQ2N3(6%2Q zGBD(T@(+ZzeesZiAsggw2yJ`dA*8<91EFJgJcPRYA=KRv+IGrA28JvK2A>HK+P3E* z14Aar-4NO~+*mBv_H_t0Ycl_JYZl*1cf(*wiSWuhvk=<$ z%RL5$NYH+H2yJ`j9>kqT?m^sn07BcYxW~W{0U8&8(6$TiF))OK+zp{^YoPi{AnJVz zAhd17JqCs_P`?#I+XmcYUwY?Txz-cV4&)apxHbZM)?z149s~-wL5^*W6`b2n6-FA+&AFT}b<=0Yb;t zK+P$E==Ujr(6$nH89?jueMBI%Ezey@{lfvFZJ*qM@E<^E+aq@v!296VK0}aN2)}gGq$-v+X3MU9{D{~Vf z&vBE1!4))q0HJN4fCgbe?N$hFTX6%TF69P9T>^x*^|%2E9~TI1>i|(_YjcBv!5NgF zAhfLxNSuMeM*~9JUbqf1?+k>tO@PooF%a68=Q^Zb|8tFj!3>lhAhhk5Ymj>V1BA8} zxW>TX4XVc>v@Odu2JrsyJ69q4FI;6{um#nF5Zd;{Rfzs05Zd+tRNa=V44`|ad^SL6 z+cgk*pA`_=b_rD7jH?U`)}VX~p=~EXI0vC`oP*e7a}J`<0z%s| zoP(Hu;w%G0FDrv?$ytbe0fe@VISX;W#90Q03RVW)J7*x_f8`7V=)Ovy3lQ4&%o#{L zoq*7`6=xvklt5_PJEtN18xY#I5l3J7hx1gdVvNl1R10-MnL3!LLjs)%Si_CzMeHFAmKRW1Ovkd76#o8C|}|PME=Ba2%P|> zTaH20XB>m54}tPG9EFHC9EFJIK>0op+E(N!Bwf5Y0tvqdM;I6^LG2j`ZF}PgB>b*G zXxlG`A?AI6(6%*)A@O4arBx0?%#%0_NoQLQLDX-6(6%cMLikG{v~9#eNPL0@F)cvj z?gtncEEpJUe;k0M$1?{Y>0$vy+-DAiw(U6pvDW}fOB{ftdw~NG`&kY^%w4b_qTgdb z#9kK&ZTny!M1K#I*4YP<*MQKr5qlxw;jtHzZe1X>t;1eOc-TN_+a-G#7&@34bTjrq z^rt{*TNbEz$8Lyt3xu|nfY3f75Zd<6E{OYf?1I?0VHX2?B9?y-RZe7=_gRQ%6+ z2JrbNAR4sJ>j#t%qL~>OY+tNrU;y8%1fgT^tOvK}mw;%{_{W0v5c6xG`am?uoC+u( zM1#!9fauRjfzYubP;)>u$eaKuA4G%3QGC`jfY0gHftmxNLFQ^e`5+o(uFQG{@cAne z5Zd;{I*5Bx)-iz3-|>L*AFKh3+s3SdgxitjknpKl4i@*ZSPlsvhh-4)A4?(PTb4q^ zU6w+^O$I9dV+kbOKs3l*U!Z&t4RY6$C6I7?0HI@VEP;d@hz9w0&Ju|E6;OR38e~oh zln zZOLLtcttFRxa-40Fm1bHAp^r-(7Ct^85p*K&P|^W3BN6KAmNlV2dvIVV-6&o3}!>b zU(AAtFPQ}qSC|C}zaKLp;#X!u!Vg4)+_z;WBz!BzqV7a5nD280 zLfbao z&^^!&3AY*TV0oVyC~eXX@h^x5xzhm32hkvRDzroVD+8fpzqCQ^YlE0`147##X@j^Q zM1#WN0F)1+LH_AzgV>({QSYMyr9p$Y;P`HXgvXy&hJ#*2HEe>!oYADbRT95B)@)WW?;|eH?{fk|+a3XlGc)M!Xl7v01Ff%s(6$?z85ndy>nk9% zZBH`;!xd0JrWw+Hl4*wc8$^TrEzk@J|2<6*aS#pi|BfcGxb2iCNVrXCVgR52l>_Bx zKxkW+CI*HFpz~duAmzZBMyUEmNdD(&gw(Gu8X)F_Xpp^6pnMPwvhPL%*gl^t5ZX4Q z0UF*75c2{cw5?1714ArmzM~#u-<*1gd_q0Mz8iIrdTB=;#6A!WvTqBN528W#t*C?8 zw**4lTGT=8Q>lZPrvRaC-_$ZNTw`I--B1g$FQ*nFZ%_-dZ$%9Q!+ub|qXuGMM-9Z> z7APM?gY2t-ikCoWTaFrteP5~}=6!(BwtK1>7<54U;Hx3!NkTQmTo4WNM+}q?qCw^c zR733ZfzY-x)ev)8Am;gi2LD0*<~3Ci^LnZv=7DICc^yzbhz6NgQw1@v0z%t*R6)!$ zsDijt2SVF&R6)||pGpSsxg|d!wC$HlNP7MNp>5w(GJwxJ+))Y9zo8P6UqCb{zpR1s zK{P18tf*vQ2w`Q=odZ?xQVHod$UylL5Zd-n1p~tl(D{!Q5OYsJXxjr75c5Ga$oxG} zK8OaHKc|8Ld|qP&M7>W4gtqm8ssqs=eI8Ighz9A?fa>F^fXuUUR4{5G+ICJEBtB+9XxoM|NO_P^ z2FcGMWeg07%nZ5)Wf1r3KxkV5kbY(cT^0}x8qbB$wtq??=KX-sws%S)=3Oa;n75-8 zV$POQ28Lv22HhD@{uBspn^FpKX9S1_jW0uJ+W?4pK0XlI)&y#<4AfkXQiwZmlt9eC zQUbB}ObNu^4N&nlB@lZjK>0lo+P0zu(jSv3fyDotVu(BL6f-brgVswxXxl5r5dU3( z(6%1Mko0$;2tv;(VgR4lm{Q2V0J`7Rr4W*zKr|>nIY9X!8kC<*3L*K)07Bbp6hhpu z0-1OdAmhj^1q=)ySr~Nh&AqCw{Qw%o(~|j?VUV`e~;ub zFa(0`W6Fbs#|8*(J0TC^{vHTz8<7VocSRubJ^~Qh_DU|K{JoO{k)M$RF=q;dwvEVv z$Un%2gkM261Na<5jU-4rcS#h4wuyr1{}Bn%{{=$Z?udlwZwZB{vj~9bzvBbp-|&Xe zBAyWa7d#;P&p>F~2_6vrAs!HU0f@K{4}`Y8;0}?$;s%kQ;0Dp(1EFmL+#vEIQ27h4 z5cx9@+IE5~L_WtJ;y(vlh20qLDYMgL*!Y^A@U3m+V+SUME;B^ zM83lmBHsd`Z9PmO@)t}X_DwK=*w>*Cp)+(K`c!lv`V=6v?GtT?z7^UK`4nx4d;)~F zRe{P&XhGz!XhP&KKxo@3nh^aFnh<#rh`5gcgton+0g=y8fw=33BE&sM&|gyk=(5Es$YgP-S57$$`+eDKent^$bfuG$`Lh$S{D;Nm~MUBqCx63pnMPw%5Mr#b3rsnUIxks(IEL3(h&DNkOr?e@wo$`ZRbcs>Yo|XkouCwi(h43`MLAx+&6-{2T$ILFF`rwhfSmPEmw;%H`X5j}hz645>N?~fz{ z_#DG0k`ViDNJ8rwNk~021u8xPLfiI8GBAWPGw3!*g2(@tfM}4vYM^`&4f0opBm={1 zP`FAmFrHNI>lUAi)4WXYLJz zwtXQ1vG)mtwtWCqcLhX)`Y90F_6$Vc=LCedJpvMEX3*Uu!N4E`TBi)5ZMQ(=eKtU7 zTMG#W@VP}M5Zcy20+J4NBp4W^LGz3d+Ezh=0el`Niv%QoK!FJA-@Flr#Lo?JNIPMT zI7EJlI0N{+!YSgAc70Z_h$IK*BPaRyM5@G*eUwi@CPdlkeX`CbM> z+e(NtfX_ALfa?Dv2CmigI5Dk)FBE|rU3ZDfK z+IEf@c>VDb5Dij41Ih={AoUZV=7VUEd=HclqCxTn@Kxo?2u0HJLg zL?Q7|1EFo-h(Of65P_(B0-r{L3K>ZD$HW011GJpzTpEnTN_Jts1ediNFu>XA? zKxo@L5OLcJf(#5y3=B&^G$_5Df$~8#D8220@>V z3WT z#B&D=xF6)x0-28 z2HOkF5c|(SXxlvydI^XInY#nZ2hkvNH!y?!y#z}8EMaC~*u~7CI|ri9X9k3}od8t_ zrG0vsA^qYGi2M=|4Klw4$_LRP^K+nl5Dk*gfbu~!NIr!b;x89wh`&HIDEu6td=L%t zmjFbc4-bU4{lf(I=MoSNGWQ3R528Wleqe(53rhPuVS@PU4n&>L4G3*}0jds4`Sp|npAln%`L zh0;D5P(GBlO@Z2z0QEnJ2ALBB<%4LDIWAB>hz7|!K=~jVBrgIDFBXXXJ`51r_74L% zyq17ykiH*KK8ObC`@jGRA1Do4mJQB#cOdF~Za`?;3s7}X+UE=dBz#Ul82EGUe28R1g4156$3=H>}82CIG7#Qv{G4MGsFfiO3wIGBNOh^7BI`20lZPLHQIUzW~ag0i{9t732?4{sg%nln+641rx;m1yCB4A3^>}fbt`t zbO4kF>e4xh6z~{lpz@W;^zz0g_D$ERg z8jK7KPna3_6c`y89y2rWaWFD4B(pN`fzo>tD+AvP1_p+s%nW=F7#JANF*ERi((ff^ z20l=_z0AzO2TG^MK<;5+V7SQ4z_){ef#EF3Jq!#CwJZ#LpmbNv!oW9yfq|ing@Lbw zfq|ifg@Lbufq|ivg@Lbvfq|ipg@Lbtfq|it1(FWSSs3^d7#J9;SRm=Kf(4TPp0GgD z-*Xm7`g_R&Nq?_cAnETZ3j;X)yvNIiFJi*A$bc68@BRf+A zQwtM2(*dRw{(GyP!t!^F-sg?R=uJJSm0HO%ZxH<<4*vol>_zQWAT^n~RF z3p-N-YYQto(+bu#tn5rjSWmFBGu>dl!^+Oo!#079o#_DE5jJ+F7i@3X*qK_`JJ{Ko zX0Xp;XJ;ACg|!_mOW&a{GS z4HrAp9Igdi>`Z6)F7UB49pF2{$HcTia)~4p(;dkNlI%=pq%KIYGc_o*D6liVPQR}X!p`(V`HwO?(;MXv%Ir)J zl%FUwGTl*rqs-29M)`s=JJSV~D=I9^FI3*Bd{AL$TA{i|m7QsV>J(KbrZ;LI)YzFi z)O*yKn3ia)&|qgep>aloiRp;u2~BpUCz>xbnV9})HE6Rl&Cy<<&CWDKXO0d#(*&I< zI!sJGx)XHSnHqFkbeWib=={-PXIh}UM3`ZSgK3Fg@ zHCVP-vNO%FoMXw(bine6B@@#hy9RqErU^k)f|!^t1YZeeVtNqvB#en^LBx^>CZ?9` zj%+5ThP;+MCZ;c?KT4UH&U7gi>i&iBwBat}mb;AXOfT*-z5&q>?lL|B(JSsTuDQp^#B}8z z`X2989VMXGBMq_&v@rPC~ZGvYuK@ zXS(p5@d}8(@`~}sD@JyvGp`sgfar!dj4f{%*_nR4X8iM-k%?)|8^#SF{(`rROWrcF zGtGF*IOi?Mp7)G*-h=GkBnzNg7kl8{PUTSo$148#xI{i=6qq? z@P(0yspBhS&sRn!riO2fE#DZKnC^UId;p?belm9aWMpF6@|SVPUq&XTCyh)m8kyLc zwzM`W^@Gpzy9S3Wb{0MTbYGhG1D z9bcJxzA~{hHGE}i0nux|GHn3SOTIF#_{zk@H02x9jBlXu_|DYvor#I*$q%L%KbY8= zj{IUe@r#L_Y0odF1HVB2`NOp44=DWpF`f9w#KbhGk$FKQGZWLFM&^blW+tX3&CDyB znVFb2v@&mLWoBaf(9Zm&otd5KPABt&PG)wdE1k?YK=hqS%nv4k_>-7#fao8SnE!z2 z50jX`faoccnP*I9W@qY|%sc@^ZchtC-oDeyn8v1LDtF#k>H-pR$U128iCVig^!+-mr>!3yA))iun(S z{;-Pq3y7Ywnt8@*P&ln-o&cgZtY+Q>Q_Cjij!mHO*v!0UGcyxY!xrY2EzC?z9b1`uwlcFb&DqMlU@J2d z)0VBwJ3#y+TbWOQ=pS2||A53hb};ws0J(oB^Mswu>`V`KGC$b~3cp>#!?vX6PjK2W^u zW&Q)=f7r|X1w=pD$NT~$eqtZ<84!J7AM+6qy<f9(6cF8Un7Ic`A7Sn}0&?GB<_{qLlf%p}K=hp>%nv}~2aYfw z0ns~-Fz*4;YmPE+I0|y#QRXQiy5lHw4~T9!#@uoY=Q#5N5Pju1^9>Mv;so=V z6Ci(_VBP?tmz-c;0ix%eWL|I*6yGPATR`-W6U=`=;vY^je*y8YoMgTMqR*UUz5t?+ zoMJw43Y18&`omdfcBU<7 znRkHbIcJ#{oMmQV?m5dm;VknMkkF3H%zG{~von3U%=`mH&$z-o2h{AHaD{mah<=9=W@kEcgZTo8zvCwJo|~Xhy~(@=MEBfeo&cg- zZZda(>08Vlw?LtAllcvZ|KKL`6A*pl7V{mD_?}zL2SD_eTg*E^^qSku8*YPA*=^=2 zAiCo=a}S7axWn86YS%xx&HMtyzjK@U0f@eEhxrOfe9Il?9Uywm9p()nddXep6?Z|Q zewVoiL^s@JZn?|M!PIh(x#J!v$nG-#0EyqY%X|k!U%1PB1x(*#z5{=Ea-Vs{eUN$gnR`HV!+qu!5dGsm^B)j>=RWfT5Pju7^9>Mv;sNuS2cT5@fO!Lm zUh;r>1&E&Wka@vFP^x{%+ybJ1JYfC<694d!`3s1Dx<}V=rizm!)o-lJTeR#_J1tk99Df1H$edH|nCF1#p6ARHo`cML#{31ufANg@4Tyg5ocRez z{K#|W6CirebLImedczCmEiahanWns8o&lnJUNBDp(Je2TJ6?j)%?su?ApV0F%uhh{ zm6yynK;k=IGVcM=8(uPR0nsa7F|T(h6_EIrx6C_0^qRNK8$k4ecg#!PfwJ5?<_-}3=Ph#si2m}9 z`3H!;@s9Zph`#WS`3i_W@t*n2dr-Q0&%6OdFL}?r0z}XFz&z&zs1@>_xdB9fdC&X< zB>v_D^9K) z^O5-jh<@^k`2|S)#3$x6Ao{>3<|80_$7kj}pF!#7GxGuvJ>@g=3=rM%g}LVosP_2G z`~k#&@|pPsh`#fM`2k4$z!&BtAbQ6a<~<;K!&l}lUqSKwm3an;?)l0*0Yo=^V{Z8d zsy)6kzX0*?d}V$BqOW{oz5x>7@r`*8h~Dsxc?*bM@|}6bcThh3&fEi{8@@BQfao9J zng4+3JKvcffaojVnQwsT6F->G`~ZdL59SRZddUyw6(D-fPv!+bLHY0}a|?+6@q_sf zNc_W3<}V=rm7mNvK=hfP%ojlPkzdRweu2ulU(9Pj^nzc^OF;CL-^??9gYw}o=070* zhhNNJK=g~>%x^&AXMQtZ0MSQ&GoJv_JN_{5`2z~iKg7@t=7Qh~Ds@c?*bM(!jE!frXu^qk*LdL^m|Bw1DUz z4J>~^^qmHl2O#=N1IrB%eWH=&Od|_B)0#$>4Ip|+Bg+a9J*SCfK@(`KrHQ2lME_`H z`2!Mv)5P)t#J|wQas@=6Xks}7q7O8)9BF1@XIj$CvI0cUX=Ygfq9?SlOle_ZXZq62 z@&m+w)6DV#L_cX^c>xkX(ZX^DL?38jIRc`0w6g4JWnpKU)5@{{L{DjDnE|4E+E^yE zv9L3JXl3~V;=gERc>|*Fw6Qz@i63ZVIRc`0w6W{~(Hq)XwzRXbGfin{nE|4E+F2%m z=!OoKmJSwnrYG$zFF^b|?JN&K^py^l8zAu=9V~l5^o9HE zx}}q)14RGmWcdT4?{u;}0MS=ES#E&nGhHkfx>(qmHgvIU0nsbESk{2(hHjRYZWeZ? zA6+beK>R)3EC)dRE!`|TK=hSfmK(hw`CgVkAo@cu%NG#+rH|!D9}5%Hi$0b&eJm`@ zSNd3P^s(IOV_|1n(a*A`pM{-iK|jk95Iv)xWllc}3-go-EHfss%$dN#&U9e{%M}oP zVgk#V2`o%ZQzo*^n8?D!v|u935)i#+BFhF4y<;NF9uR$GBFhO7ePJTY6%hSmBFh^P z{bM4_9}wL!iKS-}3lr0fNi1_f^omI=Ye4jlNi2In^p`0tKc=uSG2K|ra%VLQ6VryH zEL)C()Zb&7bB~3I>BLu-GhbPln4WxNdGU>fiRsL5mJ7dGn3yK~WtsAqg^B6PKb9N+ zSeTd^npj(!SeclXOkiCxft88rz(m#~6Iq#CJT357Swhm^RF0-7=Gv ziRr=|)+=*ZnV24|VtulTm5J%kYSxA|tV~Q#Hn6_f0MfUKb~O@f>8&OV%|nS(%uwykWiZ2IP)ktPQ_G_Wfa< z^9MvXvdw8^V`93~#P*#TUd$N{|k?G1>wg+q3m_YQ6wQMZRN7k~PSj%>1EgL)2 zopo#v*0HfOU0KI=14RE=$My$Ae^|%%1w^k|&$eMb8#~jI^=vCZ^ojLsXF&9U^=wB# z^oR9qUqJMW^=xlI^o$K`b2hNCGfmjQHU&iQ*~E5W6B|3zmQ8FsK=hn#Yzwxru`~7T zV4JW5q;416lwEA>Olx+rZ2-|fcCq~d(I0lPeF4!gcCozy(GPa9Jps`-cC+2t4br!V zZOR@tcBYO!Y&{^lVGmmih~BW5ZOdMe`TN)=>;sMJ?qll!(SP=`HGt?Zd)a<~}7iaqVMcwdjO&v_OrF@XJcpDu%B%Uh+eUuZ4HQCu%B%Sh@P>ZZ4QW@u%B%T zh<_?8za+-6Kp$9g4}Xk63-goXY%h+p zy*bXt#ME<&ZNe!wcBVO}*cO~(V_`mVn(fSKwhO1(n3yJlVT1w{9pXPa;yWb1jh4iLTJ zJlhr!z2ZFE8Zdp4ZOuhCcBTav*_MFlGZ)z|faoI^*-n7yH<#ExTw()tO4xo}W@Bgi zaE0y570?L#6}C4Zdcsw`ZU2vwZ;3Gj6cW0f|qz!8Qd%Ke)m61VmrB!FB~iH{4`vxd|HI zzr}Xs7ASSyX4`NZl<;q}ow&_*<~AsS++mw=2jtY-Y(GH!mb+{ncR@jShphobFSyIL z1Vqoc%Qgo@_uONfaF30NX~sRaIrl(D-ecPUqL-lya9>7Wn1tT6bf(IHh|~{Z`q!J=o@d@?tthi z@7QL%1BLQCwh17*;T>DcJ2ob!4{zDNfaE`XVEgg`l>9%kZTSci|HSs?6Da$9Ve9$A z#?I96ovr0N8xzxxA8dPmfZW@}zN3kqiD|-2_9-*jnV3H8WdE|0or&qsZuW*f?CeZE zd)Oy{=r4QNe}L#Wd)PmK=$^go6ZW#RGqvnx?*P$9_OhP<(R=o?9{|xC_Ofr;%g)5K zU@!X;5WV35`<4Uj>`ZG8vTr!Z&d#*tAp44g>`Y8A4zs^G%+AiV;3)f&qo8S`qwI4) z^oyhHZ$R{eqwG(PvNJI?9A|Gi&d$VioW9%GE2ad5HImXV;wC4)@fh+9nOk1w7 z@3;aIzsY{&COZ?;l>6*6?z6Kq-MP>H07UP2!@lPYJ3G^cH|$$L^p!X4H$e26H|!Tc z^qV*AA3*ezH|#Iouro28_{e_dBRf0OgHP;FKC!bi-T1_Q2Soq*#NP0kot^2+C-xs8 ze$Q9-3130s@RhyeD?1a@p0Df&K>P>a*q?j@>HEfh=Nmf{)0toF7k;s`GaYH>IMK|( z&UB!a<47w9JJXI$hn3$d{;CQisgNfBk0+KN~>$w{pDL%E836WgEwi zZ5-@OH@0)!+0MbvbYVNkmF*l%Oh`Z_5ax{SH{TvOT>B2AjIezTtU}x$$#L;sIWd9+K77#t<2*->g9PCUz zM>r-N;b3CgafD+Ji0(PcG2ti&JJXcw95b$i!YNf6sM}10ep2+Z=0d zgWPwU?dP zc+PPIMDKXcu?Ivyc+T+zMBjMMaR)^IdCt-B0uyapw`4;&vpfP(%5N5e-@()h@+;3Ee+)0&SQ8$kSq?;I`PIT)F~eB)^N z4oXVjIDUNNU}9?d!O`)9gNbR+4~_#MddDx0J-}xRcmSd&v~o^q?bWMbOV!MOu8b-bj5b43Ry2h*E&&JXRJ984cNIKOmoGBJJWkybi;DamgSu6Of!~q&H>RAmUB)4 z(L0uN?g7yomUC_a(LF0TC#(R4^9s%m5PfDP=Y^G=>`X^ia-IOuFIIBC0nrauay|jk z4XZd?R&j!+UpW7O_zPBXE&=gptm2#lqED>hJhO(Ao$0_D&LbfD$r{cVAo|W4&Icg+ z&l=8#wV-fV!}$ZmpR$&728iFYmU9A#UbB{S1BhO-mU9J&KCzbb42V9kmh%XRez2DF z35dS2mh;Y9P<*cA>{-Xj&eX7;vt>OeJJXrKy<@K&X$cJ_io_)vjG&| z8#%Xt_!l;EUIEc3HgcW;(Qh_#egM%=HgdiI(G8n9TQ-CAZQ}g12^24zIhSk(rJK#1 zGeF`~ws6ka!pY9mvxRd4h~Bb=a|eiCvxRd5h`z9e^9qPQv4!&th<>w$^8<)}vW4@- z7EUInIa@gwYz3v8t(*ry^p>rhJ3#b}t(jm<5P!mM&MCV=;l7)53y6PYFXxH9Ab;=W zJOH8}?B#p{qHpZwyaS?t?B)CeqCf2A`~sq9?BkrXkCUBg!amL^Ao|Mz&L0Oj*_qxP z;QRohdk%6=I0$n0LCy{kJ>v-HoFgFhM>wY(;bdZZaFp}OQBHQI4JSCaoB)N(NzR5- zoJ>qVPILY_4a)y#ID5`;GBK?p;&T&pT2g?8FICp^PHRm`tfanG1IG2Fr&z$4D0OCJ6 z$N2(8-#N$m07Sny&-vy&Clk|*3!HNY=l0;QMRoC|J) z%AY%&U+!=+F&(+XdEyQy2h)Z-oLlaI%7uHJYwmHfGtIfrx!^u02h)>>oG%`7GBKTb z!g=8d$owaqbDn_Y-*PT^%gN3(=M4~j<}K$15dGmT z=NAzD;w|SJ5IyG|=Yn^f>`Xh}aqa=pXWnsM0MTFGasB|&KR$B)`3NdcKXQKf$jQj` z;3MaokDz?=nRCKtkUKwft^v_|K64%b(N8{ez5vlPzHrX@0t&w`oI61Dg)f{}K=hk0 zoF71R!&lChub_DR%DDwZulUNj21LL3%J~LFKlsY|1VnH7#<}AgClk|>Z=5T>f#UZE zXU`8%e1GTs^BpAqgL4Ilzvd_BhM%Bx@{@B4h<@>t^9_h@_{G`s3zYAFa{dAFr~Kxe z@tc#K>BMi&Ga&lGZ_Xzm`p0k1KOlO`AI=?rK=Jj5a|4K;^OtkMUru(W4}Uqofan*0 zIp2WjJAXMJ{N-d~I`NnD42a+HkF)0=D1ZLr-1Coi~#`WV`a%}<87p8Ju0nrntb4{7f#l+MzlWW3EE+(cK zv$*EW;$ml7F^g*rh<-AQ>jj9uGmGm1h@LZ>Yr$+TcBUz_xn_Xqj@ev2v$>d8o9hBd{L37!A9J{vm{!c?S~Hi6iRr*xt|K7&#$2vDAo{~xt}h_EV;)z}Jdk_m zaUB5B7v^zY0ntz9alHW1Kjv}$0nt74xhBl#VrSYipKAw*elnly1&IDKpX&#RZdt(9 zu>j<*1za;g^pXW!D?s#&g^<)tj6Vr)BTxUS^nZ;Ze7IU#P z-C4}_07S1?!nI}z7dz8}C0t8D^pquBGnQ~MF|{n=>HzTp=r=34K7i;aE4W^O=$4gS9Vaj`QU*~E2X6BiTHjxAh!wt(ETh3f{0-msNx%T`eO*~+yBL?7A8bpk}s*v2(y z8z>&OaZLfyKeloG0nsbAbFJA9vTq01fgPZD+0AukH;CTDb!HDJo$uv3vKJJu`?zN8 z1Lc?fTr2j2;%h(G0}y>>Ki3TqJ?8}1f)k*Hh$px%fas2sTsE#sHj#HrUJjJyE zL|-|@bpu47ImLAWM1MHN^#w$~IK}k_L{B))HRUuY|DNXR0nramb3Fmk6V7l=IRo1& zlwId)xeoIBb*={>`pk8%3n2QNBxmcK&+~8VqgKNzVE_S9HH@NPA=nFTvu7Kz_ zH@H54=nXfyw%i28)?Ka}ce&V^{@mqixCe6eJ+2iXdcl3JCHFzG^nh#115hkH;5zew zi=FAs1FjDs{)$IjYaVeiF|B#bwc#-r6Vsi?Tn|9>hsRuB9)n`(3D=A#TTvxtu&vgexfB4V! zs{?NzG&h)2`yP=<(o#{$H z_YDwzrl0!)h(6HIeWah8iD^SW_ZAR;$pr2d6S&!#=1kyT0HV)K;JyH&uT0{;F^QX< zX~iV&H6XfY688iU{a_;ZlZhaAOyoW>k(-fe$3*TUApVYt+j&Z*L(Kk+T-#GzFYbUs`fanh=xW9nt7bm#ifanP)xu=}uW@qX+$=w5@ z*PP_u0HT+ic9rqFtedZna1rUAY9rp8xZ~A9rqIuec%K4kq@AB_JMm3h~Cq{bD)8TooP!0&khj1q?u<$GY>n{oMxT{ zAiAf8XF>}PJ5x&wPX~x@Xya*V<6&p|(aQ6um4}^aMjOu@5Pw1&&lC{7qm5?|h~Ch~ zvjs$7Y2qR+JPTxjEAVw%v+Go_n{ooP)s&jt{ErJLtQHxCojlpdZLJv{78J9>Eb zfasoHo(a7?>`WhedA@+?o<5!leLSEA&pcZ|^qoGQ2Yo#3OlSIdE`aDCeLR0a^oo9- zHT^uGd0d_)AbL+f&jAp9rl02mh`!U$^8iG@>F4sG)w@gpTM&OL~ohEvjaq* zn80%eMBkaf^8iGDn85P|M8BBG^JXFs2h)woJa;DZfLg#jYi9AVGaZ=8b7UqD3-g@W zJPT&?ESb&2&U9op&j}DcVGhrfIXo=PH|Fr%nZxs74i7uil({@J=JK#J^~~j&0HU|d z<=FwE*UaVF0HQC<<+%c)Pt4^xGna>nX~8_6CG$YGE#z6V5aim0JWCexurNb7wIRJJXVtJS$d$;&3I;0ua4tCC>p6y=5iO4iNodCC?KOePboh z9T2@_70-%QAoZ(w7J%ppt9Yh>=sl}=4uI$_t9W*R=m)EKo`C2Zt9b6L;$dN)u$pJe zYMvRZc{rF_R`YbM=3!^ru$pHJh<>q-=gm4EcBTjGc%H1|VPa}o&(pDV|mv~1w%*Z^W~=4si?)3KR{h55-Ao)=qq-fZDvVtTWU=fgH0CZ;dD zcz)~xrNiAk9lLp0m>2BkS+bjF#cq%tyLp~~=o`Cv?tthydw3S?0R{3No*5vzV-HWy z9v&v9AG>+}faH(t<2kVpRq8kqLv>XN{?L$0&4uP`7VV)g_K~Z{` zXTf2fB_QUX!#oW~cv_Bte0qdu3y5BEgl7$iK68ZU0*F3xgy+N&9v0>gM|i#*;rRg) zT5^`XUq^V|W^dv5a_0MQF>^DF_;e{S(K zfanLec%Iw>WyD)NCqVRyTRdw(bjvNC4iNp~CeNFjAphLtxd5V9+~ipUqW|3BX#mkT zZt&c>0ZIrrcy@s32{(AAfanj`dA?ldVQ0E?o#z3F-f^904~U*}oo5D!{&J1y2PiyV zT;q8IqAy(IxdNh(T;n+bqCec{`Ennm{~^zVhamGG@$7g6a_1wS6CnD^Bc2pXWRcFL+p(H@x84@`7i_3sBN~$#dW(D2Kk}dGV6x%}Y>8{)%VAE0EMHo&zBI z#VejSAo{{9o+}`F$~&GJ??9>K9nS<1z2+Uy1`xgE9nT67edZm{1rUAY9nT36{p20b z3lM$bJ`}Cbn-GWedyx-(#6Zp)X>e_(#^}lJg1v?K{xM`ZeDh#o*v!_J-qBpEj_#)Ao@o) z@1Jg7CZ-qNyl+7AFM4?2fW>=w|A6QZy}Vy~d6}5*^zuIF9!Pe1Pg5dEN^_X&u;(a(DaMDLiuyJrF~JJW^< zyjwu@f{DCKCi1c~&6vnL2So3g$a?@pZ<)xuVh^qr}^ z4?uLoG~SkJyzERrrt`m=zyVIeO&(}cymQx=2bYBBE}5Pe}W z?-daJVKMI)5dC5??;8-^v4pp02`HkL@V0>HDXVyAtOA+8igyBtUbBjK1BhO-igyKw zKC_DV0*F4ciuVMFezA)84TyfQiuVbK-msf@%WhtFrX_oLSM1?sVw$ptcg7x&`TKcW z_JcxsKkpn6Jz+oZ6cD{-Kkp6@y=Fh}1`vH=KkpR~ePTcF84!Kv0PlkXyi81I4)9(8 z(H{=*emTI)&UE51@0r8A>`Vs^^Bw`wHxBdO0nr~0^L_!*FAnp*0nr^tczce3>_5WW z0-_fj;avivXB^?31EO~v;oSqGHyq*J0-~=R;k^N(&m7^s0HWU<;r#%jpB&+R0it`3 z@=iDkO1(#UJ3#b}6TEj$@Uk;qIKg`bMDIDpd*Bo(-cRxFIK|7t+;Ez=md2-ye%Ml#dY2_ zAbP=d-X$RV$t~U&w|JSDZrtL%bBmXq>CY|RhTFXCOkZyC{s8e;+~HkwhnJmc!5!Wu zAo|M#-X9NmL8BAAA3*ejN4!rSfl}8a-a8=r!z11=AiCo*Z_i_py^ncY9)n{4DesJ@ zpw#e`cLj*P@s#%th`#WY_X>#q@Rauph<@>u_YH`i@QioLGhTM4j%U0*Ao|EN-V-2t z&okZwAbP_y-Yw5~nV1$l<6Q#cpLxN1;RPr+zTiCpqMy9reF38Hyx@HRqW`?$ZFmXt z*9+bsApVS(ymLVO2`_o4fazDfQ(l2m*K6JjuX)*-?!4xG0HSBS;hpma6#j2`r-0}U zZ+N$W=oN2x*MR6FZ+K6D=pS!*|A6QZZ+O3e=qGP@U%cT3Ew|&n0phQD%e&z%C^dZK z-SLr^iK*igZ_g)C8TN^H28izY%sb&TC^dcN?Euj~KJotf#LL9= zvM^8i!aL&&@0>5ZEX-$q@?QAKd*vs{)L*0W z2Z(O@&D-%Cl0ixIZYP;+p~DZ)xV+(aguh^reOGM++Z2Q%fsfM=Kv_ zWS;K`h~Cl4w+BSuXyv;DqA#@aT>;T=TKPVJ=ml+jOWOEA{V2XUAiAfGZ$cX%6Vsno zz6KEeq@C|YJ0Ck!M+aX|2Om4rmM*>>U3~0Jf4cY@y7}0dE_Cx<0nvN9`3`{SE!})O zK=h0rzBxT0^*ww$Ky*hhUr#R|JJXR~z7rt2r;l$!A4q>6-xUzu(9hS>4^lsoZ^uMF zcBU^A`F?=t3zPV+OyXl_dNG;r&160%rZrRfHcaJXXWBEB?*NGYF_rHRi2g8@?+b{Y zFpY1@G?06z@%4b{CDZs;fan|3`0jw{3)A?nfaoLB_)bjYV`ADejc*5te`Pw~jp?9p zoyj+2CLcS~l9_xfK=gx|d{031jhTFRK=hB9e1Aanhnaj|Ky=S6z6rBH;XRA*2#DS> zi*FBzUNeht!z?}~ra80t7J%p_v-wuc=3{3%F`MrUi2g8_@5@|1CZ;p<_%6)jV`us> zkMGMoJ|?Ce^ZEA7=VNEOv5@c1LOyn;AItduECY$J;M=nTq<;n984%sFlCNVWC>~bu zHGt?jEBO|H=qW4tW`O7oEBUs7=qD@rUV!L3EBPLP=nE_PuB_x^Vmh#r?+A#0Vin(+ zRUrFU@qGc&Q&#iMSPkN@=KBJo=d9yfu#OM343+Nzi2ksi@5_2VCZ?W^d=obEu`|ut z$hQDQ-`L1^2Si`k$ae)qf7rmIp+xRAI1EuG!d<`J}g6(`uw(~JDJ=wwcVh1Rl?cn?l5G3cykVBlk9fP*7h3=Dj11`G-FnZaWFxk2)vQ$4_3h94RX41BB%3=I{F zzyhmkp!_UZFduXdK1lw-{Dolt2OE%n28J7;12z~K7!=kpFz~T6Fg*PaG2dwxgfAt` z0#@Iw3E@A0$}5B1$Iig;7|PeLfY`TVwjx-4Krh664S6OoUw#QhzhxZ6Jnd-^{%I(G z;cN)MAIjf21H$j&gQ)L@`o|%e6>Q$?sSx=&Q2EF6A^i7I5cQ!OA$&G*2tRr{gfAQb z;U9#`8$$VEQ2i62{CFma`)9a8!o#W>6#fhh70~dP-3&2rG1PuhX!yN`@@*GE~SU{&HF)%RnEr!S|Lix9#?ssB@n6C*6FD3>Cjk%Ec2Hj`F zhs58z0HQw{sy`BH|6xCf{^u(o@<*WZictG+LitWm`(H!(g;4Vtq4tCB?E%?m0JVQA z)IaJ_`HP_Z#>Bv20hPZ7m2ZWbcL(a8sZf44G<{8h@};5qs~5_@4h`SwP=4SB1_qG* z4p8$op?nW0Uku6*fb#D{)8|I0{>@PLML^}{q4ozr-9G{9zGx`lvl5b@GNAb>5z2qC z9}@mkq2?t(&FhA`cM??pJgEIkq5Rp<@V^7)UtJ1`k55oOBQ*TIm>}_`3Jw2cDBlwr zp1Yy^K4|(l4&`5lre9`eh<+ESf5f4Dd#L+Np!^`H`@Eq1D5(1ip!`m#`${y${+)#o`+h?CU*|#i zY+MlaDp2>yLHS)!_gO>vJE88&g7W2|?(2l|RiW;?2IX5o-S-yCcYwOjfE!|;H`IM@ zQ2qgE`d5{K$ftnHdu9fP577J<1|d`oC~nE{p00;y+WU?_m{S)t{P6V$v=XnEic z=~^%tT1Bhd8x3hF*isDHjd`BhN=q{%|;FNON29?I{4=C`X* zek(M;J%#f3L(_A;97O+XXnLLqZT$-!wr7 zjWRGW2tnOv1?6i)-FFbm_lLUg9F)Hb>b_@C{u5|<@CnNIg1T?5D#U#OQ1|VI@{^(N zD^-KYXG7iB1m!Pv;h80x;eP(CNr zebY4|`uU;mTMy+cLER^*1(DZ+x=$0zH-)+{8p^MNx-SRHpA2>1WGMd-H2mi)V^V7U7cn<qF$I-%ThEq^J7u3C;h7kQiQ1^yG`94th&V%xEq3+!X<OLDNe<##^T&58Df6($p7Rt|ux^ESfp9OW_VJN>A>b_r4eihVx{ALjI zK=)aK`bYjy{sULm73w58QImEn8Q1@v;`N~lDl|uP)Q1`V% z`G!#UorCf%q3*j6pZi5zU+kZWuWd8w1VjOfVxi!%FltiFB;090Cisu zl>Y!)z8r?~RiW;?1m$-_-6vrUF@GY|edb{#$ zz5>*JqM(DV85kH`pzc$F^5;X{R}SUhgqAN|P`*9XeXpT>SE&1bLirI;_bJ&z+@An- zpAnQl3+lc=D1SG!{ELP1uRzO}Vkn;(>b@>0KNIS{b5Q;asQd0h`TwBhpP3!Reio?v zJfM7WsQYF@`SMWr?SS%+MnT3SLO=&mGcYi?fyyT)28Ie~dsQD)K7qQP^FRaxLyZnZ z{fREf_{S}%`Ua?aU#NNksCql7`vrI)?#qR`-vG+L40XRBlz$VXpPhlB56b@nEnl8P z`EQ`*<1r{-6dJxv(D51+FI1WnJEpyN4p(DZT(%2$Tw&&^PNEHr*J zq57vo%YPdvUlHn`A}IeIG`$Hy^`C;8&jaNrLG!B`lrID=Z^WVec~JNLhmN1{LdzFd zsQhwh{xN~_rJ?0ZJ(SM@Eq_9w{Q1!M>43)138?-&=y;SR)cj^BKLIwLm;@P5T;>gp z@5PY#o&=4LX^xQioCJ-(8BqUsL+zUYwQmtLJRU>ca}1ik-$40kQ2nR8A?D>k(D1Q=j)$#;hVL&oi1}Bc@sk7{U;7Dl zZz+@?4I1BMWnl2_hK%2~!T8k>{!6I)5~1!lgu15>%0B@OFDWR0iUb z3=9ksQ2&%c<(r`CNiPKAJ|n36GGie8=}`B%M??7Epz`0LKYA>pCh1sOj$ z4)yPkI!O9GlMWeg5A0)L040q((DErAq@RU>;USc-4>f;#5X8Jw(DZT!YF;I@yzz;J z$j^etUj~%F85;i;Q2rxmc+GFYI=e+t@uj)$uM11+C=p!`)( z`=&TU%y)#Q4+AKFBGkMLD8CRCKA^ijpynq*?e~VtYeMVycBp^Sp!&Z+!>bEw9}6`8 z*`f6hKU9A?DE`irq?zoA9No* zXuSIZH2!Tt`k5FQZb12~pyka?XnwAP=8r>AzB|;v^PzlyXnx)V2_u4@Dub}CBC6s>=n*Jw3`5U0_D}?gPp!S79`I1ogoQ3l1q4C26x&ViPfk6bC ze!QW4DX4pjp?qDadlo|Z>!9w}fbvbD_ML?C9iZ-Em4t-HS!j9c2j#ay-LD1Z&x88U z8p=0@x~~|@PlDRl3+0~xf9J!w((bUIsO<70MTaj@N94@*hCUiz!e(FDU)9 zGcX*0@@1jsUxD)HL-Sh!)V~$b^7tcEJ{)TQODKOiw7&TX<^KSg&&kzZaq58vz|(=Z2bB3gzoS?W=|IqoL+6hVtv7?%N9G=R@P~H?%+40gWF%dr182 zL-pH1*AKi&hqR~OR6_cL+oAEN4OPDh8eh|){2d_ovokPUhw^2i>9YaK_kqTDJCuJK z8lDW$@~sTyKNbdt1<>#)DT3HPr50lUMQHpThpC6UXCsu)05$(5l>Z*u9z6i9Z}&m# zt4L^l`v+>?e&~7&KWO-5L;2~@@TrILcSGZ&6RO`6S|3+H!|N-wep~^S7lX#nekk7+ z8opPc{7h*4FhSQ3_=3u376yh_Q2&31miHD=c~5BlbOE}4B?juBnNa)pL(AKjQ2ttI zd284zm7xsKcVHb}cRz6jKPH=%qjsQd0i`6*EM zJ%#dXq3(MP<*$Ld?<15i1a;qcD1SNBJ%Z5m;s|x`U#R?AsQW~q@&};hr#O^f59RAX z$5Yxt27Fz=0e98RzSHQIu&kfCAtx)p=py_o!l>Yq2XnNZTHGdB@z1@QH&qL$$HX(EPj~%IAiL=N~BF3hG`3=y=~P==j?WXnA?a4>Dfi0`2cChK64` zRQ(HR_$`3)|L_Gg zKSV&s#}c9G-x(?&49!2{Ppq2Y53Djx~;-)|^?5!C!HsQMacc&&lDHyY|5c_@D_G`vng`DdW%;}Mkq6dJ$3 zpnNT8c*#NA+f~r;@`v)bK=V%)l>ZW%UQa{$&!Fjh3Y7m4n!eXU`A?wfZ4R_OyA+zf zC86yDO{jhAq4Kk!=AD4@r$Wtp0OhZM+W!a2zYonHW>E8HK<)E^@`IuNb%pZ%pyn4s z`FEk|KM=~#hn8Qfq5VZ~Xnj=;0C!DE^rk7+yfz_jf^j(EKn|z8soZHy-?*UV45Cne2-LiL(DE}KYTjEYpB)-r+|c?W9GYGQp!_+|^dJu9GeO-e59R-brY}_} zUjS;pHk2;`b*~YW?+y)rODMk>+P<}i@|VRkFz_=nFr@5(jBjUHLij3sA^aJM5dMaJ z5WZ6`gnxk*GN1Dus$T&re*((SI08{G098NbFods=57GbTID}s!1>u)K^}9j!%N&Ks z3kyQzE!ZLUNlaj1;OAgqcu@sOU!5rsc^9aD>2wHR;TS}JwLApyeoSO?)h2Hl&@$iN`M z3Q=#t4Usol4UreNg7D9*g76#VA$$?&dj8pN5Wde>h`i=Rh<|rfL;U+94k91I05QL_ z7{X6rf$)Q%d=n^trV2!U2bBLu0mAQr@`0_B@)L*#8h7nCwEFtoKo_zk}y{yi@Y;dA_g@Rijd zd=@CbO$owZ1G+#JbVnxxgwK!K9G>7o7 zOoi}2f&F)YL8TMIcZJHEK>0tCAnILOA@U_q`8iPj8L0e@c8I(LRQ?9<LsDh6PZ0 zg=rA^*Jcp&9Hv9~`Ox%MBMRXQLHS3Z>8}kMJ}01j`#_L>28I-9dYTT+zd2VS;V06~ zz`)POz;FUuK3eQFfeqbLG*{T zLFAW1-7}*V!k=jek^kWdF>iYggkK>K;fq1ttFsBBzKs(iZ_*Fpr$Ei~34o|S5)6@# z0bQiaz`&p;3*rA@gvcj|L---k@c1VN;nzU<+|c|#;W@554oLatQ~=>;fG+H1U|?{EmcMI27x^+UF#Pd@$QMAvV>i^lPoR7=CWw3uKg7PX z{t*5iDF25Sgnt3bf29TCe}M8^St0x%P<}%tr2P2-EpKhgA@X~m;Zp$hFUtmq`{znR z3_`HdN@augb`b|P1d|POEOo67i)3FfwE3pvy{0<2J&r1kDz!bvo ziGlDNgdqGA!4UowXnHV!+TRN`@5u{@JQvh|SD^M;Geh*3K;@TZL--le5cL(%__tUF z2`>{UUjwRN9~zz-zL5Bt6a>+q1C8&+(E2XmEW|wH5QzK=XnHY+hK~X?J;p-$JW##` zG`!|O`FEk^!3QW`7#hD{pys83(i;Z@!vkn~;Oc^;j~meXrUIJY3_usLGcYj71wh;* zU;uIdb3O>a16m({iiYrep!?5uK*QSws@{GIM4qD(;=dGV`yv6FUgbg|@*U9dxoHjI zhnPX^D~E<(4=03g4b86s-VicaH@uO)A zG5-rEsPtiAu!ZLL8Gj(|I|;2HOQ3umWr+F!DE}0=d^*7JVgkfIuOf*20%&;u%YyJj zgdy?;(h&ZM^$`1SK+~tod5C?gQ2)+>@*|=3xyLn#``V!D4Y(kD0jPWrG(NMS=~)MA zUk$W;N`aOaZ=wEgfv&eugQm9=Q1fb_d>v?b9fqo(Q4ew7I;edwp#D1vRo?;SAAr_x zXSP7p*FgQF11+DQLF4a;4hWhsbG(Ofr!#@Mc z7l(%T1kgqDp!r5%P^Y;M;hdfC5b%N{10}MR{5dJoBd2@iFqa0#>t_jF}2N=G@ zLgbIzgZK;#HqiR93L4%m(EPjrD*pl6ehG4dsF$dLn5PZR|8u56_$JWuqXAlf3xdiU zMg|524v2jVLFEk_1499{{WJxd|1v&6^s9s0F9#SVghJHw$bsxTz|a8YCqwIxJI^5M zW1#iT9w>i3v^_Hg%J-51>1SY&f$~M6d>$x&7qmR%ftJ@2;P%S_h6<>CF<|)v3_Vc( zQLuX$7>+!J*uMl?-snL2XE;Fi9bl+|s&|C)JD~jMVD}ziXo2#J!SW0Y22l6>f|lod zoJK=^*p{)YzCzKziS#}BCbgV69_0nPt2OCaU@9%y;b1Fc_7p!qi%n*J9+ z(|;_u{mj770+k1qTA=>Sk2MhcuX=#|$H1WR4Z`PwrjLg25Wcz#L_Pr8pYYLx@I#>e zuL5X$y`TaTzq`Qp9bi}joxe=sf~cP|1!CSBaD8`xVL>58{VHhsh$)8feZl3&0fr~> z5Pl7`zdHlkUOWbEA1Nq9Lluew+g<-=O8y(=v$q255aX588j411*0mpEIlPb_?zk= z=9Oea_zvLkV_*om3*q}g%ZHXk2wwrpUjtn~d>2|Dvq1B|2{^nN7#yJG$4O}W<^VLl zKST9jXoi^g0NNgEfY#Tg(Db7M?SC8x23_JWG{0?Y+x<(ShkA?D8pz`~m^|J}I|DXuX4=zyqm7(do z1==6sgqF7Q2i=U{yXq^$pMCf6o~%Y;P%o1 z28K)sUkp6HaDZV#E`1vI?4pyk($FA)3hL;H_YpnNCj_=68r zeLb{%R&j@zmjlhe4p9F^gY!QFg9J1`yFu%F6=?pFhKBbAX#6aK#_tq1P)WwXU;@qW zDbV)mG-!Ql5(u%c99n<$K-=f_(Dq;ov_JF+>fRD)`cQRFj;;*I-5}r?>?S&BN zc!elbeu^SQzax}CffvHR1ub7Ap!zo(L(Jo`fXF+5+XoB`H7gHIbq4D_x8lR@%_WuC}6KMQpL&x)Gtc95O0P3DQ z9uW7iLi^t(<`BL#G`+Gw?bm{ipR9oTCm343Y=Or2TBv_>pz^-Z_G=Ba{Bwi0cXZA{ z+&>Rm{$GHW{~Mv@zla9Jeg)`wBnvcuXS;&J?*KysbUaHEI^Jbt1Tl{TnxA^0<58Ev z?Z*QQ9uFb%flzsi*%0%U!1f(rPzZwXd7{(^1@zX9z+K;thATHdul>t9o-{dcq=?zaVvr!q1yxIpW};(CaAK2Y=cpy_=I zw7ts)O^+qe{L%$AKgSSaUcUxJ{}E_=_e?2-|6x8PeAc!=_;+SP_!`js-vQI0C@Uj7q&mUkokPYE)fbth4LHI%7`h|gk0~#O2(Dj?dkNmS1zA@*krh;VS}d zpS*y!cPDT_%8xhT@c;&fJ<$4iIyC&RK+~rtw0+338ls*TT7QH<+c%fM?SBS_1ZerY z0V;n7+JB!42!O-#O3()p~6m+~x z;~yk`+@ST(k(m(pu7uVB{IdJ*Sz#syxKN+F@{|G4mC$xN!sD-Fc0H@yr3=D0M z_+A68pJT2=39?=@(CNLT>jA8&@J|1%51KMD=MjtYo= z?>30MMFPZpVRZ=K0II$R+Ftwv4bS(``uhh|J_tIVT?6GGhq^Dp6k^_5XnS%>1cc86 zZSQgHg1F}sR6WBU2w$xcV!sM>g5Y}%gs<}$BF_pPFFXU~8yG?4uSh}6xAlbZ*FcWL zVt511&mW-US$9G8Ey$=!i2oBCAnHAMA^P>8=`9E9-!;(mlmO-PL&GBk%74}a(Z2_J z9?}n}`xOpC%%9Q(kw35>!avOj;s3Y<;U_`WAAs^bq3UDyLgd#%W8`d$hhFHvEEnD+^q9zN7U)OSJa&o6%<=E*oi?4R%x z!rucOpP8Wr(f<+}zdq~`z7Mp0x<(tqKLVW(_JNKMCZ|Ho%P57|cMF={8=&L!Z=m6E z0~+2kju7=8O%U~*(DpP-2ZYZBZci{UEP*UPVz>xy?=Ucwa6{z(LdQQYctYIs7~1}x z;0NJ<$$(dpF!h$3p9SDpy_!DKO}s*p!^fi{22`8Pk{1Wq3N{&+W)A5rUws*c7{FB z_|n-9Ngq1U{#nX1h=PaE_KprTeNTs`w*_k;@_V51yWz|t65Pl}Ker1D%ibg2sn}B1HZbH2sJuK=|d*`lkWv zo?FoTsRQM2g!Z4`K+{75w14y?45GgZ>i;_{Anxmd_IKt$$DiIq>uZ|;NchcxhNr+Z z2;UnTze}L$|1-4y54a1F-v=!ZDxmRS2=4DQFg!_s*l!ALA6P)gpOm2EeIhy#`470cjO|E__`%R%G2MFwJCF0?(kWgW!7ozVGS9utWCZ)kX^ zKD5gMKcsv-V;3k?sM9T5IG2T1wWaSOu#1PzZZ+adgV zaCy(b5Cg66S3uQofvVpN?JrtDlrxk;%UcO(dom81-|j%`>lx7e_ypSix(*G`0}mkn zy$21C4^aQDf~K#UI}i&Jq2nti(ENM^8lDDFKB%1qO5ZKe@}d;het~FbxDRblL5pjK z+0gQr0XiS;1$Dm-RDB&ZydFUP>jurgG0^n#22{TztzQd)+V=+P-h0sTH4$ie76vW< zHK675m1fo*SCq?m*?s z!14zera;H%!=dTpK^4Tq2GHVlcDJ?;RnS3s!;x)*ARXuG`-nC%LgZD{ydNmG2aVnUP~dw z{oK&}cw`Yoe;%|yu_q6r{vNJgkKF>uf@o~Pyy`^fV#yX_lQ8G z88$)7Hwh?T7To`2V32|GcSFYmU?u_+`J+(#3!wcA4QP0!K=}^P^1I_S zM13Z-{eI;pgr5X%PcSe%xC-H4gy#PbMtp!r<|+FxD> z&98Hy{ohV#`Dg%@_k;46K;=20{aX*H{8H%rLI{+<7&?C70UggWgUBGpvAyj|!B33Oe2*a2+DR0xj>3KQ6fZ#Oi}L_O z0+i1Wnm^(^z@Px-ABM_1K>72a`~^_HJE%P5Jiss`9#X=qgX&Mt0}KpM`8lBVMVt%_ z7Et+iQ2P{Veena(_z>p-h6hmjFVOX#TcGRBI5Z*Qc>~IS1?_(aK*!%AA|diGpzV!s z(Dvg8===w0S{anTH$caiwnFC{CqV1#TTuN!pzCYDLfh{g(E9XpIK+G&XnFkrI$rkx zTHi26K;&JZ{S`lG|0V)j{^&x@=Yf`&lcD}8$%e!i1Jpc@TnPUh)Vv+Jko+zH)vpi? z;VVPOt2!(o{3s|tf)m2u33cxic?f?c)I5V~2>&yb-;w~~vqJU1afR?5q5M4}5dM6q zc_BIweizg|TcG{51JLzp4bb+>OsM<|DBlAbUmuDg{_}(S_XV`TTnM$VB@ZIM3R>P~ zK+CsiXnfsihsc*e`7A9EzAlvC10B!MhuWtCEpJt!?iYZL=YWC{lpg*-`NdHCFF*_U ziBSF%Wr+FHpy8zgZSVF&&3gjvKR<@@w?Nx_IZ*W?(E6?l>Ye~-`%e}s9{{c2zk6RMGTHqwznuqv|h@MCC6-Ge0Z>Ro)6s{dILzc_9r{z9X7^1Dbzy(cD)b zj;jALn*2UA_rAG@s;?ekpX!hSlGygZ5c}Zyg>qb)_gQngFEq){z zQT-!{X1^7hyak%PF`E15p{0LOH2V*uslSWH-w=iBo=s@}nTeL3n9%I|j%HpJnt94- z>c1AF+UJKB-&@eqQ#6|Ym!r8)1dZQ`rhWpN`yZmEM+Y?fP0-A%K=WTN8ebaCe+6ji zg9pvL&?Tt;Pe$XPMDzbPH1{*a$4B`Y8pg*LC+20AWLBjX8JcJ2m82HsCFaBz=M@xX z=9Q$m1|;VOcqdn3DmDvBEyyn_am67U0M(9FuaSW#)S}?z{DRb!;F6-uymYg~f`Zh% z6oiRp@$n_aiFt;mA;pP#&Kar6*=~uMIjLY3nZbtfm6e#zGBm`YFta$Zqy(e^;otZo zuovP}i;D7#;)_dja}$dy8R84_i!&?YiwhFV^WxJob5i3IlS?x5^NQnBQj1H9@=;YJ zmXs7BBp?osFDS}SMiPwjgZjkB(8M=2H@~PdC^0WRH8{1zHNY=8-q0{4qbM~oCAcK9 zB-J%HHy7kexE}N1%Dm*T#3B>VyiDxsQIx|BbI!?6&NeQFSz+mtnpd0}oRgU3n3I#A z?3|dKk?NWS(TS1HOCrTWabjLdQhr5zeqMZDeo1B;#1d$bS@@Qgq*er{mKZyxq_|cl zRWih0`N-R#ba7;-7>vtuf(9p;+CB-E*5u0kb3(SI2 zbMwnmp=P0knxP3K3WHM9GmA@#Dvd1NGV@X(V$S(_C8-r9PL=+}o-RK5$=RtX*o-i8 zaWS-XE=o--N%hH3&rD9tfoKP-1?PkK+{A+T;*7+U{Bnl)c)wux)Dp*{^fD}Yzycm6 z#hK}l)a#lV;9VAgMX|9#aAsAib53G$F*s=?mgE;18~NlXC+2`tiKkz1yb)G4AQ=O%`( zLnDX|h-t35MCvl|%FoP$>LJn|m(-HP1cUT$K6b7D?TQetwpt6y-uu@R<@fRZA| zqN2n~P|1^-3{que2#$Hjl$4^>;^N?f#N^bl%+zx9_yv_(CUA>E+KXMW`zAOuJufi_ z8sCOyE~U932Sf5nY7q`y=Fa)KNtt=6DR3(we#4ehK{BvZNSrrajZ8pUC%L3FF(;=I zYDH=a$Z+hQKu>&z!6k`BC9pJ62?`7Y2rs0vAQihAI1)bCBv65X!w_gGh*Zd?6{W(h zfXhN`hlaAHe;&+OtZ{7Pfcj^NZ1P&Nfs^N`{SyIU;$^H7zc z7RZ>M#L$4TTxPXw+1oaphz;l0Aer8^L3An_Zb)VyRggA7d(_CXp% zSc25h6jYFBCI=T}=7AMifLbfTIr-(Nt}--)_&2yDF*)1VFBK+@l0?lxMQl-e8LC!9 zLNW0yNi8z*ORXq@szA|gXb@bPo0Ja0xU`@E zR9$A~=Ru2LLo*aHgjQ6Y#vq^gr$KyGY?29T;bU_WsyaiXG-$mJid1aAGc*k;&-Y0! zOU-erEJ^iEEb#QHG&FPdsWdULG{aZTgWGyoTM(|0{s+W$us}CPsdvo%^MX=AJr0N> zRIg%|$9R=nLNc>&VnIP>Ub;_WWqxUiDJiDoQEcj*pOasdS(OS&9>vfQgn7y!q$n{t zH6XF51SW&(6GP|x+}!*;x17ZEVnf5=)DoA}w8YXJxN4|5ri2t2nPOzx_`G~jqYt~i z7Kn7|o>~IRsxWols17tnZF3obaw4QX2lXk6awCwuZ(>DQW)Y}C1a0|YRS9Y~`6gC` z7N-_rRgKpjMuwinAw{LBZlJKr%u7eL2(MN{6VGBudT>kzmBUcSK?B;z2$T&VWhr=A zAvv|6B)**TAW;zSpXgt zKy!=*!Z9wDd5O81$&Pt>`6Y?i)FL??

    Ports

    -

    FreeBSD

    - -

    - Go 1.18 is the last release that is supported on FreeBSD 11.x, which has - already reached end-of-life. Go 1.19 will require FreeBSD 12.2+ or FreeBSD - 13.0+. - FreeBSD 13.0+ will require a kernel with the COMPAT_FREEBSD12 option set (this is the default). -

    -

    AMD64

    @@ -105,6 +96,15 @@ proposal. now supports the c-archive and c-shared build modes.

    +

    Windows

    + +

    + The windows/arm and windows/arm64 ports now support + non-cooperative preemption, bringing that capability to all four Windows + ports, which should hopefully address subtle bugs encountered when calling + into Win32 functions that block for extended periods of time. +

    +

    iOS

    @@ -113,6 +113,15 @@ proposal. Go 1.18 now requires iOS 12 or later; support for previous versions has been discontinued.

    +

    FreeBSD

    + +

    + Go 1.18 is the last release that is supported on FreeBSD 11.x, which has + already reached end-of-life. Go 1.19 will require FreeBSD 12.2+ or FreeBSD + 13.0+. + FreeBSD 13.0+ will require a kernel with the COMPAT_FREEBSD12 option set (this is the default). +

    +

    Tools

    Go command

    @@ -200,13 +209,6 @@ proposal.

    Runtime

    -

    - The windows/arm and windows/arm64 ports now support - non-cooperative preemption, bringing that capability to all four Windows - ports, which should hopefully address subtle bugs encountered when calling - into Win32 functions that block for extended periods of time. -

    -

    The garbage collector now includes non-heap sources of garbage collector work (e.g., stack scanning) when determining how frequently to run. As a result, @@ -222,6 +224,13 @@ proposal. been tuned to work more aggressively as a result.

    +

    + Go 1.17 generally improved the formatting of arguments in stack traces, + but could print inaccurate values for arguments passed in registers. + This is improved in Go 1.18 by printing a question mark (?) + after each value that may be inaccurate. +

    +

    Compiler

    @@ -243,13 +252,6 @@ proposal. Go 1.17 release notes for more details.

    -

    - Go 1.17 generally improved the formatting of arguments in stack traces, - but could print inaccurate values for arguments passed in registers. - This is improved in Go 1.18 by printing a question mark (?) - after each value that may be inaccurate. -

    -

    The new compiler -asan option supports the new go command -asan option. -- GitLab From deb988a2866ce541058d8af3844912d1a638980b Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Fri, 3 Dec 2021 12:23:44 -0500 Subject: [PATCH 2397/2500] doc/go1.18: mention fuzzing in the release notes Also make a few small formatting fixes. Change-Id: Iad99d030312393af3b6533f2cd00f09aea0f2a7d Reviewed-on: https://go-review.googlesource.com/c/go/+/369074 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Gopher Robot Reviewed-by: Robert Griesemer --- doc/go1.18.html | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 3e7de64121..27eaf0beec 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -59,9 +59,9 @@ Do not send CLs removing the interior tags from such phrases.

    Generics

    -Go 1.18 includes an implementation of generics as described -by the -proposal. + Go 1.18 includes an implementation of generics as described + by the + generics proposal.

    @@ -74,6 +74,27 @@ proposal.

    +

    Fuzzing

    + +

    + Go 1.18 includes an implementation of fuzzing as described by + the fuzzing proposal. +

    + +

    + See the fuzzing landing page to get + started. +

    + +

    + Please be aware that fuzzing can consume a lot of memory and may impact your + machine’s performance while it runs. Also be aware that the fuzzing engine + writes values that expand test coverage to a fuzz cache directory within + $GOCACHE/fuzz while it runs. There is currently no limit to the + number of files or total bytes that may be written to the fuzz cache, so it + may occupy a large amount of storage (possibly several GBs). +

    +

    Ports

    AMD64

    -- GitLab From c4a8550421ce16f233b48a85dc5dd04b16469b7f Mon Sep 17 00:00:00 2001 From: Sean Liao Date: Tue, 23 Nov 2021 20:52:07 +0100 Subject: [PATCH 2398/2500] .github: use multiple issue templates There are currently multiple issue templates floating around for different projects, these can sometimes be hard to find. Fixes #29839 Change-Id: I6600b6f78842736d81d35e6a64247d00706d9e0e Reviewed-on: https://go-review.googlesource.com/c/go/+/366736 Trust: Russ Cox Reviewed-by: Dmitri Shuralyov Run-TryBot: Dmitri Shuralyov TryBot-Result: Gopher Robot --- .../00-bug.md} | 11 +++- .github/ISSUE_TEMPLATE/01-pkgsite.md | 47 ++++++++++++++ .github/ISSUE_TEMPLATE/02-pkgsite-removal.md | 39 ++++++++++++ .github/ISSUE_TEMPLATE/03-gopls.md | 61 +++++++++++++++++++ .github/ISSUE_TEMPLATE/10-proposal.md | 13 ++++ .github/ISSUE_TEMPLATE/11-language-change.md | 52 ++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 8 +++ 7 files changed, 229 insertions(+), 2 deletions(-) rename .github/{ISSUE_TEMPLATE => ISSUE_TEMPLATE/00-bug.md} (80%) create mode 100644 .github/ISSUE_TEMPLATE/01-pkgsite.md create mode 100644 .github/ISSUE_TEMPLATE/02-pkgsite-removal.md create mode 100644 .github/ISSUE_TEMPLATE/03-gopls.md create mode 100644 .github/ISSUE_TEMPLATE/10-proposal.md create mode 100644 .github/ISSUE_TEMPLATE/11-language-change.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE/00-bug.md similarity index 80% rename from .github/ISSUE_TEMPLATE rename to .github/ISSUE_TEMPLATE/00-bug.md index 5cbfc09fe7..f056dab7dd 100644 --- a/.github/ISSUE_TEMPLATE +++ b/.github/ISSUE_TEMPLATE/00-bug.md @@ -1,6 +1,11 @@ +--- +name: Bugs +about: The go command, standard library, or anything else +title: "affected/package: " +--- + ### What version of Go are you using (`go version`)? @@ -26,7 +31,7 @@ $ go env @@ -36,3 +41,5 @@ A link on play.golang.org is best. ### What did you see instead? + + diff --git a/.github/ISSUE_TEMPLATE/01-pkgsite.md b/.github/ISSUE_TEMPLATE/01-pkgsite.md new file mode 100644 index 0000000000..fee00f5b27 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/01-pkgsite.md @@ -0,0 +1,47 @@ +--- +name: Pkg.go.dev bugs or feature requests +about: Issues or feature requests for the documentation site +title: "x/pkgsite: " +labels: pkgsite +--- + + + +### What is the URL of the page with the issue? + + + +### What is your user agent? + + + + + +### Screenshot + + + + + +### What did you do? + + + + + +### What did you expect to see? + + + +### What did you see instead? + + diff --git a/.github/ISSUE_TEMPLATE/02-pkgsite-removal.md b/.github/ISSUE_TEMPLATE/02-pkgsite-removal.md new file mode 100644 index 0000000000..5c1eb94be6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/02-pkgsite-removal.md @@ -0,0 +1,39 @@ +--- +name: Pkg.go.dev package removal request +about: Request a package be removed from the documentation site (pkg.go.dev) +title: "x/pkgsite: package removal request for [type path here]" +labels: pkgsite +--- + + + +### What is the path of the package that you would like to have removed? + + + + + +### Are you the owner of this package? + + + + + +### What is the reason that you could not retract this package instead? + + + + diff --git a/.github/ISSUE_TEMPLATE/03-gopls.md b/.github/ISSUE_TEMPLATE/03-gopls.md new file mode 100644 index 0000000000..c4934c3898 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/03-gopls.md @@ -0,0 +1,61 @@ +--- +name: Gopls bugs or feature requests +about: Issues or feature requests for the Go language server (gopls) +title: "x/tools/gopls: " +labels: gopls Tools +--- + + + +### gopls version + + + + + +### go env + + + + +### What did you do? + + + + + +### What did you expect to see? + + + +### What did you see instead? + + + +### Editor and settings + + + + + +### Logs + + + + diff --git a/.github/ISSUE_TEMPLATE/10-proposal.md b/.github/ISSUE_TEMPLATE/10-proposal.md new file mode 100644 index 0000000000..ab30ddf417 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/10-proposal.md @@ -0,0 +1,13 @@ +--- +name: Proposals +about: New external API or other notable changes +title: "proposal: affected/package: " +labels: Proposal +--- + + + + diff --git a/.github/ISSUE_TEMPLATE/11-language-change.md b/.github/ISSUE_TEMPLATE/11-language-change.md new file mode 100644 index 0000000000..2032301327 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/11-language-change.md @@ -0,0 +1,52 @@ +--- +name: Language Change Proposals +about: Changes to the language +title: "proposal: Go 2: " +labels: Proposal Go2 LanguageChange +--- + + + +### Author background + +- **Would you consider yourself a novice, intermediate, or experienced Go programmer?** +- **What other languages do you have experience with?** + +### Related proposals + +- **Has this idea, or one like it, been proposed before?** + - **If so, how does this proposal differ?** +- **Does this affect error handling?** + - **If so, how does this differ from previous error handling proposals?** +- **Is this about generics?** + - **If so, how does this relate to the accepted design and other generics proposals?** + +### Proposal + +- **What is the proposed change?** +- **Who does this proposal help, and why?** +- **Please describe as precisely as possible the change to the language.** +- **What would change in the language spec?** +- **Please also describe the change informally, as in a class teaching Go.** +- **Is this change backward compatible?** + - Breaking the Go 1 compatibility guarantee is a large cost and requires a large benefit. + Show example code before and after the change. + - **Before** + - **After** +- **Orthogonality: how does this change interact or overlap with existing features?** +- **Is the goal of this change a performance improvement?** + - **If so, what quantifiable improvement should we expect?** + - **How would we measure it?** + +### Costs + +- **Would this change make Go easier or harder to learn, and why?** +- **What is the cost of this proposal? (Every language change has a cost).** +- **How many tools (such as vet, gopls, gofmt, goimports, etc.) would be affected?** +- **What is the compile time cost?** +- **What is the run time cost?** +- **Can you describe a possible implementation?** +- **Do you have a prototype? (This is not required.)** diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..ddf5fc6833 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Questions + about: Please use one of the forums for questions or general discussions + url: https://go.dev/wiki/Questions + - name: Security Vulnerabilities + about: See here for our security policy + url: https://go.dev/security -- GitLab From ebe99189fce39be68ef4eafa29923b3a6585a262 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 3 Dec 2021 13:39:42 -0500 Subject: [PATCH 2399/2500] doc/go1.18: catch up with runtime/compiler commits and API changes For #47694. Change-Id: I21b1af1807d4da2fb2f4d9b961d44a21d715d7d2 Reviewed-on: https://go-review.googlesource.com/c/go/+/369155 Trust: Austin Clements Trust: Jeremy Faller Reviewed-by: Jeremy Faller --- doc/go1.18.html | 58 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 27eaf0beec..4776936083 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -255,7 +255,7 @@ Do not send CLs removing the interior tags from such phrases.

    Compiler

    - Go 1.17 implemented a new way of passing + Go 1.17 implemented a new way of passing function arguments and results using registers instead of the stack on 64-bit x86 architecture on selected operating systems. Go 1.18 expands the supported platforms to include 64-bit ARM (GOARCH=arm64), @@ -263,14 +263,19 @@ Do not send CLs removing the interior tags from such phrases. as well as 64-bit x86 architecture (GOARCH=amd64) on all operating systems. On 64-bit ARM and 64-bit PowerPC systems, benchmarking shows - performance improvements of 10% or more. + typical performance improvements of 10% or more.

    - As mentioned in the Go 1.17 release notes, + As mentioned in the Go 1.17 release notes, this change does not affect the functionality of any safe Go code and is designed to have no impact on most assembly code. See the - Go 1.17 release notes for more details. + Go 1.17 release notes for more details. +

    + +

    + The compiler now can inline functions that contain range loops or + labeled for loops.

    @@ -278,6 +283,10 @@ Do not send CLs removing the interior tags from such phrases. new go command -asan option.

    +

    + TODO: Mention build speed impact. +

    +

    Linker

    @@ -367,6 +376,10 @@ Do not send CLs removing the interior tags from such phrases. handle Unicode punctuation and language-specific capitalization rules, and is superseded by the golang.org/x/text/cases package.

    + +

    + TODO: bytes.Cut. +

    @@ -393,6 +406,22 @@ Do not send CLs removing the interior tags from such phrases. +
    go/ast
    +
    +

    + TODO: Mention new generics APIs. +

    +
    +
    + +
    go/types
    +
    +

    + TODO: Mention new generics APIs. +

    +
    +
    +
    image/draw

    @@ -412,6 +441,12 @@ Do not send CLs removing the interior tags from such phrases. net.Error.Temporary has been deprecated.

    + +
    +

    + TODO: Several new net APIs. +

    +
    net/http
    @@ -488,6 +523,17 @@ Do not send CLs removing the interior tags from such phrases. Value.FieldByIndex when stepping through a nil pointer to an embedded struct.

    + +

    + reflect.Ptr and + reflect.PtrTo + have been renamed to + reflect.Pointer and + reflect.PointerTo, + respectively, for consistency with the rest of the reflect package. + The old names will continue to work, but will be deprecated in a + future Go release. +

    @@ -526,6 +572,10 @@ Do not send CLs removing the interior tags from such phrases. handle Unicode punctuation and language-specific capitalization rules, and is superseded by the golang.org/x/text/cases package.

    + +

    + TODO: strings.Cut. +

    -- GitLab From b3e1fbff4d45034a9345cf5ee95099c2742c78c6 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 3 Dec 2021 13:40:10 -0500 Subject: [PATCH 2400/2500] cmd/compile/abi-internal: mention SSE restriction on Plan 9 Change-Id: I2be08b88b5147cf37ac55b7472d63503739c9f05 Reviewed-on: https://go-review.googlesource.com/c/go/+/369156 Trust: Austin Clements Reviewed-by: Cherry Mui --- src/cmd/compile/abi-internal.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/abi-internal.md b/src/cmd/compile/abi-internal.md index 50d8ed9159..7fe4463665 100644 --- a/src/cmd/compile/abi-internal.md +++ b/src/cmd/compile/abi-internal.md @@ -410,7 +410,11 @@ Special-purpose registers are as follows: | R13 | Scratch | Scratch | Scratch | | R14 | Current goroutine | Same | Same | | R15 | GOT reference temporary if dynlink | Same | Same | -| X15 | Zero value | Same | Scratch | +| X15 | Zero value (*) | Same | Scratch | + +(*) Except on Plan 9, where X15 is a scratch register because SSE +registers cannot be used in note handlers (so the compiler avoids +using them except when absolutely necessary). *Rationale*: These register meanings are compatible with Go’s stack-based calling convention except for R14 and X15, which will have -- GitLab From d20a0bfc8a7fd70537766990691d4c9e5841e086 Mon Sep 17 00:00:00 2001 From: Hossein Zolfi Date: Fri, 3 Dec 2021 22:51:11 +0330 Subject: [PATCH 2401/2500] doc/go1.18: change github.com/golang/go/issues to golang.org/issue Updates #47694 Change-Id: I84547ff995e2a302cf229fefefd28a7220a17028 Reviewed-on: https://go-review.googlesource.com/c/go/+/369016 Reviewed-by: Michael Knyszek Trust: Austin Clements --- doc/go1.18.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 4776936083..ea686933e0 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -230,7 +230,7 @@ Do not send CLs removing the interior tags from such phrases.

    Runtime

    -

    +

    The garbage collector now includes non-heap sources of garbage collector work (e.g., stack scanning) when determining how frequently to run. As a result, garbage collector overhead is more predictable when these sources are -- GitLab From 9ae0b35fad5d4bb95cdcf4a05fcf4b077a798572 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 3 Dec 2021 13:57:25 -0800 Subject: [PATCH 2402/2500] test: add test of select inside generic function Make sure that we can import/export selects for generics. Change-Id: Ibf36e98fc574ce9275820aa426b3e6703b0aae6d Reviewed-on: https://go-review.googlesource.com/c/go/+/369101 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Gopher Robot Reviewed-by: Dan Scales --- test/typeparam/select.dir/a.go | 15 +++++++++++++++ test/typeparam/select.dir/main.go | 28 ++++++++++++++++++++++++++++ test/typeparam/select.go | 7 +++++++ 3 files changed, 50 insertions(+) create mode 100644 test/typeparam/select.dir/a.go create mode 100644 test/typeparam/select.dir/main.go create mode 100644 test/typeparam/select.go diff --git a/test/typeparam/select.dir/a.go b/test/typeparam/select.dir/a.go new file mode 100644 index 0000000000..983e4b1d5f --- /dev/null +++ b/test/typeparam/select.dir/a.go @@ -0,0 +1,15 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +func F[T any](c, d chan T) T { + select { + case x := <- c: + return x + case x := <- d: + return x + } +} + diff --git a/test/typeparam/select.dir/main.go b/test/typeparam/select.dir/main.go new file mode 100644 index 0000000000..6ea3fe2eea --- /dev/null +++ b/test/typeparam/select.dir/main.go @@ -0,0 +1,28 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "sort" + + "./a" +) + +func main() { + c := make(chan int, 1) + d := make(chan int, 1) + + c <- 5 + d <- 6 + + var r [2]int + r[0] = a.F(c, d) + r[1] = a.F(c, d) + sort.Ints(r[:]) + + if r != [2]int{5, 6} { + panic("incorrect results") + } +} diff --git a/test/typeparam/select.go b/test/typeparam/select.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/select.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From ba83aa7caa4116266b6cc999d4e1fe9123fe18cb Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 3 Dec 2021 10:04:49 -0800 Subject: [PATCH 2403/2500] doc/go1.18: add documentation for changes to go/constant Updates #47694 Change-Id: I2ce5aaa4493259790712a8a49e5b03472c8a7400 Reviewed-on: https://go-review.googlesource.com/c/go/+/369094 Trust: Robert Griesemer Reviewed-by: Robert Findley --- doc/go1.18.html | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index ea686933e0..5b0520e9d6 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -406,18 +406,11 @@ Do not send CLs removing the interior tags from such phrases. -

    go/ast
    +
    go/constant
    -

    - TODO: Mention new generics APIs. -

    -
    -
    - -
    go/types
    -
    -

    - TODO: Mention new generics APIs. +

    + The new Kind.String + method returns a human-readable name for the receiver kind.

    -- GitLab From 821bf04f2aa6b79d1d66ef7aba7537d346ea5a21 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 3 Dec 2021 10:11:53 -0800 Subject: [PATCH 2404/2500] doc/go1.18: add documentation for changes to go/token Updates #47694 Change-Id: I232fb20b3a77409b84c15f9ec1586e480f0f6390 Reviewed-on: https://go-review.googlesource.com/c/go/+/369095 Trust: Robert Griesemer Reviewed-by: Robert Findley --- doc/go1.18.html | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/doc/go1.18.html b/doc/go1.18.html index 5b0520e9d6..5f32d64283 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -415,6 +415,18 @@ Do not send CLs removing the interior tags from such phrases.
    +
    go/token
    +
    +

    + The new constant TILDE + represents the ~ token per the proposal + + Additions to go/ast and go/token to support parameterized functions and types + . +

    +
    +
    +
    image/draw

    -- GitLab From fa88ba1e8adacda08973d112cca8d6e66c1390e1 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 3 Dec 2021 10:52:52 -0800 Subject: [PATCH 2405/2500] doc/go1.18: add documentation for changes to go/ast Updates #47694 Change-Id: Ied26f6345df2c8640d4be5132a05db3897b59009 Reviewed-on: https://go-review.googlesource.com/c/go/+/369096 Trust: Robert Griesemer Reviewed-by: Robert Findley --- doc/go1.18.html | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/doc/go1.18.html b/doc/go1.18.html index 5f32d64283..c2a04ef419 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -406,6 +406,30 @@ Do not send CLs removing the interior tags from such phrases.

    +
    go/ast
    +
    +

    + Per the proposal + + Additions to go/ast and go/token to support parameterized functions and types + + the following additions are made to the go/ast package: +

      +
    • + the FuncType + and TypeSpec + nodes have a new field TypeParams to hold type parameters, if any. +
    • +
    • + The new expression node IndexListExpr + represents index expressions with multiple indices, used for function and type instantiations + with more than one explicit type argument. +
    • +
    +

    +
    +
    +
    go/constant

    -- GitLab From cd5f2cf50f6372e31dde0b407c1c3be57a2ce90f Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 3 Dec 2021 12:20:33 -0800 Subject: [PATCH 2406/2500] doc/go1.18: add documentation for changes to go/types The number of involved CLs is too large (hundreds) so no CLs are mentioned in (html) comments. Updates #47694 Change-Id: I655d800a1e56a71e9d70a190f1c42c17baf6861e Reviewed-on: https://go-review.googlesource.com/c/go/+/369099 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Gopher Robot Reviewed-by: Robert Findley --- doc/go1.18.html | 87 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/doc/go1.18.html b/doc/go1.18.html index c2a04ef419..fb0b054e28 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -451,6 +451,93 @@ Do not send CLs removing the interior tags from such phrases.

    +
    go/types
    +
    +

    + Per the proposal + + Additions to go/types to support type parameters + + the following additions are made to the go/types package: +

    +
      +
    • + The new type + TypeParam, factory function + NewTypeParam, + and associated methods were added to represent a type parameter. +
    • +
    • + The new type + TypeParamList holds a list of + type parameters. +
    • +
    • + The new type + TypeList and factory function + NewTypeList facilitate storing + a list of types. +
    • +
    • + The new factory function + NewSignatureType allocates a + Signature with + (receiver or function) type parameters. + To access those type parameters, the Signature type has two new methods + Signature.RecvTypeParams and + Signature.TypeParams. +
    • +
    • + Named types have four new methods: + Named.Origin to get the original + parameterized types of instantiated types, + Named.TypeArgs and + Named.TypeParams to get the + type arguments or type parameters of an instantiated or parameterized type, and + Named.SetTypeParams to set the + type parameters (for instance, when importing a named type where allocation of the named + type and setting of type parameters cannot be done both at once due to possible cycles). +
    • +
    • + The Interface type has four new methods: + Interface.IsComparable and + Interface.IsMethodSet to + query properties of the type set defined by the interface, and + Interface.MarkImplicit and + Interface.IsImplicit to set + and test whether the interface is an implicit interface around a type constraint literal. +
    • +
    • + The new types + Union and + Term, factory functions + NewUnion and + NewTerm, and associated + methods were added to represent type sets in interfaces. +
    • +
    • + The new function + Instantiate + instantiates a parameterized type. +
    • +
    • + The new Info.Instances + map records function and type instantiations through the new + Instance type. +
    • +
    • + The new type ArgumentError + and associated methods were added to represent an error related to a type argument. +
    • +
    • + The new type Context and factory function + NewContext + were added to facilitate sharing of identical type instances across type-checked packages. +
    • +
    +
    +
    +
    image/draw

    -- GitLab From 549cfefc7233f17e6bf2d79294d11882181e9387 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 3 Dec 2021 19:24:54 -0800 Subject: [PATCH 2407/2500] doc/go1.18: expand section on generics Also, move it up in the document. Updates #47694 Change-Id: I927c4c845089a5c22e2c5b5f3de1831c04c6d990 Reviewed-on: https://go-review.googlesource.com/c/go/+/369102 Trust: Robert Griesemer Reviewed-by: Ian Lance Taylor --- doc/go1.18.html | 78 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 18 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index fb0b054e28..4f485143a9 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -29,6 +29,66 @@ Do not send CLs removing the interior tags from such phrases. TODO: complete this section

    +

    Generics

    + +

    + Go 1.18 includes an implementation of generic features as described by the + Type + Parameters Proposal. + This includes major - but fully backward-compatible - changes to the language. + The following is a list of the most visible changes. For a more comprehensive overview, see the + proposal. + For details see the language spec. +

    +
      +
    • + The new token ~ is added to the set of + operators and punctuation. +
    • +
    • + The syntax for + Function and + type declarations + now accepts + type parameters. +
    • +
    • + The syntax for + Interface types + now permits the embedding of arbitrary types (not just type names of interfaces) + as well as union and ~T type elements. Such interfaces may only be used + as type constraints. + An interface now defines a set of types as well as a set of methods. +
    • +
    • + Parameterized functions and types can be instantiated by following them with a list of + type arguments in square brackets. +
    • +
    • + The new + predeclared identifier + any is an alias for the empty interface. It may be used instead of + interface{}. +
    • +
    • + The new + predeclared identifier + comparable is an interface the denotes the set of all types which can be + compared using == or !=. It may only be used as (or embedded in) + a type constraint. +
    • +
    + +

    + The current generics implementation has the following limitations: +

      +
    • + The Go compiler cannot currently handle type declarations inside generic functions + or methods. We hope to provide support for this feature in Go 1.19. +
    • +
    +

    +

    Bug fixes

    @@ -56,24 +116,6 @@ Do not send CLs removing the interior tags from such phrases. programs is likely very small.

    -

    Generics

    - -

    - Go 1.18 includes an implementation of generics as described - by the - generics proposal. -

    - -

    - The current generics implementation has the following limitations: -

      -
    • - The Go compiler cannot currently handle type declarations inside generic functions - or methods. We hope to provide support for this feature in Go 1.19. -
    • -
    -

    -

    Fuzzing

    -- GitLab From 1876b38263407ba51f9f3fa2e412ac3f84d3cb95 Mon Sep 17 00:00:00 2001 From: Jeremy Faller Date: Thu, 2 Dec 2021 13:37:25 -0500 Subject: [PATCH 2408/2500] doc/go1.18: add docs for SysProcAttr.Pdeathsig CL 355570 Updates #47694 Change-Id: I922cda28ca4cf1ae6d5e4f457cc66d5041b0e3e8 Reviewed-on: https://go-review.googlesource.com/c/go/+/368798 Trust: Jeremy Faller Run-TryBot: Jeremy Faller TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor Reviewed-by: Tobias Klauser --- doc/go1.18.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 4f485143a9..fa65ad604e 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -761,7 +761,8 @@ Do not send CLs removing the interior tags from such phrases.

    - TODO: https://golang.org/cl/355570: add support for SysProcAttr.Pdeathsig on FreeBSD + SysProcAttr.Pdeathsig. + is now supported in FreeBSD.

    -- GitLab From 3396878af43752a7c25406dabd525754f80a1c40 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sat, 4 Dec 2021 06:34:08 -0800 Subject: [PATCH 2409/2500] doc/go1.18: use correct link for reflect.PointerTo For #47694 Change-Id: Iee4fda069a56ea4436b8aa32e2605f3349d7c154 Reviewed-on: https://go-review.googlesource.com/c/go/+/369334 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gopher Robot Reviewed-by: Emmanuel Odeke --- doc/go1.18.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index fa65ad604e..16a5a6723c 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -687,7 +687,7 @@ Do not send CLs removing the interior tags from such phrases. reflect.PtrTo have been renamed to reflect.Pointer and - reflect.PointerTo, + reflect.PointerTo, respectively, for consistency with the rest of the reflect package. The old names will continue to work, but will be deprecated in a future Go release. -- GitLab From ecf6b52b7f4ba6e8c98f25adf9e83773fe908829 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sat, 4 Dec 2021 17:59:19 -0800 Subject: [PATCH 2410/2500] test/ken/slicearray.go: correct type width in comment The type was changed in https://golang.org/cl/3991043 but the comment wasn't updated. Change-Id: I7ba3f625c732e5e801675ffc5d4a28e1d310faa3 Reviewed-on: https://go-review.googlesource.com/c/go/+/369374 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gopher Robot Reviewed-by: Rob Pike --- test/ken/slicearray.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ken/slicearray.go b/test/ken/slicearray.go index 6cf676c588..a431983d15 100644 --- a/test/ken/slicearray.go +++ b/test/ken/slicearray.go @@ -89,7 +89,7 @@ func main() { by = bx[2:8] tstb() - // width 4 (float64) + // width 8 (float64) lb = 0 hb = 10 fy = fx[lb:hb] -- GitLab From 20b9aaca30f7caa5a7cdd05fe0c2e18f64b04a16 Mon Sep 17 00:00:00 2001 From: zhouguangyuan Date: Mon, 6 Dec 2021 09:16:24 +0800 Subject: [PATCH 2411/2500] all: update vendored golang.org/x/sys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update the vendored x/sys to pick up CL 368994, which remove the declaration of function darwinSupportsAVX512 in cpu/cpu_gc_x86.go. The following commands were used:   go get -d golang.org/x/sys@97ca703d548df069cb02aacea9efc3093ffdc3c4   go mod tidy   go mod vendor Fixes #49942 Change-Id: I05162a051f572bf8599be198a6033384b7d19445 Reviewed-on: https://go-review.googlesource.com/c/go/+/369454 Trust: Emmanuel Odeke Reviewed-by: Ian Lance Taylor Reviewed-by: Tobias Klauser Reviewed-by: Keith Randall Run-TryBot: Ian Lance Taylor TryBot-Result: Gopher Robot --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 +- .../golang.org/x/sys/plan9/pwd_go15_plan9.go | 1 + .../golang.org/x/sys/plan9/pwd_plan9.go | 1 + src/cmd/vendor/golang.org/x/sys/plan9/race.go | 1 + .../vendor/golang.org/x/sys/plan9/race0.go | 1 + src/cmd/vendor/golang.org/x/sys/plan9/str.go | 1 + .../vendor/golang.org/x/sys/plan9/syscall.go | 1 + .../x/sys/plan9/zsyscall_plan9_386.go | 1 + .../x/sys/plan9/zsyscall_plan9_amd64.go | 1 + .../x/sys/plan9/zsyscall_plan9_arm.go | 1 + .../vendor/golang.org/x/sys/unix/README.md | 2 +- src/cmd/vendor/golang.org/x/sys/unix/mkall.sh | 2 +- .../vendor/golang.org/x/sys/unix/mkerrors.sh | 3 +- .../golang.org/x/sys/unix/syscall_linux.go | 10 + .../golang.org/x/sys/unix/zerrors_linux.go | 14 +- .../x/sys/unix/zerrors_linux_386.go | 2 +- .../x/sys/unix/zerrors_linux_amd64.go | 2 +- .../x/sys/unix/zerrors_linux_arm.go | 2 +- .../x/sys/unix/zerrors_linux_arm64.go | 2 +- .../x/sys/unix/zerrors_linux_mips.go | 2 +- .../x/sys/unix/zerrors_linux_mips64.go | 2 +- .../x/sys/unix/zerrors_linux_mips64le.go | 2 +- .../x/sys/unix/zerrors_linux_mipsle.go | 2 +- .../x/sys/unix/zerrors_linux_ppc.go | 2 +- .../x/sys/unix/zerrors_linux_ppc64.go | 2 +- .../x/sys/unix/zerrors_linux_ppc64le.go | 2 +- .../x/sys/unix/zerrors_linux_riscv64.go | 2 +- .../x/sys/unix/zerrors_linux_s390x.go | 2 +- .../x/sys/unix/zerrors_linux_sparc64.go | 2 +- .../golang.org/x/sys/unix/zsyscall_linux.go | 17 +- .../golang.org/x/sys/unix/ztypes_linux.go | 11 +- .../golang.org/x/sys/unix/ztypes_linux_386.go | 2 +- .../x/sys/unix/ztypes_linux_amd64.go | 2 +- .../golang.org/x/sys/unix/ztypes_linux_arm.go | 2 +- .../x/sys/unix/ztypes_linux_arm64.go | 2 +- .../x/sys/unix/ztypes_linux_mips.go | 2 +- .../x/sys/unix/ztypes_linux_mips64.go | 2 +- .../x/sys/unix/ztypes_linux_mips64le.go | 2 +- .../x/sys/unix/ztypes_linux_mipsle.go | 2 +- .../golang.org/x/sys/unix/ztypes_linux_ppc.go | 2 +- .../x/sys/unix/ztypes_linux_ppc64.go | 2 +- .../x/sys/unix/ztypes_linux_ppc64le.go | 2 +- .../x/sys/unix/ztypes_linux_riscv64.go | 2 +- .../x/sys/unix/ztypes_linux_s390x.go | 2 +- .../x/sys/unix/ztypes_linux_sparc64.go | 2 +- .../golang.org/x/sys/windows/mksyscall.go | 2 +- .../x/sys/windows/setupapi_windows.go | 1425 +++++++++++++++++ .../x/sys/windows/setupapierrors_windows.go | 100 -- .../x/sys/windows/syscall_windows.go | 3 + .../golang.org/x/sys/windows/types_windows.go | 17 + .../x/sys/windows/zsyscall_windows.go | 313 ++++ src/cmd/vendor/modules.txt | 2 +- src/go.mod | 2 +- src/go.sum | 4 +- src/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go | 4 - src/vendor/modules.txt | 2 +- 57 files changed, 1857 insertions(+), 147 deletions(-) create mode 100644 src/cmd/vendor/golang.org/x/sys/windows/setupapi_windows.go delete mode 100644 src/cmd/vendor/golang.org/x/sys/windows/setupapierrors_windows.go diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 833c7d7b1f..434081eb2f 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -14,6 +14,6 @@ require ( require ( github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d // indirect golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa // indirect - golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e // indirect + golang.org/x/sys v0.0.0-20211205182925-97ca703d548d // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 0d39656a1d..4b7aa6994c 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -14,8 +14,8 @@ golang.org/x/mod v0.6.0-dev.0.20211102181907-3a5865c02020/go.mod h1:3p9vT2HGsQu2 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e h1:i6Vklmyu+fZMFYpum+sR4ZWABGW7MyIxfJZXYvcnbns= -golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211205182925-97ca703d548d h1:FjkYO/PPp4Wi0EAUOVLxePm7qVW4r4ctbWpURyuOD0E= +golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/tools v0.1.8-0.20211202032535-e212aff8fd14 h1:KPFD5zp3T4bZL/kdosp4tGDJ6DKwUmYSWM0twy7w/bg= diff --git a/src/cmd/vendor/golang.org/x/sys/plan9/pwd_go15_plan9.go b/src/cmd/vendor/golang.org/x/sys/plan9/pwd_go15_plan9.go index 87ae9d2a33..c9b69937a0 100644 --- a/src/cmd/vendor/golang.org/x/sys/plan9/pwd_go15_plan9.go +++ b/src/cmd/vendor/golang.org/x/sys/plan9/pwd_go15_plan9.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build go1.5 // +build go1.5 package plan9 diff --git a/src/cmd/vendor/golang.org/x/sys/plan9/pwd_plan9.go b/src/cmd/vendor/golang.org/x/sys/plan9/pwd_plan9.go index c07c798bc5..98bf56b732 100644 --- a/src/cmd/vendor/golang.org/x/sys/plan9/pwd_plan9.go +++ b/src/cmd/vendor/golang.org/x/sys/plan9/pwd_plan9.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !go1.5 // +build !go1.5 package plan9 diff --git a/src/cmd/vendor/golang.org/x/sys/plan9/race.go b/src/cmd/vendor/golang.org/x/sys/plan9/race.go index 42edd93ef9..62377d2ff9 100644 --- a/src/cmd/vendor/golang.org/x/sys/plan9/race.go +++ b/src/cmd/vendor/golang.org/x/sys/plan9/race.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build plan9 && race // +build plan9,race package plan9 diff --git a/src/cmd/vendor/golang.org/x/sys/plan9/race0.go b/src/cmd/vendor/golang.org/x/sys/plan9/race0.go index c89cf8fc0d..f8da30876d 100644 --- a/src/cmd/vendor/golang.org/x/sys/plan9/race0.go +++ b/src/cmd/vendor/golang.org/x/sys/plan9/race0.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build plan9 && !race // +build plan9,!race package plan9 diff --git a/src/cmd/vendor/golang.org/x/sys/plan9/str.go b/src/cmd/vendor/golang.org/x/sys/plan9/str.go index 4f7f9ad7c8..55fa8d025e 100644 --- a/src/cmd/vendor/golang.org/x/sys/plan9/str.go +++ b/src/cmd/vendor/golang.org/x/sys/plan9/str.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build plan9 // +build plan9 package plan9 diff --git a/src/cmd/vendor/golang.org/x/sys/plan9/syscall.go b/src/cmd/vendor/golang.org/x/sys/plan9/syscall.go index e7363a2f54..602473cba3 100644 --- a/src/cmd/vendor/golang.org/x/sys/plan9/syscall.go +++ b/src/cmd/vendor/golang.org/x/sys/plan9/syscall.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build plan9 // +build plan9 // Package plan9 contains an interface to the low-level operating system diff --git a/src/cmd/vendor/golang.org/x/sys/plan9/zsyscall_plan9_386.go b/src/cmd/vendor/golang.org/x/sys/plan9/zsyscall_plan9_386.go index 6819bc2094..3f40b9bd74 100644 --- a/src/cmd/vendor/golang.org/x/sys/plan9/zsyscall_plan9_386.go +++ b/src/cmd/vendor/golang.org/x/sys/plan9/zsyscall_plan9_386.go @@ -1,6 +1,7 @@ // go run mksyscall.go -l32 -plan9 -tags plan9,386 syscall_plan9.go // Code generated by the command above; see README.md. DO NOT EDIT. +//go:build plan9 && 386 // +build plan9,386 package plan9 diff --git a/src/cmd/vendor/golang.org/x/sys/plan9/zsyscall_plan9_amd64.go b/src/cmd/vendor/golang.org/x/sys/plan9/zsyscall_plan9_amd64.go index 418abbbfc7..0e6a96aa4f 100644 --- a/src/cmd/vendor/golang.org/x/sys/plan9/zsyscall_plan9_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/plan9/zsyscall_plan9_amd64.go @@ -1,6 +1,7 @@ // go run mksyscall.go -l32 -plan9 -tags plan9,amd64 syscall_plan9.go // Code generated by the command above; see README.md. DO NOT EDIT. +//go:build plan9 && amd64 // +build plan9,amd64 package plan9 diff --git a/src/cmd/vendor/golang.org/x/sys/plan9/zsyscall_plan9_arm.go b/src/cmd/vendor/golang.org/x/sys/plan9/zsyscall_plan9_arm.go index 3e8a1a58ca..244c501b77 100644 --- a/src/cmd/vendor/golang.org/x/sys/plan9/zsyscall_plan9_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/plan9/zsyscall_plan9_arm.go @@ -1,6 +1,7 @@ // go run mksyscall.go -l32 -plan9 -tags plan9,arm syscall_plan9.go // Code generated by the command above; see README.md. DO NOT EDIT. +//go:build plan9 && arm // +build plan9,arm package plan9 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/README.md b/src/cmd/vendor/golang.org/x/sys/unix/README.md index 474efad0e0..7d3c060e12 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/README.md +++ b/src/cmd/vendor/golang.org/x/sys/unix/README.md @@ -149,7 +149,7 @@ To add a constant, add the header that includes it to the appropriate variable. Then, edit the regex (if necessary) to match the desired constant. Avoid making the regex too broad to avoid matching unintended constants. -### mkmerge.go +### internal/mkmerge This program is used to extract duplicate const, func, and type declarations from the generated architecture-specific files listed below, and merge these diff --git a/src/cmd/vendor/golang.org/x/sys/unix/mkall.sh b/src/cmd/vendor/golang.org/x/sys/unix/mkall.sh index 396aadf86d..ee73623489 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/mkall.sh +++ b/src/cmd/vendor/golang.org/x/sys/unix/mkall.sh @@ -50,7 +50,7 @@ if [[ "$GOOS" = "linux" ]]; then # Use the Docker-based build system # Files generated through docker (use $cmd so you can Ctl-C the build or run) $cmd docker build --tag generate:$GOOS $GOOS - $cmd docker run --interactive --tty --volume $(cd -- "$(dirname -- "$0")" && /bin/pwd):/build generate:$GOOS + $cmd docker run --interactive --tty --volume $(cd -- "$(dirname -- "$0")/.." && /bin/pwd):/build generate:$GOOS exit fi diff --git a/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh b/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh index a74ef58f8c..4945739ea0 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -239,6 +239,7 @@ struct ltchars { #include #include #include +#include #include #include #include @@ -520,7 +521,7 @@ ccflags="$@" $2 ~ /^HW_MACHINE$/ || $2 ~ /^SYSCTL_VERS/ || $2 !~ "MNT_BITS" && - $2 ~ /^(MS|MNT|UMOUNT)_/ || + $2 ~ /^(MS|MNT|MOUNT|UMOUNT)_/ || $2 ~ /^NS_GET_/ || $2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ || $2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT|TFD)_/ || diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go index bc9dc2e10a..4bc5baf77d 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -1775,6 +1775,16 @@ func Mount(source string, target string, fstype string, flags uintptr, data stri return mount(source, target, fstype, flags, datap) } +//sys mountSetattr(dirfd int, pathname string, flags uint, attr *MountAttr, size uintptr) (err error) = SYS_MOUNT_SETATTR + +// MountSetattr is a wrapper for mount_setattr(2). +// https://man7.org/linux/man-pages/man2/mount_setattr.2.html +// +// Requires kernel >= 5.12. +func MountSetattr(dirfd int, pathname string, flags uint, attr *MountAttr) error { + return mountSetattr(dirfd, pathname, flags, attr, unsafe.Sizeof(*attr)) +} + func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { if raceenabled { raceReleaseMerge(unsafe.Pointer(&ioSync)) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go index 3bbc527519..d175aae896 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -1,4 +1,4 @@ -// Code generated by mkmerge.go; DO NOT EDIT. +// Code generated by mkmerge; DO NOT EDIT. //go:build linux // +build linux @@ -1476,6 +1476,18 @@ const ( MNT_FORCE = 0x1 MODULE_INIT_IGNORE_MODVERSIONS = 0x1 MODULE_INIT_IGNORE_VERMAGIC = 0x2 + MOUNT_ATTR_IDMAP = 0x100000 + MOUNT_ATTR_NOATIME = 0x10 + MOUNT_ATTR_NODEV = 0x4 + MOUNT_ATTR_NODIRATIME = 0x80 + MOUNT_ATTR_NOEXEC = 0x8 + MOUNT_ATTR_NOSUID = 0x2 + MOUNT_ATTR_NOSYMFOLLOW = 0x200000 + MOUNT_ATTR_RDONLY = 0x1 + MOUNT_ATTR_RELATIME = 0x0 + MOUNT_ATTR_SIZE_VER0 = 0x20 + MOUNT_ATTR_STRICTATIME = 0x20 + MOUNT_ATTR__ATIME = 0x70 MSDOS_SUPER_MAGIC = 0x4d44 MSG_BATCH = 0x40000 MSG_CMSG_CLOEXEC = 0x40000000 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index 80c790840c..3ca40ca7f0 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -5,7 +5,7 @@ // +build 386,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m32 /build/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m32 /build/unix/_const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index da55638a44..ead332091a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -5,7 +5,7 @@ // +build amd64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m64 /build/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m64 /build/unix/_const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index c3da063c70..39bdc94558 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -5,7 +5,7 @@ // +build arm,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index fd9f0d1dbf..9aec987db1 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -5,7 +5,7 @@ // +build arm64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/unix/_const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index c358ada0d3..a8bba9491e 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -5,7 +5,7 @@ // +build mips,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index 1dc1ee16b9..ee9e7e2020 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -5,7 +5,7 @@ // +build mips64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index 3ae187dd93..ba4b288a3c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -5,7 +5,7 @@ // +build mips64le,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index 39895f0dd1..bc93afc367 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -5,7 +5,7 @@ // +build mipsle,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go index a98a45537b..9295e69478 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go @@ -5,7 +5,7 @@ // +build ppc,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index 0a8fbbffaa..1fa081c9a6 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -5,7 +5,7 @@ // +build ppc64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index cb835a1442..74b3211494 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -5,7 +5,7 @@ // +build ppc64le,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go index 73cf6554b0..c91c8ac5b0 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -5,7 +5,7 @@ // +build riscv64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index 04b6dfaf5f..b66bf22289 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -5,7 +5,7 @@ // +build s390x,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/unix/_const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go index 8c87d979d4..f7fb149b0c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go @@ -5,7 +5,7 @@ // +build sparc64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go index 4f5da1f54f..93edda4c49 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go @@ -1,4 +1,4 @@ -// Code generated by mkmerge.go; DO NOT EDIT. +// Code generated by mkmerge; DO NOT EDIT. //go:build linux // +build linux @@ -409,6 +409,21 @@ func mount(source string, target string, fstype string, flags uintptr, data *byt // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func mountSetattr(dirfd int, pathname string, flags uint, attr *MountAttr, size uintptr) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(pathname) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_MOUNT_SETATTR, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(unsafe.Pointer(attr)), uintptr(size), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Acct(path string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go index 620a6702fe..37b521436b 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -1,4 +1,4 @@ -// Code generated by mkmerge.go; DO NOT EDIT. +// Code generated by mkmerge; DO NOT EDIT. //go:build linux // +build linux @@ -743,6 +743,8 @@ const ( AT_STATX_FORCE_SYNC = 0x2000 AT_STATX_DONT_SYNC = 0x4000 + AT_RECURSIVE = 0x8000 + AT_SYMLINK_FOLLOW = 0x400 AT_SYMLINK_NOFOLLOW = 0x100 @@ -3959,3 +3961,10 @@ const ( SHM_RDONLY = 0x1000 SHM_RND = 0x2000 ) + +type MountAttr struct { + Attr_set uint64 + Attr_clr uint64 + Propagation uint64 + Userns_fd uint64 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index eeeb9aa39a..bea2549455 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m32 /build/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m32 /build/unix/linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index d30e1155cc..b8c8f28943 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m64 /build/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m64 /build/unix/linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index 69d0297520..4db4430163 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index 28a0455bc9..3ebcad8a88 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/unix/linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index 64a845483d..3eb33e48ab 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index a1b7dee412..79a9446725 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips64 && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index 936fa6a266..8f4b107cad 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips64le && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index 5dd546fbf0..e4eb217981 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mipsle && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go index 947b32e434..d5b21f0f7d 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index 2a606151b0..5188d142b9 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64 && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index d0d735d02c..de4dd4c736 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64le && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go index 95e3d6d06f..dccbf9b060 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build riscv64 && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index cccf1ef26a..6358806106 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/unix/linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build s390x && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go index 44fcbe4e9a..765edc13ff 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build sparc64 && linux diff --git a/src/cmd/vendor/golang.org/x/sys/windows/mksyscall.go b/src/cmd/vendor/golang.org/x/sys/windows/mksyscall.go index 6102910989..8563f79c57 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/mksyscall.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/mksyscall.go @@ -7,4 +7,4 @@ package windows -//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go eventlog.go service.go syscall_windows.go security_windows.go +//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go eventlog.go service.go syscall_windows.go security_windows.go setupapi_windows.go diff --git a/src/cmd/vendor/golang.org/x/sys/windows/setupapi_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/setupapi_windows.go new file mode 100644 index 0000000000..14027da3f3 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/sys/windows/setupapi_windows.go @@ -0,0 +1,1425 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package windows + +import ( + "encoding/binary" + "errors" + "fmt" + "runtime" + "strings" + "syscall" + "unsafe" +) + +// This file contains functions that wrap SetupAPI.dll and CfgMgr32.dll, +// core system functions for managing hardware devices, drivers, and the PnP tree. +// Information about these APIs can be found at: +// https://docs.microsoft.com/en-us/windows-hardware/drivers/install/setupapi +// https://docs.microsoft.com/en-us/windows/win32/devinst/cfgmgr32- + +const ( + ERROR_EXPECTED_SECTION_NAME Errno = 0x20000000 | 0xC0000000 | 0 + ERROR_BAD_SECTION_NAME_LINE Errno = 0x20000000 | 0xC0000000 | 1 + ERROR_SECTION_NAME_TOO_LONG Errno = 0x20000000 | 0xC0000000 | 2 + ERROR_GENERAL_SYNTAX Errno = 0x20000000 | 0xC0000000 | 3 + ERROR_WRONG_INF_STYLE Errno = 0x20000000 | 0xC0000000 | 0x100 + ERROR_SECTION_NOT_FOUND Errno = 0x20000000 | 0xC0000000 | 0x101 + ERROR_LINE_NOT_FOUND Errno = 0x20000000 | 0xC0000000 | 0x102 + ERROR_NO_BACKUP Errno = 0x20000000 | 0xC0000000 | 0x103 + ERROR_NO_ASSOCIATED_CLASS Errno = 0x20000000 | 0xC0000000 | 0x200 + ERROR_CLASS_MISMATCH Errno = 0x20000000 | 0xC0000000 | 0x201 + ERROR_DUPLICATE_FOUND Errno = 0x20000000 | 0xC0000000 | 0x202 + ERROR_NO_DRIVER_SELECTED Errno = 0x20000000 | 0xC0000000 | 0x203 + ERROR_KEY_DOES_NOT_EXIST Errno = 0x20000000 | 0xC0000000 | 0x204 + ERROR_INVALID_DEVINST_NAME Errno = 0x20000000 | 0xC0000000 | 0x205 + ERROR_INVALID_CLASS Errno = 0x20000000 | 0xC0000000 | 0x206 + ERROR_DEVINST_ALREADY_EXISTS Errno = 0x20000000 | 0xC0000000 | 0x207 + ERROR_DEVINFO_NOT_REGISTERED Errno = 0x20000000 | 0xC0000000 | 0x208 + ERROR_INVALID_REG_PROPERTY Errno = 0x20000000 | 0xC0000000 | 0x209 + ERROR_NO_INF Errno = 0x20000000 | 0xC0000000 | 0x20A + ERROR_NO_SUCH_DEVINST Errno = 0x20000000 | 0xC0000000 | 0x20B + ERROR_CANT_LOAD_CLASS_ICON Errno = 0x20000000 | 0xC0000000 | 0x20C + ERROR_INVALID_CLASS_INSTALLER Errno = 0x20000000 | 0xC0000000 | 0x20D + ERROR_DI_DO_DEFAULT Errno = 0x20000000 | 0xC0000000 | 0x20E + ERROR_DI_NOFILECOPY Errno = 0x20000000 | 0xC0000000 | 0x20F + ERROR_INVALID_HWPROFILE Errno = 0x20000000 | 0xC0000000 | 0x210 + ERROR_NO_DEVICE_SELECTED Errno = 0x20000000 | 0xC0000000 | 0x211 + ERROR_DEVINFO_LIST_LOCKED Errno = 0x20000000 | 0xC0000000 | 0x212 + ERROR_DEVINFO_DATA_LOCKED Errno = 0x20000000 | 0xC0000000 | 0x213 + ERROR_DI_BAD_PATH Errno = 0x20000000 | 0xC0000000 | 0x214 + ERROR_NO_CLASSINSTALL_PARAMS Errno = 0x20000000 | 0xC0000000 | 0x215 + ERROR_FILEQUEUE_LOCKED Errno = 0x20000000 | 0xC0000000 | 0x216 + ERROR_BAD_SERVICE_INSTALLSECT Errno = 0x20000000 | 0xC0000000 | 0x217 + ERROR_NO_CLASS_DRIVER_LIST Errno = 0x20000000 | 0xC0000000 | 0x218 + ERROR_NO_ASSOCIATED_SERVICE Errno = 0x20000000 | 0xC0000000 | 0x219 + ERROR_NO_DEFAULT_DEVICE_INTERFACE Errno = 0x20000000 | 0xC0000000 | 0x21A + ERROR_DEVICE_INTERFACE_ACTIVE Errno = 0x20000000 | 0xC0000000 | 0x21B + ERROR_DEVICE_INTERFACE_REMOVED Errno = 0x20000000 | 0xC0000000 | 0x21C + ERROR_BAD_INTERFACE_INSTALLSECT Errno = 0x20000000 | 0xC0000000 | 0x21D + ERROR_NO_SUCH_INTERFACE_CLASS Errno = 0x20000000 | 0xC0000000 | 0x21E + ERROR_INVALID_REFERENCE_STRING Errno = 0x20000000 | 0xC0000000 | 0x21F + ERROR_INVALID_MACHINENAME Errno = 0x20000000 | 0xC0000000 | 0x220 + ERROR_REMOTE_COMM_FAILURE Errno = 0x20000000 | 0xC0000000 | 0x221 + ERROR_MACHINE_UNAVAILABLE Errno = 0x20000000 | 0xC0000000 | 0x222 + ERROR_NO_CONFIGMGR_SERVICES Errno = 0x20000000 | 0xC0000000 | 0x223 + ERROR_INVALID_PROPPAGE_PROVIDER Errno = 0x20000000 | 0xC0000000 | 0x224 + ERROR_NO_SUCH_DEVICE_INTERFACE Errno = 0x20000000 | 0xC0000000 | 0x225 + ERROR_DI_POSTPROCESSING_REQUIRED Errno = 0x20000000 | 0xC0000000 | 0x226 + ERROR_INVALID_COINSTALLER Errno = 0x20000000 | 0xC0000000 | 0x227 + ERROR_NO_COMPAT_DRIVERS Errno = 0x20000000 | 0xC0000000 | 0x228 + ERROR_NO_DEVICE_ICON Errno = 0x20000000 | 0xC0000000 | 0x229 + ERROR_INVALID_INF_LOGCONFIG Errno = 0x20000000 | 0xC0000000 | 0x22A + ERROR_DI_DONT_INSTALL Errno = 0x20000000 | 0xC0000000 | 0x22B + ERROR_INVALID_FILTER_DRIVER Errno = 0x20000000 | 0xC0000000 | 0x22C + ERROR_NON_WINDOWS_NT_DRIVER Errno = 0x20000000 | 0xC0000000 | 0x22D + ERROR_NON_WINDOWS_DRIVER Errno = 0x20000000 | 0xC0000000 | 0x22E + ERROR_NO_CATALOG_FOR_OEM_INF Errno = 0x20000000 | 0xC0000000 | 0x22F + ERROR_DEVINSTALL_QUEUE_NONNATIVE Errno = 0x20000000 | 0xC0000000 | 0x230 + ERROR_NOT_DISABLEABLE Errno = 0x20000000 | 0xC0000000 | 0x231 + ERROR_CANT_REMOVE_DEVINST Errno = 0x20000000 | 0xC0000000 | 0x232 + ERROR_INVALID_TARGET Errno = 0x20000000 | 0xC0000000 | 0x233 + ERROR_DRIVER_NONNATIVE Errno = 0x20000000 | 0xC0000000 | 0x234 + ERROR_IN_WOW64 Errno = 0x20000000 | 0xC0000000 | 0x235 + ERROR_SET_SYSTEM_RESTORE_POINT Errno = 0x20000000 | 0xC0000000 | 0x236 + ERROR_SCE_DISABLED Errno = 0x20000000 | 0xC0000000 | 0x238 + ERROR_UNKNOWN_EXCEPTION Errno = 0x20000000 | 0xC0000000 | 0x239 + ERROR_PNP_REGISTRY_ERROR Errno = 0x20000000 | 0xC0000000 | 0x23A + ERROR_REMOTE_REQUEST_UNSUPPORTED Errno = 0x20000000 | 0xC0000000 | 0x23B + ERROR_NOT_AN_INSTALLED_OEM_INF Errno = 0x20000000 | 0xC0000000 | 0x23C + ERROR_INF_IN_USE_BY_DEVICES Errno = 0x20000000 | 0xC0000000 | 0x23D + ERROR_DI_FUNCTION_OBSOLETE Errno = 0x20000000 | 0xC0000000 | 0x23E + ERROR_NO_AUTHENTICODE_CATALOG Errno = 0x20000000 | 0xC0000000 | 0x23F + ERROR_AUTHENTICODE_DISALLOWED Errno = 0x20000000 | 0xC0000000 | 0x240 + ERROR_AUTHENTICODE_TRUSTED_PUBLISHER Errno = 0x20000000 | 0xC0000000 | 0x241 + ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED Errno = 0x20000000 | 0xC0000000 | 0x242 + ERROR_AUTHENTICODE_PUBLISHER_NOT_TRUSTED Errno = 0x20000000 | 0xC0000000 | 0x243 + ERROR_SIGNATURE_OSATTRIBUTE_MISMATCH Errno = 0x20000000 | 0xC0000000 | 0x244 + ERROR_ONLY_VALIDATE_VIA_AUTHENTICODE Errno = 0x20000000 | 0xC0000000 | 0x245 + ERROR_DEVICE_INSTALLER_NOT_READY Errno = 0x20000000 | 0xC0000000 | 0x246 + ERROR_DRIVER_STORE_ADD_FAILED Errno = 0x20000000 | 0xC0000000 | 0x247 + ERROR_DEVICE_INSTALL_BLOCKED Errno = 0x20000000 | 0xC0000000 | 0x248 + ERROR_DRIVER_INSTALL_BLOCKED Errno = 0x20000000 | 0xC0000000 | 0x249 + ERROR_WRONG_INF_TYPE Errno = 0x20000000 | 0xC0000000 | 0x24A + ERROR_FILE_HASH_NOT_IN_CATALOG Errno = 0x20000000 | 0xC0000000 | 0x24B + ERROR_DRIVER_STORE_DELETE_FAILED Errno = 0x20000000 | 0xC0000000 | 0x24C + ERROR_UNRECOVERABLE_STACK_OVERFLOW Errno = 0x20000000 | 0xC0000000 | 0x300 + EXCEPTION_SPAPI_UNRECOVERABLE_STACK_OVERFLOW Errno = ERROR_UNRECOVERABLE_STACK_OVERFLOW + ERROR_NO_DEFAULT_INTERFACE_DEVICE Errno = ERROR_NO_DEFAULT_DEVICE_INTERFACE + ERROR_INTERFACE_DEVICE_ACTIVE Errno = ERROR_DEVICE_INTERFACE_ACTIVE + ERROR_INTERFACE_DEVICE_REMOVED Errno = ERROR_DEVICE_INTERFACE_REMOVED + ERROR_NO_SUCH_INTERFACE_DEVICE Errno = ERROR_NO_SUCH_DEVICE_INTERFACE +) + +const ( + MAX_DEVICE_ID_LEN = 200 + MAX_DEVNODE_ID_LEN = MAX_DEVICE_ID_LEN + MAX_GUID_STRING_LEN = 39 // 38 chars + terminator null + MAX_CLASS_NAME_LEN = 32 + MAX_PROFILE_LEN = 80 + MAX_CONFIG_VALUE = 9999 + MAX_INSTANCE_VALUE = 9999 + CONFIGMG_VERSION = 0x0400 +) + +// Maximum string length constants +const ( + LINE_LEN = 256 // Windows 9x-compatible maximum for displayable strings coming from a device INF. + MAX_INF_STRING_LENGTH = 4096 // Actual maximum size of an INF string (including string substitutions). + MAX_INF_SECTION_NAME_LENGTH = 255 // For Windows 9x compatibility, INF section names should be constrained to 32 characters. + MAX_TITLE_LEN = 60 + MAX_INSTRUCTION_LEN = 256 + MAX_LABEL_LEN = 30 + MAX_SERVICE_NAME_LEN = 256 + MAX_SUBTITLE_LEN = 256 +) + +const ( + // SP_MAX_MACHINENAME_LENGTH defines maximum length of a machine name in the format expected by ConfigMgr32 CM_Connect_Machine (i.e., "\\\\MachineName\0"). + SP_MAX_MACHINENAME_LENGTH = MAX_PATH + 3 +) + +// HSPFILEQ is type for setup file queue +type HSPFILEQ uintptr + +// DevInfo holds reference to device information set +type DevInfo Handle + +// DEVINST is a handle usually recognized by cfgmgr32 APIs +type DEVINST uint32 + +// DevInfoData is a device information structure (references a device instance that is a member of a device information set) +type DevInfoData struct { + size uint32 + ClassGUID GUID + DevInst DEVINST + _ uintptr +} + +// DevInfoListDetailData is a structure for detailed information on a device information set (used for SetupDiGetDeviceInfoListDetail which supersedes the functionality of SetupDiGetDeviceInfoListClass). +type DevInfoListDetailData struct { + size uint32 // Use unsafeSizeOf method + ClassGUID GUID + RemoteMachineHandle Handle + remoteMachineName [SP_MAX_MACHINENAME_LENGTH]uint16 +} + +func (*DevInfoListDetailData) unsafeSizeOf() uint32 { + if unsafe.Sizeof(uintptr(0)) == 4 { + // Windows declares this with pshpack1.h + return uint32(unsafe.Offsetof(DevInfoListDetailData{}.remoteMachineName) + unsafe.Sizeof(DevInfoListDetailData{}.remoteMachineName)) + } + return uint32(unsafe.Sizeof(DevInfoListDetailData{})) +} + +func (data *DevInfoListDetailData) RemoteMachineName() string { + return UTF16ToString(data.remoteMachineName[:]) +} + +func (data *DevInfoListDetailData) SetRemoteMachineName(remoteMachineName string) error { + str, err := UTF16FromString(remoteMachineName) + if err != nil { + return err + } + copy(data.remoteMachineName[:], str) + return nil +} + +// DI_FUNCTION is function type for device installer +type DI_FUNCTION uint32 + +const ( + DIF_SELECTDEVICE DI_FUNCTION = 0x00000001 + DIF_INSTALLDEVICE DI_FUNCTION = 0x00000002 + DIF_ASSIGNRESOURCES DI_FUNCTION = 0x00000003 + DIF_PROPERTIES DI_FUNCTION = 0x00000004 + DIF_REMOVE DI_FUNCTION = 0x00000005 + DIF_FIRSTTIMESETUP DI_FUNCTION = 0x00000006 + DIF_FOUNDDEVICE DI_FUNCTION = 0x00000007 + DIF_SELECTCLASSDRIVERS DI_FUNCTION = 0x00000008 + DIF_VALIDATECLASSDRIVERS DI_FUNCTION = 0x00000009 + DIF_INSTALLCLASSDRIVERS DI_FUNCTION = 0x0000000A + DIF_CALCDISKSPACE DI_FUNCTION = 0x0000000B + DIF_DESTROYPRIVATEDATA DI_FUNCTION = 0x0000000C + DIF_VALIDATEDRIVER DI_FUNCTION = 0x0000000D + DIF_DETECT DI_FUNCTION = 0x0000000F + DIF_INSTALLWIZARD DI_FUNCTION = 0x00000010 + DIF_DESTROYWIZARDDATA DI_FUNCTION = 0x00000011 + DIF_PROPERTYCHANGE DI_FUNCTION = 0x00000012 + DIF_ENABLECLASS DI_FUNCTION = 0x00000013 + DIF_DETECTVERIFY DI_FUNCTION = 0x00000014 + DIF_INSTALLDEVICEFILES DI_FUNCTION = 0x00000015 + DIF_UNREMOVE DI_FUNCTION = 0x00000016 + DIF_SELECTBESTCOMPATDRV DI_FUNCTION = 0x00000017 + DIF_ALLOW_INSTALL DI_FUNCTION = 0x00000018 + DIF_REGISTERDEVICE DI_FUNCTION = 0x00000019 + DIF_NEWDEVICEWIZARD_PRESELECT DI_FUNCTION = 0x0000001A + DIF_NEWDEVICEWIZARD_SELECT DI_FUNCTION = 0x0000001B + DIF_NEWDEVICEWIZARD_PREANALYZE DI_FUNCTION = 0x0000001C + DIF_NEWDEVICEWIZARD_POSTANALYZE DI_FUNCTION = 0x0000001D + DIF_NEWDEVICEWIZARD_FINISHINSTALL DI_FUNCTION = 0x0000001E + DIF_INSTALLINTERFACES DI_FUNCTION = 0x00000020 + DIF_DETECTCANCEL DI_FUNCTION = 0x00000021 + DIF_REGISTER_COINSTALLERS DI_FUNCTION = 0x00000022 + DIF_ADDPROPERTYPAGE_ADVANCED DI_FUNCTION = 0x00000023 + DIF_ADDPROPERTYPAGE_BASIC DI_FUNCTION = 0x00000024 + DIF_TROUBLESHOOTER DI_FUNCTION = 0x00000026 + DIF_POWERMESSAGEWAKE DI_FUNCTION = 0x00000027 + DIF_ADDREMOTEPROPERTYPAGE_ADVANCED DI_FUNCTION = 0x00000028 + DIF_UPDATEDRIVER_UI DI_FUNCTION = 0x00000029 + DIF_FINISHINSTALL_ACTION DI_FUNCTION = 0x0000002A +) + +// DevInstallParams is device installation parameters structure (associated with a particular device information element, or globally with a device information set) +type DevInstallParams struct { + size uint32 + Flags DI_FLAGS + FlagsEx DI_FLAGSEX + hwndParent uintptr + InstallMsgHandler uintptr + InstallMsgHandlerContext uintptr + FileQueue HSPFILEQ + _ uintptr + _ uint32 + driverPath [MAX_PATH]uint16 +} + +func (params *DevInstallParams) DriverPath() string { + return UTF16ToString(params.driverPath[:]) +} + +func (params *DevInstallParams) SetDriverPath(driverPath string) error { + str, err := UTF16FromString(driverPath) + if err != nil { + return err + } + copy(params.driverPath[:], str) + return nil +} + +// DI_FLAGS is SP_DEVINSTALL_PARAMS.Flags values +type DI_FLAGS uint32 + +const ( + // Flags for choosing a device + DI_SHOWOEM DI_FLAGS = 0x00000001 // support Other... button + DI_SHOWCOMPAT DI_FLAGS = 0x00000002 // show compatibility list + DI_SHOWCLASS DI_FLAGS = 0x00000004 // show class list + DI_SHOWALL DI_FLAGS = 0x00000007 // both class & compat list shown + DI_NOVCP DI_FLAGS = 0x00000008 // don't create a new copy queue--use caller-supplied FileQueue + DI_DIDCOMPAT DI_FLAGS = 0x00000010 // Searched for compatible devices + DI_DIDCLASS DI_FLAGS = 0x00000020 // Searched for class devices + DI_AUTOASSIGNRES DI_FLAGS = 0x00000040 // No UI for resources if possible + + // Flags returned by DiInstallDevice to indicate need to reboot/restart + DI_NEEDRESTART DI_FLAGS = 0x00000080 // Reboot required to take effect + DI_NEEDREBOOT DI_FLAGS = 0x00000100 // "" + + // Flags for device installation + DI_NOBROWSE DI_FLAGS = 0x00000200 // no Browse... in InsertDisk + + // Flags set by DiBuildDriverInfoList + DI_MULTMFGS DI_FLAGS = 0x00000400 // Set if multiple manufacturers in class driver list + + // Flag indicates that device is disabled + DI_DISABLED DI_FLAGS = 0x00000800 // Set if device disabled + + // Flags for Device/Class Properties + DI_GENERALPAGE_ADDED DI_FLAGS = 0x00001000 + DI_RESOURCEPAGE_ADDED DI_FLAGS = 0x00002000 + + // Flag to indicate the setting properties for this Device (or class) caused a change so the Dev Mgr UI probably needs to be updated. + DI_PROPERTIES_CHANGE DI_FLAGS = 0x00004000 + + // Flag to indicate that the sorting from the INF file should be used. + DI_INF_IS_SORTED DI_FLAGS = 0x00008000 + + // Flag to indicate that only the the INF specified by SP_DEVINSTALL_PARAMS.DriverPath should be searched. + DI_ENUMSINGLEINF DI_FLAGS = 0x00010000 + + // Flag that prevents ConfigMgr from removing/re-enumerating devices during device + // registration, installation, and deletion. + DI_DONOTCALLCONFIGMG DI_FLAGS = 0x00020000 + + // The following flag can be used to install a device disabled + DI_INSTALLDISABLED DI_FLAGS = 0x00040000 + + // Flag that causes SetupDiBuildDriverInfoList to build a device's compatible driver + // list from its existing class driver list, instead of the normal INF search. + DI_COMPAT_FROM_CLASS DI_FLAGS = 0x00080000 + + // This flag is set if the Class Install params should be used. + DI_CLASSINSTALLPARAMS DI_FLAGS = 0x00100000 + + // This flag is set if the caller of DiCallClassInstaller does NOT want the internal default action performed if the Class installer returns ERROR_DI_DO_DEFAULT. + DI_NODI_DEFAULTACTION DI_FLAGS = 0x00200000 + + // Flags for device installation + DI_QUIETINSTALL DI_FLAGS = 0x00800000 // don't confuse the user with questions or excess info + DI_NOFILECOPY DI_FLAGS = 0x01000000 // No file Copy necessary + DI_FORCECOPY DI_FLAGS = 0x02000000 // Force files to be copied from install path + DI_DRIVERPAGE_ADDED DI_FLAGS = 0x04000000 // Prop provider added Driver page. + DI_USECI_SELECTSTRINGS DI_FLAGS = 0x08000000 // Use Class Installer Provided strings in the Select Device Dlg + DI_OVERRIDE_INFFLAGS DI_FLAGS = 0x10000000 // Override INF flags + DI_PROPS_NOCHANGEUSAGE DI_FLAGS = 0x20000000 // No Enable/Disable in General Props + + DI_NOSELECTICONS DI_FLAGS = 0x40000000 // No small icons in select device dialogs + + DI_NOWRITE_IDS DI_FLAGS = 0x80000000 // Don't write HW & Compat IDs on install +) + +// DI_FLAGSEX is SP_DEVINSTALL_PARAMS.FlagsEx values +type DI_FLAGSEX uint32 + +const ( + DI_FLAGSEX_CI_FAILED DI_FLAGSEX = 0x00000004 // Failed to Load/Call class installer + DI_FLAGSEX_FINISHINSTALL_ACTION DI_FLAGSEX = 0x00000008 // Class/co-installer wants to get a DIF_FINISH_INSTALL action in client context. + DI_FLAGSEX_DIDINFOLIST DI_FLAGSEX = 0x00000010 // Did the Class Info List + DI_FLAGSEX_DIDCOMPATINFO DI_FLAGSEX = 0x00000020 // Did the Compat Info List + DI_FLAGSEX_FILTERCLASSES DI_FLAGSEX = 0x00000040 + DI_FLAGSEX_SETFAILEDINSTALL DI_FLAGSEX = 0x00000080 + DI_FLAGSEX_DEVICECHANGE DI_FLAGSEX = 0x00000100 + DI_FLAGSEX_ALWAYSWRITEIDS DI_FLAGSEX = 0x00000200 + DI_FLAGSEX_PROPCHANGE_PENDING DI_FLAGSEX = 0x00000400 // One or more device property sheets have had changes made to them, and need to have a DIF_PROPERTYCHANGE occur. + DI_FLAGSEX_ALLOWEXCLUDEDDRVS DI_FLAGSEX = 0x00000800 + DI_FLAGSEX_NOUIONQUERYREMOVE DI_FLAGSEX = 0x00001000 + DI_FLAGSEX_USECLASSFORCOMPAT DI_FLAGSEX = 0x00002000 // Use the device's class when building compat drv list. (Ignored if DI_COMPAT_FROM_CLASS flag is specified.) + DI_FLAGSEX_NO_DRVREG_MODIFY DI_FLAGSEX = 0x00008000 // Don't run AddReg and DelReg for device's software (driver) key. + DI_FLAGSEX_IN_SYSTEM_SETUP DI_FLAGSEX = 0x00010000 // Installation is occurring during initial system setup. + DI_FLAGSEX_INET_DRIVER DI_FLAGSEX = 0x00020000 // Driver came from Windows Update + DI_FLAGSEX_APPENDDRIVERLIST DI_FLAGSEX = 0x00040000 // Cause SetupDiBuildDriverInfoList to append a new driver list to an existing list. + DI_FLAGSEX_PREINSTALLBACKUP DI_FLAGSEX = 0x00080000 // not used + DI_FLAGSEX_BACKUPONREPLACE DI_FLAGSEX = 0x00100000 // not used + DI_FLAGSEX_DRIVERLIST_FROM_URL DI_FLAGSEX = 0x00200000 // build driver list from INF(s) retrieved from URL specified in SP_DEVINSTALL_PARAMS.DriverPath (empty string means Windows Update website) + DI_FLAGSEX_EXCLUDE_OLD_INET_DRIVERS DI_FLAGSEX = 0x00800000 // Don't include old Internet drivers when building a driver list. Ignored on Windows Vista and later. + DI_FLAGSEX_POWERPAGE_ADDED DI_FLAGSEX = 0x01000000 // class installer added their own power page + DI_FLAGSEX_FILTERSIMILARDRIVERS DI_FLAGSEX = 0x02000000 // only include similar drivers in class list + DI_FLAGSEX_INSTALLEDDRIVER DI_FLAGSEX = 0x04000000 // only add the installed driver to the class or compat driver list. Used in calls to SetupDiBuildDriverInfoList + DI_FLAGSEX_NO_CLASSLIST_NODE_MERGE DI_FLAGSEX = 0x08000000 // Don't remove identical driver nodes from the class list + DI_FLAGSEX_ALTPLATFORM_DRVSEARCH DI_FLAGSEX = 0x10000000 // Build driver list based on alternate platform information specified in associated file queue + DI_FLAGSEX_RESTART_DEVICE_ONLY DI_FLAGSEX = 0x20000000 // only restart the device drivers are being installed on as opposed to restarting all devices using those drivers. + DI_FLAGSEX_RECURSIVESEARCH DI_FLAGSEX = 0x40000000 // Tell SetupDiBuildDriverInfoList to do a recursive search + DI_FLAGSEX_SEARCH_PUBLISHED_INFS DI_FLAGSEX = 0x80000000 // Tell SetupDiBuildDriverInfoList to do a "published INF" search +) + +// ClassInstallHeader is the first member of any class install parameters structure. It contains the device installation request code that defines the format of the rest of the install parameters structure. +type ClassInstallHeader struct { + size uint32 + InstallFunction DI_FUNCTION +} + +func MakeClassInstallHeader(installFunction DI_FUNCTION) *ClassInstallHeader { + hdr := &ClassInstallHeader{InstallFunction: installFunction} + hdr.size = uint32(unsafe.Sizeof(*hdr)) + return hdr +} + +// DICS_STATE specifies values indicating a change in a device's state +type DICS_STATE uint32 + +const ( + DICS_ENABLE DICS_STATE = 0x00000001 // The device is being enabled. + DICS_DISABLE DICS_STATE = 0x00000002 // The device is being disabled. + DICS_PROPCHANGE DICS_STATE = 0x00000003 // The properties of the device have changed. + DICS_START DICS_STATE = 0x00000004 // The device is being started (if the request is for the currently active hardware profile). + DICS_STOP DICS_STATE = 0x00000005 // The device is being stopped. The driver stack will be unloaded and the CSCONFIGFLAG_DO_NOT_START flag will be set for the device. +) + +// DICS_FLAG specifies the scope of a device property change +type DICS_FLAG uint32 + +const ( + DICS_FLAG_GLOBAL DICS_FLAG = 0x00000001 // make change in all hardware profiles + DICS_FLAG_CONFIGSPECIFIC DICS_FLAG = 0x00000002 // make change in specified profile only + DICS_FLAG_CONFIGGENERAL DICS_FLAG = 0x00000004 // 1 or more hardware profile-specific changes to follow (obsolete) +) + +// PropChangeParams is a structure corresponding to a DIF_PROPERTYCHANGE install function. +type PropChangeParams struct { + ClassInstallHeader ClassInstallHeader + StateChange DICS_STATE + Scope DICS_FLAG + HwProfile uint32 +} + +// DI_REMOVEDEVICE specifies the scope of the device removal +type DI_REMOVEDEVICE uint32 + +const ( + DI_REMOVEDEVICE_GLOBAL DI_REMOVEDEVICE = 0x00000001 // Make this change in all hardware profiles. Remove information about the device from the registry. + DI_REMOVEDEVICE_CONFIGSPECIFIC DI_REMOVEDEVICE = 0x00000002 // Make this change to only the hardware profile specified by HwProfile. this flag only applies to root-enumerated devices. When Windows removes the device from the last hardware profile in which it was configured, Windows performs a global removal. +) + +// RemoveDeviceParams is a structure corresponding to a DIF_REMOVE install function. +type RemoveDeviceParams struct { + ClassInstallHeader ClassInstallHeader + Scope DI_REMOVEDEVICE + HwProfile uint32 +} + +// DrvInfoData is driver information structure (member of a driver info list that may be associated with a particular device instance, or (globally) with a device information set) +type DrvInfoData struct { + size uint32 + DriverType uint32 + _ uintptr + description [LINE_LEN]uint16 + mfgName [LINE_LEN]uint16 + providerName [LINE_LEN]uint16 + DriverDate Filetime + DriverVersion uint64 +} + +func (data *DrvInfoData) Description() string { + return UTF16ToString(data.description[:]) +} + +func (data *DrvInfoData) SetDescription(description string) error { + str, err := UTF16FromString(description) + if err != nil { + return err + } + copy(data.description[:], str) + return nil +} + +func (data *DrvInfoData) MfgName() string { + return UTF16ToString(data.mfgName[:]) +} + +func (data *DrvInfoData) SetMfgName(mfgName string) error { + str, err := UTF16FromString(mfgName) + if err != nil { + return err + } + copy(data.mfgName[:], str) + return nil +} + +func (data *DrvInfoData) ProviderName() string { + return UTF16ToString(data.providerName[:]) +} + +func (data *DrvInfoData) SetProviderName(providerName string) error { + str, err := UTF16FromString(providerName) + if err != nil { + return err + } + copy(data.providerName[:], str) + return nil +} + +// IsNewer method returns true if DrvInfoData date and version is newer than supplied parameters. +func (data *DrvInfoData) IsNewer(driverDate Filetime, driverVersion uint64) bool { + if data.DriverDate.HighDateTime > driverDate.HighDateTime { + return true + } + if data.DriverDate.HighDateTime < driverDate.HighDateTime { + return false + } + + if data.DriverDate.LowDateTime > driverDate.LowDateTime { + return true + } + if data.DriverDate.LowDateTime < driverDate.LowDateTime { + return false + } + + if data.DriverVersion > driverVersion { + return true + } + if data.DriverVersion < driverVersion { + return false + } + + return false +} + +// DrvInfoDetailData is driver information details structure (provides detailed information about a particular driver information structure) +type DrvInfoDetailData struct { + size uint32 // Use unsafeSizeOf method + InfDate Filetime + compatIDsOffset uint32 + compatIDsLength uint32 + _ uintptr + sectionName [LINE_LEN]uint16 + infFileName [MAX_PATH]uint16 + drvDescription [LINE_LEN]uint16 + hardwareID [1]uint16 +} + +func (*DrvInfoDetailData) unsafeSizeOf() uint32 { + if unsafe.Sizeof(uintptr(0)) == 4 { + // Windows declares this with pshpack1.h + return uint32(unsafe.Offsetof(DrvInfoDetailData{}.hardwareID) + unsafe.Sizeof(DrvInfoDetailData{}.hardwareID)) + } + return uint32(unsafe.Sizeof(DrvInfoDetailData{})) +} + +func (data *DrvInfoDetailData) SectionName() string { + return UTF16ToString(data.sectionName[:]) +} + +func (data *DrvInfoDetailData) InfFileName() string { + return UTF16ToString(data.infFileName[:]) +} + +func (data *DrvInfoDetailData) DrvDescription() string { + return UTF16ToString(data.drvDescription[:]) +} + +func (data *DrvInfoDetailData) HardwareID() string { + if data.compatIDsOffset > 1 { + bufW := data.getBuf() + return UTF16ToString(bufW[:wcslen(bufW)]) + } + + return "" +} + +func (data *DrvInfoDetailData) CompatIDs() []string { + a := make([]string, 0) + + if data.compatIDsLength > 0 { + bufW := data.getBuf() + bufW = bufW[data.compatIDsOffset : data.compatIDsOffset+data.compatIDsLength] + for i := 0; i < len(bufW); { + j := i + wcslen(bufW[i:]) + if i < j { + a = append(a, UTF16ToString(bufW[i:j])) + } + i = j + 1 + } + } + + return a +} + +func (data *DrvInfoDetailData) getBuf() []uint16 { + len := (data.size - uint32(unsafe.Offsetof(data.hardwareID))) / 2 + sl := struct { + addr *uint16 + len int + cap int + }{&data.hardwareID[0], int(len), int(len)} + return *(*[]uint16)(unsafe.Pointer(&sl)) +} + +// IsCompatible method tests if given hardware ID matches the driver or is listed on the compatible ID list. +func (data *DrvInfoDetailData) IsCompatible(hwid string) bool { + hwidLC := strings.ToLower(hwid) + if strings.ToLower(data.HardwareID()) == hwidLC { + return true + } + a := data.CompatIDs() + for i := range a { + if strings.ToLower(a[i]) == hwidLC { + return true + } + } + + return false +} + +// DICD flags control SetupDiCreateDeviceInfo +type DICD uint32 + +const ( + DICD_GENERATE_ID DICD = 0x00000001 + DICD_INHERIT_CLASSDRVS DICD = 0x00000002 +) + +// SUOI flags control SetupUninstallOEMInf +type SUOI uint32 + +const ( + SUOI_FORCEDELETE SUOI = 0x0001 +) + +// SPDIT flags to distinguish between class drivers and +// device drivers. (Passed in 'DriverType' parameter of +// driver information list APIs) +type SPDIT uint32 + +const ( + SPDIT_NODRIVER SPDIT = 0x00000000 + SPDIT_CLASSDRIVER SPDIT = 0x00000001 + SPDIT_COMPATDRIVER SPDIT = 0x00000002 +) + +// DIGCF flags control what is included in the device information set built by SetupDiGetClassDevs +type DIGCF uint32 + +const ( + DIGCF_DEFAULT DIGCF = 0x00000001 // only valid with DIGCF_DEVICEINTERFACE + DIGCF_PRESENT DIGCF = 0x00000002 + DIGCF_ALLCLASSES DIGCF = 0x00000004 + DIGCF_PROFILE DIGCF = 0x00000008 + DIGCF_DEVICEINTERFACE DIGCF = 0x00000010 +) + +// DIREG specifies values for SetupDiCreateDevRegKey, SetupDiOpenDevRegKey, and SetupDiDeleteDevRegKey. +type DIREG uint32 + +const ( + DIREG_DEV DIREG = 0x00000001 // Open/Create/Delete device key + DIREG_DRV DIREG = 0x00000002 // Open/Create/Delete driver key + DIREG_BOTH DIREG = 0x00000004 // Delete both driver and Device key +) + +// SPDRP specifies device registry property codes +// (Codes marked as read-only (R) may only be used for +// SetupDiGetDeviceRegistryProperty) +// +// These values should cover the same set of registry properties +// as defined by the CM_DRP codes in cfgmgr32.h. +// +// Note that SPDRP codes are zero based while CM_DRP codes are one based! +type SPDRP uint32 + +const ( + SPDRP_DEVICEDESC SPDRP = 0x00000000 // DeviceDesc (R/W) + SPDRP_HARDWAREID SPDRP = 0x00000001 // HardwareID (R/W) + SPDRP_COMPATIBLEIDS SPDRP = 0x00000002 // CompatibleIDs (R/W) + SPDRP_SERVICE SPDRP = 0x00000004 // Service (R/W) + SPDRP_CLASS SPDRP = 0x00000007 // Class (R--tied to ClassGUID) + SPDRP_CLASSGUID SPDRP = 0x00000008 // ClassGUID (R/W) + SPDRP_DRIVER SPDRP = 0x00000009 // Driver (R/W) + SPDRP_CONFIGFLAGS SPDRP = 0x0000000A // ConfigFlags (R/W) + SPDRP_MFG SPDRP = 0x0000000B // Mfg (R/W) + SPDRP_FRIENDLYNAME SPDRP = 0x0000000C // FriendlyName (R/W) + SPDRP_LOCATION_INFORMATION SPDRP = 0x0000000D // LocationInformation (R/W) + SPDRP_PHYSICAL_DEVICE_OBJECT_NAME SPDRP = 0x0000000E // PhysicalDeviceObjectName (R) + SPDRP_CAPABILITIES SPDRP = 0x0000000F // Capabilities (R) + SPDRP_UI_NUMBER SPDRP = 0x00000010 // UiNumber (R) + SPDRP_UPPERFILTERS SPDRP = 0x00000011 // UpperFilters (R/W) + SPDRP_LOWERFILTERS SPDRP = 0x00000012 // LowerFilters (R/W) + SPDRP_BUSTYPEGUID SPDRP = 0x00000013 // BusTypeGUID (R) + SPDRP_LEGACYBUSTYPE SPDRP = 0x00000014 // LegacyBusType (R) + SPDRP_BUSNUMBER SPDRP = 0x00000015 // BusNumber (R) + SPDRP_ENUMERATOR_NAME SPDRP = 0x00000016 // Enumerator Name (R) + SPDRP_SECURITY SPDRP = 0x00000017 // Security (R/W, binary form) + SPDRP_SECURITY_SDS SPDRP = 0x00000018 // Security (W, SDS form) + SPDRP_DEVTYPE SPDRP = 0x00000019 // Device Type (R/W) + SPDRP_EXCLUSIVE SPDRP = 0x0000001A // Device is exclusive-access (R/W) + SPDRP_CHARACTERISTICS SPDRP = 0x0000001B // Device Characteristics (R/W) + SPDRP_ADDRESS SPDRP = 0x0000001C // Device Address (R) + SPDRP_UI_NUMBER_DESC_FORMAT SPDRP = 0x0000001D // UiNumberDescFormat (R/W) + SPDRP_DEVICE_POWER_DATA SPDRP = 0x0000001E // Device Power Data (R) + SPDRP_REMOVAL_POLICY SPDRP = 0x0000001F // Removal Policy (R) + SPDRP_REMOVAL_POLICY_HW_DEFAULT SPDRP = 0x00000020 // Hardware Removal Policy (R) + SPDRP_REMOVAL_POLICY_OVERRIDE SPDRP = 0x00000021 // Removal Policy Override (RW) + SPDRP_INSTALL_STATE SPDRP = 0x00000022 // Device Install State (R) + SPDRP_LOCATION_PATHS SPDRP = 0x00000023 // Device Location Paths (R) + SPDRP_BASE_CONTAINERID SPDRP = 0x00000024 // Base ContainerID (R) + + SPDRP_MAXIMUM_PROPERTY SPDRP = 0x00000025 // Upper bound on ordinals +) + +// DEVPROPTYPE represents the property-data-type identifier that specifies the +// data type of a device property value in the unified device property model. +type DEVPROPTYPE uint32 + +const ( + DEVPROP_TYPEMOD_ARRAY DEVPROPTYPE = 0x00001000 + DEVPROP_TYPEMOD_LIST DEVPROPTYPE = 0x00002000 + + DEVPROP_TYPE_EMPTY DEVPROPTYPE = 0x00000000 + DEVPROP_TYPE_NULL DEVPROPTYPE = 0x00000001 + DEVPROP_TYPE_SBYTE DEVPROPTYPE = 0x00000002 + DEVPROP_TYPE_BYTE DEVPROPTYPE = 0x00000003 + DEVPROP_TYPE_INT16 DEVPROPTYPE = 0x00000004 + DEVPROP_TYPE_UINT16 DEVPROPTYPE = 0x00000005 + DEVPROP_TYPE_INT32 DEVPROPTYPE = 0x00000006 + DEVPROP_TYPE_UINT32 DEVPROPTYPE = 0x00000007 + DEVPROP_TYPE_INT64 DEVPROPTYPE = 0x00000008 + DEVPROP_TYPE_UINT64 DEVPROPTYPE = 0x00000009 + DEVPROP_TYPE_FLOAT DEVPROPTYPE = 0x0000000A + DEVPROP_TYPE_DOUBLE DEVPROPTYPE = 0x0000000B + DEVPROP_TYPE_DECIMAL DEVPROPTYPE = 0x0000000C + DEVPROP_TYPE_GUID DEVPROPTYPE = 0x0000000D + DEVPROP_TYPE_CURRENCY DEVPROPTYPE = 0x0000000E + DEVPROP_TYPE_DATE DEVPROPTYPE = 0x0000000F + DEVPROP_TYPE_FILETIME DEVPROPTYPE = 0x00000010 + DEVPROP_TYPE_BOOLEAN DEVPROPTYPE = 0x00000011 + DEVPROP_TYPE_STRING DEVPROPTYPE = 0x00000012 + DEVPROP_TYPE_STRING_LIST DEVPROPTYPE = DEVPROP_TYPE_STRING | DEVPROP_TYPEMOD_LIST + DEVPROP_TYPE_SECURITY_DESCRIPTOR DEVPROPTYPE = 0x00000013 + DEVPROP_TYPE_SECURITY_DESCRIPTOR_STRING DEVPROPTYPE = 0x00000014 + DEVPROP_TYPE_DEVPROPKEY DEVPROPTYPE = 0x00000015 + DEVPROP_TYPE_DEVPROPTYPE DEVPROPTYPE = 0x00000016 + DEVPROP_TYPE_BINARY DEVPROPTYPE = DEVPROP_TYPE_BYTE | DEVPROP_TYPEMOD_ARRAY + DEVPROP_TYPE_ERROR DEVPROPTYPE = 0x00000017 + DEVPROP_TYPE_NTSTATUS DEVPROPTYPE = 0x00000018 + DEVPROP_TYPE_STRING_INDIRECT DEVPROPTYPE = 0x00000019 + + MAX_DEVPROP_TYPE DEVPROPTYPE = 0x00000019 + MAX_DEVPROP_TYPEMOD DEVPROPTYPE = 0x00002000 + + DEVPROP_MASK_TYPE DEVPROPTYPE = 0x00000FFF + DEVPROP_MASK_TYPEMOD DEVPROPTYPE = 0x0000F000 +) + +// DEVPROPGUID specifies a property category. +type DEVPROPGUID GUID + +// DEVPROPID uniquely identifies the property within the property category. +type DEVPROPID uint32 + +const DEVPROPID_FIRST_USABLE DEVPROPID = 2 + +// DEVPROPKEY represents a device property key for a device property in the +// unified device property model. +type DEVPROPKEY struct { + FmtID DEVPROPGUID + PID DEVPROPID +} + +// CONFIGRET is a return value or error code from cfgmgr32 APIs +type CONFIGRET uint32 + +func (ret CONFIGRET) Error() string { + if win32Error, ok := ret.Unwrap().(Errno); ok { + return fmt.Sprintf("%s (CfgMgr error: 0x%08x)", win32Error.Error(), uint32(ret)) + } + return fmt.Sprintf("CfgMgr error: 0x%08x", uint32(ret)) +} + +func (ret CONFIGRET) Win32Error(defaultError Errno) Errno { + return cm_MapCrToWin32Err(ret, defaultError) +} + +func (ret CONFIGRET) Unwrap() error { + const noMatch = Errno(^uintptr(0)) + win32Error := ret.Win32Error(noMatch) + if win32Error == noMatch { + return nil + } + return win32Error +} + +const ( + CR_SUCCESS CONFIGRET = 0x00000000 + CR_DEFAULT CONFIGRET = 0x00000001 + CR_OUT_OF_MEMORY CONFIGRET = 0x00000002 + CR_INVALID_POINTER CONFIGRET = 0x00000003 + CR_INVALID_FLAG CONFIGRET = 0x00000004 + CR_INVALID_DEVNODE CONFIGRET = 0x00000005 + CR_INVALID_DEVINST = CR_INVALID_DEVNODE + CR_INVALID_RES_DES CONFIGRET = 0x00000006 + CR_INVALID_LOG_CONF CONFIGRET = 0x00000007 + CR_INVALID_ARBITRATOR CONFIGRET = 0x00000008 + CR_INVALID_NODELIST CONFIGRET = 0x00000009 + CR_DEVNODE_HAS_REQS CONFIGRET = 0x0000000A + CR_DEVINST_HAS_REQS = CR_DEVNODE_HAS_REQS + CR_INVALID_RESOURCEID CONFIGRET = 0x0000000B + CR_DLVXD_NOT_FOUND CONFIGRET = 0x0000000C + CR_NO_SUCH_DEVNODE CONFIGRET = 0x0000000D + CR_NO_SUCH_DEVINST = CR_NO_SUCH_DEVNODE + CR_NO_MORE_LOG_CONF CONFIGRET = 0x0000000E + CR_NO_MORE_RES_DES CONFIGRET = 0x0000000F + CR_ALREADY_SUCH_DEVNODE CONFIGRET = 0x00000010 + CR_ALREADY_SUCH_DEVINST = CR_ALREADY_SUCH_DEVNODE + CR_INVALID_RANGE_LIST CONFIGRET = 0x00000011 + CR_INVALID_RANGE CONFIGRET = 0x00000012 + CR_FAILURE CONFIGRET = 0x00000013 + CR_NO_SUCH_LOGICAL_DEV CONFIGRET = 0x00000014 + CR_CREATE_BLOCKED CONFIGRET = 0x00000015 + CR_NOT_SYSTEM_VM CONFIGRET = 0x00000016 + CR_REMOVE_VETOED CONFIGRET = 0x00000017 + CR_APM_VETOED CONFIGRET = 0x00000018 + CR_INVALID_LOAD_TYPE CONFIGRET = 0x00000019 + CR_BUFFER_SMALL CONFIGRET = 0x0000001A + CR_NO_ARBITRATOR CONFIGRET = 0x0000001B + CR_NO_REGISTRY_HANDLE CONFIGRET = 0x0000001C + CR_REGISTRY_ERROR CONFIGRET = 0x0000001D + CR_INVALID_DEVICE_ID CONFIGRET = 0x0000001E + CR_INVALID_DATA CONFIGRET = 0x0000001F + CR_INVALID_API CONFIGRET = 0x00000020 + CR_DEVLOADER_NOT_READY CONFIGRET = 0x00000021 + CR_NEED_RESTART CONFIGRET = 0x00000022 + CR_NO_MORE_HW_PROFILES CONFIGRET = 0x00000023 + CR_DEVICE_NOT_THERE CONFIGRET = 0x00000024 + CR_NO_SUCH_VALUE CONFIGRET = 0x00000025 + CR_WRONG_TYPE CONFIGRET = 0x00000026 + CR_INVALID_PRIORITY CONFIGRET = 0x00000027 + CR_NOT_DISABLEABLE CONFIGRET = 0x00000028 + CR_FREE_RESOURCES CONFIGRET = 0x00000029 + CR_QUERY_VETOED CONFIGRET = 0x0000002A + CR_CANT_SHARE_IRQ CONFIGRET = 0x0000002B + CR_NO_DEPENDENT CONFIGRET = 0x0000002C + CR_SAME_RESOURCES CONFIGRET = 0x0000002D + CR_NO_SUCH_REGISTRY_KEY CONFIGRET = 0x0000002E + CR_INVALID_MACHINENAME CONFIGRET = 0x0000002F + CR_REMOTE_COMM_FAILURE CONFIGRET = 0x00000030 + CR_MACHINE_UNAVAILABLE CONFIGRET = 0x00000031 + CR_NO_CM_SERVICES CONFIGRET = 0x00000032 + CR_ACCESS_DENIED CONFIGRET = 0x00000033 + CR_CALL_NOT_IMPLEMENTED CONFIGRET = 0x00000034 + CR_INVALID_PROPERTY CONFIGRET = 0x00000035 + CR_DEVICE_INTERFACE_ACTIVE CONFIGRET = 0x00000036 + CR_NO_SUCH_DEVICE_INTERFACE CONFIGRET = 0x00000037 + CR_INVALID_REFERENCE_STRING CONFIGRET = 0x00000038 + CR_INVALID_CONFLICT_LIST CONFIGRET = 0x00000039 + CR_INVALID_INDEX CONFIGRET = 0x0000003A + CR_INVALID_STRUCTURE_SIZE CONFIGRET = 0x0000003B + NUM_CR_RESULTS CONFIGRET = 0x0000003C +) + +const ( + CM_GET_DEVICE_INTERFACE_LIST_PRESENT = 0 // only currently 'live' device interfaces + CM_GET_DEVICE_INTERFACE_LIST_ALL_DEVICES = 1 // all registered device interfaces, live or not +) + +const ( + DN_ROOT_ENUMERATED = 0x00000001 // Was enumerated by ROOT + DN_DRIVER_LOADED = 0x00000002 // Has Register_Device_Driver + DN_ENUM_LOADED = 0x00000004 // Has Register_Enumerator + DN_STARTED = 0x00000008 // Is currently configured + DN_MANUAL = 0x00000010 // Manually installed + DN_NEED_TO_ENUM = 0x00000020 // May need reenumeration + DN_NOT_FIRST_TIME = 0x00000040 // Has received a config + DN_HARDWARE_ENUM = 0x00000080 // Enum generates hardware ID + DN_LIAR = 0x00000100 // Lied about can reconfig once + DN_HAS_MARK = 0x00000200 // Not CM_Create_DevInst lately + DN_HAS_PROBLEM = 0x00000400 // Need device installer + DN_FILTERED = 0x00000800 // Is filtered + DN_MOVED = 0x00001000 // Has been moved + DN_DISABLEABLE = 0x00002000 // Can be disabled + DN_REMOVABLE = 0x00004000 // Can be removed + DN_PRIVATE_PROBLEM = 0x00008000 // Has a private problem + DN_MF_PARENT = 0x00010000 // Multi function parent + DN_MF_CHILD = 0x00020000 // Multi function child + DN_WILL_BE_REMOVED = 0x00040000 // DevInst is being removed + DN_NOT_FIRST_TIMEE = 0x00080000 // Has received a config enumerate + DN_STOP_FREE_RES = 0x00100000 // When child is stopped, free resources + DN_REBAL_CANDIDATE = 0x00200000 // Don't skip during rebalance + DN_BAD_PARTIAL = 0x00400000 // This devnode's log_confs do not have same resources + DN_NT_ENUMERATOR = 0x00800000 // This devnode's is an NT enumerator + DN_NT_DRIVER = 0x01000000 // This devnode's is an NT driver + DN_NEEDS_LOCKING = 0x02000000 // Devnode need lock resume processing + DN_ARM_WAKEUP = 0x04000000 // Devnode can be the wakeup device + DN_APM_ENUMERATOR = 0x08000000 // APM aware enumerator + DN_APM_DRIVER = 0x10000000 // APM aware driver + DN_SILENT_INSTALL = 0x20000000 // Silent install + DN_NO_SHOW_IN_DM = 0x40000000 // No show in device manager + DN_BOOT_LOG_PROB = 0x80000000 // Had a problem during preassignment of boot log conf + DN_NEED_RESTART = DN_LIAR // System needs to be restarted for this Devnode to work properly + DN_DRIVER_BLOCKED = DN_NOT_FIRST_TIME // One or more drivers are blocked from loading for this Devnode + DN_LEGACY_DRIVER = DN_MOVED // This device is using a legacy driver + DN_CHILD_WITH_INVALID_ID = DN_HAS_MARK // One or more children have invalid IDs + DN_DEVICE_DISCONNECTED = DN_NEEDS_LOCKING // The function driver for a device reported that the device is not connected. Typically this means a wireless device is out of range. + DN_QUERY_REMOVE_PENDING = DN_MF_PARENT // Device is part of a set of related devices collectively pending query-removal + DN_QUERY_REMOVE_ACTIVE = DN_MF_CHILD // Device is actively engaged in a query-remove IRP + DN_CHANGEABLE_FLAGS = DN_NOT_FIRST_TIME | DN_HARDWARE_ENUM | DN_HAS_MARK | DN_DISABLEABLE | DN_REMOVABLE | DN_MF_CHILD | DN_MF_PARENT | DN_NOT_FIRST_TIMEE | DN_STOP_FREE_RES | DN_REBAL_CANDIDATE | DN_NT_ENUMERATOR | DN_NT_DRIVER | DN_SILENT_INSTALL | DN_NO_SHOW_IN_DM +) + +//sys setupDiCreateDeviceInfoListEx(classGUID *GUID, hwndParent uintptr, machineName *uint16, reserved uintptr) (handle DevInfo, err error) [failretval==DevInfo(InvalidHandle)] = setupapi.SetupDiCreateDeviceInfoListExW + +// SetupDiCreateDeviceInfoListEx function creates an empty device information set on a remote or a local computer and optionally associates the set with a device setup class. +func SetupDiCreateDeviceInfoListEx(classGUID *GUID, hwndParent uintptr, machineName string) (deviceInfoSet DevInfo, err error) { + var machineNameUTF16 *uint16 + if machineName != "" { + machineNameUTF16, err = UTF16PtrFromString(machineName) + if err != nil { + return + } + } + return setupDiCreateDeviceInfoListEx(classGUID, hwndParent, machineNameUTF16, 0) +} + +//sys setupDiGetDeviceInfoListDetail(deviceInfoSet DevInfo, deviceInfoSetDetailData *DevInfoListDetailData) (err error) = setupapi.SetupDiGetDeviceInfoListDetailW + +// SetupDiGetDeviceInfoListDetail function retrieves information associated with a device information set including the class GUID, remote computer handle, and remote computer name. +func SetupDiGetDeviceInfoListDetail(deviceInfoSet DevInfo) (deviceInfoSetDetailData *DevInfoListDetailData, err error) { + data := &DevInfoListDetailData{} + data.size = data.unsafeSizeOf() + + return data, setupDiGetDeviceInfoListDetail(deviceInfoSet, data) +} + +// DeviceInfoListDetail method retrieves information associated with a device information set including the class GUID, remote computer handle, and remote computer name. +func (deviceInfoSet DevInfo) DeviceInfoListDetail() (*DevInfoListDetailData, error) { + return SetupDiGetDeviceInfoListDetail(deviceInfoSet) +} + +//sys setupDiCreateDeviceInfo(deviceInfoSet DevInfo, DeviceName *uint16, classGUID *GUID, DeviceDescription *uint16, hwndParent uintptr, CreationFlags DICD, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiCreateDeviceInfoW + +// SetupDiCreateDeviceInfo function creates a new device information element and adds it as a new member to the specified device information set. +func SetupDiCreateDeviceInfo(deviceInfoSet DevInfo, deviceName string, classGUID *GUID, deviceDescription string, hwndParent uintptr, creationFlags DICD) (deviceInfoData *DevInfoData, err error) { + deviceNameUTF16, err := UTF16PtrFromString(deviceName) + if err != nil { + return + } + + var deviceDescriptionUTF16 *uint16 + if deviceDescription != "" { + deviceDescriptionUTF16, err = UTF16PtrFromString(deviceDescription) + if err != nil { + return + } + } + + data := &DevInfoData{} + data.size = uint32(unsafe.Sizeof(*data)) + + return data, setupDiCreateDeviceInfo(deviceInfoSet, deviceNameUTF16, classGUID, deviceDescriptionUTF16, hwndParent, creationFlags, data) +} + +// CreateDeviceInfo method creates a new device information element and adds it as a new member to the specified device information set. +func (deviceInfoSet DevInfo) CreateDeviceInfo(deviceName string, classGUID *GUID, deviceDescription string, hwndParent uintptr, creationFlags DICD) (*DevInfoData, error) { + return SetupDiCreateDeviceInfo(deviceInfoSet, deviceName, classGUID, deviceDescription, hwndParent, creationFlags) +} + +//sys setupDiEnumDeviceInfo(deviceInfoSet DevInfo, memberIndex uint32, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiEnumDeviceInfo + +// SetupDiEnumDeviceInfo function returns a DevInfoData structure that specifies a device information element in a device information set. +func SetupDiEnumDeviceInfo(deviceInfoSet DevInfo, memberIndex int) (*DevInfoData, error) { + data := &DevInfoData{} + data.size = uint32(unsafe.Sizeof(*data)) + + return data, setupDiEnumDeviceInfo(deviceInfoSet, uint32(memberIndex), data) +} + +// EnumDeviceInfo method returns a DevInfoData structure that specifies a device information element in a device information set. +func (deviceInfoSet DevInfo) EnumDeviceInfo(memberIndex int) (*DevInfoData, error) { + return SetupDiEnumDeviceInfo(deviceInfoSet, memberIndex) +} + +// SetupDiDestroyDeviceInfoList function deletes a device information set and frees all associated memory. +//sys SetupDiDestroyDeviceInfoList(deviceInfoSet DevInfo) (err error) = setupapi.SetupDiDestroyDeviceInfoList + +// Close method deletes a device information set and frees all associated memory. +func (deviceInfoSet DevInfo) Close() error { + return SetupDiDestroyDeviceInfoList(deviceInfoSet) +} + +//sys SetupDiBuildDriverInfoList(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT) (err error) = setupapi.SetupDiBuildDriverInfoList + +// BuildDriverInfoList method builds a list of drivers that is associated with a specific device or with the global class driver list for a device information set. +func (deviceInfoSet DevInfo) BuildDriverInfoList(deviceInfoData *DevInfoData, driverType SPDIT) error { + return SetupDiBuildDriverInfoList(deviceInfoSet, deviceInfoData, driverType) +} + +//sys SetupDiCancelDriverInfoSearch(deviceInfoSet DevInfo) (err error) = setupapi.SetupDiCancelDriverInfoSearch + +// CancelDriverInfoSearch method cancels a driver list search that is currently in progress in a different thread. +func (deviceInfoSet DevInfo) CancelDriverInfoSearch() error { + return SetupDiCancelDriverInfoSearch(deviceInfoSet) +} + +//sys setupDiEnumDriverInfo(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT, memberIndex uint32, driverInfoData *DrvInfoData) (err error) = setupapi.SetupDiEnumDriverInfoW + +// SetupDiEnumDriverInfo function enumerates the members of a driver list. +func SetupDiEnumDriverInfo(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT, memberIndex int) (*DrvInfoData, error) { + data := &DrvInfoData{} + data.size = uint32(unsafe.Sizeof(*data)) + + return data, setupDiEnumDriverInfo(deviceInfoSet, deviceInfoData, driverType, uint32(memberIndex), data) +} + +// EnumDriverInfo method enumerates the members of a driver list. +func (deviceInfoSet DevInfo) EnumDriverInfo(deviceInfoData *DevInfoData, driverType SPDIT, memberIndex int) (*DrvInfoData, error) { + return SetupDiEnumDriverInfo(deviceInfoSet, deviceInfoData, driverType, memberIndex) +} + +//sys setupDiGetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (err error) = setupapi.SetupDiGetSelectedDriverW + +// SetupDiGetSelectedDriver function retrieves the selected driver for a device information set or a particular device information element. +func SetupDiGetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (*DrvInfoData, error) { + data := &DrvInfoData{} + data.size = uint32(unsafe.Sizeof(*data)) + + return data, setupDiGetSelectedDriver(deviceInfoSet, deviceInfoData, data) +} + +// SelectedDriver method retrieves the selected driver for a device information set or a particular device information element. +func (deviceInfoSet DevInfo) SelectedDriver(deviceInfoData *DevInfoData) (*DrvInfoData, error) { + return SetupDiGetSelectedDriver(deviceInfoSet, deviceInfoData) +} + +//sys SetupDiSetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (err error) = setupapi.SetupDiSetSelectedDriverW + +// SetSelectedDriver method sets, or resets, the selected driver for a device information element or the selected class driver for a device information set. +func (deviceInfoSet DevInfo) SetSelectedDriver(deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) error { + return SetupDiSetSelectedDriver(deviceInfoSet, deviceInfoData, driverInfoData) +} + +//sys setupDiGetDriverInfoDetail(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData, driverInfoDetailData *DrvInfoDetailData, driverInfoDetailDataSize uint32, requiredSize *uint32) (err error) = setupapi.SetupDiGetDriverInfoDetailW + +// SetupDiGetDriverInfoDetail function retrieves driver information detail for a device information set or a particular device information element in the device information set. +func SetupDiGetDriverInfoDetail(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (*DrvInfoDetailData, error) { + reqSize := uint32(2048) + for { + buf := make([]byte, reqSize) + data := (*DrvInfoDetailData)(unsafe.Pointer(&buf[0])) + data.size = data.unsafeSizeOf() + err := setupDiGetDriverInfoDetail(deviceInfoSet, deviceInfoData, driverInfoData, data, uint32(len(buf)), &reqSize) + if err == ERROR_INSUFFICIENT_BUFFER { + continue + } + if err != nil { + return nil, err + } + data.size = reqSize + return data, nil + } +} + +// DriverInfoDetail method retrieves driver information detail for a device information set or a particular device information element in the device information set. +func (deviceInfoSet DevInfo) DriverInfoDetail(deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (*DrvInfoDetailData, error) { + return SetupDiGetDriverInfoDetail(deviceInfoSet, deviceInfoData, driverInfoData) +} + +//sys SetupDiDestroyDriverInfoList(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT) (err error) = setupapi.SetupDiDestroyDriverInfoList + +// DestroyDriverInfoList method deletes a driver list. +func (deviceInfoSet DevInfo) DestroyDriverInfoList(deviceInfoData *DevInfoData, driverType SPDIT) error { + return SetupDiDestroyDriverInfoList(deviceInfoSet, deviceInfoData, driverType) +} + +//sys setupDiGetClassDevsEx(classGUID *GUID, Enumerator *uint16, hwndParent uintptr, Flags DIGCF, deviceInfoSet DevInfo, machineName *uint16, reserved uintptr) (handle DevInfo, err error) [failretval==DevInfo(InvalidHandle)] = setupapi.SetupDiGetClassDevsExW + +// SetupDiGetClassDevsEx function returns a handle to a device information set that contains requested device information elements for a local or a remote computer. +func SetupDiGetClassDevsEx(classGUID *GUID, enumerator string, hwndParent uintptr, flags DIGCF, deviceInfoSet DevInfo, machineName string) (handle DevInfo, err error) { + var enumeratorUTF16 *uint16 + if enumerator != "" { + enumeratorUTF16, err = UTF16PtrFromString(enumerator) + if err != nil { + return + } + } + var machineNameUTF16 *uint16 + if machineName != "" { + machineNameUTF16, err = UTF16PtrFromString(machineName) + if err != nil { + return + } + } + return setupDiGetClassDevsEx(classGUID, enumeratorUTF16, hwndParent, flags, deviceInfoSet, machineNameUTF16, 0) +} + +// SetupDiCallClassInstaller function calls the appropriate class installer, and any registered co-installers, with the specified installation request (DIF code). +//sys SetupDiCallClassInstaller(installFunction DI_FUNCTION, deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiCallClassInstaller + +// CallClassInstaller member calls the appropriate class installer, and any registered co-installers, with the specified installation request (DIF code). +func (deviceInfoSet DevInfo) CallClassInstaller(installFunction DI_FUNCTION, deviceInfoData *DevInfoData) error { + return SetupDiCallClassInstaller(installFunction, deviceInfoSet, deviceInfoData) +} + +// SetupDiOpenDevRegKey function opens a registry key for device-specific configuration information. +//sys SetupDiOpenDevRegKey(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, Scope DICS_FLAG, HwProfile uint32, KeyType DIREG, samDesired uint32) (key Handle, err error) [failretval==InvalidHandle] = setupapi.SetupDiOpenDevRegKey + +// OpenDevRegKey method opens a registry key for device-specific configuration information. +func (deviceInfoSet DevInfo) OpenDevRegKey(DeviceInfoData *DevInfoData, Scope DICS_FLAG, HwProfile uint32, KeyType DIREG, samDesired uint32) (Handle, error) { + return SetupDiOpenDevRegKey(deviceInfoSet, DeviceInfoData, Scope, HwProfile, KeyType, samDesired) +} + +//sys setupDiGetDeviceProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, propertyKey *DEVPROPKEY, propertyType *DEVPROPTYPE, propertyBuffer *byte, propertyBufferSize uint32, requiredSize *uint32, flags uint32) (err error) = setupapi.SetupDiGetDevicePropertyW + +// SetupDiGetDeviceProperty function retrieves a specified device instance property. +func SetupDiGetDeviceProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, propertyKey *DEVPROPKEY) (value interface{}, err error) { + reqSize := uint32(256) + for { + var dataType DEVPROPTYPE + buf := make([]byte, reqSize) + err = setupDiGetDeviceProperty(deviceInfoSet, deviceInfoData, propertyKey, &dataType, &buf[0], uint32(len(buf)), &reqSize, 0) + if err == ERROR_INSUFFICIENT_BUFFER { + continue + } + if err != nil { + return + } + switch dataType { + case DEVPROP_TYPE_STRING: + ret := UTF16ToString(bufToUTF16(buf)) + runtime.KeepAlive(buf) + return ret, nil + } + return nil, errors.New("unimplemented property type") + } +} + +//sys setupDiGetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyRegDataType *uint32, propertyBuffer *byte, propertyBufferSize uint32, requiredSize *uint32) (err error) = setupapi.SetupDiGetDeviceRegistryPropertyW + +// SetupDiGetDeviceRegistryProperty function retrieves a specified Plug and Play device property. +func SetupDiGetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP) (value interface{}, err error) { + reqSize := uint32(256) + for { + var dataType uint32 + buf := make([]byte, reqSize) + err = setupDiGetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, &dataType, &buf[0], uint32(len(buf)), &reqSize) + if err == ERROR_INSUFFICIENT_BUFFER { + continue + } + if err != nil { + return + } + return getRegistryValue(buf[:reqSize], dataType) + } +} + +func getRegistryValue(buf []byte, dataType uint32) (interface{}, error) { + switch dataType { + case REG_SZ: + ret := UTF16ToString(bufToUTF16(buf)) + runtime.KeepAlive(buf) + return ret, nil + case REG_EXPAND_SZ: + value := UTF16ToString(bufToUTF16(buf)) + if value == "" { + return "", nil + } + p, err := syscall.UTF16PtrFromString(value) + if err != nil { + return "", err + } + ret := make([]uint16, 100) + for { + n, err := ExpandEnvironmentStrings(p, &ret[0], uint32(len(ret))) + if err != nil { + return "", err + } + if n <= uint32(len(ret)) { + return UTF16ToString(ret[:n]), nil + } + ret = make([]uint16, n) + } + case REG_BINARY: + return buf, nil + case REG_DWORD_LITTLE_ENDIAN: + return binary.LittleEndian.Uint32(buf), nil + case REG_DWORD_BIG_ENDIAN: + return binary.BigEndian.Uint32(buf), nil + case REG_MULTI_SZ: + bufW := bufToUTF16(buf) + a := []string{} + for i := 0; i < len(bufW); { + j := i + wcslen(bufW[i:]) + if i < j { + a = append(a, UTF16ToString(bufW[i:j])) + } + i = j + 1 + } + runtime.KeepAlive(buf) + return a, nil + case REG_QWORD_LITTLE_ENDIAN: + return binary.LittleEndian.Uint64(buf), nil + default: + return nil, fmt.Errorf("Unsupported registry value type: %v", dataType) + } +} + +// bufToUTF16 function reinterprets []byte buffer as []uint16 +func bufToUTF16(buf []byte) []uint16 { + sl := struct { + addr *uint16 + len int + cap int + }{(*uint16)(unsafe.Pointer(&buf[0])), len(buf) / 2, cap(buf) / 2} + return *(*[]uint16)(unsafe.Pointer(&sl)) +} + +// utf16ToBuf function reinterprets []uint16 as []byte +func utf16ToBuf(buf []uint16) []byte { + sl := struct { + addr *byte + len int + cap int + }{(*byte)(unsafe.Pointer(&buf[0])), len(buf) * 2, cap(buf) * 2} + return *(*[]byte)(unsafe.Pointer(&sl)) +} + +func wcslen(str []uint16) int { + for i := 0; i < len(str); i++ { + if str[i] == 0 { + return i + } + } + return len(str) +} + +// DeviceRegistryProperty method retrieves a specified Plug and Play device property. +func (deviceInfoSet DevInfo) DeviceRegistryProperty(deviceInfoData *DevInfoData, property SPDRP) (interface{}, error) { + return SetupDiGetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property) +} + +//sys setupDiSetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyBuffer *byte, propertyBufferSize uint32) (err error) = setupapi.SetupDiSetDeviceRegistryPropertyW + +// SetupDiSetDeviceRegistryProperty function sets a Plug and Play device property for a device. +func SetupDiSetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyBuffers []byte) error { + return setupDiSetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, &propertyBuffers[0], uint32(len(propertyBuffers))) +} + +// SetDeviceRegistryProperty function sets a Plug and Play device property for a device. +func (deviceInfoSet DevInfo) SetDeviceRegistryProperty(deviceInfoData *DevInfoData, property SPDRP, propertyBuffers []byte) error { + return SetupDiSetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, propertyBuffers) +} + +// SetDeviceRegistryPropertyString method sets a Plug and Play device property string for a device. +func (deviceInfoSet DevInfo) SetDeviceRegistryPropertyString(deviceInfoData *DevInfoData, property SPDRP, str string) error { + str16, err := UTF16FromString(str) + if err != nil { + return err + } + err = SetupDiSetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, utf16ToBuf(append(str16, 0))) + runtime.KeepAlive(str16) + return err +} + +//sys setupDiGetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) (err error) = setupapi.SetupDiGetDeviceInstallParamsW + +// SetupDiGetDeviceInstallParams function retrieves device installation parameters for a device information set or a particular device information element. +func SetupDiGetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (*DevInstallParams, error) { + params := &DevInstallParams{} + params.size = uint32(unsafe.Sizeof(*params)) + + return params, setupDiGetDeviceInstallParams(deviceInfoSet, deviceInfoData, params) +} + +// DeviceInstallParams method retrieves device installation parameters for a device information set or a particular device information element. +func (deviceInfoSet DevInfo) DeviceInstallParams(deviceInfoData *DevInfoData) (*DevInstallParams, error) { + return SetupDiGetDeviceInstallParams(deviceInfoSet, deviceInfoData) +} + +//sys setupDiGetDeviceInstanceId(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, instanceId *uint16, instanceIdSize uint32, instanceIdRequiredSize *uint32) (err error) = setupapi.SetupDiGetDeviceInstanceIdW + +// SetupDiGetDeviceInstanceId function retrieves the instance ID of the device. +func SetupDiGetDeviceInstanceId(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (string, error) { + reqSize := uint32(1024) + for { + buf := make([]uint16, reqSize) + err := setupDiGetDeviceInstanceId(deviceInfoSet, deviceInfoData, &buf[0], uint32(len(buf)), &reqSize) + if err == ERROR_INSUFFICIENT_BUFFER { + continue + } + if err != nil { + return "", err + } + return UTF16ToString(buf), nil + } +} + +// DeviceInstanceID method retrieves the instance ID of the device. +func (deviceInfoSet DevInfo) DeviceInstanceID(deviceInfoData *DevInfoData) (string, error) { + return SetupDiGetDeviceInstanceId(deviceInfoSet, deviceInfoData) +} + +// SetupDiGetClassInstallParams function retrieves class installation parameters for a device information set or a particular device information element. +//sys SetupDiGetClassInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32, requiredSize *uint32) (err error) = setupapi.SetupDiGetClassInstallParamsW + +// ClassInstallParams method retrieves class installation parameters for a device information set or a particular device information element. +func (deviceInfoSet DevInfo) ClassInstallParams(deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32, requiredSize *uint32) error { + return SetupDiGetClassInstallParams(deviceInfoSet, deviceInfoData, classInstallParams, classInstallParamsSize, requiredSize) +} + +//sys SetupDiSetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) (err error) = setupapi.SetupDiSetDeviceInstallParamsW + +// SetDeviceInstallParams member sets device installation parameters for a device information set or a particular device information element. +func (deviceInfoSet DevInfo) SetDeviceInstallParams(deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) error { + return SetupDiSetDeviceInstallParams(deviceInfoSet, deviceInfoData, deviceInstallParams) +} + +// SetupDiSetClassInstallParams function sets or clears class install parameters for a device information set or a particular device information element. +//sys SetupDiSetClassInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32) (err error) = setupapi.SetupDiSetClassInstallParamsW + +// SetClassInstallParams method sets or clears class install parameters for a device information set or a particular device information element. +func (deviceInfoSet DevInfo) SetClassInstallParams(deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32) error { + return SetupDiSetClassInstallParams(deviceInfoSet, deviceInfoData, classInstallParams, classInstallParamsSize) +} + +//sys setupDiClassNameFromGuidEx(classGUID *GUID, className *uint16, classNameSize uint32, requiredSize *uint32, machineName *uint16, reserved uintptr) (err error) = setupapi.SetupDiClassNameFromGuidExW + +// SetupDiClassNameFromGuidEx function retrieves the class name associated with a class GUID. The class can be installed on a local or remote computer. +func SetupDiClassNameFromGuidEx(classGUID *GUID, machineName string) (className string, err error) { + var classNameUTF16 [MAX_CLASS_NAME_LEN]uint16 + + var machineNameUTF16 *uint16 + if machineName != "" { + machineNameUTF16, err = UTF16PtrFromString(machineName) + if err != nil { + return + } + } + + err = setupDiClassNameFromGuidEx(classGUID, &classNameUTF16[0], MAX_CLASS_NAME_LEN, nil, machineNameUTF16, 0) + if err != nil { + return + } + + className = UTF16ToString(classNameUTF16[:]) + return +} + +//sys setupDiClassGuidsFromNameEx(className *uint16, classGuidList *GUID, classGuidListSize uint32, requiredSize *uint32, machineName *uint16, reserved uintptr) (err error) = setupapi.SetupDiClassGuidsFromNameExW + +// SetupDiClassGuidsFromNameEx function retrieves the GUIDs associated with the specified class name. This resulting list contains the classes currently installed on a local or remote computer. +func SetupDiClassGuidsFromNameEx(className string, machineName string) ([]GUID, error) { + classNameUTF16, err := UTF16PtrFromString(className) + if err != nil { + return nil, err + } + + var machineNameUTF16 *uint16 + if machineName != "" { + machineNameUTF16, err = UTF16PtrFromString(machineName) + if err != nil { + return nil, err + } + } + + reqSize := uint32(4) + for { + buf := make([]GUID, reqSize) + err = setupDiClassGuidsFromNameEx(classNameUTF16, &buf[0], uint32(len(buf)), &reqSize, machineNameUTF16, 0) + if err == ERROR_INSUFFICIENT_BUFFER { + continue + } + if err != nil { + return nil, err + } + return buf[:reqSize], nil + } +} + +//sys setupDiGetSelectedDevice(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiGetSelectedDevice + +// SetupDiGetSelectedDevice function retrieves the selected device information element in a device information set. +func SetupDiGetSelectedDevice(deviceInfoSet DevInfo) (*DevInfoData, error) { + data := &DevInfoData{} + data.size = uint32(unsafe.Sizeof(*data)) + + return data, setupDiGetSelectedDevice(deviceInfoSet, data) +} + +// SelectedDevice method retrieves the selected device information element in a device information set. +func (deviceInfoSet DevInfo) SelectedDevice() (*DevInfoData, error) { + return SetupDiGetSelectedDevice(deviceInfoSet) +} + +// SetupDiSetSelectedDevice function sets a device information element as the selected member of a device information set. This function is typically used by an installation wizard. +//sys SetupDiSetSelectedDevice(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) = setupapi.SetupDiSetSelectedDevice + +// SetSelectedDevice method sets a device information element as the selected member of a device information set. This function is typically used by an installation wizard. +func (deviceInfoSet DevInfo) SetSelectedDevice(deviceInfoData *DevInfoData) error { + return SetupDiSetSelectedDevice(deviceInfoSet, deviceInfoData) +} + +//sys setupUninstallOEMInf(infFileName *uint16, flags SUOI, reserved uintptr) (err error) = setupapi.SetupUninstallOEMInfW + +// SetupUninstallOEMInf uninstalls the specified driver. +func SetupUninstallOEMInf(infFileName string, flags SUOI) error { + infFileName16, err := UTF16PtrFromString(infFileName) + if err != nil { + return err + } + return setupUninstallOEMInf(infFileName16, flags, 0) +} + +//sys cm_MapCrToWin32Err(configRet CONFIGRET, defaultWin32Error Errno) (ret Errno) = CfgMgr32.CM_MapCrToWin32Err + +//sys cm_Get_Device_Interface_List_Size(len *uint32, interfaceClass *GUID, deviceID *uint16, flags uint32) (ret CONFIGRET) = CfgMgr32.CM_Get_Device_Interface_List_SizeW +//sys cm_Get_Device_Interface_List(interfaceClass *GUID, deviceID *uint16, buffer *uint16, bufferLen uint32, flags uint32) (ret CONFIGRET) = CfgMgr32.CM_Get_Device_Interface_ListW + +func CM_Get_Device_Interface_List(deviceID string, interfaceClass *GUID, flags uint32) ([]string, error) { + deviceID16, err := UTF16PtrFromString(deviceID) + if err != nil { + return nil, err + } + var buf []uint16 + var buflen uint32 + for { + if ret := cm_Get_Device_Interface_List_Size(&buflen, interfaceClass, deviceID16, flags); ret != CR_SUCCESS { + return nil, ret + } + buf = make([]uint16, buflen) + if ret := cm_Get_Device_Interface_List(interfaceClass, deviceID16, &buf[0], buflen, flags); ret == CR_SUCCESS { + break + } else if ret != CR_BUFFER_SMALL { + return nil, ret + } + } + var interfaces []string + for i := 0; i < len(buf); { + j := i + wcslen(buf[i:]) + if i < j { + interfaces = append(interfaces, UTF16ToString(buf[i:j])) + } + i = j + 1 + } + if interfaces == nil { + return nil, ERROR_NO_SUCH_DEVICE_INTERFACE + } + return interfaces, nil +} + +//sys cm_Get_DevNode_Status(status *uint32, problemNumber *uint32, devInst DEVINST, flags uint32) (ret CONFIGRET) = CfgMgr32.CM_Get_DevNode_Status + +func CM_Get_DevNode_Status(status *uint32, problemNumber *uint32, devInst DEVINST, flags uint32) error { + ret := cm_Get_DevNode_Status(status, problemNumber, devInst, flags) + if ret == CR_SUCCESS { + return nil + } + return ret +} diff --git a/src/cmd/vendor/golang.org/x/sys/windows/setupapierrors_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/setupapierrors_windows.go deleted file mode 100644 index 1681810e04..0000000000 --- a/src/cmd/vendor/golang.org/x/sys/windows/setupapierrors_windows.go +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package windows - -import "syscall" - -const ( - ERROR_EXPECTED_SECTION_NAME syscall.Errno = 0x20000000 | 0xC0000000 | 0 - ERROR_BAD_SECTION_NAME_LINE syscall.Errno = 0x20000000 | 0xC0000000 | 1 - ERROR_SECTION_NAME_TOO_LONG syscall.Errno = 0x20000000 | 0xC0000000 | 2 - ERROR_GENERAL_SYNTAX syscall.Errno = 0x20000000 | 0xC0000000 | 3 - ERROR_WRONG_INF_STYLE syscall.Errno = 0x20000000 | 0xC0000000 | 0x100 - ERROR_SECTION_NOT_FOUND syscall.Errno = 0x20000000 | 0xC0000000 | 0x101 - ERROR_LINE_NOT_FOUND syscall.Errno = 0x20000000 | 0xC0000000 | 0x102 - ERROR_NO_BACKUP syscall.Errno = 0x20000000 | 0xC0000000 | 0x103 - ERROR_NO_ASSOCIATED_CLASS syscall.Errno = 0x20000000 | 0xC0000000 | 0x200 - ERROR_CLASS_MISMATCH syscall.Errno = 0x20000000 | 0xC0000000 | 0x201 - ERROR_DUPLICATE_FOUND syscall.Errno = 0x20000000 | 0xC0000000 | 0x202 - ERROR_NO_DRIVER_SELECTED syscall.Errno = 0x20000000 | 0xC0000000 | 0x203 - ERROR_KEY_DOES_NOT_EXIST syscall.Errno = 0x20000000 | 0xC0000000 | 0x204 - ERROR_INVALID_DEVINST_NAME syscall.Errno = 0x20000000 | 0xC0000000 | 0x205 - ERROR_INVALID_CLASS syscall.Errno = 0x20000000 | 0xC0000000 | 0x206 - ERROR_DEVINST_ALREADY_EXISTS syscall.Errno = 0x20000000 | 0xC0000000 | 0x207 - ERROR_DEVINFO_NOT_REGISTERED syscall.Errno = 0x20000000 | 0xC0000000 | 0x208 - ERROR_INVALID_REG_PROPERTY syscall.Errno = 0x20000000 | 0xC0000000 | 0x209 - ERROR_NO_INF syscall.Errno = 0x20000000 | 0xC0000000 | 0x20A - ERROR_NO_SUCH_DEVINST syscall.Errno = 0x20000000 | 0xC0000000 | 0x20B - ERROR_CANT_LOAD_CLASS_ICON syscall.Errno = 0x20000000 | 0xC0000000 | 0x20C - ERROR_INVALID_CLASS_INSTALLER syscall.Errno = 0x20000000 | 0xC0000000 | 0x20D - ERROR_DI_DO_DEFAULT syscall.Errno = 0x20000000 | 0xC0000000 | 0x20E - ERROR_DI_NOFILECOPY syscall.Errno = 0x20000000 | 0xC0000000 | 0x20F - ERROR_INVALID_HWPROFILE syscall.Errno = 0x20000000 | 0xC0000000 | 0x210 - ERROR_NO_DEVICE_SELECTED syscall.Errno = 0x20000000 | 0xC0000000 | 0x211 - ERROR_DEVINFO_LIST_LOCKED syscall.Errno = 0x20000000 | 0xC0000000 | 0x212 - ERROR_DEVINFO_DATA_LOCKED syscall.Errno = 0x20000000 | 0xC0000000 | 0x213 - ERROR_DI_BAD_PATH syscall.Errno = 0x20000000 | 0xC0000000 | 0x214 - ERROR_NO_CLASSINSTALL_PARAMS syscall.Errno = 0x20000000 | 0xC0000000 | 0x215 - ERROR_FILEQUEUE_LOCKED syscall.Errno = 0x20000000 | 0xC0000000 | 0x216 - ERROR_BAD_SERVICE_INSTALLSECT syscall.Errno = 0x20000000 | 0xC0000000 | 0x217 - ERROR_NO_CLASS_DRIVER_LIST syscall.Errno = 0x20000000 | 0xC0000000 | 0x218 - ERROR_NO_ASSOCIATED_SERVICE syscall.Errno = 0x20000000 | 0xC0000000 | 0x219 - ERROR_NO_DEFAULT_DEVICE_INTERFACE syscall.Errno = 0x20000000 | 0xC0000000 | 0x21A - ERROR_DEVICE_INTERFACE_ACTIVE syscall.Errno = 0x20000000 | 0xC0000000 | 0x21B - ERROR_DEVICE_INTERFACE_REMOVED syscall.Errno = 0x20000000 | 0xC0000000 | 0x21C - ERROR_BAD_INTERFACE_INSTALLSECT syscall.Errno = 0x20000000 | 0xC0000000 | 0x21D - ERROR_NO_SUCH_INTERFACE_CLASS syscall.Errno = 0x20000000 | 0xC0000000 | 0x21E - ERROR_INVALID_REFERENCE_STRING syscall.Errno = 0x20000000 | 0xC0000000 | 0x21F - ERROR_INVALID_MACHINENAME syscall.Errno = 0x20000000 | 0xC0000000 | 0x220 - ERROR_REMOTE_COMM_FAILURE syscall.Errno = 0x20000000 | 0xC0000000 | 0x221 - ERROR_MACHINE_UNAVAILABLE syscall.Errno = 0x20000000 | 0xC0000000 | 0x222 - ERROR_NO_CONFIGMGR_SERVICES syscall.Errno = 0x20000000 | 0xC0000000 | 0x223 - ERROR_INVALID_PROPPAGE_PROVIDER syscall.Errno = 0x20000000 | 0xC0000000 | 0x224 - ERROR_NO_SUCH_DEVICE_INTERFACE syscall.Errno = 0x20000000 | 0xC0000000 | 0x225 - ERROR_DI_POSTPROCESSING_REQUIRED syscall.Errno = 0x20000000 | 0xC0000000 | 0x226 - ERROR_INVALID_COINSTALLER syscall.Errno = 0x20000000 | 0xC0000000 | 0x227 - ERROR_NO_COMPAT_DRIVERS syscall.Errno = 0x20000000 | 0xC0000000 | 0x228 - ERROR_NO_DEVICE_ICON syscall.Errno = 0x20000000 | 0xC0000000 | 0x229 - ERROR_INVALID_INF_LOGCONFIG syscall.Errno = 0x20000000 | 0xC0000000 | 0x22A - ERROR_DI_DONT_INSTALL syscall.Errno = 0x20000000 | 0xC0000000 | 0x22B - ERROR_INVALID_FILTER_DRIVER syscall.Errno = 0x20000000 | 0xC0000000 | 0x22C - ERROR_NON_WINDOWS_NT_DRIVER syscall.Errno = 0x20000000 | 0xC0000000 | 0x22D - ERROR_NON_WINDOWS_DRIVER syscall.Errno = 0x20000000 | 0xC0000000 | 0x22E - ERROR_NO_CATALOG_FOR_OEM_INF syscall.Errno = 0x20000000 | 0xC0000000 | 0x22F - ERROR_DEVINSTALL_QUEUE_NONNATIVE syscall.Errno = 0x20000000 | 0xC0000000 | 0x230 - ERROR_NOT_DISABLEABLE syscall.Errno = 0x20000000 | 0xC0000000 | 0x231 - ERROR_CANT_REMOVE_DEVINST syscall.Errno = 0x20000000 | 0xC0000000 | 0x232 - ERROR_INVALID_TARGET syscall.Errno = 0x20000000 | 0xC0000000 | 0x233 - ERROR_DRIVER_NONNATIVE syscall.Errno = 0x20000000 | 0xC0000000 | 0x234 - ERROR_IN_WOW64 syscall.Errno = 0x20000000 | 0xC0000000 | 0x235 - ERROR_SET_SYSTEM_RESTORE_POINT syscall.Errno = 0x20000000 | 0xC0000000 | 0x236 - ERROR_SCE_DISABLED syscall.Errno = 0x20000000 | 0xC0000000 | 0x238 - ERROR_UNKNOWN_EXCEPTION syscall.Errno = 0x20000000 | 0xC0000000 | 0x239 - ERROR_PNP_REGISTRY_ERROR syscall.Errno = 0x20000000 | 0xC0000000 | 0x23A - ERROR_REMOTE_REQUEST_UNSUPPORTED syscall.Errno = 0x20000000 | 0xC0000000 | 0x23B - ERROR_NOT_AN_INSTALLED_OEM_INF syscall.Errno = 0x20000000 | 0xC0000000 | 0x23C - ERROR_INF_IN_USE_BY_DEVICES syscall.Errno = 0x20000000 | 0xC0000000 | 0x23D - ERROR_DI_FUNCTION_OBSOLETE syscall.Errno = 0x20000000 | 0xC0000000 | 0x23E - ERROR_NO_AUTHENTICODE_CATALOG syscall.Errno = 0x20000000 | 0xC0000000 | 0x23F - ERROR_AUTHENTICODE_DISALLOWED syscall.Errno = 0x20000000 | 0xC0000000 | 0x240 - ERROR_AUTHENTICODE_TRUSTED_PUBLISHER syscall.Errno = 0x20000000 | 0xC0000000 | 0x241 - ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED syscall.Errno = 0x20000000 | 0xC0000000 | 0x242 - ERROR_AUTHENTICODE_PUBLISHER_NOT_TRUSTED syscall.Errno = 0x20000000 | 0xC0000000 | 0x243 - ERROR_SIGNATURE_OSATTRIBUTE_MISMATCH syscall.Errno = 0x20000000 | 0xC0000000 | 0x244 - ERROR_ONLY_VALIDATE_VIA_AUTHENTICODE syscall.Errno = 0x20000000 | 0xC0000000 | 0x245 - ERROR_DEVICE_INSTALLER_NOT_READY syscall.Errno = 0x20000000 | 0xC0000000 | 0x246 - ERROR_DRIVER_STORE_ADD_FAILED syscall.Errno = 0x20000000 | 0xC0000000 | 0x247 - ERROR_DEVICE_INSTALL_BLOCKED syscall.Errno = 0x20000000 | 0xC0000000 | 0x248 - ERROR_DRIVER_INSTALL_BLOCKED syscall.Errno = 0x20000000 | 0xC0000000 | 0x249 - ERROR_WRONG_INF_TYPE syscall.Errno = 0x20000000 | 0xC0000000 | 0x24A - ERROR_FILE_HASH_NOT_IN_CATALOG syscall.Errno = 0x20000000 | 0xC0000000 | 0x24B - ERROR_DRIVER_STORE_DELETE_FAILED syscall.Errno = 0x20000000 | 0xC0000000 | 0x24C - ERROR_UNRECOVERABLE_STACK_OVERFLOW syscall.Errno = 0x20000000 | 0xC0000000 | 0x300 - EXCEPTION_SPAPI_UNRECOVERABLE_STACK_OVERFLOW syscall.Errno = ERROR_UNRECOVERABLE_STACK_OVERFLOW - ERROR_NO_DEFAULT_INTERFACE_DEVICE syscall.Errno = ERROR_NO_DEFAULT_DEVICE_INTERFACE - ERROR_INTERFACE_DEVICE_ACTIVE syscall.Errno = ERROR_DEVICE_INTERFACE_ACTIVE - ERROR_INTERFACE_DEVICE_REMOVED syscall.Errno = ERROR_DEVICE_INTERFACE_REMOVED - ERROR_NO_SUCH_INTERFACE_DEVICE syscall.Errno = ERROR_NO_SUCH_DEVICE_INTERFACE -) diff --git a/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go index 2ff6aa0470..200b62a003 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go @@ -248,6 +248,7 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys FreeEnvironmentStrings(envs *uint16) (err error) = kernel32.FreeEnvironmentStringsW //sys GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, err error) = kernel32.GetEnvironmentVariableW //sys SetEnvironmentVariable(name *uint16, value *uint16) (err error) = kernel32.SetEnvironmentVariableW +//sys ExpandEnvironmentStrings(src *uint16, dst *uint16, size uint32) (n uint32, err error) = kernel32.ExpandEnvironmentStringsW //sys CreateEnvironmentBlock(block **uint16, token Token, inheritExisting bool) (err error) = userenv.CreateEnvironmentBlock //sys DestroyEnvironmentBlock(block *uint16) (err error) = userenv.DestroyEnvironmentBlock //sys getTickCount64() (ms uint64) = kernel32.GetTickCount64 @@ -322,6 +323,8 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) = kernel32.WriteConsoleW //sys ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) = kernel32.ReadConsoleW //sys CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) [failretval==InvalidHandle] = kernel32.CreateToolhelp32Snapshot +//sys Module32First(snapshot Handle, moduleEntry *ModuleEntry32) (err error) = kernel32.Module32FirstW +//sys Module32Next(snapshot Handle, moduleEntry *ModuleEntry32) (err error) = kernel32.Module32NextW //sys Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32FirstW //sys Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32NextW //sys Thread32First(snapshot Handle, threadEntry *ThreadEntry32) (err error) diff --git a/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go index 286dd1eab9..73087bf5e5 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go @@ -156,6 +156,8 @@ const ( MAX_PATH = 260 MAX_LONG_PATH = 32768 + MAX_MODULE_NAME32 = 255 + MAX_COMPUTERNAME_LENGTH = 15 TIME_ZONE_ID_UNKNOWN = 0 @@ -970,6 +972,21 @@ type ThreadEntry32 struct { Flags uint32 } +type ModuleEntry32 struct { + Size uint32 + ModuleID uint32 + ProcessID uint32 + GlblcntUsage uint32 + ProccntUsage uint32 + ModBaseAddr uintptr + ModBaseSize uint32 + ModuleHandle Handle + Module [MAX_MODULE_NAME32 + 1]uint16 + ExePath [MAX_PATH]uint16 +} + +const SizeofModuleEntry32 = unsafe.Sizeof(ModuleEntry32{}) + type Systemtime struct { Year uint16 Month uint16 diff --git a/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go index 91817d6dcb..1055d47ed3 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go @@ -36,6 +36,7 @@ func errnoErr(e syscall.Errno) error { } var ( + modCfgMgr32 = NewLazySystemDLL("CfgMgr32.dll") modadvapi32 = NewLazySystemDLL("advapi32.dll") modcrypt32 = NewLazySystemDLL("crypt32.dll") moddnsapi = NewLazySystemDLL("dnsapi.dll") @@ -48,6 +49,7 @@ var ( modpsapi = NewLazySystemDLL("psapi.dll") modsechost = NewLazySystemDLL("sechost.dll") modsecur32 = NewLazySystemDLL("secur32.dll") + modsetupapi = NewLazySystemDLL("setupapi.dll") modshell32 = NewLazySystemDLL("shell32.dll") moduser32 = NewLazySystemDLL("user32.dll") moduserenv = NewLazySystemDLL("userenv.dll") @@ -56,6 +58,10 @@ var ( modws2_32 = NewLazySystemDLL("ws2_32.dll") modwtsapi32 = NewLazySystemDLL("wtsapi32.dll") + procCM_Get_DevNode_Status = modCfgMgr32.NewProc("CM_Get_DevNode_Status") + procCM_Get_Device_Interface_ListW = modCfgMgr32.NewProc("CM_Get_Device_Interface_ListW") + procCM_Get_Device_Interface_List_SizeW = modCfgMgr32.NewProc("CM_Get_Device_Interface_List_SizeW") + procCM_MapCrToWin32Err = modCfgMgr32.NewProc("CM_MapCrToWin32Err") procAdjustTokenGroups = modadvapi32.NewProc("AdjustTokenGroups") procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges") procAllocateAndInitializeSid = modadvapi32.NewProc("AllocateAndInitializeSid") @@ -199,6 +205,7 @@ var ( procDeviceIoControl = modkernel32.NewProc("DeviceIoControl") procDuplicateHandle = modkernel32.NewProc("DuplicateHandle") procExitProcess = modkernel32.NewProc("ExitProcess") + procExpandEnvironmentStringsW = modkernel32.NewProc("ExpandEnvironmentStringsW") procFindClose = modkernel32.NewProc("FindClose") procFindCloseChangeNotification = modkernel32.NewProc("FindCloseChangeNotification") procFindFirstChangeNotificationW = modkernel32.NewProc("FindFirstChangeNotificationW") @@ -288,6 +295,8 @@ var ( procLockFileEx = modkernel32.NewProc("LockFileEx") procLockResource = modkernel32.NewProc("LockResource") procMapViewOfFile = modkernel32.NewProc("MapViewOfFile") + procModule32FirstW = modkernel32.NewProc("Module32FirstW") + procModule32NextW = modkernel32.NewProc("Module32NextW") procMoveFileExW = modkernel32.NewProc("MoveFileExW") procMoveFileW = modkernel32.NewProc("MoveFileW") procMultiByteToWideChar = modkernel32.NewProc("MultiByteToWideChar") @@ -400,6 +409,34 @@ var ( procUnsubscribeServiceChangeNotifications = modsechost.NewProc("UnsubscribeServiceChangeNotifications") procGetUserNameExW = modsecur32.NewProc("GetUserNameExW") procTranslateNameW = modsecur32.NewProc("TranslateNameW") + procSetupDiBuildDriverInfoList = modsetupapi.NewProc("SetupDiBuildDriverInfoList") + procSetupDiCallClassInstaller = modsetupapi.NewProc("SetupDiCallClassInstaller") + procSetupDiCancelDriverInfoSearch = modsetupapi.NewProc("SetupDiCancelDriverInfoSearch") + procSetupDiClassGuidsFromNameExW = modsetupapi.NewProc("SetupDiClassGuidsFromNameExW") + procSetupDiClassNameFromGuidExW = modsetupapi.NewProc("SetupDiClassNameFromGuidExW") + procSetupDiCreateDeviceInfoListExW = modsetupapi.NewProc("SetupDiCreateDeviceInfoListExW") + procSetupDiCreateDeviceInfoW = modsetupapi.NewProc("SetupDiCreateDeviceInfoW") + procSetupDiDestroyDeviceInfoList = modsetupapi.NewProc("SetupDiDestroyDeviceInfoList") + procSetupDiDestroyDriverInfoList = modsetupapi.NewProc("SetupDiDestroyDriverInfoList") + procSetupDiEnumDeviceInfo = modsetupapi.NewProc("SetupDiEnumDeviceInfo") + procSetupDiEnumDriverInfoW = modsetupapi.NewProc("SetupDiEnumDriverInfoW") + procSetupDiGetClassDevsExW = modsetupapi.NewProc("SetupDiGetClassDevsExW") + procSetupDiGetClassInstallParamsW = modsetupapi.NewProc("SetupDiGetClassInstallParamsW") + procSetupDiGetDeviceInfoListDetailW = modsetupapi.NewProc("SetupDiGetDeviceInfoListDetailW") + procSetupDiGetDeviceInstallParamsW = modsetupapi.NewProc("SetupDiGetDeviceInstallParamsW") + procSetupDiGetDeviceInstanceIdW = modsetupapi.NewProc("SetupDiGetDeviceInstanceIdW") + procSetupDiGetDevicePropertyW = modsetupapi.NewProc("SetupDiGetDevicePropertyW") + procSetupDiGetDeviceRegistryPropertyW = modsetupapi.NewProc("SetupDiGetDeviceRegistryPropertyW") + procSetupDiGetDriverInfoDetailW = modsetupapi.NewProc("SetupDiGetDriverInfoDetailW") + procSetupDiGetSelectedDevice = modsetupapi.NewProc("SetupDiGetSelectedDevice") + procSetupDiGetSelectedDriverW = modsetupapi.NewProc("SetupDiGetSelectedDriverW") + procSetupDiOpenDevRegKey = modsetupapi.NewProc("SetupDiOpenDevRegKey") + procSetupDiSetClassInstallParamsW = modsetupapi.NewProc("SetupDiSetClassInstallParamsW") + procSetupDiSetDeviceInstallParamsW = modsetupapi.NewProc("SetupDiSetDeviceInstallParamsW") + procSetupDiSetDeviceRegistryPropertyW = modsetupapi.NewProc("SetupDiSetDeviceRegistryPropertyW") + procSetupDiSetSelectedDevice = modsetupapi.NewProc("SetupDiSetSelectedDevice") + procSetupDiSetSelectedDriverW = modsetupapi.NewProc("SetupDiSetSelectedDriverW") + procSetupUninstallOEMInfW = modsetupapi.NewProc("SetupUninstallOEMInfW") procCommandLineToArgvW = modshell32.NewProc("CommandLineToArgvW") procSHGetKnownFolderPath = modshell32.NewProc("SHGetKnownFolderPath") procShellExecuteW = modshell32.NewProc("ShellExecuteW") @@ -447,6 +484,30 @@ var ( procWTSQueryUserToken = modwtsapi32.NewProc("WTSQueryUserToken") ) +func cm_Get_DevNode_Status(status *uint32, problemNumber *uint32, devInst DEVINST, flags uint32) (ret CONFIGRET) { + r0, _, _ := syscall.Syscall6(procCM_Get_DevNode_Status.Addr(), 4, uintptr(unsafe.Pointer(status)), uintptr(unsafe.Pointer(problemNumber)), uintptr(devInst), uintptr(flags), 0, 0) + ret = CONFIGRET(r0) + return +} + +func cm_Get_Device_Interface_List(interfaceClass *GUID, deviceID *uint16, buffer *uint16, bufferLen uint32, flags uint32) (ret CONFIGRET) { + r0, _, _ := syscall.Syscall6(procCM_Get_Device_Interface_ListW.Addr(), 5, uintptr(unsafe.Pointer(interfaceClass)), uintptr(unsafe.Pointer(deviceID)), uintptr(unsafe.Pointer(buffer)), uintptr(bufferLen), uintptr(flags), 0) + ret = CONFIGRET(r0) + return +} + +func cm_Get_Device_Interface_List_Size(len *uint32, interfaceClass *GUID, deviceID *uint16, flags uint32) (ret CONFIGRET) { + r0, _, _ := syscall.Syscall6(procCM_Get_Device_Interface_List_SizeW.Addr(), 4, uintptr(unsafe.Pointer(len)), uintptr(unsafe.Pointer(interfaceClass)), uintptr(unsafe.Pointer(deviceID)), uintptr(flags), 0, 0) + ret = CONFIGRET(r0) + return +} + +func cm_MapCrToWin32Err(configRet CONFIGRET, defaultWin32Error Errno) (ret Errno) { + r0, _, _ := syscall.Syscall(procCM_MapCrToWin32Err.Addr(), 2, uintptr(configRet), uintptr(defaultWin32Error), 0) + ret = Errno(r0) + return +} + func AdjustTokenGroups(token Token, resetToDefault bool, newstate *Tokengroups, buflen uint32, prevstate *Tokengroups, returnlen *uint32) (err error) { var _p0 uint32 if resetToDefault { @@ -1716,6 +1777,15 @@ func ExitProcess(exitcode uint32) { return } +func ExpandEnvironmentStrings(src *uint16, dst *uint16, size uint32) (n uint32, err error) { + r0, _, e1 := syscall.Syscall(procExpandEnvironmentStringsW.Addr(), 3, uintptr(unsafe.Pointer(src)), uintptr(unsafe.Pointer(dst)), uintptr(size)) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) + } + return +} + func FindClose(handle Handle) (err error) { r1, _, e1 := syscall.Syscall(procFindClose.Addr(), 1, uintptr(handle), 0, 0) if r1 == 0 { @@ -2499,6 +2569,22 @@ func MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow ui return } +func Module32First(snapshot Handle, moduleEntry *ModuleEntry32) (err error) { + r1, _, e1 := syscall.Syscall(procModule32FirstW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(moduleEntry)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func Module32Next(snapshot Handle, moduleEntry *ModuleEntry32) (err error) { + r1, _, e1 := syscall.Syscall(procModule32NextW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(moduleEntry)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) { r1, _, e1 := syscall.Syscall(procMoveFileExW.Addr(), 3, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), uintptr(flags)) if r1 == 0 { @@ -3432,6 +3518,233 @@ func TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint return } +func SetupDiBuildDriverInfoList(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT) (err error) { + r1, _, e1 := syscall.Syscall(procSetupDiBuildDriverInfoList.Addr(), 3, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(driverType)) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetupDiCallClassInstaller(installFunction DI_FUNCTION, deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) { + r1, _, e1 := syscall.Syscall(procSetupDiCallClassInstaller.Addr(), 3, uintptr(installFunction), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetupDiCancelDriverInfoSearch(deviceInfoSet DevInfo) (err error) { + r1, _, e1 := syscall.Syscall(procSetupDiCancelDriverInfoSearch.Addr(), 1, uintptr(deviceInfoSet), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func setupDiClassGuidsFromNameEx(className *uint16, classGuidList *GUID, classGuidListSize uint32, requiredSize *uint32, machineName *uint16, reserved uintptr) (err error) { + r1, _, e1 := syscall.Syscall6(procSetupDiClassGuidsFromNameExW.Addr(), 6, uintptr(unsafe.Pointer(className)), uintptr(unsafe.Pointer(classGuidList)), uintptr(classGuidListSize), uintptr(unsafe.Pointer(requiredSize)), uintptr(unsafe.Pointer(machineName)), uintptr(reserved)) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func setupDiClassNameFromGuidEx(classGUID *GUID, className *uint16, classNameSize uint32, requiredSize *uint32, machineName *uint16, reserved uintptr) (err error) { + r1, _, e1 := syscall.Syscall6(procSetupDiClassNameFromGuidExW.Addr(), 6, uintptr(unsafe.Pointer(classGUID)), uintptr(unsafe.Pointer(className)), uintptr(classNameSize), uintptr(unsafe.Pointer(requiredSize)), uintptr(unsafe.Pointer(machineName)), uintptr(reserved)) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func setupDiCreateDeviceInfoListEx(classGUID *GUID, hwndParent uintptr, machineName *uint16, reserved uintptr) (handle DevInfo, err error) { + r0, _, e1 := syscall.Syscall6(procSetupDiCreateDeviceInfoListExW.Addr(), 4, uintptr(unsafe.Pointer(classGUID)), uintptr(hwndParent), uintptr(unsafe.Pointer(machineName)), uintptr(reserved), 0, 0) + handle = DevInfo(r0) + if handle == DevInfo(InvalidHandle) { + err = errnoErr(e1) + } + return +} + +func setupDiCreateDeviceInfo(deviceInfoSet DevInfo, DeviceName *uint16, classGUID *GUID, DeviceDescription *uint16, hwndParent uintptr, CreationFlags DICD, deviceInfoData *DevInfoData) (err error) { + r1, _, e1 := syscall.Syscall9(procSetupDiCreateDeviceInfoW.Addr(), 7, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(DeviceName)), uintptr(unsafe.Pointer(classGUID)), uintptr(unsafe.Pointer(DeviceDescription)), uintptr(hwndParent), uintptr(CreationFlags), uintptr(unsafe.Pointer(deviceInfoData)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetupDiDestroyDeviceInfoList(deviceInfoSet DevInfo) (err error) { + r1, _, e1 := syscall.Syscall(procSetupDiDestroyDeviceInfoList.Addr(), 1, uintptr(deviceInfoSet), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetupDiDestroyDriverInfoList(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT) (err error) { + r1, _, e1 := syscall.Syscall(procSetupDiDestroyDriverInfoList.Addr(), 3, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(driverType)) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func setupDiEnumDeviceInfo(deviceInfoSet DevInfo, memberIndex uint32, deviceInfoData *DevInfoData) (err error) { + r1, _, e1 := syscall.Syscall(procSetupDiEnumDeviceInfo.Addr(), 3, uintptr(deviceInfoSet), uintptr(memberIndex), uintptr(unsafe.Pointer(deviceInfoData))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func setupDiEnumDriverInfo(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverType SPDIT, memberIndex uint32, driverInfoData *DrvInfoData) (err error) { + r1, _, e1 := syscall.Syscall6(procSetupDiEnumDriverInfoW.Addr(), 5, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(driverType), uintptr(memberIndex), uintptr(unsafe.Pointer(driverInfoData)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func setupDiGetClassDevsEx(classGUID *GUID, Enumerator *uint16, hwndParent uintptr, Flags DIGCF, deviceInfoSet DevInfo, machineName *uint16, reserved uintptr) (handle DevInfo, err error) { + r0, _, e1 := syscall.Syscall9(procSetupDiGetClassDevsExW.Addr(), 7, uintptr(unsafe.Pointer(classGUID)), uintptr(unsafe.Pointer(Enumerator)), uintptr(hwndParent), uintptr(Flags), uintptr(deviceInfoSet), uintptr(unsafe.Pointer(machineName)), uintptr(reserved), 0, 0) + handle = DevInfo(r0) + if handle == DevInfo(InvalidHandle) { + err = errnoErr(e1) + } + return +} + +func SetupDiGetClassInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32, requiredSize *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procSetupDiGetClassInstallParamsW.Addr(), 5, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(classInstallParams)), uintptr(classInstallParamsSize), uintptr(unsafe.Pointer(requiredSize)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func setupDiGetDeviceInfoListDetail(deviceInfoSet DevInfo, deviceInfoSetDetailData *DevInfoListDetailData) (err error) { + r1, _, e1 := syscall.Syscall(procSetupDiGetDeviceInfoListDetailW.Addr(), 2, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoSetDetailData)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func setupDiGetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) (err error) { + r1, _, e1 := syscall.Syscall(procSetupDiGetDeviceInstallParamsW.Addr(), 3, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(deviceInstallParams))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func setupDiGetDeviceInstanceId(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, instanceId *uint16, instanceIdSize uint32, instanceIdRequiredSize *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procSetupDiGetDeviceInstanceIdW.Addr(), 5, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(instanceId)), uintptr(instanceIdSize), uintptr(unsafe.Pointer(instanceIdRequiredSize)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func setupDiGetDeviceProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, propertyKey *DEVPROPKEY, propertyType *DEVPROPTYPE, propertyBuffer *byte, propertyBufferSize uint32, requiredSize *uint32, flags uint32) (err error) { + r1, _, e1 := syscall.Syscall9(procSetupDiGetDevicePropertyW.Addr(), 8, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(propertyKey)), uintptr(unsafe.Pointer(propertyType)), uintptr(unsafe.Pointer(propertyBuffer)), uintptr(propertyBufferSize), uintptr(unsafe.Pointer(requiredSize)), uintptr(flags), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func setupDiGetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyRegDataType *uint32, propertyBuffer *byte, propertyBufferSize uint32, requiredSize *uint32) (err error) { + r1, _, e1 := syscall.Syscall9(procSetupDiGetDeviceRegistryPropertyW.Addr(), 7, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(property), uintptr(unsafe.Pointer(propertyRegDataType)), uintptr(unsafe.Pointer(propertyBuffer)), uintptr(propertyBufferSize), uintptr(unsafe.Pointer(requiredSize)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func setupDiGetDriverInfoDetail(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData, driverInfoDetailData *DrvInfoDetailData, driverInfoDetailDataSize uint32, requiredSize *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procSetupDiGetDriverInfoDetailW.Addr(), 6, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(driverInfoData)), uintptr(unsafe.Pointer(driverInfoDetailData)), uintptr(driverInfoDetailDataSize), uintptr(unsafe.Pointer(requiredSize))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func setupDiGetSelectedDevice(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) { + r1, _, e1 := syscall.Syscall(procSetupDiGetSelectedDevice.Addr(), 2, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func setupDiGetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (err error) { + r1, _, e1 := syscall.Syscall(procSetupDiGetSelectedDriverW.Addr(), 3, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(driverInfoData))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetupDiOpenDevRegKey(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, Scope DICS_FLAG, HwProfile uint32, KeyType DIREG, samDesired uint32) (key Handle, err error) { + r0, _, e1 := syscall.Syscall6(procSetupDiOpenDevRegKey.Addr(), 6, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(Scope), uintptr(HwProfile), uintptr(KeyType), uintptr(samDesired)) + key = Handle(r0) + if key == InvalidHandle { + err = errnoErr(e1) + } + return +} + +func SetupDiSetClassInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, classInstallParams *ClassInstallHeader, classInstallParamsSize uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procSetupDiSetClassInstallParamsW.Addr(), 4, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(classInstallParams)), uintptr(classInstallParamsSize), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetupDiSetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) (err error) { + r1, _, e1 := syscall.Syscall(procSetupDiSetDeviceInstallParamsW.Addr(), 3, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(deviceInstallParams))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func setupDiSetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, property SPDRP, propertyBuffer *byte, propertyBufferSize uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procSetupDiSetDeviceRegistryPropertyW.Addr(), 5, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(property), uintptr(unsafe.Pointer(propertyBuffer)), uintptr(propertyBufferSize), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetupDiSetSelectedDevice(deviceInfoSet DevInfo, deviceInfoData *DevInfoData) (err error) { + r1, _, e1 := syscall.Syscall(procSetupDiSetSelectedDevice.Addr(), 2, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetupDiSetSelectedDriver(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, driverInfoData *DrvInfoData) (err error) { + r1, _, e1 := syscall.Syscall(procSetupDiSetSelectedDriverW.Addr(), 3, uintptr(deviceInfoSet), uintptr(unsafe.Pointer(deviceInfoData)), uintptr(unsafe.Pointer(driverInfoData))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func setupUninstallOEMInf(infFileName *uint16, flags SUOI, reserved uintptr) (err error) { + r1, _, e1 := syscall.Syscall(procSetupUninstallOEMInfW.Addr(), 3, uintptr(unsafe.Pointer(infFileName)), uintptr(flags), uintptr(reserved)) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) { r0, _, e1 := syscall.Syscall(procCommandLineToArgvW.Addr(), 2, uintptr(unsafe.Pointer(cmd)), uintptr(unsafe.Pointer(argc)), 0) argv = (*[8192]*[8192]uint16)(unsafe.Pointer(r0)) diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 0c107cd5ea..5ce2fe2f63 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -42,7 +42,7 @@ golang.org/x/mod/zip # golang.org/x/sync v0.0.0-20210220032951-036812b2e83c ## explicit golang.org/x/sync/semaphore -# golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e +# golang.org/x/sys v0.0.0-20211205182925-97ca703d548d ## explicit; go 1.17 golang.org/x/sys/internal/unsafeheader golang.org/x/sys/plan9 diff --git a/src/go.mod b/src/go.mod index d26e4960b3..24d034b810 100644 --- a/src/go.mod +++ b/src/go.mod @@ -8,6 +8,6 @@ require ( ) require ( - golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e // indirect + golang.org/x/sys v0.0.0-20211205182925-97ca703d548d // indirect golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 // indirect ) diff --git a/src/go.sum b/src/go.sum index fddc4fbe93..d063e65530 100644 --- a/src/go.sum +++ b/src/go.sum @@ -2,7 +2,7 @@ golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa h1:idItI2DDfCokpg0N51B2Vt golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 h1:0qxwC5n+ttVOINCBeRHO0nq9X7uy8SDsPoi5OaCdIEI= golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e h1:i6Vklmyu+fZMFYpum+sR4ZWABGW7MyIxfJZXYvcnbns= -golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211205182925-97ca703d548d h1:FjkYO/PPp4Wi0EAUOVLxePm7qVW4r4ctbWpURyuOD0E= +golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 h1:GLw7MR8AfAG2GmGcmVgObFOHXYypgGjnGno25RDwn3Y= golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0= diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go b/src/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go index 3298a87e98..fa7cdb9bcd 100644 --- a/src/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go +++ b/src/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go @@ -15,7 +15,3 @@ func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) // xgetbv with ecx = 0 is implemented in cpu_x86.s for gc compiler // and in cpu_gccgo.c for gccgo. func xgetbv() (eax, edx uint32) - -// darwinSupportsAVX512 is implemented in cpu_x86.s for gc compiler -// and in cpu_gccgo_x86.go for gccgo. -func darwinSupportsAVX512() bool diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index 2650806683..bef622891e 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -19,7 +19,7 @@ golang.org/x/net/idna golang.org/x/net/lif golang.org/x/net/nettest golang.org/x/net/route -# golang.org/x/sys v0.0.0-20211109065445-02f5c0300f6e +# golang.org/x/sys v0.0.0-20211205182925-97ca703d548d ## explicit; go 1.17 golang.org/x/sys/cpu # golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 -- GitLab From f8a8a73096a4d36ce7d35e9643db89e669bbee1f Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sun, 5 Dec 2021 22:18:04 -0500 Subject: [PATCH 2412/2500] go/types, types2: unexport NewTypeList NewTypeList was not part of the go/types API proposal, and was left in by accident. It also shouldn't be necessary, so remove it. Updates #47916 Change-Id: I4db3ccf036ccfb708ecf2c176ea4921fe68089a4 Reviewed-on: https://go-review.googlesource.com/c/go/+/369475 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Gopher Robot Reviewed-by: Robert Griesemer --- doc/go1.18.html | 4 +--- src/cmd/compile/internal/types2/check.go | 2 +- src/cmd/compile/internal/types2/instantiate.go | 2 +- src/cmd/compile/internal/types2/typelists.go | 4 ++-- src/cmd/compile/internal/types2/typexpr.go | 4 ++-- src/go/types/check.go | 2 +- src/go/types/instantiate.go | 2 +- src/go/types/typelists.go | 4 ++-- src/go/types/typexpr.go | 4 ++-- 9 files changed, 13 insertions(+), 15 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 16a5a6723c..35b3d744ec 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -516,9 +516,7 @@ Do not send CLs removing the interior tags from such phrases.
  • The new type - TypeList and factory function - NewTypeList facilitate storing - a list of types. + TypeList holds a list of types.
  • ignoring struct tags (see below), - x's type and T have identical - underlying types. + x's type and T are not + type parameters but have + identical underlying types.
  • ignoring struct tags (see below), x's type and T are pointer types that are not named types, - and their pointer base types have identical underlying types. + and their pointer base types are not type parameters but + have identical underlying types.
  • x's type and T are both integer or floating -- GitLab From 2580d0e08d5e9f979b943758d3c49877fb2324cb Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 1 Dec 2021 12:15:45 -0500 Subject: [PATCH 2489/2500] all: gofmt -w -r 'interface{} -> any' src And then revert the bootstrap cmd directories and certain testdata. And adjust tests as needed. Not reverting the changes in std that are bootstrapped, because some of those changes would appear in API docs, and we want to use any consistently. Instead, rewrite 'any' to 'interface{}' in cmd/dist for those directories when preparing the bootstrap copy. A few files changed as a result of running gofmt -w not because of interface{} -> any but because they hadn't been updated for the new //go:build lines. Fixes #49884. Change-Id: Ie8045cba995f65bd79c694ec77a1b3d1fe01bb09 Reviewed-on: https://go-review.googlesource.com/c/go/+/368254 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Robert Griesemer TryBot-Result: Gopher Robot --- src/archive/tar/common.go | 2 +- src/archive/tar/reader_test.go | 4 +- src/archive/tar/tar_test.go | 2 +- src/archive/tar/writer_test.go | 6 +- src/archive/zip/reader.go | 2 +- src/archive/zip/struct.go | 2 +- src/builtin/builtin.go | 4 +- src/bytes/reader_test.go | 2 +- src/cmd/api/goapi.go | 2 +- .../testdata/src/issue21181/p/p_generic.go | 1 + src/cmd/api/testdata/src/pkg/p1/p1.go | 2 +- src/cmd/api/testdata/src/pkg/p4/p4.go | 4 +- .../internal/importer/gcimporter_test.go | 2 +- src/cmd/cover/testdata/test.go | 4 +- src/cmd/dist/buildtool.go | 7 +- src/cmd/doc/pkg.go | 6 +- src/cmd/doc/testdata/nested/ignore.go | 1 + src/cmd/fix/cftype.go | 8 +- src/cmd/fix/fix.go | 8 +- src/cmd/fix/gotypes.go | 2 +- src/cmd/fix/main.go | 2 +- src/cmd/fix/netipv6zone.go | 2 +- src/cmd/fix/printerconfig.go | 2 +- src/cmd/fix/typecheck.go | 12 +- src/cmd/go/internal/base/base.go | 6 +- src/cmd/go/internal/cmdflag/flag.go | 2 +- src/cmd/go/internal/fsys/fsys.go | 6 +- src/cmd/go/internal/generate/generate.go | 2 +- src/cmd/go/internal/help/help.go | 2 +- .../go/internal/imports/testdata/android/e.go | 1 + .../go/internal/imports/testdata/android/f.go | 1 + .../go/internal/imports/testdata/android/g.go | 1 + .../go/internal/imports/testdata/illumos/e.go | 1 + .../go/internal/imports/testdata/illumos/f.go | 1 + .../go/internal/imports/testdata/illumos/g.go | 1 + .../go/internal/imports/testdata/star/x1.go | 7 +- src/cmd/go/internal/list/list.go | 6 +- src/cmd/go/internal/load/pkg.go | 20 +-- src/cmd/go/internal/modcmd/tidy.go | 4 +- src/cmd/go/internal/modfetch/cache.go | 12 +- .../go/internal/modfetch/codehost/codehost.go | 4 +- src/cmd/go/internal/modfetch/codehost/git.go | 4 +- src/cmd/go/internal/modfetch/codehost/vcs.go | 4 +- src/cmd/go/internal/modfetch/coderepo.go | 4 +- src/cmd/go/internal/modfetch/fetch.go | 4 +- src/cmd/go/internal/modfetch/repo.go | 6 +- src/cmd/go/internal/modget/get.go | 4 +- src/cmd/go/internal/modload/buildlist.go | 2 +- src/cmd/go/internal/modload/import.go | 4 +- src/cmd/go/internal/modload/load.go | 4 +- src/cmd/go/internal/modload/modfile.go | 4 +- src/cmd/go/internal/modload/vendor.go | 2 +- src/cmd/go/internal/mvs/mvs.go | 2 +- src/cmd/go/internal/par/work.go | 32 ++-- src/cmd/go/internal/par/work_test.go | 12 +- src/cmd/go/internal/run/run.go | 2 +- src/cmd/go/internal/str/str.go | 2 +- src/cmd/go/internal/vcs/vcs.go | 4 +- src/cmd/go/internal/work/action.go | 8 +- src/cmd/go/internal/work/build_test.go | 2 +- src/cmd/go/internal/work/exec.go | 10 +- src/cmd/go/internal/work/gc.go | 10 +- src/cmd/go/proxy_test.go | 4 +- src/cmd/go/script_test.go | 4 +- src/cmd/go/testdata/addmod.go | 3 +- src/cmd/go/testdata/savedir.go | 1 + .../testterminal18153/terminal_test.go | 1 + src/cmd/gofmt/gofmt.go | 2 +- src/cmd/internal/buildid/buildid_test.go | 2 +- src/cmd/internal/buildid/rewrite.go | 2 +- src/cmd/internal/test2json/test2json_test.go | 2 +- src/cmd/internal/traceviewer/format.go | 28 ++-- src/cmd/nm/nm.go | 2 +- src/cmd/pack/pack_test.go | 4 +- src/cmd/pprof/readlineui.go | 6 +- src/cmd/trace/main.go | 2 +- src/cmd/trace/mmu.go | 2 +- src/cmd/trace/trace.go | 2 +- src/container/heap/example_intheap_test.go | 4 +- src/container/heap/example_pq_test.go | 4 +- src/container/heap/heap.go | 10 +- src/container/heap/heap_test.go | 4 +- src/container/list/list.go | 14 +- src/container/list/list_test.go | 46 +++--- src/container/ring/example_test.go | 8 +- src/container/ring/ring.go | 4 +- src/container/ring/ring_test.go | 2 +- src/context/context.go | 16 +- src/context/context_test.go | 20 +-- src/crypto/crypto.go | 6 +- .../edwards25519/scalar_alias_test.go | 2 +- src/crypto/tls/cipher_suites.go | 8 +- src/crypto/tls/common.go | 2 +- src/crypto/tls/conn.go | 16 +- src/crypto/tls/generate_cert.go | 4 +- src/crypto/tls/handshake_client.go | 2 +- src/crypto/tls/handshake_client_test.go | 4 +- src/crypto/tls/handshake_messages_test.go | 2 +- src/crypto/tls/handshake_server.go | 2 +- src/crypto/tls/handshake_server_test.go | 6 +- src/crypto/x509/name_constraints_test.go | 2 +- src/crypto/x509/parser.go | 2 +- src/crypto/x509/pkcs8.go | 4 +- src/crypto/x509/pkix/pkix.go | 2 +- src/crypto/x509/verify.go | 14 +- src/crypto/x509/x509.go | 20 +-- src/crypto/x509/x509_test.go | 8 +- src/database/sql/convert.go | 14 +- src/database/sql/convert_test.go | 42 +++--- src/database/sql/driver/driver.go | 2 +- src/database/sql/driver/types.go | 18 +-- src/database/sql/driver/types_test.go | 4 +- src/database/sql/fakedb_test.go | 32 ++-- src/database/sql/sql.go | 96 ++++++------ src/database/sql/sql_test.go | 40 ++--- src/debug/dwarf/entry.go | 6 +- src/debug/dwarf/entry_test.go | 2 +- src/debug/elf/elf_test.go | 2 +- src/debug/elf/file.go | 2 +- src/debug/gosym/symtab.go | 2 +- src/debug/macho/file.go | 2 +- src/debug/macho/file_test.go | 12 +- src/debug/pe/file.go | 6 +- src/debug/pe/file_test.go | 4 +- src/debug/plan9obj/file.go | 2 +- src/embed/embed.go | 2 +- src/embed/internal/embedtest/embed_test.go | 2 +- src/encoding/ascii85/ascii85_test.go | 2 +- src/encoding/asn1/asn1.go | 6 +- src/encoding/asn1/asn1_test.go | 10 +- src/encoding/asn1/marshal.go | 4 +- src/encoding/asn1/marshal_test.go | 12 +- src/encoding/base32/base32_test.go | 2 +- src/encoding/base64/base64_test.go | 2 +- src/encoding/binary/binary.go | 8 +- src/encoding/binary/binary_test.go | 16 +- src/encoding/binary/example_test.go | 2 +- src/encoding/gob/codec_test.go | 34 ++--- src/encoding/gob/debug.go | 2 +- src/encoding/gob/decoder.go | 2 +- src/encoding/gob/encode.go | 2 +- src/encoding/gob/encoder.go | 2 +- src/encoding/gob/encoder_test.go | 48 +++--- src/encoding/gob/error.go | 2 +- src/encoding/gob/gobencdec_test.go | 2 +- src/encoding/gob/timing_test.go | 18 +-- src/encoding/gob/type.go | 8 +- src/encoding/gob/type_test.go | 4 +- src/encoding/json/bench_test.go | 2 +- src/encoding/json/decode.go | 20 +-- src/encoding/json/decode_test.go | 106 +++++++------- src/encoding/json/encode.go | 10 +- src/encoding/json/encode_test.go | 112 +++++++------- src/encoding/json/example_test.go | 2 +- src/encoding/json/fuzz.go | 8 +- src/encoding/json/scanner.go | 2 +- src/encoding/json/scanner_test.go | 10 +- src/encoding/json/stream.go | 8 +- src/encoding/json/stream_test.go | 70 ++++----- src/encoding/json/tagkey_test.go | 6 +- src/encoding/xml/marshal.go | 8 +- src/encoding/xml/marshal_test.go | 38 ++--- src/encoding/xml/read.go | 8 +- src/encoding/xml/read_test.go | 6 +- src/encoding/xml/xml.go | 2 +- src/errors/wrap.go | 4 +- src/errors/wrap_test.go | 8 +- src/expvar/expvar.go | 10 +- src/expvar/expvar_test.go | 8 +- src/flag/flag.go | 22 +-- src/fmt/errors.go | 2 +- src/fmt/fmt_test.go | 50 +++---- src/fmt/print.go | 34 ++--- src/fmt/scan.go | 26 ++-- src/fmt/scan_test.go | 20 +-- src/go/ast/print.go | 18 +-- src/go/ast/print_test.go | 2 +- src/go/ast/resolve.go | 2 +- src/go/ast/scope.go | 8 +- src/go/constant/value.go | 4 +- src/go/constant/value_test.go | 4 +- src/go/doc/doc.go | 2 +- src/go/doc/doc_test.go | 2 +- src/go/doc/testdata/benchmark.go | 4 +- src/go/doc/testdata/testing.0.golden | 24 +-- src/go/doc/testdata/testing.1.golden | 40 ++--- src/go/doc/testdata/testing.2.golden | 24 +-- src/go/doc/testdata/testing.go | 20 +-- src/go/format/format.go | 2 +- src/go/internal/gccgoimporter/parser.go | 32 ++-- src/go/internal/gcimporter/gcimporter_test.go | 2 +- src/go/internal/gcimporter/support.go | 2 +- .../internal/gcimporter/testdata/exports.go | 6 +- src/go/parser/error_test.go | 2 +- src/go/parser/interface.go | 6 +- src/go/parser/parser.go | 2 +- src/go/parser/resolver.go | 6 +- src/go/printer/printer.go | 14 +- src/go/printer/testdata/parser.go | 4 +- src/go/scanner/scanner.go | 2 +- src/go/token/serialize.go | 4 +- src/go/token/serialize_test.go | 4 +- src/go/types/check.go | 4 +- src/go/types/conversions.go | 2 +- src/go/types/errors.go | 20 +-- src/go/types/eval_test.go | 4 +- src/go/types/expr.go | 4 +- src/go/types/gotype.go | 2 +- src/go/types/hilbert_test.go | 2 +- src/go/types/initorder.go | 4 +- src/go/types/instantiate.go | 2 +- src/go/types/operand.go | 2 +- src/go/types/sizeof_test.go | 6 +- src/go/types/stdlib_test.go | 4 +- src/go/types/stmt.go | 4 +- src/go/types/subst.go | 4 +- src/html/template/content.go | 6 +- src/html/template/content_test.go | 4 +- src/html/template/css.go | 4 +- src/html/template/error.go | 2 +- src/html/template/escape.go | 8 +- src/html/template/escape_test.go | 12 +- src/html/template/example_test.go | 2 +- src/html/template/exec_test.go | 36 ++--- src/html/template/html.go | 12 +- src/html/template/js.go | 10 +- src/html/template/js_test.go | 14 +- src/html/template/template.go | 8 +- src/html/template/template_test.go | 2 +- src/html/template/url.go | 10 +- src/html/template/url_test.go | 2 +- src/image/draw/draw_test.go | 4 +- src/internal/abi/abi.go | 4 +- src/internal/fmtsort/sort_test.go | 14 +- src/internal/fuzz/encoding.go | 12 +- src/internal/fuzz/fuzz.go | 14 +- src/internal/fuzz/minimize_test.go | 34 ++--- src/internal/fuzz/mutator.go | 2 +- src/internal/fuzz/mutator_test.go | 10 +- src/internal/fuzz/queue.go | 10 +- src/internal/fuzz/worker.go | 10 +- src/internal/fuzz/worker_test.go | 6 +- src/internal/intern/intern.go | 10 +- src/internal/lazytemplate/lazytemplate.go | 2 +- src/internal/nettrace/nettrace.go | 2 +- src/internal/poll/splice_linux.go | 2 +- src/internal/poll/splice_linux_test.go | 2 +- src/internal/reflectlite/all_test.go | 32 ++-- src/internal/reflectlite/export_test.go | 2 +- src/internal/reflectlite/set_test.go | 12 +- src/internal/reflectlite/swapper.go | 2 +- src/internal/reflectlite/type.go | 2 +- src/internal/reflectlite/value.go | 26 ++-- src/internal/singleflight/singleflight.go | 10 +- .../singleflight/singleflight_test.go | 6 +- .../syscall/windows/registry/registry_test.go | 2 +- src/internal/trace/gc.go | 8 +- .../unsafeheader/unsafeheader_test.go | 2 +- src/io/fs/fs.go | 2 +- src/io/io.go | 2 +- src/log/log.go | 36 ++--- src/math/all_test.go | 2 +- src/math/big/floatconv_test.go | 2 +- src/math/bits/make_examples.go | 20 +-- src/math/rand/example_test.go | 2 +- src/math/rand/regress_test.go | 6 +- src/mime/quotedprintable/reader_test.go | 4 +- src/mime/type.go | 2 +- src/net/http/cgi/host.go | 2 +- src/net/http/client_test.go | 2 +- src/net/http/clientserver_test.go | 10 +- src/net/http/cookie_test.go | 2 +- src/net/http/fs_test.go | 2 +- src/net/http/h2_bundle.go | 52 +++---- src/net/http/header.go | 2 +- src/net/http/httptrace/trace.go | 2 +- src/net/http/httputil/dump_test.go | 2 +- src/net/http/httputil/reverseproxy.go | 2 +- src/net/http/omithttp2.go | 6 +- src/net/http/requestwrite_test.go | 2 +- src/net/http/response_test.go | 16 +- src/net/http/roundtrip_js.go | 12 +- src/net/http/serve_test.go | 16 +- src/net/http/server.go | 8 +- src/net/http/transfer.go | 6 +- src/net/http/transport.go | 4 +- src/net/http/transport_test.go | 10 +- src/net/ip_test.go | 2 +- src/net/listen_test.go | 2 +- src/net/lookup.go | 10 +- src/net/lookup_test.go | 2 +- src/net/lookup_windows_test.go | 2 +- src/net/mail/message.go | 2 +- src/net/netip/netip_test.go | 2 +- src/net/platform_test.go | 2 +- src/net/rpc/client.go | 22 +-- src/net/rpc/client_test.go | 4 +- src/net/rpc/debug.go | 2 +- src/net/rpc/jsonrpc/all_test.go | 6 +- src/net/rpc/jsonrpc/client.go | 12 +- src/net/rpc/jsonrpc/server.go | 10 +- src/net/rpc/server.go | 20 +-- src/net/rpc/server_test.go | 8 +- src/net/smtp/smtp.go | 2 +- src/net/textproto/textproto.go | 2 +- src/net/textproto/writer.go | 2 +- src/net/url/example_test.go | 2 +- src/net/url/url_test.go | 2 +- src/os/dir_unix.go | 2 +- src/os/env_test.go | 2 +- src/os/exec.go | 4 +- src/os/exec/exec.go | 2 +- src/os/exec/exec_test.go | 2 +- src/os/exec_plan9.go | 4 +- src/os/exec_posix.go | 4 +- src/os/stat_plan9.go | 2 +- src/os/types_plan9.go | 4 +- src/os/types_unix.go | 2 +- src/os/types_windows.go | 2 +- src/os/user/lookup_unix.go | 8 +- src/plugin/plugin.go | 4 +- src/plugin/plugin_dlopen.go | 4 +- src/reflect/abi_test.go | 6 +- src/reflect/all_test.go | 138 +++++++++--------- src/reflect/deepequal.go | 2 +- src/reflect/example_test.go | 4 +- src/reflect/export_test.go | 2 +- src/reflect/set_test.go | 18 +-- src/reflect/swapper.go | 2 +- src/reflect/type.go | 18 +-- src/reflect/value.go | 30 ++-- src/reflect/visiblefields_test.go | 4 +- src/runtime/abi_test.go | 2 +- src/runtime/alg.go | 2 +- src/runtime/cgo.go | 2 +- src/runtime/cgo/handle.go | 4 +- src/runtime/cgo/handle_test.go | 6 +- src/runtime/cgocall.go | 4 +- src/runtime/chan_test.go | 2 +- src/runtime/crash_test.go | 2 +- src/runtime/debug/garbage_test.go | 4 +- src/runtime/debugcall.go | 2 +- src/runtime/debuglog.go | 2 +- src/runtime/defer_test.go | 2 +- src/runtime/error.go | 4 +- src/runtime/export_debug_test.go | 4 +- src/runtime/export_debuglog_test.go | 18 +-- src/runtime/export_test.go | 10 +- src/runtime/gc_test.go | 12 +- src/runtime/gcinfo_test.go | 28 ++-- src/runtime/hash_test.go | 2 +- src/runtime/iface.go | 10 +- src/runtime/iface_test.go | 16 +- src/runtime/internal/atomic/bench_test.go | 2 +- src/runtime/lfstack_test.go | 2 +- src/runtime/malloc_test.go | 12 +- src/runtime/map_benchmark_test.go | 6 +- src/runtime/map_test.go | 6 +- src/runtime/mbitmap.go | 4 +- src/runtime/mfinal.go | 6 +- src/runtime/mfinal_test.go | 16 +- src/runtime/mgcscavenge.go | 2 +- src/runtime/mkpreempt.go | 2 +- src/runtime/netpoll.go | 12 +- src/runtime/os_windows.go | 4 +- src/runtime/panic.go | 4 +- src/runtime/plugin.go | 6 +- src/runtime/pprof/mprof_test.go | 2 +- src/runtime/pprof/pprof.go | 8 +- src/runtime/pprof/pprof_test.go | 4 +- src/runtime/pprof/proto_test.go | 2 +- src/runtime/race/race_test.go | 2 +- src/runtime/race/testdata/issue12664_test.go | 2 +- src/runtime/race/testdata/mop_test.go | 18 +-- src/runtime/race/testdata/pool_test.go | 4 +- src/runtime/runtime2.go | 4 +- src/runtime/runtime_test.go | 4 +- src/runtime/sizeof_test.go | 6 +- src/runtime/softfloat64_test.go | 2 +- src/runtime/stack.go | 2 +- src/runtime/stack_test.go | 2 +- src/runtime/syscall_windows_test.go | 2 +- src/runtime/testdata/testprog/gc.go | 6 +- src/runtime/testdata/testprog/signal.go | 1 + .../testdata/testprog/syscalls_none.go | 1 + src/runtime/testdata/testprogcgo/callback.go | 1 + .../testdata/testprogcgo/catchpanic.go | 1 + src/runtime/testdata/testprogcgo/dropm.go | 1 + src/runtime/testdata/testprogcgo/eintr.go | 1 + src/runtime/testdata/testprogcgo/exec.go | 1 + .../testdata/testprogcgo/lockosthread.go | 1 + .../testdata/testprogcgo/needmdeadlock.go | 1 + .../testdata/testprogcgo/numgoroutine.go | 1 + src/runtime/testdata/testprogcgo/raceprof.go | 1 + src/runtime/testdata/testprogcgo/racesig.go | 1 + src/runtime/testdata/testprogcgo/segv.go | 1 + src/runtime/testdata/testprogcgo/sigstack.go | 1 + .../testdata/testprogcgo/threadpanic.go | 1 + .../testdata/testprogcgo/threadpprof.go | 3 +- .../testdata/testprogcgo/threadprof.go | 4 +- src/runtime/testdata/testprognet/signal.go | 1 + .../testdata/testprognet/signalexec.go | 1 + src/runtime/testdata/testwinlib/main.go | 1 + src/runtime/time.go | 10 +- src/runtime/trace/annotation.go | 2 +- src/sort/slice.go | 6 +- src/sort/slice_go14.go | 2 +- src/strings/export_test.go | 2 +- src/strings/reader_test.go | 2 +- src/sync/atomic/atomic_test.go | 2 +- src/sync/atomic/value.go | 12 +- src/sync/atomic/value_test.go | 18 +-- src/sync/example_pool_test.go | 2 +- src/sync/export_test.go | 18 +-- src/sync/map.go | 40 ++--- src/sync/map_bench_test.go | 4 +- src/sync/map_reference_test.go | 58 ++++---- src/sync/map_test.go | 28 ++-- src/sync/pool.go | 14 +- src/sync/pool_test.go | 12 +- src/sync/poolqueue.go | 18 +-- src/syscall/fs_js.go | 4 +- src/syscall/js/func.go | 4 +- src/syscall/js/js.go | 18 +-- src/syscall/js/js_test.go | 18 +-- src/syscall/net_js.go | 3 +- src/syscall/syscall_windows.go | 6 +- src/testing/allocs_test.go | 2 +- src/testing/example.go | 2 +- src/testing/fstest/mapfs.go | 4 +- src/testing/fstest/testfs.go | 2 +- src/testing/fuzz.go | 10 +- src/testing/internal/testdeps/deps.go | 2 +- src/testing/quick/quick.go | 18 +-- src/testing/testing.go | 50 +++---- src/text/scanner/scanner.go | 2 +- src/text/template/exec.go | 12 +- src/text/template/exec_test.go | 34 ++--- src/text/template/funcs.go | 10 +- src/text/template/parse/lex.go | 2 +- src/text/template/parse/parse.go | 12 +- src/text/template/parse/parse_test.go | 2 +- src/time/internal_test.go | 2 +- src/time/sleep.go | 10 +- src/time/tzdata/generate_zipdata.go | 2 +- 445 files changed, 1906 insertions(+), 1875 deletions(-) diff --git a/src/archive/tar/common.go b/src/archive/tar/common.go index 595de64725..c99b5c1920 100644 --- a/src/archive/tar/common.go +++ b/src/archive/tar/common.go @@ -538,7 +538,7 @@ type headerFileInfo struct { func (fi headerFileInfo) Size() int64 { return fi.h.Size } func (fi headerFileInfo) IsDir() bool { return fi.Mode().IsDir() } func (fi headerFileInfo) ModTime() time.Time { return fi.h.ModTime } -func (fi headerFileInfo) Sys() interface{} { return fi.h } +func (fi headerFileInfo) Sys() any { return fi.h } // Name returns the base name of the file. func (fi headerFileInfo) Name() string { diff --git a/src/archive/tar/reader_test.go b/src/archive/tar/reader_test.go index c31a847ec3..f21a6065b4 100644 --- a/src/archive/tar/reader_test.go +++ b/src/archive/tar/reader_test.go @@ -1363,7 +1363,7 @@ func TestFileReader(t *testing.T) { wantLCnt int64 wantPCnt int64 } - testFnc interface{} // testRead | testWriteTo | testRemaining + testFnc any // testRead | testWriteTo | testRemaining ) type ( @@ -1376,7 +1376,7 @@ func TestFileReader(t *testing.T) { spd sparseDatas size int64 } - fileMaker interface{} // makeReg | makeSparse + fileMaker any // makeReg | makeSparse ) vectors := []struct { diff --git a/src/archive/tar/tar_test.go b/src/archive/tar/tar_test.go index e9fafc7cc7..a476f5eb01 100644 --- a/src/archive/tar/tar_test.go +++ b/src/archive/tar/tar_test.go @@ -23,7 +23,7 @@ import ( type testError struct{ error } -type fileOps []interface{} // []T where T is (string | int64) +type fileOps []any // []T where T is (string | int64) // testFile is an io.ReadWriteSeeker where the IO operations performed // on it must match the list of operations in ops. diff --git a/src/archive/tar/writer_test.go b/src/archive/tar/writer_test.go index 95ce99a3ed..da3fb89e65 100644 --- a/src/archive/tar/writer_test.go +++ b/src/archive/tar/writer_test.go @@ -67,7 +67,7 @@ func TestWriter(t *testing.T) { testClose struct { // Close() == wantErr wantErr error } - testFnc interface{} // testHeader | testWrite | testReadFrom | testClose + testFnc any // testHeader | testWrite | testReadFrom | testClose ) vectors := []struct { @@ -1031,7 +1031,7 @@ func TestFileWriter(t *testing.T) { wantLCnt int64 wantPCnt int64 } - testFnc interface{} // testWrite | testReadFrom | testRemaining + testFnc any // testWrite | testReadFrom | testRemaining ) type ( @@ -1044,7 +1044,7 @@ func TestFileWriter(t *testing.T) { sph sparseHoles size int64 } - fileMaker interface{} // makeReg | makeSparse + fileMaker any // makeReg | makeSparse ) vectors := []struct { diff --git a/src/archive/zip/reader.go b/src/archive/zip/reader.go index 2843a5d658..92fd6f6a92 100644 --- a/src/archive/zip/reader.go +++ b/src/archive/zip/reader.go @@ -670,7 +670,7 @@ func (f *fileListEntry) Size() int64 { return 0 } func (f *fileListEntry) Mode() fs.FileMode { return fs.ModeDir | 0555 } func (f *fileListEntry) Type() fs.FileMode { return fs.ModeDir } func (f *fileListEntry) IsDir() bool { return true } -func (f *fileListEntry) Sys() interface{} { return nil } +func (f *fileListEntry) Sys() any { return nil } func (f *fileListEntry) ModTime() time.Time { if f.file == nil { diff --git a/src/archive/zip/struct.go b/src/archive/zip/struct.go index 88effedc0f..6f73fb8376 100644 --- a/src/archive/zip/struct.go +++ b/src/archive/zip/struct.go @@ -163,7 +163,7 @@ func (fi headerFileInfo) ModTime() time.Time { } func (fi headerFileInfo) Mode() fs.FileMode { return fi.fh.Mode() } func (fi headerFileInfo) Type() fs.FileMode { return fi.fh.Mode().Type() } -func (fi headerFileInfo) Sys() interface{} { return fi.fh } +func (fi headerFileInfo) Sys() any { return fi.fh } func (fi headerFileInfo) Info() (fs.FileInfo, error) { return fi, nil } diff --git a/src/builtin/builtin.go b/src/builtin/builtin.go index 9a94c7357d..08ae7ed313 100644 --- a/src/builtin/builtin.go +++ b/src/builtin/builtin.go @@ -239,7 +239,7 @@ func close(c chan<- Type) // that point, the program is terminated with a non-zero exit code. This // termination sequence is called panicking and can be controlled by the // built-in function recover. -func panic(v interface{}) +func panic(v any) // The recover built-in function allows a program to manage behavior of a // panicking goroutine. Executing a call to recover inside a deferred @@ -250,7 +250,7 @@ func panic(v interface{}) // panicking, or if the argument supplied to panic was nil, recover returns // nil. Thus the return value from recover reports whether the goroutine is // panicking. -func recover() interface{} +func recover() any // The print built-in function formats its arguments in an // implementation-specific way and writes the result to standard error. diff --git a/src/bytes/reader_test.go b/src/bytes/reader_test.go index 8baac5046c..9119c944ac 100644 --- a/src/bytes/reader_test.go +++ b/src/bytes/reader_test.go @@ -76,7 +76,7 @@ func TestReaderAt(t *testing.T) { off int64 n int want string - wanterr interface{} + wanterr any }{ {0, 10, "0123456789", nil}, {1, 10, "123456789", io.EOF}, diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go index a55e51cc9b..036aefe4d8 100644 --- a/src/cmd/api/goapi.go +++ b/src/cmd/api/goapi.go @@ -1071,7 +1071,7 @@ func (w *Walker) emitMethod(m *types.Selection) { w.emitf("method (%s%s) %s%s", w.typeString(recv), tps, m.Obj().Name(), w.signatureString(sig)) } -func (w *Walker) emitf(format string, args ...interface{}) { +func (w *Walker) emitf(format string, args ...any) { f := strings.Join(w.scope, ", ") + ", " + fmt.Sprintf(format, args...) if strings.Contains(f, "\n") { panic("feature contains newlines: " + f) diff --git a/src/cmd/api/testdata/src/issue21181/p/p_generic.go b/src/cmd/api/testdata/src/issue21181/p/p_generic.go index 4d75809676..ad6df20187 100644 --- a/src/cmd/api/testdata/src/issue21181/p/p_generic.go +++ b/src/cmd/api/testdata/src/issue21181/p/p_generic.go @@ -1,3 +1,4 @@ +//go:build !amd64 // +build !amd64 package p diff --git a/src/cmd/api/testdata/src/pkg/p1/p1.go b/src/cmd/api/testdata/src/pkg/p1/p1.go index 65181b248a..81826d768b 100644 --- a/src/cmd/api/testdata/src/pkg/p1/p1.go +++ b/src/cmd/api/testdata/src/pkg/p1/p1.go @@ -197,7 +197,7 @@ var m map[string]int var chanVar chan int -var ifaceVar interface{} = 5 +var ifaceVar any = 5 var assertVar = ifaceVar.(int) diff --git a/src/cmd/api/testdata/src/pkg/p4/p4.go b/src/cmd/api/testdata/src/pkg/p4/p4.go index 462a75be1a..1f90e779dd 100644 --- a/src/cmd/api/testdata/src/pkg/p4/p4.go +++ b/src/cmd/api/testdata/src/pkg/p4/p4.go @@ -4,12 +4,12 @@ package p4 -type Pair[T1 interface { M() }, T2 ~int] struct { +type Pair[T1 interface{ M() }, T2 ~int] struct { f1 T1 f2 T2 } -func NewPair[T1 interface { M() }, T2 ~int](v1 T1, v2 T2) Pair[T1, T2] { +func NewPair[T1 interface{ M() }, T2 ~int](v1 T1, v2 T2) Pair[T1, T2] { return Pair[T1, T2]{f1: v1, f2: v2} } diff --git a/src/cmd/compile/internal/importer/gcimporter_test.go b/src/cmd/compile/internal/importer/gcimporter_test.go index e097507f69..5d80db244b 100644 --- a/src/cmd/compile/internal/importer/gcimporter_test.go +++ b/src/cmd/compile/internal/importer/gcimporter_test.go @@ -258,7 +258,7 @@ var importedObjectTests = []struct { {"go/internal/gcimporter.FindPkg", "func FindPkg(path string, srcDir string) (filename string, id string)"}, // interfaces - {"context.Context", "type Context interface{Deadline() (deadline time.Time, ok bool); Done() <-chan struct{}; Err() error; Value(key interface{}) interface{}}"}, + {"context.Context", "type Context interface{Deadline() (deadline time.Time, ok bool); Done() <-chan struct{}; Err() error; Value(key any) any}"}, {"crypto.Decrypter", "type Decrypter interface{Decrypt(rand io.Reader, msg []byte, opts DecrypterOpts) (plaintext []byte, err error); Public() PublicKey}"}, {"encoding.BinaryMarshaler", "type BinaryMarshaler interface{MarshalBinary() (data []byte, err error)}"}, {"io.Reader", "type Reader interface{Read(p []byte) (n int, err error)}"}, diff --git a/src/cmd/cover/testdata/test.go b/src/cmd/cover/testdata/test.go index 703fba57a4..0e1dbc6194 100644 --- a/src/cmd/cover/testdata/test.go +++ b/src/cmd/cover/testdata/test.go @@ -151,7 +151,7 @@ func testSwitch() { } func testTypeSwitch() { - var x = []interface{}{1, 2.0, "hi"} + var x = []any{1, 2.0, "hi"} for _, v := range x { switch func() { check(LINE, 3) }(); v.(type) { case int: @@ -215,7 +215,7 @@ func testEmptySwitches() { switch 3 { } check(LINE, 1) - switch i := (interface{})(3).(int); i { + switch i := (any)(3).(int); i { } check(LINE, 1) c := make(chan int) diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go index 17538ad5a4..036f8c52fa 100644 --- a/src/cmd/dist/buildtool.go +++ b/src/cmd/dist/buildtool.go @@ -15,6 +15,7 @@ import ( "fmt" "os" "path/filepath" + "regexp" "runtime" "strings" ) @@ -288,7 +289,11 @@ func rewriteBlock%s(b *Block) bool { panic("unused during bootstrap") } } func bootstrapFixImports(srcFile string) string { - lines := strings.SplitAfter(readfile(srcFile), "\n") + text := readfile(srcFile) + if !strings.Contains(srcFile, "/cmd/") && !strings.Contains(srcFile, `\cmd\`) { + text = regexp.MustCompile(`\bany\b`).ReplaceAllString(text, "interface{}") + } + lines := strings.SplitAfter(text, "\n") inBlock := false for i, line := range lines { if strings.HasPrefix(line, "import (") { diff --git a/src/cmd/doc/pkg.go b/src/cmd/doc/pkg.go index 2257c5c0eb..f51efe08af 100644 --- a/src/cmd/doc/pkg.go +++ b/src/cmd/doc/pkg.go @@ -122,7 +122,7 @@ func trim(path, prefix string) (string, bool) { // main do function, so it doesn't cause an exit. Allows testing to work // without running a subprocess. The log prefix will be added when // logged in main; it is not added here. -func (pkg *Package) Fatalf(format string, args ...interface{}) { +func (pkg *Package) Fatalf(format string, args ...any) { panic(PackageError(fmt.Sprintf(format, args...))) } @@ -209,7 +209,7 @@ func parsePackage(writer io.Writer, pkg *build.Package, userPath string) *Packag return p } -func (pkg *Package) Printf(format string, args ...interface{}) { +func (pkg *Package) Printf(format string, args ...any) { fmt.Fprintf(&pkg.buf, format, args...) } @@ -235,7 +235,7 @@ func (pkg *Package) newlines(n int) { // clears the stuff we don't want to print anyway. It's a bit of a magic trick. func (pkg *Package) emit(comment string, node ast.Node) { if node != nil { - var arg interface{} = node + var arg any = node if showSrc { // Need an extra little dance to get internal comments to appear. arg = &printer.CommentedNode{ diff --git a/src/cmd/doc/testdata/nested/ignore.go b/src/cmd/doc/testdata/nested/ignore.go index c497f1b5bc..5fa811d0a8 100644 --- a/src/cmd/doc/testdata/nested/ignore.go +++ b/src/cmd/doc/testdata/nested/ignore.go @@ -1,3 +1,4 @@ +//go:build ignore // +build ignore // Ignored package diff --git a/src/cmd/fix/cftype.go b/src/cmd/fix/cftype.go index 3d292bdeba..27e4088aa9 100644 --- a/src/cmd/fix/cftype.go +++ b/src/cmd/fix/cftype.go @@ -45,8 +45,8 @@ func typefix(f *ast.File, badType func(string) bool) bool { // step 1: Find all the nils with the offending types. // Compute their replacement. - badNils := map[interface{}]ast.Expr{} - walk(f, func(n interface{}) { + badNils := map[any]ast.Expr{} + walk(f, func(n any) { if i, ok := n.(*ast.Ident); ok && i.Name == "nil" && badType(typeof[n]) { badNils[n] = &ast.BasicLit{ValuePos: i.NamePos, Kind: token.INT, Value: "0"} } @@ -58,7 +58,7 @@ func typefix(f *ast.File, badType func(string) bool) bool { if len(badNils) > 0 { exprType := reflect.TypeOf((*ast.Expr)(nil)).Elem() exprSliceType := reflect.TypeOf(([]ast.Expr)(nil)) - walk(f, func(n interface{}) { + walk(f, func(n any) { if n == nil { return } @@ -99,7 +99,7 @@ func typefix(f *ast.File, badType func(string) bool) bool { // Now we need unsafe.Pointer as an intermediate cast. // (*unsafe.Pointer)(x) where x is type *bad -> (*unsafe.Pointer)(unsafe.Pointer(x)) // (*bad.type)(x) where x is type *unsafe.Pointer -> (*bad.type)(unsafe.Pointer(x)) - walk(f, func(n interface{}) { + walk(f, func(n any) { if n == nil { return } diff --git a/src/cmd/fix/fix.go b/src/cmd/fix/fix.go index b9980c17b9..7abdab28a8 100644 --- a/src/cmd/fix/fix.go +++ b/src/cmd/fix/fix.go @@ -43,15 +43,15 @@ func register(f fix) { // walk traverses the AST x, calling visit(y) for each node y in the tree but // also with a pointer to each ast.Expr, ast.Stmt, and *ast.BlockStmt, // in a bottom-up traversal. -func walk(x interface{}, visit func(interface{})) { +func walk(x any, visit func(any)) { walkBeforeAfter(x, nop, visit) } -func nop(interface{}) {} +func nop(any) {} // walkBeforeAfter is like walk but calls before(x) before traversing // x's children and after(x) afterward. -func walkBeforeAfter(x interface{}, before, after func(interface{})) { +func walkBeforeAfter(x any, before, after func(any)) { before(x) switch n := x.(type) { @@ -390,7 +390,7 @@ func renameTop(f *ast.File, old, new string) bool { // Rename top-level old to new, both unresolved names // (probably defined in another file) and names that resolve // to a declaration we renamed. - walk(f, func(n interface{}) { + walk(f, func(n any) { id, ok := n.(*ast.Ident) if ok && isTopName(id, old) { id.Name = new diff --git a/src/cmd/fix/gotypes.go b/src/cmd/fix/gotypes.go index 031f85c9cc..6085816ada 100644 --- a/src/cmd/fix/gotypes.go +++ b/src/cmd/fix/gotypes.go @@ -36,7 +36,7 @@ func fixGoExact(f *ast.File) bool { // This one is harder because the import name changes. // First find the import spec. var importSpec *ast.ImportSpec - walk(f, func(n interface{}) { + walk(f, func(n any) { if importSpec != nil { return } diff --git a/src/cmd/fix/main.go b/src/cmd/fix/main.go index b5f7b901d6..3229b71ec4 100644 --- a/src/cmd/fix/main.go +++ b/src/cmd/fix/main.go @@ -245,7 +245,7 @@ func processFile(filename string, useStdin bool) error { return os.WriteFile(f.Name(), newSrc, 0) } -func gofmt(n interface{}) string { +func gofmt(n any) string { var gofmtBuf bytes.Buffer if err := format.Node(&gofmtBuf, fset, n); err != nil { return "<" + err.Error() + ">" diff --git a/src/cmd/fix/netipv6zone.go b/src/cmd/fix/netipv6zone.go index 3e502bda07..199fcf5bf5 100644 --- a/src/cmd/fix/netipv6zone.go +++ b/src/cmd/fix/netipv6zone.go @@ -26,7 +26,7 @@ func netipv6zone(f *ast.File) bool { } fixed := false - walk(f, func(n interface{}) { + walk(f, func(n any) { cl, ok := n.(*ast.CompositeLit) if !ok { return diff --git a/src/cmd/fix/printerconfig.go b/src/cmd/fix/printerconfig.go index 6d93996872..bad6953196 100644 --- a/src/cmd/fix/printerconfig.go +++ b/src/cmd/fix/printerconfig.go @@ -23,7 +23,7 @@ func printerconfig(f *ast.File) bool { } fixed := false - walk(f, func(n interface{}) { + walk(f, func(n any) { cl, ok := n.(*ast.CompositeLit) if !ok { return diff --git a/src/cmd/fix/typecheck.go b/src/cmd/fix/typecheck.go index b7ec72e116..8a18d61bf2 100644 --- a/src/cmd/fix/typecheck.go +++ b/src/cmd/fix/typecheck.go @@ -142,9 +142,9 @@ func (typ *Type) dot(cfg *TypeConfig, name string) string { // typeof maps AST nodes to type information in gofmt string form. // assign maps type strings to lists of expressions that were assigned // to values of another type that were assigned to that type. -func typecheck(cfg *TypeConfig, f *ast.File) (typeof map[interface{}]string, assign map[string][]interface{}) { - typeof = make(map[interface{}]string) - assign = make(map[string][]interface{}) +func typecheck(cfg *TypeConfig, f *ast.File) (typeof map[any]string, assign map[string][]any) { + typeof = make(map[any]string) + assign = make(map[string][]any) cfg1 := &TypeConfig{} *cfg1 = *cfg // make copy so we can add locally copied := false @@ -296,7 +296,7 @@ func makeExprList(a []*ast.Ident) []ast.Expr { // Typecheck1 is the recursive form of typecheck. // It is like typecheck but adds to the information in typeof // instead of allocating a new map. -func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string, assign map[string][]interface{}) { +func typecheck1(cfg *TypeConfig, f any, typeof map[any]string, assign map[string][]any) { // set sets the type of n to typ. // If isDecl is true, n is being declared. set := func(n ast.Expr, typ string, isDecl bool) { @@ -368,7 +368,7 @@ func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string, a // the curfn stack. var curfn []*ast.FuncType - before := func(n interface{}) { + before := func(n any) { // push function type on stack switch n := n.(type) { case *ast.FuncDecl: @@ -379,7 +379,7 @@ func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string, a } // After is the real type checker. - after := func(n interface{}) { + after := func(n any) { if n == nil { return } diff --git a/src/cmd/go/internal/base/base.go b/src/cmd/go/internal/base/base.go index 954ce47a98..c2d4e6b258 100644 --- a/src/cmd/go/internal/base/base.go +++ b/src/cmd/go/internal/base/base.go @@ -117,12 +117,12 @@ func Exit() { os.Exit(exitStatus) } -func Fatalf(format string, args ...interface{}) { +func Fatalf(format string, args ...any) { Errorf(format, args...) Exit() } -func Errorf(format string, args ...interface{}) { +func Errorf(format string, args ...any) { log.Printf(format, args...) SetExitStatus(1) } @@ -151,7 +151,7 @@ func GetExitStatus() int { // Run runs the command, with stdout and stderr // connected to the go command's own stdout and stderr. // If the command fails, Run reports the error using Errorf. -func Run(cmdargs ...interface{}) { +func Run(cmdargs ...any) { cmdline := str.StringList(cmdargs...) if cfg.BuildN || cfg.BuildX { fmt.Printf("%s\n", strings.Join(cmdline, " ")) diff --git a/src/cmd/go/internal/cmdflag/flag.go b/src/cmd/go/internal/cmdflag/flag.go index 8abb7e559f..a634bc1ab8 100644 --- a/src/cmd/go/internal/cmdflag/flag.go +++ b/src/cmd/go/internal/cmdflag/flag.go @@ -92,7 +92,7 @@ func ParseOne(fs *flag.FlagSet, args []string) (f *flag.Flag, remainingArgs []st // Use fs.Set instead of f.Value.Set below so that any subsequent call to // fs.Visit will correctly visit the flags that have been set. - failf := func(format string, a ...interface{}) (*flag.Flag, []string, error) { + failf := func(format string, a ...any) (*flag.Flag, []string, error) { return f, args, fmt.Errorf(format, a...) } diff --git a/src/cmd/go/internal/fsys/fsys.go b/src/cmd/go/internal/fsys/fsys.go index 0b806027e6..9a1bbf890e 100644 --- a/src/cmd/go/internal/fsys/fsys.go +++ b/src/cmd/go/internal/fsys/fsys.go @@ -499,7 +499,7 @@ func (f fakeFile) Size() int64 { return f.real.Size() } func (f fakeFile) Mode() fs.FileMode { return f.real.Mode() } func (f fakeFile) ModTime() time.Time { return f.real.ModTime() } func (f fakeFile) IsDir() bool { return f.real.IsDir() } -func (f fakeFile) Sys() interface{} { return f.real.Sys() } +func (f fakeFile) Sys() any { return f.real.Sys() } // missingFile provides an fs.FileInfo for an overlaid file where the // destination file in the overlay doesn't exist. It returns zero values @@ -512,7 +512,7 @@ func (f missingFile) Size() int64 { return 0 } func (f missingFile) Mode() fs.FileMode { return fs.ModeIrregular } func (f missingFile) ModTime() time.Time { return time.Unix(0, 0) } func (f missingFile) IsDir() bool { return false } -func (f missingFile) Sys() interface{} { return nil } +func (f missingFile) Sys() any { return nil } // fakeDir provides an fs.FileInfo implementation for directories that are // implicitly created by overlaid files. Each directory in the @@ -524,7 +524,7 @@ func (f fakeDir) Size() int64 { return 0 } func (f fakeDir) Mode() fs.FileMode { return fs.ModeDir | 0500 } func (f fakeDir) ModTime() time.Time { return time.Unix(0, 0) } func (f fakeDir) IsDir() bool { return true } -func (f fakeDir) Sys() interface{} { return nil } +func (f fakeDir) Sys() any { return nil } // Glob is like filepath.Glob but uses the overlay file system. func Glob(pattern string) (matches []string, err error) { diff --git a/src/cmd/go/internal/generate/generate.go b/src/cmd/go/internal/generate/generate.go index 4c17f42930..54ccfe78f2 100644 --- a/src/cmd/go/internal/generate/generate.go +++ b/src/cmd/go/internal/generate/generate.go @@ -408,7 +408,7 @@ var stop = fmt.Errorf("error in generation") // errorf logs an error message prefixed with the file and line number. // It then exits the program (with exit status 1) because generation stops // at the first error. -func (g *Generator) errorf(format string, args ...interface{}) { +func (g *Generator) errorf(format string, args ...any) { fmt.Fprintf(os.Stderr, "%s:%d: %s\n", base.ShortPath(g.path), g.lineNum, fmt.Sprintf(format, args...)) panic(stop) diff --git a/src/cmd/go/internal/help/help.go b/src/cmd/go/internal/help/help.go index 7a730fc8eb..2a07d2423b 100644 --- a/src/cmd/go/internal/help/help.go +++ b/src/cmd/go/internal/help/help.go @@ -162,7 +162,7 @@ func (w *errWriter) Write(b []byte) (int, error) { } // tmpl executes the given template text on data, writing the result to w. -func tmpl(w io.Writer, text string, data interface{}) { +func tmpl(w io.Writer, text string, data any) { t := template.New("top") t.Funcs(template.FuncMap{"trim": strings.TrimSpace, "capitalize": capitalize}) template.Must(t.Parse(text)) diff --git a/src/cmd/go/internal/imports/testdata/android/e.go b/src/cmd/go/internal/imports/testdata/android/e.go index d9b2db769b..f1b9c888c2 100644 --- a/src/cmd/go/internal/imports/testdata/android/e.go +++ b/src/cmd/go/internal/imports/testdata/android/e.go @@ -1,3 +1,4 @@ +//go:build android // +build android package android diff --git a/src/cmd/go/internal/imports/testdata/android/f.go b/src/cmd/go/internal/imports/testdata/android/f.go index 281e4dd6b9..bb0ff7b73f 100644 --- a/src/cmd/go/internal/imports/testdata/android/f.go +++ b/src/cmd/go/internal/imports/testdata/android/f.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package android diff --git a/src/cmd/go/internal/imports/testdata/android/g.go b/src/cmd/go/internal/imports/testdata/android/g.go index 66a789c0ad..ee19424890 100644 --- a/src/cmd/go/internal/imports/testdata/android/g.go +++ b/src/cmd/go/internal/imports/testdata/android/g.go @@ -1,3 +1,4 @@ +//go:build !android // +build !android package android diff --git a/src/cmd/go/internal/imports/testdata/illumos/e.go b/src/cmd/go/internal/imports/testdata/illumos/e.go index 5e1ed3cb9d..fddf2c4299 100644 --- a/src/cmd/go/internal/imports/testdata/illumos/e.go +++ b/src/cmd/go/internal/imports/testdata/illumos/e.go @@ -1,3 +1,4 @@ +//go:build illumos // +build illumos package illumos diff --git a/src/cmd/go/internal/imports/testdata/illumos/f.go b/src/cmd/go/internal/imports/testdata/illumos/f.go index f3e3f728bc..4b6d528e4c 100644 --- a/src/cmd/go/internal/imports/testdata/illumos/f.go +++ b/src/cmd/go/internal/imports/testdata/illumos/f.go @@ -1,3 +1,4 @@ +//go:build solaris // +build solaris package illumos diff --git a/src/cmd/go/internal/imports/testdata/illumos/g.go b/src/cmd/go/internal/imports/testdata/illumos/g.go index b30f1eb403..1bf826b815 100644 --- a/src/cmd/go/internal/imports/testdata/illumos/g.go +++ b/src/cmd/go/internal/imports/testdata/illumos/g.go @@ -1,3 +1,4 @@ +//go:build !illumos // +build !illumos package illumos diff --git a/src/cmd/go/internal/imports/testdata/star/x1.go b/src/cmd/go/internal/imports/testdata/star/x1.go index 6a9594aed0..eaaea979e9 100644 --- a/src/cmd/go/internal/imports/testdata/star/x1.go +++ b/src/cmd/go/internal/imports/testdata/star/x1.go @@ -1,8 +1,5 @@ -// +build blahblh -// +build linux -// +build !linux -// +build windows -// +build darwin +//go:build blahblh && linux && !linux && windows && darwin +// +build blahblh,linux,!linux,windows,darwin package x diff --git a/src/cmd/go/internal/list/list.go b/src/cmd/go/internal/list/list.go index 5ecd384787..d9a7078ccf 100644 --- a/src/cmd/go/internal/list/list.go +++ b/src/cmd/go/internal/list/list.go @@ -358,9 +358,9 @@ func runList(ctx context.Context, cmd *base.Command, args []string) { } } - var do func(interface{}) + var do func(any) if *listJson { - do = func(x interface{}) { + do = func(x any) { b, err := json.MarshalIndent(x, "", "\t") if err != nil { out.Flush() @@ -386,7 +386,7 @@ func runList(ctx context.Context, cmd *base.Command, args []string) { if err != nil { base.Fatalf("%s", err) } - do = func(x interface{}) { + do = func(x any) { if err := tmpl.Execute(out, x); err != nil { out.Flush() base.Fatalf("%s", err) diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index 589bf9e729..a891d601b1 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -498,7 +498,7 @@ type importError struct { err error // created with fmt.Errorf } -func ImportErrorf(path, format string, args ...interface{}) ImportPathError { +func ImportErrorf(path, format string, args ...any) ImportPathError { err := &importError{importPath: path, err: fmt.Errorf(format, args...)} if errStr := err.Error(); !strings.Contains(errStr, path) { panic(fmt.Sprintf("path %q not in error %q", path, errStr)) @@ -589,10 +589,10 @@ func ClearPackageCachePartial(args []string) { delete(packageCache, arg) } } - resolvedImportCache.DeleteIf(func(key interface{}) bool { + resolvedImportCache.DeleteIf(func(key any) bool { return shouldDelete[key.(importSpec).path] }) - packageDataCache.DeleteIf(func(key interface{}) bool { + packageDataCache.DeleteIf(func(key any) bool { return shouldDelete[key.(string)] }) } @@ -605,7 +605,7 @@ func ReloadPackageNoFlags(arg string, stk *ImportStack) *Package { p := packageCache[arg] if p != nil { delete(packageCache, arg) - resolvedImportCache.DeleteIf(func(key interface{}) bool { + resolvedImportCache.DeleteIf(func(key any) bool { return key.(importSpec).path == p.ImportPath }) packageDataCache.Delete(p.ImportPath) @@ -817,7 +817,7 @@ func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoo parentIsStd: parentIsStd, mode: mode, } - r := resolvedImportCache.Do(importKey, func() interface{} { + r := resolvedImportCache.Do(importKey, func() any { var r resolvedImport if build.IsLocalImport(path) { r.dir = filepath.Join(parentDir, path) @@ -844,7 +844,7 @@ func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoo // Load the package from its directory. If we already found the package's // directory when resolving its import path, use that. - data := packageDataCache.Do(r.path, func() interface{} { + data := packageDataCache.Do(r.path, func() any { loaded = true var data packageData if r.dir != "" { @@ -1063,7 +1063,7 @@ func cleanImport(path string) string { var isDirCache par.Cache func isDir(path string) bool { - return isDirCache.Do(path, func() interface{} { + return isDirCache.Do(path, func() any { fi, err := fsys.Stat(path) return err == nil && fi.IsDir() }).(bool) @@ -1191,7 +1191,7 @@ var ( // goModPath returns the module path in the go.mod in dir, if any. func goModPath(dir string) (path string) { - return goModPathCache.Do(dir, func() interface{} { + return goModPathCache.Do(dir, func() any { data, err := os.ReadFile(filepath.Join(dir, "go.mod")) if err != nil { return "" @@ -2221,7 +2221,7 @@ func (p *Package) setBuildInfo() { // executables always appear stale unless the user sets the same flags. // Perhaps it's safe to omit those flags when GO_GCFLAGS and GO_LDFLAGS // are not set? - setPkgErrorf := func(format string, args ...interface{}) { + setPkgErrorf := func(format string, args ...any) { if p.Error == nil { p.Error = &PackageError{Err: fmt.Errorf(format, args...)} } @@ -2397,7 +2397,7 @@ func (p *Package) setBuildInfo() { Status vcs.Status Err error } - cached := vcsStatusCache.Do(repoDir, func() interface{} { + cached := vcsStatusCache.Do(repoDir, func() any { st, err := vcsCmd.Status(vcsCmd, repoDir) return vcsStatusError{st, err} }).(vcsStatusError) diff --git a/src/cmd/go/internal/modcmd/tidy.go b/src/cmd/go/internal/modcmd/tidy.go index 57d303a13c..d35476eb53 100644 --- a/src/cmd/go/internal/modcmd/tidy.go +++ b/src/cmd/go/internal/modcmd/tidy.go @@ -75,8 +75,8 @@ type goVersionFlag struct { v string } -func (f *goVersionFlag) String() string { return f.v } -func (f *goVersionFlag) Get() interface{} { return f.v } +func (f *goVersionFlag) String() string { return f.v } +func (f *goVersionFlag) Get() any { return f.v } func (f *goVersionFlag) Set(s string) error { if s != "" { diff --git a/src/cmd/go/internal/modfetch/cache.go b/src/cmd/go/internal/modfetch/cache.go index 8d299e931a..c682447900 100644 --- a/src/cmd/go/internal/modfetch/cache.go +++ b/src/cmd/go/internal/modfetch/cache.go @@ -204,7 +204,7 @@ func (r *cachingRepo) Versions(prefix string) ([]string, error) { list []string err error } - c := r.cache.Do("versions:"+prefix, func() interface{} { + c := r.cache.Do("versions:"+prefix, func() any { list, err := r.repo().Versions(prefix) return cached{list, err} }).(cached) @@ -221,7 +221,7 @@ type cachedInfo struct { } func (r *cachingRepo) Stat(rev string) (*RevInfo, error) { - c := r.cache.Do("stat:"+rev, func() interface{} { + c := r.cache.Do("stat:"+rev, func() any { file, info, err := readDiskStat(r.path, rev) if err == nil { return cachedInfo{info, nil} @@ -233,7 +233,7 @@ func (r *cachingRepo) Stat(rev string) (*RevInfo, error) { // then save the information under the proper version, for future use. if info.Version != rev { file, _ = CachePath(module.Version{Path: r.path, Version: info.Version}, "info") - r.cache.Do("stat:"+info.Version, func() interface{} { + r.cache.Do("stat:"+info.Version, func() any { return cachedInfo{info, err} }) } @@ -253,12 +253,12 @@ func (r *cachingRepo) Stat(rev string) (*RevInfo, error) { } func (r *cachingRepo) Latest() (*RevInfo, error) { - c := r.cache.Do("latest:", func() interface{} { + c := r.cache.Do("latest:", func() any { info, err := r.repo().Latest() // Save info for likely future Stat call. if err == nil { - r.cache.Do("stat:"+info.Version, func() interface{} { + r.cache.Do("stat:"+info.Version, func() any { return cachedInfo{info, err} }) if file, _, err := readDiskStat(r.path, info.Version); err != nil { @@ -281,7 +281,7 @@ func (r *cachingRepo) GoMod(version string) ([]byte, error) { text []byte err error } - c := r.cache.Do("gomod:"+version, func() interface{} { + c := r.cache.Do("gomod:"+version, func() any { file, text, err := readDiskGoMod(r.path, version) if err == nil { // Note: readDiskGoMod already called checkGoMod. diff --git a/src/cmd/go/internal/modfetch/codehost/codehost.go b/src/cmd/go/internal/modfetch/codehost/codehost.go index 5063f8616a..4a0e2241e5 100644 --- a/src/cmd/go/internal/modfetch/codehost/codehost.go +++ b/src/cmd/go/internal/modfetch/codehost/codehost.go @@ -228,7 +228,7 @@ var dirLock sync.Map // It returns the standard output and, for a non-zero exit, // a *RunError indicating the command, exit status, and standard error. // Standard error is unavailable for commands that exit successfully. -func Run(dir string, cmdline ...interface{}) ([]byte, error) { +func Run(dir string, cmdline ...any) ([]byte, error) { return RunWithStdin(dir, nil, cmdline...) } @@ -236,7 +236,7 @@ func Run(dir string, cmdline ...interface{}) ([]byte, error) { // See https://www.gnu.org/software/bash/manual/html_node/Double-Quotes.html. var bashQuoter = strings.NewReplacer(`"`, `\"`, `$`, `\$`, "`", "\\`", `\`, `\\`) -func RunWithStdin(dir string, stdin io.Reader, cmdline ...interface{}) ([]byte, error) { +func RunWithStdin(dir string, stdin io.Reader, cmdline ...any) ([]byte, error) { if dir != "" { muIface, ok := dirLock.Load(dir) if !ok { diff --git a/src/cmd/go/internal/modfetch/codehost/git.go b/src/cmd/go/internal/modfetch/codehost/git.go index 2a5255f115..34f453c855 100644 --- a/src/cmd/go/internal/modfetch/codehost/git.go +++ b/src/cmd/go/internal/modfetch/codehost/git.go @@ -56,7 +56,7 @@ func newGitRepoCached(remote string, localOK bool) (Repo, error) { err error } - c := gitRepoCache.Do(key{remote, localOK}, func() interface{} { + c := gitRepoCache.Do(key{remote, localOK}, func() any { repo, err := newGitRepo(remote, localOK) return cached{repo, err} }).(cached) @@ -503,7 +503,7 @@ func (r *gitRepo) Stat(rev string) (*RevInfo, error) { info *RevInfo err error } - c := r.statCache.Do(rev, func() interface{} { + c := r.statCache.Do(rev, func() any { info, err := r.stat(rev) return cached{info, err} }).(cached) diff --git a/src/cmd/go/internal/modfetch/codehost/vcs.go b/src/cmd/go/internal/modfetch/codehost/vcs.go index c8449ccdcc..de62265efc 100644 --- a/src/cmd/go/internal/modfetch/codehost/vcs.go +++ b/src/cmd/go/internal/modfetch/codehost/vcs.go @@ -38,7 +38,7 @@ type VCSError struct { func (e *VCSError) Error() string { return e.Err.Error() } -func vcsErrorf(format string, a ...interface{}) error { +func vcsErrorf(format string, a ...any) error { return &VCSError{Err: fmt.Errorf(format, a...)} } @@ -51,7 +51,7 @@ func NewRepo(vcs, remote string) (Repo, error) { repo Repo err error } - c := vcsRepoCache.Do(key{vcs, remote}, func() interface{} { + c := vcsRepoCache.Do(key{vcs, remote}, func() any { repo, err := newVCSRepo(vcs, remote) if err != nil { err = &VCSError{err} diff --git a/src/cmd/go/internal/modfetch/coderepo.go b/src/cmd/go/internal/modfetch/coderepo.go index df835c3d7e..79da010809 100644 --- a/src/cmd/go/internal/modfetch/coderepo.go +++ b/src/cmd/go/internal/modfetch/coderepo.go @@ -321,7 +321,7 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e return ok } - invalidf := func(format string, args ...interface{}) error { + invalidf := func(format string, args ...any) error { return &module.ModuleError{ Path: r.modPath, Err: &module.InvalidVersionError{ @@ -1066,7 +1066,7 @@ func (fi dataFileInfo) Size() int64 { return int64(len(fi.f.data)) } func (fi dataFileInfo) Mode() fs.FileMode { return 0644 } func (fi dataFileInfo) ModTime() time.Time { return time.Time{} } func (fi dataFileInfo) IsDir() bool { return false } -func (fi dataFileInfo) Sys() interface{} { return nil } +func (fi dataFileInfo) Sys() any { return nil } // hasPathPrefix reports whether the path s begins with the // elements in prefix. diff --git a/src/cmd/go/internal/modfetch/fetch.go b/src/cmd/go/internal/modfetch/fetch.go index e246c1a04d..12b7431570 100644 --- a/src/cmd/go/internal/modfetch/fetch.go +++ b/src/cmd/go/internal/modfetch/fetch.go @@ -48,7 +48,7 @@ func Download(ctx context.Context, mod module.Version) (dir string, err error) { dir string err error } - c := downloadCache.Do(mod, func() interface{} { + c := downloadCache.Do(mod, func() any { dir, err := download(ctx, mod) if err != nil { return cached{"", err} @@ -165,7 +165,7 @@ func DownloadZip(ctx context.Context, mod module.Version) (zipfile string, err e zipfile string err error } - c := downloadZipCache.Do(mod, func() interface{} { + c := downloadZipCache.Do(mod, func() any { zipfile, err := CachePath(mod, "zip") if err != nil { return cached{"", err} diff --git a/src/cmd/go/internal/modfetch/repo.go b/src/cmd/go/internal/modfetch/repo.go index 0bffa55af6..1b42ecb6ed 100644 --- a/src/cmd/go/internal/modfetch/repo.go +++ b/src/cmd/go/internal/modfetch/repo.go @@ -196,7 +196,7 @@ func Lookup(proxy, path string) Repo { type cached struct { r Repo } - c := lookupCache.Do(lookupCacheKey{proxy, path}, func() interface{} { + c := lookupCache.Do(lookupCacheKey{proxy, path}, func() any { r := newCachingRepo(path, func() (Repo, error) { r, err := lookup(proxy, path) if err == nil && traceRepo { @@ -308,7 +308,7 @@ func newLoggingRepo(r Repo) *loggingRepo { // defer logCall("hello %s", arg)() // // Note the final (). -func logCall(format string, args ...interface{}) func() { +func logCall(format string, args ...any) func() { start := time.Now() fmt.Fprintf(os.Stderr, "+++ %s\n", fmt.Sprintf(format, args...)) return func() { @@ -371,7 +371,7 @@ type notExistError struct { err error } -func notExistErrorf(format string, args ...interface{}) error { +func notExistErrorf(format string, args ...any) error { return notExistError{fmt.Errorf(format, args...)} } diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index 893cc92e39..3d8463e892 100644 --- a/src/cmd/go/internal/modget/get.go +++ b/src/cmd/go/internal/modget/get.go @@ -601,7 +601,7 @@ func (r *resolver) matchInModule(ctx context.Context, pattern string, m module.V err error } - e := r.matchInModuleCache.Do(key{pattern, m}, func() interface{} { + e := r.matchInModuleCache.Do(key{pattern, m}, func() any { match := modload.MatchInModule(ctx, pattern, m, imports.AnyTags()) if len(match.Errs) > 0 { return entry{match.Pkgs, match.Errs[0]} @@ -893,7 +893,7 @@ func (r *resolver) checkWildcardVersions(ctx context.Context) { // curM at its original version contains a path matching q.pattern, // but at rev.Version it does not, so (somewhat paradoxically) if // we changed the version of curM it would no longer match the query. - var version interface{} = m + var version any = m if rev.Version != q.version { version = fmt.Sprintf("%s@%s (%s)", m.Path, q.version, m.Version) } diff --git a/src/cmd/go/internal/modload/buildlist.go b/src/cmd/go/internal/modload/buildlist.go index 4ce71fef5b..45be51f1c6 100644 --- a/src/cmd/go/internal/modload/buildlist.go +++ b/src/cmd/go/internal/modload/buildlist.go @@ -326,7 +326,7 @@ func readModGraph(ctx context.Context, pruning modPruning, roots []module.Versio // It does not load the transitive requirements of m even if the go version in // m's go.mod file indicates that it supports graph pruning. loadOne := func(m module.Version) (*modFileSummary, error) { - cached := mg.loadCache.Do(m, func() interface{} { + cached := mg.loadCache.Do(m, func() any { summary, err := goModSummary(m) mu.Lock() diff --git a/src/cmd/go/internal/modload/import.go b/src/cmd/go/internal/modload/import.go index bc2b0a0230..812e48a156 100644 --- a/src/cmd/go/internal/modload/import.go +++ b/src/cmd/go/internal/modload/import.go @@ -612,7 +612,7 @@ func dirInModule(path, mpath, mdir string, isLocal bool) (dir string, haveGoFile // (the main module, and any directory trees pointed at by replace directives). if isLocal { for d := dir; d != mdir && len(d) > len(mdir); { - haveGoMod := haveGoModCache.Do(d, func() interface{} { + haveGoMod := haveGoModCache.Do(d, func() any { fi, err := fsys.Stat(filepath.Join(d, "go.mod")) return err == nil && !fi.IsDir() }).(bool) @@ -635,7 +635,7 @@ func dirInModule(path, mpath, mdir string, isLocal bool) (dir string, haveGoFile // Are there Go source files in the directory? // We don't care about build tags, not even "+build ignore". // We're just looking for a plausible directory. - res := haveGoFilesCache.Do(dir, func() interface{} { + res := haveGoFilesCache.Do(dir, func() any { ok, err := fsys.IsDirWithGoFiles(dir) return goFilesEntry{haveGoFiles: ok, err: err} }).(goFilesEntry) diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index 5e7075da4e..617b634d26 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -859,7 +859,7 @@ func (ld *loader) reset() { // errorf reports an error via either os.Stderr or base.Errorf, // according to whether ld.AllowErrors is set. -func (ld *loader) errorf(format string, args ...interface{}) { +func (ld *loader) errorf(format string, args ...any) { if ld.AllowErrors { fmt.Fprintf(os.Stderr, format, args...) } else { @@ -1492,7 +1492,7 @@ func (ld *loader) pkg(ctx context.Context, path string, flags loadPkgFlags) *loa panic("internal error: (*loader).pkg called with pkgImportsLoaded flag set") } - pkg := ld.pkgCache.Do(path, func() interface{} { + pkg := ld.pkgCache.Do(path, func() any { pkg := &loadPkg{ path: path, } diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index 40e6ed787d..ec3f57ae3e 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -664,7 +664,7 @@ func rawGoModSummary(m module.Version) (*modFileSummary, error) { summary *modFileSummary err error } - c := rawGoModSummaryCache.Do(key{m}, func() interface{} { + c := rawGoModSummaryCache.Do(key{m}, func() any { summary := new(modFileSummary) name, data, err := rawGoModData(m) if err != nil { @@ -766,7 +766,7 @@ func queryLatestVersionIgnoringRetractions(ctx context.Context, path string) (la latest module.Version err error } - e := latestVersionIgnoringRetractionsCache.Do(path, func() interface{} { + e := latestVersionIgnoringRetractionsCache.Do(path, func() any { ctx, span := trace.StartSpan(ctx, "queryLatestVersionIgnoringRetractions "+path) defer span.Done() diff --git a/src/cmd/go/internal/modload/vendor.go b/src/cmd/go/internal/modload/vendor.go index a735cad905..5ea82a8620 100644 --- a/src/cmd/go/internal/modload/vendor.go +++ b/src/cmd/go/internal/modload/vendor.go @@ -147,7 +147,7 @@ func checkVendorConsistency(index *modFileIndex, modFile *modfile.File) { } vendErrors := new(strings.Builder) - vendErrorf := func(mod module.Version, format string, args ...interface{}) { + vendErrorf := func(mod module.Version, format string, args ...any) { detail := fmt.Sprintf(format, args...) if mod.Version == "" { fmt.Fprintf(vendErrors, "\n\t%s: %s", mod.Path, detail) diff --git a/src/cmd/go/internal/mvs/mvs.go b/src/cmd/go/internal/mvs/mvs.go index 566fa4b6b3..d25d447b0e 100644 --- a/src/cmd/go/internal/mvs/mvs.go +++ b/src/cmd/go/internal/mvs/mvs.go @@ -114,7 +114,7 @@ func buildList(targets []module.Version, reqs Reqs, upgrade func(module.Version) for _, target := range targets { work.Add(target) } - work.Do(10, func(item interface{}) { + work.Do(10, func(item any) { m := item.(module.Version) var required []module.Version diff --git a/src/cmd/go/internal/par/work.go b/src/cmd/go/internal/par/work.go index 960cec6fb1..496c41b150 100644 --- a/src/cmd/go/internal/par/work.go +++ b/src/cmd/go/internal/par/work.go @@ -14,24 +14,24 @@ import ( // Work manages a set of work items to be executed in parallel, at most once each. // The items in the set must all be valid map keys. type Work struct { - f func(interface{}) // function to run for each item - running int // total number of runners + f func(any) // function to run for each item + running int // total number of runners mu sync.Mutex - added map[interface{}]bool // items added to set - todo []interface{} // items yet to be run - wait sync.Cond // wait when todo is empty - waiting int // number of runners waiting for todo + added map[any]bool // items added to set + todo []any // items yet to be run + wait sync.Cond // wait when todo is empty + waiting int // number of runners waiting for todo } func (w *Work) init() { if w.added == nil { - w.added = make(map[interface{}]bool) + w.added = make(map[any]bool) } } // Add adds item to the work set, if it hasn't already been added. -func (w *Work) Add(item interface{}) { +func (w *Work) Add(item any) { w.mu.Lock() w.init() if !w.added[item] { @@ -51,7 +51,7 @@ func (w *Work) Add(item interface{}) { // before calling Do (or else Do returns immediately), // but it is allowed for f(item) to add new items to the set. // Do should only be used once on a given Work. -func (w *Work) Do(n int, f func(item interface{})) { +func (w *Work) Do(n int, f func(item any)) { if n < 1 { panic("par.Work.Do: n < 1") } @@ -110,13 +110,13 @@ type Cache struct { type cacheEntry struct { done uint32 mu sync.Mutex - result interface{} + result any } // Do calls the function f if and only if Do is being called for the first time with this key. // No call to Do with a given key returns until the one call to f returns. // Do returns the value returned by the one call to f. -func (c *Cache) Do(key interface{}, f func() interface{}) interface{} { +func (c *Cache) Do(key any, f func() any) any { entryIface, ok := c.m.Load(key) if !ok { entryIface, _ = c.m.LoadOrStore(key, new(cacheEntry)) @@ -136,7 +136,7 @@ func (c *Cache) Do(key interface{}, f func() interface{}) interface{} { // Get returns the cached result associated with key. // It returns nil if there is no such result. // If the result for key is being computed, Get does not wait for the computation to finish. -func (c *Cache) Get(key interface{}) interface{} { +func (c *Cache) Get(key any) any { entryIface, ok := c.m.Load(key) if !ok { return nil @@ -156,7 +156,7 @@ func (c *Cache) Get(key interface{}) interface{} { // TODO(jayconrod): Delete this after the package cache clearing functions // in internal/load have been removed. func (c *Cache) Clear() { - c.m.Range(func(key, value interface{}) bool { + c.m.Range(func(key, value any) bool { c.m.Delete(key) return true }) @@ -169,7 +169,7 @@ func (c *Cache) Clear() { // // TODO(jayconrod): Delete this after the package cache clearing functions // in internal/load have been removed. -func (c *Cache) Delete(key interface{}) { +func (c *Cache) Delete(key any) { c.m.Delete(key) } @@ -180,8 +180,8 @@ func (c *Cache) Delete(key interface{}) { // // TODO(jayconrod): Delete this after the package cache clearing functions // in internal/load have been removed. -func (c *Cache) DeleteIf(pred func(key interface{}) bool) { - c.m.Range(func(key, _ interface{}) bool { +func (c *Cache) DeleteIf(pred func(key any) bool) { + c.m.Range(func(key, _ any) bool { if pred(key) { c.Delete(key) } diff --git a/src/cmd/go/internal/par/work_test.go b/src/cmd/go/internal/par/work_test.go index f104bc4106..add0e640d8 100644 --- a/src/cmd/go/internal/par/work_test.go +++ b/src/cmd/go/internal/par/work_test.go @@ -16,7 +16,7 @@ func TestWork(t *testing.T) { const N = 10000 n := int32(0) w.Add(N) - w.Do(100, func(x interface{}) { + w.Do(100, func(x any) { atomic.AddInt32(&n, 1) i := x.(int) if i >= 2 { @@ -40,7 +40,7 @@ func TestWorkParallel(t *testing.T) { } start := time.Now() var n int32 - w.Do(N, func(x interface{}) { + w.Do(N, func(x any) { time.Sleep(1 * time.Millisecond) atomic.AddInt32(&n, +1) }) @@ -58,19 +58,19 @@ func TestCache(t *testing.T) { var cache Cache n := 1 - v := cache.Do(1, func() interface{} { n++; return n }) + v := cache.Do(1, func() any { n++; return n }) if v != 2 { t.Fatalf("cache.Do(1) did not run f") } - v = cache.Do(1, func() interface{} { n++; return n }) + v = cache.Do(1, func() any { n++; return n }) if v != 2 { t.Fatalf("cache.Do(1) ran f again!") } - v = cache.Do(2, func() interface{} { n++; return n }) + v = cache.Do(2, func() any { n++; return n }) if v != 3 { t.Fatalf("cache.Do(2) did not run f") } - v = cache.Do(1, func() interface{} { n++; return n }) + v = cache.Do(1, func() any { n++; return n }) if v != 2 { t.Fatalf("cache.Do(1) did not returned saved value from original cache.Do(1)") } diff --git a/src/cmd/go/internal/run/run.go b/src/cmd/go/internal/run/run.go index 878cee367e..c4b70b64fe 100644 --- a/src/cmd/go/internal/run/run.go +++ b/src/cmd/go/internal/run/run.go @@ -69,7 +69,7 @@ func init() { CmdRun.Flag.Var((*base.StringsFlag)(&work.ExecCmd), "exec", "") } -func printStderr(args ...interface{}) (int, error) { +func printStderr(args ...any) (int, error) { return fmt.Fprint(os.Stderr, args...) } diff --git a/src/cmd/go/internal/str/str.go b/src/cmd/go/internal/str/str.go index 5bc521b9df..021bfbff77 100644 --- a/src/cmd/go/internal/str/str.go +++ b/src/cmd/go/internal/str/str.go @@ -14,7 +14,7 @@ import ( // StringList flattens its arguments into a single []string. // Each argument in args must have type string or []string. -func StringList(args ...interface{}) []string { +func StringList(args ...any) []string { var x []string for _, arg := range args { switch arg := arg.(type) { diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go index 77a75fd51c..313dc62b78 100644 --- a/src/cmd/go/internal/vcs/vcs.go +++ b/src/cmd/go/internal/vcs/vcs.go @@ -1311,7 +1311,7 @@ func metaImportsForPrefix(importPrefix string, mod ModuleMode, security web.Secu return res, nil } - resi, _, _ := fetchGroup.Do(importPrefix, func() (resi interface{}, err error) { + resi, _, _ := fetchGroup.Do(importPrefix, func() (resi any, err error) { fetchCacheMu.Lock() if res, ok := fetchCache[importPrefix]; ok { fetchCacheMu.Unlock() @@ -1588,7 +1588,7 @@ type importError struct { err error } -func importErrorf(path, format string, args ...interface{}) error { +func importErrorf(path, format string, args ...any) error { err := &importError{importPath: path, err: fmt.Errorf(format, args...)} if errStr := err.Error(); !strings.Contains(errStr, path) { panic(fmt.Sprintf("path %q not in error %q", path, errStr)) diff --git a/src/cmd/go/internal/work/action.go b/src/cmd/go/internal/work/action.go index 6f5ac1364c..c0862c5efe 100644 --- a/src/cmd/go/internal/work/action.go +++ b/src/cmd/go/internal/work/action.go @@ -37,7 +37,7 @@ type Builder struct { actionCache map[cacheKey]*Action // a cache of already-constructed actions mkdirCache map[string]bool // a cache of created directories flagCache map[[2]string]bool // a cache of supported compiler flags - Print func(args ...interface{}) (int, error) + Print func(args ...any) (int, error) IsCmdList bool // running as part of go list; set p.Stale and additional fields below NeedError bool // list needs p.Error @@ -120,8 +120,8 @@ type actionQueue []*Action func (q *actionQueue) Len() int { return len(*q) } func (q *actionQueue) Swap(i, j int) { (*q)[i], (*q)[j] = (*q)[j], (*q)[i] } func (q *actionQueue) Less(i, j int) bool { return (*q)[i].priority < (*q)[j].priority } -func (q *actionQueue) Push(x interface{}) { *q = append(*q, x.(*Action)) } -func (q *actionQueue) Pop() interface{} { +func (q *actionQueue) Push(x any) { *q = append(*q, x.(*Action)) } +func (q *actionQueue) Pop() any { n := len(*q) - 1 x := (*q)[n] *q = (*q)[:n] @@ -241,7 +241,7 @@ const ( ) func (b *Builder) Init() { - b.Print = func(a ...interface{}) (int, error) { + b.Print = func(a ...any) (int, error) { return fmt.Fprint(os.Stderr, a...) } b.actionCache = make(map[cacheKey]*Action) diff --git a/src/cmd/go/internal/work/build_test.go b/src/cmd/go/internal/work/build_test.go index 600fc3083f..0b6b83a706 100644 --- a/src/cmd/go/internal/work/build_test.go +++ b/src/cmd/go/internal/work/build_test.go @@ -234,7 +234,7 @@ func TestRespectSetgidDir(t *testing.T) { // of `(*Builder).ShowCmd` afterwards as a sanity check. cfg.BuildX = true var cmdBuf bytes.Buffer - b.Print = func(a ...interface{}) (int, error) { + b.Print = func(a ...any) (int, error) { return cmdBuf.WriteString(fmt.Sprint(a...)) } diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index 2c040b8ff4..ccd5aee221 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -1948,7 +1948,7 @@ func mayberemovefile(s string) { // fmtcmd replaces the name of the current directory with dot (.) // but only when it is at the beginning of a space-separated token. // -func (b *Builder) fmtcmd(dir string, format string, args ...interface{}) string { +func (b *Builder) fmtcmd(dir string, format string, args ...any) string { cmd := fmt.Sprintf(format, args...) if dir != "" && dir != "/" { dot := " ." @@ -1974,7 +1974,7 @@ func (b *Builder) fmtcmd(dir string, format string, args ...interface{}) string // showcmd prints the given command to standard output // for the implementation of -n or -x. -func (b *Builder) Showcmd(dir string, format string, args ...interface{}) { +func (b *Builder) Showcmd(dir string, format string, args ...any) { b.output.Lock() defer b.output.Unlock() b.Print(b.fmtcmd(dir, format, args...) + "\n") @@ -2038,7 +2038,7 @@ var cgoTypeSigRe = lazyregexp.New(`\b_C2?(type|func|var|macro)_\B`) // run runs the command given by cmdline in the directory dir. // If the command fails, run prints information about the failure // and returns a non-nil error. -func (b *Builder) run(a *Action, dir string, desc string, env []string, cmdargs ...interface{}) error { +func (b *Builder) run(a *Action, dir string, desc string, env []string, cmdargs ...any) error { out, err := b.runOut(a, dir, env, cmdargs...) if len(out) > 0 { if desc == "" { @@ -2072,7 +2072,7 @@ func (b *Builder) processOutput(out []byte) string { // runOut runs the command given by cmdline in the directory dir. // It returns the command output and any errors that occurred. // It accumulates execution time in a. -func (b *Builder) runOut(a *Action, dir string, env []string, cmdargs ...interface{}) ([]byte, error) { +func (b *Builder) runOut(a *Action, dir string, env []string, cmdargs ...any) ([]byte, error) { cmdline := str.StringList(cmdargs...) for _, arg := range cmdline { @@ -2409,7 +2409,7 @@ func (b *Builder) gccld(a *Action, p *load.Package, objdir, outfile string, flag cmd = b.GccCmd(p.Dir, objdir) } - cmdargs := []interface{}{cmd, "-o", outfile, objs, flags} + cmdargs := []any{cmd, "-o", outfile, objs, flags} dir := p.Dir out, err := b.runOut(a, base.Cwd(), b.cCompilerEnv(), cmdargs...) diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go index e3b4a817e7..40175324d2 100644 --- a/src/cmd/go/internal/work/gc.go +++ b/src/cmd/go/internal/work/gc.go @@ -165,7 +165,7 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg gcflags = append(gcflags, fmt.Sprintf("-c=%d", c)) } - args := []interface{}{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", a.trimpath(), defaultGcFlags, gcflags} + args := []any{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", a.trimpath(), defaultGcFlags, gcflags} if p.Internal.LocalPrefix == "" { args = append(args, "-nolocalimports") } else { @@ -362,11 +362,11 @@ func (a *Action) trimpath() string { return rewrite } -func asmArgs(a *Action, p *load.Package) []interface{} { +func asmArgs(a *Action, p *load.Package) []any { // Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files. inc := filepath.Join(cfg.GOROOT, "pkg", "include") pkgpath := pkgPath(a) - args := []interface{}{cfg.BuildToolexec, base.Tool("asm"), "-p", pkgpath, "-trimpath", a.trimpath(), "-I", a.Objdir, "-I", inc, "-D", "GOOS_" + cfg.Goos, "-D", "GOARCH_" + cfg.Goarch, forcedAsmflags, p.Internal.Asmflags} + args := []any{cfg.BuildToolexec, base.Tool("asm"), "-p", pkgpath, "-trimpath", a.trimpath(), "-I", a.Objdir, "-I", inc, "-D", "GOOS_" + cfg.Goos, "-D", "GOARCH_" + cfg.Goarch, forcedAsmflags, p.Internal.Asmflags} if p.ImportPath == "runtime" && cfg.Goarch == "386" { for _, arg := range forcedAsmflags { if arg == "-dynlink" { @@ -455,8 +455,8 @@ func (gcToolchain) symabis(b *Builder, a *Action, sfiles []string) (string, erro // toolVerify checks that the command line args writes the same output file // if run using newTool instead. // Unused now but kept around for future use. -func toolVerify(a *Action, b *Builder, p *load.Package, newTool string, ofile string, args []interface{}) error { - newArgs := make([]interface{}, len(args)) +func toolVerify(a *Action, b *Builder, p *load.Package, newTool string, ofile string, args []any) error { + newArgs := make([]any, len(args)) copy(newArgs, args) newArgs[1] = base.Tool(newTool) newArgs[3] = ofile + ".new" // x.6 becomes x.6.new diff --git a/src/cmd/go/proxy_test.go b/src/cmd/go/proxy_test.go index a387fe67db..517a885542 100644 --- a/src/cmd/go/proxy_test.go +++ b/src/cmd/go/proxy_test.go @@ -357,7 +357,7 @@ func proxyHandler(w http.ResponseWriter, r *http.Request) { zip []byte err error } - c := zipCache.Do(a, func() interface{} { + c := zipCache.Do(a, func() any { var buf bytes.Buffer z := zip.NewWriter(&buf) for _, f := range a.Files { @@ -431,7 +431,7 @@ func readArchive(path, vers string) (*txtar.Archive, error) { prefix := strings.ReplaceAll(enc, "/", "_") name := filepath.Join(cmdGoDir, "testdata/mod", prefix+"_"+encVers+".txt") - a := archiveCache.Do(name, func() interface{} { + a := archiveCache.Do(name, func() any { a, err := txtar.ParseFile(name) if err != nil { if testing.Verbose() || !os.IsNotExist(err) { diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go index 101195fc9d..dbfba2291c 100644 --- a/src/cmd/go/script_test.go +++ b/src/cmd/go/script_test.go @@ -375,7 +375,7 @@ Script: default: if strings.HasPrefix(cond.tag, "exec:") { prog := cond.tag[len("exec:"):] - ok = execCache.Do(prog, func() interface{} { + ok = execCache.Do(prog, func() any { if runtime.GOOS == "plan9" && prog == "git" { // The Git command is usually not the real Git on Plan 9. // See https://golang.org/issues/29640. @@ -1310,7 +1310,7 @@ func (ts *testScript) expand(s string, inRegexp bool) string { } // fatalf aborts the test with the given failure message. -func (ts *testScript) fatalf(format string, args ...interface{}) { +func (ts *testScript) fatalf(format string, args ...any) { fmt.Fprintf(&ts.log, "FAIL: %s:%d: %s\n", ts.file, ts.lineno, fmt.Sprintf(format, args...)) ts.t.FailNow() } diff --git a/src/cmd/go/testdata/addmod.go b/src/cmd/go/testdata/addmod.go index a1ace4ce59..eac2a7ad44 100644 --- a/src/cmd/go/testdata/addmod.go +++ b/src/cmd/go/testdata/addmod.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // Addmod adds a module as a txtar archive to the testdata/mod directory. @@ -39,7 +40,7 @@ func usage() { var tmpdir string -func fatalf(format string, args ...interface{}) { +func fatalf(format string, args ...any) { os.RemoveAll(tmpdir) log.Fatalf(format, args...) } diff --git a/src/cmd/go/testdata/savedir.go b/src/cmd/go/testdata/savedir.go index 6a8a232702..53c78cfb00 100644 --- a/src/cmd/go/testdata/savedir.go +++ b/src/cmd/go/testdata/savedir.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // Savedir archives a directory tree as a txtar archive printed to standard output. diff --git a/src/cmd/go/testdata/testterminal18153/terminal_test.go b/src/cmd/go/testdata/testterminal18153/terminal_test.go index 71493efe98..34ee580c0e 100644 --- a/src/cmd/go/testdata/testterminal18153/terminal_test.go +++ b/src/cmd/go/testdata/testterminal18153/terminal_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux // +build linux // This test is run by src/cmd/dist/test.go (cmd_go_test_terminal), diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go index 860d77aaf0..51f6e652d9 100644 --- a/src/cmd/gofmt/gofmt.go +++ b/src/cmd/gofmt/gofmt.go @@ -183,7 +183,7 @@ func (r *reporter) getState() *reporterState { // Warnf emits a warning message to the reporter's error stream, // without changing its exit code. -func (r *reporter) Warnf(format string, args ...interface{}) { +func (r *reporter) Warnf(format string, args ...any) { fmt.Fprintf(r.getState().err, format, args...) } diff --git a/src/cmd/internal/buildid/buildid_test.go b/src/cmd/internal/buildid/buildid_test.go index 4895a49e11..f04e328046 100644 --- a/src/cmd/internal/buildid/buildid_test.go +++ b/src/cmd/internal/buildid/buildid_test.go @@ -103,7 +103,7 @@ func TestFindAndHash(t *testing.T) { id[i] = byte(i) } numError := 0 - errorf := func(msg string, args ...interface{}) { + errorf := func(msg string, args ...any) { t.Errorf(msg, args...) if numError++; numError > 20 { t.Logf("stopping after too many errors") diff --git a/src/cmd/internal/buildid/rewrite.go b/src/cmd/internal/buildid/rewrite.go index 8814950db0..becc078242 100644 --- a/src/cmd/internal/buildid/rewrite.go +++ b/src/cmd/internal/buildid/rewrite.go @@ -151,7 +151,7 @@ func (r *excludedReader) Read(p []byte) (int, error) { return n, err } -func findMachoCodeSignature(r interface{}) (*macho.File, codesign.CodeSigCmd, bool) { +func findMachoCodeSignature(r any) (*macho.File, codesign.CodeSigCmd, bool) { ra, ok := r.(io.ReaderAt) if !ok { return nil, codesign.CodeSigCmd{}, false diff --git a/src/cmd/internal/test2json/test2json_test.go b/src/cmd/internal/test2json/test2json_test.go index 4683907888..e69739d3fe 100644 --- a/src/cmd/internal/test2json/test2json_test.go +++ b/src/cmd/internal/test2json/test2json_test.go @@ -145,7 +145,7 @@ func writeAndKill(w io.Writer, b []byte) { // and fails the test with a useful message if they don't match. func diffJSON(t *testing.T, have, want []byte) { t.Helper() - type event map[string]interface{} + type event map[string]any // Parse into events, one per line. parseEvents := func(b []byte) ([]event, []string) { diff --git a/src/cmd/internal/traceviewer/format.go b/src/cmd/internal/traceviewer/format.go index 871477447f..3636c1053d 100644 --- a/src/cmd/internal/traceviewer/format.go +++ b/src/cmd/internal/traceviewer/format.go @@ -16,20 +16,20 @@ type Data struct { } type Event struct { - Name string `json:"name,omitempty"` - Phase string `json:"ph"` - Scope string `json:"s,omitempty"` - Time float64 `json:"ts"` - Dur float64 `json:"dur,omitempty"` - PID uint64 `json:"pid"` - TID uint64 `json:"tid"` - ID uint64 `json:"id,omitempty"` - BindPoint string `json:"bp,omitempty"` - Stack int `json:"sf,omitempty"` - EndStack int `json:"esf,omitempty"` - Arg interface{} `json:"args,omitempty"` - Cname string `json:"cname,omitempty"` - Category string `json:"cat,omitempty"` + Name string `json:"name,omitempty"` + Phase string `json:"ph"` + Scope string `json:"s,omitempty"` + Time float64 `json:"ts"` + Dur float64 `json:"dur,omitempty"` + PID uint64 `json:"pid"` + TID uint64 `json:"tid"` + ID uint64 `json:"id,omitempty"` + BindPoint string `json:"bp,omitempty"` + Stack int `json:"sf,omitempty"` + EndStack int `json:"esf,omitempty"` + Arg any `json:"args,omitempty"` + Cname string `json:"cname,omitempty"` + Category string `json:"cat,omitempty"` } type Frame struct { diff --git a/src/cmd/nm/nm.go b/src/cmd/nm/nm.go index 457239921b..178eeb27be 100644 --- a/src/cmd/nm/nm.go +++ b/src/cmd/nm/nm.go @@ -93,7 +93,7 @@ func main() { var exitCode = 0 -func errorf(format string, args ...interface{}) { +func errorf(format string, args ...any) { log.Printf(format, args...) exitCode = 1 } diff --git a/src/cmd/pack/pack_test.go b/src/cmd/pack/pack_test.go index 7842b562dc..81e78f53e2 100644 --- a/src/cmd/pack/pack_test.go +++ b/src/cmd/pack/pack_test.go @@ -203,7 +203,7 @@ func TestLargeDefs(t *testing.T) { } b := bufio.NewWriter(f) - printf := func(format string, args ...interface{}) { + printf := func(format string, args ...any) { _, err := fmt.Fprintf(b, format, args...) if err != nil { t.Fatalf("Writing to %s: %v", large, err) @@ -454,7 +454,7 @@ func (f *FakeFile) IsDir() bool { return false } -func (f *FakeFile) Sys() interface{} { +func (f *FakeFile) Sys() any { return nil } diff --git a/src/cmd/pprof/readlineui.go b/src/cmd/pprof/readlineui.go index 7ad712cd60..b269177650 100644 --- a/src/cmd/pprof/readlineui.go +++ b/src/cmd/pprof/readlineui.go @@ -69,18 +69,18 @@ func (r *readlineUI) ReadLine(prompt string) (string, error) { // It formats the text as fmt.Print would and adds a final \n if not already present. // For line-based UI, Print writes to standard error. // (Standard output is reserved for report data.) -func (r *readlineUI) Print(args ...interface{}) { +func (r *readlineUI) Print(args ...any) { r.print(false, args...) } // PrintErr shows an error message to the user. // It formats the text as fmt.Print would and adds a final \n if not already present. // For line-based UI, PrintErr writes to standard error. -func (r *readlineUI) PrintErr(args ...interface{}) { +func (r *readlineUI) PrintErr(args ...any) { r.print(true, args...) } -func (r *readlineUI) print(withColor bool, args ...interface{}) { +func (r *readlineUI) print(withColor bool, args ...any) { text := fmt.Sprint(args...) if !strings.HasSuffix(text, "\n") { text += "\n" diff --git a/src/cmd/trace/main.go b/src/cmd/trace/main.go index 3aeba223ee..a30db9a012 100644 --- a/src/cmd/trace/main.go +++ b/src/cmd/trace/main.go @@ -206,7 +206,7 @@ var templMain = template.Must(template.New("").Parse(` `)) -func dief(msg string, args ...interface{}) { +func dief(msg string, args ...any) { fmt.Fprintf(os.Stderr, msg, args...) os.Exit(1) } diff --git a/src/cmd/trace/mmu.go b/src/cmd/trace/mmu.go index 1d1fd2ea94..b71dcd6411 100644 --- a/src/cmd/trace/mmu.go +++ b/src/cmd/trace/mmu.go @@ -155,7 +155,7 @@ func httpMMUPlot(w http.ResponseWriter, r *http.Request) { } // Create JSON response. - err = json.NewEncoder(w).Encode(map[string]interface{}{"xMin": int64(xMin), "xMax": int64(xMax), "quantiles": quantiles, "curve": plot}) + err = json.NewEncoder(w).Encode(map[string]any{"xMin": int64(xMin), "xMax": int64(xMax), "quantiles": quantiles, "curve": plot}) if err != nil { log.Printf("failed to serialize response: %v", err) return diff --git a/src/cmd/trace/trace.go b/src/cmd/trace/trace.go index ca10736c32..0139639dae 100644 --- a/src/cmd/trace/trace.go +++ b/src/cmd/trace/trace.go @@ -1054,7 +1054,7 @@ func (ctx *traceContext) emitInstant(ev *trace.Event, name, category string) { cname = colorLightGrey } } - var arg interface{} + var arg any if ev.Type == trace.EvProcStart { type Arg struct { ThreadID uint64 diff --git a/src/container/heap/example_intheap_test.go b/src/container/heap/example_intheap_test.go index 02d3d8668e..7e7ef8b8df 100644 --- a/src/container/heap/example_intheap_test.go +++ b/src/container/heap/example_intheap_test.go @@ -17,13 +17,13 @@ func (h IntHeap) Len() int { return len(h) } func (h IntHeap) Less(i, j int) bool { return h[i] < h[j] } func (h IntHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } -func (h *IntHeap) Push(x interface{}) { +func (h *IntHeap) Push(x any) { // Push and Pop use pointer receivers because they modify the slice's length, // not just its contents. *h = append(*h, x.(int)) } -func (h *IntHeap) Pop() interface{} { +func (h *IntHeap) Pop() any { old := *h n := len(old) x := old[n-1] diff --git a/src/container/heap/example_pq_test.go b/src/container/heap/example_pq_test.go index da1a233b70..4511b6c33e 100644 --- a/src/container/heap/example_pq_test.go +++ b/src/container/heap/example_pq_test.go @@ -34,14 +34,14 @@ func (pq PriorityQueue) Swap(i, j int) { pq[j].index = j } -func (pq *PriorityQueue) Push(x interface{}) { +func (pq *PriorityQueue) Push(x any) { n := len(*pq) item := x.(*Item) item.index = n *pq = append(*pq, item) } -func (pq *PriorityQueue) Pop() interface{} { +func (pq *PriorityQueue) Pop() any { old := *pq n := len(old) item := old[n-1] diff --git a/src/container/heap/heap.go b/src/container/heap/heap.go index 2e09da8613..c3168f9b27 100644 --- a/src/container/heap/heap.go +++ b/src/container/heap/heap.go @@ -31,8 +31,8 @@ import "sort" // use heap.Push and heap.Pop. type Interface interface { sort.Interface - Push(x interface{}) // add x as element Len() - Pop() interface{} // remove and return element Len() - 1. + Push(x any) // add x as element Len() + Pop() any // remove and return element Len() - 1. } // Init establishes the heap invariants required by the other routines in this package. @@ -49,7 +49,7 @@ func Init(h Interface) { // Push pushes the element x onto the heap. // The complexity is O(log n) where n = h.Len(). -func Push(h Interface, x interface{}) { +func Push(h Interface, x any) { h.Push(x) up(h, h.Len()-1) } @@ -57,7 +57,7 @@ func Push(h Interface, x interface{}) { // Pop removes and returns the minimum element (according to Less) from the heap. // The complexity is O(log n) where n = h.Len(). // Pop is equivalent to Remove(h, 0). -func Pop(h Interface) interface{} { +func Pop(h Interface) any { n := h.Len() - 1 h.Swap(0, n) down(h, 0, n) @@ -66,7 +66,7 @@ func Pop(h Interface) interface{} { // Remove removes and returns the element at index i from the heap. // The complexity is O(log n) where n = h.Len(). -func Remove(h Interface, i int) interface{} { +func Remove(h Interface, i int) any { n := h.Len() - 1 if n != i { h.Swap(i, n) diff --git a/src/container/heap/heap_test.go b/src/container/heap/heap_test.go index f19f9cfa74..c9f9f140ea 100644 --- a/src/container/heap/heap_test.go +++ b/src/container/heap/heap_test.go @@ -23,12 +23,12 @@ func (h *myHeap) Len() int { return len(*h) } -func (h *myHeap) Pop() (v interface{}) { +func (h *myHeap) Pop() (v any) { *h, v = (*h)[:h.Len()-1], (*h)[h.Len()-1] return } -func (h *myHeap) Push(v interface{}) { +func (h *myHeap) Push(v any) { *h = append(*h, v.(int)) } diff --git a/src/container/list/list.go b/src/container/list/list.go index aa89b7f599..9555ad3900 100644 --- a/src/container/list/list.go +++ b/src/container/list/list.go @@ -24,7 +24,7 @@ type Element struct { list *List // The value stored with this element. - Value interface{} + Value any } // Next returns the next list element or nil. @@ -100,7 +100,7 @@ func (l *List) insert(e, at *Element) *Element { } // insertValue is a convenience wrapper for insert(&Element{Value: v}, at). -func (l *List) insertValue(v interface{}, at *Element) *Element { +func (l *List) insertValue(v any, at *Element) *Element { return l.insert(&Element{Value: v}, at) } @@ -131,7 +131,7 @@ func (l *List) move(e, at *Element) { // Remove removes e from l if e is an element of list l. // It returns the element value e.Value. // The element must not be nil. -func (l *List) Remove(e *Element) interface{} { +func (l *List) Remove(e *Element) any { if e.list == l { // if e.list == l, l must have been initialized when e was inserted // in l or l == nil (e is a zero Element) and l.remove will crash @@ -141,13 +141,13 @@ func (l *List) Remove(e *Element) interface{} { } // PushFront inserts a new element e with value v at the front of list l and returns e. -func (l *List) PushFront(v interface{}) *Element { +func (l *List) PushFront(v any) *Element { l.lazyInit() return l.insertValue(v, &l.root) } // PushBack inserts a new element e with value v at the back of list l and returns e. -func (l *List) PushBack(v interface{}) *Element { +func (l *List) PushBack(v any) *Element { l.lazyInit() return l.insertValue(v, l.root.prev) } @@ -155,7 +155,7 @@ func (l *List) PushBack(v interface{}) *Element { // InsertBefore inserts a new element e with value v immediately before mark and returns e. // If mark is not an element of l, the list is not modified. // The mark must not be nil. -func (l *List) InsertBefore(v interface{}, mark *Element) *Element { +func (l *List) InsertBefore(v any, mark *Element) *Element { if mark.list != l { return nil } @@ -166,7 +166,7 @@ func (l *List) InsertBefore(v interface{}, mark *Element) *Element { // InsertAfter inserts a new element e with value v immediately after mark and returns e. // If mark is not an element of l, the list is not modified. // The mark must not be nil. -func (l *List) InsertAfter(v interface{}, mark *Element) *Element { +func (l *List) InsertAfter(v any, mark *Element) *Element { if mark.list != l { return nil } diff --git a/src/container/list/list_test.go b/src/container/list/list_test.go index c74724b398..daa2114997 100644 --- a/src/container/list/list_test.go +++ b/src/container/list/list_test.go @@ -141,7 +141,7 @@ func TestList(t *testing.T) { checkListPointers(t, l, []*Element{}) } -func checkList(t *testing.T, l *List, es []interface{}) { +func checkList(t *testing.T, l *List, es []any) { if !checkListLen(t, l, len(es)) { return } @@ -169,36 +169,36 @@ func TestExtending(t *testing.T) { l3 := New() l3.PushBackList(l1) - checkList(t, l3, []interface{}{1, 2, 3}) + checkList(t, l3, []any{1, 2, 3}) l3.PushBackList(l2) - checkList(t, l3, []interface{}{1, 2, 3, 4, 5}) + checkList(t, l3, []any{1, 2, 3, 4, 5}) l3 = New() l3.PushFrontList(l2) - checkList(t, l3, []interface{}{4, 5}) + checkList(t, l3, []any{4, 5}) l3.PushFrontList(l1) - checkList(t, l3, []interface{}{1, 2, 3, 4, 5}) + checkList(t, l3, []any{1, 2, 3, 4, 5}) - checkList(t, l1, []interface{}{1, 2, 3}) - checkList(t, l2, []interface{}{4, 5}) + checkList(t, l1, []any{1, 2, 3}) + checkList(t, l2, []any{4, 5}) l3 = New() l3.PushBackList(l1) - checkList(t, l3, []interface{}{1, 2, 3}) + checkList(t, l3, []any{1, 2, 3}) l3.PushBackList(l3) - checkList(t, l3, []interface{}{1, 2, 3, 1, 2, 3}) + checkList(t, l3, []any{1, 2, 3, 1, 2, 3}) l3 = New() l3.PushFrontList(l1) - checkList(t, l3, []interface{}{1, 2, 3}) + checkList(t, l3, []any{1, 2, 3}) l3.PushFrontList(l3) - checkList(t, l3, []interface{}{1, 2, 3, 1, 2, 3}) + checkList(t, l3, []any{1, 2, 3, 1, 2, 3}) l3 = New() l1.PushBackList(l3) - checkList(t, l1, []interface{}{1, 2, 3}) + checkList(t, l1, []any{1, 2, 3}) l1.PushFrontList(l3) - checkList(t, l1, []interface{}{1, 2, 3}) + checkList(t, l1, []any{1, 2, 3}) } func TestRemove(t *testing.T) { @@ -289,19 +289,19 @@ func TestMove(t *testing.T) { func TestZeroList(t *testing.T) { var l1 = new(List) l1.PushFront(1) - checkList(t, l1, []interface{}{1}) + checkList(t, l1, []any{1}) var l2 = new(List) l2.PushBack(1) - checkList(t, l2, []interface{}{1}) + checkList(t, l2, []any{1}) var l3 = new(List) l3.PushFrontList(l1) - checkList(t, l3, []interface{}{1}) + checkList(t, l3, []any{1}) var l4 = new(List) l4.PushBackList(l2) - checkList(t, l4, []interface{}{1}) + checkList(t, l4, []any{1}) } // Test that a list l is not modified when calling InsertBefore with a mark that is not an element of l. @@ -311,7 +311,7 @@ func TestInsertBeforeUnknownMark(t *testing.T) { l.PushBack(2) l.PushBack(3) l.InsertBefore(1, new(Element)) - checkList(t, &l, []interface{}{1, 2, 3}) + checkList(t, &l, []any{1, 2, 3}) } // Test that a list l is not modified when calling InsertAfter with a mark that is not an element of l. @@ -321,7 +321,7 @@ func TestInsertAfterUnknownMark(t *testing.T) { l.PushBack(2) l.PushBack(3) l.InsertAfter(1, new(Element)) - checkList(t, &l, []interface{}{1, 2, 3}) + checkList(t, &l, []any{1, 2, 3}) } // Test that a list l is not modified when calling MoveAfter or MoveBefore with a mark that is not an element of l. @@ -333,10 +333,10 @@ func TestMoveUnknownMark(t *testing.T) { e2 := l2.PushBack(2) l1.MoveAfter(e1, e2) - checkList(t, &l1, []interface{}{1}) - checkList(t, &l2, []interface{}{2}) + checkList(t, &l1, []any{1}) + checkList(t, &l2, []any{2}) l1.MoveBefore(e1, e2) - checkList(t, &l1, []interface{}{1}) - checkList(t, &l2, []interface{}{2}) + checkList(t, &l1, []any{1}) + checkList(t, &l2, []any{2}) } diff --git a/src/container/ring/example_test.go b/src/container/ring/example_test.go index 30bd0d74c9..4b659d25da 100644 --- a/src/container/ring/example_test.go +++ b/src/container/ring/example_test.go @@ -88,7 +88,7 @@ func ExampleRing_Do() { } // Iterate through the ring and print its contents - r.Do(func(p interface{}) { + r.Do(func(p any) { fmt.Println(p.(int)) }) @@ -117,7 +117,7 @@ func ExampleRing_Move() { r = r.Move(3) // Iterate through the ring and print its contents - r.Do(func(p interface{}) { + r.Do(func(p any) { fmt.Println(p.(int)) }) @@ -154,7 +154,7 @@ func ExampleRing_Link() { rs := r.Link(s) // Iterate through the combined ring and print its contents - rs.Do(func(p interface{}) { + rs.Do(func(p any) { fmt.Println(p.(int)) }) @@ -182,7 +182,7 @@ func ExampleRing_Unlink() { r.Unlink(3) // Iterate through the remaining ring and print its contents - r.Do(func(p interface{}) { + r.Do(func(p any) { fmt.Println(p.(int)) }) diff --git a/src/container/ring/ring.go b/src/container/ring/ring.go index 6d3b3e5b32..ce15032543 100644 --- a/src/container/ring/ring.go +++ b/src/container/ring/ring.go @@ -13,7 +13,7 @@ package ring // type Ring struct { next, prev *Ring - Value interface{} // for use by client; untouched by this library + Value any // for use by client; untouched by this library } func (r *Ring) init() *Ring { @@ -131,7 +131,7 @@ func (r *Ring) Len() int { // Do calls function f on each element of the ring, in forward order. // The behavior of Do is undefined if f changes *r. -func (r *Ring) Do(f func(interface{})) { +func (r *Ring) Do(f func(any)) { if r != nil { f(r.Value) for p := r.Next(); p != r; p = p.next { diff --git a/src/container/ring/ring_test.go b/src/container/ring/ring_test.go index 41d18abf8b..28acbbc250 100644 --- a/src/container/ring/ring_test.go +++ b/src/container/ring/ring_test.go @@ -33,7 +33,7 @@ func verify(t *testing.T, r *Ring, N int, sum int) { // iteration n = 0 s := 0 - r.Do(func(p interface{}) { + r.Do(func(p any) { n++ if p != nil { s += p.(int) diff --git a/src/context/context.go b/src/context/context.go index a9e14703fd..cf010b2a69 100644 --- a/src/context/context.go +++ b/src/context/context.go @@ -150,7 +150,7 @@ type Context interface { // u, ok := ctx.Value(userKey).(*User) // return u, ok // } - Value(key interface{}) interface{} + Value(key any) any } // Canceled is the error returned by Context.Err when the context is canceled. @@ -182,7 +182,7 @@ func (*emptyCtx) Err() error { return nil } -func (*emptyCtx) Value(key interface{}) interface{} { +func (*emptyCtx) Value(key any) any { return nil } @@ -348,7 +348,7 @@ type cancelCtx struct { err error // set to non-nil by the first cancel call } -func (c *cancelCtx) Value(key interface{}) interface{} { +func (c *cancelCtx) Value(key any) any { if key == &cancelCtxKey { return c } @@ -520,7 +520,7 @@ func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { // interface{}, context keys often have concrete type // struct{}. Alternatively, exported context key variables' static // type should be a pointer or interface. -func WithValue(parent Context, key, val interface{}) Context { +func WithValue(parent Context, key, val any) Context { if parent == nil { panic("cannot create context from nil parent") } @@ -537,13 +537,13 @@ func WithValue(parent Context, key, val interface{}) Context { // delegates all other calls to the embedded Context. type valueCtx struct { Context - key, val interface{} + key, val any } // stringify tries a bit to stringify v, without using fmt, since we don't // want context depending on the unicode tables. This is only used by // *valueCtx.String(). -func stringify(v interface{}) string { +func stringify(v any) string { switch s := v.(type) { case stringer: return s.String() @@ -559,14 +559,14 @@ func (c *valueCtx) String() string { ", val " + stringify(c.val) + ")" } -func (c *valueCtx) Value(key interface{}) interface{} { +func (c *valueCtx) Value(key any) any { if c.key == key { return c.val } return value(c.Context, key) } -func value(c Context, key interface{}) interface{} { +func value(c Context, key any) any { for { switch ctx := c.(type) { case *valueCtx: diff --git a/src/context/context_test.go b/src/context/context_test.go index a2e2324a0e..8673c0fdea 100644 --- a/src/context/context_test.go +++ b/src/context/context_test.go @@ -16,21 +16,21 @@ import ( type testingT interface { Deadline() (time.Time, bool) - Error(args ...interface{}) - Errorf(format string, args ...interface{}) + Error(args ...any) + Errorf(format string, args ...any) Fail() FailNow() Failed() bool - Fatal(args ...interface{}) - Fatalf(format string, args ...interface{}) + Fatal(args ...any) + Fatalf(format string, args ...any) Helper() - Log(args ...interface{}) - Logf(format string, args ...interface{}) + Log(args ...any) + Logf(format string, args ...any) Name() string Parallel() - Skip(args ...interface{}) + Skip(args ...any) SkipNow() - Skipf(format string, args ...interface{}) + Skipf(format string, args ...any) Skipped() bool } @@ -553,7 +553,7 @@ func testLayers(t testingT, seed int64, testTimeout bool) { t.Parallel() r := rand.New(rand.NewSource(seed)) - errorf := func(format string, a ...interface{}) { + errorf := func(format string, a ...any) { t.Errorf(fmt.Sprintf("seed=%d: %s", seed, format), a...) } const ( @@ -691,7 +691,7 @@ func XTestInvalidDerivedFail(t testingT) { } } -func recoveredValue(fn func()) (v interface{}) { +func recoveredValue(fn func()) (v any) { defer func() { v = recover() }() fn() return diff --git a/src/crypto/crypto.go b/src/crypto/crypto.go index cb87972afc..fe1c0690bc 100644 --- a/src/crypto/crypto.go +++ b/src/crypto/crypto.go @@ -159,7 +159,7 @@ func RegisterHash(h Hash, f func() hash.Hash) { // } // // which can be used for increased type safety within applications. -type PublicKey interface{} +type PublicKey any // PrivateKey represents a private key using an unspecified algorithm. // @@ -173,7 +173,7 @@ type PublicKey interface{} // // as well as purpose-specific interfaces such as Signer and Decrypter, which // can be used for increased type safety within applications. -type PrivateKey interface{} +type PrivateKey any // Signer is an interface for an opaque private key that can be used for // signing operations. For example, an RSA key kept in a hardware module. @@ -220,4 +220,4 @@ type Decrypter interface { Decrypt(rand io.Reader, msg []byte, opts DecrypterOpts) (plaintext []byte, err error) } -type DecrypterOpts interface{} +type DecrypterOpts any diff --git a/src/crypto/ed25519/internal/edwards25519/scalar_alias_test.go b/src/crypto/ed25519/internal/edwards25519/scalar_alias_test.go index 18d800d556..827153b9bd 100644 --- a/src/crypto/ed25519/internal/edwards25519/scalar_alias_test.go +++ b/src/crypto/ed25519/internal/edwards25519/scalar_alias_test.go @@ -71,7 +71,7 @@ func TestScalarAliasing(t *testing.T) { return x == x1 && y == y1 } - for name, f := range map[string]interface{}{ + for name, f := range map[string]any{ "Negate": func(v, x Scalar) bool { return checkAliasingOneArg((*Scalar).Negate, v, x) }, diff --git a/src/crypto/tls/cipher_suites.go b/src/crypto/tls/cipher_suites.go index 4bf06468c6..d164991eec 100644 --- a/src/crypto/tls/cipher_suites.go +++ b/src/crypto/tls/cipher_suites.go @@ -140,7 +140,7 @@ type cipherSuite struct { ka func(version uint16) keyAgreement // flags is a bitmask of the suite* values, above. flags int - cipher func(key, iv []byte, isRead bool) interface{} + cipher func(key, iv []byte, isRead bool) any mac func(key []byte) hash.Hash aead func(key, fixedNonce []byte) aead } @@ -399,12 +399,12 @@ func aesgcmPreferred(ciphers []uint16) bool { return false } -func cipherRC4(key, iv []byte, isRead bool) interface{} { +func cipherRC4(key, iv []byte, isRead bool) any { cipher, _ := rc4.NewCipher(key) return cipher } -func cipher3DES(key, iv []byte, isRead bool) interface{} { +func cipher3DES(key, iv []byte, isRead bool) any { block, _ := des.NewTripleDESCipher(key) if isRead { return cipher.NewCBCDecrypter(block, iv) @@ -412,7 +412,7 @@ func cipher3DES(key, iv []byte, isRead bool) interface{} { return cipher.NewCBCEncrypter(block, iv) } -func cipherAES(key, iv []byte, isRead bool) interface{} { +func cipherAES(key, iv []byte, isRead bool) any { block, _ := aes.NewCipher(key) if isRead { return cipher.NewCBCDecrypter(block, iv) diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go index bb5bec3c4d..e6e7598ce9 100644 --- a/src/crypto/tls/common.go +++ b/src/crypto/tls/common.go @@ -1466,7 +1466,7 @@ func defaultConfig() *Config { return &emptyConfig } -func unexpectedMessageError(wanted, got interface{}) error { +func unexpectedMessageError(wanted, got any) error { return fmt.Errorf("tls: received unexpected handshake message of type %T when waiting for %T", got, wanted) } diff --git a/src/crypto/tls/conn.go b/src/crypto/tls/conn.go index 300e9a233c..28ab063782 100644 --- a/src/crypto/tls/conn.go +++ b/src/crypto/tls/conn.go @@ -163,16 +163,16 @@ func (c *Conn) NetConn() net.Conn { type halfConn struct { sync.Mutex - err error // first permanent error - version uint16 // protocol version - cipher interface{} // cipher algorithm + err error // first permanent error + version uint16 // protocol version + cipher any // cipher algorithm mac hash.Hash seq [8]byte // 64-bit sequence number scratchBuf [13]byte // to avoid allocs; interface method args escape - nextCipher interface{} // next encryption state - nextMac hash.Hash // next MAC algorithm + nextCipher any // next encryption state + nextMac hash.Hash // next MAC algorithm trafficSecret []byte // current TLS 1.3 traffic secret } @@ -197,7 +197,7 @@ func (hc *halfConn) setErrorLocked(err error) error { // prepareCipherSpec sets the encryption and MAC states // that a subsequent changeCipherSpec will use. -func (hc *halfConn) prepareCipherSpec(version uint16, cipher interface{}, mac hash.Hash) { +func (hc *halfConn) prepareCipherSpec(version uint16, cipher any, mac hash.Hash) { hc.version = version hc.nextCipher = cipher hc.nextMac = mac @@ -935,7 +935,7 @@ func (c *Conn) flush() (int, error) { // outBufPool pools the record-sized scratch buffers used by writeRecordLocked. var outBufPool = sync.Pool{ - New: func() interface{} { + New: func() any { return new([]byte) }, } @@ -1011,7 +1011,7 @@ func (c *Conn) writeRecord(typ recordType, data []byte) (int, error) { // readHandshake reads the next handshake message from // the record layer. -func (c *Conn) readHandshake() (interface{}, error) { +func (c *Conn) readHandshake() (any, error) { for c.hand.Len() < 4 { if err := c.readRecord(); err != nil { return nil, err diff --git a/src/crypto/tls/generate_cert.go b/src/crypto/tls/generate_cert.go index 58fdd025db..74509c9dea 100644 --- a/src/crypto/tls/generate_cert.go +++ b/src/crypto/tls/generate_cert.go @@ -37,7 +37,7 @@ var ( ed25519Key = flag.Bool("ed25519", false, "Generate an Ed25519 key") ) -func publicKey(priv interface{}) interface{} { +func publicKey(priv any) any { switch k := priv.(type) { case *rsa.PrivateKey: return &k.PublicKey @@ -57,7 +57,7 @@ func main() { log.Fatalf("Missing required --host parameter") } - var priv interface{} + var priv any var err error switch *ecdsaCurve { case "": diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go index 2ae6f3f534..a3e00777f1 100644 --- a/src/crypto/tls/handshake_client.go +++ b/src/crypto/tls/handshake_client.go @@ -657,7 +657,7 @@ func (hs *clientHandshakeState) establishKeys() error { clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen) - var clientCipher, serverCipher interface{} + var clientCipher, serverCipher any var clientHash, serverHash hash.Hash if hs.suite.cipher != nil { clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */) diff --git a/src/crypto/tls/handshake_client_test.go b/src/crypto/tls/handshake_client_test.go index 2158f3247b..0950bb0ac4 100644 --- a/src/crypto/tls/handshake_client_test.go +++ b/src/crypto/tls/handshake_client_test.go @@ -134,7 +134,7 @@ type clientTest struct { cert []byte // key, if not nil, contains either a *rsa.PrivateKey, ed25519.PrivateKey or // *ecdsa.PrivateKey which is the private key for the reference server. - key interface{} + key any // extensions, if not nil, contains a list of extension data to be returned // from the ServerHello. The data should be in standard TLS format with // a 2-byte uint16 type, 2-byte data length, followed by the extension data. @@ -171,7 +171,7 @@ func (test *clientTest) connFromCommand() (conn *recordingConn, child *exec.Cmd, certPath := tempFile(string(cert)) defer os.Remove(certPath) - var key interface{} = testRSAPrivateKey + var key any = testRSAPrivateKey if test.key != nil { key = test.key } diff --git a/src/crypto/tls/handshake_messages_test.go b/src/crypto/tls/handshake_messages_test.go index bb8aea8670..cc427bf72a 100644 --- a/src/crypto/tls/handshake_messages_test.go +++ b/src/crypto/tls/handshake_messages_test.go @@ -14,7 +14,7 @@ import ( "time" ) -var tests = []interface{}{ +var tests = []any{ &clientHelloMsg{}, &serverHelloMsg{}, &finishedMsg{}, diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go index 5cb152755b..097046340b 100644 --- a/src/crypto/tls/handshake_server.go +++ b/src/crypto/tls/handshake_server.go @@ -681,7 +681,7 @@ func (hs *serverHandshakeState) establishKeys() error { clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen) - var clientCipher, serverCipher interface{} + var clientCipher, serverCipher any var clientHash, serverHash hash.Hash if hs.suite.aead == nil { diff --git a/src/crypto/tls/handshake_server_test.go b/src/crypto/tls/handshake_server_test.go index 5fb2ebbbb3..6d2c405626 100644 --- a/src/crypto/tls/handshake_server_test.go +++ b/src/crypto/tls/handshake_server_test.go @@ -249,7 +249,7 @@ func TestTLS12OnlyCipherSuites(t *testing.T) { } c, s := localPipe(t) - replyChan := make(chan interface{}) + replyChan := make(chan any) go func() { cli := Client(c, testConfig) cli.vers = clientHello.vers @@ -304,7 +304,7 @@ func TestTLSPointFormats(t *testing.T) { } c, s := localPipe(t) - replyChan := make(chan interface{}) + replyChan := make(chan any) go func() { cli := Client(c, testConfig) cli.vers = clientHello.vers @@ -600,7 +600,7 @@ func (test *serverTest) connFromCommand() (conn *recordingConn, child *exec.Cmd, return nil, nil, err } - connChan := make(chan interface{}, 1) + connChan := make(chan any, 1) go func() { tcpConn, err := l.Accept() if err != nil { diff --git a/src/crypto/x509/name_constraints_test.go b/src/crypto/x509/name_constraints_test.go index a6b5aa1ee6..04c1e7a627 100644 --- a/src/crypto/x509/name_constraints_test.go +++ b/src/crypto/x509/name_constraints_test.go @@ -1850,7 +1850,7 @@ func parseEKUs(ekuStrs []string) (ekus []ExtKeyUsage, unknowns []asn1.ObjectIden func TestConstraintCases(t *testing.T) { privateKeys := sync.Pool{ - New: func() interface{} { + New: func() any { priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { panic(err) diff --git a/src/crypto/x509/parser.go b/src/crypto/x509/parser.go index c2770f3f08..5e6bd54368 100644 --- a/src/crypto/x509/parser.go +++ b/src/crypto/x509/parser.go @@ -229,7 +229,7 @@ func parseExtension(der cryptobyte.String) (pkix.Extension, error) { return ext, nil } -func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{}, error) { +func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (any, error) { der := cryptobyte.String(keyData.PublicKey.RightAlign()) switch algo { case RSA: diff --git a/src/crypto/x509/pkcs8.go b/src/crypto/x509/pkcs8.go index a5ee4cfbfe..d77efa3156 100644 --- a/src/crypto/x509/pkcs8.go +++ b/src/crypto/x509/pkcs8.go @@ -30,7 +30,7 @@ type pkcs8 struct { // More types might be supported in the future. // // This kind of key is commonly encoded in PEM blocks of type "PRIVATE KEY". -func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) { +func ParsePKCS8PrivateKey(der []byte) (key any, err error) { var privKey pkcs8 if _, err := asn1.Unmarshal(der, &privKey); err != nil { if _, err := asn1.Unmarshal(der, &ecPrivateKey{}); err == nil { @@ -85,7 +85,7 @@ func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) { // and ed25519.PrivateKey. Unsupported key types result in an error. // // This kind of key is commonly encoded in PEM blocks of type "PRIVATE KEY". -func MarshalPKCS8PrivateKey(key interface{}) ([]byte, error) { +func MarshalPKCS8PrivateKey(key any) ([]byte, error) { var privKey pkcs8 switch k := key.(type) { diff --git a/src/crypto/x509/pkix/pkix.go b/src/crypto/x509/pkix/pkix.go index 62ae065496..e9179ed067 100644 --- a/src/crypto/x509/pkix/pkix.go +++ b/src/crypto/x509/pkix/pkix.go @@ -98,7 +98,7 @@ type RelativeDistinguishedNameSET []AttributeTypeAndValue // RFC 5280, Section 4.1.2.4. type AttributeTypeAndValue struct { Type asn1.ObjectIdentifier - Value interface{} + Value any } // AttributeTypeAndValueSET represents a set of ASN.1 sequences of diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go index 1562ee57af..e8c7707f3f 100644 --- a/src/crypto/x509/verify.go +++ b/src/crypto/x509/verify.go @@ -500,9 +500,9 @@ func (c *Certificate) checkNameConstraints(count *int, maxConstraintComparisons int, nameType string, name string, - parsedName interface{}, - match func(parsedName, constraint interface{}) (match bool, err error), - permitted, excluded interface{}) error { + parsedName any, + match func(parsedName, constraint any) (match bool, err error), + permitted, excluded any) error { excludedValue := reflect.ValueOf(excluded) @@ -609,7 +609,7 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V } if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "email address", name, mailbox, - func(parsedName, constraint interface{}) (bool, error) { + func(parsedName, constraint any) (bool, error) { return matchEmailConstraint(parsedName.(rfc2821Mailbox), constraint.(string)) }, c.PermittedEmailAddresses, c.ExcludedEmailAddresses); err != nil { return err @@ -622,7 +622,7 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V } if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "DNS name", name, name, - func(parsedName, constraint interface{}) (bool, error) { + func(parsedName, constraint any) (bool, error) { return matchDomainConstraint(parsedName.(string), constraint.(string)) }, c.PermittedDNSDomains, c.ExcludedDNSDomains); err != nil { return err @@ -636,7 +636,7 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V } if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "URI", name, uri, - func(parsedName, constraint interface{}) (bool, error) { + func(parsedName, constraint any) (bool, error) { return matchURIConstraint(parsedName.(*url.URL), constraint.(string)) }, c.PermittedURIDomains, c.ExcludedURIDomains); err != nil { return err @@ -649,7 +649,7 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V } if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "IP address", ip.String(), ip, - func(parsedName, constraint interface{}) (bool, error) { + func(parsedName, constraint any) (bool, error) { return matchIPConstraint(parsedName.(net.IP), constraint.(*net.IPNet)) }, c.PermittedIPRanges, c.ExcludedIPRanges); err != nil { return err diff --git a/src/crypto/x509/x509.go b/src/crypto/x509/x509.go index b5c2b22cd7..47be77d994 100644 --- a/src/crypto/x509/x509.go +++ b/src/crypto/x509/x509.go @@ -52,7 +52,7 @@ type pkixPublicKey struct { // ed25519.PublicKey. More types might be supported in the future. // // This kind of key is commonly encoded in PEM blocks of type "PUBLIC KEY". -func ParsePKIXPublicKey(derBytes []byte) (pub interface{}, err error) { +func ParsePKIXPublicKey(derBytes []byte) (pub any, err error) { var pki publicKeyInfo if rest, err := asn1.Unmarshal(derBytes, &pki); err != nil { if _, err := asn1.Unmarshal(derBytes, &pkcs1PublicKey{}); err == nil { @@ -69,7 +69,7 @@ func ParsePKIXPublicKey(derBytes []byte) (pub interface{}, err error) { return parsePublicKey(algo, &pki) } -func marshalPublicKey(pub interface{}) (publicKeyBytes []byte, publicKeyAlgorithm pkix.AlgorithmIdentifier, err error) { +func marshalPublicKey(pub any) (publicKeyBytes []byte, publicKeyAlgorithm pkix.AlgorithmIdentifier, err error) { switch pub := pub.(type) { case *rsa.PublicKey: publicKeyBytes, err = asn1.Marshal(pkcs1PublicKey{ @@ -114,7 +114,7 @@ func marshalPublicKey(pub interface{}) (publicKeyBytes []byte, publicKeyAlgorith // and ed25519.PublicKey. Unsupported key types result in an error. // // This kind of key is commonly encoded in PEM blocks of type "PUBLIC KEY". -func MarshalPKIXPublicKey(pub interface{}) ([]byte, error) { +func MarshalPKIXPublicKey(pub any) ([]byte, error) { var publicKeyBytes []byte var publicKeyAlgorithm pkix.AlgorithmIdentifier var err error @@ -636,7 +636,7 @@ type Certificate struct { SignatureAlgorithm SignatureAlgorithm PublicKeyAlgorithm PublicKeyAlgorithm - PublicKey interface{} + PublicKey any Version int SerialNumber *big.Int @@ -814,7 +814,7 @@ func (c *Certificate) getSANExtension() []byte { return nil } -func signaturePublicKeyAlgoMismatchError(expectedPubKeyAlgo PublicKeyAlgorithm, pubKey interface{}) error { +func signaturePublicKeyAlgoMismatchError(expectedPubKeyAlgo PublicKeyAlgorithm, pubKey any) error { return fmt.Errorf("x509: signature algorithm specifies an %s public key, but have public key of type %T", expectedPubKeyAlgo.String(), pubKey) } @@ -1357,7 +1357,7 @@ func subjectBytes(cert *Certificate) ([]byte, error) { // signingParamsForPublicKey returns the parameters to use for signing with // priv. If requestedSigAlgo is not zero then it overrides the default // signature algorithm. -func signingParamsForPublicKey(pub interface{}, requestedSigAlgo SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) { +func signingParamsForPublicKey(pub any, requestedSigAlgo SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) { var pubType PublicKeyAlgorithm switch pub := pub.(type) { @@ -1483,7 +1483,7 @@ var emptyASN1Subject = []byte{0x30, 0} // // If SubjectKeyId from template is empty and the template is a CA, SubjectKeyId // will be generated from the hash of the public key. -func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv interface{}) ([]byte, error) { +func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv any) ([]byte, error) { key, ok := priv.(crypto.Signer) if !ok { return nil, errors.New("x509: certificate private key does not implement crypto.Signer") @@ -1648,7 +1648,7 @@ func ParseDERCRL(derBytes []byte) (*pkix.CertificateList, error) { // // Note: this method does not generate an RFC 5280 conformant X.509 v2 CRL. // To generate a standards compliant CRL, use CreateRevocationList instead. -func (c *Certificate) CreateCRL(rand io.Reader, priv interface{}, revokedCerts []pkix.RevokedCertificate, now, expiry time.Time) (crlBytes []byte, err error) { +func (c *Certificate) CreateCRL(rand io.Reader, priv any, revokedCerts []pkix.RevokedCertificate, now, expiry time.Time) (crlBytes []byte, err error) { key, ok := priv.(crypto.Signer) if !ok { return nil, errors.New("x509: certificate private key does not implement crypto.Signer") @@ -1723,7 +1723,7 @@ type CertificateRequest struct { SignatureAlgorithm SignatureAlgorithm PublicKeyAlgorithm PublicKeyAlgorithm - PublicKey interface{} + PublicKey any Subject pkix.Name @@ -1860,7 +1860,7 @@ func parseCSRExtensions(rawAttributes []asn1.RawValue) ([]pkix.Extension, error) // ed25519.PrivateKey satisfies this.) // // The returned slice is the certificate request in DER encoding. -func CreateCertificateRequest(rand io.Reader, template *CertificateRequest, priv interface{}) (csr []byte, err error) { +func CreateCertificateRequest(rand io.Reader, template *CertificateRequest, priv any) (csr []byte, err error) { key, ok := priv.(crypto.Signer) if !ok { return nil, errors.New("x509: certificate private key does not implement crypto.Signer") diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go index 3345f57075..a42b852a42 100644 --- a/src/crypto/x509/x509_test.go +++ b/src/crypto/x509/x509_test.go @@ -68,7 +68,7 @@ func TestPKCS1MismatchPublicKeyFormat(t *testing.T) { } } -func testParsePKIXPublicKey(t *testing.T, pemBytes string) (pub interface{}) { +func testParsePKIXPublicKey(t *testing.T, pemBytes string) (pub any) { block, _ := pem.Decode([]byte(pemBytes)) pub, err := ParsePKIXPublicKey(block.Bytes) if err != nil { @@ -581,7 +581,7 @@ func TestCreateSelfSignedCertificate(t *testing.T) { tests := []struct { name string - pub, priv interface{} + pub, priv any checkSig bool sigAlgo SignatureAlgorithm }{ @@ -1233,7 +1233,7 @@ func TestCRLCreation(t *testing.T) { tests := []struct { name string - priv interface{} + priv any cert *Certificate }{ {"RSA CA", privRSA, certRSA}, @@ -1385,7 +1385,7 @@ func TestCreateCertificateRequest(t *testing.T) { tests := []struct { name string - priv interface{} + priv any sigAlgo SignatureAlgorithm }{ {"RSA", testPrivateKey, SHA256WithRSA}, diff --git a/src/database/sql/convert.go b/src/database/sql/convert.go index c0997b7fc5..4d9d070137 100644 --- a/src/database/sql/convert.go +++ b/src/database/sql/convert.go @@ -104,7 +104,7 @@ func defaultCheckNamedValue(nv *driver.NamedValue) (err error) { // The statement ds may be nil, if no statement is available. // // ci must be locked. -func driverArgsConnLocked(ci driver.Conn, ds *driverStmt, args []interface{}) ([]driver.NamedValue, error) { +func driverArgsConnLocked(ci driver.Conn, ds *driverStmt, args []any) ([]driver.NamedValue, error) { nvargs := make([]driver.NamedValue, len(args)) // -1 means the driver doesn't know how to count the number of @@ -207,7 +207,7 @@ func driverArgsConnLocked(ci driver.Conn, ds *driverStmt, args []interface{}) ([ // convertAssign is the same as convertAssignRows, but without the optional // rows argument. -func convertAssign(dest, src interface{}) error { +func convertAssign(dest, src any) error { return convertAssignRows(dest, src, nil) } @@ -216,7 +216,7 @@ func convertAssign(dest, src interface{}) error { // dest should be a pointer type. If rows is passed in, the rows will // be used as the parent for any cursor values converted from a // driver.Rows to a *Rows. -func convertAssignRows(dest, src interface{}, rows *Rows) error { +func convertAssignRows(dest, src any, rows *Rows) error { // Common cases, without reflect. switch s := src.(type) { case string: @@ -248,7 +248,7 @@ func convertAssignRows(dest, src interface{}, rows *Rows) error { } *d = string(s) return nil - case *interface{}: + case *any: if d == nil { return errNilPtr } @@ -295,7 +295,7 @@ func convertAssignRows(dest, src interface{}, rows *Rows) error { } case nil: switch d := dest.(type) { - case *interface{}: + case *any: if d == nil { return errNilPtr } @@ -376,7 +376,7 @@ func convertAssignRows(dest, src interface{}, rows *Rows) error { *d = bv.(bool) } return err - case *interface{}: + case *any: *d = src return nil } @@ -495,7 +495,7 @@ func cloneBytes(b []byte) []byte { return c } -func asString(src interface{}) string { +func asString(src any) string { switch v := src.(type) { case string: return v diff --git a/src/database/sql/convert_test.go b/src/database/sql/convert_test.go index 400da7ea57..6d09fa1eae 100644 --- a/src/database/sql/convert_test.go +++ b/src/database/sql/convert_test.go @@ -25,7 +25,7 @@ type ( ) type conversionTest struct { - s, d interface{} // source and destination + s, d any // source and destination // following are used if they're non-zero wantint int64 @@ -38,7 +38,7 @@ type conversionTest struct { wanttime time.Time wantbool bool // used if d is of type *bool wanterr string - wantiface interface{} + wantiface any wantptr *int64 // if non-nil, *d's pointed value must be equal to *wantptr wantnil bool // if true, *d must be *int64(nil) wantusrdef userDefined @@ -58,7 +58,7 @@ var ( scanf64 float64 scantime time.Time scanptr *int64 - scaniface interface{} + scaniface any ) func conversionTests() []conversionTest { @@ -161,7 +161,7 @@ func conversionTests() []conversionTest { {s: "1.5", d: &scanf64, wantf64: float64(1.5)}, // Pointers - {s: interface{}(nil), d: &scanptr, wantnil: true}, + {s: any(nil), d: &scanptr, wantnil: true}, {s: int64(42), d: &scanptr, wantptr: &answer}, // To interface{} @@ -185,27 +185,27 @@ func conversionTests() []conversionTest { } } -func intPtrValue(intptr interface{}) interface{} { +func intPtrValue(intptr any) any { return reflect.Indirect(reflect.Indirect(reflect.ValueOf(intptr))).Int() } -func intValue(intptr interface{}) int64 { +func intValue(intptr any) int64 { return reflect.Indirect(reflect.ValueOf(intptr)).Int() } -func uintValue(intptr interface{}) uint64 { +func uintValue(intptr any) uint64 { return reflect.Indirect(reflect.ValueOf(intptr)).Uint() } -func float64Value(ptr interface{}) float64 { +func float64Value(ptr any) float64 { return *(ptr.(*float64)) } -func float32Value(ptr interface{}) float32 { +func float32Value(ptr any) float32 { return *(ptr.(*float32)) } -func timeValue(ptr interface{}) time.Time { +func timeValue(ptr any) time.Time { return *(ptr.(*time.Time)) } @@ -216,7 +216,7 @@ func TestConversions(t *testing.T) { if err != nil { errstr = err.Error() } - errf := func(format string, args ...interface{}) { + errf := func(format string, args ...any) { base := fmt.Sprintf("convertAssign #%d: for %v (%T) -> %T, ", n, ct.s, ct.s, ct.d) t.Errorf(base+format, args...) } @@ -260,7 +260,7 @@ func TestConversions(t *testing.T) { errf("want pointer to %v, got %v", *ct.wantptr, intPtrValue(ct.d)) } } - if ifptr, ok := ct.d.(*interface{}); ok { + if ifptr, ok := ct.d.(*any); ok { if !reflect.DeepEqual(ct.wantiface, scaniface) { errf("want interface %#v, got %#v", ct.wantiface, scaniface) continue @@ -301,7 +301,7 @@ func TestNullString(t *testing.T) { type valueConverterTest struct { c driver.ValueConverter - in, out interface{} + in, out any err string } @@ -335,7 +335,7 @@ func TestValueConverters(t *testing.T) { func TestRawBytesAllocs(t *testing.T) { var tests = []struct { name string - in interface{} + in any want string }{ {"uint64", uint64(12345678), "12345678"}, @@ -355,7 +355,7 @@ func TestRawBytesAllocs(t *testing.T) { } buf := make(RawBytes, 10) - test := func(name string, in interface{}, want string) { + test := func(name string, in any, want string) { if err := convertAssign(&buf, in); err != nil { t.Fatalf("%s: convertAssign = %v", name, err) } @@ -430,11 +430,11 @@ func TestDriverArgs(t *testing.T) { var nilValuerPPtr *Valuer_P var nilStrPtr *string tests := []struct { - args []interface{} + args []any want []driver.NamedValue }{ 0: { - args: []interface{}{Valuer_V("foo")}, + args: []any{Valuer_V("foo")}, want: []driver.NamedValue{ { Ordinal: 1, @@ -443,7 +443,7 @@ func TestDriverArgs(t *testing.T) { }, }, 1: { - args: []interface{}{nilValuerVPtr}, + args: []any{nilValuerVPtr}, want: []driver.NamedValue{ { Ordinal: 1, @@ -452,7 +452,7 @@ func TestDriverArgs(t *testing.T) { }, }, 2: { - args: []interface{}{nilValuerPPtr}, + args: []any{nilValuerPPtr}, want: []driver.NamedValue{ { Ordinal: 1, @@ -461,7 +461,7 @@ func TestDriverArgs(t *testing.T) { }, }, 3: { - args: []interface{}{"plain-str"}, + args: []any{"plain-str"}, want: []driver.NamedValue{ { Ordinal: 1, @@ -470,7 +470,7 @@ func TestDriverArgs(t *testing.T) { }, }, 4: { - args: []interface{}{nilStrPtr}, + args: []any{nilStrPtr}, want: []driver.NamedValue{ { Ordinal: 1, diff --git a/src/database/sql/driver/driver.go b/src/database/sql/driver/driver.go index ea1de5a8fb..5342315d12 100644 --- a/src/database/sql/driver/driver.go +++ b/src/database/sql/driver/driver.go @@ -58,7 +58,7 @@ import ( // in this package. This is used, for example, when a user selects a cursor // such as "select cursor(select * from my_table) from dual". If the Rows // from the select is closed, the cursor Rows will also be closed. -type Value interface{} +type Value any // NamedValue holds both the value name and value. type NamedValue struct { diff --git a/src/database/sql/driver/types.go b/src/database/sql/driver/types.go index 3337c2e0bc..506ce6c2cd 100644 --- a/src/database/sql/driver/types.go +++ b/src/database/sql/driver/types.go @@ -29,7 +29,7 @@ import ( // to a user's type in a scan. type ValueConverter interface { // ConvertValue converts a value to a driver Value. - ConvertValue(v interface{}) (Value, error) + ConvertValue(v any) (Value, error) } // Valuer is the interface providing the Value method. @@ -60,7 +60,7 @@ var _ ValueConverter = boolType{} func (boolType) String() string { return "Bool" } -func (boolType) ConvertValue(src interface{}) (Value, error) { +func (boolType) ConvertValue(src any) (Value, error) { switch s := src.(type) { case bool: return s, nil @@ -105,7 +105,7 @@ type int32Type struct{} var _ ValueConverter = int32Type{} -func (int32Type) ConvertValue(v interface{}) (Value, error) { +func (int32Type) ConvertValue(v any) (Value, error) { rv := reflect.ValueOf(v) switch rv.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: @@ -138,7 +138,7 @@ var String stringType type stringType struct{} -func (stringType) ConvertValue(v interface{}) (Value, error) { +func (stringType) ConvertValue(v any) (Value, error) { switch v.(type) { case string, []byte: return v, nil @@ -152,7 +152,7 @@ type Null struct { Converter ValueConverter } -func (n Null) ConvertValue(v interface{}) (Value, error) { +func (n Null) ConvertValue(v any) (Value, error) { if v == nil { return nil, nil } @@ -165,7 +165,7 @@ type NotNull struct { Converter ValueConverter } -func (n NotNull) ConvertValue(v interface{}) (Value, error) { +func (n NotNull) ConvertValue(v any) (Value, error) { if v == nil { return nil, fmt.Errorf("nil value not allowed") } @@ -173,7 +173,7 @@ func (n NotNull) ConvertValue(v interface{}) (Value, error) { } // IsValue reports whether v is a valid Value parameter type. -func IsValue(v interface{}) bool { +func IsValue(v any) bool { if v == nil { return true } @@ -188,7 +188,7 @@ func IsValue(v interface{}) bool { // IsScanValue is equivalent to IsValue. // It exists for compatibility. -func IsScanValue(v interface{}) bool { +func IsScanValue(v any) bool { return IsValue(v) } @@ -233,7 +233,7 @@ func callValuerValue(vr Valuer) (v Value, err error) { return vr.Value() } -func (defaultConverter) ConvertValue(v interface{}) (Value, error) { +func (defaultConverter) ConvertValue(v any) (Value, error) { if IsValue(v) { return v, nil } diff --git a/src/database/sql/driver/types_test.go b/src/database/sql/driver/types_test.go index 4c2996da85..80e5e05469 100644 --- a/src/database/sql/driver/types_test.go +++ b/src/database/sql/driver/types_test.go @@ -12,8 +12,8 @@ import ( type valueConverterTest struct { c ValueConverter - in interface{} - out interface{} + in any + out any err string } diff --git a/src/database/sql/fakedb_test.go b/src/database/sql/fakedb_test.go index 34e97e012b..8f953f6cb6 100644 --- a/src/database/sql/fakedb_test.go +++ b/src/database/sql/fakedb_test.go @@ -126,7 +126,7 @@ func (t *table) columnIndex(name string) int { } type row struct { - cols []interface{} // must be same size as its table colname + coltype + cols []any // must be same size as its table colname + coltype } type memToucher interface { @@ -198,10 +198,10 @@ type fakeStmt struct { closed bool - colName []string // used by CREATE, INSERT, SELECT (selected columns) - colType []string // used by CREATE - colValue []interface{} // used by INSERT (mix of strings and "?" for bound params) - placeholders int // used by INSERT/SELECT: number of ? params + colName []string // used by CREATE, INSERT, SELECT (selected columns) + colType []string // used by CREATE + colValue []any // used by INSERT (mix of strings and "?" for bound params) + placeholders int // used by INSERT/SELECT: number of ? params whereCol []boundCol // used by SELECT (all placeholders) @@ -504,7 +504,7 @@ func (c *fakeConn) QueryContext(ctx context.Context, query string, args []driver return nil, driver.ErrSkip } -func errf(msg string, args ...interface{}) error { +func errf(msg string, args ...any) error { return errors.New("fakedb: " + fmt.Sprintf(msg, args...)) } @@ -586,7 +586,7 @@ func (c *fakeConn) prepareInsert(ctx context.Context, stmt *fakeStmt, parts []st stmt.colName = append(stmt.colName, column) if !strings.HasPrefix(value, "?") { - var subsetVal interface{} + var subsetVal any // Convert to driver subset type switch ctype { case "string": @@ -829,9 +829,9 @@ func (s *fakeStmt) execInsert(args []driver.NamedValue, doInsert bool) (driver.R t.mu.Lock() defer t.mu.Unlock() - var cols []interface{} + var cols []any if doInsert { - cols = make([]interface{}, len(t.colname)) + cols = make([]any, len(t.colname)) } argPos := 0 for n, colname := range s.colName { @@ -839,7 +839,7 @@ func (s *fakeStmt) execInsert(args []driver.NamedValue, doInsert bool) (driver.R if colidx == -1 { return nil, fmt.Errorf("fakedb: column %q doesn't exist or dropped since prepared statement was created", colname) } - var val interface{} + var val any if strvalue, ok := s.colValue[n].(string); ok && strings.HasPrefix(strvalue, "?") { if strvalue == "?" { val = args[argPos].Value @@ -930,7 +930,7 @@ func (s *fakeStmt) QueryContext(ctx context.Context, args []driver.NamedValue) ( rows: [][]*row{ { { - cols: []interface{}{ + cols: []any{ txStatus, }, }, @@ -980,7 +980,7 @@ func (s *fakeStmt) QueryContext(ctx context.Context, args []driver.NamedValue) ( // lazy hack to avoid sprintf %v on a []byte tcol = string(bs) } - var argValue interface{} + var argValue any if wcol.Placeholder == "?" { argValue = args[wcol.Ordinal-1].Value } else { @@ -996,7 +996,7 @@ func (s *fakeStmt) QueryContext(ctx context.Context, args []driver.NamedValue) ( continue rows } } - mrow := &row{cols: make([]interface{}, len(s.colName))} + mrow := &row{cols: make([]any, len(s.colName))} for seli, name := range s.colName { mrow.cols[seli] = trow.cols[colIdx[name]] } @@ -1174,7 +1174,7 @@ func (rc *rowsCursor) NextResultSet() error { // type fakeDriverString struct{} -func (fakeDriverString) ConvertValue(v interface{}) (driver.Value, error) { +func (fakeDriverString) ConvertValue(v any) (driver.Value, error) { switch c := v.(type) { case string, []byte: return v, nil @@ -1189,7 +1189,7 @@ func (fakeDriverString) ConvertValue(v interface{}) (driver.Value, error) { type anyTypeConverter struct{} -func (anyTypeConverter) ConvertValue(v interface{}) (driver.Value, error) { +func (anyTypeConverter) ConvertValue(v any) (driver.Value, error) { return v, nil } @@ -1260,7 +1260,7 @@ func colTypeToReflectType(typ string) reflect.Type { case "datetime": return reflect.TypeOf(time.Time{}) case "any": - return reflect.TypeOf(new(interface{})).Elem() + return reflect.TypeOf(new(any)).Elem() } panic("invalid fakedb column type of " + typ) } diff --git a/src/database/sql/sql.go b/src/database/sql/sql.go index c5b4f50aa7..d55cee1210 100644 --- a/src/database/sql/sql.go +++ b/src/database/sql/sql.go @@ -92,7 +92,7 @@ type NamedArg struct { // Value is the value of the parameter. // It may be assigned the same value types as the query // arguments. - Value interface{} + Value any } // Named provides a more concise way to create NamedArg values. @@ -107,7 +107,7 @@ type NamedArg struct { // sql.Named("start", startTime), // sql.Named("end", endTime), // ) -func Named(name string, value interface{}) NamedArg { +func Named(name string, value any) NamedArg { // This method exists because the go1compat promise // doesn't guarantee that structs don't grow more fields, // so unkeyed struct literals are a vet error. Thus, we don't @@ -191,7 +191,7 @@ type NullString struct { } // Scan implements the Scanner interface. -func (ns *NullString) Scan(value interface{}) error { +func (ns *NullString) Scan(value any) error { if value == nil { ns.String, ns.Valid = "", false return nil @@ -217,7 +217,7 @@ type NullInt64 struct { } // Scan implements the Scanner interface. -func (n *NullInt64) Scan(value interface{}) error { +func (n *NullInt64) Scan(value any) error { if value == nil { n.Int64, n.Valid = 0, false return nil @@ -243,7 +243,7 @@ type NullInt32 struct { } // Scan implements the Scanner interface. -func (n *NullInt32) Scan(value interface{}) error { +func (n *NullInt32) Scan(value any) error { if value == nil { n.Int32, n.Valid = 0, false return nil @@ -269,7 +269,7 @@ type NullInt16 struct { } // Scan implements the Scanner interface. -func (n *NullInt16) Scan(value interface{}) error { +func (n *NullInt16) Scan(value any) error { if value == nil { n.Int16, n.Valid = 0, false return nil @@ -296,7 +296,7 @@ type NullByte struct { } // Scan implements the Scanner interface. -func (n *NullByte) Scan(value interface{}) error { +func (n *NullByte) Scan(value any) error { if value == nil { n.Byte, n.Valid = 0, false return nil @@ -323,7 +323,7 @@ type NullFloat64 struct { } // Scan implements the Scanner interface. -func (n *NullFloat64) Scan(value interface{}) error { +func (n *NullFloat64) Scan(value any) error { if value == nil { n.Float64, n.Valid = 0, false return nil @@ -349,7 +349,7 @@ type NullBool struct { } // Scan implements the Scanner interface. -func (n *NullBool) Scan(value interface{}) error { +func (n *NullBool) Scan(value any) error { if value == nil { n.Bool, n.Valid = false, false return nil @@ -375,7 +375,7 @@ type NullTime struct { } // Scan implements the Scanner interface. -func (n *NullTime) Scan(value interface{}) error { +func (n *NullTime) Scan(value any) error { if value == nil { n.Time, n.Valid = time.Time{}, false return nil @@ -412,7 +412,7 @@ type Scanner interface { // Reference types such as []byte are only valid until the next call to Scan // and should not be retained. Their underlying memory is owned by the driver. // If retention is necessary, copy their values before the next call to Scan. - Scan(src interface{}) error + Scan(src any) error } // Out may be used to retrieve OUTPUT value parameters from stored procedures. @@ -428,7 +428,7 @@ type Out struct { // Dest is a pointer to the value that will be set to the result of the // stored procedure's OUTPUT parameter. - Dest interface{} + Dest any // In is whether the parameter is an INOUT parameter. If so, the input value to the stored // procedure is the dereferenced value of Dest's pointer, which is then replaced with @@ -680,7 +680,7 @@ func (ds *driverStmt) Close() error { } // depSet is a finalCloser's outstanding dependencies -type depSet map[interface{}]bool // set of true bools +type depSet map[any]bool // set of true bools // The finalCloser interface is used by (*DB).addDep and related // dependency reference counting. @@ -692,13 +692,13 @@ type finalCloser interface { // addDep notes that x now depends on dep, and x's finalClose won't be // called until all of x's dependencies are removed with removeDep. -func (db *DB) addDep(x finalCloser, dep interface{}) { +func (db *DB) addDep(x finalCloser, dep any) { db.mu.Lock() defer db.mu.Unlock() db.addDepLocked(x, dep) } -func (db *DB) addDepLocked(x finalCloser, dep interface{}) { +func (db *DB) addDepLocked(x finalCloser, dep any) { if db.dep == nil { db.dep = make(map[finalCloser]depSet) } @@ -714,14 +714,14 @@ func (db *DB) addDepLocked(x finalCloser, dep interface{}) { // If x still has dependencies, nil is returned. // If x no longer has any dependencies, its finalClose method will be // called and its error value will be returned. -func (db *DB) removeDep(x finalCloser, dep interface{}) error { +func (db *DB) removeDep(x finalCloser, dep any) error { db.mu.Lock() fn := db.removeDepLocked(x, dep) db.mu.Unlock() return fn() } -func (db *DB) removeDepLocked(x finalCloser, dep interface{}) func() error { +func (db *DB) removeDepLocked(x finalCloser, dep any) func() error { xdep, ok := db.dep[x] if !ok { @@ -1627,7 +1627,7 @@ func (db *DB) prepareDC(ctx context.Context, dc *driverConn, release func(error) // ExecContext executes a query without returning any rows. // The args are for any placeholder parameters in the query. -func (db *DB) ExecContext(ctx context.Context, query string, args ...interface{}) (Result, error) { +func (db *DB) ExecContext(ctx context.Context, query string, args ...any) (Result, error) { var res Result var err error var isBadConn bool @@ -1649,11 +1649,11 @@ func (db *DB) ExecContext(ctx context.Context, query string, args ...interface{} // // Exec uses context.Background internally; to specify the context, use // ExecContext. -func (db *DB) Exec(query string, args ...interface{}) (Result, error) { +func (db *DB) Exec(query string, args ...any) (Result, error) { return db.ExecContext(context.Background(), query, args...) } -func (db *DB) exec(ctx context.Context, query string, args []interface{}, strategy connReuseStrategy) (Result, error) { +func (db *DB) exec(ctx context.Context, query string, args []any, strategy connReuseStrategy) (Result, error) { dc, err := db.conn(ctx, strategy) if err != nil { return nil, err @@ -1661,7 +1661,7 @@ func (db *DB) exec(ctx context.Context, query string, args []interface{}, strate return db.execDC(ctx, dc, dc.releaseConn, query, args) } -func (db *DB) execDC(ctx context.Context, dc *driverConn, release func(error), query string, args []interface{}) (res Result, err error) { +func (db *DB) execDC(ctx context.Context, dc *driverConn, release func(error), query string, args []any) (res Result, err error) { defer func() { release(err) }() @@ -1702,7 +1702,7 @@ func (db *DB) execDC(ctx context.Context, dc *driverConn, release func(error), q // QueryContext executes a query that returns rows, typically a SELECT. // The args are for any placeholder parameters in the query. -func (db *DB) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error) { +func (db *DB) QueryContext(ctx context.Context, query string, args ...any) (*Rows, error) { var rows *Rows var err error var isBadConn bool @@ -1724,11 +1724,11 @@ func (db *DB) QueryContext(ctx context.Context, query string, args ...interface{ // // Query uses context.Background internally; to specify the context, use // QueryContext. -func (db *DB) Query(query string, args ...interface{}) (*Rows, error) { +func (db *DB) Query(query string, args ...any) (*Rows, error) { return db.QueryContext(context.Background(), query, args...) } -func (db *DB) query(ctx context.Context, query string, args []interface{}, strategy connReuseStrategy) (*Rows, error) { +func (db *DB) query(ctx context.Context, query string, args []any, strategy connReuseStrategy) (*Rows, error) { dc, err := db.conn(ctx, strategy) if err != nil { return nil, err @@ -1741,7 +1741,7 @@ func (db *DB) query(ctx context.Context, query string, args []interface{}, strat // The connection gets released by the releaseConn function. // The ctx context is from a query method and the txctx context is from an // optional transaction context. -func (db *DB) queryDC(ctx, txctx context.Context, dc *driverConn, releaseConn func(error), query string, args []interface{}) (*Rows, error) { +func (db *DB) queryDC(ctx, txctx context.Context, dc *driverConn, releaseConn func(error), query string, args []any) (*Rows, error) { queryerCtx, ok := dc.ci.(driver.QueryerContext) var queryer driver.Queryer if !ok { @@ -1811,7 +1811,7 @@ func (db *DB) queryDC(ctx, txctx context.Context, dc *driverConn, releaseConn fu // If the query selects no rows, the *Row's Scan will return ErrNoRows. // Otherwise, the *Row's Scan scans the first selected row and discards // the rest. -func (db *DB) QueryRowContext(ctx context.Context, query string, args ...interface{}) *Row { +func (db *DB) QueryRowContext(ctx context.Context, query string, args ...any) *Row { rows, err := db.QueryContext(ctx, query, args...) return &Row{rows: rows, err: err} } @@ -1825,7 +1825,7 @@ func (db *DB) QueryRowContext(ctx context.Context, query string, args ...interfa // // QueryRow uses context.Background internally; to specify the context, use // QueryRowContext. -func (db *DB) QueryRow(query string, args ...interface{}) *Row { +func (db *DB) QueryRow(query string, args ...any) *Row { return db.QueryRowContext(context.Background(), query, args...) } @@ -1995,7 +1995,7 @@ func (c *Conn) PingContext(ctx context.Context) error { // ExecContext executes a query without returning any rows. // The args are for any placeholder parameters in the query. -func (c *Conn) ExecContext(ctx context.Context, query string, args ...interface{}) (Result, error) { +func (c *Conn) ExecContext(ctx context.Context, query string, args ...any) (Result, error) { dc, release, err := c.grabConn(ctx) if err != nil { return nil, err @@ -2005,7 +2005,7 @@ func (c *Conn) ExecContext(ctx context.Context, query string, args ...interface{ // QueryContext executes a query that returns rows, typically a SELECT. // The args are for any placeholder parameters in the query. -func (c *Conn) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error) { +func (c *Conn) QueryContext(ctx context.Context, query string, args ...any) (*Rows, error) { dc, release, err := c.grabConn(ctx) if err != nil { return nil, err @@ -2019,7 +2019,7 @@ func (c *Conn) QueryContext(ctx context.Context, query string, args ...interface // If the query selects no rows, the *Row's Scan will return ErrNoRows. // Otherwise, the *Row's Scan scans the first selected row and discards // the rest. -func (c *Conn) QueryRowContext(ctx context.Context, query string, args ...interface{}) *Row { +func (c *Conn) QueryRowContext(ctx context.Context, query string, args ...any) *Row { rows, err := c.QueryContext(ctx, query, args...) return &Row{rows: rows, err: err} } @@ -2045,7 +2045,7 @@ func (c *Conn) PrepareContext(ctx context.Context, query string) (*Stmt, error) // // Once f returns and err is not driver.ErrBadConn, the Conn will continue to be usable // until Conn.Close is called. -func (c *Conn) Raw(f func(driverConn interface{}) error) (err error) { +func (c *Conn) Raw(f func(driverConn any) error) (err error) { var dc *driverConn var release releaseConn @@ -2483,7 +2483,7 @@ func (tx *Tx) Stmt(stmt *Stmt) *Stmt { // ExecContext executes a query that doesn't return rows. // For example: an INSERT and UPDATE. -func (tx *Tx) ExecContext(ctx context.Context, query string, args ...interface{}) (Result, error) { +func (tx *Tx) ExecContext(ctx context.Context, query string, args ...any) (Result, error) { dc, release, err := tx.grabConn(ctx) if err != nil { return nil, err @@ -2496,12 +2496,12 @@ func (tx *Tx) ExecContext(ctx context.Context, query string, args ...interface{} // // Exec uses context.Background internally; to specify the context, use // ExecContext. -func (tx *Tx) Exec(query string, args ...interface{}) (Result, error) { +func (tx *Tx) Exec(query string, args ...any) (Result, error) { return tx.ExecContext(context.Background(), query, args...) } // QueryContext executes a query that returns rows, typically a SELECT. -func (tx *Tx) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error) { +func (tx *Tx) QueryContext(ctx context.Context, query string, args ...any) (*Rows, error) { dc, release, err := tx.grabConn(ctx) if err != nil { return nil, err @@ -2514,7 +2514,7 @@ func (tx *Tx) QueryContext(ctx context.Context, query string, args ...interface{ // // Query uses context.Background internally; to specify the context, use // QueryContext. -func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error) { +func (tx *Tx) Query(query string, args ...any) (*Rows, error) { return tx.QueryContext(context.Background(), query, args...) } @@ -2524,7 +2524,7 @@ func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error) { // If the query selects no rows, the *Row's Scan will return ErrNoRows. // Otherwise, the *Row's Scan scans the first selected row and discards // the rest. -func (tx *Tx) QueryRowContext(ctx context.Context, query string, args ...interface{}) *Row { +func (tx *Tx) QueryRowContext(ctx context.Context, query string, args ...any) *Row { rows, err := tx.QueryContext(ctx, query, args...) return &Row{rows: rows, err: err} } @@ -2538,7 +2538,7 @@ func (tx *Tx) QueryRowContext(ctx context.Context, query string, args ...interfa // // QueryRow uses context.Background internally; to specify the context, use // QueryRowContext. -func (tx *Tx) QueryRow(query string, args ...interface{}) *Row { +func (tx *Tx) QueryRow(query string, args ...any) *Row { return tx.QueryRowContext(context.Background(), query, args...) } @@ -2615,7 +2615,7 @@ type Stmt struct { // ExecContext executes a prepared statement with the given arguments and // returns a Result summarizing the effect of the statement. -func (s *Stmt) ExecContext(ctx context.Context, args ...interface{}) (Result, error) { +func (s *Stmt) ExecContext(ctx context.Context, args ...any) (Result, error) { s.closemu.RLock() defer s.closemu.RUnlock() @@ -2647,11 +2647,11 @@ func (s *Stmt) ExecContext(ctx context.Context, args ...interface{}) (Result, er // // Exec uses context.Background internally; to specify the context, use // ExecContext. -func (s *Stmt) Exec(args ...interface{}) (Result, error) { +func (s *Stmt) Exec(args ...any) (Result, error) { return s.ExecContext(context.Background(), args...) } -func resultFromStatement(ctx context.Context, ci driver.Conn, ds *driverStmt, args ...interface{}) (Result, error) { +func resultFromStatement(ctx context.Context, ci driver.Conn, ds *driverStmt, args ...any) (Result, error) { ds.Lock() defer ds.Unlock() @@ -2763,7 +2763,7 @@ func (s *Stmt) prepareOnConnLocked(ctx context.Context, dc *driverConn) (*driver // QueryContext executes a prepared query statement with the given arguments // and returns the query results as a *Rows. -func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, error) { +func (s *Stmt) QueryContext(ctx context.Context, args ...any) (*Rows, error) { s.closemu.RLock() defer s.closemu.RUnlock() @@ -2821,11 +2821,11 @@ func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, er // // Query uses context.Background internally; to specify the context, use // QueryContext. -func (s *Stmt) Query(args ...interface{}) (*Rows, error) { +func (s *Stmt) Query(args ...any) (*Rows, error) { return s.QueryContext(context.Background(), args...) } -func rowsiFromStatement(ctx context.Context, ci driver.Conn, ds *driverStmt, args ...interface{}) (driver.Rows, error) { +func rowsiFromStatement(ctx context.Context, ci driver.Conn, ds *driverStmt, args ...any) (driver.Rows, error) { ds.Lock() defer ds.Unlock() dargs, err := driverArgsConnLocked(ci, ds, args) @@ -2841,7 +2841,7 @@ func rowsiFromStatement(ctx context.Context, ci driver.Conn, ds *driverStmt, arg // If the query selects no rows, the *Row's Scan will return ErrNoRows. // Otherwise, the *Row's Scan scans the first selected row and discards // the rest. -func (s *Stmt) QueryRowContext(ctx context.Context, args ...interface{}) *Row { +func (s *Stmt) QueryRowContext(ctx context.Context, args ...any) *Row { rows, err := s.QueryContext(ctx, args...) if err != nil { return &Row{err: err} @@ -2863,7 +2863,7 @@ func (s *Stmt) QueryRowContext(ctx context.Context, args ...interface{}) *Row { // // QueryRow uses context.Background internally; to specify the context, use // QueryRowContext. -func (s *Stmt) QueryRow(args ...interface{}) *Row { +func (s *Stmt) QueryRow(args ...any) *Row { return s.QueryRowContext(context.Background(), args...) } @@ -3185,7 +3185,7 @@ func rowsColumnInfoSetupConnLocked(rowsi driver.Rows) []*ColumnType { if prop, ok := rowsi.(driver.RowsColumnTypeScanType); ok { ci.scanType = prop.ColumnTypeScanType(i) } else { - ci.scanType = reflect.TypeOf(new(interface{})).Elem() + ci.scanType = reflect.TypeOf(new(any)).Elem() } if prop, ok := rowsi.(driver.RowsColumnTypeDatabaseTypeName); ok { ci.databaseType = prop.ColumnTypeDatabaseTypeName(i) @@ -3263,7 +3263,7 @@ func rowsColumnInfoSetupConnLocked(rowsi driver.Rows) []*ColumnType { // // If any of the first arguments implementing Scanner returns an error, // that error will be wrapped in the returned error -func (rs *Rows) Scan(dest ...interface{}) error { +func (rs *Rows) Scan(dest ...any) error { rs.closemu.RLock() if rs.lasterr != nil && rs.lasterr != io.EOF { @@ -3346,7 +3346,7 @@ type Row struct { // If more than one row matches the query, // Scan uses the first row and discards the rest. If no row matches // the query, Scan returns ErrNoRows. -func (r *Row) Scan(dest ...interface{}) error { +func (r *Row) Scan(dest ...any) error { if r.err != nil { return r.err } diff --git a/src/database/sql/sql_test.go b/src/database/sql/sql_test.go index b887b40d71..1bb9afc407 100644 --- a/src/database/sql/sql_test.go +++ b/src/database/sql/sql_test.go @@ -135,7 +135,7 @@ func TestDriverPanic(t *testing.T) { exec(t, db, "WIPE") // check not deadlocked } -func exec(t testing.TB, db *DB, query string, args ...interface{}) { +func exec(t testing.TB, db *DB, query string, args ...any) { t.Helper() _, err := db.Exec(query, args...) if err != nil { @@ -743,7 +743,7 @@ func TestRowsColumnTypes(t *testing.T) { } types[i] = st } - values := make([]interface{}, len(tt)) + values := make([]any, len(tt)) for i := range values { values[i] = reflect.New(types[i]).Interface() } @@ -1006,23 +1006,23 @@ func TestExec(t *testing.T) { defer stmt.Close() type execTest struct { - args []interface{} + args []any wantErr string } execTests := []execTest{ // Okay: - {[]interface{}{"Brad", 31}, ""}, - {[]interface{}{"Brad", int64(31)}, ""}, - {[]interface{}{"Bob", "32"}, ""}, - {[]interface{}{7, 9}, ""}, + {[]any{"Brad", 31}, ""}, + {[]any{"Brad", int64(31)}, ""}, + {[]any{"Bob", "32"}, ""}, + {[]any{7, 9}, ""}, // Invalid conversions: - {[]interface{}{"Brad", int64(0xFFFFFFFF)}, "sql: converting argument $2 type: sql/driver: value 4294967295 overflows int32"}, - {[]interface{}{"Brad", "strconv fail"}, `sql: converting argument $2 type: sql/driver: value "strconv fail" can't be converted to int32`}, + {[]any{"Brad", int64(0xFFFFFFFF)}, "sql: converting argument $2 type: sql/driver: value 4294967295 overflows int32"}, + {[]any{"Brad", "strconv fail"}, `sql: converting argument $2 type: sql/driver: value "strconv fail" can't be converted to int32`}, // Wrong number of args: - {[]interface{}{}, "sql: expected 2 arguments, got 0"}, - {[]interface{}{1, 2, 3}, "sql: expected 2 arguments, got 3"}, + {[]any{}, "sql: expected 2 arguments, got 0"}, + {[]any{1, 2, 3}, "sql: expected 2 arguments, got 3"}, } for n, et := range execTests { _, err := stmt.Exec(et.args...) @@ -1409,7 +1409,7 @@ func TestConnRaw(t *testing.T) { defer conn.Close() sawFunc := false - err = conn.Raw(func(dc interface{}) error { + err = conn.Raw(func(dc any) error { sawFunc = true if _, ok := dc.(*fakeConn); !ok { return fmt.Errorf("got %T want *fakeConn", dc) @@ -1436,7 +1436,7 @@ func TestConnRaw(t *testing.T) { t.Fatal("expected connection to be closed after panic") } }() - err = conn.Raw(func(dc interface{}) error { + err = conn.Raw(func(dc any) error { panic("Conn.Raw panic should return an error") }) t.Fatal("expected panic from Raw func") @@ -1495,7 +1495,7 @@ func TestInvalidNilValues(t *testing.T) { tests := []struct { name string - input interface{} + input any expectedError string }{ { @@ -1593,7 +1593,7 @@ func TestConnIsValid(t *testing.T) { t.Fatal(err) } - err = c.Raw(func(raw interface{}) error { + err = c.Raw(func(raw any) error { dc := raw.(*fakeConn) dc.stickyBad = true return nil @@ -1772,9 +1772,9 @@ func TestIssue6651(t *testing.T) { } type nullTestRow struct { - nullParam interface{} - notNullParam interface{} - scanNullVal interface{} + nullParam any + notNullParam any + scanNullVal any } type nullTestSpec struct { @@ -4129,7 +4129,7 @@ func TestNamedValueChecker(t *testing.T) { t.Fatal("select", err) } - list := []struct{ got, want interface{} }{ + list := []struct{ got, want any }{ {o1, "from-server"}, {dec1, decimalInt{123}}, {str1, "hello"}, @@ -4318,7 +4318,7 @@ type alwaysErrScanner struct{} var errTestScanWrap = errors.New("errTestScanWrap") -func (alwaysErrScanner) Scan(interface{}) error { +func (alwaysErrScanner) Scan(any) error { return errTestScanWrap } diff --git a/src/debug/dwarf/entry.go b/src/debug/dwarf/entry.go index 25a3b5beec..cbdc838a12 100644 --- a/src/debug/dwarf/entry.go +++ b/src/debug/dwarf/entry.go @@ -261,7 +261,7 @@ type Entry struct { // ClassUnknown. type Field struct { Attr Attr - Val interface{} + Val any Class Class } @@ -382,7 +382,7 @@ func (i Class) GoString() string { // the check that the value has the expected dynamic type, as in: // v, ok := e.Val(AttrSibling).(int64) // -func (e *Entry) Val(a Attr) interface{} { +func (e *Entry) Val(a Attr) any { if f := e.AttrField(a); f != nil { return f.Val } @@ -501,7 +501,7 @@ func (b *buf) entry(cu *Entry, atab abbrevTable, ubase Offset, vers int) *Entry fmt = format(b.uint()) e.Field[i].Class = formToClass(fmt, a.field[i].attr, vers, b) } - var val interface{} + var val any switch fmt { default: b.error("unknown entry attr format 0x" + strconv.FormatInt(int64(fmt), 16)) diff --git a/src/debug/dwarf/entry_test.go b/src/debug/dwarf/entry_test.go index 1f41d742ea..8c6ca7259e 100644 --- a/src/debug/dwarf/entry_test.go +++ b/src/debug/dwarf/entry_test.go @@ -277,7 +277,7 @@ func TestUnitIteration(t *testing.T) { for _, file := range files { t.Run(file, func(t *testing.T) { d := elfData(t, file) - var units [2][]interface{} + var units [2][]any for method := range units { for r := d.Reader(); ; { ent, err := r.Next() diff --git a/src/debug/elf/elf_test.go b/src/debug/elf/elf_test.go index f8985a8992..a61b491090 100644 --- a/src/debug/elf/elf_test.go +++ b/src/debug/elf/elf_test.go @@ -10,7 +10,7 @@ import ( ) type nameTest struct { - val interface{} + val any str string } diff --git a/src/debug/elf/file.go b/src/debug/elf/file.go index e265796ddc..eefcaab8d6 100644 --- a/src/debug/elf/file.go +++ b/src/debug/elf/file.go @@ -185,7 +185,7 @@ type Symbol struct { type FormatError struct { off int64 msg string - val interface{} + val any } func (e *FormatError) Error() string { diff --git a/src/debug/gosym/symtab.go b/src/debug/gosym/symtab.go index 72490dca8a..4e63f1cdf7 100644 --- a/src/debug/gosym/symtab.go +++ b/src/debug/gosym/symtab.go @@ -751,7 +751,7 @@ func (e *UnknownLineError) Error() string { type DecodingError struct { off int msg string - val interface{} + val any } func (e *DecodingError) Error() string { diff --git a/src/debug/macho/file.go b/src/debug/macho/file.go index cdc500e476..b57dba8496 100644 --- a/src/debug/macho/file.go +++ b/src/debug/macho/file.go @@ -184,7 +184,7 @@ type Symbol struct { type FormatError struct { off int64 msg string - val interface{} + val any } func (e *FormatError) Error() string { diff --git a/src/debug/macho/file_test.go b/src/debug/macho/file_test.go index 9beeb80dd2..313c376c54 100644 --- a/src/debug/macho/file_test.go +++ b/src/debug/macho/file_test.go @@ -15,7 +15,7 @@ import ( type fileTest struct { file string hdr FileHeader - loads []interface{} + loads []any sections []*SectionHeader relocations map[string][]Reloc } @@ -24,7 +24,7 @@ var fileTests = []fileTest{ { "testdata/gcc-386-darwin-exec.base64", FileHeader{0xfeedface, Cpu386, 0x3, 0x2, 0xc, 0x3c0, 0x85}, - []interface{}{ + []any{ &SegmentHeader{LoadCmdSegment, 0x38, "__PAGEZERO", 0x0, 0x1000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, &SegmentHeader{LoadCmdSegment, 0xc0, "__TEXT", 0x1000, 0x1000, 0x0, 0x1000, 0x7, 0x5, 0x2, 0x0}, &SegmentHeader{LoadCmdSegment, 0xc0, "__DATA", 0x2000, 0x1000, 0x1000, 0x1000, 0x7, 0x3, 0x2, 0x0}, @@ -50,7 +50,7 @@ var fileTests = []fileTest{ { "testdata/gcc-amd64-darwin-exec.base64", FileHeader{0xfeedfacf, CpuAmd64, 0x80000003, 0x2, 0xb, 0x568, 0x85}, - []interface{}{ + []any{ &SegmentHeader{LoadCmdSegment64, 0x48, "__PAGEZERO", 0x0, 0x100000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, &SegmentHeader{LoadCmdSegment64, 0x1d8, "__TEXT", 0x100000000, 0x1000, 0x0, 0x1000, 0x7, 0x5, 0x5, 0x0}, &SegmentHeader{LoadCmdSegment64, 0x138, "__DATA", 0x100001000, 0x1000, 0x1000, 0x1000, 0x7, 0x3, 0x3, 0x0}, @@ -78,7 +78,7 @@ var fileTests = []fileTest{ { "testdata/gcc-amd64-darwin-exec-debug.base64", FileHeader{0xfeedfacf, CpuAmd64, 0x80000003, 0xa, 0x4, 0x5a0, 0}, - []interface{}{ + []any{ nil, // LC_UUID &SegmentHeader{LoadCmdSegment64, 0x1d8, "__TEXT", 0x100000000, 0x1000, 0x0, 0x0, 0x7, 0x5, 0x5, 0x0}, &SegmentHeader{LoadCmdSegment64, 0x138, "__DATA", 0x100001000, 0x1000, 0x0, 0x0, 0x7, 0x3, 0x3, 0x0}, @@ -106,7 +106,7 @@ var fileTests = []fileTest{ { "testdata/clang-386-darwin-exec-with-rpath.base64", FileHeader{0xfeedface, Cpu386, 0x3, 0x2, 0x10, 0x42c, 0x1200085}, - []interface{}{ + []any{ nil, // LC_SEGMENT nil, // LC_SEGMENT nil, // LC_SEGMENT @@ -130,7 +130,7 @@ var fileTests = []fileTest{ { "testdata/clang-amd64-darwin-exec-with-rpath.base64", FileHeader{0xfeedfacf, CpuAmd64, 0x80000003, 0x2, 0x10, 0x4c8, 0x200085}, - []interface{}{ + []any{ nil, // LC_SEGMENT nil, // LC_SEGMENT nil, // LC_SEGMENT diff --git a/src/debug/pe/file.go b/src/debug/pe/file.go index ab00a48f5c..aa0955a133 100644 --- a/src/debug/pe/file.go +++ b/src/debug/pe/file.go @@ -22,7 +22,7 @@ const seekStart = 0 // A File represents an open PE file. type File struct { FileHeader - OptionalHeader interface{} // of type *OptionalHeader32 or *OptionalHeader64 + OptionalHeader any // of type *OptionalHeader32 or *OptionalHeader64 Sections []*Section Symbols []*Symbol // COFF symbols with auxiliary symbol records removed COFFSymbols []COFFSymbol // all COFF symbols (including auxiliary symbol records) @@ -452,7 +452,7 @@ func (e *FormatError) Error() string { // and its size as seen in the file header. // It parses the given size of bytes and returns optional header. It infers whether the // bytes being parsed refer to 32 bit or 64 bit version of optional header. -func readOptionalHeader(r io.ReadSeeker, sz uint16) (interface{}, error) { +func readOptionalHeader(r io.ReadSeeker, sz uint16) (any, error) { // If optional header size is 0, return empty optional header. if sz == 0 { return nil, nil @@ -473,7 +473,7 @@ func readOptionalHeader(r io.ReadSeeker, sz uint16) (interface{}, error) { // read reads from io.ReadSeeke, r, into data. var err error - read := func(data interface{}) bool { + read := func(data any) bool { err = binary.Read(r, binary.LittleEndian, data) return err == nil } diff --git a/src/debug/pe/file_test.go b/src/debug/pe/file_test.go index 8964b4f847..5368e08ad7 100644 --- a/src/debug/pe/file_test.go +++ b/src/debug/pe/file_test.go @@ -22,7 +22,7 @@ import ( type fileTest struct { file string hdr FileHeader - opthdr interface{} + opthdr any sections []*SectionHeader symbols []*Symbol hasNoDwarfInfo bool @@ -250,7 +250,7 @@ var fileTests = []fileTest{ }, } -func isOptHdrEq(a, b interface{}) bool { +func isOptHdrEq(a, b any) bool { switch va := a.(type) { case *OptionalHeader32: vb, ok := b.(*OptionalHeader32) diff --git a/src/debug/plan9obj/file.go b/src/debug/plan9obj/file.go index c054635148..0c33fa10bb 100644 --- a/src/debug/plan9obj/file.go +++ b/src/debug/plan9obj/file.go @@ -82,7 +82,7 @@ type Sym struct { type formatError struct { off int msg string - val interface{} + val any } func (e *formatError) Error() string { diff --git a/src/embed/embed.go b/src/embed/embed.go index 24c3a89e9b..9737ccdf6b 100644 --- a/src/embed/embed.go +++ b/src/embed/embed.go @@ -232,7 +232,7 @@ func (f *file) Name() string { _, elem, _ := split(f.name); return func (f *file) Size() int64 { return int64(len(f.data)) } func (f *file) ModTime() time.Time { return time.Time{} } func (f *file) IsDir() bool { _, _, isDir := split(f.name); return isDir } -func (f *file) Sys() interface{} { return nil } +func (f *file) Sys() any { return nil } func (f *file) Type() fs.FileMode { return f.Mode().Type() } func (f *file) Info() (fs.FileInfo, error) { return f, nil } diff --git a/src/embed/internal/embedtest/embed_test.go b/src/embed/internal/embedtest/embed_test.go index 1337e421bd..cbd58ee846 100644 --- a/src/embed/internal/embedtest/embed_test.go +++ b/src/embed/internal/embedtest/embed_test.go @@ -162,7 +162,7 @@ func TestAliases(t *testing.T) { if e != nil { t.Fatal("ReadFile:", e) } - check := func(g interface{}) { + check := func(g any) { got := reflect.ValueOf(g) for i := 0; i < got.Len(); i++ { if byte(got.Index(i).Uint()) != want[i] { diff --git a/src/encoding/ascii85/ascii85_test.go b/src/encoding/ascii85/ascii85_test.go index c637103942..9e6b34e997 100644 --- a/src/encoding/ascii85/ascii85_test.go +++ b/src/encoding/ascii85/ascii85_test.go @@ -42,7 +42,7 @@ var pairs = []testpair{ }, } -func testEqual(t *testing.T, msg string, args ...interface{}) bool { +func testEqual(t *testing.T, msg string, args ...any) bool { t.Helper() if args[len(args)-2] != args[len(args)-1] { t.Errorf(msg, args...) diff --git a/src/encoding/asn1/asn1.go b/src/encoding/asn1/asn1.go index d0e1c6b176..cad1d7b08f 100644 --- a/src/encoding/asn1/asn1.go +++ b/src/encoding/asn1/asn1.go @@ -695,7 +695,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam err = SyntaxError{"data truncated"} return } - var result interface{} + var result any if !t.isCompound && t.class == ClassUniversal { innerBytes := bytes[offset : offset+t.length] switch t.tag { @@ -1086,7 +1086,7 @@ func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) { // // Other ASN.1 types are not supported; if it encounters them, // Unmarshal returns a parse error. -func Unmarshal(b []byte, val interface{}) (rest []byte, err error) { +func Unmarshal(b []byte, val any) (rest []byte, err error) { return UnmarshalWithParams(b, val, "") } @@ -1109,7 +1109,7 @@ func (e *invalidUnmarshalError) Error() string { // UnmarshalWithParams allows field parameters to be specified for the // top-level element. The form of the params is the same as the field tags. -func UnmarshalWithParams(b []byte, val interface{}, params string) (rest []byte, err error) { +func UnmarshalWithParams(b []byte, val any, params string) (rest []byte, err error) { v := reflect.ValueOf(val) if v.Kind() != reflect.Pointer || v.IsNil() { return nil, &invalidUnmarshalError{reflect.TypeOf(val)} diff --git a/src/encoding/asn1/asn1_test.go b/src/encoding/asn1/asn1_test.go index 8985538468..b1e05b96ae 100644 --- a/src/encoding/asn1/asn1_test.go +++ b/src/encoding/asn1/asn1_test.go @@ -479,7 +479,7 @@ type TestSet struct { var unmarshalTestData = []struct { in []byte - out interface{} + out any }{ {[]byte{0x02, 0x01, 0x42}, newInt(0x42)}, {[]byte{0x05, 0x00}, &RawValue{0, 5, false, []byte{}, []byte{0x05, 0x00}}}, @@ -521,7 +521,7 @@ func TestUnmarshal(t *testing.T) { func TestUnmarshalWithNilOrNonPointer(t *testing.T) { tests := []struct { b []byte - v interface{} + v any want string }{ {b: []byte{0x05, 0x00}, v: nil, want: "asn1: Unmarshal recipient value is nil"}, @@ -567,7 +567,7 @@ type RelativeDistinguishedNameSET []AttributeTypeAndValue type AttributeTypeAndValue struct { Type ObjectIdentifier - Value interface{} + Value any } type Validity struct { @@ -998,9 +998,9 @@ func TestUnmarshalInvalidUTF8(t *testing.T) { } func TestMarshalNilValue(t *testing.T) { - nilValueTestData := []interface{}{ + nilValueTestData := []any{ nil, - struct{ V interface{} }{}, + struct{ V any }{}, } for i, test := range nilValueTestData { if _, err := Marshal(test); err == nil { diff --git a/src/encoding/asn1/marshal.go b/src/encoding/asn1/marshal.go index 5b4d786d49..c243349175 100644 --- a/src/encoding/asn1/marshal.go +++ b/src/encoding/asn1/marshal.go @@ -730,13 +730,13 @@ func makeField(v reflect.Value, params fieldParameters) (e encoder, err error) { // utf8: causes strings to be marshaled as ASN.1, UTF8String values // utc: causes time.Time to be marshaled as ASN.1, UTCTime values // generalized: causes time.Time to be marshaled as ASN.1, GeneralizedTime values -func Marshal(val interface{}) ([]byte, error) { +func Marshal(val any) ([]byte, error) { return MarshalWithParams(val, "") } // MarshalWithParams allows field parameters to be specified for the // top-level element. The form of the params is the same as the field tags. -func MarshalWithParams(val interface{}, params string) ([]byte, error) { +func MarshalWithParams(val any, params string) ([]byte, error) { e, err := makeField(reflect.ValueOf(val), parseFieldParameters(params)) if err != nil { return nil, err diff --git a/src/encoding/asn1/marshal_test.go b/src/encoding/asn1/marshal_test.go index f0217ba8a5..d9c3cf48fa 100644 --- a/src/encoding/asn1/marshal_test.go +++ b/src/encoding/asn1/marshal_test.go @@ -97,7 +97,7 @@ type testSET []int var PST = time.FixedZone("PST", -8*60*60) type marshalTest struct { - in interface{} + in any out string // hex encoded } @@ -196,7 +196,7 @@ func TestMarshal(t *testing.T) { } type marshalWithParamsTest struct { - in interface{} + in any params string out string // hex encoded } @@ -222,7 +222,7 @@ func TestMarshalWithParams(t *testing.T) { } type marshalErrTest struct { - in interface{} + in any err string } @@ -276,7 +276,7 @@ func TestMarshalOID(t *testing.T) { func TestIssue11130(t *testing.T) { data := []byte("\x06\x010") // == \x06\x01\x30 == OID = 0 (the figure) - var v interface{} + var v any // v has Zero value here and Elem() would panic _, err := Unmarshal(data, &v) if err != nil { @@ -299,7 +299,7 @@ func TestIssue11130(t *testing.T) { return } - var v1 interface{} + var v1 any _, err = Unmarshal(data1, &v1) if err != nil { t.Errorf("%v", err) @@ -382,7 +382,7 @@ func BenchmarkUnmarshal(b *testing.B) { type testCase struct { in []byte - out interface{} + out any } var testData []testCase for _, test := range unmarshalTestData { diff --git a/src/encoding/base32/base32_test.go b/src/encoding/base32/base32_test.go index 8fb22b9078..dbd2b613b4 100644 --- a/src/encoding/base32/base32_test.go +++ b/src/encoding/base32/base32_test.go @@ -42,7 +42,7 @@ var bigtest = testpair{ "KR3WC4ZAMJZGS3DMNFTSYIDBNZSCA5DIMUQHG3DJORUHSIDUN53GK4Y=", } -func testEqual(t *testing.T, msg string, args ...interface{}) bool { +func testEqual(t *testing.T, msg string, args ...any) bool { t.Helper() if args[len(args)-2] != args[len(args)-1] { t.Errorf(msg, args...) diff --git a/src/encoding/base64/base64_test.go b/src/encoding/base64/base64_test.go index 51047402bd..57256a3846 100644 --- a/src/encoding/base64/base64_test.go +++ b/src/encoding/base64/base64_test.go @@ -98,7 +98,7 @@ var bigtest = testpair{ "VHdhcyBicmlsbGlnLCBhbmQgdGhlIHNsaXRoeSB0b3Zlcw==", } -func testEqual(t *testing.T, msg string, args ...interface{}) bool { +func testEqual(t *testing.T, msg string, args ...any) bool { t.Helper() if args[len(args)-2] != args[len(args)-1] { t.Errorf(msg, args...) diff --git a/src/encoding/binary/binary.go b/src/encoding/binary/binary.go index 52417a7933..ee933461ee 100644 --- a/src/encoding/binary/binary.go +++ b/src/encoding/binary/binary.go @@ -159,7 +159,7 @@ func (bigEndian) GoString() string { return "binary.BigEndian" } // The error is EOF only if no bytes were read. // If an EOF happens after reading some but not all the bytes, // Read returns ErrUnexpectedEOF. -func Read(r io.Reader, order ByteOrder, data interface{}) error { +func Read(r io.Reader, order ByteOrder, data any) error { // Fast path for basic types and slices. if n := intDataSize(data); n != 0 { bs := make([]byte, n) @@ -268,7 +268,7 @@ func Read(r io.Reader, order ByteOrder, data interface{}) error { // and read from successive fields of the data. // When writing structs, zero values are written for fields // with blank (_) field names. -func Write(w io.Writer, order ByteOrder, data interface{}) error { +func Write(w io.Writer, order ByteOrder, data any) error { // Fast path for basic types and slices. if n := intDataSize(data); n != 0 { bs := make([]byte, n) @@ -392,7 +392,7 @@ func Write(w io.Writer, order ByteOrder, data interface{}) error { // Size returns how many bytes Write would generate to encode the value v, which // must be a fixed-size value or a slice of fixed-size values, or a pointer to such data. // If v is neither of these, Size returns -1. -func Size(v interface{}) int { +func Size(v any) int { return dataSize(reflect.Indirect(reflect.ValueOf(v))) } @@ -696,7 +696,7 @@ func (e *encoder) skip(v reflect.Value) { // intDataSize returns the size of the data required to represent the data when encoded. // It returns zero if the type cannot be implemented by the fast path in Read or Write. -func intDataSize(data interface{}) int { +func intDataSize(data any) int { switch data := data.(type) { case bool, int8, uint8, *bool, *int8, *uint8: return 1 diff --git a/src/encoding/binary/binary_test.go b/src/encoding/binary/binary_test.go index 83af89e8a7..9e1b5f12db 100644 --- a/src/encoding/binary/binary_test.go +++ b/src/encoding/binary/binary_test.go @@ -113,7 +113,7 @@ var src = []byte{1, 2, 3, 4, 5, 6, 7, 8} var res = []int32{0x01020304, 0x05060708} var putbuf = []byte{0, 0, 0, 0, 0, 0, 0, 0} -func checkResult(t *testing.T, dir string, order ByteOrder, err error, have, want interface{}) { +func checkResult(t *testing.T, dir string, order ByteOrder, err error, have, want any) { if err != nil { t.Errorf("%v %v: %v", dir, order, err) return @@ -123,13 +123,13 @@ func checkResult(t *testing.T, dir string, order ByteOrder, err error, have, wan } } -func testRead(t *testing.T, order ByteOrder, b []byte, s1 interface{}) { +func testRead(t *testing.T, order ByteOrder, b []byte, s1 any) { var s2 Struct err := Read(bytes.NewReader(b), order, &s2) checkResult(t, "Read", order, err, s2, s1) } -func testWrite(t *testing.T, order ByteOrder, b []byte, s1 interface{}) { +func testWrite(t *testing.T, order ByteOrder, b []byte, s1 any) { buf := new(bytes.Buffer) err := Write(buf, order, s1) checkResult(t, "Write", order, err, buf.Bytes(), b) @@ -175,7 +175,7 @@ func TestReadBoolSlice(t *testing.T) { } // Addresses of arrays are easier to manipulate with reflection than are slices. -var intArrays = []interface{}{ +var intArrays = []any{ &[100]int8{}, &[100]int16{}, &[100]int32{}, @@ -304,7 +304,7 @@ func TestSizeStructCache(t *testing.T) { count := func() int { var i int - structSize.Range(func(_, _ interface{}) bool { + structSize.Range(func(_, _ any) bool { i++ return true }) @@ -329,7 +329,7 @@ func TestSizeStructCache(t *testing.T) { } testcases := []struct { - val interface{} + val any want int }{ {new(foo), 1}, @@ -376,7 +376,7 @@ func TestUnexportedRead(t *testing.T) { func TestReadErrorMsg(t *testing.T) { var buf bytes.Buffer - read := func(data interface{}) { + read := func(data any) { err := Read(&buf, LittleEndian, data) want := "binary.Read: invalid type " + reflect.TypeOf(data).String() if err == nil { @@ -457,7 +457,7 @@ func TestReadInvalidDestination(t *testing.T) { } func testReadInvalidDestination(t *testing.T, order ByteOrder) { - destinations := []interface{}{ + destinations := []any{ int8(0), int16(0), int32(0), diff --git a/src/encoding/binary/example_test.go b/src/encoding/binary/example_test.go index b994b897ce..4c10daaf68 100644 --- a/src/encoding/binary/example_test.go +++ b/src/encoding/binary/example_test.go @@ -24,7 +24,7 @@ func ExampleWrite() { func ExampleWrite_multi() { buf := new(bytes.Buffer) - var data = []interface{}{ + var data = []any{ uint16(61374), int8(-54), uint8(254), diff --git a/src/encoding/gob/codec_test.go b/src/encoding/gob/codec_test.go index f38e88b638..1ca9d878ee 100644 --- a/src/encoding/gob/codec_test.go +++ b/src/encoding/gob/codec_test.go @@ -1178,13 +1178,13 @@ func TestInterface(t *testing.T) { // A struct with all basic types, stored in interfaces. type BasicInterfaceItem struct { - Int, Int8, Int16, Int32, Int64 interface{} - Uint, Uint8, Uint16, Uint32, Uint64 interface{} - Float32, Float64 interface{} - Complex64, Complex128 interface{} - Bool interface{} - String interface{} - Bytes interface{} + Int, Int8, Int16, Int32, Int64 any + Uint, Uint8, Uint16, Uint32, Uint64 any + Float32, Float64 any + Complex64, Complex128 any + Bool any + String any + Bytes any } func TestInterfaceBasic(t *testing.T) { @@ -1223,8 +1223,8 @@ func TestInterfaceBasic(t *testing.T) { type String string type PtrInterfaceItem struct { - Str1 interface{} // basic - Str2 interface{} // derived + Str1 any // basic + Str2 any // derived } // We'll send pointers; should receive values. @@ -1318,7 +1318,7 @@ func TestUnexportedFields(t *testing.T) { } } -var singletons = []interface{}{ +var singletons = []any{ true, 7, uint(10), @@ -1354,9 +1354,9 @@ type DT struct { A int B string C float64 - I interface{} - J interface{} - I_nil interface{} + I any + J any + I_nil any M map[string]int T [3]int S []string @@ -1396,7 +1396,7 @@ func TestDebugStruct(t *testing.T) { debugFunc(debugBuffer) } -func encFuzzDec(rng *rand.Rand, in interface{}) error { +func encFuzzDec(rng *rand.Rand, in any) error { buf := new(bytes.Buffer) enc := NewEncoder(buf) if err := enc.Encode(&in); err != nil { @@ -1411,7 +1411,7 @@ func encFuzzDec(rng *rand.Rand, in interface{}) error { } dec := NewDecoder(buf) - var e interface{} + var e any if err := dec.Decode(&e); err != nil { return err } @@ -1425,7 +1425,7 @@ func TestFuzz(t *testing.T) { } // all possible inputs - input := []interface{}{ + input := []any{ new(int), new(float32), new(float64), @@ -1450,7 +1450,7 @@ func TestFuzzRegressions(t *testing.T) { testFuzz(t, 1330522872628565000, 100, new(int)) } -func testFuzz(t *testing.T, seed int64, n int, input ...interface{}) { +func testFuzz(t *testing.T, seed int64, n int, input ...any) { for _, e := range input { t.Logf("seed=%d n=%d e=%T", seed, n, e) rng := rand.New(rand.NewSource(seed)) diff --git a/src/encoding/gob/debug.go b/src/encoding/gob/debug.go index 5ceb2bfac7..b6d5a3e95c 100644 --- a/src/encoding/gob/debug.go +++ b/src/encoding/gob/debug.go @@ -118,7 +118,7 @@ type debugger struct { // dump prints the next nBytes of the input. // It arranges to print the output aligned from call to // call, to make it easy to see what has been consumed. -func (deb *debugger) dump(format string, args ...interface{}) { +func (deb *debugger) dump(format string, args ...any) { if !dumpBytes { return } diff --git a/src/encoding/gob/decoder.go b/src/encoding/gob/decoder.go index 96e215eb8c..86f54b4193 100644 --- a/src/encoding/gob/decoder.go +++ b/src/encoding/gob/decoder.go @@ -186,7 +186,7 @@ func (dec *Decoder) decodeTypeSequence(isInterface bool) typeId { // correct type for the next data item received. // If the input is at EOF, Decode returns io.EOF and // does not modify e. -func (dec *Decoder) Decode(e interface{}) error { +func (dec *Decoder) Decode(e any) error { if e == nil { return dec.DecodeValue(reflect.Value{}) } diff --git a/src/encoding/gob/encode.go b/src/encoding/gob/encode.go index e49b452f6c..548d614f52 100644 --- a/src/encoding/gob/encode.go +++ b/src/encoding/gob/encode.go @@ -40,7 +40,7 @@ type encBuffer struct { } var encBufferPool = sync.Pool{ - New: func() interface{} { + New: func() any { e := new(encBuffer) e.data = e.scratch[0:0] return e diff --git a/src/encoding/gob/encoder.go b/src/encoding/gob/encoder.go index 32865a7ede..5a80e6c3e8 100644 --- a/src/encoding/gob/encoder.go +++ b/src/encoding/gob/encoder.go @@ -172,7 +172,7 @@ func (enc *Encoder) sendType(w io.Writer, state *encoderState, origt reflect.Typ // Encode transmits the data item represented by the empty interface value, // guaranteeing that all necessary type information has been transmitted first. // Passing a nil pointer to Encoder will panic, as they cannot be transmitted by gob. -func (enc *Encoder) Encode(e interface{}) error { +func (enc *Encoder) Encode(e any) error { return enc.EncodeValue(reflect.ValueOf(e)) } diff --git a/src/encoding/gob/encoder_test.go b/src/encoding/gob/encoder_test.go index a358d5bc30..6934841b3a 100644 --- a/src/encoding/gob/encoder_test.go +++ b/src/encoding/gob/encoder_test.go @@ -18,7 +18,7 @@ import ( // Test basic operations in a safe manner. func TestBasicEncoderDecoder(t *testing.T) { - var values = []interface{}{ + var values = []any{ true, int(123), int8(123), @@ -228,7 +228,7 @@ func TestEncoderDecoder(t *testing.T) { // Run one value through the encoder/decoder, but use the wrong type. // Input is always an ET1; we compare it to whatever is under 'e'. -func badTypeCheck(e interface{}, shouldFail bool, msg string, t *testing.T) { +func badTypeCheck(e any, shouldFail bool, msg string, t *testing.T) { b := new(bytes.Buffer) enc := NewEncoder(b) et1 := new(ET1) @@ -256,7 +256,7 @@ func TestWrongTypeDecoder(t *testing.T) { } // Types not supported at top level by the Encoder. -var unsupportedValues = []interface{}{ +var unsupportedValues = []any{ make(chan int), func(a int) bool { return true }, } @@ -272,7 +272,7 @@ func TestUnsupported(t *testing.T) { } } -func encAndDec(in, out interface{}) error { +func encAndDec(in, out any) error { b := new(bytes.Buffer) enc := NewEncoder(b) err := enc.Encode(in) @@ -418,8 +418,8 @@ var testMap map[string]int var testArray [7]int type SingleTest struct { - in interface{} - out interface{} + in any + out any err string } @@ -536,7 +536,7 @@ func TestInterfaceIndirect(t *testing.T) { // encoder and decoder don't skew with respect to type definitions. type Struct0 struct { - I interface{} + I any } type NewType0 struct { @@ -544,7 +544,7 @@ type NewType0 struct { } type ignoreTest struct { - in, out interface{} + in, out any } var ignoreTests = []ignoreTest{ @@ -559,7 +559,7 @@ var ignoreTests = []ignoreTest{ // Decode struct containing an interface into a nil. {&Struct0{&NewType0{"value0"}}, nil}, // Decode singleton slice of interfaces into a nil. - {[]interface{}{"hi", &NewType0{"value1"}, 23}, nil}, + {[]any{"hi", &NewType0{"value1"}, 23}, nil}, } func TestDecodeIntoNothing(t *testing.T) { @@ -621,7 +621,7 @@ func TestIgnoreRecursiveType(t *testing.T) { // Another bug from golang-nuts, involving nested interfaces. type Bug0Outer struct { - Bug0Field interface{} + Bug0Field any } type Bug0Inner struct { @@ -635,7 +635,7 @@ func TestNestedInterfaces(t *testing.T) { Register(new(Bug0Outer)) Register(new(Bug0Inner)) f := &Bug0Outer{&Bug0Outer{&Bug0Inner{7}}} - var v interface{} = f + var v any = f err := e.Encode(&v) if err != nil { t.Fatal("Encode:", err) @@ -694,7 +694,7 @@ func TestMapBug1(t *testing.T) { } func TestGobMapInterfaceEncode(t *testing.T) { - m := map[string]interface{}{ + m := map[string]any{ "up": uintptr(0), "i0": []int{-1}, "i1": []int8{-1}, @@ -876,10 +876,10 @@ func TestGobPtrSlices(t *testing.T) { // getDecEnginePtr cached engine for ut.base instead of ut.user so we passed // a *map and then tried to reuse its engine to decode the inner map. func TestPtrToMapOfMap(t *testing.T) { - Register(make(map[string]interface{})) - subdata := make(map[string]interface{}) + Register(make(map[string]any)) + subdata := make(map[string]any) subdata["bar"] = "baz" - data := make(map[string]interface{}) + data := make(map[string]any) data["foo"] = subdata b := new(bytes.Buffer) @@ -887,7 +887,7 @@ func TestPtrToMapOfMap(t *testing.T) { if err != nil { t.Fatal("encode:", err) } - var newData map[string]interface{} + var newData map[string]any err = NewDecoder(b).Decode(&newData) if err != nil { t.Fatal("decode:", err) @@ -927,7 +927,7 @@ func TestTopLevelNilPointer(t *testing.T) { } } -func encodeAndRecover(value interface{}) (encodeErr, panicErr error) { +func encodeAndRecover(value any) (encodeErr, panicErr error) { defer func() { e := recover() if e != nil { @@ -959,7 +959,7 @@ func TestNilPointerPanics(t *testing.T) { ) testCases := []struct { - value interface{} + value any mustPanic bool }{ {nilStringPtr, true}, @@ -991,7 +991,7 @@ func TestNilPointerPanics(t *testing.T) { func TestNilPointerInsideInterface(t *testing.T) { var ip *int si := struct { - I interface{} + I any }{ I: ip, } @@ -1049,7 +1049,7 @@ type Z struct { func Test29ElementSlice(t *testing.T) { Register(Z{}) - src := make([]interface{}, 100) // Size needs to be bigger than size of type definition. + src := make([]any, 100) // Size needs to be bigger than size of type definition. for i := range src { src[i] = Z{} } @@ -1060,7 +1060,7 @@ func Test29ElementSlice(t *testing.T) { return } - var dst []interface{} + var dst []any err = NewDecoder(buf).Decode(&dst) if err != nil { t.Errorf("decode: %v", err) @@ -1091,9 +1091,9 @@ func TestErrorForHugeSlice(t *testing.T) { } type badDataTest struct { - input string // The input encoded as a hex string. - error string // A substring of the error that should result. - data interface{} // What to decode into. + input string // The input encoded as a hex string. + error string // A substring of the error that should result. + data any // What to decode into. } var badDataTests = []badDataTest{ diff --git a/src/encoding/gob/error.go b/src/encoding/gob/error.go index 949333bc03..3c9515b5ed 100644 --- a/src/encoding/gob/error.go +++ b/src/encoding/gob/error.go @@ -20,7 +20,7 @@ type gobError struct { // errorf is like error_ but takes Printf-style arguments to construct an error. // It always prefixes the message with "gob: ". -func errorf(format string, args ...interface{}) { +func errorf(format string, args ...any) { error_(fmt.Errorf("gob: "+format, args...)) } diff --git a/src/encoding/gob/gobencdec_test.go b/src/encoding/gob/gobencdec_test.go index 6d2c8db42d..1d5dde22a4 100644 --- a/src/encoding/gob/gobencdec_test.go +++ b/src/encoding/gob/gobencdec_test.go @@ -734,7 +734,7 @@ func (a *isZeroBugArray) GobDecode(data []byte) error { } type isZeroBugInterface struct { - I interface{} + I any } func (i isZeroBugInterface) GobEncode() (b []byte, e error) { diff --git a/src/encoding/gob/timing_test.go b/src/encoding/gob/timing_test.go index 516aeea92c..bdee39c447 100644 --- a/src/encoding/gob/timing_test.go +++ b/src/encoding/gob/timing_test.go @@ -20,7 +20,7 @@ type Bench struct { D []byte } -func benchmarkEndToEnd(b *testing.B, ctor func() interface{}, pipe func() (r io.Reader, w io.Writer, err error)) { +func benchmarkEndToEnd(b *testing.B, ctor func() any, pipe func() (r io.Reader, w io.Writer, err error)) { b.RunParallel(func(pb *testing.PB) { r, w, err := pipe() if err != nil { @@ -41,7 +41,7 @@ func benchmarkEndToEnd(b *testing.B, ctor func() interface{}, pipe func() (r io. } func BenchmarkEndToEndPipe(b *testing.B) { - benchmarkEndToEnd(b, func() interface{} { + benchmarkEndToEnd(b, func() any { return &Bench{7, 3.2, "now is the time", bytes.Repeat([]byte("for all good men"), 100)} }, func() (r io.Reader, w io.Writer, err error) { r, w, err = os.Pipe() @@ -50,7 +50,7 @@ func BenchmarkEndToEndPipe(b *testing.B) { } func BenchmarkEndToEndByteBuffer(b *testing.B) { - benchmarkEndToEnd(b, func() interface{} { + benchmarkEndToEnd(b, func() any { return &Bench{7, 3.2, "now is the time", bytes.Repeat([]byte("for all good men"), 100)} }, func() (r io.Reader, w io.Writer, err error) { var buf bytes.Buffer @@ -59,10 +59,10 @@ func BenchmarkEndToEndByteBuffer(b *testing.B) { } func BenchmarkEndToEndSliceByteBuffer(b *testing.B) { - benchmarkEndToEnd(b, func() interface{} { + benchmarkEndToEnd(b, func() any { v := &Bench{7, 3.2, "now is the time", nil} Register(v) - arr := make([]interface{}, 100) + arr := make([]any, 100) for i := range arr { arr[i] = v } @@ -133,7 +133,7 @@ func TestCountDecodeMallocs(t *testing.T) { } } -func benchmarkEncodeSlice(b *testing.B, a interface{}) { +func benchmarkEncodeSlice(b *testing.B, a any) { b.ResetTimer() b.RunParallel(func(pb *testing.PB) { var buf bytes.Buffer @@ -182,7 +182,7 @@ func BenchmarkEncodeStringSlice(b *testing.B) { } func BenchmarkEncodeInterfaceSlice(b *testing.B) { - a := make([]interface{}, 1000) + a := make([]any, 1000) for i := range a { a[i] = "now is the time" } @@ -217,7 +217,7 @@ func (b *benchmarkBuf) reset() { b.offset = 0 } -func benchmarkDecodeSlice(b *testing.B, a interface{}) { +func benchmarkDecodeSlice(b *testing.B, a any) { var buf bytes.Buffer enc := NewEncoder(&buf) err := enc.Encode(a) @@ -295,7 +295,7 @@ func BenchmarkDecodeBytesSlice(b *testing.B) { } func BenchmarkDecodeInterfaceSlice(b *testing.B) { - a := make([]interface{}, 1000) + a := make([]any, 1000) for i := range a { a[i] = "now is the time" } diff --git a/src/encoding/gob/type.go b/src/encoding/gob/type.go index 412a348137..6e2c724232 100644 --- a/src/encoding/gob/type.go +++ b/src/encoding/gob/type.go @@ -244,7 +244,7 @@ var ( tBytes = bootstrapType("bytes", (*[]byte)(nil), 5) tString = bootstrapType("string", (*string)(nil), 6) tComplex = bootstrapType("complex", (*complex128)(nil), 7) - tInterface = bootstrapType("interface", (*interface{})(nil), 8) + tInterface = bootstrapType("interface", (*any)(nil), 8) // Reserve some Ids for compatible expansion tReserved7 = bootstrapType("_reserved1", (*struct{ r7 int })(nil), 9) tReserved6 = bootstrapType("_reserved1", (*struct{ r6 int })(nil), 10) @@ -611,7 +611,7 @@ func checkId(want, got typeId) { // used for building the basic types; called only from init(). the incoming // interface always refers to a pointer. -func bootstrapType(name string, e interface{}, expect typeId) typeId { +func bootstrapType(name string, e any, expect typeId) typeId { rt := reflect.TypeOf(e).Elem() _, present := types[rt] if present { @@ -804,7 +804,7 @@ var ( // RegisterName is like Register but uses the provided name rather than the // type's default. -func RegisterName(name string, value interface{}) { +func RegisterName(name string, value any) { if name == "" { // reserved for nil panic("attempt to register empty name") @@ -833,7 +833,7 @@ func RegisterName(name string, value interface{}) { // transferred as implementations of interface values need to be registered. // Expecting to be used only during initialization, it panics if the mapping // between types and names is not a bijection. -func Register(value interface{}) { +func Register(value any) { // Default to printed representation for unnamed types rt := reflect.TypeOf(value) name := rt.String() diff --git a/src/encoding/gob/type_test.go b/src/encoding/gob/type_test.go index fa3e802d4e..f5f8db8bcb 100644 --- a/src/encoding/gob/type_test.go +++ b/src/encoding/gob/type_test.go @@ -168,7 +168,7 @@ type N2 struct{} // See comment in type.go/Register. func TestRegistrationNaming(t *testing.T) { testCases := []struct { - t interface{} + t any name string }{ {&N1{}, "*gob.N1"}, @@ -231,7 +231,7 @@ func TestTypeRace(t *testing.T) { var buf bytes.Buffer enc := NewEncoder(&buf) dec := NewDecoder(&buf) - var x interface{} + var x any switch i { case 0: x = &N1{} diff --git a/src/encoding/json/bench_test.go b/src/encoding/json/bench_test.go index 73c7b09fb6..95609140b0 100644 --- a/src/encoding/json/bench_test.go +++ b/src/encoding/json/bench_test.go @@ -192,7 +192,7 @@ func BenchmarkDecoderStream(b *testing.B) { var buf bytes.Buffer dec := NewDecoder(&buf) buf.WriteString(`"` + strings.Repeat("x", 1000000) + `"` + "\n\n\n") - var x interface{} + var x any if err := dec.Decode(&x); err != nil { b.Fatal("Decode:", err) } diff --git a/src/encoding/json/decode.go b/src/encoding/json/decode.go index df4c5e1a16..555df0b7e8 100644 --- a/src/encoding/json/decode.go +++ b/src/encoding/json/decode.go @@ -93,7 +93,7 @@ import ( // Instead, they are replaced by the Unicode replacement // character U+FFFD. // -func Unmarshal(data []byte, v interface{}) error { +func Unmarshal(data []byte, v any) error { // Check for well-formedness. // Avoids filling out half a data structure // before discovering a JSON syntax error. @@ -167,7 +167,7 @@ func (e *InvalidUnmarshalError) Error() string { return "json: Unmarshal(nil " + e.Type.String() + ")" } -func (d *decodeState) unmarshal(v interface{}) error { +func (d *decodeState) unmarshal(v any) error { rv := reflect.ValueOf(v) if rv.Kind() != reflect.Pointer || rv.IsNil() { return &InvalidUnmarshalError{reflect.TypeOf(v)} @@ -398,7 +398,7 @@ type unquotedValue struct{} // quoted string literal or literal null into an interface value. // If it finds anything other than a quoted string literal or null, // valueQuoted returns unquotedValue{}. -func (d *decodeState) valueQuoted() interface{} { +func (d *decodeState) valueQuoted() any { switch d.opcode { default: panic(phasePanicMsg) @@ -840,7 +840,7 @@ func (d *decodeState) object(v reflect.Value) error { // convertNumber converts the number literal s to a float64 or a Number // depending on the setting of d.useNumber. -func (d *decodeState) convertNumber(s string) (interface{}, error) { +func (d *decodeState) convertNumber(s string) (any, error) { if d.useNumber { return Number(s), nil } @@ -1037,7 +1037,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool // but they avoid the weight of reflection in this common case. // valueInterface is like value but returns interface{} -func (d *decodeState) valueInterface() (val interface{}) { +func (d *decodeState) valueInterface() (val any) { switch d.opcode { default: panic(phasePanicMsg) @@ -1054,8 +1054,8 @@ func (d *decodeState) valueInterface() (val interface{}) { } // arrayInterface is like array but returns []interface{}. -func (d *decodeState) arrayInterface() []interface{} { - var v = make([]interface{}, 0) +func (d *decodeState) arrayInterface() []any { + var v = make([]any, 0) for { // Look ahead for ] - can only happen on first iteration. d.scanWhile(scanSkipSpace) @@ -1080,8 +1080,8 @@ func (d *decodeState) arrayInterface() []interface{} { } // objectInterface is like object but returns map[string]interface{}. -func (d *decodeState) objectInterface() map[string]interface{} { - m := make(map[string]interface{}) +func (d *decodeState) objectInterface() map[string]any { + m := make(map[string]any) for { // Read opening " of string key or closing }. d.scanWhile(scanSkipSpace) @@ -1131,7 +1131,7 @@ func (d *decodeState) objectInterface() map[string]interface{} { // literalInterface consumes and returns a literal from d.data[d.off-1:] and // it reads the following byte ahead. The first byte of the literal has been // read already (that's how the caller knows it's a literal). -func (d *decodeState) literalInterface() interface{} { +func (d *decodeState) literalInterface() any { // All bytes inside literal return scanContinue op code. start := d.readIndex() d.rescanLiteral() diff --git a/src/encoding/json/decode_test.go b/src/encoding/json/decode_test.go index 96bf9fb5ff..c2c036b609 100644 --- a/src/encoding/json/decode_test.go +++ b/src/encoding/json/decode_test.go @@ -31,7 +31,7 @@ type U struct { } type V struct { - F1 interface{} + F1 any F2 int32 F3 Number F4 *VOuter @@ -62,18 +62,18 @@ func (*SS) UnmarshalJSON(data []byte) error { // ifaceNumAsFloat64/ifaceNumAsNumber are used to test unmarshaling with and // without UseNumber -var ifaceNumAsFloat64 = map[string]interface{}{ +var ifaceNumAsFloat64 = map[string]any{ "k1": float64(1), "k2": "s", - "k3": []interface{}{float64(1), float64(2.0), float64(3e-3)}, - "k4": map[string]interface{}{"kk1": "s", "kk2": float64(2)}, + "k3": []any{float64(1), float64(2.0), float64(3e-3)}, + "k4": map[string]any{"kk1": "s", "kk2": float64(2)}, } -var ifaceNumAsNumber = map[string]interface{}{ +var ifaceNumAsNumber = map[string]any{ "k1": Number("1"), "k2": "s", - "k3": []interface{}{Number("1"), Number("2.0"), Number("3e-3")}, - "k4": map[string]interface{}{"kk1": "s", "kk2": Number("2")}, + "k3": []any{Number("1"), Number("2.0"), Number("3e-3")}, + "k4": map[string]any{"kk1": "s", "kk2": Number("2")}, } type tx struct { @@ -262,9 +262,9 @@ type Ambig struct { } type XYZ struct { - X interface{} - Y interface{} - Z interface{} + X any + Y any + Z any } type unexportedWithMethods struct{} @@ -389,8 +389,8 @@ type mapStringToStringData struct { type unmarshalTest struct { in string - ptr interface{} // new(type) - out interface{} + ptr any // new(type) + out any err error useNumber bool golden bool @@ -414,13 +414,13 @@ var unmarshalTests = []unmarshalTest{ {in: `-5`, ptr: new(int16), out: int16(-5)}, {in: `2`, ptr: new(Number), out: Number("2"), useNumber: true}, {in: `2`, ptr: new(Number), out: Number("2")}, - {in: `2`, ptr: new(interface{}), out: float64(2.0)}, - {in: `2`, ptr: new(interface{}), out: Number("2"), useNumber: true}, + {in: `2`, ptr: new(any), out: float64(2.0)}, + {in: `2`, ptr: new(any), out: Number("2"), useNumber: true}, {in: `"a\u1234"`, ptr: new(string), out: "a\u1234"}, {in: `"http:\/\/"`, ptr: new(string), out: "http://"}, {in: `"g-clef: \uD834\uDD1E"`, ptr: new(string), out: "g-clef: \U0001D11E"}, {in: `"invalid: \uD834x\uDD1E"`, ptr: new(string), out: "invalid: \uFFFDx\uFFFD"}, - {in: "null", ptr: new(interface{}), out: nil}, + {in: "null", ptr: new(any), out: nil}, {in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &UnmarshalTypeError{"array", reflect.TypeOf(""), 7, "T", "X"}}, {in: `{"X": 23}`, ptr: new(T), out: T{}, err: &UnmarshalTypeError{"number", reflect.TypeOf(""), 8, "T", "X"}}, {in: `{"x": 1}`, ptr: new(tx), out: tx{}}, {in: `{"x": 1}`, ptr: new(tx), out: tx{}}, @@ -428,8 +428,8 @@ var unmarshalTests = []unmarshalTest{ {in: `{"S": 23}`, ptr: new(W), out: W{}, err: &UnmarshalTypeError{"number", reflect.TypeOf(SS("")), 0, "W", "S"}}, {in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: float64(1), F2: int32(2), F3: Number("3")}}, {in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: Number("1"), F2: int32(2), F3: Number("3")}, useNumber: true}, - {in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsFloat64}, - {in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsNumber, useNumber: true}, + {in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(any), out: ifaceNumAsFloat64}, + {in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(any), out: ifaceNumAsNumber, useNumber: true}, // raw values with whitespace {in: "\n true ", ptr: new(bool), out: true}, @@ -472,10 +472,10 @@ var unmarshalTests = []unmarshalTest{ {in: `[1, 2, 3]`, ptr: new(MustNotUnmarshalJSON), err: errors.New("MustNotUnmarshalJSON was used")}, // empty array to interface test - {in: `[]`, ptr: new([]interface{}), out: []interface{}{}}, - {in: `null`, ptr: new([]interface{}), out: []interface{}(nil)}, - {in: `{"T":[]}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": []interface{}{}}}, - {in: `{"T":null}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": interface{}(nil)}}, + {in: `[]`, ptr: new([]any), out: []any{}}, + {in: `null`, ptr: new([]any), out: []any(nil)}, + {in: `{"T":[]}`, ptr: new(map[string]any), out: map[string]any{"T": []any{}}}, + {in: `{"T":null}`, ptr: new(map[string]any), out: map[string]any{"T": any(nil)}}, // composite tests {in: allValueIndent, ptr: new(All), out: allValue}, @@ -1176,7 +1176,7 @@ func TestUnmarshal(t *testing.T) { func TestUnmarshalMarshal(t *testing.T) { initBig() - var v interface{} + var v any if err := Unmarshal(jsonBig, &v); err != nil { t.Fatalf("Unmarshal: %v", err) } @@ -1248,7 +1248,7 @@ type Xint struct { func TestUnmarshalInterface(t *testing.T) { var xint Xint - var i interface{} = &xint + var i any = &xint if err := Unmarshal([]byte(`{"X":1}`), &i); err != nil { t.Fatalf("Unmarshal: %v", err) } @@ -1382,8 +1382,8 @@ type All struct { PSmall *Small PPSmall **Small - Interface interface{} - PInterface *interface{} + Interface any + PInterface *any unexported int } @@ -1717,9 +1717,9 @@ func intpp(x *int) **int { } var interfaceSetTests = []struct { - pre interface{} + pre any json string - post interface{} + post any }{ {"foo", `"bar"`, "bar"}, {"foo", `2`, 2.0}, @@ -1738,7 +1738,7 @@ var interfaceSetTests = []struct { func TestInterfaceSet(t *testing.T) { for _, tt := range interfaceSetTests { - b := struct{ X interface{} }{tt.pre} + b := struct{ X any }{tt.pre} blob := `{"X":` + tt.json + `}` if err := Unmarshal([]byte(blob), &b); err != nil { t.Errorf("Unmarshal %#q: %v", blob, err) @@ -1768,7 +1768,7 @@ type NullTest struct { PBool *bool Map map[string]string Slice []string - Interface interface{} + Interface any PRaw *RawMessage PTime *time.Time @@ -1989,7 +1989,7 @@ func TestSliceOfCustomByte(t *testing.T) { } var decodeTypeErrorTests = []struct { - dest interface{} + dest any src string }{ {new(string), `{"user": "name"}`}, // issue 4628. @@ -2022,7 +2022,7 @@ var unmarshalSyntaxTests = []string{ } func TestUnmarshalSyntax(t *testing.T) { - var x interface{} + var x any for _, src := range unmarshalSyntaxTests { err := Unmarshal([]byte(src), &x) if _, ok := err.(*SyntaxError); !ok { @@ -2035,8 +2035,8 @@ func TestUnmarshalSyntax(t *testing.T) { // Issue 4660 type unexportedFields struct { Name string - m map[string]interface{} `json:"-"` - m2 map[string]interface{} `json:"abcd"` + m map[string]any `json:"-"` + m2 map[string]any `json:"abcd"` s []int `json:"-"` } @@ -2087,7 +2087,7 @@ func TestUnmarshalJSONLiteralError(t *testing.T) { // Issue 3717 func TestSkipArrayObjects(t *testing.T) { json := `[{}]` - var dest [0]interface{} + var dest [0]any err := Unmarshal([]byte(json), &dest) if err != nil { @@ -2102,8 +2102,8 @@ func TestPrefilled(t *testing.T) { // Values here change, cannot reuse table across runs. var prefillTests = []struct { in string - ptr interface{} - out interface{} + ptr any + out any }{ { in: `{"X": 1, "Y": 2}`, @@ -2112,8 +2112,8 @@ func TestPrefilled(t *testing.T) { }, { in: `{"X": 1, "Y": 2}`, - ptr: &map[string]interface{}{"X": float32(3), "Y": int16(4), "Z": 1.5}, - out: &map[string]interface{}{"X": float64(1), "Y": float64(2), "Z": 1.5}, + ptr: &map[string]any{"X": float32(3), "Y": int16(4), "Z": 1.5}, + out: &map[string]any{"X": float64(1), "Y": float64(2), "Z": 1.5}, }, { in: `[2]`, @@ -2150,7 +2150,7 @@ func TestPrefilled(t *testing.T) { } var invalidUnmarshalTests = []struct { - v interface{} + v any want string }{ {nil, "json: Unmarshal(nil)"}, @@ -2173,7 +2173,7 @@ func TestInvalidUnmarshal(t *testing.T) { } var invalidUnmarshalTextTests = []struct { - v interface{} + v any want string }{ {nil, "json: Unmarshal(nil)"}, @@ -2205,7 +2205,7 @@ func TestInvalidStringOption(t *testing.T) { M map[string]string `json:",string"` S []string `json:",string"` A [1]string `json:",string"` - I interface{} `json:",string"` + I any `json:",string"` P *int `json:",string"` }{M: make(map[string]string), S: make([]string, 0), I: num, P: &num} @@ -2276,8 +2276,8 @@ func TestUnmarshalEmbeddedUnexported(t *testing.T) { tests := []struct { in string - ptr interface{} - out interface{} + ptr any + out any err error }{{ // Error since we cannot set S1.embed1, but still able to set S1.R. @@ -2375,7 +2375,7 @@ func TestUnmarshalErrorAfterMultipleJSON(t *testing.T) { dec := NewDecoder(strings.NewReader(tt.in)) var err error for { - var v interface{} + var v any if err = dec.Decode(&v); err != nil { break } @@ -2403,7 +2403,7 @@ func TestUnmarshalPanic(t *testing.T) { // The decoder used to hang if decoding into an interface pointing to its own address. // See golang.org/issues/31740. func TestUnmarshalRecursivePointer(t *testing.T) { - var v interface{} + var v any v = &v data := []byte(`{"a": "b"}`) @@ -2517,36 +2517,36 @@ func TestUnmarshalMaxDepth(t *testing.T) { targets := []struct { name string - newValue func() interface{} + newValue func() any }{ { name: "unstructured", - newValue: func() interface{} { - var v interface{} + newValue: func() any { + var v any return &v }, }, { name: "typed named field", - newValue: func() interface{} { + newValue: func() any { v := struct { - A interface{} `json:"a"` + A any `json:"a"` }{} return &v }, }, { name: "typed missing field", - newValue: func() interface{} { + newValue: func() any { v := struct { - B interface{} `json:"b"` + B any `json:"b"` }{} return &v }, }, { name: "custom unmarshaler", - newValue: func() interface{} { + newValue: func() any { v := unmarshaler{} return &v }, diff --git a/src/encoding/json/encode.go b/src/encoding/json/encode.go index 4f40197797..1f5e3e446a 100644 --- a/src/encoding/json/encode.go +++ b/src/encoding/json/encode.go @@ -155,7 +155,7 @@ import ( // handle them. Passing cyclic structures to Marshal will result in // an error. // -func Marshal(v interface{}) ([]byte, error) { +func Marshal(v any) ([]byte, error) { e := newEncodeState() err := e.marshal(v, encOpts{escapeHTML: true}) @@ -172,7 +172,7 @@ func Marshal(v interface{}) ([]byte, error) { // MarshalIndent is like Marshal but applies Indent to format the output. // Each JSON element in the output will begin on a new line beginning with prefix // followed by one or more copies of indent according to the indentation nesting. -func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) { +func MarshalIndent(v any, prefix, indent string) ([]byte, error) { b, err := Marshal(v) if err != nil { return nil, err @@ -294,7 +294,7 @@ type encodeState struct { // startDetectingCyclesAfter, so that we skip the work if we're within a // reasonable amount of nested pointers deep. ptrLevel uint - ptrSeen map[interface{}]struct{} + ptrSeen map[any]struct{} } const startDetectingCyclesAfter = 1000 @@ -311,7 +311,7 @@ func newEncodeState() *encodeState { e.ptrLevel = 0 return e } - return &encodeState{ptrSeen: make(map[interface{}]struct{})} + return &encodeState{ptrSeen: make(map[any]struct{})} } // jsonError is an error wrapper type for internal use only. @@ -319,7 +319,7 @@ func newEncodeState() *encodeState { // can distinguish intentional panics from this package. type jsonError struct{ error } -func (e *encodeState) marshal(v interface{}, opts encOpts) (err error) { +func (e *encodeState) marshal(v any, opts encOpts) (err error) { defer func() { if r := recover(); r != nil { if je, ok := r.(jsonError); ok { diff --git a/src/encoding/json/encode_test.go b/src/encoding/json/encode_test.go index 0dad951095..0b021f0074 100644 --- a/src/encoding/json/encode_test.go +++ b/src/encoding/json/encode_test.go @@ -28,8 +28,8 @@ type Optionals struct { Slr []string `json:"slr,random"` Slo []string `json:"slo,omitempty"` - Mr map[string]interface{} `json:"mr"` - Mo map[string]interface{} `json:",omitempty"` + Mr map[string]any `json:"mr"` + Mo map[string]any `json:",omitempty"` Fr float64 `json:"fr"` Fo float64 `json:"fo,omitempty"` @@ -59,8 +59,8 @@ var optionalsExpected = `{ func TestOmitEmpty(t *testing.T) { var o Optionals o.Sw = "something" - o.Mr = map[string]interface{}{} - o.Mo = map[string]interface{}{} + o.Mr = map[string]any{} + o.Mo = map[string]any{} got, err := MarshalIndent(&o, "", " ") if err != nil { @@ -180,16 +180,16 @@ type PointerCycle struct { var pointerCycle = &PointerCycle{} type PointerCycleIndirect struct { - Ptrs []interface{} + Ptrs []any } type RecursiveSlice []RecursiveSlice var ( pointerCycleIndirect = &PointerCycleIndirect{} - mapCycle = make(map[string]interface{}) - sliceCycle = []interface{}{nil} - sliceNoCycle = []interface{}{nil, nil} + mapCycle = make(map[string]any) + sliceCycle = []any{nil} + sliceNoCycle = []any{nil, nil} recursiveSliceCycle = []RecursiveSlice{nil} ) @@ -199,13 +199,13 @@ func init() { samePointerNoCycle.Ptr2 = ptr pointerCycle.Ptr = pointerCycle - pointerCycleIndirect.Ptrs = []interface{}{pointerCycleIndirect} + pointerCycleIndirect.Ptrs = []any{pointerCycleIndirect} mapCycle["x"] = mapCycle sliceCycle[0] = sliceCycle sliceNoCycle[1] = sliceNoCycle[:1] for i := startDetectingCyclesAfter; i > 0; i-- { - sliceNoCycle = []interface{}{sliceNoCycle} + sliceNoCycle = []any{sliceNoCycle} } recursiveSliceCycle[0] = recursiveSliceCycle } @@ -222,7 +222,7 @@ func TestSliceNoCycle(t *testing.T) { } } -var unsupportedValues = []interface{}{ +var unsupportedValues = []any{ math.NaN(), math.Inf(-1), math.Inf(1), @@ -367,15 +367,15 @@ func TestMarshalerEscaping(t *testing.T) { func TestAnonymousFields(t *testing.T) { tests := []struct { - label string // Test name - makeInput func() interface{} // Function to create input value - want string // Expected JSON output + label string // Test name + makeInput func() any // Function to create input value + want string // Expected JSON output }{{ // Both S1 and S2 have a field named X. From the perspective of S, // it is ambiguous which one X refers to. // This should not serialize either field. label: "AmbiguousField", - makeInput: func() interface{} { + makeInput: func() any { type ( S1 struct{ x, X int } S2 struct{ x, X int } @@ -391,7 +391,7 @@ func TestAnonymousFields(t *testing.T) { label: "DominantField", // Both S1 and S2 have a field named X, but since S has an X field as // well, it takes precedence over S1.X and S2.X. - makeInput: func() interface{} { + makeInput: func() any { type ( S1 struct{ x, X int } S2 struct{ x, X int } @@ -407,7 +407,7 @@ func TestAnonymousFields(t *testing.T) { }, { // Unexported embedded field of non-struct type should not be serialized. label: "UnexportedEmbeddedInt", - makeInput: func() interface{} { + makeInput: func() any { type ( myInt int S struct{ myInt } @@ -418,7 +418,7 @@ func TestAnonymousFields(t *testing.T) { }, { // Exported embedded field of non-struct type should be serialized. label: "ExportedEmbeddedInt", - makeInput: func() interface{} { + makeInput: func() any { type ( MyInt int S struct{ MyInt } @@ -430,7 +430,7 @@ func TestAnonymousFields(t *testing.T) { // Unexported embedded field of pointer to non-struct type // should not be serialized. label: "UnexportedEmbeddedIntPointer", - makeInput: func() interface{} { + makeInput: func() any { type ( myInt int S struct{ *myInt } @@ -444,7 +444,7 @@ func TestAnonymousFields(t *testing.T) { // Exported embedded field of pointer to non-struct type // should be serialized. label: "ExportedEmbeddedIntPointer", - makeInput: func() interface{} { + makeInput: func() any { type ( MyInt int S struct{ *MyInt } @@ -459,7 +459,7 @@ func TestAnonymousFields(t *testing.T) { // exported fields be serialized regardless of whether the struct types // themselves are exported. label: "EmbeddedStruct", - makeInput: func() interface{} { + makeInput: func() any { type ( s1 struct{ x, X int } S2 struct{ y, Y int } @@ -476,7 +476,7 @@ func TestAnonymousFields(t *testing.T) { // exported fields be serialized regardless of whether the struct types // themselves are exported. label: "EmbeddedStructPointer", - makeInput: func() interface{} { + makeInput: func() any { type ( s1 struct{ x, X int } S2 struct{ y, Y int } @@ -492,7 +492,7 @@ func TestAnonymousFields(t *testing.T) { // Exported fields on embedded unexported structs at multiple levels // of nesting should still be serialized. label: "NestedStructAndInts", - makeInput: func() interface{} { + makeInput: func() any { type ( MyInt1 int MyInt2 int @@ -519,7 +519,7 @@ func TestAnonymousFields(t *testing.T) { // the embedded fields behind it. Not properly doing so may // result in the wrong output or reflect panics. label: "EmbeddedFieldBehindNilPointer", - makeInput: func() interface{} { + makeInput: func() any { type ( S2 struct{ Field string } S struct{ *S2 } @@ -589,22 +589,22 @@ func (nm *nilTextMarshaler) MarshalText() ([]byte, error) { // See golang.org/issue/16042 and golang.org/issue/34235. func TestNilMarshal(t *testing.T) { testCases := []struct { - v interface{} + v any want string }{ {v: nil, want: `null`}, {v: new(float64), want: `0`}, - {v: []interface{}(nil), want: `null`}, + {v: []any(nil), want: `null`}, {v: []string(nil), want: `null`}, {v: map[string]string(nil), want: `null`}, {v: []byte(nil), want: `null`}, {v: struct{ M string }{"gopher"}, want: `{"M":"gopher"}`}, {v: struct{ M Marshaler }{}, want: `{"M":null}`}, {v: struct{ M Marshaler }{(*nilJSONMarshaler)(nil)}, want: `{"M":"0zenil0"}`}, - {v: struct{ M interface{} }{(*nilJSONMarshaler)(nil)}, want: `{"M":null}`}, + {v: struct{ M any }{(*nilJSONMarshaler)(nil)}, want: `{"M":null}`}, {v: struct{ M encoding.TextMarshaler }{}, want: `{"M":null}`}, {v: struct{ M encoding.TextMarshaler }{(*nilTextMarshaler)(nil)}, want: `{"M":"0zenil0"}`}, - {v: struct{ M interface{} }{(*nilTextMarshaler)(nil)}, want: `{"M":null}`}, + {v: struct{ M any }{(*nilTextMarshaler)(nil)}, want: `{"M":null}`}, } for _, tt := range testCases { @@ -864,7 +864,7 @@ type textint int func (i textint) MarshalText() ([]byte, error) { return tenc(`TI:%d`, i) } -func tenc(format string, a ...interface{}) ([]byte, error) { +func tenc(format string, a ...any) ([]byte, error) { var buf bytes.Buffer fmt.Fprintf(&buf, format, a...) return buf.Bytes(), nil @@ -877,7 +877,7 @@ func (f textfloat) MarshalText() ([]byte, error) { return tenc(`TF:%0.2f`, f) } // Issue 13783 func TestEncodeBytekind(t *testing.T) { testdata := []struct { - data interface{} + data any want string }{ {byte(7), "7"}, @@ -966,7 +966,7 @@ func TestMarshalFloat(t *testing.T) { t.Parallel() nfail := 0 test := func(f float64, bits int) { - vf := interface{}(f) + vf := any(f) if bits == 32 { f = float64(float32(f)) // round vf = float32(f) @@ -1062,25 +1062,25 @@ func TestMarshalRawMessageValue(t *testing.T) { ) tests := []struct { - in interface{} + in any want string ok bool }{ // Test with nil RawMessage. {rawNil, "null", true}, {&rawNil, "null", true}, - {[]interface{}{rawNil}, "[null]", true}, - {&[]interface{}{rawNil}, "[null]", true}, - {[]interface{}{&rawNil}, "[null]", true}, - {&[]interface{}{&rawNil}, "[null]", true}, + {[]any{rawNil}, "[null]", true}, + {&[]any{rawNil}, "[null]", true}, + {[]any{&rawNil}, "[null]", true}, + {&[]any{&rawNil}, "[null]", true}, {struct{ M RawMessage }{rawNil}, `{"M":null}`, true}, {&struct{ M RawMessage }{rawNil}, `{"M":null}`, true}, {struct{ M *RawMessage }{&rawNil}, `{"M":null}`, true}, {&struct{ M *RawMessage }{&rawNil}, `{"M":null}`, true}, - {map[string]interface{}{"M": rawNil}, `{"M":null}`, true}, - {&map[string]interface{}{"M": rawNil}, `{"M":null}`, true}, - {map[string]interface{}{"M": &rawNil}, `{"M":null}`, true}, - {&map[string]interface{}{"M": &rawNil}, `{"M":null}`, true}, + {map[string]any{"M": rawNil}, `{"M":null}`, true}, + {&map[string]any{"M": rawNil}, `{"M":null}`, true}, + {map[string]any{"M": &rawNil}, `{"M":null}`, true}, + {&map[string]any{"M": &rawNil}, `{"M":null}`, true}, {T1{rawNil}, "{}", true}, {T2{&rawNil}, `{"M":null}`, true}, {&T1{rawNil}, "{}", true}, @@ -1089,18 +1089,18 @@ func TestMarshalRawMessageValue(t *testing.T) { // Test with empty, but non-nil, RawMessage. {rawEmpty, "", false}, {&rawEmpty, "", false}, - {[]interface{}{rawEmpty}, "", false}, - {&[]interface{}{rawEmpty}, "", false}, - {[]interface{}{&rawEmpty}, "", false}, - {&[]interface{}{&rawEmpty}, "", false}, + {[]any{rawEmpty}, "", false}, + {&[]any{rawEmpty}, "", false}, + {[]any{&rawEmpty}, "", false}, + {&[]any{&rawEmpty}, "", false}, {struct{ X RawMessage }{rawEmpty}, "", false}, {&struct{ X RawMessage }{rawEmpty}, "", false}, {struct{ X *RawMessage }{&rawEmpty}, "", false}, {&struct{ X *RawMessage }{&rawEmpty}, "", false}, - {map[string]interface{}{"nil": rawEmpty}, "", false}, - {&map[string]interface{}{"nil": rawEmpty}, "", false}, - {map[string]interface{}{"nil": &rawEmpty}, "", false}, - {&map[string]interface{}{"nil": &rawEmpty}, "", false}, + {map[string]any{"nil": rawEmpty}, "", false}, + {&map[string]any{"nil": rawEmpty}, "", false}, + {map[string]any{"nil": &rawEmpty}, "", false}, + {&map[string]any{"nil": &rawEmpty}, "", false}, {T1{rawEmpty}, "{}", true}, {T2{&rawEmpty}, "", false}, {&T1{rawEmpty}, "{}", true}, @@ -1113,18 +1113,18 @@ func TestMarshalRawMessageValue(t *testing.T) { // See https://golang.org/issues/14493#issuecomment-255857318 {rawText, `"foo"`, true}, // Issue6458 {&rawText, `"foo"`, true}, - {[]interface{}{rawText}, `["foo"]`, true}, // Issue6458 - {&[]interface{}{rawText}, `["foo"]`, true}, // Issue6458 - {[]interface{}{&rawText}, `["foo"]`, true}, - {&[]interface{}{&rawText}, `["foo"]`, true}, + {[]any{rawText}, `["foo"]`, true}, // Issue6458 + {&[]any{rawText}, `["foo"]`, true}, // Issue6458 + {[]any{&rawText}, `["foo"]`, true}, + {&[]any{&rawText}, `["foo"]`, true}, {struct{ M RawMessage }{rawText}, `{"M":"foo"}`, true}, // Issue6458 {&struct{ M RawMessage }{rawText}, `{"M":"foo"}`, true}, {struct{ M *RawMessage }{&rawText}, `{"M":"foo"}`, true}, {&struct{ M *RawMessage }{&rawText}, `{"M":"foo"}`, true}, - {map[string]interface{}{"M": rawText}, `{"M":"foo"}`, true}, // Issue6458 - {&map[string]interface{}{"M": rawText}, `{"M":"foo"}`, true}, // Issue6458 - {map[string]interface{}{"M": &rawText}, `{"M":"foo"}`, true}, - {&map[string]interface{}{"M": &rawText}, `{"M":"foo"}`, true}, + {map[string]any{"M": rawText}, `{"M":"foo"}`, true}, // Issue6458 + {&map[string]any{"M": rawText}, `{"M":"foo"}`, true}, // Issue6458 + {map[string]any{"M": &rawText}, `{"M":"foo"}`, true}, + {&map[string]any{"M": &rawText}, `{"M":"foo"}`, true}, {T1{rawText}, `{"M":"foo"}`, true}, // Issue6458 {T2{&rawText}, `{"M":"foo"}`, true}, {&T1{rawText}, `{"M":"foo"}`, true}, diff --git a/src/encoding/json/example_test.go b/src/encoding/json/example_test.go index fbecf1b593..2261c770c0 100644 --- a/src/encoding/json/example_test.go +++ b/src/encoding/json/example_test.go @@ -200,7 +200,7 @@ func ExampleRawMessage_unmarshal() { } for _, c := range colors { - var dst interface{} + var dst any switch c.Space { case "RGB": dst = new(RGB) diff --git a/src/encoding/json/fuzz.go b/src/encoding/json/fuzz.go index f00898a798..b8f4ff2c1d 100644 --- a/src/encoding/json/fuzz.go +++ b/src/encoding/json/fuzz.go @@ -11,10 +11,10 @@ import ( ) func Fuzz(data []byte) (score int) { - for _, ctor := range []func() interface{}{ - func() interface{} { return new(interface{}) }, - func() interface{} { return new(map[string]interface{}) }, - func() interface{} { return new([]interface{}) }, + for _, ctor := range []func() any{ + func() any { return new(any) }, + func() any { return new(map[string]any) }, + func() any { return new([]any) }, } { v := ctor() err := Unmarshal(data, v) diff --git a/src/encoding/json/scanner.go b/src/encoding/json/scanner.go index 9dc1903e2d..dbaa821bec 100644 --- a/src/encoding/json/scanner.go +++ b/src/encoding/json/scanner.go @@ -83,7 +83,7 @@ type scanner struct { } var scannerPool = sync.Pool{ - New: func() interface{} { + New: func() any { return &scanner{} }, } diff --git a/src/encoding/json/scanner_test.go b/src/encoding/json/scanner_test.go index 3737516a45..3474b3e481 100644 --- a/src/encoding/json/scanner_test.go +++ b/src/encoding/json/scanner_test.go @@ -237,7 +237,7 @@ func initBig() { jsonBig = b } -func genValue(n int) interface{} { +func genValue(n int) any { if n > 1 { switch rand.Intn(2) { case 0: @@ -270,7 +270,7 @@ func genString(stddev float64) string { return string(c) } -func genArray(n int) []interface{} { +func genArray(n int) []any { f := int(math.Abs(rand.NormFloat64()) * math.Min(10, float64(n/2))) if f > n { f = n @@ -278,14 +278,14 @@ func genArray(n int) []interface{} { if f < 1 { f = 1 } - x := make([]interface{}, f) + x := make([]any, f) for i := range x { x[i] = genValue(((i+1)*n)/f - (i*n)/f) } return x } -func genMap(n int) map[string]interface{} { +func genMap(n int) map[string]any { f := int(math.Abs(rand.NormFloat64()) * math.Min(10, float64(n/2))) if f > n { f = n @@ -293,7 +293,7 @@ func genMap(n int) map[string]interface{} { if n > 0 && f == 0 { f = 1 } - x := make(map[string]interface{}) + x := make(map[string]any) for i := 0; i < f; i++ { x[genString(10)] = genValue(((i+1)*n)/f - (i*n)/f) } diff --git a/src/encoding/json/stream.go b/src/encoding/json/stream.go index 81f404f426..6362170d5d 100644 --- a/src/encoding/json/stream.go +++ b/src/encoding/json/stream.go @@ -46,7 +46,7 @@ func (dec *Decoder) DisallowUnknownFields() { dec.d.disallowUnknownFields = true // // See the documentation for Unmarshal for details about // the conversion of JSON into a Go value. -func (dec *Decoder) Decode(v interface{}) error { +func (dec *Decoder) Decode(v any) error { if dec.err != nil { return dec.err } @@ -198,7 +198,7 @@ func NewEncoder(w io.Writer) *Encoder { // // See the documentation for Marshal for details about the // conversion of Go values to JSON. -func (enc *Encoder) Encode(v interface{}) error { +func (enc *Encoder) Encode(v any) error { if enc.err != nil { return enc.err } @@ -288,7 +288,7 @@ var _ Unmarshaler = (*RawMessage)(nil) // string, for JSON string literals // nil, for JSON null // -type Token interface{} +type Token any const ( tokenTopValue = iota @@ -452,7 +452,7 @@ func (dec *Decoder) Token() (Token, error) { if !dec.tokenValueAllowed() { return dec.tokenError(c) } - var x interface{} + var x any if err := dec.Decode(&x); err != nil { return nil, err } diff --git a/src/encoding/json/stream_test.go b/src/encoding/json/stream_test.go index c284f2d965..0e156d98e9 100644 --- a/src/encoding/json/stream_test.go +++ b/src/encoding/json/stream_test.go @@ -18,14 +18,14 @@ import ( // Test values for the stream test. // One of each JSON kind. -var streamTest = []interface{}{ +var streamTest = []any{ 0.1, "hello", nil, true, false, - []interface{}{"a", "b", "c"}, - map[string]interface{}{"K": "Kelvin", "ß": "long s"}, + []any{"a", "b", "c"}, + map[string]any{"K": "Kelvin", "ß": "long s"}, 3.14, // another value to make sure something can follow map } @@ -124,7 +124,7 @@ func TestEncoderSetEscapeHTML(t *testing.T) { for _, tt := range []struct { name string - v interface{} + v any wantEscape string want string }{ @@ -182,7 +182,7 @@ func TestDecoder(t *testing.T) { buf.WriteRune(c) } } - out := make([]interface{}, i) + out := make([]any, i) dec := NewDecoder(&buf) for j := range out { if err := dec.Decode(&out[j]); err != nil { @@ -297,7 +297,7 @@ func TestBlocking(t *testing.T) { for _, enc := range blockingTests { r, w := net.Pipe() go w.Write([]byte(enc)) - var val interface{} + var val any // If Decode reads beyond what w.Write writes above, // it will block, and the test will deadlock. @@ -326,80 +326,80 @@ func BenchmarkEncoderEncode(b *testing.B) { type tokenStreamCase struct { json string - expTokens []interface{} + expTokens []any } type decodeThis struct { - v interface{} + v any } var tokenStreamCases = []tokenStreamCase{ // streaming token cases - {json: `10`, expTokens: []interface{}{float64(10)}}, - {json: ` [10] `, expTokens: []interface{}{ + {json: `10`, expTokens: []any{float64(10)}}, + {json: ` [10] `, expTokens: []any{ Delim('['), float64(10), Delim(']')}}, - {json: ` [false,10,"b"] `, expTokens: []interface{}{ + {json: ` [false,10,"b"] `, expTokens: []any{ Delim('['), false, float64(10), "b", Delim(']')}}, - {json: `{ "a": 1 }`, expTokens: []interface{}{ + {json: `{ "a": 1 }`, expTokens: []any{ Delim('{'), "a", float64(1), Delim('}')}}, - {json: `{"a": 1, "b":"3"}`, expTokens: []interface{}{ + {json: `{"a": 1, "b":"3"}`, expTokens: []any{ Delim('{'), "a", float64(1), "b", "3", Delim('}')}}, - {json: ` [{"a": 1},{"a": 2}] `, expTokens: []interface{}{ + {json: ` [{"a": 1},{"a": 2}] `, expTokens: []any{ Delim('['), Delim('{'), "a", float64(1), Delim('}'), Delim('{'), "a", float64(2), Delim('}'), Delim(']')}}, - {json: `{"obj": {"a": 1}}`, expTokens: []interface{}{ + {json: `{"obj": {"a": 1}}`, expTokens: []any{ Delim('{'), "obj", Delim('{'), "a", float64(1), Delim('}'), Delim('}')}}, - {json: `{"obj": [{"a": 1}]}`, expTokens: []interface{}{ + {json: `{"obj": [{"a": 1}]}`, expTokens: []any{ Delim('{'), "obj", Delim('['), Delim('{'), "a", float64(1), Delim('}'), Delim(']'), Delim('}')}}, // streaming tokens with intermittent Decode() - {json: `{ "a": 1 }`, expTokens: []interface{}{ + {json: `{ "a": 1 }`, expTokens: []any{ Delim('{'), "a", decodeThis{float64(1)}, Delim('}')}}, - {json: ` [ { "a" : 1 } ] `, expTokens: []interface{}{ + {json: ` [ { "a" : 1 } ] `, expTokens: []any{ Delim('['), - decodeThis{map[string]interface{}{"a": float64(1)}}, + decodeThis{map[string]any{"a": float64(1)}}, Delim(']')}}, - {json: ` [{"a": 1},{"a": 2}] `, expTokens: []interface{}{ + {json: ` [{"a": 1},{"a": 2}] `, expTokens: []any{ Delim('['), - decodeThis{map[string]interface{}{"a": float64(1)}}, - decodeThis{map[string]interface{}{"a": float64(2)}}, + decodeThis{map[string]any{"a": float64(1)}}, + decodeThis{map[string]any{"a": float64(2)}}, Delim(']')}}, - {json: `{ "obj" : [ { "a" : 1 } ] }`, expTokens: []interface{}{ + {json: `{ "obj" : [ { "a" : 1 } ] }`, expTokens: []any{ Delim('{'), "obj", Delim('['), - decodeThis{map[string]interface{}{"a": float64(1)}}, + decodeThis{map[string]any{"a": float64(1)}}, Delim(']'), Delim('}')}}, - {json: `{"obj": {"a": 1}}`, expTokens: []interface{}{ + {json: `{"obj": {"a": 1}}`, expTokens: []any{ Delim('{'), "obj", - decodeThis{map[string]interface{}{"a": float64(1)}}, + decodeThis{map[string]any{"a": float64(1)}}, Delim('}')}}, - {json: `{"obj": [{"a": 1}]}`, expTokens: []interface{}{ + {json: `{"obj": [{"a": 1}]}`, expTokens: []any{ Delim('{'), "obj", - decodeThis{[]interface{}{ - map[string]interface{}{"a": float64(1)}, + decodeThis{[]any{ + map[string]any{"a": float64(1)}, }}, Delim('}')}}, - {json: ` [{"a": 1} {"a": 2}] `, expTokens: []interface{}{ + {json: ` [{"a": 1} {"a": 2}] `, expTokens: []any{ Delim('['), - decodeThis{map[string]interface{}{"a": float64(1)}}, + decodeThis{map[string]any{"a": float64(1)}}, decodeThis{&SyntaxError{"expected comma after array element", 11}}, }}, - {json: `{ "` + strings.Repeat("a", 513) + `" 1 }`, expTokens: []interface{}{ + {json: `{ "` + strings.Repeat("a", 513) + `" 1 }`, expTokens: []any{ Delim('{'), strings.Repeat("a", 513), decodeThis{&SyntaxError{"expected colon after object key", 518}}, }}, - {json: `{ "\a" }`, expTokens: []interface{}{ + {json: `{ "\a" }`, expTokens: []any{ Delim('{'), &SyntaxError{"invalid character 'a' in string escape code", 3}, }}, - {json: ` \a`, expTokens: []interface{}{ + {json: ` \a`, expTokens: []any{ &SyntaxError{"invalid character '\\\\' looking for beginning of value", 1}, }}, } @@ -410,7 +410,7 @@ func TestDecodeInStream(t *testing.T) { dec := NewDecoder(strings.NewReader(tcase.json)) for i, etk := range tcase.expTokens { - var tk interface{} + var tk any var err error if dt, ok := etk.(decodeThis); ok { diff --git a/src/encoding/json/tagkey_test.go b/src/encoding/json/tagkey_test.go index bbb4e6a28d..6330efd3c2 100644 --- a/src/encoding/json/tagkey_test.go +++ b/src/encoding/json/tagkey_test.go @@ -73,7 +73,7 @@ type unicodeTag struct { } var structTagObjectKeyTests = []struct { - raw interface{} + raw any value string key string }{ @@ -101,12 +101,12 @@ func TestStructTagObjectKey(t *testing.T) { if err != nil { t.Fatalf("Marshal(%#q) failed: %v", tt.raw, err) } - var f interface{} + var f any err = Unmarshal(b, &f) if err != nil { t.Fatalf("Unmarshal(%#q) failed: %v", b, err) } - for i, v := range f.(map[string]interface{}) { + for i, v := range f.(map[string]any) { switch i { case tt.key: if s, ok := v.(string); !ok || s != tt.value { diff --git a/src/encoding/xml/marshal.go b/src/encoding/xml/marshal.go index 1f0eb76341..6859be04a2 100644 --- a/src/encoding/xml/marshal.go +++ b/src/encoding/xml/marshal.go @@ -76,7 +76,7 @@ const ( // See MarshalIndent for an example. // // Marshal will return an error if asked to marshal a channel, function, or map. -func Marshal(v interface{}) ([]byte, error) { +func Marshal(v any) ([]byte, error) { var b bytes.Buffer if err := NewEncoder(&b).Encode(v); err != nil { return nil, err @@ -122,7 +122,7 @@ type MarshalerAttr interface { // MarshalIndent works like Marshal, but each XML element begins on a new // indented line that starts with prefix and is followed by one or more // copies of indent according to the nesting depth. -func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) { +func MarshalIndent(v any, prefix, indent string) ([]byte, error) { var b bytes.Buffer enc := NewEncoder(&b) enc.Indent(prefix, indent) @@ -158,7 +158,7 @@ func (enc *Encoder) Indent(prefix, indent string) { // of Go values to XML. // // Encode calls Flush before returning. -func (enc *Encoder) Encode(v interface{}) error { +func (enc *Encoder) Encode(v any) error { err := enc.p.marshalValue(reflect.ValueOf(v), nil, nil) if err != nil { return err @@ -173,7 +173,7 @@ func (enc *Encoder) Encode(v interface{}) error { // of Go values to XML. // // EncodeElement calls Flush before returning. -func (enc *Encoder) EncodeElement(v interface{}, start StartElement) error { +func (enc *Encoder) EncodeElement(v any, start StartElement) error { err := enc.p.marshalValue(reflect.ValueOf(v), nil, &start) if err != nil { return err diff --git a/src/encoding/xml/marshal_test.go b/src/encoding/xml/marshal_test.go index cb95905f5b..5fdbae7ef0 100644 --- a/src/encoding/xml/marshal_test.go +++ b/src/encoding/xml/marshal_test.go @@ -120,17 +120,17 @@ type MixedNested struct { } type NilTest struct { - A interface{} `xml:"parent1>parent2>a"` - B interface{} `xml:"parent1>b"` - C interface{} `xml:"parent1>parent2>c"` + A any `xml:"parent1>parent2>a"` + B any `xml:"parent1>b"` + C any `xml:"parent1>parent2>c"` } type Service struct { XMLName struct{} `xml:"service"` Domain *Domain `xml:"host>domain"` Port *Port `xml:"host>port"` - Extra1 interface{} - Extra2 interface{} `xml:"host>extra2"` + Extra1 any + Extra2 any `xml:"host>extra2"` } var nilStruct *Ship @@ -283,7 +283,7 @@ type Data struct { } type Plain struct { - V interface{} + V any } type MyInt int @@ -387,7 +387,7 @@ type NestedAndCData struct { CDATA string `xml:",cdata"` } -func ifaceptr(x interface{}) interface{} { +func ifaceptr(x any) any { return &x } @@ -412,7 +412,7 @@ type DirectComment struct { type IfaceComment struct { T1 T1 - Comment interface{} `xml:",comment"` + Comment any `xml:",comment"` T2 T2 } @@ -430,7 +430,7 @@ type DirectChardata struct { type IfaceChardata struct { T1 T1 - Chardata interface{} `xml:",chardata"` + Chardata any `xml:",chardata"` T2 T2 } @@ -448,7 +448,7 @@ type DirectCDATA struct { type IfaceCDATA struct { T1 T1 - CDATA interface{} `xml:",cdata"` + CDATA any `xml:",cdata"` T2 T2 } @@ -466,7 +466,7 @@ type DirectInnerXML struct { type IfaceInnerXML struct { T1 T1 - InnerXML interface{} `xml:",innerxml"` + InnerXML any `xml:",innerxml"` T2 T2 } @@ -484,7 +484,7 @@ type DirectElement struct { type IfaceElement struct { T1 T1 - Element interface{} + Element any T2 T2 } @@ -502,7 +502,7 @@ type DirectOmitEmpty struct { type IfaceOmitEmpty struct { T1 T1 - OmitEmpty interface{} `xml:",omitempty"` + OmitEmpty any `xml:",omitempty"` T2 T2 } @@ -520,7 +520,7 @@ type DirectAny struct { type IfaceAny struct { T1 T1 - Any interface{} `xml:",any"` + Any any `xml:",any"` T2 T2 } @@ -540,7 +540,7 @@ var ( // please try to make them two-way as well to ensure that // marshaling and unmarshaling are as symmetrical as feasible. var marshalTests = []struct { - Value interface{} + Value any ExpectXML string MarshalOnly bool MarshalError string @@ -1700,7 +1700,7 @@ type BadAttr struct { } var marshalErrorTests = []struct { - Value interface{} + Value any Err string Kind reflect.Kind }{ @@ -1738,7 +1738,7 @@ var marshalErrorTests = []struct { } var marshalIndentTests = []struct { - Value interface{} + Value any Prefix string Indent string ExpectXML string @@ -1933,7 +1933,7 @@ func BenchmarkUnmarshal(b *testing.B) { func TestStructPointerMarshal(t *testing.T) { type A struct { XMLName string `xml:"a"` - B []interface{} + B []any } type C struct { XMLName Name @@ -2327,7 +2327,7 @@ loop: continue loop } } - errorf := func(f string, a ...interface{}) { + errorf := func(f string, a ...any) { t.Errorf("#%d %s token #%d:%s", i, tt.desc, len(tt.toks)-1, fmt.Sprintf(f, a...)) } switch { diff --git a/src/encoding/xml/read.go b/src/encoding/xml/read.go index 48b0ec055c..0701e18625 100644 --- a/src/encoding/xml/read.go +++ b/src/encoding/xml/read.go @@ -129,13 +129,13 @@ import ( // A missing element or empty attribute value will be unmarshaled as a zero value. // If the field is a slice, a zero value will be appended to the field. Otherwise, the // field will be set to its zero value. -func Unmarshal(data []byte, v interface{}) error { +func Unmarshal(data []byte, v any) error { return NewDecoder(bytes.NewReader(data)).Decode(v) } // Decode works like Unmarshal, except it reads the decoder // stream to find the start element. -func (d *Decoder) Decode(v interface{}) error { +func (d *Decoder) Decode(v any) error { return d.DecodeElement(v, nil) } @@ -143,7 +143,7 @@ func (d *Decoder) Decode(v interface{}) error { // a pointer to the start XML element to decode into v. // It is useful when a client reads some raw XML tokens itself // but also wants to defer to Unmarshal for some elements. -func (d *Decoder) DecodeElement(v interface{}, start *StartElement) error { +func (d *Decoder) DecodeElement(v any, start *StartElement) error { val := reflect.ValueOf(v) if val.Kind() != reflect.Pointer { return errors.New("non-pointer passed to Unmarshal") @@ -188,7 +188,7 @@ type UnmarshalerAttr interface { } // receiverType returns the receiver type to use in an expression like "%s.MethodName". -func receiverType(val interface{}) string { +func receiverType(val any) string { t := reflect.TypeOf(val) if t.Name() != "" { return t.String() diff --git a/src/encoding/xml/read_test.go b/src/encoding/xml/read_test.go index 8c2e70fa22..391fe731a8 100644 --- a/src/encoding/xml/read_test.go +++ b/src/encoding/xml/read_test.go @@ -270,7 +270,7 @@ type PathTestE struct { Before, After string } -var pathTests = []interface{}{ +var pathTests = []any{ &PathTestA{Items: []PathTestItem{{"A"}, {"D"}}, Before: "1", After: "2"}, &PathTestB{Other: []PathTestItem{{"A"}, {"D"}}, Before: "1", After: "2"}, &PathTestC{Values1: []string{"A", "C", "D"}, Values2: []string{"B"}, Before: "1", After: "2"}, @@ -321,7 +321,7 @@ type BadPathEmbeddedB struct { } var badPathTests = []struct { - v, e interface{} + v, e any }{ {&BadPathTestA{}, &TagPathError{reflect.TypeOf(BadPathTestA{}), "First", "items>item1", "Second", "items"}}, {&BadPathTestB{}, &TagPathError{reflect.TypeOf(BadPathTestB{}), "First", "items>item1", "Second", "items>item1>value"}}, @@ -691,7 +691,7 @@ type Pea struct { } type Pod struct { - Pea interface{} `xml:"Pea"` + Pea any `xml:"Pea"` } // https://golang.org/issue/6836 diff --git a/src/encoding/xml/xml.go b/src/encoding/xml/xml.go index 33d0b417b9..8a0a9c253a 100644 --- a/src/encoding/xml/xml.go +++ b/src/encoding/xml/xml.go @@ -52,7 +52,7 @@ type Attr struct { // A Token is an interface holding one of the token types: // StartElement, EndElement, CharData, Comment, ProcInst, or Directive. -type Token interface{} +type Token any // A StartElement represents an XML start element. type StartElement struct { diff --git a/src/errors/wrap.go b/src/errors/wrap.go index ab3cdb86d3..263ae16b48 100644 --- a/src/errors/wrap.go +++ b/src/errors/wrap.go @@ -75,7 +75,7 @@ func Is(err, target error) bool { // // As panics if target is not a non-nil pointer to either a type that implements // error, or to any interface type. -func As(err error, target interface{}) bool { +func As(err error, target any) bool { if target == nil { panic("errors: target cannot be nil") } @@ -93,7 +93,7 @@ func As(err error, target interface{}) bool { val.Elem().Set(reflectlite.ValueOf(err)) return true } - if x, ok := err.(interface{ As(interface{}) bool }); ok && x.As(target) { + if x, ok := err.(interface{ As(any) bool }); ok && x.As(target) { return true } err = Unwrap(err) diff --git a/src/errors/wrap_test.go b/src/errors/wrap_test.go index a22fee2f04..eb8314b04b 100644 --- a/src/errors/wrap_test.go +++ b/src/errors/wrap_test.go @@ -66,7 +66,7 @@ var poserPathErr = &fs.PathError{Op: "poser"} func (p *poser) Error() string { return p.msg } func (p *poser) Is(err error) bool { return p.f(err) } -func (p *poser) As(err interface{}) bool { +func (p *poser) As(err any) bool { switch x := err.(type) { case **poser: *x = p @@ -90,9 +90,9 @@ func TestAs(t *testing.T) { testCases := []struct { err error - target interface{} + target any match bool - want interface{} // value of target on match + want any // value of target on match }{{ nil, &errP, @@ -171,7 +171,7 @@ func TestAs(t *testing.T) { func TestAsValidation(t *testing.T) { var s string - testCases := []interface{}{ + testCases := []any{ nil, (*int)(nil), "error", diff --git a/src/expvar/expvar.go b/src/expvar/expvar.go index 13b5c99b6e..8bbf41b151 100644 --- a/src/expvar/expvar.go +++ b/src/expvar/expvar.go @@ -130,7 +130,7 @@ func (v *Map) Init() *Map { v.keysMu.Lock() defer v.keysMu.Unlock() v.keys = v.keys[:0] - v.m.Range(func(k, _ interface{}) bool { + v.m.Range(func(k, _ any) bool { v.m.Delete(k) return true }) @@ -252,9 +252,9 @@ func (v *String) Set(value string) { // Func implements Var by calling the function // and formatting the returned value using JSON. -type Func func() interface{} +type Func func() any -func (f Func) Value() interface{} { +func (f Func) Value() any { return f() } @@ -350,11 +350,11 @@ func Handler() http.Handler { return http.HandlerFunc(expvarHandler) } -func cmdline() interface{} { +func cmdline() any { return os.Args } -func memstats() interface{} { +func memstats() any { stats := new(runtime.MemStats) runtime.ReadMemStats(stats) return *stats diff --git a/src/expvar/expvar_test.go b/src/expvar/expvar_test.go index 69b0a76058..ba95a36066 100644 --- a/src/expvar/expvar_test.go +++ b/src/expvar/expvar_test.go @@ -242,12 +242,12 @@ func TestMapCounter(t *testing.T) { // colors.String() should be '{"red":3, "blue":4}', // though the order of red and blue could vary. s := colors.String() - var j interface{} + var j any err := json.Unmarshal([]byte(s), &j) if err != nil { t.Errorf("colors.String() isn't valid JSON: %v", err) } - m, ok := j.(map[string]interface{}) + m, ok := j.(map[string]any) if !ok { t.Error("colors.String() didn't produce a map.") } @@ -427,8 +427,8 @@ func BenchmarkMapAddDifferentSteadyState(b *testing.B) { func TestFunc(t *testing.T) { RemoveAll() - var x interface{} = []string{"a", "b"} - f := Func(func() interface{} { return x }) + var x any = []string{"a", "b"} + f := Func(func() any { return x }) if s, exp := f.String(), `["a","b"]`; s != exp { t.Errorf(`f.String() = %q, want %q`, s, exp) } diff --git a/src/flag/flag.go b/src/flag/flag.go index 86e16e5a61..4e2af450c5 100644 --- a/src/flag/flag.go +++ b/src/flag/flag.go @@ -122,7 +122,7 @@ func (b *boolValue) Set(s string) error { return err } -func (b *boolValue) Get() interface{} { return bool(*b) } +func (b *boolValue) Get() any { return bool(*b) } func (b *boolValue) String() string { return strconv.FormatBool(bool(*b)) } @@ -152,7 +152,7 @@ func (i *intValue) Set(s string) error { return err } -func (i *intValue) Get() interface{} { return int(*i) } +func (i *intValue) Get() any { return int(*i) } func (i *intValue) String() string { return strconv.Itoa(int(*i)) } @@ -173,7 +173,7 @@ func (i *int64Value) Set(s string) error { return err } -func (i *int64Value) Get() interface{} { return int64(*i) } +func (i *int64Value) Get() any { return int64(*i) } func (i *int64Value) String() string { return strconv.FormatInt(int64(*i), 10) } @@ -194,7 +194,7 @@ func (i *uintValue) Set(s string) error { return err } -func (i *uintValue) Get() interface{} { return uint(*i) } +func (i *uintValue) Get() any { return uint(*i) } func (i *uintValue) String() string { return strconv.FormatUint(uint64(*i), 10) } @@ -215,7 +215,7 @@ func (i *uint64Value) Set(s string) error { return err } -func (i *uint64Value) Get() interface{} { return uint64(*i) } +func (i *uint64Value) Get() any { return uint64(*i) } func (i *uint64Value) String() string { return strconv.FormatUint(uint64(*i), 10) } @@ -232,7 +232,7 @@ func (s *stringValue) Set(val string) error { return nil } -func (s *stringValue) Get() interface{} { return string(*s) } +func (s *stringValue) Get() any { return string(*s) } func (s *stringValue) String() string { return string(*s) } @@ -253,7 +253,7 @@ func (f *float64Value) Set(s string) error { return err } -func (f *float64Value) Get() interface{} { return float64(*f) } +func (f *float64Value) Get() any { return float64(*f) } func (f *float64Value) String() string { return strconv.FormatFloat(float64(*f), 'g', -1, 64) } @@ -274,7 +274,7 @@ func (d *durationValue) Set(s string) error { return err } -func (d *durationValue) Get() interface{} { return time.Duration(*d) } +func (d *durationValue) Get() any { return time.Duration(*d) } func (d *durationValue) String() string { return (*time.Duration)(d).String() } @@ -305,7 +305,7 @@ type Value interface { // by this package satisfy the Getter interface, except the type used by Func. type Getter interface { Value - Get() interface{} + Get() any } // ErrorHandling defines how FlagSet.Parse behaves if the parse fails. @@ -895,7 +895,7 @@ func Var(value Value, name string, usage string) { } // sprintf formats the message, prints it to output, and returns it. -func (f *FlagSet) sprintf(format string, a ...interface{}) string { +func (f *FlagSet) sprintf(format string, a ...any) string { msg := fmt.Sprintf(format, a...) fmt.Fprintln(f.Output(), msg) return msg @@ -903,7 +903,7 @@ func (f *FlagSet) sprintf(format string, a ...interface{}) string { // failf prints to standard error a formatted error and usage message and // returns the error. -func (f *FlagSet) failf(format string, a ...interface{}) error { +func (f *FlagSet) failf(format string, a ...any) error { msg := f.sprintf(format, a...) f.usage() return errors.New(msg) diff --git a/src/fmt/errors.go b/src/fmt/errors.go index 466a620353..4f4daf19e1 100644 --- a/src/fmt/errors.go +++ b/src/fmt/errors.go @@ -14,7 +14,7 @@ import "errors" // invalid to include more than one %w verb or to supply it with an operand // that does not implement the error interface. The %w verb is otherwise // a synonym for %v. -func Errorf(format string, a ...interface{}) error { +func Errorf(format string, a ...any) error { p := newPrinter() p.wrapErrs = true p.doPrintf(format, a) diff --git a/src/fmt/fmt_test.go b/src/fmt/fmt_test.go index 87fb323809..a4c65b8f5e 100644 --- a/src/fmt/fmt_test.go +++ b/src/fmt/fmt_test.go @@ -40,7 +40,7 @@ type ( ) func TestFmtInterface(t *testing.T) { - var i1 interface{} + var i1 any i1 = "abc" s := Sprintf("%s", i1) if s != "abc" { @@ -56,7 +56,7 @@ var ( intVar = 0 array = [5]int{1, 2, 3, 4, 5} - iarray = [4]interface{}{1, "hello", 2.5, nil} + iarray = [4]any{1, "hello", 2.5, nil} slice = array[:] islice = iarray[:] ) @@ -100,7 +100,7 @@ type S struct { } type SI struct { - I interface{} + I any } // P is a type with a String method with pointer receiver for testing %p. @@ -141,7 +141,7 @@ func (sf writeStringFormatter) Format(f State, c rune) { var fmtTests = []struct { fmt string - val interface{} + val any out string }{ {"%d", 12345, "12345"}, @@ -993,14 +993,14 @@ var fmtTests = []struct { // float and complex formatting should not change the padding width // for other elements. See issue 14642. - {"%06v", []interface{}{+10.0, 10}, "[000010 000010]"}, - {"%06v", []interface{}{-10.0, 10}, "[-00010 000010]"}, - {"%06v", []interface{}{+10.0 + 10i, 10}, "[(000010+00010i) 000010]"}, - {"%06v", []interface{}{-10.0 + 10i, 10}, "[(-00010+00010i) 000010]"}, + {"%06v", []any{+10.0, 10}, "[000010 000010]"}, + {"%06v", []any{-10.0, 10}, "[-00010 000010]"}, + {"%06v", []any{+10.0 + 10i, 10}, "[(000010+00010i) 000010]"}, + {"%06v", []any{-10.0 + 10i, 10}, "[(-00010+00010i) 000010]"}, // integer formatting should not alter padding for other elements. - {"%03.6v", []interface{}{1, 2.0, "x"}, "[000001 002 00x]"}, - {"%03.0v", []interface{}{0, 2.0, "x"}, "[ 002 000]"}, + {"%03.6v", []any{1, 2.0, "x"}, "[000001 002 00x]"}, + {"%03.0v", []any{0, 2.0, "x"}, "[ 002 000]"}, // Complex fmt used to leave the plus flag set for future entries in the array // causing +2+0i and +3+0i instead of 2+0i and 3+0i. @@ -1060,7 +1060,7 @@ var fmtTests = []struct { // Tests to check that not supported verbs generate an error string. {"%☠", nil, "%!☠()"}, - {"%☠", interface{}(nil), "%!☠()"}, + {"%☠", any(nil), "%!☠()"}, {"%☠", int(0), "%!☠(int=0)"}, {"%☠", uint(0), "%!☠(uint=0)"}, {"%☠", []byte{0, 1}, "[%!☠(uint8=0) %!☠(uint8=1)]"}, @@ -1077,8 +1077,8 @@ var fmtTests = []struct { {"%☠", func() {}, "%!☠(func()=0xPTR)"}, {"%☠", reflect.ValueOf(renamedInt(0)), "%!☠(fmt_test.renamedInt=0)"}, {"%☠", SI{renamedInt(0)}, "{%!☠(fmt_test.renamedInt=0)}"}, - {"%☠", &[]interface{}{I(1), G(2)}, "&[%!☠(fmt_test.I=1) %!☠(fmt_test.G=2)]"}, - {"%☠", SI{&[]interface{}{I(1), G(2)}}, "{%!☠(*[]interface {}=&[1 2])}"}, + {"%☠", &[]any{I(1), G(2)}, "&[%!☠(fmt_test.I=1) %!☠(fmt_test.G=2)]"}, + {"%☠", SI{&[]any{I(1), G(2)}}, "{%!☠(*[]interface {}=&[1 2])}"}, {"%☠", reflect.Value{}, ""}, {"%☠", map[float64]int{NaN: 1}, "map[%!☠(float64=NaN):%!☠(int=1)]"}, } @@ -1180,7 +1180,7 @@ func TestComplexFormatting(t *testing.T) { } } -type SE []interface{} // slice of empty; notational compactness. +type SE []any // slice of empty; notational compactness. var reorderTests = []struct { fmt string @@ -1267,7 +1267,7 @@ func BenchmarkSprintfTruncateString(b *testing.B) { } func BenchmarkSprintfTruncateBytes(b *testing.B) { - var bytes interface{} = []byte("日本語日本語日本語日本語") + var bytes any = []byte("日本語日本語日本語日本語") b.RunParallel(func(pb *testing.PB) { for pb.Next() { Sprintf("%.3s", bytes) @@ -1375,7 +1375,7 @@ func BenchmarkSprintfStringer(b *testing.B) { } func BenchmarkSprintfStructure(b *testing.B) { - s := &[]interface{}{SI{12345}, map[int]string{0: "hello"}} + s := &[]any{SI{12345}, map[int]string{0: "hello"}} b.RunParallel(func(pb *testing.PB) { for pb.Next() { Sprintf("%#v", s) @@ -1411,7 +1411,7 @@ func BenchmarkFprintfBytes(b *testing.B) { } func BenchmarkFprintIntNoAlloc(b *testing.B) { - var x interface{} = 123456 + var x any = 123456 var buf bytes.Buffer for i := 0; i < b.N; i++ { buf.Reset() @@ -1641,11 +1641,11 @@ func TestFormatterPrintln(t *testing.T) { } } -func args(a ...interface{}) []interface{} { return a } +func args(a ...any) []any { return a } var startests = []struct { fmt string - in []interface{} + in []any out string }{ {"%*d", args(4, 42), " 42"}, @@ -1687,7 +1687,7 @@ func TestWidthAndPrecision(t *testing.T) { // PanicS is a type that panics in String. type PanicS struct { - message interface{} + message any } // Value receiver. @@ -1697,7 +1697,7 @@ func (p PanicS) String() string { // PanicGo is a type that panics in GoString. type PanicGo struct { - message interface{} + message any } // Value receiver. @@ -1707,7 +1707,7 @@ func (p PanicGo) GoString() string { // PanicF is a type that panics in Format. type PanicF struct { - message interface{} + message any } // Value receiver. @@ -1717,7 +1717,7 @@ func (p PanicF) Format(f State, c rune) { var panictests = []struct { fmt string - in interface{} + in any out string }{ // String @@ -1729,7 +1729,7 @@ var panictests = []struct { {"%#v", PanicGo{io.ErrUnexpectedEOF}, "%!v(PANIC=GoString method: unexpected EOF)"}, {"%#v", PanicGo{3}, "%!v(PANIC=GoString method: 3)"}, // Issue 18282. catchPanic should not clear fmtFlags permanently. - {"%#v", []interface{}{PanicGo{3}, PanicGo{3}}, "[]interface {}{%!v(PANIC=GoString method: 3), %!v(PANIC=GoString method: 3)}"}, + {"%#v", []any{PanicGo{3}, PanicGo{3}}, "[]interface {}{%!v(PANIC=GoString method: 3), %!v(PANIC=GoString method: 3)}"}, // Format {"%s", (*PanicF)(nil), ""}, // nil pointer special case {"%s", PanicF{io.ErrUnexpectedEOF}, "%!s(PANIC=Format method: unexpected EOF)"}, @@ -1805,7 +1805,7 @@ func TestNilDoesNotBecomeTyped(t *testing.T) { var formatterFlagTests = []struct { in string - val interface{} + val any out string }{ // scalar values with the (unused by fmt) 'a' verb. diff --git a/src/fmt/print.go b/src/fmt/print.go index 698ab557a4..1c37c3cb7b 100644 --- a/src/fmt/print.go +++ b/src/fmt/print.go @@ -106,7 +106,7 @@ type pp struct { buf buffer // arg holds the current item, as an interface{}. - arg interface{} + arg any // value is used instead of arg for reflect values. value reflect.Value @@ -129,7 +129,7 @@ type pp struct { } var ppFree = sync.Pool{ - New: func() interface{} { return new(pp) }, + New: func() any { return new(pp) }, } // newPrinter allocates a new pp struct or grabs a cached one. @@ -199,7 +199,7 @@ func (p *pp) WriteString(s string) (ret int, err error) { // Fprintf formats according to a format specifier and writes to w. // It returns the number of bytes written and any write error encountered. -func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { +func Fprintf(w io.Writer, format string, a ...any) (n int, err error) { p := newPrinter() p.doPrintf(format, a) n, err = w.Write(p.buf) @@ -209,12 +209,12 @@ func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { // Printf formats according to a format specifier and writes to standard output. // It returns the number of bytes written and any write error encountered. -func Printf(format string, a ...interface{}) (n int, err error) { +func Printf(format string, a ...any) (n int, err error) { return Fprintf(os.Stdout, format, a...) } // Sprintf formats according to a format specifier and returns the resulting string. -func Sprintf(format string, a ...interface{}) string { +func Sprintf(format string, a ...any) string { p := newPrinter() p.doPrintf(format, a) s := string(p.buf) @@ -227,7 +227,7 @@ func Sprintf(format string, a ...interface{}) string { // Fprint formats using the default formats for its operands and writes to w. // Spaces are added between operands when neither is a string. // It returns the number of bytes written and any write error encountered. -func Fprint(w io.Writer, a ...interface{}) (n int, err error) { +func Fprint(w io.Writer, a ...any) (n int, err error) { p := newPrinter() p.doPrint(a) n, err = w.Write(p.buf) @@ -238,13 +238,13 @@ func Fprint(w io.Writer, a ...interface{}) (n int, err error) { // Print formats using the default formats for its operands and writes to standard output. // Spaces are added between operands when neither is a string. // It returns the number of bytes written and any write error encountered. -func Print(a ...interface{}) (n int, err error) { +func Print(a ...any) (n int, err error) { return Fprint(os.Stdout, a...) } // Sprint formats using the default formats for its operands and returns the resulting string. // Spaces are added between operands when neither is a string. -func Sprint(a ...interface{}) string { +func Sprint(a ...any) string { p := newPrinter() p.doPrint(a) s := string(p.buf) @@ -259,7 +259,7 @@ func Sprint(a ...interface{}) string { // Fprintln formats using the default formats for its operands and writes to w. // Spaces are always added between operands and a newline is appended. // It returns the number of bytes written and any write error encountered. -func Fprintln(w io.Writer, a ...interface{}) (n int, err error) { +func Fprintln(w io.Writer, a ...any) (n int, err error) { p := newPrinter() p.doPrintln(a) n, err = w.Write(p.buf) @@ -270,13 +270,13 @@ func Fprintln(w io.Writer, a ...interface{}) (n int, err error) { // Println formats using the default formats for its operands and writes to standard output. // Spaces are always added between operands and a newline is appended. // It returns the number of bytes written and any write error encountered. -func Println(a ...interface{}) (n int, err error) { +func Println(a ...any) (n int, err error) { return Fprintln(os.Stdout, a...) } // Sprintln formats using the default formats for its operands and returns the resulting string. // Spaces are always added between operands and a newline is appended. -func Sprintln(a ...interface{}) string { +func Sprintln(a ...any) string { p := newPrinter() p.doPrintln(a) s := string(p.buf) @@ -533,7 +533,7 @@ func (p *pp) fmtPointer(value reflect.Value, verb rune) { } } -func (p *pp) catchPanic(arg interface{}, verb rune, method string) { +func (p *pp) catchPanic(arg any, verb rune, method string) { if err := recover(); err != nil { // If it's a nil pointer, just say "". The likeliest causes are a // Stringer that fails to guard against nil or a nil pointer for a @@ -631,7 +631,7 @@ func (p *pp) handleMethods(verb rune) (handled bool) { return false } -func (p *pp) printArg(arg interface{}, verb rune) { +func (p *pp) printArg(arg any, verb rune) { p.arg = arg p.value = reflect.Value{} @@ -886,7 +886,7 @@ func (p *pp) printValue(value reflect.Value, verb rune, depth int) { } // intFromArg gets the argNumth element of a. On return, isInt reports whether the argument has integer type. -func intFromArg(a []interface{}, argNum int) (num int, isInt bool, newArgNum int) { +func intFromArg(a []any, argNum int) (num int, isInt bool, newArgNum int) { newArgNum = argNum if argNum < len(a) { num, isInt = a[argNum].(int) // Almost always OK. @@ -971,7 +971,7 @@ func (p *pp) missingArg(verb rune) { p.buf.writeString(missingString) } -func (p *pp) doPrintf(format string, a []interface{}) { +func (p *pp) doPrintf(format string, a []any) { end := len(format) argNum := 0 // we process one argument per non-trivial format afterIndex := false // previous item in format was an index like [3]. @@ -1146,7 +1146,7 @@ formatLoop: } } -func (p *pp) doPrint(a []interface{}) { +func (p *pp) doPrint(a []any) { prevString := false for argNum, arg := range a { isString := arg != nil && reflect.TypeOf(arg).Kind() == reflect.String @@ -1161,7 +1161,7 @@ func (p *pp) doPrint(a []interface{}) { // doPrintln is like doPrint but always adds a space between arguments // and a newline after the last argument. -func (p *pp) doPrintln(a []interface{}) { +func (p *pp) doPrintln(a []any) { for argNum, arg := range a { if argNum > 0 { p.buf.writeByte(' ') diff --git a/src/fmt/scan.go b/src/fmt/scan.go index 18cb608f43..d38610df35 100644 --- a/src/fmt/scan.go +++ b/src/fmt/scan.go @@ -60,13 +60,13 @@ type Scanner interface { // space-separated values into successive arguments. Newlines count // as space. It returns the number of items successfully scanned. // If that is less than the number of arguments, err will report why. -func Scan(a ...interface{}) (n int, err error) { +func Scan(a ...any) (n int, err error) { return Fscan(os.Stdin, a...) } // Scanln is similar to Scan, but stops scanning at a newline and // after the final item there must be a newline or EOF. -func Scanln(a ...interface{}) (n int, err error) { +func Scanln(a ...any) (n int, err error) { return Fscanln(os.Stdin, a...) } @@ -77,7 +77,7 @@ func Scanln(a ...interface{}) (n int, err error) { // Newlines in the input must match newlines in the format. // The one exception: the verb %c always scans the next rune in the // input, even if it is a space (or tab etc.) or newline. -func Scanf(format string, a ...interface{}) (n int, err error) { +func Scanf(format string, a ...any) (n int, err error) { return Fscanf(os.Stdin, format, a...) } @@ -96,13 +96,13 @@ func (r *stringReader) Read(b []byte) (n int, err error) { // values into successive arguments. Newlines count as space. It // returns the number of items successfully scanned. If that is less // than the number of arguments, err will report why. -func Sscan(str string, a ...interface{}) (n int, err error) { +func Sscan(str string, a ...any) (n int, err error) { return Fscan((*stringReader)(&str), a...) } // Sscanln is similar to Sscan, but stops scanning at a newline and // after the final item there must be a newline or EOF. -func Sscanln(str string, a ...interface{}) (n int, err error) { +func Sscanln(str string, a ...any) (n int, err error) { return Fscanln((*stringReader)(&str), a...) } @@ -110,7 +110,7 @@ func Sscanln(str string, a ...interface{}) (n int, err error) { // values into successive arguments as determined by the format. It // returns the number of items successfully parsed. // Newlines in the input must match newlines in the format. -func Sscanf(str string, format string, a ...interface{}) (n int, err error) { +func Sscanf(str string, format string, a ...any) (n int, err error) { return Fscanf((*stringReader)(&str), format, a...) } @@ -118,7 +118,7 @@ func Sscanf(str string, format string, a ...interface{}) (n int, err error) { // values into successive arguments. Newlines count as space. It // returns the number of items successfully scanned. If that is less // than the number of arguments, err will report why. -func Fscan(r io.Reader, a ...interface{}) (n int, err error) { +func Fscan(r io.Reader, a ...any) (n int, err error) { s, old := newScanState(r, true, false) n, err = s.doScan(a) s.free(old) @@ -127,7 +127,7 @@ func Fscan(r io.Reader, a ...interface{}) (n int, err error) { // Fscanln is similar to Fscan, but stops scanning at a newline and // after the final item there must be a newline or EOF. -func Fscanln(r io.Reader, a ...interface{}) (n int, err error) { +func Fscanln(r io.Reader, a ...any) (n int, err error) { s, old := newScanState(r, false, true) n, err = s.doScan(a) s.free(old) @@ -138,7 +138,7 @@ func Fscanln(r io.Reader, a ...interface{}) (n int, err error) { // values into successive arguments as determined by the format. It // returns the number of items successfully parsed. // Newlines in the input must match newlines in the format. -func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err error) { +func Fscanf(r io.Reader, format string, a ...any) (n int, err error) { s, old := newScanState(r, false, false) n, err = s.doScanf(format, a) s.free(old) @@ -376,7 +376,7 @@ func (r *readRune) UnreadRune() error { } var ssFree = sync.Pool{ - New: func() interface{} { return new(ss) }, + New: func() any { return new(ss) }, } // newScanState allocates a new ss struct or grab a cached one. @@ -950,7 +950,7 @@ func (s *ss) scanPercent() { } // scanOne scans a single value, deriving the scanner from the type of the argument. -func (s *ss) scanOne(verb rune, arg interface{}) { +func (s *ss) scanOne(verb rune, arg any) { s.buf = s.buf[:0] var err error // If the parameter has its own Scan method, use that. @@ -1067,7 +1067,7 @@ func errorHandler(errp *error) { } // doScan does the real work for scanning without a format string. -func (s *ss) doScan(a []interface{}) (numProcessed int, err error) { +func (s *ss) doScan(a []any) (numProcessed int, err error) { defer errorHandler(&err) for _, arg := range a { s.scanOne('v', arg) @@ -1178,7 +1178,7 @@ func (s *ss) advance(format string) (i int) { // doScanf does the real work when scanning with a format string. // At the moment, it handles only pointers to basic types. -func (s *ss) doScanf(format string, a []interface{}) (numProcessed int, err error) { +func (s *ss) doScanf(format string, a []any) (numProcessed int, err error) { defer errorHandler(&err) end := len(format) - 1 // We process one item per non-trivial format diff --git a/src/fmt/scan_test.go b/src/fmt/scan_test.go index 6b71b792ed..da0dfd19a2 100644 --- a/src/fmt/scan_test.go +++ b/src/fmt/scan_test.go @@ -21,22 +21,22 @@ import ( type ScanTest struct { text string - in interface{} - out interface{} + in any + out any } type ScanfTest struct { format string text string - in interface{} - out interface{} + in any + out any } type ScanfMultiTest struct { format string text string - in []interface{} - out []interface{} + in []any + out []any err string } @@ -444,7 +444,7 @@ var z IntString var r1, r2, r3 rune var multiTests = []ScanfMultiTest{ - {"", "", []interface{}{}, []interface{}{}, ""}, + {"", "", []any{}, []any{}, ""}, {"%d", "23", args(&i), args(23), ""}, {"%2s%3s", "22333", args(&s, &t), args("22", "333"), ""}, {"%2d%3d", "44555", args(&i, &j), args(44, 555), ""}, @@ -498,7 +498,7 @@ var readers = []struct { }}, } -func testScan(t *testing.T, f func(string) io.Reader, scan func(r io.Reader, a ...interface{}) (int, error)) { +func testScan(t *testing.T, f func(string) io.Reader, scan func(r io.Reader, a ...any) (int, error)) { for _, test := range scanTests { r := f(test.text) n, err := scan(r, test.in) @@ -637,7 +637,7 @@ func TestInf(t *testing.T) { } func testScanfMulti(t *testing.T, f func(string) io.Reader) { - sliceType := reflect.TypeOf(make([]interface{}, 1)) + sliceType := reflect.TypeOf(make([]any, 1)) for _, test := range multiTests { r := f(test.text) n, err := Fscanf(r, test.format, test.in...) @@ -836,7 +836,7 @@ func TestEOFAtEndOfInput(t *testing.T) { var eofTests = []struct { format string - v interface{} + v any }{ {"%s", &stringVal}, {"%q", &stringVal}, diff --git a/src/go/ast/print.go b/src/go/ast/print.go index b58683075c..85e6943928 100644 --- a/src/go/ast/print.go +++ b/src/go/ast/print.go @@ -36,17 +36,17 @@ func NotNilFilter(_ string, v reflect.Value) bool { // struct fields for which f(fieldname, fieldvalue) is true are // printed; all others are filtered from the output. Unexported // struct fields are never printed. -func Fprint(w io.Writer, fset *token.FileSet, x interface{}, f FieldFilter) error { +func Fprint(w io.Writer, fset *token.FileSet, x any, f FieldFilter) error { return fprint(w, fset, x, f) } -func fprint(w io.Writer, fset *token.FileSet, x interface{}, f FieldFilter) (err error) { +func fprint(w io.Writer, fset *token.FileSet, x any, f FieldFilter) (err error) { // setup printer p := printer{ output: w, fset: fset, filter: f, - ptrmap: make(map[interface{}]int), + ptrmap: make(map[any]int), last: '\n', // force printing of line number on first line } @@ -70,7 +70,7 @@ func fprint(w io.Writer, fset *token.FileSet, x interface{}, f FieldFilter) (err // Print prints x to standard output, skipping nil fields. // Print(fset, x) is the same as Fprint(os.Stdout, fset, x, NotNilFilter). -func Print(fset *token.FileSet, x interface{}) error { +func Print(fset *token.FileSet, x any) error { return Fprint(os.Stdout, fset, x, NotNilFilter) } @@ -78,10 +78,10 @@ type printer struct { output io.Writer fset *token.FileSet filter FieldFilter - ptrmap map[interface{}]int // *T -> line number - indent int // current indentation level - last byte // the last byte processed by Write - line int // current line number + ptrmap map[any]int // *T -> line number + indent int // current indentation level + last byte // the last byte processed by Write + line int // current line number } var indent = []byte(". ") @@ -125,7 +125,7 @@ type localError struct { } // printf is a convenience wrapper that takes care of print errors. -func (p *printer) printf(format string, args ...interface{}) { +func (p *printer) printf(format string, args ...any) { if _, err := fmt.Fprintf(p, format, args...); err != nil { panic(localError{err}) } diff --git a/src/go/ast/print_test.go b/src/go/ast/print_test.go index 210f164301..6691ccd63a 100644 --- a/src/go/ast/print_test.go +++ b/src/go/ast/print_test.go @@ -11,7 +11,7 @@ import ( ) var tests = []struct { - x interface{} // x is printed as s + x any // x is printed as s s string }{ // basic types diff --git a/src/go/ast/resolve.go b/src/go/ast/resolve.go index c1830b5e4d..126a27b18c 100644 --- a/src/go/ast/resolve.go +++ b/src/go/ast/resolve.go @@ -22,7 +22,7 @@ func (p *pkgBuilder) error(pos token.Pos, msg string) { p.errors.Add(p.fset.Position(pos), msg) } -func (p *pkgBuilder) errorf(pos token.Pos, format string, args ...interface{}) { +func (p *pkgBuilder) errorf(pos token.Pos, format string, args ...any) { p.error(pos, fmt.Sprintf(format, args...)) } diff --git a/src/go/ast/scope.go b/src/go/ast/scope.go index a400c7152a..d24a5f0e00 100644 --- a/src/go/ast/scope.go +++ b/src/go/ast/scope.go @@ -75,10 +75,10 @@ func (s *Scope) String() string { // type Object struct { Kind ObjKind - Name string // declared name - Decl interface{} // corresponding Field, XxxSpec, FuncDecl, LabeledStmt, AssignStmt, Scope; or nil - Data interface{} // object-specific data; or nil - Type interface{} // placeholder for type information; may be nil + Name string // declared name + Decl any // corresponding Field, XxxSpec, FuncDecl, LabeledStmt, AssignStmt, Scope; or nil + Data any // object-specific data; or nil + Type any // placeholder for type information; may be nil } // NewObj creates a new object of a given kind and name. diff --git a/src/go/constant/value.go b/src/go/constant/value.go index 014e873100..dee3bce9ee 100644 --- a/src/go/constant/value.go +++ b/src/go/constant/value.go @@ -579,7 +579,7 @@ func Float64Val(x Value) (float64, bool) { // Float *big.Float or *big.Rat // everything else nil // -func Val(x Value) interface{} { +func Val(x Value) any { switch x := x.(type) { case boolVal: return bool(x) @@ -610,7 +610,7 @@ func Val(x Value) interface{} { // *big.Rat Float // anything else Unknown // -func Make(x interface{}) Value { +func Make(x any) Value { switch x := x.(type) { case bool: return boolVal(x) diff --git a/src/go/constant/value_test.go b/src/go/constant/value_test.go index ac179b3d8c..e41315ee27 100644 --- a/src/go/constant/value_test.go +++ b/src/go/constant/value_test.go @@ -659,10 +659,10 @@ func TestMakeFloat64(t *testing.T) { type makeTestCase struct { kind Kind - arg, want interface{} + arg, want any } -func dup(k Kind, x interface{}) makeTestCase { return makeTestCase{k, x, x} } +func dup(k Kind, x any) makeTestCase { return makeTestCase{k, x, x} } func TestMake(t *testing.T) { for _, test := range []makeTestCase{ diff --git a/src/go/doc/doc.go b/src/go/doc/doc.go index 79d38998e7..5ab854d084 100644 --- a/src/go/doc/doc.go +++ b/src/go/doc/doc.go @@ -157,7 +157,7 @@ func New(pkg *ast.Package, importPath string, mode Mode) *Package { // NewFromFiles takes ownership of the AST files and may edit them, // unless the PreserveAST Mode bit is on. // -func NewFromFiles(fset *token.FileSet, files []*ast.File, importPath string, opts ...interface{}) (*Package, error) { +func NewFromFiles(fset *token.FileSet, files []*ast.File, importPath string, opts ...any) (*Package, error) { // Check for invalid API usage. if fset == nil { panic(fmt.Errorf("doc.NewFromFiles: no token.FileSet provided (fset == nil)")) diff --git a/src/go/doc/doc_test.go b/src/go/doc/doc_test.go index cbdca62aa1..3d17036f01 100644 --- a/src/go/doc/doc_test.go +++ b/src/go/doc/doc_test.go @@ -38,7 +38,7 @@ func readTemplate(filename string) *template.Template { return template.Must(t.ParseFiles(filepath.Join(dataDir, filename))) } -func nodeFmt(node interface{}, fset *token.FileSet) string { +func nodeFmt(node any, fset *token.FileSet) string { var buf bytes.Buffer printer.Fprint(&buf, fset, node) return strings.ReplaceAll(strings.TrimSpace(buf.String()), "\n", "\n\t") diff --git a/src/go/doc/testdata/benchmark.go b/src/go/doc/testdata/benchmark.go index 1d581f057e..d27bf116aa 100644 --- a/src/go/doc/testdata/benchmark.go +++ b/src/go/doc/testdata/benchmark.go @@ -232,7 +232,7 @@ func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks [ runtime.GOMAXPROCS(procs) b := &B{ common: common{ - signal: make(chan interface{}), + signal: make(chan any), }, benchmark: Benchmark, } @@ -285,7 +285,7 @@ func (b *B) trimOutput() { func Benchmark(f func(b *B)) BenchmarkResult { b := &B{ common: common{ - signal: make(chan interface{}), + signal: make(chan any), }, benchmark: InternalBenchmark{"", f}, } diff --git a/src/go/doc/testdata/testing.0.golden b/src/go/doc/testdata/testing.0.golden index 83cf37cd3a..61dac8bb66 100644 --- a/src/go/doc/testdata/testing.0.golden +++ b/src/go/doc/testdata/testing.0.golden @@ -46,10 +46,10 @@ TYPES } // Error is equivalent to Log() followed by Fail(). - func (c *B) Error(args ...interface{}) + func (c *B) Error(args ...any) // Errorf is equivalent to Logf() followed by Fail(). - func (c *B) Errorf(format string, args ...interface{}) + func (c *B) Errorf(format string, args ...any) // Fail marks the function as having failed but continues ... func (c *B) Fail() @@ -61,16 +61,16 @@ TYPES func (c *B) Failed() bool // Fatal is equivalent to Log() followed by FailNow(). - func (c *B) Fatal(args ...interface{}) + func (c *B) Fatal(args ...any) // Fatalf is equivalent to Logf() followed by FailNow(). - func (c *B) Fatalf(format string, args ...interface{}) + func (c *B) Fatalf(format string, args ...any) // Log formats its arguments using default formatting, analogous ... - func (c *B) Log(args ...interface{}) + func (c *B) Log(args ...any) // Logf formats its arguments according to the format, analogous ... - func (c *B) Logf(format string, args ...interface{}) + func (c *B) Logf(format string, args ...any) // ResetTimer sets the elapsed benchmark time to zero. It does not ... func (b *B) ResetTimer() @@ -125,10 +125,10 @@ TYPES } // Error is equivalent to Log() followed by Fail(). - func (c *T) Error(args ...interface{}) + func (c *T) Error(args ...any) // Errorf is equivalent to Logf() followed by Fail(). - func (c *T) Errorf(format string, args ...interface{}) + func (c *T) Errorf(format string, args ...any) // Fail marks the function as having failed but continues ... func (c *T) Fail() @@ -140,16 +140,16 @@ TYPES func (c *T) Failed() bool // Fatal is equivalent to Log() followed by FailNow(). - func (c *T) Fatal(args ...interface{}) + func (c *T) Fatal(args ...any) // Fatalf is equivalent to Logf() followed by FailNow(). - func (c *T) Fatalf(format string, args ...interface{}) + func (c *T) Fatalf(format string, args ...any) // Log formats its arguments using default formatting, analogous ... - func (c *T) Log(args ...interface{}) + func (c *T) Log(args ...any) // Logf formats its arguments according to the format, analogous ... - func (c *T) Logf(format string, args ...interface{}) + func (c *T) Logf(format string, args ...any) // Parallel signals that this test is to be run in parallel with ... func (t *T) Parallel() diff --git a/src/go/doc/testdata/testing.1.golden b/src/go/doc/testdata/testing.1.golden index b9d14517a9..1655af11a8 100644 --- a/src/go/doc/testdata/testing.1.golden +++ b/src/go/doc/testdata/testing.1.golden @@ -119,10 +119,10 @@ TYPES } // Error is equivalent to Log() followed by Fail(). - func (c *B) Error(args ...interface{}) + func (c *B) Error(args ...any) // Errorf is equivalent to Logf() followed by Fail(). - func (c *B) Errorf(format string, args ...interface{}) + func (c *B) Errorf(format string, args ...any) // Fail marks the function as having failed but continues ... func (c *B) Fail() @@ -134,16 +134,16 @@ TYPES func (c *B) Failed() bool // Fatal is equivalent to Log() followed by FailNow(). - func (c *B) Fatal(args ...interface{}) + func (c *B) Fatal(args ...any) // Fatalf is equivalent to Logf() followed by FailNow(). - func (c *B) Fatalf(format string, args ...interface{}) + func (c *B) Fatalf(format string, args ...any) // Log formats its arguments using default formatting, analogous ... - func (c *B) Log(args ...interface{}) + func (c *B) Log(args ...any) // Logf formats its arguments according to the format, analogous ... - func (c *B) Logf(format string, args ...interface{}) + func (c *B) Logf(format string, args ...any) // ResetTimer sets the elapsed benchmark time to zero. It does not ... func (b *B) ResetTimer() @@ -221,10 +221,10 @@ TYPES } // Error is equivalent to Log() followed by Fail(). - func (c *T) Error(args ...interface{}) + func (c *T) Error(args ...any) // Errorf is equivalent to Logf() followed by Fail(). - func (c *T) Errorf(format string, args ...interface{}) + func (c *T) Errorf(format string, args ...any) // Fail marks the function as having failed but continues ... func (c *T) Fail() @@ -236,16 +236,16 @@ TYPES func (c *T) Failed() bool // Fatal is equivalent to Log() followed by FailNow(). - func (c *T) Fatal(args ...interface{}) + func (c *T) Fatal(args ...any) // Fatalf is equivalent to Logf() followed by FailNow(). - func (c *T) Fatalf(format string, args ...interface{}) + func (c *T) Fatalf(format string, args ...any) // Log formats its arguments using default formatting, analogous ... - func (c *T) Log(args ...interface{}) + func (c *T) Log(args ...any) // Logf formats its arguments according to the format, analogous ... - func (c *T) Logf(format string, args ...interface{}) + func (c *T) Logf(format string, args ...any) // Parallel signals that this test is to be run in parallel with ... func (t *T) Parallel() @@ -262,15 +262,15 @@ TYPES failed bool // Test or benchmark has failed. start time.Time // Time test or benchmark started duration time.Duration - self interface{} // To be sent on signal channel when done. - signal chan interface{} // Output for serial tests. + self any // To be sent on signal channel when done. + signal chan any // Output for serial tests. } // Error is equivalent to Log() followed by Fail(). - func (c *common) Error(args ...interface{}) + func (c *common) Error(args ...any) // Errorf is equivalent to Logf() followed by Fail(). - func (c *common) Errorf(format string, args ...interface{}) + func (c *common) Errorf(format string, args ...any) // Fail marks the function as having failed but continues ... func (c *common) Fail() @@ -282,16 +282,16 @@ TYPES func (c *common) Failed() bool // Fatal is equivalent to Log() followed by FailNow(). - func (c *common) Fatal(args ...interface{}) + func (c *common) Fatal(args ...any) // Fatalf is equivalent to Logf() followed by FailNow(). - func (c *common) Fatalf(format string, args ...interface{}) + func (c *common) Fatalf(format string, args ...any) // Log formats its arguments using default formatting, analogous ... - func (c *common) Log(args ...interface{}) + func (c *common) Log(args ...any) // Logf formats its arguments according to the format, analogous ... - func (c *common) Logf(format string, args ...interface{}) + func (c *common) Logf(format string, args ...any) // log generates the output. It's always at the same stack depth. func (c *common) log(s string) diff --git a/src/go/doc/testdata/testing.2.golden b/src/go/doc/testdata/testing.2.golden index 83cf37cd3a..61dac8bb66 100644 --- a/src/go/doc/testdata/testing.2.golden +++ b/src/go/doc/testdata/testing.2.golden @@ -46,10 +46,10 @@ TYPES } // Error is equivalent to Log() followed by Fail(). - func (c *B) Error(args ...interface{}) + func (c *B) Error(args ...any) // Errorf is equivalent to Logf() followed by Fail(). - func (c *B) Errorf(format string, args ...interface{}) + func (c *B) Errorf(format string, args ...any) // Fail marks the function as having failed but continues ... func (c *B) Fail() @@ -61,16 +61,16 @@ TYPES func (c *B) Failed() bool // Fatal is equivalent to Log() followed by FailNow(). - func (c *B) Fatal(args ...interface{}) + func (c *B) Fatal(args ...any) // Fatalf is equivalent to Logf() followed by FailNow(). - func (c *B) Fatalf(format string, args ...interface{}) + func (c *B) Fatalf(format string, args ...any) // Log formats its arguments using default formatting, analogous ... - func (c *B) Log(args ...interface{}) + func (c *B) Log(args ...any) // Logf formats its arguments according to the format, analogous ... - func (c *B) Logf(format string, args ...interface{}) + func (c *B) Logf(format string, args ...any) // ResetTimer sets the elapsed benchmark time to zero. It does not ... func (b *B) ResetTimer() @@ -125,10 +125,10 @@ TYPES } // Error is equivalent to Log() followed by Fail(). - func (c *T) Error(args ...interface{}) + func (c *T) Error(args ...any) // Errorf is equivalent to Logf() followed by Fail(). - func (c *T) Errorf(format string, args ...interface{}) + func (c *T) Errorf(format string, args ...any) // Fail marks the function as having failed but continues ... func (c *T) Fail() @@ -140,16 +140,16 @@ TYPES func (c *T) Failed() bool // Fatal is equivalent to Log() followed by FailNow(). - func (c *T) Fatal(args ...interface{}) + func (c *T) Fatal(args ...any) // Fatalf is equivalent to Logf() followed by FailNow(). - func (c *T) Fatalf(format string, args ...interface{}) + func (c *T) Fatalf(format string, args ...any) // Log formats its arguments using default formatting, analogous ... - func (c *T) Log(args ...interface{}) + func (c *T) Log(args ...any) // Logf formats its arguments according to the format, analogous ... - func (c *T) Logf(format string, args ...interface{}) + func (c *T) Logf(format string, args ...any) // Parallel signals that this test is to be run in parallel with ... func (t *T) Parallel() diff --git a/src/go/doc/testdata/testing.go b/src/go/doc/testdata/testing.go index 52810f7a56..80238df283 100644 --- a/src/go/doc/testdata/testing.go +++ b/src/go/doc/testdata/testing.go @@ -77,8 +77,8 @@ type common struct { failed bool // Test or benchmark has failed. start time.Time // Time test or benchmark started duration time.Duration - self interface{} // To be sent on signal channel when done. - signal chan interface{} // Output for serial tests. + self any // To be sent on signal channel when done. + signal chan any // Output for serial tests. } // Short reports whether the -test.short flag is set. @@ -167,32 +167,32 @@ func (c *common) log(s string) { // Log formats its arguments using default formatting, analogous to Println(), // and records the text in the error log. -func (c *common) Log(args ...interface{}) { c.log(fmt.Sprintln(args...)) } +func (c *common) Log(args ...any) { c.log(fmt.Sprintln(args...)) } // Logf formats its arguments according to the format, analogous to Printf(), // and records the text in the error log. -func (c *common) Logf(format string, args ...interface{}) { c.log(fmt.Sprintf(format, args...)) } +func (c *common) Logf(format string, args ...any) { c.log(fmt.Sprintf(format, args...)) } // Error is equivalent to Log() followed by Fail(). -func (c *common) Error(args ...interface{}) { +func (c *common) Error(args ...any) { c.log(fmt.Sprintln(args...)) c.Fail() } // Errorf is equivalent to Logf() followed by Fail(). -func (c *common) Errorf(format string, args ...interface{}) { +func (c *common) Errorf(format string, args ...any) { c.log(fmt.Sprintf(format, args...)) c.Fail() } // Fatal is equivalent to Log() followed by FailNow(). -func (c *common) Fatal(args ...interface{}) { +func (c *common) Fatal(args ...any) { c.log(fmt.Sprintln(args...)) c.FailNow() } // Fatalf is equivalent to Logf() followed by FailNow(). -func (c *common) Fatalf(format string, args ...interface{}) { +func (c *common) Fatalf(format string, args ...any) { c.log(fmt.Sprintf(format, args...)) c.FailNow() } @@ -269,7 +269,7 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT // If all tests pump to the same channel, a bug can occur where a test // kicks off a goroutine that Fails, yet the test still delivers a completion signal, // which skews the counting. - var collector = make(chan interface{}) + var collector = make(chan any) numParallel := 0 startParallel := make(chan bool) @@ -289,7 +289,7 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT } t := &T{ common: common{ - signal: make(chan interface{}), + signal: make(chan any), }, name: testName, startParallel: startParallel, diff --git a/src/go/format/format.go b/src/go/format/format.go index a603d9630e..ea8dd20823 100644 --- a/src/go/format/format.go +++ b/src/go/format/format.go @@ -51,7 +51,7 @@ const parserMode = parser.ParseComments // The function may return early (before the entire result is written) // and return a formatting error, for instance due to an incorrect AST. // -func Node(dst io.Writer, fset *token.FileSet, node interface{}) error { +func Node(dst io.Writer, fset *token.FileSet, node any) error { // Determine if we have a complete source file (file != nil). var file *ast.File var cnode *printer.CommentedNode diff --git a/src/go/internal/gccgoimporter/parser.go b/src/go/internal/gccgoimporter/parser.go index 267c9953e4..48335fa6d8 100644 --- a/src/go/internal/gccgoimporter/parser.go +++ b/src/go/internal/gccgoimporter/parser.go @@ -80,7 +80,7 @@ func (e importError) Error() string { return fmt.Sprintf("import error %s (byte offset = %d): %s", e.pos, e.pos.Offset, e.err) } -func (p *parser) error(err interface{}) { +func (p *parser) error(err any) { if s, ok := err.(string); ok { err = errors.New(s) } @@ -88,7 +88,7 @@ func (p *parser) error(err interface{}) { panic(importError{p.scanner.Pos(), err.(error)}) } -func (p *parser) errorf(format string, args ...interface{}) { +func (p *parser) errorf(format string, args ...any) { p.error(fmt.Errorf(format, args...)) } @@ -474,7 +474,7 @@ func (p *parser) reserve(n int) { // used to resolve named types, or it can be a *types.Pointer, // used to resolve pointers to named types in case they are referenced // by embedded fields. -func (p *parser) update(t types.Type, nlist []interface{}) { +func (p *parser) update(t types.Type, nlist []any) { if t == reserved { p.errorf("internal error: update(%v) invoked on reserved", nlist) } @@ -509,7 +509,7 @@ func (p *parser) update(t types.Type, nlist []interface{}) { // NamedType = TypeName [ "=" ] Type { Method } . // TypeName = ExportedName . // Method = "func" "(" Param ")" Name ParamList ResultList [InlineBody] ";" . -func (p *parser) parseNamedType(nlist []interface{}) types.Type { +func (p *parser) parseNamedType(nlist []any) types.Type { pkg, name := p.parseExportedName() scope := pkg.Scope() obj := scope.Lookup(name) @@ -626,7 +626,7 @@ func (p *parser) parseInt() int { } // ArrayOrSliceType = "[" [ int ] "]" Type . -func (p *parser) parseArrayOrSliceType(pkg *types.Package, nlist []interface{}) types.Type { +func (p *parser) parseArrayOrSliceType(pkg *types.Package, nlist []any) types.Type { p.expect('[') if p.tok == ']' { p.next() @@ -649,7 +649,7 @@ func (p *parser) parseArrayOrSliceType(pkg *types.Package, nlist []interface{}) } // MapType = "map" "[" Type "]" Type . -func (p *parser) parseMapType(pkg *types.Package, nlist []interface{}) types.Type { +func (p *parser) parseMapType(pkg *types.Package, nlist []any) types.Type { p.expectKeyword("map") t := new(types.Map) @@ -665,7 +665,7 @@ func (p *parser) parseMapType(pkg *types.Package, nlist []interface{}) types.Typ } // ChanType = "chan" ["<-" | "-<"] Type . -func (p *parser) parseChanType(pkg *types.Package, nlist []interface{}) types.Type { +func (p *parser) parseChanType(pkg *types.Package, nlist []any) types.Type { p.expectKeyword("chan") t := new(types.Chan) @@ -692,7 +692,7 @@ func (p *parser) parseChanType(pkg *types.Package, nlist []interface{}) types.Ty } // StructType = "struct" "{" { Field } "}" . -func (p *parser) parseStructType(pkg *types.Package, nlist []interface{}) types.Type { +func (p *parser) parseStructType(pkg *types.Package, nlist []any) types.Type { p.expectKeyword("struct") t := new(types.Struct) @@ -759,7 +759,7 @@ func (p *parser) parseResultList(pkg *types.Package) *types.Tuple { } // FunctionType = ParamList ResultList . -func (p *parser) parseFunctionType(pkg *types.Package, nlist []interface{}) *types.Signature { +func (p *parser) parseFunctionType(pkg *types.Package, nlist []any) *types.Signature { t := new(types.Signature) p.update(t, nlist) @@ -799,7 +799,7 @@ func (p *parser) parseFunc(pkg *types.Package) *types.Func { } // InterfaceType = "interface" "{" { ("?" Type | Func) ";" } "}" . -func (p *parser) parseInterfaceType(pkg *types.Package, nlist []interface{}) types.Type { +func (p *parser) parseInterfaceType(pkg *types.Package, nlist []any) types.Type { p.expectKeyword("interface") t := new(types.Interface) @@ -828,7 +828,7 @@ func (p *parser) parseInterfaceType(pkg *types.Package, nlist []interface{}) typ } // PointerType = "*" ("any" | Type) . -func (p *parser) parsePointerType(pkg *types.Package, nlist []interface{}) types.Type { +func (p *parser) parsePointerType(pkg *types.Package, nlist []any) types.Type { p.expect('*') if p.tok == scanner.Ident { p.expectKeyword("any") @@ -846,7 +846,7 @@ func (p *parser) parsePointerType(pkg *types.Package, nlist []interface{}) types } // TypeSpec = NamedType | MapType | ChanType | StructType | InterfaceType | PointerType | ArrayOrSliceType | FunctionType . -func (p *parser) parseTypeSpec(pkg *types.Package, nlist []interface{}) types.Type { +func (p *parser) parseTypeSpec(pkg *types.Package, nlist []any) types.Type { switch p.tok { case scanner.String: return p.parseNamedType(nlist) @@ -935,14 +935,14 @@ func lookupBuiltinType(typ int) types.Type { // // parseType updates the type map to t for all type numbers n. // -func (p *parser) parseType(pkg *types.Package, n ...interface{}) types.Type { +func (p *parser) parseType(pkg *types.Package, n ...any) types.Type { p.expect('<') t, _ := p.parseTypeAfterAngle(pkg, n...) return t } // (*parser).Type after reading the "<". -func (p *parser) parseTypeAfterAngle(pkg *types.Package, n ...interface{}) (t types.Type, n1 int) { +func (p *parser) parseTypeAfterAngle(pkg *types.Package, n ...any) (t types.Type, n1 int) { p.expectKeyword("type") n1 = 0 @@ -985,7 +985,7 @@ func (p *parser) parseTypeAfterAngle(pkg *types.Package, n ...interface{}) (t ty // parseTypeExtended is identical to parseType, but if the type in // question is a saved type, returns the index as well as the type // pointer (index returned is zero if we parsed a builtin). -func (p *parser) parseTypeExtended(pkg *types.Package, n ...interface{}) (t types.Type, n1 int) { +func (p *parser) parseTypeExtended(pkg *types.Package, n ...any) (t types.Type, n1 int) { p.expect('<') t, n1 = p.parseTypeAfterAngle(pkg, n...) return @@ -1072,7 +1072,7 @@ func (p *parser) parseTypes(pkg *types.Package) { } // parseSavedType parses one saved type definition. -func (p *parser) parseSavedType(pkg *types.Package, i int, nlist []interface{}) { +func (p *parser) parseSavedType(pkg *types.Package, i int, nlist []any) { defer func(s *scanner.Scanner, tok rune, lit string) { p.scanner = s p.tok = tok diff --git a/src/go/internal/gcimporter/gcimporter_test.go b/src/go/internal/gcimporter/gcimporter_test.go index c0f4e3934b..15a7b176bb 100644 --- a/src/go/internal/gcimporter/gcimporter_test.go +++ b/src/go/internal/gcimporter/gcimporter_test.go @@ -390,7 +390,7 @@ var importedObjectTests = []struct { {"go/internal/gcimporter.FindPkg", "func FindPkg(path string, srcDir string) (filename string, id string)"}, // interfaces - {"context.Context", "type Context interface{Deadline() (deadline time.Time, ok bool); Done() <-chan struct{}; Err() error; Value(key interface{}) interface{}}"}, + {"context.Context", "type Context interface{Deadline() (deadline time.Time, ok bool); Done() <-chan struct{}; Err() error; Value(key any) any}"}, {"crypto.Decrypter", "type Decrypter interface{Decrypt(rand io.Reader, msg []byte, opts DecrypterOpts) (plaintext []byte, err error); Public() PublicKey}"}, {"encoding.BinaryMarshaler", "type BinaryMarshaler interface{MarshalBinary() (data []byte, err error)}"}, {"io.Reader", "type Reader interface{Read(p []byte) (n int, err error)}"}, diff --git a/src/go/internal/gcimporter/support.go b/src/go/internal/gcimporter/support.go index 965e5d8838..61d1b46a68 100644 --- a/src/go/internal/gcimporter/support.go +++ b/src/go/internal/gcimporter/support.go @@ -13,7 +13,7 @@ import ( "sync" ) -func errorf(format string, args ...interface{}) { +func errorf(format string, args ...any) { panic(fmt.Sprintf(format, args...)) } diff --git a/src/go/internal/gcimporter/testdata/exports.go b/src/go/internal/gcimporter/testdata/exports.go index 91598c03e3..3d5a8c9e39 100644 --- a/src/go/internal/gcimporter/testdata/exports.go +++ b/src/go/internal/gcimporter/testdata/exports.go @@ -50,7 +50,7 @@ type ( _ *T10 } T11 map[int]string - T12 interface{} + T12 any T13 interface { m1() m2(int) float32 @@ -65,7 +65,7 @@ type ( T17 func(x int) T18 func() float32 T19 func() (x float32) - T20 func(...interface{}) + T20 func(...any) T21 struct{ next *T21 } T22 struct{ link *T23 } T23 struct{ link *T22 } @@ -86,6 +86,6 @@ func F1() {} func F2(x int) {} func F3() int { return 0 } func F4() float32 { return 0 } -func F5(a, b, c int, u, v, w struct{ x, y T1 }, more ...interface{}) (p, q, r chan<- T10) +func F5(a, b, c int, u, v, w struct{ x, y T1 }, more ...any) (p, q, r chan<- T10) func (p *T1) M1() diff --git a/src/go/parser/error_test.go b/src/go/parser/error_test.go index a45c897da3..bedfc265b5 100644 --- a/src/go/parser/error_test.go +++ b/src/go/parser/error_test.go @@ -154,7 +154,7 @@ func compareErrors(t *testing.T, fset *token.FileSet, expected map[token.Pos]str } } -func checkErrors(t *testing.T, filename string, input interface{}, mode Mode, expectErrors bool) { +func checkErrors(t *testing.T, filename string, input any, mode Mode, expectErrors bool) { t.Helper() src, err := readSource(filename, input) if err != nil { diff --git a/src/go/parser/interface.go b/src/go/parser/interface.go index 85486d2f4b..e4f8c281ea 100644 --- a/src/go/parser/interface.go +++ b/src/go/parser/interface.go @@ -22,7 +22,7 @@ import ( // otherwise it returns an error. If src == nil, readSource returns // the result of reading the file specified by filename. // -func readSource(filename string, src interface{}) ([]byte, error) { +func readSource(filename string, src any) ([]byte, error) { if src != nil { switch s := src.(type) { case string: @@ -82,7 +82,7 @@ const ( // representing the fragments of erroneous source code). Multiple errors // are returned via a scanner.ErrorList which is sorted by source position. // -func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode) (f *ast.File, err error) { +func ParseFile(fset *token.FileSet, filename string, src any, mode Mode) (f *ast.File, err error) { if fset == nil { panic("parser.ParseFile: no token.FileSet provided (fset == nil)") } @@ -188,7 +188,7 @@ func ParseDir(fset *token.FileSet, path string, filter func(fs.FileInfo) bool, m // representing the fragments of erroneous source code). Multiple errors // are returned via a scanner.ErrorList which is sorted by source position. // -func ParseExprFrom(fset *token.FileSet, filename string, src interface{}, mode Mode) (expr ast.Expr, err error) { +func ParseExprFrom(fset *token.FileSet, filename string, src any, mode Mode) (expr ast.Expr, err error) { if fset == nil { panic("parser.ParseExprFrom: no token.FileSet provided (fset == nil)") } diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go index 7c1a8be2fa..e456e2930e 100644 --- a/src/go/parser/parser.go +++ b/src/go/parser/parser.go @@ -82,7 +82,7 @@ func (p *parser) allowTypeSets() bool { return p.mode&typeparams.DisallowTypeSet // ---------------------------------------------------------------------------- // Parsing support -func (p *parser) printTrace(a ...interface{}) { +func (p *parser) printTrace(a ...any) { const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " const n = len(dots) pos := p.file.Position(p.pos) diff --git a/src/go/parser/resolver.go b/src/go/parser/resolver.go index 54732a7fd6..910ca0689c 100644 --- a/src/go/parser/resolver.go +++ b/src/go/parser/resolver.go @@ -67,11 +67,11 @@ type resolver struct { targetStack [][]*ast.Ident // stack of unresolved labels } -func (r *resolver) dump(format string, args ...interface{}) { +func (r *resolver) dump(format string, args ...any) { fmt.Println(">>> " + r.sprintf(format, args...)) } -func (r *resolver) sprintf(format string, args ...interface{}) string { +func (r *resolver) sprintf(format string, args ...any) string { for i, arg := range args { switch arg := arg.(type) { case token.Pos: @@ -115,7 +115,7 @@ func (r *resolver) closeLabelScope() { r.labelScope = r.labelScope.Outer } -func (r *resolver) declare(decl, data interface{}, scope *ast.Scope, kind ast.ObjKind, idents ...*ast.Ident) { +func (r *resolver) declare(decl, data any, scope *ast.Scope, kind ast.ObjKind, idents ...*ast.Ident) { for _, ident := range idents { assert(ident.Obj == nil, "identifier already declared or resolved") obj := ast.NewObj(kind, ident.Name) diff --git a/src/go/printer/printer.go b/src/go/printer/printer.go index 2f41e7bf72..e4679b0021 100644 --- a/src/go/printer/printer.go +++ b/src/go/printer/printer.go @@ -104,7 +104,7 @@ func (p *printer) init(cfg *Config, fset *token.FileSet, nodeSizes map[ast.Node] p.cachedPos = -1 } -func (p *printer) internalError(msg ...interface{}) { +func (p *printer) internalError(msg ...any) { if debug { fmt.Print(p.pos.String() + ": ") fmt.Println(msg...) @@ -878,7 +878,7 @@ func mayCombine(prev token.Token, next byte) (b bool) { // space for best comment placement. Then, any leftover whitespace is // printed, followed by the actual token. // -func (p *printer) print(args ...interface{}) { +func (p *printer) print(args ...any) { for _, arg := range args { // information about the current arg var data string @@ -1075,7 +1075,7 @@ func getLastComment(n ast.Node) *ast.CommentGroup { return nil } -func (p *printer) printNode(node interface{}) error { +func (p *printer) printNode(node any) error { // unpack *CommentedNode, if any var comments []*ast.CommentGroup if cnode, ok := node.(*CommentedNode); ok { @@ -1309,7 +1309,7 @@ type Config struct { } // fprint implements Fprint and takes a nodesSizes map for setting up the printer state. -func (cfg *Config) fprint(output io.Writer, fset *token.FileSet, node interface{}, nodeSizes map[ast.Node]int) (err error) { +func (cfg *Config) fprint(output io.Writer, fset *token.FileSet, node any, nodeSizes map[ast.Node]int) (err error) { // print node var p printer p.init(cfg, fset, nodeSizes) @@ -1365,7 +1365,7 @@ func (cfg *Config) fprint(output io.Writer, fset *token.FileSet, node interface{ // It may be provided as argument to any of the Fprint functions. // type CommentedNode struct { - Node interface{} // *ast.File, or ast.Expr, ast.Decl, ast.Spec, or ast.Stmt + Node any // *ast.File, or ast.Expr, ast.Decl, ast.Spec, or ast.Stmt Comments []*ast.CommentGroup } @@ -1374,7 +1374,7 @@ type CommentedNode struct { // The node type must be *ast.File, *CommentedNode, []ast.Decl, []ast.Stmt, // or assignment-compatible to ast.Expr, ast.Decl, ast.Spec, or ast.Stmt. // -func (cfg *Config) Fprint(output io.Writer, fset *token.FileSet, node interface{}) error { +func (cfg *Config) Fprint(output io.Writer, fset *token.FileSet, node any) error { return cfg.fprint(output, fset, node, make(map[ast.Node]int)) } @@ -1383,6 +1383,6 @@ func (cfg *Config) Fprint(output io.Writer, fset *token.FileSet, node interface{ // Note that gofmt uses tabs for indentation but spaces for alignment; // use format.Node (package go/format) for output that matches gofmt. // -func Fprint(output io.Writer, fset *token.FileSet, node interface{}) error { +func Fprint(output io.Writer, fset *token.FileSet, node any) error { return (&Config{Tabwidth: 8}).Fprint(output, fset, node) } diff --git a/src/go/printer/testdata/parser.go b/src/go/printer/testdata/parser.go index fc2812adee..7e8379739c 100644 --- a/src/go/printer/testdata/parser.go +++ b/src/go/printer/testdata/parser.go @@ -122,7 +122,7 @@ func (p *parser) closeLabelScope() { p.labelScope = p.labelScope.Outer } -func (p *parser) declare(decl interface{}, scope *ast.Scope, kind ast.ObjKind, idents ...*ast.Ident) { +func (p *parser) declare(decl any, scope *ast.Scope, kind ast.ObjKind, idents ...*ast.Ident) { for _, ident := range idents { assert(ident.Obj == nil, "identifier already declared or resolved") if ident.Name != "_" { @@ -200,7 +200,7 @@ func (p *parser) resolve(x ast.Expr) { // ---------------------------------------------------------------------------- // Parsing support -func (p *parser) printTrace(a ...interface{}) { +func (p *parser) printTrace(a ...any) { const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " + ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " const n = uint(len(dots)) diff --git a/src/go/scanner/scanner.go b/src/go/scanner/scanner.go index ca4b5264cf..23d8db9d1c 100644 --- a/src/go/scanner/scanner.go +++ b/src/go/scanner/scanner.go @@ -155,7 +155,7 @@ func (s *Scanner) error(offs int, msg string) { s.ErrorCount++ } -func (s *Scanner) errorf(offs int, format string, args ...interface{}) { +func (s *Scanner) errorf(offs int, format string, args ...any) { s.error(offs, fmt.Sprintf(format, args...)) } diff --git a/src/go/token/serialize.go b/src/go/token/serialize.go index d0ea34517a..ffb69908b9 100644 --- a/src/go/token/serialize.go +++ b/src/go/token/serialize.go @@ -19,7 +19,7 @@ type serializedFileSet struct { } // Read calls decode to deserialize a file set into s; s must not be nil. -func (s *FileSet) Read(decode func(interface{}) error) error { +func (s *FileSet) Read(decode func(any) error) error { var ss serializedFileSet if err := decode(&ss); err != nil { return err @@ -47,7 +47,7 @@ func (s *FileSet) Read(decode func(interface{}) error) error { } // Write calls encode to serialize the file set s. -func (s *FileSet) Write(encode func(interface{}) error) error { +func (s *FileSet) Write(encode func(any) error) error { var ss serializedFileSet s.mutex.Lock() diff --git a/src/go/token/serialize_test.go b/src/go/token/serialize_test.go index 4e925adb6f..4aa0b0da26 100644 --- a/src/go/token/serialize_test.go +++ b/src/go/token/serialize_test.go @@ -70,7 +70,7 @@ func equal(p, q *FileSet) error { func checkSerialize(t *testing.T, p *FileSet) { var buf bytes.Buffer - encode := func(x interface{}) error { + encode := func(x any) error { return gob.NewEncoder(&buf).Encode(x) } if err := p.Write(encode); err != nil { @@ -78,7 +78,7 @@ func checkSerialize(t *testing.T, p *FileSet) { return } q := NewFileSet() - decode := func(x interface{}) error { + decode := func(x any) error { return gob.NewDecoder(&buf).Decode(x) } if err := q.Read(decode); err != nil { diff --git a/src/go/types/check.go b/src/go/types/check.go index d967c0bd25..2dd38e2e1e 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -90,7 +90,7 @@ type action struct { // If debug is set, describef sets a printf-formatted description for action a. // Otherwise, it is a no-op. -func (a *action) describef(pos positioner, format string, args ...interface{}) { +func (a *action) describef(pos positioner, format string, args ...any) { if debug { a.desc = &actionDesc{pos, format, args} } @@ -101,7 +101,7 @@ func (a *action) describef(pos positioner, format string, args ...interface{}) { type actionDesc struct { pos positioner format string - args []interface{} + args []any } // A Checker maintains the state of the type checker. diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go index fb3771635d..a5b359e539 100644 --- a/src/go/types/conversions.go +++ b/src/go/types/conversions.go @@ -203,7 +203,7 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool { return false } - errorf := func(format string, args ...interface{}) { + errorf := func(format string, args ...any) { if check != nil && cause != nil { msg := check.sprintf(format, args...) if *cause != "" { diff --git a/src/go/types/errors.go b/src/go/types/errors.go index 92002add13..81c62a82f0 100644 --- a/src/go/types/errors.go +++ b/src/go/types/errors.go @@ -62,11 +62,11 @@ func (check *Checker) markImports(pkg *Package) { } } -func (check *Checker) sprintf(format string, args ...interface{}) string { +func (check *Checker) sprintf(format string, args ...any) string { return sprintf(check.fset, check.qualifier, false, format, args...) } -func sprintf(fset *token.FileSet, qf Qualifier, debug bool, format string, args ...interface{}) string { +func sprintf(fset *token.FileSet, qf Qualifier, debug bool, format string, args ...any) string { for i, arg := range args { switch a := arg.(type) { case nil: @@ -91,7 +91,7 @@ func sprintf(fset *token.FileSet, qf Qualifier, debug bool, format string, args return fmt.Sprintf(format, args...) } -func (check *Checker) trace(pos token.Pos, format string, args ...interface{}) { +func (check *Checker) trace(pos token.Pos, format string, args ...any) { fmt.Printf("%s:\t%s%s\n", check.fset.Position(pos), strings.Repeat(". ", check.indent), @@ -100,7 +100,7 @@ func (check *Checker) trace(pos token.Pos, format string, args ...interface{}) { } // dump is only needed for debugging -func (check *Checker) dump(format string, args ...interface{}) { +func (check *Checker) dump(format string, args ...any) { fmt.Println(sprintf(check.fset, check.qualifier, true, format, args...)) } @@ -170,7 +170,7 @@ func (check *Checker) newError(at positioner, code errorCode, soft bool, msg str } // newErrorf creates a new Error, but does not handle it. -func (check *Checker) newErrorf(at positioner, code errorCode, soft bool, format string, args ...interface{}) error { +func (check *Checker) newErrorf(at positioner, code errorCode, soft bool, format string, args ...any) error { msg := check.sprintf(format, args...) return check.newError(at, code, soft, msg) } @@ -179,23 +179,23 @@ func (check *Checker) error(at positioner, code errorCode, msg string) { check.err(check.newError(at, code, false, msg)) } -func (check *Checker) errorf(at positioner, code errorCode, format string, args ...interface{}) { +func (check *Checker) errorf(at positioner, code errorCode, format string, args ...any) { check.error(at, code, check.sprintf(format, args...)) } -func (check *Checker) softErrorf(at positioner, code errorCode, format string, args ...interface{}) { +func (check *Checker) softErrorf(at positioner, code errorCode, format string, args ...any) { check.err(check.newErrorf(at, code, true, format, args...)) } -func (check *Checker) invalidAST(at positioner, format string, args ...interface{}) { +func (check *Checker) invalidAST(at positioner, format string, args ...any) { check.errorf(at, 0, "invalid AST: "+format, args...) } -func (check *Checker) invalidArg(at positioner, code errorCode, format string, args ...interface{}) { +func (check *Checker) invalidArg(at positioner, code errorCode, format string, args ...any) { check.errorf(at, code, "invalid argument: "+format, args...) } -func (check *Checker) invalidOp(at positioner, code errorCode, format string, args ...interface{}) { +func (check *Checker) invalidOp(at positioner, code errorCode, format string, args ...any) { check.errorf(at, code, "invalid operation: "+format, args...) } diff --git a/src/go/types/eval_test.go b/src/go/types/eval_test.go index 345bd14305..b0745c16d9 100644 --- a/src/go/types/eval_test.go +++ b/src/go/types/eval_test.go @@ -111,7 +111,7 @@ func TestEvalPos(t *testing.T) { x = a + len(s) return float64(x) /* true => true, untyped bool */ - /* fmt.Println => , func(a ...interface{}) (n int, err error) */ + /* fmt.Println => , func(a ...any) (n int, err error) */ /* c => 3, untyped float */ /* T => , p.T */ /* a => , int */ @@ -218,7 +218,7 @@ type T []int type S struct{ X int } func f(a int, s string) S { - /* fmt.Println => func fmt.Println(a ...interface{}) (n int, err error) */ + /* fmt.Println => func fmt.Println(a ...any) (n int, err error) */ /* fmt.Stringer.String => func (fmt.Stringer).String() string */ fmt.Println("calling f") diff --git a/src/go/types/expr.go b/src/go/types/expr.go index dd18abaf13..452e9ab598 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -1354,7 +1354,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { check.error(e, _InvalidTypeCycle, "illegal cycle in type declaration") goto Error } - visited := make(map[interface{}][]Type, len(e.Elts)) + visited := make(map[any][]Type, len(e.Elts)) for _, e := range e.Elts { kv, _ := e.(*ast.KeyValueExpr) if kv == nil { @@ -1542,7 +1542,7 @@ Error: return statement // avoid follow-up errors } -func keyVal(x constant.Value) interface{} { +func keyVal(x constant.Value) any { switch x.Kind() { case constant.Bool: return constant.BoolVal(x) diff --git a/src/go/types/gotype.go b/src/go/types/gotype.go index 1126b73810..5d27bb7a07 100644 --- a/src/go/types/gotype.go +++ b/src/go/types/gotype.go @@ -179,7 +179,7 @@ func report(err error) { } // parse may be called concurrently -func parse(filename string, src interface{}) (*ast.File, error) { +func parse(filename string, src any) (*ast.File, error) { if *verbose { fmt.Println(filename) } diff --git a/src/go/types/hilbert_test.go b/src/go/types/hilbert_test.go index 77954d2f8b..7d0f58ea40 100644 --- a/src/go/types/hilbert_test.go +++ b/src/go/types/hilbert_test.go @@ -84,7 +84,7 @@ type gen struct { bytes.Buffer } -func (g *gen) p(format string, args ...interface{}) { +func (g *gen) p(format string, args ...any) { fmt.Fprintf(&g.Buffer, format, args...) } diff --git a/src/go/types/initorder.go b/src/go/types/initorder.go index 27595ae233..1118b58f7b 100644 --- a/src/go/types/initorder.go +++ b/src/go/types/initorder.go @@ -304,11 +304,11 @@ func (a nodeQueue) Less(i, j int) bool { return x.ndeps < y.ndeps || x.ndeps == y.ndeps && x.obj.order() < y.obj.order() } -func (a *nodeQueue) Push(x interface{}) { +func (a *nodeQueue) Push(x any) { panic("unreachable") } -func (a *nodeQueue) Pop() interface{} { +func (a *nodeQueue) Pop() any { n := len(*a) x := (*a)[n-1] x.index = -1 // for safety diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index e91d08cc5e..e8748975c9 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -164,7 +164,7 @@ func (check *Checker) implements(V, T Type, qf Qualifier) error { return nil } - errorf := func(format string, args ...interface{}) error { + errorf := func(format string, args ...any) error { return errors.New(sprintf(nil, qf, false, format, args...)) } diff --git a/src/go/types/operand.go b/src/go/types/operand.go index c35b1650be..06ecbf1410 100644 --- a/src/go/types/operand.go +++ b/src/go/types/operand.go @@ -337,7 +337,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er return false, _IncompatibleAssign } - errorf := func(format string, args ...interface{}) { + errorf := func(format string, args ...any) { if check != nil && reason != nil { msg := check.sprintf(format, args...) if *reason != "" { diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index 5b7ee8bb78..69571d1159 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -14,9 +14,9 @@ func TestSizeof(t *testing.T) { const _64bit = ^uint(0)>>32 != 0 var tests = []struct { - val interface{} // type as a value - _32bit uintptr // size on 32bit platforms - _64bit uintptr // size on 64bit platforms + val any // type as a value + _32bit uintptr // size on 32bit platforms + _64bit uintptr // size on 64bit platforms }{ // Types {Basic{}, 16, 32}, diff --git a/src/go/types/stdlib_test.go b/src/go/types/stdlib_test.go index 687b80540a..5e5e09562a 100644 --- a/src/go/types/stdlib_test.go +++ b/src/go/types/stdlib_test.go @@ -296,7 +296,7 @@ func pkgFilenames(dir string) ([]string, error) { return filenames, nil } -func walkPkgDirs(dir string, pkgh func(dir string, filenames []string), errh func(args ...interface{})) time.Duration { +func walkPkgDirs(dir string, pkgh func(dir string, filenames []string), errh func(args ...any)) time.Duration { w := walker{time.Now(), 10 * time.Millisecond, pkgh, errh} w.walk(dir) return time.Since(w.start) @@ -306,7 +306,7 @@ type walker struct { start time.Time dmax time.Duration pkgh func(dir string, filenames []string) - errh func(args ...interface{}) + errh func(args ...any) } func (w *walker) walk(dir string) { diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index 06c9d3175d..8621d2800a 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -193,7 +193,7 @@ func (check *Checker) suspendedCall(keyword string, call *ast.CallExpr) { } // goVal returns the Go value for val, or nil. -func goVal(val constant.Value) interface{} { +func goVal(val constant.Value) any { // val should exist, but be conservative and check if val == nil { return nil @@ -227,7 +227,7 @@ func goVal(val constant.Value) interface{} { // types we need to also check the value's types (e.g., byte(1) vs myByte(1)) // when the switch expression is of interface type. type ( - valueMap map[interface{}][]valueType // underlying Go value -> valueType + valueMap map[any][]valueType // underlying Go value -> valueType valueType struct { pos token.Pos typ Type diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 04eb3a6215..169540365b 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -156,13 +156,13 @@ func (subst *subster) typ(typ Type) Type { case *Named: // dump is for debugging - dump := func(string, ...interface{}) {} + dump := func(string, ...any) {} if subst.check != nil && trace { subst.check.indent++ defer func() { subst.check.indent-- }() - dump = func(format string, args ...interface{}) { + dump = func(format string, args ...any) { subst.check.trace(subst.pos, format, args...) } } diff --git a/src/html/template/content.go b/src/html/template/content.go index 232ba199f3..b104267177 100644 --- a/src/html/template/content.go +++ b/src/html/template/content.go @@ -112,7 +112,7 @@ const ( // indirect returns the value, after dereferencing as many times // as necessary to reach the base type (or nil). -func indirect(a interface{}) interface{} { +func indirect(a any) any { if a == nil { return nil } @@ -135,7 +135,7 @@ var ( // indirectToStringerOrError returns the value, after dereferencing as many times // as necessary to reach the base type (or nil) or an implementation of fmt.Stringer // or error, -func indirectToStringerOrError(a interface{}) interface{} { +func indirectToStringerOrError(a any) any { if a == nil { return nil } @@ -148,7 +148,7 @@ func indirectToStringerOrError(a interface{}) interface{} { // stringify converts its arguments to a string and the type of the content. // All pointers are dereferenced, as in the text/template package. -func stringify(args ...interface{}) (string, contentType) { +func stringify(args ...any) (string, contentType) { if len(args) == 1 { switch s := indirect(args[0]).(type) { case string: diff --git a/src/html/template/content_test.go b/src/html/template/content_test.go index b7a39d4814..497264ea32 100644 --- a/src/html/template/content_test.go +++ b/src/html/template/content_test.go @@ -12,7 +12,7 @@ import ( ) func TestTypedContent(t *testing.T) { - data := []interface{}{ + data := []any{ ` "foo%" O'Reilly &bar;`, CSS(`a[href =~ "//example.com"]#foo`), HTML(`Hello, World &tc!`), @@ -449,7 +449,7 @@ func TestEscapingNilNonemptyInterfaces(t *testing.T) { // A non-empty interface should print like an empty interface. want := new(bytes.Buffer) - data := struct{ E interface{} }{} + data := struct{ E any }{} tmpl.Execute(want, data) if !bytes.Equal(want.Bytes(), got.Bytes()) { diff --git a/src/html/template/css.go b/src/html/template/css.go index eb92fc92b5..890a0c6b22 100644 --- a/src/html/template/css.go +++ b/src/html/template/css.go @@ -155,7 +155,7 @@ func isCSSSpace(b byte) bool { } // cssEscaper escapes HTML and CSS special characters using \+ escapes. -func cssEscaper(args ...interface{}) string { +func cssEscaper(args ...any) string { s, _ := stringify(args...) var b strings.Builder r, w, written := rune(0), 0, 0 @@ -218,7 +218,7 @@ var mozBindingBytes = []byte("mozbinding") // (inherit, blue), and colors (#888). // It filters out unsafe values, such as those that affect token boundaries, // and anything that might execute scripts. -func cssValueFilter(args ...interface{}) string { +func cssValueFilter(args ...any) string { s, t := stringify(args...) if t == contentTypeCSS { return s diff --git a/src/html/template/error.go b/src/html/template/error.go index 0e527063ea..6bb5a2027f 100644 --- a/src/html/template/error.go +++ b/src/html/template/error.go @@ -228,6 +228,6 @@ func (e *Error) Error() string { // errorf creates an error given a format string f and args. // The template Name still needs to be supplied. -func errorf(k ErrorCode, node parse.Node, line int, f string, args ...interface{}) *Error { +func errorf(k ErrorCode, node parse.Node, line int, f string, args ...any) *Error { return &Error{k, node, "", line, fmt.Sprintf(f, args...)} } diff --git a/src/html/template/escape.go b/src/html/template/escape.go index 6dea79c7b5..2b11526f52 100644 --- a/src/html/template/escape.go +++ b/src/html/template/escape.go @@ -45,7 +45,7 @@ func escapeTemplate(tmpl *Template, node parse.Node, name string) error { // evalArgs formats the list of arguments into a string. It is equivalent to // fmt.Sprint(args...), except that it deferences all pointers. -func evalArgs(args ...interface{}) string { +func evalArgs(args ...any) string { // Optimization for simple common case of a single string argument. if len(args) == 1 { if s, ok := args[0].(string); ok { @@ -934,7 +934,7 @@ func HTMLEscapeString(s string) string { // HTMLEscaper returns the escaped HTML equivalent of the textual // representation of its arguments. -func HTMLEscaper(args ...interface{}) string { +func HTMLEscaper(args ...any) string { return template.HTMLEscaper(args...) } @@ -950,12 +950,12 @@ func JSEscapeString(s string) string { // JSEscaper returns the escaped JavaScript equivalent of the textual // representation of its arguments. -func JSEscaper(args ...interface{}) string { +func JSEscaper(args ...any) string { return template.JSEscaper(args...) } // URLQueryEscaper returns the escaped value of the textual representation of // its arguments in a form suitable for embedding in a URL query. -func URLQueryEscaper(args ...interface{}) string { +func URLQueryEscaper(args ...any) string { return template.URLQueryEscaper(args...) } diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go index 3b0aa8c846..58f3f271b7 100644 --- a/src/html/template/escape_test.go +++ b/src/html/template/escape_test.go @@ -35,8 +35,8 @@ func TestEscape(t *testing.T) { A, E []string B, M json.Marshaler N int - U interface{} // untyped nil - Z *int // typed nil + U any // untyped nil + Z *int // typed nil W HTML }{ F: false, @@ -858,7 +858,7 @@ func TestEscapeSet(t *testing.T) { // pred is a template function that returns the predecessor of a // natural number for testing recursive templates. - fns := FuncMap{"pred": func(a ...interface{}) (interface{}, error) { + fns := FuncMap{"pred": func(a ...any) (any, error) { if len(a) == 1 { if i, _ := a[0].(int); i > 0 { return i - 1, nil @@ -1788,7 +1788,7 @@ func TestEscapeSetErrorsNotIgnorable(t *testing.T) { } func TestRedundantFuncs(t *testing.T) { - inputs := []interface{}{ + inputs := []any{ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + ` !"#$%&'()*+,-./` + @@ -1808,9 +1808,9 @@ func TestRedundantFuncs(t *testing.T) { } for n0, m := range redundantFuncs { - f0 := funcMap[n0].(func(...interface{}) string) + f0 := funcMap[n0].(func(...any) string) for n1 := range m { - f1 := funcMap[n1].(func(...interface{}) string) + f1 := funcMap[n1].(func(...any) string) for _, input := range inputs { want := f0(input) if got := f1(want); want != got { diff --git a/src/html/template/example_test.go b/src/html/template/example_test.go index 6cf936f270..605b25f41d 100644 --- a/src/html/template/example_test.go +++ b/src/html/template/example_test.go @@ -98,7 +98,7 @@ func Example_autoescaping() { func Example_escape() { const s = `"Fran & Freddie's Diner" ` - v := []interface{}{`"Fran & Freddie's Diner"`, ' ', ``} + v := []any{`"Fran & Freddie's Diner"`, ' ', ``} fmt.Println(template.HTMLEscapeString(s)) template.HTMLEscape(os.Stdout, []byte(s)) diff --git a/src/html/template/exec_test.go b/src/html/template/exec_test.go index 523340bac9..6cf710efab 100644 --- a/src/html/template/exec_test.go +++ b/src/html/template/exec_test.go @@ -49,7 +49,7 @@ type T struct { MSI map[string]int MSIone map[string]int // one element, for deterministic output MSIEmpty map[string]int - MXI map[interface{}]int + MXI map[any]int MII map[int]int MI32S map[int32]string MI64S map[int64]string @@ -59,11 +59,11 @@ type T struct { MUI8S map[uint8]string SMSI []map[string]int // Empty interfaces; used to see if we can dig inside one. - Empty0 interface{} // nil - Empty1 interface{} - Empty2 interface{} - Empty3 interface{} - Empty4 interface{} + Empty0 any // nil + Empty1 any + Empty2 any + Empty3 any + Empty4 any // Non-empty interfaces. NonEmptyInterface I NonEmptyInterfacePtS *I @@ -141,7 +141,7 @@ var tVal = &T{ SB: []bool{true, false}, MSI: map[string]int{"one": 1, "two": 2, "three": 3}, MSIone: map[string]int{"one": 1}, - MXI: map[interface{}]int{"one": 1}, + MXI: map[any]int{"one": 1}, MII: map[int]int{1: 1}, MI32S: map[int32]string{1: "one", 2: "two"}, MI64S: map[int64]string{2: "i642", 3: "i643"}, @@ -212,7 +212,7 @@ func (t *T) Method2(a uint16, b string) string { return fmt.Sprintf("Method2: %d %s", a, b) } -func (t *T) Method3(v interface{}) string { +func (t *T) Method3(v any) string { return fmt.Sprintf("Method3: %v", v) } @@ -252,7 +252,7 @@ func (u *U) TrueFalse(b bool) string { return "" } -func typeOf(arg interface{}) string { +func typeOf(arg any) string { return fmt.Sprintf("%T", arg) } @@ -260,7 +260,7 @@ type execTest struct { name string input string output string - data interface{} + data any ok bool } @@ -393,7 +393,7 @@ var execTests = []execTest{ {".VariadicFuncInt", "{{call .VariadicFuncInt 33 `he` `llo`}}", "33=<he+llo>", tVal, true}, {"if .BinaryFunc call", "{{ if .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{end}}", "[1=2]", tVal, true}, {"if not .BinaryFunc call", "{{ if not .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{else}}No{{end}}", "No", tVal, true}, - {"Interface Call", `{{stringer .S}}`, "foozle", map[string]interface{}{"S": bytes.NewBufferString("foozle")}, true}, + {"Interface Call", `{{stringer .S}}`, "foozle", map[string]any{"S": bytes.NewBufferString("foozle")}, true}, {".ErrFunc", "{{call .ErrFunc}}", "bla", tVal, true}, {"call nil", "{{call nil}}", "", tVal, false}, @@ -740,7 +740,7 @@ func add(args ...int) int { return sum } -func echo(arg interface{}) interface{} { +func echo(arg any) any { return arg } @@ -759,7 +759,7 @@ func stringer(s fmt.Stringer) string { return s.String() } -func mapOfThree() interface{} { +func mapOfThree() any { return map[string]int{"three": 3} } @@ -1438,7 +1438,7 @@ func TestBlock(t *testing.T) { func TestEvalFieldErrors(t *testing.T) { tests := []struct { name, src string - value interface{} + value any want string }{ { @@ -1581,7 +1581,7 @@ func TestInterfaceValues(t *testing.T) { for _, tt := range tests { tmpl := Must(New("tmpl").Parse(tt.text)) var buf bytes.Buffer - err := tmpl.Execute(&buf, map[string]interface{}{ + err := tmpl.Execute(&buf, map[string]any{ "PlusOne": func(n int) int { return n + 1 }, @@ -1610,7 +1610,7 @@ func TestInterfaceValues(t *testing.T) { // Check that panics during calls are recovered and returned as errors. func TestExecutePanicDuringCall(t *testing.T) { - funcs := map[string]interface{}{ + funcs := map[string]any{ "doPanic": func() string { panic("custom panic string") }, @@ -1618,7 +1618,7 @@ func TestExecutePanicDuringCall(t *testing.T) { tests := []struct { name string input string - data interface{} + data any wantErr string }{ { @@ -1816,7 +1816,7 @@ func TestRecursiveExecuteViaMethod(t *testing.T) { func TestTemplateFuncsAfterClone(t *testing.T) { s := `{{ f . }}` want := "test" - orig := New("orig").Funcs(map[string]interface{}{ + orig := New("orig").Funcs(map[string]any{ "f": func(in string) string { return in }, diff --git a/src/html/template/html.go b/src/html/template/html.go index 356b8298ae..19bd0ccb20 100644 --- a/src/html/template/html.go +++ b/src/html/template/html.go @@ -12,7 +12,7 @@ import ( ) // htmlNospaceEscaper escapes for inclusion in unquoted attribute values. -func htmlNospaceEscaper(args ...interface{}) string { +func htmlNospaceEscaper(args ...any) string { s, t := stringify(args...) if t == contentTypeHTML { return htmlReplacer(stripTags(s), htmlNospaceNormReplacementTable, false) @@ -21,7 +21,7 @@ func htmlNospaceEscaper(args ...interface{}) string { } // attrEscaper escapes for inclusion in quoted attribute values. -func attrEscaper(args ...interface{}) string { +func attrEscaper(args ...any) string { s, t := stringify(args...) if t == contentTypeHTML { return htmlReplacer(stripTags(s), htmlNormReplacementTable, true) @@ -30,7 +30,7 @@ func attrEscaper(args ...interface{}) string { } // rcdataEscaper escapes for inclusion in an RCDATA element body. -func rcdataEscaper(args ...interface{}) string { +func rcdataEscaper(args ...any) string { s, t := stringify(args...) if t == contentTypeHTML { return htmlReplacer(s, htmlNormReplacementTable, true) @@ -39,7 +39,7 @@ func rcdataEscaper(args ...interface{}) string { } // htmlEscaper escapes for inclusion in HTML text. -func htmlEscaper(args ...interface{}) string { +func htmlEscaper(args ...any) string { s, t := stringify(args...) if t == contentTypeHTML { return s @@ -225,7 +225,7 @@ func stripTags(html string) string { // htmlNameFilter accepts valid parts of an HTML attribute or tag name or // a known-safe HTML attribute. -func htmlNameFilter(args ...interface{}) string { +func htmlNameFilter(args ...any) string { s, t := stringify(args...) if t == contentTypeHTMLAttr { return s @@ -260,6 +260,6 @@ func htmlNameFilter(args ...interface{}) string { // content interpolated into comments. // This approach is equally valid whether or not static comment content is // removed from the template. -func commentEscaper(args ...interface{}) string { +func commentEscaper(args ...any) string { return "" } diff --git a/src/html/template/js.go b/src/html/template/js.go index 7e919c48e6..50523d00f1 100644 --- a/src/html/template/js.go +++ b/src/html/template/js.go @@ -122,7 +122,7 @@ var jsonMarshalType = reflect.TypeOf((*json.Marshaler)(nil)).Elem() // indirectToJSONMarshaler returns the value, after dereferencing as many times // as necessary to reach the base type (or nil) or an implementation of json.Marshal. -func indirectToJSONMarshaler(a interface{}) interface{} { +func indirectToJSONMarshaler(a any) any { // text/template now supports passing untyped nil as a func call // argument, so we must support it. Otherwise we'd panic below, as one // cannot call the Type or Interface methods on an invalid @@ -140,8 +140,8 @@ func indirectToJSONMarshaler(a interface{}) interface{} { // jsValEscaper escapes its inputs to a JS Expression (section 11.14) that has // neither side-effects nor free variables outside (NaN, Infinity). -func jsValEscaper(args ...interface{}) string { - var a interface{} +func jsValEscaper(args ...any) string { + var a any if len(args) == 1 { a = indirectToJSONMarshaler(args[0]) switch t := a.(type) { @@ -224,7 +224,7 @@ func jsValEscaper(args ...interface{}) string { // jsStrEscaper produces a string that can be included between quotes in // JavaScript source, in JavaScript embedded in an HTML5 ", "-->"}, `["\u003c!--","\u003c/script\u003e","--\u003e"]`}, {"", `"--\u003e"`}, @@ -158,7 +158,7 @@ func TestJSValEscaper(t *testing.T) { } // Make sure that escaping corner cases are not broken // by nesting. - a := []interface{}{test.x} + a := []any{test.x} want := "[" + strings.TrimSpace(test.js) + "]" if js := jsValEscaper(a); js != want { t.Errorf("%+v: want\n\t%q\ngot\n\t%q", a, want, js) @@ -168,7 +168,7 @@ func TestJSValEscaper(t *testing.T) { func TestJSStrEscaper(t *testing.T) { tests := []struct { - x interface{} + x any esc string }{ {"", ``}, @@ -223,7 +223,7 @@ func TestJSStrEscaper(t *testing.T) { func TestJSRegexpEscaper(t *testing.T) { tests := []struct { - x interface{} + x any esc string }{ {"", `(?:)`}, @@ -278,7 +278,7 @@ func TestEscapersOnLower7AndSelectHighCodepoints(t *testing.T) { tests := []struct { name string - escaper func(...interface{}) string + escaper func(...any) string escaped string }{ { diff --git a/src/html/template/template.go b/src/html/template/template.go index 69312d36fd..7eba716f1b 100644 --- a/src/html/template/template.go +++ b/src/html/template/template.go @@ -117,7 +117,7 @@ func (t *Template) escape() error { // the output writer. // A template may be executed safely in parallel, although if parallel // executions share a Writer the output may be interleaved. -func (t *Template) Execute(wr io.Writer, data interface{}) error { +func (t *Template) Execute(wr io.Writer, data any) error { if err := t.escape(); err != nil { return err } @@ -131,7 +131,7 @@ func (t *Template) Execute(wr io.Writer, data interface{}) error { // the output writer. // A template may be executed safely in parallel, although if parallel // executions share a Writer the output may be interleaved. -func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error { +func (t *Template) ExecuteTemplate(wr io.Writer, name string, data any) error { tmpl, err := t.lookupAndEscapeTemplate(name) if err != nil { return err @@ -335,7 +335,7 @@ func (t *Template) Name() string { // terminates and Execute returns that error. FuncMap has the same base type // as FuncMap in "text/template", copied here so clients need not import // "text/template". -type FuncMap map[string]interface{} +type FuncMap map[string]any // Funcs adds the elements of the argument map to the template's function map. // It must be called before the template is parsed. @@ -486,7 +486,7 @@ func parseGlob(t *Template, pattern string) (*Template, error) { // IsTrue reports whether the value is 'true', in the sense of not the zero of its type, // and whether the value has a meaningful truth value. This is the definition of // truth used by if and other such actions. -func IsTrue(val interface{}) (truth, ok bool) { +func IsTrue(val any) (truth, ok bool) { return template.IsTrue(val) } diff --git a/src/html/template/template_test.go b/src/html/template/template_test.go index 1f2c888bbe..99a1091c77 100644 --- a/src/html/template/template_test.go +++ b/src/html/template/template_test.go @@ -206,7 +206,7 @@ func (c *testCase) mustNotParse(t *Template, text string) { } } -func (c *testCase) mustExecute(t *Template, val interface{}, want string) { +func (c *testCase) mustExecute(t *Template, val any, want string) { var buf bytes.Buffer err := t.Execute(&buf, val) if err != nil { diff --git a/src/html/template/url.go b/src/html/template/url.go index 4b39fddf07..93905586a2 100644 --- a/src/html/template/url.go +++ b/src/html/template/url.go @@ -32,7 +32,7 @@ import ( // To allow URLs containing other schemes to bypass this filter, developers must // explicitly indicate that such a URL is expected and safe by encapsulating it // in a template.URL value. -func urlFilter(args ...interface{}) string { +func urlFilter(args ...any) string { s, t := stringify(args...) if t == contentTypeURL { return s @@ -56,7 +56,7 @@ func isSafeURL(s string) bool { // urlEscaper produces an output that can be embedded in a URL query. // The output can be embedded in an HTML attribute without further escaping. -func urlEscaper(args ...interface{}) string { +func urlEscaper(args ...any) string { return urlProcessor(false, args...) } @@ -65,13 +65,13 @@ func urlEscaper(args ...interface{}) string { // The normalizer does not encode all HTML specials. Specifically, it does not // encode '&' so correct embedding in an HTML attribute requires escaping of // '&' to '&'. -func urlNormalizer(args ...interface{}) string { +func urlNormalizer(args ...any) string { return urlProcessor(true, args...) } // urlProcessor normalizes (when norm is true) or escapes its input to produce // a valid hierarchical or opaque URL part. -func urlProcessor(norm bool, args ...interface{}) string { +func urlProcessor(norm bool, args ...any) string { s, t := stringify(args...) if t == contentTypeURL { norm = true @@ -141,7 +141,7 @@ func processURLOnto(s string, norm bool, b *bytes.Buffer) bool { // Filters and normalizes srcset values which are comma separated // URLs followed by metadata. -func srcsetFilterAndEscaper(args ...interface{}) string { +func srcsetFilterAndEscaper(args ...any) string { s, t := stringify(args...) switch t { case contentTypeSrcset: diff --git a/src/html/template/url_test.go b/src/html/template/url_test.go index 75c354eba8..a04f39cdff 100644 --- a/src/html/template/url_test.go +++ b/src/html/template/url_test.go @@ -48,7 +48,7 @@ func TestURLFilters(t *testing.T) { tests := []struct { name string - escaper func(...interface{}) string + escaper func(...any) string escaped string }{ { diff --git a/src/image/draw/draw_test.go b/src/image/draw/draw_test.go index 77f1c5c2c2..3be93962ad 100644 --- a/src/image/draw/draw_test.go +++ b/src/image/draw/draw_test.go @@ -84,7 +84,7 @@ func convertToSlowestRGBA(m image.Image) *slowestRGBA { } func init() { - var p interface{} = (*slowestRGBA)(nil) + var p any = (*slowestRGBA)(nil) if _, ok := p.(RGBA64Image); ok { panic("slowestRGBA should not be an RGBA64Image") } @@ -173,7 +173,7 @@ func convertToSlowerRGBA(m image.Image) *slowerRGBA { } func init() { - var p interface{} = (*slowerRGBA)(nil) + var p any = (*slowerRGBA)(nil) if _, ok := p.(RGBA64Image); !ok { panic("slowerRGBA should be an RGBA64Image") } diff --git a/src/internal/abi/abi.go b/src/internal/abi/abi.go index b266a7ff78..11acac346f 100644 --- a/src/internal/abi/abi.go +++ b/src/internal/abi/abi.go @@ -114,7 +114,7 @@ func (b *IntArgRegBitmap) Get(i int) bool { // compile-time error. // // Implemented as a compile intrinsic. -func FuncPCABI0(f interface{}) uintptr +func FuncPCABI0(f any) uintptr // FuncPCABIInternal returns the entry PC of the function f. If f is a // direct reference of a function, it must be defined as ABIInternal. @@ -123,4 +123,4 @@ func FuncPCABI0(f interface{}) uintptr // the behavior is undefined. // // Implemented as a compile intrinsic. -func FuncPCABIInternal(f interface{}) uintptr +func FuncPCABIInternal(f any) uintptr diff --git a/src/internal/fmtsort/sort_test.go b/src/internal/fmtsort/sort_test.go index ab063af5ba..11befca6f1 100644 --- a/src/internal/fmtsort/sort_test.go +++ b/src/internal/fmtsort/sort_test.go @@ -38,12 +38,12 @@ var compareTests = [][]reflect.Value{ ct(reflect.TypeOf(chans[0]), chans[0], chans[1], chans[2]), ct(reflect.TypeOf(toy{}), toy{0, 1}, toy{0, 2}, toy{1, -1}, toy{1, 1}), ct(reflect.TypeOf([2]int{}), [2]int{1, 1}, [2]int{1, 2}, [2]int{2, 0}), - ct(reflect.TypeOf(interface{}(interface{}(0))), iFace, 1, 2, 3), + ct(reflect.TypeOf(any(any(0))), iFace, 1, 2, 3), } -var iFace interface{} +var iFace any -func ct(typ reflect.Type, args ...interface{}) []reflect.Value { +func ct(typ reflect.Type, args ...any) []reflect.Value { value := make([]reflect.Value, len(args)) for i, v := range args { x := reflect.ValueOf(v) @@ -84,8 +84,8 @@ func TestCompare(t *testing.T) { } type sortTest struct { - data interface{} // Always a map. - print string // Printed result using our custom printer. + data any // Always a map. + print string // Printed result using our custom printer. } var sortTests = []sortTest{ @@ -135,7 +135,7 @@ var sortTests = []sortTest{ }, } -func sprint(data interface{}) string { +func sprint(data any) string { om := fmtsort.Sort(reflect.ValueOf(data)) if om == nil { return "nil" @@ -244,7 +244,7 @@ func TestInterface(t *testing.T) { // A map containing multiple concrete types should be sorted by type, // then value. However, the relative ordering of types is unspecified, // so test this by checking the presence of sorted subgroups. - m := map[interface{}]string{ + m := map[any]string{ [2]int{1, 0}: "", [2]int{0, 1}: "", true: "", diff --git a/src/internal/fuzz/encoding.go b/src/internal/fuzz/encoding.go index d3f24c3e6c..2bfa02b8c0 100644 --- a/src/internal/fuzz/encoding.go +++ b/src/internal/fuzz/encoding.go @@ -18,7 +18,7 @@ var encVersion1 = "go test fuzz v1" // marshalCorpusFile encodes an arbitrary number of arguments into the file format for the // corpus. -func marshalCorpusFile(vals ...interface{}) []byte { +func marshalCorpusFile(vals ...any) []byte { if len(vals) == 0 { panic("must have at least one value to marshal") } @@ -45,7 +45,7 @@ func marshalCorpusFile(vals ...interface{}) []byte { } // unmarshalCorpusFile decodes corpus bytes into their respective values. -func unmarshalCorpusFile(b []byte) ([]interface{}, error) { +func unmarshalCorpusFile(b []byte) ([]any, error) { if len(b) == 0 { return nil, fmt.Errorf("cannot unmarshal empty string") } @@ -56,7 +56,7 @@ func unmarshalCorpusFile(b []byte) ([]interface{}, error) { if string(lines[0]) != encVersion1 { return nil, fmt.Errorf("unknown encoding version: %s", lines[0]) } - var vals []interface{} + var vals []any for _, line := range lines[1:] { line = bytes.TrimSpace(line) if len(line) == 0 { @@ -71,7 +71,7 @@ func unmarshalCorpusFile(b []byte) ([]interface{}, error) { return vals, nil } -func parseCorpusValue(line []byte) (interface{}, error) { +func parseCorpusValue(line []byte) (any, error) { fs := token.NewFileSet() expr, err := parser.ParseExprFrom(fs, "(test)", line, 0) if err != nil { @@ -197,7 +197,7 @@ func parseCorpusValue(line []byte) (interface{}, error) { } // parseInt returns an integer of value val and type typ. -func parseInt(val, typ string) (interface{}, error) { +func parseInt(val, typ string) (any, error) { switch typ { case "int": return strconv.Atoi(val) @@ -218,7 +218,7 @@ func parseInt(val, typ string) (interface{}, error) { } // parseInt returns an unsigned integer of value val and type typ. -func parseUint(val, typ string) (interface{}, error) { +func parseUint(val, typ string) (any, error) { switch typ { case "uint": i, err := strconv.ParseUint(val, 10, 0) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index cb739232c7..b3f1381dbb 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -455,7 +455,7 @@ type CorpusEntry = struct { Data []byte // Values is the unmarshaled values from a corpus file. - Values []interface{} + Values []any Generation int @@ -684,7 +684,7 @@ func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { if len(c.corpus.entries) == 0 { fmt.Fprintf(c.opts.Log, "warning: starting with empty corpus\n") - var vals []interface{} + var vals []any for _, t := range opts.Types { vals = append(vals, zeroValue(t)) } @@ -968,7 +968,7 @@ func ReadCorpus(dir string, types []reflect.Type) ([]CorpusEntry, error) { if err != nil { return nil, fmt.Errorf("failed to read corpus file: %v", err) } - var vals []interface{} + var vals []any vals, err = readCorpusData(data, types) if err != nil { errs = append(errs, fmt.Errorf("%q: %v", filename, err)) @@ -982,7 +982,7 @@ func ReadCorpus(dir string, types []reflect.Type) ([]CorpusEntry, error) { return corpus, nil } -func readCorpusData(data []byte, types []reflect.Type) ([]interface{}, error) { +func readCorpusData(data []byte, types []reflect.Type) ([]any, error) { vals, err := unmarshalCorpusFile(data) if err != nil { return nil, fmt.Errorf("unmarshal: %v", err) @@ -995,7 +995,7 @@ func readCorpusData(data []byte, types []reflect.Type) ([]interface{}, error) { // CheckCorpus verifies that the types in vals match the expected types // provided. -func CheckCorpus(vals []interface{}, types []reflect.Type) error { +func CheckCorpus(vals []any, types []reflect.Type) error { if len(vals) != len(types) { return fmt.Errorf("wrong number of values in corpus entry: %d, want %d", len(vals), len(types)) } @@ -1032,7 +1032,7 @@ func testName(path string) string { return filepath.Base(path) } -func zeroValue(t reflect.Type) interface{} { +func zeroValue(t reflect.Type) any { for _, v := range zeroVals { if reflect.TypeOf(v) == t { return v @@ -1041,7 +1041,7 @@ func zeroValue(t reflect.Type) interface{} { panic(fmt.Sprintf("unsupported type: %v", t)) } -var zeroVals []interface{} = []interface{}{ +var zeroVals []any = []any{ []byte(""), string(""), false, diff --git a/src/internal/fuzz/minimize_test.go b/src/internal/fuzz/minimize_test.go index f9041d1d34..6e5f3184b4 100644 --- a/src/internal/fuzz/minimize_test.go +++ b/src/internal/fuzz/minimize_test.go @@ -22,8 +22,8 @@ func TestMinimizeInput(t *testing.T) { type testcase struct { name string fn func(CorpusEntry) error - input []interface{} - expected []interface{} + input []any + expected []any } cases := []testcase{ { @@ -41,8 +41,8 @@ func TestMinimizeInput(t *testing.T) { } return nil }, - input: []interface{}{[]byte{0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - expected: []interface{}{[]byte{1, 1, 1}}, + input: []any{[]byte{0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + expected: []any{[]byte{1, 1, 1}}, }, { name: "single_bytes", @@ -56,8 +56,8 @@ func TestMinimizeInput(t *testing.T) { } return fmt.Errorf("bad %v", e.Values[0]) }, - input: []interface{}{[]byte{1, 2, 3, 4, 5}}, - expected: []interface{}{[]byte("00")}, + input: []any{[]byte{1, 2, 3, 4, 5}}, + expected: []any{[]byte("00")}, }, { name: "set_of_bytes", @@ -71,8 +71,8 @@ func TestMinimizeInput(t *testing.T) { } return nil }, - input: []interface{}{[]byte{0, 1, 2, 3, 4, 5}}, - expected: []interface{}{[]byte{0, 4, 5}}, + input: []any{[]byte{0, 1, 2, 3, 4, 5}}, + expected: []any{[]byte{0, 4, 5}}, }, { name: "non_ascii_bytes", @@ -83,8 +83,8 @@ func TestMinimizeInput(t *testing.T) { } return nil }, - input: []interface{}{[]byte("ท")}, // ท is 3 bytes - expected: []interface{}{[]byte("000")}, + input: []any{[]byte("ท")}, // ท is 3 bytes + expected: []any{[]byte("000")}, }, { name: "ones_string", @@ -101,8 +101,8 @@ func TestMinimizeInput(t *testing.T) { } return nil }, - input: []interface{}{"001010001000000000000000000"}, - expected: []interface{}{"111"}, + input: []any{"001010001000000000000000000"}, + expected: []any{"111"}, }, { name: "string_length", @@ -113,8 +113,8 @@ func TestMinimizeInput(t *testing.T) { } return nil }, - input: []interface{}{"zzzzz"}, - expected: []interface{}{"00000"}, + input: []any{"zzzzz"}, + expected: []any{"00000"}, }, { name: "string_with_letter", @@ -126,8 +126,8 @@ func TestMinimizeInput(t *testing.T) { } return nil }, - input: []interface{}{"ZZZZZ"}, - expected: []interface{}{"A"}, + input: []any{"ZZZZZ"}, + expected: []any{"A"}, }, } @@ -167,7 +167,7 @@ func TestMinimizeFlaky(t *testing.T) { return time.Second, errors.New("ohno") }} mem := &sharedMem{region: make([]byte, 100)} // big enough to hold value and header - vals := []interface{}{[]byte(nil)} + vals := []any{[]byte(nil)} args := minimizeArgs{KeepCoverage: make([]byte, len(coverageSnapshot))} success, err := ws.minimizeInput(context.Background(), vals, mem, args) if success { diff --git a/src/internal/fuzz/mutator.go b/src/internal/fuzz/mutator.go index a3161c04ea..e26ae5a583 100644 --- a/src/internal/fuzz/mutator.go +++ b/src/internal/fuzz/mutator.go @@ -53,7 +53,7 @@ func min(a, b int) int { } // mutate performs several mutations on the provided values. -func (m *mutator) mutate(vals []interface{}, maxBytes int) { +func (m *mutator) mutate(vals []any, maxBytes int) { // TODO(katiehockman): pull some of these functions into helper methods and // test that each case is working as expected. // TODO(katiehockman): perform more types of mutations for []byte. diff --git a/src/internal/fuzz/mutator_test.go b/src/internal/fuzz/mutator_test.go index d8015ce213..cea7e2e3be 100644 --- a/src/internal/fuzz/mutator_test.go +++ b/src/internal/fuzz/mutator_test.go @@ -34,7 +34,7 @@ func BenchmarkMutatorBytes(b *testing.B) { // resize buffer to the correct shape and reset the PCG buf = buf[0:size] m.r = newPcgRand() - m.mutate([]interface{}{buf}, workerSharedMemSize) + m.mutate([]any{buf}, workerSharedMemSize) } }) } @@ -62,7 +62,7 @@ func BenchmarkMutatorString(b *testing.B) { // resize buffer to the correct shape and reset the PCG buf = buf[0:size] m.r = newPcgRand() - m.mutate([]interface{}{string(buf)}, workerSharedMemSize) + m.mutate([]any{string(buf)}, workerSharedMemSize) } }) } @@ -74,7 +74,7 @@ func BenchmarkMutatorAllBasicTypes(b *testing.B) { os.Setenv("GODEBUG", fmt.Sprintf("%s,fuzzseed=123", origEnv)) m := newMutator() - types := []interface{}{ + types := []any{ []byte(""), string(""), false, @@ -95,14 +95,14 @@ func BenchmarkMutatorAllBasicTypes(b *testing.B) { b.Run(fmt.Sprintf("%T", t), func(b *testing.B) { for i := 0; i < b.N; i++ { m.r = newPcgRand() - m.mutate([]interface{}{t}, workerSharedMemSize) + m.mutate([]any{t}, workerSharedMemSize) } }) } } func TestStringImmutability(t *testing.T) { - v := []interface{}{"hello"} + v := []any{"hello"} m := newMutator() m.mutate(v, 1024) original := v[0].(string) diff --git a/src/internal/fuzz/queue.go b/src/internal/fuzz/queue.go index cf67a28ba7..42a8379541 100644 --- a/src/internal/fuzz/queue.go +++ b/src/internal/fuzz/queue.go @@ -16,7 +16,7 @@ type queue struct { // The queue is empty when begin = end. // The queue is full (until grow is called) when end = begin + N - 1 (mod N) // where N = cap(elems). - elems []interface{} + elems []any head, len int } @@ -30,7 +30,7 @@ func (q *queue) grow() { if newCap == 0 { newCap = 8 } - newElems := make([]interface{}, newCap) + newElems := make([]any, newCap) oldLen := q.len for i := 0; i < oldLen; i++ { newElems[i] = q.elems[(q.head+i)%oldCap] @@ -39,7 +39,7 @@ func (q *queue) grow() { q.head = 0 } -func (q *queue) enqueue(e interface{}) { +func (q *queue) enqueue(e any) { if q.len+1 > q.cap() { q.grow() } @@ -48,7 +48,7 @@ func (q *queue) enqueue(e interface{}) { q.len++ } -func (q *queue) dequeue() (interface{}, bool) { +func (q *queue) dequeue() (any, bool) { if q.len == 0 { return nil, false } @@ -59,7 +59,7 @@ func (q *queue) dequeue() (interface{}, bool) { return e, true } -func (q *queue) peek() (interface{}, bool) { +func (q *queue) peek() (any, bool) { if q.len == 0 { return nil, false } diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index c39804cad1..c2d553240c 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -654,7 +654,7 @@ func (ws *workerServer) serve(ctx context.Context) error { } } - var resp interface{} + var resp any switch { case c.Fuzz != nil: resp = ws.fuzz(ctx, *c.Fuzz) @@ -726,7 +726,7 @@ func (ws *workerServer) fuzz(ctx context.Context, args fuzzArgs) (resp fuzzRespo resp.InternalErr = err.Error() return resp } - vals := make([]interface{}, len(originalVals)) + vals := make([]any, len(originalVals)) copy(vals, originalVals) shouldStop := func() bool { @@ -827,7 +827,7 @@ func (ws *workerServer) minimize(ctx context.Context, args minimizeArgs) (resp m // coverage, in fuzzFn. It uses the context to determine how long to run, // stopping once closed. It returns a bool indicating whether minimization was // successful and an error if one was found. -func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, mem *sharedMem, args minimizeArgs) (success bool, retErr error) { +func (ws *workerServer) minimizeInput(ctx context.Context, vals []any, mem *sharedMem, args minimizeArgs) (success bool, retErr error) { keepCoverage := args.KeepCoverage memBytes := mem.valueRef() bPtr := &memBytes @@ -900,7 +900,7 @@ func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, m return true, retErr } -func writeToMem(vals []interface{}, mem *sharedMem) { +func writeToMem(vals []any, mem *sharedMem) { b := marshalCorpusFile(vals...) mem.setValue(b) } @@ -1127,7 +1127,7 @@ func (wc *workerClient) ping(ctx context.Context) error { // callLocked sends an RPC from the coordinator to the worker process and waits // for the response. The callLocked may be cancelled with ctx. -func (wc *workerClient) callLocked(ctx context.Context, c call, resp interface{}) (err error) { +func (wc *workerClient) callLocked(ctx context.Context, c call, resp any) (err error) { enc := json.NewEncoder(wc.fuzzIn) dec := json.NewDecoder(&contextReader{ctx: ctx, r: wc.fuzzOut}) if err := enc.Encode(c); err != nil { diff --git a/src/internal/fuzz/worker_test.go b/src/internal/fuzz/worker_test.go index e2ecf0a9c3..d0b21da783 100644 --- a/src/internal/fuzz/worker_test.go +++ b/src/internal/fuzz/worker_test.go @@ -53,7 +53,7 @@ func BenchmarkWorkerFuzzOverhead(b *testing.B) { } }() - initialVal := []interface{}{make([]byte, 32)} + initialVal := []any{make([]byte, 32)} encodedVals := marshalCorpusFile(initialVal...) mem.setValue(encodedVals) @@ -92,7 +92,7 @@ func BenchmarkWorkerFuzz(b *testing.B) { } b.SetParallelism(1) w := newWorkerForTest(b) - entry := CorpusEntry{Values: []interface{}{[]byte(nil)}} + entry := CorpusEntry{Values: []any{[]byte(nil)}} entry.Data = marshalCorpusFile(entry.Values...) for i := int64(0); i < int64(b.N); { args := fuzzArgs{ @@ -183,7 +183,7 @@ func BenchmarkWorkerMinimize(b *testing.B) { ctx := context.Background() for sz := 1; sz <= len(bytes); sz <<= 1 { sz := sz - input := []interface{}{bytes[:sz]} + input := []any{bytes[:sz]} encodedVals := marshalCorpusFile(input...) mem = <-ws.memMu mem.setValue(encodedVals) diff --git a/src/internal/intern/intern.go b/src/internal/intern/intern.go index 666caa6d2f..75641106ab 100644 --- a/src/internal/intern/intern.go +++ b/src/internal/intern/intern.go @@ -21,7 +21,7 @@ import ( // See func Get for how Value pointers may be used. type Value struct { _ [0]func() // prevent people from accidentally using value type as comparable - cmpVal interface{} + cmpVal any // resurrected is guarded by mu (for all instances of Value). // It is set true whenever v is synthesized from a uintptr. resurrected bool @@ -29,21 +29,21 @@ type Value struct { // Get returns the comparable value passed to the Get func // that returned v. -func (v *Value) Get() interface{} { return v.cmpVal } +func (v *Value) Get() any { return v.cmpVal } // key is a key in our global value map. // It contains type-specialized fields to avoid allocations // when converting common types to empty interfaces. type key struct { s string - cmpVal interface{} + cmpVal any // isString reports whether key contains a string. // Without it, the zero value of key is ambiguous. isString bool } // keyFor returns a key to use with cmpVal. -func keyFor(cmpVal interface{}) key { +func keyFor(cmpVal any) key { if s, ok := cmpVal.(string); ok { return key{s: s, isString: true} } @@ -79,7 +79,7 @@ func safeMap() map[key]*Value { // // The returned pointer will be the same for Get(v) and Get(v2) // if and only if v == v2, and can be used as a map key. -func Get(cmpVal interface{}) *Value { +func Get(cmpVal any) *Value { return get(keyFor(cmpVal)) } diff --git a/src/internal/lazytemplate/lazytemplate.go b/src/internal/lazytemplate/lazytemplate.go index c83eaeaf3e..8eeed5a527 100644 --- a/src/internal/lazytemplate/lazytemplate.go +++ b/src/internal/lazytemplate/lazytemplate.go @@ -33,7 +33,7 @@ func (r *Template) build() { r.name, r.text = "", "" } -func (r *Template) Execute(w io.Writer, data interface{}) error { +func (r *Template) Execute(w io.Writer, data any) error { return r.tp().Execute(w, data) } diff --git a/src/internal/nettrace/nettrace.go b/src/internal/nettrace/nettrace.go index de3254df58..94f38a71ee 100644 --- a/src/internal/nettrace/nettrace.go +++ b/src/internal/nettrace/nettrace.go @@ -30,7 +30,7 @@ type Trace struct { // The coalesced parameter is whether singleflight de-dupped // the call. The addrs are of type net.IPAddr but can't // actually be for circular dependency reasons. - DNSDone func(netIPs []interface{}, coalesced bool, err error) + DNSDone func(netIPs []any, coalesced bool, err error) // ConnectStart is called before a Dial, excluding Dials made // during DNS lookups. In the case of DualStack (Happy Eyeballs) diff --git a/src/internal/poll/splice_linux.go b/src/internal/poll/splice_linux.go index 2d87c3d023..43eec04a71 100644 --- a/src/internal/poll/splice_linux.go +++ b/src/internal/poll/splice_linux.go @@ -173,7 +173,7 @@ type splicePipe struct { // a finalizer for each pipe to close its file descriptors before the actual GC. var splicePipePool = sync.Pool{New: newPoolPipe} -func newPoolPipe() interface{} { +func newPoolPipe() any { // Discard the error which occurred during the creation of pipe buffer, // redirecting the data transmission to the conventional way utilizing read() + write() as a fallback. p := newPipe() diff --git a/src/internal/poll/splice_linux_test.go b/src/internal/poll/splice_linux_test.go index 8c4363886e..29bcaab414 100644 --- a/src/internal/poll/splice_linux_test.go +++ b/src/internal/poll/splice_linux_test.go @@ -73,7 +73,7 @@ func TestSplicePipePool(t *testing.T) { // Detect whether all pipes are closed properly. var leakedFDs []int - pendingFDs.Range(func(k, v interface{}) bool { + pendingFDs.Range(func(k, v any) bool { leakedFDs = append(leakedFDs, k.(int)) return true }) diff --git a/src/internal/reflectlite/all_test.go b/src/internal/reflectlite/all_test.go index e15f364fcd..ea750831ef 100644 --- a/src/internal/reflectlite/all_test.go +++ b/src/internal/reflectlite/all_test.go @@ -32,7 +32,7 @@ type T struct { } type pair struct { - i interface{} + i any s string } @@ -421,7 +421,7 @@ func TestAll(t *testing.T) { func TestInterfaceValue(t *testing.T) { var inter struct { - E interface{} + E any } inter.E = 123.456 v1 := ValueOf(&inter) @@ -437,7 +437,7 @@ func TestInterfaceValue(t *testing.T) { } func TestFunctionValue(t *testing.T) { - var x interface{} = func() {} + var x any = func() {} v := ValueOf(x) if fmt.Sprint(ToInterface(v)) != fmt.Sprint(x) { t.Fatalf("TestFunction returned wrong pointer") @@ -496,7 +496,7 @@ type Basic struct { type NotBasic Basic type DeepEqualTest struct { - a, b interface{} + a, b any eq bool } @@ -510,7 +510,7 @@ var ( type self struct{} type Loop *Loop -type Loopy interface{} +type Loopy any var loop1, loop2 Loop var loopy1, loopy2 Loopy @@ -578,7 +578,7 @@ var typeOfTests = []DeepEqualTest{ {int32(1), int64(1), false}, {0.5, "hello", false}, {[]int{1, 2, 3}, [3]int{1, 2, 3}, false}, - {&[3]interface{}{1, 2, 4}, &[3]interface{}{1, 2, "s"}, false}, + {&[3]any{1, 2, 4}, &[3]any{1, 2, "s"}, false}, {Basic{1, 0.5}, NotBasic{1, 0.5}, false}, {map[uint]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, false}, @@ -606,14 +606,14 @@ func TestTypeOf(t *testing.T) { } } -func Nil(a interface{}, t *testing.T) { +func Nil(a any, t *testing.T) { n := Field(ValueOf(a), 0) if !n.IsNil() { t.Errorf("%v should be nil", a) } } -func NotNil(a interface{}, t *testing.T) { +func NotNil(a any, t *testing.T) { n := Field(ValueOf(a), 0) if n.IsNil() { t.Errorf("value of type %v should not be nil", TypeString(ValueOf(a).Type())) @@ -623,9 +623,9 @@ func NotNil(a interface{}, t *testing.T) { func TestIsNil(t *testing.T) { // These implement IsNil. // Wrap in extra struct to hide interface type. - doNil := []interface{}{ + doNil := []any{ struct{ x *int }{}, - struct{ x interface{} }{}, + struct{ x any }{}, struct{ x map[string]int }{}, struct{ x func() bool }{}, struct{ x chan int }{}, @@ -668,7 +668,7 @@ func TestIsNil(t *testing.T) { NotNil(mi, t) var ii struct { - x interface{} + x any } Nil(ii, t) ii.x = 2 @@ -770,7 +770,7 @@ func TestImportPath(t *testing.T) { {TypeOf([]byte(nil)), ""}, {TypeOf([]rune(nil)), ""}, {TypeOf(string("")), ""}, - {TypeOf((*interface{})(nil)).Elem(), ""}, + {TypeOf((*any)(nil)).Elem(), ""}, {TypeOf((*byte)(nil)), ""}, {TypeOf((*rune)(nil)), ""}, {TypeOf((*int64)(nil)), ""}, @@ -805,7 +805,7 @@ func noAlloc(t *testing.T, n int, f func(int)) { func TestAllocations(t *testing.T) { noAlloc(t, 100, func(j int) { - var i interface{} + var i any var v Value // We can uncomment this when compiler escape analysis @@ -939,7 +939,7 @@ func TestBigZero(t *testing.T) { func TestInvalid(t *testing.T) { // Used to have inconsistency between IsValid() and Kind() != Invalid. - type T struct{ v interface{} } + type T struct{ v any } v := Field(ValueOf(T{}), 0) if v.IsValid() != true || v.Kind() != Interface { @@ -954,7 +954,7 @@ func TestInvalid(t *testing.T) { type TheNameOfThisTypeIsExactly255BytesLongSoWhenTheCompilerPrependsTheReflectTestPackageNameAndExtraStarTheLinkerRuntimeAndReflectPackagesWillHaveToCorrectlyDecodeTheSecondLengthByte0123456789_0123456789_0123456789_0123456789_0123456789_012345678 int type nameTest struct { - v interface{} + v any want string } @@ -966,7 +966,7 @@ var nameTests = []nameTest{ {(*func() D1)(nil), ""}, {(*<-chan D1)(nil), ""}, {(*chan<- D1)(nil), ""}, - {(*interface{})(nil), ""}, + {(*any)(nil), ""}, {(*interface { F() })(nil), ""}, diff --git a/src/internal/reflectlite/export_test.go b/src/internal/reflectlite/export_test.go index 354ea9dbd0..adae229e92 100644 --- a/src/internal/reflectlite/export_test.go +++ b/src/internal/reflectlite/export_test.go @@ -81,7 +81,7 @@ func Zero(typ Type) Value { // var i interface{} = (v's underlying value) // It panics if the Value was obtained by accessing // unexported struct fields. -func ToInterface(v Value) (i interface{}) { +func ToInterface(v Value) (i any) { return valueInterface(v) } diff --git a/src/internal/reflectlite/set_test.go b/src/internal/reflectlite/set_test.go index a610499d08..ca7ea9b0bc 100644 --- a/src/internal/reflectlite/set_test.go +++ b/src/internal/reflectlite/set_test.go @@ -26,8 +26,8 @@ func TestImplicitSetConversion(t *testing.T) { } var implementsTests = []struct { - x interface{} - t interface{} + x any + t any b bool }{ {new(*bytes.Buffer), new(io.Reader), true}, @@ -73,8 +73,8 @@ func TestImplements(t *testing.T) { } var assignableTests = []struct { - x interface{} - t interface{} + x any + t any b bool }{ {new(chan int), new(<-chan int), true}, @@ -82,13 +82,13 @@ var assignableTests = []struct { {new(*int), new(IntPtr), true}, {new(IntPtr), new(*int), true}, {new(IntPtr), new(IntPtr1), false}, - {new(Ch), new(<-chan interface{}), true}, + {new(Ch), new(<-chan any), true}, // test runs implementsTests too } type IntPtr *int type IntPtr1 *int -type Ch <-chan interface{} +type Ch <-chan any func TestAssignableTo(t *testing.T) { for i, tt := range append(assignableTests, implementsTests...) { diff --git a/src/internal/reflectlite/swapper.go b/src/internal/reflectlite/swapper.go index ac081d49bb..fc402bb38a 100644 --- a/src/internal/reflectlite/swapper.go +++ b/src/internal/reflectlite/swapper.go @@ -14,7 +14,7 @@ import ( // slice. // // Swapper panics if the provided interface is not a slice. -func Swapper(slice interface{}) func(i, j int) { +func Swapper(slice any) func(i, j int) { v := ValueOf(slice) if v.Kind() != Slice { panic(&ValueError{Method: "Swapper", Kind: v.Kind()}) diff --git a/src/internal/reflectlite/type.go b/src/internal/reflectlite/type.go index fdf1584a27..8f649600d2 100644 --- a/src/internal/reflectlite/type.go +++ b/src/internal/reflectlite/type.go @@ -707,7 +707,7 @@ func (t *interfaceType) NumMethod() int { return len(t.methods) } // TypeOf returns the reflection Type that represents the dynamic type of i. // If i is a nil interface value, TypeOf returns nil. -func TypeOf(i interface{}) Type { +func TypeOf(i any) Type { eface := *(*emptyInterface)(unsafe.Pointer(&i)) return toType(eface.typ) } diff --git a/src/internal/reflectlite/value.go b/src/internal/reflectlite/value.go index 0734069255..966230f581 100644 --- a/src/internal/reflectlite/value.go +++ b/src/internal/reflectlite/value.go @@ -99,9 +99,9 @@ func (v Value) pointer() unsafe.Pointer { } // packEface converts v to the empty interface. -func packEface(v Value) interface{} { +func packEface(v Value) any { t := v.typ - var i interface{} + var i any e := (*emptyInterface)(unsafe.Pointer(&i)) // First, fill in the data portion of the interface. switch { @@ -136,7 +136,7 @@ func packEface(v Value) interface{} { } // unpackEface converts the empty interface i to a Value. -func unpackEface(i interface{}) Value { +func unpackEface(i any) Value { e := (*emptyInterface)(unsafe.Pointer(&i)) // NOTE: don't read e.word until we know whether it is really a pointer or not. t := e.typ @@ -226,11 +226,11 @@ func (v Value) Elem() Value { k := v.kind() switch k { case Interface: - var eface interface{} + var eface any if v.typ.NumMethod() == 0 { - eface = *(*interface{})(v.ptr) + eface = *(*any)(v.ptr) } else { - eface = (interface{})(*(*interface { + eface = (any)(*(*interface { M() })(v.ptr)) } @@ -257,7 +257,7 @@ func (v Value) Elem() Value { panic(&ValueError{"reflectlite.Value.Elem", v.kind()}) } -func valueInterface(v Value) interface{} { +func valueInterface(v Value) any { if v.flag == 0 { panic(&ValueError{"reflectlite.Value.Interface", 0}) } @@ -267,7 +267,7 @@ func valueInterface(v Value) interface{} { // Empty interface has one layout, all interfaces with // methods have a second layout. if v.numMethod() == 0 { - return *(*interface{})(v.ptr) + return *(*any)(v.ptr) } return *(*interface { M() @@ -391,7 +391,7 @@ func unsafe_New(*rtype) unsafe.Pointer // ValueOf returns a new Value initialized to the concrete value // stored in the interface i. ValueOf(nil) returns the zero Value. -func ValueOf(i interface{}) Value { +func ValueOf(i any) Value { if i == nil { return Value{} } @@ -433,7 +433,7 @@ func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value } x := valueInterface(v) if dst.NumMethod() == 0 { - *(*interface{})(target) = x + *(*any)(target) = x } else { ifaceE2I(dst, x, target) } @@ -455,7 +455,7 @@ func arrayAt(p unsafe.Pointer, i int, eltSize uintptr, whySafe string) unsafe.Po return add(p, uintptr(i)*eltSize, "i < len") } -func ifaceE2I(t *rtype, src interface{}, dst unsafe.Pointer) +func ifaceE2I(t *rtype, src any, dst unsafe.Pointer) // typedmemmove copies a value of type t to dst from src. //go:noescape @@ -464,7 +464,7 @@ func typedmemmove(t *rtype, dst, src unsafe.Pointer) // Dummy annotation marking that the value x escapes, // for use in cases where the reflect code is so clever that // the compiler cannot follow. -func escapes(x interface{}) { +func escapes(x any) { if dummy.b { dummy.x = x } @@ -472,5 +472,5 @@ func escapes(x interface{}) { var dummy struct { b bool - x interface{} + x any } diff --git a/src/internal/singleflight/singleflight.go b/src/internal/singleflight/singleflight.go index b2d82e26c2..07b3f40ec0 100644 --- a/src/internal/singleflight/singleflight.go +++ b/src/internal/singleflight/singleflight.go @@ -14,7 +14,7 @@ type call struct { // These fields are written once before the WaitGroup is done // and are only read after the WaitGroup is done. - val interface{} + val any err error // These fields are read and written with the singleflight @@ -34,7 +34,7 @@ type Group struct { // Result holds the results of Do, so they can be passed // on a channel. type Result struct { - Val interface{} + Val any Err error Shared bool } @@ -44,7 +44,7 @@ type Result struct { // time. If a duplicate comes in, the duplicate caller waits for the // original to complete and receives the same results. // The return value shared indicates whether v was given to multiple callers. -func (g *Group) Do(key string, fn func() (interface{}, error)) (v interface{}, err error, shared bool) { +func (g *Group) Do(key string, fn func() (any, error)) (v any, err error, shared bool) { g.mu.Lock() if g.m == nil { g.m = make(map[string]*call) @@ -68,7 +68,7 @@ func (g *Group) Do(key string, fn func() (interface{}, error)) (v interface{}, e // results when they are ready. The second result is true if the function // will eventually be called, false if it will not (because there is // a pending request with this key). -func (g *Group) DoChan(key string, fn func() (interface{}, error)) (<-chan Result, bool) { +func (g *Group) DoChan(key string, fn func() (any, error)) (<-chan Result, bool) { ch := make(chan Result, 1) g.mu.Lock() if g.m == nil { @@ -91,7 +91,7 @@ func (g *Group) DoChan(key string, fn func() (interface{}, error)) (<-chan Resul } // doCall handles the single call for a key. -func (g *Group) doCall(c *call, key string, fn func() (interface{}, error)) { +func (g *Group) doCall(c *call, key string, fn func() (any, error)) { c.val, c.err = fn() c.wg.Done() diff --git a/src/internal/singleflight/singleflight_test.go b/src/internal/singleflight/singleflight_test.go index 6404a1775a..c2310375f7 100644 --- a/src/internal/singleflight/singleflight_test.go +++ b/src/internal/singleflight/singleflight_test.go @@ -15,7 +15,7 @@ import ( func TestDo(t *testing.T) { var g Group - v, err, _ := g.Do("key", func() (interface{}, error) { + v, err, _ := g.Do("key", func() (any, error) { return "bar", nil }) if got, want := fmt.Sprintf("%v (%T)", v, v), "bar (string)"; got != want { @@ -29,7 +29,7 @@ func TestDo(t *testing.T) { func TestDoErr(t *testing.T) { var g Group someErr := errors.New("some error") - v, err, _ := g.Do("key", func() (interface{}, error) { + v, err, _ := g.Do("key", func() (any, error) { return nil, someErr }) if err != someErr { @@ -45,7 +45,7 @@ func TestDoDupSuppress(t *testing.T) { var wg1, wg2 sync.WaitGroup c := make(chan string, 1) var calls int32 - fn := func() (interface{}, error) { + fn := func() (any, error) { if atomic.AddInt32(&calls, 1) == 1 { // First invocation. wg1.Done() diff --git a/src/internal/syscall/windows/registry/registry_test.go b/src/internal/syscall/windows/registry/registry_test.go index 134b5450fc..278b0b4911 100644 --- a/src/internal/syscall/windows/registry/registry_test.go +++ b/src/internal/syscall/windows/registry/registry_test.go @@ -118,7 +118,7 @@ func equalStringSlice(a, b []string) bool { type ValueTest struct { Type uint32 Name string - Value interface{} + Value any WillFail bool } diff --git a/src/internal/trace/gc.go b/src/internal/trace/gc.go index cc19fdf891..c1bc862340 100644 --- a/src/internal/trace/gc.go +++ b/src/internal/trace/gc.go @@ -352,11 +352,11 @@ func (h bandUtilHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } -func (h *bandUtilHeap) Push(x interface{}) { +func (h *bandUtilHeap) Push(x any) { *h = append(*h, x.(bandUtil)) } -func (h *bandUtilHeap) Pop() interface{} { +func (h *bandUtilHeap) Pop() any { x := (*h)[len(*h)-1] *h = (*h)[:len(*h)-1] return x @@ -386,11 +386,11 @@ func (h utilHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } -func (h *utilHeap) Push(x interface{}) { +func (h *utilHeap) Push(x any) { *h = append(*h, x.(UtilWindow)) } -func (h *utilHeap) Pop() interface{} { +func (h *utilHeap) Pop() any { x := (*h)[len(*h)-1] *h = (*h)[:len(*h)-1] return x diff --git a/src/internal/unsafeheader/unsafeheader_test.go b/src/internal/unsafeheader/unsafeheader_test.go index 6fb7cca888..f3d1a9bb68 100644 --- a/src/internal/unsafeheader/unsafeheader_test.go +++ b/src/internal/unsafeheader/unsafeheader_test.go @@ -25,7 +25,7 @@ func TestTypeMatchesReflectType(t *testing.T) { }) } -func testHeaderMatchesReflect(t *testing.T, header, reflectHeader interface{}) { +func testHeaderMatchesReflect(t *testing.T, header, reflectHeader any) { h := reflect.TypeOf(header) rh := reflect.TypeOf(reflectHeader) diff --git a/src/io/fs/fs.go b/src/io/fs/fs.go index e603afadb0..5c0d9a6664 100644 --- a/src/io/fs/fs.go +++ b/src/io/fs/fs.go @@ -153,7 +153,7 @@ type FileInfo interface { Mode() FileMode // file mode bits ModTime() time.Time // modification time IsDir() bool // abbreviation for Mode().IsDir() - Sys() interface{} // underlying data source (can return nil) + Sys() any // underlying data source (can return nil) } // A FileMode represents a file's mode and permission bits. diff --git a/src/io/io.go b/src/io/io.go index 5635392dfb..1ea01d5d63 100644 --- a/src/io/io.go +++ b/src/io/io.go @@ -597,7 +597,7 @@ func (discard) WriteString(s string) (int, error) { } var blackHolePool = sync.Pool{ - New: func() interface{} { + New: func() any { b := make([]byte, 8192) return &b }, diff --git a/src/log/log.go b/src/log/log.go index 3172384718..5e79b19522 100644 --- a/src/log/log.go +++ b/src/log/log.go @@ -198,7 +198,7 @@ func (l *Logger) Output(calldepth int, s string) error { // Printf calls l.Output to print to the logger. // Arguments are handled in the manner of fmt.Printf. -func (l *Logger) Printf(format string, v ...interface{}) { +func (l *Logger) Printf(format string, v ...any) { if atomic.LoadInt32(&l.isDiscard) != 0 { return } @@ -207,7 +207,7 @@ func (l *Logger) Printf(format string, v ...interface{}) { // Print calls l.Output to print to the logger. // Arguments are handled in the manner of fmt.Print. -func (l *Logger) Print(v ...interface{}) { +func (l *Logger) Print(v ...any) { if atomic.LoadInt32(&l.isDiscard) != 0 { return } @@ -216,7 +216,7 @@ func (l *Logger) Print(v ...interface{}) { // Println calls l.Output to print to the logger. // Arguments are handled in the manner of fmt.Println. -func (l *Logger) Println(v ...interface{}) { +func (l *Logger) Println(v ...any) { if atomic.LoadInt32(&l.isDiscard) != 0 { return } @@ -224,39 +224,39 @@ func (l *Logger) Println(v ...interface{}) { } // Fatal is equivalent to l.Print() followed by a call to os.Exit(1). -func (l *Logger) Fatal(v ...interface{}) { +func (l *Logger) Fatal(v ...any) { l.Output(2, fmt.Sprint(v...)) os.Exit(1) } // Fatalf is equivalent to l.Printf() followed by a call to os.Exit(1). -func (l *Logger) Fatalf(format string, v ...interface{}) { +func (l *Logger) Fatalf(format string, v ...any) { l.Output(2, fmt.Sprintf(format, v...)) os.Exit(1) } // Fatalln is equivalent to l.Println() followed by a call to os.Exit(1). -func (l *Logger) Fatalln(v ...interface{}) { +func (l *Logger) Fatalln(v ...any) { l.Output(2, fmt.Sprintln(v...)) os.Exit(1) } // Panic is equivalent to l.Print() followed by a call to panic(). -func (l *Logger) Panic(v ...interface{}) { +func (l *Logger) Panic(v ...any) { s := fmt.Sprint(v...) l.Output(2, s) panic(s) } // Panicf is equivalent to l.Printf() followed by a call to panic(). -func (l *Logger) Panicf(format string, v ...interface{}) { +func (l *Logger) Panicf(format string, v ...any) { s := fmt.Sprintf(format, v...) l.Output(2, s) panic(s) } // Panicln is equivalent to l.Println() followed by a call to panic(). -func (l *Logger) Panicln(v ...interface{}) { +func (l *Logger) Panicln(v ...any) { s := fmt.Sprintln(v...) l.Output(2, s) panic(s) @@ -335,7 +335,7 @@ func Writer() io.Writer { // Print calls Output to print to the standard logger. // Arguments are handled in the manner of fmt.Print. -func Print(v ...interface{}) { +func Print(v ...any) { if atomic.LoadInt32(&std.isDiscard) != 0 { return } @@ -344,7 +344,7 @@ func Print(v ...interface{}) { // Printf calls Output to print to the standard logger. // Arguments are handled in the manner of fmt.Printf. -func Printf(format string, v ...interface{}) { +func Printf(format string, v ...any) { if atomic.LoadInt32(&std.isDiscard) != 0 { return } @@ -353,7 +353,7 @@ func Printf(format string, v ...interface{}) { // Println calls Output to print to the standard logger. // Arguments are handled in the manner of fmt.Println. -func Println(v ...interface{}) { +func Println(v ...any) { if atomic.LoadInt32(&std.isDiscard) != 0 { return } @@ -361,39 +361,39 @@ func Println(v ...interface{}) { } // Fatal is equivalent to Print() followed by a call to os.Exit(1). -func Fatal(v ...interface{}) { +func Fatal(v ...any) { std.Output(2, fmt.Sprint(v...)) os.Exit(1) } // Fatalf is equivalent to Printf() followed by a call to os.Exit(1). -func Fatalf(format string, v ...interface{}) { +func Fatalf(format string, v ...any) { std.Output(2, fmt.Sprintf(format, v...)) os.Exit(1) } // Fatalln is equivalent to Println() followed by a call to os.Exit(1). -func Fatalln(v ...interface{}) { +func Fatalln(v ...any) { std.Output(2, fmt.Sprintln(v...)) os.Exit(1) } // Panic is equivalent to Print() followed by a call to panic(). -func Panic(v ...interface{}) { +func Panic(v ...any) { s := fmt.Sprint(v...) std.Output(2, s) panic(s) } // Panicf is equivalent to Printf() followed by a call to panic(). -func Panicf(format string, v ...interface{}) { +func Panicf(format string, v ...any) { s := fmt.Sprintf(format, v...) std.Output(2, s) panic(s) } // Panicln is equivalent to Println() followed by a call to panic(). -func Panicln(v ...interface{}) { +func Panicln(v ...any) { s := fmt.Sprintln(v...) std.Output(2, s) panic(s) diff --git a/src/math/all_test.go b/src/math/all_test.go index 55c805e199..c11d823233 100644 --- a/src/math/all_test.go +++ b/src/math/all_test.go @@ -3175,7 +3175,7 @@ func TestTrigReduce(t *testing.T) { // https://golang.org/issue/201 type floatTest struct { - val interface{} + val any name string str string } diff --git a/src/math/big/floatconv_test.go b/src/math/big/floatconv_test.go index 3aa6834143..a1cc38a459 100644 --- a/src/math/big/floatconv_test.go +++ b/src/math/big/floatconv_test.go @@ -576,7 +576,7 @@ func TestFloatText(t *testing.T) { func TestFloatFormat(t *testing.T) { for _, test := range []struct { format string - value interface{} // float32, float64, or string (== 512bit *Float) + value any // float32, float64, or string (== 512bit *Float) want string }{ // from fmt/fmt_test.go diff --git a/src/math/bits/make_examples.go b/src/math/bits/make_examples.go index ac4004df41..92e9aabfb5 100644 --- a/src/math/bits/make_examples.go +++ b/src/math/bits/make_examples.go @@ -37,44 +37,44 @@ func main() { for _, e := range []struct { name string in int - out [4]interface{} - out2 [4]interface{} + out [4]any + out2 [4]any }{ { name: "LeadingZeros", in: 1, - out: [4]interface{}{bits.LeadingZeros8(1), bits.LeadingZeros16(1), bits.LeadingZeros32(1), bits.LeadingZeros64(1)}, + out: [4]any{bits.LeadingZeros8(1), bits.LeadingZeros16(1), bits.LeadingZeros32(1), bits.LeadingZeros64(1)}, }, { name: "TrailingZeros", in: 14, - out: [4]interface{}{bits.TrailingZeros8(14), bits.TrailingZeros16(14), bits.TrailingZeros32(14), bits.TrailingZeros64(14)}, + out: [4]any{bits.TrailingZeros8(14), bits.TrailingZeros16(14), bits.TrailingZeros32(14), bits.TrailingZeros64(14)}, }, { name: "OnesCount", in: 14, - out: [4]interface{}{bits.OnesCount8(14), bits.OnesCount16(14), bits.OnesCount32(14), bits.OnesCount64(14)}, + out: [4]any{bits.OnesCount8(14), bits.OnesCount16(14), bits.OnesCount32(14), bits.OnesCount64(14)}, }, { name: "RotateLeft", in: 15, - out: [4]interface{}{bits.RotateLeft8(15, 2), bits.RotateLeft16(15, 2), bits.RotateLeft32(15, 2), bits.RotateLeft64(15, 2)}, - out2: [4]interface{}{bits.RotateLeft8(15, -2), bits.RotateLeft16(15, -2), bits.RotateLeft32(15, -2), bits.RotateLeft64(15, -2)}, + out: [4]any{bits.RotateLeft8(15, 2), bits.RotateLeft16(15, 2), bits.RotateLeft32(15, 2), bits.RotateLeft64(15, 2)}, + out2: [4]any{bits.RotateLeft8(15, -2), bits.RotateLeft16(15, -2), bits.RotateLeft32(15, -2), bits.RotateLeft64(15, -2)}, }, { name: "Reverse", in: 19, - out: [4]interface{}{bits.Reverse8(19), bits.Reverse16(19), bits.Reverse32(19), bits.Reverse64(19)}, + out: [4]any{bits.Reverse8(19), bits.Reverse16(19), bits.Reverse32(19), bits.Reverse64(19)}, }, { name: "ReverseBytes", in: 15, - out: [4]interface{}{nil, bits.ReverseBytes16(15), bits.ReverseBytes32(15), bits.ReverseBytes64(15)}, + out: [4]any{nil, bits.ReverseBytes16(15), bits.ReverseBytes32(15), bits.ReverseBytes64(15)}, }, { name: "Len", in: 8, - out: [4]interface{}{bits.Len8(8), bits.Len16(8), bits.Len32(8), bits.Len64(8)}, + out: [4]any{bits.Len8(8), bits.Len16(8), bits.Len32(8), bits.Len64(8)}, }, } { for i, size := range []int{8, 16, 32, 64} { diff --git a/src/math/rand/example_test.go b/src/math/rand/example_test.go index 4107613555..f691e39d64 100644 --- a/src/math/rand/example_test.go +++ b/src/math/rand/example_test.go @@ -57,7 +57,7 @@ func Example_rand() { // The tabwriter here helps us generate aligned output. w := tabwriter.NewWriter(os.Stdout, 1, 1, 1, ' ', 0) defer w.Flush() - show := func(name string, v1, v2, v3 interface{}) { + show := func(name string, v1, v2, v3 any) { fmt.Fprintf(w, "%s\t%v\t%v\t%v\n", name, v1, v2, v3) } diff --git a/src/math/rand/regress_test.go b/src/math/rand/regress_test.go index 1f30be85d1..813098ec9c 100644 --- a/src/math/rand/regress_test.go +++ b/src/math/rand/regress_test.go @@ -46,7 +46,7 @@ func TestRegress(t *testing.T) { var args []reflect.Value var argstr string if mt.NumIn() == 1 { - var x interface{} + var x any switch mt.In(0).Kind() { default: t.Fatalf("unexpected argument type for r.%s", m.Name) @@ -83,7 +83,7 @@ func TestRegress(t *testing.T) { args = append(args, reflect.ValueOf(x)) } - var out interface{} + var out any out = mv.Call(args)[0].Interface() if m.Name == "Int" || m.Name == "Intn" { out = int64(out.(int)) @@ -120,7 +120,7 @@ func TestRegress(t *testing.T) { } } -var regressGolden = []interface{}{ +var regressGolden = []any{ float64(4.668112973579268), // ExpFloat64() float64(0.1601593871172866), // ExpFloat64() float64(3.0465834105636), // ExpFloat64() diff --git a/src/mime/quotedprintable/reader_test.go b/src/mime/quotedprintable/reader_test.go index 48a7ff6495..19e9fea19b 100644 --- a/src/mime/quotedprintable/reader_test.go +++ b/src/mime/quotedprintable/reader_test.go @@ -22,7 +22,7 @@ import ( func TestReader(t *testing.T) { tests := []struct { in, want string - err interface{} + err any }{ {in: "", want: ""}, {in: "foo bar", want: "foo bar"}, @@ -160,7 +160,7 @@ func TestExhaustive(t *testing.T) { if err != nil { panic(err) } - qpres := make(chan interface{}, 2) + qpres := make(chan any, 2) go func() { br := bufio.NewReader(stderr) s, _ := br.ReadString('\n') diff --git a/src/mime/type.go b/src/mime/type.go index 26424339af..bdb8bb319a 100644 --- a/src/mime/type.go +++ b/src/mime/type.go @@ -23,7 +23,7 @@ var ( ) func clearSyncMap(m *sync.Map) { - m.Range(func(k, _ interface{}) bool { + m.Range(func(k, _ any) bool { m.Delete(k) return true }) diff --git a/src/net/http/cgi/host.go b/src/net/http/cgi/host.go index e7124a2ab0..95b2e13e4e 100644 --- a/src/net/http/cgi/host.go +++ b/src/net/http/cgi/host.go @@ -350,7 +350,7 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { } } -func (h *Handler) printf(format string, v ...interface{}) { +func (h *Handler) printf(format string, v ...any) { if h.Logger != nil { h.Logger.Printf(format, v...) } else { diff --git a/src/net/http/client_test.go b/src/net/http/client_test.go index 62bf9342f4..c2ea6f4330 100644 --- a/src/net/http/client_test.go +++ b/src/net/http/client_test.go @@ -745,7 +745,7 @@ func (j *RecordingJar) Cookies(u *url.URL) []*Cookie { return nil } -func (j *RecordingJar) logf(format string, args ...interface{}) { +func (j *RecordingJar) logf(format string, args ...any) { j.mu.Lock() defer j.mu.Unlock() fmt.Fprintf(&j.log, format, args...) diff --git a/src/net/http/clientserver_test.go b/src/net/http/clientserver_test.go index 125d63566b..71b2a32cb4 100644 --- a/src/net/http/clientserver_test.go +++ b/src/net/http/clientserver_test.go @@ -81,7 +81,7 @@ func optWithServerLog(lg *log.Logger) func(*httptest.Server) { } } -func newClientServerTest(t *testing.T, h2 bool, h Handler, opts ...interface{}) *clientServerTest { +func newClientServerTest(t *testing.T, h2 bool, h Handler, opts ...any) *clientServerTest { if h2 { CondSkipHTTP2(t) } @@ -189,7 +189,7 @@ type h12Compare struct { ReqFunc reqFunc // optional CheckResponse func(proto string, res *Response) // optional EarlyCheckResponse func(proto string, res *Response) // optional; pre-normalize - Opts []interface{} + Opts []any } func (tt h12Compare) reqFunc() reqFunc { @@ -441,7 +441,7 @@ func TestH12_AutoGzip(t *testing.T) { func TestH12_AutoGzip_Disabled(t *testing.T) { h12Compare{ - Opts: []interface{}{ + Opts: []any{ func(tr *Transport) { tr.DisableCompression = true }, }, Handler: func(w ResponseWriter, r *Request) { @@ -1168,7 +1168,7 @@ func TestInterruptWithPanic_ErrAbortHandler_h1(t *testing.T) { func TestInterruptWithPanic_ErrAbortHandler_h2(t *testing.T) { testInterruptWithPanic(t, h2Mode, ErrAbortHandler) } -func testInterruptWithPanic(t *testing.T, h2 bool, panicValue interface{}) { +func testInterruptWithPanic(t *testing.T, h2 bool, panicValue any) { setParallel(t) const msg = "hello" defer afterTest(t) @@ -1518,7 +1518,7 @@ func TestBidiStreamReverseProxy(t *testing.T) { })) defer proxy.close() - bodyRes := make(chan interface{}, 1) // error or hash.Hash + bodyRes := make(chan any, 1) // error or hash.Hash pr, pw := io.Pipe() req, _ := NewRequest("PUT", proxy.ts.URL, pr) const size = 4 << 20 diff --git a/src/net/http/cookie_test.go b/src/net/http/cookie_test.go index 257dc57420..ccc5f98091 100644 --- a/src/net/http/cookie_test.go +++ b/src/net/http/cookie_test.go @@ -360,7 +360,7 @@ var readSetCookiesTests = []struct { // Header{"Set-Cookie": {"ASP.NET_SessionId=foo; path=/; HttpOnly, .ASPXAUTH=7E3AA; expires=Wed, 07-Mar-2012 14:25:06 GMT; path=/; HttpOnly"}}, } -func toJSON(v interface{}) string { +func toJSON(v any) string { b, err := json.Marshal(v) if err != nil { return fmt.Sprintf("%#v", v) diff --git a/src/net/http/fs_test.go b/src/net/http/fs_test.go index b42ade1e8a..4b01cce72d 100644 --- a/src/net/http/fs_test.go +++ b/src/net/http/fs_test.go @@ -658,7 +658,7 @@ type fakeFileInfo struct { } func (f *fakeFileInfo) Name() string { return f.basename } -func (f *fakeFileInfo) Sys() interface{} { return nil } +func (f *fakeFileInfo) Sys() any { return nil } func (f *fakeFileInfo) ModTime() time.Time { return f.modtime } func (f *fakeFileInfo) IsDir() bool { return f.dir } func (f *fakeFileInfo) Size() int64 { return int64(len(f.contents)) } diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go index bb82f24585..83b6d29144 100644 --- a/src/net/http/h2_bundle.go +++ b/src/net/http/h2_bundle.go @@ -1049,11 +1049,11 @@ var ( 16 << 10, } http2dataChunkPools = [...]sync.Pool{ - {New: func() interface{} { return make([]byte, 1<<10) }}, - {New: func() interface{} { return make([]byte, 2<<10) }}, - {New: func() interface{} { return make([]byte, 4<<10) }}, - {New: func() interface{} { return make([]byte, 8<<10) }}, - {New: func() interface{} { return make([]byte, 16<<10) }}, + {New: func() any { return make([]byte, 1<<10) }}, + {New: func() any { return make([]byte, 2<<10) }}, + {New: func() any { return make([]byte, 4<<10) }}, + {New: func() any { return make([]byte, 8<<10) }}, + {New: func() any { return make([]byte, 16<<10) }}, } ) @@ -1548,7 +1548,7 @@ func (h *http2FrameHeader) invalidate() { h.valid = false } // frame header bytes. // Used only by ReadFrameHeader. var http2fhBytes = sync.Pool{ - New: func() interface{} { + New: func() any { buf := make([]byte, http2frameHeaderLen) return &buf }, @@ -1655,8 +1655,8 @@ type http2Framer struct { debugFramer *http2Framer // only use for logging written writes debugFramerBuf *bytes.Buffer - debugReadLoggerf func(string, ...interface{}) - debugWriteLoggerf func(string, ...interface{}) + debugReadLoggerf func(string, ...any) + debugWriteLoggerf func(string, ...any) frameCache *http2frameCache // nil if frames aren't reused (default) } @@ -3061,7 +3061,7 @@ func http2curGoroutineID() uint64 { } var http2littleBuf = sync.Pool{ - New: func() interface{} { + New: func() any { buf := make([]byte, 64) return &buf }, @@ -3468,7 +3468,7 @@ func http2newBufferedWriter(w io.Writer) *http2bufferedWriter { const http2bufWriterPoolBufferSize = 4 << 10 var http2bufWriterPool = sync.Pool{ - New: func() interface{} { + New: func() any { return bufio.NewWriterSize(nil, http2bufWriterPoolBufferSize) }, } @@ -3540,7 +3540,7 @@ type http2connectionStater interface { ConnectionState() tls.ConnectionState } -var http2sorterPool = sync.Pool{New: func() interface{} { return new(http2sorter) }} +var http2sorterPool = sync.Pool{New: func() any { return new(http2sorter) }} type http2sorter struct { v []string // owned by sorter @@ -3781,7 +3781,7 @@ var ( ) var http2responseWriterStatePool = sync.Pool{ - New: func() interface{} { + New: func() any { rws := &http2responseWriterState{} rws.bw = bufio.NewWriterSize(http2chunkWriter{rws}, http2handlerChunkWriteSize) return rws @@ -3793,7 +3793,7 @@ var ( http2testHookOnConn func() http2testHookGetServerConn func(*http2serverConn) http2testHookOnPanicMu *sync.Mutex // nil except in tests - http2testHookOnPanic func(sc *http2serverConn, panicVal interface{}) (rePanic bool) + http2testHookOnPanic func(sc *http2serverConn, panicVal any) (rePanic bool) ) // Server is an HTTP/2 server. @@ -4086,7 +4086,7 @@ func (s *http2Server) ServeConn(c net.Conn, opts *http2ServeConnOpts) { streams: make(map[uint32]*http2stream), readFrameCh: make(chan http2readFrameResult), wantWriteFrameCh: make(chan http2FrameWriteRequest, 8), - serveMsgCh: make(chan interface{}, 8), + serveMsgCh: make(chan any, 8), wroteFrameCh: make(chan http2frameWriteResult, 1), // buffered; one send in writeFrameAsync bodyReadCh: make(chan http2bodyReadMsg), // buffering doesn't matter either way doneServing: make(chan struct{}), @@ -4216,7 +4216,7 @@ type http2serverConn struct { wantWriteFrameCh chan http2FrameWriteRequest // from handlers -> serve wroteFrameCh chan http2frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes bodyReadCh chan http2bodyReadMsg // from handlers -> serve - serveMsgCh chan interface{} // misc messages & code to send to / run on the serve loop + serveMsgCh chan any // misc messages & code to send to / run on the serve loop flow http2flow // conn-wide (not stream-specific) outbound flow control inflow http2flow // conn-wide inbound flow control tlsState *tls.ConnectionState // shared by all handlers, like net/http @@ -4351,13 +4351,13 @@ func (sc *http2serverConn) setConnState(state ConnState) { } } -func (sc *http2serverConn) vlogf(format string, args ...interface{}) { +func (sc *http2serverConn) vlogf(format string, args ...any) { if http2VerboseLogs { sc.logf(format, args...) } } -func (sc *http2serverConn) logf(format string, args ...interface{}) { +func (sc *http2serverConn) logf(format string, args ...any) { if lg := sc.hs.ErrorLog; lg != nil { lg.Printf(format, args...) } else { @@ -4409,7 +4409,7 @@ func http2isClosedConnError(err error) bool { return false } -func (sc *http2serverConn) condlogf(err error, format string, args ...interface{}) { +func (sc *http2serverConn) condlogf(err error, format string, args ...any) { if err == nil { return } @@ -4679,7 +4679,7 @@ func (sc *http2serverConn) onIdleTimer() { sc.sendServeMsg(http2idleTimerMsg) } func (sc *http2serverConn) onShutdownTimer() { sc.sendServeMsg(http2shutdownTimerMsg) } -func (sc *http2serverConn) sendServeMsg(msg interface{}) { +func (sc *http2serverConn) sendServeMsg(msg any) { sc.serveG.checkNotOn() // NOT select { case sc.serveMsgCh <- msg: @@ -4721,11 +4721,11 @@ func (sc *http2serverConn) readPreface() error { } var http2errChanPool = sync.Pool{ - New: func() interface{} { return make(chan error, 1) }, + New: func() any { return make(chan error, 1) }, } var http2writeDataPool = sync.Pool{ - New: func() interface{} { return new(http2writeData) }, + New: func() any { return new(http2writeData) }, } // writeDataFromHandler writes DATA response frames from a handler on @@ -6712,7 +6712,7 @@ func http2new400Handler(err error) HandlerFunc { // disabled. See comments on h1ServerShutdownChan above for why // the code is written this way. func http2h1ServerKeepAlivesDisabled(hs *Server) bool { - var x interface{} = hs + var x any = hs type I interface { doKeepAlives() bool } @@ -9577,21 +9577,21 @@ var ( http2errRequestHeaderListSize = errors.New("http2: request header list larger than peer's advertised limit") ) -func (cc *http2ClientConn) logf(format string, args ...interface{}) { +func (cc *http2ClientConn) logf(format string, args ...any) { cc.t.logf(format, args...) } -func (cc *http2ClientConn) vlogf(format string, args ...interface{}) { +func (cc *http2ClientConn) vlogf(format string, args ...any) { cc.t.vlogf(format, args...) } -func (t *http2Transport) vlogf(format string, args ...interface{}) { +func (t *http2Transport) vlogf(format string, args ...any) { if http2VerboseLogs { t.logf(format, args...) } } -func (t *http2Transport) logf(format string, args ...interface{}) { +func (t *http2Transport) logf(format string, args ...any) { log.Printf(format, args...) } diff --git a/src/net/http/header.go b/src/net/http/header.go index 5c77cbb882..6487e5025d 100644 --- a/src/net/http/header.go +++ b/src/net/http/header.go @@ -157,7 +157,7 @@ func (s *headerSorter) Swap(i, j int) { s.kvs[i], s.kvs[j] = s.kvs[j], s.kv func (s *headerSorter) Less(i, j int) bool { return s.kvs[i].key < s.kvs[j].key } var headerSorterPool = sync.Pool{ - New: func() interface{} { return new(headerSorter) }, + New: func() any { return new(headerSorter) }, } // sortedKeyValues returns h's keys sorted in the returned kvs diff --git a/src/net/http/httptrace/trace.go b/src/net/http/httptrace/trace.go index 5777c91747..6af30f78d1 100644 --- a/src/net/http/httptrace/trace.go +++ b/src/net/http/httptrace/trace.go @@ -50,7 +50,7 @@ func WithClientTrace(ctx context.Context, trace *ClientTrace) context.Context { } } if trace.DNSDone != nil { - nt.DNSDone = func(netIPs []interface{}, coalesced bool, err error) { + nt.DNSDone = func(netIPs []any, coalesced bool, err error) { addrs := make([]net.IPAddr, len(netIPs)) for i, ip := range netIPs { addrs[i] = ip.(net.IPAddr) diff --git a/src/net/http/httputil/dump_test.go b/src/net/http/httputil/dump_test.go index 366cc8239a..5df2ee8075 100644 --- a/src/net/http/httputil/dump_test.go +++ b/src/net/http/httputil/dump_test.go @@ -31,7 +31,7 @@ type dumpTest struct { Req *http.Request GetReq func() *http.Request - Body interface{} // optional []byte or func() io.ReadCloser to populate Req.Body + Body any // optional []byte or func() io.ReadCloser to populate Req.Body WantDump string WantDumpOut string diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go index 71849bb8f7..319e2a3f3f 100644 --- a/src/net/http/httputil/reverseproxy.go +++ b/src/net/http/httputil/reverseproxy.go @@ -484,7 +484,7 @@ func (p *ReverseProxy) copyBuffer(dst io.Writer, src io.Reader, buf []byte) (int } } -func (p *ReverseProxy) logf(format string, args ...interface{}) { +func (p *ReverseProxy) logf(format string, args ...any) { if p.ErrorLog != nil { p.ErrorLog.Printf(format, args...) } else { diff --git a/src/net/http/omithttp2.go b/src/net/http/omithttp2.go index 63c0e92d6a..3316f55c6d 100644 --- a/src/net/http/omithttp2.go +++ b/src/net/http/omithttp2.go @@ -26,7 +26,7 @@ const http2NextProtoTLS = "h2" type http2Transport struct { MaxHeaderListSize uint32 - ConnPool interface{} + ConnPool any } func (*http2Transport) RoundTrip(*Request) (*Response, error) { panic(noHTTP2) } @@ -56,9 +56,9 @@ type http2Server struct { NewWriteScheduler func() http2WriteScheduler } -type http2WriteScheduler interface{} +type http2WriteScheduler any -func http2NewPriorityWriteScheduler(interface{}) http2WriteScheduler { panic(noHTTP2) } +func http2NewPriorityWriteScheduler(any) http2WriteScheduler { panic(noHTTP2) } func http2ConfigureServer(s *Server, conf *http2Server) error { panic(noHTTP2) } diff --git a/src/net/http/requestwrite_test.go b/src/net/http/requestwrite_test.go index 1157bdfff9..bdc1e3c508 100644 --- a/src/net/http/requestwrite_test.go +++ b/src/net/http/requestwrite_test.go @@ -20,7 +20,7 @@ import ( type reqWriteTest struct { Req Request - Body interface{} // optional []byte or func() io.ReadCloser to populate Req.Body + Body any // optional []byte or func() io.ReadCloser to populate Req.Body // Any of these three may be empty to skip that test. WantWrite string // Request.Write diff --git a/src/net/http/response_test.go b/src/net/http/response_test.go index 8eef65474e..5a735b0215 100644 --- a/src/net/http/response_test.go +++ b/src/net/http/response_test.go @@ -646,8 +646,8 @@ type readerAndCloser struct { func TestReadResponseCloseInMiddle(t *testing.T) { t.Parallel() for _, test := range readResponseCloseInMiddleTests { - fatalf := func(format string, args ...interface{}) { - args = append([]interface{}{test.chunked, test.compressed}, args...) + fatalf := func(format string, args ...any) { + args = append([]any{test.chunked, test.compressed}, args...) t.Fatalf("on test chunked=%v, compressed=%v: "+format, args...) } checkErr := func(err error, msg string) { @@ -732,7 +732,7 @@ func TestReadResponseCloseInMiddle(t *testing.T) { } } -func diff(t *testing.T, prefix string, have, want interface{}) { +func diff(t *testing.T, prefix string, have, want any) { t.Helper() hv := reflect.ValueOf(have).Elem() wv := reflect.ValueOf(want).Elem() @@ -849,10 +849,10 @@ func TestReadResponseErrors(t *testing.T) { type testCase struct { name string // optional, defaults to in in string - wantErr interface{} // nil, err value, or string substring + wantErr any // nil, err value, or string substring } - status := func(s string, wantErr interface{}) testCase { + status := func(s string, wantErr any) testCase { if wantErr == true { wantErr = "malformed HTTP status code" } @@ -863,7 +863,7 @@ func TestReadResponseErrors(t *testing.T) { } } - version := func(s string, wantErr interface{}) testCase { + version := func(s string, wantErr any) testCase { if wantErr == true { wantErr = "malformed HTTP version" } @@ -874,7 +874,7 @@ func TestReadResponseErrors(t *testing.T) { } } - contentLength := func(status, body string, wantErr interface{}) testCase { + contentLength := func(status, body string, wantErr any) testCase { return testCase{ name: fmt.Sprintf("status %q %q", status, body), in: fmt.Sprintf("HTTP/1.1 %s\r\n%s", status, body), @@ -947,7 +947,7 @@ func TestReadResponseErrors(t *testing.T) { // wantErr can be nil, an error value to match exactly, or type string to // match a substring. -func matchErr(err error, wantErr interface{}) error { +func matchErr(err error, wantErr any) error { if err == nil { if wantErr == nil { return nil diff --git a/src/net/http/roundtrip_js.go b/src/net/http/roundtrip_js.go index dd042e9a01..01c0600ba5 100644 --- a/src/net/http/roundtrip_js.go +++ b/src/net/http/roundtrip_js.go @@ -118,7 +118,7 @@ func (t *Transport) RoundTrip(req *Request) (*Response, error) { errCh = make(chan error, 1) success, failure js.Func ) - success = js.FuncOf(func(this js.Value, args []js.Value) interface{} { + success = js.FuncOf(func(this js.Value, args []js.Value) any { success.Release() failure.Release() @@ -182,7 +182,7 @@ func (t *Transport) RoundTrip(req *Request) (*Response, error) { return nil }) - failure = js.FuncOf(func(this js.Value, args []js.Value) interface{} { + failure = js.FuncOf(func(this js.Value, args []js.Value) any { success.Release() failure.Release() errCh <- fmt.Errorf("net/http: fetch() failed: %s", args[0].Get("message").String()) @@ -223,7 +223,7 @@ func (r *streamReader) Read(p []byte) (n int, err error) { bCh = make(chan []byte, 1) errCh = make(chan error, 1) ) - success := js.FuncOf(func(this js.Value, args []js.Value) interface{} { + success := js.FuncOf(func(this js.Value, args []js.Value) any { result := args[0] if result.Get("done").Bool() { errCh <- io.EOF @@ -235,7 +235,7 @@ func (r *streamReader) Read(p []byte) (n int, err error) { return nil }) defer success.Release() - failure := js.FuncOf(func(this js.Value, args []js.Value) interface{} { + failure := js.FuncOf(func(this js.Value, args []js.Value) any { // Assumes it's a TypeError. See // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError // for more information on this type. See @@ -289,7 +289,7 @@ func (r *arrayReader) Read(p []byte) (n int, err error) { bCh = make(chan []byte, 1) errCh = make(chan error, 1) ) - success := js.FuncOf(func(this js.Value, args []js.Value) interface{} { + success := js.FuncOf(func(this js.Value, args []js.Value) any { // Wrap the input ArrayBuffer with a Uint8Array uint8arrayWrapper := uint8Array.New(args[0]) value := make([]byte, uint8arrayWrapper.Get("byteLength").Int()) @@ -298,7 +298,7 @@ func (r *arrayReader) Read(p []byte) (n int, err error) { return nil }) defer success.Release() - failure := js.FuncOf(func(this js.Value, args []js.Value) interface{} { + failure := js.FuncOf(func(this js.Value, args []js.Value) any { // Assumes it's a TypeError. See // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError // for more information on this type. diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index d46400ef75..fb18cb2c6f 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -2147,7 +2147,7 @@ func TestInvalidTrailerClosesConnection(t *testing.T) { // Read and Write. type slowTestConn struct { // over multiple calls to Read, time.Durations are slept, strings are read. - script []interface{} + script []any closec chan bool mu sync.Mutex // guards rd/wd @@ -2239,7 +2239,7 @@ func TestRequestBodyTimeoutClosesConnection(t *testing.T) { defer afterTest(t) for _, handler := range testHandlerBodyConsumers { conn := &slowTestConn{ - script: []interface{}{ + script: []any{ "POST /public HTTP/1.1\r\n" + "Host: test\r\n" + "Content-Length: 10000\r\n" + @@ -2766,7 +2766,7 @@ func TestHandlerPanicWithHijack(t *testing.T) { testHandlerPanic(t, true, h1Mode, nil, "intentional death for testing") } -func testHandlerPanic(t *testing.T, withHijack, h2 bool, wrapper func(Handler) Handler, panicValue interface{}) { +func testHandlerPanic(t *testing.T, withHijack, h2 bool, wrapper func(Handler) Handler, panicValue any) { defer afterTest(t) // Unlike the other tests that set the log output to io.Discard // to quiet the output, this test uses a pipe. The pipe serves three @@ -3934,7 +3934,7 @@ func testTransportAndServerSharedBodyRace(t *testing.T, h2 bool) { // this test fails, it hangs. This helps debugging and I've // added this enough times "temporarily". It now gets added // full time. - errorf := func(format string, args ...interface{}) { + errorf := func(format string, args ...any) { v := fmt.Sprintf(format, args...) println(v) t.Error(v) @@ -3943,10 +3943,10 @@ func testTransportAndServerSharedBodyRace(t *testing.T, h2 bool) { unblockBackend := make(chan bool) backend := newClientServerTest(t, h2, HandlerFunc(func(rw ResponseWriter, req *Request) { gone := rw.(CloseNotifier).CloseNotify() - didCopy := make(chan interface{}) + didCopy := make(chan any) go func() { n, err := io.CopyN(rw, req.Body, bodySize) - didCopy <- []interface{}{n, err} + didCopy <- []any{n, err} }() isGone := false Loop: @@ -4938,7 +4938,7 @@ func TestServerContext_LocalAddrContextKey_h2(t *testing.T) { func testServerContext_LocalAddrContextKey(t *testing.T, h2 bool) { setParallel(t) defer afterTest(t) - ch := make(chan interface{}, 1) + ch := make(chan any, 1) cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { ch <- r.Context().Value(LocalAddrContextKey) })) @@ -6293,7 +6293,7 @@ func testContentEncodingNoSniffing(t *testing.T, h2 bool) { // setting contentEncoding as an interface instead of a string // directly, so as to differentiate between 3 states: // unset, empty string "" and set string "foo/bar". - contentEncoding interface{} + contentEncoding any wantContentType string } diff --git a/src/net/http/server.go b/src/net/http/server.go index f0b0e86e91..ddc799bd9e 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -798,7 +798,7 @@ var ( ) var copyBufPool = sync.Pool{ - New: func() interface{} { + New: func() any { b := make([]byte, 32*1024) return &b }, @@ -3190,7 +3190,7 @@ func (srv *Server) SetKeepAlivesEnabled(v bool) { // TODO: Issue 26303: close HTTP/2 conns as soon as they become idle. } -func (s *Server) logf(format string, args ...interface{}) { +func (s *Server) logf(format string, args ...any) { if s.ErrorLog != nil { s.ErrorLog.Printf(format, args...) } else { @@ -3201,7 +3201,7 @@ func (s *Server) logf(format string, args ...interface{}) { // logf prints to the ErrorLog of the *Server associated with request r // via ServerContextKey. If there's no associated server, or if ErrorLog // is nil, logging is done via the log package's standard logger. -func logf(r *Request, format string, args ...interface{}) { +func logf(r *Request, format string, args ...any) { s, _ := r.Context().Value(ServerContextKey).(*Server) if s != nil && s.ErrorLog != nil { s.ErrorLog.Printf(format, args...) @@ -3364,7 +3364,7 @@ func (h *timeoutHandler) ServeHTTP(w ResponseWriter, r *Request) { h: make(Header), req: r, } - panicChan := make(chan interface{}, 1) + panicChan := make(chan any, 1) go func() { defer func() { if p := recover(); p != nil { diff --git a/src/net/http/transfer.go b/src/net/http/transfer.go index 2be1c9fa3c..6d51178ee9 100644 --- a/src/net/http/transfer.go +++ b/src/net/http/transfer.go @@ -73,7 +73,7 @@ type transferWriter struct { ByteReadCh chan readResult // non-nil if probeRequestBody called } -func newTransferWriter(r interface{}) (t *transferWriter, err error) { +func newTransferWriter(r any) (t *transferWriter, err error) { t = &transferWriter{} // Extract relevant fields @@ -481,7 +481,7 @@ func suppressedHeaders(status int) []string { } // msg is *Request or *Response. -func readTransfer(msg interface{}, r *bufio.Reader) (err error) { +func readTransfer(msg any, r *bufio.Reader) (err error) { t := &transferReader{RequestMethod: "GET"} // Unify input @@ -809,7 +809,7 @@ func fixTrailer(header Header, chunked bool) (Header, error) { // and then reads the trailer if necessary. type body struct { src io.Reader - hdr interface{} // non-nil (Response or Request) value means read trailer + hdr any // non-nil (Response or Request) value means read trailer r *bufio.Reader // underlying wire-format reader for the trailer closing bool // is the connection to be closed after reading body? doEarlyClose bool // whether Close should stop early diff --git a/src/net/http/transport.go b/src/net/http/transport.go index f2d2f79280..5fe3e6ebb4 100644 --- a/src/net/http/transport.go +++ b/src/net/http/transport.go @@ -2668,8 +2668,8 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err // a t.Logf func. See export_test.go's Request.WithT method. type tLogKey struct{} -func (tr *transportRequest) logf(format string, args ...interface{}) { - if logf, ok := tr.Request.Context().Value(tLogKey{}).(func(string, ...interface{})); ok { +func (tr *transportRequest) logf(format string, args ...any) { + if logf, ok := tr.Request.Context().Value(tLogKey{}).(func(string, ...any)); ok { logf(time.Now().Format(time.RFC3339Nano)+": "+format, args...) } } diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go index 0cdd946de4..e5d60afb1b 100644 --- a/src/net/http/transport_test.go +++ b/src/net/http/transport_test.go @@ -776,7 +776,7 @@ func TestTransportServerClosingUnexpectedly(t *testing.T) { c := ts.Client() fetch := func(n, retries int) string { - condFatalf := func(format string, arg ...interface{}) { + condFatalf := func(format string, arg ...any) { if retries <= 0 { t.Fatalf(format, arg...) } @@ -3514,7 +3514,7 @@ func TestRetryRequestsOnError(t *testing.T) { mu sync.Mutex logbuf bytes.Buffer ) - logf := func(format string, args ...interface{}) { + logf := func(format string, args ...any) { mu.Lock() defer mu.Unlock() fmt.Fprintf(&logbuf, format, args...) @@ -4491,7 +4491,7 @@ func testTransportEventTrace(t *testing.T, h2 bool, noHooks bool) { var mu sync.Mutex // guards buf var buf bytes.Buffer - logf := func(format string, args ...interface{}) { + logf := func(format string, args ...any) { mu.Lock() defer mu.Unlock() fmt.Fprintf(&buf, format, args...) @@ -4650,7 +4650,7 @@ func testTransportEventTrace(t *testing.T, h2 bool, noHooks bool) { func TestTransportEventTraceTLSVerify(t *testing.T) { var mu sync.Mutex var buf bytes.Buffer - logf := func(format string, args ...interface{}) { + logf := func(format string, args ...any) { mu.Lock() defer mu.Unlock() fmt.Fprintf(&buf, format, args...) @@ -4736,7 +4736,7 @@ func TestTransportEventTraceRealDNS(t *testing.T) { var mu sync.Mutex // guards buf var buf bytes.Buffer - logf := func(format string, args ...interface{}) { + logf := func(format string, args ...any) { mu.Lock() defer mu.Unlock() fmt.Fprintf(&buf, format, args...) diff --git a/src/net/ip_test.go b/src/net/ip_test.go index 10e77f3bdb..777461ad27 100644 --- a/src/net/ip_test.go +++ b/src/net/ip_test.go @@ -718,7 +718,7 @@ var ipAddrScopeTests = []struct { {IP.IsPrivate, IP{0xfe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false}, } -func name(f interface{}) string { +func name(f any) string { return runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name() } diff --git a/src/net/listen_test.go b/src/net/listen_test.go index 09ffbb31a1..59c0112122 100644 --- a/src/net/listen_test.go +++ b/src/net/listen_test.go @@ -379,7 +379,7 @@ func differentWildcardAddr(i, j string) bool { return true } -func checkFirstListener(network string, ln interface{}) error { +func checkFirstListener(network string, ln any) error { switch network { case "tcp": fd := ln.(*TCPListener).fd diff --git a/src/net/lookup.go b/src/net/lookup.go index ff4ddbeb82..c7b8dc6905 100644 --- a/src/net/lookup.go +++ b/src/net/lookup.go @@ -265,7 +265,7 @@ type onlyValuesCtx struct { var _ context.Context = (*onlyValuesCtx)(nil) // Value performs a lookup if the original context hasn't expired. -func (ovc *onlyValuesCtx) Value(key interface{}) interface{} { +func (ovc *onlyValuesCtx) Value(key any) any { select { case <-ovc.lookupValues.Done(): return nil @@ -314,7 +314,7 @@ func (r *Resolver) lookupIPAddr(ctx context.Context, network, host string) ([]IP lookupKey := network + "\000" + host dnsWaitGroup.Add(1) - ch, called := r.getLookupGroup().DoChan(lookupKey, func() (interface{}, error) { + ch, called := r.getLookupGroup().DoChan(lookupKey, func() (any, error) { defer dnsWaitGroup.Done() return testHookLookupIP(lookupGroupCtx, resolverFunc, network, host) }) @@ -377,7 +377,7 @@ func (r *Resolver) lookupIPAddr(ctx context.Context, network, host string) ([]IP // lookupIPReturn turns the return values from singleflight.Do into // the return values from LookupIP. -func lookupIPReturn(addrsi interface{}, err error, shared bool) ([]IPAddr, error) { +func lookupIPReturn(addrsi any, err error, shared bool) ([]IPAddr, error) { if err != nil { return nil, err } @@ -391,8 +391,8 @@ func lookupIPReturn(addrsi interface{}, err error, shared bool) ([]IPAddr, error } // ipAddrsEface returns an empty interface slice of addrs. -func ipAddrsEface(addrs []IPAddr) []interface{} { - s := make([]interface{}, len(addrs)) +func ipAddrsEface(addrs []IPAddr) []any { + s := make([]any, len(addrs)) for i, v := range addrs { s[i] = v } diff --git a/src/net/lookup_test.go b/src/net/lookup_test.go index 5b3a3e24b2..d71a18c684 100644 --- a/src/net/lookup_test.go +++ b/src/net/lookup_test.go @@ -1057,7 +1057,7 @@ func TestLookupIPAddrPreservesContextValues(t *testing.T) { defer func() { testHookLookupIP = origTestHookLookupIP }() keyValues := []struct { - key, value interface{} + key, value any }{ {"key-1", 12}, {384, "value2"}, diff --git a/src/net/lookup_windows_test.go b/src/net/lookup_windows_test.go index f726ef0f34..9254733364 100644 --- a/src/net/lookup_windows_test.go +++ b/src/net/lookup_windows_test.go @@ -21,7 +21,7 @@ import ( var nslookupTestServers = []string{"mail.golang.com", "gmail.com"} var lookupTestIPs = []string{"8.8.8.8", "1.1.1.1"} -func toJson(v interface{}) string { +func toJson(v any) string { data, _ := json.Marshal(v) return string(data) } diff --git a/src/net/mail/message.go b/src/net/mail/message.go index c120316730..985b6fcae2 100644 --- a/src/net/mail/message.go +++ b/src/net/mail/message.go @@ -35,7 +35,7 @@ var debug = debugT(false) type debugT bool -func (d debugT) Printf(format string, args ...interface{}) { +func (d debugT) Printf(format string, args ...any) { if d { log.Printf(format, args...) } diff --git a/src/net/netip/netip_test.go b/src/net/netip/netip_test.go index 520695cdfb..d988864827 100644 --- a/src/net/netip/netip_test.go +++ b/src/net/netip/netip_test.go @@ -1451,7 +1451,7 @@ type ip4i struct { flags2 byte flags3 byte flags4 byte - ipv6 interface{} + ipv6 any } func newip4i_v4(a, b, c, d byte) ip4i { diff --git a/src/net/platform_test.go b/src/net/platform_test.go index 7d92a0de5d..c522ba2829 100644 --- a/src/net/platform_test.go +++ b/src/net/platform_test.go @@ -173,7 +173,7 @@ func testableListenArgs(network, address, client string) bool { return true } -func condFatalf(t *testing.T, network string, format string, args ...interface{}) { +func condFatalf(t *testing.T, network string, format string, args ...any) { t.Helper() // A few APIs like File and Read/WriteMsg{UDP,IP} are not // fully implemented yet on Plan 9 and Windows. diff --git a/src/net/rpc/client.go b/src/net/rpc/client.go index 60bb2cc99f..42d13519b1 100644 --- a/src/net/rpc/client.go +++ b/src/net/rpc/client.go @@ -27,11 +27,11 @@ var ErrShutdown = errors.New("connection is shut down") // Call represents an active RPC. type Call struct { - ServiceMethod string // The name of the service and method to call. - Args interface{} // The argument to the function (*struct). - Reply interface{} // The reply from the function (*struct). - Error error // After completion, the error status. - Done chan *Call // Receives *Call when Go is complete. + ServiceMethod string // The name of the service and method to call. + Args any // The argument to the function (*struct). + Reply any // The reply from the function (*struct). + Error error // After completion, the error status. + Done chan *Call // Receives *Call when Go is complete. } // Client represents an RPC Client. @@ -61,9 +61,9 @@ type Client struct { // discarded. // See NewClient's comment for information about concurrent access. type ClientCodec interface { - WriteRequest(*Request, interface{}) error + WriteRequest(*Request, any) error ReadResponseHeader(*Response) error - ReadResponseBody(interface{}) error + ReadResponseBody(any) error Close() error } @@ -214,7 +214,7 @@ type gobClientCodec struct { encBuf *bufio.Writer } -func (c *gobClientCodec) WriteRequest(r *Request, body interface{}) (err error) { +func (c *gobClientCodec) WriteRequest(r *Request, body any) (err error) { if err = c.enc.Encode(r); err != nil { return } @@ -228,7 +228,7 @@ func (c *gobClientCodec) ReadResponseHeader(r *Response) error { return c.dec.Decode(r) } -func (c *gobClientCodec) ReadResponseBody(body interface{}) error { +func (c *gobClientCodec) ReadResponseBody(body any) error { return c.dec.Decode(body) } @@ -295,7 +295,7 @@ func (client *Client) Close() error { // the invocation. The done channel will signal when the call is complete by returning // the same Call object. If done is nil, Go will allocate a new channel. // If non-nil, done must be buffered or Go will deliberately crash. -func (client *Client) Go(serviceMethod string, args interface{}, reply interface{}, done chan *Call) *Call { +func (client *Client) Go(serviceMethod string, args any, reply any, done chan *Call) *Call { call := new(Call) call.ServiceMethod = serviceMethod call.Args = args @@ -317,7 +317,7 @@ func (client *Client) Go(serviceMethod string, args interface{}, reply interface } // Call invokes the named function, waits for it to complete, and returns its error status. -func (client *Client) Call(serviceMethod string, args interface{}, reply interface{}) error { +func (client *Client) Call(serviceMethod string, args any, reply any) error { call := <-client.Go(serviceMethod, args, reply, make(chan *Call, 1)).Done return call.Error } diff --git a/src/net/rpc/client_test.go b/src/net/rpc/client_test.go index 38a10ce0b3..ffc12faeda 100644 --- a/src/net/rpc/client_test.go +++ b/src/net/rpc/client_test.go @@ -17,8 +17,8 @@ type shutdownCodec struct { closed bool } -func (c *shutdownCodec) WriteRequest(*Request, interface{}) error { return nil } -func (c *shutdownCodec) ReadResponseBody(interface{}) error { return nil } +func (c *shutdownCodec) WriteRequest(*Request, any) error { return nil } +func (c *shutdownCodec) ReadResponseBody(any) error { return nil } func (c *shutdownCodec) ReadResponseHeader(*Response) error { c.responded <- 1 return errors.New("shutdownCodec ReadResponseHeader") diff --git a/src/net/rpc/debug.go b/src/net/rpc/debug.go index a1d799ff19..9e499fd984 100644 --- a/src/net/rpc/debug.go +++ b/src/net/rpc/debug.go @@ -72,7 +72,7 @@ type debugHTTP struct { func (server debugHTTP) ServeHTTP(w http.ResponseWriter, req *http.Request) { // Build a sorted version of the data. var services serviceArray - server.serviceMap.Range(func(snamei, svci interface{}) bool { + server.serviceMap.Range(func(snamei, svci any) bool { svc := svci.(*service) ds := debugService{svc, snamei.(string), make(methodArray, 0, len(svc.method))} for mname, method := range svc.method { diff --git a/src/net/rpc/jsonrpc/all_test.go b/src/net/rpc/jsonrpc/all_test.go index 667f839f58..f4e1278d03 100644 --- a/src/net/rpc/jsonrpc/all_test.go +++ b/src/net/rpc/jsonrpc/all_test.go @@ -28,9 +28,9 @@ type Reply struct { type Arith int type ArithAddResp struct { - Id interface{} `json:"id"` - Result Reply `json:"result"` - Error interface{} `json:"error"` + Id any `json:"id"` + Result Reply `json:"result"` + Error any `json:"error"` } func (t *Arith) Add(args *Args, reply *Reply) error { diff --git a/src/net/rpc/jsonrpc/client.go b/src/net/rpc/jsonrpc/client.go index e6359bed59..c473017d26 100644 --- a/src/net/rpc/jsonrpc/client.go +++ b/src/net/rpc/jsonrpc/client.go @@ -44,12 +44,12 @@ func NewClientCodec(conn io.ReadWriteCloser) rpc.ClientCodec { } type clientRequest struct { - Method string `json:"method"` - Params [1]interface{} `json:"params"` - Id uint64 `json:"id"` + Method string `json:"method"` + Params [1]any `json:"params"` + Id uint64 `json:"id"` } -func (c *clientCodec) WriteRequest(r *rpc.Request, param interface{}) error { +func (c *clientCodec) WriteRequest(r *rpc.Request, param any) error { c.mutex.Lock() c.pending[r.Seq] = r.ServiceMethod c.mutex.Unlock() @@ -62,7 +62,7 @@ func (c *clientCodec) WriteRequest(r *rpc.Request, param interface{}) error { type clientResponse struct { Id uint64 `json:"id"` Result *json.RawMessage `json:"result"` - Error interface{} `json:"error"` + Error any `json:"error"` } func (r *clientResponse) reset() { @@ -97,7 +97,7 @@ func (c *clientCodec) ReadResponseHeader(r *rpc.Response) error { return nil } -func (c *clientCodec) ReadResponseBody(x interface{}) error { +func (c *clientCodec) ReadResponseBody(x any) error { if x == nil { return nil } diff --git a/src/net/rpc/jsonrpc/server.go b/src/net/rpc/jsonrpc/server.go index 40e4e6f2aa..3ee4ddfef2 100644 --- a/src/net/rpc/jsonrpc/server.go +++ b/src/net/rpc/jsonrpc/server.go @@ -57,8 +57,8 @@ func (r *serverRequest) reset() { type serverResponse struct { Id *json.RawMessage `json:"id"` - Result interface{} `json:"result"` - Error interface{} `json:"error"` + Result any `json:"result"` + Error any `json:"error"` } func (c *serverCodec) ReadRequestHeader(r *rpc.Request) error { @@ -81,7 +81,7 @@ func (c *serverCodec) ReadRequestHeader(r *rpc.Request) error { return nil } -func (c *serverCodec) ReadRequestBody(x interface{}) error { +func (c *serverCodec) ReadRequestBody(x any) error { if x == nil { return nil } @@ -92,14 +92,14 @@ func (c *serverCodec) ReadRequestBody(x interface{}) error { // RPC params is struct. // Unmarshal into array containing struct for now. // Should think about making RPC more general. - var params [1]interface{} + var params [1]any params[0] = x return json.Unmarshal(*c.req.Params, ¶ms) } var null = json.RawMessage([]byte("null")) -func (c *serverCodec) WriteResponse(r *rpc.Response, x interface{}) error { +func (c *serverCodec) WriteResponse(r *rpc.Response, x any) error { c.mutex.Lock() b, ok := c.pending[r.Seq] if !ok { diff --git a/src/net/rpc/server.go b/src/net/rpc/server.go index 223a53cfa7..d5207a42cf 100644 --- a/src/net/rpc/server.go +++ b/src/net/rpc/server.go @@ -221,13 +221,13 @@ func isExportedOrBuiltinType(t reflect.Type) bool { // no suitable methods. It also logs the error using package log. // The client accesses each method using a string of the form "Type.Method", // where Type is the receiver's concrete type. -func (server *Server) Register(rcvr interface{}) error { +func (server *Server) Register(rcvr any) error { return server.register(rcvr, "", false) } // RegisterName is like Register but uses the provided name for the type // instead of the receiver's concrete type. -func (server *Server) RegisterName(name string, rcvr interface{}) error { +func (server *Server) RegisterName(name string, rcvr any) error { return server.register(rcvr, name, true) } @@ -235,7 +235,7 @@ func (server *Server) RegisterName(name string, rcvr interface{}) error { // To debug registration, recompile the package with this set to true. const logRegisterError = false -func (server *Server) register(rcvr interface{}, name string, useName bool) error { +func (server *Server) register(rcvr any, name string, useName bool) error { s := new(service) s.typ = reflect.TypeOf(rcvr) s.rcvr = reflect.ValueOf(rcvr) @@ -344,7 +344,7 @@ func suitableMethods(typ reflect.Type, logErr bool) map[string]*methodType { // contains an error when it is used. var invalidRequest = struct{}{} -func (server *Server) sendResponse(sending *sync.Mutex, req *Request, reply interface{}, codec ServerCodec, errmsg string) { +func (server *Server) sendResponse(sending *sync.Mutex, req *Request, reply any, codec ServerCodec, errmsg string) { resp := server.getResponse() // Encode the response header resp.ServiceMethod = req.ServiceMethod @@ -401,11 +401,11 @@ func (c *gobServerCodec) ReadRequestHeader(r *Request) error { return c.dec.Decode(r) } -func (c *gobServerCodec) ReadRequestBody(body interface{}) error { +func (c *gobServerCodec) ReadRequestBody(body any) error { return c.dec.Decode(body) } -func (c *gobServerCodec) WriteResponse(r *Response, body interface{}) (err error) { +func (c *gobServerCodec) WriteResponse(r *Response, body any) (err error) { if err = c.enc.Encode(r); err != nil { if c.encBuf.Flush() == nil { // Gob couldn't encode the header. Should not happen, so if it does, @@ -636,11 +636,11 @@ func (server *Server) Accept(lis net.Listener) { } // Register publishes the receiver's methods in the DefaultServer. -func Register(rcvr interface{}) error { return DefaultServer.Register(rcvr) } +func Register(rcvr any) error { return DefaultServer.Register(rcvr) } // RegisterName is like Register but uses the provided name for the type // instead of the receiver's concrete type. -func RegisterName(name string, rcvr interface{}) error { +func RegisterName(name string, rcvr any) error { return DefaultServer.RegisterName(name, rcvr) } @@ -654,8 +654,8 @@ func RegisterName(name string, rcvr interface{}) error { // See NewClient's comment for information about concurrent access. type ServerCodec interface { ReadRequestHeader(*Request) error - ReadRequestBody(interface{}) error - WriteResponse(*Response, interface{}) error + ReadRequestBody(any) error + WriteResponse(*Response, any) error // Close can be called multiple times and must be idempotent. Close() error diff --git a/src/net/rpc/server_test.go b/src/net/rpc/server_test.go index e5d7fe0c8f..dc5f5decc7 100644 --- a/src/net/rpc/server_test.go +++ b/src/net/rpc/server_test.go @@ -427,7 +427,7 @@ func (codec *CodecEmulator) ReadRequestHeader(req *Request) error { return nil } -func (codec *CodecEmulator) ReadRequestBody(argv interface{}) error { +func (codec *CodecEmulator) ReadRequestBody(argv any) error { if codec.args == nil { return io.ErrUnexpectedEOF } @@ -435,7 +435,7 @@ func (codec *CodecEmulator) ReadRequestBody(argv interface{}) error { return nil } -func (codec *CodecEmulator) WriteResponse(resp *Response, reply interface{}) error { +func (codec *CodecEmulator) WriteResponse(resp *Response, reply any) error { if resp.Error != "" { codec.err = errors.New(resp.Error) } else { @@ -521,7 +521,7 @@ func TestRegistrationError(t *testing.T) { type WriteFailCodec int -func (WriteFailCodec) WriteRequest(*Request, interface{}) error { +func (WriteFailCodec) WriteRequest(*Request, any) error { // the panic caused by this error used to not unlock a lock. return errors.New("fail") } @@ -530,7 +530,7 @@ func (WriteFailCodec) ReadResponseHeader(*Response) error { select {} } -func (WriteFailCodec) ReadResponseBody(interface{}) error { +func (WriteFailCodec) ReadResponseBody(any) error { select {} } diff --git a/src/net/smtp/smtp.go b/src/net/smtp/smtp.go index bcccaa2597..c1f00a04e1 100644 --- a/src/net/smtp/smtp.go +++ b/src/net/smtp/smtp.go @@ -105,7 +105,7 @@ func (c *Client) Hello(localName string) error { } // cmd is a convenience function that sends a command and returns the response -func (c *Client) cmd(expectCode int, format string, args ...interface{}) (int, string, error) { +func (c *Client) cmd(expectCode int, format string, args ...any) (int, string, error) { id, err := c.Text.Cmd(format, args...) if err != nil { return 0, "", err diff --git a/src/net/textproto/textproto.go b/src/net/textproto/textproto.go index 8fd781e777..cc1a847e4e 100644 --- a/src/net/textproto/textproto.go +++ b/src/net/textproto/textproto.go @@ -111,7 +111,7 @@ func Dial(network, addr string) (*Conn, error) { // } // return c.ReadCodeLine(250) // -func (c *Conn) Cmd(format string, args ...interface{}) (id uint, err error) { +func (c *Conn) Cmd(format string, args ...any) (id uint, err error) { id = c.Next() c.StartRequest(id) err = c.PrintfLine(format, args...) diff --git a/src/net/textproto/writer.go b/src/net/textproto/writer.go index 33c146c022..2ece3f511b 100644 --- a/src/net/textproto/writer.go +++ b/src/net/textproto/writer.go @@ -26,7 +26,7 @@ var crnl = []byte{'\r', '\n'} var dotcrnl = []byte{'.', '\r', '\n'} // PrintfLine writes the formatted output followed by \r\n. -func (w *Writer) PrintfLine(format string, args ...interface{}) error { +func (w *Writer) PrintfLine(format string, args ...any) error { w.closeDot() fmt.Fprintf(w.W, format, args...) w.W.Write(crnl) diff --git a/src/net/url/example_test.go b/src/net/url/example_test.go index 87b6e74a85..a1913508f7 100644 --- a/src/net/url/example_test.go +++ b/src/net/url/example_test.go @@ -365,7 +365,7 @@ func ExampleURL_RequestURI() { // Output: /path?foo=bar } -func toJSON(m interface{}) string { +func toJSON(m any) string { js, err := json.Marshal(m) if err != nil { log.Fatal(err) diff --git a/src/net/url/url_test.go b/src/net/url/url_test.go index 7c807d7a38..664757b832 100644 --- a/src/net/url/url_test.go +++ b/src/net/url/url_test.go @@ -618,7 +618,7 @@ var urltests = []URLTest{ // more useful string for debugging than fmt's struct printer func ufmt(u *URL) string { - var user, pass interface{} + var user, pass any if u.User != nil { user = u.User.Username() if p, ok := u.User.Password(); ok { diff --git a/src/os/dir_unix.go b/src/os/dir_unix.go index 4eeb9ab86c..9b3871a3e8 100644 --- a/src/os/dir_unix.go +++ b/src/os/dir_unix.go @@ -27,7 +27,7 @@ const ( ) var dirBufPool = sync.Pool{ - New: func() interface{} { + New: func() any { // The buffer must be at least a block long. buf := make([]byte, blockSize) return &buf diff --git a/src/os/env_test.go b/src/os/env_test.go index 11b3b89725..f8d56ef8e0 100644 --- a/src/os/env_test.go +++ b/src/os/env_test.go @@ -66,7 +66,7 @@ func TestExpand(t *testing.T) { } } -var global interface{} +var global any func BenchmarkExpand(b *testing.B) { b.Run("noop", func(b *testing.B) { diff --git a/src/os/exec.go b/src/os/exec.go index 2beac55f89..9eb3166ecb 100644 --- a/src/os/exec.go +++ b/src/os/exec.go @@ -164,7 +164,7 @@ func (p *ProcessState) Success() bool { // Sys returns system-dependent exit information about // the process. Convert it to the appropriate underlying // type, such as syscall.WaitStatus on Unix, to access its contents. -func (p *ProcessState) Sys() interface{} { +func (p *ProcessState) Sys() any { return p.sys() } @@ -173,6 +173,6 @@ func (p *ProcessState) Sys() interface{} { // type, such as *syscall.Rusage on Unix, to access its contents. // (On Unix, *syscall.Rusage matches struct rusage as defined in the // getrusage(2) manual page.) -func (p *ProcessState) SysUsage() interface{} { +func (p *ProcessState) SysUsage() any { return p.sysUsage() } diff --git a/src/os/exec/exec.go b/src/os/exec/exec.go index 9551c22d6e..845b737e28 100644 --- a/src/os/exec/exec.go +++ b/src/os/exec/exec.go @@ -216,7 +216,7 @@ func (c *Cmd) String() string { // interfaceEqual protects against panics from doing equality tests on // two interfaces with non-comparable underlying types. -func interfaceEqual(a, b interface{}) bool { +func interfaceEqual(a, b any) bool { defer func() { recover() }() diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go index 81de018e09..92992a6d66 100644 --- a/src/os/exec/exec_test.go +++ b/src/os/exec/exec_test.go @@ -700,7 +700,7 @@ func TestHelperProcess(*testing.T) { cmd, args := args[0], args[1:] switch cmd { case "echo": - iargs := []interface{}{} + iargs := []any{} for _, s := range args { iargs = append(iargs, s) } diff --git a/src/os/exec_plan9.go b/src/os/exec_plan9.go index cc84f97669..69714ff798 100644 --- a/src/os/exec_plan9.go +++ b/src/os/exec_plan9.go @@ -115,11 +115,11 @@ func (p *ProcessState) success() bool { return p.status.ExitStatus() == 0 } -func (p *ProcessState) sys() interface{} { +func (p *ProcessState) sys() any { return p.status } -func (p *ProcessState) sysUsage() interface{} { +func (p *ProcessState) sysUsage() any { return p.status } diff --git a/src/os/exec_posix.go b/src/os/exec_posix.go index 07e2b36f62..d619984693 100644 --- a/src/os/exec_posix.go +++ b/src/os/exec_posix.go @@ -87,11 +87,11 @@ func (p *ProcessState) success() bool { return p.status.ExitStatus() == 0 } -func (p *ProcessState) sys() interface{} { +func (p *ProcessState) sys() any { return p.status } -func (p *ProcessState) sysUsage() interface{} { +func (p *ProcessState) sysUsage() any { return p.rusage } diff --git a/src/os/stat_plan9.go b/src/os/stat_plan9.go index 57ae6fb0bb..e20accf191 100644 --- a/src/os/stat_plan9.go +++ b/src/os/stat_plan9.go @@ -43,7 +43,7 @@ func fileInfoFromStat(d *syscall.Dir) *fileStat { } // arg is an open *File or a path string. -func dirstat(arg interface{}) (*syscall.Dir, error) { +func dirstat(arg any) (*syscall.Dir, error) { var name string var err error diff --git a/src/os/types_plan9.go b/src/os/types_plan9.go index 125da661b7..ccf4fd932e 100644 --- a/src/os/types_plan9.go +++ b/src/os/types_plan9.go @@ -15,13 +15,13 @@ type fileStat struct { size int64 mode FileMode modTime time.Time - sys interface{} + sys any } func (fs *fileStat) Size() int64 { return fs.size } func (fs *fileStat) Mode() FileMode { return fs.mode } func (fs *fileStat) ModTime() time.Time { return fs.modTime } -func (fs *fileStat) Sys() interface{} { return fs.sys } +func (fs *fileStat) Sys() any { return fs.sys } func sameFile(fs1, fs2 *fileStat) bool { a := fs1.sys.(*syscall.Dir) diff --git a/src/os/types_unix.go b/src/os/types_unix.go index 105bb78765..1b90a5a141 100644 --- a/src/os/types_unix.go +++ b/src/os/types_unix.go @@ -23,7 +23,7 @@ type fileStat struct { func (fs *fileStat) Size() int64 { return fs.size } func (fs *fileStat) Mode() FileMode { return fs.mode } func (fs *fileStat) ModTime() time.Time { return fs.modTime } -func (fs *fileStat) Sys() interface{} { return &fs.sys } +func (fs *fileStat) Sys() any { return &fs.sys } func sameFile(fs1, fs2 *fileStat) bool { return fs1.sys.Dev == fs2.sys.Dev && fs1.sys.Ino == fs2.sys.Ino diff --git a/src/os/types_windows.go b/src/os/types_windows.go index 59bf5ca381..5443dfedc8 100644 --- a/src/os/types_windows.go +++ b/src/os/types_windows.go @@ -138,7 +138,7 @@ func (fs *fileStat) ModTime() time.Time { } // Sys returns syscall.Win32FileAttributeData for file fs. -func (fs *fileStat) Sys() interface{} { +func (fs *fileStat) Sys() any { return &syscall.Win32FileAttributeData{ FileAttributes: fs.FileAttributes, CreationTime: fs.CreationTime, diff --git a/src/os/user/lookup_unix.go b/src/os/user/lookup_unix.go index e25323fbad..058dab1fb5 100644 --- a/src/os/user/lookup_unix.go +++ b/src/os/user/lookup_unix.go @@ -19,7 +19,7 @@ import ( const userFile = "/etc/passwd" // lineFunc returns a value, an error, or (nil, nil) to skip the row. -type lineFunc func(line []byte) (v interface{}, err error) +type lineFunc func(line []byte) (v any, err error) // readColonFile parses r as an /etc/group or /etc/passwd style file, running // fn for each row. readColonFile returns a value, an error, or (nil, nil) if @@ -27,7 +27,7 @@ type lineFunc func(line []byte) (v interface{}, err error) // // readCols is the minimum number of colon-separated fields that will be passed // to fn; in a long line additional fields may be silently discarded. -func readColonFile(r io.Reader, fn lineFunc, readCols int) (v interface{}, err error) { +func readColonFile(r io.Reader, fn lineFunc, readCols int) (v any, err error) { rd := bufio.NewReader(r) // Read the file line-by-line. @@ -98,7 +98,7 @@ func matchGroupIndexValue(value string, idx int) lineFunc { leadColon = ":" } substr := []byte(leadColon + value + ":") - return func(line []byte) (v interface{}, err error) { + return func(line []byte) (v any, err error) { if !bytes.Contains(line, substr) || bytes.Count(line, colon) < 3 { return } @@ -145,7 +145,7 @@ func matchUserIndexValue(value string, idx int) lineFunc { leadColon = ":" } substr := []byte(leadColon + value + ":") - return func(line []byte) (v interface{}, err error) { + return func(line []byte) (v any, err error) { if !bytes.Contains(line, substr) || bytes.Count(line, colon) < 6 { return } diff --git a/src/plugin/plugin.go b/src/plugin/plugin.go index 4a524bfa3f..b2a0fbe3ea 100644 --- a/src/plugin/plugin.go +++ b/src/plugin/plugin.go @@ -22,7 +22,7 @@ type Plugin struct { pluginpath string err string // set if plugin failed to load loaded chan struct{} // closed when loaded - syms map[string]interface{} + syms map[string]any } // Open opens a Go plugin. @@ -69,4 +69,4 @@ func (p *Plugin) Lookup(symName string) (Symbol, error) { // } // *v.(*int) = 7 // f.(func())() // prints "Hello, number 7" -type Symbol interface{} +type Symbol any diff --git a/src/plugin/plugin_dlopen.go b/src/plugin/plugin_dlopen.go index 5fff329fc5..c59f11ef71 100644 --- a/src/plugin/plugin_dlopen.go +++ b/src/plugin/plugin_dlopen.go @@ -102,7 +102,7 @@ func open(name string) (*Plugin, error) { } // Fill out the value of each plugin symbol. - updatedSyms := map[string]interface{}{} + updatedSyms := map[string]any{} for symName, sym := range syms { isFunc := symName[0] == '.' if isFunc { @@ -147,7 +147,7 @@ var ( ) // lastmoduleinit is defined in package runtime -func lastmoduleinit() (pluginpath string, syms map[string]interface{}, errstr string) +func lastmoduleinit() (pluginpath string, syms map[string]any, errstr string) // doInit is defined in package runtime //go:linkname doInit runtime.doInit diff --git a/src/reflect/abi_test.go b/src/reflect/abi_test.go index 41cfd9d082..f39eb5efea 100644 --- a/src/reflect/abi_test.go +++ b/src/reflect/abi_test.go @@ -33,7 +33,7 @@ func TestMethodValueCallABI(t *testing.T) { // for us, so there isn't a whole lot to do. Let's just // make sure that we can pass register and stack arguments // through. The exact combination is not super important. - makeMethodValue := func(method string) (*StructWithMethods, interface{}) { + makeMethodValue := func(method string) (*StructWithMethods, any) { s := new(StructWithMethods) v := reflect.ValueOf(s).MethodByName(method) return s, v.Interface() @@ -256,7 +256,7 @@ func TestReflectMakeFuncCallABI(t *testing.T) { }) } -var abiCallTestCases = []interface{}{ +var abiCallTestCases = []any{ passNone, passInt, passInt8, @@ -551,7 +551,7 @@ func passStruct10AndSmall(a Struct10, b byte, c uint) (Struct10, byte, uint) { return a, b, c } -var abiMakeFuncTestCases = []interface{}{ +var abiMakeFuncTestCases = []any{ callArgsNone, callArgsInt, callArgsInt8, diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index 8c51d8ec26..9c8434c22c 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -29,7 +29,7 @@ import ( "unsafe" ) -var sink interface{} +var sink any func TestBool(t *testing.T) { v := ValueOf(true) @@ -47,7 +47,7 @@ type T struct { } type pair struct { - i interface{} + i any s string } @@ -337,7 +337,7 @@ func TestSetValue(t *testing.T) { } func TestMapIterSet(t *testing.T) { - m := make(map[string]interface{}, len(valueTests)) + m := make(map[string]any, len(valueTests)) for _, tt := range valueTests { m[tt.s] = tt.i } @@ -385,7 +385,7 @@ func TestCanIntUintFloatComplex(t *testing.T) { var ops = [...]string{"CanInt", "CanUint", "CanFloat", "CanComplex"} var testCases = []struct { - i interface{} + i any want [4]bool }{ // signed integer @@ -691,7 +691,7 @@ func TestAll(t *testing.T) { func TestInterfaceGet(t *testing.T) { var inter struct { - E interface{} + E any } inter.E = 123.456 v1 := ValueOf(&inter) @@ -704,7 +704,7 @@ func TestInterfaceGet(t *testing.T) { func TestInterfaceValue(t *testing.T) { var inter struct { - E interface{} + E any } inter.E = 123.456 v1 := ValueOf(&inter) @@ -720,7 +720,7 @@ func TestInterfaceValue(t *testing.T) { } func TestFunctionValue(t *testing.T) { - var x interface{} = func() {} + var x any = func() {} v := ValueOf(x) if fmt.Sprint(v.Interface()) != fmt.Sprint(x) { t.Fatalf("TestFunction returned wrong pointer") @@ -920,7 +920,7 @@ type Basic struct { type NotBasic Basic type DeepEqualTest struct { - a, b interface{} + a, b any eq bool } @@ -934,11 +934,11 @@ var ( type self struct{} type Loop *Loop -type Loopy interface{} +type Loopy any var loop1, loop2 Loop var loopy1, loopy2 Loopy -var cycleMap1, cycleMap2, cycleMap3 map[string]interface{} +var cycleMap1, cycleMap2, cycleMap3 map[string]any type structWithSelfPtr struct { p *structWithSelfPtr @@ -952,11 +952,11 @@ func init() { loopy1 = &loopy2 loopy2 = &loopy1 - cycleMap1 = map[string]interface{}{} + cycleMap1 = map[string]any{} cycleMap1["cycle"] = cycleMap1 - cycleMap2 = map[string]interface{}{} + cycleMap2 = map[string]any{} cycleMap2["cycle"] = cycleMap2 - cycleMap3 = map[string]interface{}{} + cycleMap3 = map[string]any{} cycleMap3["different"] = cycleMap3 } @@ -1021,7 +1021,7 @@ var deepEqualTests = []DeepEqualTest{ {int32(1), int64(1), false}, {0.5, "hello", false}, {[]int{1, 2, 3}, [3]int{1, 2, 3}, false}, - {&[3]interface{}{1, 2, 4}, &[3]interface{}{1, 2, "s"}, false}, + {&[3]any{1, 2, 4}, &[3]any{1, 2, "s"}, false}, {Basic{1, 0.5}, NotBasic{1, 0.5}, false}, {map[uint]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, false}, {[]byte{1, 2, 3}, []MyByte{1, 2, 3}, false}, @@ -1127,7 +1127,7 @@ func TestDeepEqualUnexportedMap(t *testing.T) { } var deepEqualPerfTests = []struct { - x, y interface{} + x, y any }{ {x: int8(99), y: int8(99)}, {x: []int8{99}, y: []int8{99}}, @@ -1202,7 +1202,7 @@ func BenchmarkDeepEqual(b *testing.B) { } } -func check2ndField(x interface{}, offs uintptr, t *testing.T) { +func check2ndField(x any, offs uintptr, t *testing.T) { s := ValueOf(x) f := s.Type().Field(1) if f.Offset != offs { @@ -1235,14 +1235,14 @@ func TestAlignment(t *testing.T) { check2ndField(x1, uintptr(unsafe.Pointer(&x1.f))-uintptr(unsafe.Pointer(&x1)), t) } -func Nil(a interface{}, t *testing.T) { +func Nil(a any, t *testing.T) { n := ValueOf(a).Field(0) if !n.IsNil() { t.Errorf("%v should be nil", a) } } -func NotNil(a interface{}, t *testing.T) { +func NotNil(a any, t *testing.T) { n := ValueOf(a).Field(0) if n.IsNil() { t.Errorf("value of type %v should not be nil", ValueOf(a).Type().String()) @@ -1252,9 +1252,9 @@ func NotNil(a interface{}, t *testing.T) { func TestIsNil(t *testing.T) { // These implement IsNil. // Wrap in extra struct to hide interface type. - doNil := []interface{}{ + doNil := []any{ struct{ x *int }{}, - struct{ x interface{} }{}, + struct{ x any }{}, struct{ x map[string]int }{}, struct{ x func() bool }{}, struct{ x chan int }{}, @@ -1297,7 +1297,7 @@ func TestIsNil(t *testing.T) { NotNil(mi, t) var ii struct { - x interface{} + x any } Nil(ii, t) ii.x = 2 @@ -1313,7 +1313,7 @@ func TestIsNil(t *testing.T) { func TestIsZero(t *testing.T) { for i, tt := range []struct { - x interface{} + x any want bool }{ // Booleans @@ -1425,7 +1425,7 @@ func TestInterfaceExtraction(t *testing.T) { s.W = os.Stdout v := Indirect(ValueOf(&s)).Field(0).Interface() - if v != s.W.(interface{}) { + if v != s.W.(any) { t.Error("Interface() on interface: ", v, s.W) } } @@ -1974,7 +1974,7 @@ func selectWatcher() { // runSelect runs a single select test. // It returns the values returned by Select but also returns // a panic value if the Select panics. -func runSelect(cases []SelectCase, info []caseInfo) (chosen int, recv Value, recvOK bool, panicErr interface{}) { +func runSelect(cases []SelectCase, info []caseInfo) (chosen int, recv Value, recvOK bool, panicErr any) { defer func() { panicErr = recover() @@ -2765,7 +2765,7 @@ func TestMethod5(t *testing.T) { var TinterType = TypeOf(new(Tinter)).Elem() - CheckI := func(name string, i interface{}, inc int) { + CheckI := func(name string, i any, inc int) { v := ValueOf(i) CheckV(name, v, inc) CheckV("(i="+name+")", v.Convert(TinterType), inc) @@ -2814,7 +2814,7 @@ func TestInterfaceSet(t *testing.T) { p := &Point{3, 4} var s struct { - I interface{} + I any P interface { Dist(int) int } @@ -2856,7 +2856,7 @@ func TestAnonymousFields(t *testing.T) { } type FTest struct { - s interface{} + s any name string index []int value int @@ -3087,7 +3087,7 @@ func TestImportPath(t *testing.T) { {TypeOf([]byte(nil)), ""}, {TypeOf([]rune(nil)), ""}, {TypeOf(string("")), ""}, - {TypeOf((*interface{})(nil)).Elem(), ""}, + {TypeOf((*any)(nil)).Elem(), ""}, {TypeOf((*byte)(nil)), ""}, {TypeOf((*rune)(nil)), ""}, {TypeOf((*int64)(nil)), ""}, @@ -3290,7 +3290,7 @@ func TestEmbeddedMethods(t *testing.T) { } } -type FuncDDD func(...interface{}) error +type FuncDDD func(...any) error func (f FuncDDD) M() {} @@ -3328,7 +3328,7 @@ func TestPtrToGC(t *testing.T) { tt := TypeOf(T(nil)) pt := PointerTo(tt) const n = 100 - var x []interface{} + var x []any for i := 0; i < n; i++ { v := New(pt) p := new(*uintptr) @@ -3450,7 +3450,7 @@ func noAlloc(t *testing.T, n int, f func(int)) { func TestAllocations(t *testing.T) { noAlloc(t, 100, func(j int) { - var i interface{} + var i any var v Value // We can uncomment this when compiler escape analysis @@ -3624,7 +3624,7 @@ func TestVariadic(t *testing.T) { } b.Reset() - V(fmt.Fprintf).CallSlice([]Value{V(&b), V("%s, %d world"), V([]interface{}{"hello", 42})}) + V(fmt.Fprintf).CallSlice([]Value{V(&b), V("%s, %d world"), V([]any{"hello", 42})}) if b.String() != "hello, 42 world" { t.Errorf("after Fprintf CallSlice: %q != %q", b.String(), "hello 42 world") } @@ -3967,7 +3967,7 @@ func shouldPanic(expect string, f func()) { f() } -func isNonNil(x interface{}) { +func isNonNil(x any) { if x == nil { panic("nil interface") } @@ -3993,7 +3993,7 @@ func TestAlias(t *testing.T) { var V = ValueOf -func EmptyInterfaceV(x interface{}) Value { +func EmptyInterfaceV(x any) Value { return ValueOf(&x).Elem() } @@ -4434,7 +4434,7 @@ var convertTests = []struct { {V((map[uint]bool)(nil)), V((map[uint]bool)(nil))}, {V([]uint(nil)), V([]uint(nil))}, {V([]int(nil)), V([]int(nil))}, - {V(new(interface{})), V(new(interface{}))}, + {V(new(any)), V(new(any))}, {V(new(io.Reader)), V(new(io.Reader))}, {V(new(io.Writer)), V(new(io.Writer))}, @@ -4633,7 +4633,7 @@ var comparableTests = []struct { {TypeOf(NonComparableStruct{}), false}, {TypeOf([10]map[string]int{}), false}, {TypeOf([10]string{}), true}, - {TypeOf(new(interface{})).Elem(), true}, + {TypeOf(new(any)).Elem(), true}, } func TestComparable(t *testing.T) { @@ -4683,7 +4683,7 @@ func TestOverflow(t *testing.T) { } } -func checkSameType(t *testing.T, x Type, y interface{}) { +func checkSameType(t *testing.T, x Type, y any) { if x != TypeOf(y) || TypeOf(Zero(x).Interface()) != TypeOf(y) { t.Errorf("did not find preexisting type for %s (vs %s)", TypeOf(x), TypeOf(y)) } @@ -4693,73 +4693,73 @@ func TestArrayOf(t *testing.T) { // check construction and use of type not in binary tests := []struct { n int - value func(i int) interface{} + value func(i int) any comparable bool want string }{ { n: 0, - value: func(i int) interface{} { type Tint int; return Tint(i) }, + value: func(i int) any { type Tint int; return Tint(i) }, comparable: true, want: "[]", }, { n: 10, - value: func(i int) interface{} { type Tint int; return Tint(i) }, + value: func(i int) any { type Tint int; return Tint(i) }, comparable: true, want: "[0 1 2 3 4 5 6 7 8 9]", }, { n: 10, - value: func(i int) interface{} { type Tfloat float64; return Tfloat(i) }, + value: func(i int) any { type Tfloat float64; return Tfloat(i) }, comparable: true, want: "[0 1 2 3 4 5 6 7 8 9]", }, { n: 10, - value: func(i int) interface{} { type Tstring string; return Tstring(strconv.Itoa(i)) }, + value: func(i int) any { type Tstring string; return Tstring(strconv.Itoa(i)) }, comparable: true, want: "[0 1 2 3 4 5 6 7 8 9]", }, { n: 10, - value: func(i int) interface{} { type Tstruct struct{ V int }; return Tstruct{i} }, + value: func(i int) any { type Tstruct struct{ V int }; return Tstruct{i} }, comparable: true, want: "[{0} {1} {2} {3} {4} {5} {6} {7} {8} {9}]", }, { n: 10, - value: func(i int) interface{} { type Tint int; return []Tint{Tint(i)} }, + value: func(i int) any { type Tint int; return []Tint{Tint(i)} }, comparable: false, want: "[[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]]", }, { n: 10, - value: func(i int) interface{} { type Tint int; return [1]Tint{Tint(i)} }, + value: func(i int) any { type Tint int; return [1]Tint{Tint(i)} }, comparable: true, want: "[[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]]", }, { n: 10, - value: func(i int) interface{} { type Tstruct struct{ V [1]int }; return Tstruct{[1]int{i}} }, + value: func(i int) any { type Tstruct struct{ V [1]int }; return Tstruct{[1]int{i}} }, comparable: true, want: "[{[0]} {[1]} {[2]} {[3]} {[4]} {[5]} {[6]} {[7]} {[8]} {[9]}]", }, { n: 10, - value: func(i int) interface{} { type Tstruct struct{ V []int }; return Tstruct{[]int{i}} }, + value: func(i int) any { type Tstruct struct{ V []int }; return Tstruct{[]int{i}} }, comparable: false, want: "[{[0]} {[1]} {[2]} {[3]} {[4]} {[5]} {[6]} {[7]} {[8]} {[9]}]", }, { n: 10, - value: func(i int) interface{} { type TstructUV struct{ U, V int }; return TstructUV{i, i} }, + value: func(i int) any { type TstructUV struct{ U, V int }; return TstructUV{i, i} }, comparable: true, want: "[{0 0} {1 1} {2 2} {3 3} {4 4} {5 5} {6 6} {7 7} {8 8} {9 9}]", }, { n: 10, - value: func(i int) interface{} { + value: func(i int) any { type TstructUV struct { U int V float64 @@ -4820,7 +4820,7 @@ func TestArrayOfGC(t *testing.T) { type T *uintptr tt := TypeOf(T(nil)) const n = 100 - var x []interface{} + var x []any for i := 0; i < n; i++ { v := New(ArrayOf(n, tt)).Elem() for j := 0; j < v.Len(); j++ { @@ -4984,7 +4984,7 @@ func TestSliceOfGC(t *testing.T) { tt := TypeOf(T(nil)) st := SliceOf(tt) const n = 100 - var x []interface{} + var x []any for i := 0; i < n; i++ { v := MakeSlice(st, n, n) for j := 0; j < v.Len(); j++ { @@ -5174,7 +5174,7 @@ func TestStructOf(t *testing.T) { checkSameType(t, StructOf(fields[2:3]), struct{ Y uint64 }{}) // gccgo used to fail this test. - type structFieldType interface{} + type structFieldType any checkSameType(t, StructOf([]StructField{ { @@ -5350,7 +5350,7 @@ func TestStructOfGC(t *testing.T) { st := StructOf(fields) const n = 10000 - var x []interface{} + var x []any for i := 0; i < n; i++ { v := New(st).Elem() for j := 0; j < v.NumField(); j++ { @@ -5616,7 +5616,7 @@ func TestStructOfWithInterface(t *testing.T) { { name: "StructI", typ: PointerTo(TypeOf(StructI(want))), - val: ValueOf(func() interface{} { + val: ValueOf(func() any { v := StructI(want) return &v }()), @@ -5625,7 +5625,7 @@ func TestStructOfWithInterface(t *testing.T) { { name: "StructIPtr", typ: PointerTo(TypeOf(StructIPtr(want))), - val: ValueOf(func() interface{} { + val: ValueOf(func() any { v := StructIPtr(want) return &v }()), @@ -5887,7 +5887,7 @@ func TestChanOfGC(t *testing.T) { // so we have to save pointers to channels in x; the pointer code will // use the gc info in the newly constructed chan type. const n = 100 - var x []interface{} + var x []any for i := 0; i < n; i++ { v := MakeChan(ct, n) for j := 0; j < n; j++ { @@ -5945,7 +5945,7 @@ func TestMapOfGCKeys(t *testing.T) { // so we have to save pointers to maps in x; the pointer code will // use the gc info in the newly constructed map type. const n = 100 - var x []interface{} + var x []any for i := 0; i < n; i++ { v := MakeMap(mt) for j := 0; j < n; j++ { @@ -5983,7 +5983,7 @@ func TestMapOfGCValues(t *testing.T) { // so we have to save pointers to maps in x; the pointer code will // use the gc info in the newly constructed map type. const n = 100 - var x []interface{} + var x []any for i := 0; i < n; i++ { v := MakeMap(mt) for j := 0; j < n; j++ { @@ -6051,7 +6051,7 @@ func TestFuncOf(t *testing.T) { testCases := []struct { in, out []Type variadic bool - want interface{} + want any }{ {in: []Type{TypeOf(T1(0))}, want: (func(T1))(nil)}, {in: []Type{TypeOf(int(0))}, want: (func(int))(nil)}, @@ -6544,7 +6544,7 @@ func TestValueString(t *testing.T) { func TestInvalid(t *testing.T) { // Used to have inconsistency between IsValid() and Kind() != Invalid. - type T struct{ v interface{} } + type T struct{ v any } v := ValueOf(T{}).Field(0) if v.IsValid() != true || v.Kind() != Interface { @@ -6562,7 +6562,7 @@ func TestLargeGCProg(t *testing.T) { fv.Call([]Value{ValueOf([256]*byte{})}) } -func fieldIndexRecover(t Type, i int) (recovered interface{}) { +func fieldIndexRecover(t Type, i int) (recovered any) { defer func() { recovered = recover() }() @@ -6736,7 +6736,7 @@ func TestFuncLayout(t *testing.T) { gc: r, }, { - typ: ValueOf(func(a map[int]int, b uintptr, c interface{}) {}).Type(), + typ: ValueOf(func(a map[int]int, b uintptr, c any) {}).Type(), size: 4 * goarch.PtrSize, argsize: 4 * goarch.PtrSize, retOffset: 4 * goarch.PtrSize, @@ -6989,7 +6989,7 @@ func TestGCBits(t *testing.T) { hdr := make([]byte, 8/goarch.PtrSize) - verifyMapBucket := func(t *testing.T, k, e Type, m interface{}, want []byte) { + verifyMapBucket := func(t *testing.T, k, e Type, m any, want []byte) { verifyGCBits(t, MapBucketOf(k, e), want) verifyGCBits(t, CachedBucketOf(TypeOf(m)), want) } @@ -7118,7 +7118,7 @@ func TestChanAlloc(t *testing.T) { type TheNameOfThisTypeIsExactly255BytesLongSoWhenTheCompilerPrependsTheReflectTestPackageNameAndExtraStarTheLinkerRuntimeAndReflectPackagesWillHaveToCorrectlyDecodeTheSecondLengthByte0123456789_0123456789_0123456789_0123456789_0123456789_012345678 int type nameTest struct { - v interface{} + v any want string } @@ -7130,7 +7130,7 @@ var nameTests = []nameTest{ {(*func() D1)(nil), ""}, {(*<-chan D1)(nil), ""}, {(*chan<- D1)(nil), ""}, - {(*interface{})(nil), ""}, + {(*any)(nil), ""}, {(*interface { F() })(nil), ""}, @@ -7156,7 +7156,7 @@ func TestExported(t *testing.T) { type p3 p type exportTest struct { - v interface{} + v any want bool } exportTests := []exportTest{ @@ -7291,9 +7291,9 @@ func TestSwapper(t *testing.T) { type S string tests := []struct { - in interface{} + in any i, j int - want interface{} + want any }{ { in: []int{1, 20, 300}, @@ -7707,7 +7707,7 @@ func TestSetIter(t *testing.T) { }) // Make sure assignment conversion works. - var x interface{} + var x any y := ValueOf(&x).Elem() y.SetIterKey(i) if _, ok := data[x.(string)]; !ok { diff --git a/src/reflect/deepequal.go b/src/reflect/deepequal.go index b71504fa21..eaab101221 100644 --- a/src/reflect/deepequal.go +++ b/src/reflect/deepequal.go @@ -225,7 +225,7 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool) bool { // values that have been compared before, it treats the values as // equal rather than examining the values to which they point. // This ensures that DeepEqual terminates. -func DeepEqual(x, y interface{}) bool { +func DeepEqual(x, y any) bool { if x == nil || y == nil { return x == y } diff --git a/src/reflect/example_test.go b/src/reflect/example_test.go index 684bafd648..3db971c3ae 100644 --- a/src/reflect/example_test.go +++ b/src/reflect/example_test.go @@ -14,7 +14,7 @@ import ( ) func ExampleKind() { - for _, v := range []interface{}{"hi", 42, func() {}} { + for _, v := range []any{"hi", 42, func() {}} { switch v := reflect.ValueOf(v); v.Kind() { case reflect.String: fmt.Println(v.String()) @@ -45,7 +45,7 @@ func ExampleMakeFunc() { // When the function is invoked, reflect turns the arguments // into Values, calls swap, and then turns swap's result slice // into the values returned by the new function. - makeSwap := func(fptr interface{}) { + makeSwap := func(fptr any) { // fptr is a pointer to a function. // Obtain the function value itself (likely nil) as a reflect.Value // so that we can query its type and then set the value. diff --git a/src/reflect/export_test.go b/src/reflect/export_test.go index ba7fb68067..a5a3c1c271 100644 --- a/src/reflect/export_test.go +++ b/src/reflect/export_test.go @@ -88,7 +88,7 @@ func TypeLinks() []string { var GCBits = gcbits -func gcbits(interface{}) []byte // provided by runtime +func gcbits(any) []byte // provided by runtime func MapBucketOf(x, y Type) Type { return bucketOf(x.(*rtype), y.(*rtype)) diff --git a/src/reflect/set_test.go b/src/reflect/set_test.go index 566dc7fb65..9ce0e09b82 100644 --- a/src/reflect/set_test.go +++ b/src/reflect/set_test.go @@ -31,7 +31,7 @@ func TestImplicitMapConversion(t *testing.T) { } { // convert interface key - m := make(map[interface{}]int) + m := make(map[any]int) mv := ValueOf(m) mv.SetMapIndex(ValueOf(1), ValueOf(2)) x, ok := m[1] @@ -44,7 +44,7 @@ func TestImplicitMapConversion(t *testing.T) { } { // convert interface value - m := make(map[int]interface{}) + m := make(map[int]any) mv := ValueOf(m) mv.SetMapIndex(ValueOf(1), ValueOf(2)) x, ok := m[1] @@ -57,7 +57,7 @@ func TestImplicitMapConversion(t *testing.T) { } { // convert both interface key and interface value - m := make(map[interface{}]interface{}) + m := make(map[any]any) mv := ValueOf(m) mv.SetMapIndex(ValueOf(1), ValueOf(2)) x, ok := m[1] @@ -160,8 +160,8 @@ func TestImplicitAppendConversion(t *testing.T) { } var implementsTests = []struct { - x interface{} - t interface{} + x any + t any b bool }{ {new(*bytes.Buffer), new(io.Reader), true}, @@ -198,8 +198,8 @@ func TestImplements(t *testing.T) { } var assignableTests = []struct { - x interface{} - t interface{} + x any + t any b bool }{ {new(chan int), new(<-chan int), true}, @@ -207,13 +207,13 @@ var assignableTests = []struct { {new(*int), new(IntPtr), true}, {new(IntPtr), new(*int), true}, {new(IntPtr), new(IntPtr1), false}, - {new(Ch), new(<-chan interface{}), true}, + {new(Ch), new(<-chan any), true}, // test runs implementsTests too } type IntPtr *int type IntPtr1 *int -type Ch <-chan interface{} +type Ch <-chan any func TestAssignableTo(t *testing.T) { for _, tt := range append(assignableTests, implementsTests...) { diff --git a/src/reflect/swapper.go b/src/reflect/swapper.go index 67b7fbe59b..745c7b9f49 100644 --- a/src/reflect/swapper.go +++ b/src/reflect/swapper.go @@ -14,7 +14,7 @@ import ( // slice. // // Swapper panics if the provided interface is not a slice. -func Swapper(slice interface{}) func(i, j int) { +func Swapper(slice any) func(i, j int) { v := ValueOf(slice) if v.Kind() != Slice { panic(&ValueError{Method: "Swapper", Kind: v.Kind()}) diff --git a/src/reflect/type.go b/src/reflect/type.go index 4701e06c49..6217291a3f 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -1414,7 +1414,7 @@ func (t *structType) FieldByName(name string) (f StructField, present bool) { // TypeOf returns the reflection Type that represents the dynamic type of i. // If i is a nil interface value, TypeOf returns nil. -func TypeOf(i interface{}) Type { +func TypeOf(i any) Type { eface := *(*emptyInterface)(unsafe.Pointer(&i)) return toType(eface.typ) } @@ -1458,7 +1458,7 @@ func (t *rtype) ptrTo() *rtype { // Create a new ptrType starting with the description // of an *unsafe.Pointer. - var iptr interface{} = (*unsafe.Pointer)(nil) + var iptr any = (*unsafe.Pointer)(nil) prototype := *(**ptrType)(unsafe.Pointer(&iptr)) pp := *prototype @@ -1876,7 +1876,7 @@ func ChanOf(dir ChanDir, t Type) Type { } // Make a channel type. - var ichan interface{} = (chan unsafe.Pointer)(nil) + var ichan any = (chan unsafe.Pointer)(nil) prototype := *(**chanType)(unsafe.Pointer(&ichan)) ch := *prototype ch.tflag = tflagRegularMemory @@ -1922,7 +1922,7 @@ func MapOf(key, elem Type) Type { // Make a map type. // Note: flag values must match those used in the TMAP case // in ../cmd/compile/internal/reflectdata/reflect.go:writeType. - var imap interface{} = (map[unsafe.Pointer]unsafe.Pointer)(nil) + var imap any = (map[unsafe.Pointer]unsafe.Pointer)(nil) mt := **(**mapType)(unsafe.Pointer(&imap)) mt.str = resolveReflectName(newName(s, "", false)) mt.tflag = 0 @@ -2002,7 +2002,7 @@ func FuncOf(in, out []Type, variadic bool) Type { } // Make a func type. - var ifunc interface{} = (func())(nil) + var ifunc any = (func())(nil) prototype := *(**funcType)(unsafe.Pointer(&ifunc)) n := len(in) + len(out) @@ -2360,7 +2360,7 @@ func SliceOf(t Type) Type { } // Make a slice type. - var islice interface{} = ([]unsafe.Pointer)(nil) + var islice any = ([]unsafe.Pointer)(nil) prototype := *(**sliceType)(unsafe.Pointer(&islice)) slice := *prototype slice.tflag = 0 @@ -2688,7 +2688,7 @@ func StructOf(fields []StructField) Type { size = align(size, uintptr(typalign)) // Make the struct type. - var istruct interface{} = struct{}{} + var istruct any = struct{}{} prototype := *(**structType)(unsafe.Pointer(&istruct)) *typ = *prototype typ.fields = fs @@ -2908,7 +2908,7 @@ func ArrayOf(length int, elem Type) Type { } // Make an array type. - var iarray interface{} = [1]unsafe.Pointer{} + var iarray any = [1]unsafe.Pointer{} prototype := *(**arrayType)(unsafe.Pointer(&iarray)) array := *prototype array.tflag = typ.tflag & tflagRegularMemory @@ -3095,7 +3095,7 @@ func funcLayout(t *funcType, rcvr *rtype) (frametype *rtype, framePool *sync.Poo x.str = resolveReflectName(newName(s, "", false)) // cache result for future callers - framePool = &sync.Pool{New: func() interface{} { + framePool = &sync.Pool{New: func() any { return unsafe_New(x) }} lti, _ := layoutCache.LoadOrStore(k, layoutType{ diff --git a/src/reflect/value.go b/src/reflect/value.go index 02354f2736..dcc359dae4 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -104,9 +104,9 @@ func (v Value) pointer() unsafe.Pointer { } // packEface converts v to the empty interface. -func packEface(v Value) interface{} { +func packEface(v Value) any { t := v.typ - var i interface{} + var i any e := (*emptyInterface)(unsafe.Pointer(&i)) // First, fill in the data portion of the interface. switch { @@ -141,7 +141,7 @@ func packEface(v Value) interface{} { } // unpackEface converts the empty interface i to a Value. -func unpackEface(i interface{}) Value { +func unpackEface(i any) Value { e := (*emptyInterface)(unsafe.Pointer(&i)) // NOTE: don't read e.word until we know whether it is really a pointer or not. t := e.typ @@ -1167,11 +1167,11 @@ func (v Value) Elem() Value { k := v.kind() switch k { case Interface: - var eface interface{} + var eface any if v.typ.NumMethod() == 0 { - eface = *(*interface{})(v.ptr) + eface = *(*any)(v.ptr) } else { - eface = (interface{})(*(*interface { + eface = (any)(*(*interface { M() })(v.ptr)) } @@ -1426,11 +1426,11 @@ func (v Value) CanInterface() bool { // var i interface{} = (v's underlying value) // It panics if the Value was obtained by accessing // unexported struct fields. -func (v Value) Interface() (i interface{}) { +func (v Value) Interface() (i any) { return valueInterface(v, true) } -func valueInterface(v Value, safe bool) interface{} { +func valueInterface(v Value, safe bool) any { if v.flag == 0 { panic(&ValueError{"reflect.Value.Interface", Invalid}) } @@ -1449,7 +1449,7 @@ func valueInterface(v Value, safe bool) interface{} { // Empty interface has one layout, all interfaces with // methods have a second layout. if v.NumMethod() == 0 { - return *(*interface{})(v.ptr) + return *(*any)(v.ptr) } return *(*interface { M() @@ -2954,7 +2954,7 @@ func Indirect(v Value) Value { // ValueOf returns a new Value initialized to the concrete value // stored in the interface i. ValueOf(nil) returns the zero Value. -func ValueOf(i interface{}) Value { +func ValueOf(i any) Value { if i == nil { return Value{} } @@ -3051,7 +3051,7 @@ func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value } x := valueInterface(v, false) if dst.NumMethod() == 0 { - *(*interface{})(target) = x + *(*any)(target) = x } else { ifaceE2I(dst, x, target) } @@ -3382,7 +3382,7 @@ func cvtT2I(v Value, typ Type) Value { target := unsafe_New(typ.common()) x := valueInterface(v, false) if typ.NumMethod() == 0 { - *(*interface{})(target) = x + *(*any)(target) = x } else { ifaceE2I(typ.(*rtype), x, target) } @@ -3481,7 +3481,7 @@ func maplen(m unsafe.Pointer) int //go:linkname call runtime.reflectcall func call(stackArgsType *rtype, f, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs) -func ifaceE2I(t *rtype, src interface{}, dst unsafe.Pointer) +func ifaceE2I(t *rtype, src any, dst unsafe.Pointer) // memmove copies size bytes to dst from src. No write barriers are used. //go:noescape @@ -3518,7 +3518,7 @@ func verifyNotInHeapPtr(p uintptr) bool // Dummy annotation marking that the value x escapes, // for use in cases where the reflect code is so clever that // the compiler cannot follow. -func escapes(x interface{}) { +func escapes(x any) { if dummy.b { dummy.x = x } @@ -3526,5 +3526,5 @@ func escapes(x interface{}) { var dummy struct { b bool - x interface{} + x any } diff --git a/src/reflect/visiblefields_test.go b/src/reflect/visiblefields_test.go index 5ae322321b..fdedc21f73 100644 --- a/src/reflect/visiblefields_test.go +++ b/src/reflect/visiblefields_test.go @@ -17,7 +17,7 @@ type structField struct { var fieldsTests = []struct { testName string - val interface{} + val any expect []structField }{{ testName: "SimpleStruct", @@ -279,7 +279,7 @@ type RS3 struct { RS1 } -type M map[string]interface{} +type M map[string]any type Rec1 struct { *Rec2 diff --git a/src/runtime/abi_test.go b/src/runtime/abi_test.go index 5c1f1f4067..f9e8d701ce 100644 --- a/src/runtime/abi_test.go +++ b/src/runtime/abi_test.go @@ -78,7 +78,7 @@ func TestFinalizerRegisterABI(t *testing.T) { tests := []struct { name string - fin interface{} + fin any confirmValue int }{ {"Pointer", regFinalizerPointer, -1}, diff --git a/src/runtime/alg.go b/src/runtime/alg.go index 978a3b85dc..5d7d1c77f4 100644 --- a/src/runtime/alg.go +++ b/src/runtime/alg.go @@ -290,7 +290,7 @@ func int64Hash(i uint64, seed uintptr) uintptr { return memhash64(noescape(unsafe.Pointer(&i)), seed) } -func efaceHash(i interface{}, seed uintptr) uintptr { +func efaceHash(i any, seed uintptr) uintptr { return nilinterhash(noescape(unsafe.Pointer(&i)), seed) } diff --git a/src/runtime/cgo.go b/src/runtime/cgo.go index 395d54a66e..d90468240d 100644 --- a/src/runtime/cgo.go +++ b/src/runtime/cgo.go @@ -42,7 +42,7 @@ var cgoHasExtraM bool // 2) they keep the argument alive until the call site; the call is emitted after // the end of the (presumed) use of the argument by C. // cgoUse should not actually be called (see cgoAlwaysFalse). -func cgoUse(interface{}) { throw("cgoUse should not be called") } +func cgoUse(any) { throw("cgoUse should not be called") } // cgoAlwaysFalse is a boolean value that is always false. // The cgo-generated code says if cgoAlwaysFalse { cgoUse(p) }. diff --git a/src/runtime/cgo/handle.go b/src/runtime/cgo/handle.go index 726f0a396d..d711900d79 100644 --- a/src/runtime/cgo/handle.go +++ b/src/runtime/cgo/handle.go @@ -105,7 +105,7 @@ type Handle uintptr // // The intended use is to pass the returned handle to C code, which // passes it back to Go, which calls Value. -func NewHandle(v interface{}) Handle { +func NewHandle(v any) Handle { h := atomic.AddUintptr(&handleIdx, 1) if h == 0 { panic("runtime/cgo: ran out of handle space") @@ -118,7 +118,7 @@ func NewHandle(v interface{}) Handle { // Value returns the associated Go value for a valid handle. // // The method panics if the handle is invalid. -func (h Handle) Value() interface{} { +func (h Handle) Value() any { v, ok := handles.Load(uintptr(h)) if !ok { panic("runtime/cgo: misuse of an invalid Handle") diff --git a/src/runtime/cgo/handle_test.go b/src/runtime/cgo/handle_test.go index 738051a0ea..b341c8e1e4 100644 --- a/src/runtime/cgo/handle_test.go +++ b/src/runtime/cgo/handle_test.go @@ -13,8 +13,8 @@ func TestHandle(t *testing.T) { v := 42 tests := []struct { - v1 interface{} - v2 interface{} + v1 any + v2 any }{ {v1: v, v2: v}, {v1: &v, v2: &v}, @@ -44,7 +44,7 @@ func TestHandle(t *testing.T) { } siz := 0 - handles.Range(func(k, v interface{}) bool { + handles.Range(func(k, v any) bool { siz++ return true }) diff --git a/src/runtime/cgocall.go b/src/runtime/cgocall.go index 694b3e66cd..a0c9560fd0 100644 --- a/src/runtime/cgocall.go +++ b/src/runtime/cgocall.go @@ -389,7 +389,7 @@ var racecgosync uint64 // represents possible synchronization in C code // cgoCheckPointer checks if the argument contains a Go pointer that // points to a Go pointer, and panics if it does. -func cgoCheckPointer(ptr interface{}, arg interface{}) { +func cgoCheckPointer(ptr any, arg any) { if debug.cgocheck == 0 { return } @@ -628,7 +628,7 @@ func cgoInRange(p unsafe.Pointer, start, end uintptr) bool { // cgoCheckResult is called to check the result parameter of an // exported Go function. It panics if the result is or contains a Go // pointer. -func cgoCheckResult(val interface{}) { +func cgoCheckResult(val any) { if debug.cgocheck == 0 { return } diff --git a/src/runtime/chan_test.go b/src/runtime/chan_test.go index 355267c5e3..9471d4596c 100644 --- a/src/runtime/chan_test.go +++ b/src/runtime/chan_test.go @@ -494,7 +494,7 @@ func TestSelectFairness(t *testing.T) { func TestChanSendInterface(t *testing.T) { type mt struct{} m := &mt{} - c := make(chan interface{}, 1) + c := make(chan any, 1) c <- m select { case c <- m: diff --git a/src/runtime/crash_test.go b/src/runtime/crash_test.go index 01b1ebcdd7..9b9ab4f3e1 100644 --- a/src/runtime/crash_test.go +++ b/src/runtime/crash_test.go @@ -403,7 +403,7 @@ func TestRuntimePanicWithRuntimeError(t *testing.T) { } } -func panicValue(fn func()) (recovered interface{}) { +func panicValue(fn func()) (recovered any) { defer func() { recovered = recover() }() diff --git a/src/runtime/debug/garbage_test.go b/src/runtime/debug/garbage_test.go index c3501408dd..7213bbe641 100644 --- a/src/runtime/debug/garbage_test.go +++ b/src/runtime/debug/garbage_test.go @@ -151,8 +151,8 @@ func TestFreeOSMemory(t *testing.T) { } var ( - setGCPercentBallast interface{} - setGCPercentSink interface{} + setGCPercentBallast any + setGCPercentSink any ) func TestSetGCPercent(t *testing.T) { diff --git a/src/runtime/debugcall.go b/src/runtime/debugcall.go index 005a259f28..205971c428 100644 --- a/src/runtime/debugcall.go +++ b/src/runtime/debugcall.go @@ -16,7 +16,7 @@ const ( ) func debugCallV2() -func debugCallPanicked(val interface{}) +func debugCallPanicked(val any) // debugCallCheck checks whether it is safe to inject a debugger // function call with return PC pc. If not, it returns a string diff --git a/src/runtime/debuglog.go b/src/runtime/debuglog.go index 588b54d1f5..75b91c4216 100644 --- a/src/runtime/debuglog.go +++ b/src/runtime/debuglog.go @@ -266,7 +266,7 @@ func (l *dlogger) hex(x uint64) *dlogger { } //go:nosplit -func (l *dlogger) p(x interface{}) *dlogger { +func (l *dlogger) p(x any) *dlogger { if !dlogEnabled { return l } diff --git a/src/runtime/defer_test.go b/src/runtime/defer_test.go index 821db0ca12..3a54951c31 100644 --- a/src/runtime/defer_test.go +++ b/src/runtime/defer_test.go @@ -433,7 +433,7 @@ func TestIssue43921(t *testing.T) { }() } -func expect(t *testing.T, n int, err interface{}) { +func expect(t *testing.T, n int, err any) { if n != err { t.Fatalf("have %v, want %v", err, n) } diff --git a/src/runtime/error.go b/src/runtime/error.go index 91f83ae126..43114f092e 100644 --- a/src/runtime/error.go +++ b/src/runtime/error.go @@ -210,7 +210,7 @@ type stringer interface { // printany prints an argument passed to panic. // If panic is called with a value that has a String or Error method, // it has already been converted into a string by preprintpanics. -func printany(i interface{}) { +func printany(i any) { switch v := i.(type) { case nil: print("nil") @@ -253,7 +253,7 @@ func printany(i interface{}) { } } -func printanycustomtype(i interface{}) { +func printanycustomtype(i any) { eface := efaceOf(&i) typestring := eface._type.string() diff --git a/src/runtime/export_debug_test.go b/src/runtime/export_debug_test.go index fffc99d7e5..19a9ec135f 100644 --- a/src/runtime/export_debug_test.go +++ b/src/runtime/export_debug_test.go @@ -22,7 +22,7 @@ import ( // // On success, InjectDebugCall returns the panic value of fn or nil. // If fn did not panic, its results will be available in args. -func InjectDebugCall(gp *g, fn interface{}, regArgs *abi.RegArgs, stackArgs interface{}, tkill func(tid int) error, returnOnUnsafePoint bool) (interface{}, error) { +func InjectDebugCall(gp *g, fn any, regArgs *abi.RegArgs, stackArgs any, tkill func(tid int) error, returnOnUnsafePoint bool) (any, error) { if gp.lockedm == 0 { return nil, plainError("goroutine not locked to thread") } @@ -96,7 +96,7 @@ type debugCallHandler struct { regArgs *abi.RegArgs argp unsafe.Pointer argSize uintptr - panic interface{} + panic any handleF func(info *siginfo, ctxt *sigctxt, gp2 *g) bool diff --git a/src/runtime/export_debuglog_test.go b/src/runtime/export_debuglog_test.go index 8cd943b438..1a9074e646 100644 --- a/src/runtime/export_debuglog_test.go +++ b/src/runtime/export_debuglog_test.go @@ -14,15 +14,15 @@ const DebugLogStringLimit = debugLogStringLimit var Dlog = dlog -func (l *dlogger) End() { l.end() } -func (l *dlogger) B(x bool) *dlogger { return l.b(x) } -func (l *dlogger) I(x int) *dlogger { return l.i(x) } -func (l *dlogger) I16(x int16) *dlogger { return l.i16(x) } -func (l *dlogger) U64(x uint64) *dlogger { return l.u64(x) } -func (l *dlogger) Hex(x uint64) *dlogger { return l.hex(x) } -func (l *dlogger) P(x interface{}) *dlogger { return l.p(x) } -func (l *dlogger) S(x string) *dlogger { return l.s(x) } -func (l *dlogger) PC(x uintptr) *dlogger { return l.pc(x) } +func (l *dlogger) End() { l.end() } +func (l *dlogger) B(x bool) *dlogger { return l.b(x) } +func (l *dlogger) I(x int) *dlogger { return l.i(x) } +func (l *dlogger) I16(x int16) *dlogger { return l.i16(x) } +func (l *dlogger) U64(x uint64) *dlogger { return l.u64(x) } +func (l *dlogger) Hex(x uint64) *dlogger { return l.hex(x) } +func (l *dlogger) P(x any) *dlogger { return l.p(x) } +func (l *dlogger) S(x string) *dlogger { return l.s(x) } +func (l *dlogger) PC(x uintptr) *dlogger { return l.pc(x) } func DumpDebugLog() string { g := getg() diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index 4a03f24ded..3c8f9eb49b 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -75,7 +75,7 @@ func Netpoll(delta int64) { }) } -func GCMask(x interface{}) (ret []byte) { +func GCMask(x any) (ret []byte) { systemstack(func() { ret = getgcmask(x) }) @@ -218,7 +218,7 @@ func SetEnvs(e []string) { envs = e } // For benchmarking. -func BenchSetType(n int, x interface{}) { +func BenchSetType(n int, x any) { e := *efaceOf(&x) t := e._type var size uintptr @@ -546,7 +546,7 @@ func MapTombstoneCheck(m map[int]int) { // We should have a series of filled and emptyOne cells, followed by // a series of emptyRest cells. h := *(**hmap)(unsafe.Pointer(&m)) - i := interface{}(m) + i := any(m) t := *(**maptype)(unsafe.Pointer(&i)) for x := 0; x < 1< G is inlined and F is excluded from stack // traces, G still appears. diff --git a/src/runtime/syscall_windows_test.go b/src/runtime/syscall_windows_test.go index 65f74b32fb..101e94107c 100644 --- a/src/runtime/syscall_windows_test.go +++ b/src/runtime/syscall_windows_test.go @@ -288,7 +288,7 @@ func TestCallbackInAnotherThread(t *testing.T) { } type cbFunc struct { - goFunc interface{} + goFunc any } func (f cbFunc) cName(cdecl bool) string { diff --git a/src/runtime/testdata/testprog/gc.go b/src/runtime/testdata/testprog/gc.go index 7d371a6a89..215228ea05 100644 --- a/src/runtime/testdata/testprog/gc.go +++ b/src/runtime/testdata/testprog/gc.go @@ -90,7 +90,7 @@ func GCFairness2() { runtime.GOMAXPROCS(1) debug.SetGCPercent(1) var count [3]int64 - var sink [3]interface{} + var sink [3]any for i := range count { go func(i int) { for { @@ -266,9 +266,9 @@ func DeferLiveness() { } //go:noinline -func escape(x interface{}) { sink2 = x; sink2 = nil } +func escape(x any) { sink2 = x; sink2 = nil } -var sink2 interface{} +var sink2 any // Test zombie object detection and reporting. func GCZombie() { diff --git a/src/runtime/testdata/testprog/signal.go b/src/runtime/testdata/testprog/signal.go index 417e105c68..cc5ac8af58 100644 --- a/src/runtime/testdata/testprog/signal.go +++ b/src/runtime/testdata/testprog/signal.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !windows && !plan9 // +build !windows,!plan9 package main diff --git a/src/runtime/testdata/testprog/syscalls_none.go b/src/runtime/testdata/testprog/syscalls_none.go index 7f8ded3994..068bb59af3 100644 --- a/src/runtime/testdata/testprog/syscalls_none.go +++ b/src/runtime/testdata/testprog/syscalls_none.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !linux // +build !linux package main diff --git a/src/runtime/testdata/testprogcgo/callback.go b/src/runtime/testdata/testprogcgo/callback.go index be0409f39d..a2d8a492a4 100644 --- a/src/runtime/testdata/testprogcgo/callback.go +++ b/src/runtime/testdata/testprogcgo/callback.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !plan9 && !windows // +build !plan9,!windows package main diff --git a/src/runtime/testdata/testprogcgo/catchpanic.go b/src/runtime/testdata/testprogcgo/catchpanic.go index 55a606d1bc..c722d40a19 100644 --- a/src/runtime/testdata/testprogcgo/catchpanic.go +++ b/src/runtime/testdata/testprogcgo/catchpanic.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !plan9 && !windows // +build !plan9,!windows package main diff --git a/src/runtime/testdata/testprogcgo/dropm.go b/src/runtime/testdata/testprogcgo/dropm.go index 9e782f504f..700b7fa0c2 100644 --- a/src/runtime/testdata/testprogcgo/dropm.go +++ b/src/runtime/testdata/testprogcgo/dropm.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !plan9 && !windows // +build !plan9,!windows // Test that a sequence of callbacks from C to Go get the same m. diff --git a/src/runtime/testdata/testprogcgo/eintr.go b/src/runtime/testdata/testprogcgo/eintr.go index 1722a75eb9..b35b280a76 100644 --- a/src/runtime/testdata/testprogcgo/eintr.go +++ b/src/runtime/testdata/testprogcgo/eintr.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !plan9 && !windows // +build !plan9,!windows package main diff --git a/src/runtime/testdata/testprogcgo/exec.go b/src/runtime/testdata/testprogcgo/exec.go index 15723c7369..c268bcd9b2 100644 --- a/src/runtime/testdata/testprogcgo/exec.go +++ b/src/runtime/testdata/testprogcgo/exec.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !plan9 && !windows // +build !plan9,!windows package main diff --git a/src/runtime/testdata/testprogcgo/lockosthread.go b/src/runtime/testdata/testprogcgo/lockosthread.go index 36423d9eb0..8fcea35f52 100644 --- a/src/runtime/testdata/testprogcgo/lockosthread.go +++ b/src/runtime/testdata/testprogcgo/lockosthread.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !plan9 && !windows // +build !plan9,!windows package main diff --git a/src/runtime/testdata/testprogcgo/needmdeadlock.go b/src/runtime/testdata/testprogcgo/needmdeadlock.go index 5a9c359006..b95ec77468 100644 --- a/src/runtime/testdata/testprogcgo/needmdeadlock.go +++ b/src/runtime/testdata/testprogcgo/needmdeadlock.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !plan9 && !windows // +build !plan9,!windows package main diff --git a/src/runtime/testdata/testprogcgo/numgoroutine.go b/src/runtime/testdata/testprogcgo/numgoroutine.go index 5bdfe52ed4..1b9f202f46 100644 --- a/src/runtime/testdata/testprogcgo/numgoroutine.go +++ b/src/runtime/testdata/testprogcgo/numgoroutine.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !plan9 && !windows // +build !plan9,!windows package main diff --git a/src/runtime/testdata/testprogcgo/raceprof.go b/src/runtime/testdata/testprogcgo/raceprof.go index f7ca629789..c098e16196 100644 --- a/src/runtime/testdata/testprogcgo/raceprof.go +++ b/src/runtime/testdata/testprogcgo/raceprof.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build (linux && amd64) || (freebsd && amd64) // +build linux,amd64 freebsd,amd64 package main diff --git a/src/runtime/testdata/testprogcgo/racesig.go b/src/runtime/testdata/testprogcgo/racesig.go index a079b3fd1a..9352679714 100644 --- a/src/runtime/testdata/testprogcgo/racesig.go +++ b/src/runtime/testdata/testprogcgo/racesig.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build (linux && amd64) || (freebsd && amd64) // +build linux,amd64 freebsd,amd64 package main diff --git a/src/runtime/testdata/testprogcgo/segv.go b/src/runtime/testdata/testprogcgo/segv.go index 3237a8c69c..0632475228 100644 --- a/src/runtime/testdata/testprogcgo/segv.go +++ b/src/runtime/testdata/testprogcgo/segv.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !plan9 && !windows // +build !plan9,!windows package main diff --git a/src/runtime/testdata/testprogcgo/sigstack.go b/src/runtime/testdata/testprogcgo/sigstack.go index 21b668d6c0..12ca661033 100644 --- a/src/runtime/testdata/testprogcgo/sigstack.go +++ b/src/runtime/testdata/testprogcgo/sigstack.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !plan9 && !windows // +build !plan9,!windows // Test handling of Go-allocated signal stacks when calling from diff --git a/src/runtime/testdata/testprogcgo/threadpanic.go b/src/runtime/testdata/testprogcgo/threadpanic.go index f9b48a9026..2d24fe68ea 100644 --- a/src/runtime/testdata/testprogcgo/threadpanic.go +++ b/src/runtime/testdata/testprogcgo/threadpanic.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !plan9 // +build !plan9 package main diff --git a/src/runtime/testdata/testprogcgo/threadpprof.go b/src/runtime/testdata/testprogcgo/threadpprof.go index e093f67e1e..ec5e750da9 100644 --- a/src/runtime/testdata/testprogcgo/threadpprof.go +++ b/src/runtime/testdata/testprogcgo/threadpprof.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !plan9 && !windows // +build !plan9,!windows package main @@ -108,7 +109,7 @@ func pprofThread() { C.runCPUHogThread() }) - time.Sleep(1*time.Second) + time.Sleep(1 * time.Second) pprof.StopCPUProfile() diff --git a/src/runtime/testdata/testprogcgo/threadprof.go b/src/runtime/testdata/testprogcgo/threadprof.go index 2d4c1039fb..8081173c0f 100644 --- a/src/runtime/testdata/testprogcgo/threadprof.go +++ b/src/runtime/testdata/testprogcgo/threadprof.go @@ -5,8 +5,8 @@ // We only build this file with the tag "threadprof", since it starts // a thread running a busy loop at constructor time. -// +build !plan9,!windows -// +build threadprof +//go:build !plan9 && !windows && threadprof +// +build !plan9,!windows,threadprof package main diff --git a/src/runtime/testdata/testprognet/signal.go b/src/runtime/testdata/testprognet/signal.go index 4d2de79d97..dfa2e10e7a 100644 --- a/src/runtime/testdata/testprognet/signal.go +++ b/src/runtime/testdata/testprognet/signal.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !windows && !plan9 // +build !windows,!plan9 // This is in testprognet instead of testprog because testprog diff --git a/src/runtime/testdata/testprognet/signalexec.go b/src/runtime/testdata/testprognet/signalexec.go index 4a988ef6c1..62ebce7176 100644 --- a/src/runtime/testdata/testprognet/signalexec.go +++ b/src/runtime/testdata/testprognet/signalexec.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd // +build darwin dragonfly freebsd linux netbsd openbsd // This is in testprognet instead of testprog because testprog diff --git a/src/runtime/testdata/testwinlib/main.go b/src/runtime/testdata/testwinlib/main.go index 400eaa1c82..025ef913e5 100644 --- a/src/runtime/testdata/testwinlib/main.go +++ b/src/runtime/testdata/testwinlib/main.go @@ -1,3 +1,4 @@ +//go:build windows && cgo // +build windows,cgo package main diff --git a/src/runtime/time.go b/src/runtime/time.go index 46e9a8c2ab..a9ad620776 100644 --- a/src/runtime/time.go +++ b/src/runtime/time.go @@ -28,8 +28,8 @@ type timer struct { // when must be positive on an active timer. when int64 period int64 - f func(interface{}, uintptr) - arg interface{} + f func(any, uintptr) + arg any seq uintptr // What to set the when field to in timerModifiedXX status. @@ -232,14 +232,14 @@ func resetTimer(t *timer, when int64) bool { // modTimer modifies an existing timer. //go:linkname modTimer time.modTimer -func modTimer(t *timer, when, period int64, f func(interface{}, uintptr), arg interface{}, seq uintptr) { +func modTimer(t *timer, when, period int64, f func(any, uintptr), arg any, seq uintptr) { modtimer(t, when, period, f, arg, seq) } // Go runtime. // Ready the goroutine arg. -func goroutineReady(arg interface{}, seq uintptr) { +func goroutineReady(arg any, seq uintptr) { goready(arg.(*g), 0) } @@ -421,7 +421,7 @@ func dodeltimer0(pp *p) { // modtimer modifies an existing timer. // This is called by the netpoll code or time.Ticker.Reset or time.Timer.Reset. // Reports whether the timer was modified before it was run. -func modtimer(t *timer, when, period int64, f func(interface{}, uintptr), arg interface{}, seq uintptr) bool { +func modtimer(t *timer, when, period int64, f func(any, uintptr), arg any, seq uintptr) bool { if when <= 0 { throw("timer when must be positive") } diff --git a/src/runtime/trace/annotation.go b/src/runtime/trace/annotation.go index 6e18bfb755..d05b5e2261 100644 --- a/src/runtime/trace/annotation.go +++ b/src/runtime/trace/annotation.go @@ -98,7 +98,7 @@ func Log(ctx context.Context, category, message string) { } // Logf is like Log, but the value is formatted using the specified format spec. -func Logf(ctx context.Context, category, format string, args ...interface{}) { +func Logf(ctx context.Context, category, format string, args ...any) { if IsEnabled() { // Ideally this should be just Log, but that will // add one more frame in the stack trace. diff --git a/src/sort/slice.go b/src/sort/slice.go index 992ad1559d..ba5c2e2f3d 100644 --- a/src/sort/slice.go +++ b/src/sort/slice.go @@ -13,7 +13,7 @@ package sort // // The less function must satisfy the same requirements as // the Interface type's Less method. -func Slice(x interface{}, less func(i, j int) bool) { +func Slice(x any, less func(i, j int) bool) { rv := reflectValueOf(x) swap := reflectSwapper(x) length := rv.Len() @@ -26,7 +26,7 @@ func Slice(x interface{}, less func(i, j int) bool) { // // The less function must satisfy the same requirements as // the Interface type's Less method. -func SliceStable(x interface{}, less func(i, j int) bool) { +func SliceStable(x any, less func(i, j int) bool) { rv := reflectValueOf(x) swap := reflectSwapper(x) stable_func(lessSwap{less, swap}, rv.Len()) @@ -34,7 +34,7 @@ func SliceStable(x interface{}, less func(i, j int) bool) { // SliceIsSorted reports whether the slice x is sorted according to the provided less function. // It panics if x is not a slice. -func SliceIsSorted(x interface{}, less func(i, j int) bool) bool { +func SliceIsSorted(x any, less func(i, j int) bool) bool { rv := reflectValueOf(x) n := rv.Len() for i := n - 1; i > 0; i-- { diff --git a/src/sort/slice_go14.go b/src/sort/slice_go14.go index 5d5949f3ca..e477367618 100644 --- a/src/sort/slice_go14.go +++ b/src/sort/slice_go14.go @@ -11,7 +11,7 @@ import "reflect" var reflectValueOf = reflect.ValueOf -func reflectSwapper(x interface{}) func(int, int) { +func reflectSwapper(x any) func(int, int) { v := reflectValueOf(x) tmp := reflect.New(v.Type().Elem()).Elem() return func(i, j int) { diff --git a/src/strings/export_test.go b/src/strings/export_test.go index b39cee6b1d..81d1cab9d0 100644 --- a/src/strings/export_test.go +++ b/src/strings/export_test.go @@ -4,7 +4,7 @@ package strings -func (r *Replacer) Replacer() interface{} { +func (r *Replacer) Replacer() any { r.once.Do(r.buildOnce) return r.r } diff --git a/src/strings/reader_test.go b/src/strings/reader_test.go index 5adea6f7ab..dc99f9c248 100644 --- a/src/strings/reader_test.go +++ b/src/strings/reader_test.go @@ -77,7 +77,7 @@ func TestReaderAt(t *testing.T) { off int64 n int want string - wanterr interface{} + wanterr any }{ {0, 10, "0123456789", nil}, {1, 10, "123456789", io.EOF}, diff --git a/src/sync/atomic/atomic_test.go b/src/sync/atomic/atomic_test.go index 4b8c2a58f3..8a53094cb7 100644 --- a/src/sync/atomic/atomic_test.go +++ b/src/sync/atomic/atomic_test.go @@ -32,7 +32,7 @@ const ( ) // Do the 64-bit functions panic? If so, don't bother testing. -var test64err = func() (err interface{}) { +var test64err = func() (err any) { defer func() { err = recover() }() diff --git a/src/sync/atomic/value.go b/src/sync/atomic/value.go index af6295de91..f18b7ee095 100644 --- a/src/sync/atomic/value.go +++ b/src/sync/atomic/value.go @@ -14,7 +14,7 @@ import ( // // A Value must not be copied after first use. type Value struct { - v interface{} + v any } // ifaceWords is interface{} internal representation. @@ -25,7 +25,7 @@ type ifaceWords struct { // Load returns the value set by the most recent Store. // It returns nil if there has been no call to Store for this Value. -func (v *Value) Load() (val interface{}) { +func (v *Value) Load() (val any) { vp := (*ifaceWords)(unsafe.Pointer(v)) typ := LoadPointer(&vp.typ) if typ == nil || typ == unsafe.Pointer(&firstStoreInProgress) { @@ -44,7 +44,7 @@ var firstStoreInProgress byte // Store sets the value of the Value to x. // All calls to Store for a given Value must use values of the same concrete type. // Store of an inconsistent type panics, as does Store(nil). -func (v *Value) Store(val interface{}) { +func (v *Value) Store(val any) { if val == nil { panic("sync/atomic: store of nil value into Value") } @@ -87,7 +87,7 @@ func (v *Value) Store(val interface{}) { // // All calls to Swap for a given Value must use values of the same concrete // type. Swap of an inconsistent type panics, as does Swap(nil). -func (v *Value) Swap(new interface{}) (old interface{}) { +func (v *Value) Swap(new any) (old any) { if new == nil { panic("sync/atomic: swap of nil value into Value") } @@ -132,7 +132,7 @@ func (v *Value) Swap(new interface{}) (old interface{}) { // All calls to CompareAndSwap for a given Value must use values of the same // concrete type. CompareAndSwap of an inconsistent type panics, as does // CompareAndSwap(old, nil). -func (v *Value) CompareAndSwap(old, new interface{}) (swapped bool) { +func (v *Value) CompareAndSwap(old, new any) (swapped bool) { if new == nil { panic("sync/atomic: compare and swap of nil value into Value") } @@ -179,7 +179,7 @@ func (v *Value) CompareAndSwap(old, new interface{}) (swapped bool) { // CompareAndSwapPointer below only ensures vp.data // has not changed since LoadPointer. data := LoadPointer(&vp.data) - var i interface{} + var i any (*ifaceWords)(unsafe.Pointer(&i)).typ = typ (*ifaceWords)(unsafe.Pointer(&i)).data = data if i != old { diff --git a/src/sync/atomic/value_test.go b/src/sync/atomic/value_test.go index a5e717d6e0..721da965e3 100644 --- a/src/sync/atomic/value_test.go +++ b/src/sync/atomic/value_test.go @@ -80,7 +80,7 @@ func TestValuePanic(t *testing.T) { } func TestValueConcurrent(t *testing.T) { - tests := [][]interface{}{ + tests := [][]any{ {uint16(0), ^uint16(0), uint16(1 + 2<<8), uint16(3 + 4<<8)}, {uint32(0), ^uint32(0), uint32(1 + 2<<16), uint32(3 + 4<<16)}, {uint64(0), ^uint64(0), uint64(1 + 2<<32), uint64(3 + 4<<32)}, @@ -138,10 +138,10 @@ func BenchmarkValueRead(b *testing.B) { } var Value_SwapTests = []struct { - init interface{} - new interface{} - want interface{} - err interface{} + init any + new any + want any + err any }{ {init: nil, new: nil, err: "sync/atomic: swap of nil value into Value"}, {init: nil, new: true, want: nil, err: nil}, @@ -207,11 +207,11 @@ func TestValueSwapConcurrent(t *testing.T) { var heapA, heapB = struct{ uint }{0}, struct{ uint }{0} var Value_CompareAndSwapTests = []struct { - init interface{} - new interface{} - old interface{} + init any + new any + old any want bool - err interface{} + err any }{ {init: nil, new: nil, old: nil, err: "sync/atomic: compare and swap of nil value into Value"}, {init: nil, new: true, old: "", err: "sync/atomic: compare and swap of inconsistently typed values into Value"}, diff --git a/src/sync/example_pool_test.go b/src/sync/example_pool_test.go index 8288d41e8c..2fb4c1e6b9 100644 --- a/src/sync/example_pool_test.go +++ b/src/sync/example_pool_test.go @@ -13,7 +13,7 @@ import ( ) var bufPool = sync.Pool{ - New: func() interface{} { + New: func() any { // The Pool's New function should generally only return pointer // types, since a pointer can be put into the return interface // value without an allocation: diff --git a/src/sync/export_test.go b/src/sync/export_test.go index ffbe567464..c020ef737d 100644 --- a/src/sync/export_test.go +++ b/src/sync/export_test.go @@ -12,9 +12,9 @@ var Runtime_procUnpin = runtime_procUnpin // poolDequeue testing. type PoolDequeue interface { - PushHead(val interface{}) bool - PopHead() (interface{}, bool) - PopTail() (interface{}, bool) + PushHead(val any) bool + PopHead() (any, bool) + PopTail() (any, bool) } func NewPoolDequeue(n int) PoolDequeue { @@ -27,15 +27,15 @@ func NewPoolDequeue(n int) PoolDequeue { return d } -func (d *poolDequeue) PushHead(val interface{}) bool { +func (d *poolDequeue) PushHead(val any) bool { return d.pushHead(val) } -func (d *poolDequeue) PopHead() (interface{}, bool) { +func (d *poolDequeue) PopHead() (any, bool) { return d.popHead() } -func (d *poolDequeue) PopTail() (interface{}, bool) { +func (d *poolDequeue) PopTail() (any, bool) { return d.popTail() } @@ -43,15 +43,15 @@ func NewPoolChain() PoolDequeue { return new(poolChain) } -func (c *poolChain) PushHead(val interface{}) bool { +func (c *poolChain) PushHead(val any) bool { c.pushHead(val) return true } -func (c *poolChain) PopHead() (interface{}, bool) { +func (c *poolChain) PopHead() (any, bool) { return c.popHead() } -func (c *poolChain) PopTail() (interface{}, bool) { +func (c *poolChain) PopTail() (any, bool) { return c.popTail() } diff --git a/src/sync/map.go b/src/sync/map.go index 7a6c82e5c3..2fa3253429 100644 --- a/src/sync/map.go +++ b/src/sync/map.go @@ -48,7 +48,7 @@ type Map struct { // // If the dirty map is nil, the next write to the map will initialize it by // making a shallow copy of the clean map, omitting stale entries. - dirty map[interface{}]*entry + dirty map[any]*entry // misses counts the number of loads since the read map was last updated that // needed to lock mu to determine whether the key was present. @@ -61,13 +61,13 @@ type Map struct { // readOnly is an immutable struct stored atomically in the Map.read field. type readOnly struct { - m map[interface{}]*entry + m map[any]*entry amended bool // true if the dirty map contains some key not in m. } // expunged is an arbitrary pointer that marks entries which have been deleted // from the dirty map. -var expunged = unsafe.Pointer(new(interface{})) +var expunged = unsafe.Pointer(new(any)) // An entry is a slot in the map corresponding to a particular key. type entry struct { @@ -93,14 +93,14 @@ type entry struct { p unsafe.Pointer // *interface{} } -func newEntry(i interface{}) *entry { +func newEntry(i any) *entry { return &entry{p: unsafe.Pointer(&i)} } // Load returns the value stored in the map for a key, or nil if no // value is present. // The ok result indicates whether value was found in the map. -func (m *Map) Load(key interface{}) (value interface{}, ok bool) { +func (m *Map) Load(key any) (value any, ok bool) { read, _ := m.read.Load().(readOnly) e, ok := read.m[key] if !ok && read.amended { @@ -125,16 +125,16 @@ func (m *Map) Load(key interface{}) (value interface{}, ok bool) { return e.load() } -func (e *entry) load() (value interface{}, ok bool) { +func (e *entry) load() (value any, ok bool) { p := atomic.LoadPointer(&e.p) if p == nil || p == expunged { return nil, false } - return *(*interface{})(p), true + return *(*any)(p), true } // Store sets the value for a key. -func (m *Map) Store(key, value interface{}) { +func (m *Map) Store(key, value any) { read, _ := m.read.Load().(readOnly) if e, ok := read.m[key]; ok && e.tryStore(&value) { return @@ -167,7 +167,7 @@ func (m *Map) Store(key, value interface{}) { // // If the entry is expunged, tryStore returns false and leaves the entry // unchanged. -func (e *entry) tryStore(i *interface{}) bool { +func (e *entry) tryStore(i *any) bool { for { p := atomic.LoadPointer(&e.p) if p == expunged { @@ -190,14 +190,14 @@ func (e *entry) unexpungeLocked() (wasExpunged bool) { // storeLocked unconditionally stores a value to the entry. // // The entry must be known not to be expunged. -func (e *entry) storeLocked(i *interface{}) { +func (e *entry) storeLocked(i *any) { atomic.StorePointer(&e.p, unsafe.Pointer(i)) } // LoadOrStore returns the existing value for the key if present. // Otherwise, it stores and returns the given value. // The loaded result is true if the value was loaded, false if stored. -func (m *Map) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool) { +func (m *Map) LoadOrStore(key, value any) (actual any, loaded bool) { // Avoid locking if it's a clean hit. read, _ := m.read.Load().(readOnly) if e, ok := read.m[key]; ok { @@ -237,13 +237,13 @@ func (m *Map) LoadOrStore(key, value interface{}) (actual interface{}, loaded bo // // If the entry is expunged, tryLoadOrStore leaves the entry unchanged and // returns with ok==false. -func (e *entry) tryLoadOrStore(i interface{}) (actual interface{}, loaded, ok bool) { +func (e *entry) tryLoadOrStore(i any) (actual any, loaded, ok bool) { p := atomic.LoadPointer(&e.p) if p == expunged { return nil, false, false } if p != nil { - return *(*interface{})(p), true, true + return *(*any)(p), true, true } // Copy the interface after the first load to make this method more amenable @@ -259,14 +259,14 @@ func (e *entry) tryLoadOrStore(i interface{}) (actual interface{}, loaded, ok bo return nil, false, false } if p != nil { - return *(*interface{})(p), true, true + return *(*any)(p), true, true } } } // LoadAndDelete deletes the value for a key, returning the previous value if any. // The loaded result reports whether the key was present. -func (m *Map) LoadAndDelete(key interface{}) (value interface{}, loaded bool) { +func (m *Map) LoadAndDelete(key any) (value any, loaded bool) { read, _ := m.read.Load().(readOnly) e, ok := read.m[key] if !ok && read.amended { @@ -290,18 +290,18 @@ func (m *Map) LoadAndDelete(key interface{}) (value interface{}, loaded bool) { } // Delete deletes the value for a key. -func (m *Map) Delete(key interface{}) { +func (m *Map) Delete(key any) { m.LoadAndDelete(key) } -func (e *entry) delete() (value interface{}, ok bool) { +func (e *entry) delete() (value any, ok bool) { for { p := atomic.LoadPointer(&e.p) if p == nil || p == expunged { return nil, false } if atomic.CompareAndSwapPointer(&e.p, p, nil) { - return *(*interface{})(p), true + return *(*any)(p), true } } } @@ -317,7 +317,7 @@ func (e *entry) delete() (value interface{}, ok bool) { // // Range may be O(N) with the number of elements in the map even if f returns // false after a constant number of calls. -func (m *Map) Range(f func(key, value interface{}) bool) { +func (m *Map) Range(f func(key, value any) bool) { // We need to be able to iterate over all of the keys that were already // present at the start of the call to Range. // If read.amended is false, then read.m satisfies that property without @@ -366,7 +366,7 @@ func (m *Map) dirtyLocked() { } read, _ := m.read.Load().(readOnly) - m.dirty = make(map[interface{}]*entry, len(read.m)) + m.dirty = make(map[any]*entry, len(read.m)) for k, e := range read.m { if !e.tryExpungeLocked() { m.dirty[k] = e diff --git a/src/sync/map_bench_test.go b/src/sync/map_bench_test.go index cf0a3d7fde..e7b0e6039c 100644 --- a/src/sync/map_bench_test.go +++ b/src/sync/map_bench_test.go @@ -216,7 +216,7 @@ func BenchmarkRange(b *testing.B) { perG: func(b *testing.B, pb *testing.PB, i int, m mapInterface) { for ; pb.Next(); i++ { - m.Range(func(_, _ interface{}) bool { return true }) + m.Range(func(_, _ any) bool { return true }) } }, }) @@ -263,7 +263,7 @@ func BenchmarkAdversarialDelete(b *testing.B) { m.Load(i) if i%mapSize == 0 { - m.Range(func(k, _ interface{}) bool { + m.Range(func(k, _ any) bool { m.Delete(k) return false }) diff --git a/src/sync/map_reference_test.go b/src/sync/map_reference_test.go index d105a24e92..1122b40b9b 100644 --- a/src/sync/map_reference_test.go +++ b/src/sync/map_reference_test.go @@ -13,43 +13,43 @@ import ( // mapInterface is the interface Map implements. type mapInterface interface { - Load(interface{}) (interface{}, bool) - Store(key, value interface{}) - LoadOrStore(key, value interface{}) (actual interface{}, loaded bool) - LoadAndDelete(key interface{}) (value interface{}, loaded bool) - Delete(interface{}) - Range(func(key, value interface{}) (shouldContinue bool)) + Load(any) (any, bool) + Store(key, value any) + LoadOrStore(key, value any) (actual any, loaded bool) + LoadAndDelete(key any) (value any, loaded bool) + Delete(any) + Range(func(key, value any) (shouldContinue bool)) } // RWMutexMap is an implementation of mapInterface using a sync.RWMutex. type RWMutexMap struct { mu sync.RWMutex - dirty map[interface{}]interface{} + dirty map[any]any } -func (m *RWMutexMap) Load(key interface{}) (value interface{}, ok bool) { +func (m *RWMutexMap) Load(key any) (value any, ok bool) { m.mu.RLock() value, ok = m.dirty[key] m.mu.RUnlock() return } -func (m *RWMutexMap) Store(key, value interface{}) { +func (m *RWMutexMap) Store(key, value any) { m.mu.Lock() if m.dirty == nil { - m.dirty = make(map[interface{}]interface{}) + m.dirty = make(map[any]any) } m.dirty[key] = value m.mu.Unlock() } -func (m *RWMutexMap) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool) { +func (m *RWMutexMap) LoadOrStore(key, value any) (actual any, loaded bool) { m.mu.Lock() actual, loaded = m.dirty[key] if !loaded { actual = value if m.dirty == nil { - m.dirty = make(map[interface{}]interface{}) + m.dirty = make(map[any]any) } m.dirty[key] = value } @@ -57,7 +57,7 @@ func (m *RWMutexMap) LoadOrStore(key, value interface{}) (actual interface{}, lo return actual, loaded } -func (m *RWMutexMap) LoadAndDelete(key interface{}) (value interface{}, loaded bool) { +func (m *RWMutexMap) LoadAndDelete(key any) (value any, loaded bool) { m.mu.Lock() value, loaded = m.dirty[key] if !loaded { @@ -69,15 +69,15 @@ func (m *RWMutexMap) LoadAndDelete(key interface{}) (value interface{}, loaded b return value, loaded } -func (m *RWMutexMap) Delete(key interface{}) { +func (m *RWMutexMap) Delete(key any) { m.mu.Lock() delete(m.dirty, key) m.mu.Unlock() } -func (m *RWMutexMap) Range(f func(key, value interface{}) (shouldContinue bool)) { +func (m *RWMutexMap) Range(f func(key, value any) (shouldContinue bool)) { m.mu.RLock() - keys := make([]interface{}, 0, len(m.dirty)) + keys := make([]any, 0, len(m.dirty)) for k := range m.dirty { keys = append(keys, k) } @@ -102,13 +102,13 @@ type DeepCopyMap struct { clean atomic.Value } -func (m *DeepCopyMap) Load(key interface{}) (value interface{}, ok bool) { - clean, _ := m.clean.Load().(map[interface{}]interface{}) +func (m *DeepCopyMap) Load(key any) (value any, ok bool) { + clean, _ := m.clean.Load().(map[any]any) value, ok = clean[key] return value, ok } -func (m *DeepCopyMap) Store(key, value interface{}) { +func (m *DeepCopyMap) Store(key, value any) { m.mu.Lock() dirty := m.dirty() dirty[key] = value @@ -116,8 +116,8 @@ func (m *DeepCopyMap) Store(key, value interface{}) { m.mu.Unlock() } -func (m *DeepCopyMap) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool) { - clean, _ := m.clean.Load().(map[interface{}]interface{}) +func (m *DeepCopyMap) LoadOrStore(key, value any) (actual any, loaded bool) { + clean, _ := m.clean.Load().(map[any]any) actual, loaded = clean[key] if loaded { return actual, loaded @@ -125,7 +125,7 @@ func (m *DeepCopyMap) LoadOrStore(key, value interface{}) (actual interface{}, l m.mu.Lock() // Reload clean in case it changed while we were waiting on m.mu. - clean, _ = m.clean.Load().(map[interface{}]interface{}) + clean, _ = m.clean.Load().(map[any]any) actual, loaded = clean[key] if !loaded { dirty := m.dirty() @@ -137,7 +137,7 @@ func (m *DeepCopyMap) LoadOrStore(key, value interface{}) (actual interface{}, l return actual, loaded } -func (m *DeepCopyMap) LoadAndDelete(key interface{}) (value interface{}, loaded bool) { +func (m *DeepCopyMap) LoadAndDelete(key any) (value any, loaded bool) { m.mu.Lock() dirty := m.dirty() value, loaded = dirty[key] @@ -147,7 +147,7 @@ func (m *DeepCopyMap) LoadAndDelete(key interface{}) (value interface{}, loaded return } -func (m *DeepCopyMap) Delete(key interface{}) { +func (m *DeepCopyMap) Delete(key any) { m.mu.Lock() dirty := m.dirty() delete(dirty, key) @@ -155,8 +155,8 @@ func (m *DeepCopyMap) Delete(key interface{}) { m.mu.Unlock() } -func (m *DeepCopyMap) Range(f func(key, value interface{}) (shouldContinue bool)) { - clean, _ := m.clean.Load().(map[interface{}]interface{}) +func (m *DeepCopyMap) Range(f func(key, value any) (shouldContinue bool)) { + clean, _ := m.clean.Load().(map[any]any) for k, v := range clean { if !f(k, v) { break @@ -164,9 +164,9 @@ func (m *DeepCopyMap) Range(f func(key, value interface{}) (shouldContinue bool) } } -func (m *DeepCopyMap) dirty() map[interface{}]interface{} { - clean, _ := m.clean.Load().(map[interface{}]interface{}) - dirty := make(map[interface{}]interface{}, len(clean)+1) +func (m *DeepCopyMap) dirty() map[any]any { + clean, _ := m.clean.Load().(map[any]any) + dirty := make(map[any]any, len(clean)+1) for k, v := range clean { dirty[k] = v } diff --git a/src/sync/map_test.go b/src/sync/map_test.go index c4a8f8b99a..8352471104 100644 --- a/src/sync/map_test.go +++ b/src/sync/map_test.go @@ -29,10 +29,10 @@ var mapOps = [...]mapOp{opLoad, opStore, opLoadOrStore, opLoadAndDelete, opDelet // mapCall is a quick.Generator for calls on mapInterface. type mapCall struct { op mapOp - k, v interface{} + k, v any } -func (c mapCall) apply(m mapInterface) (interface{}, bool) { +func (c mapCall) apply(m mapInterface) (any, bool) { switch c.op { case opLoad: return m.Load(c.k) @@ -52,11 +52,11 @@ func (c mapCall) apply(m mapInterface) (interface{}, bool) { } type mapResult struct { - value interface{} + value any ok bool } -func randValue(r *rand.Rand) interface{} { +func randValue(r *rand.Rand) any { b := make([]byte, r.Intn(4)) for i := range b { b[i] = 'a' + byte(rand.Intn(26)) @@ -73,14 +73,14 @@ func (mapCall) Generate(r *rand.Rand, size int) reflect.Value { return reflect.ValueOf(c) } -func applyCalls(m mapInterface, calls []mapCall) (results []mapResult, final map[interface{}]interface{}) { +func applyCalls(m mapInterface, calls []mapCall) (results []mapResult, final map[any]any) { for _, c := range calls { v, ok := c.apply(m) results = append(results, mapResult{v, ok}) } - final = make(map[interface{}]interface{}) - m.Range(func(k, v interface{}) bool { + final = make(map[any]any) + m.Range(func(k, v any) bool { final[k] = v return true }) @@ -88,15 +88,15 @@ func applyCalls(m mapInterface, calls []mapCall) (results []mapResult, final map return results, final } -func applyMap(calls []mapCall) ([]mapResult, map[interface{}]interface{}) { +func applyMap(calls []mapCall) ([]mapResult, map[any]any) { return applyCalls(new(sync.Map), calls) } -func applyRWMutexMap(calls []mapCall) ([]mapResult, map[interface{}]interface{}) { +func applyRWMutexMap(calls []mapCall) ([]mapResult, map[any]any) { return applyCalls(new(RWMutexMap), calls) } -func applyDeepCopyMap(calls []mapCall) ([]mapResult, map[interface{}]interface{}) { +func applyDeepCopyMap(calls []mapCall) ([]mapResult, map[any]any) { return applyCalls(new(DeepCopyMap), calls) } @@ -155,7 +155,7 @@ func TestConcurrentRange(t *testing.T) { for n := iters; n > 0; n-- { seen := make(map[int64]bool, mapSize) - m.Range(func(ki, vi interface{}) bool { + m.Range(func(ki, vi any) bool { k, v := ki.(int64), vi.(int64) if v%k != 0 { t.Fatalf("while Storing multiples of %v, Range saw value %v", k, v) @@ -201,8 +201,8 @@ func TestMapRangeNestedCall(t *testing.T) { // Issue 46399 for i, v := range [3]string{"hello", "world", "Go"} { m.Store(i, v) } - m.Range(func(key, value interface{}) bool { - m.Range(func(key, value interface{}) bool { + m.Range(func(key, value any) bool { + m.Range(func(key, value any) bool { // We should be able to load the key offered in the Range callback, // because there are no concurrent Delete involved in this tested map. if v, ok := m.Load(key); !ok || !reflect.DeepEqual(v, value) { @@ -236,7 +236,7 @@ func TestMapRangeNestedCall(t *testing.T) { // Issue 46399 // After a Range of Delete, all keys should be removed and any // further Range won't invoke the callback. Hence length remains 0. length := 0 - m.Range(func(key, value interface{}) bool { + m.Range(func(key, value any) bool { length++ return true }) diff --git a/src/sync/pool.go b/src/sync/pool.go index 9802f29d6f..d1abb6a8b7 100644 --- a/src/sync/pool.go +++ b/src/sync/pool.go @@ -53,13 +53,13 @@ type Pool struct { // New optionally specifies a function to generate // a value when Get would otherwise return nil. // It may not be changed concurrently with calls to Get. - New func() interface{} + New func() any } // Local per-P Pool appendix. type poolLocalInternal struct { - private interface{} // Can be used only by the respective P. - shared poolChain // Local P can pushHead/popHead; any P can popTail. + private any // Can be used only by the respective P. + shared poolChain // Local P can pushHead/popHead; any P can popTail. } type poolLocal struct { @@ -80,14 +80,14 @@ var poolRaceHash [128]uint64 // directly, for fear of conflicting with other synchronization on that address. // Instead, we hash the pointer to get an index into poolRaceHash. // See discussion on golang.org/cl/31589. -func poolRaceAddr(x interface{}) unsafe.Pointer { +func poolRaceAddr(x any) unsafe.Pointer { ptr := uintptr((*[2]unsafe.Pointer)(unsafe.Pointer(&x))[1]) h := uint32((uint64(uint32(ptr)) * 0x85ebca6b) >> 16) return unsafe.Pointer(&poolRaceHash[h%uint32(len(poolRaceHash))]) } // Put adds x to the pool. -func (p *Pool) Put(x interface{}) { +func (p *Pool) Put(x any) { if x == nil { return } @@ -121,7 +121,7 @@ func (p *Pool) Put(x interface{}) { // // If Get would otherwise return nil and p.New is non-nil, Get returns // the result of calling p.New. -func (p *Pool) Get() interface{} { +func (p *Pool) Get() any { if race.Enabled { race.Disable() } @@ -150,7 +150,7 @@ func (p *Pool) Get() interface{} { return x } -func (p *Pool) getSlow(pid int) interface{} { +func (p *Pool) getSlow(pid int) any { // See the comment in pin regarding ordering of the loads. size := runtime_LoadAcquintptr(&p.localSize) // load-acquire locals := p.local // load-consume diff --git a/src/sync/pool_test.go b/src/sync/pool_test.go index d991621624..bb20043a54 100644 --- a/src/sync/pool_test.go +++ b/src/sync/pool_test.go @@ -64,7 +64,7 @@ func TestPoolNew(t *testing.T) { i := 0 p := Pool{ - New: func() interface{} { + New: func() any { i++ return i }, @@ -143,7 +143,7 @@ func TestPoolStress(t *testing.T) { done := make(chan bool) for i := 0; i < P; i++ { go func() { - var v interface{} = 0 + var v any = 0 for j := 0; j < N; j++ { if v == nil { v = 0 @@ -290,7 +290,7 @@ func BenchmarkPoolStarvation(b *testing.B) { }) } -var globalSink interface{} +var globalSink any func BenchmarkPoolSTW(b *testing.B) { // Take control of GC. @@ -303,7 +303,7 @@ func BenchmarkPoolSTW(b *testing.B) { for i := 0; i < b.N; i++ { // Put a large number of items into a pool. const N = 100000 - var item interface{} = 42 + var item any = 42 for i := 0; i < N; i++ { p.Put(item) } @@ -338,7 +338,7 @@ func BenchmarkPoolExpensiveNew(b *testing.B) { // Create a pool that's "expensive" to fill. var p Pool var nNew uint64 - p.New = func() interface{} { + p.New = func() any { atomic.AddUint64(&nNew, 1) time.Sleep(time.Millisecond) return 42 @@ -348,7 +348,7 @@ func BenchmarkPoolExpensiveNew(b *testing.B) { b.RunParallel(func(pb *testing.PB) { // Simulate 100X the number of goroutines having items // checked out from the Pool simultaneously. - items := make([]interface{}, 100) + items := make([]any, 100) var sink []byte for pb.Next() { // Stress the pool. diff --git a/src/sync/poolqueue.go b/src/sync/poolqueue.go index 9be83e9a43..631f2c15fd 100644 --- a/src/sync/poolqueue.go +++ b/src/sync/poolqueue.go @@ -77,7 +77,7 @@ func (d *poolDequeue) pack(head, tail uint32) uint64 { // pushHead adds val at the head of the queue. It returns false if the // queue is full. It must only be called by a single producer. -func (d *poolDequeue) pushHead(val interface{}) bool { +func (d *poolDequeue) pushHead(val any) bool { ptrs := atomic.LoadUint64(&d.headTail) head, tail := d.unpack(ptrs) if (tail+uint32(len(d.vals)))&(1<= 1 { // on Node.js 8, fs.utimes calls the callback without any arguments diff --git a/src/syscall/js/func.go b/src/syscall/js/func.go index 77fb9e66ca..cc94972364 100644 --- a/src/syscall/js/func.go +++ b/src/syscall/js/func.go @@ -10,7 +10,7 @@ import "sync" var ( funcsMu sync.Mutex - funcs = make(map[uint32]func(Value, []Value) interface{}) + funcs = make(map[uint32]func(Value, []Value) any) nextFuncID uint32 = 1 ) @@ -38,7 +38,7 @@ type Func struct { // new goroutine. // // Func.Release must be called to free up resources when the function will not be invoked any more. -func FuncOf(fn func(this Value, args []Value) interface{}) Func { +func FuncOf(fn func(this Value, args []Value) any) Func { funcsMu.Lock() id := nextFuncID nextFuncID++ diff --git a/src/syscall/js/js.go b/src/syscall/js/js.go index d80d5d63de..a5210faf7f 100644 --- a/src/syscall/js/js.go +++ b/src/syscall/js/js.go @@ -148,7 +148,7 @@ func Global() Value { // | map[string]interface{} | new object | // // Panics if x is not one of the expected types. -func ValueOf(x interface{}) Value { +func ValueOf(x any) Value { switch x := x.(type) { case Value: return x @@ -192,13 +192,13 @@ func ValueOf(x interface{}) Value { return floatValue(x) case string: return makeValue(stringVal(x)) - case []interface{}: + case []any: a := arrayConstructor.New(len(x)) for i, s := range x { a.SetIndex(i, s) } return a - case map[string]interface{}: + case map[string]any: o := objectConstructor.New() for k, v := range x { o.Set(k, v) @@ -296,7 +296,7 @@ func valueGet(v ref, p string) ref // Set sets the JavaScript property p of value v to ValueOf(x). // It panics if v is not a JavaScript object. -func (v Value) Set(p string, x interface{}) { +func (v Value) Set(p string, x any) { if vType := v.Type(); !vType.isObject() { panic(&ValueError{"Value.Set", vType}) } @@ -335,7 +335,7 @@ func valueIndex(v ref, i int) ref // SetIndex sets the JavaScript index i of value v to ValueOf(x). // It panics if v is not a JavaScript object. -func (v Value) SetIndex(i int, x interface{}) { +func (v Value) SetIndex(i int, x any) { if vType := v.Type(); !vType.isObject() { panic(&ValueError{"Value.SetIndex", vType}) } @@ -347,7 +347,7 @@ func (v Value) SetIndex(i int, x interface{}) { func valueSetIndex(v ref, i int, x ref) -func makeArgs(args []interface{}) ([]Value, []ref) { +func makeArgs(args []any) ([]Value, []ref) { argVals := make([]Value, len(args)) argRefs := make([]ref, len(args)) for i, arg := range args { @@ -374,7 +374,7 @@ func valueLength(v ref) int // Call does a JavaScript call to the method m of value v with the given arguments. // It panics if v has no method m. // The arguments get mapped to JavaScript values according to the ValueOf function. -func (v Value) Call(m string, args ...interface{}) Value { +func (v Value) Call(m string, args ...any) Value { argVals, argRefs := makeArgs(args) res, ok := valueCall(v.ref, m, argRefs) runtime.KeepAlive(v) @@ -396,7 +396,7 @@ func valueCall(v ref, m string, args []ref) (ref, bool) // Invoke does a JavaScript call of the value v with the given arguments. // It panics if v is not a JavaScript function. // The arguments get mapped to JavaScript values according to the ValueOf function. -func (v Value) Invoke(args ...interface{}) Value { +func (v Value) Invoke(args ...any) Value { argVals, argRefs := makeArgs(args) res, ok := valueInvoke(v.ref, argRefs) runtime.KeepAlive(v) @@ -415,7 +415,7 @@ func valueInvoke(v ref, args []ref) (ref, bool) // New uses JavaScript's "new" operator with value v as constructor and the given arguments. // It panics if v is not a JavaScript function. // The arguments get mapped to JavaScript values according to the ValueOf function. -func (v Value) New(args ...interface{}) Value { +func (v Value) New(args ...any) Value { argVals, argRefs := makeArgs(args) res, ok := valueNew(v.ref, argRefs) runtime.KeepAlive(v) diff --git a/src/syscall/js/js_test.go b/src/syscall/js/js_test.go index fa8c782459..f860a5bb50 100644 --- a/src/syscall/js/js_test.go +++ b/src/syscall/js/js_test.go @@ -364,8 +364,8 @@ func TestType(t *testing.T) { } } -type object = map[string]interface{} -type array = []interface{} +type object = map[string]any +type array = []any func TestValueOf(t *testing.T) { a := js.ValueOf(array{0, array{0, 42, 0}, 0}) @@ -388,7 +388,7 @@ func TestZeroValue(t *testing.T) { func TestFuncOf(t *testing.T) { c := make(chan struct{}) - cb := js.FuncOf(func(this js.Value, args []js.Value) interface{} { + cb := js.FuncOf(func(this js.Value, args []js.Value) any { if got := args[0].Int(); got != 42 { t.Errorf("got %#v, want %#v", got, 42) } @@ -402,8 +402,8 @@ func TestFuncOf(t *testing.T) { func TestInvokeFunction(t *testing.T) { called := false - cb := js.FuncOf(func(this js.Value, args []js.Value) interface{} { - cb2 := js.FuncOf(func(this js.Value, args []js.Value) interface{} { + cb := js.FuncOf(func(this js.Value, args []js.Value) any { + cb2 := js.FuncOf(func(this js.Value, args []js.Value) any { called = true return 42 }) @@ -423,7 +423,7 @@ func TestInterleavedFunctions(t *testing.T) { c1 := make(chan struct{}) c2 := make(chan struct{}) - js.Global().Get("setTimeout").Invoke(js.FuncOf(func(this js.Value, args []js.Value) interface{} { + js.Global().Get("setTimeout").Invoke(js.FuncOf(func(this js.Value, args []js.Value) any { c1 <- struct{}{} <-c2 return nil @@ -432,7 +432,7 @@ func TestInterleavedFunctions(t *testing.T) { <-c1 c2 <- struct{}{} // this goroutine is running, but the callback of setTimeout did not return yet, invoke another function now - f := js.FuncOf(func(this js.Value, args []js.Value) interface{} { + f := js.FuncOf(func(this js.Value, args []js.Value) any { return nil }) f.Invoke() @@ -440,7 +440,7 @@ func TestInterleavedFunctions(t *testing.T) { func ExampleFuncOf() { var cb js.Func - cb = js.FuncOf(func(this js.Value, args []js.Value) interface{} { + cb = js.FuncOf(func(this js.Value, args []js.Value) any { fmt.Println("button clicked") cb.Release() // release the function if the button will not be clicked again return nil @@ -593,7 +593,7 @@ func BenchmarkDOM(b *testing.B) { } func TestGlobal(t *testing.T) { - ident := js.FuncOf(func(this js.Value, args []js.Value) interface{} { + ident := js.FuncOf(func(this js.Value, args []js.Value) any { return args[0] }) defer ident.Release() diff --git a/src/syscall/net_js.go b/src/syscall/net_js.go index 253ab22dd9..2ed4e191bd 100644 --- a/src/syscall/net_js.go +++ b/src/syscall/net_js.go @@ -45,8 +45,7 @@ const ( SYS_FCNTL = 500 // unsupported ) -type Sockaddr interface { -} +type Sockaddr any type SockaddrInet4 struct { Port int diff --git a/src/syscall/syscall_windows.go b/src/syscall/syscall_windows.go index ecb1eeecf6..78e46a656d 100644 --- a/src/syscall/syscall_windows.go +++ b/src/syscall/syscall_windows.go @@ -169,7 +169,7 @@ func (e Errno) Timeout() bool { } // Implemented in runtime/syscall_windows.go. -func compileCallback(fn interface{}, cleanstack bool) uintptr +func compileCallback(fn any, cleanstack bool) uintptr // NewCallback converts a Go function to a function pointer conforming to the stdcall calling convention. // This is useful when interoperating with Windows code requiring callbacks. @@ -177,7 +177,7 @@ func compileCallback(fn interface{}, cleanstack bool) uintptr // Only a limited number of callbacks may be created in a single Go process, and any memory allocated // for these callbacks is never released. // Between NewCallback and NewCallbackCDecl, at least 1024 callbacks can always be created. -func NewCallback(fn interface{}) uintptr { +func NewCallback(fn any) uintptr { return compileCallback(fn, true) } @@ -187,7 +187,7 @@ func NewCallback(fn interface{}) uintptr { // Only a limited number of callbacks may be created in a single Go process, and any memory allocated // for these callbacks is never released. // Between NewCallback and NewCallbackCDecl, at least 1024 callbacks can always be created. -func NewCallbackCDecl(fn interface{}) uintptr { +func NewCallbackCDecl(fn any) uintptr { return compileCallback(fn, false) } diff --git a/src/testing/allocs_test.go b/src/testing/allocs_test.go index 5b346aaf83..bbd3ae79c8 100644 --- a/src/testing/allocs_test.go +++ b/src/testing/allocs_test.go @@ -6,7 +6,7 @@ package testing_test import "testing" -var global interface{} +var global any var allocsPerRunTests = []struct { name string diff --git a/src/testing/example.go b/src/testing/example.go index 0217c5d242..f33e8d2f92 100644 --- a/src/testing/example.go +++ b/src/testing/example.go @@ -64,7 +64,7 @@ func sortLines(output string) string { // If recovered is non-nil, it'll panic with that value. // If the test panicked with nil, or invoked runtime.Goexit, it'll be // made to fail and panic with errNilPanicOrGoexit -func (eg *InternalExample) processRunResult(stdout string, timeSpent time.Duration, finished bool, recovered interface{}) (passed bool) { +func (eg *InternalExample) processRunResult(stdout string, timeSpent time.Duration, finished bool, recovered any) (passed bool) { passed = true dstr := fmtDuration(timeSpent) var fail string diff --git a/src/testing/fstest/mapfs.go b/src/testing/fstest/mapfs.go index 056ef133fa..4595b7313d 100644 --- a/src/testing/fstest/mapfs.go +++ b/src/testing/fstest/mapfs.go @@ -37,7 +37,7 @@ type MapFile struct { Data []byte // file content Mode fs.FileMode // FileInfo.Mode ModTime time.Time // FileInfo.ModTime - Sys interface{} // FileInfo.Sys + Sys any // FileInfo.Sys } var _ fs.FS = MapFS(nil) @@ -156,7 +156,7 @@ func (i *mapFileInfo) Mode() fs.FileMode { return i.f.Mode } func (i *mapFileInfo) Type() fs.FileMode { return i.f.Mode.Type() } func (i *mapFileInfo) ModTime() time.Time { return i.f.ModTime } func (i *mapFileInfo) IsDir() bool { return i.f.Mode&fs.ModeDir != 0 } -func (i *mapFileInfo) Sys() interface{} { return i.f.Sys } +func (i *mapFileInfo) Sys() any { return i.f.Sys } func (i *mapFileInfo) Info() (fs.FileInfo, error) { return i, nil } // An openMapFile is a regular (non-directory) fs.File open for reading. diff --git a/src/testing/fstest/testfs.go b/src/testing/fstest/testfs.go index 5c4f30af16..9a65fbbd0b 100644 --- a/src/testing/fstest/testfs.go +++ b/src/testing/fstest/testfs.go @@ -105,7 +105,7 @@ type fsTester struct { } // errorf adds an error line to errText. -func (t *fsTester) errorf(format string, args ...interface{}) { +func (t *fsTester) errorf(format string, args ...any) { if len(t.errText) > 0 { t.errText = append(t.errText, '\n') } diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 19ff39947b..18f2b2f319 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -91,7 +91,7 @@ type corpusEntry = struct { Parent string Path string Data []byte - Values []interface{} + Values []any Generation int IsSeed bool } @@ -149,8 +149,8 @@ func (f *F) Skipped() bool { // Add will add the arguments to the seed corpus for the fuzz test. This will be // a no-op if called after or within the fuzz target, and args must match the // arguments for the fuzz target. -func (f *F) Add(args ...interface{}) { - var values []interface{} +func (f *F) Add(args ...any) { + var values []any for i := range args { if t := reflect.TypeOf(args[i]); !supportedTypes[t] { panic(fmt.Sprintf("testing: unsupported type to Add %v", t)) @@ -207,7 +207,7 @@ var supportedTypes = map[reflect.Type]bool{ // When fuzzing, F.Fuzz does not return until a problem is found, time runs out // (set with -fuzztime), or the test process is interrupted by a signal. F.Fuzz // should be called exactly once, unless F.Skip or F.Fail is called beforehand. -func (f *F) Fuzz(ff interface{}) { +func (f *F) Fuzz(ff any) { if f.fuzzCalled { panic("testing: F.Fuzz called more than once") } @@ -638,7 +638,7 @@ func fRunner(f *F, fn func(*F)) { // If we recovered a panic or inappropriate runtime.Goexit, fail the test, // flush the output log up to the root, then panic. - doPanic := func(err interface{}) { + doPanic := func(err any) { f.Fail() if r := f.runCleanup(recoverAndReturnPanic); r != nil { f.Logf("cleanup panicked with %v", r) diff --git a/src/testing/internal/testdeps/deps.go b/src/testing/internal/testdeps/deps.go index c612355a00..2e85a41b07 100644 --- a/src/testing/internal/testdeps/deps.go +++ b/src/testing/internal/testdeps/deps.go @@ -186,7 +186,7 @@ func (TestDeps) ReadCorpus(dir string, types []reflect.Type) ([]fuzz.CorpusEntry return fuzz.ReadCorpus(dir, types) } -func (TestDeps) CheckCorpus(vals []interface{}, types []reflect.Type) error { +func (TestDeps) CheckCorpus(vals []any, types []reflect.Type) error { return fuzz.CheckCorpus(vals, types) } diff --git a/src/testing/quick/quick.go b/src/testing/quick/quick.go index 777338bb37..e73d307c13 100644 --- a/src/testing/quick/quick.go +++ b/src/testing/quick/quick.go @@ -227,7 +227,7 @@ func (s SetupError) Error() string { return string(s) } // A CheckError is the result of Check finding an error. type CheckError struct { Count int - In []interface{} + In []any } func (s *CheckError) Error() string { @@ -237,8 +237,8 @@ func (s *CheckError) Error() string { // A CheckEqualError is the result CheckEqual finding an error. type CheckEqualError struct { CheckError - Out1 []interface{} - Out2 []interface{} + Out1 []any + Out2 []any } func (s *CheckEqualError) Error() string { @@ -260,7 +260,7 @@ func (s *CheckEqualError) Error() string { // t.Error(err) // } // } -func Check(f interface{}, config *Config) error { +func Check(f any, config *Config) error { if config == nil { config = &defaultConfig } @@ -299,7 +299,7 @@ func Check(f interface{}, config *Config) error { // It calls f and g repeatedly with arbitrary values for each argument. // If f and g return different answers, CheckEqual returns a *CheckEqualError // describing the input and the outputs. -func CheckEqual(f, g interface{}, config *Config) error { +func CheckEqual(f, g any, config *Config) error { if config == nil { config = &defaultConfig } @@ -358,7 +358,7 @@ func arbitraryValues(args []reflect.Value, f reflect.Type, config *Config, rand return } -func functionAndType(f interface{}) (v reflect.Value, t reflect.Type, ok bool) { +func functionAndType(f any) (v reflect.Value, t reflect.Type, ok bool) { v = reflect.ValueOf(f) ok = v.Kind() == reflect.Func if !ok { @@ -368,15 +368,15 @@ func functionAndType(f interface{}) (v reflect.Value, t reflect.Type, ok bool) { return } -func toInterfaces(values []reflect.Value) []interface{} { - ret := make([]interface{}, len(values)) +func toInterfaces(values []reflect.Value) []any { + ret := make([]any, len(values)) for i, v := range values { ret[i] = v.Interface() } return ret } -func toString(interfaces []interface{}) string { +func toString(interfaces []any) string { s := make([]string, len(interfaces)) for i, v := range interfaces { s[i] = fmt.Sprintf("%#v", v) diff --git a/src/testing/testing.go b/src/testing/testing.go index e4b7aa30e5..7bd13a850c 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -453,7 +453,7 @@ func newChattyPrinter(w io.Writer) *chattyPrinter { // Updatef prints a message about the status of the named test to w. // // The formatted message must include the test name itself. -func (p *chattyPrinter) Updatef(testName, format string, args ...interface{}) { +func (p *chattyPrinter) Updatef(testName, format string, args ...any) { p.lastNameMu.Lock() defer p.lastNameMu.Unlock() @@ -467,7 +467,7 @@ func (p *chattyPrinter) Updatef(testName, format string, args ...interface{}) { // Printf prints a message, generated by the named test, that does not // necessarily mention that tests's name itself. -func (p *chattyPrinter) Printf(testName, format string, args ...interface{}) { +func (p *chattyPrinter) Printf(testName, format string, args ...any) { p.lastNameMu.Lock() defer p.lastNameMu.Unlock() @@ -680,7 +680,7 @@ func (c *common) decorate(s string, skip int) string { // flushToParent writes c.output to the parent after first writing the header // with the given format and arguments. -func (c *common) flushToParent(testName, format string, args ...interface{}) { +func (c *common) flushToParent(testName, format string, args ...any) { p := c.parent p.mu.Lock() defer p.mu.Unlock() @@ -743,21 +743,21 @@ func fmtDuration(d time.Duration) string { // TB is the interface common to T, B, and F. type TB interface { Cleanup(func()) - Error(args ...interface{}) - Errorf(format string, args ...interface{}) + Error(args ...any) + Errorf(format string, args ...any) Fail() FailNow() Failed() bool - Fatal(args ...interface{}) - Fatalf(format string, args ...interface{}) + Fatal(args ...any) + Fatalf(format string, args ...any) Helper() - Log(args ...interface{}) - Logf(format string, args ...interface{}) + Log(args ...any) + Logf(format string, args ...any) Name() string Setenv(key, value string) - Skip(args ...interface{}) + Skip(args ...any) SkipNow() - Skipf(format string, args ...interface{}) + Skipf(format string, args ...any) Skipped() bool TempDir() string @@ -906,7 +906,7 @@ func (c *common) logDepth(s string, depth int) { // and records the text in the error log. For tests, the text will be printed only if // the test fails or the -test.v flag is set. For benchmarks, the text is always // printed to avoid having performance depend on the value of the -test.v flag. -func (c *common) Log(args ...interface{}) { +func (c *common) Log(args ...any) { c.checkFuzzFn("Log") c.log(fmt.Sprintln(args...)) } @@ -916,48 +916,48 @@ func (c *common) Log(args ...interface{}) { // tests, the text will be printed only if the test fails or the -test.v flag is // set. For benchmarks, the text is always printed to avoid having performance // depend on the value of the -test.v flag. -func (c *common) Logf(format string, args ...interface{}) { +func (c *common) Logf(format string, args ...any) { c.checkFuzzFn("Logf") c.log(fmt.Sprintf(format, args...)) } // Error is equivalent to Log followed by Fail. -func (c *common) Error(args ...interface{}) { +func (c *common) Error(args ...any) { c.checkFuzzFn("Error") c.log(fmt.Sprintln(args...)) c.Fail() } // Errorf is equivalent to Logf followed by Fail. -func (c *common) Errorf(format string, args ...interface{}) { +func (c *common) Errorf(format string, args ...any) { c.checkFuzzFn("Errorf") c.log(fmt.Sprintf(format, args...)) c.Fail() } // Fatal is equivalent to Log followed by FailNow. -func (c *common) Fatal(args ...interface{}) { +func (c *common) Fatal(args ...any) { c.checkFuzzFn("Fatal") c.log(fmt.Sprintln(args...)) c.FailNow() } // Fatalf is equivalent to Logf followed by FailNow. -func (c *common) Fatalf(format string, args ...interface{}) { +func (c *common) Fatalf(format string, args ...any) { c.checkFuzzFn("Fatalf") c.log(fmt.Sprintf(format, args...)) c.FailNow() } // Skip is equivalent to Log followed by SkipNow. -func (c *common) Skip(args ...interface{}) { +func (c *common) Skip(args ...any) { c.checkFuzzFn("Skip") c.log(fmt.Sprintln(args...)) c.SkipNow() } // Skipf is equivalent to Logf followed by SkipNow. -func (c *common) Skipf(format string, args ...interface{}) { +func (c *common) Skipf(format string, args ...any) { c.checkFuzzFn("Skipf") c.log(fmt.Sprintf(format, args...)) c.SkipNow() @@ -1141,7 +1141,7 @@ const ( // runCleanup is called at the end of the test. // If catchPanic is true, this will catch panics, and return the recovered // value if any. -func (c *common) runCleanup(ph panicHandling) (panicVal interface{}) { +func (c *common) runCleanup(ph panicHandling) (panicVal any) { if ph == recoverAndReturnPanic { defer func() { panicVal = recover() @@ -1340,7 +1340,7 @@ func tRunner(t *T, fn func(t *T)) { t.signal <- signal }() - doPanic := func(err interface{}) { + doPanic := func(err any) { t.Fail() if r := t.runCleanup(recoverAndReturnPanic); r != nil { t.Logf("cleanup panicked with %v", r) @@ -1554,9 +1554,9 @@ func (f matchStringOnly) RunFuzzWorker(func(corpusEntry) error) error { return e func (f matchStringOnly) ReadCorpus(string, []reflect.Type) ([]corpusEntry, error) { return nil, errMain } -func (f matchStringOnly) CheckCorpus([]interface{}, []reflect.Type) error { return nil } -func (f matchStringOnly) ResetCoverage() {} -func (f matchStringOnly) SnapshotCoverage() {} +func (f matchStringOnly) CheckCorpus([]any, []reflect.Type) error { return nil } +func (f matchStringOnly) ResetCoverage() {} +func (f matchStringOnly) SnapshotCoverage() {} // Main is an internal function, part of the implementation of the "go test" command. // It was exported because it is cross-package and predates "internal" packages. @@ -1602,7 +1602,7 @@ type testDeps interface { CoordinateFuzzing(time.Duration, int64, time.Duration, int64, int, []corpusEntry, []reflect.Type, string, string) error RunFuzzWorker(func(corpusEntry) error) error ReadCorpus(string, []reflect.Type) ([]corpusEntry, error) - CheckCorpus([]interface{}, []reflect.Type) error + CheckCorpus([]any, []reflect.Type) error ResetCoverage() SnapshotCoverage() } diff --git a/src/text/scanner/scanner.go b/src/text/scanner/scanner.go index c5fc4ff93b..f1fbf9861d 100644 --- a/src/text/scanner/scanner.go +++ b/src/text/scanner/scanner.go @@ -340,7 +340,7 @@ func (s *Scanner) error(msg string) { fmt.Fprintf(os.Stderr, "%s: %s\n", pos, msg) } -func (s *Scanner) errorf(format string, args ...interface{}) { +func (s *Scanner) errorf(format string, args ...any) { s.error(fmt.Sprintf(format, args...)) } diff --git a/src/text/template/exec.go b/src/text/template/exec.go index c42cbb2ad3..37984cf91a 100644 --- a/src/text/template/exec.go +++ b/src/text/template/exec.go @@ -126,7 +126,7 @@ func (e ExecError) Unwrap() error { } // errorf records an ExecError and terminates processing. -func (s *state) errorf(format string, args ...interface{}) { +func (s *state) errorf(format string, args ...any) { name := doublePercent(s.tmpl.Name()) if s.node == nil { format = fmt.Sprintf("template: %s: %s", name, format) @@ -179,7 +179,7 @@ func errRecover(errp *error) { // the output writer. // A template may be executed safely in parallel, although if parallel // executions share a Writer the output may be interleaved. -func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error { +func (t *Template) ExecuteTemplate(wr io.Writer, name string, data any) error { tmpl := t.Lookup(name) if tmpl == nil { return fmt.Errorf("template: no template %q associated with template %q", name, t.name) @@ -197,11 +197,11 @@ func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) // // If data is a reflect.Value, the template applies to the concrete // value that the reflect.Value holds, as in fmt.Print. -func (t *Template) Execute(wr io.Writer, data interface{}) error { +func (t *Template) Execute(wr io.Writer, data any) error { return t.execute(wr, data) } -func (t *Template) execute(wr io.Writer, data interface{}) (err error) { +func (t *Template) execute(wr io.Writer, data any) (err error) { defer errRecover(&err) value, ok := data.(reflect.Value) if !ok { @@ -311,7 +311,7 @@ func (s *state) walkIfOrWith(typ parse.NodeType, dot reflect.Value, pipe *parse. // IsTrue reports whether the value is 'true', in the sense of not the zero of its type, // and whether the value has a meaningful truth value. This is the definition of // truth used by if and other such actions. -func IsTrue(val interface{}) (truth, ok bool) { +func IsTrue(val any) (truth, ok bool) { return isTrue(reflect.ValueOf(val)) } @@ -1023,7 +1023,7 @@ func (s *state) printValue(n parse.Node, v reflect.Value) { // printableValue returns the, possibly indirected, interface value inside v that // is best for a call to formatted printer. -func printableValue(v reflect.Value) (interface{}, bool) { +func printableValue(v reflect.Value) (any, bool) { if v.Kind() == reflect.Pointer { v, _ = indirect(v) // fmt.Fprint handles nil. } diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go index 3c40aa901e..8c8143396d 100644 --- a/src/text/template/exec_test.go +++ b/src/text/template/exec_test.go @@ -46,7 +46,7 @@ type T struct { MSI map[string]int MSIone map[string]int // one element, for deterministic output MSIEmpty map[string]int - MXI map[interface{}]int + MXI map[any]int MII map[int]int MI32S map[int32]string MI64S map[int64]string @@ -56,11 +56,11 @@ type T struct { MUI8S map[uint8]string SMSI []map[string]int // Empty interfaces; used to see if we can dig inside one. - Empty0 interface{} // nil - Empty1 interface{} - Empty2 interface{} - Empty3 interface{} - Empty4 interface{} + Empty0 any // nil + Empty1 any + Empty2 any + Empty3 any + Empty4 any // Non-empty interfaces. NonEmptyInterface I NonEmptyInterfacePtS *I @@ -138,7 +138,7 @@ var tVal = &T{ SB: []bool{true, false}, MSI: map[string]int{"one": 1, "two": 2, "three": 3}, MSIone: map[string]int{"one": 1}, - MXI: map[interface{}]int{"one": 1}, + MXI: map[any]int{"one": 1}, MII: map[int]int{1: 1}, MI32S: map[int32]string{1: "one", 2: "two"}, MI64S: map[int64]string{2: "i642", 3: "i643"}, @@ -209,7 +209,7 @@ func (t *T) Method2(a uint16, b string) string { return fmt.Sprintf("Method2: %d %s", a, b) } -func (t *T) Method3(v interface{}) string { +func (t *T) Method3(v any) string { return fmt.Sprintf("Method3: %v", v) } @@ -249,7 +249,7 @@ func (u *U) TrueFalse(b bool) string { return "" } -func typeOf(arg interface{}) string { +func typeOf(arg any) string { return fmt.Sprintf("%T", arg) } @@ -257,7 +257,7 @@ type execTest struct { name string input string output string - data interface{} + data any ok bool } @@ -390,7 +390,7 @@ var execTests = []execTest{ {".VariadicFuncInt", "{{call .VariadicFuncInt 33 `he` `llo`}}", "33=", tVal, true}, {"if .BinaryFunc call", "{{ if .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{end}}", "[1=2]", tVal, true}, {"if not .BinaryFunc call", "{{ if not .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{else}}No{{end}}", "No", tVal, true}, - {"Interface Call", `{{stringer .S}}`, "foozle", map[string]interface{}{"S": bytes.NewBufferString("foozle")}, true}, + {"Interface Call", `{{stringer .S}}`, "foozle", map[string]any{"S": bytes.NewBufferString("foozle")}, true}, {".ErrFunc", "{{call .ErrFunc}}", "bla", tVal, true}, {"call nil", "{{call nil}}", "", tVal, false}, @@ -748,7 +748,7 @@ func add(args ...int) int { return sum } -func echo(arg interface{}) interface{} { +func echo(arg any) any { return arg } @@ -767,7 +767,7 @@ func stringer(s fmt.Stringer) string { return s.String() } -func mapOfThree() interface{} { +func mapOfThree() any { return map[string]int{"three": 3} } @@ -1468,7 +1468,7 @@ func TestBlock(t *testing.T) { func TestEvalFieldErrors(t *testing.T) { tests := []struct { name, src string - value interface{} + value any want string }{ { @@ -1611,7 +1611,7 @@ func TestInterfaceValues(t *testing.T) { for _, tt := range tests { tmpl := Must(New("tmpl").Parse(tt.text)) var buf bytes.Buffer - err := tmpl.Execute(&buf, map[string]interface{}{ + err := tmpl.Execute(&buf, map[string]any{ "PlusOne": func(n int) int { return n + 1 }, @@ -1640,7 +1640,7 @@ func TestInterfaceValues(t *testing.T) { // Check that panics during calls are recovered and returned as errors. func TestExecutePanicDuringCall(t *testing.T) { - funcs := map[string]interface{}{ + funcs := map[string]any{ "doPanic": func() string { panic("custom panic string") }, @@ -1648,7 +1648,7 @@ func TestExecutePanicDuringCall(t *testing.T) { tests := []struct { name string input string - data interface{} + data any wantErr string }{ { diff --git a/src/text/template/funcs.go b/src/text/template/funcs.go index 11e2e903c8..dca5ed28db 100644 --- a/src/text/template/funcs.go +++ b/src/text/template/funcs.go @@ -31,7 +31,7 @@ import ( // apply to arguments of arbitrary type can use parameters of type interface{} or // of type reflect.Value. Similarly, functions meant to return a result of arbitrary // type can return interface{} or reflect.Value. -type FuncMap map[string]interface{} +type FuncMap map[string]any // builtins returns the FuncMap. // It is not a global variable so the linker can dead code eliminate @@ -627,7 +627,7 @@ func HTMLEscapeString(s string) string { // HTMLEscaper returns the escaped HTML equivalent of the textual // representation of its arguments. -func HTMLEscaper(args ...interface{}) string { +func HTMLEscaper(args ...any) string { return HTMLEscapeString(evalArgs(args)) } @@ -718,13 +718,13 @@ func jsIsSpecial(r rune) bool { // JSEscaper returns the escaped JavaScript equivalent of the textual // representation of its arguments. -func JSEscaper(args ...interface{}) string { +func JSEscaper(args ...any) string { return JSEscapeString(evalArgs(args)) } // URLQueryEscaper returns the escaped value of the textual representation of // its arguments in a form suitable for embedding in a URL query. -func URLQueryEscaper(args ...interface{}) string { +func URLQueryEscaper(args ...any) string { return url.QueryEscape(evalArgs(args)) } @@ -733,7 +733,7 @@ func URLQueryEscaper(args ...interface{}) string { // except that each argument is indirected (if a pointer), as required, // using the same rules as the default string evaluation during template // execution. -func evalArgs(args []interface{}) string { +func evalArgs(args []any) string { ok := false var s string // Fast path for simple common case. diff --git a/src/text/template/parse/lex.go b/src/text/template/parse/lex.go index 95e33771c0..40d0411121 100644 --- a/src/text/template/parse/lex.go +++ b/src/text/template/parse/lex.go @@ -190,7 +190,7 @@ func (l *lexer) acceptRun(valid string) { // errorf returns an error token and terminates the scan by passing // back a nil pointer that will be the next state, terminating l.nextItem. -func (l *lexer) errorf(format string, args ...interface{}) stateFn { +func (l *lexer) errorf(format string, args ...any) stateFn { l.items <- item{itemError, l.start, fmt.Sprintf(format, args...), l.startLine} return nil } diff --git a/src/text/template/parse/parse.go b/src/text/template/parse/parse.go index 64b29a2e16..b0cbe9dfc8 100644 --- a/src/text/template/parse/parse.go +++ b/src/text/template/parse/parse.go @@ -24,7 +24,7 @@ type Tree struct { Mode Mode // parsing mode. text string // text parsed to create the template (or its parent) // Parsing only; cleared after parse. - funcs []map[string]interface{} + funcs []map[string]any lex *lexer token [3]item // three-token lookahead for parser. peekCount int @@ -59,7 +59,7 @@ func (t *Tree) Copy() *Tree { // templates described in the argument string. The top-level template will be // given the specified name. If an error is encountered, parsing stops and an // empty map is returned with the error. -func Parse(name, text, leftDelim, rightDelim string, funcs ...map[string]interface{}) (map[string]*Tree, error) { +func Parse(name, text, leftDelim, rightDelim string, funcs ...map[string]any) (map[string]*Tree, error) { treeSet := make(map[string]*Tree) t := New(name) t.text = text @@ -128,7 +128,7 @@ func (t *Tree) peekNonSpace() item { // Parsing. // New allocates a new parse tree with the given name. -func New(name string, funcs ...map[string]interface{}) *Tree { +func New(name string, funcs ...map[string]any) *Tree { return &Tree{ Name: name, funcs: funcs, @@ -158,7 +158,7 @@ func (t *Tree) ErrorContext(n Node) (location, context string) { } // errorf formats the error and terminates processing. -func (t *Tree) errorf(format string, args ...interface{}) { +func (t *Tree) errorf(format string, args ...any) { t.Root = nil format = fmt.Sprintf("template: %s:%d: %s", t.ParseName, t.token[0].line, format) panic(fmt.Errorf(format, args...)) @@ -218,7 +218,7 @@ func (t *Tree) recover(errp *error) { } // startParse initializes the parser, using the lexer. -func (t *Tree) startParse(funcs []map[string]interface{}, lex *lexer, treeSet map[string]*Tree) { +func (t *Tree) startParse(funcs []map[string]any, lex *lexer, treeSet map[string]*Tree) { t.Root = nil t.lex = lex t.vars = []string{"$"} @@ -240,7 +240,7 @@ func (t *Tree) stopParse() { // the template for execution. If either action delimiter string is empty, the // default ("{{" or "}}") is used. Embedded template definitions are added to // the treeSet map. -func (t *Tree) Parse(text, leftDelim, rightDelim string, treeSet map[string]*Tree, funcs ...map[string]interface{}) (tree *Tree, err error) { +func (t *Tree) Parse(text, leftDelim, rightDelim string, treeSet map[string]*Tree, funcs ...map[string]any) (tree *Tree, err error) { defer t.recover(&err) t.ParseName = t.Name emitComment := t.Mode&ParseComments != 0 diff --git a/src/text/template/parse/parse_test.go b/src/text/template/parse/parse_test.go index c3679a08de..0c4778c7b3 100644 --- a/src/text/template/parse/parse_test.go +++ b/src/text/template/parse/parse_test.go @@ -318,7 +318,7 @@ var parseTests = []parseTest{ {"block definition", `{{block "foo"}}hello{{end}}`, hasError, ""}, } -var builtins = map[string]interface{}{ +var builtins = map[string]any{ "printf": fmt.Sprintf, "contains": strings.Contains, } diff --git a/src/time/internal_test.go b/src/time/internal_test.go index 2c75e449d3..f0dddb7373 100644 --- a/src/time/internal_test.go +++ b/src/time/internal_test.go @@ -31,7 +31,7 @@ func forceZipFileForTesting(zipOnly bool) { var Interrupt = interrupt var DaysIn = daysIn -func empty(arg interface{}, seq uintptr) {} +func empty(arg any, seq uintptr) {} // Test that a runtimeTimer with a period that would overflow when on // expiration does not throw or cause other timers to hang. diff --git a/src/time/sleep.go b/src/time/sleep.go index b467d1d589..1ffaabec67 100644 --- a/src/time/sleep.go +++ b/src/time/sleep.go @@ -14,8 +14,8 @@ type runtimeTimer struct { pp uintptr when int64 period int64 - f func(interface{}, uintptr) // NOTE: must not be closure - arg interface{} + f func(any, uintptr) // NOTE: must not be closure + arg any seq uintptr nextwhen int64 status uint32 @@ -41,7 +41,7 @@ func when(d Duration) int64 { func startTimer(*runtimeTimer) func stopTimer(*runtimeTimer) bool func resetTimer(*runtimeTimer, int64) bool -func modTimer(t *runtimeTimer, when, period int64, f func(interface{}, uintptr), arg interface{}, seq uintptr) +func modTimer(t *runtimeTimer, when, period int64, f func(any, uintptr), arg any, seq uintptr) // The Timer type represents a single event. // When the Timer expires, the current time will be sent on C, @@ -140,7 +140,7 @@ func (t *Timer) Reset(d Duration) bool { } // sendTime does a non-blocking send of the current time on c. -func sendTime(c interface{}, seq uintptr) { +func sendTime(c any, seq uintptr) { select { case c.(chan Time) <- Now(): default: @@ -172,6 +172,6 @@ func AfterFunc(d Duration, f func()) *Timer { return t } -func goFunc(arg interface{}, seq uintptr) { +func goFunc(arg any, seq uintptr) { go arg.(func())() } diff --git a/src/time/tzdata/generate_zipdata.go b/src/time/tzdata/generate_zipdata.go index 4f40b51c73..653577cafa 100644 --- a/src/time/tzdata/generate_zipdata.go +++ b/src/time/tzdata/generate_zipdata.go @@ -71,7 +71,7 @@ func main() { } } -func die(format string, args ...interface{}) { +func die(format string, args ...any) { fmt.Fprintf(os.Stderr, format+"\n", args...) os.Exit(1) } -- GitLab From f909f813a0c12fde089a6c5e18fdcb9e71759cf7 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Fri, 10 Dec 2021 14:03:20 -0500 Subject: [PATCH 2490/2500] testing: update docs for fuzzcachedir Although most of the code seems to be already implemented to support this for general use, it didn't make it in for Go 1.18, so for now we should at least document that it's only for use by the go command. Change-Id: Id559e72d590aedeaaa50bcf880bca1a385d858dd Reviewed-on: https://go-review.googlesource.com/c/go/+/370954 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Gopher Robot Reviewed-by: Bryan Mills --- src/testing/fuzz.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index 18f2b2f319..4a5def1ab4 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -22,8 +22,9 @@ func initFuzzFlags() { matchFuzz = flag.String("test.fuzz", "", "run the fuzz test matching `regexp`") flag.Var(&fuzzDuration, "test.fuzztime", "time to spend fuzzing; default is to run indefinitely") flag.Var(&minimizeDuration, "test.fuzzminimizetime", "time to spend minimizing a value after finding a failing input") - fuzzCacheDir = flag.String("test.fuzzcachedir", "", "directory where interesting fuzzing inputs are stored") - isFuzzWorker = flag.Bool("test.fuzzworker", false, "coordinate with the parent process to fuzz random values") + + fuzzCacheDir = flag.String("test.fuzzcachedir", "", "directory where interesting fuzzing inputs are stored (for use only by cmd/go)") + isFuzzWorker = flag.Bool("test.fuzzworker", false, "coordinate with the parent process to fuzz random values (for use only by cmd/go)") } var ( -- GitLab From 3e8aa5dd495d30ff29cd4fb78aabe8fc0ebb1eda Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Mon, 13 Dec 2021 12:03:13 -0500 Subject: [PATCH 2491/2500] cmd/compile/internal/amd64: fix for coverage testing Fix up a unit test to make it more friendly for coverage runs. Currently on tip if you do cd ${GOROOT}/src ; go test -cover cmd/compile/... it will cause a failure in the TestGoAMD64v1 testpoint of cmd/compile/internal/amd64, the reason being that this testpoint copies and reruns the test executable, expecting the rerun to produce only the output "PASS", whereas if "-cover" is used, the output will include percentage of statements covered as well. To fix, rework the test to tolerate additional output if coverage is enabled. Change-Id: I2512e06ca06e5f38108f2891ff84276d148c4f9e Reviewed-on: https://go-review.googlesource.com/c/go/+/371234 Reviewed-by: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Gopher Robot Reviewed-by: Cherry Mui --- src/cmd/compile/internal/amd64/versions_test.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/amd64/versions_test.go b/src/cmd/compile/internal/amd64/versions_test.go index ee1a8ca3aa..7aa697b811 100644 --- a/src/cmd/compile/internal/amd64/versions_test.go +++ b/src/cmd/compile/internal/amd64/versions_test.go @@ -74,8 +74,18 @@ func TestGoAMD64v1(t *testing.T) { if err != nil { t.Fatalf("couldn't execute test: %s", err) } - if string(out) != "PASS\n" { - t.Fatalf("test reported error: %s", string(out)) + // Expect to see output of the form "PASS\n", unless the test binary + // was compiled for coverage (in which case there will be an extra line). + success := false + lines := strings.Split(string(out), "\n") + if len(lines) == 2 { + success = lines[0] == "PASS" && lines[1] == "" + } else if len(lines) == 3 { + success = lines[0] == "PASS" && + strings.HasPrefix(lines[1], "coverage") && lines[2] == "" + } + if !success { + t.Fatalf("test reported error: %s lines=%+v", string(out), lines) } } -- GitLab From 7bdbc73be1d10a9b32cb5edc6b9d0c93805f059c Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Fri, 10 Dec 2021 14:25:55 -0500 Subject: [PATCH 2492/2500] cmd/go: document -fuzzminimizetime Change-Id: I435942ff7285d32ffbc8901d9d7e76544d5aeb61 Reviewed-on: https://go-review.googlesource.com/c/go/+/370881 Trust: Katie Hockman Run-TryBot: Katie Hockman Reviewed-by: Bryan Mills TryBot-Result: Gopher Robot --- src/cmd/go/alldocs.go | 18 +++++++++++++----- src/cmd/go/internal/test/test.go | 18 +++++++++++++----- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index f9a2b59c05..6703792054 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -2861,11 +2861,19 @@ // section of the testing package documentation for details. // // -fuzztime t -// Run enough iterations of the fuzz test to take t, specified as a -// time.Duration (for example, -fuzztime 1h30s). The default is to run -// forever. -// The special syntax Nx means to run the fuzz test N times -// (for example, -fuzztime 100x). +// Run enough iterations of the fuzz target during fuzzing to take t, +// specified as a time.Duration (for example, -fuzztime 1h30s). +// The default is to run forever. +// The special syntax Nx means to run the fuzz target N times +// (for example, -fuzztime 1000x). +// +// -fuzzminimizetime t +// Run enough iterations of the fuzz target during each minimization +// attempt to take t, as specified as a time.Duration (for example, +// -fuzzminimizetime 30s). +// The default is 60s. +// The special syntax Nx means to run the fuzz target N times +// (for example, -fuzzminimizetime 100x). // // -json // Log verbose output and test results in JSON. This presents the diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 7ea9d4f1f1..50e6d5201b 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -257,11 +257,19 @@ control the execution of any test: section of the testing package documentation for details. -fuzztime t - Run enough iterations of the fuzz test to take t, specified as a - time.Duration (for example, -fuzztime 1h30s). The default is to run - forever. - The special syntax Nx means to run the fuzz test N times - (for example, -fuzztime 100x). + Run enough iterations of the fuzz target during fuzzing to take t, + specified as a time.Duration (for example, -fuzztime 1h30s). + The default is to run forever. + The special syntax Nx means to run the fuzz target N times + (for example, -fuzztime 1000x). + + -fuzzminimizetime t + Run enough iterations of the fuzz target during each minimization + attempt to take t, as specified as a time.Duration (for example, + -fuzzminimizetime 30s). + The default is 60s. + The special syntax Nx means to run the fuzz target N times + (for example, -fuzzminimizetime 100x). -json Log verbose output and test results in JSON. This presents the -- GitLab From 9e85dc5f183d688f5297203dd76f281a6d87d94f Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 13 Dec 2021 16:12:50 -0500 Subject: [PATCH 2493/2500] net/http: revert h2_bundle.go formatting change from CL 368254 h2_bundle.go is automatically generated from x/net/http2. Any formatting changes within that file need to be first made upstream. This brings the contents of h2_bundle.go back in line with the upstream generator, fixing the cmd/internal/moddeps test that is currently failing on the longtest builders. For #49884 Change-Id: I5757240b77e250e0026b8a52a0e867e1578ec2d4 Reviewed-on: https://go-review.googlesource.com/c/go/+/371297 Trust: Bryan Mills Run-TryBot: Bryan Mills Reviewed-by: David Chase TryBot-Result: Gopher Robot --- src/net/http/h2_bundle.go | 52 +++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go index 83b6d29144..bb82f24585 100644 --- a/src/net/http/h2_bundle.go +++ b/src/net/http/h2_bundle.go @@ -1049,11 +1049,11 @@ var ( 16 << 10, } http2dataChunkPools = [...]sync.Pool{ - {New: func() any { return make([]byte, 1<<10) }}, - {New: func() any { return make([]byte, 2<<10) }}, - {New: func() any { return make([]byte, 4<<10) }}, - {New: func() any { return make([]byte, 8<<10) }}, - {New: func() any { return make([]byte, 16<<10) }}, + {New: func() interface{} { return make([]byte, 1<<10) }}, + {New: func() interface{} { return make([]byte, 2<<10) }}, + {New: func() interface{} { return make([]byte, 4<<10) }}, + {New: func() interface{} { return make([]byte, 8<<10) }}, + {New: func() interface{} { return make([]byte, 16<<10) }}, } ) @@ -1548,7 +1548,7 @@ func (h *http2FrameHeader) invalidate() { h.valid = false } // frame header bytes. // Used only by ReadFrameHeader. var http2fhBytes = sync.Pool{ - New: func() any { + New: func() interface{} { buf := make([]byte, http2frameHeaderLen) return &buf }, @@ -1655,8 +1655,8 @@ type http2Framer struct { debugFramer *http2Framer // only use for logging written writes debugFramerBuf *bytes.Buffer - debugReadLoggerf func(string, ...any) - debugWriteLoggerf func(string, ...any) + debugReadLoggerf func(string, ...interface{}) + debugWriteLoggerf func(string, ...interface{}) frameCache *http2frameCache // nil if frames aren't reused (default) } @@ -3061,7 +3061,7 @@ func http2curGoroutineID() uint64 { } var http2littleBuf = sync.Pool{ - New: func() any { + New: func() interface{} { buf := make([]byte, 64) return &buf }, @@ -3468,7 +3468,7 @@ func http2newBufferedWriter(w io.Writer) *http2bufferedWriter { const http2bufWriterPoolBufferSize = 4 << 10 var http2bufWriterPool = sync.Pool{ - New: func() any { + New: func() interface{} { return bufio.NewWriterSize(nil, http2bufWriterPoolBufferSize) }, } @@ -3540,7 +3540,7 @@ type http2connectionStater interface { ConnectionState() tls.ConnectionState } -var http2sorterPool = sync.Pool{New: func() any { return new(http2sorter) }} +var http2sorterPool = sync.Pool{New: func() interface{} { return new(http2sorter) }} type http2sorter struct { v []string // owned by sorter @@ -3781,7 +3781,7 @@ var ( ) var http2responseWriterStatePool = sync.Pool{ - New: func() any { + New: func() interface{} { rws := &http2responseWriterState{} rws.bw = bufio.NewWriterSize(http2chunkWriter{rws}, http2handlerChunkWriteSize) return rws @@ -3793,7 +3793,7 @@ var ( http2testHookOnConn func() http2testHookGetServerConn func(*http2serverConn) http2testHookOnPanicMu *sync.Mutex // nil except in tests - http2testHookOnPanic func(sc *http2serverConn, panicVal any) (rePanic bool) + http2testHookOnPanic func(sc *http2serverConn, panicVal interface{}) (rePanic bool) ) // Server is an HTTP/2 server. @@ -4086,7 +4086,7 @@ func (s *http2Server) ServeConn(c net.Conn, opts *http2ServeConnOpts) { streams: make(map[uint32]*http2stream), readFrameCh: make(chan http2readFrameResult), wantWriteFrameCh: make(chan http2FrameWriteRequest, 8), - serveMsgCh: make(chan any, 8), + serveMsgCh: make(chan interface{}, 8), wroteFrameCh: make(chan http2frameWriteResult, 1), // buffered; one send in writeFrameAsync bodyReadCh: make(chan http2bodyReadMsg), // buffering doesn't matter either way doneServing: make(chan struct{}), @@ -4216,7 +4216,7 @@ type http2serverConn struct { wantWriteFrameCh chan http2FrameWriteRequest // from handlers -> serve wroteFrameCh chan http2frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes bodyReadCh chan http2bodyReadMsg // from handlers -> serve - serveMsgCh chan any // misc messages & code to send to / run on the serve loop + serveMsgCh chan interface{} // misc messages & code to send to / run on the serve loop flow http2flow // conn-wide (not stream-specific) outbound flow control inflow http2flow // conn-wide inbound flow control tlsState *tls.ConnectionState // shared by all handlers, like net/http @@ -4351,13 +4351,13 @@ func (sc *http2serverConn) setConnState(state ConnState) { } } -func (sc *http2serverConn) vlogf(format string, args ...any) { +func (sc *http2serverConn) vlogf(format string, args ...interface{}) { if http2VerboseLogs { sc.logf(format, args...) } } -func (sc *http2serverConn) logf(format string, args ...any) { +func (sc *http2serverConn) logf(format string, args ...interface{}) { if lg := sc.hs.ErrorLog; lg != nil { lg.Printf(format, args...) } else { @@ -4409,7 +4409,7 @@ func http2isClosedConnError(err error) bool { return false } -func (sc *http2serverConn) condlogf(err error, format string, args ...any) { +func (sc *http2serverConn) condlogf(err error, format string, args ...interface{}) { if err == nil { return } @@ -4679,7 +4679,7 @@ func (sc *http2serverConn) onIdleTimer() { sc.sendServeMsg(http2idleTimerMsg) } func (sc *http2serverConn) onShutdownTimer() { sc.sendServeMsg(http2shutdownTimerMsg) } -func (sc *http2serverConn) sendServeMsg(msg any) { +func (sc *http2serverConn) sendServeMsg(msg interface{}) { sc.serveG.checkNotOn() // NOT select { case sc.serveMsgCh <- msg: @@ -4721,11 +4721,11 @@ func (sc *http2serverConn) readPreface() error { } var http2errChanPool = sync.Pool{ - New: func() any { return make(chan error, 1) }, + New: func() interface{} { return make(chan error, 1) }, } var http2writeDataPool = sync.Pool{ - New: func() any { return new(http2writeData) }, + New: func() interface{} { return new(http2writeData) }, } // writeDataFromHandler writes DATA response frames from a handler on @@ -6712,7 +6712,7 @@ func http2new400Handler(err error) HandlerFunc { // disabled. See comments on h1ServerShutdownChan above for why // the code is written this way. func http2h1ServerKeepAlivesDisabled(hs *Server) bool { - var x any = hs + var x interface{} = hs type I interface { doKeepAlives() bool } @@ -9577,21 +9577,21 @@ var ( http2errRequestHeaderListSize = errors.New("http2: request header list larger than peer's advertised limit") ) -func (cc *http2ClientConn) logf(format string, args ...any) { +func (cc *http2ClientConn) logf(format string, args ...interface{}) { cc.t.logf(format, args...) } -func (cc *http2ClientConn) vlogf(format string, args ...any) { +func (cc *http2ClientConn) vlogf(format string, args ...interface{}) { cc.t.vlogf(format, args...) } -func (t *http2Transport) vlogf(format string, args ...any) { +func (t *http2Transport) vlogf(format string, args ...interface{}) { if http2VerboseLogs { t.logf(format, args...) } } -func (t *http2Transport) logf(format string, args ...any) { +func (t *http2Transport) logf(format string, args ...interface{}) { log.Printf(format, args...) } -- GitLab From 67917c3d78002ebca7de697f4ede74e602701554 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Mon, 13 Dec 2021 10:24:07 -0500 Subject: [PATCH 2494/2500] cmd/internal/obj: fix tail call in non-zero frame leaf function on MIPS and S390X A "RET f(SB)" wasn't assembled correctly in a leaf function with non-zero frame size. Follows CL 371034, for MIPS(32/64)(be/le) and S390X. Other architectures seem to do it right. Add a test. Change-Id: I41349a7ae9862b924f3a3de2bcb55b782061ce21 Reviewed-on: https://go-review.googlesource.com/c/go/+/371214 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: David Chase --- src/cmd/internal/obj/mips/obj0.go | 12 +++++++++--- src/cmd/internal/obj/s390x/objz.go | 9 +++++++-- test/retjmp.dir/a.s | 4 ++++ test/retjmp.dir/main.go | 8 +++++++- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/cmd/internal/obj/mips/obj0.go b/src/cmd/internal/obj/mips/obj0.go index 9e2ccc1929..b96a28a944 100644 --- a/src/cmd/internal/obj/mips/obj0.go +++ b/src/cmd/internal/obj/mips/obj0.go @@ -466,9 +466,15 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { q = c.newprog() q.As = AJMP q.Pos = p.Pos - q.To.Type = obj.TYPE_MEM - q.To.Offset = 0 - q.To.Reg = REGLINK + if retSym != nil { // retjmp + q.To.Type = obj.TYPE_BRANCH + q.To.Name = obj.NAME_EXTERN + q.To.Sym = retSym + } else { + q.To.Type = obj.TYPE_MEM + q.To.Reg = REGLINK + q.To.Offset = 0 + } q.Mark |= BRANCH q.Spadj = +autosize diff --git a/src/cmd/internal/obj/s390x/objz.go b/src/cmd/internal/obj/s390x/objz.go index de40ff05af..aebbf8dbc5 100644 --- a/src/cmd/internal/obj/s390x/objz.go +++ b/src/cmd/internal/obj/s390x/objz.go @@ -488,8 +488,13 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { q = obj.Appendp(p, c.newprog) q.As = ABR q.From = obj.Addr{} - q.To.Type = obj.TYPE_REG - q.To.Reg = REG_LR + if retTarget == nil { + q.To.Type = obj.TYPE_REG + q.To.Reg = REG_LR + } else { + q.To.Type = obj.TYPE_BRANCH + q.To.Sym = retTarget + } q.Mark |= BRANCH q.Spadj = autosize break diff --git a/test/retjmp.dir/a.s b/test/retjmp.dir/a.s index c67a06638f..101b3428fc 100644 --- a/test/retjmp.dir/a.s +++ b/test/retjmp.dir/a.s @@ -10,3 +10,7 @@ TEXT ·f(SB), 4, $8-0 TEXT ·leaf(SB), 4, $0-0 RET ·f3(SB) JMP ·unreachable(SB) + +TEXT ·leaf2(SB), 4, $32-0 // nonzero frame size + RET ·f4(SB) + JMP ·unreachable(SB) diff --git a/test/retjmp.dir/main.go b/test/retjmp.dir/main.go index cb4bd018bf..0bed5a61b7 100644 --- a/test/retjmp.dir/main.go +++ b/test/retjmp.dir/main.go @@ -6,8 +6,9 @@ package main func f() func leaf() +func leaf2() -var f1called, f2called, f3called bool +var f1called, f2called, f3called, f4called bool func main() { f() @@ -21,11 +22,16 @@ func main() { if !f3called { panic("f3 not called") } + leaf2() + if !f4called { + panic("f4 not called") + } } func f1() { f1called = true } func f2() { f2called = true } func f3() { f3called = true } +func f4() { f4called = true } func unreachable() { panic("unreachable function called") -- GitLab From 5b9207ff67bd3df43a95fd403b2e06e2aa4c33bf Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 13 Dec 2021 12:42:38 -0800 Subject: [PATCH 2495/2500] cmd/compile: avoid re-instantiating method that is already imported We can import an shape-instantiated function/method for inlining purposes. If we are instantiating the methods of a instantiated type that we have seen, and it happens to need a shape instantiation that we have imported, then don't re-create the instantiation, since we will end up with conflicting/duplicate definitions for the instantiation symbol. Instead, we can just use the existing imported instantation, and enter it in the instInfoMap[]. Fixes #50121 Change-Id: I6eeb8786faad71106e261e113048b579afad04fa Reviewed-on: https://go-review.googlesource.com/c/go/+/371414 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Gopher Robot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 19 +++++++++++++++++-- test/typeparam/issue50121.dir/a.go | 22 ++++++++++++++++++++++ test/typeparam/issue50121.dir/main.go | 18 ++++++++++++++++++ test/typeparam/issue50121.go | 7 +++++++ 4 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 test/typeparam/issue50121.dir/a.go create mode 100644 test/typeparam/issue50121.dir/main.go create mode 100644 test/typeparam/issue50121.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 004db54c3b..62c306b89e 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -684,7 +684,22 @@ func (g *genInst) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMe } info.dictInfo.shapeToBound = make(map[*types.Type]*types.Type) - // genericSubst fills in info.dictParam and info.tparamToBound. + if sym.Def != nil { + // This instantiation must have been imported from another + // package (because it was needed for inlining), so we should + // not re-generate it and have conflicting definitions for the + // symbol (issue #50121). It will have already gone through the + // dictionary transformations of dictPass, so we don't actually + // need the info.dictParam and info.shapeToBound info filled in + // below. We just set the imported instantiation as info.fun. + assert(sym.Pkg != types.LocalPkg) + info.fun = sym.Def.(*ir.Name).Func + assert(info.fun != nil) + g.instInfoMap[sym] = info + return info + } + + // genericSubst fills in info.dictParam and info.shapeToBound. st := g.genericSubst(sym, nameNode, shapes, isMeth, info) info.fun = st g.instInfoMap[sym] = info @@ -722,7 +737,7 @@ type subster struct { // args shapes. For a method with a generic receiver, it returns an instantiated // function type where the receiver becomes the first parameter. For either a generic // method or function, a dictionary parameter is the added as the very first -// parameter. genericSubst fills in info.dictParam and info.tparamToBound. +// parameter. genericSubst fills in info.dictParam and info.shapeToBound. func (g *genInst) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes []*types.Type, isMethod bool, info *instInfo) *ir.Func { var tparams []*types.Type if isMethod { diff --git a/test/typeparam/issue50121.dir/a.go b/test/typeparam/issue50121.dir/a.go new file mode 100644 index 0000000000..9918fa38a6 --- /dev/null +++ b/test/typeparam/issue50121.dir/a.go @@ -0,0 +1,22 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +import ( + "constraints" + "math/rand" +) + +type Builder[T constraints.Integer] struct{} + +func (r Builder[T]) New() T { + return T(rand.Int()) +} + +var IntBuilder = Builder[int]{} + +func BuildInt() int { + return IntBuilder.New() +} diff --git a/test/typeparam/issue50121.dir/main.go b/test/typeparam/issue50121.dir/main.go new file mode 100644 index 0000000000..71eb44ff62 --- /dev/null +++ b/test/typeparam/issue50121.dir/main.go @@ -0,0 +1,18 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "a" +) + +//go:noinline +func BuildInt() int { + return a.BuildInt() +} + +func main() { + BuildInt() +} diff --git a/test/typeparam/issue50121.go b/test/typeparam/issue50121.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/issue50121.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored -- GitLab From 006d4e627812816123a5bb86ebf5a2fa57af8b4a Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 13 Dec 2021 16:15:52 -0800 Subject: [PATCH 2496/2500] cmd/compile: fix case where we didn't delay transformAssign in varDecl We delay all transformations on generic functions, and only do them on instantiated functions, for several reasons, of which one is that otherwise the compiler won't understand the relationship between constrained type parameters. In an instantiation with shape arguments, the underlying relationship between the type arguments are clear and don't lead to compiler errors. This issue is because I missed delaying assignment transformations for variable declarations. So, we were trying to transform an assignment, and the compiler doesn't understand the relationship between the T and U type parameters. The fix is to delay assignment transformations for variable declarations of generic functions, just as we do already for normal assignment statements. A work-around for this issue would be to just separate the assignment from the variable declaration in the generic function (for this case of an assignment involving both of the constrained type parameters). Fixes #50147 Change-Id: Icdbcda147e5c4b386e4715811761cbe73d0d837e Reviewed-on: https://go-review.googlesource.com/c/go/+/371534 Trust: Dan Scales Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/decl.go | 24 ++++++++++++++---------- test/typeparam/issue50147.go | 11 +++++++++++ 2 files changed, 25 insertions(+), 10 deletions(-) create mode 100644 test/typeparam/issue50147.go diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go index b7fd95e2e8..df1ca1c505 100644 --- a/src/cmd/compile/internal/noder/decl.go +++ b/src/cmd/compile/internal/noder/decl.go @@ -286,22 +286,26 @@ func (g *irgen) varDecl(out *ir.Nodes, decl *syntax.VarDecl) { } else if ir.CurFunc == nil { name.Defn = as } - lhs := []ir.Node{as.X} - rhs := []ir.Node{} - if as.Y != nil { - rhs = []ir.Node{as.Y} - } - transformAssign(as, lhs, rhs) - as.X = lhs[0] - if as.Y != nil { - as.Y = rhs[0] + if !g.delayTransform() { + lhs := []ir.Node{as.X} + rhs := []ir.Node{} + if as.Y != nil { + rhs = []ir.Node{as.Y} + } + transformAssign(as, lhs, rhs) + as.X = lhs[0] + if as.Y != nil { + as.Y = rhs[0] + } } as.SetTypecheck(1) out.Append(as) } } if as2 != nil { - transformAssign(as2, as2.Lhs, as2.Rhs) + if !g.delayTransform() { + transformAssign(as2, as2.Lhs, as2.Rhs) + } as2.SetTypecheck(1) out.Append(as2) } diff --git a/test/typeparam/issue50147.go b/test/typeparam/issue50147.go new file mode 100644 index 0000000000..2bdce6c504 --- /dev/null +++ b/test/typeparam/issue50147.go @@ -0,0 +1,11 @@ +// compile -G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func Foo[T any, U interface{ *T }](x T) { + var _ U = &x +} -- GitLab From 1afa432ab93aa9adb2e0f04b6c15eb654762d652 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 13 Dec 2021 15:04:43 -0800 Subject: [PATCH 2497/2500] go/types, types2: record (top-level) union types Fixes #50093. Change-Id: Ibebeda542d2a81c979670f9098c4a6d2c3e73abb Reviewed-on: https://go-review.googlesource.com/c/go/+/371514 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/api.go | 6 +++++ src/cmd/compile/internal/types2/api_test.go | 10 ++++++++ src/cmd/compile/internal/types2/interface.go | 10 +------- src/cmd/compile/internal/types2/union.go | 24 +++++++++++++++----- src/go/types/api.go | 6 +++++ src/go/types/api_test.go | 10 ++++++++ src/go/types/interface.go | 10 +------- src/go/types/union.go | 24 +++++++++++++++----- 8 files changed, 70 insertions(+), 30 deletions(-) diff --git a/src/cmd/compile/internal/types2/api.go b/src/cmd/compile/internal/types2/api.go index 4ea3989c39..ed5bced643 100644 --- a/src/cmd/compile/internal/types2/api.go +++ b/src/cmd/compile/internal/types2/api.go @@ -202,6 +202,12 @@ type Info struct { // identifier z in a variable declaration 'var z int' is found // only in the Defs map, and identifiers denoting packages in // qualified identifiers are collected in the Uses map. + // + // For binary expressions representing unions in constraint + // position or type elements in interfaces, a union type is + // recorded for the top-level expression only. For instance, + // given the constraint a|b|c, the union type for (a|b)|c + // is recorded, but not the union type for a|b. Types map[syntax.Expr]TypeAndValue // Instances maps identifiers denoting parameterized types or functions to diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index 4227397df9..fc8b5cd4ee 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -342,6 +342,16 @@ func TestTypesInfo(t *testing.T) { // issue 47895 {`package p; import "unsafe"; type S struct { f int }; var s S; var _ = unsafe.Offsetof(s.f)`, `s.f`, `int`}, + + // issue 50093 + {`package u0a; func _[_ interface{int}]() {}`, `int`, `int`}, + {`package u1a; func _[_ interface{~int}]() {}`, `~int`, `~int`}, + {`package u2a; func _[_ interface{int|string}]() {}`, `int | string`, `int|string`}, + {`package u3a; func _[_ interface{int|string|~bool}]() {}`, `int | string | ~bool`, `int|string|~bool`}, + {`package u0b; func _[_ int]() {}`, `int`, `int`}, + {`package u1b; func _[_ ~int]() {}`, `~int`, `~int`}, + {`package u2b; func _[_ int|string]() {}`, `int | string`, `int|string`}, + {`package u3b; func _[_ int|string|~bool]() {}`, `int | string | ~bool`, `int|string|~bool`}, } for _, test := range tests { diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index 96c92ccaec..b048fdd9e2 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -111,7 +111,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType for _, f := range iface.MethodList { if f.Name == nil { - addEmbedded(posFor(f.Type), parseUnion(check, flattenUnion(nil, f.Type))) + addEmbedded(posFor(f.Type), parseUnion(check, f.Type)) continue } // f.Name != nil @@ -182,11 +182,3 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType ityp.check = nil }).describef(iface, "compute type set for %s", ityp) } - -func flattenUnion(list []syntax.Expr, x syntax.Expr) []syntax.Expr { - if o, _ := x.(*syntax.Operation); o != nil && o.Op == syntax.Or { - list = flattenUnion(list, o.X) - x = o.Y - } - return append(list, x) -} diff --git a/src/cmd/compile/internal/types2/union.go b/src/cmd/compile/internal/types2/union.go index 2304b30280..97581fe863 100644 --- a/src/cmd/compile/internal/types2/union.go +++ b/src/cmd/compile/internal/types2/union.go @@ -46,10 +46,11 @@ func (t *Term) String() string { return (*term)(t).String() } // Avoid excessive type-checking times due to quadratic termlist operations. const maxTermCount = 100 -// parseUnion parses the given list of type expressions tlist as a union of -// those expressions. The result is a Union type, or Typ[Invalid] for some -// errors. -func parseUnion(check *Checker, tlist []syntax.Expr) Type { +// parseUnion parses uexpr as a union of expressions. +// The result is a Union type, or Typ[Invalid] for some errors. +func parseUnion(check *Checker, uexpr syntax.Expr) Type { + tlist := flattenUnion(nil, uexpr) + var terms []*Term for _, x := range tlist { tilde, typ := parseTilde(check, x) @@ -57,10 +58,11 @@ func parseUnion(check *Checker, tlist []syntax.Expr) Type { // Single type. Ok to return early because all relevant // checks have been performed in parseTilde (no need to // run through term validity check below). - return typ + return typ // typ already recorded through check.typ in parseTilde } if len(terms) >= maxTermCount { check.errorf(x, "cannot handle more than %d union terms (implementation limitation)", maxTermCount) + check.recordTypeAndValue(uexpr, typexpr, Typ[Invalid], nil) return Typ[Invalid] } terms = append(terms, NewTerm(tilde, typ)) @@ -105,7 +107,9 @@ func parseUnion(check *Checker, tlist []syntax.Expr) Type { } }) - return &Union{terms, nil} + u := &Union{terms, nil} + check.recordTypeAndValue(uexpr, typexpr, u, nil) + return u } func parseTilde(check *Checker, x syntax.Expr) (tilde bool, typ Type) { @@ -143,3 +147,11 @@ func overlappingTerm(terms []*Term, y *Term) int { } return -1 } + +func flattenUnion(list []syntax.Expr, x syntax.Expr) []syntax.Expr { + if o, _ := x.(*syntax.Operation); o != nil && o.Op == syntax.Or { + list = flattenUnion(list, o.X) + x = o.Y + } + return append(list, x) +} diff --git a/src/go/types/api.go b/src/go/types/api.go index 51d58c49aa..c4d81c1491 100644 --- a/src/go/types/api.go +++ b/src/go/types/api.go @@ -197,6 +197,12 @@ type Info struct { // identifier z in a variable declaration 'var z int' is found // only in the Defs map, and identifiers denoting packages in // qualified identifiers are collected in the Uses map. + // + // For binary expressions representing unions in constraint + // position or type elements in interfaces, a union type is + // recorded for the top-level expression only. For instance, + // given the constraint a|b|c, the union type for (a|b)|c + // is recorded, but not the union type for a|b. Types map[ast.Expr]TypeAndValue // Instances maps identifiers denoting parameterized types or functions to diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index 7b7baa7604..1ee9806fd0 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -373,6 +373,16 @@ func TestTypesInfo(t *testing.T) { // issue 47895 {`package p; import "unsafe"; type S struct { f int }; var s S; var _ = unsafe.Offsetof(s.f)`, `s.f`, `int`}, + + // issue 50093 + {genericPkg + `u0a; func _[_ interface{int}]() {}`, `int`, `int`}, + {genericPkg + `u1a; func _[_ interface{~int}]() {}`, `~int`, `~int`}, + {genericPkg + `u2a; func _[_ interface{int|string}]() {}`, `int | string`, `int|string`}, + {genericPkg + `u3a; func _[_ interface{int|string|~bool}]() {}`, `int | string | ~bool`, `int|string|~bool`}, + {genericPkg + `u0b; func _[_ int]() {}`, `int`, `int`}, + {genericPkg + `u1b; func _[_ ~int]() {}`, `~int`, `~int`}, + {genericPkg + `u2b; func _[_ int|string]() {}`, `int | string`, `int|string`}, + {genericPkg + `u3b; func _[_ int|string|~bool]() {}`, `int | string | ~bool`, `int|string|~bool`}, } for _, test := range tests { diff --git a/src/go/types/interface.go b/src/go/types/interface.go index ef65bc6b2b..1ff9015780 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -152,7 +152,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d for _, f := range iface.Methods.List { if len(f.Names) == 0 { - addEmbedded(f.Type.Pos(), parseUnion(check, flattenUnion(nil, f.Type))) + addEmbedded(f.Type.Pos(), parseUnion(check, f.Type)) continue } // f.Name != nil @@ -223,11 +223,3 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d ityp.check = nil }).describef(iface, "compute type set for %s", ityp) } - -func flattenUnion(list []ast.Expr, x ast.Expr) []ast.Expr { - if o, _ := x.(*ast.BinaryExpr); o != nil && o.Op == token.OR { - list = flattenUnion(list, o.X) - x = o.Y - } - return append(list, x) -} diff --git a/src/go/types/union.go b/src/go/types/union.go index 2a65ca4d8e..1437bd4624 100644 --- a/src/go/types/union.go +++ b/src/go/types/union.go @@ -49,10 +49,11 @@ func (t *Term) String() string { return (*term)(t).String() } // Avoid excessive type-checking times due to quadratic termlist operations. const maxTermCount = 100 -// parseUnion parses the given list of type expressions tlist as a union of -// those expressions. The result is a Union type, or Typ[Invalid] for some -// errors. -func parseUnion(check *Checker, tlist []ast.Expr) Type { +// parseUnion parses uexpr as a union of expressions. +// The result is a Union type, or Typ[Invalid] for some errors. +func parseUnion(check *Checker, uexpr ast.Expr) Type { + tlist := flattenUnion(nil, uexpr) + var terms []*Term for _, x := range tlist { tilde, typ := parseTilde(check, x) @@ -60,10 +61,11 @@ func parseUnion(check *Checker, tlist []ast.Expr) Type { // Single type. Ok to return early because all relevant // checks have been performed in parseTilde (no need to // run through term validity check below). - return typ + return typ // typ already recorded through check.typ in parseTilde } if len(terms) >= maxTermCount { check.errorf(x, _InvalidUnion, "cannot handle more than %d union terms (implementation limitation)", maxTermCount) + check.recordTypeAndValue(uexpr, typexpr, Typ[Invalid], nil) return Typ[Invalid] } terms = append(terms, NewTerm(tilde, typ)) @@ -108,7 +110,9 @@ func parseUnion(check *Checker, tlist []ast.Expr) Type { } }) - return &Union{terms, nil} + u := &Union{terms, nil} + check.recordTypeAndValue(uexpr, typexpr, u, nil) + return u } func parseTilde(check *Checker, x ast.Expr) (tilde bool, typ Type) { @@ -146,3 +150,11 @@ func overlappingTerm(terms []*Term, y *Term) int { } return -1 } + +func flattenUnion(list []ast.Expr, x ast.Expr) []ast.Expr { + if o, _ := x.(*ast.BinaryExpr); o != nil && o.Op == token.OR { + list = flattenUnion(list, o.X) + x = o.Y + } + return append(list, x) +} -- GitLab From c1f012a0d9b4c7bc9f2a1474f4935e53eccd1794 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 14 Dec 2021 10:49:07 -0500 Subject: [PATCH 2498/2500] cmd/compile: fix any in -G=0 mode Fixes go test -gcflags=all=-G=0 -short std, except for the packages with generics in their tests (constraints, encoding/xml), and except for the go/internal/gcimporter and go/types tests, because the compiler does not preserve any in its -G=0 export information. (That's probably acceptable for now.) Fixes cd test/; GO_BUILDER_NAME=longtest go run run.go completely, which should fix the longtest builder. Fixes #50159. Change-Id: I9390972239c18831833edd6530191da2842b876b Reviewed-on: https://go-review.googlesource.com/c/go/+/371715 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Cherry Mui TryBot-Result: Gopher Robot --- src/cmd/compile/internal/types/universe.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/types/universe.go b/src/cmd/compile/internal/types/universe.go index f845614e13..54b04bda22 100644 --- a/src/cmd/compile/internal/types/universe.go +++ b/src/cmd/compile/internal/types/universe.go @@ -57,7 +57,7 @@ func InitTypes(defTypeName func(sym *Sym, typ *Type) Object) { SimType[et] = et } - Types[TANY] = newType(TANY) + Types[TANY] = newType(TANY) // note: an old placeholder type, NOT the new builtin 'any' alias for interface{} Types[TINTER] = NewInterface(LocalPkg, nil, false) CheckSize(Types[TINTER]) @@ -91,6 +91,7 @@ func InitTypes(defTypeName func(sym *Sym, typ *Type) Object) { // int32 Hence, (bytetype|runtype).Sym.isAlias() is false. // TODO(gri) Should we get rid of this special case (at the cost // of less informative error messages involving bytes and runes)? + // NOTE(rsc): No, the error message quality is important. // (Alternatively, we could introduce an OTALIAS node representing // type aliases, albeit at the cost of having to deal with it everywhere). ByteType = defBasic(TUINT8, BuiltinPkg, "byte") @@ -111,12 +112,11 @@ func InitTypes(defTypeName func(sym *Sym, typ *Type) Object) { // any type (interface) DeferCheckSize() AnyType = defBasic(TFORW, BuiltinPkg, "any") - AnyType.SetUnderlying(NewInterface(NoPkg, []*Field{}, false)) + AnyType.SetUnderlying(NewInterface(BuiltinPkg, []*Field{}, false)) ResumeCheckSize() if base.Flag.G == 0 { ComparableType.Sym().Def = nil - AnyType.Sym().Def = nil } Types[TUNSAFEPTR] = defBasic(TUNSAFEPTR, UnsafePkg, "Pointer") -- GitLab From 46ba32a2ca304b0b73979736d6fb8013529e9172 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 14 Dec 2021 12:17:53 -0500 Subject: [PATCH 2499/2500] doc/go1.18: remove residual TODOs There doesn't seem anything that still needs to de done there. Updates #47694. Change-Id: I7909f566638332f3904d20a34f61d371af1d2da2 Reviewed-on: https://go-review.googlesource.com/c/go/+/371754 Trust: Cherry Mui Reviewed-by: Jeremy Faller Trust: Jeremy Faller Reviewed-by: Alex Rakoczy --- doc/go1.18.html | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 67af3e6a90..5ab40280b5 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -411,12 +411,6 @@ Do not send CLs removing the interior tags from such phrases. types and netip.AddrPort.

    -

    TODO

    - -

    - TODO: complete this section -

    -

    Minor changes to the library

    @@ -425,10 +419,6 @@ Do not send CLs removing the interior tags from such phrases. in mind.

    -

    - TODO: complete this section -

    -
    bufio

    -- GitLab From becaeea1199b875bc24800fa88f2f4fea119bf78 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 14 Dec 2021 12:24:08 -0500 Subject: [PATCH 2500/2500] api: promote next to go1.18 Change-Id: Ifc61e67413e5e56afbd0d4954f0150303d1a3a27 Reviewed-on: https://go-review.googlesource.com/c/go/+/371755 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: Russ Cox Reviewed-by: Alex Rakoczy TryBot-Result: Gopher Robot --- api/go1.18.txt | 238 +++++++++++++++++++++++++++++++++++++++++++++++++ api/next.txt | 47 ---------- 2 files changed, 238 insertions(+), 47 deletions(-) create mode 100644 api/go1.18.txt diff --git a/api/go1.18.txt b/api/go1.18.txt new file mode 100644 index 0000000000..afcb31c638 --- /dev/null +++ b/api/go1.18.txt @@ -0,0 +1,238 @@ +pkg bufio, method (*Writer) AvailableBuffer() []uint8 +pkg bufio, method (ReadWriter) AvailableBuffer() []uint8 +pkg bytes, func Cut([]uint8, []uint8) ([]uint8, []uint8, bool) +pkg constraints, type Complex interface {} +pkg constraints, type Float interface {} +pkg constraints, type Integer interface {} +pkg constraints, type Ordered interface {} +pkg constraints, type Signed interface {} +pkg constraints, type Unsigned interface {} +pkg crypto/tls, method (*Conn) NetConn() net.Conn +pkg debug/buildinfo, func Read(io.ReaderAt) (*debug.BuildInfo, error) +pkg debug/buildinfo, func ReadFile(string) (*debug.BuildInfo, error) +pkg debug/buildinfo, type BuildInfo = debug.BuildInfo +pkg debug/elf, const R_PPC64_RELATIVE = 22 +pkg debug/elf, const R_PPC64_RELATIVE R_PPC64 +pkg debug/plan9obj, var ErrNoSymbols error +pkg go/ast, method (*IndexListExpr) End() token.Pos +pkg go/ast, method (*IndexListExpr) Pos() token.Pos +pkg go/ast, type FuncType struct, TypeParams *FieldList +pkg go/ast, type IndexListExpr struct +pkg go/ast, type IndexListExpr struct, Indices []Expr +pkg go/ast, type IndexListExpr struct, Lbrack token.Pos +pkg go/ast, type IndexListExpr struct, Rbrack token.Pos +pkg go/ast, type IndexListExpr struct, X Expr +pkg go/ast, type TypeSpec struct, TypeParams *FieldList +pkg go/constant, method (Kind) String() string +pkg go/token, const TILDE = 88 +pkg go/token, const TILDE Token +pkg go/types, func Instantiate(*Context, Type, []Type, bool) (Type, error) +pkg go/types, func NewContext() *Context +pkg go/types, func NewSignatureType(*Var, []*TypeParam, []*TypeParam, *Tuple, *Tuple, bool) *Signature +pkg go/types, func NewTerm(bool, Type) *Term +pkg go/types, func NewTypeParam(*TypeName, Type) *TypeParam +pkg go/types, func NewUnion([]*Term) *Union +pkg go/types, method (*ArgumentError) Error() string +pkg go/types, method (*ArgumentError) Unwrap() error +pkg go/types, method (*Interface) IsComparable() bool +pkg go/types, method (*Interface) IsImplicit() bool +pkg go/types, method (*Interface) IsMethodSet() bool +pkg go/types, method (*Interface) MarkImplicit() +pkg go/types, method (*Named) Origin() *Named +pkg go/types, method (*Named) SetTypeParams([]*TypeParam) +pkg go/types, method (*Named) TypeArgs() *TypeList +pkg go/types, method (*Named) TypeParams() *TypeParamList +pkg go/types, method (*Signature) RecvTypeParams() *TypeParamList +pkg go/types, method (*Signature) TypeParams() *TypeParamList +pkg go/types, method (*Term) String() string +pkg go/types, method (*Term) Tilde() bool +pkg go/types, method (*Term) Type() Type +pkg go/types, method (*TypeList) At(int) Type +pkg go/types, method (*TypeList) Len() int +pkg go/types, method (*TypeList) String() string +pkg go/types, method (*TypeParam) Constraint() Type +pkg go/types, method (*TypeParam) Index() int +pkg go/types, method (*TypeParam) Obj() *TypeName +pkg go/types, method (*TypeParam) SetConstraint(Type) +pkg go/types, method (*TypeParam) String() string +pkg go/types, method (*TypeParam) Underlying() Type +pkg go/types, method (*TypeParamList) At(int) *TypeParam +pkg go/types, method (*TypeParamList) Len() int +pkg go/types, method (*Union) Len() int +pkg go/types, method (*Union) String() string +pkg go/types, method (*Union) Term(int) *Term +pkg go/types, method (*Union) Underlying() Type +pkg go/types, type ArgumentError struct +pkg go/types, type ArgumentError struct, Err error +pkg go/types, type ArgumentError struct, Index int +pkg go/types, type Config struct, Context *Context +pkg go/types, type Config struct, GoVersion string +pkg go/types, type Context struct +pkg go/types, type Info struct, Instances map[*ast.Ident]Instance +pkg go/types, type Instance struct +pkg go/types, type Instance struct, Type Type +pkg go/types, type Instance struct, TypeArgs *TypeList +pkg go/types, type Term struct +pkg go/types, type TypeList struct +pkg go/types, type TypeParam struct +pkg go/types, type TypeParamList struct +pkg go/types, type Union struct +pkg net, func TCPAddrFromAddrPort(netip.AddrPort) *TCPAddr +pkg net, func UDPAddrFromAddrPort(netip.AddrPort) *UDPAddr +pkg net, method (*Resolver) LookupNetIP(context.Context, string, string) ([]netip.Addr, error) +pkg net, method (*TCPAddr) AddrPort() netip.AddrPort +pkg net, method (*UDPAddr) AddrPort() netip.AddrPort +pkg net, method (*UDPConn) ReadFromUDPAddrPort([]uint8) (int, netip.AddrPort, error) +pkg net, method (*UDPConn) ReadMsgUDPAddrPort([]uint8, []uint8) (int, int, int, netip.AddrPort, error) +pkg net, method (*UDPConn) WriteMsgUDPAddrPort([]uint8, []uint8, netip.AddrPort) (int, int, error) +pkg net, method (*UDPConn) WriteToUDPAddrPort([]uint8, netip.AddrPort) (int, error) +pkg net/http, func MaxBytesHandler(Handler, int64) Handler +pkg net/http, method (*Cookie) Valid() error +pkg net/netip, func AddrFrom16([16]uint8) Addr +pkg net/netip, func AddrFrom4([4]uint8) Addr +pkg net/netip, func AddrFromSlice([]uint8) (Addr, bool) +pkg net/netip, func AddrPortFrom(Addr, uint16) AddrPort +pkg net/netip, func IPv4Unspecified() Addr +pkg net/netip, func IPv6LinkLocalAllNodes() Addr +pkg net/netip, func IPv6Unspecified() Addr +pkg net/netip, func MustParseAddr(string) Addr +pkg net/netip, func MustParseAddrPort(string) AddrPort +pkg net/netip, func MustParsePrefix(string) Prefix +pkg net/netip, func ParseAddr(string) (Addr, error) +pkg net/netip, func ParseAddrPort(string) (AddrPort, error) +pkg net/netip, func ParsePrefix(string) (Prefix, error) +pkg net/netip, func PrefixFrom(Addr, int) Prefix +pkg net/netip, method (*Addr) UnmarshalBinary([]uint8) error +pkg net/netip, method (*Addr) UnmarshalText([]uint8) error +pkg net/netip, method (*AddrPort) UnmarshalBinary([]uint8) error +pkg net/netip, method (*AddrPort) UnmarshalText([]uint8) error +pkg net/netip, method (*Prefix) UnmarshalBinary([]uint8) error +pkg net/netip, method (*Prefix) UnmarshalText([]uint8) error +pkg net/netip, method (Addr) AppendTo([]uint8) []uint8 +pkg net/netip, method (Addr) As16() [16]uint8 +pkg net/netip, method (Addr) As4() [4]uint8 +pkg net/netip, method (Addr) AsSlice() []uint8 +pkg net/netip, method (Addr) BitLen() int +pkg net/netip, method (Addr) Compare(Addr) int +pkg net/netip, method (Addr) Is4() bool +pkg net/netip, method (Addr) Is4In6() bool +pkg net/netip, method (Addr) Is6() bool +pkg net/netip, method (Addr) IsGlobalUnicast() bool +pkg net/netip, method (Addr) IsInterfaceLocalMulticast() bool +pkg net/netip, method (Addr) IsLinkLocalMulticast() bool +pkg net/netip, method (Addr) IsLinkLocalUnicast() bool +pkg net/netip, method (Addr) IsLoopback() bool +pkg net/netip, method (Addr) IsMulticast() bool +pkg net/netip, method (Addr) IsPrivate() bool +pkg net/netip, method (Addr) IsUnspecified() bool +pkg net/netip, method (Addr) IsValid() bool +pkg net/netip, method (Addr) Less(Addr) bool +pkg net/netip, method (Addr) MarshalBinary() ([]uint8, error) +pkg net/netip, method (Addr) MarshalText() ([]uint8, error) +pkg net/netip, method (Addr) Next() Addr +pkg net/netip, method (Addr) Prefix(int) (Prefix, error) +pkg net/netip, method (Addr) Prev() Addr +pkg net/netip, method (Addr) String() string +pkg net/netip, method (Addr) StringExpanded() string +pkg net/netip, method (Addr) Unmap() Addr +pkg net/netip, method (Addr) WithZone(string) Addr +pkg net/netip, method (Addr) Zone() string +pkg net/netip, method (AddrPort) Addr() Addr +pkg net/netip, method (AddrPort) AppendTo([]uint8) []uint8 +pkg net/netip, method (AddrPort) IsValid() bool +pkg net/netip, method (AddrPort) MarshalBinary() ([]uint8, error) +pkg net/netip, method (AddrPort) MarshalText() ([]uint8, error) +pkg net/netip, method (AddrPort) Port() uint16 +pkg net/netip, method (AddrPort) String() string +pkg net/netip, method (Prefix) Addr() Addr +pkg net/netip, method (Prefix) AppendTo([]uint8) []uint8 +pkg net/netip, method (Prefix) Bits() int +pkg net/netip, method (Prefix) Contains(Addr) bool +pkg net/netip, method (Prefix) IsSingleIP() bool +pkg net/netip, method (Prefix) IsValid() bool +pkg net/netip, method (Prefix) MarshalBinary() ([]uint8, error) +pkg net/netip, method (Prefix) MarshalText() ([]uint8, error) +pkg net/netip, method (Prefix) Masked() Prefix +pkg net/netip, method (Prefix) Overlaps(Prefix) bool +pkg net/netip, method (Prefix) String() string +pkg net/netip, type Addr struct +pkg net/netip, type AddrPort struct +pkg net/netip, type Prefix struct +pkg reflect, const Pointer = 22 +pkg reflect, const Pointer Kind +pkg reflect, func PointerTo(Type) Type +pkg reflect, method (*MapIter) Reset(Value) +pkg reflect, method (Value) CanComplex() bool +pkg reflect, method (Value) CanFloat() bool +pkg reflect, method (Value) CanInt() bool +pkg reflect, method (Value) CanUint() bool +pkg reflect, method (Value) FieldByIndexErr([]int) (Value, error) +pkg reflect, method (Value) SetIterKey(*MapIter) +pkg reflect, method (Value) SetIterValue(*MapIter) +pkg reflect, method (Value) UnsafePointer() unsafe.Pointer +pkg runtime/debug, method (*BuildInfo) MarshalText() ([]uint8, error) +pkg runtime/debug, method (*BuildInfo) UnmarshalText([]uint8) error +pkg runtime/debug, type BuildInfo struct, GoVersion string +pkg runtime/debug, type BuildInfo struct, Settings []BuildSetting +pkg runtime/debug, type BuildSetting struct +pkg runtime/debug, type BuildSetting struct, Key string +pkg runtime/debug, type BuildSetting struct, Value string +pkg strings, func Clone(string) string +pkg strings, func Cut(string, string) (string, string, bool) +pkg sync, method (*Mutex) TryLock() bool +pkg sync, method (*RWMutex) TryLock() bool +pkg sync, method (*RWMutex) TryRLock() bool +pkg syscall (freebsd-386), type SysProcAttr struct, Pdeathsig Signal +pkg syscall (freebsd-386-cgo), type SysProcAttr struct, Pdeathsig Signal +pkg syscall (freebsd-amd64), type SysProcAttr struct, Pdeathsig Signal +pkg syscall (freebsd-amd64-cgo), type SysProcAttr struct, Pdeathsig Signal +pkg syscall (freebsd-arm), type SysProcAttr struct, Pdeathsig Signal +pkg syscall (freebsd-arm-cgo), type SysProcAttr struct, Pdeathsig Signal +pkg syscall (windows-386), func SyscallN(uintptr, ...uintptr) (uintptr, uintptr, Errno) +pkg syscall (windows-amd64), func SyscallN(uintptr, ...uintptr) (uintptr, uintptr, Errno) +pkg testing, func MainStart(testDeps, []InternalTest, []InternalBenchmark, []InternalFuzzTarget, []InternalExample) *M +pkg testing, method (*F) Add(...interface{}) +pkg testing, method (*F) Cleanup(func()) +pkg testing, method (*F) Error(...interface{}) +pkg testing, method (*F) Errorf(string, ...interface{}) +pkg testing, method (*F) Fail() +pkg testing, method (*F) FailNow() +pkg testing, method (*F) Failed() bool +pkg testing, method (*F) Fatal(...interface{}) +pkg testing, method (*F) Fatalf(string, ...interface{}) +pkg testing, method (*F) Fuzz(interface{}) +pkg testing, method (*F) Helper() +pkg testing, method (*F) Log(...interface{}) +pkg testing, method (*F) Logf(string, ...interface{}) +pkg testing, method (*F) Name() string +pkg testing, method (*F) Setenv(string, string) +pkg testing, method (*F) Skip(...interface{}) +pkg testing, method (*F) SkipNow() +pkg testing, method (*F) Skipf(string, ...interface{}) +pkg testing, method (*F) Skipped() bool +pkg testing, method (*F) TempDir() string +pkg testing, type F struct +pkg testing, type InternalFuzzTarget struct +pkg testing, type InternalFuzzTarget struct, Fn func(*F) +pkg testing, type InternalFuzzTarget struct, Name string +pkg text/template/parse, const NodeBreak = 21 +pkg text/template/parse, const NodeBreak NodeType +pkg text/template/parse, const NodeContinue = 22 +pkg text/template/parse, const NodeContinue NodeType +pkg text/template/parse, method (*BreakNode) Copy() Node +pkg text/template/parse, method (*BreakNode) String() string +pkg text/template/parse, method (*ContinueNode) Copy() Node +pkg text/template/parse, method (*ContinueNode) String() string +pkg text/template/parse, method (BreakNode) Position() Pos +pkg text/template/parse, method (BreakNode) Type() NodeType +pkg text/template/parse, method (ContinueNode) Position() Pos +pkg text/template/parse, method (ContinueNode) Type() NodeType +pkg text/template/parse, type BreakNode struct +pkg text/template/parse, type BreakNode struct, Line int +pkg text/template/parse, type BreakNode struct, embedded NodeType +pkg text/template/parse, type BreakNode struct, embedded Pos +pkg text/template/parse, type ContinueNode struct +pkg text/template/parse, type ContinueNode struct, Line int +pkg text/template/parse, type ContinueNode struct, embedded NodeType +pkg text/template/parse, type ContinueNode struct, embedded Pos +pkg unicode/utf8, func AppendRune([]uint8, int32) []uint8 diff --git a/api/next.txt b/api/next.txt index cc4120b7ab..e69de29bb2 100644 --- a/api/next.txt +++ b/api/next.txt @@ -1,47 +0,0 @@ -pkg debug/buildinfo, func Read(io.ReaderAt) (*debug.BuildInfo, error) -pkg debug/buildinfo, func ReadFile(string) (*debug.BuildInfo, error) -pkg debug/buildinfo, type BuildInfo = debug.BuildInfo -pkg runtime/debug, method (*BuildInfo) MarshalText() ([]byte, error) -pkg runtime/debug, method (*BuildInfo) UnmarshalText() ([]byte, error) -pkg runtime/debug, type BuildInfo struct, GoVersion string -pkg runtime/debug, type BuildInfo struct, Settings []BuildSetting -pkg runtime/debug, type BuildSetting struct -pkg runtime/debug, type BuildSetting struct, Key string -pkg runtime/debug, type BuildSetting struct, Value string -pkg testing, func Fuzz(func(*F)) FuzzResult -pkg testing, func MainStart(testDeps, []InternalTest, []InternalBenchmark, []InternalFuzzTarget, []InternalExample) *M -pkg testing, func RunFuzzTargets(func(string, string) (bool, error), []InternalFuzzTarget) bool -pkg testing, func RunFuzzing(func(string, string) (bool, error), []InternalFuzzTarget) bool -pkg testing, method (*B) Setenv(string, string) -pkg testing, method (*F) Add(...interface{}) -pkg testing, method (*F) Cleanup(func()) -pkg testing, method (*F) Error(...interface{}) -pkg testing, method (*F) Errorf(string, ...interface{}) -pkg testing, method (*F) Fail() -pkg testing, method (*F) FailNow() -pkg testing, method (*F) Failed() bool -pkg testing, method (*F) Fatal(...interface{}) -pkg testing, method (*F) Fatalf(string, ...interface{}) -pkg testing, method (*F) Fuzz(interface{}) -pkg testing, method (*F) Helper() -pkg testing, method (*F) Log(...interface{}) -pkg testing, method (*F) Logf(string, ...interface{}) -pkg testing, method (*F) Name() string -pkg testing, method (*F) Setenv(string, string) -pkg testing, method (*F) Skip(...interface{}) -pkg testing, method (*F) SkipNow() -pkg testing, method (*F) Skipf(string, ...interface{}) -pkg testing, method (*F) Skipped() bool -pkg testing, method (*F) TempDir() string -pkg testing, method (*T) Setenv(string, string) -pkg testing, method (FuzzResult) String() string -pkg testing, type F struct -pkg testing, type FuzzResult struct -pkg testing, type FuzzResult struct, Crasher entry -pkg testing, type FuzzResult struct, Error error -pkg testing, type FuzzResult struct, N int -pkg testing, type FuzzResult struct, T time.Duration -pkg testing, type InternalFuzzTarget struct -pkg testing, type InternalFuzzTarget struct, Fn func(*F) -pkg testing, type InternalFuzzTarget struct, Name string -pkg net/http, method (*Cookie) Valid() error -- GitLab

  • NT0&@t=dnRCOeG^NPGg4D62KJig0U4etr(jVpL7oa-yLnxN8WB6KEdAs@upIlE*^xic*vF)AKT`Qd2+y zh*dFqC)&^g)K*BWaLmapONEp)*!7vZrB^72oYH%8*rv%uWe}*1Xh!(tC#IyPKxz%scAYtL@)k8i98@VxWEZy0j6?L@#mUXmRXdahs}{jM((L4E{R3unR(u+ zMR}JLY7j=cT5gs)eN+q#^>|_JdTJP!)()k|nsx^UN*C!R|JA z1K2mQGAOmAv?$N7GzY6%V@NULk(q~RH9IGQiYEN}43VlGa6#mV-F!n+c;NyX$V|?* z0H-)ysx85p2HeOB%>(r-a49rLCt7|O=ey?Sh*RBN)(guNLd7>CZ>SgNrVk1Na|3`N0vYnj(qAn)&dtSQ8{ks3t=LP*DOIZGgHJDub=1Rg{{Onpm6)Rfsp3L0uW} zzz!snqK1&UZ+>2WNq$~tvR`6een@66%t#bv7WgC$O~JLPQ)XUbQKerZb`uOijW3V~ zQ;Umnsxc2O0QHgxC^L4+#Og>xY&D;uF{rk2E6UFWI}#dRD4sLK=rMtYJCft!-KO}` zyyC<(>~42*$i%7$ zQXz0DbSGMd=4BR^rXm!exDrd8!A(L{h}m&7Gy->ez;j`#SRIXRm>*PDxj-h+uxm0h z02lS3jO|$*nwOKAn^}TGC1@@P)LI6QPZLsX0vafS^nbwW(T#?cEr?pz!m~IyBe4j( z<%X#B1a!U;RF=clL!$y(??5IbQ52wru#q8T+6vsngfy2yim@4tq7PdjgSw+`nR%JT z8R(8NMD44CMl8`35;WYvKM$W4BNrDV14!{3kWpETG=qhu+%z)vO{`2x1&>oZB_?O5 z7v+~i=gUyDoRJwsA!s%hrVuu>231MO;pX7vng~m&(AYr>5HrxIFI){FBT-euOhlf? zH37{5V{@QcP^xQ1YBDw{Lr4w)SAK?|{Nh|%RFs-m5`bN`F?goiHz3GA#MLyiS zE5?!o;0j@`!I%?HO91YLiuEETlFcm2F;?JBgEigkd10L=`m=fg7 z3Db^hqcKWn&>5x(Y5+WQqKP9iCz=GF%n4J8YCm%3gsFg84$GWq;z*ejCWB%oj?4*D z3o{*-Ibq@`W}s$HtV$4>6DAEc8Iii+!HHrvj?@KL3^fKdbHeOEF$pts!j!?xz)T|; z)*z)3s2pSwPJSMA*%(87B4`eYAs)KuD?LBH7_=^cAwC^6?p06%TS*3*4+QZ_!2=y2 z7E}jx`5Aa>3ABm_Z8;un@Dwy%3R?J9T9oRTmjdd%ftKV28^&iQxf+@lr6!kxN2DNA zR1EQu(Z$T%#Pn3S5YlR^{JePZ(muGm(@OJ_<5Md#OBmvz6wU>3pb09NufXf$z^mUN zqEJ6UIK`7$NQ!hrKhI2 z=j10P=780~S3t&R<`tJD=H$fZf(MD?6Z2ByK?^S8GeDE^m|ibVElC5-12Mofe zSLNrW7Q;oLyprVN)Dlo|F~pZ7r$d=J@p{E2MIe`gmmq=|paqZdkSGByk%UDjXw(=I zr5UM-DXB#a@hPPR4Dkh!g#@4_aiCC4&Q458DT>d-CR3bQm5L$*(VCe87A!5!Nlh(a zh=)?~@wug-1w1GIDm zMaIV@DL~^}z`6s52EO@asStO7TnWx;7;3;X9^l3q*!L(wh_1`X7-AZDwY6t%CTM*%*t3MS z8k#}1f)+G@^%K@(Yzox_THK9noqrK{8iz<@;8uf-0WAbe!DBT_pc@&u5=E(@nJ=_52F+Ob=jBwoLX|;7+|oC(0AdQ7grS*dv1>&^YH~?x3Zy#-Q-Ep# zy_cw2fKvu6LmHy5PKEjo)s65#@XLp;EPyJ51_B~!qD7!3bcj8_2c^;+dsi5gP z-~1HNE){SLqnZy3Q;3^DYKuei{e!U@Z%E@R8nrkexXA%rKci-TA45~nvXwOOx>lqb z2m4kUNS%rj9vDj^OoL&Qv7jYXo+++b*mNP&%#zX)P^S+xLl~BrQwnLTV$)z~0a625ty$!mmz-0Yl4|CbUzD3z z0&2=&CRIa2WDU8lBq+`#MR9<4GAYWFNKp)mATx-cAq)P%8IynsCZNI;X{I>-B(I`rDh*t_qv#tR|nhH)(I2>REnkk2^%YtmZ!|qa~!97ERoSb-&*HTIgK=}b% z7#QZJ=Ei3h$Afy{xYVF{J})N~v_v0UC>a?!Czd3Frfv%|GLykmj^G*@m$}eUFwoL= zQ+x^u7O>!z#h|%e^qpqN`*&PTU5XMx+Y9`HP2w#AQj5TfUBTPQFf%cg>@*8XP0P&5 z0kr{$uoP+1J~uTtITsXbWxoHOas(aLud) z+l1Nq1jSZ7r0ELYMvLkhGuMieqQvA9P!Z;pTM%5}ip^<0#wL&s3~b^I+JivdP69C* z#ZMUH%iv8ASQHwA=Hq?x%fUI=#DO{{?SQK0J4 z7U7^2lZK|r`FWs(SB$C$#r1|ppdoNX9}Qd-Kobl+$Sfhda|80RI}@}D1e~ToWsnbO zZHZ?dXmbQs)rMF`FAPlr@(aKwfEUcd^g*2g>nVc!eTc>)a=#DR)mX9>Xzeg)j21F( z0u4IUU@-U0OD+PfS_{c9Nz4I-33g>JsYECvoFvQw@(W6H5=&A+eOb^>73_%ultT#? z#lc3P@h`t%qj*DOPz-Aqs1MMB5w!9f5{i%v0+j|Y#)afr5AZNJXkA)JVmhiJ z;2jPANm;4MC7@+{Sk+j%mF6Y8=9LsdMjp|Ikx-(_7}|@2%ojky0JUL^qTC$3N*1{s zC8Wj3!ZWWpwWtJAh$E7iTYeG9Z=mqS=RRoD-4i?p?g~0T0n{?Y<3dYFTOXnUG?_?@ zCKF^Id14)s0tW+HibX5@@{17tvRsCo_;|=vM?B_AZ*#mlLCf`^X##bGOYhxSx+DQn3||rr_bF)PQ8qJn&dA)Hx`r0Wk>BY|v_z$FW{3_@uL;CB-8$~bWG4%#^CnO9s=R0=+uB_J7^ zZeW3jNXDS8D^N+))QEM;2Gr(-o+e;u3~RADf%aZON^$gIWl+!(SNTD*8Hy7OjZs>j zuDL{+21$Nc&g?*PyQ?e6%aD0KhWO0<5EzV5OO)Sm^ zDFJPtV2Cfx0}aqH#KVSaKr-OT)?CnOEb&RHX`uO5$btrjc>mzwg3LV7qE*N+Et=}Y zw35`Kc+iS8Gzq9N5E+CaAcGKYL+LYs3_wiQ7lXD^r6!hS#3w^H#1dIr89di}{^gqGnw13!YW!vxx&{zo1}wUu zaRVNvbvAN^+JIHo5GIRiKVmfiXw?8{C?pe`GcDnB;l-KhpdkbB;4BuEcq=-~g3{uQ zc<`w#LEhLjySP}Sr}~s4K`5>Q3LBjB5Ho)^wbil0chR@H!;C= zmpgVP*q4fdJEaiYPz^-1V8F{qpq65~$P%=Q1+-r=52^&s7>K_>9Z=92N`^*|)#eaU zs19gQ7@EPGDPYfl#?rxg7}Z3~y$hfOLYzWFsEw#5TEeDHA&VWNKudjG1IjW%1rxY{ zOv}szaWIy_z|#(F5fo@O05+9~L8IKnl(NiX&|C{d9nA00vt~f2pJ2YChy|$O0y;XPs3f>F3AF4zwHS16NpgU9uwi_#aeQVbHXR6mmM3O{ zcfVu?U{h#h2-)cBSd^RrYWO-Al!BYZnVAfj`+ZOxg-0i-|A3+v>42S-(gGt_Y%Vdx zGWG&0?*hD&v3U@iYD3om9I6p>G{q&*$sDYvB7&{BqzIovEQK1DgpZiMfmoYY3R*{m z)n-%hjsd@Xm(^?C{9KTo;H6># zAX_jM8iEJNL-L{OyvuTNC`80zW-)l-pDT6)ksJ%@ErF^gP~~a_U+a(2lS+2QVHi>& z4cbcsPKd!q@z{dc!oMIj5A2Ho?_^Mu-vq>gOdW$KnXqXxG6eMt;KwPXrudhZ6qJ^@ zLZT2>c44gewg8>}20mK_q7XG#A{-4~nhG@xRSk_Nk|Fa`SREIhm|5bMUj&^b!|FJb zV9>fsxBMdC%$%IeVytRRVQPX?lk@XZuq(2FuKx%wNz6-0EJ|_1q0R_i(ST-@usPez zvl!~)pwhfN&{A4#su0t)pao%|fk~`xM?_F^PJVGJHZ_*cAQ?~!!X|47I;Y12e9jKi zEGEIS9hWvxu7ssEXu}XP9s%(qObR0zf)9X1?3je8Monj?p2eV1@Ki`unwo;mH%2Zl z@N-c?8OO}U1#K@JDEk_ky11a8@rcbn*n0k4$a$QQU1Jc1FmIsl>2o%MIthogAy^u; zQW|pHYdom`1YLt(kXVudUwK=Rnp_G#fFS@Pir$zpfK082hI+byW_km>L0ZvQ{^D8A z?`oV|oX!xRSd?s1l$e*2pBtZ4n#K?h>aOPJr6Ib0#i==I4DqQIsmW!j@CFum9V(~_ zi84k$yEZ-%vM47$xhSzX1GE^rB-ItPd=*&$WC)`Bh(!m&ZqNvN3Bp!TvnC!U24Cp_ zT?Ad08()-~o(bL=09uTnin34~^$gj>loW7IVTgxP&{iJEY2XGVbYnW4pPnC|SdyQc znQUef51tvrlrc6!lY#mSt`ce{EQ}c93o;83eoM>D10O_I6rY}7lwS%uu>(mbXh9Ox zpNUDu`8lN}so+)LkoYRefh;2i4He`i=7J0bA8rC_=|k45Lq#E*CtwcA1+Bn`TLO;K z_#)7HN4OYh}c06cG5+V&6I|L8Iq?aZZrNI51o*$o@hr&f(*bbH|Mr=cJOks$JHlV=*1t0;GjS;CO&%p^W7wIn$sJ~0K0tg#V3 zSu>OPocu)W+E64wkqh@VB=!rE;Q}DpcqBe#F9srOrl*z^7o;XRyOD|k=apg9Yr=}3E3+ozD z(0R_d>@hTTNlnf#N(7$~2RdjCmqH_Bkb}Vf4K6K6E%M8UHb-!2Fa-Mmtbw3f?CXLo zd=m@6UdL&L3EWNS>R=V1iEm;7r2h+P1mFs8tN~{TKKuk43Ah|#WC(Hu*nZTA4e-X6 zY`~!c4-l|6SL{guees|XXej~2FQAT+Qzdi>A#u75L8oORbh~C@b)F^2FCf!F$Ghfc zW@1(3V~9u#;Dd=ki&U_B7G-?j&@?dxW$m(SZf+7NV`AnQLsX5Rqq#wcJ%E?0Ive59 zX9hZS8`NeA$%m{+1NE1%n2&V0q@gKfbOGdR|MI-lBJjR@5G%zwAGA>io6kVo>Rt27 zaG4HTS_nPS!~#r13KCF}f?Jn`Pky=^=56K0F z1)#(0;=#Mra2lACm=1Pmk)dH4sBnUuh>t@#%18yMlYupv7#Rm=c86e^lyUB*2l;oRQT%4Gm>YoRx z1+lBN2udsmy8tG2ir~}|P`O8OeHpu?=D1cSVHN_QafKjo?-Df94p9Kr zY-kQys|Fd-0@o{8(s*ueE{ZPL5-;$vl>SAKc{0a5$Z>DrZas9s0X#|os;0n>g4qcj zh=*vyY8`IdJkwmkeT%%0cvi76B2^hmv!N*qM&v zcZ}f{OUD%0X+N0|ccGY%+5&(tr3U%Qz!#j7L9+p_0U22I8ksVcu%}oTIIRH9? z05moj4;nH6kM}`FF;k1c#}LGW#G`zS%;O<%a7qx3=T>|$`jhn)5e(h_V8QI6t!>=Ww9>%|O>JX4&(gIeHPF$g+$3Qj#J zMxl2MjSYfI^I(|}w0#tQT@5I8g6^|o>?}y%51cTtxe3oq9%yMJ%3=|$R^l-LvQP{()(9?85eIT1 zr#n|y%ItuZHCR?FQe-eVRe`4zp>1Mf9EyBU6sSalo<-qSR_2N|@KCn_f&v`cPr$Ak zIX##{mZ_u`L7M;IGy!%qxFmoIg6c3FHd{aoPf&M17;^I*IFT4)OSq<>R8#^D=sN2E&)3$7`vIsDiM2=uoO6m>1xm#f#L%2-ZJcl8i%Cj7J#-4fRC#u z#+gN_pa}xpD$&-Lfg9hDHj956q(CZm4afy8G{NRe{JFyrU-}}$IFxZK^z@3&JVP9* z09vDhD`ZHk25WE|nSe@8_@-}2+Ywy2fmSsJ& z8iK^C&oV674>q=eTNQYzFp^&#^HM@`ilM#?Hi(BA4O^-PI)KI_u{a~O&^5>#CW%`6 zBH#XD0U9C%b&qkXMj2^@FIj_}DhXOTgu@cN+6-L-uxmp;;RkdO8T^(hw}7%>gLu$3 zLeMl_Vh(7sSH;CKDBRO8-Zdg5*bkiPVI?`VX9!+TY3Y)hRGJPtQN%UC4HOwwuE=T; ziw$upLG~FgxT9V-9&Jfj5?LLO) z*+?TbklqfaV?aFx$Uzf*st(G$c*8p@DN{a!x8ZydnCDU5x;$ z$KX9VtS&P&fGtslZUut$icmrdc8(3CYYLt!02z$7l_@hRDFAeX9%$AsCBGbE0!qx7 zIhKGIiIHIVxp2s73Y&66(1Ih-+=)wODnYg8koiGkl$wAp5GBG$6G(3a zvM3<86zrjpFnH$zt@{TKd}zuuG=i+Cf;Jp5!!iimfkfG^1U4RSICQ%!?0i^AqJU<1 z=%7^qYNyD;#RX~|*d-|O;$u;gkqT~ELTo{mG_uUeFOSaw-9Z%(&X)1HnR)SvpnEaE z8(%Ta!`efH+zkc9CS`2=xSKdiC9R|C}C!3T$-1i zmk+vi7<8r}!~hf(M&Kz)$bAh+w@^VN5?KW7C=|VhmarBpvN~|cBDHIYG72A2QO41?51hx)oGxlflH-t zD)Ek)H#)CkfdRK8B{rB^8*` zXu*l-lRyd=4C7GMTYwiOfo@zvw#(2EI$VjUV$n;(;CNW5poS?%Q3L93f~#xDa2Qry zK8BXaZHJ)5Yc*`Z|Dxv`Ngp1Oz!Lm#q z8sUaCunc(tCNah%-zDivz#|~DQQ{Trj3c7!X%rs-O2nw$Jmdu6gBAh--pN7UXte_J zapWKeg0`@uhA)P*e2fghIXopk7jzjEsMQL-G74-piU*89lXqx4ol%-4xw(+!fuhUD z$P}FF!7bg~#LD<0@YPT8d7$+JU`wD8>|RO770v$ks2qr2R2=XT4oIJ|hW(oBtauky2 zL|7*u)&T)Wg`p+nR9Wch29S`YhQUV09*M=!^pXOeHG`&NNEwcvPp~`A9CU3lXgOph z%p~l(p_v(U16F1p=xR{V9#K#;3Y70a2O)q*dLTIxwIngLEQWWT;JawCDKs)cZ_mT_ z++tO25uBe^5>#9aK550ZA~`iR1*yLeE?rO@V&viip0G~^xfT-s$h}>x8Vn7frC=(w z6N=J725CWbtl&2{VRNlzwo7GB3TSv0i!9-DQcPVSM;9cPq~h5r4%*xeI{hT1C^4@% zEwu=u6y!=g6^b|${T!I3h3xD&@>_PG&tA{SQ3CXV4T5QYCxq3EV)BEc*trk zz-ORTWR^g}8>$miouLtU48boSH0J}E?!s*-C=KQ(gZ5WL56DDn5)yC@s3jQ=J6Drv zZHA`qMfv5B$$m&O$8U`xbRh<0b15OO8-j;lgUdmeQW8=N9jbPNE~h7;+=57Th6bS4 zDWuOwz)0A!C!mHUL8V}ih2$3mIO9@^nn4Yd!Pg!`RuaaicMBS5ThQwtqnfu3*;{7$UUqL4z?BSN2tTlHA0*S8}KJy8`!0UwIMQZ5w`4{S&0@y z&^^QmXQM?8VwVi){sNRB^f5F;ZZi7i=cPjAQH(G$2q?X9+6+xxQuB&agL4v-z~Km55Mu^88_3ls*UZ$^ z*v!=@7ksO`E7CcJI2x6NOon$_5k?yt7@4?I!DvGRaB~ZMsu7aQ$uS-gl;)v%#h`oo zAO#rK1}2J^p_v5i5>U&iIJE?JUMVO`<1_%He8aME6(zQP3{BvZJ&-yHJ^O)0!9_5N zMnenFVvJ*dK=m2y#vzOm0YV0&P^U46{Qa zL#v?cFfkosXaSp223;QxO%qs@nSjo;1|MGs8o-0P5}H-f`r6Q*1g0UNYZ48iqjA{w zhGI_AU^l}6Y6j{?QczmK++GSc0qRae$TjwmK_y6c0@iK-uiXNxMG1N2aZpomF@!C8 z%z{%(ATzR#dC-dikmpxGiz_gV1|N`#x2q7~R+a>@4(fg%LsR7H$0rjijpk%{{wuNo zT}c$5TN)2B2B$hB!{W-^r2L%Bs??%*XwM?Qh>$KrWL*#&pboVJ-B|)|`*Gf>HD0Xydkw802+lz}HGL{LZOu$qrF6%K7efey_oDlN_|O9h=t391p1O4}k( z!@!lGNsv|*xh5gaL}lis`y^K8mzEfsgJ#J=F7i)<^w%IQ3<4`qP}?66cjJ#zP-+&6&Sg=xH3R44AV2Uw1hED5KLnP(+I&d zL@*I76AQQj#t5bnf@z3gB3NeTa9ySdrU`;+j9?len1%=@f@NlgFblynK`@OGOd|x- z5Wz&SOikftnIM?P2&NH&X^3DVSY{@0156Q269m&3!8AfJ4G~NP%gh*I7J_MlU>YNs zMhK=Mf{9?686nIYJZ;Rcu)z?r59rU`;+ zj9?len1%?ZB|}b0Zh-|X>6%)?nI;IPF@kA?U>YKr2$rb@!Tr z3_vhV5KLnP(+I&dL}J1XFf)KNO%P0D1k(t?G(<2h!0FW-kzV0U6H7SL7{N3`Fbxq* z1k2O{p$ow@LNE;xOa#l!9Ind*!8ArNjSx&j1QWqBGlLsoieQ=`n8paE5rS!mU?Nzi zrf{=N5KLnP(+I&dL@*I7GZVN0rU<49f@zFk8X=g52quDMW{fZk!8AcIjS);E1k(_~ zM6k?^5N08mCJ3f6f@y?c8X}komYE^KECka8!8ArNjSx&jBqrPdGXpr&1i>^$FpUsQ zLj=iU>YHqh6pBtWoC>p3&Au&FpUvRBLveB!9=jkj1Xoam?j9OF@kA?U>YKr2$q>4 z!Yl;S1i>^$FpUsQLnJ2L05bzP(-grpK`@OGOd|x-5WzG9Cv#IoGKVuwEa6OJ1k(t? zG(<2FEK>`(E)xXP7{N3`Fbxq*1k21EZh$F*X@X!HBbY`ArXhlfV40aA%tA0t5KLnP z(+I&dL@<$A2(wJ#OcMmt7{N3`Fbxq*1k20>Zh$F*X^dbRA((~;CW2*Vj4%MfG(j+p z5lkZl(-6T#u*{4QW+9j+2&OTDX@p=JBA5u4sUh4f69m&3!8AfJ4Uw2|U1kPwrYVAH zf?ygWm_`VuA%bZNPS7TZ1Py1JSi+gc2&NH&X^3DVSf&YKr2$q>S z!T^$FpUsQLj)7SGBJUhWsG1NA((~;CW2*V4A*6fV45J9#t5bnf@z3gB3Ncd2(u7O z69m&3!8AfJ4G~NP%ghjA7J_MlU>YNsMhK=M5)*EKnE{+>ieQ=`n8paE5rS!mV48rF zw=p7l!iU>YHqh6pBtWo8aHz!bqWK`@OGOd|x- z5Wz&SOwHhCnIM?P2&NH&X^3DVu}t9xm?D@a2&OTDX@p=JBA5u4nF-u169m&3!8AfJ z4G~NP%gh*VfGL7$f?ygWm_`VuA%clunHj;&GC?qn5lkZl(-6T#u*?kM2ACq4CJ3f6 zf@y?c8X_^_2ACPZnWhM)34&>iU>YHqh6tuH{_`C{2S_u-gGtbMhY>@LbAYFzp=G=g zBHhE8CYErfF@kA?U>YKr2$rb@T$c%gX^dbRA((~;CW2*V4mZFQ!8AcIjS);E1k(_~ zM6gWF;AWX1n8paE5rS!mU?QYKr2$q=%+$<9W(-^@tLNE;x zOa#l!7;bHf@zFk z8X_^_y37pVOj88Y1i>^$Fbxq*BXE&z2uZ}omhn)QA&g~YZVnSOF@~~CjEz97c)jA1 zB0W<}Ls+^uK`@OGOd|x-5Wz&SOf3)wAehDorV)Z^h+raEX6A4MOc6{I1k)J7G(s>9 z5ljTj)C_Kx34&>iU>YHqh6pAS%M@;aDS~N&U>YNsMhK=Mf{9?6nZV65K`@OGOd|x- z5Wz&S%#7g%m?D@a2&OTDX@p=JBA5u4nGwP)1k(h;G)6Fu5KKb^6TvbwM3{wOnjo0Q z2&NH&X^6~(B|0+$gjoot34&>iU>YHqhDc0s7BB#30aFXhcnHhb1jaHnhOvwdVJuL2 z4^d}f0o7oH#4?A8nZsCy2$ms2%oM85*bK%pG=Q;;EKH!XX2vj* z8JojcpbQFeoslt2%-9gdGBkj(EDfPr4Gmx{BMSqln6VLzWo`U)3Du$*rIiv$x( zIMW!xG(s>95ljTj)B>){1i>^$FpUsQLj)7SGBbx8V2WUxAehDorV)Z^h+raEre<)n zOb|?C1k(t?G(<3wSf+3TOc6{I1k)J7G(s>95ljTj%miT;f@y+a8Y7rS2&N%|iC~!- zBg{fDO%P0D1k(t?G(<2FEHfj7SqP>Hf@zFk8X=g52quDMW{5Bg!8AcIjS);E1k(_S a2{*vZ0M0Z;Fij9lV+7L(!89~5U;qGMS;n0J -- GitLab From 8da66a35cab2de4f7ce0215c47929be624eeb03d Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 2 Dec 2021 19:05:27 -0500 Subject: [PATCH 2391/2500] cmd/compile: set PPC64's MAXWIDTH as other architectures PPC64's MAXWIDTH is set as 1<<60 whereas on other 64-bit architetures it is set as 1<<50. Set to 1<<50 for consistency. The toolchain cannot handle such large program anyway. May fix PPC64 build. Change-Id: Ic3972a089b2f14a96e4ded57ef218d763c924a6a Reviewed-on: https://go-review.googlesource.com/c/go/+/368955 Trust: Cherry Mui Trust: Dan Scales Run-TryBot: Cherry Mui TryBot-Result: Gopher Robot Reviewed-by: Dan Scales --- src/cmd/compile/internal/ppc64/galign.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/ppc64/galign.go b/src/cmd/compile/internal/ppc64/galign.go index 6f9d1407d6..20fd8cec54 100644 --- a/src/cmd/compile/internal/ppc64/galign.go +++ b/src/cmd/compile/internal/ppc64/galign.go @@ -16,7 +16,7 @@ func Init(arch *ssagen.ArchInfo) { arch.LinkArch = &ppc64.Linkppc64le } arch.REGSP = ppc64.REGSP - arch.MAXWIDTH = 1 << 60 + arch.MAXWIDTH = 1 << 50 arch.ZeroRange = zerorange arch.Ginsnop = ginsnop -- GitLab From 098599003ba78225152d22984f82f78892221dad Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 2 Dec 2021 14:52:31 -0800 Subject: [PATCH 2392/2500] builtin: document "any" and "comparable" Fixes #49927 Change-Id: I8b34cf13b3bc6338309f005648ca3ee6852927f0 Reviewed-on: https://go-review.googlesource.com/c/go/+/368954 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Robert Griesemer TryBot-Result: Gopher Robot --- src/builtin/builtin.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/builtin/builtin.go b/src/builtin/builtin.go index 01190e9900..9a94c7357d 100644 --- a/src/builtin/builtin.go +++ b/src/builtin/builtin.go @@ -91,6 +91,16 @@ type byte = uint8 // used, by convention, to distinguish character values from integer values. type rune = int32 +// any is an alias for interface{} and is equivalent to interface{} in all ways. +type any = interface{} + +// comparable is an interface that is implemented by all comparable types +// (booleans, numbers, strings, pointers, channels, interfaces, +// arrays of comparable types, structs whose fields are all comparable types). +// The comparable interface may only be used as a type parameter constraint, +// not as the type of a variable. +type comparable comparable + // iota is a predeclared identifier representing the untyped integer ordinal // number of the current const specification in a (usually parenthesized) // const declaration. It is zero-indexed. -- GitLab From a174638a5cc88eb4fccaaa699990f5626fbb0e30 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Tue, 30 Nov 2021 16:33:51 -0500 Subject: [PATCH 2393/2500] os: test that LookupEnv reports all keys found in Environ For #49886 Change-Id: Ie3a7f12a0d30ec719caf375e7be30cc4a5796c3f Reviewed-on: https://go-review.googlesource.com/c/go/+/367850 Trust: Bryan Mills Run-TryBot: Bryan Mills Reviewed-by: Ian Lance Taylor TryBot-Result: Gopher Robot --- src/os/env_test.go | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/os/env_test.go b/src/os/env_test.go index 4b860157b4..11b3b89725 100644 --- a/src/os/env_test.go +++ b/src/os/env_test.go @@ -166,3 +166,39 @@ func TestLookupEnv(t *testing.T) { t.Errorf("smallpox release failed; world remains safe but LookupEnv is broken") } } + +// On Windows, Environ was observed to report keys with a single leading "=". +// Check that they are properly reported by LookupEnv and can be set by SetEnv. +// See https://golang.org/issue/49886. +func TestEnvironConsistency(t *testing.T) { + for _, kv := range Environ() { + i := strings.Index(kv, "=") + if i == 0 { + // We observe in practice keys with a single leading "=" on Windows. + // TODO(#49886): Should we consume only the first leading "=" as part + // of the key, or parse through arbitrarily many of them until a non-=, + // or try each possible key/value boundary until LookupEnv succeeds? + i = strings.Index(kv[1:], "=") + 1 + } + if i < 0 { + t.Errorf("Environ entry missing '=': %q", kv) + } + + k := kv[:i] + v := kv[i+1:] + v2, ok := LookupEnv(k) + if ok && v == v2 { + t.Logf("LookupEnv(%q) = %q, %t", k, v2, ok) + } else { + t.Errorf("Environ contains %q, but LookupEnv(%q) = %q, %t", kv, k, v2, ok) + } + + // Since k=v is already present in the environment, + // setting it should be a no-op. + if err := Setenv(k, v); err == nil { + t.Logf("Setenv(%q, %q)", k, v) + } else { + t.Errorf("Environ contains %q, but SetEnv(%q, %q) = %q", kv, k, v, err) + } + } +} -- GitLab From 9b0de0854d5a5655890ef0b2b9052da2541182a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Geisend=C3=B6rfer?= Date: Mon, 20 Sep 2021 16:09:47 +0200 Subject: [PATCH 2394/2500] runtime: fix missing pprof labels Use gp.m.curg instead of the gp when recording cpu profiler stack traces. This ensures profiler labels are captured when systemstack or similar is executing on behalf of the current goroutine. After this there are still rare cases of samples containing the labelHog function, so more work might be needed. This patch should fix ~99% of the problem. Also change testCPUProfile interface a little to allow the new test to re-run with a longer duration if it fails during a -short run. Fixes #48577. Change-Id: I3dbc9fd5af3c513544e822acaa43055b2e00dfa9 Reviewed-on: https://go-review.googlesource.com/c/go/+/367200 Trust: Michael Pratt Trust: Bryan Mills Run-TryBot: Michael Pratt TryBot-Result: Gopher Robot Reviewed-by: Michael Pratt --- src/runtime/cpuprof.go | 11 +- src/runtime/pprof/pprof_test.go | 227 +++++++++++++++++++++++--------- src/runtime/proc.go | 9 +- 3 files changed, 177 insertions(+), 70 deletions(-) diff --git a/src/runtime/cpuprof.go b/src/runtime/cpuprof.go index c81ab710c2..6076564716 100644 --- a/src/runtime/cpuprof.go +++ b/src/runtime/cpuprof.go @@ -89,7 +89,7 @@ func SetCPUProfileRate(hz int) { // held at the time of the signal, nor can it use substantial amounts // of stack. //go:nowritebarrierrec -func (p *cpuProfile) add(gp *g, stk []uintptr) { +func (p *cpuProfile) add(tagPtr *unsafe.Pointer, stk []uintptr) { // Simple cas-lock to coordinate with setcpuprofilerate. for !atomic.Cas(&prof.signalLock, 0, 1) { osyield() @@ -104,15 +104,6 @@ func (p *cpuProfile) add(gp *g, stk []uintptr) { // because otherwise its write barrier behavior may not // be correct. See the long comment there before // changing the argument here. - // - // Note: it can happen on Windows, where we are calling - // p.add with a gp that is not the current g, that gp is nil, - // meaning we interrupted a system thread with no g. - // Avoid faulting in that case. - var tagPtr *unsafe.Pointer - if gp != nil { - tagPtr = &gp.labels - } cpuprof.log.write(tagPtr, nanotime(), hdr[:], stk) } diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go index d9be00d030..e32928b347 100644 --- a/src/runtime/pprof/pprof_test.go +++ b/src/runtime/pprof/pprof_test.go @@ -93,14 +93,16 @@ func avoidFunctions() []string { } func TestCPUProfile(t *testing.T) { - testCPUProfile(t, stackContains, []string{"runtime/pprof.cpuHog1"}, avoidFunctions(), func(dur time.Duration) { + matches := matchAndAvoidStacks(stackContains, []string{"runtime/pprof.cpuHog1"}, avoidFunctions()) + testCPUProfile(t, matches, func(dur time.Duration) { cpuHogger(cpuHog1, &salt1, dur) }) } func TestCPUProfileMultithreaded(t *testing.T) { defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2)) - testCPUProfile(t, stackContains, []string{"runtime/pprof.cpuHog1", "runtime/pprof.cpuHog2"}, avoidFunctions(), func(dur time.Duration) { + matches := matchAndAvoidStacks(stackContains, []string{"runtime/pprof.cpuHog1", "runtime/pprof.cpuHog2"}, avoidFunctions()) + testCPUProfile(t, matches, func(dur time.Duration) { c := make(chan int) go func() { cpuHogger(cpuHog1, &salt1, dur) @@ -167,7 +169,8 @@ func TestCPUProfileMultithreadMagnitude(t *testing.T) { runtime.GC() var cpuTime1, cpuTimeN time.Duration - p := testCPUProfile(t, stackContains, []string{"runtime/pprof.cpuHog1", "runtime/pprof.cpuHog3"}, avoidFunctions(), func(dur time.Duration) { + matches := matchAndAvoidStacks(stackContains, []string{"runtime/pprof.cpuHog1", "runtime/pprof.cpuHog3"}, avoidFunctions()) + p := testCPUProfile(t, matches, func(dur time.Duration) { cpuTime1 = diffCPUTime(t, func() { // Consume CPU in one goroutine cpuHogger(cpuHog1, &salt1, dur) @@ -272,7 +275,8 @@ func TestCPUProfileInlining(t *testing.T) { t.Skip("Can't determine whether inlinedCallee was inlined into inlinedCaller.") } - p := testCPUProfile(t, stackContains, []string{"runtime/pprof.inlinedCallee", "runtime/pprof.inlinedCaller"}, avoidFunctions(), func(dur time.Duration) { + matches := matchAndAvoidStacks(stackContains, []string{"runtime/pprof.inlinedCallee", "runtime/pprof.inlinedCaller"}, avoidFunctions()) + p := testCPUProfile(t, matches, func(dur time.Duration) { cpuHogger(inlinedCaller, &salt1, dur) }) @@ -322,7 +326,8 @@ func inlinedCalleeDump(pcs []uintptr) { } func TestCPUProfileRecursion(t *testing.T) { - p := testCPUProfile(t, stackContains, []string{"runtime/pprof.inlinedCallee", "runtime/pprof.recursionCallee", "runtime/pprof.recursionCaller"}, avoidFunctions(), func(dur time.Duration) { + matches := matchAndAvoidStacks(stackContains, []string{"runtime/pprof.inlinedCallee", "runtime/pprof.recursionCallee", "runtime/pprof.recursionCaller"}, avoidFunctions()) + p := testCPUProfile(t, matches, func(dur time.Duration) { cpuHogger(recursionCaller, &salt1, dur) }) @@ -407,7 +412,7 @@ func cpuProfilingBroken() bool { // testCPUProfile runs f under the CPU profiler, checking for some conditions specified by need, // as interpreted by matches, and returns the parsed profile. -func testCPUProfile(t *testing.T, matches matchFunc, need []string, avoid []string, f func(dur time.Duration)) *profile.Profile { +func testCPUProfile(t *testing.T, matches profileMatchFunc, f func(dur time.Duration)) *profile.Profile { switch runtime.GOOS { case "darwin": out, err := exec.Command("uname", "-a").CombinedOutput() @@ -448,7 +453,7 @@ func testCPUProfile(t *testing.T, matches matchFunc, need []string, avoid []stri f(duration) StopCPUProfile() - if p, ok := profileOk(t, matches, need, avoid, prof, duration); ok { + if p, ok := profileOk(t, matches, prof, duration); ok { return p } @@ -504,15 +509,11 @@ func stackContains(spec string, count uintptr, stk []*profile.Location, labels m return false } -type matchFunc func(spec string, count uintptr, stk []*profile.Location, labels map[string][]string) bool +type sampleMatchFunc func(spec string, count uintptr, stk []*profile.Location, labels map[string][]string) bool -func profileOk(t *testing.T, matches matchFunc, need []string, avoid []string, prof bytes.Buffer, duration time.Duration) (_ *profile.Profile, ok bool) { +func profileOk(t *testing.T, matches profileMatchFunc, prof bytes.Buffer, duration time.Duration) (_ *profile.Profile, ok bool) { ok = true - // Check that profile is well formed, contains 'need', and does not contain - // anything from 'avoid'. - have := make([]uintptr, len(need)) - avoidSamples := make([]uintptr, len(avoid)) var samples uintptr var buf bytes.Buffer p := parseProfile(t, prof.Bytes(), func(count uintptr, stk []*profile.Location, labels map[string][]string) { @@ -520,20 +521,6 @@ func profileOk(t *testing.T, matches matchFunc, need []string, avoid []string, p fprintStack(&buf, stk) fmt.Fprintf(&buf, " labels: %v\n", labels) samples += count - for i, spec := range need { - if matches(spec, count, stk, labels) { - have[i] += count - } - } - for i, name := range avoid { - for _, loc := range stk { - for _, line := range loc.Line { - if strings.Contains(line.Function.Name, name) { - avoidSamples[i] += count - } - } - } - } fmt.Fprintf(&buf, "\n") }) t.Logf("total %d CPU profile samples collected:\n%s", samples, buf.String()) @@ -556,39 +543,77 @@ func profileOk(t *testing.T, matches matchFunc, need []string, avoid []string, p ok = false } - for i, name := range avoid { - bad := avoidSamples[i] - if bad != 0 { - t.Logf("found %d samples in avoid-function %s\n", bad, name) - ok = false - } + if matches != nil && !matches(t, p) { + ok = false } - if len(need) == 0 { - return p, ok - } + return p, ok +} - var total uintptr - for i, name := range need { - total += have[i] - t.Logf("%s: %d\n", name, have[i]) - } - if total == 0 { - t.Logf("no samples in expected functions") - ok = false - } - // We'd like to check a reasonable minimum, like - // total / len(have) / smallconstant, but this test is - // pretty flaky (see bug 7095). So we'll just test to - // make sure we got at least one sample. - min := uintptr(1) - for i, name := range need { - if have[i] < min { - t.Logf("%s has %d samples out of %d, want at least %d, ideally %d", name, have[i], total, min, total/uintptr(len(have))) +type profileMatchFunc func(*testing.T, *profile.Profile) bool + +func matchAndAvoidStacks(matches sampleMatchFunc, need []string, avoid []string) profileMatchFunc { + return func(t *testing.T, p *profile.Profile) (ok bool) { + ok = true + + // Check that profile is well formed, contains 'need', and does not contain + // anything from 'avoid'. + have := make([]uintptr, len(need)) + avoidSamples := make([]uintptr, len(avoid)) + + for _, sample := range p.Sample { + count := uintptr(sample.Value[0]) + for i, spec := range need { + if matches(spec, count, sample.Location, sample.Label) { + have[i] += count + } + } + for i, name := range avoid { + for _, loc := range sample.Location { + for _, line := range loc.Line { + if strings.Contains(line.Function.Name, name) { + avoidSamples[i] += count + } + } + } + } + } + + for i, name := range avoid { + bad := avoidSamples[i] + if bad != 0 { + t.Logf("found %d samples in avoid-function %s\n", bad, name) + ok = false + } + } + + if len(need) == 0 { + return + } + + var total uintptr + for i, name := range need { + total += have[i] + t.Logf("%s: %d\n", name, have[i]) + } + if total == 0 { + t.Logf("no samples in expected functions") ok = false } + + // We'd like to check a reasonable minimum, like + // total / len(have) / smallconstant, but this test is + // pretty flaky (see bug 7095). So we'll just test to + // make sure we got at least one sample. + min := uintptr(1) + for i, name := range need { + if have[i] < min { + t.Logf("%s has %d samples out of %d, want at least %d, ideally %d", name, have[i], total, min, total/uintptr(len(have))) + ok = false + } + } + return } - return p, ok } // Fork can hang if preempted with signals frequently enough (see issue 5517). @@ -704,7 +729,7 @@ func fprintStack(w io.Writer, stk []*profile.Location) { // Test that profiling of division operations is okay, especially on ARM. See issue 6681. func TestMathBigDivide(t *testing.T) { - testCPUProfile(t, nil, nil, nil, func(duration time.Duration) { + testCPUProfile(t, nil, func(duration time.Duration) { t := time.After(duration) pi := new(big.Int) for { @@ -733,7 +758,8 @@ func stackContainsAll(spec string, count uintptr, stk []*profile.Location, label } func TestMorestack(t *testing.T) { - testCPUProfile(t, stackContainsAll, []string{"runtime.newstack,runtime/pprof.growstack"}, avoidFunctions(), func(duration time.Duration) { + matches := matchAndAvoidStacks(stackContainsAll, []string{"runtime.newstack,runtime/pprof.growstack"}, avoidFunctions()) + testCPUProfile(t, matches, func(duration time.Duration) { t := time.After(duration) c := make(chan bool) for { @@ -1364,7 +1390,8 @@ func stackContainsLabeled(spec string, count uintptr, stk []*profile.Location, l } func TestCPUProfileLabel(t *testing.T) { - testCPUProfile(t, stackContainsLabeled, []string{"runtime/pprof.cpuHogger;key=value"}, avoidFunctions(), func(dur time.Duration) { + matches := matchAndAvoidStacks(stackContainsLabeled, []string{"runtime/pprof.cpuHogger;key=value"}, avoidFunctions()) + testCPUProfile(t, matches, func(dur time.Duration) { Do(context.Background(), Labels("key", "value"), func(context.Context) { cpuHogger(cpuHog1, &salt1, dur) }) @@ -1375,7 +1402,8 @@ func TestLabelRace(t *testing.T) { // Test the race detector annotations for synchronization // between settings labels and consuming them from the // profile. - testCPUProfile(t, stackContainsLabeled, []string{"runtime/pprof.cpuHogger;key=value"}, nil, func(dur time.Duration) { + matches := matchAndAvoidStacks(stackContainsLabeled, []string{"runtime/pprof.cpuHogger;key=value"}, nil) + testCPUProfile(t, matches, func(dur time.Duration) { start := time.Now() var wg sync.WaitGroup for time.Since(start) < dur { @@ -1394,6 +1422,86 @@ func TestLabelRace(t *testing.T) { }) } +// TestLabelSystemstack makes sure CPU profiler samples of goroutines running +// on systemstack include the correct pprof labels. See issue #48577 +func TestLabelSystemstack(t *testing.T) { + matchBasics := matchAndAvoidStacks(stackContainsLabeled, []string{"runtime.systemstack;key=value"}, avoidFunctions()) + matches := func(t *testing.T, prof *profile.Profile) bool { + if !matchBasics(t, prof) { + return false + } + + var withLabel, withoutLabel int64 + for _, s := range prof.Sample { + var systemstack, labelHog bool + for _, loc := range s.Location { + for _, l := range loc.Line { + switch l.Function.Name { + case "runtime.systemstack": + systemstack = true + case "runtime/pprof.labelHog": + labelHog = true + } + } + } + + if systemstack && labelHog { + if s.Label != nil && contains(s.Label["key"], "value") { + withLabel += s.Value[0] + } else { + withoutLabel += s.Value[0] + } + } + } + + // ratio on 2019 Intel MBP before/after CL 351751 for n=30 runs: + // before: mean=0.013 stddev=0.013 min=0.000 max=0.039 + // after : mean=0.996 stddev=0.007 min=0.967 max=1.000 + // + // TODO: Figure out why some samples (containing gcWriteBarrier, gcStart) + // still have labelHog without labels. Once fixed this test case can be + // simplified to just check that all samples containing labelHog() have the + // label, and no other samples do. + ratio := float64(withLabel) / float64((withLabel + withoutLabel)) + if ratio < 0.9 { + t.Logf("only %.1f%% of labelHog(systemstack()) samples have label", ratio*100) + return false + } + return true + } + + testCPUProfile(t, matches, func(dur time.Duration) { + Do(context.Background(), Labels("key", "value"), func(context.Context) { + var wg sync.WaitGroup + stop := make(chan struct{}) + for i := 0; i < runtime.GOMAXPROCS(0); i++ { + wg.Add(1) + go func() { + defer wg.Done() + labelHog(stop) + }() + } + + time.Sleep(dur) + close(stop) + wg.Wait() + }) + }) +} + +// labelHog is designed to burn CPU time in a way that a high number of CPU +// samples end up running on systemstack. +func labelHog(stop chan struct{}) { + for i := 0; ; i++ { + select { + case <-stop: + return + default: + fmt.Fprintf(io.Discard, "%d", i) + } + } +} + // Check that there is no deadlock when the program receives SIGPROF while in // 64bit atomics' critical section. Used to happen on mips{,le}. See #20146. func TestAtomicLoadStore64(t *testing.T) { @@ -1686,7 +1794,8 @@ func TestTimeVDSO(t *testing.T) { testenv.SkipFlaky(t, 48655) } - p := testCPUProfile(t, stackContains, []string{"time.now"}, avoidFunctions(), func(dur time.Duration) { + matches := matchAndAvoidStacks(stackContains, []string{"time.now"}, avoidFunctions()) + p := testCPUProfile(t, matches, func(dur time.Duration) { t0 := time.Now() for { t := time.Now() diff --git a/src/runtime/proc.go b/src/runtime/proc.go index f375b67981..7509f7632f 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -4726,7 +4726,14 @@ func sigprof(pc, sp, lr uintptr, gp *g, mp *m) { } if prof.hz != 0 { - cpuprof.add(gp, stk[:n]) + // Note: it can happen on Windows that we interrupted a system thread + // with no g, so gp could nil. The other nil checks are done out of + // caution, but not expected to be nil in practice. + var tagPtr *unsafe.Pointer + if gp != nil && gp.m != nil && gp.m.curg != nil { + tagPtr = &gp.m.curg.labels + } + cpuprof.add(tagPtr, stk[:n]) } getg().m.mallocing-- } -- GitLab From 29483b3dae9bc043887b5372aefe0e53194b9ce7 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sat, 27 Nov 2021 10:33:59 -0800 Subject: [PATCH 2395/2500] test: re-enable a bunch of tests with types2 Enable a bunch of types2-related error tests to run successfully, so they no longer have to be disabled in run.go. - directive.go: split it into directive.go and directive2.go, since the possible errors are now split across the parser and noder2, so they can't all be reported in one file. - linkname2.go: similarly, split it into linkname2.go and linkname3.go for the same reason. - issue16428.go, issue17645.go, issue47201.dir/bo.go: handle slightly different wording by types2 - issue5609.go: handle slight different error (array length must be integer vs. array bound too large). - float_lit3.go: handle slightly different wording (overflows float vs cannot convert to float) I purposely didn't try to fix tests yet where there are extra or missing errors on different lines, since that is not easy to make work for both -G=3 and -G=0. In a later change, will flip to make the types2 version match correctly, vs. the -G=0 version. Change-Id: I6079ff258e3b90146335b9995764e3b1b56cda59 Reviewed-on: https://go-review.googlesource.com/c/go/+/368455 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Gopher Robot Reviewed-by: Matthew Dempsky --- .../compile/internal/types2/stdlib_test.go | 2 + src/go/types/stdlib_test.go | 2 + test/directive.go | 37 +---------- test/directive2.go | 63 ++++++++++++++++++ test/fixedbugs/issue16428.go | 2 +- test/fixedbugs/issue17645.go | 2 +- test/fixedbugs/issue47201.dir/b.go | 2 +- test/fixedbugs/issue5609.go | 2 +- test/float_lit3.go | 8 +-- test/linkname2.go | 6 -- test/linkname3.go | 25 +++++++ test/run.go | 18 ++--- test/shift1.go | 66 +++++++++---------- 13 files changed, 142 insertions(+), 93 deletions(-) create mode 100644 test/directive2.go create mode 100644 test/linkname3.go diff --git a/src/cmd/compile/internal/types2/stdlib_test.go b/src/cmd/compile/internal/types2/stdlib_test.go index 5ac01ac253..551611da55 100644 --- a/src/cmd/compile/internal/types2/stdlib_test.go +++ b/src/cmd/compile/internal/types2/stdlib_test.go @@ -165,9 +165,11 @@ func TestStdTest(t *testing.T) { testTestDir(t, filepath.Join(runtime.GOROOT(), "test"), "cmplxdivide.go", // also needs file cmplxdivide1.go - ignore "directive.go", // tests compiler rejection of bad directive placement - ignore + "directive2.go", // tests compiler rejection of bad directive placement - ignore "embedfunc.go", // tests //go:embed "embedvers.go", // tests //go:embed "linkname2.go", // types2 doesn't check validity of //go:xxx directives + "linkname3.go", // types2 doesn't check validity of //go:xxx directives ) } diff --git a/src/go/types/stdlib_test.go b/src/go/types/stdlib_test.go index c56e0ba428..687b80540a 100644 --- a/src/go/types/stdlib_test.go +++ b/src/go/types/stdlib_test.go @@ -166,9 +166,11 @@ func TestStdTest(t *testing.T) { testTestDir(t, filepath.Join(runtime.GOROOT(), "test"), "cmplxdivide.go", // also needs file cmplxdivide1.go - ignore "directive.go", // tests compiler rejection of bad directive placement - ignore + "directive2.go", // tests compiler rejection of bad directive placement - ignore "embedfunc.go", // tests //go:embed "embedvers.go", // tests //go:embed "linkname2.go", // go/types doesn't check validity of //go:xxx directives + "linkname3.go", // go/types doesn't check validity of //go:xxx directives ) } diff --git a/test/directive.go b/test/directive.go index 37781c30d5..147e81db2c 100644 --- a/test/directive.go +++ b/test/directive.go @@ -6,16 +6,11 @@ // Verify that misplaced directives are diagnosed. -// ok -//go:build !ignore - //go:noinline // ERROR "misplaced compiler directive" //go:noinline // ERROR "misplaced compiler directive" package main -//go:build bad // ERROR "misplaced compiler directive" - //go:nosplit func f1() {} @@ -38,11 +33,10 @@ type T int //go:notinheap type T1 int -//go:notinheap // ERROR "misplaced compiler directive" type ( //go:notinheap //go:noinline // ERROR "misplaced compiler directive" - T2 int //go:notinheap // ERROR "misplaced compiler directive" + T2 int T2b int //go:notinheap T2c int @@ -50,40 +44,20 @@ type ( T3 int ) -//go:notinheap // ERROR "misplaced compiler directive" -type ( - //go:notinheap - T4 int -) - -//go:notinheap // ERROR "misplaced compiler directive" -type () - -type T5 int - -func g() {} //go:noinline // ERROR "misplaced compiler directive" - -// ok: attached to f (duplicated yes, but ok) -//go:noinline - //go:noinline func f() { - //go:noinline // ERROR "misplaced compiler directive" x := 1 - //go:noinline // ERROR "misplaced compiler directive" { - _ = x //go:noinline // ERROR "misplaced compiler directive" + _ = x } //go:noinline // ERROR "misplaced compiler directive" - var y int //go:noinline // ERROR "misplaced compiler directive" - //go:noinline // ERROR "misplaced compiler directive" + var y int _ = y //go:noinline // ERROR "misplaced compiler directive" const c = 1 - //go:noinline // ERROR "misplaced compiler directive" _ = func() {} //go:noinline // ERROR "misplaced compiler directive" @@ -95,8 +69,3 @@ func f() { // someday there might be a directive that can apply to type aliases, but go:notinheap doesn't. //go:notinheap // ERROR "misplaced compiler directive" type T6 = int - -// EOF -//go:noinline // ERROR "misplaced compiler directive" - -//go:build bad // ERROR "misplaced compiler directive" diff --git a/test/directive2.go b/test/directive2.go new file mode 100644 index 0000000000..e73e11235d --- /dev/null +++ b/test/directive2.go @@ -0,0 +1,63 @@ +// errorcheck + +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Verify that misplaced directives are diagnosed. + +// ok +//go:build !ignore + +package main + +//go:build bad // ERROR "misplaced compiler directive" + +//go:notinheap // ERROR "misplaced compiler directive" +type ( + T2 int //go:notinheap // ERROR "misplaced compiler directive" + T2b int + T2c int + T3 int +) + +//go:notinheap // ERROR "misplaced compiler directive" +type ( + //go:notinheap + T4 int +) + +//go:notinheap // ERROR "misplaced compiler directive" +type () + +type T5 int + +func g() {} //go:noinline // ERROR "misplaced compiler directive" + +// ok: attached to f (duplicated yes, but ok) +//go:noinline + +//go:noinline +func f() { + //go:noinline // ERROR "misplaced compiler directive" + x := 1 + + //go:noinline // ERROR "misplaced compiler directive" + { + _ = x //go:noinline // ERROR "misplaced compiler directive" + } + var y int //go:noinline // ERROR "misplaced compiler directive" + //go:noinline // ERROR "misplaced compiler directive" + _ = y + + const c = 1 + + _ = func() {} + + // ok: + //go:notinheap + type T int +} + +// EOF +//go:noinline // ERROR "misplaced compiler directive" diff --git a/test/fixedbugs/issue16428.go b/test/fixedbugs/issue16428.go index 5696d186c7..91e1079959 100644 --- a/test/fixedbugs/issue16428.go +++ b/test/fixedbugs/issue16428.go @@ -7,6 +7,6 @@ package p var ( - b = [...]byte("abc") // ERROR "outside of array literal" + b = [...]byte("abc") // ERROR "outside of array literal|outside a composite literal" s = len(b) ) diff --git a/test/fixedbugs/issue17645.go b/test/fixedbugs/issue17645.go index bb34e4ee97..111fa81e13 100644 --- a/test/fixedbugs/issue17645.go +++ b/test/fixedbugs/issue17645.go @@ -12,5 +12,5 @@ type Foo struct { func main() { var s []int - var _ string = append(s, Foo{""}) // ERROR "cannot use .. \(type untyped string\) as type int in field value|incompatible type" "cannot use Foo{...} \(type Foo\) as type int in append" "cannot use append\(s\, Foo{...}\) \(type \[\]int\) as type string in assignment" + var _ string = append(s, Foo{""}) // ERROR "cannot use .. \(.*untyped string.*\) as .*int.*|incompatible type" "cannot use Foo{.*} \(.*type Foo\) as type int in .*append" "cannot use append\(s\, Foo{.*}\) \(.*type \[\]int\) as type string in (assignment|variable declaration)" } diff --git a/test/fixedbugs/issue47201.dir/b.go b/test/fixedbugs/issue47201.dir/b.go index 5fd0635af2..ae3ff3f2b8 100644 --- a/test/fixedbugs/issue47201.dir/b.go +++ b/test/fixedbugs/issue47201.dir/b.go @@ -4,6 +4,6 @@ package main -func Println() {} // ERROR "Println redeclared in this block" +func Println() {} // ERROR "Println redeclared in this block|Println already declared" func main() {} diff --git a/test/fixedbugs/issue5609.go b/test/fixedbugs/issue5609.go index ea770b4865..a39d3fb0c6 100644 --- a/test/fixedbugs/issue5609.go +++ b/test/fixedbugs/issue5609.go @@ -10,4 +10,4 @@ package pkg const Large uint64 = 18446744073709551615 -var foo [Large]uint64 // ERROR "array bound is too large|array bound overflows" +var foo [Large]uint64 // ERROR "array bound is too large|array bound overflows|array length.*must be integer" diff --git a/test/float_lit3.go b/test/float_lit3.go index 850d02c9c7..37a1289fb9 100644 --- a/test/float_lit3.go +++ b/test/float_lit3.go @@ -29,19 +29,19 @@ const ( var x = []interface{}{ float32(max32 + ulp32/2 - 1), // ok float32(max32 + ulp32/2 - two128/two256), // ok - float32(max32 + ulp32/2), // ERROR "constant 3\.40282e\+38 overflows float32" + float32(max32 + ulp32/2), // ERROR "constant 3\.40282e\+38 overflows float32|cannot convert.*to type float32" float32(-max32 - ulp32/2 + 1), // ok float32(-max32 - ulp32/2 + two128/two256), // ok - float32(-max32 - ulp32/2), // ERROR "constant -3\.40282e\+38 overflows float32" + float32(-max32 - ulp32/2), // ERROR "constant -3\.40282e\+38 overflows float32|cannot convert.*to type float32" // If the compiler's internal floating point representation // is shorter than 1024 bits, it cannot distinguish max64+ulp64/2-1 and max64+ulp64/2. float64(max64 + ulp64/2 - two1024/two256), // ok float64(max64 + ulp64/2 - 1), // ok - float64(max64 + ulp64/2), // ERROR "constant 1\.79769e\+308 overflows float64" + float64(max64 + ulp64/2), // ERROR "constant 1\.79769e\+308 overflows float64|cannot convert.*to type float64" float64(-max64 - ulp64/2 + two1024/two256), // ok float64(-max64 - ulp64/2 + 1), // ok - float64(-max64 - ulp64/2), // ERROR "constant -1\.79769e\+308 overflows float64" + float64(-max64 - ulp64/2), // ERROR "constant -1\.79769e\+308 overflows float64|cannot convert.*to type float64" } diff --git a/test/linkname2.go b/test/linkname2.go index cb7f9be345..5eb250f9c4 100644 --- a/test/linkname2.go +++ b/test/linkname2.go @@ -16,12 +16,6 @@ var x, y int //go:linkname x ok // ERROR "//go:linkname requires linkname argument or -p compiler flag" -// ERROR "//go:linkname must refer to declared function or variable" -// ERROR "//go:linkname must refer to declared function or variable" -// ERROR "duplicate //go:linkname for x" //line linkname2.go:18 //go:linkname y -//go:linkname nonexist nonexist -//go:linkname t notvarfunc -//go:linkname x duplicate diff --git a/test/linkname3.go b/test/linkname3.go new file mode 100644 index 0000000000..df110cd064 --- /dev/null +++ b/test/linkname3.go @@ -0,0 +1,25 @@ +// errorcheck + +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Tests that errors are reported for misuse of linkname. +package p + +import _ "unsafe" + +type t int + +var x, y int + +//go:linkname x ok + +// ERROR "//go:linkname must refer to declared function or variable" +// ERROR "//go:linkname must refer to declared function or variable" +// ERROR "duplicate //go:linkname for x" + +//line linkname3.go:18 +//go:linkname nonexist nonexist +//go:linkname t notvarfunc +//go:linkname x duplicate diff --git a/test/run.go b/test/run.go index c6e82891da..e17d9729bc 100644 --- a/test/run.go +++ b/test/run.go @@ -2115,14 +2115,11 @@ func overlayDir(dstRoot, srcRoot string) error { // List of files that the compiler cannot errorcheck with the new typechecker (compiler -G option). // Temporary scaffolding until we pass all the tests at which point this map can be removed. var types2Failures = setOf( - "directive.go", // misplaced compiler directive checks - "float_lit3.go", // types2 reports extra errors "import1.go", // types2 reports extra errors "import6.go", // issue #43109 "initializerr.go", // types2 reports extra errors - "linkname2.go", // error reported by noder (not running for types2 errorcheck test) "notinheap.go", // types2 doesn't report errors about conversions that are invalid due to //go:notinheap - "shift1.go", // issue #42989 + "shift1.go", // mostly just different wording, but reports two new errors. "typecheck.go", // invalid function is not causing errors when called "fixedbugs/bug176.go", // types2 reports all errors (pref: types2) @@ -2138,11 +2135,9 @@ var types2Failures = setOf( "fixedbugs/issue11610.go", // types2 not run after syntax errors "fixedbugs/issue11614.go", // types2 reports an extra error "fixedbugs/issue14520.go", // missing import path error by types2 - "fixedbugs/issue16428.go", // types2 reports two instead of one error "fixedbugs/issue17038.go", // types2 doesn't report a follow-on error (pref: types2) - "fixedbugs/issue17645.go", // multiple errors on same line "fixedbugs/issue18331.go", // missing error about misuse of //go:noescape (irgen needs code from noder) - "fixedbugs/issue18419.go", // types2 reports + "fixedbugs/issue18419.go", // types2 reports no field or method member, but should say unexported "fixedbugs/issue19012.go", // multiple errors on same line "fixedbugs/issue20233.go", // types2 reports two instead of one error (pref: compiler) "fixedbugs/issue20245.go", // types2 reports two instead of one error (pref: compiler) @@ -2156,8 +2151,6 @@ var types2Failures = setOf( "fixedbugs/issue4232.go", // types2 reports (correct) extra errors "fixedbugs/issue4452.go", // types2 reports (correct) extra errors "fixedbugs/issue4510.go", // types2 reports different (but ok) line numbers - "fixedbugs/issue47201.go", // types2 spells the error message differently - "fixedbugs/issue5609.go", // types2 needs a better error message "fixedbugs/issue7525b.go", // types2 reports init cycle error on different line - ok otherwise "fixedbugs/issue7525c.go", // types2 reports init cycle error on different line - ok otherwise "fixedbugs/issue7525d.go", // types2 reports init cycle error on different line - ok otherwise @@ -2176,9 +2169,10 @@ var g3Failures = setOf( ) var unifiedFailures = setOf( - "closure3.go", // unified IR numbers closures differently than -d=inlfuncswithclosures - "escape4.go", // unified IR can inline f5 and f6; test doesn't expect this - "inline.go", // unified IR reports function literal diagnostics on different lines than -d=inlfuncswithclosures + "closure3.go", // unified IR numbers closures differently than -d=inlfuncswithclosures + "escape4.go", // unified IR can inline f5 and f6; test doesn't expect this + "inline.go", // unified IR reports function literal diagnostics on different lines than -d=inlfuncswithclosures + "linkname3.go", // unified IR is missing some linkname errors "fixedbugs/issue42284.go", // prints "T(0) does not escape", but test expects "a.I(a.T(0)) does not escape" "fixedbugs/issue7921.go", // prints "… escapes to heap", but test expects "string(…) escapes to heap" diff --git a/test/shift1.go b/test/shift1.go index d6a6c38839..0dae49a74d 100644 --- a/test/shift1.go +++ b/test/shift1.go @@ -25,7 +25,7 @@ var ( var ( e1 = g(2.0 << s) // ERROR "invalid|shift of non-integer operand" f1 = h(2 << s) // ERROR "invalid" - g1 int64 = 1.1 << s // ERROR "truncated" + g1 int64 = 1.1 << s // ERROR "truncated|must be integer" ) // constant shift expressions @@ -44,7 +44,7 @@ var ( b3 = 1< Date: Fri, 3 Dec 2021 09:04:26 -0500 Subject: [PATCH 2396/2500] doc/go1.18: reorganize runtime/compiler a little For #47694. Change-Id: Iedf85f522f7c79ae0a61b4fc1f2f092cf7b613df Reviewed-on: https://go-review.googlesource.com/c/go/+/368696 Trust: Austin Clements Reviewed-by: Jeremy Faller --- doc/go1.18.html | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 2ea8e08423..3e7de64121 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -76,15 +76,6 @@ proposal.

  • The new factory function diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go index 38fc25c74d..aacbb25b3b 100644 --- a/src/cmd/compile/internal/types2/check.go +++ b/src/cmd/compile/internal/types2/check.go @@ -494,7 +494,7 @@ func (check *Checker) recordInstance(expr syntax.Expr, targs []Type, typ Type) { assert(ident != nil) assert(typ != nil) if m := check.Instances; m != nil { - m[ident] = Instance{NewTypeList(targs), typ} + m[ident] = Instance{newTypeList(targs), typ} } } diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index f9423dd70e..cda6c7baf4 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -77,7 +77,7 @@ func (check *Checker) instance(pos syntax.Pos, orig Type, targs []Type, ctxt *Co case *Named: tname := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil) named := check.newNamed(tname, orig, nil, nil, nil) // underlying, tparams, and methods are set when named is resolved - named.targs = NewTypeList(targs) + named.targs = newTypeList(targs) named.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, []*Func) { return expandNamed(ctxt, n, pos) } diff --git a/src/cmd/compile/internal/types2/typelists.go b/src/cmd/compile/internal/types2/typelists.go index ababe85909..0b77edbde2 100644 --- a/src/cmd/compile/internal/types2/typelists.go +++ b/src/cmd/compile/internal/types2/typelists.go @@ -29,8 +29,8 @@ func (l *TypeParamList) list() []*TypeParam { // TypeList holds a list of types. type TypeList struct{ types []Type } -// NewTypeList returns a new TypeList with the types in list. -func NewTypeList(list []Type) *TypeList { +// newTypeList returns a new TypeList with the types in list. +func newTypeList(list []Type) *TypeList { if len(list) == 0 { return nil } diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 56a7dcd203..9121c2c1f6 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -442,7 +442,7 @@ func (check *Checker) instantiatedType(x syntax.Expr, xlist []syntax.Expr, def * if inst == nil { tname := NewTypeName(x.Pos(), orig.obj.pkg, orig.obj.name, nil) inst = check.newNamed(tname, orig, nil, nil, nil) // underlying, methods and tparams are set when named is resolved - inst.targs = NewTypeList(targs) + inst.targs = newTypeList(targs) inst = ctxt.update(h, orig, targs, inst).(*Named) } def.setUnderlying(inst) @@ -456,7 +456,7 @@ func (check *Checker) instantiatedType(x syntax.Expr, xlist []syntax.Expr, def * // be set to Typ[Invalid] in expandNamed. inferred = check.infer(x.Pos(), tparams, targs, nil, nil) if len(inferred) > len(targs) { - inst.targs = NewTypeList(inferred) + inst.targs = newTypeList(inferred) } } diff --git a/src/go/types/check.go b/src/go/types/check.go index 38508c77a9..d967c0bd25 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -487,7 +487,7 @@ func (check *Checker) recordInstance(expr ast.Expr, targs []Type, typ Type) { assert(ident != nil) assert(typ != nil) if m := check.Instances; m != nil { - m[ident] = Instance{NewTypeList(targs), typ} + m[ident] = Instance{newTypeList(targs), typ} } } diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 597a6da624..e91d08cc5e 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -77,7 +77,7 @@ func (check *Checker) instance(pos token.Pos, orig Type, targs []Type, ctxt *Con case *Named: tname := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil) named := check.newNamed(tname, orig, nil, nil, nil) // underlying, tparams, and methods are set when named is resolved - named.targs = NewTypeList(targs) + named.targs = newTypeList(targs) named.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, []*Func) { return expandNamed(ctxt, n, pos) } diff --git a/src/go/types/typelists.go b/src/go/types/typelists.go index ba74b8d45a..aea19e946d 100644 --- a/src/go/types/typelists.go +++ b/src/go/types/typelists.go @@ -29,8 +29,8 @@ func (l *TypeParamList) list() []*TypeParam { // TypeList holds a list of types. type TypeList struct{ types []Type } -// NewTypeList returns a new TypeList with the types in list. -func NewTypeList(list []Type) *TypeList { +// newTypeList returns a new TypeList with the types in list. +func newTypeList(list []Type) *TypeList { if len(list) == 0 { return nil } diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 0a74a875bc..b961f7c47f 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -427,7 +427,7 @@ func (check *Checker) instantiatedType(ix *typeparams.IndexExpr, def *Named) (re if inst == nil { tname := NewTypeName(ix.X.Pos(), orig.obj.pkg, orig.obj.name, nil) inst = check.newNamed(tname, orig, nil, nil, nil) // underlying, methods and tparams are set when named is resolved - inst.targs = NewTypeList(targs) + inst.targs = newTypeList(targs) inst = ctxt.update(h, orig, targs, inst).(*Named) } def.setUnderlying(inst) @@ -441,7 +441,7 @@ func (check *Checker) instantiatedType(ix *typeparams.IndexExpr, def *Named) (re // be set to Typ[Invalid] in expandNamed. inferred = check.infer(ix.Orig, tparams, targs, nil, nil) if len(inferred) > len(targs) { - inst.targs = NewTypeList(inferred) + inst.targs = newTypeList(inferred) } } -- GitLab From 2cb9042dc2d5fdf6013305a077d013dbbfbaac06 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 6 Dec 2021 11:43:48 -0500 Subject: [PATCH 2413/2500] doc/go1.18: cite CLs for more efficient scavenging For #47694. Change-Id: Ic6088b1811600670a57f28426f4158a7c7517c82 Reviewed-on: https://go-review.googlesource.com/c/go/+/369616 Trust: Austin Clements Reviewed-by: Michael Knyszek --- doc/go1.18.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 35b3d744ec..e4e0d2300d 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -282,7 +282,7 @@ Do not send CLs removing the interior tags from such phrases. GOGC where necessary.

    -

    +

    The runtime now returns memory to the operating system more efficiently and has been tuned to work more aggressively as a result.

    -- GitLab From 7a840664fe9d8d4c11b943dba77c513dba5207a1 Mon Sep 17 00:00:00 2001 From: Roi Martin Date: Tue, 30 Nov 2021 19:35:47 +0100 Subject: [PATCH 2414/2500] cmd/go: update "go help doc" docs This CL updates "go help doc" docs so they reflect the following changes: - CL 59413 modified "go doc", so the behavior of the two-args case is consistent with the one-arg one. - CL 141397 removed godoc's command-line interface in favor of "go doc". Fixes #49830. Change-Id: I0923634291d34ae663fe2944d69757462b814919 Reviewed-on: https://go-review.googlesource.com/c/go/+/367497 Reviewed-by: Bryan Mills Run-TryBot: Bryan Mills TryBot-Result: Gopher Robot Trust: Russ Cox --- src/cmd/go/alldocs.go | 5 ++--- src/cmd/go/internal/doc/doc.go | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 12b64d309c..b9fca791be 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -368,9 +368,8 @@ // path. The go tool's usual package mechanism does not apply: package path // elements like . and ... are not implemented by go doc. // -// When run with two arguments, the first must be a full package path (not just a -// suffix), and the second is a symbol, or symbol with method or struct field. -// This is similar to the syntax accepted by godoc: +// When run with two arguments, the first is a package path (full path or suffix), +// and the second is a symbol, or symbol with method or struct field: // // go doc [.] // diff --git a/src/cmd/go/internal/doc/doc.go b/src/cmd/go/internal/doc/doc.go index 8580a5dc4d..7741a9022c 100644 --- a/src/cmd/go/internal/doc/doc.go +++ b/src/cmd/go/internal/doc/doc.go @@ -60,9 +60,8 @@ The package path must be either a qualified path or a proper suffix of a path. The go tool's usual package mechanism does not apply: package path elements like . and ... are not implemented by go doc. -When run with two arguments, the first must be a full package path (not just a -suffix), and the second is a symbol, or symbol with method or struct field. -This is similar to the syntax accepted by godoc: +When run with two arguments, the first is a package path (full path or suffix), +and the second is a symbol, or symbol with method or struct field: go doc [.] -- GitLab From c27a3592aec5f46ae18f7fd3d9ba18e69e2f1dcb Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 23 Aug 2021 17:27:40 +0000 Subject: [PATCH 2415/2500] runtime: set iOS addr space to 40 bits with incremental pagealloc In iOS <14, the address space is strictly limited to 8 GiB, or 33 bits. As a result, the page allocator also assumes all heap memory lives in this region. This is especially necessary because the page allocator has a PROT_NONE mapping proportional to the size of the usable address space, so this keeps that mapping very small. However starting with iOS 14, this restriction is relaxed, and mmap may start returning addresses outside of the <14 range. Today this means that in iOS 14 and later, users experience an error in the page allocator when a heap arena is mapped outside of the old range. This change increases the ios/arm64 heapAddrBits to 40 while simultaneously making ios/arm64 use the 64-bit pagealloc implementation (with reservations and incremental mapping) to accommodate both iOS versions <14 and 14+. Once iOS <14 is deprecated, we can remove these exceptions and treat ios/arm64 like any other arm64 platform. This change also makes the BaseChunkIdx expression a little bit easier to read, while we're here. Fixes #46860. Change-Id: I13865f799777739109585f14f1cc49d6d57e096b Reviewed-on: https://go-review.googlesource.com/c/go/+/344401 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Gopher Robot Reviewed-by: Cherry Mui Reviewed-by: Austin Clements --- src/runtime/export_test.go | 14 +++++++++++++- src/runtime/malloc.go | 20 +++++++++++++------- src/runtime/mgcscavenge_test.go | 5 ++++- src/runtime/mpagealloc_32bit.go | 8 +------- src/runtime/mpagealloc_64bit.go | 4 +--- src/runtime/mpagealloc_test.go | 9 +++++++-- src/runtime/mpagecache_test.go | 5 ++++- 7 files changed, 43 insertions(+), 22 deletions(-) diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index ef601f770c..4a03f24ded 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -1048,7 +1048,19 @@ func FreePageAlloc(pp *PageAlloc) { // // This should not be higher than 0x100*pallocChunkBytes to support // mips and mipsle, which only have 31-bit address spaces. -var BaseChunkIdx = ChunkIdx(chunkIndex(((0xc000*pageAlloc64Bit + 0x100*pageAlloc32Bit) * pallocChunkBytes) + arenaBaseOffset*goos.IsAix)) +var BaseChunkIdx = func() ChunkIdx { + var prefix uintptr + if pageAlloc64Bit != 0 { + prefix = 0xc000 + } else { + prefix = 0x100 + } + baseAddr := prefix * pallocChunkBytes + if goos.IsAix != 0 { + baseAddr += arenaBaseOffset + } + return ChunkIdx(chunkIndex(baseAddr)) +}() // PageBase returns an address given a chunk index and a page index // relative to that chunk. diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index e267e2df23..6ed6ceade2 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -201,15 +201,21 @@ const ( // we further limit it to 31 bits. // // On ios/arm64, although 64-bit pointers are presumably - // available, pointers are truncated to 33 bits. Furthermore, - // only the top 4 GiB of the address space are actually available - // to the application, but we allow the whole 33 bits anyway for - // simplicity. - // TODO(mknyszek): Consider limiting it to 32 bits and using - // arenaBaseOffset to offset into the top 4 GiB. + // available, pointers are truncated to 33 bits in iOS <14. + // Furthermore, only the top 4 GiB of the address space are + // actually available to the application. In iOS >=14, more + // of the address space is available, and the OS can now + // provide addresses outside of those 33 bits. Pick 40 bits + // as a reasonable balance between address space usage by the + // page allocator, and flexibility for what mmap'd regions + // we'll accept for the heap. We can't just move to the full + // 48 bits because this uses too much address space for older + // iOS versions. + // TODO(mknyszek): Once iOS <14 is deprecated, promote ios/arm64 + // to a 48-bit address space like every other arm64 platform. // // WebAssembly currently has a limit of 4GB linear memory. - heapAddrBits = (_64bit*(1-goarch.IsWasm)*(1-goos.IsIos*goarch.IsArm64))*48 + (1-_64bit+goarch.IsWasm)*(32-(goarch.IsMips+goarch.IsMipsle)) + 33*goos.IsIos*goarch.IsArm64 + heapAddrBits = (_64bit*(1-goarch.IsWasm)*(1-goos.IsIos*goarch.IsArm64))*48 + (1-_64bit+goarch.IsWasm)*(32-(goarch.IsMips+goarch.IsMipsle)) + 40*goos.IsIos*goarch.IsArm64 // maxAlloc is the maximum size of an allocation. On 64-bit, // it's theoretically possible to allocate 1< Date: Sun, 5 Dec 2021 16:39:20 +0000 Subject: [PATCH 2416/2500] src/cmd/go/internal/work: lock Builder output mutex consistently To prevent interleaving of output when 'go build' compiles several packages in parallel, the output mutex in the Builder struct must be locked around any calls to Builder.Print which could generate arbitrary amounts of text (ie more than is guaranteed to be written atomically to a pipe). Fixes #49987 For #49338 Change-Id: I7947df57667deeff3f03f231824298d823f8a943 Reviewed-on: https://go-review.googlesource.com/c/go/+/369018 Reviewed-by: Bryan Mills Run-TryBot: Bryan Mills TryBot-Result: Gopher Robot Trust: Russ Cox --- src/cmd/go/internal/work/buildid.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cmd/go/internal/work/buildid.go b/src/cmd/go/internal/work/buildid.go index 4e9189a363..76335e9bb1 100644 --- a/src/cmd/go/internal/work/buildid.go +++ b/src/cmd/go/internal/work/buildid.go @@ -570,6 +570,8 @@ func showStdout(b *Builder, c *cache.Cache, actionID cache.ActionID, key string) b.Showcmd("", "%s # internal", joinUnambiguously(str.StringList("cat", c.OutputFile(stdoutEntry.OutputID)))) } if !cfg.BuildN { + b.output.Lock() + defer b.output.Unlock() b.Print(string(stdout)) } } @@ -578,6 +580,8 @@ func showStdout(b *Builder, c *cache.Cache, actionID cache.ActionID, key string) // flushOutput flushes the output being queued in a. func (b *Builder) flushOutput(a *Action) { + b.output.Lock() + defer b.output.Unlock() b.Print(string(a.output)) a.output = nil } -- GitLab From 9ecb853cf2252f3cd9ed2e7b3401d17df2d1ab06 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 6 Dec 2021 13:33:54 -0500 Subject: [PATCH 2417/2500] doc/go1.18: minor tweaks to generics section This CL reorders the bullet points in the generics section to more closely match what I think users will consider most important. I put the ~ token before the mention of ~T in interfaces to avoid a forward reference, though I wonder if we actually want to spent a couple more sentences saying what union and ~T types are, since most people are going to care about that a lot more than they care about the low-level detail that there's a new token. For #47694. Change-Id: Ib84f096ef6346a711801268ce362b64fa423d3f2 Reviewed-on: https://go-review.googlesource.com/c/go/+/369734 Trust: Austin Clements Reviewed-by: Ian Lance Taylor --- doc/go1.18.html | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index e4e0d2300d..15cec4e1f0 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -41,10 +41,6 @@ Do not send CLs removing the interior tags from such phrases. For details see the language spec.

      -
    • - The new token ~ is added to the set of - operators and punctuation. -
    • The syntax for Function and @@ -52,6 +48,14 @@ Do not send CLs removing the interior tags from such phrases. now accepts type parameters.
    • +
    • + Parameterized functions and types can be instantiated by following them with a list of + type arguments in square brackets. +
    • +
    • + The new token ~ has been added to the set of + operators and punctuation. +
    • The syntax for Interface types @@ -60,10 +64,6 @@ Do not send CLs removing the interior tags from such phrases. as type constraints. An interface now defines a set of types as well as a set of methods.
    • -
    • - Parameterized functions and types can be instantiated by following them with a list of - type arguments in square brackets. -
    • The new predeclared identifier -- GitLab From 0bbb74b5ac8c01def959ef2e32ac3295d4f2707e Mon Sep 17 00:00:00 2001 From: Jeremy Faller Date: Thu, 2 Dec 2021 13:22:46 -0500 Subject: [PATCH 2418/2500] doc/go1.18: add changes to regexp to release notes CL 354569 Updates #47694 Change-Id: I78536c110215b3c9f247c1420bcaa5fc3d8fb930 Reviewed-on: https://go-review.googlesource.com/c/go/+/368795 Trust: Jeremy Faller Run-TryBot: Jeremy Faller Reviewed-by: Ian Lance Taylor --- doc/go1.18.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 15cec4e1f0..82facf3845 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -696,7 +696,8 @@ Do not send CLs removing the interior tags from such phrases.
      regexp

      - TODO: https://golang.org/cl/354569: document and implement that invalid UTF-8 bytes are the same as U+FFFD + regexp + now treats each invalid byte of a UTF-8 string as U+FFFD.

      -- GitLab From 1c4cf50e113f402eb6986a2007cd9c820b1bb69f Mon Sep 17 00:00:00 2001 From: Jeremy Faller Date: Thu, 2 Dec 2021 13:41:37 -0500 Subject: [PATCH 2419/2500] doc/go1.18: add docs for js.Wrapper's removal CL 356430 Updates #47694 Change-Id: I802cd50f2827caa0549c25685c0b1bb8dfc40968 Reviewed-on: https://go-review.googlesource.com/c/go/+/368799 Trust: Jeremy Faller Run-TryBot: Jeremy Faller Reviewed-by: Cherry Mui --- doc/go1.18.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 82facf3845..818f7c7dcb 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -769,7 +769,7 @@ Do not send CLs removing the interior tags from such phrases.
      syscall/js

      - TODO: https://golang.org/cl/356430: remove Wrapper interface + Wrapper interface has been removed.

      -- GitLab From 870f33f6efcbb5db7b556cbe3438aa7925270825 Mon Sep 17 00:00:00 2001 From: Jeremy Faller Date: Thu, 2 Dec 2021 13:26:51 -0500 Subject: [PATCH 2420/2500] doc/go1.18: add changes to strconv.Unquote to release notes CL 343877 Updates #47694 Change-Id: I37a0a0d1f7ab937b12812981ecddc89eb8c99c24 Reviewed-on: https://go-review.googlesource.com/c/go/+/368796 Trust: Jeremy Faller Run-TryBot: Jeremy Faller Reviewed-by: Joe Tsai --- doc/go1.18.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 818f7c7dcb..7a4869cf6a 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -705,7 +705,8 @@ Do not send CLs removing the interior tags from such phrases.
      strconv

      - TODO: https://golang.org/cl/343877: reject surrogate halves in Unquote + strconv.Unquote + now rejects Unicode surrogate halves.

      -- GitLab From d16a57542a83adfb8182508291ddcfe99c406818 Mon Sep 17 00:00:00 2001 From: Jeremy Faller Date: Thu, 2 Dec 2021 13:33:18 -0500 Subject: [PATCH 2421/2500] doc/go1.18: add new sync.[RW]Mutex methods CL 319769 Updates #47694 Change-Id: I9655af0d249926617645c33617d53b73f985aa19 Reviewed-on: https://go-review.googlesource.com/c/go/+/368797 Trust: Jeremy Faller Run-TryBot: Jeremy Faller Reviewed-by: Ian Lance Taylor --- doc/go1.18.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 7a4869cf6a..77c26bc257 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -740,7 +740,11 @@ Do not send CLs removing the interior tags from such phrases.
      sync

      - TODO: https://golang.org/cl/319769: add Mutex.TryLock, RWMutex.TryLock, RWMutex.TryRLock + The new methods + Mutex.TryLock, + RWMutex.TryLock, and + RWMutex.TryRLock, + will acquire the lock if it is not currently held.

      -- GitLab From 6180c4f5ebae4635377dfa778e05097cf8fc69a8 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Tue, 23 Nov 2021 17:02:10 -0500 Subject: [PATCH 2422/2500] log/syslog: create unix sockets in unique directories startServer was invoking os.Remove on the temporary file for a unix socket after creating it. Since the files were created in the global temp directory, that could cause two tests to arrive at colliding names. (Noticed while looking into the failure at https://storage.googleapis.com/go-build-log/af2c83b1/solaris-amd64-oraclerel_3e01fda8.log, but I would be surprised if this solves that failure.) This change uses unique temporary directories, and attempts to keep name lengths minimal to avoid accidentally running into socket-name length limitations. Updates #34611 Change-Id: I21743f245e5c14645e03f09795013e058b984471 Reviewed-on: https://go-review.googlesource.com/c/go/+/366774 Trust: Bryan Mills Run-TryBot: Bryan Mills TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor --- src/log/syslog/syslog_test.go | 94 ++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 39 deletions(-) diff --git a/src/log/syslog/syslog_test.go b/src/log/syslog/syslog_test.go index 26530480ee..de1681d653 100644 --- a/src/log/syslog/syslog_test.go +++ b/src/log/syslog/syslog_test.go @@ -10,9 +10,9 @@ import ( "bufio" "fmt" "io" - "log" "net" "os" + "path/filepath" "runtime" "sync" "testing" @@ -81,28 +81,36 @@ func runStreamSyslog(l net.Listener, done chan<- string, wg *sync.WaitGroup) { } } -func startServer(n, la string, done chan<- string) (addr string, sock io.Closer, wg *sync.WaitGroup) { +func startServer(t *testing.T, n, la string, done chan<- string) (addr string, sock io.Closer, wg *sync.WaitGroup) { if n == "udp" || n == "tcp" { la = "127.0.0.1:0" } else { - // unix and unixgram: choose an address if none given + // unix and unixgram: choose an address if none given. if la == "" { - // use os.CreateTemp to get a name that is unique - f, err := os.CreateTemp("", "syslogtest") + // The address must be short to fit in the sun_path field of the + // sockaddr_un passed to the underlying system calls, so we use + // os.MkdirTemp instead of t.TempDir: t.TempDir generally includes all or + // part of the test name in the directory, which can be much more verbose + // and risks running up against the limit. + dir, err := os.MkdirTemp("", "") if err != nil { - log.Fatal("TempFile: ", err) + t.Fatal(err) } - f.Close() - la = f.Name() + t.Cleanup(func() { + if err := os.RemoveAll(dir); err != nil { + t.Errorf("failed to remove socket temp directory: %v", err) + } + }) + la = filepath.Join(dir, "sock") } - os.Remove(la) } wg = new(sync.WaitGroup) if n == "udp" || n == "unixgram" { l, e := net.ListenPacket(n, la) if e != nil { - log.Fatalf("startServer failed: %v", e) + t.Helper() + t.Fatalf("startServer failed: %v", e) } addr = l.LocalAddr().String() sock = l @@ -114,7 +122,8 @@ func startServer(n, la string, done chan<- string) (addr string, sock io.Closer, } else { l, e := net.Listen(n, la) if e != nil { - log.Fatalf("startServer failed: %v", e) + t.Helper() + t.Fatalf("startServer failed: %v", e) } addr = l.Addr().String() sock = l @@ -129,32 +138,35 @@ func startServer(n, la string, done chan<- string) (addr string, sock io.Closer, func TestWithSimulated(t *testing.T) { t.Parallel() + msg := "Test 123" - var transport []string - for _, n := range []string{"unix", "unixgram", "udp", "tcp"} { - if testableNetwork(n) { - transport = append(transport, n) + for _, tr := range []string{"unix", "unixgram", "udp", "tcp"} { + if !testableNetwork(tr) { + continue } - } - for _, tr := range transport { - done := make(chan string) - addr, sock, srvWG := startServer(tr, "", done) - defer srvWG.Wait() - defer sock.Close() - if tr == "unix" || tr == "unixgram" { - defer os.Remove(addr) - } - s, err := Dial(tr, addr, LOG_INFO|LOG_USER, "syslog_test") - if err != nil { - t.Fatalf("Dial() failed: %v", err) - } - err = s.Info(msg) - if err != nil { - t.Fatalf("log failed: %v", err) - } - check(t, msg, <-done, tr) - s.Close() + tr := tr + t.Run(tr, func(t *testing.T) { + t.Parallel() + + done := make(chan string) + addr, sock, srvWG := startServer(t, tr, "", done) + defer srvWG.Wait() + defer sock.Close() + if tr == "unix" || tr == "unixgram" { + defer os.Remove(addr) + } + s, err := Dial(tr, addr, LOG_INFO|LOG_USER, "syslog_test") + if err != nil { + t.Fatalf("Dial() failed: %v", err) + } + err = s.Info(msg) + if err != nil { + t.Fatalf("log failed: %v", err) + } + check(t, msg, <-done, tr) + s.Close() + }) } } @@ -165,7 +177,7 @@ func TestFlap(t *testing.T) { } done := make(chan string) - addr, sock, srvWG := startServer(net, "", done) + addr, sock, srvWG := startServer(t, net, "", done) defer srvWG.Wait() defer os.Remove(addr) defer sock.Close() @@ -182,7 +194,10 @@ func TestFlap(t *testing.T) { check(t, msg, <-done, net) // restart the server - _, sock2, srvWG2 := startServer(net, addr, done) + if err := os.Remove(addr); err != nil { + t.Fatal(err) + } + _, sock2, srvWG2 := startServer(t, net, addr, done) defer srvWG2.Wait() defer sock2.Close() @@ -282,6 +297,7 @@ func check(t *testing.T, in, out, transport string) { func TestWrite(t *testing.T) { t.Parallel() + tests := []struct { pri Priority pre string @@ -299,7 +315,7 @@ func TestWrite(t *testing.T) { } else { for _, test := range tests { done := make(chan string) - addr, sock, srvWG := startServer("udp", "", done) + addr, sock, srvWG := startServer(t, "udp", "", done) defer srvWG.Wait() defer sock.Close() l, err := Dial("udp", addr, test.pri, test.pre) @@ -323,7 +339,7 @@ func TestWrite(t *testing.T) { } func TestConcurrentWrite(t *testing.T) { - addr, sock, srvWG := startServer("udp", "", make(chan string, 1)) + addr, sock, srvWG := startServer(t, "udp", "", make(chan string, 1)) defer srvWG.Wait() defer sock.Close() w, err := Dial("udp", addr, LOG_USER|LOG_ERR, "how's it going?") @@ -359,7 +375,7 @@ func TestConcurrentReconnect(t *testing.T) { } } done := make(chan string, N*M) - addr, sock, srvWG := startServer(net, "", done) + addr, sock, srvWG := startServer(t, net, "", done) if net == "unix" { defer os.Remove(addr) } -- GitLab From 8ea0ffb84a5807438061d34256448df9948a3809 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 3 Dec 2021 17:09:06 -0500 Subject: [PATCH 2423/2500] net: clarify that conn.LocalAddr and conn.RemoteAddr might not be known For #34611 Change-Id: I9a1357f53124c98ad017b58774696d0377dbea27 Reviewed-on: https://go-review.googlesource.com/c/go/+/369160 Trust: Bryan Mills Run-TryBot: Bryan Mills TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor --- src/net/net.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/net/net.go b/src/net/net.go index ab6aeaac2f..77e54a9125 100644 --- a/src/net/net.go +++ b/src/net/net.go @@ -125,10 +125,10 @@ type Conn interface { // Any blocked Read or Write operations will be unblocked and return errors. Close() error - // LocalAddr returns the local network address. + // LocalAddr returns the local network address, if known. LocalAddr() Addr - // RemoteAddr returns the remote network address. + // RemoteAddr returns the remote network address, if known. RemoteAddr() Addr // SetDeadline sets the read and write deadlines associated @@ -328,7 +328,7 @@ type PacketConn interface { // Any blocked ReadFrom or WriteTo operations will be unblocked and return errors. Close() error - // LocalAddr returns the local network address. + // LocalAddr returns the local network address, if known. LocalAddr() Addr // SetDeadline sets the read and write deadlines associated -- GitLab From 871d63fb73476bc3bf52ceec9aa8bef3ffc85d51 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 6 Dec 2021 17:35:58 -0500 Subject: [PATCH 2424/2500] runtime: call runtime.GC in several tests that disable GC These tests disable GC because of the potential for a deadlock, but don't consider that a GC could be in progress due to other tests. The likelihood of this case was increased when the minimum heap size was lowered during the Go 1.18 cycle. The issue was then mitigated by CL 368137 but in theory is always a problem. This change is intended specifically for #45867, but I just walked over a whole bunch of other tests that don't take this precaution where it seems like it could be relevant (some tests it's not, like the UserForcedGC test, or testprogs where no other code has run before it). Fixes #45867. Change-Id: I6a1b4ae73e05cab5a0b2d2cce14126bd13be0ba5 Reviewed-on: https://go-review.googlesource.com/c/go/+/369747 Reviewed-by: Michael Pratt Reviewed-by: David Chase Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Gopher Robot --- src/runtime/proc_test.go | 9 +++++++++ src/runtime/testdata/testprog/badtraceback.go | 3 +++ src/runtime/testdata/testprog/preempt.go | 3 +++ 3 files changed, 15 insertions(+) diff --git a/src/runtime/proc_test.go b/src/runtime/proc_test.go index 53cafe8907..9198022ace 100644 --- a/src/runtime/proc_test.go +++ b/src/runtime/proc_test.go @@ -119,6 +119,9 @@ func TestGoroutineParallelism(t *testing.T) { // since the goroutines can't be stopped/preempted. // Disable GC for this test (see issue #10958). defer debug.SetGCPercent(debug.SetGCPercent(-1)) + // Now that GCs are disabled, block until any outstanding GCs + // are also done. + runtime.GC() for try := 0; try < N; try++ { done := make(chan bool) x := uint32(0) @@ -163,6 +166,9 @@ func testGoroutineParallelism2(t *testing.T, load, netpoll bool) { // since the goroutines can't be stopped/preempted. // Disable GC for this test (see issue #10958). defer debug.SetGCPercent(debug.SetGCPercent(-1)) + // Now that GCs are disabled, block until any outstanding GCs + // are also done. + runtime.GC() for try := 0; try < N; try++ { if load { // Create P goroutines and wait until they all run. @@ -623,6 +629,9 @@ func TestSchedLocalQueueEmpty(t *testing.T) { // If runtime triggers a forced GC during this test then it will deadlock, // since the goroutines can't be stopped/preempted during spin wait. defer debug.SetGCPercent(debug.SetGCPercent(-1)) + // Now that GCs are disabled, block until any outstanding GCs + // are also done. + runtime.GC() iters := int(1e5) if testing.Short() { diff --git a/src/runtime/testdata/testprog/badtraceback.go b/src/runtime/testdata/testprog/badtraceback.go index d558adceec..09aa2b877e 100644 --- a/src/runtime/testdata/testprog/badtraceback.go +++ b/src/runtime/testdata/testprog/badtraceback.go @@ -17,6 +17,9 @@ func init() { func BadTraceback() { // Disable GC to prevent traceback at unexpected time. debug.SetGCPercent(-1) + // Out of an abundance of caution, also make sure that there are + // no GCs actively in progress. + runtime.GC() // Run badLR1 on its own stack to minimize the stack size and // exercise the stack bounds logic in the hex dump. diff --git a/src/runtime/testdata/testprog/preempt.go b/src/runtime/testdata/testprog/preempt.go index 1c74d0e435..eb9f59053c 100644 --- a/src/runtime/testdata/testprog/preempt.go +++ b/src/runtime/testdata/testprog/preempt.go @@ -20,6 +20,9 @@ func AsyncPreempt() { runtime.GOMAXPROCS(1) // Disable GC so we have complete control of what we're testing. debug.SetGCPercent(-1) + // Out of an abundance of caution, also make sure that there are + // no GCs actively in progress. + runtime.GC() // Start a goroutine with no sync safe-points. var ready, ready2 uint32 -- GitLab From 79b425e9fca11d189142504bc81cf4e009092f6d Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Mon, 6 Dec 2021 18:05:53 -0500 Subject: [PATCH 2425/2500] misc/cgo/testplugin: remove skip in TestIssue25756pie Though this was a problem for Go 1.17, it appears not to be a problem on tip. This reverts change made in CL 321349. For #46239. Change-Id: Ie4d6649fbabce3bb2c1cf04d97760ba6ceadaca5 Reviewed-on: https://go-review.googlesource.com/c/go/+/369752 Run-TryBot: Dmitri Shuralyov Reviewed-by: Cherry Mui TryBot-Result: Gopher Robot Trust: Dmitri Shuralyov --- misc/cgo/testplugin/plugin_test.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/misc/cgo/testplugin/plugin_test.go b/misc/cgo/testplugin/plugin_test.go index 9697dbf7a7..a6accc1dfb 100644 --- a/misc/cgo/testplugin/plugin_test.go +++ b/misc/cgo/testplugin/plugin_test.go @@ -265,10 +265,6 @@ func TestIssue25756(t *testing.T) { // Test with main using -buildmode=pie with plugin for issue #43228 func TestIssue25756pie(t *testing.T) { - if os.Getenv("GO_BUILDER_NAME") == "darwin-arm64-11_0-toothrot" { - t.Skip("broken on darwin/arm64 builder in sharded mode; see issue 46239") - } - goCmd(t, "build", "-buildmode=plugin", "-o", "life.so", "./issue25756/plugin") goCmd(t, "build", "-buildmode=pie", "-o", "issue25756pie.exe", "./issue25756/main.go") run(t, "./issue25756pie.exe") -- GitLab From 6f65d470d8b688573891420f7a428191d8c6cd49 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 6 Dec 2021 17:53:35 -0500 Subject: [PATCH 2426/2500] runtime: clean up redundant calls to SetGCPercent in debug_test.go SetGCPercent(-1) is called by several tests in debug_test.go (followed by a call to runtime.GC) due to #49370. However, startDebugCallWorker already actually has this, just without the runtime.GC call (allowing an in-progress GC to still mess up the test). This CL consolidates SetGCPercent into startDebugDebugCallWorker where applicable. Change-Id: Ifa12d6a911f1506e252d3ddf03004cf2ab3f4ee4 Reviewed-on: https://go-review.googlesource.com/c/go/+/369751 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Gopher Robot Reviewed-by: David Chase --- src/runtime/debug_test.go | 35 +++++------------------------------ 1 file changed, 5 insertions(+), 30 deletions(-) diff --git a/src/runtime/debug_test.go b/src/runtime/debug_test.go index 89ea577d64..44585b1744 100644 --- a/src/runtime/debug_test.go +++ b/src/runtime/debug_test.go @@ -34,12 +34,15 @@ func startDebugCallWorker(t *testing.T) (g *runtime.G, after func()) { skipUnderDebugger(t) // This can deadlock if there aren't enough threads or if a GC - // tries to interrupt an atomic loop (see issue #10958). We + // tries to interrupt an atomic loop (see issue #10958). A GC + // could also actively be in progress (see issue #49370), so we + // need to call runtime.GC to block until it has complete. We // use 8 Ps so there's room for the debug call worker, // something that's trying to preempt the call worker, and the // goroutine that's trying to stop the call worker. ogomaxprocs := runtime.GOMAXPROCS(8) ogcpercent := debug.SetGCPercent(-1) + runtime.GC() // ready is a buffered channel so debugCallWorker won't block // on sending to it. This makes it less likely we'll catch @@ -114,13 +117,6 @@ func skipUnderDebugger(t *testing.T) { } func TestDebugCall(t *testing.T) { - // InjectDebugCall cannot be executed while a GC is actively in - // progress. Wait until the current GC is done, and turn it off. - // - // See #49370. - runtime.GC() - defer debug.SetGCPercent(debug.SetGCPercent(-1)) - g, after := startDebugCallWorker(t) defer after() @@ -172,13 +168,6 @@ func TestDebugCall(t *testing.T) { } func TestDebugCallLarge(t *testing.T) { - // InjectDebugCall cannot be executed while a GC is actively in - // progress. Wait until the current GC is done, and turn it off. - // - // See #49370. - runtime.GC() - defer debug.SetGCPercent(debug.SetGCPercent(-1)) - g, after := startDebugCallWorker(t) defer after() @@ -208,13 +197,6 @@ func TestDebugCallLarge(t *testing.T) { } func TestDebugCallGC(t *testing.T) { - // InjectDebugCall cannot be executed while a GC is actively in - // progress. Wait until the current GC is done, and turn it off. - // - // See #49370. - runtime.GC() - defer debug.SetGCPercent(debug.SetGCPercent(-1)) - g, after := startDebugCallWorker(t) defer after() @@ -225,13 +207,6 @@ func TestDebugCallGC(t *testing.T) { } func TestDebugCallGrowStack(t *testing.T) { - // InjectDebugCall cannot be executed while a GC is actively in - // progress. Wait until the current GC is done, and turn it off. - // - // See #49370. - runtime.GC() - defer debug.SetGCPercent(debug.SetGCPercent(-1)) - g, after := startDebugCallWorker(t) defer after() @@ -294,7 +269,7 @@ func TestDebugCallPanic(t *testing.T) { // InjectDebugCall cannot be executed while a GC is actively in // progress. Wait until the current GC is done, and turn it off. // - // See #49370. + // See #10958 and #49370. runtime.GC() defer debug.SetGCPercent(debug.SetGCPercent(-1)) -- GitLab From 0eb39ca1f0ca118e78648fb6844d35d0a96e5eee Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Mon, 6 Dec 2021 18:41:49 -0500 Subject: [PATCH 2427/2500] cmd/dist: enable plugin test on Linux/ARM64 The test was skipped because with the old gold linker on the builder it fails with an internal error in gold. The builders now have gold 2.31 and the test passes. Enable it. Fixes #17138. Change-Id: Ia0054030dd12f1d003c7420bf7ed8b112715baa9 Reviewed-on: https://go-review.googlesource.com/c/go/+/369814 Trust: Cherry Mui Run-TryBot: Cherry Mui Reviewed-by: Than McIntosh TryBot-Result: Gopher Robot --- src/cmd/dist/test.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index aea1ee6f25..50a2e5936c 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -1043,10 +1043,8 @@ func (t *tester) supportedBuildmode(mode string) bool { } return false case "plugin": - // linux-arm64 is missing because it causes the external linker - // to crash, see https://golang.org/issue/17138 switch pair { - case "linux-386", "linux-amd64", "linux-arm", "linux-s390x", "linux-ppc64le": + case "linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-s390x", "linux-ppc64le": return true case "darwin-amd64", "darwin-arm64": return true -- GitLab From e07b02ff87af594a68484dcb1e3a78d1c39abc56 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Tue, 23 Nov 2021 10:27:30 -0500 Subject: [PATCH 2428/2500] net: in (*netFD).dial, use the passed in local address if getsockname fails 'man getsockname' lists a number of possible failure modes, including ENOBUFS (for resource exhaustion) and EBADF (which we could possibly see in the event of a bug or race condition elsewhere in the program). If getsockname fails for an explicit user-provided local address, the user is probably not expecting LocalAddr on the returned net.Conn to return nil. This may or may not fix #34611, but should at least help us diagnose it more clearly. While we're add it, also add more nil-checking logic in the test based on the stack traces posted to https://golang.org/issue/34611#issuecomment-975923748. For #34611 Change-Id: Iba870b96787811e4b9959b74ef648afce9316602 Reviewed-on: https://go-review.googlesource.com/c/go/+/366536 Trust: Bryan Mills Run-TryBot: Bryan Mills Reviewed-by: Ian Lance Taylor TryBot-Result: Gopher Robot --- src/net/server_test.go | 10 +++++++++- src/net/sock_posix.go | 16 +++++++++++----- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/net/server_test.go b/src/net/server_test.go index 33d33b0337..b69cd29289 100644 --- a/src/net/server_test.go +++ b/src/net/server_test.go @@ -200,9 +200,17 @@ func TestUnixAndUnixpacketServer(t *testing.T) { if c == nil { panic("Dial returned a nil Conn") } - if rc := reflect.ValueOf(c); rc.Kind() == reflect.Pointer && rc.IsNil() { + rc := reflect.ValueOf(c) + if rc.IsNil() { panic(fmt.Sprintf("Dial returned a nil %T", c)) } + fd := rc.Elem().FieldByName("fd") + if fd.IsNil() { + panic(fmt.Sprintf("Dial returned a %T with a nil fd", c)) + } + if addr := fd.Elem().FieldByName("laddr"); addr.IsNil() { + panic(fmt.Sprintf("Dial returned a %T whose fd has a nil laddr", c)) + } addr := c.LocalAddr() if addr == nil { panic(fmt.Sprintf("(%T).LocalAddr returned a nil Addr", c)) diff --git a/src/net/sock_posix.go b/src/net/sock_posix.go index 98a48229c7..603fb2bb64 100644 --- a/src/net/sock_posix.go +++ b/src/net/sock_posix.go @@ -156,18 +156,24 @@ func (fd *netFD) dial(ctx context.Context, laddr, raddr sockaddr, ctrlFn func(st } } // Record the local and remote addresses from the actual socket. - // Get the local address by calling Getsockname. + // For the local address, use + // 1) the one returned by Getsockname, if that succeeds; or + // 2) the one passed to us as the laddr parameter; or + // 3) nil. // For the remote address, use // 1) the one returned by the connect method, if any; or // 2) the one from Getpeername, if it succeeds; or // 3) the one passed to us as the raddr parameter. - lsa, _ = syscall.Getsockname(fd.pfd.Sysfd) + var laddrName Addr = laddr + if lsa, err := syscall.Getsockname(fd.pfd.Sysfd); err == nil { + laddrName = fd.addrFunc()(lsa) + } if crsa != nil { - fd.setAddr(fd.addrFunc()(lsa), fd.addrFunc()(crsa)) + fd.setAddr(laddrName, fd.addrFunc()(crsa)) } else if rsa, _ = syscall.Getpeername(fd.pfd.Sysfd); rsa != nil { - fd.setAddr(fd.addrFunc()(lsa), fd.addrFunc()(rsa)) + fd.setAddr(laddrName, fd.addrFunc()(rsa)) } else { - fd.setAddr(fd.addrFunc()(lsa), raddr) + fd.setAddr(laddrName, raddr) } return nil } -- GitLab From dc65c489cc5a795a68d844ed7a45e5d16562401d Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 6 Dec 2021 17:25:34 -0500 Subject: [PATCH 2429/2500] cmd/go: fix tests broken in CL 358539 CL 358539 revised the build-stamp format, and updated the git and hg tests to match. However, the fossil and bzr tests were missed, and were not caught on the builders due to the fact that none of the builder images have the necessary VCS tools installed. Updates #48802 Updates #49168 Change-Id: I6b9fd0e19b81cb539864c94ab0860f74e7be6748 Reviewed-on: https://go-review.googlesource.com/c/go/+/369743 Trust: Bryan Mills Run-TryBot: Bryan Mills TryBot-Result: Gopher Robot Reviewed-by: Russ Cox --- .../testdata/script/version_buildvcs_bzr.txt | 33 ++++++++++--------- .../script/version_buildvcs_fossil.txt | 21 +++++++----- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/src/cmd/go/testdata/script/version_buildvcs_bzr.txt b/src/cmd/go/testdata/script/version_buildvcs_bzr.txt index 83069713d7..85db9bab6d 100644 --- a/src/cmd/go/testdata/script/version_buildvcs_bzr.txt +++ b/src/cmd/go/testdata/script/version_buildvcs_bzr.txt @@ -31,14 +31,15 @@ cd .. env PATH=$oldpath rm .bzr -# If there is an empty repository in a parent directory, only "uncommitted" is tagged. +# If there is an empty repository in a parent directory, only "modified" is tagged. exec bzr init cd a go install go version -m $GOBIN/a$GOEXE -! stdout bzrrevision -! stdout bzrcommittime -stdout '^\tbuild\tbzruncommitted\ttrue$' +stdout '^\tbuild\tvcs=bzr$' +! stdout vcs.revision +! stdout vcs.time +stdout '^\tbuild\tvcs.modified=true$' cd .. # Revision and commit time are tagged for repositories with commits. @@ -47,9 +48,10 @@ exec bzr commit -m 'initial commit' cd a go install go version -m $GOBIN/a$GOEXE -stdout '^\tbuild\tbzrrevision\t' -stdout '^\tbuild\tbzrcommittime\t' -stdout '^\tbuild\tbzruncommitted\tfalse$' +stdout '^\tbuild\tvcs=bzr$' +stdout '^\tbuild\tvcs.revision=' +stdout '^\tbuild\tvcs.time=' +stdout '^\tbuild\tvcs.modified=false$' rm $GOBIN/a$GOEXE # Building an earlier commit should still build clean. @@ -59,29 +61,30 @@ exec bzr commit -m 'add NEWS' exec bzr update -r1 go install go version -m $GOBIN/a$GOEXE -stdout '^\tbuild\tbzrrevision\t' -stdout '^\tbuild\tbzrcommittime\t' -stdout '^\tbuild\tbzruncommitted\tfalse$' +stdout '^\tbuild\tvcs=bzr$' +stdout '^\tbuild\tvcs.revision=' +stdout '^\tbuild\tvcs.time=' +stdout '^\tbuild\tvcs.modified=false$' # Building with -buildvcs=false suppresses the info. go install -buildvcs=false go version -m $GOBIN/a$GOEXE -! stdout bzrrevision +! stdout vcs.revision rm $GOBIN/a$GOEXE -# An untracked file is shown as uncommitted, even if it isn't part of the build. +# An untracked file is shown as modified, even if it isn't part of the build. cp ../../outside/empty.txt . go install go version -m $GOBIN/a$GOEXE -stdout '^\tbuild\tbzruncommitted\ttrue$' +stdout '^\tbuild\tvcs.modified=true$' rm empty.txt rm $GOBIN/a$GOEXE -# An edited file is shown as uncommitted, even if it isn't part of the build. +# An edited file is shown as modified, even if it isn't part of the build. cp ../../outside/empty.txt ../README go install go version -m $GOBIN/a$GOEXE -stdout '^\tbuild\tbzruncommitted\ttrue$' +stdout '^\tbuild\tvcs.modified=true$' exec bzr revert ../README rm $GOBIN/a$GOEXE diff --git a/src/cmd/go/testdata/script/version_buildvcs_fossil.txt b/src/cmd/go/testdata/script/version_buildvcs_fossil.txt index 3a4bde883f..720306868b 100644 --- a/src/cmd/go/testdata/script/version_buildvcs_fossil.txt +++ b/src/cmd/go/testdata/script/version_buildvcs_fossil.txt @@ -19,7 +19,7 @@ cd repo/a # If there's no local repository, there's no VCS info. go install go version -m $GOBIN/a$GOEXE -! stdout fossilrevision +! stdout vcs.revision rm $GOBIN/a$GOEXE # If there is a repository, but it can't be used for some reason, @@ -44,30 +44,33 @@ exec fossil commit -m 'initial commit' cd a go install go version -m $GOBIN/a$GOEXE -stdout '^\tbuild\tfossilrevision\t' -stdout '^\tbuild\tfossilcommittime\t' -stdout '^\tbuild\tfossiluncommitted\tfalse$' +stdout '^\tbuild\tvcs=fossil\n' +stdout '^\tbuild\tvcs.revision=' +stdout '^\tbuild\tvcs.time=' +stdout '^\tbuild\tvcs.modified=false$' rm $GOBIN/a$GOEXE # Building with -buildvcs=false suppresses the info. go install -buildvcs=false go version -m $GOBIN/a$GOEXE -! stdout fossilrevision +! stdout vcs.revision rm $GOBIN/a$GOEXE -# An untracked file is shown as uncommitted, even if it isn't part of the build. +# An untracked file is shown as modified, even if it isn't part of the build. cp ../../outside/empty.txt . go install go version -m $GOBIN/a$GOEXE -stdout '^\tbuild\tfossiluncommitted\ttrue$' +stdout '^\tbuild\tvcs=fossil\n' +stdout '^\tbuild\tvcs.modified=true$' rm empty.txt rm $GOBIN/a$GOEXE -# An edited file is shown as uncommitted, even if it isn't part of the build. +# An edited file is shown as modified, even if it isn't part of the build. cp ../../outside/empty.txt ../README go install go version -m $GOBIN/a$GOEXE -stdout '^\tbuild\tfossiluncommitted\ttrue$' +stdout '^\tbuild\tvcs=fossil\n' +stdout '^\tbuild\tvcs.modified=true$' exec fossil revert ../README rm $GOBIN/a$GOEXE -- GitLab From 4c943abb95578da4bfd70d365814a130da8d5aa2 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Tue, 7 Dec 2021 00:24:54 -0500 Subject: [PATCH 2430/2500] runtime: fix comments on the behavior of SetGCPercent Fixes for #49680, #49695, #45867, and #49370 all assumed that SetGCPercent(-1) doesn't block until the GC's mark phase is done, but it actually does. The cause of 3 of those 4 failures comes from the fact that at the beginning of the sweep phase, the GC does try to preempt every P once, and this may run concurrently with test code. In the fourth case, the issue was likely that only *one* of the debug_test.go tests was missing a call to SetGCPercent(-1). Just to be safe, leave a TODO there for now to remove the extraneous runtime.GC calls, but leave the calls in. Updates #49680, #49695, #45867, and #49370. Change-Id: Ibf4e64addfba18312526968bcf40f1f5d54eb3f1 Reviewed-on: https://go-review.googlesource.com/c/go/+/369815 Reviewed-by: Austin Clements Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Gopher Robot --- misc/cgo/test/testdata/issue9400_linux.go | 4 +++- src/runtime/debug_test.go | 23 ++++++++++++++++++----- src/runtime/proc_test.go | 15 +++++++++------ src/runtime/rwmutex_test.go | 4 +++- src/runtime/testdata/testprog/preempt.go | 3 ++- 5 files changed, 35 insertions(+), 14 deletions(-) diff --git a/misc/cgo/test/testdata/issue9400_linux.go b/misc/cgo/test/testdata/issue9400_linux.go index 47f224dc4f..051b9ab0bb 100644 --- a/misc/cgo/test/testdata/issue9400_linux.go +++ b/misc/cgo/test/testdata/issue9400_linux.go @@ -50,7 +50,9 @@ func test9400(t *testing.T) { // Disable GC for the duration of the test. // This avoids a potential GC deadlock when spinning in uninterruptable ASM below #49695. defer debug.SetGCPercent(debug.SetGCPercent(-1)) - // And finish any pending GC after we pause, if any. + // SetGCPercent waits until the mark phase is over, but the runtime + // also preempts at the start of the sweep phase, so make sure that's + // done too. See #49695. runtime.GC() // Temporarily rewind the stack and trigger SIGSETXID diff --git a/src/runtime/debug_test.go b/src/runtime/debug_test.go index 44585b1744..5bb0c5cee3 100644 --- a/src/runtime/debug_test.go +++ b/src/runtime/debug_test.go @@ -34,10 +34,17 @@ func startDebugCallWorker(t *testing.T) (g *runtime.G, after func()) { skipUnderDebugger(t) // This can deadlock if there aren't enough threads or if a GC - // tries to interrupt an atomic loop (see issue #10958). A GC - // could also actively be in progress (see issue #49370), so we - // need to call runtime.GC to block until it has complete. We - // use 8 Ps so there's room for the debug call worker, + // tries to interrupt an atomic loop (see issue #10958). Execute + // an extra GC to ensure even the sweep phase is done (out of + // caution to prevent #49370 from happening). + // TODO(mknyszek): This extra GC cycle is likely unnecessary + // because preemption (which may happen during the sweep phase) + // isn't much of an issue anymore thanks to asynchronous preemption. + // The biggest risk is having a write barrier in the debug call + // injection test code fire, because it runs in a signal handler + // and may not have a P. + // + // We use 8 Ps so there's room for the debug call worker, // something that's trying to preempt the call worker, and the // goroutine that's trying to stop the call worker. ogomaxprocs := runtime.GOMAXPROCS(8) @@ -270,8 +277,14 @@ func TestDebugCallPanic(t *testing.T) { // progress. Wait until the current GC is done, and turn it off. // // See #10958 and #49370. - runtime.GC() defer debug.SetGCPercent(debug.SetGCPercent(-1)) + // TODO(mknyszek): This extra GC cycle is likely unnecessary + // because preemption (which may happen during the sweep phase) + // isn't much of an issue anymore thanks to asynchronous preemption. + // The biggest risk is having a write barrier in the debug call + // injection test code fire, because it runs in a signal handler + // and may not have a P. + runtime.GC() ready := make(chan *runtime.G) var stop uint32 diff --git a/src/runtime/proc_test.go b/src/runtime/proc_test.go index 9198022ace..cc899a24c6 100644 --- a/src/runtime/proc_test.go +++ b/src/runtime/proc_test.go @@ -119,8 +119,9 @@ func TestGoroutineParallelism(t *testing.T) { // since the goroutines can't be stopped/preempted. // Disable GC for this test (see issue #10958). defer debug.SetGCPercent(debug.SetGCPercent(-1)) - // Now that GCs are disabled, block until any outstanding GCs - // are also done. + // SetGCPercent waits until the mark phase is over, but the runtime + // also preempts at the start of the sweep phase, so make sure that's + // done too. See #45867. runtime.GC() for try := 0; try < N; try++ { done := make(chan bool) @@ -166,8 +167,9 @@ func testGoroutineParallelism2(t *testing.T, load, netpoll bool) { // since the goroutines can't be stopped/preempted. // Disable GC for this test (see issue #10958). defer debug.SetGCPercent(debug.SetGCPercent(-1)) - // Now that GCs are disabled, block until any outstanding GCs - // are also done. + // SetGCPercent waits until the mark phase is over, but the runtime + // also preempts at the start of the sweep phase, so make sure that's + // done too. See #45867. runtime.GC() for try := 0; try < N; try++ { if load { @@ -629,8 +631,9 @@ func TestSchedLocalQueueEmpty(t *testing.T) { // If runtime triggers a forced GC during this test then it will deadlock, // since the goroutines can't be stopped/preempted during spin wait. defer debug.SetGCPercent(debug.SetGCPercent(-1)) - // Now that GCs are disabled, block until any outstanding GCs - // are also done. + // SetGCPercent waits until the mark phase is over, but the runtime + // also preempts at the start of the sweep phase, so make sure that's + // done too. See #45867. runtime.GC() iters := int(1e5) diff --git a/src/runtime/rwmutex_test.go b/src/runtime/rwmutex_test.go index 33ddd7d1d5..f15d367b32 100644 --- a/src/runtime/rwmutex_test.go +++ b/src/runtime/rwmutex_test.go @@ -55,7 +55,9 @@ func TestParallelRWMutexReaders(t *testing.T) { // since the goroutines can't be stopped/preempted. // Disable GC for this test (see issue #10958). defer debug.SetGCPercent(debug.SetGCPercent(-1)) - // Finish any in-progress GCs and get ourselves to a clean slate. + // SetGCPercent waits until the mark phase is over, but the runtime + // also preempts at the start of the sweep phase, so make sure that's + // done too. GC() doTestParallelReaders(1) diff --git a/src/runtime/testdata/testprog/preempt.go b/src/runtime/testdata/testprog/preempt.go index eb9f59053c..fb6755a372 100644 --- a/src/runtime/testdata/testprog/preempt.go +++ b/src/runtime/testdata/testprog/preempt.go @@ -21,7 +21,8 @@ func AsyncPreempt() { // Disable GC so we have complete control of what we're testing. debug.SetGCPercent(-1) // Out of an abundance of caution, also make sure that there are - // no GCs actively in progress. + // no GCs actively in progress. The sweep phase of a GC cycle + // for instance tries to preempt Ps at the very beginning. runtime.GC() // Start a goroutine with no sync safe-points. -- GitLab From e5ba7d3abf1e356f8cb7d760f95a389dd08c63ae Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 6 Dec 2021 22:09:12 -0500 Subject: [PATCH 2431/2500] net/http: remove arbitrary timeout in TestServerHijackGetsBackgroundByte_big This test fails with "timeout" once per couple of months. It may be that the arbitrary timeout is too short, or it may be that the test is detecting a real bug (perhaps a deadlock) and reporting it without sufficient information to debug. Either way, the arbitrary timeout is doing only harm: either it is too short, or it is preventing us from getting a useful goroutine dump when the test inevitably times out. Fixes #35498 (hopefully). Change-Id: Ic6bbb1ef8df2c111b9888ba9903f58633e7cb95d Reviewed-on: https://go-review.googlesource.com/c/go/+/369854 Trust: Bryan Mills Run-TryBot: Bryan Mills TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor Reviewed-by: Damien Neil --- src/net/http/serve_test.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index 82c1a6716f..d46400ef75 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -5998,11 +5998,7 @@ func TestServerHijackGetsBackgroundByte_big(t *testing.T) { t.Fatal(err) } - select { - case <-done: - case <-time.After(2 * time.Second): - t.Error("timeout") - } + <-done } // Issue 18319: test that the Server validates the request method. -- GitLab From 085d6ff5312a789b8c34c51e84e4a2b39a6631ca Mon Sep 17 00:00:00 2001 From: Jeremy Faller Date: Thu, 2 Dec 2021 13:47:39 -0500 Subject: [PATCH 2432/2500] doc/go1.18: add docs for -count when benchmarking CL 356669 Updates #47694 Change-Id: I49e0cdd3b34e81e9e44020a8eb1304d78249cd66 Reviewed-on: https://go-review.googlesource.com/c/go/+/368677 Trust: Jeremy Faller Run-TryBot: Jeremy Faller Reviewed-by: Michael Pratt TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor --- doc/go1.18.html | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 77c26bc257..4a09cb6773 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -782,11 +782,17 @@ Do not send CLs removing the interior tags from such phrases.
      testing

      - TODO: https://golang.org/cl/343883: increase alternation precedence + The precedence of / in the argument for -run and + -bench has been increased. A/B|C/D used to be + treated as A/(B|C)/D and is now treated as + (A/B)/(C/D).

      - TODO: https://golang.org/cl/356669: skip extra -count iterations if there are no tests + If the -run option does not select any tests, the + -count option is ignored. This could change the behavior of + existing tests in the unlikely case that a test changes the set of subtests + that are run each time the test function itself is run.

      -- GitLab From a08bbd964dd037331b2693aff731ec2d8376a721 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 18 Oct 2021 14:59:05 -0400 Subject: [PATCH 2433/2500] cmd/go: add missing cgo conditions in script tests Change-Id: I7cd1643b2dd5c00be84574d17830b1d5383643fa Reviewed-on: https://go-review.googlesource.com/c/go/+/356610 Trust: Bryan Mills Run-TryBot: Bryan Mills Reviewed-by: Ian Lance Taylor TryBot-Result: Gopher Robot Reviewed-by: Michael Matloob --- src/cmd/go/testdata/script/build_overlay.txt | 28 +++++++++---------- src/cmd/go/testdata/script/list_swigcxx.txt | 6 ++-- .../go/testdata/script/test_build_failure.txt | 2 +- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/cmd/go/testdata/script/build_overlay.txt b/src/cmd/go/testdata/script/build_overlay.txt index 2932b94e6c..56e812f44b 100644 --- a/src/cmd/go/testdata/script/build_overlay.txt +++ b/src/cmd/go/testdata/script/build_overlay.txt @@ -31,17 +31,17 @@ exec ./print_trimpath_two_files$GOEXE stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]main.go stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]other.go -go build -overlay overlay.json -o main_cgo_replace$GOEXE ./cgo_hello_replace -exec ./main_cgo_replace$GOEXE -stdout '^hello cgo\r?\n' +[cgo] go build -overlay overlay.json -o main_cgo_replace$GOEXE ./cgo_hello_replace +[cgo] exec ./main_cgo_replace$GOEXE +[cgo] stdout '^hello cgo\r?\n' -go build -overlay overlay.json -o main_cgo_quote$GOEXE ./cgo_hello_quote -exec ./main_cgo_quote$GOEXE -stdout '^hello cgo\r?\n' +[cgo] go build -overlay overlay.json -o main_cgo_quote$GOEXE ./cgo_hello_quote +[cgo] exec ./main_cgo_quote$GOEXE +[cgo] stdout '^hello cgo\r?\n' -go build -overlay overlay.json -o main_cgo_angle$GOEXE ./cgo_hello_angle -exec ./main_cgo_angle$GOEXE -stdout '^hello cgo\r?\n' +[cgo] go build -overlay overlay.json -o main_cgo_angle$GOEXE ./cgo_hello_angle +[cgo] exec ./main_cgo_angle$GOEXE +[cgo] stdout '^hello cgo\r?\n' go build -overlay overlay.json -o main_call_asm$GOEXE ./call_asm exec ./main_call_asm$GOEXE @@ -55,11 +55,11 @@ cp overlay/test_cache_different.go overlay/test_cache.go go list -overlay overlay.json -f '{{.Stale}}' ./test_cache stdout '^true$' -go list -compiled -overlay overlay.json -f '{{range .CompiledGoFiles}}{{. | printf "%s\n"}}{{end}}' ./cgo_hello_replace -cp stdout compiled_cgo_sources.txt -go run ../print_line_comments.go compiled_cgo_sources.txt -stdout $GOPATH[/\\]src[/\\]m[/\\]cgo_hello_replace[/\\]cgo_hello_replace.go -! stdout $GOPATH[/\\]src[/\\]m[/\\]overlay[/\\]hello.c +[cgo] go list -compiled -overlay overlay.json -f '{{range .CompiledGoFiles}}{{. | printf "%s\n"}}{{end}}' ./cgo_hello_replace +[cgo] cp stdout compiled_cgo_sources.txt +[cgo] go run ../print_line_comments.go compiled_cgo_sources.txt +[cgo] stdout $GOPATH[/\\]src[/\\]m[/\\]cgo_hello_replace[/\\]cgo_hello_replace.go +[cgo] ! stdout $GOPATH[/\\]src[/\\]m[/\\]overlay[/\\]hello.c # Run same tests but with gccgo. env GO111MODULE=off diff --git a/src/cmd/go/testdata/script/list_swigcxx.txt b/src/cmd/go/testdata/script/list_swigcxx.txt index c6acd9ecdb..d4227a80e8 100644 --- a/src/cmd/go/testdata/script/list_swigcxx.txt +++ b/src/cmd/go/testdata/script/list_swigcxx.txt @@ -2,17 +2,19 @@ [!exec:swig] skip [!exec:g++] skip +[!cgo] skip # CompiledGoFiles should contain 4 files: # a.go # a.swigcxx.go # _cgo_gotypes.go # a.cgo1.go +# +# These names we see here, other than a.go, will be from the build cache, +# so we just count them. go list -f '{{.CompiledGoFiles}}' -compiled=true example/swig -# These names we see here, other than a.go, will be from the build cache, -# so we just count them. stdout a\.go stdout -count=3 $GOCACHE diff --git a/src/cmd/go/testdata/script/test_build_failure.txt b/src/cmd/go/testdata/script/test_build_failure.txt index 8d13634c8c..e8c984f272 100644 --- a/src/cmd/go/testdata/script/test_build_failure.txt +++ b/src/cmd/go/testdata/script/test_build_failure.txt @@ -3,7 +3,7 @@ ! go test -x coverbad ! stderr '[\\/]coverbad\.test( |$)' # 'go test' should not claim to have run the test. stderr 'undefined: g' -stderr 'undefined: j' +[cgo] stderr 'undefined: j' -- go.mod -- module coverbad -- GitLab From 4300f105147dc0da9d1034704ad1cd24bedde5da Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 6 Dec 2021 13:36:42 -0500 Subject: [PATCH 2434/2500] build: for default bootstrap, use Go 1.17 if present, falling back to Go 1.4 Preparation for #44505, but safe for Go 1.18. Also fixes the default build on Macs, at least for people who have a $HOME/go1.17 or have run go install golang.org/dl/go1.17@latest go1.17 download Change-Id: I822f93e75498620fad87db2436376148c42f6bff Reviewed-on: https://go-review.googlesource.com/c/go/+/369914 Trust: Russ Cox Reviewed-by: Ian Lance Taylor --- src/cmd/dist/buildtool.go | 13 ++++++++++++- src/make.bash | 9 ++++++++- src/make.bat | 2 ++ src/make.rc | 3 +++ 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go index 75f04a975c..17538ad5a4 100644 --- a/src/cmd/dist/buildtool.go +++ b/src/cmd/dist/buildtool.go @@ -93,10 +93,21 @@ var ignoreSuffixes = []string{ "_test.go", } +var tryDirs = []string{ + "sdk/go1.17", + "go1.17", +} + func bootstrapBuildTools() { goroot_bootstrap := os.Getenv("GOROOT_BOOTSTRAP") if goroot_bootstrap == "" { - goroot_bootstrap = pathf("%s/go1.4", os.Getenv("HOME")) + home := os.Getenv("HOME") + goroot_bootstrap = pathf("%s/go1.4", home) + for _, d := range tryDirs { + if p := pathf("%s/%s", home, d); isdir(p) { + goroot_bootstrap = p + } + } } xprintf("Building Go toolchain1 using %s.\n", goroot_bootstrap) diff --git a/src/make.bash b/src/make.bash index 3310692a18..2d6c47272e 100755 --- a/src/make.bash +++ b/src/make.bash @@ -153,7 +153,14 @@ if [ "$1" = "-v" ]; then fi goroot_bootstrap_set=${GOROOT_BOOTSTRAP+"true"} -export GOROOT_BOOTSTRAP=${GOROOT_BOOTSTRAP:-$HOME/go1.4} +if [ -z "$GOROOT_BOOTSTRAP" ]; then + GOROOT_BOOTSTRAP="$HOME/go1.4" + for d in sdk/go1.17 go1.17; do + if [ -d "$HOME/$d" ]; then + GOROOT_BOOTSTRAP="$HOME/$d" + fi + done +fi export GOROOT="$(cd .. && pwd)" IFS=$'\n'; for go_exe in $(type -ap go); do if [ ! -x "$GOROOT_BOOTSTRAP/bin/go" ]; then diff --git a/src/make.bat b/src/make.bat index 8f2825b09a..6bffee050e 100644 --- a/src/make.bat +++ b/src/make.bat @@ -83,6 +83,8 @@ for /f "tokens=*" %%g in ('where go 2^>nul') do ( ) ) ) +if "x%GOROOT_BOOTSTRAP%"=="x" if exist "%HOMEDRIVE%%HOMEPATH%\go1.17" set GOROOT_BOOTSTRAP=%HOMEDRIVE%%HOMEPATH%\go1.17 +if "x%GOROOT_BOOTSTRAP%"=="x" if exist "%HOMEDRIVE%%HOMEPATH%\sdk\go1.17" set GOROOT_BOOTSTRAP=%HOMEDRIVE%%HOMEPATH%\sdk\go1.17 if "x%GOROOT_BOOTSTRAP%"=="x" set GOROOT_BOOTSTRAP=%HOMEDRIVE%%HOMEPATH%\Go1.4 :bootstrapset diff --git a/src/make.rc b/src/make.rc index ba8c5db2d9..37087d6357 100755 --- a/src/make.rc +++ b/src/make.rc @@ -55,6 +55,9 @@ goroot_bootstrap_set = 'true' if(! ~ $#GOROOT_BOOTSTRAP 1){ goroot_bootstrap_set = 'false' GOROOT_BOOTSTRAP = $home/go1.4 + for(d in sdk/go1.17 go1.17) + if(test -d $home/$d) + GOROOT_BOOTSTRAP = $home/$d } for(p in $path){ if(! test -x $GOROOT_BOOTSTRAP/bin/go){ -- GitLab From b37a5391f9e452aa779205add12bd89f44e3fcf0 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 6 Dec 2021 13:38:04 -0500 Subject: [PATCH 2435/2500] cmd/link, cmd/go: make version info easier to extract Reading the version information to date has required evaluating two pointers to strings (which themselves contain pointers to data), which means applying relocations, which can be very system-dependent. To simplify the lookup, inline the string data into the build info blob. This makes go version work on binaries built with external linking on darwin/arm64. Also test that at least the very basics work on a trivial binary, even in short mode. Change-Id: I463088c19e837ae0ce57e1278c7b72e74a80b2c4 Reviewed-on: https://go-review.googlesource.com/c/go/+/369977 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Gopher Robot Reviewed-by: Cherry Mui --- src/cmd/go/internal/modload/build.go | 35 ++++++----------- src/cmd/go/internal/work/exec.go | 10 +++-- src/cmd/go/testdata/script/version.txt | 13 ++++++- src/cmd/link/internal/ld/data.go | 29 ++++++++------ src/cmd/link/internal/ld/deadcode.go | 6 --- src/cmd/link/internal/ld/ld.go | 6 +++ src/debug/buildinfo/buildinfo.go | 54 ++++++++++++++++++-------- 7 files changed, 93 insertions(+), 60 deletions(-) diff --git a/src/cmd/go/internal/modload/build.go b/src/cmd/go/internal/modload/build.go index 0e0292ec15..bfc73cc2f9 100644 --- a/src/cmd/go/internal/modload/build.go +++ b/src/cmd/go/internal/modload/build.go @@ -346,33 +346,22 @@ func findModule(ld *loader, path string) (module.Version, bool) { } func ModInfoProg(info string, isgccgo bool) []byte { - // Inject a variable with the debug information as runtime.modinfo, - // but compile it in package main so that it is specific to the binary. - // The variable must be a literal so that it will have the correct value - // before the initializer for package main runs. - // - // The runtime startup code refers to the variable, which keeps it live - // in all binaries. - // - // Note: we use an alternate recipe below for gccgo (based on an - // init function) due to the fact that gccgo does not support - // applying a "//go:linkname" directive to a variable. This has - // drawbacks in that other packages may want to look at the module - // info in their init functions (see issue 29628), which won't - // work for gccgo. See also issue 30344. - - if !isgccgo { - return []byte(fmt.Sprintf(`package main -import _ "unsafe" -//go:linkname __debug_modinfo__ runtime.modinfo -var __debug_modinfo__ = %q -`, string(infoStart)+info+string(infoEnd))) - } else { + // Inject an init function to set runtime.modinfo. + // This is only used for gccgo - with gc we hand the info directly to the linker. + // The init function has the drawback that packages may want to + // look at the module info in their init functions (see issue 29628), + // which won't work. See also issue 30344. + if isgccgo { return []byte(fmt.Sprintf(`package main import _ "unsafe" //go:linkname __set_debug_modinfo__ runtime.setmodinfo func __set_debug_modinfo__(string) func init() { __set_debug_modinfo__(%q) } -`, string(infoStart)+info+string(infoEnd))) +`, ModInfoData(info))) } + return nil +} + +func ModInfoData(info string) []byte { + return []byte(string(infoStart) + info + string(infoEnd)) } diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index 03f8866cf2..2c040b8ff4 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -794,10 +794,13 @@ OverlayLoop: } if p.Internal.BuildInfo != "" && cfg.ModulesEnabled { - if err := b.writeFile(objdir+"_gomod_.go", modload.ModInfoProg(p.Internal.BuildInfo, cfg.BuildToolchainName == "gccgo")); err != nil { - return err + prog := modload.ModInfoProg(p.Internal.BuildInfo, cfg.BuildToolchainName == "gccgo") + if len(prog) > 0 { + if err := b.writeFile(objdir+"_gomod_.go", prog); err != nil { + return err + } + gofiles = append(gofiles, objdir+"_gomod_.go") } - gofiles = append(gofiles, objdir+"_gomod_.go") } // Compile Go. @@ -1394,6 +1397,7 @@ func (b *Builder) writeLinkImportcfg(a *Action, file string) error { fmt.Fprintf(&icfg, "packageshlib %s=%s\n", p1.ImportPath, p1.Shlib) } } + fmt.Fprintf(&icfg, "modinfo %q\n", modload.ModInfoData(a.Package.Internal.BuildInfo)) return b.writeFile(file, icfg.Bytes()) } diff --git a/src/cmd/go/testdata/script/version.txt b/src/cmd/go/testdata/script/version.txt index 8c08bae725..adca7af7a9 100644 --- a/src/cmd/go/testdata/script/version.txt +++ b/src/cmd/go/testdata/script/version.txt @@ -16,7 +16,14 @@ stdout '^go version' env GOFLAGS= env GO111MODULE=on -# Skip the builds below if we are running in short mode. + +# Check that very basic version lookup succeeds. +go build empty.go +go version empty$GOEXE +[cgo] go build -ldflags=-linkmode=external empty.go +[cgo] go version empty$GOEXE + +# Skip the remaining builds if we are running in short mode. [short] skip # Check that 'go version' and 'go version -m' work on a binary built in module mode. @@ -57,3 +64,7 @@ stdout '^\tmod\trsc.io/fortune\tv1.0.0' -- go.mod -- module m + +-- empty.go -- +package main +func main(){} diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 4d85977d43..95a8e0facb 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -2169,11 +2169,10 @@ func (ctxt *Link) buildinfo() { return } + // Write the buildinfo symbol, which go version looks for. + // The code reading this data is in package debug/buildinfo. ldr := ctxt.loader s := ldr.CreateSymForUpdate(".go.buildinfo", 0) - // On AIX, .go.buildinfo must be in the symbol table as - // it has relocations. - s.SetNotInSymbolTable(!ctxt.IsAIX()) s.SetType(sym.SBUILDINFO) s.SetAlign(16) // The \xff is invalid UTF-8, meant to make it less likely @@ -2186,16 +2185,24 @@ func (ctxt *Link) buildinfo() { if ctxt.Arch.ByteOrder == binary.BigEndian { data[len(prefix)+1] = 1 } + data[len(prefix)+1] |= 2 // signals new pointer-free format + data = appendString(data, strdata["runtime.buildVersion"]) + data = appendString(data, strdata["runtime.modinfo"]) + // MacOS linker gets very upset if the size os not a multiple of alignment. + for len(data)%16 != 0 { + data = append(data, 0) + } s.SetData(data) s.SetSize(int64(len(data))) - r, _ := s.AddRel(objabi.R_ADDR) - r.SetOff(16) - r.SetSiz(uint8(ctxt.Arch.PtrSize)) - r.SetSym(ldr.LookupOrCreateSym("runtime.buildVersion", 0)) - r, _ = s.AddRel(objabi.R_ADDR) - r.SetOff(16 + int32(ctxt.Arch.PtrSize)) - r.SetSiz(uint8(ctxt.Arch.PtrSize)) - r.SetSym(ldr.LookupOrCreateSym("runtime.modinfo", 0)) +} + +// appendString appends s to data, prefixed by its varint-encoded length. +func appendString(data []byte, s string) []byte { + var v [binary.MaxVarintLen64]byte + n := binary.PutUvarint(v[:], uint64(len(s))) + data = append(data, v[:n]...) + data = append(data, s...) + return data } // assign addresses to text diff --git a/src/cmd/link/internal/ld/deadcode.go b/src/cmd/link/internal/ld/deadcode.go index 7b57a85cde..dba22323b0 100644 --- a/src/cmd/link/internal/ld/deadcode.go +++ b/src/cmd/link/internal/ld/deadcode.go @@ -71,12 +71,6 @@ func (d *deadcodePass) init() { // runtime.unreachableMethod is a function that will throw if called. // We redirect unreachable methods to it. names = append(names, "runtime.unreachableMethod") - if !d.ctxt.linkShared && d.ctxt.BuildMode != BuildModePlugin { - // runtime.buildVersion and runtime.modinfo are referenced in .go.buildinfo section - // (see function buildinfo in data.go). They should normally be reachable from the - // runtime. Just make it explicit, in case. - names = append(names, "runtime.buildVersion", "runtime.modinfo") - } if d.ctxt.BuildMode == BuildModePlugin { names = append(names, objabi.PathToPrefix(*flagPluginPath)+"..inittask", objabi.PathToPrefix(*flagPluginPath)+".main", "go.plugin.tabs") diff --git a/src/cmd/link/internal/ld/ld.go b/src/cmd/link/internal/ld/ld.go index 7ff9c41f96..954921844c 100644 --- a/src/cmd/link/internal/ld/ld.go +++ b/src/cmd/link/internal/ld/ld.go @@ -85,6 +85,12 @@ func (ctxt *Link) readImportCfg(file string) { log.Fatalf(`%s:%d: invalid packageshlib: syntax is "packageshlib path=filename"`, file, lineNum) } ctxt.PackageShlib[before] = after + case "modinfo": + s, err := strconv.Unquote(args) + if err != nil { + log.Fatalf("%s:%d: invalid modinfo: %v", file, lineNum, err) + } + addstrdata1(ctxt, "runtime.modinfo="+s) } } } diff --git a/src/debug/buildinfo/buildinfo.go b/src/debug/buildinfo/buildinfo.go index f84429a342..2c0200e8dc 100644 --- a/src/debug/buildinfo/buildinfo.go +++ b/src/debug/buildinfo/buildinfo.go @@ -146,12 +146,18 @@ func readRawBuildInfo(r io.ReaderAt) (vers, mod string, err error) { } const ( buildInfoAlign = 16 - buildinfoSize = 32 + buildInfoSize = 32 ) - for ; !bytes.HasPrefix(data, buildInfoMagic); data = data[buildInfoAlign:] { - if len(data) < 32 { + for { + i := bytes.Index(data, buildInfoMagic) + if i < 0 || len(data)-i < buildInfoSize { return "", "", errNotGoExe } + if i%buildInfoAlign == 0 && len(data)-i >= buildInfoSize { + data = data[i:] + break + } + data = data[(i+buildInfoAlign-1)&^buildInfoAlign:] } // Decode the blob. @@ -161,25 +167,33 @@ func readRawBuildInfo(r io.ReaderAt) (vers, mod string, err error) { // Two virtual addresses to Go strings follow that: runtime.buildVersion, // and runtime.modinfo. // On 32-bit platforms, the last 8 bytes are unused. + // If the endianness has the 2 bit set, then the pointers are zero + // and the 32-byte header is followed by varint-prefixed string data + // for the two string values we care about. ptrSize := int(data[14]) - bigEndian := data[15] != 0 - var bo binary.ByteOrder - if bigEndian { - bo = binary.BigEndian - } else { - bo = binary.LittleEndian - } - var readPtr func([]byte) uint64 - if ptrSize == 4 { - readPtr = func(b []byte) uint64 { return uint64(bo.Uint32(b)) } + if data[15]&2 != 0 { + vers, data = decodeString(data[32:]) + mod, data = decodeString(data) } else { - readPtr = bo.Uint64 + bigEndian := data[15] != 0 + var bo binary.ByteOrder + if bigEndian { + bo = binary.BigEndian + } else { + bo = binary.LittleEndian + } + var readPtr func([]byte) uint64 + if ptrSize == 4 { + readPtr = func(b []byte) uint64 { return uint64(bo.Uint32(b)) } + } else { + readPtr = bo.Uint64 + } + vers = readString(x, ptrSize, readPtr, readPtr(data[16:])) + mod = readString(x, ptrSize, readPtr, readPtr(data[16+ptrSize:])) } - vers = readString(x, ptrSize, readPtr, readPtr(data[16:])) if vers == "" { return "", "", errNotGoExe } - mod = readString(x, ptrSize, readPtr, readPtr(data[16+ptrSize:])) if len(mod) >= 33 && mod[len(mod)-17] == '\n' { // Strip module framing: sentinel strings delimiting the module info. // These are cmd/go/internal/modload.infoStart and infoEnd. @@ -191,6 +205,14 @@ func readRawBuildInfo(r io.ReaderAt) (vers, mod string, err error) { return vers, mod, nil } +func decodeString(data []byte) (s string, rest []byte) { + u, n := binary.Uvarint(data) + if n <= 0 || u >= uint64(len(data)-n) { + return "", nil + } + return string(data[n : uint64(n)+u]), data[uint64(n)+u:] +} + // readString returns the string at address addr in the executable x. func readString(x exe, ptrSize int, readPtr func([]byte) uint64, addr uint64) string { hdr, err := x.ReadData(addr, uint64(2*ptrSize)) -- GitLab From 2ebe081288377fa4e9f71b1dab8557a042a9a670 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Wed, 1 Dec 2021 11:25:16 -0500 Subject: [PATCH 2436/2500] internal/fuzz: handle unrecoverable errors during minimization Previously, if an unrecoverable error occurred during minimization, then the input that caused the failure could not be retrieved by the coordinator. This was fine if minimizing a crash, since the coordinator could simply report the original error, and ignore the new one. However, if an error occurred while minimizing an interesting input, then we may lose an important error that would be better to report. This changes is a pretty major refactor of the minimization logic in order to support this. It removes minimization support of all types except []byte and string. There isn't compelling evidence that minimizing types like int or float64 are actually beneficial, so removing this seems fine. With this change, the coordinator requests that the worker minimize a single value at a time. The worker updates shared memory directly during minimzation, writing the *unmarshaled* bytes to the shared memory region. If a nonrecoverable error occurs during minimization, then the coordinator can get the unmarshaled value out of shared memory for that type being minimized. Fixes #48731 Change-Id: I4d1d449c411129b3c83b148e666bc70f09e95828 Reviewed-on: https://go-review.googlesource.com/c/go/+/367848 Trust: Bryan Mills Reviewed-by: Roland Shoemaker Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Gopher Robot --- .../script/test_fuzz_minimize_interesting.txt | 40 ++- src/internal/fuzz/mem.go | 8 +- src/internal/fuzz/minimize.go | 44 +-- src/internal/fuzz/minimize_test.go | 156 +---------- src/internal/fuzz/worker.go | 252 ++++++++---------- src/internal/fuzz/worker_test.go | 48 ++++ 6 files changed, 215 insertions(+), 333 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt b/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt index e017a4cad3..c9b04d02ea 100644 --- a/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt +++ b/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt @@ -17,12 +17,13 @@ env GOCACHE=$WORK/gocache exec ./fuzz.test$GOEXE -test.fuzzcachedir=$GOCACHE/fuzz -test.fuzz=FuzzMinCache -test.fuzztime=1000x go run check_cache.go $GOCACHE/fuzz/FuzzMinCache +go test -c -fuzz=. # Build using shared build cache for speed. +env GOCACHE=$WORK/gocache + # Test that minimization occurs for a crash that appears while minimizing a # newly found interesting input. There must be only one worker for this test to # be flaky like we want. -go test -c -fuzz=. # Build using shared build cache for speed. -env GOCACHE=$WORK/gocache -! exec ./fuzz.test$GOEXE -test.fuzzcachedir=$GOCACHE/fuzz -test.fuzz=FuzzMinimizerCrashInMinimization -test.fuzztime=10000x -test.parallel=1 +! exec ./fuzz.test$GOEXE -test.fuzzcachedir=$GOCACHE/fuzz -test.fuzz=FuzzMinimizerCrashInMinimization -test.run=FuzzMinimizerCrashInMinimization -test.fuzztime=10000x -test.parallel=1 ! stdout '^ok' stdout 'got the minimum size!' stdout -count=1 'flaky failure' @@ -31,6 +32,17 @@ stdout FAIL # Make sure the crash that was written will fail when run with go test ! go test -run=FuzzMinimizerCrashInMinimization . +# Test that a nonrecoverable error that occurs while minimizing an interesting +# input is reported correctly. +! exec ./fuzz.test$GOEXE -test.fuzzcachedir=$GOCACHE/fuzz -test.fuzz=FuzzMinimizerNonrecoverableCrashInMinimization -test.run=FuzzMinimizerNonrecoverableCrashInMinimization -test.fuzztime=10000x -test.parallel=1 +! stdout '^ok' +stdout -count=1 'fuzzing process hung or terminated unexpectedly while minimizing' +stdout -count=1 'EOF' +stdout FAIL + +# Make sure the crash that was written will fail when run with go test +! go test -run=FuzzMinimizerNonrecoverableCrashInMinimization . + -- go.mod -- module fuzz @@ -54,6 +66,7 @@ package fuzz import ( "bytes" "io" + "os" "testing" ) @@ -70,7 +83,7 @@ func FuzzMinimizerCrashInMinimization(f *testing.F) { // should be attempting minimization Y(io.Discard, b) } - if len(b) < 350 { + if len(b) < 55 { t.Error("flaky failure") } if len(b) == 50 { @@ -79,6 +92,25 @@ func FuzzMinimizerCrashInMinimization(f *testing.F) { }) } +func FuzzMinimizerNonrecoverableCrashInMinimization(f *testing.F) { + seed := make([]byte, 1000) + f.Add(seed) + f.Fuzz(func(t *testing.T, b []byte) { + if len(b) < 50 || len(b) > 1100 { + // Make sure that b is large enough that it can be minimized + return + } + if !bytes.Equal(b, seed) { + // This should have hit a new edge, and the interesting input + // should be attempting minimization + Y(io.Discard, b) + } + if len(b) < 55 { + os.Exit(19) + } + }) +} + func FuzzMinCache(f *testing.F) { seed := bytes.Repeat([]byte("a"), 20) f.Add(seed) diff --git a/src/internal/fuzz/mem.go b/src/internal/fuzz/mem.go index ccd4da2455..d6d45be20e 100644 --- a/src/internal/fuzz/mem.go +++ b/src/internal/fuzz/mem.go @@ -41,11 +41,17 @@ type sharedMemHeader struct { // May be reset by coordinator. count int64 - // valueLen is the length of the value that was last fuzzed. + // valueLen is the number of bytes in region which should be read. valueLen int // randState and randInc hold the state of a pseudo-random number generator. randState, randInc uint64 + + // rawInMem is true if the region holds raw bytes, which occurs during + // minimization. If true after the worker fails during minimization, this + // indicates that an unrecoverable error occurred, and the region can be + // used to retrive the raw bytes that caused the error. + rawInMem bool } // sharedMemSize returns the size needed for a shared memory buffer that can diff --git a/src/internal/fuzz/minimize.go b/src/internal/fuzz/minimize.go index c6e4559665..0e410fb86a 100644 --- a/src/internal/fuzz/minimize.go +++ b/src/internal/fuzz/minimize.go @@ -5,20 +5,14 @@ package fuzz import ( - "math" "reflect" ) func isMinimizable(t reflect.Type) bool { - for _, v := range zeroVals { - if t == reflect.TypeOf(v) { - return true - } - } - return false + return t == reflect.TypeOf("") || t == reflect.TypeOf([]byte(nil)) } -func minimizeBytes(v []byte, try func(interface{}) bool, shouldStop func() bool) { +func minimizeBytes(v []byte, try func([]byte) bool, shouldStop func() bool) { tmp := make([]byte, len(v)) // If minimization was successful at any point during minimizeBytes, // then the vals slice in (*workerServer).minimizeInput will point to @@ -99,37 +93,3 @@ func minimizeBytes(v []byte, try func(interface{}) bool, shouldStop func() bool) } } } - -func minimizeInteger(v uint, try func(interface{}) bool, shouldStop func() bool) { - // TODO(rolandshoemaker): another approach could be either unsetting/setting all bits - // (depending on signed-ness), or rotating bits? When operating on cast signed integers - // this would probably be more complex though. - for ; v != 0; v /= 10 { - if shouldStop() { - return - } - // We ignore the return value here because there is no point - // advancing the loop, since there is nothing after this check, - // and we don't return early because a smaller value could - // re-trigger the crash. - try(v) - } -} - -func minimizeFloat(v float64, try func(interface{}) bool, shouldStop func() bool) { - if math.IsNaN(v) { - return - } - minimized := float64(0) - for div := 10.0; minimized < v; div *= 10 { - if shouldStop() { - return - } - minimized = float64(int(v*div)) / div - if !try(minimized) { - // Since we are searching from least precision -> highest precision we - // can return early since we've already found the smallest value - return - } - } -} diff --git a/src/internal/fuzz/minimize_test.go b/src/internal/fuzz/minimize_test.go index 04d785ce40..f9041d1d34 100644 --- a/src/internal/fuzz/minimize_test.go +++ b/src/internal/fuzz/minimize_test.go @@ -129,150 +129,6 @@ func TestMinimizeInput(t *testing.T) { input: []interface{}{"ZZZZZ"}, expected: []interface{}{"A"}, }, - { - name: "int", - fn: func(e CorpusEntry) error { - i := e.Values[0].(int) - if i > 100 { - return fmt.Errorf("bad %v", e.Values[0]) - } - return nil - }, - input: []interface{}{123456}, - expected: []interface{}{123}, - }, - { - name: "int8", - fn: func(e CorpusEntry) error { - i := e.Values[0].(int8) - if i > 10 { - return fmt.Errorf("bad %v", e.Values[0]) - } - return nil - }, - input: []interface{}{int8(1<<7 - 1)}, - expected: []interface{}{int8(12)}, - }, - { - name: "int16", - fn: func(e CorpusEntry) error { - i := e.Values[0].(int16) - if i > 10 { - return fmt.Errorf("bad %v", e.Values[0]) - } - return nil - }, - input: []interface{}{int16(1<<15 - 1)}, - expected: []interface{}{int16(32)}, - }, - { - fn: func(e CorpusEntry) error { - i := e.Values[0].(int32) - if i > 10 { - return fmt.Errorf("bad %v", e.Values[0]) - } - return nil - }, - input: []interface{}{int32(1<<31 - 1)}, - expected: []interface{}{int32(21)}, - }, - { - name: "int32", - fn: func(e CorpusEntry) error { - i := e.Values[0].(uint) - if i > 10 { - return fmt.Errorf("bad %v", e.Values[0]) - } - return nil - }, - input: []interface{}{uint(123456)}, - expected: []interface{}{uint(12)}, - }, - { - name: "uint8", - fn: func(e CorpusEntry) error { - i := e.Values[0].(uint8) - if i > 10 { - return fmt.Errorf("bad %v", e.Values[0]) - } - return nil - }, - input: []interface{}{uint8(1<<8 - 1)}, - expected: []interface{}{uint8(25)}, - }, - { - name: "uint16", - fn: func(e CorpusEntry) error { - i := e.Values[0].(uint16) - if i > 10 { - return fmt.Errorf("bad %v", e.Values[0]) - } - return nil - }, - input: []interface{}{uint16(1<<16 - 1)}, - expected: []interface{}{uint16(65)}, - }, - { - name: "uint32", - fn: func(e CorpusEntry) error { - i := e.Values[0].(uint32) - if i > 10 { - return fmt.Errorf("bad %v", e.Values[0]) - } - return nil - }, - input: []interface{}{uint32(1<<32 - 1)}, - expected: []interface{}{uint32(42)}, - }, - { - name: "float32", - fn: func(e CorpusEntry) error { - if i := e.Values[0].(float32); i == 1.23 { - return nil - } - return fmt.Errorf("bad %v", e.Values[0]) - }, - input: []interface{}{float32(1.23456789)}, - expected: []interface{}{float32(1.2)}, - }, - { - name: "float64", - fn: func(e CorpusEntry) error { - if i := e.Values[0].(float64); i == 1.23 { - return nil - } - return fmt.Errorf("bad %v", e.Values[0]) - }, - input: []interface{}{float64(1.23456789)}, - expected: []interface{}{float64(1.2)}, - }, - } - - // If we are on a 64 bit platform add int64 and uint64 tests - if v := int64(1<<63 - 1); int64(int(v)) == v { - cases = append(cases, testcase{ - name: "int64", - fn: func(e CorpusEntry) error { - i := e.Values[0].(int64) - if i > 10 { - return fmt.Errorf("bad %v", e.Values[0]) - } - return nil - }, - input: []interface{}{int64(1<<63 - 1)}, - expected: []interface{}{int64(92)}, - }, testcase{ - name: "uint64", - fn: func(e CorpusEntry) error { - i := e.Values[0].(uint64) - if i > 10 { - return fmt.Errorf("bad %v", e.Values[0]) - } - return nil - }, - input: []interface{}{uint64(1<<64 - 1)}, - expected: []interface{}{uint64(18)}, - }) } for _, tc := range cases { @@ -284,9 +140,9 @@ func TestMinimizeInput(t *testing.T) { return time.Second, tc.fn(e) }, } - count := int64(0) + mem := &sharedMem{region: make([]byte, 100)} // big enough to hold value and header vals := tc.input - success, err := ws.minimizeInput(context.Background(), vals, &count, 0, nil) + success, err := ws.minimizeInput(context.Background(), vals, mem, minimizeArgs{}) if !success { t.Errorf("minimizeInput did not succeed") } @@ -310,17 +166,17 @@ func TestMinimizeFlaky(t *testing.T) { ws := &workerServer{fuzzFn: func(e CorpusEntry) (time.Duration, error) { return time.Second, errors.New("ohno") }} - keepCoverage := make([]byte, len(coverageSnapshot)) - count := int64(0) + mem := &sharedMem{region: make([]byte, 100)} // big enough to hold value and header vals := []interface{}{[]byte(nil)} - success, err := ws.minimizeInput(context.Background(), vals, &count, 0, keepCoverage) + args := minimizeArgs{KeepCoverage: make([]byte, len(coverageSnapshot))} + success, err := ws.minimizeInput(context.Background(), vals, mem, args) if success { t.Error("unexpected success") } if err != nil { t.Errorf("unexpected error: %v", err) } - if count != 1 { + if count := mem.header().count; count != 1 { t.Errorf("count: got %d, want 1", count) } } diff --git a/src/internal/fuzz/worker.go b/src/internal/fuzz/worker.go index 5be49d28f9..c39804cad1 100644 --- a/src/internal/fuzz/worker.go +++ b/src/internal/fuzz/worker.go @@ -15,6 +15,7 @@ import ( "io/ioutil" "os" "os/exec" + "reflect" "runtime" "sync" "time" @@ -255,7 +256,14 @@ func (w *worker) minimize(ctx context.Context, input fuzzMinimizeInput) (min fuz limit: input.limit, }, nil } - return fuzzResult{}, fmt.Errorf("fuzzing process hung or terminated unexpectedly while minimizing: %w", w.waitErr) + return fuzzResult{ + entry: entry, + crasherMsg: fmt.Sprintf("fuzzing process hung or terminated unexpectedly while minimizing: %v", err), + canMinimize: false, + limit: input.limit, + count: resp.Count, + totalDuration: resp.Duration, + }, nil } if input.crasherMsg != "" && resp.Err == "" { @@ -510,6 +518,9 @@ type minimizeArgs struct { // keep in minimized values. When provided, the worker will reject inputs that // don't cause at least one of these bits to be set. KeepCoverage []byte + + // Index is the index of the fuzz target parameter to be minimized. + Index int } // minimizeResponse contains results from workerServer.minimize. @@ -797,11 +808,10 @@ func (ws *workerServer) minimize(ctx context.Context, args minimizeArgs) (resp m // Minimize the values in vals, then write to shared memory. We only write // to shared memory after completing minimization. - // TODO(48165): If the worker terminates unexpectedly during minimization, - // the coordinator has no way of retrieving the crashing input. - success, err := ws.minimizeInput(ctx, vals, &mem.header().count, args.Limit, args.KeepCoverage) + success, err := ws.minimizeInput(ctx, vals, mem, args) if success { writeToMem(vals, mem) + mem.header().rawInMem = false resp.WroteToMem = true if err != nil { resp.Err = err.Error() @@ -813,14 +823,18 @@ func (ws *workerServer) minimize(ctx context.Context, args minimizeArgs) (resp m } // minimizeInput applies a series of minimizing transformations on the provided -// vals, ensuring that each minimization still causes an error in fuzzFn. It -// uses the context to determine how long to run, stopping once closed. It -// returns a bool indicating whether minimization was successful and an error if -// one was found. -func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, count *int64, limit int64, keepCoverage []byte) (success bool, retErr error) { +// vals, ensuring that each minimization still causes an error, or keeps +// coverage, in fuzzFn. It uses the context to determine how long to run, +// stopping once closed. It returns a bool indicating whether minimization was +// successful and an error if one was found. +func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, mem *sharedMem, args minimizeArgs) (success bool, retErr error) { + keepCoverage := args.KeepCoverage + memBytes := mem.valueRef() + bPtr := &memBytes + count := &mem.header().count shouldStop := func() bool { return ctx.Err() != nil || - (limit > 0 && *count >= limit) + (args.Limit > 0 && *count >= args.Limit) } if shouldStop() { return false, nil @@ -838,64 +852,25 @@ func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, c } else if retErr == nil { return false, nil } + mem.header().rawInMem = true - var valI int // tryMinimized runs the fuzz function with candidate replacing the value // at index valI. tryMinimized returns whether the input with candidate is // interesting for the same reason as the original input: it returns // an error if one was expected, or it preserves coverage. - tryMinimized := func(candidate interface{}) bool { - prev := vals[valI] - // Set vals[valI] to the candidate after it has been - // properly cast. We know that candidate must be of - // the same type as prev, so use that as a reference. - switch c := candidate.(type) { - case float64: - switch prev.(type) { - case float32: - vals[valI] = float32(c) - case float64: - vals[valI] = c - default: - panic("impossible") - } - case uint: - switch prev.(type) { - case uint: - vals[valI] = c - case uint8: - vals[valI] = uint8(c) - case uint16: - vals[valI] = uint16(c) - case uint32: - vals[valI] = uint32(c) - case uint64: - vals[valI] = uint64(c) - case int: - vals[valI] = int(c) - case int8: - vals[valI] = int8(c) - case int16: - vals[valI] = int16(c) - case int32: - vals[valI] = int32(c) - case int64: - vals[valI] = int64(c) - default: - panic("impossible") - } + tryMinimized := func(candidate []byte) bool { + prev := vals[args.Index] + switch prev.(type) { case []byte: - switch prev.(type) { - case []byte: - vals[valI] = c - case string: - vals[valI] = string(c) - default: - panic("impossible") - } + vals[args.Index] = candidate + case string: + vals[args.Index] = string(candidate) default: panic("impossible") } + copy(*bPtr, candidate) + *bPtr = (*bPtr)[:len(candidate)] + mem.setValueLen(len(candidate)) *count++ _, err := ws.fuzzFn(CorpusEntry{Values: vals}) if err != nil { @@ -911,58 +886,16 @@ func (ws *workerServer) minimizeInput(ctx context.Context, vals []interface{}, c if keepCoverage != nil && hasCoverageBit(keepCoverage, coverageSnapshot) { return true } - vals[valI] = prev + vals[args.Index] = prev return false } - - for valI = range vals { - if shouldStop() { - break - } - switch v := vals[valI].(type) { - case bool: - continue // can't minimize - case float32: - minimizeFloat(float64(v), tryMinimized, shouldStop) - case float64: - minimizeFloat(v, tryMinimized, shouldStop) - case uint: - minimizeInteger(v, tryMinimized, shouldStop) - case uint8: - minimizeInteger(uint(v), tryMinimized, shouldStop) - case uint16: - minimizeInteger(uint(v), tryMinimized, shouldStop) - case uint32: - minimizeInteger(uint(v), tryMinimized, shouldStop) - case uint64: - if uint64(uint(v)) != v { - // Skip minimizing a uint64 on 32 bit platforms, since we'll truncate the - // value when casting - continue - } - minimizeInteger(uint(v), tryMinimized, shouldStop) - case int: - minimizeInteger(uint(v), tryMinimized, shouldStop) - case int8: - minimizeInteger(uint(v), tryMinimized, shouldStop) - case int16: - minimizeInteger(uint(v), tryMinimized, shouldStop) - case int32: - minimizeInteger(uint(v), tryMinimized, shouldStop) - case int64: - if int64(int(v)) != v { - // Skip minimizing a int64 on 32 bit platforms, since we'll truncate the - // value when casting - continue - } - minimizeInteger(uint(v), tryMinimized, shouldStop) - case string: - minimizeBytes([]byte(v), tryMinimized, shouldStop) - case []byte: - minimizeBytes(v, tryMinimized, shouldStop) - default: - panic("unreachable") - } + switch v := vals[args.Index].(type) { + case string: + minimizeBytes([]byte(v), tryMinimized, shouldStop) + case []byte: + minimizeBytes(v, tryMinimized, shouldStop) + default: + panic("impossible") } return true, retErr } @@ -983,8 +916,14 @@ func (ws *workerServer) ping(ctx context.Context, args pingArgs) pingResponse { // workerServer). type workerClient struct { workerComm + m *mutator + + // mu is the mutex protecting the workerComm.fuzzIn pipe. This must be + // locked before making calls to the workerServer. It prevents + // workerClient.Close from closing fuzzIn while workerClient methods are + // writing to it concurrently, and prevents multiple callers from writing to + // fuzzIn concurrently. mu sync.Mutex - m *mutator } func newWorkerClient(comm workerComm, m *mutator) *workerClient { @@ -1025,7 +964,7 @@ var errSharedMemClosed = errors.New("internal error: shared memory was closed an // minimize tells the worker to call the minimize method. See // workerServer.minimize. -func (wc *workerClient) minimize(ctx context.Context, entryIn CorpusEntry, args minimizeArgs) (entryOut CorpusEntry, resp minimizeResponse, err error) { +func (wc *workerClient) minimize(ctx context.Context, entryIn CorpusEntry, args minimizeArgs) (entryOut CorpusEntry, resp minimizeResponse, retErr error) { wc.mu.Lock() defer wc.mu.Unlock() @@ -1039,34 +978,75 @@ func (wc *workerClient) minimize(ctx context.Context, entryIn CorpusEntry, args return CorpusEntry{}, minimizeResponse{}, err } mem.setValue(inp) - wc.memMu <- mem - - c := call{Minimize: &args} - callErr := wc.callLocked(ctx, c, &resp) - mem, ok = <-wc.memMu - if !ok { - return CorpusEntry{}, minimizeResponse{}, errSharedMemClosed - } defer func() { wc.memMu <- mem }() - resp.Count = mem.header().count - if resp.WroteToMem { - entryOut.Data = mem.valueCopy() - entryOut.Values, err = unmarshalCorpusFile(entryOut.Data) - h := sha256.Sum256(entryOut.Data) - name := fmt.Sprintf("%x", h[:4]) - entryOut.Path = name - entryOut.Parent = entryIn.Parent - entryOut.Generation = entryIn.Generation - if err != nil { - return CorpusEntry{}, minimizeResponse{}, fmt.Errorf("workerClient.minimize unmarshaling minimized value: %v", err) - } - } else { - // Did not minimize, but the original input may still be interesting, - // for example, if there was an error. - entryOut = entryIn + entryOut = entryIn + entryOut.Values, err = unmarshalCorpusFile(inp) + if err != nil { + return CorpusEntry{}, minimizeResponse{}, fmt.Errorf("workerClient.minimize unmarshaling provided value: %v", err) } + for i, v := range entryOut.Values { + if !isMinimizable(reflect.TypeOf(v)) { + continue + } - return entryOut, resp, callErr + wc.memMu <- mem + args.Index = i + c := call{Minimize: &args} + callErr := wc.callLocked(ctx, c, &resp) + mem, ok = <-wc.memMu + if !ok { + return CorpusEntry{}, minimizeResponse{}, errSharedMemClosed + } + + if callErr != nil { + retErr = callErr + if !mem.header().rawInMem { + // An unrecoverable error occurred before minimization began. + return entryIn, minimizeResponse{}, retErr + } + // An unrecoverable error occurred during minimization. mem now + // holds the raw, unmarshalled bytes of entryIn.Values[i] that + // caused the error. + switch entryOut.Values[i].(type) { + case string: + entryOut.Values[i] = string(mem.valueCopy()) + case []byte: + entryOut.Values[i] = mem.valueCopy() + default: + panic("impossible") + } + entryOut.Data = marshalCorpusFile(entryOut.Values...) + // Stop minimizing; another unrecoverable error is likely to occur. + break + } + + if resp.WroteToMem { + // Minimization succeeded, and mem holds the marshaled data. + entryOut.Data = mem.valueCopy() + entryOut.Values, err = unmarshalCorpusFile(entryOut.Data) + if err != nil { + return CorpusEntry{}, minimizeResponse{}, fmt.Errorf("workerClient.minimize unmarshaling minimized value: %v", err) + } + } + + // Prepare for next iteration of the loop. + if args.Timeout != 0 { + args.Timeout -= resp.Duration + if args.Timeout <= 0 { + break + } + } + if args.Limit != 0 { + args.Limit -= mem.header().count + if args.Limit <= 0 { + break + } + } + } + resp.Count = mem.header().count + h := sha256.Sum256(entryOut.Data) + entryOut.Path = fmt.Sprintf("%x", h[:4]) + return entryOut, resp, retErr } // fuzz tells the worker to call the fuzz method. See workerServer.fuzz. diff --git a/src/internal/fuzz/worker_test.go b/src/internal/fuzz/worker_test.go index ed9722f43a..e2ecf0a9c3 100644 --- a/src/internal/fuzz/worker_test.go +++ b/src/internal/fuzz/worker_test.go @@ -6,6 +6,7 @@ package fuzz import ( "context" + "errors" "flag" "fmt" "internal/race" @@ -13,6 +14,7 @@ import ( "os" "os/signal" "reflect" + "strconv" "testing" "time" ) @@ -156,3 +158,49 @@ func runBenchmarkWorker() { panic(err) } } + +func BenchmarkWorkerMinimize(b *testing.B) { + if race.Enabled { + b.Skip("TODO(48504): fix and re-enable") + } + + ws := &workerServer{ + workerComm: workerComm{memMu: make(chan *sharedMem, 1)}, + } + + mem, err := sharedMemTempFile(workerSharedMemSize) + if err != nil { + b.Fatalf("failed to create temporary shared memory file: %s", err) + } + defer func() { + if err := mem.Close(); err != nil { + b.Error(err) + } + }() + ws.memMu <- mem + + bytes := make([]byte, 1024) + ctx := context.Background() + for sz := 1; sz <= len(bytes); sz <<= 1 { + sz := sz + input := []interface{}{bytes[:sz]} + encodedVals := marshalCorpusFile(input...) + mem = <-ws.memMu + mem.setValue(encodedVals) + ws.memMu <- mem + b.Run(strconv.Itoa(sz), func(b *testing.B) { + i := 0 + ws.fuzzFn = func(_ CorpusEntry) (time.Duration, error) { + if i == 0 { + i++ + return time.Second, errors.New("initial failure for deflake") + } + return time.Second, nil + } + for i := 0; i < b.N; i++ { + b.SetBytes(int64(sz)) + ws.minimize(ctx, minimizeArgs{}) + } + }) + } +} -- GitLab From daf901810553b0ccdd9562523ecfad7d11e9b001 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Tue, 7 Dec 2021 13:50:51 -0500 Subject: [PATCH 2437/2500] cmd/go: fix flaky test Change-Id: I641c7b8bcf8b9a8f0637995b26eea0fbe2900ef9 Reviewed-on: https://go-review.googlesource.com/c/go/+/369978 Reviewed-by: Roland Shoemaker Reviewed-by: Bryan Mills Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Gopher Robot --- .../script/test_fuzz_minimize_interesting.txt | 123 +++++++++++++----- 1 file changed, 92 insertions(+), 31 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt b/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt index c9b04d02ea..5d0de17f6b 100644 --- a/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt +++ b/src/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt @@ -1,3 +1,4 @@ +[short] skip [!fuzz-instrumented] skip # Test that when an interesting value is discovered (one that expands coverage), @@ -15,7 +16,7 @@ go test -c -fuzz=. # Build using shared build cache for speed. env GOCACHE=$WORK/gocache exec ./fuzz.test$GOEXE -test.fuzzcachedir=$GOCACHE/fuzz -test.fuzz=FuzzMinCache -test.fuzztime=1000x -go run check_cache.go $GOCACHE/fuzz/FuzzMinCache +go run check_cache/check_cache.go $GOCACHE/fuzz/FuzzMinCache go test -c -fuzz=. # Build using shared build cache for speed. env GOCACHE=$WORK/gocache @@ -25,12 +26,12 @@ env GOCACHE=$WORK/gocache # be flaky like we want. ! exec ./fuzz.test$GOEXE -test.fuzzcachedir=$GOCACHE/fuzz -test.fuzz=FuzzMinimizerCrashInMinimization -test.run=FuzzMinimizerCrashInMinimization -test.fuzztime=10000x -test.parallel=1 ! stdout '^ok' -stdout 'got the minimum size!' +stdout -count=1 'got the minimum size!' stdout -count=1 'flaky failure' stdout FAIL - -# Make sure the crash that was written will fail when run with go test -! go test -run=FuzzMinimizerCrashInMinimization . +# Check that the input written to testdata will reproduce the error, and is the +# smallest possible. +go run check_testdata/check_testdata.go FuzzMinimizerCrashInMinimization 50 # Test that a nonrecoverable error that occurs while minimizing an interesting # input is reported correctly. @@ -39,9 +40,8 @@ stdout FAIL stdout -count=1 'fuzzing process hung or terminated unexpectedly while minimizing' stdout -count=1 'EOF' stdout FAIL - -# Make sure the crash that was written will fail when run with go test -! go test -run=FuzzMinimizerNonrecoverableCrashInMinimization . +# Check that the input written to testdata will reproduce the error. +go run check_testdata/check_testdata.go FuzzMinimizerNonrecoverableCrashInMinimization 100 -- go.mod -- module fuzz @@ -55,8 +55,8 @@ import ( "io" ) -func Y(w io.Writer, b []byte) { - if !bytes.Equal(b, []byte("y")) { +func Y(w io.Writer, s string) { + if !bytes.Equal([]byte(s), []byte("y")) { w.Write([]byte("not equal")) } } @@ -67,45 +67,54 @@ import ( "bytes" "io" "os" + "strings" "testing" + "unicode/utf8" ) func FuzzMinimizerCrashInMinimization(f *testing.F) { - seed := make([]byte, 1000) + seed := strings.Repeat("A", 1000) f.Add(seed) - f.Fuzz(func(t *testing.T, b []byte) { - if len(b) < 50 || len(b) > 1100 { + i := 3 + f.Fuzz(func(t *testing.T, s string) { + if len(s) < 50 || len(s) > 1100 { // Make sure that b is large enough that it can be minimized return } - if !bytes.Equal(b, seed) { - // This should have hit a new edge, and the interesting input - // should be attempting minimization - Y(io.Discard, b) + if s != seed { + // This should hit a new edge, and the interesting input + // should attempt minimization + Y(io.Discard, s) } - if len(b) < 55 { + if i > 0 { + // Don't let it fail right away. + i-- + } else if utf8.RuneCountInString(s) == len(s) && len(s) <= 100 { + // Make sure this only fails if the number of bytes in the + // marshaled string is the same as the unmarshaled string, + // so that we can check the length of the testdata file. t.Error("flaky failure") - } - if len(b) == 50 { - t.Log("got the minimum size!") + if len(s) == 50 { + t.Error("got the minimum size!") + } } }) } func FuzzMinimizerNonrecoverableCrashInMinimization(f *testing.F) { - seed := make([]byte, 1000) + seed := strings.Repeat("A", 1000) f.Add(seed) - f.Fuzz(func(t *testing.T, b []byte) { - if len(b) < 50 || len(b) > 1100 { - // Make sure that b is large enough that it can be minimized + i := 3 + f.Fuzz(func(t *testing.T, s string) { + if len(s) < 50 || len(s) > 1100 { return } - if !bytes.Equal(b, seed) { - // This should have hit a new edge, and the interesting input - // should be attempting minimization - Y(io.Discard, b) + if s != seed { + Y(io.Discard, s) } - if len(b) < 55 { + if i > 0 { + i-- + } else if utf8.RuneCountInString(s) == len(s) && len(s) <= 100 { os.Exit(19) } }) @@ -131,7 +140,59 @@ func sum(buf []byte) int { } return n } --- check_cache.go -- +-- check_testdata/check_testdata.go -- +//go:build ignore +// +build ignore + +// check_testdata.go checks that the string written +// is not longer than the provided length. +package main + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strconv" +) + +func main() { + wantLen, err := strconv.Atoi(os.Args[2]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + testName := os.Args[1] + dir := filepath.Join("testdata/fuzz", testName) + + files, err := ioutil.ReadDir(dir) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + + if len(files) == 0 { + fmt.Fprintf(os.Stderr, "expect at least one failure to be written to testdata\n") + os.Exit(1) + } + + fname := files[0].Name() + contents, err := ioutil.ReadFile(filepath.Join(dir, fname)) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + contentsLen := len(contents) - len(`go test fuzz v1 +string("") +`) + if got, want := contentsLen, wantLen; got > want { + fmt.Fprintf(os.Stderr, "expect length <= %d, got %d\n", want, got) + os.Exit(1) + } + fmt.Fprintf(os.Stderr, "%s\n", contents) +} + +-- check_cache/check_cache.go -- //go:build ignore // +build ignore -- GitLab From dc50d69119ca8070dd16fb968b46f21f854d89fb Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 7 Dec 2021 14:37:37 -0500 Subject: [PATCH 2438/2500] doc/go1.18: drop TODO for "Changes to the language" For #47694 Change-Id: I142776001eecb451e8722163cfd3f2ecb0ecf35c Reviewed-on: https://go-review.googlesource.com/c/go/+/369980 Trust: Austin Clements Reviewed-by: Jeremy Faller --- doc/go1.18.html | 4 ---- 1 file changed, 4 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 4a09cb6773..8131afffdb 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -25,10 +25,6 @@ Do not send CLs removing the interior tags from such phrases.

      Changes to the language

      -

      - TODO: complete this section -

      -

      Generics

      -- GitLab From e08d1fba37ad32fbe7e8d57cd75c9a88dfdde87f Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 7 Dec 2021 14:51:45 -0500 Subject: [PATCH 2439/2500] doc/go1.18: mention bytes.Cut and strings.Cut For #47694. Updates #46336. Change-Id: Ibbd058a1fd4d6b0aa38d3e8dc15b560d1e149f7e Reviewed-on: https://go-review.googlesource.com/c/go/+/369981 Trust: Austin Clements Reviewed-by: Jeremy Faller --- doc/go1.18.html | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 8131afffdb..06c6786bf2 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -403,6 +403,16 @@ Do not send CLs removing the interior tags from such phrases.

      bytes
      +

      + The new Cut function + slices a []byte around a separator. It can replace + and simplify many common uses of + Index, + IndexByte, + IndexRune, + and SplitN. +

      +

      Trim, TrimLeft, and TrimRight are now allocation free and, especially for @@ -414,10 +424,6 @@ Do not send CLs removing the interior tags from such phrases. handle Unicode punctuation and language-specific capitalization rules, and is superseded by the golang.org/x/text/cases package.

      - -

      - TODO: bytes.Cut. -

      @@ -709,6 +715,16 @@ Do not send CLs removing the interior tags from such phrases.
      strings
      +

      + The new Cut function + slices a string around a separator. It can replace + and simplify many common uses of + Index, + IndexByte, + IndexRune, + and SplitN. +

      +

      The new Clone function copies the input string without the returned cloned string referencing @@ -726,10 +742,6 @@ Do not send CLs removing the interior tags from such phrases. handle Unicode punctuation and language-specific capitalization rules, and is superseded by the golang.org/x/text/cases package.

      - -

      - TODO: strings.Cut. -

      -- GitLab From cf1ec173603f950aaccb549602ed0fee57e6b709 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 6 Dec 2021 16:30:19 -0800 Subject: [PATCH 2440/2500] cmd/compile: deal with unsatisfiable type assertion in some instantiations Deal with case where a certain instantiation of a generic function/method leads to an unsatisfiable type assertion or type case. In that case, the compiler was causing a fatal error while trying to create an impossible itab for the dictionary. To deal with that case, allow ITabLsym() to create a dummy itab even when the concrete type doesn't implement the interface. This dummy itab is analogous to the "negative" itabs created on-the-fly by the runtime. We will use the dummy itab in type asserts and type switches in instantiations that use that dictionary entry. Since the dummy itab can never be used for any real value at runtime (since the concrete type doesn't implement the interface), there will always be a failure for the corresponding type assertion or a non-match for the corresponding type-switch case. Fixes #50002 Change-Id: I1df05b1019533e1fc93dd7ab29f331a74fab9202 Reviewed-on: https://go-review.googlesource.com/c/go/+/369894 Reviewed-by: Keith Randall Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Gopher Robot --- .../compile/internal/reflectdata/reflect.go | 30 ++++++--- test/run.go | 1 + test/typeparam/issue50002.go | 64 +++++++++++++++++++ 3 files changed, 86 insertions(+), 9 deletions(-) create mode 100644 test/typeparam/issue50002.go diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 142b289dae..b1e2902385 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -846,14 +846,19 @@ func TypePtr(t *types.Type) *ir.AddrExpr { return typecheck.Expr(typecheck.NodAddr(n)).(*ir.AddrExpr) } -// ITabLsym returns the LSym representing the itab for concreate type typ -// implementing interface iface. +// ITabLsym returns the LSym representing the itab for concrete type typ implementing +// interface iface. A dummy tab will be created in the unusual case where typ doesn't +// implement iface. Normally, this wouldn't happen, because the typechecker would +// have reported a compile-time error. This situation can only happen when the +// destination type of a type assert or a type in a type switch is parameterized, so +// it may sometimes, but not always, be a type that can't implement the specified +// interface. func ITabLsym(typ, iface *types.Type) *obj.LSym { s, existed := ir.Pkgs.Itab.LookupOK(typ.LinkString() + "," + iface.LinkString()) lsym := s.Linksym() if !existed { - writeITab(lsym, typ, iface) + writeITab(lsym, typ, iface, true) } return lsym } @@ -865,7 +870,7 @@ func ITabAddr(typ, iface *types.Type) *ir.AddrExpr { lsym := s.Linksym() if !existed { - writeITab(lsym, typ, iface) + writeITab(lsym, typ, iface, false) } n := ir.NewLinksymExpr(base.Pos, lsym, types.Types[types.TUINT8]) @@ -1277,9 +1282,10 @@ func WriteRuntimeTypes() { } } -// writeITab writes the itab for concrete type typ implementing -// interface iface. -func writeITab(lsym *obj.LSym, typ, iface *types.Type) { +// writeITab writes the itab for concrete type typ implementing interface iface. If +// allowNonImplement is true, allow the case where typ does not implement iface, and just +// create a dummy itab with zeroed-out method entries. +func writeITab(lsym *obj.LSym, typ, iface *types.Type, allowNonImplement bool) { // TODO(mdempsky): Fix methodWrapper, geneq, and genhash (and maybe // others) to stop clobbering these. oldpos, oldfn := base.Pos, ir.CurFunc @@ -1306,7 +1312,8 @@ func writeITab(lsym *obj.LSym, typ, iface *types.Type) { } } } - if len(sigs) != 0 { + completeItab := len(sigs) == 0 + if !allowNonImplement && !completeItab { base.Fatalf("incomplete itab") } @@ -1323,7 +1330,12 @@ func writeITab(lsym *obj.LSym, typ, iface *types.Type) { o = objw.Uint32(lsym, o, types.TypeHash(typ)) // copy of type hash o += 4 // skip unused field for _, fn := range entries { - o = objw.SymPtrWeak(lsym, o, fn, 0) // method pointer for each method + if !completeItab { + // If typ doesn't implement iface, make method entries be zero. + o = objw.Uintptr(lsym, o, 0) + } else { + o = objw.SymPtrWeak(lsym, o, fn, 0) // method pointer for each method + } } // Nothing writes static itabs, so they are read only. objw.Global(lsym, int32(o), int16(obj.DUPOK|obj.RODATA)) diff --git a/test/run.go b/test/run.go index e17d9729bc..2ff7117ea9 100644 --- a/test/run.go +++ b/test/run.go @@ -2182,6 +2182,7 @@ var unifiedFailures = setOf( "fixedbugs/issue42058b.go", // unified IR doesn't report channel element too large "fixedbugs/issue49767.go", // unified IR doesn't report channel element too large "fixedbugs/issue49814.go", // unified IR doesn't report array type too large + "typeparam/issue50002.go", // pure stenciling leads to a static type assertion error ) func setOf(keys ...string) map[string]bool { diff --git a/test/typeparam/issue50002.go b/test/typeparam/issue50002.go new file mode 100644 index 0000000000..670fc2eae3 --- /dev/null +++ b/test/typeparam/issue50002.go @@ -0,0 +1,64 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test for cases where certain instantiations of a generic function (F in this +// example) will always fail on a type assertion or mismatch on a type case. + +package main + +import "fmt" + +type S struct{} + +func (S) M() byte { + return 0 +} + +type I[T any] interface { + M() T +} + +func F[T, A any](x I[T], shouldMatch bool) { + switch x.(type) { + case A: + if !shouldMatch { + fmt.Printf("wanted mis-match, got match") + } + default: + if shouldMatch { + fmt.Printf("wanted match, got mismatch") + } + } + + _, ok := x.(A) + if ok != shouldMatch { + fmt.Printf("ok: got %v, wanted %v", ok, shouldMatch) + } + + if !shouldMatch { + defer func() { + if shouldMatch { + fmt.Printf("Shouldn't have panicked") + } + recover() + }() + } + _ = x.(A) + if !shouldMatch { + fmt.Printf("Should have panicked") + } +} + +func main() { + // Test instantiation where the type switch/type asserts can't possibly succeed + // (since string does not implement I[byte]). + F[byte, string](S{}, false) + + // Test instantiation where the type switch/type asserts should succeed + // (since S does implement I[byte]) + F[byte, S](S{}, true) + F[byte, S](I[byte](S{}), true) +} -- GitLab From a3ae45ebe1b3576428f5eb27347704b2d099eab0 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Mon, 6 Dec 2021 16:05:55 -0500 Subject: [PATCH 2441/2500] runtime/pprof: consume tag for first CPU record profBuf.write uses an index in b.tags for each entry, even if that entry has no tag (that slice entry just remains 0). profBuf.read similarly returns a tags slice with exactly as many entries as there are records in data. profileBuilder.addCPUData iterates through the tags in lockstep with the data records. Except in the special case of the first record, where it forgets to increment tags. Thus the first read of profiling data has all tags off-by-one. To help avoid regressions, addCPUData is changed to assert that tags contains exactly the correct number of tags. For #50007. Change-Id: I5f32f93003297be8d6e33ad472c185d924a63256 Reviewed-on: https://go-review.googlesource.com/c/go/+/369741 Reviewed-by: Austin Clements Trust: Michael Pratt Run-TryBot: Michael Pratt TryBot-Result: Gopher Robot --- src/runtime/cpuprof.go | 2 ++ src/runtime/pprof/pprof_test.go | 12 +++++++++++- src/runtime/pprof/proto.go | 22 +++++++++++++++------- src/runtime/pprof/proto_test.go | 14 +++++++++----- 4 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/runtime/cpuprof.go b/src/runtime/cpuprof.go index 6076564716..48cef46fe9 100644 --- a/src/runtime/cpuprof.go +++ b/src/runtime/cpuprof.go @@ -200,6 +200,8 @@ func runtime_pprof_runtime_cyclesPerSecond() int64 { // If profiling is turned off and all the profile data accumulated while it was // on has been returned, readProfile returns eof=true. // The caller must save the returned data and tags before calling readProfile again. +// The returned data contains a whole number of records, and tags contains +// exactly one entry per record. // //go:linkname runtime_pprof_readProfile runtime/pprof.readProfile func runtime_pprof_readProfile() ([]uint64, []unsafe.Pointer, bool) { diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go index e32928b347..913f899593 100644 --- a/src/runtime/pprof/pprof_test.go +++ b/src/runtime/pprof/pprof_test.go @@ -1608,6 +1608,7 @@ func TestTryAdd(t *testing.T) { testCases := []struct { name string input []uint64 // following the input format assumed by profileBuilder.addCPUData. + count int // number of records in input. wantLocs [][]string // ordered location entries with function names. wantSamples []*profile.Sample // ordered samples, we care only about Value and the profile location IDs. }{{ @@ -1617,6 +1618,7 @@ func TestTryAdd(t *testing.T) { 3, 0, 500, // hz = 500. Must match the period. 5, 0, 50, inlinedCallerStack[0], inlinedCallerStack[1], }, + count: 2, wantLocs: [][]string{ {"runtime/pprof.inlinedCalleeDump", "runtime/pprof.inlinedCallerDump"}, }, @@ -1633,6 +1635,7 @@ func TestTryAdd(t *testing.T) { 7, 0, 10, inlinedCallerStack[0], inlinedCallerStack[1], inlinedCallerStack[0], inlinedCallerStack[1], 5, 0, 20, inlinedCallerStack[0], inlinedCallerStack[1], }, + count: 3, wantLocs: [][]string{{"runtime/pprof.inlinedCalleeDump", "runtime/pprof.inlinedCallerDump"}}, wantSamples: []*profile.Sample{ {Value: []int64{10, 10 * period}, Location: []*profile.Location{{ID: 1}, {ID: 1}}}, @@ -1646,6 +1649,7 @@ func TestTryAdd(t *testing.T) { // entry. The "stk" entry is actually the count. 4, 0, 0, 4242, }, + count: 2, wantLocs: [][]string{{"runtime/pprof.lostProfileEvent"}}, wantSamples: []*profile.Sample{ {Value: []int64{4242, 4242 * period}, Location: []*profile.Location{{ID: 1}}}, @@ -1664,6 +1668,7 @@ func TestTryAdd(t *testing.T) { 5, 0, 30, inlinedCallerStack[0], inlinedCallerStack[0], 4, 0, 40, inlinedCallerStack[0], }, + count: 3, // inlinedCallerDump shows up here because // runtime_expandFinalInlineFrame adds it to the stack frame. wantLocs: [][]string{{"runtime/pprof.inlinedCalleeDump"}, {"runtime/pprof.inlinedCallerDump"}}, @@ -1677,6 +1682,7 @@ func TestTryAdd(t *testing.T) { 3, 0, 500, // hz = 500. Must match the period. 9, 0, 10, recursionStack[0], recursionStack[1], recursionStack[2], recursionStack[3], recursionStack[4], recursionStack[5], }, + count: 2, wantLocs: [][]string{ {"runtime/pprof.recursionChainBottom"}, { @@ -1700,6 +1706,7 @@ func TestTryAdd(t *testing.T) { 5, 0, 50, inlinedCallerStack[0], inlinedCallerStack[1], 4, 0, 60, inlinedCallerStack[0], }, + count: 3, wantLocs: [][]string{{"runtime/pprof.inlinedCalleeDump", "runtime/pprof.inlinedCallerDump"}}, wantSamples: []*profile.Sample{ {Value: []int64{50, 50 * period}, Location: []*profile.Location{{ID: 1}}}, @@ -1712,6 +1719,7 @@ func TestTryAdd(t *testing.T) { 4, 0, 70, inlinedCallerStack[0], 5, 0, 80, inlinedCallerStack[0], inlinedCallerStack[1], }, + count: 3, wantLocs: [][]string{{"runtime/pprof.inlinedCalleeDump", "runtime/pprof.inlinedCallerDump"}}, wantSamples: []*profile.Sample{ {Value: []int64{70, 70 * period}, Location: []*profile.Location{{ID: 1}}}, @@ -1724,6 +1732,7 @@ func TestTryAdd(t *testing.T) { 3, 0, 500, // hz = 500. Must match the period. 4, 0, 70, inlinedCallerStack[0], }, + count: 2, wantLocs: [][]string{{"runtime/pprof.inlinedCalleeDump", "runtime/pprof.inlinedCallerDump"}}, wantSamples: []*profile.Sample{ {Value: []int64{70, 70 * period}, Location: []*profile.Location{{ID: 1}}}, @@ -1739,6 +1748,7 @@ func TestTryAdd(t *testing.T) { // from getting merged into above. 5, 0, 80, inlinedCallerStack[1], inlinedCallerStack[0], }, + count: 3, wantLocs: [][]string{ {"runtime/pprof.inlinedCalleeDump", "runtime/pprof.inlinedCallerDump"}, {"runtime/pprof.inlinedCallerDump"}, @@ -1751,7 +1761,7 @@ func TestTryAdd(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - p, err := translateCPUProfile(tc.input) + p, err := translateCPUProfile(tc.input, tc.count) if err != nil { t.Fatalf("translating profile: %v", err) } diff --git a/src/runtime/pprof/proto.go b/src/runtime/pprof/proto.go index 54e7a80183..073a076802 100644 --- a/src/runtime/pprof/proto.go +++ b/src/runtime/pprof/proto.go @@ -266,8 +266,9 @@ func newProfileBuilder(w io.Writer) *profileBuilder { } // addCPUData adds the CPU profiling data to the profile. -// The data must be a whole number of records, -// as delivered by the runtime. +// +// The data must be a whole number of records, as delivered by the runtime. +// len(tags) must be equal to the number of records in data. func (b *profileBuilder) addCPUData(data []uint64, tags []unsafe.Pointer) error { if !b.havePeriod { // first record is period @@ -282,6 +283,9 @@ func (b *profileBuilder) addCPUData(data []uint64, tags []unsafe.Pointer) error b.period = 1e9 / int64(data[2]) b.havePeriod = true data = data[3:] + // Consume tag slot. Note that there isn't a meaningful tag + // value for this record. + tags = tags[1:] } // Parse CPU samples from the profile. @@ -306,14 +310,14 @@ func (b *profileBuilder) addCPUData(data []uint64, tags []unsafe.Pointer) error if data[0] < 3 || tags != nil && len(tags) < 1 { return fmt.Errorf("malformed profile") } + if len(tags) < 1 { + return fmt.Errorf("mismatched profile records and tags") + } count := data[2] stk := data[3:data[0]] data = data[data[0]:] - var tag unsafe.Pointer - if tags != nil { - tag = tags[0] - tags = tags[1:] - } + tag := tags[0] + tags = tags[1:] if count == 0 && len(stk) == 1 { // overflow record @@ -327,6 +331,10 @@ func (b *profileBuilder) addCPUData(data []uint64, tags []unsafe.Pointer) error } b.m.lookup(stk, tag).count += int64(count) } + + if len(tags) != 0 { + return fmt.Errorf("mismatched profile records and tags") + } return nil } diff --git a/src/runtime/pprof/proto_test.go b/src/runtime/pprof/proto_test.go index 4a9749a83f..ea0ed9aefd 100644 --- a/src/runtime/pprof/proto_test.go +++ b/src/runtime/pprof/proto_test.go @@ -17,16 +17,20 @@ import ( "runtime" "strings" "testing" + "unsafe" ) // translateCPUProfile parses binary CPU profiling stack trace data // generated by runtime.CPUProfile() into a profile struct. // This is only used for testing. Real conversions stream the // data into the profileBuilder as it becomes available. -func translateCPUProfile(data []uint64) (*profile.Profile, error) { +// +// count is the number of records in data. +func translateCPUProfile(data []uint64, count int) (*profile.Profile, error) { var buf bytes.Buffer b := newProfileBuilder(&buf) - if err := b.addCPUData(data, nil); err != nil { + tags := make([]unsafe.Pointer, count) + if err := b.addCPUData(data, tags); err != nil { return nil, err } b.build() @@ -46,7 +50,7 @@ func TestConvertCPUProfileEmpty(t *testing.T) { var buf bytes.Buffer b := []uint64{3, 0, 500} // empty profile at 500 Hz (2ms sample period) - p, err := translateCPUProfile(b) + p, err := translateCPUProfile(b, 1) if err != nil { t.Fatalf("translateCPUProfile: %v", err) } @@ -120,7 +124,7 @@ func TestConvertCPUProfile(t *testing.T) { 5, 0, 40, uint64(addr2 + 1), uint64(addr2 + 2), // 40 samples in addr2 5, 0, 10, uint64(addr1 + 1), uint64(addr1 + 2), // 10 samples in addr1 } - p, err := translateCPUProfile(b) + p, err := translateCPUProfile(b, 4) if err != nil { t.Fatalf("translating profile: %v", err) } @@ -429,7 +433,7 @@ func TestEmptyStack(t *testing.T) { 3, 0, 500, // hz = 500 3, 0, 10, // 10 samples with an empty stack trace } - _, err := translateCPUProfile(b) + _, err := translateCPUProfile(b, 2) if err != nil { t.Fatalf("translating profile: %v", err) } -- GitLab From 0a15e7851a0ea1ebe1523bb70a6cfe56488ea2ef Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Mon, 6 Dec 2021 17:26:32 -0500 Subject: [PATCH 2442/2500] runtime/pprof: assert that labelHog samples are always labeled With https://golang.org/issue/50007 resolved, there are no known issues with pprof labels remaining. Thus, the 10% allowed error in TestLabelSystemstack should not be required. Drop it in favor of an explicit assertion that all samples containing labelHog are properly labeled. This is no flaky in my local testing. It is possible that other bugs will appear at larger testing scale, in which case this CL will be reverted, but then at least we will be aware of additional failure modes. For #50007. Change-Id: I1ef530c303bd9a01af649b8b08d4b35505e8aada Reviewed-on: https://go-review.googlesource.com/c/go/+/369744 Reviewed-by: Bryan Mills Trust: Michael Pratt Run-TryBot: Michael Pratt TryBot-Result: Gopher Robot --- src/runtime/pprof/pprof_test.go | 68 +++++++++++---------------------- 1 file changed, 22 insertions(+), 46 deletions(-) diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go index 913f899593..2e6165ff88 100644 --- a/src/runtime/pprof/pprof_test.go +++ b/src/runtime/pprof/pprof_test.go @@ -1425,52 +1425,8 @@ func TestLabelRace(t *testing.T) { // TestLabelSystemstack makes sure CPU profiler samples of goroutines running // on systemstack include the correct pprof labels. See issue #48577 func TestLabelSystemstack(t *testing.T) { - matchBasics := matchAndAvoidStacks(stackContainsLabeled, []string{"runtime.systemstack;key=value"}, avoidFunctions()) - matches := func(t *testing.T, prof *profile.Profile) bool { - if !matchBasics(t, prof) { - return false - } - - var withLabel, withoutLabel int64 - for _, s := range prof.Sample { - var systemstack, labelHog bool - for _, loc := range s.Location { - for _, l := range loc.Line { - switch l.Function.Name { - case "runtime.systemstack": - systemstack = true - case "runtime/pprof.labelHog": - labelHog = true - } - } - } - - if systemstack && labelHog { - if s.Label != nil && contains(s.Label["key"], "value") { - withLabel += s.Value[0] - } else { - withoutLabel += s.Value[0] - } - } - } - - // ratio on 2019 Intel MBP before/after CL 351751 for n=30 runs: - // before: mean=0.013 stddev=0.013 min=0.000 max=0.039 - // after : mean=0.996 stddev=0.007 min=0.967 max=1.000 - // - // TODO: Figure out why some samples (containing gcWriteBarrier, gcStart) - // still have labelHog without labels. Once fixed this test case can be - // simplified to just check that all samples containing labelHog() have the - // label, and no other samples do. - ratio := float64(withLabel) / float64((withLabel + withoutLabel)) - if ratio < 0.9 { - t.Logf("only %.1f%% of labelHog(systemstack()) samples have label", ratio*100) - return false - } - return true - } - - testCPUProfile(t, matches, func(dur time.Duration) { + matches := matchAndAvoidStacks(stackContainsLabeled, []string{"runtime.systemstack;key=value"}, avoidFunctions()) + p := testCPUProfile(t, matches, func(dur time.Duration) { Do(context.Background(), Labels("key", "value"), func(context.Context) { var wg sync.WaitGroup stop := make(chan struct{}) @@ -1487,6 +1443,26 @@ func TestLabelSystemstack(t *testing.T) { wg.Wait() }) }) + + // labelHog should always be labeled. + for _, s := range p.Sample { + for _, loc := range s.Location { + for _, l := range loc.Line { + if l.Function.Name != "runtime/pprof.labelHog" { + continue + } + + if s.Label == nil { + t.Errorf("labelHog sample labels got nil want key=value") + continue + } + if !contains(s.Label["key"], "value") { + t.Errorf("labelHog sample labels got %+v want contains key=value", s.Label) + continue + } + } + } + } } // labelHog is designed to burn CPU time in a way that a high number of CPU -- GitLab From 34573aeb9717cf20d768e640c263b294df5318a4 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Tue, 7 Dec 2021 22:51:46 +0000 Subject: [PATCH 2443/2500] Revert "build: for default bootstrap, use Go 1.17 if present, falling back to Go 1.4" This reverts https://golang.org/cl/369914. Reason for revert: Breaking previously working toolchain builds. For #44505. Change-Id: I09ae20e50109a600d036358118077d27669df39c Reviewed-on: https://go-review.googlesource.com/c/go/+/370138 Reviewed-by: Dmitri Shuralyov Trust: Michael Pratt Run-TryBot: Michael Pratt TryBot-Result: Gopher Robot --- src/cmd/dist/buildtool.go | 13 +------------ src/make.bash | 9 +-------- src/make.bat | 2 -- src/make.rc | 3 --- 4 files changed, 2 insertions(+), 25 deletions(-) diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go index 17538ad5a4..75f04a975c 100644 --- a/src/cmd/dist/buildtool.go +++ b/src/cmd/dist/buildtool.go @@ -93,21 +93,10 @@ var ignoreSuffixes = []string{ "_test.go", } -var tryDirs = []string{ - "sdk/go1.17", - "go1.17", -} - func bootstrapBuildTools() { goroot_bootstrap := os.Getenv("GOROOT_BOOTSTRAP") if goroot_bootstrap == "" { - home := os.Getenv("HOME") - goroot_bootstrap = pathf("%s/go1.4", home) - for _, d := range tryDirs { - if p := pathf("%s/%s", home, d); isdir(p) { - goroot_bootstrap = p - } - } + goroot_bootstrap = pathf("%s/go1.4", os.Getenv("HOME")) } xprintf("Building Go toolchain1 using %s.\n", goroot_bootstrap) diff --git a/src/make.bash b/src/make.bash index 2d6c47272e..3310692a18 100755 --- a/src/make.bash +++ b/src/make.bash @@ -153,14 +153,7 @@ if [ "$1" = "-v" ]; then fi goroot_bootstrap_set=${GOROOT_BOOTSTRAP+"true"} -if [ -z "$GOROOT_BOOTSTRAP" ]; then - GOROOT_BOOTSTRAP="$HOME/go1.4" - for d in sdk/go1.17 go1.17; do - if [ -d "$HOME/$d" ]; then - GOROOT_BOOTSTRAP="$HOME/$d" - fi - done -fi +export GOROOT_BOOTSTRAP=${GOROOT_BOOTSTRAP:-$HOME/go1.4} export GOROOT="$(cd .. && pwd)" IFS=$'\n'; for go_exe in $(type -ap go); do if [ ! -x "$GOROOT_BOOTSTRAP/bin/go" ]; then diff --git a/src/make.bat b/src/make.bat index 6bffee050e..8f2825b09a 100644 --- a/src/make.bat +++ b/src/make.bat @@ -83,8 +83,6 @@ for /f "tokens=*" %%g in ('where go 2^>nul') do ( ) ) ) -if "x%GOROOT_BOOTSTRAP%"=="x" if exist "%HOMEDRIVE%%HOMEPATH%\go1.17" set GOROOT_BOOTSTRAP=%HOMEDRIVE%%HOMEPATH%\go1.17 -if "x%GOROOT_BOOTSTRAP%"=="x" if exist "%HOMEDRIVE%%HOMEPATH%\sdk\go1.17" set GOROOT_BOOTSTRAP=%HOMEDRIVE%%HOMEPATH%\sdk\go1.17 if "x%GOROOT_BOOTSTRAP%"=="x" set GOROOT_BOOTSTRAP=%HOMEDRIVE%%HOMEPATH%\Go1.4 :bootstrapset diff --git a/src/make.rc b/src/make.rc index 37087d6357..ba8c5db2d9 100755 --- a/src/make.rc +++ b/src/make.rc @@ -55,9 +55,6 @@ goroot_bootstrap_set = 'true' if(! ~ $#GOROOT_BOOTSTRAP 1){ goroot_bootstrap_set = 'false' GOROOT_BOOTSTRAP = $home/go1.4 - for(d in sdk/go1.17 go1.17) - if(test -d $home/$d) - GOROOT_BOOTSTRAP = $home/$d } for(p in $path){ if(! test -x $GOROOT_BOOTSTRAP/bin/go){ -- GitLab From 016e6ebb4264f4b46e505bb404953cdb410f63f2 Mon Sep 17 00:00:00 2001 From: Hana Date: Tue, 7 Dec 2021 17:50:50 -0500 Subject: [PATCH 2444/2500] cmd/go: fix references to old `go mod editwork` That is replaced by `go work edit`. Change-Id: I39996c7bea0182a18edf6a1f70b6616c74099a1b Reviewed-on: https://go-review.googlesource.com/c/go/+/370139 Reviewed-by: Michael Matloob Trust: Hyang-Ah Hana Kim --- src/cmd/go/alldocs.go | 10 +++++----- src/cmd/go/internal/modload/init.go | 2 +- src/cmd/go/internal/workcmd/edit.go | 10 +++++----- src/cmd/go/internal/workcmd/init.go | 6 +++--- src/cmd/go/testdata/script/work_replace_conflict.txt | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index b9fca791be..f9a2b59c05 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -1407,10 +1407,10 @@ // // go work edit [editing flags] [go.work] // -// Editwork provides a command-line interface for editing go.work, +// Edit provides a command-line interface for editing go.work, // for use primarily by tools or scripts. It only reads go.work; // it does not look up information about the modules involved. -// If no file is specified, editwork looks for a go.work file in the current +// If no file is specified, Edit looks for a go.work file in the current // directory and its parent directories // // The editing flags specify a sequence of editing operations. @@ -1418,7 +1418,7 @@ // The -fmt flag reformats the go.work file without making other changes. // This reformatting is also implied by any other modifications that use or // rewrite the go.mod file. The only time this flag is needed is if no other -// flags are specified, as in 'go mod editwork -fmt'. +// flags are specified, as in 'go work edit -fmt'. // // The -use=path and -dropuse=path flags // add and drop a use directive from the go.work file's set of module directories. @@ -1478,10 +1478,10 @@ // // go work init [moddirs] // -// go mod initwork initializes and writes a new go.work file in the current +// Init initializes and writes a new go.work file in the current // directory, in effect creating a new workspace at the current directory. // -// go mod initwork optionally accepts paths to the workspace modules as arguments. +// go work init optionally accepts paths to the workspace modules as arguments. // If the argument is omitted, an empty workspace with no modules will be created. // // See the workspaces design proposal at diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 943547e71b..854c17d776 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -1019,7 +1019,7 @@ func makeMainModules(ms []module.Version, rootDirs []string, modFiles []*modfile if replacedByWorkFile[r.Old.Path] { continue } else if prev, ok := replacements[r.Old]; ok && !curModuleReplaces[r.Old] && prev != r.New { - base.Fatalf("go: conflicting replacements for %v:\n\t%v\n\t%v\nuse \"go mod editwork -replace %v=[override]\" to resolve", r.Old, prev, r.New, r.Old) + base.Fatalf("go: conflicting replacements for %v:\n\t%v\n\t%v\nuse \"go work edit -replace %v=[override]\" to resolve", r.Old, prev, r.New, r.Old) } curModuleReplaces[r.Old] = true replacements[r.Old] = r.New diff --git a/src/cmd/go/internal/workcmd/edit.go b/src/cmd/go/internal/workcmd/edit.go index 03a27f2bc6..c42000710e 100644 --- a/src/cmd/go/internal/workcmd/edit.go +++ b/src/cmd/go/internal/workcmd/edit.go @@ -24,10 +24,10 @@ import ( var cmdEdit = &base.Command{ UsageLine: "go work edit [editing flags] [go.work]", Short: "edit go.work from tools or scripts", - Long: `Editwork provides a command-line interface for editing go.work, + Long: `Edit provides a command-line interface for editing go.work, for use primarily by tools or scripts. It only reads go.work; it does not look up information about the modules involved. -If no file is specified, editwork looks for a go.work file in the current +If no file is specified, Edit looks for a go.work file in the current directory and its parent directories The editing flags specify a sequence of editing operations. @@ -35,7 +35,7 @@ The editing flags specify a sequence of editing operations. The -fmt flag reformats the go.work file without making other changes. This reformatting is also implied by any other modifications that use or rewrite the go.mod file. The only time this flag is needed is if no other -flags are specified, as in 'go mod editwork -fmt'. +flags are specified, as in 'go work edit -fmt'. The -use=path and -dropuse=path flags add and drop a use directive from the go.work file's set of module directories. @@ -123,7 +123,7 @@ func runEditwork(ctx context.Context, cmd *base.Command, args []string) { len(workedits) > 0 if !anyFlags { - base.Fatalf("go: no flags specified (see 'go help mod editwork').") + base.Fatalf("go: no flags specified (see 'go help work edit').") } if *editJSON && *editPrint { @@ -131,7 +131,7 @@ func runEditwork(ctx context.Context, cmd *base.Command, args []string) { } if len(args) > 1 { - base.Fatalf("go: 'go mod editwork' accepts at most one argument") + base.Fatalf("go: 'go help work edit' accepts at most one argument") } var gowork string if len(args) == 1 { diff --git a/src/cmd/go/internal/workcmd/init.go b/src/cmd/go/internal/workcmd/init.go index fde1483efb..2297ac20d0 100644 --- a/src/cmd/go/internal/workcmd/init.go +++ b/src/cmd/go/internal/workcmd/init.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// go mod initwork +// go work init package workcmd @@ -20,10 +20,10 @@ import ( var cmdInit = &base.Command{ UsageLine: "go work init [moddirs]", Short: "initialize workspace file", - Long: `go mod initwork initializes and writes a new go.work file in the current + Long: `Init initializes and writes a new go.work file in the current directory, in effect creating a new workspace at the current directory. -go mod initwork optionally accepts paths to the workspace modules as arguments. +go work init optionally accepts paths to the workspace modules as arguments. If the argument is omitted, an empty workspace with no modules will be created. See the workspaces design proposal at diff --git a/src/cmd/go/testdata/script/work_replace_conflict.txt b/src/cmd/go/testdata/script/work_replace_conflict.txt index e5677b21d7..81d1fcb043 100644 --- a/src/cmd/go/testdata/script/work_replace_conflict.txt +++ b/src/cmd/go/testdata/script/work_replace_conflict.txt @@ -2,7 +2,7 @@ # overriding it in the go.work file. ! go list -m example.com/dep -stderr 'go: conflicting replacements for example.com/dep@v1.0.0:\n\t./dep1\n\t./dep2\nuse "go mod editwork -replace example.com/dep@v1.0.0=\[override\]" to resolve' +stderr 'go: conflicting replacements for example.com/dep@v1.0.0:\n\t./dep1\n\t./dep2\nuse "go work edit -replace example.com/dep@v1.0.0=\[override\]" to resolve' go work edit -replace example.com/dep@v1.0.0=./dep1 go list -m example.com/dep stdout 'example.com/dep v1.0.0 => ./dep1' -- GitLab From a19e72cb89fd33e5bf1474887e267806f65b7a40 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 7 Dec 2021 09:50:44 -0800 Subject: [PATCH 2445/2500] doc/go1.18: move fuzzing to tools section For #47694 Change-Id: Idab1a5822a096447c71776ee4339c4262183ceb7 Reviewed-on: https://go-review.googlesource.com/c/go/+/370034 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gopher Robot Reviewed-by: Katie Hockman Trust: Katie Hockman --- doc/go1.18.html | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 06c6786bf2..10a05ad886 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -112,27 +112,6 @@ Do not send CLs removing the interior tags from such phrases. programs is likely very small.

      -

      Fuzzing

      - -

      - Go 1.18 includes an implementation of fuzzing as described by - the fuzzing proposal. -

      - -

      - See the fuzzing landing page to get - started. -

      - -

      - Please be aware that fuzzing can consume a lot of memory and may impact your - machine’s performance while it runs. Also be aware that the fuzzing engine - writes values that expand test coverage to a fuzz cache directory within - $GOCACHE/fuzz while it runs. There is currently no limit to the - number of files or total bytes that may be written to the fuzz cache, so it - may occupy a large amount of storage (possibly several GBs). -

      -

      Ports

      AMD64

      @@ -183,6 +162,27 @@ Do not send CLs removing the interior tags from such phrases.

      Tools

      +

      Fuzzing

      + +

      + Go 1.18 includes an implementation of fuzzing as described by + the fuzzing proposal. +

      + +

      + See the fuzzing landing page to get + started. +

      + +

      + Please be aware that fuzzing can consume a lot of memory and may impact your + machine’s performance while it runs. Also be aware that the fuzzing engine + writes values that expand test coverage to a fuzz cache directory within + $GOCACHE/fuzz while it runs. There is currently no limit to the + number of files or total bytes that may be written to the fuzz cache, so it + may occupy a large amount of storage (possibly several GBs). +

      +

      Go command

      -- GitLab From 08025a9d6d7d33f3ac0c78b4d067bdc339225507 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 7 Dec 2021 17:09:41 -0500 Subject: [PATCH 2446/2500] cmd: go get golang.org/x/tools@fd2bfb7 (Dec 7 2021) cd src/cmd go get golang.org/x/tools@fd2bfb7 go mod tidy go mod vendor Brings in fixes to cmd/vet for 'any' changes. Change-Id: I70a48d451bd99f5d82f91fd079fbdd1b4bac2520 Reviewed-on: https://go-review.googlesource.com/c/go/+/370136 Trust: Russ Cox Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 ++-- .../x/tools/go/analysis/passes/stdmethods/stdmethods.go | 6 ++++-- src/cmd/vendor/modules.txt | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 434081eb2f..f46c770c19 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -8,7 +8,7 @@ require ( golang.org/x/mod v0.6.0-dev.0.20211102181907-3a5865c02020 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 - golang.org/x/tools v0.1.8-0.20211202032535-e212aff8fd14 + golang.org/x/tools v0.1.9-0.20211207220608-fd2bfb79a16a ) require ( diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 4b7aa6994c..941011fe09 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -18,7 +18,7 @@ golang.org/x/sys v0.0.0-20211205182925-97ca703d548d h1:FjkYO/PPp4Wi0EAUOVLxePm7q golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/tools v0.1.8-0.20211202032535-e212aff8fd14 h1:KPFD5zp3T4bZL/kdosp4tGDJ6DKwUmYSWM0twy7w/bg= -golang.org/x/tools v0.1.8-0.20211202032535-e212aff8fd14/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.9-0.20211207220608-fd2bfb79a16a h1:G+TZ7v63o8mn+LBWOdnHaiypIhcgFZ6BDDnyX+RXDYg= +golang.org/x/tools v0.1.9-0.20211207220608-fd2bfb79a16a/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stdmethods/stdmethods.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stdmethods/stdmethods.go index 64a28ac0b9..cc9497179d 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stdmethods/stdmethods.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stdmethods/stdmethods.go @@ -61,7 +61,7 @@ var Analyzer = &analysis.Analyzer{ // we let it go. But if it does have a fmt.ScanState, then the // rest has to match. var canonicalMethods = map[string]struct{ args, results []string }{ - "As": {[]string{"interface{}"}, []string{"bool"}}, // errors.As + "As": {[]string{"any"}, []string{"bool"}}, // errors.As // "Flush": {{}, {"error"}}, // http.Flusher and jpeg.writer conflict "Format": {[]string{"=fmt.State", "rune"}, []string{}}, // fmt.Formatter "GobDecode": {[]string{"[]byte"}, []string{"error"}}, // gob.GobDecoder @@ -194,7 +194,9 @@ func matchParams(pass *analysis.Pass, expect []string, actual *types.Tuple, pref func matchParamType(expect string, actual types.Type) bool { expect = strings.TrimPrefix(expect, "=") // Overkill but easy. - return typeString(actual) == expect + t := typeString(actual) + return t == expect || + (t == "any" || t == "interface{}") && (expect == "any" || expect == "interface{}") } var errorType = types.Universe.Lookup("error").Type().Underlying().(*types.Interface) diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 5ce2fe2f63..22dd145a55 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -51,7 +51,7 @@ golang.org/x/sys/windows # golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 ## explicit; go 1.17 golang.org/x/term -# golang.org/x/tools v0.1.8-0.20211202032535-e212aff8fd14 +# golang.org/x/tools v0.1.9-0.20211207220608-fd2bfb79a16a ## explicit; go 1.17 golang.org/x/tools/cover golang.org/x/tools/go/analysis -- GitLab From 9fe77de3c198848b972915245e41ff26439b08aa Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Wed, 8 Dec 2021 09:49:04 -0500 Subject: [PATCH 2447/2500] debug/buildinfo: update test for CL 369977 As a side effect of the changes in cmd/go/internal/work in CL 369977, binaries built in GOPATH mode now include rudimentary build metadata for at least the package path and compiler in use. That seems like a strict improvement, but the test needs to be updated to reflect the newly-available metadata. Change-Id: I657c785e3e9992ed594c9524409f2d076f9eb376 Reviewed-on: https://go-review.googlesource.com/c/go/+/370234 Trust: Bryan Mills Run-TryBot: Bryan Mills Reviewed-by: Russ Cox TryBot-Result: Gopher Robot Reviewed-by: Cherry Mui --- src/debug/buildinfo/buildinfo_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/debug/buildinfo/buildinfo_test.go b/src/debug/buildinfo/buildinfo_test.go index fd31caf135..8346be0109 100644 --- a/src/debug/buildinfo/buildinfo_test.go +++ b/src/debug/buildinfo/buildinfo_test.go @@ -177,7 +177,9 @@ func TestReadFile(t *testing.T) { { name: "valid_gopath", build: buildWithGOPATH, - want: "go\tGOVERSION\n", + want: "go\tGOVERSION\n" + + "path\texample.com/m\n" + + "build\t-compiler=gc\n", }, { name: "invalid_gopath", -- GitLab From 2c85fcd47d6804d94a1fa4da65f756200ecf57a8 Mon Sep 17 00:00:00 2001 From: Bryan Mills Date: Tue, 7 Dec 2021 20:34:46 +0000 Subject: [PATCH 2448/2500] Revert "net: in (*netFD).dial, use the passed in local address if getsockname fails" This reverts CL 366536 Reason for revert: may have caused #50033 due to an invalid or partially-populated *TCPAddr Fixes #50033 Change-Id: Ia29ca4116503dba65d56e89caa46ba1c848d421a Reviewed-on: https://go-review.googlesource.com/c/go/+/369982 Trust: Bryan Mills Run-TryBot: Bryan Mills TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor --- src/net/server_test.go | 10 +--------- src/net/sock_posix.go | 16 +++++----------- 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/src/net/server_test.go b/src/net/server_test.go index b69cd29289..33d33b0337 100644 --- a/src/net/server_test.go +++ b/src/net/server_test.go @@ -200,17 +200,9 @@ func TestUnixAndUnixpacketServer(t *testing.T) { if c == nil { panic("Dial returned a nil Conn") } - rc := reflect.ValueOf(c) - if rc.IsNil() { + if rc := reflect.ValueOf(c); rc.Kind() == reflect.Pointer && rc.IsNil() { panic(fmt.Sprintf("Dial returned a nil %T", c)) } - fd := rc.Elem().FieldByName("fd") - if fd.IsNil() { - panic(fmt.Sprintf("Dial returned a %T with a nil fd", c)) - } - if addr := fd.Elem().FieldByName("laddr"); addr.IsNil() { - panic(fmt.Sprintf("Dial returned a %T whose fd has a nil laddr", c)) - } addr := c.LocalAddr() if addr == nil { panic(fmt.Sprintf("(%T).LocalAddr returned a nil Addr", c)) diff --git a/src/net/sock_posix.go b/src/net/sock_posix.go index 603fb2bb64..98a48229c7 100644 --- a/src/net/sock_posix.go +++ b/src/net/sock_posix.go @@ -156,24 +156,18 @@ func (fd *netFD) dial(ctx context.Context, laddr, raddr sockaddr, ctrlFn func(st } } // Record the local and remote addresses from the actual socket. - // For the local address, use - // 1) the one returned by Getsockname, if that succeeds; or - // 2) the one passed to us as the laddr parameter; or - // 3) nil. + // Get the local address by calling Getsockname. // For the remote address, use // 1) the one returned by the connect method, if any; or // 2) the one from Getpeername, if it succeeds; or // 3) the one passed to us as the raddr parameter. - var laddrName Addr = laddr - if lsa, err := syscall.Getsockname(fd.pfd.Sysfd); err == nil { - laddrName = fd.addrFunc()(lsa) - } + lsa, _ = syscall.Getsockname(fd.pfd.Sysfd) if crsa != nil { - fd.setAddr(laddrName, fd.addrFunc()(crsa)) + fd.setAddr(fd.addrFunc()(lsa), fd.addrFunc()(crsa)) } else if rsa, _ = syscall.Getpeername(fd.pfd.Sysfd); rsa != nil { - fd.setAddr(laddrName, fd.addrFunc()(rsa)) + fd.setAddr(fd.addrFunc()(lsa), fd.addrFunc()(rsa)) } else { - fd.setAddr(laddrName, raddr) + fd.setAddr(fd.addrFunc()(lsa), raddr) } return nil } -- GitLab From 3042ba34db86853c7035046716c4a00b2dbef2ed Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Tue, 7 Dec 2021 17:32:55 -0500 Subject: [PATCH 2449/2500] net/smtp: skip TestTLSSClient on all freebsd platforms This test seems like it needs attention from a TLS and/or FreeBSD expert. In the meantime, it needs to stop causing noise on the build dashboard. For #19229 Change-Id: If7e9e3533ae7cb29006a670c3e9df90512dcf9f2 Reviewed-on: https://go-review.googlesource.com/c/go/+/370137 Trust: Bryan Mills Run-TryBot: Bryan Mills TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor --- src/net/smtp/smtp_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/smtp/smtp_test.go b/src/net/smtp/smtp_test.go index 55219372d2..0f758f4a33 100644 --- a/src/net/smtp/smtp_test.go +++ b/src/net/smtp/smtp_test.go @@ -948,7 +948,7 @@ QUIT ` func TestTLSClient(t *testing.T) { - if (runtime.GOOS == "freebsd" && runtime.GOARCH == "amd64") || runtime.GOOS == "js" { + if runtime.GOOS == "freebsd" || runtime.GOOS == "js" { testenv.SkipFlaky(t, 19229) } ln := newLocalListener(t) -- GitLab From 46db6aa1573def4ba06dbf5c38e704d85dc303b6 Mon Sep 17 00:00:00 2001 From: Rhys Hiltner Date: Tue, 7 Dec 2021 13:32:24 -0800 Subject: [PATCH 2450/2500] runtime: fix flake in TestCgoPprofThread If the test's main goroutine receives a SIGPROF while creating the C-owned thread for the test, that sample will appear in the resulting profile. The root end of that stack will show a set of Go functions. The leaf end will be the C functions returned by the SetCgoTraceback handler, which will confuse the test runner. Add a label to the main goroutine while it calls in to C, so all profile samples that triggered the SetCgoTraceback handler are either correct, or can easily be excluded from the test's analysis. (The labels will not apply to the resulting C-owned thread, which does not use goroutines.) Fixes #43174 Change-Id: Ica3100ca0f191dcf91b30b0084e8541c5a25689f Reviewed-on: https://go-review.googlesource.com/c/go/+/370135 Reviewed-by: Michael Pratt Trust: Michael Pratt Run-TryBot: Michael Pratt Trust: Michael Knyszek TryBot-Result: Gopher Robot --- src/runtime/crash_cgo_test.go | 2 +- src/runtime/testdata/testprogcgo/threadpprof.go | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go index bfb260a143..058eae1c09 100644 --- a/src/runtime/crash_cgo_test.go +++ b/src/runtime/crash_cgo_test.go @@ -314,7 +314,7 @@ func testCgoPprof(t *testing.T, buildArg, runArg, top, bottom string) { defer os.Remove(fn) for try := 0; try < 2; try++ { - cmd := testenv.CleanCmdEnv(exec.Command(testenv.GoToolPath(t), "tool", "pprof", "-traces")) + cmd := testenv.CleanCmdEnv(exec.Command(testenv.GoToolPath(t), "tool", "pprof", "-tagignore=ignore", "-traces")) // Check that pprof works both with and without explicit executable on command line. if try == 0 { cmd.Args = append(cmd.Args, exe, fn) diff --git a/src/runtime/testdata/testprogcgo/threadpprof.go b/src/runtime/testdata/testprogcgo/threadpprof.go index 4bc84d16d0..e093f67e1e 100644 --- a/src/runtime/testdata/testprogcgo/threadpprof.go +++ b/src/runtime/testdata/testprogcgo/threadpprof.go @@ -64,6 +64,7 @@ void runCPUHogThread(void) { import "C" import ( + "context" "fmt" "os" "runtime" @@ -98,7 +99,14 @@ func pprofThread() { os.Exit(2) } - C.runCPUHogThread() + // This goroutine may receive a profiling signal while creating the C-owned + // thread. If it does, the SetCgoTraceback handler will make the leaf end of + // the stack look almost (but not exactly) like the stacks the test case is + // trying to find. Attach a profiler label so the test can filter out those + // confusing samples. + pprof.Do(context.Background(), pprof.Labels("ignore", "ignore"), func(ctx context.Context) { + C.runCPUHogThread() + }) time.Sleep(1*time.Second) -- GitLab From f5b5939c28ecb8b8c0897584fed78589c27348f6 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 6 Dec 2021 13:36:42 -0500 Subject: [PATCH 2451/2500] build: for default bootstrap, use Go 1.17 if present, falling back to Go 1.4 Preparation for #44505, but safe for Go 1.18. Also fixes the default build on Macs, at least for people who have a $HOME/go1.17 or have run go install golang.org/dl/go1.17@latest go1.17 download Replay of CL 369914 after revert in CL 370138. Only change is adding 'export GOROOT_BOOTSTRAP' in make.bash. Change-Id: I8ced4e87a9dc0f05cc49095578b401ae6212ac85 Reviewed-on: https://go-review.googlesource.com/c/go/+/370274 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Cuong Manh Le TryBot-Result: Gopher Robot --- src/cmd/dist/buildtool.go | 13 ++++++++++++- src/make.bash | 11 ++++++++++- src/make.bat | 2 ++ src/make.rc | 3 +++ 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go index 75f04a975c..17538ad5a4 100644 --- a/src/cmd/dist/buildtool.go +++ b/src/cmd/dist/buildtool.go @@ -93,10 +93,21 @@ var ignoreSuffixes = []string{ "_test.go", } +var tryDirs = []string{ + "sdk/go1.17", + "go1.17", +} + func bootstrapBuildTools() { goroot_bootstrap := os.Getenv("GOROOT_BOOTSTRAP") if goroot_bootstrap == "" { - goroot_bootstrap = pathf("%s/go1.4", os.Getenv("HOME")) + home := os.Getenv("HOME") + goroot_bootstrap = pathf("%s/go1.4", home) + for _, d := range tryDirs { + if p := pathf("%s/%s", home, d); isdir(p) { + goroot_bootstrap = p + } + } } xprintf("Building Go toolchain1 using %s.\n", goroot_bootstrap) diff --git a/src/make.bash b/src/make.bash index 3310692a18..9acf079c24 100755 --- a/src/make.bash +++ b/src/make.bash @@ -153,7 +153,16 @@ if [ "$1" = "-v" ]; then fi goroot_bootstrap_set=${GOROOT_BOOTSTRAP+"true"} -export GOROOT_BOOTSTRAP=${GOROOT_BOOTSTRAP:-$HOME/go1.4} +if [ -z "$GOROOT_BOOTSTRAP" ]; then + GOROOT_BOOTSTRAP="$HOME/go1.4" + for d in sdk/go1.17 go1.17; do + if [ -d "$HOME/$d" ]; then + GOROOT_BOOTSTRAP="$HOME/$d" + fi + done +fi +export GOROOT_BOOTSTRAP + export GOROOT="$(cd .. && pwd)" IFS=$'\n'; for go_exe in $(type -ap go); do if [ ! -x "$GOROOT_BOOTSTRAP/bin/go" ]; then diff --git a/src/make.bat b/src/make.bat index 8f2825b09a..6bffee050e 100644 --- a/src/make.bat +++ b/src/make.bat @@ -83,6 +83,8 @@ for /f "tokens=*" %%g in ('where go 2^>nul') do ( ) ) ) +if "x%GOROOT_BOOTSTRAP%"=="x" if exist "%HOMEDRIVE%%HOMEPATH%\go1.17" set GOROOT_BOOTSTRAP=%HOMEDRIVE%%HOMEPATH%\go1.17 +if "x%GOROOT_BOOTSTRAP%"=="x" if exist "%HOMEDRIVE%%HOMEPATH%\sdk\go1.17" set GOROOT_BOOTSTRAP=%HOMEDRIVE%%HOMEPATH%\sdk\go1.17 if "x%GOROOT_BOOTSTRAP%"=="x" set GOROOT_BOOTSTRAP=%HOMEDRIVE%%HOMEPATH%\Go1.4 :bootstrapset diff --git a/src/make.rc b/src/make.rc index ba8c5db2d9..37087d6357 100755 --- a/src/make.rc +++ b/src/make.rc @@ -55,6 +55,9 @@ goroot_bootstrap_set = 'true' if(! ~ $#GOROOT_BOOTSTRAP 1){ goroot_bootstrap_set = 'false' GOROOT_BOOTSTRAP = $home/go1.4 + for(d in sdk/go1.17 go1.17) + if(test -d $home/$d) + GOROOT_BOOTSTRAP = $home/$d } for(p in $path){ if(! test -x $GOROOT_BOOTSTRAP/bin/go){ -- GitLab From c759ec228435e387a5c863b6b886b49a055fa80a Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 7 Dec 2021 16:29:21 -0500 Subject: [PATCH 2452/2500] doc/go1.18: clarify additions to net package API For #47694. Updates #46518. Change-Id: Ife3a8d3d6a1c50f55b5ab15730d5a6bd3ec512e1 Reviewed-on: https://go-review.googlesource.com/c/go/+/370134 Trust: Austin Clements Reviewed-by: Damien Neil --- doc/go1.18.html | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 10a05ad886..ad08083793 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -360,9 +360,15 @@ Do not send CLs removing the interior tags from such phrases. a network CIDR prefix.

      - The net package now has methods to send and receive UDP packets - using netip.Addr values instead of the relatively heavy - *net.UDPAddr values. + The net package includes new + methods that parallel existing methods, but + return netip.AddrPort instead of the + heavier-weight net.IP or + *net.UDPAddr types. + The net package also now includes functions and methods + to convert between the existing + TCPAddr/UDPAddr + types and netip.AddrPort.

      TODO

      @@ -599,12 +605,6 @@ Do not send CLs removing the interior tags from such phrases.
      net.Error.Temporary has been deprecated.

      - -
      -

      - TODO: Several new net APIs. -

      -
      net/http
      -- GitLab From ac7e950d385b871ca28e1ac723d6ad97ebe3a4d7 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sat, 4 Dec 2021 09:35:34 -0500 Subject: [PATCH 2453/2500] go/types: sort to reduce computational complexity of initOrder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Our calculation of initOrder builds the dependency graph and then removes function nodes approximately at random. While profiling, I noticed that this latter step introduces a superlinear algorithm into our type checking pass, which can dominate type checking for large packages such as runtime. It is hard to analyze this rigorously, but to give an idea of how such a non-linearity could arise, suppose the following assumptions hold: - Every function makes D calls at random to other functions in the package, for some fixed constant D. - The number of functions is proportional to N, the size of the package. Under these simplified assumptions, the cost of removing an arbitrary function F is P*D, where P is the expected number of functions calling F. P has a Poisson distribution with mean D. Now consider the fact that when removing a function F in position i, we recursively pay the cost of copying F's predecessors and successors for each node in the remaining unremoved subgraph of functions containing F. With our assumptions, the size of this subgraph is proportional to (N-i), the number of remaining functions to remove. Therefore, the total cost of removing functions is proportional to P*D*Σᴺ(N-i) which is proportional to N². However, if we remove functions in ascending order of cost, we can partition by the number of predecessors, and the total cost of removing functions is proportional to N*D*Σ(PMF(X)) where PMF is the probability mass function of P. In other words cost is proportional to N. Assuming the above analysis is correct, it is still the case that the initial assumptions are naive. Many large packages are more accurately characterized as combinations of many smaller packages. Nevertheless, it is intuitively clear that removing expensive nodes last should be cheaper. Therefore, we sort by cost first before removing nodes in dependencyGraph. We also move deletes to the outer loop, to avoid redundant deletes. By inspection, this avoids a bug where n may not have been removed from its successors if n had no predecessors. name old time/op new time/op delta Check/runtime/funcbodies/noinfo-8 568ms ±25% 82ms ± 1% -85.53% (p=0.000 n=8+10) name old lines/s new lines/s delta Check/runtime/funcbodies/noinfo-8 93.1k ±56% 705.1k ± 1% +657.63% (p=0.000 n=10+10) Updates #49856 Change-Id: Id2e70d67401af19205e1e0b9947baa16dd6506f0 Reviewed-on: https://go-review.googlesource.com/c/go/+/369434 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Gopher Robot --- src/go/types/initorder.go | 62 ++++++++++++++++++++++++++------------- src/go/types/self_test.go | 1 + 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/src/go/types/initorder.go b/src/go/types/initorder.go index 77a739c7c1..27595ae233 100644 --- a/src/go/types/initorder.go +++ b/src/go/types/initorder.go @@ -7,6 +7,7 @@ package types import ( "container/heap" "fmt" + "sort" ) // initOrder computes the Info.InitOrder for package variables. @@ -184,6 +185,12 @@ type graphNode struct { ndeps int // number of outstanding dependencies before this object can be initialized } +// cost returns the cost of removing this node, which involves copying each +// predecessor to each successor (and vice-versa). +func (n *graphNode) cost() int { + return len(n.pred) * len(n.succ) +} + type nodeSet map[*graphNode]bool func (s *nodeSet) add(p *graphNode) { @@ -221,35 +228,48 @@ func dependencyGraph(objMap map[Object]*declInfo) []*graphNode { } } + var G, funcG []*graphNode // separate non-functions and functions + for _, n := range M { + if _, ok := n.obj.(*Func); ok { + funcG = append(funcG, n) + } else { + G = append(G, n) + } + } + // remove function nodes and collect remaining graph nodes in G // (Mutually recursive functions may introduce cycles among themselves // which are permitted. Yet such cycles may incorrectly inflate the dependency // count for variables which in turn may not get scheduled for initialization // in correct order.) - var G []*graphNode - for obj, n := range M { - if _, ok := obj.(*Func); ok { - // connect each predecessor p of n with each successor s - // and drop the function node (don't collect it in G) - for p := range n.pred { - // ignore self-cycles - if p != n { - // Each successor s of n becomes a successor of p, and - // each predecessor p of n becomes a predecessor of s. - for s := range n.succ { - // ignore self-cycles - if s != n { - p.succ.add(s) - s.pred.add(p) - delete(s.pred, n) // remove edge to n - } + // + // Note that because we recursively copy predecessors and successors + // throughout the function graph, the cost of removing a function at + // position X is proportional to cost * (len(funcG)-X). Therefore, we should + // remove high-cost functions last. + sort.Slice(funcG, func(i, j int) bool { + return funcG[i].cost() < funcG[j].cost() + }) + for _, n := range funcG { + // connect each predecessor p of n with each successor s + // and drop the function node (don't collect it in G) + for p := range n.pred { + // ignore self-cycles + if p != n { + // Each successor s of n becomes a successor of p, and + // each predecessor p of n becomes a predecessor of s. + for s := range n.succ { + // ignore self-cycles + if s != n { + p.succ.add(s) + s.pred.add(p) } - delete(p.succ, n) // remove edge to n } + delete(p.succ, n) // remove edge to n } - } else { - // collect non-function nodes - G = append(G, n) + } + for s := range n.succ { + delete(s.pred, n) // remove edge to n } } diff --git a/src/go/types/self_test.go b/src/go/types/self_test.go index 55436d3b62..a1af85f27b 100644 --- a/src/go/types/self_test.go +++ b/src/go/types/self_test.go @@ -36,6 +36,7 @@ func BenchmarkCheck(b *testing.B) { "net/http", "go/parser", "go/constant", + "runtime", filepath.Join("go", "internal", "gcimporter"), } { b.Run(path.Base(p), func(b *testing.B) { -- GitLab From 6b609110fdfab4a496c246889f1e67fd7cba61df Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Sun, 5 Dec 2021 22:09:32 -0500 Subject: [PATCH 2454/2500] cmd/compile/internal/types2: sort to reduce computational complexity of initOrder This is a clean port of CL 369434 to types2. Change-Id: I3f9f80757bfbefb7b0417eef9e7b7c74c4c100b9 Reviewed-on: https://go-review.googlesource.com/c/go/+/369474 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Gopher Robot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/initorder.go | 62 +++++++++++++------- src/cmd/compile/internal/types2/self_test.go | 1 + 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/src/cmd/compile/internal/types2/initorder.go b/src/cmd/compile/internal/types2/initorder.go index 4081627666..cf6110baa9 100644 --- a/src/cmd/compile/internal/types2/initorder.go +++ b/src/cmd/compile/internal/types2/initorder.go @@ -7,6 +7,7 @@ package types2 import ( "container/heap" "fmt" + "sort" ) // initOrder computes the Info.InitOrder for package variables. @@ -190,6 +191,12 @@ type graphNode struct { ndeps int // number of outstanding dependencies before this object can be initialized } +// cost returns the cost of removing this node, which involves copying each +// predecessor to each successor (and vice-versa). +func (n *graphNode) cost() int { + return len(n.pred) * len(n.succ) +} + type nodeSet map[*graphNode]bool func (s *nodeSet) add(p *graphNode) { @@ -227,35 +234,48 @@ func dependencyGraph(objMap map[Object]*declInfo) []*graphNode { } } + var G, funcG []*graphNode // separate non-functions and functions + for _, n := range M { + if _, ok := n.obj.(*Func); ok { + funcG = append(funcG, n) + } else { + G = append(G, n) + } + } + // remove function nodes and collect remaining graph nodes in G // (Mutually recursive functions may introduce cycles among themselves // which are permitted. Yet such cycles may incorrectly inflate the dependency // count for variables which in turn may not get scheduled for initialization // in correct order.) - var G []*graphNode - for obj, n := range M { - if _, ok := obj.(*Func); ok { - // connect each predecessor p of n with each successor s - // and drop the function node (don't collect it in G) - for p := range n.pred { - // ignore self-cycles - if p != n { - // Each successor s of n becomes a successor of p, and - // each predecessor p of n becomes a predecessor of s. - for s := range n.succ { - // ignore self-cycles - if s != n { - p.succ.add(s) - s.pred.add(p) - delete(s.pred, n) // remove edge to n - } + // + // Note that because we recursively copy predecessors and successors + // throughout the function graph, the cost of removing a function at + // position X is proportional to cost * (len(funcG)-X). Therefore, we should + // remove high-cost functions last. + sort.Slice(funcG, func(i, j int) bool { + return funcG[i].cost() < funcG[j].cost() + }) + for _, n := range funcG { + // connect each predecessor p of n with each successor s + // and drop the function node (don't collect it in G) + for p := range n.pred { + // ignore self-cycles + if p != n { + // Each successor s of n becomes a successor of p, and + // each predecessor p of n becomes a predecessor of s. + for s := range n.succ { + // ignore self-cycles + if s != n { + p.succ.add(s) + s.pred.add(p) } - delete(p.succ, n) // remove edge to n } + delete(p.succ, n) // remove edge to n } - } else { - // collect non-function nodes - G = append(G, n) + } + for s := range n.succ { + delete(s.pred, n) // remove edge to n } } diff --git a/src/cmd/compile/internal/types2/self_test.go b/src/cmd/compile/internal/types2/self_test.go index e0d2e1b07a..9a01ccdf7a 100644 --- a/src/cmd/compile/internal/types2/self_test.go +++ b/src/cmd/compile/internal/types2/self_test.go @@ -33,6 +33,7 @@ func BenchmarkCheck(b *testing.B) { filepath.Join("src", "net", "http"), filepath.Join("src", "go", "parser"), filepath.Join("src", "go", "constant"), + filepath.Join("src", "runtime"), filepath.Join("src", "go", "internal", "gcimporter"), } { b.Run(path.Base(p), func(b *testing.B) { -- GitLab From 85a8e1786a669efe525fd4555edb77a60bac2ffe Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Tue, 23 Nov 2021 17:36:21 -0500 Subject: [PATCH 2455/2500] cmd/go: fix hang in workspaces golang.org/cl/365234 incorrectly had pruningForGoVersion always return workspace pruning instead of just returning workspace pruning at the top level, which broke the proper determination of pruning for dependency packages. Fix that code, and also fix a hang that resulted because the module loading code keeps loading dependencies until it reaches a pruned module or an unpruned module it already saw, so it could get stuck in a cycle. Change-Id: I8911f7d83aaee5870c43ef0355abbd439f15d4f7 Reviewed-on: https://go-review.googlesource.com/c/go/+/366775 Trust: Michael Matloob Run-TryBot: Michael Matloob Reviewed-by: Bryan Mills TryBot-Result: Gopher Robot --- src/cmd/go/internal/modload/init.go | 6 +- src/cmd/go/internal/modload/modfile.go | 3 - .../testdata/script/work_regression_hang.txt | 71 +++++++++++++++++++ 3 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 src/cmd/go/testdata/script/work_regression_hang.txt diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index 854c17d776..df083e7fcc 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -694,7 +694,11 @@ func LoadModFile(ctx context.Context) *Requirements { MainModules = makeMainModules([]module.Version{mainModule}, []string{""}, []*modfile.File{nil}, []*modFileIndex{nil}, "", nil) goVersion := LatestGoVersion() rawGoVersion.Store(mainModule, goVersion) - requirements = newRequirements(pruningForGoVersion(goVersion), nil, nil) + pruning := pruningForGoVersion(goVersion) + if inWorkspaceMode() { + pruning = workspace + } + requirements = newRequirements(pruning, nil, nil) return requirements } diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index 7cc2272ea0..40e6ed787d 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -124,9 +124,6 @@ const ( ) func pruningForGoVersion(goVersion string) modPruning { - if inWorkspaceMode() { - return workspace - } if semver.Compare("v"+goVersion, ExplicitIndirectVersionV) < 0 { // The go.mod file does not duplicate relevant information about transitive // dependencies, so they cannot be pruned out. diff --git a/src/cmd/go/testdata/script/work_regression_hang.txt b/src/cmd/go/testdata/script/work_regression_hang.txt new file mode 100644 index 0000000000..a7661b68ad --- /dev/null +++ b/src/cmd/go/testdata/script/work_regression_hang.txt @@ -0,0 +1,71 @@ +# This test makes checks against a regression of a bug in the Go command +# where the module loader hung forever because all main module dependencies +# kept workspace pruning instead of adopting the pruning in their go.mod +# files, and the loader kept adding dependencies on the queue until they +# were either pruned or unpruned, never breaking a module dependency cycle. +# +# This is the module graph in the test: +# +# /-------------------------\ +# | | +# V | +# example.com/a -> example.com/b v1.0.0 -> example.com/c v1.1.0 + +go list -m -f '{{.Version}}' example.com/c + +-- go.work -- +go 1.16 + +use ( + ./a +) +-- a/go.mod -- +module example.com/a + +go 1.18 + +require example.com/b v1.0.0 + +replace example.com/b v1.0.0 => ../b +replace example.com/c v1.0.0 => ../c +-- a/foo.go -- +package main + +import "example.com/b" + +func main() { + b.B() +} +-- b/go.mod -- +module example.com/b + +go 1.18 + +require example.com/c v1.0.0 +-- b/b.go -- +package b + +func B() { +} +-- b/cmd/main.go -- +package main + +import "example.com/c" + +func main() { + c.C() +} +-- c/go.mod -- +module example.com/c + +go 1.18 + +require example.com/b v1.0.0 +-- c/c.go -- +package c + +import "example.com/b" + +func C() { + b.B() +} \ No newline at end of file -- GitLab From c1c303f6f8b77d3ed4e135583f3d60b159907245 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 7 Dec 2021 15:59:22 -0800 Subject: [PATCH 2456/2500] test: add extra typeswitch tests that cause duplicate cases Augmented some of the typeswitch*.go tests so that some instantiations have duplicate cases, in order to ensure we're testing that. Spacing changes in the tests are due to gofmt. Change-Id: I5d3678813505c520c544281d4ac8a62ce7e236ad Reviewed-on: https://go-review.googlesource.com/c/go/+/370155 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Gopher Robot Reviewed-by: Keith Randall --- test/run.go | 4 ++++ test/typeparam/typeswitch1.go | 6 ++++-- test/typeparam/typeswitch1.out | 2 ++ test/typeparam/typeswitch2.go | 2 ++ test/typeparam/typeswitch2.out | 2 ++ test/typeparam/typeswitch3.go | 7 ++++++- test/typeparam/typeswitch3.out | 3 +++ test/typeparam/typeswitch4.go | 11 ++++++++--- test/typeparam/typeswitch4.out | 3 +++ 9 files changed, 34 insertions(+), 6 deletions(-) diff --git a/test/run.go b/test/run.go index 2ff7117ea9..37be958959 100644 --- a/test/run.go +++ b/test/run.go @@ -2183,6 +2183,10 @@ var unifiedFailures = setOf( "fixedbugs/issue49767.go", // unified IR doesn't report channel element too large "fixedbugs/issue49814.go", // unified IR doesn't report array type too large "typeparam/issue50002.go", // pure stenciling leads to a static type assertion error + "typeparam/typeswitch1.go", // duplicate case failure due to stenciling + "typeparam/typeswitch2.go", // duplicate case failure due to stenciling + "typeparam/typeswitch3.go", // duplicate case failure due to stenciling + "typeparam/typeswitch4.go", // duplicate case failure due to stenciling ) func setOf(keys ...string) map[string]bool { diff --git a/test/typeparam/typeswitch1.go b/test/typeparam/typeswitch1.go index 27161b3db8..834302e37a 100644 --- a/test/typeparam/typeswitch1.go +++ b/test/typeparam/typeswitch1.go @@ -14,7 +14,7 @@ func f[T any](i interface{}) { println("int") case int32, int16: println("int32/int16") - case struct { a, b T }: + case struct{ a, b T }: println("struct{T,T}") default: println("other") @@ -24,6 +24,8 @@ func main() { f[float64](float64(6)) f[float64](int(7)) f[float64](int32(8)) - f[float64](struct{a, b float64}{a:1, b:2}) + f[float64](struct{ a, b float64 }{a: 1, b: 2}) f[float64](int8(9)) + f[int32](int32(7)) + f[int](int32(7)) } diff --git a/test/typeparam/typeswitch1.out b/test/typeparam/typeswitch1.out index 4bdbccfddb..dc5dfdb761 100644 --- a/test/typeparam/typeswitch1.out +++ b/test/typeparam/typeswitch1.out @@ -3,3 +3,5 @@ int int32/int16 struct{T,T} other +T +int32/int16 diff --git a/test/typeparam/typeswitch2.go b/test/typeparam/typeswitch2.go index 0e434e1383..ce4af34f04 100644 --- a/test/typeparam/typeswitch2.go +++ b/test/typeparam/typeswitch2.go @@ -28,4 +28,6 @@ func main() { f[float64](int32(8)) f[float64](struct{ a, b float64 }{a: 1, b: 2}) f[float64](int8(9)) + f[int32](int32(7)) + f[int](int32(7)) } diff --git a/test/typeparam/typeswitch2.out b/test/typeparam/typeswitch2.out index 944cc04cc6..85b54e38ae 100644 --- a/test/typeparam/typeswitch2.out +++ b/test/typeparam/typeswitch2.out @@ -3,3 +3,5 @@ int 7 int32/int16 8 struct{T,T} +1.000000e+000 +2.000000e+000 other 9 +T 7 +int32/int16 7 diff --git a/test/typeparam/typeswitch3.go b/test/typeparam/typeswitch3.go index 6ab0301140..0527a83eb0 100644 --- a/test/typeparam/typeswitch3.go +++ b/test/typeparam/typeswitch3.go @@ -6,16 +6,18 @@ package main -type I interface { foo() int } +type I interface{ foo() int } type myint int func (x myint) foo() int { return int(x) } type myfloat float64 + func (x myfloat) foo() int { return int(x) } type myint32 int32 + func (x myint32) foo() int { return int(x) } func f[T I](i I) { @@ -32,4 +34,7 @@ func main() { f[myfloat](myint(6)) f[myfloat](myfloat(7)) f[myfloat](myint32(8)) + f[myint32](myint32(8)) + f[myint32](myfloat(7)) + f[myint](myint32(9)) } diff --git a/test/typeparam/typeswitch3.out b/test/typeparam/typeswitch3.out index 2c69c72c30..ed59987e6d 100644 --- a/test/typeparam/typeswitch3.out +++ b/test/typeparam/typeswitch3.out @@ -1,3 +1,6 @@ myint 6 T 7 other 8 +T 8 +other 7 +other 9 diff --git a/test/typeparam/typeswitch4.go b/test/typeparam/typeswitch4.go index 6113026b65..08de2a1d41 100644 --- a/test/typeparam/typeswitch4.go +++ b/test/typeparam/typeswitch4.go @@ -6,16 +6,18 @@ package main -type I interface { foo() int } +type I interface{ foo() int } type myint int -func (x myint) foo() int {return int(x)} +func (x myint) foo() int { return int(x) } type myfloat float64 -func (x myfloat) foo() int {return int(x)} + +func (x myfloat) foo() int { return int(x) } type myint32 int32 + func (x myint32) foo() int { return int(x) } func f[T I](i I) { @@ -30,4 +32,7 @@ func main() { f[myfloat](myint(6)) f[myfloat](myfloat(7)) f[myfloat](myint32(8)) + f[myint32](myint32(9)) + f[myint](myint32(10)) + f[myint](myfloat(42)) } diff --git a/test/typeparam/typeswitch4.out b/test/typeparam/typeswitch4.out index b0d54077c9..d6121d077c 100644 --- a/test/typeparam/typeswitch4.out +++ b/test/typeparam/typeswitch4.out @@ -1,3 +1,6 @@ other 6 T/myint32 7 T/myint32 8 +T/myint32 9 +T/myint32 10 +other 42 -- GitLab From 7b7efd7a7c952f8b372c861c94acd159ee371acb Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 7 Dec 2021 13:32:36 -0800 Subject: [PATCH 2457/2500] doc: add in release note about compiler being roughly 15% slower Updates #49569 Change-Id: Ifba769993c50bb547cb355f56934fb572ec17a1a Reviewed-on: https://go-review.googlesource.com/c/go/+/370154 Reviewed-by: Austin Clements Trust: Dan Scales --- doc/go1.18.html | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index ad08083793..a3c2da059b 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -321,8 +321,11 @@ Do not send CLs removing the interior tags from such phrases. new go command -asan option.

      -

      - TODO: Mention build speed impact. +

      + Because of changes in the compiler related to supporting generics, the + Go 1.18 compile speed can be roughly 15% slower than the Go 1.17 compile speed. + The execution time of the compiled code is not affected. We + intend to improve the speed of the compiler in Go 1.19.

      Linker

      -- GitLab From 61011de1af0bc6ab286c4722632719d3da2cf746 Mon Sep 17 00:00:00 2001 From: David Chase Date: Tue, 23 Nov 2021 13:29:13 -0500 Subject: [PATCH 2458/2500] cmd/compile: try to preserve IsStmt marks from OpConvert Note when a statement mark was not consumed during Prog generation, and try to use it on a subsequent opcode so that the statement marker will not be lost. And a test. Fixes #49628. Change-Id: I03f7782a9809cc4a0a5870df92b3e182cf124554 Reviewed-on: https://go-review.googlesource.com/c/go/+/366694 Trust: David Chase Run-TryBot: David Chase Trust: Dan Scales Reviewed-by: Dan Scales TryBot-Result: Gopher Robot --- .../compile/internal/ssa/debug_lines_test.go | 19 +++++++++++++++++++ .../internal/ssa/testdata/convertline.go | 16 ++++++++++++++++ src/cmd/compile/internal/ssagen/ssa.go | 17 +++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 src/cmd/compile/internal/ssa/testdata/convertline.go diff --git a/src/cmd/compile/internal/ssa/debug_lines_test.go b/src/cmd/compile/internal/ssa/debug_lines_test.go index 0df56f5d4b..c0ccdb1c93 100644 --- a/src/cmd/compile/internal/ssa/debug_lines_test.go +++ b/src/cmd/compile/internal/ssa/debug_lines_test.go @@ -82,6 +82,25 @@ func TestDebugLinesPushback(t *testing.T) { } } +func TestDebugLinesConvert(t *testing.T) { + if runtime.GOOS != "linux" && runtime.GOOS != "darwin" { // in particular, it could be windows. + t.Skip("this test depends on creating a file with a wonky name, only works for sure on Linux and Darwin") + } + + switch testGoArch() { + default: + t.Skip("skipped for many architectures") + + case "arm64", "amd64": // register ABI + fn := "G[go.shape.int_0]" + if buildcfg.Experiment.Unified { + // Unified mangles differently + fn = "G[int]" + } + testDebugLines(t, "-N -l -G=3", "convertline.go", fn, []int{9, 10, 11}, true) + } +} + func TestInlineLines(t *testing.T) { if runtime.GOARCH != "amd64" && *testGoArchFlag == "" { // As of september 2021, works for everything except mips64, but still potentially fragile diff --git a/src/cmd/compile/internal/ssa/testdata/convertline.go b/src/cmd/compile/internal/ssa/testdata/convertline.go new file mode 100644 index 0000000000..08f3ae8a35 --- /dev/null +++ b/src/cmd/compile/internal/ssa/testdata/convertline.go @@ -0,0 +1,16 @@ +package main + +import "fmt" + +func F[T any](n T) { + fmt.Printf("called\n") +} + +func G[T any](n T) { + F(n) + fmt.Printf("after\n") +} + +func main() { + G(3) +} diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index d6407af334..265ef1aab3 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -6577,6 +6577,22 @@ func (s *State) DebugFriendlySetPosFrom(v *ssa.Value) { // explicit statement boundaries should appear // in the generated code. if p.IsStmt() != src.PosIsStmt { + if s.pp.Pos.IsStmt() == src.PosIsStmt && s.pp.Pos.SameFileAndLine(p) { + // If s.pp.Pos already has a statement mark, then it was set here (below) for + // the previous value. If an actual instruction had been emitted for that + // value, then the statement mark would have been reset. Since the statement + // mark of s.pp.Pos was not reset, this position (file/line) still needs a + // statement mark on an instruction. If file and line for this value are + // the same as the previous value, then the first instruction for this + // value will work to take the statement mark. Return early to avoid + // resetting the statement mark. + // + // The reset of s.pp.Pos occurs in (*Progs).Prog() -- if it emits + // an instruction, and the instruction's statement mark was set, + // and it is not one of the LosesStmtMark instructions, + // then Prog() resets the statement mark on the (*Progs).Pos. + return + } p = p.WithNotStmt() // Calls use the pos attached to v, but copy the statement mark from State } @@ -6818,6 +6834,7 @@ func genssa(f *ssa.Func, pp *objw.Progs) { for i, b := range f.Blocks { s.bstart[b.ID] = s.pp.Next s.lineRunStart = nil + s.SetPos(s.pp.Pos.WithNotStmt()) // It needs a non-empty Pos, but cannot be a statement boundary (yet). // Attach a "default" liveness info. Normally this will be // overwritten in the Values loop below for each Value. But -- GitLab From 9e29dd42df18141506dcfc2513e8a653564fdbf1 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 7 Dec 2021 14:29:21 -0500 Subject: [PATCH 2459/2500] doc: document cmd/vet changes for generics in 1.18 Fixes #50011 Updates #47694 Change-Id: Id3d43f2f72de61b360b79c2b375ca1372d5f4692 Reviewed-on: https://go-review.googlesource.com/c/go/+/369979 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Gopher Robot Reviewed-by: Tim King --- doc/go1.18.html | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/doc/go1.18.html b/doc/go1.18.html index a3c2da059b..2813ddc12c 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -266,6 +266,28 @@ Do not send CLs removing the interior tags from such phrases. multiple CPUs, gofmt should now be significantly faster.

      +

      vet

      + +

      Updates for Generics

      + +

      + The vet tool is updated to support generic code. In most cases, + it reports an error in generic code whenever it would report an error in the + equivalent non-generic code after substituting for type parameters with a + type from their + type set. + + For example, vet reports a format error in +

      func Print[T ~int|~string](t T) {
      +	fmt.Printf("%d", t)
      +}
      + because it would report a format error in the non-generic equivalent of + Print[string]: +
      func PrintString(x string) {
      +	fmt.Printf("%d", x)
      +}
      +

      +

      Runtime

      -- GitLab From bb9b20a15d637667614ec4a312f216bd4c67b76a Mon Sep 17 00:00:00 2001 From: Heschi Kreinick Date: Wed, 8 Dec 2021 15:29:12 -0500 Subject: [PATCH 2460/2500] cmd/api: run half as many go list calls in parallel We currently run one 'go list' invocation per GOMAXPROC. Since the go command uses memory and has its own internal parallelism, that's unlikely to be an efficient use of resources. Run half as many. I suspect that's still too many but this should fix our OOMs. For #49957. Change-Id: Id06b6e0f0d96387a2a050e400f38bde6ba71aa60 Reviewed-on: https://go-review.googlesource.com/c/go/+/370376 Trust: Heschi Kreinick Run-TryBot: Heschi Kreinick Reviewed-by: Bryan Mills --- src/cmd/api/goapi.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go index 0c61b1b489..a55e51cc9b 100644 --- a/src/cmd/api/goapi.go +++ b/src/cmd/api/goapi.go @@ -460,7 +460,7 @@ type listImports struct { var listCache sync.Map // map[string]listImports, keyed by contextName // listSem is a semaphore restricting concurrent invocations of 'go list'. -var listSem = make(chan semToken, runtime.GOMAXPROCS(0)) +var listSem = make(chan semToken, ((runtime.GOMAXPROCS(0)-1)/2)+1) type semToken struct{} -- GitLab From f5ddd94334a63ac8107c976aa4bd6ee2171d7d64 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Wed, 8 Dec 2021 15:30:28 -0500 Subject: [PATCH 2461/2500] runtime/pprof: increase systemstack calls in TestLabelSystemstack TestLabelSystemstack needs to collect samples within runtime.systemstack to complete the test. The current approach uses fmt.Fprintf, which gets into systemstack through the allocator and GC, but also does lots of other work. In my measurements, approximately 2% of samples contain runtime.systemstack. The new approach uses debug.SetGCPercent, which uses systemstack for most of its work, including contention on mheap_.lock, which extends usage even more. In my measurements, approximately 99% of samples contain runtime.systemstack. Fixes #50050 Change-Id: I59e5bb756341b716a12e13d2e3fe0adadd7fe956 Reviewed-on: https://go-review.googlesource.com/c/go/+/370375 Reviewed-by: Bryan Mills Trust: Michael Pratt Run-TryBot: Michael Pratt Reviewed-by: Michael Knyszek TryBot-Result: Gopher Robot --- src/runtime/pprof/pprof_test.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go index 2e6165ff88..b3a8927dc7 100644 --- a/src/runtime/pprof/pprof_test.go +++ b/src/runtime/pprof/pprof_test.go @@ -1425,6 +1425,11 @@ func TestLabelRace(t *testing.T) { // TestLabelSystemstack makes sure CPU profiler samples of goroutines running // on systemstack include the correct pprof labels. See issue #48577 func TestLabelSystemstack(t *testing.T) { + // Grab and re-set the initial value before continuing to ensure + // GOGC doesn't actually change following the test. + gogc := debug.SetGCPercent(100) + debug.SetGCPercent(gogc) + matches := matchAndAvoidStacks(stackContainsLabeled, []string{"runtime.systemstack;key=value"}, avoidFunctions()) p := testCPUProfile(t, matches, func(dur time.Duration) { Do(context.Background(), Labels("key", "value"), func(context.Context) { @@ -1434,7 +1439,7 @@ func TestLabelSystemstack(t *testing.T) { wg.Add(1) go func() { defer wg.Done() - labelHog(stop) + labelHog(stop, gogc) }() } @@ -1467,13 +1472,13 @@ func TestLabelSystemstack(t *testing.T) { // labelHog is designed to burn CPU time in a way that a high number of CPU // samples end up running on systemstack. -func labelHog(stop chan struct{}) { +func labelHog(stop chan struct{}, gogc int) { for i := 0; ; i++ { select { case <-stop: return default: - fmt.Fprintf(io.Discard, "%d", i) + debug.SetGCPercent(gogc) } } } -- GitLab From d6c4583ad4923533ddc9f5792ed3b66f3b9f9feb Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 7 Dec 2021 19:15:51 -0500 Subject: [PATCH 2462/2500] doc: document the new types.Config.GoVersion field Also update some other go/types release notes to use the present tense. Updates #47694 Change-Id: I654371c065e76fd5d22679d0d3c1a81bc3d1e513 Reviewed-on: https://go-review.googlesource.com/c/go/+/370235 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Gopher Robot Reviewed-by: Robert Griesemer --- doc/go1.18.html | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 2813ddc12c..8142a93b7b 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -528,6 +528,11 @@ Do not send CLs removing the interior tags from such phrases.

      go/types
      +

      + The new Config.GoVersion + field sets the accepted Go language version. +

      +

      Per the proposal @@ -540,7 +545,7 @@ Do not send CLs removing the interior tags from such phrases. The new type TypeParam, factory function NewTypeParam, - and associated methods were added to represent a type parameter. + and associated methods are added to represent a type parameter.

    • The new type @@ -569,7 +574,7 @@ Do not send CLs removing the interior tags from such phrases. type arguments or type parameters of an instantiated or parameterized type, and Named.SetTypeParams to set the type parameters (for instance, when importing a named type where allocation of the named - type and setting of type parameters cannot be done both at once due to possible cycles). + type and setting of type parameters cannot be done simultaneously due to possible cycles).
    • The Interface type has four new methods: @@ -586,7 +591,7 @@ Do not send CLs removing the interior tags from such phrases. Term, factory functions NewUnion and NewTerm, and associated - methods were added to represent type sets in interfaces. + methods are added to represent type sets in interfaces.
    • The new function @@ -600,12 +605,12 @@ Do not send CLs removing the interior tags from such phrases.
    • The new type ArgumentError - and associated methods were added to represent an error related to a type argument. + and associated methods are added to represent an error related to a type argument.
    • The new type Context and factory function NewContext - were added to facilitate sharing of identical type instances across type-checked packages. + are added to facilitate sharing of identical type instances across type-checked packages.
    -- GitLab From a76511f3a40ea69ee4f5cd86e735e1c8a84f0aa2 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 8 Dec 2021 18:05:11 -0500 Subject: [PATCH 2463/2500] syscall: fix ForkLock spurious close(0) on pipe failure Pipe (and therefore forkLockPipe) does not make any guarantees about the state of p after a failed Pipe(p). Avoid that assumption and the too-clever goto, so that we don't accidentally Close a real fd if the failed pipe leaves p[0] or p[1] set >= 0. Fixes #50057 Fixes CVE-2021-44717 Change-Id: Iff8e19a6efbba0c73cc8b13ecfae381c87600bb4 Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1291270 Reviewed-by: Ian Lance Taylor Reviewed-on: https://go-review.googlesource.com/c/go/+/370576 Run-TryBot: Filippo Valsorda Trust: Russ Cox Reviewed-by: Alex Rakoczy --- src/syscall/exec_unix.go | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/src/syscall/exec_unix.go b/src/syscall/exec_unix.go index 64eb5ed9f0..0e41959ffe 100644 --- a/src/syscall/exec_unix.go +++ b/src/syscall/exec_unix.go @@ -152,9 +152,6 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) sys = &zeroSysProcAttr } - p[0] = -1 - p[1] = -1 - // Convert args to C form. argv0p, err := BytePtrFromString(argv0) if err != nil { @@ -204,14 +201,17 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) // Allocate child status pipe close on exec. if err = forkExecPipe(p[:]); err != nil { - goto error + ForkLock.Unlock() + return 0, err } // Kick off child. pid, err1 = forkAndExecInChild(argv0p, argvp, envvp, chroot, dir, attr, sys, p[1]) if err1 != 0 { - err = Errno(err1) - goto error + Close(p[0]) + Close(p[1]) + ForkLock.Unlock() + return 0, Errno(err1) } ForkLock.Unlock() @@ -243,14 +243,6 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) // Read got EOF, so pipe closed on exec, so exec succeeded. return pid, nil - -error: - if p[0] >= 0 { - Close(p[0]) - Close(p[1]) - } - ForkLock.Unlock() - return 0, err } // Combination of fork and exec, careful to be thread safe. -- GitLab From 474ebb917cb802bf1d08434a265515d50c174082 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 8 Dec 2021 18:06:41 -0500 Subject: [PATCH 2464/2500] syscall: avoid writing to p when Pipe(p) fails Generally speaking Go functions make no guarantees about what has happened to result parameters on error, and Pipe is no exception: callers should avoid looking at p if Pipe returns an error. However, we had a bug in which ForkExec was using the content of p after a failed Pipe, and others may too. As a robustness fix, make Pipe avoid writing to p on failure. Updates #50057 Change-Id: Ie8955025dbd20702fabadc9bbe1d1a5ac0f36305 Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1291271 Reviewed-by: Ian Lance Taylor Reviewed-on: https://go-review.googlesource.com/c/go/+/370577 Run-TryBot: Filippo Valsorda Trust: Russ Cox TryBot-Result: Gopher Robot Reviewed-by: Alex Rakoczy --- src/syscall/syscall_aix.go | 6 ++++-- src/syscall/syscall_darwin.go | 6 ++++-- src/syscall/syscall_dragonfly.go | 12 +++++++++--- src/syscall/syscall_freebsd.go | 6 ++++-- src/syscall/syscall_linux.go | 6 ++++-- src/syscall/syscall_netbsd.go | 6 ++++-- src/syscall/syscall_openbsd.go | 6 ++++-- src/syscall/syscall_plan9.go | 6 ++++-- src/syscall/syscall_solaris.go | 4 +++- 9 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/syscall/syscall_aix.go b/src/syscall/syscall_aix.go index 0f5101999f..739c55f179 100644 --- a/src/syscall/syscall_aix.go +++ b/src/syscall/syscall_aix.go @@ -66,8 +66,10 @@ func Pipe(p []int) (err error) { } var pp [2]_C_int err = pipe(&pp) - p[0] = int(pp[0]) - p[1] = int(pp[1]) + if err == nil { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } return } diff --git a/src/syscall/syscall_darwin.go b/src/syscall/syscall_darwin.go index 5bb34e300c..902d6e77e1 100644 --- a/src/syscall/syscall_darwin.go +++ b/src/syscall/syscall_darwin.go @@ -80,8 +80,10 @@ func Pipe(p []int) (err error) { } var q [2]int32 err = pipe(&q) - p[0] = int(q[0]) - p[1] = int(q[1]) + if err == nil { + p[0] = int(q[0]) + p[1] = int(q[1]) + } return } diff --git a/src/syscall/syscall_dragonfly.go b/src/syscall/syscall_dragonfly.go index cc92c4a93e..f3c0f54521 100644 --- a/src/syscall/syscall_dragonfly.go +++ b/src/syscall/syscall_dragonfly.go @@ -98,8 +98,11 @@ func Pipe(p []int) (err error) { if len(p) != 2 { return EINVAL } - p[0], p[1], err = pipe() - return + r, w, err := pipe() + if err == nil { + p[0], p[1] = r, w + } + return err } //sysnb pipe2(p *[2]_C_int, flags int) (r int, w int, err error) @@ -111,7 +114,10 @@ func Pipe2(p []int, flags int) (err error) { var pp [2]_C_int // pipe2 on dragonfly takes an fds array as an argument, but still // returns the file descriptors. - p[0], p[1], err = pipe2(&pp, flags) + r, w, err := pipe2(&pp, flags) + if err == nil { + p[0], p[1] = r, w + } return err } diff --git a/src/syscall/syscall_freebsd.go b/src/syscall/syscall_freebsd.go index 6f44b25cb9..ecb9ec825a 100644 --- a/src/syscall/syscall_freebsd.go +++ b/src/syscall/syscall_freebsd.go @@ -105,8 +105,10 @@ func Pipe2(p []int, flags int) error { } var pp [2]_C_int err := pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) + if err == nil { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } return err } diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go index c002299641..abcf1d5dfe 100644 --- a/src/syscall/syscall_linux.go +++ b/src/syscall/syscall_linux.go @@ -173,8 +173,10 @@ func Pipe2(p []int, flags int) error { } var pp [2]_C_int err := pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) + if err == nil { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } return err } diff --git a/src/syscall/syscall_netbsd.go b/src/syscall/syscall_netbsd.go index cebef10be8..0d562cc78e 100644 --- a/src/syscall/syscall_netbsd.go +++ b/src/syscall/syscall_netbsd.go @@ -114,8 +114,10 @@ func Pipe2(p []int, flags int) error { } var pp [2]_C_int err := pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) + if err == nil { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } return err } diff --git a/src/syscall/syscall_openbsd.go b/src/syscall/syscall_openbsd.go index 195cf8617c..fa939ec5c8 100644 --- a/src/syscall/syscall_openbsd.go +++ b/src/syscall/syscall_openbsd.go @@ -72,8 +72,10 @@ func Pipe2(p []int, flags int) error { } var pp [2]_C_int err := pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) + if err == nil { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } return err } diff --git a/src/syscall/syscall_plan9.go b/src/syscall/syscall_plan9.go index d16cad45d8..6a8ab97dc6 100644 --- a/src/syscall/syscall_plan9.go +++ b/src/syscall/syscall_plan9.go @@ -198,8 +198,10 @@ func Pipe(p []int) (err error) { } var pp [2]int32 err = pipe(&pp) - p[0] = int(pp[0]) - p[1] = int(pp[1]) + if err == nil { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } return } diff --git a/src/syscall/syscall_solaris.go b/src/syscall/syscall_solaris.go index 5f12f229c4..f44a9e25ac 100644 --- a/src/syscall/syscall_solaris.go +++ b/src/syscall/syscall_solaris.go @@ -57,7 +57,9 @@ func Pipe(p []int) (err error) { if e1 != 0 { err = Errno(e1) } - p[0], p[1] = int(r0), int(w0) + if err == nil { + p[0], p[1] = int(r0), int(w0) + } return } -- GitLab From 61ba0bcf8eebd1515d1af7a0e918bf912db6eb46 Mon Sep 17 00:00:00 2001 From: Julie Qiu Date: Mon, 6 Dec 2021 12:31:27 -0500 Subject: [PATCH 2465/2500] cmd/go: use -count=1 in test_fuzz_chatty.txt Fuzz tests in test_fuzz_chatty.txt now use -count=1 where applicable. Fixes #48984 Change-Id: If1673924af990fe12d5dfba95082ccb573806fde Reviewed-on: https://go-review.googlesource.com/c/go/+/369674 Trust: Julie Qiu Trust: Katie Hockman Reviewed-by: Katie Hockman --- src/cmd/go/testdata/script/test_fuzz_chatty.txt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_chatty.txt b/src/cmd/go/testdata/script/test_fuzz_chatty.txt index 1abcbbd389..d07fe50f95 100644 --- a/src/cmd/go/testdata/script/test_fuzz_chatty.txt +++ b/src/cmd/go/testdata/script/test_fuzz_chatty.txt @@ -37,11 +37,9 @@ go test -v chatty_with_test_fuzz_test.go -fuzz=Fuzz -fuzztime=1x stdout ok stdout PASS ! stdout FAIL -# TODO: It's currently the case that it's logged twice. Fix that, and change -# this check to verify it. -stdout 'all good here' +stdout -count=1 'all good here' # Verify that the unit test is only run once. -! stdout '(?s)logged foo.*logged foo' +stdout -count=1 'logged foo' -- chatty_error_fuzz_test.go -- package chatty_error_fuzz -- GitLab From 307d7c67477ee7ccb8544ac802e965b5d18a069e Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Thu, 9 Dec 2021 09:09:52 -0500 Subject: [PATCH 2466/2500] net/http: update bundled golang.org/x/net/http2 Pull in security fix 2d13015 http2: cap the size of the server's canonical header cache and 0a0e4e1 http2: Fix handling of expect continue 04296fa http2: prioritize RST_STREAM frames in random write scheduler Fixes #50058 Fixes CVE-2021-44716 Change-Id: Ia40a2e52fa240e54a83b5ec7d8116cb6639ecbb9 Reviewed-on: https://go-review.googlesource.com/c/go/+/370579 Trust: Filippo Valsorda Run-TryBot: Filippo Valsorda TryBot-Result: Gopher Robot Reviewed-by: Damien Neil --- src/go.mod | 2 +- src/go.sum | 4 +-- src/net/http/h2_bundle.go | 32 ++++++++++++------- .../x/net/dns/dnsmessage/message.go | 22 ++++++------- src/vendor/modules.txt | 2 +- 5 files changed, 36 insertions(+), 26 deletions(-) diff --git a/src/go.mod b/src/go.mod index 24d034b810..07d0acf2bd 100644 --- a/src/go.mod +++ b/src/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa - golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 + golang.org/x/net v0.0.0-20211209124913-491a49abca63 ) require ( diff --git a/src/go.sum b/src/go.sum index d063e65530..cec5bc4d0e 100644 --- a/src/go.sum +++ b/src/go.sum @@ -1,7 +1,7 @@ golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa h1:idItI2DDfCokpg0N51B2VtiLdJ4vAuXC9fnCb2gACo4= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 h1:0qxwC5n+ttVOINCBeRHO0nq9X7uy8SDsPoi5OaCdIEI= -golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY= +golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sys v0.0.0-20211205182925-97ca703d548d h1:FjkYO/PPp4Wi0EAUOVLxePm7qVW4r4ctbWpURyuOD0E= golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 h1:GLw7MR8AfAG2GmGcmVgObFOHXYypgGjnGno25RDwn3Y= diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go index 8d19c42b5a..bb82f24585 100644 --- a/src/net/http/h2_bundle.go +++ b/src/net/http/h2_bundle.go @@ -4436,7 +4436,15 @@ func (sc *http2serverConn) canonicalHeader(v string) string { sc.canonHeader = make(map[string]string) } cv = CanonicalHeaderKey(v) - sc.canonHeader[v] = cv + // maxCachedCanonicalHeaders is an arbitrarily-chosen limit on the number of + // entries in the canonHeader cache. This should be larger than the number + // of unique, uncommon header keys likely to be sent by the peer, while not + // so high as to permit unreaasonable memory usage if the peer sends an unbounded + // number of unique header keys. + const maxCachedCanonicalHeaders = 32 + if len(sc.canonHeader) < maxCachedCanonicalHeaders { + sc.canonHeader[v] = cv + } return cv } @@ -7958,12 +7966,12 @@ func (cs *http2clientStream) writeRequest(req *Request) (err error) { } continueTimeout := cc.t.expectContinueTimeout() - if continueTimeout != 0 && - !httpguts.HeaderValuesContainsToken( - req.Header["Expect"], - "100-continue") { - continueTimeout = 0 - cs.on100 = make(chan struct{}, 1) + if continueTimeout != 0 { + if !httpguts.HeaderValuesContainsToken(req.Header["Expect"], "100-continue") { + continueTimeout = 0 + } else { + cs.on100 = make(chan struct{}, 1) + } } // Past this point (where we send request headers), it is possible for @@ -10117,7 +10125,8 @@ type http2WriteScheduler interface { // Pop dequeues the next frame to write. Returns false if no frames can // be written. Frames with a given wr.StreamID() are Pop'd in the same - // order they are Push'd. No frames should be discarded except by CloseStream. + // order they are Push'd, except RST_STREAM frames. No frames should be + // discarded except by CloseStream. Pop() (wr http2FrameWriteRequest, ok bool) } @@ -10137,6 +10146,7 @@ type http2FrameWriteRequest struct { // stream is the stream on which this frame will be written. // nil for non-stream frames like PING and SETTINGS. + // nil for RST_STREAM streams, which use the StreamError.StreamID field instead. stream *http2stream // done, if non-nil, must be a buffered channel with space for @@ -10816,11 +10826,11 @@ func (ws *http2randomWriteScheduler) AdjustStream(streamID uint32, priority http } func (ws *http2randomWriteScheduler) Push(wr http2FrameWriteRequest) { - id := wr.StreamID() - if id == 0 { + if wr.isControl() { ws.zero.push(wr) return } + id := wr.StreamID() q, ok := ws.sq[id] if !ok { q = ws.queuePool.get() @@ -10830,7 +10840,7 @@ func (ws *http2randomWriteScheduler) Push(wr http2FrameWriteRequest) { } func (ws *http2randomWriteScheduler) Pop() (http2FrameWriteRequest, bool) { - // Control frames first. + // Control and RST_STREAM frames first. if !ws.zero.empty() { return ws.zero.shift(), true } diff --git a/src/vendor/golang.org/x/net/dns/dnsmessage/message.go b/src/vendor/golang.org/x/net/dns/dnsmessage/message.go index 1736fc5d12..8c24430c5c 100644 --- a/src/vendor/golang.org/x/net/dns/dnsmessage/message.go +++ b/src/vendor/golang.org/x/net/dns/dnsmessage/message.go @@ -125,14 +125,14 @@ func (o OpCode) GoString() string { // An RCode is a DNS response status code. type RCode uint16 +// Header.RCode values. const ( - // Message.Rcode - RCodeSuccess RCode = 0 - RCodeFormatError RCode = 1 - RCodeServerFailure RCode = 2 - RCodeNameError RCode = 3 - RCodeNotImplemented RCode = 4 - RCodeRefused RCode = 5 + RCodeSuccess RCode = 0 // NoError + RCodeFormatError RCode = 1 // FormErr + RCodeServerFailure RCode = 2 // ServFail + RCodeNameError RCode = 3 // NXDomain + RCodeNotImplemented RCode = 4 // NotImp + RCodeRefused RCode = 5 // Refused ) var rCodeNames = map[RCode]string{ @@ -1207,8 +1207,8 @@ type Builder struct { // // The DNS message is appended to the provided initial buffer buf (which may be // nil) as it is built. The final message is returned by the (*Builder).Finish -// method, which may return the same underlying array if there was sufficient -// capacity in the slice. +// method, which includes buf[:len(buf)] and may return the same underlying +// array if there was sufficient capacity in the slice. func NewBuilder(buf []byte, h Header) Builder { if buf == nil { buf = make([]byte, 0, packStartingCap) @@ -1713,7 +1713,7 @@ const ( // SetEDNS0 configures h for EDNS(0). // -// The provided extRCode must be an extedned RCode. +// The provided extRCode must be an extended RCode. func (h *ResourceHeader) SetEDNS0(udpPayloadLen int, extRCode RCode, dnssecOK bool) error { h.Name = Name{Data: [nameLen]byte{'.'}, Length: 1} // RFC 6891 section 6.1.2 h.Type = TypeOPT @@ -1880,7 +1880,7 @@ const nameLen = 255 // A Name is a non-encoded domain name. It is used instead of strings to avoid // allocations. type Name struct { - Data [nameLen]byte + Data [nameLen]byte // 255 bytes Length uint8 } diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index bef622891e..4130027c7f 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -9,7 +9,7 @@ golang.org/x/crypto/curve25519/internal/field golang.org/x/crypto/hkdf golang.org/x/crypto/internal/poly1305 golang.org/x/crypto/internal/subtle -# golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 +# golang.org/x/net v0.0.0-20211209124913-491a49abca63 ## explicit; go 1.17 golang.org/x/net/dns/dnsmessage golang.org/x/net/http/httpguts -- GitLab From 78b4518e31b39aac4fbad1679db95b3f526229a7 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Wed, 8 Dec 2021 16:47:56 -0500 Subject: [PATCH 2467/2500] crypto/x509: skip known TestSystemVerify flakes on windows-*-2008 builders The "-2008" builders are the only ones on which the failure has been observed, so I suspect that it is due to a platform bug fixed in a subsequent release. Since no one has added a workaround since #19564 was filed over four years ago, I'm assuming that no workaround is planned for this issue. Let's add a skip for the known failure mode and call it at that. Fixes #19564 Change-Id: Iefc22d1cc78bfdc79c845eb60cac22e26caf388c Reviewed-on: https://go-review.googlesource.com/c/go/+/370377 Trust: Bryan Mills Run-TryBot: Bryan Mills TryBot-Result: Gopher Robot Reviewed-by: Roland Shoemaker Reviewed-by: Filippo Valsorda --- src/crypto/x509/verify_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go index 05d521c09d..f4ea08bbf5 100644 --- a/src/crypto/x509/verify_test.go +++ b/src/crypto/x509/verify_test.go @@ -13,6 +13,7 @@ import ( "encoding/pem" "errors" "fmt" + "internal/testenv" "math/big" "runtime" "strings" @@ -469,6 +470,9 @@ func testVerify(t *testing.T, test verifyTest, useSystemRoots bool) { chains, err := leaf.Verify(opts) if test.errorCallback == nil && err != nil { + if runtime.GOOS == "windows" && strings.HasSuffix(testenv.Builder(), "-2008") && err.Error() == "x509: certificate signed by unknown authority" { + testenv.SkipFlaky(t, 19564) + } t.Fatalf("unexpected error: %v", err) } if test.errorCallback != nil { -- GitLab From ece493eb831a7797d03d60b44b817caf1c63a0ab Mon Sep 17 00:00:00 2001 From: Jason7602 Date: Tue, 9 Nov 2021 23:46:41 +0800 Subject: [PATCH 2468/2500] cmd/compile: fix type error reported on the wrong line The 'Does not match' type error shoud be reported where the function is called, not where the function is declared. And fix the todo by gri of issue45985 Fixes #45985 Fixes #49800 Change-Id: I15aac44dd44f2a57c485a1c273fcd79db912c389 Reviewed-on: https://go-review.googlesource.com/c/go/+/362634 Reviewed-by: Robert Griesemer Reviewed-by: Robert Findley Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Gopher Robot --- src/cmd/compile/internal/types2/infer.go | 10 +++++----- .../internal/types2/testdata/fixedbugs/issue45985.go2 | 5 ++--- src/go/types/infer.go | 10 +++++----- src/go/types/testdata/fixedbugs/issue45985.go2 | 5 ++--- 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index 4f85a5894c..b203985b8d 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -60,7 +60,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, // If we have type arguments, see how far we get with constraint type inference. if len(targs) > 0 && useConstraintTypeInference { var index int - targs, index = check.inferB(tparams, targs) + targs, index = check.inferB(pos, tparams, targs) if targs == nil || index < 0 { return targs } @@ -171,7 +171,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, // Note that even if we don't have any type arguments, constraint type inference // may produce results for constraints that explicitly specify a type. if useConstraintTypeInference { - targs, index = check.inferB(tparams, targs) + targs, index = check.inferB(pos, tparams, targs) if targs == nil || index < 0 { return targs } @@ -209,7 +209,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, // Again, follow up with constraint type inference. if useConstraintTypeInference { - targs, index = check.inferB(tparams, targs) + targs, index = check.inferB(pos, tparams, targs) if targs == nil || index < 0 { return targs } @@ -360,7 +360,7 @@ func (w *tpWalker) isParameterizedTypeList(list []Type) bool { // first type argument in that list that couldn't be inferred (and thus is nil). If all // type arguments were inferred successfully, index is < 0. The number of type arguments // provided may be less than the number of type parameters, but there must be at least one. -func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type, index int) { +func (check *Checker) inferB(pos syntax.Pos, tparams []*TypeParam, targs []Type) (types []Type, index int) { assert(len(tparams) >= len(targs) && len(targs) > 0) // Setup bidirectional unification between constraints @@ -388,7 +388,7 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type, if !u.unify(tpar, sbound) { // TODO(gri) improve error message by providing the type arguments // which we know already - check.errorf(tpar.obj, "%s does not match %s", tpar, sbound) + check.errorf(pos, "%s does not match %s", tpar, sbound) return nil, 0 } } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45985.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45985.go2 index 9963d2ee00..cea8c14983 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45985.go2 +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue45985.go2 @@ -4,11 +4,10 @@ package issue45985 -// TODO(gri): this error should be on app[int] below. -func app[S /* ERROR "S does not match" */ interface{ ~[]T }, T any](s S, e T) S { +func app[S interface{ ~[]T }, T any](s S, e T) S { return append(s, e) } func _() { - _ = app[int] + _ = app[/* ERROR "S does not match" */int] } diff --git a/src/go/types/infer.go b/src/go/types/infer.go index 909042219c..a5088f2705 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -59,7 +59,7 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, // If we have type arguments, see how far we get with constraint type inference. if len(targs) > 0 { var index int - targs, index = check.inferB(tparams, targs) + targs, index = check.inferB(posn, tparams, targs) if targs == nil || index < 0 { return targs } @@ -174,7 +174,7 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, // See how far we get with constraint type inference. // Note that even if we don't have any type arguments, constraint type inference // may produce results for constraints that explicitly specify a type. - targs, index = check.inferB(tparams, targs) + targs, index = check.inferB(posn, tparams, targs) if targs == nil || index < 0 { return targs } @@ -210,7 +210,7 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, } // Again, follow up with constraint type inference. - targs, index = check.inferB(tparams, targs) + targs, index = check.inferB(posn, tparams, targs) if targs == nil || index < 0 { return targs } @@ -359,7 +359,7 @@ func (w *tpWalker) isParameterizedTypeList(list []Type) bool { // first type argument in that list that couldn't be inferred (and thus is nil). If all // type arguments were inferred successfully, index is < 0. The number of type arguments // provided may be less than the number of type parameters, but there must be at least one. -func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type, index int) { +func (check *Checker) inferB(posn positioner, tparams []*TypeParam, targs []Type) (types []Type, index int) { assert(len(tparams) >= len(targs) && len(targs) > 0) // Setup bidirectional unification between constraints @@ -387,7 +387,7 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type, if !u.unify(tpar, sbound) { // TODO(gri) improve error message by providing the type arguments // which we know already - check.errorf(tpar.obj, _InvalidTypeArg, "%s does not match %s", tpar, sbound) + check.errorf(posn, _InvalidTypeArg, "%s does not match %s", tpar, sbound) return nil, 0 } } diff --git a/src/go/types/testdata/fixedbugs/issue45985.go2 b/src/go/types/testdata/fixedbugs/issue45985.go2 index 637e2cad5e..9a0f5e3697 100644 --- a/src/go/types/testdata/fixedbugs/issue45985.go2 +++ b/src/go/types/testdata/fixedbugs/issue45985.go2 @@ -4,11 +4,10 @@ package issue45985 -// TODO(rFindley): this error should be on app[int] below. -func app[S /* ERROR "S does not match" */ interface{ ~[]T }, T any](s S, e T) S { +func app[S interface{ ~[]T }, T any](s S, e T) S { return append(s, e) } func _() { - _ = app[int] + _ = app/* ERROR "S does not match" */[int] } -- GitLab From 8ff254e30ba9d9c13747fe42213c3f54b47c58e7 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 8 Dec 2021 11:12:50 -0800 Subject: [PATCH 2469/2500] cmd/compile: preserve 'any' type alias in unified IR When exporting the "any" empty interface type for unified IR, write it out as a reference to the "any" alias, rather than to the underlying empty interface. This matches how "byte" and "rune" are handled. Verified to fix the issue demonstrated in CL 369975. Change-Id: Ic2844b0acc3b17c20b3a40aaf262f62ec653eb5a Reviewed-on: https://go-review.googlesource.com/c/go/+/370374 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Gopher Robot Reviewed-by: Russ Cox --- src/cmd/compile/internal/noder/writer.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index dde42c85d6..2bb0b4d5d7 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -229,6 +229,8 @@ func (pw *pkgWriter) pkgIdx(pkg *types2.Package) int { // @@@ Types +var anyTypeName = types2.Universe.Lookup("any").(*types2.TypeName) + func (w *writer) typ(typ types2.Type) { w.typInfo(w.p.typIdx(typ, w.dict)) } @@ -350,6 +352,12 @@ func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo { w.structType(typ) case *types2.Interface: + if typ == anyTypeName.Type() { + w.code(typeNamed) + w.obj(anyTypeName, nil) + break + } + w.code(typeInterface) w.interfaceType(typ) -- GitLab From 13d15d147dd09b9209f5bc3778905684379129d8 Mon Sep 17 00:00:00 2001 From: Hossein Zolfi Date: Fri, 10 Dec 2021 12:39:57 +0330 Subject: [PATCH 2470/2500] go/types: remove TODO that is no longer relevant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ie897b7b9c0a61c837245642c608129108e28423e Reviewed-on: https://go-review.googlesource.com/c/go/+/370582 Reviewed-by: Robert Findley Trust: Robert Findley Run-TryBot: Robert Findley Trust: Nooras Saba‎ TryBot-Result: Gopher Robot --- src/go/types/testdata/check/issues.go2 | 1 - 1 file changed, 1 deletion(-) diff --git a/src/go/types/testdata/check/issues.go2 b/src/go/types/testdata/check/issues.go2 index ac8ef789e5..371856eea3 100644 --- a/src/go/types/testdata/check/issues.go2 +++ b/src/go/types/testdata/check/issues.go2 @@ -47,7 +47,6 @@ func (T) m1() func (*T) m2() func _() { - // TODO(rFindley) this error should be positioned on the 'T'. f2[T /* ERROR wrong method signature */ ]() f2[*T]() } -- GitLab From c473ca087733236a6524900d037d92f32d5f6b70 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 3 Dec 2021 14:02:58 -0500 Subject: [PATCH 2471/2500] net: ignore EADDRINUSE errors when dialing to IPv4 from IPv6 on FreeBSD The failure mode in #34264 appears to match https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=210726. That bug was supposed to have been fixed in FreeBSD 12, but we're still observing failures specifically for the 6-to-4 case on FreeBSD 12.2. It is not clear to me whether FreeBSD 13.0 is also affected. For #34264 Change-Id: Iba7c7fc57676ae628b13c0b8fe43ddf2251c3637 Reviewed-on: https://go-review.googlesource.com/c/go/+/369157 Trust: Bryan Mills Run-TryBot: Bryan Mills Trust: Dmitri Shuralyov TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor --- src/net/dial_test.go | 17 +++++++++++++++-- src/net/dial_unix_test.go | 7 +++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/net/dial_test.go b/src/net/dial_test.go index 8967892197..36843870aa 100644 --- a/src/net/dial_test.go +++ b/src/net/dial_test.go @@ -537,6 +537,9 @@ func TestDialerPartialDeadline(t *testing.T) { } } +// isEADDRINUSE reports whether err is syscall.EADDRINUSE. +var isEADDRINUSE = func(err error) bool { return false } + func TestDialerLocalAddr(t *testing.T) { if !supportsIPv4() || !supportsIPv6() { t.Skip("both IPv4 and IPv6 are required") @@ -592,7 +595,9 @@ func TestDialerLocalAddr(t *testing.T) { {"tcp", "::1", &UnixAddr{}, &AddrError{Err: "some error"}}, } + issue34264Index := -1 if supportsIPv4map() { + issue34264Index = len(tests) tests = append(tests, test{ "tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("::")}, nil, }) @@ -627,7 +632,7 @@ func TestDialerLocalAddr(t *testing.T) { } } - for _, tt := range tests { + for i, tt := range tests { d := &Dialer{LocalAddr: tt.laddr} var addr string ip := ParseIP(tt.raddr) @@ -639,7 +644,15 @@ func TestDialerLocalAddr(t *testing.T) { } c, err := d.Dial(tt.network, addr) if err == nil && tt.error != nil || err != nil && tt.error == nil { - t.Errorf("%s %v->%s: got %v; want %v", tt.network, tt.laddr, tt.raddr, err, tt.error) + if i == issue34264Index && runtime.GOOS == "freebsd" && isEADDRINUSE(err) { + // https://golang.org/issue/34264: FreeBSD through at least version 12.2 + // has been observed to fail with EADDRINUSE when dialing from an IPv6 + // local address to an IPv4 remote address. + t.Logf("%s %v->%s: got %v; want %v", tt.network, tt.laddr, tt.raddr, err, tt.error) + t.Logf("(spurious EADDRINUSE ignored on freebsd: see https://golang.org/issue/34264)") + } else { + t.Errorf("%s %v->%s: got %v; want %v", tt.network, tt.laddr, tt.raddr, err, tt.error) + } } if err != nil { if perr := parseDialError(err); perr != nil { diff --git a/src/net/dial_unix_test.go b/src/net/dial_unix_test.go index 1113aaca90..64dca70eb8 100644 --- a/src/net/dial_unix_test.go +++ b/src/net/dial_unix_test.go @@ -8,11 +8,18 @@ package net import ( "context" + "errors" "syscall" "testing" "time" ) +func init() { + isEADDRINUSE = func(err error) bool { + return errors.Is(err, syscall.EADDRINUSE) + } +} + // Issue 16523 func TestDialContextCancelRace(t *testing.T) { oldConnectFunc := connectFunc -- GitLab From 766f89b5c625f8c57492cf5645576d9e6f450cc2 Mon Sep 17 00:00:00 2001 From: Tim King Date: Thu, 9 Dec 2021 11:06:25 -0800 Subject: [PATCH 2472/2500] doc: document cmd/vet changes for 1.18 release cmd/vet has several precision improvements for the checkers copylock, printf, sortslice, testinggoroutine, and tests. Adds a high level mention in the release notes and an example of string constant concatenation. Updates #47694 Change-Id: I7a342a57ca3fd9e2f3e8ec99f7b647269798317f Reviewed-on: https://go-review.googlesource.com/c/go/+/370734 Reviewed-by: Russ Cox Reviewed-by: Robert Findley Trust: Tim King Run-TryBot: Tim King TryBot-Result: Gopher Robot --- doc/go1.18.html | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/doc/go1.18.html b/doc/go1.18.html index 8142a93b7b..67af3e6a90 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -288,6 +288,21 @@ Do not send CLs removing the interior tags from such phrases. }

    +

    Precision improvements for existing checkers

    + +

    + The cmd/vet checkers copylock, printf, + sortslice, testinggoroutine, and tests + have all had moderate precision improvements to handle additional code patterns. + This may lead to newly reported errors in existing packages. For example, the + printf checker now tracks formatting strings created by + concatenating string constants. So vet will report an error in: +

    +  // fmt.Printf formatting directive %d is being passed to Println.
    +  fmt.Println("%d"+` ≡ x (mod 2)`+"\n", x%2)
    +
    +

    +

    Runtime

    -- GitLab From 1c1998ea08d41ef09ef16c22eb8e53ea0eb569c5 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Sat, 11 Dec 2021 16:17:46 -0800 Subject: [PATCH 2473/2500] net/netip: fix formatting of IPv4-in-6 address with zone Weird, but don't drop the zone when stringifying. Fixes #50111 Change-Id: I5fbccdfedcdc77a77ee6bafc8d82b8ec8ec7220c Reviewed-on: https://go-review.googlesource.com/c/go/+/371094 Run-TryBot: Brad Fitzpatrick TryBot-Result: Gopher Robot Reviewed-by: Matt Layher Trust: Matt Layher Trust: Ian Lance Taylor --- src/net/netip/netip.go | 21 ++++++++++++++++++--- src/net/netip/netip_test.go | 6 ++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/net/netip/netip.go b/src/net/netip/netip.go index 01f6fe5efa..dc5faff40f 100644 --- a/src/net/netip/netip.go +++ b/src/net/netip/netip.go @@ -769,7 +769,11 @@ func (ip Addr) String() string { default: if ip.Is4In6() { // TODO(bradfitz): this could alloc less. - return "::ffff:" + ip.Unmap().String() + if z := ip.Zone(); z != "" { + return "::ffff:" + ip.Unmap().String() + "%" + z + } else { + return "::ffff:" + ip.Unmap().String() + } } return ip.string6() } @@ -787,7 +791,12 @@ func (ip Addr) AppendTo(b []byte) []byte { default: if ip.Is4In6() { b = append(b, "::ffff:"...) - return ip.Unmap().appendTo4(b) + b = ip.Unmap().appendTo4(b) + if z := ip.Zone(); z != "" { + b = append(b, '%') + b = append(b, z...) + } + return b } return ip.appendTo6(b) } @@ -947,10 +956,16 @@ func (ip Addr) MarshalText() ([]byte, error) { b := make([]byte, 0, max) if ip.Is4In6() { b = append(b, "::ffff:"...) - return ip.Unmap().appendTo4(b), nil + b = ip.Unmap().appendTo4(b) + if z := ip.Zone(); z != "" { + b = append(b, '%') + b = append(b, z...) + } + return b, nil } return ip.appendTo6(b), nil } + } // UnmarshalText implements the encoding.TextUnmarshaler interface. diff --git a/src/net/netip/netip_test.go b/src/net/netip/netip_test.go index a6327f0dea..2105545139 100644 --- a/src/net/netip/netip_test.go +++ b/src/net/netip/netip_test.go @@ -114,6 +114,12 @@ func TestParseAddr(t *testing.T) { ip: MkAddr(Mk128(0x0001000200000000, 0x0000ffffc0a88cff), intern.Get("eth1")), str: "1:2::ffff:c0a8:8cff%eth1", }, + // 4-in-6 with zone + { + in: "::ffff:192.168.140.255%eth1", + ip: MkAddr(Mk128(0, 0x0000ffffc0a88cff), intern.Get("eth1")), + str: "::ffff:192.168.140.255%eth1", + }, // IPv6 with capital letters. { in: "FD9E:1A04:F01D::1", -- GitLab From 9c6e8f63c0e4f24ccf4326164ddbc0f0607343a2 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Sat, 11 Dec 2021 19:35:08 -0800 Subject: [PATCH 2474/2500] net/netip: make AddrPort.MarshalText format 4-in-6 IPs consistently Thanks again to @capnspacehook. Fixes #50110 Change-Id: I1973bdea68eac9842b45f9524f62152e4f5342cf Reviewed-on: https://go-review.googlesource.com/c/go/+/371114 Run-TryBot: Brad Fitzpatrick Reviewed-by: Matt Layher Trust: Matt Layher Trust: Brad Fitzpatrick TryBot-Result: Gopher Robot --- src/net/netip/netip.go | 13 +++++++++++-- src/net/netip/netip_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/net/netip/netip.go b/src/net/netip/netip.go index dc5faff40f..aaaf435ed8 100644 --- a/src/net/netip/netip.go +++ b/src/net/netip/netip.go @@ -1157,8 +1157,17 @@ func (p AddrPort) AppendTo(b []byte) []byte { case z4: b = p.ip.appendTo4(b) default: - b = append(b, '[') - b = p.ip.appendTo6(b) + if p.ip.Is4In6() { + b = append(b, "[::ffff:"...) + b = p.ip.Unmap().appendTo4(b) + if z := p.ip.Zone(); z != "" { + b = append(b, '%') + b = append(b, z...) + } + } else { + b = append(b, '[') + b = p.ip.appendTo6(b) + } b = append(b, ']') } b = append(b, ':') diff --git a/src/net/netip/netip_test.go b/src/net/netip/netip_test.go index 2105545139..869628050a 100644 --- a/src/net/netip/netip_test.go +++ b/src/net/netip/netip_test.go @@ -347,6 +347,32 @@ func TestAddrMarshalUnmarshalBinary(t *testing.T) { } } +func TestAddrPortMarshalTextString(t *testing.T) { + tests := []struct { + in AddrPort + want string + }{ + {mustIPPort("1.2.3.4:80"), "1.2.3.4:80"}, + {mustIPPort("[1::CAFE]:80"), "[1::cafe]:80"}, + {mustIPPort("[1::CAFE%en0]:80"), "[1::cafe%en0]:80"}, + {mustIPPort("[::FFFF:192.168.140.255]:80"), "[::ffff:192.168.140.255]:80"}, + {mustIPPort("[::FFFF:192.168.140.255%en0]:80"), "[::ffff:192.168.140.255%en0]:80"}, + } + for i, tt := range tests { + if got := tt.in.String(); got != tt.want { + t.Errorf("%d. for (%v, %v) String = %q; want %q", i, tt.in.Addr(), tt.in.Port(), got, tt.want) + } + mt, err := tt.in.MarshalText() + if err != nil { + t.Errorf("%d. for (%v, %v) MarshalText error: %v", i, tt.in.Addr(), tt.in.Port(), err) + continue + } + if string(mt) != tt.want { + t.Errorf("%d. for (%v, %v) MarshalText = %q; want %q", i, tt.in.Addr(), tt.in.Port(), mt, tt.want) + } + } +} + func TestAddrPortMarshalUnmarshalBinary(t *testing.T) { tests := []struct { ipport string -- GitLab From 6b8977372263504535cad6e880ffca156bdfdf68 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 9 Dec 2021 12:25:04 -0500 Subject: [PATCH 2475/2500] testenv: abstract run-with-timeout into testenv This lifts the logic to run a subcommand with a timeout in a test from the runtime's runTestProg into testenv. The implementation is unchanged in this CL. We'll improve it in a future CL. Currently, tests that run subcommands usually just timeout with no useful output if the subcommand runs for too long. This is a step toward improving this. For #37405. Change-Id: I2298770db516e216379c4c438e05d23cbbdda51d Reviewed-on: https://go-review.googlesource.com/c/go/+/370701 Trust: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Gopher Robot Reviewed-by: Michael Knyszek Reviewed-by: Bryan Mills --- src/internal/testenv/testenv.go | 51 +++++++++++++++++++ .../testenv/testenv_notunix.go} | 8 +-- src/internal/testenv/testenv_unix.go | 13 +++++ src/runtime/crash_test.go | 41 +-------------- src/runtime/crash_unix_test.go | 6 +-- 5 files changed, 71 insertions(+), 48 deletions(-) rename src/{runtime/crash_nonunix_test.go => internal/testenv/testenv_notunix.go} (57%) create mode 100644 src/internal/testenv/testenv_unix.go diff --git a/src/internal/testenv/testenv.go b/src/internal/testenv/testenv.go index c902b1404f..eeb7d65a9b 100644 --- a/src/internal/testenv/testenv.go +++ b/src/internal/testenv/testenv.go @@ -11,6 +11,7 @@ package testenv import ( + "bytes" "errors" "flag" "internal/cfg" @@ -22,6 +23,7 @@ import ( "strings" "sync" "testing" + "time" ) // Builder reports the name of the builder running this test @@ -306,3 +308,52 @@ func SkipIfShortAndSlow(t testing.TB) { t.Skipf("skipping test in -short mode on %s", runtime.GOARCH) } } + +// RunWithTimeout runs cmd and returns its combined output. If the +// subprocess exits with a non-zero status, it will log that status +// and return a non-nil error, but this is not considered fatal. +func RunWithTimeout(t testing.TB, cmd *exec.Cmd) ([]byte, error) { + args := cmd.Args + if args == nil { + args = []string{cmd.Path} + } + + var b bytes.Buffer + cmd.Stdout = &b + cmd.Stderr = &b + if err := cmd.Start(); err != nil { + t.Fatalf("starting %s: %v", args, err) + } + + // If the process doesn't complete within 1 minute, + // assume it is hanging and kill it to get a stack trace. + p := cmd.Process + done := make(chan bool) + go func() { + scale := 1 + // This GOARCH/GOOS test is copied from cmd/dist/test.go. + // TODO(iant): Have cmd/dist update the environment variable. + if runtime.GOARCH == "arm" || runtime.GOOS == "windows" { + scale = 2 + } + if s := os.Getenv("GO_TEST_TIMEOUT_SCALE"); s != "" { + if sc, err := strconv.Atoi(s); err == nil { + scale = sc + } + } + + select { + case <-done: + case <-time.After(time.Duration(scale) * time.Minute): + p.Signal(Sigquit) + } + }() + + err := cmd.Wait() + if err != nil { + t.Logf("%s exit status: %v", args, err) + } + close(done) + + return b.Bytes(), err +} diff --git a/src/runtime/crash_nonunix_test.go b/src/internal/testenv/testenv_notunix.go similarity index 57% rename from src/runtime/crash_nonunix_test.go rename to src/internal/testenv/testenv_notunix.go index 73c1cd3101..180206bc9b 100644 --- a/src/runtime/crash_nonunix_test.go +++ b/src/internal/testenv/testenv_notunix.go @@ -1,13 +1,13 @@ -// Copyright 2016 The Go Authors. All rights reserved. +// Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. //go:build windows || plan9 || (js && wasm) -package runtime_test +package testenv import "os" -// sigquit is the signal to send to kill a hanging testdata program. +// Sigquit is the signal to send to kill a hanging subprocess. // On Unix we send SIGQUIT, but on non-Unix we only have os.Kill. -var sigquit = os.Kill +var Sigquit = os.Kill diff --git a/src/internal/testenv/testenv_unix.go b/src/internal/testenv/testenv_unix.go new file mode 100644 index 0000000000..3dc5daf45e --- /dev/null +++ b/src/internal/testenv/testenv_unix.go @@ -0,0 +1,13 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris + +package testenv + +import "syscall" + +// Sigquit is the signal to send to kill a hanging subprocess. +// Send SIGQUIT to get a stack trace. +var Sigquit = syscall.SIGQUIT diff --git a/src/runtime/crash_test.go b/src/runtime/crash_test.go index ec4db99d78..01b1ebcdd7 100644 --- a/src/runtime/crash_test.go +++ b/src/runtime/crash_test.go @@ -15,11 +15,9 @@ import ( "path/filepath" "regexp" "runtime" - "strconv" "strings" "sync" "testing" - "time" ) var toRemove []string @@ -71,43 +69,8 @@ func runBuiltTestProg(t *testing.T, exe, name string, env ...string) string { if testing.Short() { cmd.Env = append(cmd.Env, "RUNTIME_TEST_SHORT=1") } - var b bytes.Buffer - cmd.Stdout = &b - cmd.Stderr = &b - if err := cmd.Start(); err != nil { - t.Fatalf("starting %s %s: %v", exe, name, err) - } - - // If the process doesn't complete within 1 minute, - // assume it is hanging and kill it to get a stack trace. - p := cmd.Process - done := make(chan bool) - go func() { - scale := 1 - // This GOARCH/GOOS test is copied from cmd/dist/test.go. - // TODO(iant): Have cmd/dist update the environment variable. - if runtime.GOARCH == "arm" || runtime.GOOS == "windows" { - scale = 2 - } - if s := os.Getenv("GO_TEST_TIMEOUT_SCALE"); s != "" { - if sc, err := strconv.Atoi(s); err == nil { - scale = sc - } - } - - select { - case <-done: - case <-time.After(time.Duration(scale) * time.Minute): - p.Signal(sigquit) - } - }() - - if err := cmd.Wait(); err != nil { - t.Logf("%s %s exit status: %v", exe, name, err) - } - close(done) - - return b.String() + out, _ := testenv.RunWithTimeout(t, cmd) + return string(out) } var serializeBuild = make(chan bool, 2) diff --git a/src/runtime/crash_unix_test.go b/src/runtime/crash_unix_test.go index b93a760276..1eb10f9b60 100644 --- a/src/runtime/crash_unix_test.go +++ b/src/runtime/crash_unix_test.go @@ -21,16 +21,12 @@ import ( "unsafe" ) -// sigquit is the signal to send to kill a hanging testdata program. -// Send SIGQUIT to get a stack trace. -var sigquit = syscall.SIGQUIT - func init() { if runtime.Sigisblocked(int(syscall.SIGQUIT)) { // We can't use SIGQUIT to kill subprocesses because // it's blocked. Use SIGKILL instead. See issue // #19196 for an example of when this happens. - sigquit = syscall.SIGKILL + testenv.Sigquit = syscall.SIGKILL } } -- GitLab From cc795a01dcec7c97044b31571af88ac98310f2b3 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 9 Dec 2021 12:51:29 -0500 Subject: [PATCH 2476/2500] testenv: kill subprocess if SIGQUIT doesn't do it This makes testenv.RunWithTimeout first attempt to SIGQUIT the subprocess to get a useful Go traceback, but if that doesn't work, it sends a SIGKILL instead to make sure we tear down the subprocess. This is potentially important for non-Go subprocesses. For #37405. Change-Id: I9e7e118dc5769ec3f45288a71658733bff30c9cd Reviewed-on: https://go-review.googlesource.com/c/go/+/370702 Trust: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Gopher Robot Reviewed-by: Bryan Mills Reviewed-by: Ian Lance Taylor --- src/internal/testenv/testenv.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/internal/testenv/testenv.go b/src/internal/testenv/testenv.go index eeb7d65a9b..d7614b0706 100644 --- a/src/internal/testenv/testenv.go +++ b/src/internal/testenv/testenv.go @@ -346,6 +346,13 @@ func RunWithTimeout(t testing.TB, cmd *exec.Cmd) ([]byte, error) { case <-done: case <-time.After(time.Duration(scale) * time.Minute): p.Signal(Sigquit) + // If SIGQUIT doesn't do it after a little + // while, kill the process. + select { + case <-done: + case <-time.After(time.Duration(scale) * 30 * time.Second): + p.Signal(os.Kill) + } } }() -- GitLab From 8692bacb6a43d1f65e09d0e581ca8b464fd77664 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 9 Dec 2021 13:52:18 -0500 Subject: [PATCH 2477/2500] runtime: run gdb with a timeout for TestGdbBacktrace This sometimes times out and we don't have any useful output for debugging it. Hopefully this will help. For #37405. Change-Id: I79074e6fbb9bd16a864c651109a0acbfc8aa6cef Reviewed-on: https://go-review.googlesource.com/c/go/+/370703 Trust: Austin Clements Run-TryBot: Austin Clements Reviewed-by: Michael Knyszek TryBot-Result: Gopher Robot --- src/runtime/runtime-gdb_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/runtime-gdb_test.go b/src/runtime/runtime-gdb_test.go index 4a0f489c2f..63d3160ee4 100644 --- a/src/runtime/runtime-gdb_test.go +++ b/src/runtime/runtime-gdb_test.go @@ -424,7 +424,7 @@ func TestGdbBacktrace(t *testing.T) { "-ex", "continue", filepath.Join(dir, "a.exe"), } - got, err := exec.Command("gdb", args...).CombinedOutput() + got, err := testenv.RunWithTimeout(t, exec.Command("gdb", args...)) t.Logf("gdb output:\n%s", got) if err != nil { t.Fatalf("gdb exited with error: %v", err) -- GitLab From 56817040d53187abcd568af0eea27cc21379c0ad Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 10 Dec 2021 21:09:16 -0500 Subject: [PATCH 2478/2500] os: document error returned by pending I/O operations on Close Currently, File.Close only documents that "an" error will be returned by pending I/O operations. Update the documentation to say that error is specifically ErrClosed. Change-Id: Ica817c9196ad6cb570c826789d37a4ff15a5d13d Reviewed-on: https://go-review.googlesource.com/c/go/+/371015 Trust: Austin Clements Reviewed-by: Ian Lance Taylor --- src/os/file_plan9.go | 2 +- src/os/file_posix.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/os/file_plan9.go b/src/os/file_plan9.go index 604aea607b..887e1c8892 100644 --- a/src/os/file_plan9.go +++ b/src/os/file_plan9.go @@ -139,7 +139,7 @@ func openFileNolog(name string, flag int, perm FileMode) (*File, error) { // Close closes the File, rendering it unusable for I/O. // On files that support SetDeadline, any pending I/O operations will -// be canceled and return immediately with an error. +// be canceled and return immediately with an ErrClosed error. // Close will return an error if it has already been called. func (f *File) Close() error { if err := f.checkValid("close"); err != nil { diff --git a/src/os/file_posix.go b/src/os/file_posix.go index 0dc6da0908..f34571d68d 100644 --- a/src/os/file_posix.go +++ b/src/os/file_posix.go @@ -16,7 +16,7 @@ func sigpipe() // implemented in package runtime // Close closes the File, rendering it unusable for I/O. // On files that support SetDeadline, any pending I/O operations will -// be canceled and return immediately with an error. +// be canceled and return immediately with an ErrClosed error. // Close will return an error if it has already been called. func (f *File) Close() error { if f == nil { -- GitLab From 49b7c9caec6b96d0b327624efee61bd8a72cf68c Mon Sep 17 00:00:00 2001 From: Matt Layher Date: Sun, 12 Dec 2021 10:53:17 -0500 Subject: [PATCH 2479/2500] net/netip: make Prefix.MarshalText format 4-in-6 IPs consistently Fixes #50115. Change-Id: Iac76e5b486d3a2a784583345eaeb22c31cc4a36d Reviewed-on: https://go-review.googlesource.com/c/go/+/371134 Trust: Matt Layher Run-TryBot: Matt Layher Reviewed-by: Brad Fitzpatrick Trust: Brad Fitzpatrick TryBot-Result: Gopher Robot --- src/net/netip/netip.go | 7 ++++++- src/net/netip/netip_test.go | 27 ++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/net/netip/netip.go b/src/net/netip/netip.go index aaaf435ed8..591d38abc8 100644 --- a/src/net/netip/netip.go +++ b/src/net/netip/netip.go @@ -1422,7 +1422,12 @@ func (p Prefix) AppendTo(b []byte) []byte { if p.ip.z == z4 { b = p.ip.appendTo4(b) } else { - b = p.ip.appendTo6(b) + if p.ip.Is4In6() { + b = append(b, "::ffff:"...) + b = p.ip.Unmap().appendTo4(b) + } else { + b = p.ip.appendTo6(b) + } } b = append(b, '/') diff --git a/src/net/netip/netip_test.go b/src/net/netip/netip_test.go index 869628050a..520695cdfb 100644 --- a/src/net/netip/netip_test.go +++ b/src/net/netip/netip_test.go @@ -413,6 +413,32 @@ func TestAddrPortMarshalUnmarshalBinary(t *testing.T) { } } +func TestPrefixMarshalTextString(t *testing.T) { + tests := []struct { + in Prefix + want string + }{ + {mustPrefix("1.2.3.4/24"), "1.2.3.4/24"}, + {mustPrefix("fd7a:115c:a1e0:ab12:4843:cd96:626b:430b/118"), "fd7a:115c:a1e0:ab12:4843:cd96:626b:430b/118"}, + {mustPrefix("::ffff:c000:0280/96"), "::ffff:192.0.2.128/96"}, + {mustPrefix("::ffff:c000:0280%eth0/37"), "::ffff:192.0.2.128/37"}, // Zone should be stripped + {mustPrefix("::ffff:192.168.140.255/8"), "::ffff:192.168.140.255/8"}, + } + for i, tt := range tests { + if got := tt.in.String(); got != tt.want { + t.Errorf("%d. for %v String = %q; want %q", i, tt.in, got, tt.want) + } + mt, err := tt.in.MarshalText() + if err != nil { + t.Errorf("%d. for %v MarshalText error: %v", i, tt.in, err) + continue + } + if string(mt) != tt.want { + t.Errorf("%d. for %v MarshalText = %q; want %q", i, tt.in, mt, tt.want) + } + } +} + func TestPrefixMarshalUnmarshalBinary(t *testing.T) { type testCase struct { prefix Prefix @@ -994,7 +1020,6 @@ func TestPrefixMarshalUnmarshal(t *testing.T) { "0.0.0.0/0", "::/0", "::1/128", - "::ffff:c000:1234/128", "2001:db8::/32", } -- GitLab From 9bfe09d78bd1b3ab97bc6e1c31395f0822875fba Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sun, 12 Dec 2021 11:08:59 -0800 Subject: [PATCH 2480/2500] cmd/compile: fix identity case relating to 'any' and shape types In identical(), we don't want any to match a shape empty-interface type for the identStrict option, since IdenticalStrict() is specifically not supposed to match a shape type with a non-shape type. There is similar code in (*Type).cmp() (TINTER case), but I don't believe that we want to disqualify shape types from matching any in this case, since cmp() is used for back-end code, where we don't care about shape types vs non-shape types. The issue mainly comes about when 'any' is used as a type argument (rather than 'interface{}'), but only with some complicated circumstances, as shown by the test case. (Couldn't reproduce with simpler test cases.) Fixes #50109 Change-Id: I3f2f88be158f9ad09273237e1d346bc56aac099f Reviewed-on: https://go-review.googlesource.com/c/go/+/371154 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Gopher Robot Reviewed-by: Keith Randall --- src/cmd/compile/internal/types/identity.go | 6 +- test/typeparam/issue50109.go | 105 +++++++++++++++++++++ test/typeparam/issue50109.out | 1 + 3 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 test/typeparam/issue50109.go create mode 100644 test/typeparam/issue50109.out diff --git a/src/cmd/compile/internal/types/identity.go b/src/cmd/compile/internal/types/identity.go index f99e50a1c3..a164b84da9 100644 --- a/src/cmd/compile/internal/types/identity.go +++ b/src/cmd/compile/internal/types/identity.go @@ -59,7 +59,11 @@ func identical(t1, t2 *Type, flags int, assumedEqual map[typePair]struct{}) bool case TINT32: return (t1 == Types[TINT32] || t1 == RuneType) && (t2 == Types[TINT32] || t2 == RuneType) case TINTER: - // Make sure named any type matches any empty interface. + // Make sure named any type matches any empty interface + // (but not a shape type, if identStrict). + if flags&identStrict != 0 { + return t1 == AnyType && t2.IsEmptyInterface() && !t2.HasShape() || t2 == AnyType && t1.IsEmptyInterface() && !t1.HasShape() + } return t1 == AnyType && t2.IsEmptyInterface() || t2 == AnyType && t1.IsEmptyInterface() default: return false diff --git a/test/typeparam/issue50109.go b/test/typeparam/issue50109.go new file mode 100644 index 0000000000..a6913df843 --- /dev/null +++ b/test/typeparam/issue50109.go @@ -0,0 +1,105 @@ +// run -gcflags=-G=3 + +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" +) + +type AnyCacher[T any] interface { + // Get an item from the cache. Returns the item or nil, and a bool indicating + // whether the key was found. + Get(k string) (T, bool) + // Add an item to the cache, replacing any existing item. + Set(k string, x T) +} + +// Item ... +type Item[T any] struct { + Object T +} + +// AnyCache implements AnyCacher +type AnyCache[T any] struct { + *anyCache[T] +} + +type anyCache[T any] struct { + items map[string]Item[T] + janitor *janitor[T] // Needed for the failure in the issue +} + +// Set adds an item to the cache, replacing any existing item. +func (c *anyCache[T]) Set(k string, x T) { + c.items[k] = Item[T]{ + Object: x, + } +} + +// Get gets an item from the cache. Returns the item or nil, and a bool indicating +// whether the key was found. +func (c *anyCache[T]) Get(k string) (T, bool) { + // "Inlining" of get and Expired + item, found := c.items[k] + if !found { + var ret T + return ret, false + } + + return item.Object, true +} + +type janitor[T any] struct { + stop chan bool +} + +func newAnyCache[T any](m map[string]Item[T]) *anyCache[T] { + c := &anyCache[T]{ + items: m, + } + return c +} + +// NewAny[T any](...) returns a new AnyCache[T]. +func NewAny[T any]() *AnyCache[T] { + items := make(map[string]Item[T]) + return &AnyCache[T]{newAnyCache(items)} +} + +// NewAnyCacher[T any](...) returns an AnyCacher[T] interface. +func NewAnyCacher[T any]() AnyCacher[T] { + return NewAny[T]() +} + +type MyStruct struct { + Name string +} + +func main() { + // Create a generic cache. + // All items are cached as interface{} so they need to be cast back to their + // original type when retrieved. + // Failure in issue doesn't happen with 'any' replaced by 'interface{}' + c := NewAnyCacher[any]() + + myStruct := &MyStruct{"MySuperStruct"} + + c.Set("MySuperStruct", myStruct) + + myRawCachedStruct, found := c.Get("MySuperStruct") + + if found { + // Casting the retrieved object back to its original type + myCachedStruct := myRawCachedStruct.(*MyStruct) + fmt.Printf("%s", myCachedStruct.Name) + } else { + fmt.Printf("Error: MySuperStruct not found in cache") + } + + // Output: + // MySuperStruct +} diff --git a/test/typeparam/issue50109.out b/test/typeparam/issue50109.out new file mode 100644 index 0000000000..7d6ecc0c6d --- /dev/null +++ b/test/typeparam/issue50109.out @@ -0,0 +1 @@ +MySuperStruct \ No newline at end of file -- GitLab From 36db10f3cb916a1b97af3bfd4be7e3a2932185f8 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 9 Dec 2021 17:00:51 -0500 Subject: [PATCH 2481/2500] net: remove erroneous Dial check in TestListenerClose TestListenerClose had been asserting that a Dial to the newly-closed address always fails, on the assumption that the listener's address and port would not be reused by some other listener that could then accept the connection. As far as I can tell, that assumption is not valid: the Dial after Close may well connect to a Listener opened for some other test, or even one opened by a completely different process running concurrently on the same machine. Fixes #38700 Change-Id: I925ed1b2ccb556135a2c5be0240d1789ed27d5fc Reviewed-on: https://go-review.googlesource.com/c/go/+/370666 Trust: Bryan Mills Run-TryBot: Bryan Mills TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor --- src/net/net_test.go | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/src/net/net_test.go b/src/net/net_test.go index 35acac509b..5d9c3c67e6 100644 --- a/src/net/net_test.go +++ b/src/net/net_test.go @@ -243,7 +243,6 @@ func TestListenerClose(t *testing.T) { defer os.Remove(ln.Addr().String()) } - dst := ln.Addr().String() if err := ln.Close(); err != nil { if perr := parseCloseError(err, false); perr != nil { t.Error(perr) @@ -256,28 +255,12 @@ func TestListenerClose(t *testing.T) { t.Fatal("should fail") } - if network == "tcp" { - // We will have two TCP FSMs inside the - // kernel here. There's no guarantee that a - // signal comes from the far end FSM will be - // delivered immediately to the near end FSM, - // especially on the platforms that allow - // multiple consumer threads to pull pending - // established connections at the same time by - // enabling SO_REUSEPORT option such as Linux, - // DragonFly BSD. So we need to give some time - // quantum to the kernel. - // - // Note that net.inet.tcp.reuseport_ext=1 by - // default on DragonFly BSD. - time.Sleep(time.Millisecond) - - cc, err := Dial("tcp", dst) - if err == nil { - t.Error("Dial to closed TCP listener succeeded.") - cc.Close() - } - } + // Note: we cannot ensure that a subsequent Dial does not succeed, because + // we do not in general have any guarantee that ln.Addr is not immediately + // reused. (TCP sockets enter a TIME_WAIT state when closed, but that only + // applies to existing connections for the port — it does not prevent the + // port itself from being used for entirely new connections in the + // meantime.) }) } } -- GitLab From 6f42be78bbc107beef8b6eb61a794355e07120ca Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 9 Dec 2021 11:54:46 -0500 Subject: [PATCH 2482/2500] net: do not try to remove the LocalAddr of a unix socket MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TestUnixAndUnixpacketServer deferred a call to os.Remove on the local address of a dialed unix domain socket, in an attempt to remove the socket from the server. However, that call appears to be neither necessary nor correct. In this test, the file that needs to be unlinked is the one attached to the listener — but the listener's Close method already does that (see the Unlink call in (*UnixListener).close), so there is no need for the test itself to do the same. Moreover, the local address is not something that is sensible to delete — on Linux, it is empirically always the literal string "@" — and the Addr returned by c.LocalAddr is not reliably non-nil on all platforms (see #34611). Since we don't need to do anything with the local address, we shouldn't. At best, this is a benign Remove of a file that doesn't exist anyway; at worst, it is a nil-panic. Fixes #34611 Change-Id: Ie072b3388d884d60e819d1df210fa7d3e2eed124 Reviewed-on: https://go-review.googlesource.com/c/go/+/370695 Trust: Bryan Mills Run-TryBot: Bryan Mills TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor --- src/net/server_test.go | 29 ++--------------------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/src/net/server_test.go b/src/net/server_test.go index 33d33b0337..ae1c1619ed 100644 --- a/src/net/server_test.go +++ b/src/net/server_test.go @@ -7,9 +7,7 @@ package net import ( - "fmt" "os" - "reflect" "testing" ) @@ -190,32 +188,9 @@ func TestUnixAndUnixpacketServer(t *testing.T) { t.Fatal(err) } - // We really just want to defer os.Remove(c.LocalAddr().String()) here, - // but sometimes that panics due to a nil dereference on the - // solaris-amd64-oraclerel builder (https://golang.org/issue/34611). - // The source of the nil panic is not obvious because there are many - // nillable types involved, so we will temporarily inspect all of them to - // try to get a better idea of what is happening on that platform. - checkNils := func() { - if c == nil { - panic("Dial returned a nil Conn") - } - if rc := reflect.ValueOf(c); rc.Kind() == reflect.Pointer && rc.IsNil() { - panic(fmt.Sprintf("Dial returned a nil %T", c)) - } - addr := c.LocalAddr() - if addr == nil { - panic(fmt.Sprintf("(%T).LocalAddr returned a nil Addr", c)) - } - if raddr := reflect.ValueOf(addr); raddr.Kind() == reflect.Pointer && raddr.IsNil() { - panic(fmt.Sprintf("(%T).LocalAddr returned a nil %T", c, addr)) - } + if addr := c.LocalAddr(); addr != nil { + t.Logf("connected %s->%s", addr, lss[i].Listener.Addr()) } - defer func() { - checkNils() - os.Remove(c.LocalAddr().String()) - }() - checkNils() defer c.Close() trchs = append(trchs, make(chan error, 1)) -- GitLab From f4ca598c9f08a4d00942a1c6a6b8cc7d8f162b66 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 3 Dec 2021 11:44:00 -0500 Subject: [PATCH 2483/2500] net: don't check "invalid.invalid" lookup errors in TestLookupHostCancel The exact error isn't actually relevant to the test, and may depend on whether the Go or cgo resolver is used. Also run the test in parallel, because it spends most of its time sleeping in between lookups. Fixes #38767 Fixes #43140 Change-Id: I2d64ffddf2eb114a69ed3242daa9a9e4a5679f67 Reviewed-on: https://go-review.googlesource.com/c/go/+/369037 Trust: Bryan Mills Run-TryBot: Bryan Mills TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor --- src/net/lookup_test.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/net/lookup_test.go b/src/net/lookup_test.go index 7bcc5c5be8..5b3a3e24b2 100644 --- a/src/net/lookup_test.go +++ b/src/net/lookup_test.go @@ -925,6 +925,8 @@ func TestNilResolverLookup(t *testing.T) { // canceled lookups (see golang.org/issue/24178 for details). func TestLookupHostCancel(t *testing.T) { mustHaveExternalNetwork(t) + t.Parallel() // Executes 600ms worth of sequential sleeps. + const ( google = "www.google.com" invalidDomain = "invalid.invalid" // RFC 2606 reserves .invalid @@ -943,9 +945,15 @@ func TestLookupHostCancel(t *testing.T) { if err == nil { t.Fatalf("LookupHost(%q): returns %v, but should fail", invalidDomain, addr) } - if !strings.Contains(err.Error(), "canceled") { - t.Fatalf("LookupHost(%q): failed with unexpected error: %v", invalidDomain, err) - } + + // Don't verify what the actual error is. + // We know that it must be non-nil because the domain is invalid, + // but we don't have any guarantee that LookupHost actually bothers + // to check for cancellation on the fast path. + // (For example, it could use a local cache to avoid blocking entirely.) + + // The lookup may deduplicate in-flight requests, so give it time to settle + // in between. time.Sleep(time.Millisecond * 1) } -- GitLab From d198a36d8c1d0a251449a1cc2355485a177310c4 Mon Sep 17 00:00:00 2001 From: "Paul E. Murphy" Date: Fri, 10 Dec 2021 16:58:43 -0600 Subject: [PATCH 2484/2500] cmd/asm,cmd/compile: fix tail call in leaf functions on PPC64 In some leaf functions using "RET foo(SB)", the jump may be incorrectly translated into "JMP LR" instead of "JMP foo(SB)". Such is the case when compiling the autogenerated function in k8s k8s.io/kubernetes/pkg/kubelet/server/stats.(*resourceAnalyzer).GetPodVolumeStats. Fixes #50048 Change-Id: Icdf65fcda6b3c5eb9d3ad5c7aad04add9419dffb Reviewed-on: https://go-review.googlesource.com/c/go/+/371034 Run-TryBot: Paul Murphy Reviewed-by: Cherry Mui Trust: Paul Murphy --- src/cmd/internal/obj/ppc64/obj9.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/cmd/internal/obj/ppc64/obj9.go b/src/cmd/internal/obj/ppc64/obj9.go index 7ac6465a72..c986c0d2b6 100644 --- a/src/cmd/internal/obj/ppc64/obj9.go +++ b/src/cmd/internal/obj/ppc64/obj9.go @@ -884,8 +884,13 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { q = c.newprog() q.As = ABR q.Pos = p.Pos - q.To.Type = obj.TYPE_REG - q.To.Reg = REG_LR + if retTarget == nil { + q.To.Type = obj.TYPE_REG + q.To.Reg = REG_LR + } else { + q.To.Type = obj.TYPE_BRANCH + q.To.Sym = retTarget + } q.Mark |= BRANCH q.Spadj = +autosize -- GitLab From b55cbbb9e76969d67fbc6e264a584ad18c2f95fa Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 9 Dec 2021 11:42:42 -0500 Subject: [PATCH 2485/2500] net: pass a testing.TB to newLocal* helpers Passing in an explicit testing.TB gives two benefits: 1. It allows the helper to fail the test itself, instead of returning an error to the caller. A non-nil error invariably fails the calling test, and none of these callers bother to add detail to the error when logging it anyway so returning the error just added noise to the test bodies. 2. It allows the helper to use t.Cleanup to perform any needed cleanup tasks, which will be used in CL 370695 to clean up temp directories used as namespaces for unix socket paths. For #34611 Change-Id: I805e701687c12de2caca955649369294229c10b4 Reviewed-on: https://go-review.googlesource.com/c/go/+/370696 Trust: Bryan Mills Reviewed-by: Ian Lance Taylor Run-TryBot: Bryan Mills TryBot-Result: Gopher Robot --- src/net/conn_test.go | 5 +- src/net/dial_test.go | 38 +++----------- src/net/dial_unix_test.go | 5 +- src/net/error_test.go | 15 ++---- src/net/file_test.go | 35 +++++-------- src/net/listen_test.go | 25 ++++------ src/net/mockserver_test.go | 84 ++++++++++++++++++++----------- src/net/net_test.go | 49 +++++------------- src/net/protoconn_test.go | 5 +- src/net/rawconn_test.go | 15 ++---- src/net/sendfile_test.go | 25 ++-------- src/net/server_test.go | 20 ++------ src/net/splice_test.go | 71 +++++++------------------- src/net/tcpsock_test.go | 25 ++-------- src/net/tcpsock_unix_test.go | 5 +- src/net/timeout_test.go | 86 +++++++------------------------- src/net/udpsock_test.go | 20 ++------ src/net/unixsock_test.go | 15 ++---- src/net/unixsock_windows_test.go | 5 +- src/net/writev_test.go | 5 +- 20 files changed, 164 insertions(+), 389 deletions(-) diff --git a/src/net/conn_test.go b/src/net/conn_test.go index e3cb0c5ec7..3403eddfd3 100644 --- a/src/net/conn_test.go +++ b/src/net/conn_test.go @@ -26,10 +26,7 @@ func TestConnAndListener(t *testing.T) { continue } - ls, err := newLocalServer(network) - if err != nil { - t.Fatal(err) - } + ls := newLocalServer(t, network) defer ls.teardown() ch := make(chan error, 1) handler := func(ls *localServer, ln Listener) { ls.transponder(ln, ch) } diff --git a/src/net/dial_test.go b/src/net/dial_test.go index 36843870aa..e0c9cdc2ae 100644 --- a/src/net/dial_test.go +++ b/src/net/dial_test.go @@ -59,10 +59,7 @@ func TestProhibitionaryDialArg(t *testing.T) { } func TestDialLocal(t *testing.T) { - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") defer ln.Close() _, port, err := SplitHostPort(ln.Addr().String()) if err != nil { @@ -619,13 +616,9 @@ func TestDialerLocalAddr(t *testing.T) { c.Close() } } - var err error var lss [2]*localServer for i, network := range []string{"tcp4", "tcp6"} { - lss[i], err = newLocalServer(network) - if err != nil { - t.Fatal(err) - } + lss[i] = newLocalServer(t, network) defer lss[i].teardown() if err := lss[i].buildup(handler); err != nil { t.Fatal(err) @@ -725,10 +718,7 @@ func TestDialerKeepAlive(t *testing.T) { c.Close() } } - ls, err := newLocalServer("tcp") - if err != nil { - t.Fatal(err) - } + ls := newLocalServer(t, "tcp") defer ls.teardown() if err := ls.buildup(handler); err != nil { t.Fatal(err) @@ -826,10 +816,7 @@ func TestCancelAfterDial(t *testing.T) { t.Skip("avoiding time.Sleep") } - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") var wg sync.WaitGroup wg.Add(1) @@ -932,11 +919,7 @@ func TestDialerControl(t *testing.T) { if !testableNetwork(network) { continue } - ln, err := newLocalListener(network) - if err != nil { - t.Error(err) - continue - } + ln := newLocalListener(t, network) defer ln.Close() d := Dialer{Control: controlOnConnSetup} c, err := d.Dial(network, ln.Addr().String()) @@ -952,11 +935,7 @@ func TestDialerControl(t *testing.T) { if !testableNetwork(network) { continue } - c1, err := newLocalPacketListener(network) - if err != nil { - t.Error(err) - continue - } + c1 := newLocalPacketListener(t, network) if network == "unixgram" { defer os.Remove(c1.LocalAddr().String()) } @@ -992,10 +971,7 @@ func (contextWithNonZeroDeadline) Deadline() (time.Time, bool) { } func TestDialWithNonZeroDeadline(t *testing.T) { - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") defer ln.Close() _, port, err := SplitHostPort(ln.Addr().String()) if err != nil { diff --git a/src/net/dial_unix_test.go b/src/net/dial_unix_test.go index 64dca70eb8..4170367c4b 100644 --- a/src/net/dial_unix_test.go +++ b/src/net/dial_unix_test.go @@ -31,10 +31,7 @@ func TestDialContextCancelRace(t *testing.T) { testHookCanceledDial = oldTestHookCanceledDial }() - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") listenerDone := make(chan struct{}) go func() { defer close(listenerDone) diff --git a/src/net/error_test.go b/src/net/error_test.go index 30f8af3aee..4a191673e2 100644 --- a/src/net/error_test.go +++ b/src/net/error_test.go @@ -553,10 +553,7 @@ third: } func TestCloseError(t *testing.T) { - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") defer ln.Close() c, err := Dial(ln.Addr().Network(), ln.Addr().String()) if err != nil { @@ -664,10 +661,7 @@ func TestAcceptError(t *testing.T) { c.Close() } } - ls, err := newLocalServer("tcp") - if err != nil { - t.Fatal(err) - } + ls := newLocalServer(t, "tcp") if err := ls.buildup(handler); err != nil { ls.teardown() t.Fatal(err) @@ -773,10 +767,7 @@ func TestFileError(t *testing.T) { t.Error("should fail") } - ln, err = newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln = newLocalListener(t, "tcp") for i := 0; i < 3; i++ { f, err := ln.(*TCPListener).File() diff --git a/src/net/file_test.go b/src/net/file_test.go index e86c15fac7..ea2a218dfb 100644 --- a/src/net/file_test.go +++ b/src/net/file_test.go @@ -44,10 +44,7 @@ func TestFileConn(t *testing.T) { var network, address string switch tt.network { case "udp": - c, err := newLocalPacketListener(tt.network) - if err != nil { - t.Fatal(err) - } + c := newLocalPacketListener(t, tt.network) defer c.Close() network = c.LocalAddr().Network() address = c.LocalAddr().String() @@ -61,10 +58,7 @@ func TestFileConn(t *testing.T) { var b [1]byte c.Read(b[:]) } - ls, err := newLocalServer(tt.network) - if err != nil { - t.Fatal(err) - } + ls := newLocalServer(t, tt.network) defer ls.teardown() if err := ls.buildup(handler); err != nil { t.Fatal(err) @@ -148,17 +142,17 @@ func TestFileListener(t *testing.T) { continue } - ln1, err := newLocalListener(tt.network) - if err != nil { - t.Fatal(err) - } + ln1 := newLocalListener(t, tt.network) switch tt.network { case "unix", "unixpacket": defer os.Remove(ln1.Addr().String()) } addr := ln1.Addr() - var f *os.File + var ( + f *os.File + err error + ) switch ln1 := ln1.(type) { case *TCPListener: f, err = ln1.File() @@ -240,17 +234,17 @@ func TestFilePacketConn(t *testing.T) { continue } - c1, err := newLocalPacketListener(tt.network) - if err != nil { - t.Fatal(err) - } + c1 := newLocalPacketListener(t, tt.network) switch tt.network { case "unixgram": defer os.Remove(c1.LocalAddr().String()) } addr := c1.LocalAddr() - var f *os.File + var ( + f *os.File + err error + ) switch c1 := c1.(type) { case *UDPConn: f, err = c1.File() @@ -314,10 +308,7 @@ func TestFileCloseRace(t *testing.T) { c.Read(b[:]) } - ls, err := newLocalServer("tcp") - if err != nil { - t.Fatal(err) - } + ls := newLocalServer(t, "tcp") defer ls.teardown() if err := ls.buildup(handler); err != nil { t.Fatal(err) diff --git a/src/net/listen_test.go b/src/net/listen_test.go index 7aaebe8fa1..09ffbb31a1 100644 --- a/src/net/listen_test.go +++ b/src/net/listen_test.go @@ -697,10 +697,7 @@ func multicastRIBContains(ip IP) (bool, error) { // Issue 21856. func TestClosingListener(t *testing.T) { - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") addr := ln.Addr() go func() { @@ -738,15 +735,13 @@ func TestListenConfigControl(t *testing.T) { if !testableNetwork(network) { continue } - ln, err := newLocalListener(network) - if err != nil { - t.Error(err) - continue - } + ln := newLocalListener(t, network) address := ln.Addr().String() + // TODO: This is racy. The selected address could be reused in between + // this Close and the subsequent Listen. ln.Close() lc := ListenConfig{Control: controlOnConnSetup} - ln, err = lc.Listen(context.Background(), network, address) + ln, err := lc.Listen(context.Background(), network, address) if err != nil { t.Error(err) continue @@ -759,18 +754,16 @@ func TestListenConfigControl(t *testing.T) { if !testableNetwork(network) { continue } - c, err := newLocalPacketListener(network) - if err != nil { - t.Error(err) - continue - } + c := newLocalPacketListener(t, network) address := c.LocalAddr().String() + // TODO: This is racy. The selected address could be reused in between + // this Close and the subsequent ListenPacket. c.Close() if network == "unixgram" { os.Remove(address) } lc := ListenConfig{Control: controlOnConnSetup} - c, err = lc.ListenPacket(context.Background(), network, address) + c, err := lc.ListenPacket(context.Background(), network, address) if err != nil { t.Error(err) continue diff --git a/src/net/mockserver_test.go b/src/net/mockserver_test.go index 70ecc69f66..0868871b7b 100644 --- a/src/net/mockserver_test.go +++ b/src/net/mockserver_test.go @@ -11,6 +11,7 @@ import ( "fmt" "os" "sync" + "testing" "time" ) @@ -26,29 +27,44 @@ func testUnixAddr() string { return addr } -func newLocalListener(network string) (Listener, error) { +func newLocalListener(t testing.TB, network string) Listener { + listen := func(net, addr string) Listener { + ln, err := Listen(net, addr) + if err != nil { + t.Helper() + t.Fatal(err) + } + return ln + } + switch network { case "tcp": if supportsIPv4() { + if !supportsIPv6() { + return listen("tcp4", "127.0.0.1:0") + } if ln, err := Listen("tcp4", "127.0.0.1:0"); err == nil { - return ln, nil + return ln } } if supportsIPv6() { - return Listen("tcp6", "[::1]:0") + return listen("tcp6", "[::1]:0") } case "tcp4": if supportsIPv4() { - return Listen("tcp4", "127.0.0.1:0") + return listen("tcp4", "127.0.0.1:0") } case "tcp6": if supportsIPv6() { - return Listen("tcp6", "[::1]:0") + return listen("tcp6", "[::1]:0") } case "unix", "unixpacket": - return Listen(network, testUnixAddr()) + return listen(network, testUnixAddr()) } - return nil, fmt.Errorf("%s is not supported", network) + + t.Helper() + t.Fatalf("%s is not supported", network) + return nil } func newDualStackListener() (lns []*TCPListener, err error) { @@ -119,12 +135,10 @@ func (ls *localServer) teardown() error { return nil } -func newLocalServer(network string) (*localServer, error) { - ln, err := newLocalListener(network) - if err != nil { - return nil, err - } - return &localServer{Listener: ln, done: make(chan bool)}, nil +func newLocalServer(t testing.TB, network string) *localServer { + t.Helper() + ln := newLocalListener(t, network) + return &localServer{Listener: ln, done: make(chan bool)} } type streamListener struct { @@ -133,8 +147,8 @@ type streamListener struct { done chan bool // signal that indicates server stopped } -func (sl *streamListener) newLocalServer() (*localServer, error) { - return &localServer{Listener: sl.Listener, done: make(chan bool)}, nil +func (sl *streamListener) newLocalServer() *localServer { + return &localServer{Listener: sl.Listener, done: make(chan bool)} } type dualStackServer struct { @@ -286,27 +300,39 @@ func transceiver(c Conn, wb []byte, ch chan<- error) { } } -func newLocalPacketListener(network string) (PacketConn, error) { +func newLocalPacketListener(t testing.TB, network string) PacketConn { + listenPacket := func(net, addr string) PacketConn { + c, err := ListenPacket(net, addr) + if err != nil { + t.Helper() + t.Fatal(err) + } + return c + } + switch network { case "udp": if supportsIPv4() { - return ListenPacket("udp4", "127.0.0.1:0") + return listenPacket("udp4", "127.0.0.1:0") } if supportsIPv6() { - return ListenPacket("udp6", "[::1]:0") + return listenPacket("udp6", "[::1]:0") } case "udp4": if supportsIPv4() { - return ListenPacket("udp4", "127.0.0.1:0") + return listenPacket("udp4", "127.0.0.1:0") } case "udp6": if supportsIPv6() { - return ListenPacket("udp6", "[::1]:0") + return listenPacket("udp6", "[::1]:0") } case "unixgram": - return ListenPacket(network, testUnixAddr()) + return listenPacket(network, testUnixAddr()) } - return nil, fmt.Errorf("%s is not supported", network) + + t.Helper() + t.Fatalf("%s is not supported", network) + return nil } func newDualStackPacketListener() (cs []*UDPConn, err error) { @@ -371,20 +397,18 @@ func (ls *localPacketServer) teardown() error { return nil } -func newLocalPacketServer(network string) (*localPacketServer, error) { - c, err := newLocalPacketListener(network) - if err != nil { - return nil, err - } - return &localPacketServer{PacketConn: c, done: make(chan bool)}, nil +func newLocalPacketServer(t testing.TB, network string) *localPacketServer { + t.Helper() + c := newLocalPacketListener(t, network) + return &localPacketServer{PacketConn: c, done: make(chan bool)} } type packetListener struct { PacketConn } -func (pl *packetListener) newLocalServer() (*localPacketServer, error) { - return &localPacketServer{PacketConn: pl.PacketConn, done: make(chan bool)}, nil +func (pl *packetListener) newLocalServer() *localPacketServer { + return &localPacketServer{PacketConn: pl.PacketConn, done: make(chan bool)} } func packetTransponder(c PacketConn, ch chan<- error) { diff --git a/src/net/net_test.go b/src/net/net_test.go index 5d9c3c67e6..7b169916f1 100644 --- a/src/net/net_test.go +++ b/src/net/net_test.go @@ -33,10 +33,7 @@ func TestCloseRead(t *testing.T) { } t.Parallel() - ln, err := newLocalListener(network) - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, network) switch network { case "unix", "unixpacket": defer os.Remove(ln.Addr().String()) @@ -132,10 +129,7 @@ func TestCloseWrite(t *testing.T) { } } - ls, err := newLocalServer(network) - if err != nil { - t.Fatal(err) - } + ls := newLocalServer(t, network) defer ls.teardown() if err := ls.buildup(handler); err != nil { t.Fatal(err) @@ -189,10 +183,7 @@ func TestConnClose(t *testing.T) { } t.Parallel() - ln, err := newLocalListener(network) - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, network) switch network { case "unix", "unixpacket": defer os.Remove(ln.Addr().String()) @@ -234,10 +225,7 @@ func TestListenerClose(t *testing.T) { } t.Parallel() - ln, err := newLocalListener(network) - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, network) switch network { case "unix", "unixpacket": defer os.Remove(ln.Addr().String()) @@ -275,10 +263,7 @@ func TestPacketConnClose(t *testing.T) { } t.Parallel() - c, err := newLocalPacketListener(network) - if err != nil { - t.Fatal(err) - } + c := newLocalPacketListener(t, network) switch network { case "unixgram": defer os.Remove(c.LocalAddr().String()) @@ -303,18 +288,17 @@ func TestPacketConnClose(t *testing.T) { func TestListenCloseListen(t *testing.T) { const maxTries = 10 for tries := 0; tries < maxTries; tries++ { - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") addr := ln.Addr().String() + // TODO: This is racy. The selected address could be reused in between this + // Close and the subsequent Listen. if err := ln.Close(); err != nil { if perr := parseCloseError(err, false); perr != nil { t.Error(perr) } t.Fatal(err) } - ln, err = Listen("tcp", addr) + ln, err := Listen("tcp", addr) if err == nil { // Success. (This test didn't always make it here earlier.) ln.Close() @@ -360,10 +344,7 @@ func TestAcceptIgnoreAbortedConnRequest(t *testing.T) { } c.Close() } - ls, err := newLocalServer("tcp") - if err != nil { - t.Fatal(err) - } + ls := newLocalServer(t, "tcp") defer ls.teardown() if err := ls.buildup(handler); err != nil { t.Fatal(err) @@ -390,10 +371,7 @@ func TestZeroByteRead(t *testing.T) { } t.Parallel() - ln, err := newLocalListener(network) - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, network) connc := make(chan Conn, 1) go func() { defer ln.Close() @@ -442,10 +420,7 @@ func TestZeroByteRead(t *testing.T) { // runs peer1 and peer2 concurrently. withTCPConnPair returns when // both have completed. func withTCPConnPair(t *testing.T, peer1, peer2 func(c *TCPConn) error) { - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") defer ln.Close() errc := make(chan error, 2) go func() { diff --git a/src/net/protoconn_test.go b/src/net/protoconn_test.go index 9f7d8ee4ef..baf3ac6679 100644 --- a/src/net/protoconn_test.go +++ b/src/net/protoconn_test.go @@ -73,10 +73,7 @@ func TestTCPConnSpecificMethods(t *testing.T) { } ch := make(chan error, 1) handler := func(ls *localServer, ln Listener) { ls.transponder(ls.Listener, ch) } - ls, err := (&streamListener{Listener: ln}).newLocalServer() - if err != nil { - t.Fatal(err) - } + ls := (&streamListener{Listener: ln}).newLocalServer() defer ls.teardown() if err := ls.buildup(handler); err != nil { t.Fatal(err) diff --git a/src/net/rawconn_test.go b/src/net/rawconn_test.go index 645d82a1a6..d1ef79d715 100644 --- a/src/net/rawconn_test.go +++ b/src/net/rawconn_test.go @@ -64,10 +64,7 @@ func TestRawConnReadWrite(t *testing.T) { return } } - ls, err := newLocalServer("tcp") - if err != nil { - t.Fatal(err) - } + ls := newLocalServer(t, "tcp") defer ls.teardown() if err := ls.buildup(handler); err != nil { t.Fatal(err) @@ -102,10 +99,7 @@ func TestRawConnReadWrite(t *testing.T) { t.Skipf("not supported on %s", runtime.GOOS) } - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") defer ln.Close() c, err := Dial(ln.Addr().Network(), ln.Addr().String()) @@ -180,10 +174,7 @@ func TestRawConnControl(t *testing.T) { } t.Run("TCP", func(t *testing.T) { - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") defer ln.Close() cc1, err := ln.(*TCPListener).SyscallConn() diff --git a/src/net/sendfile_test.go b/src/net/sendfile_test.go index 492333d0c8..6edfb67dd7 100644 --- a/src/net/sendfile_test.go +++ b/src/net/sendfile_test.go @@ -27,10 +27,7 @@ const ( ) func TestSendfile(t *testing.T) { - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") defer ln.Close() errc := make(chan error, 1) @@ -97,10 +94,7 @@ func TestSendfile(t *testing.T) { } func TestSendfileParts(t *testing.T) { - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") defer ln.Close() errc := make(chan error, 1) @@ -155,10 +149,7 @@ func TestSendfileParts(t *testing.T) { } func TestSendfileSeeked(t *testing.T) { - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") defer ln.Close() const seekTo = 65 << 10 @@ -225,10 +216,7 @@ func TestSendfilePipe(t *testing.T) { t.Parallel() - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") defer ln.Close() r, w, err := os.Pipe() @@ -317,10 +305,7 @@ func TestSendfilePipe(t *testing.T) { // Issue 43822: tests that returns EOF when conn write timeout. func TestSendfileOnWriteTimeoutExceeded(t *testing.T) { - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") defer ln.Close() errc := make(chan error, 1) diff --git a/src/net/server_test.go b/src/net/server_test.go index ae1c1619ed..be12c1a12d 100644 --- a/src/net/server_test.go +++ b/src/net/server_test.go @@ -77,10 +77,7 @@ func TestTCPServer(t *testing.T) { } }() for i := 0; i < N; i++ { - ls, err := (&streamListener{Listener: ln}).newLocalServer() - if err != nil { - t.Fatal(err) - } + ls := (&streamListener{Listener: ln}).newLocalServer() lss = append(lss, ls) tpchs = append(tpchs, make(chan error, 1)) } @@ -162,10 +159,7 @@ func TestUnixAndUnixpacketServer(t *testing.T) { } }() for i := 0; i < N; i++ { - ls, err := (&streamListener{Listener: ln}).newLocalServer() - if err != nil { - t.Fatal(err) - } + ls := (&streamListener{Listener: ln}).newLocalServer() lss = append(lss, ls) tpchs = append(tpchs, make(chan error, 1)) } @@ -270,10 +264,7 @@ func TestUDPServer(t *testing.T) { t.Fatal(err) } - ls, err := (&packetListener{PacketConn: c1}).newLocalServer() - if err != nil { - t.Fatal(err) - } + ls := (&packetListener{PacketConn: c1}).newLocalServer() defer ls.teardown() tpch := make(chan error, 1) handler := func(ls *localPacketServer, c PacketConn) { packetTransponder(c, tpch) } @@ -348,10 +339,7 @@ func TestUnixgramServer(t *testing.T) { t.Fatal(err) } - ls, err := (&packetListener{PacketConn: c1}).newLocalServer() - if err != nil { - t.Fatal(err) - } + ls := (&packetListener{PacketConn: c1}).newLocalServer() defer ls.teardown() tpch := make(chan error, 1) handler := func(ls *localPacketServer, c PacketConn) { packetTransponder(c, tpch) } diff --git a/src/net/splice_test.go b/src/net/splice_test.go index 43e0b926f7..38d51451b6 100644 --- a/src/net/splice_test.go +++ b/src/net/splice_test.go @@ -46,20 +46,14 @@ type spliceTestCase struct { } func (tc spliceTestCase) test(t *testing.T) { - clientUp, serverUp, err := spliceTestSocketPair(tc.upNet) - if err != nil { - t.Fatal(err) - } + clientUp, serverUp := spliceTestSocketPair(t, tc.upNet) defer serverUp.Close() cleanup, err := startSpliceClient(clientUp, "w", tc.chunkSize, tc.totalSize) if err != nil { t.Fatal(err) } defer cleanup() - clientDown, serverDown, err := spliceTestSocketPair(tc.downNet) - if err != nil { - t.Fatal(err) - } + clientDown, serverDown := spliceTestSocketPair(t, tc.downNet) defer serverDown.Close() cleanup, err = startSpliceClient(clientDown, "r", tc.chunkSize, tc.totalSize) if err != nil { @@ -103,15 +97,9 @@ func (tc spliceTestCase) test(t *testing.T) { } func testSpliceReaderAtEOF(t *testing.T, upNet, downNet string) { - clientUp, serverUp, err := spliceTestSocketPair(upNet) - if err != nil { - t.Fatal(err) - } + clientUp, serverUp := spliceTestSocketPair(t, upNet) defer clientUp.Close() - clientDown, serverDown, err := spliceTestSocketPair(downNet) - if err != nil { - t.Fatal(err) - } + clientDown, serverDown := spliceTestSocketPair(t, downNet) defer clientDown.Close() serverUp.Close() @@ -140,7 +128,7 @@ func testSpliceReaderAtEOF(t *testing.T, upNet, downNet string) { }() buf := make([]byte, 3) - _, err = io.ReadFull(clientDown, buf) + _, err := io.ReadFull(clientDown, buf) if err != nil { t.Errorf("clientDown: %v", err) } @@ -150,15 +138,9 @@ func testSpliceReaderAtEOF(t *testing.T, upNet, downNet string) { } func testSpliceIssue25985(t *testing.T, upNet, downNet string) { - front, err := newLocalListener(upNet) - if err != nil { - t.Fatal(err) - } + front := newLocalListener(t, upNet) defer front.Close() - back, err := newLocalListener(downNet) - if err != nil { - t.Fatal(err) - } + back := newLocalListener(t, downNet) defer back.Close() var wg sync.WaitGroup @@ -210,16 +192,10 @@ func testSpliceIssue25985(t *testing.T, upNet, downNet string) { } func testSpliceNoUnixpacket(t *testing.T) { - clientUp, serverUp, err := spliceTestSocketPair("unixpacket") - if err != nil { - t.Fatal(err) - } + clientUp, serverUp := spliceTestSocketPair(t, "unixpacket") defer clientUp.Close() defer serverUp.Close() - clientDown, serverDown, err := spliceTestSocketPair("tcp") - if err != nil { - t.Fatal(err) - } + clientDown, serverDown := spliceTestSocketPair(t, "tcp") defer clientDown.Close() defer serverDown.Close() // If splice called poll.Splice here, we'd get err == syscall.EINVAL @@ -247,10 +223,7 @@ func testSpliceNoUnixgram(t *testing.T) { t.Fatal(err) } defer up.Close() - clientDown, serverDown, err := spliceTestSocketPair("tcp") - if err != nil { - t.Fatal(err) - } + clientDown, serverDown := spliceTestSocketPair(t, "tcp") defer clientDown.Close() defer serverDown.Close() // Analogous to testSpliceNoUnixpacket. @@ -284,10 +257,7 @@ func (tc spliceTestCase) bench(b *testing.B) { // To benchmark the genericReadFrom code path, set this to false. useSplice := true - clientUp, serverUp, err := spliceTestSocketPair(tc.upNet) - if err != nil { - b.Fatal(err) - } + clientUp, serverUp := spliceTestSocketPair(b, tc.upNet) defer serverUp.Close() cleanup, err := startSpliceClient(clientUp, "w", tc.chunkSize, tc.chunkSize*b.N) @@ -296,10 +266,7 @@ func (tc spliceTestCase) bench(b *testing.B) { } defer cleanup() - clientDown, serverDown, err := spliceTestSocketPair(tc.downNet) - if err != nil { - b.Fatal(err) - } + clientDown, serverDown := spliceTestSocketPair(b, tc.downNet) defer serverDown.Close() cleanup, err = startSpliceClient(clientDown, "r", tc.chunkSize, tc.chunkSize*b.N) @@ -327,11 +294,9 @@ func (tc spliceTestCase) bench(b *testing.B) { } } -func spliceTestSocketPair(net string) (client, server Conn, err error) { - ln, err := newLocalListener(net) - if err != nil { - return nil, nil, err - } +func spliceTestSocketPair(t testing.TB, net string) (client, server Conn) { + t.Helper() + ln := newLocalListener(t, net) defer ln.Close() var cerr, serr error acceptDone := make(chan struct{}) @@ -345,15 +310,15 @@ func spliceTestSocketPair(net string) (client, server Conn, err error) { if server != nil { server.Close() } - return nil, nil, cerr + t.Fatal(cerr) } if serr != nil { if client != nil { client.Close() } - return nil, nil, serr + t.Fatal(serr) } - return client, server, nil + return client, server } func startSpliceClient(conn Conn, op string, chunkSize, totalSize int) (func(), error) { diff --git a/src/net/tcpsock_test.go b/src/net/tcpsock_test.go index fdf5c330a9..ae65788a73 100644 --- a/src/net/tcpsock_test.go +++ b/src/net/tcpsock_test.go @@ -387,10 +387,7 @@ func TestIPv6LinkLocalUnicastTCP(t *testing.T) { t.Log(err) continue } - ls, err := (&streamListener{Listener: ln}).newLocalServer() - if err != nil { - t.Fatal(err) - } + ls := (&streamListener{Listener: ln}).newLocalServer() defer ls.teardown() ch := make(chan error, 1) handler := func(ls *localServer, ln Listener) { ls.transponder(ln, ch) } @@ -626,10 +623,7 @@ func TestTCPSelfConnect(t *testing.T) { t.Skip("known-broken test on windows") } - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") var d Dialer c, err := d.Dial(ln.Addr().Network(), ln.Addr().String()) if err != nil { @@ -676,10 +670,7 @@ func TestTCPBig(t *testing.T) { for _, writev := range []bool{false, true} { t.Run(fmt.Sprintf("writev=%v", writev), func(t *testing.T) { - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") defer ln.Close() x := int(1 << 30) @@ -723,10 +714,7 @@ func TestTCPBig(t *testing.T) { } func TestCopyPipeIntoTCP(t *testing.T) { - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") defer ln.Close() errc := make(chan error, 1) @@ -794,10 +782,7 @@ func TestCopyPipeIntoTCP(t *testing.T) { } func BenchmarkSetReadDeadline(b *testing.B) { - ln, err := newLocalListener("tcp") - if err != nil { - b.Fatal(err) - } + ln := newLocalListener(b, "tcp") defer ln.Close() var serv Conn done := make(chan error) diff --git a/src/net/tcpsock_unix_test.go b/src/net/tcpsock_unix_test.go index b1f2876d4e..b14670bc67 100644 --- a/src/net/tcpsock_unix_test.go +++ b/src/net/tcpsock_unix_test.go @@ -22,10 +22,7 @@ func TestTCPSpuriousConnSetupCompletion(t *testing.T) { t.Skip("skipping in short mode") } - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") var wg sync.WaitGroup wg.Add(1) go func(ln Listener) { diff --git a/src/net/timeout_test.go b/src/net/timeout_test.go index 515aa07ec3..cd6b953747 100644 --- a/src/net/timeout_test.go +++ b/src/net/timeout_test.go @@ -93,10 +93,7 @@ func TestDialTimeout(t *testing.T) { } func TestDialTimeoutMaxDuration(t *testing.T) { - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") defer func() { if err := ln.Close(); err != nil { t.Error(err) @@ -147,10 +144,7 @@ func TestAcceptTimeout(t *testing.T) { t.Skipf("not supported on %s", runtime.GOOS) } - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") defer ln.Close() var wg sync.WaitGroup @@ -203,10 +197,7 @@ func TestAcceptTimeoutMustReturn(t *testing.T) { t.Skipf("not supported on %s", runtime.GOOS) } - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") defer ln.Close() max := time.NewTimer(time.Second) @@ -249,10 +240,7 @@ func TestAcceptTimeoutMustNotReturn(t *testing.T) { t.Skipf("not supported on %s", runtime.GOOS) } - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") defer ln.Close() max := time.NewTimer(100 * time.Millisecond) @@ -302,10 +290,7 @@ func TestReadTimeout(t *testing.T) { c.Write([]byte("READ TIMEOUT TEST")) defer c.Close() } - ls, err := newLocalServer("tcp") - if err != nil { - t.Fatal(err) - } + ls := newLocalServer(t, "tcp") defer ls.teardown() if err := ls.buildup(handler); err != nil { t.Fatal(err) @@ -354,10 +339,7 @@ func TestReadTimeoutMustNotReturn(t *testing.T) { t.Skipf("not supported on %s", runtime.GOOS) } - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") defer ln.Close() c, err := Dial(ln.Addr().Network(), ln.Addr().String()) @@ -421,10 +403,7 @@ func TestReadFromTimeout(t *testing.T) { c.WriteTo([]byte("READFROM TIMEOUT TEST"), dst) } } - ls, err := newLocalPacketServer("udp") - if err != nil { - t.Fatal(err) - } + ls := newLocalPacketServer(t, "udp") defer ls.teardown() if err := ls.buildup(handler); err != nil { t.Fatal(err) @@ -484,10 +463,7 @@ var writeTimeoutTests = []struct { func TestWriteTimeout(t *testing.T) { t.Parallel() - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") defer ln.Close() for i, tt := range writeTimeoutTests { @@ -532,10 +508,7 @@ func TestWriteTimeoutMustNotReturn(t *testing.T) { t.Skipf("not supported on %s", runtime.GOOS) } - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") defer ln.Close() c, err := Dial(ln.Addr().Network(), ln.Addr().String()) @@ -598,10 +571,7 @@ var writeToTimeoutTests = []struct { func TestWriteToTimeout(t *testing.T) { t.Parallel() - c1, err := newLocalPacketListener("udp") - if err != nil { - t.Fatal(err) - } + c1 := newLocalPacketListener(t, "udp") defer c1.Close() host, _, err := SplitHostPort(c1.LocalAddr().String()) @@ -687,10 +657,7 @@ func nextTimeout(actual time.Duration) (next time.Duration, ok bool) { } func TestReadTimeoutFluctuation(t *testing.T) { - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") defer ln.Close() c, err := Dial(ln.Addr().Network(), ln.Addr().String()) @@ -746,10 +713,7 @@ func TestReadTimeoutFluctuation(t *testing.T) { } func TestReadFromTimeoutFluctuation(t *testing.T) { - c1, err := newLocalPacketListener("udp") - if err != nil { - t.Fatal(err) - } + c1 := newLocalPacketListener(t, "udp") defer c1.Close() c2, err := Dial(c1.LocalAddr().Network(), c1.LocalAddr().String()) @@ -810,10 +774,7 @@ func TestWriteTimeoutFluctuation(t *testing.T) { t.Skipf("not supported on %s", runtime.GOOS) } - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") defer ln.Close() c, err := Dial(ln.Addr().Network(), ln.Addr().String()) @@ -938,10 +899,7 @@ func testVariousDeadlines(t *testing.T) { c.Close() } } - ls, err := newLocalServer("tcp") - if err != nil { - t.Fatal(err) - } + ls := newLocalServer(t, "tcp") defer ls.teardown() if err := ls.buildup(handler); err != nil { t.Fatal(err) @@ -1073,10 +1031,7 @@ func TestReadWriteProlongedTimeout(t *testing.T) { }() wg.Wait() } - ls, err := newLocalServer("tcp") - if err != nil { - t.Fatal(err) - } + ls := newLocalServer(t, "tcp") defer ls.teardown() if err := ls.buildup(handler); err != nil { t.Fatal(err) @@ -1103,10 +1058,7 @@ func TestReadWriteDeadlineRace(t *testing.T) { N = 50 } - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") defer ln.Close() c, err := Dial(ln.Addr().Network(), ln.Addr().String()) @@ -1156,10 +1108,7 @@ func TestReadWriteDeadlineRace(t *testing.T) { // Issue 35367. func TestConcurrentSetDeadline(t *testing.T) { - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") defer ln.Close() const goroutines = 8 @@ -1168,6 +1117,7 @@ func TestConcurrentSetDeadline(t *testing.T) { var c [conns]Conn for i := 0; i < conns; i++ { + var err error c[i], err = Dial(ln.Addr().Network(), ln.Addr().String()) if err != nil { t.Fatal(err) diff --git a/src/net/udpsock_test.go b/src/net/udpsock_test.go index 8ccdb365ab..6f82554e56 100644 --- a/src/net/udpsock_test.go +++ b/src/net/udpsock_test.go @@ -285,10 +285,7 @@ func TestIPv6LinkLocalUnicastUDP(t *testing.T) { t.Log(err) continue } - ls, err := (&packetListener{PacketConn: c1}).newLocalServer() - if err != nil { - t.Fatal(err) - } + ls := (&packetListener{PacketConn: c1}).newLocalServer() defer ls.teardown() ch := make(chan error, 1) handler := func(ls *localPacketServer, c PacketConn) { packetTransponder(c, ch) } @@ -333,10 +330,7 @@ func TestUDPZeroBytePayload(t *testing.T) { testenv.SkipFlaky(t, 29225) } - c, err := newLocalPacketListener("udp") - if err != nil { - t.Fatal(err) - } + c := newLocalPacketListener(t, "udp") defer c.Close() for _, genericRead := range []bool{false, true} { @@ -369,10 +363,7 @@ func TestUDPZeroByteBuffer(t *testing.T) { t.Skipf("not supported on %s", runtime.GOOS) } - c, err := newLocalPacketListener("udp") - if err != nil { - t.Fatal(err) - } + c := newLocalPacketListener(t, "udp") defer c.Close() b := []byte("UDP ZERO BYTE BUFFER TEST") @@ -406,10 +397,7 @@ func TestUDPReadSizeError(t *testing.T) { t.Skipf("not supported on %s", runtime.GOOS) } - c1, err := newLocalPacketListener("udp") - if err != nil { - t.Fatal(err) - } + c1 := newLocalPacketListener(t, "udp") defer c1.Close() c2, err := Dial("udp", c1.LocalAddr().String()) diff --git a/src/net/unixsock_test.go b/src/net/unixsock_test.go index a75578235f..5ad20a0151 100644 --- a/src/net/unixsock_test.go +++ b/src/net/unixsock_test.go @@ -76,10 +76,7 @@ func TestUnixgramZeroBytePayload(t *testing.T) { t.Skip("unixgram test") } - c1, err := newLocalPacketListener("unixgram") - if err != nil { - t.Fatal(err) - } + c1 := newLocalPacketListener(t, "unixgram") defer os.Remove(c1.LocalAddr().String()) defer c1.Close() @@ -126,10 +123,7 @@ func TestUnixgramZeroByteBuffer(t *testing.T) { // issue 4352: Recvfrom failed with "address family not // supported by protocol family" if zero-length buffer provided - c1, err := newLocalPacketListener("unixgram") - if err != nil { - t.Fatal(err) - } + c1 := newLocalPacketListener(t, "unixgram") defer os.Remove(c1.LocalAddr().String()) defer c1.Close() @@ -259,10 +253,7 @@ func TestUnixConnLocalAndRemoteNames(t *testing.T) { if err != nil { t.Fatal(err) } - ls, err := (&streamListener{Listener: ln}).newLocalServer() - if err != nil { - t.Fatal(err) - } + ls := (&streamListener{Listener: ln}).newLocalServer() defer ls.teardown() if err := ls.buildup(handler); err != nil { t.Fatal(err) diff --git a/src/net/unixsock_windows_test.go b/src/net/unixsock_windows_test.go index dedd761c56..e847a20de0 100644 --- a/src/net/unixsock_windows_test.go +++ b/src/net/unixsock_windows_test.go @@ -56,10 +56,7 @@ func TestUnixConnLocalWindows(t *testing.T) { if err != nil { t.Fatal(err) } - ls, err := (&streamListener{Listener: ln}).newLocalServer() - if err != nil { - t.Fatal(err) - } + ls := (&streamListener{Listener: ln}).newLocalServer() defer ls.teardown() if err := ls.buildup(handler); err != nil { t.Fatal(err) diff --git a/src/net/writev_test.go b/src/net/writev_test.go index b752295862..18795a457a 100644 --- a/src/net/writev_test.go +++ b/src/net/writev_test.go @@ -186,10 +186,7 @@ func TestWritevError(t *testing.T) { t.Skipf("skipping the test: windows does not have problem sending large chunks of data") } - ln, err := newLocalListener("tcp") - if err != nil { - t.Fatal(err) - } + ln := newLocalListener(t, "tcp") defer ln.Close() ch := make(chan Conn, 1) -- GitLab From 4b3d8d1a390a51ea6a1b3f66ef9d56ef7203bbe7 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 9 Dec 2021 11:55:20 -0500 Subject: [PATCH 2486/2500] net: create unix sockets in unique directories MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change applies the same transformation as in CL 366774, but to the net package. testUnixAddr was using os.CreateTemp to obtain a unique socket path, but then calling os.Remove on that path immediately. Since the existence of the file is what guarantees its uniqueness, that could occasionally result in testUnixAddr returning the same path for two calls, causing the tests using those paths to fail — especially if they are the same test or are run in parallel. Instead, we now create a unique, short temp directory for each call, and use a path within that directory for the socket address. For #34611 Change-Id: I8e13b606abce2479a0305f7aeecf5d54c449a032 Reviewed-on: https://go-review.googlesource.com/c/go/+/370694 Trust: Bryan Mills Reviewed-by: Ian Lance Taylor Run-TryBot: Bryan Mills TryBot-Result: Gopher Robot --- src/net/mockserver_test.go | 26 ++++++++++++-------- src/net/packetconn_test.go | 27 +++++++++++++------- src/net/protoconn_test.go | 4 +-- src/net/server_test.go | 42 ++++++++++++++++---------------- src/net/splice_test.go | 2 +- src/net/unixsock_test.go | 16 ++++++------ src/net/unixsock_windows_test.go | 4 +-- 7 files changed, 68 insertions(+), 53 deletions(-) diff --git a/src/net/mockserver_test.go b/src/net/mockserver_test.go index 0868871b7b..186bd330b2 100644 --- a/src/net/mockserver_test.go +++ b/src/net/mockserver_test.go @@ -10,21 +10,27 @@ import ( "errors" "fmt" "os" + "path/filepath" "sync" "testing" "time" ) -// testUnixAddr uses os.CreateTemp to get a name that is unique. -func testUnixAddr() string { - f, err := os.CreateTemp("", "go-nettest") +// testUnixAddr uses os.MkdirTemp to get a name that is unique. +func testUnixAddr(t testing.TB) string { + // Pass an empty pattern to get a directory name that is as short as possible. + // If we end up with a name longer than the sun_path field in the sockaddr_un + // struct, we won't be able to make the syscall to open the socket. + d, err := os.MkdirTemp("", "") if err != nil { - panic(err) + t.Fatal(err) } - addr := f.Name() - f.Close() - os.Remove(addr) - return addr + t.Cleanup(func() { + if err := os.RemoveAll(d); err != nil { + t.Error(err) + } + }) + return filepath.Join(d, "sock") } func newLocalListener(t testing.TB, network string) Listener { @@ -59,7 +65,7 @@ func newLocalListener(t testing.TB, network string) Listener { return listen("tcp6", "[::1]:0") } case "unix", "unixpacket": - return listen(network, testUnixAddr()) + return listen(network, testUnixAddr(t)) } t.Helper() @@ -327,7 +333,7 @@ func newLocalPacketListener(t testing.TB, network string) PacketConn { return listenPacket("udp6", "[::1]:0") } case "unixgram": - return listenPacket(network, testUnixAddr()) + return listenPacket(network, testUnixAddr(t)) } t.Helper() diff --git a/src/net/packetconn_test.go b/src/net/packetconn_test.go index 487912efab..fa160df5f5 100644 --- a/src/net/packetconn_test.go +++ b/src/net/packetconn_test.go @@ -27,16 +27,16 @@ func packetConnTestData(t *testing.T, network string) ([]byte, func()) { return []byte("PACKETCONN TEST"), nil } -var packetConnTests = []struct { - net string - addr1 string - addr2 string -}{ - {"udp", "127.0.0.1:0", "127.0.0.1:0"}, - {"unixgram", testUnixAddr(), testUnixAddr()}, -} - func TestPacketConn(t *testing.T) { + var packetConnTests = []struct { + net string + addr1 string + addr2 string + }{ + {"udp", "127.0.0.1:0", "127.0.0.1:0"}, + {"unixgram", testUnixAddr(t), testUnixAddr(t)}, + } + closer := func(c PacketConn, net, addr1, addr2 string) { c.Close() switch net { @@ -85,6 +85,15 @@ func TestPacketConn(t *testing.T) { } func TestConnAndPacketConn(t *testing.T) { + var packetConnTests = []struct { + net string + addr1 string + addr2 string + }{ + {"udp", "127.0.0.1:0", "127.0.0.1:0"}, + {"unixgram", testUnixAddr(t), testUnixAddr(t)}, + } + closer := func(c PacketConn, net, addr1, addr2 string) { c.Close() switch net { diff --git a/src/net/protoconn_test.go b/src/net/protoconn_test.go index baf3ac6679..e4198a3a05 100644 --- a/src/net/protoconn_test.go +++ b/src/net/protoconn_test.go @@ -204,7 +204,7 @@ func TestUnixListenerSpecificMethods(t *testing.T) { t.Skip("unix test") } - addr := testUnixAddr() + addr := testUnixAddr(t) la, err := ResolveUnixAddr("unix", addr) if err != nil { t.Fatal(err) @@ -245,7 +245,7 @@ func TestUnixConnSpecificMethods(t *testing.T) { t.Skip("unixgram test") } - addr1, addr2, addr3 := testUnixAddr(), testUnixAddr(), testUnixAddr() + addr1, addr2, addr3 := testUnixAddr(t), testUnixAddr(t), testUnixAddr(t) a1, err := ResolveUnixAddr("unixgram", addr1) if err != nil { diff --git a/src/net/server_test.go b/src/net/server_test.go index be12c1a12d..6796d7993e 100644 --- a/src/net/server_test.go +++ b/src/net/server_test.go @@ -122,19 +122,19 @@ func TestTCPServer(t *testing.T) { } } -var unixAndUnixpacketServerTests = []struct { - network, address string -}{ - {"unix", testUnixAddr()}, - {"unix", "@nettest/go/unix"}, - - {"unixpacket", testUnixAddr()}, - {"unixpacket", "@nettest/go/unixpacket"}, -} - // TestUnixAndUnixpacketServer tests concurrent accept-read-write // servers func TestUnixAndUnixpacketServer(t *testing.T) { + var unixAndUnixpacketServerTests = []struct { + network, address string + }{ + {"unix", testUnixAddr(t)}, + {"unix", "@nettest/go/unix"}, + + {"unixpacket", testUnixAddr(t)}, + {"unixpacket", "@nettest/go/unixpacket"}, + } + const N = 3 for i, tt := range unixAndUnixpacketServerTests { @@ -313,18 +313,18 @@ func TestUDPServer(t *testing.T) { } } -var unixgramServerTests = []struct { - saddr string // server endpoint - caddr string // client endpoint - dial bool // test with Dial -}{ - {saddr: testUnixAddr(), caddr: testUnixAddr()}, - {saddr: testUnixAddr(), caddr: testUnixAddr(), dial: true}, - - {saddr: "@nettest/go/unixgram/server", caddr: "@nettest/go/unixgram/client"}, -} - func TestUnixgramServer(t *testing.T) { + var unixgramServerTests = []struct { + saddr string // server endpoint + caddr string // client endpoint + dial bool // test with Dial + }{ + {saddr: testUnixAddr(t), caddr: testUnixAddr(t)}, + {saddr: testUnixAddr(t), caddr: testUnixAddr(t), dial: true}, + + {saddr: "@nettest/go/unixgram/server", caddr: "@nettest/go/unixgram/client"}, + } + for i, tt := range unixgramServerTests { if !testableListenArgs("unixgram", tt.saddr, "") { t.Logf("skipping %s test", "unixgram "+tt.saddr+"<-"+tt.caddr) diff --git a/src/net/splice_test.go b/src/net/splice_test.go index 38d51451b6..fa14c95eb7 100644 --- a/src/net/splice_test.go +++ b/src/net/splice_test.go @@ -213,7 +213,7 @@ func testSpliceNoUnixpacket(t *testing.T) { } func testSpliceNoUnixgram(t *testing.T) { - addr, err := ResolveUnixAddr("unixgram", testUnixAddr()) + addr, err := ResolveUnixAddr("unixgram", testUnixAddr(t)) if err != nil { t.Fatal(err) } diff --git a/src/net/unixsock_test.go b/src/net/unixsock_test.go index 5ad20a0151..2fc9580caf 100644 --- a/src/net/unixsock_test.go +++ b/src/net/unixsock_test.go @@ -25,7 +25,7 @@ func TestReadUnixgramWithUnnamedSocket(t *testing.T) { testenv.SkipFlaky(t, 15157) } - addr := testUnixAddr() + addr := testUnixAddr(t) la, err := ResolveUnixAddr("unixgram", addr) if err != nil { t.Fatal(err) @@ -168,7 +168,7 @@ func TestUnixgramWrite(t *testing.T) { t.Skip("unixgram test") } - addr := testUnixAddr() + addr := testUnixAddr(t) laddr, err := ResolveUnixAddr("unixgram", addr) if err != nil { t.Fatal(err) @@ -213,7 +213,7 @@ func testUnixgramWriteConn(t *testing.T, raddr *UnixAddr) { } func testUnixgramWritePacketConn(t *testing.T, raddr *UnixAddr) { - addr := testUnixAddr() + addr := testUnixAddr(t) c, err := ListenPacket("unixgram", addr) if err != nil { t.Fatal(err) @@ -242,9 +242,9 @@ func TestUnixConnLocalAndRemoteNames(t *testing.T) { } handler := func(ls *localServer, ln Listener) {} - for _, laddr := range []string{"", testUnixAddr()} { + for _, laddr := range []string{"", testUnixAddr(t)} { laddr := laddr - taddr := testUnixAddr() + taddr := testUnixAddr(t) ta, err := ResolveUnixAddr("unix", taddr) if err != nil { t.Fatal(err) @@ -301,9 +301,9 @@ func TestUnixgramConnLocalAndRemoteNames(t *testing.T) { t.Skip("unixgram test") } - for _, laddr := range []string{"", testUnixAddr()} { + for _, laddr := range []string{"", testUnixAddr(t)} { laddr := laddr - taddr := testUnixAddr() + taddr := testUnixAddr(t) ta, err := ResolveUnixAddr("unixgram", taddr) if err != nil { t.Fatal(err) @@ -359,7 +359,7 @@ func TestUnixUnlink(t *testing.T) { if !testableNetwork("unix") { t.Skip("unix test") } - name := testUnixAddr() + name := testUnixAddr(t) listen := func(t *testing.T) *UnixListener { l, err := Listen("unix", name) diff --git a/src/net/unixsock_windows_test.go b/src/net/unixsock_windows_test.go index e847a20de0..d541d89f78 100644 --- a/src/net/unixsock_windows_test.go +++ b/src/net/unixsock_windows_test.go @@ -45,9 +45,9 @@ func TestUnixConnLocalWindows(t *testing.T) { } handler := func(ls *localServer, ln Listener) {} - for _, laddr := range []string{"", testUnixAddr()} { + for _, laddr := range []string{"", testUnixAddr(t)} { laddr := laddr - taddr := testUnixAddr() + taddr := testUnixAddr(t) ta, err := ResolveUnixAddr("unix", taddr) if err != nil { t.Fatal(err) -- GitLab From acc65b47e12e2ba061b8ab4f86b183d039072776 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 10 Dec 2021 14:13:52 -0500 Subject: [PATCH 2487/2500] net: refactor TestWriteToTimeout The test cases for this test had listed specific errors, but the specific error values were ignored in favor of just calling isDeadlineExceeded. Moreover, ENOBUFS errors (which can legitimately occur in the test if the network interface also happens to be saturated when the timeout occurs) were not handled at all. Now the test relies only on the timeout: we iterate until we have seen two of the expected timeout errors, and if we see ENOBUFS instead of "deadline exceeded" we back off to give the queues time to drain. Fixes #49930 Change-Id: I258a6d5c935d9635b02dffd79e197ba9caf83ac8 Reviewed-on: https://go-review.googlesource.com/c/go/+/370882 Trust: Bryan Mills Reviewed-by: Ian Lance Taylor Run-TryBot: Bryan Mills TryBot-Result: Gopher Robot --- src/net/error_plan9_test.go | 4 ++ src/net/error_unix_test.go | 5 +++ src/net/error_windows_test.go | 12 +++++- src/net/timeout_test.go | 78 ++++++++++++++++++++--------------- 4 files changed, 64 insertions(+), 35 deletions(-) diff --git a/src/net/error_plan9_test.go b/src/net/error_plan9_test.go index d7c7f1487f..1270af19e5 100644 --- a/src/net/error_plan9_test.go +++ b/src/net/error_plan9_test.go @@ -17,3 +17,7 @@ func isPlatformError(err error) bool { _, ok := err.(syscall.ErrorString) return ok } + +func isENOBUFS(err error) bool { + return false // ENOBUFS is Unix-specific +} diff --git a/src/net/error_unix_test.go b/src/net/error_unix_test.go index 1334aa86b6..291a7234f2 100644 --- a/src/net/error_unix_test.go +++ b/src/net/error_unix_test.go @@ -7,6 +7,7 @@ package net import ( + "errors" "os" "syscall" ) @@ -32,3 +33,7 @@ func samePlatformError(err, want error) bool { } return err == want } + +func isENOBUFS(err error) bool { + return errors.Is(err, syscall.ENOBUFS) +} diff --git a/src/net/error_windows_test.go b/src/net/error_windows_test.go index 834a9de441..25825f96f8 100644 --- a/src/net/error_windows_test.go +++ b/src/net/error_windows_test.go @@ -4,7 +4,10 @@ package net -import "syscall" +import ( + "errors" + "syscall" +) var ( errTimedout = syscall.ETIMEDOUT @@ -17,3 +20,10 @@ func isPlatformError(err error) bool { _, ok := err.(syscall.Errno) return ok } + +func isENOBUFS(err error) bool { + // syscall.ENOBUFS is a completely made-up value on Windows: we don't expect + // a real system call to ever actually return it. However, since it is already + // defined in the syscall package we may as well check for it. + return errors.Is(err, syscall.ENOBUFS) +} diff --git a/src/net/timeout_test.go b/src/net/timeout_test.go index cd6b953747..032770dd83 100644 --- a/src/net/timeout_test.go +++ b/src/net/timeout_test.go @@ -557,17 +557,6 @@ func TestWriteTimeoutMustNotReturn(t *testing.T) { } } -var writeToTimeoutTests = []struct { - timeout time.Duration - xerrs [2]error // expected errors in transition -}{ - // Tests that write deadlines work, even if there's buffer - // space available to write. - {-5 * time.Second, [2]error{os.ErrDeadlineExceeded, os.ErrDeadlineExceeded}}, - - {10 * time.Millisecond, [2]error{nil, os.ErrDeadlineExceeded}}, -} - func TestWriteToTimeout(t *testing.T) { t.Parallel() @@ -579,37 +568,58 @@ func TestWriteToTimeout(t *testing.T) { t.Fatal(err) } - for i, tt := range writeToTimeoutTests { - c2, err := ListenPacket(c1.LocalAddr().Network(), JoinHostPort(host, "0")) - if err != nil { - t.Fatal(err) - } - defer c2.Close() + timeouts := []time.Duration{ + -5 * time.Second, + 10 * time.Millisecond, + } - if err := c2.SetWriteDeadline(time.Now().Add(tt.timeout)); err != nil { - t.Fatalf("#%d: %v", i, err) - } - for j, xerr := range tt.xerrs { - for { + for _, timeout := range timeouts { + t.Run(fmt.Sprint(timeout), func(t *testing.T) { + c2, err := ListenPacket(c1.LocalAddr().Network(), JoinHostPort(host, "0")) + if err != nil { + t.Fatal(err) + } + defer c2.Close() + + if err := c2.SetWriteDeadline(time.Now().Add(timeout)); err != nil { + t.Fatalf("SetWriteDeadline: %v", err) + } + backoff := 1 * time.Millisecond + nDeadlineExceeded := 0 + for j := 0; nDeadlineExceeded < 2; j++ { n, err := c2.WriteTo([]byte("WRITETO TIMEOUT TEST"), c1.LocalAddr()) - if xerr != nil { - if perr := parseWriteError(err); perr != nil { - t.Errorf("#%d/%d: %v", i, j, perr) - } - if !isDeadlineExceeded(err) { - t.Fatalf("#%d/%d: %v", i, j, err) - } + t.Logf("#%d: WriteTo: %d, %v", j, n, err) + if err == nil && timeout >= 0 && nDeadlineExceeded == 0 { + // If the timeout is nonnegative, some number of WriteTo calls may + // succeed before the timeout takes effect. + t.Logf("WriteTo succeeded; sleeping %v", timeout/3) + time.Sleep(timeout / 3) + continue } - if err == nil { - time.Sleep(tt.timeout / 3) + if isENOBUFS(err) { + t.Logf("WriteTo: %v", err) + // We're looking for a deadline exceeded error, but if the kernel's + // network buffers are saturated we may see ENOBUFS instead (see + // https://go.dev/issue/49930). Give it some time to unsaturate. + time.Sleep(backoff) + backoff *= 2 continue } + if perr := parseWriteError(err); perr != nil { + t.Errorf("failed to parse error: %v", perr) + } + if !isDeadlineExceeded(err) { + t.Errorf("error is not 'deadline exceeded'") + } if n != 0 { - t.Fatalf("#%d/%d: wrote %d; want 0", i, j, n) + t.Errorf("unexpectedly wrote %d bytes", n) } - break + if !t.Failed() { + t.Logf("WriteTo timed out as expected") + } + nDeadlineExceeded++ } - } + }) } } -- GitLab From 083ef5462494e81ee23316245c5d65085a3f62d9 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 10 Dec 2021 15:35:46 -0800 Subject: [PATCH 2488/2500] spec: fix conversion rules (match implementation) As written, the conversion P(x), where P and the type of x are type parameters with identical underlying types (i.e., identical constraints), is valid. However, unless the type of x and P are identical (which is covered with the assignability rule), such a conversion is not valid in general (consider the case where both type parameters are different type parameters with constraint "any"). This change adjusts the rules to prohibit type parameters in this case. The same reasoning applies and the analogue change is made for pointer types. The type checker already implements these updated rules. Change-Id: Id90187900cb2820f6a0a0cf582cf26cdf8addbce Reviewed-on: https://go-review.googlesource.com/c/go/+/371074 Trust: Robert Griesemer Reviewed-by: Ian Lance Taylor --- doc/go_spec.html | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index 2832b0739d..cb57aa301c 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,6 +1,6 @@ @@ -4782,14 +4782,16 @@ in any of these cases: